summaryrefslogtreecommitdiff
path: root/sw/source/core
diff options
context:
space:
mode:
Diffstat (limited to 'sw/source/core')
-rw-r--r--sw/source/core/SwNumberTree/SwNodeNum.cxx418
-rw-r--r--sw/source/core/SwNumberTree/SwNumberTree.cxx1321
-rw-r--r--sw/source/core/access/acccell.cxx378
-rw-r--r--sw/source/core/access/acccell.hxx139
-rw-r--r--sw/source/core/access/acccontext.cxx1584
-rw-r--r--sw/source/core/access/acccontext.hxx433
-rw-r--r--sw/source/core/access/accdoc.cxx514
-rw-r--r--sw/source/core/access/accdoc.hxx213
-rw-r--r--sw/source/core/access/accembedded.cxx100
-rw-r--r--sw/source/core/access/accembedded.hxx72
-rw-r--r--sw/source/core/access/accfootnote.cxx158
-rw-r--r--sw/source/core/access/accfootnote.hxx90
-rw-r--r--sw/source/core/access/accframe.cxx496
-rw-r--r--sw/source/core/access/accframe.hxx176
-rw-r--r--sw/source/core/access/accframebase.cxx282
-rw-r--r--sw/source/core/access/accframebase.hxx74
-rw-r--r--sw/source/core/access/accfrmobj.cxx430
-rw-r--r--sw/source/core/access/accfrmobj.hxx95
-rw-r--r--sw/source/core/access/accfrmobjmap.cxx171
-rw-r--r--sw/source/core/access/accfrmobjmap.hxx98
-rw-r--r--sw/source/core/access/accfrmobjslist.cxx175
-rw-r--r--sw/source/core/access/accfrmobjslist.hxx148
-rw-r--r--sw/source/core/access/accgraphic.cxx100
-rw-r--r--sw/source/core/access/accgraphic.hxx72
-rw-r--r--sw/source/core/access/accheaderfooter.cxx146
-rw-r--r--sw/source/core/access/accheaderfooter.hxx85
-rw-r--r--sw/source/core/access/acchyperlink.cxx192
-rw-r--r--sw/source/core/access/acchyperlink.hxx93
-rw-r--r--sw/source/core/access/acchypertextdata.cxx58
-rw-r--r--sw/source/core/access/acchypertextdata.hxx53
-rw-r--r--sw/source/core/access/accmap.cxx2781
-rw-r--r--sw/source/core/access/accnotextframe.cxx262
-rw-r--r--sw/source/core/access/accnotextframe.hxx110
-rw-r--r--sw/source/core/access/accpage.cxx201
-rw-r--r--sw/source/core/access/accpage.hxx99
-rw-r--r--sw/source/core/access/accpara.cxx2611
-rw-r--r--sw/source/core/access/accpara.hxx435
-rw-r--r--sw/source/core/access/accportions.cxx750
-rw-r--r--sw/source/core/access/accportions.hxx177
-rw-r--r--sw/source/core/access/accpreview.cxx97
-rw-r--r--sw/source/core/access/accpreview.hxx78
-rw-r--r--sw/source/core/access/accselectionhelper.cxx332
-rw-r--r--sw/source/core/access/accselectionhelper.hxx83
-rw-r--r--sw/source/core/access/acctable.cxx1755
-rw-r--r--sw/source/core/access/acctable.hxx331
-rw-r--r--sw/source/core/access/acctextframe.cxx278
-rw-r--r--sw/source/core/access/acctextframe.hxx116
-rw-r--r--sw/source/core/access/parachangetrackinginfo.cxx227
-rw-r--r--sw/source/core/access/parachangetrackinginfo.hxx58
-rw-r--r--sw/source/core/access/textmarkuphelper.cxx232
-rw-r--r--sw/source/core/access/textmarkuphelper.hxx84
-rw-r--r--sw/source/core/attr/calbck.cxx567
-rw-r--r--sw/source/core/attr/cellatr.cxx265
-rw-r--r--sw/source/core/attr/fmtfollowtextflow.cxx40
-rw-r--r--sw/source/core/attr/fmtwrapinfluenceonobjpos.cxx164
-rw-r--r--sw/source/core/attr/format.cxx677
-rw-r--r--sw/source/core/attr/hints.cxx296
-rw-r--r--sw/source/core/attr/swatrset.cxx395
-rw-r--r--sw/source/core/bastyp/SwSmartTagMgr.cxx85
-rw-r--r--sw/source/core/bastyp/bparr.cxx582
-rw-r--r--sw/source/core/bastyp/breakit.cxx172
-rw-r--r--sw/source/core/bastyp/calc.cxx1745
-rw-r--r--sw/source/core/bastyp/checkit.cxx53
-rw-r--r--sw/source/core/bastyp/index.cxx463
-rw-r--r--sw/source/core/bastyp/init.cxx902
-rw-r--r--sw/source/core/bastyp/ring.cxx112
-rw-r--r--sw/source/core/bastyp/swcache.cxx570
-rw-r--r--sw/source/core/bastyp/swrect.cxx308
-rw-r--r--sw/source/core/bastyp/swregion.cxx247
-rw-r--r--sw/source/core/bastyp/swtypes.cxx136
-rw-r--r--sw/source/core/bastyp/tabcol.cxx143
-rw-r--r--sw/source/core/crsr/BlockCursor.cxx108
-rw-r--r--sw/source/core/crsr/BlockCursor.hxx39
-rw-r--r--sw/source/core/crsr/IBlockCursor.hxx97
-rw-r--r--sw/source/core/crsr/bookmrk.cxx371
-rw-r--r--sw/source/core/crsr/callnk.cxx265
-rw-r--r--sw/source/core/crsr/callnk.hxx60
-rw-r--r--sw/source/core/crsr/crbm.cxx263
-rw-r--r--sw/source/core/crsr/crossrefbookmark.cxx104
-rw-r--r--sw/source/core/crsr/crsrsh.cxx3439
-rw-r--r--sw/source/core/crsr/crstrvl.cxx2194
-rw-r--r--sw/source/core/crsr/crstrvl1.cxx107
-rw-r--r--sw/source/core/crsr/findattr.cxx1273
-rw-r--r--sw/source/core/crsr/findcoll.cxx124
-rw-r--r--sw/source/core/crsr/findfmt.cxx86
-rw-r--r--sw/source/core/crsr/findtxt.cxx713
-rw-r--r--sw/source/core/crsr/pam.cxx1205
-rw-r--r--sw/source/core/crsr/paminit.cxx134
-rw-r--r--sw/source/core/crsr/swcrsr.cxx2360
-rw-r--r--sw/source/core/crsr/trvlcol.cxx135
-rw-r--r--sw/source/core/crsr/trvlfnfl.cxx361
-rw-r--r--sw/source/core/crsr/trvlreg.cxx293
-rw-r--r--sw/source/core/crsr/trvltbl.cxx932
-rw-r--r--sw/source/core/crsr/unocrsr.cxx266
-rw-r--r--sw/source/core/crsr/viscrs.cxx758
-rw-r--r--sw/source/core/doc/SwStyleNameMapper.cxx1146
-rw-r--r--sw/source/core/doc/acmplwrd.cxx443
-rw-r--r--sw/source/core/doc/dbgoutsw.cxx1042
-rw-r--r--sw/source/core/doc/doc.cxx2737
-rw-r--r--sw/source/core/doc/docbasic.cxx262
-rw-r--r--sw/source/core/doc/docbm.cxx1740
-rw-r--r--sw/source/core/doc/docchart.cxx278
-rw-r--r--sw/source/core/doc/doccomp.cxx1848
-rw-r--r--sw/source/core/doc/doccorr.cxx360
-rw-r--r--sw/source/core/doc/docdde.cxx418
-rw-r--r--sw/source/core/doc/docdesc.cxx907
-rw-r--r--sw/source/core/doc/docdraw.cxx1041
-rw-r--r--sw/source/core/doc/docedt.cxx2801
-rw-r--r--sw/source/core/doc/docfld.cxx2703
-rw-r--r--sw/source/core/doc/docfly.cxx1015
-rw-r--r--sw/source/core/doc/docfmt.cxx2600
-rw-r--r--sw/source/core/doc/docftn.cxx529
-rw-r--r--sw/source/core/doc/docglbl.cxx827
-rw-r--r--sw/source/core/doc/docglos.cxx203
-rw-r--r--sw/source/core/doc/doclay.cxx2366
-rw-r--r--sw/source/core/doc/docnew.cxx1204
-rw-r--r--sw/source/core/doc/docnum.cxx2640
-rw-r--r--sw/source/core/doc/docredln.cxx3853
-rw-r--r--sw/source/core/doc/docruby.cxx343
-rw-r--r--sw/source/core/doc/docsort.cxx986
-rw-r--r--sw/source/core/doc/docstat.cxx71
-rw-r--r--sw/source/core/doc/doctxm.cxx2386
-rw-r--r--sw/source/core/doc/docxforms.cxx126
-rw-r--r--sw/source/core/doc/extinput.cxx302
-rw-r--r--sw/source/core/doc/fmtcol.cxx709
-rw-r--r--sw/source/core/doc/ftnidx.cxx401
-rw-r--r--sw/source/core/doc/gctable.cxx454
-rw-r--r--sw/source/core/doc/htmltbl.cxx1844
-rw-r--r--sw/source/core/doc/lineinfo.cxx159
-rw-r--r--sw/source/core/doc/list.cxx293
-rw-r--r--sw/source/core/doc/notxtfrm.cxx1046
-rw-r--r--sw/source/core/doc/number.cxx1457
-rw-r--r--sw/source/core/doc/poolfmt.cxx2507
-rw-r--r--sw/source/core/doc/sortopt.cxx96
-rw-r--r--sw/source/core/doc/swserv.cxx359
-rw-r--r--sw/source/core/doc/swstylemanager.cxx172
-rw-r--r--sw/source/core/doc/swstylemanager.hxx37
-rw-r--r--sw/source/core/doc/tblafmt.cxx1106
-rw-r--r--sw/source/core/doc/tblcpy.cxx1077
-rw-r--r--sw/source/core/doc/tblrwcl.cxx4712
-rw-r--r--sw/source/core/doc/visiturl.cxx141
-rw-r--r--sw/source/core/docnode/cancellablejob.cxx43
-rw-r--r--sw/source/core/docnode/cancellablejob.hxx56
-rw-r--r--sw/source/core/docnode/finalthreadmanager.cxx505
-rw-r--r--sw/source/core/docnode/ndcopy.cxx1620
-rw-r--r--sw/source/core/docnode/ndindex.cxx166
-rw-r--r--sw/source/core/docnode/ndnotxt.cxx308
-rw-r--r--sw/source/core/docnode/ndnum.cxx148
-rw-r--r--sw/source/core/docnode/ndsect.cxx1479
-rw-r--r--sw/source/core/docnode/ndtbl.cxx4563
-rw-r--r--sw/source/core/docnode/ndtbl1.cxx1598
-rw-r--r--sw/source/core/docnode/node.cxx2028
-rw-r--r--sw/source/core/docnode/node2lay.cxx474
-rw-r--r--sw/source/core/docnode/nodes.cxx2508
-rw-r--r--sw/source/core/docnode/observablethread.cxx100
-rw-r--r--sw/source/core/docnode/pausethreadstarting.cxx58
-rw-r--r--sw/source/core/docnode/retrievedinputstreamdata.cxx169
-rw-r--r--sw/source/core/docnode/retrieveinputstream.cxx87
-rw-r--r--sw/source/core/docnode/retrieveinputstreamconsumer.cxx74
-rw-r--r--sw/source/core/docnode/section.cxx1777
-rw-r--r--sw/source/core/docnode/swbaslnk.cxx502
-rw-r--r--sw/source/core/docnode/swthreadjoiner.cxx64
-rw-r--r--sw/source/core/docnode/swthreadmanager.cxx90
-rw-r--r--sw/source/core/docnode/threadlistener.cxx59
-rw-r--r--sw/source/core/docnode/threadmanager.cxx260
-rw-r--r--sw/source/core/draw/dcontact.cxx2663
-rw-r--r--sw/source/core/draw/dflyobj.cxx957
-rw-r--r--sw/source/core/draw/dobjfac.cxx58
-rw-r--r--sw/source/core/draw/dpage.cxx254
-rw-r--r--sw/source/core/draw/drawdoc.cxx234
-rw-r--r--sw/source/core/draw/dview.cxx1071
-rw-r--r--sw/source/core/edit/acorrect.cxx545
-rw-r--r--sw/source/core/edit/autofmt.cxx2754
-rw-r--r--sw/source/core/edit/edatmisc.cxx181
-rw-r--r--sw/source/core/edit/edattr.cxx630
-rw-r--r--sw/source/core/edit/eddel.cxx358
-rw-r--r--sw/source/core/edit/edfcol.cxx161
-rw-r--r--sw/source/core/edit/edfld.cxx557
-rw-r--r--sw/source/core/edit/edfldexp.cxx99
-rw-r--r--sw/source/core/edit/edfmt.cxx200
-rw-r--r--sw/source/core/edit/edglbldc.cxx412
-rw-r--r--sw/source/core/edit/edglss.cxx373
-rw-r--r--sw/source/core/edit/editsh.cxx1167
-rw-r--r--sw/source/core/edit/edlingu.cxx1927
-rw-r--r--sw/source/core/edit/ednumber.cxx801
-rw-r--r--sw/source/core/edit/edredln.cxx152
-rw-r--r--sw/source/core/edit/edsect.cxx455
-rw-r--r--sw/source/core/edit/edtab.cxx493
-rw-r--r--sw/source/core/edit/edtox.cxx467
-rw-r--r--sw/source/core/edit/edundo.cxx260
-rw-r--r--sw/source/core/edit/edws.cxx367
-rw-r--r--sw/source/core/fields/authfld.cxx756
-rw-r--r--sw/source/core/fields/cellfml.cxx1215
-rw-r--r--sw/source/core/fields/chpfld.cxx280
-rw-r--r--sw/source/core/fields/dbfld.cxx995
-rw-r--r--sw/source/core/fields/ddefld.cxx443
-rw-r--r--sw/source/core/fields/ddetbl.cxx199
-rw-r--r--sw/source/core/fields/docufld.cxx2603
-rw-r--r--sw/source/core/fields/expfld.cxx1300
-rw-r--r--sw/source/core/fields/fldbas.cxx776
-rw-r--r--sw/source/core/fields/flddat.cxx270
-rw-r--r--sw/source/core/fields/flddropdown.cxx285
-rw-r--r--sw/source/core/fields/fldlst.cxx232
-rw-r--r--sw/source/core/fields/macrofld.cxx259
-rw-r--r--sw/source/core/fields/postithelper.cxx208
-rw-r--r--sw/source/core/fields/reffld.cxx1074
-rw-r--r--sw/source/core/fields/scrptfld.cxx147
-rw-r--r--sw/source/core/fields/tblcalc.cxx247
-rw-r--r--sw/source/core/fields/textapi.cxx194
-rw-r--r--sw/source/core/fields/usrfld.cxx369
-rw-r--r--sw/source/core/frmedt/fecopy.cxx1539
-rw-r--r--sw/source/core/frmedt/fedesc.cxx283
-rw-r--r--sw/source/core/frmedt/fefly1.cxx2207
-rw-r--r--sw/source/core/frmedt/feflyole.cxx151
-rw-r--r--sw/source/core/frmedt/feshview.cxx3111
-rw-r--r--sw/source/core/frmedt/fetab.cxx2509
-rw-r--r--sw/source/core/frmedt/fews.cxx1355
-rw-r--r--sw/source/core/frmedt/tblsel.cxx2703
-rw-r--r--sw/source/core/graphic/grfatr.cxx359
-rw-r--r--sw/source/core/graphic/ndgrf.cxx1205
-rw-r--r--sw/source/core/inc/GetMetricVal.hxx57
-rw-r--r--sw/source/core/inc/MarkManager.hxx100
-rw-r--r--sw/source/core/inc/SwGrammarMarkUp.hxx77
-rw-r--r--sw/source/core/inc/SwPortionHandler.hxx104
-rw-r--r--sw/source/core/inc/SwUndoFmt.hxx255
-rw-r--r--sw/source/core/inc/SwUndoPageDesc.hxx96
-rw-r--r--sw/source/core/inc/SwUndoTOXChange.hxx52
-rw-r--r--sw/source/core/inc/SwXMLBlockExport.hxx76
-rw-r--r--sw/source/core/inc/SwXMLBlockImport.hxx92
-rw-r--r--sw/source/core/inc/SwXMLBlockListContext.hxx129
-rw-r--r--sw/source/core/inc/SwXMLTextBlocks.hxx114
-rw-r--r--sw/source/core/inc/SwXTextDefaults.hxx85
-rw-r--r--sw/source/core/inc/UndoAttribute.hxx288
-rw-r--r--sw/source/core/inc/UndoBookmark.hxx83
-rw-r--r--sw/source/core/inc/UndoCore.hxx266
-rw-r--r--sw/source/core/inc/UndoDelete.hxx115
-rw-r--r--sw/source/core/inc/UndoDraw.hxx150
-rw-r--r--sw/source/core/inc/UndoInsert.hxx235
-rw-r--r--sw/source/core/inc/UndoManager.hxx124
-rw-r--r--sw/source/core/inc/UndoNumbering.hxx150
-rw-r--r--sw/source/core/inc/UndoOverwrite.hxx105
-rw-r--r--sw/source/core/inc/UndoRedline.hxx145
-rw-r--r--sw/source/core/inc/UndoSection.hxx82
-rw-r--r--sw/source/core/inc/UndoSort.hxx97
-rw-r--r--sw/source/core/inc/UndoSplitMove.hxx96
-rw-r--r--sw/source/core/inc/UndoTable.hxx391
-rw-r--r--sw/source/core/inc/acorrect.hxx126
-rw-r--r--sw/source/core/inc/anchoredobjectposition.hxx474
-rw-r--r--sw/source/core/inc/ascharanchoredobjectposition.hxx174
-rw-r--r--sw/source/core/inc/attrhint.hxx44
-rw-r--r--sw/source/core/inc/blink.hxx91
-rw-r--r--sw/source/core/inc/bodyfrm.hxx54
-rw-r--r--sw/source/core/inc/bookmrk.hxx266
-rw-r--r--sw/source/core/inc/cellfrm.hxx75
-rw-r--r--sw/source/core/inc/cntfrm.hxx153
-rw-r--r--sw/source/core/inc/colfrm.hxx45
-rw-r--r--sw/source/core/inc/crossrefbookmark.hxx102
-rw-r--r--sw/source/core/inc/dbg_lay.hxx123
-rw-r--r--sw/source/core/inc/dbgloop.hxx77
-rw-r--r--sw/source/core/inc/dflyobj.hxx143
-rw-r--r--sw/source/core/inc/docfld.hxx195
-rw-r--r--sw/source/core/inc/docsort.hxx180
-rw-r--r--sw/source/core/inc/doctxm.hxx148
-rw-r--r--sw/source/core/inc/drawdev.hxx141
-rw-r--r--sw/source/core/inc/drawfont.hxx628
-rw-r--r--sw/source/core/inc/dview.hxx136
-rw-r--r--sw/source/core/inc/environmentofanchoredobject.hxx106
-rw-r--r--sw/source/core/inc/fieldhint.hxx44
-rw-r--r--sw/source/core/inc/finalthreadmanager.hxx108
-rw-r--r--sw/source/core/inc/flowfrm.hxx255
-rw-r--r--sw/source/core/inc/flyfrm.hxx288
-rw-r--r--sw/source/core/inc/flyfrms.hxx260
-rw-r--r--sw/source/core/inc/fntcache.hxx163
-rw-r--r--sw/source/core/inc/frame.hxx1324
-rw-r--r--sw/source/core/inc/frminf.hxx87
-rw-r--r--sw/source/core/inc/frmtool.hxx579
-rw-r--r--sw/source/core/inc/ftnboss.hxx140
-rw-r--r--sw/source/core/inc/ftnfrm.hxx153
-rw-r--r--sw/source/core/inc/hffrm.hxx69
-rw-r--r--sw/source/core/inc/ifinishedthreadlistener.hxx58
-rw-r--r--sw/source/core/inc/ithreadlistenerowner.hxx61
-rw-r--r--sw/source/core/inc/layact.hxx242
-rw-r--r--sw/source/core/inc/laycache.hxx80
-rw-r--r--sw/source/core/inc/layfrm.hxx209
-rw-r--r--sw/source/core/inc/layouter.hxx185
-rw-r--r--sw/source/core/inc/movedfwdfrmsbyobjpos.hxx73
-rw-r--r--sw/source/core/inc/mvsave.hxx215
-rw-r--r--sw/source/core/inc/node2lay.hxx84
-rw-r--r--sw/source/core/inc/noteurl.hxx78
-rw-r--r--sw/source/core/inc/notxtfrm.hxx80
-rw-r--r--sw/source/core/inc/objectformatter.hxx212
-rw-r--r--sw/source/core/inc/observablethread.hxx106
-rw-r--r--sw/source/core/inc/pagedeschint.hxx46
-rw-r--r--sw/source/core/inc/pagefrm.hrc45
-rw-r--r--sw/source/core/inc/pagefrm.hxx490
-rw-r--r--sw/source/core/inc/pamtyp.hxx105
-rw-r--r--sw/source/core/inc/prevwpage.hxx62
-rw-r--r--sw/source/core/inc/ptqueue.hxx65
-rw-r--r--sw/source/core/inc/retrievedinputstreamdata.hxx110
-rw-r--r--sw/source/core/inc/retrieveinputstream.hxx66
-rw-r--r--sw/source/core/inc/retrieveinputstreamconsumer.hxx69
-rw-r--r--sw/source/core/inc/rolbck.hxx439
-rw-r--r--sw/source/core/inc/rootfrm.hxx375
-rw-r--r--sw/source/core/inc/rowfrm.hxx114
-rw-r--r--sw/source/core/inc/scriptinfo.hxx436
-rw-r--r--sw/source/core/inc/sectfrm.hxx153
-rw-r--r--sw/source/core/inc/setmapvirtdev.hxx73
-rw-r--r--sw/source/core/inc/sortedobjs.hxx100
-rw-r--r--sw/source/core/inc/sortedobjsimpl.hxx64
-rw-r--r--sw/source/core/inc/swblocks.hxx148
-rw-r--r--sw/source/core/inc/swcache.hxx303
-rw-r--r--sw/source/core/inc/swfntcch.hxx102
-rw-r--r--sw/source/core/inc/swfont.hxx899
-rw-r--r--sw/source/core/inc/swselectionlist.hxx100
-rw-r--r--sw/source/core/inc/swthreadjoiner.hxx54
-rw-r--r--sw/source/core/inc/swthreadmanager.hxx86
-rw-r--r--sw/source/core/inc/tabfrm.hxx238
-rw-r--r--sw/source/core/inc/tblrwcl.hxx232
-rw-r--r--sw/source/core/inc/textapi.hxx73
-rw-r--r--sw/source/core/inc/threadlistener.hxx65
-rw-r--r--sw/source/core/inc/threadmanager.hxx175
-rw-r--r--sw/source/core/inc/tocntntanchoredobjectposition.hxx99
-rw-r--r--sw/source/core/inc/tolayoutanchoredobjectposition.hxx63
-rw-r--r--sw/source/core/inc/toxhlp.hxx79
-rw-r--r--sw/source/core/inc/txmsrt.hxx297
-rw-r--r--sw/source/core/inc/txtfrm.hxx795
-rw-r--r--sw/source/core/inc/txttypes.hxx106
-rw-r--r--sw/source/core/inc/undoflystrattr.hxx59
-rw-r--r--sw/source/core/inc/unofldmid.h74
-rw-r--r--sw/source/core/inc/unometa.hxx370
-rw-r--r--sw/source/core/inc/viewimp.hxx353
-rw-r--r--sw/source/core/inc/visiturl.hxx48
-rw-r--r--sw/source/core/inc/wrong.hxx167
-rw-r--r--sw/source/core/layout/anchoreddrawobject.cxx900
-rw-r--r--sw/source/core/layout/anchoredobject.cxx1062
-rw-r--r--sw/source/core/layout/atrfrm.cxx3299
-rw-r--r--sw/source/core/layout/calcmove.cxx2116
-rw-r--r--sw/source/core/layout/colfrm.cxx478
-rw-r--r--sw/source/core/layout/dbg_lay.cxx868
-rw-r--r--sw/source/core/layout/findfrm.cxx1793
-rw-r--r--sw/source/core/layout/flowfrm.cxx2672
-rw-r--r--sw/source/core/layout/fly.cxx2882
-rw-r--r--sw/source/core/layout/flycnt.cxx1541
-rw-r--r--sw/source/core/layout/flyincnt.cxx338
-rw-r--r--sw/source/core/layout/flylay.cxx1319
-rw-r--r--sw/source/core/layout/flypos.cxx114
-rw-r--r--sw/source/core/layout/frmtool.cxx3604
-rw-r--r--sw/source/core/layout/ftnfrm.cxx3241
-rw-r--r--sw/source/core/layout/hffrm.cxx796
-rw-r--r--sw/source/core/layout/layact.cxx2546
-rw-r--r--sw/source/core/layout/laycache.cxx1338
-rw-r--r--sw/source/core/layout/layhelp.hxx240
-rw-r--r--sw/source/core/layout/layouter.cxx565
-rw-r--r--sw/source/core/layout/movedfwdfrmsbyobjpos.cxx108
-rw-r--r--sw/source/core/layout/newfrm.cxx679
-rw-r--r--sw/source/core/layout/objectformatter.cxx580
-rw-r--r--sw/source/core/layout/objectformatterlayfrm.cxx216
-rw-r--r--sw/source/core/layout/objectformatterlayfrm.hxx84
-rw-r--r--sw/source/core/layout/objectformattertxtfrm.cxx814
-rw-r--r--sw/source/core/layout/objectformattertxtfrm.hxx201
-rw-r--r--sw/source/core/layout/objstmpconsiderwrapinfl.cxx76
-rw-r--r--sw/source/core/layout/objstmpconsiderwrapinfl.hxx50
-rw-r--r--sw/source/core/layout/pagechg.cxx2454
-rw-r--r--sw/source/core/layout/pagedesc.cxx487
-rw-r--r--sw/source/core/layout/pagefrm.src7
-rw-r--r--sw/source/core/layout/paintfrm.cxx6701
-rw-r--r--sw/source/core/layout/sectfrm.cxx2779
-rw-r--r--sw/source/core/layout/softpagebreak.cxx157
-rw-r--r--sw/source/core/layout/sortedobjs.cxx79
-rw-r--r--sw/source/core/layout/sortedobjsimpl.cxx312
-rw-r--r--sw/source/core/layout/ssfrm.cxx814
-rw-r--r--sw/source/core/layout/swselectionlist.cxx96
-rw-r--r--sw/source/core/layout/tabfrm.cxx5798
-rw-r--r--sw/source/core/layout/trvlfrm.cxx2611
-rw-r--r--sw/source/core/layout/unusedf.cxx92
-rw-r--r--sw/source/core/layout/virtoutp.cxx258
-rw-r--r--sw/source/core/layout/virtoutp.hxx77
-rw-r--r--sw/source/core/layout/wsfrm.cxx3967
-rw-r--r--sw/source/core/objectpositioning/anchoredobjectposition.cxx1100
-rw-r--r--sw/source/core/objectpositioning/ascharanchoredobjectposition.cxx458
-rw-r--r--sw/source/core/objectpositioning/environmentofanchoredobject.cxx116
-rw-r--r--sw/source/core/objectpositioning/tocntntanchoredobjectposition.cxx1129
-rw-r--r--sw/source/core/objectpositioning/tolayoutanchoredobjectposition.cxx257
-rw-r--r--sw/source/core/ole/ndole.cxx997
-rw-r--r--sw/source/core/para/paratr.cxx278
-rw-r--r--sw/source/core/sw3io/sw3convert.cxx413
-rw-r--r--sw/source/core/sw3io/swacorr.cxx105
-rw-r--r--sw/source/core/swg/SwXMLBlockExport.cxx145
-rw-r--r--sw/source/core/swg/SwXMLBlockImport.cxx119
-rw-r--r--sw/source/core/swg/SwXMLBlockListContext.cxx253
-rw-r--r--sw/source/core/swg/SwXMLSectionList.cxx157
-rw-r--r--sw/source/core/swg/SwXMLTextBlocks.cxx606
-rw-r--r--sw/source/core/swg/SwXMLTextBlocks1.cxx737
-rw-r--r--sw/source/core/swg/swblocks.cxx657
-rw-r--r--sw/source/core/table/swnewtable.cxx2175
-rw-r--r--sw/source/core/table/swtable.cxx2824
-rw-r--r--sw/source/core/text/EnhancedPDFExportHelper.cxx2205
-rw-r--r--sw/source/core/text/SwGrammarMarkUp.cxx168
-rw-r--r--sw/source/core/text/atrhndl.hxx182
-rw-r--r--sw/source/core/text/atrstck.cxx957
-rw-r--r--sw/source/core/text/blink.cxx200
-rw-r--r--sw/source/core/text/frmcrsr.cxx1752
-rw-r--r--sw/source/core/text/frmform.cxx2068
-rw-r--r--sw/source/core/text/frminf.cxx378
-rw-r--r--sw/source/core/text/frmpaint.cxx743
-rw-r--r--sw/source/core/text/guess.cxx554
-rw-r--r--sw/source/core/text/guess.hxx76
-rw-r--r--sw/source/core/text/inftxt.cxx1942
-rw-r--r--sw/source/core/text/inftxt.hxx896
-rw-r--r--sw/source/core/text/itradj.cxx901
-rw-r--r--sw/source/core/text/itratr.cxx1075
-rw-r--r--sw/source/core/text/itratr.hxx136
-rw-r--r--sw/source/core/text/itrcrsr.cxx1880
-rw-r--r--sw/source/core/text/itrform2.cxx2162
-rw-r--r--sw/source/core/text/itrform2.hxx213
-rw-r--r--sw/source/core/text/itrpaint.cxx708
-rw-r--r--sw/source/core/text/itrpaint.hxx72
-rw-r--r--sw/source/core/text/itrtxt.cxx513
-rw-r--r--sw/source/core/text/itrtxt.hxx348
-rw-r--r--sw/source/core/text/noteurl.cxx89
-rw-r--r--sw/source/core/text/pordrop.hxx122
-rw-r--r--sw/source/core/text/porexp.cxx314
-rw-r--r--sw/source/core/text/porexp.hxx111
-rw-r--r--sw/source/core/text/porfld.cxx1374
-rw-r--r--sw/source/core/text/porfld.hxx269
-rw-r--r--sw/source/core/text/porfly.cxx457
-rw-r--r--sw/source/core/text/porfly.hxx111
-rw-r--r--sw/source/core/text/porftn.hxx131
-rw-r--r--sw/source/core/text/porglue.cxx315
-rw-r--r--sw/source/core/text/porglue.hxx134
-rw-r--r--sw/source/core/text/porhyph.hxx122
-rw-r--r--sw/source/core/text/porlay.cxx2424
-rw-r--r--sw/source/core/text/porlay.hxx436
-rw-r--r--sw/source/core/text/porlin.cxx420
-rw-r--r--sw/source/core/text/porlin.hxx254
-rw-r--r--sw/source/core/text/pormulti.cxx2411
-rw-r--r--sw/source/core/text/pormulti.hxx271
-rw-r--r--sw/source/core/text/porref.cxx116
-rw-r--r--sw/source/core/text/porref.hxx76
-rw-r--r--sw/source/core/text/porrst.cxx598
-rw-r--r--sw/source/core/text/porrst.hxx190
-rw-r--r--sw/source/core/text/portab.hxx160
-rw-r--r--sw/source/core/text/portox.cxx116
-rw-r--r--sw/source/core/text/portox.hxx77
-rw-r--r--sw/source/core/text/portxt.cxx876
-rw-r--r--sw/source/core/text/portxt.hxx124
-rw-r--r--sw/source/core/text/possiz.hxx86
-rw-r--r--sw/source/core/text/redlnitr.cxx504
-rw-r--r--sw/source/core/text/redlnitr.hxx123
-rw-r--r--sw/source/core/text/txtcache.cxx215
-rw-r--r--sw/source/core/text/txtcache.hxx79
-rw-r--r--sw/source/core/text/txtdrop.cxx1092
-rw-r--r--sw/source/core/text/txtfld.cxx569
-rw-r--r--sw/source/core/text/txtfly.cxx2424
-rw-r--r--sw/source/core/text/txtfly.hxx219
-rw-r--r--sw/source/core/text/txtfrm.cxx2813
-rw-r--r--sw/source/core/text/txtftn.cxx1697
-rw-r--r--sw/source/core/text/txthyph.cxx662
-rw-r--r--sw/source/core/text/txtinit.cxx99
-rw-r--r--sw/source/core/text/txtio.cxx723
-rw-r--r--sw/source/core/text/txtpaint.cxx135
-rw-r--r--sw/source/core/text/txtpaint.hxx194
-rw-r--r--sw/source/core/text/txttab.cxx679
-rw-r--r--sw/source/core/text/widorp.cxx574
-rw-r--r--sw/source/core/text/widorp.hxx98
-rw-r--r--sw/source/core/text/wrong.cxx646
-rw-r--r--sw/source/core/text/xmldump.cxx318
-rw-r--r--sw/source/core/tox/tox.cxx935
-rw-r--r--sw/source/core/tox/toxhlp.cxx194
-rw-r--r--sw/source/core/tox/txmsrt.cxx883
-rw-r--r--sw/source/core/txtnode/SwGrammarContact.cxx205
-rw-r--r--sw/source/core/txtnode/atrfld.cxx424
-rw-r--r--sw/source/core/txtnode/atrflyin.cxx286
-rw-r--r--sw/source/core/txtnode/atrftn.cxx545
-rw-r--r--sw/source/core/txtnode/atrref.cxx105
-rw-r--r--sw/source/core/txtnode/atrtox.cxx99
-rw-r--r--sw/source/core/txtnode/chrfmt.cxx40
-rw-r--r--sw/source/core/txtnode/fmtatr2.cxx905
-rw-r--r--sw/source/core/txtnode/fntcache.cxx2651
-rw-r--r--sw/source/core/txtnode/fntcap.cxx846
-rw-r--r--sw/source/core/txtnode/modeltoviewhelper.cxx123
-rw-r--r--sw/source/core/txtnode/ndhints.cxx431
-rw-r--r--sw/source/core/txtnode/ndtxt.cxx4829
-rw-r--r--sw/source/core/txtnode/swfntcch.cxx90
-rw-r--r--sw/source/core/txtnode/swfont.cxx1243
-rw-r--r--sw/source/core/txtnode/thints.cxx3063
-rw-r--r--sw/source/core/txtnode/txatbase.cxx86
-rw-r--r--sw/source/core/txtnode/txatritr.cxx246
-rw-r--r--sw/source/core/txtnode/txtatr2.cxx353
-rw-r--r--sw/source/core/txtnode/txtedt.cxx2123
-rw-r--r--sw/source/core/undo/SwRewriter.cxx80
-rw-r--r--sw/source/core/undo/SwUndoField.cxx165
-rw-r--r--sw/source/core/undo/SwUndoFmt.cxx462
-rw-r--r--sw/source/core/undo/SwUndoPageDesc.cxx435
-rw-r--r--sw/source/core/undo/SwUndoTOXChange.cxx79
-rw-r--r--sw/source/core/undo/docundo.cxx581
-rw-r--r--sw/source/core/undo/rolbck.cxx1516
-rw-r--r--sw/source/core/undo/unattr.cxx1259
-rw-r--r--sw/source/core/undo/unbkmk.cxx107
-rw-r--r--sw/source/core/undo/undel.cxx991
-rw-r--r--sw/source/core/undo/undo.hrc185
-rw-r--r--sw/source/core/undo/undo.src657
-rw-r--r--sw/source/core/undo/undobj.cxx1347
-rw-r--r--sw/source/core/undo/undobj1.cxx729
-rw-r--r--sw/source/core/undo/undoflystrattr.cxx102
-rw-r--r--sw/source/core/undo/undraw.cxx608
-rw-r--r--sw/source/core/undo/unfmco.cxx122
-rw-r--r--sw/source/core/undo/unins.cxx1068
-rw-r--r--sw/source/core/undo/unmove.cxx357
-rw-r--r--sw/source/core/undo/unnum.cxx454
-rw-r--r--sw/source/core/undo/unoutl.cxx64
-rw-r--r--sw/source/core/undo/unovwr.cxx504
-rw-r--r--sw/source/core/undo/unredln.cxx541
-rw-r--r--sw/source/core/undo/unsect.cxx501
-rw-r--r--sw/source/core/undo/unsort.cxx282
-rw-r--r--sw/source/core/undo/unspnd.cxx206
-rw-r--r--sw/source/core/undo/untbl.cxx3269
-rw-r--r--sw/source/core/undo/untblk.cxx357
-rw-r--r--sw/source/core/unocore/SwXTextDefaults.cxx291
-rw-r--r--sw/source/core/unocore/TextCursorHelper.cxx58
-rw-r--r--sw/source/core/unocore/XMLRangeHelper.cxx415
-rw-r--r--sw/source/core/unocore/XMLRangeHelper.hxx81
-rw-r--r--sw/source/core/unocore/swunohelper.cxx291
-rw-r--r--sw/source/core/unocore/unobkm.cxx734
-rw-r--r--sw/source/core/unocore/unochart.cxx2956
-rw-r--r--sw/source/core/unocore/unocoll.cxx1996
-rw-r--r--sw/source/core/unocore/unocore.src64
-rw-r--r--sw/source/core/unocore/unocrsrhelper.cxx1079
-rw-r--r--sw/source/core/unocore/unodraw.cxx2850
-rw-r--r--sw/source/core/unocore/unoevent.cxx331
-rw-r--r--sw/source/core/unocore/unoevtlstnr.cxx105
-rw-r--r--sw/source/core/unocore/unofield.cxx2806
-rw-r--r--sw/source/core/unocore/unoflatpara.cxx533
-rw-r--r--sw/source/core/unocore/unoframe.cxx3144
-rw-r--r--sw/source/core/unocore/unoftn.cxx634
-rw-r--r--sw/source/core/unocore/unoidx.cxx3223
-rw-r--r--sw/source/core/unocore/unomap.cxx3061
-rw-r--r--sw/source/core/unocore/unoobj.cxx2981
-rw-r--r--sw/source/core/unocore/unoobj2.cxx1970
-rw-r--r--sw/source/core/unocore/unoparagraph.cxx1327
-rw-r--r--sw/source/core/unocore/unoport.cxx979
-rw-r--r--sw/source/core/unocore/unoportenum.cxx1175
-rw-r--r--sw/source/core/unocore/unoprnms.cxx803
-rw-r--r--sw/source/core/unocore/unoredline.cxx687
-rw-r--r--sw/source/core/unocore/unoredlines.cxx199
-rw-r--r--sw/source/core/unocore/unorefmk.cxx1623
-rw-r--r--sw/source/core/unocore/unosect.cxx1796
-rw-r--r--sw/source/core/unocore/unosett.cxx2639
-rw-r--r--sw/source/core/unocore/unosrch.cxx746
-rw-r--r--sw/source/core/unocore/unostyle.cxx4126
-rw-r--r--sw/source/core/unocore/unotbl.cxx5045
-rw-r--r--sw/source/core/unocore/unotext.cxx2815
-rw-r--r--sw/source/core/unocore/unotextmarkup.cxx490
-rw-r--r--sw/source/core/view/pagepreviewlayout.cxx1393
-rw-r--r--sw/source/core/view/printdata.cxx541
-rw-r--r--sw/source/core/view/vdraw.cxx276
-rw-r--r--sw/source/core/view/viewimp.cxx476
-rw-r--r--sw/source/core/view/viewpg.cxx247
-rw-r--r--sw/source/core/view/viewsh.cxx2326
-rw-r--r--sw/source/core/view/vnew.cxx369
-rw-r--r--sw/source/core/view/vprint.cxx653
561 files changed, 398396 insertions, 0 deletions
diff --git a/sw/source/core/SwNumberTree/SwNodeNum.cxx b/sw/source/core/SwNumberTree/SwNodeNum.cxx
new file mode 100644
index 000000000000..67a0110000c6
--- /dev/null
+++ b/sw/source/core/SwNumberTree/SwNodeNum.cxx
@@ -0,0 +1,418 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+#include <editeng/svxenum.hxx>
+#include <numrule.hxx>
+#include <SwNodeNum.hxx>
+#include <ndtxt.hxx>
+#include <pam.hxx>
+#include <stdio.h>
+// --> OD 2007-10-31 #i83479#
+#include <IDocumentListItems.hxx>
+// <--
+#include <doc.hxx>
+
+SwNodeNum::SwNodeNum( SwTxtNode* pTxtNode )
+ : SwNumberTreeNode(),
+ mpTxtNode( pTxtNode ),
+ mpNumRule( 0 )
+{
+}
+
+SwNodeNum::SwNodeNum( SwNumRule* pNumRule )
+ : SwNumberTreeNode(),
+ mpTxtNode( 0 ),
+ mpNumRule( pNumRule )
+{
+}
+
+SwNodeNum::~SwNodeNum()
+{
+}
+
+SwTxtNode * SwNodeNum::GetTxtNode() const
+{
+ return mpTxtNode;
+}
+
+SwNumRule * SwNodeNum::GetNumRule() const
+{
+ return mpNumRule;
+}
+
+void SwNodeNum::ChangeNumRule( SwNumRule& rNumRule )
+{
+ OSL_ENSURE( GetNumRule() && GetTxtNode(),
+ "<SwNodeNum::ChangeNumRule(..)> - missing list style and/or text node. Serious defect -> please informm OD." );
+ if ( GetNumRule() && GetTxtNode() )
+ {
+ GetNumRule()->RemoveTxtNode( *(GetTxtNode()) );
+ }
+
+ mpNumRule = &rNumRule;
+
+ if ( GetNumRule() && GetTxtNode() )
+ {
+ GetNumRule()->AddTxtNode( *(GetTxtNode()) );
+ }
+}
+
+SwPosition SwNodeNum::GetPosition() const
+{
+ OSL_ENSURE( GetTxtNode(),
+ "<SwNodeNum::GetPosition()> - no text node set at <SwNodeNum> instance" );
+ return SwPosition(*mpTxtNode);
+}
+
+SwNumberTreeNode * SwNodeNum::Create() const
+{
+ SwNodeNum * pResult = new SwNodeNum( GetNumRule() );
+
+ return pResult;
+}
+
+void SwNodeNum::PreAdd()
+{
+ OSL_ENSURE( GetTxtNode(),
+ "<SwNodeNum::PreAdd()> - no text node set at <SwNodeNum> instance" );
+ if ( !GetNumRule() && GetTxtNode() )
+ {
+ mpNumRule = GetTxtNode()->GetNumRule();
+ }
+ OSL_ENSURE( GetNumRule(),
+ "<SwNodeNum::PreAdd()> - no list style set at <SwNodeNum> instance" );
+ if ( GetNumRule() && GetTxtNode() )
+ {
+ GetNumRule()->AddTxtNode( *(GetTxtNode()) );
+ }
+
+
+ {
+ if ( GetTxtNode() &&
+ GetTxtNode()->GetNodes().IsDocNodes() )
+ {
+ GetTxtNode()->getIDocumentListItems().addListItem( *this );
+ }
+ }
+}
+
+void SwNodeNum::PostRemove()
+{
+ OSL_ENSURE( GetTxtNode(),
+ "<SwNodeNum::PostRemove()> - no text node set at <SwNodeNum> instance" );
+ OSL_ENSURE( GetNumRule(),
+ "<SwNodeNum::PostRemove()> - no list style set at <SwNodeNum> instance" );
+
+ if ( GetTxtNode() )
+ {
+ GetTxtNode()->getIDocumentListItems().removeListItem( *this );
+ }
+
+ if ( GetNumRule() )
+ {
+ if ( GetTxtNode() )
+ {
+ GetNumRule()->RemoveTxtNode( *(GetTxtNode()) );
+ }
+ mpNumRule = 0;
+ }
+}
+// <--
+
+bool SwNodeNum::IsNotifiable() const
+{
+ bool aResult = true;
+
+ if ( GetTxtNode() )
+ aResult = GetTxtNode()->IsNotifiable();
+
+ return aResult;
+}
+
+bool SwNodeNum::IsNotificationEnabled() const
+{
+ bool aResult = true;
+
+ if ( GetTxtNode() )
+ aResult = GetTxtNode()->IsNotificationEnabled();
+
+ return aResult;
+}
+
+bool SwNodeNum::IsContinuous() const
+{
+ bool aResult = false;
+
+ // --> OD 2006-04-21 #i64311#
+ if ( GetNumRule() )
+ {
+ aResult = mpNumRule->IsContinusNum();
+ }
+ else if ( GetParent() )
+ {
+ aResult = GetParent()->IsContinuous();
+ }
+ else
+ {
+ OSL_FAIL( "<SwNodeNum::IsContinuous()> - OD debug" );
+ }
+ // <--
+
+ return aResult;
+}
+
+bool SwNodeNum::IsCounted() const
+{
+ bool aResult = false;
+
+ if ( GetTxtNode() )
+ {
+ // --> OD 2006-01-25 #i59559#
+ // <SwTxtNode::IsCounted()> determines, if a text node is counted for numbering
+ aResult = GetTxtNode()->IsCountedInList();
+ // <--
+ }
+ else
+ aResult = SwNumberTreeNode::IsCounted();
+
+ return aResult;
+}
+
+// --> OD 2006-04-26 #i64010#
+bool SwNodeNum::HasCountedChildren() const
+{
+ bool bResult = false;
+
+ tSwNumberTreeChildren::const_iterator aIt;
+
+ for (aIt = mChildren.begin(); aIt != mChildren.end(); ++aIt)
+ {
+ SwNodeNum* pChild( dynamic_cast<SwNodeNum*>(*aIt) );
+ OSL_ENSURE( pChild,
+ "<SwNodeNum::HasCountedChildren()> - unexcepted type of child -> please inform OD" );
+ if ( pChild &&
+ ( pChild->IsCountedForNumbering() ||
+ pChild->HasCountedChildren() ) )
+ {
+ bResult = true;
+
+ break;
+ }
+ }
+
+ return bResult;
+}
+// <--
+// --> OD 2006-04-26 #i64010#
+bool SwNodeNum::IsCountedForNumbering() const
+{
+ return IsCounted() &&
+ ( IsPhantom() || // phantoms
+ !GetTxtNode() || // root node
+ GetTxtNode()->HasNumber() || // text node
+ GetTxtNode()->HasBullet() ); // text node
+}
+// <--
+
+
+void SwNodeNum::NotifyNode()
+{
+ ValidateMe();
+
+ if (mpTxtNode)
+ {
+ mpTxtNode->NumRuleChgd();
+ }
+}
+
+bool SwNodeNum::LessThan(const SwNumberTreeNode & rNode) const
+{
+ bool bResult = false;
+ const SwNodeNum & rTmpNode = static_cast<const SwNodeNum &>(rNode);
+
+ if (mpTxtNode == NULL && rTmpNode.mpTxtNode != NULL)
+ bResult = true;
+ else if (mpTxtNode != NULL && rTmpNode.mpTxtNode != NULL)
+ {
+ // --> OD 2007-10-31 #i83479# - refactoring
+ // simplify comparison by comparing the indexes of the text nodes
+ bResult = ( mpTxtNode->GetIndex() < rTmpNode.mpTxtNode->GetIndex() ) ? true : false;
+ // <--
+ }
+
+ return bResult;
+}
+
+bool SwNodeNum::IsRestart() const
+{
+ bool bIsRestart = false;
+
+ if ( GetTxtNode() )
+ {
+ bIsRestart = GetTxtNode()->IsListRestart();
+ }
+
+ return bIsRestart;
+}
+
+bool SwNodeNum::IsCountPhantoms() const
+{
+ bool bResult = true;
+
+ // --> OD 2006-04-21 #i64311#
+ // phantoms aren't counted in consecutive numbering rules
+ if ( mpNumRule )
+ bResult = !mpNumRule->IsContinusNum() &&
+ mpNumRule->IsCountPhantoms();
+ else
+ {
+ OSL_FAIL( "<SwNodeNum::IsCountPhantoms(): missing numbering rule - please inform OD" );
+ }
+ // <--
+
+ return bResult;
+}
+
+SwNumberTree::tSwNumTreeNumber SwNodeNum::GetStartValue() const
+{
+ SwNumberTree::tSwNumTreeNumber aResult = 1;
+
+ if ( IsRestart() && GetTxtNode() )
+ {
+ aResult = GetTxtNode()->GetActualListStartValue();
+ }
+ else
+ {
+ SwNumRule * pRule = GetNumRule();
+
+ if (pRule)
+ {
+ int nLevel = GetParent() ? GetLevelInListTree() : 0;
+
+ if (nLevel >= 0 && nLevel < MAXLEVEL)
+ {
+ const SwNumFmt * pFmt = pRule->GetNumFmt( static_cast<sal_uInt16>(nLevel));
+
+ if (pFmt)
+ aResult = pFmt->GetStart();
+ }
+ }
+ }
+
+ return aResult;
+}
+
+void SwNodeNum::HandleNumberTreeRootNodeDelete( SwNodeNum& rNodeNum )
+{
+ SwNodeNum* pRootNode = rNodeNum.GetParent()
+ ? dynamic_cast<SwNodeNum*>(rNodeNum.GetRoot())
+ : &rNodeNum;
+ if ( !pRootNode )
+ {
+ // no root node -> nothing do.
+ return;
+ }
+
+ // unregister all number tree node entries, which correspond to a text node,
+ // about the deletion of the number tree root node.
+ _UnregisterMeAndChildrenDueToRootDelete( *pRootNode );
+}
+
+void SwNodeNum::_UnregisterMeAndChildrenDueToRootDelete( SwNodeNum& rNodeNum )
+{
+ const bool bIsPhantom( rNodeNum.IsPhantom() );
+ tSwNumberTreeChildren::size_type nAllowedChildCount( 0 );
+ bool bDone( false );
+ while ( !bDone &&
+ rNodeNum.GetChildCount() > nAllowedChildCount )
+ {
+ SwNodeNum* pChildNode( dynamic_cast<SwNodeNum*>((*rNodeNum.mChildren.begin())) );
+ if ( !pChildNode )
+ {
+ OSL_FAIL( "<SwNodeNum::_UnregisterMeAndChildrenDueToRootDelete(..)> - unknown number tree node child" );
+ ++nAllowedChildCount;
+ continue;
+ }
+
+ // Unregistering the last child of a phantom will destroy the phantom.
+ // Thus <rNodeNum> will be destroyed and access on <rNodeNum> has to
+ // be suppressed.
+ if ( bIsPhantom && rNodeNum.GetChildCount() == 1 )
+ {
+ bDone = true;
+ }
+
+ _UnregisterMeAndChildrenDueToRootDelete( *pChildNode );
+ }
+
+ if ( !bIsPhantom )
+ {
+ SwTxtNode* pTxtNode( rNodeNum.GetTxtNode() );
+ if ( pTxtNode )
+ {
+ pTxtNode->RemoveFromList();
+ // --> clear all list attributes and the list style
+ SvUShortsSort aResetAttrsArray;
+ aResetAttrsArray.Insert( RES_PARATR_LIST_ID );
+ aResetAttrsArray.Insert( RES_PARATR_LIST_LEVEL );
+ aResetAttrsArray.Insert( RES_PARATR_LIST_ISRESTART );
+ aResetAttrsArray.Insert( RES_PARATR_LIST_RESTARTVALUE );
+ aResetAttrsArray.Insert( RES_PARATR_LIST_ISCOUNTED );
+ aResetAttrsArray.Insert( RES_PARATR_NUMRULE );
+ SwPaM aPam( *pTxtNode );
+ pTxtNode->GetDoc()->ResetAttrs( aPam, sal_False,
+ &aResetAttrsArray,
+ false );
+ // <--
+ }
+ }
+}
+// <--
+
+// --> OD 2007-09-06 #i81002#
+const SwNodeNum* SwNodeNum::GetPrecedingNodeNumOf( const SwTxtNode& rTxtNode ) const
+{
+ const SwNodeNum* pPrecedingNodeNum( 0 );
+
+ // --> OD 2007-10-31 #i83479#
+ SwNodeNum aNodeNumForTxtNode( const_cast<SwTxtNode*>(&rTxtNode) );
+ // <--
+
+ pPrecedingNodeNum = dynamic_cast<const SwNodeNum*>(
+ GetRoot()
+ ? GetRoot()->GetPrecedingNodeOf( aNodeNumForTxtNode )
+ : GetPrecedingNodeOf( aNodeNumForTxtNode ) );
+
+ return pPrecedingNodeNum;
+}
+// <--
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/SwNumberTree/SwNumberTree.cxx b/sw/source/core/SwNumberTree/SwNumberTree.cxx
new file mode 100644
index 000000000000..03ccf0e71bad
--- /dev/null
+++ b/sw/source/core/SwNumberTree/SwNumberTree.cxx
@@ -0,0 +1,1321 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+#include <algorithm>
+#include <functional>
+#include <SwNumberTree.hxx>
+
+using std::vector;
+using std::find;
+
+#if OSL_DEBUG_LEVEL > 1
+unsigned long SwNumberTreeNode::nInstances = 0;
+#endif
+
+SwNumberTreeNode::SwNumberTreeNode()
+ : mChildren(),
+ mpParent( 0 ),
+ mnNumber( 0 ),
+ mbContinueingPreviousSubTree( false ),
+ mbPhantom( false ),
+ mItLastValid()
+{
+ mItLastValid = mChildren.end();
+
+#if OSL_DEBUG_LEVEL > 1
+ mnSerial = nInstances;
+ nInstances++;
+#endif
+}
+
+SwNumberTreeNode::~SwNumberTreeNode()
+{
+ if (GetChildCount() > 0)
+ {
+ if (HasOnlyPhantoms())
+ {
+ delete *mChildren.begin();
+
+ mChildren.clear();
+ mItLastValid = mChildren.end();
+ }
+ else
+ {
+ OSL_FAIL("lost children!");
+ }
+ }
+
+ OSL_ENSURE( IsPhantom() || mpParent == NULL, ": I'm not supposed to have a parent.");
+
+#if OSL_DEBUG_LEVEL > 1
+ nInstances--;
+#endif
+
+ mpParent = (SwNumberTreeNode *) 0xdeadbeef;
+
+ OSL_ENSURE(mChildren.empty(), "children left!");
+}
+
+SwNumberTreeNode * SwNumberTreeNode::CreatePhantom()
+{
+ SwNumberTreeNode * pNew = NULL;
+
+ if (! mChildren.empty() &&
+ (*mChildren.begin())->IsPhantom())
+ {
+ OSL_FAIL("phantom already present");
+ }
+ else
+ {
+ pNew = Create();
+ pNew->SetPhantom(true);
+ pNew->mpParent = this;
+
+ std::pair<tSwNumberTreeChildren::iterator, bool> aInsert =
+ mChildren.insert(pNew);
+
+ if (! aInsert.second)
+ {
+ OSL_FAIL("insert of phantom failed!");
+
+ delete pNew;
+ pNew = NULL;
+ }
+ }
+
+ return pNew;
+}
+
+SwNumberTreeNode * SwNumberTreeNode::GetRoot() const
+{
+ SwNumberTreeNode * pResult = mpParent;
+
+ if (pResult)
+ while (pResult->mpParent)
+ pResult = pResult->mpParent;
+
+ return pResult;
+}
+
+void SwNumberTreeNode::ClearObsoletePhantoms()
+{
+ tSwNumberTreeChildren::iterator aIt = mChildren.begin();
+
+ if (aIt != mChildren.end() && (*aIt)->IsPhantom())
+ {
+ (*aIt)->ClearObsoletePhantoms();
+
+ if ((*aIt)->mChildren.empty())
+ {
+ // --> OD 2006-01-17 #i60652#
+ // Because <mChildren.erase(aIt)> could destroy the element, which
+ // is referenced by <mItLastValid>, it's needed to adjust
+ // <mItLastValid> before erasing <aIt>.
+ SetLastValid(mChildren.end());
+ // <--
+
+ delete *aIt;
+ mChildren.erase(aIt);
+ }
+ }
+}
+
+void SwNumberTreeNode::ValidateHierarchical(const SwNumberTreeNode * pNode) const
+{
+ tSwNumberTreeChildren::const_iterator aValidateIt =
+ GetIterator(pNode);
+
+ if (aValidateIt != mChildren.end())
+ {
+ OSL_ENSURE((*aValidateIt)->mpParent == this, "wrong parent");
+
+ tSwNumberTreeChildren::const_iterator aIt = mItLastValid;
+
+ // -->
+ // improvement:
+ // - Only one time checked for <mChildren.end()>.
+ // - Less checks for each loop run.
+ // correction:
+ // - consider case that current node isn't counted and isn't the first
+ // child of its parent. In this case the number of last counted child
+ // of the previous node determines the start value for the following
+ // children loop, if all children have to be validated and the first
+ // one doesn't restart the counting.
+ SwNumberTree::tSwNumTreeNumber nTmpNumber( 0 );
+ if (aIt != mChildren.end())
+ nTmpNumber = (*aIt)->mnNumber;
+ else
+ {
+ aIt = mChildren.begin();
+ (*aIt)->mbContinueingPreviousSubTree = false;
+
+ // determine default start value
+ // consider the case that the first child isn't counted.
+ nTmpNumber = (*aIt)->GetStartValue();
+ if ( !(*aIt)->IsCounted() &&
+ ( !(*aIt)->HasCountedChildren() || (*aIt)->IsPhantom() ) )
+ {
+ --nTmpNumber;
+ }
+
+ // determine special start value for the case that first child
+ // doesn't restart the numbering and the parent node isn't counted
+ // and isn't the first child.
+ const bool bParentCounted( IsCounted() &&
+ ( !IsPhantom() ||
+ HasPhantomCountedParent() ) );
+ if ( !(*aIt)->IsRestart() &&
+ GetParent() && !bParentCounted )
+ {
+ tSwNumberTreeChildren::const_iterator aParentChildIt =
+ GetParent()->GetIterator( this );
+ while ( aParentChildIt != GetParent()->mChildren.begin() )
+ {
+ --aParentChildIt;
+ SwNumberTreeNode* pPrevNode( *aParentChildIt );
+ if ( pPrevNode->GetChildCount() > 0 )
+ {
+ (*aIt)->mbContinueingPreviousSubTree = true;
+ nTmpNumber = (*(pPrevNode->mChildren.rbegin()))->GetNumber();
+ if ( (*aIt)->IsCounted() &&
+ ( !(*aIt)->IsPhantom() ||
+ (*aIt)->HasPhantomCountedParent() ) )
+ {
+ ++nTmpNumber;
+ }
+ break;
+ }
+ else if ( pPrevNode->IsCounted() )
+ {
+ break;
+ }
+ else
+ {
+ // Previous node has no children and is not counted.
+ // Thus, next turn and check for the previous node.
+ }
+ }
+ }
+
+ (*aIt)->mnNumber = nTmpNumber;
+ }
+
+ while (aIt != aValidateIt)
+ {
+ ++aIt;
+ (*aIt)->mbContinueingPreviousSubTree = false;
+
+ // --> only for counted nodes the number
+ // has to be adjusted, compared to the previous node.
+ // this condition is hold also for nodes, which restart the numbering.
+ if ( (*aIt)->IsCounted() )
+ {
+ if ((*aIt)->IsRestart())
+ nTmpNumber = (*aIt)->GetStartValue();
+ else
+ ++nTmpNumber;
+ }
+ // <--
+
+ (*aIt)->mnNumber = nTmpNumber;
+ }
+ // <--
+
+ SetLastValid(aIt, true);
+ }
+}
+
+void SwNumberTreeNode::ValidateContinuous(const SwNumberTreeNode * pNode) const
+{
+ tSwNumberTreeChildren::const_iterator aIt = mItLastValid;
+
+ SwNumberTree::tSwNumTreeNumber nTmpNumber = 0;
+
+ do
+ {
+ if (aIt == mChildren.end())
+ {
+ aIt = mChildren.begin();
+
+ nTmpNumber = GetStartValue();
+ }
+ else
+ ++aIt;
+
+ if (aIt != mChildren.end())
+ {
+ SwNumberTreeNode * pPred = (*aIt)->GetPred();
+
+ // --> OD 2006-04-21 #i64311#
+ // correct consideration of phantoms
+ // correct consideration of restart at a number tree node
+ if ( pPred )
+ {
+ if ( !(*aIt)->IsCounted() )
+ // --> OD 2006-05-12 #i65284#
+ nTmpNumber = pPred->GetNumber( pPred->GetParent() != (*aIt)->GetParent() );
+ // <--
+ else
+ {
+ if ( (*aIt)->IsRestart() )
+ nTmpNumber = (*aIt)->GetStartValue();
+ else
+ nTmpNumber = pPred->GetNumber( pPred->GetParent() != (*aIt)->GetParent() ) + 1;
+ }
+ }
+ else
+ {
+ if ( !(*aIt)->IsCounted() )
+ nTmpNumber = GetStartValue() - 1;
+ else
+ {
+ if ( (*aIt)->IsRestart() )
+ nTmpNumber = (*aIt)->GetStartValue();
+ else
+ nTmpNumber = GetStartValue();
+ }
+ }
+ // <--
+
+ (*aIt)->mnNumber = nTmpNumber;
+ }
+ }
+ while (aIt != mChildren.end() && *aIt != pNode);
+
+ // --> OD 2008-05-21 #i74748# - applied patch from garnier_romain
+ // number tree node has to be validated.
+ SetLastValid( aIt, true );
+ // <--
+}
+
+void SwNumberTreeNode::Validate(const SwNumberTreeNode * pNode) const
+{
+ if (! IsValid(pNode))
+ {
+ if (IsContinuous())
+ ValidateContinuous(pNode);
+ else
+ ValidateHierarchical(pNode);
+ }
+}
+
+void SwNumberTreeNode::ValidateTree()
+{
+ if (! IsContinuous())
+ {
+ {
+ tSwNumberTreeChildren::reverse_iterator aIt = mChildren.rbegin();
+
+ if (aIt != mChildren.rend())
+ Validate(*aIt);
+ }
+ {
+ tSwNumberTreeChildren::iterator aIt;
+
+ for (aIt = mChildren.begin(); aIt != mChildren.end(); ++aIt)
+ (*aIt)->ValidateTree();
+ }
+ }
+ else
+ {
+ SwNumberTreeNode * pNode = GetLastDescendant();
+
+ if (pNode && pNode->mpParent)
+ pNode->mpParent->Validate(pNode);
+ }
+}
+
+void SwNumberTreeNode::_GetNumberVector(vector<SwNumberTree::tSwNumTreeNumber> & rVector,
+ bool bValidate) const
+{
+ if (mpParent)
+ {
+ mpParent->_GetNumberVector(rVector, bValidate);
+ rVector.push_back(GetNumber(bValidate));
+ }
+}
+
+SwNumberTreeNode * SwNumberTreeNode::GetFirstNonPhantomChild()
+{
+ if (IsPhantom())
+ return (*mChildren.begin())->GetFirstNonPhantomChild();
+
+ return this;
+}
+
+/** Moves all children of this node that are greater than a given node
+ to the destination node.
+*/
+void SwNumberTreeNode::MoveGreaterChildren( SwNumberTreeNode& _rCompareNode,
+ SwNumberTreeNode& _rDestNode )
+{
+ if ( mChildren.size() == 0 )
+ return;
+
+ // determine first child, which has to move to <_rDestNode>
+ tSwNumberTreeChildren::iterator aItUpper( mChildren.end() );
+ if ((*mChildren.begin())->IsPhantom() &&
+ _rCompareNode.LessThan(*(*mChildren.begin())->GetFirstNonPhantomChild()))
+ {
+ aItUpper = mChildren.begin();
+ }
+ else
+ {
+ aItUpper = mChildren.upper_bound(&_rCompareNode);
+ }
+
+ // move children
+ if (aItUpper != mChildren.end())
+ {
+ tSwNumberTreeChildren::iterator aIt;
+ for (aIt = aItUpper; aIt != mChildren.end(); ++aIt)
+ (*aIt)->mpParent = &_rDestNode;
+
+ _rDestNode.mChildren.insert(aItUpper, mChildren.end());
+
+ // --> OD 2006-01-17 #i60652#
+ // Because <mChildren.erase(aItUpper, mChildren.end())> could destroy
+ // the element, which is referenced by <mItLastValid>, it's needed to
+ // adjust <mItLastValid> before erasing <aIt>.
+ SetLastValid( mChildren.end() );
+ // <--
+
+ mChildren.erase(aItUpper, mChildren.end());
+
+ // --> OD 2006-01-17 #i60652#
+ if ( !mChildren.empty() )
+ {
+ SetLastValid( --(mChildren.end()) );
+ }
+ // <--
+ }
+
+#ifdef __SW_NUMBER_TREE_SANITY_CHECK
+ if (! IsSane(false) || ! IsSane(&_rDestNode))
+ clog << __FUNCTION__ << "insanity!" << endl;
+#endif
+}
+
+void SwNumberTreeNode::MoveChildren(SwNumberTreeNode * pDest)
+{
+ if (! mChildren.empty())
+ {
+ tSwNumberTreeChildren::iterator aItBegin = mChildren.begin();
+ SwNumberTreeNode * pMyFirst = *mChildren.begin();
+
+ // --> OD 2006-01-17 #i60652#
+ // Because <mChildren.erase(aItBegin)> could destroy the element,
+ // which is referenced by <mItLastValid>, it's needed to adjust
+ // <mItLastValid> before erasing <aItBegin>.
+ SetLastValid(mChildren.end());
+ // <--
+
+ if (pMyFirst->IsPhantom())
+ {
+ SwNumberTreeNode * pDestLast = NULL;
+
+ if (pDest->mChildren.empty())
+ pDestLast = pDest->CreatePhantom();
+ else
+ pDestLast = *pDest->mChildren.rbegin();
+
+ pMyFirst->MoveChildren(pDestLast);
+
+ delete pMyFirst;
+ mChildren.erase(aItBegin);
+
+ aItBegin = mChildren.begin();
+ }
+
+ tSwNumberTreeChildren::iterator aIt;
+ for (aIt = mChildren.begin(); aIt != mChildren.end(); ++aIt)
+ (*aIt)->mpParent = pDest;
+
+ pDest->mChildren.insert(mChildren.begin(), mChildren.end());
+ mChildren.clear();
+ // <stl::set.clear()> destroys all existing iterators.
+ // Thus, <mItLastValid> is also destroyed and reset becomes necessary
+ mItLastValid = mChildren.end();
+ }
+
+ OSL_ENSURE(mChildren.empty(), "MoveChildren failed!");
+
+#ifdef __SW_NUMBER_TREE_SANITY_CHECK
+ OSL_ENSURE(IsSane(false) && pDest->IsSane(false), "insanity!");
+#endif
+}
+
+void SwNumberTreeNode::AddChild( SwNumberTreeNode * pChild,
+ const int nDepth )
+{
+ /*
+ Algorithm:
+
+ Search first child A that is greater than pChild,
+ A may be the end of childs.
+ If nDepth > 0 then
+ {
+ if A is first child then
+ create new phantom child B at beginning of child list
+ else
+ B is A
+
+ Add child to B with depth nDepth - 1.
+ }
+ else
+ {
+ Insert pNode before A.
+
+ if A has predecessor B then
+ remove children of B that are greater as A and insert them as
+ children of A.
+ }
+
+*/
+
+ if ( nDepth < 0 )
+ {
+ OSL_FAIL( "<SwNumberTreeNode::AddChild(..)> - parameter <nDepth> out of valid range. Serious defect -> please inform OD." );
+ return;
+ }
+
+ if ( pChild->GetParent() != NULL || pChild->GetChildCount() > 0 )
+ {
+ OSL_FAIL("only orphans allowed.");
+ return;
+ }
+
+ if (nDepth > 0)
+ {
+ tSwNumberTreeChildren::iterator aInsertDeepIt =
+ mChildren.upper_bound(pChild);
+
+ OSL_ENSURE(! (aInsertDeepIt != mChildren.end() &&
+ (*aInsertDeepIt)->IsPhantom()), " unexspected phantom");
+
+
+ if (aInsertDeepIt == mChildren.begin())
+ {
+ SwNumberTreeNode * pNew = CreatePhantom();
+
+ SetLastValid(mChildren.end());
+
+ if (pNew)
+ pNew->AddChild(pChild, nDepth - 1);
+ }
+ else
+ {
+ --aInsertDeepIt;
+ (*aInsertDeepIt)->AddChild(pChild, nDepth - 1);
+ }
+
+ }
+ else
+ {
+ pChild->PreAdd();
+ std::pair<tSwNumberTreeChildren::iterator, bool> aResult =
+ mChildren.insert(pChild);
+
+ if (aResult.second)
+ {
+ pChild->mpParent = this;
+ bool bNotification = pChild->IsNotificationEnabled();
+ tSwNumberTreeChildren::iterator aInsertedIt = aResult.first;
+
+ if (aInsertedIt != mChildren.begin())
+ {
+ tSwNumberTreeChildren::iterator aPredIt = aInsertedIt;
+ --aPredIt;
+
+ // -->
+ // Move greater children of previous node to new child.
+ // This has to be done recursively on the children levels.
+ // Initialize loop variables <pPrevChildNode> and <pDestNode>
+ // for loop on children levels.
+ SwNumberTreeNode* pPrevChildNode( *aPredIt );
+ SwNumberTreeNode* pDestNode( pChild );
+ while ( pDestNode && pPrevChildNode &&
+ pPrevChildNode->GetChildCount() > 0 )
+ {
+ // move children
+ pPrevChildNode->MoveGreaterChildren( *pChild, *pDestNode );
+
+ // prepare next loop:
+ // - search of last child of <pPrevChildNode
+ // - If found, determine destination node
+ if ( pPrevChildNode->GetChildCount() > 0 )
+ {
+ tSwNumberTreeChildren::reverse_iterator aIt =
+ pPrevChildNode->mChildren.rbegin();
+ pPrevChildNode = *aIt;
+ // determine new destination node
+ if ( pDestNode->GetChildCount() > 0 )
+ {
+ pDestNode = *(pDestNode->mChildren.begin());
+ if ( !pDestNode->IsPhantom() )
+ {
+ pDestNode = pDestNode->mpParent->CreatePhantom();
+ }
+ }
+ else
+ {
+ pDestNode = pDestNode->CreatePhantom();
+ }
+ }
+ else
+ {
+ // ready -> break loop.
+ break;
+ }
+ }
+ // assure that unnessary created phantoms at <pChild> are deleted.
+ pChild->ClearObsoletePhantoms();
+ // <--
+
+ if ((*aPredIt)->IsValid())
+ SetLastValid(aPredIt);
+ }
+ else
+ SetLastValid(mChildren.end());
+
+ ClearObsoletePhantoms();
+
+ if( bNotification )
+ {
+ // invalidation of not counted parent
+ // and notification of its siblings.
+ if ( !IsCounted() )
+ {
+ InvalidateMe();
+ NotifyInvalidSiblings();
+ }
+ NotifyInvalidChildren();
+ }
+ }
+ }
+
+#ifdef __SW_NUMBER_TREE_SANITY_CHECK
+ if (! IsSane(false))
+ clog << __FUNCTION__ << ": insanity!" << endl;
+#endif
+}
+
+void SwNumberTreeNode::RemoveChild(SwNumberTreeNode * pChild)
+{
+ /*
+ Algorithm:
+
+ if pChild has predecessor A then
+ B is A
+ else
+ create phantom child B at beginning of child list
+
+ Move children of pChild to B.
+ */
+
+ if (pChild->IsPhantom())
+ {
+ OSL_FAIL("not applicable to phantoms!");
+
+ return;
+ }
+
+ tSwNumberTreeChildren::const_iterator aRemoveIt = GetIterator(pChild);
+
+ if (aRemoveIt != mChildren.end())
+ {
+ SwNumberTreeNode * pRemove = *aRemoveIt;
+
+ pRemove->mpParent = NULL;
+
+ tSwNumberTreeChildren::const_iterator aItPred = mChildren.end();
+
+ if (aRemoveIt == mChildren.begin())
+ {
+ if (! pRemove->mChildren.empty())
+ {
+ CreatePhantom();
+
+ aItPred = mChildren.begin();
+ }
+ }
+ else
+ {
+ aItPred = aRemoveIt;
+ --aItPred;
+ }
+
+ if (! pRemove->mChildren.empty())
+ {
+ pRemove->MoveChildren(*aItPred);
+ (*aItPred)->InvalidateTree();
+ (*aItPred)->NotifyInvalidChildren();
+ }
+
+ // --> OD 2006-01-17 #i60652#
+ // Because <mChildren.erase(aRemoveIt)> could destroy the element,
+ // which is referenced by <mItLastValid>, it's needed to adjust
+ // <mItLastValid> before erasing <aRemoveIt>.
+ if (aItPred != mChildren.end() && (*aItPred)->IsPhantom())
+ SetLastValid(mChildren.end());
+ else
+ SetLastValid(aItPred);
+ // <--
+
+ mChildren.erase(aRemoveIt);
+
+ NotifyInvalidChildren();
+ }
+ else
+ {
+ OSL_FAIL("RemoveChild: failed!");
+ }
+
+ pChild->PostRemove();
+}
+
+void SwNumberTreeNode::RemoveMe()
+{
+ if (mpParent)
+ {
+ SwNumberTreeNode * pSavedParent = mpParent;
+
+ pSavedParent->RemoveChild(this);
+
+ while (pSavedParent && pSavedParent->IsPhantom() &&
+ pSavedParent->HasOnlyPhantoms())
+ pSavedParent = pSavedParent->GetParent();
+
+ if (pSavedParent)
+ pSavedParent->ClearObsoletePhantoms();
+
+#ifdef __SW_NUMBER_TREE_SANITY_CHECK
+ if (! IsSane(false))
+ clog << __FUNCTION__ << ": insanity!" << endl;
+#endif
+ }
+}
+
+bool SwNumberTreeNode::IsValid() const
+{
+ return mpParent ? mpParent->IsValid(this) : false;
+}
+
+SwNumberTree::tSwNumTreeNumber SwNumberTreeNode::GetNumber(bool bValidate)
+ const
+{
+ if (bValidate && mpParent)
+ mpParent->Validate(this);
+
+ return mnNumber;
+}
+
+bool SwNumberTreeNode::IsContinueingPreviousSubTree() const
+{
+ return mbContinueingPreviousSubTree;
+}
+
+
+vector<SwNumberTree::tSwNumTreeNumber> SwNumberTreeNode::GetNumberVector() const
+{
+ vector<SwNumberTree::tSwNumTreeNumber> aResult;
+
+ _GetNumberVector(aResult);
+
+ return aResult;
+}
+
+bool SwNumberTreeNode::IsValid(const SwNumberTreeNode * pChild) const
+{
+ bool bResult = false;
+
+ if (mItLastValid != mChildren.end())
+ {
+ if (pChild && pChild->mpParent == this)
+ {
+ bResult = ! (*mItLastValid)->LessThan(*pChild);
+ }
+ }
+
+ return bResult;
+}
+
+bool SwNumberTreeNode::IsPhantom() const
+{
+ return mbPhantom;
+}
+
+void SwNumberTreeNode::SetPhantom(bool _bPhantom)
+{
+ mbPhantom = _bPhantom;
+}
+
+bool SwNumberTreeNode::HasOnlyPhantoms() const
+{
+ bool bResult = false;
+
+ if (GetChildCount() == 1)
+ {
+ tSwNumberTreeChildren::const_iterator aIt = mChildren.begin();
+
+ bResult = (*aIt)->IsPhantom() && (*aIt)->HasOnlyPhantoms();
+ }
+ else if (GetChildCount() == 0)
+ bResult = true;
+
+ return bResult;
+}
+
+bool SwNumberTreeNode::IsCounted() const
+{
+ return !IsPhantom() ||
+ ( IsCountPhantoms() && HasCountedChildren() );
+}
+
+bool SwNumberTreeNode::HasPhantomCountedParent() const
+{
+ bool bRet( false );
+
+ OSL_ENSURE( IsPhantom(),
+ "<SwNumberTreeNode::HasPhantomCountedParent()> - wrong usage of method - it's only for phantoms" );
+ if ( IsPhantom() && mpParent )
+ {
+ if ( mpParent == GetRoot() )
+ {
+ bRet = true;
+ }
+ else if ( !mpParent->IsPhantom() )
+ {
+ bRet = mpParent->IsCounted();
+ }
+ else
+ {
+ bRet = mpParent->IsCounted() && mpParent->HasPhantomCountedParent();
+ }
+ }
+
+ return bRet;
+}
+
+bool SwNumberTreeNode::IsFirst(const SwNumberTreeNode * pNode) const
+{
+ tSwNumberTreeChildren::const_iterator aIt = mChildren.begin();
+
+ if ((*aIt)->IsPhantom())
+ ++aIt;
+
+ return *aIt == pNode;
+}
+
+bool SwNumberTreeNode::IsFirst() const
+{
+ bool bResult = true;
+
+ if (GetParent())
+ {
+ if (GetParent()->IsFirst(this))
+ {
+ SwNumberTreeNode * pNode = GetParent();
+
+ while (pNode)
+ {
+ if (!pNode->IsPhantom() && pNode->GetParent())
+ {
+ bResult = false;
+ break;
+ }
+
+ pNode = pNode->GetParent();
+ }
+
+ // If node isn't the first child, it is the second child and the
+ // first child is a phanton. In this case check, if the first phantom
+ // child have only phanton childs
+ if ( bResult &&
+ this != *(GetParent()->mChildren.begin()) &&
+ !(*(GetParent()->mChildren.begin()))->HasOnlyPhantoms() )
+ {
+ bResult = false;
+ }
+ }
+ else
+ bResult = false;
+ }
+
+ return bResult;
+}
+
+void SwNumberTreeNode::SetLevelInListTree( const int nLevel )
+{
+ if ( nLevel < 0 )
+ {
+ OSL_FAIL( "<SwNumberTreeNode::SetLevelInListTree(..)> - parameter <nLevel> out of valid range. Serious defect -> please inform OD." );
+ return;
+ }
+
+ OSL_ENSURE( GetParent(),
+ "<SwNumberTreeNode::SetLevelInListTree(..)> - can only be called for number tree nodes in a list tree" );
+ if ( GetParent() )
+ {
+ if ( nLevel != GetLevelInListTree() )
+ {
+ SwNumberTreeNode* pRootTreeNode = GetRoot();
+ OSL_ENSURE( pRootTreeNode,
+ "<SwNumberTreeNode::SetLevelInListTree(..)> - no root tree node found. Serious defect -> please inform OD." );
+
+ RemoveMe();
+ pRootTreeNode->AddChild( this, nLevel );
+ }
+ }
+}
+
+int SwNumberTreeNode::GetLevelInListTree() const
+{
+ if (mpParent)
+ return mpParent->GetLevelInListTree() + 1;
+
+ return -1;
+}
+
+SwNumberTreeNode::tSwNumberTreeChildren::size_type
+SwNumberTreeNode::GetChildCount() const
+{
+ return mChildren.size();
+}
+
+#ifdef __SW_NUMBER_TREE_SANITY_CHECK
+bool SwNumberTreeNode::IsSane(bool bRecursive) const
+{
+ vector<const SwNumberTreeNode*> aParents;
+
+ return IsSane(bRecursive, aParents);
+}
+
+bool SwNumberTreeNode::IsSane(bool bRecursive,
+ vector<const SwNumberTreeNode *> rParents)
+ const
+{
+ bool bResult = true;
+
+ tSwNumberTreeChildren::const_iterator aIt;
+
+ if (find(rParents.begin(), rParents.end(), this) != rParents.end())
+ {
+ OSL_FAIL(" I'm my own ancestor!");
+
+ bResult = false;
+ }
+
+ if (! rParents.empty() && rParents.back() != mpParent)
+ {
+ OSL_FAIL(" I'm a bastard!");
+
+ bResult = false;
+ }
+
+ rParents.push_back(this);
+
+ bool bFirst = true;
+ for (aIt = mChildren.begin(); aIt != mChildren.end(); ++aIt)
+ {
+ if (*aIt)
+ {
+ if ((*aIt)->IsPhantom())
+ {
+ if ((*aIt)->HasOnlyPhantoms())
+ {
+ bResult = false;
+ }
+
+ if (! bFirst)
+ {
+ OSL_FAIL(" found phantom not at first position.");
+
+ bResult = false;
+ }
+ }
+
+ if ((*aIt)->mpParent != (SwNumberTreeNode *) this)
+ {
+ OSL_FAIL("found a bastard");
+
+ bResult = false;
+ }
+
+ if (mpParent)
+ {
+ if (!(*aIt)->IsPhantom() && (*aIt)->LessThan(*this))
+ {
+ OSL_FAIL(" found child less than me");
+
+ bResult = false;
+ }
+ }
+ }
+ else
+ {
+ OSL_FAIL("found child that is NULL");
+ bResult = false;
+ }
+
+ if (bRecursive)
+ bResult = (*aIt)->IsSane(bRecursive, rParents) && bResult;
+ }
+
+ rParents.pop_back();
+
+ return bResult;
+}
+#endif // __SW_NUMBER_TREE_SANITY_CHECK
+
+SwNumberTreeNode::tSwNumberTreeChildren::const_iterator
+SwNumberTreeNode::GetIterator(const SwNumberTreeNode * pChild) const
+{
+ tSwNumberTreeChildren::const_iterator aItResult =
+ mChildren.find(const_cast<SwNumberTreeNode *>(pChild));
+
+ OSL_ENSURE( aItResult != mChildren.end(),
+ "something went wrong getting the iterator for a child");
+
+ return aItResult;
+}
+
+#if OSL_DEBUG_LEVEL > 1
+unsigned long SwNumberTreeNode::GetInstances()
+{
+ return nInstances;
+}
+
+unsigned long SwNumberTreeNode::GetSerial()
+{
+ return mnSerial;
+}
+#endif
+
+bool SwNumberTreeNodeLessThan(const SwNumberTreeNode * pA,
+ const SwNumberTreeNode * pB)
+{
+ bool bResult = false;
+
+ if (pA == NULL && pB != NULL)
+ bResult = true;
+ else if (pA != NULL && pB != NULL)
+ bResult = pA->LessThan(*pB);
+
+ return bResult;
+}
+
+SwNumberTreeNode * SwNumberTreeNode::GetLastDescendant() const
+{
+ SwNumberTreeNode * pResult = NULL;
+ tSwNumberTreeChildren::const_reverse_iterator aIt = mChildren.rbegin();
+
+ if (aIt != mChildren.rend())
+ {
+ pResult = (*aIt)->GetLastDescendant();
+
+ if (! pResult)
+ pResult = *aIt;
+ }
+
+ return pResult;
+}
+
+bool SwNumberTreeNode::LessThan(const SwNumberTreeNode & rTreeNode) const
+{
+ return this < &rTreeNode;
+}
+
+SwNumberTreeNode * SwNumberTreeNode::GetPred(bool bSibling) const
+{
+ SwNumberTreeNode * pResult = NULL;
+
+ if (mpParent)
+ {
+ tSwNumberTreeChildren::const_iterator aIt =
+ mpParent->GetIterator(this);
+
+ if ( aIt == mpParent->mChildren.begin() )
+ {
+ // --> OD 2006-04-24 #i64311#
+ // root node is no valid predecessor
+ pResult = mpParent->GetParent() ? mpParent : NULL;
+ // <--
+ }
+ else
+ {
+ --aIt;
+
+ if ( !bSibling )
+ pResult = (*aIt)->GetLastDescendant();
+ else
+ pResult = (*aIt);
+
+ if (! pResult)
+ pResult = (*aIt);
+ }
+ }
+
+ return pResult;
+}
+
+void SwNumberTreeNode::SetLastValid
+ ( SwNumberTreeNode::tSwNumberTreeChildren::const_iterator aItValid,
+ bool bValidating ) const
+{
+ OSL_ENSURE( (aItValid == mChildren.end() || GetIterator(*aItValid) != mChildren.end()),
+ "last-valid iterator");
+
+ if (
+ bValidating ||
+ aItValid == mChildren.end() ||
+ (mItLastValid != mChildren.end() &&
+ (*aItValid)->LessThan(**mItLastValid))
+ )
+ {
+ mItLastValid = aItValid;
+ // invalidation of children of next not counted is needed
+ if ( GetParent() )
+ {
+ tSwNumberTreeChildren::const_iterator aParentChildIt =
+ GetParent()->GetIterator( this );
+ ++aParentChildIt;
+ if ( aParentChildIt != GetParent()->mChildren.end() )
+ {
+ SwNumberTreeNode* pNextNode( *aParentChildIt );
+ if ( !pNextNode->IsCounted() )
+ {
+ pNextNode->InvalidateChildren();
+ }
+ }
+ }
+ }
+
+ {
+ if (IsContinuous())
+ {
+ tSwNumberTreeChildren::const_iterator aIt = mItLastValid;
+
+ if (aIt != mChildren.end())
+ ++aIt;
+ else
+ aIt = mChildren.begin();
+
+ while (aIt != mChildren.end())
+ {
+ (*aIt)->InvalidateTree();
+
+ ++aIt;
+ }
+
+ SetLastValid(bValidating);
+ }
+ }
+}
+
+void SwNumberTreeNode::SetLastValid(bool bValidating) const
+{
+ if (mpParent)
+ {
+ tSwNumberTreeChildren::const_iterator aIt = mpParent->GetIterator(this);
+
+ mpParent->SetLastValid(aIt, bValidating);
+ }
+}
+
+void SwNumberTreeNode::InvalidateTree() const
+{
+ // do not call SetInvalid, would cause loop !!!
+ mItLastValid = mChildren.end();
+
+ tSwNumberTreeChildren::const_iterator aIt;
+
+ for (aIt = mChildren.begin(); aIt != mChildren.end(); ++aIt)
+ (*aIt)->InvalidateTree();
+}
+
+void SwNumberTreeNode::Invalidate(SwNumberTreeNode * pChild)
+{
+ if (pChild->IsValid())
+ {
+ tSwNumberTreeChildren::const_iterator aIt = GetIterator(pChild);
+
+ if (aIt != mChildren.begin())
+ --aIt;
+ else
+ aIt = mChildren.end();
+
+ SetLastValid(aIt);
+
+ }
+}
+
+void SwNumberTreeNode::InvalidateMe()
+{
+ if (mpParent)
+ mpParent->Invalidate(this);
+}
+
+void SwNumberTreeNode::ValidateMe()
+{
+ if (mpParent)
+ mpParent->Validate(this);
+}
+
+void SwNumberTreeNode::Notify()
+{
+ if (IsNotifiable())
+ {
+ if (! IsPhantom())
+ NotifyNode();
+
+ tSwNumberTreeChildren::iterator aIt;
+
+ for (aIt = mChildren.begin(); aIt != mChildren.end(); ++aIt)
+ (*aIt)->Notify();
+ }
+}
+
+void SwNumberTreeNode::NotifyInvalidChildren()
+{
+ if (IsNotifiable())
+ {
+ tSwNumberTreeChildren::const_iterator aIt = mItLastValid;
+
+ if (aIt == mChildren.end())
+ aIt = mChildren.begin();
+ else
+ ++aIt;
+
+ while (aIt != mChildren.end())
+ {
+ (*aIt)->Notify();
+
+ ++aIt;
+ }
+ // notification of next not counted node is also needed.
+ if ( GetParent() )
+ {
+ tSwNumberTreeChildren::const_iterator aParentChildIt =
+ GetParent()->GetIterator( this );
+ ++aParentChildIt;
+ if ( aParentChildIt != GetParent()->mChildren.end() )
+ {
+ SwNumberTreeNode* pNextNode( *aParentChildIt );
+ if ( !pNextNode->IsCounted() )
+ {
+ pNextNode->NotifyInvalidChildren();
+ }
+ }
+ }
+
+ // <--
+ }
+
+ if (IsContinuous() && mpParent)
+ mpParent->NotifyInvalidChildren();
+}
+
+void SwNumberTreeNode::NotifyInvalidSiblings()
+{
+ if (mpParent != NULL)
+ mpParent->NotifyInvalidChildren();
+}
+
+// --> OD 2007-09-07 #i81002#
+const SwNumberTreeNode* SwNumberTreeNode::GetPrecedingNodeOf(
+ const SwNumberTreeNode& rNode ) const
+{
+ const SwNumberTreeNode* pPrecedingNode( 0 );
+
+ if ( GetChildCount() > 0 )
+ {
+ tSwNumberTreeChildren::const_iterator aUpperBoundIt =
+ mChildren.upper_bound( const_cast<SwNumberTreeNode*>(&rNode) );
+ if ( aUpperBoundIt != mChildren.begin() )
+ {
+ --aUpperBoundIt;
+ pPrecedingNode = (*aUpperBoundIt)->GetPrecedingNodeOf( rNode );
+ }
+ }
+
+ if ( pPrecedingNode == 0 && GetRoot() )
+ {
+ // <this> node has no children or the given node precedes all its children
+ // and the <this> node isn't the root node.
+ // Thus, compare the given node with the <this> node in order to check,
+ // if the <this> node precedes the given node.
+ if ( !(rNode.LessThan( *this )) )
+ {
+ pPrecedingNode = this;
+ }
+ }
+
+ return pPrecedingNode;
+}
+// <--
+
+void SwNumberTreeNode::NotifyNodesOnListLevel( const int nListLevel )
+{
+ if ( nListLevel < 0 )
+ {
+ OSL_FAIL( "<SwNumberTreeNode::NotifyNodesOnListLevel(..)> - invalid list level provided" );
+ return;
+ }
+
+ SwNumberTreeNode* pRootNode = GetParent() ? GetRoot() : this;
+
+ pRootNode->NotifyChildrenOnDepth( nListLevel );
+}
+
+void SwNumberTreeNode::NotifyChildrenOnDepth( const int nDepth )
+{
+ OSL_ENSURE( nDepth >= 0,
+ "<SwNumberTreeNode::NotifyChildrenOnDepth(..)> - misusage" );
+
+ SwNumberTreeNode::tSwNumberTreeChildren::iterator aChildIter =
+ mChildren.begin();
+ while ( aChildIter != mChildren.end() )
+ {
+ if ( nDepth == 0 )
+ {
+ (*aChildIter)->NotifyNode();
+ }
+ else
+ {
+ (*aChildIter)->NotifyChildrenOnDepth( nDepth - 1 );
+ }
+
+ ++aChildIter;
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/access/acccell.cxx b/sw/source/core/access/acccell.cxx
new file mode 100644
index 000000000000..dbd1b5196593
--- /dev/null
+++ b/sw/source/core/access/acccell.cxx
@@ -0,0 +1,378 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+ /*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+
+#include <osl/mutex.hxx>
+#include <com/sun/star/accessibility/AccessibleRole.hpp>
+#include <com/sun/star/accessibility/AccessibleStateType.hpp>
+#include <com/sun/star/accessibility/AccessibleEventId.hpp>
+#include <unotools/accessiblestatesethelper.hxx>
+#include <rtl/uuid.h>
+#include <vcl/svapp.hxx>
+#include <cellfrm.hxx>
+#include <tabfrm.hxx>
+#include <swtable.hxx>
+#include "crsrsh.hxx"
+#include "viscrs.hxx"
+#include <accfrmobj.hxx>
+#include <accfrmobjslist.hxx>
+#include "frmfmt.hxx"
+#include "cellatr.hxx"
+#include "accmap.hxx"
+#include <acccell.hxx>
+
+#ifndef _STLP_CFLOAT
+#include <cfloat>
+#endif
+
+#include <limits.h>
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::accessibility;
+using ::rtl::OUString;
+using namespace sw::access;
+
+const sal_Char sServiceName[] = "com.sun.star.table.AccessibleCellView";
+const sal_Char sImplementationName[] = "com.sun.star.comp.Writer.SwAccessibleCellView";
+
+sal_Bool SwAccessibleCell::IsSelected()
+{
+ sal_Bool bRet = sal_False;
+
+ DBG_ASSERT( GetMap(), "no map?" );
+ const ViewShell *pVSh = GetMap()->GetShell();
+ DBG_ASSERT( pVSh, "no shell?" );
+ if( pVSh->ISA( SwCrsrShell ) )
+ {
+ const SwCrsrShell *pCSh = static_cast< const SwCrsrShell * >( pVSh );
+ if( pCSh->IsTableMode() )
+ {
+ const SwCellFrm *pCFrm =
+ static_cast< const SwCellFrm * >( GetFrm() );
+ SwTableBox *pBox =
+ const_cast< SwTableBox *>( pCFrm->GetTabBox() ); //SVPtrArr!
+ bRet = pCSh->GetTableCrsr()->GetBoxes().Seek_Entry( pBox );
+ }
+ }
+
+ return bRet;
+}
+
+void SwAccessibleCell::GetStates( ::utl::AccessibleStateSetHelper& rStateSet )
+{
+ SwAccessibleContext::GetStates( rStateSet );
+
+ // SELECTABLE
+ const ViewShell *pVSh = GetMap()->GetShell();
+ DBG_ASSERT( pVSh, "no shell?" );
+ if( pVSh->ISA( SwCrsrShell ) )
+ rStateSet.AddState( AccessibleStateType::SELECTABLE );
+
+ // SELECTED
+ if( IsSelected() )
+ {
+ rStateSet.AddState( AccessibleStateType::SELECTED );
+ OSL_ENSURE( bIsSelected, "bSelected out of sync" );
+ ::rtl::Reference < SwAccessibleContext > xThis( this );
+ GetMap()->SetCursorContext( xThis );
+ }
+}
+
+SwAccessibleCell::SwAccessibleCell( SwAccessibleMap *pInitMap,
+ const SwCellFrm *pCellFrm )
+ : SwAccessibleContext( pInitMap, AccessibleRole::TABLE_CELL, pCellFrm )
+ , bIsSelected( sal_False )
+{
+ SolarMutexGuard aGuard;
+ OUString sBoxName( pCellFrm->GetTabBox()->GetName() );
+ SetName( sBoxName );
+
+ bIsSelected = IsSelected();
+}
+
+sal_Bool SwAccessibleCell::_InvalidateMyCursorPos()
+{
+ sal_Bool bNew = IsSelected();
+ sal_Bool bOld;
+ {
+ osl::MutexGuard aGuard( aMutex );
+ bOld = bIsSelected;
+ bIsSelected = bNew;
+ }
+ if( bNew )
+ {
+ // remember that object as the one that has the caret. This is
+ // neccessary to notify that object if the cursor leaves it.
+ ::rtl::Reference < SwAccessibleContext > xThis( this );
+ GetMap()->SetCursorContext( xThis );
+ }
+
+ sal_Bool bChanged = bOld != bNew;
+ if( bChanged )
+ FireStateChangedEvent( AccessibleStateType::SELECTED, bNew );
+
+ return bChanged;
+}
+
+sal_Bool SwAccessibleCell::_InvalidateChildrenCursorPos( const SwFrm *pFrm )
+{
+ sal_Bool bChanged = sal_False;
+
+ const SwAccessibleChildSList aVisList( GetVisArea(), *pFrm, *GetMap() );
+ SwAccessibleChildSList::const_iterator aIter( aVisList.begin() );
+ while( aIter != aVisList.end() )
+ {
+ const SwAccessibleChild& rLower = *aIter;
+ const SwFrm *pLower = rLower.GetSwFrm();
+ if( pLower )
+ {
+ if( rLower.IsAccessible( GetMap()->GetShell()->IsPreView() ) )
+ {
+ ::rtl::Reference< SwAccessibleContext > xAccImpl(
+ GetMap()->GetContextImpl( pLower, sal_False ) );
+ if( xAccImpl.is() )
+ {
+ OSL_ENSURE( xAccImpl->GetFrm()->IsCellFrm(),
+ "table child is not a cell frame" );
+ bChanged |= static_cast< SwAccessibleCell *>(
+ xAccImpl.get() )->_InvalidateMyCursorPos();
+ }
+ else
+ bChanged = sal_True; // If the context is not know we
+ // don't know whether the selection
+ // changed or not.
+ }
+ else
+ {
+ // This is a box with sub rows.
+ bChanged |= _InvalidateChildrenCursorPos( pLower );
+ }
+ }
+ ++aIter;
+ }
+
+ return bChanged;
+}
+
+void SwAccessibleCell::_InvalidateCursorPos()
+{
+
+ const SwFrm *pParent = GetParent( SwAccessibleChild(GetFrm()), IsInPagePreview() );
+ OSL_ENSURE( pParent->IsTabFrm(), "parent is not a tab frame" );
+ const SwTabFrm *pTabFrm = static_cast< const SwTabFrm * >( pParent );
+ if( pTabFrm->IsFollow() )
+ pTabFrm = pTabFrm->FindMaster();
+
+ while( pTabFrm )
+ {
+ sal_Bool bChanged = _InvalidateChildrenCursorPos( pTabFrm );
+ if( bChanged )
+ {
+ ::rtl::Reference< SwAccessibleContext > xAccImpl(
+ GetMap()->GetContextImpl( pTabFrm, sal_False ) );
+ if( xAccImpl.is() )
+ {
+ AccessibleEventObject aEvent;
+ aEvent.EventId = AccessibleEventId::SELECTION_CHANGED;
+ xAccImpl->FireAccessibleEvent( aEvent );
+ }
+ }
+
+ pTabFrm = pTabFrm->GetFollow();
+ }
+}
+
+sal_Bool SwAccessibleCell::HasCursor()
+{
+ osl::MutexGuard aGuard( aMutex );
+ return bIsSelected;
+}
+
+SwAccessibleCell::~SwAccessibleCell()
+{
+}
+
+OUString SAL_CALL SwAccessibleCell::getAccessibleDescription (void)
+ throw (uno::RuntimeException)
+{
+ return GetName();
+}
+
+OUString SAL_CALL SwAccessibleCell::getImplementationName()
+ throw( uno::RuntimeException )
+{
+ return OUString(RTL_CONSTASCII_USTRINGPARAM(sImplementationName));
+}
+
+sal_Bool SAL_CALL SwAccessibleCell::supportsService(
+ const ::rtl::OUString& sTestServiceName)
+ throw (uno::RuntimeException)
+{
+ return sTestServiceName.equalsAsciiL( sServiceName,
+ sizeof(sServiceName)-1 ) ||
+ sTestServiceName.equalsAsciiL( sAccessibleServiceName,
+ sizeof(sAccessibleServiceName)-1 );
+}
+
+uno::Sequence< OUString > SAL_CALL SwAccessibleCell::getSupportedServiceNames()
+ throw( uno::RuntimeException )
+{
+ uno::Sequence< OUString > aRet(2);
+ OUString* pArray = aRet.getArray();
+ pArray[0] = OUString( RTL_CONSTASCII_USTRINGPARAM(sServiceName) );
+ pArray[1] = OUString( RTL_CONSTASCII_USTRINGPARAM(sAccessibleServiceName) );
+ return aRet;
+}
+
+void SwAccessibleCell::Dispose( sal_Bool bRecursive )
+{
+ const SwFrm *pParent = GetParent( SwAccessibleChild(GetFrm()), IsInPagePreview() );
+ ::rtl::Reference< SwAccessibleContext > xAccImpl(
+ GetMap()->GetContextImpl( pParent, sal_False ) );
+ if( xAccImpl.is() )
+ xAccImpl->DisposeChild( SwAccessibleChild(GetFrm()), bRecursive );
+ SwAccessibleContext::Dispose( bRecursive );
+}
+
+void SwAccessibleCell::InvalidatePosOrSize( const SwRect& rOldBox )
+{
+ const SwFrm *pParent = GetParent( SwAccessibleChild(GetFrm()), IsInPagePreview() );
+ ::rtl::Reference< SwAccessibleContext > xAccImpl(
+ GetMap()->GetContextImpl( pParent, sal_False ) );
+ if( xAccImpl.is() )
+ xAccImpl->InvalidateChildPosOrSize( SwAccessibleChild(GetFrm()), rOldBox );
+ SwAccessibleContext::InvalidatePosOrSize( rOldBox );
+}
+
+
+// ===== XAccessibleInterface ===========================================
+
+uno::Any SwAccessibleCell::queryInterface( const uno::Type& rType )
+ throw( uno::RuntimeException )
+{
+ if ( rType == ::getCppuType( static_cast< uno::Reference< XAccessibleValue > * >( 0 ) ) )
+ {
+ uno::Reference<XAccessibleValue> xValue = this;
+ uno::Any aRet;
+ aRet <<= xValue;
+ return aRet;
+ }
+ else
+ {
+ return SwAccessibleContext::queryInterface( rType );
+ }
+}
+
+//====== XTypeProvider ====================================================
+uno::Sequence< uno::Type > SAL_CALL SwAccessibleCell::getTypes()
+ throw(uno::RuntimeException)
+{
+ uno::Sequence< uno::Type > aTypes( SwAccessibleContext::getTypes() );
+
+ sal_Int32 nIndex = aTypes.getLength();
+ aTypes.realloc( nIndex + 1 );
+
+ uno::Type* pTypes = aTypes.getArray();
+ pTypes[nIndex] = ::getCppuType( static_cast< uno::Reference< XAccessibleValue > * >( 0 ) );
+
+ return aTypes;
+}
+
+uno::Sequence< sal_Int8 > SAL_CALL SwAccessibleCell::getImplementationId()
+ throw(uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+ static uno::Sequence< sal_Int8 > aId( 16 );
+ static sal_Bool bInit = sal_False;
+ if(!bInit)
+ {
+ rtl_createUuid( (sal_uInt8 *)(aId.getArray() ), 0, sal_True );
+ bInit = sal_True;
+ }
+ return aId;
+}
+
+// ===== XAccessibleValue ===============================================
+
+SwFrmFmt* SwAccessibleCell::GetTblBoxFormat() const
+{
+ DBG_ASSERT( GetFrm() != NULL, "no frame?" );
+ DBG_ASSERT( GetFrm()->IsCellFrm(), "no cell frame?" );
+
+ const SwCellFrm* pCellFrm = static_cast<const SwCellFrm*>( GetFrm() );
+ return pCellFrm->GetTabBox()->GetFrmFmt();
+}
+
+
+uno::Any SwAccessibleCell::getCurrentValue( )
+ throw( uno::RuntimeException )
+{
+ SolarMutexGuard aGuard;
+ CHECK_FOR_DEFUNC( XAccessibleValue );
+
+ uno::Any aAny;
+ aAny <<= GetTblBoxFormat()->GetTblBoxValue().GetValue();
+ return aAny;
+}
+
+sal_Bool SwAccessibleCell::setCurrentValue( const uno::Any& aNumber )
+ throw( uno::RuntimeException )
+{
+ SolarMutexGuard aGuard;
+ CHECK_FOR_DEFUNC( XAccessibleValue );
+
+ double fValue = 0;
+ sal_Bool bValid = (aNumber >>= fValue);
+ if( bValid )
+ {
+ SwTblBoxValue aValue( fValue );
+ GetTblBoxFormat()->SetFmtAttr( aValue );
+ }
+ return bValid;
+}
+
+uno::Any SwAccessibleCell::getMaximumValue( )
+ throw( uno::RuntimeException )
+{
+ uno::Any aAny;
+ aAny <<= DBL_MAX;
+ return aAny;
+}
+
+uno::Any SwAccessibleCell::getMinimumValue( )
+ throw( uno::RuntimeException )
+{
+ uno::Any aAny;
+ aAny <<= -DBL_MAX;
+ return aAny;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/access/acccell.hxx b/sw/source/core/access/acccell.hxx
new file mode 100644
index 000000000000..0983f8ccc4d1
--- /dev/null
+++ b/sw/source/core/access/acccell.hxx
@@ -0,0 +1,139 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+#ifndef _ACCCELL_HXX
+#define _ACCCELL_HXX
+
+#include "acccontext.hxx"
+#include <com/sun/star/accessibility/XAccessibleValue.hpp>
+
+class SwCellFrm;
+class SwFrmFmt;
+
+class SwAccessibleCell : public SwAccessibleContext,
+ ::com::sun::star::accessibility::XAccessibleValue
+
+{
+ sal_Bool bIsSelected; // protected by base class mutex
+
+ sal_Bool IsSelected();
+
+ sal_Bool _InvalidateMyCursorPos();
+ sal_Bool _InvalidateChildrenCursorPos( const SwFrm *pFrm );
+
+protected:
+
+ // Set states for getAccessibleStateSet.
+ // This drived class additionaly sets SELECTABLE(1) and SELECTED(+)
+ virtual void GetStates( ::utl::AccessibleStateSetHelper& rStateSet );
+
+ virtual void _InvalidateCursorPos();
+
+ virtual ~SwAccessibleCell();
+
+public:
+
+ SwAccessibleCell( SwAccessibleMap* pInitMap, const SwCellFrm *pCellFrm );
+
+ virtual sal_Bool HasCursor(); // required by map to remember that object
+
+ //===== XAccessibleContext ==============================================
+
+ /// Return this object's description.
+ virtual ::rtl::OUString SAL_CALL
+ getAccessibleDescription (void)
+ throw (com::sun::star::uno::RuntimeException);
+
+ //===== XServiceInfo ====================================================
+
+ /** Returns an identifier for the implementation of this object.
+ */
+ virtual ::rtl::OUString SAL_CALL
+ getImplementationName (void)
+ throw (::com::sun::star::uno::RuntimeException);
+
+ /** Return whether the specified service is supported by this class.
+ */
+ virtual sal_Bool SAL_CALL
+ supportsService (const ::rtl::OUString& sServiceName)
+ throw (::com::sun::star::uno::RuntimeException);
+
+ /** Returns a list of all supported services. In this case that is just
+ the AccessibleContext service.
+ */
+ virtual ::com::sun::star::uno::Sequence< ::rtl::OUString> SAL_CALL
+ getSupportedServiceNames (void)
+ throw (::com::sun::star::uno::RuntimeException);
+
+ virtual void Dispose( sal_Bool bRecursive = sal_False );
+
+ virtual void InvalidatePosOrSize( const SwRect& rFrm );
+
+ //===== XInterface ======================================================
+
+ // (XInterface methods need to be implemented to disambiguate
+ // between those inherited through SwAcessibleContext and
+ // XAccessibleValue).
+
+ virtual ::com::sun::star::uno::Any SAL_CALL queryInterface(
+ const ::com::sun::star::uno::Type& aType )
+ throw (::com::sun::star::uno::RuntimeException);
+
+ virtual void SAL_CALL acquire( ) throw ()
+ { SwAccessibleContext::acquire(); };
+
+ virtual void SAL_CALL release( ) throw ()
+ { SwAccessibleContext::release(); };
+
+ //====== XTypeProvider ====================================================
+ virtual ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Type > SAL_CALL getTypes( ) throw(::com::sun::star::uno::RuntimeException);
+ virtual ::com::sun::star::uno::Sequence< sal_Int8 > SAL_CALL getImplementationId( ) throw(::com::sun::star::uno::RuntimeException);
+
+ //===== XAccessibleValue ================================================
+
+private:
+ SwFrmFmt* GetTblBoxFormat() const;
+
+public:
+ virtual ::com::sun::star::uno::Any SAL_CALL getCurrentValue( )
+ throw (::com::sun::star::uno::RuntimeException);
+
+ virtual sal_Bool SAL_CALL setCurrentValue(
+ const ::com::sun::star::uno::Any& aNumber )
+ throw (::com::sun::star::uno::RuntimeException);
+
+ virtual ::com::sun::star::uno::Any SAL_CALL getMaximumValue( )
+ throw (::com::sun::star::uno::RuntimeException);
+
+ virtual ::com::sun::star::uno::Any SAL_CALL getMinimumValue( )
+ throw (::com::sun::star::uno::RuntimeException);
+};
+
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/access/acccontext.cxx b/sw/source/core/access/acccontext.cxx
new file mode 100644
index 000000000000..f8820f56039a
--- /dev/null
+++ b/sw/source/core/access/acccontext.cxx
@@ -0,0 +1,1584 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+ /*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+#if (OSL_DEBUG_LEVEL > 1) && defined TEST_MIB
+ #ifndef _STRING_HXX
+ #include <tools/string.hxx>
+ #endif
+
+ #ifndef _STREAM_HXX
+ #include <tools/stream.hxx>
+ #endif
+#endif // #if (OSL_DEBUG_LEVEL > 1) && defined TEST_MIB
+#include <tools/debug.hxx>
+#include <vcl/window.hxx>
+#include <swtypes.hxx>
+
+#include <com/sun/star/accessibility/XAccessible.hpp>
+#include <com/sun/star/accessibility/XAccessibleStateSet.hpp>
+#include <com/sun/star/accessibility/AccessibleStateType.hpp>
+#include <com/sun/star/accessibility/AccessibleEventId.hpp>
+#include <osl/mutex.hxx>
+#include <vcl/svapp.hxx>
+#include <unotools/accessiblestatesethelper.hxx>
+#include <unotools/accessiblerelationsethelper.hxx>
+#include <viewsh.hxx>
+#include <crsrsh.hxx>
+#include <fesh.hxx>
+#include <txtfrm.hxx>
+#include <ndtxt.hxx>
+#include <pagefrm.hxx>
+#include <flyfrm.hxx>
+#include <dflyobj.hxx>
+#include <pam.hxx>
+#include <viewimp.hxx>
+#include <accmap.hxx>
+#include <accfrmobjslist.hxx>
+#include <acccontext.hxx>
+#include <svx/AccessibleShape.hxx>
+#include <comphelper/accessibleeventnotifier.hxx>
+#include <PostItMgr.hxx>
+
+using namespace sw::access;
+
+#if (OSL_DEBUG_LEVEL > 1) && defined TEST_MIB
+#define DBG_MSG( _msg ) \
+ lcl_SwAccessibleContext_DbgMsg( this, _msg, 0, sal_False );
+#define DBG_MSG_CD( _msg ) \
+ lcl_SwAccessibleContext_DbgMsg( this, _msg, 0, sal_True );
+#define DBG_MSG_PARAM( _msg, _param ) \
+ lcl_SwAccessibleContext_DbgMsg( this, _msg, _param, sal_False );
+#define DBG_MSG_THIS_PARAM( _msg, _this, _param ) \
+ lcl_SwAccessibleContext_DbgMsg( _this, _msg, _param, sal_False );
+
+void lcl_SwAccessibleContext_DbgMsg( SwAccessibleContext *pThisAcc,
+ const char *pMsg,
+ SwAccessibleContext *pChildAcc,
+ sal_Bool bConstrDestr );
+#else
+#define DBG_MSG( _msg )
+#define DBG_MSG_PARAM( _msg, _param )
+#define DBG_MSG_THIS_PARAM( _msg, _this, _param )
+#define DBG_MSG_CD( _msg )
+#endif
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::accessibility;
+using ::rtl::OUString;
+
+void SwAccessibleContext::InitStates()
+{
+ bIsShowingState = GetMap() ? IsShowing( *(GetMap()) ) : sal_False;
+
+ ViewShell *pVSh = GetMap()->GetShell();
+ bIsEditableState = pVSh && IsEditable( pVSh );
+ bIsOpaqueState = pVSh && IsOpaque( pVSh );
+ bIsDefuncState = sal_False;
+}
+
+void SwAccessibleContext::SetParent( SwAccessibleContext *pParent )
+{
+ osl::MutexGuard aGuard( aMutex );
+
+ uno::Reference < XAccessible > xParent( pParent );
+ xWeakParent = xParent;
+}
+
+uno::Reference< XAccessible > SwAccessibleContext::GetWeakParent() const
+{
+ osl::MutexGuard aGuard( aMutex );
+
+ uno::Reference< XAccessible > xParent( xWeakParent );
+ return xParent;
+}
+
+Window *SwAccessibleContext::GetWindow()
+{
+ Window *pWin = 0;
+
+ if( GetMap() )
+ {
+ const ViewShell *pVSh = GetMap()->GetShell();
+ OSL_ENSURE( pVSh, "no view shell" );
+ if( pVSh )
+ pWin = pVSh->GetWin();
+
+ OSL_ENSURE( pWin, "no window" );
+ }
+
+ return pWin;
+}
+
+// get ViewShell from accessibility map, and cast to cursor shell
+SwCrsrShell* SwAccessibleContext::GetCrsrShell()
+{
+ SwCrsrShell* pCrsrShell;
+ ViewShell* pViewShell = GetMap() ? GetMap()->GetShell() : 0;
+ OSL_ENSURE( pViewShell, "no view shell" );
+ if( pViewShell && pViewShell->ISA( SwCrsrShell ) )
+ pCrsrShell = static_cast<SwCrsrShell*>( pViewShell );
+ else
+ pCrsrShell = NULL;
+
+ return pCrsrShell;
+}
+
+const SwCrsrShell* SwAccessibleContext::GetCrsrShell() const
+{
+ // just like non-const GetCrsrShell
+ const SwCrsrShell* pCrsrShell;
+ const ViewShell* pViewShell = GetMap() ? GetMap()->GetShell() : 0;
+ OSL_ENSURE( pViewShell, "no view shell" );
+ if( pViewShell && pViewShell->ISA( SwCrsrShell ) )
+ pCrsrShell = static_cast<const SwCrsrShell*>( pViewShell );
+ else
+ pCrsrShell = NULL;
+
+ return pCrsrShell;
+}
+
+
+enum Action { NONE, SCROLLED, SCROLLED_WITHIN,
+ SCROLLED_IN, SCROLLED_OUT };
+
+void SwAccessibleContext::ChildrenScrolled( const SwFrm *pFrm,
+ const SwRect& rOldVisArea )
+{
+ const SwRect& rNewVisArea = GetVisArea();
+ const bool bVisibleChildrenOnly = SwAccessibleChild( pFrm ).IsVisibleChildrenOnly();
+
+ const SwAccessibleChildSList aList( *pFrm, *(GetMap()) );
+ SwAccessibleChildSList::const_iterator aIter( aList.begin() );
+ while( aIter != aList.end() )
+ {
+ const SwAccessibleChild& rLower = *aIter;
+ const SwRect aBox( rLower.GetBox( *(GetMap()) ) );
+ if( rLower.IsAccessible( GetShell()->IsPreView() ) )
+ {
+ Action eAction = NONE;
+ if( aBox.IsOver( rNewVisArea ) )
+ {
+ if( aBox.IsOver( rOldVisArea ) )
+ {
+ eAction = SCROLLED_WITHIN;
+ }
+ else
+ {
+ if ( bVisibleChildrenOnly &&
+ !rLower.AlwaysIncludeAsChild() )
+ {
+ eAction = SCROLLED_IN;
+ }
+ else
+ {
+ eAction = SCROLLED;
+ }
+ }
+ }
+ else if( aBox.IsOver( rOldVisArea ) )
+ {
+ if ( bVisibleChildrenOnly &&
+ !rLower.AlwaysIncludeAsChild() )
+ {
+ eAction = SCROLLED_OUT;
+ }
+ else
+ {
+ eAction = SCROLLED;
+ }
+ }
+ else if( !bVisibleChildrenOnly ||
+ rLower.AlwaysIncludeAsChild() )
+ {
+ // This wouldn't be required if the SwAccessibleFrame,
+ // wouldn't know about the vis area.
+ eAction = SCROLLED;
+ }
+ if( NONE != eAction )
+ {
+ if ( rLower.GetSwFrm() )
+ {
+ OSL_ENSURE( !rLower.AlwaysIncludeAsChild(),
+ "<SwAccessibleContext::ChildrenScrolled(..)> - always included child not considered!" );
+ const SwFrm* pLower( rLower.GetSwFrm() );
+ ::rtl::Reference< SwAccessibleContext > xAccImpl =
+ GetMap()->GetContextImpl( pLower, SCROLLED_OUT == eAction ||
+ SCROLLED_IN == eAction );
+ if( xAccImpl.is() )
+ {
+ switch( eAction )
+ {
+ case SCROLLED:
+ xAccImpl->Scrolled( rOldVisArea );
+ break;
+ case SCROLLED_WITHIN:
+ xAccImpl->ScrolledWithin( rOldVisArea );
+ break;
+ case SCROLLED_IN:
+ xAccImpl->ScrolledIn();
+ break;
+ case SCROLLED_OUT:
+ xAccImpl->ScrolledOut( rOldVisArea );
+ break;
+ case NONE:
+ break;
+ }
+ }
+ else
+ {
+ ChildrenScrolled( pLower, rOldVisArea );
+ }
+ }
+ else if ( rLower.GetDrawObject() )
+ {
+ OSL_ENSURE( !rLower.AlwaysIncludeAsChild(),
+ "<SwAccessibleContext::ChildrenScrolled(..)> - always included child not considered!" );
+ ::rtl::Reference< ::accessibility::AccessibleShape > xAccImpl =
+ GetMap()->GetContextImpl( rLower.GetDrawObject(),
+ this,
+ SCROLLED_OUT == eAction ||
+ SCROLLED_IN == eAction );
+ if( xAccImpl.is() )
+ {
+ switch( eAction )
+ {
+ case SCROLLED:
+ case SCROLLED_WITHIN:
+ xAccImpl->ViewForwarderChanged(
+ ::accessibility::IAccessibleViewForwarderListener::VISIBLE_AREA,
+ GetMap() );
+ break;
+ case SCROLLED_IN:
+ ScrolledInShape( rLower.GetDrawObject(),
+ xAccImpl.get() );
+ break;
+ case SCROLLED_OUT:
+ {
+ xAccImpl->ViewForwarderChanged(
+ ::accessibility::IAccessibleViewForwarderListener::VISIBLE_AREA,
+ GetMap() );
+ DisposeShape( rLower.GetDrawObject(),
+ xAccImpl.get() );
+ }
+ break;
+ case NONE:
+ break;
+ }
+ }
+ }
+ else if ( rLower.GetWindow() )
+ {
+ // nothing to do - as such children are always included as children.
+ OSL_ENSURE( rLower.AlwaysIncludeAsChild(),
+ "<SwAccessibleContext::ChildrenScrolled(..)> - not always included child not considered!" );
+ }
+ }
+ }
+ else if ( rLower.GetSwFrm() &&
+ ( !bVisibleChildrenOnly ||
+ aBox.IsOver( rOldVisArea ) ||
+ aBox.IsOver( rNewVisArea ) ) )
+ {
+ // There are no unaccessible SdrObjects that need to be notified
+ ChildrenScrolled( rLower.GetSwFrm(), rOldVisArea );
+ }
+ ++aIter;
+ }
+}
+
+void SwAccessibleContext::Scrolled( const SwRect& rOldVisArea )
+{
+ SetVisArea( GetMap()->GetVisArea() );
+
+ ChildrenScrolled( GetFrm(), rOldVisArea );
+
+ sal_Bool bIsOldShowingState;
+ sal_Bool bIsNewShowingState = IsShowing( *(GetMap()) );
+ {
+ osl::MutexGuard aGuard( aMutex );
+ bIsOldShowingState = bIsShowingState;
+ bIsShowingState = bIsNewShowingState;
+ }
+
+ if( bIsOldShowingState != bIsNewShowingState )
+ FireStateChangedEvent( AccessibleStateType::SHOWING,
+ bIsNewShowingState );
+}
+
+void SwAccessibleContext::ScrolledWithin( const SwRect& rOldVisArea )
+{
+ SetVisArea( GetMap()->GetVisArea() );
+
+ ChildrenScrolled( GetFrm(), rOldVisArea );
+
+ FireVisibleDataEvent();
+}
+
+void SwAccessibleContext::ScrolledIn()
+{
+ // This accessible should be freshly created, because it
+ // was not visisble before. Therefor, its vis area must already
+ // reflect the scrolling.
+ OSL_ENSURE( GetVisArea() == GetMap()->GetVisArea(),
+ "Vis area of child is wrong. Did it exist already?" );
+
+ // Send child event at parent. That's all we have to do here.
+ const SwFrm* pParent = GetParent();
+ ::rtl::Reference< SwAccessibleContext > xParentImpl(
+ GetMap()->GetContextImpl( pParent, sal_False ) );
+ uno::Reference < XAccessibleContext > xThis( this );
+ if( xParentImpl.is() )
+ {
+ SetParent( xParentImpl.get() );
+
+ AccessibleEventObject aEvent;
+ aEvent.EventId = AccessibleEventId::CHILD;
+ aEvent.NewValue <<= xThis;
+
+ xParentImpl->FireAccessibleEvent( aEvent );
+ DBG_MSG_PARAM( "AccessibleChild (added)", xChildImpl.get() );
+
+ if( HasCursor() )
+ {
+ Window *pWin = GetWindow();
+ if( pWin && pWin->HasFocus() )
+ {
+ FireStateChangedEvent( AccessibleStateType::FOCUSED, sal_True );
+ }
+ }
+
+ }
+}
+
+void SwAccessibleContext::ScrolledOut( const SwRect& rOldVisArea )
+{
+ SetVisArea( GetMap()->GetVisArea() );
+
+ // First of all, update the children. That's required to dispose
+ // all children that are existing only if they are visible. They
+ // are not disposed by the recusive Dispose call that follows later on,
+ // because this call will only dispose children that are in the
+ // new vis area. The children we want to dispode however are in the
+ // old vis area all.
+ ChildrenScrolled( GetFrm(), rOldVisArea );
+
+ // Broadcast a state changed event for the showing state.
+ // It might be that the child is freshly created just to send
+ // the child event. In this case no listener will exist.
+ FireStateChangedEvent( AccessibleStateType::SHOWING, sal_False );
+
+ // We now dispose the frame
+ Dispose( sal_True );
+}
+
+// #i27301# - use new type definition for <_nStates>
+void SwAccessibleContext::InvalidateChildrenStates( const SwFrm* _pFrm,
+ tAccessibleStates _nStates )
+{
+ const SwAccessibleChildSList aVisList( GetVisArea(), *_pFrm, *(GetMap()) );
+
+ SwAccessibleChildSList::const_iterator aIter( aVisList.begin() );
+ while( aIter != aVisList.end() )
+ {
+ const SwAccessibleChild& rLower = *aIter;
+ const SwFrm* pLower = rLower.GetSwFrm();
+ if( pLower )
+ {
+ ::rtl::Reference< SwAccessibleContext > xAccImpl;
+ if( rLower.IsAccessible( GetShell()->IsPreView() ) )
+ xAccImpl = GetMap()->GetContextImpl( pLower, sal_False );
+ if( xAccImpl.is() )
+ xAccImpl->InvalidateStates( _nStates );
+ else
+ InvalidateChildrenStates( pLower, _nStates );
+ }
+ else if ( rLower.GetDrawObject() )
+ {
+ // TODO: SdrObjects
+ }
+ else if ( rLower.GetWindow() )
+ {
+ // nothing to do ?
+ }
+
+ ++aIter;
+ }
+}
+// <--
+
+void SwAccessibleContext::DisposeChildren( const SwFrm *pFrm,
+ sal_Bool bRecursive )
+{
+ const SwAccessibleChildSList aVisList( GetVisArea(), *pFrm, *(GetMap()) );
+ SwAccessibleChildSList::const_iterator aIter( aVisList.begin() );
+ while( aIter != aVisList.end() )
+ {
+ const SwAccessibleChild& rLower = *aIter;
+ const SwFrm* pLower = rLower.GetSwFrm();
+ if( pLower )
+ {
+ ::rtl::Reference< SwAccessibleContext > xAccImpl;
+ if( rLower.IsAccessible( GetShell()->IsPreView() ) )
+ xAccImpl = GetMap()->GetContextImpl( pLower, sal_False );
+ if( xAccImpl.is() )
+ xAccImpl->Dispose( bRecursive );
+ else if( bRecursive )
+ DisposeChildren( pLower, bRecursive );
+ }
+ else if ( rLower.GetDrawObject() )
+ {
+ ::rtl::Reference< ::accessibility::AccessibleShape > xAccImpl(
+ GetMap()->GetContextImpl( rLower.GetDrawObject(),
+ this, sal_False ) );
+ if( xAccImpl.is() )
+ DisposeShape( rLower.GetDrawObject(), xAccImpl.get() );
+ }
+ else if ( rLower.GetWindow() )
+ {
+ DisposeChild( rLower, sal_False );
+ }
+ ++aIter;
+ }
+}
+
+void SwAccessibleContext::_InvalidateContent( sal_Bool )
+{
+}
+
+void SwAccessibleContext::_InvalidateCursorPos()
+{
+}
+
+void SwAccessibleContext::_InvalidateFocus()
+{
+}
+
+void SwAccessibleContext::FireAccessibleEvent( AccessibleEventObject& rEvent )
+{
+ OSL_ENSURE( GetFrm(), "fire event for diposed frame?" );
+ if( !GetFrm() )
+ return;
+
+ if( !rEvent.Source.is() )
+ {
+ uno::Reference < XAccessibleContext > xThis( this );
+ rEvent.Source = xThis;
+ }
+
+ if (nClientId)
+ comphelper::AccessibleEventNotifier::addEvent( nClientId, rEvent );
+}
+
+void SwAccessibleContext::FireVisibleDataEvent()
+{
+ AccessibleEventObject aEvent;
+ aEvent.EventId = AccessibleEventId::VISIBLE_DATA_CHANGED;
+
+ FireAccessibleEvent( aEvent );
+ DBG_MSG( "AccessibleVisibleData" )
+}
+
+void SwAccessibleContext::FireStateChangedEvent( sal_Int16 nState,
+ sal_Bool bNewState )
+{
+ AccessibleEventObject aEvent;
+
+ aEvent.EventId = AccessibleEventId::STATE_CHANGED;
+ if( bNewState )
+ aEvent.NewValue <<= nState;
+ else
+ aEvent.OldValue <<= nState;
+
+ FireAccessibleEvent( aEvent );
+ DBG_MSG( "StateChanged" )
+}
+
+void SwAccessibleContext::GetStates(
+ ::utl::AccessibleStateSetHelper& rStateSet )
+{
+ SolarMutexGuard aGuard;
+
+ // SHOWING
+ if( bIsShowingState )
+ rStateSet.AddState( AccessibleStateType::SHOWING );
+
+ // EDITABLE
+ if( bIsEditableState )
+ rStateSet.AddState( AccessibleStateType::EDITABLE );
+
+ // ENABLED
+ rStateSet.AddState( AccessibleStateType::ENABLED );
+
+ // OPAQUE
+ if( bIsOpaqueState )
+ rStateSet.AddState( AccessibleStateType::OPAQUE );
+
+ // VISIBLE
+ rStateSet.AddState( AccessibleStateType::VISIBLE );
+
+ if( bIsDefuncState )
+ rStateSet.AddState( AccessibleStateType::DEFUNC );
+}
+
+sal_Bool SwAccessibleContext::IsEditableState()
+{
+ sal_Bool bRet;
+ {
+ osl::MutexGuard aGuard( aMutex );
+ bRet = bIsEditableState;
+ }
+
+ return bRet;
+}
+
+SwAccessibleContext::SwAccessibleContext( SwAccessibleMap *pM,
+ sal_Int16 nR,
+ const SwFrm *pF )
+ : SwAccessibleFrame( pM->GetVisArea().SVRect(), pF,
+ pM->GetShell()->IsPreView() )
+ , pMap( pM )
+ , nClientId(0)
+ , nRole( nR )
+ , bDisposing( sal_False )
+ , bRegisteredAtAccessibleMap( true )
+{
+ InitStates();
+ DBG_MSG_CD( "constructed" )
+}
+
+SwAccessibleContext::~SwAccessibleContext()
+{
+ SolarMutexGuard aGuard;
+
+ DBG_MSG_CD( "destructed" )
+ RemoveFrmFromAccessibleMap();
+}
+
+uno::Reference< XAccessibleContext > SAL_CALL
+ SwAccessibleContext::getAccessibleContext( void )
+ throw (uno::RuntimeException)
+{
+ uno::Reference < XAccessibleContext > xRet( this );
+ return xRet;
+}
+
+sal_Int32 SAL_CALL SwAccessibleContext::getAccessibleChildCount( void )
+ throw (uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+
+ CHECK_FOR_DEFUNC( XAccessibleContext )
+
+ return bDisposing ? 0 : GetChildCount( *(GetMap()) );
+}
+
+uno::Reference< XAccessible> SAL_CALL
+ SwAccessibleContext::getAccessibleChild( sal_Int32 nIndex )
+ throw (uno::RuntimeException, lang::IndexOutOfBoundsException)
+{
+ SolarMutexGuard aGuard;
+
+ CHECK_FOR_DEFUNC( XAccessibleContext )
+
+ const SwAccessibleChild aChild( GetChild( *(GetMap()), nIndex ) );
+ if( !aChild.IsValid() )
+ {
+ uno::Reference < XAccessibleContext > xThis( this );
+ lang::IndexOutOfBoundsException aExcept(
+ OUString( RTL_CONSTASCII_USTRINGPARAM("index out of bounds") ),
+ xThis );
+ throw aExcept;
+ }
+
+ uno::Reference< XAccessible > xChild;
+ if( aChild.GetSwFrm() )
+ {
+ ::rtl::Reference < SwAccessibleContext > xChildImpl(
+ GetMap()->GetContextImpl( aChild.GetSwFrm(), !bDisposing ) );
+ if( xChildImpl.is() )
+ {
+ xChildImpl->SetParent( this );
+ xChild = xChildImpl.get();
+ }
+ }
+ else if ( aChild.GetDrawObject() )
+ {
+ ::rtl::Reference < ::accessibility::AccessibleShape > xChildImpl(
+ GetMap()->GetContextImpl( aChild.GetDrawObject(),
+ this, !bDisposing ) );
+ if( xChildImpl.is() )
+ xChild = xChildImpl.get();
+ }
+ else if ( aChild.GetWindow() )
+ {
+ xChild = aChild.GetWindow()->GetAccessible();
+ }
+
+ return xChild;
+}
+
+uno::Reference< XAccessible> SAL_CALL SwAccessibleContext::getAccessibleParent (void)
+ throw (uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+
+ CHECK_FOR_DEFUNC( XAccessibleContext )
+
+ const SwFrm *pUpper = GetParent();
+ OSL_ENSURE( pUpper != 0 || bDisposing, "no upper found" );
+
+ uno::Reference< XAccessible > xAcc;
+ if( pUpper )
+ xAcc = GetMap()->GetContext( pUpper, !bDisposing );
+
+ OSL_ENSURE( xAcc.is() || bDisposing, "no parent found" );
+
+ // Remember the parent as weak ref.
+ {
+ osl::MutexGuard aWeakParentGuard( aMutex );
+ xWeakParent = xAcc;
+ }
+
+ return xAcc;
+}
+
+sal_Int32 SAL_CALL SwAccessibleContext::getAccessibleIndexInParent (void)
+ throw (uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+
+ CHECK_FOR_DEFUNC( XAccessibleContext )
+
+ const SwFrm *pUpper = GetParent();
+ OSL_ENSURE( pUpper != 0 || bDisposing, "no upper found" );
+
+ sal_Int32 nIndex = -1;
+ if( pUpper )
+ {
+ ::rtl::Reference < SwAccessibleContext > xAccImpl(
+ GetMap()->GetContextImpl( pUpper, !bDisposing ) );
+ OSL_ENSURE( xAccImpl.is() || bDisposing, "no parent found" );
+ if( xAccImpl.is() )
+ nIndex = xAccImpl->GetChildIndex( *(GetMap()), SwAccessibleChild(GetFrm()) );
+ }
+
+ return nIndex;
+}
+
+sal_Int16 SAL_CALL SwAccessibleContext::getAccessibleRole (void)
+ throw (uno::RuntimeException)
+{
+ return nRole;
+}
+
+OUString SAL_CALL SwAccessibleContext::getAccessibleDescription (void)
+ throw (uno::RuntimeException)
+{
+ OSL_ENSURE( !this, "description needs to be overloaded" );
+ THROW_RUNTIME_EXCEPTION( XAccessibleContext, "internal error (method must be overloaded)" );
+}
+
+OUString SAL_CALL SwAccessibleContext::getAccessibleName (void)
+ throw (uno::RuntimeException)
+{
+ return sName;
+}
+
+uno::Reference< XAccessibleRelationSet> SAL_CALL
+ SwAccessibleContext::getAccessibleRelationSet (void)
+ throw (uno::RuntimeException)
+{
+ // by default there are no relations
+ uno::Reference< XAccessibleRelationSet> xRet( new utl::AccessibleRelationSetHelper() );
+ return xRet;
+}
+
+uno::Reference<XAccessibleStateSet> SAL_CALL
+ SwAccessibleContext::getAccessibleStateSet (void)
+ throw (uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+
+ CHECK_FOR_DEFUNC( XAccessibleContext )
+
+ ::utl::AccessibleStateSetHelper *pStateSet =
+ new ::utl::AccessibleStateSetHelper;
+
+ uno::Reference<XAccessibleStateSet> xStateSet( pStateSet );
+ GetStates( *pStateSet );
+
+ return xStateSet;
+}
+
+lang::Locale SAL_CALL SwAccessibleContext::getLocale (void)
+ throw (IllegalAccessibleComponentStateException, uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+
+ lang::Locale aLoc( Application::GetSettings().GetLocale() );
+ return aLoc;
+}
+
+void SAL_CALL SwAccessibleContext::addEventListener(
+ const uno::Reference< XAccessibleEventListener >& xListener )
+ throw (uno::RuntimeException)
+{
+ DBG_MSG( "accessible event listener added" )
+
+ if (xListener.is())
+ {
+ SolarMutexGuard aGuard;
+ if (!nClientId)
+ nClientId = comphelper::AccessibleEventNotifier::registerClient( );
+ comphelper::AccessibleEventNotifier::addEventListener( nClientId, xListener );
+ }
+}
+
+void SAL_CALL SwAccessibleContext::removeEventListener(
+ const uno::Reference< XAccessibleEventListener >& xListener )
+ throw (uno::RuntimeException)
+{
+ DBG_MSG( "accessible event listener removed" )
+
+ if (xListener.is())
+ {
+ SolarMutexGuard aGuard;
+ sal_Int32 nListenerCount = comphelper::AccessibleEventNotifier::removeEventListener( nClientId, xListener );
+ if ( !nListenerCount )
+ {
+ // no listeners anymore
+ // -> revoke ourself. This may lead to the notifier thread dying (if we were the last client),
+ // and at least to us not firing any events anymore, in case somebody calls
+ // NotifyAccessibleEvent, again
+ comphelper::AccessibleEventNotifier::revokeClient( nClientId );
+ nClientId = 0;
+ }
+ }
+}
+
+static sal_Bool lcl_PointInRectangle(const awt::Point & aPoint,
+ const awt::Rectangle & aRect)
+{
+ long nDiffX = aPoint.X - aRect.X;
+ long nDiffY = aPoint.Y - aRect.Y;
+
+ return
+ nDiffX >= 0 && nDiffX < aRect.Width && nDiffY >= 0 &&
+ nDiffY < aRect.Height;
+
+}
+
+sal_Bool SAL_CALL SwAccessibleContext::containsPoint(
+ const awt::Point& aPoint )
+ throw (uno::RuntimeException)
+{
+ awt::Rectangle aPixBounds = getBoundsImpl(sal_True);
+ aPixBounds.X = 0;
+ aPixBounds.Y = 0;
+
+ return lcl_PointInRectangle(aPoint, aPixBounds);
+}
+
+uno::Reference< XAccessible > SAL_CALL SwAccessibleContext::getAccessibleAtPoint(
+ const awt::Point& aPoint )
+ throw (uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+
+ CHECK_FOR_DEFUNC( XAccessibleComponent )
+
+ uno::Reference< XAccessible > xAcc;
+
+ Window *pWin = GetWindow();
+ CHECK_FOR_WINDOW( XAccessibleComponent, pWin )
+
+ Point aPixPoint( aPoint.X, aPoint.Y ); // px rel to parent
+ if( !GetFrm()->IsRootFrm() )
+ {
+ SwRect aLogBounds( GetBounds( *(GetMap()), GetFrm() ) ); // twip rel to doc root
+ Point aPixPos( GetMap()->CoreToPixel( aLogBounds.SVRect() ).TopLeft() );
+ aPixPoint.X() += aPixPos.X();
+ aPixPoint.Y() += aPixPos.Y();
+ }
+
+ const SwAccessibleChild aChild( GetChildAtPixel( aPixPoint, *(GetMap()) ) );
+ if( aChild.GetSwFrm() )
+ {
+ xAcc = GetMap()->GetContext( aChild.GetSwFrm() );
+ }
+ else if( aChild.GetDrawObject() )
+ {
+ xAcc = GetMap()->GetContext( aChild.GetDrawObject(), this );
+ }
+ else if ( aChild.GetWindow() )
+ {
+ xAcc = aChild.GetWindow()->GetAccessible();
+ }
+
+ return xAcc;
+}
+
+
+/**
+ Get bounding box.
+
+ There are two modes.
+
+ - realative
+
+ Return bounding box relative to parent if parent is no root
+ frame. Otherwise return the absolute bounding box.
+
+ - absolute
+
+ Return the absolute bounding box.
+
+ @param bRelative
+ true: Use relative mode.
+ false: Use absolute mode.
+*/
+awt::Rectangle SAL_CALL SwAccessibleContext::getBoundsImpl(sal_Bool bRelative)
+ throw (uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+
+ CHECK_FOR_DEFUNC( XAccessibleComponent )
+
+ const SwFrm *pParent = GetParent();
+ OSL_ENSURE( pParent, "no Parent found" );
+ Window *pWin = GetWindow();
+
+ CHECK_FOR_WINDOW( XAccessibleComponent, pWin && pParent )
+
+ SwRect aLogBounds( GetBounds( *(GetMap()), GetFrm() ) ); // twip rel to doc root
+ Rectangle aPixBounds( 0, 0, 0, 0 );
+ if( GetFrm()->IsPageFrm() &&
+ static_cast < const SwPageFrm * >( GetFrm() )->IsEmptyPage() )
+ {
+ OSL_ENSURE( GetShell()->IsPreView(), "empty page accessible?" );
+ if( GetShell()->IsPreView() )
+ {
+ // adjust method call <GetMap()->GetPreViewPageSize()>
+ sal_uInt16 nPageNum =
+ static_cast < const SwPageFrm * >( GetFrm() )->GetPhyPageNum();
+ aLogBounds.SSize( GetMap()->GetPreViewPageSize( nPageNum ) );
+ }
+ }
+ if( !aLogBounds.IsEmpty() )
+ {
+ aPixBounds = GetMap()->CoreToPixel( aLogBounds.SVRect() );
+ if( !pParent->IsRootFrm() && bRelative)
+ {
+ SwRect aParentLogBounds( GetBounds( *(GetMap()), pParent ) ); // twip rel to doc root
+ Point aParentPixPos( GetMap()->CoreToPixel( aParentLogBounds.SVRect() ).TopLeft() );
+ aPixBounds.Move( -aParentPixPos.X(), -aParentPixPos.Y() );
+ }
+ }
+
+ awt::Rectangle aBox( aPixBounds.Left(), aPixBounds.Top(),
+ aPixBounds.GetWidth(), aPixBounds.GetHeight() );
+
+ return aBox;
+}
+
+
+awt::Rectangle SAL_CALL SwAccessibleContext::getBounds()
+ throw (uno::RuntimeException)
+{
+ return getBoundsImpl(sal_True);
+}
+
+awt::Point SAL_CALL SwAccessibleContext::getLocation()
+ throw (uno::RuntimeException)
+{
+ awt::Rectangle aRect = getBoundsImpl(sal_True);
+ awt::Point aPoint(aRect.X, aRect.Y);
+
+ return aPoint;
+}
+
+
+
+awt::Point SAL_CALL SwAccessibleContext::getLocationOnScreen()
+ throw (uno::RuntimeException)
+{
+ awt::Rectangle aRect = getBoundsImpl(sal_False);
+
+ Point aPixPos(aRect.X, aRect.Y);
+
+ /* getBoundsImpl already checked that GetWindow returns valid pointer. */
+ aPixPos = GetWindow()->OutputToAbsoluteScreenPixel(aPixPos);
+ awt::Point aPoint(aPixPos.X(), aPixPos.Y());
+
+ return aPoint;
+}
+
+
+awt::Size SAL_CALL SwAccessibleContext::getSize()
+ throw (uno::RuntimeException)
+{
+ awt::Rectangle aRect = getBoundsImpl(sal_False);
+ awt::Size aSize( aRect.Width, aRect.Height );
+
+ return aSize;
+}
+
+void SAL_CALL SwAccessibleContext::grabFocus()
+ throw (uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+
+ CHECK_FOR_DEFUNC( XAccessibleContext );
+
+ if( GetFrm()->IsFlyFrm() )
+ {
+ const SdrObject *pObj =
+ static_cast < const SwFlyFrm * >( GetFrm() )->GetVirtDrawObj();
+ if( pObj )
+ Select( const_cast < SdrObject * >( pObj ), sal_False );
+ }
+ else
+ {
+ const SwCntntFrm *pCFrm = 0;
+ if( GetFrm()->IsCntntFrm() )
+ pCFrm = static_cast< const SwCntntFrm * >( GetFrm() );
+ else if( GetFrm()->IsLayoutFrm() )
+ pCFrm = static_cast< const SwLayoutFrm * >( GetFrm() )->ContainsCntnt();
+
+ if( pCFrm && pCFrm->IsTxtFrm() )
+ {
+ const SwTxtFrm *pTxtFrm = static_cast< const SwTxtFrm * >( pCFrm );
+ const SwTxtNode *pTxtNd = pTxtFrm->GetTxtNode();
+ if( pTxtNd )
+ {
+ // create pam for selection
+ SwIndex aIndex( const_cast< SwTxtNode * >( pTxtNd ),
+ pTxtFrm->GetOfst() );
+ SwPosition aStartPos( *pTxtNd, aIndex );
+ SwPaM aPaM( aStartPos );
+
+ // set PaM at cursor shell
+ Select( aPaM );
+ }
+ }
+ }
+}
+
+
+uno::Any SAL_CALL SwAccessibleContext::getAccessibleKeyBinding()
+ throw (uno::RuntimeException)
+{
+ // There are no key bindings
+ return uno::Any();
+}
+
+sal_Int32 SAL_CALL SwAccessibleContext::getForeground()
+ throw (uno::RuntimeException)
+{
+ return 0;
+}
+
+sal_Int32 SAL_CALL SwAccessibleContext::getBackground()
+ throw (uno::RuntimeException)
+{
+ return 0xffffff;
+}
+
+
+OUString SAL_CALL SwAccessibleContext::getImplementationName()
+ throw( uno::RuntimeException )
+{
+ OSL_ENSURE( !this, "implementation name needs to be overloaded" );
+
+ THROW_RUNTIME_EXCEPTION( lang::XServiceInfo, "implementation name needs to be overloaded" )
+}
+
+sal_Bool SAL_CALL
+ SwAccessibleContext::supportsService (const ::rtl::OUString& )
+ throw (uno::RuntimeException)
+{
+ OSL_ENSURE( !this, "supports service needs to be overloaded" );
+ THROW_RUNTIME_EXCEPTION( lang::XServiceInfo, "supports service needs to be overloaded" )
+}
+
+uno::Sequence< OUString > SAL_CALL SwAccessibleContext::getSupportedServiceNames()
+ throw( uno::RuntimeException )
+{
+ OSL_ENSURE( !this, "supported services names needs to be overloaded" );
+ THROW_RUNTIME_EXCEPTION( lang::XServiceInfo, "supported services needs to be overloaded" )
+}
+
+void SwAccessibleContext::DisposeShape( const SdrObject *pObj,
+ ::accessibility::AccessibleShape *pAccImpl )
+{
+ ::rtl::Reference< ::accessibility::AccessibleShape > xAccImpl( pAccImpl );
+ if( !xAccImpl.is() )
+ xAccImpl = GetMap()->GetContextImpl( pObj, this, sal_True );
+
+ AccessibleEventObject aEvent;
+ aEvent.EventId = AccessibleEventId::CHILD;
+ uno::Reference< XAccessible > xAcc( xAccImpl.get() );
+ aEvent.OldValue <<= xAcc;
+ FireAccessibleEvent( aEvent );
+
+ GetMap()->RemoveContext( pObj );
+ xAccImpl->dispose();
+}
+
+void SwAccessibleContext::ScrolledInShape( const SdrObject* ,
+ ::accessibility::AccessibleShape *pAccImpl )
+{
+ AccessibleEventObject aEvent;
+ aEvent.EventId = AccessibleEventId::CHILD;
+ uno::Reference< XAccessible > xAcc( pAccImpl );
+ aEvent.NewValue <<= xAcc;
+ FireAccessibleEvent( aEvent );
+
+ if( pAccImpl->GetState( AccessibleStateType::FOCUSED ) )
+ {
+ Window *pWin = GetWindow();
+ if( pWin && pWin->HasFocus() )
+ {
+ AccessibleEventObject aStateChangedEvent;
+ aStateChangedEvent.EventId = AccessibleEventId::STATE_CHANGED;
+ aStateChangedEvent.NewValue <<= AccessibleStateType::FOCUSED;
+ aStateChangedEvent.Source = xAcc;
+
+ FireAccessibleEvent( aStateChangedEvent );
+ }
+ }
+}
+
+void SwAccessibleContext::Dispose( sal_Bool bRecursive )
+{
+ SolarMutexGuard aGuard;
+
+ OSL_ENSURE( GetFrm() && GetMap(), "already disposed" );
+ OSL_ENSURE( GetMap()->GetVisArea() == GetVisArea(),
+ "invalid vis area for dispose" );
+
+ bDisposing = sal_True;
+
+ // dispose children
+ if( bRecursive )
+ DisposeChildren( GetFrm(), bRecursive );
+
+ // get parent
+ uno::Reference< XAccessible > xParent( GetWeakParent() );
+ uno::Reference < XAccessibleContext > xThis( this );
+
+ // send child event at parent
+ if( xParent.is() )
+ {
+ SwAccessibleContext *pAcc = (SwAccessibleContext *)xParent.get();
+
+ AccessibleEventObject aEvent;
+ aEvent.EventId = AccessibleEventId::CHILD;
+ aEvent.OldValue <<= xThis;
+ pAcc->FireAccessibleEvent( aEvent );
+ DBG_MSG_THIS_PARAM( "AccessibleChild (removed)", pAcc, this )
+ }
+
+ // set defunc state (its not required to broadcast a state changed
+ // event if the object is diposed afterwards)
+ {
+ osl::MutexGuard aDefuncStateGuard( aMutex );
+ bIsDefuncState = sal_True;
+ }
+
+ // broadcast dispose event
+ if ( nClientId )
+ {
+ comphelper::AccessibleEventNotifier::revokeClientNotifyDisposing( nClientId, *this );
+ nClientId = 0;
+ DBG_MSG_CD( "dispose" )
+ }
+
+ RemoveFrmFromAccessibleMap();
+ ClearFrm();
+ pMap = 0;
+
+ bDisposing = sal_False;
+}
+
+void SwAccessibleContext::DisposeChild( const SwAccessibleChild& rChildFrmOrObj,
+ sal_Bool bRecursive )
+{
+ SolarMutexGuard aGuard;
+
+ if ( IsShowing( *(GetMap()), rChildFrmOrObj ) ||
+ rChildFrmOrObj.AlwaysIncludeAsChild() ||
+ !SwAccessibleChild( GetFrm() ).IsVisibleChildrenOnly() )
+ {
+ // If the object could have existed before, than there is nothing to do,
+ // because no wrapper exists now and therefor no one is interested to
+ // get notified of the movement.
+ if( rChildFrmOrObj.GetSwFrm() )
+ {
+ ::rtl::Reference< SwAccessibleContext > xAccImpl =
+ GetMap()->GetContextImpl( rChildFrmOrObj.GetSwFrm(),
+ sal_True );
+ xAccImpl->Dispose( bRecursive );
+ }
+ else if ( rChildFrmOrObj.GetDrawObject() )
+ {
+ ::rtl::Reference< ::accessibility::AccessibleShape > xAccImpl =
+ GetMap()->GetContextImpl( rChildFrmOrObj.GetDrawObject(),
+ this, sal_True );
+ DisposeShape( rChildFrmOrObj.GetDrawObject(),
+ xAccImpl.get() );
+ }
+ else if ( rChildFrmOrObj.GetWindow() )
+ {
+ AccessibleEventObject aEvent;
+ aEvent.EventId = AccessibleEventId::CHILD;
+ uno::Reference< XAccessible > xAcc =
+ rChildFrmOrObj.GetWindow()->GetAccessible();
+ aEvent.OldValue <<= xAcc;
+ FireAccessibleEvent( aEvent );
+ }
+ }
+ else if( bRecursive && rChildFrmOrObj.GetSwFrm() )
+ DisposeChildren( rChildFrmOrObj.GetSwFrm(), bRecursive );
+}
+
+void SwAccessibleContext::InvalidatePosOrSize( const SwRect& )
+{
+ SolarMutexGuard aGuard;
+
+ OSL_ENSURE( GetFrm() && !GetFrm()->Frm().IsEmpty(), "context should have a size" );
+
+ sal_Bool bIsOldShowingState;
+ sal_Bool bIsNewShowingState = IsShowing( *(GetMap()) );
+ {
+ osl::MutexGuard aShowingStateGuard( aMutex );
+ bIsOldShowingState = bIsShowingState;
+ bIsShowingState = bIsNewShowingState;
+ }
+
+ if( bIsOldShowingState != bIsNewShowingState )
+ {
+ FireStateChangedEvent( AccessibleStateType::SHOWING,
+ bIsNewShowingState );
+ }
+ else if( bIsNewShowingState )
+ {
+ // The frame stays visible -> broadcast event
+ FireVisibleDataEvent();
+ }
+
+ if( !bIsNewShowingState &&
+ SwAccessibleChild( GetParent() ).IsVisibleChildrenOnly() )
+ {
+ // The frame is now invisible -> dispose it
+ Dispose( sal_True );
+ }
+ else
+ {
+ _InvalidateContent( sal_True );
+ }
+}
+
+void SwAccessibleContext::InvalidateChildPosOrSize(
+ const SwAccessibleChild& rChildFrmOrObj,
+ const SwRect& rOldFrm )
+{
+ SolarMutexGuard aGuard;
+
+ OSL_ENSURE( !rChildFrmOrObj.GetSwFrm() ||
+ !rChildFrmOrObj.GetSwFrm()->Frm().IsEmpty(),
+ "child context should have a size" );
+
+ if ( rChildFrmOrObj.AlwaysIncludeAsChild() )
+ {
+ // nothing to do;
+ return;
+ }
+
+ const bool bVisibleChildrenOnly = SwAccessibleChild( GetFrm() ).IsVisibleChildrenOnly();
+ const bool bNew = rOldFrm.IsEmpty() ||
+ ( rOldFrm.Left() == 0 && rOldFrm.Top() == 0 );
+ if( IsShowing( *(GetMap()), rChildFrmOrObj ) )
+ {
+ // If the object could have existed before, than there is nothing to do,
+ // because no wrapper exists now and therefor no one is interested to
+ // get notified of the movement.
+ if( bNew || (bVisibleChildrenOnly && !IsShowing( rOldFrm )) )
+ {
+ if( rChildFrmOrObj.GetSwFrm() )
+ {
+ // The frame becomes visible. A child event must be send.
+ ::rtl::Reference< SwAccessibleContext > xAccImpl =
+ GetMap()->GetContextImpl( rChildFrmOrObj.GetSwFrm(),
+ sal_True );
+ xAccImpl->ScrolledIn();
+ }
+ else if ( rChildFrmOrObj.GetDrawObject() )
+ {
+ ::rtl::Reference< ::accessibility::AccessibleShape > xAccImpl =
+ GetMap()->GetContextImpl( rChildFrmOrObj.GetDrawObject(),
+ this, sal_True );
+ // #i37790#
+ if ( xAccImpl.is() )
+ {
+ ScrolledInShape( rChildFrmOrObj.GetDrawObject(),
+ xAccImpl.get() );
+ }
+ else
+ {
+ OSL_FAIL( "<SwAccessibleContext::InvalidateChildPosOrSize(..)> - no accessible shape found." );
+ }
+ // <--
+ }
+ else if ( rChildFrmOrObj.GetWindow() )
+ {
+ AccessibleEventObject aEvent;
+ aEvent.EventId = AccessibleEventId::CHILD;
+ aEvent.NewValue <<= (rChildFrmOrObj.GetWindow()->GetAccessible());
+ FireAccessibleEvent( aEvent );
+ }
+ }
+ }
+ else
+ {
+ // If the frame was visible before, than a child event for the parent
+ // needs to be send. However, there is no wrapper existing, and so
+ // no notifications for grandchildren are required. If the are
+ // grandgrandchildren, they would be notified by the layout.
+ if( bVisibleChildrenOnly &&
+ !bNew && IsShowing( rOldFrm ) )
+ {
+ if( rChildFrmOrObj.GetSwFrm() )
+ {
+ ::rtl::Reference< SwAccessibleContext > xAccImpl =
+ GetMap()->GetContextImpl( rChildFrmOrObj.GetSwFrm(),
+ sal_True );
+ xAccImpl->SetParent( this );
+ xAccImpl->Dispose( sal_True );
+ }
+ else if ( rChildFrmOrObj.GetDrawObject() )
+ {
+ ::rtl::Reference< ::accessibility::AccessibleShape > xAccImpl =
+ GetMap()->GetContextImpl( rChildFrmOrObj.GetDrawObject(),
+ this, sal_True );
+ DisposeShape( rChildFrmOrObj.GetDrawObject(),
+ xAccImpl.get() );
+ }
+ else if ( rChildFrmOrObj.GetWindow() )
+ {
+ OSL_FAIL( "<SwAccessibleContext::InvalidateChildPosOrSize(..)> - not expected to handle dispose of child of type <Window>." );
+ }
+ }
+ }
+}
+
+void SwAccessibleContext::InvalidateContent()
+{
+ SolarMutexGuard aGuard;
+
+ _InvalidateContent( sal_False );
+}
+
+void SwAccessibleContext::InvalidateCursorPos()
+{
+ SolarMutexGuard aGuard;
+
+ _InvalidateCursorPos();
+}
+
+void SwAccessibleContext::InvalidateFocus()
+{
+ SolarMutexGuard aGuard;
+
+ _InvalidateFocus();
+}
+
+// #i27301# - use new type definition for <_nStates>
+void SwAccessibleContext::InvalidateStates( tAccessibleStates _nStates )
+{
+ if( GetMap() )
+ {
+ ViewShell *pVSh = GetMap()->GetShell();
+ if( pVSh )
+ {
+ if( (_nStates & ACC_STATE_EDITABLE) != 0 )
+ {
+ sal_Bool bIsOldEditableState;
+ sal_Bool bIsNewEditableState = IsEditable( pVSh );
+ {
+ osl::MutexGuard aGuard( aMutex );
+ bIsOldEditableState = bIsEditableState;
+ bIsEditableState = bIsNewEditableState;
+ }
+
+ if( bIsOldEditableState != bIsNewEditableState )
+ FireStateChangedEvent( AccessibleStateType::EDITABLE,
+ bIsNewEditableState );
+ }
+ if( (_nStates & ACC_STATE_OPAQUE) != 0 )
+ {
+ sal_Bool bIsOldOpaqueState;
+ sal_Bool bIsNewOpaqueState = IsOpaque( pVSh );
+ {
+ osl::MutexGuard aGuard( aMutex );
+ bIsOldOpaqueState = bIsOpaqueState;
+ bIsOpaqueState = bIsNewOpaqueState;
+ }
+
+ if( bIsOldOpaqueState != bIsNewOpaqueState )
+ FireStateChangedEvent( AccessibleStateType::OPAQUE,
+ bIsNewOpaqueState );
+ }
+ }
+
+ InvalidateChildrenStates( GetFrm(), _nStates );
+ }
+}
+// <--
+
+void SwAccessibleContext::InvalidateRelation( sal_uInt16 nType )
+{
+ AccessibleEventObject aEvent;
+ aEvent.EventId = nType;
+
+ FireAccessibleEvent( aEvent );
+}
+
+/** #i27301# - text selection has changed */
+void SwAccessibleContext::InvalidateTextSelection()
+{
+ AccessibleEventObject aEvent;
+ aEvent.EventId = AccessibleEventId::TEXT_SELECTION_CHANGED;
+
+ FireAccessibleEvent( aEvent );
+}
+
+/** #i88069# - attributes has changed */
+void SwAccessibleContext::InvalidateAttr()
+{
+ AccessibleEventObject aEvent;
+ aEvent.EventId = AccessibleEventId::TEXT_ATTRIBUTE_CHANGED;
+
+ FireAccessibleEvent( aEvent );
+}
+
+sal_Bool SwAccessibleContext::HasCursor()
+{
+ return sal_False;
+}
+
+sal_Bool SwAccessibleContext::Select( SwPaM *pPaM, SdrObject *pObj,
+ sal_Bool bAdd )
+{
+ SwCrsrShell* pCrsrShell = GetCrsrShell();
+ if( !pCrsrShell )
+ return sal_False;
+
+ SwFEShell* pFEShell = pCrsrShell->ISA( SwFEShell )
+ ? static_cast<SwFEShell*>( pCrsrShell )
+ : 0;
+ // Get rid of activated OLE object
+ if( pFEShell )
+ pFEShell->FinishOLEObj();
+
+ sal_Bool bRet = sal_False;
+ if( pObj )
+ {
+ if( pFEShell )
+ {
+ Point aDummy;
+ sal_uInt8 nFlags = bAdd ? SW_ADD_SELECT : 0;
+ pFEShell->SelectObj( aDummy, nFlags, pObj );
+ bRet = sal_True;
+ }
+ }
+ else if( pPaM )
+ {
+ // Get rid of frame selection. If there is one, make text cursor
+ // visible again.
+ sal_Bool bCallShowCrsr = sal_False;
+ if( pFEShell && (pFEShell->IsFrmSelected() ||
+ pFEShell->IsObjSelected()) )
+ {
+ Point aPt( LONG_MIN, LONG_MIN );
+ pFEShell->SelectObj( aPt, 0 );
+ bCallShowCrsr = sal_True;
+ }
+ pCrsrShell->KillPams();
+ pCrsrShell->SetSelection( *pPaM );
+ if( bCallShowCrsr )
+ pCrsrShell->ShowCrsr();
+ bRet = sal_True;
+ }
+
+ return bRet;
+}
+
+OUString SwAccessibleContext::GetResource( sal_uInt16 nResId,
+ const OUString *pArg1,
+ const OUString *pArg2 )
+{
+ String sStr;
+ {
+ SolarMutexGuard aGuard;
+
+ sStr = SW_RES( nResId );
+ }
+
+ if( pArg1 )
+ {
+ sStr.SearchAndReplace( String::CreateFromAscii(
+ RTL_CONSTASCII_STRINGPARAM( "$(ARG1)" )),
+ String( *pArg1 ) );
+ }
+ if( pArg2 )
+ {
+ sStr.SearchAndReplace( String::CreateFromAscii(
+ RTL_CONSTASCII_STRINGPARAM( "$(ARG2)" )),
+ String( *pArg2 ) );
+ }
+
+ return OUString( sStr );
+}
+
+void SwAccessibleContext::RemoveFrmFromAccessibleMap()
+{
+ if( bRegisteredAtAccessibleMap && GetFrm() && GetMap() )
+ GetMap()->RemoveContext( GetFrm() );
+}
+
+bool SwAccessibleContext::HasAdditionalAccessibleChildren()
+{
+ bool bRet( false );
+
+ if ( GetFrm()->IsTxtFrm() )
+ {
+ SwPostItMgr* pPostItMgr = GetMap()->GetShell()->GetPostItMgr();
+ if ( pPostItMgr && pPostItMgr->HasNotes() && pPostItMgr->ShowNotes() )
+ {
+ bRet = pPostItMgr->HasFrmConnectedSidebarWins( *(GetFrm()) );
+ }
+ }
+
+ return bRet;
+}
+/** #i88070# - get additional accessible child by index */
+Window* SwAccessibleContext::GetAdditionalAccessibleChild( const sal_Int32 nIndex )
+{
+ Window* pAdditionalAccessibleChild( 0 );
+
+ if ( GetFrm()->IsTxtFrm() )
+ {
+ SwPostItMgr* pPostItMgr = GetMap()->GetShell()->GetPostItMgr();
+ if ( pPostItMgr && pPostItMgr->HasNotes() && pPostItMgr->ShowNotes() )
+ {
+ pAdditionalAccessibleChild =
+ pPostItMgr->GetSidebarWinForFrmByIndex( *(GetFrm()), nIndex );
+ }
+ }
+
+ return pAdditionalAccessibleChild;
+}
+
+/** #i88070# - get all additional accessible children */
+void SwAccessibleContext::GetAdditionalAccessibleChildren( std::vector< Window* >* pChildren )
+{
+ if ( GetFrm()->IsTxtFrm() )
+ {
+ SwPostItMgr* pPostItMgr = GetMap()->GetShell()->GetPostItMgr();
+ if ( pPostItMgr && pPostItMgr->HasNotes() && pPostItMgr->ShowNotes() )
+ {
+ pPostItMgr->GetAllSidebarWinForFrm( *(GetFrm()), pChildren );
+ }
+ }
+}
+
+#if (OSL_DEBUG_LEVEL > 1) && defined TEST_MIB
+void lcl_SwAccessibleContext_DbgMsg( SwAccessibleContext *pThisAcc,
+ const char *pMsg,
+ SwAccessibleContext *pChildAcc,
+ sal_Bool bConstrDestr )
+{
+ static SvFileStream aStrm( String::CreateFromAscii("j:\\acc.log"),
+ STREAM_WRITE|STREAM_TRUNC|STREAM_SHARE_DENYNONE );
+ ByteString aName( String(pThisAcc->GetName()),
+ RTL_TEXTENCODING_ISO_8859_1 );
+ if( aName.Len() )
+ {
+ aStrm << aName.GetBuffer()
+ << ": ";
+ }
+ aStrm << pMsg;
+ if( pChildAcc )
+ {
+ ByteString aChild( String(pChildAcc->GetName()),
+ RTL_TEXTENCODING_ISO_8859_1 );
+ aStrm << ": "
+ << aChild.GetBuffer();
+ }
+ aStrm << "\r\n (";
+
+ if( !bConstrDestr )
+ {
+ ByteString aDesc( String(pThisAcc->getAccessibleDescription()),
+ RTL_TEXTENCODING_ISO_8859_1 );
+ aStrm << aDesc.GetBuffer()
+ << ", ";
+ }
+
+ Rectangle aVisArea( pThisAcc->GetVisArea() );
+ aStrm << "VA: "
+ << ByteString::CreateFromInt32( aVisArea.Left() ).GetBuffer()
+ << ","
+ << ByteString::CreateFromInt32( aVisArea.Top() ).GetBuffer()
+ << ","
+ << ByteString::CreateFromInt32( aVisArea.GetWidth() ).GetBuffer()
+ << ","
+ << ByteString::CreateFromInt32( aVisArea.GetHeight() ).GetBuffer();
+
+ if( pThisAcc->GetFrm() )
+ {
+ Rectangle aBounds( pThisAcc->GetBounds( pThisAcc->GetFrm() ) );
+ aStrm << ", BB: "
+ << ByteString::CreateFromInt32( aBounds.Left() ).GetBuffer()
+ << ","
+ << ByteString::CreateFromInt32( aBounds.Top() ).GetBuffer()
+ << ","
+ << ByteString::CreateFromInt32( aBounds.GetWidth() ).GetBuffer()
+ << ","
+ << ByteString::CreateFromInt32( aBounds.GetHeight() ).GetBuffer()
+ << ")\r\n";
+ }
+
+ aStrm.Flush();
+}
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/access/acccontext.hxx b/sw/source/core/access/acccontext.hxx
new file mode 100644
index 000000000000..d9fd0e113d55
--- /dev/null
+++ b/sw/source/core/access/acccontext.hxx
@@ -0,0 +1,433 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+#ifndef _ACCBASE_HXX
+#define _ACCBASE_HXX
+#include <accframe.hxx>
+#include <accmap.hxx>
+#include <com/sun/star/accessibility/XAccessibleComponent.hpp>
+#include <com/sun/star/accessibility/XAccessibleEventBroadcaster.hpp>
+#include <com/sun/star/lang/DisposedException.hpp>
+#include <com/sun/star/lang/XServiceInfo.hpp>
+#include <cppuhelper/implbase5.hxx>
+#include <cppuhelper/interfacecontainer.hxx>
+
+class Window;
+class SwAccessibleMap;
+class SwCrsrShell;
+class SdrObject;
+class SwPaM;
+namespace utl {
+ class AccessibleStateSetHelper;
+}
+namespace accessibility {
+ class AccessibleShape;
+}
+class SwFmtFld;
+class SwAccessibleChildContainer;
+
+const sal_Char sAccessibleServiceName[] = "com.sun.star.accessibility.Accessible";
+
+class SwAccessibleContext :
+ public ::cppu::WeakImplHelper5<
+ ::com::sun::star::accessibility::XAccessible,
+ ::com::sun::star::accessibility::XAccessibleContext,
+ ::com::sun::star::accessibility::XAccessibleComponent,
+ ::com::sun::star::accessibility::XAccessibleEventBroadcaster,
+ ::com::sun::star::lang::XServiceInfo
+ >,
+ public SwAccessibleFrame
+{
+ // The implements for the XAccessibleSelection interface has been
+ // 'externalized' and wants access to the protected members like
+ // GetMap, GetChild, GetParent, and GetFrm.
+ friend class SwAccessibleSelectionHelper;
+
+
+protected:
+
+ mutable ::osl::Mutex aListenerMutex;
+ mutable ::osl::Mutex aMutex;
+
+private:
+
+ ::rtl::OUString sName; // immutable outside constructor
+
+ // The parent if it has been retrieved. This is always an
+ // SwAccessibleContext. (protected by Mutex)
+ ::com::sun::star::uno::WeakReference <
+ ::com::sun::star::accessibility::XAccessible > xWeakParent;
+
+ SwAccessibleMap *pMap; // must be protected by solar mutex
+
+ sal_uInt32 nClientId; // client id in the AccessibleEventNotifier queue
+ sal_Int16 nRole; // immutable outside constructor
+
+ // The current states (protected by mutex)
+ sal_Bool bIsShowingState : 1;
+ sal_Bool bIsEditableState : 1;
+ sal_Bool bIsOpaqueState : 1;
+ sal_Bool bIsDefuncState : 1;
+
+ // Are we currently disposing that object (protected by solar mutex)?
+ sal_Bool bDisposing : 1;
+
+ // #i85634# - boolean, indicating if the accessible context is
+ // in general registered at the accessible map.
+ bool bRegisteredAtAccessibleMap;
+
+ void InitStates();
+
+protected:
+ void SetName( const ::rtl::OUString& rName ) { sName = rName; }
+ inline sal_Int16 GetRole() const
+ {
+ return nRole;
+ }
+
+ void SetParent( SwAccessibleContext *pParent );
+ ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible> GetWeakParent() const;
+
+ sal_Bool IsDisposing() const { return bDisposing; }
+
+ Window *GetWindow();
+ SwAccessibleMap *GetMap() { return pMap; }
+ const SwAccessibleMap *GetMap() const { return pMap; }
+
+ /** convenience method to get the SwViewShell through accessibility map */
+ inline ViewShell* GetShell()
+ {
+ return GetMap()->GetShell();
+ }
+ inline const ViewShell* GetShell() const
+ {
+ return GetMap()->GetShell();
+ }
+
+ /** convenience method to get SwCrsrShell through accessibility map
+ * @returns SwCrsrShell, or NULL if none is found */
+ SwCrsrShell* GetCrsrShell();
+ const SwCrsrShell* GetCrsrShell() const;
+
+ // Notify all children that the vis araea has changed.
+ // The SwFrm might belong to the current object or to any other child or
+ // grandchild.
+ void ChildrenScrolled( const SwFrm *pFrm, const SwRect& rOldVisArea );
+
+ // The context's showing state changed. May only be called for context that
+ // exist even if they aren't visible.
+ void Scrolled( const SwRect& rOldVisArea );
+
+ // A child has been moved while setting the vis area
+ void ScrolledWithin( const SwRect& rOldVisArea );
+
+ // The has been added while setting the vis area
+ void ScrolledIn();
+
+ // The context has to be removed while setting the vis area
+ void ScrolledOut( const SwRect& rOldVisArea );
+
+ // Invalidate the states of all children of the specified SwFrm. The
+ // SwFrm might belong the the current object or to any child or grandchild!
+ // #i27301# - use new type definition for <_nStates>
+ void InvalidateChildrenStates( const SwFrm* _pFrm,
+ tAccessibleStates _nStates );
+ // <--
+
+ // Dispose children of the specified SwFrm. The SwFrm might belong to
+ // the current object or to any other child or grandchild.
+ void DisposeChildren( const SwFrm *pFrm,
+ sal_Bool bRecursive );
+
+ void DisposeShape( const SdrObject *pObj,
+ ::accessibility::AccessibleShape *pAccImpl );
+ void ScrolledInShape( const SdrObject *pObj,
+ ::accessibility::AccessibleShape *pAccImpl );
+
+ virtual void _InvalidateContent( sal_Bool bVisibleDataFired );
+
+ virtual void _InvalidateCursorPos();
+ virtual void _InvalidateFocus();
+
+public:
+
+ void FireAccessibleEvent( ::com::sun::star::accessibility::AccessibleEventObject& rEvent );
+
+protected:
+
+ // broadcast visual data event
+ void FireVisibleDataEvent();
+
+ // broadcast state change event
+ void FireStateChangedEvent( sal_Int16 nState, sal_Bool bNewState );
+
+ // Set states for getAccessibleStateSet.
+ // This base class sets DEFUNC(0/1), EDITABLE(0/1), ENABLED(1),
+ // SHOWING(0/1), OPAQUE(0/1) and VISIBLE(1).
+ virtual void GetStates( ::utl::AccessibleStateSetHelper& rStateSet );
+
+ sal_Bool IsEditableState();
+
+ virtual ::com::sun::star::awt::Rectangle SAL_CALL
+ getBoundsImpl(sal_Bool bRelative)
+ throw (::com::sun::star::uno::RuntimeException);
+
+ // #i85634#
+ inline void NotRegisteredAtAccessibleMap()
+ {
+ bRegisteredAtAccessibleMap = false;
+ }
+ void RemoveFrmFromAccessibleMap();
+
+ virtual ~SwAccessibleContext();
+
+public:
+
+ SwAccessibleContext( SwAccessibleMap *pMap, sal_Int16 nRole,
+ const SwFrm *pFrm );
+
+ //===== XAccessible =====================================================
+
+ /// Return the XAccessibleContext.
+ virtual ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessibleContext> SAL_CALL
+ getAccessibleContext (void) throw (com::sun::star::uno::RuntimeException);
+
+ //===== XAccessibleContext ==============================================
+
+ /// Return the number of currently visible children.
+ virtual sal_Int32 SAL_CALL getAccessibleChildCount (void)
+ throw (::com::sun::star::uno::RuntimeException);
+
+ /// Return the specified child or NULL if index is invalid.
+ virtual ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible> SAL_CALL
+ getAccessibleChild (sal_Int32 nIndex)
+ throw (::com::sun::star::uno::RuntimeException,
+ ::com::sun::star::lang::IndexOutOfBoundsException);
+
+ /// Return a reference to the parent.
+ virtual ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible> SAL_CALL
+ getAccessibleParent (void)
+ throw (::com::sun::star::uno::RuntimeException);
+
+ /// Return this objects index among the parents children.
+ virtual sal_Int32 SAL_CALL
+ getAccessibleIndexInParent (void)
+ throw (::com::sun::star::uno::RuntimeException);
+
+ /// Return this object's role.
+ virtual sal_Int16 SAL_CALL
+ getAccessibleRole (void)
+ throw (::com::sun::star::uno::RuntimeException);
+
+ /// Return this object's description.
+ virtual ::rtl::OUString SAL_CALL
+ getAccessibleDescription (void)
+ throw (::com::sun::star::uno::RuntimeException);
+
+ /// Return the object's current name.
+ virtual ::rtl::OUString SAL_CALL
+ getAccessibleName (void)
+ throw (::com::sun::star::uno::RuntimeException);
+
+ /// Return NULL to indicate that an empty relation set.
+ virtual ::com::sun::star::uno::Reference<
+ ::com::sun::star::accessibility::XAccessibleRelationSet> SAL_CALL
+ getAccessibleRelationSet (void)
+ throw (::com::sun::star::uno::RuntimeException);
+
+ /// Return the set of current states.
+ virtual ::com::sun::star::uno::Reference<
+ ::com::sun::star::accessibility::XAccessibleStateSet> SAL_CALL
+ getAccessibleStateSet (void)
+ throw (::com::sun::star::uno::RuntimeException);
+
+ /** Return the parents locale or throw exception if this object has no
+ parent yet/anymore.
+ */
+ virtual ::com::sun::star::lang::Locale SAL_CALL
+ getLocale (void)
+ throw (::com::sun::star::accessibility::IllegalAccessibleComponentStateException, ::com::sun::star::uno::RuntimeException);
+
+ //===== XAccessibleEventBroadcaster =====================================
+
+ virtual void SAL_CALL addEventListener(
+ const ::com::sun::star::uno::Reference<
+ ::com::sun::star::accessibility::XAccessibleEventListener >& xListener )
+ throw (::com::sun::star::uno::RuntimeException);
+ virtual void SAL_CALL removeEventListener(
+ const ::com::sun::star::uno::Reference<
+ ::com::sun::star::accessibility::XAccessibleEventListener >& xListener )
+ throw (::com::sun::star::uno::RuntimeException);
+
+ //===== XAccessibleComponent ============================================
+ virtual sal_Bool SAL_CALL containsPoint(
+ const ::com::sun::star::awt::Point& aPoint )
+ throw (::com::sun::star::uno::RuntimeException);
+
+ virtual ::com::sun::star::uno::Reference<
+ ::com::sun::star::accessibility::XAccessible > SAL_CALL getAccessibleAtPoint(
+ const ::com::sun::star::awt::Point& aPoint )
+ throw (::com::sun::star::uno::RuntimeException);
+
+ virtual ::com::sun::star::awt::Rectangle SAL_CALL getBounds()
+ throw (::com::sun::star::uno::RuntimeException);
+
+ virtual ::com::sun::star::awt::Point SAL_CALL getLocation()
+ throw (::com::sun::star::uno::RuntimeException);
+
+ virtual ::com::sun::star::awt::Point SAL_CALL getLocationOnScreen()
+ throw (::com::sun::star::uno::RuntimeException);
+
+ virtual ::com::sun::star::awt::Size SAL_CALL getSize()
+ throw (::com::sun::star::uno::RuntimeException);
+
+ virtual void SAL_CALL grabFocus()
+ throw (::com::sun::star::uno::RuntimeException);
+
+ virtual ::com::sun::star::uno::Any SAL_CALL getAccessibleKeyBinding()
+ throw (::com::sun::star::uno::RuntimeException);
+ virtual sal_Int32 SAL_CALL getForeground()
+ throw (::com::sun::star::uno::RuntimeException);
+ virtual sal_Int32 SAL_CALL getBackground()
+ throw (::com::sun::star::uno::RuntimeException);
+
+
+ //===== XServiceInfo ====================================================
+
+ /** Returns an identifier for the implementation of this object.
+ */
+ virtual ::rtl::OUString SAL_CALL
+ getImplementationName (void)
+ throw (::com::sun::star::uno::RuntimeException);
+
+ /** Return whether the specified service is supported by this class.
+ */
+ virtual sal_Bool SAL_CALL
+ supportsService (const ::rtl::OUString& sServiceName)
+ throw (::com::sun::star::uno::RuntimeException);
+
+ /** Returns a list of all supported services. In this case that is just
+ the AccessibleContext service.
+ */
+ virtual ::com::sun::star::uno::Sequence< ::rtl::OUString> SAL_CALL
+ getSupportedServiceNames (void)
+ throw (::com::sun::star::uno::RuntimeException);
+
+ //====== thread safe C++ interface ========================================
+
+ // The object is not visible an longer and should be destroyed
+ virtual void Dispose( sal_Bool bRecursive = sal_False );
+
+ // The child object is not visible an longer and should be destroyed
+ virtual void DisposeChild( const sw::access::SwAccessibleChild& rFrmOrObj, sal_Bool bRecursive );
+
+ // The object has been moved by the layout
+ virtual void InvalidatePosOrSize( const SwRect& rFrm );
+
+ // The vhild object has been moved by the layout
+ virtual void InvalidateChildPosOrSize( const sw::access::SwAccessibleChild& rFrmOrObj,
+ const SwRect& rFrm );
+
+ // The content may have changed (but it hasn't tohave changed)
+ void InvalidateContent();
+
+ // The caretPos has changed
+ void InvalidateCursorPos();
+
+ // The Focus state has changed
+ void InvalidateFocus();
+
+ // Check states
+ // #i27301# - use new type definition for <_nStates>
+ void InvalidateStates( tAccessibleStates _nStates );
+
+ // the XAccessibleRelationSet may have changed
+ void InvalidateRelation( sal_uInt16 nType );
+
+ void InvalidateTextSelection(); // #i27301# - text selection has changed
+ void InvalidateAttr(); // #i88069# - attributes has changed
+
+ bool HasAdditionalAccessibleChildren();
+
+ // #i88070# - get additional child by index
+ Window* GetAdditionalAccessibleChild( const sal_Int32 nIndex );
+
+ // #i88070# - get all additional accessible children
+ void GetAdditionalAccessibleChildren( std::vector< Window* >* pChildren );
+
+ const ::rtl::OUString& GetName() const { return sName; }
+
+ virtual sal_Bool HasCursor(); // required by map to remember that object
+
+ sal_Bool Select( SwPaM *pPaM, SdrObject *pObj, sal_Bool bAdd );
+ inline sal_Bool Select( SwPaM& rPaM )
+ {
+ return Select( &rPaM, 0, sal_False );
+ }
+ inline sal_Bool Select( SdrObject *pObj, sal_Bool bAdd )
+ {
+ return Select( 0, pObj, bAdd );
+ }
+
+ static ::rtl::OUString GetResource( sal_uInt16 nResId,
+ const ::rtl::OUString *pArg1 = 0,
+ const ::rtl::OUString *pArg2 = 0 );
+
+
+};
+
+// some heaviliy used exception support
+const sal_Char sDefunc[] = "object is defunctional";
+const sal_Char sMissingWindow[] = "window is missing";
+
+#define THROW_RUNTIME_EXCEPTION( ifc, msg ) \
+ ::com::sun::star::uno::Reference < ifc > xThis( this ); \
+ ::com::sun::star::uno::RuntimeException aExcept( \
+ ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(msg) ), xThis ); \
+ throw aExcept;
+
+#define CHECK_FOR_DEFUNC_THIS( ifc, ths ) \
+ if( !(GetFrm() && GetMap()) ) \
+ { \
+ ::com::sun::star::uno::Reference < ifc > xThis( ths ); \
+ ::com::sun::star::lang::DisposedException aExcept( \
+ ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(sDefunc) ), \
+ xThis ); \
+ throw aExcept; \
+ }
+
+#define CHECK_FOR_DEFUNC( ifc ) \
+ CHECK_FOR_DEFUNC_THIS( ifc, this )
+
+#define CHECK_FOR_WINDOW( i, w ) \
+ if( !(w) ) \
+ { \
+ THROW_RUNTIME_EXCEPTION( i, sMissingWindow ); \
+ }
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/access/accdoc.cxx b/sw/source/core/access/accdoc.cxx
new file mode 100644
index 000000000000..bad6b1b4f5ab
--- /dev/null
+++ b/sw/source/core/access/accdoc.cxx
@@ -0,0 +1,514 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+ /*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+#include <vcl/window.hxx>
+#include <rootfrm.hxx>
+
+
+#include <com/sun/star/accessibility/AccessibleRole.hpp>
+#include <com/sun/star/accessibility/AccessibleStateType.hpp>
+#include <com/sun/star/beans/XPropertyChangeListener.hpp>
+#include <com/sun/star/accessibility/AccessibleEventId.hpp>
+#include <unotools/accessiblestatesethelper.hxx>
+#include <tools/link.hxx>
+#include <sfx2/viewsh.hxx>
+#include <osl/mutex.hxx>
+#include <vcl/svapp.hxx>
+#include <viewsh.hxx>
+#include <doc.hxx>
+#include <accmap.hxx>
+#include <accdoc.hxx>
+#include "access.hrc"
+#include <pagefrm.hxx>
+
+const sal_Char sServiceName[] = "com.sun.star.text.AccessibleTextDocumentView";
+const sal_Char sImplementationName[] = "com.sun.star.comp.Writer.SwAccessibleDocumentView";
+
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::accessibility;
+using ::rtl::OUString;
+
+using lang::IndexOutOfBoundsException;
+
+
+
+//
+// SwAccessibleDocumentBase: base class for SwAccessibleDocument and
+// SwAccessiblePreview
+//
+
+SwAccessibleDocumentBase::SwAccessibleDocumentBase ( SwAccessibleMap *_pMap ) :
+ SwAccessibleContext( _pMap, AccessibleRole::DOCUMENT,
+ _pMap->GetShell()->GetLayout() ),//swmod 071107//swmod 071225
+ mxParent( _pMap->GetShell()->GetWin()->GetAccessibleParentWindow()->GetAccessible() ),
+ mpChildWin( 0 )
+{
+}
+
+SwAccessibleDocumentBase::~SwAccessibleDocumentBase()
+{
+}
+
+void SwAccessibleDocumentBase::SetVisArea()
+{
+ SolarMutexGuard aGuard;
+
+ SwRect aOldVisArea( GetVisArea() );
+ const SwRect& rNewVisArea = GetMap()->GetVisArea();
+ if( aOldVisArea != rNewVisArea )
+ {
+ SwAccessibleFrame::SetVisArea( GetMap()->GetVisArea() );
+ // #i58139# - showing state of document view needs also be updated.
+ // Thus, call method <Scrolled(..)> instead of <ChildrenScrolled(..)>
+// ChildrenScrolled( GetFrm(), aOldVisArea );
+ Scrolled( aOldVisArea );
+ }
+}
+
+void SwAccessibleDocumentBase::AddChild( Window *pWin, sal_Bool bFireEvent )
+{
+ SolarMutexGuard aGuard;
+
+ OSL_ENSURE( !mpChildWin, "only one child window is supported" );
+ if( !mpChildWin )
+ {
+ mpChildWin = pWin;
+
+ if( bFireEvent )
+ {
+ AccessibleEventObject aEvent;
+ aEvent.EventId = AccessibleEventId::CHILD;
+ aEvent.NewValue <<= mpChildWin->GetAccessible();
+ FireAccessibleEvent( aEvent );
+ }
+ }
+}
+
+void SwAccessibleDocumentBase::RemoveChild( Window *pWin )
+{
+ SolarMutexGuard aGuard;
+
+ OSL_ENSURE( !mpChildWin || pWin == mpChildWin, "invalid child window to remove" );
+ if( mpChildWin && pWin == mpChildWin )
+ {
+ AccessibleEventObject aEvent;
+ aEvent.EventId = AccessibleEventId::CHILD;
+ aEvent.OldValue <<= mpChildWin->GetAccessible();
+ FireAccessibleEvent( aEvent );
+
+ mpChildWin = 0;
+ }
+}
+
+sal_Int32 SAL_CALL SwAccessibleDocumentBase::getAccessibleChildCount( void )
+ throw (uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+
+ // CHECK_FOR_DEFUNC is called by parent
+
+ sal_Int32 nChildren = SwAccessibleContext::getAccessibleChildCount();
+ if( !IsDisposing() && mpChildWin )
+ nChildren++;
+
+ return nChildren;
+}
+
+uno::Reference< XAccessible> SAL_CALL
+ SwAccessibleDocumentBase::getAccessibleChild( sal_Int32 nIndex )
+ throw (uno::RuntimeException,
+ lang::IndexOutOfBoundsException)
+{
+ SolarMutexGuard aGuard;
+
+ if( mpChildWin )
+ {
+ CHECK_FOR_DEFUNC( XAccessibleContext )
+ if ( nIndex == GetChildCount( *(GetMap()) ) )
+ {
+ return mpChildWin->GetAccessible();
+ }
+ }
+
+ return SwAccessibleContext::getAccessibleChild( nIndex );
+}
+
+
+uno::Reference< XAccessible> SAL_CALL SwAccessibleDocumentBase::getAccessibleParent (void)
+ throw (uno::RuntimeException)
+{
+ return mxParent;
+}
+
+sal_Int32 SAL_CALL SwAccessibleDocumentBase::getAccessibleIndexInParent (void)
+ throw (uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+
+ uno::Reference < XAccessibleContext > xAcc( mxParent->getAccessibleContext() );
+ uno::Reference < XAccessible > xThis( this );
+ sal_Int32 nCount = xAcc->getAccessibleChildCount();
+
+ for( sal_Int32 i=0; i < nCount; i++ )
+ {
+ if( xAcc->getAccessibleChild( i ) == xThis )
+ return i;
+ }
+ return -1L;
+}
+
+OUString SAL_CALL SwAccessibleDocumentBase::getAccessibleDescription (void)
+ throw (uno::RuntimeException)
+{
+ return GetResource( STR_ACCESS_DOC_DESC );
+}
+
+awt::Rectangle SAL_CALL SwAccessibleDocumentBase::getBounds()
+ throw (uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+
+ Window *pWin = GetWindow();
+
+ CHECK_FOR_WINDOW( XAccessibleComponent, pWin )
+
+ Rectangle aPixBounds( pWin->GetWindowExtentsRelative( pWin->GetAccessibleParentWindow() ) );
+ awt::Rectangle aBox( aPixBounds.Left(), aPixBounds.Top(),
+ aPixBounds.GetWidth(), aPixBounds.GetHeight() );
+
+ return aBox;
+}
+
+
+awt::Point SAL_CALL SwAccessibleDocumentBase::getLocation()
+ throw (uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+
+ Window *pWin = GetWindow();
+
+ CHECK_FOR_WINDOW( XAccessibleComponent, pWin )
+
+ Point aPixPos( pWin->GetWindowExtentsRelative( pWin->GetAccessibleParentWindow() ).TopLeft() );
+ awt::Point aLoc( aPixPos.X(), aPixPos.Y() );
+
+ return aLoc;
+}
+
+
+::com::sun::star::awt::Point SAL_CALL SwAccessibleDocumentBase::getLocationOnScreen()
+ throw (uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+
+ Window *pWin = GetWindow();
+
+ CHECK_FOR_WINDOW( XAccessibleComponent, pWin )
+
+ Point aPixPos( pWin->GetWindowExtentsRelative( 0 ).TopLeft() );
+ awt::Point aLoc( aPixPos.X(), aPixPos.Y() );
+
+ return aLoc;
+}
+
+
+::com::sun::star::awt::Size SAL_CALL SwAccessibleDocumentBase::getSize()
+ throw (uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+
+ Window *pWin = GetWindow();
+
+ CHECK_FOR_WINDOW( XAccessibleComponent, pWin )
+
+ Size aPixSize( pWin->GetWindowExtentsRelative( 0 ).GetSize() );
+ awt::Size aSize( aPixSize.Width(), aPixSize.Height() );
+
+ return aSize;
+}
+
+sal_Bool SAL_CALL SwAccessibleDocumentBase::containsPoint(
+ const awt::Point& aPoint )
+ throw (uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+
+ Window *pWin = GetWindow();
+
+ CHECK_FOR_WINDOW( XAccessibleComponent, pWin )
+
+ Rectangle aPixBounds( pWin->GetWindowExtentsRelative( 0 ) );
+ aPixBounds.Move(-aPixBounds.Left(), -aPixBounds.Top());
+
+ Point aPixPoint( aPoint.X, aPoint.Y );
+ return aPixBounds.IsInside( aPixPoint );
+}
+
+uno::Reference< XAccessible > SAL_CALL SwAccessibleDocumentBase::getAccessibleAtPoint(
+ const awt::Point& aPoint )
+ throw (uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+
+ if( mpChildWin )
+ {
+ CHECK_FOR_DEFUNC( XAccessibleComponent )
+
+ Window *pWin = GetWindow();
+ CHECK_FOR_WINDOW( XAccessibleComponent, pWin )
+
+ Point aPixPoint( aPoint.X, aPoint.Y ); // px rel to window
+ if( mpChildWin->GetWindowExtentsRelative( pWin ).IsInside( aPixPoint ) )
+ return mpChildWin->GetAccessible();
+ }
+
+ return SwAccessibleContext::getAccessibleAtPoint( aPoint );
+}
+
+//
+// SwAccessibeDocument
+//
+
+void SwAccessibleDocument::GetStates(
+ ::utl::AccessibleStateSetHelper& rStateSet )
+{
+ SwAccessibleContext::GetStates( rStateSet );
+
+ // MULTISELECTABLE
+ rStateSet.AddState( AccessibleStateType::MULTI_SELECTABLE );
+}
+
+
+SwAccessibleDocument::SwAccessibleDocument ( SwAccessibleMap* pInitMap ) :
+ SwAccessibleDocumentBase( pInitMap ),
+ maSelectionHelper( *this )
+{
+ SetName( GetResource( STR_ACCESS_DOC_NAME ) );
+ Window *pWin = pInitMap->GetShell()->GetWin();
+ if( pWin )
+ {
+ pWin->AddChildEventListener( LINK( this, SwAccessibleDocument, WindowChildEventListener ));
+ sal_uInt16 nCount = pWin->GetChildCount();
+ for( sal_uInt16 i=0; i < nCount; i++ )
+ {
+ Window* pChildWin = pWin->GetChild( i );
+ if( pChildWin &&
+ AccessibleRole::EMBEDDED_OBJECT == pChildWin->GetAccessibleRole() )
+ AddChild( pChildWin, sal_False );
+ }
+ }
+}
+
+SwAccessibleDocument::~SwAccessibleDocument()
+{
+ Window *pWin = GetMap() ? GetMap()->GetShell()->GetWin() : 0;
+ if( pWin )
+ pWin->RemoveChildEventListener( LINK( this, SwAccessibleDocument, WindowChildEventListener ));
+}
+
+void SwAccessibleDocument::Dispose( sal_Bool bRecursive )
+{
+ OSL_ENSURE( GetFrm() && GetMap(), "already disposed" );
+
+ Window *pWin = GetMap() ? GetMap()->GetShell()->GetWin() : 0;
+ if( pWin )
+ pWin->RemoveChildEventListener( LINK( this, SwAccessibleDocument, WindowChildEventListener ));
+ SwAccessibleContext::Dispose( bRecursive );
+}
+
+IMPL_LINK( SwAccessibleDocument, WindowChildEventListener, VclSimpleEvent*, pEvent )
+{
+ DBG_ASSERT( pEvent && pEvent->ISA( VclWindowEvent ), "Unknown WindowEvent!" );
+ if ( pEvent && pEvent->ISA( VclWindowEvent ) )
+ {
+ VclWindowEvent *pVclEvent = static_cast< VclWindowEvent * >( pEvent );
+ DBG_ASSERT( pVclEvent->GetWindow(), "Window???" );
+ switch ( pVclEvent->GetId() )
+ {
+ case VCLEVENT_WINDOW_SHOW: // send create on show for direct accessible children
+ {
+ Window* pChildWin = static_cast< Window* >( pVclEvent->GetData() );
+ if( pChildWin && AccessibleRole::EMBEDDED_OBJECT == pChildWin->GetAccessibleRole() )
+ {
+ AddChild( pChildWin );
+ }
+ }
+ break;
+ case VCLEVENT_WINDOW_HIDE: // send destroy on hide for direct accessible children
+ {
+ Window* pChildWin = static_cast< Window* >( pVclEvent->GetData() );
+ if( pChildWin && AccessibleRole::EMBEDDED_OBJECT == pChildWin->GetAccessibleRole() )
+ {
+ RemoveChild( pChildWin );
+ }
+ }
+ break;
+ case VCLEVENT_OBJECT_DYING: // send destroy on hide for direct accessible children
+ {
+ Window* pChildWin = pVclEvent->GetWindow();
+ if( pChildWin && AccessibleRole::EMBEDDED_OBJECT == pChildWin->GetAccessibleRole() )
+ {
+ RemoveChild( pChildWin );
+ }
+ }
+ break;
+ }
+ }
+ return 0;
+}
+
+
+OUString SAL_CALL SwAccessibleDocument::getImplementationName()
+ throw( uno::RuntimeException )
+{
+ return OUString(RTL_CONSTASCII_USTRINGPARAM(sImplementationName));
+}
+
+sal_Bool SAL_CALL SwAccessibleDocument::supportsService(
+ const ::rtl::OUString& sTestServiceName)
+ throw (uno::RuntimeException)
+{
+ return sTestServiceName.equalsAsciiL( sServiceName,
+ sizeof(sServiceName)-1 ) ||
+ sTestServiceName.equalsAsciiL( sAccessibleServiceName,
+ sizeof(sAccessibleServiceName)-1 );
+}
+
+uno::Sequence< OUString > SAL_CALL SwAccessibleDocument::getSupportedServiceNames()
+ throw( uno::RuntimeException )
+{
+ uno::Sequence< OUString > aRet(2);
+ OUString* pArray = aRet.getArray();
+ pArray[0] = OUString( RTL_CONSTASCII_USTRINGPARAM(sServiceName) );
+ pArray[1] = OUString( RTL_CONSTASCII_USTRINGPARAM(sAccessibleServiceName) );
+ return aRet;
+}
+
+//===== XInterface ======================================================
+
+uno::Any SwAccessibleDocument::queryInterface(
+ const uno::Type& rType )
+ throw ( uno::RuntimeException )
+{
+ uno::Any aRet;
+ if ( rType == ::getCppuType( static_cast< uno::Reference< XAccessibleSelection > * >( 0 ) ) )
+ {
+ uno::Reference<XAccessibleSelection> aSelect = this;
+ aRet <<= aSelect;
+ }
+ else
+ aRet = SwAccessibleContext::queryInterface( rType );
+ return aRet;
+}
+
+//====== XTypeProvider ====================================================
+uno::Sequence< uno::Type > SAL_CALL SwAccessibleDocument::getTypes()
+ throw(uno::RuntimeException)
+{
+ uno::Sequence< uno::Type > aTypes( SwAccessibleDocumentBase::getTypes() );
+
+ sal_Int32 nIndex = aTypes.getLength();
+ aTypes.realloc( nIndex + 1 );
+
+ uno::Type* pTypes = aTypes.getArray();
+ pTypes[nIndex] = ::getCppuType( static_cast< uno::Reference< XAccessibleSelection > * >( 0 ) );
+
+ return aTypes;
+}
+
+uno::Sequence< sal_Int8 > SAL_CALL SwAccessibleDocument::getImplementationId()
+ throw(uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+ static uno::Sequence< sal_Int8 > aId( 16 );
+ static sal_Bool bInit = sal_False;
+ if(!bInit)
+ {
+ rtl_createUuid( (sal_uInt8 *)(aId.getArray() ), 0, sal_True );
+ bInit = sal_True;
+ }
+ return aId;
+}
+
+//===== XAccessibleSelection ============================================
+
+void SwAccessibleDocument::selectAccessibleChild(
+ sal_Int32 nChildIndex )
+ throw ( lang::IndexOutOfBoundsException,
+ uno::RuntimeException )
+{
+ maSelectionHelper.selectAccessibleChild(nChildIndex);
+}
+
+sal_Bool SwAccessibleDocument::isAccessibleChildSelected(
+ sal_Int32 nChildIndex )
+ throw ( lang::IndexOutOfBoundsException,
+ uno::RuntimeException )
+{
+ return maSelectionHelper.isAccessibleChildSelected(nChildIndex);
+}
+
+void SwAccessibleDocument::clearAccessibleSelection( )
+ throw ( uno::RuntimeException )
+{
+ maSelectionHelper.clearAccessibleSelection();
+}
+
+void SwAccessibleDocument::selectAllAccessibleChildren( )
+ throw ( uno::RuntimeException )
+{
+ maSelectionHelper.selectAllAccessibleChildren();
+}
+
+sal_Int32 SwAccessibleDocument::getSelectedAccessibleChildCount( )
+ throw ( uno::RuntimeException )
+{
+ return maSelectionHelper.getSelectedAccessibleChildCount();
+}
+
+uno::Reference<XAccessible> SwAccessibleDocument::getSelectedAccessibleChild(
+ sal_Int32 nSelectedChildIndex )
+ throw ( lang::IndexOutOfBoundsException,
+ uno::RuntimeException)
+{
+ return maSelectionHelper.getSelectedAccessibleChild(nSelectedChildIndex);
+}
+
+// index has to be treated as global child index.
+void SwAccessibleDocument::deselectAccessibleChild(
+ sal_Int32 nChildIndex )
+ throw ( lang::IndexOutOfBoundsException,
+ uno::RuntimeException )
+{
+ maSelectionHelper.deselectAccessibleChild( nChildIndex );
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/access/accdoc.hxx b/sw/source/core/access/accdoc.hxx
new file mode 100644
index 000000000000..2a4e125b7fb4
--- /dev/null
+++ b/sw/source/core/access/accdoc.hxx
@@ -0,0 +1,213 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+#ifndef _ACCDOC_HXX
+#define _ACCDOC_HXX
+#include "acccontext.hxx"
+#include <com/sun/star/accessibility/XAccessibleSelection.hpp>
+#include <accselectionhelper.hxx>
+
+class VclSimpleEvent;
+
+/**
+ * base class for SwAccessibleDocument (in this same header file) and
+ * SwAccessiblePreview
+ */
+class SwAccessibleDocumentBase : public SwAccessibleContext
+{
+ ::com::sun::star::uno::Reference<
+ ::com::sun::star::accessibility::XAccessible> mxParent;
+
+ Window* mpChildWin; // protected by solar mutext
+
+ using SwAccessibleFrame::SetVisArea;
+
+protected:
+
+ virtual ~SwAccessibleDocumentBase();
+
+public:
+
+ SwAccessibleDocumentBase( SwAccessibleMap* pInitMap );
+
+ void SetVisArea();
+
+ virtual void AddChild( Window *pWin, sal_Bool bFireEvent = sal_True );
+ virtual void RemoveChild( Window *pWin );
+
+ //===== XAccessibleContext ==============================================
+
+ /// Return the number of currently visible children.
+ virtual sal_Int32 SAL_CALL getAccessibleChildCount (void)
+ throw (::com::sun::star::uno::RuntimeException);
+
+ /// Return the specified child or NULL if index is invalid.
+ virtual ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible> SAL_CALL
+ getAccessibleChild (sal_Int32 nIndex)
+ throw (::com::sun::star::uno::RuntimeException,
+ ::com::sun::star::lang::IndexOutOfBoundsException);
+
+ /// Return a reference to the parent.
+ virtual ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible> SAL_CALL
+ getAccessibleParent (void)
+ throw (::com::sun::star::uno::RuntimeException);
+
+ /// Return this objects index among the parents children.
+ virtual sal_Int32 SAL_CALL
+ getAccessibleIndexInParent (void)
+ throw (::com::sun::star::uno::RuntimeException);
+
+ /// Return this object's description.
+ virtual ::rtl::OUString SAL_CALL
+ getAccessibleDescription (void) throw (com::sun::star::uno::RuntimeException);
+
+ //===== XAccessibleComponent ==============================================
+ virtual sal_Bool SAL_CALL containsPoint(
+ const ::com::sun::star::awt::Point& aPoint )
+ throw (::com::sun::star::uno::RuntimeException);
+
+ virtual ::com::sun::star::uno::Reference<
+ ::com::sun::star::accessibility::XAccessible > SAL_CALL getAccessibleAtPoint(
+ const ::com::sun::star::awt::Point& aPoint )
+ throw (::com::sun::star::uno::RuntimeException);
+
+ virtual ::com::sun::star::awt::Rectangle SAL_CALL getBounds()
+ throw (::com::sun::star::uno::RuntimeException);
+
+ virtual ::com::sun::star::awt::Point SAL_CALL getLocation()
+ throw (::com::sun::star::uno::RuntimeException);
+
+ virtual ::com::sun::star::awt::Point SAL_CALL getLocationOnScreen()
+ throw (::com::sun::star::uno::RuntimeException);
+
+ virtual ::com::sun::star::awt::Size SAL_CALL getSize()
+ throw (::com::sun::star::uno::RuntimeException);
+};
+
+
+
+/**
+ * access to an accessible Writer document
+ */
+class SwAccessibleDocument : public SwAccessibleDocumentBase,
+ public com::sun::star::accessibility::XAccessibleSelection
+{
+ // Implementation for XAccessibleSelection interface
+ SwAccessibleSelectionHelper maSelectionHelper;
+
+protected:
+
+ // Set states for getAccessibleStateSet.
+ // This drived class additinaly sets MULTISELECTABLE(1)
+ virtual void GetStates( ::utl::AccessibleStateSetHelper& rStateSet );
+
+ virtual ~SwAccessibleDocument();
+
+public:
+
+ SwAccessibleDocument( SwAccessibleMap* pInitMap );
+
+ DECL_LINK( WindowChildEventListener, VclSimpleEvent* );
+
+ //===== XServiceInfo ====================================================
+
+ /** Returns an identifier for the implementation of this object.
+ */
+ virtual ::rtl::OUString SAL_CALL
+ getImplementationName (void)
+ throw (::com::sun::star::uno::RuntimeException);
+
+ /** Return whether the specified service is supported by this class.
+ */
+ virtual sal_Bool SAL_CALL
+ supportsService (const ::rtl::OUString& sServiceName)
+ throw (::com::sun::star::uno::RuntimeException);
+
+ /** Returns a list of all supported services. In this case that is just
+ the AccessibleContext service.
+ */
+ virtual ::com::sun::star::uno::Sequence< ::rtl::OUString> SAL_CALL
+ getSupportedServiceNames (void)
+ throw (::com::sun::star::uno::RuntimeException);
+
+ //===== XInterface ======================================================
+
+ // XInterface is inherited through SwAcessibleContext and
+ // XAccessibleSelection. These methods are needed to avoid
+ // ambigiouties.
+
+ virtual ::com::sun::star::uno::Any SAL_CALL queryInterface(
+ const ::com::sun::star::uno::Type& aType )
+ throw (::com::sun::star::uno::RuntimeException);
+
+ virtual void SAL_CALL acquire( ) throw ()
+ { SwAccessibleContext::acquire(); };
+
+ virtual void SAL_CALL release( ) throw ()
+ { SwAccessibleContext::release(); };
+
+ //====== XTypeProvider ====================================================
+ virtual ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Type > SAL_CALL getTypes( ) throw(::com::sun::star::uno::RuntimeException);
+ virtual ::com::sun::star::uno::Sequence< sal_Int8 > SAL_CALL getImplementationId( ) throw(::com::sun::star::uno::RuntimeException);
+
+ //===== XAccessibleSelection ============================================
+
+ virtual void SAL_CALL selectAccessibleChild(
+ sal_Int32 nChildIndex )
+ throw ( ::com::sun::star::lang::IndexOutOfBoundsException,
+ ::com::sun::star::uno::RuntimeException );
+
+ virtual sal_Bool SAL_CALL isAccessibleChildSelected(
+ sal_Int32 nChildIndex )
+ throw ( ::com::sun::star::lang::IndexOutOfBoundsException,
+ ::com::sun::star::uno::RuntimeException );
+ virtual void SAL_CALL clearAccessibleSelection( )
+ throw ( ::com::sun::star::uno::RuntimeException );
+ virtual void SAL_CALL selectAllAccessibleChildren( )
+ throw ( ::com::sun::star::uno::RuntimeException );
+ virtual sal_Int32 SAL_CALL getSelectedAccessibleChildCount( )
+ throw ( ::com::sun::star::uno::RuntimeException );
+ virtual ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible > SAL_CALL getSelectedAccessibleChild(
+ sal_Int32 nSelectedChildIndex )
+ throw ( ::com::sun::star::lang::IndexOutOfBoundsException,
+ ::com::sun::star::uno::RuntimeException);
+
+ // index has to be treated as global child index.
+ virtual void SAL_CALL deselectAccessibleChild(
+ sal_Int32 nChildIndex )
+ throw ( ::com::sun::star::lang::IndexOutOfBoundsException,
+ ::com::sun::star::uno::RuntimeException );
+
+ //====== thread safe C++ interface ========================================
+
+ // The object is not visible an longer and should be destroyed
+ virtual void Dispose( sal_Bool bRecursive = sal_False );
+};
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/access/accembedded.cxx b/sw/source/core/access/accembedded.cxx
new file mode 100644
index 000000000000..5ccbc03f3339
--- /dev/null
+++ b/sw/source/core/access/accembedded.cxx
@@ -0,0 +1,100 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+ /*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+
+#include <vcl/svapp.hxx>
+#include <com/sun/star/accessibility/AccessibleRole.hpp>
+#include <com/sun/star/uno/RuntimeException.hpp>
+#include <rtl/uuid.h>
+#include <flyfrm.hxx>
+#include "accembedded.hxx"
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star::accessibility;
+using ::rtl::OUString;
+
+const sal_Char sServiceName[] = "com.sun.star.text.AccessibleTextEmbeddedObject";
+const sal_Char sImplementationName[] = "com.sun.star.comp.Writer.SwAccessibleEmbeddedObject";
+
+SwAccessibleEmbeddedObject::SwAccessibleEmbeddedObject(
+ SwAccessibleMap* pInitMap,
+ const SwFlyFrm* pFlyFrm ) :
+ SwAccessibleNoTextFrame( pInitMap, AccessibleRole::EMBEDDED_OBJECT, pFlyFrm )
+{
+}
+
+SwAccessibleEmbeddedObject::~SwAccessibleEmbeddedObject()
+{
+}
+
+OUString SAL_CALL SwAccessibleEmbeddedObject::getImplementationName()
+ throw( uno::RuntimeException )
+{
+ return OUString(RTL_CONSTASCII_USTRINGPARAM(sImplementationName));
+}
+
+sal_Bool SAL_CALL SwAccessibleEmbeddedObject::supportsService(
+ const ::rtl::OUString& sTestServiceName)
+ throw (uno::RuntimeException)
+{
+ return sTestServiceName.equalsAsciiL( sServiceName,
+ sizeof(sServiceName)-1 ) ||
+ sTestServiceName.equalsAsciiL( sAccessibleServiceName,
+ sizeof(sAccessibleServiceName)-1 );
+}
+
+uno::Sequence< OUString > SAL_CALL SwAccessibleEmbeddedObject::getSupportedServiceNames()
+ throw( uno::RuntimeException )
+{
+ uno::Sequence< OUString > aRet(2);
+ OUString* pArray = aRet.getArray();
+ pArray[0] = OUString( RTL_CONSTASCII_USTRINGPARAM(sServiceName) );
+ pArray[1] = OUString( RTL_CONSTASCII_USTRINGPARAM(sAccessibleServiceName) );
+ return aRet;
+}
+
+
+uno::Sequence< sal_Int8 > SAL_CALL SwAccessibleEmbeddedObject::getImplementationId()
+ throw(uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+ static uno::Sequence< sal_Int8 > aId( 16 );
+ static sal_Bool bInit = sal_False;
+ if(!bInit)
+ {
+ rtl_createUuid( (sal_uInt8 *)(aId.getArray() ), 0, sal_True );
+ bInit = sal_True;
+ }
+ return aId;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/access/accembedded.hxx b/sw/source/core/access/accembedded.hxx
new file mode 100644
index 000000000000..94f8e2d43c20
--- /dev/null
+++ b/sw/source/core/access/accembedded.hxx
@@ -0,0 +1,72 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+#ifndef _ACCEMBEDDED_HXX
+#define _ACCEMBEDDED_HXX
+#include "accnotextframe.hxx"
+
+class SwAccessibleEmbeddedObject : public SwAccessibleNoTextFrame
+{
+
+protected:
+
+ virtual ~SwAccessibleEmbeddedObject();
+
+public:
+
+ SwAccessibleEmbeddedObject( SwAccessibleMap* pInitMap,
+ const SwFlyFrm* pFlyFrm );
+
+ //===== XServiceInfo ====================================================
+
+ /** Returns an identifier for the implementation of this object.
+ */
+ virtual ::rtl::OUString SAL_CALL
+ getImplementationName (void)
+ throw (::com::sun::star::uno::RuntimeException);
+
+ /** Return whether the specified service is supported by this class.
+ */
+ virtual sal_Bool SAL_CALL
+ supportsService (const ::rtl::OUString& sServiceName)
+ throw (::com::sun::star::uno::RuntimeException);
+
+ /** Returns a list of all supported services. In this case that is just
+ the AccessibleContext service.
+ */
+ virtual ::com::sun::star::uno::Sequence< ::rtl::OUString> SAL_CALL
+ getSupportedServiceNames (void)
+ throw (::com::sun::star::uno::RuntimeException);
+
+ //===== XTypeProvider ====================================================
+ virtual ::com::sun::star::uno::Sequence< sal_Int8 > SAL_CALL getImplementationId( ) throw(::com::sun::star::uno::RuntimeException);
+};
+
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/access/accfootnote.cxx b/sw/source/core/access/accfootnote.cxx
new file mode 100644
index 000000000000..2efd6cf6d78f
--- /dev/null
+++ b/sw/source/core/access/accfootnote.cxx
@@ -0,0 +1,158 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+ /*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+
+#include <osl/mutex.hxx>
+#include <com/sun/star/accessibility/AccessibleRole.hpp>
+#include <com/sun/star/accessibility/AccessibleStateType.hpp>
+#include <unotools/accessiblestatesethelper.hxx>
+#include <rtl/uuid.h>
+#include <vcl/svapp.hxx>
+#include <ftnfrm.hxx>
+#include <fmtftn.hxx>
+#include <txtftn.hxx>
+#include <viewsh.hxx>
+#include <accmap.hxx>
+#include "accfootnote.hxx"
+#include "access.hrc"
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star::accessibility;
+using ::rtl::OUString;
+
+const sal_Char sServiceNameFootnote[] = "com.sun.star.text.AccessibleFootnoteView";
+const sal_Char sServiceNameEndnote[] = "com.sun.star.text.AccessibleEndnoteView";
+const sal_Char sImplementationNameFootnote[] = "com.sun.star.comp.Writer.SwAccessibleFootnoteView";
+const sal_Char sImplementationNameEndnote[] = "com.sun.star.comp.Writer.SwAccessibleEndnoteView";
+
+SwAccessibleFootnote::SwAccessibleFootnote(
+ SwAccessibleMap* pInitMap,
+ sal_Bool bIsEndnote,
+ sal_Int32 nFootEndNote,
+ const SwFtnFrm *pFtnFrm ) :
+ SwAccessibleContext( pInitMap,
+ bIsEndnote ? AccessibleRole::END_NOTE : AccessibleRole::FOOTNOTE,
+ pFtnFrm )
+{
+ SolarMutexGuard aGuard;
+
+ sal_uInt16 nResId = bIsEndnote ? STR_ACCESS_ENDNOTE_NAME
+ : STR_ACCESS_FOOTNOTE_NAME;
+ OUString sArg( OUString::valueOf( nFootEndNote ) );
+ SetName( GetResource( nResId, &sArg ) );
+}
+
+SwAccessibleFootnote::~SwAccessibleFootnote()
+{
+}
+
+OUString SAL_CALL SwAccessibleFootnote::getAccessibleDescription (void)
+ throw (uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+
+ CHECK_FOR_DEFUNC( XAccessibleContext )
+
+ sal_uInt16 nResId = AccessibleRole::END_NOTE == GetRole()
+ ? STR_ACCESS_ENDNOTE_DESC
+ : STR_ACCESS_FOOTNOTE_DESC ;
+
+ OUString sArg;
+ const SwTxtFtn *pTxtFtn =
+ static_cast< const SwFtnFrm *>( GetFrm() )->GetAttr();
+ if( pTxtFtn )
+ {
+ const SwDoc *pDoc = GetMap()->GetShell()->GetDoc();
+ sArg = pTxtFtn->GetFtn().GetViewNumStr( *pDoc );
+ }
+
+ return GetResource( nResId, &sArg );
+}
+
+OUString SAL_CALL SwAccessibleFootnote::getImplementationName()
+ throw( RuntimeException )
+{
+ if( AccessibleRole::END_NOTE == GetRole() )
+ return OUString(RTL_CONSTASCII_USTRINGPARAM(sImplementationNameEndnote));
+ else
+ return OUString(RTL_CONSTASCII_USTRINGPARAM(sImplementationNameFootnote));
+}
+
+sal_Bool SAL_CALL SwAccessibleFootnote::supportsService(
+ const ::rtl::OUString& sTestServiceName)
+ throw (uno::RuntimeException)
+{
+ if( sTestServiceName.equalsAsciiL( sAccessibleServiceName,
+ sizeof(sAccessibleServiceName)-1 ) )
+ return sal_True;
+ else if( AccessibleRole::END_NOTE == GetRole() )
+ return sTestServiceName.equalsAsciiL( sServiceNameEndnote, sizeof(sServiceNameEndnote)-1 );
+ else
+ return sTestServiceName.equalsAsciiL( sServiceNameFootnote, sizeof(sServiceNameFootnote)-1 );
+
+}
+
+Sequence< OUString > SAL_CALL SwAccessibleFootnote::getSupportedServiceNames()
+ throw( uno::RuntimeException )
+{
+ Sequence< OUString > aRet(2);
+ OUString* pArray = aRet.getArray();
+ if( AccessibleRole::END_NOTE == GetRole() )
+ pArray[0] = OUString( RTL_CONSTASCII_USTRINGPARAM(sServiceNameEndnote) );
+ else
+ pArray[0] = OUString( RTL_CONSTASCII_USTRINGPARAM(sServiceNameFootnote) );
+ pArray[1] = OUString( RTL_CONSTASCII_USTRINGPARAM(sAccessibleServiceName) );
+ return aRet;
+}
+
+Sequence< sal_Int8 > SAL_CALL SwAccessibleFootnote::getImplementationId()
+ throw(RuntimeException)
+{
+ SolarMutexGuard aGuard;
+ static Sequence< sal_Int8 > aId( 16 );
+ static sal_Bool bInit = sal_False;
+ if(!bInit)
+ {
+ rtl_createUuid( (sal_uInt8 *)(aId.getArray() ), 0, sal_True );
+ bInit = sal_True;
+ }
+ return aId;
+}
+
+sal_Bool SwAccessibleFootnote::IsEndnote( const SwFtnFrm *pFtnFrm )
+{
+ const SwTxtFtn *pTxtFtn = pFtnFrm ->GetAttr();
+ return pTxtFtn && pTxtFtn->GetFtn().IsEndNote() ;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/access/accfootnote.hxx b/sw/source/core/access/accfootnote.hxx
new file mode 100644
index 000000000000..521247685a16
--- /dev/null
+++ b/sw/source/core/access/accfootnote.hxx
@@ -0,0 +1,90 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+#ifndef _ACCFOOTNOTE_HXX
+#define _ACCFOOTNOTE_HXX
+
+#include <sal/types.h>
+
+#include <acccontext.hxx>
+
+class SwAccessibleMap;
+class SwFtnFrm;
+
+class SwAccessibleFootnote : public SwAccessibleContext
+{
+
+protected:
+
+ virtual ~SwAccessibleFootnote();
+
+public:
+
+ SwAccessibleFootnote( SwAccessibleMap* pInitMap,
+ sal_Bool bIsEndnote,
+ sal_Int32 nFootEndNote,
+ const SwFtnFrm *pFtnFrm );
+
+
+ //===== XAccessibleContext ==============================================
+
+ /// Return this object's description.
+ virtual ::rtl::OUString SAL_CALL
+ getAccessibleDescription (void)
+ throw (com::sun::star::uno::RuntimeException);
+
+ //===== XServiceInfo ====================================================
+
+ /** Returns an identifier for the implementation of this object.
+ */
+ virtual ::rtl::OUString SAL_CALL
+ getImplementationName (void)
+ throw (::com::sun::star::uno::RuntimeException);
+
+ /** Return whether the specified service is supported by this class.
+ */
+ virtual sal_Bool SAL_CALL
+ supportsService (const ::rtl::OUString& sServiceName)
+ throw (::com::sun::star::uno::RuntimeException);
+
+ /** Returns a list of all supported services. In this case that is just
+ the AccessibleContext service.
+ */
+ virtual ::com::sun::star::uno::Sequence< ::rtl::OUString> SAL_CALL
+ getSupportedServiceNames (void)
+ throw (::com::sun::star::uno::RuntimeException);
+
+ //===== XTypeProvider ====================================================
+ virtual ::com::sun::star::uno::Sequence< sal_Int8 > SAL_CALL getImplementationId( ) throw(::com::sun::star::uno::RuntimeException);
+
+ static sal_Bool IsEndnote( const SwFtnFrm *pFrm );
+};
+
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/access/accframe.cxx b/sw/source/core/access/accframe.cxx
new file mode 100644
index 000000000000..c19c7cf8ef1d
--- /dev/null
+++ b/sw/source/core/access/accframe.cxx
@@ -0,0 +1,496 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+ /*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+
+
+#include <hintids.hxx>
+#include <editeng/brshitem.hxx>
+#include <flyfrm.hxx>
+#include <rootfrm.hxx>
+#include <txtfrm.hxx>
+#include <sectfrm.hxx>
+#include <section.hxx>
+#include <viewsh.hxx>
+#include <viewopt.hxx>
+#include <doc.hxx>
+#include <frmatr.hxx>
+#include <pagefrm.hxx>
+#include <pagedesc.hxx>
+#include <fmtanchr.hxx>
+#include <fldbas.hxx>
+#include <dcontact.hxx>
+#include <accmap.hxx>
+#include <accfrmobjslist.hxx>
+#include <accfrmobjmap.hxx>
+#include <accframe.hxx>
+
+using namespace sw::access;
+
+// Regarding visibilily (or in terms of accessibility: regarding the showing
+// state): A frame is visible and therfor contained in the tree if its frame
+// size overlaps with the visible area. The bounding box however is the
+// frame's paint area.
+/* static */ sal_Int32 SwAccessibleFrame::GetChildCount( SwAccessibleMap& rAccMap,
+ const SwRect& rVisArea,
+ const SwFrm *pFrm,
+ sal_Bool bInPagePreview )
+{
+ sal_Int32 nCount = 0;
+
+ const SwAccessibleChildSList aVisList( rVisArea, *pFrm, rAccMap );
+ SwAccessibleChildSList::const_iterator aIter( aVisList.begin() );
+ while( aIter != aVisList.end() )
+ {
+ const SwAccessibleChild& rLower = *aIter;
+ if( rLower.IsAccessible( bInPagePreview ) )
+ {
+ nCount++;
+ }
+ else if( rLower.GetSwFrm() )
+ {
+ // There are no unaccessible SdrObjects that count
+ nCount += GetChildCount( rAccMap,
+ rVisArea, rLower.GetSwFrm(),
+ bInPagePreview );
+ }
+ ++aIter;
+ }
+
+ return nCount;
+}
+
+/* static */ SwAccessibleChild SwAccessibleFrame::GetChild(
+ SwAccessibleMap& rAccMap,
+ const SwRect& rVisArea,
+ const SwFrm& rFrm,
+ sal_Int32& rPos,
+ sal_Bool bInPagePreview )
+{
+ SwAccessibleChild aRet;
+
+ if( rPos >= 0 )
+ {
+ if( SwAccessibleChildMap::IsSortingRequired( rFrm ) )
+ {
+ // We need a sorted list here
+ const SwAccessibleChildMap aVisMap( rVisArea, rFrm, rAccMap );
+ SwAccessibleChildMap::const_iterator aIter( aVisMap.begin() );
+ while( aIter != aVisMap.end() && !aRet.IsValid() )
+ {
+ const SwAccessibleChild& rLower = (*aIter).second;
+ if( rLower.IsAccessible( bInPagePreview ) )
+ {
+ if( 0 == rPos )
+ aRet = rLower;
+ else
+ rPos--;
+ }
+ else if( rLower.GetSwFrm() )
+ {
+ // There are no unaccessible SdrObjects that count
+ aRet = GetChild( rAccMap,
+ rVisArea, *(rLower.GetSwFrm()), rPos,
+ bInPagePreview );
+ }
+ ++aIter;
+ }
+ }
+ else
+ {
+ // The unsorted list is sorted enough, because it return lower
+ // frames in the correct order.
+ const SwAccessibleChildSList aVisList( rVisArea, rFrm, rAccMap );
+ SwAccessibleChildSList::const_iterator aIter( aVisList.begin() );
+ while( aIter != aVisList.end() && !aRet.IsValid() )
+ {
+ const SwAccessibleChild& rLower = *aIter;
+ if( rLower.IsAccessible( bInPagePreview ) )
+ {
+ if( 0 == rPos )
+ aRet = rLower;
+ else
+ rPos--;
+ }
+ else if( rLower.GetSwFrm() )
+ {
+ // There are no unaccessible SdrObjects that count
+ aRet = GetChild( rAccMap,
+ rVisArea, *(rLower.GetSwFrm()), rPos,
+ bInPagePreview );
+ }
+ ++aIter;
+ }
+ }
+ }
+
+ return aRet;
+}
+
+/* static */ sal_Bool SwAccessibleFrame::GetChildIndex(
+ SwAccessibleMap& rAccMap,
+ const SwRect& rVisArea,
+ const SwFrm& rFrm,
+ const SwAccessibleChild& rChild,
+ sal_Int32& rPos,
+ sal_Bool bInPagePreview )
+{
+ sal_Bool bFound = sal_False;
+
+ if( SwAccessibleChildMap::IsSortingRequired( rFrm ) )
+ {
+ // We need a sorted list here
+ const SwAccessibleChildMap aVisMap( rVisArea, rFrm, rAccMap );
+ SwAccessibleChildMap::const_iterator aIter( aVisMap.begin() );
+ while( aIter != aVisMap.end() && !bFound )
+ {
+ const SwAccessibleChild& rLower = (*aIter).second;
+ if( rLower.IsAccessible( bInPagePreview ) )
+ {
+ if( rChild == rLower )
+ bFound = sal_True;
+ else
+ rPos++;
+ }
+ else if( rLower.GetSwFrm() )
+ {
+ // There are no unaccessible SdrObjects that count
+ bFound = GetChildIndex( rAccMap,
+ rVisArea, *(rLower.GetSwFrm()), rChild,
+ rPos, bInPagePreview );
+ }
+ ++aIter;
+ }
+ }
+ else
+ {
+ // The unsorted list is sorted enough, because it return lower
+ // frames in the correct order.
+ const SwAccessibleChildSList aVisList( rVisArea, rFrm, rAccMap );
+ SwAccessibleChildSList::const_iterator aIter( aVisList.begin() );
+ while( aIter != aVisList.end() && !bFound )
+ {
+ const SwAccessibleChild& rLower = *aIter;
+ if( rLower.IsAccessible( bInPagePreview ) )
+ {
+ if( rChild == rLower )
+ bFound = sal_True;
+ else
+ rPos++;
+ }
+ else if( rLower.GetSwFrm() )
+ {
+ // There are no unaccessible SdrObjects that count
+ bFound = GetChildIndex( rAccMap,
+ rVisArea, *(rLower.GetSwFrm()), rChild,
+ rPos, bInPagePreview );
+ }
+ ++aIter;
+ }
+ }
+
+ return bFound;
+}
+
+SwAccessibleChild SwAccessibleFrame::GetChildAtPixel( const SwRect& rVisArea,
+ const SwFrm& rFrm,
+ const Point& rPixPos,
+ sal_Bool bInPagePreview,
+ SwAccessibleMap& rAccMap )
+{
+ SwAccessibleChild aRet;
+
+ if( SwAccessibleChildMap::IsSortingRequired( rFrm ) )
+ {
+ // We need a sorted list here, and we have to reverse iterate,
+ // because objects in front should be returned.
+ const SwAccessibleChildMap aVisMap( rVisArea, rFrm, rAccMap );
+ SwAccessibleChildMap::const_reverse_iterator aRIter( aVisMap.rbegin() );
+ while( aRIter != aVisMap.rend() && !aRet.IsValid() )
+ {
+ const SwAccessibleChild& rLower = (*aRIter).second;
+ // A frame is returned if it's frame size is inside the visarea
+ // and the positiion is inside the frame's paint area.
+ if( rLower.IsAccessible( bInPagePreview ) )
+ {
+ SwRect aLogBounds( rLower.GetBounds( rAccMap ) );
+ if( !aLogBounds.IsEmpty() )
+ {
+ Rectangle aPixBounds( rAccMap.CoreToPixel( aLogBounds.SVRect() ) );
+ if( aPixBounds.IsInside( rPixPos ) )
+ aRet = rLower;
+ }
+ }
+ else if( rLower.GetSwFrm() )
+ {
+ // There are no unaccessible SdrObjects that count
+ aRet = GetChildAtPixel( rVisArea, *(rLower.GetSwFrm()), rPixPos,
+ bInPagePreview, rAccMap );
+ }
+ ++aRIter;
+ }
+ }
+ else
+ {
+ // The unsorted list is sorted enough, because it returns lower
+ // frames in the correct order. Morover, we can iterate forward,
+ // because the lowers don't overlap!
+ const SwAccessibleChildSList aVisList( rVisArea, rFrm, rAccMap );
+ SwAccessibleChildSList::const_iterator aIter( aVisList.begin() );
+ while( aIter != aVisList.end() && !aRet.IsValid() )
+ {
+ const SwAccessibleChild& rLower = *aIter;
+ // A frame is returned if it's frame size is inside the visarea
+ // and the positiion is inside the frame's paint area.
+ if( rLower.IsAccessible( bInPagePreview ) )
+ {
+ SwRect aLogBounds( rLower.GetBounds( rAccMap ) );
+ if( !aLogBounds.IsEmpty() )
+ {
+ Rectangle aPixBounds( rAccMap.CoreToPixel( aLogBounds.SVRect() ) );
+ if( aPixBounds.IsInside( rPixPos ) )
+ aRet = rLower;
+ }
+ }
+ else if( rLower.GetSwFrm() )
+ {
+ // There are no unaccessible SdrObjects that count
+ aRet = GetChildAtPixel( rVisArea, *(rLower.GetSwFrm()), rPixPos,
+ bInPagePreview, rAccMap );
+ }
+ ++aIter;
+ }
+ }
+
+ return aRet;
+}
+
+/* static */ void SwAccessibleFrame::GetChildren( SwAccessibleMap& rAccMap,
+ const SwRect& rVisArea,
+ const SwFrm& rFrm,
+ ::std::list< SwAccessibleChild >& rChildren,
+ sal_Bool bInPagePreview )
+{
+ if( SwAccessibleChildMap::IsSortingRequired( rFrm ) )
+ {
+ // We need a sorted list here
+ const SwAccessibleChildMap aVisMap( rVisArea, rFrm, rAccMap );
+ SwAccessibleChildMap::const_iterator aIter( aVisMap.begin() );
+ while( aIter != aVisMap.end() )
+ {
+ const SwAccessibleChild& rLower = (*aIter).second;
+ if( rLower.IsAccessible( bInPagePreview ) )
+ {
+ rChildren.push_back( rLower );
+ }
+ else if( rLower.GetSwFrm() )
+ {
+ // There are no unaccessible SdrObjects that count
+ GetChildren( rAccMap, rVisArea, *(rLower.GetSwFrm()),
+ rChildren, bInPagePreview );
+ }
+ ++aIter;
+ }
+ }
+ else
+ {
+ // The unsorted list is sorted enough, because it return lower
+ // frames in the correct order.
+ const SwAccessibleChildSList aVisList( rVisArea, rFrm, rAccMap );
+ SwAccessibleChildSList::const_iterator aIter( aVisList.begin() );
+ while( aIter != aVisList.end() )
+ {
+ const SwAccessibleChild& rLower = *aIter;
+ if( rLower.IsAccessible( bInPagePreview ) )
+ {
+ rChildren.push_back( rLower );
+ }
+ else if( rLower.GetSwFrm() )
+ {
+ // There are no unaccessible SdrObjects that count
+ GetChildren( rAccMap, rVisArea, *(rLower.GetSwFrm()),
+ rChildren, bInPagePreview );
+ }
+ ++aIter;
+ }
+ }
+}
+
+SwRect SwAccessibleFrame::GetBounds( const SwAccessibleMap& rAccMap,
+ const SwFrm *pFrm )
+{
+ if( !pFrm )
+ pFrm = GetFrm();
+
+ SwAccessibleChild aFrm( pFrm );
+ SwRect aBounds( aFrm.GetBounds( rAccMap ).Intersection( maVisArea ) );
+ return aBounds;
+}
+
+sal_Bool SwAccessibleFrame::IsEditable( ViewShell *pVSh ) const
+{
+ const SwFrm *pFrm = GetFrm();
+ if( !pFrm )
+ return sal_False;
+
+ OSL_ENSURE( pVSh, "no view shell" );
+ if( pVSh && (pVSh->GetViewOptions()->IsReadonly() ||
+ pVSh->IsPreView()) )
+ return sal_False;
+
+ if( !pFrm->IsRootFrm() && pFrm->IsProtected() )
+ return sal_False;
+
+ return sal_True;
+}
+
+sal_Bool SwAccessibleFrame::IsOpaque( ViewShell *pVSh ) const
+{
+ SwAccessibleChild aFrm( GetFrm() );
+ if( !aFrm.GetSwFrm() )
+ return sal_False;
+
+ OSL_ENSURE( pVSh, "no view shell" );
+ if( !pVSh )
+ return sal_False;
+
+ const SwViewOption *pVOpt = pVSh->GetViewOptions();
+ do
+ {
+ const SwFrm *pFrm = aFrm.GetSwFrm();
+ if( pFrm->IsRootFrm() )
+ return sal_True;
+
+ if( pFrm->IsPageFrm() && !pVOpt->IsPageBack() )
+ return sal_False;
+
+ const SvxBrushItem &rBack = pFrm->GetAttrSet()->GetBackground();
+ if( !rBack.GetColor().GetTransparency() ||
+ rBack.GetGraphicPos() != GPOS_NONE )
+ return sal_True;
+
+ // If a fly frame has a transparent background color, we have to consider the background.
+ // But a background color "no fill"/"auto fill" has *not* to be considered.
+ if( pFrm->IsFlyFrm() &&
+ (rBack.GetColor().GetTransparency() != 0) &&
+ (rBack.GetColor() != COL_TRANSPARENT)
+ )
+ return sal_True;
+
+ if( pFrm->IsSctFrm() )
+ {
+ const SwSection* pSection = ((SwSectionFrm*)pFrm)->GetSection();
+ if( pSection && ( TOX_HEADER_SECTION == pSection->GetType() ||
+ TOX_CONTENT_SECTION == pSection->GetType() ) &&
+ !pVOpt->IsReadonly() &&
+ SwViewOption::IsIndexShadings() )
+ return sal_True;
+ }
+ if( pFrm->IsFlyFrm() )
+ aFrm = static_cast<const SwFlyFrm*>(pFrm)->GetAnchorFrm();
+ else
+ aFrm = pFrm->GetUpper();
+ } while( aFrm.GetSwFrm() && !aFrm.IsAccessible( IsInPagePreview() ) );
+
+ return sal_False;
+}
+
+SwAccessibleFrame::SwAccessibleFrame( const SwRect& rVisArea,
+ const SwFrm *pF,
+ sal_Bool bIsPagePreview ) :
+ maVisArea( rVisArea ),
+ mpFrm( pF ),
+ mbIsInPagePreview( bIsPagePreview )
+{
+}
+
+SwAccessibleFrame::~SwAccessibleFrame()
+{
+}
+
+/* static */ const SwFrm* SwAccessibleFrame::GetParent( const SwAccessibleChild& rFrmOrObj,
+ sal_Bool bInPagePreview )
+{
+ return rFrmOrObj.GetParent( bInPagePreview );
+}
+
+String SwAccessibleFrame::GetFormattedPageNumber() const
+{
+ sal_uInt16 nPageNum = GetFrm()->GetVirtPageNum();
+ sal_uInt32 nFmt = GetFrm()->FindPageFrm()->GetPageDesc()
+ ->GetNumType().GetNumberingType();
+ if( SVX_NUM_NUMBER_NONE == nFmt )
+ nFmt = SVX_NUM_ARABIC;
+
+ String sRet( FormatNumber( nPageNum, nFmt ) );
+ return sRet;
+}
+
+sal_Int32 SwAccessibleFrame::GetChildCount( SwAccessibleMap& rAccMap ) const
+{
+ return GetChildCount( rAccMap, maVisArea, mpFrm, IsInPagePreview() );
+}
+
+sw::access::SwAccessibleChild SwAccessibleFrame::GetChild(
+ SwAccessibleMap& rAccMap,
+ sal_Int32 nPos ) const
+{
+ return SwAccessibleFrame::GetChild( rAccMap, maVisArea, *mpFrm, nPos, IsInPagePreview() );
+}
+
+sal_Int32 SwAccessibleFrame::GetChildIndex( SwAccessibleMap& rAccMap,
+ const sw::access::SwAccessibleChild& rChild ) const
+{
+ sal_Int32 nPos = 0;
+ return GetChildIndex( rAccMap, maVisArea, *mpFrm, rChild, nPos, IsInPagePreview() )
+ ? nPos
+ : -1L;
+}
+
+sw::access::SwAccessibleChild SwAccessibleFrame::GetChildAtPixel(
+ const Point& rPos,
+ SwAccessibleMap& rAccMap ) const
+{
+ return GetChildAtPixel( maVisArea, *mpFrm, rPos, IsInPagePreview(), rAccMap );
+}
+
+void SwAccessibleFrame::GetChildren( SwAccessibleMap& rAccMap,
+ ::std::list< sw::access::SwAccessibleChild >& rChildren ) const
+{
+ GetChildren( rAccMap, maVisArea, *mpFrm, rChildren, IsInPagePreview() );
+}
+
+sal_Bool SwAccessibleFrame::IsShowing( const SwAccessibleMap& rAccMap,
+ const sw::access::SwAccessibleChild& rFrmOrObj ) const
+{
+ return IsShowing( rFrmOrObj.GetBox( rAccMap ) );
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/access/accframe.hxx b/sw/source/core/access/accframe.hxx
new file mode 100644
index 000000000000..7aa7e42f9e0c
--- /dev/null
+++ b/sw/source/core/access/accframe.hxx
@@ -0,0 +1,176 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+#ifndef _ACCFRAME_HXX
+#define _ACCFRAME_HXX
+
+#include <swrect.hxx>
+
+#include <sal/types.h>
+#include <tools/string.hxx>
+
+#include <list>
+#include <accfrmobj.hxx>
+
+class SwAccessibleMap;
+class SwFrm;
+class ViewShell;
+namespace sw { namespace access {
+ class SwAccessibleChild;
+}}
+
+// Any method of this class must be called with an acquired solar mutex!
+
+class SwAccessibleFrame
+{
+ SwRect maVisArea;
+ const SwFrm* mpFrm;
+ const sal_Bool mbIsInPagePreview;
+
+protected:
+ // #i77106# - method needs to be called by new class <SwAccessibleTableColHeaders>
+ static sal_Int32 GetChildCount( SwAccessibleMap& rAccMap,
+ const SwRect& rVisArea,
+ const SwFrm *pFrm,
+ sal_Bool bInPagePreview );
+private:
+ static sw::access::SwAccessibleChild GetChild( SwAccessibleMap& rAccMap,
+ const SwRect& rVisArea,
+ const SwFrm& rFrm,
+ sal_Int32& rPos,
+ sal_Bool bInPagePreview);
+
+ static sal_Bool GetChildIndex( SwAccessibleMap& rAccMap,
+ const SwRect& rVisArea,
+ const SwFrm& rFrm,
+ const sw::access::SwAccessibleChild& rChild,
+ sal_Int32& rPos,
+ sal_Bool bInPagePreview );
+
+ static sw::access::SwAccessibleChild GetChildAtPixel( const SwRect& rVisArea,
+ const SwFrm& rFrm,
+ const Point& rPos,
+ sal_Bool bInPagePreview,
+ SwAccessibleMap& rAccMap );
+
+ static void GetChildren( SwAccessibleMap& rAccMap,
+ const SwRect& rVisArea,
+ const SwFrm& rFrm,
+ ::std::list< sw::access::SwAccessibleChild >& rChildren,
+ sal_Bool bInPagePreview );
+
+protected:
+
+ sal_Bool IsEditable( ViewShell *pVSh ) const;
+
+ sal_Bool IsOpaque( ViewShell *pVSh ) const;
+
+ sal_Bool IsShowing( const SwAccessibleMap& rAccMap,
+ const sw::access::SwAccessibleChild& rFrmOrObj ) const;
+ inline sal_Bool IsShowing( const SwRect& rFrm ) const;
+ inline sal_Bool IsShowing( const SwAccessibleMap& rAccMap ) const;
+
+ inline sal_Bool IsInPagePreview() const
+ {
+ return mbIsInPagePreview;
+ }
+
+ inline void ClearFrm()
+ {
+ mpFrm = 0;
+ }
+
+ SwAccessibleFrame( const SwRect& rVisArea,
+ const SwFrm *pFrm,
+ sal_Bool bIsPagePreview );
+ virtual ~SwAccessibleFrame();
+
+public:
+ // Return the SwFrm this context is attached to.
+ const SwFrm* GetFrm() const { return mpFrm; };
+
+ static const SwFrm* GetParent( const sw::access::SwAccessibleChild& rFrmOrObj,
+ sal_Bool bInPagePreview );
+
+ sal_Int32 GetChildIndex( SwAccessibleMap& rAccMap,
+ const sw::access::SwAccessibleChild& rChild ) const;
+
+protected:
+
+ // Return the bounding box of the frame clipped to the vis area. If
+ // no frame is specified, use this' frame.
+ SwRect GetBounds( const SwAccessibleMap& rAccMap,
+ const SwFrm *pFrm = 0 );
+
+ // Return the upper that has a context attached. This might be
+ // another one than the immediate upper.
+ inline const SwFrm *GetParent() const;
+
+ // Return the lower count or the nth lower, there the lowers have a
+ // not be same one as the SwFrm's lowers
+ sal_Int32 GetChildCount( SwAccessibleMap& rAccMap ) const;
+ sw::access::SwAccessibleChild GetChild( SwAccessibleMap& rAccMap,
+ sal_Int32 nPos ) const;
+ sw::access::SwAccessibleChild GetChildAtPixel( const Point& rPos,
+ SwAccessibleMap& rAccMap ) const;
+ void GetChildren( SwAccessibleMap& rAccMap,
+ ::std::list< sw::access::SwAccessibleChild >& rChildren ) const;
+
+ inline void SetVisArea( const SwRect& rNewVisArea )
+ {
+ maVisArea = rNewVisArea;
+ }
+
+ inline const SwRect& GetVisArea() const
+ {
+ return maVisArea;
+ }
+
+
+ String GetFormattedPageNumber() const;
+};
+
+inline sal_Bool SwAccessibleFrame::IsShowing( const SwRect& rFrm ) const
+{
+ return rFrm.IsOver( maVisArea );
+}
+
+inline sal_Bool SwAccessibleFrame::IsShowing( const SwAccessibleMap& rAccMap ) const
+{
+ sw::access::SwAccessibleChild aFrmOrObj( GetFrm() );
+ return IsShowing( rAccMap, aFrmOrObj );
+}
+
+inline const SwFrm *SwAccessibleFrame::GetParent() const
+{
+ sw::access::SwAccessibleChild aFrmOrObj( GetFrm() );
+ return GetParent( aFrmOrObj, IsInPagePreview() );
+}
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/access/accframebase.cxx b/sw/source/core/access/accframebase.cxx
new file mode 100644
index 000000000000..f96b050260b6
--- /dev/null
+++ b/sw/source/core/access/accframebase.cxx
@@ -0,0 +1,282 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+ /*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+
+#include <com/sun/star/accessibility/AccessibleStateType.hpp>
+#include <com/sun/star/accessibility/AccessibleEventId.hpp>
+#include <unotools/accessiblestatesethelper.hxx>
+#include <osl/mutex.hxx>
+#include <vcl/svapp.hxx>
+#include <vcl/window.hxx>
+#include <frmfmt.hxx>
+#include <ndnotxt.hxx>
+#include <flyfrm.hxx>
+#include <cntfrm.hxx>
+#include <fmtcntnt.hxx>
+#include <ndindex.hxx>
+#include "fesh.hxx"
+#include <hints.hxx>
+#include "accmap.hxx"
+#include "accframebase.hxx"
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::accessibility;
+using ::rtl::OUString;
+
+sal_Bool SwAccessibleFrameBase::IsSelected()
+{
+ sal_Bool bRet = sal_False;
+
+ DBG_ASSERT( GetMap(), "no map?" );
+ const ViewShell *pVSh = GetMap()->GetShell();
+ DBG_ASSERT( pVSh, "no shell?" );
+ if( pVSh->ISA( SwFEShell ) )
+ {
+ const SwFEShell *pFESh = static_cast< const SwFEShell * >( pVSh );
+ const SwFrm *pFlyFrm = pFESh->GetCurrFlyFrm();
+ if( pFlyFrm == GetFrm() )
+ bRet = sal_True;
+ }
+
+ return bRet;
+}
+
+void SwAccessibleFrameBase::GetStates(
+ ::utl::AccessibleStateSetHelper& rStateSet )
+{
+ SwAccessibleContext::GetStates( rStateSet );
+
+ const ViewShell *pVSh = GetMap()->GetShell();
+ DBG_ASSERT( pVSh, "no shell?" );
+ sal_Bool bSelectable = pVSh->ISA( SwFEShell );
+
+ // SELECTABLE
+ if( bSelectable )
+ rStateSet.AddState( AccessibleStateType::SELECTABLE );
+
+ // FOCUSABLE
+ if( bSelectable )
+ rStateSet.AddState( AccessibleStateType::FOCUSABLE );
+
+ // SELECTED and FOCUSED
+ if( IsSelected() )
+ {
+ rStateSet.AddState( AccessibleStateType::SELECTED );
+ OSL_ENSURE( bIsSelected, "bSelected out of sync" );
+ ::rtl::Reference < SwAccessibleContext > xThis( this );
+ GetMap()->SetCursorContext( xThis );
+
+ Window *pWin = GetWindow();
+ if( pWin && pWin->HasFocus() )
+ rStateSet.AddState( AccessibleStateType::FOCUSED );
+ }
+}
+
+
+sal_uInt8 SwAccessibleFrameBase::GetNodeType( const SwFlyFrm *pFlyFrm )
+{
+ sal_uInt8 nType = ND_TEXTNODE;
+ if( pFlyFrm->Lower() )
+ {
+ if( pFlyFrm->Lower()->IsNoTxtFrm() )
+ {
+ const SwCntntFrm *pCntFrm =
+ static_cast<const SwCntntFrm *>( pFlyFrm->Lower() );
+ nType = pCntFrm->GetNode()->GetNodeType();
+ }
+ }
+ else
+ {
+ const SwFrmFmt *pFrmFmt = pFlyFrm->GetFmt();
+ const SwFmtCntnt& rCntnt = pFrmFmt->GetCntnt();
+ const SwNodeIndex *pNdIdx = rCntnt.GetCntntIdx();
+ if( pNdIdx )
+ {
+ const SwCntntNode *pCNd =
+ (pNdIdx->GetNodes())[pNdIdx->GetIndex()+1]->GetCntntNode();
+ if( pCNd )
+ nType = pCNd->GetNodeType();
+ }
+ }
+
+ return nType;
+}
+
+SwAccessibleFrameBase::SwAccessibleFrameBase(
+ SwAccessibleMap* pInitMap,
+ sal_Int16 nInitRole,
+ const SwFlyFrm* pFlyFrm ) :
+ SwAccessibleContext( pInitMap, nInitRole, pFlyFrm ),
+ bIsSelected( sal_False )
+{
+ SolarMutexGuard aGuard;
+
+ const SwFrmFmt *pFrmFmt = pFlyFrm->GetFmt();
+ const_cast< SwFrmFmt * >( pFrmFmt )->Add( this );
+
+ SetName( pFrmFmt->GetName() );
+
+ bIsSelected = IsSelected();
+}
+
+void SwAccessibleFrameBase::_InvalidateCursorPos()
+{
+ sal_Bool bNewSelected = IsSelected();
+ sal_Bool bOldSelected;
+
+ {
+ osl::MutexGuard aGuard( aMutex );
+ bOldSelected = bIsSelected;
+ bIsSelected = bNewSelected;
+ }
+
+ if( bNewSelected )
+ {
+ // remember that object as the one that has the caret. This is
+ // neccessary to notify that object if the cursor leaves it.
+ ::rtl::Reference < SwAccessibleContext > xThis( this );
+ GetMap()->SetCursorContext( xThis );
+ }
+
+ if( bOldSelected != bNewSelected )
+ {
+ Window *pWin = GetWindow();
+ if( pWin && pWin->HasFocus() && bNewSelected )
+ FireStateChangedEvent( AccessibleStateType::FOCUSED, bNewSelected );
+ FireStateChangedEvent( AccessibleStateType::SELECTED, bNewSelected );
+ if( pWin && pWin->HasFocus() && !bNewSelected )
+ FireStateChangedEvent( AccessibleStateType::FOCUSED, bNewSelected );
+
+ uno::Reference< XAccessible > xParent( GetWeakParent() );
+ if( xParent.is() )
+ {
+ SwAccessibleContext *pAcc =
+ static_cast <SwAccessibleContext *>( xParent.get() );
+
+ AccessibleEventObject aEvent;
+ aEvent.EventId = AccessibleEventId::SELECTION_CHANGED;
+ pAcc->FireAccessibleEvent( aEvent );
+ }
+ }
+}
+
+void SwAccessibleFrameBase::_InvalidateFocus()
+{
+ Window *pWin = GetWindow();
+ if( pWin )
+ {
+ sal_Bool bSelected;
+
+ {
+ osl::MutexGuard aGuard( aMutex );
+ bSelected = bIsSelected;
+ }
+ OSL_ENSURE( bSelected, "focus object should be selected" );
+
+ FireStateChangedEvent( AccessibleStateType::FOCUSED,
+ pWin->HasFocus() && bSelected );
+ }
+}
+
+sal_Bool SwAccessibleFrameBase::HasCursor()
+{
+ osl::MutexGuard aGuard( aMutex );
+ return bIsSelected;
+}
+
+
+SwAccessibleFrameBase::~SwAccessibleFrameBase()
+{
+}
+
+void SwAccessibleFrameBase::Modify( const SfxPoolItem* pOld, const SfxPoolItem *pNew)
+{
+ sal_uInt16 nWhich = pOld ? pOld->Which() : pNew ? pNew->Which() : 0 ;
+ const SwFlyFrm *pFlyFrm = static_cast< const SwFlyFrm * >( GetFrm() );
+ switch( nWhich )
+ {
+ case RES_NAME_CHANGED:
+ if( pFlyFrm )
+ {
+ const SwFrmFmt *pFrmFmt = pFlyFrm->GetFmt();
+ OSL_ENSURE( pFrmFmt == GetRegisteredIn(), "invalid frame" );
+
+ OUString sOldName( GetName() );
+ OSL_ENSURE( !pOld ||
+ static_cast < const SwStringMsgPoolItem * >( pOld )->GetString() == String( sOldName ),
+ "invalid old name" );
+
+ const String& rNewName = pFrmFmt->GetName();
+ SetName( rNewName );
+ OSL_ENSURE( !pNew ||
+ static_cast < const SwStringMsgPoolItem * >( pNew )->GetString() == rNewName,
+ "invalid new name" );
+
+ if( sOldName != GetName() )
+ {
+ AccessibleEventObject aEvent;
+ aEvent.EventId = AccessibleEventId::NAME_CHANGED;
+ aEvent.OldValue <<= sOldName;
+ aEvent.NewValue <<= GetName();
+ FireAccessibleEvent( aEvent );
+ }
+ }
+ break;
+ case RES_OBJECTDYING:
+ // mba: it seems that this class intentionally does not call code in base class SwClient
+ if( GetRegisteredIn() ==
+ static_cast< SwModify *>( static_cast< const SwPtrMsgPoolItem * >( pOld )->pObject ) )
+ GetRegisteredInNonConst()->Remove( this );
+ break;
+
+ case RES_FMT_CHG:
+ if( static_cast< const SwFmtChg * >(pNew)->pChangedFmt == GetRegisteredIn() &&
+ static_cast< const SwFmtChg * >(pOld)->pChangedFmt->IsFmtInDTOR() )
+ GetRegisteredInNonConst()->Remove( this );
+ break;
+
+ default:
+ // mba: former call to base class method removed as it is meant to handle only RES_OBJECTDYING
+ break;
+ }
+}
+
+void SwAccessibleFrameBase::Dispose( sal_Bool bRecursive )
+{
+ SolarMutexGuard aGuard;
+
+ if( GetRegisteredIn() )
+ GetRegisteredInNonConst()->Remove( this );
+
+ SwAccessibleContext::Dispose( bRecursive );
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/access/accframebase.hxx b/sw/source/core/access/accframebase.hxx
new file mode 100644
index 000000000000..8ac7f2e2e0c6
--- /dev/null
+++ b/sw/source/core/access/accframebase.hxx
@@ -0,0 +1,74 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+#ifndef _ACCFRAMEBASE_HXX
+#define _ACCFRAMEBASE_HXX
+
+#include <acccontext.hxx>
+
+#include <calbck.hxx>
+
+class SwFlyFrm;
+
+class SwAccessibleFrameBase : public SwAccessibleContext,
+ public SwClient
+{
+ sal_Bool bIsSelected; // protected by base class mutex
+
+ sal_Bool IsSelected();
+
+protected:
+
+ // Set states for getAccessibleStateSet.
+ // This drived class additionaly sets SELECTABLE(1), SELECTED(+),
+ // FOCUSABLE(1) and FOCUSED(+)
+ virtual void GetStates( ::utl::AccessibleStateSetHelper& rStateSet );
+
+ virtual void _InvalidateCursorPos();
+ virtual void _InvalidateFocus();
+
+ virtual ~SwAccessibleFrameBase();
+ virtual void Modify( const SfxPoolItem* pOld, const SfxPoolItem *pNew);
+
+public:
+
+ SwAccessibleFrameBase( SwAccessibleMap* pInitMap,
+ sal_Int16 nInitRole,
+ const SwFlyFrm *pFlyFrm );
+
+ virtual sal_Bool HasCursor(); // required by map to remember that object
+
+ static sal_uInt8 GetNodeType( const SwFlyFrm *pFlyFrm );
+
+ // The object is not visible an longer and should be destroyed
+ virtual void Dispose( sal_Bool bRecursive = sal_False );
+};
+
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/access/accfrmobj.cxx b/sw/source/core/access/accfrmobj.cxx
new file mode 100644
index 000000000000..6b3f73c713b3
--- /dev/null
+++ b/sw/source/core/access/accfrmobj.cxx
@@ -0,0 +1,430 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+ /*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+#include <accfrmobj.hxx>
+
+#include <accmap.hxx>
+#include <acccontext.hxx>
+
+#include <viewsh.hxx>
+#include <rootfrm.hxx>
+#include <flyfrm.hxx>
+#include <pagefrm.hxx>
+#include <cellfrm.hxx>
+#include <swtable.hxx>
+#include <dflyobj.hxx>
+#include <frmfmt.hxx>
+#include <fmtanchr.hxx>
+#include <dcontact.hxx>
+
+#include <vcl/window.hxx>
+
+namespace css = ::com::sun::star;
+
+namespace sw { namespace access {
+
+SwAccessibleChild::SwAccessibleChild()
+ : mpFrm( 0 )
+ , mpDrawObj( 0 )
+ , mpWindow( 0 )
+{}
+
+SwAccessibleChild::SwAccessibleChild( const SdrObject* pDrawObj )
+ : mpFrm( 0 )
+ , mpDrawObj( 0 )
+ , mpWindow( 0 )
+{
+ Init( pDrawObj );
+}
+
+SwAccessibleChild::SwAccessibleChild( const SwFrm* pFrm )
+ : mpFrm( 0 )
+ , mpDrawObj( 0 )
+ , mpWindow( 0 )
+{
+ Init( pFrm );
+}
+
+SwAccessibleChild::SwAccessibleChild( Window* pWindow )
+ : mpFrm( 0 )
+ , mpDrawObj( 0 )
+ , mpWindow( 0 )
+{
+ Init( pWindow );
+}
+
+
+SwAccessibleChild::SwAccessibleChild( const SwFrm* pFrm,
+ const SdrObject* pDrawObj,
+ Window* pWindow )
+{
+ if ( pFrm )
+ {
+ Init( pFrm );
+ }
+ else if ( pDrawObj )
+ {
+ Init( pDrawObj );
+ }
+ else if ( pWindow )
+ {
+ Init( pWindow );
+ }
+ OSL_ENSURE( (!pFrm || pFrm == mpFrm) &&
+ (!pDrawObj || pDrawObj == mpDrawObj) &&
+ (!pWindow || pWindow == mpWindow),
+ "invalid frame/object/window combination" );
+
+}
+
+void SwAccessibleChild::Init( const SdrObject* pDrawObj )
+{
+ mpDrawObj = pDrawObj;
+ mpFrm = mpDrawObj && mpDrawObj->ISA(SwVirtFlyDrawObj)
+ ? static_cast < const SwVirtFlyDrawObj * >( mpDrawObj )->GetFlyFrm()
+ : 0;
+ mpWindow = 0;
+}
+
+void SwAccessibleChild::Init( const SwFrm* pFrm )
+{
+ mpFrm = pFrm;
+ mpDrawObj = mpFrm && mpFrm->IsFlyFrm()
+ ? static_cast < const SwFlyFrm * >( mpFrm )->GetVirtDrawObj()
+ : 0;
+ mpWindow = 0;
+}
+
+void SwAccessibleChild::Init( Window* pWindow )
+{
+ mpWindow = pWindow;
+ mpFrm = 0;
+ mpDrawObj = 0;
+}
+
+bool SwAccessibleChild::IsAccessible( sal_Bool bPagePreview ) const
+{
+ bool bRet( false );
+
+ if ( mpFrm )
+ {
+ bRet = mpFrm->IsAccessibleFrm() &&
+ ( !mpFrm->IsCellFrm() ||
+ static_cast<const SwCellFrm *>( mpFrm )->GetTabBox()->GetSttNd() != 0 ) &&
+ !mpFrm->IsInCoveredCell() &&
+ ( bPagePreview ||
+ !mpFrm->IsPageFrm() );
+ }
+ else if ( mpDrawObj )
+ {
+ bRet = true;
+ }
+ else if ( mpWindow )
+ {
+ bRet = true;
+ }
+
+ return bRet;
+}
+
+bool SwAccessibleChild::IsBoundAsChar() const
+{
+ bool bRet( false );
+
+ if ( mpFrm )
+ {
+ bRet = mpFrm->IsFlyFrm() &&
+ static_cast< const SwFlyFrm *>(mpFrm)->IsFlyInCntFrm();
+ }
+ else if ( mpDrawObj )
+ {
+ const SwFrmFmt* mpFrmFmt = ::FindFrmFmt( mpDrawObj );
+ bRet = mpFrmFmt
+ ? (FLY_AS_CHAR == mpFrmFmt->GetAnchor().GetAnchorId())
+ : false;
+ }
+ else if ( mpWindow )
+ {
+ bRet = false;
+ }
+
+ return bRet;
+}
+
+SwAccessibleChild::SwAccessibleChild( const SwAccessibleChild& r )
+ : mpFrm( r.mpFrm )
+ , mpDrawObj( r.mpDrawObj )
+ , mpWindow( r.mpWindow )
+{}
+
+SwAccessibleChild& SwAccessibleChild::operator=( const SwAccessibleChild& r )
+{
+ mpDrawObj = r.mpDrawObj;
+ mpFrm = r.mpFrm;
+ mpWindow = r.mpWindow;
+
+ return *this;
+}
+
+SwAccessibleChild& SwAccessibleChild::operator=( const SdrObject* pDrawObj )
+{
+ Init( pDrawObj );
+ return *this;
+}
+
+SwAccessibleChild& SwAccessibleChild::operator=( const SwFrm* pFrm )
+{
+ Init( pFrm );
+ return *this;
+}
+
+SwAccessibleChild& SwAccessibleChild::operator=( Window* pWindow )
+{
+ Init( pWindow );
+ return *this;
+}
+
+bool SwAccessibleChild::operator==( const SwAccessibleChild& r ) const
+{
+ return mpFrm == r.mpFrm &&
+ mpDrawObj == r.mpDrawObj &&
+ mpWindow == r.mpWindow;
+}
+
+bool SwAccessibleChild::IsValid() const
+{
+ return mpFrm != 0 ||
+ mpDrawObj != 0 ||
+ mpWindow != 0;
+}
+
+const SdrObject* SwAccessibleChild::GetDrawObject() const
+{
+ return mpDrawObj;
+}
+
+const SwFrm *SwAccessibleChild::GetSwFrm() const
+{
+ return mpFrm;
+}
+
+Window* SwAccessibleChild::GetWindow() const
+{
+ return mpWindow;
+}
+
+bool SwAccessibleChild::IsVisibleChildrenOnly() const
+{
+ bool bRet( false );
+
+ if ( !mpFrm )
+ {
+ bRet = true;
+ }
+ else
+ {
+ bRet = mpFrm->IsRootFrm() ||
+ !( mpFrm->IsTabFrm() ||
+ mpFrm->IsInTab() ||
+ ( IsBoundAsChar() &&
+ static_cast<const SwFlyFrm*>(mpFrm)->GetAnchorFrm()->IsInTab() ) );
+ }
+
+ return bRet;
+}
+
+SwRect SwAccessibleChild::GetBox( const SwAccessibleMap& rAccMap ) const
+{
+ SwRect aBox;
+
+ if ( mpFrm )
+ {
+ if ( mpFrm->IsPageFrm() &&
+ static_cast< const SwPageFrm * >( mpFrm )->IsEmptyPage() )
+ {
+ aBox = SwRect( mpFrm->Frm().Left(), mpFrm->Frm().Top()-1, 1, 1 );
+ }
+ else if ( mpFrm->IsTabFrm() )
+ {
+ aBox = SwRect( mpFrm->Frm() );
+ aBox.Intersection( mpFrm->GetUpper()->Frm() );
+ }
+ else
+ {
+ aBox = mpFrm->Frm();
+ }
+ }
+ else if( mpDrawObj )
+ {
+ aBox = SwRect( mpDrawObj->GetCurrentBoundRect() );
+ }
+ else if ( mpWindow )
+ {
+ aBox = SwRect( rAccMap.GetShell()->GetWin()->PixelToLogic(
+ Rectangle( mpWindow->GetPosPixel(),
+ mpWindow->GetSizePixel() ) ) );
+}
+
+ return aBox;
+}
+
+SwRect SwAccessibleChild::GetBounds( const SwAccessibleMap& rAccMap ) const
+{
+ SwRect aBound;
+
+ if( mpFrm )
+ {
+ if( mpFrm->IsPageFrm() &&
+ static_cast< const SwPageFrm * >( mpFrm )->IsEmptyPage() )
+ {
+ aBound = SwRect( mpFrm->Frm().Left(), mpFrm->Frm().Top()-1, 0, 0 );
+ }
+ else
+ aBound = mpFrm->PaintArea();
+ }
+ else if( mpDrawObj )
+ {
+ aBound = GetBox( rAccMap );
+ }
+ else if ( mpWindow )
+ {
+ aBound = GetBox( rAccMap );
+ }
+
+ return aBound;
+}
+
+bool SwAccessibleChild::AlwaysIncludeAsChild() const
+{
+ bool bAlwaysIncludedAsChild( false );
+
+ if ( mpWindow )
+ {
+ bAlwaysIncludedAsChild = true;
+ }
+
+ return bAlwaysIncludedAsChild;
+}
+
+const SwFrm* SwAccessibleChild::GetParent( const sal_Bool bInPagePreview ) const
+{
+ const SwFrm* pParent( 0 );
+
+ if ( mpFrm )
+ {
+ if( mpFrm->IsFlyFrm() )
+ {
+ const SwFlyFrm* pFly = static_cast< const SwFlyFrm *>( mpFrm );
+ if( pFly->IsFlyInCntFrm() )
+ {
+ // For FLY_AS_CHAR the parent is the anchor
+ pParent = pFly->GetAnchorFrm();
+ OSL_ENSURE( SwAccessibleChild( pParent ).IsAccessible( bInPagePreview ),
+ "parent is not accessible" );
+ }
+ else
+ {
+ // In any other case the parent is the root frm
+ // (in page preview, the page frame)
+ if( bInPagePreview )
+ pParent = pFly->FindPageFrm();
+ else
+ pParent = pFly->getRootFrm();
+ }
+ }
+ else
+ {
+ SwAccessibleChild aUpper( mpFrm->GetUpper() );
+ while( aUpper.GetSwFrm() && !aUpper.IsAccessible(bInPagePreview) )
+ {
+ aUpper = aUpper.GetSwFrm()->GetUpper();
+ }
+ pParent = aUpper.GetSwFrm();
+ }
+ }
+ else if( mpDrawObj )
+ {
+ const SwDrawContact *pContact =
+ static_cast< const SwDrawContact* >( GetUserCall( mpDrawObj ) );
+ OSL_ENSURE( pContact, "sdr contact is missing" );
+ if( pContact )
+ {
+ const SwFrmFmt *pFrmFmt = pContact->GetFmt();
+ OSL_ENSURE( pFrmFmt, "frame format is missing" );
+ if( pFrmFmt && FLY_AS_CHAR == pFrmFmt->GetAnchor().GetAnchorId() )
+ {
+ // For FLY_AS_CHAR the parent is the anchor
+ pParent = pContact->GetAnchorFrm();
+ OSL_ENSURE( SwAccessibleChild( pParent ).IsAccessible( bInPagePreview ),
+ "parent is not accessible" );
+
+ }
+ else
+ {
+ // In any other case the parent is the root frm
+ if( bInPagePreview )
+ pParent = pContact->GetAnchorFrm()->FindPageFrm();
+ else
+ pParent = pContact->GetAnchorFrm()->getRootFrm();
+ }
+ }
+ }
+ else if ( mpWindow )
+ {
+ css::uno::Reference < css::accessibility::XAccessible > xAcc =
+ mpWindow->GetAccessible();
+ if ( xAcc.is() )
+ {
+ css::uno::Reference < css::accessibility::XAccessibleContext > xAccContext =
+ xAcc->getAccessibleContext();
+ if ( xAccContext.is() )
+ {
+ css::uno::Reference < css::accessibility::XAccessible > xAccParent =
+ xAccContext->getAccessibleParent();
+ if ( xAccParent.is() )
+ {
+ SwAccessibleContext* pAccParentImpl =
+ dynamic_cast< SwAccessibleContext *>( xAccParent.get() );
+ if ( pAccParentImpl )
+ {
+ pParent = pAccParentImpl->GetFrm();
+ }
+ }
+ }
+ }
+ }
+
+ return pParent;
+}
+
+} } // eof of namespace sw::access
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/access/accfrmobj.hxx b/sw/source/core/access/accfrmobj.hxx
new file mode 100644
index 000000000000..8b196711277e
--- /dev/null
+++ b/sw/source/core/access/accfrmobj.hxx
@@ -0,0 +1,95 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+#ifndef _ACCFRMOBJ_HXX
+#define _ACCFRMOBJ_HXX
+
+#include <sal/types.h>
+
+class SwAccessibleMap;
+class SwFrm;
+class SdrObject;
+class Window;
+class SwRect;
+
+namespace sw { namespace access {
+
+class SwAccessibleChild
+{
+ public:
+ SwAccessibleChild();
+ explicit SwAccessibleChild( const SdrObject* pDrawObj );
+ explicit SwAccessibleChild( const SwFrm* pFrm );
+ explicit SwAccessibleChild( Window* pWindow );
+ SwAccessibleChild( const SwFrm* pFrm,
+ const SdrObject* pDrawObj,
+ Window* pWindow );
+
+ SwAccessibleChild( const SwAccessibleChild& r );
+ SwAccessibleChild& operator=( const SwAccessibleChild& r );
+
+ SwAccessibleChild& operator=( const SdrObject* pDrawObj );
+ SwAccessibleChild& operator=( const SwFrm* pFrm );
+ SwAccessibleChild& operator=( Window* pWindow );
+
+ bool operator==( const SwAccessibleChild& r ) const;
+
+ bool IsValid() const;
+
+ const SwFrm* GetSwFrm() const;
+ const SdrObject* GetDrawObject() const;
+ Window* GetWindow() const;
+
+ const SwFrm* GetParent( const sal_Bool bInPagePreview ) const;
+
+ bool IsAccessible( sal_Bool bPagePreview ) const;
+ bool IsBoundAsChar() const;
+
+ bool IsVisibleChildrenOnly() const;
+ SwRect GetBox( const SwAccessibleMap& rAccMap ) const;
+ SwRect GetBounds( const SwAccessibleMap& rAccMap ) const;
+
+ /** indicating, if accessible child is included even, if the corresponding
+ object is not visible. */
+ bool AlwaysIncludeAsChild() const;
+
+ private:
+ const SwFrm* mpFrm;
+ const SdrObject* mpDrawObj;
+ Window* mpWindow;
+
+ void Init( const SdrObject* pDrawObj );
+ void Init( const SwFrm* pFrm );
+ void Init( Window* pWindow );
+};
+
+
+} } // eof of namespace sw::access
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/access/accfrmobjmap.cxx b/sw/source/core/access/accfrmobjmap.cxx
new file mode 100644
index 000000000000..e7fd8644da77
--- /dev/null
+++ b/sw/source/core/access/accfrmobjmap.cxx
@@ -0,0 +1,171 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+ /*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+#include <accfrmobjmap.hxx>
+#include <accframe.hxx>
+#include <accmap.hxx>
+#include <acccontext.hxx>
+
+#include <viewsh.hxx>
+#include <doc.hxx>
+#include <frmfmt.hxx>
+#include <pagefrm.hxx>
+#include <txtfrm.hxx>
+#include <node.hxx>
+#include <sortedobjs.hxx>
+#include <anchoredobject.hxx>
+
+#include <svx/svdobj.hxx>
+
+using namespace sw::access;
+
+SwAccessibleChildMap::SwAccessibleChildMap( const SwRect& rVisArea,
+ const SwFrm& rFrm,
+ SwAccessibleMap& rAccMap )
+ : nHellId( rAccMap.GetShell()->GetDoc()->GetHellId() )
+ , nControlsId( rAccMap.GetShell()->GetDoc()->GetControlsId() )
+{
+ const bool bVisibleChildrenOnly = SwAccessibleChild( &rFrm ).IsVisibleChildrenOnly();
+
+ sal_uInt32 nPos = 0;
+ SwAccessibleChild aLower( rFrm.GetLower() );
+ while( aLower.GetSwFrm() )
+ {
+ if ( !bVisibleChildrenOnly ||
+ aLower.AlwaysIncludeAsChild() ||
+ aLower.GetBox( rAccMap ).IsOver( rVisArea ) )
+ {
+ insert( nPos++, SwAccessibleChildMapKey::TEXT, aLower );
+ }
+
+ aLower = aLower.GetSwFrm()->GetNext();
+ }
+
+ if ( rFrm.IsPageFrm() )
+ {
+ OSL_ENSURE( bVisibleChildrenOnly, "page frame within tab frame???" );
+ const SwPageFrm *pPgFrm =
+ static_cast< const SwPageFrm * >( &rFrm );
+ const SwSortedObjs *pObjs = pPgFrm->GetSortedObjs();
+ if ( pObjs )
+ {
+ for( sal_uInt16 i=0; i<pObjs->Count(); i++ )
+ {
+ aLower = (*pObjs)[i]->GetDrawObj();
+ if ( aLower.GetBox( rAccMap ).IsOver( rVisArea ) )
+ {
+ insert( aLower.GetDrawObject(), aLower );
+ }
+ }
+ }
+ }
+ else if( rFrm.IsTxtFrm() )
+ {
+ const SwSortedObjs *pObjs = rFrm.GetDrawObjs();
+ if ( pObjs )
+ {
+ for( sal_uInt16 i=0; i<pObjs->Count(); i++ )
+ {
+ aLower = (*pObjs)[i]->GetDrawObj();
+ if ( aLower.IsBoundAsChar() &&
+ ( !bVisibleChildrenOnly ||
+ aLower.AlwaysIncludeAsChild() ||
+ aLower.GetBox( rAccMap ).IsOver( rVisArea ) ) )
+ {
+ insert( aLower.GetDrawObject(), aLower );
+ }
+ }
+ }
+
+ {
+ ::rtl::Reference < SwAccessibleContext > xAccImpl =
+ rAccMap.GetContextImpl( &rFrm, sal_False );
+ if( xAccImpl.is() )
+ {
+ SwAccessibleContext* pAccImpl = xAccImpl.get();
+ if ( pAccImpl &&
+ pAccImpl->HasAdditionalAccessibleChildren() )
+ {
+ std::vector< Window* >* pAdditionalChildren =
+ new std::vector< Window* >();
+ pAccImpl->GetAdditionalAccessibleChildren( pAdditionalChildren );
+
+ sal_Int32 nCounter( 0 );
+ for ( std::vector< Window* >::iterator aIter = pAdditionalChildren->begin();
+ aIter != pAdditionalChildren->end();
+ ++aIter )
+ {
+ aLower = (*aIter);
+ insert( ++nCounter, SwAccessibleChildMapKey::XWINDOW, aLower );
+ }
+
+ delete pAdditionalChildren;
+ }
+ }
+ }
+ }
+}
+
+::std::pair< SwAccessibleChildMap::iterator, bool > SwAccessibleChildMap::insert(
+ const sal_uInt32 nPos,
+ const SwAccessibleChildMapKey::LayerId eLayerId,
+ const SwAccessibleChild& rLower )
+{
+ SwAccessibleChildMapKey aKey( eLayerId, nPos );
+ value_type aEntry( aKey, rLower );
+ return _SwAccessibleChildMap::insert( aEntry );
+}
+
+::std::pair< SwAccessibleChildMap::iterator, bool > SwAccessibleChildMap::insert(
+ const SdrObject *pObj,
+ const SwAccessibleChild& rLower )
+{
+ const SdrLayerID nLayer = pObj->GetLayer();
+ SwAccessibleChildMapKey::LayerId eLayerId =
+ (nHellId == nLayer)
+ ? SwAccessibleChildMapKey::HELL
+ : ( (nControlsId == nLayer)
+ ? SwAccessibleChildMapKey::CONTROLS
+ : SwAccessibleChildMapKey::HEAVEN );
+ SwAccessibleChildMapKey aKey( eLayerId, pObj->GetOrdNum() );
+ value_type aEntry( aKey, rLower );
+ return _SwAccessibleChildMap::insert( aEntry );
+}
+
+/* static */ sal_Bool SwAccessibleChildMap::IsSortingRequired( const SwFrm& rFrm )
+{
+ return ( rFrm.IsPageFrm() &&
+ static_cast< const SwPageFrm& >( rFrm ).GetSortedObjs() ) ||
+ ( rFrm.IsTxtFrm() &&
+ rFrm.GetDrawObjs() );
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/access/accfrmobjmap.hxx b/sw/source/core/access/accfrmobjmap.hxx
new file mode 100644
index 000000000000..441202e6acb9
--- /dev/null
+++ b/sw/source/core/access/accfrmobjmap.hxx
@@ -0,0 +1,98 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+#ifndef _ACCFRMOBJMAP_HXX
+#define _ACCFRMOBJMAP_HXX
+
+#include <accfrmobj.hxx>
+
+#include <svx/svdtypes.hxx>
+
+#include <map>
+
+class SwAccessibleMap;
+class SwDoc;
+class SwRect;
+class SwFrm;
+class SdrObject;
+
+class SwAccessibleChildMapKey
+{
+public:
+ enum LayerId { INVALID, HELL, TEXT, HEAVEN, CONTROLS, XWINDOW };
+
+ inline SwAccessibleChildMapKey()
+ : eLayerId( INVALID )
+ , nOrdNum( 0 )
+ {}
+
+ inline SwAccessibleChildMapKey( LayerId eId, sal_uInt32 nOrd )
+ : eLayerId( eId )
+ , nOrdNum( nOrd )
+ {}
+
+ inline bool operator()( const SwAccessibleChildMapKey& r1,
+ const SwAccessibleChildMapKey& r2 ) const
+ {
+ return (r1.eLayerId == r2.eLayerId)
+ ? (r1.nOrdNum < r2.nOrdNum)
+ : (r1.eLayerId < r2.eLayerId);
+ }
+
+private:
+
+ LayerId eLayerId;
+ sal_uInt32 nOrdNum;
+
+};
+
+typedef ::std::map < SwAccessibleChildMapKey, sw::access::SwAccessibleChild, SwAccessibleChildMapKey >
+ _SwAccessibleChildMap;
+
+class SwAccessibleChildMap : public _SwAccessibleChildMap
+{
+ const SdrLayerID nHellId;
+ const SdrLayerID nControlsId;
+
+ ::std::pair< iterator, bool > insert( const sal_uInt32 nPos,
+ const SwAccessibleChildMapKey::LayerId eLayerId,
+ const sw::access::SwAccessibleChild& rLower );
+ ::std::pair< iterator, bool > insert( const SdrObject* pObj,
+ const sw::access::SwAccessibleChild& rLower );
+
+public:
+
+ SwAccessibleChildMap( const SwRect& rVisArea,
+ const SwFrm& rFrm,
+ SwAccessibleMap& rAccMap );
+
+ static sal_Bool IsSortingRequired( const SwFrm& rFrm );
+};
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/access/accfrmobjslist.cxx b/sw/source/core/access/accfrmobjslist.cxx
new file mode 100644
index 000000000000..846e06a0435c
--- /dev/null
+++ b/sw/source/core/access/accfrmobjslist.cxx
@@ -0,0 +1,175 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+ /*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+#include <accfrmobjslist.hxx>
+#include <accmap.hxx>
+#include <acccontext.hxx>
+
+#include <pagefrm.hxx>
+#include <sortedobjs.hxx>
+#include <anchoredobject.hxx>
+
+using namespace ::sw::access;
+
+SwAccessibleChildSList_const_iterator::SwAccessibleChildSList_const_iterator(
+ const SwAccessibleChildSList& rLst,
+ SwAccessibleMap& rAccMap )
+ : rList( rLst ),
+ aCurr( rList.GetFrm().GetLower() ),
+ nNextObj( 0 )
+{
+ if( !aCurr.GetSwFrm() )
+ {
+ const SwFrm& rFrm = rList.GetFrm();
+ if( rFrm.IsPageFrm() )
+ {
+ const SwPageFrm& rPgFrm = static_cast< const SwPageFrm& >( rFrm );
+ const SwSortedObjs *pObjs = rPgFrm.GetSortedObjs();
+ if( pObjs && pObjs->Count() )
+ {
+ aCurr = (*pObjs)[nNextObj++]->GetDrawObj();
+ }
+ }
+ else if( rFrm.IsTxtFrm() )
+ {
+ const SwSortedObjs *pObjs = rFrm.GetDrawObjs();
+ if ( pObjs && pObjs->Count() )
+ {
+ aCurr = (*pObjs)[nNextObj++]->GetDrawObj();
+ while( aCurr.IsValid() && !aCurr.IsBoundAsChar() )
+ {
+ aCurr = (nNextObj < pObjs->Count())
+ ? (*pObjs)[nNextObj++]->GetDrawObj()
+ : static_cast< const SdrObject *>( 0 );
+ }
+ }
+ if ( !aCurr.IsValid() )
+ {
+ ::rtl::Reference < SwAccessibleContext > xAccImpl =
+ rAccMap.GetContextImpl( &rFrm, sal_False );
+ if( xAccImpl.is() )
+ {
+ SwAccessibleContext* pAccImpl = xAccImpl.get();
+ aCurr = SwAccessibleChild( pAccImpl->GetAdditionalAccessibleChild( 0 ) );
+ ++nNextObj;
+ }
+ }
+ }
+ }
+
+ if( rList.IsVisibleChildrenOnly() )
+ {
+ // Find the first visible
+ while( aCurr.IsValid() &&
+ !aCurr.AlwaysIncludeAsChild() &&
+ !aCurr.GetBox( rAccMap ).IsOver( rList.GetVisArea() ) )
+ {
+ next();
+ }
+ }
+}
+
+SwAccessibleChildSList_const_iterator& SwAccessibleChildSList_const_iterator::next()
+{
+ bool bNextTaken( true );
+ if( aCurr.GetDrawObject() || aCurr.GetWindow() )
+ {
+ bNextTaken = false;
+ }
+ else if( aCurr.GetSwFrm() )
+ {
+ aCurr = aCurr.GetSwFrm()->GetNext();
+ if( !aCurr.GetSwFrm() )
+ {
+ bNextTaken = false;
+ }
+ }
+
+ if( !bNextTaken )
+ {
+ const SwFrm& rFrm = rList.GetFrm();
+ if( rFrm.IsPageFrm() )
+ {
+ const SwPageFrm& rPgFrm = static_cast< const SwPageFrm& >( rFrm );
+ const SwSortedObjs *pObjs = rPgFrm.GetSortedObjs();
+ aCurr = ( pObjs && nNextObj < pObjs->Count() )
+ ? (*pObjs)[nNextObj++]->GetDrawObj()
+ : static_cast< const SdrObject *>( 0 );
+ }
+ else if( rFrm.IsTxtFrm() )
+ {
+ const SwSortedObjs* pObjs = rFrm.GetDrawObjs();
+ const sal_uInt32 nObjsCount = pObjs ? pObjs->Count() : 0;
+ aCurr = ( pObjs && nNextObj < nObjsCount )
+ ? (*pObjs)[nNextObj++]->GetDrawObj()
+ : static_cast< const SdrObject *>( 0 );
+ while( aCurr.IsValid() && !aCurr.IsBoundAsChar() )
+ {
+ aCurr = ( nNextObj < nObjsCount )
+ ? (*pObjs)[nNextObj++]->GetDrawObj()
+ : static_cast< const SdrObject *>( 0 );
+ }
+ if ( !aCurr.IsValid() )
+ {
+ ::rtl::Reference < SwAccessibleContext > xAccImpl =
+ rList.GetAccMap().GetContextImpl( &rFrm, sal_False );
+ if( xAccImpl.is() )
+ {
+ SwAccessibleContext* pAccImpl = xAccImpl.get();
+ aCurr = SwAccessibleChild( pAccImpl->GetAdditionalAccessibleChild( nNextObj - nObjsCount ) );
+ ++nNextObj;
+ }
+ }
+ }
+ }
+
+ return *this;
+}
+
+SwAccessibleChildSList_const_iterator& SwAccessibleChildSList_const_iterator::next_visible()
+{
+ next();
+ while( aCurr.IsValid() &&
+ !aCurr.AlwaysIncludeAsChild() &&
+ !aCurr.GetBox( rList.GetAccMap() ).IsOver( rList.GetVisArea() ) )
+ {
+ next();
+ }
+
+ return *this;
+}
+
+SwAccessibleChildSList_const_iterator& SwAccessibleChildSList_const_iterator::operator++()
+{
+ return rList.IsVisibleChildrenOnly() ? next_visible() : next();
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/access/accfrmobjslist.hxx b/sw/source/core/access/accfrmobjslist.hxx
new file mode 100644
index 000000000000..78052177fbac
--- /dev/null
+++ b/sw/source/core/access/accfrmobjslist.hxx
@@ -0,0 +1,148 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+#ifndef _ACCFRMOBJSLIST_HXX
+#define _ACCFRMOBJSLIST_HXX
+
+#include <accfrmobj.hxx>
+#include <swrect.hxx>
+
+class SwAccessibleMap;
+
+class SwAccessibleChildSList;
+
+class SwAccessibleChildSList_const_iterator
+{
+private:
+ friend class SwAccessibleChildSList;
+
+ const SwAccessibleChildSList& rList; // The frame we are iterating over
+ sw::access::SwAccessibleChild aCurr; // The current object
+ sal_uInt16 nNextObj; // The index of the current sdr object
+
+ inline SwAccessibleChildSList_const_iterator( const SwAccessibleChildSList& rLst )
+ : rList( rLst )
+ , nNextObj( 0 )
+ {}
+
+ SwAccessibleChildSList_const_iterator( const SwAccessibleChildSList& rLst,
+ SwAccessibleMap& rAccMap );
+
+ SwAccessibleChildSList_const_iterator& next();
+ SwAccessibleChildSList_const_iterator& next_visible();
+
+public:
+
+ inline SwAccessibleChildSList_const_iterator( const SwAccessibleChildSList_const_iterator& rIter )
+ : rList( rIter.rList )
+ , aCurr( rIter.aCurr )
+ , nNextObj( rIter.nNextObj )
+ {}
+
+ inline sal_Bool operator==( const SwAccessibleChildSList_const_iterator& r ) const
+ {
+ return aCurr == r.aCurr;
+ }
+
+ inline sal_Bool operator!=(
+ const SwAccessibleChildSList_const_iterator& r ) const
+ {
+ return !(*this == r);
+ }
+
+ SwAccessibleChildSList_const_iterator& operator++();
+
+ inline const sw::access::SwAccessibleChild& operator*() const
+ {
+ return aCurr;
+ }
+};
+
+// An iterator to iterate over a frame's child in any order
+class SwAccessibleChildSList
+{
+ const SwRect maVisArea;
+ const SwFrm& mrFrm;
+ const sal_Bool mbVisibleChildrenOnly;
+ SwAccessibleMap& mrAccMap;
+
+public:
+
+ typedef SwAccessibleChildSList_const_iterator const_iterator;
+
+ inline SwAccessibleChildSList( const SwFrm& rFrm,
+ SwAccessibleMap& rAccMap )
+ : maVisArea()
+ , mrFrm( rFrm )
+ , mbVisibleChildrenOnly( sal_False )
+ , mrAccMap( rAccMap )
+ {}
+
+ inline SwAccessibleChildSList( const SwRect& rVisArea,
+ const SwFrm& rFrm,
+ SwAccessibleMap& rAccMap )
+ : maVisArea( rVisArea )
+ , mrFrm( rFrm )
+ , mbVisibleChildrenOnly( sw::access::SwAccessibleChild( &rFrm ).IsVisibleChildrenOnly() )
+ , mrAccMap( rAccMap )
+ {
+ }
+
+ inline const_iterator begin() const
+ {
+ return SwAccessibleChildSList_const_iterator( *this, mrAccMap );
+ }
+
+ inline const_iterator end() const
+ {
+ return SwAccessibleChildSList_const_iterator( *this );
+ }
+
+ inline const SwFrm& GetFrm() const
+ {
+ return mrFrm;
+ }
+
+ inline sal_Bool IsVisibleChildrenOnly() const
+ {
+ return mbVisibleChildrenOnly;
+ }
+
+ inline const SwRect& GetVisArea() const
+ {
+ return maVisArea;
+ }
+
+ inline SwAccessibleMap& GetAccMap() const
+ {
+ return mrAccMap;
+ }
+};
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/access/accgraphic.cxx b/sw/source/core/access/accgraphic.cxx
new file mode 100644
index 000000000000..4c389e2f85c1
--- /dev/null
+++ b/sw/source/core/access/accgraphic.cxx
@@ -0,0 +1,100 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+ /*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+
+#include <vcl/svapp.hxx>
+#include <com/sun/star/accessibility/AccessibleRole.hpp>
+#include <com/sun/star/uno/RuntimeException.hpp>
+#include <rtl/uuid.h>
+#include <flyfrm.hxx>
+#include "accgraphic.hxx"
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::accessibility;
+using ::rtl::OUString;
+
+const sal_Char sServiceName[] = "com.sun.star.text.AccessibleTextGraphicObject";
+const sal_Char sImplementationName[] = "com.sun.star.comp.Writer.SwAccessibleGraphic";
+
+SwAccessibleGraphic::SwAccessibleGraphic(
+ SwAccessibleMap* pInitMap,
+ const SwFlyFrm* pFlyFrm ) :
+ SwAccessibleNoTextFrame( pInitMap, AccessibleRole::GRAPHIC, pFlyFrm )
+{
+}
+
+SwAccessibleGraphic::~SwAccessibleGraphic()
+{
+}
+
+OUString SAL_CALL SwAccessibleGraphic::getImplementationName()
+ throw( RuntimeException )
+{
+ return OUString(RTL_CONSTASCII_USTRINGPARAM(sImplementationName));
+}
+
+sal_Bool SAL_CALL SwAccessibleGraphic::supportsService(
+ const ::rtl::OUString& sTestServiceName)
+ throw (uno::RuntimeException)
+{
+ return sTestServiceName.equalsAsciiL( sServiceName,
+ sizeof(sServiceName)-1 ) ||
+ sTestServiceName.equalsAsciiL( sAccessibleServiceName,
+ sizeof(sAccessibleServiceName)-1 );
+}
+
+Sequence< OUString > SAL_CALL SwAccessibleGraphic::getSupportedServiceNames()
+ throw( uno::RuntimeException )
+{
+ Sequence< OUString > aRet(2);
+ OUString* pArray = aRet.getArray();
+ pArray[0] = OUString( RTL_CONSTASCII_USTRINGPARAM(sServiceName) );
+ pArray[1] = OUString( RTL_CONSTASCII_USTRINGPARAM(sAccessibleServiceName) );
+ return aRet;
+}
+
+Sequence< sal_Int8 > SAL_CALL SwAccessibleGraphic::getImplementationId()
+ throw(RuntimeException)
+{
+ SolarMutexGuard aGuard;
+ static Sequence< sal_Int8 > aId( 16 );
+ static sal_Bool bInit = sal_False;
+ if(!bInit)
+ {
+ rtl_createUuid( (sal_uInt8 *)(aId.getArray() ), 0, sal_True );
+ bInit = sal_True;
+ }
+ return aId;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/access/accgraphic.hxx b/sw/source/core/access/accgraphic.hxx
new file mode 100644
index 000000000000..18c0f67b68dc
--- /dev/null
+++ b/sw/source/core/access/accgraphic.hxx
@@ -0,0 +1,72 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+#ifndef _ACCGRAPHIC_HXX
+#define _ACCGRAPHIC_HXX
+#include "accnotextframe.hxx"
+
+class SwAccessibleGraphic : public SwAccessibleNoTextFrame
+{
+
+protected:
+
+ virtual ~SwAccessibleGraphic();
+
+public:
+
+ SwAccessibleGraphic( SwAccessibleMap* pInitMap,
+ const SwFlyFrm *pFlyFrm );
+
+ //===== XServiceInfo ====================================================
+
+ /** Returns an identifier for the implementation of this object.
+ */
+ virtual ::rtl::OUString SAL_CALL
+ getImplementationName (void)
+ throw (::com::sun::star::uno::RuntimeException);
+
+ /** Return whether the specified service is supported by this class.
+ */
+ virtual sal_Bool SAL_CALL
+ supportsService (const ::rtl::OUString& sServiceName)
+ throw (::com::sun::star::uno::RuntimeException);
+
+ /** Returns a list of all supported services. In this case that is just
+ the AccessibleContext service.
+ */
+ virtual ::com::sun::star::uno::Sequence< ::rtl::OUString> SAL_CALL
+ getSupportedServiceNames (void)
+ throw (::com::sun::star::uno::RuntimeException);
+
+ //===== XTypeProvider ====================================================
+ virtual ::com::sun::star::uno::Sequence< sal_Int8 > SAL_CALL getImplementationId( ) throw(::com::sun::star::uno::RuntimeException);
+};
+
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/access/accheaderfooter.cxx b/sw/source/core/access/accheaderfooter.cxx
new file mode 100644
index 000000000000..6472f75e9fe5
--- /dev/null
+++ b/sw/source/core/access/accheaderfooter.cxx
@@ -0,0 +1,146 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+ /*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+
+#include <osl/mutex.hxx>
+#include <com/sun/star/accessibility/AccessibleRole.hpp>
+#include <com/sun/star/accessibility/AccessibleStateType.hpp>
+#include <unotools/accessiblestatesethelper.hxx>
+#include <rtl/uuid.h>
+#include <vcl/svapp.hxx>
+#include <hffrm.hxx>
+#include "accheaderfooter.hxx"
+#include "access.hrc"
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::accessibility;
+using ::rtl::OUString;
+
+const sal_Char sServiceNameHeader[] = "com.sun.star.text.AccessibleHeaderView";
+const sal_Char sServiceNameFooter[] = "com.sun.star.text.AccessibleFooterView";
+const sal_Char sImplementationNameHeader[] = "com.sun.star.comp.Writer.SwAccessibleHeaderView";
+const sal_Char sImplementationNameFooter[] = "com.sun.star.comp.Writer.SwAccessibleFooterView";
+
+SwAccessibleHeaderFooter::SwAccessibleHeaderFooter(
+ SwAccessibleMap* pInitMap,
+ const SwHeaderFrm* pHdFrm ) :
+ SwAccessibleContext( pInitMap, AccessibleRole::HEADER, pHdFrm )
+{
+ SolarMutexGuard aGuard;
+
+ OUString sArg( OUString::valueOf( (sal_Int32)pHdFrm->GetPhyPageNum() ) );
+ SetName( GetResource( STR_ACCESS_HEADER_NAME, &sArg ) );
+}
+
+SwAccessibleHeaderFooter::SwAccessibleHeaderFooter(
+ SwAccessibleMap* pInitMap,
+ const SwFooterFrm* pFtFrm ) :
+ SwAccessibleContext( pInitMap, AccessibleRole::FOOTER, pFtFrm )
+{
+ SolarMutexGuard aGuard;
+
+ OUString sArg( OUString::valueOf( (sal_Int32)pFtFrm->GetPhyPageNum() ) );
+ SetName( GetResource( STR_ACCESS_FOOTER_NAME, &sArg ) );
+}
+
+SwAccessibleHeaderFooter::~SwAccessibleHeaderFooter()
+{
+}
+
+OUString SAL_CALL SwAccessibleHeaderFooter::getAccessibleDescription (void)
+ throw (uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+
+ CHECK_FOR_DEFUNC( XAccessibleContext )
+
+ sal_uInt16 nResId = AccessibleRole::HEADER == GetRole()
+ ? STR_ACCESS_HEADER_DESC
+ : STR_ACCESS_FOOTER_DESC ;
+
+ OUString sArg( GetFormattedPageNumber() );
+
+ return GetResource( nResId, &sArg );
+}
+
+OUString SAL_CALL SwAccessibleHeaderFooter::getImplementationName()
+ throw( RuntimeException )
+{
+ if( AccessibleRole::HEADER == GetRole() )
+ return OUString(RTL_CONSTASCII_USTRINGPARAM(sImplementationNameHeader));
+ else
+ return OUString(RTL_CONSTASCII_USTRINGPARAM(sImplementationNameFooter));
+}
+
+sal_Bool SAL_CALL SwAccessibleHeaderFooter::supportsService(
+ const ::rtl::OUString& sTestServiceName)
+ throw (uno::RuntimeException)
+{
+ if( sTestServiceName.equalsAsciiL( sAccessibleServiceName,
+ sizeof(sAccessibleServiceName)-1 ) )
+ return sal_True;
+ else if( AccessibleRole::HEADER == GetRole() )
+ return sTestServiceName.equalsAsciiL( sServiceNameHeader, sizeof(sServiceNameHeader)-1 );
+ else
+ return sTestServiceName.equalsAsciiL( sServiceNameFooter, sizeof(sServiceNameFooter)-1 );
+
+}
+
+Sequence< OUString > SAL_CALL SwAccessibleHeaderFooter::getSupportedServiceNames()
+ throw( uno::RuntimeException )
+{
+ Sequence< OUString > aRet(2);
+ OUString* pArray = aRet.getArray();
+ if( AccessibleRole::HEADER == GetRole() )
+ pArray[0] = OUString( RTL_CONSTASCII_USTRINGPARAM(sServiceNameHeader) );
+ else
+ pArray[0] = OUString( RTL_CONSTASCII_USTRINGPARAM(sServiceNameFooter) );
+ pArray[1] = OUString( RTL_CONSTASCII_USTRINGPARAM(sAccessibleServiceName) );
+ return aRet;
+}
+
+Sequence< sal_Int8 > SAL_CALL SwAccessibleHeaderFooter::getImplementationId()
+ throw(RuntimeException)
+{
+ SolarMutexGuard aGuard;
+ static Sequence< sal_Int8 > aId( 16 );
+ static sal_Bool bInit = sal_False;
+ if(!bInit)
+ {
+ rtl_createUuid( (sal_uInt8 *)(aId.getArray() ), 0, sal_True );
+ bInit = sal_True;
+ }
+ return aId;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/access/accheaderfooter.hxx b/sw/source/core/access/accheaderfooter.hxx
new file mode 100644
index 000000000000..210657e7602a
--- /dev/null
+++ b/sw/source/core/access/accheaderfooter.hxx
@@ -0,0 +1,85 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+#ifndef _ACCHEADERFOOTER_HXX
+#define _ACCHEADERFOOTER_HXX
+#include "acccontext.hxx"
+
+class SwHeaderFrm;
+class SwFooterFrm;
+
+class SwAccessibleHeaderFooter : public SwAccessibleContext
+{
+
+protected:
+
+ virtual ~SwAccessibleHeaderFooter();
+
+public:
+
+ SwAccessibleHeaderFooter( SwAccessibleMap* pInitMap,
+ const SwHeaderFrm* pHdFrm );
+ SwAccessibleHeaderFooter( SwAccessibleMap* pInitMap,
+ const SwFooterFrm* pFtFrm );
+
+
+ //===== XAccessibleContext ==============================================
+
+ /// Return this object's description.
+ virtual ::rtl::OUString SAL_CALL
+ getAccessibleDescription (void)
+ throw (com::sun::star::uno::RuntimeException);
+
+ //===== XServiceInfo ====================================================
+
+ /** Returns an identifier for the implementation of this object.
+ */
+ virtual ::rtl::OUString SAL_CALL
+ getImplementationName (void)
+ throw (::com::sun::star::uno::RuntimeException);
+
+ /** Return whether the specified service is supported by this class.
+ */
+ virtual sal_Bool SAL_CALL
+ supportsService (const ::rtl::OUString& sServiceName)
+ throw (::com::sun::star::uno::RuntimeException);
+
+ /** Returns a list of all supported services. In this case that is just
+ the AccessibleContext service.
+ */
+ virtual ::com::sun::star::uno::Sequence< ::rtl::OUString> SAL_CALL
+ getSupportedServiceNames (void)
+ throw (::com::sun::star::uno::RuntimeException);
+
+ //===== XTypeProvider ====================================================
+ virtual ::com::sun::star::uno::Sequence< sal_Int8 > SAL_CALL getImplementationId( ) throw(::com::sun::star::uno::RuntimeException);
+};
+
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/access/acchyperlink.cxx b/sw/source/core/access/acchyperlink.cxx
new file mode 100644
index 000000000000..6b239b04e0e2
--- /dev/null
+++ b/sw/source/core/access/acchyperlink.cxx
@@ -0,0 +1,192 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+ /*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+#include <comphelper/accessiblekeybindinghelper.hxx>
+#include <swurl.hxx>
+#include <osl/mutex.hxx>
+#include <vcl/svapp.hxx>
+#include <ndtxt.hxx>
+#include <txtinet.hxx>
+#include <accpara.hxx>
+#include <acchyperlink.hxx>
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::accessibility;
+using ::rtl::OUString;
+
+SwAccessibleHyperlink::SwAccessibleHyperlink( sal_uInt16 nHPos,
+ SwAccessibleParagraph *p, sal_Int32 nStt, sal_Int32 nEnd ) :
+ nHintPos( nHPos ),
+ xPara( p ),
+ nStartIdx( nStt ),
+ nEndIdx( nEnd )
+{
+}
+
+const SwTxtAttr *SwAccessibleHyperlink::GetTxtAttr() const
+{
+ const SwTxtAttr *pTxtAttr = 0;
+ if( xPara.is() && xPara->GetMap() )
+ {
+ const SwTxtNode *pTxtNd = xPara->GetTxtNode();
+ const SwpHints *pHints = pTxtNd->GetpSwpHints();
+ if( pHints && nHintPos < pHints->Count() )
+ {
+ const SwTxtAttr *pHt = (*pHints)[nHintPos];
+ if( RES_TXTATR_INETFMT == pHt->Which() )
+ pTxtAttr = pHt;
+ }
+ }
+
+ return pTxtAttr;
+}
+
+
+// XAccessibleAction
+sal_Int32 SAL_CALL SwAccessibleHyperlink::getAccessibleActionCount()
+ throw (uno::RuntimeException)
+{
+ return isValid() ? 1 : 0;
+}
+
+sal_Bool SAL_CALL SwAccessibleHyperlink::doAccessibleAction( sal_Int32 nIndex )
+ throw (lang::IndexOutOfBoundsException, uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+
+ sal_Bool bRet = sal_False;
+
+ const SwTxtAttr *pTxtAttr = GetTxtAttr();
+ if( pTxtAttr && 0 == nIndex )
+ {
+ const SwFmtINetFmt& rINetFmt = pTxtAttr->GetINetFmt();
+ if( rINetFmt.GetValue().Len() )
+ {
+ ViewShell *pVSh = xPara->GetShell();
+ if( pVSh )
+ {
+ LoadURL( rINetFmt.GetValue(), pVSh, URLLOAD_NOFILTER,
+ &rINetFmt.GetTargetFrame() );
+ OSL_ENSURE( pTxtAttr == rINetFmt.GetTxtINetFmt(),
+ "lost my txt attr" );
+ const SwTxtINetFmt* pTxtAttr2 = rINetFmt.GetTxtINetFmt();
+ if( pTxtAttr2 )
+ {
+ const_cast<SwTxtINetFmt*>(pTxtAttr2)->SetVisited(true);
+ const_cast<SwTxtINetFmt*>(pTxtAttr2)->SetVisitedValid(true);
+ }
+ bRet = sal_True;
+ }
+ }
+ }
+
+ return bRet;
+}
+
+OUString SAL_CALL SwAccessibleHyperlink::getAccessibleActionDescription(
+ sal_Int32 nIndex )
+ throw (lang::IndexOutOfBoundsException, uno::RuntimeException)
+{
+ OUString sDesc;
+
+ const SwTxtAttr *pTxtAttr = GetTxtAttr();
+ if( pTxtAttr && 0 == nIndex )
+ {
+ const SwFmtINetFmt& rINetFmt = pTxtAttr->GetINetFmt();
+ sDesc = OUString( rINetFmt.GetValue() );
+ }
+
+ return sDesc;
+}
+
+uno::Reference< XAccessibleKeyBinding > SAL_CALL
+ SwAccessibleHyperlink::getAccessibleActionKeyBinding( sal_Int32 nIndex )
+ throw (lang::IndexOutOfBoundsException, uno::RuntimeException)
+{
+ uno::Reference< XAccessibleKeyBinding > xKeyBinding;
+
+ if( isValid() && 0==nIndex )
+ {
+ ::comphelper::OAccessibleKeyBindingHelper* pKeyBindingHelper =
+ new ::comphelper::OAccessibleKeyBindingHelper();
+ xKeyBinding = pKeyBindingHelper;
+
+ awt::KeyStroke aKeyStroke;
+ aKeyStroke.Modifiers = 0;
+ aKeyStroke.KeyCode = KEY_RETURN;
+ aKeyStroke.KeyChar = 0;
+ aKeyStroke.KeyFunc = 0;
+ pKeyBindingHelper->AddKeyBinding( aKeyStroke );
+ }
+
+ return xKeyBinding;
+}
+
+// XAccessibleHyperlink
+uno::Any SAL_CALL SwAccessibleHyperlink::getAccessibleActionAnchor(
+ sal_Int32 /*nIndex*/ )
+ throw (lang::IndexOutOfBoundsException, uno::RuntimeException)
+{
+ return uno::Any();
+}
+
+uno::Any SAL_CALL SwAccessibleHyperlink::getAccessibleActionObject(
+ sal_Int32 /*nIndex*/ )
+ throw (lang::IndexOutOfBoundsException, uno::RuntimeException)
+{
+ return uno::Any();
+}
+
+sal_Int32 SAL_CALL SwAccessibleHyperlink::getStartIndex()
+ throw (uno::RuntimeException)
+{
+ return nStartIdx;
+}
+
+sal_Int32 SAL_CALL SwAccessibleHyperlink::getEndIndex()
+ throw (uno::RuntimeException)
+{
+ return nEndIdx;
+}
+
+sal_Bool SAL_CALL SwAccessibleHyperlink::isValid( )
+ throw (uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+ return xPara.is();
+}
+
+void SwAccessibleHyperlink::Invalidate()
+{
+ SolarMutexGuard aGuard;
+ xPara = 0;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/access/acchyperlink.hxx b/sw/source/core/access/acchyperlink.hxx
new file mode 100644
index 000000000000..ecbaff3ec383
--- /dev/null
+++ b/sw/source/core/access/acchyperlink.hxx
@@ -0,0 +1,93 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+#ifndef _ACCHYPERLINK_HXX
+#define _ACCHYPERLINK_HXX
+#include <com/sun/star/accessibility/XAccessibleHyperlink.hpp>
+#include <rtl/ref.hxx>
+#include <cppuhelper/implbase1.hxx>
+#include <fmtinfmt.hxx>
+
+class SwAccessibleParagraph;
+class SwTxtAttr;
+
+class SwAccessibleHyperlink :
+ public ::cppu::WeakImplHelper1<
+ ::com::sun::star::accessibility::XAccessibleHyperlink >
+{
+ friend class SwAccessibleParagraph;
+ friend class SwAccessibleHyperTextData;
+ sal_uInt16 nHintPos;
+ ::rtl::Reference< SwAccessibleParagraph > xPara;
+ sal_Int32 nStartIdx;
+ sal_Int32 nEndIdx;
+
+ SwAccessibleHyperlink( sal_uInt16 nHintPos,
+ SwAccessibleParagraph *p,
+ sal_Int32 nStt, sal_Int32 nEnd );
+
+ const SwTxtAttr *GetTxtAttr() const;
+ void Invalidate();
+
+public:
+
+ // XAccessibleAction
+ virtual sal_Int32 SAL_CALL getAccessibleActionCount()
+ throw (::com::sun::star::uno::RuntimeException);
+ virtual sal_Bool SAL_CALL doAccessibleAction( sal_Int32 nIndex )
+ throw (::com::sun::star::lang::IndexOutOfBoundsException,
+ ::com::sun::star::uno::RuntimeException);
+ virtual ::rtl::OUString SAL_CALL getAccessibleActionDescription(
+ sal_Int32 nIndex )
+ throw (::com::sun::star::lang::IndexOutOfBoundsException,
+ ::com::sun::star::uno::RuntimeException);
+ virtual ::com::sun::star::uno::Reference<
+ ::com::sun::star::accessibility::XAccessibleKeyBinding > SAL_CALL
+ getAccessibleActionKeyBinding( sal_Int32 nIndex )
+ throw (::com::sun::star::lang::IndexOutOfBoundsException,
+ ::com::sun::star::uno::RuntimeException);
+
+ // XAccessibleHyperlink
+ virtual ::com::sun::star::uno::Any SAL_CALL getAccessibleActionAnchor(
+ sal_Int32 nIndex )
+ throw (::com::sun::star::lang::IndexOutOfBoundsException,
+ ::com::sun::star::uno::RuntimeException);
+ virtual ::com::sun::star::uno::Any SAL_CALL getAccessibleActionObject(
+ sal_Int32 nIndex )
+ throw (::com::sun::star::lang::IndexOutOfBoundsException,
+ ::com::sun::star::uno::RuntimeException);
+ virtual sal_Int32 SAL_CALL getStartIndex()
+ throw (::com::sun::star::uno::RuntimeException);
+ virtual sal_Int32 SAL_CALL getEndIndex()
+ throw (::com::sun::star::uno::RuntimeException);
+ virtual sal_Bool SAL_CALL isValid( )
+ throw (::com::sun::star::uno::RuntimeException);
+};
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/access/acchypertextdata.cxx b/sw/source/core/access/acchypertextdata.cxx
new file mode 100644
index 000000000000..2e233522aa64
--- /dev/null
+++ b/sw/source/core/access/acchypertextdata.cxx
@@ -0,0 +1,58 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+ /*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+#include <acchyperlink.hxx>
+#include <acchypertextdata.hxx>
+
+using namespace ::com::sun::star::accessibility;
+using namespace ::com::sun::star::uno;
+
+SwAccessibleHyperTextData::SwAccessibleHyperTextData() :
+ _SwAccessibleHyperlinkMap_Impl()
+{
+}
+
+SwAccessibleHyperTextData::~SwAccessibleHyperTextData()
+{
+ iterator aIter = begin();
+ while( aIter != end() )
+ {
+ Reference < XAccessibleHyperlink > xTmp = (*aIter).second;
+ if( xTmp.is() )
+ {
+ SwAccessibleHyperlink *pTmp =
+ static_cast< SwAccessibleHyperlink * >( xTmp.get() );
+ pTmp->Invalidate();
+ }
+ ++aIter;
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/access/acchypertextdata.hxx b/sw/source/core/access/acchypertextdata.hxx
new file mode 100644
index 000000000000..d3d49e4e211b
--- /dev/null
+++ b/sw/source/core/access/acchypertextdata.hxx
@@ -0,0 +1,53 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+#ifndef _ACCHYPERTEXTDATA_HXX
+#define _ACCHYPERTEXTDATA_HXX
+
+#include <cppuhelper/weakref.hxx>
+
+#include <map>
+
+class SwTxtAttr;
+
+namespace com { namespace sun { namespace star {
+ namespace accessibility { class XAccessibleHyperlink; }
+} } }
+
+typedef ::std::less< const SwTxtAttr * > SwTxtAttrPtrLess;
+typedef ::std::map < const SwTxtAttr *, ::com::sun::star::uno::WeakReference < com::sun::star::accessibility::XAccessibleHyperlink >, SwTxtAttrPtrLess > _SwAccessibleHyperlinkMap_Impl;
+
+class SwAccessibleHyperTextData : public _SwAccessibleHyperlinkMap_Impl
+{
+public:
+ SwAccessibleHyperTextData();
+ ~SwAccessibleHyperTextData();
+};
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/access/accmap.cxx b/sw/source/core/access/accmap.cxx
new file mode 100644
index 000000000000..a3294bc2aa01
--- /dev/null
+++ b/sw/source/core/access/accmap.cxx
@@ -0,0 +1,2781 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+ /*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+
+#include <rtl/ref.hxx>
+#include <cppuhelper/weakref.hxx>
+#include <vcl/window.hxx>
+#include <svx/svdmodel.hxx>
+#include <svx/unomod.hxx>
+#include <tools/debug.hxx>
+
+#include <map>
+#include <list>
+#include <accmap.hxx>
+#include <acccontext.hxx>
+#include <accdoc.hxx>
+#include <accpreview.hxx>
+#include <accpage.hxx>
+#include <accpara.hxx>
+#include <accheaderfooter.hxx>
+#include <accfootnote.hxx>
+#include <acctextframe.hxx>
+#include <accgraphic.hxx>
+#include <accembedded.hxx>
+#include <acccell.hxx>
+#include <acctable.hxx>
+#include <fesh.hxx>
+#include <rootfrm.hxx>
+#include <txtfrm.hxx>
+#include <hffrm.hxx>
+#include <ftnfrm.hxx>
+#include <cellfrm.hxx>
+#include <tabfrm.hxx>
+#include <pagefrm.hxx>
+#include <flyfrm.hxx>
+#include <ndtyp.hxx>
+#include <IDocumentDrawModelAccess.hxx>
+#include <svx/ShapeTypeHandler.hxx>
+#include <vcl/svapp.hxx>
+#include <com/sun/star/accessibility/AccessibleRelationType.hpp>
+#include <com/sun/star/accessibility/AccessibleEventId.hpp>
+#include <com/sun/star/accessibility/AccessibleStateType.hpp>
+#include <cppuhelper/implbase1.hxx>
+#include <pagepreviewlayout.hxx>
+#include <pam.hxx>
+#include <ndtxt.hxx>
+#include <dflyobj.hxx>
+#include <prevwpage.hxx>
+#include <switerator.hxx>
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::accessibility;
+using ::rtl::OUString;
+using namespace ::sw::access;
+
+struct SwFrmFunc
+{
+ sal_Bool operator()( const SwFrm * p1,
+ const SwFrm * p2) const
+ {
+ return p1 < p2;
+ }
+};
+
+typedef ::std::map < const SwFrm *, uno::WeakReference < XAccessible >, SwFrmFunc > _SwAccessibleContextMap_Impl;
+
+class SwAccessibleContextMap_Impl: public _SwAccessibleContextMap_Impl
+{
+public:
+
+#if OSL_DEBUG_LEVEL > 1
+ sal_Bool mbLocked;
+#endif
+
+ SwAccessibleContextMap_Impl()
+#if OSL_DEBUG_LEVEL > 1
+ : mbLocked( sal_False )
+#endif
+ {}
+
+};
+
+//------------------------------------------------------------------------------
+class SwDrawModellListener_Impl : public SfxListener,
+ public ::cppu::WeakImplHelper1< document::XEventBroadcaster >
+{
+ mutable ::osl::Mutex maListenerMutex;
+ ::cppu::OInterfaceContainerHelper maEventListeners;
+ SdrModel *mpDrawModel;
+protected:
+ virtual ~SwDrawModellListener_Impl();
+public:
+
+ SwDrawModellListener_Impl( SdrModel *pDrawModel );
+
+
+ virtual void SAL_CALL addEventListener( const uno::Reference< document::XEventListener >& xListener ) throw (uno::RuntimeException);
+ virtual void SAL_CALL removeEventListener( const uno::Reference< document::XEventListener >& xListener ) throw (uno::RuntimeException);
+
+ virtual void Notify( SfxBroadcaster& rBC, const SfxHint& rHint );
+ void Dispose();
+};
+
+SwDrawModellListener_Impl::SwDrawModellListener_Impl( SdrModel *pDrawModel ) :
+ maEventListeners( maListenerMutex ),
+ mpDrawModel( pDrawModel )
+{
+ StartListening( *mpDrawModel );
+}
+
+SwDrawModellListener_Impl::~SwDrawModellListener_Impl()
+{
+ EndListening( *mpDrawModel );
+}
+
+void SAL_CALL SwDrawModellListener_Impl::addEventListener( const uno::Reference< document::XEventListener >& xListener ) throw (uno::RuntimeException)
+{
+ maEventListeners.addInterface( xListener );
+}
+
+void SAL_CALL SwDrawModellListener_Impl::removeEventListener( const uno::Reference< document::XEventListener >& xListener ) throw (uno::RuntimeException)
+{
+ maEventListeners.removeInterface( xListener );
+}
+
+void SwDrawModellListener_Impl::Notify( SfxBroadcaster& /*rBC*/,
+ const SfxHint& rHint )
+{
+ // do not broadcast notifications for writer fly frames, because there
+ // are no shapes that need to know about them.
+ const SdrHint *pSdrHint = PTR_CAST( SdrHint, &rHint );
+ if ( !pSdrHint ||
+ ( pSdrHint->GetObject() &&
+ ( pSdrHint->GetObject()->ISA(SwFlyDrawObj) ||
+ pSdrHint->GetObject()->ISA(SwVirtFlyDrawObj) ||
+ IS_TYPE(SdrObject,pSdrHint->GetObject()) ) ) )
+ {
+ return;
+ }
+
+ OSL_ENSURE( mpDrawModel, "draw model listener is disposed" );
+ if( !mpDrawModel )
+ return;
+
+ document::EventObject aEvent;
+ if( !SvxUnoDrawMSFactory::createEvent( mpDrawModel, pSdrHint, aEvent ) )
+ return;
+
+ ::cppu::OInterfaceIteratorHelper aIter( maEventListeners );
+ while( aIter.hasMoreElements() )
+ {
+ uno::Reference < document::XEventListener > xListener( aIter.next(),
+ uno::UNO_QUERY );
+ try
+ {
+ xListener->notifyEvent( aEvent );
+ }
+ catch( uno::RuntimeException const & r )
+ {
+ (void)r;
+#if OSL_DEBUG_LEVEL > 1
+ ByteString aError( "Runtime exception caught while notifying shape.:\n" );
+ aError += ByteString( String( r.Message), RTL_TEXTENCODING_ASCII_US );
+ OSL_FAIL( aError.GetBuffer() );
+#endif
+ }
+ }
+}
+
+void SwDrawModellListener_Impl::Dispose()
+{
+ mpDrawModel = 0;
+}
+
+//------------------------------------------------------------------------------
+struct SwShapeFunc
+{
+ sal_Bool operator()( const SdrObject * p1,
+ const SdrObject * p2) const
+ {
+ return p1 < p2;
+ }
+};
+typedef ::std::map < const SdrObject *, uno::WeakReference < XAccessible >, SwShapeFunc > _SwAccessibleShapeMap_Impl;
+typedef ::std::pair < const SdrObject *, ::rtl::Reference < ::accessibility::AccessibleShape > > SwAccessibleObjShape_Impl;
+
+class SwAccessibleShapeMap_Impl: public _SwAccessibleShapeMap_Impl
+
+{
+ ::accessibility::AccessibleShapeTreeInfo maInfo;
+
+public:
+
+#if OSL_DEBUG_LEVEL > 1
+ sal_Bool mbLocked;
+#endif
+ SwAccessibleShapeMap_Impl( SwAccessibleMap *pMap )
+#if OSL_DEBUG_LEVEL > 1
+ : mbLocked( sal_False )
+#endif
+ {
+ maInfo.SetSdrView( pMap->GetShell()->GetDrawView() );
+ maInfo.SetWindow( pMap->GetShell()->GetWin() );
+ maInfo.SetViewForwarder( pMap );
+ uno::Reference < document::XEventBroadcaster > xModelBroadcaster =
+ new SwDrawModellListener_Impl(
+ pMap->GetShell()->getIDocumentDrawModelAccess()->GetOrCreateDrawModel() );
+ maInfo.SetControllerBroadcaster( xModelBroadcaster );
+ }
+
+ ~SwAccessibleShapeMap_Impl();
+
+ const ::accessibility::AccessibleShapeTreeInfo& GetInfo() const { return maInfo; }
+
+ SwAccessibleObjShape_Impl *Copy( size_t& rSize,
+ const SwFEShell *pFESh = 0,
+ SwAccessibleObjShape_Impl **pSelShape = 0 ) const;
+};
+
+SwAccessibleShapeMap_Impl::~SwAccessibleShapeMap_Impl()
+{
+ uno::Reference < document::XEventBroadcaster > xBrd( maInfo.GetControllerBroadcaster() );
+ if( xBrd.is() )
+ static_cast < SwDrawModellListener_Impl * >( xBrd.get() )->Dispose();
+}
+
+SwAccessibleObjShape_Impl
+ *SwAccessibleShapeMap_Impl::Copy(
+ size_t& rSize, const SwFEShell *pFESh,
+ SwAccessibleObjShape_Impl **pSelStart ) const
+{
+ SwAccessibleObjShape_Impl *pShapes = 0;
+ SwAccessibleObjShape_Impl *pSelShape = 0;
+
+ sal_uInt16 nSelShapes = pFESh ? pFESh->IsObjSelected() : 0;
+ rSize = size();
+
+ if( rSize > 0 )
+ {
+ pShapes =
+ new SwAccessibleObjShape_Impl[rSize];
+
+ const_iterator aIter = begin();
+ const_iterator aEndIter = end();
+
+ SwAccessibleObjShape_Impl *pShape = pShapes;
+ pSelShape = &(pShapes[rSize]);
+ while( aIter != aEndIter )
+ {
+ const SdrObject *pObj = (*aIter).first;
+ uno::Reference < XAccessible > xAcc( (*aIter).second );
+ if( nSelShapes && pFESh->IsObjSelected( *pObj ) )
+ {
+ // selected objects are inserted from the back
+ --pSelShape;
+ pSelShape->first = pObj;
+ pSelShape->second =
+ static_cast < ::accessibility::AccessibleShape* >(
+ xAcc.get() );
+ --nSelShapes;
+ }
+ else
+ {
+ pShape->first = pObj;
+ pShape->second =
+ static_cast < ::accessibility::AccessibleShape* >(
+ xAcc.get() );
+ ++pShape;
+ }
+ ++aIter;
+ }
+ OSL_ENSURE( pSelShape == pShape, "copying shapes went wrong!" );
+ }
+
+ if( pSelStart )
+ *pSelStart = pSelShape;
+
+ return pShapes;
+}
+
+//------------------------------------------------------------------------------
+struct SwAccessibleEvent_Impl
+{
+public:
+ enum EventType { CARET_OR_STATES,
+ INVALID_CONTENT,
+ POS_CHANGED,
+ CHILD_POS_CHANGED,
+ SHAPE_SELECTION,
+ DISPOSE,
+ INVALID_ATTR };
+
+private:
+ SwRect maOldBox; // the old bounds for CHILD_POS_CHANGED
+ // and POS_CHANGED
+ uno::WeakReference < XAccessible > mxAcc; // The object that fires the event
+ SwAccessibleChild maFrmOrObj; // the child for CHILD_POS_CHANGED and
+ // the same as xAcc for any other
+ // event type
+ EventType meType; // The event type
+ tAccessibleStates mnStates; // check states or update caret pos
+
+ SwAccessibleEvent_Impl& operator==( const SwAccessibleEvent_Impl& );
+
+public:
+ SwAccessibleEvent_Impl( EventType eT,
+ SwAccessibleContext *pA,
+ const SwAccessibleChild& rFrmOrObj )
+ : mxAcc( pA ),
+ maFrmOrObj( rFrmOrObj ),
+ meType( eT ),
+ mnStates( 0 )
+ {}
+
+ SwAccessibleEvent_Impl( EventType eT,
+ const SwAccessibleChild& rFrmOrObj )
+ : maFrmOrObj( rFrmOrObj ),
+ meType( eT ),
+ mnStates( 0 )
+ {
+ OSL_ENSURE( SwAccessibleEvent_Impl::DISPOSE == meType,
+ "wrong event constructor, DISPOSE only" );
+ }
+
+ SwAccessibleEvent_Impl( EventType eT )
+ : meType( eT ),
+ mnStates( 0 )
+ {
+ OSL_ENSURE( SwAccessibleEvent_Impl::SHAPE_SELECTION == meType,
+ "wrong event constructor, SHAPE_SELECTION only" );
+ }
+
+ SwAccessibleEvent_Impl( EventType eT,
+ SwAccessibleContext *pA,
+ const SwAccessibleChild& rFrmOrObj,
+ const SwRect& rR )
+ : maOldBox( rR ),
+ mxAcc( pA ),
+ maFrmOrObj( rFrmOrObj ),
+ meType( eT ),
+ mnStates( 0 )
+ {
+ OSL_ENSURE( SwAccessibleEvent_Impl::CHILD_POS_CHANGED == meType ||
+ SwAccessibleEvent_Impl::POS_CHANGED == meType,
+ "wrong event constructor, (CHILD_)POS_CHANGED only" );
+ }
+
+ SwAccessibleEvent_Impl( EventType eT,
+ SwAccessibleContext *pA,
+ const SwAccessibleChild& rFrmOrObj,
+ const tAccessibleStates _nStates )
+ : mxAcc( pA ),
+ maFrmOrObj( rFrmOrObj ),
+ meType( eT ),
+ mnStates( _nStates )
+ {
+ OSL_ENSURE( SwAccessibleEvent_Impl::CARET_OR_STATES == meType,
+ "wrong event constructor, CARET_OR_STATES only" );
+ }
+
+ // <SetType(..)> only used in method <SwAccessibleMap::AppendEvent(..)>
+ inline void SetType( EventType eT )
+ {
+ meType = eT;
+ }
+ inline EventType GetType() const
+ {
+ return meType;
+ }
+
+ inline ::rtl::Reference < SwAccessibleContext > GetContext() const
+ {
+ uno::Reference < XAccessible > xTmp( mxAcc );
+ ::rtl::Reference < SwAccessibleContext > xAccImpl(
+ static_cast<SwAccessibleContext*>( xTmp.get() ) );
+
+ return xAccImpl;
+ }
+
+ inline const SwRect& GetOldBox() const
+ {
+ return maOldBox;
+ }
+ // <SetOldBox(..)> only used in method <SwAccessibleMap::AppendEvent(..)>
+ inline void SetOldBox( const SwRect& rOldBox )
+ {
+ maOldBox = rOldBox;
+ }
+
+ inline const SwAccessibleChild& GetFrmOrObj() const
+ {
+ return maFrmOrObj;
+ }
+
+ // <SetStates(..)> only used in method <SwAccessibleMap::AppendEvent(..)>
+ inline void SetStates( tAccessibleStates _nStates )
+ {
+ mnStates |= _nStates;
+ }
+
+ inline sal_Bool IsUpdateCursorPos() const
+ {
+ return (mnStates & ACC_STATE_CARET) != 0;
+ }
+ inline sal_Bool IsInvalidateStates() const
+ {
+ return (mnStates & ACC_STATE_MASK) != 0;
+ }
+ inline sal_Bool IsInvalidateRelation() const
+ {
+ return (mnStates & ACC_STATE_RELATION_MASK) != 0;
+ }
+ inline sal_Bool IsInvalidateTextSelection() const
+ {
+ return ( mnStates & ACC_STATE_TEXT_SELECTION_CHANGED ) != 0;
+ }
+
+ inline sal_Bool IsInvalidateTextAttrs() const
+ {
+ return ( mnStates & ACC_STATE_TEXT_ATTRIBUTE_CHANGED ) != 0;
+ }
+
+ inline tAccessibleStates GetStates() const
+ {
+ return mnStates & ACC_STATE_MASK;
+ }
+
+ inline tAccessibleStates GetAllStates() const
+ {
+ return mnStates;
+ }
+
+};
+
+//------------------------------------------------------------------------------
+typedef ::std::list < SwAccessibleEvent_Impl > _SwAccessibleEventList_Impl;
+
+class SwAccessibleEventList_Impl: public _SwAccessibleEventList_Impl
+{
+ sal_Bool mbFiring;
+
+public:
+
+ SwAccessibleEventList_Impl()
+ : mbFiring( sal_False )
+ {}
+
+ inline void SetFiring()
+ {
+ mbFiring = sal_True;
+ }
+ inline sal_Bool IsFiring() const
+ {
+ return mbFiring;
+ }
+};
+
+//------------------------------------------------------------------------------
+// The shape list is filled if an accessible shape is destroyed. It
+// simply keeps a reference to the accessible shape's XShape. These
+// references are destroyed within the EndAction when firing events,
+// There are twp reason for this. First of all, a new accessible shape
+// for the XShape might be created soon. It's then cheaper if the XShape
+// still exists. The other reason are situations where an accessible shape
+// is destroyed within an SwFrmFmt::Modify. In this case, destryoing
+// the XShape at the same time (indirectly by destroying the accessible
+// shape) leads to an assert, because a client of the Modify is destroyed
+// within a Modify call.
+
+typedef ::std::list < uno::Reference < drawing::XShape > > _SwShapeList_Impl;
+
+class SwShapeList_Impl: public _SwShapeList_Impl
+{
+public:
+
+ SwShapeList_Impl() {}
+};
+
+
+//------------------------------------------------------------------------------
+struct SwAccessibleChildFunc
+{
+ sal_Bool operator()( const SwAccessibleChild& r1,
+ const SwAccessibleChild& r2 ) const
+ {
+ const void *p1 = r1.GetSwFrm()
+ ? static_cast < const void * >( r1.GetSwFrm())
+ : ( r1.GetDrawObject()
+ ? static_cast < const void * >( r1.GetDrawObject() )
+ : static_cast < const void * >( r1.GetWindow() ) );
+ const void *p2 = r2.GetSwFrm()
+ ? static_cast < const void * >( r2.GetSwFrm())
+ : ( r2.GetDrawObject()
+ ? static_cast < const void * >( r2.GetDrawObject() )
+ : static_cast < const void * >( r2.GetWindow() ) );
+ return p1 < p2;
+ }
+};
+typedef ::std::map < SwAccessibleChild, SwAccessibleEventList_Impl::iterator,
+ SwAccessibleChildFunc > _SwAccessibleEventMap_Impl;
+
+class SwAccessibleEventMap_Impl: public _SwAccessibleEventMap_Impl
+{
+};
+
+//------------------------------------------------------------------------------
+
+struct SwAccessibleParaSelection
+{
+ xub_StrLen nStartOfSelection;
+ xub_StrLen nEndOfSelection;
+
+ SwAccessibleParaSelection( const xub_StrLen _nStartOfSelection,
+ const xub_StrLen _nEndOfSelection )
+ : nStartOfSelection( _nStartOfSelection ),
+ nEndOfSelection( _nEndOfSelection )
+ {}
+};
+
+struct SwXAccWeakRefComp
+{
+ sal_Bool operator()( const uno::WeakReference<XAccessible>& _rXAccWeakRef1,
+ const uno::WeakReference<XAccessible>& _rXAccWeakRef2 ) const
+ {
+ return _rXAccWeakRef1.get() < _rXAccWeakRef2.get();
+ }
+};
+
+typedef ::std::map< uno::WeakReference < XAccessible >,
+ SwAccessibleParaSelection,
+ SwXAccWeakRefComp > _SwAccessibleSelectedParas_Impl;
+
+class SwAccessibleSelectedParas_Impl: public _SwAccessibleSelectedParas_Impl
+{};
+
+// helper class that stores preview data
+class SwAccPreviewData
+{
+ typedef std::vector<Rectangle> Rectangles;
+ Rectangles maPreviewRects;
+ Rectangles maLogicRects;
+
+ SwRect maVisArea;
+ Fraction maScale;
+
+ const SwPageFrm *mpSelPage;
+
+ /** adjust logic page retangle to its visible part
+
+ @param _iorLogicPgSwRect
+ input/output parameter - reference to the logic page rectangle, which
+ has to be adjusted.
+
+ @param _rPrevwPgSwRect
+ input parameter - constant reference to the corresponding preview page
+ rectangle; needed to determine the visible part of the logic page rectangle.
+
+ @param _rPrevwWinSize
+ input paramter - constant reference to the preview window size in TWIP;
+ needed to determine the visible part of the logic page rectangle
+ */
+ void AdjustLogicPgRectToVisibleArea( SwRect& _iorLogicPgSwRect,
+ const SwRect& _rPrevwPgSwRect,
+ const Size& _rPrevwWinSize );
+
+public:
+ SwAccPreviewData();
+ ~SwAccPreviewData();
+
+ void Update( const SwAccessibleMap& rAccMap,
+ const std::vector<PrevwPage*>& _rPrevwPages,
+ const Fraction& _rScale,
+ const SwPageFrm* _pSelectedPageFrm,
+ const Size& _rPrevwWinSize );
+
+ void InvalidateSelection( const SwPageFrm* _pSelectedPageFrm );
+
+ const SwRect& GetVisArea() const;
+
+ MapMode GetMapModeForPreview( ) const;
+
+ /** Adjust the MapMode so that the preview page appears at the
+ * proper position. rPoint identifies the page for which the
+ * MapMode should be adjusted. If bFromPreview is true, rPoint is
+ * a preview coordinate; else it's a document coordinate. */
+ void AdjustMapMode( MapMode& rMapMode,
+ const Point& rPoint ) const;
+
+ inline const SwPageFrm *GetSelPage() const { return mpSelPage; }
+
+ void DisposePage(const SwPageFrm *pPageFrm );
+};
+
+SwAccPreviewData::SwAccPreviewData() :
+ mpSelPage( 0 )
+{
+}
+
+SwAccPreviewData::~SwAccPreviewData()
+{
+}
+
+void SwAccPreviewData::Update( const SwAccessibleMap& rAccMap,
+ const std::vector<PrevwPage*>& _rPrevwPages,
+ const Fraction& _rScale,
+ const SwPageFrm* _pSelectedPageFrm,
+ const Size& _rPrevwWinSize )
+{
+ // store preview scaling, maximal preview page size and selected page
+ maScale = _rScale;
+ mpSelPage = _pSelectedPageFrm;
+
+ // prepare loop on preview pages
+ maPreviewRects.clear();
+ maLogicRects.clear();
+ SwAccessibleChild aPage;
+ maVisArea.Clear();
+
+ // loop on preview pages to calculate <maPreviewRects>, <maLogicRects> and
+ // <maVisArea>
+ for ( std::vector<PrevwPage*>::const_iterator aPageIter = _rPrevwPages.begin();
+ aPageIter != _rPrevwPages.end();
+ ++aPageIter )
+ {
+ aPage = (*aPageIter)->pPage;
+
+ // add preview page rectangle to <maPreviewRects>
+ Rectangle aPrevwPgRect( (*aPageIter)->aPrevwWinPos, (*aPageIter)->aPageSize );
+ maPreviewRects.push_back( aPrevwPgRect );
+
+ // add logic page rectangle to <maLogicRects>
+ SwRect aLogicPgSwRect( aPage.GetBox( rAccMap ) );
+ Rectangle aLogicPgRect( aLogicPgSwRect.SVRect() );
+ maLogicRects.push_back( aLogicPgRect );
+ // union visible area with visible part of logic page rectangle
+ if ( (*aPageIter)->bVisible )
+ {
+ if ( !(*aPageIter)->pPage->IsEmptyPage() )
+ {
+ AdjustLogicPgRectToVisibleArea( aLogicPgSwRect,
+ SwRect( aPrevwPgRect ),
+ _rPrevwWinSize );
+ }
+ if ( maVisArea.IsEmpty() )
+ maVisArea = aLogicPgSwRect;
+ else
+ maVisArea.Union( aLogicPgSwRect );
+ }
+ }
+}
+
+void SwAccPreviewData::InvalidateSelection( const SwPageFrm* _pSelectedPageFrm )
+{
+ mpSelPage = _pSelectedPageFrm;
+ OSL_ENSURE( mpSelPage, "selected page not found" );
+}
+
+struct ContainsPredicate
+{
+ const Point& mrPoint;
+ ContainsPredicate( const Point& rPoint ) : mrPoint(rPoint) {}
+ bool operator() ( const Rectangle& rRect ) const
+ {
+ return rRect.IsInside( mrPoint ) ? true : false;
+ }
+};
+
+const SwRect& SwAccPreviewData::GetVisArea() const
+{
+ return maVisArea;
+}
+
+void SwAccPreviewData::AdjustMapMode( MapMode& rMapMode,
+ const Point& rPoint ) const
+{
+ // adjust scale
+ rMapMode.SetScaleX( maScale );
+ rMapMode.SetScaleY( maScale );
+
+ // find proper rectangle
+ Rectangles::const_iterator aBegin = maLogicRects.begin();
+ Rectangles::const_iterator aEnd = maLogicRects.end();
+ Rectangles::const_iterator aFound = ::std::find_if( aBegin, aEnd,
+ ContainsPredicate( rPoint ) );
+
+ if( aFound != aEnd )
+ {
+ // found! set new origin
+ Point aPoint = (maPreviewRects.begin() + (aFound - aBegin))->TopLeft();
+ aPoint -= (maLogicRects.begin() + (aFound-aBegin))->TopLeft();
+ rMapMode.SetOrigin( aPoint );
+ }
+ // else: don't adjust MapMode
+}
+
+void SwAccPreviewData::DisposePage(const SwPageFrm *pPageFrm )
+{
+ if( mpSelPage == pPageFrm )
+ mpSelPage = 0;
+}
+
+// adjust logic page retangle to its visible part
+void SwAccPreviewData::AdjustLogicPgRectToVisibleArea(
+ SwRect& _iorLogicPgSwRect,
+ const SwRect& _rPrevwPgSwRect,
+ const Size& _rPrevwWinSize )
+{
+ // determine preview window rectangle
+ const SwRect aPrevwWinSwRect( Point( 0, 0 ), _rPrevwWinSize );
+ // calculate visible preview page rectangle
+ SwRect aVisPrevwPgSwRect( _rPrevwPgSwRect );
+ aVisPrevwPgSwRect.Intersection( aPrevwWinSwRect );
+ // adjust logic page rectangle
+ SwTwips nTmpDiff;
+ // left
+ nTmpDiff = aVisPrevwPgSwRect.Left() - _rPrevwPgSwRect.Left();
+ if ( nTmpDiff > 0 )
+ _iorLogicPgSwRect.Left( _iorLogicPgSwRect.Left() + nTmpDiff );
+ // top
+ nTmpDiff = aVisPrevwPgSwRect.Top() - _rPrevwPgSwRect.Top();
+ if ( nTmpDiff > 0 )
+ _iorLogicPgSwRect.Top( _iorLogicPgSwRect.Top() + nTmpDiff );
+ // right
+ nTmpDiff = _rPrevwPgSwRect.Right() - aVisPrevwPgSwRect.Right();
+ if ( nTmpDiff > 0 )
+ _iorLogicPgSwRect.Right( _iorLogicPgSwRect.Right() - nTmpDiff );
+ // bottom
+ nTmpDiff = _rPrevwPgSwRect.Bottom() - aVisPrevwPgSwRect.Bottom();
+ if ( nTmpDiff > 0 )
+ _iorLogicPgSwRect.Bottom( _iorLogicPgSwRect.Bottom() - nTmpDiff );
+}
+
+//------------------------------------------------------------------------------
+static sal_Bool AreInSameTable( const uno::Reference< XAccessible >& rAcc,
+ const SwFrm *pFrm )
+{
+ sal_Bool bRet = sal_False;
+
+ if( pFrm && pFrm->IsCellFrm() && rAcc.is() )
+ {
+ // Is it in the same table? We check that
+ // by comparing the last table frame in the
+ // follow chain, because that's cheaper than
+ // searching the first one.
+ SwAccessibleContext *pAccImpl =
+ static_cast< SwAccessibleContext *>( rAcc.get() );
+ if( pAccImpl->GetFrm()->IsCellFrm() )
+ {
+ const SwTabFrm *pTabFrm1 = pAccImpl->GetFrm()->FindTabFrm();
+ while( pTabFrm1->GetFollow() )
+ pTabFrm1 = pTabFrm1->GetFollow();
+
+ const SwTabFrm *pTabFrm2 = pFrm->FindTabFrm();
+ while( pTabFrm2->GetFollow() )
+ pTabFrm2 = pTabFrm2->GetFollow();
+
+ bRet = (pTabFrm1 == pTabFrm2);
+ }
+ }
+
+ return bRet;
+}
+
+void SwAccessibleMap::FireEvent( const SwAccessibleEvent_Impl& rEvent )
+{
+ ::rtl::Reference < SwAccessibleContext > xAccImpl( rEvent.GetContext() );
+ if( SwAccessibleEvent_Impl::SHAPE_SELECTION == rEvent.GetType() )
+ {
+ DoInvalidateShapeSelection();
+ }
+ else if( xAccImpl.is() && xAccImpl->GetFrm() )
+ {
+ if ( rEvent.GetType() != SwAccessibleEvent_Impl::DISPOSE &&
+ rEvent.IsInvalidateTextAttrs() )
+ {
+ xAccImpl->InvalidateAttr();
+ }
+ switch( rEvent.GetType() )
+ {
+ case SwAccessibleEvent_Impl::INVALID_CONTENT:
+ xAccImpl->InvalidateContent();
+ break;
+ case SwAccessibleEvent_Impl::POS_CHANGED:
+ xAccImpl->InvalidatePosOrSize( rEvent.GetOldBox() );
+ break;
+ case SwAccessibleEvent_Impl::CHILD_POS_CHANGED:
+ xAccImpl->InvalidateChildPosOrSize( rEvent.GetFrmOrObj(),
+ rEvent.GetOldBox() );
+ break;
+ case SwAccessibleEvent_Impl::DISPOSE:
+ OSL_ENSURE( xAccImpl.is(),
+ "dispose event has been stored" );
+ break;
+ case SwAccessibleEvent_Impl::INVALID_ATTR:
+ // nothing to do here - handled above
+ break;
+ default:
+ break;
+ }
+ if( SwAccessibleEvent_Impl::DISPOSE != rEvent.GetType() )
+ {
+ if( rEvent.IsUpdateCursorPos() )
+ xAccImpl->InvalidateCursorPos();
+ if( rEvent.IsInvalidateStates() )
+ xAccImpl->InvalidateStates( rEvent.GetStates() );
+ if( rEvent.IsInvalidateRelation() )
+ {
+ // both events CONTENT_FLOWS_FROM_RELATION_CHANGED and
+ // CONTENT_FLOWS_TO_RELATION_CHANGED are possible
+ if ( rEvent.GetAllStates() & ACC_STATE_RELATION_FROM )
+ {
+ xAccImpl->InvalidateRelation(
+ AccessibleEventId::CONTENT_FLOWS_FROM_RELATION_CHANGED );
+ }
+ if ( rEvent.GetAllStates() & ACC_STATE_RELATION_TO )
+ {
+ xAccImpl->InvalidateRelation(
+ AccessibleEventId::CONTENT_FLOWS_TO_RELATION_CHANGED );
+ }
+ }
+
+ if ( rEvent.IsInvalidateTextSelection() )
+ {
+ xAccImpl->InvalidateTextSelection();
+ }
+ }
+ }
+}
+
+void SwAccessibleMap::AppendEvent( const SwAccessibleEvent_Impl& rEvent )
+{
+ osl::MutexGuard aGuard( maEventMutex );
+
+ if( !mpEvents )
+ mpEvents = new SwAccessibleEventList_Impl;
+ if( !mpEventMap )
+ mpEventMap = new SwAccessibleEventMap_Impl;
+
+ if( mpEvents->IsFiring() )
+ {
+ // While events are fired new ones are generated. They have to be fired
+ // now. This does not work for DISPOSE events!
+ OSL_ENSURE( rEvent.GetType() != SwAccessibleEvent_Impl::DISPOSE,
+ "dispose event while firing events" );
+ FireEvent( rEvent );
+ }
+ else
+ {
+
+ SwAccessibleEventMap_Impl::iterator aIter =
+ mpEventMap->find( rEvent.GetFrmOrObj() );
+ if( aIter != mpEventMap->end() )
+ {
+ SwAccessibleEvent_Impl aEvent( *(*aIter).second );
+ OSL_ENSURE( aEvent.GetType() != SwAccessibleEvent_Impl::DISPOSE,
+ "dispose events should not be stored" );
+ sal_Bool bAppendEvent = sal_True;
+ switch( rEvent.GetType() )
+ {
+ case SwAccessibleEvent_Impl::CARET_OR_STATES:
+ // A CARET_OR_STATES event is added to any other
+ // event only. It is broadcasted after any other event, so the
+ // event should be put to the back.
+ OSL_ENSURE( aEvent.GetType() != SwAccessibleEvent_Impl::CHILD_POS_CHANGED,
+ "invalid event combination" );
+ aEvent.SetStates( rEvent.GetAllStates() );
+ break;
+ case SwAccessibleEvent_Impl::INVALID_CONTENT:
+ // An INVALID_CONTENT event overwrites a CARET_OR_STATES
+ // event (but keeps its flags) and it is contained in a
+ // POS_CHANGED event.
+ // Therefor, the event's type has to be adapted and the event
+ // has to be put at the end.
+ OSL_ENSURE( aEvent.GetType() != SwAccessibleEvent_Impl::CHILD_POS_CHANGED,
+ "invalid event combination" );
+ if( aEvent.GetType() == SwAccessibleEvent_Impl::CARET_OR_STATES )
+ aEvent.SetType( SwAccessibleEvent_Impl::INVALID_CONTENT );
+ break;
+ case SwAccessibleEvent_Impl::POS_CHANGED:
+ // A pos changed event overwrites CARET_STATES (keeping its
+ // flags) as well as INVALID_CONTENT. The old box position
+ // has to be stored however if the old event is not a
+ // POS_CHANGED itself.
+ OSL_ENSURE( aEvent.GetType() != SwAccessibleEvent_Impl::CHILD_POS_CHANGED,
+ "invalid event combination" );
+ if( aEvent.GetType() != SwAccessibleEvent_Impl::POS_CHANGED )
+ aEvent.SetOldBox( rEvent.GetOldBox() );
+ aEvent.SetType( SwAccessibleEvent_Impl::POS_CHANGED );
+ break;
+ case SwAccessibleEvent_Impl::CHILD_POS_CHANGED:
+ // CHILD_POS_CHANGED events can only follow CHILD_POS_CHANGED
+ // events. The only action that needs to be done again is
+ // to put the old event to the back. The new one cannot be used,
+ // because we are interested in the old frame bounds.
+ OSL_ENSURE( aEvent.GetType() == SwAccessibleEvent_Impl::CHILD_POS_CHANGED,
+ "invalid event combination" );
+ break;
+ case SwAccessibleEvent_Impl::SHAPE_SELECTION:
+ OSL_ENSURE( aEvent.GetType() == SwAccessibleEvent_Impl::SHAPE_SELECTION,
+ "invalid event combination" );
+ break;
+ case SwAccessibleEvent_Impl::DISPOSE:
+ // DISPOSE events overwrite all others. They are not stored
+ // but executed immediatly to avoid broadcasting of
+ // defunctional objects. So what needs to be done here is to
+ // remove all events for the frame in question.
+ bAppendEvent = sal_False;
+ break;
+ case SwAccessibleEvent_Impl::INVALID_ATTR:
+ OSL_ENSURE( aEvent.GetType() == SwAccessibleEvent_Impl::INVALID_ATTR,
+ "invalid event combination" );
+ break;
+ }
+ if( bAppendEvent )
+ {
+ mpEvents->erase( (*aIter).second );
+ (*aIter).second = mpEvents->insert( mpEvents->end(), aEvent );
+ }
+ else
+ {
+ mpEvents->erase( (*aIter).second );
+ mpEventMap->erase( aIter );
+ }
+ }
+ else if( SwAccessibleEvent_Impl::DISPOSE != rEvent.GetType() )
+ {
+ SwAccessibleEventMap_Impl::value_type aEntry( rEvent.GetFrmOrObj(),
+ mpEvents->insert( mpEvents->end(), rEvent ) );
+ mpEventMap->insert( aEntry );
+ }
+ }
+}
+
+void SwAccessibleMap::InvalidateCursorPosition(
+ const uno::Reference< XAccessible >& rAcc )
+{
+ SwAccessibleContext *pAccImpl =
+ static_cast< SwAccessibleContext *>( rAcc.get() );
+ OSL_ENSURE( pAccImpl, "no caret context" );
+ OSL_ENSURE( pAccImpl->GetFrm(), "caret context is disposed" );
+ if( GetShell()->ActionPend() )
+ {
+ SwAccessibleEvent_Impl aEvent( SwAccessibleEvent_Impl::CARET_OR_STATES,
+ pAccImpl,
+ SwAccessibleChild(pAccImpl->GetFrm()),
+ ACC_STATE_CARET );
+ AppendEvent( aEvent );
+ }
+ else
+ {
+ FireEvents();
+ // While firing events the current frame might have
+ // been disposed because it moved out of the vis area.
+ // Setting the cursor for such frames is useless and even
+ // causes asserts.
+ if( pAccImpl->GetFrm() )
+ pAccImpl->InvalidateCursorPos();
+ }
+}
+
+void SwAccessibleMap::InvalidateShapeSelection()
+{
+ if( GetShell()->ActionPend() )
+ {
+ SwAccessibleEvent_Impl aEvent(
+ SwAccessibleEvent_Impl::SHAPE_SELECTION );
+ AppendEvent( aEvent );
+ }
+ else
+ {
+ FireEvents();
+ DoInvalidateShapeSelection();
+ }
+}
+
+void SwAccessibleMap::DoInvalidateShapeSelection()
+{
+ SwAccessibleObjShape_Impl *pShapes = 0;
+ SwAccessibleObjShape_Impl *pSelShape = 0;
+ size_t nShapes = 0;
+
+ const ViewShell *pVSh = GetShell();
+ const SwFEShell *pFESh = pVSh->ISA( SwFEShell ) ?
+ static_cast< const SwFEShell * >( pVSh ) : 0;
+ sal_uInt16 nSelShapes = pFESh ? pFESh->IsObjSelected() : 0;
+
+ {
+ osl::MutexGuard aGuard( maMutex );
+ if( mpShapeMap )
+ pShapes = mpShapeMap->Copy( nShapes, pFESh, &pSelShape );
+ }
+
+ if( pShapes )
+ {
+ ::std::list< const SwFrm * > aParents;
+ Window *pWin = GetShell()->GetWin();
+ sal_Bool bFocused = pWin && pWin->HasFocus();
+ SwAccessibleObjShape_Impl *pShape = pShapes;
+ while( nShapes )
+ {
+ if( pShape->second.is() )
+ {
+ sal_Bool bChanged;
+ if( pShape >= pSelShape )
+ {
+ bChanged =
+ pShape->second->SetState( AccessibleStateType::SELECTED );
+ if( bFocused && 1 == nSelShapes )
+ pShape->second->SetState( AccessibleStateType::FOCUSED );
+ else
+ pShape->second->ResetState( AccessibleStateType::FOCUSED );
+ }
+ else
+ {
+ bChanged =
+ pShape->second->ResetState( AccessibleStateType::SELECTED );
+ pShape->second->ResetState( AccessibleStateType::FOCUSED );
+ }
+ if( bChanged )
+ {
+ const SwFrm* pParent = SwAccessibleFrame::GetParent(
+ SwAccessibleChild( pShape->first ),
+ GetShell()->IsPreView() );
+ aParents.push_back( pParent );
+ }
+ }
+
+ --nShapes;
+ ++pShape;
+ }
+ if( aParents.size() > 0 )
+ {
+ ::std::list< const SwFrm * >::const_iterator aIter = aParents.begin();
+ ::std::list< const SwFrm * >::const_iterator aEndIter = aParents.end();
+ while( aIter != aEndIter )
+ {
+ ::rtl::Reference< SwAccessibleContext > xParentAccImpl;
+ {
+ osl::MutexGuard aGuard( maMutex );
+ if( mpFrmMap )
+ {
+ SwAccessibleContextMap_Impl::const_iterator aMapIter =
+ mpFrmMap->find( *aIter );
+ if( aMapIter != mpFrmMap->end() )
+ {
+ uno::Reference < XAccessible > xAcc( (*aMapIter).second );
+ xParentAccImpl =
+ static_cast< SwAccessibleContext *>( xAcc.get() );
+ }
+ }
+ }
+ if( xParentAccImpl.is() )
+ {
+ AccessibleEventObject aEvent;
+ aEvent.EventId = AccessibleEventId::SELECTION_CHANGED;
+ xParentAccImpl->FireAccessibleEvent( aEvent );
+ }
+
+ ++aIter;
+ }
+ }
+
+ delete[] pShapes;
+ }
+}
+
+void SwAccessibleMap::DoInvalidateShapeFocus()
+{
+ const ViewShell *pVSh = GetShell();
+ const SwFEShell *pFESh = pVSh->ISA( SwFEShell ) ?
+ static_cast< const SwFEShell * >( pVSh ) : 0;
+ sal_uInt16 nSelShapes = pFESh ? pFESh->IsObjSelected() : 0;
+
+ if( nSelShapes != 1 )
+ return;
+
+ SwAccessibleObjShape_Impl *pShapes = 0;
+ SwAccessibleObjShape_Impl *pSelShape = 0;
+ size_t nShapes = 0;
+
+
+ {
+ osl::MutexGuard aGuard( maMutex );
+ if( mpShapeMap )
+ pShapes = mpShapeMap->Copy( nShapes, pFESh, &pSelShape );
+ }
+
+ if( pShapes )
+ {
+ Window *pWin = GetShell()->GetWin();
+ sal_Bool bFocused = pWin && pWin->HasFocus();
+ SwAccessibleObjShape_Impl *pShape = pShapes;
+ while( nShapes )
+ {
+ if( pShape->second.is() )
+ {
+ if( bFocused && pShape >= pSelShape )
+ pShape->second->SetState( AccessibleStateType::FOCUSED );
+ else
+ pShape->second->ResetState( AccessibleStateType::FOCUSED );
+ }
+
+ --nShapes;
+ ++pShape;
+ }
+
+ delete[] pShapes;
+ }
+}
+
+
+SwAccessibleMap::SwAccessibleMap( ViewShell *pSh ) :
+ mpFrmMap( 0 ),
+ mpShapeMap( 0 ),
+ mpShapes( 0 ),
+ mpEvents( 0 ),
+ mpEventMap( 0 ),
+ mpSelectedParas( 0 ),
+ mpVSh( pSh ),
+ mpPreview( 0 ),
+ mnPara( 1 ),
+ mnFootnote( 1 ),
+ mnEndnote( 1 ),
+ mbShapeSelected( sal_False )
+{
+ pSh->GetLayout()->AddAccessibleShell();
+}
+
+SwAccessibleMap::~SwAccessibleMap()
+{
+ uno::Reference < XAccessible > xAcc;
+ {
+ osl::MutexGuard aGuard( maMutex );
+ if( mpFrmMap )
+ {
+ const SwRootFrm *pRootFrm = GetShell()->GetLayout();
+ SwAccessibleContextMap_Impl::iterator aIter = mpFrmMap->find( pRootFrm );
+ if( aIter != mpFrmMap->end() )
+ xAcc = (*aIter).second;
+ if( !xAcc.is() )
+ xAcc = new SwAccessibleDocument( this );
+ }
+ }
+
+ SwAccessibleDocument *pAcc =
+ static_cast< SwAccessibleDocument * >( xAcc.get() );
+ pAcc->Dispose( sal_True );
+
+ {
+ osl::MutexGuard aGuard( maMutex );
+#if OSL_DEBUG_LEVEL > 1
+ OSL_ENSURE( !mpFrmMap || mpFrmMap->empty(),
+ "Frame map should be empty after disposing the root frame" );
+ if( mpFrmMap )
+ {
+ SwAccessibleContextMap_Impl::iterator aIter = mpFrmMap->begin();
+ while( aIter != mpFrmMap->end() )
+ {
+ uno::Reference < XAccessible > xTmp = (*aIter).second;
+ if( xTmp.is() )
+ {
+ SwAccessibleContext *pTmp =
+ static_cast< SwAccessibleContext * >( xTmp.get() );
+ (void) pTmp;
+ }
+ ++aIter;
+ }
+ }
+ OSL_ENSURE( !mpShapeMap || mpShapeMap->empty(),
+ "Object map should be empty after disposing the root frame" );
+ if( mpShapeMap )
+ {
+ SwAccessibleShapeMap_Impl::iterator aIter = mpShapeMap->begin();
+ while( aIter != mpShapeMap->end() )
+ {
+ uno::Reference < XAccessible > xTmp = (*aIter).second;
+ if( xTmp.is() )
+ {
+ ::accessibility::AccessibleShape *pTmp =
+ static_cast< ::accessibility::AccessibleShape* >( xTmp.get() );
+ (void) pTmp;
+ }
+ ++aIter;
+ }
+ }
+#endif
+ delete mpFrmMap;
+ mpFrmMap = 0;
+ delete mpShapeMap;
+ mpShapeMap = 0;
+ delete mpShapes;
+ mpShapes = 0;
+ delete mpSelectedParas;
+ mpSelectedParas = 0;
+ }
+
+ delete mpPreview;
+ mpPreview = NULL;
+
+ {
+ osl::MutexGuard aGuard( maEventMutex );
+#if OSL_DEBUG_LEVEL > 1
+ OSL_ENSURE( !(mpEvents || mpEventMap), "pending events" );
+ if( mpEvents )
+ {
+ SwAccessibleEventList_Impl::iterator aIter = mpEvents->begin();
+ while( aIter != mpEvents->end() )
+ {
+ ++aIter;
+ }
+ }
+ if( mpEventMap )
+ {
+ SwAccessibleEventMap_Impl::iterator aIter = mpEventMap->begin();
+ while( aIter != mpEventMap->end() )
+ {
+ ++aIter;
+ }
+ }
+#endif
+ delete mpEventMap;
+ mpEventMap = 0;
+ delete mpEvents;
+ mpEvents = 0;
+ }
+ mpVSh->GetLayout()->RemoveAccessibleShell();
+}
+
+uno::Reference< XAccessible > SwAccessibleMap::_GetDocumentView(
+ sal_Bool bPagePreview )
+{
+ uno::Reference < XAccessible > xAcc;
+ sal_Bool bSetVisArea = sal_False;
+
+ {
+ osl::MutexGuard aGuard( maMutex );
+
+ if( !mpFrmMap )
+ {
+ mpFrmMap = new SwAccessibleContextMap_Impl;
+#if OSL_DEBUG_LEVEL > 1
+ mpFrmMap->mbLocked = sal_False;
+#endif
+ }
+
+#if OSL_DEBUG_LEVEL > 1
+ OSL_ENSURE( !mpFrmMap->mbLocked, "Map is locked" );
+ mpFrmMap->mbLocked = sal_True;
+#endif
+
+ const SwRootFrm *pRootFrm = GetShell()->GetLayout();
+ SwAccessibleContextMap_Impl::iterator aIter = mpFrmMap->find( pRootFrm );
+ if( aIter != mpFrmMap->end() )
+ xAcc = (*aIter).second;
+ if( xAcc.is() )
+ {
+ bSetVisArea = sal_True; // Set VisArea when map mutex is not
+ // locked
+ }
+ else
+ {
+ if( bPagePreview )
+ xAcc = new SwAccessiblePreview( this );
+ else
+ xAcc = new SwAccessibleDocument( this );
+
+ if( aIter != mpFrmMap->end() )
+ {
+ (*aIter).second = xAcc;
+ }
+ else
+ {
+ SwAccessibleContextMap_Impl::value_type aEntry( pRootFrm, xAcc );
+ mpFrmMap->insert( aEntry );
+ }
+ }
+
+#if OSL_DEBUG_LEVEL > 1
+ mpFrmMap->mbLocked = sal_False;
+#endif
+ }
+
+ if( bSetVisArea )
+ {
+ SwAccessibleDocumentBase *pAcc =
+ static_cast< SwAccessibleDocumentBase * >( xAcc.get() );
+ pAcc->SetVisArea();
+ }
+
+ return xAcc;
+}
+
+uno::Reference< XAccessible > SwAccessibleMap::GetDocumentView( )
+{
+ return _GetDocumentView( sal_False );
+}
+
+uno::Reference<XAccessible> SwAccessibleMap::GetDocumentPreview(
+ const std::vector<PrevwPage*>& _rPrevwPages,
+ const Fraction& _rScale,
+ const SwPageFrm* _pSelectedPageFrm,
+ const Size& _rPrevwWinSize )
+{
+ // create & update preview data object
+ if( mpPreview == NULL )
+ mpPreview = new SwAccPreviewData();
+ mpPreview->Update( *this, _rPrevwPages, _rScale, _pSelectedPageFrm, _rPrevwWinSize );
+
+ uno::Reference<XAccessible> xAcc = _GetDocumentView( sal_True );
+ return xAcc;
+}
+
+uno::Reference< XAccessible> SwAccessibleMap::GetContext( const SwFrm *pFrm,
+ sal_Bool bCreate )
+{
+ uno::Reference < XAccessible > xAcc;
+ uno::Reference < XAccessible > xOldCursorAcc;
+ sal_Bool bOldShapeSelected = sal_False;
+
+ {
+ osl::MutexGuard aGuard( maMutex );
+
+ if( !mpFrmMap && bCreate )
+ mpFrmMap = new SwAccessibleContextMap_Impl;
+ if( mpFrmMap )
+ {
+ SwAccessibleContextMap_Impl::iterator aIter = mpFrmMap->find( pFrm );
+ if( aIter != mpFrmMap->end() )
+ xAcc = (*aIter).second;
+
+ if( !xAcc.is() && bCreate )
+ {
+ SwAccessibleContext *pAcc = 0;
+ switch( pFrm->GetType() )
+ {
+ case FRM_TXT:
+ mnPara++;
+ pAcc = new SwAccessibleParagraph( *this,
+ static_cast< const SwTxtFrm& >( *pFrm ) );
+ break;
+ case FRM_HEADER:
+ pAcc = new SwAccessibleHeaderFooter( this,
+ static_cast< const SwHeaderFrm *>( pFrm ) );
+ break;
+ case FRM_FOOTER:
+ pAcc = new SwAccessibleHeaderFooter( this,
+ static_cast< const SwFooterFrm *>( pFrm ) );
+ break;
+ case FRM_FTN:
+ {
+ const SwFtnFrm *pFtnFrm =
+ static_cast < const SwFtnFrm * >( pFrm );
+ sal_Bool bIsEndnote =
+ SwAccessibleFootnote::IsEndnote( pFtnFrm );
+ pAcc = new SwAccessibleFootnote( this, bIsEndnote,
+ (bIsEndnote ? mnEndnote++ : mnFootnote++),
+ pFtnFrm );
+ }
+ break;
+ case FRM_FLY:
+ {
+ const SwFlyFrm *pFlyFrm =
+ static_cast < const SwFlyFrm * >( pFrm );
+ switch( SwAccessibleFrameBase::GetNodeType( pFlyFrm ) )
+ {
+ case ND_GRFNODE:
+ pAcc = new SwAccessibleGraphic( this, pFlyFrm );
+ break;
+ case ND_OLENODE:
+ pAcc = new SwAccessibleEmbeddedObject( this, pFlyFrm );
+ break;
+ default:
+ pAcc = new SwAccessibleTextFrame( this, pFlyFrm );
+ break;
+ }
+ }
+ break;
+ case FRM_CELL:
+ pAcc = new SwAccessibleCell( this,
+ static_cast< const SwCellFrm *>( pFrm ) );
+ break;
+ case FRM_TAB:
+ pAcc = new SwAccessibleTable( this,
+ static_cast< const SwTabFrm *>( pFrm ) );
+ break;
+ case FRM_PAGE:
+ DBG_ASSERT( GetShell()->IsPreView(),
+ "accessible page frames only in PagePreview" );
+ pAcc = new SwAccessiblePage( this, pFrm );
+ break;
+ }
+ xAcc = pAcc;
+
+ OSL_ENSURE( xAcc.is(), "unknown frame type" );
+ if( xAcc.is() )
+ {
+ if( aIter != mpFrmMap->end() )
+ {
+ (*aIter).second = xAcc;
+ }
+ else
+ {
+ SwAccessibleContextMap_Impl::value_type aEntry( pFrm, xAcc );
+ mpFrmMap->insert( aEntry );
+ }
+
+ if( pAcc->HasCursor() &&
+ !AreInSameTable( mxCursorContext, pFrm ) )
+ {
+ // If the new context has the focus, and if we know
+ // another context that had the focus, then the focus
+ // just moves from the old context to the new one. We
+ // have to send a focus event and a caret event for
+ // the old context then. We have to to that know,
+ // because after we have left this method, anyone might
+ // call getStates for the new context and will get a
+ // focused state then. Sending the focus changes event
+ // after that seems to be strange. However, we cannot
+ // send a focus event fo the new context now, because
+ // noone except us knows it. In any case, we remeber
+ // the new context as the one that has the focus
+ // currently.
+
+ xOldCursorAcc = mxCursorContext;
+ mxCursorContext = xAcc;
+
+ bOldShapeSelected = mbShapeSelected;
+ mbShapeSelected = sal_False;
+ }
+ }
+ }
+ }
+ }
+
+ // Invalidate focus for old object when map is not locked
+ if( xOldCursorAcc.is() )
+ InvalidateCursorPosition( xOldCursorAcc );
+ if( bOldShapeSelected )
+ InvalidateShapeSelection();
+
+ return xAcc;
+}
+
+::rtl::Reference < SwAccessibleContext > SwAccessibleMap::GetContextImpl(
+ const SwFrm *pFrm,
+ sal_Bool bCreate )
+{
+ uno::Reference < XAccessible > xAcc( GetContext( pFrm, bCreate ) );
+
+ ::rtl::Reference < SwAccessibleContext > xAccImpl(
+ static_cast< SwAccessibleContext * >( xAcc.get() ) );
+
+ return xAccImpl;
+}
+
+uno::Reference< XAccessible> SwAccessibleMap::GetContext(
+ const SdrObject *pObj,
+ SwAccessibleContext *pParentImpl,
+ sal_Bool bCreate )
+{
+ uno::Reference < XAccessible > xAcc;
+ uno::Reference < XAccessible > xOldCursorAcc;
+
+ {
+ osl::MutexGuard aGuard( maMutex );
+
+ if( !mpShapeMap && bCreate )
+ mpShapeMap = new SwAccessibleShapeMap_Impl( this );
+ if( mpShapeMap )
+ {
+ SwAccessibleShapeMap_Impl::iterator aIter =
+ mpShapeMap->find( pObj );
+ if( aIter != mpShapeMap->end() )
+ xAcc = (*aIter).second;
+
+ if( !xAcc.is() && bCreate )
+ {
+ ::accessibility::AccessibleShape *pAcc = 0;
+ uno::Reference < drawing::XShape > xShape(
+ const_cast< SdrObject * >( pObj )->getUnoShape(),
+ uno::UNO_QUERY );
+ if( xShape.is() )
+ {
+ ::accessibility::ShapeTypeHandler& rShapeTypeHandler =
+ ::accessibility::ShapeTypeHandler::Instance();
+ uno::Reference < XAccessible > xParent( pParentImpl );
+ ::accessibility::AccessibleShapeInfo aShapeInfo(
+ xShape, xParent, this );
+
+ pAcc = rShapeTypeHandler.CreateAccessibleObject(
+ aShapeInfo, mpShapeMap->GetInfo() );
+ }
+ xAcc = pAcc;
+
+ OSL_ENSURE( xAcc.is(), "unknown shape type" );
+ if( xAcc.is() )
+ {
+ pAcc->Init();
+ if( aIter != mpShapeMap->end() )
+ {
+ (*aIter).second = xAcc;
+ }
+ else
+ {
+ SwAccessibleShapeMap_Impl::value_type aEntry( pObj,
+ xAcc );
+ mpShapeMap->insert( aEntry );
+ }
+ // TODO: focus!!!
+ }
+ }
+ }
+ }
+
+ // Invalidate focus for old object when map is not locked
+ if( xOldCursorAcc.is() )
+ InvalidateCursorPosition( xOldCursorAcc );
+
+ return xAcc;
+}
+
+::rtl::Reference < ::accessibility::AccessibleShape > SwAccessibleMap::GetContextImpl(
+ const SdrObject *pObj,
+ SwAccessibleContext *pParentImpl,
+ sal_Bool bCreate )
+{
+ uno::Reference < XAccessible > xAcc( GetContext( pObj, pParentImpl, bCreate ) );
+
+ ::rtl::Reference < ::accessibility::AccessibleShape > xAccImpl(
+ static_cast< ::accessibility::AccessibleShape* >( xAcc.get() ) );
+
+ return xAccImpl;
+}
+
+
+void SwAccessibleMap::RemoveContext( const SwFrm *pFrm )
+{
+ osl::MutexGuard aGuard( maMutex );
+
+ if( mpFrmMap )
+ {
+ SwAccessibleContextMap_Impl::iterator aIter =
+ mpFrmMap->find( pFrm );
+ if( aIter != mpFrmMap->end() )
+ {
+ mpFrmMap->erase( aIter );
+
+ // Remove reference to old caret object. Though mxCursorContext
+ // is a weak reference and cleared automatically, clearing it
+ // directly makes sure to not keep a defunctional object.
+ uno::Reference < XAccessible > xOldAcc( mxCursorContext );
+ if( xOldAcc.is() )
+ {
+ SwAccessibleContext *pOldAccImpl =
+ static_cast< SwAccessibleContext *>( xOldAcc.get() );
+ OSL_ENSURE( pOldAccImpl->GetFrm(), "old caret context is disposed" );
+ if( pOldAccImpl->GetFrm() == pFrm )
+ {
+ xOldAcc.clear(); // get an empty ref
+ mxCursorContext = xOldAcc;
+ }
+ }
+
+ if( mpFrmMap->empty() )
+ {
+ delete mpFrmMap;
+ mpFrmMap = 0;
+ }
+ }
+ }
+}
+
+void SwAccessibleMap::RemoveContext( const SdrObject *pObj )
+{
+ osl::MutexGuard aGuard( maMutex );
+
+ if( mpShapeMap )
+ {
+ SwAccessibleShapeMap_Impl::iterator aIter =
+ mpShapeMap->find( pObj );
+ if( aIter != mpShapeMap->end() )
+ {
+ mpShapeMap->erase( aIter );
+
+ // The shape selection flag is not cleared, but one might do
+ // so but has to make sure that the removed context is the one
+ // that is selected.
+
+ if( mpShapeMap->empty() )
+ {
+ delete mpShapeMap;
+ mpShapeMap = 0;
+ }
+ }
+ }
+}
+
+
+void SwAccessibleMap::Dispose( const SwFrm *pFrm,
+ const SdrObject *pObj,
+ Window* pWindow,
+ sal_Bool bRecursive )
+{
+ SwAccessibleChild aFrmOrObj( pFrm, pObj, pWindow );
+
+ // Indeed, the following assert checks the frame's accessible flag,
+ // because that's the one that is evaluated in the layout. The frame
+ // might not be accessible anyway. That's the case for cell frames that
+ // contain further cells.
+ OSL_ENSURE( !aFrmOrObj.GetSwFrm() || aFrmOrObj.GetSwFrm()->IsAccessibleFrm(),
+ "non accessible frame should be disposed" );
+
+ if( aFrmOrObj.IsAccessible( GetShell()->IsPreView() ) )
+ {
+ ::rtl::Reference< SwAccessibleContext > xAccImpl;
+ ::rtl::Reference< SwAccessibleContext > xParentAccImpl;
+ ::rtl::Reference< ::accessibility::AccessibleShape > xShapeAccImpl;
+ // get accessible context for frame
+ {
+ osl::MutexGuard aGuard( maMutex );
+
+ // First of all look for an accessible context for a frame
+ if( aFrmOrObj.GetSwFrm() && mpFrmMap )
+ {
+ SwAccessibleContextMap_Impl::iterator aIter =
+ mpFrmMap->find( aFrmOrObj.GetSwFrm() );
+ if( aIter != mpFrmMap->end() )
+ {
+ uno::Reference < XAccessible > xAcc( (*aIter).second );
+ xAccImpl =
+ static_cast< SwAccessibleContext *>( xAcc.get() );
+ }
+ }
+ if( !xAccImpl.is() && mpFrmMap )
+ {
+ // If there is none, look if the parent is accessible.
+ const SwFrm *pParent =
+ SwAccessibleFrame::GetParent( aFrmOrObj,
+ GetShell()->IsPreView());
+
+ if( pParent )
+ {
+ SwAccessibleContextMap_Impl::iterator aIter =
+ mpFrmMap->find( pParent );
+ if( aIter != mpFrmMap->end() )
+ {
+ uno::Reference < XAccessible > xAcc( (*aIter).second );
+ xParentAccImpl =
+ static_cast< SwAccessibleContext *>( xAcc.get() );
+ }
+ }
+ }
+ if( !xParentAccImpl.is() && !aFrmOrObj.GetSwFrm() &&
+ mpShapeMap )
+ {
+ SwAccessibleShapeMap_Impl::iterator aIter =
+ mpShapeMap->find( aFrmOrObj.GetDrawObject() );
+ if( aIter != mpShapeMap->end() )
+ {
+ uno::Reference < XAccessible > xAcc( (*aIter).second );
+ xShapeAccImpl =
+ static_cast< ::accessibility::AccessibleShape *>( xAcc.get() );
+ }
+ }
+ if( pObj && GetShell()->ActionPend() &&
+ (xParentAccImpl.is() || xShapeAccImpl.is()) )
+ {
+ // Keep a reference to the XShape to avoid that it
+ // is deleted with a SwFrmFmt::Modify.
+ uno::Reference < drawing::XShape > xShape(
+ const_cast< SdrObject * >( pObj )->getUnoShape(),
+ uno::UNO_QUERY );
+ if( xShape.is() )
+ {
+ if( !mpShapes )
+ mpShapes = new SwShapeList_Impl;
+ mpShapes->push_back( xShape );
+ }
+ }
+ }
+
+ // remove events stored for the frame
+ {
+ osl::MutexGuard aGuard( maEventMutex );
+ if( mpEvents )
+ {
+ SwAccessibleEventMap_Impl::iterator aIter =
+ mpEventMap->find( aFrmOrObj );
+ if( aIter != mpEventMap->end() )
+ {
+ SwAccessibleEvent_Impl aEvent(
+ SwAccessibleEvent_Impl::DISPOSE, aFrmOrObj );
+ AppendEvent( aEvent );
+ }
+ }
+ }
+
+ // If the frame is accessible and there is a context for it, dispose
+ // the frame. If the frame is no context for it but disposing should
+ // take place recursive, the frame's children have to be disposed
+ // anyway, so we have to create the context then.
+ if( xAccImpl.is() )
+ {
+ xAccImpl->Dispose( bRecursive );
+ }
+ else if( xParentAccImpl.is() )
+ {
+ // If the frame is a cell frame, the table must be notified.
+ // If we are in an action, a table model change event will
+ // be broadcasted at the end of the action to give the table
+ // a chance to generate a single table change event.
+
+ xParentAccImpl->DisposeChild( aFrmOrObj, bRecursive );
+ }
+ else if( xShapeAccImpl.is() )
+ {
+ RemoveContext( aFrmOrObj.GetDrawObject() );
+ xShapeAccImpl->dispose();
+ }
+
+ if( mpPreview && pFrm && pFrm->IsPageFrm() )
+ mpPreview->DisposePage( static_cast< const SwPageFrm *>( pFrm ) );
+ }
+}
+
+void SwAccessibleMap::InvalidatePosOrSize( const SwFrm *pFrm,
+ const SdrObject *pObj,
+ Window* pWindow,
+ const SwRect& rOldBox )
+{
+ SwAccessibleChild aFrmOrObj( pFrm, pObj, pWindow );
+ if( aFrmOrObj.IsAccessible( GetShell()->IsPreView() ) )
+ {
+ ::rtl::Reference< SwAccessibleContext > xAccImpl;
+ ::rtl::Reference< SwAccessibleContext > xParentAccImpl;
+ {
+ osl::MutexGuard aGuard( maMutex );
+
+ if( mpFrmMap )
+ {
+ if( aFrmOrObj.GetSwFrm() )
+ {
+ SwAccessibleContextMap_Impl::iterator aIter =
+ mpFrmMap->find( aFrmOrObj.GetSwFrm() );
+ if( aIter != mpFrmMap->end() )
+ {
+ // If there is an accesible object already it is
+ // notified directly.
+ uno::Reference < XAccessible > xAcc( (*aIter).second );
+ xAccImpl =
+ static_cast< SwAccessibleContext *>( xAcc.get() );
+ }
+ }
+ if( !xAccImpl.is() )
+ {
+ // Otherwise we look if the parent is accessible.
+ // If not, there is nothing to do.
+ const SwFrm *pParent =
+ SwAccessibleFrame::GetParent( aFrmOrObj,
+ GetShell()->IsPreView());
+
+ if( pParent )
+ {
+ SwAccessibleContextMap_Impl::iterator aIter =
+ mpFrmMap->find( pParent );
+ if( aIter != mpFrmMap->end() )
+ {
+ uno::Reference < XAccessible > xAcc( (*aIter).second );
+ xParentAccImpl =
+ static_cast< SwAccessibleContext *>( xAcc.get() );
+ }
+ }
+ }
+ }
+ }
+
+ if( xAccImpl.is() )
+ {
+ if( GetShell()->ActionPend() )
+ {
+ SwAccessibleEvent_Impl aEvent(
+ SwAccessibleEvent_Impl::POS_CHANGED, xAccImpl.get(),
+ aFrmOrObj, rOldBox );
+ AppendEvent( aEvent );
+ }
+ else
+ {
+ FireEvents();
+ xAccImpl->InvalidatePosOrSize( rOldBox );
+ }
+ }
+ else if( xParentAccImpl.is() )
+ {
+ if( GetShell()->ActionPend() )
+ {
+ SwAccessibleEvent_Impl aEvent(
+ SwAccessibleEvent_Impl::CHILD_POS_CHANGED,
+ xParentAccImpl.get(), aFrmOrObj, rOldBox );
+ AppendEvent( aEvent );
+ }
+ else
+ {
+ FireEvents();
+ xParentAccImpl->InvalidateChildPosOrSize( aFrmOrObj,
+ rOldBox );
+ }
+ }
+ }
+}
+
+void SwAccessibleMap::InvalidateContent( const SwFrm *pFrm )
+{
+ SwAccessibleChild aFrmOrObj( pFrm );
+ if( aFrmOrObj.IsAccessible( GetShell()->IsPreView() ) )
+ {
+ uno::Reference < XAccessible > xAcc;
+ {
+ osl::MutexGuard aGuard( maMutex );
+
+ if( mpFrmMap )
+ {
+ SwAccessibleContextMap_Impl::iterator aIter =
+ mpFrmMap->find( aFrmOrObj.GetSwFrm() );
+ if( aIter != mpFrmMap->end() )
+ xAcc = (*aIter).second;
+ }
+ }
+
+ if( xAcc.is() )
+ {
+ SwAccessibleContext *pAccImpl =
+ static_cast< SwAccessibleContext *>( xAcc.get() );
+ if( GetShell()->ActionPend() )
+ {
+ SwAccessibleEvent_Impl aEvent(
+ SwAccessibleEvent_Impl::INVALID_CONTENT, pAccImpl,
+ aFrmOrObj );
+ AppendEvent( aEvent );
+ }
+ else
+ {
+ FireEvents();
+ pAccImpl->InvalidateContent();
+ }
+ }
+ }
+}
+
+void SwAccessibleMap::InvalidateAttr( const SwTxtFrm& rTxtFrm )
+{
+ SwAccessibleChild aFrmOrObj( &rTxtFrm );
+ if( aFrmOrObj.IsAccessible( GetShell()->IsPreView() ) )
+ {
+ uno::Reference < XAccessible > xAcc;
+ {
+ osl::MutexGuard aGuard( maMutex );
+
+ if( mpFrmMap )
+ {
+ SwAccessibleContextMap_Impl::iterator aIter =
+ mpFrmMap->find( aFrmOrObj.GetSwFrm() );
+ if( aIter != mpFrmMap->end() )
+ xAcc = (*aIter).second;
+ }
+ }
+
+ if( xAcc.is() )
+ {
+ SwAccessibleContext *pAccImpl =
+ static_cast< SwAccessibleContext *>( xAcc.get() );
+ if( GetShell()->ActionPend() )
+ {
+ SwAccessibleEvent_Impl aEvent( SwAccessibleEvent_Impl::INVALID_ATTR,
+ pAccImpl, aFrmOrObj );
+ aEvent.SetStates( ACC_STATE_TEXT_ATTRIBUTE_CHANGED );
+ AppendEvent( aEvent );
+ }
+ else
+ {
+ FireEvents();
+ pAccImpl->InvalidateAttr();
+ }
+ }
+ }
+}
+
+void SwAccessibleMap::InvalidateCursorPosition( const SwFrm *pFrm )
+{
+ SwAccessibleChild aFrmOrObj( pFrm );
+ sal_Bool bShapeSelected = sal_False;
+ const ViewShell *pVSh = GetShell();
+ if( pVSh->ISA( SwCrsrShell ) )
+ {
+ const SwCrsrShell *pCSh = static_cast< const SwCrsrShell * >( pVSh );
+ if( pCSh->IsTableMode() )
+ {
+ while( aFrmOrObj.GetSwFrm() && !aFrmOrObj.GetSwFrm()->IsCellFrm() )
+ aFrmOrObj = aFrmOrObj.GetSwFrm()->GetUpper();
+ }
+ else if( pVSh->ISA( SwFEShell ) )
+ {
+ const SwFEShell *pFESh = static_cast< const SwFEShell * >( pVSh );
+ const SwFrm *pFlyFrm = pFESh->GetCurrFlyFrm();
+ if( pFlyFrm )
+ {
+ OSL_ENSURE( !pFrm || pFrm->FindFlyFrm() == pFlyFrm,
+ "cursor is not contained in fly frame" );
+ aFrmOrObj = pFlyFrm;
+ }
+ else if( pFESh->IsObjSelected() > 0 )
+ {
+ bShapeSelected = sal_True;
+ aFrmOrObj = static_cast<const SwFrm *>( 0 );
+ }
+ }
+ }
+
+ OSL_ENSURE( bShapeSelected || aFrmOrObj.IsAccessible(GetShell()->IsPreView()),
+ "frame is not accessible" );
+
+ uno::Reference < XAccessible > xOldAcc;
+ uno::Reference < XAccessible > xAcc;
+ sal_Bool bOldShapeSelected = sal_False;
+
+ {
+ osl::MutexGuard aGuard( maMutex );
+
+ xOldAcc = mxCursorContext;
+ mxCursorContext = xAcc; // clear reference
+
+ bOldShapeSelected = mbShapeSelected;
+ mbShapeSelected = bShapeSelected;
+
+ if( aFrmOrObj.GetSwFrm() && mpFrmMap )
+ {
+ SwAccessibleContextMap_Impl::iterator aIter =
+ mpFrmMap->find( aFrmOrObj.GetSwFrm() );
+ if( aIter != mpFrmMap->end() )
+ xAcc = (*aIter).second;
+
+ // For cells, some extra thoughts are necessary,
+ // because invalidating the cursor for one cell
+ // invalidates the cursor for all cells of the same
+ // table. For this reason, we don't want to
+ // invalidate the cursor for the old cursor object
+ // and the new one if they are within the same table,
+ // because this would result in doing the work twice.
+ // Moreover, we have to make sure to invalidate the
+ // cursor even if the current cell has no accessible object.
+ // If the old cursor objects exists and is in the same
+ // table, its the best choice, because using it avoids
+ // an unnessarary cursor invalidation cycle when creating
+ // a new object for the current cell.
+ if( aFrmOrObj.GetSwFrm()->IsCellFrm() )
+ {
+ if( xOldAcc.is() &&
+ AreInSameTable( xOldAcc, aFrmOrObj.GetSwFrm() ) )
+ {
+ if( xAcc.is() )
+ xOldAcc = xAcc; // avoid extra invalidation
+ else
+ xAcc = xOldAcc; // make sure ate least one
+ }
+ if( !xAcc.is() )
+ xAcc = GetContext( aFrmOrObj.GetSwFrm(), sal_True );
+ }
+ }
+ }
+
+ if( xOldAcc.is() && xOldAcc != xAcc )
+ InvalidateCursorPosition( xOldAcc );
+ if( bOldShapeSelected || bShapeSelected )
+ InvalidateShapeSelection();
+ if( xAcc.is() )
+ InvalidateCursorPosition( xAcc );
+}
+
+void SwAccessibleMap::InvalidateFocus()
+{
+ uno::Reference < XAccessible > xAcc;
+ sal_Bool bShapeSelected;
+ {
+ osl::MutexGuard aGuard( maMutex );
+
+ xAcc = mxCursorContext;
+ bShapeSelected = mbShapeSelected;
+ }
+
+ if( xAcc.is() )
+ {
+ SwAccessibleContext *pAccImpl =
+ static_cast< SwAccessibleContext *>( xAcc.get() );
+ pAccImpl->InvalidateFocus();
+ }
+ else if( bShapeSelected )
+ {
+ DoInvalidateShapeFocus();
+ }
+}
+
+void SwAccessibleMap::SetCursorContext(
+ const ::rtl::Reference < SwAccessibleContext >& rCursorContext )
+{
+ osl::MutexGuard aGuard( maMutex );
+ uno::Reference < XAccessible > xAcc( rCursorContext.get() );
+ mxCursorContext = xAcc;
+}
+
+void SwAccessibleMap::InvalidateStates( tAccessibleStates _nStates,
+ const SwFrm* _pFrm )
+{
+ // Start with the frame or the first upper that is accessible
+ SwAccessibleChild aFrmOrObj( _pFrm );
+ while( aFrmOrObj.GetSwFrm() &&
+ !aFrmOrObj.IsAccessible( GetShell()->IsPreView() ) )
+ aFrmOrObj = aFrmOrObj.GetSwFrm()->GetUpper();
+ if( !aFrmOrObj.GetSwFrm() )
+ aFrmOrObj = GetShell()->GetLayout();
+
+ uno::Reference< XAccessible > xAcc( GetContext( aFrmOrObj.GetSwFrm(), sal_True ) );
+ SwAccessibleContext *pAccImpl =
+ static_cast< SwAccessibleContext *>( xAcc.get() );
+ if( GetShell()->ActionPend() )
+ {
+ SwAccessibleEvent_Impl aEvent( SwAccessibleEvent_Impl::CARET_OR_STATES,
+ pAccImpl,
+ SwAccessibleChild(pAccImpl->GetFrm()),
+ _nStates );
+ AppendEvent( aEvent );
+ }
+ else
+ {
+ FireEvents();
+ pAccImpl->InvalidateStates( _nStates );
+ }
+}
+
+void SwAccessibleMap::_InvalidateRelationSet( const SwFrm* pFrm,
+ sal_Bool bFrom )
+{
+ // first, see if this frame is accessible, and if so, get the respective
+ SwAccessibleChild aFrmOrObj( pFrm );
+ if( aFrmOrObj.IsAccessible( GetShell()->IsPreView() ) )
+ {
+ uno::Reference < XAccessible > xAcc;
+ {
+ osl::MutexGuard aGuard( maMutex );
+
+ if( mpFrmMap )
+ {
+ SwAccessibleContextMap_Impl::iterator aIter =
+ mpFrmMap->find( aFrmOrObj.GetSwFrm() );
+ if( aIter != mpFrmMap->end() )
+ {
+ xAcc = (*aIter).second;
+ }
+ }
+ }
+
+ // deliver event directly, or queue event
+ if( xAcc.is() )
+ {
+ SwAccessibleContext *pAccImpl =
+ static_cast< SwAccessibleContext *>( xAcc.get() );
+ if( GetShell()->ActionPend() )
+ {
+ SwAccessibleEvent_Impl aEvent( SwAccessibleEvent_Impl::CARET_OR_STATES,
+ pAccImpl, SwAccessibleChild(pFrm),
+ ( bFrom
+ ? ACC_STATE_RELATION_FROM
+ : ACC_STATE_RELATION_TO ) );
+ AppendEvent( aEvent );
+ }
+ else
+ {
+ FireEvents();
+ pAccImpl->InvalidateRelation( bFrom
+ ? AccessibleEventId::CONTENT_FLOWS_FROM_RELATION_CHANGED
+ : AccessibleEventId::CONTENT_FLOWS_TO_RELATION_CHANGED );
+ }
+ }
+ }
+}
+
+void SwAccessibleMap::InvalidateRelationSet( const SwFrm* pMaster,
+ const SwFrm* pFollow )
+{
+ _InvalidateRelationSet( pMaster, sal_False );
+ _InvalidateRelationSet( pFollow, sal_True );
+}
+
+// invalidation of CONTENT_FLOW_FROM/_TO relation of a paragraph
+void SwAccessibleMap::InvalidateParaFlowRelation( const SwTxtFrm& _rTxtFrm,
+ const bool _bFrom )
+{
+ _InvalidateRelationSet( &_rTxtFrm, _bFrom );
+}
+
+// invalidation of text selection of a paragraph
+void SwAccessibleMap::InvalidateParaTextSelection( const SwTxtFrm& _rTxtFrm )
+{
+ // first, see if this frame is accessible, and if so, get the respective
+ SwAccessibleChild aFrmOrObj( &_rTxtFrm );
+ if( aFrmOrObj.IsAccessible( GetShell()->IsPreView() ) )
+ {
+ uno::Reference < XAccessible > xAcc;
+ {
+ osl::MutexGuard aGuard( maMutex );
+
+ if( mpFrmMap )
+ {
+ SwAccessibleContextMap_Impl::iterator aIter =
+ mpFrmMap->find( aFrmOrObj.GetSwFrm() );
+ if( aIter != mpFrmMap->end() )
+ {
+ xAcc = (*aIter).second;
+ }
+ }
+ }
+
+ // deliver event directly, or queue event
+ if( xAcc.is() )
+ {
+ SwAccessibleContext *pAccImpl =
+ static_cast< SwAccessibleContext *>( xAcc.get() );
+ if( GetShell()->ActionPend() )
+ {
+ SwAccessibleEvent_Impl aEvent(
+ SwAccessibleEvent_Impl::CARET_OR_STATES,
+ pAccImpl,
+ SwAccessibleChild( &_rTxtFrm ),
+ ACC_STATE_TEXT_SELECTION_CHANGED );
+ AppendEvent( aEvent );
+ }
+ else
+ {
+ FireEvents();
+ pAccImpl->InvalidateTextSelection();
+ }
+ }
+ }
+}
+
+sal_Int32 SwAccessibleMap::GetChildIndex( const SwFrm& rParentFrm,
+ Window& rChild ) const
+{
+ sal_Int32 nIndex( -1 );
+
+ SwAccessibleChild aFrmOrObj( &rParentFrm );
+ if( aFrmOrObj.IsAccessible( GetShell()->IsPreView() ) )
+ {
+ uno::Reference < XAccessible > xAcc;
+ {
+ osl::MutexGuard aGuard( maMutex );
+
+ if( mpFrmMap )
+ {
+ SwAccessibleContextMap_Impl::iterator aIter =
+ mpFrmMap->find( aFrmOrObj.GetSwFrm() );
+ if( aIter != mpFrmMap->end() )
+ {
+ xAcc = (*aIter).second;
+ }
+ }
+ }
+
+ if( xAcc.is() )
+ {
+ SwAccessibleContext *pAccImpl =
+ static_cast< SwAccessibleContext *>( xAcc.get() );
+
+ nIndex = pAccImpl->GetChildIndex( const_cast<SwAccessibleMap&>(*this),
+ SwAccessibleChild( &rChild ) );
+ }
+ }
+
+ return nIndex;
+}
+
+void SwAccessibleMap::UpdatePreview( const std::vector<PrevwPage*>& _rPrevwPages,
+ const Fraction& _rScale,
+ const SwPageFrm* _pSelectedPageFrm,
+ const Size& _rPrevwWinSize )
+{
+ DBG_ASSERT( GetShell()->IsPreView(), "no preview?" );
+ DBG_ASSERT( mpPreview != NULL, "no preview data?" );
+
+ mpPreview->Update( *this, _rPrevwPages, _rScale, _pSelectedPageFrm, _rPrevwWinSize );
+
+ // propagate change of VisArea through the document's
+ // accessibility tree; this will also send appropriate scroll
+ // events
+ SwAccessibleContext* pDoc =
+ GetContextImpl( GetShell()->GetLayout() ).get();
+ static_cast<SwAccessibleDocumentBase*>( pDoc )->SetVisArea();
+
+ uno::Reference < XAccessible > xOldAcc;
+ uno::Reference < XAccessible > xAcc;
+ {
+ osl::MutexGuard aGuard( maMutex );
+
+ xOldAcc = mxCursorContext;
+
+ const SwPageFrm *pSelPage = mpPreview->GetSelPage();
+ if( pSelPage && mpFrmMap )
+ {
+ SwAccessibleContextMap_Impl::iterator aIter =
+ mpFrmMap->find( pSelPage );
+ if( aIter != mpFrmMap->end() )
+ xAcc = (*aIter).second;
+ }
+ }
+
+ if( xOldAcc.is() && xOldAcc != xAcc )
+ InvalidateCursorPosition( xOldAcc );
+ if( xAcc.is() )
+ InvalidateCursorPosition( xAcc );
+}
+
+void SwAccessibleMap::InvalidatePreViewSelection( sal_uInt16 nSelPage )
+{
+ DBG_ASSERT( GetShell()->IsPreView(), "no preview?" );
+ DBG_ASSERT( mpPreview != NULL, "no preview data?" );
+
+ mpPreview->InvalidateSelection( GetShell()->GetLayout()->GetPageByPageNum( nSelPage ) );
+
+ uno::Reference < XAccessible > xOldAcc;
+ uno::Reference < XAccessible > xAcc;
+ {
+ osl::MutexGuard aGuard( maMutex );
+
+ xOldAcc = mxCursorContext;
+
+ const SwPageFrm *pSelPage = mpPreview->GetSelPage();
+ if( pSelPage && mpFrmMap )
+ {
+ SwAccessibleContextMap_Impl::iterator aIter =
+ mpFrmMap->find( pSelPage );
+ if( aIter != mpFrmMap->end() )
+ xAcc = (*aIter).second;
+ }
+ }
+
+ if( xOldAcc.is() && xOldAcc != xAcc )
+ InvalidateCursorPosition( xOldAcc );
+ if( xAcc.is() )
+ InvalidateCursorPosition( xAcc );
+}
+
+
+sal_Bool SwAccessibleMap::IsPageSelected( const SwPageFrm *pPageFrm ) const
+{
+ return mpPreview && mpPreview->GetSelPage() == pPageFrm;
+}
+
+
+void SwAccessibleMap::FireEvents()
+{
+ {
+ osl::MutexGuard aGuard( maEventMutex );
+ if( mpEvents )
+ {
+ mpEvents->SetFiring();
+ SwAccessibleEventList_Impl::iterator aIter = mpEvents->begin();
+ while( aIter != mpEvents->end() )
+ {
+ FireEvent( *aIter );
+ ++aIter;
+ }
+
+ delete mpEventMap;
+ mpEventMap = 0;
+
+ delete mpEvents;
+ mpEvents = 0;
+ }
+ }
+ {
+ osl::MutexGuard aGuard( maMutex );
+ if( mpShapes )
+ {
+ delete mpShapes;
+ mpShapes = 0;
+ }
+ }
+
+}
+
+sal_Bool SwAccessibleMap::IsValid() const
+{
+ return sal_True;
+}
+
+Rectangle SwAccessibleMap::GetVisibleArea() const
+{
+ MapMode aSrc( MAP_TWIP );
+ MapMode aDest( MAP_100TH_MM );
+ return OutputDevice::LogicToLogic( GetVisArea().SVRect(), aSrc, aDest );
+}
+
+// Convert a MM100 value realtive to the document root into a pixel value
+// realtive to the screen!
+Point SwAccessibleMap::LogicToPixel( const Point& rPoint ) const
+{
+ MapMode aSrc( MAP_100TH_MM );
+ MapMode aDest( MAP_TWIP );
+
+ Point aPoint = rPoint;
+
+ aPoint = OutputDevice::LogicToLogic( aPoint, aSrc, aDest );
+ Window *pWin = GetShell()->GetWin();
+ if( pWin )
+ {
+ MapMode aMapMode;
+ GetMapMode( aPoint, aMapMode );
+ aPoint = pWin->LogicToPixel( aPoint, aMapMode );
+ aPoint = pWin->OutputToAbsoluteScreenPixel( aPoint );
+ }
+
+ return aPoint;
+}
+
+Size SwAccessibleMap::LogicToPixel( const Size& rSize ) const
+{
+ MapMode aSrc( MAP_100TH_MM );
+ MapMode aDest( MAP_TWIP );
+ Size aSize( OutputDevice::LogicToLogic( rSize, aSrc, aDest ) );
+ if( GetShell()->GetWin() )
+ {
+ MapMode aMapMode;
+ GetMapMode( Point(0,0), aMapMode );
+ aSize = GetShell()->GetWin()->LogicToPixel( aSize, aMapMode );
+ }
+
+ return aSize;
+}
+
+Point SwAccessibleMap::PixelToLogic( const Point& rPoint ) const
+{
+ Point aPoint;
+ Window *pWin = GetShell()->GetWin();
+ if( pWin )
+ {
+ aPoint = pWin->ScreenToOutputPixel( rPoint );
+ MapMode aMapMode;
+ GetMapMode( aPoint, aMapMode );
+ aPoint = pWin->PixelToLogic( aPoint, aMapMode );
+ MapMode aSrc( MAP_TWIP );
+ MapMode aDest( MAP_100TH_MM );
+ aPoint = OutputDevice::LogicToLogic( aPoint, aSrc, aDest );
+ }
+
+ return aPoint;
+}
+
+Size SwAccessibleMap::PixelToLogic( const Size& rSize ) const
+{
+ Size aSize;
+ if( GetShell()->GetWin() )
+ {
+ MapMode aMapMode;
+ GetMapMode( Point(0,0), aMapMode );
+ aSize = GetShell()->GetWin()->PixelToLogic( rSize, aMapMode );
+ MapMode aSrc( MAP_TWIP );
+ MapMode aDest( MAP_100TH_MM );
+ aSize = OutputDevice::LogicToLogic( aSize, aSrc, aDest );
+ }
+
+ return aSize;
+}
+
+sal_Bool SwAccessibleMap::ReplaceChild (
+ ::accessibility::AccessibleShape* pCurrentChild,
+ const uno::Reference< drawing::XShape >& _rxShape,
+ const long /*_nIndex*/,
+ const ::accessibility::AccessibleShapeTreeInfo& /*_rShapeTreeInfo*/
+ ) throw (uno::RuntimeException)
+{
+ const SdrObject *pObj = 0;
+ {
+ osl::MutexGuard aGuard( maMutex );
+ if( mpShapeMap )
+ {
+ SwAccessibleShapeMap_Impl::const_iterator aIter = mpShapeMap->begin();
+ SwAccessibleShapeMap_Impl::const_iterator aEndIter = mpShapeMap->end();
+ while( aIter != aEndIter && !pObj )
+ {
+ uno::Reference < XAccessible > xAcc( (*aIter).second );
+ ::accessibility::AccessibleShape *pAccShape =
+ static_cast < ::accessibility::AccessibleShape* >( xAcc.get() );
+ if( pAccShape == pCurrentChild )
+ {
+ pObj = (*aIter).first;
+ }
+ ++aIter;
+ }
+ }
+ }
+ if( !pObj )
+ return sal_False;
+
+ uno::Reference < drawing::XShape > xShape( _rxShape ); //keep reference to shape, because
+ // we might be the only one that
+ // hold it.
+ // Also get keep parent.
+ uno::Reference < XAccessible > xParent( pCurrentChild->getAccessibleParent() );
+ pCurrentChild = 0; // well be realease by dispose
+ Dispose( 0, pObj, 0 );
+
+ {
+ osl::MutexGuard aGuard( maMutex );
+
+ if( !mpShapeMap )
+ mpShapeMap = new SwAccessibleShapeMap_Impl( this );
+
+ // create the new child
+ ::accessibility::ShapeTypeHandler& rShapeTypeHandler =
+ ::accessibility::ShapeTypeHandler::Instance();
+ ::accessibility::AccessibleShapeInfo aShapeInfo(
+ xShape, xParent, this );
+ ::accessibility::AccessibleShape* pReplacement =
+ rShapeTypeHandler.CreateAccessibleObject (
+ aShapeInfo, mpShapeMap->GetInfo() );
+
+ uno::Reference < XAccessible > xAcc( pReplacement );
+ if( xAcc.is() )
+ {
+ pReplacement->Init();
+
+ SwAccessibleShapeMap_Impl::iterator aIter =
+ mpShapeMap->find( pObj );
+ if( aIter != mpShapeMap->end() )
+ {
+ (*aIter).second = xAcc;
+ }
+ else
+ {
+ SwAccessibleShapeMap_Impl::value_type aEntry( pObj, xAcc );
+ mpShapeMap->insert( aEntry );
+ }
+ }
+ }
+
+ SwRect aEmptyRect;
+ InvalidatePosOrSize( 0, pObj, 0, aEmptyRect );
+
+ return sal_True;
+}
+
+Point SwAccessibleMap::PixelToCore( const Point& rPoint ) const
+{
+ Point aPoint;
+ if( GetShell()->GetWin() )
+ {
+ MapMode aMapMode;
+ GetMapMode( rPoint, aMapMode );
+ aPoint = GetShell()->GetWin()->PixelToLogic( rPoint, aMapMode );
+ }
+ return aPoint;
+}
+
+static inline long lcl_CorrectCoarseValue(long aCoarseValue, long aFineValue,
+ long aRefValue, bool bToLower)
+{
+ long aResult = aCoarseValue;
+
+ if (bToLower)
+ {
+ if (aFineValue < aRefValue)
+ aResult -= 1;
+ }
+ else
+ {
+ if (aFineValue > aRefValue)
+ aResult += 1;
+ }
+
+ return aResult;
+}
+
+static inline void lcl_CorrectRectangle(Rectangle & rRect,
+ const Rectangle & rSource,
+ const Rectangle & rInGrid)
+{
+ rRect.nLeft = lcl_CorrectCoarseValue(rRect.nLeft, rSource.nLeft,
+ rInGrid.nLeft, false);
+ rRect.nTop = lcl_CorrectCoarseValue(rRect.nTop, rSource.nTop,
+ rInGrid.nTop, false);
+ rRect.nRight = lcl_CorrectCoarseValue(rRect.nRight, rSource.nRight,
+ rInGrid.nRight, true);
+ rRect.nBottom = lcl_CorrectCoarseValue(rRect.nBottom, rSource.nBottom,
+ rInGrid.nBottom, true);
+}
+
+Rectangle SwAccessibleMap::CoreToPixel( const Rectangle& rRect ) const
+{
+ Rectangle aRect;
+ if( GetShell()->GetWin() )
+ {
+ MapMode aMapMode;
+ GetMapMode( rRect.TopLeft(), aMapMode );
+ aRect = GetShell()->GetWin()->LogicToPixel( rRect, aMapMode );
+
+ Rectangle aTmpRect = GetShell()->GetWin()->PixelToLogic( aRect, aMapMode );
+ lcl_CorrectRectangle(aRect, rRect, aTmpRect);
+ }
+
+ return aRect;
+}
+
+/** get mapping mode for LogicToPixel and PixelToLogic conversions
+
+ Method returns mapping mode of current output device and adjusts it,
+ if the shell is in page/print preview.
+ Necessary, because <PreviewAdjust(..)> changes mapping mode at current
+ output device for mapping logic document positions to page preview window
+ positions and vice versa and doesn't take care to recover its changes.
+*/
+void SwAccessibleMap::GetMapMode( const Point& _rPoint,
+ MapMode& _orMapMode ) const
+{
+ MapMode aMapMode = GetShell()->GetWin()->GetMapMode();
+ if( GetShell()->IsPreView() )
+ {
+ DBG_ASSERT( mpPreview != NULL, "need preview data" );
+
+ mpPreview->AdjustMapMode( aMapMode, _rPoint );
+ }
+ _orMapMode = aMapMode;
+}
+
+Size SwAccessibleMap::GetPreViewPageSize( sal_uInt16 _nPrevwPageNum ) const
+{
+ DBG_ASSERT( mpVSh->IsPreView(), "no page preview accessible." );
+ DBG_ASSERT( mpVSh->IsPreView() && ( mpPreview != NULL ),
+ "missing accessible preview data at page preview" );
+ if ( mpVSh->IsPreView() && ( mpPreview != NULL ) )
+ {
+ return mpVSh->PagePreviewLayout()->GetPrevwPageSizeByPageNum( _nPrevwPageNum );
+ }
+ else
+ {
+ return Size( 0, 0 );
+ }
+}
+
+/** method to build up a new data structure of the accessible pararaphs,
+ which have a selection
+ Important note: method has to used inside a mutual exclusive section
+*/
+SwAccessibleSelectedParas_Impl* SwAccessibleMap::_BuildSelectedParas()
+{
+ // no accessible contexts, no selection
+ if ( !mpFrmMap )
+ {
+ return 0L;
+ }
+
+ // get cursor as an instance of its base class <SwPaM>
+ SwPaM* pCrsr( 0L );
+ {
+ SwCrsrShell* pCrsrShell = dynamic_cast<SwCrsrShell*>(GetShell());
+ if ( pCrsrShell )
+ {
+ SwFEShell* pFEShell = dynamic_cast<SwFEShell*>(pCrsrShell);
+ if ( !pFEShell ||
+ ( !pFEShell->IsFrmSelected() &&
+ pFEShell->IsObjSelected() == 0 ) )
+ {
+ // get cursor without updating an existing table cursor.
+ pCrsr = pCrsrShell->GetCrsr( sal_False );
+ }
+ }
+ }
+ // no cursor, no selection
+ if ( !pCrsr )
+ {
+ return 0L;
+ }
+
+ SwAccessibleSelectedParas_Impl* pRetSelectedParas( 0L );
+
+ // loop on all cursors
+ SwPaM* pRingStart = pCrsr;
+ do {
+
+ // for a selection the cursor has to have a mark.
+ // for savety reasons assure that point and mark are in text nodes
+ if ( pCrsr->HasMark() &&
+ pCrsr->GetPoint()->nNode.GetNode().IsTxtNode() &&
+ pCrsr->GetMark()->nNode.GetNode().IsTxtNode() )
+ {
+ SwPosition* pStartPos = pCrsr->Start();
+ SwPosition* pEndPos = pCrsr->End();
+ // loop on all text nodes inside the selection
+ SwNodeIndex aIdx( pStartPos->nNode );
+ for ( ; aIdx.GetIndex() <= pEndPos->nNode.GetIndex(); ++aIdx )
+ {
+ SwTxtNode* pTxtNode( aIdx.GetNode().GetTxtNode() );
+ if ( pTxtNode )
+ {
+ // loop on all text frames registered at the text node.
+ SwIterator<SwTxtFrm,SwTxtNode> aIter( *pTxtNode );
+ for( SwTxtFrm* pTxtFrm = aIter.First(); pTxtFrm; pTxtFrm = aIter.Next() )
+ {
+ uno::WeakReference < XAccessible > xWeakAcc;
+ SwAccessibleContextMap_Impl::iterator aMapIter =
+ mpFrmMap->find( pTxtFrm );
+ if( aMapIter != mpFrmMap->end() )
+ {
+ xWeakAcc = (*aMapIter).second;
+ SwAccessibleParaSelection aDataEntry(
+ pTxtNode == &(pStartPos->nNode.GetNode())
+ ? pStartPos->nContent.GetIndex()
+ : 0,
+ pTxtNode == &(pEndPos->nNode.GetNode())
+ ? pEndPos->nContent.GetIndex()
+ : STRING_LEN );
+ SwAccessibleSelectedParas_Impl::value_type
+ aEntry( xWeakAcc, aDataEntry );
+ if ( !pRetSelectedParas )
+ {
+ pRetSelectedParas =
+ new SwAccessibleSelectedParas_Impl;
+ }
+ pRetSelectedParas->insert( aEntry );
+ }
+ }
+ }
+ }
+ }
+
+ // prepare next turn: get next cursor in ring
+ pCrsr = static_cast<SwPaM*>( pCrsr->GetNext() );
+ } while ( pCrsr != pRingStart );
+
+ return pRetSelectedParas;
+}
+
+void SwAccessibleMap::InvalidateTextSelectionOfAllParas()
+{
+ osl::MutexGuard aGuard( maMutex );
+
+ // keep previously known selected paragraphs
+ SwAccessibleSelectedParas_Impl* pPrevSelectedParas( mpSelectedParas );
+
+ // determine currently selected paragraphs
+ mpSelectedParas = _BuildSelectedParas();
+
+ // compare currently selected paragraphs with the previously selected
+ // paragraphs and submit corresponding TEXT_SELECTION_CHANGED events.
+ // first, search for new and changed selections.
+ // on the run remove selections from previously known ones, if they are
+ // also in the current ones.
+ if ( mpSelectedParas )
+ {
+ SwAccessibleSelectedParas_Impl::iterator aIter = mpSelectedParas->begin();
+ for ( ; aIter != mpSelectedParas->end(); ++aIter )
+ {
+ bool bSubmitEvent( false );
+ if ( !pPrevSelectedParas )
+ {
+ // new selection
+ bSubmitEvent = true;
+ }
+ else
+ {
+ SwAccessibleSelectedParas_Impl::iterator aPrevSelected =
+ pPrevSelectedParas->find( (*aIter).first );
+ if ( aPrevSelected != pPrevSelectedParas->end() )
+ {
+ // check, if selection has changed
+ if ( (*aIter).second.nStartOfSelection !=
+ (*aPrevSelected).second.nStartOfSelection ||
+ (*aIter).second.nEndOfSelection !=
+ (*aPrevSelected).second.nEndOfSelection )
+ {
+ // changed selection
+ bSubmitEvent = true;
+ }
+ pPrevSelectedParas->erase( aPrevSelected );
+ }
+ else
+ {
+ // new selection
+ bSubmitEvent = true;
+ }
+ }
+
+ if ( bSubmitEvent )
+ {
+ uno::Reference < XAccessible > xAcc( (*aIter).first );
+ if ( xAcc.is() )
+ {
+ ::rtl::Reference < SwAccessibleContext > xAccImpl(
+ static_cast<SwAccessibleContext*>( xAcc.get() ) );
+ if ( xAccImpl.is() && xAccImpl->GetFrm() )
+ {
+ const SwTxtFrm* pTxtFrm(
+ dynamic_cast<const SwTxtFrm*>(xAccImpl->GetFrm()) );
+ OSL_ENSURE( pTxtFrm,
+ "<SwAccessibleMap::_SubmitTextSelectionChangedEvents()> - unexcepted type of frame" );
+ if ( pTxtFrm )
+ {
+ InvalidateParaTextSelection( *pTxtFrm );
+ }
+ }
+ }
+ }
+ }
+ }
+
+ // second, handle previous selections - after the first step the data
+ // structure of the previously known only contains the 'old' selections
+ if ( pPrevSelectedParas )
+ {
+ SwAccessibleSelectedParas_Impl::iterator aIter = pPrevSelectedParas->begin();
+ for ( ; aIter != pPrevSelectedParas->end(); ++aIter )
+ {
+ uno::Reference < XAccessible > xAcc( (*aIter).first );
+ if ( xAcc.is() )
+ {
+ ::rtl::Reference < SwAccessibleContext > xAccImpl(
+ static_cast<SwAccessibleContext*>( xAcc.get() ) );
+ if ( xAccImpl.is() && xAccImpl->GetFrm() )
+ {
+ const SwTxtFrm* pTxtFrm(
+ dynamic_cast<const SwTxtFrm*>(xAccImpl->GetFrm()) );
+ OSL_ENSURE( pTxtFrm,
+ "<SwAccessibleMap::_SubmitTextSelectionChangedEvents()> - unexcepted type of frame" );
+ if ( pTxtFrm )
+ {
+ InvalidateParaTextSelection( *pTxtFrm );
+ }
+ }
+ }
+ }
+
+ delete pPrevSelectedParas;
+ }
+}
+
+const SwRect& SwAccessibleMap::GetVisArea() const
+{
+ DBG_ASSERT( !GetShell()->IsPreView() || (mpPreview != NULL),
+ "preview without preview data?" );
+
+ return GetShell()->IsPreView()
+ ? mpPreview->GetVisArea()
+ : GetShell()->VisArea();
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/access/accnotextframe.cxx b/sw/source/core/access/accnotextframe.cxx
new file mode 100644
index 000000000000..6777b63f23a5
--- /dev/null
+++ b/sw/source/core/access/accnotextframe.cxx
@@ -0,0 +1,262 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+ /*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+
+#include <osl/mutex.hxx>
+#include <vcl/svapp.hxx>
+#include <com/sun/star/accessibility/AccessibleRole.hpp>
+#include <com/sun/star/accessibility/AccessibleStateType.hpp>
+#include <com/sun/star/accessibility/AccessibleEventId.hpp>
+#include <unotools/accessiblestatesethelper.hxx>
+#include <frmfmt.hxx>
+#include <ndnotxt.hxx>
+#include <flyfrm.hxx>
+#include <cntfrm.hxx>
+#include <hints.hxx> //#i73249#
+#include "accnotextframe.hxx"
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::accessibility;
+using ::rtl::OUString;
+
+const SwNoTxtNode *SwAccessibleNoTextFrame::GetNoTxtNode() const
+{
+ const SwNoTxtNode *pNd = 0;
+ const SwFlyFrm *pFlyFrm = static_cast< const SwFlyFrm *>( GetFrm() );
+ if( pFlyFrm->Lower() && pFlyFrm->Lower()->IsNoTxtFrm() )
+ {
+ const SwCntntFrm *pCntFrm =
+ static_cast<const SwCntntFrm *>( pFlyFrm->Lower() );
+ pNd = pCntFrm->GetNode()->GetNoTxtNode();
+ }
+
+ return pNd;
+}
+
+SwAccessibleNoTextFrame::SwAccessibleNoTextFrame(
+ SwAccessibleMap* pInitMap,
+ sal_Int16 nInitRole,
+ const SwFlyFrm* pFlyFrm ) :
+ SwAccessibleFrameBase( pInitMap, nInitRole, pFlyFrm ),
+ aDepend( this, const_cast < SwNoTxtNode * >( GetNoTxtNode() ) ),
+ msTitle(),
+ msDesc()
+{
+ const SwNoTxtNode* pNd = GetNoTxtNode();
+ // #i73249#
+ // consider new attributes Title and Description
+ if( pNd )
+ {
+ msTitle = pNd->GetTitle();
+
+ msDesc = pNd->GetDescription();
+ if ( msDesc.getLength() == 0 &&
+ msTitle != GetName() )
+ {
+ msDesc = msTitle;
+ }
+ }
+ // <--
+}
+
+SwAccessibleNoTextFrame::~SwAccessibleNoTextFrame()
+{
+}
+
+void SwAccessibleNoTextFrame::Modify( const SfxPoolItem* pOld, const SfxPoolItem *pNew)
+{
+ const sal_uInt16 nWhich = pOld ? pOld->Which() : pNew ? pNew->Which() : 0 ;
+ // #i73249#
+ // suppress handling of RES_NAME_CHANGED in case that attribute Title is
+ // used as the accessible name.
+ if ( nWhich != RES_NAME_CHANGED ||
+ msTitle.getLength() == 0 )
+ {
+ SwAccessibleFrameBase::Modify( pOld, pNew );
+ }
+
+ const SwNoTxtNode *pNd = GetNoTxtNode();
+ OSL_ENSURE( pNd == aDepend.GetRegisteredIn(), "invalid frame" );
+ switch( nWhich )
+ {
+ // #i73249#
+ case RES_TITLE_CHANGED:
+ {
+ const String& sOldTitle(
+ dynamic_cast<const SwStringMsgPoolItem*>(pOld)->GetString() );
+ const String& sNewTitle(
+ dynamic_cast<const SwStringMsgPoolItem*>(pNew)->GetString() );
+ if ( sOldTitle == sNewTitle )
+ {
+ break;
+ }
+ msTitle = sNewTitle;
+ AccessibleEventObject aEvent;
+ aEvent.EventId = AccessibleEventId::NAME_CHANGED;
+ aEvent.OldValue <<= OUString( sOldTitle );
+ aEvent.NewValue <<= msTitle;
+ FireAccessibleEvent( aEvent );
+
+ if ( pNd->GetDescription().Len() != 0 )
+ {
+ break;
+ }
+ }
+ // intentional no break here
+ case RES_DESCRIPTION_CHANGED:
+ {
+ if ( pNd && GetFrm() )
+ {
+ const OUString sOldDesc( msDesc );
+
+ const String& rDesc = pNd->GetDescription();
+ msDesc = rDesc;
+ if ( msDesc.getLength() == 0 &&
+ msTitle != GetName() )
+ {
+ msDesc = msTitle;
+ }
+
+ if ( msDesc != sOldDesc )
+ {
+ AccessibleEventObject aEvent;
+ aEvent.EventId = AccessibleEventId::DESCRIPTION_CHANGED;
+ aEvent.OldValue <<= sOldDesc;
+ aEvent.NewValue <<= msDesc;
+ FireAccessibleEvent( aEvent );
+ }
+ }
+ }
+ break;
+ }
+}
+
+void SwAccessibleNoTextFrame::Dispose( sal_Bool bRecursive )
+{
+ SolarMutexGuard aGuard;
+
+ if( aDepend.GetRegisteredIn() )
+ const_cast < SwModify *>( aDepend.GetRegisteredIn() )->Remove( &aDepend );
+
+ SwAccessibleFrameBase::Dispose( bRecursive );
+}
+
+// #i73249#
+OUString SAL_CALL SwAccessibleNoTextFrame::getAccessibleName (void)
+ throw (uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+
+ CHECK_FOR_DEFUNC( XAccessibleContext )
+
+ if ( msTitle.getLength() != 0 )
+ {
+ return msTitle;
+ }
+
+ return SwAccessibleFrameBase::getAccessibleName();
+}
+// <--
+
+OUString SAL_CALL SwAccessibleNoTextFrame::getAccessibleDescription (void)
+ throw (uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+
+ CHECK_FOR_DEFUNC( XAccessibleContext )
+
+ return msDesc;
+}
+
+
+
+//
+// XInterface
+//
+
+uno::Any SAL_CALL SwAccessibleNoTextFrame::queryInterface( const uno::Type& aType )
+ throw (uno::RuntimeException)
+{
+ if( aType ==
+ ::getCppuType( static_cast<uno::Reference<XAccessibleImage>*>( NULL ) ) )
+ {
+ uno::Reference<XAccessibleImage> xImage = this;
+ uno::Any aAny;
+ aAny <<= xImage;
+ return aAny;
+ }
+ else
+ return SwAccessibleContext::queryInterface( aType );
+}
+
+
+//====== XTypeProvider ====================================================
+uno::Sequence< uno::Type > SAL_CALL SwAccessibleNoTextFrame::getTypes() throw(uno::RuntimeException)
+{
+ uno::Sequence< uno::Type > aTypes( SwAccessibleFrameBase::getTypes() );
+
+ sal_Int32 nIndex = aTypes.getLength();
+ aTypes.realloc( nIndex + 1 );
+
+ uno::Type* pTypes = aTypes.getArray();
+ pTypes[nIndex] = ::getCppuType( static_cast< uno::Reference< XAccessibleImage > * >( 0 ) );
+
+ return aTypes;
+}
+
+
+//
+// XAccessibleImage
+//
+
+// implementation of the XAccessibleImage methods is a no-brainer, as
+// all releveant information is already accessible through other
+// methods. So we just delegate to those.
+
+OUString SAL_CALL SwAccessibleNoTextFrame::getAccessibleImageDescription()
+ throw ( uno::RuntimeException )
+{
+ return getAccessibleDescription();
+}
+
+sal_Int32 SAL_CALL SwAccessibleNoTextFrame::getAccessibleImageHeight( )
+ throw ( uno::RuntimeException )
+{
+ return getSize().Height;
+}
+
+sal_Int32 SAL_CALL SwAccessibleNoTextFrame::getAccessibleImageWidth( )
+ throw ( uno::RuntimeException )
+{
+ return getSize().Width;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/access/accnotextframe.hxx b/sw/source/core/access/accnotextframe.hxx
new file mode 100644
index 000000000000..ce4ef672c110
--- /dev/null
+++ b/sw/source/core/access/accnotextframe.hxx
@@ -0,0 +1,110 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+#ifndef _ACCNOTEXTFRAME_HXX
+#define _ACCNOTEXTFRAME_HXX
+#include "accframebase.hxx"
+#include <com/sun/star/accessibility/XAccessibleImage.hpp>
+
+class SwFlyFrm;
+class SwNoTxtNode;
+
+class SwAccessibleNoTextFrame : public SwAccessibleFrameBase,
+ public ::com::sun::star::accessibility::XAccessibleImage
+{
+ SwDepend aDepend;
+ ::rtl::OUString msTitle; // #i73249#
+ ::rtl::OUString msDesc;
+
+protected:
+
+ virtual ~SwAccessibleNoTextFrame();
+
+ const SwNoTxtNode *GetNoTxtNode() const;
+
+ virtual void Modify( const SfxPoolItem* pOld, const SfxPoolItem *pNew);
+
+public:
+
+ SwAccessibleNoTextFrame( SwAccessibleMap* pInitMap,
+ sal_Int16 nInitRole,
+ const SwFlyFrm *pFlyFrm );
+
+ //===== XAccessibleContext ==============================================
+
+ // #i73249# - Return the object's current name.
+ virtual ::rtl::OUString SAL_CALL
+ getAccessibleName (void)
+ throw (::com::sun::star::uno::RuntimeException);
+ // <--
+
+ /// Return this object's description.
+ virtual ::rtl::OUString SAL_CALL
+ getAccessibleDescription (void)
+ throw (com::sun::star::uno::RuntimeException);
+
+ //===== XInterface ======================================================
+
+ // XInterface methods need to be implemented to disambiguate
+ // between those inherited through SwAcessibleContext and
+ // XAccessibleImage.
+
+ virtual ::com::sun::star::uno::Any SAL_CALL queryInterface(
+ const ::com::sun::star::uno::Type& aType )
+ throw (::com::sun::star::uno::RuntimeException);
+
+ virtual void SAL_CALL acquire( ) throw ()
+ { SwAccessibleContext::acquire(); };
+
+ virtual void SAL_CALL release( ) throw ()
+ { SwAccessibleContext::release(); };
+
+ //====== XTypeProvider ====================================================
+ virtual ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Type > SAL_CALL getTypes( ) throw(::com::sun::star::uno::RuntimeException);
+
+ //===== XAccessibleImage ================================================
+
+ virtual ::rtl::OUString SAL_CALL
+ getAccessibleImageDescription( )
+ throw ( ::com::sun::star::uno::RuntimeException );
+
+ virtual sal_Int32 SAL_CALL
+ getAccessibleImageHeight( )
+ throw ( ::com::sun::star::uno::RuntimeException );
+
+ virtual sal_Int32 SAL_CALL
+ getAccessibleImageWidth( )
+ throw ( ::com::sun::star::uno::RuntimeException );
+
+ // The object is not visible an longer and should be destroyed
+ virtual void Dispose( sal_Bool bRecursive = sal_False );
+};
+
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/access/accpage.cxx b/sw/source/core/access/accpage.cxx
new file mode 100644
index 000000000000..2b5886e026d2
--- /dev/null
+++ b/sw/source/core/access/accpage.cxx
@@ -0,0 +1,201 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+ /*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+
+#include <rtl/uuid.h>
+#include <vcl/window.hxx>
+#include <vcl/svapp.hxx>
+#include <unotools/accessiblestatesethelper.hxx>
+#include <com/sun/star/accessibility/AccessibleStateType.hpp>
+#include <com/sun/star/accessibility/AccessibleRole.hpp>
+#include "accpage.hxx"
+
+#include "access.hrc"
+#include <pagefrm.hxx>
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::accessibility;
+
+using uno::Reference;
+using uno::RuntimeException;
+using uno::Sequence;
+using ::rtl::OUString;
+
+
+const sal_Char sServiceName[] = "com.sun.star.text.AccessiblePageView";
+const sal_Char sImplementationName[] = "com.sun.star.comp.Writer.SwAccessiblePageView";
+
+sal_Bool SwAccessiblePage::IsSelected()
+{
+ return GetMap()->IsPageSelected( static_cast < const SwPageFrm * >( GetFrm() ) );
+}
+
+void SwAccessiblePage::GetStates(
+ ::utl::AccessibleStateSetHelper& rStateSet )
+{
+ SwAccessibleContext::GetStates( rStateSet );
+
+ // FOCUSABLE
+ rStateSet.AddState( AccessibleStateType::FOCUSABLE );
+
+ // FOCUSED
+ if( IsSelected() )
+ {
+ OSL_ENSURE( bIsSelected, "bSelected out of sync" );
+ ::rtl::Reference < SwAccessibleContext > xThis( this );
+ GetMap()->SetCursorContext( xThis );
+
+ Window *pWin = GetWindow();
+ if( pWin && pWin->HasFocus() )
+ rStateSet.AddState( AccessibleStateType::FOCUSED );
+ }
+}
+
+void SwAccessiblePage::_InvalidateCursorPos()
+{
+ sal_Bool bNewSelected = IsSelected();
+ sal_Bool bOldSelected;
+
+ {
+ osl::MutexGuard aGuard( aMutex );
+ bOldSelected = bIsSelected;
+ bIsSelected = bNewSelected;
+ }
+
+ if( bNewSelected )
+ {
+ // remember that object as the one that has the caret. This is
+ // neccessary to notify that object if the cursor leaves it.
+ ::rtl::Reference < SwAccessibleContext > xThis( this );
+ GetMap()->SetCursorContext( xThis );
+ }
+
+ if( bOldSelected != bNewSelected )
+ {
+ Window *pWin = GetWindow();
+ if( pWin && pWin->HasFocus() )
+ FireStateChangedEvent( AccessibleStateType::FOCUSED, bNewSelected );
+ }
+}
+
+void SwAccessiblePage::_InvalidateFocus()
+{
+ Window *pWin = GetWindow();
+ if( pWin )
+ {
+ sal_Bool bSelected;
+
+ {
+ osl::MutexGuard aGuard( aMutex );
+ bSelected = bIsSelected;
+ }
+ OSL_ENSURE( bSelected, "focus object should be selected" );
+
+ FireStateChangedEvent( AccessibleStateType::FOCUSED,
+ pWin->HasFocus() && bSelected );
+ }
+}
+
+SwAccessiblePage::SwAccessiblePage( SwAccessibleMap* pInitMap,
+ const SwFrm* pFrame )
+ : SwAccessibleContext( pInitMap, AccessibleRole::PANEL, pFrame )
+ , bIsSelected( sal_False )
+{
+ DBG_ASSERT( pFrame != NULL, "need frame" );
+ DBG_ASSERT( pInitMap != NULL, "need map" );
+ DBG_ASSERT( pFrame->IsPageFrm(), "need page frame" );
+
+ SolarMutexGuard aGuard;
+
+ OUString sPage = OUString::valueOf(
+ static_cast<sal_Int32>(
+ static_cast<const SwPageFrm*>( GetFrm() )->GetPhyPageNum() ) );
+ SetName( GetResource( STR_ACCESS_PAGE_NAME, &sPage ) );
+}
+
+SwAccessiblePage::~SwAccessiblePage()
+{
+}
+
+sal_Bool SwAccessiblePage::HasCursor()
+{
+ osl::MutexGuard aGuard( aMutex );
+ return bIsSelected;
+}
+
+OUString SwAccessiblePage::getImplementationName( )
+ throw( RuntimeException )
+{
+ return OUString(RTL_CONSTASCII_USTRINGPARAM(sImplementationName));
+}
+
+sal_Bool SwAccessiblePage::supportsService( const OUString& rServiceName)
+ throw( RuntimeException )
+{
+ return rServiceName.equalsAsciiL( sServiceName, sizeof(sServiceName)-1 ) ||
+ rServiceName.equalsAsciiL( sAccessibleServiceName,
+ sizeof(sAccessibleServiceName)-1 );
+}
+
+Sequence<OUString> SwAccessiblePage::getSupportedServiceNames( )
+ throw( RuntimeException )
+{
+ Sequence< OUString > aRet(2);
+ OUString* pArray = aRet.getArray();
+ pArray[0] = OUString( RTL_CONSTASCII_USTRINGPARAM(sServiceName) );
+ pArray[1] = OUString( RTL_CONSTASCII_USTRINGPARAM(sAccessibleServiceName) );
+ return aRet;
+}
+
+Sequence< sal_Int8 > SAL_CALL SwAccessiblePage::getImplementationId()
+ throw(RuntimeException)
+{
+ SolarMutexGuard aGuard;
+ static Sequence< sal_Int8 > aId( 16 );
+ static sal_Bool bInit = sal_False;
+ if(!bInit)
+ {
+ rtl_createUuid( (sal_uInt8 *)(aId.getArray() ), 0, sal_True );
+ bInit = sal_True;
+ }
+ return aId;
+}
+
+OUString SwAccessiblePage::getAccessibleDescription( )
+ throw( RuntimeException )
+{
+ CHECK_FOR_DEFUNC( ::com::sun::star::accessibility::XAccessibleContext );
+
+ OUString sArg( GetFormattedPageNumber() );
+ return GetResource( STR_ACCESS_PAGE_DESC, &sArg );
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/access/accpage.hxx b/sw/source/core/access/accpage.hxx
new file mode 100644
index 000000000000..ebb96cf8948f
--- /dev/null
+++ b/sw/source/core/access/accpage.hxx
@@ -0,0 +1,99 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+#ifndef _ACCPAGE_HXX
+#define _ACCPAGE_HXX
+
+#include "acccontext.hxx"
+
+
+/**
+ * accessibility implementation for the page (SwPageFrm)
+ * The page is _only_ visible in the page preview. For the regular
+ * document view, it doesn't make sense to add this additional element
+ * into the hierarchy. For the page preview, however, the page is the
+ * important.
+ */
+class SwAccessiblePage : public SwAccessibleContext
+{
+ sal_Bool bIsSelected; // protected by base class mutex
+
+ sal_Bool IsSelected();
+
+ using SwAccessibleFrame::GetBounds;
+
+protected:
+
+ // return the bounding box for the page in page preview mode
+ SwRect GetBounds( /* const SwFrm *pFrm =0 */ );
+
+ // Set states for getAccessibleStateSet.
+ // This drived class additionaly sets
+ // FOCUSABLE(1) and FOCUSED(+)
+ virtual void GetStates( ::utl::AccessibleStateSetHelper& rStateSet );
+
+ virtual void _InvalidateCursorPos();
+ virtual void _InvalidateFocus();
+
+ virtual ~SwAccessiblePage();
+
+public:
+ // convenience constructor to avoid typecast;
+ // may only be called with SwPageFrm argument
+ SwAccessiblePage( SwAccessibleMap* pInitMap, const SwFrm* pFrame );
+
+
+
+ //
+ // XAccessibleContext methods that need to be overridden
+ //
+
+ virtual ::rtl::OUString SAL_CALL getAccessibleDescription (void)
+ throw (::com::sun::star::uno::RuntimeException);
+
+ //
+ // XServiceInfo
+ //
+
+ virtual ::rtl::OUString SAL_CALL getImplementationName (void)
+ throw (::com::sun::star::uno::RuntimeException);
+ virtual sal_Bool SAL_CALL supportsService (
+ const ::rtl::OUString& sServiceName)
+ throw (::com::sun::star::uno::RuntimeException);
+ virtual ::com::sun::star::uno::Sequence< ::rtl::OUString> SAL_CALL
+ getSupportedServiceNames (void)
+ throw (::com::sun::star::uno::RuntimeException);
+
+ //===== XTypeProvider ====================================================
+ virtual ::com::sun::star::uno::Sequence< sal_Int8 > SAL_CALL getImplementationId( ) throw(::com::sun::star::uno::RuntimeException);
+
+ virtual sal_Bool HasCursor(); // required by map to remember that object
+};
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/access/accpara.cxx b/sw/source/core/access/accpara.cxx
new file mode 100644
index 000000000000..f515494d234d
--- /dev/null
+++ b/sw/source/core/access/accpara.cxx
@@ -0,0 +1,2611 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+ /*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+#include <txtfrm.hxx>
+#include <flyfrm.hxx>
+#include <ndtxt.hxx>
+#include <pam.hxx>
+#include <unotextrange.hxx>
+#include <unocrsrhelper.hxx>
+#include <crstate.hxx>
+#include <accmap.hxx>
+#include <fesh.hxx>
+#include <viewopt.hxx>
+#include <osl/mutex.hxx>
+#include <vcl/svapp.hxx>
+#include <vcl/window.hxx>
+#include <rtl/ustrbuf.hxx>
+#include <com/sun/star/accessibility/AccessibleRole.hpp>
+#include <com/sun/star/accessibility/AccessibleStateType.hpp>
+#include <com/sun/star/accessibility/AccessibleTextType.hpp>
+#include <com/sun/star/accessibility/AccessibleEventId.hpp>
+#include <unotools/accessiblestatesethelper.hxx>
+#include <com/sun/star/i18n/CharacterIteratorMode.hpp>
+#include <com/sun/star/i18n/WordType.hpp>
+#include <com/sun/star/i18n/XBreakIterator.hpp>
+#include <com/sun/star/beans/UnknownPropertyException.hpp>
+#include <breakit.hxx>
+#include <accpara.hxx>
+#include <access.hrc>
+#include <accportions.hxx>
+#include <sfx2/viewsh.hxx> // for ExecuteAtViewShell(...)
+#include <sfx2/viewfrm.hxx> // for ExecuteAtViewShell(...)
+#include <sfx2/dispatch.hxx> // for ExecuteAtViewShell(...)
+#include <unotools/charclass.hxx> // for GetWordBoundary
+// for get/setCharacterAttribute(...)
+#include <unocrsr.hxx>
+#include <unoport.hxx>
+#include <doc.hxx>
+#include <crsskip.hxx>
+#include <txtatr.hxx>
+#include <acchyperlink.hxx>
+#include <acchypertextdata.hxx>
+#include <unotools/accessiblerelationsethelper.hxx>
+#include <com/sun/star/accessibility/AccessibleRelationType.hpp>
+#include <comphelper/accessibletexthelper.hxx>
+#include <unomap.hxx>
+#include <unoprnms.hxx>
+#include <com/sun/star/text/WritingMode2.hpp>
+#include <editeng/brshitem.hxx>
+#include <viewimp.hxx>
+#include <boost/scoped_ptr.hpp>
+#include <textmarkuphelper.hxx>
+// #i10825#
+#include <parachangetrackinginfo.hxx>
+#include <com/sun/star/text/TextMarkupType.hpp>
+// <--
+#include <comphelper/stlunosequence.hxx> // #i92233#
+
+#include <algorithm>
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::accessibility;
+
+using beans::PropertyValue;
+using beans::XMultiPropertySet;
+using beans::UnknownPropertyException;
+using beans::PropertyState_DIRECT_VALUE;
+
+using std::max;
+using std::min;
+using std::sort;
+
+namespace com { namespace sun { namespace star {
+ namespace text {
+ class XText;
+ }
+} } }
+
+
+const sal_Char sServiceName[] = "com.sun.star.text.AccessibleParagraphView";
+const sal_Char sImplementationName[] = "com.sun.star.comp.Writer.SwAccessibleParagraphView";
+const xub_StrLen MAX_DESC_TEXT_LEN = 40;
+const SwTxtNode* SwAccessibleParagraph::GetTxtNode() const
+{
+ const SwFrm* pFrm = GetFrm();
+ DBG_ASSERT( pFrm->IsTxtFrm(), "The text frame has mutated!" );
+
+ const SwTxtNode* pNode = static_cast<const SwTxtFrm*>(pFrm)->GetTxtNode();
+ DBG_ASSERT( pNode != NULL, "A text frame without a text node." );
+
+ return pNode;
+}
+
+::rtl::OUString SwAccessibleParagraph::GetString()
+{
+ return GetPortionData().GetAccessibleString();
+}
+
+::rtl::OUString SwAccessibleParagraph::GetDescription()
+{
+ return ::rtl::OUString(); // provide empty description for paragraphs
+}
+
+sal_Int32 SwAccessibleParagraph::GetCaretPos()
+{
+ sal_Int32 nRet = -1;
+
+ // get the selection's point, and test whether it's in our node
+ // #i27301# - consider adjusted method signature
+ SwPaM* pCaret = GetCursor( false ); // caret is first PaM in PaM-ring
+
+ if( pCaret != NULL )
+ {
+ const SwTxtNode* pNode = GetTxtNode();
+
+ // check whether the point points into 'our' node
+ SwPosition* pPoint = pCaret->GetPoint();
+ if( pNode->GetIndex() == pPoint->nNode.GetIndex() )
+ {
+ // same node? Then check whether it's also within 'our' part
+ // of the paragraph
+ sal_uInt16 nIndex = pPoint->nContent.GetIndex();
+ if( GetPortionData().IsValidCorePosition( nIndex ) )
+ {
+ // Yes, it's us!
+ // consider that cursor/caret is in front of the list label
+ if ( pCaret->IsInFrontOfLabel() )
+ {
+ nRet = 0;
+ }
+ else
+ {
+ nRet = GetPortionData().GetAccessiblePosition( nIndex );
+ }
+
+ DBG_ASSERT( nRet >= 0, "invalid cursor?" );
+ DBG_ASSERT( nRet <= GetPortionData().GetAccessibleString().
+ getLength(), "invalid cursor?" );
+ }
+ // else: in this paragraph, but in different frame
+ }
+ // else: not in this paragraph
+ }
+ // else: no cursor -> no caret
+
+ return nRet;
+}
+
+sal_Bool SwAccessibleParagraph::GetSelection(
+ sal_Int32& nStart, sal_Int32& nEnd)
+{
+ sal_Bool bRet = sal_False;
+ nStart = -1;
+ nEnd = -1;
+
+ // get the selection, and test whether it affects our text node
+ SwPaM* pCrsr = GetCursor( true ); // #i27301# - consider adjusted method signature
+ if( pCrsr != NULL )
+ {
+ // get SwPosition for my node
+ const SwTxtNode* pNode = GetTxtNode();
+ sal_uLong nHere = pNode->GetIndex();
+
+ // iterate over ring
+ SwPaM* pRingStart = pCrsr;
+ do
+ {
+ // ignore, if no mark
+ if( pCrsr->HasMark() )
+ {
+ // check whether nHere is 'inside' pCrsr
+ SwPosition* pStart = pCrsr->Start();
+ sal_uLong nStartIndex = pStart->nNode.GetIndex();
+ SwPosition* pEnd = pCrsr->End();
+ sal_uLong nEndIndex = pEnd->nNode.GetIndex();
+ if( ( nHere >= nStartIndex ) &&
+ ( nHere <= nEndIndex ) )
+ {
+ // translate start and end positions
+
+ // start position
+ sal_Int32 nLocalStart = -1;
+ if( nHere > nStartIndex )
+ {
+ // selection starts in previous node:
+ // then our local selection starts with the paragraph
+ nLocalStart = 0;
+ }
+ else
+ {
+ DBG_ASSERT( nHere == nStartIndex,
+ "miscalculated index" );
+
+ // selection starts in this node:
+ // then check whether it's before or inside our part of
+ // the paragraph, and if so, get the proper position
+ sal_uInt16 nCoreStart = pStart->nContent.GetIndex();
+ if( nCoreStart <
+ GetPortionData().GetFirstValidCorePosition() )
+ {
+ nLocalStart = 0;
+ }
+ else if( nCoreStart <=
+ GetPortionData().GetLastValidCorePosition() )
+ {
+ DBG_ASSERT(
+ GetPortionData().IsValidCorePosition(
+ nCoreStart ),
+ "problem determining valid core position" );
+
+ nLocalStart =
+ GetPortionData().GetAccessiblePosition(
+ nCoreStart );
+ }
+ }
+
+ // end position
+ sal_Int32 nLocalEnd = -1;
+ if( nHere < nEndIndex )
+ {
+ // selection ends in following node:
+ // then our local selection extends to the end
+ nLocalEnd = GetPortionData().GetAccessibleString().
+ getLength();
+ }
+ else
+ {
+ DBG_ASSERT( nHere == nEndIndex,
+ "miscalculated index" );
+
+ // selection ends in this node: then select everything
+ // before our part of the node
+ sal_uInt16 nCoreEnd = pEnd->nContent.GetIndex();
+ if( nCoreEnd >
+ GetPortionData().GetLastValidCorePosition() )
+ {
+ // selection extends beyond out part of this para
+ nLocalEnd = GetPortionData().GetAccessibleString().
+ getLength();
+ }
+ else if( nCoreEnd >=
+ GetPortionData().GetFirstValidCorePosition() )
+ {
+ // selection is inside our part of this para
+ DBG_ASSERT(
+ GetPortionData().IsValidCorePosition(
+ nCoreEnd ),
+ "problem determining valid core position" );
+
+ nLocalEnd = GetPortionData().GetAccessiblePosition(
+ nCoreEnd );
+ }
+ }
+
+ if( ( nLocalStart != -1 ) && ( nLocalEnd != -1 ) )
+ {
+ nStart = nLocalStart;
+ nEnd = nLocalEnd;
+ bRet = sal_True;
+ }
+ }
+ // else: this PaM doesn't point to this paragraph
+ }
+ // else: this PaM is collapsed and doesn't select anything
+
+ // next PaM in ring
+ pCrsr = static_cast<SwPaM*>( pCrsr->GetNext() );
+ }
+ while( !bRet && (pCrsr != pRingStart) );
+ }
+ // else: nocursor -> no selection
+
+ return bRet;
+}
+
+// #i27301# - new parameter <_bForSelection>
+SwPaM* SwAccessibleParagraph::GetCursor( const bool _bForSelection )
+{
+ // get the cursor shell; if we don't have any, we don't have a
+ // cursor/selection either
+ SwPaM* pCrsr = NULL;
+ SwCrsrShell* pCrsrShell = SwAccessibleParagraph::GetCrsrShell();
+ // #i27301# - if cursor is retrieved for selection, the cursors for
+ // a table selection has to be returned.
+ if ( pCrsrShell != NULL &&
+ ( _bForSelection || !pCrsrShell->IsTableMode() ) )
+ // <--
+ {
+ SwFEShell *pFESh = pCrsrShell->ISA( SwFEShell )
+ ? static_cast< SwFEShell * >( pCrsrShell ) : 0;
+ if( !pFESh ||
+ !(pFESh->IsFrmSelected() || pFESh->IsObjSelected() > 0) )
+ {
+ // get the selection, and test whether it affects our text node
+ pCrsr = pCrsrShell->GetCrsr( sal_False /* ??? */ );
+ }
+ }
+
+ return pCrsr;
+}
+
+sal_Bool SwAccessibleParagraph::IsHeading() const
+{
+ const SwTxtNode *pTxtNd = GetTxtNode();
+ return pTxtNd->IsOutline();
+}
+
+void SwAccessibleParagraph::GetStates(
+ ::utl::AccessibleStateSetHelper& rStateSet )
+{
+ SwAccessibleContext::GetStates( rStateSet );
+
+ // MULTILINE
+ rStateSet.AddState( AccessibleStateType::MULTI_LINE );
+
+ // MULTISELECTABLE
+ SwCrsrShell *pCrsrSh = GetCrsrShell();
+ if( pCrsrSh )
+ rStateSet.AddState( AccessibleStateType::MULTI_SELECTABLE );
+
+ // FOCUSABLE
+ if( pCrsrSh )
+ rStateSet.AddState( AccessibleStateType::FOCUSABLE );
+
+ // FOCUSED (simulates node index of cursor)
+ SwPaM* pCaret = GetCursor( false ); // #i27301# - consider adjusted method signature
+ const SwTxtNode* pTxtNd = GetTxtNode();
+ if( pCaret != 0 && pTxtNd != 0 &&
+ pTxtNd->GetIndex() == pCaret->GetPoint()->nNode.GetIndex() &&
+ nOldCaretPos != -1)
+ {
+ Window *pWin = GetWindow();
+ if( pWin && pWin->HasFocus() )
+ rStateSet.AddState( AccessibleStateType::FOCUSED );
+ ::rtl::Reference < SwAccessibleContext > xThis( this );
+ GetMap()->SetCursorContext( xThis );
+ }
+}
+
+void SwAccessibleParagraph::_InvalidateContent( sal_Bool bVisibleDataFired )
+{
+ ::rtl::OUString sOldText( GetString() );
+
+ ClearPortionData();
+
+ const ::rtl::OUString& rText = GetString();
+
+ if( rText != sOldText )
+ {
+ // The text is changed
+ AccessibleEventObject aEvent;
+ aEvent.EventId = AccessibleEventId::TEXT_CHANGED;
+
+ // determine exact changes between sOldText and rText
+ comphelper::OCommonAccessibleText::implInitTextChangedEvent(
+ sOldText, rText,
+ aEvent.OldValue, aEvent.NewValue );
+
+ FireAccessibleEvent( aEvent );
+ }
+ else if( !bVisibleDataFired )
+ {
+ FireVisibleDataEvent();
+ }
+
+ sal_Bool bNewIsHeading = IsHeading();
+ sal_Bool bOldIsHeading;
+ {
+ osl::MutexGuard aGuard( aMutex );
+ bOldIsHeading = bIsHeading;
+ if( bIsHeading != bNewIsHeading )
+ bIsHeading = bNewIsHeading;
+ }
+
+
+ if( bNewIsHeading != bOldIsHeading || rText != sOldText )
+ {
+ ::rtl::OUString sNewDesc( GetDescription() );
+ ::rtl::OUString sOldDesc;
+ {
+ osl::MutexGuard aGuard( aMutex );
+ sOldDesc = sDesc;
+ if( sDesc != sNewDesc )
+ sDesc = sNewDesc;
+ }
+
+ if( sNewDesc != sOldDesc )
+ {
+ // The text is changed
+ AccessibleEventObject aEvent;
+ aEvent.EventId = AccessibleEventId::DESCRIPTION_CHANGED;
+ aEvent.OldValue <<= sOldDesc;
+ aEvent.NewValue <<= sNewDesc;
+
+ FireAccessibleEvent( aEvent );
+ }
+ }
+}
+
+void SwAccessibleParagraph::_InvalidateCursorPos()
+{
+ // The text is changed
+ sal_Int32 nNew = GetCaretPos();
+ sal_Int32 nOld;
+ {
+ osl::MutexGuard aGuard( aMutex );
+ nOld = nOldCaretPos;
+ nOldCaretPos = nNew;
+ }
+ if( -1 != nNew )
+ {
+ // remember that object as the one that has the caret. This is
+ // neccessary to notify that object if the cursor leaves it.
+ ::rtl::Reference < SwAccessibleContext > xThis( this );
+ GetMap()->SetCursorContext( xThis );
+ }
+
+ Window *pWin = GetWindow();
+ if( nOld != nNew )
+ {
+ // The cursor's node position is sumilated by the focus!
+ if( pWin && pWin->HasFocus() && -1 == nOld )
+ FireStateChangedEvent( AccessibleStateType::FOCUSED, sal_True );
+
+
+ AccessibleEventObject aEvent;
+ aEvent.EventId = AccessibleEventId::CARET_CHANGED;
+ aEvent.OldValue <<= nOld;
+ aEvent.NewValue <<= nNew;
+
+ FireAccessibleEvent( aEvent );
+
+ if( pWin && pWin->HasFocus() && -1 == nNew )
+ FireStateChangedEvent( AccessibleStateType::FOCUSED, sal_False );
+ }
+}
+
+void SwAccessibleParagraph::_InvalidateFocus()
+{
+ Window *pWin = GetWindow();
+ if( pWin )
+ {
+ sal_Int32 nPos;
+ {
+ osl::MutexGuard aGuard( aMutex );
+ nPos = nOldCaretPos;
+ }
+ OSL_ENSURE( nPos != -1, "focus object should be selected" );
+
+ FireStateChangedEvent( AccessibleStateType::FOCUSED,
+ pWin->HasFocus() && nPos != -1 );
+ }
+}
+
+SwAccessibleParagraph::SwAccessibleParagraph(
+ SwAccessibleMap& rInitMap,
+ const SwTxtFrm& rTxtFrm )
+ : SwClient( const_cast<SwTxtNode*>(rTxtFrm.GetTxtNode()) ) // #i108125#
+ , SwAccessibleContext( &rInitMap, AccessibleRole::PARAGRAPH, &rTxtFrm )
+ , sDesc()
+ , pPortionData( NULL )
+ , pHyperTextData( NULL )
+ , nOldCaretPos( -1 )
+ , bIsHeading( sal_False )
+ , aSelectionHelper( *this )
+ , mpParaChangeTrackInfo( new SwParaChangeTrackingInfo( rTxtFrm ) ) // #i108125#
+{
+ SolarMutexGuard aGuard;
+
+ bIsHeading = IsHeading();
+ SetName( ::rtl::OUString() ); // set an empty accessibility name for paragraphs
+
+ // If this object has the focus, then it is remembered by the map itself.
+ nOldCaretPos = GetCaretPos();
+}
+
+SwAccessibleParagraph::~SwAccessibleParagraph()
+{
+ SolarMutexGuard aGuard;
+
+ delete pPortionData;
+ delete pHyperTextData;
+ delete mpParaChangeTrackInfo; // #i108125#
+}
+
+sal_Bool SwAccessibleParagraph::HasCursor()
+{
+ osl::MutexGuard aGuard( aMutex );
+ return nOldCaretPos != -1;
+}
+
+void SwAccessibleParagraph::UpdatePortionData()
+ throw( uno::RuntimeException )
+{
+ // obtain the text frame
+ DBG_ASSERT( GetFrm() != NULL, "The text frame has vanished!" );
+ DBG_ASSERT( GetFrm()->IsTxtFrm(), "The text frame has mutated!" );
+ const SwTxtFrm* pFrm = static_cast<const SwTxtFrm*>( GetFrm() );
+
+ // build new portion data
+ delete pPortionData;
+ pPortionData = new SwAccessiblePortionData(
+ pFrm->GetTxtNode(), GetMap()->GetShell()->GetViewOptions() );
+ pFrm->VisitPortions( *pPortionData );
+
+ DBG_ASSERT( pPortionData != NULL, "UpdatePortionData() failed" );
+}
+
+void SwAccessibleParagraph::ClearPortionData()
+{
+ delete pPortionData;
+ pPortionData = NULL;
+
+ delete pHyperTextData;
+ pHyperTextData = 0;
+}
+
+
+void SwAccessibleParagraph::ExecuteAtViewShell( sal_uInt16 nSlot )
+{
+ DBG_ASSERT( GetMap() != NULL, "no map?" );
+ ViewShell* pViewShell = GetMap()->GetShell();
+
+ DBG_ASSERT( pViewShell != NULL, "View shell exptected!" );
+ SfxViewShell* pSfxShell = pViewShell->GetSfxViewShell();
+
+ DBG_ASSERT( pSfxShell != NULL, "SfxViewShell shell exptected!" );
+ if( !pSfxShell )
+ return;
+
+ SfxViewFrame *pFrame = pSfxShell->GetViewFrame();
+ DBG_ASSERT( pFrame != NULL, "View frame exptected!" );
+ if( !pFrame )
+ return;
+
+ SfxDispatcher *pDispatcher = pFrame->GetDispatcher();
+ DBG_ASSERT( pDispatcher != NULL, "Dispatcher exptected!" );
+ if( !pDispatcher )
+ return;
+
+ pDispatcher->Execute( nSlot );
+}
+
+SwXTextPortion* SwAccessibleParagraph::CreateUnoPortion(
+ sal_Int32 nStartIndex,
+ sal_Int32 nEndIndex )
+{
+ DBG_ASSERT( (IsValidChar(nStartIndex, GetString().getLength()) &&
+ (nEndIndex == -1)) ||
+ IsValidRange(nStartIndex, nEndIndex, GetString().getLength()),
+ "please check parameters before calling this method" );
+
+ sal_uInt16 nStart = GetPortionData().GetModelPosition( nStartIndex );
+ sal_uInt16 nEnd = (nEndIndex == -1) ? (nStart + 1) :
+ GetPortionData().GetModelPosition( nEndIndex );
+
+ // create UNO cursor
+ SwTxtNode* pTxtNode = const_cast<SwTxtNode*>( GetTxtNode() );
+ SwIndex aIndex( pTxtNode, nStart );
+ SwPosition aStartPos( *pTxtNode, aIndex );
+ SwUnoCrsr* pUnoCursor = pTxtNode->GetDoc()->CreateUnoCrsr( aStartPos );
+ pUnoCursor->SetMark();
+ pUnoCursor->GetMark()->nContent = nEnd;
+
+ // create a (dummy) text portion to be returned
+ uno::Reference<text::XText> aEmpty;
+ SwXTextPortion* pPortion =
+ new SwXTextPortion ( pUnoCursor, aEmpty, PORTION_TEXT);
+ delete pUnoCursor;
+
+ return pPortion;
+}
+
+
+//
+// range checking for parameter
+//
+
+sal_Bool SwAccessibleParagraph::IsValidChar(
+ sal_Int32 nPos, sal_Int32 nLength)
+{
+ return (nPos >= 0) && (nPos < nLength);
+}
+
+sal_Bool SwAccessibleParagraph::IsValidPosition(
+ sal_Int32 nPos, sal_Int32 nLength)
+{
+ return (nPos >= 0) && (nPos <= nLength);
+}
+
+sal_Bool SwAccessibleParagraph::IsValidRange(
+ sal_Int32 nBegin, sal_Int32 nEnd, sal_Int32 nLength)
+{
+ return IsValidPosition(nBegin, nLength) && IsValidPosition(nEnd, nLength);
+}
+
+
+//
+// text boundaries
+//
+
+
+sal_Bool SwAccessibleParagraph::GetCharBoundary(
+ i18n::Boundary& rBound,
+ const ::rtl::OUString&,
+ sal_Int32 nPos )
+{
+ rBound.startPos = nPos;
+ rBound.endPos = nPos+1;
+ return sal_True;
+}
+
+sal_Bool SwAccessibleParagraph::GetWordBoundary(
+ i18n::Boundary& rBound,
+ const ::rtl::OUString& rText,
+ sal_Int32 nPos )
+{
+ sal_Bool bRet = sal_False;
+
+ // now ask the Break-Iterator for the word
+ DBG_ASSERT( pBreakIt != NULL, "We always need a break." );
+ DBG_ASSERT( pBreakIt->GetBreakIter().is(), "No break-iterator." );
+ if( pBreakIt->GetBreakIter().is() )
+ {
+ // get locale for this position
+ sal_uInt16 nModelPos = GetPortionData().GetModelPosition( nPos );
+ lang::Locale aLocale = pBreakIt->GetLocale(
+ GetTxtNode()->GetLang( nModelPos ) );
+
+ // which type of word are we interested in?
+ // (DICTIONARY_WORD includes punctuation, ANY_WORD doesn't.)
+ const sal_uInt16 nWordType = i18n::WordType::ANY_WORD;
+
+ // get word boundary, as the Break-Iterator sees fit.
+ rBound = pBreakIt->GetBreakIter()->getWordBoundary(
+ rText, nPos, aLocale, nWordType, sal_True );
+
+ // It's a word if the first character is an alpha-numeric character.
+ bRet = GetAppCharClass().isLetterNumeric(
+ rText.getStr()[ rBound.startPos ] );
+ }
+ else
+ {
+ // no break Iterator -> no word
+ rBound.startPos = nPos;
+ rBound.endPos = nPos;
+ }
+
+ return bRet;
+}
+
+sal_Bool SwAccessibleParagraph::GetSentenceBoundary(
+ i18n::Boundary& rBound,
+ const ::rtl::OUString&,
+ sal_Int32 nPos )
+{
+ GetPortionData().GetSentenceBoundary( rBound, nPos );
+ return sal_True;
+}
+
+sal_Bool SwAccessibleParagraph::GetLineBoundary(
+ i18n::Boundary& rBound,
+ const ::rtl::OUString& rText,
+ sal_Int32 nPos )
+{
+ if( rText.getLength() == nPos )
+ GetPortionData().GetLastLineBoundary( rBound );
+ else
+ GetPortionData().GetLineBoundary( rBound, nPos );
+ return sal_True;
+}
+
+sal_Bool SwAccessibleParagraph::GetParagraphBoundary(
+ i18n::Boundary& rBound,
+ const ::rtl::OUString& rText,
+ sal_Int32 )
+{
+ rBound.startPos = 0;
+ rBound.endPos = rText.getLength();
+ return sal_True;
+}
+
+sal_Bool SwAccessibleParagraph::GetAttributeBoundary(
+ i18n::Boundary& rBound,
+ const ::rtl::OUString&,
+ sal_Int32 nPos )
+{
+ GetPortionData().GetAttributeBoundary( rBound, nPos );
+ return sal_True;
+}
+
+sal_Bool SwAccessibleParagraph::GetGlyphBoundary(
+ i18n::Boundary& rBound,
+ const ::rtl::OUString& rText,
+ sal_Int32 nPos )
+{
+ sal_Bool bRet = sal_False;
+
+ // ask the Break-Iterator for the glyph by moving one cell
+ // forward, and then one cell back
+ DBG_ASSERT( pBreakIt != NULL, "We always need a break." );
+ DBG_ASSERT( pBreakIt->GetBreakIter().is(), "No break-iterator." );
+ if( pBreakIt->GetBreakIter().is() )
+ {
+ // get locale for this position
+ sal_uInt16 nModelPos = GetPortionData().GetModelPosition( nPos );
+ lang::Locale aLocale = pBreakIt->GetLocale(
+ GetTxtNode()->GetLang( nModelPos ) );
+
+ // get word boundary, as the Break-Iterator sees fit.
+ const sal_uInt16 nIterMode = i18n::CharacterIteratorMode::SKIPCELL;
+ sal_Int32 nDone = 0;
+ rBound.endPos = pBreakIt->GetBreakIter()->nextCharacters(
+ rText, nPos, aLocale, nIterMode, 1, nDone );
+ rBound.startPos = pBreakIt->GetBreakIter()->previousCharacters(
+ rText, rBound.endPos, aLocale, nIterMode, 1, nDone );
+
+ DBG_ASSERT( rBound.startPos <= nPos, "start pos too high" );
+ DBG_ASSERT( rBound.endPos >= nPos, "end pos too low" );
+ }
+ else
+ {
+ // no break Iterator -> no glyph
+ rBound.startPos = nPos;
+ rBound.endPos = nPos;
+ }
+
+ return bRet;
+}
+
+
+sal_Bool SwAccessibleParagraph::GetTextBoundary(
+ i18n::Boundary& rBound,
+ const ::rtl::OUString& rText,
+ sal_Int32 nPos,
+ sal_Int16 nTextType )
+ throw (
+ lang::IndexOutOfBoundsException,
+ lang::IllegalArgumentException,
+ uno::RuntimeException)
+{
+ // error checking
+ if( !( AccessibleTextType::LINE == nTextType
+ ? IsValidPosition( nPos, rText.getLength() )
+ : IsValidChar( nPos, rText.getLength() ) ) )
+ throw lang::IndexOutOfBoundsException();
+
+ sal_Bool bRet;
+
+ switch( nTextType )
+ {
+ case AccessibleTextType::WORD:
+ bRet = GetWordBoundary( rBound, rText, nPos );
+ break;
+
+ case AccessibleTextType::SENTENCE:
+ bRet = GetSentenceBoundary( rBound, rText, nPos );
+ break;
+
+ case AccessibleTextType::PARAGRAPH:
+ bRet = GetParagraphBoundary( rBound, rText, nPos );
+ break;
+
+ case AccessibleTextType::CHARACTER:
+ bRet = GetCharBoundary( rBound, rText, nPos );
+ break;
+
+ case AccessibleTextType::LINE:
+ bRet = GetLineBoundary( rBound, rText, nPos );
+ break;
+
+ case AccessibleTextType::ATTRIBUTE_RUN:
+ bRet = GetAttributeBoundary( rBound, rText, nPos );
+ break;
+
+ case AccessibleTextType::GLYPH:
+ bRet = GetGlyphBoundary( rBound, rText, nPos );
+ break;
+
+ default:
+ throw lang::IllegalArgumentException( );
+ }
+
+ return bRet;
+}
+
+::rtl::OUString SAL_CALL SwAccessibleParagraph::getAccessibleDescription (void)
+ throw (uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+
+ CHECK_FOR_DEFUNC( XAccessibleContext );
+
+ osl::MutexGuard aGuard2( aMutex );
+ if( !sDesc.getLength() )
+ sDesc = GetDescription();
+
+ return sDesc;
+}
+
+lang::Locale SAL_CALL SwAccessibleParagraph::getLocale (void)
+ throw (IllegalAccessibleComponentStateException, uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+
+ SwTxtFrm *pTxtFrm = PTR_CAST( SwTxtFrm, GetFrm() );
+ if( !pTxtFrm )
+ {
+ THROW_RUNTIME_EXCEPTION( XAccessibleContext, "internal error (no text frame)" );
+ }
+
+ const SwTxtNode *pTxtNd = pTxtFrm->GetTxtNode();
+ lang::Locale aLoc( pBreakIt->GetLocale( pTxtNd->GetLang( 0 ) ) );
+
+ return aLoc;
+}
+
+/** #i27138# - paragraphs are in relation CONTENT_FLOWS_FROM and/or CONTENT_FLOWS_TO */
+uno::Reference<XAccessibleRelationSet> SAL_CALL SwAccessibleParagraph::getAccessibleRelationSet()
+ throw ( uno::RuntimeException )
+{
+ SolarMutexGuard aGuard;
+ CHECK_FOR_DEFUNC( XAccessibleContext );
+
+ utl::AccessibleRelationSetHelper* pHelper = new utl::AccessibleRelationSetHelper();
+
+ const SwTxtFrm* pTxtFrm = dynamic_cast<const SwTxtFrm*>(GetFrm());
+ OSL_ENSURE( pTxtFrm,
+ "<SwAccessibleParagraph::getAccessibleRelationSet()> - missing text frame");
+ if ( pTxtFrm )
+ {
+ const SwCntntFrm* pPrevCntFrm( pTxtFrm->FindPrevCnt( true ) );
+ if ( pPrevCntFrm )
+ {
+ uno::Sequence< uno::Reference<XInterface> > aSequence(1);
+ aSequence[0] = GetMap()->GetContext( pPrevCntFrm );
+ AccessibleRelation aAccRel( AccessibleRelationType::CONTENT_FLOWS_FROM,
+ aSequence );
+ pHelper->AddRelation( aAccRel );
+ }
+
+ const SwCntntFrm* pNextCntFrm( pTxtFrm->FindNextCnt( true ) );
+ if ( pNextCntFrm )
+ {
+ uno::Sequence< uno::Reference<XInterface> > aSequence(1);
+ aSequence[0] = GetMap()->GetContext( pNextCntFrm );
+ AccessibleRelation aAccRel( AccessibleRelationType::CONTENT_FLOWS_TO,
+ aSequence );
+ pHelper->AddRelation( aAccRel );
+ }
+ }
+
+ return pHelper;
+}
+
+void SAL_CALL SwAccessibleParagraph::grabFocus()
+ throw (uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+
+ CHECK_FOR_DEFUNC( XAccessibleContext );
+
+ // get cursor shell
+ SwCrsrShell *pCrsrSh = GetCrsrShell();
+ SwPaM *pCrsr = GetCursor( false ); // #i27301# - consider new method signature
+ const SwTxtFrm *pTxtFrm = static_cast<const SwTxtFrm*>( GetFrm() );
+ const SwTxtNode* pTxtNd = pTxtFrm->GetTxtNode();
+
+ if( pCrsrSh != 0 && pTxtNd != 0 &&
+ ( pCrsr == 0 ||
+ pCrsr->GetPoint()->nNode.GetIndex() != pTxtNd->GetIndex() ||
+ !pTxtFrm->IsInside( pCrsr->GetPoint()->nContent.GetIndex()) ) )
+ {
+ // create pam for selection
+ SwIndex aIndex( const_cast< SwTxtNode * >( pTxtNd ),
+ pTxtFrm->GetOfst() );
+ SwPosition aStartPos( *pTxtNd, aIndex );
+ SwPaM aPaM( aStartPos );
+
+ // set PaM at cursor shell
+ Select( aPaM );
+
+
+ }
+
+ /* ->#i13955# */
+ Window * pWindow = GetWindow();
+
+ if (pWindow != NULL)
+ pWindow->GrabFocus();
+ /* <-#i13955# */
+}
+
+// #i71385#
+bool lcl_GetBackgroundColor( Color & rColor,
+ const SwFrm* pFrm,
+ SwCrsrShell* pCrsrSh )
+{
+ const SvxBrushItem* pBackgrdBrush = 0;
+ const Color* pSectionTOXColor = 0;
+ SwRect aDummyRect;
+ if ( pFrm &&
+ pFrm->GetBackgroundBrush( pBackgrdBrush, pSectionTOXColor, aDummyRect, false ) )
+ {
+ if ( pSectionTOXColor )
+ {
+ rColor = *pSectionTOXColor;
+ return true;
+ }
+ else
+ {
+ rColor = pBackgrdBrush->GetColor();
+ return true;
+ }
+ }
+ else if ( pCrsrSh )
+ {
+ rColor = pCrsrSh->Imp()->GetRetoucheColor();
+ return true;
+ }
+
+ return false;
+}
+
+sal_Int32 SAL_CALL SwAccessibleParagraph::getForeground()
+ throw (uno::RuntimeException)
+{
+ Color aBackgroundCol;
+
+ if ( lcl_GetBackgroundColor( aBackgroundCol, GetFrm(), GetCrsrShell() ) )
+ {
+ if ( aBackgroundCol.IsDark() )
+ {
+ return COL_WHITE;
+ }
+ else
+ {
+ return COL_BLACK;
+ }
+ }
+
+ return SwAccessibleContext::getForeground();
+}
+
+sal_Int32 SAL_CALL SwAccessibleParagraph::getBackground()
+ throw (uno::RuntimeException)
+{
+ Color aBackgroundCol;
+
+ if ( lcl_GetBackgroundColor( aBackgroundCol, GetFrm(), GetCrsrShell() ) )
+ {
+ return aBackgroundCol.GetColor();
+ }
+
+ return SwAccessibleContext::getBackground();
+}
+// <--
+
+::rtl::OUString SAL_CALL SwAccessibleParagraph::getImplementationName()
+ throw( uno::RuntimeException )
+{
+ return ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(sImplementationName));
+}
+
+sal_Bool SAL_CALL SwAccessibleParagraph::supportsService(
+ const ::rtl::OUString& sTestServiceName)
+ throw (uno::RuntimeException)
+{
+ return sTestServiceName.equalsAsciiL( sServiceName,
+ sizeof(sServiceName)-1 ) ||
+ sTestServiceName.equalsAsciiL( sAccessibleServiceName,
+ sizeof(sAccessibleServiceName)-1 );
+}
+
+uno::Sequence< ::rtl::OUString > SAL_CALL SwAccessibleParagraph::getSupportedServiceNames()
+ throw( uno::RuntimeException )
+{
+ uno::Sequence< ::rtl::OUString > aRet(2);
+ ::rtl::OUString* pArray = aRet.getArray();
+ pArray[0] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(sServiceName) );
+ pArray[1] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(sAccessibleServiceName) );
+ return aRet;
+}
+
+//
+//===== XInterface =======================================================
+//
+
+uno::Any SwAccessibleParagraph::queryInterface( const uno::Type& rType )
+ throw (uno::RuntimeException)
+{
+ uno::Any aRet;
+ if ( rType == ::getCppuType((uno::Reference<XAccessibleText> *)0) )
+ {
+ uno::Reference<XAccessibleText> aAccText = (XAccessibleText *) *this; // resolve ambiguity
+ aRet <<= aAccText;
+ }
+ else if ( rType == ::getCppuType((uno::Reference<XAccessibleEditableText> *)0) )
+ {
+ uno::Reference<XAccessibleEditableText> aAccEditText = this;
+ aRet <<= aAccEditText;
+ }
+ else if ( rType == ::getCppuType((uno::Reference<XAccessibleSelection> *)0) )
+ {
+ uno::Reference<XAccessibleSelection> aAccSel = this;
+ aRet <<= aAccSel;
+ }
+ else if ( rType == ::getCppuType((uno::Reference<XAccessibleHypertext> *)0) )
+ {
+ uno::Reference<XAccessibleHypertext> aAccHyp = this;
+ aRet <<= aAccHyp;
+ }
+ // #i63870#
+ // add interface com::sun:star:accessibility::XAccessibleTextAttributes
+ else if ( rType == ::getCppuType((uno::Reference<XAccessibleTextAttributes> *)0) )
+ {
+ uno::Reference<XAccessibleTextAttributes> aAccTextAttr = this;
+ aRet <<= aAccTextAttr;
+ }
+ // <--
+ // #i89175#
+ // add interface com::sun:star:accessibility::XAccessibleTextMarkup
+ else if ( rType == ::getCppuType((uno::Reference<XAccessibleTextMarkup> *)0) )
+ {
+ uno::Reference<XAccessibleTextMarkup> aAccTextMarkup = this;
+ aRet <<= aAccTextMarkup;
+ }
+ // add interface com::sun:star:accessibility::XAccessibleMultiLineText
+ else if ( rType == ::getCppuType((uno::Reference<XAccessibleMultiLineText> *)0) )
+ {
+ uno::Reference<XAccessibleMultiLineText> aAccMultiLineText = this;
+ aRet <<= aAccMultiLineText;
+ }
+ // <--
+ else
+ {
+ aRet = SwAccessibleContext::queryInterface(rType);
+ }
+
+ return aRet;
+}
+
+//====== XTypeProvider ====================================================
+uno::Sequence< uno::Type > SAL_CALL SwAccessibleParagraph::getTypes() throw(uno::RuntimeException)
+{
+ uno::Sequence< uno::Type > aTypes( SwAccessibleContext::getTypes() );
+
+ sal_Int32 nIndex = aTypes.getLength();
+ // #i63870# - add type accessibility::XAccessibleTextAttributes
+ // #i89175# - add type accessibility::XAccessibleTextMarkup and
+ // accessibility::XAccessibleMultiLineText
+ aTypes.realloc( nIndex + 6 );
+
+ uno::Type* pTypes = aTypes.getArray();
+ pTypes[nIndex++] = ::getCppuType( static_cast< uno::Reference< XAccessibleEditableText > * >( 0 ) );
+ pTypes[nIndex++] = ::getCppuType( static_cast< uno::Reference< XAccessibleTextAttributes > * >( 0 ) );
+ pTypes[nIndex++] = ::getCppuType( static_cast< uno::Reference< XAccessibleSelection > * >( 0 ) );
+ pTypes[nIndex++] = ::getCppuType( static_cast< uno::Reference< XAccessibleTextMarkup > * >( 0 ) );
+ pTypes[nIndex++] = ::getCppuType( static_cast< uno::Reference< XAccessibleMultiLineText > * >( 0 ) );
+ pTypes[nIndex] = ::getCppuType( static_cast< uno::Reference< XAccessibleHypertext > * >( 0 ) );
+ // <--
+
+ return aTypes;
+}
+
+uno::Sequence< sal_Int8 > SAL_CALL SwAccessibleParagraph::getImplementationId()
+ throw(uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+ static uno::Sequence< sal_Int8 > aId( 16 );
+ static sal_Bool bInit = sal_False;
+ if(!bInit)
+ {
+ rtl_createUuid( (sal_uInt8 *)(aId.getArray() ), 0, sal_True );
+ bInit = sal_True;
+ }
+ return aId;
+}
+
+
+//
+//===== XAccesibleText ===================================================
+//
+
+sal_Int32 SwAccessibleParagraph::getCaretPosition()
+ throw (uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+
+ CHECK_FOR_DEFUNC_THIS( XAccessibleText, *this );
+
+ sal_Int32 nRet = GetCaretPos();
+ {
+ osl::MutexGuard aOldCaretPosGuard( aMutex );
+ OSL_ENSURE( nRet == nOldCaretPos, "caret pos out of sync" );
+ nOldCaretPos = nRet;
+ }
+ if( -1 != nRet )
+ {
+ ::rtl::Reference < SwAccessibleContext > xThis( this );
+ GetMap()->SetCursorContext( xThis );
+ }
+
+ return nRet;
+}
+
+sal_Bool SAL_CALL SwAccessibleParagraph::setCaretPosition( sal_Int32 nIndex )
+ throw (lang::IndexOutOfBoundsException, uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+
+ CHECK_FOR_DEFUNC_THIS( XAccessibleText, *this );
+
+ // parameter checking
+ sal_Int32 nLength = GetString().getLength();
+ if ( ! IsValidPosition( nIndex, nLength ) )
+ {
+ throw lang::IndexOutOfBoundsException();
+ }
+
+ sal_Bool bRet = sal_False;
+
+ // get cursor shell
+ SwCrsrShell* pCrsrShell = GetCrsrShell();
+ if( pCrsrShell != NULL )
+ {
+ // create pam for selection
+ SwTxtNode* pNode = const_cast<SwTxtNode*>( GetTxtNode() );
+ SwIndex aIndex( pNode, GetPortionData().GetModelPosition(nIndex));
+ SwPosition aStartPos( *pNode, aIndex );
+ SwPaM aPaM( aStartPos );
+
+ // set PaM at cursor shell
+ bRet = Select( aPaM );
+ }
+
+ return bRet;
+}
+
+sal_Unicode SwAccessibleParagraph::getCharacter( sal_Int32 nIndex )
+ throw (lang::IndexOutOfBoundsException, uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+
+ CHECK_FOR_DEFUNC_THIS( XAccessibleText, *this );
+
+ ::rtl::OUString sText( GetString() );
+
+ // return character (if valid)
+ if( IsValidChar(nIndex, sText.getLength() ) )
+ {
+ return sText.getStr()[nIndex];
+ }
+ else
+ throw lang::IndexOutOfBoundsException();
+}
+
+// #i63870# - re-implement method on behalf of methods
+// <_getDefaultAttributesImpl(..)> and <_getRunAttributesImpl(..)>
+uno::Sequence<PropertyValue> SwAccessibleParagraph::getCharacterAttributes(
+ sal_Int32 nIndex,
+ const uno::Sequence< ::rtl::OUString >& aRequestedAttributes )
+ throw (lang::IndexOutOfBoundsException, uno::RuntimeException)
+{
+
+ SolarMutexGuard aGuard;
+ CHECK_FOR_DEFUNC_THIS( XAccessibleText, *this );
+
+ const ::rtl::OUString& rText = GetString();
+
+ if( ! IsValidChar( nIndex, rText.getLength() ) )
+ throw lang::IndexOutOfBoundsException();
+
+ // retrieve default character attributes
+ tAccParaPropValMap aDefAttrSeq;
+ _getDefaultAttributesImpl( aRequestedAttributes, aDefAttrSeq, true );
+
+ // retrieved run character attributes
+ tAccParaPropValMap aRunAttrSeq;
+ _getRunAttributesImpl( nIndex, aRequestedAttributes, aRunAttrSeq );
+
+ // merge default and run attributes
+ uno::Sequence< PropertyValue > aValues( aDefAttrSeq.size() );
+ PropertyValue* pValues = aValues.getArray();
+ sal_Int32 i = 0;
+ for ( tAccParaPropValMap::const_iterator aDefIter = aDefAttrSeq.begin();
+ aDefIter != aDefAttrSeq.end();
+ ++aDefIter )
+ {
+ tAccParaPropValMap::const_iterator aRunIter =
+ aRunAttrSeq.find( aDefIter->first );
+ if ( aRunIter != aRunAttrSeq.end() )
+ {
+ pValues[i] = aRunIter->second;
+ }
+ else
+ {
+ pValues[i] = aDefIter->second;
+ }
+ ++i;
+ }
+
+ return aValues;
+}
+
+// #i63870#
+void SwAccessibleParagraph::_getDefaultAttributesImpl(
+ const uno::Sequence< ::rtl::OUString >& aRequestedAttributes,
+ tAccParaPropValMap& rDefAttrSeq,
+ const bool bOnlyCharAttrs )
+{
+ // retrieve default attributes
+ const SwTxtNode* pTxtNode( GetTxtNode() );
+ ::boost::scoped_ptr<SfxItemSet> pSet;
+ if ( !bOnlyCharAttrs )
+ {
+ pSet.reset( new SfxItemSet( const_cast<SwAttrPool&>(pTxtNode->GetDoc()->GetAttrPool()),
+ RES_CHRATR_BEGIN, RES_CHRATR_END - 1,
+ RES_PARATR_BEGIN, RES_PARATR_END - 1,
+ RES_FRMATR_BEGIN, RES_FRMATR_END - 1,
+ 0 ) );
+ }
+ else
+ {
+ pSet.reset( new SfxItemSet( const_cast<SwAttrPool&>(pTxtNode->GetDoc()->GetAttrPool()),
+ RES_CHRATR_BEGIN, RES_CHRATR_END - 1,
+ 0 ) );
+ }
+ // #i82637# - From the perspective of the a11y API the default character
+ // attributes are the character attributes, which are set at the paragraph style
+ // of the paragraph. The character attributes set at the automatic paragraph
+ // style of the paragraph are treated as run attributes.
+// pTxtNode->SwCntntNode::GetAttr( *pSet );
+ // get default paragraph attributes, if needed, and merge these into <pSet>
+ if ( !bOnlyCharAttrs )
+ {
+ SfxItemSet aParaSet( const_cast<SwAttrPool&>(pTxtNode->GetDoc()->GetAttrPool()),
+ RES_PARATR_BEGIN, RES_PARATR_END - 1,
+ RES_FRMATR_BEGIN, RES_FRMATR_END - 1,
+ 0 );
+ pTxtNode->SwCntntNode::GetAttr( aParaSet );
+ pSet->Put( aParaSet );
+ }
+ // get default character attributes and merge these into <pSet>
+ OSL_ENSURE( pTxtNode->GetTxtColl(),
+ "<SwAccessibleParagraph::_getDefaultAttributesImpl(..)> - missing paragraph style. Serious defect, please inform OD!" );
+ if ( pTxtNode->GetTxtColl() )
+ {
+ SfxItemSet aCharSet( const_cast<SwAttrPool&>(pTxtNode->GetDoc()->GetAttrPool()),
+ RES_CHRATR_BEGIN, RES_CHRATR_END - 1,
+ 0 );
+ aCharSet.Put( pTxtNode->GetTxtColl()->GetAttrSet() );
+ pSet->Put( aCharSet );
+ }
+ // <--
+
+ // build-up sequence containing the run attributes <rDefAttrSeq>
+ tAccParaPropValMap aDefAttrSeq;
+ {
+ const SfxItemPropertyMap* pPropMap =
+ aSwMapProvider.GetPropertySet( PROPERTY_MAP_TEXT_CURSOR )->getPropertyMap();
+ PropertyEntryVector_t aPropertyEntries = pPropMap->getPropertyEntries();
+ PropertyEntryVector_t::const_iterator aPropIt = aPropertyEntries.begin();
+ while ( aPropIt != aPropertyEntries.end() )
+ {
+ const SfxPoolItem* pItem = pSet->GetItem( aPropIt->nWID );
+ if ( pItem )
+ {
+ uno::Any aVal;
+ pItem->QueryValue( aVal, aPropIt->nMemberId );
+
+ PropertyValue rPropVal;
+ rPropVal.Name = aPropIt->sName;
+ rPropVal.Value = aVal;
+ rPropVal.Handle = -1;
+ rPropVal.State = beans::PropertyState_DEFAULT_VALUE;
+
+ aDefAttrSeq[rPropVal.Name] = rPropVal;
+ }
+ ++aPropIt;
+ }
+
+ // #i72800#
+ // add property value entry for the paragraph style
+ if ( !bOnlyCharAttrs && pTxtNode->GetTxtColl() )
+ {
+ const ::rtl::OUString sParaStyleName =
+ ::rtl::OUString::createFromAscii(
+ GetPropName( UNO_NAME_PARA_STYLE_NAME ).pName );
+ if ( aDefAttrSeq.find( sParaStyleName ) == aDefAttrSeq.end() )
+ {
+ PropertyValue rPropVal;
+ rPropVal.Name = sParaStyleName;
+ uno::Any aVal( uno::makeAny( ::rtl::OUString( pTxtNode->GetTxtColl()->GetName() ) ) );
+ rPropVal.Value = aVal;
+ rPropVal.Handle = -1;
+ rPropVal.State = beans::PropertyState_DEFAULT_VALUE;
+
+ aDefAttrSeq[rPropVal.Name] = rPropVal;
+ }
+ }
+ // <--
+
+ // #i73371#
+ // resolve value text::WritingMode2::PAGE of property value entry WritingMode
+ if ( !bOnlyCharAttrs && GetFrm() )
+ {
+ const ::rtl::OUString sWritingMode =
+ ::rtl::OUString::createFromAscii(
+ GetPropName( UNO_NAME_WRITING_MODE ).pName );
+ tAccParaPropValMap::iterator aIter = aDefAttrSeq.find( sWritingMode );
+ if ( aIter != aDefAttrSeq.end() )
+ {
+ PropertyValue rPropVal( aIter->second );
+ sal_Int16 nVal = rPropVal.Value.get<sal_Int16>();
+ if ( nVal == text::WritingMode2::PAGE )
+ {
+ const SwFrm* pUpperFrm( GetFrm()->GetUpper() );
+ while ( pUpperFrm )
+ {
+ if ( pUpperFrm->GetType() &
+ ( FRM_PAGE | FRM_FLY | FRM_SECTION | FRM_TAB | FRM_CELL ) )
+ {
+ if ( pUpperFrm->IsVertical() )
+ {
+ nVal = text::WritingMode2::TB_RL;
+ }
+ else if ( pUpperFrm->IsRightToLeft() )
+ {
+ nVal = text::WritingMode2::RL_TB;
+ }
+ else
+ {
+ nVal = text::WritingMode2::LR_TB;
+ }
+ rPropVal.Value <<= nVal;
+ aDefAttrSeq[rPropVal.Name] = rPropVal;
+ break;
+ }
+
+ if ( dynamic_cast<const SwFlyFrm*>(pUpperFrm) )
+ {
+ pUpperFrm = dynamic_cast<const SwFlyFrm*>(pUpperFrm)->GetAnchorFrm();
+ }
+ else
+ {
+ pUpperFrm = pUpperFrm->GetUpper();
+ }
+ }
+ }
+ }
+ }
+ // <--
+ }
+
+ if ( aRequestedAttributes.getLength() == 0 )
+ {
+ rDefAttrSeq = aDefAttrSeq;
+ }
+ else
+ {
+ const ::rtl::OUString* pReqAttrs = aRequestedAttributes.getConstArray();
+ const sal_Int32 nLength = aRequestedAttributes.getLength();
+ for( sal_Int32 i = 0; i < nLength; ++i )
+ {
+ tAccParaPropValMap::const_iterator const aIter = aDefAttrSeq.find( pReqAttrs[i] );
+ if ( aIter != aDefAttrSeq.end() )
+ {
+ rDefAttrSeq[ aIter->first ] = aIter->second;
+ }
+ }
+ }
+}
+
+uno::Sequence< PropertyValue > SwAccessibleParagraph::getDefaultAttributes(
+ const uno::Sequence< ::rtl::OUString >& aRequestedAttributes )
+ throw ( uno::RuntimeException )
+{
+ SolarMutexGuard aGuard;
+ CHECK_FOR_DEFUNC_THIS( XAccessibleText, *this );
+
+ tAccParaPropValMap aDefAttrSeq;
+ _getDefaultAttributesImpl( aRequestedAttributes, aDefAttrSeq );
+
+ // #i92233#
+ static rtl::OUString sMMToPixelRatio(RTL_CONSTASCII_USTRINGPARAM("MMToPixelRatio"));
+ bool bProvideMMToPixelRatio( false );
+ {
+ if ( aRequestedAttributes.getLength() == 0 )
+ {
+ bProvideMMToPixelRatio = true;
+ }
+ else
+ {
+ const rtl::OUString* aRequestedAttrIter =
+ ::std::find( ::comphelper::stl_begin( aRequestedAttributes ),
+ ::comphelper::stl_end( aRequestedAttributes ),
+ sMMToPixelRatio );
+ if ( aRequestedAttrIter != ::comphelper::stl_end( aRequestedAttributes ) )
+ {
+ bProvideMMToPixelRatio = true;
+ }
+ }
+ }
+ // <--
+
+ uno::Sequence< PropertyValue > aValues( aDefAttrSeq.size() +
+ ( bProvideMMToPixelRatio ? 1 : 0 ) );
+ PropertyValue* pValues = aValues.getArray();
+ sal_Int32 i = 0;
+ for ( tAccParaPropValMap::const_iterator aIter = aDefAttrSeq.begin();
+ aIter != aDefAttrSeq.end();
+ ++aIter )
+ {
+ pValues[i] = aIter->second;
+ ++i;
+ }
+
+ // #i92233#
+ if ( bProvideMMToPixelRatio )
+ {
+ PropertyValue rPropVal;
+ rPropVal.Name = sMMToPixelRatio;
+ const Size a100thMMSize( 1000, 1000 );
+ const Size aPixelSize = GetMap()->LogicToPixel( a100thMMSize );
+ const float fRatio = ((float)a100thMMSize.Width()/100)/aPixelSize.Width();
+ rPropVal.Value = uno::makeAny( fRatio );
+ rPropVal.Handle = -1;
+ rPropVal.State = beans::PropertyState_DEFAULT_VALUE;
+ pValues[ aValues.getLength() - 1 ] = rPropVal;
+ }
+ // <--
+
+ return aValues;
+}
+
+void SwAccessibleParagraph::_getRunAttributesImpl(
+ const sal_Int32 nIndex,
+ const uno::Sequence< ::rtl::OUString >& aRequestedAttributes,
+ tAccParaPropValMap& rRunAttrSeq )
+{
+ // create PaM for character at position <nIndex>
+ SwPaM* pPaM( 0 );
+ {
+ const SwTxtNode* pTxtNode( GetTxtNode() );
+ SwPosition* pStartPos = new SwPosition( *pTxtNode );
+ pStartPos->nContent.Assign( const_cast<SwTxtNode*>(pTxtNode), static_cast<sal_uInt16>(nIndex) );
+ SwPosition* pEndPos = new SwPosition( *pTxtNode );
+ pEndPos->nContent.Assign( const_cast<SwTxtNode*>(pTxtNode), static_cast<sal_uInt16>(nIndex+1) );
+
+ pPaM = new SwPaM( *pStartPos, *pEndPos );
+
+ delete pStartPos;
+ delete pEndPos;
+ }
+
+ // retrieve character attributes for the created PaM <pPaM>
+ SfxItemSet aSet( pPaM->GetDoc()->GetAttrPool(),
+ RES_CHRATR_BEGIN, RES_CHRATR_END -1,
+ 0 );
+ // #i82637#
+ // From the perspective of the a11y API the character attributes, which
+ // are set at the automatic paragraph style of the paragraph are treated
+ // as run attributes.
+// SwXTextCursor::GetCrsrAttr( *pPaM, aSet, sal_True, sal_True );
+ // get character attributes from automatic paragraph style and merge these into <aSet>
+ {
+ const SwTxtNode* pTxtNode( GetTxtNode() );
+ if ( pTxtNode->HasSwAttrSet() )
+ {
+ SfxItemSet aAutomaticParaStyleCharAttrs( pPaM->GetDoc()->GetAttrPool(),
+ RES_CHRATR_BEGIN, RES_CHRATR_END -1,
+ 0 );
+ aAutomaticParaStyleCharAttrs.Put( *(pTxtNode->GetpSwAttrSet()), sal_False );
+ aSet.Put( aAutomaticParaStyleCharAttrs );
+ }
+ }
+ // get character attributes at <pPaM> and merge these into <aSet>
+ {
+ SfxItemSet aCharAttrsAtPaM( pPaM->GetDoc()->GetAttrPool(),
+ RES_CHRATR_BEGIN, RES_CHRATR_END -1,
+ 0 );
+ SwUnoCursorHelper::GetCrsrAttr(*pPaM, aCharAttrsAtPaM, sal_True, sal_True);
+ aSet.Put( aCharAttrsAtPaM );
+ }
+ // <--
+
+ // build-up sequence containing the run attributes <rRunAttrSeq>
+ {
+ tAccParaPropValMap aRunAttrSeq;
+ {
+ tAccParaPropValMap aDefAttrSeq;
+ uno::Sequence< ::rtl::OUString > aDummy;
+ _getDefaultAttributesImpl( aDummy, aDefAttrSeq, true ); // #i82637#
+
+ const SfxItemPropertyMap* pPropMap =
+ aSwMapProvider.GetPropertySet( PROPERTY_MAP_TEXT_CURSOR )->getPropertyMap();
+ PropertyEntryVector_t aPropertyEntries = pPropMap->getPropertyEntries();
+ PropertyEntryVector_t::const_iterator aPropIt = aPropertyEntries.begin();
+ while ( aPropIt != aPropertyEntries.end() )
+ {
+ const SfxPoolItem* pItem( 0 );
+ // #i82637# - Found character attributes, whose value equals the value of
+ // the corresponding default character attributes, are excluded.
+ if ( aSet.GetItemState( aPropIt->nWID, sal_True, &pItem ) == SFX_ITEM_SET )
+ {
+ uno::Any aVal;
+ pItem->QueryValue( aVal, aPropIt->nMemberId );
+
+ PropertyValue rPropVal;
+ rPropVal.Name = aPropIt->sName;
+ rPropVal.Value = aVal;
+ rPropVal.Handle = -1;
+ rPropVal.State = PropertyState_DIRECT_VALUE;
+
+ tAccParaPropValMap::const_iterator aDefIter =
+ aDefAttrSeq.find( rPropVal.Name );
+ if ( aDefIter == aDefAttrSeq.end() ||
+ rPropVal.Value != aDefIter->second.Value )
+ {
+ aRunAttrSeq[rPropVal.Name] = rPropVal;
+ }
+ }
+
+ ++aPropIt;
+ }
+ }
+
+ if ( aRequestedAttributes.getLength() == 0 )
+ {
+ rRunAttrSeq = aRunAttrSeq;
+ }
+ else
+ {
+ const ::rtl::OUString* pReqAttrs = aRequestedAttributes.getConstArray();
+ const sal_Int32 nLength = aRequestedAttributes.getLength();
+ for( sal_Int32 i = 0; i < nLength; ++i )
+ {
+ tAccParaPropValMap::iterator aIter = aRunAttrSeq.find( pReqAttrs[i] );
+ if ( aIter != aRunAttrSeq.end() )
+ {
+ rRunAttrSeq[ (*aIter).first ] = (*aIter).second;
+ }
+ }
+ }
+ }
+
+ delete pPaM;
+}
+
+uno::Sequence< PropertyValue > SwAccessibleParagraph::getRunAttributes(
+ sal_Int32 nIndex,
+ const uno::Sequence< ::rtl::OUString >& aRequestedAttributes )
+ throw ( lang::IndexOutOfBoundsException,
+ uno::RuntimeException )
+{
+ SolarMutexGuard aGuard;
+ CHECK_FOR_DEFUNC_THIS( XAccessibleText, *this );
+
+ {
+ const ::rtl::OUString& rText = GetString();
+ if ( !IsValidChar( nIndex, rText.getLength() ) )
+ {
+ throw lang::IndexOutOfBoundsException();
+ }
+ }
+
+ tAccParaPropValMap aRunAttrSeq;
+ _getRunAttributesImpl( nIndex, aRequestedAttributes, aRunAttrSeq );
+
+ uno::Sequence< PropertyValue > aValues( aRunAttrSeq.size() );
+ PropertyValue* pValues = aValues.getArray();
+ sal_Int32 i = 0;
+ for ( tAccParaPropValMap::const_iterator aIter = aRunAttrSeq.begin();
+ aIter != aRunAttrSeq.end();
+ ++aIter )
+ {
+ pValues[i] = aIter->second;
+ ++i;
+ }
+
+ return aValues;
+}
+// <--
+
+awt::Rectangle SwAccessibleParagraph::getCharacterBounds(
+ sal_Int32 nIndex )
+ throw (lang::IndexOutOfBoundsException, uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+
+ CHECK_FOR_DEFUNC_THIS( XAccessibleText, *this );
+
+
+ /* #i12332# The position after the string needs special treatment.
+ IsValidChar -> IsValidPosition
+ */
+ if( ! (IsValidPosition( nIndex, GetString().getLength() ) ) )
+ throw lang::IndexOutOfBoundsException();
+
+ /* #i12332# */
+ sal_Bool bBehindText = sal_False;
+ if ( nIndex == GetString().getLength() )
+ bBehindText = sal_True;
+
+ // get model position & prepare GetCharRect() arguments
+ SwCrsrMoveState aMoveState;
+ aMoveState.bRealHeight = sal_True;
+ aMoveState.bRealWidth = sal_True;
+ SwSpecialPos aSpecialPos;
+ SwTxtNode* pNode = const_cast<SwTxtNode*>( GetTxtNode() );
+
+ sal_uInt16 nPos = 0;
+
+ /* #i12332# FillSpecialPos does not accept nIndex ==
+ GetString().getLength(). In that case nPos is set to the
+ length of the string in the core. This way GetCharRect
+ returns the rectangle for a cursor at the end of the
+ paragraph. */
+ if (bBehindText)
+ {
+ nPos = pNode->GetTxt().Len();
+ }
+ else
+ nPos = GetPortionData().FillSpecialPos
+ (nIndex, aSpecialPos, aMoveState.pSpecialPos );
+
+ // call GetCharRect
+ SwRect aCoreRect;
+ SwIndex aIndex( pNode, nPos );
+ SwPosition aPosition( *pNode, aIndex );
+ GetFrm()->GetCharRect( aCoreRect, aPosition, &aMoveState );
+
+ // translate core coordinates into accessibility coordinates
+ Window *pWin = GetWindow();
+ CHECK_FOR_WINDOW( XAccessibleComponent, pWin );
+
+ Rectangle aScreenRect( GetMap()->CoreToPixel( aCoreRect.SVRect() ));
+ SwRect aFrmLogBounds( GetBounds( *(GetMap()) ) ); // twip rel to doc root
+
+ Point aFrmPixPos( GetMap()->CoreToPixel( aFrmLogBounds.SVRect() ).TopLeft() );
+ aScreenRect.Move( -aFrmPixPos.X(), -aFrmPixPos.Y() );
+
+ // convert into AWT Rectangle
+ return awt::Rectangle(
+ aScreenRect.Left(), aScreenRect.Top(),
+ aScreenRect.GetWidth(), aScreenRect.GetHeight() );
+}
+
+sal_Int32 SwAccessibleParagraph::getCharacterCount()
+ throw (uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+
+ CHECK_FOR_DEFUNC_THIS( XAccessibleText, *this );
+
+ return GetString().getLength();
+}
+
+sal_Int32 SwAccessibleParagraph::getIndexAtPoint( const awt::Point& rPoint )
+ throw (uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+
+
+ CHECK_FOR_DEFUNC_THIS( XAccessibleText, *this );
+
+ // construct SwPosition (where GetCrsrOfst() will put the result into)
+ SwTxtNode* pNode = const_cast<SwTxtNode*>( GetTxtNode() );
+ SwIndex aIndex( pNode, 0);
+ SwPosition aPos( *pNode, aIndex );
+
+ // construct Point (translate into layout coordinates)
+ Window *pWin = GetWindow();
+ CHECK_FOR_WINDOW( XAccessibleComponent, pWin );
+ Point aPoint( rPoint.X, rPoint.Y );
+ SwRect aLogBounds( GetBounds( *(GetMap()), GetFrm() ) ); // twip rel to doc root
+ Point aPixPos( GetMap()->CoreToPixel( aLogBounds.SVRect() ).TopLeft() );
+ aPoint.X() += aPixPos.X();
+ aPoint.Y() += aPixPos.Y();
+ MapMode aMapMode = pWin->GetMapMode();
+ Point aCorePoint( GetMap()->PixelToCore( aPoint ) );
+ if( !aLogBounds.IsInside( aCorePoint ) )
+ {
+ /* #i12332# rPoint is may also be in rectangle returned by
+ getCharacterBounds(getCharacterCount() */
+
+ awt::Rectangle aRectEndPos =
+ getCharacterBounds(getCharacterCount());
+
+ if (rPoint.X - aRectEndPos.X >= 0 &&
+ rPoint.X - aRectEndPos.X < aRectEndPos.Width &&
+ rPoint.Y - aRectEndPos.Y >= 0 &&
+ rPoint.Y - aRectEndPos.Y < aRectEndPos.Height)
+ return getCharacterCount();
+
+ return -1;
+ }
+
+ // ask core for position
+ DBG_ASSERT( GetFrm() != NULL, "The text frame has vanished!" );
+ DBG_ASSERT( GetFrm()->IsTxtFrm(), "The text frame has mutated!" );
+ const SwTxtFrm* pFrm = static_cast<const SwTxtFrm*>( GetFrm() );
+ SwCrsrMoveState aMoveState;
+ aMoveState.bPosMatchesBounds = sal_True;
+ sal_Bool bSuccess = pFrm->GetCrsrOfst( &aPos, aCorePoint, &aMoveState );
+
+ SwIndex aCntntIdx = aPos.nContent;
+ const xub_StrLen nIndex = aCntntIdx.GetIndex();
+ if ( nIndex > 0 )
+ {
+ SwRect aResultRect;
+ pFrm->GetCharRect( aResultRect, aPos );
+ bool bVert = pFrm->IsVertical();
+ bool bR2L = pFrm->IsRightToLeft();
+
+ if ( (!bVert && aResultRect.Pos().X() > aCorePoint.X()) ||
+ ( bVert && aResultRect.Pos().Y() > aCorePoint.Y()) ||
+ ( bR2L && aResultRect.Right() < aCorePoint.X()) )
+ {
+ SwIndex aIdxPrev( pNode, nIndex - 1);
+ SwPosition aPosPrev( *pNode, aIdxPrev );
+ SwRect aResultRectPrev;
+ pFrm->GetCharRect( aResultRectPrev, aPosPrev );
+ if ( (!bVert && aResultRectPrev.Pos().X() < aCorePoint.X() && aResultRect.Pos().Y() == aResultRectPrev.Pos().Y()) ||
+ ( bVert && aResultRectPrev.Pos().Y() < aCorePoint.Y() && aResultRect.Pos().X() == aResultRectPrev.Pos().X()) ||
+ ( bR2L && aResultRectPrev.Right() > aCorePoint.X() && aResultRect.Pos().Y() == aResultRectPrev.Pos().Y()) )
+ aPos = aPosPrev;
+ }
+ }
+
+ return bSuccess ?
+ GetPortionData().GetAccessiblePosition( aPos.nContent.GetIndex() )
+ : -1L;
+}
+
+::rtl::OUString SwAccessibleParagraph::getSelectedText()
+ throw (uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+
+ CHECK_FOR_DEFUNC_THIS( XAccessibleText, *this );
+
+ sal_Int32 nStart, nEnd;
+ sal_Bool bSelected = GetSelection( nStart, nEnd );
+ return bSelected
+ ? GetString().copy( nStart, nEnd - nStart )
+ : ::rtl::OUString();
+}
+
+sal_Int32 SwAccessibleParagraph::getSelectionStart()
+ throw (uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+
+ CHECK_FOR_DEFUNC_THIS( XAccessibleText, *this );
+
+ sal_Int32 nStart, nEnd;
+ GetSelection( nStart, nEnd );
+ return nStart;
+}
+
+sal_Int32 SwAccessibleParagraph::getSelectionEnd()
+ throw (uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+
+ CHECK_FOR_DEFUNC_THIS( XAccessibleText, *this );
+
+ sal_Int32 nStart, nEnd;
+ GetSelection( nStart, nEnd );
+ return nEnd;
+}
+
+sal_Bool SwAccessibleParagraph::setSelection( sal_Int32 nStartIndex, sal_Int32 nEndIndex )
+ throw (lang::IndexOutOfBoundsException, uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+
+ CHECK_FOR_DEFUNC_THIS( XAccessibleText, *this );
+
+ // parameter checking
+ sal_Int32 nLength = GetString().getLength();
+ if ( ! IsValidRange( nStartIndex, nEndIndex, nLength ) )
+ {
+ throw lang::IndexOutOfBoundsException();
+ }
+
+ sal_Bool bRet = sal_False;
+
+ // get cursor shell
+ SwCrsrShell* pCrsrShell = GetCrsrShell();
+ if( pCrsrShell != NULL )
+ {
+ // create pam for selection
+ SwTxtNode* pNode = const_cast<SwTxtNode*>( GetTxtNode() );
+ SwIndex aIndex( pNode, GetPortionData().GetModelPosition(nStartIndex));
+ SwPosition aStartPos( *pNode, aIndex );
+ SwPaM aPaM( aStartPos );
+ aPaM.SetMark();
+ aPaM.GetPoint()->nContent =
+ GetPortionData().GetModelPosition(nEndIndex);
+
+ // set PaM at cursor shell
+ bRet = Select( aPaM );
+ }
+
+ return bRet;
+}
+
+::rtl::OUString SwAccessibleParagraph::getText()
+ throw (uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+
+ CHECK_FOR_DEFUNC_THIS( XAccessibleText, *this );
+
+ return GetString();
+}
+
+::rtl::OUString SwAccessibleParagraph::getTextRange(
+ sal_Int32 nStartIndex, sal_Int32 nEndIndex )
+ throw (lang::IndexOutOfBoundsException, uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+
+ CHECK_FOR_DEFUNC_THIS( XAccessibleText, *this );
+
+ ::rtl::OUString sText( GetString() );
+
+ if ( IsValidRange( nStartIndex, nEndIndex, sText.getLength() ) )
+ {
+ OrderRange( nStartIndex, nEndIndex );
+ return sText.copy(nStartIndex, nEndIndex-nStartIndex );
+ }
+ else
+ throw lang::IndexOutOfBoundsException();
+}
+
+/*accessibility::*/TextSegment SwAccessibleParagraph::getTextAtIndex( sal_Int32 nIndex, sal_Int16 nTextType ) throw (lang::IndexOutOfBoundsException, lang::IllegalArgumentException, uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+
+ CHECK_FOR_DEFUNC_THIS( XAccessibleText, *this );
+
+ /*accessibility::*/TextSegment aResult;
+ aResult.SegmentStart = -1;
+ aResult.SegmentEnd = -1;
+
+ const ::rtl::OUString rText = GetString();
+ // implement the silly specification that first position after
+ // text must return an empty string, rather than throwing an
+ // IndexOutOfBoundsException, except for LINE, where the last
+ // line is returned
+ if( nIndex == rText.getLength() && AccessibleTextType::LINE != nTextType )
+ return aResult;
+
+ // with error checking
+ i18n::Boundary aBound;
+ sal_Bool bWord = GetTextBoundary( aBound, rText, nIndex, nTextType );
+
+ DBG_ASSERT( aBound.startPos >= 0, "illegal boundary" );
+ DBG_ASSERT( aBound.startPos <= aBound.endPos, "illegal boundary" );
+
+ // return word (if present)
+ if ( bWord )
+ {
+ aResult.SegmentText = rText.copy( aBound.startPos, aBound.endPos - aBound.startPos );
+ aResult.SegmentStart = aBound.startPos;
+ aResult.SegmentEnd = aBound.endPos;
+ }
+
+ return aResult;
+}
+
+/*accessibility::*/TextSegment SwAccessibleParagraph::getTextBeforeIndex( sal_Int32 nIndex, sal_Int16 nTextType ) throw (lang::IndexOutOfBoundsException, lang::IllegalArgumentException, uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+
+ CHECK_FOR_DEFUNC_THIS( XAccessibleText, *this );
+
+ const ::rtl::OUString rText = GetString();
+
+ /*accessibility::*/TextSegment aResult;
+ aResult.SegmentStart = -1;
+ aResult.SegmentEnd = -1;
+
+ // get starting pos
+ i18n::Boundary aBound;
+ if (nIndex == rText.getLength())
+ aBound.startPos = aBound.endPos = nIndex;
+ else
+ {
+ sal_Bool bTmp = GetTextBoundary( aBound, rText, nIndex, nTextType );
+
+ if ( ! bTmp )
+ aBound.startPos = aBound.endPos = nIndex;
+ }
+
+ // now skip to previous word
+ sal_Bool bWord = sal_False;
+ while( !bWord )
+ {
+ nIndex = min( nIndex, aBound.startPos ) - 1;
+ if( nIndex >= 0 )
+ bWord = GetTextBoundary( aBound, rText, nIndex, nTextType );
+ else
+ break; // exit if beginning of string is reached
+ }
+
+ if ( bWord )
+ {
+ aResult.SegmentText = rText.copy( aBound.startPos, aBound.endPos - aBound.startPos );
+ aResult.SegmentStart = aBound.startPos;
+ aResult.SegmentEnd = aBound.endPos;
+ };
+ return aResult;
+}
+
+/*accessibility::*/TextSegment SwAccessibleParagraph::getTextBehindIndex( sal_Int32 nIndex, sal_Int16 nTextType ) throw (lang::IndexOutOfBoundsException, lang::IllegalArgumentException, uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+
+ CHECK_FOR_DEFUNC_THIS( XAccessibleText, *this );
+
+ /*accessibility::*/TextSegment aResult;
+ aResult.SegmentStart = -1;
+ aResult.SegmentEnd = -1;
+ const ::rtl::OUString rText = GetString();
+
+ // implement the silly specification that first position after
+ // text must return an empty string, rather than throwing an
+ // IndexOutOfBoundsException
+ if( nIndex == rText.getLength() )
+ return aResult;
+
+
+ // get first word, then skip to next word
+ i18n::Boundary aBound;
+ GetTextBoundary( aBound, rText, nIndex, nTextType );
+ sal_Bool bWord = sal_False;
+ while( !bWord )
+ {
+ nIndex = max( sal_Int32(nIndex+1), aBound.endPos );
+ if( nIndex < rText.getLength() )
+ bWord = GetTextBoundary( aBound, rText, nIndex, nTextType );
+ else
+ break; // exit if end of string is reached
+ }
+
+ if ( bWord )
+ {
+ aResult.SegmentText = rText.copy( aBound.startPos, aBound.endPos - aBound.startPos );
+ aResult.SegmentStart = aBound.startPos;
+ aResult.SegmentEnd = aBound.endPos;
+ }
+ return aResult;
+}
+
+sal_Bool SwAccessibleParagraph::copyText( sal_Int32 nStartIndex, sal_Int32 nEndIndex )
+ throw (lang::IndexOutOfBoundsException, uno::RuntimeException)
+{
+ CHECK_FOR_DEFUNC_THIS( XAccessibleText, *this );
+ SolarMutexGuard aGuard;
+
+ // select and copy (through dispatch mechanism)
+ setSelection( nStartIndex, nEndIndex );
+ ExecuteAtViewShell( SID_COPY );
+ return sal_True;
+}
+
+
+//
+//===== XAccesibleEditableText ==========================================
+//
+
+sal_Bool SwAccessibleParagraph::cutText( sal_Int32 nStartIndex, sal_Int32 nEndIndex )
+ throw (lang::IndexOutOfBoundsException, uno::RuntimeException)
+{
+ CHECK_FOR_DEFUNC( XAccessibleEditableText );
+ SolarMutexGuard aGuard;
+
+ if( !IsEditableState() )
+ return sal_False;
+
+ // select and cut (through dispatch mechanism)
+ setSelection( nStartIndex, nEndIndex );
+ ExecuteAtViewShell( SID_CUT );
+ return sal_True;
+}
+
+sal_Bool SwAccessibleParagraph::pasteText( sal_Int32 nIndex )
+ throw (lang::IndexOutOfBoundsException, uno::RuntimeException)
+{
+ CHECK_FOR_DEFUNC( XAccessibleEditableText );
+ SolarMutexGuard aGuard;
+
+ if( !IsEditableState() )
+ return sal_False;
+
+ // select and paste (through dispatch mechanism)
+ setSelection( nIndex, nIndex );
+ ExecuteAtViewShell( SID_PASTE );
+ return sal_True;
+}
+
+sal_Bool SwAccessibleParagraph::deleteText( sal_Int32 nStartIndex, sal_Int32 nEndIndex )
+ throw (lang::IndexOutOfBoundsException, uno::RuntimeException)
+{
+ return replaceText( nStartIndex, nEndIndex, ::rtl::OUString() );
+}
+
+sal_Bool SwAccessibleParagraph::insertText( const ::rtl::OUString& sText, sal_Int32 nIndex )
+ throw (lang::IndexOutOfBoundsException, uno::RuntimeException)
+{
+ return replaceText( nIndex, nIndex, sText );
+}
+
+sal_Bool SwAccessibleParagraph::replaceText(
+ sal_Int32 nStartIndex, sal_Int32 nEndIndex,
+ const ::rtl::OUString& sReplacement )
+ throw (lang::IndexOutOfBoundsException, uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+
+ CHECK_FOR_DEFUNC( XAccessibleEditableText );
+
+ const ::rtl::OUString& rText = GetString();
+
+ if( IsValidRange( nStartIndex, nEndIndex, rText.getLength() ) )
+ {
+ if( !IsEditableState() )
+ return sal_False;
+
+ SwTxtNode* pNode = const_cast<SwTxtNode*>( GetTxtNode() );
+
+ // translate positions
+ sal_uInt16 nStart, nEnd;
+ sal_Bool bSuccess = GetPortionData().GetEditableRange(
+ nStartIndex, nEndIndex, nStart, nEnd );
+
+ // edit only if the range is editable
+ if( bSuccess )
+ {
+ // create SwPosition for nStartIndex
+ SwIndex aIndex( pNode, nStart );
+ SwPosition aStartPos( *pNode, aIndex );
+
+ // create SwPosition for nEndIndex
+ SwPosition aEndPos( aStartPos );
+ aEndPos.nContent = nEnd;
+
+ // now create XTextRange as helper and set string
+ const uno::Reference<text::XTextRange> xRange(
+ SwXTextRange::CreateXTextRange(
+ *pNode->GetDoc(), aStartPos, &aEndPos));
+ xRange->setString(sReplacement);
+
+ // delete portion data
+ ClearPortionData();
+ }
+
+ return bSuccess;
+ }
+ else
+ throw lang::IndexOutOfBoundsException();
+}
+
+struct IndexCompare
+{
+ const PropertyValue* pValues;
+ IndexCompare( const PropertyValue* pVals ) : pValues(pVals) {}
+ bool operator() ( const sal_Int32& a, const sal_Int32& b ) const
+ {
+ return (pValues[a].Name < pValues[b].Name) ? true : false;
+ }
+};
+
+
+sal_Bool SwAccessibleParagraph::setAttributes(
+ sal_Int32 nStartIndex,
+ sal_Int32 nEndIndex,
+ const uno::Sequence<PropertyValue>& rAttributeSet )
+ throw (lang::IndexOutOfBoundsException, uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+ CHECK_FOR_DEFUNC( XAccessibleEditableText );
+
+ const ::rtl::OUString& rText = GetString();
+
+ if( ! IsValidRange( nStartIndex, nEndIndex, rText.getLength() ) )
+ throw lang::IndexOutOfBoundsException();
+
+ if( !IsEditableState() )
+ return sal_False;
+
+
+ // create a (dummy) text portion for the sole purpose of calling
+ // setPropertyValue on it
+ uno::Reference<XMultiPropertySet> xPortion = CreateUnoPortion( nStartIndex,
+ nEndIndex );
+
+ // build sorted index array
+ sal_Int32 nLength = rAttributeSet.getLength();
+ const PropertyValue* pPairs = rAttributeSet.getConstArray();
+ sal_Int32* pIndices = new sal_Int32[nLength];
+ sal_Int32 i;
+ for( i = 0; i < nLength; i++ )
+ pIndices[i] = i;
+ sort( &pIndices[0], &pIndices[nLength], IndexCompare(pPairs) );
+
+ // create sorted sequences accoring to index array
+ uno::Sequence< ::rtl::OUString > aNames( nLength );
+ ::rtl::OUString* pNames = aNames.getArray();
+ uno::Sequence< uno::Any > aValues( nLength );
+ uno::Any* pValues = aValues.getArray();
+ for( i = 0; i < nLength; i++ )
+ {
+ const PropertyValue& rVal = pPairs[pIndices[i]];
+ pNames[i] = rVal.Name;
+ pValues[i] = rVal.Value;
+ }
+ delete[] pIndices;
+
+ // now set the values
+ sal_Bool bRet = sal_True;
+ try
+ {
+ xPortion->setPropertyValues( aNames, aValues );
+ }
+ catch( UnknownPropertyException &e )
+ {
+ // error handling through return code!
+ bRet = sal_False;
+ }
+
+ return bRet;
+}
+
+sal_Bool SwAccessibleParagraph::setText( const ::rtl::OUString& sText )
+ throw (uno::RuntimeException)
+{
+ return replaceText(0, GetString().getLength(), sText);
+}
+
+//===== XAccessibleSelection ============================================
+
+void SwAccessibleParagraph::selectAccessibleChild(
+ sal_Int32 nChildIndex )
+ throw ( lang::IndexOutOfBoundsException,
+ uno::RuntimeException )
+{
+ CHECK_FOR_DEFUNC( XAccessibleSelection );
+
+ aSelectionHelper.selectAccessibleChild(nChildIndex);
+}
+
+sal_Bool SwAccessibleParagraph::isAccessibleChildSelected(
+ sal_Int32 nChildIndex )
+ throw ( lang::IndexOutOfBoundsException,
+ uno::RuntimeException )
+{
+ CHECK_FOR_DEFUNC( XAccessibleSelection );
+
+ return aSelectionHelper.isAccessibleChildSelected(nChildIndex);
+}
+
+void SwAccessibleParagraph::clearAccessibleSelection( )
+ throw ( uno::RuntimeException )
+{
+ CHECK_FOR_DEFUNC( XAccessibleSelection );
+
+ aSelectionHelper.clearAccessibleSelection();
+}
+
+void SwAccessibleParagraph::selectAllAccessibleChildren( )
+ throw ( uno::RuntimeException )
+{
+ CHECK_FOR_DEFUNC( XAccessibleSelection );
+
+ aSelectionHelper.selectAllAccessibleChildren();
+}
+
+sal_Int32 SwAccessibleParagraph::getSelectedAccessibleChildCount( )
+ throw ( uno::RuntimeException )
+{
+ CHECK_FOR_DEFUNC( XAccessibleSelection );
+
+ return aSelectionHelper.getSelectedAccessibleChildCount();
+}
+
+uno::Reference<XAccessible> SwAccessibleParagraph::getSelectedAccessibleChild(
+ sal_Int32 nSelectedChildIndex )
+ throw ( lang::IndexOutOfBoundsException,
+ uno::RuntimeException)
+{
+ CHECK_FOR_DEFUNC( XAccessibleSelection );
+
+ return aSelectionHelper.getSelectedAccessibleChild(nSelectedChildIndex);
+}
+
+// index has to be treated as global child index.
+void SwAccessibleParagraph::deselectAccessibleChild(
+ sal_Int32 nChildIndex )
+ throw ( lang::IndexOutOfBoundsException,
+ uno::RuntimeException )
+{
+ CHECK_FOR_DEFUNC( XAccessibleSelection );
+
+ aSelectionHelper.deselectAccessibleChild( nChildIndex );
+}
+
+//===== XAccessibleHypertext ============================================
+
+class SwHyperlinkIter_Impl
+{
+ const SwpHints *pHints;
+ xub_StrLen nStt;
+ xub_StrLen nEnd;
+ sal_uInt16 nPos;
+
+public:
+ SwHyperlinkIter_Impl( const SwTxtFrm *pTxtFrm );
+ const SwTxtAttr *next();
+ sal_uInt16 getCurrHintPos() const { return nPos-1; }
+
+ xub_StrLen startIdx() const { return nStt; }
+ xub_StrLen endIdx() const { return nEnd; }
+};
+
+SwHyperlinkIter_Impl::SwHyperlinkIter_Impl( const SwTxtFrm *pTxtFrm ) :
+ pHints( pTxtFrm->GetTxtNode()->GetpSwpHints() ),
+ nStt( pTxtFrm->GetOfst() ),
+ nPos( 0 )
+{
+ const SwTxtFrm *pFollFrm = pTxtFrm->GetFollow();
+ nEnd = pFollFrm ? pFollFrm->GetOfst() : pTxtFrm->GetTxtNode()->Len();
+}
+
+const SwTxtAttr *SwHyperlinkIter_Impl::next()
+{
+ const SwTxtAttr *pAttr = 0;
+ if( pHints )
+ {
+ while( !pAttr && nPos < pHints->Count() )
+ {
+ const SwTxtAttr *pHt = (*pHints)[nPos];
+ if( RES_TXTATR_INETFMT == pHt->Which() )
+ {
+ xub_StrLen nHtStt = *pHt->GetStart();
+ xub_StrLen nHtEnd = *pHt->GetAnyEnd();
+ if( nHtEnd > nHtStt &&
+ ( (nHtStt >= nStt && nHtStt < nEnd) ||
+ (nHtEnd > nStt && nHtEnd <= nEnd) ) )
+ {
+ pAttr = pHt;
+ }
+ }
+ ++nPos;
+ }
+ }
+
+ return pAttr;
+};
+
+sal_Int32 SAL_CALL SwAccessibleParagraph::getHyperLinkCount()
+ throw (uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+
+ CHECK_FOR_DEFUNC( XAccessibleHypertext );
+
+ sal_Int32 nCount = 0;
+ // #i77108# - provide hyperlinks also in editable documents.
+// if( !IsEditableState() )
+ // <--
+ {
+ const SwTxtFrm *pTxtFrm = static_cast<const SwTxtFrm*>( GetFrm() );
+ SwHyperlinkIter_Impl aIter( pTxtFrm );
+ while( aIter.next() )
+ nCount++;
+ }
+
+ return nCount;
+}
+
+uno::Reference< XAccessibleHyperlink > SAL_CALL
+ SwAccessibleParagraph::getHyperLink( sal_Int32 nLinkIndex )
+ throw (lang::IndexOutOfBoundsException, uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+ CHECK_FOR_DEFUNC( XAccessibleHypertext );
+
+ uno::Reference< XAccessibleHyperlink > xRet;
+
+ // #i77108#
+ {
+ const SwTxtFrm *pTxtFrm = static_cast<const SwTxtFrm*>( GetFrm() );
+ SwHyperlinkIter_Impl aHIter( pTxtFrm );
+ while( nLinkIndex-- )
+ aHIter.next();
+
+ const SwTxtAttr *pHt = aHIter.next();
+ if( pHt )
+ {
+ if( !pHyperTextData )
+ pHyperTextData = new SwAccessibleHyperTextData;
+ SwAccessibleHyperTextData::iterator aIter =
+ pHyperTextData ->find( pHt );
+ if( aIter != pHyperTextData->end() )
+ {
+ xRet = (*aIter).second;
+ }
+ if( !xRet.is() )
+ {
+ sal_Int32 nHStt= GetPortionData().GetAccessiblePosition(
+ max( aHIter.startIdx(), *pHt->GetStart() ) );
+ sal_Int32 nHEnd= GetPortionData().GetAccessiblePosition(
+ min( aHIter.endIdx(), *pHt->GetAnyEnd() ) );
+ xRet = new SwAccessibleHyperlink( aHIter.getCurrHintPos(),
+ this, nHStt, nHEnd );
+ if( aIter != pHyperTextData->end() )
+ {
+ (*aIter).second = xRet;
+ }
+ else
+ {
+ SwAccessibleHyperTextData::value_type aEntry( pHt, xRet );
+ pHyperTextData->insert( aEntry );
+ }
+ }
+ }
+ }
+
+ if( !xRet.is() )
+ throw lang::IndexOutOfBoundsException();
+
+ return xRet;
+}
+
+sal_Int32 SAL_CALL SwAccessibleParagraph::getHyperLinkIndex( sal_Int32 nCharIndex )
+ throw (lang::IndexOutOfBoundsException, uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+ CHECK_FOR_DEFUNC( XAccessibleHypertext );
+
+ // parameter checking
+ sal_Int32 nLength = GetString().getLength();
+ if ( ! IsValidPosition( nCharIndex, nLength ) )
+ {
+ throw lang::IndexOutOfBoundsException();
+ }
+
+ sal_Int32 nRet = -1;
+ // #i77108#
+ {
+ const SwTxtFrm *pTxtFrm = static_cast<const SwTxtFrm*>( GetFrm() );
+ SwHyperlinkIter_Impl aHIter( pTxtFrm );
+
+ xub_StrLen nIdx = GetPortionData().GetModelPosition( nCharIndex );
+ sal_Int32 nPos = 0;
+ const SwTxtAttr *pHt = aHIter.next();
+ while( pHt && !(nIdx >= *pHt->GetStart() && nIdx < *pHt->GetAnyEnd()) )
+ {
+ pHt = aHIter.next();
+ nPos++;
+ }
+
+ if( pHt )
+ nRet = nPos;
+
+ }
+
+ return nRet;
+}
+
+// #i71360#, #i108125# - adjustments for change tracking text markup
+sal_Int32 SAL_CALL SwAccessibleParagraph::getTextMarkupCount( sal_Int32 nTextMarkupType )
+ throw (lang::IllegalArgumentException,
+ uno::RuntimeException)
+{
+ std::auto_ptr<SwTextMarkupHelper> pTextMarkupHelper;
+ switch ( nTextMarkupType )
+ {
+ case text::TextMarkupType::TRACK_CHANGE_INSERTION:
+ case text::TextMarkupType::TRACK_CHANGE_DELETION:
+ case text::TextMarkupType::TRACK_CHANGE_FORMATCHANGE:
+ {
+ pTextMarkupHelper.reset( new SwTextMarkupHelper(
+ GetPortionData(),
+ *(mpParaChangeTrackInfo->getChangeTrackingTextMarkupList( nTextMarkupType ) )) );
+ }
+ break;
+ default:
+ {
+ pTextMarkupHelper.reset( new SwTextMarkupHelper( GetPortionData(), *GetTxtNode() ) );
+ }
+ }
+
+ return pTextMarkupHelper->getTextMarkupCount( nTextMarkupType );
+}
+
+/*accessibility::*/TextSegment SAL_CALL
+ SwAccessibleParagraph::getTextMarkup( sal_Int32 nTextMarkupIndex,
+ sal_Int32 nTextMarkupType )
+ throw (lang::IndexOutOfBoundsException,
+ lang::IllegalArgumentException,
+ uno::RuntimeException)
+{
+ std::auto_ptr<SwTextMarkupHelper> pTextMarkupHelper;
+ switch ( nTextMarkupType )
+ {
+ case text::TextMarkupType::TRACK_CHANGE_INSERTION:
+ case text::TextMarkupType::TRACK_CHANGE_DELETION:
+ case text::TextMarkupType::TRACK_CHANGE_FORMATCHANGE:
+ {
+ pTextMarkupHelper.reset( new SwTextMarkupHelper(
+ GetPortionData(),
+ *(mpParaChangeTrackInfo->getChangeTrackingTextMarkupList( nTextMarkupType ) )) );
+ }
+ break;
+ default:
+ {
+ pTextMarkupHelper.reset( new SwTextMarkupHelper( GetPortionData(), *GetTxtNode() ) );
+ }
+ }
+
+ return pTextMarkupHelper->getTextMarkup( nTextMarkupIndex, nTextMarkupType );
+}
+
+uno::Sequence< /*accessibility::*/TextSegment > SAL_CALL
+ SwAccessibleParagraph::getTextMarkupAtIndex( sal_Int32 nCharIndex,
+ sal_Int32 nTextMarkupType )
+ throw (lang::IndexOutOfBoundsException,
+ lang::IllegalArgumentException,
+ uno::RuntimeException)
+{
+ // parameter checking
+ const sal_Int32 nLength = GetString().getLength();
+ if ( ! IsValidPosition( nCharIndex, nLength ) )
+ {
+ throw lang::IndexOutOfBoundsException();
+ }
+
+ std::auto_ptr<SwTextMarkupHelper> pTextMarkupHelper;
+ switch ( nTextMarkupType )
+ {
+ case text::TextMarkupType::TRACK_CHANGE_INSERTION:
+ case text::TextMarkupType::TRACK_CHANGE_DELETION:
+ case text::TextMarkupType::TRACK_CHANGE_FORMATCHANGE:
+ {
+ pTextMarkupHelper.reset( new SwTextMarkupHelper(
+ GetPortionData(),
+ *(mpParaChangeTrackInfo->getChangeTrackingTextMarkupList( nTextMarkupType ) )) );
+ }
+ break;
+ default:
+ {
+ pTextMarkupHelper.reset( new SwTextMarkupHelper( GetPortionData(), *GetTxtNode() ) );
+ }
+ }
+
+ return pTextMarkupHelper->getTextMarkupAtIndex( nCharIndex, nTextMarkupType );
+}
+// <--
+
+// #i89175#
+sal_Int32 SAL_CALL SwAccessibleParagraph::getLineNumberAtIndex( sal_Int32 nIndex )
+ throw (lang::IndexOutOfBoundsException,
+ uno::RuntimeException)
+{
+ // parameter checking
+ const sal_Int32 nLength = GetString().getLength();
+ if ( ! IsValidPosition( nIndex, nLength ) )
+ {
+ throw lang::IndexOutOfBoundsException();
+ }
+
+ const sal_Int32 nLineNo = GetPortionData().GetLineNo( nIndex );
+ return nLineNo;
+}
+
+/*accessibility::*/TextSegment SAL_CALL
+ SwAccessibleParagraph::getTextAtLineNumber( sal_Int32 nLineNo )
+ throw (lang::IndexOutOfBoundsException,
+ uno::RuntimeException)
+{
+ // parameter checking
+ if ( nLineNo < 0 ||
+ nLineNo >= GetPortionData().GetLineCount() )
+ {
+ throw lang::IndexOutOfBoundsException();
+ }
+
+ i18n::Boundary aLineBound;
+ GetPortionData().GetBoundaryOfLine( nLineNo, aLineBound );
+
+ /*accessibility::*/TextSegment aTextAtLine;
+ const ::rtl::OUString rText = GetString();
+ aTextAtLine.SegmentText = rText.copy( aLineBound.startPos,
+ aLineBound.endPos - aLineBound.startPos );
+ aTextAtLine.SegmentStart = aLineBound.startPos;
+ aTextAtLine.SegmentEnd = aLineBound.endPos;
+
+ return aTextAtLine;
+}
+
+/*accessibility::*/TextSegment SAL_CALL SwAccessibleParagraph::getTextAtLineWithCaret()
+ throw (uno::RuntimeException)
+{
+ const sal_Int32 nLineNoOfCaret = getNumberOfLineWithCaret();
+
+ if ( nLineNoOfCaret >= 0 &&
+ nLineNoOfCaret < GetPortionData().GetLineCount() )
+ {
+ return getTextAtLineNumber( nLineNoOfCaret );
+ }
+
+ return /*accessibility::*/TextSegment();
+}
+
+sal_Int32 SAL_CALL SwAccessibleParagraph::getNumberOfLineWithCaret()
+ throw (uno::RuntimeException)
+{
+ const sal_Int32 nCaretPos = getCaretPosition();
+ const sal_Int32 nLength = GetString().getLength();
+ if ( !IsValidPosition( nCaretPos, nLength ) )
+ {
+ return -1;
+ }
+
+ sal_Int32 nLineNo = GetPortionData().GetLineNo( nCaretPos );
+
+ // special handling for cursor positioned at end of text line via End key
+ if ( nCaretPos != 0 )
+ {
+ i18n::Boundary aLineBound;
+ GetPortionData().GetBoundaryOfLine( nLineNo, aLineBound );
+ if ( nCaretPos == aLineBound.startPos )
+ {
+ SwCrsrShell* pCrsrShell = SwAccessibleParagraph::GetCrsrShell();
+ if ( pCrsrShell != 0 )
+ {
+ const awt::Rectangle aCharRect = getCharacterBounds( nCaretPos );
+
+ const SwRect& aCursorCoreRect = pCrsrShell->GetCharRect();
+ // translate core coordinates into accessibility coordinates
+ Window *pWin = GetWindow();
+ CHECK_FOR_WINDOW( XAccessibleComponent, pWin );
+
+ Rectangle aScreenRect( GetMap()->CoreToPixel( aCursorCoreRect.SVRect() ));
+
+ SwRect aFrmLogBounds( GetBounds( *(GetMap()) ) ); // twip rel to doc root
+ Point aFrmPixPos( GetMap()->CoreToPixel( aFrmLogBounds.SVRect() ).TopLeft() );
+ aScreenRect.Move( -aFrmPixPos.X(), -aFrmPixPos.Y() );
+
+ // convert into AWT Rectangle
+ const awt::Rectangle aCursorRect( aScreenRect.Left(),
+ aScreenRect.Top(),
+ aScreenRect.GetWidth(),
+ aScreenRect.GetHeight() );
+
+ if ( aCharRect.X != aCursorRect.X ||
+ aCharRect.Y != aCursorRect.Y )
+ {
+ --nLineNo;
+ }
+ }
+ }
+ }
+
+ return nLineNo;
+}
+
+// #i108125#
+void SwAccessibleParagraph::Modify( const SfxPoolItem* pOld, const SfxPoolItem* pNew )
+{
+ mpParaChangeTrackInfo->reset();
+
+ CheckRegistration( pOld, pNew );
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/access/accpara.hxx b/sw/source/core/access/accpara.hxx
new file mode 100644
index 000000000000..d3092e2326f3
--- /dev/null
+++ b/sw/source/core/access/accpara.hxx
@@ -0,0 +1,435 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+#ifndef _ACCPARA_HXX
+#define _ACCPARA_HXX
+
+#include <acccontext.hxx>
+#include <com/sun/star/accessibility/XAccessibleEditableText.hpp>
+#include <com/sun/star/accessibility/XAccessibleSelection.hpp>
+#include <com/sun/star/accessibility/XAccessibleHypertext.hpp>
+#include <com/sun/star/accessibility/XAccessibleTextMarkup.hpp>
+#include <com/sun/star/accessibility/XAccessibleMultiLineText.hpp>
+#include <com/sun/star/accessibility/XAccessibleTextAttributes.hpp>
+#include <boost/unordered_map.hpp>
+#include <accselectionhelper.hxx>
+#include <calbck.hxx> // #i108125#
+
+class SwTxtFrm;
+class SwTxtNode;
+class SwPaM;
+class SwAccessiblePortionData;
+class SwAccessibleHyperTextData;
+class SwXTextPortion;
+class SwParaChangeTrackingInfo; //#i108125#
+
+namespace rtl { class OUString; }
+namespace com { namespace sun { namespace star {
+ namespace i18n { struct Boundary; }
+ namespace accessibility { class XAccessibleHyperlink; }
+} } }
+
+typedef ::boost::unordered_map< ::rtl::OUString,
+ ::com::sun::star::beans::PropertyValue,
+ ::rtl::OUStringHash,
+ ::std::equal_to< ::rtl::OUString > > tAccParaPropValMap;
+
+class SwAccessibleParagraph :
+ public SwClient, // #i108125#
+ public SwAccessibleContext,
+ public ::com::sun::star::accessibility::XAccessibleEditableText,
+ public com::sun::star::accessibility::XAccessibleSelection,
+ public com::sun::star::accessibility::XAccessibleHypertext,
+ public com::sun::star::accessibility::XAccessibleTextMarkup,
+ public com::sun::star::accessibility::XAccessibleMultiLineText,
+ public ::com::sun::star::accessibility::XAccessibleTextAttributes
+{
+ friend class SwAccessibleHyperlink;
+
+ ::rtl::OUString sDesc; // protected by base classes mutex
+
+ /// data for this paragraph's text portions; this contains the
+ /// mapping from the core 'model string' to the accessible text
+ /// string.
+ /// pPortionData may be NULL; it should only be accessed through the
+ /// Get/Clear/Has/UpdatePortionData() methods
+ SwAccessiblePortionData* pPortionData;
+ SwAccessibleHyperTextData *pHyperTextData;
+
+ sal_Int32 nOldCaretPos; // The 'old' caret pos. It's only valid as long
+ // as the cursor is inside this object (protected by
+ // mutex)
+
+ sal_Bool bIsHeading; // protected by base classes mutex
+
+ // implementation for XAccessibleSelection
+ SwAccessibleSelectionHelper aSelectionHelper;
+
+ SwParaChangeTrackingInfo* mpParaChangeTrackInfo; // #i108125#
+
+ /// get the SwTxtNode (requires frame; check before)
+ const SwTxtNode* GetTxtNode() const;
+
+ /// get the (accessible) text string (requires frame; check before)
+ ::rtl::OUString GetString();
+
+ ::rtl::OUString GetDescription();
+
+ // get the current care position
+ sal_Int32 GetCaretPos();
+
+ /// determine the current selection. Fill the values with
+ /// -1 if there is no selection in the this paragraph
+ sal_Bool GetSelection(sal_Int32& nStart, sal_Int32& nEnd);
+
+ // helper for GetSelection and getCaretPosition
+ // #i27301# - add parameter <_bForSelection>, which indicates,
+ // if the cursor is retrieved for selection or for caret position.
+ SwPaM* GetCursor( const bool _bForSelection );
+
+ /// for cut/copy/paste: execute a particular slot at the view shell
+ void ExecuteAtViewShell( sal_uInt16 nSlot );
+
+ /// helper method for get/setAttributes
+ /// (for the special case of (nEndIndex==-1) a single character will
+ /// be selected)
+ SwXTextPortion* CreateUnoPortion( sal_Int32 nStart, sal_Int32 nEnd );
+
+
+ // methods for checking the parameter range:
+
+ /// does nPos point to a char?
+ sal_Bool IsValidChar(sal_Int32 nPos, sal_Int32 nLength);
+
+ /// does nPos point to a position? (may be behind the last character)
+ sal_Bool IsValidPosition(sal_Int32 nPos, sal_Int32 nLength);
+
+ /// is nBegin...nEnd a valid range? (nEnd points past the last character)
+ sal_Bool IsValidRange(sal_Int32 nBegin, sal_Int32 nEnd, sal_Int32 nLength);
+
+ /// Ensure ordered range (i.e. nBegin is smaller then nEnd)
+ inline void OrderRange(sal_Int32& nBegin, sal_Int32& nEnd)
+ {
+ if( nBegin > nEnd )
+ {
+ sal_Int32 nTmp = nBegin; nBegin = nEnd; nEnd = nTmp;
+ }
+ }
+
+ // #i63870#
+ void _getDefaultAttributesImpl(
+ const ::com::sun::star::uno::Sequence< ::rtl::OUString >& aRequestedAttributes,
+ tAccParaPropValMap& rDefAttrSeq,
+ const bool bOnlyCharAttrs = false );
+ void _getRunAttributesImpl(
+ const sal_Int32 nIndex,
+ const ::com::sun::star::uno::Sequence< ::rtl::OUString >& aRequestedAttributes,
+ tAccParaPropValMap& rRunAttrSeq );
+ // <--
+
+public:
+
+ sal_Bool IsHeading() const;
+
+protected:
+
+ // Set states for getAccessibleStateSet.
+ // This drived class additinaly sets MULTILINE(1), MULTISELECTABLE(+),
+ // FOCUSABLE(+) and FOCUSED(+)
+ virtual void GetStates( ::utl::AccessibleStateSetHelper& rStateSet );
+
+ virtual void _InvalidateContent( sal_Bool bVisibleDataFired );
+
+ virtual void _InvalidateCursorPos();
+ virtual void _InvalidateFocus();
+
+ virtual ~SwAccessibleParagraph();
+
+ //===== handling of data for the text portions ===========================
+
+ /// force update of new portion data
+ void UpdatePortionData()
+ throw( com::sun::star::uno::RuntimeException );
+
+ /// remove the current portion data
+ void ClearPortionData();
+
+ /// get portion data; update if necesary
+ SwAccessiblePortionData& GetPortionData()
+ throw( com::sun::star::uno::RuntimeException )
+ {
+ if( pPortionData == NULL )
+ UpdatePortionData();
+ return *pPortionData;
+ }
+
+ /// determine if portion data is currently available
+ sal_Bool HasPortionData() { return (pPortionData != NULL); }
+
+
+ //===== helpers for word boundaries ====================================
+
+ sal_Bool GetCharBoundary( com::sun::star::i18n::Boundary& rBound,
+ const rtl::OUString& rText,
+ sal_Int32 nPos );
+ sal_Bool GetWordBoundary( com::sun::star::i18n::Boundary& rBound,
+ const rtl::OUString& rText,
+ sal_Int32 nPos );
+ sal_Bool GetSentenceBoundary( com::sun::star::i18n::Boundary& rBound,
+ const rtl::OUString& rText,
+ sal_Int32 nPos );
+ sal_Bool GetLineBoundary( com::sun::star::i18n::Boundary& rBound,
+ const rtl::OUString& rText,
+ sal_Int32 nPos );
+ sal_Bool GetParagraphBoundary( com::sun::star::i18n::Boundary& rBound,
+ const rtl::OUString& rText,
+ sal_Int32 nPos );
+ sal_Bool GetAttributeBoundary( com::sun::star::i18n::Boundary& rBound,
+ const rtl::OUString& rText,
+ sal_Int32 nPos );
+ sal_Bool GetGlyphBoundary( com::sun::star::i18n::Boundary& rBound,
+ const rtl::OUString& rText,
+ sal_Int32 nPos );
+
+ /// get boundaries of word/sentence/etc. for specified text type
+ /// Does all argument checking, and then delegates to helper methods above.
+ sal_Bool GetTextBoundary( com::sun::star::i18n::Boundary& rBound,
+ const rtl::OUString& rText,
+ sal_Int32 nPos,
+ sal_Int16 aTextType )
+ throw (
+ ::com::sun::star::lang::IndexOutOfBoundsException,
+ ::com::sun::star::lang::IllegalArgumentException,
+ ::com::sun::star::uno::RuntimeException);
+
+ virtual void Modify( const SfxPoolItem* pOld, const SfxPoolItem* pNew);
+
+public:
+
+ SwAccessibleParagraph( SwAccessibleMap& rInitMap,
+ const SwTxtFrm& rTxtFrm );
+
+ inline operator ::com::sun::star::accessibility::XAccessibleText *();
+
+ virtual sal_Bool HasCursor(); // required by map to remember that object
+
+ //===== XAccessibleContext ==============================================
+
+ /// Return this object's description.
+ virtual ::rtl::OUString SAL_CALL
+ getAccessibleDescription (void)
+ throw (com::sun::star::uno::RuntimeException);
+
+ /** Return the parents locale or throw exception if this object has no
+ parent yet/anymore.
+ */
+ virtual ::com::sun::star::lang::Locale SAL_CALL
+ getLocale (void)
+ throw (::com::sun::star::accessibility::IllegalAccessibleComponentStateException, ::com::sun::star::uno::RuntimeException);
+
+ /** #i27138# - paragraphs are in relation CONTENT_FLOWS_FROM and/or CONTENT_FLOWS_TO */
+ virtual ::com::sun::star::uno::Reference<
+ ::com::sun::star::accessibility::XAccessibleRelationSet> SAL_CALL
+ getAccessibleRelationSet (void)
+ throw (::com::sun::star::uno::RuntimeException);
+
+ //===== XAccessibleComponent ============================================
+
+ virtual void SAL_CALL grabFocus()
+ throw (::com::sun::star::uno::RuntimeException);
+ // #i71385#
+ virtual sal_Int32 SAL_CALL getForeground()
+ throw (::com::sun::star::uno::RuntimeException);
+ virtual sal_Int32 SAL_CALL getBackground()
+ throw (::com::sun::star::uno::RuntimeException);
+ // <--
+
+ //===== XServiceInfo ====================================================
+
+ /** Returns an identifier for the implementation of this object.
+ */
+ virtual ::rtl::OUString SAL_CALL
+ getImplementationName (void)
+ throw (::com::sun::star::uno::RuntimeException);
+
+ /** Return whether the specified service is supported by this class.
+ */
+ virtual sal_Bool SAL_CALL
+ supportsService (const ::rtl::OUString& sServiceName)
+ throw (::com::sun::star::uno::RuntimeException);
+
+ /** Returns a list of all supported services. In this case that is just
+ the AccessibleContext service.
+ */
+ virtual ::com::sun::star::uno::Sequence< ::rtl::OUString> SAL_CALL
+ getSupportedServiceNames (void)
+ throw (::com::sun::star::uno::RuntimeException);
+
+
+ //===== XInterface ======================================================
+
+ // (XInterface methods need to be implemented to disambiguate
+ // between those inherited through SwAcessibleContext and
+ // XAccessibleEditableText).
+
+ virtual ::com::sun::star::uno::Any SAL_CALL queryInterface(
+ const ::com::sun::star::uno::Type& aType )
+ throw (::com::sun::star::uno::RuntimeException);
+
+ virtual void SAL_CALL acquire( ) throw ()
+ { SwAccessibleContext::acquire(); };
+
+ virtual void SAL_CALL release( ) throw ()
+ { SwAccessibleContext::release(); };
+
+ //====== XTypeProvider ====================================================
+ virtual ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Type > SAL_CALL getTypes( ) throw(::com::sun::star::uno::RuntimeException);
+ virtual ::com::sun::star::uno::Sequence< sal_Int8 > SAL_CALL getImplementationId( ) throw(::com::sun::star::uno::RuntimeException);
+
+ //===== XAccesibleText ==================================================
+ virtual sal_Int32 SAL_CALL getCaretPosition( ) throw (::com::sun::star::uno::RuntimeException);
+ virtual sal_Bool SAL_CALL setCaretPosition( sal_Int32 nIndex ) throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::uno::RuntimeException);
+ virtual sal_Unicode SAL_CALL getCharacter( sal_Int32 nIndex ) throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::uno::RuntimeException);
+ virtual ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue > SAL_CALL getCharacterAttributes( sal_Int32 nIndex, const ::com::sun::star::uno::Sequence< ::rtl::OUString >& aRequestedAttributes ) throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::uno::RuntimeException);
+ virtual ::com::sun::star::awt::Rectangle SAL_CALL getCharacterBounds( sal_Int32 nIndex ) throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::uno::RuntimeException);
+ virtual sal_Int32 SAL_CALL getCharacterCount( ) throw (::com::sun::star::uno::RuntimeException);
+ virtual sal_Int32 SAL_CALL getIndexAtPoint( const ::com::sun::star::awt::Point& aPoint ) throw (::com::sun::star::uno::RuntimeException);
+ virtual ::rtl::OUString SAL_CALL getSelectedText( ) throw (::com::sun::star::uno::RuntimeException);
+ virtual sal_Int32 SAL_CALL getSelectionStart( ) throw (::com::sun::star::uno::RuntimeException);
+ virtual sal_Int32 SAL_CALL getSelectionEnd( ) throw (::com::sun::star::uno::RuntimeException);
+ virtual sal_Bool SAL_CALL setSelection( sal_Int32 nStartIndex, sal_Int32 nEndIndex ) throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::uno::RuntimeException);
+ virtual ::rtl::OUString SAL_CALL getText( ) throw (::com::sun::star::uno::RuntimeException);
+ virtual ::rtl::OUString SAL_CALL getTextRange( sal_Int32 nStartIndex, sal_Int32 nEndIndex ) throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::uno::RuntimeException);
+ virtual ::com::sun::star::accessibility::TextSegment SAL_CALL getTextAtIndex( sal_Int32 nIndex, sal_Int16 aTextType ) throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException);
+ virtual ::com::sun::star::accessibility::TextSegment SAL_CALL getTextBeforeIndex( sal_Int32 nIndex, sal_Int16 aTextType ) throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException);
+ virtual ::com::sun::star::accessibility::TextSegment SAL_CALL getTextBehindIndex( sal_Int32 nIndex, sal_Int16 aTextType ) throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException);
+ virtual sal_Bool SAL_CALL copyText( sal_Int32 nStartIndex, sal_Int32 nEndIndex ) throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::uno::RuntimeException);
+
+ //===== XAccesibleEditableText ==========================================
+ virtual sal_Bool SAL_CALL cutText( sal_Int32 nStartIndex, sal_Int32 nEndIndex ) throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::uno::RuntimeException);
+ virtual sal_Bool SAL_CALL pasteText( sal_Int32 nIndex ) throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::uno::RuntimeException);
+ virtual sal_Bool SAL_CALL deleteText( sal_Int32 nStartIndex, sal_Int32 nEndIndex ) throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::uno::RuntimeException);
+ virtual sal_Bool SAL_CALL insertText( const ::rtl::OUString& sText, sal_Int32 nIndex ) throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::uno::RuntimeException);
+ virtual sal_Bool SAL_CALL replaceText( sal_Int32 nStartIndex, sal_Int32 nEndIndex, const ::rtl::OUString& sReplacement ) throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::uno::RuntimeException);
+ virtual sal_Bool SAL_CALL setAttributes( sal_Int32 nStartIndex, sal_Int32 nEndIndex, const ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue >& aAttributeSet ) throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::uno::RuntimeException);
+ virtual sal_Bool SAL_CALL setText( const ::rtl::OUString& sText ) throw (::com::sun::star::uno::RuntimeException);
+
+ //===== XAccessibleSelection ============================================
+ virtual void SAL_CALL selectAccessibleChild(
+ sal_Int32 nChildIndex )
+ throw ( ::com::sun::star::lang::IndexOutOfBoundsException,
+ ::com::sun::star::uno::RuntimeException );
+
+ virtual sal_Bool SAL_CALL isAccessibleChildSelected(
+ sal_Int32 nChildIndex )
+ throw ( ::com::sun::star::lang::IndexOutOfBoundsException,
+ ::com::sun::star::uno::RuntimeException );
+ virtual void SAL_CALL clearAccessibleSelection( )
+ throw ( ::com::sun::star::uno::RuntimeException );
+ virtual void SAL_CALL selectAllAccessibleChildren( )
+ throw ( ::com::sun::star::uno::RuntimeException );
+ virtual sal_Int32 SAL_CALL getSelectedAccessibleChildCount( )
+ throw ( ::com::sun::star::uno::RuntimeException );
+ virtual ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible > SAL_CALL getSelectedAccessibleChild(
+ sal_Int32 nSelectedChildIndex )
+ throw ( ::com::sun::star::lang::IndexOutOfBoundsException,
+ ::com::sun::star::uno::RuntimeException);
+
+ // index has to be treated as global child index.
+ virtual void SAL_CALL deselectAccessibleChild(
+ sal_Int32 nChildIndex )
+ throw ( ::com::sun::star::lang::IndexOutOfBoundsException,
+ ::com::sun::star::uno::RuntimeException );
+
+ //===== XAccessibleHypertext ============================================
+ virtual sal_Int32 SAL_CALL getHyperLinkCount()
+ throw (::com::sun::star::uno::RuntimeException);
+ virtual ::com::sun::star::uno::Reference<
+ ::com::sun::star::accessibility::XAccessibleHyperlink >
+ SAL_CALL getHyperLink( sal_Int32 nLinkIndex )
+ throw (::com::sun::star::lang::IndexOutOfBoundsException,
+ ::com::sun::star::uno::RuntimeException);
+ virtual sal_Int32 SAL_CALL getHyperLinkIndex( sal_Int32 nCharIndex )
+ throw (::com::sun::star::lang::IndexOutOfBoundsException,
+ ::com::sun::star::uno::RuntimeException);
+
+ // #i71360#
+ //===== XAccesibleTextMarkup ============================================
+ virtual sal_Int32 SAL_CALL getTextMarkupCount( sal_Int32 nTextMarkupType )
+ throw (::com::sun::star::lang::IllegalArgumentException,
+ ::com::sun::star::uno::RuntimeException);
+
+ virtual ::com::sun::star::accessibility::TextSegment SAL_CALL
+ getTextMarkup( sal_Int32 nTextMarkupIndex,
+ sal_Int32 nTextMarkupType )
+ throw (::com::sun::star::lang::IndexOutOfBoundsException,
+ ::com::sun::star::lang::IllegalArgumentException,
+ ::com::sun::star::uno::RuntimeException);
+
+ virtual ::com::sun::star::uno::Sequence< ::com::sun::star::accessibility::TextSegment > SAL_CALL
+ getTextMarkupAtIndex( sal_Int32 nCharIndex,
+ sal_Int32 nTextMarkupType )
+ throw (::com::sun::star::lang::IndexOutOfBoundsException,
+ ::com::sun::star::lang::IllegalArgumentException,
+ ::com::sun::star::uno::RuntimeException);
+ // <--
+
+ // #i89175#
+ //===== XAccessibleMultiLineText ========================================
+ virtual sal_Int32 SAL_CALL getLineNumberAtIndex( sal_Int32 nIndex )
+ throw (::com::sun::star::lang::IndexOutOfBoundsException,
+ ::com::sun::star::uno::RuntimeException);
+
+ virtual ::com::sun::star::accessibility::TextSegment SAL_CALL
+ getTextAtLineNumber( sal_Int32 nLineNo )
+ throw (::com::sun::star::lang::IndexOutOfBoundsException,
+ ::com::sun::star::uno::RuntimeException);
+
+ virtual ::com::sun::star::accessibility::TextSegment SAL_CALL
+ getTextAtLineWithCaret()
+ throw (::com::sun::star::uno::RuntimeException);
+
+ virtual sal_Int32 SAL_CALL getNumberOfLineWithCaret()
+ throw (::com::sun::star::uno::RuntimeException);
+ // <--
+
+ // #i63870#
+ //===== XAccesibleTextAttributes ========================================
+ virtual ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue > SAL_CALL getDefaultAttributes( const ::com::sun::star::uno::Sequence< ::rtl::OUString >& aRequestedAttributes ) throw (::com::sun::star::uno::RuntimeException);
+ virtual ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue > SAL_CALL getRunAttributes( sal_Int32 nIndex, const ::com::sun::star::uno::Sequence< ::rtl::OUString >& aRequestedAttributes ) throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::uno::RuntimeException);
+ // <--
+};
+
+inline SwAccessibleParagraph::operator ::com::sun::star::accessibility::XAccessibleText *()
+{
+ return static_cast<
+ ::com::sun::star::accessibility::XAccessibleEditableText * >( this );
+}
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/access/accportions.cxx b/sw/source/core/access/accportions.cxx
new file mode 100644
index 000000000000..0142391027b8
--- /dev/null
+++ b/sw/source/core/access/accportions.cxx
@@ -0,0 +1,750 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+#include "accportions.hxx"
+#include <tools/debug.hxx>
+#include <rtl/ustring.hxx>
+#include <com/sun/star/i18n/Boundary.hpp>
+#include <txttypes.hxx>
+
+// for portion replacement in Special()
+#include "access.hrc"
+#include <tools/resid.hxx>
+#include "viewopt.hxx"
+
+// for GetWordBoundary(...), GetSentenceBoundary(...):
+#include <breakit.hxx>
+#include <com/sun/star/i18n/WordType.hpp>
+#include <com/sun/star/i18n/XBreakIterator.hpp>
+#include <ndtxt.hxx>
+
+// for FillSpecialPos(...)
+#include "crstate.hxx"
+
+// for SwAccessibleContext::GetResource()
+#include "acccontext.hxx"
+
+// for Post-It replacement text:
+#include "txatbase.hxx"
+#include "fmtfld.hxx"
+#include "fldbas.hxx"
+#include "docufld.hxx"
+
+// for in-line graphics replacement:
+#include "ndindex.hxx"
+#include "ndnotxt.hxx"
+#include "fmtflcnt.hxx"
+#include "frmfmt.hxx"
+#include "fmtcntnt.hxx"
+
+
+using namespace ::com::sun::star;
+
+using rtl::OUString;
+using rtl::OUStringBuffer;
+using i18n::Boundary;
+
+
+// 'portion type' for terminating portions
+#define POR_TERMINATE 0
+
+
+// portion attributes
+#define PORATTR_SPECIAL 1
+#define PORATTR_READONLY 2
+#define PORATTR_GRAY 4
+#define PORATTR_TERM 128
+
+SwAccessiblePortionData::SwAccessiblePortionData(
+ const SwTxtNode* pTxtNd,
+ const SwViewOption* pViewOpt ) :
+ SwPortionHandler(),
+ pTxtNode( pTxtNd ),
+ aBuffer(),
+ nModelPosition( 0 ),
+ bFinished( sal_False ),
+ pViewOptions( pViewOpt ),
+ sAccessibleString(),
+ aLineBreaks(),
+ aModelPositions(),
+ aAccessiblePositions(),
+ pSentences( 0 ),
+ nBeforePortions( 0 ),
+ bLastIsSpecial( sal_False )
+{
+ DBG_ASSERT( pTxtNode != NULL, "Text node is needed!" );
+
+ // reserve some space to reduce memory allocations
+ aLineBreaks.reserve( 5 );
+ aModelPositions.reserve( 10 );
+ aAccessiblePositions.reserve( 10 );
+
+ // always include 'first' line-break position
+ aLineBreaks.push_back( 0 );
+}
+
+SwAccessiblePortionData::~SwAccessiblePortionData()
+{
+ delete pSentences;
+}
+
+void SwAccessiblePortionData::Text(sal_uInt16 nLength, sal_uInt16 nType)
+{
+ DBG_ASSERT( (nModelPosition + nLength) <= pTxtNode->GetTxt().Len(),
+ "portion exceeds model string!" );
+
+ DBG_ASSERT( !bFinished, "We are already done!" );
+
+ // ignore zero-length portions
+ if( nLength == 0 )
+ return;
+
+ // store 'old' positions
+ aModelPositions.push_back( nModelPosition );
+ aAccessiblePositions.push_back( aBuffer.getLength() );
+
+ // store portion attributes
+ sal_uInt8 nAttr = IsGrayPortionType(nType) ? PORATTR_GRAY : 0;
+ aPortionAttrs.push_back( nAttr );
+
+ // update buffer + nModelPosition
+ aBuffer.append( OUString(
+ pTxtNode->GetTxt().Copy(
+ static_cast<sal_uInt16>( nModelPosition ),
+ nLength ) ) );
+ nModelPosition += nLength;
+
+ bLastIsSpecial = sal_False;
+}
+
+void SwAccessiblePortionData::Special(
+ sal_uInt16 nLength, const String& rText, sal_uInt16 nType)
+{
+ DBG_ASSERT( nModelPosition >= 0, "illegal position" );
+ DBG_ASSERT( (nModelPosition + nLength) <= pTxtNode->GetTxt().Len(),
+ "portion exceeds model string!" );
+
+ DBG_ASSERT( !bFinished, "We are already done!" );
+
+ // construct string with representation; either directly from
+ // rText, or use resources for special case portions
+ String sDisplay;
+ switch( nType )
+ {
+ case POR_POSTITS:
+ case POR_FLYCNT:
+ case POR_GRFNUM:
+ sDisplay = String(sal_Unicode(0xfffc));
+
+ break;
+ case POR_NUMBER:
+ {
+ OUStringBuffer aTmpBuffer( rText.Len() + 1 );
+ aTmpBuffer.append( rText );
+ aTmpBuffer.append( sal_Unicode(' ') );
+ sDisplay = aTmpBuffer.makeStringAndClear();
+ break;
+ }
+ // #i111768# - apply patch from kstribley:
+ // Include the control characters.
+ case POR_CONTROLCHAR:
+ {
+ OUStringBuffer aTmpBuffer( rText.Len() + 1 );
+ aTmpBuffer.append( rText );
+ aTmpBuffer.append( pTxtNode->GetTxt().GetChar(nModelPosition) );
+ sDisplay = aTmpBuffer.makeStringAndClear();
+ break;
+ }
+ // <--
+ default:
+ sDisplay = rText;
+ break;
+ }
+
+ // ignore zero/zero portions (except for terminators)
+ if( (nLength == 0) && (sDisplay.Len() == 0) && (nType != POR_TERMINATE) )
+ return;
+
+ // special treatment for zero length portion at the beginning:
+ // count as 'before' portion
+ if( ( nLength == 0 ) && ( nModelPosition == 0 ) )
+ nBeforePortions++;
+
+ // store the 'old' positions
+ aModelPositions.push_back( nModelPosition );
+ aAccessiblePositions.push_back( aBuffer.getLength() );
+
+ // store portion attributes
+ sal_uInt8 nAttr = PORATTR_SPECIAL;
+ if( IsGrayPortionType(nType) ) nAttr |= PORATTR_GRAY;
+ if( nLength == 0 ) nAttr |= PORATTR_READONLY;
+ if( nType == POR_TERMINATE ) nAttr |= PORATTR_TERM;
+ aPortionAttrs.push_back( nAttr );
+
+ // update buffer + nModelPosition
+ aBuffer.append( OUString(sDisplay) );
+ nModelPosition += nLength;
+
+ // remember 'last' special portion (unless it's our own 'closing'
+ // portions from 'Finish()'
+ if( nType != POR_TERMINATE )
+ bLastIsSpecial = sal_True;
+}
+
+void SwAccessiblePortionData::LineBreak()
+{
+ DBG_ASSERT( !bFinished, "We are already done!" );
+
+ aLineBreaks.push_back( aBuffer.getLength() );
+}
+
+void SwAccessiblePortionData::Skip(sal_uInt16 nLength)
+{
+ DBG_ASSERT( !bFinished, "We are already done!" );
+ DBG_ASSERT( aModelPositions.size() == 0, "Never Skip() after portions" );
+ DBG_ASSERT( nLength <= pTxtNode->GetTxt().Len(), "skip exceeds model string!" );
+
+ nModelPosition += nLength;
+}
+
+void SwAccessiblePortionData::Finish()
+{
+ DBG_ASSERT( !bFinished, "We are already done!" );
+
+ // include terminator values: always include two 'last character'
+ // markers in the position arrays to make sure we always find one
+ // position before the end
+ Special( 0, String(), POR_TERMINATE );
+ Special( 0, String(), POR_TERMINATE );
+ LineBreak();
+ LineBreak();
+
+ sAccessibleString = aBuffer.makeStringAndClear();
+ bFinished = sal_True;
+}
+
+
+sal_Bool SwAccessiblePortionData::IsPortionAttrSet(
+ size_t nPortionNo, sal_uInt8 nAttr ) const
+{
+ DBG_ASSERT( nPortionNo < aPortionAttrs.size(),
+ "Illegal portion number" );
+ return (aPortionAttrs[nPortionNo] & nAttr) != 0;
+}
+
+sal_Bool SwAccessiblePortionData::IsSpecialPortion( size_t nPortionNo ) const
+{
+ return IsPortionAttrSet(nPortionNo, PORATTR_SPECIAL);
+}
+
+sal_Bool SwAccessiblePortionData::IsReadOnlyPortion( size_t nPortionNo ) const
+{
+ return IsPortionAttrSet(nPortionNo, PORATTR_READONLY);
+}
+
+sal_Bool SwAccessiblePortionData::IsGrayPortionType( sal_uInt16 nType ) const
+{
+ // gray portions?
+ // Compare with: inftxt.cxx, SwTxtPaintInfo::DrawViewOpt(...)
+ sal_Bool bGray = sal_False;
+ switch( nType )
+ {
+ case POR_FTN:
+ case POR_ISOREF:
+ case POR_REF:
+ case POR_QUOVADIS:
+ case POR_NUMBER:
+ case POR_FLD:
+ case POR_URL:
+ case POR_ISOTOX:
+ case POR_TOX:
+ case POR_HIDDEN:
+ bGray = !pViewOptions->IsPagePreview() &&
+ !pViewOptions->IsReadonly() && SwViewOption::IsFieldShadings();
+ break;
+ case POR_TAB: bGray = pViewOptions->IsTab(); break;
+ case POR_SOFTHYPH: bGray = pViewOptions->IsSoftHyph(); break;
+ case POR_BLANK: bGray = pViewOptions->IsHardBlank(); break;
+ default:
+ break; // bGray is false
+ }
+ return bGray;
+}
+
+
+const OUString& SwAccessiblePortionData::GetAccessibleString() const
+{
+ DBG_ASSERT( bFinished, "Shouldn't call this before we are done!" );
+
+ return sAccessibleString;
+}
+
+
+void SwAccessiblePortionData::GetLineBoundary(
+ Boundary& rBound,
+ sal_Int32 nPos ) const
+{
+ FillBoundary( rBound, aLineBreaks,
+ FindBreak( aLineBreaks, nPos ) );
+}
+
+// #i89175#
+sal_Int32 SwAccessiblePortionData::GetLineCount() const
+{
+ size_t nBreaks = aLineBreaks.size();
+ // A non-empty paragraph has at least 4 breaks: one for each line3 and
+ // 3 additional ones.
+ // An empty paragraph has 3 breaks.
+ // Less than 3 breaks is an error case.
+ sal_Int32 nLineCount = ( nBreaks > 3 )
+ ? nBreaks - 3
+ : ( ( nBreaks == 3 ) ? 1 : 0 );
+ return nLineCount;
+}
+
+sal_Int32 SwAccessiblePortionData::GetLineNo( const sal_Int32 nPos ) const
+{
+ sal_Int32 nLineNo = FindBreak( aLineBreaks, nPos );
+
+ // handling of position after last character
+ const sal_Int32 nLineCount( GetLineCount() );
+ if ( nLineNo >= nLineCount )
+ {
+ nLineNo = nLineCount - 1;
+ }
+
+ return nLineNo;
+}
+
+void SwAccessiblePortionData::GetBoundaryOfLine( const sal_Int32 nLineNo,
+ i18n::Boundary& rLineBound )
+{
+ FillBoundary( rLineBound, aLineBreaks, nLineNo );
+}
+// <--
+
+void SwAccessiblePortionData::GetLastLineBoundary(
+ Boundary& rBound ) const
+{
+ DBG_ASSERT( aLineBreaks.size() >= 2, "need min + max value" );
+
+ // The last two positions except the two deleimiters are the ones
+ // we are looking for, except for empty paragraphs (nBreaks==3)
+ size_t nBreaks = aLineBreaks.size();
+ FillBoundary( rBound, aLineBreaks, nBreaks <= 3 ? 0 : nBreaks-4 );
+}
+
+sal_uInt16 SwAccessiblePortionData::GetModelPosition( sal_Int32 nPos ) const
+{
+ DBG_ASSERT( nPos >= 0, "illegal position" );
+ DBG_ASSERT( nPos <= sAccessibleString.getLength(), "illegal position" );
+
+ // find the portion number
+ size_t nPortionNo = FindBreak( aAccessiblePositions, nPos );
+
+ // get model portion size
+ sal_Int32 nStartPos = aModelPositions[nPortionNo];
+
+ // if it's a non-special portion, move into the portion, else
+ // return the portion start
+ if( ! IsSpecialPortion( nPortionNo ) )
+ {
+ // 'wide' portions have to be of the same width
+ DBG_ASSERT( ( aModelPositions[nPortionNo+1] - nStartPos ) ==
+ ( aAccessiblePositions[nPortionNo+1] -
+ aAccessiblePositions[nPortionNo] ),
+ "accesability portion disagrees with text model" );
+
+ sal_Int32 nWithinPortion = nPos - aAccessiblePositions[nPortionNo];
+ nStartPos += nWithinPortion;
+ }
+ // else: return nStartPos unmodified
+
+ DBG_ASSERT( (nStartPos >= 0) && (nStartPos < USHRT_MAX),
+ "How can the SwTxtNode have so many characters?" );
+ return static_cast<sal_uInt16>(nStartPos);
+}
+
+void SwAccessiblePortionData::FillBoundary(
+ Boundary& rBound,
+ const Positions_t& rPositions,
+ size_t nPos ) const
+{
+ rBound.startPos = rPositions[nPos];
+ rBound.endPos = rPositions[nPos+1];
+}
+
+
+size_t SwAccessiblePortionData::FindBreak(
+ const Positions_t& rPositions,
+ sal_Int32 nValue ) const
+{
+ DBG_ASSERT( rPositions.size() >= 2, "need min + max value" );
+ DBG_ASSERT( rPositions[0] <= nValue, "need min value" );
+ DBG_ASSERT( rPositions[rPositions.size()-1] >= nValue,
+ "need first terminator value" );
+ DBG_ASSERT( rPositions[rPositions.size()-2] >= nValue,
+ "need second terminator value" );
+
+ size_t nMin = 0;
+ size_t nMax = rPositions.size()-2;
+
+ // loop until no more than two candidates are left
+ while( nMin+1 < nMax )
+ {
+ // check loop invariants
+ DBG_ASSERT( ( (nMin == 0) && (rPositions[nMin] <= nValue) ) ||
+ ( (nMin != 0) && (rPositions[nMin] < nValue) ),
+ "minvalue not minimal" );
+ DBG_ASSERT( nValue <= rPositions[nMax], "max value not maximal" );
+
+ // get middle (and ensure progress)
+ size_t nMiddle = (nMin + nMax)/2;
+ DBG_ASSERT( nMin < nMiddle, "progress?" );
+ DBG_ASSERT( nMiddle < nMax, "progress?" );
+
+ // check array
+ DBG_ASSERT( rPositions[nMin] <= rPositions[nMiddle],
+ "garbled positions array" );
+ DBG_ASSERT( rPositions[nMiddle] <= rPositions[nMax],
+ "garbled positions array" );
+
+ if( nValue > rPositions[nMiddle] )
+ nMin = nMiddle;
+ else
+ nMax = nMiddle;
+ }
+
+ // only two are left; we only need to check which one is the winner
+ DBG_ASSERT( (nMax == nMin) || (nMax == nMin+1), "only two left" );
+ if( (rPositions[nMin] < nValue) && (rPositions[nMin+1] <= nValue) )
+ nMin = nMin+1;
+
+ // finally, check to see whether the returned value is the 'right' position
+ DBG_ASSERT( rPositions[nMin] <= nValue, "not smaller or equal" );
+ DBG_ASSERT( nValue <= rPositions[nMin+1], "not equal or larger" );
+ DBG_ASSERT( (nMin == 0) || (rPositions[nMin-1] <= nValue),
+ "earlier value should have been returned" );
+
+ DBG_ASSERT( nMin < rPositions.size()-1,
+ "shouldn't return last position (due to termintator values)" );
+
+ return nMin;
+}
+
+size_t SwAccessiblePortionData::FindLastBreak(
+ const Positions_t& rPositions,
+ sal_Int32 nValue ) const
+{
+ size_t nResult = FindBreak( rPositions, nValue );
+
+ // skip 'zero-length' portions
+ // #i70538# consider size of <rPosition> and ignore last entry
+ while ( nResult < rPositions.size() - 2 &&
+ rPositions[nResult+1] <= nValue )
+ {
+ nResult++;
+ }
+ // <--
+
+ return nResult;
+}
+
+
+void SwAccessiblePortionData::GetSentenceBoundary(
+ Boundary& rBound,
+ sal_Int32 nPos )
+{
+ DBG_ASSERT( nPos >= 0, "illegal position; check before" );
+ DBG_ASSERT( nPos < sAccessibleString.getLength(), "illegal position" );
+
+ if( pSentences == NULL )
+ {
+ DBG_ASSERT( pBreakIt != NULL, "We always need a break." );
+ DBG_ASSERT( pBreakIt->GetBreakIter().is(), "No break-iterator." );
+ if( pBreakIt->GetBreakIter().is() )
+ {
+ pSentences = new Positions_t();
+ pSentences->reserve(10);
+
+ // use xBreak->endOfSentence to iterate over all words; store
+ // positions in pSentences
+ sal_Int32 nCurrent = 0;
+ sal_Int32 nLength = sAccessibleString.getLength();
+ do
+ {
+ pSentences->push_back( nCurrent );
+
+ sal_uInt16 nModelPos = GetModelPosition( nCurrent );
+
+ sal_Int32 nNew = pBreakIt->GetBreakIter()->endOfSentence(
+ sAccessibleString, nCurrent,
+ pBreakIt->GetLocale(pTxtNode->GetLang(nModelPos)) ) + 1;
+
+ if( (nNew < 0) && (nNew > nLength) )
+ nNew = nLength;
+ else if (nNew <= nCurrent)
+ nNew = nCurrent + 1; // ensure forward progress
+
+ nCurrent = nNew;
+ }
+ while (nCurrent < nLength);
+
+ // finish with two terminators
+ pSentences->push_back( nLength );
+ pSentences->push_back( nLength );
+ }
+ else
+ {
+ // no break iterator -> empty word
+ rBound.startPos = 0;
+ rBound.endPos = 0;
+ return;
+ }
+ }
+
+ FillBoundary( rBound, *pSentences, FindBreak( *pSentences, nPos ) );
+}
+
+void SwAccessiblePortionData::GetAttributeBoundary(
+ Boundary& rBound,
+ sal_Int32 nPos) const
+{
+ DBG_ASSERT( pTxtNode != NULL, "Need SwTxtNode!" );
+
+ // attribute boundaries can only occur on portion boundaries
+ FillBoundary( rBound, aAccessiblePositions,
+ FindBreak( aAccessiblePositions, nPos ) );
+}
+
+
+sal_Int32 SwAccessiblePortionData::GetAccessiblePosition( sal_uInt16 nPos ) const
+{
+ DBG_ASSERT( nPos <= pTxtNode->GetTxt().Len(), "illegal position" );
+
+ // find the portion number
+ // #i70538# - consider "empty" model portions - e.g. number portion
+ size_t nPortionNo = FindLastBreak( aModelPositions,
+ static_cast<sal_Int32>(nPos) );
+
+ sal_Int32 nRet = aAccessiblePositions[nPortionNo];
+
+ // if the model portion has more than one position, go into it;
+ // else return that position
+ sal_Int32 nStartPos = aModelPositions[nPortionNo];
+ sal_Int32 nEndPos = aModelPositions[nPortionNo+1];
+ if( (nEndPos - nStartPos) > 1 )
+ {
+ // 'wide' portions have to be of the same width
+ DBG_ASSERT( ( nEndPos - nStartPos ) ==
+ ( aAccessiblePositions[nPortionNo+1] -
+ aAccessiblePositions[nPortionNo] ),
+ "accesability portion disagrees with text model" );
+
+ sal_Int32 nWithinPortion = nPos - aModelPositions[nPortionNo];
+ nRet += nWithinPortion;
+ }
+ // else: return nRet unmodified
+
+ DBG_ASSERT( (nRet >= 0) && (nRet <= sAccessibleString.getLength()),
+ "too long!" );
+ return nRet;
+}
+
+sal_uInt16 SwAccessiblePortionData::FillSpecialPos(
+ sal_Int32 nPos,
+ SwSpecialPos& rPos,
+ SwSpecialPos*& rpPos ) const
+{
+ size_t nPortionNo = FindLastBreak( aAccessiblePositions, nPos );
+
+ sal_uInt8 nExtend(SP_EXTEND_RANGE_NONE);
+ sal_Int32 nRefPos(0);
+ sal_Int32 nModelPos(0);
+
+ if( nPortionNo < nBeforePortions )
+ {
+ nExtend = SP_EXTEND_RANGE_BEFORE;
+ rpPos = &rPos;
+ }
+ else
+ {
+ sal_Int32 nModelEndPos = aModelPositions[nPortionNo+1];
+ nModelPos = aModelPositions[nPortionNo];
+
+ // skip backwards over zero-length portions, since GetCharRect()
+ // counts all model-zero-length portions as belonging to the
+ // previus portion
+ size_t nCorePortionNo = nPortionNo;
+ while( nModelPos == nModelEndPos )
+ {
+ nCorePortionNo--;
+ nModelEndPos = nModelPos;
+ nModelPos = aModelPositions[nCorePortionNo];
+
+ DBG_ASSERT( nModelPos >= 0, "Can't happen." );
+ DBG_ASSERT( nCorePortionNo >= nBeforePortions, "Can't happen." );
+ }
+ DBG_ASSERT( nModelPos != nModelEndPos,
+ "portion with core-representation expected" );
+
+ // if we have anything except plain text, compute nExtend + nRefPos
+ if( (nModelEndPos - nModelPos == 1) &&
+ (pTxtNode->GetTxt().GetChar(static_cast<sal_uInt16>(nModelPos)) !=
+ sAccessibleString.getStr()[nPos]) )
+ {
+ // case 1: a one-character, non-text portion
+ // reference position is the first accessibilty for our
+ // core portion
+ nRefPos = aAccessiblePositions[ nCorePortionNo ];
+ nExtend = SP_EXTEND_RANGE_NONE;
+ rpPos = &rPos;
+ }
+ else if(nPortionNo != nCorePortionNo)
+ {
+ // case 2: a multi-character (text!) portion, followed by
+ // zero-length portions
+ // reference position is the first character of the next
+ // portion, and we are 'behind'
+ nRefPos = aAccessiblePositions[ nCorePortionNo+1 ];
+ nExtend = SP_EXTEND_RANGE_BEHIND;
+ rpPos = &rPos;
+ }
+ else
+ {
+ // case 3: regular text portion
+ DBG_ASSERT( ( nModelEndPos - nModelPos ) ==
+ ( aAccessiblePositions[nPortionNo+1] -
+ aAccessiblePositions[nPortionNo] ),
+ "text portion expected" );
+
+ nModelPos += nPos - aAccessiblePositions[ nPortionNo ];
+ rpPos = NULL;
+ }
+ }
+ if( rpPos != NULL )
+ {
+ DBG_ASSERT( rpPos == &rPos, "Yes!" );
+ DBG_ASSERT( nRefPos <= nPos, "wrong reference" );
+ DBG_ASSERT( (nExtend == SP_EXTEND_RANGE_NONE) ||
+ (nExtend == SP_EXTEND_RANGE_BEFORE) ||
+ (nExtend == SP_EXTEND_RANGE_BEHIND), "need extend" );
+
+ // get the line number, and adjust nRefPos for the line
+ // (if necessary)
+ size_t nRefLine = FindBreak( aLineBreaks, nRefPos );
+ size_t nMyLine = FindBreak( aLineBreaks, nPos );
+ sal_uInt16 nLineOffset = static_cast<sal_uInt16>( nMyLine - nRefLine );
+ if( nLineOffset != 0 )
+ nRefPos = aLineBreaks[ nMyLine ];
+
+ // fill char offset and 'special position'
+ rPos.nCharOfst = static_cast<sal_uInt16>( nPos - nRefPos );
+ rPos.nExtendRange = nExtend;
+ rPos.nLineOfst = nLineOffset;
+ }
+
+ return static_cast<sal_uInt16>( nModelPos );
+}
+
+void SwAccessiblePortionData::AdjustAndCheck(
+ sal_Int32 nPos,
+ size_t& nPortionNo,
+ sal_uInt16& nCorePos,
+ sal_Bool& bEdit) const
+{
+ // find portion and get mode position
+ nPortionNo = FindBreak( aAccessiblePositions, nPos );
+ nCorePos = static_cast<sal_uInt16>( aModelPositions[ nPortionNo ] );
+
+ // for special portions, make sure we're on a portion boundary
+ // for text portions, add the in-portion offset
+ if( IsSpecialPortion( nPortionNo ) )
+ bEdit &= nPos == aAccessiblePositions[nPortionNo];
+ else
+ nCorePos = static_cast<sal_uInt16>( nCorePos +
+ nPos - aAccessiblePositions[nPortionNo] );
+}
+
+sal_Bool SwAccessiblePortionData::GetEditableRange(
+ sal_Int32 nStart, sal_Int32 nEnd,
+ sal_uInt16& nCoreStart, sal_uInt16& nCoreEnd ) const
+{
+ sal_Bool bIsEditable = sal_True;
+
+ // get start and end portions
+ size_t nStartPortion, nEndPortion;
+ AdjustAndCheck( nStart, nStartPortion, nCoreStart, bIsEditable );
+ AdjustAndCheck( nEnd, nEndPortion, nCoreEnd, bIsEditable );
+
+ // iterate over portions, and make sure there is no read-only portion
+ // in-between
+ size_t nLastPortion = nEndPortion;
+
+ // don't count last portion if we're in front of a special portion
+ if( IsSpecialPortion(nLastPortion) )
+ {
+ if (nLastPortion > 0)
+ nLastPortion--;
+ else
+ // special case: because size_t is usually unsigned, we can't just
+ // decrease nLastPortion to -1 (which would normally do the job, so
+ // this whole if wouldn't be needed). Instead, we'll do this
+ // special case and just increae the start portion beyond the last
+ // portion to make sure the loop below will have zero iteration.
+ nStartPortion = nLastPortion + 1;
+ }
+
+ for( size_t nPor = nStartPortion; nPor <= nLastPortion; nPor ++ )
+ {
+ bIsEditable &= ! IsReadOnlyPortion( nPor );
+ }
+
+ return bIsEditable;
+}
+
+sal_Bool SwAccessiblePortionData::IsValidCorePosition( sal_uInt16 nPos ) const
+{
+ // a position is valid its within the model positions that we know
+ return ( aModelPositions[0] <= nPos ) &&
+ ( nPos <= aModelPositions[ aModelPositions.size()-1 ] );
+}
+
+sal_uInt16 SwAccessiblePortionData::GetFirstValidCorePosition() const
+{
+ return static_cast<sal_uInt16>( aModelPositions[0] );
+}
+
+sal_uInt16 SwAccessiblePortionData::GetLastValidCorePosition() const
+{
+ return static_cast<sal_uInt16>( aModelPositions[ aModelPositions.size()-1 ] );
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/access/accportions.hxx b/sw/source/core/access/accportions.hxx
new file mode 100644
index 000000000000..ef04e7ff56eb
--- /dev/null
+++ b/sw/source/core/access/accportions.hxx
@@ -0,0 +1,177 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+#ifndef _ACCPORTIONS_HXX
+#define _ACCPORTIONS_HXX
+#include <SwPortionHandler.hxx>
+#include <sal/types.h>
+#include <rtl/ustrbuf.hxx>
+#include <vector>
+
+class String;
+class SwTxtNode;
+struct SwSpecialPos;
+class SwViewOption;
+namespace com { namespace sun { namespace star {
+ namespace i18n { struct Boundary; }
+} } }
+
+/**
+ * collect text portion data from the layout through SwPortionHandler interface
+ */
+class SwAccessiblePortionData : public SwPortionHandler
+{
+ // the node this portion is referring to
+ const SwTxtNode* pTxtNode;
+
+ // variables used while collecting the data
+ rtl::OUStringBuffer aBuffer;
+ sal_Int32 nModelPosition;
+ sal_Bool bFinished;
+ const SwViewOption* pViewOptions;
+
+ // the accessible string
+ rtl::OUString sAccessibleString;
+
+ // positions array
+ // instances of Position_t must always include the minimum and
+ // maximum positions as first/last elements (to simplify the
+ // algorithms)
+ typedef std::vector<sal_Int32> Positions_t;
+
+ Positions_t aLineBreaks; /// position of line breaks
+ Positions_t aModelPositions; /// position of portion breaks in the model
+ Positions_t aAccessiblePositions; /// portion breaks in sAccessibleString
+
+ typedef std::vector<sal_uInt8> PortionAttrs_t;
+ PortionAttrs_t aPortionAttrs; /// additional portion attributes
+
+ Positions_t* pSentences; /// positions of sentence breaks
+
+ size_t nBeforePortions; /// # of portions before first model character
+ sal_Bool bLastIsSpecial; /// set if last portion was 'Special()'
+
+ /// returns the index of the first position whose value is smaller
+ /// or equal, and whose following value is equal or larger
+ size_t FindBreak( const Positions_t& rPositions, sal_Int32 nValue ) const;
+
+ /// like FindBreak, but finds the last equal or larger position
+ size_t FindLastBreak( const Positions_t& rPositions, sal_Int32 nValue ) const;
+
+ /// fill the boundary with the values from rPositions[nPos]
+ void FillBoundary(com::sun::star::i18n::Boundary& rBound,
+ const Positions_t& rPositions,
+ size_t nPos ) const;
+
+ /// Access to portion attributes
+ sal_Bool IsPortionAttrSet( size_t nPortionNo, sal_uInt8 nAttr ) const;
+ sal_Bool IsSpecialPortion( size_t nPortionNo ) const;
+ sal_Bool IsReadOnlyPortion( size_t nPortionNo ) const;
+ sal_Bool IsGrayPortionType( sal_uInt16 nType ) const;
+
+ // helper method for GetEditableRange(...):
+ void AdjustAndCheck( sal_Int32 nPos, size_t& nPortionNo,
+ sal_uInt16& nCorePos, sal_Bool& bEdit ) const;
+
+public:
+ SwAccessiblePortionData( const SwTxtNode* pTxtNd,
+ const SwViewOption* pViewOpt = NULL );
+ virtual ~SwAccessiblePortionData();
+
+ // SwPortionHandler methods
+ virtual void Text(sal_uInt16 nLength, sal_uInt16 nType);
+ virtual void Special(sal_uInt16 nLength, const String& rText, sal_uInt16 nType);
+ virtual void LineBreak();
+ virtual void Skip(sal_uInt16 nLength);
+ virtual void Finish();
+
+
+ // access to the portion data
+
+ /// get the text string, as presented by the layout
+ const rtl::OUString& GetAccessibleString() const;
+
+ /// get the start & end positions of the sentence
+ void GetLineBoundary( com::sun::star::i18n::Boundary& rBound,
+ sal_Int32 nPos ) const;
+
+ // get start and end position of the last line
+ void GetLastLineBoundary( com::sun::star::i18n::Boundary& rBound ) const;
+
+ // #i89175#
+ sal_Int32 GetLineCount() const;
+ sal_Int32 GetLineNo( const sal_Int32 nPos ) const;
+ void GetBoundaryOfLine( const sal_Int32 nLineNo,
+ com::sun::star::i18n::Boundary& rLineBound );
+ // <--
+
+ /// get the position in the model string for a given
+ /// (accessibility) position
+ sal_uInt16 GetModelPosition( sal_Int32 nPos ) const;
+
+ /// get the position in the accessibility string for a given model position
+ sal_Int32 GetAccessiblePosition( sal_uInt16 nPos ) const;
+
+ /// fill a SwSpecialPos structure, suitable for calling
+ /// SwTxtFrm->GetCharRect
+ /// Returns the core position, and fills thr rpPos either with NULL or
+ /// with the &rPos, after putting the appropriate data into it.
+ sal_uInt16 FillSpecialPos( sal_Int32 nPos,
+ SwSpecialPos& rPos,
+ SwSpecialPos*& rpPos ) const;
+
+
+ // get boundaries of words/sentences. The data structures are
+ // created on-demand.
+ void GetSentenceBoundary( com::sun::star::i18n::Boundary& rBound,
+ sal_Int32 nPos );
+
+ // get (a) boundary for attribut change
+ void GetAttributeBoundary( com::sun::star::i18n::Boundary& rBound,
+ sal_Int32 nPos ) const;
+
+ /// Convert start and end positions into core positions.
+ /// @returns true if 'special' portions are included either completely
+ /// or not at all. This can be used to test whether editing
+ /// that range would be legal
+ sal_Bool GetEditableRange( sal_Int32 nStart, sal_Int32 nEnd,
+ sal_uInt16& nCoreStart, sal_uInt16& nCoreEnd ) const;
+
+ /// Determine whether this core position is valid for these portions.
+ /// (A paragraph may be split into several frames, e.g. at page
+ /// boundaries. In this case, only part of a paragraph is represented
+ /// through this object. This method determines whether one particular
+ /// position is valid for this object or not.)
+ sal_Bool IsValidCorePosition( sal_uInt16 nPos ) const;
+ sal_uInt16 GetFirstValidCorePosition() const;
+ sal_uInt16 GetLastValidCorePosition() const;
+};
+
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/access/accpreview.cxx b/sw/source/core/access/accpreview.cxx
new file mode 100644
index 000000000000..c656b4000d05
--- /dev/null
+++ b/sw/source/core/access/accpreview.cxx
@@ -0,0 +1,97 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+ /*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+#include <vcl/svapp.hxx>
+#include <rtl/uuid.h>
+#include "access.hrc"
+#include <accpreview.hxx>
+
+const sal_Char sServiceName[] = "com.sun.star.text.AccessibleTextDocumentPageView";
+const sal_Char sImplementationName[] = "com.sun.star.comp.Writer.SwAccessibleDocumentPageView";
+
+using ::com::sun::star::lang::IndexOutOfBoundsException;
+using ::com::sun::star::uno::RuntimeException;
+using ::com::sun::star::uno::Sequence;
+using ::rtl::OUString;
+
+//
+// SwAccessiblePreview
+//
+
+SwAccessiblePreview::SwAccessiblePreview( SwAccessibleMap *pMp ) :
+ SwAccessibleDocumentBase( pMp )
+{
+ SetName( GetResource( STR_ACCESS_DOC_NAME ) );
+}
+
+SwAccessiblePreview::~SwAccessiblePreview()
+{
+}
+
+OUString SwAccessiblePreview::getImplementationName( )
+ throw( RuntimeException )
+{
+ return OUString( RTL_CONSTASCII_USTRINGPARAM( sImplementationName ) );
+}
+
+sal_Bool SwAccessiblePreview::supportsService( const OUString& rServiceName )
+ throw( RuntimeException )
+{
+ return rServiceName.equalsAsciiL(
+ RTL_CONSTASCII_STRINGPARAM( sServiceName) ) ||
+ rServiceName.equalsAsciiL(
+ RTL_CONSTASCII_STRINGPARAM( sAccessibleServiceName ) );
+}
+
+Sequence<OUString> SwAccessiblePreview::getSupportedServiceNames( )
+ throw( RuntimeException )
+{
+ Sequence<OUString> aSeq( 2 );
+ aSeq[0] = OUString( RTL_CONSTASCII_USTRINGPARAM( sServiceName ) );
+ aSeq[1] = OUString( RTL_CONSTASCII_USTRINGPARAM( sAccessibleServiceName ) );
+ return aSeq;
+}
+
+Sequence< sal_Int8 > SAL_CALL SwAccessiblePreview::getImplementationId()
+ throw(RuntimeException)
+{
+ SolarMutexGuard aGuard;
+ static Sequence< sal_Int8 > aId( 16 );
+ static sal_Bool bInit = sal_False;
+ if(!bInit)
+ {
+ rtl_createUuid( (sal_uInt8 *)(aId.getArray() ), 0, sal_True );
+ bInit = sal_True;
+ }
+ return aId;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/access/accpreview.hxx b/sw/source/core/access/accpreview.hxx
new file mode 100644
index 000000000000..589811e927c9
--- /dev/null
+++ b/sw/source/core/access/accpreview.hxx
@@ -0,0 +1,78 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+#ifndef _ACCPREVIEW_HXX
+#define _ACCPREVIEW_HXX
+
+#include "accdoc.hxx"
+
+/**
+ * accessibility implementation for the page preview.
+ * The children of the page preview are the pages that are visible in the
+ * preview.
+ *
+ * The vast majority of the implemention logic is inherited from
+ * SwAccessibleDocumentBase.
+ */
+class SwAccessiblePreview : public SwAccessibleDocumentBase
+{
+ virtual ~SwAccessiblePreview();
+
+public:
+
+ SwAccessiblePreview( SwAccessibleMap *pMap );
+
+
+
+ //===== XServiceInfo ====================================================
+
+ /** Returns an identifier for the implementation of this object.
+ */
+ virtual ::rtl::OUString SAL_CALL
+ getImplementationName (void)
+ throw (::com::sun::star::uno::RuntimeException);
+
+ /** Return whether the specified service is supported by this class.
+ */
+ virtual sal_Bool SAL_CALL
+ supportsService (const ::rtl::OUString& sServiceName)
+ throw (::com::sun::star::uno::RuntimeException);
+
+ /** Returns a list of all supported services. In this case that is just
+ the AccessibleContext service.
+ */
+ virtual ::com::sun::star::uno::Sequence< ::rtl::OUString> SAL_CALL
+ getSupportedServiceNames (void)
+ throw (::com::sun::star::uno::RuntimeException);
+
+ //====== XTypeProvider ====================================================
+ virtual ::com::sun::star::uno::Sequence< sal_Int8 > SAL_CALL getImplementationId( ) throw(::com::sun::star::uno::RuntimeException);
+};
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/access/accselectionhelper.cxx b/sw/source/core/access/accselectionhelper.cxx
new file mode 100644
index 000000000000..c3beba54da6e
--- /dev/null
+++ b/sw/source/core/access/accselectionhelper.cxx
@@ -0,0 +1,332 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+ /*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+
+#include <com/sun/star/accessibility/XAccessibleSelection.hpp>
+#include <accselectionhelper.hxx>
+
+#include <acccontext.hxx>
+#include <accmap.hxx>
+#include <svx/AccessibleShape.hxx>
+#include <viewsh.hxx>
+#include <fesh.hxx>
+#include <vcl/svapp.hxx> // for SolarMutex
+#include <tools/debug.hxx>
+#include <flyfrm.hxx>
+
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::uno;
+
+using ::com::sun::star::accessibility::XAccessible;
+using ::com::sun::star::accessibility::XAccessibleContext;
+using ::com::sun::star::accessibility::XAccessibleSelection;
+
+using namespace ::sw::access;
+
+SwAccessibleSelectionHelper::SwAccessibleSelectionHelper(
+ SwAccessibleContext& rCtxt ) :
+ rContext( rCtxt )
+{
+}
+
+SwAccessibleSelectionHelper::~SwAccessibleSelectionHelper()
+{
+}
+
+SwFEShell* SwAccessibleSelectionHelper::GetFEShell()
+{
+ DBG_ASSERT( rContext.GetMap() != NULL, "no map?" );
+ ViewShell* pViewShell = rContext.GetMap()->GetShell();
+ DBG_ASSERT( pViewShell != NULL,
+ "No view shell? Then what are you looking at?" );
+
+ SwFEShell* pFEShell = NULL;
+ if( pViewShell->ISA( SwFEShell ) )
+ {
+ pFEShell = static_cast<SwFEShell*>( pViewShell );
+ }
+
+ return pFEShell;
+}
+
+void SwAccessibleSelectionHelper::throwIndexOutOfBoundsException()
+ throw ( lang::IndexOutOfBoundsException )
+{
+ Reference < XAccessibleContext > xThis( &rContext );
+ Reference < XAccessibleSelection >xSelThis( xThis, UNO_QUERY );
+ lang::IndexOutOfBoundsException aExcept(
+ ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("index out of bounds") ),
+ xSelThis ); \
+ throw aExcept;
+}
+
+
+//===== XAccessibleSelection ============================================
+
+void SwAccessibleSelectionHelper::selectAccessibleChild(
+ sal_Int32 nChildIndex )
+ throw ( lang::IndexOutOfBoundsException,
+ RuntimeException )
+{
+ SolarMutexGuard aGuard;
+
+ // Get the respective child as SwFrm (also do index checking), ...
+ const SwAccessibleChild aChild = rContext.GetChild( *(rContext.GetMap()),
+ nChildIndex );
+ if( !aChild.IsValid() )
+ throwIndexOutOfBoundsException();
+
+ // we can only select fly frames, so we ignore (should: return
+ // false) all other attempts at child selection
+ SwFEShell* pFEShell = GetFEShell();
+ if( pFEShell != NULL )
+ {
+ const SdrObject *pObj = aChild.GetDrawObject();
+ if( pObj )
+ rContext.Select( const_cast< SdrObject *>( pObj ), 0==aChild.GetSwFrm());
+ }
+ // no frame shell, or no frame, or no fly frame -> can't select
+}
+
+sal_Bool SwAccessibleSelectionHelper::isAccessibleChildSelected(
+ sal_Int32 nChildIndex )
+ throw ( lang::IndexOutOfBoundsException,
+ RuntimeException )
+{
+ SolarMutexGuard aGuard;
+
+ // Get the respective child as SwFrm (also do index checking), ...
+ const SwAccessibleChild aChild = rContext.GetChild( *(rContext.GetMap()),
+ nChildIndex );
+ if( !aChild.IsValid() )
+ throwIndexOutOfBoundsException();
+
+ // ... and compare to the currently selected frame
+ sal_Bool bRet = sal_False;
+ SwFEShell* pFEShell = GetFEShell();
+ if( pFEShell )
+ {
+ if ( aChild.GetSwFrm() != 0 )
+ {
+ bRet = (pFEShell->GetCurrFlyFrm() == aChild.GetSwFrm());
+ }
+ else if ( aChild.GetDrawObject() )
+ {
+ bRet = pFEShell->IsObjSelected( *aChild.GetDrawObject() );
+ }
+ }
+
+ return bRet;
+}
+
+void SwAccessibleSelectionHelper::clearAccessibleSelection( )
+ throw ( RuntimeException )
+{
+ // return sal_False // we can't deselect
+}
+
+void SwAccessibleSelectionHelper::selectAllAccessibleChildren( )
+ throw ( RuntimeException )
+{
+ SolarMutexGuard aGuard;
+
+ // We can select only one. So iterate over the children to find
+ // the first we can select, and select it.
+
+ SwFEShell* pFEShell = GetFEShell();
+ if( pFEShell )
+ {
+ ::std::list< SwAccessibleChild > aChildren;
+ rContext.GetChildren( *(rContext.GetMap()), aChildren );
+
+ ::std::list< SwAccessibleChild >::const_iterator aIter = aChildren.begin();
+ ::std::list< SwAccessibleChild >::const_iterator aEndIter = aChildren.end();
+ while( aIter != aEndIter )
+ {
+ const SwAccessibleChild& rChild = *aIter;
+ const SdrObject* pObj = rChild.GetDrawObject();
+ const SwFrm* pFrm = rChild.GetSwFrm();
+ if( pObj && !(pFrm != 0 && pFEShell->IsObjSelected()) )
+ {
+ rContext.Select( const_cast< SdrObject *>( pObj ), 0==pFrm );
+ if( pFrm )
+ break;
+ }
+ ++aIter;
+ }
+ }
+}
+
+sal_Int32 SwAccessibleSelectionHelper::getSelectedAccessibleChildCount( )
+ throw ( RuntimeException )
+{
+ SolarMutexGuard aGuard;
+
+ sal_Int32 nCount = 0;
+ // Only one frame can be selected at a time, and we only frames
+ // for selectable children.
+ SwFEShell* pFEShell = GetFEShell();
+ if( pFEShell != 0 )
+ {
+ const SwFlyFrm* pFlyFrm = pFEShell->GetCurrFlyFrm();
+ if( pFlyFrm )
+ {
+ if( rContext.GetParent( SwAccessibleChild(pFlyFrm), rContext.IsInPagePreview()) ==
+ rContext.GetFrm() )
+ {
+ nCount = 1;
+ }
+ }
+ else
+ {
+ sal_uInt16 nSelObjs = pFEShell->IsObjSelected();
+ if( nSelObjs > 0 )
+ {
+ ::std::list< SwAccessibleChild > aChildren;
+ rContext.GetChildren( *(rContext.GetMap()), aChildren );
+
+ ::std::list< SwAccessibleChild >::const_iterator aIter =
+ aChildren.begin();
+ ::std::list< SwAccessibleChild >::const_iterator aEndIter =
+ aChildren.end();
+ while( aIter != aEndIter && nCount < nSelObjs )
+ {
+ const SwAccessibleChild& rChild = *aIter;
+ if( rChild.GetDrawObject() && !rChild.GetSwFrm() &&
+ rContext.GetParent(rChild, rContext.IsInPagePreview())
+ == rContext.GetFrm() &&
+ pFEShell->IsObjSelected( *rChild.GetDrawObject() ) )
+ {
+ nCount++;
+ }
+ ++aIter;
+ }
+ }
+ }
+ }
+ return nCount;
+}
+
+Reference<XAccessible> SwAccessibleSelectionHelper::getSelectedAccessibleChild(
+ sal_Int32 nSelectedChildIndex )
+ throw ( lang::IndexOutOfBoundsException,
+ RuntimeException)
+{
+ SolarMutexGuard aGuard;
+
+ // Since the index is relative to the selected children, and since
+ // there can be at most one selected frame child, the index must
+ // be 0, and a selection must exist, otherwise we have to throw an
+ // lang::IndexOutOfBoundsException
+ SwFEShell* pFEShell = GetFEShell();
+ if( 0 == pFEShell )
+ throwIndexOutOfBoundsException();
+
+ SwAccessibleChild aChild;
+ const SwFlyFrm *pFlyFrm = pFEShell->GetCurrFlyFrm();
+ if( pFlyFrm )
+ {
+ if( 0 == nSelectedChildIndex &&
+ rContext.GetParent( SwAccessibleChild(pFlyFrm), rContext.IsInPagePreview()) ==
+ rContext.GetFrm() )
+ {
+ aChild = pFlyFrm;
+ }
+ }
+ else
+ {
+ sal_uInt16 nSelObjs = pFEShell->IsObjSelected();
+ if( 0 == nSelObjs || nSelectedChildIndex >= nSelObjs )
+ throwIndexOutOfBoundsException();
+
+ ::std::list< SwAccessibleChild > aChildren;
+ rContext.GetChildren( *(rContext.GetMap()), aChildren );
+
+ ::std::list< SwAccessibleChild >::const_iterator aIter = aChildren.begin();
+ ::std::list< SwAccessibleChild >::const_iterator aEndIter = aChildren.end();
+ while( aIter != aEndIter && !aChild.IsValid() )
+ {
+ const SwAccessibleChild& rChild = *aIter;
+ if( rChild.GetDrawObject() && !rChild.GetSwFrm() &&
+ rContext.GetParent(rChild, rContext.IsInPagePreview()) ==
+ rContext.GetFrm() &&
+ pFEShell->IsObjSelected( *rChild.GetDrawObject() ) )
+ {
+ if( 0 == nSelectedChildIndex )
+ aChild = rChild;
+ else
+ --nSelectedChildIndex;
+ }
+ ++aIter;
+ }
+ }
+
+ if( !aChild.IsValid() )
+ throwIndexOutOfBoundsException();
+
+ DBG_ASSERT( rContext.GetMap() != NULL, "We need the map." );
+ Reference< XAccessible > xChild;
+ if( aChild.GetSwFrm() )
+ {
+ ::rtl::Reference < SwAccessibleContext > xChildImpl(
+ rContext.GetMap()->GetContextImpl( aChild.GetSwFrm(),
+ sal_True ) );
+ if( xChildImpl.is() )
+ {
+ xChildImpl->SetParent( &rContext );
+ xChild = xChildImpl.get();
+ }
+ }
+ else if ( aChild.GetDrawObject() )
+ {
+ ::rtl::Reference < ::accessibility::AccessibleShape > xChildImpl(
+ rContext.GetMap()->GetContextImpl( aChild.GetDrawObject(),
+ &rContext, sal_True ) );
+ if( xChildImpl.is() )
+ xChild = xChildImpl.get();
+ }
+ return xChild;
+}
+
+// index has to be treated as global child index.
+void SwAccessibleSelectionHelper::deselectAccessibleChild(
+ sal_Int32 nChildIndex )
+ throw ( lang::IndexOutOfBoundsException,
+ RuntimeException )
+{
+ // return sal_False // we can't deselect
+ if( nChildIndex < 0 ||
+ nChildIndex >= rContext.GetChildCount( *(rContext.GetMap()) ) )
+ throwIndexOutOfBoundsException();
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/access/accselectionhelper.hxx b/sw/source/core/access/accselectionhelper.hxx
new file mode 100644
index 000000000000..43ccce61612d
--- /dev/null
+++ b/sw/source/core/access/accselectionhelper.hxx
@@ -0,0 +1,83 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+#ifndef _ACCSELECTIONHELPER_HXX_
+#define _ACCSELECTIONHELPER_HXX_
+class SwAccessibleContext;
+class SwFEShell;
+#include <com/sun/star/accessibility/XAccessibleSelection.hpp>
+
+class SwAccessibleSelectionHelper
+{
+ /// the context on which this helper works
+ SwAccessibleContext& rContext;
+
+
+ /// get FE-Shell
+ SwFEShell* GetFEShell();
+
+ void throwIndexOutOfBoundsException()
+ throw ( ::com::sun::star::lang::IndexOutOfBoundsException );
+
+public:
+
+ SwAccessibleSelectionHelper( SwAccessibleContext& rContext );
+ ~SwAccessibleSelectionHelper();
+
+
+ //===== XAccessibleSelection ============================================
+
+ void selectAccessibleChild(
+ sal_Int32 nChildIndex )
+ throw ( ::com::sun::star::lang::IndexOutOfBoundsException,
+ ::com::sun::star::uno::RuntimeException );
+
+ sal_Bool isAccessibleChildSelected(
+ sal_Int32 nChildIndex )
+ throw ( ::com::sun::star::lang::IndexOutOfBoundsException,
+ ::com::sun::star::uno::RuntimeException );
+ void clearAccessibleSelection( )
+ throw ( ::com::sun::star::uno::RuntimeException );
+ void selectAllAccessibleChildren( )
+ throw ( ::com::sun::star::uno::RuntimeException );
+ sal_Int32 getSelectedAccessibleChildCount( )
+ throw ( ::com::sun::star::uno::RuntimeException );
+ ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible > getSelectedAccessibleChild(
+ sal_Int32 nSelectedChildIndex )
+ throw ( ::com::sun::star::lang::IndexOutOfBoundsException,
+ ::com::sun::star::uno::RuntimeException);
+ // index has to be treated as global child index.
+ void deselectAccessibleChild(
+ sal_Int32 nChildIndex )
+ throw ( ::com::sun::star::lang::IndexOutOfBoundsException,
+ ::com::sun::star::uno::RuntimeException );
+};
+
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/access/acctable.cxx b/sw/source/core/access/acctable.cxx
new file mode 100644
index 000000000000..ba843fb22715
--- /dev/null
+++ b/sw/source/core/access/acctable.cxx
@@ -0,0 +1,1755 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+ /*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+#include <osl/mutex.hxx>
+#include <rtl/uuid.h>
+#include <rtl/ustrbuf.hxx>
+
+#include <list>
+#include <set>
+#include <com/sun/star/accessibility/AccessibleRole.hpp>
+#include <com/sun/star/accessibility/AccessibleStateType.hpp>
+#include <com/sun/star/accessibility/AccessibleEventId.hpp>
+#include <com/sun/star/accessibility/AccessibleTableModelChange.hpp>
+#include <com/sun/star/accessibility/AccessibleTableModelChangeType.hpp>
+#include <unotools/accessiblestatesethelper.hxx>
+#include <vcl/svapp.hxx>
+#include <frmfmt.hxx>
+#include <tabfrm.hxx>
+#include <rowfrm.hxx>
+#include <cellfrm.hxx>
+#include <swtable.hxx>
+#include <crsrsh.hxx>
+#include <viscrs.hxx>
+#include <hints.hxx>
+#include <fesh.hxx>
+#include <accfrmobjslist.hxx>
+#include <accmap.hxx>
+#include <access.hrc>
+#include <acctable.hxx>
+
+#include <com/sun/star/accessibility/XAccessibleText.hpp>
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::accessibility;
+using ::rtl::OUString;
+using ::rtl::OUStringBuffer;
+using namespace ::sw::access;
+
+const sal_Char sServiceName[] = "com.sun.star.table.AccessibleTableView";
+const sal_Char sImplementationName[] = "com.sun.star.comp.Writer.SwAccessibleTableView";
+
+typedef ::std::less < sal_Int32 > Int32Less_Impl;
+typedef ::std::set < sal_Int32, Int32Less_Impl > Int32Set_Impl;
+
+typedef ::std::pair < sal_Int32, sal_Int32 > Int32Pair_Impl;
+typedef ::std::list < Int32Pair_Impl > Int32PairList_Impl;
+
+class SwAccTableSelHander_Impl
+{
+public:
+ virtual void Unselect( sal_Int32 nRowOrCol, sal_Int32 nExt ) = 0;
+};
+
+
+//------------------------------------------------------------------------------
+
+class SwAccessibleTableData_Impl
+{
+ SwAccessibleMap& mrAccMap;
+ Int32Set_Impl maRows;
+ Int32Set_Impl maColumns;
+ Int32PairList_Impl maExtents; // cell extends for event processing only
+ Point maTabFrmPos;
+ const SwTabFrm *mpTabFrm;
+ sal_Bool mbIsInPagePreview;
+ bool mbOnlyTableColumnHeader;
+
+ void CollectData( const SwFrm *pFrm );
+ void CollectExtents( const SwFrm *pFrm );
+
+ sal_Bool FindCell( const Point& rPos, const SwFrm *pFrm ,
+ sal_Bool bExact, const SwFrm *& rFrm ) const;
+
+ void GetSelection( const Point& rTabPos, const SwRect& rArea,
+ const SwSelBoxes& rSelBoxes, const SwFrm *pFrm,
+ SwAccTableSelHander_Impl& rSelHdl,
+ sal_Bool bColumns ) const;
+
+ // #i77106#
+ inline bool IncludeRow( const SwFrm& rFrm ) const
+ {
+ return !mbOnlyTableColumnHeader ||
+ mpTabFrm->IsInHeadline( rFrm );
+ }
+ // <--
+public:
+ // #i77106# - add third optional parameter <bOnlyTableColumnHeader>, default value <false>
+ SwAccessibleTableData_Impl( SwAccessibleMap& rAccMap,
+ const SwTabFrm *pTabFrm,
+ sal_Bool bIsInPagePreview,
+ bool bOnlyTableColumnHeader = false );
+ // <--
+
+ const Int32Set_Impl& GetRows() const { return maRows; }
+ const Int32Set_Impl& GetColumns() const { return maColumns; }
+
+ inline Int32Set_Impl::const_iterator GetRowIter( sal_Int32 nRow ) const;
+ inline Int32Set_Impl::const_iterator GetColumnIter( sal_Int32 nCol ) const;
+
+ const SwFrm *GetCell( sal_Int32 nRow, sal_Int32 nColumn, sal_Bool bExact,
+ SwAccessibleTable *pThis ) const
+ throw(lang::IndexOutOfBoundsException );
+ const SwFrm *GetCellAtPos( sal_Int32 nLeft, sal_Int32 nTop,
+ sal_Bool bExact ) const;
+ inline sal_Int32 GetRowCount() const;
+ inline sal_Int32 GetColumnCount() const;
+ sal_Bool CompareExtents( const SwAccessibleTableData_Impl& r ) const;
+
+ void GetSelection( sal_Int32 nStart, sal_Int32 nEnd,
+ const SwSelBoxes& rSelBoxes,
+ SwAccTableSelHander_Impl& rSelHdl,
+ sal_Bool bColumns ) const;
+
+ void CheckRowAndCol( sal_Int32 nRow, sal_Int32 nCol,
+ SwAccessibleTable *pThis ) const
+ throw(lang::IndexOutOfBoundsException );
+
+ void GetRowColumnAndExtent( const SwRect& rBox,
+ sal_Int32& rRow, sal_Int32& rColumn,
+ sal_Int32& rRowExtent,
+ sal_Int32& rColumnExtent ) const;
+
+ const Point& GetTablePos() const { return maTabFrmPos; }
+ void SetTablePos( const Point& rPos ) { maTabFrmPos = rPos; }
+};
+
+void SwAccessibleTableData_Impl::CollectData( const SwFrm *pFrm )
+{
+ const SwAccessibleChildSList aList( *pFrm, mrAccMap );
+ SwAccessibleChildSList::const_iterator aIter( aList.begin() );
+ SwAccessibleChildSList::const_iterator aEndIter( aList.end() );
+ while( aIter != aEndIter )
+ {
+ const SwAccessibleChild& rLower = *aIter;
+ const SwFrm *pLower = rLower.GetSwFrm();
+ if( pLower )
+ {
+ if( pLower->IsRowFrm() )
+ {
+ // #i77106#
+ if ( IncludeRow( *pLower ) )
+ {
+ maRows.insert( pLower->Frm().Top() - maTabFrmPos.Y() );
+ CollectData( pLower );
+ }
+ }
+ else if( pLower->IsCellFrm() &&
+ rLower.IsAccessible( mbIsInPagePreview ) )
+ {
+ maColumns.insert( pLower->Frm().Left() - maTabFrmPos.X() );
+ }
+ else
+ {
+ CollectData( pLower );
+ }
+ }
+ ++aIter;
+ }
+}
+
+void SwAccessibleTableData_Impl::CollectExtents( const SwFrm *pFrm )
+{
+ const SwAccessibleChildSList aList( *pFrm, mrAccMap );
+ SwAccessibleChildSList::const_iterator aIter( aList.begin() );
+ SwAccessibleChildSList::const_iterator aEndIter( aList.end() );
+ while( aIter != aEndIter )
+ {
+ const SwAccessibleChild& rLower = *aIter;
+ const SwFrm *pLower = rLower.GetSwFrm();
+ if( pLower )
+ {
+ if( pLower->IsCellFrm() &&
+ rLower.IsAccessible( mbIsInPagePreview ) )
+ {
+ sal_Int32 nRow, nCol;
+ Int32Pair_Impl aCellExtents;
+ GetRowColumnAndExtent( pLower->Frm(), nRow, nCol,
+ aCellExtents.first,
+ aCellExtents.second );
+
+ maExtents.push_back( aCellExtents );
+ }
+ else
+ {
+ // #i77106#
+ if ( !pLower->IsRowFrm() ||
+ IncludeRow( *pLower ) )
+ {
+ CollectExtents( pLower );
+ }
+ }
+ }
+ ++aIter;
+ }
+}
+
+sal_Bool SwAccessibleTableData_Impl::FindCell(
+ const Point& rPos, const SwFrm *pFrm, sal_Bool bExact,
+ const SwFrm *& rRet ) const
+{
+ sal_Bool bFound = sal_False;
+
+ const SwAccessibleChildSList aList( *pFrm, mrAccMap );
+ SwAccessibleChildSList::const_iterator aIter( aList.begin() );
+ SwAccessibleChildSList::const_iterator aEndIter( aList.end() );
+ while( !bFound && aIter != aEndIter )
+ {
+ const SwAccessibleChild& rLower = *aIter;
+ const SwFrm *pLower = rLower.GetSwFrm();
+ OSL_ENSURE( pLower, "child should be a frame" );
+ if( pLower )
+ {
+ if( rLower.IsAccessible( mbIsInPagePreview ) )
+ {
+ OSL_ENSURE( pLower->IsCellFrm(), "lower is not a cell frame" );
+ const SwRect& rFrm = pLower->Frm();
+ if( rFrm.Right() >= rPos.X() && rFrm.Bottom() >= rPos.Y() )
+ {
+ // We have found the cell
+ OSL_ENSURE( rFrm.Left() <= rPos.X() && rFrm.Top() <= rPos.Y(),
+ "find frame moved to far!" );
+ bFound = sal_True;
+ if( !bExact ||
+ (rFrm.Top() == rPos.Y() && rFrm.Left() == rPos.Y() ) )
+ {
+ rRet = pLower;
+ }
+ }
+ }
+ else
+ {
+ // #i77106#
+ if ( !pLower->IsRowFrm() ||
+ IncludeRow( *pLower ) )
+ {
+ bFound = FindCell( rPos, pLower, bExact, rRet );
+ }
+ }
+ }
+ ++aIter;
+ }
+
+ return bFound;
+}
+
+void SwAccessibleTableData_Impl::GetSelection(
+ const Point& rTabPos,
+ const SwRect& rArea,
+ const SwSelBoxes& rSelBoxes,
+ const SwFrm *pFrm,
+ SwAccTableSelHander_Impl& rSelHdl,
+ sal_Bool bColumns ) const
+{
+ const SwAccessibleChildSList aList( *pFrm, mrAccMap );
+ SwAccessibleChildSList::const_iterator aIter( aList.begin() );
+ SwAccessibleChildSList::const_iterator aEndIter( aList.end() );
+ while( aIter != aEndIter )
+ {
+ const SwAccessibleChild& rLower = *aIter;
+ const SwFrm *pLower = rLower.GetSwFrm();
+ OSL_ENSURE( pLower, "child should be a frame" );
+ const SwRect& rBox = rLower.GetBox( mrAccMap );
+ if( pLower && rBox.IsOver( rArea ) )
+ {
+ if( rLower.IsAccessible( mbIsInPagePreview ) )
+ {
+ OSL_ENSURE( pLower->IsCellFrm(), "lower is not a cell frame" );
+ const SwCellFrm *pCFrm =
+ static_cast < const SwCellFrm * >( pLower );
+ SwTableBox *pBox =
+ const_cast< SwTableBox *>( pCFrm->GetTabBox() ); //SVPtrArr!
+ if( !rSelBoxes.Seek_Entry( pBox ) )
+ {
+ const Int32Set_Impl rRowsOrCols =
+ bColumns ? maColumns : maRows;
+
+ sal_Int32 nPos = bColumns ? (rBox.Left() - rTabPos.X())
+ : (rBox.Top() - rTabPos.Y());
+ Int32Set_Impl::const_iterator aSttRowOrCol(
+ rRowsOrCols.lower_bound( nPos ) );
+ sal_Int32 nRowOrCol =
+ static_cast< sal_Int32 >( ::std::distance(
+ rRowsOrCols.begin(), aSttRowOrCol ) );
+
+ nPos = bColumns ? (rBox.Right() - rTabPos.X())
+ : (rBox.Bottom() - rTabPos.Y());
+ Int32Set_Impl::const_iterator aEndRowOrCol(
+ rRowsOrCols.upper_bound( nPos ) );
+ sal_Int32 nExt =
+ static_cast< sal_Int32 >( ::std::distance(
+ aSttRowOrCol, aEndRowOrCol ) );
+
+ rSelHdl.Unselect( nRowOrCol, nExt );
+ }
+ }
+ else
+ {
+ // #i77106#
+ if ( !pLower->IsRowFrm() ||
+ IncludeRow( *pLower ) )
+ {
+ GetSelection( rTabPos, rArea, rSelBoxes, pLower, rSelHdl,
+ bColumns );
+ }
+ }
+ }
+ ++aIter;
+ }
+}
+
+const SwFrm *SwAccessibleTableData_Impl::GetCell(
+ sal_Int32 nRow, sal_Int32 nColumn, sal_Bool,
+ SwAccessibleTable *pThis ) const
+ throw(lang::IndexOutOfBoundsException )
+{
+ CheckRowAndCol( nRow, nColumn, pThis );
+
+ Int32Set_Impl::const_iterator aSttCol( GetColumnIter( nColumn ) );
+ Int32Set_Impl::const_iterator aSttRow( GetRowIter( nRow ) );
+ const SwFrm *pCellFrm = GetCellAtPos( *aSttCol, *aSttRow, sal_False );
+
+ return pCellFrm;
+}
+
+void SwAccessibleTableData_Impl::GetSelection(
+ sal_Int32 nStart, sal_Int32 nEnd,
+ const SwSelBoxes& rSelBoxes,
+ SwAccTableSelHander_Impl& rSelHdl,
+ sal_Bool bColumns ) const
+{
+ SwRect aArea( mpTabFrm->Frm() );
+ Point aPos( aArea.Pos() );
+
+ const Int32Set_Impl& rRowsOrColumns = bColumns ? maColumns : maRows;
+ if( nStart > 0 )
+ {
+ Int32Set_Impl::const_iterator aStt( rRowsOrColumns.begin() );
+ ::std::advance( aStt,
+ static_cast< Int32Set_Impl::difference_type >( nStart ) );
+ if( bColumns )
+ aArea.Left( *aStt + aPos.X() );
+ else
+ aArea.Top( *aStt + aPos.Y() );
+ }
+ if( nEnd < static_cast< sal_Int32 >( rRowsOrColumns.size() ) )
+ {
+ Int32Set_Impl::const_iterator aEnd( rRowsOrColumns.begin() );
+ ::std::advance( aEnd,
+ static_cast< Int32Set_Impl::difference_type >( nEnd ) );
+ if( bColumns )
+ aArea.Right( *aEnd + aPos.X() - 1 );
+ else
+ aArea.Bottom( *aEnd + aPos.Y() - 1 );
+ }
+
+ GetSelection( aPos, aArea, rSelBoxes, mpTabFrm, rSelHdl, bColumns );
+}
+
+const SwFrm *SwAccessibleTableData_Impl::GetCellAtPos(
+ sal_Int32 nLeft, sal_Int32 nTop, sal_Bool bExact ) const
+{
+ Point aPos( mpTabFrm->Frm().Pos() );
+ aPos.Move( nLeft, nTop );
+ const SwFrm *pRet = 0;
+ FindCell( aPos, mpTabFrm, bExact, pRet );
+
+ return pRet;
+}
+
+inline sal_Int32 SwAccessibleTableData_Impl::GetRowCount() const
+{
+ return static_cast< sal_Int32 >( maRows.size() );
+}
+
+inline sal_Int32 SwAccessibleTableData_Impl::GetColumnCount() const
+{
+ return static_cast< sal_Int32 >( maColumns.size() );
+}
+
+sal_Bool SwAccessibleTableData_Impl::CompareExtents(
+ const SwAccessibleTableData_Impl& rCmp ) const
+{
+ if( maExtents.size() != rCmp.maExtents.size() )
+ return sal_False;
+
+ Int32PairList_Impl::const_iterator aIter( maExtents.begin() );
+ Int32PairList_Impl::const_iterator aEndIter( maExtents.end() );
+ Int32PairList_Impl::const_iterator aCmpIter( rCmp.maExtents.begin() );
+ while( aIter != aEndIter )
+ {
+ if( *aIter != *aCmpIter )
+ return sal_False;
+
+ ++aIter;
+ ++aCmpIter;
+ }
+
+ return sal_True;
+}
+
+SwAccessibleTableData_Impl::SwAccessibleTableData_Impl( SwAccessibleMap& rAccMap,
+ const SwTabFrm *pTabFrm,
+ sal_Bool bIsInPagePreview,
+ bool bOnlyTableColumnHeader )
+ : mrAccMap( rAccMap )
+ , maTabFrmPos( pTabFrm->Frm().Pos() )
+ , mpTabFrm( pTabFrm )
+ , mbIsInPagePreview( bIsInPagePreview )
+ , mbOnlyTableColumnHeader( bOnlyTableColumnHeader )
+{
+ CollectData( mpTabFrm );
+ CollectExtents( mpTabFrm );
+}
+
+inline Int32Set_Impl::const_iterator SwAccessibleTableData_Impl::GetRowIter(
+ sal_Int32 nRow ) const
+{
+ Int32Set_Impl::const_iterator aCol( GetRows().begin() );
+ if( nRow > 0 )
+ {
+ ::std::advance( aCol,
+ static_cast< Int32Set_Impl::difference_type >( nRow ) );
+ }
+ return aCol;
+}
+
+inline Int32Set_Impl::const_iterator SwAccessibleTableData_Impl::GetColumnIter(
+ sal_Int32 nColumn ) const
+{
+ Int32Set_Impl::const_iterator aCol = GetColumns().begin();
+ if( nColumn > 0 )
+ {
+ ::std::advance( aCol,
+ static_cast< Int32Set_Impl::difference_type >( nColumn ) );
+ }
+ return aCol;
+}
+
+void SwAccessibleTableData_Impl::CheckRowAndCol(
+ sal_Int32 nRow, sal_Int32 nCol, SwAccessibleTable *pThis ) const
+ throw(lang::IndexOutOfBoundsException )
+{
+ if( ( nRow < 0 || nRow >= static_cast< sal_Int32 >( maRows.size() ) ) ||
+ ( nCol < 0 || nCol >= static_cast< sal_Int32 >( maColumns.size() ) ) )
+ {
+ uno::Reference < XAccessibleTable > xThis( pThis );
+ lang::IndexOutOfBoundsException aExcept(
+ OUString( RTL_CONSTASCII_USTRINGPARAM(
+ "row or column index out of range") ),
+ xThis );
+ throw aExcept;
+ }
+}
+
+void SwAccessibleTableData_Impl::GetRowColumnAndExtent(
+ const SwRect& rBox,
+ sal_Int32& rRow, sal_Int32& rColumn,
+ sal_Int32& rRowExtent, sal_Int32& rColumnExtent ) const
+{
+ Int32Set_Impl::const_iterator aStt(
+ maRows.lower_bound( rBox.Top() - maTabFrmPos.Y() ) );
+ Int32Set_Impl::const_iterator aEnd(
+ maRows.upper_bound( rBox.Bottom() - maTabFrmPos.Y() ) );
+ rRow =
+ static_cast< sal_Int32 >( ::std::distance( maRows.begin(), aStt ) );
+ rRowExtent =
+ static_cast< sal_Int32 >( ::std::distance( aStt, aEnd ) );
+
+ aStt = maColumns.lower_bound( rBox.Left() - maTabFrmPos.X() );
+ aEnd = maColumns.upper_bound( rBox.Right() - maTabFrmPos.X() );
+ rColumn =
+ static_cast< sal_Int32 >( ::std::distance( maColumns.begin(), aStt ) );
+ rColumnExtent =
+ static_cast< sal_Int32 >( ::std::distance( aStt, aEnd ) );
+}
+
+//------------------------------------------------------------------------------
+
+class SwAccSingleTableSelHander_Impl : public SwAccTableSelHander_Impl
+{
+ sal_Bool bSelected;
+
+public:
+
+ inline SwAccSingleTableSelHander_Impl();
+
+ inline sal_Bool IsSelected() const { return bSelected; }
+
+ virtual void Unselect( sal_Int32, sal_Int32 );
+};
+
+inline SwAccSingleTableSelHander_Impl::SwAccSingleTableSelHander_Impl() :
+ bSelected( sal_True )
+{
+}
+
+void SwAccSingleTableSelHander_Impl::Unselect( sal_Int32, sal_Int32 )
+{
+ bSelected = sal_False;
+}
+
+//------------------------------------------------------------------------------
+
+class SwAccAllTableSelHander_Impl : public SwAccTableSelHander_Impl
+
+{
+ ::std::vector< sal_Bool > aSelected;
+ sal_Int32 nCount;
+
+public:
+
+ inline SwAccAllTableSelHander_Impl( sal_Int32 nSize );
+
+ uno::Sequence < sal_Int32 > GetSelSequence();
+
+ virtual void Unselect( sal_Int32 nRowOrCol, sal_Int32 nExt );
+ virtual ~SwAccAllTableSelHander_Impl();
+};
+
+SwAccAllTableSelHander_Impl::~SwAccAllTableSelHander_Impl()
+{
+}
+
+inline SwAccAllTableSelHander_Impl::SwAccAllTableSelHander_Impl( sal_Int32 nSize ) :
+ aSelected( nSize, sal_True ),
+ nCount( nSize )
+{
+}
+
+uno::Sequence < sal_Int32 > SwAccAllTableSelHander_Impl::GetSelSequence()
+{
+ OSL_ENSURE( nCount >= 0, "underflow" );
+ uno::Sequence < sal_Int32 > aRet( nCount );
+ sal_Int32 *pRet = aRet.getArray();
+ sal_Int32 nPos = 0;
+ size_t nSize = aSelected.size();
+ for( size_t i=0; i < nSize && nPos < nCount; i++ )
+ {
+ if( aSelected[i] )
+ {
+ *pRet++ = i;
+ nPos++;
+ }
+ }
+
+ OSL_ENSURE( nPos == nCount, "count is wrong" );
+
+ return aRet;
+}
+
+void SwAccAllTableSelHander_Impl::Unselect( sal_Int32 nRowOrCol,
+ sal_Int32 nExt )
+{
+ OSL_ENSURE( static_cast< size_t >( nRowOrCol ) < aSelected.size(),
+ "index to large" );
+ OSL_ENSURE( static_cast< size_t >( nRowOrCol+nExt ) <= aSelected.size(),
+ "extent to large" );
+ while( nExt )
+ {
+ if( aSelected[static_cast< size_t >( nRowOrCol )] )
+ {
+ aSelected[static_cast< size_t >( nRowOrCol )] = sal_False;
+ nCount--;
+ }
+ nExt--;
+ nRowOrCol++;
+ }
+}
+
+//------------------------------------------------------------------------------
+
+const SwSelBoxes *SwAccessibleTable::GetSelBoxes() const
+{
+ const SwSelBoxes *pSelBoxes = 0;
+ const SwCrsrShell *pCSh = GetCrsrShell();
+ if( (pCSh != NULL) && pCSh->IsTableMode() )
+ {
+ pSelBoxes = &pCSh->GetTableCrsr()->GetBoxes();
+ }
+
+ return pSelBoxes;
+}
+
+void SwAccessibleTable::FireTableChangeEvent(
+ const SwAccessibleTableData_Impl& rTableData )
+{
+ AccessibleTableModelChange aModelChange;
+ aModelChange.Type = AccessibleTableModelChangeType::UPDATE;
+ aModelChange.FirstRow = 0;
+ aModelChange.LastRow = rTableData.GetRowCount() - 1;
+ aModelChange.FirstColumn = 0;
+ aModelChange.LastColumn = rTableData.GetColumnCount() - 1;
+
+ AccessibleEventObject aEvent;
+ aEvent.EventId = AccessibleEventId::TABLE_MODEL_CHANGED;
+ aEvent.NewValue <<= aModelChange;
+
+ FireAccessibleEvent( aEvent );
+}
+
+
+const SwTableBox* SwAccessibleTable::GetTableBox( sal_Int32 nChildIndex ) const
+{
+ DBG_ASSERT( nChildIndex >= 0, "Illegal child index." );
+ DBG_ASSERT( nChildIndex < const_cast<SwAccessibleTable*>(this)->getAccessibleChildCount(), "Illegal child index." ); // #i77106#
+
+ const SwTableBox* pBox = NULL;
+
+ // get table box for 'our' table cell
+ SwAccessibleChild aCell( GetChild( *(const_cast<SwAccessibleMap*>(GetMap())), nChildIndex ) );
+ if( aCell.GetSwFrm() )
+ {
+ const SwFrm* pChildFrm = aCell.GetSwFrm();
+ if( (pChildFrm != NULL) && pChildFrm->IsCellFrm() )
+ {
+ const SwCellFrm* pCellFrm =
+ static_cast<const SwCellFrm*>( pChildFrm );
+ pBox = pCellFrm->GetTabBox();
+ }
+ }
+
+ DBG_ASSERT( pBox != NULL, "We need the table box." );
+ return pBox;
+}
+
+sal_Bool SwAccessibleTable::IsChildSelected( sal_Int32 nChildIndex ) const
+{
+ sal_Bool bRet = sal_False;
+ const SwSelBoxes* pSelBoxes = GetSelBoxes();
+ if( pSelBoxes )
+ {
+ const SwTableBox* pBox = GetTableBox( nChildIndex );
+ DBG_ASSERT( pBox != NULL, "We need the table box." );
+ bRet = pSelBoxes->Seek_Entry( const_cast<SwTableBox*>( pBox ) );
+ }
+
+ return bRet;
+}
+
+sal_Int32 SwAccessibleTable::GetIndexOfSelectedChild(
+ sal_Int32 nSelectedChildIndex ) const
+{
+ // iterate over all children to n-th isAccessibleChildSelected()
+ sal_Int32 nChildren = const_cast<SwAccessibleTable*>(this)->getAccessibleChildCount(); // #i77106#
+ if( nSelectedChildIndex >= nChildren )
+ return -1L;
+
+ sal_Int32 n = 0;
+ while( n < nChildren )
+ {
+ if( IsChildSelected( n ) )
+ {
+ if( 0 == nSelectedChildIndex )
+ break;
+ else
+ --nSelectedChildIndex;
+ }
+ ++n;
+ }
+
+ return n < nChildren ? n : -1L;
+}
+
+void SwAccessibleTable::GetStates(
+ ::utl::AccessibleStateSetHelper& rStateSet )
+{
+ SwAccessibleContext::GetStates( rStateSet );
+
+ // MULTISELECTABLE
+ SwCrsrShell* pCrsrShell = GetCrsrShell();
+ if( pCrsrShell )
+ rStateSet.AddState( AccessibleStateType::MULTI_SELECTABLE );
+}
+
+SwAccessibleTable::SwAccessibleTable(
+ SwAccessibleMap* pInitMap,
+ const SwTabFrm* pTabFrm ) :
+ SwAccessibleContext( pInitMap, AccessibleRole::TABLE, pTabFrm ),
+ mpTableData( 0 )
+{
+ SolarMutexGuard aGuard;
+
+ const SwFrmFmt *pFrmFmt = pTabFrm->GetFmt();
+ const_cast< SwFrmFmt * >( pFrmFmt )->Add( this );
+ const String& rName = pFrmFmt->GetName();
+
+ OUStringBuffer aBuffer( rName.Len() + 4 );
+ aBuffer.append( OUString(rName) );
+ aBuffer.append( static_cast<sal_Unicode>( '-' ) );
+ aBuffer.append( static_cast<sal_Int32>( pTabFrm->GetPhyPageNum() ) );
+
+ SetName( aBuffer.makeStringAndClear() );
+
+ OUString sArg1( static_cast< const SwTabFrm * >( GetFrm() )
+ ->GetFmt()->GetName() );
+ OUString sArg2( GetFormattedPageNumber() );
+
+ sDesc = GetResource( STR_ACCESS_TABLE_DESC, &sArg1, &sArg2 );
+}
+
+SwAccessibleTable::~SwAccessibleTable()
+{
+ SolarMutexGuard aGuard;
+
+ delete mpTableData;
+}
+
+void SwAccessibleTable::Modify( const SfxPoolItem* pOld, const SfxPoolItem *pNew)
+{
+ sal_uInt16 nWhich = pOld ? pOld->Which() : pNew ? pNew->Which() : 0 ;
+ const SwTabFrm *pTabFrm = static_cast< const SwTabFrm * >( GetFrm() );
+ switch( nWhich )
+ {
+ case RES_NAME_CHANGED:
+ if( pTabFrm )
+ {
+ const SwFrmFmt *pFrmFmt = pTabFrm->GetFmt();
+ OSL_ENSURE( pFrmFmt == GetRegisteredIn(), "invalid frame" );
+
+ OUString sOldName( GetName() );
+
+ const String& rNewTabName = pFrmFmt->GetName();
+ OUStringBuffer aBuffer( rNewTabName.Len() + 4 );
+ aBuffer.append( OUString(rNewTabName) );
+ aBuffer.append( static_cast<sal_Unicode>( '-' ) );
+ aBuffer.append( static_cast<sal_Int32>( pTabFrm->GetPhyPageNum() ) );
+
+ SetName( aBuffer.makeStringAndClear() );
+ if( sOldName != GetName() )
+ {
+ AccessibleEventObject aEvent;
+ aEvent.EventId = AccessibleEventId::NAME_CHANGED;
+ aEvent.OldValue <<= sOldName;
+ aEvent.NewValue <<= GetName();
+ FireAccessibleEvent( aEvent );
+ }
+
+ OUString sOldDesc( sDesc );
+ OUString sArg1( rNewTabName );
+ OUString sArg2( GetFormattedPageNumber() );
+
+ sDesc = GetResource( STR_ACCESS_TABLE_DESC, &sArg1, &sArg2 );
+ if( sDesc != sOldDesc )
+ {
+ AccessibleEventObject aEvent;
+ aEvent.EventId = AccessibleEventId::DESCRIPTION_CHANGED;
+ aEvent.OldValue <<= sOldDesc;
+ aEvent.NewValue <<= sDesc;
+ FireAccessibleEvent( aEvent );
+ }
+ }
+ break;
+
+ case RES_OBJECTDYING:
+ // mba: it seems that this class intentionally does not call code in base class SwClient
+ if( GetRegisteredIn() ==
+ static_cast< SwModify *>( static_cast< const SwPtrMsgPoolItem * >( pOld )->pObject ) )
+ GetRegisteredInNonConst()->Remove( this );
+ break;
+
+ default:
+ // mba: former call to base class method removed as it is meant to handle only RES_OBJECTDYING
+ break;
+ }
+}
+
+uno::Any SwAccessibleTable::queryInterface( const uno::Type& rType )
+ throw (uno::RuntimeException)
+{
+ uno::Any aRet;
+ if ( rType == ::getCppuType( static_cast< uno::Reference< XAccessibleTable > * >( 0 ) ) )
+ {
+ uno::Reference<XAccessibleTable> xThis( this );
+ aRet <<= xThis;
+ }
+ else if ( rType == ::getCppuType( static_cast< uno::Reference< XAccessibleSelection > * >( 0 ) ) )
+ {
+ uno::Reference<XAccessibleSelection> xSelection( this );
+ aRet <<= xSelection;
+ }
+ else
+ {
+ aRet = SwAccessibleContext::queryInterface(rType);
+ }
+
+ return aRet;
+}
+
+//====== XTypeProvider ====================================================
+uno::Sequence< uno::Type > SAL_CALL SwAccessibleTable::getTypes()
+ throw(uno::RuntimeException)
+{
+ uno::Sequence< uno::Type > aTypes( SwAccessibleContext::getTypes() );
+
+ sal_Int32 nIndex = aTypes.getLength();
+ aTypes.realloc( nIndex + 2 );
+
+ uno::Type* pTypes = aTypes.getArray();
+ pTypes[nIndex++] = ::getCppuType( static_cast< uno::Reference< XAccessibleSelection > * >( 0 ) );
+ pTypes[nIndex++] = ::getCppuType( static_cast< uno::Reference< XAccessibleTable > * >( 0 ) );
+
+ return aTypes;
+}
+
+uno::Sequence< sal_Int8 > SAL_CALL SwAccessibleTable::getImplementationId()
+ throw(uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+ static uno::Sequence< sal_Int8 > aId( 16 );
+ static sal_Bool bInit = sal_False;
+ if(!bInit)
+ {
+ rtl_createUuid( (sal_uInt8 *)(aId.getArray() ), 0, sal_True );
+ bInit = sal_True;
+ }
+ return aId;
+}
+
+// #i77106#
+SwAccessibleTableData_Impl* SwAccessibleTable::CreateNewTableData()
+{
+ const SwTabFrm* pTabFrm = static_cast<const SwTabFrm*>( GetFrm() );
+ return new SwAccessibleTableData_Impl( *GetMap(), pTabFrm, IsInPagePreview() );
+}
+// <--
+
+void SwAccessibleTable::UpdateTableData()
+{
+ // #i77106# - usage of new method <CreateNewTableData()>
+ delete mpTableData;
+ mpTableData = CreateNewTableData();
+ // <--
+}
+
+void SwAccessibleTable::ClearTableData()
+{
+ delete mpTableData;
+ mpTableData = 0;
+}
+
+OUString SAL_CALL SwAccessibleTable::getAccessibleDescription (void)
+ throw (uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+
+ CHECK_FOR_DEFUNC( XAccessibleContext )
+
+ return sDesc;
+}
+
+sal_Int32 SAL_CALL SwAccessibleTable::getAccessibleRowCount()
+ throw (uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+
+ CHECK_FOR_DEFUNC( XAccessibleTable )
+
+ return GetTableData().GetRowCount();
+}
+
+sal_Int32 SAL_CALL SwAccessibleTable::getAccessibleColumnCount( )
+ throw (uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+
+ CHECK_FOR_DEFUNC( XAccessibleTable )
+
+ return GetTableData().GetColumnCount();
+}
+
+OUString SAL_CALL SwAccessibleTable::getAccessibleRowDescription(
+ sal_Int32 nRow )
+ throw (lang::IndexOutOfBoundsException, uno::RuntimeException)
+{
+ // #i87532# - determine table cell in <nRow>th row and
+ // in first column of row header table and return its text content.
+ OUString sRowDesc;
+
+ GetTableData().CheckRowAndCol(nRow, 0, this);
+
+ uno::Reference< XAccessibleTable > xTableRowHeader = getAccessibleRowHeaders();
+ if ( xTableRowHeader.is() )
+ {
+ uno::Reference< XAccessible > xRowHeaderCell =
+ xTableRowHeader->getAccessibleCellAt( nRow, 0 );
+ OSL_ENSURE( xRowHeaderCell.is(),
+ "<SwAccessibleTable::getAccessibleRowDescription(..)> - missing row header cell -> serious issue." );
+ uno::Reference< XAccessibleContext > xRowHeaderCellContext =
+ xRowHeaderCell->getAccessibleContext();
+ const sal_Int32 nCellChildCount( xRowHeaderCellContext->getAccessibleChildCount() );
+ for ( sal_Int32 nChildIndex = 0; nChildIndex < nCellChildCount; ++nChildIndex )
+ {
+ uno::Reference< XAccessible > xChild = xRowHeaderCellContext->getAccessibleChild( nChildIndex );
+ uno::Reference< XAccessibleText > xChildText( xChild, uno::UNO_QUERY );
+ if ( xChildText.is() )
+ {
+ sRowDesc = sRowDesc + xChildText->getText();
+ }
+ }
+ }
+
+ return sRowDesc;
+ // <--
+}
+
+OUString SAL_CALL SwAccessibleTable::getAccessibleColumnDescription(
+ sal_Int32 nColumn )
+ throw (lang::IndexOutOfBoundsException, uno::RuntimeException)
+{
+ // #i87532# - determine table cell in first row and
+ // in <nColumn>th column of column header table and return its text content.
+ OUString sColumnDesc;
+
+ GetTableData().CheckRowAndCol(0, nColumn, this);
+
+ uno::Reference< XAccessibleTable > xTableColumnHeader = getAccessibleColumnHeaders();
+ if ( xTableColumnHeader.is() )
+ {
+ uno::Reference< XAccessible > xColumnHeaderCell =
+ xTableColumnHeader->getAccessibleCellAt( 0, nColumn );
+ OSL_ENSURE( xColumnHeaderCell.is(),
+ "<SwAccessibleTable::getAccessibleColumnDescription(..)> - missing column header cell -> serious issue." );
+ uno::Reference< XAccessibleContext > xColumnHeaderCellContext =
+ xColumnHeaderCell->getAccessibleContext();
+ const sal_Int32 nCellChildCount( xColumnHeaderCellContext->getAccessibleChildCount() );
+ for ( sal_Int32 nChildIndex = 0; nChildIndex < nCellChildCount; ++nChildIndex )
+ {
+ uno::Reference< XAccessible > xChild = xColumnHeaderCellContext->getAccessibleChild( nChildIndex );
+ uno::Reference< XAccessibleText > xChildText( xChild, uno::UNO_QUERY );
+ if ( xChildText.is() )
+ {
+ sColumnDesc = sColumnDesc + xChildText->getText();
+ }
+ }
+ }
+
+ return sColumnDesc;
+ // <--
+}
+
+sal_Int32 SAL_CALL SwAccessibleTable::getAccessibleRowExtentAt(
+ sal_Int32 nRow, sal_Int32 nColumn )
+ throw (lang::IndexOutOfBoundsException, uno::RuntimeException)
+{
+ sal_Int32 nExtend = -1;
+
+ SolarMutexGuard aGuard;
+
+ CHECK_FOR_DEFUNC( XAccessibleTable )
+
+ GetTableData().CheckRowAndCol( nRow, nColumn, this );
+
+ Int32Set_Impl::const_iterator aSttCol(
+ GetTableData().GetColumnIter( nColumn ) );
+ Int32Set_Impl::const_iterator aSttRow(
+ GetTableData().GetRowIter( nRow ) );
+ const SwFrm *pCellFrm = GetTableData().GetCellAtPos( *aSttCol, *aSttRow,
+ sal_False );
+ if( pCellFrm )
+ {
+ sal_Int32 nBottom = pCellFrm->Frm().Bottom();
+ nBottom -= GetFrm()->Frm().Top();
+ Int32Set_Impl::const_iterator aEndRow(
+ GetTableData().GetRows().upper_bound( nBottom ) );
+ nExtend =
+ static_cast< sal_Int32 >( ::std::distance( aSttRow, aEndRow ) );
+ }
+
+ return nExtend;
+}
+
+sal_Int32 SAL_CALL SwAccessibleTable::getAccessibleColumnExtentAt(
+ sal_Int32 nRow, sal_Int32 nColumn )
+ throw (lang::IndexOutOfBoundsException, uno::RuntimeException)
+{
+ sal_Int32 nExtend = -1;
+
+ SolarMutexGuard aGuard;
+
+ CHECK_FOR_DEFUNC( XAccessibleTable )
+
+ GetTableData().CheckRowAndCol( nRow, nColumn, this );
+
+ Int32Set_Impl::const_iterator aSttCol(
+ GetTableData().GetColumnIter( nColumn ) );
+ Int32Set_Impl::const_iterator aSttRow(
+ GetTableData().GetRowIter( nRow ) );
+ const SwFrm *pCellFrm = GetTableData().GetCellAtPos( *aSttCol, *aSttRow,
+ sal_False );
+ if( pCellFrm )
+ {
+ sal_Int32 nRight = pCellFrm->Frm().Right();
+ nRight -= GetFrm()->Frm().Left();
+ Int32Set_Impl::const_iterator aEndCol(
+ GetTableData().GetColumns().upper_bound( nRight ) );
+ nExtend =
+ static_cast< sal_Int32 >( ::std::distance( aSttCol, aEndCol ) );
+ }
+
+ return nExtend;
+}
+
+uno::Reference< XAccessibleTable > SAL_CALL
+ SwAccessibleTable::getAccessibleRowHeaders( )
+ throw (uno::RuntimeException)
+{
+ // Row headers aren't supported
+ return uno::Reference< XAccessibleTable >();
+}
+
+uno::Reference< XAccessibleTable > SAL_CALL
+ SwAccessibleTable::getAccessibleColumnHeaders( )
+ throw (uno::RuntimeException)
+{
+ // #i87532# - assure that return accesible object is empty,
+ // if no column header exists.
+ SwAccessibleTableColHeaders* pTableColHeaders =
+ new SwAccessibleTableColHeaders( GetMap(), static_cast< const SwTabFrm *>( GetFrm() ) );
+ uno::Reference< XAccessibleTable > xTableColumnHeaders( pTableColHeaders );
+ if ( pTableColHeaders->getAccessibleChildCount() <= 0 )
+ {
+ return uno::Reference< XAccessibleTable >();
+ }
+
+ return xTableColumnHeaders;
+ // <--
+}
+
+uno::Sequence< sal_Int32 > SAL_CALL SwAccessibleTable::getSelectedAccessibleRows()
+ throw (uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+
+ CHECK_FOR_DEFUNC( XAccessibleTable )
+
+ const SwSelBoxes *pSelBoxes = GetSelBoxes();
+ if( pSelBoxes )
+ {
+ sal_Int32 nRows = GetTableData().GetRowCount();
+ SwAccAllTableSelHander_Impl aSelRows( nRows );
+
+ GetTableData().GetSelection( 0, nRows, *pSelBoxes, aSelRows,
+ sal_False );
+
+ return aSelRows.GetSelSequence();
+ }
+ else
+ {
+ return uno::Sequence< sal_Int32 >( 0 );
+ }
+}
+
+uno::Sequence< sal_Int32 > SAL_CALL SwAccessibleTable::getSelectedAccessibleColumns()
+ throw (uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+
+ CHECK_FOR_DEFUNC( XAccessibleTable )
+
+ const SwSelBoxes *pSelBoxes = GetSelBoxes();
+ if( pSelBoxes )
+ {
+ sal_Int32 nCols = GetTableData().GetColumnCount();
+ SwAccAllTableSelHander_Impl aSelCols( nCols );
+
+ GetTableData().GetSelection( 0, nCols, *pSelBoxes, aSelCols, sal_True );
+
+ return aSelCols.GetSelSequence();
+ }
+ else
+ {
+ return uno::Sequence< sal_Int32 >( 0 );
+ }
+}
+
+sal_Bool SAL_CALL SwAccessibleTable::isAccessibleRowSelected( sal_Int32 nRow )
+ throw (lang::IndexOutOfBoundsException, uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+
+ CHECK_FOR_DEFUNC( XAccessibleTable )
+
+ GetTableData().CheckRowAndCol( nRow, 0, this );
+
+ sal_Bool bRet;
+ const SwSelBoxes *pSelBoxes = GetSelBoxes();
+ if( pSelBoxes )
+ {
+ SwAccSingleTableSelHander_Impl aSelRow;
+ GetTableData().GetSelection( nRow, nRow+1, *pSelBoxes, aSelRow,
+ sal_False );
+ bRet = aSelRow.IsSelected();
+ }
+ else
+ {
+ bRet = sal_False;
+ }
+
+ return bRet;
+}
+
+sal_Bool SAL_CALL SwAccessibleTable::isAccessibleColumnSelected(
+ sal_Int32 nColumn )
+ throw (lang::IndexOutOfBoundsException, uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+
+ CHECK_FOR_DEFUNC( XAccessibleTable )
+
+ GetTableData().CheckRowAndCol( 0, nColumn, this );
+
+ sal_Bool bRet;
+ const SwSelBoxes *pSelBoxes = GetSelBoxes();
+ if( pSelBoxes )
+ {
+ SwAccSingleTableSelHander_Impl aSelCol;
+
+ GetTableData().GetSelection( nColumn, nColumn+1, *pSelBoxes, aSelCol,
+ sal_True );
+ bRet = aSelCol.IsSelected();
+ }
+ else
+ {
+ bRet = sal_False;
+ }
+
+ return bRet;
+}
+
+uno::Reference< XAccessible > SAL_CALL SwAccessibleTable::getAccessibleCellAt(
+ sal_Int32 nRow, sal_Int32 nColumn )
+ throw (lang::IndexOutOfBoundsException, uno::RuntimeException)
+{
+ uno::Reference< XAccessible > xRet;
+
+ SolarMutexGuard aGuard;
+
+ CHECK_FOR_DEFUNC( XAccessibleTable )
+
+ const SwFrm *pCellFrm =
+ GetTableData().GetCell( nRow, nColumn, sal_False, this );
+ if( pCellFrm )
+ xRet = GetMap()->GetContext( pCellFrm, sal_True );
+
+ return xRet;
+}
+
+uno::Reference< XAccessible > SAL_CALL SwAccessibleTable::getAccessibleCaption()
+ throw (uno::RuntimeException)
+{
+ // captions aren't supported
+ return uno::Reference< XAccessible >();
+}
+
+uno::Reference< XAccessible > SAL_CALL SwAccessibleTable::getAccessibleSummary()
+ throw (uno::RuntimeException)
+{
+ // summaries aren't supported
+ return uno::Reference< XAccessible >();
+}
+
+sal_Bool SAL_CALL SwAccessibleTable::isAccessibleSelected(
+ sal_Int32 nRow, sal_Int32 nColumn )
+ throw (lang::IndexOutOfBoundsException, uno::RuntimeException)
+{
+ sal_Bool bRet = sal_False;
+
+ SolarMutexGuard aGuard;
+
+ CHECK_FOR_DEFUNC( XAccessibleTable )
+
+ const SwFrm *pFrm =
+ GetTableData().GetCell( nRow, nColumn, sal_False, this );
+ if( pFrm && pFrm->IsCellFrm() )
+ {
+ const SwSelBoxes *pSelBoxes = GetSelBoxes();
+ if( pSelBoxes )
+ {
+ const SwCellFrm *pCFrm = static_cast < const SwCellFrm * >( pFrm );
+ SwTableBox *pBox =
+ const_cast< SwTableBox *>( pCFrm->GetTabBox() ); //SVPtrArr!
+ bRet = pSelBoxes->Seek_Entry( pBox );
+ }
+ }
+
+ return bRet;
+}
+
+sal_Int32 SAL_CALL SwAccessibleTable::getAccessibleIndex(
+ sal_Int32 nRow, sal_Int32 nColumn )
+ throw (lang::IndexOutOfBoundsException, uno::RuntimeException)
+{
+ sal_Int32 nRet = -1;
+
+ SolarMutexGuard aGuard;
+
+ CHECK_FOR_DEFUNC( XAccessibleTable )
+
+ SwAccessibleChild aCell( GetTableData().GetCell( nRow, nColumn, sal_False, this ));
+ if ( aCell.IsValid() )
+ {
+ nRet = GetChildIndex( *(GetMap()), aCell );
+ }
+
+ return nRet;
+}
+
+sal_Int32 SAL_CALL SwAccessibleTable::getAccessibleRow( sal_Int32 nChildIndex )
+ throw (lang::IndexOutOfBoundsException, uno::RuntimeException)
+{
+ sal_Int32 nRet = -1;
+
+ SolarMutexGuard aGuard;
+
+ CHECK_FOR_DEFUNC( XAccessibleTable )
+
+ // #i77106#
+ if ( ( nChildIndex < 0 ) ||
+ ( nChildIndex >= getAccessibleChildCount() ) )
+ {
+ throw lang::IndexOutOfBoundsException();
+ }
+ // <--
+
+ SwAccessibleChild aCell( GetChild( *(GetMap()), nChildIndex ) );
+ if ( aCell.GetSwFrm() )
+ {
+ sal_Int32 nTop = aCell.GetSwFrm()->Frm().Top();
+ nTop -= GetFrm()->Frm().Top();
+ Int32Set_Impl::const_iterator aRow(
+ GetTableData().GetRows().lower_bound( nTop ) );
+ nRet = static_cast< sal_Int32 >( ::std::distance(
+ GetTableData().GetRows().begin(), aRow ) );
+ }
+ else
+ {
+ OSL_ENSURE( !aCell.IsValid(), "SwAccessibleTable::getAccessibleColumn:"
+ "aCell not expected to be valid.");
+
+ throw lang::IndexOutOfBoundsException();
+ }
+
+ return nRet;
+}
+
+sal_Int32 SAL_CALL SwAccessibleTable::getAccessibleColumn(
+ sal_Int32 nChildIndex )
+ throw (lang::IndexOutOfBoundsException, uno::RuntimeException)
+{
+ sal_Int32 nRet = -1;
+
+ SolarMutexGuard aGuard;
+
+ CHECK_FOR_DEFUNC( XAccessibleTable )
+
+ // #i77106#
+ if ( ( nChildIndex < 0 ) ||
+ ( nChildIndex >= getAccessibleChildCount() ) )
+ {
+ throw lang::IndexOutOfBoundsException();
+ }
+ // <--
+
+ SwAccessibleChild aCell( GetChild( *(GetMap()), nChildIndex ) );
+ if ( aCell.GetSwFrm() )
+ {
+ sal_Int32 nLeft = aCell.GetSwFrm()->Frm().Left();
+ nLeft -= GetFrm()->Frm().Left();
+ Int32Set_Impl::const_iterator aCol(
+ GetTableData().GetColumns().lower_bound( nLeft ) );
+ nRet = static_cast< sal_Int32 >( ::std::distance(
+ GetTableData().GetColumns().begin(), aCol ) );
+ }
+ else
+ {
+ OSL_ENSURE( !aCell.IsValid(), "SwAccessibleTable::getAccessibleColumn:"
+ "aCell not expected to be valid.");
+
+ throw lang::IndexOutOfBoundsException();
+ }
+
+ return nRet;
+}
+
+
+OUString SAL_CALL SwAccessibleTable::getImplementationName()
+ throw( uno::RuntimeException )
+{
+ return OUString(RTL_CONSTASCII_USTRINGPARAM(sImplementationName));
+}
+
+sal_Bool SAL_CALL SwAccessibleTable::supportsService(
+ const OUString& sTestServiceName)
+ throw (uno::RuntimeException)
+{
+ return sTestServiceName.equalsAsciiL( sServiceName,
+ sizeof(sServiceName)-1 ) ||
+ sTestServiceName.equalsAsciiL( sAccessibleServiceName,
+ sizeof(sAccessibleServiceName)-1 );
+}
+
+uno::Sequence< OUString > SAL_CALL SwAccessibleTable::getSupportedServiceNames()
+ throw( uno::RuntimeException )
+{
+ uno::Sequence< OUString > aRet(2);
+ OUString* pArray = aRet.getArray();
+ pArray[0] = OUString( RTL_CONSTASCII_USTRINGPARAM(sServiceName) );
+ pArray[1] = OUString( RTL_CONSTASCII_USTRINGPARAM(sAccessibleServiceName) );
+ return aRet;
+}
+
+void SwAccessibleTable::InvalidatePosOrSize( const SwRect& rOldBox )
+{
+ SolarMutexGuard aGuard;
+
+ if( HasTableData() )
+ GetTableData().SetTablePos( GetFrm()->Frm().Pos() );
+
+ SwAccessibleContext::InvalidatePosOrSize( rOldBox );
+}
+
+void SwAccessibleTable::Dispose( sal_Bool bRecursive )
+{
+ SolarMutexGuard aGuard;
+
+ if( GetRegisteredIn() )
+ GetRegisteredInNonConst()->Remove( this );
+
+ SwAccessibleContext::Dispose( bRecursive );
+}
+
+void SwAccessibleTable::DisposeChild( const SwAccessibleChild& rChildFrmOrObj,
+ sal_Bool bRecursive )
+{
+ SolarMutexGuard aGuard;
+
+ const SwFrm *pFrm = rChildFrmOrObj.GetSwFrm();
+ OSL_ENSURE( pFrm, "frame expected" );
+ if( HasTableData() )
+ {
+ FireTableChangeEvent( GetTableData() );
+ ClearTableData();
+ }
+
+ // There are two reason why this method has been called. The first one
+ // is there is no context for pFrm. The method is them called by
+ // the map, and we have to call our superclass.
+ // The other situation is that we have been call by a call to get notified
+ // about its change. We then must not call the superclass
+ uno::Reference< XAccessible > xAcc( GetMap()->GetContext( pFrm, sal_False ) );
+ if( !xAcc.is() )
+ SwAccessibleContext::DisposeChild( rChildFrmOrObj, bRecursive );
+}
+
+void SwAccessibleTable::InvalidateChildPosOrSize( const SwAccessibleChild& rChildFrmOrObj,
+ const SwRect& rOldBox )
+{
+ SolarMutexGuard aGuard;
+
+ if( HasTableData() )
+ {
+ OSL_ENSURE( !HasTableData() ||
+ GetFrm()->Frm().Pos() == GetTableData().GetTablePos(),
+ "table has invalid position" );
+ if( HasTableData() )
+ {
+ SwAccessibleTableData_Impl *pNewTableData = CreateNewTableData(); // #i77106#
+ if( !pNewTableData->CompareExtents( GetTableData() ) )
+ {
+ FireTableChangeEvent( GetTableData() );
+ ClearTableData();
+ mpTableData = pNewTableData;
+ }
+ else
+ {
+ delete pNewTableData;
+ }
+ }
+ }
+
+ // #i013961# - always call super class method
+ SwAccessibleContext::InvalidateChildPosOrSize( rChildFrmOrObj, rOldBox );
+}
+
+
+//
+// XAccessibleSelection
+//
+
+void SAL_CALL SwAccessibleTable::selectAccessibleChild(
+ sal_Int32 nChildIndex )
+ throw ( lang::IndexOutOfBoundsException, uno::RuntimeException )
+{
+ SolarMutexGuard aGuard;
+ CHECK_FOR_DEFUNC( XAccessibleTable );
+
+ if( (nChildIndex < 0) || (nChildIndex >= getAccessibleChildCount()) ) // #i77106#
+ throw lang::IndexOutOfBoundsException();
+
+ // preliminaries: get 'our' table box, and get the cursor shell
+ const SwTableBox* pBox = GetTableBox( nChildIndex );
+ DBG_ASSERT( pBox != NULL, "We need the table box." );
+
+ SwCrsrShell* pCrsrShell = GetCrsrShell();
+ if( pCrsrShell == NULL )
+ return;
+
+ // assure, that child, indentified by the given index, isn't already selected.
+ if ( IsChildSelected( nChildIndex ) )
+ {
+ return;
+ }
+
+ // now we can start to do the work: check whether we already have
+ // a table selection (in 'our' table). If so, extend the
+ // selection, else select the current cell.
+
+ // if we have a selection in a table, check if it's in the
+ // same table that we're trying to select in
+ const SwTableNode* pSelectedTable = pCrsrShell->IsCrsrInTbl();
+ if( pSelectedTable != NULL )
+ {
+ // get top-most table line
+ const SwTableLine* pUpper = pBox->GetUpper();
+ while( pUpper->GetUpper() != NULL )
+ pUpper = pUpper->GetUpper()->GetUpper();
+ sal_uInt16 nPos =
+ pSelectedTable->GetTable().GetTabLines().GetPos( pUpper );
+ if( nPos == USHRT_MAX )
+ pSelectedTable = NULL;
+ }
+
+ // create the new selection
+ const SwStartNode* pStartNode = pBox->GetSttNd();
+ if( pSelectedTable == NULL || !pCrsrShell->GetTblCrs() )
+ {
+ pCrsrShell->StartAction();
+ // Set cursor into current cell. This deletes any table cursor.
+ SwPaM aPaM( *pStartNode );
+ aPaM.Move( fnMoveForward, fnGoNode );
+ Select( aPaM );
+ // Move cursor to the end of the table creating a selection and a table
+ // cursor.
+ pCrsrShell->SetMark();
+ pCrsrShell->MoveTable( fnTableCurr, fnTableEnd );
+ // now set the cursor into the cell again.
+ SwPaM *pPaM = pCrsrShell->GetTblCrs() ? pCrsrShell->GetTblCrs()
+ : pCrsrShell->GetCrsr();
+ *pPaM->GetPoint() = *pPaM->GetMark();
+ pCrsrShell->EndAction();
+ // we now have one cell selected!
+ }
+ else
+ {
+ // if the cursor is already in this table,
+ // expand the current selection (i.e., set
+ // point to new position; keep mark)
+ SwPaM aPaM( *pStartNode );
+ aPaM.Move( fnMoveForward, fnGoNode );
+ aPaM.SetMark();
+ const SwPaM *pPaM = pCrsrShell->GetTblCrs() ? pCrsrShell->GetTblCrs()
+ : pCrsrShell->GetCrsr();
+ *(aPaM.GetMark()) = *pPaM->GetMark();
+ Select( aPaM );
+
+ }
+}
+
+
+sal_Bool SAL_CALL SwAccessibleTable::isAccessibleChildSelected(
+ sal_Int32 nChildIndex )
+ throw ( lang::IndexOutOfBoundsException,
+ uno::RuntimeException )
+{
+ SolarMutexGuard aGuard;
+ CHECK_FOR_DEFUNC( XAccessibleTable );
+
+ if( (nChildIndex < 0) || (nChildIndex >= getAccessibleChildCount()) ) // #i77106#
+ throw lang::IndexOutOfBoundsException();
+
+ return IsChildSelected( nChildIndex );
+}
+
+void SAL_CALL SwAccessibleTable::clearAccessibleSelection( )
+ throw ( uno::RuntimeException )
+{
+ SolarMutexGuard aGuard;
+
+ CHECK_FOR_DEFUNC( XAccessibleTable );
+
+ SwCrsrShell* pCrsrShell = GetCrsrShell();
+ if( pCrsrShell != NULL )
+ {
+ pCrsrShell->StartAction();
+ pCrsrShell->ClearMark();
+ pCrsrShell->EndAction();
+ }
+}
+
+void SAL_CALL SwAccessibleTable::selectAllAccessibleChildren( )
+ throw ( uno::RuntimeException )
+{
+ // first clear selection, then select first and last child
+ clearAccessibleSelection();
+ selectAccessibleChild( 0 );
+ selectAccessibleChild( getAccessibleChildCount()-1 ); // #i77106#
+}
+
+sal_Int32 SAL_CALL SwAccessibleTable::getSelectedAccessibleChildCount( )
+ throw ( uno::RuntimeException )
+{
+ SolarMutexGuard aGuard;
+ CHECK_FOR_DEFUNC( XAccessibleTable );
+
+ // iterate over all children and count isAccessibleChildSelected()
+ sal_Int32 nCount = 0;
+
+ sal_Int32 nChildren = getAccessibleChildCount(); // #i71106#
+ for( sal_Int32 n = 0; n < nChildren; n++ )
+ if( IsChildSelected( n ) )
+ nCount++;
+
+ return nCount;
+}
+
+uno::Reference<XAccessible> SAL_CALL SwAccessibleTable::getSelectedAccessibleChild(
+ sal_Int32 nSelectedChildIndex )
+ throw ( lang::IndexOutOfBoundsException,
+ uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+ CHECK_FOR_DEFUNC( XAccessibleTable );
+
+ // paremter checking (part 1): index lower 0
+ if( nSelectedChildIndex < 0 )
+ throw lang::IndexOutOfBoundsException();
+
+ sal_Int32 nChildIndex = GetIndexOfSelectedChild( nSelectedChildIndex );
+
+ // parameter checking (part 2): index higher than selected children?
+ if( nChildIndex < 0 )
+ throw lang::IndexOutOfBoundsException();
+
+ // #i77106#
+ if ( nChildIndex >= getAccessibleChildCount() )
+ {
+ throw lang::IndexOutOfBoundsException();
+ }
+
+ return getAccessibleChild( nChildIndex );
+}
+
+// index has to be treated as global child index.
+void SAL_CALL SwAccessibleTable::deselectAccessibleChild(
+ sal_Int32 nChildIndex )
+ throw ( lang::IndexOutOfBoundsException,
+ uno::RuntimeException )
+{
+ SolarMutexGuard aGuard;
+ CHECK_FOR_DEFUNC( XAccessibleTable );
+
+ SwCrsrShell* pCrsrShell = GetCrsrShell();
+
+ // index has to be treated as global child index
+ if ( !pCrsrShell )
+ throw lang::IndexOutOfBoundsException();
+
+ // assure, that given child index is in bounds.
+ if ( nChildIndex < 0 || nChildIndex >= getAccessibleChildCount() ) // #i77106#
+ throw lang::IndexOutOfBoundsException();
+
+ // assure, that child, identified by the given index, is selected.
+ if ( !IsChildSelected( nChildIndex ) )
+ return;
+ // <--
+
+ const SwTableBox* pBox = GetTableBox( nChildIndex );
+ DBG_ASSERT( pBox != NULL, "We need the table box." );
+
+ // If we unselect point, then set cursor to mark. If we clear another
+ // selected box, then set cursor to point.
+ // reduce selection to mark.
+ SwPaM *pPaM = pCrsrShell->GetTblCrs() ? pCrsrShell->GetTblCrs()
+ : pCrsrShell->GetCrsr();
+ sal_Bool bDeselectPoint =
+ pBox->GetSttNd() ==
+ pPaM->GetPoint()->nNode.GetNode().FindTableBoxStartNode();
+
+ SwPaM aPaM( bDeselectPoint ? *pPaM->GetMark() : *pPaM->GetPoint() );
+
+ pCrsrShell->StartAction();
+
+ // Set cursor into either point or mark
+ Select( aPaM );
+ // Move cursor to the end of the table creating a selection and a table
+ // cursor.
+ pCrsrShell->SetMark();
+ pCrsrShell->MoveTable( fnTableCurr, fnTableEnd );
+ // now set the cursor into the cell again.
+ pPaM = pCrsrShell->GetTblCrs() ? pCrsrShell->GetTblCrs()
+ : pCrsrShell->GetCrsr();
+ *pPaM->GetPoint() = *pPaM->GetMark();
+ pCrsrShell->EndAction();
+}
+
+// #i77106# - implementation of class <SwAccessibleTableColHeaders>
+SwAccessibleTableColHeaders::SwAccessibleTableColHeaders( SwAccessibleMap *pMap2,
+ const SwTabFrm *pTabFrm )
+ : SwAccessibleTable( pMap2, pTabFrm )
+{
+ SolarMutexGuard aGuard;
+
+ const SwFrmFmt *pFrmFmt = pTabFrm->GetFmt();
+ const_cast< SwFrmFmt * >( pFrmFmt )->Add( this );
+ const String& rName = pFrmFmt->GetName();
+
+ OUStringBuffer aBuffer( rName.Len() + 15 + 6 );
+ aBuffer.append( OUString(rName) );
+ aBuffer.append( String::CreateFromAscii("-ColumnHeaders-") );
+ aBuffer.append( static_cast<sal_Int32>( pTabFrm->GetPhyPageNum() ) );
+
+ SetName( aBuffer.makeStringAndClear() );
+
+ OUStringBuffer aBuffer2( rName.Len() + 14 );
+ aBuffer2.append( OUString(rName) );
+ aBuffer2.append( String::CreateFromAscii("-ColumnHeaders") );
+ OUString sArg1( aBuffer2.makeStringAndClear() );
+ OUString sArg2( GetFormattedPageNumber() );
+
+ OUString sDesc2 = GetResource( STR_ACCESS_TABLE_DESC, &sArg1, &sArg2 );
+ SetDesc( sDesc2 );
+
+ NotRegisteredAtAccessibleMap(); // #i85634#
+}
+
+SwAccessibleTableData_Impl* SwAccessibleTableColHeaders::CreateNewTableData()
+{
+ const SwTabFrm* pTabFrm = static_cast<const SwTabFrm*>( GetFrm() );
+ return new SwAccessibleTableData_Impl( *(GetMap()), pTabFrm, IsInPagePreview(), true );
+}
+
+
+void SwAccessibleTableColHeaders::Modify( const SfxPoolItem * /*pOld*/, const SfxPoolItem * /*pNew*/ )
+{
+}
+
+//===== XInterface ======================================================
+uno::Any SAL_CALL SwAccessibleTableColHeaders::queryInterface( const uno::Type& aType )
+ throw (uno::RuntimeException)
+{
+ return SwAccessibleTable::queryInterface( aType );
+}
+
+//===== XAccessibleContext ==============================================
+sal_Int32 SAL_CALL SwAccessibleTableColHeaders::getAccessibleChildCount(void)
+ throw (uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+
+ CHECK_FOR_DEFUNC( XAccessibleContext )
+
+ sal_Int32 nCount = 0;
+
+ const SwTabFrm* pTabFrm = static_cast<const SwTabFrm*>( GetFrm() );
+ const SwAccessibleChildSList aVisList( GetVisArea(), *pTabFrm, *(GetMap()) );
+ SwAccessibleChildSList::const_iterator aIter( aVisList.begin() );
+ while( aIter != aVisList.end() )
+ {
+ const SwAccessibleChild& rLower = *aIter;
+ if( rLower.IsAccessible( IsInPagePreview() ) )
+ {
+ nCount++;
+ }
+ else if( rLower.GetSwFrm() )
+ {
+ // There are no unaccessible SdrObjects that count
+ if ( !rLower.GetSwFrm()->IsRowFrm() ||
+ pTabFrm->IsInHeadline( *(rLower.GetSwFrm()) ) )
+ {
+ nCount += SwAccessibleFrame::GetChildCount( *(GetMap()),
+ GetVisArea(),
+ rLower.GetSwFrm(),
+ IsInPagePreview() );
+ }
+ }
+ ++aIter;
+ }
+
+ return nCount;
+}
+
+uno::Reference< XAccessible> SAL_CALL
+ SwAccessibleTableColHeaders::getAccessibleChild (sal_Int32 nIndex)
+ throw (uno::RuntimeException, lang::IndexOutOfBoundsException)
+{
+ if ( nIndex < 0 || nIndex >= getAccessibleChildCount() )
+ {
+ throw lang::IndexOutOfBoundsException();
+ }
+
+ return SwAccessibleTable::getAccessibleChild( nIndex );
+}
+
+//===== XAccessibleTable ================================================
+uno::Reference< XAccessibleTable >
+ SAL_CALL SwAccessibleTableColHeaders::getAccessibleRowHeaders()
+ throw (uno::RuntimeException)
+{
+ return uno::Reference< XAccessibleTable >();
+}
+
+uno::Reference< XAccessibleTable >
+ SAL_CALL SwAccessibleTableColHeaders::getAccessibleColumnHeaders()
+ throw (uno::RuntimeException)
+{
+ return uno::Reference< XAccessibleTable >();
+}
+
+//===== XServiceInfo ====================================================
+
+::rtl::OUString SAL_CALL SwAccessibleTableColHeaders::getImplementationName (void)
+ throw (uno::RuntimeException)
+{
+ static const sal_Char sImplName[] = "com.sun.star.comp.Writer.SwAccessibleTableColumnHeadersView";
+ return OUString(RTL_CONSTASCII_USTRINGPARAM(sImplName));
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/access/acctable.hxx b/sw/source/core/access/acctable.hxx
new file mode 100644
index 000000000000..491ba5c4416d
--- /dev/null
+++ b/sw/source/core/access/acctable.hxx
@@ -0,0 +1,331 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+#ifndef _ACCTABLE_HXX
+#define _ACCTABLE_HXX
+#include <com/sun/star/accessibility/XAccessibleTable.hpp>
+#include <com/sun/star/accessibility/XAccessibleSelection.hpp>
+
+#include <acccontext.hxx>
+
+class SwTabFrm;
+class SwAccessibleTableData_Impl;
+class SwTableBox;
+class SwSelBoxes;
+
+namespace sw { namespace access {
+ class SwAccessibleChild;
+} }
+
+class SwAccessibleTable :
+ public SwAccessibleContext,
+ public ::com::sun::star::accessibility::XAccessibleTable,
+ public ::com::sun::star::accessibility::XAccessibleSelection,
+ public SwClient
+{
+ SwAccessibleTableData_Impl *mpTableData; // the table's data, prot by Sol-Mutex
+ ::rtl::OUString sDesc;
+ const SwSelBoxes *GetSelBoxes() const;
+
+ void FireTableChangeEvent( const SwAccessibleTableData_Impl& rTableData );
+
+ /** get the SwTableBox* for the given child */
+ const SwTableBox* GetTableBox( sal_Int32 ) const;
+
+ sal_Bool IsChildSelected( sal_Int32 nChildIndex ) const;
+
+ sal_Int32 GetIndexOfSelectedChild( sal_Int32 nSelectedChildIndex ) const;
+
+protected:
+
+ // Set states for getAccessibleStateSet.
+ // This drived class additinaly sets MULTISELECTABLE(+)
+ virtual void GetStates( ::utl::AccessibleStateSetHelper& rStateSet );
+
+ virtual ~SwAccessibleTable();
+
+ // #i77106#
+ inline void SetDesc( ::rtl::OUString sNewDesc )
+ {
+ sDesc = sNewDesc;
+ }
+
+ virtual SwAccessibleTableData_Impl* CreateNewTableData(); // #i77106#
+
+ // force update of table data
+ void UpdateTableData();
+
+ // remove the current table data
+ void ClearTableData();
+
+ // get table data, update if necessary
+ inline SwAccessibleTableData_Impl& GetTableData();
+
+ // Is table data evailable?
+ sal_Bool HasTableData() const { return (mpTableData != 0); }
+
+ virtual void Modify( const SfxPoolItem* pOld, const SfxPoolItem *pNew);
+
+public:
+
+ SwAccessibleTable( SwAccessibleMap* pInitMap, const SwTabFrm* pTableFrm );
+
+ //===== XInterface ======================================================
+
+ // (XInterface methods need to be implemented to disambigouate
+ // between those inherited through SwAcessibleContext and
+ // XAccessibleTable).
+
+ virtual ::com::sun::star::uno::Any SAL_CALL queryInterface(
+ const ::com::sun::star::uno::Type& aType )
+ throw (::com::sun::star::uno::RuntimeException);
+
+ virtual void SAL_CALL acquire( ) throw ()
+ { SwAccessibleContext::acquire(); };
+
+ virtual void SAL_CALL release( ) throw ()
+ { SwAccessibleContext::release(); };
+
+ //====== XTypeProvider ====================================================
+ virtual ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Type > SAL_CALL getTypes( ) throw(::com::sun::star::uno::RuntimeException);
+ virtual ::com::sun::star::uno::Sequence< sal_Int8 > SAL_CALL getImplementationId( ) throw(::com::sun::star::uno::RuntimeException);
+
+ //===== XAccessibleContext ==============================================
+
+ /// Return this object's description.
+ virtual ::rtl::OUString SAL_CALL
+ getAccessibleDescription (void)
+ throw (com::sun::star::uno::RuntimeException);
+
+ //===== XAccessibleTable ================================================
+
+ virtual sal_Int32 SAL_CALL getAccessibleRowCount()
+ throw (::com::sun::star::uno::RuntimeException);
+ virtual sal_Int32 SAL_CALL getAccessibleColumnCount( )
+ throw (::com::sun::star::uno::RuntimeException);
+ virtual ::rtl::OUString SAL_CALL getAccessibleRowDescription(
+ sal_Int32 nRow )
+ throw (::com::sun::star::lang::IndexOutOfBoundsException,
+ ::com::sun::star::uno::RuntimeException);
+ virtual ::rtl::OUString SAL_CALL getAccessibleColumnDescription(
+ sal_Int32 nColumn )
+ throw (::com::sun::star::lang::IndexOutOfBoundsException,
+ ::com::sun::star::uno::RuntimeException);
+ virtual sal_Int32 SAL_CALL getAccessibleRowExtentAt(
+ sal_Int32 nRow, sal_Int32 nColumn )
+ throw (::com::sun::star::lang::IndexOutOfBoundsException,
+ ::com::sun::star::uno::RuntimeException);
+ virtual sal_Int32 SAL_CALL getAccessibleColumnExtentAt(
+ sal_Int32 nRow, sal_Int32 nColumn )
+ throw (::com::sun::star::lang::IndexOutOfBoundsException,
+ ::com::sun::star::uno::RuntimeException);
+ virtual ::com::sun::star::uno::Reference<
+ ::com::sun::star::accessibility::XAccessibleTable >
+ SAL_CALL getAccessibleRowHeaders( )
+ throw (::com::sun::star::uno::RuntimeException);
+ virtual ::com::sun::star::uno::Reference<
+ ::com::sun::star::accessibility::XAccessibleTable >
+ SAL_CALL getAccessibleColumnHeaders( )
+ throw (::com::sun::star::uno::RuntimeException);
+ virtual ::com::sun::star::uno::Sequence< sal_Int32 > SAL_CALL
+ getSelectedAccessibleRows( )
+ throw (::com::sun::star::uno::RuntimeException);
+ virtual ::com::sun::star::uno::Sequence< sal_Int32 > SAL_CALL
+ getSelectedAccessibleColumns( )
+ throw (::com::sun::star::uno::RuntimeException);
+ virtual sal_Bool SAL_CALL isAccessibleRowSelected( sal_Int32 nRow )
+ throw (::com::sun::star::lang::IndexOutOfBoundsException,
+ ::com::sun::star::uno::RuntimeException);
+ virtual sal_Bool SAL_CALL isAccessibleColumnSelected( sal_Int32 nColumn )
+ throw (::com::sun::star::lang::IndexOutOfBoundsException,
+ ::com::sun::star::uno::RuntimeException);
+ virtual ::com::sun::star::uno::Reference<
+ ::com::sun::star::accessibility::XAccessible > SAL_CALL
+ getAccessibleCellAt( sal_Int32 nRow, sal_Int32 nColumn )
+ throw (::com::sun::star::lang::IndexOutOfBoundsException,
+ ::com::sun::star::uno::RuntimeException);
+ virtual ::com::sun::star::uno::Reference<
+ ::com::sun::star::accessibility::XAccessible > SAL_CALL
+ getAccessibleCaption( )
+ throw (::com::sun::star::uno::RuntimeException);
+ virtual ::com::sun::star::uno::Reference<
+ ::com::sun::star::accessibility::XAccessible > SAL_CALL
+ getAccessibleSummary( )
+ throw (::com::sun::star::uno::RuntimeException);
+ virtual sal_Bool SAL_CALL isAccessibleSelected(
+ sal_Int32 nRow, sal_Int32 nColumn )
+ throw (::com::sun::star::lang::IndexOutOfBoundsException,
+ ::com::sun::star::uno::RuntimeException);
+ virtual sal_Int32 SAL_CALL getAccessibleIndex(
+ sal_Int32 nRow, sal_Int32 nColumn )
+ throw (::com::sun::star::lang::IndexOutOfBoundsException,
+ ::com::sun::star::uno::RuntimeException);
+ virtual sal_Int32 SAL_CALL getAccessibleRow( sal_Int32 nChildIndex )
+ throw (::com::sun::star::lang::IndexOutOfBoundsException,
+ ::com::sun::star::uno::RuntimeException);
+ virtual sal_Int32 SAL_CALL getAccessibleColumn( sal_Int32 nChildIndex )
+ throw (::com::sun::star::lang::IndexOutOfBoundsException,
+ ::com::sun::star::uno::RuntimeException);
+
+ //===== XServiceInfo ====================================================
+
+ /** Returns an identifier for the implementation of this object.
+ */
+ virtual ::rtl::OUString SAL_CALL
+ getImplementationName (void)
+ throw (::com::sun::star::uno::RuntimeException);
+
+ /** Return whether the specified service is supported by this class.
+ */
+ virtual sal_Bool SAL_CALL
+ supportsService (const ::rtl::OUString& sServiceName)
+ throw (::com::sun::star::uno::RuntimeException);
+
+ /** Returns a list of all supported services. In this case that is just
+ the AccessibleContext service.
+ */
+ virtual ::com::sun::star::uno::Sequence< ::rtl::OUString> SAL_CALL
+ getSupportedServiceNames (void)
+ throw (::com::sun::star::uno::RuntimeException);
+
+ //===== C++ interface ======================================================
+
+ // The object has been moved by the layout
+ virtual void InvalidatePosOrSize( const SwRect& rOldBox );
+
+ // The object is not visible an longer and should be destroyed
+ virtual void Dispose( sal_Bool bRecursive = sal_False );
+
+ virtual void DisposeChild( const sw::access::SwAccessibleChild& rFrmOrObj,
+ sal_Bool bRecursive );
+ virtual void InvalidateChildPosOrSize( const sw::access::SwAccessibleChild& rFrmOrObj,
+ const SwRect& rFrm );
+
+ //===== XAccessibleSelection ============================================
+
+ virtual void SAL_CALL selectAccessibleChild(
+ sal_Int32 nChildIndex )
+ throw ( ::com::sun::star::lang::IndexOutOfBoundsException,
+ ::com::sun::star::uno::RuntimeException );
+
+ virtual sal_Bool SAL_CALL isAccessibleChildSelected(
+ sal_Int32 nChildIndex )
+ throw ( ::com::sun::star::lang::IndexOutOfBoundsException,
+ ::com::sun::star::uno::RuntimeException );
+
+ virtual void SAL_CALL clearAccessibleSelection( )
+ throw ( ::com::sun::star::uno::RuntimeException );
+
+ virtual void SAL_CALL selectAllAccessibleChildren( )
+ throw ( ::com::sun::star::uno::RuntimeException );
+
+ virtual sal_Int32 SAL_CALL getSelectedAccessibleChildCount( )
+ throw ( ::com::sun::star::uno::RuntimeException );
+
+ virtual ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible > SAL_CALL getSelectedAccessibleChild(
+ sal_Int32 nSelectedChildIndex )
+ throw ( ::com::sun::star::lang::IndexOutOfBoundsException,
+ ::com::sun::star::uno::RuntimeException);
+
+ // index has to be treated as global child index.
+ virtual void SAL_CALL deselectAccessibleChild(
+ sal_Int32 nChildIndex )
+ throw ( ::com::sun::star::lang::IndexOutOfBoundsException,
+ ::com::sun::star::uno::RuntimeException );
+
+};
+
+inline SwAccessibleTableData_Impl& SwAccessibleTable::GetTableData()
+{
+ if( !mpTableData )
+ UpdateTableData();
+ return *mpTableData;
+}
+
+// #i77106# - subclass to represent table column headers
+class SwAccessibleTableColHeaders : public SwAccessibleTable
+{
+protected:
+
+ virtual ~SwAccessibleTableColHeaders()
+ {}
+
+ virtual SwAccessibleTableData_Impl* CreateNewTableData();
+ virtual void Modify( const SfxPoolItem* pOld, const SfxPoolItem *pNew);
+
+public:
+
+ SwAccessibleTableColHeaders( SwAccessibleMap *pMap, const SwTabFrm *pTabFrm );
+
+ //===== XInterface ======================================================
+
+ virtual ::com::sun::star::uno::Any SAL_CALL queryInterface(
+ const ::com::sun::star::uno::Type& aType )
+ throw (::com::sun::star::uno::RuntimeException);
+
+ virtual void SAL_CALL acquire( ) throw ()
+ { SwAccessibleContext::acquire(); };
+
+ virtual void SAL_CALL release( ) throw ()
+ { SwAccessibleContext::release(); };
+
+ //===== XAccessibleContext ==============================================
+
+ /// Return the number of currently visible children.
+ virtual sal_Int32 SAL_CALL getAccessibleChildCount (void)
+ throw (::com::sun::star::uno::RuntimeException);
+
+ /// Return the specified child or NULL if index is invalid.
+ virtual ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible> SAL_CALL
+ getAccessibleChild (sal_Int32 nIndex)
+ throw (::com::sun::star::uno::RuntimeException,
+ ::com::sun::star::lang::IndexOutOfBoundsException);
+
+ //===== XAccessibleTable ================================================
+
+ virtual ::com::sun::star::uno::Reference<
+ ::com::sun::star::accessibility::XAccessibleTable >
+ SAL_CALL getAccessibleRowHeaders( )
+ throw (::com::sun::star::uno::RuntimeException);
+ virtual ::com::sun::star::uno::Reference<
+ ::com::sun::star::accessibility::XAccessibleTable >
+ SAL_CALL getAccessibleColumnHeaders( )
+ throw (::com::sun::star::uno::RuntimeException);
+
+ //===== XServiceInfo ====================================================
+
+ /** Returns an identifier for the implementation of this object.
+ */
+ virtual ::rtl::OUString SAL_CALL
+ getImplementationName (void)
+ throw (::com::sun::star::uno::RuntimeException);
+
+};
+// <--
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/access/acctextframe.cxx b/sw/source/core/access/acctextframe.cxx
new file mode 100644
index 000000000000..6d41322a7703
--- /dev/null
+++ b/sw/source/core/access/acctextframe.cxx
@@ -0,0 +1,278 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+ /*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+#include <com/sun/star/accessibility/XAccessibleContext.hpp>
+#include <rtl/uuid.h>
+#include <osl/mutex.hxx>
+#include <vcl/svapp.hxx>
+#include <com/sun/star/accessibility/AccessibleRole.hpp>
+#include <com/sun/star/accessibility/AccessibleStateType.hpp>
+#include <com/sun/star/accessibility/AccessibleRelation.hpp>
+#include <com/sun/star/accessibility/AccessibleRelationType.hpp>
+#include <com/sun/star/accessibility/XAccessibleRelationSet.hpp>
+#include <com/sun/star/accessibility/AccessibleEventId.hpp>
+#include <unotools/accessiblestatesethelper.hxx>
+#include <frmfmt.hxx>
+#include <flyfrm.hxx>
+#include <accmap.hxx>
+#include <unotools/accessiblerelationsethelper.hxx>
+#include <hints.hxx> // #i73249#
+#include "acctextframe.hxx"
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::accessibility;
+using ::rtl::OUString;
+
+using utl::AccessibleRelationSetHelper;
+using ::com::sun::star::accessibility::XAccessibleContext;
+
+const sal_Char sServiceName[] = "com.sun.star.text.AccessibleTextFrameView";
+const sal_Char sImplementationName[] = "com.sun.star.comp.Writer.SwAccessibleTextFrameView";
+
+SwAccessibleTextFrame::SwAccessibleTextFrame(
+ SwAccessibleMap* pInitMap,
+ const SwFlyFrm* pFlyFrm ) :
+ SwAccessibleFrameBase( pInitMap, AccessibleRole::TEXT_FRAME, pFlyFrm ),
+ msTitle(),
+ msDesc()
+{
+ if ( pFlyFrm )
+ {
+ const SwFlyFrmFmt* pFlyFrmFmt =
+ dynamic_cast<const SwFlyFrmFmt*>( pFlyFrm->GetFmt() );
+ msTitle = pFlyFrmFmt->GetObjTitle();
+
+ msDesc = pFlyFrmFmt->GetObjDescription();
+ if ( msDesc.getLength() == 0 &&
+ msTitle != GetName() )
+ {
+ msDesc = msTitle;
+ }
+ }
+}
+
+SwAccessibleTextFrame::~SwAccessibleTextFrame()
+{
+}
+
+void SwAccessibleTextFrame::Modify( const SfxPoolItem* pOld, const SfxPoolItem *pNew)
+{
+ const sal_uInt16 nWhich = pOld ? pOld->Which() : pNew ? pNew->Which() : 0 ;
+ // #i73249# - suppress handling of RES_NAME_CHANGED
+ // in case that attribute Title is used as the accessible name.
+ if ( nWhich != RES_NAME_CHANGED ||
+ msTitle.getLength() == 0 )
+ {
+ SwAccessibleFrameBase::Modify( pOld, pNew );
+ }
+
+ const SwFlyFrm *pFlyFrm = static_cast< const SwFlyFrm * >( GetFrm() );
+ switch( nWhich )
+ {
+ // #i73249#
+ case RES_TITLE_CHANGED:
+ {
+ const String& sOldTitle(
+ dynamic_cast<const SwStringMsgPoolItem*>(pOld)->GetString() );
+ const String& sNewTitle(
+ dynamic_cast<const SwStringMsgPoolItem*>(pNew)->GetString() );
+ if ( sOldTitle == sNewTitle )
+ {
+ break;
+ }
+ msTitle = sNewTitle;
+ AccessibleEventObject aEvent;
+ aEvent.EventId = AccessibleEventId::NAME_CHANGED;
+ aEvent.OldValue <<= OUString( sOldTitle );
+ aEvent.NewValue <<= msTitle;
+ FireAccessibleEvent( aEvent );
+
+ const SwFlyFrmFmt* pFlyFrmFmt =
+ dynamic_cast<const SwFlyFrmFmt*>( pFlyFrm->GetFmt() );
+ if ( pFlyFrmFmt->GetObjDescription().Len() != 0 )
+ {
+ break;
+ }
+ }
+ // intentional no break here
+ case RES_DESCRIPTION_CHANGED:
+ {
+ if ( pFlyFrm )
+ {
+ const OUString sOldDesc( msDesc );
+
+ const SwFlyFrmFmt* pFlyFrmFmt =
+ dynamic_cast<const SwFlyFrmFmt*>( pFlyFrm->GetFmt() );
+ const String& rDesc = pFlyFrmFmt->GetObjDescription();
+ msDesc = rDesc;
+ if ( msDesc.getLength() == 0 &&
+ msTitle != GetName() )
+ {
+ msDesc = msTitle;
+ }
+
+ if ( msDesc != sOldDesc )
+ {
+ AccessibleEventObject aEvent;
+ aEvent.EventId = AccessibleEventId::DESCRIPTION_CHANGED;
+ aEvent.OldValue <<= sOldDesc;
+ aEvent.NewValue <<= msDesc;
+ FireAccessibleEvent( aEvent );
+ }
+ }
+ }
+ break;
+ // <--
+ }
+}
+
+// #i73249#
+OUString SAL_CALL SwAccessibleTextFrame::getAccessibleName (void)
+ throw (uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+
+ CHECK_FOR_DEFUNC( XAccessibleContext )
+
+ if ( msTitle.getLength() != 0 )
+ {
+ return msTitle;
+ }
+
+ return SwAccessibleFrameBase::getAccessibleName();
+}
+// <--
+OUString SAL_CALL SwAccessibleTextFrame::getAccessibleDescription (void)
+ throw (uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+
+ CHECK_FOR_DEFUNC( XAccessibleContext )
+
+ return msDesc;
+
+}
+
+OUString SAL_CALL SwAccessibleTextFrame::getImplementationName()
+ throw( uno::RuntimeException )
+{
+ return OUString(RTL_CONSTASCII_USTRINGPARAM(sImplementationName));
+}
+
+sal_Bool SAL_CALL SwAccessibleTextFrame::supportsService(
+ const OUString& sTestServiceName)
+ throw (uno::RuntimeException)
+{
+ return sTestServiceName.equalsAsciiL( sServiceName,
+ sizeof(sServiceName)-1 ) ||
+ sTestServiceName.equalsAsciiL( sAccessibleServiceName,
+ sizeof(sAccessibleServiceName)-1 );
+}
+
+uno::Sequence< OUString > SAL_CALL SwAccessibleTextFrame::getSupportedServiceNames()
+ throw( uno::RuntimeException )
+{
+ uno::Sequence< OUString > aRet(2);
+ OUString* pArray = aRet.getArray();
+ pArray[0] = OUString( RTL_CONSTASCII_USTRINGPARAM(sServiceName) );
+ pArray[1] = OUString( RTL_CONSTASCII_USTRINGPARAM(sAccessibleServiceName) );
+ return aRet;
+}
+
+uno::Sequence< sal_Int8 > SAL_CALL SwAccessibleTextFrame::getImplementationId()
+ throw(uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+ static uno::Sequence< sal_Int8 > aId( 16 );
+ static sal_Bool bInit = sal_False;
+ if(!bInit)
+ {
+ rtl_createUuid( (sal_uInt8 *)(aId.getArray() ), 0, sal_True );
+ bInit = sal_True;
+ }
+ return aId;
+}
+
+
+//
+// XAccessibleRelationSet
+//
+
+
+SwFlyFrm* SwAccessibleTextFrame::getFlyFrm() const
+{
+ SwFlyFrm* pFlyFrm = NULL;
+
+ const SwFrm* pFrm = GetFrm();
+ DBG_ASSERT( pFrm != NULL, "frame expected" );
+ if( pFrm->IsFlyFrm() )
+ {
+ pFlyFrm = static_cast<SwFlyFrm*>( const_cast<SwFrm*>( pFrm ) );
+ }
+
+ return pFlyFrm;
+}
+
+AccessibleRelation SwAccessibleTextFrame::makeRelation( sal_Int16 nType, const SwFlyFrm* pFrm )
+{
+ uno::Sequence<uno::Reference<XInterface> > aSequence(1);
+ aSequence[0] = GetMap()->GetContext( pFrm );
+ return AccessibleRelation( nType, aSequence );
+}
+
+
+uno::Reference<XAccessibleRelationSet> SAL_CALL SwAccessibleTextFrame::getAccessibleRelationSet( )
+ throw ( uno::RuntimeException )
+{
+ SolarMutexGuard aGuard;
+ CHECK_FOR_DEFUNC( XAccessibleContext );
+
+ // get the frame, and insert prev/next relations into helper
+
+ AccessibleRelationSetHelper* pHelper = new AccessibleRelationSetHelper();
+
+ SwFlyFrm* pFlyFrm = getFlyFrm();
+ DBG_ASSERT( pFlyFrm != NULL, "fly frame expected" );
+
+ const SwFlyFrm* pPrevFrm = pFlyFrm->GetPrevLink();
+ if( pPrevFrm != NULL )
+ pHelper->AddRelation( makeRelation(
+ AccessibleRelationType::CONTENT_FLOWS_FROM, pPrevFrm ) );
+
+ const SwFlyFrm* pNextFrm = pFlyFrm->GetNextLink();
+ if( pNextFrm != NULL )
+ pHelper->AddRelation( makeRelation(
+ AccessibleRelationType::CONTENT_FLOWS_TO, pNextFrm ) );
+
+ return pHelper;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/access/acctextframe.hxx b/sw/source/core/access/acctextframe.hxx
new file mode 100644
index 000000000000..92c029d69e23
--- /dev/null
+++ b/sw/source/core/access/acctextframe.hxx
@@ -0,0 +1,116 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+#ifndef _ACCTEXTFRAME_HXX
+#define _ACCTEXTFRAME_HXX
+#include "accframebase.hxx"
+
+class SwFlyFrm;
+namespace utl { class AccessibleRelationSetHelper; }
+namespace com { namespace star {
+ namespace accessibility { struct AccessibleRelation; }
+} }
+
+class SwAccessibleTextFrame : public SwAccessibleFrameBase
+{
+private:
+ // #i73249#
+ ::rtl::OUString msTitle;
+ ::rtl::OUString msDesc;
+ // <--
+
+protected:
+
+ virtual ~SwAccessibleTextFrame();
+
+ virtual void Modify( const SfxPoolItem* pOld, const SfxPoolItem *pNew);
+
+public:
+
+ SwAccessibleTextFrame( SwAccessibleMap* pInitMap, const SwFlyFrm* pFlyFrm );
+
+ //===== XAccessibleContext ==============================================
+
+ // #i73249# - Return the object's current name.
+ virtual ::rtl::OUString SAL_CALL
+ getAccessibleName (void)
+ throw (::com::sun::star::uno::RuntimeException);
+ // <--
+ /// Return this object's description.
+ virtual ::rtl::OUString SAL_CALL
+ getAccessibleDescription (void)
+ throw (com::sun::star::uno::RuntimeException);
+
+ //===== XServiceInfo ====================================================
+
+ /** Returns an identifier for the implementation of this object.
+ */
+ virtual ::rtl::OUString SAL_CALL
+ getImplementationName (void)
+ throw (::com::sun::star::uno::RuntimeException);
+
+ /** Return whether the specified service is supported by this class.
+ */
+ virtual sal_Bool SAL_CALL
+ supportsService (const ::rtl::OUString& sServiceName)
+ throw (::com::sun::star::uno::RuntimeException);
+
+ /** Returns a list of all supported services. In this case that is just
+ the AccessibleContext service.
+ */
+ virtual ::com::sun::star::uno::Sequence< ::rtl::OUString> SAL_CALL
+ getSupportedServiceNames (void)
+ throw (::com::sun::star::uno::RuntimeException);
+
+ //====== XTypeProvider ====================================================
+ virtual ::com::sun::star::uno::Sequence< sal_Int8 > SAL_CALL getImplementationId( ) throw(::com::sun::star::uno::RuntimeException);
+
+
+ //===== XAccessibleContext::getAccessibleRelationSet ====================
+
+ // text frame may have accessible relations to their
+ // predocesor/successor frames
+
+private:
+ // helper methods for getAccessibleRelationSet:
+ SwFlyFrm* getFlyFrm() const;
+
+ com::sun::star::accessibility::AccessibleRelation makeRelation(
+ sal_Int16 nType, const SwFlyFrm* pFrm );
+
+public:
+
+ virtual ::com::sun::star::uno::Reference<
+ ::com::sun::star::accessibility::XAccessibleRelationSet> SAL_CALL
+ getAccessibleRelationSet (void)
+ throw (::com::sun::star::uno::RuntimeException);
+};
+
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/access/parachangetrackinginfo.cxx b/sw/source/core/access/parachangetrackinginfo.cxx
new file mode 100644
index 000000000000..c98510bd4b74
--- /dev/null
+++ b/sw/source/core/access/parachangetrackinginfo.cxx
@@ -0,0 +1,227 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#include "precompiled_sw.hxx"
+
+#include <parachangetrackinginfo.hxx>
+
+#include <wrong.hxx>
+#include <com/sun/star/text/TextMarkupType.hpp>
+
+#include <txtfrm.hxx>
+#include <ndtxt.hxx>
+#include <IDocumentRedlineAccess.hxx>
+#include <docary.hxx>
+#include <redline.hxx>
+
+namespace css = com::sun::star;
+
+namespace {
+ void initChangeTrackTextMarkupLists( const SwTxtFrm& rTxtFrm,
+ SwWrongList*& opChangeTrackInsertionTextMarkupList,
+ SwWrongList*& opChangeTrackDeletionTextMarkupList,
+ SwWrongList*& opChangeTrackFormatChangeTextMarkupList )
+ {
+ opChangeTrackInsertionTextMarkupList = new SwWrongList( WRONGLIST_CHANGETRACKING );
+ opChangeTrackDeletionTextMarkupList = new SwWrongList( WRONGLIST_CHANGETRACKING );
+ opChangeTrackFormatChangeTextMarkupList = new SwWrongList( WRONGLIST_CHANGETRACKING );
+
+ if ( !rTxtFrm.GetTxtNode() )
+ {
+ OSL_FAIL( "<initChangeTrackTextMarkupLists(..) - missing <SwTxtNode> instance!" );
+ return;
+ }
+ const SwTxtNode& rTxtNode( *(rTxtFrm.GetTxtNode()) );
+
+ const IDocumentRedlineAccess* pIDocChangeTrack( rTxtNode.getIDocumentRedlineAccess() );
+ if ( !pIDocChangeTrack )
+ {
+ OSL_FAIL( "<initChangeTrackTextMarkupLists(..) - missing <IDocumentRedlineAccess> instance!" );
+ return;
+ }
+
+ if ( !IDocumentRedlineAccess::IsShowChanges( pIDocChangeTrack->GetRedlineMode() ) ||
+ pIDocChangeTrack->GetRedlineTbl().Count() == 0 )
+ {
+ // nothing to do --> empty change track text markup lists.
+ return;
+ }
+
+ const sal_uInt16 nIdxOfFirstRedlineForTxtNode =
+ pIDocChangeTrack->GetRedlinePos( rTxtNode, USHRT_MAX );
+ if ( nIdxOfFirstRedlineForTxtNode == USHRT_MAX )
+ {
+ // nothing to do --> empty change track text markup lists.
+ return;
+ }
+
+ const xub_StrLen nTxtFrmTextStartPos = rTxtFrm.IsFollow()
+ ? rTxtFrm.GetOfst()
+ : 0;
+ const xub_StrLen nTxtFrmTextEndPos = rTxtFrm.HasFollow()
+ ? rTxtFrm.GetFollow()->GetOfst()
+ : rTxtFrm.GetTxt().Len();
+
+ // iteration over the redlines which overlap with the text node.
+ const SwRedlineTbl& rRedlineTbl = pIDocChangeTrack->GetRedlineTbl();
+ const sal_uInt16 nRedlineCount( rRedlineTbl.Count() );
+ for ( sal_uInt16 nActRedline = nIdxOfFirstRedlineForTxtNode;
+ nActRedline < nRedlineCount;
+ ++nActRedline)
+ {
+ const SwRedline* pActRedline = rRedlineTbl[ nActRedline ];
+ if ( pActRedline->Start()->nNode > rTxtNode.GetIndex() )
+ {
+ break;
+ }
+
+ xub_StrLen nTxtNodeChangeTrackStart( STRING_LEN );
+ xub_StrLen nTxtNodeChangeTrackEnd( STRING_LEN );
+ pActRedline->CalcStartEnd( rTxtNode.GetIndex(),
+ nTxtNodeChangeTrackStart,
+ nTxtNodeChangeTrackEnd );
+ if ( nTxtNodeChangeTrackStart > nTxtFrmTextEndPos ||
+ nTxtNodeChangeTrackEnd < nTxtFrmTextStartPos )
+ {
+ // Consider only redlines which overlap with the text frame's text.
+ continue;
+ }
+
+ SwWrongList* pMarkupList( 0 );
+ switch ( pActRedline->GetType() )
+ {
+ case nsRedlineType_t::REDLINE_INSERT:
+ {
+ pMarkupList = opChangeTrackInsertionTextMarkupList;
+ }
+ break;
+ case nsRedlineType_t::REDLINE_DELETE:
+ {
+ pMarkupList = opChangeTrackDeletionTextMarkupList;
+ }
+ break;
+ case nsRedlineType_t::REDLINE_FORMAT:
+ {
+ pMarkupList = opChangeTrackFormatChangeTextMarkupList;
+ }
+ break;
+ default:
+ {
+ // other types are not considered
+ }
+ }
+ if ( pMarkupList )
+ {
+ const xub_StrLen nTxtFrmChangeTrackStart =
+ nTxtNodeChangeTrackStart <= nTxtFrmTextStartPos
+ ? nTxtFrmTextStartPos
+ : nTxtNodeChangeTrackStart;
+
+ const xub_StrLen nTxtFrmChangeTrackEnd =
+ nTxtNodeChangeTrackEnd >= nTxtFrmTextEndPos
+ ? nTxtFrmTextEndPos
+ : nTxtNodeChangeTrackEnd;
+
+ pMarkupList->Insert( rtl::OUString(), 0,
+ nTxtFrmChangeTrackStart,
+ nTxtFrmChangeTrackEnd - nTxtFrmChangeTrackStart,
+ pMarkupList->Count() );
+ }
+ } // eof iteration over the redlines which overlap with the text node
+ }
+} // eof anonymous namespace
+
+SwParaChangeTrackingInfo::SwParaChangeTrackingInfo( const SwTxtFrm& rTxtFrm )
+ : mrTxtFrm( rTxtFrm )
+ , mpChangeTrackInsertionTextMarkupList( 0 )
+ , mpChangeTrackDeletionTextMarkupList( 0 )
+ , mpChangeTrackFormatChangeTextMarkupList( 0 )
+{
+}
+
+
+SwParaChangeTrackingInfo::~SwParaChangeTrackingInfo()
+{
+ reset();
+}
+
+void SwParaChangeTrackingInfo::reset()
+{
+ delete mpChangeTrackInsertionTextMarkupList;
+ mpChangeTrackInsertionTextMarkupList = 0;
+
+ delete mpChangeTrackDeletionTextMarkupList;
+ mpChangeTrackDeletionTextMarkupList = 0;
+
+ delete mpChangeTrackFormatChangeTextMarkupList;
+ mpChangeTrackFormatChangeTextMarkupList = 0;
+}
+
+const SwWrongList* SwParaChangeTrackingInfo::getChangeTrackingTextMarkupList( const sal_Int32 nTextMarkupType )
+{
+ SwWrongList* pChangeTrackingTextMarkupList = 0;
+
+ if ( mpChangeTrackInsertionTextMarkupList == 0 )
+ {
+ OSL_ENSURE( mpChangeTrackDeletionTextMarkupList == 0,
+ "<SwParaChangeTrackingInfo::getChangeTrackingTextMarkupList(..) - <mpChangeTrackDeletionTextMarkupList> expected to be NULL." );
+ OSL_ENSURE( mpChangeTrackFormatChangeTextMarkupList == 0,
+ "<SwParaChangeTrackingInfo::getChangeTrackingTextMarkupList(..) - <mpChangeTrackFormatChangeTextMarkupList> expected to be NULL." );
+ initChangeTrackTextMarkupLists( mrTxtFrm,
+ mpChangeTrackInsertionTextMarkupList,
+ mpChangeTrackDeletionTextMarkupList,
+ mpChangeTrackFormatChangeTextMarkupList );
+ }
+
+ switch ( nTextMarkupType )
+ {
+ case css::text::TextMarkupType::TRACK_CHANGE_INSERTION:
+ {
+ pChangeTrackingTextMarkupList = mpChangeTrackInsertionTextMarkupList;
+ }
+ break;
+ case css::text::TextMarkupType::TRACK_CHANGE_DELETION:
+ {
+ pChangeTrackingTextMarkupList = mpChangeTrackDeletionTextMarkupList;
+ }
+ break;
+ case css::text::TextMarkupType::TRACK_CHANGE_FORMATCHANGE:
+ {
+ pChangeTrackingTextMarkupList = mpChangeTrackFormatChangeTextMarkupList;
+ }
+ break;
+ default:
+ {
+ OSL_FAIL( "<SwParaChangeTrackingInfo::getChangeTrackingTextMarkupList(..)> - misusage - unexpected text markup type for change tracking." );
+ }
+ }
+
+ return pChangeTrackingTextMarkupList;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/access/parachangetrackinginfo.hxx b/sw/source/core/access/parachangetrackinginfo.hxx
new file mode 100644
index 000000000000..fea7d2fb5f14
--- /dev/null
+++ b/sw/source/core/access/parachangetrackinginfo.hxx
@@ -0,0 +1,58 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+#ifndef _PARACHANGETRACKINGINFO_HXX_
+#define _PARACHANGETRACKINGINFO_HXX_
+
+#include <sal/types.h>
+
+class SwTxtFrm;
+class SwWrongList;
+
+class SwParaChangeTrackingInfo
+{
+ public:
+ explicit SwParaChangeTrackingInfo( const SwTxtFrm& rTxtFrm );
+ ~SwParaChangeTrackingInfo();
+
+ void reset();
+
+ const SwWrongList* getChangeTrackingTextMarkupList( const sal_Int32 nTextMarkupType );
+
+ private:
+ SwParaChangeTrackingInfo( const SwParaChangeTrackingInfo& );
+ SwParaChangeTrackingInfo& operator=( const SwParaChangeTrackingInfo& );
+
+ const SwTxtFrm& mrTxtFrm;
+
+ SwWrongList* mpChangeTrackInsertionTextMarkupList;
+ SwWrongList* mpChangeTrackDeletionTextMarkupList;
+ SwWrongList* mpChangeTrackFormatChangeTextMarkupList;
+};
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/access/textmarkuphelper.cxx b/sw/source/core/access/textmarkuphelper.cxx
new file mode 100644
index 000000000000..c3dd4d7d6bab
--- /dev/null
+++ b/sw/source/core/access/textmarkuphelper.cxx
@@ -0,0 +1,232 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#include "precompiled_sw.hxx"
+
+#include <textmarkuphelper.hxx>
+#include <accportions.hxx>
+
+#include <vector>
+#include <algorithm>
+#include <comphelper/stlunosequence.hxx>
+
+
+#include <com/sun/star/text/TextMarkupType.hpp>
+#include <com/sun/star/accessibility/TextSegment.hpp>
+
+#include <ndtxt.hxx>
+#include <wrong.hxx>
+
+using namespace com::sun::star;
+
+// helper functions
+namespace {
+ const SwWrongList* getTextMarkupList( const SwTxtNode& rTxtNode,
+ const sal_Int32 nTextMarkupType )
+ throw (::com::sun::star::lang::IllegalArgumentException,
+ ::com::sun::star::uno::RuntimeException)
+ {
+ const SwWrongList* pTextMarkupList( 0 );
+ switch ( nTextMarkupType )
+ {
+ case text::TextMarkupType::SPELLCHECK:
+ {
+ pTextMarkupList = rTxtNode.GetWrong();
+ }
+ break;
+ case text::TextMarkupType::PROOFREADING:
+ {
+ // support not implemented yet
+ pTextMarkupList = 0;
+ }
+ break;
+ case text::TextMarkupType::SMARTTAG:
+ {
+ // support not implemented yet
+ pTextMarkupList = 0;
+ }
+ break;
+ default:
+ {
+ throw lang::IllegalArgumentException();
+ }
+ }
+
+ return pTextMarkupList;
+ }
+}
+
+// implementation of class <SwTextMarkupoHelper>
+SwTextMarkupHelper::SwTextMarkupHelper( const SwAccessiblePortionData& rPortionData,
+ const SwTxtNode& rTxtNode )
+ : mrPortionData( rPortionData )
+ // #i108125#
+ , mpTxtNode( &rTxtNode )
+ , mpTextMarkupList( 0 )
+ // <--
+{
+}
+
+// #i108125#
+SwTextMarkupHelper::SwTextMarkupHelper( const SwAccessiblePortionData& rPortionData,
+ const SwWrongList& rTextMarkupList )
+ : mrPortionData( rPortionData )
+ , mpTxtNode( 0 )
+ , mpTextMarkupList( &rTextMarkupList )
+{
+}
+// <--
+
+sal_Int32 SwTextMarkupHelper::getTextMarkupCount( const sal_Int32 nTextMarkupType )
+ throw (::com::sun::star::lang::IllegalArgumentException,
+ ::com::sun::star::uno::RuntimeException)
+{
+ sal_Int32 nTextMarkupCount( 0 );
+
+ // #i108125#
+ const SwWrongList* pTextMarkupList =
+ mpTextMarkupList
+ ? mpTextMarkupList
+ : getTextMarkupList( *mpTxtNode, nTextMarkupType );
+ // <--
+ if ( pTextMarkupList )
+ {
+ nTextMarkupCount = pTextMarkupList->Count();
+ }
+
+ return nTextMarkupCount;
+}
+::com::sun::star::accessibility::TextSegment
+ SwTextMarkupHelper::getTextMarkup( const sal_Int32 nTextMarkupIndex,
+ const sal_Int32 nTextMarkupType )
+ throw (::com::sun::star::lang::IndexOutOfBoundsException,
+ ::com::sun::star::lang::IllegalArgumentException,
+ ::com::sun::star::uno::RuntimeException)
+{
+ if ( nTextMarkupIndex >= getTextMarkupCount( nTextMarkupType ) ||
+ nTextMarkupIndex < 0 )
+ {
+ throw lang::IndexOutOfBoundsException();
+ }
+
+ ::com::sun::star::accessibility::TextSegment aTextMarkupSegment;
+ aTextMarkupSegment.SegmentStart = -1;
+ aTextMarkupSegment.SegmentEnd = -1;
+
+ // #i108125#
+ const SwWrongList* pTextMarkupList =
+ mpTextMarkupList
+ ? mpTextMarkupList
+ : getTextMarkupList( *mpTxtNode, nTextMarkupType );
+ // <--
+ if ( pTextMarkupList )
+ {
+ const SwWrongArea* pTextMarkup =
+ pTextMarkupList->GetElement( static_cast<sal_uInt16>(nTextMarkupIndex) );
+ if ( pTextMarkup )
+ {
+ const ::rtl::OUString rText = mrPortionData.GetAccessibleString();
+ const sal_Int32 nStartPos =
+ mrPortionData.GetAccessiblePosition( pTextMarkup->mnPos );
+ const sal_Int32 nEndPos =
+ mrPortionData.GetAccessiblePosition( pTextMarkup->mnPos + pTextMarkup->mnLen );
+ aTextMarkupSegment.SegmentText = rText.copy( nStartPos, nEndPos - nStartPos );
+ aTextMarkupSegment.SegmentStart = nStartPos;
+ aTextMarkupSegment.SegmentEnd = nEndPos;
+ }
+ else
+ {
+ OSL_FAIL( "<SwTextMarkupHelper::getTextMarkup(..)> - missing <SwWrongArea> instance" );
+ }
+ }
+
+ return aTextMarkupSegment;
+}
+
+::com::sun::star::uno::Sequence< ::com::sun::star::accessibility::TextSegment >
+ SwTextMarkupHelper::getTextMarkupAtIndex( const sal_Int32 nCharIndex,
+ const sal_Int32 nTextMarkupType )
+ throw (::com::sun::star::lang::IndexOutOfBoundsException,
+ ::com::sun::star::lang::IllegalArgumentException,
+ ::com::sun::star::uno::RuntimeException)
+{
+ // assumption:
+ // value of <nCharIndex> is in range [0..length of accessible text)
+
+ const sal_uInt16 nCoreCharIndex = mrPortionData.GetModelPosition( nCharIndex );
+ // Handling of portions with core length == 0 at the beginning of the
+ // paragraph - e.g. numbering portion.
+ if ( mrPortionData.GetAccessiblePosition( nCoreCharIndex ) > nCharIndex )
+ {
+ return uno::Sequence< ::com::sun::star::accessibility::TextSegment >();
+ }
+
+ // #i108125#
+ const SwWrongList* pTextMarkupList =
+ mpTextMarkupList
+ ? mpTextMarkupList
+ : getTextMarkupList( *mpTxtNode, nTextMarkupType );
+ // <--
+ ::std::vector< ::com::sun::star::accessibility::TextSegment > aTmpTextMarkups;
+ if ( pTextMarkupList )
+ {
+ const ::rtl::OUString rText = mrPortionData.GetAccessibleString();
+
+ const sal_uInt16 nTextMarkupCount = pTextMarkupList->Count();
+ for ( sal_uInt16 nTextMarkupIdx = 0; nTextMarkupIdx < nTextMarkupCount; ++nTextMarkupIdx )
+ {
+ const SwWrongArea* pTextMarkup =
+ pTextMarkupList->GetElement( static_cast<sal_uInt16>(nTextMarkupIdx) );
+ OSL_ENSURE( pTextMarkup,
+ "<SwTextMarkupHelper::getTextMarkup(..)> - missing <SwWrongArea> instance" );
+ if ( pTextMarkup &&
+ pTextMarkup->mnPos <= nCoreCharIndex &&
+ nCoreCharIndex < ( pTextMarkup->mnPos + pTextMarkup->mnLen ) )
+ {
+ const sal_Int32 nStartPos =
+ mrPortionData.GetAccessiblePosition( pTextMarkup->mnPos );
+ const sal_Int32 nEndPos =
+ mrPortionData.GetAccessiblePosition( pTextMarkup->mnPos + pTextMarkup->mnLen );
+ ::com::sun::star::accessibility::TextSegment aTextMarkupSegment;
+ aTextMarkupSegment.SegmentText = rText.copy( nStartPos, nEndPos - nStartPos );
+ aTextMarkupSegment.SegmentStart = nStartPos;
+ aTextMarkupSegment.SegmentEnd = nEndPos;
+ aTmpTextMarkups.push_back( aTextMarkupSegment );
+ }
+ }
+ }
+
+ uno::Sequence< ::com::sun::star::accessibility::TextSegment > aTextMarkups(
+ aTmpTextMarkups.size() );
+ ::std::copy( aTmpTextMarkups.begin(), aTmpTextMarkups.end(),
+ ::comphelper::stl_begin( aTextMarkups ) );
+
+ return aTextMarkups;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/access/textmarkuphelper.hxx b/sw/source/core/access/textmarkuphelper.hxx
new file mode 100644
index 000000000000..57d3152bab2a
--- /dev/null
+++ b/sw/source/core/access/textmarkuphelper.hxx
@@ -0,0 +1,84 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+#ifndef _TEXTMARKUPHELPER_HXX_
+#define _TEXTMARKUPHELPER_HXX_
+
+#include <sal/types.h>
+#include "com/sun/star/lang/IndexOutOfBoundsException.hdl"
+#include "com/sun/star/lang/IllegalArgumentException.hdl"
+#include "com/sun/star/uno/RuntimeException.hdl"
+#include "com/sun/star/uno/Sequence.h"
+
+namespace com { namespace sun { namespace star { namespace accessibility {
+struct TextSegment;
+} } } }
+
+class SwAccessiblePortionData;
+class SwTxtNode;
+class SwWrongList; // #i108125#
+class SwTextMarkupHelper
+{
+ public:
+ SwTextMarkupHelper( const SwAccessiblePortionData& rPortionData,
+ const SwTxtNode& rTxtNode );
+ SwTextMarkupHelper( const SwAccessiblePortionData& rPortionData,
+ const SwWrongList& rTextMarkupList ); // #i108125#
+ ~SwTextMarkupHelper() {}
+
+ sal_Int32 getTextMarkupCount( const sal_Int32 nTextMarkupType )
+ throw (::com::sun::star::lang::IllegalArgumentException,
+ ::com::sun::star::uno::RuntimeException);
+
+ ::com::sun::star::accessibility::TextSegment getTextMarkup(
+ const sal_Int32 nTextMarkupIndex,
+ const sal_Int32 nTextMarkupType )
+ throw (::com::sun::star::lang::IndexOutOfBoundsException,
+ ::com::sun::star::lang::IllegalArgumentException,
+ ::com::sun::star::uno::RuntimeException);
+
+ ::com::sun::star::uno::Sequence< ::com::sun::star::accessibility::TextSegment >
+ getTextMarkupAtIndex( const sal_Int32 nCharIndex,
+ const sal_Int32 nTextMarkupType )
+ throw (::com::sun::star::lang::IndexOutOfBoundsException,
+ ::com::sun::star::lang::IllegalArgumentException,
+ ::com::sun::star::uno::RuntimeException);
+
+ private:
+ SwTextMarkupHelper( const SwTextMarkupHelper& );
+ SwTextMarkupHelper& operator=( const SwTextMarkupHelper& );
+
+ const SwAccessiblePortionData& mrPortionData;
+
+ // #i108125#
+ const SwTxtNode* mpTxtNode;
+ const SwWrongList* mpTextMarkupList;
+ // <--
+};
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/attr/calbck.cxx b/sw/source/core/attr/calbck.cxx
new file mode 100644
index 000000000000..844bd0dfbbd2
--- /dev/null
+++ b/sw/source/core/attr/calbck.cxx
@@ -0,0 +1,567 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+#include <hintids.hxx> // contains RES_.. IDs
+#include <frame.hxx>
+#include <hints.hxx>
+#include <swcache.hxx> // mba: get rid of that dependency
+#include <swfntcch.hxx> // mba: get rid of that dependency
+
+static SwClientIter* pClientIters = 0;
+
+TYPEINIT0(SwClient);
+
+/*************************************************************************/
+SwClient::SwClient(SwModify *pToRegisterIn)
+ : pLeft( 0 ), pRight( 0 ), pRegisteredIn( 0 ), mbIsAllowedToBeRemovedInModifyCall(false)
+{
+ if(pToRegisterIn)
+ // connect to SwModify
+ pToRegisterIn->Add(this);
+}
+
+/*************************************************************************/
+void SwClient::CheckRegistration( const SfxPoolItem* pOld, const SfxPoolItem * )
+{
+ // this method only handles notification about dying SwModify objects
+ if( (!pOld || pOld->Which() != RES_OBJECTDYING) )
+ return;
+
+ const SwPtrMsgPoolItem *pDead = static_cast<const SwPtrMsgPoolItem*>(pOld);
+ if(pDead && pDead->pObject == pRegisteredIn)
+ {
+ // I've got a notification from the object I know
+ SwModify *pAbove = const_cast<SwModify*>(pRegisteredIn->GetRegisteredIn());
+ if(pAbove)
+ {
+ // if the dying object itself was listening at an SwModify, I take over
+ // adding myself to pAbove will automatically remove me from my current pRegisteredIn
+ pAbove->Add(this);
+ return;
+ }
+
+ // destroy connection
+ pRegisteredIn->Remove(this);
+ }
+}
+
+void SwClient::Modify( const SfxPoolItem *pOldValue, const SfxPoolItem *pNewValue )
+{
+ CheckRegistration( pOldValue, pNewValue );
+}
+
+void SwClient::SwClientNotify( const SwModify&, const SfxHint& )
+{
+
+}
+
+//*************************************************************************
+SwClient::~SwClient()
+{
+ DBG_ASSERT( !pRegisteredIn || pRegisteredIn->GetDepends(),"SwModify still known, but Client already disconnected!" );
+ if( pRegisteredIn && pRegisteredIn->GetDepends() )
+ // still connected
+ pRegisteredIn->Remove( this );
+}
+
+
+sal_Bool SwClient::GetInfo( SfxPoolItem& ) const
+{
+ return sal_True; // und weiter
+}
+
+
+/*************************************************************************/
+SwModify::SwModify()
+ : SwClient(0), pRoot(0)
+{
+ bModifyLocked = sal_False;
+ bLockClientList = sal_False;
+ bInDocDTOR = sal_False;
+ bInCache = sal_False;
+ bInSwFntCache = sal_False;
+}
+
+SwModify::SwModify( SwModify *pToRegisterIn )
+ : SwClient(pToRegisterIn), pRoot( 0 )
+{
+ bModifyLocked = sal_False;
+ bLockClientList = sal_False;
+ bInDocDTOR = sal_False;
+ bInCache = sal_False;
+ bInSwFntCache = sal_False;
+}
+
+/*************************************************************************/
+SwModify::~SwModify()
+{
+ OSL_ENSURE( !IsModifyLocked(), "Modify destroyed but locked." );
+
+ if ( IsInCache() )
+ SwFrm::GetCache().Delete( this );
+
+ if ( IsInSwFntCache() )
+ pSwFontCache->Delete( this );
+
+ if( pRoot )
+ {
+ // there are depending objects
+ if( IsInDocDTOR() )
+ {
+ // if document gets destroyed anyway, just tell clients to forget me
+ // so that they don't try to get removed from my list later when they also get destroyed
+ SwClientIter aIter( *this );
+ SwClient* p = aIter.GoStart();
+ while ( p )
+ {
+ p->pRegisteredIn = 0;
+ p = aIter++;
+ }
+ }
+ else
+ {
+ // notify all clients that they shall remove themselves
+ SwPtrMsgPoolItem aDyObject( RES_OBJECTDYING, this );
+ NotifyClients( &aDyObject, &aDyObject );
+
+ // remove all clients that have not done themselves
+ // mba: possibly a hotfix for forgotten base class calls?!
+ while( pRoot )
+ pRoot->CheckRegistration(&aDyObject, &aDyObject);
+ }
+ }
+}
+
+/*************************************************************************/
+void SwModify::Modify( const SfxPoolItem *pOldValue, const SfxPoolItem *pNewValue )
+{
+ NotifyClients( pOldValue, pNewValue );
+}
+
+void SwModify::NotifyClients( const SfxPoolItem *pOldValue, const SfxPoolItem *pNewValue )
+{
+ if (IsInCache() || IsInSwFntCache())
+ {
+ const sal_uInt16 nWhich = pOldValue ? pOldValue->Which() :
+ pNewValue ? pNewValue->Which() : 0;
+ CheckCaching( nWhich );
+ }
+
+ if (!pRoot || IsModifyLocked())
+ return;
+
+ LockModify();
+
+ // mba: WTF?!
+ if( !pOldValue )
+ bLockClientList = sal_True;
+ else
+ {
+ // following Modifies shouldn't call an ASSERT
+ switch( pOldValue->Which() )
+ {
+ case RES_OBJECTDYING:
+ case RES_REMOVE_UNO_OBJECT:
+ bLockClientList = ((SwPtrMsgPoolItem *)pOldValue)->pObject != this;
+ break;
+
+ case RES_FOOTNOTE_DELETED:
+ case RES_REFMARK_DELETED:
+ case RES_TOXMARK_DELETED:
+ case RES_FIELD_DELETED:
+ bLockClientList = sal_False;
+ break;
+ default:
+ bLockClientList = sal_True;
+ }
+ }
+
+ ModifyBroadcast( pOldValue, pNewValue );
+ bLockClientList = sal_False;
+ UnlockModify();
+}
+
+sal_Bool SwModify::GetInfo( SfxPoolItem& rInfo ) const
+{
+ sal_Bool bRet = sal_True; // bedeutet weiter zum naechsten
+
+ if( pRoot )
+ {
+ SwClientIter aIter( *(SwModify*)this );
+
+ SwClient* pLast = aIter.GoStart();
+ if( pLast )
+ while( 0 != ( bRet = pLast->GetInfo( rInfo )) &&
+ 0 != ( pLast = aIter++ ) )
+ ;
+ }
+
+ return bRet;
+}
+
+/*************************************************************************/
+void SwModify::Add(SwClient *pDepend)
+{
+ OSL_ENSURE( !bLockClientList, "Client inserted while in Modify" );
+
+ if(pDepend->pRegisteredIn != this )
+ {
+#if OSL_DEBUG_LEVEL > 1
+ SwClientIter* pTmp = pClientIters;
+ while( pTmp )
+ {
+ OSL_ENSURE( &pTmp->GetModify() != pRoot, "Client added to active ClientIter" );
+ pTmp = pTmp->pNxtIter;
+ }
+#endif
+ // deregister new client in case it is already registered elsewhere
+ if( pDepend->pRegisteredIn != 0 )
+ pDepend->pRegisteredIn->Remove( pDepend );
+
+ if( !pRoot )
+ {
+ // first client added
+ pRoot = pDepend;
+ pRoot->pLeft = 0;
+ pRoot->pRight = 0;
+ }
+ else
+ {
+ // append client
+ pDepend->pRight = pRoot->pRight;
+ pRoot->pRight = pDepend;
+ pDepend->pLeft = pRoot;
+ if( pDepend->pRight )
+ pDepend->pRight->pLeft = pDepend;
+ }
+
+ // connect client to me
+ pDepend->pRegisteredIn = this;
+ }
+}
+
+/*************************************************************************/
+
+SwClient* SwModify::Remove(SwClient * pDepend)
+{
+ if ( bInDocDTOR )
+ return 0;
+
+ OSL_ENSURE( !bLockClientList || pDepend->mbIsAllowedToBeRemovedInModifyCall, "SwClient shall be removed in Modify call!" );
+
+ if( pDepend->pRegisteredIn == this )
+ {
+ // SwClient is my listener
+ // remove it from my list
+ SwClient* pR = pDepend->pRight;
+ SwClient* pL = pDepend->pLeft;
+ if( pRoot == pDepend )
+ pRoot = pL ? pL : pR;
+
+ if( pL )
+ pL->pRight = pR;
+ if( pR )
+ pR->pLeft = pL;
+
+ // update ClientIters
+ SwClientIter* pTmp = pClientIters;
+ while( pTmp )
+ {
+ if( pTmp->pAct == pDepend || pTmp->pDelNext == pDepend )
+ // if object being removed is the current or next object in an iterator, advance this iterator
+ pTmp->pDelNext = pR;
+ pTmp = pTmp->pNxtIter;
+ }
+
+ pDepend->pLeft = 0;
+ pDepend->pRight = 0;
+ }
+ else
+ {
+ OSL_FAIL( "SwModify::Remove(): pDepend nicht gefunden" );
+ }
+
+ // disconnect client from me
+ pDepend->pRegisteredIn = 0;
+ return pDepend;
+}
+
+int SwModify::GetClientCount() const
+{
+ int nRet=0;
+ SwClientIter aIter( *this );
+ SwClient *pLast = aIter.GoStart();
+ if( pLast )
+ do
+ {
+ ++nRet;
+ } while( 0 != ( pLast = aIter++ ));
+ return nRet;
+}
+
+void SwModify::CheckCaching( const sal_uInt16 nWhich )
+{
+ if (isCHRATR(nWhich))
+ {
+ SetInSwFntCache( sal_False );
+ }
+ else
+ switch ( nWhich )
+ {
+ case RES_OBJECTDYING:
+ case RES_FMT_CHG:
+ case RES_ATTRSET_CHG:
+ SetInSwFntCache( sal_False );
+
+ case RES_UL_SPACE:
+ case RES_LR_SPACE:
+ case RES_BOX:
+ case RES_SHADOW:
+ case RES_FRM_SIZE:
+ case RES_KEEP:
+ case RES_BREAK:
+ if ( IsInCache() )
+ {
+ SwFrm::GetCache().Delete( this );
+ SetInCache( sal_False );
+ }
+ break;
+ }
+}
+
+void SwModify::CallSwClientNotify( const SfxHint& rHint ) const
+{
+ SwClientIter aIter(*this);
+ SwClient * pClient = aIter.GoStart();
+ while (pClient)
+ {
+ pClient->SwClientNotify( *this, rHint );
+ pClient = aIter++;
+ }
+}
+
+void SwModify::ModifyBroadcast( const SfxPoolItem *pOldValue, const SfxPoolItem *pNewValue, TypeId nType )
+{
+ SwClientIter aIter(*this);
+ SwClient * pClient = aIter.First( nType );
+ while (pClient)
+ {
+ pClient->Modify( pOldValue, pNewValue );
+ pClient = aIter.Next();
+ }
+}
+
+// ----------
+// SwDepend
+// ----------
+
+/*************************************************************************/
+
+SwDepend::SwDepend(SwClient *pTellHim, SwModify *pDepend)
+ : SwClient(pDepend)
+{
+ pToTell = pTellHim;
+}
+
+/*************************************************************************/
+
+void SwDepend::Modify( const SfxPoolItem* pOldValue, const SfxPoolItem *pNewValue )
+{
+ if(pNewValue && pNewValue->Which() == RES_OBJECTDYING)
+ CheckRegistration(pOldValue,pNewValue);
+ else if(pToTell)
+ pToTell->ModifyNotification(pOldValue, pNewValue);
+}
+
+void SwDepend::SwClientNotify( const SwModify& rMod, const SfxHint& rHint )
+{
+ if ( pToTell )
+ pToTell->SwClientNotifyCall( rMod, rHint );
+}
+
+sal_Bool SwDepend::GetInfo( SfxPoolItem& rInfo ) const
+{
+ return pToTell ? pToTell->GetInfo( rInfo ) : sal_True;
+}
+
+/********************************************************************/
+
+SwClientIter::SwClientIter( const SwModify& rModify )
+ : rRoot( rModify )
+{
+ pNxtIter = 0;
+ if( pClientIters )
+ {
+ // append to list of ClientIters
+ SwClientIter* pTmp = pClientIters;
+ while( pTmp->pNxtIter )
+ pTmp = pTmp->pNxtIter;
+ pTmp->pNxtIter = this;
+ }
+ else
+ pClientIters = this;
+
+ pAct = const_cast<SwClient*>(rRoot.GetDepends());
+ pDelNext = pAct;
+}
+
+
+
+SwClientIter::~SwClientIter()
+{
+ if( pClientIters )
+ {
+ // reorganize list of ClientIters
+ if( pClientIters == this )
+ pClientIters = pNxtIter;
+ else
+ {
+ SwClientIter* pTmp = pClientIters;
+ while( pTmp->pNxtIter != this )
+ if( 0 == ( pTmp = pTmp->pNxtIter ) )
+ {
+ OSL_ENSURE( this, "wo ist mein Pointer" );
+ return ;
+ }
+ pTmp->pNxtIter = pNxtIter;
+ }
+ }
+}
+
+
+SwClient* SwClientIter::operator++(int)
+{
+ if( pDelNext == pAct )
+ {
+ pAct = pAct->pRight;
+ pDelNext = pAct;
+ }
+ else
+ pAct = pDelNext;
+ return pAct;
+}
+
+SwClient* SwClientIter::GoStart()
+{
+ pAct = const_cast<SwClient*>(rRoot.GetDepends());
+ if( pAct )
+ while( pAct->pLeft )
+ pAct = pAct->pLeft;
+ pDelNext = pAct;
+ return pAct;
+}
+
+SwClient* SwClientIter::GoEnd()
+{
+ pAct = pDelNext;
+ if( !pAct )
+ pAct = const_cast<SwClient*>(rRoot.GetDepends());
+ if( pAct )
+ while( pAct->pRight )
+ pAct = pAct->pRight;
+ pDelNext = pAct;
+ return pAct;
+}
+
+SwClient* SwClientIter::First( TypeId nType )
+{
+ aSrchId = nType;
+ GoStart();
+ if( pAct )
+ do {
+ if( pAct->IsA( aSrchId ) )
+ break;
+
+ if( pDelNext == pAct )
+ {
+ pAct = pAct->pRight;
+ pDelNext = pAct;
+ }
+ else
+ pAct = pDelNext;
+
+ } while( pAct );
+ return pAct;
+}
+
+SwClient* SwClientIter::Next()
+{
+ do {
+ if( pDelNext == pAct )
+ {
+ pAct = pAct->pRight;
+ pDelNext = pAct;
+ }
+ else
+ pAct = pDelNext;
+
+ if( pAct && pAct->IsA( aSrchId ) )
+ break;
+ } while( pAct );
+ return pAct;
+}
+
+SwClient* SwClientIter::Last( TypeId nType )
+{
+ aSrchId = nType;
+ GoEnd();
+ if( pAct )
+ do {
+ if( pAct->IsA( aSrchId ) )
+ break;
+
+ if( pDelNext == pAct )
+ pAct = pAct->pLeft;
+ else
+ pAct = pDelNext->pLeft;
+ pDelNext = pAct;
+
+ } while( pAct );
+ return pAct;
+}
+
+SwClient* SwClientIter::Previous()
+{
+ do {
+ if( pDelNext == pAct )
+ pAct = pAct->pLeft;
+ else
+ pAct = pDelNext->pLeft;
+ pDelNext = pAct;
+
+ if( pAct && pAct->IsA( aSrchId ) )
+ break;
+ } while( pAct );
+ return pAct;
+}
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/attr/cellatr.cxx b/sw/source/core/attr/cellatr.cxx
new file mode 100644
index 000000000000..abd2dfd887d1
--- /dev/null
+++ b/sw/source/core/attr/cellatr.cxx
@@ -0,0 +1,265 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+#include <float.h>
+#include <rtl/math.hxx>
+#include <hintids.hxx> // fuer RES_..
+#include <cellatr.hxx>
+#include <calc.hxx>
+#include <format.hxx>
+#include <doc.hxx>
+#include <swtable.hxx>
+#include <node.hxx>
+#include <hints.hxx>
+#include <rolbck.hxx>
+#include <switerator.hxx>
+
+
+//TYPEINIT1( SwFmt, SwClient ); //rtti fuer SwFmt
+
+/*************************************************************************
+|*
+*************************************************************************/
+
+
+SwTblBoxNumFormat::SwTblBoxNumFormat( sal_uInt32 nFormat, sal_Bool bFlag )
+ : SfxUInt32Item( RES_BOXATR_FORMAT, nFormat ), bAuto( bFlag )
+{
+}
+
+
+int SwTblBoxNumFormat::operator==( const SfxPoolItem& rAttr ) const
+{
+ OSL_ENSURE( SfxPoolItem::operator==( rAttr ), "keine gleichen Attribute" );
+ return GetValue() == ((SwTblBoxNumFormat&)rAttr).GetValue() &&
+ bAuto == ((SwTblBoxNumFormat&)rAttr).bAuto;
+}
+
+
+SfxPoolItem* SwTblBoxNumFormat::Clone( SfxItemPool* ) const
+{
+ return new SwTblBoxNumFormat( GetValue(), bAuto );
+}
+
+
+/*************************************************************************
+|*
+*************************************************************************/
+
+
+
+SwTblBoxFormula::SwTblBoxFormula( const String& rFormula )
+ : SfxPoolItem( RES_BOXATR_FORMULA ),
+ SwTableFormula( rFormula ),
+ pDefinedIn( 0 )
+{
+}
+
+
+int SwTblBoxFormula::operator==( const SfxPoolItem& rAttr ) const
+{
+ OSL_ENSURE( SfxPoolItem::operator==( rAttr ), "keine gleichen Attribute" );
+ return GetFormula() == ((SwTblBoxFormula&)rAttr).GetFormula() &&
+ pDefinedIn == ((SwTblBoxFormula&)rAttr).pDefinedIn;
+}
+
+
+SfxPoolItem* SwTblBoxFormula::Clone( SfxItemPool* ) const
+{
+// auf externe Darstellung umschalten!!
+ SwTblBoxFormula* pNew = new SwTblBoxFormula( GetFormula() );
+ pNew->SwTableFormula::operator=( *this );
+ return pNew;
+}
+
+
+
+ // suche den Node, in dem die Formel steht:
+ // TextFeld -> TextNode,
+ // BoxAttribut -> BoxStartNode
+ // !!! MUSS VON JEDER ABLEITUNG UEBERLADEN WERDEN !!!
+const SwNode* SwTblBoxFormula::GetNodeOfFormula() const
+{
+ const SwNode* pRet = 0;
+ if( pDefinedIn )
+ {
+ SwTableBox* pBox = SwIterator<SwTableBox,SwModify>::FirstElement( *pDefinedIn );
+ if( pBox )
+ pRet = pBox->GetSttNd();
+ }
+ return pRet;
+}
+
+
+SwTableBox* SwTblBoxFormula::GetTableBox()
+{
+ SwTableBox* pBox = 0;
+ if( pDefinedIn )
+ pBox = SwIterator<SwTableBox,SwModify>::FirstElement( *pDefinedIn );
+ return pBox;
+}
+
+
+void SwTblBoxFormula::ChangeState( const SfxPoolItem* pItem )
+{
+ if( !pDefinedIn )
+ return ;
+
+ SwTableFmlUpdate* pUpdtFld;
+ if( !pItem || RES_TABLEFML_UPDATE != pItem->Which() )
+ {
+ // setze bei allen das Value-Flag zurueck
+ ChgValid( sal_False );
+ return ;
+ }
+
+ pUpdtFld = (SwTableFmlUpdate*)pItem;
+
+ // bestimme die Tabelle, in der das Attribut steht
+ const SwTableNode* pTblNd;
+ const SwNode* pNd = GetNodeOfFormula();
+ if( pNd && &pNd->GetNodes() == &pNd->GetDoc()->GetNodes() &&
+ 0 != ( pTblNd = pNd->FindTableNode() ))
+ {
+ switch( pUpdtFld->eFlags )
+ {
+ case TBL_CALC:
+ // setze das Value-Flag zurueck
+ // JP 17.06.96: interne Darstellung auf alle Formeln
+ // (Referenzen auf andere Tabellen!!!)
+ ChgValid( sal_False );
+ break;
+ case TBL_BOXNAME:
+ // ist es die gesuchte Tabelle ??
+ if( &pTblNd->GetTable() == pUpdtFld->pTbl )
+ // zur externen Darstellung
+ PtrToBoxNm( pUpdtFld->pTbl );
+ break;
+ case TBL_BOXPTR:
+ // zur internen Darstellung
+ // JP 17.06.96: interne Darstellung auf alle Formeln
+ // (Referenzen auf andere Tabellen!!!)
+ BoxNmToPtr( &pTblNd->GetTable() );
+ break;
+ case TBL_RELBOXNAME:
+ // ist es die gesuchte Tabelle ??
+ if( &pTblNd->GetTable() == pUpdtFld->pTbl )
+ // zur relativen Darstellung
+ ToRelBoxNm( pUpdtFld->pTbl );
+ break;
+
+ case TBL_SPLITTBL:
+ if( &pTblNd->GetTable() == pUpdtFld->pTbl )
+ {
+ sal_uInt16 nLnPos = SwTableFormula::GetLnPosInTbl(
+ pTblNd->GetTable(), GetTableBox() );
+ pUpdtFld->bBehindSplitLine = USHRT_MAX != nLnPos &&
+ pUpdtFld->nSplitLine <= nLnPos;
+ }
+ else
+ pUpdtFld->bBehindSplitLine = sal_False;
+ // kein break
+ case TBL_MERGETBL:
+ if( pUpdtFld->pHistory )
+ {
+ // fuer die History brauche ich aber die unveraenderte Formel
+ SwTblBoxFormula aCopy( *this );
+ pUpdtFld->bModified = sal_False;
+ ToSplitMergeBoxNm( *pUpdtFld );
+
+ if( pUpdtFld->bModified )
+ {
+ // und dann in der externen Darstellung
+ aCopy.PtrToBoxNm( &pTblNd->GetTable() );
+ pUpdtFld->pHistory->Add( &aCopy, &aCopy,
+ pNd->FindTableBoxStartNode()->GetIndex() );
+ }
+ }
+ else
+ ToSplitMergeBoxNm( *pUpdtFld );
+ break;
+ }
+ }
+}
+
+
+void SwTblBoxFormula::Calc( SwTblCalcPara& rCalcPara, double& rValue )
+{
+ if( !rCalcPara.rCalc.IsCalcError() ) // ist schon Fehler gesetzt ?
+ {
+ // erzeuge aus den BoxNamen die Pointer
+ BoxNmToPtr( rCalcPara.pTbl );
+ String sFml( MakeFormel( rCalcPara ));
+ if( !rCalcPara.rCalc.IsCalcError() )
+ rValue = rCalcPara.rCalc.Calculate( sFml ).GetDouble();
+ else
+ rValue = DBL_MAX;
+ ChgValid( !rCalcPara.IsStackOverFlow() ); // der Wert ist wieder gueltig
+ }
+}
+
+/*************************************************************************
+|*
+*************************************************************************/
+
+
+SwTblBoxValue::SwTblBoxValue()
+ : SfxPoolItem( RES_BOXATR_VALUE ), nValue( 0 )
+{
+}
+
+
+SwTblBoxValue::SwTblBoxValue( const double nVal )
+ : SfxPoolItem( RES_BOXATR_VALUE ), nValue( nVal )
+{
+}
+
+
+int SwTblBoxValue::operator==( const SfxPoolItem& rAttr ) const
+{
+ OSL_ENSURE(SfxPoolItem::operator==(rAttr), "SwTblBoxValue: item not equal");
+ SwTblBoxValue const& rOther( static_cast<SwTblBoxValue const&>(rAttr) );
+ // items with NaN should be equal to enable pooling
+ return ::rtl::math::isNan(nValue)
+ ? ::rtl::math::isNan(rOther.nValue)
+ : (nValue == rOther.nValue);
+}
+
+
+SfxPoolItem* SwTblBoxValue::Clone( SfxItemPool* ) const
+{
+ return new SwTblBoxValue( nValue );
+}
+
+
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/attr/fmtfollowtextflow.cxx b/sw/source/core/attr/fmtfollowtextflow.cxx
new file mode 100644
index 000000000000..b51d15be5cc3
--- /dev/null
+++ b/sw/source/core/attr/fmtfollowtextflow.cxx
@@ -0,0 +1,40 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+#include <fmtfollowtextflow.hxx>
+
+TYPEINIT1(SwFmtFollowTextFlow, SfxBoolItem);
+
+SfxPoolItem* SwFmtFollowTextFlow::Clone( SfxItemPool * ) const
+{
+ return new SwFmtFollowTextFlow(*this);
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/attr/fmtwrapinfluenceonobjpos.cxx b/sw/source/core/attr/fmtwrapinfluenceonobjpos.cxx
new file mode 100644
index 000000000000..c228387fcfd0
--- /dev/null
+++ b/sw/source/core/attr/fmtwrapinfluenceonobjpos.cxx
@@ -0,0 +1,164 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+#include <fmtwrapinfluenceonobjpos.hxx>
+
+#include <unomid.h>
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::uno;
+
+TYPEINIT1(SwFmtWrapInfluenceOnObjPos, SfxPoolItem);
+
+SwFmtWrapInfluenceOnObjPos::SwFmtWrapInfluenceOnObjPos(
+ sal_Int16 _nWrapInfluenceOnPosition )
+ : SfxPoolItem( RES_WRAP_INFLUENCE_ON_OBJPOS ),
+ mnWrapInfluenceOnPosition( _nWrapInfluenceOnPosition )
+{
+}
+
+SwFmtWrapInfluenceOnObjPos::SwFmtWrapInfluenceOnObjPos(
+ const SwFmtWrapInfluenceOnObjPos& _rCpy )
+ : SfxPoolItem( RES_WRAP_INFLUENCE_ON_OBJPOS ),
+ mnWrapInfluenceOnPosition( _rCpy.GetWrapInfluenceOnObjPos() )
+{
+}
+
+SwFmtWrapInfluenceOnObjPos::~SwFmtWrapInfluenceOnObjPos()
+{
+}
+
+SwFmtWrapInfluenceOnObjPos& SwFmtWrapInfluenceOnObjPos::operator=(
+ const SwFmtWrapInfluenceOnObjPos& _rSource )
+{
+ mnWrapInfluenceOnPosition = _rSource.GetWrapInfluenceOnObjPos();
+
+ return *this;
+}
+
+int SwFmtWrapInfluenceOnObjPos::operator==( const SfxPoolItem& _rAttr ) const
+{
+ OSL_ENSURE( SfxPoolItem::operator==( _rAttr ), "keine gleichen Attribute" );
+ return ( mnWrapInfluenceOnPosition ==
+ static_cast<const SwFmtWrapInfluenceOnObjPos&>(_rAttr).
+ GetWrapInfluenceOnObjPos() );
+}
+
+SfxPoolItem* SwFmtWrapInfluenceOnObjPos::Clone( SfxItemPool * ) const
+{
+ return new SwFmtWrapInfluenceOnObjPos(*this);
+}
+
+bool SwFmtWrapInfluenceOnObjPos::QueryValue( Any& rVal, sal_uInt8 nMemberId ) const
+{
+ nMemberId &= ~CONVERT_TWIPS;
+ bool bRet = true;
+ switch ( nMemberId )
+ {
+ case MID_WRAP_INFLUENCE:
+ {
+ rVal <<= GetWrapInfluenceOnObjPos();
+ }
+ break;
+ default:
+ OSL_FAIL( "<SwFmtWrapInfluenceOnObjPos::QueryValue()> - unknown MemberId" );
+ bRet = false;
+ }
+
+ return bRet;
+}
+
+bool SwFmtWrapInfluenceOnObjPos::PutValue( const Any& rVal, sal_uInt8 nMemberId )
+{
+ nMemberId &= ~CONVERT_TWIPS;
+ bool bRet = true;
+
+ switch ( nMemberId )
+ {
+ case MID_WRAP_INFLUENCE:
+ {
+ sal_Int16 nNewWrapInfluence = 0;
+ rVal >>= nNewWrapInfluence;
+ // #i35017# - constant names have changed and
+ // <ITERATIVE> has been added
+ if ( nNewWrapInfluence == text::WrapInfluenceOnPosition::ONCE_SUCCESSIVE ||
+ nNewWrapInfluence == text::WrapInfluenceOnPosition::ONCE_CONCURRENT ||
+ nNewWrapInfluence == text::WrapInfluenceOnPosition::ITERATIVE )
+ {
+ SetWrapInfluenceOnObjPos( nNewWrapInfluence );
+ }
+ else
+ {
+ OSL_FAIL( "<SwFmtWrapInfluenceOnObjPos::PutValue(..)> - invalid attribute value" );
+ bRet = false;
+ }
+ }
+ break;
+ default:
+ OSL_FAIL( "<SwFmtWrapInfluenceOnObjPos::QueryValue()> - unknown MemberId" );
+ bRet = false;
+ }
+
+ return bRet;
+}
+
+void SwFmtWrapInfluenceOnObjPos::SetWrapInfluenceOnObjPos( sal_Int16 _nWrapInfluenceOnPosition )
+{
+ // #i35017# - constant names have changed and consider
+ // new value <ITERATIVE>
+ if ( _nWrapInfluenceOnPosition == text::WrapInfluenceOnPosition::ONCE_SUCCESSIVE ||
+ _nWrapInfluenceOnPosition == text::WrapInfluenceOnPosition::ONCE_CONCURRENT ||
+ _nWrapInfluenceOnPosition == text::WrapInfluenceOnPosition::ITERATIVE )
+ {
+ mnWrapInfluenceOnPosition = _nWrapInfluenceOnPosition;
+ }
+ else
+ {
+ OSL_FAIL( "<SwFmtWrapInfluenceOnObjPos::SetWrapInfluenceOnObjPos(..)> - invalid attribute value" );
+ }
+}
+
+// #i35017# - add parameter <_bIterativeAsOnceConcurrent>
+// to control, if value <ITERATIVE> has to be treated as <ONCE_CONCURRENT>
+sal_Int16 SwFmtWrapInfluenceOnObjPos::GetWrapInfluenceOnObjPos(
+ const bool _bIterativeAsOnceConcurrent ) const
+{
+ sal_Int16 nWrapInfluenceOnPosition( mnWrapInfluenceOnPosition );
+
+ if ( _bIterativeAsOnceConcurrent &&
+ nWrapInfluenceOnPosition == text::WrapInfluenceOnPosition::ITERATIVE )
+ {
+ nWrapInfluenceOnPosition = text::WrapInfluenceOnPosition::ONCE_CONCURRENT;
+ }
+
+ return nWrapInfluenceOnPosition;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/attr/format.cxx b/sw/source/core/attr/format.cxx
new file mode 100644
index 000000000000..d15daee10f9a
--- /dev/null
+++ b/sw/source/core/attr/format.cxx
@@ -0,0 +1,677 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+
+#include <hintids.hxx> // fuer RES_..
+#include <frame.hxx> // fuer AttrCache
+#include <format.hxx>
+#include <hints.hxx> // fuer SwFmtChg
+#include <doc.hxx>
+#include <paratr.hxx> // fuer SwParaFmt - SwHyphenBug
+#include <swcache.hxx>
+#include <fmtcolfunc.hxx>
+
+TYPEINIT1( SwFmt, SwClient ); //rtti fuer SwFmt
+
+/*************************************************************************
+|* SwFmt::SwFmt
+*************************************************************************/
+
+
+SwFmt::SwFmt( SwAttrPool& rPool, const sal_Char* pFmtNm,
+ const sal_uInt16* pWhichRanges, SwFmt *pDrvdFrm, sal_uInt16 nFmtWhich )
+ : SwModify( pDrvdFrm ),
+ aSet( rPool, pWhichRanges ),
+ nWhichId( nFmtWhich ),
+ nFmtId( 0 ),
+ nPoolFmtId( USHRT_MAX ),
+ nPoolHelpId( USHRT_MAX ),
+ nPoolHlpFileId( UCHAR_MAX )
+{
+ aFmtName.AssignAscii( pFmtNm );
+ bWritten = bFmtInDTOR = bAutoUpdateFmt = sal_False; // LAYER_IMPL
+ bAutoFmt = sal_True;
+
+ if( pDrvdFrm )
+ aSet.SetParent( &pDrvdFrm->aSet );
+}
+
+
+SwFmt::SwFmt( SwAttrPool& rPool, const String &rFmtNm,
+ const sal_uInt16* pWhichRanges, SwFmt *pDrvdFrm, sal_uInt16 nFmtWhich )
+ : SwModify( pDrvdFrm ),
+ aFmtName( rFmtNm ),
+ aSet( rPool, pWhichRanges ),
+ nWhichId( nFmtWhich ),
+ nFmtId( 0 ),
+ nPoolFmtId( USHRT_MAX ),
+ nPoolHelpId( USHRT_MAX ),
+ nPoolHlpFileId( UCHAR_MAX )
+{
+ bWritten = bFmtInDTOR = bAutoUpdateFmt = sal_False; // LAYER_IMPL
+ bAutoFmt = sal_True;
+
+ if( pDrvdFrm )
+ aSet.SetParent( &pDrvdFrm->aSet );
+}
+
+
+SwFmt::SwFmt( const SwFmt& rFmt )
+ : SwModify( rFmt.DerivedFrom() ),
+ aFmtName( rFmt.aFmtName ),
+ aSet( rFmt.aSet ),
+ nWhichId( rFmt.nWhichId ),
+ nFmtId( 0 ),
+ nPoolFmtId( rFmt.GetPoolFmtId() ),
+ nPoolHelpId( rFmt.GetPoolHelpId() ),
+ nPoolHlpFileId( rFmt.GetPoolHlpFileId() )
+{
+ bWritten = bFmtInDTOR = sal_False; // LAYER_IMPL
+ bAutoFmt = rFmt.bAutoFmt;
+ bAutoUpdateFmt = rFmt.bAutoUpdateFmt;
+
+ if( rFmt.DerivedFrom() )
+ aSet.SetParent( &rFmt.DerivedFrom()->aSet );
+ // einige Sonderbehandlungen fuer Attribute
+ aSet.SetModifyAtAttr( this );
+}
+
+/*************************************************************************
+|* SwFmt &SwFmt::operator=(const SwFmt& aFmt)
+|*
+|* Beschreibung Dokument 1.14
+*************************************************************************/
+
+
+SwFmt &SwFmt::operator=(const SwFmt& rFmt)
+{
+ nWhichId = rFmt.nWhichId;
+ nPoolFmtId = rFmt.GetPoolFmtId();
+ nPoolHelpId = rFmt.GetPoolHelpId();
+ nPoolHlpFileId = rFmt.GetPoolHlpFileId();
+
+ if ( IsInCache() )
+ {
+ SwFrm::GetCache().Delete( this );
+ SetInCache( sal_False );
+ }
+ SetInSwFntCache( sal_False );
+
+ // kopiere nur das Attribut-Delta Array
+ SwAttrSet aOld( *aSet.GetPool(), aSet.GetRanges() ),
+ aNew( *aSet.GetPool(), aSet.GetRanges() );
+ aSet.Intersect_BC( rFmt.aSet, &aOld, &aNew );
+ aSet.Put_BC( rFmt.aSet, &aOld, &aNew );
+
+ // einige Sonderbehandlungen fuer Attribute
+ aSet.SetModifyAtAttr( this );
+
+ // PoolItem-Attr erzeugen fuers Modify !!!
+ if( aOld.Count() )
+ {
+ SwAttrSetChg aChgOld( aSet, aOld );
+ SwAttrSetChg aChgNew( aSet, aNew );
+ ModifyNotification( &aChgOld, &aChgNew ); // alle veraenderten werden verschickt
+ }
+
+ if( GetRegisteredIn() != rFmt.GetRegisteredIn() )
+ {
+ if( GetRegisteredIn() )
+ GetRegisteredInNonConst()->Remove(this);
+ if(rFmt.GetRegisteredIn())
+ {
+ const_cast<SwFmt&>(rFmt).GetRegisteredInNonConst()->Add(this);
+ aSet.SetParent( &rFmt.aSet );
+ }
+ else
+ aSet.SetParent( 0 );
+ }
+ bAutoFmt = rFmt.bAutoFmt;
+ bAutoUpdateFmt = rFmt.bAutoUpdateFmt;
+ return *this;
+}
+
+void SwFmt::SetName( const String& rNewName, sal_Bool bBroadcast )
+{
+ OSL_ENSURE(!IsDefault(), "SetName: Defaultformat" );
+ if( bBroadcast )
+ {
+ SwStringMsgPoolItem aOld( RES_NAME_CHANGED, aFmtName );
+ SwStringMsgPoolItem aNew( RES_NAME_CHANGED, rNewName );
+ aFmtName = rNewName;
+ ModifyNotification( &aOld, &aNew );
+ }
+ else
+ {
+ aFmtName = rNewName;
+ }
+}
+
+/* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+ * diese Funktion wird in jedem Copy-Ctor gerufen, damit die
+ * Attribute kopiert werden. Diese koennen erst kopiert werden,
+ * wenn die abgeleitet Klasse existiert, denn beim Setzen der
+ * Attribute wird die Which()-Methode gerufen, die hier in der
+ * Basis-Klasse auf 0 defaultet ist.
+ *
+ * Zusatz: JP 8.4.1994
+ * Wird ueber Dokumentgrenzen kopiert, so muss das neue Dokument
+ * mit angeben werden, in dem this steht. Z.Z. ist das fuers
+ * DropCaps wichtig, dieses haelt Daten, die tief kopiert werden
+ * muessen !!
+ * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */
+
+
+void SwFmt::CopyAttrs( const SwFmt& rFmt, sal_Bool bReplace )
+{
+ // kopiere nur das Attribut-Delta Array
+
+ if ( IsInCache() )
+ {
+ SwFrm::GetCache().Delete( this );
+ SetInCache( sal_False );
+ }
+ SetInSwFntCache( sal_False );
+
+ // Sonderbehandlung fuer einige Attribute
+ SwAttrSet* pChgSet = (SwAttrSet*)&rFmt.aSet;
+
+ if( !bReplace ) // nur die neu, die nicht gesetzt sind ??
+ {
+ if( pChgSet == (SwAttrSet*)&rFmt.aSet ) // Set hier kopieren
+ pChgSet = new SwAttrSet( rFmt.aSet );
+ pChgSet->Differentiate( aSet );
+ }
+
+ // kopiere nur das Attribut-Delta Array
+ if( pChgSet->GetPool() != aSet.GetPool() )
+ pChgSet->CopyToModify( *this );
+ else
+ {
+ SwAttrSet aOld( *aSet.GetPool(), aSet.GetRanges() ),
+ aNew( *aSet.GetPool(), aSet.GetRanges() );
+
+ if ( 0 != aSet.Put_BC( *pChgSet, &aOld, &aNew ) )
+ {
+ // einige Sonderbehandlungen fuer Attribute
+ aSet.SetModifyAtAttr( this );
+
+ SwAttrSetChg aChgOld( aSet, aOld );
+ SwAttrSetChg aChgNew( aSet, aNew );
+ ModifyNotification( &aChgOld, &aChgNew ); // alle veraenderten werden verschickt
+ }
+ }
+
+ if( pChgSet != (SwAttrSet*)&rFmt.aSet ) // Set hier angelegt ?
+ delete pChgSet;
+}
+
+/*************************************************************************
+|* SwFmt::~SwFmt()
+|*
+|* Beschreibung Dokument 1.14
+*************************************************************************/
+
+
+SwFmt::~SwFmt()
+{
+ /* das passiert bei der ObjectDying Message */
+ /* alle Abhaengigen auf DerivedFrom umhaengen */
+ if( GetDepends() )
+ {
+ OSL_ENSURE(DerivedFrom(), "SwFmt::~SwFmt: Def Abhaengige!" );
+
+ bFmtInDTOR = sal_True;
+
+ SwFmt *pParentFmt = DerivedFrom();
+ if (!pParentFmt)
+ {
+ OSL_FAIL( "~SwFmt: parent format missing" );
+ }
+ else
+ {
+ while( GetDepends() )
+ {
+ SwFmtChg aOldFmt(this);
+ SwFmtChg aNewFmt(pParentFmt);
+ SwClient * pDepend = (SwClient*)GetDepends();
+ pParentFmt->Add(pDepend);
+ pDepend->ModifyNotification(&aOldFmt, &aNewFmt);
+ }
+ }
+ }
+}
+
+
+/*************************************************************************
+|* void SwFmt::Modify( const SfxPoolItem* pOldValue, const SfxPoolItem* pNewValue )
+|*
+|* Beschreibung Dokument 1.14
+*************************************************************************/
+
+
+void SwFmt::Modify( const SfxPoolItem* pOldValue, const SfxPoolItem* pNewValue )
+{
+ sal_Bool bWeiter = sal_True; // sal_True = Propagierung an die Abhaengigen
+
+ sal_uInt16 nWhich = pOldValue ? pOldValue->Which() :
+ pNewValue ? pNewValue->Which() : 0 ;
+ switch( nWhich )
+ {
+ case 0: break; // Which-Id von 0 ???
+
+ case RES_OBJECTDYING :
+ {
+ // ist das sterbende Object das "Parent"-Format von diesen Format,
+ // dann haengt sich dieses Format an den Parent vom Parent
+ SwFmt * pFmt = (SwFmt *) ((SwPtrMsgPoolItem *)pNewValue)->pObject;
+
+ // nicht umhaengen wenn dieses das oberste Format ist !!
+ if( GetRegisteredIn() && GetRegisteredIn() == pFmt )
+ {
+ if( pFmt->GetRegisteredIn() )
+ {
+ // wenn Parent, dann im neuen Parent wieder anmelden
+ pFmt->DerivedFrom()->Add( this );
+ aSet.SetParent( &DerivedFrom()->aSet );
+ }
+ else
+ {
+ // sonst auf jeden Fall beim sterbenden abmelden
+ DerivedFrom()->Remove( this );
+ aSet.SetParent( 0 );
+ }
+ }
+ } // OBJECTDYING
+ break;
+
+ case RES_ATTRSET_CHG:
+ if( ((SwAttrSetChg*)pOldValue)->GetTheChgdSet() != &aSet )
+ {
+ //nur die weiter geben, die hier nicht gesetzt sind !!
+ SwAttrSetChg aOld( *(SwAttrSetChg*)pOldValue );
+ SwAttrSetChg aNew( *(SwAttrSetChg*)pNewValue );
+
+ aOld.GetChgSet()->Differentiate( aSet );
+ aNew.GetChgSet()->Differentiate( aSet );
+
+ if( aNew.Count() )
+ // keine mehr gesetzt, dann Ende !!
+ NotifyClients( &aOld, &aNew );
+ bWeiter = sal_False;
+ }
+ break;
+ case RES_FMT_CHG:
+ // falls mein Format Parent umgesetzt wird, dann melde ich
+ // meinen Attrset beim Neuen an.
+
+ // sein eigenes Modify ueberspringen !!
+ if( ((SwFmtChg*)pOldValue)->pChangedFmt != this &&
+ ((SwFmtChg*)pNewValue)->pChangedFmt == DerivedFrom() )
+ {
+ // den Set an den neuen Parent haengen
+ aSet.SetParent( DerivedFrom() ? &DerivedFrom()->aSet : 0 );
+ }
+ break;
+
+ case RES_RESET_FMTWRITTEN:
+ {
+ // IsWritten-Flag zuruecksetzen. Hint nur an abhanegige
+ // Formate (und keine Frames) propagieren.
+ // mba: the code does the opposite from what is written in the comment!
+ ResetWritten();
+ // mba: here we don't use the additional stuff from NotifyClients().
+ // should we?!
+ // mba: move the code that ignores this event to the clients
+ ModifyBroadcast( pOldValue, pNewValue, TYPE(SwFmt) );
+ bWeiter = sal_False;
+ }
+ break;
+
+ default:
+ {
+ // Ist das Attribut in diesem Format definiert, dann auf
+ // NICHT weiter propagieren !!
+ if( SFX_ITEM_SET == aSet.GetItemState( nWhich, sal_False ))
+ {
+// wie finde ich heraus, ob nicht ich die Message versende ??
+// aber wer ruft das hier ????
+// OSL_ENSURE( FALSE, "Modify ohne Absender verschickt" );
+//JP 11.06.96: DropCaps koennen hierher kommen
+ OSL_ENSURE( RES_PARATR_DROP == nWhich, "Modify ohne Absender verschickt" );
+ bWeiter = sal_False;
+ }
+
+ } // default
+ } // switch
+
+ if( bWeiter )
+ {
+ // laufe durch alle abhaengigen Formate
+ NotifyClients( pOldValue, pNewValue );
+ }
+
+}
+
+
+sal_Bool SwFmt::SetDerivedFrom(SwFmt *pDerFrom)
+{
+ if ( pDerFrom )
+ {
+ // Zyklus?
+ const SwFmt* pFmt = pDerFrom;
+ while ( pFmt != 0 )
+ {
+ if ( pFmt == this )
+ return sal_False;
+
+ pFmt=pFmt->DerivedFrom();
+ }
+ }
+ else
+ {
+ // Nichts angegeben, Dflt-Format suchen
+ pDerFrom = this;
+ while ( pDerFrom->DerivedFrom() )
+ pDerFrom = pDerFrom->DerivedFrom();
+ }
+ if ( (pDerFrom == DerivedFrom()) || (pDerFrom == this) )
+ return sal_False;
+
+ OSL_ENSURE( Which()==pDerFrom->Which()
+ || ( Which()==RES_CONDTXTFMTCOLL && pDerFrom->Which()==RES_TXTFMTCOLL)
+ || ( Which()==RES_TXTFMTCOLL && pDerFrom->Which()==RES_CONDTXTFMTCOLL)
+ || ( Which()==RES_FLYFRMFMT && pDerFrom->Which()==RES_FRMFMT ),
+ "SetDerivedFrom: Aepfel von Birnen ableiten?");
+
+ if ( IsInCache() )
+ {
+ SwFrm::GetCache().Delete( this );
+ SetInCache( sal_False );
+ }
+ SetInSwFntCache( sal_False );
+
+ pDerFrom->Add(this);
+ aSet.SetParent( &pDerFrom->aSet );
+
+ SwFmtChg aOldFmt(this);
+ SwFmtChg aNewFmt(this);
+ ModifyNotification( &aOldFmt, &aNewFmt );
+
+ return sal_True;
+}
+
+
+sal_Bool SwFmt::SetFmtAttr(const SfxPoolItem& rAttr )
+{
+ if ( IsInCache() || IsInSwFntCache() )
+ {
+ const sal_uInt16 nWhich = rAttr.Which();
+ CheckCaching( nWhich );
+ }
+
+ // wenn Modify gelockt ist, werden keine Modifies verschickt;
+ // fuer FrmFmt's immer das Modify verschicken!
+ sal_Bool bRet = sal_False;
+ const sal_uInt16 nFmtWhich = Which();
+ if( IsModifyLocked() || (!GetDepends() &&
+ (RES_GRFFMTCOLL == nFmtWhich ||
+ RES_TXTFMTCOLL == nFmtWhich ) ) )
+ {
+ if( 0 != ( bRet = (0 != aSet.Put( rAttr ))) )
+ aSet.SetModifyAtAttr( this );
+ // #i71574#
+ if ( nFmtWhich == RES_TXTFMTCOLL && rAttr.Which() == RES_PARATR_NUMRULE )
+ {
+ TxtFmtCollFunc::CheckTxtFmtCollForDeletionOfAssignmentToOutlineStyle( this );
+ }
+ }
+ else
+ {
+ // kopiere nur das Attribut-Delta Array
+ SwAttrSet aOld( *aSet.GetPool(), aSet.GetRanges() ),
+ aNew( *aSet.GetPool(), aSet.GetRanges() );
+
+ bRet = 0 != aSet.Put_BC( rAttr, &aOld, &aNew );
+ if( bRet )
+ {
+ // einige Sonderbehandlungen fuer Attribute
+ aSet.SetModifyAtAttr( this );
+
+ SwAttrSetChg aChgOld( aSet, aOld );
+ SwAttrSetChg aChgNew( aSet, aNew );
+ ModifyNotification( &aChgOld, &aChgNew ); // alle veraenderten werden verschickt
+ }
+ }
+ return bRet;
+}
+
+
+sal_Bool SwFmt::SetFmtAttr( const SfxItemSet& rSet )
+{
+ if( !rSet.Count() )
+ return sal_False;
+
+ if ( IsInCache() )
+ {
+ SwFrm::GetCache().Delete( this );
+ SetInCache( sal_False );
+ }
+ SetInSwFntCache( sal_False );
+
+ // wenn Modify gelockt ist, werden keine Modifies verschickt;
+ // fuer FrmFmt's immer das Modify verschicken!
+ sal_Bool bRet = sal_False;
+ const sal_uInt16 nFmtWhich = Which();
+ if ( IsModifyLocked() ||
+ ( !GetDepends() &&
+ ( RES_GRFFMTCOLL == nFmtWhich ||
+ RES_TXTFMTCOLL == nFmtWhich ) ) )
+ {
+ if( 0 != ( bRet = (0 != aSet.Put( rSet ))) )
+ aSet.SetModifyAtAttr( this );
+ // #i71574#
+ if ( nFmtWhich == RES_TXTFMTCOLL )
+ {
+ TxtFmtCollFunc::CheckTxtFmtCollForDeletionOfAssignmentToOutlineStyle( this );
+ }
+ }
+ else
+ {
+ SwAttrSet aOld( *aSet.GetPool(), aSet.GetRanges() ),
+ aNew( *aSet.GetPool(), aSet.GetRanges() );
+ bRet = 0 != aSet.Put_BC( rSet, &aOld, &aNew );
+ if( bRet )
+ {
+ // einige Sonderbehandlungen fuer Attribute
+ aSet.SetModifyAtAttr( this );
+ SwAttrSetChg aChgOld( aSet, aOld );
+ SwAttrSetChg aChgNew( aSet, aNew );
+ ModifyNotification( &aChgOld, &aChgNew ); // alle veraenderten werden verschickt
+ }
+ }
+ return bRet;
+}
+
+// Nimmt den Hint mit nWhich aus dem Delta-Array
+
+
+sal_Bool SwFmt::ResetFmtAttr( sal_uInt16 nWhich1, sal_uInt16 nWhich2 )
+{
+ if( !aSet.Count() )
+ return sal_False;
+
+ if( !nWhich2 || nWhich2 < nWhich1 )
+ nWhich2 = nWhich1; // dann setze auf 1. Id, nur dieses Item
+
+ if ( IsInCache() || IsInSwFntCache() )
+ {
+ for( sal_uInt16 n = nWhich1; n < nWhich2; ++n )
+ CheckCaching( n );
+ }
+
+ // wenn Modify gelockt ist, werden keine Modifies verschickt
+ if( IsModifyLocked() )
+ return 0 != (( nWhich2 == nWhich1 )
+ ? aSet.ClearItem( nWhich1 )
+ : aSet.ClearItem_BC( nWhich1, nWhich2 ));
+
+ SwAttrSet aOld( *aSet.GetPool(), aSet.GetRanges() ),
+ aNew( *aSet.GetPool(), aSet.GetRanges() );
+ sal_Bool bRet = 0 != aSet.ClearItem_BC( nWhich1, nWhich2, &aOld, &aNew );
+
+ if( bRet )
+ {
+ SwAttrSetChg aChgOld( aSet, aOld );
+ SwAttrSetChg aChgNew( aSet, aNew );
+ ModifyNotification( &aChgOld, &aChgNew ); // alle veraenderten werden verschickt
+ }
+ return bRet;
+}
+
+
+
+// #i73790#
+// method renamed
+sal_uInt16 SwFmt::ResetAllFmtAttr()
+{
+ if( !aSet.Count() )
+ return 0;
+
+ if ( IsInCache() )
+ {
+ SwFrm::GetCache().Delete( this );
+ SetInCache( sal_False );
+ }
+ SetInSwFntCache( sal_False );
+
+ // wenn Modify gelockt ist, werden keine Modifies verschickt
+ if( IsModifyLocked() )
+ return aSet.ClearItem( 0 );
+
+ SwAttrSet aOld( *aSet.GetPool(), aSet.GetRanges() ),
+ aNew( *aSet.GetPool(), aSet.GetRanges() );
+ sal_Bool bRet = 0 != aSet.ClearItem_BC( 0, &aOld, &aNew );
+
+ if( bRet )
+ {
+ SwAttrSetChg aChgOld( aSet, aOld );
+ SwAttrSetChg aChgNew( aSet, aNew );
+ ModifyNotification( &aChgOld, &aChgNew ); // alle veraenderten werden verschickt
+ }
+ return aNew.Count();
+}
+
+
+/*************************************************************************
+|* void SwFmt::GetInfo( const SfxPoolItem& ) const
+*************************************************************************/
+
+
+sal_Bool SwFmt::GetInfo( SfxPoolItem& rInfo ) const
+{
+ sal_Bool bRet = SwModify::GetInfo( rInfo );
+ return bRet;
+}
+
+
+void SwFmt::DelDiffs( const SfxItemSet& rSet )
+{
+ if( !aSet.Count() )
+ return;
+
+ if ( IsInCache() )
+ {
+ SwFrm::GetCache().Delete( this );
+ SetInCache( sal_False );
+ }
+ SetInSwFntCache( sal_False );
+
+ // wenn Modify gelockt ist, werden keine Modifies verschickt
+ if( IsModifyLocked() )
+ {
+ aSet.Intersect( rSet );
+ return;
+ }
+
+ SwAttrSet aOld( *aSet.GetPool(), aSet.GetRanges() ),
+ aNew( *aSet.GetPool(), aSet.GetRanges() );
+ sal_Bool bRet = 0 != aSet.Intersect_BC( rSet, &aOld, &aNew );
+
+ if( bRet )
+ {
+ SwAttrSetChg aChgOld( aSet, aOld );
+ SwAttrSetChg aChgNew( aSet, aNew );
+ ModifyNotification( &aChgOld, &aChgNew ); // alle veraenderten werden verschickt
+ }
+}
+
+/** SwFmt::IsBackgroundTransparent
+
+ Virtual method to determine, if background of format is transparent.
+ Default implementation returns false. Thus, subclasses have to overload
+ method, if the specific subclass can have a transparent background.
+
+ @author OD
+
+ @return false, default implementation
+*/
+sal_Bool SwFmt::IsBackgroundTransparent() const
+{
+ return sal_False;
+}
+
+/** SwFmt::IsShadowTransparent
+
+ Virtual method to determine, if shadow of format is transparent.
+ Default implementation returns false. Thus, subclasses have to overload
+ method, if the specific subclass can have a transparent shadow.
+
+ @return false, default implementation
+*/
+sal_Bool SwFmt::IsShadowTransparent() const
+{
+ return sal_False;
+}
+
+/*
+ * Document Interface Access
+ */
+const IDocumentSettingAccess* SwFmt::getIDocumentSettingAccess() const { return GetDoc(); }
+const IDocumentDrawModelAccess* SwFmt::getIDocumentDrawModelAccess() const { return GetDoc(); }
+IDocumentDrawModelAccess* SwFmt::getIDocumentDrawModelAccess() { return GetDoc(); }
+const IDocumentLayoutAccess* SwFmt::getIDocumentLayoutAccess() const { return GetDoc(); }
+IDocumentLayoutAccess* SwFmt::getIDocumentLayoutAccess() { return GetDoc(); }
+IDocumentTimerAccess* SwFmt::getIDocumentTimerAccess() { return GetDoc(); }
+IDocumentFieldsAccess* SwFmt::getIDocumentFieldsAccess() { return GetDoc(); }
+IDocumentChartDataProviderAccess* SwFmt::getIDocumentChartDataProviderAccess() { return GetDoc(); }
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/attr/hints.cxx b/sw/source/core/attr/hints.cxx
new file mode 100644
index 000000000000..da097a79c0fd
--- /dev/null
+++ b/sw/source/core/attr/hints.cxx
@@ -0,0 +1,296 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+#include <hints.hxx>
+
+#include <com/sun/star/i18n/ScriptType.hdl>
+#include <editeng/scripttypeitem.hxx>
+#include <hintids.hxx>
+#include <swtypes.hxx>
+#include <ndtxt.hxx>
+
+SwFmtChg::SwFmtChg( SwFmt *pFmt )
+ : SwMsgPoolItem( RES_FMT_CHG ),
+ pChangedFmt( pFmt )
+{}
+
+
+
+SwInsTxt::SwInsTxt( xub_StrLen nP, xub_StrLen nL )
+ : SwMsgPoolItem( RES_INS_TXT ),
+ nPos( nP ),
+ nLen( nL )
+{}
+
+
+
+SwDelChr::SwDelChr( xub_StrLen nP )
+ : SwMsgPoolItem( RES_DEL_CHR ),
+ nPos( nP )
+{}
+
+
+
+SwDelTxt::SwDelTxt( xub_StrLen nS, xub_StrLen nL )
+ : SwMsgPoolItem( RES_DEL_TXT ),
+ nStart( nS ),
+ nLen( nL )
+{}
+
+
+
+SwUpdateAttr::SwUpdateAttr( xub_StrLen nS, xub_StrLen nE, sal_uInt16 nW )
+ : SwMsgPoolItem( RES_UPDATE_ATTR ),
+ nStart( nS ),
+ nEnd( nE ),
+ nWhichAttr( nW )
+{}
+
+
+// SwRefMarkFldUpdate wird verschickt, wenn sich die ReferenzMarkierungen
+// Updaten sollen. Um Seiten-/KapitelNummer feststellen zu koennen, muss
+// der akt. Frame befragt werden. Dafuer wird das akt. OutputDevice benoetigt.
+
+
+SwRefMarkFldUpdate::SwRefMarkFldUpdate( const OutputDevice* pOutput )
+ : SwMsgPoolItem( RES_REFMARKFLD_UPDATE ),
+ pOut( pOutput )
+{
+ OSL_ENSURE( pOut, "es muss ein OutputDevice-Pointer gesetzt werden!" );
+}
+
+
+SwDocPosUpdate::SwDocPosUpdate( const SwTwips nDcPos )
+ : SwMsgPoolItem( RES_DOCPOS_UPDATE ),
+ nDocPos(nDcPos)
+{}
+
+
+
+// SwTableFmlUpdate wird verschickt, wenn sich die Tabelle neu berechnen soll
+SwTableFmlUpdate::SwTableFmlUpdate( const SwTable* pNewTbl )
+ : SwMsgPoolItem( RES_TABLEFML_UPDATE ),
+ pTbl( pNewTbl ), pHistory( 0 ), nSplitLine( USHRT_MAX ),
+ eFlags( TBL_CALC )
+{
+ DATA.pDelTbl = 0;
+ bModified = bBehindSplitLine = sal_False;
+ OSL_ENSURE( pTbl, "es muss ein Table-Pointer gesetzt werden!" );
+}
+
+
+SwAutoFmtGetDocNode::SwAutoFmtGetDocNode( const SwNodes* pNds )
+ : SwMsgPoolItem( RES_AUTOFMT_DOCNODE ),
+ pCntntNode( 0 ), pNodes( pNds )
+{}
+
+
+SwAttrSetChg::SwAttrSetChg( const SwAttrSet& rTheSet, SwAttrSet& rSet )
+ : SwMsgPoolItem( RES_ATTRSET_CHG ),
+ bDelSet( sal_False ),
+ pChgSet( &rSet ),
+ pTheChgdSet( &rTheSet )
+{}
+
+
+SwAttrSetChg::SwAttrSetChg( const SwAttrSetChg& rChgSet )
+ : SwMsgPoolItem( RES_ATTRSET_CHG ),
+ bDelSet( sal_True ),
+ pTheChgdSet( rChgSet.pTheChgdSet )
+{
+ pChgSet = new SwAttrSet( *rChgSet.pChgSet );
+}
+
+
+SwAttrSetChg::~SwAttrSetChg()
+{
+ if( bDelSet )
+ delete pChgSet;
+}
+
+
+#if OSL_DEBUG_LEVEL > 1
+
+void SwAttrSetChg::ClearItem( sal_uInt16 nWhch )
+{
+ OSL_ENSURE( bDelSet, "der Set darf nicht veraendert werden!" );
+ pChgSet->ClearItem( nWhch );
+}
+
+#endif
+
+
+SwMsgPoolItem::SwMsgPoolItem( sal_uInt16 nWhch )
+ : SfxPoolItem( nWhch )
+{}
+
+
+// "Overhead" vom SfxPoolItem
+int SwMsgPoolItem::operator==( const SfxPoolItem& ) const
+{
+ OSL_FAIL( "SwMsgPoolItem kennt kein ==" );
+ return 0;
+}
+
+
+SfxPoolItem* SwMsgPoolItem::Clone( SfxItemPool* ) const
+{
+ OSL_FAIL( "SwMsgPoolItem kennt kein Clone" );
+ return 0;
+}
+
+/******************************************************************************
+ * hole aus der Default-Attribut Tabelle ueber den Which-Wert
+ * das entsprechende default Attribut.
+ * Ist keines vorhanden, returnt ein 0-Pointer !!!
+ * Used to be inlined (hintids.hxx) in PRODUCT.
+ ******************************************************************************/
+#if OSL_DEBUG_LEVEL > 1
+const SfxPoolItem* GetDfltAttr( sal_uInt16 nWhich )
+{
+ OSL_ASSERT( nWhich < POOLATTR_END && nWhich >= POOLATTR_BEGIN );
+
+ SfxPoolItem *pHt = aAttrTab[ nWhich - POOLATTR_BEGIN ];
+ OSL_ENSURE( pHt, "GetDfltFmtAttr(): Dflt == 0" );
+ return pHt;
+}
+#else
+const SfxPoolItem* GetDfltAttr( sal_uInt16 nWhich )
+{
+ return aAttrTab[ nWhich - POOLATTR_BEGIN ];
+}
+#endif
+
+
+
+SwCondCollCondChg::SwCondCollCondChg( SwFmt *pFmt )
+ : SwMsgPoolItem( RES_CONDCOLL_CONDCHG ), pChangedFmt( pFmt )
+{
+}
+
+
+SwVirtPageNumInfo::SwVirtPageNumInfo( const SwPageFrm *pPg ) :
+ SwMsgPoolItem( RES_VIRTPAGENUM_INFO ),
+ pPage( 0 ),
+ pOrigPage( pPg ),
+ pFrm( 0 )
+{
+}
+
+
+SwFindNearestNode::SwFindNearestNode( const SwNode& rNd )
+ : SwMsgPoolItem( RES_FINDNEARESTNODE ), pNd( &rNd ), pFnd( 0 )
+{
+}
+
+void SwFindNearestNode::CheckNode( const SwNode& rNd )
+{
+ if( &pNd->GetNodes() == &rNd.GetNodes() )
+ {
+ sal_uLong nIdx = rNd.GetIndex();
+ if( nIdx < pNd->GetIndex() &&
+ ( !pFnd || nIdx > pFnd->GetIndex() ) &&
+ nIdx > rNd.GetNodes().GetEndOfExtras().GetIndex() )
+ pFnd = &rNd;
+ }
+}
+
+
+
+sal_uInt16 GetWhichOfScript( sal_uInt16 nWhich, sal_uInt16 nScript )
+{
+ static const sal_uInt16 aLangMap[3] =
+ { RES_CHRATR_LANGUAGE, RES_CHRATR_CJK_LANGUAGE, RES_CHRATR_CTL_LANGUAGE };
+ static const sal_uInt16 aFontMap[3] =
+ { RES_CHRATR_FONT, RES_CHRATR_CJK_FONT, RES_CHRATR_CTL_FONT};
+ static const sal_uInt16 aFontSizeMap[3] =
+ { RES_CHRATR_FONTSIZE, RES_CHRATR_CJK_FONTSIZE, RES_CHRATR_CTL_FONTSIZE };
+ static const sal_uInt16 aWeightMap[3] =
+ { RES_CHRATR_WEIGHT, RES_CHRATR_CJK_WEIGHT, RES_CHRATR_CTL_WEIGHT};
+ static const sal_uInt16 aPostureMap[3] =
+ { RES_CHRATR_POSTURE, RES_CHRATR_CJK_POSTURE, RES_CHRATR_CTL_POSTURE};
+
+ const sal_uInt16* pM;
+ switch( nWhich )
+ {
+ case RES_CHRATR_LANGUAGE:
+ case RES_CHRATR_CJK_LANGUAGE:
+ case RES_CHRATR_CTL_LANGUAGE:
+ pM = aLangMap;
+ break;
+
+ case RES_CHRATR_FONT:
+ case RES_CHRATR_CJK_FONT:
+ case RES_CHRATR_CTL_FONT:
+ pM = aFontMap;
+ break;
+
+ case RES_CHRATR_FONTSIZE:
+ case RES_CHRATR_CJK_FONTSIZE:
+ case RES_CHRATR_CTL_FONTSIZE:
+ pM = aFontSizeMap;
+ break;
+
+ case RES_CHRATR_WEIGHT:
+ case RES_CHRATR_CJK_WEIGHT:
+ case RES_CHRATR_CTL_WEIGHT:
+ pM = aWeightMap;
+ break;
+ case RES_CHRATR_POSTURE:
+ case RES_CHRATR_CJK_POSTURE:
+ case RES_CHRATR_CTL_POSTURE:
+ pM = aPostureMap;
+ break;
+
+ default:
+ pM = 0;
+ }
+
+ sal_uInt16 nRet;
+ if( pM )
+ {
+ using namespace ::com::sun::star::i18n;
+ {
+ if( ScriptType::WEAK == nScript )
+ nScript = GetI18NScriptTypeOfLanguage( (sal_uInt16)GetAppLanguage() );
+ switch( nScript)
+ {
+ case ScriptType::COMPLEX: ++pM; // no break;
+ case ScriptType::ASIAN: ++pM; // no break;
+ default: nRet = *pM;
+ }
+ }
+ }
+ else
+ nRet = nWhich;
+ return nRet;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/attr/swatrset.cxx b/sw/source/core/attr/swatrset.cxx
new file mode 100644
index 000000000000..558f5ba7caf4
--- /dev/null
+++ b/sw/source/core/attr/swatrset.cxx
@@ -0,0 +1,395 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+
+#include <hintids.hxx>
+#include <svl/whiter.hxx>
+#include <editeng/colritem.hxx>
+#include <editeng/brshitem.hxx>
+#include <editeng/bolnitem.hxx>
+#include <editeng/boxitem.hxx>
+#include <svx/xtable.hxx>
+#include <fmtpdsc.hxx>
+#include <pagedesc.hxx>
+#include <charfmt.hxx>
+#include <doc.hxx>
+#include <node.hxx>
+#include <paratr.hxx> // fuer SetModifyAtAttr
+#include <cellatr.hxx> // fuer SetModifyAtAttr
+#include <cmdid.h>
+#include <istyleaccess.hxx>
+#include <numrule.hxx>
+#include <list.hxx>
+
+
+SwAttrPool::SwAttrPool( SwDoc* pD )
+ : SfxItemPool( String::CreateFromAscii(
+ RTL_CONSTASCII_STRINGPARAM( "SWG" )),
+ POOLATTR_BEGIN, POOLATTR_END-1,
+ aSlotTab, aAttrTab ),
+ pDoc( pD )
+{
+ SetVersionMap( 1, 1, 60, pVersionMap1 );
+ SetVersionMap( 2, 1, 75, pVersionMap2 );
+ SetVersionMap( 3, 1, 86, pVersionMap3 );
+ SetVersionMap( 4, 1,121, pVersionMap4 );
+ // #i18732# - apply new version map
+ SetVersionMap( 5, 1,130, pVersionMap5 );
+ SetVersionMap( 6, 1,136, pVersionMap6 );
+}
+
+SwAttrPool::~SwAttrPool()
+{
+}
+
+SwAttrSet::SwAttrSet( SwAttrPool& rPool, sal_uInt16 nWh1, sal_uInt16 nWh2 )
+ : SfxItemSet( rPool, nWh1, nWh2 ), pOldSet( 0 ), pNewSet( 0 )
+{
+}
+
+
+SwAttrSet::SwAttrSet( SwAttrPool& rPool, const sal_uInt16* nWhichPairTable )
+ : SfxItemSet( rPool, nWhichPairTable ), pOldSet( 0 ), pNewSet( 0 )
+{
+}
+
+
+SwAttrSet::SwAttrSet( const SwAttrSet& rSet )
+ : SfxItemSet( rSet ), pOldSet( 0 ), pNewSet( 0 )
+{
+}
+
+SfxItemSet* SwAttrSet::Clone( sal_Bool bItems, SfxItemPool *pToPool ) const
+{
+ if ( pToPool && pToPool != GetPool() )
+ {
+ SwAttrPool* pAttrPool = dynamic_cast< SwAttrPool* >(pToPool);
+ SfxItemSet* pTmpSet = 0;
+ if ( !pAttrPool )
+ pTmpSet = SfxItemSet::Clone( bItems, pToPool );
+ else
+ {
+ pTmpSet = new SwAttrSet( *pAttrPool, GetRanges() );
+ if ( bItems )
+ {
+ SfxWhichIter aIter(*pTmpSet);
+ sal_uInt16 nWhich = aIter.FirstWhich();
+ while ( nWhich )
+ {
+ const SfxPoolItem* pItem;
+ if ( SFX_ITEM_SET == GetItemState( nWhich, sal_False, &pItem ) )
+ pTmpSet->Put( *pItem, pItem->Which() );
+ nWhich = aIter.NextWhich();
+ }
+ }
+ }
+ return pTmpSet;
+ }
+ else
+ return bItems
+ ? new SwAttrSet( *this )
+ : new SwAttrSet( *GetPool(), GetRanges() );
+}
+
+int SwAttrSet::Put_BC( const SfxPoolItem& rAttr,
+ SwAttrSet* pOld, SwAttrSet* pNew )
+{
+ pNewSet = pNew;
+ pOldSet = pOld;
+ int nRet = 0 != SfxItemSet::Put( rAttr );
+ pOldSet = pNewSet = 0;
+ return nRet;
+}
+
+
+int SwAttrSet::Put_BC( const SfxItemSet& rSet,
+ SwAttrSet* pOld, SwAttrSet* pNew )
+{
+ pNewSet = pNew;
+ pOldSet = pOld;
+ int nRet = 0 != SfxItemSet::Put( rSet );
+ pOldSet = pNewSet = 0;
+ return nRet;
+}
+
+
+
+sal_uInt16 SwAttrSet::ClearItem_BC( sal_uInt16 nWhich,
+ SwAttrSet* pOld, SwAttrSet* pNew )
+{
+ pNewSet = pNew;
+ pOldSet = pOld;
+ sal_uInt16 nRet = SfxItemSet::ClearItem( nWhich );
+ pOldSet = pNewSet = 0;
+ return nRet;
+}
+
+
+sal_uInt16 SwAttrSet::ClearItem_BC( sal_uInt16 nWhich1, sal_uInt16 nWhich2,
+ SwAttrSet* pOld, SwAttrSet* pNew )
+{
+ OSL_ENSURE( nWhich1 <= nWhich2, "kein gueltiger Bereich" );
+ pNewSet = pNew;
+ pOldSet = pOld;
+ sal_uInt16 nRet = 0;
+ for( ; nWhich1 <= nWhich2; ++nWhich1 )
+ nRet = nRet + SfxItemSet::ClearItem( nWhich1 );
+ pOldSet = pNewSet = 0;
+ return nRet;
+}
+
+
+
+int SwAttrSet::Intersect_BC( const SfxItemSet& rSet,
+ SwAttrSet* pOld, SwAttrSet* pNew )
+{
+ pNewSet = pNew;
+ pOldSet = pOld;
+ SfxItemSet::Intersect( rSet );
+ pOldSet = pNewSet = 0;
+ return pNew ? pNew->Count() : ( pOld ? pOld->Count() : 0 );
+}
+
+// Notification-Callback
+void SwAttrSet::Changed( const SfxPoolItem& rOld,
+ const SfxPoolItem& rNew )
+{
+ if( pOldSet )
+ pOldSet->PutChgd( rOld );
+
+ if( pNewSet )
+ pNewSet->PutChgd( rNew );
+}
+
+
+// ----------------------------------------------------------------
+// Sonderbehandlung fuer einige Attribute
+// Setze den Modify-Pointer (alten pDefinedIn) bei folgenden Attributen:
+// - SwFmtDropCaps
+// - SwFmtPageDesc
+// (Wird beim Einfuegen in Formate/Nodes gerufen)
+// ----------------------------------------------------------------
+
+bool SwAttrSet::SetModifyAtAttr( const SwModify* pModify )
+{
+ bool bSet = false;
+
+ const SfxPoolItem* pItem;
+ if( SFX_ITEM_SET == GetItemState( RES_PAGEDESC, sal_False, &pItem ) &&
+ ((SwFmtPageDesc*)pItem)->GetDefinedIn() != pModify )
+ {
+ ((SwFmtPageDesc*)pItem)->ChgDefinedIn( pModify );
+ bSet = true;
+ }
+
+ if( SFX_ITEM_SET == GetItemState( RES_PARATR_DROP, sal_False, &pItem ) &&
+ ((SwFmtDrop*)pItem)->GetDefinedIn() != pModify )
+ {
+ // CharFormat gesetzt und dann noch in unterschiedlichen
+ // Attribut Pools, dann muss das CharFormat kopiert werden!
+ SwCharFmt* pCharFmt;
+ if( 0 != ( pCharFmt = ((SwFmtDrop*)pItem)->GetCharFmt() )
+ && GetPool() != pCharFmt->GetAttrSet().GetPool() )
+ {
+ pCharFmt = GetDoc()->CopyCharFmt( *pCharFmt );
+ ((SwFmtDrop*)pItem)->SetCharFmt( pCharFmt );
+ }
+ ((SwFmtDrop*)pItem)->ChgDefinedIn( pModify );
+ bSet = true;
+ }
+
+ if( SFX_ITEM_SET == GetItemState( RES_BOXATR_FORMULA, sal_False, &pItem ) &&
+ ((SwTblBoxFormula*)pItem)->GetDefinedIn() != pModify )
+ {
+ ((SwTblBoxFormula*)pItem)->ChgDefinedIn( pModify );
+ bSet = true;
+ }
+
+ return bSet;
+}
+
+void SwAttrSet::CopyToModify( SwModify& rMod ) const
+{
+ // kopiere die Attribute ggfs. ueber Dokumentgrenzen
+ SwCntntNode* pCNd = PTR_CAST( SwCntntNode, &rMod );
+ SwFmt* pFmt = PTR_CAST( SwFmt, &rMod );
+
+ if( pCNd || pFmt )
+ {
+ if( Count() )
+ {
+ // #i92811#
+ SfxStringItem* pNewListIdItem( 0 );
+
+ const SfxPoolItem* pItem;
+ const SwDoc *pSrcDoc = GetDoc();
+ SwDoc *pDstDoc = pCNd ? pCNd->GetDoc() : pFmt->GetDoc();
+
+ // muss die NumRule kopiert werden?
+ if( pSrcDoc != pDstDoc && SFX_ITEM_SET == GetItemState(
+ RES_PARATR_NUMRULE, sal_False, &pItem ) )
+ {
+ const String& rNm = ((SwNumRuleItem*)pItem)->GetValue();
+ if( rNm.Len() )
+ {
+ SwNumRule* pDestRule = pDstDoc->FindNumRulePtr( rNm );
+ if( pDestRule )
+ pDestRule->SetInvalidRule( sal_True );
+ else
+ pDstDoc->MakeNumRule( rNm,
+ pSrcDoc->FindNumRulePtr( rNm ) );
+ }
+ }
+
+ // copy list and if needed also the corresponding list style
+ // for text nodes
+ if ( pSrcDoc != pDstDoc &&
+ pCNd && pCNd->IsTxtNode() &&
+ GetItemState( RES_PARATR_LIST_ID, sal_False, &pItem ) == SFX_ITEM_SET )
+ {
+ const String& sListId =
+ dynamic_cast<const SfxStringItem*>(pItem)->GetValue();
+ if ( sListId.Len() > 0 &&
+ !pDstDoc->getListByName( sListId ) )
+ {
+ const SwList* pList = pSrcDoc->getListByName( sListId );
+ // copy list style, if needed
+ const String sDefaultListStyleName =
+ pList->GetDefaultListStyleName();
+ // #i92811#
+ const SwNumRule* pDstDocNumRule =
+ pDstDoc->FindNumRulePtr( sDefaultListStyleName );
+ if ( !pDstDocNumRule )
+ {
+ pDstDoc->MakeNumRule( sDefaultListStyleName,
+ pSrcDoc->FindNumRulePtr( sDefaultListStyleName ) );
+ }
+ else
+ {
+ const SwNumRule* pSrcDocNumRule =
+ pSrcDoc->FindNumRulePtr( sDefaultListStyleName );
+ // If list id of text node equals the list style's
+ // default list id in the source document, the same
+ // should be hold in the destination document.
+ // Thus, create new list id item.
+ if ( sListId == pSrcDocNumRule->GetDefaultListId() )
+ {
+ pNewListIdItem = new SfxStringItem (
+ RES_PARATR_LIST_ID,
+ pDstDocNumRule->GetDefaultListId() );
+ }
+ }
+ // check again, if list exist, because <SwDoc::MakeNumRule(..)>
+ // could have also created it.
+ if ( pNewListIdItem == 0 &&
+ !pDstDoc->getListByName( sListId ) )
+ {
+ // copy list
+ pDstDoc->createList( sListId, sDefaultListStyleName );
+ }
+ }
+ }
+
+ // Seitenvorlagenwechsel mit kopieren Gegenueber dem alten
+ // Verhalten, sie zu entfernen
+ const SwPageDesc* pPgDesc;
+ if( pSrcDoc != pDstDoc && SFX_ITEM_SET == GetItemState(
+ RES_PAGEDESC, sal_False, &pItem ) &&
+ 0 != ( pPgDesc = ((SwFmtPageDesc*)pItem)->GetPageDesc()) )
+ {
+ SfxItemSet aTmpSet( *this );
+
+ SwPageDesc* pDstPgDesc = pDstDoc->FindPageDescByName(
+ pPgDesc->GetName() );
+ if( !pDstPgDesc )
+ {
+ // dann kopieren, ansonsten den benutzen
+ pDstPgDesc = &pDstDoc->_GetPageDesc( pDstDoc->MakePageDesc(
+ pPgDesc->GetName() ));
+ pDstDoc->CopyPageDesc( *pPgDesc, *pDstPgDesc );
+ }
+ SwFmtPageDesc aDesc( pDstPgDesc );
+ aDesc.SetNumOffset( ((SwFmtPageDesc*)pItem)->GetNumOffset() );
+ aTmpSet.Put( aDesc );
+
+ if( pCNd )
+ {
+ // #i92811#
+ if ( pNewListIdItem != 0 )
+ {
+ aTmpSet.Put( *pNewListIdItem );
+ }
+ pCNd->SetAttr( aTmpSet );
+ }
+ else
+ pFmt->SetFmtAttr( aTmpSet );
+ }
+ else if( pCNd )
+ {
+ // #i92811#
+ if ( pNewListIdItem != 0 )
+ {
+ SfxItemSet aTmpSet( *this );
+ aTmpSet.Put( *pNewListIdItem );
+ pCNd->SetAttr( aTmpSet );
+ }
+ else
+ {
+ pCNd->SetAttr( *this );
+ }
+ }
+ else
+ pFmt->SetFmtAttr( *this );
+
+ // #i92811#
+ delete pNewListIdItem;
+ pNewListIdItem = 0;
+ }
+ }
+#if OSL_DEBUG_LEVEL > 1
+ else
+ OSL_ENSURE( !this, "weder Format noch ContentNode - keine Attribute kopiert");
+#endif
+}
+
+// check if ID is InRange of AttrSet-Ids
+sal_Bool IsInRange( const sal_uInt16* pRange, const sal_uInt16 nId )
+{
+ while( *pRange )
+ {
+ if( *pRange <= nId && nId <= *(pRange+1) )
+ return sal_True;
+ pRange += 2;
+ }
+ return sal_False;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/bastyp/SwSmartTagMgr.cxx b/sw/source/core/bastyp/SwSmartTagMgr.cxx
new file mode 100644
index 000000000000..2e773d532e41
--- /dev/null
+++ b/sw/source/core/bastyp/SwSmartTagMgr.cxx
@@ -0,0 +1,85 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+#include "SwSmartTagMgr.hxx"
+
+#include <osl/mutex.hxx>
+#include <vcl/svapp.hxx>
+#include <swmodule.hxx>
+
+#include <docsh.hxx>
+
+using namespace com::sun::star;
+using namespace com::sun::star::uno;
+
+SwSmartTagMgr* SwSmartTagMgr::mpTheSwSmartTagMgr = 0;
+
+SwSmartTagMgr& SwSmartTagMgr::Get()
+{
+ if ( !mpTheSwSmartTagMgr )
+ {
+ mpTheSwSmartTagMgr = new SwSmartTagMgr( SwDocShell::Factory().GetModuleName() );
+ mpTheSwSmartTagMgr->Init(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Writer")));
+ }
+ return *mpTheSwSmartTagMgr;
+}
+
+SwSmartTagMgr::SwSmartTagMgr( const rtl::OUString& rModuleName ) :
+ SmartTagMgr( rModuleName )
+{
+}
+
+SwSmartTagMgr::~SwSmartTagMgr()
+{
+}
+
+// ::com::sun::star::util::XModifyListener
+void SwSmartTagMgr::modified( const lang::EventObject& rEO ) throw( RuntimeException )
+{
+ SolarMutexGuard aGuard;
+
+ // Installed recognizers have changed. We remove all existing smart tags:
+ SW_MOD()->CheckSpellChanges( sal_False, sal_True, sal_True, sal_True );
+
+ SmartTagMgr::modified( rEO );
+}
+
+// ::com::sun::star::util::XChangesListener
+void SwSmartTagMgr::changesOccurred( const util::ChangesEvent& rEvent ) throw( RuntimeException)
+{
+ SolarMutexGuard aGuard;
+
+ // Configuration has changed. We remove all existing smart tags:
+ SW_MOD()->CheckSpellChanges( sal_False, sal_True, sal_True, sal_True );
+
+ SmartTagMgr::changesOccurred( rEvent );
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/bastyp/bparr.cxx b/sw/source/core/bastyp/bparr.cxx
new file mode 100644
index 000000000000..f7f87e160dad
--- /dev/null
+++ b/sw/source/core/bastyp/bparr.cxx
@@ -0,0 +1,582 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+
+
+#include <string.h>
+#include <limits.h>
+#include "bparr.hxx"
+
+// die Blockverwaltung waechst/schrumpft immer um 20 Bloecke, das sind dann
+// immer ~ 20 * MAXENTRY == 20000 Eintraege
+const sal_uInt16 nBlockGrowSize = 20;
+
+#if OSL_DEBUG_LEVEL > 2
+
+#define CHECKIDX( p, n, i, c ) CheckIdx( p, n, i, c );
+
+void CheckIdx( BlockInfo** ppInf, sal_uInt16 nBlock, sal_uLong nSize, sal_uInt16 nCur )
+{
+ DBG_ASSERT( !nSize || nCur < nBlock, "BigPtrArray: CurIndex steht falsch" );
+
+ sal_uLong nIdx = 0;
+ for( sal_uInt16 nCnt = 0; nCnt < nBlock; ++nCnt, ++ppInf )
+ {
+ nIdx += (*ppInf)->nElem;
+ // Array mit Luecken darf es nicht geben
+ DBG_ASSERT( !nCnt || (*(ppInf-1))->nEnd + 1 == (*ppInf)->nStart,
+ "BigPtrArray: Luecke in der Verwaltung!" );
+ }
+
+ DBG_ASSERT( nIdx == nSize, "BigPtrArray: Anzahl ungueltig" );
+}
+
+#else
+
+#define CHECKIDX( p, n, i, c )
+
+#endif
+
+
+BigPtrArray::BigPtrArray()
+{
+ nBlock = nCur = 0;
+ nSize = 0;
+ nMaxBlock = nBlockGrowSize; // == 20 * 1000 Eintraege
+ ppInf = new BlockInfo* [ nMaxBlock ];
+}
+
+
+
+BigPtrArray::~BigPtrArray()
+{
+ if( nBlock )
+ {
+ BlockInfo** pp = ppInf;
+ for( sal_uInt16 n = 0; n < nBlock; ++n, ++pp )
+ {
+ delete[] (*pp)->pData;
+ delete *pp;
+ }
+ }
+ delete[] ppInf;
+}
+
+// Auch der Move ist schlicht. Optimieren ist hier wg. der
+// Stueckelung des Feldes zwecklos!
+
+void BigPtrArray::Move( sal_uLong from, sal_uLong to )
+{
+ sal_uInt16 cur = Index2Block( from );
+ BlockInfo* p = ppInf[ cur ];
+ ElementPtr pElem = p->pData[ from - p->nStart ];
+ Insert( pElem, to ); // erst einfuegen, dann loeschen !!!!
+ Remove( ( to < from ) ? ( from + 1 ) : from );
+}
+
+// das Ende ist EXCLUSIV
+
+
+void BigPtrArray::ForEach( sal_uLong nStart, sal_uLong nEnd,
+ FnForEach fn, void* pArgs )
+{
+ if( nEnd > nSize )
+ nEnd = nSize;
+
+ if( nStart < nEnd )
+ {
+ sal_uInt16 cur = Index2Block( nStart );
+ BlockInfo** pp = ppInf + cur;
+ BlockInfo* p = *pp;
+ sal_uInt16 nElem = sal_uInt16( nStart - p->nStart );
+ ElementPtr* pElem = p->pData + nElem;
+ nElem = p->nElem - nElem;
+ for(;;)
+ {
+ if( !(*fn)( *pElem++, pArgs ) || ++nStart >= nEnd )
+ break;
+
+ // naechstes Element
+ if( !--nElem )
+ {
+ // neuer Block
+ p = *++pp;
+ pElem = p->pData;
+ nElem = p->nElem;
+ }
+ }
+ }
+}
+
+
+ElementPtr BigPtrArray::operator[]( sal_uLong idx ) const
+{
+ // weil die Funktion eben doch nicht const ist:
+ DBG_ASSERT( idx < nSize, "operator[]: Index aussserhalb" );
+ BigPtrArray* pThis = (BigPtrArray*) this;
+ sal_uInt16 cur = Index2Block( idx );
+ BlockInfo* p = ppInf[ cur ];
+ pThis->nCur = cur;
+ return p->pData[ idx - p->nStart ];
+}
+
+///////////////////////////////////////////////////////////////////////////
+
+// private Methoden
+
+// Suchen des Blocks einer bestimmten Position
+// Algorithmus:
+// 1. Test, ob der letzte Block der gesuchte Block ist
+// 2. Sonderfall: Index = 0?
+// 3. Test der Nachbarbloecke
+
+// 4. Binaere Suche
+
+
+
+sal_uInt16 BigPtrArray::Index2Block( sal_uLong pos ) const
+{
+ // zuletzt verwendeter Block?
+ BlockInfo* p = ppInf[ nCur ];
+ if( p->nStart <= pos && p->nEnd >= pos )
+ return nCur;
+ // Index = 0?
+ if( !pos )
+ return 0;
+ // Folgeblock?
+ if( nCur < ( nBlock - 1 ) )
+ {
+ p = ppInf[ nCur+1 ];
+ if( p->nStart <= pos && p->nEnd >= pos )
+ return nCur+1;
+ }
+ // vorangehender Block?
+ else if( pos < p->nStart && nCur > 0 )
+ {
+ p = ppInf[ nCur-1 ];
+ if( p->nStart <= pos && p->nEnd >= pos )
+ return nCur-1;
+ }
+ // Binaere Suche:
+ // Diese fuehrt immer zum Erfolg
+ sal_uInt16 lower = 0, upper = nBlock - 1;
+ sal_uInt16 cur = 0;
+ for(;;)
+ {
+ sal_uInt16 n = lower + ( upper - lower ) / 2;
+ cur = ( n == cur ) ? n+1 : n;
+ p = ppInf[ cur ];
+ if( p->nStart <= pos && p->nEnd >= pos )
+ return cur;
+ if( p->nStart > pos )
+ upper = cur;
+ else
+ lower = cur;
+ }
+}
+
+
+// Update aller Indexbereiche ab einer bestimmten Position
+
+// pos bezeichnet den letzten korrekten Block
+
+void BigPtrArray::UpdIndex( sal_uInt16 pos )
+{
+ BlockInfo** pp = ppInf + pos;
+ sal_uLong idx = (*pp)->nEnd + 1;
+ BlockInfo* p;
+ while( ++pos < nBlock )
+ {
+ p = *++pp;
+ p->nStart = idx;
+ idx += p->nElem;
+ p->nEnd = idx - 1;
+ }
+}
+
+// Einrichten eines neuen Blocks an einer bestimmten Position
+
+// Vorhandene Blocks werden nach hinten verschoben
+
+
+
+BlockInfo* BigPtrArray::InsBlock( sal_uInt16 pos )
+{
+ if( nBlock == nMaxBlock )
+ {
+ // dann sollte wir mal das Array erweitern
+ BlockInfo** ppNew = new BlockInfo* [ nMaxBlock + nBlockGrowSize ];
+ memcpy( ppNew, ppInf, nMaxBlock * sizeof( BlockInfo* ));
+ delete[] ppInf;
+ nMaxBlock += nBlockGrowSize;
+ ppInf = ppNew;
+ }
+ if( pos != nBlock )
+ memmove( ppInf + pos+1, ppInf + pos ,
+ ( nBlock - pos ) * sizeof (BlockInfo*) );
+ ++nBlock;
+ BlockInfo* p = new BlockInfo;
+ ppInf[ pos ] = p;
+
+ if( pos )
+ p->nStart = p->nEnd = ppInf[ pos-1 ]->nEnd + 1;
+ else
+ p->nStart = p->nEnd = 0;
+ p->nEnd--; // keine Elemente
+ p->nElem = 0;
+ p->pData = new ElementPtr [ MAXENTRY ];
+ p->pBigArr = this;
+ return p;
+}
+
+void BigPtrArray::BlockDel( sal_uInt16 nDel )
+{
+ nBlock = nBlock - nDel;
+ if( nMaxBlock - nBlock > nBlockGrowSize )
+ {
+ // dann koennen wir wieder schrumpfen
+ nDel = (( nBlock / nBlockGrowSize ) + 1 ) * nBlockGrowSize;
+ BlockInfo** ppNew = new BlockInfo* [ nDel ];
+ memcpy( ppNew, ppInf, nBlock * sizeof( BlockInfo* ));
+ delete[] ppInf;
+ ppInf = ppNew;
+ nMaxBlock = nDel;
+ }
+}
+
+
+void BigPtrArray::Insert( const ElementPtr& rElem, sal_uLong pos )
+{
+ CHECKIDX( ppInf, nBlock, nSize, nCur );
+
+ BlockInfo* p;
+ sal_uInt16 cur;
+ if( !nSize )
+ // Sonderfall: erstes Element einfuegen
+ p = InsBlock( cur = 0 );
+ else if( pos == nSize )
+ {
+ // Sonderfall: Einfuegen am Ende
+ cur = nBlock - 1;
+ p = ppInf[ cur ];
+ if( p->nElem == MAXENTRY )
+ // Der letzte Block ist voll, neuen anlegen
+ p = InsBlock( ++cur );
+ }
+ else
+ {
+ // Standardfall:
+ cur = Index2Block( pos );
+ p = ppInf[ cur ];
+ }
+ if( p->nElem == MAXENTRY )
+ {
+ // passt der letzte Eintrag in den naechsten Block?
+ BlockInfo* q;
+ if( cur < ( nBlock - 1 ) && ppInf[ cur+1 ]->nElem < MAXENTRY )
+ {
+ q = ppInf[ cur+1 ];
+ if( q->nElem )
+ {
+ int nCount = q->nElem;
+ ElementPtr *pFrom = q->pData + nCount,
+ *pTo = pFrom+1;
+ while( nCount-- )
+ ++( *--pTo = *--pFrom )->nOffset;
+ }
+ q->nStart--;
+ q->nEnd--;
+ }
+ else
+ {
+ // Wenn er auch nicht in den Folgeblock passt, muss ein
+ // neuer Block eingefuegt werden
+ // erst mal bei Bedarf komprimieren
+
+ // wenn mehr als 50% "Luft" im Array ist, dann sollte man mal das
+ // Compress aufrufen
+ if( /*nBlock == nMaxBlock &&*/
+ nBlock > ( nSize / ( MAXENTRY / 2 ) ) &&
+ cur >= Compress() )
+ {
+ // es wurde vor der akt. Pos etwas verschoben und alle
+ // Pointer koennen ungueltig sein. Also das Insert
+ // nochmals aufsetzen
+ Insert( rElem, pos );
+ return ;
+ }
+
+ q = InsBlock( cur+1 );
+ }
+
+ // Eintrag passt nicht mehr. Dann muss Platz gemacht werden
+ ElementPtr pLast = p->pData[ MAXENTRY-1 ];
+ pLast->nOffset = 0;
+ pLast->pBlock = q;
+
+ q->pData[ 0 ] = pLast;
+ q->nElem++;
+ q->nEnd++;
+
+ p->nEnd--;
+ p->nElem--;
+ }
+ // Nun haben wir einen freien Block am Wickel: eintragen
+ pos -= p->nStart;
+ DBG_ASSERT( pos < MAXENTRY, "falsche Pos" );
+ if( pos != p->nElem )
+ {
+ int nCount = p->nElem - sal_uInt16(pos);
+ ElementPtr *pFrom = p->pData + p->nElem,
+ *pTo = pFrom + 1;
+ while( nCount-- )
+ ++( *--pTo = *--pFrom )->nOffset;
+ }
+ // Element eintragen und Indexe updaten
+ ((ElementPtr&)rElem)->nOffset = sal_uInt16(pos);
+ ((ElementPtr&)rElem)->pBlock = p;
+ p->pData[ pos ] = rElem;
+ p->nEnd++;
+ p->nElem++;
+ nSize++;
+ if( cur != ( nBlock - 1 ) ) UpdIndex( cur );
+ nCur = cur;
+
+ CHECKIDX( ppInf, nBlock, nSize, nCur );
+}
+
+void BigPtrArray::Remove( sal_uLong pos, sal_uLong n )
+{
+ CHECKIDX( ppInf, nBlock, nSize, nCur );
+
+ sal_uInt16 nBlkdel = 0; // entfernte Bloecke
+ sal_uInt16 cur = Index2Block( pos ); // aktuelle Blocknr
+ sal_uInt16 nBlk1 = cur; // 1. behandelter Block
+ sal_uInt16 nBlk1del = USHRT_MAX; // 1. entfernter Block
+ BlockInfo* p = ppInf[ cur ];
+ pos -= p->nStart;
+ sal_uLong nElem = n;
+ while( nElem )
+ {
+ sal_uInt16 nel = p->nElem - sal_uInt16(pos);
+ if( sal_uLong(nel) > nElem )
+ nel = sal_uInt16(nElem);
+ // Eventuell Elemente verschieben
+ if( ( pos + nel ) < sal_uLong(p->nElem) )
+ {
+ ElementPtr *pTo = p->pData + pos,
+ *pFrom = pTo + nel;
+ int nCount = p->nElem - nel - sal_uInt16(pos);
+ while( nCount-- )
+ {
+ *pTo = *pFrom++;
+ (*pTo)->nOffset = (*pTo)->nOffset - nel;
+ ++pTo;
+ }
+ }
+ p->nEnd -= nel;
+ p->nElem = p->nElem - nel;
+ if( !p->nElem )
+ {
+ // eventuell Block ganz entfernen
+ delete[] p->pData;
+ nBlkdel++;
+ if( USHRT_MAX == nBlk1del )
+ nBlk1del = cur;
+ }
+ nElem -= nel;
+ if( !nElem )
+ break;
+ p = ppInf[ ++cur ];
+ pos = 0;
+ }
+ // Am Ende die Tabelle updaten, falls Bloecke geloescht waren
+ if( nBlkdel )
+ {
+ // loeschen sollte man immer !!
+ for( sal_uInt16 i = nBlk1del; i < ( nBlk1del + nBlkdel ); i++ )
+ delete ppInf[ i ];
+
+ if( ( nBlk1del + nBlkdel ) < nBlock )
+ {
+ memmove( ppInf + nBlk1del, ppInf + nBlk1del + nBlkdel,
+ ( nBlock - nBlkdel - nBlk1del ) * sizeof( BlockInfo* ) );
+
+ // JP 19.07.95: nicht den ersten behandelten, sondern den davor!!
+ // UpdateIdx updatet nur alle Nachfolgende!!
+ if( !nBlk1 )
+ {
+ p = ppInf[ 0 ];
+ p->nStart = 0;
+ p->nEnd = p->nElem-1;
+ }
+ else
+ --nBlk1;
+ }
+ BlockDel( nBlkdel ); // es wurden Bloecke geloescht
+ }
+
+ nSize -= n;
+ if( nBlk1 != ( nBlock - 1 ) && nSize )
+ UpdIndex( nBlk1 );
+ nCur = nBlk1;
+
+ // wenn mehr als 50% "Luft" im Array ist, dann sollte man mal das
+ // Compress aufrufen
+ if( nBlock > ( nSize / ( MAXENTRY / 2 ) ) )
+ Compress();
+
+ CHECKIDX( ppInf, nBlock, nSize, nCur );
+}
+
+
+void BigPtrArray::Replace( sal_uLong idx, const ElementPtr& rElem)
+{
+ // weil die Funktion eben doch nicht const ist:
+ DBG_ASSERT( idx < nSize, "Set: Index aussserhalb" );
+ BigPtrArray* pThis = (BigPtrArray*) this;
+ sal_uInt16 cur = Index2Block( idx );
+ BlockInfo* p = ppInf[ cur ];
+ pThis->nCur = cur;
+ ((ElementPtr&)rElem)->nOffset = sal_uInt16(idx - p->nStart);
+ ((ElementPtr&)rElem)->pBlock = p;
+ p->pData[ idx - p->nStart ] = rElem;
+}
+
+
+// Array komprimieren
+
+sal_uInt16 BigPtrArray::Compress( short nMax )
+{
+ CHECKIDX( ppInf, nBlock, nSize, nCur );
+
+ // Es wird von vorne nach hinten ueber das InfoBlock Array iteriert.
+ // Wenn zwischen durch Block gel�scht werden, dann mussen alle
+ // nachfolgenden verschoben werden. Dazu werden die Pointer pp und qq
+ // benutzt; wobei pp das "alte" Array, qq das "neue" Array ist.
+ BlockInfo** pp = ppInf, **qq = pp;
+ BlockInfo* p;
+ BlockInfo* pLast(0); // letzter nicht voller Block
+ sal_uInt16 nLast = 0; // fehlende Elemente
+ sal_uInt16 nBlkdel = 0; // Anzahl der geloeschte Bloecke
+ sal_uInt16 nFirstChgPos = USHRT_MAX; // ab welcher Pos gab es die 1. Aenderung?
+
+ // von Fuell-Prozenten auf uebrige Eintrage umrechnen
+ nMax = MAXENTRY - (long) MAXENTRY * nMax / 100;
+
+ for( sal_uInt16 cur = 0; cur < nBlock; ++cur )
+ {
+ p = *pp++;
+ sal_uInt16 n = p->nElem;
+ // Testen, ob der noch nicht volle Block so gelassen wird
+ // dies ist der Fall, wenn der aktuelle Block gesplittet
+ // werden muesste, der noch nicht volle Block aber bereits
+ // ueber dem uebergebenen Break-Wert voll ist. In diesem
+ // Fall wird von einer weiteren Fuellung (die ja wegen dem
+ // zweifachen memmove() zeitaufwendig ist) abgesehen.
+ if( nLast && ( n > nLast ) && ( nLast < nMax ) )
+ nLast = 0;
+ if( nLast )
+ {
+ if( USHRT_MAX == nFirstChgPos )
+ nFirstChgPos = cur;
+
+ // ein nicht voller Block vorhanden: auffuellen
+ if( n > nLast )
+ n = nLast;
+
+ // Elemente uebertragen, vom akt. in den letzten
+ ElementPtr* pElem = pLast->pData + pLast->nElem;
+ ElementPtr* pFrom = p->pData;
+ for( sal_uInt16 nCount = n, nOff = pLast->nElem;
+ nCount; --nCount, ++pElem )
+ *pElem = *pFrom++,
+ (*pElem)->pBlock = pLast,
+ (*pElem)->nOffset = nOff++;
+
+ // korrigieren
+ pLast->nElem = pLast->nElem + n;
+ nLast = nLast - n;
+ p->nElem = p->nElem - n;
+
+ // Ist der aktuelle Block dadurch leer geworden?
+ if( !p->nElem )
+ {
+ // dann kann der entfernt werden
+ delete[] p->pData;
+ delete p, p = 0;
+ ++nBlkdel;
+ }
+ else
+ {
+ pElem = p->pData, pFrom = pElem + n;
+ int nCount = p->nElem;
+ while( nCount-- )
+ {
+ *pElem = *pFrom++;
+ (*pElem)->nOffset = (*pElem)->nOffset - n;
+ ++pElem;
+ }
+ }
+ }
+
+ if( p ) // die Blockinfo wurde nicht geloescht
+ {
+ *qq++ = p; // dann setze sie an die richtige neue Position
+
+ // eventuell den letzten halbvollen Block festhalten
+ if( !nLast && p->nElem < MAXENTRY )
+ {
+ pLast = p;
+ nLast = MAXENTRY - p->nElem;
+ }
+ }
+ }
+
+ // Bloecke geloescht wurden, ggfs. das BlockInfo Array verkuerzen
+ if( nBlkdel )
+ BlockDel( nBlkdel );
+
+ // Und neu durchindizieren
+ p = ppInf[ 0 ];
+ p->nEnd = p->nElem - 1;
+ UpdIndex( 0 );
+
+ if( nCur >= nFirstChgPos )
+ nCur = 0;
+
+ CHECKIDX( ppInf, nBlock, nSize, nCur );
+
+ return nFirstChgPos;
+}
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/bastyp/breakit.cxx b/sw/source/core/bastyp/breakit.cxx
new file mode 100644
index 000000000000..c571e389acf8
--- /dev/null
+++ b/sw/source/core/bastyp/breakit.cxx
@@ -0,0 +1,172 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+#include "breakit.hxx"
+#include <unicode/uchar.h>
+#include <com/sun/star/lang/XMultiServiceFactory.hpp>
+#include <com/sun/star/i18n/ScriptType.hdl>
+#include <unotools/localedatawrapper.hxx>
+
+#include <editeng/unolingu.hxx>
+#include <editeng/scripttypeitem.hxx>
+#include "swtypes.hxx"
+
+using namespace com::sun::star;
+
+SwBreakIt * pBreakIt = 0;
+
+void SwBreakIt::_Create(
+ const uno::Reference< lang::XMultiServiceFactory > & rxMSF)
+{
+ delete pBreakIt, pBreakIt = new SwBreakIt( rxMSF );
+}
+
+void SwBreakIt::_Delete()
+{
+ delete pBreakIt, pBreakIt = 0;
+}
+
+SwBreakIt * SwBreakIt::Get()
+{
+ return pBreakIt;
+}
+
+SwBreakIt::SwBreakIt(
+ const uno::Reference< lang::XMultiServiceFactory > & rxMSF)
+ : m_xMSF( rxMSF ),
+ m_pLocale( NULL ),
+ m_pForbidden( NULL ),
+ aLast( LANGUAGE_DONTKNOW ),
+ aForbiddenLang( LANGUAGE_DONTKNOW)
+{
+ DBG_ASSERT( m_xMSF.is(), "SwBreakIt: no MultiServiceFactory" );
+}
+
+SwBreakIt::~SwBreakIt()
+{
+ delete m_pLocale;
+ delete m_pForbidden;
+}
+void SwBreakIt::createBreakIterator() const
+{
+ if ( m_xMSF.is() && !xBreak.is() )
+ xBreak.set(m_xMSF->createInstance(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.i18n.BreakIterator"))),uno::UNO_QUERY);
+}
+void SwBreakIt::createScriptTypeDetector()
+{
+ if ( m_xMSF.is() && !xCTLDetect.is() )
+ xCTLDetect.set(m_xMSF->createInstance(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.i18n.ScriptTypeDetector" ))),uno::UNO_QUERY);
+}
+void SwBreakIt::_GetLocale( const LanguageType aLang )
+{
+ aLast = aLang;
+ delete m_pLocale;
+ m_pLocale = new lang::Locale( SvxCreateLocale( aLast ) );
+}
+
+void SwBreakIt::_GetForbidden( const LanguageType aLang )
+{
+ LocaleDataWrapper aWrap( m_xMSF, GetLocale( aLang ) );
+
+ aForbiddenLang = aLang;
+ delete m_pForbidden;
+ m_pForbidden = new i18n::ForbiddenCharacters( aWrap.getForbiddenCharacters() );
+}
+
+sal_uInt16 SwBreakIt::GetRealScriptOfText( const String& rTxt,
+ xub_StrLen nPos ) const
+{
+ createBreakIterator();
+ sal_uInt16 nScript = i18n::ScriptType::WEAK;
+ if( xBreak.is() && rTxt.Len() )
+ {
+ if( nPos && nPos == rTxt.Len() )
+ --nPos;
+ nScript = xBreak->getScriptType( rTxt, nPos );
+ sal_Int32 nChgPos = 0;
+ if ( i18n::ScriptType::WEAK == nScript && nPos + 1 < rTxt.Len() )
+ {
+ // A weak character followed by a mark may be meant to combine with
+ // the mark, so prefer the following character's script
+ switch ( u_charType(rTxt.GetChar(nPos + 1) ) ) {
+ case U_NON_SPACING_MARK:
+ case U_ENCLOSING_MARK:
+ case U_COMBINING_SPACING_MARK:
+ nScript = xBreak->getScriptType( rTxt, nPos+1 );
+ break;
+ }
+ }
+ if( i18n::ScriptType::WEAK == nScript && nPos &&
+ 0 < (nChgPos = xBreak->beginOfScript( rTxt, nPos, nScript )) )
+ nScript = xBreak->getScriptType( rTxt, nChgPos-1 );
+
+ if( i18n::ScriptType::WEAK == nScript && rTxt.Len() >
+ ( nChgPos = xBreak->endOfScript( rTxt, nPos, nScript ) ) &&
+ 0 <= nChgPos )
+ nScript = xBreak->getScriptType( rTxt, nChgPos );
+ }
+ if( i18n::ScriptType::WEAK == nScript )
+ nScript = GetI18NScriptTypeOfLanguage( (sal_uInt16)GetAppLanguage() );
+ return nScript;
+}
+
+sal_uInt16 SwBreakIt::GetAllScriptsOfText( const String& rTxt ) const
+{
+ const sal_uInt16 coAllScripts = ( SCRIPTTYPE_LATIN |
+ SCRIPTTYPE_ASIAN |
+ SCRIPTTYPE_COMPLEX );
+ createBreakIterator();
+ sal_uInt16 nRet = 0, nScript;
+ if( !xBreak.is() )
+ nRet = coAllScripts;
+ else if( rTxt.Len() )
+ {
+ for( xub_StrLen n = 0, nEnd = rTxt.Len(); n < nEnd;
+ n = static_cast<xub_StrLen>(xBreak->endOfScript( rTxt, n, nScript )) )
+ {
+ switch( nScript = xBreak->getScriptType( rTxt, n ) )
+ {
+ case i18n::ScriptType::LATIN: nRet |= SCRIPTTYPE_LATIN; break;
+ case i18n::ScriptType::ASIAN: nRet |= SCRIPTTYPE_ASIAN; break;
+ case i18n::ScriptType::COMPLEX: nRet |= SCRIPTTYPE_COMPLEX; break;
+ case i18n::ScriptType::WEAK:
+ if( !nRet )
+ nRet |= coAllScripts;
+ break;
+ }
+ if( coAllScripts == nRet )
+ break;
+ }
+ }
+ return nRet;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/bastyp/calc.cxx b/sw/source/core/bastyp/calc.cxx
new file mode 100644
index 000000000000..ba6aa92fadb6
--- /dev/null
+++ b/sw/source/core/bastyp/calc.cxx
@@ -0,0 +1,1745 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+
+#include <cctype>
+#if defined(MACOSX)
+#include <stdlib.h>
+#endif
+#include <cstdlib>
+#include <climits>
+#include <cfloat>
+#include <hintids.hxx>
+#include <osl/diagnose.hxx>
+#include <rtl/math.hxx>
+#include <editeng/langitem.hxx>
+#include <com/sun/star/lang/XMultiServiceFactory.hpp>
+#include <comphelper/processfactory.hxx>
+#include <unotools/localedatawrapper.hxx>
+#include <unotools/charclass.hxx>
+#include <editeng/unolingu.hxx>
+#include <editeng/scripttypeitem.hxx>
+#include <unotools/useroptions.hxx>
+#include <tools/datetime.hxx>
+#include <svl/zforlist.hxx>
+#include <swmodule.hxx>
+#include <doc.hxx>
+#include <viewsh.hxx>
+#include <docstat.hxx>
+#include <calc.hxx>
+#include <shellres.hxx>
+#include <dbfld.hxx>
+#include <expfld.hxx>
+#include <usrfld.hxx>
+#include <dbmgr.hxx>
+#include <docfld.hxx>
+#include <swunodef.hxx>
+#include <swtypes.hxx>
+
+using namespace ::com::sun::star;
+
+// tippt sich schneller
+#define RESOURCE ViewShell::GetShellRes()
+
+const sal_Char sCalc_Add[] = "add";
+const sal_Char sCalc_Sub[] = "sub";
+const sal_Char sCalc_Mul[] = "mul";
+const sal_Char sCalc_Div[] = "div";
+const sal_Char sCalc_Phd[] = "phd";
+const sal_Char sCalc_Sqrt[] = "sqrt";
+const sal_Char sCalc_Pow[] = "pow";
+const sal_Char sCalc_Or[] = "or";
+const sal_Char sCalc_Xor[] = "xor";
+const sal_Char sCalc_And[] = "and";
+const sal_Char sCalc_Not[] = "not";
+const sal_Char sCalc_Eq[] = "eq";
+const sal_Char sCalc_Neq[] = "neq";
+const sal_Char sCalc_Leq[] = "leq";
+const sal_Char sCalc_Geq[] = "geq";
+const sal_Char sCalc_L[] = "l";
+const sal_Char sCalc_G[] = "g";
+const sal_Char sCalc_Sum[] = "sum";
+const sal_Char sCalc_Mean[] = "mean";
+const sal_Char sCalc_Min[] = "min";
+const sal_Char sCalc_Max[] = "max";
+const sal_Char sCalc_Sin[] = "sin";
+const sal_Char sCalc_Cos[] = "cos";
+const sal_Char sCalc_Tan[] = "tan";
+const sal_Char sCalc_Asin[] = "asin";
+const sal_Char sCalc_Acos[] = "acos";
+const sal_Char sCalc_Atan[] = "atan";
+const sal_Char sCalc_Round[] = "round";
+const sal_Char sCalc_Date[] = "date";
+
+
+
+//!!!!! ACHTUNG - Sortierte Liste aller Operatoren !!!!!
+struct _CalcOp
+{
+ union{
+ const sal_Char* pName;
+ const String* pUName;
+ };
+ SwCalcOper eOp;
+};
+
+_CalcOp const aOpTable[] = {
+/* ACOS */ {{sCalc_Acos}, CALC_ACOS}, // Arcuscosinus
+/* ADD */ {{sCalc_Add}, CALC_PLUS}, // Addition
+/* AND */ {{sCalc_And}, CALC_AND}, // log. und
+/* ASIN */ {{sCalc_Asin}, CALC_ASIN}, // Arcussinus
+/* ATAN */ {{sCalc_Atan}, CALC_ATAN}, // Arcustangens
+/* COS */ {{sCalc_Cos}, CALC_COS}, // Cosinus
+/* DATE */ {{sCalc_Date}, CALC_DATE}, // Date
+/* DIV */ {{sCalc_Div}, CALC_DIV}, // Dividieren
+/* EQ */ {{sCalc_Eq}, CALC_EQ}, // gleich
+/* G */ {{sCalc_G}, CALC_GRE}, // groesser
+/* GEQ */ {{sCalc_Geq}, CALC_GEQ}, // groesser gleich
+/* L */ {{sCalc_L}, CALC_LES}, // kleiner
+/* LEQ */ {{sCalc_Leq}, CALC_LEQ}, // kleiner gleich
+/* MAX */ {{sCalc_Max}, CALC_MAX}, // Maximalwert
+/* MEAN */ {{sCalc_Mean}, CALC_MEAN}, // Mittelwert
+/* MIN */ {{sCalc_Min}, CALC_MIN}, // Minimalwert
+/* MUL */ {{sCalc_Mul}, CALC_MUL}, // Multiplizieren
+/* NEQ */ {{sCalc_Neq}, CALC_NEQ}, // nicht gleich
+/* NOT */ {{sCalc_Not}, CALC_NOT}, // log. nicht
+/* OR */ {{sCalc_Or}, CALC_OR}, // log. oder
+/* PHD */ {{sCalc_Phd}, CALC_PHD}, // Prozent
+/* POW */ {{sCalc_Pow}, CALC_POW}, // Potenzieren
+/* ROUND */ {{sCalc_Round}, CALC_ROUND}, // Runden
+/* SIN */ {{sCalc_Sin}, CALC_SIN}, // Sinus
+/* SQRT */ {{sCalc_Sqrt}, CALC_SQRT}, // Wurzel
+/* SUB */ {{sCalc_Sub}, CALC_MINUS}, // Subtraktion
+/* SUM */ {{sCalc_Sum}, CALC_SUM}, // Summe
+/* TAN */ {{sCalc_Tan}, CALC_TAN}, // Tangens
+/* XOR */ {{sCalc_Xor}, CALC_XOR} // log. xoder
+};
+
+double const nRoundVal[] = {
+ 5.0e+0, 0.5e+0, 0.5e-1, 0.5e-2, 0.5e-3, 0.5e-4, 0.5e-5, 0.5e-6,
+ 0.5e-7, 0.5e-8, 0.5e-9, 0.5e-10,0.5e-11,0.5e-12,0.5e-13,0.5e-14,
+ 0.5e-15,0.5e-16
+};
+
+double const nKorrVal[] = {
+ 9, 9e-1, 9e-2, 9e-3, 9e-4, 9e-5, 9e-6, 9e-7, 9e-8,
+ 9e-9, 9e-10, 9e-11, 9e-12, 9e-13, 9e-14
+};
+
+ // First character may be any alphabetic or underscore.
+const sal_Int32 coStartFlags =
+ i18n::KParseTokens::ANY_LETTER_OR_NUMBER |
+ i18n::KParseTokens::ASC_UNDERSCORE |
+ i18n::KParseTokens::IGNORE_LEADING_WS;
+
+ // Continuing characters may be any alphanumeric or underscore or dot.
+const sal_Int32 coContFlags =
+ ( coStartFlags | i18n::KParseTokens::ASC_DOT )
+ & ~i18n::KParseTokens::IGNORE_LEADING_WS;
+
+
+extern "C" {
+static int
+#if defined( WNT )
+ __cdecl
+#endif
+#if defined( ICC )
+ _Optlink
+#endif
+ OperatorCompare( const void *pFirst, const void *pSecond)
+{
+ int nRet = 0;
+ if( CALC_NAME == ((_CalcOp*)pFirst)->eOp )
+ {
+ if( CALC_NAME == ((_CalcOp*)pSecond)->eOp )
+ nRet = ((_CalcOp*)pFirst)->pUName->CompareTo(
+ *((_CalcOp*)pSecond)->pUName );
+ else
+ nRet = ((_CalcOp*)pFirst)->pUName->CompareToAscii(
+ ((_CalcOp*)pSecond)->pName );
+ }
+ else
+ {
+ if( CALC_NAME == ((_CalcOp*)pSecond)->eOp )
+ nRet = -1 * ((_CalcOp*)pSecond)->pUName->CompareToAscii(
+ ((_CalcOp*)pFirst)->pName );
+ else
+ nRet = strcmp( ((_CalcOp*)pFirst)->pName,
+ ((_CalcOp*)pSecond)->pName );
+ }
+ return nRet;
+}
+
+}// extern "C"
+
+_CalcOp* FindOperator( const String& rSrch )
+{
+ _CalcOp aSrch;
+ aSrch.pUName = &rSrch;
+ aSrch.eOp = CALC_NAME;
+
+ return (_CalcOp*)bsearch( (void*) &aSrch,
+ (void*) aOpTable,
+ sizeof( aOpTable ) / sizeof( _CalcOp ),
+ sizeof( _CalcOp ),
+ OperatorCompare );
+}
+
+
+//-----------------------------------------------------------------------------
+
+SwHash* Find( const String& rStr, SwHash** ppTable, sal_uInt16 nTblSize,
+ sal_uInt16* pPos )
+{
+ sal_uLong ii = 0;
+ for( xub_StrLen n = 0; n < rStr.Len(); ++n )
+ ii = ii << 1 ^ rStr.GetChar( n );
+ ii %= nTblSize;
+
+ if( pPos )
+ *pPos = (sal_uInt16)ii;
+
+ for( SwHash* pEntry = *(ppTable+ii); pEntry; pEntry = pEntry->pNext )
+ if( rStr == pEntry->aStr )
+ return pEntry;
+ return 0;
+}
+
+inline LanguageType GetDocAppScriptLang( SwDoc& rDoc )
+{
+ return ((SvxLanguageItem&)rDoc.GetDefault(
+ GetWhichOfScript( RES_CHRATR_LANGUAGE,
+ GetI18NScriptTypeOfLanguage( (sal_uInt16)GetAppLanguage() ))
+ )).GetLanguage();
+}
+
+double lcl_ConvertToDateValue( SwDoc& rDoc, sal_Int32 nDate )
+{
+ double nRet = 0;
+ SvNumberFormatter* pFormatter = rDoc.GetNumberFormatter();
+ if( pFormatter )
+ {
+ Date* pNull = pFormatter->GetNullDate();
+ Date aDate( nDate >> 24, (nDate & 0x00FF0000) >> 16, nDate & 0x0000FFFF );
+ nRet = aDate - *pNull;
+ }
+ return nRet;
+}
+
+//-----------------------------------------------------------------------------
+
+/******************************************************************************
+|*
+|* SwCalc::SwCalc( SwDoc* pD ) :
+|*
+|******************************************************************************/
+
+SwCalc::SwCalc( SwDoc& rD )
+ :
+ aErrExpr( aEmptyStr, SwSbxValue(), 0 ),
+ rDoc( rD ),
+ pLclData( m_aSysLocale.GetLocaleDataPtr() ),
+ pCharClass( &GetAppCharClass() ),
+ nListPor( 0 ),
+ eError( CALC_NOERR )
+{
+ aErrExpr.aStr.AssignAscii( "~C_ERR~" );
+ memset( VarTable, 0, sizeof(VarTable) );
+ LanguageType eLang = GetDocAppScriptLang( rDoc );
+
+ if( eLang != SvxLocaleToLanguage( pLclData->getLocale() ) ||
+ eLang != SvxLocaleToLanguage( pCharClass->getLocale() ) )
+ {
+ STAR_NMSPC::lang::Locale aLocale( SvxCreateLocale( eLang ));
+ STAR_REFERENCE( lang::XMultiServiceFactory ) xMSF(
+ ::comphelper::getProcessServiceFactory() );
+ pCharClass = new CharClass( xMSF, aLocale );
+ pLclData = new LocaleDataWrapper( xMSF, aLocale );
+ }
+
+ sCurrSym = pLclData->getCurrSymbol();
+ sCurrSym.EraseLeadingChars().EraseTrailingChars();
+ pCharClass->toLower( sCurrSym );
+
+static sal_Char const
+ sNType0[] = "false",
+ sNType1[] = "true",
+ sNType2[] = "pi",
+ sNType3[] = "e",
+ sNType4[] = "tables",
+ sNType5[] = "graf",
+ sNType6[] = "ole",
+ sNType7[] = "page",
+ sNType8[] = "para",
+ sNType9[] = "word",
+ sNType10[]= "char",
+
+ sNType11[] = "user_firstname" ,
+ sNType12[] = "user_lastname" ,
+ sNType13[] = "user_initials" ,
+ sNType14[] = "user_company" ,
+ sNType15[] = "user_street" ,
+ sNType16[] = "user_country" ,
+ sNType17[] = "user_zipcode" ,
+ sNType18[] = "user_city" ,
+ sNType19[] = "user_title" ,
+ sNType20[] = "user_position" ,
+ sNType21[] = "user_tel_work" ,
+ sNType22[] = "user_tel_home" ,
+ sNType23[] = "user_fax" ,
+ sNType24[] = "user_email" ,
+ sNType25[] = "user_state" ,
+ sNType26[] = "graph"
+ ;
+
+static const sal_Char* const sNTypeTab[ 27 ] =
+{
+ sNType0, sNType1, sNType2, sNType3, sNType4, sNType5,
+ sNType6, sNType7, sNType8, sNType9, sNType10, sNType11,
+ sNType12, sNType13, sNType14, sNType15, sNType16, sNType17,
+ sNType18, sNType19, sNType20, sNType21, sNType22, sNType23,
+ sNType24,
+
+ // diese sind mit doppelten HashIds
+ sNType25, sNType26
+};
+static sal_uInt16 const aHashValue[ 27 ] =
+{
+ 34, 38, 43, 7, 18, 32, 22, 29, 30, 33, 3,
+ 28, 24, 40, 9, 11, 26, 45, 4, 23, 36, 44, 19, 5, 1,
+ // diese sind mit doppelten HashIds
+ 11, 38
+};
+static sal_uInt16 const aAdrToken[ 12 ] =
+{
+ USER_OPT_COMPANY, USER_OPT_STREET, USER_OPT_COUNTRY, USER_OPT_ZIP,
+ USER_OPT_CITY, USER_OPT_TITLE, USER_OPT_POSITION, USER_OPT_TELEPHONEWORK,
+ USER_OPT_TELEPHONEHOME, USER_OPT_FAX, USER_OPT_EMAIL, USER_OPT_STATE
+};
+
+static sal_uInt16 SwDocStat::* const aDocStat1[ 3 ] =
+{
+ &SwDocStat::nTbl, &SwDocStat::nGrf, &SwDocStat::nOLE
+};
+static sal_uLong SwDocStat::* const aDocStat2[ 4 ] =
+{
+ &SwDocStat::nPage, &SwDocStat::nPara,
+ &SwDocStat::nWord, &SwDocStat::nChar
+};
+
+#if TBLSZ != 47
+#error Alle Hashwerte angepasst?
+#endif
+
+ const SwDocStat& rDocStat = rDoc.GetDocStat();
+
+ SwSbxValue nVal;
+ String sTmpStr;
+ sal_uInt16 n;
+
+ for( n = 0; n < 25; ++n )
+ {
+ sTmpStr.AssignAscii( sNTypeTab[ n ] );
+ VarTable[ aHashValue[ n ] ] = new SwCalcExp( sTmpStr, nVal, 0 );
+ }
+
+ ((SwCalcExp*)VarTable[ aHashValue[ 0 ] ])->nValue.PutBool( sal_False );
+ ((SwCalcExp*)VarTable[ aHashValue[ 1 ] ])->nValue.PutBool( sal_True );
+ ((SwCalcExp*)VarTable[ aHashValue[ 2 ] ])->nValue.PutDouble( F_PI );
+ ((SwCalcExp*)VarTable[ aHashValue[ 3 ] ])->nValue.PutDouble( 2.7182818284590452354 );
+
+ for( n = 0; n < 3; ++n )
+ ((SwCalcExp*)VarTable[ aHashValue[ n + 4 ] ])->nValue.PutLong( rDocStat.*aDocStat1[ n ] );
+ for( n = 0; n < 4; ++n )
+ ((SwCalcExp*)VarTable[ aHashValue[ n + 7 ] ])->nValue.PutLong( rDocStat.*aDocStat2[ n ] );
+
+ SvtUserOptions& rUserOptions = SW_MOD()->GetUserOptions();
+
+ ((SwCalcExp*)VarTable[ aHashValue[ 11 ] ])->nValue.PutString( (String)rUserOptions.GetFirstName() );
+ ((SwCalcExp*)VarTable[ aHashValue[ 12 ] ])->nValue.PutString( (String)rUserOptions.GetLastName() );
+ ((SwCalcExp*)VarTable[ aHashValue[ 13 ] ])->nValue.PutString( (String)rUserOptions.GetID() );
+
+ for( n = 0; n < 11; ++n )
+ ((SwCalcExp*)VarTable[ aHashValue[ n + 14 ] ])->nValue.PutString(
+ (String)rUserOptions.GetToken( aAdrToken[ n ] ));
+
+ nVal.PutString( (String)rUserOptions.GetToken( aAdrToken[ 11 ] ));
+ sTmpStr.AssignAscii( sNTypeTab[ 25 ] );
+ VarTable[ aHashValue[ 25 ] ]->pNext = new SwCalcExp( sTmpStr, nVal, 0 );
+
+}
+
+/******************************************************************************
+|*
+|* SwCalc::~SwCalc()
+|*
+|******************************************************************************/
+
+SwCalc::~SwCalc()
+{
+ for( sal_uInt16 n = 0; n < TBLSZ; ++n )
+ delete VarTable[n];
+ if( pLclData != m_aSysLocale.GetLocaleDataPtr() )
+ delete pLclData;
+ if( pCharClass != &GetAppCharClass() )
+ delete pCharClass;
+}
+
+/******************************************************************************
+|*
+|* SwSbxValue SwCalc::Calculate( const String& rStr )
+|*
+|******************************************************************************/
+
+SwSbxValue SwCalc::Calculate( const String& rStr )
+{
+ eError = CALC_NOERR;
+ SwSbxValue nResult;
+
+ if( !rStr.Len() )
+ return nResult;
+
+ nListPor = 0;
+ eCurrListOper = CALC_PLUS; // defaulten auf Summe
+
+ sCommand = rStr;
+ nCommandPos = 0;
+
+ while( (eCurrOper = GetToken()) != CALC_ENDCALC && eError == CALC_NOERR )
+ nResult = Expr();
+
+ if( eError )
+ nResult.PutDouble( DBL_MAX );
+
+ return nResult;
+}
+
+/******************************************************************************
+|*
+|* String SwCalc::GetStrResult( SwSbxValue nValue, sal_Bool bRound = sal_True )
+|* Beschreibung Der Parameter bRound ist auf sal_True defaultet und darf
+|* nur beim errechnen von Tabellenzellen auf sal_False gesetzt
+|* werden, damit keine Rundungsfehler beim zusammenstellen
+|* der Formel entstehen.
+|*
+|******************************************************************************/
+
+String SwCalc::GetStrResult( const SwSbxValue& rVal, sal_Bool bRound )
+{
+ if( !rVal.IsDouble() )
+ return rVal.GetString();
+
+ return GetStrResult( rVal.GetDouble(), bRound );
+}
+
+
+String SwCalc::GetStrResult( double nValue, sal_Bool )
+{
+ if( nValue >= DBL_MAX )
+ switch( eError )
+ {
+ case CALC_SYNTAX : return RESOURCE->aCalc_Syntax;
+ case CALC_ZERODIV : return RESOURCE->aCalc_ZeroDiv;
+ case CALC_BRACK : return RESOURCE->aCalc_Brack;
+ case CALC_POWERR : return RESOURCE->aCalc_Pow;
+ case CALC_VARNFND : return RESOURCE->aCalc_VarNFnd;
+ case CALC_OVERFLOW : return RESOURCE->aCalc_Overflow;
+ case CALC_WRONGTIME : return RESOURCE->aCalc_WrongTime;
+ default : return RESOURCE->aCalc_Default;
+ }
+
+ sal_uInt16 nDec = 15; //pLclData->getNumDigits();
+ String aRetStr( ::rtl::math::doubleToUString( nValue,
+ rtl_math_StringFormat_Automatic,
+ nDec,
+ pLclData->getNumDecimalSep().GetChar(0),
+ true ));
+
+ return aRetStr;
+}
+
+/******************************************************************************
+|*
+|* SwCalcExp* SwCalc::VarLook( const String& )
+|*
+|******************************************************************************/
+
+SwCalcExp* SwCalc::VarInsert( const String &rStr )
+{
+ String aStr( rStr );
+ pCharClass->toLower( aStr );
+ return VarLook( aStr, 1 );
+}
+
+/******************************************************************************
+|*
+|* SwCalcExp* SwCalc::VarLook( const String& , sal_uInt16 ins )
+|*
+|******************************************************************************/
+SwCalcExp* SwCalc::VarLook( const String& rStr, sal_uInt16 ins )
+{
+ aErrExpr.nValue.SetVoidValue(false);
+
+ sal_uInt16 ii = 0;
+ String aStr( rStr );
+ pCharClass->toLower( aStr );
+
+ SwHash* pFnd = Find( aStr, VarTable, TBLSZ, &ii );
+
+ if( !pFnd )
+ {
+ // dann sehen wir mal im Doc nach:
+ SwHash** ppDocTbl = rDoc.GetUpdtFlds().GetFldTypeTable();
+ for( SwHash* pEntry = *(ppDocTbl+ii); pEntry; pEntry = pEntry->pNext )
+ if( aStr == pEntry->aStr )
+ {
+ // dann hier zufuegen
+ pFnd = new SwCalcExp( aStr, SwSbxValue(),
+ ((SwCalcFldType*)pEntry)->pFldType );
+ pFnd->pNext = *(VarTable+ii);
+ *(VarTable+ii) = pFnd;
+ break;
+ }
+ }
+
+ if( pFnd )
+ {
+ SwCalcExp* pFndExp = (SwCalcExp*)pFnd;
+
+ if( pFndExp->pFldType && pFndExp->pFldType->Which() == RES_USERFLD )
+ {
+ SwUserFieldType* pUFld = (SwUserFieldType*)pFndExp->pFldType;
+ if( nsSwGetSetExpType::GSE_STRING & pUFld->GetType() )
+ pFndExp->nValue.PutString( pUFld->GetContent() );
+ else if( !pUFld->IsValid() )
+ {
+ // Die aktuellen Werte sichern . . .
+ sal_uInt16 nOld_ListPor = nListPor;
+ SwSbxValue nOld_LastLeft = nLastLeft;
+ SwSbxValue nOld_NumberValue = nNumberValue;
+ xub_StrLen nOld_CommandPos = nCommandPos;
+ SwCalcOper eOld_CurrOper = eCurrOper;
+ SwCalcOper eOld_CurrListOper = eCurrListOper;
+
+ pFndExp->nValue.PutDouble( pUFld->GetValue( *this ) );
+
+ // . . . und zurueck damit.
+ nListPor = nOld_ListPor;
+ nLastLeft = nOld_LastLeft;
+ nNumberValue = nOld_NumberValue;
+ nCommandPos = nOld_CommandPos;
+ eCurrOper = eOld_CurrOper;
+ eCurrListOper = eOld_CurrListOper;
+ }
+ else
+ pFndExp->nValue.PutDouble( pUFld->GetValue() );
+ }
+ return pFndExp;
+ }
+
+ // Name(p)=Adress.PLZ oder Adress.DATENSATZNUMMER
+ // DBSETNUMBERFLD = DatenSATZ-nummernfeld (NICHT "setze Datensatznummer!!!")
+ // At this point the "real" case variable has to be used
+ String sTmpName( rStr );
+ ::ReplacePoint( sTmpName );
+
+ if( !ins )
+ {
+ SwNewDBMgr *pMgr = rDoc.GetNewDBMgr();
+
+ // Name(p)=Adress.PLZ oder Adress.DATENSATZNUMMER
+ // DBSETNUMBERFLD = DatenSATZ-nummernfeld (NICHT "setze Datensatznummer!!!")
+ String sDBName(GetDBName( sTmpName ));
+ String sSourceName(sDBName.GetToken(0, DB_DELIM));
+ String sTableName(sDBName.GetToken(0).GetToken(1, DB_DELIM));
+ if( pMgr && sSourceName.Len() && sTableName.Len() &&
+ pMgr->OpenDataSource(sSourceName, sTableName, -1, false))
+ {
+ String sColumnName( GetColumnName( sTmpName ));
+ OSL_ENSURE(sColumnName.Len(), "DB-Spaltenname fehlt!");
+
+ String sDBNum( SwFieldType::GetTypeStr(TYP_DBSETNUMBERFLD) );
+ pCharClass->toLower(sDBNum);
+
+ // Hier nochmal initialisieren, da das nicht mehr in docfld
+ // fuer Felder != RES_DBFLD geschieht. Z.B. wenn ein Expressionfield
+ // vor einem DB_Field in einem Dok vorkommt.
+ VarChange( sDBNum, pMgr->GetSelectedRecordId(sSourceName, sTableName));
+
+ if( sDBNum.EqualsIgnoreCaseAscii(sColumnName) )
+ {
+ aErrExpr.nValue.PutLong(long(pMgr->GetSelectedRecordId(sSourceName, sTableName)));
+ return &aErrExpr;
+ }
+
+ sal_uLong nTmpRec = 0;
+ if( 0 != ( pFnd = Find( sDBNum, VarTable, TBLSZ ) ) )
+ nTmpRec = ((SwCalcExp*)pFnd)->nValue.GetULong();
+
+ String sResult;
+ double nNumber = DBL_MAX;
+
+ long nLang = SvxLocaleToLanguage( pLclData->getLocale() );
+ if(pMgr->GetColumnCnt( sSourceName, sTableName, sColumnName,
+ nTmpRec, nLang, sResult, &nNumber ))
+ {
+ if (nNumber != DBL_MAX)
+ aErrExpr.nValue.PutDouble( nNumber );
+ else
+ aErrExpr.nValue.PutString( sResult );
+
+ return &aErrExpr;
+ }
+ }
+ else
+ {
+ //data source was not available - set return to "NoValue"
+ aErrExpr.nValue.SetVoidValue(true);
+ }
+ // auf keinen fall eintragen!!
+ return &aErrExpr;
+ }
+
+
+ SwCalcExp* pNewExp = new SwCalcExp( aStr, SwSbxValue(), 0 );
+ pNewExp->pNext = VarTable[ ii ];
+ VarTable[ ii ] = pNewExp;
+
+ String sColumnName( GetColumnName( sTmpName ));
+ OSL_ENSURE( sColumnName.Len(), "DB-Spaltenname fehlt!" );
+ if( sColumnName.EqualsIgnoreCaseAscii(
+ SwFieldType::GetTypeStr( TYP_DBSETNUMBERFLD ) ))
+ {
+ SwNewDBMgr *pMgr = rDoc.GetNewDBMgr();
+ String sDBName(GetDBName( sTmpName ));
+ String sSourceName(sDBName.GetToken(0, DB_DELIM));
+ String sTableName(sDBName.GetToken(0).GetToken(1, DB_DELIM));
+ if( pMgr && sSourceName.Len() && sTableName.Len() &&
+ pMgr->OpenDataSource(sSourceName, sTableName, -1, false) &&
+ !pMgr->IsInMerge())
+ pNewExp->nValue.PutULong( pMgr->GetSelectedRecordId(sSourceName, sTableName));
+ else
+ pNewExp->nValue.SetVoidValue(true);
+ }
+
+ return pNewExp;
+}
+
+/******************************************************************************
+|*
+|* sal_Bool SwCalc::VarChange( const String& rStr, const SwSbxValue nValue )
+|*
+|******************************************************************************/
+
+void SwCalc::VarChange( const String& rStr, double nValue )
+{
+ SwSbxValue aVal( nValue );
+ VarChange( rStr, aVal );
+}
+
+void SwCalc::VarChange( const String& rStr, const SwSbxValue& rValue )
+{
+ String aStr( rStr );
+ pCharClass->toLower( aStr );
+
+ sal_uInt16 nPos = 0;
+ SwCalcExp* pFnd = (SwCalcExp*)Find( aStr, VarTable, TBLSZ, &nPos );
+
+ if( !pFnd )
+ {
+ pFnd = new SwCalcExp( aStr, SwSbxValue( rValue ), 0 );
+ pFnd->pNext = VarTable[ nPos ];
+ VarTable[ nPos ] = pFnd;
+ }
+ else
+ pFnd->nValue = rValue;
+}
+
+/******************************************************************************
+|*
+|* sal_Bool SwCalc::Push( const void* pPtr )
+|*
+|******************************************************************************/
+
+sal_Bool SwCalc::Push( const VoidPtr pPtr )
+{
+ if( USHRT_MAX != aRekurStk.GetPos( pPtr ) )
+ return sal_False;
+
+ aRekurStk.Insert( pPtr, aRekurStk.Count() );
+ return sal_True;
+}
+
+/******************************************************************************
+|*
+|* void SwCalc::Pop( const void* pPtr )
+|*
+|******************************************************************************/
+
+void SwCalc::Pop( const VoidPtr )
+{
+ OSL_ENSURE( aRekurStk.Count(), "SwCalc: Pop auf ungueltigen Ptr" );
+
+ aRekurStk.Remove( aRekurStk.Count() - 1 );
+}
+
+
+/******************************************************************************
+|*
+|* SwCalcOper SwCalc::GetToken()
+|*
+|******************************************************************************/
+
+SwCalcOper SwCalc::GetToken()
+{
+#if OSL_DEBUG_LEVEL > 1
+//static for switch back to the "old" implementation of the
+//calculator, which don't use the I18N routines.
+static int nUseOld = 0;
+if( !nUseOld )
+{
+#endif
+
+ if( nCommandPos >= sCommand.Len() )
+ return eCurrOper = CALC_ENDCALC;
+
+ using namespace ::com::sun::star::i18n;
+ {
+ // Parse any token.
+ ParseResult aRes = pCharClass->parseAnyToken( sCommand, nCommandPos,
+ coStartFlags, aEmptyStr,
+ coContFlags, aEmptyStr );
+
+ sal_Bool bSetError = sal_True;
+ xub_StrLen nRealStt = nCommandPos + (xub_StrLen)aRes.LeadingWhiteSpace;
+ if( aRes.TokenType & (KParseType::ASC_NUMBER | KParseType::UNI_NUMBER) )
+ {
+ nNumberValue.PutDouble( aRes.Value );
+ eCurrOper = CALC_NUMBER;
+ bSetError = sal_False;
+ }
+ else if( aRes.TokenType & KParseType::IDENTNAME )
+ {
+ String aName( sCommand.Copy( nRealStt, static_cast<xub_StrLen>(aRes.EndPos) - nRealStt ));
+ //#101436#: the variable may contain a database name it must not be converted to lower case
+ // instead all further comparisons must be done case-insensitive
+ //pCharClass->toLower( aName );
+ String sLowerCaseName(aName);
+ pCharClass->toLower( sLowerCaseName );
+ // Currency-Symbol abfangen
+ if( sLowerCaseName == sCurrSym )
+ {
+ nCommandPos = (xub_StrLen)aRes.EndPos;
+ return GetToken(); // also nochmal aufrufen
+ }
+
+ // Operations abfangen
+ _CalcOp* pFnd = ::FindOperator( sLowerCaseName );
+ if( pFnd )
+ {
+ switch( ( eCurrOper = ((_CalcOp*)pFnd)->eOp ) )
+ {
+ case CALC_SUM:
+ case CALC_MEAN:
+ eCurrListOper = CALC_PLUS;
+ break;
+ case CALC_MIN:
+ eCurrListOper = CALC_MIN_IN;
+ break;
+ case CALC_MAX:
+ eCurrListOper = CALC_MAX_IN;
+ break;
+ case CALC_DATE:
+ eCurrListOper = CALC_MONTH;
+ break;
+ default:
+ break;
+ }
+ nCommandPos = (xub_StrLen)aRes.EndPos;
+ return eCurrOper;
+ }
+ aVarName = aName;
+ eCurrOper = CALC_NAME;
+ bSetError = sal_False;
+ }
+ else if ( aRes.TokenType & KParseType::DOUBLE_QUOTE_STRING )
+ {
+ nNumberValue.PutString( String( aRes.DequotedNameOrString ));
+ eCurrOper = CALC_NUMBER;
+ bSetError = sal_False;
+ }
+ else if( aRes.TokenType & KParseType::ONE_SINGLE_CHAR )
+ {
+ String aName( sCommand.Copy( nRealStt, static_cast<xub_StrLen>(aRes.EndPos) - nRealStt ));
+ if( 1 == aName.Len() )
+ {
+ bSetError = sal_False;
+ sal_Unicode ch = aName.GetChar( 0 );
+ switch( ch )
+ {
+ case ';': if( CALC_MONTH == eCurrListOper ||
+ CALC_DAY == eCurrListOper )
+ {
+ eCurrOper = eCurrListOper;
+ break;
+ }
+ case '\n':
+ eCurrOper = CALC_PRINT;
+ break;
+ case '%':
+ case '^':
+ case '*':
+ case '/':
+ case '+':
+ case '-':
+ case '(':
+ case ')': eCurrOper = SwCalcOper(ch);
+ break;
+
+ case '=':
+ case '!':
+ {
+ SwCalcOper eTmp2;
+ if( '=' == ch )
+ eCurrOper = SwCalcOper('='), eTmp2 = CALC_EQ;
+ else
+ eCurrOper = CALC_NOT, eTmp2 = CALC_NEQ;
+
+ if( aRes.EndPos < sCommand.Len() &&
+ '=' == sCommand.GetChar( (xub_StrLen)aRes.EndPos ) )
+ {
+ eCurrOper = eTmp2;
+ ++aRes.EndPos;
+ }
+ }
+ break;
+
+ case cListDelim :
+ eCurrOper = eCurrListOper;
+ break;
+
+ case '[':
+ if( aRes.EndPos < sCommand.Len() )
+ {
+ aVarName.Erase();
+ xub_StrLen nFndPos = (xub_StrLen)aRes.EndPos,
+ nSttPos = nFndPos;
+
+ do{
+ if( STRING_NOTFOUND != ( nFndPos =
+ sCommand.Search( ']', nFndPos )) )
+ {
+ // ignore the ]
+ if( '\\' == sCommand.GetChar(nFndPos-1))
+ {
+ aVarName += sCommand.Copy( nSttPos,
+ nFndPos - nSttPos - 1 );
+ nSttPos = ++nFndPos;
+ }
+ else
+ break;
+ }
+ } while( STRING_NOTFOUND != nFndPos );
+
+ if( STRING_NOTFOUND != nFndPos )
+ {
+ if( nSttPos != nFndPos )
+ aVarName += sCommand.Copy( nSttPos,
+ nFndPos - nSttPos );
+ aRes.EndPos = nFndPos + 1;
+ eCurrOper = CALC_NAME;
+ }
+ else
+ bSetError = sal_True;
+ }
+ else
+ bSetError = sal_True;
+ break;
+
+ default:
+ bSetError = sal_True;
+ break;
+ }
+ }
+ }
+ else if( aRes.TokenType & KParseType::BOOLEAN )
+ {
+ String aName( sCommand.Copy( nRealStt, static_cast<xub_StrLen>(aRes.EndPos) - nRealStt ));
+ if( aName.Len() )
+ {
+ sal_Unicode ch = aName.GetChar(0);
+
+ bSetError = sal_True;
+ if ('<' == ch || '>' == ch)
+ {
+ bSetError = sal_False;
+
+ SwCalcOper eTmp2 = ('<' == ch) ? CALC_LEQ : CALC_GEQ;
+ eCurrOper = ('<' == ch) ? CALC_LES : CALC_GRE;
+
+ if( 2 == aName.Len() && '=' == aName.GetChar(1) )
+ eCurrOper = eTmp2;
+ else if( 1 != aName.Len() )
+ bSetError = sal_True;
+ }
+ }
+ }
+ else if( nRealStt == sCommand.Len() )
+ {
+ eCurrOper = CALC_ENDCALC;
+ bSetError = sal_False;
+ }
+
+ if( bSetError )
+ {
+ eError = CALC_SYNTAX;
+ eCurrOper = CALC_PRINT;
+ }
+ nCommandPos = (xub_StrLen)aRes.EndPos;
+ };
+
+#if OSL_DEBUG_LEVEL > 1
+
+#define NextCh( s, n ) (nCommandPos < sCommand.Len() ? sCommand.GetChar( nCommandPos++ ) : 0)
+
+}
+else
+{
+ sal_Unicode ch;
+ sal_Unicode cTSep = pLclData->getNumThousandSep().GetChar(0),
+ cDSep = pLclData->getNumDecimalSep().GetChar(0);
+
+ do {
+ if( 0 == ( ch = NextCh( sCommand, nCommandPos ) ) )
+ return eCurrOper = CALC_ENDCALC;
+ } while ( ch == '\t' || ch == ' ' || ch == cTSep );
+
+ if( ch == cDSep )
+ ch = '.';
+
+ switch( ch )
+ {
+ case ';': if( CALC_MONTH == eCurrListOper || CALC_DAY == eCurrListOper )
+ {
+ eCurrOper = eCurrListOper;
+ break;
+ } // else .. no break
+ case '\n':
+ {
+ sal_Unicode c;
+ while( nCommandPos < sCommand.Len() && ( ( c =
+ sCommand.GetChar( nCommandPos ) ) == ' ' ||
+ c == '\t' || c == '\x0a' || c == '\x0d' ))
+ ++nCommandPos;
+ eCurrOper = CALC_PRINT;
+ }
+ break;
+ case '%':
+ case '^':
+ case '*':
+ case '/':
+ case '+':
+ case '-':
+ case '(':
+ case ')': eCurrOper = SwCalcOper(ch);
+ break;
+
+ case '=': if( '=' == sCommand.GetChar( nCommandPos ) )
+ {
+ ++nCommandPos;
+ eCurrOper = CALC_EQ;
+ }
+ else
+ eCurrOper = SwCalcOper(ch);
+ break;
+
+ case '!': if( '=' == sCommand.GetChar( nCommandPos ) )
+ {
+ ++nCommandPos;
+ eCurrOper = CALC_NEQ;
+ }
+ else
+ eCurrOper = CALC_NOT;
+ break;
+
+ case '>':
+ case '<': eCurrOper = '>' == ch ? CALC_GRE : CALC_LES;
+ if( '=' == (ch = sCommand.GetChar( nCommandPos ) ) )
+ {
+ ++nCommandPos;
+ eCurrOper = CALC_GRE == eCurrOper ? CALC_GEQ : CALC_LEQ;
+ }
+ else if( ' ' != ch )
+ {
+ eError = CALC_SYNTAX;
+ eCurrOper = CALC_PRINT;
+ }
+ break;
+
+ case cListDelim :
+ eCurrOper = eCurrListOper;
+ break;
+
+ case '0': case '1': case '2': case '3': case '4':
+ case '5': case '6': case '7': case '8': case '9':
+ case ',':
+ case '.': {
+ double nVal;
+ --nCommandPos; // auf das 1. Zeichen zurueck
+ if( Str2Double( sCommand, nCommandPos, nVal, pLclData ))
+ {
+ nNumberValue.PutDouble( nVal );
+ eCurrOper = CALC_NUMBER;
+ }
+ else
+ {
+ // fehlerhafte Zahl
+ eError = CALC_SYNTAX;
+ eCurrOper = CALC_PRINT;
+ }
+ }
+ break;
+
+ case '[': {
+ String aStr;
+ sal_Bool bIgnore = sal_False;
+ do {
+ while( 0 != ( ch = NextCh( sCommand, nCommandPos ))
+ && ch != ']' )
+ {
+ if( !bIgnore && '\\' == ch )
+ bIgnore = sal_True;
+ else if( bIgnore )
+ bIgnore = sal_False;
+ aStr += ch;
+ }
+
+ if( !bIgnore )
+ break;
+
+ aStr.SetChar( aStr.Len() - 1, ch );
+ } while( ch );
+
+ aVarName = aStr;
+ eCurrOper = CALC_NAME;
+ }
+ break;
+
+ case '"': {
+ xub_StrLen nStt = nCommandPos;
+ while( 0 != ( ch = NextCh( sCommand, nCommandPos ) )
+ && '"' != ch )
+ ;
+
+ xub_StrLen nLen = nCommandPos - nStt;
+ if( '"' == ch )
+ --nLen;
+ nNumberValue.PutString( sCommand.Copy( nStt, nLen ));
+ eCurrOper = CALC_NUMBER;
+ }
+ break;
+
+ default: if (ch && (pCharClass->isLetter( sCommand, nCommandPos - 1) || '_' == ch))
+ {
+ xub_StrLen nStt = nCommandPos-1;
+ while( 0 != (ch = NextCh( sCommand, nCommandPos )) &&
+ (pCharClass->isLetterNumeric(
+ sCommand, nCommandPos - 1) ||
+ ch == '_' || ch == '.' ) )
+ ;
+
+ if( ch )
+ --nCommandPos;
+
+ String aStr( sCommand.Copy( nStt, nCommandPos-nStt ));
+ pCharClass->toLower( aStr );
+
+
+ // Currency-Symbol abfangen
+ if( aStr == sCurrSym )
+ return GetToken(); // also nochmal aufrufen
+
+ // Operations abfangen
+ _CalcOp* pFnd = ::FindOperator( aStr );
+ if( pFnd )
+ {
+ switch( ( eCurrOper = ((_CalcOp*)pFnd)->eOp ) )
+ {
+ case CALC_SUM :
+ case CALC_MEAN : eCurrListOper = CALC_PLUS;
+ break;
+ case CALC_MIN : eCurrListOper = CALC_MIN_IN;
+ break;
+ case CALC_MAX : eCurrListOper = CALC_MAX_IN;
+ break;
+ case CALC_DATE : eCurrListOper = CALC_MONTH;
+ break;
+ default :
+ break;
+ }
+ return eCurrOper;
+ }
+ aVarName = aStr;
+ eCurrOper = CALC_NAME;
+ }
+ else
+ {
+ eError = CALC_SYNTAX;
+ eCurrOper = CALC_PRINT;
+ }
+ break;
+ }
+
+}
+#endif
+ return eCurrOper;
+}
+
+/******************************************************************************
+|*
+|* SwSbxValue SwCalc::Term()
+|*
+|******************************************************************************/
+
+SwSbxValue SwCalc::Term()
+{
+ SwSbxValue left( Prim() );
+ nLastLeft = left;
+ for(;;)
+ {
+ sal_uInt16 nSbxOper = USHRT_MAX;
+
+ switch( eCurrOper )
+ {
+ case CALC_AND: {
+ GetToken();
+ sal_Bool bB = Prim().GetBool();
+ left.PutBool( left.GetBool() && bB );
+ }
+ break;
+ case CALC_OR: {
+ GetToken();
+ sal_Bool bB = Prim().GetBool();
+ left.PutBool( left.GetBool() || bB );
+ }
+ break;
+ case CALC_XOR: {
+ GetToken();
+ sal_Bool bR = Prim().GetBool();
+ sal_Bool bL = left.GetBool();
+ left.PutBool( (bL && !bR) || (!bL && bR) );
+ }
+ break;
+
+ case CALC_EQ: nSbxOper = SbxEQ; break;
+ case CALC_NEQ: nSbxOper = SbxNE; break;
+ case CALC_LEQ: nSbxOper = SbxLE; break;
+ case CALC_GEQ: nSbxOper = SbxGE; break;
+ case CALC_GRE: nSbxOper = SbxGT; break;
+ case CALC_LES: nSbxOper = SbxLT; break;
+
+ case CALC_MUL: nSbxOper = SbxMUL; break;
+ case CALC_DIV: nSbxOper = SbxDIV; break;
+
+ case CALC_MIN_IN:
+ {
+ GetToken();
+ SwSbxValue e = Prim();
+ left = left.GetDouble() < e.GetDouble()
+ ? left : e;
+ }
+ break;
+ case CALC_MAX_IN:
+ {
+ GetToken();
+ SwSbxValue e = Prim();
+ left = left.GetDouble() > e.GetDouble()
+ ? left : e;
+ }
+ break;
+ case CALC_MONTH:
+ {
+ GetToken();
+ SwSbxValue e = Prim();
+ sal_Int32 nYear = (sal_Int32) floor( left.GetDouble() );
+ nYear = nYear & 0x0000FFFF;
+ sal_Int32 nMonth = (sal_Int32) floor( e.GetDouble() );
+ nMonth = ( nMonth & 0x000000FF ) << 16;
+ left.PutLong( nMonth + nYear );
+ eCurrOper = CALC_DAY;
+ }
+ break;
+ case CALC_DAY:
+ {
+ GetToken();
+ SwSbxValue e = Prim();
+ sal_Int32 nYearMonth = (sal_Int32) floor( left.GetDouble() );
+ nYearMonth = nYearMonth & 0x00FFFFFF;
+ sal_Int32 nDay = (sal_Int32) floor( e.GetDouble() );
+ nDay = ( nDay & 0x000000FF ) << 24;
+ left = lcl_ConvertToDateValue( rDoc, nDay + nYearMonth );
+ }
+ break;
+ case CALC_ROUND:
+ {
+ GetToken();
+ SwSbxValue e = Prim();
+
+ double fVal = 0;
+ double fFac = 1;
+ sal_Int32 nDec = (sal_Int32) floor( e.GetDouble() );
+ if( nDec < -20 || nDec > 20 )
+ {
+ eError = CALC_OVERFLOW;
+ left.Clear();
+ return left;
+ }
+ fVal = left.GetDouble();
+ sal_uInt16 i;
+ if( nDec >= 0)
+ for (i = 0; i < (sal_uInt16) nDec; ++i )
+ fFac *= 10.0;
+ else
+ for (i = 0; i < (sal_uInt16) -nDec; ++i )
+ fFac /= 10.0;
+
+ fVal *= fFac;
+
+ sal_Bool bSign;
+ if (fVal < 0.0)
+ {
+ fVal *= -1.0;
+ bSign = sal_True;
+ }
+ else
+ bSign = sal_False;
+
+ // runden
+ double fNum = fVal; // find the exponent
+ int nExp = 0;
+ if( fNum > 0 )
+ {
+ while( fNum < 1.0 ) fNum *= 10.0, --nExp;
+ while( fNum >= 10.0 ) fNum /= 10.0, ++nExp;
+ }
+ nExp = 15 - nExp;
+ if( nExp > 15 )
+ nExp = 15;
+ else if( nExp <= 1 )
+ nExp = 0;
+ fVal = floor( fVal+ 0.5 + nRoundVal[ nExp ] );
+
+ if (bSign)
+ fVal *= -1.0;
+
+ fVal /= fFac;
+
+ left.PutDouble( fVal );
+ }
+ break;
+
+//#77448# (=2*3^2 != 18)
+
+ default: return left;
+ }
+
+ if( USHRT_MAX != nSbxOper )
+ {
+ // #i47706: cast to SbxOperator AFTER comparing to USHRT_MAX
+ SbxOperator eSbxOper = (SbxOperator)nSbxOper;
+
+ GetToken();
+ if( SbxEQ <= eSbxOper && eSbxOper <= SbxGE )
+ left.PutBool( left.Compare( eSbxOper, Prim() ));
+ else
+ {
+ SwSbxValue aRight( Prim() );
+ aRight.MakeDouble();
+ left.MakeDouble();
+
+ if( SbxDIV == eSbxOper && !aRight.GetDouble() )
+ eError = CALC_ZERODIV;
+ else
+ left.Compute( eSbxOper, aRight );
+ }
+ }
+ }
+}
+
+/******************************************************************************
+|*
+|* SwSbxValue SwCalc::Prim()
+|*
+|******************************************************************************/
+
+extern "C" typedef double (*pfCalc)( double );
+
+SwSbxValue SwCalc::Prim()
+{
+ SwSbxValue nErg;
+
+ pfCalc pFnc = 0;
+
+ sal_Bool bChkTrig = sal_False, bChkPow = sal_False;
+
+ switch( eCurrOper )
+ {
+ case CALC_SIN: pFnc = &sin; break;
+ case CALC_COS: pFnc = &cos; break;
+ case CALC_TAN: pFnc = &tan; break;
+ case CALC_ATAN: pFnc = &atan; break;
+ case CALC_ASIN: pFnc = &asin; bChkTrig = sal_True; break;
+ case CALC_ACOS: pFnc = &acos; bChkTrig = sal_True; break;
+
+ case CALC_NOT: {
+ GetToken();
+ nErg = Prim();
+ if( SbxSTRING == nErg.GetType() )
+ nErg.PutBool( 0 == nErg.GetString().Len() );
+ else if(SbxBOOL == nErg.GetType() )
+ nErg.PutBool(!nErg.GetBool());
+ // evaluate arguments manually so that the binary NOT below
+ // does not get called.
+ // We want a BOOLEAN NOT.
+ else if (nErg.IsNumeric())
+ nErg.PutLong( nErg.GetDouble() == 0.0 ? 1 : 0 );
+ else
+ {
+ OSL_FAIL( "unexpected case. computing binary NOT" );
+ //!! computes a binary NOT
+ nErg.Compute( SbxNOT, nErg );
+ }
+ }
+ break;
+
+ case CALC_NUMBER: if( GetToken() == CALC_PHD )
+ {
+ double aTmp = nNumberValue.GetDouble();
+ aTmp *= 0.01;
+ nErg.PutDouble( aTmp );
+ GetToken();
+ }
+ else if( eCurrOper == CALC_NAME )
+ eError = CALC_SYNTAX;
+ else
+ {
+ nErg = nNumberValue;
+ bChkPow = sal_True;
+ }
+ break;
+
+ case CALC_NAME: if( GetToken() == CALC_ASSIGN )
+ {
+ SwCalcExp* n = VarInsert( aVarName );
+ GetToken();
+ nErg = n->nValue = Expr();
+ }
+ else
+ {
+ nErg = VarLook( aVarName )->nValue;
+ bChkPow = sal_True;
+ }
+ break;
+
+ case CALC_MINUS: GetToken();
+ nErg.PutDouble( -(Prim().GetDouble()) );
+ break;
+
+ case CALC_LP: {
+ GetToken();
+ nErg = Expr();
+ if( eCurrOper != CALC_RP )
+ eError = CALC_BRACK;
+ else
+ {
+ GetToken();
+ bChkPow = sal_True; // in order for =(7)^2 to work
+ }
+ }
+ break;
+
+ case CALC_MEAN: {
+ nListPor = 1;
+ GetToken();
+ nErg = Expr();
+ double aTmp = nErg.GetDouble();
+ aTmp /= nListPor;
+ nErg.PutDouble( aTmp );
+ }
+ break;
+
+ case CALC_SQRT: {
+ GetToken();
+ nErg = Prim();
+ if( nErg.GetDouble() < 0 )
+ eError = CALC_OVERFLOW;
+ else
+ nErg.PutDouble( sqrt( nErg.GetDouble() ));
+ }
+ break;
+
+ case CALC_SUM:
+ case CALC_DATE:
+ case CALC_MIN:
+ case CALC_MAX: GetToken();
+ nErg = Expr();
+ break;
+
+ case CALC_ENDCALC: nErg.Clear();
+ break;
+
+ default: eError = CALC_SYNTAX;
+ break;
+ }
+
+ if( pFnc )
+ {
+ GetToken();
+ double nVal = Prim().GetDouble();
+ if( !bChkTrig || ( nVal > -1 && nVal < 1 ) )
+ nErg.PutDouble( (*pFnc)( nVal ) );
+ else
+ eError = CALC_OVERFLOW;
+ }
+
+ if( bChkPow && eCurrOper == CALC_POW )
+ {
+ double dleft = nErg.GetDouble();
+ GetToken();
+ double right = Prim().GetDouble();
+
+ double fraction, integer;
+ fraction = modf( right, &integer );
+ if( ( dleft < 0.0 && 0.0 != fraction ) ||
+ ( 0.0 == dleft && right < 0.0 ) )
+ {
+ eError = CALC_OVERFLOW;
+ nErg.Clear();
+ }
+ else
+ {
+ dleft = pow(dleft, right );
+ if( dleft == HUGE_VAL )
+ {
+ eError = CALC_POWERR;
+ nErg.Clear();
+ }
+ else
+ {
+ nErg.PutDouble( dleft );
+// GetToken();
+ }
+ }
+ }
+
+ return nErg;
+}
+
+/******************************************************************************
+|*
+|* SwSbxValue SwCalc::Expr()
+|*
+|******************************************************************************/
+
+SwSbxValue SwCalc::Expr()
+{
+ SwSbxValue left = Term(), right;
+ nLastLeft = left;
+ for(;;)
+ switch(eCurrOper)
+ {
+ case CALC_PLUS: GetToken();
+ // erzeuge zum addieren auf jedenfall einen
+ // Double-Wert
+ left.MakeDouble();
+ ( right = Term() ).MakeDouble();
+ left.Compute( SbxPLUS, right );
+ nListPor++;
+ break;
+
+ case CALC_MINUS: GetToken();
+ // erzeuge zum addieren auf jedenfall einen
+ // Double-Wert
+ left.MakeDouble();
+ ( right = Term() ).MakeDouble();
+ left.Compute( SbxMINUS, right );
+ break;
+
+ default: return left;
+ }
+}
+
+//------------------------------------------------------------------------------
+
+String SwCalc::GetColumnName(const String& rName)
+{
+ xub_StrLen nPos = rName.Search(DB_DELIM);
+ if( STRING_NOTFOUND != nPos )
+ {
+ nPos = rName.Search(DB_DELIM, nPos + 1);
+
+ if( STRING_NOTFOUND != nPos )
+ return rName.Copy(nPos + 1);
+ }
+ return rName;
+}
+
+//------------------------------------------------------------------------------
+
+String SwCalc::GetDBName(const String& rName)
+{
+ xub_StrLen nPos = rName.Search(DB_DELIM);
+ if( STRING_NOTFOUND != nPos )
+ {
+ nPos = rName.Search(DB_DELIM, nPos + 1);
+
+ if( STRING_NOTFOUND != nPos )
+ return rName.Copy( 0, nPos );
+ }
+ SwDBData aData = rDoc.GetDBData();
+ String sRet = aData.sDataSource;
+ sRet += DB_DELIM;
+ sRet += String(aData.sCommand);
+ return sRet;
+}
+
+//------------------------------------------------------------------------------
+
+namespace
+{
+
+static bool
+lcl_Str2Double( const String& rCommand, xub_StrLen& rCommandPos, double& rVal,
+ const LocaleDataWrapper* const pLclData )
+{
+ OSL_ASSERT(pLclData);
+ const xub_Unicode nCurrCmdPos = rCommandPos;
+ rtl_math_ConversionStatus eStatus;
+ const sal_Unicode* pEnd;
+ rVal = rtl_math_uStringToDouble( rCommand.GetBuffer() + rCommandPos,
+ rCommand.GetBuffer() + rCommand.Len(),
+ pLclData->getNumDecimalSep().GetChar(0),
+ pLclData->getNumThousandSep().GetChar(0),
+ &eStatus, &pEnd );
+ rCommandPos = static_cast<xub_StrLen>(pEnd - rCommand.GetBuffer());
+
+ return rtl_math_ConversionStatus_Ok == eStatus && nCurrCmdPos != rCommandPos;
+}
+
+}
+
+/******************************************************************************
+ * Methode : sal_Bool SwCalc::Str2Double( double& )
+ ******************************************************************************/
+bool SwCalc::Str2Double( const String& rCommand, xub_StrLen& rCommandPos,
+ double& rVal, const LocaleDataWrapper* const pLclData )
+{
+ const SvtSysLocale aSysLocale;
+ return lcl_Str2Double( rCommand, rCommandPos, rVal,
+ pLclData ? pLclData : aSysLocale.GetLocaleDataPtr() );
+}
+
+bool SwCalc::Str2Double( const String& rCommand, xub_StrLen& rCommandPos,
+ double& rVal, SwDoc* const pDoc )
+{
+ const SvtSysLocale aSysLocale;
+ ::std::auto_ptr<const LocaleDataWrapper> pLclD;
+ if( pDoc )
+ {
+ LanguageType eLang = GetDocAppScriptLang( *pDoc );
+ if (eLang !=
+ SvxLocaleToLanguage(aSysLocale.GetLocaleData().getLocale()))
+ {
+ pLclD.reset( new LocaleDataWrapper(
+ ::comphelper::getProcessServiceFactory(),
+ SvxCreateLocale( eLang ) ) );
+ }
+ }
+
+ bool const bRet = lcl_Str2Double( rCommand, rCommandPos, rVal,
+ (pLclD.get()) ? pLclD.get() : aSysLocale.GetLocaleDataPtr() );
+
+ return bRet;
+}
+
+//------------------------------------------------------------------------------
+
+sal_Bool SwCalc::IsValidVarName( const String& rStr,
+ String* pValidName )
+{
+ sal_Bool bRet = sal_False;
+ using namespace ::com::sun::star::i18n;
+ {
+ // Parse any token.
+ ParseResult aRes = GetAppCharClass().parseAnyToken( rStr, 0,
+ coStartFlags, aEmptyStr,
+ coContFlags, aEmptyStr );
+
+ if( aRes.TokenType & KParseType::IDENTNAME )
+ {
+ bRet = aRes.EndPos == rStr.Len();
+ if( pValidName )
+ {
+ xub_StrLen nRealStt = (xub_StrLen)aRes.LeadingWhiteSpace;
+ *pValidName = rStr.Copy( nRealStt, static_cast<xub_StrLen>(aRes.EndPos) - nRealStt );
+ }
+ }
+ else if( pValidName )
+ pValidName->Erase();
+ }
+ return bRet;
+}
+
+//------------------------------------------------------------------------------
+
+/******************************************************************************
+|*
+|* CTOR DTOR der SwHash classes
+|*
+******************************************************************************/
+
+SwHash::SwHash( const String& rStr ) :
+ aStr( rStr ),
+ pNext( 0 )
+{}
+
+SwHash::~SwHash()
+{
+ if( pNext )
+ delete pNext;
+}
+
+void DeleteHashTable( SwHash **ppHashTable, sal_uInt16 nCount )
+{
+ for ( sal_uInt16 i = 0; i < nCount; ++i )
+ delete *(ppHashTable+i);
+ delete [] ppHashTable;
+}
+
+SwCalcExp::SwCalcExp( const String& rStr, const SwSbxValue& rVal,
+ const SwFieldType* pType )
+ : SwHash( rStr ),
+ nValue( rVal ),
+ pFldType( pType )
+{
+}
+
+
+SwSbxValue::~SwSbxValue()
+{
+}
+
+sal_Bool SwSbxValue::GetBool() const
+{
+ return SbxSTRING == GetType() ? 0 != GetString().Len()
+ : 0 != SbxValue::GetBool();
+}
+
+double SwSbxValue::GetDouble() const
+{
+ double nRet;
+ if( SbxSTRING == GetType() )
+ {
+ xub_StrLen nStt = 0;
+ SwCalc::Str2Double( GetString(), nStt, nRet );
+ }
+ else if (IsBool())
+ {
+ nRet = 0 != GetBool() ? 1.0 : 0.0;
+ }
+ else
+ nRet = SbxValue::GetDouble();
+ return nRet;
+}
+
+SwSbxValue& SwSbxValue::MakeDouble()
+{
+ if( GetType() == SbxSTRING || GetType() == SbxBOOL )
+ PutDouble( GetDouble() );
+ return *this;
+}
+
+#ifdef STANDALONE_HASHCALC
+
+// dies ist der Beispielcode zu erzeugen der HashValues im CTOR:
+
+#include <stdio.h>
+
+void main()
+{
+static sal_Char
+ sNType0[] = "false", sNType1[] = "true", sNType2[] = "pi",
+ sNType3[] = "e", sNType4[] = "tables", sNType5[] = "graf",
+ sNType6[] = "ole", sNType7[] = "page", sNType8[] = "para",
+ sNType9[] = "word", sNType10[]= "char",
+ sNType11[] = "user_company" , sNType12[] = "user_firstname" ,
+ sNType13[] = "user_lastname" , sNType14[] = "user_initials",
+ sNType15[] = "user_street" , sNType16[] = "user_country" ,
+ sNType17[] = "user_zipcode" , sNType18[] = "user_city" ,
+ sNType19[] = "user_title" , sNType20[] = "user_position" ,
+ sNType21[] = "user_tel_home", sNType22[] = "user_tel_work",
+ sNType23[] = "user_fax" , sNType24[] = "user_email" ,
+ sNType25[] = "user_state", sNType26[] = "graph"
+ ;
+
+static const sal_Char* sNTypeTab[ 27 ] =
+{
+ sNType0, sNType1, sNType2, sNType3, sNType4, sNType5,
+ sNType6, sNType7, sNType8, sNType9, sNType10, sNType11,
+ sNType12, sNType13, sNType14, sNType15, sNType16, sNType17,
+ sNType18, sNType19, sNType20, sNType21, sNType22, sNType23,
+ sNType24, sNType25, sNType26
+};
+
+ const unsigned short nTblSize = 47;
+ int aArr[ nTblSize ] = { 0 };
+ sal_Char ch;
+
+ for( int n = 0; n < 27; ++n )
+ {
+ unsigned long ii = 0;
+ const sal_Char* pp = sNTypeTab[ n ];
+
+ while( *pp )
+ ii = ii << 1 ^ *pp++;
+ ii %= nTblSize;
+
+ ch = aArr[ ii ] ? 'X' : ' ';
+ aArr[ ii ] = 1;
+ printf( "%-20s -> %3d [%c]\n", sNTypeTab[ n ], ii, ch );
+ }
+}
+
+#endif
+
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/bastyp/checkit.cxx b/sw/source/core/bastyp/checkit.cxx
new file mode 100644
index 000000000000..ec4a3b8e8aed
--- /dev/null
+++ b/sw/source/core/bastyp/checkit.cxx
@@ -0,0 +1,53 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+
+#include <com/sun/star/lang/XMultiServiceFactory.hpp>
+#include <comphelper/processfactory.hxx>
+#include <checkit.hxx>
+
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star::i18n;
+
+SwCheckIt::SwCheckIt()
+{
+ Reference< XMultiServiceFactory > xMSF = ::comphelper::getProcessServiceFactory();
+ Reference < XInterface > xI = xMSF->createInstance(
+ ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.i18n.InputSequenceChecker")) );
+ if ( xI.is() )
+ {
+ Any x = xI->queryInterface( ::getCppuType((const Reference< XExtendedInputSequenceChecker >*)0) );
+ x >>= xCheck;
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/bastyp/index.cxx b/sw/source/core/bastyp/index.cxx
new file mode 100644
index 000000000000..32457b85c960
--- /dev/null
+++ b/sw/source/core/bastyp/index.cxx
@@ -0,0 +1,463 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+
+#include <stdlib.h> // fuer qsort
+#include <tools/solar.h>
+
+#include "index.hxx"
+
+#if OSL_DEBUG_LEVEL > 1
+int SwIndex::nSerial = 0;
+#endif
+
+
+TYPEINIT0(SwIndexReg); // rtti
+
+
+SwIndex::SwIndex(SwIndexReg *const pArr, xub_StrLen const nIdx)
+ : nIndex( nIdx ), pArray( pArr ), pNext( 0 ), pPrev( 0 )
+{
+ if( !pArray )
+ {
+ pArray = SwIndexReg::pEmptyIndexArray;
+ nIndex = 0; // steht immer auf 0 !!!
+ }
+
+ if( !pArray->pFirst || !pArray->pLast ) // 1. Index ??
+ pArray->pFirst = pArray->pLast = this;
+ else if( nIdx > ((pArray->pLast->nIndex - pArray->pFirst->nIndex) / 2) )
+ ChgValue( *pArray->pLast, nIdx );
+ else
+ ChgValue( *pArray->pFirst, nIdx );
+
+#if OSL_DEBUG_LEVEL > 1
+ MySerial = ++nSerial; // nur in der nicht PRODUCT-Version
+#endif
+}
+
+
+SwIndex::SwIndex( const SwIndex& rIdx, short nIdx )
+ : pArray( rIdx.pArray ), pNext( 0 ), pPrev( 0 )
+{
+ ChgValue( rIdx, rIdx.nIndex + nIdx );
+
+#if OSL_DEBUG_LEVEL > 1
+ MySerial = ++nSerial; // nur in der nicht PRODUCT-Version
+#endif
+}
+
+
+SwIndex::SwIndex( const SwIndex& rIdx )
+ : nIndex( rIdx.nIndex ), pArray( rIdx.pArray ), pNext( 0 ), pPrev( 0 )
+{
+ ChgValue( rIdx, rIdx.nIndex );
+#if OSL_DEBUG_LEVEL > 1
+ MySerial = ++nSerial; // nur in der nicht PRODUCT-Version
+#endif
+}
+
+
+SwIndex& SwIndex::ChgValue( const SwIndex& rIdx, xub_StrLen nNewValue )
+{
+ SwIndex* pFnd = (SwIndex*)&rIdx;
+ if( rIdx.nIndex > nNewValue ) // nach vorne versuchen
+ {
+ SwIndex* pPrv;
+ while( 0 != ( pPrv = pFnd->pPrev ) && pPrv->nIndex > nNewValue )
+ pFnd = pPrv;
+
+ if( pFnd != this )
+ {
+ // an alter Position ausketten
+ // erstmal an alter Position ausketten
+ if( pPrev )
+ pPrev->pNext = pNext;
+ else if( pArray->pFirst == this )
+ pArray->pFirst = pNext;
+
+ if( pNext )
+ pNext->pPrev = pPrev;
+ else if( pArray->pLast == this )
+ pArray->pLast = pPrev;
+
+ pNext = pFnd;
+ pPrev = pFnd->pPrev;
+ if( pPrev )
+ pPrev->pNext = this;
+ else
+ pArray->pFirst = this;
+ pFnd->pPrev = this;
+ }
+ }
+ else if( rIdx.nIndex < nNewValue )
+ {
+ SwIndex* pNxt;
+ while( 0 != ( pNxt = pFnd->pNext ) && pNxt->nIndex < nNewValue )
+ pFnd = pNxt;
+
+ if( pFnd != this )
+ {
+ // erstmal an alter Position ausketten
+ if( pPrev )
+ pPrev->pNext = pNext;
+ else if( pArray->pFirst == this )
+ pArray->pFirst = pNext;
+
+ if( pNext )
+ pNext->pPrev = pPrev;
+ else if( pArray->pLast == this )
+ pArray->pLast = pPrev;
+
+ pPrev = pFnd;
+ pNext = pFnd->pNext;
+ if( pNext )
+ pNext->pPrev = this;
+ else
+ pArray->pLast = this;
+ pFnd->pNext = this;
+ }
+ }
+ else if( pFnd != this )
+ {
+ // erstmal an alter Position ausketten
+ if( pPrev )
+ pPrev->pNext = pNext;
+ else if( pArray->pFirst == this )
+ pArray->pFirst = pNext;
+
+ if( pNext )
+ pNext->pPrev = pPrev;
+ else if( pArray->pLast == this )
+ pArray->pLast = pPrev;
+
+ pPrev = (SwIndex*)&rIdx;
+ pNext = rIdx.pNext;
+ pPrev->pNext = this;
+
+ if( !pNext ) // im IndexArray als letzes
+ pArray->pLast = this;
+ else
+ pNext->pPrev = this;
+ }
+ pArray = rIdx.pArray;
+
+ if( pArray->pFirst == pNext )
+ pArray->pFirst = this;
+ if( pArray->pLast == pPrev )
+ pArray->pLast = this;
+
+ nIndex = nNewValue;
+
+ return *this; }
+
+
+void SwIndex::Remove()
+{
+ if( !pPrev )
+ pArray->pFirst = pNext;
+ else
+ pPrev->pNext = pNext;
+
+ if( !pNext )
+ pArray->pLast = pPrev;
+ else
+ pNext->pPrev = pPrev;
+}
+
+/*************************************************************************
+|* SwIndex & SwIndex::operator=( const SwIndex & aSwIndex )
+*************************************************************************/
+
+
+SwIndex& SwIndex::operator=( const SwIndex& rIdx )
+{
+ int bEqual;
+ if( rIdx.pArray != pArray ) // im alten abmelden !!
+ {
+ Remove();
+ pArray = rIdx.pArray;
+ pNext = pPrev = 0;
+ bEqual = sal_False;
+ }
+ else
+ bEqual = rIdx.nIndex == nIndex;
+
+ if( !bEqual )
+ ChgValue( rIdx, rIdx.nIndex );
+ return *this;
+}
+
+/*************************************************************************
+|* SwIndex &SwIndex::Assign
+*************************************************************************/
+
+
+SwIndex& SwIndex::Assign( SwIndexReg* pArr, xub_StrLen nIdx )
+{
+ if( !pArr )
+ {
+ pArr = SwIndexReg::pEmptyIndexArray;
+ nIdx = 0; // steht immer auf 0 !!!
+ }
+
+ if( pArr != pArray ) // im alten abmelden !!
+ {
+ Remove();
+ pArray = pArr;
+ pNext = pPrev = 0;
+ if( !pArr->pFirst ) // 1. Index ??
+ {
+ pArr->pFirst = pArr->pLast = this;
+ nIndex = nIdx;
+ }
+ else if( pArr->pLast && (nIdx > ((pArr->pLast->nIndex - pArr->pFirst->nIndex) / 2)) )
+ ChgValue( *pArr->pLast, nIdx );
+ else
+ ChgValue( *pArr->pFirst, nIdx );
+ }
+ else if( nIndex != nIdx )
+ ChgValue( *this, nIdx );
+ return *this;
+}
+
+
+SwIndexReg::SwIndexReg()
+ : pFirst( 0 ), pLast( 0 )
+{
+}
+
+
+
+SwIndexReg::~SwIndexReg()
+{
+ OSL_ENSURE( !pFirst || !pLast, "Es sind noch Indizies angemeldet" );
+}
+
+
+
+void SwIndexReg::Update( SwIndex const & rIdx, const xub_StrLen nDiff,
+ const bool bNeg, const bool /* argument is only used in derived class*/ )
+{
+ SwIndex* pStt = const_cast<SwIndex*>(&rIdx);
+ xub_StrLen nNewVal = rIdx.nIndex;
+ if( bNeg )
+ {
+ xub_StrLen nLast = rIdx.GetIndex() + nDiff;
+ while( pStt && pStt->nIndex == nNewVal )
+ {
+ pStt->nIndex = nNewVal;
+ pStt = pStt->pPrev;
+ }
+ pStt = rIdx.pNext;
+ while( pStt && pStt->nIndex >= nNewVal &&
+ pStt->nIndex <= nLast )
+ {
+ pStt->nIndex = nNewVal;
+ pStt = pStt->pNext;
+ }
+ while( pStt )
+ {
+ pStt->nIndex = pStt->nIndex - nDiff;
+ pStt = pStt->pNext;
+ }
+ }
+ else
+ {
+ while( pStt && pStt->nIndex == nNewVal )
+ {
+ pStt->nIndex = pStt->nIndex + nDiff;
+ pStt = pStt->pPrev;
+ }
+ pStt = rIdx.pNext;
+ while( pStt )
+ {
+ pStt->nIndex = pStt->nIndex + nDiff;
+ pStt = pStt->pNext;
+ }
+ }
+}
+
+#if OSL_DEBUG_LEVEL > 1
+
+/*************************************************************************
+|* SwIndex::operator++()
+*************************************************************************/
+xub_StrLen SwIndex::operator++(int)
+{
+ OSL_ASSERT( nIndex < INVALID_INDEX );
+
+ xub_StrLen nOldIndex = nIndex;
+ ChgValue( *this, nIndex+1 );
+ return nOldIndex;
+}
+
+
+xub_StrLen SwIndex::operator++()
+{
+ OSL_ASSERT( nIndex < INVALID_INDEX );
+
+ ChgValue( *this, nIndex+1 );
+ return nIndex;
+}
+
+/*************************************************************************
+|* SwIndex::operator--()
+*************************************************************************/
+
+
+xub_StrLen SwIndex::operator--(int)
+{
+ OSL_ASSERT( nIndex );
+
+ xub_StrLen nOldIndex = nIndex;
+ ChgValue( *this, nIndex-1 );
+ return nOldIndex;
+}
+
+
+xub_StrLen SwIndex::operator--()
+{
+ OSL_ASSERT( nIndex );
+ return ChgValue( *this, nIndex-1 ).nIndex;
+}
+
+/*************************************************************************
+|* SwIndex::operator+=( xub_StrLen )
+*************************************************************************/
+
+xub_StrLen SwIndex::operator+=( xub_StrLen nWert )
+{
+ OSL_ASSERT( nIndex < INVALID_INDEX - nWert );
+ return ChgValue( *this, nIndex + nWert ).nIndex;
+}
+
+/*************************************************************************
+|* SwIndex::operator-=( xub_StrLen )
+*************************************************************************/
+
+xub_StrLen SwIndex::operator-=( xub_StrLen nWert )
+{
+ OSL_ASSERT( nIndex >= nWert );
+ return ChgValue( *this, nIndex - nWert ).nIndex;
+}
+
+/*************************************************************************
+|* SwIndex::operator+=( const SwIndex & )
+*************************************************************************/
+
+xub_StrLen SwIndex::operator+=( const SwIndex & rIndex )
+{
+ OSL_ASSERT( nIndex < INVALID_INDEX - rIndex.nIndex );
+ return ChgValue( *this, nIndex + rIndex.nIndex ).nIndex;
+}
+
+/*************************************************************************
+|* SwIndex::operator-=( const SwIndex & )
+*************************************************************************/
+
+xub_StrLen SwIndex::operator-=( const SwIndex & rIndex )
+{
+ OSL_ASSERT( nIndex >= rIndex.nIndex );
+ return ChgValue( *this, nIndex - rIndex.nIndex ).nIndex;
+}
+
+/*************************************************************************
+|* SwIndex::operator<( const SwIndex & )
+*************************************************************************/
+
+sal_Bool SwIndex::operator<( const SwIndex & rIndex ) const
+{
+ OSL_ENSURE( pArray == rIndex.pArray, "Attempt to compare indices into different arrays.");
+ return nIndex < rIndex.nIndex;
+}
+
+/*************************************************************************
+|* SwIndex::operator<=( const SwIndex & )
+*************************************************************************/
+
+sal_Bool SwIndex::operator<=( const SwIndex & rIndex ) const
+{
+ OSL_ENSURE( pArray == rIndex.pArray, "Attempt to compare indices into different arrays.");
+ return nIndex <= rIndex.nIndex;
+}
+
+/*************************************************************************
+|* SwIndex::operator>( const SwIndex & )
+*************************************************************************/
+
+sal_Bool SwIndex::operator>( const SwIndex & rIndex ) const
+{
+ OSL_ENSURE( pArray == rIndex.pArray, "Attempt to compare indices into different arrays.");
+ return nIndex > rIndex.nIndex;
+}
+
+/*************************************************************************
+|* SwIndex::operator>=( const SwIndex & )
+*************************************************************************/
+
+sal_Bool SwIndex::operator>=( const SwIndex & rIndex ) const
+{
+ OSL_ENSURE( pArray == rIndex.pArray, "Attempt to compare indices into different arrays.");
+ return nIndex >= rIndex.nIndex;
+}
+
+/*************************************************************************
+|* SwIndex & SwIndex::operator=( xub_StrLen )
+*************************************************************************/
+
+SwIndex& SwIndex::operator=( xub_StrLen nWert )
+{
+ // Werte kopieren und im neuen Array anmelden
+ if( nIndex != nWert )
+ ChgValue( *this, nWert );
+
+ return *this;
+}
+
+#endif // ifndef PRODUCT
+
+void SwIndexReg::MoveTo( SwIndexReg& rArr )
+{
+ if( this != &rArr && pFirst )
+ {
+ SwIndex* pIdx = (SwIndex*)pFirst, *pNext;
+ while( pIdx )
+ {
+ pNext = pIdx->pNext;
+ pIdx->Assign( &rArr, pIdx->GetIndex() );
+ pIdx = pNext;
+ }
+ pFirst = 0, pLast = 0;
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/bastyp/init.cxx b/sw/source/core/bastyp/init.cxx
new file mode 100644
index 000000000000..270385c63bbb
--- /dev/null
+++ b/sw/source/core/bastyp/init.cxx
@@ -0,0 +1,902 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+#include <hintids.hxx>
+#include <tools/globname.hxx>
+#include <vcl/mapmod.hxx>
+#include <editeng/xmlcnitm.hxx>
+#include <svl/macitem.hxx>
+#include <editeng/pbinitem.hxx>
+#include <editeng/keepitem.hxx>
+#include <editeng/nlbkitem.hxx>
+#include <editeng/hyznitem.hxx>
+#include <editeng/protitem.hxx>
+#include <editeng/ulspitem.hxx>
+#include <editeng/prszitem.hxx>
+#include <editeng/opaqitem.hxx>
+#include <editeng/shaditem.hxx>
+#include <editeng/prntitem.hxx>
+#include <editeng/brkitem.hxx>
+#include <editeng/tstpitem.hxx>
+#include <editeng/langitem.hxx>
+#include <editeng/wrlmitem.hxx>
+#include <editeng/kernitem.hxx>
+#include <editeng/escpitem.hxx>
+#include <editeng/cscoitem.hxx>
+#include <editeng/lrspitem.hxx>
+#include <editeng/orphitem.hxx>
+#include <editeng/widwitem.hxx>
+#include <editeng/nhypitem.hxx>
+#include <editeng/spltitem.hxx>
+#include <editeng/lspcitem.hxx>
+#include <editeng/blnkitem.hxx>
+#include <editeng/akrnitem.hxx>
+#include <editeng/emphitem.hxx>
+#include <editeng/twolinesitem.hxx>
+#include <editeng/scriptspaceitem.hxx>
+#include <editeng/hngpnctitem.hxx>
+#include <editeng/cmapitem.hxx>
+#include <editeng/charscaleitem.hxx>
+#include <editeng/charrotateitem.hxx>
+#include <editeng/charreliefitem.hxx>
+#include <editeng/frmdiritem.hxx>
+#include <svx/dialogs.hrc>
+#include <editeng/swafopt.hxx>
+#include <editeng/svxacorr.hxx>
+#include <unotools/charclass.hxx>
+#include <editeng/unolingu.hxx>
+#include <editeng/forbiddenruleitem.hxx>
+#include <editeng/paravertalignitem.hxx>
+#include <editeng/pgrditem.hxx>
+#include <editeng/charhiddenitem.hxx>
+#include <com/sun/star/lang/XMultiServiceFactory.hpp>
+#include <comphelper/processfactory.hxx>
+#include <unotools/collatorwrapper.hxx>
+#include <unotools/syslocale.hxx>
+#include <com/sun/star/i18n/CollatorOptions.hpp>
+#include <unotools/transliterationwrapper.hxx>
+#include <editeng/acorrcfg.hxx>
+#include <vcl/svapp.hxx>
+#include <fmtanchr.hxx>
+#include <fmtornt.hxx>
+#include <fmtsrnd.hxx>
+#include <fmtfsize.hxx>
+#include <fmtfld.hxx>
+#include <fmtrfmrk.hxx>
+#include <fmtlsplt.hxx>
+#include <fmtrowsplt.hxx>
+#include <fmteiro.hxx>
+#include <fmtclds.hxx>
+#include <fmturl.hxx>
+#include <fmtcntnt.hxx>
+#include <fmthdft.hxx>
+#include <fmtpdsc.hxx>
+#include <fmtftn.hxx>
+#include <fmtfordr.hxx>
+#include <fmtflcnt.hxx>
+#include <fchrfmt.hxx>
+#include <fmtinfmt.hxx>
+#include <fmtcnct.hxx>
+#include <fmtline.hxx>
+#include <fmtftntx.hxx>
+#include <fmtruby.hxx>
+#include <fmtautofmt.hxx>
+#include <tgrditem.hxx>
+#include <hfspacingitem.hxx>
+#include <editsh.hxx>
+#include <pam.hxx>
+#include <init.hxx>
+#include <paratr.hxx>
+#include <grfatr.hxx>
+#include <tox.hxx>
+#include <cellatr.hxx>
+#include <tblafmt.hxx>
+#include <viscrs.hxx>
+#include <fntcache.hxx>
+#include <doc.hxx>
+#include <acmplwrd.hxx>
+#include <fmtclbl.hxx>
+#include <cmdid.h>
+#include <breakit.hxx>
+#include <checkit.hxx>
+#include <swcalwrp.hxx>
+#include <SwStyleNameMapper.hxx>
+
+#include <fmtfollowtextflow.hxx>
+#include <fmtwrapinfluenceonobjpos.hxx>
+
+#include <fmtmeta.hxx>
+
+
+using namespace ::com::sun::star;
+
+extern void _FrmFinit();
+extern void ClearFEShellTabCols();
+
+/*************************************************************************
+|* einige Bereiche fuer die Set in Collections / Nodes
+|*************************************************************************/
+ // AttrSet-Range fuer die 2 Break-Attribute
+sal_uInt16 aBreakSetRange[] = {
+ RES_PAGEDESC, RES_BREAK,
+ 0 };
+
+ // AttrSet-Range fuer die TxtFmtColl
+ // list attributes ( RES_PARATR_LIST_BEGIN - RES_PARATR_LIST_END ) are not
+ // included in the paragraph style's itemset.
+sal_uInt16 aTxtFmtCollSetRange[] = {
+ RES_FRMATR_BEGIN, RES_FRMATR_END-1,
+ RES_CHRATR_BEGIN, RES_CHRATR_END-1,
+ RES_PARATR_BEGIN, RES_PARATR_END-1,
+ RES_UNKNOWNATR_BEGIN, RES_UNKNOWNATR_END-1,
+ 0
+};
+
+ // AttrSet-Range fuer die GrfFmtColl
+sal_uInt16 aGrfFmtCollSetRange[] = {
+ RES_FRMATR_BEGIN, RES_FRMATR_END-1,
+ RES_GRFATR_BEGIN, RES_GRFATR_END-1,
+ RES_UNKNOWNATR_BEGIN, RES_UNKNOWNATR_END-1,
+ 0
+};
+
+ // AttrSet-Range fuer die TextNode
+sal_uInt16 aTxtNodeSetRange[] = {
+ RES_FRMATR_BEGIN, RES_FRMATR_END-1,
+ RES_CHRATR_BEGIN, RES_CHRATR_END-1,
+ RES_PARATR_BEGIN, RES_PARATR_END-1,
+ RES_PARATR_LIST_BEGIN, RES_PARATR_LIST_END-1,
+ RES_UNKNOWNATR_BEGIN, RES_UNKNOWNATR_END-1,
+ 0
+};
+
+ // AttrSet-Range fuer die NoTxtNode
+sal_uInt16 aNoTxtNodeSetRange[] = {
+ RES_FRMATR_BEGIN, RES_FRMATR_END-1,
+ RES_GRFATR_BEGIN, RES_GRFATR_END-1,
+ RES_UNKNOWNATR_BEGIN, RES_UNKNOWNATR_END-1,
+ 0
+};
+
+sal_uInt16 aTableSetRange[] = {
+ RES_FILL_ORDER, RES_FRM_SIZE,
+ RES_LR_SPACE, RES_BREAK,
+ RES_BACKGROUND, RES_SHADOW,
+ RES_HORI_ORIENT, RES_HORI_ORIENT,
+ RES_KEEP, RES_KEEP,
+ RES_LAYOUT_SPLIT, RES_LAYOUT_SPLIT,
+ RES_FRAMEDIR, RES_FRAMEDIR,
+ // --> collapsing borders FME 2005-05-27 #i29550#
+ RES_COLLAPSING_BORDERS, RES_COLLAPSING_BORDERS,
+ // <-- collapsing
+ RES_UNKNOWNATR_BEGIN, RES_UNKNOWNATR_END-1,
+ 0
+};
+
+sal_uInt16 aTableLineSetRange[] = {
+ RES_FILL_ORDER, RES_FRM_SIZE,
+ RES_LR_SPACE, RES_UL_SPACE,
+ RES_BACKGROUND, RES_SHADOW,
+ RES_ROW_SPLIT, RES_ROW_SPLIT,
+ RES_PROTECT, RES_PROTECT,
+ RES_VERT_ORIENT, RES_VERT_ORIENT,
+ RES_UNKNOWNATR_BEGIN, RES_UNKNOWNATR_END-1,
+ 0
+};
+
+sal_uInt16 aTableBoxSetRange[] = {
+ RES_FILL_ORDER, RES_FRM_SIZE,
+ RES_LR_SPACE, RES_UL_SPACE,
+ RES_BACKGROUND, RES_SHADOW,
+ RES_PROTECT, RES_PROTECT,
+ RES_VERT_ORIENT, RES_VERT_ORIENT,
+ RES_FRAMEDIR, RES_FRAMEDIR,
+ RES_BOXATR_BEGIN, RES_BOXATR_END-1,
+ RES_UNKNOWNATR_BEGIN, RES_UNKNOWNATR_END-1,
+ 0
+};
+
+// AttrSet-Range fuer die SwFrmFmt
+sal_uInt16 aFrmFmtSetRange[] = {
+ RES_FRMATR_BEGIN, RES_FRMATR_END-1,
+ RES_UNKNOWNATR_BEGIN, RES_UNKNOWNATR_END-1,
+ 0
+};
+
+// AttrSet-Range fuer die SwCharFmt
+sal_uInt16 aCharFmtSetRange[] = {
+ RES_CHRATR_BEGIN, RES_CHRATR_END-1,
+ RES_UNKNOWNATR_BEGIN, RES_UNKNOWNATR_END-1,
+ 0
+};
+
+// AttrSet-Range fuer die character autostyles
+sal_uInt16 aCharAutoFmtSetRange[] = {
+ RES_CHRATR_BEGIN, RES_CHRATR_END-1,
+ RES_TXTATR_UNKNOWN_CONTAINER, RES_TXTATR_UNKNOWN_CONTAINER,
+ RES_UNKNOWNATR_BEGIN, RES_UNKNOWNATR_END-1,
+ 0
+};
+
+// AttrSet-Range fuer die SwPageDescFmt
+sal_uInt16 aPgFrmFmtSetRange[] = {
+ RES_FRMATR_BEGIN, RES_FRMATR_END-1,
+ RES_UNKNOWNATR_BEGIN, RES_UNKNOWNATR_END-1,
+ 0
+};
+
+/******************************************************************************
+ * lege eine Tabelle fuer einen Zugriff auf die
+ * Default-Format-Attribute an
+ ******************************************************************************/
+SwDfltAttrTab aAttrTab;
+
+SfxItemInfo aSlotTab[] =
+{
+ { SID_ATTR_CHAR_CASEMAP, SFX_ITEM_POOLABLE }, // RES_CHRATR_CASEMAP
+ { SID_ATTR_CHAR_CHARSETCOLOR, SFX_ITEM_POOLABLE }, // RES_CHRATR_CHARSETCOLOR
+ { SID_ATTR_CHAR_COLOR, SFX_ITEM_POOLABLE }, // RES_CHRATR_COLOR
+ { SID_ATTR_CHAR_CONTOUR, SFX_ITEM_POOLABLE }, // RES_CHRATR_CONTOUR
+ { SID_ATTR_CHAR_STRIKEOUT, SFX_ITEM_POOLABLE }, // RES_CHRATR_CROSSEDOUT
+ { SID_ATTR_CHAR_ESCAPEMENT, SFX_ITEM_POOLABLE }, // RES_CHRATR_ESCAPEMENT
+ { SID_ATTR_CHAR_FONT, SFX_ITEM_POOLABLE }, // RES_CHRATR_FONT
+ { SID_ATTR_CHAR_FONTHEIGHT, SFX_ITEM_POOLABLE }, // RES_CHRATR_FONTSIZE
+ { SID_ATTR_CHAR_KERNING, SFX_ITEM_POOLABLE }, // RES_CHRATR_KERNING
+ { SID_ATTR_CHAR_LANGUAGE, SFX_ITEM_POOLABLE }, // RES_CHRATR_LANGUAGE
+ { SID_ATTR_CHAR_POSTURE, SFX_ITEM_POOLABLE }, // RES_CHRATR_POSTURE
+ { SID_ATTR_CHAR_PROPSIZE, SFX_ITEM_POOLABLE }, // RES_CHRATR_PROPORTIONALFONTSIZE
+ { SID_ATTR_CHAR_SHADOWED, SFX_ITEM_POOLABLE }, // RES_CHRATR_SHADOWED
+ { SID_ATTR_CHAR_UNDERLINE, SFX_ITEM_POOLABLE }, // RES_CHRATR_UNDERLINE
+ { SID_ATTR_CHAR_WEIGHT, SFX_ITEM_POOLABLE }, // RES_CHRATR_WEIGHT
+ { SID_ATTR_CHAR_WORDLINEMODE, SFX_ITEM_POOLABLE }, // RES_CHRATR_WORDLINEMODE
+ { SID_ATTR_CHAR_AUTOKERN, SFX_ITEM_POOLABLE }, // RES_CHRATR_AUTOKERN
+ { SID_ATTR_FLASH, SFX_ITEM_POOLABLE }, // RES_CHRATR_BLINK
+ { 0, SFX_ITEM_POOLABLE }, // RES_CHRATR_NOLINEBREAK
+ { 0, SFX_ITEM_POOLABLE }, // RES_CHRATR_NOHYPHEN
+ { SID_ATTR_BRUSH_CHAR, SFX_ITEM_POOLABLE }, // RES_CHRATR_BACKGROUND
+ { SID_ATTR_CHAR_CJK_FONT, SFX_ITEM_POOLABLE }, // RES_CHRATR_CJK_FONT
+ { SID_ATTR_CHAR_CJK_FONTHEIGHT, SFX_ITEM_POOLABLE },// RES_CHRATR_CJK_FONTSIZE
+ { SID_ATTR_CHAR_CJK_LANGUAGE, SFX_ITEM_POOLABLE }, // RES_CHRATR_CJK_LANGUAGE
+ { SID_ATTR_CHAR_CJK_POSTURE, SFX_ITEM_POOLABLE }, // RES_CHRATR_CJK_POSTURE
+ { SID_ATTR_CHAR_CJK_WEIGHT, SFX_ITEM_POOLABLE }, // RES_CHRATR_CJK_WEIGHT
+ { SID_ATTR_CHAR_CTL_FONT, SFX_ITEM_POOLABLE }, // RES_CHRATR_CTL_FONT
+ { SID_ATTR_CHAR_CTL_FONTHEIGHT, SFX_ITEM_POOLABLE },// RES_CHRATR_CTL_FONTSIZE
+ { SID_ATTR_CHAR_CTL_LANGUAGE, SFX_ITEM_POOLABLE }, // RES_CHRATR_CTL_LANGUAGE
+ { SID_ATTR_CHAR_CTL_POSTURE, SFX_ITEM_POOLABLE }, // RES_CHRATR_CTL_POSTURE
+ { SID_ATTR_CHAR_CTL_WEIGHT, SFX_ITEM_POOLABLE }, // RES_CHRATR_CTL_WEIGHT
+ { SID_ATTR_CHAR_ROTATED, SFX_ITEM_POOLABLE }, // RES_CHRATR_ROTATE
+ { SID_ATTR_CHAR_EMPHASISMARK, SFX_ITEM_POOLABLE }, // RES_CHRATR_EMPHASIS_MARK
+ { SID_ATTR_CHAR_TWO_LINES, SFX_ITEM_POOLABLE }, // RES_CHRATR_TWO_LINES
+ { SID_ATTR_CHAR_SCALEWIDTH, SFX_ITEM_POOLABLE }, // RES_CHRATR_SCALEW
+ { SID_ATTR_CHAR_RELIEF, SFX_ITEM_POOLABLE }, // RES_CHRATR_RELIEF
+ { SID_ATTR_CHAR_HIDDEN, SFX_ITEM_POOLABLE }, // RES_CHRATR_HIDDEN
+ { SID_ATTR_CHAR_OVERLINE, SFX_ITEM_POOLABLE }, // RES_CHRATR_OVERLINE
+ { 0, SFX_ITEM_POOLABLE }, // RES_CHRATR_DUMMY1
+ { 0, SFX_ITEM_POOLABLE }, // RES_CHRATR_DUMMY2
+
+ { 0, 0 }, // RES_TXTATR_REFMARK
+ { 0, 0 }, // RES_TXTATR_TOXMARK
+ { 0, 0 }, // RES_TXTATR_META
+ { 0, 0 }, // RES_TXTATR_METAFIELD
+ { 0, SFX_ITEM_POOLABLE }, // RES_TXTATR_AUTOFMT
+ { FN_TXTATR_INET, 0 }, // RES_TXTATR_INETFMT
+ { 0, 0 }, // RES_TXTATR_CHARFMT
+ { SID_ATTR_CHAR_CJK_RUBY, 0 }, // RES_TXTATR_CJK_RUBY
+ { 0, SFX_ITEM_POOLABLE }, // RES_TXTATR_UNKNOWN_CONTAINER
+ { 0, SFX_ITEM_POOLABLE }, // RES_TXTATR_DUMMY5
+
+ { 0, 0 }, // RES_TXTATR_FIELD
+ { 0, 0 }, // RES_TXTATR_FLYCNT
+ { 0, 0 }, // RES_TXTATR_FTN
+ { 0, SFX_ITEM_POOLABLE }, // RES_TXTATR_DUMMY4
+ { 0, SFX_ITEM_POOLABLE }, // RES_TXTATR_DUMMY3
+ { 0, SFX_ITEM_POOLABLE }, // RES_TXTATR_DUMMY1
+ { 0, SFX_ITEM_POOLABLE }, // RES_TXTATR_DUMMY2
+
+ { SID_ATTR_PARA_LINESPACE, SFX_ITEM_POOLABLE }, // RES_PARATR_LINESPACING
+ { SID_ATTR_PARA_ADJUST, SFX_ITEM_POOLABLE }, // RES_PARATR_ADJUST
+ { SID_ATTR_PARA_SPLIT, SFX_ITEM_POOLABLE }, // RES_PARATR_SPLIT
+ { SID_ATTR_PARA_ORPHANS, SFX_ITEM_POOLABLE }, // RES_PARATR_ORPHANS
+ { SID_ATTR_PARA_WIDOWS, SFX_ITEM_POOLABLE }, // RES_PARATR_WIDOWS
+ { SID_ATTR_TABSTOP, SFX_ITEM_POOLABLE }, // RES_PARATR_TABSTOP
+ { SID_ATTR_PARA_HYPHENZONE, SFX_ITEM_POOLABLE }, // RES_PARATR_HYPHENZONE
+ { FN_FORMAT_DROPCAPS, 0 }, // RES_PARATR_DROP
+ { SID_ATTR_PARA_REGISTER, SFX_ITEM_POOLABLE }, // RES_PARATR_REGISTER
+ // RES_PARATR_NUMRULE is now poolable
+ { SID_ATTR_PARA_NUMRULE, SFX_ITEM_POOLABLE }, // RES_PARATR_NUMRULE
+ { SID_ATTR_PARA_SCRIPTSPACE, SFX_ITEM_POOLABLE }, // RES_PARATR_SCRIPTSPACE
+ { SID_ATTR_PARA_HANGPUNCTUATION, SFX_ITEM_POOLABLE },// RES_PARATR_HANGINGPUNCTUATION
+
+ { SID_ATTR_PARA_FORBIDDEN_RULES, SFX_ITEM_POOLABLE },// RES_PARATR_FORBIDDEN_RULES
+ { SID_PARA_VERTALIGN, SFX_ITEM_POOLABLE }, // RES_PARATR_VERTALIGN
+ { SID_ATTR_PARA_SNAPTOGRID, SFX_ITEM_POOLABLE }, // RES_PARATR_SNAPTOGRID
+ { SID_ATTR_BORDER_CONNECT, SFX_ITEM_POOLABLE }, // RES_PARATR_CONNECT_BORDER
+
+ { SID_ATTR_PARA_OUTLINE_LEVEL, SFX_ITEM_POOLABLE }, // RES_PARATR_OUTLINELEVEL //#outline level,zhaojianwei
+
+ { 0, SFX_ITEM_POOLABLE }, // RES_PARATR_LIST_ID
+ { 0, SFX_ITEM_POOLABLE }, // RES_PARATR_LIST_LEVEL
+ { 0, SFX_ITEM_POOLABLE }, // RES_PARATR_LIST_ISRESTART
+ { 0, SFX_ITEM_POOLABLE }, // RES_PARATR_LIST_RESTARTVALUE
+ { 0, SFX_ITEM_POOLABLE }, // RES_PARATR_LIST_ISCOUNTED
+
+ { 0, SFX_ITEM_POOLABLE }, // RES_FILL_ORDER
+ { 0, SFX_ITEM_POOLABLE }, // RES_FRM_SIZE
+ { SID_ATTR_PAGE_PAPERBIN, SFX_ITEM_POOLABLE }, // RES_PAPER_BIN
+ { SID_ATTR_LRSPACE, SFX_ITEM_POOLABLE }, // RES_LR_SPACE
+ { SID_ATTR_ULSPACE, SFX_ITEM_POOLABLE }, // RES_UL_SPACE
+ { 0, 0 }, // RES_PAGEDESC
+ { SID_ATTR_PARA_PAGEBREAK, SFX_ITEM_POOLABLE }, // RES_BREAK
+ { 0, 0 }, // RES_CNTNT
+ { 0, SFX_ITEM_POOLABLE }, // RES_HEADER
+ { 0, SFX_ITEM_POOLABLE }, // RES_FOOTER
+ { 0, SFX_ITEM_POOLABLE }, // RES_PRINT
+ { FN_OPAQUE, SFX_ITEM_POOLABLE }, // RES_OPAQUE
+ { FN_SET_PROTECT, SFX_ITEM_POOLABLE }, // RES_PROTECT
+ { FN_SURROUND, SFX_ITEM_POOLABLE }, // RES_SURROUND
+ { FN_VERT_ORIENT, SFX_ITEM_POOLABLE }, // RES_VERT_ORIENT
+ { FN_HORI_ORIENT, SFX_ITEM_POOLABLE }, // RES_HORI_ORIENT
+ { 0, 0 }, // RES_ANCHOR
+ { SID_ATTR_BRUSH, SFX_ITEM_POOLABLE }, // RES_BACKGROUND
+ { SID_ATTR_BORDER_OUTER, SFX_ITEM_POOLABLE }, // RES_BOX
+ { SID_ATTR_BORDER_SHADOW, SFX_ITEM_POOLABLE }, // RES_SHADOW
+ { SID_ATTR_MACROITEM, SFX_ITEM_POOLABLE }, // RES_FRMMACRO
+ { FN_ATTR_COLUMNS, SFX_ITEM_POOLABLE }, // RES_COL
+ { SID_ATTR_PARA_KEEP, SFX_ITEM_POOLABLE }, // RES_KEEP
+ { 0, SFX_ITEM_POOLABLE }, // RES_URL
+ { 0, SFX_ITEM_POOLABLE }, // RES_EDIT_IN_READONLY
+
+ { 0, SFX_ITEM_POOLABLE }, // RES_LAYOUT_SPLIT
+ { 0, 0 }, // RES_CHAIN
+ { 0, SFX_ITEM_POOLABLE }, // RES_TEXTGRID
+ { FN_FORMAT_LINENUMBER, SFX_ITEM_POOLABLE }, // RES_LINENUMBER
+ { 0, SFX_ITEM_POOLABLE }, // RES_FTN_AT_TXTEND
+ { 0, SFX_ITEM_POOLABLE }, // RES_END_AT_TXTEND
+ { 0, SFX_ITEM_POOLABLE }, // RES_COLUMNBALANCE
+
+ { SID_ATTR_FRAMEDIRECTION, SFX_ITEM_POOLABLE }, // RES_FRAMEDIR
+
+ { SID_ATTR_HDFT_DYNAMIC_SPACING, SFX_ITEM_POOLABLE }, // RES_HEADER_FOOTER_EAT_SPACING
+ { FN_TABLE_ROW_SPLIT, SFX_ITEM_POOLABLE }, // RES_ROW_SPLIT
+ // #i18732# - use slot-id define in svx
+ { SID_SW_FOLLOW_TEXT_FLOW, SFX_ITEM_POOLABLE }, // RES_FOLLOW_TEXT_FLOW
+ // collapsing borders #i29550#
+ { SID_SW_COLLAPSING_BORDERS, SFX_ITEM_POOLABLE }, // RES_COLLAPSING_BORDERS
+ // #i28701#
+ { SID_SW_WRAP_INFLUENCE_ON_OBJPOS, SFX_ITEM_POOLABLE }, // RES_WRAP_INFLUENCE_ON_OBJPOS
+ { 0, 0 }, // RES_AUTO_STYLE
+ { 0, SFX_ITEM_POOLABLE }, // RES_FRMATR_STYLE_NAME
+ { 0, SFX_ITEM_POOLABLE }, // RES_FRMATR_CONDITIONAL_STYLE_NAME
+
+ { 0, SFX_ITEM_POOLABLE }, // RES_GRFATR_MIRRORGRF
+ { SID_ATTR_GRAF_CROP, SFX_ITEM_POOLABLE }, // RES_GRFATR_CROPGRF
+ { 0, SFX_ITEM_POOLABLE }, // RES_GRFATR_ROTATION,
+ { 0, SFX_ITEM_POOLABLE }, // RES_GRFATR_LUMINANCE,
+ { 0, SFX_ITEM_POOLABLE }, // RES_GRFATR_CONTRAST,
+ { 0, SFX_ITEM_POOLABLE }, // RES_GRFATR_CHANNELR,
+ { 0, SFX_ITEM_POOLABLE }, // RES_GRFATR_CHANNELG,
+ { 0, SFX_ITEM_POOLABLE }, // RES_GRFATR_CHANNELB,
+ { 0, SFX_ITEM_POOLABLE }, // RES_GRFATR_GAMMA,
+ { 0, SFX_ITEM_POOLABLE }, // RES_GRFATR_INVERT,
+ { 0, SFX_ITEM_POOLABLE }, // RES_GRFATR_TRANSPARENCY,
+ { 0, SFX_ITEM_POOLABLE }, // RES_GRFATR_DUMMY1,
+ { 0, SFX_ITEM_POOLABLE }, // RES_GRFATR_DUMMY2,
+ { 0, SFX_ITEM_POOLABLE }, // RES_GRFATR_DUMMY3,
+ { 0, SFX_ITEM_POOLABLE }, // RES_GRFATR_DUMMY4,
+ { 0, SFX_ITEM_POOLABLE }, // RES_GRFATR_DUMMY5,
+ { 0, SFX_ITEM_POOLABLE }, // RES_GRFATR_DUMMY6,
+
+ { 0, SFX_ITEM_POOLABLE }, // RES_BOXATR_FORMAT
+ { 0, 0 }, // RES_BOXATR_FORMULA,
+ { 0, SFX_ITEM_POOLABLE }, // RES_BOXATR_VALUE
+
+ { 0, SFX_ITEM_POOLABLE } // RES_UNKNOWNATR_CONTAINER
+};
+
+
+sal_uInt16* SwAttrPool::pVersionMap1 = 0;
+sal_uInt16* SwAttrPool::pVersionMap2 = 0;
+sal_uInt16* SwAttrPool::pVersionMap3 = 0;
+sal_uInt16* SwAttrPool::pVersionMap4 = 0;
+// #i18732#
+sal_uInt16* SwAttrPool::pVersionMap5 = 0;
+sal_uInt16* SwAttrPool::pVersionMap6 = 0;
+SwIndexReg* SwIndexReg::pEmptyIndexArray = 0;
+
+const sal_Char* pMarkToTable = "table";
+const sal_Char* pMarkToFrame = "frame";
+const sal_Char* pMarkToRegion = "region";
+const sal_Char* pMarkToText = "text";
+const sal_Char* pMarkToOutline = "outline";
+const sal_Char* pMarkToGraphic = "graphic";
+const sal_Char* pMarkToOLE = "ole";
+
+SvPtrarr *pGlobalOLEExcludeList = 0;
+
+SwAutoCompleteWord* SwDoc::pACmpltWords = 0;
+
+SwCheckIt* pCheckIt = 0;
+CharClass* pAppCharClass = 0;
+
+CollatorWrapper* pCollator = 0, *pCaseCollator = 0;
+::utl::TransliterationWrapper* pTransWrp = 0;
+
+/******************************************************************************
+ * void _InitCore()
+ ******************************************************************************/
+salhelper::SingletonRef<SwCalendarWrapper>* s_getCalendarWrapper()
+{
+ static salhelper::SingletonRef<SwCalendarWrapper> aCalendarWrapper;
+ return &aCalendarWrapper;
+}
+void _InitCore()
+{
+ SfxPoolItem* pItem;
+
+ // erstmal alle Attribut-Pointer auf 0 setzen
+ memset( aAttrTab, 0, (POOLATTR_END - POOLATTR_BEGIN) *
+ sizeof( SfxPoolItem* ) );
+
+ aAttrTab[ RES_CHRATR_CASEMAP- POOLATTR_BEGIN ] = new SvxCaseMapItem( SVX_CASEMAP_NOT_MAPPED, RES_CHRATR_CASEMAP);
+ aAttrTab[ RES_CHRATR_CHARSETCOLOR- POOLATTR_BEGIN ] = new SvxCharSetColorItem(RES_CHRATR_CHARSETCOLOR);
+ aAttrTab[ RES_CHRATR_COLOR- POOLATTR_BEGIN ] = new SvxColorItem(RES_CHRATR_COLOR);
+ aAttrTab[ RES_CHRATR_CONTOUR- POOLATTR_BEGIN ] = new SvxContourItem( sal_False, RES_CHRATR_CONTOUR );
+ aAttrTab[ RES_CHRATR_CROSSEDOUT- POOLATTR_BEGIN ] = new SvxCrossedOutItem( STRIKEOUT_NONE, RES_CHRATR_CROSSEDOUT );
+ aAttrTab[ RES_CHRATR_ESCAPEMENT- POOLATTR_BEGIN ] = new SvxEscapementItem( RES_CHRATR_ESCAPEMENT );
+ aAttrTab[ RES_CHRATR_FONT- POOLATTR_BEGIN ] = new SvxFontItem( RES_CHRATR_FONT );
+
+ aAttrTab[ RES_CHRATR_FONTSIZE- POOLATTR_BEGIN ] = new SvxFontHeightItem( 240, 100, RES_CHRATR_FONTSIZE );
+ aAttrTab[ RES_CHRATR_KERNING- POOLATTR_BEGIN ] = new SvxKerningItem( 0, RES_CHRATR_KERNING );
+ aAttrTab[ RES_CHRATR_LANGUAGE- POOLATTR_BEGIN ] = new SvxLanguageItem(LANGUAGE_DONTKNOW, RES_CHRATR_LANGUAGE );
+ aAttrTab[ RES_CHRATR_POSTURE- POOLATTR_BEGIN ] = new SvxPostureItem( ITALIC_NONE, RES_CHRATR_POSTURE );
+ aAttrTab[ RES_CHRATR_PROPORTIONALFONTSIZE- POOLATTR_BEGIN ] = new SvxPropSizeItem( 100, RES_CHRATR_PROPORTIONALFONTSIZE );
+ aAttrTab[ RES_CHRATR_SHADOWED- POOLATTR_BEGIN ] = new SvxShadowedItem( sal_False, RES_CHRATR_SHADOWED );
+ aAttrTab[ RES_CHRATR_UNDERLINE- POOLATTR_BEGIN ] = new SvxUnderlineItem( UNDERLINE_NONE, RES_CHRATR_UNDERLINE );
+ aAttrTab[ RES_CHRATR_WEIGHT- POOLATTR_BEGIN ] = new SvxWeightItem( WEIGHT_NORMAL, RES_CHRATR_WEIGHT );
+ aAttrTab[ RES_CHRATR_WORDLINEMODE- POOLATTR_BEGIN ] = new SvxWordLineModeItem( sal_False, RES_CHRATR_WORDLINEMODE );
+ aAttrTab[ RES_CHRATR_AUTOKERN- POOLATTR_BEGIN ] = new SvxAutoKernItem( sal_False, RES_CHRATR_AUTOKERN );
+ aAttrTab[ RES_CHRATR_BLINK - POOLATTR_BEGIN ] = new SvxBlinkItem( sal_False, RES_CHRATR_BLINK );
+ aAttrTab[ RES_CHRATR_NOHYPHEN - POOLATTR_BEGIN ] = new SvxNoHyphenItem( sal_True, RES_CHRATR_NOHYPHEN );
+ aAttrTab[ RES_CHRATR_NOLINEBREAK- POOLATTR_BEGIN ] = new SvxNoLinebreakItem( sal_True, RES_CHRATR_NOLINEBREAK );
+ aAttrTab[ RES_CHRATR_BACKGROUND - POOLATTR_BEGIN ] = new SvxBrushItem( RES_CHRATR_BACKGROUND );
+
+ // CJK-Attributes
+ aAttrTab[ RES_CHRATR_CJK_FONT - POOLATTR_BEGIN ] = new SvxFontItem( RES_CHRATR_CJK_FONT );
+ aAttrTab[ RES_CHRATR_CJK_FONTSIZE - POOLATTR_BEGIN ] = new SvxFontHeightItem( 240, 100, RES_CHRATR_CJK_FONTSIZE );
+ aAttrTab[ RES_CHRATR_CJK_LANGUAGE - POOLATTR_BEGIN ] = new SvxLanguageItem(LANGUAGE_DONTKNOW, RES_CHRATR_CJK_LANGUAGE);
+ aAttrTab[ RES_CHRATR_CJK_POSTURE - POOLATTR_BEGIN ] = new SvxPostureItem(ITALIC_NONE, RES_CHRATR_CJK_POSTURE );
+ aAttrTab[ RES_CHRATR_CJK_WEIGHT - POOLATTR_BEGIN ] = new SvxWeightItem( WEIGHT_NORMAL, RES_CHRATR_CJK_WEIGHT );
+
+ // CTL-Attributes
+ aAttrTab[ RES_CHRATR_CTL_FONT - POOLATTR_BEGIN ] = new SvxFontItem( RES_CHRATR_CTL_FONT );
+ aAttrTab[ RES_CHRATR_CTL_FONTSIZE - POOLATTR_BEGIN ] = new SvxFontHeightItem( 240, 100, RES_CHRATR_CTL_FONTSIZE );
+ aAttrTab[ RES_CHRATR_CTL_LANGUAGE - POOLATTR_BEGIN ] = new SvxLanguageItem(LANGUAGE_DONTKNOW, RES_CHRATR_CTL_LANGUAGE);
+ aAttrTab[ RES_CHRATR_CTL_POSTURE - POOLATTR_BEGIN ] = new SvxPostureItem(ITALIC_NONE, RES_CHRATR_CTL_POSTURE );
+ aAttrTab[ RES_CHRATR_CTL_WEIGHT - POOLATTR_BEGIN ] = new SvxWeightItem( WEIGHT_NORMAL, RES_CHRATR_CTL_WEIGHT );
+
+ aAttrTab[ RES_CHRATR_ROTATE - POOLATTR_BEGIN ] = new SvxCharRotateItem( 0, sal_False, RES_CHRATR_ROTATE );
+ aAttrTab[ RES_CHRATR_EMPHASIS_MARK - POOLATTR_BEGIN ] = new SvxEmphasisMarkItem( EMPHASISMARK_NONE, RES_CHRATR_EMPHASIS_MARK );
+ aAttrTab[ RES_CHRATR_TWO_LINES - POOLATTR_BEGIN ] = new SvxTwoLinesItem( sal_False, 0, 0, RES_CHRATR_TWO_LINES );
+ aAttrTab[ RES_CHRATR_SCALEW - POOLATTR_BEGIN ] = new SvxCharScaleWidthItem( 100, RES_CHRATR_SCALEW );
+ aAttrTab[ RES_CHRATR_RELIEF - POOLATTR_BEGIN ] = new SvxCharReliefItem( RELIEF_NONE, RES_CHRATR_RELIEF );
+ aAttrTab[ RES_CHRATR_HIDDEN - POOLATTR_BEGIN ] = new SvxCharHiddenItem( sal_False, RES_CHRATR_HIDDEN );
+ aAttrTab[ RES_CHRATR_OVERLINE- POOLATTR_BEGIN ] = new SvxOverlineItem( UNDERLINE_NONE, RES_CHRATR_OVERLINE );
+
+// CharakterAttr - Dummies
+ aAttrTab[ RES_CHRATR_DUMMY1 - POOLATTR_BEGIN ] = new SfxBoolItem( RES_CHRATR_DUMMY1 );
+ aAttrTab[ RES_CHRATR_DUMMY2 - POOLATTR_BEGIN ] = new SfxBoolItem( RES_CHRATR_DUMMY2 );
+// CharakterAttr - Dummies
+
+ aAttrTab[ RES_TXTATR_AUTOFMT- POOLATTR_BEGIN ] = new SwFmtAutoFmt;
+ aAttrTab[ RES_TXTATR_INETFMT - POOLATTR_BEGIN ] = new SwFmtINetFmt( aEmptyStr, aEmptyStr );
+ aAttrTab[ RES_TXTATR_REFMARK - POOLATTR_BEGIN ] = new SwFmtRefMark( aEmptyStr );
+ aAttrTab[ RES_TXTATR_TOXMARK - POOLATTR_BEGIN ] = new SwTOXMark;
+ aAttrTab[ RES_TXTATR_CHARFMT- POOLATTR_BEGIN ] = new SwFmtCharFmt( 0 );
+ aAttrTab[ RES_TXTATR_CJK_RUBY - POOLATTR_BEGIN ] = new SwFmtRuby( aEmptyStr );
+ aAttrTab[ RES_TXTATR_UNKNOWN_CONTAINER - POOLATTR_BEGIN ] = new SvXMLAttrContainerItem( RES_TXTATR_UNKNOWN_CONTAINER );
+ aAttrTab[ RES_TXTATR_META - POOLATTR_BEGIN ] = SwFmtMeta::CreatePoolDefault(RES_TXTATR_META);
+ aAttrTab[ RES_TXTATR_METAFIELD - POOLATTR_BEGIN ] = SwFmtMeta::CreatePoolDefault(RES_TXTATR_METAFIELD);
+
+ aAttrTab[ RES_TXTATR_FIELD- POOLATTR_BEGIN ] = new SwFmtFld;
+ aAttrTab[ RES_TXTATR_FLYCNT - POOLATTR_BEGIN ] = new SwFmtFlyCnt( 0 );
+ aAttrTab[ RES_TXTATR_FTN - POOLATTR_BEGIN ] = new SwFmtFtn;
+
+// TextAttr - Dummies
+ aAttrTab[ RES_TXTATR_DUMMY4 - POOLATTR_BEGIN ] = new SfxBoolItem( RES_TXTATR_DUMMY4 );
+ aAttrTab[ RES_TXTATR_DUMMY3 - POOLATTR_BEGIN ] = new SfxBoolItem( RES_TXTATR_DUMMY3 );
+ aAttrTab[ RES_TXTATR_DUMMY1 - POOLATTR_BEGIN ] = new SfxBoolItem( RES_TXTATR_DUMMY1 );
+ aAttrTab[ RES_TXTATR_DUMMY2 - POOLATTR_BEGIN ] = new SfxBoolItem( RES_TXTATR_DUMMY2 );
+ aAttrTab[ RES_TXTATR_DUMMY5 - POOLATTR_BEGIN ] = new SfxBoolItem( RES_TXTATR_DUMMY5 );
+// TextAttr - Dummies
+
+ aAttrTab[ RES_PARATR_LINESPACING- POOLATTR_BEGIN ] = new SvxLineSpacingItem( LINE_SPACE_DEFAULT_HEIGHT, RES_PARATR_LINESPACING );
+ aAttrTab[ RES_PARATR_ADJUST- POOLATTR_BEGIN ] = new SvxAdjustItem( SVX_ADJUST_LEFT, RES_PARATR_ADJUST );
+ aAttrTab[ RES_PARATR_SPLIT- POOLATTR_BEGIN ] = new SvxFmtSplitItem( sal_True, RES_PARATR_SPLIT );
+ aAttrTab[ RES_PARATR_WIDOWS- POOLATTR_BEGIN ] = new SvxWidowsItem( 0, RES_PARATR_WIDOWS );
+ aAttrTab[ RES_PARATR_ORPHANS- POOLATTR_BEGIN ] = new SvxOrphansItem( 0, RES_PARATR_ORPHANS );
+ aAttrTab[ RES_PARATR_TABSTOP- POOLATTR_BEGIN ] = new SvxTabStopItem( 1, SVX_TAB_DEFDIST, SVX_TAB_ADJUST_DEFAULT, RES_PARATR_TABSTOP );
+
+ pItem = new SvxHyphenZoneItem( sal_False, RES_PARATR_HYPHENZONE );
+ ((SvxHyphenZoneItem*)pItem)->GetMaxHyphens() = 0; // Default z.Z. auf 0
+ aAttrTab[ RES_PARATR_HYPHENZONE- POOLATTR_BEGIN ] = pItem;
+
+ aAttrTab[ RES_PARATR_DROP- POOLATTR_BEGIN ] = new SwFmtDrop;
+ aAttrTab[ RES_PARATR_REGISTER - POOLATTR_BEGIN ] = new SwRegisterItem( sal_False );
+ aAttrTab[ RES_PARATR_NUMRULE - POOLATTR_BEGIN ] = new SwNumRuleItem( aEmptyStr );
+
+ aAttrTab[ RES_PARATR_SCRIPTSPACE - POOLATTR_BEGIN ] = new SvxScriptSpaceItem( sal_True, RES_PARATR_SCRIPTSPACE );
+ aAttrTab[ RES_PARATR_HANGINGPUNCTUATION - POOLATTR_BEGIN ] = new SvxHangingPunctuationItem( sal_True, RES_PARATR_HANGINGPUNCTUATION );
+ aAttrTab[ RES_PARATR_FORBIDDEN_RULES - POOLATTR_BEGIN ] = new SvxForbiddenRuleItem( sal_True, RES_PARATR_FORBIDDEN_RULES );
+ aAttrTab[ RES_PARATR_VERTALIGN - POOLATTR_BEGIN ] = new SvxParaVertAlignItem( 0, RES_PARATR_VERTALIGN );
+ aAttrTab[ RES_PARATR_SNAPTOGRID - POOLATTR_BEGIN ] = new SvxParaGridItem( sal_True, RES_PARATR_SNAPTOGRID );
+ aAttrTab[ RES_PARATR_CONNECT_BORDER - POOLATTR_BEGIN ] = new SwParaConnectBorderItem;
+
+ aAttrTab[ RES_PARATR_OUTLINELEVEL - POOLATTR_BEGIN ] = new SfxUInt16Item( RES_PARATR_OUTLINELEVEL, 0 );//#outline level,zhaojianwei
+
+ aAttrTab[ RES_PARATR_LIST_ID - POOLATTR_BEGIN ] = new SfxStringItem( RES_PARATR_LIST_ID, aEmptyStr );
+ aAttrTab[ RES_PARATR_LIST_LEVEL - POOLATTR_BEGIN ] = new SfxInt16Item( RES_PARATR_LIST_LEVEL, 0 );
+ aAttrTab[ RES_PARATR_LIST_ISRESTART - POOLATTR_BEGIN ] = new SfxBoolItem( RES_PARATR_LIST_ISRESTART, sal_False );
+ aAttrTab[ RES_PARATR_LIST_RESTARTVALUE - POOLATTR_BEGIN ] = new SfxInt16Item( RES_PARATR_LIST_RESTARTVALUE, 1 );
+ aAttrTab[ RES_PARATR_LIST_ISCOUNTED - POOLATTR_BEGIN ] = new SfxBoolItem( RES_PARATR_LIST_ISCOUNTED, sal_True );
+
+ aAttrTab[ RES_FILL_ORDER- POOLATTR_BEGIN ] = new SwFmtFillOrder;
+ aAttrTab[ RES_FRM_SIZE- POOLATTR_BEGIN ] = new SwFmtFrmSize;
+ aAttrTab[ RES_PAPER_BIN- POOLATTR_BEGIN ] = new SvxPaperBinItem( RES_PAPER_BIN );
+ aAttrTab[ RES_LR_SPACE- POOLATTR_BEGIN ] = new SvxLRSpaceItem( RES_LR_SPACE );
+ aAttrTab[ RES_UL_SPACE- POOLATTR_BEGIN ] = new SvxULSpaceItem( RES_UL_SPACE );
+ aAttrTab[ RES_PAGEDESC- POOLATTR_BEGIN ] = new SwFmtPageDesc;
+ aAttrTab[ RES_BREAK- POOLATTR_BEGIN ] = new SvxFmtBreakItem( SVX_BREAK_NONE, RES_BREAK);
+ aAttrTab[ RES_CNTNT- POOLATTR_BEGIN ] = new SwFmtCntnt;
+ aAttrTab[ RES_HEADER- POOLATTR_BEGIN ] = new SwFmtHeader;
+ aAttrTab[ RES_FOOTER- POOLATTR_BEGIN ] = new SwFmtFooter;
+ aAttrTab[ RES_PRINT- POOLATTR_BEGIN ] = new SvxPrintItem( RES_PRINT );
+ aAttrTab[ RES_OPAQUE- POOLATTR_BEGIN ] = new SvxOpaqueItem( RES_OPAQUE );
+ aAttrTab[ RES_PROTECT- POOLATTR_BEGIN ] = new SvxProtectItem( RES_PROTECT );
+ aAttrTab[ RES_SURROUND- POOLATTR_BEGIN ] = new SwFmtSurround;
+ aAttrTab[ RES_VERT_ORIENT- POOLATTR_BEGIN ] = new SwFmtVertOrient;
+ aAttrTab[ RES_HORI_ORIENT- POOLATTR_BEGIN ] = new SwFmtHoriOrient;
+ aAttrTab[ RES_ANCHOR- POOLATTR_BEGIN ] = new SwFmtAnchor;
+ aAttrTab[ RES_BACKGROUND- POOLATTR_BEGIN ] = new SvxBrushItem( RES_BACKGROUND );
+ aAttrTab[ RES_BOX- POOLATTR_BEGIN ] = new SvxBoxItem( RES_BOX );
+ aAttrTab[ RES_SHADOW- POOLATTR_BEGIN ] = new SvxShadowItem( RES_SHADOW );
+ aAttrTab[ RES_FRMMACRO- POOLATTR_BEGIN ] = new SvxMacroItem( RES_FRMMACRO );
+ aAttrTab[ RES_COL- POOLATTR_BEGIN ] = new SwFmtCol;
+ aAttrTab[ RES_KEEP - POOLATTR_BEGIN ] = new SvxFmtKeepItem( sal_False, RES_KEEP );
+ aAttrTab[ RES_URL - POOLATTR_BEGIN ] = new SwFmtURL();
+ aAttrTab[ RES_EDIT_IN_READONLY - POOLATTR_BEGIN ] = new SwFmtEditInReadonly;
+ aAttrTab[ RES_LAYOUT_SPLIT - POOLATTR_BEGIN ] = new SwFmtLayoutSplit;
+ aAttrTab[ RES_CHAIN - POOLATTR_BEGIN ] = new SwFmtChain;
+ aAttrTab[ RES_TEXTGRID - POOLATTR_BEGIN ] = new SwTextGridItem;
+ aAttrTab[ RES_HEADER_FOOTER_EAT_SPACING - POOLATTR_BEGIN ] = new SwHeaderAndFooterEatSpacingItem;
+ aAttrTab[ RES_LINENUMBER - POOLATTR_BEGIN ] = new SwFmtLineNumber;
+ aAttrTab[ RES_FTN_AT_TXTEND - POOLATTR_BEGIN ] = new SwFmtFtnAtTxtEnd;
+ aAttrTab[ RES_END_AT_TXTEND - POOLATTR_BEGIN ] = new SwFmtEndAtTxtEnd;
+ aAttrTab[ RES_COLUMNBALANCE - POOLATTR_BEGIN ] = new SwFmtNoBalancedColumns;
+ aAttrTab[ RES_FRAMEDIR - POOLATTR_BEGIN ] = new SvxFrameDirectionItem( FRMDIR_ENVIRONMENT, RES_FRAMEDIR );
+ aAttrTab[ RES_ROW_SPLIT - POOLATTR_BEGIN ] = new SwFmtRowSplit;
+
+ // #i18732#
+ aAttrTab[ RES_FOLLOW_TEXT_FLOW - POOLATTR_BEGIN ] = new SwFmtFollowTextFlow( sal_True );
+ // collapsing borders #i29550#
+ aAttrTab[ RES_COLLAPSING_BORDERS - POOLATTR_BEGIN ] = new SfxBoolItem( RES_COLLAPSING_BORDERS, sal_False );
+ // #i28701#
+ // #i35017# - constant name has changed
+ aAttrTab[ RES_WRAP_INFLUENCE_ON_OBJPOS - POOLATTR_BEGIN ] =
+ new SwFmtWrapInfluenceOnObjPos( text::WrapInfluenceOnPosition::ONCE_CONCURRENT );
+ // <--
+// FrmAttr-Dummies
+ aAttrTab[ RES_AUTO_STYLE - POOLATTR_BEGIN ] = new SwFmtAutoFmt( RES_AUTO_STYLE );
+ aAttrTab[ RES_FRMATR_STYLE_NAME - POOLATTR_BEGIN ] = new SfxStringItem( RES_FRMATR_STYLE_NAME, aEmptyStr );
+ aAttrTab[ RES_FRMATR_CONDITIONAL_STYLE_NAME - POOLATTR_BEGIN ] = new SfxStringItem( RES_FRMATR_CONDITIONAL_STYLE_NAME, aEmptyStr );
+// FrmAttr-Dummies
+
+ aAttrTab[ RES_GRFATR_MIRRORGRF- POOLATTR_BEGIN ] = new SwMirrorGrf;
+ aAttrTab[ RES_GRFATR_CROPGRF- POOLATTR_BEGIN ] = new SwCropGrf;
+ aAttrTab[ RES_GRFATR_ROTATION - POOLATTR_BEGIN ] = new SwRotationGrf;
+ aAttrTab[ RES_GRFATR_LUMINANCE - POOLATTR_BEGIN ] = new SwLuminanceGrf;
+ aAttrTab[ RES_GRFATR_CONTRAST - POOLATTR_BEGIN ] = new SwContrastGrf;
+ aAttrTab[ RES_GRFATR_CHANNELR - POOLATTR_BEGIN ] = new SwChannelRGrf;
+ aAttrTab[ RES_GRFATR_CHANNELG - POOLATTR_BEGIN ] = new SwChannelGGrf;
+ aAttrTab[ RES_GRFATR_CHANNELB - POOLATTR_BEGIN ] = new SwChannelBGrf;
+ aAttrTab[ RES_GRFATR_GAMMA - POOLATTR_BEGIN ] = new SwGammaGrf;
+ aAttrTab[ RES_GRFATR_INVERT - POOLATTR_BEGIN ] = new SwInvertGrf;
+ aAttrTab[ RES_GRFATR_TRANSPARENCY - POOLATTR_BEGIN ] = new SwTransparencyGrf;
+ aAttrTab[ RES_GRFATR_DRAWMODE - POOLATTR_BEGIN ] = new SwDrawModeGrf;
+
+// GraphicAttr - Dummies
+ aAttrTab[ RES_GRFATR_DUMMY1 - POOLATTR_BEGIN ] = new SfxBoolItem( RES_GRFATR_DUMMY1 );
+ aAttrTab[ RES_GRFATR_DUMMY2 - POOLATTR_BEGIN ] = new SfxBoolItem( RES_GRFATR_DUMMY2 );
+ aAttrTab[ RES_GRFATR_DUMMY3 - POOLATTR_BEGIN ] = new SfxBoolItem( RES_GRFATR_DUMMY3 );
+ aAttrTab[ RES_GRFATR_DUMMY4 - POOLATTR_BEGIN ] = new SfxBoolItem( RES_GRFATR_DUMMY4 );
+ aAttrTab[ RES_GRFATR_DUMMY5 - POOLATTR_BEGIN ] = new SfxBoolItem( RES_GRFATR_DUMMY5 );
+// GraphicAttr - Dummies
+
+ aAttrTab[ RES_BOXATR_FORMAT- POOLATTR_BEGIN ] = new SwTblBoxNumFormat;
+ aAttrTab[ RES_BOXATR_FORMULA- POOLATTR_BEGIN ] = new SwTblBoxFormula( aEmptyStr );
+ aAttrTab[ RES_BOXATR_VALUE- POOLATTR_BEGIN ] = new SwTblBoxValue;
+
+ aAttrTab[ RES_UNKNOWNATR_CONTAINER- POOLATTR_BEGIN ] =
+ new SvXMLAttrContainerItem( RES_UNKNOWNATR_CONTAINER );
+
+ // get the correct fonts:
+ ::GetDefaultFonts( *(SvxFontItem*)aAttrTab[ RES_CHRATR_FONT- POOLATTR_BEGIN ],
+ *(SvxFontItem*)aAttrTab[ RES_CHRATR_CJK_FONT - POOLATTR_BEGIN ],
+ *(SvxFontItem*)aAttrTab[ RES_CHRATR_CTL_FONT - POOLATTR_BEGIN ] );
+
+ // 1. Version - neue Attribute:
+ // - RES_CHRATR_BLINK
+ // - RES_CHRATR_NOHYPHEN
+ // - RES_CHRATR_NOLINEBREAK
+ // - RES_PARATR_REGISTER
+ // + 2 Dummies fuer die einzelnen "Bereiche"
+ SwAttrPool::pVersionMap1 = new sal_uInt16[ 60 ];
+ sal_uInt16 i;
+ for( i = 1; i <= 17; i++ )
+ SwAttrPool::pVersionMap1[ i-1 ] = i;
+ for ( i = 18; i <= 27; ++i )
+ SwAttrPool::pVersionMap1[ i-1 ] = i + 5;
+ for ( i = 28; i <= 35; ++i )
+ SwAttrPool::pVersionMap1[ i-1 ] = i + 7;
+ for ( i = 36; i <= 58; ++i )
+ SwAttrPool::pVersionMap1[ i-1 ] = i + 10;
+ for ( i = 59; i <= 60; ++i )
+ SwAttrPool::pVersionMap1[ i-1 ] = i + 12;
+
+ // 2. Version - neue Attribute:
+ // 10 Dummies fuer den Frame "Bereich"
+ SwAttrPool::pVersionMap2 = new sal_uInt16[ 75 ];
+ for( i = 1; i <= 70; i++ )
+ SwAttrPool::pVersionMap2[ i-1 ] = i;
+ for ( i = 71; i <= 75; ++i )
+ SwAttrPool::pVersionMap2[ i-1 ] = i + 10;
+
+ // 3. Version - neue Attribute:
+ // neue Attribute und Dummies fuer die CJK-Version
+ // und neue Grafik-Attribute
+ SwAttrPool::pVersionMap3 = new sal_uInt16[ 86 ];
+ for( i = 1; i <= 21; i++ )
+ SwAttrPool::pVersionMap3[ i-1 ] = i;
+ for ( i = 22; i <= 27; ++i )
+ SwAttrPool::pVersionMap3[ i-1 ] = i + 15;
+ for ( i = 28; i <= 82; ++i )
+ SwAttrPool::pVersionMap3[ i-1 ] = i + 20;
+ for ( i = 83; i <= 86; ++i )
+ SwAttrPool::pVersionMap3[ i-1 ] = i + 35;
+
+ // 4. Version - neue Paragraph Attribute fuer die CJK-Version
+ SwAttrPool::pVersionMap4 = new sal_uInt16[ 121 ];
+ for( i = 1; i <= 65; i++ )
+ SwAttrPool::pVersionMap4[ i-1 ] = i;
+ for ( i = 66; i <= 121; ++i )
+ SwAttrPool::pVersionMap4[ i-1 ] = i + 9;
+
+ // #i18732# - setup new version map due to extension of
+ // the frame attributes (RES_FRMATR_*) for binary filters.
+ SwAttrPool::pVersionMap5 = new sal_uInt16[ 130 ];
+ for( i = 1; i <= 109; i++ )
+ SwAttrPool::pVersionMap5[ i-1 ] = i;
+ for ( i = 110; i <= 130; ++i )
+ SwAttrPool::pVersionMap5[ i-1 ] = i + 6;
+
+ // 6. Version - new character attribute for overlining plus 2 dummies
+ SwAttrPool::pVersionMap6 = new sal_uInt16[ 136 ];
+ for( i = 1; i <= 37; i++ )
+ SwAttrPool::pVersionMap6[ i-1 ] = i;
+ for ( i = 38; i <= 136; ++i )
+ SwAttrPool::pVersionMap6[ i-1 ] = i + 3;
+
+ uno::Reference<
+ lang::XMultiServiceFactory > xMSF =
+ ::comphelper::getProcessServiceFactory();
+
+ SwBreakIt::_Create( xMSF );
+ pCheckIt = NULL;
+
+ _FrmInit();
+ _TextInit();
+
+ SwSelPaintRects::pMapMode = new MapMode;
+ SwFntObj::pPixMap = new MapMode;
+
+ SwIndexReg::pEmptyIndexArray = new SwIndexReg;
+
+ pGlobalOLEExcludeList = new SvPtrarr;
+
+ const SvxSwAutoFmtFlags& rAFlags = SvxAutoCorrCfg::Get()->GetAutoCorrect()->GetSwFlags();
+ SwDoc::pACmpltWords = new SwAutoCompleteWord( rAFlags.nAutoCmpltListLen,
+ rAFlags.nAutoCmpltWordLen );
+}
+
+/******************************************************************************
+ * void _FinitCore()
+ ******************************************************************************/
+
+
+
+void _FinitCore()
+{
+ _FrmFinit();
+ _TextFinit();
+
+ SwBreakIt::_Delete();
+ delete pCheckIt;
+ delete pAppCharClass;
+ delete pCollator;
+ delete pCaseCollator;
+
+ // das default TableAutoFormat zerstoeren
+ delete SwTableAutoFmt::pDfltBoxAutoFmt;
+
+ delete SwSelPaintRects::pMapMode;
+ delete SwFntObj::pPixMap;
+
+ delete SwEditShell::pAutoFmtFlags;
+
+#if OSL_DEBUG_LEVEL > 1
+ //Defaultattribut freigeben lassen um asserts zu vermeiden.
+ if ( aAttrTab[0]->GetRefCount() )
+ SfxItemPool::ReleaseDefaults( aAttrTab, POOLATTR_END-POOLATTR_BEGIN, sal_False);
+#endif
+ delete SwDoc::pACmpltWords;
+
+ delete SwStyleNameMapper::pTextUINameArray;
+ delete SwStyleNameMapper::pListsUINameArray;
+ delete SwStyleNameMapper::pExtraUINameArray;
+ delete SwStyleNameMapper::pRegisterUINameArray;
+ delete SwStyleNameMapper::pDocUINameArray;
+ delete SwStyleNameMapper::pHTMLUINameArray;
+ delete SwStyleNameMapper::pFrmFmtUINameArray;
+ delete SwStyleNameMapper::pChrFmtUINameArray;
+ delete SwStyleNameMapper::pHTMLChrFmtUINameArray;
+ delete SwStyleNameMapper::pPageDescUINameArray;
+ delete SwStyleNameMapper::pNumRuleUINameArray;
+
+ // Delete programmatic name arrays also
+ delete SwStyleNameMapper::pTextProgNameArray;
+ delete SwStyleNameMapper::pListsProgNameArray;
+ delete SwStyleNameMapper::pExtraProgNameArray;
+ delete SwStyleNameMapper::pRegisterProgNameArray;
+ delete SwStyleNameMapper::pDocProgNameArray;
+ delete SwStyleNameMapper::pHTMLProgNameArray;
+ delete SwStyleNameMapper::pFrmFmtProgNameArray;
+ delete SwStyleNameMapper::pChrFmtProgNameArray;
+ delete SwStyleNameMapper::pHTMLChrFmtProgNameArray;
+ delete SwStyleNameMapper::pPageDescProgNameArray;
+ delete SwStyleNameMapper::pNumRuleProgNameArray;
+
+ // And finally, any hash tables that we used
+ delete SwStyleNameMapper::pParaUIMap;
+ delete SwStyleNameMapper::pCharUIMap;
+ delete SwStyleNameMapper::pPageUIMap;
+ delete SwStyleNameMapper::pFrameUIMap;
+ delete SwStyleNameMapper::pNumRuleUIMap;
+
+ delete SwStyleNameMapper::pParaProgMap;
+ delete SwStyleNameMapper::pCharProgMap;
+ delete SwStyleNameMapper::pPageProgMap;
+ delete SwStyleNameMapper::pFrameProgMap;
+ delete SwStyleNameMapper::pNumRuleProgMap;
+
+
+ // loesche alle default-Attribute
+ SfxPoolItem* pHt;
+ for( sal_uInt16 n = 0; n < POOLATTR_END - POOLATTR_BEGIN; n++ )
+ if( 0 != ( pHt = aAttrTab[n] ))
+ delete pHt;
+
+ ::ClearFEShellTabCols();
+
+ delete SwIndexReg::pEmptyIndexArray;
+ delete[] SwAttrPool::pVersionMap1;
+ delete[] SwAttrPool::pVersionMap2;
+ delete[] SwAttrPool::pVersionMap3;
+ delete[] SwAttrPool::pVersionMap4;
+ // #i18732#
+ delete[] SwAttrPool::pVersionMap5;
+ delete[] SwAttrPool::pVersionMap6;
+
+ for ( sal_uInt16 i = 0; i < pGlobalOLEExcludeList->Count(); ++i )
+ delete (SvGlobalName*)(*pGlobalOLEExcludeList)[i];
+ delete pGlobalOLEExcludeList;
+}
+
+// returns the APP - CharClass instance - used for all ToUpper/ToLower/...
+CharClass& GetAppCharClass()
+{
+ if ( !pAppCharClass )
+ {
+ uno::Reference< lang::XMultiServiceFactory > xMSF = ::comphelper::getProcessServiceFactory();
+ pAppCharClass = new CharClass(
+ xMSF, SwBreakIt::Get()->GetLocale( (LanguageType)GetAppLanguage() ));
+ }
+ return *pAppCharClass;
+}
+
+void SwCalendarWrapper::LoadDefaultCalendar( sal_uInt16 eLang )
+{
+ sUniqueId.Erase();
+ if( eLang != nLang )
+ loadDefaultCalendar( SvxCreateLocale( nLang = eLang ));
+}
+
+LanguageType GetAppLanguage()
+{
+ return Application::GetSettings().GetLanguage();
+}
+
+CollatorWrapper& GetAppCollator()
+{
+ if( !pCollator )
+ {
+ const lang::Locale& rLcl = pBreakIt->GetLocale(
+ (LanguageType)GetAppLanguage() );
+ uno::Reference<
+ lang::XMultiServiceFactory > xMSF =
+ ::comphelper::getProcessServiceFactory();
+
+ pCollator = new CollatorWrapper( xMSF );
+ pCollator->loadDefaultCollator( rLcl, SW_COLLATOR_IGNORES );
+ }
+ return *pCollator;
+}
+CollatorWrapper& GetAppCaseCollator()
+{
+ if( !pCaseCollator )
+ {
+ const lang::Locale& rLcl = pBreakIt->GetLocale(
+ (LanguageType)GetAppLanguage() );
+ uno::Reference<
+ lang::XMultiServiceFactory > xMSF =
+ ::comphelper::getProcessServiceFactory();
+
+ pCaseCollator = new CollatorWrapper( xMSF );
+ pCaseCollator->loadDefaultCollator( rLcl, 0 );
+ }
+ return *pCaseCollator;
+}
+
+const ::utl::TransliterationWrapper& GetAppCmpStrIgnore()
+{
+ if( !pTransWrp )
+ {
+ uno::Reference<
+ lang::XMultiServiceFactory > xMSF =
+ ::comphelper::getProcessServiceFactory();
+
+ pTransWrp = new ::utl::TransliterationWrapper( xMSF,
+ i18n::TransliterationModules_IGNORE_CASE |
+ i18n::TransliterationModules_IGNORE_KANA |
+ i18n::TransliterationModules_IGNORE_WIDTH );
+ pTransWrp->loadModuleIfNeeded( static_cast<sal_uInt16>(GetAppLanguage()) );
+ }
+ return *pTransWrp;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/bastyp/ring.cxx b/sw/source/core/bastyp/ring.cxx
new file mode 100644
index 000000000000..697bb9f3c80a
--- /dev/null
+++ b/sw/source/core/bastyp/ring.cxx
@@ -0,0 +1,112 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+
+
+#include "ring.hxx"
+
+
+/*************************************************************************
+|* Ring::Ring()
+*************************************************************************/
+
+Ring::Ring( Ring *pObj )
+{
+ if( !pObj )
+ pNext = this, pPrev = this;
+ else
+ {
+ pNext = pObj;
+ pPrev = pObj->pPrev;
+ pObj->pPrev = this;
+ pPrev->pNext = this;
+ }
+}
+
+/*************************************************************************
+|* Ring::~Ring()
+*************************************************************************/
+
+Ring::~Ring()
+{
+ pNext->pPrev = pPrev;
+ pPrev->pNext = pNext;
+}
+
+/*************************************************************************
+|* Ring::MoveTo
+*************************************************************************/
+
+void Ring::MoveTo(Ring *pDestRing)
+{
+ // loeschen aus dem alten
+ pNext->pPrev = pPrev;
+ pPrev->pNext = pNext;
+
+ // im neuen einfuegen
+ if( pDestRing )
+ {
+ pNext = pDestRing;
+ pPrev = pDestRing->pPrev;
+ pDestRing->pPrev = this;
+ pPrev->pNext = this;
+ }
+ else
+ pNext = pPrev = this;
+
+}
+
+void Ring::MoveRingTo(Ring *pDestRing)
+{
+ // den gesamten Ring in den DestRing einfuegen
+ Ring* pMyPrev = pPrev;
+ Ring* pDestPrev = pDestRing->pPrev;
+
+ pMyPrev->pNext = pDestRing;
+ pDestPrev->pNext = this;
+ pDestRing->pPrev = pMyPrev;
+ pPrev = pDestPrev;
+}
+
+sal_uInt32 Ring::numberOf() const
+{
+ sal_uInt32 nRet = 1;
+ const Ring* pNxt = pNext;
+ while( pNxt != this )
+ {
+ ++nRet;
+ pNxt = pNxt->GetNext();
+ }
+ return nRet;
+}
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/bastyp/swcache.cxx b/sw/source/core/bastyp/swcache.cxx
new file mode 100644
index 000000000000..3098eb2cff6a
--- /dev/null
+++ b/sw/source/core/bastyp/swcache.cxx
@@ -0,0 +1,570 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+#include <tools/debug.hxx>
+#include <swcache.hxx>
+
+SV_IMPL_PTRARR(SwCacheObjArr,SwCacheObj*);
+
+#if OSL_DEBUG_LEVEL > 1
+#define INCREMENT( nVar ) ++nVar
+#else
+#define INCREMENT( nVar )
+#endif
+
+/*************************************************************************
+|* SwCache::Check()
+|*************************************************************************/
+
+#if OSL_DEBUG_LEVEL > 1
+
+void SwCache::Check()
+{
+ if ( !pRealFirst )
+ return;
+
+ //Konsistenspruefung.
+ OSL_ENSURE( !pLast->GetNext(), "Last but not last." );
+ OSL_ENSURE( !pRealFirst->GetPrev(), "First but not first." );
+ sal_uInt16 nCnt = 0;
+ sal_Bool bFirstFound = sal_False;
+ SwCacheObj *pObj = pRealFirst;
+ SwCacheObj *pRekursive = pObj;
+ while ( pObj )
+ {
+ //Das Objekt muss auch auf dem Rueckwaertsweg gefunden werden.
+ SwCacheObj *pTmp = pLast;
+ while ( pTmp && pTmp != pObj )
+ pTmp = pTmp->GetPrev();
+ OSL_ENSURE( pTmp, "Objekt not found." );
+
+ ++nCnt;
+ if ( pObj == pFirst )
+ bFirstFound = sal_True;
+ if ( !pObj->GetNext() )
+ OSL_ENSURE( pObj == pLast, "Last not Found." );
+ pObj = pObj->GetNext();
+ OSL_ENSURE( pObj != pRekursive, "Recursion in SwCache." );
+ }
+ OSL_ENSURE( bFirstFound, "First not Found." );
+ OSL_ENSURE( (nCnt + aFreePositions.Count()) == Count(), "Lost Chain." );
+ if ( Count() == nCurMax )
+ OSL_ENSURE( (nCurMax - nCnt) == aFreePositions.Count(), "Lost FreePositions." );
+}
+#endif
+
+#if OSL_DEBUG_LEVEL > 1
+#define CHECK Check();
+#else
+#define CHECK
+#endif
+
+/*************************************************************************
+|* SwCache::SwCache(), ~SwCache()
+|*************************************************************************/
+
+
+SwCache::SwCache( const sal_uInt16 nInitSize, const sal_uInt16 nGrowSize
+#if OSL_DEBUG_LEVEL > 1
+ , const ByteString &rNm
+#endif
+ ) :
+ SwCacheObjArr( (sal_uInt8)nInitSize, (sal_uInt8)nGrowSize ),
+ aFreePositions( 5, 5 ),
+ pRealFirst( 0 ),
+ pFirst( 0 ),
+ pLast( 0 ),
+ nMax( nInitSize ),
+ nCurMax( nInitSize )
+#if OSL_DEBUG_LEVEL > 1
+ , aName( rNm ),
+ nAppend( 0 ),
+ nInsertFree( 0 ),
+ nReplace( 0 ),
+ nGetSuccess( 0 ),
+ nGetFail( 0 ),
+ nToTop( 0 ),
+ nDelete( 0 ),
+ nGetSeek( 0 ),
+ nAverageSeekCnt( 0 ),
+ nFlushCnt( 0 ),
+ nFlushedObjects( 0 ),
+ nIncreaseMax( 0 ),
+ nDecreaseMax( 0 )
+#endif
+{
+}
+
+#if OSL_DEBUG_LEVEL > 1
+SwCache::~SwCache()
+{
+ {
+ ByteString sOut( aName ); sOut += '\n';
+ (( sOut += "Anzahl neuer Eintraege: " )
+ += ByteString::CreateFromInt32( nAppend ))+= '\n';
+ (( sOut += "Anzahl Insert auf freie Plaetze: " )
+ += ByteString::CreateFromInt32( nInsertFree ))+= '\n';
+ (( sOut += "Anzahl Ersetzungen: " )
+ += ByteString::CreateFromInt32( nReplace ))+= '\n';
+ (( sOut += "Anzahl Erfolgreicher Get's: " )
+ += ByteString::CreateFromInt32( nGetSuccess ))+= '\n';
+ (( sOut += "Anzahl Fehlgeschlagener Get's: " )
+ += ByteString::CreateFromInt32( nGetFail ))+= '\n';
+ (( sOut += "Anzahl Umsortierungen (LRU): " )
+ += ByteString::CreateFromInt32( nToTop ))+= '\n';
+ (( sOut += "Anzahl Loeschungen: " )
+ += ByteString::CreateFromInt32( nDelete ))+= '\n';
+ (( sOut += "Anzahl Get's ohne Index: " )
+ += ByteString::CreateFromInt32( nGetSeek ))+= '\n';
+ (( sOut += "Anzahl Seek fuer Get ohne Index: " )
+ += ByteString::CreateFromInt32( nAverageSeekCnt ))+= '\n';
+ (( sOut += "Anzahl Flush-Aufrufe: " )
+ += ByteString::CreateFromInt32( nFlushCnt ))+= '\n';
+ (( sOut += "Anzahl geflush'ter Objekte: " )
+ += ByteString::CreateFromInt32( nFlushedObjects ))+= '\n';
+ (( sOut += "Anzahl Cache-Erweiterungen: " )
+ += ByteString::CreateFromInt32( nIncreaseMax ))+= '\n';
+ (( sOut += "Anzahl Cache-Verkleinerungen: " )
+ += ByteString::CreateFromInt32( nDecreaseMax ))+= '\n';
+
+ OSL_FAIL( sOut.GetBuffer() );
+ }
+ Check();
+}
+#endif
+
+/*************************************************************************
+|* SwCache::Flush()
+|*************************************************************************/
+
+
+void SwCache::Flush( const sal_uInt8 )
+{
+ INCREMENT( nFlushCnt );
+ SwCacheObj *pObj = pRealFirst;
+ pRealFirst = pFirst = pLast = 0;
+ SwCacheObj *pTmp;
+ while ( pObj )
+ {
+#if OSL_DEBUG_LEVEL > 1
+ if ( pObj->IsLocked() )
+ {
+ OSL_FAIL( "Flushing locked objects." );
+ if ( !pRealFirst )
+ {
+ pRealFirst = pFirst = pLast = pObj;
+ pTmp = pObj->GetNext();
+ pObj->SetNext( 0 ); pObj->SetPrev( 0 );
+ pObj = pTmp;
+ }
+ else
+ { pLast->SetNext( pObj );
+ pObj->SetPrev( pLast );
+ pLast = pObj;
+ pTmp = pObj->GetNext();
+ pObj->SetNext( 0 );
+ pObj = pTmp;
+ }
+ }
+ else
+#endif
+ {
+ pTmp = (SwCacheObj*)pObj;
+ pObj = pTmp->GetNext();
+ aFreePositions.Insert( pTmp->GetCachePos(), aFreePositions.Count() );
+ *(pData + pTmp->GetCachePos()) = (void*)0;
+ delete pTmp;
+ INCREMENT( nFlushedObjects );
+ }
+ }
+}
+
+/*************************************************************************
+|* SwCache::ToTop()
+|*************************************************************************/
+
+
+void SwCache::ToTop( SwCacheObj *pObj )
+{
+ INCREMENT( nToTop );
+
+ //Objekt aus der LRU-Kette ausschneiden und am Anfang einfuegen.
+ if ( pRealFirst == pObj ) //pFirst wurde vom Aufrufer geprueft!
+ { CHECK;
+ return;
+ }
+
+ if ( !pRealFirst )
+ { //Der erste wird eingetragen.
+ OSL_ENSURE( !pFirst && !pLast, "First not first." );
+ pRealFirst = pFirst = pLast = pObj;
+ CHECK;
+ return;
+ }
+
+ //Ausschneiden.
+ if ( pObj == pLast )
+ {
+ OSL_ENSURE( pObj->GetPrev(), "Last but no Prev." );
+ pLast = pObj->GetPrev();
+ pLast->SetNext( 0 );
+ }
+ else
+ {
+ if ( pObj->GetNext() )
+ pObj->GetNext()->SetPrev( pObj->GetPrev() );
+ if ( pObj->GetPrev() )
+ pObj->GetPrev()->SetNext( pObj->GetNext() );
+ }
+
+ //Am (virtuellen) Anfang einfuegen.
+ if ( pRealFirst == pFirst )
+ {
+ pRealFirst->SetPrev( pObj );
+ pObj->SetNext( pRealFirst );
+ pObj->SetPrev( 0 );
+ pRealFirst = pFirst = pObj;
+ CHECK;
+ }
+ else
+ {
+ OSL_ENSURE( pFirst, "ToTop, First ist not RealFirst an Empty." );
+
+ if ( pFirst->GetPrev() )
+ {
+ pFirst->GetPrev()->SetNext( pObj );
+ pObj->SetPrev( pFirst->GetPrev() );
+ }
+ else
+ pObj->SetPrev( 0 );
+ pFirst->SetPrev( pObj );
+ pObj->SetNext( pFirst );
+ pFirst = pObj;
+ CHECK;
+ }
+}
+
+/*************************************************************************
+|* SwCache::Get()
+|*************************************************************************/
+
+
+SwCacheObj *SwCache::Get( const void *pOwner, const sal_uInt16 nIndex,
+ const sal_Bool bToTop )
+{
+ SwCacheObj *pRet;
+ if ( 0 != (pRet = nIndex < Count() ? operator[]( nIndex ) : 0) )
+ {
+ if ( !pRet->IsOwner( pOwner ) )
+ pRet = 0;
+ else if ( bToTop && pRet != pFirst )
+ ToTop( pRet );
+ }
+
+#if OSL_DEBUG_LEVEL > 1
+ if ( pRet )
+ ++nGetSuccess;
+ else
+ ++nGetFail;
+#endif
+
+ return pRet;
+}
+
+
+
+SwCacheObj *SwCache::Get( const void *pOwner, const sal_Bool bToTop )
+{
+ SwCacheObj *pRet = pRealFirst;
+ while ( pRet && !pRet->IsOwner( pOwner ) )
+ {
+ INCREMENT( nAverageSeekCnt );
+ pRet = pRet->GetNext();
+ }
+
+ if ( bToTop && pRet && pRet != pFirst )
+ ToTop( pRet );
+
+#if OSL_DEBUG_LEVEL > 1
+ if ( pRet )
+ ++nGetSuccess;
+ else
+ ++nGetFail;
+ ++nGetSeek;
+#endif
+ return pRet;
+}
+
+/*************************************************************************
+|* SwCache::Delete()
+|*************************************************************************/
+
+
+void SwCache::DeleteObj( SwCacheObj *pObj )
+{
+ CHECK;
+ OSL_ENSURE( !pObj->IsLocked(), "SwCache::Delete: Object ist Locked." );
+ if ( pObj->IsLocked() )
+ return;
+
+ if ( pFirst == pObj )
+ {
+ if ( pFirst->GetNext() )
+ pFirst = pFirst->GetNext();
+ else
+ pFirst = pFirst->GetPrev();
+ }
+ if ( pRealFirst == pObj )
+ pRealFirst = pRealFirst->GetNext();
+ if ( pLast == pObj )
+ pLast = pLast->GetPrev();
+ if ( pObj->GetPrev() )
+ pObj->GetPrev()->SetNext( pObj->GetNext() );
+ if ( pObj->GetNext() )
+ pObj->GetNext()->SetPrev( pObj->GetPrev() );
+
+ aFreePositions.Insert( pObj->GetCachePos(), aFreePositions.Count() );
+ *(pData + pObj->GetCachePos()) = (void*)0;
+ delete pObj;
+
+ CHECK;
+ if ( Count() > nCurMax &&
+ (nCurMax <= (Count() - aFreePositions.Count())) )
+ {
+ //Falls moeglich wieder verkleinern, dazu muessen allerdings ausreichend
+ //Freie Positionen bereitstehen.
+ //Unangenehmer Nebeneffekt ist, das die Positionen verschoben werden
+ //muessen, und die Eigentuemer der Objekte diese wahrscheinlich nicht
+ //wiederfinden werden.
+ for ( sal_uInt16 i = 0; i < Count(); ++i )
+ {
+ SwCacheObj *pTmpObj = operator[](i);
+ if ( !pTmpObj )
+ { SwCacheObjArr::Remove( i, 1 );
+ --i;
+ }
+ else
+ pTmpObj->SetCachePos( i );
+ }
+ aFreePositions.Remove( 0, aFreePositions.Count() );
+ }
+ CHECK;
+}
+
+void SwCache::Delete( const void *pOwner )
+{
+ INCREMENT( nDelete );
+ SwCacheObj *pObj;
+ if ( 0 != (pObj = Get( pOwner, sal_Bool(sal_False) )) )
+ DeleteObj( pObj );
+}
+
+
+/*************************************************************************
+|* SwCache::Insert()
+|*************************************************************************/
+
+
+sal_Bool SwCache::Insert( SwCacheObj *pNew )
+{
+ CHECK;
+ OSL_ENSURE( !pNew->GetPrev() && !pNew->GetNext(), "New but not new." );
+
+ sal_uInt16 nPos;//Wird hinter den if's zum setzen am Obj benutzt.
+ if ( Count() < nCurMax )
+ {
+ //Es ist noch Platz frei, also einfach einfuegen.
+ INCREMENT( nAppend );
+ nPos = Count();
+ SwCacheObjArr::C40_INSERT( SwCacheObj, pNew, nPos );
+ }
+ else if ( aFreePositions.Count() )
+ {
+ //Es exitieren Platzhalter, also den letzten benutzen.
+ INCREMENT( nInsertFree );
+ const sal_uInt16 nFreePos = aFreePositions.Count() - 1;
+ nPos = aFreePositions[ nFreePos ];
+ *(pData + nPos) = pNew;
+ aFreePositions.Remove( nFreePos );
+ }
+ else
+ {
+ INCREMENT( nReplace );
+ //Der letzte des LRU fliegt raus.
+ SwCacheObj *pObj = pLast;
+
+ while ( pObj && pObj->IsLocked() )
+ pObj = pObj->GetPrev();
+ if ( !pObj )
+ {
+ OSL_FAIL( "Cache overflow." );
+ return sal_False;
+ }
+
+ nPos = pObj->GetCachePos();
+ if ( pObj == pLast )
+ { OSL_ENSURE( pObj->GetPrev(), "Last but no Prev" );
+ pLast = pObj->GetPrev();
+ pLast->SetNext( 0 );
+ }
+ else
+ {
+ if ( pObj->GetPrev() )
+ pObj->GetPrev()->SetNext( pObj->GetNext() );
+ if ( pObj->GetNext() )
+ pObj->GetNext()->SetPrev( pObj->GetPrev() );
+ }
+ delete pObj;
+ *(pData + nPos) = pNew;
+ }
+ pNew->SetCachePos( nPos );
+
+ //Anstelle von ToTop, einfach als pFirst einfuegen.
+// ToTop( nPos );
+ if ( pFirst )
+ {
+ if ( pFirst->GetPrev() )
+ { pFirst->GetPrev()->SetNext( pNew );
+ pNew->SetPrev( pFirst->GetPrev() );
+ }
+ pFirst->SetPrev( pNew );
+ pNew->SetNext( pFirst );
+ }
+ else
+ { OSL_ENSURE( !pLast, "Last but no First." );
+ pLast = pNew;
+ }
+ if ( pFirst == pRealFirst )
+ pRealFirst = pNew;
+ pFirst = pNew;
+
+ CHECK;
+ return sal_True;
+}
+
+/*************************************************************************
+|* SwCache::SetLRUOfst()
+|*************************************************************************/
+
+
+void SwCache::SetLRUOfst( const sal_uInt16 nOfst )
+{
+ if ( !pRealFirst || ((Count() - aFreePositions.Count()) < nOfst) )
+ return;
+
+ CHECK;
+ pFirst = pRealFirst;
+ for ( sal_uInt16 i = 0; i < Count() && i < nOfst; ++i )
+ {
+ if ( pFirst->GetNext() && pFirst->GetNext()->GetNext() )
+ pFirst = pFirst->GetNext();
+ else
+ break;
+ }
+ CHECK;
+}
+
+/*************************************************************************
+|* SwCacheObj::SwCacheObj()
+|*************************************************************************/
+
+
+SwCacheObj::SwCacheObj( const void *pOwn ) :
+ pNext( 0 ),
+ pPrev( 0 ),
+ nCachePos( USHRT_MAX ),
+ nLock( 0 ),
+ pOwner( pOwn )
+{
+}
+
+
+
+SwCacheObj::~SwCacheObj()
+{
+}
+
+/*************************************************************************
+|* SwCacheObj::SetLock(), Unlock()
+|*************************************************************************/
+
+#if OSL_DEBUG_LEVEL > 1
+
+void SwCacheObj::Lock()
+{
+ OSL_ENSURE( nLock < UCHAR_MAX, "To many Locks for CacheObject." );
+ ++nLock;
+}
+
+
+
+void SwCacheObj::Unlock()
+{
+ OSL_ENSURE( nLock, "No more Locks available." );
+ --nLock;
+}
+#endif
+
+
+SwCacheAccess::~SwCacheAccess()
+{
+ if ( pObj )
+ pObj->Unlock();
+}
+
+/*************************************************************************
+|* SwCacheAccess::Get()
+|*************************************************************************/
+
+void SwCacheAccess::_Get()
+{
+ OSL_ENSURE( !pObj, "SwCacheAcces Obj already available." );
+
+ pObj = NewObj();
+ if ( !rCache.Insert( pObj ) )
+ {
+ delete pObj;
+ pObj = 0;
+ }
+ else
+ pObj->Lock();
+}
+
+/*************************************************************************
+|* SwCacheAccess::IsAvailable()
+|*************************************************************************/
+
+sal_Bool SwCacheAccess::IsAvailable() const
+{
+ return pObj != 0;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/bastyp/swrect.cxx b/sw/source/core/bastyp/swrect.cxx
new file mode 100644
index 000000000000..9f5a7b6c6a1f
--- /dev/null
+++ b/sw/source/core/bastyp/swrect.cxx
@@ -0,0 +1,308 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+
+#if OSL_DEBUG_LEVEL > 1
+#include <tools/stream.hxx>
+#endif
+#include <stdlib.h>
+#include "swrect.hxx"
+#include <math.h>
+
+/*************************************************************************
+|*
+|* SwRect::SwRect()
+|*
+|*************************************************************************/
+
+
+
+SwRect::SwRect( const Rectangle &rRect ) :
+ m_Point( rRect.Left(), rRect.Top() )
+{
+ m_Size.setWidth(rRect.Right() == RECT_EMPTY ? 0 :
+ rRect.Right() - rRect.Left() +1);
+ m_Size.setHeight(rRect.Bottom() == RECT_EMPTY ? 0 :
+ rRect.Bottom() - rRect.Top() + 1);
+}
+
+/*************************************************************************
+|*
+|* SwRect::Center()
+|*
+|*************************************************************************/
+Point SwRect::Center() const
+{
+ return Point( Left() + Width() / 2,
+ Top() + Height() / 2 );
+}
+
+/*************************************************************************
+|*
+|* SwRect::Union()
+|*
+|*************************************************************************/
+
+
+
+SwRect& SwRect::Union( const SwRect& rRect )
+{
+ if ( Top() > rRect.Top() )
+ Top( rRect.Top() );
+ if ( Left() > rRect.Left() )
+ Left( rRect.Left() );
+ long n = rRect.Right();
+ if ( Right() < n )
+ Right( n );
+ n = rRect.Bottom();
+ if ( Bottom() < n )
+ Bottom( n );
+ return *this;
+}
+/*************************************************************************
+|*
+|* SwRect::Intersection(), _Intersection()
+|*
+|*************************************************************************/
+
+
+
+SwRect& SwRect::Intersection( const SwRect& rRect )
+{
+ //Hat das Teil ueberhaupt Gemeinsamkeiten mit mir?
+ if ( IsOver( rRect ) )
+ {
+ //Bestimmung der kleineren rechten sowie unteren und
+ // der groesseren linken sowie oberen Kante.
+ if ( Left() < rRect.Left() )
+ Left( rRect.Left() );
+ if ( Top() < rRect.Top() )
+ Top( rRect.Top() );
+ long n = rRect.Right();
+ if ( Right() > n )
+ Right( n );
+ n = rRect.Bottom();
+ if ( Bottom() > n )
+ Bottom( n );
+ }
+ else
+ //Def.: Bei einer leeren Intersection wird nur die SSize genullt.
+ SSize(0, 0);
+
+ return *this;
+}
+
+
+
+SwRect& SwRect::_Intersection( const SwRect& rRect )
+{
+ //Bestimmung der kleineren rechten sowie unteren und
+ // der groesseren linken sowie oberen Kante.
+ if ( Left() < rRect.Left() )
+ Left( rRect.Left() );
+ if ( Top() < rRect.Top() )
+ Top( rRect.Top() );
+ long n = rRect.Right();
+ if ( Right() > n )
+ Right( n );
+ n = rRect.Bottom();
+ if ( Bottom() > n )
+ Bottom( n );
+
+ return *this;
+}
+/*************************************************************************
+|*
+|* SwRect::IsInside()
+|*
+|*************************************************************************/
+
+
+
+sal_Bool SwRect::IsInside( const SwRect& rRect ) const
+{
+ const long nRight = Right();
+ const long nBottom = Bottom();
+ const long nrRight = rRect.Right();
+ const long nrBottom= rRect.Bottom();
+ return (Left() <= rRect.Left()) && (rRect.Left()<= nRight) &&
+ (Left() <= nrRight) && (nrRight <= nRight) &&
+ (Top() <= rRect.Top()) && (rRect.Top() <= nBottom) &&
+ (Top() <= nrBottom) && (nrBottom <= nBottom);
+}
+
+
+
+sal_Bool SwRect::IsInside( const Point& rPoint ) const
+{
+ return (Left() <= rPoint.X())
+ && (Top() <= rPoint.Y())
+ && (Right() >= rPoint.X())
+ && (Bottom()>= rPoint.Y());
+}
+/* ---------------------------------------------------------------------------
+ mouse moving of table borders
+ ---------------------------------------------------------------------------*/
+sal_Bool SwRect::IsNear( const Point& rPoint, long nTolerance ) const
+{
+ return IsInside(rPoint) ||
+ (((Left() - nTolerance) <= rPoint.X())
+ && ((Top() - nTolerance) <= rPoint.Y())
+ && ((Right() + nTolerance) >= rPoint.X())
+ && ((Bottom() + nTolerance)>= rPoint.Y()));
+}
+
+/*************************************************************************
+|*
+|* SwRect::IsOver()
+|*
+|*************************************************************************/
+
+
+
+sal_Bool SwRect::IsOver( const SwRect& rRect ) const
+{
+ return (Top() <= rRect.Bottom())
+ && (Left() <= rRect.Right())
+ && (Right() >= rRect.Left())
+ && (Bottom()>= rRect.Top()) ? sal_True : sal_False;
+}
+
+/*************************************************************************
+|*
+|* SwRect::Justify()
+|*
+|*************************************************************************/
+
+
+
+void SwRect::Justify()
+{
+ if ( m_Size.getHeight() < 0 )
+ {
+ m_Point.Y() += m_Size.getHeight() + 1;
+ m_Size.setHeight(-m_Size.getHeight());
+ }
+ if ( m_Size.getWidth() < 0 )
+ {
+ m_Point.X() += m_Size.getWidth() + 1;
+ m_Size.setWidth(-m_Size.getWidth());
+ }
+}
+
+
+// Similiar to the inline methods, but we need the function pointers
+
+void SwRect::_Width( const long nNew ) { m_Size.setWidth(nNew); }
+void SwRect::_Height( const long nNew ) { m_Size.setHeight(nNew); }
+void SwRect::_Left( const long nLeft ){ m_Size.Width() += m_Point.getX() - nLeft; m_Point.setX(nLeft); }
+void SwRect::_Right( const long nRight ){ m_Size.setWidth(nRight - m_Point.getX()); }
+void SwRect::_Top( const long nTop ){ m_Size.Height() += m_Point.getY() - nTop; m_Point.setY(nTop); }
+void SwRect::_Bottom( const long nBottom ){ m_Size.setHeight(nBottom - m_Point.getY()); }
+
+long SwRect::_Width() const{ return m_Size.getWidth(); }
+long SwRect::_Height() const{ return m_Size.getHeight(); }
+long SwRect::_Left() const{ return m_Point.getX(); }
+long SwRect::_Right() const{ return m_Point.getX() + m_Size.getWidth(); }
+long SwRect::_Top() const{ return m_Point.getY(); }
+long SwRect::_Bottom() const{ return m_Point.getY() + m_Size.getHeight(); }
+
+void SwRect::AddWidth( const long nAdd ) { m_Size.Width() += nAdd; }
+void SwRect::AddHeight( const long nAdd ) { m_Size.Height() += nAdd; }
+void SwRect::SubLeft( const long nSub ){ m_Size.Width() += nSub; m_Point.X() -= nSub; }
+void SwRect::AddRight( const long nAdd ){ m_Size.Width() += nAdd; }
+void SwRect::SubTop( const long nSub ){ m_Size.Height() += nSub; m_Point.Y() -= nSub; }
+void SwRect::AddBottom( const long nAdd ){ m_Size.Height() += nAdd; }
+void SwRect::SetPosX( const long nNew ){ m_Point.setX(nNew); }
+void SwRect::SetPosY( const long nNew ){ m_Point.setY(nNew); }
+const Size SwRect::_Size() const { return SSize(); }
+const Size SwRect::SwappedSize() const { return Size( m_Size.getHeight(), m_Size.getWidth() ); }
+const Point SwRect::TopLeft() const { return Pos(); }
+const Point SwRect::TopRight() const { return Point( m_Point.getX() + m_Size.getWidth(), m_Point.getY() ); }
+const Point SwRect::BottomLeft() const { return Point( m_Point.getX(), m_Point.getY() + m_Size.getHeight() ); }
+const Point SwRect::BottomRight() const
+ { return Point( m_Point.getX() + m_Size.getWidth(), m_Point.getY() + m_Size.getHeight() ); }
+long SwRect::GetLeftDistance( long nLimit ) const { return m_Point.getX() - nLimit; }
+long SwRect::GetBottomDistance( long nLim ) const { return nLim - m_Point.getY() - m_Size.getHeight();}
+long SwRect::GetTopDistance( long nLimit ) const { return m_Point.getY() - nLimit; }
+long SwRect::GetRightDistance( long nLim ) const { return nLim - m_Point.getX() - m_Size.getWidth(); }
+sal_Bool SwRect::OverStepLeft( long nLimit ) const
+ { return nLimit > m_Point.getX() && m_Point.getX() + m_Size.getWidth() > nLimit; }
+sal_Bool SwRect::OverStepBottom( long nLimit ) const
+ { return nLimit > m_Point.getY() && m_Point.getY() + m_Size.getHeight() > nLimit; }
+sal_Bool SwRect::OverStepTop( long nLimit ) const
+ { return nLimit > m_Point.getY() && m_Point.getY() + m_Size.getHeight() > nLimit; }
+sal_Bool SwRect::OverStepRight( long nLimit ) const
+ { return nLimit > m_Point.getX() && m_Point.getX() + m_Size.getWidth() > nLimit; }
+void SwRect::SetLeftAndWidth( long nLeft, long nNew )
+{
+ m_Point.setX(nLeft);
+ m_Size.setWidth(nNew);
+}
+void SwRect::SetTopAndHeight( long nTop, long nNew )
+{
+ m_Point.setY(nTop);
+ m_Size.setHeight(nNew);
+}
+void SwRect::SetRightAndWidth( long nRight, long nNew )
+{
+ m_Point.setX(nRight - nNew);
+ m_Size.setWidth(nNew);
+}
+void SwRect::SetBottomAndHeight( long nBottom, long nNew )
+{
+ m_Point.setY(nBottom - nNew);
+ m_Size.setHeight(nNew);
+}
+void SwRect::SetUpperLeftCorner( const Point& rNew )
+ { m_Point = rNew; }
+void SwRect::SetUpperRightCorner( const Point& rNew )
+ { m_Point = Point(rNew.nA - m_Size.getWidth(), rNew.nB); }
+void SwRect::SetLowerLeftCorner( const Point& rNew )
+ { m_Point = Point(rNew.nA, rNew.nB - m_Size.getHeight()); }
+
+#if OSL_DEBUG_LEVEL > 1
+/*************************************************************************
+ * operator<<( ostream&, SwRect&)
+ *************************************************************************/
+
+
+
+SvStream &operator<<( SvStream &rStream, const SwRect &rRect )
+{
+ rStream << '[' << rRect.Top() << '/' << rRect.Left()
+ << ',' << rRect.Width() << 'x' << rRect.Height() << "] ";
+ return rStream;
+}
+#endif
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/bastyp/swregion.cxx b/sw/source/core/bastyp/swregion.cxx
new file mode 100644
index 000000000000..5b812314da95
--- /dev/null
+++ b/sw/source/core/bastyp/swregion.cxx
@@ -0,0 +1,247 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+
+
+
+#include <tools/debug.hxx>
+#include "swtypes.hxx"
+#include "swrect.hxx"
+#include "swregion.hxx"
+
+
+SV_IMPL_VARARR( SwRects, SwRect );
+
+/*************************************************************************
+|* SwRegionRects::SwRegionRects()
+|*************************************************************************/
+
+SwRegionRects::SwRegionRects( const SwRect &rStartRect, sal_uInt16 nInit,
+ sal_uInt16 nGrow ) :
+ SwRects( (sal_uInt8)nInit, (sal_uInt8)nGrow ),
+ aOrigin( rStartRect )
+{
+ Insert( aOrigin, 0 );
+}
+
+/*************************************************************************
+ * inline InsertRect()
+ *
+ * InsertRect() wird nur von operator-=() gerufen.
+ * Wenn bDel == sal_True ist, dann wird das Rect an der Position nPos mit
+ * rRect ueberschrieben, ansonsten wird rRect hinten angehaengt.
+ *************************************************************************/
+
+inline void SwRegionRects::InsertRect( const SwRect &rRect, const sal_uInt16 nPos,
+ sal_Bool &rDel )
+{
+ if( rDel )
+ {
+ pData = (SwRect*)pData; // looks weird but seems to help gcc ->i78417
+ *(pData+nPos) = rRect;
+ rDel = sal_False;
+ }
+ else
+ Insert( rRect, Count() );
+}
+
+/*************************************************************************
+|*
+|* SwRegionRects::operator-=()
+|*
+|* Beschreibung Alle Ueberschneidungen der Rechtecke, die sich
+|* gerade im Array befinden, mit dem uebergebenen Rechteck werden
+|* entfernt.
+|* Dazu muessen die vorhandenen Rechtecke entweder aufgeteilt oder
+|* geloescht werden.
+|*
+|*************************************************************************/
+
+void SwRegionRects::operator-=( const SwRect &rRect )
+{
+ sal_uInt16 nMax = Count();
+ for ( sal_uInt16 i = 0; i < nMax; ++i )
+ {
+ if ( rRect.IsOver( *(pData+i) ) )
+ {
+ SwRect aTmp( *(pData+i) );
+ SwRect aInter( aTmp );
+ aInter._Intersection( rRect );
+
+ // Das erste Rect, das wir inserten wollen, nimmt die
+ // Stelle von i ein. So ersparen wir uns das Delete().
+ sal_Bool bDel = sal_True;
+
+ //Jetzt aufteilen das Teil: Es sollen diejenigen Rechtecke
+ //zurueckbleiben, die im alten aber nicht im neuen liegen.
+ //Sprich alle Rechtecke die im alten aber nicht in der Intersection
+ //liegen.
+ long nTmp;
+ if ( 0 < (nTmp = aInter.Top() - aTmp.Top()) )
+ {
+ const long nOldVal = aTmp.Height();
+ aTmp.Height(nTmp);
+ InsertRect( aTmp, i, bDel );
+ aTmp.Height( nOldVal );
+ }
+
+ aTmp.Top( aInter.Top() + aInter.Height() );
+ if ( aTmp.Height() > 0 )
+ InsertRect( aTmp, i, bDel );
+
+ aTmp.Top( aInter.Top() );
+ aTmp.Bottom( aInter.Bottom() );
+ if ( 0 < (nTmp = aInter.Left() - aTmp.Left()) )
+ {
+ const long nOldVal = aTmp.Width();
+ aTmp.Width( nTmp );
+ InsertRect( aTmp, i, bDel );
+ aTmp.Width( nOldVal );
+ }
+
+ aTmp.Left( aInter.Left() + aInter.Width() ); //+1?
+ if ( aTmp.Width() > 0 )
+ InsertRect( aTmp, i, bDel );
+
+ if( bDel )
+ {
+ Remove( i );
+ --i; //Damit wir keinen uebergehen.
+ --nMax; //Damit wir keinen zuviel verarbeiten.
+ }
+ }
+ }
+
+}
+
+/*************************************************************************
+ * SwRegionRects::Invert()
+ *
+ * Bezugspunkt ist aOrigin, das Original-SRectangle.
+ * Aus Loechern werden Flaechen, aus Flaechen werden Loecher.
+ * Ein Hinweis: Wenn keine Rects abgezogen wurden, so ist das enthaltene
+ * Rechteck identisch mit aOrigin. Nach Invert() besteht die Region aus
+ * einem Null-SRectangle.
+ *************************************************************************/
+
+void SwRegionRects::Invert()
+{
+ // Nicht besonders elegant und schnell, aber wirkungsvoll:
+ // Wir legen eine weitere Region an und ziehen alle Flaechen ab,
+ // die in uns noch uebrig geblieben sind. Danach werden alle
+ // Werte uebertragen.
+
+ // Um unuetze Speicheranforderungen zu vermeiden versuchen wir die
+ // iniale Groesse moeglichst brauchbar anzulegen:
+ // Anzahl der Rechtecke in der Region * 2 + 2
+ // plus zwei um den Sonderfall eines einzelnen Loches (macht vier
+ // Rechtecke im inversen Fall) abzudecken.
+
+ SwRegionRects aInvRegion( aOrigin, Count()*2+2 );
+ const SwRect *pDat = GetData();
+ for( sal_uInt16 i = 0; i < Count(); ++pDat, ++i )
+ aInvRegion -= *pDat;
+
+ sal_uInt16 nCpy = Count(), nDel = 0;
+ if( aInvRegion.Count() < Count() )
+ {
+ nDel = Count() - aInvRegion.Count();
+ nCpy = aInvRegion.Count();
+ }
+ // alle vorhandenen ueberschreiben
+ memcpy( pData, aInvRegion.GetData(), nCpy * sizeof( SwRect ));
+
+ if( nCpy < aInvRegion.Count() )
+ Insert( &aInvRegion, nCpy, nCpy );
+ else if( nDel )
+ Remove( nCpy, nDel );
+}
+/*************************************************************************
+|*
+|* SwRegionRects::Compress()
+|*
+|* Beschreibung Zusammenfassen von benachbarten Rechtecken.
+|*
+|*************************************************************************/
+inline SwTwips CalcArea( const SwRect &rRect )
+{
+ return rRect.Width() * rRect.Height();
+}
+
+
+void SwRegionRects::Compress( sal_Bool bFuzzy )
+{
+ for ( int i = 0; i < Count(); ++i )
+ {
+ for ( int j = i+1; j < Count(); ++j )
+ {
+ //Wenn zwei Rechtecke ineinanderliegen, so ist eins davon
+ //uberfluessig.
+ if ( (*(pData + i)).IsInside( *(pData + j) ) )
+ {
+ Remove( static_cast<sal_uInt16>(j), 1 );
+ --j;
+ }
+ else if ( (*(pData + j)).IsInside( *(pData + i) ) )
+ {
+ *(pData + i) = *(pData + j);
+ Remove( static_cast<sal_uInt16>(j), 1 );
+ i = -1;
+ break;
+ }
+ else
+ {
+ //Wenn zwei Rechtecke dieselbe Flaeche haben wie deren
+ //Union abzueglich deren Intersection, so ist eines
+ //davon ueberfluessig.
+ //Um moeglichst viel zusammenzufassen und in der Folge
+ //moeglichst wenig einzelne Paints zu haben darf die Flaeche
+ //der Union ruhig ein bischen groesser sein
+ //( 9622 * 141.5 = 1361513 ~= ein virtel Zentimeter ueber die
+ // Breite einer DINA4 Seite)
+ const long nFuzzy = bFuzzy ? 1361513 : 0;
+ SwRect aUnion( *(pData + i) );aUnion.Union( *(pData + j) );
+ SwRect aInter( *(pData + i) );aInter.Intersection( *(pData + j));
+ if ( (::CalcArea( *(pData + i) ) +
+ ::CalcArea( *(pData + j) ) + nFuzzy) >=
+ (::CalcArea( aUnion ) - CalcArea( aInter )) )
+ {
+ *(pData + i) = aUnion;
+ Remove( static_cast<sal_uInt16>(j), 1 );
+ i = -1;
+ break;
+ }
+ }
+ }
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/bastyp/swtypes.cxx b/sw/source/core/bastyp/swtypes.cxx
new file mode 100644
index 000000000000..a683ed170c0f
--- /dev/null
+++ b/sw/source/core/bastyp/swtypes.cxx
@@ -0,0 +1,136 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+#include "swtypes.hxx"
+#include "tools/string.hxx"
+#include <vcl/svapp.hxx>
+#include <vcl/window.hxx>
+#include <vcl/graph.hxx>
+#include <editeng/unolingu.hxx>
+#include <pagefrm.hxx>
+#include <swatrset.hxx>
+#include <frmfmt.hxx>
+#include <frmtool.hxx>
+#include <ndtxt.hxx>
+#include <UndoDelete.hxx>
+#include <UndoInsert.hxx>
+#include <swtable.hxx>
+#include <viscrs.hxx>
+#include <fntcache.hxx>
+#include <swfntcch.hxx>
+#include <hffrm.hxx>
+#include <colfrm.hxx>
+#include <bodyfrm.hxx>
+#include <tabfrm.hxx>
+#include <txtfrm.hxx>
+#include <swtblfmt.hxx>
+#include <rowfrm.hxx>
+#include <cellfrm.hxx>
+#include <sectfrm.hxx>
+
+using namespace com::sun::star;
+
+ByteString aEmptyByteStr; // Konstante Strings
+String aEmptyStr; // Konstante Strings
+String aDotStr('.'); // Konstante Strings
+
+IMPL_FIXEDMEMPOOL_NEWDEL( SwAttrSet, 25, 25 )
+IMPL_FIXEDMEMPOOL_NEWDEL( SwStartNode, 20, 20 )
+IMPL_FIXEDMEMPOOL_NEWDEL( SwEndNode, 20, 20 )
+IMPL_FIXEDMEMPOOL_NEWDEL( SwTableBox, 50, 50 )
+IMPL_FIXEDMEMPOOL_NEWDEL( SwUndoDelete, 10, 10 )
+IMPL_FIXEDMEMPOOL_NEWDEL( SwUndoInsert, 10, 10 )
+IMPL_FIXEDMEMPOOL_NEWDEL( SwPaM, 10, 10 )
+IMPL_FIXEDMEMPOOL_NEWDEL( SwCursor, 10, 10 )
+IMPL_FIXEDMEMPOOL_NEWDEL( SwShellCrsr, 10, 10 )
+IMPL_FIXEDMEMPOOL_NEWDEL( SwTxtNode, 50, 50 )
+IMPL_FIXEDMEMPOOL_NEWDEL( SwpHints, 25, 25 )
+IMPL_FIXEDMEMPOOL_NEWDEL( SwFntObj, 50, 50 )
+IMPL_FIXEDMEMPOOL_NEWDEL( SwFontObj, 50, 50 )
+IMPL_FIXEDMEMPOOL_NEWDEL( SwBorderAttrs, 100, 100 )
+IMPL_FIXEDMEMPOOL_NEWDEL( SwCellFrm, 50, 50 )
+IMPL_FIXEDMEMPOOL_NEWDEL( SwRowFrm, 10, 10 )
+IMPL_FIXEDMEMPOOL_NEWDEL( SwColumnFrm, 40, 40 )
+IMPL_FIXEDMEMPOOL_NEWDEL( SwSectionFrm, 20, 20 )
+IMPL_FIXEDMEMPOOL_NEWDEL( SwTabFrm, 10, 10 )
+IMPL_FIXEDMEMPOOL_NEWDEL( SwPageFrm, 20, 20 )
+IMPL_FIXEDMEMPOOL_NEWDEL( SwBodyFrm, 20, 20 )
+IMPL_FIXEDMEMPOOL_NEWDEL( SwHeaderFrm, 20, 20 )
+IMPL_FIXEDMEMPOOL_NEWDEL( SwFooterFrm, 20, 20 )
+IMPL_FIXEDMEMPOOL_NEWDEL( SwTxtFrm, 50, 50 )
+IMPL_FIXEDMEMPOOL_NEWDEL( SwTableFmt, 10, 10 )
+IMPL_FIXEDMEMPOOL_NEWDEL( SwTableLineFmt, 10, 10 )
+IMPL_FIXEDMEMPOOL_NEWDEL( SwTableBoxFmt, 50, 50 )
+IMPL_FIXEDMEMPOOL_NEWDEL( _SwCursor_SavePos, 20, 20 )
+
+
+Size GetGraphicSizeTwip( const Graphic& rGraphic, OutputDevice* pOutDev )
+{
+ const MapMode aMapTwip( MAP_TWIP );
+ Size aSize( rGraphic.GetPrefSize() );
+ if( MAP_PIXEL == rGraphic.GetPrefMapMode().GetMapUnit() )
+ {
+ if( !pOutDev )
+ pOutDev = Application::GetDefaultDevice();
+ aSize = pOutDev->PixelToLogic( aSize, aMapTwip );
+ }
+ else
+ aSize = OutputDevice::LogicToLogic( aSize,
+ rGraphic.GetPrefMapMode(), aMapTwip );
+ return aSize;
+}
+
+
+uno::Reference< linguistic2::XSpellChecker1 > GetSpellChecker()
+{
+ return LinguMgr::GetSpellChecker();
+}
+
+
+uno::Reference< linguistic2::XHyphenator > GetHyphenator()
+{
+ return LinguMgr::GetHyphenator();
+}
+
+
+uno::Reference< linguistic2::XThesaurus > GetThesaurus()
+{
+ return LinguMgr::GetThesaurus();
+}
+
+
+uno::Reference< beans::XPropertySet > GetLinguPropertySet()
+{
+ return LinguMgr::GetLinguPropertySet();
+}
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/bastyp/tabcol.cxx b/sw/source/core/bastyp/tabcol.cxx
new file mode 100644
index 000000000000..bf6a87dfd331
--- /dev/null
+++ b/sw/source/core/bastyp/tabcol.cxx
@@ -0,0 +1,143 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+#include <osl/diagnose.h>
+#include "tabcol.hxx"
+
+#include <limits.h> //for LONG_MAX
+
+SwTabCols::SwTabCols( sal_uInt16 nSize ) :
+ nLeftMin( 0 ),
+ nLeft( 0 ),
+ nRight( 0 ),
+ nRightMax( 0 ),
+ bLastRowAllowedToChange( true )
+{
+ if ( nSize )
+ aData.reserve( nSize );
+}
+
+SwTabCols::SwTabCols( const SwTabCols& rCpy ) :
+ nLeftMin( rCpy.GetLeftMin() ),
+ nLeft( rCpy.GetLeft() ),
+ nRight( rCpy.GetRight() ),
+ nRightMax( rCpy.GetRightMax() ),
+ bLastRowAllowedToChange( rCpy.IsLastRowAllowedToChange() ),
+ aData( rCpy.GetData() )
+{
+#if OSL_DEBUG_LEVEL > 1
+ for ( sal_uInt16 i = 0; i < Count(); ++i )
+ {
+ SwTabColsEntry aEntry1 = aData[i];
+ SwTabColsEntry aEntry2 = rCpy.GetData()[i];
+ (void) aEntry1;
+ (void) aEntry2;
+ OSL_ENSURE( aEntry1.nPos == aEntry2.nPos &&
+ aEntry1.nMin == aEntry2.nMin &&
+ aEntry1.nMax == aEntry2.nMax &&
+ aEntry1.bHidden == aEntry2.bHidden,
+ "CopyContructor of SwTabColsEntries did not succeed!" );
+ }
+#endif
+}
+
+SwTabCols &SwTabCols::operator=( const SwTabCols& rCpy )
+{
+ nLeftMin = rCpy.GetLeftMin();
+ nLeft = rCpy.GetLeft();
+ nRight = rCpy.GetRight();
+ nRightMax= rCpy.GetRightMax();
+ bLastRowAllowedToChange = rCpy.IsLastRowAllowedToChange();
+
+ Remove( 0, Count() );
+ aData = rCpy.GetData();
+
+ return *this;
+}
+
+sal_Bool SwTabCols::operator==( const SwTabCols& rCmp ) const
+{
+ sal_uInt16 i;
+
+ if ( !(nLeftMin == rCmp.GetLeftMin() &&
+ nLeft == rCmp.GetLeft() &&
+ nRight == rCmp.GetRight() &&
+ nRightMax== rCmp.GetRightMax()&&
+ bLastRowAllowedToChange== rCmp.IsLastRowAllowedToChange() &&
+ Count()== rCmp.Count()) )
+ return sal_False;
+
+ for ( i = 0; i < Count(); ++i )
+ {
+ SwTabColsEntry aEntry1 = aData[i];
+ SwTabColsEntry aEntry2 = rCmp.GetData()[i];
+ if ( aEntry1.nPos != aEntry2.nPos || aEntry1.bHidden != aEntry2.bHidden )
+ return sal_False;
+ }
+
+ return sal_True;
+}
+
+void SwTabCols::Insert( long nValue, long nMin, long nMax, sal_Bool bValue, sal_uInt16 nPos )
+{
+ SwTabColsEntry aEntry;
+ aEntry.nPos = nValue;
+ aEntry.nMin = nMin;
+ aEntry.nMax = nMax;
+ aEntry.bHidden = bValue;
+ aData.insert( aData.begin() + nPos, aEntry );
+}
+
+void SwTabCols::Insert( long nValue, sal_Bool bValue, sal_uInt16 nPos )
+{
+ SwTabColsEntry aEntry;
+ aEntry.nPos = nValue;
+ aEntry.nMin = 0;
+ aEntry.nMax = LONG_MAX;
+ aEntry.bHidden = bValue;
+ aData.insert( aData.begin() + nPos, aEntry );
+
+#if OSL_DEBUG_LEVEL > 1
+ SwTabColsEntries::iterator aPos = aData.begin();
+ for ( ; aPos != aData.end(); ++aPos )
+ {
+ aEntry =(*aPos);
+ }
+#endif
+}
+
+void SwTabCols::Remove( sal_uInt16 nPos, sal_uInt16 nAnz )
+{
+ SwTabColsEntries::iterator aStart = aData.begin() + nPos;
+ aData.erase( aStart, aStart + nAnz );
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/crsr/BlockCursor.cxx b/sw/source/core/crsr/BlockCursor.cxx
new file mode 100644
index 000000000000..45e5c0c7291e
--- /dev/null
+++ b/sw/source/core/crsr/BlockCursor.cxx
@@ -0,0 +1,108 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+#include <IBlockCursor.hxx>
+#include <viscrs.hxx>
+#include "BlockCursor.hxx"
+
+/** The implementation of the block cursor interface
+
+ It's simply an aggregation of a SwShellCrsr and a rectangle defined by
+ a start and an end point.
+*/
+class SwBlockCursor : public IBlockCursor
+{
+ SwShellCrsr aCursor;
+ Point *pStartPt;
+ Point *pEndPt;
+public:
+ SwBlockCursor( const SwCrsrShell& rCrsrSh, const SwPosition &rPos ) :
+ aCursor( rCrsrSh, rPos ), pStartPt(0), pEndPt(0) {}
+ virtual SwShellCrsr& getShellCrsr();
+ virtual void setStartPoint( const Point &rPt );
+ virtual void setEndPoint( const Point &rPt );
+ virtual const Point* getStartPoint() const;
+ virtual const Point* getEndPoint() const;
+ virtual void clearPoints();
+ virtual ~SwBlockCursor();
+};
+
+SwBlockCursor::~SwBlockCursor()
+{
+ delete pStartPt;
+ delete pEndPt;
+}
+
+SwShellCrsr& SwBlockCursor::getShellCrsr()
+{
+ return aCursor;
+}
+
+void SwBlockCursor::setStartPoint( const Point &rPt )
+{
+ if( pStartPt )
+ *pStartPt = rPt;
+ else
+ pStartPt = new Point( rPt );
+}
+
+void SwBlockCursor::setEndPoint( const Point &rPt )
+{
+ if( pEndPt )
+ *pEndPt = rPt;
+ else
+ pEndPt = new Point( rPt );
+}
+
+const Point* SwBlockCursor::getStartPoint() const
+{
+ return pStartPt;
+}
+
+const Point* SwBlockCursor::getEndPoint() const
+{
+ return pEndPt;
+}
+
+void SwBlockCursor::clearPoints()
+{
+ delete pStartPt;
+ delete pEndPt;
+ pStartPt = 0;
+ pEndPt = 0;
+}
+
+IBlockCursor *createBlockCursor( const SwCrsrShell& rCrsrSh, const SwPosition &rPos )
+{
+ return new SwBlockCursor( rCrsrSh, rPos );
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/crsr/BlockCursor.hxx b/sw/source/core/crsr/BlockCursor.hxx
new file mode 100644
index 000000000000..aced7c582cd1
--- /dev/null
+++ b/sw/source/core/crsr/BlockCursor.hxx
@@ -0,0 +1,39 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+#ifndef _BLOCKCURSOR_HXX
+#define _BLOCKCURSOR_HXX
+
+class IBlockCursor;
+class SwCrsrShell;
+struct SwPosition;
+
+IBlockCursor *createBlockCursor(const SwCrsrShell& rCrsrSh, const SwPosition &rPos);
+
+#endif //_BLOCKURSOR_HXX
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/crsr/IBlockCursor.hxx b/sw/source/core/crsr/IBlockCursor.hxx
new file mode 100644
index 000000000000..da3c3c3ef383
--- /dev/null
+++ b/sw/source/core/crsr/IBlockCursor.hxx
@@ -0,0 +1,97 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef IBLOCKCURSOR_HXX_INCLUDED
+#define IBLOCKCURSOR_HXX_INCLUDED
+
+class SwShellCrsr;
+class Point;
+
+ /** Access to the block cursor
+
+ A block cursor contains a SwShellCrsr and additional information about
+ the rectangle which has been created by pressing the mouse button and
+ moving the mouse.
+ This interface provides access to the SwShellCrsr and to start and end
+ point of the mouse movement.
+ */
+ class IBlockCursor
+ {
+ public:
+/** Access to the shell cursor
+
+ @return SwShellCrsr& which represents the start and end position of the
+ current block selection
+*/
+ virtual SwShellCrsr& getShellCrsr() = 0;
+
+/** Defines the starting vertex of the block selection
+
+ @param rPt
+ rPt should contain the document coordinates of the mouse cursor when
+ the block selection starts (MouseButtonDown)
+*/
+ virtual void setStartPoint( const Point &rPt ) = 0;
+
+/** Defines the ending vertex of the block selection
+
+ @param rPt
+ rPt should contain the document coordinates of the mouse cursor when
+ the block selection has started and the mouse has been moved (MouseMove)
+*/
+ virtual void setEndPoint( const Point &rPt ) = 0;
+
+/** The document coordinates where the block selection has been started
+
+ @return 0, if no start point has been set
+*/
+ virtual const Point* getStartPoint() const = 0;
+
+
+/** The document coordinates where the block selection ends (at the moment)
+
+ @return 0, if no end point has been set
+*/
+ virtual const Point* getEndPoint() const = 0;
+
+/** Deletion of the mouse created rectangle
+
+ When start and end points exist, the block cursor depends on this. If the
+ cursor is moved by cursor keys (e.g. up/down, home/end) the mouse rectangle
+ is obsolet and has to be deleted.
+*/
+ virtual void clearPoints() = 0;
+
+/** Destructor of the block curosr interface
+*/
+ virtual ~IBlockCursor() {};
+ };
+
+#endif // IBLOCKCURSOR_HXX_INCLUDED
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/crsr/bookmrk.cxx b/sw/source/core/crsr/bookmrk.cxx
new file mode 100644
index 000000000000..30039539de96
--- /dev/null
+++ b/sw/source/core/crsr/bookmrk.cxx
@@ -0,0 +1,371 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+
+#include <bookmrk.hxx>
+#include <IDocumentMarkAccess.hxx>
+#include <IDocumentUndoRedo.hxx>
+#include <doc.hxx>
+#include <ndtxt.hxx>
+#include <pam.hxx>
+#include <swserv.hxx>
+#include <sfx2/linkmgr.hxx>
+#include <swtypes.hxx>
+#include <UndoBookmark.hxx>
+#include <unobookmark.hxx>
+#include <rtl/random.h>
+#include <xmloff/odffields.hxx>
+
+
+SV_IMPL_REF( SwServerObject )
+
+using namespace ::sw::mark;
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::uno;
+
+namespace
+{
+ static void lcl_FixPosition(SwPosition& rPos)
+ {
+ // make sure the position has 1) the proper node, and 2) a proper index
+ SwTxtNode* pTxtNode = rPos.nNode.GetNode().GetTxtNode();
+ if(pTxtNode == NULL && rPos.nContent.GetIndex() > 0)
+ {
+ OSL_TRACE(
+ "bookmrk.cxx::lcl_FixPosition"
+ " - illegal position: %d without proper TxtNode", rPos.nContent.GetIndex());
+ rPos.nContent.Assign(NULL, 0);
+ }
+ else if(pTxtNode != NULL && rPos.nContent.GetIndex() > pTxtNode->Len())
+ {
+ OSL_TRACE(
+ "bookmrk.cxx::lcl_FixPosition"
+ " - illegal position: %d is beyond %d", rPos.nContent.GetIndex(), pTxtNode->Len());
+ rPos.nContent.Assign(pTxtNode, pTxtNode->Len());
+ }
+ };
+
+ static void lcl_AssureFieldMarksSet(Fieldmark* const pField,
+ SwDoc* const io_pDoc,
+ const sal_Unicode aStartMark,
+ const sal_Unicode aEndMark)
+ {
+ SwPosition& rStart = pField->GetMarkStart();
+ SwPosition& rEnd = pField->GetMarkEnd();
+ SwTxtNode const*const pStartTxtNode =
+ rStart.nNode.GetNode().GetTxtNode();
+ SwTxtNode const*const pEndTxtNode = rEnd.nNode.GetNode().GetTxtNode();
+ const sal_Unicode ch_start=pStartTxtNode->GetTxt().GetChar(rStart.nContent.GetIndex());
+ xub_StrLen nEndPos = rEnd == rStart ? rEnd.nContent.GetIndex() : rEnd.nContent.GetIndex() - 1;
+ const sal_Unicode ch_end=pEndTxtNode->GetTxt().GetChar( nEndPos );
+ SwPaM aStartPaM(rStart);
+ SwPaM aEndPaM(rEnd);
+ io_pDoc->GetIDocumentUndoRedo().StartUndo(UNDO_UI_REPLACE, NULL);
+ if( ( ch_start != aStartMark ) && ( aEndMark != CH_TXT_ATR_FORMELEMENT ) )
+ {
+ io_pDoc->InsertString(aStartPaM, aStartMark);
+ rStart.nContent--;
+ }
+ if ( aEndMark && ( ch_end != aEndMark ) )
+ {
+ io_pDoc->InsertString(aEndPaM, aEndMark);
+ rEnd.nContent++;
+ }
+ io_pDoc->GetIDocumentUndoRedo().EndUndo(UNDO_UI_REPLACE, NULL);
+ };
+}
+
+namespace sw { namespace mark
+{
+ MarkBase::MarkBase(const SwPaM& aPaM,
+ const ::rtl::OUString& rName)
+ : SwModify(0)
+ , m_pPos1(new SwPosition(*(aPaM.GetPoint())))
+ , m_aName(rName)
+ {
+ lcl_FixPosition(*m_pPos1);
+ if(aPaM.HasMark())
+ {
+ MarkBase::SetOtherMarkPos(*(aPaM.GetMark()));
+ lcl_FixPosition(*m_pPos2);
+ }
+ }
+
+ bool MarkBase::IsCoveringPosition(const SwPosition& rPos) const
+ {
+ return GetMarkStart() <= rPos && rPos < GetMarkEnd();
+ }
+
+ void MarkBase::SetMarkPos(const SwPosition& rNewPos)
+ {
+ ::boost::scoped_ptr<SwPosition>(new SwPosition(rNewPos)).swap(m_pPos1);
+ }
+
+ void MarkBase::SetOtherMarkPos(const SwPosition& rNewPos)
+ {
+ ::boost::scoped_ptr<SwPosition>(new SwPosition(rNewPos)).swap(m_pPos2);
+ }
+
+ rtl::OUString MarkBase::ToString( ) const
+ {
+ rtl::OUStringBuffer buf;
+ buf.appendAscii( "Mark: ( Name, [ Node1, Index1 ] ): ( " );
+ buf.append( m_aName ).appendAscii( ", [ " );
+ buf.append( sal_Int32( GetMarkPos().nNode.GetIndex( ) ) ).appendAscii( ", " );
+ buf.append( sal_Int32( GetMarkPos().nContent.GetIndex( ) ) ).appendAscii( " ] )" );
+
+ return buf.makeStringAndClear( );
+ }
+
+ MarkBase::~MarkBase()
+ { }
+
+ ::rtl::OUString MarkBase::GenerateNewName(const ::rtl::OUString& rPrefix)
+ {
+ static rtlRandomPool aPool = rtl_random_createPool();
+ static ::rtl::OUString sUniquePostfix;
+ static sal_Int32 nCount = SAL_MAX_INT32;
+ ::rtl::OUStringBuffer aResult(rPrefix);
+ if(nCount == SAL_MAX_INT32)
+ {
+ sal_Int32 nRandom;
+ ::rtl::OUStringBuffer sUniquePostfixBuffer;
+ rtl_random_getBytes(aPool, &nRandom, sizeof(nRandom));
+ sUniquePostfix = ::rtl::OUStringBuffer(13).appendAscii("_").append(static_cast<sal_Int32>(abs(nRandom))).makeStringAndClear();
+ nCount = 0;
+ }
+ // putting the counter in front of the random parts will speed up string comparisons
+ return aResult.append(nCount++).append(sUniquePostfix).makeStringAndClear();
+ }
+
+
+ void MarkBase::Modify( const SfxPoolItem *pOld, const SfxPoolItem *pNew )
+ {
+ NotifyClients(pOld, pNew);
+ if (pOld && (RES_REMOVE_UNO_OBJECT == pOld->Which()))
+ { // invalidate cached uno object
+ SetXBookmark(uno::Reference<text::XTextContent>(0));
+ }
+ }
+
+
+ NavigatorReminder::NavigatorReminder(const SwPaM& rPaM)
+ : MarkBase(rPaM, our_sNamePrefix)
+ { }
+
+ const ::rtl::OUString NavigatorReminder::our_sNamePrefix(RTL_CONSTASCII_USTRINGPARAM("__NavigatorReminder__"));
+
+ UnoMark::UnoMark(const SwPaM& aPaM)
+ : MarkBase(aPaM, MarkBase::GenerateNewName(our_sNamePrefix))
+ { }
+
+ const ::rtl::OUString UnoMark::our_sNamePrefix(RTL_CONSTASCII_USTRINGPARAM("__UnoMark__"));
+
+ DdeBookmark::DdeBookmark(const SwPaM& aPaM)
+ : MarkBase(aPaM, MarkBase::GenerateNewName(our_sNamePrefix))
+ , m_aRefObj(NULL)
+ { }
+
+ void DdeBookmark::SetRefObject(SwServerObject* pObj)
+ {
+ m_aRefObj = pObj;
+ }
+
+ const ::rtl::OUString DdeBookmark::our_sNamePrefix(RTL_CONSTASCII_USTRINGPARAM("__DdeLink__"));
+
+ void DdeBookmark::DeregisterFromDoc(SwDoc* const pDoc)
+ {
+ if(m_aRefObj.Is())
+ pDoc->GetLinkManager().RemoveServer(m_aRefObj);
+ }
+
+ DdeBookmark::~DdeBookmark()
+ {
+ if( m_aRefObj.Is() )
+ {
+ if(m_aRefObj->HasDataLinks())
+ {
+ ::sfx2::SvLinkSource* p = &m_aRefObj;
+ p->SendDataChanged();
+ }
+ m_aRefObj->SetNoServer();
+ }
+ }
+
+ Bookmark::Bookmark(const SwPaM& aPaM,
+ const KeyCode& rCode,
+ const ::rtl::OUString& rName,
+ const ::rtl::OUString& rShortName)
+ : DdeBookmark(aPaM)
+ , ::sfx2::Metadatable()
+ , m_aCode(rCode)
+ , m_sShortName(rShortName)
+ {
+ m_aName = rName;
+ }
+
+ void Bookmark::InitDoc(SwDoc* const io_pDoc)
+ {
+ if (io_pDoc->GetIDocumentUndoRedo().DoesUndo())
+ {
+ io_pDoc->GetIDocumentUndoRedo().AppendUndo(
+ new SwUndoInsBookmark(*this));
+ }
+ io_pDoc->SetModified();
+ }
+
+ // ::sfx2::Metadatable
+ ::sfx2::IXmlIdRegistry& Bookmark::GetRegistry()
+ {
+ SwDoc *const pDoc( GetMarkPos().GetDoc() );
+ OSL_ENSURE(pDoc, "Bookmark::MakeUnoObject: no doc?");
+ return pDoc->GetXmlIdRegistry();
+ }
+
+ bool Bookmark::IsInClipboard() const
+ {
+ SwDoc *const pDoc( GetMarkPos().GetDoc() );
+ OSL_ENSURE(pDoc, "Bookmark::IsInClipboard: no doc?");
+ return pDoc->IsClipBoard();
+ }
+
+ bool Bookmark::IsInUndo() const
+ {
+ return false;
+ }
+
+ bool Bookmark::IsInContent() const
+ {
+ SwDoc *const pDoc( GetMarkPos().GetDoc() );
+ OSL_ENSURE(pDoc, "Bookmark::IsInContent: no doc?");
+ return !pDoc->IsInHeaderFooter( SwNodeIndex(GetMarkPos().nNode) );
+ }
+
+ uno::Reference< rdf::XMetadatable > Bookmark::MakeUnoObject()
+ {
+ // create new SwXBookmark
+ SwDoc *const pDoc( GetMarkPos().GetDoc() );
+ OSL_ENSURE(pDoc, "Bookmark::MakeUnoObject: no doc?");
+ const uno::Reference< rdf::XMetadatable> xMeta(
+ SwXBookmark::CreateXBookmark(*pDoc, *this), uno::UNO_QUERY);
+ return xMeta;
+ }
+
+
+ Fieldmark::Fieldmark(const SwPaM& rPaM)
+ : MarkBase(rPaM, MarkBase::GenerateNewName(our_sNamePrefix))
+ {
+ if(!IsExpanded())
+ SetOtherMarkPos(GetMarkPos());
+ }
+
+ rtl::OUString Fieldmark::ToString( ) const
+ {
+ rtl::OUStringBuffer buf;
+ buf.appendAscii( "Fieldmark: ( Name, Type, [ Nd1, Id1 ], [ Nd2, Id2 ] ): ( " );
+ buf.append( m_aName ).appendAscii( ", " );
+ buf.append( m_aFieldname ).appendAscii( ", [ " );
+ buf.append( sal_Int32( GetMarkPos().nNode.GetIndex( ) ) ).appendAscii( ", " );
+ buf.append( sal_Int32( GetMarkPos( ).nContent.GetIndex( ) ) ).appendAscii( " ], [" );
+ buf.append( sal_Int32( GetOtherMarkPos().nNode.GetIndex( ) ) ).appendAscii( ", " );
+ buf.append( sal_Int32( GetOtherMarkPos( ).nContent.GetIndex( ) ) ).appendAscii( " ] ) " );
+
+ return buf.makeStringAndClear( );
+ }
+
+ void Fieldmark::Invalidate( )
+ {
+ // @TODO: Does exist a better solution to trigger a format of the
+ // fieldmark portion? If yes, please use it.
+ SwPaM aPaM( this->GetMarkPos(), this->GetOtherMarkPos() );
+ aPaM.InvalidatePaM();
+ }
+
+ const ::rtl::OUString Fieldmark::our_sNamePrefix(RTL_CONSTASCII_USTRINGPARAM("__Fieldmark__"));
+
+ TextFieldmark::TextFieldmark(const SwPaM& rPaM)
+ : Fieldmark(rPaM)
+ { }
+
+ void TextFieldmark::InitDoc(SwDoc* const io_pDoc)
+ {
+ lcl_AssureFieldMarksSet(this, io_pDoc, CH_TXT_ATR_FIELDSTART, CH_TXT_ATR_FIELDEND);
+ }
+
+ CheckboxFieldmark::CheckboxFieldmark(const SwPaM& rPaM)
+ : Fieldmark(rPaM)
+ { }
+
+ void CheckboxFieldmark::InitDoc(SwDoc* const io_pDoc)
+ {
+ lcl_AssureFieldMarksSet(this, io_pDoc, CH_TXT_ATR_FIELDSTART, CH_TXT_ATR_FORMELEMENT);
+
+ // For some reason the end mark is moved from 1 by the Insert: we don't
+ // want this for checkboxes
+ this->GetMarkEnd( ).nContent--;
+ }
+ void CheckboxFieldmark::SetChecked(bool checked)
+ {
+ if ( IsChecked() != checked )
+ {
+ (*GetParameters())[::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(ODF_FORMCHECKBOX_RESULT))] = makeAny(checked);
+ // mark document as modified
+ SwDoc *const pDoc( GetMarkPos().GetDoc() );
+ if ( pDoc )
+ pDoc->SetModified();
+ }
+ }
+
+ bool CheckboxFieldmark::IsChecked() const
+ {
+ bool bResult = false;
+ parameter_map_t::const_iterator pResult = GetParameters()->find(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(ODF_FORMCHECKBOX_RESULT)));
+ if(pResult != GetParameters()->end())
+ pResult->second >>= bResult;
+ return bResult;
+ }
+
+ rtl::OUString CheckboxFieldmark::toString( ) const
+ {
+ rtl::OUStringBuffer buf;
+ buf.appendAscii( "CheckboxFieldmark: ( Name, Type, [ Nd1, Id1 ], [ Nd2, Id2 ] ): ( " );
+ buf.append( m_aName ).appendAscii( ", " );
+ buf.append( GetFieldname() ).appendAscii( ", [ " );
+ buf.append( sal_Int32( GetMarkPos().nNode.GetIndex( ) ) ).appendAscii( ", " );
+ buf.append( sal_Int32( GetMarkPos( ).nContent.GetIndex( ) ) ).appendAscii( " ], [" );
+ buf.append( sal_Int32( GetOtherMarkPos().nNode.GetIndex( ) ) ).appendAscii( ", " );
+ buf.append( sal_Int32( GetOtherMarkPos( ).nContent.GetIndex( ) ) ).appendAscii( " ] ) " );
+
+ return buf.makeStringAndClear( );
+ }
+}}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/crsr/callnk.cxx b/sw/source/core/crsr/callnk.cxx
new file mode 100644
index 000000000000..56b1f6ce6785
--- /dev/null
+++ b/sw/source/core/crsr/callnk.cxx
@@ -0,0 +1,265 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+
+#include <hintids.hxx>
+
+#include <com/sun/star/i18n/ScriptType.hdl>
+#include <fmtcntnt.hxx>
+#include <txatbase.hxx>
+#include <frmatr.hxx>
+#include <viscrs.hxx>
+#include <callnk.hxx>
+#include <crsrsh.hxx>
+#include <doc.hxx>
+#include <frmfmt.hxx>
+#include <txtfrm.hxx>
+#include <tabfrm.hxx>
+#include <rowfrm.hxx>
+#include <fmtfsize.hxx>
+#include <ndtxt.hxx>
+#include <flyfrm.hxx>
+#include <breakit.hxx>
+
+#include<vcl/window.hxx>
+
+
+SwCallLink::SwCallLink( SwCrsrShell & rSh, sal_uLong nAktNode, xub_StrLen nAktCntnt,
+ sal_uInt8 nAktNdTyp, long nLRPos, bool bAktSelection )
+ : rShell( rSh ), nNode( nAktNode ), nCntnt( nAktCntnt ),
+ nNdTyp( nAktNdTyp ), nLeftFrmPos( nLRPos ),
+ bHasSelection( bAktSelection )
+{
+}
+
+
+SwCallLink::SwCallLink( SwCrsrShell & rSh )
+ : rShell( rSh )
+{
+ // remember SPoint-values of current cursor
+ SwPaM* pCrsr = rShell.IsTableMode() ? rShell.GetTblCrs() : rShell.GetCrsr();
+ SwNode& rNd = pCrsr->GetPoint()->nNode.GetNode();
+ nNode = rNd.GetIndex();
+ nCntnt = pCrsr->GetPoint()->nContent.GetIndex();
+ nNdTyp = rNd.GetNodeType();
+ bHasSelection = ( *pCrsr->GetPoint() != *pCrsr->GetMark() );
+
+ if( ND_TEXTNODE & nNdTyp )
+ nLeftFrmPos = SwCallLink::getLayoutFrm( rShell.GetLayout(), (SwTxtNode&)rNd, nCntnt,
+ !rShell.ActionPend() );
+ else
+ {
+ nLeftFrmPos = 0;
+
+ // A special treatment for SwFeShell:
+ // When deleting the header/footer, footnotes SwFeShell sets the
+ // Cursor to NULL (Node + Content).
+ // If the Cursor is not on a CntntNode (ContentNode) this fact gets
+ // saved in NdType.
+ if( ND_CONTENTNODE & nNdTyp )
+ nNdTyp = 0;
+ }
+}
+
+
+SwCallLink::~SwCallLink()
+{
+ if( !nNdTyp || !rShell.bCallChgLnk ) // see ctor
+ return ;
+
+ // If travelling over Nodes check formats and register them anew at the
+ // new Node.
+ SwPaM* pCurCrsr = rShell.IsTableMode() ? rShell.GetTblCrs() : rShell.GetCrsr();
+ SwCntntNode * pCNd = pCurCrsr->GetCntntNode();
+ if( !pCNd )
+ return;
+
+ SwFrm *myFrm = pCNd->getLayoutFrm( rShell.GetLayout() );
+ if (myFrm!=NULL)
+ {
+ // We need to emulated a change of the row height in order
+ // to have the complete row redrawn
+ SwRowFrm* pRow = myFrm->FindRowFrm( );
+ if ( pRow )
+ {
+ const SwTableLine* pLine = pRow->GetTabLine( );
+ SwFmtFrmSize pSize = pLine->GetFrmFmt( )->GetFrmSize( );
+ pRow->ModifyNotification( NULL, &pSize );
+ }
+ }
+
+ const SwDoc *pDoc=rShell.GetDoc();
+ const SwCntntNode *pNode = NULL;
+ if ( ( pDoc != NULL && nNode < pDoc->GetNodes( ).Count( ) ) )
+ {
+ pNode = pDoc->GetNodes()[nNode]->GetCntntNode();
+ }
+ if ( pNode != NULL )
+ {
+ SwFrm *myFrm2 = pNode->getLayoutFrm( rShell.GetLayout() );
+ if (myFrm2!=NULL)
+ {
+ // We need to emulated a change of the row height in order
+ // to have the complete row redrawn
+ SwRowFrm* pRow = myFrm2->FindRowFrm();
+ if ( pRow )
+ {
+ const SwTableLine* pLine = pRow->GetTabLine( );
+ SwFmtFrmSize pSize = pLine->GetFrmFmt( )->GetFrmSize( );
+ pRow->ModifyNotification( NULL, &pSize );
+ }
+ }
+ }
+
+ xub_StrLen nCmp, nAktCntnt = pCurCrsr->GetPoint()->nContent.GetIndex();
+ sal_uInt16 nNdWhich = pCNd->GetNodeType();
+ sal_uLong nAktNode = pCurCrsr->GetPoint()->nNode.GetIndex();
+
+ // Register the Shell as dependent at the current Node. By doing this all
+ // attribute changes can be signaled over the link.
+ pCNd->Add( &rShell );
+
+ if( nNdTyp != nNdWhich || nNode != nAktNode )
+ {
+ // Every time a switch between nodes occurs, there is a chance that
+ // new attributes do apply - meaning text-attributes.
+ // So the currently applying attributes would have to be determined.
+ // That can be done in one go by the handler.
+ rShell.CallChgLnk();
+ }
+ else if( !bHasSelection != !(*pCurCrsr->GetPoint() != *pCurCrsr->GetMark()) )
+ {
+ // always call change link when selection changes
+ rShell.CallChgLnk();
+ }
+ else if( rShell.aChgLnk.IsSet() && ND_TEXTNODE == nNdWhich &&
+ nCntnt != nAktCntnt )
+ {
+ // If travelling with left/right only and the frame is
+ // unchanged (columns!) then check text hints.
+ if( nLeftFrmPos == SwCallLink::getLayoutFrm( rShell.GetLayout(), (SwTxtNode&)*pCNd, nAktCntnt,
+ !rShell.ActionPend() ) &&
+ (( nCmp = nCntnt ) + 1 == nAktCntnt || // Right
+ nCntnt -1 == ( nCmp = nAktCntnt )) ) // Left
+ {
+ if( nCmp == nAktCntnt && pCurCrsr->HasMark() ) // left & select
+ ++nCmp;
+ if ( ((SwTxtNode*)pCNd)->HasHints() )
+ {
+
+ const SwpHints &rHts = ((SwTxtNode*)pCNd)->GetSwpHints();
+ sal_uInt16 n;
+ xub_StrLen nStart;
+ const xub_StrLen *pEnd;
+
+ for( n = 0; n < rHts.Count(); n++ )
+ {
+ const SwTxtAttr* pHt = rHts[ n ];
+ pEnd = pHt->GetEnd();
+ nStart = *pHt->GetStart();
+
+ // If "only start" or "start and end equal" then call on
+ // every overflow of start.
+ if( ( !pEnd || ( nStart == *pEnd ) ) &&
+ ( nStart == nCntnt || nStart == nAktCntnt) )
+ {
+ rShell.CallChgLnk();
+ return;
+ }
+
+ // If the attribute has an area and that area is not empty ...
+ else if( pEnd && nStart < *pEnd &&
+ // ... then test if travelling occurred via start/end.
+ ( nStart == nCmp ||
+ ( pHt->DontExpand() ? nCmp == *pEnd-1
+ : nCmp == *pEnd ) ))
+ {
+ rShell.CallChgLnk();
+ return;
+ }
+ nStart = 0;
+ }
+ }
+
+ if( pBreakIt->GetBreakIter().is() )
+ {
+ const String& rTxt = ((SwTxtNode*)pCNd)->GetTxt();
+ if( !nCmp ||
+ pBreakIt->GetBreakIter()->getScriptType( rTxt, nCmp )
+ != pBreakIt->GetBreakIter()->getScriptType( rTxt, nCmp - 1 ))
+ {
+ rShell.CallChgLnk();
+ return;
+ }
+ }
+ }
+ else
+ // If travelling more than one character with home/end/.. then
+ // always call ChgLnk, because it can not be determined here what
+ // has changed. Something may have changed.
+ rShell.CallChgLnk();
+ }
+
+ const SwFrm* pFrm;
+ const SwFlyFrm *pFlyFrm;
+ if( !rShell.ActionPend() && 0 != ( pFrm = pCNd->getLayoutFrm(rShell.GetLayout(),0,0,sal_False) ) &&
+ 0 != ( pFlyFrm = pFrm->FindFlyFrm() ) && !rShell.IsTableMode() )
+ {
+ const SwNodeIndex* pIndex = pFlyFrm->GetFmt()->GetCntnt().GetCntntIdx();
+ OSL_ENSURE( pIndex, "Fly ohne Cntnt" );
+
+ if (!pIndex)
+ return;
+
+ const SwNode& rStNd = pIndex->GetNode();
+
+ if( rStNd.EndOfSectionNode()->StartOfSectionIndex() > nNode ||
+ nNode > rStNd.EndOfSectionIndex() )
+ rShell.GetFlyMacroLnk().Call( (void*)pFlyFrm->GetFmt() );
+ }
+}
+
+long SwCallLink::getLayoutFrm( const SwRootFrm* pRoot, SwTxtNode& rNd, xub_StrLen nCntPos, sal_Bool bCalcFrm )
+{
+ SwTxtFrm* pFrm = (SwTxtFrm*)rNd.getLayoutFrm(pRoot,0,0,bCalcFrm), *pNext = pFrm;
+ if ( pFrm && !pFrm->IsHiddenNow() )
+ {
+ if( pFrm->HasFollow() )
+ while( 0 != ( pNext = (SwTxtFrm*)pFrm->GetFollow() ) &&
+ nCntPos >= pNext->GetOfst() )
+ pFrm = pNext;
+
+ return pFrm->Frm().Left();
+ }
+ return 0;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/crsr/callnk.hxx b/sw/source/core/crsr/callnk.hxx
new file mode 100644
index 000000000000..56aade636601
--- /dev/null
+++ b/sw/source/core/crsr/callnk.hxx
@@ -0,0 +1,60 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+#ifndef _CALLNK_HXX
+#define _CALLNK_HXX
+
+#include <tools/solar.h>
+
+class SwCrsrShell;
+class SwTxtNode;
+class SwRootFrm;
+
+class SwCallLink
+{
+public:
+ SwCrsrShell & rShell;
+ sal_uLong nNode;
+ xub_StrLen nCntnt;
+ sal_uInt8 nNdTyp;
+ long nLeftFrmPos;
+ bool bHasSelection;
+
+ SwCallLink( SwCrsrShell & rSh );
+ SwCallLink( SwCrsrShell & rSh, sal_uLong nAktNode, xub_StrLen nAktCntnt,
+ sal_uInt8 nAktNdTyp, long nLRPos,
+ bool bAktSelection );
+ ~SwCallLink();
+
+ static long getLayoutFrm( const SwRootFrm*, SwTxtNode& rNd, xub_StrLen nCntPos, sal_Bool bCalcFrm );
+};
+
+
+
+#endif // _CALLNK_HXX
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/crsr/crbm.cxx b/sw/source/core/crsr/crbm.cxx
new file mode 100644
index 000000000000..33a2c686ebaa
--- /dev/null
+++ b/sw/source/core/crsr/crbm.cxx
@@ -0,0 +1,263 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+
+#include "crsrsh.hxx"
+#include "ndtxt.hxx"
+#include <docary.hxx>
+#include <boost/bind.hpp>
+
+#include "IMark.hxx"
+#include "callnk.hxx"
+#include "swcrsr.hxx"
+#include <IDocumentMarkAccess.hxx>
+#include <IDocumentSettingAccess.hxx>
+
+using namespace std;
+
+namespace
+{
+ struct CrsrStateHelper
+ {
+ CrsrStateHelper(SwCrsrShell& rShell)
+ : m_aLink(rShell)
+ , m_pCrsr(rShell.GetSwCrsr())
+ , m_aSaveState(*m_pCrsr)
+ { }
+
+ void SetCrsrToMark(::sw::mark::IMark const * const pMark)
+ {
+ *(m_pCrsr->GetPoint()) = pMark->GetMarkStart();
+ if(pMark->IsExpanded())
+ {
+ m_pCrsr->SetMark();
+ *(m_pCrsr->GetMark()) = pMark->GetMarkEnd();
+ }
+ }
+
+ // returns true if the Cursor had been rolled back
+ bool RollbackIfIllegal()
+ {
+ if(m_pCrsr->IsSelOvr(nsSwCursorSelOverFlags::SELOVER_CHECKNODESSECTION
+ | nsSwCursorSelOverFlags::SELOVER_TOGGLE))
+ {
+ m_pCrsr->DeleteMark();
+ m_pCrsr->RestoreSavePos();
+ return true;
+ }
+ return false;
+ }
+
+ SwCallLink m_aLink;
+ SwCursor* m_pCrsr;
+ SwCrsrSaveState m_aSaveState;
+ };
+
+
+ static bool lcl_ReverseMarkOrderingByEnd(const IDocumentMarkAccess::pMark_t& rpFirst,
+ const IDocumentMarkAccess::pMark_t& rpSecond)
+ {
+ return rpFirst->GetMarkEnd() > rpSecond->GetMarkEnd();
+ }
+
+ static bool lcl_IsInvisibleBookmark(IDocumentMarkAccess::pMark_t pMark)
+ {
+ return IDocumentMarkAccess::GetType(*pMark) != IDocumentMarkAccess::BOOKMARK;
+ }
+}
+
+// at CurCrsr.SPoint
+::sw::mark::IMark* SwCrsrShell::SetBookmark(
+ const KeyCode& rCode,
+ const ::rtl::OUString& rName,
+ const ::rtl::OUString& rShortName,
+ IDocumentMarkAccess::MarkType eMark)
+{
+ StartAction();
+ ::sw::mark::IMark* pMark = getIDocumentMarkAccess()->makeMark(
+ *GetCrsr(),
+ rName,
+ eMark);
+ ::sw::mark::IBookmark* pBookmark = dynamic_cast< ::sw::mark::IBookmark* >(pMark);
+ if(pBookmark)
+ {
+ pBookmark->SetKeyCode(rCode);
+ pBookmark->SetShortName(rShortName);
+ }
+ EndAction();
+ return pMark;
+}
+// setzt CurCrsr.SPoint
+
+bool SwCrsrShell::GotoMark(const ::sw::mark::IMark* const pMark, bool bAtStart)
+{
+ // watch Crsr-Moves
+ CrsrStateHelper aCrsrSt(*this);
+ if ( bAtStart )
+ *(aCrsrSt.m_pCrsr)->GetPoint() = pMark->GetMarkStart();
+ else
+ *(aCrsrSt.m_pCrsr)->GetPoint() = pMark->GetMarkEnd();
+ if(aCrsrSt.RollbackIfIllegal()) return false;
+
+ UpdateCrsr(SwCrsrShell::SCROLLWIN|SwCrsrShell::CHKRANGE|SwCrsrShell::READONLY);
+ return true;
+}
+
+bool SwCrsrShell::GotoMark(const ::sw::mark::IMark* const pMark)
+{
+ // watch Crsr-Moves
+ CrsrStateHelper aCrsrSt(*this);
+ aCrsrSt.SetCrsrToMark(pMark);
+
+ if(aCrsrSt.RollbackIfIllegal()) return false;
+
+ UpdateCrsr(SwCrsrShell::SCROLLWIN|SwCrsrShell::CHKRANGE|SwCrsrShell::READONLY);
+ return true;
+}
+
+bool SwCrsrShell::GoNextBookmark()
+{
+ IDocumentMarkAccess* const pMarkAccess = getIDocumentMarkAccess();
+ IDocumentMarkAccess::container_t vCandidates;
+ remove_copy_if(
+ upper_bound(
+ pMarkAccess->getBookmarksBegin(),
+ pMarkAccess->getBookmarksEnd(),
+ *GetCrsr()->GetPoint(),
+ bind(&::sw::mark::IMark::StartsAfter, _2, _1)), // finds the first that is starting after
+ pMarkAccess->getBookmarksEnd(),
+ back_inserter(vCandidates),
+ &lcl_IsInvisibleBookmark);
+
+ // watch Crsr-Moves
+ CrsrStateHelper aCrsrSt(*this);
+ IDocumentMarkAccess::const_iterator_t ppMark = vCandidates.begin();
+ for(; ppMark!=vCandidates.end(); ++ppMark)
+ {
+ aCrsrSt.SetCrsrToMark(ppMark->get());
+ if(!aCrsrSt.RollbackIfIllegal())
+ break; // found legal move
+ }
+ if(ppMark==vCandidates.end())
+ {
+ SttEndDoc(false);
+ return false;
+ }
+
+ UpdateCrsr(SwCrsrShell::SCROLLWIN|SwCrsrShell::CHKRANGE|SwCrsrShell::READONLY);
+ return true;
+}
+
+bool SwCrsrShell::GoPrevBookmark()
+{
+ IDocumentMarkAccess* const pMarkAccess = getIDocumentMarkAccess();
+ // candidates from which to choose the mark before
+ // no need to consider marks starting after rPos
+ IDocumentMarkAccess::container_t vCandidates;
+ remove_copy_if(
+ pMarkAccess->getBookmarksBegin(),
+ upper_bound(
+ pMarkAccess->getBookmarksBegin(),
+ pMarkAccess->getBookmarksEnd(),
+ *GetCrsr()->GetPoint(),
+ bind(&::sw::mark::IMark::StartsAfter, _2, _1)),
+ back_inserter(vCandidates),
+ &lcl_IsInvisibleBookmark);
+ sort(
+ vCandidates.begin(),
+ vCandidates.end(),
+ &lcl_ReverseMarkOrderingByEnd);
+
+ // watch Crsr-Moves
+ CrsrStateHelper aCrsrSt(*this);
+ IDocumentMarkAccess::const_iterator_t ppMark = vCandidates.begin();
+ for(; ppMark!=vCandidates.end(); ++ppMark)
+ {
+ // ignoring those not ending before the Crsr
+ // (we were only able to eliminate those starting
+ // behind the Crsr by the upper_bound(..)
+ // above)
+ if(!(**ppMark).EndsBefore(*GetCrsr()->GetPoint()))
+ continue;
+ aCrsrSt.SetCrsrToMark(ppMark->get());
+ if(!aCrsrSt.RollbackIfIllegal())
+ break; // found legal move
+ }
+ if(ppMark==vCandidates.end())
+ {
+ SttEndDoc(true);
+ return false;
+ }
+
+ UpdateCrsr(SwCrsrShell::SCROLLWIN|SwCrsrShell::CHKRANGE|SwCrsrShell::READONLY);
+ return true;
+}
+
+bool SwCrsrShell::IsFormProtected()
+{
+ return getIDocumentSettingAccess()->get(IDocumentSettingAccess::PROTECT_FORM);
+}
+
+::sw::mark::IFieldmark* SwCrsrShell::GetCurrentFieldmark()
+{
+ // TODO: Refactor
+ SwPosition pos(*GetCrsr()->GetPoint());
+ return getIDocumentMarkAccess()->getFieldmarkFor(pos);
+}
+
+::sw::mark::IFieldmark* SwCrsrShell::GetFieldmarkAfter()
+{
+ SwPosition pos(*GetCrsr()->GetPoint());
+ return getIDocumentMarkAccess()->getFieldmarkAfter(pos);
+}
+
+::sw::mark::IFieldmark* SwCrsrShell::GetFieldmarkBefore()
+{
+ SwPosition pos(*GetCrsr()->GetPoint());
+ return getIDocumentMarkAccess()->getFieldmarkBefore(pos);
+}
+
+bool SwCrsrShell::GotoFieldmark(::sw::mark::IFieldmark const * const pMark)
+{
+ if(pMark==NULL) return false;
+
+ // watch Crsr-Moves
+ CrsrStateHelper aCrsrSt(*this);
+ aCrsrSt.SetCrsrToMark(pMark);
+ aCrsrSt.m_pCrsr->GetPoint()->nContent++;
+ aCrsrSt.m_pCrsr->GetMark()->nContent--;
+ if(aCrsrSt.RollbackIfIllegal()) return false;
+
+ UpdateCrsr(SwCrsrShell::SCROLLWIN|SwCrsrShell::CHKRANGE|SwCrsrShell::READONLY);
+ return true;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/crsr/crossrefbookmark.cxx b/sw/source/core/crsr/crossrefbookmark.cxx
new file mode 100644
index 000000000000..3f649ef7ed56
--- /dev/null
+++ b/sw/source/core/crsr/crossrefbookmark.cxx
@@ -0,0 +1,104 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+#include <crossrefbookmark.hxx>
+#include <ndtxt.hxx>
+
+using ::rtl::OUString;
+namespace sw { namespace mark
+{
+ CrossRefBookmark::CrossRefBookmark(const SwPaM& rPaM,
+ const KeyCode& rCode,
+ const OUString& rName,
+ const OUString& rShortName,
+ const OUString& rPrefix)
+ : Bookmark(rPaM, rCode, rName, rShortName)
+ {
+ if(rPaM.HasMark())
+ OSL_ENSURE((rPaM.GetMark()->nNode == rPaM.GetPoint()->nNode &&
+ rPaM.Start()->nContent.GetIndex() == 0 &&
+ rPaM.End()->nContent.GetIndex() == rPaM.GetPoint()->nNode.GetNode().GetTxtNode()->Len()),
+ "<CrossRefBookmark::CrossRefBookmark(..)>"
+ "- creation of cross-reference bookmark with an expanded PaM that does not expand over exactly one whole paragraph.");
+ SetMarkPos(*rPaM.Start());
+ if(!rName.getLength())
+ m_aName = MarkBase::GenerateNewName(rPrefix);
+ }
+
+ void CrossRefBookmark::SetMarkPos(const SwPosition& rNewPos)
+ {
+ OSL_PRECOND(rNewPos.nNode.GetNode().GetTxtNode(),
+ "<SwCrossRefBookmark::SetMarkPos(..)>"
+ " - new bookmark position for cross-reference bookmark doesn't mark text node");
+ OSL_PRECOND(rNewPos.nContent.GetIndex() == 0,
+ "<SwCrossRefBookmark::SetMarkPos(..)>"
+ " - new bookmark position for cross-reference bookmark doesn't mark start of text node");
+ MarkBase::SetMarkPos(rNewPos);
+ }
+
+ SwPosition& CrossRefBookmark::GetOtherMarkPos() const
+ {
+ OSL_PRECOND(false,
+ "<SwCrossRefBookmark::GetOtherMarkPos(..)>"
+ " - this should never be called!");
+ return *static_cast<SwPosition*>(NULL);
+ }
+
+ CrossRefHeadingBookmark::CrossRefHeadingBookmark(const SwPaM& rPaM,
+ const KeyCode& rCode,
+ const OUString& rName,
+ const OUString& rShortName)
+ : CrossRefBookmark(rPaM, rCode, rName, rShortName, our_sNamePrefix)
+ { }
+
+ const ::rtl::OUString CrossRefHeadingBookmark::our_sNamePrefix(RTL_CONSTASCII_USTRINGPARAM("__RefHeading__"));
+
+ bool CrossRefHeadingBookmark::IsLegalName(const ::rtl::OUString& rName)
+ {
+ return rName.match(our_sNamePrefix);
+ }
+
+ CrossRefNumItemBookmark::CrossRefNumItemBookmark(const SwPaM& rPaM,
+ const KeyCode& rCode,
+ const OUString& rName,
+ const OUString& rShortName)
+ : CrossRefBookmark(rPaM, rCode, rName, rShortName, our_sNamePrefix)
+ { }
+
+ const ::rtl::OUString CrossRefNumItemBookmark::our_sNamePrefix(RTL_CONSTASCII_USTRINGPARAM("__RefNumPara__"));
+
+ bool CrossRefNumItemBookmark::IsLegalName(const ::rtl::OUString& rName)
+ {
+ return rName.match(our_sNamePrefix);
+ }
+}}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/crsr/crsrsh.cxx b/sw/source/core/crsr/crsrsh.cxx
new file mode 100644
index 000000000000..a91ccd2ee847
--- /dev/null
+++ b/sw/source/core/crsr/crsrsh.cxx
@@ -0,0 +1,3439 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+#include <com/sun/star/util/SearchOptions.hpp>
+#include <com/sun/star/text/XTextRange.hpp>
+#include <hintids.hxx>
+#include <svx/svdmodel.hxx>
+#include <editeng/frmdiritem.hxx>
+
+#include <SwSmartTagMgr.hxx>
+#include <doc.hxx>
+#include <rootfrm.hxx>
+#include <pagefrm.hxx>
+#include <cntfrm.hxx>
+#include <viewimp.hxx>
+#include <pam.hxx>
+#include <swselectionlist.hxx>
+#include <IBlockCursor.hxx>
+#include "BlockCursor.hxx"
+#include <ndtxt.hxx>
+#include <flyfrm.hxx>
+#include <dview.hxx>
+#include <viewopt.hxx>
+#include <frmtool.hxx>
+#include <crsrsh.hxx>
+#include <tabfrm.hxx>
+#include <txtfrm.hxx>
+#include <sectfrm.hxx>
+#include <swtable.hxx>
+#include <callnk.hxx>
+#include <viscrs.hxx>
+#include <section.hxx>
+#include <docsh.hxx>
+#include <scriptinfo.hxx>
+#include <globdoc.hxx>
+#include <pamtyp.hxx>
+#include <mdiexp.hxx> // ...Percent()
+#include <fmteiro.hxx>
+#include <wrong.hxx> // SMARTTAGS
+#include <unotextrange.hxx> // SMARTTAGS
+#include <vcl/svapp.hxx>
+#include <numrule.hxx>
+#include <IGrammarContact.hxx>
+
+#include <globals.hrc>
+
+#include <comcore.hrc>
+
+using namespace com::sun::star;
+using namespace util;
+
+TYPEINIT2(SwCrsrShell,ViewShell,SwModify);
+
+
+// Funktion loescht, alle ueberlappenden Cursor aus einem Cursor-Ring
+void CheckRange( SwCursor* );
+
+//-----------------------------------------------------------------------
+
+/*
+ * Ueberpruefe ob der pCurCrsr in einen schon bestehenden Bereich zeigt.
+ * Wenn ja, dann hebe den alten Bereich auf.
+ */
+
+
+void CheckRange( SwCursor* pCurCrsr )
+{
+ const SwPosition *pStt = pCurCrsr->Start(),
+ *pEnd = pCurCrsr->GetPoint() == pStt ? pCurCrsr->GetMark() : pCurCrsr->GetPoint();
+
+ SwPaM *pTmpDel = 0,
+ *pTmp = (SwPaM*)pCurCrsr->GetNext();
+
+ // durchsuche den gesamten Ring
+ while( pTmp != pCurCrsr )
+ {
+ const SwPosition *pTmpStt = pTmp->Start(),
+ *pTmpEnd = pTmp->GetPoint() == pTmpStt ?
+ pTmp->GetMark() : pTmp->GetPoint();
+ if( *pStt <= *pTmpStt )
+ {
+ if( *pEnd > *pTmpStt ||
+ ( *pEnd == *pTmpStt && *pEnd == *pTmpEnd ))
+ pTmpDel = pTmp;
+ }
+ else
+ if( *pStt < *pTmpEnd )
+ pTmpDel = pTmp;
+ /*
+ * liegt ein SPoint oder GetMark innerhalb vom Crsr-Bereich
+ * muss der alte Bereich aufgehoben werden.
+ * Beim Vergleich ist darauf zu achten, das SPoint nicht mehr zum
+ * Bereich gehoert !
+ */
+ pTmp = (SwPaM*)pTmp->GetNext();
+ if( pTmpDel )
+ {
+ delete pTmpDel; // hebe alten Bereich auf
+ pTmpDel = 0;
+ }
+ }
+}
+
+// -------------- Methoden von der SwCrsrShell -------------
+
+SwPaM * SwCrsrShell::CreateCrsr()
+{
+ // Innerhalb der Tabellen-SSelection keinen neuen Crsr anlegen
+ OSL_ENSURE( !IsTableMode(), "in Tabellen SSelection" );
+
+ // neuen Cursor als Kopie vom akt. und in den Ring aufnehmen
+ // Verkettung zeigt immer auf den zuerst erzeugten, also vorwaerts
+ SwShellCrsr* pNew = new SwShellCrsr( *pCurCrsr );
+
+ // hier den akt. Pam nur logisch Hiden, weil sonst die Invertierung
+ // vom kopierten Pam aufgehoben wird !!
+
+ // #i75172#
+ pNew->swapContent(*pCurCrsr);
+
+ pCurCrsr->DeleteMark();
+
+ UpdateCrsr( SwCrsrShell::SCROLLWIN );
+// return pCurCrsr;
+ return pNew;
+}
+
+// loesche den aktuellen Cursor und der folgende wird zum Aktuellen
+
+
+sal_Bool SwCrsrShell::DestroyCrsr()
+{
+ // Innerhalb der Tabellen-SSelection keinen neuen Crsr loeschen
+ OSL_ENSURE( !IsTableMode(), "in Tabellen SSelection" );
+
+ // ist ueberhaupt ein naechtser vorhanden ?
+ if(pCurCrsr->GetNext() == pCurCrsr)
+ return sal_False;
+
+ SwCallLink aLk( *this ); // Crsr-Moves ueberwachen,
+ SwCursor* pNextCrsr = (SwCursor*)pCurCrsr->GetNext();
+ delete pCurCrsr;
+ pCurCrsr = dynamic_cast<SwShellCrsr*>(pNextCrsr);
+ UpdateCrsr();
+ return sal_True;
+}
+
+
+SwPaM & SwCrsrShell::CreateNewShellCursor()
+{
+ if (HasSelection())
+ {
+ (void) CreateCrsr(); // n.b. returns old cursor
+ }
+ return *GetCrsr();
+}
+
+SwPaM & SwCrsrShell::GetCurrentShellCursor()
+{
+ return *GetCrsr();
+}
+
+
+// gebe den aktuellen zurueck
+
+SwPaM* SwCrsrShell::GetCrsr( sal_Bool bMakeTblCrsr ) const
+{
+ if( pTblCrsr )
+ {
+ if( bMakeTblCrsr && pTblCrsr->IsCrsrMovedUpdt() )
+ {
+ // geparkte Cursor werden nicht wieder erzeugt
+ const SwCntntNode* pCNd;
+ if( pTblCrsr->GetPoint()->nNode.GetIndex() &&
+ pTblCrsr->GetMark()->nNode.GetIndex() &&
+ 0 != ( pCNd = pTblCrsr->GetCntntNode() ) && pCNd->getLayoutFrm( GetLayout() ) &&
+ 0 != ( pCNd = pTblCrsr->GetCntntNode(sal_False) ) && pCNd->getLayoutFrm( GetLayout() ) )
+ {
+ SwShellTableCrsr* pTC = (SwShellTableCrsr*)pTblCrsr;
+ GetLayout()->MakeTblCrsrs( *pTC );
+ }
+ }
+
+ if( pTblCrsr->IsChgd() )
+ {
+ const_cast<SwCrsrShell*>(this)->pCurCrsr =
+ dynamic_cast<SwShellCrsr*>(pTblCrsr->MakeBoxSels( pCurCrsr ));
+ }
+ }
+ return pCurCrsr;
+}
+
+
+void SwCrsrShell::StartAction()
+{
+ if( !ActionPend() )
+ {
+ // fuer das Update des Ribbon-Bars merken
+ const SwNode& rNd = pCurCrsr->GetPoint()->nNode.GetNode();
+ nAktNode = rNd.GetIndex();
+ nAktCntnt = pCurCrsr->GetPoint()->nContent.GetIndex();
+ nAktNdTyp = rNd.GetNodeType();
+ bAktSelection = *pCurCrsr->GetPoint() != *pCurCrsr->GetMark();
+ if( ND_TEXTNODE & nAktNdTyp )
+ nLeftFrmPos = SwCallLink::getLayoutFrm( GetLayout(), (SwTxtNode&)rNd, nAktCntnt, sal_True );
+ else
+ nLeftFrmPos = 0;
+ }
+ ViewShell::StartAction(); // zur ViewShell
+}
+
+
+void SwCrsrShell::EndAction( const sal_Bool bIdleEnd )
+{
+
+ sal_Bool bVis = bSVCrsrVis;
+
+ // Idle-Formatierung ?
+ if( bIdleEnd && Imp()->GetRegion() )
+ {
+ pCurCrsr->Hide();
+ }
+
+ // vor der letzten Action alle invaliden Numerierungen updaten
+ if( 1 == nStartAction )
+ GetDoc()->UpdateNumRule();
+
+ // Task: 76923: dont show the cursor in the ViewShell::EndAction() - call.
+ // Only the UpdateCrsr shows the cursor.
+ sal_Bool bSavSVCrsrVis = bSVCrsrVis;
+ bSVCrsrVis = sal_False;
+
+ ViewShell::EndAction( bIdleEnd ); //der ViewShell den Vortritt lassen
+
+ bSVCrsrVis = bSavSVCrsrVis;
+
+ if( ActionPend() )
+ {
+ if( bVis ) // auch SV-Cursor wieder anzeigen
+ pVisCrsr->Show();
+
+ // falls noch ein ChgCall vorhanden ist und nur noch die Basic
+ // Klammerung vorhanden ist, dann rufe ihn. Dadurch wird die interne
+ // mit der Basic-Klammerung entkoppelt; die Shells werden umgeschaltet
+ if( !BasicActionPend() )
+ {
+ // es muss innerhalb einer BasicAction
+ // der Cursor geupdatet werden; um z.B. den
+ // TabellenCursor zu erzeugen. Im UpdateCrsr wird
+ // das jetzt beruecksichtigt!
+ UpdateCrsr( SwCrsrShell::CHKRANGE, bIdleEnd );
+
+ {
+ // Crsr-Moves ueberwachen, evt. Link callen
+ // der DTOR ist das interressante!!
+ SwCallLink aLk( *this, nAktNode, nAktCntnt, (sal_uInt8)nAktNdTyp,
+ nLeftFrmPos, bAktSelection );
+
+ }
+ if( bCallChgLnk && bChgCallFlag && aChgLnk.IsSet() )
+ {
+ aChgLnk.Call( this );
+ bChgCallFlag = sal_False; // Flag zuruecksetzen
+ }
+ }
+ return;
+ }
+
+ sal_uInt16 nParm = SwCrsrShell::CHKRANGE;
+ if ( !bIdleEnd )
+ nParm |= SwCrsrShell::SCROLLWIN;
+// if( !IsViewLocked() )
+ UpdateCrsr( nParm, bIdleEnd ); // Cursor-Aenderungen anzeigen
+
+ {
+ SwCallLink aLk( *this ); // Crsr-Moves ueberwachen,
+ aLk.nNode = nAktNode; // evt. Link callen
+ aLk.nNdTyp = (sal_uInt8)nAktNdTyp;
+ aLk.nCntnt = nAktCntnt;
+ aLk.nLeftFrmPos = nLeftFrmPos;
+
+ if( !nCrsrMove ||
+ ( 1 == nCrsrMove && bInCMvVisportChgd ) )
+ ShowCrsrs( bSVCrsrVis ? sal_True : sal_False ); // Cursor & Selektionen wieder anzeigen
+ }
+ // falls noch ein ChgCall vorhanden ist, dann rufe ihn
+ if( bCallChgLnk && bChgCallFlag && aChgLnk.IsSet() )
+ {
+ aChgLnk.Call( this );
+ bChgCallFlag = sal_False; // Flag zuruecksetzen
+ }
+}
+
+
+#if OSL_DEBUG_LEVEL > 1
+
+void SwCrsrShell::SttCrsrMove()
+{
+ OSL_ENSURE( nCrsrMove < USHRT_MAX, "To many nested CrsrMoves." );
+ ++nCrsrMove;
+ StartAction();
+}
+
+void SwCrsrShell::EndCrsrMove( const sal_Bool bIdleEnd )
+{
+ OSL_ENSURE( nCrsrMove, "EndCrsrMove() ohne SttCrsrMove()." );
+ EndAction( bIdleEnd );
+ if( !--nCrsrMove )
+ bInCMvVisportChgd = sal_False;
+}
+
+#endif
+
+
+sal_Bool SwCrsrShell::LeftRight( sal_Bool bLeft, sal_uInt16 nCnt, sal_uInt16 nMode,
+ sal_Bool bVisualAllowed )
+{
+ if( IsTableMode() )
+ return bLeft ? GoPrevCell() : GoNextCell();
+
+ SwCallLink aLk( *this ); // Crsr-Moves ueberwachen, evt. Link callen
+ sal_Bool bRet = sal_False;
+
+ // #i27615# Handle cursor in front of label.
+ const SwTxtNode* pTxtNd = 0;
+
+ if( pBlockCrsr )
+ pBlockCrsr->clearPoints();
+
+ //
+ // 1. CASE: Cursor is in front of label. A move to the right
+ // will simply reset the bInFrontOfLabel flag:
+ //
+ SwShellCrsr* pShellCrsr = getShellCrsr( true );
+ if ( !bLeft && pShellCrsr->IsInFrontOfLabel() )
+ {
+ SetInFrontOfLabel( sal_False );
+ bRet = sal_True;
+ }
+ //
+ // 2. CASE: Cursor is at beginning of numbered paragraph. A move
+ // to the left will simply set the bInFrontOfLabel flag:
+ //
+ else if ( bLeft && 0 == pShellCrsr->GetPoint()->nContent.GetIndex() &&
+ !pShellCrsr->IsInFrontOfLabel() && !pShellCrsr->HasMark() &&
+ 0 != ( pTxtNd = pShellCrsr->GetNode()->GetTxtNode() ) &&
+ pTxtNd->HasVisibleNumberingOrBullet() )
+ {
+ SetInFrontOfLabel( sal_True );
+ bRet = sal_True;
+ }
+ //
+ // 3. CASE: Regular cursor move. Reset the bInFrontOfLabel flag:
+ //
+ else
+ {
+ const sal_Bool bSkipHidden = !GetViewOptions()->IsShowHiddenChar();
+ // #i107447#
+ // To avoid loop the reset of <bInFrontOfLabel> flag is no longer
+ // reflected in the return value <bRet>.
+ const bool bResetOfInFrontOfLabel = SetInFrontOfLabel( sal_False );
+ bRet = pShellCrsr->LeftRight( bLeft, nCnt, nMode, bVisualAllowed,
+ bSkipHidden, !IsOverwriteCrsr() );
+ if ( !bRet && bLeft && bResetOfInFrontOfLabel )
+ {
+ // undo reset of <bInFrontOfLabel> flag
+ SetInFrontOfLabel( sal_True );
+ }
+ }
+
+ if( bRet )
+ {
+ UpdateCrsr();
+ }
+ return bRet;
+}
+
+void SwCrsrShell::MarkListLevel( const String& sListId,
+ const int nListLevel )
+{
+ if ( sListId != sMarkedListId ||
+ nListLevel != nMarkedListLevel)
+ {
+ if ( sMarkedListId.Len() > 0 )
+ pDoc->MarkListLevel( sMarkedListId, nMarkedListLevel, sal_False );
+
+ if ( sListId.Len() > 0 )
+ {
+ pDoc->MarkListLevel( sListId, nListLevel, sal_True );
+ }
+
+ sMarkedListId = sListId;
+ nMarkedListLevel = nListLevel;
+ }
+}
+
+void SwCrsrShell::UpdateMarkedListLevel()
+{
+ SwTxtNode * pTxtNd = _GetCrsr()->GetNode()->GetTxtNode();
+
+ if ( pTxtNd )
+ {
+ if ( !pTxtNd->IsNumbered() )
+ {
+ pCurCrsr->_SetInFrontOfLabel( sal_False );
+ MarkListLevel( String(), 0 );
+ }
+ else if ( pCurCrsr->IsInFrontOfLabel() )
+ {
+ if ( pTxtNd->IsInList() )
+ {
+ OSL_ENSURE( pTxtNd->GetActualListLevel() >= 0 &&
+ pTxtNd->GetActualListLevel() < MAXLEVEL, "Which level?");
+ MarkListLevel( pTxtNd->GetListId(),
+ pTxtNd->GetActualListLevel() );
+ }
+ }
+ else
+ {
+ MarkListLevel( String(), 0 );
+ }
+ }
+}
+// <--
+
+sal_Bool SwCrsrShell::UpDown( sal_Bool bUp, sal_uInt16 nCnt )
+{
+ SET_CURR_SHELL( this );
+ SwCallLink aLk( *this ); // Crsr-Moves ueberwachen, evt. Link callen
+
+ sal_Bool bTableMode = IsTableMode();
+ SwShellCrsr* pTmpCrsr = getShellCrsr( true );
+
+ sal_Bool bRet = pTmpCrsr->UpDown( bUp, nCnt );
+ // #i40019# UpDown should always reset the bInFrontOfLabel flag:
+ bRet = SetInFrontOfLabel(sal_False) || bRet;
+
+ if( pBlockCrsr )
+ pBlockCrsr->clearPoints();
+
+ if( bRet )
+ {
+ eMvState = MV_UPDOWN; // Status fuers Crsr-Travelling - GetCrsrOfst
+ if( !ActionPend() )
+ {
+ CrsrFlag eUpdtMode = SwCrsrShell::SCROLLWIN;
+ if( !bTableMode )
+ eUpdtMode = (CrsrFlag) (eUpdtMode
+ | SwCrsrShell::UPDOWN | SwCrsrShell::CHKRANGE);
+ UpdateCrsr( static_cast<sal_uInt16>(eUpdtMode) );
+ }
+ }
+ return bRet;
+}
+
+
+sal_Bool SwCrsrShell::LRMargin( sal_Bool bLeft, sal_Bool bAPI)
+{
+ SwCallLink aLk( *this ); // Crsr-Moves ueberwachen, evt. Link callen
+ SET_CURR_SHELL( this );
+ eMvState = MV_LEFTMARGIN; // Status fuers Crsr-Travelling - GetCrsrOfst
+
+ const sal_Bool bTableMode = IsTableMode();
+ SwShellCrsr* pTmpCrsr = getShellCrsr( true );
+
+ if( pBlockCrsr )
+ pBlockCrsr->clearPoints();
+
+ const sal_Bool bWasAtLM =
+ ( 0 == _GetCrsr()->GetPoint()->nContent.GetIndex() );
+
+ sal_Bool bRet = pTmpCrsr->LeftRightMargin( bLeft, bAPI );
+
+ if ( bLeft && !bTableMode && bRet && bWasAtLM && !_GetCrsr()->HasMark() )
+ {
+ const SwTxtNode * pTxtNd = _GetCrsr()->GetNode()->GetTxtNode();
+ if ( pTxtNd && pTxtNd->HasVisibleNumberingOrBullet() )
+ SetInFrontOfLabel( sal_True );
+ }
+ else if ( !bLeft )
+ {
+ bRet = SetInFrontOfLabel( sal_False ) || bRet;
+ }
+
+ if( bRet )
+ {
+ UpdateCrsr();
+ }
+ return bRet;
+}
+
+sal_Bool SwCrsrShell::IsAtLRMargin( sal_Bool bLeft, sal_Bool bAPI ) const
+{
+ const SwShellCrsr* pTmpCrsr = getShellCrsr( true );
+ return pTmpCrsr->IsAtLeftRightMargin( bLeft, bAPI );
+}
+
+
+sal_Bool SwCrsrShell::SttEndDoc( sal_Bool bStt )
+{
+ SwCallLink aLk( *this ); // Crsr-Moves ueberwachen, evt. Link callen
+
+ SwShellCrsr* pTmpCrsr = pBlockCrsr ? &pBlockCrsr->getShellCrsr() : pCurCrsr;
+ sal_Bool bRet = pTmpCrsr->SttEndDoc( bStt );
+ if( bRet )
+ {
+ if( bStt )
+ pTmpCrsr->GetPtPos().Y() = 0; // expl. 0 setzen (TabellenHeader)
+ if( pBlockCrsr )
+ {
+ pBlockCrsr->clearPoints();
+ RefreshBlockCursor();
+ }
+
+ UpdateCrsr(SwCrsrShell::SCROLLWIN|SwCrsrShell::CHKRANGE|SwCrsrShell::READONLY);
+ }
+ return bRet;
+}
+
+void SwCrsrShell::ExtendedSelectAll()
+{
+ SwNodes& rNodes = GetDoc()->GetNodes();
+ SwPosition* pPos = pCurCrsr->GetPoint();
+ pPos->nNode = rNodes.GetEndOfPostIts();
+ pPos->nContent.Assign( rNodes.GoNext( &pPos->nNode ), 0 );
+ pPos = pCurCrsr->GetMark();
+ pPos->nNode = rNodes.GetEndOfContent();
+ SwCntntNode* pCNd = rNodes.GoPrevious( &pPos->nNode );
+ pPos->nContent.Assign( pCNd, pCNd ? pCNd->Len() : 0 );
+}
+
+sal_Bool SwCrsrShell::MovePage( SwWhichPage fnWhichPage, SwPosPage fnPosPage )
+{
+ sal_Bool bRet = sal_False;
+
+ // Springe beim Selektieren nie ueber Section-Grenzen !!
+ if( !pCurCrsr->HasMark() || !pCurCrsr->IsNoCntnt() )
+ {
+ SwCallLink aLk( *this ); // Crsr-Moves ueberwachen, evt. Link callen
+ SET_CURR_SHELL( this );
+
+ SwCrsrSaveState aSaveState( *pCurCrsr );
+ Point& rPt = pCurCrsr->GetPtPos();
+ SwCntntFrm * pFrm = pCurCrsr->GetCntntNode()->
+ getLayoutFrm( GetLayout(), &rPt, pCurCrsr->GetPoint(), sal_False );
+ if( pFrm && sal_True == ( bRet = GetFrmInPage( pFrm, fnWhichPage,
+ fnPosPage, pCurCrsr ) ) &&
+ !pCurCrsr->IsSelOvr( nsSwCursorSelOverFlags::SELOVER_TOGGLE |
+ nsSwCursorSelOverFlags::SELOVER_CHANGEPOS ))
+ UpdateCrsr();
+ else
+ bRet = sal_False;
+ }
+ return bRet;
+}
+
+
+sal_Bool SwCrsrShell::MovePara(SwWhichPara fnWhichPara, SwPosPara fnPosPara )
+{
+ SwCallLink aLk( *this ); // Crsr-Moves ueberwachen, evt. Link callen
+ SwCursor* pTmpCrsr = getShellCrsr( true );
+ sal_Bool bRet = pTmpCrsr->MovePara( fnWhichPara, fnPosPara );
+ if( bRet )
+ UpdateCrsr();
+ return bRet;
+}
+
+
+sal_Bool SwCrsrShell::MoveSection( SwWhichSection fnWhichSect,
+ SwPosSection fnPosSect)
+{
+ SwCallLink aLk( *this ); // Crsr-Moves ueberwachen, evt. Link callen
+ SwCursor* pTmpCrsr = getShellCrsr( true );
+ sal_Bool bRet = pTmpCrsr->MoveSection( fnWhichSect, fnPosSect );
+ if( bRet )
+ UpdateCrsr();
+ return bRet;
+
+}
+
+
+// Positionieren des Cursors
+
+
+SwFrm* lcl_IsInHeaderFooter( const SwNodeIndex& rIdx, Point& rPt )
+{
+ SwFrm* pFrm = 0;
+ SwCntntNode* pCNd = rIdx.GetNode().GetCntntNode();
+ if( pCNd )
+ {
+ pFrm = pCNd->getLayoutFrm( pCNd->GetDoc()->GetCurrentLayout(), &rPt, 0, sal_False )->GetUpper();
+ while( pFrm && !pFrm->IsHeaderFrm() && !pFrm->IsFooterFrm() )
+ pFrm = pFrm->IsFlyFrm() ? ((SwFlyFrm*)pFrm)->AnchorFrm()
+ : pFrm->GetUpper();
+ }
+ return pFrm;
+}
+
+sal_Bool SwCrsrShell::IsInHeaderFooter( sal_Bool* pbInHeader ) const
+{
+ Point aPt;
+ SwFrm* pFrm = ::lcl_IsInHeaderFooter( pCurCrsr->GetPoint()->nNode, aPt );
+ if( pFrm && pbInHeader )
+ *pbInHeader = pFrm->IsHeaderFrm();
+ return 0 != pFrm;
+}
+
+int SwCrsrShell::SetCrsr( const Point &rLPt, sal_Bool bOnlyText, bool bBlock )
+{
+ SET_CURR_SHELL( this );
+
+ SwShellCrsr* pCrsr = getShellCrsr( bBlock );
+ SwPosition aPos( *pCrsr->GetPoint() );
+ Point aPt( rLPt );
+ Point & rAktCrsrPt = pCrsr->GetPtPos();
+ SwCrsrMoveState aTmpState( IsTableMode() ? MV_TBLSEL :
+ bOnlyText ? MV_SETONLYTEXT : MV_NONE );
+ aTmpState.bSetInReadOnly = IsReadOnlyAvailable();
+
+ SwTxtNode * pTxtNd = pCrsr->GetNode()->GetTxtNode();
+
+ if ( pTxtNd && !IsTableMode() &&
+ // --> FME 2004-11-25 #i37515# No bInFrontOfLabel during selection
+ !pCrsr->HasMark() &&
+ // <--
+ pTxtNd->HasVisibleNumberingOrBullet() )
+ {
+ aTmpState.bInFrontOfLabel = sal_True; // #i27615#
+ }
+ else
+ {
+ aTmpState.bInFrontOfLabel = sal_False;
+ }
+
+ int bRet = CRSR_POSOLD |
+ ( GetLayout()->GetCrsrOfst( &aPos, aPt, &aTmpState )
+ ? 0 : CRSR_POSCHG );
+
+ const bool bOldInFrontOfLabel = IsInFrontOfLabel();
+ const bool bNewInFrontOfLabel = aTmpState.bInFrontOfLabel;
+
+ pCrsr->SetCrsrBidiLevel( aTmpState.nCursorBidiLevel );
+
+ if( MV_RIGHTMARGIN == aTmpState.eState )
+ eMvState = MV_RIGHTMARGIN;
+ // steht neu Pos im Header/Footer ?
+ SwFrm* pFrm = lcl_IsInHeaderFooter( aPos.nNode, aPt );
+ if( IsTableMode() && !pFrm && aPos.nNode.GetNode().StartOfSectionNode() ==
+ pCrsr->GetPoint()->nNode.GetNode().StartOfSectionNode() )
+ // gleiche Tabellenzelle und nicht im Header/Footer
+ // -> zurueck
+ return bRet;
+
+ if( pBlockCrsr && bBlock )
+ {
+ pBlockCrsr->setEndPoint( rLPt );
+ if( !pCrsr->HasMark() )
+ pBlockCrsr->setStartPoint( rLPt );
+ else if( !pBlockCrsr->getStartPoint() )
+ pBlockCrsr->setStartPoint( pCrsr->GetMkPos() );
+ }
+ if( !pCrsr->HasMark() )
+ {
+ // steht an der gleichen Position und wenn im Header/Footer,
+ // dann im gleichen
+ if( aPos == *pCrsr->GetPoint() &&
+ bOldInFrontOfLabel == bNewInFrontOfLabel )
+ {
+ if( pFrm )
+ {
+ if( pFrm->Frm().IsInside( rAktCrsrPt ))
+ return bRet;
+ }
+ else if( aPos.nNode.GetNode().IsCntntNode() )
+ {
+ // im gleichen Frame gelandet?
+ SwFrm* pOld = ((SwCntntNode&)aPos.nNode.GetNode()).getLayoutFrm(
+ GetLayout(), &aCharRect.Pos(), 0, sal_False );
+ SwFrm* pNew = ((SwCntntNode&)aPos.nNode.GetNode()).getLayoutFrm(
+ GetLayout(), &aPt, 0, sal_False );
+ if( pNew == pOld )
+ return bRet;
+ }
+ }
+ }
+ else
+ {
+ // SSelection ueber nicht erlaubte Sections oder wenn im Header/Footer
+ // dann in verschiedene
+ if( !CheckNodesRange( aPos.nNode, pCrsr->GetMark()->nNode, sal_True )
+ || ( pFrm && !pFrm->Frm().IsInside( pCrsr->GetMkPos() ) ))
+ return bRet;
+
+ // steht an der gleichen Position und nicht im Header/Footer
+ if( aPos == *pCrsr->GetPoint() )
+ return bRet;
+ }
+
+ SwCallLink aLk( *this ); // Crsr-Moves ueberwachen, evt. Link callen
+ SwCrsrSaveState aSaveState( *pCrsr );
+
+ *pCrsr->GetPoint() = aPos;
+ rAktCrsrPt = aPt;
+
+ // #i41424# Only update the marked number levels if necessary
+ // Force update of marked number levels if necessary.
+ if ( bNewInFrontOfLabel || bOldInFrontOfLabel )
+ pCurCrsr->_SetInFrontOfLabel( !bNewInFrontOfLabel );
+ SetInFrontOfLabel( bNewInFrontOfLabel );
+
+ if( !pCrsr->IsSelOvr( nsSwCursorSelOverFlags::SELOVER_CHANGEPOS ) )
+ {
+ sal_uInt16 nFlag = SwCrsrShell::SCROLLWIN | SwCrsrShell::CHKRANGE;
+ UpdateCrsr( nFlag );
+ bRet &= ~CRSR_POSOLD;
+ }
+ else if( bOnlyText && !pCurCrsr->HasMark() )
+ {
+ if( FindValidCntntNode( bOnlyText ) )
+ {
+ // Cursor in einen gueltigen Content stellen
+ if( aPos == *pCrsr->GetPoint() )
+ bRet = CRSR_POSOLD;
+ else
+ {
+ UpdateCrsr( SwCrsrShell::SCROLLWIN | SwCrsrShell::CHKRANGE );
+ bRet &= ~CRSR_POSOLD;
+ }
+ }
+ else
+ {
+ // es gibt keinen gueltigen Inhalt -> Cursor verstecken
+ pVisCrsr->Hide(); // sichtbaren Cursor immer verstecken
+ eMvState = MV_NONE; // Status fuers Crsr-Travelling
+ bAllProtect = sal_True;
+ if( GetDoc()->GetDocShell() )
+ {
+ GetDoc()->GetDocShell()->SetReadOnlyUI( sal_True );
+ CallChgLnk(); // UI bescheid sagen!
+ }
+ }
+ }
+
+ return bRet;
+}
+
+
+void SwCrsrShell::TblCrsrToCursor()
+{
+ OSL_ENSURE( pTblCrsr, "TblCrsrToCursor: Why?" );
+ delete pTblCrsr, pTblCrsr = 0;
+}
+
+void SwCrsrShell::BlockCrsrToCrsr()
+{
+ OSL_ENSURE( pBlockCrsr, "BlockCrsrToCrsr: Why?" );
+ if( pBlockCrsr && !HasSelection() )
+ {
+ SwPaM& rPam = pBlockCrsr->getShellCrsr();
+ pCurCrsr->SetMark();
+ *pCurCrsr->GetPoint() = *rPam.GetPoint();
+ if( rPam.HasMark() )
+ *pCurCrsr->GetMark() = *rPam.GetMark();
+ else
+ pCurCrsr->DeleteMark();
+ }
+ delete pBlockCrsr, pBlockCrsr = 0;
+}
+
+void SwCrsrShell::CrsrToBlockCrsr()
+{
+ if( !pBlockCrsr )
+ {
+ SwPosition aPos( *pCurCrsr->GetPoint() );
+ pBlockCrsr = createBlockCursor( *this, aPos );
+ SwShellCrsr &rBlock = pBlockCrsr->getShellCrsr();
+ rBlock.GetPtPos() = pCurCrsr->GetPtPos();
+ if( pCurCrsr->HasMark() )
+ {
+ rBlock.SetMark();
+ *rBlock.GetMark() = *pCurCrsr->GetMark();
+ rBlock.GetMkPos() = pCurCrsr->GetMkPos();
+ }
+ }
+ pBlockCrsr->clearPoints();
+ RefreshBlockCursor();
+}
+
+void SwCrsrShell::ClearMark()
+{
+ // ist ueberhaupt ein GetMark gesetzt ?
+ if( pTblCrsr )
+ {
+ while( pCurCrsr->GetNext() != pCurCrsr )
+ delete pCurCrsr->GetNext();
+ pTblCrsr->DeleteMark();
+
+ if( pCurCrsr->HasMark() )
+ {
+ // falls doch nicht alle Indizies richtig verschoben werden
+ // (z.B.: Kopf-/Fusszeile loeschen) den Content-Anteil vom
+ // Mark aufs Nodes-Array setzen
+ SwPosition& rPos = *pCurCrsr->GetMark();
+ rPos.nNode.Assign( pDoc->GetNodes(), 0 );
+ rPos.nContent.Assign( 0, 0 );
+ pCurCrsr->DeleteMark();
+ }
+
+ *pCurCrsr->GetPoint() = *pTblCrsr->GetPoint();
+ pCurCrsr->GetPtPos() = pTblCrsr->GetPtPos();
+ delete pTblCrsr, pTblCrsr = 0;
+ pCurCrsr->SwSelPaintRects::Show();
+ }
+ else
+ {
+ if( !pCurCrsr->HasMark() )
+ return;
+ // falls doch nicht alle Indizies richtig verschoben werden
+ // (z.B.: Kopf-/Fusszeile loeschen) den Content-Anteil vom
+ // Mark aufs Nodes-Array setzen
+ SwPosition& rPos = *pCurCrsr->GetMark();
+ rPos.nNode.Assign( pDoc->GetNodes(), 0 );
+ rPos.nContent.Assign( 0, 0 );
+ pCurCrsr->DeleteMark();
+ if( !nCrsrMove )
+ pCurCrsr->SwSelPaintRects::Show();
+ }
+}
+
+
+void SwCrsrShell::NormalizePam(sal_Bool bPointFirst)
+{
+ SwCallLink aLk( *this ); // Crsr-Moves ueberwachen, evt. Link callen
+ pCurCrsr->Normalize(bPointFirst);
+}
+
+void SwCrsrShell::SwapPam()
+{
+ SwCallLink aLk( *this ); // Crsr-Moves ueberwachen, evt. Link callen
+ pCurCrsr->Exchange();
+}
+
+
+// suche innerhalb der Selektierten-Bereiche nach einer Selektion, die
+// den angebenen SPoint umschliesst
+// Ist das Flag bTstOnly gesetzt, dann wird nur getestet, ob dort eine
+// SSelection besteht; des akt. Cursr wird nicht umgesetzt!
+// Ansonsten wird er auf die gewaehlte SSelection gesetzt.
+
+
+sal_Bool SwCrsrShell::ChgCurrPam( const Point & rPt,
+ sal_Bool bTstOnly, sal_Bool bTstHit )
+{
+ SET_CURR_SHELL( this );
+
+ // Pruefe ob der SPoint in einer Tabellen-Selektion liegt
+ if( bTstOnly && pTblCrsr )
+ return pTblCrsr->IsInside( rPt );
+
+ SwCallLink aLk( *this ); // Crsr-Moves ueberwachen, evt. Link callen
+ // Suche die Position rPt im Dokument
+ SwPosition aPtPos( *pCurCrsr->GetPoint() );
+ Point aPt( rPt );
+
+ SwCrsrMoveState aTmpState( MV_NONE );
+ aTmpState.bSetInReadOnly = IsReadOnlyAvailable();
+ if ( !GetLayout()->GetCrsrOfst( &aPtPos, aPt, &aTmpState ) && bTstHit )
+ return sal_False;
+
+ // suche in allen Selektionen nach dieser Position
+ SwShellCrsr* pCmp = (SwShellCrsr*)pCurCrsr; // sicher den Pointer auf Cursor
+ do {
+ if( pCmp->HasMark() &&
+ *pCmp->Start() <= aPtPos && *pCmp->End() > aPtPos )
+ {
+ if( bTstOnly || pCurCrsr == pCmp ) // ist der aktuelle.
+ return sal_True; // return ohne Update
+
+ pCurCrsr = pCmp;
+ UpdateCrsr(); // Cursor steht schon richtig
+ return sal_True;
+ }
+ } while( pCurCrsr !=
+ ( pCmp = dynamic_cast<SwShellCrsr*>(pCmp->GetNext()) ) );
+ return sal_False;
+}
+
+
+void SwCrsrShell::KillPams()
+{
+ // keiner zum loeschen vorhanden?
+ if( !pTblCrsr && !pBlockCrsr && pCurCrsr->GetNext() == pCurCrsr )
+ return;
+
+ while( pCurCrsr->GetNext() != pCurCrsr )
+ delete pCurCrsr->GetNext();
+ pCurCrsr->SetColumnSelection( false );
+
+ if( pTblCrsr )
+ {
+ // Cursor Ring loeschen
+ pCurCrsr->DeleteMark();
+ *pCurCrsr->GetPoint() = *pTblCrsr->GetPoint();
+ pCurCrsr->GetPtPos() = pTblCrsr->GetPtPos();
+ delete pTblCrsr;
+ pTblCrsr = 0;
+ }
+ else if( pBlockCrsr )
+ {
+ // delete the ring of cursors
+ pCurCrsr->DeleteMark();
+ SwShellCrsr &rBlock = pBlockCrsr->getShellCrsr();
+ *pCurCrsr->GetPoint() = *rBlock.GetPoint();
+ pCurCrsr->GetPtPos() = rBlock.GetPtPos();
+ rBlock.DeleteMark();
+ pBlockCrsr->clearPoints();
+ }
+ UpdateCrsr( SwCrsrShell::SCROLLWIN );
+}
+
+
+int SwCrsrShell::CompareCursor( CrsrCompareType eType ) const
+{
+ int nRet = 0;
+ const SwPosition *pFirst = 0, *pSecond = 0;
+ const SwPaM *pCur = GetCrsr(), *pStk = pCrsrStk;
+ if( CurrPtCurrMk != eType && pStk )
+ {
+ switch ( eType)
+ {
+ case StackPtStackMk:
+ pFirst = pStk->GetPoint();
+ pSecond = pStk->GetMark();
+ break;
+ case StackPtCurrPt:
+ pFirst = pStk->GetPoint();
+ pSecond = pCur->GetPoint();
+ break;
+ case StackPtCurrMk:
+ pFirst = pStk->GetPoint();
+ pSecond = pCur->GetMark();
+ break;
+ case StackMkCurrPt:
+ pFirst = pStk->GetMark();
+ pSecond = pCur->GetPoint();
+ break;
+ case StackMkCurrMk:
+ pFirst = pStk->GetMark();
+ pSecond = pStk->GetMark();
+ break;
+ case CurrPtCurrMk:
+ pFirst = pCur->GetPoint();
+ pSecond = pCur->GetMark();
+ break;
+ }
+ }
+ if( !pFirst || !pSecond )
+ nRet = INT_MAX;
+ else if( *pFirst < *pSecond )
+ nRet = -1;
+ else if( *pFirst == *pSecond )
+ nRet = 0;
+ else
+ nRet = 1;
+ return nRet;
+}
+
+
+sal_Bool SwCrsrShell::IsSttPara() const
+{ return( pCurCrsr->GetPoint()->nContent == 0 ? sal_True : sal_False ); }
+
+
+sal_Bool SwCrsrShell::IsEndPara() const
+{ return( pCurCrsr->GetPoint()->nContent == pCurCrsr->GetCntntNode()->Len() ? sal_True : sal_False ); }
+
+
+sal_Bool SwCrsrShell::IsInFrontOfLabel() const
+{
+ return pCurCrsr->IsInFrontOfLabel();
+}
+
+bool SwCrsrShell::SetInFrontOfLabel( sal_Bool bNew )
+{
+ if ( bNew != IsInFrontOfLabel() )
+ {
+ pCurCrsr->_SetInFrontOfLabel( bNew );
+ UpdateMarkedListLevel();
+ return true;
+ }
+ return false;
+}
+
+sal_Bool SwCrsrShell::GotoPage( sal_uInt16 nPage )
+{
+ SET_CURR_SHELL( this );
+ SwCallLink aLk( *this ); // Crsr-Moves ueberwachen, evt. Link callen
+ SwCrsrSaveState aSaveState( *pCurCrsr );
+ sal_Bool bRet = GetLayout()->SetCurrPage( pCurCrsr, nPage ) &&
+ !pCurCrsr->IsSelOvr( nsSwCursorSelOverFlags::SELOVER_TOGGLE |
+ nsSwCursorSelOverFlags::SELOVER_CHANGEPOS );
+ if( bRet )
+ UpdateCrsr(SwCrsrShell::SCROLLWIN|SwCrsrShell::CHKRANGE|SwCrsrShell::READONLY);
+ return bRet;
+}
+
+
+void SwCrsrShell::GetPageNum( sal_uInt16 &rnPhyNum, sal_uInt16 &rnVirtNum,
+ sal_Bool bAtCrsrPos, const sal_Bool bCalcFrm )
+{
+ SET_CURR_SHELL( this );
+ // Seitennummer: die erste sichtbare Seite oder die am Cursor
+ const SwCntntFrm* pCFrm;
+ const SwPageFrm *pPg = 0;
+
+ if( !bAtCrsrPos || 0 == (pCFrm = GetCurrFrm( bCalcFrm )) ||
+ 0 == (pPg = pCFrm->FindPageFrm()) )
+ {
+ pPg = Imp()->GetFirstVisPage();
+ while( pPg && pPg->IsEmptyPage() )
+ pPg = (const SwPageFrm *)pPg->GetNext();
+ }
+ // Abfrage auf pPg muss fuer den Sonderfall Writerstart mit
+ // standard.vor sein.
+ rnPhyNum = pPg? pPg->GetPhyPageNum() : 1;
+ rnVirtNum = pPg? pPg->GetVirtPageNum() : 1;
+}
+
+
+sal_uInt16 SwCrsrShell::GetNextPrevPageNum( sal_Bool bNext )
+{
+ SET_CURR_SHELL( this );
+
+ // Seitennummer: die erste sichtbare Seite oder die am Cursor
+ const SwPageFrm *pPg = Imp()->GetFirstVisPage();
+ if( pPg )
+ {
+ const SwTwips nPageTop = pPg->Frm().Top();
+
+ if( bNext )
+ {
+ // go to next view layout row:
+ do
+ {
+ pPg = (const SwPageFrm *)pPg->GetNext();
+ }
+ while( pPg && pPg->Frm().Top() == nPageTop );
+
+ while( pPg && pPg->IsEmptyPage() )
+ pPg = (const SwPageFrm *)pPg->GetNext();
+ }
+ else
+ {
+ // go to previous view layout row:
+ do
+ {
+ pPg = (const SwPageFrm *)pPg->GetPrev();
+ }
+ while( pPg && pPg->Frm().Top() == nPageTop );
+
+ while( pPg && pPg->IsEmptyPage() )
+ pPg = (const SwPageFrm *)pPg->GetPrev();
+ }
+ }
+ // Abfrage auf pPg muss fuer den Sonderfall Writerstart mit
+ // standard.vor sein.
+ return pPg ? pPg->GetPhyPageNum() : USHRT_MAX;
+}
+
+
+sal_uInt16 SwCrsrShell::GetPageCnt()
+{
+ SET_CURR_SHELL( this );
+ // gebe die Anzahl der Seiten zurueck
+ return GetLayout()->GetPageNum();
+}
+
+// Gehe zur naechsten SSelection
+
+
+sal_Bool SwCrsrShell::GoNextCrsr()
+{
+ // besteht ueberhaupt ein Ring ?
+ if( pCurCrsr->GetNext() == pCurCrsr )
+ return sal_False;
+
+ SET_CURR_SHELL( this );
+ SwCallLink aLk( *this ); // Crsr-Moves ueberwachen, evt. Link callen
+ pCurCrsr = dynamic_cast<SwShellCrsr*>(pCurCrsr->GetNext());
+
+ // Bug 24086: auch alle anderen anzeigen
+ if( !ActionPend() )
+ {
+ UpdateCrsr();
+ pCurCrsr->Show();
+ }
+ return sal_True;
+}
+
+// gehe zur vorherigen SSelection
+
+
+sal_Bool SwCrsrShell::GoPrevCrsr()
+{
+ // besteht ueberhaupt ein Ring ?
+ if( pCurCrsr->GetNext() == pCurCrsr )
+ return sal_False;
+
+ SET_CURR_SHELL( this );
+ SwCallLink aLk( *this ); // Crsr-Moves ueberwachen, evt. Link callen
+ pCurCrsr = dynamic_cast<SwShellCrsr*>(pCurCrsr->GetPrev());
+
+ // Bug 24086: auch alle anderen anzeigen
+ if( !ActionPend() )
+ {
+ UpdateCrsr();
+ pCurCrsr->Show();
+ }
+
+ return sal_True;
+}
+
+
+void SwCrsrShell::Paint( const Rectangle &rRect)
+{
+ SET_CURR_SHELL( this );
+
+ // beim Painten immer alle Cursor ausschalten
+ SwRect aRect( rRect );
+
+ sal_Bool bVis = sal_False;
+ // ist Cursor sichtbar, dann verstecke den SV-Cursor
+ if( pVisCrsr->IsVisible() && !aRect.IsOver( aCharRect ) ) //JP 18.06.97: ???
+ {
+ bVis = sal_True;
+ pVisCrsr->Hide();
+ }
+
+ // Bereich neu painten
+ ViewShell::Paint( rRect );
+
+ if( bHasFocus && !bBasicHideCrsr )
+ {
+ SwShellCrsr* pAktCrsr = pTblCrsr ? pTblCrsr : pCurCrsr;
+// pAktCrsr->Invalidate( aRect );
+ if( !ActionPend() )
+ {
+ // damit nicht rechts/unten die Raender abgeschnitten werden
+ pAktCrsr->Invalidate( VisArea() );
+ pAktCrsr->Show();
+ }
+ else
+ pAktCrsr->Invalidate( aRect );
+
+ }
+ if( bSVCrsrVis && bVis ) // auch SV-Cursor wieder anzeigen
+ pVisCrsr->Show();
+}
+
+
+
+void SwCrsrShell::VisPortChgd( const SwRect & rRect )
+{
+ SET_CURR_SHELL( this );
+ sal_Bool bVis; // beim Scrollen immer alle Cursor ausschalten
+
+ // ist Cursor sichtbar, dann verstecke den SV-Cursor
+ if( sal_True == ( bVis = pVisCrsr->IsVisible() ))
+ pVisCrsr->Hide();
+
+ bVisPortChgd = sal_True;
+ aOldRBPos.X() = VisArea().Right();
+ aOldRBPos.Y() = VisArea().Bottom();
+
+ //Damit es es keine Probleme mit dem SV-Cursor gibt, wird in
+ //ViewShell::VisPo.. ein Update() auf das Window gerufen.
+ //Waehrend des Paintens duerfen aber nun wieder keine Selectionen
+ //angezeigt werden, deshalb wird der Aufruf hier geklammert.
+ ViewShell::VisPortChgd( rRect ); // Bereich verschieben
+
+ if( bSVCrsrVis && bVis ) // auch SV-Cursor wieder anzeigen
+ pVisCrsr->Show();
+
+ if( nCrsrMove )
+ bInCMvVisportChgd = sal_True;
+
+ bVisPortChgd = sal_False;
+}
+
+// aktualisiere den Crsrs, d.H. setze ihn wieder in den Content.
+// Das sollte nur aufgerufen werden, wenn der Cursor z.B. beim
+// Loeschen von Rahmen irgendwohin gesetzt wurde. Die Position
+// ergibt sich aus seiner aktuellen Position im Layout !!
+
+
+void SwCrsrShell::UpdateCrsrPos()
+{
+ SET_CURR_SHELL( this );
+ ++nStartAction;
+ SwShellCrsr* pShellCrsr = getShellCrsr( true );
+ Size aOldSz( GetDocSize() );
+ SwCntntNode *pCNode = pShellCrsr->GetCntntNode();
+ SwCntntFrm *pFrm = pCNode ?
+ pCNode->getLayoutFrm( GetLayout(), &pShellCrsr->GetPtPos(), pShellCrsr->GetPoint(), sal_False ) :0;
+ if( !pFrm || (pFrm->IsTxtFrm() && ((SwTxtFrm*)pFrm)->IsHiddenNow()) )
+ {
+ SwCrsrMoveState aTmpState( MV_NONE );
+ aTmpState.bSetInReadOnly = IsReadOnlyAvailable();
+ GetLayout()->GetCrsrOfst( pShellCrsr->GetPoint(), pShellCrsr->GetPtPos(),
+ &aTmpState );
+ if( pShellCrsr->HasMark())
+ pShellCrsr->DeleteMark();
+ }
+ IGrammarContact *pGrammarContact = GetDoc() ? GetDoc()->getGrammarContact() : 0;
+ if( pGrammarContact )
+ pGrammarContact->updateCursorPosition( *pCurCrsr->GetPoint() );
+ --nStartAction;
+ if( aOldSz != GetDocSize() )
+ SizeChgNotify();
+}
+
+// JP 30.04.99: Bug 65475 - falls Point/Mark in versteckten Bereichen
+// stehen, so mussen diese daraus verschoben werden
+static void lcl_CheckHiddenSection( SwNodeIndex& rIdx )
+{
+ const SwSectionNode* pSectNd = rIdx.GetNode().FindSectionNode();
+ if( pSectNd && pSectNd->GetSection().IsHiddenFlag() )
+ {
+ SwNodeIndex aTmp( *pSectNd );
+#if OSL_DEBUG_LEVEL > 1
+ const SwNode* pFrmNd =
+#endif
+ rIdx.GetNodes().FindPrvNxtFrmNode( aTmp, pSectNd->EndOfSectionNode() );
+
+#if OSL_DEBUG_LEVEL > 1
+ (void) pFrmNd;
+ OSL_ENSURE( pFrmNd, "keinen Node mit Frames gefunden" );
+#endif
+ rIdx = aTmp;
+ }
+}
+
+// Try to set the cursor to the next visible content node.
+static void lcl_CheckHiddenPara( SwPosition& rPos )
+{
+ SwNodeIndex aTmp( rPos.nNode );
+ SwTxtNode* pTxtNd = aTmp.GetNode().GetTxtNode();
+ while( pTxtNd && pTxtNd->HasHiddenCharAttribute( true ) )
+ {
+ SwCntntNode* pCntnt = aTmp.GetNodes().GoNext( &aTmp );
+ if ( pCntnt && pCntnt->IsTxtNode() )
+ pTxtNd = (SwTxtNode*)pCntnt;
+ else
+ pTxtNd = 0;
+ }
+
+ if ( pTxtNd )
+ rPos = SwPosition( aTmp, SwIndex( pTxtNd, 0 ) );
+}
+
+// #i27301# - helper class, which notifies the accessibility about invalid text
+// selections in its destructor
+class SwNotifyAccAboutInvalidTextSelections
+{
+ private:
+ SwCrsrShell& mrCrsrSh;
+
+ public:
+ SwNotifyAccAboutInvalidTextSelections( SwCrsrShell& _rCrsrSh )
+ : mrCrsrSh( _rCrsrSh )
+ {}
+
+ ~SwNotifyAccAboutInvalidTextSelections()
+ {
+ mrCrsrSh.InvalidateAccessibleParaTextSelection();
+ }
+};
+// <--
+void SwCrsrShell::UpdateCrsr( sal_uInt16 eFlags, sal_Bool bIdleEnd )
+{
+ SET_CURR_SHELL( this );
+
+ ClearUpCrsrs();
+
+ // es muss innerhalb einer BasicAction der
+ // Cursor geupdatet werden; um z.B. den TabellenCursor zu
+ // erzeugen. Im EndAction wird jetzt das UpdateCrsr gerufen!
+ if( ActionPend() && BasicActionPend() )
+ {
+ if ( eFlags & SwCrsrShell::READONLY )
+ bIgnoreReadonly = sal_True;
+ return; // wenn nicht, dann kein Update !!
+ }
+
+ // #i27301#
+ SwNotifyAccAboutInvalidTextSelections aInvalidateTextSelections( *this );
+
+ if ( bIgnoreReadonly )
+ {
+ bIgnoreReadonly = sal_False;
+ eFlags |= SwCrsrShell::READONLY;
+ }
+
+ if( eFlags & SwCrsrShell::CHKRANGE ) // alle Cursor-Bewegungen auf
+ CheckRange( pCurCrsr ); // ueberlappende Bereiche testen
+
+ if( !bIdleEnd )
+ CheckTblBoxCntnt();
+
+ // steht der akt. Crsr in einer Tabelle und in unterschiedlichen Boxen
+ // (oder ist noch TabellenMode), dann gilt der Tabellen Mode
+ SwPaM* pTstCrsr = getShellCrsr( true );
+ if( pTstCrsr->HasMark() && !pBlockCrsr &&
+ pDoc->IsIdxInTbl( pTstCrsr->GetPoint()->nNode ) &&
+ ( pTblCrsr ||
+ pTstCrsr->GetNode( sal_True )->StartOfSectionNode() !=
+ pTstCrsr->GetNode( sal_False )->StartOfSectionNode() ) )
+ {
+ SwShellCrsr* pITmpCrsr = getShellCrsr( true );
+ Point aTmpPt( pITmpCrsr->GetPtPos() );
+ Point aTmpMk( pITmpCrsr->GetMkPos() );
+ SwPosition* pPos = pITmpCrsr->GetPoint();
+
+ // JP 30.04.99: Bug 65475 - falls Point/Mark in versteckten Bereichen
+ // stehen, so mussen diese daraus verschoben werden
+ lcl_CheckHiddenSection( pPos->nNode );
+ lcl_CheckHiddenSection( pITmpCrsr->GetMark()->nNode );
+
+ // Move cursor out of hidden paragraphs
+ if ( !GetViewOptions()->IsShowHiddenChar() )
+ {
+ lcl_CheckHiddenPara( *pPos );
+ lcl_CheckHiddenPara( *pITmpCrsr->GetMark() );
+ }
+
+ SwCntntFrm *pTblFrm = pPos->nNode.GetNode().GetCntntNode()->
+ getLayoutFrm( GetLayout(), &aTmpPt, pPos, sal_False );
+
+ OSL_ENSURE( pTblFrm, "Tabelle Crsr nicht im Content ??" );
+
+ // --> Make code robust. The table cursor may point
+ // to a table in a currently inactive header.
+ SwTabFrm *pTab = pTblFrm ? pTblFrm->FindTabFrm() : 0;
+ // <--
+
+ if ( pTab && pTab->GetTable()->GetRowsToRepeat() > 0 )
+ {
+ // First check if point is in repeated headline:
+ bool bInRepeatedHeadline = pTab->IsFollow() && pTab->IsInHeadline( *pTblFrm );
+
+ // Second check if mark is in repeated headline:
+ if ( !bInRepeatedHeadline )
+ {
+ SwCntntFrm* pMarkTblFrm = pITmpCrsr->GetCntntNode( sal_False )->
+ getLayoutFrm( GetLayout(), &aTmpMk, pITmpCrsr->GetMark(), sal_False );
+ OSL_ENSURE( pMarkTblFrm, "Tabelle Crsr nicht im Content ??" );
+
+ if ( pMarkTblFrm )
+ {
+ SwTabFrm* pMarkTab = pMarkTblFrm->FindTabFrm();
+ OSL_ENSURE( pMarkTab, "Tabelle Crsr nicht im Content ??" );
+
+ // Make code robust:
+ if ( pMarkTab )
+ {
+ bInRepeatedHeadline = pMarkTab->IsFollow() && pMarkTab->IsInHeadline( *pMarkTblFrm );
+ }
+ }
+ }
+
+ // No table cursor in repeaded headlines:
+ if ( bInRepeatedHeadline )
+ {
+ pTblFrm = 0;
+
+ SwPosSection fnPosSect = *pPos < *pITmpCrsr->GetMark()
+ ? fnSectionStart
+ : fnSectionEnd;
+
+ // dann nur innerhalb der Box selektieren
+ if( pTblCrsr )
+ {
+ pCurCrsr->SetMark();
+ *pCurCrsr->GetMark() = *pTblCrsr->GetMark();
+ pCurCrsr->GetMkPos() = pTblCrsr->GetMkPos();
+ pTblCrsr->DeleteMark();
+ pTblCrsr->SwSelPaintRects::Hide();
+ }
+
+ *pCurCrsr->GetPoint() = *pCurCrsr->GetMark();
+ (*fnSectionCurr)( *pCurCrsr, fnPosSect );
+ }
+ }
+
+ // wir wollen wirklich eine Tabellen-Selektion
+ if( pTab && pTblFrm )
+ {
+ if( !pTblCrsr )
+ {
+ pTblCrsr = new SwShellTableCrsr( *this,
+ *pCurCrsr->GetMark(), pCurCrsr->GetMkPos(),
+ *pPos, aTmpPt );
+ pCurCrsr->DeleteMark();
+ pCurCrsr->SwSelPaintRects::Hide();
+
+ CheckTblBoxCntnt();
+ }
+
+ SwCrsrMoveState aTmpState( MV_NONE );
+ aTmpState.bRealHeight = sal_True;
+ if( !pTblFrm->GetCharRect( aCharRect, *pTblCrsr->GetPoint(), &aTmpState ) )
+ {
+ Point aCentrPt( aCharRect.Center() );
+ aTmpState.bSetInReadOnly = IsReadOnlyAvailable();
+ pTblFrm->GetCrsrOfst( pTblCrsr->GetPoint(), aCentrPt, &aTmpState );
+#if OSL_DEBUG_LEVEL > 1
+ if ( !pTblFrm->GetCharRect( aCharRect, *pTblCrsr->GetPoint() ) )
+ OSL_ENSURE( !this, "GetCharRect failed." );
+#else
+ pTblFrm->GetCharRect( aCharRect, *pTblCrsr->GetPoint() );
+#endif
+ }
+
+ pVisCrsr->Hide(); // sichtbaren Cursor immer verstecken
+ // Curosr in den sichtbaren Bereich scrollen
+ if( (eFlags & SwCrsrShell::SCROLLWIN) &&
+ (HasSelection() || eFlags & SwCrsrShell::READONLY ||
+ !IsCrsrReadonly()) )
+ {
+ SwFrm* pBoxFrm = pTblFrm;
+ while( pBoxFrm && !pBoxFrm->IsCellFrm() )
+ pBoxFrm = pBoxFrm->GetUpper();
+ if( pBoxFrm && pBoxFrm->Frm().HasArea() )
+ MakeVisible( pBoxFrm->Frm() );
+ else
+ MakeVisible( aCharRect );
+ }
+
+ // lasse vom Layout die Crsr in den Boxen erzeugen
+ if( pTblCrsr->IsCrsrMovedUpdt() )
+ GetLayout()->MakeTblCrsrs( *pTblCrsr );
+ if( bHasFocus && !bBasicHideCrsr )
+ pTblCrsr->Show();
+
+ // Cursor-Points auf die neuen Positionen setzen
+ pTblCrsr->GetPtPos().X() = aCharRect.Left();
+ pTblCrsr->GetPtPos().Y() = aCharRect.Top();
+
+ if( bSVCrsrVis )
+ {
+ aCrsrHeight.X() = 0;
+ aCrsrHeight.Y() = aTmpState.aRealHeight.Y() < 0 ?
+ -aCharRect.Width() : aCharRect.Height();
+ pVisCrsr->Show(); // wieder anzeigen
+ }
+ eMvState = MV_NONE; // Status fuers Crsr-Travelling - GetCrsrOfst
+ if( pTblFrm && Imp()->IsAccessible() )
+ Imp()->InvalidateAccessibleCursorPosition( pTblFrm );
+ return;
+ }
+ }
+
+ if( pTblCrsr )
+ {
+ // Cursor Ring loeschen
+ while( pCurCrsr->GetNext() != pCurCrsr )
+ delete pCurCrsr->GetNext();
+ pCurCrsr->DeleteMark();
+ *pCurCrsr->GetPoint() = *pTblCrsr->GetPoint();
+ pCurCrsr->GetPtPos() = pTblCrsr->GetPtPos();
+ delete pTblCrsr, pTblCrsr = 0;
+ }
+
+ pVisCrsr->Hide(); // sichtbaren Cursor immer verstecken
+
+ // sind wir vielleicht in einer geschuetzten/versteckten Section ?
+ {
+ SwShellCrsr* pShellCrsr = getShellCrsr( true );
+ sal_Bool bChgState = sal_True;
+ const SwSectionNode* pSectNd = pShellCrsr->GetNode()->FindSectionNode();
+ if( pSectNd && ( pSectNd->GetSection().IsHiddenFlag() ||
+ ( !IsReadOnlyAvailable() &&
+ pSectNd->GetSection().IsProtectFlag() &&
+ ( !pDoc->GetDocShell() ||
+ !pDoc->GetDocShell()->IsReadOnly() || bAllProtect )) ) )
+ {
+ if( !FindValidCntntNode( !HasDrawView() ||
+ 0 == Imp()->GetDrawView()->GetMarkedObjectList().GetMarkCount()))
+ {
+ // alles ist geschuetzt / versteckt -> besonderer Mode
+ if( bAllProtect && !IsReadOnlyAvailable() &&
+ pSectNd->GetSection().IsProtectFlag() )
+ bChgState = sal_False;
+ else
+ {
+ eMvState = MV_NONE; // Status fuers Crsr-Travelling
+ bAllProtect = sal_True;
+ if( GetDoc()->GetDocShell() )
+ {
+ GetDoc()->GetDocShell()->SetReadOnlyUI( sal_True );
+ CallChgLnk(); // UI bescheid sagen!
+ }
+ return;
+ }
+ }
+ }
+ if( bChgState )
+ {
+ sal_Bool bWasAllProtect = bAllProtect;
+ bAllProtect = sal_False;
+ if( bWasAllProtect && GetDoc()->GetDocShell() &&
+ GetDoc()->GetDocShell()->IsReadOnlyUI() )
+ {
+ GetDoc()->GetDocShell()->SetReadOnlyUI( sal_False );
+ CallChgLnk(); // UI bescheid sagen!
+ }
+ }
+ }
+
+ UpdateCrsrPos();
+
+ // The cursor must always point into content; there's some code
+ // that relies on this. (E.g. in SwEditShell::GetScriptType, which always
+ // loops _behind_ the last node in the selection, which always works if you
+ // are in content.) To achieve this, we'll force cursor(s) to point into
+ // content, if UpdateCrsrPos() hasn't already done so.
+ SwPaM* pCmp = pCurCrsr;
+ do
+ {
+ // start will move forwards, end will move backwards
+ bool bPointIsStart = ( pCmp->Start() == pCmp->GetPoint() );
+
+ // move point; forward if it's the start, backwards if it's the end
+ if( ! pCmp->GetPoint()->nNode.GetNode().IsCntntNode() )
+ pCmp->Move( bPointIsStart ? fnMoveForward : fnMoveBackward,
+ fnGoCntnt );
+
+ // move mark (if exists); forward if it's the start, else backwards
+ if( pCmp->HasMark() )
+ {
+ if( ! pCmp->GetMark()->nNode.GetNode().IsCntntNode() )
+ {
+ pCmp->Exchange();
+ pCmp->Move( !bPointIsStart ? fnMoveForward : fnMoveBackward,
+ fnGoCntnt );
+ pCmp->Exchange();
+ }
+ }
+
+ // iterate to next PaM in ring
+ pCmp = static_cast<SwPaM*>( pCmp->GetNext() );
+ }
+ while( pCmp != pCurCrsr );
+
+
+ SwRect aOld( aCharRect );
+ sal_Bool bFirst = sal_True;
+ SwCntntFrm *pFrm;
+ int nLoopCnt = 100;
+ SwShellCrsr* pShellCrsr = getShellCrsr( true );
+
+ do {
+ sal_Bool bAgainst;
+ do {
+ bAgainst = sal_False;
+ pFrm = pShellCrsr->GetCntntNode()->getLayoutFrm( GetLayout(),
+ &pShellCrsr->GetPtPos(), pShellCrsr->GetPoint(), sal_False );
+ // ist der Frm nicht mehr vorhanden, dann muss das gesamte Layout
+ // erzeugt werden, weil ja mal hier einer vorhanden war !!
+ if ( !pFrm )
+ {
+ do
+ {
+ CalcLayout();
+ pFrm = pShellCrsr->GetCntntNode()->getLayoutFrm( GetLayout(),
+ &pShellCrsr->GetPtPos(), pShellCrsr->GetPoint(), sal_False );
+ } while( !pFrm );
+ }
+ else if ( Imp()->IsIdleAction() )
+ //Wir stellen sicher, dass anstaendig Formatiert wurde
+ pFrm->PrepareCrsr();
+
+ // im geschuetzten Fly? aber bei Rahmenselektion ignorieren
+ if( !IsReadOnlyAvailable() && pFrm->IsProtected() &&
+ ( !Imp()->GetDrawView() ||
+ !Imp()->GetDrawView()->GetMarkedObjectList().GetMarkCount() ) &&
+ (!pDoc->GetDocShell() ||
+ !pDoc->GetDocShell()->IsReadOnly() || bAllProtect ) )
+ {
+ // dann suche eine gueltige Position
+ sal_Bool bChgState = sal_True;
+ if( !FindValidCntntNode(!HasDrawView() ||
+ 0 == Imp()->GetDrawView()->GetMarkedObjectList().GetMarkCount()))
+ {
+ // alles ist geschuetzt / versteckt -> besonderer Mode
+ if( bAllProtect )
+ bChgState = sal_False;
+ else
+ {
+ eMvState = MV_NONE; // Status fuers Crsr-Travelling
+ bAllProtect = sal_True;
+ if( GetDoc()->GetDocShell() )
+ {
+ GetDoc()->GetDocShell()->SetReadOnlyUI( sal_True );
+ CallChgLnk(); // UI bescheid sagen!
+ }
+ return;
+ }
+ }
+
+ if( bChgState )
+ {
+ sal_Bool bWasAllProtect = bAllProtect;
+ bAllProtect = sal_False;
+ if( bWasAllProtect && GetDoc()->GetDocShell() &&
+ GetDoc()->GetDocShell()->IsReadOnlyUI() )
+ {
+ GetDoc()->GetDocShell()->SetReadOnlyUI( sal_False );
+ CallChgLnk(); // UI bescheid sagen!
+ }
+ bAllProtect = sal_False;
+ bAgainst = sal_True; // nochmal den richigen Frm suchen
+ }
+ }
+ } while( bAgainst );
+
+ if( !( eFlags & SwCrsrShell::NOCALRECT ))
+ {
+ SwCrsrMoveState aTmpState( eMvState );
+ aTmpState.bSetInReadOnly = IsReadOnlyAvailable();
+ aTmpState.bRealHeight = sal_True;
+ aTmpState.bRealWidth = IsOverwriteCrsr();
+ aTmpState.nCursorBidiLevel = pShellCrsr->GetCrsrBidiLevel();
+
+ // #i27615#,#i30453#
+ SwSpecialPos aSpecialPos;
+ aSpecialPos.nExtendRange = SP_EXTEND_RANGE_BEFORE;
+ if (pShellCrsr->IsInFrontOfLabel())
+ {
+ aTmpState.pSpecialPos = &aSpecialPos;
+ }
+
+ if( !pFrm->GetCharRect( aCharRect, *pShellCrsr->GetPoint(), &aTmpState ) )
+ {
+ Point& rPt = pShellCrsr->GetPtPos();
+ rPt = aCharRect.Center();
+ pFrm->GetCrsrOfst( pShellCrsr->GetPoint(), rPt, &aTmpState );
+ }
+
+ if( !pShellCrsr->HasMark() )
+ aCrsrHeight = aTmpState.aRealHeight;
+ else
+ {
+ aCrsrHeight.X() = 0;
+ aCrsrHeight.Y() = aTmpState.aRealHeight.Y() < 0 ?
+ -aCharRect.Width() : aCharRect.Height();
+ }
+ }
+ else
+ {
+ aCrsrHeight.X() = 0;
+ aCrsrHeight.Y() = aCharRect.Height();
+ }
+
+ if( !bFirst && aOld == aCharRect )
+ break;
+
+ // falls das Layout meint, nach dem 100 durchlauf ist man immer noch
+ // im Fluss, sollte man die akt. Pos. als gegeben hinnehmen!
+ // siehe Bug: 29658
+ if( !--nLoopCnt )
+ {
+ OSL_ENSURE( !this, "Endlosschleife? CharRect != OldCharRect ");
+ break;
+ }
+ aOld = aCharRect;
+ bFirst = sal_False;
+
+ // Cursor-Points auf die neuen Positionen setzen
+ pShellCrsr->GetPtPos().X() = aCharRect.Left();
+ pShellCrsr->GetPtPos().Y() = aCharRect.Top();
+
+ if( !(eFlags & SwCrsrShell::UPDOWN )) // alte Pos. von Up/Down loeschen
+ {
+ pFrm->Calc();
+ nUpDownX = pFrm->IsVertical() ?
+ aCharRect.Top() - pFrm->Frm().Top() :
+ aCharRect.Left() - pFrm->Frm().Left();
+ }
+
+ // Curosr in den sichtbaren Bereich scrollen
+ if( bHasFocus && eFlags & SwCrsrShell::SCROLLWIN &&
+ (HasSelection() || eFlags & SwCrsrShell::READONLY ||
+ !IsCrsrReadonly() || GetViewOptions()->IsSelectionInReadonly()) )
+ {
+ //JP 30.04.99: damit das EndAction, beim evtuellen Scrollen, den
+ // SV-Crsr nicht wieder sichtbar macht, wird hier das Flag
+ // gesichert und zurueckgesetzt.
+ sal_Bool bSav = bSVCrsrVis; bSVCrsrVis = sal_False;
+ MakeSelVisible();
+ bSVCrsrVis = bSav;
+ }
+
+ } while( eFlags & SwCrsrShell::SCROLLWIN );
+
+ if( pBlockCrsr )
+ RefreshBlockCursor();
+
+ if( !bIdleEnd && bHasFocus && !bBasicHideCrsr )
+ {
+ if( pTblCrsr )
+ pTblCrsr->SwSelPaintRects::Show();
+ else
+ {
+ pCurCrsr->SwSelPaintRects::Show();
+ if( pBlockCrsr )
+ {
+ SwShellCrsr* pNxt = dynamic_cast<SwShellCrsr*>(pCurCrsr->GetNext());
+ while( pNxt && pNxt != pCurCrsr )
+ {
+ pNxt->SwSelPaintRects::Show();
+ pNxt = dynamic_cast<SwShellCrsr*>(pNxt->GetNext());
+ }
+ }
+ }
+ }
+
+ eMvState = MV_NONE; // Status fuers Crsr-Travelling - GetCrsrOfst
+
+ if( pFrm && Imp()->IsAccessible() )
+ Imp()->InvalidateAccessibleCursorPosition( pFrm );
+
+ // switch from blinking cursor to read-only-text-selection cursor
+ static const long nNoBlinkTime = STYLE_CURSOR_NOBLINKTIME;
+ const long nBlinkTime = GetOut()->GetSettings().GetStyleSettings().
+ GetCursorBlinkTime();
+
+ if ( (IsCrsrReadonly() && GetViewOptions()->IsSelectionInReadonly()) ==
+ ( nBlinkTime != nNoBlinkTime ) )
+ {
+ // non blinking cursor in read only - text selection mode
+ AllSettings aSettings = GetOut()->GetSettings();
+ StyleSettings aStyleSettings = aSettings.GetStyleSettings();
+ const long nNewBlinkTime = nBlinkTime == nNoBlinkTime ?
+ Application::GetSettings().GetStyleSettings().GetCursorBlinkTime() :
+ nNoBlinkTime;
+ aStyleSettings.SetCursorBlinkTime( nNewBlinkTime );
+ aSettings.SetStyleSettings( aStyleSettings );
+ GetOut()->SetSettings( aSettings );
+ }
+
+ if( bSVCrsrVis )
+ pVisCrsr->Show(); // wieder anzeigen
+}
+
+void SwCrsrShell::RefreshBlockCursor()
+{
+ OSL_ENSURE( pBlockCrsr, "Don't call me without a block cursor" );
+ SwShellCrsr &rBlock = pBlockCrsr->getShellCrsr();
+ Point aPt = rBlock.GetPtPos();
+ SwCntntFrm* pFrm = rBlock.GetCntntNode()->getLayoutFrm( GetLayout(), &aPt, rBlock.GetPoint(), sal_False );
+ Point aMk;
+ if( pBlockCrsr->getEndPoint() && pBlockCrsr->getStartPoint() )
+ {
+ aPt = *pBlockCrsr->getStartPoint();
+ aMk = *pBlockCrsr->getEndPoint();
+ }
+ else
+ {
+ aPt = rBlock.GetPtPos();
+ if( pFrm )
+ {
+ if( pFrm->IsVertical() )
+ aPt.Y() = pFrm->Frm().Top() + GetUpDownX();
+ else
+ aPt.X() = pFrm->Frm().Left() + GetUpDownX();
+ }
+ aMk = rBlock.GetMkPos();
+ }
+ SwRect aRect( aMk, aPt );
+ aRect.Justify();
+ SwSelectionList aSelList( pFrm );
+
+ if( GetLayout()->FillSelection( aSelList, aRect ) )
+ {
+ SwCursor* pNxt = (SwCursor*)pCurCrsr->GetNext();
+ while( pNxt != pCurCrsr )
+ {
+ delete pNxt;
+ pNxt = (SwCursor*)pCurCrsr->GetNext();
+ }
+
+ std::list<SwPaM*>::iterator pStart = aSelList.getStart();
+ std::list<SwPaM*>::iterator pPam = aSelList.getEnd();
+ OSL_ENSURE( pPam != pStart, "FillSelection should deliver at least one PaM" );
+ pCurCrsr->SetMark();
+ --pPam;
+ // If there is only one text portion inside the rectangle, a simple
+ // selection is created
+ if( pPam == pStart )
+ {
+ *pCurCrsr->GetPoint() = *(*pPam)->GetPoint();
+ if( (*pPam)->HasMark() )
+ *pCurCrsr->GetMark() = *(*pPam)->GetMark();
+ else
+ pCurCrsr->DeleteMark();
+ delete *pPam;
+ pCurCrsr->SetColumnSelection( false );
+ }
+ else
+ {
+ // The order of the SwSelectionList has to be preserved but
+ // the order inside the ring created by CreateCrsr() is not like
+ // exspected => First create the selections before the last one
+ // downto the first selection.
+ // At least create the cursor for the last selection
+ --pPam;
+ *pCurCrsr->GetPoint() = *(*pPam)->GetPoint(); // n-1 (if n == number of selections)
+ if( (*pPam)->HasMark() )
+ *pCurCrsr->GetMark() = *(*pPam)->GetMark();
+ else
+ pCurCrsr->DeleteMark();
+ delete *pPam;
+ pCurCrsr->SetColumnSelection( true );
+ while( pPam != pStart )
+ {
+ --pPam;
+
+ SwShellCrsr* pNew = new SwShellCrsr( *pCurCrsr );
+ pNew->Insert( pCurCrsr, 0 );
+ pCurCrsr->Remove( 0, pCurCrsr->Count() );
+ pCurCrsr->DeleteMark();
+
+ *pCurCrsr->GetPoint() = *(*pPam)->GetPoint(); // n-2, n-3, .., 2, 1
+ if( (*pPam)->HasMark() )
+ {
+ pCurCrsr->SetMark();
+ *pCurCrsr->GetMark() = *(*pPam)->GetMark();
+ }
+ else
+ pCurCrsr->DeleteMark();
+ pCurCrsr->SetColumnSelection( true );
+ delete *pPam;
+ }
+ {
+ SwShellCrsr* pNew = new SwShellCrsr( *pCurCrsr );
+ pNew->Insert( pCurCrsr, 0 );
+ pCurCrsr->Remove( 0, pCurCrsr->Count() );
+ pCurCrsr->DeleteMark();
+ }
+ pPam = aSelList.getEnd();
+ --pPam;
+ *pCurCrsr->GetPoint() = *(*pPam)->GetPoint(); // n, the last selection
+ if( (*pPam)->HasMark() )
+ {
+ pCurCrsr->SetMark();
+ *pCurCrsr->GetMark() = *(*pPam)->GetMark();
+ }
+ else
+ pCurCrsr->DeleteMark();
+ pCurCrsr->SetColumnSelection( true );
+ delete *pPam;
+ }
+ }
+}
+
+// erzeuge eine Kopie vom Cursor und speicher diese im Stack
+
+
+void SwCrsrShell::Push()
+{
+ pCrsrStk = new SwShellCrsr( *this, *pCurCrsr->GetPoint(),
+ pCurCrsr->GetPtPos(), pCrsrStk );
+
+ if( pCurCrsr->HasMark() )
+ {
+ pCrsrStk->SetMark();
+ *pCrsrStk->GetMark() = *pCurCrsr->GetMark();
+ }
+}
+
+/*
+ * Loescht einen Cursor (gesteuert durch bOldCrsr)
+ * - vom Stack oder ( bOldCrsr = sal_True )
+ * - den aktuellen und der auf dem Stack stehende wird zum aktuellen
+ *
+ * Return: es war auf dem Stack noch einer vorhanden
+ */
+
+
+sal_Bool SwCrsrShell::Pop( sal_Bool bOldCrsr )
+{
+ SwCallLink aLk( *this ); // Crsr-Moves ueberwachen, evt. Link callen
+
+ // noch weitere vorhanden ?
+ if( 0 == pCrsrStk )
+ return sal_False;
+
+ SwShellCrsr *pTmp = 0, *pOldStk = pCrsrStk;
+
+ // der Nachfolger wird der Aktuelle
+ if( pCrsrStk->GetNext() != pCrsrStk )
+ {
+ pTmp = dynamic_cast<SwShellCrsr*>(pCrsrStk->GetNext());
+ }
+
+ if( bOldCrsr ) // loesche vom Stack
+ delete pCrsrStk; //
+
+ pCrsrStk = pTmp; // neu zuweisen
+
+ if( !bOldCrsr )
+ {
+ SwCrsrSaveState aSaveState( *pCurCrsr );
+
+ // wurde die sichtbare SSelection nicht veraendert
+ if( pOldStk->GetPtPos() == pCurCrsr->GetPtPos() ||
+ pOldStk->GetPtPos() == pCurCrsr->GetMkPos() )
+ {
+ // "Selektions-Rechtecke" verschieben
+ pCurCrsr->Insert( pOldStk, 0 );
+ pOldStk->Remove( 0, pOldStk->Count() );
+ }
+
+ if( pOldStk->HasMark() )
+ {
+ pCurCrsr->SetMark();
+ *pCurCrsr->GetMark() = *pOldStk->GetMark();
+ pCurCrsr->GetMkPos() = pOldStk->GetMkPos();
+ }
+ else
+ // keine Selection also alte aufheben und auf die alte Pos setzen
+ pCurCrsr->DeleteMark();
+ *pCurCrsr->GetPoint() = *pOldStk->GetPoint();
+ pCurCrsr->GetPtPos() = pOldStk->GetPtPos();
+ delete pOldStk;
+
+ if( !pCurCrsr->IsInProtectTable( sal_True ) &&
+ !pCurCrsr->IsSelOvr( nsSwCursorSelOverFlags::SELOVER_TOGGLE |
+ nsSwCursorSelOverFlags::SELOVER_CHANGEPOS ) )
+ UpdateCrsr(); // akt. Cursor Updaten
+ }
+ return sal_True;
+}
+
+/*
+ * Verbinde zwei Cursor miteinander.
+ * Loesche vom Stack den obersten und setzen dessen GetMark im Aktuellen.
+ */
+
+
+void SwCrsrShell::Combine()
+{
+ // noch weitere vorhanden ?
+ if( 0 == pCrsrStk )
+ return;
+
+ SwCallLink aLk( *this ); // Crsr-Moves ueberwachen, evt. Link callen
+ SwCrsrSaveState aSaveState( *pCurCrsr );
+ if( pCrsrStk->HasMark() ) // nur wenn GetMark gesetzt wurde
+ {
+#if OSL_DEBUG_LEVEL > 1
+ if( !CheckNodesRange( pCrsrStk->GetMark()->nNode, pCurCrsr->GetPoint()->nNode, sal_True ))
+ OSL_ENSURE( !this, "StackCrsr & akt. Crsr nicht in gleicher Section." );
+#else
+ CheckNodesRange( pCrsrStk->GetMark()->nNode, pCurCrsr->GetPoint()->nNode, sal_True );
+#endif
+ // kopiere das GetMark
+ if( !pCurCrsr->HasMark() )
+ pCurCrsr->SetMark();
+ *pCurCrsr->GetMark() = *pCrsrStk->GetMark();
+ pCurCrsr->GetMkPos() = pCrsrStk->GetMkPos();
+ }
+
+ SwShellCrsr * pTmp = 0;
+ if( pCrsrStk->GetNext() != pCrsrStk )
+ {
+ pTmp = dynamic_cast<SwShellCrsr*>(pCrsrStk->GetNext());
+ }
+ delete pCrsrStk;
+ pCrsrStk = pTmp;
+ if( !pCurCrsr->IsInProtectTable( sal_True ) &&
+ !pCurCrsr->IsSelOvr( nsSwCursorSelOverFlags::SELOVER_TOGGLE |
+ nsSwCursorSelOverFlags::SELOVER_CHANGEPOS ) )
+ UpdateCrsr(); // akt. Cursor Updaten
+}
+
+
+void SwCrsrShell::HideCrsrs()
+{
+ if( !bHasFocus || bBasicHideCrsr )
+ return;
+
+ // ist Cursor sichtbar, dann verstecke den SV-Cursor
+ if( pVisCrsr->IsVisible() )
+ {
+ SET_CURR_SHELL( this );
+ pVisCrsr->Hide();
+ }
+ // hebe die Invertierung der SSelection auf
+ SwShellCrsr* pAktCrsr = pTblCrsr ? pTblCrsr : pCurCrsr;
+ pAktCrsr->Hide();
+}
+
+
+
+void SwCrsrShell::ShowCrsrs( sal_Bool bCrsrVis )
+{
+ if( !bHasFocus || bAllProtect || bBasicHideCrsr )
+ return;
+
+ SET_CURR_SHELL( this );
+ SwShellCrsr* pAktCrsr = pTblCrsr ? pTblCrsr : pCurCrsr;
+ pAktCrsr->Show();
+
+ if( bSVCrsrVis && bCrsrVis ) // auch SV-Cursor wieder anzeigen
+ pVisCrsr->Show();
+}
+
+// Methoden zum Anzeigen bzw. Verstecken des sichtbaren Text-Cursors
+
+
+void SwCrsrShell::ShowCrsr()
+{
+ if( !bBasicHideCrsr )
+ {
+ bSVCrsrVis = sal_True;
+ UpdateCrsr();
+ }
+}
+
+
+void SwCrsrShell::HideCrsr()
+{
+ if( !bBasicHideCrsr )
+ {
+ bSVCrsrVis = sal_False;
+ // evt. die sel. Bereiche aufheben !!
+ SET_CURR_SHELL( this );
+ pVisCrsr->Hide();
+ }
+}
+
+
+void SwCrsrShell::ShLooseFcs()
+{
+ if( !bBasicHideCrsr )
+ HideCrsrs();
+ bHasFocus = sal_False;
+}
+
+
+void SwCrsrShell::ShGetFcs( sal_Bool bUpdate )
+{
+ bHasFocus = sal_True;
+ if( !bBasicHideCrsr && VisArea().Width() )
+ {
+ UpdateCrsr( static_cast<sal_uInt16>( bUpdate ?
+ SwCrsrShell::CHKRANGE|SwCrsrShell::SCROLLWIN
+ : SwCrsrShell::CHKRANGE ) );
+ ShowCrsrs( bSVCrsrVis ? sal_True : sal_False );
+ }
+}
+
+// gebe den aktuellen Frame, in dem der Cursor steht, zurueck
+
+SwCntntFrm *SwCrsrShell::GetCurrFrm( const sal_Bool bCalcFrm ) const
+{
+ SET_CURR_SHELL( (ViewShell*)this );
+ SwCntntFrm *pRet = 0;
+ SwCntntNode *pNd = pCurCrsr->GetCntntNode();
+ if ( pNd )
+ {
+ if ( bCalcFrm )
+ {
+ const sal_uInt16* pST = &nStartAction;
+ ++(*((sal_uInt16*)pST));
+ const Size aOldSz( GetDocSize() );
+ pRet = pNd->getLayoutFrm( GetLayout(), &pCurCrsr->GetPtPos(), pCurCrsr->GetPoint() );
+ --(*((sal_uInt16*)pST));
+ if( aOldSz != GetDocSize() )
+ ((SwCrsrShell*)this)->SizeChgNotify();
+ }
+ else
+ pRet = pNd->getLayoutFrm( GetLayout(), &pCurCrsr->GetPtPos(), pCurCrsr->GetPoint(), sal_False);
+ }
+ return pRet;
+}
+
+
+// alle Attribut/Format-Aenderungen am akt. Node werden an den
+// Link weitergeleitet.
+
+
+void SwCrsrShell::Modify( const SfxPoolItem* pOld, const SfxPoolItem* pNew )
+{
+ const sal_uInt16 nWhich = pOld ?
+ pOld->Which() :
+ pNew ?
+ pNew->Which() :
+ sal::static_int_cast<sal_uInt16>(RES_MSG_BEGIN);
+
+ if( bCallChgLnk &&
+ ( nWhich < RES_MSG_BEGIN || nWhich >= RES_MSG_END ||
+ nWhich == RES_FMT_CHG || nWhich == RES_UPDATE_ATTR ||
+ nWhich == RES_ATTRSET_CHG ))
+ // die Messages werden nicht weitergemeldet
+ //MA 07. Apr. 94 fix(6681): RES_UPDATE_ATTR wird implizit vom
+ //SwTxtNode::Insert(SwTxtHint*, sal_uInt16) abgesetzt; hier wird reagiert und
+ //vom Insert brauch nicht mehr die Keule RES_FMT_CHG versandt werden.
+ CallChgLnk();
+
+ if( aGrfArrivedLnk.IsSet() &&
+ ( RES_GRAPHIC_ARRIVED == nWhich || RES_GRAPHIC_SWAPIN == nWhich ))
+ aGrfArrivedLnk.Call( this );
+}
+
+
+// Abfrage, ob der aktuelle Cursor eine Selektion aufspannt,
+// also, ob GetMark gesetzt und SPoint und GetMark unterschiedlich sind.
+
+
+sal_Bool SwCrsrShell::HasSelection() const
+{
+ const SwPaM* pCrsr = getShellCrsr( true );
+ return( IsTableMode() || ( pCrsr->HasMark() &&
+ *pCrsr->GetPoint() != *pCrsr->GetMark())
+ ? sal_True : sal_False );
+}
+
+
+void SwCrsrShell::CallChgLnk()
+{
+ // innerhalb von Start-/End-Action kein Call, sondern nur merken,
+ // das sich etwas geaendert hat. Wird bei EndAction beachtet.
+ if( BasicActionPend() )
+ bChgCallFlag = sal_True; // das Change merken
+ else if( aChgLnk.IsSet() )
+ {
+ if( bCallChgLnk )
+ aChgLnk.Call( this );
+ bChgCallFlag = sal_False; // Flag zuruecksetzen
+ }
+}
+
+// returne den am akt.Cursor selektierten Text eines Nodes.
+
+
+String SwCrsrShell::GetSelTxt() const
+{
+ String aTxt;
+ if( pCurCrsr->GetPoint()->nNode.GetIndex() ==
+ pCurCrsr->GetMark()->nNode.GetIndex() )
+ {
+ SwTxtNode* pTxtNd = pCurCrsr->GetNode()->GetTxtNode();
+ if( pTxtNd )
+ {
+ xub_StrLen nStt = pCurCrsr->Start()->nContent.GetIndex();
+ aTxt = pTxtNd->GetExpandTxt( nStt,
+ pCurCrsr->End()->nContent.GetIndex() - nStt );
+ }
+ }
+ return aTxt;
+}
+
+// gebe nur den Text ab der akt. Cursor Position zurueck (bis zum NodeEnde)
+
+
+String SwCrsrShell::GetText() const
+{
+ String aTxt;
+ if( pCurCrsr->GetPoint()->nNode.GetIndex() ==
+ pCurCrsr->GetMark()->nNode.GetIndex() )
+ {
+ SwTxtNode* pTxtNd = pCurCrsr->GetNode()->GetTxtNode();
+ if( pTxtNd )
+ aTxt = pTxtNd->GetTxt().Copy(
+ pCurCrsr->GetPoint()->nContent.GetIndex() );
+ }
+ return aTxt;
+}
+
+// hole vom Start/Ende der akt. SSelection das nte Zeichen
+sal_Unicode SwCrsrShell::GetChar( sal_Bool bEnd, long nOffset )
+{
+ if( IsTableMode() ) // im TabelleMode nicht moeglich
+ return 0;
+
+ const SwPosition* pPos = !pCurCrsr->HasMark() ? pCurCrsr->GetPoint()
+ : bEnd ? pCurCrsr->End() : pCurCrsr->Start();
+ SwTxtNode* pTxtNd = pPos->nNode.GetNode().GetTxtNode();
+ if( !pTxtNd )
+ return 0;
+
+ xub_StrLen nPos = pPos->nContent.GetIndex();
+ const String& rStr = pTxtNd->GetTxt();
+ sal_Unicode cCh = 0;
+
+ if( ((nPos+nOffset) >= 0 ) && (nPos+nOffset) < rStr.Len() )
+ cCh = rStr.GetChar( static_cast<xub_StrLen>(nPos+nOffset) );
+
+ return cCh;
+}
+
+// erweiter die akt. SSelection am Anfang/Ende um n Zeichen
+
+
+sal_Bool SwCrsrShell::ExtendSelection( sal_Bool bEnd, xub_StrLen nCount )
+{
+ if( !pCurCrsr->HasMark() || IsTableMode() )
+ return sal_False; // keine Selektion
+
+ SwPosition* pPos = bEnd ? pCurCrsr->End() : pCurCrsr->Start();
+ SwTxtNode* pTxtNd = pPos->nNode.GetNode().GetTxtNode();
+ OSL_ENSURE( pTxtNd, "kein TextNode, wie soll erweitert werden?" );
+
+ xub_StrLen nPos = pPos->nContent.GetIndex();
+ if( bEnd )
+ {
+ if( ( nPos + nCount ) <= pTxtNd->GetTxt().Len() )
+ nPos = nPos + nCount;
+ else
+ return sal_False; // nicht mehr moeglich
+ }
+ else if( nPos >= nCount )
+ nPos = nPos - nCount;
+ else
+ return sal_False; // nicht mehr moeglich
+
+ SwCallLink aLk( *this ); // Crsr-Moves ueberwachen,
+
+ pPos->nContent = nPos;
+ UpdateCrsr();
+
+ return sal_True;
+}
+
+// setze nur den sichtbaren Cursor an die angegebene Dokument-Pos.
+// returnt sal_False: wenn der SPoint vom Layout korrigiert wurde.
+
+sal_Bool SwCrsrShell::SetVisCrsr( const Point &rPt )
+{
+ SET_CURR_SHELL( this );
+ Point aPt( rPt );
+ SwPosition aPos( *pCurCrsr->GetPoint() );
+ SwCrsrMoveState aTmpState( MV_SETONLYTEXT );
+ aTmpState.bSetInReadOnly = IsReadOnlyAvailable();
+ aTmpState.bRealHeight = sal_True;
+
+ sal_Bool bRet = GetLayout()->GetCrsrOfst( &aPos, aPt /*, &aTmpState*/ );
+
+ SetInFrontOfLabel( sal_False ); // #i27615#
+
+ // nur in TextNodes anzeigen !!
+ SwTxtNode* pTxtNd = aPos.nNode.GetNode().GetTxtNode();
+ if( !pTxtNd )
+ return sal_False;
+
+ const SwSectionNode* pSectNd = pTxtNd->FindSectionNode();
+ if( pSectNd && (pSectNd->GetSection().IsHiddenFlag() ||
+ ( !IsReadOnlyAvailable() &&
+ pSectNd->GetSection().IsProtectFlag())) )
+ return sal_False;
+
+ SwCntntFrm *pFrm = pTxtNd->getLayoutFrm( GetLayout(), &aPt, &aPos );
+ if ( Imp()->IsIdleAction() )
+ pFrm->PrepareCrsr();
+ SwRect aTmp( aCharRect );
+
+ pFrm->GetCharRect( aCharRect, aPos, &aTmpState );
+
+ if( aTmp == aCharRect && // BUG 10137: bleibt der Cursor auf der
+ pVisCrsr->IsVisible() ) // Position nicht hidden & showen
+ return sal_True;
+
+ pVisCrsr->Hide(); // sichtbaren Cursor immer verstecken
+ if( IsScrollMDI( this, aCharRect ))
+ {
+ MakeVisible( aCharRect );
+ pCurCrsr->Show();
+ }
+
+ {
+ if( aTmpState.bRealHeight )
+ aCrsrHeight = aTmpState.aRealHeight;
+ else
+ {
+ aCrsrHeight.X() = 0;
+ aCrsrHeight.Y() = aCharRect.Height();
+ }
+
+ pVisCrsr->SetDragCrsr( sal_True );
+ pVisCrsr->Show(); // wieder anzeigen
+ }
+ return bRet;
+}
+
+sal_Bool SwCrsrShell::IsOverReadOnlyPos( const Point& rPt ) const
+{
+ Point aPt( rPt );
+ SwPaM aPam( *pCurCrsr->GetPoint() );
+ GetLayout()->GetCrsrOfst( aPam.GetPoint(), aPt );
+ // Formular view
+ return aPam.HasReadonlySel( GetViewOptions()->IsFormView() );
+}
+
+
+ // returne die Anzahl der Cursor im Ring (Flag besagt ob man nur
+ // aufgepspannte haben will - sprich etwas selektiert ist (Basic))
+sal_uInt16 SwCrsrShell::GetCrsrCnt( sal_Bool bAll ) const
+{
+ Ring* pTmp = GetCrsr()->GetNext();
+ sal_uInt16 n = (bAll || ( pCurCrsr->HasMark() &&
+ *pCurCrsr->GetPoint() != *pCurCrsr->GetMark())) ? 1 : 0;
+ while( pTmp != pCurCrsr )
+ {
+ if( bAll || ( ((SwPaM*)pTmp)->HasMark() &&
+ *((SwPaM*)pTmp)->GetPoint() != *((SwPaM*)pTmp)->GetMark()))
+ ++n;
+ pTmp = pTmp->GetNext();
+ }
+ return n;
+}
+
+
+sal_Bool SwCrsrShell::IsStartOfDoc() const
+{
+ if( pCurCrsr->GetPoint()->nContent.GetIndex() )
+ return sal_False;
+
+ // Hinter EndOfIcons kommt die Content-Section (EndNd+StNd+CntntNd)
+ SwNodeIndex aIdx( GetDoc()->GetNodes().GetEndOfExtras(), 2 );
+ if( !aIdx.GetNode().IsCntntNode() )
+ GetDoc()->GetNodes().GoNext( &aIdx );
+ return aIdx == pCurCrsr->GetPoint()->nNode;
+}
+
+
+sal_Bool SwCrsrShell::IsEndOfDoc() const
+{
+ SwNodeIndex aIdx( GetDoc()->GetNodes().GetEndOfContent(), -1 );
+ SwCntntNode* pCNd = aIdx.GetNode().GetCntntNode();
+ if( !pCNd )
+ pCNd = GetDoc()->GetNodes().GoPrevious( &aIdx );
+
+ return aIdx == pCurCrsr->GetPoint()->nNode &&
+ pCNd->Len() == pCurCrsr->GetPoint()->nContent.GetIndex();
+}
+
+
+// loesche alle erzeugten Crsr, setze den Tabellen-Crsr und den letzten
+// Cursor auf seinen TextNode (oder StartNode?).
+// Beim naechsten ::GetCrsr werden sie wieder alle erzeugt
+// Wird fuers Drag&Drop / ClipBorad-Paste in Tabellen benoetigt.
+sal_Bool SwCrsrShell::ParkTblCrsr()
+{
+ if( !pTblCrsr )
+ return sal_False;
+
+ pTblCrsr->ParkCrsr();
+
+ while( pCurCrsr->GetNext() != pCurCrsr )
+ delete pCurCrsr->GetNext();
+
+ // vom Cursor !immer! SPoint und Mark umsetzen
+ pCurCrsr->SetMark();
+ *pCurCrsr->GetMark() = *pCurCrsr->GetPoint() = *pTblCrsr->GetPoint();
+ pCurCrsr->DeleteMark();
+
+ return sal_True;
+}
+
+/***********************************************************************
+#* Class : SwCrsrShell
+#* Methode : ParkCrsr
+#* Beschreibung: Vernichtet Selektionen und zus. Crsr aller Shell der
+#* verbleibende Crsr der Shell wird geparkt.
+#***********************************************************************/
+
+void SwCrsrShell::_ParkPams( SwPaM* pDelRg, SwShellCrsr** ppDelRing )
+{
+ const SwPosition *pStt = pDelRg->Start(),
+ *pEnd = pDelRg->GetPoint() == pStt ? pDelRg->GetMark() : pDelRg->GetPoint();
+
+ SwPaM *pTmpDel = 0, *pTmp = *ppDelRing;
+
+ // durchsuche den gesamten Ring
+ sal_Bool bGoNext;
+ do {
+ const SwPosition *pTmpStt = pTmp->Start(),
+ *pTmpEnd = pTmp->GetPoint() == pTmpStt ?
+ pTmp->GetMark() : pTmp->GetPoint();
+ /*
+ * liegt ein SPoint oder GetMark innerhalb vom Crsr-Bereich
+ * muss der alte Bereich aufgehoben werden.
+ * Beim Vergleich ist darauf zu achten, das End() nicht mehr zum
+ * Bereich gehoert !
+ */
+ if( *pStt <= *pTmpStt )
+ {
+ if( *pEnd > *pTmpStt ||
+ ( *pEnd == *pTmpStt && *pEnd == *pTmpEnd ))
+ pTmpDel = pTmp;
+ }
+ else
+ if( *pStt < *pTmpEnd )
+ pTmpDel = pTmp;
+
+ bGoNext = sal_True;
+ if( pTmpDel ) // ist der Pam im Bereich ?? loesche ihn
+ {
+ sal_Bool bDelete = sal_True;
+ if( *ppDelRing == pTmpDel )
+ {
+ if( *ppDelRing == pCurCrsr )
+ {
+ if( sal_True == ( bDelete = GoNextCrsr() ))
+ {
+ bGoNext = sal_False;
+ pTmp = (SwPaM*)pTmp->GetNext();
+ }
+ }
+ else
+ bDelete = sal_False; // StackCrsr nie loeschen !!
+ }
+
+ if( bDelete )
+ delete pTmpDel; // hebe alten Bereich auf
+ else
+ {
+ pTmpDel->GetPoint()->nContent.Assign( 0, 0 );
+ pTmpDel->GetPoint()->nNode = 0;
+ pTmpDel->SetMark();
+ pTmpDel->DeleteMark();
+ }
+ pTmpDel = 0;
+ }
+ else if( !pTmp->HasMark() ) // sorge auf jedenfall dafuer, das
+ { // nicht benutzte Indizies beachtet werden!
+ pTmp->SetMark(); // SPoint liegt nicht im Bereich,
+ pTmp->DeleteMark(); // aber vielleicht GetMark, also setzen
+ }
+ if( bGoNext )
+ pTmp = (SwPaM*)pTmp->GetNext();
+ } while( !bGoNext || *ppDelRing != pTmp );
+}
+
+void SwCrsrShell::ParkCrsr( const SwNodeIndex &rIdx )
+{
+ SwNode *pNode = &rIdx.GetNode();
+
+ // erzeuge einen neuen Pam
+ SwPaM * pNew = new SwPaM( *GetCrsr()->GetPoint() );
+ if( pNode->GetStartNode() )
+ {
+ if( ( pNode = pNode->StartOfSectionNode())->IsTableNode() )
+ {
+ // der angegebene Node steht in einer Tabelle, also Parke
+ // den Crsr auf dem Tabellen-Node (ausserhalb der Tabelle)
+ pNew->GetPoint()->nNode = *pNode->StartOfSectionNode();
+ }
+ else // also auf dem StartNode selbst.
+ // Dann immer ueber seinen EndNode den StartNode erfragen !!!
+ // (StartOfSection vom StartNode ist der Parent !)
+ pNew->GetPoint()->nNode = *pNode->EndOfSectionNode()->StartOfSectionNode();
+ }
+ else
+ pNew->GetPoint()->nNode = *pNode->StartOfSectionNode();
+ pNew->SetMark();
+ pNew->GetPoint()->nNode = *pNode->EndOfSectionNode();
+
+ //Alle Shells wollen etwas davon haben.
+ ViewShell *pTmp = this;
+ do {
+ if( pTmp->IsA( TYPE( SwCrsrShell )))
+ {
+ SwCrsrShell* pSh = (SwCrsrShell*)pTmp;
+ if( pSh->pCrsrStk )
+ pSh->_ParkPams( pNew, &pSh->pCrsrStk );
+
+ pSh->_ParkPams( pNew, &pSh->pCurCrsr );
+ if( pSh->pTblCrsr )
+ {
+ // setze den Tabellen Cursor immer auf 0, den aktuellen
+ // immer auf den Anfang der Tabelle
+ SwPaM* pTCrsr = pSh->GetTblCrs();
+ SwNode* pTblNd = pTCrsr->GetPoint()->nNode.GetNode().FindTableNode();
+ if ( pTblNd )
+ {
+ pTCrsr->GetPoint()->nContent.Assign( 0, 0 );
+ pTCrsr->GetPoint()->nNode = 0;
+ pTCrsr->SetMark();
+ pTCrsr->DeleteMark();
+ pSh->pCurCrsr->GetPoint()->nNode = *pTblNd;
+ }
+ }
+ }
+ } while ( this != (pTmp = (ViewShell*)pTmp->GetNext() ));
+ delete pNew;
+}
+
+//=========================================================================
+
+/*
+ * der Copy-Constructor
+ * Cursor-Position kopieren, in den Ring eingetragen.
+ * Alle Ansichten eines Dokumentes stehen im Ring der Shells.
+ */
+
+SwCrsrShell::SwCrsrShell( SwCrsrShell& rShell, Window *pInitWin )
+ : ViewShell( rShell, pInitWin ),
+ SwModify( 0 ), pCrsrStk( 0 ), pBlockCrsr( 0 ), pTblCrsr( 0 ),
+ pBoxIdx( 0 ), pBoxPtr( 0 ), nCrsrMove( 0 ), nBasicActionCnt( 0 ),
+ eMvState( MV_NONE ),
+ sMarkedListId(),
+ nMarkedListLevel( 0 )
+{
+ SET_CURR_SHELL( this );
+ // Nur die Position vom aktuellen Cursor aus der Copy-Shell uebernehmen
+ pCurCrsr = new SwShellCrsr( *this, *(rShell.pCurCrsr->GetPoint()) );
+ pCurCrsr->GetCntntNode()->Add( this );
+
+ bAllProtect = bVisPortChgd = bChgCallFlag = bInCMvVisportChgd =
+ bGCAttr = bIgnoreReadonly = bSelTblCells = bBasicHideCrsr =
+ bOverwriteCrsr = sal_False;
+ bCallChgLnk = bHasFocus = bSVCrsrVis = bAutoUpdateCells = sal_True;
+ bSetCrsrInReadOnly = sal_True;
+ pVisCrsr = new SwVisCrsr( this );
+ mbMacroExecAllowed = rShell.IsMacroExecAllowed();
+}
+
+
+/*
+ * der normale Constructor
+ */
+
+SwCrsrShell::SwCrsrShell( SwDoc& rDoc, Window *pInitWin,
+ const SwViewOption *pInitOpt )
+ : ViewShell( rDoc, pInitWin, pInitOpt ),
+ SwModify( 0 ), pCrsrStk( 0 ), pBlockCrsr( 0 ), pTblCrsr( 0 ),
+ pBoxIdx( 0 ), pBoxPtr( 0 ), nCrsrMove( 0 ), nBasicActionCnt( 0 ),
+ eMvState( MV_NONE ), // state for crsr-travelling - GetCrsrOfst
+ sMarkedListId(),
+ nMarkedListLevel( 0 )
+{
+ SET_CURR_SHELL( this );
+ /*
+ * Erzeugen des initialen Cursors, wird auf die erste
+ * Inhaltsposition gesetzt
+ */
+ SwNodes& rNds = rDoc.GetNodes();
+
+ SwNodeIndex aNodeIdx( *rNds.GetEndOfContent().StartOfSectionNode() );
+ SwCntntNode* pCNd = rNds.GoNext( &aNodeIdx ); // gehe zum 1. ContentNode
+
+ pCurCrsr = new SwShellCrsr( *this, SwPosition( aNodeIdx, SwIndex( pCNd, 0 )));
+
+ // melde die Shell beim akt. Node als abhaengig an, dadurch koennen alle
+ // Attribut-Aenderungen ueber den Link weiter gemeldet werden.
+ pCNd->Add( this );
+
+ bAllProtect = bVisPortChgd = bChgCallFlag = bInCMvVisportChgd =
+ bGCAttr = bIgnoreReadonly = bSelTblCells = bBasicHideCrsr =
+ bOverwriteCrsr = sal_False;
+ bCallChgLnk = bHasFocus = bSVCrsrVis = bAutoUpdateCells = sal_True;
+ bSetCrsrInReadOnly = sal_True;
+
+ pVisCrsr = new SwVisCrsr( this );
+ mbMacroExecAllowed = true;
+}
+
+
+
+SwCrsrShell::~SwCrsrShell()
+{
+ // wenn es nicht die letzte View so sollte zu mindest das
+ // Feld noch geupdatet werden.
+ if( GetNext() != this )
+ CheckTblBoxCntnt( pCurCrsr->GetPoint() );
+ else
+ ClearTblBoxCntnt();
+
+ delete pVisCrsr;
+ delete pBlockCrsr;
+ delete pTblCrsr;
+
+ /*
+ * Freigabe der Cursor
+ */
+ while(pCurCrsr->GetNext() != pCurCrsr)
+ delete pCurCrsr->GetNext();
+ delete pCurCrsr;
+
+ // Stack freigeben
+ if( pCrsrStk )
+ {
+ while( pCrsrStk->GetNext() != pCrsrStk )
+ delete pCrsrStk->GetNext();
+ delete pCrsrStk;
+ }
+
+ // JP 27.07.98: Bug 54025 - ggfs. den HTML-Parser, der als Client in
+ // der CursorShell haengt keine Chance geben, sich an den
+ // TextNode zu haengen.
+ if( GetRegisteredIn() )
+ GetRegisteredInNonConst()->Remove( this );
+}
+
+SwShellCrsr* SwCrsrShell::getShellCrsr( bool bBlock )
+{
+ if( pTblCrsr )
+ return pTblCrsr;
+ if( pBlockCrsr && bBlock )
+ return &pBlockCrsr->getShellCrsr();
+ return pCurCrsr;
+}
+
+//Sollte fuer das Clipboard der WaitPtr geschaltet werden?
+//Warten bei TableMode, Mehrfachselektion und mehr als x Selektieren Absaetzen.
+
+sal_Bool SwCrsrShell::ShouldWait() const
+{
+ if ( IsTableMode() || GetCrsrCnt() > 1 )
+ return sal_True;
+
+ if( HasDrawView() && GetDrawView()->GetMarkedObjectList().GetMarkCount() )
+ return sal_True;
+
+ SwPaM* pPam = GetCrsr();
+ return pPam->Start()->nNode.GetIndex() + 10 <
+ pPam->End()->nNode.GetIndex();
+}
+
+
+sal_uInt16 SwCrsrShell::UpdateTblSelBoxes()
+{
+ if( pTblCrsr && ( pTblCrsr->IsChgd() || !pTblCrsr->GetBoxesCount() ))
+ GetLayout()->MakeTblCrsrs( *pTblCrsr );
+ return pTblCrsr ? pTblCrsr->GetBoxesCount() : 0;
+}
+
+// zeige das akt. selektierte "Object" an
+void SwCrsrShell::MakeSelVisible()
+{
+ OSL_ENSURE( bHasFocus, "kein Focus aber Cursor sichtbar machen?" );
+ if( aCrsrHeight.Y() < aCharRect.Height() && aCharRect.Height() > VisArea().Height() )
+ {
+ SwRect aTmp( aCharRect );
+ long nDiff = aCharRect.Height() - VisArea().Height();
+ if( nDiff < aCrsrHeight.X() )
+ aTmp.Top( nDiff + aCharRect.Top() );
+ else
+ {
+ aTmp.Top( aCrsrHeight.X() + aCharRect.Top() );
+ aTmp.Height( aCrsrHeight.Y() );
+ }
+ if( !aTmp.HasArea() )
+ {
+ aTmp.SSize().Height() += 1;
+ aTmp.SSize().Width() += 1;
+ }
+ MakeVisible( aTmp );
+ }
+ else
+ {
+ if( aCharRect.HasArea() )
+ MakeVisible( aCharRect );
+ else
+ {
+ SwRect aTmp( aCharRect );
+ aTmp.SSize().Height() += 1; aTmp.SSize().Width() += 1;
+ MakeVisible( aTmp );
+ }
+ }
+}
+
+
+// suche eine gueltige ContentPosition (nicht geschuetzt/nicht versteckt)
+sal_Bool SwCrsrShell::FindValidCntntNode( sal_Bool bOnlyText )
+{
+ if( pTblCrsr ) // was soll ich jetzt machen ??
+ {
+ OSL_ENSURE( !this, "TabellenSelection nicht aufgehoben!" );
+ return sal_False;
+ }
+
+ //JP 28.10.97: Bug 45129 - im UI-ReadOnly ist alles erlaubt
+ if( !bAllProtect && GetDoc()->GetDocShell() &&
+ GetDoc()->GetDocShell()->IsReadOnlyUI() )
+ return sal_True;
+
+ // dann raus da!
+ if( pCurCrsr->HasMark() )
+ ClearMark();
+
+ // als erstes mal auf Rahmen abpruefen
+ SwNodeIndex& rNdIdx = pCurCrsr->GetPoint()->nNode;
+ sal_uLong nNdIdx = rNdIdx.GetIndex(); // sichern
+ SwNodes& rNds = pDoc->GetNodes();
+ SwCntntNode* pCNd = rNdIdx.GetNode().GetCntntNode();
+ const SwCntntFrm * pFrm;
+
+ if( pCNd && 0 != (pFrm = pCNd->getLayoutFrm( GetLayout(),0,pCurCrsr->GetPoint(),sal_False)) &&
+ !IsReadOnlyAvailable() && pFrm->IsProtected() &&
+ nNdIdx < rNds.GetEndOfExtras().GetIndex() )
+ {
+ // geschuetzter Rahmen ueberspringen
+ SwPaM aPam( *pCurCrsr->GetPoint() );
+ aPam.SetMark();
+ aPam.GetMark()->nNode = rNds.GetEndOfContent();
+ aPam.GetPoint()->nNode = *pCNd->EndOfSectionNode();
+
+ sal_Bool bFirst = sal_False;
+ if( 0 == (pCNd = ::GetNode( aPam, bFirst, fnMoveForward, sal_False )))
+ {
+ aPam.GetMark()->nNode = *rNds.GetEndOfPostIts().StartOfSectionNode();
+ pCNd = ::GetNode( aPam, bFirst, fnMoveBackward, sal_False );
+ }
+
+ if( !pCNd ) // sollte nie passieren !!!
+ {
+ rNdIdx = nNdIdx; // alten Node zurueck
+ return sal_False;
+ }
+ *pCurCrsr->GetPoint() = *aPam.GetPoint();
+ }
+ else if( bOnlyText && pCNd && pCNd->IsNoTxtNode() )
+ {
+ // dann auf den Anfang vom Doc stellen
+ rNdIdx = pDoc->GetNodes().GetEndOfExtras();
+ pCurCrsr->GetPoint()->nContent.Assign( pDoc->GetNodes().GoNext(
+ &rNdIdx ), 0 );
+ nNdIdx = rNdIdx.GetIndex();
+ }
+
+ sal_Bool bOk = sal_True;
+
+ // #i9059# cursor may not stand in protected cells
+ // (unless cursor in protected areas is OK.)
+ const SwTableNode* pTableNode = rNdIdx.GetNode().FindTableNode();
+ if( !IsReadOnlyAvailable() &&
+ pTableNode != NULL && rNdIdx.GetNode().IsProtect() )
+ {
+ // we're in a table, and we're in a protected area, so we're
+ // probably in a protected cell.
+
+ // move forward into non-protected area.
+ SwPaM aPam( rNdIdx.GetNode(), 0 );
+ while( aPam.GetNode()->IsProtect() &&
+ aPam.Move( fnMoveForward, fnGoCntnt ) )
+ ; // nothing to do in the loop; the aPam.Move does the moving!
+
+ // didn't work? then go backwards!
+ if( aPam.GetNode()->IsProtect() )
+ {
+ SwPaM aTmpPaM( rNdIdx.GetNode(), 0 );
+ aPam = aTmpPaM;
+ while( aPam.GetNode()->IsProtect() &&
+ aPam.Move( fnMoveBackward, fnGoCntnt ) )
+ ; // nothing to do in the loop; the aPam.Move does the moving!
+ }
+
+ // if we're successful, set the new position
+ if( ! aPam.GetNode()->IsProtect() )
+ {
+ *pCurCrsr->GetPoint() = *aPam.GetPoint();
+ }
+ }
+
+ // in einem geschuetzten Bereich
+ const SwSectionNode* pSectNd = rNdIdx.GetNode().FindSectionNode();
+ if( pSectNd && ( pSectNd->GetSection().IsHiddenFlag() ||
+ ( !IsReadOnlyAvailable() &&
+ pSectNd->GetSection().IsProtectFlag() )) )
+ {
+ typedef SwCntntNode* (SwNodes:: *FNGoSection)( SwNodeIndex *, int, int ) const;
+ FNGoSection funcGoSection = &SwNodes::GoNextSection;
+
+ bOk = sal_False;
+
+ for( int nLoopCnt = 0; !bOk && nLoopCnt < 2; ++nLoopCnt )
+ {
+ sal_Bool bWeiter;
+ do {
+ bWeiter = sal_False;
+ while( 0 != ( pCNd = (rNds.*funcGoSection)( &rNdIdx,
+ sal_True, !IsReadOnlyAvailable() )) )
+ {
+ // in eine Tabelle verschoben -> pruefe ob die
+ // vielleicht geschuetzt ist
+ if( pCNd->FindTableNode() )
+ {
+ SwCallLink aTmp( *this );
+ SwCrsrSaveState aSaveState( *pCurCrsr );
+ aTmp.nNdTyp = 0; // im DTOR nichts machen!
+ if( !pCurCrsr->IsInProtectTable( sal_True, sal_True ) )
+ {
+ const SwSectionNode* pSNd = pCNd->FindSectionNode();
+ if( !pSNd || !pSNd->GetSection().IsHiddenFlag()
+ || (!IsReadOnlyAvailable() &&
+ pSNd->GetSection().IsProtectFlag() ))
+ {
+ bOk = sal_True;
+ break; // eine nicht geschuetzte Zelle gef.
+ }
+ continue; // dann weiter suchen
+ }
+ }
+ else
+ {
+ bOk = sal_True;
+ break; // eine nicht geschuetzte Zelle gef.
+ }
+ }
+
+ if( bOk && rNdIdx.GetIndex() < rNds.GetEndOfExtras().GetIndex() )
+ {
+ // Teste mal auf Fly - kann auch noch geschuetzt sein!!
+ if( 0 == (pFrm = pCNd->getLayoutFrm( GetLayout(),0,0,sal_False)) ||
+ ( !IsReadOnlyAvailable() && pFrm->IsProtected() ) ||
+ ( bOnlyText && pCNd->IsNoTxtNode() ) )
+ {
+ // dann weiter suchen!
+ bOk = sal_False;
+ bWeiter = sal_True;
+ }
+ }
+ } while( bWeiter );
+
+ if( !bOk )
+ {
+ if( !nLoopCnt )
+ funcGoSection = &SwNodes::GoPrevSection;
+ rNdIdx = nNdIdx;
+ }
+ }
+ }
+ if( bOk )
+ {
+ pCNd = rNdIdx.GetNode().GetCntntNode();
+ xub_StrLen nCntnt = rNdIdx.GetIndex() < nNdIdx ? pCNd->Len() : 0;
+ pCurCrsr->GetPoint()->nContent.Assign( pCNd, nCntnt );
+ }
+ else
+ {
+ pCNd = rNdIdx.GetNode().GetCntntNode();
+
+ // falls Cursor im versteckten Bereich ist, auf jedenfall schon mal
+ // verschieben!!
+ if( !pCNd || !pCNd->getLayoutFrm( GetLayout(),0,0,sal_False) )
+ {
+ SwCrsrMoveState aTmpState( MV_NONE );
+ aTmpState.bSetInReadOnly = IsReadOnlyAvailable();
+ GetLayout()->GetCrsrOfst( pCurCrsr->GetPoint(), pCurCrsr->GetPtPos(),
+ &aTmpState );
+ }
+ }
+ return bOk;
+}
+
+
+void SwCrsrShell::NewCoreSelection()
+{
+}
+
+
+sal_Bool SwCrsrShell::IsCrsrReadonly() const
+{
+ if ( GetViewOptions()->IsReadonly() ||
+ // Formular view
+ GetViewOptions()->IsFormView() )
+ {
+ SwFrm *pFrm = GetCurrFrm( sal_False );
+ const SwFlyFrm* pFly;
+ const SwSection* pSection;
+
+ if( pFrm && pFrm->IsInFly() &&
+ (pFly = pFrm->FindFlyFrm())->GetFmt()->GetEditInReadonly().GetValue() &&
+ pFly->Lower() &&
+ !pFly->Lower()->IsNoTxtFrm() &&
+ !GetDrawView()->GetMarkedObjectList().GetMarkCount() )
+ {
+ return sal_False;
+ }
+ // edit in readonly sections
+ else if ( pFrm && pFrm->IsInSct() &&
+ 0 != ( pSection = pFrm->FindSctFrm()->GetSection() ) &&
+ pSection->IsEditInReadonlyFlag() )
+ {
+ return sal_False;
+ }
+
+ return sal_True;
+ }
+ return sal_False;
+}
+
+
+// darf der Cursor in ReadOnlyBereiche?
+void SwCrsrShell::SetReadOnlyAvailable( sal_Bool bFlag )
+{
+ // im GlobalDoc darf NIE umgeschaltet werden
+ if( (!GetDoc()->GetDocShell() ||
+ !GetDoc()->GetDocShell()->IsA( SwGlobalDocShell::StaticType() )) &&
+ bFlag != bSetCrsrInReadOnly )
+ {
+ // wenn das Flag ausgeschaltet wird, dann muessen erstmal alle
+ // Selektionen aufgehoben werden. Denn sonst wird sich darauf
+ // verlassen, das nichts geschuetztes selektiert ist!
+ if( !bFlag )
+ {
+ ClearMark();
+ }
+ bSetCrsrInReadOnly = bFlag;
+ UpdateCrsr();
+ }
+}
+
+sal_Bool SwCrsrShell::HasReadonlySel() const
+{
+ sal_Bool bRet = sal_False;
+ if( IsReadOnlyAvailable() || GetViewOptions()->IsFormView() )
+ {
+ if( pTblCrsr )
+ bRet = pTblCrsr->HasReadOnlyBoxSel() ||
+ pTblCrsr->HasReadonlySel( GetViewOptions()->IsFormView() );
+ else
+ {
+ const SwPaM* pCrsr = pCurCrsr;
+
+ do {
+ if( pCrsr->HasReadonlySel( GetViewOptions()->IsFormView() ) )
+ bRet = sal_True;
+ } while( !bRet && pCurCrsr != ( pCrsr = (SwPaM*)pCrsr->GetNext() ));
+ }
+ }
+ return bRet;
+}
+
+sal_Bool SwCrsrShell::IsSelFullPara() const
+{
+ sal_Bool bRet = sal_False;
+
+ if( pCurCrsr->GetPoint()->nNode.GetIndex() ==
+ pCurCrsr->GetMark()->nNode.GetIndex() && pCurCrsr == pCurCrsr->GetNext() )
+ {
+ xub_StrLen nStt = pCurCrsr->GetPoint()->nContent.GetIndex(),
+ nEnd = pCurCrsr->GetMark()->nContent.GetIndex();
+ if( nStt > nEnd )
+ {
+ xub_StrLen nTmp = nStt;
+ nStt = nEnd;
+ nEnd = nTmp;
+ }
+ const SwCntntNode* pCNd = pCurCrsr->GetCntntNode();
+ bRet = pCNd && !nStt && nEnd == pCNd->Len();
+ }
+ return bRet;
+}
+
+short SwCrsrShell::GetTextDirection( const Point* pPt ) const
+{
+ SwPosition aPos( *pCurCrsr->GetPoint() );
+ Point aPt( pPt ? *pPt : pCurCrsr->GetPtPos() );
+ if( pPt )
+ {
+ SwCrsrMoveState aTmpState( MV_NONE );
+ aTmpState.bSetInReadOnly = IsReadOnlyAvailable();
+
+ GetLayout()->GetCrsrOfst( &aPos, aPt, &aTmpState );
+ }
+
+ return pDoc->GetTextDirection( aPos, &aPt );
+}
+
+sal_Bool SwCrsrShell::IsInVerticalText( const Point* pPt ) const
+{
+ const short nDir = GetTextDirection( pPt );
+ return FRMDIR_VERT_TOP_RIGHT == nDir || FRMDIR_VERT_TOP_LEFT == nDir;
+}
+
+sal_Bool SwCrsrShell::IsInRightToLeftText( const Point* pPt ) const
+{
+ const short nDir = GetTextDirection( pPt );
+ // GetTextDirection uses FRMDIR_VERT_TOP_LEFT to indicate RTL in
+ // vertical environment
+ return FRMDIR_VERT_TOP_LEFT == nDir || FRMDIR_HORI_RIGHT_TOP == nDir;
+}
+
+//
+// If the current cursor position is inside a hidden range, the hidden range
+// is selected:
+//
+bool SwCrsrShell::SelectHiddenRange()
+{
+ bool bRet = false;
+ if ( !GetViewOptions()->IsShowHiddenChar() && !pCurCrsr->HasMark() )
+ {
+ SwPosition& rPt = *(SwPosition*)pCurCrsr->GetPoint();
+ const SwTxtNode* pNode = rPt.nNode.GetNode().GetTxtNode();
+ if ( pNode )
+ {
+ const xub_StrLen nPos = rPt.nContent.GetIndex();
+
+ // check if nPos is in hidden range
+ xub_StrLen nHiddenStart;
+ xub_StrLen nHiddenEnd;
+ SwScriptInfo::GetBoundsOfHiddenRange( *pNode, nPos, nHiddenStart, nHiddenEnd );
+ if ( STRING_LEN != nHiddenStart )
+ {
+ // make selection:
+ pCurCrsr->SetMark();
+ pCurCrsr->GetMark()->nContent = nHiddenEnd;
+ bRet = true;
+ }
+ }
+ }
+
+ return bRet;
+}
+
+ // die Suchfunktionen
+sal_uLong SwCrsrShell::Find( const SearchOptions& rSearchOpt, sal_Bool bSearchInNotes,
+ SwDocPositions eStart, SwDocPositions eEnde,
+ sal_Bool& bCancel,
+ FindRanges eRng, int bReplace )
+{
+ if( pTblCrsr )
+ GetCrsr();
+ delete pTblCrsr, pTblCrsr = 0;
+ SwCallLink aLk( *this ); // Crsr-Moves ueberwachen, evt. Link callen
+ sal_uLong nRet = pCurCrsr->Find( rSearchOpt, bSearchInNotes, eStart, eEnde, bCancel, eRng, bReplace );
+ if( nRet || bCancel )
+ UpdateCrsr();
+ return nRet;
+}
+
+sal_uLong SwCrsrShell::Find( const SwTxtFmtColl& rFmtColl,
+ SwDocPositions eStart, SwDocPositions eEnde,
+ sal_Bool& bCancel,
+ FindRanges eRng, const SwTxtFmtColl* pReplFmt )
+{
+ if( pTblCrsr )
+ GetCrsr();
+ delete pTblCrsr, pTblCrsr = 0;
+ SwCallLink aLk( *this ); // Crsr-Moves ueberwachen, evt. Link callen
+ sal_uLong nRet = pCurCrsr->Find( rFmtColl, eStart, eEnde, bCancel, eRng, pReplFmt );
+ if( nRet )
+ UpdateCrsr();
+ return nRet;
+}
+
+sal_uLong SwCrsrShell::Find( const SfxItemSet& rSet, sal_Bool bNoCollections,
+ SwDocPositions eStart, SwDocPositions eEnde,
+ sal_Bool& bCancel,
+ FindRanges eRng, const SearchOptions* pSearchOpt,
+ const SfxItemSet* rReplSet )
+{
+ if( pTblCrsr )
+ GetCrsr();
+ delete pTblCrsr, pTblCrsr = 0;
+ SwCallLink aLk( *this ); // Crsr-Moves ueberwachen, evt. Link callen
+ sal_uLong nRet = pCurCrsr->Find( rSet, bNoCollections, eStart, eEnde, bCancel,
+ eRng, pSearchOpt, rReplSet );
+ if( nRet )
+ UpdateCrsr();
+ return nRet;
+}
+
+void SwCrsrShell::SetSelection( const SwPaM& rCrsr )
+{
+ StartAction();
+ SwPaM* pCrsr = GetCrsr();
+ *pCrsr->GetPoint() = *rCrsr.GetPoint();
+ if(rCrsr.HasMark())
+ {
+ pCrsr->SetMark();
+ *pCrsr->GetMark() = *rCrsr.GetMark();
+ }
+ if((SwPaM*)rCrsr.GetNext() != &rCrsr)
+ {
+ const SwPaM *_pStartCrsr = (SwPaM*)rCrsr.GetNext();
+ do
+ {
+ SwPaM* pCurrentCrsr = CreateCrsr();
+ *pCurrentCrsr->GetPoint() = *_pStartCrsr->GetPoint();
+ if(_pStartCrsr->HasMark())
+ {
+ pCurrentCrsr->SetMark();
+ *pCurrentCrsr->GetMark() = *_pStartCrsr->GetMark();
+ }
+ } while( (_pStartCrsr=(SwPaM *)_pStartCrsr->GetNext()) != &rCrsr );
+ }
+ EndAction();
+}
+
+void lcl_RemoveMark( SwPaM* pPam )
+{
+ OSL_ENSURE( pPam->HasMark(), "Don't remove pPoint!" );
+ pPam->GetMark()->nContent.Assign( 0, 0 );
+ pPam->GetMark()->nNode = 0;
+ pPam->DeleteMark();
+}
+
+const SwStartNode* lcl_NodeContext( const SwNode& rNode )
+{
+ const SwStartNode *pRet = rNode.StartOfSectionNode();
+ while( pRet->IsSectionNode() || pRet->IsTableNode() ||
+ pRet->GetStartNodeType() == SwTableBoxStartNode )
+ {
+ pRet = pRet->StartOfSectionNode();
+ }
+ return pRet;
+}
+
+/**
+ Checks if a position is valid. To be valid the position's node must
+ be a content node and the content must not be unregistered.
+
+ @param aPos the position to check.
+*/
+bool lcl_PosOk(const SwPosition & aPos)
+{
+ return NULL != aPos.nNode.GetNode().GetCntntNode() &&
+ SwIndexReg::pEmptyIndexArray != aPos.nContent.GetIdxReg();
+}
+
+/**
+ Checks if a PaM is valid. For a PaM to be valid its point must be
+ valid. Additionaly if the PaM has a mark this has to be valid, too.
+
+ @param aPam the PaM to check
+*/
+static bool lcl_CrsrOk(SwPaM & aPam)
+{
+ return lcl_PosOk(*aPam.GetPoint()) && (! aPam.HasMark()
+ || lcl_PosOk(*aPam.GetMark()));
+}
+
+void SwCrsrShell::ClearUpCrsrs()
+{
+ // start of the ring
+ SwPaM * pStartCrsr = GetCrsr();
+ // start loop with second entry of the ring
+ SwPaM * pCrsr = (SwPaM *) pStartCrsr->GetNext();
+ SwPaM * pTmpCrsr;
+ bool bChanged = false;
+
+ /*
+ For all entries in the ring except the start entry delete the
+ entry if it is invalid.
+ */
+ while (pCrsr != pStartCrsr)
+ {
+ pTmpCrsr = (SwPaM *) pCrsr->GetNext();
+
+ if ( ! lcl_CrsrOk(*pCrsr))
+ {
+ delete pCrsr;
+
+ bChanged = true;
+ }
+
+ pCrsr = pTmpCrsr;
+ }
+
+ if( pStartCrsr->HasMark() && !lcl_PosOk( *pStartCrsr->GetMark() ) )
+ {
+ lcl_RemoveMark( pStartCrsr );
+ bChanged = true;
+ }
+ if( !lcl_PosOk( *pStartCrsr->GetPoint() ) )
+ {
+ SwNodes & aNodes = GetDoc()->GetNodes();
+ const SwNode* pStart = lcl_NodeContext( pStartCrsr->GetPoint()->nNode.GetNode() );
+ SwNodeIndex aIdx( pStartCrsr->GetPoint()->nNode );
+ SwNode * pNode = aNodes.GoPrevious(&aIdx);
+ if( pNode == NULL || lcl_NodeContext( *pNode ) != pStart )
+ aNodes.GoNext( &aIdx );
+ if( pNode == NULL || lcl_NodeContext( *pNode ) != pStart )
+ {
+ /*
+ If the start entry of the ring is invalid replace it with a
+ cursor pointing to the beginning of the first content node in
+ the document.
+ */
+ aIdx = (*(aNodes.GetEndOfContent().StartOfSectionNode()));
+ pNode = aNodes.GoNext( &aIdx );
+ }
+ bool bFound = (pNode != NULL);
+
+ OSL_ENSURE(bFound, "no content node found");
+
+ if (bFound)
+ {
+ SwPaM aTmpPam(*pNode);
+ *pStartCrsr = aTmpPam;
+ }
+
+ bChanged = true;
+ }
+
+ /*
+ If at least one of the cursors in the ring have been deleted or
+ replaced, remove the table cursor.
+ */
+ if (pTblCrsr != NULL && bChanged)
+ TblCrsrToCursor();
+}
+
+String SwCrsrShell::GetCrsrDescr() const
+{
+ String aResult;
+
+ if (IsMultiSelection())
+ aResult += String(SW_RES(STR_MULTISEL));
+ else
+ aResult = GetDoc()->GetPaMDescr(*GetCrsr());
+
+ return aResult;
+}
+
+// SMARTTAGS
+
+void lcl_FillRecognizerData( uno::Sequence< rtl::OUString >& rSmartTagTypes,
+ uno::Sequence< uno::Reference< container::XStringKeyMap > >& rStringKeyMaps,
+ const SwWrongList& rSmartTagList, xub_StrLen nCurrent )
+{
+ // Insert smart tag information
+ std::vector< rtl::OUString > aSmartTagTypes;
+ std::vector< uno::Reference< container::XStringKeyMap > > aStringKeyMaps;
+
+ for ( sal_uInt16 i = 0; i < rSmartTagList.Count(); ++i )
+ {
+ const xub_StrLen nSTPos = rSmartTagList.Pos( i );
+ const xub_StrLen nSTLen = rSmartTagList.Len( i );
+
+ if ( nSTPos <= nCurrent && nCurrent < nSTPos + nSTLen )
+ {
+ const SwWrongArea* pArea = rSmartTagList.GetElement( i );
+ if ( pArea )
+ {
+ aSmartTagTypes.push_back( pArea->maType );
+ aStringKeyMaps.push_back( pArea->mxPropertyBag );
+ }
+ }
+ }
+
+ if ( aSmartTagTypes.size() )
+ {
+ rSmartTagTypes.realloc( aSmartTagTypes.size() );
+ rStringKeyMaps.realloc( aSmartTagTypes.size() );
+
+ std::vector< rtl::OUString >::const_iterator aTypesIter = aSmartTagTypes.begin();
+ sal_uInt16 i = 0;
+ for ( aTypesIter = aSmartTagTypes.begin(); aTypesIter != aSmartTagTypes.end(); ++aTypesIter )
+ rSmartTagTypes[i++] = *aTypesIter;
+
+ std::vector< uno::Reference< container::XStringKeyMap > >::const_iterator aMapsIter = aStringKeyMaps.begin();
+ i = 0;
+ for ( aMapsIter = aStringKeyMaps.begin(); aMapsIter != aStringKeyMaps.end(); ++aMapsIter )
+ rStringKeyMaps[i++] = *aMapsIter;
+ }
+}
+
+void lcl_FillTextRange( uno::Reference<text::XTextRange>& rRange,
+ SwTxtNode& rNode, xub_StrLen nBegin, xub_StrLen nLen )
+{
+ // create SwPosition for nStartIndex
+ SwIndex aIndex( &rNode, nBegin );
+ SwPosition aStartPos( rNode, aIndex );
+
+ // create SwPosition for nEndIndex
+ SwPosition aEndPos( aStartPos );
+ aEndPos.nContent = nBegin + nLen;
+
+ const uno::Reference<text::XTextRange> xRange =
+ SwXTextRange::CreateXTextRange(*rNode.GetDoc(), aStartPos, &aEndPos);
+
+ rRange = xRange;
+}
+
+void SwCrsrShell::GetSmartTagTerm( uno::Sequence< rtl::OUString >& rSmartTagTypes,
+ uno::Sequence< uno::Reference< container::XStringKeyMap > >& rStringKeyMaps,
+ uno::Reference< text::XTextRange>& rRange ) const
+{
+ if ( !SwSmartTagMgr::Get().IsSmartTagsEnabled() )
+ return;
+
+ SwPaM* pCrsr = GetCrsr();
+ SwPosition aPos( *pCrsr->GetPoint() );
+ SwTxtNode *pNode = aPos.nNode.GetNode().GetTxtNode();
+ if ( pNode && !pNode->IsInProtectSect() )
+ {
+ const SwWrongList *pSmartTagList = pNode->GetSmartTags();
+ if ( pSmartTagList )
+ {
+ xub_StrLen nCurrent = aPos.nContent.GetIndex();
+ xub_StrLen nBegin = nCurrent;
+ xub_StrLen nLen = 1;
+
+ if( pSmartTagList->InWrongWord( nBegin, nLen ) && !pNode->IsSymbol(nBegin) )
+ {
+ const sal_uInt16 nIndex = pSmartTagList->GetWrongPos( nBegin );
+ const SwWrongList* pSubList = pSmartTagList->SubList( nIndex );
+ if ( pSubList )
+ {
+ pSmartTagList = pSubList;
+ nCurrent = 0;
+ }
+
+ lcl_FillRecognizerData( rSmartTagTypes, rStringKeyMaps, *pSmartTagList, nCurrent );
+ lcl_FillTextRange( rRange, *pNode, nBegin, nLen );
+ }
+ }
+ }
+}
+
+// see also SwEditShell::GetCorrection( const Point* pPt, SwRect& rSelectRect )
+void SwCrsrShell::GetSmartTagTerm( const Point& rPt, SwRect& rSelectRect,
+ uno::Sequence< rtl::OUString >& rSmartTagTypes,
+ uno::Sequence< uno::Reference< container::XStringKeyMap > >& rStringKeyMaps,
+ uno::Reference<text::XTextRange>& rRange )
+{
+ if ( !SwSmartTagMgr::Get().IsSmartTagsEnabled() )
+ return;
+
+ SwPaM* pCrsr = GetCrsr();
+ SwPosition aPos( *pCrsr->GetPoint() );
+ Point aPt( rPt );
+ SwCrsrMoveState eTmpState( MV_SETONLYTEXT );
+ SwSpecialPos aSpecialPos;
+ eTmpState.pSpecialPos = &aSpecialPos;
+ SwTxtNode *pNode;
+ const SwWrongList *pSmartTagList;
+
+ if( GetLayout()->GetCrsrOfst( &aPos, aPt, &eTmpState ) &&
+ 0 != (pNode = aPos.nNode.GetNode().GetTxtNode()) &&
+ 0 != (pSmartTagList = pNode->GetSmartTags()) &&
+ !pNode->IsInProtectSect() )
+ {
+ xub_StrLen nCurrent = aPos.nContent.GetIndex();
+ xub_StrLen nBegin = nCurrent;
+ xub_StrLen nLen = 1;
+
+ if( pSmartTagList->InWrongWord( nBegin, nLen ) && !pNode->IsSymbol(nBegin) )
+ {
+ const sal_uInt16 nIndex = pSmartTagList->GetWrongPos( nBegin );
+ const SwWrongList* pSubList = pSmartTagList->SubList( nIndex );
+ if ( pSubList )
+ {
+ pSmartTagList = pSubList;
+ nCurrent = eTmpState.pSpecialPos->nCharOfst;
+ }
+
+ lcl_FillRecognizerData( rSmartTagTypes, rStringKeyMaps, *pSmartTagList, nCurrent );
+ lcl_FillTextRange( rRange, *pNode, nBegin, nLen );
+
+ // get smarttag word
+ String aText( pNode->GetTxt().Copy( nBegin, nLen ) );
+
+ //save the start and end positons of the line and the starting point
+ Push();
+ LeftMargin();
+ xub_StrLen nLineStart = GetCrsr()->GetPoint()->nContent.GetIndex();
+ RightMargin();
+ xub_StrLen nLineEnd = GetCrsr()->GetPoint()->nContent.GetIndex();
+ Pop(sal_False);
+
+ // make sure the selection build later from the
+ // data below does not include footnotes and other
+ // "in word" character to the left and right in order
+ // to preserve those. Therefore count those "in words"
+ // in order to modify the selection accordingly.
+ const sal_Unicode* pChar = aText.GetBuffer();
+ xub_StrLen nLeft = 0;
+ while (pChar && *pChar++ == CH_TXTATR_INWORD)
+ ++nLeft;
+ pChar = aText.Len() ? aText.GetBuffer() + aText.Len() - 1 : 0;
+ xub_StrLen nRight = 0;
+ while (pChar && *pChar-- == CH_TXTATR_INWORD)
+ ++nRight;
+
+ aPos.nContent = nBegin + nLeft;
+ pCrsr = GetCrsr();
+ *pCrsr->GetPoint() = aPos;
+ pCrsr->SetMark();
+ ExtendSelection( sal_True, nLen - nLeft - nRight );
+ //no determine the rectangle in the current line
+ xub_StrLen nWordStart = (nBegin + nLeft) < nLineStart ? nLineStart : nBegin + nLeft;
+ //take one less than the line end - otherwise the next line would be calculated
+ xub_StrLen nWordEnd = (nBegin + nLen - nLeft - nRight) > nLineEnd ? nLineEnd : (nBegin + nLen - nLeft - nRight);
+ Push();
+ pCrsr->DeleteMark();
+ SwIndex& rContent = GetCrsr()->GetPoint()->nContent;
+ rContent = nWordStart;
+ SwRect aStartRect;
+ SwCrsrMoveState aState;
+ aState.bRealWidth = sal_True;
+ SwCntntNode* pCntntNode = pCrsr->GetCntntNode();
+ SwCntntFrm *pCntntFrame = pCntntNode->getLayoutFrm( GetLayout(), &rPt, pCrsr->GetPoint(), sal_False);
+
+ pCntntFrame->GetCharRect( aStartRect, *pCrsr->GetPoint(), &aState );
+ rContent = nWordEnd - 1;
+ SwRect aEndRect;
+ pCntntFrame->GetCharRect( aEndRect, *pCrsr->GetPoint(),&aState );
+ rSelectRect = aStartRect.Union( aEndRect );
+ Pop(sal_False);
+ }
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/crsr/crstrvl.cxx b/sw/source/core/crsr/crstrvl.cxx
new file mode 100644
index 000000000000..712670302367
--- /dev/null
+++ b/sw/source/core/crsr/crstrvl.cxx
@@ -0,0 +1,2194 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+
+#include <hintids.hxx>
+#include <svl/itemiter.hxx>
+#include <editeng/lrspitem.hxx>
+#include <editeng/adjitem.hxx>
+#include <editeng/brkitem.hxx>
+#include <svx/svdobj.hxx>
+#include <crsrsh.hxx>
+#include <doc.hxx>
+#include <IDocumentUndoRedo.hxx>
+#include <pagefrm.hxx>
+#include <cntfrm.hxx>
+#include <rootfrm.hxx>
+#include <pam.hxx>
+#include <ndtxt.hxx>
+#include <fldbas.hxx>
+#include <swtable.hxx> // SwTxtFld
+#include <docary.hxx>
+#include <txtfld.hxx>
+#include <fmtfld.hxx>
+#include <txtftn.hxx>
+#include <txtinet.hxx>
+#include <fmtinfmt.hxx>
+#include <txttxmrk.hxx>
+#include <frmfmt.hxx>
+#include <flyfrm.hxx>
+#include <viscrs.hxx>
+#include <callnk.hxx>
+#include <doctxm.hxx>
+#include <docfld.hxx>
+#include <expfld.hxx>
+#include <reffld.hxx>
+#include <flddat.hxx> // SwTxtFld
+#include <cellatr.hxx>
+#include <swundo.hxx>
+#include <redline.hxx>
+#include <fmtcntnt.hxx>
+#include <fmthdft.hxx>
+#include <pagedesc.hxx>
+#include <fesh.hxx>
+#include <charfmt.hxx>
+#include <fmturl.hxx>
+#include "txtfrm.hxx"
+#include <wrong.hxx>
+#include <switerator.hxx>
+#include <vcl/window.hxx>
+#include <docufld.hxx>
+
+using namespace ::com::sun::star;
+
+
+// zum naechsten/vorhergehenden Punkt auf gleicher Ebene
+sal_Bool SwCrsrShell::GotoNextNum()
+{
+ sal_Bool bRet = GetDoc()->GotoNextNum( *pCurCrsr->GetPoint() );
+ if( bRet )
+ {
+ SwCallLink aLk( *this ); // Crsr-Moves ueberwachen,
+ SwCrsrSaveState aSaveState( *pCurCrsr );
+ if( !ActionPend() )
+ {
+ SET_CURR_SHELL( this );
+ // dann versuche den Cursor auf die Position zu setzen,
+ // auf halber Heohe vom Char-SRectangle
+ Point aPt( pCurCrsr->GetPtPos() );
+ SwCntntFrm * pFrm = pCurCrsr->GetCntntNode()->getLayoutFrm( GetLayout(), &aPt,
+ pCurCrsr->GetPoint() );
+ pFrm->GetCharRect( aCharRect, *pCurCrsr->GetPoint() );
+ pFrm->Calc();
+ if( pFrm->IsVertical() )
+ {
+ aPt.X() = aCharRect.Center().X();
+ aPt.Y() = pFrm->Frm().Top() + nUpDownX;
+ }
+ else
+ {
+ aPt.Y() = aCharRect.Center().Y();
+ aPt.X() = pFrm->Frm().Left() + nUpDownX;
+ }
+ pFrm->GetCrsrOfst( pCurCrsr->GetPoint(), aPt );
+ bRet = !pCurCrsr->IsSelOvr( nsSwCursorSelOverFlags::SELOVER_TOGGLE |
+ nsSwCursorSelOverFlags::SELOVER_CHANGEPOS );
+ if( bRet )
+ UpdateCrsr(SwCrsrShell::UPDOWN |
+ SwCrsrShell::SCROLLWIN | SwCrsrShell::CHKRANGE |
+ SwCrsrShell::READONLY );
+ }
+ }
+ return bRet;
+}
+
+
+sal_Bool SwCrsrShell::GotoPrevNum()
+{
+ sal_Bool bRet = GetDoc()->GotoPrevNum( *pCurCrsr->GetPoint() );
+ if( bRet )
+ {
+ SwCallLink aLk( *this ); // Crsr-Moves ueberwachen,
+ SwCrsrSaveState aSaveState( *pCurCrsr );
+ if( !ActionPend() )
+ {
+ SET_CURR_SHELL( this );
+ // dann versuche den Cursor auf die Position zu setzen,
+ // auf halber Heohe vom Char-SRectangle
+ Point aPt( pCurCrsr->GetPtPos() );
+ SwCntntFrm * pFrm = pCurCrsr->GetCntntNode()->getLayoutFrm( GetLayout(), &aPt,
+ pCurCrsr->GetPoint() );
+ pFrm->GetCharRect( aCharRect, *pCurCrsr->GetPoint() );
+ pFrm->Calc();
+ if( pFrm->IsVertical() )
+ {
+ aPt.X() = aCharRect.Center().X();
+ aPt.Y() = pFrm->Frm().Top() + nUpDownX;
+ }
+ else
+ {
+ aPt.Y() = aCharRect.Center().Y();
+ aPt.X() = pFrm->Frm().Left() + nUpDownX;
+ }
+ pFrm->GetCrsrOfst( pCurCrsr->GetPoint(), aPt );
+ bRet = !pCurCrsr->IsSelOvr( nsSwCursorSelOverFlags::SELOVER_TOGGLE |
+ nsSwCursorSelOverFlags::SELOVER_CHANGEPOS );
+ if( bRet )
+ UpdateCrsr(SwCrsrShell::UPDOWN |
+ SwCrsrShell::SCROLLWIN | SwCrsrShell::CHKRANGE |
+ SwCrsrShell::READONLY );
+ }
+ }
+ return bRet;
+}
+
+// springe aus dem Content zum Header
+
+sal_Bool SwCrsrShell::GotoHeaderTxt()
+{
+ const SwFrm* pFrm = GetCurrFrm()->FindPageFrm();
+ while( pFrm && !pFrm->IsHeaderFrm() )
+ pFrm = pFrm->GetLower();
+ // Header gefunden, dann suche den 1.Cntnt-Frame
+ while( pFrm && !pFrm->IsCntntFrm() )
+ pFrm = pFrm->GetLower();
+ if( pFrm )
+ {
+ SET_CURR_SHELL( this );
+ // hole den Header-Frame
+ SwCallLink aLk( *this ); // Crsr-Moves ueberwachen,
+ SwCursor *pTmpCrsr = getShellCrsr( true );
+ SwCrsrSaveState aSaveState( *pTmpCrsr );
+ pFrm->Calc();
+ Point aPt( pFrm->Frm().Pos() + pFrm->Prt().Pos() );
+ pFrm->GetCrsrOfst( pTmpCrsr->GetPoint(), aPt );
+ if( !pTmpCrsr->IsSelOvr() )
+ UpdateCrsr();
+ else
+ pFrm = 0;
+ }
+ return 0 != pFrm;
+}
+
+
+// springe aus dem Content zum Footer
+
+sal_Bool SwCrsrShell::GotoFooterTxt()
+{
+ const SwPageFrm* pFrm = GetCurrFrm()->FindPageFrm();
+ if( pFrm )
+ {
+ const SwFrm* pLower = pFrm->GetLastLower();
+
+ while( pLower && !pLower->IsFooterFrm() )
+ pLower = pLower->GetLower();
+ // Header gefunden, dann suche den 1.Cntnt-Frame
+ while( pLower && !pLower->IsCntntFrm() )
+ pLower = pLower->GetLower();
+
+ if( pLower )
+ {
+ SwCursor *pTmpCrsr = getShellCrsr( true );
+ SET_CURR_SHELL( this );
+ // hole eine Position im Footer
+ SwCallLink aLk( *this ); // Crsr-Moves ueberwachen,
+ SwCrsrSaveState aSaveState( *pTmpCrsr );
+ pLower->Calc();
+ Point aPt( pLower->Frm().Pos() + pLower->Prt().Pos() );
+ pLower->GetCrsrOfst( pTmpCrsr->GetPoint(), aPt );
+ if( !pTmpCrsr->IsSelOvr() )
+ UpdateCrsr();
+ else
+ pFrm = 0;
+ }
+ else
+ pFrm = 0;
+ }
+ else
+ pFrm = 0;
+ return 0 != pFrm;
+}
+
+sal_Bool SwCrsrShell::SetCrsrInHdFt( sal_uInt16 nDescNo, sal_Bool bInHeader )
+{
+ sal_Bool bRet = sal_False;
+ SwDoc *pMyDoc = GetDoc();
+
+ SET_CURR_SHELL( this );
+
+ if( USHRT_MAX == nDescNo )
+ {
+ // dann den akt. nehmen
+ const SwPageFrm* pPage = GetCurrFrm()->FindPageFrm();
+ if( pPage )
+ for( sal_uInt16 i = 0; i < pMyDoc->GetPageDescCnt(); ++i )
+ if( pPage->GetPageDesc() ==
+ &const_cast<const SwDoc *>(pMyDoc)->GetPageDesc( i ) )
+ {
+ nDescNo = i;
+ break;
+ }
+ }
+
+ if( USHRT_MAX != nDescNo && nDescNo < pMyDoc->GetPageDescCnt() )
+ {
+ //dann teste mal, ob ueberhaupt das Attribut vorhanden ist.
+ const SwPageDesc& rDesc = const_cast<const SwDoc *>(pMyDoc)
+ ->GetPageDesc( nDescNo );
+ const SwFmtCntnt* pCnt = 0;
+ if( bInHeader )
+ {
+ // gespiegelte Seiten??? erstmal nicht beachten
+ const SwFmtHeader& rHd = rDesc.GetMaster().GetHeader();
+ if( rHd.GetHeaderFmt() )
+ pCnt = &rHd.GetHeaderFmt()->GetCntnt();
+ }
+ else
+ {
+ const SwFmtFooter& rFt = rDesc.GetMaster().GetFooter();
+ if( rFt.GetFooterFmt() )
+ pCnt = &rFt.GetFooterFmt()->GetCntnt();
+ }
+
+ if( pCnt && pCnt->GetCntntIdx() )
+ {
+ SwNodeIndex aIdx( *pCnt->GetCntntIdx(), 1 );
+ SwCntntNode* pCNd = aIdx.GetNode().GetCntntNode();
+ if( !pCNd )
+ pCNd = pMyDoc->GetNodes().GoNext( &aIdx );
+
+ const SwFrm* pFrm;
+ Point aPt( pCurCrsr->GetPtPos() );
+
+ if( pCNd && 0 != ( pFrm = pCNd->getLayoutFrm( GetLayout(), &aPt, 0, sal_False ) ))
+ {
+ // dann kann der Cursor ja auch hinein gesetzt werden
+ SwCallLink aLk( *this ); // Crsr-Moves ueberwachen, evt. Link callen
+ SwCrsrSaveState aSaveState( *pCurCrsr );
+
+ ClearMark();
+
+ SwPosition& rPos = *pCurCrsr->GetPoint();
+ rPos.nNode = *pCNd;
+ rPos.nContent.Assign( pCNd, 0 );
+
+ bRet = !pCurCrsr->IsSelOvr();
+ if( bRet )
+ UpdateCrsr( SwCrsrShell::SCROLLWIN | SwCrsrShell::CHKRANGE |
+ SwCrsrShell::READONLY );
+ }
+ }
+ }
+ return bRet;
+}
+
+// springe zum naechsten Verzeichnis
+
+sal_Bool SwCrsrShell::GotoNextTOXBase( const String* pName )
+{
+ sal_Bool bRet = sal_False;
+
+ const SwSectionFmts& rFmts = GetDoc()->GetSections();
+ SwCntntNode* pFnd = 0;
+ for( sal_uInt16 n = rFmts.Count(); n; )
+ {
+ const SwSection* pSect = rFmts[ --n ]->GetSection();
+ const SwSectionNode* pSectNd;
+ if( TOX_CONTENT_SECTION == pSect->GetType() &&
+ 0 != ( pSectNd = pSect->GetFmt()->GetSectionNode() ) &&
+ pCurCrsr->GetPoint()->nNode < pSectNd->GetIndex() &&
+ ( !pFnd || pFnd->GetIndex() > pSectNd->GetIndex() ) &&
+ ( !pName || *pName == ((SwTOXBaseSection*)pSect)->GetTOXName() )
+ )
+ {
+ SwNodeIndex aIdx( *pSectNd, 1 );
+ SwCntntNode* pCNd = aIdx.GetNode().GetCntntNode();
+ if( !pCNd )
+ pCNd = GetDoc()->GetNodes().GoNext( &aIdx );
+ const SwCntntFrm* pCFrm;
+ if( pCNd &&
+ pCNd->EndOfSectionIndex() <= pSectNd->EndOfSectionIndex() &&
+ 0 != ( pCFrm = pCNd->getLayoutFrm( GetLayout() ) ) &&
+ ( IsReadOnlyAvailable() || !pCFrm->IsProtected() ))
+ {
+ pFnd = pCNd;
+ }
+ }
+ }
+ if( pFnd )
+ {
+ SwCallLink aLk( *this ); // Crsr-Moves ueberwachen,
+ SwCrsrSaveState aSaveState( *pCurCrsr );
+ pCurCrsr->GetPoint()->nNode = *pFnd;
+ pCurCrsr->GetPoint()->nContent.Assign( pFnd, 0 );
+ bRet = !pCurCrsr->IsSelOvr();
+ if( bRet )
+ UpdateCrsr(SwCrsrShell::SCROLLWIN|SwCrsrShell::CHKRANGE|SwCrsrShell::READONLY);
+ }
+ return bRet;
+}
+
+// springe zum vorherigen Verzeichnis
+
+
+sal_Bool SwCrsrShell::GotoPrevTOXBase( const String* pName )
+{
+ sal_Bool bRet = sal_False;
+
+ const SwSectionFmts& rFmts = GetDoc()->GetSections();
+ SwCntntNode* pFnd = 0;
+ for( sal_uInt16 n = rFmts.Count(); n; )
+ {
+ const SwSection* pSect = rFmts[ --n ]->GetSection();
+ const SwSectionNode* pSectNd;
+ if( TOX_CONTENT_SECTION == pSect->GetType() &&
+ 0 != ( pSectNd = pSect->GetFmt()->GetSectionNode() ) &&
+ pCurCrsr->GetPoint()->nNode > pSectNd->EndOfSectionIndex() &&
+ ( !pFnd || pFnd->GetIndex() < pSectNd->GetIndex() ) &&
+ ( !pName || *pName == ((SwTOXBaseSection*)pSect)->GetTOXName() )
+ )
+ {
+ SwNodeIndex aIdx( *pSectNd, 1 );
+ SwCntntNode* pCNd = aIdx.GetNode().GetCntntNode();
+ if( !pCNd )
+ pCNd = GetDoc()->GetNodes().GoNext( &aIdx );
+ const SwCntntFrm* pCFrm;
+ if( pCNd &&
+ pCNd->EndOfSectionIndex() <= pSectNd->EndOfSectionIndex() &&
+ 0 != ( pCFrm = pCNd->getLayoutFrm( GetLayout() ) ) &&
+ ( IsReadOnlyAvailable() || !pCFrm->IsProtected() ))
+ {
+ pFnd = pCNd;
+ }
+ }
+ }
+
+ if( pFnd )
+ {
+ SwCallLink aLk( *this ); // Crsr-Moves ueberwachen,
+ SwCrsrSaveState aSaveState( *pCurCrsr );
+ pCurCrsr->GetPoint()->nNode = *pFnd;
+ pCurCrsr->GetPoint()->nContent.Assign( pFnd, 0 );
+ bRet = !pCurCrsr->IsSelOvr();
+ if( bRet )
+ UpdateCrsr(SwCrsrShell::SCROLLWIN|SwCrsrShell::CHKRANGE|SwCrsrShell::READONLY);
+ }
+ return bRet;
+}
+
+// springe zum Verzeichnis vom TOXMark
+
+sal_Bool SwCrsrShell::GotoTOXMarkBase()
+{
+ sal_Bool bRet = sal_False;
+
+ SwTOXMarks aMarks;
+ sal_uInt16 nCnt = GetDoc()->GetCurTOXMark( *pCurCrsr->GetPoint(), aMarks );
+ if( nCnt )
+ {
+ // dann nehme den 1. und hole den Verzeichnis-Typ.
+ // Suche in seiner Abhaengigkeitsliste nach dem eigentlichem
+ // Verzeichnis
+ const SwTOXType* pType = aMarks[0]->GetTOXType();
+ SwIterator<SwTOXBase,SwTOXType> aIter( *pType );
+ const SwSectionNode* pSectNd;
+ const SwSectionFmt* pSectFmt;
+
+ for( SwTOXBase* pTOX = aIter.First(); pTOX; pTOX = aIter.Next() )
+ {
+ if( pTOX->ISA( SwTOXBaseSection ) &&
+ 0 != ( pSectFmt = ((SwTOXBaseSection*)pTOX)->GetFmt() ) &&
+ 0 != ( pSectNd = pSectFmt->GetSectionNode() ))
+ {
+ SwNodeIndex aIdx( *pSectNd, 1 );
+ SwCntntNode* pCNd = aIdx.GetNode().GetCntntNode();
+ if( !pCNd )
+ pCNd = GetDoc()->GetNodes().GoNext( &aIdx );
+ const SwCntntFrm* pCFrm;
+ if( pCNd &&
+ pCNd->EndOfSectionIndex() < pSectNd->EndOfSectionIndex() &&
+ 0 != ( pCFrm = pCNd->getLayoutFrm( GetLayout() ) ) &&
+ ( IsReadOnlyAvailable() || !pCFrm->IsProtected() ))
+ {
+ SwCallLink aLk( *this ); // Crsr-Moves ueberwachen,
+ SwCrsrSaveState aSaveState( *pCurCrsr );
+ pCurCrsr->GetPoint()->nNode = *pCNd;
+ pCurCrsr->GetPoint()->nContent.Assign( pCNd, 0 );
+ bRet = !pCurCrsr->IsInProtectTable() &&
+ !pCurCrsr->IsSelOvr();
+ if( bRet )
+ UpdateCrsr(SwCrsrShell::SCROLLWIN|SwCrsrShell::CHKRANGE|SwCrsrShell::READONLY);
+ break;
+ }
+ }
+ }
+ }
+ return bRet;
+}
+
+
+ // springe zur naechsten (vorherigen) Tabellenformel
+ // optional auch nur zu kaputten Formeln springen
+sal_Bool SwCrsrShell::GotoNxtPrvTblFormula( sal_Bool bNext, sal_Bool bOnlyErrors )
+{
+ if( IsTableMode() )
+ return sal_False;
+
+ sal_Bool bFnd = sal_False;
+ SwPosition& rPos = *pCurCrsr->GetPoint();
+
+ Point aPt;
+ SwPosition aFndPos( GetDoc()->GetNodes().GetEndOfContent() );
+ if( !bNext )
+ aFndPos.nNode = 0;
+ _SetGetExpFld aFndGEF( aFndPos ), aCurGEF( rPos );
+
+ {
+ const SwNode* pSttNd = rPos.nNode.GetNode().FindTableBoxStartNode();
+ if( pSttNd )
+ {
+ const SwTableBox* pTBox = pSttNd->FindTableNode()->GetTable().
+ GetTblBox( pSttNd->GetIndex() );
+ if( pTBox )
+ aCurGEF = _SetGetExpFld( *pTBox );
+ }
+ }
+
+ if( rPos.nNode < GetDoc()->GetNodes().GetEndOfExtras() )
+ // auch beim Einsammeln wird nur der erste Frame benutzt!
+ aCurGEF.SetBodyPos( *rPos.nNode.GetNode().GetCntntNode()->getLayoutFrm( GetLayout(),
+ &aPt, &rPos, sal_False ) );
+ {
+ const SfxPoolItem* pItem;
+ const SwTableBox* pTBox;
+ sal_uInt32 n, nMaxItems = GetDoc()->GetAttrPool().GetItemCount2( RES_BOXATR_FORMULA );
+
+ for( n = 0; n < nMaxItems; ++n )
+ if( 0 != (pItem = GetDoc()->GetAttrPool().GetItem2(
+ RES_BOXATR_FORMULA, n ) ) &&
+ 0 != (pTBox = ((SwTblBoxFormula*)pItem)->GetTableBox() ) &&
+ pTBox->GetSttNd() &&
+ pTBox->GetSttNd()->GetNodes().IsDocNodes() &&
+ ( !bOnlyErrors ||
+ !((SwTblBoxFormula*)pItem)->HasValidBoxes() ) )
+ {
+ const SwCntntFrm* pCFrm;
+ SwNodeIndex aIdx( *pTBox->GetSttNd() );
+ const SwCntntNode* pCNd = GetDoc()->GetNodes().GoNext( &aIdx );
+ if( pCNd && 0 != ( pCFrm = pCNd->getLayoutFrm( GetLayout(), &aPt, 0, sal_False ) ) &&
+ (IsReadOnlyAvailable() || !pCFrm->IsProtected() ))
+ {
+ _SetGetExpFld aCmp( *pTBox );
+ aCmp.SetBodyPos( *pCFrm );
+
+ if( bNext ? ( aCurGEF < aCmp && aCmp < aFndGEF )
+ : ( aCmp < aCurGEF && aFndGEF < aCmp ))
+ {
+ aFndGEF = aCmp;
+ bFnd = sal_True;
+ }
+ }
+ }
+ }
+
+ if( bFnd )
+ {
+ SET_CURR_SHELL( this );
+ SwCallLink aLk( *this ); // Crsr-Moves ueberwachen, evt. Link callen
+ SwCrsrSaveState aSaveState( *pCurCrsr );
+
+ aFndGEF.GetPosOfContent( rPos );
+ pCurCrsr->DeleteMark();
+
+ bFnd = !pCurCrsr->IsSelOvr();
+ if( bFnd )
+ UpdateCrsr( SwCrsrShell::SCROLLWIN | SwCrsrShell::CHKRANGE |
+ SwCrsrShell::READONLY );
+ }
+ return bFnd;
+}
+
+// springe zum naechsten (vorherigen) Verzeichniseintrag
+sal_Bool SwCrsrShell::GotoNxtPrvTOXMark( sal_Bool bNext )
+{
+ if( IsTableMode() )
+ return sal_False;
+
+ sal_Bool bFnd = sal_False;
+ SwPosition& rPos = *pCurCrsr->GetPoint();
+
+ Point aPt;
+ SwPosition aFndPos( GetDoc()->GetNodes().GetEndOfContent() );
+ if( !bNext )
+ aFndPos.nNode = 0;
+ _SetGetExpFld aFndGEF( aFndPos ), aCurGEF( rPos );
+
+ if( rPos.nNode.GetIndex() < GetDoc()->GetNodes().GetEndOfExtras().GetIndex() )
+ // auch beim Einsammeln wird nur der erste Frame benutzt!
+ aCurGEF.SetBodyPos( *rPos.nNode.GetNode().
+ GetCntntNode()->getLayoutFrm( GetLayout(), &aPt, &rPos, sal_False ) );
+ {
+ const SfxPoolItem* pItem;
+ const SwCntntFrm* pCFrm;
+ const SwTxtNode* pTxtNd;
+ const SwTxtTOXMark* pTxtTOX;
+ sal_uInt32 n, nMaxItems = GetDoc()->GetAttrPool().GetItemCount2( RES_TXTATR_TOXMARK );
+
+ for( n = 0; n < nMaxItems; ++n )
+ if( 0 != (pItem = GetDoc()->GetAttrPool().GetItem2(
+ RES_TXTATR_TOXMARK, n ) ) &&
+ 0 != (pTxtTOX = ((SwTOXMark*)pItem)->GetTxtTOXMark() ) &&
+ ( pTxtNd = &pTxtTOX->GetTxtNode())->GetNodes().IsDocNodes() &&
+ 0 != ( pCFrm = pTxtNd->getLayoutFrm( GetLayout(), &aPt, 0, sal_False )) &&
+ ( IsReadOnlyAvailable() || !pCFrm->IsProtected() ))
+ {
+ SwNodeIndex aNdIndex( *pTxtNd ); // UNIX benoetigt dieses Obj.
+ _SetGetExpFld aCmp( aNdIndex, *pTxtTOX, 0 );
+ aCmp.SetBodyPos( *pCFrm );
+
+ if( bNext ? ( aCurGEF < aCmp && aCmp < aFndGEF )
+ : ( aCmp < aCurGEF && aFndGEF < aCmp ))
+ {
+ aFndGEF = aCmp;
+ bFnd = sal_True;
+ }
+ }
+ }
+
+ if( bFnd )
+ {
+ SET_CURR_SHELL( this );
+ SwCallLink aLk( *this ); // Crsr-Moves ueberwachen, evt. Link callen
+ SwCrsrSaveState aSaveState( *pCurCrsr );
+
+ aFndGEF.GetPosOfContent( rPos );
+
+ bFnd = !pCurCrsr->IsSelOvr();
+ if( bFnd )
+ UpdateCrsr( SwCrsrShell::SCROLLWIN | SwCrsrShell::CHKRANGE |
+ SwCrsrShell::READONLY );
+ }
+ return bFnd;
+}
+
+/*--------------------------------------------------------------------
+ Beschreibung: Traveling zwischen Markierungen
+ --------------------------------------------------------------------*/
+
+const SwTOXMark& SwCrsrShell::GotoTOXMark( const SwTOXMark& rStart,
+ SwTOXSearch eDir )
+{
+ SET_CURR_SHELL( this );
+ SwCallLink aLk( *this ); // Crsr-Moves ueberwachen, evt. Link callen
+ SwCrsrSaveState aSaveState( *pCurCrsr );
+
+ const SwTOXMark& rNewMark = GetDoc()->GotoTOXMark( rStart, eDir,
+ IsReadOnlyAvailable() );
+ // Position setzen
+ SwPosition& rPos = *GetCrsr()->GetPoint();
+ rPos.nNode = rNewMark.GetTxtTOXMark()->GetTxtNode();
+ rPos.nContent.Assign( rPos.nNode.GetNode().GetCntntNode(),
+ *rNewMark.GetTxtTOXMark()->GetStart() );
+
+ if( !pCurCrsr->IsSelOvr() )
+ UpdateCrsr( SwCrsrShell::SCROLLWIN | SwCrsrShell::CHKRANGE |
+ SwCrsrShell::READONLY );
+
+ return rNewMark;
+}
+
+// springe zum naechsten / vorherigen FeldTypen
+
+void lcl_MakeFldLst( _SetGetExpFlds& rLst, const SwFieldType& rFldType,
+ sal_uInt16 nSubType, sal_Bool bInReadOnly,
+ sal_Bool bChkInpFlag = sal_False )
+{
+ // es muss immer der 1. Frame gesucht werden
+ Point aPt;
+ SwTxtFld* pTxtFld;
+ SwIterator<SwFmtFld,SwFieldType> aIter(rFldType);
+ bool bSubType = nSubType != USHRT_MAX;
+ for( SwFmtFld* pFmtFld = aIter.First(); pFmtFld; pFmtFld = aIter.Next() )
+ if( 0 != ( pTxtFld = pFmtFld->GetTxtFld() ) &&
+ ( !bChkInpFlag || ((SwSetExpField*)pTxtFld->GetFld().GetFld())
+ ->GetInputFlag() ) &&
+ (!bSubType || (pFmtFld->GetFld()->GetSubType()
+ & 0xff ) == nSubType ))
+ {
+ SwCntntFrm* pCFrm;
+ const SwTxtNode& rTxtNode = pTxtFld->GetTxtNode();
+ if( 0 != ( pCFrm = rTxtNode.getLayoutFrm( rTxtNode.GetDoc()->GetCurrentLayout(), &aPt, 0, sal_False )) &&
+ ( bInReadOnly || !pCFrm->IsProtected() ))
+ {
+ _SetGetExpFld* pNew = new _SetGetExpFld(
+ SwNodeIndex( rTxtNode ), pTxtFld );
+ pNew->SetBodyPos( *pCFrm );
+ rLst.Insert( pNew );
+ }
+ }
+}
+
+
+sal_Bool SwCrsrShell::MoveFldType( const SwFieldType* pFldType, sal_Bool bNext,
+ sal_uInt16 nSubType, sal_uInt16 nResType )
+{
+ // sortierte Liste aller Felder
+ _SetGetExpFlds aSrtLst( 64 );
+
+ if (pFldType)
+ {
+ if( RES_INPUTFLD != pFldType->Which() && !pFldType->GetDepends() )
+ return sal_False;
+
+ // Modify-Object gefunden, trage alle Felder ins Array ein
+ ::lcl_MakeFldLst( aSrtLst, *pFldType, nSubType, IsReadOnlyAvailable() );
+
+ if( RES_INPUTFLD == pFldType->Which() )
+ {
+ // es gibt noch versteckte InputFelder in den SetExp. Feldern
+ const SwFldTypes& rFldTypes = *pDoc->GetFldTypes();
+ const sal_uInt16 nSize = rFldTypes.Count();
+
+ // Alle Typen abklappern
+ for( sal_uInt16 i=0; i < nSize; ++i )
+ if( RES_SETEXPFLD == ( pFldType = rFldTypes[ i ] )->Which() )
+ ::lcl_MakeFldLst( aSrtLst, *pFldType, nSubType,
+ IsReadOnlyAvailable(), sal_True );
+ }
+ }
+ else
+ {
+ const SwFldTypes& rFldTypes = *pDoc->GetFldTypes();
+ const sal_uInt16 nSize = rFldTypes.Count();
+
+ // Alle Typen abklappern
+ for( sal_uInt16 i=0; i < nSize; ++i )
+ if( nResType == ( pFldType = rFldTypes[ i ] )->Which() )
+ ::lcl_MakeFldLst( aSrtLst, *pFldType, nSubType,
+ IsReadOnlyAvailable() );
+ }
+
+ // keine Felder gefunden?
+ if( !aSrtLst.Count() )
+ return sal_False;
+
+ sal_uInt16 nPos;
+ SwCursor* pCrsr = getShellCrsr( true );
+ {
+ // JP 19.08.98: es muss immer ueber das Feld gesucht werden, damit
+ // auch immer das richtige gefunden wird, wenn welche in
+ // Rahmen stehen, die in einem Absatz verankert sind,
+ // in dem ein Feld steht - siehe auch Bug 55247
+ const SwPosition& rPos = *pCrsr->GetPoint();
+
+ SwTxtNode* pTNd = rPos.nNode.GetNode().GetTxtNode();
+ OSL_ENSURE( pTNd, "Wo ist mein CntntNode?" );
+
+ SwTxtFld * pTxtFld = static_cast<SwTxtFld *>(
+ pTNd->GetTxtAttrForCharAt(rPos.nContent.GetIndex(),
+ RES_TXTATR_FIELD));
+ sal_Bool bDelFld = 0 == pTxtFld;
+ if( bDelFld )
+ {
+ SwFmtFld* pFmtFld = new SwFmtFld( SwDateTimeField(
+ (SwDateTimeFieldType*)pDoc->GetSysFldType( RES_DATETIMEFLD ) ) );
+
+ pTxtFld = new SwTxtFld( *pFmtFld, rPos.nContent.GetIndex() );
+ pTxtFld->ChgTxtNode( pTNd );
+ }
+
+ _SetGetExpFld aSrch( rPos.nNode, pTxtFld, &rPos.nContent );
+ if( rPos.nNode.GetIndex() < pDoc->GetNodes().GetEndOfExtras().GetIndex() )
+ {
+ // auch beim Einsammeln wird nur der erste Frame benutzt!
+ Point aPt;
+ aSrch.SetBodyPos( *pTNd->getLayoutFrm( GetLayout(), &aPt, &rPos, sal_False ) );
+ }
+
+ sal_Bool bFound = aSrtLst.Seek_Entry( &aSrch, &nPos );
+ if( bDelFld )
+ {
+ delete (SwFmtFld*)&pTxtFld->GetAttr();
+ delete pTxtFld;
+ }
+
+ if( bFound ) // stehe auf einem ?
+ {
+ if( bNext )
+ {
+ if( ++nPos >= aSrtLst.Count() )
+ return sal_False; // schon am Ende
+ }
+ else if( !nPos-- )
+ return sal_False; // weiter nach vorne geht nicht
+ }
+ else if( bNext ? nPos >= aSrtLst.Count() : !nPos--)
+ return sal_False;
+ }
+ const _SetGetExpFld& rFnd = **( aSrtLst.GetData() + nPos );
+
+
+ SET_CURR_SHELL( this );
+ SwCallLink aLk( *this ); // Crsr-Moves ueberwachen, evt. Link callen
+ SwCrsrSaveState aSaveState( *pCrsr );
+
+ rFnd.GetPosOfContent( *pCrsr->GetPoint() );
+ sal_Bool bRet = !pCurCrsr->IsSelOvr( nsSwCursorSelOverFlags::SELOVER_CHECKNODESSECTION |
+ nsSwCursorSelOverFlags::SELOVER_TOGGLE );
+ if( bRet )
+ UpdateCrsr(SwCrsrShell::SCROLLWIN|SwCrsrShell::CHKRANGE|SwCrsrShell::READONLY);
+ return bRet;
+}
+
+
+sal_Bool SwCrsrShell::GotoFld( const SwFmtFld& rFld )
+{
+ sal_Bool bRet = sal_False;
+ if( rFld.GetTxtFld() )
+ {
+ SET_CURR_SHELL( this );
+ SwCallLink aLk( *this ); // Crsr-Moves ueberwachen, evt. Link callen
+
+ SwCursor* pCrsr = getShellCrsr( true );
+ SwCrsrSaveState aSaveState( *pCrsr );
+
+ SwTxtNode* pTNd = (SwTxtNode*)rFld.GetTxtFld()->GetpTxtNode();
+ pCrsr->GetPoint()->nNode = *pTNd;
+ pCrsr->GetPoint()->nContent.Assign( pTNd, *rFld.GetTxtFld()->GetStart() );
+
+ bRet = !pCrsr->IsSelOvr();
+ if( bRet )
+ UpdateCrsr(SwCrsrShell::SCROLLWIN|SwCrsrShell::CHKRANGE|SwCrsrShell::READONLY);
+ }
+ return bRet;
+}
+
+
+void SwCrsrShell::GotoOutline( sal_uInt16 nIdx )
+{
+ SwCursor* pCrsr = getShellCrsr( true );
+
+ SET_CURR_SHELL( this );
+ SwCallLink aLk( *this ); // Crsr-Moves ueberwachen, evt. Link callen
+ SwCrsrSaveState aSaveState( *pCrsr );
+
+ const SwNodes& rNds = GetDoc()->GetNodes();
+ SwTxtNode* pTxtNd = (SwTxtNode*)rNds.GetOutLineNds()[ nIdx ]->GetTxtNode();
+ pCrsr->GetPoint()->nNode = *pTxtNd;
+ pCrsr->GetPoint()->nContent.Assign( pTxtNd, 0 );
+
+ if( !pCrsr->IsSelOvr() )
+ UpdateCrsr(SwCrsrShell::SCROLLWIN|SwCrsrShell::CHKRANGE|SwCrsrShell::READONLY);
+}
+
+
+sal_Bool SwCrsrShell::GotoOutline( const String& rName )
+{
+ SwCursor* pCrsr = getShellCrsr( true );
+
+ SET_CURR_SHELL( this );
+ SwCallLink aLk( *this ); // Crsr-Moves ueberwachen, evt. Link callen
+ SwCrsrSaveState aSaveState( *pCrsr );
+
+ sal_Bool bRet = sal_False;
+ if( pDoc->GotoOutline( *pCrsr->GetPoint(), rName ) && !pCrsr->IsSelOvr() )
+ {
+ UpdateCrsr(SwCrsrShell::SCROLLWIN|SwCrsrShell::CHKRANGE|SwCrsrShell::READONLY);
+ bRet = sal_True;
+ }
+ return bRet;
+}
+
+
+
+sal_Bool SwCrsrShell::GotoNextOutline() // naechster Node mit Outline-Num.
+{
+ SwCursor* pCrsr = getShellCrsr( true );
+ const SwNodes& rNds = GetDoc()->GetNodes();
+
+ SwNode* pNd = pCrsr->GetNode();
+ sal_uInt16 nPos;
+ if( rNds.GetOutLineNds().Seek_Entry( pNd, &nPos ))
+ ++nPos;
+
+ if( nPos == rNds.GetOutLineNds().Count() )
+ return sal_False;
+
+ pNd = rNds.GetOutLineNds()[ nPos ];
+
+ SET_CURR_SHELL( this );
+ SwCallLink aLk( *this ); // Crsr-Moves ueberwachen, evt. Link callen
+ SwCrsrSaveState aSaveState( *pCrsr );
+ pCrsr->GetPoint()->nNode = *pNd;
+ pCrsr->GetPoint()->nContent.Assign( (SwTxtNode*)pNd, 0 );
+
+ sal_Bool bRet = !pCrsr->IsSelOvr();
+ if( bRet )
+ UpdateCrsr(SwCrsrShell::SCROLLWIN|SwCrsrShell::CHKRANGE|SwCrsrShell::READONLY);
+ return bRet;
+}
+
+
+sal_Bool SwCrsrShell::GotoPrevOutline() // vorheriger Node mit Outline-Num.
+{
+ SwCursor* pCrsr = getShellCrsr( true );
+ const SwNodes& rNds = GetDoc()->GetNodes();
+
+ SwNode* pNd = pCrsr->GetNode();
+ sal_uInt16 nPos;
+ rNds.GetOutLineNds().Seek_Entry( pNd, &nPos );
+
+ sal_Bool bRet = sal_False;
+ if( nPos )
+ {
+ --nPos; // davor
+
+ pNd = rNds.GetOutLineNds()[ nPos ];
+ if( pNd->GetIndex() > pCrsr->GetPoint()->nNode.GetIndex() )
+ return sal_False;
+
+ SET_CURR_SHELL( this );
+ SwCallLink aLk( *this ); // Crsr-Moves ueberwachen, evt. Link callen
+ SwCrsrSaveState aSaveState( *pCrsr );
+ pCrsr->GetPoint()->nNode = *pNd;
+ pCrsr->GetPoint()->nContent.Assign( (SwTxtNode*)pNd, 0 );
+
+ bRet = !pCrsr->IsSelOvr();
+ if( bRet )
+ UpdateCrsr(SwCrsrShell::SCROLLWIN|SwCrsrShell::CHKRANGE|SwCrsrShell::READONLY);
+ }
+ return bRet;
+}
+
+
+ // suche die "Outline-Position" vom vorherigen Outline-Node mit dem
+ // Level.
+sal_uInt16 SwCrsrShell::GetOutlinePos( sal_uInt8 nLevel )
+{
+ SwPaM* pCrsr = getShellCrsr( true );
+ const SwNodes& rNds = GetDoc()->GetNodes();
+
+ SwNode* pNd = pCrsr->GetNode();
+ sal_uInt16 nPos;
+ if( rNds.GetOutLineNds().Seek_Entry( pNd, &nPos ))
+ nPos++; // steht auf der Position, fuers while zum Naechsten
+
+ while( nPos-- ) // immer den davor testen !
+ {
+ pNd = rNds.GetOutLineNds()[ nPos ];
+
+ if( ((SwTxtNode*)pNd)->GetAttrOutlineLevel()-1 <= nLevel )//<-end,zhaojianwei
+ return nPos;
+
+ }
+ return USHRT_MAX; // davor keiner mehr also Ende
+}
+
+
+sal_Bool SwCrsrShell::MakeOutlineSel( sal_uInt16 nSttPos, sal_uInt16 nEndPos,
+ sal_Bool bWithChilds )
+{
+ const SwNodes& rNds = GetDoc()->GetNodes();
+ const SwOutlineNodes& rOutlNds = rNds.GetOutLineNds();
+ if( !rOutlNds.Count() ) // wie jetzt ???
+ return sal_False;
+
+ SET_CURR_SHELL( this );
+ SwCallLink aLk( *this ); // Crsr-Moves ueberwachen, evt. Link callen
+
+ if( nSttPos > nEndPos ) // sollte jemand das vertauscht haben?
+ {
+ OSL_ENSURE( !this, "Start- > Ende-Position im Array" );
+ sal_uInt16 nTmp = nSttPos;
+ nSttPos = nEndPos;
+ nEndPos = nTmp;
+ }
+
+ SwNode* pSttNd = rOutlNds[ nSttPos ];
+ SwNode* pEndNd = rOutlNds[ nEndPos ];
+
+ if( bWithChilds )
+ {
+ const int nLevel = pEndNd->GetTxtNode()->GetAttrOutlineLevel()-1;//<-end.zhaojianwei
+ for( ++nEndPos; nEndPos < rOutlNds.Count(); ++nEndPos )
+ {
+ pEndNd = rOutlNds[ nEndPos ];
+ const int nNxtLevel = pEndNd->GetTxtNode()->GetAttrOutlineLevel()-1;//<-end,zhaojianwei
+ if( nNxtLevel <= nLevel )
+ break; // EndPos steht jetzt auf dem naechsten
+ }
+ }
+ // ohne Childs, dann aber zumindest auf den naechsten
+ else if( ++nEndPos < rOutlNds.Count() )
+ pEndNd = rOutlNds[ nEndPos ];
+
+ if( nEndPos == rOutlNds.Count() ) // kein Ende gefunden
+ pEndNd = &rNds.GetEndOfContent();
+
+ KillPams();
+
+ SwCrsrSaveState aSaveState( *pCurCrsr );
+
+ // Jetzt das Ende ans Ende vom voherigen ContentNode setzen
+ pCurCrsr->GetPoint()->nNode = *pSttNd;
+ pCurCrsr->GetPoint()->nContent.Assign( pSttNd->GetCntntNode(), 0 );
+ pCurCrsr->SetMark();
+ pCurCrsr->GetPoint()->nNode = *pEndNd;
+ pCurCrsr->Move( fnMoveBackward, fnGoNode ); // ans Ende vom Vorgaenger
+
+ // und schon ist alles selektiert
+ sal_Bool bRet = !pCurCrsr->IsSelOvr();
+ if( bRet )
+ UpdateCrsr(SwCrsrShell::SCROLLWIN|SwCrsrShell::CHKRANGE|SwCrsrShell::READONLY);
+ return bRet;
+}
+
+
+// springe zu dieser Refmark
+sal_Bool SwCrsrShell::GotoRefMark( const String& rRefMark, sal_uInt16 nSubType,
+ sal_uInt16 nSeqNo )
+{
+ SET_CURR_SHELL( this );
+ SwCallLink aLk( *this ); // Crsr-Moves ueberwachen, evt. Link callen
+ SwCrsrSaveState aSaveState( *pCurCrsr );
+
+ sal_uInt16 nPos;
+ SwTxtNode* pTxtNd = SwGetRefFieldType::FindAnchor( GetDoc(), rRefMark,
+ nSubType, nSeqNo, &nPos );
+ if( pTxtNd && pTxtNd->GetNodes().IsDocNodes() )
+ {
+ pCurCrsr->GetPoint()->nNode = *pTxtNd;
+ pCurCrsr->GetPoint()->nContent.Assign( pTxtNd, nPos );
+
+ if( !pCurCrsr->IsSelOvr() )
+ {
+ UpdateCrsr(SwCrsrShell::SCROLLWIN|SwCrsrShell::CHKRANGE|SwCrsrShell::READONLY);
+ return sal_True;
+ }
+ }
+ return sal_False;
+}
+
+sal_Bool SwCrsrShell::IsPageAtPos( const Point &rPt ) const
+{
+ if( GetLayout() )
+ return 0 != GetLayout()->GetPageAtPos( rPt );
+ return sal_False;
+}
+
+sal_Bool SwCrsrShell::GetContentAtPos( const Point& rPt,
+ SwContentAtPos& rCntntAtPos,
+ sal_Bool bSetCrsr,
+ SwRect* pFldRect )
+{
+ SET_CURR_SHELL( this );
+ sal_Bool bRet = sal_False;
+
+ if( !IsTableMode() )
+ {
+ Point aPt( rPt );
+ SwPosition aPos( *pCurCrsr->GetPoint() );
+
+ SwTxtNode* pTxtNd;
+ SwCntntFrm *pFrm(0);
+ SwTxtAttr* pTxtAttr;
+ SwCrsrMoveState aTmpState;
+ aTmpState.bFieldInfo = sal_True;
+ aTmpState.bExactOnly = !( SwContentAtPos::SW_OUTLINE & rCntntAtPos.eCntntAtPos );
+ aTmpState.bCntntCheck = (SwContentAtPos::SW_CONTENT_CHECK & rCntntAtPos.eCntntAtPos) ? sal_True : sal_False;
+ aTmpState.bSetInReadOnly = IsReadOnlyAvailable();
+
+ SwSpecialPos aSpecialPos;
+ aTmpState.pSpecialPos = ( SwContentAtPos::SW_SMARTTAG & rCntntAtPos.eCntntAtPos ) ?
+ &aSpecialPos : 0;
+
+ const sal_Bool bCrsrFoundExact = GetLayout()->GetCrsrOfst( &aPos, aPt, &aTmpState );
+ pTxtNd = aPos.nNode.GetNode().GetTxtNode();
+
+ const SwNodes& rNds = GetDoc()->GetNodes();
+ if( pTxtNd && SwContentAtPos::SW_OUTLINE & rCntntAtPos.eCntntAtPos
+ && rNds.GetOutLineNds().Count() )
+ {
+ const SwTxtNode* pONd = pTxtNd->FindOutlineNodeOfLevel( MAXLEVEL-1);
+ if( pONd )
+ {
+ rCntntAtPos.eCntntAtPos = SwContentAtPos::SW_OUTLINE;
+ rCntntAtPos.sStr = pONd->GetExpandTxt( 0, STRING_LEN, true );
+ bRet = sal_True;
+ }
+ }
+ // --> FME 2005-05-13 #i43742# New function: SW_CONTENT_CHECK
+ else if ( SwContentAtPos::SW_CONTENT_CHECK & rCntntAtPos.eCntntAtPos &&
+ bCrsrFoundExact )
+ {
+ bRet = sal_True;
+ }
+ // <--
+ // #i23726#
+ else if( pTxtNd &&
+ SwContentAtPos::SW_NUMLABEL & rCntntAtPos.eCntntAtPos)
+ {
+ bRet = aTmpState.bInNumPortion;
+ rCntntAtPos.aFnd.pNode = pTxtNd;
+
+ Size aSizeLogic(aTmpState.nInNumPostionOffset, 0);
+ Size aSizePixel = GetWin()->LogicToPixel(aSizeLogic);
+ rCntntAtPos.nDist = aSizePixel.Width();
+ }
+ else if( bCrsrFoundExact && pTxtNd )
+ {
+ if( !aTmpState.bPosCorr )
+ {
+ if( !bRet && SwContentAtPos::SW_SMARTTAG & rCntntAtPos.eCntntAtPos
+ && !aTmpState.bFtnNoInfo )
+ {
+ const SwWrongList* pSmartTagList = pTxtNd->GetSmartTags();
+ xub_StrLen nCurrent = aPos.nContent.GetIndex();
+ xub_StrLen nBegin = nCurrent;
+ xub_StrLen nLen = 1;
+
+ if ( pSmartTagList && pSmartTagList->InWrongWord( nCurrent, nLen ) && !pTxtNd->IsSymbol(nBegin) )
+ {
+ const sal_uInt16 nIndex = pSmartTagList->GetWrongPos( nBegin );
+ const SwWrongList* pSubList = pSmartTagList->SubList( nIndex );
+ if ( pSubList )
+ {
+ nCurrent = aTmpState.pSpecialPos->nCharOfst;
+
+ if ( pSubList->InWrongWord( nCurrent, nLen ) )
+ bRet = sal_True;
+ }
+ else
+ bRet = sal_True;
+
+ if( bRet && bSetCrsr )
+ {
+ SwCrsrSaveState aSaveState( *pCurCrsr );
+ SwCallLink aLk( *this ); // Crsr-Moves ueberwachen, evt. Link callen
+ pCurCrsr->DeleteMark();
+ *pCurCrsr->GetPoint() = aPos;
+ if( pCurCrsr->IsSelOvr( nsSwCursorSelOverFlags::SELOVER_CHECKNODESSECTION |
+ nsSwCursorSelOverFlags::SELOVER_TOGGLE) )
+ bRet = sal_False;
+ else
+ UpdateCrsr();
+ }
+ if( bRet )
+ {
+ rCntntAtPos.eCntntAtPos = SwContentAtPos::SW_SMARTTAG;
+
+ if( pFldRect && 0 != ( pFrm = pTxtNd->getLayoutFrm( GetLayout(), &aPt ) ) )
+ pFrm->GetCharRect( *pFldRect, aPos, &aTmpState );
+ }
+ }
+ }
+
+ if( !bRet && ( SwContentAtPos::SW_FIELD | SwContentAtPos::SW_CLICKFIELD )
+ & rCntntAtPos.eCntntAtPos && !aTmpState.bFtnNoInfo )
+ {
+ pTxtAttr = pTxtNd->GetTxtAttrForCharAt(
+ aPos.nContent.GetIndex(), RES_TXTATR_FIELD );
+ const SwField* pFld = pTxtAttr
+ ? pTxtAttr->GetFld().GetFld()
+ : 0;
+ if( SwContentAtPos::SW_CLICKFIELD & rCntntAtPos.eCntntAtPos &&
+ pFld && !pFld->HasClickHdl() )
+ pFld = 0;
+
+ if( pFld )
+ {
+ if( pFldRect && 0 != ( pFrm = pTxtNd->getLayoutFrm( GetLayout(), &aPt ) ) )
+ pFrm->GetCharRect( *pFldRect, aPos, &aTmpState );
+
+ if( bSetCrsr )
+ {
+ SwCallLink aLk( *this ); // Crsr-Moves ueberwachen, evt. Link callen
+ SwCrsrSaveState aSaveState( *pCurCrsr );
+ pCurCrsr->DeleteMark();
+ *pCurCrsr->GetPoint() = aPos;
+ if( pCurCrsr->IsSelOvr() )
+ {
+ // Click-Felder in geschuetzten Bereichen zulassen
+ // Nur Platzhalter geht nicht!
+ if( SwContentAtPos::SW_FIELD & rCntntAtPos.eCntntAtPos
+ || RES_JUMPEDITFLD == pFld->Which() )
+ pFld = 0;
+ }
+ else
+ UpdateCrsr();
+ }
+ else if( RES_TABLEFLD == pFld->Which() &&
+ ((SwTblField*)pFld)->IsIntrnlName() )
+ {
+ // erzeuge aus der internen (fuer CORE)
+ // die externe (fuer UI) Formel
+ const SwTableNode* pTblNd = pTxtNd->FindTableNode();
+ if( pTblNd ) // steht in einer Tabelle
+ ((SwTblField*)pFld)->PtrToBoxNm( &pTblNd->GetTable() );
+ }
+ }
+
+ if( pFld )
+ {
+ rCntntAtPos.aFnd.pFld = pFld;
+ rCntntAtPos.pFndTxtAttr = pTxtAttr;
+ rCntntAtPos.eCntntAtPos = SwContentAtPos::SW_FIELD;
+ bRet = sal_True;
+ }
+ }
+
+ if( !bRet && SwContentAtPos::SW_FORMCTRL & rCntntAtPos.eCntntAtPos )
+ {
+ IDocumentMarkAccess* pMarksAccess = GetDoc()->getIDocumentMarkAccess( );
+ sw::mark::IFieldmark* pFldBookmark = pMarksAccess->getFieldmarkFor( aPos );
+ if( bCrsrFoundExact && pTxtNd && pFldBookmark) {
+ rCntntAtPos.eCntntAtPos = SwContentAtPos::SW_FORMCTRL;
+ rCntntAtPos.aFnd.pFldmark = pFldBookmark;
+ bRet=sal_True;
+ }
+ }
+
+ if( !bRet && SwContentAtPos::SW_FTN & rCntntAtPos.eCntntAtPos )
+ {
+ if( aTmpState.bFtnNoInfo )
+ {
+ // stehe ueber dem Zeichen der Fussnote (??)
+ bRet = sal_True;
+ if( bSetCrsr )
+ {
+ *pCurCrsr->GetPoint() = aPos;
+ if( !GotoFtnAnchor() )
+ bRet = sal_False;
+ }
+ if( bRet )
+ rCntntAtPos.eCntntAtPos = SwContentAtPos::SW_FTN;
+ }
+ else if ( 0 != ( pTxtAttr = pTxtNd->GetTxtAttrForCharAt(
+ aPos.nContent.GetIndex(), RES_TXTATR_FTN )) )
+ {
+ bRet = sal_True;
+ if( bSetCrsr )
+ {
+ SwCallLink aLk( *this ); // Crsr-Moves ueberwachen,
+ SwCrsrSaveState aSaveState( *pCurCrsr );
+ pCurCrsr->GetPoint()->nNode = *((SwTxtFtn*)pTxtAttr)->GetStartNode();
+ SwCntntNode* pCNd = GetDoc()->GetNodes().GoNextSection(
+ &pCurCrsr->GetPoint()->nNode,
+ sal_True, !IsReadOnlyAvailable() );
+
+ if( pCNd )
+ {
+ pCurCrsr->GetPoint()->nContent.Assign( pCNd, 0 );
+ if( pCurCrsr->IsSelOvr( nsSwCursorSelOverFlags::SELOVER_CHECKNODESSECTION |
+ nsSwCursorSelOverFlags::SELOVER_TOGGLE ))
+ bRet = sal_False;
+ else
+ UpdateCrsr();
+ }
+ else
+ bRet = sal_False;
+ }
+
+ if( bRet )
+ {
+ rCntntAtPos.eCntntAtPos = SwContentAtPos::SW_FTN;
+ rCntntAtPos.pFndTxtAttr = pTxtAttr;
+ rCntntAtPos.aFnd.pAttr = &pTxtAttr->GetAttr();
+
+ if( pFldRect && 0 != ( pFrm = pTxtNd->getLayoutFrm( GetLayout(), &aPt ) ) )
+ pFrm->GetCharRect( *pFldRect, aPos, &aTmpState );
+ }
+ }
+ }
+
+ if( !bRet && ( SwContentAtPos::SW_TOXMARK |
+ SwContentAtPos::SW_REFMARK ) &
+ rCntntAtPos.eCntntAtPos && !aTmpState.bFtnNoInfo )
+ {
+ pTxtAttr = 0;
+ if( SwContentAtPos::SW_TOXMARK & rCntntAtPos.eCntntAtPos )
+ {
+ ::std::vector<SwTxtAttr *> const marks(
+ pTxtNd->GetTxtAttrsAt(
+ aPos.nContent.GetIndex(), RES_TXTATR_TOXMARK));
+ if (marks.size())
+ { // hmm... can only return 1 here
+ pTxtAttr = *marks.begin();
+ }
+ }
+
+ if( !pTxtAttr &&
+ SwContentAtPos::SW_REFMARK & rCntntAtPos.eCntntAtPos )
+ {
+ ::std::vector<SwTxtAttr *> const marks(
+ pTxtNd->GetTxtAttrsAt(
+ aPos.nContent.GetIndex(), RES_TXTATR_REFMARK));
+ if (marks.size())
+ { // hmm... can only return 1 here
+ pTxtAttr = *marks.begin();
+ }
+ }
+
+ if( pTxtAttr )
+ {
+ bRet = sal_True;
+ if( bSetCrsr )
+ {
+ SwCallLink aLk( *this ); // Crsr-Moves ueberwachen,
+ SwCrsrSaveState aSaveState( *pCurCrsr );
+ pCurCrsr->DeleteMark();
+ *pCurCrsr->GetPoint() = aPos;
+ if( pCurCrsr->IsSelOvr( nsSwCursorSelOverFlags::SELOVER_CHECKNODESSECTION |
+ nsSwCursorSelOverFlags::SELOVER_TOGGLE ) )
+ bRet = sal_False;
+ else
+ UpdateCrsr();
+ }
+
+ if( bRet )
+ {
+ const xub_StrLen* pEnd = pTxtAttr->GetEnd();
+ if( pEnd )
+ rCntntAtPos.sStr = pTxtNd->GetExpandTxt(
+ *pTxtAttr->GetStart(),
+ *pEnd - *pTxtAttr->GetStart() );
+ else if( RES_TXTATR_TOXMARK == pTxtAttr->Which())
+ rCntntAtPos.sStr = pTxtAttr->GetTOXMark().
+ GetAlternativeText();
+
+ rCntntAtPos.eCntntAtPos =
+ RES_TXTATR_TOXMARK == pTxtAttr->Which()
+ ? SwContentAtPos::SW_TOXMARK
+ : SwContentAtPos::SW_REFMARK;
+ rCntntAtPos.pFndTxtAttr = pTxtAttr;
+ rCntntAtPos.aFnd.pAttr = &pTxtAttr->GetAttr();
+
+ if( pFldRect && 0 != ( pFrm = pTxtNd->getLayoutFrm( GetLayout(), &aPt ) ) )
+ pFrm->GetCharRect( *pFldRect, aPos, &aTmpState );
+ }
+ }
+ }
+
+ if( !bRet && SwContentAtPos::SW_INETATTR & rCntntAtPos.eCntntAtPos
+ && !aTmpState.bFtnNoInfo )
+ {
+ pTxtAttr = pTxtNd->GetTxtAttrAt(
+ aPos.nContent.GetIndex(), RES_TXTATR_INETFMT);
+ // nur INetAttrs mit URLs "erkennen"
+ if( pTxtAttr && pTxtAttr->GetINetFmt().GetValue().Len() )
+ {
+ bRet = sal_True;
+ if( bSetCrsr )
+ {
+ SwCrsrSaveState aSaveState( *pCurCrsr );
+ SwCallLink aLk( *this ); // Crsr-Moves ueberwachen, evt. Link callen
+ pCurCrsr->DeleteMark();
+ *pCurCrsr->GetPoint() = aPos;
+ if( pCurCrsr->IsSelOvr( nsSwCursorSelOverFlags::SELOVER_CHECKNODESSECTION |
+ nsSwCursorSelOverFlags::SELOVER_TOGGLE) )
+ bRet = sal_False;
+ else
+ UpdateCrsr();
+ }
+ if( bRet )
+ {
+ rCntntAtPos.sStr = pTxtNd->GetExpandTxt(
+ *pTxtAttr->GetStart(),
+ *pTxtAttr->GetEnd() - *pTxtAttr->GetStart() );
+
+ rCntntAtPos.aFnd.pAttr = &pTxtAttr->GetAttr();
+ rCntntAtPos.eCntntAtPos = SwContentAtPos::SW_INETATTR;
+ rCntntAtPos.pFndTxtAttr = pTxtAttr;
+
+ if( pFldRect && 0 != ( pFrm = pTxtNd->getLayoutFrm( GetLayout(), &aPt ) ) )
+ pFrm->GetCharRect( *pFldRect, aPos, &aTmpState );
+ }
+ }
+ }
+
+ if( !bRet && SwContentAtPos::SW_REDLINE & rCntntAtPos.eCntntAtPos )
+ {
+ const SwRedline* pRedl = GetDoc()->GetRedline(aPos, NULL);
+ if( pRedl )
+ {
+ rCntntAtPos.aFnd.pRedl = pRedl;
+ rCntntAtPos.eCntntAtPos = SwContentAtPos::SW_REDLINE;
+ rCntntAtPos.pFndTxtAttr = 0;
+ bRet = sal_True;
+
+ if( pFldRect && 0 != ( pFrm = pTxtNd->getLayoutFrm( GetLayout(), &aPt ) ) )
+ pFrm->GetCharRect( *pFldRect, aPos, &aTmpState );
+ }
+ }
+ }
+
+ if( !bRet && (
+ SwContentAtPos::SW_TABLEBOXFML & rCntntAtPos.eCntntAtPos
+#if OSL_DEBUG_LEVEL > 1
+ || SwContentAtPos::SW_TABLEBOXVALUE & rCntntAtPos.eCntntAtPos
+#endif
+ ))
+ {
+ const SwTableNode* pTblNd;
+ const SwTableBox* pBox;
+ const SwStartNode* pSttNd = pTxtNd->FindTableBoxStartNode();
+ const SfxPoolItem* pItem;
+ if( pSttNd && 0 != ( pTblNd = pTxtNd->FindTableNode()) &&
+ 0 != ( pBox = pTblNd->GetTable().GetTblBox(
+ pSttNd->GetIndex() )) &&
+#if OSL_DEBUG_LEVEL > 1
+ ( SFX_ITEM_SET == pBox->GetFrmFmt()->GetItemState(
+ RES_BOXATR_FORMULA, sal_False, &pItem ) ||
+ SFX_ITEM_SET == pBox->GetFrmFmt()->GetItemState(
+ RES_BOXATR_VALUE, sal_False, &pItem ))
+#else
+ SFX_ITEM_SET == pBox->GetFrmFmt()->GetItemState(
+ RES_BOXATR_FORMULA, sal_False, &pItem )
+#endif
+ )
+ {
+ SwFrm* pF = pTxtNd->getLayoutFrm( GetLayout(), &aPt );
+ if( pF )
+ {
+ // dann aber den CellFrame
+ pFrm = (SwCntntFrm*)pF;
+ while( pF && !pF->IsCellFrm() )
+ pF = pF->GetUpper();
+ }
+
+ // es wurde ein
+ if( aTmpState.bPosCorr )
+ {
+ if( pF && !pF->Frm().IsInside( aPt ))
+ pF = 0;
+ }
+ else if( !pF )
+ pF = pFrm;
+
+ if( pF ) // nur dann ist es gueltig!!
+ {
+ // erzeuge aus der internen (fuer CORE)
+ // die externe (fuer UI) Formel
+ rCntntAtPos.eCntntAtPos = SwContentAtPos::SW_TABLEBOXFML;
+#if OSL_DEBUG_LEVEL > 1
+ if( RES_BOXATR_VALUE == pItem->Which() )
+ rCntntAtPos.eCntntAtPos = SwContentAtPos::SW_TABLEBOXVALUE;
+ else
+#endif
+ ((SwTblBoxFormula*)pItem)->PtrToBoxNm( &pTblNd->GetTable() );
+
+ bRet = sal_True;
+ if( bSetCrsr )
+ {
+ SwCallLink aLk( *this ); // Crsr-Moves ueberwachen,
+ SwCrsrSaveState aSaveState( *pCurCrsr );
+ *pCurCrsr->GetPoint() = aPos;
+ if( pCurCrsr->IsSelOvr( nsSwCursorSelOverFlags::SELOVER_CHECKNODESSECTION |
+ nsSwCursorSelOverFlags::SELOVER_TOGGLE) )
+ bRet = sal_False;
+ else
+ UpdateCrsr();
+ }
+
+ if( bRet )
+ {
+ if( pFldRect )
+ {
+ *pFldRect = pF->Prt();
+ *pFldRect += pF->Frm().Pos();
+ }
+ rCntntAtPos.pFndTxtAttr = 0;
+ rCntntAtPos.aFnd.pAttr = pItem;
+ }
+ }
+ }
+ }
+
+#if OSL_DEBUG_LEVEL > 1
+ if( !bRet && SwContentAtPos::SW_CURR_ATTRS & rCntntAtPos.eCntntAtPos )
+ {
+ xub_StrLen n = aPos.nContent.GetIndex();
+ SfxItemSet aSet( GetDoc()->GetAttrPool(), POOLATTR_BEGIN,
+ POOLATTR_END - 1 );
+ if( pTxtNd->GetpSwpHints() )
+ {
+ for( sal_uInt16 i = 0; i < pTxtNd->GetSwpHints().Count(); ++i )
+ {
+ const SwTxtAttr* pHt = pTxtNd->GetSwpHints()[i];
+ xub_StrLen nAttrStart = *pHt->GetStart();
+ if( nAttrStart > n ) // ueber den Bereich hinaus
+ break;
+
+ if( 0 != pHt->GetEnd() && (
+ ( nAttrStart < n &&
+ ( pHt->DontExpand() ? n < *pHt->GetEnd()
+ : n <= *pHt->GetEnd() )) ||
+ ( n == nAttrStart &&
+ ( nAttrStart == *pHt->GetEnd() || !n ))) )
+ {
+ aSet.Put( pHt->GetAttr() );
+ }
+ }
+ if( pTxtNd->HasSwAttrSet() &&
+ pTxtNd->GetpSwAttrSet()->Count() )
+ {
+ SfxItemSet aFmtSet( pTxtNd->GetSwAttrSet() );
+ // aus dem Format-Set alle entfernen, die im TextSet auch gesetzt sind
+ aFmtSet.Differentiate( aSet );
+ // jetzt alle zusammen "mergen"
+ aSet.Put( aFmtSet );
+ }
+ }
+ else
+ pTxtNd->SwCntntNode::GetAttr( aSet );
+
+ rCntntAtPos.sStr.AssignAscii(
+ RTL_CONSTASCII_STRINGPARAM( "Pos: (" ));
+ rCntntAtPos.sStr += String::CreateFromInt32( aPos.nNode.GetIndex());
+ rCntntAtPos.sStr += ':';
+ rCntntAtPos.sStr += String::CreateFromInt32( aPos.nContent.GetIndex());
+ rCntntAtPos.sStr += ')';
+ rCntntAtPos.sStr.AppendAscii(
+ RTL_CONSTASCII_STRINGPARAM( "\nAbs.Vorl.: " ));
+ rCntntAtPos.sStr += pTxtNd->GetFmtColl()->GetName();
+ if( pTxtNd->GetCondFmtColl() )
+ rCntntAtPos.sStr.AppendAscii(
+ RTL_CONSTASCII_STRINGPARAM( "\nBed.Vorl.: " ))
+ += pTxtNd->GetCondFmtColl()->GetName();
+
+ if( aSet.Count() )
+ {
+ String sAttrs;
+ SfxItemIter aIter( aSet );
+ const SfxPoolItem* pItem = aIter.FirstItem();
+ while( sal_True )
+ {
+ if( !IsInvalidItem( pItem ))
+ {
+ String aStr;
+ GetDoc()->GetAttrPool().GetPresentation( *pItem,
+ SFX_ITEM_PRESENTATION_COMPLETE,
+ SFX_MAPUNIT_CM, aStr );
+ if( sAttrs.Len() )
+ sAttrs.AppendAscii(
+ RTL_CONSTASCII_STRINGPARAM( ", " ));
+ sAttrs += aStr;
+ }
+ if( aIter.IsAtEnd() )
+ break;
+ pItem = aIter.NextItem();
+ }
+ if( sAttrs.Len() )
+ {
+ if( rCntntAtPos.sStr.Len() )
+ rCntntAtPos.sStr += '\n';
+ rCntntAtPos.sStr.AppendAscii(
+ RTL_CONSTASCII_STRINGPARAM( "Attr: " ) )
+ += sAttrs;
+ }
+ }
+ bRet = sal_True;
+ rCntntAtPos.eCntntAtPos = SwContentAtPos::SW_CURR_ATTRS;
+ }
+#endif
+ }
+ }
+
+ if( !bRet )
+ {
+ rCntntAtPos.eCntntAtPos = SwContentAtPos::SW_NOTHING;
+ rCntntAtPos.aFnd.pFld = 0;
+ }
+ return bRet;
+}
+
+// #i90516#
+const SwPostItField* SwCrsrShell::GetPostItFieldAtCursor() const
+{
+ const SwPostItField* pPostItFld = 0;
+
+ if ( !IsTableMode() )
+ {
+ const SwPosition* pCursorPos = _GetCrsr()->GetPoint();
+ const SwTxtNode* pTxtNd = pCursorPos->nNode.GetNode().GetTxtNode();
+ if ( pTxtNd )
+ {
+ SwTxtAttr* pTxtAttr = pTxtNd->GetTxtAttrForCharAt(
+ pCursorPos->nContent.GetIndex(), RES_TXTATR_FIELD );
+ const SwField* pFld = pTxtAttr ? pTxtAttr->GetFld().GetFld() : 0;
+ if ( pFld && pFld->Which()== RES_POSTITFLD )
+ {
+ pPostItFld = static_cast<const SwPostItField*>(pFld);
+ }
+ }
+ }
+
+ return pPostItFld;
+}
+
+// befindet sich der Node in einem geschuetzten Bereich?
+sal_Bool SwContentAtPos::IsInProtectSect() const
+{
+ const SwTxtNode* pNd = 0;
+ if( pFndTxtAttr )
+ {
+ switch( eCntntAtPos )
+ {
+ case SW_FIELD:
+ case SW_CLICKFIELD:
+ pNd = ((SwTxtFld*)pFndTxtAttr)->GetpTxtNode();
+ break;
+
+ case SW_FTN:
+ pNd = &((SwTxtFtn*)pFndTxtAttr)->GetTxtNode();
+ break;
+
+ case SW_INETATTR:
+ pNd = ((SwTxtINetFmt*)pFndTxtAttr)->GetpTxtNode();
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ const SwCntntFrm* pFrm;
+ return pNd && ( pNd->IsInProtectSect() ||
+ ( 0 != ( pFrm = pNd->getLayoutFrm( pNd->GetDoc()->GetCurrentLayout(), 0,0,sal_False)) &&
+ pFrm->IsProtected() ));
+}
+
+bool SwContentAtPos::IsInRTLText()const
+{
+ bool bRet = false;
+ const SwTxtNode* pNd = 0;
+ if (pFndTxtAttr && (eCntntAtPos == SW_FTN))
+ {
+ const SwTxtFtn* pTxtFtn = static_cast<const SwTxtFtn*>(pFndTxtAttr);
+ if(pTxtFtn->GetStartNode())
+ {
+ SwStartNode* pSttNd = pTxtFtn->GetStartNode()->GetNode().GetStartNode();
+ SwPaM aTemp( *pSttNd );
+ aTemp.Move(fnMoveForward, fnGoNode);
+ SwCntntNode* pCntntNode = aTemp.GetCntntNode();
+ if(pCntntNode && pCntntNode->IsTxtNode())
+ pNd = static_cast<SwTxtNode*>(pCntntNode);
+ }
+ }
+ if(pNd)
+ {
+ SwIterator<SwTxtFrm,SwTxtNode> aIter(*pNd);
+ SwTxtFrm* pTmpFrm = aIter.First();
+ while( pTmpFrm )
+ {
+ if ( !pTmpFrm->IsFollow())
+ {
+ bRet = pTmpFrm->IsRightToLeft();
+ break;
+ }
+ pTmpFrm = aIter.Next();
+ }
+ }
+ return bRet;
+}
+
+sal_Bool SwCrsrShell::SelectTxtAttr( sal_uInt16 nWhich, sal_Bool bExpand,
+ const SwTxtAttr* pTxtAttr )
+{
+ SET_CURR_SHELL( this );
+ sal_Bool bRet = sal_False;
+
+ if( !IsTableMode() )
+ {
+ SwPosition& rPos = *pCurCrsr->GetPoint();
+ if( !pTxtAttr )
+ {
+ SwTxtNode* pTxtNd = rPos.nNode.GetNode().GetTxtNode();
+ pTxtAttr = (pTxtNd)
+ ? pTxtNd->GetTxtAttrAt(rPos.nContent.GetIndex(),
+ static_cast<RES_TXTATR>(nWhich),
+ (bExpand) ? SwTxtNode::EXPAND : SwTxtNode::DEFAULT)
+ : 0;
+ }
+
+ if( pTxtAttr )
+ {
+ SwCallLink aLk( *this ); // Crsr-Moves ueberwachen,
+ SwCrsrSaveState aSaveState( *pCurCrsr );
+
+ pCurCrsr->DeleteMark();
+ rPos.nContent = *pTxtAttr->GetStart();
+ pCurCrsr->SetMark();
+ const xub_StrLen* pEnd = pTxtAttr->GetEnd();
+ rPos.nContent = pEnd ? *pEnd : *pTxtAttr->GetStart() + 1;
+
+ if( !pCurCrsr->IsSelOvr() )
+ {
+ UpdateCrsr();
+ bRet = sal_True;
+ }
+ }
+ }
+ return bRet;
+}
+
+
+sal_Bool SwCrsrShell::GotoINetAttr( const SwTxtINetFmt& rAttr )
+{
+ sal_Bool bRet = sal_False;
+ if( rAttr.GetpTxtNode() )
+ {
+ SwCursor* pCrsr = getShellCrsr( true );
+
+ SET_CURR_SHELL( this );
+ SwCallLink aLk( *this ); // Crsr-Moves ueberwachen, evt. Link callen
+ SwCrsrSaveState aSaveState( *pCrsr );
+
+ pCrsr->GetPoint()->nNode = *rAttr.GetpTxtNode();
+ pCrsr->GetPoint()->nContent.Assign( (SwTxtNode*)rAttr.GetpTxtNode(),
+ *rAttr.GetStart() );
+ bRet = !pCrsr->IsSelOvr();
+ if( bRet )
+ UpdateCrsr(SwCrsrShell::SCROLLWIN|SwCrsrShell::CHKRANGE|SwCrsrShell::READONLY);
+ }
+ return bRet;
+}
+
+
+const SwFmtINetFmt* SwCrsrShell::FindINetAttr( const String& rName ) const
+{
+ return pDoc->FindINetAttr( rName );
+}
+
+sal_Bool SwCrsrShell::GetShadowCrsrPos( const Point& rPt, SwFillMode eFillMode,
+ SwRect& rRect, sal_Int16& rOrient )
+{
+
+ SET_CURR_SHELL( this );
+ sal_Bool bRet = sal_False;
+
+ if (!IsTableMode() && !HasSelection()
+ && GetDoc()->GetIDocumentUndoRedo().DoesUndo())
+ {
+ Point aPt( rPt );
+ SwPosition aPos( *pCurCrsr->GetPoint() );
+
+ SwFillCrsrPos aFPos( eFillMode );
+ SwCrsrMoveState aTmpState( &aFPos );
+
+ if( GetLayout()->GetCrsrOfst( &aPos, aPt, &aTmpState ) &&
+ !aPos.nNode.GetNode().IsProtect())
+ {
+ // Start-Position im geschuetzten Bereich?
+ rRect = aFPos.aCrsr;
+ rOrient = aFPos.eOrient;
+ bRet = sal_True;
+ }
+ }
+ return bRet;
+}
+
+sal_Bool SwCrsrShell::SetShadowCrsrPos( const Point& rPt, SwFillMode eFillMode )
+{
+ SET_CURR_SHELL( this );
+ sal_Bool bRet = sal_False;
+
+ if (!IsTableMode() && !HasSelection()
+ && GetDoc()->GetIDocumentUndoRedo().DoesUndo())
+ {
+ Point aPt( rPt );
+ SwPosition aPos( *pCurCrsr->GetPoint() );
+
+ SwFillCrsrPos aFPos( eFillMode );
+ SwCrsrMoveState aTmpState( &aFPos );
+
+ if( GetLayout()->GetCrsrOfst( &aPos, aPt, &aTmpState ) )
+ {
+ SwCallLink aLk( *this ); // Crsr-Moves ueberwachen
+ StartAction();
+
+ SwCntntNode* pCNd = aPos.nNode.GetNode().GetCntntNode();
+ SwUndoId nUndoId = UNDO_INS_FROM_SHADOWCRSR;
+ // Werden nur die Absatzattribute Adjust oder LRSpace gesetzt,
+ // dann sollte der naechste Aufruf die NICHT wieder entfernen.
+ if( 0 == aFPos.nParaCnt + aFPos.nColumnCnt &&
+ ( FILL_INDENT == aFPos.eMode ||
+ ( text::HoriOrientation::NONE != aFPos.eOrient &&
+ 0 == aFPos.nTabCnt + aFPos.nSpaceCnt )) &&
+ pCNd && pCNd->Len() )
+ nUndoId = UNDO_EMPTY;
+
+ GetDoc()->GetIDocumentUndoRedo().StartUndo( nUndoId, NULL );
+
+ SwTxtFmtColl* pNextFmt = 0;
+ SwTxtNode* pTNd = pCNd->GetTxtNode();
+ if( pTNd )
+ pNextFmt = &pTNd->GetTxtColl()->GetNextTxtFmtColl();
+
+ const SwSectionNode* pSectNd = pCNd->FindSectionNode();
+ if( pSectNd && aFPos.nParaCnt )
+ {
+ SwNodeIndex aEnd( aPos.nNode, 1 );
+ while( aEnd.GetNode().IsEndNode() &&
+ (const SwNode*)&aEnd.GetNode() !=
+ pSectNd->EndOfSectionNode() )
+ aEnd++;
+
+ if( aEnd.GetNode().IsEndNode() &&
+ pCNd->Len() == aPos.nContent.GetIndex() )
+ aPos.nNode = *pSectNd->EndOfSectionNode();
+ }
+
+ for( sal_uInt16 n = 0; n < aFPos.nParaCnt + aFPos.nColumnCnt; ++n )
+ {
+ GetDoc()->AppendTxtNode( aPos );
+ if( !n && pNextFmt )
+ {
+ *pCurCrsr->GetPoint() = aPos;
+ GetDoc()->SetTxtFmtColl( *pCurCrsr, pNextFmt, false );
+ }
+ if( n < aFPos.nColumnCnt )
+ {
+ *pCurCrsr->GetPoint() = aPos;
+ GetDoc()->InsertPoolItem( *pCurCrsr,
+ SvxFmtBreakItem( SVX_BREAK_COLUMN_BEFORE, RES_BREAK ), 0);
+ }
+ }
+
+ *pCurCrsr->GetPoint() = aPos;
+ switch( aFPos.eMode )
+ {
+ case FILL_INDENT:
+ if( 0 != (pCNd = aPos.nNode.GetNode().GetCntntNode() ))
+ {
+ SfxItemSet aSet( GetDoc()->GetAttrPool(),
+ RES_LR_SPACE, RES_LR_SPACE,
+ RES_PARATR_ADJUST, RES_PARATR_ADJUST,
+ 0 );
+ SvxLRSpaceItem aLR( (SvxLRSpaceItem&)
+ pCNd->GetAttr( RES_LR_SPACE ) );
+ aLR.SetTxtLeft( aFPos.nTabCnt );
+ aLR.SetTxtFirstLineOfst( 0 );
+ aSet.Put( aLR );
+
+ const SvxAdjustItem& rAdj = (SvxAdjustItem&)pCNd->
+ GetAttr( RES_PARATR_ADJUST );
+ if( SVX_ADJUST_LEFT != rAdj.GetAdjust() )
+ aSet.Put( SvxAdjustItem( SVX_ADJUST_LEFT, RES_PARATR_ADJUST ) );
+
+ GetDoc()->InsertItemSet( *pCurCrsr, aSet, 0 );
+ }
+ else {
+ OSL_ENSURE( !this, "wo ist mein CntntNode?" );
+ }
+ break;
+
+ case FILL_TAB:
+ case FILL_SPACE:
+ {
+ String sInsert;
+ if( aFPos.nTabCnt )
+ sInsert.Fill( aFPos.nTabCnt, '\t' );
+ if( aFPos.nSpaceCnt )
+ {
+ String sSpace;
+ sSpace.Fill( aFPos.nSpaceCnt );
+ sInsert += sSpace;
+ }
+ if( sInsert.Len() )
+ {
+ GetDoc()->InsertString( *pCurCrsr, sInsert );
+ }
+ }
+ // kein break - Ausrichtung muss noch gesetzt werden
+ case FILL_MARGIN:
+ if( text::HoriOrientation::NONE != aFPos.eOrient )
+ {
+ SvxAdjustItem aAdj( SVX_ADJUST_LEFT, RES_PARATR_ADJUST );
+ switch( aFPos.eOrient )
+ {
+ case text::HoriOrientation::CENTER:
+ aAdj.SetAdjust( SVX_ADJUST_CENTER );
+ break;
+ case text::HoriOrientation::RIGHT:
+ aAdj.SetAdjust( SVX_ADJUST_RIGHT );
+ break;
+ default:
+ break;
+ }
+ GetDoc()->InsertPoolItem( *pCurCrsr, aAdj, 0 );
+ }
+ break;
+ }
+
+ GetDoc()->GetIDocumentUndoRedo().EndUndo( nUndoId, NULL );
+ EndAction();
+
+ bRet = sal_True;
+ }
+ }
+ return bRet;
+}
+
+const SwRedline* SwCrsrShell::SelNextRedline()
+{
+ const SwRedline* pFnd = 0;
+ if( !IsTableMode() )
+ {
+ SET_CURR_SHELL( this );
+ SwCallLink aLk( *this ); // Crsr-Moves ueberwachen, evt. Link callen
+ SwCrsrSaveState aSaveState( *pCurCrsr );
+
+ pFnd = GetDoc()->SelNextRedline( *pCurCrsr );
+ if( pFnd && !pCurCrsr->IsInProtectTable() && !pCurCrsr->IsSelOvr() )
+ UpdateCrsr( SwCrsrShell::SCROLLWIN|SwCrsrShell::CHKRANGE|SwCrsrShell::READONLY);
+ else
+ pFnd = 0;
+ }
+ return pFnd;
+}
+
+const SwRedline* SwCrsrShell::SelPrevRedline()
+{
+ const SwRedline* pFnd = 0;
+ if( !IsTableMode() )
+ {
+ SET_CURR_SHELL( this );
+ SwCallLink aLk( *this ); // Crsr-Moves ueberwachen, evt. Link callen
+ SwCrsrSaveState aSaveState( *pCurCrsr );
+
+ pFnd = GetDoc()->SelPrevRedline( *pCurCrsr );
+ if( pFnd && !pCurCrsr->IsInProtectTable() && !pCurCrsr->IsSelOvr() )
+ UpdateCrsr( SwCrsrShell::SCROLLWIN|SwCrsrShell::CHKRANGE|SwCrsrShell::READONLY);
+ else
+ pFnd = 0;
+ }
+ return pFnd;
+}
+
+const SwRedline* SwCrsrShell::_GotoRedline( sal_uInt16 nArrPos, sal_Bool bSelect )
+{
+ const SwRedline* pFnd = 0;
+ SwCallLink aLk( *this ); // Crsr-Moves ueberwachen, evt. Link callen
+ SwCrsrSaveState aSaveState( *pCurCrsr );
+
+ pFnd = GetDoc()->GetRedlineTbl()[ nArrPos ];
+ if( pFnd )
+ {
+ *pCurCrsr->GetPoint() = *pFnd->Start();
+
+ SwCntntNode* pCNd;
+ SwNodeIndex* pIdx = &pCurCrsr->GetPoint()->nNode;
+ if( !pIdx->GetNode().IsCntntNode() &&
+ 0 != ( pCNd = GetDoc()->GetNodes().GoNextSection( pIdx,
+ sal_True, IsReadOnlyAvailable() )) )
+ {
+ if( *pIdx <= pFnd->End()->nNode )
+ pCurCrsr->GetPoint()->nContent.Assign( pCNd, 0 );
+ else
+ pFnd = 0;
+ }
+
+ if( pFnd && bSelect )
+ {
+ pCurCrsr->SetMark();
+ if( nsRedlineType_t::REDLINE_FMTCOLL == pFnd->GetType() )
+ {
+ pCNd = pIdx->GetNode().GetCntntNode();
+ pCurCrsr->GetPoint()->nContent.Assign( pCNd, pCNd->Len() );
+ pCurCrsr->GetMark()->nContent.Assign( pCNd, 0 );
+ }
+ else
+ *pCurCrsr->GetPoint() = *pFnd->End();
+
+ pIdx = &pCurCrsr->GetPoint()->nNode;
+ if( !pIdx->GetNode().IsCntntNode() &&
+ 0 != ( pCNd = GetDoc()->GetNodes().GoPrevSection( pIdx,
+ sal_True, IsReadOnlyAvailable() )) )
+ {
+ if( *pIdx >= pCurCrsr->GetMark()->nNode )
+ pCurCrsr->GetPoint()->nContent.Assign( pCNd, pCNd->Len() );
+ else
+ pFnd = 0;
+ }
+ }
+
+ if( !pFnd )
+ {
+ pCurCrsr->DeleteMark();
+ pCurCrsr->RestoreSavePos();
+ }
+ else if( bSelect && *pCurCrsr->GetMark() == *pCurCrsr->GetPoint() )
+ pCurCrsr->DeleteMark();
+
+ if( pFnd && !pCurCrsr->IsInProtectTable() && !pCurCrsr->IsSelOvr() )
+ UpdateCrsr( SwCrsrShell::SCROLLWIN | SwCrsrShell::CHKRANGE
+ | SwCrsrShell::READONLY );
+ else
+ {
+ pFnd = 0;
+ if( bSelect )
+ pCurCrsr->DeleteMark();
+ }
+ }
+ return pFnd;
+}
+
+const SwRedline* SwCrsrShell::GotoRedline( sal_uInt16 nArrPos, sal_Bool bSelect )
+{
+ const SwRedline* pFnd = 0;
+ if( !IsTableMode() )
+ {
+ SET_CURR_SHELL( this );
+
+ const SwRedlineTbl& rTbl = GetDoc()->GetRedlineTbl();
+ const SwRedline* pTmp = rTbl[ nArrPos ];
+ sal_uInt16 nSeqNo = pTmp->GetSeqNo();
+ if( nSeqNo && bSelect )
+ {
+ sal_Bool bCheck = sal_False;
+ int nLoopCnt = 2;
+ sal_uInt16 nArrSavPos = nArrPos;
+
+ do {
+ pTmp = _GotoRedline( nArrPos, sal_True );
+
+ if( !pFnd )
+ pFnd = pTmp;
+
+ if( pTmp && bCheck )
+ {
+ // checke auf Ueberlappungen. Das kann durch
+ // FmtColl-Redlines kommen, die auf den gesamten Absatz
+ // aus gedehnt werden.
+
+ SwPaM* pCur = pCurCrsr;
+ SwPaM* pNextPam = (SwPaM*)pCur->GetNext();
+ SwPosition* pCStt = pCur->Start(), *pCEnd = pCur->End();
+ while( pCur != pNextPam )
+ {
+ const SwPosition *pNStt = pNextPam->Start(),
+ *pNEnd = pNextPam->End();
+
+ sal_Bool bDel = sal_True;
+ switch( ::ComparePosition( *pCStt, *pCEnd,
+ *pNStt, *pNEnd ))
+ {
+ case POS_INSIDE: // Pos1 liegt vollstaendig in Pos2
+ if( !pCur->HasMark() )
+ {
+ pCur->SetMark();
+ *pCur->GetMark() = *pNStt;
+ }
+ else
+ *pCStt = *pNStt;
+ *pCEnd = *pNEnd;
+ break;
+
+ case POS_OUTSIDE: // Pos2 liegt vollstaendig in Pos1
+ case POS_EQUAL: // Pos1 ist genauso gross wie Pos2
+ break;
+
+ case POS_OVERLAP_BEFORE: // Pos1 ueberlappt Pos2 am Anfang
+ if( !pCur->HasMark() )
+ pCur->SetMark();
+ *pCEnd = *pNEnd;
+ break;
+ case POS_OVERLAP_BEHIND: // Pos1 ueberlappt Pos2 am Ende
+ if( !pCur->HasMark() )
+ {
+ pCur->SetMark();
+ *pCur->GetMark() = *pNStt;
+ }
+ else
+ *pCStt = *pNStt;
+ break;
+
+ default:
+ bDel = sal_False;
+ }
+
+ if( bDel )
+ {
+ // den brauchen wir nicht mehr
+ SwPaM* pPrevPam = (SwPaM*)pNextPam->GetPrev();
+ delete pNextPam;
+ pNextPam = pPrevPam;
+ }
+ pNextPam = (SwPaM*)pNextPam->GetNext();
+ }
+ }
+
+ sal_uInt16 nFndPos = 2 == nLoopCnt
+ ? rTbl.FindNextOfSeqNo( nArrPos )
+ : rTbl.FindPrevOfSeqNo( nArrPos );
+ if( USHRT_MAX != nFndPos ||
+ ( 0 != ( --nLoopCnt ) && USHRT_MAX != (
+ nFndPos = rTbl.FindPrevOfSeqNo( nArrSavPos ))) )
+ {
+ if( pTmp )
+ {
+ // neuen Cursor erzeugen
+ CreateCrsr();
+ bCheck = sal_True;
+ }
+ nArrPos = nFndPos;
+ }
+ else
+ nLoopCnt = 0;
+
+ } while( nLoopCnt );
+ }
+ else
+ pFnd = _GotoRedline( nArrPos, bSelect );
+ }
+ return pFnd;
+}
+
+
+sal_Bool SwCrsrShell::SelectNxtPrvHyperlink( sal_Bool bNext )
+{
+ SwNodes& rNds = GetDoc()->GetNodes();
+ const SwNode* pBodyEndNd = &rNds.GetEndOfContent();
+ const SwNode* pBodySttNd = pBodyEndNd->StartOfSectionNode();
+ sal_uLong nBodySttNdIdx = pBodySttNd->GetIndex();
+ Point aPt;
+
+ _SetGetExpFld aCmpPos( SwPosition( bNext ? *pBodyEndNd : *pBodySttNd ) );
+ _SetGetExpFld aCurPos( bNext ? *pCurCrsr->End() : *pCurCrsr->Start() );
+ if( aCurPos.GetNode() < nBodySttNdIdx )
+ {
+ const SwCntntNode* pCNd = aCurPos.GetNodeFromCntnt()->GetCntntNode();
+ SwCntntFrm* pFrm;
+ if( pCNd && 0 != ( pFrm = pCNd->getLayoutFrm( GetLayout(), &aPt )) )
+ aCurPos.SetBodyPos( *pFrm );
+ }
+
+ // check first all the hyperlink fields
+ {
+ const SwTxtNode* pTxtNd;
+ const SwCharFmts* pFmts = GetDoc()->GetCharFmts();
+ for( sal_uInt16 n = pFmts->Count(); 1 < n; )
+ {
+ SwIterator<SwTxtINetFmt,SwCharFmt> aIter(*(*pFmts)[--n]);
+
+ for( SwTxtINetFmt* pFnd = aIter.First(); pFnd; pFnd = aIter.Next() )
+ if( 0 != ( pTxtNd = pFnd->GetpTxtNode()) &&
+ pTxtNd->GetNodes().IsDocNodes() )
+ {
+ SwTxtINetFmt& rAttr = *pFnd;
+ SwPosition aTmpPos( *pTxtNd );
+ _SetGetExpFld aPos( aTmpPos.nNode, rAttr );
+ SwCntntFrm* pFrm;
+ if( pTxtNd->GetIndex() < nBodySttNdIdx &&
+ 0 != ( pFrm = pTxtNd->getLayoutFrm( GetLayout(), &aPt )) )
+ aPos.SetBodyPos( *pFrm );
+
+ if( bNext
+ ? ( aPos < aCmpPos && aCurPos < aPos )
+ : ( aCmpPos < aPos && aPos < aCurPos ))
+ {
+ String sTxt( pTxtNd->GetExpandTxt( *rAttr.GetStart(),
+ *rAttr.GetEnd() - *rAttr.GetStart() ) );
+
+ sTxt.EraseAllChars( 0x0a );
+ sTxt.EraseLeadingChars().EraseTrailingChars();
+
+ if( sTxt.Len() )
+ aCmpPos = aPos;
+ }
+ }
+ }
+ }
+ // then check all the Flys with a URL or imapge map
+ {
+ const SwSpzFrmFmts* pFmts = GetDoc()->GetSpzFrmFmts();
+ for( sal_uInt16 n = 0, nEnd = pFmts->Count(); n < nEnd; ++n )
+ {
+ SwFlyFrmFmt* pFmt = (SwFlyFrmFmt*)(*pFmts)[ n ];
+ const SwFmtURL& rURLItem = pFmt->GetURL();
+ if( rURLItem.GetMap() || rURLItem.GetURL().Len() )
+ {
+ SwFlyFrm* pFly = pFmt->GetFrm( &aPt, sal_False );
+ SwPosition aTmpPos( *pBodySttNd );
+ if( pFly &&
+ GetBodyTxtNode( *GetDoc(), aTmpPos, *pFly->GetLower() ) )
+ {
+ _SetGetExpFld aPos( *pFmt, &aTmpPos );
+
+ if( bNext
+ ? ( aPos < aCmpPos && aCurPos < aPos )
+ : ( aCmpPos < aPos && aPos < aCurPos ))
+ aCmpPos = aPos;
+ }
+ }
+ }
+ }
+
+ // found any URL ?
+ sal_Bool bRet = sal_False;
+ const SwTxtINetFmt* pFndAttr = aCmpPos.GetINetFmt();
+ const SwFlyFrmFmt* pFndFmt = aCmpPos.GetFlyFmt();
+ if( pFndAttr || pFndFmt )
+ {
+ SET_CURR_SHELL( this );
+ SwCallLink aLk( *this );
+
+ // find a text attribute ?
+ if( pFndAttr )
+ {
+ SwCrsrSaveState aSaveState( *pCurCrsr );
+
+ aCmpPos.GetPosOfContent( *pCurCrsr->GetPoint() );
+ pCurCrsr->DeleteMark();
+ pCurCrsr->SetMark();
+ pCurCrsr->GetPoint()->nContent = *pFndAttr->SwTxtAttr::GetEnd();
+
+ if( !pCurCrsr->IsInProtectTable() && !pCurCrsr->IsSelOvr() )
+ {
+ UpdateCrsr( SwCrsrShell::SCROLLWIN|SwCrsrShell::CHKRANGE|
+ SwCrsrShell::READONLY );
+ bRet = sal_True;
+ }
+ }
+ // find a draw object ?
+ else if( RES_DRAWFRMFMT == pFndFmt->Which() )
+ {
+ const SdrObject* pSObj = pFndFmt->FindSdrObject();
+ ((SwFEShell*)this)->SelectObj( pSObj->GetCurrentBoundRect().Center() );
+ MakeSelVisible();
+ bRet = sal_True;
+ }
+ else // then is it a fly
+ {
+ SwFlyFrm* pFly = pFndFmt->GetFrm(&aPt, sal_False );
+ if( pFly )
+ {
+ ((SwFEShell*)this)->SelectFlyFrm( *pFly, sal_True );
+ MakeSelVisible();
+ bRet = sal_True;
+ }
+ }
+ }
+ return bRet;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/crsr/crstrvl1.cxx b/sw/source/core/crsr/crstrvl1.cxx
new file mode 100644
index 000000000000..96bc4636d0bf
--- /dev/null
+++ b/sw/source/core/crsr/crstrvl1.cxx
@@ -0,0 +1,107 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+
+#include <crsrsh.hxx>
+#include <viscrs.hxx>
+#include <callnk.hxx>
+
+sal_Bool SwCrsrShell::IsStartWord( sal_Int16 nWordType ) const
+{
+ return pCurCrsr->IsStartWord( nWordType );
+}
+
+sal_Bool SwCrsrShell::IsEndWord( sal_Int16 nWordType ) const
+{
+ return pCurCrsr->IsEndWord( nWordType );
+}
+
+sal_Bool SwCrsrShell::IsInWord( sal_Int16 nWordType ) const
+{
+ return pCurCrsr->IsInWord( nWordType );
+}
+
+sal_Bool SwCrsrShell::IsStartSentence() const
+{
+ return pCurCrsr->IsStartEndSentence( false );
+}
+
+sal_Bool SwCrsrShell::IsEndSentence() const
+{
+ return pCurCrsr->IsStartEndSentence( true );
+}
+
+
+sal_Bool SwCrsrShell::GoStartWord()
+{
+ return CallCrsrFN( &SwCursor::GoStartWord );
+}
+sal_Bool SwCrsrShell::GoEndWord()
+{
+ return CallCrsrFN( &SwCursor::GoEndWord );
+}
+sal_Bool SwCrsrShell::GoNextWord()
+{
+ return CallCrsrFN( &SwCursor::GoNextWord );
+}
+sal_Bool SwCrsrShell::GoPrevWord()
+{
+ return CallCrsrFN( &SwCursor::GoPrevWord );
+}
+sal_Bool SwCrsrShell::GoNextSentence()
+{
+ return CallCrsrFN( &SwCursor::GoNextSentence );
+}
+sal_Bool SwCrsrShell::GoEndSentence()
+{
+ return CallCrsrFN( &SwCursor::GoEndSentence );
+}
+
+sal_Bool SwCrsrShell::GoPrevSentence()
+{
+ return CallCrsrFN( &SwCursor::GoPrevSentence );
+}
+sal_Bool SwCrsrShell::GoStartSentence()
+{
+ return CallCrsrFN( &SwCursor::GoStartSentence );
+}
+
+sal_Bool SwCrsrShell::SelectWord( const Point* pPt )
+{
+ return pCurCrsr->SelectWord( this, pPt );
+}
+
+sal_Bool SwCrsrShell::ExpandToSentenceBorders()
+{
+ return pCurCrsr->ExpandToSentenceBorders();
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/crsr/findattr.cxx b/sw/source/core/crsr/findattr.cxx
new file mode 100644
index 000000000000..d0b1a455f73a
--- /dev/null
+++ b/sw/source/core/crsr/findattr.cxx
@@ -0,0 +1,1273 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+
+#include <com/sun/star/lang/Locale.hpp>
+#include <com/sun/star/util/SearchOptions.hpp>
+#include <com/sun/star/util/SearchFlags.hpp>
+#include <i18npool/mslangid.hxx>
+#include <hintids.hxx>
+#include <vcl/svapp.hxx>
+#include <svl/itemiter.hxx>
+#include <svl/whiter.hxx>
+#include <editeng/brkitem.hxx>
+#include <editeng/colritem.hxx>
+#include <editeng/fontitem.hxx>
+#include <fmtpdsc.hxx>
+#include <txatbase.hxx>
+#include <fchrfmt.hxx>
+#include <charfmt.hxx>
+#include <doc.hxx>
+#include <IDocumentUndoRedo.hxx>
+#include <swcrsr.hxx>
+#include <editsh.hxx>
+#include <ndtxt.hxx>
+#include <pamtyp.hxx>
+#include <swundo.hxx>
+#include <crsskip.hxx>
+
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star::util;
+
+SV_DECL_PTRARR_SORT( SwpFmts, SwFmt*, 0, 4 )
+SV_IMPL_PTRARR_SORT( SwpFmts, SwFmt* )
+
+ // Sonderbehandlung fuer SvxFontItem, nur den Namen vergleichen:
+int CmpAttr( const SfxPoolItem& rItem1, const SfxPoolItem& rItem2 )
+{
+ switch( rItem1.Which() )
+ {
+ case RES_CHRATR_FONT:
+ return ((SvxFontItem&)rItem1).GetFamilyName() ==
+ ((SvxFontItem&)rItem2).GetFamilyName();
+
+ case RES_CHRATR_COLOR:
+ return ((SvxColorItem&)rItem1).GetValue().IsRGBEqual(
+ ((SvxColorItem&)rItem2).GetValue() );
+ case RES_PAGEDESC:
+ return ((SwFmtPageDesc&)rItem1).GetNumOffset() ==
+ ((SwFmtPageDesc&)rItem2).GetNumOffset() &&
+ ((SwFmtPageDesc&)rItem1).GetPageDesc() ==
+ ((SwFmtPageDesc&)rItem2).GetPageDesc();
+ }
+ return rItem1 == rItem2;
+}
+
+
+const SwTxtAttr* GetFrwrdTxtHint( const SwpHints& rHtsArr, sal_uInt16& rPos,
+ xub_StrLen nCntntPos )
+{
+ while( rPos < rHtsArr.Count() )
+ {
+ const SwTxtAttr *pTxtHt = rHtsArr.GetStart( rPos++ );
+ // der Start vom Attribut muss innerhalb des Bereiches liegen !!
+ if( *pTxtHt->GetStart() >= nCntntPos )
+ return pTxtHt; // gueltiges TextAttribut
+ }
+ return 0; // kein gueltiges TextAttribut
+}
+
+
+const SwTxtAttr* GetBkwrdTxtHint( const SwpHints& rHtsArr, sal_uInt16& rPos,
+ xub_StrLen nCntntPos )
+{
+ while( rPos > 0 )
+ {
+ //Hack mit cast fuer das Update
+ const SwTxtAttr *pTxtHt = rHtsArr.GetStart( --rPos );
+ // der Start vom Attribut muss innerhalb des Bereiches liegen !!
+ if( *pTxtHt->GetStart() < nCntntPos )
+ return pTxtHt; // gueltiges TextAttribut
+ }
+ return 0; // kein gueltiges TextAttribut
+}
+
+
+void lcl_SetAttrPam( SwPaM & rPam, xub_StrLen nStart, const xub_StrLen* pEnde,
+ const sal_Bool bSaveMark )
+{
+ xub_StrLen nCntntPos;
+ if( bSaveMark )
+ nCntntPos = rPam.GetMark()->nContent.GetIndex();
+ else
+ nCntntPos = rPam.GetPoint()->nContent.GetIndex();
+ sal_Bool bTstEnde = rPam.GetPoint()->nNode == rPam.GetMark()->nNode;
+
+ SwCntntNode* pCNd = rPam.GetCntntNode();
+ rPam.GetPoint()->nContent.Assign( pCNd, nStart );
+ rPam.SetMark(); // Point == GetMark
+
+ // Point zeigt auf das Ende vom SuchBereich oder Ende vom Attribut
+ if( pEnde )
+ {
+ if( bTstEnde && *pEnde > nCntntPos )
+ rPam.GetPoint()->nContent = nCntntPos;
+ else
+ rPam.GetPoint()->nContent = *pEnde;
+ }
+}
+
+//------------------ Suche nach einem Text Attribut -----------------------
+
+// diese Funktion sucht in einem TextNode nach dem vorgegebenen Attribut.
+// Wird es gefunden, dann hat der SwPaM den Bereich der das Attribut
+// umspannt, unter Beachtung des Suchbereiches
+
+
+sal_Bool lcl_Search( const SwTxtNode& rTxtNd, SwPaM& rPam,
+ const SfxPoolItem& rCmpItem,
+ SwMoveFn fnMove, sal_Bool bValue )
+{
+ if ( !rTxtNd.HasHints() )
+ return sal_False;
+ const SwTxtAttr *pTxtHt = 0;
+ sal_Bool bForward = fnMove == fnMoveForward;
+ sal_uInt16 nPos = bForward ? 0 : rTxtNd.GetSwpHints().Count();
+ xub_StrLen nCntntPos = rPam.GetPoint()->nContent.GetIndex();
+
+ while( 0 != ( pTxtHt=(*fnMove->fnGetHint)(rTxtNd.GetSwpHints(),nPos,nCntntPos)))
+ if( pTxtHt->Which() == rCmpItem.Which() &&
+ ( !bValue || CmpAttr( pTxtHt->GetAttr(), rCmpItem )))
+ {
+ lcl_SetAttrPam( rPam, *pTxtHt->GetStart(), pTxtHt->GetEnd(), bForward );
+ return sal_True;
+ }
+ return sal_False;
+}
+
+
+//------------------ Suche nach mehren Text Attributen -------------------
+
+struct _SwSrchChrAttr
+{
+ sal_uInt16 nWhich;
+ xub_StrLen nStt, nEnd;
+
+ _SwSrchChrAttr( const SfxPoolItem& rItem,
+ xub_StrLen nStart, xub_StrLen nAnyEnd )
+ : nWhich( rItem.Which() ), nStt( nStart ), nEnd( nAnyEnd )
+ {}
+};
+
+class SwAttrCheckArr
+{
+ _SwSrchChrAttr *pFndArr, *pStackArr;
+ xub_StrLen nNdStt, nNdEnd;
+ sal_uInt16 nArrStart, nArrLen;
+ sal_uInt16 nFound, nStackCnt;
+ SfxItemSet aCmpSet;
+ sal_Bool bNoColls;
+ sal_Bool bForward;
+
+public:
+ SwAttrCheckArr( const SfxItemSet& rSet, int bForward, int bNoCollections );
+ ~SwAttrCheckArr();
+
+ void SetNewSet( const SwTxtNode& rTxtNd, const SwPaM& rPam );
+
+ // wieviele Attribute ueberhaupt ??
+ sal_uInt16 Count() const { return aCmpSet.Count(); }
+ int Found() const { return nFound == aCmpSet.Count(); }
+ int CheckStack();
+
+ xub_StrLen Start() const;
+ xub_StrLen End() const;
+
+ xub_StrLen GetNdStt() const { return nNdStt; }
+ xub_StrLen GetNdEnd() const { return nNdEnd; }
+
+ int SetAttrFwd( const SwTxtAttr& rAttr );
+ int SetAttrBwd( const SwTxtAttr& rAttr );
+};
+
+
+
+SwAttrCheckArr::SwAttrCheckArr( const SfxItemSet& rSet, int bFwd,
+ int bNoCollections )
+ : aCmpSet( *rSet.GetPool(), RES_CHRATR_BEGIN, RES_TXTATR_END-1 )
+{
+ aCmpSet.Put( rSet, sal_False );
+ bNoColls = 0 != bNoCollections;
+
+ bForward = 0 != bFwd;
+
+ // Bestimmen den Bereich des Fnd/Stack-Arrays (Min/Max)
+ SfxItemIter aIter( aCmpSet );
+ nArrStart = aCmpSet.GetWhichByPos( aIter.GetFirstPos() );
+ nArrLen = aCmpSet.GetWhichByPos( aIter.GetLastPos() ) - nArrStart+1;
+
+ char* pFndChar = new char[ nArrLen * sizeof(_SwSrchChrAttr) ];
+ char* pStackChar = new char[ nArrLen * sizeof(_SwSrchChrAttr) ];
+
+ pFndArr = (_SwSrchChrAttr*)pFndChar;
+ pStackArr = (_SwSrchChrAttr*)pStackChar;
+}
+
+SwAttrCheckArr::~SwAttrCheckArr()
+{
+ delete[] (char*)pFndArr;
+ delete[] (char*)pStackArr;
+}
+
+void SwAttrCheckArr::SetNewSet( const SwTxtNode& rTxtNd, const SwPaM& rPam )
+{
+ memset( pFndArr, 0, nArrLen * sizeof(_SwSrchChrAttr) );
+ memset( pStackArr, 0, nArrLen * sizeof(_SwSrchChrAttr) );
+ nFound = 0;
+ nStackCnt = 0;
+
+ if( bForward )
+ {
+ nNdStt = rPam.GetPoint()->nContent.GetIndex();
+ nNdEnd = rPam.GetPoint()->nNode == rPam.GetMark()->nNode
+ ? rPam.GetMark()->nContent.GetIndex()
+ : rTxtNd.GetTxt().Len();
+ }
+ else
+ {
+ nNdEnd = rPam.GetPoint()->nContent.GetIndex();
+ nNdStt = rPam.GetPoint()->nNode == rPam.GetMark()->nNode
+ ? rPam.GetMark()->nContent.GetIndex()
+ : 0;
+ }
+
+ if( bNoColls && !rTxtNd.HasSwAttrSet() )
+ return ;
+
+ const SfxItemSet& rSet = rTxtNd.GetSwAttrSet();
+// if( !rSet.Count() )
+// return;
+
+ SfxItemIter aIter( aCmpSet );
+ const SfxPoolItem* pItem = aIter.GetCurItem();
+ const SfxPoolItem* pFndItem;
+ sal_uInt16 nWhich;
+
+ while( sal_True )
+ {
+ // nur testen, ob vorhanden ist ?
+ if( IsInvalidItem( pItem ) )
+ {
+ nWhich = aCmpSet.GetWhichByPos( aIter.GetCurPos() );
+ if( RES_TXTATR_END <= nWhich )
+ break; // Ende der TextAttribute
+
+ if( SFX_ITEM_SET == rSet.GetItemState( nWhich, !bNoColls, &pFndItem )
+ && !CmpAttr( *pFndItem, rSet.GetPool()->GetDefaultItem( nWhich ) ))
+ {
+ pFndArr[ nWhich - nArrStart ] =
+ _SwSrchChrAttr( *pFndItem, nNdStt, nNdEnd );
+ nFound++;
+ }
+ }
+ else
+ {
+ if( RES_TXTATR_END <= (nWhich = pItem->Which() ))
+ break; // Ende der TextAttribute
+
+//JP 27.02.95: wenn nach defaults gesucht wird, dann muss man bis zum Pool
+// runter
+// if( SFX_ITEM_SET == rSet.GetItemState( nWhich, !bNoColls, &pFndItem )
+// && *pFndItem == *pItem )
+ if( CmpAttr( rSet.Get( nWhich, !bNoColls ), *pItem ) )
+ {
+ pFndArr[ nWhich - nArrStart ] =
+ _SwSrchChrAttr( *pItem, nNdStt, nNdEnd );
+ nFound++;
+ }
+ }
+
+ if( aIter.IsAtEnd() )
+ break;
+ pItem = aIter.NextItem();
+ }
+}
+int SwAttrCheckArr::SetAttrFwd( const SwTxtAttr& rAttr )
+{
+ _SwSrchChrAttr aTmp( rAttr.GetAttr(), *rAttr.GetStart(), *rAttr.GetAnyEnd() );
+ // alle die nicht im Bereich sind -> ignorieren
+ if( aTmp.nEnd <= nNdStt || aTmp.nStt >= nNdEnd )
+ return Found();
+
+ const SfxPoolItem* pItem;
+
+// --------------------------------------------------------------
+// Hier wird jetzt ausdruecklich auch in Zeichenvorlagen gesucht
+// --------------------------------------------------------------
+ sal_uInt16 nWhch = rAttr.Which();
+ SfxWhichIter* pIter = NULL;
+ const SfxPoolItem* pTmpItem = NULL;
+ const SfxItemSet* pSet = NULL;
+ if( RES_TXTATR_CHARFMT == nWhch || RES_TXTATR_AUTOFMT == nWhch )
+ {
+ if( bNoColls && RES_TXTATR_CHARFMT == nWhch )
+ return Found();
+ pTmpItem = NULL;
+ pSet = CharFmt::GetItemSet( rAttr.GetAttr() );
+ if ( pSet )
+ {
+ pIter = new SfxWhichIter( *pSet );
+ nWhch = pIter->FirstWhich();
+ while( nWhch &&
+ SFX_ITEM_SET != pSet->GetItemState( nWhch, sal_True, &pTmpItem ) )
+ nWhch = pIter->NextWhich();
+ if( !nWhch )
+ pTmpItem = NULL;
+ }
+ }
+ else
+ pTmpItem = &rAttr.GetAttr();
+ while( pTmpItem )
+ {
+ SfxItemState eState = aCmpSet.GetItemState( nWhch, sal_False, &pItem );
+ if( SFX_ITEM_DONTCARE == eState || SFX_ITEM_SET == eState )
+ {
+ sal_uInt16 n;
+ _SwSrchChrAttr* pCmp;
+
+ // loesche erstmal alle, die bis zu der Start Position schon wieder
+ // ungueltig sind:
+
+ _SwSrchChrAttr* pArrPtr;
+ if( nFound )
+ for( pArrPtr = pFndArr, n = 0; n < nArrLen;
+ ++n, ++pArrPtr )
+ if( pArrPtr->nWhich && pArrPtr->nEnd <= aTmp.nStt )
+ {
+ pArrPtr->nWhich = 0; // geloescht
+ nFound--;
+ }
+
+ // loesche erstmal alle, die bis zu der Start Position schon wieder
+ // ungueltig sind. Und verschiebe alle die "offen" sind, heisst ueber
+ // die Start Position ragen, vom Stack in den FndSet
+
+ if( nStackCnt )
+ for( pArrPtr = pStackArr, n=0; n < nArrLen; ++n, ++pArrPtr )
+ {
+ if( !pArrPtr->nWhich )
+ continue;
+
+ if( pArrPtr->nEnd <= aTmp.nStt )
+ {
+ pArrPtr->nWhich = 0; // geloescht
+ if( !--nStackCnt )
+ break;
+ }
+ else if( pArrPtr->nStt <= aTmp.nStt )
+ {
+ if( ( pCmp = &pFndArr[ n ])->nWhich )
+ {
+ if( pCmp->nEnd < pArrPtr->nEnd ) // erweitern
+ pCmp->nEnd = pArrPtr->nEnd;
+ }
+ else
+ {
+ *pCmp = *pArrPtr;
+ nFound++;
+ }
+ pArrPtr->nWhich = 0;
+ if( !--nStackCnt )
+ break;
+ }
+ }
+
+ sal_Bool bContinue = sal_False;
+
+ if( SFX_ITEM_DONTCARE == eState )
+ {
+ // wird Attribut gueltig ?
+ if( !CmpAttr( aCmpSet.GetPool()->GetDefaultItem( nWhch ),
+ *pTmpItem ))
+ {
+ // suche das Attribut und erweiter es gegebenenfalls
+ if( !( pCmp = &pFndArr[ nWhch - nArrStart ])->nWhich )
+ {
+ *pCmp = aTmp; // nicht gefunden, eintragen
+ nFound++;
+ }
+ else if( pCmp->nEnd < aTmp.nEnd ) // erweitern ?
+ pCmp->nEnd = aTmp.nEnd;
+
+ bContinue = sal_True;
+ }
+ }
+ // wird Attribut gueltig ?
+ else if( CmpAttr( *pItem, *pTmpItem ) )
+ {
+ pFndArr[ nWhch - nArrStart ] = aTmp;
+ ++nFound;
+ bContinue = sal_True;
+ }
+
+ // tja, dann muss es auf den Stack
+ if( !bContinue && ( pCmp = &pFndArr[ nWhch - nArrStart ])->nWhich )
+ {
+ // vorhanden, auf den Stack. Aber nur wenn es noch grosser ist
+ if( pCmp->nEnd > aTmp.nEnd )
+ {
+ OSL_ENSURE( !pStackArr[ nWhch - nArrStart ].nWhich,
+ "Stack-Platz ist noch belegt" );
+
+ if( aTmp.nStt <= pCmp->nStt )
+ pCmp->nStt = aTmp.nEnd;
+ else
+ pCmp->nEnd = aTmp.nStt;
+ // ---------
+
+ pStackArr[ nWhch - nArrStart ] = *pCmp;
+ nStackCnt++;
+ }
+ pCmp->nWhich = 0;
+ nFound--;
+ }
+ }
+ if( pIter )
+ {
+ nWhch = pIter->NextWhich();
+ while( nWhch &&
+ SFX_ITEM_SET != pSet->GetItemState( nWhch, sal_True, &pTmpItem ) )
+ nWhch = pIter->NextWhich();
+ if( !nWhch )
+ break;
+ }
+ else
+ break;
+ }
+ return Found();
+}
+
+
+int SwAttrCheckArr::SetAttrBwd( const SwTxtAttr& rAttr )
+{
+ _SwSrchChrAttr aTmp( rAttr.GetAttr(), *rAttr.GetStart(), *rAttr.GetAnyEnd() );
+ // alle die nicht im Bereich sind -> ignorieren
+ if( aTmp.nEnd < nNdStt || aTmp.nStt >= nNdEnd )
+ return Found();
+
+ const SfxPoolItem* pItem;
+// --------------------------------------------------------------
+// Hier wird jetzt ausdruecklich auch in Zeichenvorlagen gesucht
+// --------------------------------------------------------------
+ sal_uInt16 nWhch = rAttr.Which();
+ SfxWhichIter* pIter = NULL;
+ const SfxPoolItem* pTmpItem = NULL;
+ const SfxItemSet* pSet = NULL;
+ if( RES_TXTATR_CHARFMT == nWhch || RES_TXTATR_AUTOFMT == nWhch )
+ {
+ if( bNoColls && RES_TXTATR_CHARFMT == nWhch )
+ return Found();
+
+ pSet = CharFmt::GetItemSet( rAttr.GetAttr() );
+ if ( pSet )
+ {
+ pIter = new SfxWhichIter( *pSet );
+ nWhch = pIter->FirstWhich();
+ while( nWhch &&
+ SFX_ITEM_SET != pSet->GetItemState( nWhch, sal_True, &pTmpItem ) )
+ nWhch = pIter->NextWhich();
+ if( !nWhch )
+ pTmpItem = NULL;
+ }
+ }
+ else
+ pTmpItem = &rAttr.GetAttr();
+ while( pTmpItem )
+ {
+ SfxItemState eState = aCmpSet.GetItemState( nWhch, sal_False, &pItem );
+ if( SFX_ITEM_DONTCARE == eState || SFX_ITEM_SET == eState )
+ {
+ sal_uInt16 n;
+ _SwSrchChrAttr* pCmp;
+
+ // loesche erstmal alle, die bis zu der Start Position schon wieder
+ // ungueltig sind:
+
+ _SwSrchChrAttr* pArrPtr;
+ if( nFound )
+ for( pArrPtr = pFndArr, n = 0; n < nArrLen; ++n, ++pArrPtr )
+ if( pArrPtr->nWhich && pArrPtr->nStt >= aTmp.nEnd )
+ {
+ pArrPtr->nWhich = 0; // geloescht
+ nFound--;
+ }
+
+ // loesche erstmal alle, die bis zu der Start Position schon wieder
+ // ungueltig sind. Und verschiebe alle die "offen" sind, heisst ueber
+ // die Start Position ragen, vom Stack in den FndSet
+
+ if( nStackCnt )
+ for( pArrPtr = pStackArr, n = 0; n < nArrLen; ++n, ++pArrPtr )
+ {
+ if( !pArrPtr->nWhich )
+ continue;
+
+ if( pArrPtr->nStt >= aTmp.nEnd )
+ {
+ pArrPtr->nWhich = 0; // geloescht
+ if( !--nStackCnt )
+ break;
+ }
+ else if( pArrPtr->nEnd >= aTmp.nEnd )
+ {
+ if( ( pCmp = &pFndArr[ n ])->nWhich )
+ {
+ if( pCmp->nStt > pArrPtr->nStt ) // erweitern
+ pCmp->nStt = pArrPtr->nStt;
+ }
+ else
+ {
+ *pCmp = *pArrPtr;
+ nFound++;
+ }
+ pArrPtr->nWhich = 0;
+ if( !--nStackCnt )
+ break;
+ }
+ }
+
+ sal_Bool bContinue = sal_False;
+ if( SFX_ITEM_DONTCARE == eState )
+ {
+ // wird Attribut gueltig ?
+ if( !CmpAttr( aCmpSet.GetPool()->GetDefaultItem( nWhch ),
+ *pTmpItem ) )
+ {
+ // suche das Attribut und erweiter es gegebenenfalls
+ if( !( pCmp = &pFndArr[ nWhch - nArrStart ])->nWhich )
+ {
+ *pCmp = aTmp; // nicht gefunden, eintragen
+ nFound++;
+ }
+ else if( pCmp->nStt > aTmp.nStt ) // erweitern ?
+ pCmp->nStt = aTmp.nStt;
+
+ bContinue = sal_True;
+ }
+ }
+ // wird Attribut gueltig ?
+ else if( CmpAttr( *pItem, *pTmpItem ))
+ {
+ pFndArr[ nWhch - nArrStart ] = aTmp;
+ ++nFound;
+ bContinue = sal_True;
+ }
+
+ // tja, dann muss es auf den Stack
+ if( !bContinue && ( pCmp = &pFndArr[ nWhch - nArrStart ])->nWhich )
+ {
+ // vorhanden, auf den Stack. Aber nur wenn es noch grosser ist
+ if( pCmp->nStt < aTmp.nStt )
+ {
+ OSL_ENSURE( !pStackArr[ nWhch - nArrStart ].nWhich,
+ "Stack-Platz ist noch belegt" );
+
+ if( aTmp.nEnd <= pCmp->nEnd )
+ pCmp->nEnd = aTmp.nStt;
+ else
+ pCmp->nStt = aTmp.nEnd;
+// ---------
+
+ pStackArr[ nWhch - nArrStart ] = *pCmp;
+ nStackCnt++;
+ }
+ pCmp->nWhich = 0;
+ nFound--;
+ }
+ }
+ if( pIter )
+ {
+ nWhch = pIter->NextWhich();
+ while( nWhch &&
+ SFX_ITEM_SET != pSet->GetItemState( nWhch, sal_True, &pTmpItem ) )
+ nWhch = pIter->NextWhich();
+ if( !nWhch )
+ break;
+ }
+ else
+ break;
+ }
+ return Found();
+}
+
+
+xub_StrLen SwAttrCheckArr::Start() const
+{
+ xub_StrLen nStart = nNdStt;
+ _SwSrchChrAttr* pArrPtr = pFndArr;
+ for( sal_uInt16 n = 0; n < nArrLen; ++n, ++pArrPtr )
+ if( pArrPtr->nWhich && pArrPtr->nStt > nStart )
+ nStart = pArrPtr->nStt;
+
+ return nStart;
+}
+
+
+xub_StrLen SwAttrCheckArr::End() const
+{
+ _SwSrchChrAttr* pArrPtr = pFndArr;
+ xub_StrLen nEnd = nNdEnd;
+ for( sal_uInt16 n = 0; n < nArrLen; ++n, ++pArrPtr )
+ if( pArrPtr->nWhich && pArrPtr->nEnd < nEnd )
+ nEnd = pArrPtr->nEnd;
+
+ return nEnd;
+}
+
+
+int SwAttrCheckArr::CheckStack()
+{
+ if( !nStackCnt )
+ return sal_False;
+
+ sal_uInt16 n;
+ xub_StrLen nSttPos = Start(), nEndPos = End();
+ _SwSrchChrAttr* pArrPtr;
+ for( pArrPtr = pStackArr, n = 0; n < nArrLen; ++n, ++pArrPtr )
+ {
+ if( !pArrPtr->nWhich )
+ continue;
+
+ if( bForward ? pArrPtr->nEnd <= nSttPos : pArrPtr->nStt >= nEndPos )
+ {
+ pArrPtr->nWhich = 0; // geloescht
+ if( !--nStackCnt )
+ return nFound == aCmpSet.Count();
+ }
+ else if( bForward ? pArrPtr->nStt < nEndPos : pArrPtr->nEnd > nSttPos )
+ {
+ // alle die "offen" sind, heisst ueber die Start Position ragen,
+ // im FndSet setzen
+ OSL_ENSURE( !pFndArr[ n ].nWhich, "Array-Platz ist noch belegt" );
+ pFndArr[ n ] = *pArrPtr;
+ pArrPtr->nWhich = 0;
+ nFound++;
+ if( !--nStackCnt )
+ return nFound == aCmpSet.Count();
+ }
+ }
+ return nFound == aCmpSet.Count();
+}
+
+
+
+int lcl_SearchForward( const SwTxtNode& rTxtNd, SwAttrCheckArr& rCmpArr,
+ SwPaM& rPam )
+{
+ xub_StrLen nEndPos, nSttPos;
+ rCmpArr.SetNewSet( rTxtNd, rPam );
+ if( !rTxtNd.HasHints() )
+ {
+ if( !rCmpArr.Found() )
+ return sal_False;
+ nEndPos = rCmpArr.GetNdEnd();
+ lcl_SetAttrPam( rPam, rCmpArr.GetNdStt(), &nEndPos, sal_True );
+ return sal_True;
+ }
+
+ // dann gehe mal durch das nach "Start" sortierte Array
+ const SwpHints& rHtArr = rTxtNd.GetSwpHints();
+ const SwTxtAttr* pAttr;
+ sal_uInt16 nPos = 0;
+
+ // sollte jetzt schon alles vorhanden sein, dann teste, mit welchem
+ // das wieder beendet wird.
+ if( rCmpArr.Found() )
+ {
+ for( ; nPos < rHtArr.Count(); ++nPos )
+ if( !rCmpArr.SetAttrFwd( *( pAttr = rHtArr.GetStart( nPos )) ) )
+ {
+ if( rCmpArr.GetNdStt() < *pAttr->GetStart() )
+ {
+ // dann haben wir unser Ende:
+ lcl_SetAttrPam( rPam, rCmpArr.GetNdStt(),
+ pAttr->GetStart(), sal_True );
+ return sal_True;
+ }
+ // ansonsten muessen wir weiter suchen
+ break;
+ }
+
+ if( nPos == rHtArr.Count() && rCmpArr.Found() )
+ {
+ // dann haben wir unseren Bereich
+ nEndPos = rCmpArr.GetNdEnd();
+ lcl_SetAttrPam( rPam, rCmpArr.GetNdStt(), &nEndPos, sal_True );
+ return sal_True;
+ }
+ }
+
+ for( ; nPos < rHtArr.Count(); ++nPos )
+ if( rCmpArr.SetAttrFwd( *( pAttr = rHtArr.GetStart( nPos )) ) )
+ {
+ // sollten noch mehr auf der gleichen Position anfangen ??
+ // auch die noch mit testen !!
+ nSttPos = *pAttr->GetStart();
+ while( ++nPos < rHtArr.Count() && nSttPos ==
+ *( pAttr = rHtArr.GetStart( nPos ))->GetStart() &&
+ rCmpArr.SetAttrFwd( *pAttr ) )
+ ;
+ if( !rCmpArr.Found() )
+ continue;
+
+ // dann haben wir den Bereich zusammen
+ if( (nSttPos = rCmpArr.Start()) > (nEndPos = rCmpArr.End()) )
+ return sal_False;
+ lcl_SetAttrPam( rPam, nSttPos, &nEndPos, sal_True );
+ return sal_True;
+ }
+
+ if( !rCmpArr.CheckStack() ||
+ (nSttPos = rCmpArr.Start()) > (nEndPos = rCmpArr.End()) )
+ return sal_False;
+ lcl_SetAttrPam( rPam, nSttPos, &nEndPos, sal_True );
+ return sal_True;
+}
+
+
+int lcl_SearchBackward( const SwTxtNode& rTxtNd, SwAttrCheckArr& rCmpArr,
+ SwPaM& rPam )
+{
+ xub_StrLen nEndPos, nSttPos;
+ rCmpArr.SetNewSet( rTxtNd, rPam );
+ if( !rTxtNd.HasHints() )
+ {
+ if( !rCmpArr.Found() )
+ return sal_False;
+ nEndPos = rCmpArr.GetNdEnd();
+ lcl_SetAttrPam( rPam, rCmpArr.GetNdStt(), &nEndPos, sal_False );
+ return sal_True;
+ }
+
+ // dann gehe mal durch das nach "Start" sortierte Array
+ const SwpHints& rHtArr = rTxtNd.GetSwpHints();
+ const SwTxtAttr* pAttr;
+ sal_uInt16 nPos = rHtArr.Count();
+
+ // sollte jetzt schon alles vorhanden sein, dann teste, mit welchem
+ // das wieder beendet wird.
+ if( rCmpArr.Found() )
+ {
+ while( nPos )
+ if( !rCmpArr.SetAttrBwd( *( pAttr = rHtArr.GetEnd( --nPos )) ) )
+ {
+ nSttPos = *pAttr->GetAnyEnd();
+ if( nSttPos < rCmpArr.GetNdEnd() )
+ {
+ // dann haben wir unser Ende:
+ nEndPos = rCmpArr.GetNdEnd();
+ lcl_SetAttrPam( rPam, nSttPos, &nEndPos, sal_False );
+ return sal_True;
+ }
+
+ // ansonsten muessen wir weiter suchen
+ break;
+ }
+
+ if( !nPos && rCmpArr.Found() )
+ {
+ // dann haben wir unseren Bereich
+ nEndPos = rCmpArr.GetNdEnd();
+ lcl_SetAttrPam( rPam, rCmpArr.GetNdStt(), &nEndPos, sal_False );
+ return sal_True;
+ }
+ }
+
+ while( nPos )
+ if( rCmpArr.SetAttrBwd( *( pAttr = rHtArr.GetEnd( --nPos )) ) )
+ {
+ // sollten noch mehr auf der gleichen Position anfangen ??
+ // auch die noch mit testen !!
+ if( nPos )
+ {
+ nEndPos = *pAttr->GetAnyEnd();
+ while( --nPos && nEndPos ==
+ *( pAttr = rHtArr.GetEnd( nPos ))->GetAnyEnd() &&
+ rCmpArr.SetAttrBwd( *pAttr ) )
+ ;
+ }
+ if( !rCmpArr.Found() )
+ continue;
+
+
+ // dann haben wir den Bereich zusammen
+ if( (nSttPos = rCmpArr.Start()) > (nEndPos = rCmpArr.End()) )
+ return sal_False;
+ lcl_SetAttrPam( rPam, nSttPos, &nEndPos, sal_False );
+ return sal_True;
+ }
+
+ if( !rCmpArr.CheckStack() ||
+ (nSttPos = rCmpArr.Start()) > (nEndPos = rCmpArr.End()) )
+ return sal_False;
+ lcl_SetAttrPam( rPam, nSttPos, &nEndPos, sal_False );
+ return sal_True;
+}
+
+
+int lcl_Search( const SwCntntNode& rCNd, const SfxItemSet& rCmpSet, sal_Bool bNoColls )
+{
+ // nur die harte Attributierung suchen ?
+ if( bNoColls && !rCNd.HasSwAttrSet() )
+ return sal_False;
+
+ const SfxItemSet& rNdSet = rCNd.GetSwAttrSet();
+ SfxItemIter aIter( rCmpSet );
+ const SfxPoolItem* pItem = aIter.GetCurItem();
+ const SfxPoolItem* pNdItem;
+ sal_uInt16 nWhich;
+
+ while( sal_True )
+ {
+ // nur testen, ob vorhanden ist ?
+ if( IsInvalidItem( pItem ))
+ {
+ nWhich = rCmpSet.GetWhichByPos( aIter.GetCurPos() );
+ if( SFX_ITEM_SET != rNdSet.GetItemState( nWhich, !bNoColls, &pNdItem )
+ || CmpAttr( *pNdItem, rNdSet.GetPool()->GetDefaultItem( nWhich ) ))
+ return sal_False;
+ }
+ else
+ {
+ nWhich = pItem->Which();
+
+ if( !CmpAttr( rNdSet.Get( nWhich, !bNoColls ), *pItem ))
+ return sal_False;
+ }
+
+ if( aIter.IsAtEnd() )
+ break;
+ pItem = aIter.NextItem();
+ }
+ return sal_True; // wurde gefunden
+}
+
+
+sal_Bool SwPaM::Find( const SfxPoolItem& rAttr, sal_Bool bValue, SwMoveFn fnMove,
+ const SwPaM *pRegion, sal_Bool bInReadOnly )
+{
+ // stelle fest welches Attribut gesucht wird:
+ sal_uInt16 nWhich = rAttr.Which();
+ int bCharAttr = isCHRATR(nWhich) || isTXTATR(nWhich);
+
+ SwPaM* pPam = MakeRegion( fnMove, pRegion );
+
+ sal_Bool bFound = sal_False;
+ sal_Bool bFirst = sal_True;
+ sal_Bool bSrchForward = fnMove == fnMoveForward;
+ SwCntntNode * pNode;
+ const SfxPoolItem* pItem;
+ SwpFmts aFmtArr;
+
+ // Wenn am Anfang/Ende, aus dem Node moven
+ if( bSrchForward
+ ? pPam->GetPoint()->nContent.GetIndex() == pPam->GetCntntNode()->Len()
+ : !pPam->GetPoint()->nContent.GetIndex() )
+ {
+ if( !(*fnMove->fnNds)( &pPam->GetPoint()->nNode, sal_False ))
+ {
+ delete pPam;
+ return sal_False;
+ }
+ SwCntntNode *pNd = pPam->GetCntntNode();
+ xub_StrLen nTmpPos = bSrchForward ? 0 : pNd->Len();
+ pPam->GetPoint()->nContent.Assign( pNd, nTmpPos );
+ }
+
+ while( 0 != ( pNode = ::GetNode( *pPam, bFirst, fnMove, bInReadOnly ) ) )
+ {
+ if( bCharAttr )
+ {
+ if( !pNode->IsTxtNode() ) // CharAttr sind nur in TextNodes
+ continue;
+
+ if( ((SwTxtNode*)pNode)->HasHints() &&
+ lcl_Search( *(SwTxtNode*)pNode, *pPam, rAttr, fnMove, bValue ))
+ {
+ // setze auf die Werte vom Attribut
+ SetMark();
+ *GetPoint() = *pPam->GetPoint();
+ *GetMark() = *pPam->GetMark();
+ bFound = sal_True;
+ break;
+ }
+ else if (isTXTATR(nWhich))
+ continue; // --> also weiter
+ }
+
+ // keine harte Attributierung, dann pruefe, ob die Vorlage schon
+ // mal nach dem Attribut befragt wurde
+ if( !pNode->HasSwAttrSet() )
+ {
+ const SwFmt* pTmpFmt = pNode->GetFmtColl();
+ if( aFmtArr.Count() && aFmtArr.Seek_Entry( pTmpFmt ))
+ continue; // die Collection wurde schon mal befragt
+ aFmtArr.Insert( pTmpFmt );
+ }
+
+ if( SFX_ITEM_SET == pNode->GetSwAttrSet().GetItemState( nWhich,
+ sal_True, &pItem ) && ( !bValue || *pItem == rAttr ) )
+ {
+ // FORWARD: Point an das Ende, GetMark zum Anfanf vom Node
+ // BACKWARD: Point zum Anfang, GetMark an das Ende vom Node
+ // und immer nach der Logik: inkl. Start, exkl. End !!!
+ *GetPoint() = *pPam->GetPoint();
+ SetMark();
+ pNode->MakeEndIndex( &GetPoint()->nContent );
+ bFound = sal_True;
+ break;
+ }
+ }
+
+ // beim rueckwaerts Suchen noch Point und Mark vertauschen
+ if( bFound && !bSrchForward )
+ Exchange();
+
+ delete pPam;
+ return bFound;
+}
+
+
+typedef int (*FnSearchAttr)( const SwTxtNode&, SwAttrCheckArr&, SwPaM& );
+
+sal_Bool SwPaM::Find( const SfxItemSet& rSet, sal_Bool bNoColls, SwMoveFn fnMove,
+ const SwPaM *pRegion, sal_Bool bInReadOnly, sal_Bool bMoveFirst )
+{
+ SwPaM* pPam = MakeRegion( fnMove, pRegion );
+
+ sal_Bool bFound = sal_False;
+ sal_Bool bFirst = sal_True;
+ sal_Bool bSrchForward = fnMove == fnMoveForward;
+ SwCntntNode * pNode;
+ SwpFmts aFmtArr;
+
+ // teste doch mal welche Text/Char-Attribute gesucht werden
+ SwAttrCheckArr aCmpArr( rSet, bSrchForward, bNoColls );
+ SfxItemSet aOtherSet( GetDoc()->GetAttrPool(),
+ RES_PARATR_BEGIN, RES_GRFATR_END-1 );
+ aOtherSet.Put( rSet, sal_False ); // alle Invalid-Items erhalten!
+
+ FnSearchAttr fnSearch = bSrchForward
+ ? (&::lcl_SearchForward)
+ : (&::lcl_SearchBackward);
+
+ // Wenn am Anfang/Ende, aus dem Node moven
+ // Wenn am Anfang/Ende, aus dem Node moven
+ if( bMoveFirst &&
+ ( bSrchForward
+ ? pPam->GetPoint()->nContent.GetIndex() == pPam->GetCntntNode()->Len()
+ : !pPam->GetPoint()->nContent.GetIndex() ) )
+ {
+ if( !(*fnMove->fnNds)( &pPam->GetPoint()->nNode, sal_False ))
+ {
+ delete pPam;
+ return sal_False;
+ }
+ SwCntntNode *pNd = pPam->GetCntntNode();
+ xub_StrLen nTmpPos = bSrchForward ? 0 : pNd->Len();
+ pPam->GetPoint()->nContent.Assign( pNd, nTmpPos );
+ }
+
+
+ while( 0 != ( pNode = ::GetNode( *pPam, bFirst, fnMove, bInReadOnly ) ) )
+ {
+ if( aCmpArr.Count() )
+ {
+ if( !pNode->IsTxtNode() ) // CharAttr sind nur in TextNodes
+ continue;
+
+ if( (!aOtherSet.Count() ||
+ lcl_Search( *pNode, aOtherSet, bNoColls )) &&
+ (*fnSearch)( *(SwTxtNode*)pNode, aCmpArr, *pPam ))
+ {
+ // setze auf die Werte vom Attribut
+ SetMark();
+ *GetPoint() = *pPam->GetPoint();
+ *GetMark() = *pPam->GetMark();
+ bFound = sal_True;
+ break;
+ }
+ continue; // TextAttribute
+ }
+
+ if( !aOtherSet.Count() )
+ continue;
+
+ // keine harte Attributierung, dann pruefe, ob die Vorlage schon
+ // mal nach dem Attribut befragt wurde
+ if( !pNode->HasSwAttrSet() )
+ {
+ const SwFmt* pTmpFmt = pNode->GetFmtColl();
+ if( aFmtArr.Count() && aFmtArr.Seek_Entry( pTmpFmt ))
+ continue; // die Collection wurde schon mal befragt
+ aFmtArr.Insert( pTmpFmt );
+ }
+
+ if( lcl_Search( *pNode, aOtherSet, bNoColls ))
+ {
+ // FORWARD: Point an das Ende, GetMark zum Anfanf vom Node
+ // BACKWARD: Point zum Anfang, GetMark an das Ende vom Node
+ // und immer nach der Logik: inkl. Start, exkl. End !!!
+ *GetPoint() = *pPam->GetPoint();
+ SetMark();
+ pNode->MakeEndIndex( &GetPoint()->nContent );
+ bFound = sal_True;
+ break;
+ }
+ }
+
+ // beim rueckwaerts Suchen noch Point und Mark vertauschen
+ if( bFound && !bSrchForward )
+ Exchange();
+
+ delete pPam;
+ return bFound;
+}
+
+//------------------ Methoden vom SwCursor ---------------------------
+
+// Parameter fuer das Suchen vom Attributen
+struct SwFindParaAttr : public SwFindParas
+{
+ sal_Bool bValue;
+ const SfxItemSet *pSet, *pReplSet;
+ const SearchOptions *pSearchOpt;
+ SwCursor& rCursor;
+ utl::TextSearch* pSTxt;
+
+ SwFindParaAttr( const SfxItemSet& rSet, sal_Bool bNoCollection,
+ const SearchOptions* pOpt, const SfxItemSet* pRSet,
+ SwCursor& rCrsr )
+ : bValue( bNoCollection ), pSet( &rSet ), pReplSet( pRSet ),
+ pSearchOpt( pOpt ), rCursor( rCrsr ),pSTxt( 0 ) {}
+
+ virtual ~SwFindParaAttr() { delete pSTxt; }
+
+ virtual int Find( SwPaM* , SwMoveFn , const SwPaM*, sal_Bool bInReadOnly );
+ virtual int IsReplaceMode() const;
+};
+
+
+int SwFindParaAttr::Find( SwPaM* pCrsr, SwMoveFn fnMove, const SwPaM* pRegion,
+ sal_Bool bInReadOnly )
+{
+ // String ersetzen ?? (nur wenn Text angegeben oder nicht attributiert
+ // gesucht wird)
+ sal_Bool bReplaceTxt = pSearchOpt && ( pSearchOpt->replaceString.getLength() ||
+ !pSet->Count() );
+ sal_Bool bReplaceAttr = pReplSet && pReplSet->Count();
+ sal_Bool bMoveFirst = !bReplaceAttr;
+ if( bInReadOnly && (bReplaceAttr || bReplaceTxt ))
+ bInReadOnly = sal_False;
+
+ // wir suchen nach Attributen, soll zusaetzlich Text gesucht werden ?
+ {
+ SwPaM aRegion( *pRegion->GetMark(), *pRegion->GetPoint() );
+ SwPaM* pTextRegion = &aRegion;
+ SwPaM aSrchPam( *pCrsr->GetPoint() );
+
+ while( sal_True )
+ {
+ if( pSet->Count() ) // gibts ueberhaupt Attributierung?
+ {
+ // zuerst die Attributierung
+ if( !aSrchPam.Find( *pSet, bValue, fnMove, &aRegion, bInReadOnly, bMoveFirst ) )
+//JP 17.11.95: was ist mit Attributen in leeren Absaetzen !!
+// || *pCrsr->GetMark() == *pCrsr->GetPoint() ) // kein Bereich ??
+ return FIND_NOT_FOUND;
+ bMoveFirst = sal_True;
+
+ if( !pSearchOpt )
+ break; // ok, nur Attribute, also gefunden
+
+ pTextRegion = &aSrchPam;
+ }
+ else if( !pSearchOpt )
+ return FIND_NOT_FOUND;
+
+ // dann darin den Text
+ if( !pSTxt )
+ {
+ SearchOptions aTmp( *pSearchOpt );
+
+ // search in selection
+ aTmp.searchFlag |= (SearchFlags::REG_NOT_BEGINOFLINE |
+ SearchFlags::REG_NOT_ENDOFLINE);
+
+ MsLangId::convertLanguageToLocale( LANGUAGE_SYSTEM, aTmp.Locale );
+
+ pSTxt = new utl::TextSearch( aTmp );
+ }
+
+ // todo/mba: searching for attributes in Outliner text?!
+ sal_Bool bSearchInNotes = sal_False;
+
+ // Bug 24665: suche im richtigen Bereich weiter (pTextRegion!)
+ if( aSrchPam.Find( *pSearchOpt, bSearchInNotes, *pSTxt, fnMove, pTextRegion, bInReadOnly ) &&
+ *aSrchPam.GetMark() != *aSrchPam.GetPoint() ) // gefunden ?
+ break; // also raus
+ else if( !pSet->Count() )
+ return FIND_NOT_FOUND; // nur Text und nicht gefunden
+
+ *aRegion.GetMark() = *aSrchPam.GetPoint();
+ }
+
+ *pCrsr->GetPoint() = *aSrchPam.GetPoint();
+ pCrsr->SetMark();
+ *pCrsr->GetMark() = *aSrchPam.GetMark();
+ }
+
+ if( bReplaceTxt )
+ {
+ const bool bRegExp(
+ SearchAlgorithms_REGEXP == pSearchOpt->algorithmType);
+ SwIndex& rSttCntIdx = pCrsr->Start()->nContent;
+ xub_StrLen nSttCnt = rSttCntIdx.GetIndex();
+
+ // damit die Region auch verschoben wird, in den Shell-Cursr-Ring
+ // mit aufnehmen !!
+ Ring *pPrevRing = 0;
+ if( bRegExp )
+ {
+ pPrevRing = pRegion->GetPrev();
+ ((Ring*)pRegion)->MoveRingTo( &rCursor );
+ }
+
+ ::std::auto_ptr<String> pRepl( (bRegExp) ?
+ ReplaceBackReferences( *pSearchOpt, pCrsr ) : 0 );
+ rCursor.GetDoc()->ReplaceRange( *pCrsr,
+ (pRepl.get()) ? *pRepl : String(pSearchOpt->replaceString),
+ bRegExp );
+ rCursor.SaveTblBoxCntnt( pCrsr->GetPoint() );
+
+ if( bRegExp )
+ {
+ // und die Region wieder herausnehmen:
+ Ring *p, *pNext = (Ring*)pRegion;
+ do {
+ p = pNext;
+ pNext = p->GetNext();
+ p->MoveTo( (Ring*)pRegion );
+ } while( p != pPrevRing );
+ }
+ rSttCntIdx = nSttCnt;
+ }
+
+ if( bReplaceAttr )
+ {
+ // --- Ist die Selection noch da ??????
+
+ //JP 13.07.95: alle gesuchten Attribute werden, wenn nicht im
+ // ReplaceSet angegeben, auf Default zurueck gesetzt
+
+ if( !pSet->Count() )
+ {
+ pCrsr->GetDoc()->InsertItemSet( *pCrsr, *pReplSet, 0 );
+ }
+ else
+ {
+ SfxItemPool* pPool = pReplSet->GetPool();
+ SfxItemSet aSet( *pPool, pReplSet->GetRanges() );
+
+ SfxItemIter aIter( *pSet );
+ const SfxPoolItem* pItem = aIter.GetCurItem();
+ while( sal_True )
+ {
+ // alle die nicht gesetzt sind mit Pool-Defaults aufuellen
+ if( !IsInvalidItem( pItem ) && SFX_ITEM_SET !=
+ pReplSet->GetItemState( pItem->Which(), sal_False ))
+ aSet.Put( pPool->GetDefaultItem( pItem->Which() ));
+
+ if( aIter.IsAtEnd() )
+ break;
+ pItem = aIter.NextItem();
+ }
+ aSet.Put( *pReplSet );
+ pCrsr->GetDoc()->InsertItemSet( *pCrsr, aSet, 0 );
+ }
+
+ return FIND_NO_RING;
+ }
+
+ else
+ return FIND_FOUND;
+}
+
+
+int SwFindParaAttr::IsReplaceMode() const
+{
+ return ( pSearchOpt && pSearchOpt->replaceString.getLength() ) ||
+ ( pReplSet && pReplSet->Count() );
+}
+
+// Suchen nach Attributen
+
+
+sal_uLong SwCursor::Find( const SfxItemSet& rSet, sal_Bool bNoCollections,
+ SwDocPositions nStart, SwDocPositions nEnde, sal_Bool& bCancel,
+ FindRanges eFndRngs,
+ const SearchOptions* pSearchOpt, const SfxItemSet* pReplSet )
+{
+ // OLE-Benachrichtigung abschalten !!
+ SwDoc* pDoc = GetDoc();
+ Link aLnk( pDoc->GetOle2Link() );
+ pDoc->SetOle2Link( Link() );
+
+ sal_Bool bReplace = ( pSearchOpt && ( pSearchOpt->replaceString.getLength() ||
+ !rSet.Count() ) ) ||
+ (pReplSet && pReplSet->Count());
+ bool const bStartUndo = pDoc->GetIDocumentUndoRedo().DoesUndo() && bReplace;
+ if (bStartUndo)
+ {
+ pDoc->GetIDocumentUndoRedo().StartUndo( UNDO_REPLACE, NULL );
+ }
+
+ SwFindParaAttr aSwFindParaAttr( rSet, bNoCollections, pSearchOpt,
+ pReplSet, *this );
+
+ sal_uLong nRet = FindAll(aSwFindParaAttr, nStart, nEnde, eFndRngs, bCancel );
+ pDoc->SetOle2Link( aLnk );
+ if( nRet && bReplace )
+ pDoc->SetModified();
+
+ if (bStartUndo)
+ {
+ pDoc->GetIDocumentUndoRedo().EndUndo( UNDO_REPLACE, NULL );
+ }
+
+ return nRet;
+}
+
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/crsr/findcoll.cxx b/sw/source/core/crsr/findcoll.cxx
new file mode 100644
index 000000000000..b3f3f39e8a97
--- /dev/null
+++ b/sw/source/core/crsr/findcoll.cxx
@@ -0,0 +1,124 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+#include <tools/resid.hxx>
+
+#include <swcrsr.hxx>
+#include <doc.hxx>
+#include <IDocumentUndoRedo.hxx>
+#include <pamtyp.hxx>
+#include <swundo.hxx>
+#include <SwRewriter.hxx>
+#include <comcore.hrc>
+
+//------------------ Methoden der CrsrShell ---------------------------
+
+// Parameter fuer das Suchen vom FormatCollections
+struct SwFindParaFmtColl : public SwFindParas
+{
+ const SwTxtFmtColl *pFmtColl, *pReplColl;
+ SwCursor& rCursor;
+ SwFindParaFmtColl( const SwTxtFmtColl& rFmtColl,
+ const SwTxtFmtColl* pRpColl, SwCursor& rCrsr )
+ : pFmtColl( &rFmtColl ), pReplColl( pRpColl ), rCursor( rCrsr )
+ {}
+ virtual int Find( SwPaM* , SwMoveFn , const SwPaM*, sal_Bool bInReadOnly );
+ virtual int IsReplaceMode() const;
+};
+
+
+int SwFindParaFmtColl::Find( SwPaM* pCrsr, SwMoveFn fnMove, const SwPaM* pRegion,
+ sal_Bool bInReadOnly )
+{
+ int nRet = FIND_FOUND;
+ if( bInReadOnly && pReplColl )
+ bInReadOnly = sal_False;
+
+ if( !pCrsr->Find( *pFmtColl, fnMove, pRegion, bInReadOnly ) )
+ nRet = FIND_NOT_FOUND;
+ else if( pReplColl )
+ {
+ pCrsr->GetDoc()->SetTxtFmtColl( *pCrsr, (SwTxtFmtColl*)pReplColl );
+ nRet = FIND_NO_RING;
+ }
+ return nRet;
+}
+
+
+int SwFindParaFmtColl::IsReplaceMode() const
+{
+ return 0 != pReplColl;
+}
+
+
+// Suchen nach Format-Collections
+
+
+sal_uLong SwCursor::Find( const SwTxtFmtColl& rFmtColl,
+ SwDocPositions nStart, SwDocPositions nEnde, sal_Bool& bCancel,
+ FindRanges eFndRngs, const SwTxtFmtColl* pReplFmtColl )
+{
+ // OLE-Benachrichtigung abschalten !!
+ SwDoc* pDoc = GetDoc();
+ Link aLnk( pDoc->GetOle2Link() );
+ pDoc->SetOle2Link( Link() );
+
+ bool const bStartUndo =
+ pDoc->GetIDocumentUndoRedo().DoesUndo() && pReplFmtColl;
+ if (bStartUndo)
+ {
+ SwRewriter aRewriter;
+ aRewriter.AddRule(UNDO_ARG1, rFmtColl.GetName());
+ aRewriter.AddRule(UNDO_ARG2, SW_RES(STR_YIELDS));
+ aRewriter.AddRule(UNDO_ARG3, pReplFmtColl->GetName());
+
+ pDoc->GetIDocumentUndoRedo().StartUndo( UNDO_UI_REPLACE_STYLE,
+ &aRewriter );
+ }
+
+ SwFindParaFmtColl aSwFindParaFmtColl( rFmtColl, pReplFmtColl, *this );
+
+ sal_uLong nRet = FindAll( aSwFindParaFmtColl, nStart, nEnde, eFndRngs, bCancel );
+ pDoc->SetOle2Link( aLnk );
+
+ if( nRet && pReplFmtColl )
+ pDoc->SetModified();
+
+ if (bStartUndo)
+ {
+ pDoc->GetIDocumentUndoRedo().EndUndo(UNDO_END, 0);
+ }
+ return nRet;
+}
+
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/crsr/findfmt.cxx b/sw/source/core/crsr/findfmt.cxx
new file mode 100644
index 000000000000..7a548c393f33
--- /dev/null
+++ b/sw/source/core/crsr/findfmt.cxx
@@ -0,0 +1,86 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+
+#include <doc.hxx>
+#include <pamtyp.hxx>
+
+
+sal_Bool SwPaM::Find( const SwFmt& rFmt, SwMoveFn fnMove,
+ const SwPaM *pRegion, sal_Bool bInReadOnly )
+{
+ sal_Bool bFound = sal_False;
+ sal_Bool bSrchForward = fnMove == fnMoveForward;
+ SwPaM* pPam = MakeRegion( fnMove, pRegion );
+
+ // Wenn am Anfang/Ende, aus dem Node moven
+ if( bSrchForward
+ ? pPam->GetPoint()->nContent.GetIndex() == pPam->GetCntntNode()->Len()
+ : !pPam->GetPoint()->nContent.GetIndex() )
+ {
+ if( !(*fnMove->fnNds)( &pPam->GetPoint()->nNode, sal_False ))
+ {
+ delete pPam;
+ return sal_False;
+ }
+ SwCntntNode *pNd = pPam->GetPoint()->nNode.GetNode().GetCntntNode();
+ xub_StrLen nTmpPos = bSrchForward ? 0 : pNd->Len();
+ pPam->GetPoint()->nContent.Assign( pNd, nTmpPos );
+ }
+
+ sal_Bool bFirst = sal_True;
+ SwCntntNode* pNode;
+ while( !bFound &&
+ 0 != ( pNode = ::GetNode( *pPam, bFirst, fnMove, bInReadOnly )))
+ {
+ if( 0 != ( bFound = pNode->GetFmtColl() == &rFmt ))
+ {
+ // wurde die FormatCollection gefunden, dann handelt es sich auf
+ // jedenfall um einen SwCntntNode !!
+
+ // FORWARD: SPoint an das Ende, GetMark zum Anfanf vom Node
+ // BACKWARD: SPoint zum Anfang, GetMark an das Ende vom Node
+ // und immer nach der Logik: inkl. Start, exkl. End !!!
+ *GetPoint() = *pPam->GetPoint();
+ SetMark();
+ pNode->MakeEndIndex( &GetPoint()->nContent );
+ GetMark()->nContent = 0;
+ if( !bSrchForward ) // rueckwaerts Suche?
+ Exchange(); // SPoint und GetMark tauschen
+ break;
+ }
+ }
+ delete pPam;
+ return bFound;
+}
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/crsr/findtxt.cxx b/sw/source/core/crsr/findtxt.cxx
new file mode 100644
index 000000000000..ec939a7f9786
--- /dev/null
+++ b/sw/source/core/crsr/findtxt.cxx
@@ -0,0 +1,713 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+#include <com/sun/star/util/SearchOptions.hpp>
+#include <com/sun/star/util/SearchFlags.hpp>
+
+#define _SVSTDARR_USHORTS
+#define _SVSTDARR_ULONGS
+#include <svl/svstdarr.hxx>
+
+#include <vcl/svapp.hxx>
+#include <vcl/window.hxx>
+
+#include <txatritr.hxx>
+#include <fldbas.hxx>
+#include <fmtfld.hxx>
+#include <txtatr.hxx>
+#include <txtfld.hxx>
+#include <swcrsr.hxx>
+#include <doc.hxx>
+#include <IDocumentUndoRedo.hxx>
+#include <pamtyp.hxx>
+#include <ndtxt.hxx>
+#include <swundo.hxx>
+#include <UndoInsert.hxx>
+#include <breakit.hxx>
+
+#include <docsh.hxx>
+#include <PostItMgr.hxx>
+#include <viewsh.hxx>
+
+using namespace ::com::sun::star;
+using namespace util;
+
+String *ReplaceBackReferences( const SearchOptions& rSearchOpt, SwPaM* pPam );
+
+String& lcl_CleanStr( const SwTxtNode& rNd, xub_StrLen nStart,
+ xub_StrLen& rEnde, SvULongs& rArr, String& rRet,
+ bool bRemoveSoftHyphen )
+{
+ rRet = rNd.GetTxt();
+ if( rArr.Count() )
+ rArr.Remove( 0, rArr.Count() );
+
+ const SwpHints *pHts = rNd.GetpSwpHints();
+
+ sal_uInt16 n = 0;
+ xub_StrLen nSoftHyphen = nStart;
+ xub_StrLen nHintStart = STRING_LEN;
+ bool bNewHint = true;
+ bool bNewSoftHyphen = true;
+ const xub_StrLen nEnd = rEnde;
+ SvUShorts aReplaced;
+
+ do
+ {
+ if ( bNewHint )
+ nHintStart = pHts && n < pHts->Count() ?
+ *(*pHts)[n]->GetStart() :
+ STRING_LEN;
+
+ if ( bNewSoftHyphen )
+ nSoftHyphen = bRemoveSoftHyphen ?
+ rNd.GetTxt().Search( CHAR_SOFTHYPHEN, nSoftHyphen ) :
+ STRING_LEN;
+
+ bNewHint = false;
+ bNewSoftHyphen = false;
+
+ xub_StrLen nStt = 0;
+
+ // Check if next stop is a hint.
+ if ( STRING_LEN != nHintStart && nHintStart < nSoftHyphen && nHintStart < nEnd )
+ {
+ nStt = nHintStart;
+ bNewHint = true;
+ }
+ // Check if next stop is a soft hyphen.
+ else if ( STRING_LEN != nSoftHyphen && nSoftHyphen < nHintStart && nSoftHyphen < nEnd )
+ {
+ nStt = nSoftHyphen;
+ bNewSoftHyphen = true;
+ }
+ // If nSoftHyphen == nHintStart, the current hint *must* be a hint with an end.
+ else if ( STRING_LEN != nSoftHyphen && nSoftHyphen == nHintStart )
+ {
+ nStt = nSoftHyphen;
+ bNewHint = true;
+ bNewSoftHyphen = true;
+ }
+ else
+ break;
+
+ const xub_StrLen nAkt = nStt - rArr.Count();
+
+ if ( bNewHint )
+ {
+ const SwTxtAttr* pHt = (*pHts)[n];
+ if ( pHt->HasDummyChar() && (nStt >= nStart) )
+ {
+ //JP 17.05.00: Task 75806 ask for ">=" and not for ">"
+ switch( pHt->Which() )
+ {
+ case RES_TXTATR_FLYCNT:
+ case RES_TXTATR_FTN:
+ case RES_TXTATR_FIELD:
+ case RES_TXTATR_REFMARK:
+ case RES_TXTATR_TOXMARK:
+ case RES_TXTATR_META:
+ case RES_TXTATR_METAFIELD:
+ {
+ // JP 06.05.98: mit Bug 50100 werden sie als Trenner erwuenscht und nicht
+ // mehr zum Wort dazu gehoerend.
+ // MA 23.06.98: mit Bug 51215 sollen sie konsequenterweise auch am
+ // Satzanfang und -ende ignoriert werden wenn sie Leer sind.
+ // Dazu werden sie schlicht entfernt. Fuer den Anfang entfernen
+ // wir sie einfach.
+ // Fuer das Ende merken wir uns die Ersetzungen und entferenen
+ // hinterher alle am Stringende (koenten ja 'normale' 0x7f drinstehen
+ sal_Bool bEmpty = RES_TXTATR_FIELD != pHt->Which() ||
+ !(static_cast<SwTxtFld const*>(pHt)
+ ->GetFld().GetFld()->ExpandField(true).Len());
+ if ( bEmpty && nStart == nAkt )
+ {
+ rArr.Insert( nAkt, rArr.Count() );
+ --rEnde;
+ rRet.Erase( nAkt, 1 );
+ }
+ else
+ {
+ if ( bEmpty )
+ aReplaced.Insert( nAkt, aReplaced.Count() );
+ rRet.SetChar( nAkt, '\x7f' );
+ }
+ }
+ break;
+ default:
+ OSL_FAIL( "unknown case in lcl_CleanStr" );
+ break;
+ }
+ }
+ ++n;
+ }
+
+ if ( bNewSoftHyphen )
+ {
+ rArr.Insert( nAkt, rArr.Count() );
+ --rEnde;
+ rRet.Erase( nAkt, 1 );
+ ++nSoftHyphen;
+ }
+ }
+ while ( true );
+
+ for( sal_uInt16 i = aReplaced.Count(); i; )
+ {
+ const xub_StrLen nTmp = aReplaced[ --i ];
+ if( nTmp == rRet.Len() - 1 )
+ {
+ rRet.Erase( nTmp );
+ rArr.Insert( nTmp, rArr.Count() );
+ --rEnde;
+ }
+ }
+
+ return rRet;
+}
+
+// skip all non SwPostIts inside the array
+xub_StrLen GetPostIt(xub_StrLen aCount,const SwpHints *pHts)
+{
+ xub_StrLen aIndex = 0;
+ while (aCount)
+ {
+ for (xub_StrLen i = 0; i <pHts->Count();i++)
+ {
+ aIndex++;
+ const SwTxtAttr* pTxtAttr = (*pHts)[i];
+ if ( (pTxtAttr->Which()==RES_TXTATR_FIELD) &&
+ (pTxtAttr->GetFld().GetFld()->Which()==RES_POSTITFLD))
+ {
+ aCount--;
+ if (!aCount)
+ break;
+ }
+ }
+ }
+ // throw away all following non postits
+ for (xub_StrLen i = aIndex; i <pHts->Count();i++)
+ {
+ const SwTxtAttr* pTxtAttr = (*pHts)[i];
+ if ( (pTxtAttr->Which()==RES_TXTATR_FIELD) &&
+ (pTxtAttr->GetFld().GetFld()->Which()==RES_POSTITFLD))
+ break;
+ else
+ aIndex++;
+ }
+ return aIndex;
+}
+
+sal_uInt8 SwPaM::Find( const SearchOptions& rSearchOpt, sal_Bool bSearchInNotes , utl::TextSearch& rSTxt,
+ SwMoveFn fnMove, const SwPaM * pRegion,
+ sal_Bool bInReadOnly )
+{
+ if( !rSearchOpt.searchString.getLength() )
+ return sal_False;
+
+ SwPaM* pPam = MakeRegion( fnMove, pRegion );
+ sal_Bool bSrchForward = fnMove == fnMoveForward;
+ SwNodeIndex& rNdIdx = pPam->GetPoint()->nNode;
+ SwIndex& rCntntIdx = pPam->GetPoint()->nContent;
+
+ // Wenn am Anfang/Ende, aus dem Node moven
+ // beim leeren Node nicht weiter
+ if( bSrchForward
+ ? ( rCntntIdx.GetIndex() == pPam->GetCntntNode()->Len() &&
+ rCntntIdx.GetIndex() )
+ : !rCntntIdx.GetIndex() && pPam->GetCntntNode()->Len() )
+ {
+ if( !(*fnMove->fnNds)( &rNdIdx, sal_False ))
+ {
+ delete pPam;
+ return sal_False;
+ }
+ SwCntntNode *pNd = rNdIdx.GetNode().GetCntntNode();
+ xub_StrLen nTmpPos = bSrchForward ? 0 : pNd->Len();
+ rCntntIdx.Assign( pNd, nTmpPos );
+ }
+
+ /*
+ * Ist bFound == sal_True, dann wurde der String gefunden und in
+ * nStart und nEnde steht der gefundenen String
+ */
+ sal_Bool bFound = sal_False;
+ /*
+ * StartPostion im Text oder Anfangsposition
+ */
+ sal_Bool bFirst = sal_True;
+ SwCntntNode * pNode;
+ //testarea
+ //String sCleanStr;
+ //SvULongs aFltArr;
+ //const SwNode* pSttNd = &rNdIdx.GetNode();
+
+ xub_StrLen nStart, nEnde, nTxtLen;
+
+ sal_Bool bRegSearch = SearchAlgorithms_REGEXP == rSearchOpt.algorithmType;
+ sal_Bool bChkEmptyPara = bRegSearch && 2 == rSearchOpt.searchString.getLength() &&
+ ( !rSearchOpt.searchString.compareToAscii( "^$" ) ||
+ !rSearchOpt.searchString.compareToAscii( "$^" ) );
+ sal_Bool bChkParaEnd = bRegSearch && 1 == rSearchOpt.searchString.getLength() &&
+ !rSearchOpt.searchString.compareToAscii( "$" );
+
+// LanguageType eLastLang = 0;
+ while( 0 != ( pNode = ::GetNode( *pPam, bFirst, fnMove, bInReadOnly ) ))
+ {
+ if( pNode->IsTxtNode() )
+ {
+ nTxtLen = ((SwTxtNode*)pNode)->GetTxt().Len();
+ if( rNdIdx == pPam->GetMark()->nNode )
+ nEnde = pPam->GetMark()->nContent.GetIndex();
+ else
+ nEnde = bSrchForward ? nTxtLen : 0;
+ nStart = rCntntIdx.GetIndex();
+
+ /* #i80135# */
+ // if there are SwPostItFields inside our current node text, we split the text into seperate pieces
+ // and search for text inside the pieces as well as inside the fields
+ const SwpHints *pHts = ((SwTxtNode*)pNode)->GetpSwpHints();
+
+ // count postitfields by looping over all fields
+ xub_StrLen aNumberPostits = 0;
+ xub_StrLen aIgnore = 0;
+ if (pHts && bSearchInNotes)
+ {
+ if (!bSrchForward)
+ {
+ xub_StrLen swap = nEnde;
+ nEnde = nStart;
+ nStart = swap;
+ }
+
+ for (xub_StrLen i = 0; i <pHts->Count();i++)
+ {
+ xub_StrLen aPos = *(*pHts)[i]->GetStart();
+ const SwTxtAttr* pTxtAttr = (*pHts)[i];
+ if ( (pTxtAttr->Which()==RES_TXTATR_FIELD) &&
+ (pTxtAttr->GetFld().GetFld()->Which()==RES_POSTITFLD))
+ {
+ if ( (aPos >= nStart) && (aPos <= nEnde) )
+ aNumberPostits++;
+ else
+ {
+ if (bSrchForward)
+ aIgnore++;
+ }
+ }
+ }
+
+ if (!bSrchForward)
+ {
+ xub_StrLen swap = nEnde;
+ nEnde = nStart;
+ nStart = swap;
+ }
+
+ }
+
+ SwDocShell *const pDocShell = pNode->GetDoc()->GetDocShell();
+ ViewShell *const pWrtShell = (pDocShell) ? (ViewShell*)(pDocShell->GetWrtShell()) : 0;
+ SwPostItMgr *const pPostItMgr = (pWrtShell) ? pWrtShell->GetPostItMgr() : 0;
+
+ xub_StrLen aStart = 0;
+ // do we need to finish a note?
+ if (pPostItMgr && pPostItMgr->HasActiveSidebarWin())
+ {
+ if (bSearchInNotes)
+ {
+ if (bSrchForward)
+ aStart++;
+ else
+ {
+ if (aNumberPostits)
+ --aNumberPostits;
+ }
+ //search inside and finsih and put focus back into the doc
+ if (pPostItMgr->FinishSearchReplace(rSearchOpt,bSrchForward))
+ {
+ bFound = true ;
+ break;
+ }
+ }
+ else
+ {
+ pPostItMgr->SetActiveSidebarWin(0);
+ }
+ }
+
+ if (aNumberPostits)
+ {
+ // now we have to split
+ xub_StrLen nStartInside = 0;
+ xub_StrLen nEndeInside = 0;
+ sal_Int16 aLoop= bSrchForward ? aStart : aNumberPostits;
+
+ while ( (aLoop>=0) && (aLoop<=aNumberPostits))
+ {
+ if (bSrchForward)
+ {
+ nStartInside = aLoop==0 ? nStart : *(*pHts)[GetPostIt(aLoop+aIgnore-1,pHts)]->GetStart()+1;
+ nEndeInside = aLoop==aNumberPostits? nEnde : *(*pHts)[GetPostIt(aLoop+aIgnore,pHts)]->GetStart();
+ nTxtLen = nEndeInside-nStartInside;
+ }
+ else
+ {
+ nStartInside = aLoop==aNumberPostits ? nStart : *(*pHts)[GetPostIt(aLoop+aIgnore,pHts)]->GetStart();
+ nEndeInside = aLoop==0 ? nEnde : *(*pHts)[GetPostIt(aLoop+aIgnore-1,pHts)]->GetStart()+1;
+ nTxtLen = nStartInside-nEndeInside;
+ }
+ // search inside the text between a note
+ bFound = DoSearch(rSearchOpt,rSTxt,fnMove,bSrchForward,bRegSearch,bChkEmptyPara,bChkParaEnd,
+ nStartInside,nEndeInside,nTxtLen, pNode,pPam);
+ if (bFound)
+ break;
+ else
+ {
+ // we should now be right in front of a note, search inside
+ if ( (bSrchForward && (GetPostIt(aLoop + aIgnore,pHts) < pHts->Count()) ) || ( !bSrchForward && (aLoop!=0) ))
+ {
+ const SwTxtAttr* pTxtAttr = bSrchForward ? (*pHts)[GetPostIt(aLoop+aIgnore,pHts)] : (*pHts)[GetPostIt(aLoop+aIgnore-1,pHts)];
+ if ( pPostItMgr && pPostItMgr->SearchReplace(((SwTxtFld*)pTxtAttr)->GetFld(),rSearchOpt,bSrchForward) )
+ {
+ bFound = true ;
+ break;
+ }
+ }
+ }
+ aLoop = bSrchForward ? aLoop+1 : aLoop-1;
+ }
+ }
+ else
+ {
+ // if there is no SwPostItField inside or searching inside notes is disabled, we search the whole length just like before
+ bFound = DoSearch(rSearchOpt,rSTxt,fnMove,bSrchForward,bRegSearch,bChkEmptyPara,bChkParaEnd,
+ nStart,nEnde,nTxtLen, pNode,pPam);
+ }
+ if (bFound)
+ break;
+ }
+ }
+ delete pPam;
+ return bFound;
+}
+
+bool SwPaM::DoSearch( const SearchOptions& rSearchOpt, utl::TextSearch& rSTxt,
+ SwMoveFn fnMove,
+ sal_Bool bSrchForward, sal_Bool bRegSearch, sal_Bool bChkEmptyPara, sal_Bool bChkParaEnd,
+ xub_StrLen &nStart, xub_StrLen &nEnde, xub_StrLen nTxtLen,SwNode* pNode, SwPaM* pPam)
+{
+ bool bFound = false;
+ SwNodeIndex& rNdIdx = pPam->GetPoint()->nNode;
+ const SwNode* pSttNd = &rNdIdx.GetNode();
+ String sCleanStr;
+ SvULongs aFltArr;
+ LanguageType eLastLang = 0;
+ // if the search string contains a soft hypen, we don't strip them from the text:
+ bool bRemoveSoftHyphens = true;
+ if ( bRegSearch )
+ {
+ const rtl::OUString a00AD(RTL_CONSTASCII_USTRINGPARAM("\\x00AD"));
+ if ( -1 != rSearchOpt.searchString.indexOf( a00AD ) )
+ bRemoveSoftHyphens = false;
+ }
+ else
+ {
+ if ( 1 == rSearchOpt.searchString.getLength() &&
+ CHAR_SOFTHYPHEN == rSearchOpt.searchString.toChar() )
+ bRemoveSoftHyphens = false;
+ }
+
+ if( bSrchForward )
+ lcl_CleanStr( *(SwTxtNode*)pNode, nStart, nEnde,
+ aFltArr, sCleanStr, bRemoveSoftHyphens );
+ else
+ lcl_CleanStr( *(SwTxtNode*)pNode, nEnde, nStart,
+ aFltArr, sCleanStr, bRemoveSoftHyphens );
+
+ SwScriptIterator* pScriptIter = 0;
+ sal_uInt16 nSearchScript = 0;
+ sal_uInt16 nCurrScript = 0;
+
+ if ( SearchAlgorithms_APPROXIMATE == rSearchOpt.algorithmType &&
+ pBreakIt->GetBreakIter().is() )
+ {
+ pScriptIter = new SwScriptIterator( sCleanStr, nStart, bSrchForward );
+ nSearchScript = pBreakIt->GetRealScriptOfText( rSearchOpt.searchString, 0 );
+ }
+
+ xub_StrLen nStringEnd = nEnde;
+ while ( (bSrchForward && nStart < nStringEnd) ||
+ (! bSrchForward && nStart > nStringEnd) )
+ {
+ // SearchAlgorithms_APPROXIMATE works on a per word base
+ // so we have to provide the text searcher with the correct
+ // locale, because it uses the breakiterator
+ if ( pScriptIter )
+ {
+ nEnde = pScriptIter->GetScriptChgPos();
+ nCurrScript = pScriptIter->GetCurrScript();
+ if ( nSearchScript == nCurrScript )
+ {
+ const LanguageType eCurrLang =
+ ((SwTxtNode*)pNode)->GetLang( bSrchForward ?
+ nStart :
+ nEnde );
+
+ if ( eCurrLang != eLastLang )
+ {
+ const lang::Locale aLocale(
+ pBreakIt->GetLocale( eCurrLang ) );
+ rSTxt.SetLocale( rSearchOpt, aLocale );
+ eLastLang = eCurrLang;
+ }
+ }
+ pScriptIter->Next();
+ }
+
+ if( nSearchScript == nCurrScript &&
+ (rSTxt.*fnMove->fnSearch)( sCleanStr, &nStart, &nEnde, 0 ))
+ {
+ // setze den Bereich richtig
+ *GetPoint() = *pPam->GetPoint();
+ SetMark();
+
+ // Start und Ende wieder korrigieren !!
+ if( aFltArr.Count() )
+ {
+ xub_StrLen n, nNew;
+ // bei Rueckwaertssuche die Positionen temp. vertauschen
+ if( !bSrchForward ) { n = nStart; nStart = nEnde; nEnde = n; }
+
+ for( n = 0, nNew = nStart;
+ n < aFltArr.Count() && aFltArr[ n ] <= nStart;
+ ++n, ++nNew )
+ ;
+ nStart = nNew;
+ for( n = 0, nNew = nEnde;
+ n < aFltArr.Count() && aFltArr[ n ] < nEnde;
+ ++n, ++nNew )
+ ;
+ nEnde = nNew;
+
+ // bei Rueckwaertssuche die Positionen temp. vertauschen
+ if( !bSrchForward ) { n = nStart; nStart = nEnde; nEnde = n; }
+ }
+ GetMark()->nContent = nStart; // Startposition setzen
+ GetPoint()->nContent = nEnde;
+
+ if( !bSrchForward ) // rueckwaerts Suche?
+ Exchange(); // Point und Mark tauschen
+ bFound = sal_True;
+ break;
+ }
+
+ nStart = nEnde;
+ } // end of script while
+
+ delete pScriptIter;
+
+ if ( bFound )
+ return true;
+ else if( ( bChkEmptyPara && !nStart && !nTxtLen ) || bChkParaEnd )
+ {
+ *GetPoint() = *pPam->GetPoint();
+ GetPoint()->nContent = bChkParaEnd ? nTxtLen : 0;
+ SetMark();
+ if( (bSrchForward || pSttNd != &rNdIdx.GetNode()) &&
+ Move( fnMoveForward, fnGoCntnt ) &&
+ (!bSrchForward || pSttNd != &GetPoint()->nNode.GetNode()) &&
+ 1 == Abs( (int)( GetPoint()->nNode.GetIndex() -
+ GetMark()->nNode.GetIndex()) ) )
+ {
+ if( !bSrchForward ) // rueckwaerts Suche?
+ Exchange(); // Point und Mark tauschen
+ //bFound = sal_True;
+ //break;
+ return true;
+ }
+ }
+ return bFound;
+}
+
+// Parameter fuers Suchen und Ersetzen von Text
+struct SwFindParaText : public SwFindParas
+{
+ const SearchOptions& rSearchOpt;
+ SwCursor& rCursor;
+ utl::TextSearch aSTxt;
+ sal_Bool bReplace;
+ sal_Bool bSearchInNotes;
+
+ SwFindParaText( const SearchOptions& rOpt, sal_Bool bSearchNotes, int bRepl, SwCursor& rCrsr )
+ : rSearchOpt( rOpt ), rCursor( rCrsr ), aSTxt( rOpt ), bReplace( 0 != bRepl ), bSearchInNotes( bSearchNotes )
+ {}
+ virtual int Find( SwPaM* , SwMoveFn , const SwPaM*, sal_Bool bInReadOnly );
+ virtual int IsReplaceMode() const;
+ virtual ~SwFindParaText();
+};
+
+SwFindParaText::~SwFindParaText()
+{
+}
+
+int SwFindParaText::Find( SwPaM* pCrsr, SwMoveFn fnMove,
+ const SwPaM* pRegion, sal_Bool bInReadOnly )
+{
+ if( bInReadOnly && bReplace )
+ bInReadOnly = sal_False;
+
+ sal_Bool bFnd = (sal_Bool)pCrsr->Find( rSearchOpt, bSearchInNotes, aSTxt, fnMove, pRegion, bInReadOnly );
+
+
+ if( bFnd && bReplace ) // String ersetzen ??
+ {
+ // Replace-Methode vom SwDoc benutzen
+ const bool bRegExp(SearchAlgorithms_REGEXP == rSearchOpt.algorithmType);
+ SwIndex& rSttCntIdx = pCrsr->Start()->nContent;
+ xub_StrLen nSttCnt = rSttCntIdx.GetIndex();
+ // damit die Region auch verschoben wird, in den Shell-Cursr-Ring
+ // mit aufnehmen !!
+ Ring *pPrev(0);
+ if( bRegExp )
+ {
+ pPrev = pRegion->GetPrev();
+ ((Ring*)pRegion)->MoveRingTo( &rCursor );
+ }
+
+ ::std::auto_ptr<String> pRepl( (bRegExp)
+ ? ReplaceBackReferences( rSearchOpt, pCrsr ) : 0 );
+ rCursor.GetDoc()->ReplaceRange( *pCrsr,
+ (pRepl.get()) ? *pRepl : String(rSearchOpt.replaceString),
+ bRegExp );
+ rCursor.SaveTblBoxCntnt( pCrsr->GetPoint() );
+
+ if( bRegExp )
+ {
+ // und die Region wieder herausnehmen:
+ Ring *p, *pNext = (Ring*)pRegion;
+ do {
+ p = pNext;
+ pNext = p->GetNext();
+ p->MoveTo( (Ring*)pRegion );
+ } while( p != pPrev );
+ }
+ pCrsr->Start()->nContent = nSttCnt;
+ return FIND_NO_RING;
+ }
+ return bFnd ? FIND_FOUND : FIND_NOT_FOUND;
+}
+
+
+int SwFindParaText::IsReplaceMode() const
+{
+ return bReplace;
+}
+
+
+sal_uLong SwCursor::Find( const SearchOptions& rSearchOpt, sal_Bool bSearchInNotes,
+ SwDocPositions nStart, SwDocPositions nEnde,
+ sal_Bool& bCancel,
+ FindRanges eFndRngs, int bReplace )
+{
+ // OLE-Benachrichtigung abschalten !!
+ SwDoc* pDoc = GetDoc();
+ Link aLnk( pDoc->GetOle2Link() );
+ pDoc->SetOle2Link( Link() );
+
+ bool const bStartUndo = pDoc->GetIDocumentUndoRedo().DoesUndo() && bReplace;
+ if (bStartUndo)
+ {
+ pDoc->GetIDocumentUndoRedo().StartUndo( UNDO_REPLACE, NULL );
+ }
+
+ sal_Bool bSearchSel = 0 != (rSearchOpt.searchFlag & SearchFlags::REG_NOT_BEGINOFLINE);
+ if( bSearchSel )
+ eFndRngs = (FindRanges)(eFndRngs | FND_IN_SEL);
+ SwFindParaText aSwFindParaText( rSearchOpt, bSearchInNotes, bReplace, *this );
+ sal_uLong nRet = FindAll( aSwFindParaText, nStart, nEnde, eFndRngs, bCancel );
+ pDoc->SetOle2Link( aLnk );
+ if( nRet && bReplace )
+ pDoc->SetModified();
+
+ if (bStartUndo)
+ {
+ SwRewriter rewriter(MakeUndoReplaceRewriter(
+ nRet, rSearchOpt.searchString, rSearchOpt.replaceString));
+ pDoc->GetIDocumentUndoRedo().EndUndo( UNDO_REPLACE, & rewriter );
+ }
+ return nRet;
+}
+
+String *ReplaceBackReferences( const SearchOptions& rSearchOpt, SwPaM* pPam )
+{
+ String *pRet = 0;
+ if( pPam && pPam->HasMark() &&
+ SearchAlgorithms_REGEXP == rSearchOpt.algorithmType )
+ {
+ const SwCntntNode* pTxtNode = pPam->GetCntntNode( sal_True );
+ if( pTxtNode && pTxtNode->IsTxtNode() && pTxtNode == pPam->GetCntntNode( sal_False ) )
+ {
+ utl::TextSearch aSTxt( rSearchOpt );
+ String aStr( pPam->GetTxt() );
+ String aSearchStr( rSearchOpt.searchString );
+ String aReplaceStr( rSearchOpt.replaceString );
+ aStr.EraseAllChars( CH_TXTATR_BREAKWORD );
+ aStr.EraseAllChars( CH_TXTATR_INWORD );
+ xub_StrLen nStart = 0;
+ String sX( 'x' );
+ if( pPam->Start()->nContent > 0 )
+ {
+ aStr.Insert( sX, 0 );
+ ++nStart;
+ }
+ xub_StrLen nEnd = aStr.Len();
+ bool bDeleteLastX = false;
+ if( pPam->End()->nContent < (static_cast<const SwTxtNode*>(pTxtNode))->GetTxt().Len() )
+ {
+ aStr.Insert( sX );
+ bDeleteLastX = true;
+ }
+ SearchResult aResult;
+ if( aSTxt.SearchFrwrd( aStr, &nStart, &nEnd, &aResult ) )
+ {
+ if( bDeleteLastX )
+ aStr.Erase( aStr.Len() - 1 );
+ aSTxt.ReplaceBackReferences( aReplaceStr, aStr, aResult );
+ pRet = new String( aReplaceStr );
+ }
+ }
+ }
+ return pRet;
+}
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/crsr/pam.cxx b/sw/source/core/crsr/pam.cxx
new file mode 100644
index 000000000000..fa79b3e5f397
--- /dev/null
+++ b/sw/source/core/crsr/pam.cxx
@@ -0,0 +1,1205 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+
+#include <hintids.hxx>
+#include <editeng/protitem.hxx>
+#include <cntfrm.hxx>
+#include <pagefrm.hxx>
+#include <doc.hxx>
+#include <docary.hxx>
+#include <pam.hxx>
+#include <pamtyp.hxx>
+#include <txtfrm.hxx>
+#include <fmtcntnt.hxx>
+#include <frmatr.hxx>
+#include <swtable.hxx>
+#include <crsskip.hxx>
+
+// Formular view
+#include <flyfrm.hxx>
+#include <fmteiro.hxx>
+#include <section.hxx>
+#include <sectfrm.hxx>
+#include <ndtxt.hxx>
+
+#include <IMark.hxx>
+#include <hints.hxx>
+
+#include <xmloff/odffields.hxx>
+
+// fuer den dummen ?MSC-? Compiler
+inline xub_StrLen GetSttOrEnd( sal_Bool bCondition, const SwCntntNode& rNd )
+{
+ return bCondition ? 0 : rNd.Len();
+}
+
+/*************************************************************************
+|*
+|* SwPosition
+|*
+|* Beschreibung PAM.DOC
+|*
+*************************************************************************/
+
+
+SwPosition::SwPosition( const SwNodeIndex & rNodeIndex, const SwIndex & rCntnt )
+ : nNode( rNodeIndex ), nContent( rCntnt )
+{
+}
+
+SwPosition::SwPosition( const SwNodeIndex & rNodeIndex )
+ : nNode( rNodeIndex ), nContent( nNode.GetNode().GetCntntNode() )
+{
+}
+
+SwPosition::SwPosition( const SwNode& rNode )
+ : nNode( rNode ), nContent( nNode.GetNode().GetCntntNode() )
+{
+}
+
+SwPosition::SwPosition( SwCntntNode & rNode, const xub_StrLen nOffset )
+ : nNode( rNode ), nContent( &rNode, nOffset )
+{
+}
+
+
+SwPosition::SwPosition( const SwPosition & rPos )
+ : nNode( rPos.nNode ), nContent( rPos.nContent )
+{
+}
+
+SwPosition &SwPosition::operator=(const SwPosition &rPos)
+{
+ nNode = rPos.nNode;
+ nContent = rPos.nContent;
+ return *this;
+}
+
+
+sal_Bool SwPosition::operator<(const SwPosition &rPos) const
+{
+ if( nNode < rPos.nNode )
+ return sal_True;
+ if( nNode == rPos.nNode )
+ return ( nContent < rPos.nContent );
+ return sal_False;
+}
+
+
+sal_Bool SwPosition::operator>(const SwPosition &rPos) const
+{
+ if(nNode > rPos.nNode )
+ return sal_True;
+ if( nNode == rPos.nNode )
+ return ( nContent > rPos.nContent );
+ return sal_False;
+}
+
+
+sal_Bool SwPosition::operator<=(const SwPosition &rPos) const
+{
+ if(nNode < rPos.nNode )
+ return sal_True;
+ if( nNode == rPos.nNode )
+ return ( nContent <= rPos.nContent );
+ return sal_False;
+}
+
+
+sal_Bool SwPosition::operator>=(const SwPosition &rPos) const
+{
+ if(nNode > rPos.nNode )
+ return sal_True;
+ if( nNode == rPos.nNode )
+ return ( nContent >= rPos.nContent );
+ return sal_False;
+}
+
+
+sal_Bool SwPosition::operator==(const SwPosition &rPos) const
+{
+ return
+ ( ( nNode == rPos.nNode ) && ( nContent == rPos.nContent ) ?
+ sal_True: sal_False);
+}
+
+
+sal_Bool SwPosition::operator!=(const SwPosition &rPos) const
+{
+ if( nNode != rPos.nNode )
+ return sal_True;
+ return ( nContent != rPos.nContent );
+}
+
+SwDoc * SwPosition::GetDoc() const
+{
+ return nNode.GetNode().GetDoc();
+}
+
+SwComparePosition ComparePosition(
+ const SwPosition& rStt1, const SwPosition& rEnd1,
+ const SwPosition& rStt2, const SwPosition& rEnd2 )
+{
+ SwComparePosition nRet;
+ if( rStt1 < rStt2 )
+ {
+ if( rEnd1 > rStt2 )
+ {
+ if( rEnd1 >= rEnd2 )
+ nRet = POS_OUTSIDE;
+ else
+ nRet = POS_OVERLAP_BEFORE;
+
+ }
+ else if( rEnd1 == rStt2 )
+ nRet = POS_COLLIDE_END;
+ else
+ nRet = POS_BEFORE;
+ }
+ else if( rEnd2 > rStt1 )
+ {
+ if( rEnd2 >= rEnd1 )
+ {
+ if( rEnd2 == rEnd1 && rStt2 == rStt1 )
+ nRet = POS_EQUAL;
+ else
+ nRet = POS_INSIDE;
+ }
+ else
+ {
+ if (rStt1 == rStt2)
+ nRet = POS_OUTSIDE;
+ else
+ nRet = POS_OVERLAP_BEHIND;
+ }
+ }
+ else if( rEnd2 == rStt1 )
+ nRet = POS_COLLIDE_START;
+ else
+ nRet = POS_BEHIND;
+ return nRet;
+}
+
+SwComparePosition ComparePosition(
+ const unsigned long nStt1, const unsigned long nEnd1,
+ const unsigned long nStt2, const unsigned long nEnd2 )
+{
+ SwComparePosition nRet;
+ if( nStt1 < nStt2 )
+ {
+ if( nEnd1 > nStt2 )
+ {
+ if( nEnd1 >= nEnd2 )
+ nRet = POS_OUTSIDE;
+ else
+ nRet = POS_OVERLAP_BEFORE;
+
+ }
+ else if( nEnd1 == nStt2 )
+ nRet = POS_COLLIDE_END;
+ else
+ nRet = POS_BEFORE;
+ }
+ else if( nEnd2 > nStt1 )
+ {
+ if( nEnd2 >= nEnd1 )
+ {
+ if( nEnd2 == nEnd1 && nStt2 == nStt1 )
+ nRet = POS_EQUAL;
+ else
+ nRet = POS_INSIDE;
+ }
+ else
+ {
+ if (nStt1 == nStt2)
+ nRet = POS_OUTSIDE;
+ else
+ nRet = POS_OVERLAP_BEHIND;
+ }
+ }
+ else if( nEnd2 == nStt1 )
+ nRet = POS_COLLIDE_START;
+ else
+ nRet = POS_BEHIND;
+ return nRet;
+}
+
+/* */
+
+enum CHKSECTION { Chk_Both, Chk_One, Chk_None };
+
+
+CHKSECTION lcl_TstIdx( sal_uLong nSttIdx, sal_uLong nEndIdx, const SwNode& rEndNd )
+{
+ sal_uLong nStt = rEndNd.StartOfSectionIndex(), nEnd = rEndNd.GetIndex();
+ CHKSECTION eSec = nStt < nSttIdx && nEnd >= nSttIdx ? Chk_One : Chk_None;
+ if( nStt < nEndIdx && nEnd >= nEndIdx )
+ return( eSec == Chk_One ? Chk_Both : Chk_One );
+ return eSec;
+}
+
+
+sal_Bool lcl_ChkOneRange( CHKSECTION eSec, sal_Bool bChkSections,
+ const SwNode& rBaseEnd, sal_uLong nStt, sal_uLong nEnd )
+{
+ if( eSec != Chk_Both )
+ return sal_False;
+
+ if( !bChkSections )
+ return sal_True;
+
+ // suche die umspannende Section
+ const SwNodes& rNds = rBaseEnd.GetNodes();
+ const SwNode *pTmp, *pNd = rNds[ nStt ];
+ if( !pNd->IsStartNode() )
+ pNd = pNd->StartOfSectionNode();
+
+ if( pNd == rNds[ nEnd ]->StartOfSectionNode() )
+ return sal_True; // der gleiche StartNode, die selbe Section
+
+ // steht schon auf einem GrundSection Node ? Fehler !!!
+ if( !pNd->StartOfSectionIndex() )
+ return sal_False;
+
+ while( ( pTmp = pNd->StartOfSectionNode())->EndOfSectionNode() !=
+ &rBaseEnd )
+ pNd = pTmp;
+
+ sal_uLong nSttIdx = pNd->GetIndex(), nEndIdx = pNd->EndOfSectionIndex();
+ return nSttIdx <= nStt && nStt <= nEndIdx &&
+ nSttIdx <= nEnd && nEnd <= nEndIdx ? sal_True : sal_False;
+}
+
+
+sal_Bool CheckNodesRange( const SwNodeIndex& rStt,
+ const SwNodeIndex& rEnd, sal_Bool bChkSection )
+{
+ const SwNodes& rNds = rStt.GetNodes();
+ sal_uLong nStt = rStt.GetIndex(), nEnd = rEnd.GetIndex();
+ CHKSECTION eSec = lcl_TstIdx( nStt, nEnd, rNds.GetEndOfContent() );
+ if( Chk_None != eSec ) return eSec == Chk_Both ? sal_True : sal_False;
+
+ eSec = lcl_TstIdx( nStt, nEnd, rNds.GetEndOfAutotext() );
+ if( Chk_None != eSec )
+ return lcl_ChkOneRange( eSec, bChkSection,
+ rNds.GetEndOfAutotext(), nStt, nEnd );
+
+ eSec = lcl_TstIdx( nStt, nEnd, rNds.GetEndOfPostIts() );
+ if( Chk_None != eSec )
+ return lcl_ChkOneRange( eSec, bChkSection,
+ rNds.GetEndOfPostIts(), nStt, nEnd );
+
+ eSec = lcl_TstIdx( nStt, nEnd, rNds.GetEndOfInserts() );
+ if( Chk_None != eSec )
+ return lcl_ChkOneRange( eSec, bChkSection,
+ rNds.GetEndOfInserts(), nStt, nEnd );
+
+ eSec = lcl_TstIdx( nStt, nEnd, rNds.GetEndOfRedlines() );
+ if( Chk_None != eSec )
+ return lcl_ChkOneRange( eSec, bChkSection,
+ rNds.GetEndOfRedlines(), nStt, nEnd );
+
+ return sal_False; // liegt irgendwo dazwischen, FEHLER
+}
+
+
+sal_Bool GoNext(SwNode* pNd, SwIndex * pIdx, sal_uInt16 nMode )
+{
+ if( pNd->IsCntntNode() )
+ return ((SwCntntNode*)pNd)->GoNext( pIdx, nMode );
+ return sal_False;
+}
+
+
+sal_Bool GoPrevious( SwNode* pNd, SwIndex * pIdx, sal_uInt16 nMode )
+{
+ if( pNd->IsCntntNode() )
+ return ((SwCntntNode*)pNd)->GoPrevious( pIdx, nMode );
+ return sal_False;
+}
+
+
+SwCntntNode* GoNextNds( SwNodeIndex* pIdx, sal_Bool bChk )
+{
+ SwNodeIndex aIdx( *pIdx );
+ SwCntntNode* pNd = aIdx.GetNodes().GoNext( &aIdx );
+ if( pNd )
+ {
+ if( bChk && 1 != aIdx.GetIndex() - pIdx->GetIndex() &&
+ !CheckNodesRange( *pIdx, aIdx, sal_True ) )
+ pNd = 0;
+ else
+ *pIdx = aIdx;
+ }
+ return pNd;
+}
+
+
+SwCntntNode* GoPreviousNds( SwNodeIndex * pIdx, sal_Bool bChk )
+{
+ SwNodeIndex aIdx( *pIdx );
+ SwCntntNode* pNd = aIdx.GetNodes().GoPrevious( &aIdx );
+ if( pNd )
+ {
+ if( bChk && 1 != pIdx->GetIndex() - aIdx.GetIndex() &&
+ !CheckNodesRange( *pIdx, aIdx, sal_True ) )
+ pNd = 0;
+ else
+ *pIdx = aIdx;
+ }
+ return pNd;
+}
+
+// ----------------------------------------------------------------------
+
+/*************************************************************************
+|*
+|* SwPointAndMark
+|*
+|* Beschreibung PAM.DOC
+|*
+*************************************************************************/
+
+SwPaM::SwPaM( const SwPosition& rPos, SwPaM* pRing )
+ : Ring( pRing )
+ , m_Bound1( rPos )
+ , m_Bound2( rPos.nNode.GetNode().GetNodes() ) // default initialize
+ , m_pPoint( &m_Bound1 )
+ , m_pMark( m_pPoint )
+ , m_bIsInFrontOfLabel( false )
+{
+}
+
+SwPaM::SwPaM( const SwPosition& rMark, const SwPosition& rPoint, SwPaM* pRing )
+ : Ring( pRing )
+ , m_Bound1( rMark )
+ , m_Bound2( rPoint )
+ , m_pPoint( &m_Bound2 )
+ , m_pMark( &m_Bound1 )
+ , m_bIsInFrontOfLabel( false )
+{
+}
+
+SwPaM::SwPaM( const SwNodeIndex& rMark, const SwNodeIndex& rPoint,
+ long nMarkOffset, long nPointOffset, SwPaM* pRing )
+ : Ring( pRing )
+ , m_Bound1( rMark )
+ , m_Bound2( rPoint )
+ , m_pPoint( &m_Bound2 )
+ , m_pMark( &m_Bound1 )
+ , m_bIsInFrontOfLabel( false )
+{
+ if ( nMarkOffset )
+ {
+ m_pMark->nNode += nMarkOffset;
+ }
+ if ( nPointOffset )
+ {
+ m_pPoint->nNode += nPointOffset;
+ }
+
+ m_Bound1.nContent.Assign( m_Bound1.nNode.GetNode().GetCntntNode(), 0 );
+ m_Bound2.nContent.Assign( m_Bound2.nNode.GetNode().GetCntntNode(), 0 );
+}
+
+SwPaM::SwPaM( const SwNode& rMark, const SwNode& rPoint,
+ long nMarkOffset, long nPointOffset, SwPaM* pRing )
+ : Ring( pRing )
+ , m_Bound1( rMark )
+ , m_Bound2( rPoint )
+ , m_pPoint( &m_Bound2 )
+ , m_pMark( &m_Bound1 )
+ , m_bIsInFrontOfLabel( false )
+{
+ if ( nMarkOffset )
+ {
+ m_pMark->nNode += nMarkOffset;
+ }
+ if ( nPointOffset )
+ {
+ m_pPoint->nNode += nPointOffset;
+ }
+
+ m_Bound1.nContent.Assign( m_Bound1.nNode.GetNode().GetCntntNode(), 0 );
+ m_Bound2.nContent.Assign( m_Bound2.nNode.GetNode().GetCntntNode(), 0 );
+}
+
+SwPaM::SwPaM( const SwNodeIndex& rMark , xub_StrLen nMarkCntnt,
+ const SwNodeIndex& rPoint, xub_StrLen nPointCntnt, SwPaM* pRing )
+ : Ring( pRing )
+ , m_Bound1( rMark )
+ , m_Bound2( rPoint )
+ , m_pPoint( &m_Bound2 )
+ , m_pMark( &m_Bound1 )
+ , m_bIsInFrontOfLabel( false )
+{
+ m_pPoint->nContent.Assign( rPoint.GetNode().GetCntntNode(), nPointCntnt);
+ m_pMark ->nContent.Assign( rMark .GetNode().GetCntntNode(), nMarkCntnt );
+}
+
+SwPaM::SwPaM( const SwNode& rMark , xub_StrLen nMarkCntnt,
+ const SwNode& rPoint, xub_StrLen nPointCntnt, SwPaM* pRing )
+ : Ring( pRing )
+ , m_Bound1( rMark )
+ , m_Bound2( rPoint )
+ , m_pPoint( &m_Bound2 )
+ , m_pMark( &m_Bound1 )
+ , m_bIsInFrontOfLabel( false )
+{
+ m_pPoint->nContent.Assign( m_pPoint->nNode.GetNode().GetCntntNode(),
+ nPointCntnt);
+ m_pMark ->nContent.Assign( m_pMark ->nNode.GetNode().GetCntntNode(),
+ nMarkCntnt );
+}
+
+SwPaM::SwPaM( const SwNode& rNode, xub_StrLen nCntnt, SwPaM* pRing )
+ : Ring( pRing )
+ , m_Bound1( rNode )
+ , m_Bound2( m_Bound1.nNode.GetNode().GetNodes() ) // default initialize
+ , m_pPoint( &m_Bound1 )
+ , m_pMark( &m_Bound1 )
+ , m_bIsInFrontOfLabel( false )
+{
+ m_pPoint->nContent.Assign( m_pPoint->nNode.GetNode().GetCntntNode(),
+ nCntnt );
+}
+
+SwPaM::SwPaM( const SwNodeIndex& rNodeIdx, xub_StrLen nCntnt, SwPaM* pRing )
+ : Ring( pRing )
+ , m_Bound1( rNodeIdx )
+ , m_Bound2( rNodeIdx.GetNode().GetNodes() ) // default initialize
+ , m_pPoint( &m_Bound1 )
+ , m_pMark( &m_Bound1 )
+ , m_bIsInFrontOfLabel( false )
+{
+ m_pPoint->nContent.Assign( rNodeIdx.GetNode().GetCntntNode(), nCntnt );
+}
+
+SwPaM::~SwPaM() {}
+
+// @@@ semantic: no copy ctor.
+SwPaM::SwPaM( SwPaM &rPam )
+ : Ring( &rPam )
+ , m_Bound1( *(rPam.m_pPoint) )
+ , m_Bound2( *(rPam.m_pMark) )
+ , m_pPoint( &m_Bound1 ), m_pMark( rPam.HasMark() ? &m_Bound2 : m_pPoint )
+ , m_bIsInFrontOfLabel( false )
+{
+}
+
+// @@@ semantic: no copy assignment for super class Ring.
+SwPaM &SwPaM::operator=( const SwPaM &rPam )
+{
+ *m_pPoint = *( rPam.m_pPoint );
+ if ( rPam.HasMark() )
+ {
+ SetMark();
+ *m_pMark = *( rPam.m_pMark );
+ }
+ else
+ {
+ DeleteMark();
+ }
+ return *this;
+}
+
+void SwPaM::SetMark()
+{
+ if (m_pPoint == &m_Bound1)
+ {
+ m_pMark = &m_Bound2;
+ }
+ else
+ {
+ m_pMark = &m_Bound1;
+ }
+ (*m_pMark) = (*m_pPoint);
+}
+
+#if OSL_DEBUG_LEVEL > 1
+
+void SwPaM::Exchange()
+{
+ if (m_pPoint != m_pMark)
+ {
+ SwPosition *pTmp = m_pPoint;
+ m_pPoint = m_pMark;
+ m_pMark = pTmp;
+ }
+}
+#endif
+
+// Bewegen des Cursors
+
+
+sal_Bool SwPaM::Move( SwMoveFn fnMove, SwGoInDoc fnGo )
+{
+ sal_Bool bRet = (*fnGo)( *this, fnMove );
+
+ m_bIsInFrontOfLabel = false;
+
+ return bRet;
+}
+
+
+/*************************************************************************
+|*
+|* void SwPaM::MakeRegion( SwMoveFn, SwPaM*, const SwPaM* )
+|*
+|* Beschreibung Setzt den 1. SwPaM auf den uebergebenen SwPaM
+|* oder setzt auf den Anfang oder Ende vom Document.
+|* SPoint bleibt auf der Position stehen, GetMark aendert
+|* sich entsprechend !
+|*
+|* Parameter SwDirection gibt an, ob an Anfang / Ende
+|* SwPaM * der zu setzende Bereich
+|* const SwPaM& der enventuell vorgegeben Bereich
+|* Return-Werte SwPaM* der entsprehend neu gesetzte Bereich
+|*
+*************************************************************************/
+
+
+SwPaM* SwPaM::MakeRegion( SwMoveFn fnMove, const SwPaM * pOrigRg )
+{
+ SwPaM* pPam;
+ if( pOrigRg == 0 )
+ {
+ pPam = new SwPaM( *m_pPoint );
+ pPam->SetMark(); // setze Anfang fest
+ pPam->Move( fnMove, fnGoSection); // an Anfang / Ende vom Node
+
+ // stelle SPoint wieder auf alte Position, GetMark auf das "Ende"
+ pPam->Exchange();
+ }
+ else
+ {
+ pPam = new SwPaM( *(SwPaM*)pOrigRg ); // die Suchregion ist vorgegeben
+ // sorge dafuer, dass SPoint auf dem "echten" StartPunkt steht
+ // FORWARD --> SPoint immer kleiner als GetMark
+ // BACKWARD --> SPoint immer groesser als GetMark
+ if( (pPam->GetMark()->*fnMove->fnCmpOp)( *pPam->GetPoint() ) )
+ pPam->Exchange();
+ }
+ return pPam;
+}
+
+SwPaM & SwPaM::Normalize(sal_Bool bPointFirst)
+{
+ if (HasMark())
+ if ( ( bPointFirst && *m_pPoint > *m_pMark) ||
+ (!bPointFirst && *m_pPoint < *m_pMark) )
+ {
+ Exchange();
+ }
+
+ return *this;
+}
+
+sal_uInt16 SwPaM::GetPageNum( sal_Bool bAtPoint, const Point* pLayPos )
+{
+ // return die Seitennummer am Cursor
+ // (fuer Reader + Seitengebundene Rahmen)
+ const SwCntntFrm* pCFrm;
+ const SwPageFrm *pPg;
+ const SwCntntNode *pNd ;
+ const SwPosition* pPos = bAtPoint ? m_pPoint : m_pMark;
+
+ if( 0 != ( pNd = pPos->nNode.GetNode().GetCntntNode() ) &&
+ 0 != ( pCFrm = pNd->getLayoutFrm( pNd->GetDoc()->GetCurrentLayout(), pLayPos, pPos, sal_False )) &&
+ 0 != ( pPg = pCFrm->FindPageFrm() ))
+ return pPg->GetPhyPageNum();
+ return 0;
+}
+
+// Formular view - See also SwCrsrShell::IsCrsrReadonly()
+const SwFrm* lcl_FindEditInReadonlyFrm( const SwFrm& rFrm )
+{
+ const SwFrm* pRet = 0;
+
+ const SwFlyFrm* pFly;
+ const SwSectionFrm* pSectionFrm;
+
+ if( rFrm.IsInFly() &&
+ (pFly = rFrm.FindFlyFrm())->GetFmt()->GetEditInReadonly().GetValue() &&
+ pFly->Lower() &&
+ !pFly->Lower()->IsNoTxtFrm() )
+ {
+ pRet = pFly;
+ }
+ else if ( rFrm.IsInSct() &&
+ 0 != ( pSectionFrm = rFrm.FindSctFrm() )->GetSection() &&
+ pSectionFrm->GetSection()->IsEditInReadonlyFlag() )
+ {
+ pRet = pSectionFrm;
+ }
+
+ return pRet;
+}
+
+// steht in etwas geschuetztem oder in die Selektion umspannt
+// etwas geschuetztes.
+sal_Bool SwPaM::HasReadonlySel( bool bFormView ) const
+{
+ sal_Bool bRet = sal_False;
+ Point aTmpPt;
+ const SwCntntNode *pNd;
+ const SwCntntFrm *pFrm;
+
+ if( 0 != ( pNd = GetPoint()->nNode.GetNode().GetCntntNode() ))
+ pFrm = pNd->getLayoutFrm( pNd->GetDoc()->GetCurrentLayout(), &aTmpPt, GetPoint(), sal_False );
+ else
+ pFrm = 0;
+
+ // Will be set if point/mark are inside edit-in-readonly environment
+ const SwFrm* pSttEIRFrm = 0;
+ const SwFrm* pEndEIRFrm = 0;
+
+ if( pFrm && ( pFrm->IsProtected() ||
+ ( bFormView && 0 == ( pSttEIRFrm = lcl_FindEditInReadonlyFrm( *pFrm ) ) ) ) )
+ bRet = sal_True;
+ else if( pNd )
+ {
+ const SwSectionNode* pSNd = pNd->GetSectionNode();
+ if( pSNd && ( pSNd->GetSection().IsProtectFlag() ||
+ (bFormView && !pSNd->GetSection().IsEditInReadonlyFlag()) ) )
+ bRet = sal_True;
+ }
+
+ if( !bRet && HasMark() && GetPoint()->nNode != GetMark()->nNode )
+ {
+ if( 0 != ( pNd = GetMark()->nNode.GetNode().GetCntntNode() ))
+ pFrm = pNd->getLayoutFrm( pNd->GetDoc()->GetCurrentLayout(), &aTmpPt, GetMark(), sal_False );
+ else
+ pFrm = 0;
+
+ if( pFrm && ( pFrm->IsProtected() ||
+ ( bFormView && 0 == ( pEndEIRFrm = lcl_FindEditInReadonlyFrm( *pFrm ) ) ) ) )
+ bRet = sal_True;
+ else if( pNd )
+ {
+ const SwSectionNode* pSNd = pNd->GetSectionNode();
+ if( pSNd && ( pSNd->GetSection().IsProtectFlag() ||
+ (bFormView && !pSNd->GetSection().IsEditInReadonlyFlag()) ) )
+ bRet = sal_True;
+ }
+
+ if ( !bRet && bFormView )
+ {
+ // Check if start and end frame are inside the _same_
+ // edit-in-readonly-environment. Otherwise we better return 'true'
+ if ( pSttEIRFrm != pEndEIRFrm )
+ bRet = sal_True;
+ }
+
+ // oder sollte eine geschuetzte Section innerhalb der
+ // Selektion liegen?
+ if( !bRet )
+ {
+ sal_uLong nSttIdx = GetMark()->nNode.GetIndex(),
+ nEndIdx = GetPoint()->nNode.GetIndex();
+ if( nEndIdx <= nSttIdx )
+ {
+ sal_uLong nTmp = nSttIdx;
+ nSttIdx = nEndIdx;
+ nEndIdx = nTmp;
+ }
+
+ // wenn ein geschuetzter Bereich zwischen den Nodes stehen soll,
+ // muss die Selektion selbst schon x Nodes umfassen.
+ // (TxtNd, SectNd, TxtNd, EndNd, TxtNd )
+ if( nSttIdx + 3 < nEndIdx )
+ {
+ const SwSectionFmts& rFmts = GetDoc()->GetSections();
+ for( sal_uInt16 n = rFmts.Count(); n; )
+ {
+ const SwSectionFmt* pFmt = rFmts[ --n ];
+ if( pFmt->GetProtect().IsCntntProtected() )
+ {
+ const SwFmtCntnt& rCntnt = pFmt->GetCntnt(sal_False);
+ OSL_ENSURE( rCntnt.GetCntntIdx(), "wo ist der SectionNode?" );
+ sal_uLong nIdx = rCntnt.GetCntntIdx()->GetIndex();
+ if( nSttIdx <= nIdx && nEndIdx >= nIdx &&
+ rCntnt.GetCntntIdx()->GetNode().GetNodes().IsDocNodes() )
+ {
+/* // ist es keine gelinkte Section, dann kann sie auch
+ // nicht mitselektiert werden
+ const SwSection& rSect = *pFmt->GetSection();
+ if( CONTENT_SECTION == rSect.GetType() )
+ {
+ RestoreSavePos();
+ return sal_True;
+ }
+*/
+ bRet = sal_True;
+ break;
+ }
+ }
+ }
+ }
+ }
+ }
+ //FIXME FieldBk
+ // TODO: Form Protection when Enhanced Fields are enabled
+ const SwDoc *pDoc = GetDoc();
+ sw::mark::IMark* pA = NULL;
+ sw::mark::IMark* pB = NULL;
+ bool bUnhandledMark = false;
+ if ( pDoc )
+ {
+ const IDocumentMarkAccess* pMarksAccess = pDoc->getIDocumentMarkAccess( );
+ pA = GetPoint() ? pMarksAccess->getFieldmarkFor( *GetPoint( ) ) : NULL;
+ pB = GetMark( ) ? pMarksAccess->getFieldmarkFor( *GetMark( ) ) : pA;
+
+ sw::mark::IFieldmark* pFieldmark = pMarksAccess->getFieldmarkFor( *GetPoint() );
+ if ( pFieldmark )
+ bUnhandledMark = pFieldmark->GetFieldname( ).equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( ODF_UNHANDLED ) );
+ }
+
+ if (!bRet)
+ {
+ // Unhandled fieldmarks case shouldn't be edited manually to avoid breaking anything
+ if ( ( pA == pB ) && bUnhandledMark )
+ bRet = sal_True;
+ else
+ {
+ // Form protection case
+ bool bAtStartA = pA != NULL && pA->GetMarkStart() == *GetPoint();
+ bool bAtStartB = pB != NULL && pB->GetMarkStart() == *GetMark();
+ bRet = ( pA != pB ) || bAtStartA || bAtStartB;
+ bool bProtectForm = pDoc->get( IDocumentSettingAccess::PROTECT_FORM );
+ if ( bProtectForm )
+ bRet |= ( pA == NULL || pB == NULL );
+ }
+ }
+ else
+ {
+ bRet = !( pA == pB && pA != NULL );
+ }
+ return bRet;
+}
+
+//-------------------- Suche nach Formaten( FormatNamen ) -----------------
+
+// die Funktion gibt in Suchrichtung den folgenden Node zurueck.
+// Ist in der Richtung keiner mehr vorhanden oder ist dieser ausserhalb
+// des Bereiches, wird ein 0 Pointer returnt.
+// Das rbFirst gibt an, ob es man zu erstenmal einen Node holt. Ist das der
+// Fall, darf die Position vom Pam nicht veraendert werden!
+
+
+SwCntntNode* GetNode( SwPaM & rPam, sal_Bool& rbFirst, SwMoveFn fnMove,
+ sal_Bool bInReadOnly )
+{
+ SwCntntNode * pNd = 0;
+ SwCntntFrm* pFrm;
+ if( ((*rPam.GetPoint()).*fnMove->fnCmpOp)( *rPam.GetMark() ) ||
+ ( *rPam.GetPoint() == *rPam.GetMark() && rbFirst ) )
+ {
+ if( rbFirst )
+ {
+ rbFirst = sal_False;
+ pNd = rPam.GetCntntNode();
+ if( pNd )
+ {
+ if(
+ (
+ 0 == ( pFrm = pNd->getLayoutFrm( pNd->GetDoc()->GetCurrentLayout() ) ) ||
+ ( !bInReadOnly && pFrm->IsProtected() ) ||
+ (pFrm->IsTxtFrm() && ((SwTxtFrm*)pFrm)->IsHiddenNow())
+ ) ||
+ ( !bInReadOnly && pNd->FindSectionNode() &&
+ pNd->FindSectionNode()->GetSection().IsProtect()
+ )
+ )
+ {
+ pNd = 0;
+ }
+ }
+ }
+
+ if( !pNd ) // steht Cursor auf keinem ContentNode ?
+ {
+ SwPosition aPos( *rPam.GetPoint() );
+ sal_Bool bSrchForward = fnMove == fnMoveForward;
+ SwNodes& rNodes = aPos.nNode.GetNodes();
+
+ // zum naechsten / vorherigen ContentNode
+// Funktioniert noch alles, wenn die Uerbpruefung vom ueberspringen der
+// Sektions herausgenommen wird ??
+// if( (*fnMove->fnNds)( rNodes, &aPos.nNode ) )
+ while( sal_True )
+ {
+ pNd = bSrchForward
+ ? rNodes.GoNextSection( &aPos.nNode, sal_True, !bInReadOnly )
+ : rNodes.GoPrevSection( &aPos.nNode, sal_True, !bInReadOnly );
+ if( pNd )
+ {
+ aPos.nContent.Assign( pNd, ::GetSttOrEnd( bSrchForward,*pNd ));
+ // liegt Position immer noch im Bereich ?
+ if( (aPos.*fnMove->fnCmpOp)( *rPam.GetMark() ) )
+ {
+ // nur in der AutoTextSection koennen Node stehen, die
+ // nicht angezeigt werden !!
+ if( 0 == ( pFrm = pNd->getLayoutFrm( pNd->GetDoc()->GetCurrentLayout() ) ) ||
+ ( !bInReadOnly && pFrm->IsProtected() ) ||
+ ( pFrm->IsTxtFrm() &&
+ ((SwTxtFrm*)pFrm)->IsHiddenNow() ) )
+ {
+ pNd = 0;
+ continue; // suche weiter
+ }
+ *(SwPosition*)rPam.GetPoint() = aPos;
+ }
+ else
+ pNd = 0; // kein gueltiger Node
+ break;
+ }
+ break;
+ }
+ }
+ }
+ return pNd;
+}
+
+// ----------------------------------------------------------------------
+
+// hier folgen die Move-Methoden ( Foward, Backward; Content, Node, Doc )
+
+
+void GoStartDoc( SwPosition * pPos )
+{
+ SwNodes& rNodes = pPos->nNode.GetNodes();
+ pPos->nNode = *rNodes.GetEndOfContent().StartOfSectionNode();
+ // es muss immer ein ContentNode gefunden werden !!
+ SwCntntNode* pCNd = rNodes.GoNext( &pPos->nNode );
+ if( pCNd )
+ pCNd->MakeStartIndex( &pPos->nContent );
+}
+
+
+void GoEndDoc( SwPosition * pPos )
+{
+ SwNodes& rNodes = pPos->nNode.GetNodes();
+ pPos->nNode = rNodes.GetEndOfContent();
+ SwCntntNode* pCNd = GoPreviousNds( &pPos->nNode, sal_True );
+ if( pCNd )
+ pCNd->MakeEndIndex( &pPos->nContent );
+}
+
+
+void GoStartSection( SwPosition * pPos )
+{
+ // springe zum Anfang der Section
+ SwNodes& rNodes = pPos->nNode.GetNodes();
+ sal_uInt16 nLevel = rNodes.GetSectionLevel( pPos->nNode );
+ if( pPos->nNode < rNodes.GetEndOfContent().StartOfSectionIndex() )
+ nLevel--;
+ do { rNodes.GoStartOfSection( &pPos->nNode ); } while( nLevel-- );
+
+ // steht jetzt schon auf einem CntntNode
+ pPos->nNode.GetNode().GetCntntNode()->MakeStartIndex( &pPos->nContent );
+}
+
+// gehe an das Ende der akt. Grund-Section
+
+
+void GoEndSection( SwPosition * pPos )
+{
+ // springe zum Anfang/Ende der Section
+ SwNodes& rNodes = pPos->nNode.GetNodes();
+ sal_uInt16 nLevel = rNodes.GetSectionLevel( pPos->nNode );
+ if( pPos->nNode < rNodes.GetEndOfContent().StartOfSectionIndex() )
+ nLevel--;
+ do { rNodes.GoEndOfSection( &pPos->nNode ); } while( nLevel-- );
+
+ // steht jetzt auf einem EndNode, also zum vorherigen CntntNode
+ if( GoPreviousNds( &pPos->nNode, sal_True ) )
+ pPos->nNode.GetNode().GetCntntNode()->MakeEndIndex( &pPos->nContent );
+}
+
+
+
+sal_Bool GoInDoc( SwPaM & rPam, SwMoveFn fnMove )
+{
+ (*fnMove->fnDoc)( rPam.GetPoint() );
+ return sal_True;
+}
+
+
+sal_Bool GoInSection( SwPaM & rPam, SwMoveFn fnMove )
+{
+ (*fnMove->fnSections)( (SwPosition*)rPam.GetPoint() );
+ return sal_True;
+}
+
+
+sal_Bool GoInNode( SwPaM & rPam, SwMoveFn fnMove )
+{
+ SwCntntNode *pNd = (*fnMove->fnNds)( &rPam.GetPoint()->nNode, sal_True );
+ if( pNd )
+ rPam.GetPoint()->nContent.Assign( pNd,
+ ::GetSttOrEnd( fnMove == fnMoveForward, *pNd ) );
+ return 0 != pNd;
+}
+
+
+sal_Bool GoInCntnt( SwPaM & rPam, SwMoveFn fnMove )
+{
+ if( (*fnMove->fnNd)( &rPam.GetPoint()->nNode.GetNode(),
+ &rPam.GetPoint()->nContent, CRSR_SKIP_CHARS ))
+ return sal_True;
+ return GoInNode( rPam, fnMove );
+}
+
+sal_Bool GoInCntntCells( SwPaM & rPam, SwMoveFn fnMove )
+{
+ if( (*fnMove->fnNd)( &rPam.GetPoint()->nNode.GetNode(),
+ &rPam.GetPoint()->nContent, CRSR_SKIP_CELLS ))
+ return sal_True;
+ return GoInNode( rPam, fnMove );
+}
+
+sal_Bool GoInCntntSkipHidden( SwPaM & rPam, SwMoveFn fnMove )
+{
+ if( (*fnMove->fnNd)( &rPam.GetPoint()->nNode.GetNode(),
+ &rPam.GetPoint()->nContent, CRSR_SKIP_CHARS | CRSR_SKIP_HIDDEN ) )
+ return sal_True;
+ return GoInNode( rPam, fnMove );
+}
+
+sal_Bool GoInCntntCellsSkipHidden( SwPaM & rPam, SwMoveFn fnMove )
+{
+ if( (*fnMove->fnNd)( &rPam.GetPoint()->nNode.GetNode(),
+ &rPam.GetPoint()->nContent, CRSR_SKIP_CELLS | CRSR_SKIP_HIDDEN ) )
+ return sal_True;
+ return GoInNode( rPam, fnMove );
+}
+
+
+
+// --------- Funktionsdefinitionen fuer die SwCrsrShell --------------
+
+
+sal_Bool GoPrevPara( SwPaM & rPam, SwPosPara aPosPara )
+{
+ if( rPam.Move( fnMoveBackward, fnGoNode ) )
+ {
+ // steht immer auf einem ContentNode !
+ SwPosition& rPos = *rPam.GetPoint();
+ SwCntntNode * pNd = rPos.nNode.GetNode().GetCntntNode();
+ rPos.nContent.Assign( pNd,
+ ::GetSttOrEnd( aPosPara == fnMoveForward, *pNd ) );
+ return sal_True;
+ }
+ return sal_False;
+}
+
+
+sal_Bool GoCurrPara( SwPaM & rPam, SwPosPara aPosPara )
+{
+ SwPosition& rPos = *rPam.GetPoint();
+ SwCntntNode * pNd = rPos.nNode.GetNode().GetCntntNode();
+ if( pNd )
+ {
+ xub_StrLen nOld = rPos.nContent.GetIndex(),
+ nNew = aPosPara == fnMoveForward ? 0 : pNd->Len();
+ // stand er schon auf dem Anfang/Ende dann zum naechsten/vorherigen
+ if( nOld != nNew )
+ {
+ rPos.nContent.Assign( pNd, nNew );
+ return sal_True;
+ }
+ }
+ // den Node noch etwas bewegen ( auf den naechsten/vorh. CntntNode)
+ if( ( aPosPara==fnParaStart && 0 != ( pNd =
+ GoPreviousNds( &rPos.nNode, sal_True ))) ||
+ ( aPosPara==fnParaEnd && 0 != ( pNd =
+ GoNextNds( &rPos.nNode, sal_True ))) )
+ {
+ rPos.nContent.Assign( pNd,
+ ::GetSttOrEnd( aPosPara == fnMoveForward, *pNd ));
+ return sal_True;
+ }
+ return sal_False;
+}
+
+
+sal_Bool GoNextPara( SwPaM & rPam, SwPosPara aPosPara )
+{
+ if( rPam.Move( fnMoveForward, fnGoNode ) )
+ {
+ // steht immer auf einem ContentNode !
+ SwPosition& rPos = *rPam.GetPoint();
+ SwCntntNode * pNd = rPos.nNode.GetNode().GetCntntNode();
+ rPos.nContent.Assign( pNd,
+ ::GetSttOrEnd( aPosPara == fnMoveForward, *pNd ) );
+ return sal_True;
+ }
+ return sal_False;
+}
+
+
+
+sal_Bool GoCurrSection( SwPaM & rPam, SwMoveFn fnMove )
+{
+ SwPosition& rPos = *rPam.GetPoint();
+ SwPosition aSavePos( rPos ); // eine Vergleichsposition
+ SwNodes& rNds = aSavePos.nNode.GetNodes();
+ (rNds.*fnMove->fnSection)( &rPos.nNode );
+ SwCntntNode *pNd;
+ if( 0 == ( pNd = rPos.nNode.GetNode().GetCntntNode()) &&
+ 0 == ( pNd = (*fnMove->fnNds)( &rPos.nNode, sal_True )) )
+ {
+ rPos = aSavePos; // Cusror nicht veraendern
+ return sal_False;
+ }
+
+ rPos.nContent.Assign( pNd,
+ ::GetSttOrEnd( fnMove == fnMoveForward, *pNd ) );
+ return aSavePos != rPos;
+}
+
+
+sal_Bool GoNextSection( SwPaM & rPam, SwMoveFn fnMove )
+{
+ SwPosition& rPos = *rPam.GetPoint();
+ SwPosition aSavePos( rPos ); // eine Vergleichsposition
+ SwNodes& rNds = aSavePos.nNode.GetNodes();
+ rNds.GoEndOfSection( &rPos.nNode );
+
+ // kein weiterer ContentNode vorhanden ?
+ if( !GoInCntnt( rPam, fnMoveForward ) )
+ {
+ rPos = aSavePos; // Cusror nicht veraendern
+ return sal_False;
+ }
+ (rNds.*fnMove->fnSection)( &rPos.nNode );
+ SwCntntNode *pNd = rPos.nNode.GetNode().GetCntntNode();
+ rPos.nContent.Assign( pNd,
+ ::GetSttOrEnd( fnMove == fnMoveForward, *pNd ) );
+ return sal_True;
+}
+
+
+sal_Bool GoPrevSection( SwPaM & rPam, SwMoveFn fnMove )
+{
+ SwPosition& rPos = *rPam.GetPoint();
+ SwPosition aSavePos( rPos ); // eine Vergleichsposition
+ SwNodes& rNds = aSavePos.nNode.GetNodes();
+ rNds.GoStartOfSection( &rPos.nNode );
+
+ // kein weiterer ContentNode vorhanden ?
+ if( !GoInCntnt( rPam, fnMoveBackward ))
+ {
+ rPos = aSavePos; // Cusror nicht veraendern
+ return sal_False;
+ }
+ (rNds.*fnMove->fnSection)( &rPos.nNode );
+ SwCntntNode *pNd = rPos.nNode.GetNode().GetCntntNode();
+ rPos.nContent.Assign( pNd,
+ ::GetSttOrEnd( fnMove == fnMoveForward, *pNd ));
+ return sal_True;
+}
+
+String SwPaM::GetTxt() const
+{
+ String aResult;
+
+ SwNodeIndex aNodeIndex = Start()->nNode;
+
+ /* The first node can be the end node. A first end node must be
+ handled, too. There fore do ... while and no incrementing of
+ aNodeIndex in the first pass.
+ */
+ bool bFirst = true;
+ do
+ {
+ if (! bFirst)
+ {
+ aNodeIndex++;
+ }
+
+ bFirst = false;
+
+ SwTxtNode * pTxtNode = aNodeIndex.GetNode().GetTxtNode();
+
+ if (pTxtNode != NULL)
+ {
+ const String & aTmpStr = pTxtNode->GetTxt();
+
+ if (aNodeIndex == Start()->nNode)
+ {
+ xub_StrLen nEnd;
+ if (End()->nNode == aNodeIndex)
+ nEnd = End()->nContent.GetIndex();
+ else
+ nEnd = aTmpStr.Len();
+
+ aResult += aTmpStr.Copy(Start()->nContent.GetIndex(),
+ nEnd - Start()->nContent.GetIndex()) ;
+ }
+ else if (aNodeIndex == End()->nNode)
+ aResult += aTmpStr.Copy(0, End()->nContent.GetIndex());
+ else
+ aResult += aTmpStr;
+ }
+ }
+ while (aNodeIndex != End()->nNode);
+
+ return aResult;
+}
+
+sal_Bool SwPaM::Overlap(const SwPaM & a, const SwPaM & b)
+{
+ return !(*b.End() <= *a.Start() || *a.End() <= *b.End());
+}
+
+void SwPaM::InvalidatePaM()
+{
+ const SwNode *_pNd=this->GetNode();
+ const SwTxtNode *_pTxtNd=(_pNd!=NULL?_pNd->GetTxtNode():NULL);
+ if (_pTxtNd!=NULL)
+ {
+ // pretent that the PaM marks inserted text to recalc the portion...
+ SwInsTxt aHint( Start()->nContent.GetIndex(),
+ End()->nContent.GetIndex() - Start()->nContent.GetIndex() + 1 );
+ SwModify *_pModify=(SwModify*)_pTxtNd;
+ _pModify->ModifyNotification( 0, &aHint);
+ }
+}
+
+sal_Bool SwPaM::LessThan(const SwPaM & a, const SwPaM & b)
+{
+ return (*a.Start() < *b.Start()) || (*a.Start() == *b.Start() && *a.End() < *b.End());
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/crsr/paminit.cxx b/sw/source/core/crsr/paminit.cxx
new file mode 100644
index 000000000000..726c7fbbe8ac
--- /dev/null
+++ b/sw/source/core/crsr/paminit.cxx
@@ -0,0 +1,134 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+
+#include <pamtyp.hxx>
+
+
+static SwMoveFnCollection aFwrd = {
+ /* fnNd */ &GoNext,
+ /* fnNds */ &GoNextNds,
+ /* fnDoc */ &GoEndDoc,
+ /* fnSections */ &GoEndSection,
+ /* fnCmpOp */ &SwPosition::operator<,
+ /* fnGetHint */ &GetFrwrdTxtHint,
+ /* fnSearch */ &utl::TextSearch::SearchFrwrd,
+ /* fnSection */ &SwNodes::GoStartOfSection
+};
+
+static SwMoveFnCollection aBwrd = {
+ /* fnNd */ &GoPrevious,
+ /* fnNds */ &GoPreviousNds,
+ /* fnDoc */ &GoStartDoc,
+ /* fnSections */ &GoStartSection,
+ /* fnCmpOp */ &SwPosition::operator>,
+ /* fnGetHint */ &GetBkwrdTxtHint,
+ /* fnSearch */ &utl::TextSearch::SearchBkwrd,
+ /* fnSection */ &SwNodes::GoEndOfSection
+};
+
+SwGoInDoc fnGoDoc = &GoInDoc;
+SwGoInDoc fnGoSection = &GoInSection;
+SwGoInDoc fnGoNode = &GoInNode;
+SwGoInDoc fnGoCntnt = &GoInCntnt;
+SwGoInDoc fnGoCntntCells = &GoInCntntCells;
+SwGoInDoc fnGoCntntSkipHidden = &GoInCntntSkipHidden;
+SwGoInDoc fnGoCntntCellsSkipHidden = &GoInCntntCellsSkipHidden;
+
+SwWhichPara fnParaPrev = &GoPrevPara;
+SwWhichPara fnParaCurr = &GoCurrPara;
+SwWhichPara fnParaNext = &GoNextPara;
+SwPosPara fnParaStart = &aFwrd;
+SwPosPara fnParaEnd = &aBwrd;
+
+SwWhichSection fnSectionPrev = &GoPrevSection;
+SwWhichSection fnSectionCurr = &GoCurrSection;
+SwWhichSection fnSectionNext = &GoNextSection;
+SwPosSection fnSectionStart = &aFwrd;
+SwPosSection fnSectionEnd = &aBwrd;
+
+// Travelling in Tabellen
+sal_Bool GotoPrevTable( SwPaM&, SwPosTable, sal_Bool bInReadOnly );
+sal_Bool GotoCurrTable( SwPaM&, SwPosTable, sal_Bool bInReadOnly );
+sal_Bool GotoNextTable( SwPaM&, SwPosTable, sal_Bool bInReadOnly );
+
+SwWhichTable fnTablePrev = &GotoPrevTable;
+SwWhichTable fnTableCurr = &GotoCurrTable;
+SwWhichTable fnTableNext = &GotoNextTable;
+SwPosTable fnTableStart = &aFwrd;
+SwPosTable fnTableEnd = &aBwrd;
+
+// Travelling in Bereichen
+sal_Bool GotoPrevRegion( SwPaM&, SwPosRegion, sal_Bool bInReadOnly );
+sal_Bool GotoCurrRegion( SwPaM&, SwPosRegion, sal_Bool bInReadOnly );
+sal_Bool GotoCurrRegionAndSkip( SwPaM&, SwPosRegion, sal_Bool bInReadOnly );
+sal_Bool GotoNextRegion( SwPaM&, SwPosRegion, sal_Bool bInReadOnly );
+
+SwWhichRegion fnRegionPrev = &GotoPrevRegion;
+SwWhichRegion fnRegionCurr = &GotoCurrRegion;
+SwWhichRegion fnRegionCurrAndSkip = &GotoCurrRegionAndSkip;
+SwWhichRegion fnRegionNext = &GotoNextRegion;
+SwPosRegion fnRegionStart = &aFwrd;
+SwPosRegion fnRegionEnd = &aBwrd;
+
+SwMoveFn fnMoveBackward = &aBwrd;
+SwMoveFn fnMoveForward = &aFwrd;
+
+SwWhichPara GetfnParaCurr()
+{
+ return fnParaCurr;
+}
+SwPosPara GetfnParaStart()
+{
+ return fnParaStart;
+}
+SwWhichTable GetfnTablePrev()
+{
+ return fnTablePrev;
+}
+SwPosPara GetfnParaEnd()
+{
+ return fnParaEnd;
+}
+SwPosTable GetfnTableStart()
+{
+ return fnTableStart;
+}
+SwWhichTable GetfnTableCurr()
+{
+ return fnTableCurr;
+}
+SwPosTable GetfnTableEnd()
+{
+ return fnTableEnd;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/crsr/swcrsr.cxx b/sw/source/core/crsr/swcrsr.cxx
new file mode 100644
index 000000000000..9d26aaac80c9
--- /dev/null
+++ b/sw/source/core/crsr/swcrsr.cxx
@@ -0,0 +1,2360 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+
+#include <hintids.hxx>
+#include <editeng/protitem.hxx>
+#include <com/sun/star/i18n/WordType.hdl>
+#include <com/sun/star/i18n/CharType.hdl>
+#include <unotools/charclass.hxx>
+#include <svl/ctloptions.hxx>
+#include <swmodule.hxx>
+#include <fmtcntnt.hxx>
+#include <swtblfmt.hxx>
+#include <swcrsr.hxx>
+#include <unocrsr.hxx>
+#include <doc.hxx>
+#include <IDocumentUndoRedo.hxx>
+#include <docary.hxx>
+#include <ndtxt.hxx>
+#include <section.hxx>
+#include <swtable.hxx>
+#include <cntfrm.hxx>
+#include <rootfrm.hxx>
+#include <txtfrm.hxx>
+#include <scriptinfo.hxx>
+#include <crstate.hxx>
+#include <docsh.hxx>
+#include <viewsh.hxx>
+#include <frmatr.hxx>
+#include <breakit.hxx>
+#include <crsskip.hxx>
+#include <vcl/msgbox.hxx>
+#include <mdiexp.hxx> // ...Percent()
+#include <statstr.hrc> // ResId fuer Statusleiste
+#include <redline.hxx> // SwRedline
+
+
+using namespace ::com::sun::star::i18n;
+
+
+static const sal_uInt16 coSrchRplcThreshold = 60000;
+
+struct _PercentHdl
+{
+ SwDocShell* pDSh;
+ sal_uLong nActPos;
+ sal_Bool bBack, bNodeIdx;
+
+ _PercentHdl( sal_uLong nStt, sal_uLong nEnd, SwDocShell* pSh )
+ : pDSh( pSh )
+ {
+ nActPos = nStt;
+ if( 0 != ( bBack = (nStt > nEnd )) )
+ {
+ sal_uLong n = nStt; nStt = nEnd; nEnd = n;
+ }
+ ::StartProgress( STR_STATSTR_SEARCH, nStt, nEnd, 0 );
+ }
+
+ _PercentHdl( const SwPaM& rPam )
+ : pDSh( (SwDocShell*)rPam.GetDoc()->GetDocShell() )
+ {
+ sal_uLong nStt, nEnd;
+ if( rPam.GetPoint()->nNode == rPam.GetMark()->nNode )
+ {
+ bNodeIdx = sal_False;
+ nStt = rPam.GetMark()->nContent.GetIndex();
+ nEnd = rPam.GetPoint()->nContent.GetIndex();
+ }
+ else
+ {
+ bNodeIdx = sal_True;
+ nStt = rPam.GetMark()->nNode.GetIndex();
+ nEnd = rPam.GetPoint()->nNode.GetIndex();
+ }
+ nActPos = nStt;
+ if( 0 != ( bBack = (nStt > nEnd )) )
+ {
+ sal_uLong n = nStt; nStt = nEnd; nEnd = n;
+ }
+ ::StartProgress( STR_STATSTR_SEARCH, nStt, nEnd, pDSh );
+ }
+
+ ~_PercentHdl() { ::EndProgress( pDSh ); }
+
+ void NextPos( sal_uLong nPos ) const
+ { ::SetProgressState( bBack ? nActPos - nPos : nPos, pDSh ); }
+
+ void NextPos( SwPosition& rPos ) const
+ {
+ sal_uLong nPos;
+ if( bNodeIdx )
+ nPos = rPos.nNode.GetIndex();
+ else
+ nPos = rPos.nContent.GetIndex();
+ ::SetProgressState( bBack ? nActPos - nPos : nPos, pDSh );
+ }
+};
+
+SwCursor::SwCursor( const SwPosition &rPos, SwPaM* pRing, bool bColumnSel )
+ : SwPaM( rPos, pRing ), pSavePos( 0 ), mnRowSpanOffset( 0 ), nCursorBidiLevel( 0 ),
+ mbColumnSelection( bColumnSel )
+{
+}
+
+// @@@ semantic: no copy ctor.
+SwCursor::SwCursor( SwCursor& rCpy )
+ : SwPaM( rCpy ), pSavePos( 0 ), mnRowSpanOffset( rCpy.mnRowSpanOffset ),
+ nCursorBidiLevel( rCpy.nCursorBidiLevel ), mbColumnSelection( rCpy.mbColumnSelection )
+{
+}
+
+SwCursor::~SwCursor()
+{
+ while( pSavePos )
+ {
+ _SwCursor_SavePos* pNxt = pSavePos->pNext;
+ delete pSavePos;
+ pSavePos = pNxt;
+ }
+}
+
+SwCursor* SwCursor::Create( SwPaM* pRing ) const
+{
+ return new SwCursor( *GetPoint(), pRing, false );
+}
+
+bool SwCursor::IsReadOnlyAvailable() const
+{
+ return false;
+}
+
+sal_Bool SwCursor::IsSkipOverHiddenSections() const
+{
+ return sal_True;
+}
+
+sal_Bool SwCursor::IsSkipOverProtectSections() const
+{
+ return !IsReadOnlyAvailable();
+}
+
+
+// Das CreateNewSavePos ist virtual, damit abgeleitete Klassen vom Cursor
+// gegebenenfalls eigene SaveObjecte anlegen und in den virtuellen
+// Check-Routinen verwenden koennen.
+void SwCursor::SaveState()
+{
+ _SwCursor_SavePos* pNew = CreateNewSavePos();
+ pNew->pNext = pSavePos;
+ pSavePos = pNew;
+}
+
+void SwCursor::RestoreState()
+{
+ if( pSavePos ) // Robust
+ {
+ _SwCursor_SavePos* pDel = pSavePos;
+ pSavePos = pSavePos->pNext;
+ delete pDel;
+ }
+}
+
+_SwCursor_SavePos* SwCursor::CreateNewSavePos() const
+{
+ return new _SwCursor_SavePos( *this );
+}
+
+// stelle fest, ob sich der Point ausserhalb des Content-Bereichs
+// vom Nodes-Array befindet
+sal_Bool SwCursor::IsNoCntnt() const
+{
+ return GetPoint()->nNode.GetIndex() <
+ GetDoc()->GetNodes().GetEndOfExtras().GetIndex();
+}
+
+bool SwCursor::IsSelOvrCheck(int)
+{
+ return false;
+}
+
+// extracted from IsSelOvr()
+bool SwTableCursor::IsSelOvrCheck(int eFlags)
+{
+ SwNodes& rNds = GetDoc()->GetNodes();
+ // check sections of nodes array
+ if( (nsSwCursorSelOverFlags::SELOVER_CHECKNODESSECTION & eFlags)
+ && HasMark() )
+ {
+ SwNodeIndex aOldPos( rNds, GetSavePos()->nNode );
+ if( !CheckNodesRange( aOldPos, GetPoint()->nNode, sal_True ))
+ {
+ GetPoint()->nNode = aOldPos;
+ GetPoint()->nContent.Assign( GetCntntNode(), GetSavePos()->nCntnt );
+ return true;
+ }
+ }
+ return SwCursor::IsSelOvrCheck(eFlags);
+}
+
+sal_Bool SwCursor::IsSelOvr( int eFlags )
+{
+ SwDoc* pDoc = GetDoc();
+ SwNodes& rNds = pDoc->GetNodes();
+
+ sal_Bool bSkipOverHiddenSections = IsSkipOverHiddenSections();
+ sal_Bool bSkipOverProtectSections = IsSkipOverProtectSections();
+
+ if ( IsSelOvrCheck( eFlags ) )
+ {
+ return sal_True;
+ }
+
+// neu: Bereiche ueberpruefen
+// Anfang
+ if( pSavePos->nNode != GetPoint()->nNode.GetIndex() &&
+ //JP 28.10.97: Bug 45129 - im UI-ReadOnly ist alles erlaubt
+ ( !pDoc->GetDocShell() || !pDoc->GetDocShell()->IsReadOnlyUI() ))
+ {
+ // teste doch mal die neuen Sections:
+ SwNodeIndex& rPtIdx = GetPoint()->nNode;
+ const SwSectionNode* pSectNd = rPtIdx.GetNode().FindSectionNode();
+ if( pSectNd &&
+ ((bSkipOverHiddenSections && pSectNd->GetSection().IsHiddenFlag() ) ||
+ (bSkipOverProtectSections && pSectNd->GetSection().IsProtectFlag() )))
+ {
+ if( 0 == ( nsSwCursorSelOverFlags::SELOVER_CHANGEPOS & eFlags ) )
+ {
+ // dann wars das schon
+ RestoreSavePos();
+ return sal_True;
+ }
+
+ // dann setze den Cursor auf die neue Position:
+ SwNodeIndex aIdx( rPtIdx );
+ xub_StrLen nCntntPos = pSavePos->nCntnt;
+ int bGoNxt = pSavePos->nNode < rPtIdx.GetIndex();
+ SwCntntNode* pCNd = bGoNxt
+ ? rNds.GoNextSection( &rPtIdx, bSkipOverHiddenSections, bSkipOverProtectSections)
+ : rNds.GoPrevSection( &rPtIdx, bSkipOverHiddenSections, bSkipOverProtectSections);
+ if( !pCNd && ( nsSwCursorSelOverFlags::SELOVER_ENABLEREVDIREKTION & eFlags ))
+ {
+ bGoNxt = !bGoNxt;
+ pCNd = bGoNxt ? rNds.GoNextSection( &rPtIdx, bSkipOverHiddenSections, bSkipOverProtectSections)
+ : rNds.GoPrevSection( &rPtIdx, bSkipOverHiddenSections, bSkipOverProtectSections);
+ }
+
+ int bIsValidPos = 0 != pCNd;
+ sal_Bool bValidNodesRange = bIsValidPos &&
+ ::CheckNodesRange( rPtIdx, aIdx, sal_True );
+ if( !bValidNodesRange )
+ {
+ rPtIdx = pSavePos->nNode;
+ if( 0 == ( pCNd = rPtIdx.GetNode().GetCntntNode() ) )
+ {
+ bIsValidPos = sal_False;
+ nCntntPos = 0;
+ rPtIdx = aIdx;
+ if( 0 == ( pCNd = rPtIdx.GetNode().GetCntntNode() ) )
+ {
+ // dann auf den Anfang vom Doc
+ rPtIdx = rNds.GetEndOfExtras();
+ pCNd = rNds.GoNext( &rPtIdx );
+ }
+ }
+ }
+
+ // ContentIndex noch anmelden:
+ xub_StrLen nTmpPos = bIsValidPos ? (bGoNxt ? 0 : pCNd->Len()) : nCntntPos;
+ GetPoint()->nContent.Assign( pCNd, nTmpPos );
+ if( !bIsValidPos || !bValidNodesRange ||
+ // sollten wir in einer Tabelle gelandet sein?
+ IsInProtectTable( sal_True ) )
+ return sal_True;
+ }
+
+ // oder sollte eine geschuetzte Section innerhalb der Selektion liegen?
+ if( HasMark() && bSkipOverProtectSections)
+ {
+ sal_uLong nSttIdx = GetMark()->nNode.GetIndex(),
+ nEndIdx = GetPoint()->nNode.GetIndex();
+ if( nEndIdx <= nSttIdx )
+ {
+ sal_uLong nTmp = nSttIdx;
+ nSttIdx = nEndIdx;
+ nEndIdx = nTmp;
+ }
+
+ const SwSectionFmts& rFmts = pDoc->GetSections();
+ for( sal_uInt16 n = 0; n < rFmts.Count(); ++n )
+ {
+ const SwSectionFmt* pFmt = rFmts[n];
+ const SvxProtectItem& rProtect = pFmt->GetProtect();
+ if( rProtect.IsCntntProtected() )
+ {
+ const SwFmtCntnt& rCntnt = pFmt->GetCntnt(sal_False);
+ OSL_ENSURE( rCntnt.GetCntntIdx(), "wo ist der SectionNode?" );
+ sal_uLong nIdx = rCntnt.GetCntntIdx()->GetIndex();
+ if( nSttIdx <= nIdx && nEndIdx >= nIdx )
+ {
+ // ist es keine gelinkte Section, dann kann sie auch
+ // nicht mitselektiert werden
+ const SwSection& rSect = *pFmt->GetSection();
+ if( CONTENT_SECTION == rSect.GetType() )
+ {
+ RestoreSavePos();
+ return sal_True;
+ }
+ }
+ }
+ }
+ }
+
+ }
+// Ende
+// neu: Bereiche ueberpruefen
+
+ const SwNode* pNd = &GetPoint()->nNode.GetNode();
+ if( pNd->IsCntntNode() && !dynamic_cast<SwUnoCrsr*>(this) )
+ {
+ const SwCntntFrm* pFrm = ((SwCntntNode*)pNd)->getLayoutFrm( pDoc->GetCurrentLayout() );
+ if( pFrm && pFrm->IsValid() && 0 == pFrm->Frm().Height() &&
+ 0 != ( nsSwCursorSelOverFlags::SELOVER_CHANGEPOS & eFlags ) )
+ {
+ // skip to the next / prev valid paragraph with a layout
+ SwNodeIndex& rPtIdx = GetPoint()->nNode;
+ int bGoNxt = pSavePos->nNode < rPtIdx.GetIndex();
+ while( 0 != ( pFrm = ( bGoNxt ? pFrm->GetNextCntntFrm()
+ : pFrm->GetPrevCntntFrm() )) &&
+ 0 == pFrm->Frm().Height() )
+ ;
+
+ // --> LIJIAN/FME 2007-11-27 #i72394# skip to prev /next valid paragraph
+ // with a layout in case the first search did not succeed:
+ if( !pFrm )
+ {
+ bGoNxt = !bGoNxt;
+ pFrm = ((SwCntntNode*)pNd)->getLayoutFrm( pDoc->GetCurrentLayout() );
+ while ( pFrm && 0 == pFrm->Frm().Height() )
+ {
+ pFrm = bGoNxt ? pFrm->GetNextCntntFrm()
+ : pFrm->GetPrevCntntFrm();
+ }
+ }
+ // <--
+
+ SwCntntNode* pCNd;
+ if( pFrm && 0 != (pCNd = (SwCntntNode*)pFrm->GetNode()) )
+ {
+ // set this cntntNode as new position
+ rPtIdx = *pCNd;
+ pNd = pCNd;
+
+ // ContentIndex noch anmelden:
+ xub_StrLen nTmpPos = bGoNxt ? 0 : pCNd->Len();
+ GetPoint()->nContent.Assign( pCNd, nTmpPos );
+
+ // sollten wir in einer Tabelle gelandet sein?
+ if( IsInProtectTable( sal_True ) )
+ pFrm = 0;
+ }
+ }
+
+ if( !pFrm )
+ {
+ DeleteMark();
+ RestoreSavePos();
+ return sal_True; // ohne Frames geht gar nichts!
+ }
+ }
+
+ // darf der Cursor in geschuetzen "Nodes" stehen?
+ if( 0 == ( nsSwCursorSelOverFlags::SELOVER_CHANGEPOS & eFlags ) && !IsAtValidPos() )
+ {
+ DeleteMark();
+ RestoreSavePos();
+ return sal_True;
+ }
+
+ if( !HasMark() )
+ return sal_False;
+
+ //JP 19.08.98: teste mal auf ungueltige Selektion - sprich ueber
+ // GrundSections:
+ if( !::CheckNodesRange( GetMark()->nNode, GetPoint()->nNode, sal_True ))
+ {
+ DeleteMark();
+ RestoreSavePos();
+ return sal_True; // ohne Frames geht gar nichts!
+ }
+
+ const SwTableNode* pPtNd = pNd->FindTableNode();
+
+ if( (pNd = &GetMark()->nNode.GetNode())->IsCntntNode() &&
+ !((SwCntntNode*)pNd)->getLayoutFrm( pDoc->GetCurrentLayout() ) && !dynamic_cast<SwUnoCrsr*>(this) )
+ {
+ DeleteMark();
+ RestoreSavePos();
+ return sal_True; // ohne Frames geht gar nichts!
+ }
+
+ const SwTableNode* pMrkNd = pNd->FindTableNode();
+
+ // beide in keinem oder beide im gleichen TableNode
+ if( ( !pMrkNd && !pPtNd ) || pPtNd == pMrkNd )
+ return sal_False;
+
+ // in unterschiedlichen Tabellen oder nur Mark in der Tabelle
+ if( ( pPtNd && pMrkNd ) || pMrkNd )
+ { // dann lasse das nicht zu, alte Pos zurueck
+ RestoreSavePos();
+ // Crsr bleibt an der alten Position
+ return sal_True;
+ }
+
+ // ACHTUNG: dieses kann nicht im TableMode geschehen !!
+ if( pPtNd ) // nur Point in Tabelle, dann gehe hinter/vor diese
+ {
+ if( nsSwCursorSelOverFlags::SELOVER_CHANGEPOS & eFlags )
+ {
+ sal_Bool bSelTop = GetPoint()->nNode.GetIndex() <
+ (( nsSwCursorSelOverFlags::SELOVER_TOGGLE & eFlags ) ? pSavePos->nNode
+ : GetMark()->nNode.GetIndex());
+
+ do {
+ // in Schleife fuer Tabelle hinter Tabelle
+ sal_uLong nSEIdx = pPtNd->EndOfSectionIndex();
+ sal_uLong nSttEndTbl = nSEIdx + 1; // dflt. Sel. nach unten
+
+ if( bSelTop ) // Sel. nach oben
+ nSttEndTbl = rNds[ nSEIdx ]->StartOfSectionIndex() - 1;
+
+ GetPoint()->nNode = nSttEndTbl;
+ const SwNode* pMyNd = GetNode();
+
+ if( pMyNd->IsSectionNode() || ( pMyNd->IsEndNode() &&
+ pMyNd->StartOfSectionNode()->IsSectionNode() ) )
+ {
+ // die lassen wir zu:
+ pMyNd = bSelTop
+ ? rNds.GoPrevSection( &GetPoint()->nNode,sal_True,sal_False )
+ : rNds.GoNextSection( &GetPoint()->nNode,sal_True,sal_False );
+
+ /* #i12312# Handle failure of Go{Prev|Next}Section */
+ if ( 0 == pMyNd)
+ break;
+
+ if( 0 != ( pPtNd = pMyNd->FindTableNode() ))
+ continue;
+ }
+
+ if( pMyNd->IsCntntNode() && // ist es ein ContentNode ??
+ ::CheckNodesRange( GetMark()->nNode,
+ GetPoint()->nNode, sal_True ))
+ {
+ // TABLE IN TABLE
+ const SwTableNode* pOuterTableNd = pMyNd->FindTableNode();
+ if ( pOuterTableNd )
+ pMyNd = pOuterTableNd;
+ else
+ {
+ SwCntntNode* pCNd = (SwCntntNode*)pMyNd;
+ xub_StrLen nTmpPos = bSelTop ? pCNd->Len() : 0;
+ GetPoint()->nContent.Assign( pCNd, nTmpPos );
+ return sal_False;
+ }
+ }
+ if( bSelTop
+ ? ( !pMyNd->IsEndNode() || 0 == ( pPtNd = pMyNd->FindTableNode() ))
+ : 0 == ( pPtNd = pMyNd->GetTableNode() ))
+ break;
+ } while( sal_True );
+ }
+
+ // dann verbleibe auf der alten Position
+ RestoreSavePos();
+ return sal_True; // Crsr bleibt an der alten Position
+ }
+ return sal_False; // was bleibt noch ??
+}
+
+#if defined( UNX )
+#define IDX (*pCellStt)
+#else
+#define IDX aCellStt
+#endif
+
+
+sal_Bool SwCursor::IsInProtectTable( sal_Bool bMove, sal_Bool bChgCrsr )
+{
+ SwCntntNode* pCNd = GetCntntNode();
+ if( !pCNd )
+ return sal_False;
+
+ // No table, no protected cell:
+ const SwTableNode* pTableNode = pCNd->FindTableNode();
+ if ( !pTableNode )
+ return sal_False;
+
+ // Current position == last save position?
+ if ( pSavePos->nNode == GetPoint()->nNode.GetIndex() )
+ return sal_False;
+
+ // Check for convered cell:
+ bool bInCoveredCell = false;
+ const SwStartNode* pTmpSttNode = pCNd->FindTableBoxStartNode();
+ OSL_ENSURE( pTmpSttNode, "In table, therefore I expect to get a SwTableBoxStartNode" );
+ const SwTableBox* pBox = pTmpSttNode ? pTableNode->GetTable().GetTblBox( pTmpSttNode->GetIndex() ) : 0; //Robust #151355
+ if ( pBox && pBox->getRowSpan() < 1 ) // Robust #151270
+ bInCoveredCell = true;
+
+ // Positions of covered cells are not acceptable:
+ if ( !bInCoveredCell )
+ {
+ // Position not protected?
+ if ( !pCNd->IsProtect() )
+ return sal_False;
+
+ // Cursor in protected cells allowed?
+ if ( IsReadOnlyAvailable() )
+ return sal_False;
+ }
+
+ // If we reach this point, we are in a protected or covered table cell!
+
+ if( !bMove )
+ {
+ if( bChgCrsr )
+ // restore the last save position
+ RestoreSavePos();
+ return sal_True; // Crsr bleibt an der alten Position
+ }
+
+ // wir stehen in einer geschuetzten TabellenZelle
+ // von Oben nach Unten Traveln ?
+ if( pSavePos->nNode < GetPoint()->nNode.GetIndex() )
+ {
+ // suche die naechste "gueltige" Box
+
+ // folgt nach dem EndNode der Zelle ein weiterer StartNode, dann
+ // gibt es auch eine naechste Zelle
+#if defined( UNX )
+ SwNodeIndex* pCellStt = new SwNodeIndex( *GetNode()->
+ FindTableBoxStartNode()->EndOfSectionNode(), 1 );
+#else
+ SwNodeIndex aCellStt( *GetNode()->FindTableBoxStartNode()->EndOfSectionNode(), 1 );
+#endif
+ sal_Bool bProt = sal_True;
+GoNextCell:
+ do {
+ if( !IDX.GetNode().IsStartNode() )
+ break;
+ IDX++;
+ if( 0 == ( pCNd = IDX.GetNode().GetCntntNode() ))
+ pCNd = IDX.GetNodes().GoNext( &IDX );
+ if( 0 == ( bProt = pCNd->IsProtect() ))
+ break;
+ IDX.Assign( *pCNd->FindTableBoxStartNode()->EndOfSectionNode(), 1 );
+ } while( bProt );
+
+SetNextCrsr:
+ if( !bProt ) // eine freie Zelle gefunden
+ {
+ GetPoint()->nNode = IDX;
+#if defined( UNX )
+ delete pCellStt;
+#endif
+ SwCntntNode* pTmpCNd = GetCntntNode();
+ if( pTmpCNd )
+ {
+ GetPoint()->nContent.Assign( pTmpCNd, 0 );
+ return sal_False;
+ }
+ return IsSelOvr( nsSwCursorSelOverFlags::SELOVER_TOGGLE |
+ nsSwCursorSelOverFlags::SELOVER_CHANGEPOS );
+ }
+ // am Ende der Tabelle, also setze hinter diese
+ IDX++; // auf den naechsten Node
+ SwNode* pNd;
+ if( ( pNd = &IDX.GetNode())->IsEndNode() || HasMark())
+ {
+ // Tabelle allein in einem FlyFrame oder SSelection,
+ // dann verbleibe auf der alten Position
+ if( bChgCrsr )
+ RestoreSavePos();
+#if defined( UNX )
+ delete pCellStt;
+#endif
+ return sal_True; // Crsr bleibt an der alten Position
+ }
+ else if( pNd->IsTableNode() && IDX++ )
+ goto GoNextCell;
+
+ bProt = sal_False; // Index steht jetzt auf einem ContentNode
+ goto SetNextCrsr;
+ }
+
+ // suche die vorherige "gueltige" Box
+ {
+ // liegt vor dem StartNode der Zelle ein weiterer EndNode, dann
+ // gibt es auch eine vorherige Zelle
+#if defined( UNX )
+ SwNodeIndex* pCellStt = new SwNodeIndex(
+ *GetNode()->FindTableBoxStartNode(), -1 );
+#else
+ SwNodeIndex aCellStt( *GetNode()->FindTableBoxStartNode(), -1 );
+#endif
+ SwNode* pNd;
+ sal_Bool bProt = sal_True;
+GoPrevCell:
+ do {
+ if( !( pNd = &IDX.GetNode())->IsEndNode() )
+ break;
+ IDX.Assign( *pNd->StartOfSectionNode(), +1 );
+ if( 0 == ( pCNd = IDX.GetNode().GetCntntNode() ))
+ pCNd = pNd->GetNodes().GoNext( &IDX );
+ if( 0 == ( bProt = pCNd->IsProtect() ))
+ break;
+ IDX.Assign( *pNd->FindTableBoxStartNode(), -1 );
+ } while( bProt );
+
+SetPrevCrsr:
+ if( !bProt ) // eine freie Zelle gefunden
+ {
+ GetPoint()->nNode = IDX;
+#if defined( UNX )
+ delete pCellStt;
+#endif
+ SwCntntNode* pTmpCNd = GetCntntNode();
+ if( pTmpCNd )
+ {
+ GetPoint()->nContent.Assign( pTmpCNd, 0 );
+ return sal_False;
+ }
+ return IsSelOvr( nsSwCursorSelOverFlags::SELOVER_TOGGLE |
+ nsSwCursorSelOverFlags::SELOVER_CHANGEPOS );
+ }
+ // am Start der Tabelle, also setze vor diese
+ IDX--; // auf den naechsten Node
+ if( ( pNd = &IDX.GetNode())->IsStartNode() || HasMark() )
+ {
+ // Tabelle allein in einem FlyFrame oder Selektion,
+ // dann verbleibe auf der alten Position
+ if( bChgCrsr )
+ RestoreSavePos();
+#if defined( UNX )
+ delete pCellStt;
+#endif
+ return sal_True; // Crsr bleibt an der alten Position
+ }
+ else if( pNd->StartOfSectionNode()->IsTableNode() && IDX-- )
+ goto GoPrevCell;
+
+ bProt = sal_False; // Index steht jetzt auf einem ContentNode
+ goto SetPrevCrsr;
+ }
+}
+
+// sal_True: an die Position kann der Cursor gesetzt werden
+sal_Bool SwCursor::IsAtValidPos( sal_Bool bPoint ) const
+{
+ const SwDoc* pDoc = GetDoc();
+ const SwPosition* pPos = bPoint ? GetPoint() : GetMark();
+ const SwNode* pNd = &pPos->nNode.GetNode();
+
+ if( pNd->IsCntntNode() && !((SwCntntNode*)pNd)->getLayoutFrm( pDoc->GetCurrentLayout() ) &&
+ !dynamic_cast<const SwUnoCrsr*>(this) )
+ {
+ return sal_False;
+ }
+
+ //JP 28.10.97: Bug 45129 - im UI-ReadOnly ist alles erlaubt
+ if( !pDoc->GetDocShell() || !pDoc->GetDocShell()->IsReadOnlyUI() )
+ return sal_True;
+
+ sal_Bool bCrsrInReadOnly = IsReadOnlyAvailable();
+ if( !bCrsrInReadOnly && pNd->IsProtect() )
+ return sal_False;
+
+ const SwSectionNode* pSectNd = pNd->FindSectionNode();
+ if( pSectNd && (pSectNd->GetSection().IsHiddenFlag() ||
+ ( !bCrsrInReadOnly && pSectNd->GetSection().IsProtectFlag() )))
+ return sal_False;
+
+ return sal_True;
+}
+
+void SwCursor::SaveTblBoxCntnt( const SwPosition* ) {}
+
+// setze den SRange fuer das Suchen im Dokument
+SwMoveFnCollection* SwCursor::MakeFindRange( SwDocPositions nStart,
+ SwDocPositions nEnd, SwPaM* pRange ) const
+{
+ pRange->SetMark();
+ FillFindPos( nStart, *pRange->GetMark() );
+ FillFindPos( nEnd, *pRange->GetPoint() );
+
+ // bestimme die Richtung, in der zu suchen ist
+ // ( GetPoint > GetMark -> vorwaerts, sonst rueckwaerts )
+ return ( DOCPOS_START == nStart || DOCPOS_OTHERSTART == nStart ||
+ (DOCPOS_CURR == nStart &&
+ (DOCPOS_END == nEnd || DOCPOS_OTHEREND == nEnd ) ))
+ ? fnMoveForward : fnMoveBackward;
+}
+
+
+sal_uLong lcl_FindSelection( SwFindParas& rParas, SwCursor* pCurCrsr,
+ SwMoveFn fnMove, SwCursor*& pFndRing,
+ SwPaM& aRegion, FindRanges eFndRngs,
+ sal_Bool bInReadOnly, sal_Bool& bCancel )
+{
+ SwDoc* pDoc = pCurCrsr->GetDoc();
+ bool const bDoesUndo = pDoc->GetIDocumentUndoRedo().DoesUndo();
+ int nFndRet = 0;
+ sal_uLong nFound = 0;
+ int bSrchBkwrd = fnMove == fnMoveBackward, bEnde = sal_False;
+ SwPaM *pTmpCrsr = pCurCrsr, *pSaveCrsr = pCurCrsr;
+
+ // only create progress-bar for ShellCrsr
+ bool bIsUnoCrsr = 0 != dynamic_cast<SwUnoCrsr*>(pCurCrsr);
+ _PercentHdl* pPHdl = 0;
+ sal_uInt16 nCrsrCnt = 0;
+ if( FND_IN_SEL & eFndRngs )
+ {
+ while( pCurCrsr != ( pTmpCrsr = (SwPaM*)pTmpCrsr->GetNext() ))
+ ++nCrsrCnt;
+ if( nCrsrCnt && !bIsUnoCrsr )
+ pPHdl = new _PercentHdl( 0, nCrsrCnt, pDoc->GetDocShell() );
+ }
+ else
+ pSaveCrsr = (SwPaM*)pSaveCrsr->GetPrev();
+
+ do {
+ aRegion.SetMark();
+ // egal in welche Richtung, SPoint ist immer groesser als Mark,
+ // wenn der Suchbereich gueltig ist !!
+ SwPosition *pSttPos = aRegion.GetMark(),
+ *pEndPos = aRegion.GetPoint();
+ *pSttPos = *pTmpCrsr->Start();
+ *pEndPos = *pTmpCrsr->End();
+ if( bSrchBkwrd )
+ aRegion.Exchange();
+
+ if( !nCrsrCnt && !pPHdl && !bIsUnoCrsr )
+ pPHdl = new _PercentHdl( aRegion );
+
+ // solange gefunden und nicht auf gleicher Position haengen bleibt
+ while( *pSttPos <= *pEndPos &&
+ 0 != ( nFndRet = rParas.Find( pCurCrsr, fnMove,
+ &aRegion, bInReadOnly )) &&
+ ( !pFndRing ||
+ *pFndRing->GetPoint() != *pCurCrsr->GetPoint() ||
+ *pFndRing->GetMark() != *pCurCrsr->GetMark() ))
+ {
+ if( !( FIND_NO_RING & nFndRet ))
+ {
+ // Bug 24084: Ring richtig herum aufbauen -> gleiche Mimik
+ // wie beim CreateCrsr !!!!
+
+ SwCursor* pNew = pCurCrsr->Create( pFndRing );
+ if( !pFndRing )
+ pFndRing = pNew;
+
+ pNew->SetMark();
+ *pNew->GetMark() = *pCurCrsr->GetMark();
+ }
+
+ ++nFound;
+
+ if( !( eFndRngs & FND_IN_SELALL) )
+ {
+ bEnde = sal_True;
+ break;
+ }
+
+ if ((coSrchRplcThreshold == nFound)
+ && pDoc->GetIDocumentUndoRedo().DoesUndo()
+ && rParas.IsReplaceMode())
+ {
+ short nRet = pCurCrsr->MaxReplaceArived();
+ if( RET_YES == nRet )
+ {
+ pDoc->GetIDocumentUndoRedo().DelAllUndoObj();
+ pDoc->GetIDocumentUndoRedo().DoUndo(false);
+ }
+ else
+ {
+ bEnde = sal_True;
+ if(RET_CANCEL == nRet)
+ {
+ bCancel = sal_True;
+ //unwind() ??
+ }
+ break;
+ }
+ }
+
+ if( bSrchBkwrd )
+ // bewege pEndPos vor den gefundenen Bereich
+ *pEndPos = *pCurCrsr->Start();
+ else
+ // bewege pSttPos hinter den gefundenen Bereich
+ *pSttPos = *pCurCrsr->End();
+
+ if( *pSttPos == *pEndPos ) // im Bereich, aber am Ende
+ break; // fertig
+
+ if( !nCrsrCnt && pPHdl )
+ {
+ pPHdl->NextPos( *aRegion.GetMark() );
+ }
+ }
+
+ if( bEnde || !( eFndRngs & ( FND_IN_SELALL | FND_IN_SEL )) )
+ break;
+
+ pTmpCrsr = ((SwPaM*)pTmpCrsr->GetNext());
+ if( nCrsrCnt && pPHdl )
+ {
+ pPHdl->NextPos( ++pPHdl->nActPos );
+ }
+
+ } while( pTmpCrsr != pSaveCrsr );
+
+ if( nFound && !pFndRing ) // falls kein Ring aufgebaut werden soll
+ pFndRing = pCurCrsr->Create();
+
+ delete pPHdl;
+ pDoc->GetIDocumentUndoRedo().DoUndo(bDoesUndo);
+ return nFound;
+}
+
+
+int lcl_MakeSelFwrd( const SwNode& rSttNd, const SwNode& rEndNd,
+ SwPaM& rPam, int bFirst )
+{
+ if( rSttNd.GetIndex() + 1 == rEndNd.GetIndex() )
+ return sal_False;
+
+ SwNodes& rNds = rPam.GetDoc()->GetNodes();
+ rPam.DeleteMark();
+ SwCntntNode* pCNd;
+ if( !bFirst )
+ {
+ rPam.GetPoint()->nNode = rSttNd;
+ pCNd = rNds.GoNext( &rPam.GetPoint()->nNode );
+ if( !pCNd )
+ return sal_False;
+ pCNd->MakeStartIndex( &rPam.GetPoint()->nContent );
+ }
+ else if( rSttNd.GetIndex() > rPam.GetPoint()->nNode.GetIndex() ||
+ rPam.GetPoint()->nNode.GetIndex() >= rEndNd.GetIndex() )
+ return sal_False; // steht nicht in dieser Section
+
+ rPam.SetMark();
+ rPam.GetPoint()->nNode = rEndNd;
+ pCNd = rNds.GoPrevious( &rPam.GetPoint()->nNode );
+ if( !pCNd )
+ return sal_False;
+ pCNd->MakeEndIndex( &rPam.GetPoint()->nContent );
+
+ return *rPam.GetMark() < *rPam.GetPoint();
+}
+
+
+int lcl_MakeSelBkwrd( const SwNode& rSttNd, const SwNode& rEndNd,
+ SwPaM& rPam, int bFirst )
+{
+ if( rEndNd.GetIndex() + 1 == rSttNd.GetIndex() )
+ return sal_False;
+
+ SwNodes& rNds = rPam.GetDoc()->GetNodes();
+ rPam.DeleteMark();
+ SwCntntNode* pCNd;
+ if( !bFirst )
+ {
+ rPam.GetPoint()->nNode = rSttNd;
+ pCNd = rNds.GoPrevious( &rPam.GetPoint()->nNode );
+ if( !pCNd )
+ return sal_False;
+ pCNd->MakeEndIndex( &rPam.GetPoint()->nContent );
+ }
+ else if( rEndNd.GetIndex() > rPam.GetPoint()->nNode.GetIndex() ||
+ rPam.GetPoint()->nNode.GetIndex() >= rSttNd.GetIndex() )
+ return sal_False; // steht nicht in dieser Section
+
+ rPam.SetMark();
+ rPam.GetPoint()->nNode = rEndNd;
+ pCNd = rNds.GoNext( &rPam.GetPoint()->nNode );
+ if( !pCNd )
+ return sal_False;
+ pCNd->MakeStartIndex( &rPam.GetPoint()->nContent );
+
+ return *rPam.GetPoint() < *rPam.GetMark();
+}
+
+
+// diese Methode "sucht" fuer alle Anwendungsfaelle, denn in SwFindParas
+// steht immer die richtigen Parameter und die entsprechende Find-Methode
+
+sal_uLong SwCursor::FindAll( SwFindParas& rParas,
+ SwDocPositions nStart, SwDocPositions nEnde,
+ FindRanges eFndRngs, sal_Bool& bCancel )
+{
+ bCancel = sal_False;
+ SwCrsrSaveState aSaveState( *this );
+
+ // Region erzeugen, ohne das diese in den Ring aufgenommen wird !
+ SwPaM aRegion( *GetPoint() );
+ SwMoveFn fnMove = MakeFindRange( nStart, nEnde, &aRegion );
+
+ sal_uLong nFound = 0;
+ int bMvBkwrd = fnMove == fnMoveBackward;
+ sal_Bool bInReadOnly = IsReadOnlyAvailable();
+
+ SwCursor* pFndRing = 0;
+ SwNodes& rNds = GetDoc()->GetNodes();
+
+ // suche in Bereichen ?
+ if( FND_IN_SEL & eFndRngs )
+ {
+ // String nicht im Bereich gefunden, dann erhalte alle Bereiche,
+ // der Cursor beleibt unveraendert
+ if( 0 == ( nFound = lcl_FindSelection( rParas, this, fnMove,
+ pFndRing, aRegion, eFndRngs,
+ bInReadOnly, bCancel ) ))
+ return nFound;
+
+ // der String wurde ein- bis mehrmals gefunden. Das steht alles
+ // im neuen Crsr-Ring. Darum hebe erstmal den alten Ring auf
+ while( GetNext() != this )
+ delete GetNext();
+
+ *GetPoint() = *pFndRing->GetPoint();
+ SetMark();
+ *GetMark() = *pFndRing->GetMark();
+ pFndRing->MoveRingTo( this );
+ delete pFndRing;
+ }
+ else if( FND_IN_OTHER & eFndRngs )
+ {
+ // Cursor als Kopie vom akt. und in den Ring aufnehmen
+ // Verkettung zeigt immer auf den zuerst erzeugten, also vorwaerts
+ std::auto_ptr< SwCursor > pSav( Create( this ) ); // save the current cursor
+
+ // wenn schon ausserhalb vom Bodytext, suche von der Position,
+ // ansonsten beginne mit der 1. GrundSection
+ if( bMvBkwrd
+ ? lcl_MakeSelBkwrd( rNds.GetEndOfExtras(),
+ *rNds.GetEndOfPostIts().StartOfSectionNode(),
+ *this, rNds.GetEndOfExtras().GetIndex() >=
+ GetPoint()->nNode.GetIndex() )
+ : lcl_MakeSelFwrd( *rNds.GetEndOfPostIts().StartOfSectionNode(),
+ rNds.GetEndOfExtras(), *this,
+ rNds.GetEndOfExtras().GetIndex() >=
+ GetPoint()->nNode.GetIndex() ))
+ {
+ nFound = lcl_FindSelection( rParas, this, fnMove, pFndRing,
+ aRegion, eFndRngs, bInReadOnly, bCancel );
+ }
+
+ if( !nFound )
+ {
+ // den alten wieder zurueck
+ *GetPoint() = *pSav->GetPoint();
+ if( pSav->HasMark() )
+ {
+ SetMark();
+ *GetMark() = *pSav->GetMark();
+ }
+ else
+ DeleteMark();
+ return 0;
+ }
+ pSav.release();
+
+ if( !( FND_IN_SELALL & eFndRngs ))
+ {
+ // es sollte nur einer gesucht werden, also fuege in dazu
+ // egal in welche Richtung, SPoint ist immer groesser als Mark,
+ // wenn der Suchbereich gueltig ist !!
+ *GetPoint() = *pFndRing->GetPoint();
+ SetMark();
+ *GetMark() = *pFndRing->GetMark();
+ }
+ else
+ {
+ // es wurde ein- bis mehrmals gefunden. Das steht alles
+ // im neuen Crsr-Ring. Darum hebe erstmal den alten Ring auf
+ while( GetNext() != this )
+ delete GetNext();
+
+ *GetPoint() = *pFndRing->GetPoint();
+ SetMark();
+ *GetMark() = *pFndRing->GetMark();
+ pFndRing->MoveRingTo( this );
+ }
+ delete pFndRing;
+ }
+ else if( FND_IN_SELALL & eFndRngs )
+ {
+ ::std::auto_ptr< SwCursor> pSav( Create( this ) ); // save the current cursor
+
+ const SwNode* pSttNd = ( FND_IN_BODYONLY & eFndRngs )
+ ? rNds.GetEndOfContent().StartOfSectionNode()
+ : rNds.GetEndOfPostIts().StartOfSectionNode();
+
+ if( bMvBkwrd
+ ? lcl_MakeSelBkwrd( rNds.GetEndOfContent(), *pSttNd,*this, sal_False )
+ : lcl_MakeSelFwrd( *pSttNd, rNds.GetEndOfContent(), *this, sal_False ))
+ {
+ nFound = lcl_FindSelection( rParas, this, fnMove, pFndRing,
+ aRegion, eFndRngs, bInReadOnly, bCancel );
+ }
+
+ if( !nFound )
+ {
+ // den alten wieder zurueck
+ *GetPoint() = *pSav->GetPoint();
+ if( pSav->HasMark() )
+ {
+ SetMark();
+ *GetMark() = *pSav->GetMark();
+ }
+ else
+ DeleteMark();
+ return 0;
+ }
+ pSav.release();
+ while( GetNext() != this )
+ delete GetNext();
+
+ *GetPoint() = *pFndRing->GetPoint();
+ SetMark();
+ *GetMark() = *pFndRing->GetMark();
+ pFndRing->MoveRingTo( this );
+ delete pFndRing;
+ }
+ else
+ {
+ // ist ein GetMark gesetzt, dann wird bei gefundenem Object
+ // der GetMark beibehalten !! Dadurch kann ein Bereich mit der Suche
+ // aufgespannt werden.
+ SwPosition aMarkPos( *GetMark() );
+ int bMarkPos = HasMark() && !eFndRngs;
+
+ if( 0 != (nFound = rParas.Find( this, fnMove,
+ &aRegion, bInReadOnly ) ? 1 : 0)
+ && bMarkPos )
+ *GetMark() = aMarkPos;
+ }
+
+ if( nFound && SwCursor::IsSelOvr( nsSwCursorSelOverFlags::SELOVER_TOGGLE ) )
+ nFound = 0;
+ return nFound;
+}
+
+
+void SwCursor::FillFindPos( SwDocPositions ePos, SwPosition& rPos ) const
+{
+ sal_Bool bIsStart = sal_True;
+ SwCntntNode* pCNd = 0;
+ SwNodes& rNds = GetDoc()->GetNodes();
+
+ switch( ePos )
+ {
+ case DOCPOS_START:
+ rPos.nNode = *rNds.GetEndOfContent().StartOfSectionNode();
+ pCNd = rNds.GoNext( &rPos.nNode );
+ break;
+
+ case DOCPOS_END:
+ rPos.nNode = rNds.GetEndOfContent();
+ pCNd = rNds.GoPrevious( &rPos.nNode );
+ bIsStart = sal_False;
+ break;
+
+ case DOCPOS_OTHERSTART:
+ rPos.nNode = *rNds[ sal_uLong(0) ];
+ pCNd = rNds.GoNext( &rPos.nNode );
+ break;
+
+ case DOCPOS_OTHEREND:
+ rPos.nNode = *rNds.GetEndOfContent().StartOfSectionNode();
+ pCNd = rNds.GoPrevious( &rPos.nNode );
+ bIsStart = sal_False;
+ break;
+
+// case DOCPOS_CURR:
+ default:
+ rPos = *GetPoint();
+ }
+
+ if( pCNd )
+ {
+ xub_StrLen nCPos = 0;
+ if( !bIsStart )
+ nCPos = pCNd->Len();
+ rPos.nContent.Assign( pCNd, nCPos );
+ }
+}
+
+short SwCursor::MaxReplaceArived()
+{
+ return RET_YES;
+}
+
+
+sal_Bool SwCursor::IsStartWord( sal_Int16 nWordType ) const
+{
+ return IsStartWordWT( nWordType );
+}
+
+sal_Bool SwCursor::IsEndWord( sal_Int16 nWordType ) const
+{
+ return IsEndWordWT( nWordType );
+}
+
+sal_Bool SwCursor::IsInWord( sal_Int16 nWordType ) const
+{
+ return IsInWordWT( nWordType );
+}
+
+sal_Bool SwCursor::GoStartWord()
+{
+ return GoStartWordWT( WordType::ANYWORD_IGNOREWHITESPACES );
+}
+
+sal_Bool SwCursor::GoEndWord()
+{
+ return GoEndWordWT( WordType::ANYWORD_IGNOREWHITESPACES );
+}
+
+sal_Bool SwCursor::GoNextWord()
+{
+ return GoNextWordWT( WordType::ANYWORD_IGNOREWHITESPACES );
+}
+
+sal_Bool SwCursor::GoPrevWord()
+{
+ return GoPrevWordWT( WordType::ANYWORD_IGNOREWHITESPACES );
+}
+
+sal_Bool SwCursor::SelectWord( ViewShell* pViewShell, const Point* pPt )
+{
+ return SelectWordWT( pViewShell, WordType::ANYWORD_IGNOREWHITESPACES, pPt );
+}
+
+sal_Bool SwCursor::IsStartWordWT( sal_Int16 nWordType ) const
+{
+ sal_Bool bRet = sal_False;
+ const SwTxtNode* pTxtNd = GetNode()->GetTxtNode();
+ if( pTxtNd && pBreakIt->GetBreakIter().is() )
+ {
+ xub_StrLen nPtPos = GetPoint()->nContent.GetIndex();
+ bRet = pBreakIt->GetBreakIter()->isBeginWord(
+ pTxtNd->GetTxt(), nPtPos,
+ pBreakIt->GetLocale( pTxtNd->GetLang( nPtPos )),
+ nWordType );
+ }
+ return bRet;
+}
+
+sal_Bool SwCursor::IsEndWordWT( sal_Int16 nWordType ) const
+{
+ sal_Bool bRet = sal_False;
+ const SwTxtNode* pTxtNd = GetNode()->GetTxtNode();
+ if( pTxtNd && pBreakIt->GetBreakIter().is() )
+ {
+ xub_StrLen nPtPos = GetPoint()->nContent.GetIndex();
+ bRet = pBreakIt->GetBreakIter()->isEndWord(
+ pTxtNd->GetTxt(), nPtPos,
+ pBreakIt->GetLocale( pTxtNd->GetLang( nPtPos ) ),
+ nWordType );
+
+ }
+ return bRet;
+}
+
+sal_Bool SwCursor::IsInWordWT( sal_Int16 nWordType ) const
+{
+ sal_Bool bRet = sal_False;
+ const SwTxtNode* pTxtNd = GetNode()->GetTxtNode();
+ if( pTxtNd && pBreakIt->GetBreakIter().is() )
+ {
+ xub_StrLen nPtPos = GetPoint()->nContent.GetIndex();
+ Boundary aBoundary = pBreakIt->GetBreakIter()->getWordBoundary(
+ pTxtNd->GetTxt(), nPtPos,
+ pBreakIt->GetLocale( pTxtNd->GetLang( nPtPos ) ),
+ nWordType,
+ sal_True );
+
+ bRet = aBoundary.startPos != aBoundary.endPos &&
+ aBoundary.startPos <= nPtPos &&
+ nPtPos <= aBoundary.endPos;
+ if(bRet)
+ {
+ const CharClass& rCC = GetAppCharClass();
+ bRet = rCC.isLetterNumeric( pTxtNd->GetTxt(), static_cast<xub_StrLen>(aBoundary.startPos) );
+ }
+ }
+ return bRet;
+}
+
+sal_Bool SwCursor::IsStartEndSentence( bool bEnd ) const
+{
+ sal_Bool bRet = bEnd ?
+ GetCntntNode() && GetPoint()->nContent == GetCntntNode()->Len() :
+ GetPoint()->nContent.GetIndex() == 0;
+
+ if( !bRet )
+ {
+ SwCursor aCrsr(*GetPoint(), 0, false);
+ SwPosition aOrigPos = *aCrsr.GetPoint();
+ aCrsr.GoSentence( bEnd ? SwCursor::END_SENT : SwCursor::START_SENT );
+ bRet = aOrigPos == *aCrsr.GetPoint();
+ }
+
+ return bRet;
+}
+
+sal_Bool SwCursor::GoStartWordWT( sal_Int16 nWordType )
+{
+ sal_Bool bRet = sal_False;
+ const SwTxtNode* pTxtNd = GetNode()->GetTxtNode();
+ if( pTxtNd && pBreakIt->GetBreakIter().is() )
+ {
+ SwCrsrSaveState aSave( *this );
+ xub_StrLen nPtPos = GetPoint()->nContent.GetIndex();
+ nPtPos = (xub_StrLen)pBreakIt->GetBreakIter()->getWordBoundary(
+ pTxtNd->GetTxt(), nPtPos,
+ pBreakIt->GetLocale( pTxtNd->GetLang( nPtPos ) ),
+ nWordType,
+ sal_False ).startPos;
+
+ if( nPtPos < pTxtNd->GetTxt().Len() )
+ {
+ GetPoint()->nContent = nPtPos;
+ if( !IsSelOvr() )
+ bRet = sal_True;
+ }
+ }
+ return bRet;
+}
+
+sal_Bool SwCursor::GoEndWordWT( sal_Int16 nWordType )
+{
+ sal_Bool bRet = sal_False;
+ const SwTxtNode* pTxtNd = GetNode()->GetTxtNode();
+ if( pTxtNd && pBreakIt->GetBreakIter().is() )
+ {
+ SwCrsrSaveState aSave( *this );
+ xub_StrLen nPtPos = GetPoint()->nContent.GetIndex();
+ nPtPos = (xub_StrLen)pBreakIt->GetBreakIter()->getWordBoundary(
+ pTxtNd->GetTxt(), nPtPos,
+ pBreakIt->GetLocale( pTxtNd->GetLang( nPtPos ) ),
+ nWordType,
+ sal_True ).endPos;
+
+ if( nPtPos <= pTxtNd->GetTxt().Len() &&
+ GetPoint()->nContent.GetIndex() != nPtPos )
+ {
+ GetPoint()->nContent = nPtPos;
+ if( !IsSelOvr() )
+ bRet = sal_True;
+ }
+ }
+ return bRet;
+}
+
+sal_Bool SwCursor::GoNextWordWT( sal_Int16 nWordType )
+{
+ sal_Bool bRet = sal_False;
+ const SwTxtNode* pTxtNd = GetNode()->GetTxtNode();
+ if( pTxtNd && pBreakIt->GetBreakIter().is() )
+ {
+ SwCrsrSaveState aSave( *this );
+ xub_StrLen nPtPos = GetPoint()->nContent.GetIndex();
+
+ nPtPos = (xub_StrLen)pBreakIt->GetBreakIter()->nextWord(
+ pTxtNd->GetTxt(), nPtPos,
+ pBreakIt->GetLocale( pTxtNd->GetLang( nPtPos, 1 ) ),
+ nWordType ).startPos;
+
+ if( nPtPos < pTxtNd->GetTxt().Len() )
+ {
+ GetPoint()->nContent = nPtPos;
+ if( !IsSelOvr() )
+ bRet = sal_True;
+ }
+ }
+ return bRet;
+}
+
+sal_Bool SwCursor::GoPrevWordWT( sal_Int16 nWordType )
+{
+ sal_Bool bRet = sal_False;
+ const SwTxtNode* pTxtNd = GetNode()->GetTxtNode();
+ if( pTxtNd && pBreakIt->GetBreakIter().is() )
+ {
+ SwCrsrSaveState aSave( *this );
+ xub_StrLen nPtPos = GetPoint()->nContent.GetIndex();
+ const xub_StrLen nPtStart = nPtPos;
+
+ if( nPtPos )
+ --nPtPos;
+ nPtPos = (xub_StrLen)pBreakIt->GetBreakIter()->previousWord(
+ pTxtNd->GetTxt(), nPtStart,
+ pBreakIt->GetLocale( pTxtNd->GetLang( nPtPos, 1 ) ),
+ nWordType ).startPos;
+
+ if( nPtPos < pTxtNd->GetTxt().Len() )
+ {
+ GetPoint()->nContent = nPtPos;
+ if( !IsSelOvr() )
+ bRet = sal_True;
+ }
+ }
+ return bRet;
+}
+
+sal_Bool SwCursor::SelectWordWT( ViewShell* pViewShell, sal_Int16 nWordType, const Point* pPt )
+{
+ SwCrsrSaveState aSave( *this );
+
+ sal_Bool bRet = sal_False;
+ sal_Bool bForward = sal_True;
+ DeleteMark();
+ const SwRootFrm* pLayout = pViewShell->GetLayout();
+ if( pPt && 0 != pLayout )
+ {
+ // set the cursor to the layout position
+ Point aPt( *pPt );
+ pLayout->GetCrsrOfst( GetPoint(), aPt );
+ } //swmod 071107//swmod 071225
+
+ const SwTxtNode* pTxtNd = GetNode()->GetTxtNode();
+ if( pTxtNd && pBreakIt->GetBreakIter().is() )
+ {
+ // Should we select the whole fieldmark?
+ const IDocumentMarkAccess* pMarksAccess = GetDoc()->getIDocumentMarkAccess( );
+ sw::mark::IMark* pMark = GetPoint() ? pMarksAccess->getFieldmarkFor( *GetPoint( ) ) : NULL;
+ if ( pMark )
+ {
+ const SwPosition rStart = pMark->GetMarkStart();
+ GetPoint()->nNode = rStart.nNode;
+ GetPoint()->nContent = rStart.nContent;
+ GetPoint()->nContent++; // Don't select the start delimiter
+
+ const SwPosition rEnd = pMark->GetMarkEnd();
+
+ if ( rStart != rEnd )
+ {
+ SetMark();
+ GetMark()->nNode = rEnd.nNode;
+ GetMark()->nContent = rEnd.nContent;
+ GetMark()->nContent--; //Don't select the end delimiter
+ }
+ bRet = sal_True;
+ }
+ else
+ {
+ xub_StrLen nPtPos = GetPoint()->nContent.GetIndex();
+ Boundary aBndry( pBreakIt->GetBreakIter()->getWordBoundary(
+ pTxtNd->GetTxt(), nPtPos,
+ pBreakIt->GetLocale( pTxtNd->GetLang( nPtPos ) ),
+ nWordType,
+ bForward ));
+
+ if( aBndry.startPos != aBndry.endPos )
+ {
+ GetPoint()->nContent = (xub_StrLen)aBndry.endPos;
+ if( !IsSelOvr() )
+ {
+ SetMark();
+ GetMark()->nContent = (xub_StrLen)aBndry.startPos;
+ if( !IsSelOvr() )
+ bRet = sal_True;
+ }
+ }
+ }
+ }
+
+ if( !bRet )
+ {
+ DeleteMark();
+ RestoreSavePos();
+ }
+ return bRet;
+}
+
+//-----------------------------------------------------------------------------
+
+static String lcl_MaskDeletedRedlines( const SwTxtNode* pTxtNd )
+{
+ String aRes;
+ if (pTxtNd)
+ {
+ //mask deleted redlines
+ String sNodeText(pTxtNd->GetTxt());
+ const SwDoc& rDoc = *pTxtNd->GetDoc();
+ const bool nShowChg = IDocumentRedlineAccess::IsShowChanges( rDoc.GetRedlineMode() );
+ if ( nShowChg )
+ {
+ sal_uInt16 nAct = rDoc.GetRedlinePos( *pTxtNd, USHRT_MAX );
+ for ( ; nAct < rDoc.GetRedlineTbl().Count(); nAct++ )
+ {
+ const SwRedline* pRed = rDoc.GetRedlineTbl()[ nAct ];
+ if ( pRed->Start()->nNode > pTxtNd->GetIndex() )
+ break;
+
+ if( nsRedlineType_t::REDLINE_DELETE == pRed->GetType() )
+ {
+ xub_StrLen nStart, nEnd;
+ pRed->CalcStartEnd( pTxtNd->GetIndex(), nStart, nEnd );
+
+ while ( nStart < nEnd && nStart < sNodeText.Len() )
+ sNodeText.SetChar( nStart++, CH_TXTATR_INWORD );
+ }
+ }
+ }
+ aRes = sNodeText;
+ }
+ return aRes;
+}
+
+sal_Bool SwCursor::GoSentence( SentenceMoveType eMoveType )
+{
+ sal_Bool bRet = sal_False;
+ const SwTxtNode* pTxtNd = GetNode()->GetTxtNode();
+ if( pTxtNd && pBreakIt->GetBreakIter().is() )
+ {
+ String sNodeText( lcl_MaskDeletedRedlines( pTxtNd ) );
+
+ SwCrsrSaveState aSave( *this );
+ xub_StrLen nPtPos = GetPoint()->nContent.GetIndex();
+ switch ( eMoveType )
+ {
+ case START_SENT: /* when modifying: see also ExpandToSentenceBorders below! */
+ nPtPos = (xub_StrLen)pBreakIt->GetBreakIter()->beginOfSentence(
+ sNodeText,
+ nPtPos, pBreakIt->GetLocale(
+ pTxtNd->GetLang( nPtPos ) ));
+ break;
+ case END_SENT: /* when modifying: see also ExpandToSentenceBorders below! */
+ nPtPos = (xub_StrLen)pBreakIt->GetBreakIter()->endOfSentence(
+ sNodeText,
+ nPtPos, pBreakIt->GetLocale(
+ pTxtNd->GetLang( nPtPos ) ));
+ break;
+ case NEXT_SENT:
+ {
+ nPtPos = (xub_StrLen)pBreakIt->GetBreakIter()->endOfSentence(
+ sNodeText,
+ nPtPos, pBreakIt->GetLocale(
+ pTxtNd->GetLang( nPtPos ) ));
+ while (nPtPos != (sal_uInt16) -1 && ++nPtPos < sNodeText.Len()
+ && sNodeText.GetChar(nPtPos)== ' ' /*isWhiteSpace( aTxt.GetChar(nPtPos)*/ )
+ ;
+ break;
+ }
+ case PREV_SENT:
+ nPtPos = (xub_StrLen)pBreakIt->GetBreakIter()->beginOfSentence(
+ sNodeText,
+ nPtPos, pBreakIt->GetLocale(
+ pTxtNd->GetLang( nPtPos ) ));
+ if (nPtPos == 0)
+ return sal_False; // the previous sentence is not in this paragraph
+ if (nPtPos > 0)
+ nPtPos = (xub_StrLen)pBreakIt->GetBreakIter()->beginOfSentence(
+ sNodeText,
+ nPtPos - 1, pBreakIt->GetLocale(
+ pTxtNd->GetLang( nPtPos ) ));
+ break;
+ }
+
+ // it is allowed to place the PaM just behind the last
+ // character in the text thus <= ...Len
+ if( nPtPos <= pTxtNd->GetTxt().Len() )
+ {
+ GetPoint()->nContent = nPtPos;
+ if( !IsSelOvr() )
+ bRet = sal_True;
+ }
+ }
+ return bRet;
+}
+
+
+sal_Bool SwCursor::ExpandToSentenceBorders()
+{
+ sal_Bool bRes = sal_False;
+ const SwTxtNode* pStartNd = Start()->nNode.GetNode().GetTxtNode();
+ const SwTxtNode* pEndNd = End()->nNode.GetNode().GetTxtNode();
+ if (pStartNd && pEndNd && pBreakIt->GetBreakIter().is())
+ {
+ if (!HasMark())
+ SetMark();
+
+ String sStartText( lcl_MaskDeletedRedlines( pStartNd ) );
+ String sEndText( pStartNd == pEndNd? sStartText : lcl_MaskDeletedRedlines( pEndNd ) );
+
+ SwCrsrSaveState aSave( *this );
+ xub_StrLen nStartPos = Start()->nContent.GetIndex();
+ xub_StrLen nEndPos = End()->nContent.GetIndex();
+
+ nStartPos = (xub_StrLen)pBreakIt->GetBreakIter()->beginOfSentence(
+ sStartText, nStartPos,
+ pBreakIt->GetLocale( pStartNd->GetLang( nStartPos ) ) );
+ nEndPos = (xub_StrLen)pBreakIt->GetBreakIter()->endOfSentence(
+ sEndText, nEndPos,
+ pBreakIt->GetLocale( pEndNd->GetLang( nEndPos ) ) );
+
+ // it is allowed to place the PaM just behind the last
+ // character in the text thus <= ...Len
+ bool bChanged = false;
+ if (nStartPos <= pStartNd->GetTxt().Len())
+ {
+ GetMark()->nContent = nStartPos;
+ bChanged = true;
+ }
+ if (nEndPos <= pEndNd->GetTxt().Len())
+ {
+ GetPoint()->nContent = nEndPos;
+ bChanged = true;
+ }
+ if (bChanged && !IsSelOvr())
+ bRes = sal_True;
+ }
+ return bRes;
+}
+
+
+sal_Bool SwTableCursor::LeftRight( sal_Bool bLeft, sal_uInt16 nCnt, sal_uInt16 /*nMode*/,
+ sal_Bool /*bVisualAllowed*/, sal_Bool /*bSkipHidden*/, sal_Bool /*bInsertCrsr*/ )
+{
+ return bLeft ? GoPrevCell( nCnt )
+ : GoNextCell( nCnt );
+}
+
+
+// calculate cursor bidi level: extracted from LeftRight()
+const SwCntntFrm*
+SwCursor::DoSetBidiLevelLeftRight(
+ sal_Bool & io_rbLeft, sal_Bool bVisualAllowed, sal_Bool bInsertCrsr)
+{
+ // calculate cursor bidi level
+ const SwCntntFrm* pSttFrm = NULL;
+ SwNode& rNode = GetPoint()->nNode.GetNode();
+
+ if( rNode.IsTxtNode() )
+ {
+ const SwTxtNode& rTNd = *rNode.GetTxtNode();
+ SwIndex& rIdx = GetPoint()->nContent;
+ xub_StrLen nPos = rIdx.GetIndex();
+
+ const SvtCTLOptions& rCTLOptions = SW_MOD()->GetCTLOptions();
+ if ( bVisualAllowed && rCTLOptions.IsCTLFontEnabled() &&
+ SvtCTLOptions::MOVEMENT_VISUAL ==
+ rCTLOptions.GetCTLCursorMovement() )
+ {
+ // for visual cursor travelling (used in bidi layout)
+ // we first have to convert the logic to a visual position
+ Point aPt;
+ pSttFrm = rTNd.getLayoutFrm( GetDoc()->GetCurrentLayout(), &aPt, GetPoint() );
+ if( pSttFrm )
+ {
+ sal_uInt8 nCrsrLevel = GetCrsrBidiLevel();
+ sal_Bool bForward = ! io_rbLeft;
+ ((SwTxtFrm*)pSttFrm)->PrepareVisualMove( nPos, nCrsrLevel,
+ bForward, bInsertCrsr );
+ rIdx = nPos;
+ SetCrsrBidiLevel( nCrsrLevel );
+ io_rbLeft = ! bForward;
+ }
+ }
+ else
+ {
+ const SwScriptInfo* pSI = SwScriptInfo::GetScriptInfo( rTNd );
+ if ( pSI )
+ {
+ const xub_StrLen nMoveOverPos = io_rbLeft ?
+ ( nPos ? nPos - 1 : 0 ) :
+ nPos;
+ SetCrsrBidiLevel( pSI->DirType( nMoveOverPos ) );
+ }
+ }
+ }
+ return pSttFrm;
+}
+
+sal_Bool SwCursor::LeftRight( sal_Bool bLeft, sal_uInt16 nCnt, sal_uInt16 nMode,
+ sal_Bool bVisualAllowed,sal_Bool bSkipHidden, sal_Bool bInsertCrsr )
+{
+ // calculate cursor bidi level
+ SwNode& rNode = GetPoint()->nNode.GetNode();
+ const SwCntntFrm* pSttFrm = // may side-effect bLeft!
+ DoSetBidiLevelLeftRight(bLeft, bVisualAllowed, bInsertCrsr);
+
+ // kann der Cursor n-mal weiterverschoben werden ?
+ SwCrsrSaveState aSave( *this );
+ SwMoveFn fnMove = bLeft ? fnMoveBackward : fnMoveForward;
+
+ SwGoInDoc fnGo;
+ if ( bSkipHidden )
+ fnGo = CRSR_SKIP_CELLS == nMode ? fnGoCntntCellsSkipHidden : fnGoCntntSkipHidden;
+ else
+ fnGo = CRSR_SKIP_CELLS == nMode ? fnGoCntntCells : fnGoCntnt;
+
+ // OSL_ENSURE( not in covered cell )
+
+ while( nCnt )
+ {
+ SwNodeIndex aOldNodeIdx( GetPoint()->nNode );
+
+ bool bSuccess = Move( fnMove, fnGo );
+ if ( !bSuccess )
+ break;
+
+ // If we were located inside a covered cell but our position has been
+ // corrected, we check if the last move has moved the cursor to a different
+ // table cell. In this case we set the cursor to the stored covered position
+ // and redo the move:
+ if ( mnRowSpanOffset )
+ {
+ const SwNode* pOldTabBoxSttNode = aOldNodeIdx.GetNode().FindTableBoxStartNode();
+ const SwTableNode* pOldTabSttNode = pOldTabBoxSttNode ? pOldTabBoxSttNode->FindTableNode() : 0;
+ const SwNode* pNewTabBoxSttNode = GetPoint()->nNode.GetNode().FindTableBoxStartNode();
+ const SwTableNode* pNewTabSttNode = pNewTabBoxSttNode ? pNewTabBoxSttNode->FindTableNode() : 0;
+
+ const bool bCellChanged = pOldTabSttNode && pNewTabSttNode &&
+ pOldTabSttNode == pNewTabSttNode &&
+ pOldTabBoxSttNode && pNewTabBoxSttNode &&
+ pOldTabBoxSttNode != pNewTabBoxSttNode;
+
+ if ( bCellChanged )
+ {
+ // Set cursor to start/end of covered cell:
+ SwTableBox* pTableBox = pOldTabBoxSttNode->GetTblBox();
+ const long nRowSpan = pTableBox->getRowSpan();
+ if ( nRowSpan > 1 )
+ {
+ pTableBox = & pTableBox->FindEndOfRowSpan( pOldTabSttNode->GetTable(), (sal_uInt16)(pTableBox->getRowSpan() + mnRowSpanOffset ) );
+ SwNodeIndex& rPtIdx = GetPoint()->nNode;
+ SwNodeIndex aNewIdx( *pTableBox->GetSttNd() );
+ rPtIdx = aNewIdx;
+
+ GetDoc()->GetNodes().GoNextSection( &rPtIdx, sal_False, sal_False );
+ SwCntntNode* pCntntNode = GetCntntNode();
+ if ( pCntntNode )
+ {
+ const xub_StrLen nTmpPos = bLeft ? pCntntNode->Len() : 0;
+ GetPoint()->nContent.Assign( pCntntNode, nTmpPos );
+
+ // Redo the move:
+ bSuccess = Move( fnMove, fnGo );
+ if ( !bSuccess )
+ break;
+ }
+ }
+
+ mnRowSpanOffset = 0;
+ }
+ }
+
+ // Check if I'm inside a covered cell. Correct cursor if necessary and
+ // store covered cell:
+ const SwNode* pTableBoxStartNode = GetPoint()->nNode.GetNode().FindTableBoxStartNode();
+ if ( pTableBoxStartNode )
+ {
+ const SwTableBox* pTableBox = pTableBoxStartNode->GetTblBox();
+ if ( pTableBox && pTableBox->getRowSpan() < 1 )
+ {
+ // Store the row span offset:
+ mnRowSpanOffset = pTableBox->getRowSpan();
+
+ // Move cursor to non-covered cell:
+ const SwTableNode* pTblNd = pTableBoxStartNode->FindTableNode();
+ pTableBox = & pTableBox->FindStartOfRowSpan( pTblNd->GetTable(), USHRT_MAX );
+ SwNodeIndex& rPtIdx = GetPoint()->nNode;
+ SwNodeIndex aNewIdx( *pTableBox->GetSttNd() );
+ rPtIdx = aNewIdx;
+
+ GetDoc()->GetNodes().GoNextSection( &rPtIdx, sal_False, sal_False );
+ SwCntntNode* pCntntNode = GetCntntNode();
+ if ( pCntntNode )
+ {
+ const xub_StrLen nTmpPos = bLeft ? pCntntNode->Len() : 0;
+ GetPoint()->nContent.Assign( pCntntNode, nTmpPos );
+ }
+ }
+ }
+
+ --nCnt;
+ }
+
+ // here come some special rules for visual cursor travelling
+ if ( pSttFrm )
+ {
+ SwNode& rTmpNode = GetPoint()->nNode.GetNode();
+ if ( &rTmpNode != &rNode && rTmpNode.IsTxtNode() )
+ {
+ Point aPt;
+ const SwCntntFrm* pEndFrm = ((SwTxtNode&)rTmpNode).getLayoutFrm( GetDoc()->GetCurrentLayout(), &aPt, GetPoint() );
+ if ( pEndFrm )
+ {
+ if ( ! pEndFrm->IsRightToLeft() != ! pSttFrm->IsRightToLeft() )
+ {
+ if ( ! bLeft )
+ pEndFrm->RightMargin( this );
+ else
+ pEndFrm->LeftMargin( this );
+ }
+ }
+ }
+ }
+
+ return 0 == nCnt && !IsInProtectTable( sal_True ) &&
+ !IsSelOvr( nsSwCursorSelOverFlags::SELOVER_TOGGLE |
+ nsSwCursorSelOverFlags::SELOVER_CHANGEPOS );
+}
+
+// calculate cursor bidi level: extracted from UpDown()
+void SwCursor::DoSetBidiLevelUpDown()
+{
+ SwNode& rNode = GetPoint()->nNode.GetNode();
+ if ( rNode.IsTxtNode() )
+ {
+ const SwScriptInfo* pSI =
+ SwScriptInfo::GetScriptInfo( (SwTxtNode&)rNode );
+ if ( pSI )
+ {
+ SwIndex& rIdx = GetPoint()->nContent;
+ xub_StrLen nPos = rIdx.GetIndex();
+
+ if( nPos && nPos < ((SwTxtNode&)rNode).GetTxt().Len() )
+ {
+ const sal_uInt8 nCurrLevel = pSI->DirType( nPos );
+ const sal_uInt8 nPrevLevel = pSI->DirType( nPos - 1 );
+
+ if ( nCurrLevel % 2 != nPrevLevel % 2 )
+ {
+ // set cursor level to the lower of the two levels
+ SetCrsrBidiLevel( Min( nCurrLevel, nPrevLevel ) );
+ }
+ else
+ SetCrsrBidiLevel( nCurrLevel );
+ }
+ }
+ }
+}
+
+sal_Bool SwCursor::UpDown( sal_Bool bUp, sal_uInt16 nCnt,
+ Point* pPt, long nUpDownX )
+{
+ SwTableCursor* pTblCrsr = dynamic_cast<SwTableCursor*>(this);
+ sal_Bool bAdjustTableCrsr = sal_False;
+
+ // vom Tabellen Crsr Point/Mark in der gleichen Box ??
+ // dann stelle den Point an den Anfang der Box
+ if( pTblCrsr && GetNode( sal_True )->StartOfSectionNode() ==
+ GetNode( sal_False )->StartOfSectionNode() )
+ {
+ if ( End() != GetPoint() )
+ Exchange();
+ bAdjustTableCrsr = sal_True;
+ }
+
+ sal_Bool bRet = sal_False;
+ Point aPt;
+ if( pPt )
+ aPt = *pPt;
+ SwCntntFrm* pFrm = GetCntntNode()->getLayoutFrm( GetDoc()->GetCurrentLayout(), &aPt, GetPoint() );
+
+ if( pFrm )
+ {
+ SwCrsrSaveState aSave( *this );
+
+ if( !pPt )
+ {
+ SwRect aTmpRect;
+ pFrm->GetCharRect( aTmpRect, *GetPoint() );
+ aPt = aTmpRect.Pos();
+
+ nUpDownX = pFrm->IsVertical() ?
+ aPt.Y() - pFrm->Frm().Top() :
+ aPt.X() - pFrm->Frm().Left();
+ }
+
+ // Bei Fussnoten ist auch die Bewegung in eine andere Fussnote erlaubt.
+ // aber keine Selection!!
+ const sal_Bool bChkRange = pFrm->IsInFtn() && !HasMark()
+ ? sal_False : sal_True;
+ const SwPosition aOldPos( *GetPoint() );
+ sal_Bool bInReadOnly = IsReadOnlyAvailable();
+
+ if ( bAdjustTableCrsr && !bUp )
+ {
+ // Special case: We have a table cursor but the start box
+ // has more than one paragraph. If we want to go down, we have to
+ // set the point to the last frame in the table box. This is
+ // only necessary if we do not already have a table selection
+ const SwStartNode* pTblNd = GetNode( sal_True )->FindTableBoxStartNode();
+ OSL_ENSURE( pTblNd, "pTblCrsr without SwTableNode?" );
+
+ if ( pTblNd ) // safety first
+ {
+ const SwNode* pEndNd = pTblNd->EndOfSectionNode();
+ GetPoint()->nNode = *pEndNd;
+ pTblCrsr->Move( fnMoveBackward, fnGoNode );
+ pFrm = GetCntntNode()->getLayoutFrm( GetDoc()->GetCurrentLayout(), &aPt, GetPoint() );
+ }
+ }
+
+ while( nCnt &&
+ (bUp ? pFrm->UnitUp( this, nUpDownX, bInReadOnly )
+ : pFrm->UnitDown( this, nUpDownX, bInReadOnly ) ) &&
+ CheckNodesRange( aOldPos.nNode, GetPoint()->nNode, bChkRange ))
+ {
+ pFrm = GetCntntNode()->getLayoutFrm( GetDoc()->GetCurrentLayout(), &aPt, GetPoint() );
+ --nCnt;
+ }
+
+ if( !nCnt && !IsSelOvr( nsSwCursorSelOverFlags::SELOVER_TOGGLE |
+ nsSwCursorSelOverFlags::SELOVER_CHANGEPOS ) ) // die gesamte Anzahl durchlaufen ?
+ {
+ if( !pTblCrsr )
+ {
+ // dann versuche den Cursor auf die Position zu setzen,
+ // auf halber Heohe vom Char-Rectangle
+ pFrm = GetCntntNode()->getLayoutFrm( GetDoc()->GetCurrentLayout(), &aPt, GetPoint() );
+ SwCrsrMoveState eTmpState( MV_UPDOWN );
+ eTmpState.bSetInReadOnly = bInReadOnly;
+ SwRect aTmpRect;
+ pFrm->GetCharRect( aTmpRect, *GetPoint(), &eTmpState );
+ if ( pFrm->IsVertical() )
+ {
+ aPt.X() = aTmpRect.Center().X();
+ pFrm->Calc();
+ aPt.Y() = pFrm->Frm().Top() + nUpDownX;
+ }
+ else
+ {
+ aPt.Y() = aTmpRect.Center().Y();
+ pFrm->Calc();
+ aPt.X() = pFrm->Frm().Left() + nUpDownX;
+ }
+ pFrm->GetCrsrOfst( GetPoint(), aPt, &eTmpState );
+ }
+ bRet = sal_True;
+ }
+ else
+ *GetPoint() = aOldPos;
+
+ DoSetBidiLevelUpDown(); // calculate cursor bidi level
+ }
+
+ return bRet;
+}
+
+sal_Bool SwCursor::LeftRightMargin( sal_Bool bLeft, sal_Bool bAPI )
+{
+ Point aPt;
+ SwCntntFrm * pFrm = GetCntntNode()->getLayoutFrm( GetDoc()->GetCurrentLayout(), &aPt, GetPoint() );
+
+ // calculate cursor bidi level
+ if ( pFrm )
+ SetCrsrBidiLevel( pFrm->IsRightToLeft() ? 1 : 0 );
+
+ return pFrm && (bLeft ? pFrm->LeftMargin( this ) :
+ pFrm->RightMargin( this, bAPI ) );
+}
+
+sal_Bool SwCursor::IsAtLeftRightMargin( sal_Bool bLeft, sal_Bool bAPI ) const
+{
+ sal_Bool bRet = sal_False;
+ Point aPt;
+ SwCntntFrm * pFrm = GetCntntNode()->getLayoutFrm( GetDoc()->GetCurrentLayout(), &aPt, GetPoint() );
+ if( pFrm )
+ {
+ SwPaM aPam( *GetPoint() );
+ if( !bLeft && aPam.GetPoint()->nContent.GetIndex() )
+ aPam.GetPoint()->nContent--;
+ bRet = (bLeft ? pFrm->LeftMargin( &aPam )
+ : pFrm->RightMargin( &aPam, bAPI ))
+ && *aPam.GetPoint() == *GetPoint();
+ }
+ return bRet;
+}
+
+sal_Bool SwCursor::SttEndDoc( sal_Bool bStt )
+{
+ SwCrsrSaveState aSave( *this );
+
+ // Springe beim Selektieren nie ueber Section-Grenzen !!
+ // kann der Cursor weiterverschoben werden ?
+ SwMoveFn fnMove = bStt ? fnMoveBackward : fnMoveForward;
+ sal_Bool bRet = (!HasMark() || !IsNoCntnt() ) &&
+ Move( fnMove, fnGoDoc ) &&
+ !IsInProtectTable( sal_True ) &&
+ !IsSelOvr( nsSwCursorSelOverFlags::SELOVER_TOGGLE |
+ nsSwCursorSelOverFlags::SELOVER_CHANGEPOS |
+ nsSwCursorSelOverFlags::SELOVER_ENABLEREVDIREKTION );
+
+ return bRet;
+}
+
+sal_Bool SwCursor::GoPrevNextCell( sal_Bool bNext, sal_uInt16 nCnt )
+{
+ const SwTableNode* pTblNd = GetPoint()->nNode.GetNode().FindTableNode();
+ if( !pTblNd )
+ return sal_False;
+
+ // liegt vor dem StartNode der Cell ein weiterer EndNode, dann
+ // gibt es auch eine vorherige Celle
+ SwCrsrSaveState aSave( *this );
+ SwNodeIndex& rPtIdx = GetPoint()->nNode;
+
+ while( nCnt-- )
+ {
+ const SwNode* pTableBoxStartNode = rPtIdx.GetNode().FindTableBoxStartNode();
+ const SwTableBox* pTableBox = pTableBoxStartNode->GetTblBox();
+
+ // Check if we have to move the cursor to a covered cell before
+ // proceeding:
+ if ( mnRowSpanOffset )
+ {
+ if ( pTableBox->getRowSpan() > 1 )
+ {
+ pTableBox = & pTableBox->FindEndOfRowSpan( pTblNd->GetTable(), (sal_uInt16)(pTableBox->getRowSpan() + mnRowSpanOffset) );
+ SwNodeIndex aNewIdx( *pTableBox->GetSttNd() );
+ rPtIdx = aNewIdx;
+ pTableBoxStartNode = rPtIdx.GetNode().FindTableBoxStartNode();
+ }
+ mnRowSpanOffset = 0;
+ }
+
+ const SwNode* pTmpNode = bNext ?
+ pTableBoxStartNode->EndOfSectionNode() :
+ pTableBoxStartNode;
+
+ SwNodeIndex aCellIdx( *pTmpNode, bNext ? 1 : -1 );
+ if( (bNext && !aCellIdx.GetNode().IsStartNode()) ||
+ (!bNext && !aCellIdx.GetNode().IsEndNode()) )
+ return sal_False;
+
+ rPtIdx = bNext ? aCellIdx : SwNodeIndex(*aCellIdx.GetNode().StartOfSectionNode());
+
+ pTableBoxStartNode = rPtIdx.GetNode().FindTableBoxStartNode();
+ pTableBox = pTableBoxStartNode->GetTblBox();
+ if ( pTableBox->getRowSpan() < 1 )
+ {
+ mnRowSpanOffset = pTableBox->getRowSpan();
+ // move cursor to non-covered cell:
+ pTableBox = & pTableBox->FindStartOfRowSpan( pTblNd->GetTable(), USHRT_MAX );
+ SwNodeIndex aNewIdx( *pTableBox->GetSttNd() );
+ rPtIdx = aNewIdx;
+ }
+ }
+
+ rPtIdx++;
+ if( !rPtIdx.GetNode().IsCntntNode() )
+ GetDoc()->GetNodes().GoNextSection( &rPtIdx, sal_True, sal_False );
+ GetPoint()->nContent.Assign( GetCntntNode(), 0 );
+
+ return !IsInProtectTable( sal_True );
+}
+
+sal_Bool SwTableCursor::GotoTable( const String& /*rName*/ )
+{
+ return sal_False; // invalid action
+}
+
+sal_Bool SwCursor::GotoTable( const String& rName )
+{
+ sal_Bool bRet = sal_False;
+ if ( !HasMark() )
+ {
+ SwTable* pTmpTbl = SwTable::FindTable( GetDoc()->FindTblFmtByName( rName ) );
+ if( pTmpTbl )
+ {
+ // eine Tabelle im normalen NodesArr
+ SwCrsrSaveState aSave( *this );
+ GetPoint()->nNode = *pTmpTbl->GetTabSortBoxes()[ 0 ]->
+ GetSttNd()->FindTableNode();
+ Move( fnMoveForward, fnGoCntnt );
+ bRet = !IsSelOvr();
+ }
+ }
+ return bRet;
+}
+
+sal_Bool SwCursor::GotoTblBox( const String& rName )
+{
+ sal_Bool bRet = sal_False;
+ const SwTableNode* pTblNd = GetPoint()->nNode.GetNode().FindTableNode();
+ if( pTblNd )
+ {
+ // erfrage die Box, mit dem Nanen
+ const SwTableBox* pTblBox = pTblNd->GetTable().GetTblBox( rName );
+ if( pTblBox && pTblBox->GetSttNd() &&
+ ( !pTblBox->GetFrmFmt()->GetProtect().IsCntntProtected() ||
+ IsReadOnlyAvailable() ) )
+ {
+ SwCrsrSaveState aSave( *this );
+ GetPoint()->nNode = *pTblBox->GetSttNd();
+ Move( fnMoveForward, fnGoCntnt );
+ bRet = !IsSelOvr();
+ }
+ }
+ return bRet;
+}
+
+sal_Bool SwCursor::MovePara(SwWhichPara fnWhichPara, SwPosPara fnPosPara )
+{
+ //for optimization test something before
+ const SwNode* pNd = &GetPoint()->nNode.GetNode();
+ bool bShortCut = false;
+ if ( fnWhichPara == fnParaCurr )
+ {
+ // --> FME 2005-02-21 #i41048#
+ // If fnWhichPara == fnParaCurr, (*fnWhichPara)( *this, fnPosPara )
+ // can already move the cursor to a different text node. In this case
+ // we better check if IsSelOvr().
+ const SwCntntNode* pCntntNd = pNd->GetCntntNode();
+ if ( pCntntNd )
+ {
+ const xub_StrLen nSttEnd = fnPosPara == fnMoveForward ? 0 : pCntntNd->Len();
+ if ( GetPoint()->nContent.GetIndex() != nSttEnd )
+ bShortCut = true;
+ }
+ // <--
+ }
+ else
+ {
+ if ( pNd->IsTxtNode() &&
+ pNd->GetNodes()[ pNd->GetIndex() +
+ (fnWhichPara == fnParaNext ? 1 : -1 ) ]->IsTxtNode() )
+ bShortCut = true;
+ }
+
+ if ( bShortCut )
+ return (*fnWhichPara)( *this, fnPosPara );
+
+ // else we must use the SaveStructure, because the next/prev is not
+ // a same node type.
+ SwCrsrSaveState aSave( *this );
+ return (*fnWhichPara)( *this, fnPosPara ) &&
+ !IsInProtectTable( sal_True ) &&
+ !IsSelOvr( nsSwCursorSelOverFlags::SELOVER_TOGGLE |
+ nsSwCursorSelOverFlags::SELOVER_CHANGEPOS );
+}
+
+
+sal_Bool SwCursor::MoveSection( SwWhichSection fnWhichSect,
+ SwPosSection fnPosSect)
+{
+ SwCrsrSaveState aSave( *this );
+ return (*fnWhichSect)( *this, fnPosSect ) &&
+ !IsInProtectTable( sal_True ) &&
+ !IsSelOvr( nsSwCursorSelOverFlags::SELOVER_TOGGLE |
+ nsSwCursorSelOverFlags::SELOVER_CHANGEPOS );
+}
+
+void SwCursor::RestoreSavePos()
+{
+ if( pSavePos )
+ {
+ GetPoint()->nNode = pSavePos->nNode;
+ GetPoint()->nContent.Assign( GetCntntNode(), pSavePos->nCntnt );
+ }
+}
+
+
+/* */
+
+SwTableCursor::SwTableCursor( const SwPosition &rPos, SwPaM* pRing )
+ : SwCursor( rPos, pRing, false )
+{
+ bParked = sal_False;
+ bChg = sal_False;
+ nTblPtNd = 0, nTblMkNd = 0;
+ nTblPtCnt = 0, nTblMkCnt = 0;
+}
+
+SwTableCursor::~SwTableCursor() {}
+
+
+sal_Bool lcl_SeekEntry( const SwSelBoxes& rTmp, const SwStartNode* pSrch, sal_uInt16& rFndPos )
+{
+ sal_uLong nIdx = pSrch->GetIndex();
+
+ sal_uInt16 nO = rTmp.Count();
+ if( nO > 0 )
+ {
+ nO--;
+ sal_uInt16 nU = 0;
+ while( nU <= nO )
+ {
+ sal_uInt16 nM = nU + ( nO - nU ) / 2;
+ if( rTmp[ nM ]->GetSttNd() == pSrch )
+ {
+ rFndPos = nM;
+ return sal_True;
+ }
+ else if( rTmp[ nM ]->GetSttIdx() < nIdx )
+ nU = nM + 1;
+ else if( nM == 0 )
+ return sal_False;
+ else
+ nO = nM - 1;
+ }
+ }
+ return sal_False;
+}
+
+
+SwCursor* SwTableCursor::MakeBoxSels( SwCursor* pAktCrsr )
+{
+ if( bChg ) // ???
+ {
+ if( bParked )
+ {
+ // wieder in den Inhalt schieben
+ Exchange();
+ Move( fnMoveForward );
+ Exchange();
+ Move( fnMoveForward );
+ bParked = sal_False;
+ }
+
+ bChg = sal_False;
+
+ // temp Kopie anlegen, damit alle Boxen, fuer die schon Cursor
+ // existieren, entfernt werden koennen.
+ SwSelBoxes aTmp;
+ aTmp.Insert( &aSelBoxes );
+
+ //Jetzt die Alten und die neuen abgleichen.
+ SwNodes& rNds = pAktCrsr->GetDoc()->GetNodes();
+ sal_uInt16 nPos;
+ const SwStartNode* pSttNd;
+ SwPaM* pCur = pAktCrsr;
+ do {
+ sal_Bool bDel = sal_False;
+ pSttNd = pCur->GetPoint()->nNode.GetNode().FindTableBoxStartNode();
+ if( !pCur->HasMark() || !pSttNd ||
+ pSttNd != pCur->GetMark()->nNode.GetNode().FindTableBoxStartNode() )
+ bDel = sal_True;
+
+ else if( lcl_SeekEntry( aTmp, pSttNd, nPos ))
+ {
+ SwNodeIndex aIdx( *pSttNd, 1 );
+ const SwNode* pNd = &aIdx.GetNode();
+ if( !pNd->IsCntntNode() )
+ pNd = rNds.GoNextSection( &aIdx, sal_True, sal_False );
+
+ SwPosition* pPos = pCur->GetMark();
+ if( pNd != &pPos->nNode.GetNode() )
+ pPos->nNode = *pNd;
+ pPos->nContent.Assign( (SwCntntNode*)pNd, 0 );
+
+ aIdx.Assign( *pSttNd->EndOfSectionNode(), - 1 );
+ if( !( pNd = &aIdx.GetNode())->IsCntntNode() )
+ pNd = rNds.GoPrevSection( &aIdx, sal_True, sal_False );
+
+ pPos = pCur->GetPoint();
+ if( pNd != &pPos->nNode.GetNode() )
+ pPos->nNode = *pNd;
+ pPos->nContent.Assign( (SwCntntNode*)pNd, ((SwCntntNode*)pNd)->Len() );
+
+ aTmp.Remove( nPos );
+ }
+ else
+ bDel = sal_True;
+
+ pCur = (SwPaM*)pCur->GetNext();
+ if( bDel )
+ {
+ SwPaM* pDel = (SwPaM*)pCur->GetPrev();
+
+ if( pDel == pAktCrsr )
+ pAktCrsr->DeleteMark();
+ else
+ delete pDel;
+ }
+ } while ( pAktCrsr != pCur );
+
+ for( nPos = 0; nPos < aTmp.Count(); ++nPos )
+ {
+ pSttNd = aTmp[ nPos ]->GetSttNd();
+
+ SwNodeIndex aIdx( *pSttNd, 1 );
+ if( &aIdx.GetNodes() != &rNds )
+ break;
+ const SwNode* pNd = &aIdx.GetNode();
+ if( !pNd->IsCntntNode() )
+ pNd = rNds.GoNextSection( &aIdx, sal_True, sal_False );
+
+ SwPaM* pNew;
+ if( pAktCrsr->GetNext() == pAktCrsr && !pAktCrsr->HasMark() )
+ {
+ pNew = pAktCrsr;
+ pNew->GetPoint()->nNode = *pNd;
+ pNew->GetPoint()->nContent.Assign( (SwCntntNode*)pNd, 0 );
+ }
+ else
+ {
+ pNew = pAktCrsr->Create( pAktCrsr );
+ pNew->GetPoint()->nNode = *pNd;
+ pNew->GetPoint()->nContent.Assign( (SwCntntNode*)pNd, 0 );
+ }
+ pNew->SetMark();
+
+ SwPosition* pPos = pNew->GetPoint();
+ pPos->nNode.Assign( *pSttNd->EndOfSectionNode(), - 1 );
+ if( !( pNd = &pPos->nNode.GetNode())->IsCntntNode() )
+ pNd = rNds.GoPrevSection( &pPos->nNode, sal_True, sal_False );
+
+ pPos->nContent.Assign( (SwCntntNode*)pNd, ((SwCntntNode*)pNd)->Len() );
+ }
+ }
+ return pAktCrsr;
+}
+
+
+void SwTableCursor::InsertBox( const SwTableBox& rTblBox )
+{
+ SwTableBox* pBox = (SwTableBox*)&rTblBox;
+ aSelBoxes.Insert( pBox );
+ bChg = sal_True;
+}
+
+bool SwTableCursor::NewTableSelection()
+{
+ bool bRet = false;
+ const SwNode *pStart = GetCntntNode()->FindTableBoxStartNode();
+ const SwNode *pEnd = GetCntntNode(sal_False)->FindTableBoxStartNode();
+ if( pStart && pEnd )
+ {
+ const SwTableNode *pTableNode = pStart->FindTableNode();
+ if( pTableNode == pEnd->FindTableNode() &&
+ pTableNode->GetTable().IsNewModel() )
+ {
+ bRet = true;
+ SwSelBoxes aNew;
+ aNew.Insert( &aSelBoxes );
+ pTableNode->GetTable().CreateSelection( pStart, pEnd, aNew,
+ SwTable::SEARCH_NONE, false );
+ ActualizeSelection( aNew );
+ }
+ }
+ return bRet;
+}
+
+void SwTableCursor::ActualizeSelection( const SwSelBoxes &rNew )
+{
+ sal_uInt16 nOld = 0, nNew = 0;
+ while ( nOld < aSelBoxes.Count() && nNew < rNew.Count() )
+ {
+ const SwTableBox* pPOld = *( aSelBoxes.GetData() + nOld );
+ const SwTableBox* pPNew = *( rNew.GetData() + nNew );
+ if( pPOld == pPNew )
+ { // this box will stay
+ ++nOld;
+ ++nNew;
+ }
+ else if( pPOld->GetSttIdx() < pPNew->GetSttIdx() )
+ DeleteBox( nOld ); // this box has to go
+ else
+ {
+ InsertBox( *pPNew ); // this is a new one
+ ++nOld;
+ ++nNew;
+ }
+ }
+
+ while( nOld < aSelBoxes.Count() )
+ DeleteBox( nOld ); // some more to delete
+
+ for( ; nNew < rNew.Count(); ++nNew ) // some more to insert
+ InsertBox( **( rNew.GetData() + nNew ) );
+}
+
+sal_Bool SwTableCursor::IsCrsrMovedUpdt()
+{
+ if( !IsCrsrMoved() )
+ return sal_False;
+
+ nTblMkNd = GetMark()->nNode.GetIndex();
+ nTblPtNd = GetPoint()->nNode.GetIndex();
+ nTblMkCnt = GetMark()->nContent.GetIndex();
+ nTblPtCnt = GetPoint()->nContent.GetIndex();
+ return sal_True;
+}
+
+
+// Parke den Tabellen-Cursor auf dem StartNode der Boxen.
+void SwTableCursor::ParkCrsr()
+{
+ // Index aus dem TextNode abmelden
+ SwNode* pNd = &GetPoint()->nNode.GetNode();
+ if( !pNd->IsStartNode() )
+ pNd = pNd->StartOfSectionNode();
+ GetPoint()->nNode = *pNd;
+ GetPoint()->nContent.Assign( 0, 0 );
+
+ pNd = &GetMark()->nNode.GetNode();
+ if( !pNd->IsStartNode() )
+ pNd = pNd->StartOfSectionNode();
+ GetMark()->nNode = *pNd;
+ GetMark()->nContent.Assign( 0, 0 );
+
+ bChg = sal_True;
+ bParked = sal_True;
+}
+
+
+sal_Bool SwTableCursor::HasReadOnlyBoxSel() const
+{
+ sal_Bool bRet = sal_False;
+ for( sal_uInt16 n = aSelBoxes.Count(); n; )
+ if( aSelBoxes[ --n ]->GetFrmFmt()->GetProtect().IsCntntProtected() )
+ {
+ bRet = sal_True;
+ break;
+ }
+ return bRet;
+}
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/crsr/trvlcol.cxx b/sw/source/core/crsr/trvlcol.cxx
new file mode 100644
index 000000000000..855b2d26b495
--- /dev/null
+++ b/sw/source/core/crsr/trvlcol.cxx
@@ -0,0 +1,135 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+
+
+#include <crsrsh.hxx>
+#include <doc.hxx>
+#include <layfrm.hxx>
+#include <cntfrm.hxx>
+#include <swcrsr.hxx>
+#include <viscrs.hxx>
+#include <callnk.hxx>
+
+
+
+SwLayoutFrm* GetCurrColumn( const SwLayoutFrm* pLayFrm )
+{
+ while( pLayFrm && !pLayFrm->IsColumnFrm() )
+ pLayFrm = pLayFrm->GetUpper();
+ return (SwLayoutFrm*)pLayFrm;
+}
+
+
+SwLayoutFrm* GetNextColumn( const SwLayoutFrm* pLayFrm )
+{
+ SwLayoutFrm* pActCol = GetCurrColumn( pLayFrm );
+ return pActCol ? (SwLayoutFrm*)pActCol->GetNext() : 0;
+}
+
+
+SwLayoutFrm* GetPrevColumn( const SwLayoutFrm* pLayFrm )
+{
+ SwLayoutFrm* pActCol = GetCurrColumn( pLayFrm );
+ return pActCol ? (SwLayoutFrm*)pActCol->GetPrev() : 0;
+}
+
+
+SwCntntFrm* GetColumnStt( const SwLayoutFrm* pColFrm )
+{
+ return pColFrm ? (SwCntntFrm*)pColFrm->ContainsCntnt() : 0;
+}
+
+
+SwCntntFrm* GetColumnEnd( const SwLayoutFrm* pColFrm )
+{
+ SwCntntFrm *pRet = GetColumnStt( pColFrm );
+ if( !pRet )
+ return 0;
+
+ SwCntntFrm *pNxt = pRet->GetNextCntntFrm();
+ while( pNxt && pColFrm->IsAnLower( pNxt ) )
+ {
+ pRet = pNxt;
+ pNxt = pNxt->GetNextCntntFrm();
+ }
+ return pRet;
+}
+
+
+SwWhichColumn fnColumnPrev = &GetPrevColumn;
+SwWhichColumn fnColumnCurr = &GetCurrColumn;
+SwWhichColumn fnColumnNext = &GetNextColumn;
+SwPosColumn fnColumnStart = &GetColumnStt;
+SwPosColumn fnColumnEnd = &GetColumnEnd;
+
+
+sal_Bool SwCrsrShell::MoveColumn( SwWhichColumn fnWhichCol, SwPosColumn fnPosCol )
+{
+ sal_Bool bRet = sal_False;
+ if( !pTblCrsr )
+ {
+ SwLayoutFrm* pLayFrm = GetCurrFrm()->GetUpper();
+ if( pLayFrm && 0 != ( pLayFrm = (*fnWhichCol)( pLayFrm )) )
+ {
+ SwCntntFrm* pCnt = (*fnPosCol)( pLayFrm );
+ if( pCnt )
+ {
+ SET_CURR_SHELL( this );
+ SwCallLink aLk( *this ); // Crsr-Moves ueberwachen, evt. Link callen
+ SwCrsrSaveState aSaveState( *pCurCrsr );
+
+ pCnt->Calc(); // ???
+
+ Point aPt( pCnt->Frm().Pos() + pCnt->Prt().Pos() );
+ if( fnPosCol == GetColumnEnd )
+ {
+ aPt.X() += pCnt->Prt().Width();
+ aPt.Y() += pCnt->Prt().Height();
+ }
+
+ pCnt->GetCrsrOfst( pCurCrsr->GetPoint(), aPt );
+
+ if( !pCurCrsr->IsInProtectTable( sal_True ) &&
+ !pCurCrsr->IsSelOvr() )
+ {
+ UpdateCrsr();
+ bRet = sal_True;
+ }
+ }
+ }
+ }
+ return bRet;
+}
+
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/crsr/trvlfnfl.cxx b/sw/source/core/crsr/trvlfnfl.cxx
new file mode 100644
index 000000000000..765e4094712a
--- /dev/null
+++ b/sw/source/core/crsr/trvlfnfl.cxx
@@ -0,0 +1,361 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+
+#include <svx/svdmodel.hxx>
+#include <svx/svdpage.hxx>
+#include <crsrsh.hxx>
+#include <doc.hxx>
+#include <pagefrm.hxx>
+#include <cntfrm.hxx>
+#include <ftnfrm.hxx>
+#include <viewimp.hxx>
+#include <swcrsr.hxx>
+#include <dflyobj.hxx>
+#include <ndtxt.hxx>
+#include <flyfrm.hxx>
+#include <txtfrm.hxx>
+#include <txtftn.hxx>
+#include <ftnidx.hxx>
+#include <viscrs.hxx>
+#include <callnk.hxx>
+
+sal_Bool SwCrsrShell::CallCrsrFN( FNCrsr fnCrsr )
+{
+ SwCallLink aLk( *this ); // Crsr-Moves ueberwachen,
+ SwCursor* pCrsr = getShellCrsr( true );
+ sal_Bool bRet = (pCrsr->*fnCrsr)();
+ if( bRet )
+ UpdateCrsr( SwCrsrShell::SCROLLWIN | SwCrsrShell::CHKRANGE |
+ SwCrsrShell::READONLY );
+ return bRet;
+}
+
+sal_Bool SwCursor::GotoFtnTxt()
+{
+ // springe aus dem Content zur Fussnote
+ sal_Bool bRet = sal_False;
+ SwTxtNode* pTxtNd = GetPoint()->nNode.GetNode().GetTxtNode();
+
+ SwTxtAttr *const pFtn( (pTxtNd)
+ ? pTxtNd->GetTxtAttrForCharAt(
+ GetPoint()->nContent.GetIndex(), RES_TXTATR_FTN)
+ : 0);
+ if (pFtn)
+ {
+ SwCrsrSaveState aSaveState( *this );
+ GetPoint()->nNode = *((SwTxtFtn*)pFtn)->GetStartNode();
+
+ SwCntntNode* pCNd = GetDoc()->GetNodes().GoNextSection(
+ &GetPoint()->nNode,
+ sal_True, !IsReadOnlyAvailable() );
+ if( pCNd )
+ {
+ GetPoint()->nContent.Assign( pCNd, 0 );
+ bRet = !IsSelOvr( nsSwCursorSelOverFlags::SELOVER_CHECKNODESSECTION |
+ nsSwCursorSelOverFlags::SELOVER_TOGGLE );
+ }
+ }
+ return bRet;
+}
+
+sal_Bool SwCrsrShell::GotoFtnTxt()
+{
+ sal_Bool bRet = CallCrsrFN( &SwCursor::GotoFtnTxt );
+ if( !bRet )
+ {
+ SwTxtNode* pTxtNd = _GetCrsr() ?
+ _GetCrsr()->GetPoint()->nNode.GetNode().GetTxtNode() : NULL;
+ if( pTxtNd )
+ {
+ const SwFrm *pFrm = pTxtNd->getLayoutFrm( GetLayout(), &_GetCrsr()->GetSttPos(),
+ _GetCrsr()->Start() );
+ const SwFtnBossFrm* pFtnBoss;
+ sal_Bool bSkip = pFrm && pFrm->IsInFtn();
+ while( pFrm && 0 != ( pFtnBoss = pFrm->FindFtnBossFrm() ) )
+ {
+ if( 0 != ( pFrm = pFtnBoss->FindFtnCont() ) )
+ {
+ if( bSkip )
+ bSkip = sal_False;
+ else
+ {
+ const SwCntntFrm* pCnt = static_cast<const SwLayoutFrm*>
+ (pFrm)->ContainsCntnt();
+ if( pCnt )
+ {
+ const SwCntntNode* pNode = pCnt->GetNode();
+ _GetCrsr()->GetPoint()->nNode = *pNode;
+ _GetCrsr()->GetPoint()->nContent.Assign(
+ const_cast<SwCntntNode*>(pNode),
+ static_cast<const SwTxtFrm*>(pCnt)->GetOfst() );
+ UpdateCrsr( SwCrsrShell::SCROLLWIN |
+ SwCrsrShell::CHKRANGE | SwCrsrShell::READONLY );
+ bRet = sal_True;
+ break;
+ }
+ }
+ }
+ if( pFtnBoss->GetNext() && !pFtnBoss->IsPageFrm() )
+ pFrm = pFtnBoss->GetNext();
+ else
+ pFrm = pFtnBoss->GetUpper();
+ }
+ }
+ }
+ return bRet;
+}
+
+
+sal_Bool SwCursor::GotoFtnAnchor()
+{
+ // springe aus der Fussnote zum Anker
+ const SwNode* pSttNd = GetNode()->FindFootnoteStartNode();
+ if( pSttNd )
+ {
+ // durchsuche alle Fussnoten im Dokument nach diesem StartIndex
+ const SwTxtFtn* pTxtFtn;
+ const SwFtnIdxs& rFtnArr = pSttNd->GetDoc()->GetFtnIdxs();
+ for( sal_uInt16 n = 0; n < rFtnArr.Count(); ++n )
+ if( 0 != ( pTxtFtn = rFtnArr[ n ])->GetStartNode() &&
+ pSttNd == &pTxtFtn->GetStartNode()->GetNode() )
+ {
+ SwCrsrSaveState aSaveState( *this );
+
+ SwTxtNode& rTNd = (SwTxtNode&)pTxtFtn->GetTxtNode();
+
+ GetPoint()->nNode = rTNd;
+ GetPoint()->nContent.Assign( &rTNd, *pTxtFtn->GetStart() );
+
+ return !IsSelOvr( nsSwCursorSelOverFlags::SELOVER_CHECKNODESSECTION |
+ nsSwCursorSelOverFlags::SELOVER_TOGGLE );
+ }
+ }
+ return sal_False;
+}
+
+sal_Bool SwCrsrShell::GotoFtnAnchor()
+{
+ // springe aus der Fussnote zum Anker
+ SwCallLink aLk( *this ); // Crsr-Moves ueberwachen,
+ sal_Bool bRet = pCurCrsr->GotoFtnAnchor();
+ if( bRet )
+ {
+ // BUG 5996: Tabellen-Kopfzeile sonderbehandeln
+ pCurCrsr->GetPtPos() = Point();
+ UpdateCrsr( SwCrsrShell::SCROLLWIN | SwCrsrShell::CHKRANGE |
+ SwCrsrShell::READONLY );
+ }
+ return bRet;
+}
+
+inline sal_Bool CmpLE( const SwTxtFtn& rFtn, sal_uLong nNd, xub_StrLen nCnt )
+{
+ sal_uLong nTNd = rFtn.GetTxtNode().GetIndex();
+ return nTNd < nNd || ( nTNd == nNd && *rFtn.GetStart() <= nCnt );
+}
+inline sal_Bool CmpL( const SwTxtFtn& rFtn, sal_uLong nNd, xub_StrLen nCnt )
+{
+ sal_uLong nTNd = rFtn.GetTxtNode().GetIndex();
+ return nTNd < nNd || ( nTNd == nNd && *rFtn.GetStart() < nCnt );
+}
+
+sal_Bool SwCursor::GotoNextFtnAnchor()
+{
+ const SwFtnIdxs& rFtnArr = GetDoc()->GetFtnIdxs();
+ const SwTxtFtn* pTxtFtn = 0;
+ sal_uInt16 nPos;
+
+ if( rFtnArr.SeekEntry( GetPoint()->nNode, &nPos ))
+ {
+ // es gibt eine Fussnote mit dem Index, suche also die
+ // naechstgelegene
+ if( nPos < rFtnArr.Count() )
+ {
+ sal_uLong nNdPos = GetPoint()->nNode.GetIndex();
+ xub_StrLen nCntPos = GetPoint()->nContent.GetIndex();
+
+ pTxtFtn = rFtnArr[ nPos ];
+ // suche vorewaerts zur naechsten
+ if( CmpLE( *pTxtFtn, nNdPos, nCntPos ) )
+ {
+ pTxtFtn = 0;
+ for( ++nPos; nPos < rFtnArr.Count(); ++nPos )
+ {
+ pTxtFtn = rFtnArr[ nPos ];
+ if( !CmpLE( *pTxtFtn, nNdPos, nCntPos ) )
+ break; // gefunden
+ pTxtFtn = 0;
+ }
+ }
+ else if( nPos )
+ {
+ // suche rueckwaerts zur vorherigen
+ pTxtFtn = 0;
+ while( nPos )
+ {
+ pTxtFtn = rFtnArr[ --nPos ];
+ if( CmpLE( *pTxtFtn, nNdPos, nCntPos ) )
+ {
+ pTxtFtn = rFtnArr[ ++nPos ];
+ break; // gefunden
+ }
+// pTxtFtn = 0;
+ }
+ }
+ }
+ }
+ else if( nPos < rFtnArr.Count() )
+ pTxtFtn = rFtnArr[ nPos ];
+
+ sal_Bool bRet = 0 != pTxtFtn;
+ if( bRet )
+ {
+ SwCrsrSaveState aSaveState( *this );
+
+ SwTxtNode& rTNd = (SwTxtNode&)pTxtFtn->GetTxtNode();
+ GetPoint()->nNode = rTNd;
+ GetPoint()->nContent.Assign( &rTNd, *pTxtFtn->GetStart() );
+ bRet = !IsSelOvr();
+ }
+ return bRet;
+}
+
+sal_Bool SwCursor::GotoPrevFtnAnchor()
+{
+ const SwFtnIdxs& rFtnArr = GetDoc()->GetFtnIdxs();
+ const SwTxtFtn* pTxtFtn = 0;
+ sal_uInt16 nPos;
+
+ if( rFtnArr.SeekEntry( GetPoint()->nNode, &nPos ) )
+ {
+ // es gibt eine Fussnote mit dem Index, suche also die
+ // naechstgelegene
+ sal_uLong nNdPos = GetPoint()->nNode.GetIndex();
+ xub_StrLen nCntPos = GetPoint()->nContent.GetIndex();
+
+ pTxtFtn = rFtnArr[ nPos ];
+ // suche vorwaerts zur naechsten
+ if( CmpL( *pTxtFtn, nNdPos, nCntPos ))
+ {
+ for( ++nPos; nPos < rFtnArr.Count(); ++nPos )
+ {
+ pTxtFtn = rFtnArr[ nPos ];
+ if( !CmpL( *pTxtFtn, nNdPos, nCntPos ) )
+ {
+ pTxtFtn = rFtnArr[ nPos-1 ];
+ break;
+ }
+ }
+ }
+ else if( nPos )
+ {
+ // suche rueckwaerts zur vorherigen
+ pTxtFtn = 0;
+ while( nPos )
+ {
+ pTxtFtn = rFtnArr[ --nPos ];
+ if( CmpL( *pTxtFtn, nNdPos, nCntPos ))
+ break; // gefunden
+ pTxtFtn = 0;
+ }
+ }
+ else
+ pTxtFtn = 0;
+ }
+ else if( nPos )
+ pTxtFtn = rFtnArr[ nPos-1 ];
+
+ sal_Bool bRet = 0 != pTxtFtn;
+ if( bRet )
+ {
+ SwCrsrSaveState aSaveState( *this );
+
+ SwTxtNode& rTNd = (SwTxtNode&)pTxtFtn->GetTxtNode();
+ GetPoint()->nNode = rTNd;
+ GetPoint()->nContent.Assign( &rTNd, *pTxtFtn->GetStart() );
+ bRet = !IsSelOvr();
+ }
+ return bRet;
+}
+
+sal_Bool SwCrsrShell::GotoNextFtnAnchor()
+{
+ return CallCrsrFN( &SwCursor::GotoNextFtnAnchor );
+}
+
+sal_Bool SwCrsrShell::GotoPrevFtnAnchor()
+{
+ return CallCrsrFN( &SwCursor::GotoPrevFtnAnchor );
+}
+
+// springe aus dem Rahmen zum Anker
+
+
+sal_Bool SwCrsrShell::GotoFlyAnchor()
+{
+ SET_CURR_SHELL( this );
+ const SwFrm* pFrm = GetCurrFrm();
+ do {
+ pFrm = pFrm->GetUpper();
+ } while( pFrm && !pFrm->IsFlyFrm() );
+
+ if( !pFrm ) // ist kein FlyFrame
+ return sal_False;
+
+ SwCallLink aLk( *this ); // Crsr-Moves ueberwachen,
+ SwCrsrSaveState aSaveState( *pCurCrsr );
+
+ // springe in den BodyFrame, der am naechsten vom Fly liegt
+ SwRect aTmpRect( aCharRect );
+ if( !pFrm->Frm().IsInside( aTmpRect ))
+ aTmpRect = pFrm->Frm();
+ Point aPt( aTmpRect.Left(), aTmpRect.Top() +
+ ( aTmpRect.Bottom() - aTmpRect.Top() ) / 2 );
+ aPt.X() = aPt.X() > (pFrm->Frm().Left() + (pFrm->Frm().SSize().Width() / 2 ))
+ ? pFrm->Frm().Right()
+ : pFrm->Frm().Left();
+
+ const SwPageFrm* pPageFrm = pFrm->FindPageFrm();
+ const SwCntntFrm* pFndFrm = pPageFrm->GetCntntPos( aPt, sal_False, sal_True );
+ pFndFrm->GetCrsrOfst( pCurCrsr->GetPoint(), aPt );
+
+ sal_Bool bRet = !pCurCrsr->IsInProtectTable() && !pCurCrsr->IsSelOvr();
+ if( bRet )
+ UpdateCrsr( SwCrsrShell::SCROLLWIN | SwCrsrShell::CHKRANGE |
+ SwCrsrShell::READONLY );
+ return bRet;
+}
+
+
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/crsr/trvlreg.cxx b/sw/source/core/crsr/trvlreg.cxx
new file mode 100644
index 000000000000..25550b03958a
--- /dev/null
+++ b/sw/source/core/crsr/trvlreg.cxx
@@ -0,0 +1,293 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+
+#include <crsrsh.hxx>
+#include <doc.hxx>
+#include <swcrsr.hxx>
+#include <docary.hxx>
+#include <fmtcntnt.hxx>
+#include <viscrs.hxx>
+#include <callnk.hxx>
+#include <pamtyp.hxx>
+#include <section.hxx>
+
+
+
+sal_Bool GotoPrevRegion( SwPaM& rCurCrsr, SwPosRegion fnPosRegion,
+ sal_Bool bInReadOnly )
+{
+ SwNodeIndex aIdx( rCurCrsr.GetPoint()->nNode );
+ SwSectionNode* pNd = aIdx.GetNode().FindSectionNode();
+ if( pNd )
+ aIdx.Assign( *pNd, - 1 );
+
+ do {
+ while( aIdx.GetIndex() &&
+ 0 == ( pNd = aIdx.GetNode().StartOfSectionNode()->GetSectionNode()) )
+ aIdx--;
+
+ if( pNd ) // gibt einen weiteren SectionNode ?
+ {
+ if( pNd->GetSection().IsHiddenFlag() ||
+ ( !bInReadOnly &&
+ pNd->GetSection().IsProtectFlag() ))
+ {
+ // geschuetzte/versteckte ueberspringen wir
+ aIdx.Assign( *pNd, - 1 );
+ }
+ else if( fnPosRegion == fnMoveForward )
+ {
+ aIdx = *pNd;
+ SwCntntNode* pCNd = pNd->GetNodes().GoNextSection( &aIdx,
+ sal_True, !bInReadOnly );
+ if( !pCNd )
+ {
+ aIdx--;
+ continue;
+ }
+ rCurCrsr.GetPoint()->nContent.Assign( pCNd, 0 );
+ }
+ else
+ {
+ aIdx = *pNd->EndOfSectionNode();
+ SwCntntNode* pCNd = pNd->GetNodes().GoPrevSection( &aIdx,
+ sal_True, !bInReadOnly );
+ if( !pCNd )
+ {
+ aIdx.Assign( *pNd, - 1 );
+ continue;
+ }
+ rCurCrsr.GetPoint()->nContent.Assign( pCNd, pCNd->Len() );
+ }
+
+ rCurCrsr.GetPoint()->nNode = aIdx;
+ return sal_True;
+ }
+ } while( pNd );
+ return sal_False;
+}
+
+
+sal_Bool GotoNextRegion( SwPaM& rCurCrsr, SwPosRegion fnPosRegion,
+ sal_Bool bInReadOnly )
+{
+ SwNodeIndex aIdx( rCurCrsr.GetPoint()->nNode );
+ SwSectionNode* pNd = aIdx.GetNode().FindSectionNode();
+ if( pNd )
+ aIdx.Assign( *pNd->EndOfSectionNode(), - 1 );
+
+ sal_uLong nEndCount = aIdx.GetNode().GetNodes().Count()-1;
+ do {
+ while( aIdx.GetIndex() < nEndCount &&
+ 0 == ( pNd = aIdx.GetNode().GetSectionNode()) )
+ aIdx++;
+
+ if( pNd ) // gibt einen weiteren SectionNode ?
+ {
+ if( pNd->GetSection().IsHiddenFlag() ||
+ ( !bInReadOnly &&
+ pNd->GetSection().IsProtectFlag() ))
+ {
+ // geschuetzte/versteckte ueberspringen wir
+ aIdx.Assign( *pNd->EndOfSectionNode(), +1 );
+ }
+ else if( fnPosRegion == fnMoveForward )
+ {
+ aIdx = *pNd;
+ SwCntntNode* pCNd = pNd->GetNodes().GoNextSection( &aIdx,
+ sal_True, !bInReadOnly );
+ if( !pCNd )
+ {
+ aIdx.Assign( *pNd->EndOfSectionNode(), +1 );
+ continue;
+ }
+ rCurCrsr.GetPoint()->nContent.Assign( pCNd, 0 );
+ }
+ else
+ {
+ aIdx = *pNd->EndOfSectionNode();
+ SwCntntNode* pCNd = pNd->GetNodes().GoPrevSection( &aIdx,
+ sal_True, !bInReadOnly );
+ if( !pCNd )
+ {
+ aIdx++;
+ continue;
+ }
+ rCurCrsr.GetPoint()->nContent.Assign( pCNd, pCNd->Len() );
+ }
+
+ rCurCrsr.GetPoint()->nNode = aIdx;
+ return sal_True;
+ }
+ } while( pNd );
+ return sal_False;
+}
+
+
+sal_Bool GotoCurrRegion( SwPaM& rCurCrsr, SwPosRegion fnPosRegion,
+ sal_Bool bInReadOnly )
+{
+ SwSectionNode* pNd = rCurCrsr.GetNode()->FindSectionNode();
+ if( !pNd )
+ return sal_False;
+
+ SwPosition* pPos = rCurCrsr.GetPoint();
+ sal_Bool bMoveBackward = fnPosRegion == fnMoveBackward;
+
+ SwCntntNode* pCNd;
+ if( bMoveBackward )
+ {
+ SwNodeIndex aIdx( *pNd->EndOfSectionNode() );
+ pCNd = pNd->GetNodes().GoPrevSection( &aIdx, sal_True, !bInReadOnly );
+ }
+ else
+ {
+ SwNodeIndex aIdx( *pNd );
+ pCNd = pNd->GetNodes().GoNextSection( &aIdx, sal_True, !bInReadOnly );
+ }
+
+ if( pCNd )
+ {
+ pPos->nNode = *pCNd;
+ xub_StrLen nTmpPos = bMoveBackward ? pCNd->Len() : 0;
+ pPos->nContent.Assign( pCNd, nTmpPos );
+ }
+ return 0 != pCNd;
+}
+
+
+sal_Bool GotoCurrRegionAndSkip( SwPaM& rCurCrsr, SwPosRegion fnPosRegion,
+ sal_Bool bInReadOnly )
+{
+ SwNode* pCurrNd = rCurCrsr.GetNode();
+ SwSectionNode* pNd = pCurrNd->FindSectionNode();
+ if( !pNd )
+ return sal_False;
+
+ SwPosition* pPos = rCurCrsr.GetPoint();
+ xub_StrLen nCurrCnt = pPos->nContent.GetIndex();
+ sal_Bool bMoveBackward = fnPosRegion == fnMoveBackward;
+
+ do {
+ SwCntntNode* pCNd;
+ if( bMoveBackward ) // ans Ende vom Bereich
+ {
+ SwNodeIndex aIdx( *pNd->EndOfSectionNode() );
+ pCNd = pNd->GetNodes().GoPrevSection( &aIdx, sal_True, !bInReadOnly );
+ if( !pCNd )
+ return sal_False;
+ pPos->nNode = aIdx;
+ }
+ else
+ {
+ SwNodeIndex aIdx( *pNd );
+ pCNd = pNd->GetNodes().GoNextSection( &aIdx, sal_True, !bInReadOnly );
+ if( !pCNd )
+ return sal_False;
+ pPos->nNode = aIdx;
+ }
+
+ xub_StrLen nTmpPos = bMoveBackward ? pCNd->Len() : 0;
+ pPos->nContent.Assign( pCNd, nTmpPos );
+
+ if( &pPos->nNode.GetNode() != pCurrNd ||
+ pPos->nContent.GetIndex() != nCurrCnt )
+ // es gab eine Veraenderung
+ return sal_True;
+
+ // dann versuche mal den "Parent" dieser Section
+ SwSection* pParent = pNd->GetSection().GetParent();
+ pNd = pParent ? pParent->GetFmt()->GetSectionNode() : 0;
+ } while( pNd );
+ return sal_False;
+}
+
+
+
+sal_Bool SwCursor::MoveRegion( SwWhichRegion fnWhichRegion, SwPosRegion fnPosRegion )
+{
+ SwCrsrSaveState aSaveState( *this );
+ return !dynamic_cast<SwTableCursor*>(this) &&
+ (*fnWhichRegion)( *this, fnPosRegion, IsReadOnlyAvailable() ) &&
+ !IsSelOvr() &&
+ ( GetPoint()->nNode.GetIndex() != pSavePos->nNode ||
+ GetPoint()->nContent.GetIndex() != pSavePos->nCntnt );
+}
+
+sal_Bool SwCrsrShell::MoveRegion( SwWhichRegion fnWhichRegion, SwPosRegion fnPosRegion )
+{
+ SwCallLink aLk( *this ); // Crsr-Moves ueberwachen, evt. Link callen
+ sal_Bool bRet = !pTblCrsr && pCurCrsr->MoveRegion( fnWhichRegion, fnPosRegion );
+ if( bRet )
+ UpdateCrsr();
+ return bRet;
+}
+
+
+sal_Bool SwCursor::GotoRegion( const String& rName )
+{
+ sal_Bool bRet = sal_False;
+ const SwSectionFmts& rFmts = GetDoc()->GetSections();
+ for( sal_uInt16 n = rFmts.Count(); n; )
+ {
+ const SwSectionFmt* pFmt = rFmts[ --n ];
+ const SwNodeIndex* pIdx;
+ const SwSection* pSect;
+ if( 0 != ( pSect = pFmt->GetSection() ) &&
+ pSect->GetSectionName() == rName &&
+ 0 != ( pIdx = pFmt->GetCntnt().GetCntntIdx() ) &&
+ pIdx->GetNode().GetNodes().IsDocNodes() )
+ {
+ // ein Bereich im normalen NodesArr
+ SwCrsrSaveState aSaveState( *this );
+
+ GetPoint()->nNode = *pIdx;
+ Move( fnMoveForward, fnGoCntnt );
+ bRet = !IsSelOvr();
+ }
+ }
+ return bRet;
+}
+
+sal_Bool SwCrsrShell::GotoRegion( const String& rName )
+{
+ SwCallLink aLk( *this ); // Crsr-Moves ueberwachen,
+ sal_Bool bRet = !pTblCrsr && pCurCrsr->GotoRegion( rName );
+ if( bRet )
+ UpdateCrsr( SwCrsrShell::SCROLLWIN | SwCrsrShell::CHKRANGE |
+ SwCrsrShell::READONLY ); // und den akt. Updaten
+ return bRet;
+}
+
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/crsr/trvltbl.cxx b/sw/source/core/crsr/trvltbl.cxx
new file mode 100644
index 000000000000..7bd158d3be87
--- /dev/null
+++ b/sw/source/core/crsr/trvltbl.cxx
@@ -0,0 +1,932 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+#include <hintids.hxx>
+
+#include <vcl/svapp.hxx>
+#include <editeng/protitem.hxx>
+#include <crsrsh.hxx>
+#include <doc.hxx>
+#include <cntfrm.hxx>
+#include <editsh.hxx> //EndAllAction gibts nur an der EditShell
+#include <pam.hxx>
+#include <swtable.hxx>
+#include <docary.hxx>
+#include <frmatr.hxx>
+#include <frmfmt.hxx>
+#include <viscrs.hxx>
+#include <callnk.hxx>
+#include <tabfrm.hxx>
+#include <ndtxt.hxx>
+#include <shellres.hxx>
+#include <cellatr.hxx>
+#include <cellfrm.hxx>
+#include <rowfrm.hxx>
+
+
+// setze Crsr in die naechsten/vorherigen Celle
+sal_Bool SwCrsrShell::GoNextCell( sal_Bool bAppendLine )
+{
+ sal_Bool bRet = sal_False;
+ const SwTableNode* pTblNd = 0;
+
+ if( IsTableMode() || 0 != ( pTblNd = IsCrsrInTbl() ))
+ {
+ SwCursor* pCrsr = pTblCrsr ? pTblCrsr : pCurCrsr;
+ SwCallLink aLk( *this ); // Crsr-Moves ueberwachen,
+ bRet = sal_True;
+
+ // Check if we have to move the cursor to a covered cell before
+ // proceeding:
+ const SwNode* pTableBoxStartNode = pCrsr->GetNode()->FindTableBoxStartNode();
+ const SwTableBox* pTableBox = 0;
+
+ if ( pCrsr->GetCrsrRowSpanOffset() )
+ {
+ pTableBox = pTableBoxStartNode->GetTblBox();
+ if ( pTableBox->getRowSpan() > 1 )
+ {
+ if ( !pTblNd )
+ pTblNd = IsCrsrInTbl();
+ pTableBox = & pTableBox->FindEndOfRowSpan( pTblNd->GetTable(),
+ (sal_uInt16)(pTableBox->getRowSpan() + pCrsr->GetCrsrRowSpanOffset() ) );
+ pTableBoxStartNode = pTableBox->GetSttNd();
+ }
+ }
+
+ SwNodeIndex aCellStt( *pTableBoxStartNode->EndOfSectionNode(), 1 );
+
+ // folgt nach dem EndNode der Cell ein weiterer StartNode, dann
+ // gibt es auch eine naechste Celle
+
+ if( !aCellStt.GetNode().IsStartNode() )
+ {
+ if( pCrsr->HasMark() || !bAppendLine )
+ bRet = sal_False;
+ else
+ {
+ // auf besonderen Wunsch: keine Line mehr vorhanden, dann
+ // mache doch eine neue:
+ if ( !pTableBox )
+ pTableBox = pTblNd->GetTable().GetTblBox(
+ pCrsr->GetPoint()->nNode.GetNode().
+ StartOfSectionIndex() );
+
+ OSL_ENSURE( pTableBox, "Box steht nicht in dieser Tabelle" );
+ SwSelBoxes aBoxes;
+
+ //Das Dokument veraendert sich evtl. ohne Action wuerden die Sichten
+ //nichts mitbekommen.
+ ((SwEditShell*)this)->StartAllAction();
+ bRet = pDoc->InsertRow( pTblNd->GetTable().
+ SelLineFromBox( pTableBox, aBoxes, sal_False ));
+ ((SwEditShell*)this)->EndAllAction();
+ }
+ }
+ if( bRet && 0 != ( bRet = pCrsr->GoNextCell() ))
+ UpdateCrsr(); // und den akt. Updaten
+ }
+ return bRet;
+}
+
+
+sal_Bool SwCrsrShell::GoPrevCell()
+{
+ sal_Bool bRet = sal_False;
+ if( IsTableMode() || IsCrsrInTbl() )
+ {
+ SwCursor* pCrsr = pTblCrsr ? pTblCrsr : pCurCrsr;
+ SwCallLink aLk( *this ); // Crsr-Moves ueberwachen,
+ bRet = pCrsr->GoPrevCell();
+ if( bRet )
+ UpdateCrsr(); // und den akt. Updaten
+ }
+ return bRet;
+}
+
+const SwFrm* lcl_FindMostUpperCellFrm( const SwFrm* pFrm )
+{
+ while ( pFrm &&
+ ( !pFrm->IsCellFrm() ||
+ !pFrm->GetUpper()->GetUpper()->IsTabFrm() ||
+ pFrm->GetUpper()->GetUpper()->GetUpper()->IsInTab() ) )
+ {
+ pFrm = pFrm->GetUpper();
+ }
+ return pFrm;
+}
+
+sal_Bool SwCrsrShell::_SelTblRowOrCol( bool bRow, bool bRowSimple )
+{
+ // pruefe ob vom aktuellen Crsr der SPoint/Mark in einer Tabelle stehen
+ SwFrm *pFrm = GetCurrFrm();
+ if( !pFrm->IsInTab() )
+ return sal_False;
+
+ const SwTabFrm* pTabFrm = pFrm->FindTabFrm();
+ const SwTabFrm* pMasterTabFrm = pTabFrm->IsFollow() ? pTabFrm->FindMaster( true ) : pTabFrm;
+ const SwTable* pTable = pTabFrm->GetTable();
+
+ SET_CURR_SHELL( this );
+
+ const SwTableBox* pStt = 0;
+ const SwTableBox* pEnd = 0;
+
+ // lasse ueber das Layout die Boxen suchen
+ SwSelBoxes aBoxes;
+ SwTblSearchType eType = bRow ? nsSwTblSearchType::TBLSEARCH_ROW : nsSwTblSearchType::TBLSEARCH_COL;
+ const bool bCheckProtected = !IsReadOnlyAvailable();
+
+ if( bCheckProtected )
+ eType = (SwTblSearchType)(eType | nsSwTblSearchType::TBLSEARCH_PROTECT);
+
+ if ( !bRowSimple )
+ {
+ GetTblSel( *this, aBoxes, eType );
+
+ if( !aBoxes.Count() )
+ return sal_False;
+
+ pStt = aBoxes[0];
+ pEnd = aBoxes[aBoxes.Count() - 1];
+ }
+ // --> FME 2004-07-30 #i32329# Enhanced table selection
+ else if ( pTable->IsNewModel() )
+ {
+ const SwShellCrsr *pCrsr = _GetCrsr();
+ SwTable::SearchType eSearchType = bRow ? SwTable::SEARCH_ROW : SwTable::SEARCH_COL;
+ pTable->CreateSelection( *pCrsr, aBoxes, eSearchType, bCheckProtected );
+ if( !aBoxes.Count() )
+ return sal_False;
+
+ pStt = aBoxes[0];
+ pEnd = aBoxes[aBoxes.Count() - 1];
+ }
+ else
+ {
+ const SwShellCrsr *pCrsr = _GetCrsr();
+ const SwFrm* pStartFrm = pFrm;
+ const SwCntntNode *pCNd = pCrsr->GetCntntNode( sal_False );
+ const SwFrm* pEndFrm = pCNd ? pCNd->getLayoutFrm( GetLayout(), &pCrsr->GetMkPos() ) : 0;
+
+ if ( bRow )
+ {
+ pStartFrm = lcl_FindMostUpperCellFrm( pStartFrm );
+ pEndFrm = lcl_FindMostUpperCellFrm( pEndFrm );
+ }
+
+ if ( !pStartFrm || !pEndFrm )
+ return sal_False;
+
+ const bool bVert = pFrm->ImplFindTabFrm()->IsVertical();
+
+ // If we select upwards it is sufficient to set pStt and pEnd
+ // to the first resp. last box of the selection obtained from
+ // GetTblSel. However, selecting downwards requires the frames
+ // located at the corners of the selection. This does not work
+ // for column selections in vertical tables:
+ const bool bSelectUp = ( bVert && !bRow ) ||
+ *pCrsr->GetPoint() <= *pCrsr->GetMark();
+ SwCellFrms aCells;
+ GetTblSel( static_cast<const SwCellFrm*>(pStartFrm),
+ static_cast<const SwCellFrm*>(pEndFrm),
+ aBoxes, bSelectUp ? 0 : &aCells, eType );
+
+ if( !aBoxes.Count() || ( !bSelectUp && 4 != aCells.Count() ) )
+ return sal_False;
+
+ if ( bSelectUp )
+ {
+ pStt = aBoxes[0];
+ pEnd = aBoxes[aBoxes.Count() - 1];
+ }
+ else
+ {
+ pStt = aCells[ bVert ? (bRow ? 0 : 3) : (bRow ? 2 : 1) ]->GetTabBox(); // will become point of table cursor
+ pEnd = aCells[ bVert ? (bRow ? 3 : 0) : (bRow ? 1 : 2) ]->GetTabBox(); // will become mark of table cursor
+ }
+ }
+ // <--
+
+ // noch kein Tabellen-Cursor vorhanden, dann erzeuge einen
+ if( !pTblCrsr )
+ {
+ pTblCrsr = new SwShellTableCrsr( *this, *pCurCrsr->GetPoint() );
+ pCurCrsr->DeleteMark();
+ pCurCrsr->SwSelPaintRects::Hide();
+ }
+
+ pTblCrsr->DeleteMark();
+
+ // dann setze mal Anfang und Ende der Spalte
+ pTblCrsr->GetPoint()->nNode = *pEnd->GetSttNd();
+ pTblCrsr->Move( fnMoveForward, fnGoCntnt );
+ pTblCrsr->SetMark();
+ pTblCrsr->GetPoint()->nNode = *pStt->GetSttNd()->EndOfSectionNode();
+ pTblCrsr->Move( fnMoveBackward, fnGoCntnt );
+
+ // set PtPos 'close' to the reference table, otherwise we might get problems with the
+ // repeated headlines check in UpdateCrsr():
+ if ( !bRow )
+ pTblCrsr->GetPtPos() = pMasterTabFrm->IsVertical() ? pMasterTabFrm->Frm().TopRight() : pMasterTabFrm->Frm().TopLeft();
+
+ UpdateCrsr(); // und den akt. Updaten
+ return sal_True;
+}
+
+sal_Bool SwCrsrShell::SelTbl()
+{
+ // pruefe ob vom aktuellen Crsr der SPoint/Mark in einer Tabelle stehen
+ SwFrm *pFrm = GetCurrFrm();
+ if( !pFrm->IsInTab() )
+ return sal_False;
+
+ const SwTabFrm *pTblFrm = pFrm->ImplFindTabFrm();
+ const SwTabFrm* pMasterTabFrm = pTblFrm->IsFollow() ? pTblFrm->FindMaster( true ) : pTblFrm;
+ const SwTableNode* pTblNd = pTblFrm->GetTable()->GetTableNode();
+
+ SET_CURR_SHELL( this );
+
+ if( !pTblCrsr )
+ {
+ pTblCrsr = new SwShellTableCrsr( *this, *pCurCrsr->GetPoint() );
+ pCurCrsr->DeleteMark();
+ pCurCrsr->SwSelPaintRects::Hide();
+ }
+
+ pTblCrsr->DeleteMark();
+ pTblCrsr->GetPoint()->nNode = *pTblNd;
+ pTblCrsr->Move( fnMoveForward, fnGoCntnt );
+ pTblCrsr->SetMark();
+ // set MkPos 'close' to the master table, otherwise we might get problems with the
+ // repeated headlines check in UpdateCrsr():
+ pTblCrsr->GetMkPos() = pMasterTabFrm->IsVertical() ? pMasterTabFrm->Frm().TopRight() : pMasterTabFrm->Frm().TopLeft();
+ pTblCrsr->GetPoint()->nNode = *pTblNd->EndOfSectionNode();
+ pTblCrsr->Move( fnMoveBackward, fnGoCntnt );
+ UpdateCrsr(); // und den akt. Updaten
+ return sal_True;
+}
+
+
+sal_Bool SwCrsrShell::SelTblBox()
+{
+ // if we're in a table, create a table cursor, and select the cell
+ // that the current cursor's point resides in
+
+ // search for start node of our table box. If not found, exit realy
+ const SwStartNode* pStartNode =
+ pCurCrsr->GetPoint()->nNode.GetNode().FindTableBoxStartNode();
+
+#if OSL_DEBUG_LEVEL > 1
+ // the old code checks whether we're in a table by asking the
+ // frame. This should yield the same result as searching for the
+ // table box start node, right?
+ SwFrm *pFrm = GetCurrFrm();
+ OSL_ENSURE( !pFrm->IsInTab() == !(pStartNode != NULL),
+ "Schroedinger's table: We're in a box, and also we aren't." );
+#endif
+
+ if( pStartNode == NULL )
+ return sal_False;
+
+
+ SET_CURR_SHELL( this );
+
+ // create a table cursor, if there isn't one already
+ if( !pTblCrsr )
+ {
+ pTblCrsr = new SwShellTableCrsr( *this, *pCurCrsr->GetPoint() );
+ pCurCrsr->DeleteMark();
+ pCurCrsr->SwSelPaintRects::Hide();
+ }
+
+ // select the complete box with our shiny new pTblCrsr
+ // 1. delete mark, and move point to first content node in box
+ // 2. set mark, and move point to last content node in box
+ // 3. exchange
+
+ pTblCrsr->DeleteMark();
+ *(pTblCrsr->GetPoint()) = SwPosition( *pStartNode );
+ pTblCrsr->Move( fnMoveForward, fnGoNode );
+
+ pTblCrsr->SetMark();
+ *(pTblCrsr->GetPoint()) = SwPosition( *(pStartNode->EndOfSectionNode()) );
+ pTblCrsr->Move( fnMoveBackward, fnGoNode );
+
+ pTblCrsr->Exchange();
+
+ // with some luck, UpdateCrsr() will now update everything that
+ // needs updateing
+ UpdateCrsr();
+
+ return sal_True;
+}
+
+// return the next non-protected cell inside a table
+// rIdx - is on a table node
+// return:
+// true - Idx points to content in a suitable cell
+// false - could not find a suitable cell
+bool lcl_FindNextCell( SwNodeIndex& rIdx, sal_Bool bInReadOnly )
+{
+ // ueberpruefe geschuetzte Zellen
+ SwNodeIndex aTmp( rIdx, 2 ); // TableNode + StartNode
+
+ // the resulting cell should be in that table:
+ const SwTableNode* pTblNd = rIdx.GetNode().GetTableNode();
+
+ if ( !pTblNd )
+ {
+ OSL_FAIL( "lcl_FindNextCell not celled with table start node!" );
+ return false;
+ }
+
+ const SwNode* pTableEndNode = pTblNd->EndOfSectionNode();
+
+ SwNodes& rNds = aTmp.GetNode().GetNodes();
+ SwCntntNode* pCNd = aTmp.GetNode().GetCntntNode();
+
+ // no content node => go to next content node
+ if( !pCNd )
+ pCNd = rNds.GoNext( &aTmp );
+
+ // robust
+ if ( !pCNd )
+ return false;
+
+ SwCntntFrm* pFrm = pCNd->getLayoutFrm( pCNd->GetDoc()->GetCurrentLayout() );
+
+ if ( 0 == pFrm || pCNd->FindTableNode() != pTblNd ||
+ (!bInReadOnly && pFrm->IsProtected() ) )
+ {
+ // we are not located inside a 'valid' cell. We have to continue searching...
+
+ // skip behind current section. This might be the end of the table cell
+ // or behind a inner section or or or...
+ aTmp.Assign( *pCNd->EndOfSectionNode(), 1 );
+
+ // loop to find a suitable cell...
+ for( ;; )
+ {
+ SwNode* pNd = &aTmp.GetNode();
+
+ // we break this loop if we reached the end of the table.
+ // to make this code even more robust, we also break if we are
+ // already behind the table end node:
+ if( pNd == pTableEndNode || /*robust: */ pNd->GetIndex() > pTableEndNode->GetIndex() )
+ return false;
+
+ // ok, get the next content node:
+ pCNd = aTmp.GetNode().GetCntntNode();
+ if( 0 == pCNd )
+ pCNd = rNds.GoNext( &aTmp );
+
+ // robust:
+ if ( !pCNd )
+ return false;
+
+ // check if we have found a suitable table cell:
+ pFrm = pCNd->getLayoutFrm( pCNd->GetDoc()->GetCurrentLayout() );
+
+ if ( 0 != pFrm && pCNd->FindTableNode() == pTblNd &&
+ (bInReadOnly || !pFrm->IsProtected() ) )
+ {
+ // finally, we have found a suitable table cell => set index and return
+ rIdx = *pCNd;
+ return true;
+ }
+
+ // continue behind the current section:
+ aTmp.Assign( *pCNd->EndOfSectionNode(), +1 );
+ }
+ }
+
+ rIdx = *pCNd;
+ return true;
+}
+
+// comments see lcl_FindNextCell
+bool lcl_FindPrevCell( SwNodeIndex& rIdx, sal_Bool bInReadOnly )
+{
+ SwNodeIndex aTmp( rIdx, -2 ); // TableNode + EndNode
+
+ const SwNode* pTableEndNode = &rIdx.GetNode();
+ const SwTableNode* pTblNd = pTableEndNode->StartOfSectionNode()->GetTableNode();
+
+ if ( !pTblNd )
+ {
+ OSL_FAIL( "lcl_FindPrevCell not celled with table start node!" );
+ return false;
+ }
+
+ SwNodes& rNds = aTmp.GetNode().GetNodes();
+ SwCntntNode* pCNd = aTmp.GetNode().GetCntntNode();
+
+ if( !pCNd )
+ pCNd = rNds.GoPrevious( &aTmp );
+
+ if ( !pCNd )
+ return false;
+
+ SwCntntFrm* pFrm = pCNd->getLayoutFrm( pCNd->GetDoc()->GetCurrentLayout() );
+
+ if( 0 == pFrm || pCNd->FindTableNode() != pTblNd ||
+ (!bInReadOnly && pFrm->IsProtected() ))
+ {
+ // skip before current section
+ aTmp.Assign( *pCNd->StartOfSectionNode(), -1 );
+ for( ;; )
+ {
+ SwNode* pNd = &aTmp.GetNode();
+
+ if( pNd == pTblNd || pNd->GetIndex() < pTblNd->GetIndex() )
+ return false;
+
+ pCNd = aTmp.GetNode().GetCntntNode();
+ if( 0 == pCNd )
+ pCNd = rNds.GoPrevious( &aTmp );
+
+ if ( !pCNd )
+ return false;
+
+ pFrm = pCNd->getLayoutFrm( pCNd->GetDoc()->GetCurrentLayout() );
+
+ if( 0 != pFrm && pCNd->FindTableNode() == pTblNd &&
+ (bInReadOnly || !pFrm->IsProtected() ) )
+ {
+ rIdx = *pCNd;
+ return true; // Ok, nicht geschuetzt
+ }
+ aTmp.Assign( *pCNd->StartOfSectionNode(), - 1 );
+ }
+ }
+
+ rIdx = *pCNd;
+ return true;
+}
+
+
+sal_Bool GotoPrevTable( SwPaM& rCurCrsr, SwPosTable fnPosTbl,
+ sal_Bool bInReadOnly )
+{
+ SwNodeIndex aIdx( rCurCrsr.GetPoint()->nNode );
+
+ SwTableNode* pTblNd = aIdx.GetNode().FindTableNode();
+ if( pTblNd )
+ {
+ // #i26532#: If we are inside a table, we may not go backward
+ // to the table start node, because we would miss any tables
+ // inside this table.
+ SwTableNode* pInnerTblNd = 0;
+ SwNodeIndex aTmpIdx( aIdx );
+ while( aTmpIdx.GetIndex() &&
+ 0 == ( pInnerTblNd = aTmpIdx.GetNode().StartOfSectionNode()->GetTableNode()) )
+ aTmpIdx--;
+
+ if( pInnerTblNd == pTblNd )
+ aIdx.Assign( *pTblNd, - 1 );
+ }
+
+ do {
+ while( aIdx.GetIndex() &&
+ 0 == ( pTblNd = aIdx.GetNode().StartOfSectionNode()->GetTableNode()) )
+ aIdx--;
+
+ if( pTblNd ) // gibt einen weiteren TableNode ?
+ {
+ if( fnPosTbl == fnMoveForward ) // an Anfang ?
+ {
+ aIdx = *aIdx.GetNode().StartOfSectionNode();
+ if( !lcl_FindNextCell( aIdx, bInReadOnly ))
+ {
+ // Tabelle ueberspringen
+ aIdx.Assign( *pTblNd, -1 );
+ continue;
+ }
+ }
+ else
+ {
+ // ueberpruefe geschuetzte Zellen
+ if( !lcl_FindNextCell( aIdx, bInReadOnly ))
+ {
+ // Tabelle ueberspringen
+ aIdx.Assign( *pTblNd, -1 );
+ continue;
+ }
+ }
+
+ SwTxtNode* pTxtNode = aIdx.GetNode().GetTxtNode();
+ if ( pTxtNode )
+ {
+ rCurCrsr.GetPoint()->nNode = *pTxtNode;
+ rCurCrsr.GetPoint()->nContent.Assign( pTxtNode, fnPosTbl == fnMoveBackward ?
+ pTxtNode->Len() :
+ 0 );
+ }
+ return sal_True;
+ }
+ } while( pTblNd );
+
+ return sal_False;
+}
+
+
+sal_Bool GotoNextTable( SwPaM& rCurCrsr, SwPosTable fnPosTbl,
+ sal_Bool bInReadOnly )
+{
+ SwNodeIndex aIdx( rCurCrsr.GetPoint()->nNode );
+ SwTableNode* pTblNd = aIdx.GetNode().FindTableNode();
+
+ if( pTblNd )
+ aIdx.Assign( *pTblNd->EndOfSectionNode(), 1 );
+
+ sal_uLong nLastNd = rCurCrsr.GetDoc()->GetNodes().Count() - 1;
+ do {
+ while( aIdx.GetIndex() < nLastNd &&
+ 0 == ( pTblNd = aIdx.GetNode().GetTableNode()) )
+ aIdx++;
+ if( pTblNd ) // gibt einen weiteren TableNode ?
+ {
+ if( fnPosTbl == fnMoveForward ) // an Anfang ?
+ {
+ if( !lcl_FindNextCell( aIdx, bInReadOnly ))
+ {
+ // Tabelle ueberspringen
+ aIdx.Assign( *pTblNd->EndOfSectionNode(), + 1 );
+ continue;
+ }
+ }
+ else
+ {
+ aIdx = *aIdx.GetNode().EndOfSectionNode();
+ // ueberpruefe geschuetzte Zellen
+ if( !lcl_FindNextCell( aIdx, bInReadOnly ))
+ {
+ // Tabelle ueberspringen
+ aIdx.Assign( *pTblNd->EndOfSectionNode(), + 1 );
+ continue;
+ }
+ }
+
+ SwTxtNode* pTxtNode = aIdx.GetNode().GetTxtNode();
+ if ( pTxtNode )
+ {
+ rCurCrsr.GetPoint()->nNode = *pTxtNode;
+ rCurCrsr.GetPoint()->nContent.Assign( pTxtNode, fnPosTbl == fnMoveBackward ?
+ pTxtNode->Len() :
+ 0 );
+ }
+ return sal_True;
+ }
+ } while( pTblNd );
+
+ return sal_False;
+}
+
+
+sal_Bool GotoCurrTable( SwPaM& rCurCrsr, SwPosTable fnPosTbl,
+ sal_Bool bInReadOnly )
+{
+ SwTableNode* pTblNd = rCurCrsr.GetPoint()->nNode.GetNode().FindTableNode();
+ if( !pTblNd )
+ return sal_False;
+
+ SwTxtNode* pTxtNode = 0;
+ if( fnPosTbl == fnMoveBackward ) // ans Ende der Tabelle
+ {
+ SwNodeIndex aIdx( *pTblNd->EndOfSectionNode() );
+ if( !lcl_FindPrevCell( aIdx, bInReadOnly ))
+ return sal_False;
+ pTxtNode = aIdx.GetNode().GetTxtNode();
+ }
+ else
+ {
+ SwNodeIndex aIdx( *pTblNd );
+ if( !lcl_FindNextCell( aIdx, bInReadOnly ))
+ return sal_False;
+ pTxtNode = aIdx.GetNode().GetTxtNode();
+ }
+
+ if ( pTxtNode )
+ {
+ rCurCrsr.GetPoint()->nNode = *pTxtNode;
+ rCurCrsr.GetPoint()->nContent.Assign( pTxtNode, fnPosTbl == fnMoveBackward ?
+ pTxtNode->Len() :
+ 0 );
+ }
+
+ return sal_True;
+}
+
+
+sal_Bool SwCursor::MoveTable( SwWhichTable fnWhichTbl, SwPosTable fnPosTbl )
+{
+ sal_Bool bRet = sal_False;
+ SwTableCursor* pTblCrsr = dynamic_cast<SwTableCursor*>(this);
+
+ if( pTblCrsr || !HasMark() ) // nur wenn kein Mark oder ein TblCrsr
+ {
+ SwCrsrSaveState aSaveState( *this );
+ bRet = (*fnWhichTbl)( *this, fnPosTbl, IsReadOnlyAvailable() ) &&
+ !IsSelOvr( nsSwCursorSelOverFlags::SELOVER_CHECKNODESSECTION |
+ nsSwCursorSelOverFlags::SELOVER_TOGGLE );
+ }
+ return bRet;
+}
+
+sal_Bool SwCrsrShell::MoveTable( SwWhichTable fnWhichTbl, SwPosTable fnPosTbl )
+{
+ SwCallLink aLk( *this ); // Crsr-Moves ueberwachen, evt. Link callen
+
+ SwShellCrsr* pCrsr = pTblCrsr ? pTblCrsr : pCurCrsr;
+ sal_Bool bCheckPos, bRet;
+ sal_uLong nPtNd = 0;
+ xub_StrLen nPtCnt = 0;
+
+ if( !pTblCrsr && pCurCrsr->HasMark() ) // wenn Mark und kein TblCrsr,
+ {
+ // dann auf jedenfall in den Tabellen-Modus schalten
+ pTblCrsr = new SwShellTableCrsr( *this, *pCurCrsr->GetPoint() );
+ pCurCrsr->DeleteMark();
+ pCurCrsr->SwSelPaintRects::Hide();
+ pTblCrsr->SetMark();
+ pCrsr = pTblCrsr;
+ bCheckPos = sal_False;
+ }
+ else
+ {
+ bCheckPos = sal_True;
+ nPtNd = pCrsr->GetPoint()->nNode.GetIndex();
+ nPtCnt = pCrsr->GetPoint()->nContent.GetIndex();
+ }
+
+ bRet = pCrsr->MoveTable( fnWhichTbl, fnPosTbl );
+
+ if( bRet )
+ {
+ //JP 28.10.97: Bug 45028 - die "oberste" Position setzen fuer
+ // wiederholte Kopfzeilen
+ pCrsr->GetPtPos() = Point();
+
+ UpdateCrsr(SwCrsrShell::SCROLLWIN|SwCrsrShell::CHKRANGE|SwCrsrShell::READONLY);
+
+ if( bCheckPos &&
+ pCrsr->GetPoint()->nNode.GetIndex() == nPtNd &&
+ pCrsr->GetPoint()->nContent.GetIndex() == nPtCnt )
+ bRet = sal_False;
+ }
+ return bRet;
+}
+
+
+sal_Bool SwCrsrShell::IsTblComplex() const
+{
+ SwFrm *pFrm = GetCurrFrm( sal_False );
+ if ( pFrm && pFrm->IsInTab() )
+ return pFrm->FindTabFrm()->GetTable()->IsTblComplex();
+ return sal_False;
+}
+
+
+sal_Bool SwCrsrShell::IsTblComplexForChart()
+{
+ sal_Bool bRet = sal_False;
+
+ StartAction(); // IsTblComplexForChart() may trigger table formatting
+ // we better do that inside an action
+
+ const SwTableNode* pTNd = pCurCrsr->GetPoint()->nNode.GetNode().FindTableNode();
+ if( pTNd )
+ {
+ // wir stehen in der Tabelle, dann teste mal, ob die Tabelle oder die
+ // Selektion ausgeglichen ist.
+ String sSel;
+ if( pTblCrsr )
+ sSel = GetBoxNms();
+ bRet = pTNd->GetTable().IsTblComplexForChart( sSel );
+ }
+
+ EndAction();
+
+ return bRet;
+}
+
+String SwCrsrShell::GetBoxNms() const
+{
+ String sNm;
+ const SwPosition* pPos;
+ SwFrm* pFrm;
+
+ if( IsTableMode() )
+ {
+ SwCntntNode *pCNd = pTblCrsr->Start()->nNode.GetNode().GetCntntNode();
+ pFrm = pCNd ? pCNd->getLayoutFrm( GetLayout() ) : 0;
+ if( !pFrm )
+ return sNm;
+
+ do {
+ pFrm = pFrm->GetUpper();
+ } while ( pFrm && !pFrm->IsCellFrm() );
+
+ OSL_ENSURE( pFrm, "kein Frame zur Box" );
+ sNm = ((SwCellFrm*)pFrm)->GetTabBox()->GetName();
+ sNm += ':';
+ pPos = pTblCrsr->End();
+ }
+ else
+ {
+ const SwTableNode* pTblNd = IsCrsrInTbl();
+ if( !pTblNd )
+ return sNm;
+ pPos = GetCrsr()->GetPoint();
+ }
+
+ SwCntntNode* pCNd = pPos->nNode.GetNode().GetCntntNode();
+ pFrm = pCNd ? pCNd->getLayoutFrm( GetLayout() ) : 0;
+
+ if( pFrm )
+ {
+ do {
+ pFrm = pFrm->GetUpper();
+ } while ( pFrm && !pFrm->IsCellFrm() );
+
+ if( pFrm )
+ sNm += ((SwCellFrm*)pFrm)->GetTabBox()->GetName();
+ }
+ return sNm;
+}
+
+
+sal_Bool SwCrsrShell::GotoTable( const String& rName )
+{
+ SwCallLink aLk( *this ); // Crsr-Moves ueberwachen,
+ sal_Bool bRet = !pTblCrsr && pCurCrsr->GotoTable( rName );
+ if( bRet )
+ {
+ pCurCrsr->GetPtPos() = Point();
+ UpdateCrsr( SwCrsrShell::SCROLLWIN | SwCrsrShell::CHKRANGE |
+ SwCrsrShell::READONLY ); // und den akt. Updaten
+ }
+ return bRet;
+}
+
+
+sal_Bool SwCrsrShell::CheckTblBoxCntnt( const SwPosition* pPos )
+{
+ if( !pBoxIdx || !pBoxPtr || IsSelTblCells() || !IsAutoUpdateCells() )
+ return sal_False;
+
+ // ueberpruefe, ob der Box Inhalt mit dem angegebenen Format der Box
+ // ueber einstimmt. Wenn nicht, setze neu
+ SwTableBox* pChkBox = 0;
+ SwStartNode* pSttNd = 0;
+ if( !pPos )
+ {
+ // gesicherte Position heraus holen.
+ if( pBoxIdx && pBoxPtr &&
+ 0 != ( pSttNd = pBoxIdx->GetNode().GetStartNode() ) &&
+ SwTableBoxStartNode == pSttNd->GetStartNodeType() &&
+ pBoxPtr == pSttNd->FindTableNode()->GetTable().
+ GetTblBox( pBoxIdx->GetIndex() ) )
+ pChkBox = pBoxPtr;
+ }
+ else if( 0 != ( pSttNd = pPos->nNode.GetNode().
+ FindSttNodeByType( SwTableBoxStartNode )) )
+ {
+ pChkBox = pSttNd->FindTableNode()->GetTable().GetTblBox( pSttNd->GetIndex() );
+ }
+
+
+ // Box mehr als 1 Absatz?
+ if( pChkBox && pSttNd->GetIndex() + 2 != pSttNd->EndOfSectionIndex() )
+ pChkBox = 0;
+
+ // jetzt sollten wir mal die Pointer zerstoeren, bevor eine erneute
+ // Actionklammerung kommt.
+ if( !pPos && !pChkBox )
+ ClearTblBoxCntnt();
+
+ // liegt der Cursor nicht mehr in dem Bereich ?
+ if( pChkBox && !pPos &&
+ ( pCurCrsr->HasMark() || pCurCrsr->GetNext() != pCurCrsr ||
+ pSttNd->GetIndex() + 1 == pCurCrsr->GetPoint()->nNode.GetIndex() ))
+ pChkBox = 0;
+
+ //JP 12.01.99: hat sich der Inhalt der Box ueberhaupt veraendert?
+ // Ist wichtig, wenn z.B. Undo nicht den richtigen Inhalt wieder
+ // herstellen konnte.
+ if( pChkBox )
+ {
+ const SwTxtNode* pNd = GetDoc()->GetNodes()[
+ pSttNd->GetIndex() + 1 ]->GetTxtNode();
+ if( !pNd ||
+ ( pNd->GetTxt() == ViewShell::GetShellRes()->aCalc_Error &&
+ SFX_ITEM_SET == pChkBox->GetFrmFmt()->
+ GetItemState( RES_BOXATR_FORMULA )) )
+ pChkBox = 0;
+ }
+
+ if( pChkBox )
+ {
+ // jetzt sollten wir mal die Pointer zerstoeren, bevor ein weiterer
+ // aufruf kommt.
+ ClearTblBoxCntnt();
+ StartAction();
+ GetDoc()->ChkBoxNumFmt( *pChkBox, sal_True );
+ EndAction();
+ }
+
+ return 0 != pChkBox;
+}
+
+
+void SwCrsrShell::SaveTblBoxCntnt( const SwPosition* pPos )
+{
+ if( IsSelTblCells() || !IsAutoUpdateCells() )
+ return ;
+
+ if( !pPos )
+ pPos = pCurCrsr->GetPoint();
+
+ SwStartNode* pSttNd = pPos->nNode.GetNode().FindSttNodeByType( SwTableBoxStartNode );
+
+ sal_Bool bCheckBox = sal_False;
+ if( pSttNd && pBoxIdx )
+ {
+ if( pSttNd == &pBoxIdx->GetNode() )
+ pSttNd = 0; // die haben wir schon
+ else
+ bCheckBox = sal_True;
+ }
+ else
+ bCheckBox = 0 != pBoxIdx;
+
+ if( bCheckBox )
+ {
+ // pBoxIdx Checken
+ SwPosition aPos( *pBoxIdx );
+ CheckTblBoxCntnt( &aPos );
+ }
+
+ if( pSttNd )
+ {
+ pBoxPtr = pSttNd->FindTableNode()->GetTable().GetTblBox( pSttNd->GetIndex() );
+
+ if( pBoxIdx )
+ *pBoxIdx = *pSttNd;
+ else
+ pBoxIdx = new SwNodeIndex( *pSttNd );
+ }
+}
+
+
+void SwCrsrShell::ClearTblBoxCntnt()
+{
+ delete pBoxIdx, pBoxIdx = 0;
+ pBoxPtr = 0;
+}
+
+sal_Bool SwCrsrShell::EndAllTblBoxEdit()
+{
+ sal_Bool bRet = sal_False;
+ ViewShell *pSh = this;
+ do {
+ if( pSh->IsA( TYPE( SwCrsrShell ) ) )
+ bRet |= ((SwCrsrShell*)pSh)->CheckTblBoxCntnt(
+ ((SwCrsrShell*)pSh)->pCurCrsr->GetPoint() );
+
+ } while( this != (pSh = (ViewShell *)pSh->GetNext()) );
+ return bRet;
+}
+
+
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/crsr/unocrsr.cxx b/sw/source/core/crsr/unocrsr.cxx
new file mode 100644
index 000000000000..6adb1e14dfa7
--- /dev/null
+++ b/sw/source/core/crsr/unocrsr.cxx
@@ -0,0 +1,266 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+
+#include <unocrsr.hxx>
+#include <doc.hxx>
+#include <swtable.hxx>
+#include <docary.hxx>
+#include <rootfrm.hxx>
+
+SV_IMPL_PTRARR( SwUnoCrsrTbl, SwUnoCrsrPtr )
+
+IMPL_FIXEDMEMPOOL_NEWDEL( SwUnoCrsr, 10, 10 )
+
+SwUnoCrsr::SwUnoCrsr( const SwPosition &rPos, SwPaM* pRing )
+ : SwCursor( rPos, pRing, false ), SwModify( 0 ),
+ bRemainInSection( sal_True ),
+ bSkipOverHiddenSections( sal_False ),
+ bSkipOverProtectSections( sal_False )
+
+{}
+
+SwUnoCrsr::~SwUnoCrsr()
+{
+ SwDoc* pDoc = GetDoc();
+ if( !pDoc->IsInDtor() )
+ {
+ // dann muss der Cursor aus dem Array ausgetragen werden
+ SwUnoCrsrTbl& rTbl = (SwUnoCrsrTbl&)pDoc->GetUnoCrsrTbl();
+ sal_uInt16 nDelPos = rTbl.GetPos( this );
+
+ if( USHRT_MAX != nDelPos )
+ rTbl.Remove( nDelPos );
+ else {
+ OSL_ENSURE( !this, "UNO Cursor nicht mehr im Array" );
+ }
+ }
+
+ // den gesamten Ring loeschen!
+ while( GetNext() != this )
+ {
+ Ring* pNxt = GetNext();
+ pNxt->MoveTo( 0 ); // ausketten
+ delete pNxt; // und loeschen
+ }
+}
+
+SwUnoCrsr * SwUnoCrsr::Clone() const
+{
+ SwUnoCrsr * pNewCrsr = GetDoc()->CreateUnoCrsr( *GetPoint() );
+ if (HasMark())
+ {
+ pNewCrsr->SetMark();
+ *pNewCrsr->GetMark() = *GetMark();
+ }
+ return pNewCrsr;
+}
+
+SwUnoTableCrsr * SwUnoTableCrsr::Clone() const
+{
+ SwUnoTableCrsr * pNewCrsr = dynamic_cast<SwUnoTableCrsr*>(
+ GetDoc()->CreateUnoCrsr(
+ *GetPoint(), sal_True /* create SwUnoTableCrsr */ ) );
+ OSL_ENSURE(pNewCrsr, "Clone: cannot create SwUnoTableCrsr?");
+ if (HasMark())
+ {
+ pNewCrsr->SetMark();
+ *pNewCrsr->GetMark() = *GetMark();
+ }
+ return pNewCrsr;
+}
+
+
+bool SwUnoCrsr::IsReadOnlyAvailable() const
+{
+ return true;
+}
+
+const SwCntntFrm*
+SwUnoCrsr::DoSetBidiLevelLeftRight( sal_Bool &, sal_Bool, sal_Bool )
+{
+ return 0; // not for uno cursor
+}
+
+void SwUnoCrsr::DoSetBidiLevelUpDown()
+{
+ return; // not for uno cursor
+}
+
+sal_Bool SwUnoCrsr::IsSelOvr( int eFlags )
+{
+ if( bRemainInSection )
+ {
+ SwDoc* pDoc = GetDoc();
+ SwNodeIndex aOldIdx( *pDoc->GetNodes()[ GetSavePos()->nNode ] );
+ SwNodeIndex& rPtIdx = GetPoint()->nNode;
+ SwStartNode *pOldSttNd = aOldIdx.GetNode().StartOfSectionNode(),
+ *pNewSttNd = rPtIdx.GetNode().StartOfSectionNode();
+ if( pOldSttNd != pNewSttNd )
+ {
+ sal_Bool bMoveDown = GetSavePos()->nNode < rPtIdx.GetIndex();
+ sal_Bool bValidPos = sal_False;
+
+ // search the correct surrounded start node - which the index
+ // can't leave.
+ while( pOldSttNd->IsSectionNode() )
+ pOldSttNd = pOldSttNd->StartOfSectionNode();
+
+ // is the new index inside this surrounded section?
+ if( rPtIdx > *pOldSttNd &&
+ rPtIdx < pOldSttNd->EndOfSectionIndex() )
+ {
+ // check if it a valid move inside this section
+ // (only over SwSection's !)
+ const SwStartNode* pInvalidNode;
+ do {
+ pInvalidNode = 0;
+ pNewSttNd = rPtIdx.GetNode().StartOfSectionNode();
+
+ const SwStartNode *pSttNd = pNewSttNd, *pEndNd = pOldSttNd;
+ if( pSttNd->EndOfSectionIndex() >
+ pEndNd->EndOfSectionIndex() )
+ {
+ pEndNd = pNewSttNd;
+ pSttNd = pOldSttNd;
+ }
+
+ while( pSttNd->GetIndex() > pEndNd->GetIndex() )
+ {
+ if( !pSttNd->IsSectionNode() )
+ pInvalidNode = pSttNd;
+ pSttNd = pSttNd->StartOfSectionNode();
+ }
+ if( pInvalidNode )
+ {
+ if( bMoveDown )
+ {
+ rPtIdx.Assign( *pInvalidNode->EndOfSectionNode(), 1 );
+
+ if( !rPtIdx.GetNode().IsCntntNode() &&
+ ( !pDoc->GetNodes().GoNextSection( &rPtIdx ) ||
+ rPtIdx > pOldSttNd->EndOfSectionIndex() ) )
+ break;
+ }
+ else
+ {
+ rPtIdx.Assign( *pInvalidNode, -1 );
+
+ if( !rPtIdx.GetNode().IsCntntNode() &&
+ ( !pDoc->GetNodes().GoPrevSection( &rPtIdx ) ||
+ rPtIdx < *pOldSttNd ) )
+ break;
+ }
+ }
+ else
+ bValidPos = sal_True;
+ } while ( pInvalidNode );
+ }
+
+ if( bValidPos )
+ {
+ SwCntntNode* pCNd = GetCntntNode();
+ sal_uInt16 nCnt = 0;
+ if( pCNd && !bMoveDown )
+ nCnt = pCNd->Len();
+ GetPoint()->nContent.Assign( pCNd, nCnt );
+ }
+ else
+ {
+ rPtIdx = GetSavePos()->nNode;
+ GetPoint()->nContent.Assign( GetCntntNode(), GetSavePos()->nCntnt );
+ return sal_True;
+ }
+ }
+ }
+ return SwCursor::IsSelOvr( eFlags );
+}
+
+
+/* */
+
+SwUnoTableCrsr::SwUnoTableCrsr(const SwPosition& rPos)
+ : SwCursor(rPos,0,false), SwUnoCrsr(rPos), SwTableCursor(rPos), aTblSel(rPos,0,false)
+{
+ SetRemainInSection(sal_False);
+}
+
+SwUnoTableCrsr::~SwUnoTableCrsr()
+{
+ while( aTblSel.GetNext() != &aTblSel )
+ delete aTblSel.GetNext(); // und loeschen
+}
+
+sal_Bool SwUnoTableCrsr::IsSelOvr( int eFlags )
+{
+ sal_Bool bRet = SwUnoCrsr::IsSelOvr( eFlags );
+ if( !bRet )
+ {
+ const SwTableNode* pTNd = GetPoint()->nNode.GetNode().FindTableNode();
+ bRet = !(pTNd == GetDoc()->GetNodes()[ GetSavePos()->nNode ]->
+ FindTableNode() && (!HasMark() ||
+ pTNd == GetMark()->nNode.GetNode().FindTableNode() ));
+ }
+ return bRet;
+}
+
+void SwUnoTableCrsr::MakeBoxSels()
+{
+ const SwCntntNode* pCNd;
+ bool bMakeTblCrsrs = true;
+ if( GetPoint()->nNode.GetIndex() && GetMark()->nNode.GetIndex() &&
+ 0 != ( pCNd = GetCntntNode() ) && pCNd->getLayoutFrm( pCNd->GetDoc()->GetCurrentLayout() ) &&
+ 0 != ( pCNd = GetCntntNode(sal_False) ) && pCNd->getLayoutFrm( pCNd->GetDoc()->GetCurrentLayout() ) )
+ bMakeTblCrsrs = GetDoc()->GetCurrentLayout()->MakeTblCrsrs( *this );
+
+ if ( !bMakeTblCrsrs )
+ {
+ SwSelBoxes& rTmpBoxes = (SwSelBoxes&)GetBoxes();
+ sal_uInt16 nCount = 0;
+ while( nCount < rTmpBoxes.Count() )
+ DeleteBox( nCount );
+ }
+
+ if( IsChgd() )
+ {
+ SwTableCursor::MakeBoxSels( &aTblSel );
+ if( !GetBoxesCount() )
+ {
+ const SwTableBox* pBox;
+ const SwNode* pBoxNd = GetPoint()->nNode.GetNode().FindTableBoxStartNode();
+ const SwTableNode* pTblNd = pBoxNd ? pBoxNd->FindTableNode() : 0;
+ if( pTblNd && 0 != ( pBox = pTblNd->GetTable().GetTblBox( pBoxNd->GetIndex() )) )
+ InsertBox( *pBox );
+ }
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/crsr/viscrs.cxx b/sw/source/core/crsr/viscrs.cxx
new file mode 100644
index 000000000000..2f333f708486
--- /dev/null
+++ b/sw/source/core/crsr/viscrs.cxx
@@ -0,0 +1,758 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+
+#ifndef _SVSTDARR_HXX
+#define _SVSTDARR_USHORTS
+#include <svl/svstdarr.hxx>
+#endif
+
+#include <vcl/dialog.hxx>
+#include <vcl/msgbox.hxx>
+#include <vcl/wrkwin.hxx>
+#include <viewopt.hxx>
+#include <frmtool.hxx>
+#include <viscrs.hxx>
+#include <crsrsh.hxx>
+#include <doc.hxx>
+#include <swtable.hxx>
+#include <viewimp.hxx>
+#include <dview.hxx>
+#include <rootfrm.hxx>
+#include <txtfrm.hxx> // SwTxtFrm
+#include <docary.hxx>
+#include <extinput.hxx>
+#include <ndtxt.hxx>
+#include <scriptinfo.hxx>
+#include <mdiexp.hxx> // GetSearchDialog
+#include <comcore.hrc> // ResId for query when (switching to?) Search & Replace
+
+#include <svx/sdr/overlay/overlaymanager.hxx>
+#include <svx/sdrpaintwindow.hxx>
+#include <vcl/svapp.hxx>
+#include <svx/sdr/overlay/overlayselection.hxx>
+
+extern void SwCalcPixStatics( OutputDevice *pOut );
+
+// Here static members are defined. They will get changed on alteration of the
+// MapMode. This is done so that on ShowCrsr the same size does not have to be
+// expensively determined again and again.
+
+long SwSelPaintRects::nPixPtX = 0;
+long SwSelPaintRects::nPixPtY = 0;
+MapMode* SwSelPaintRects::pMapMode = 0;
+
+// ----- Starting from here: classes / methods for the non-text-cursor -----
+
+SwVisCrsr::SwVisCrsr( const SwCrsrShell * pCShell )
+ : pCrsrShell( pCShell )
+{
+ pCShell->GetWin()->SetCursor( &aTxtCrsr );
+ bIsVisible = aTxtCrsr.IsVisible();
+ bIsDragCrsr = sal_False;
+ aTxtCrsr.SetWidth( 0 );
+
+#ifdef SW_CRSR_TIMER
+ bTimerOn = sal_True;
+ SetTimeout( 50 ); // 50 millisecond delay
+#endif
+}
+
+
+
+SwVisCrsr::~SwVisCrsr()
+{
+#ifdef SW_CRSR_TIMER
+ if( bTimerOn )
+ Stop(); // stop timer
+#endif
+
+ if( bIsVisible && aTxtCrsr.IsVisible() )
+ aTxtCrsr.Hide();
+
+ pCrsrShell->GetWin()->SetCursor( 0 );
+}
+
+
+
+
+void SwVisCrsr::Show()
+{
+ if( !bIsVisible )
+ {
+ bIsVisible = sal_True;
+
+ // display at all?
+ if( pCrsrShell->VisArea().IsOver( pCrsrShell->aCharRect ) )
+#ifdef SW_CRSR_TIMER
+ {
+ if( bTimerOn )
+ Start(); // start timer
+ else
+ {
+ if( IsActive() )
+ Stop(); // stop timer
+
+ _SetPosAndShow();
+ }
+ }
+#else
+ _SetPosAndShow();
+#endif
+ }
+}
+
+
+
+void SwVisCrsr::Hide()
+{
+ if( bIsVisible )
+ {
+ bIsVisible = sal_False;
+
+#ifdef SW_CRSR_TIMER
+ if( IsActive() )
+ Stop(); // stop timer
+#endif
+
+ if( aTxtCrsr.IsVisible() ) // Shouldn't the flags be in effect?
+ aTxtCrsr.Hide();
+ }
+}
+
+#ifdef SW_CRSR_TIMER
+
+void SwVisCrsr::Timeout()
+{
+ OSL_ENSURE( !bIsDragCrsr, "Timer vorher abschalten" );
+ if( bIsVisible )
+ {
+ if ( !pCrsrShell->GetWin() ) // SwFrmFmt::GetGraphic suspends Win temporarily!
+ Start();
+ else
+ _SetPosAndShow();
+ }
+}
+
+sal_Bool SwCrsrShell::ChgCrsrTimerFlag( sal_Bool bTimerOn )
+{
+ return pVisCrsr->ChgTimerFlag( bTimerOn );
+}
+
+
+sal_Bool SwVisCrsr::ChgTimerFlag( sal_Bool bFlag )
+{
+ bOld = bTimerOn;
+ if( !bFlag && bIsVisible && IsActive() )
+ {
+ Stop(); // stop timer
+ _SetPosAndShow();
+ }
+ bTimerOn = bFlag;
+ return bOld;
+}
+
+#endif
+
+
+void SwVisCrsr::_SetPosAndShow()
+{
+ SwRect aRect;
+ long nTmpY = pCrsrShell->aCrsrHeight.Y();
+ if( 0 > nTmpY )
+ {
+ nTmpY = -nTmpY;
+ aTxtCrsr.SetOrientation( 900 );
+ aRect = SwRect( pCrsrShell->aCharRect.Pos(),
+ Size( pCrsrShell->aCharRect.Height(), nTmpY ) );
+ aRect.Pos().X() += pCrsrShell->aCrsrHeight.X();
+ if( pCrsrShell->IsOverwriteCrsr() )
+ aRect.Pos().Y() += aRect.Width();
+ }
+ else
+ {
+ aTxtCrsr.SetOrientation( 0 );
+ aRect = SwRect( pCrsrShell->aCharRect.Pos(),
+ Size( pCrsrShell->aCharRect.Width(), nTmpY ) );
+ aRect.Pos().Y() += pCrsrShell->aCrsrHeight.X();
+ }
+
+ // check if cursor should show the current cursor bidi level
+ aTxtCrsr.SetDirection( CURSOR_DIRECTION_NONE );
+ const SwCursor* pTmpCrsr = pCrsrShell->_GetCrsr();
+
+ if ( pTmpCrsr && !pCrsrShell->IsOverwriteCrsr() )
+ {
+ SwNode& rNode = pTmpCrsr->GetPoint()->nNode.GetNode();
+ if( rNode.IsTxtNode() )
+ {
+ const SwTxtNode& rTNd = *rNode.GetTxtNode();
+ const SwFrm* pFrm = rTNd.getLayoutFrm( pCrsrShell->GetLayout(), 0, 0, sal_False );
+ if ( pFrm )
+ {
+ const SwScriptInfo* pSI = ((SwTxtFrm*)pFrm)->GetScriptInfo();
+ // cursor level has to be shown
+ if ( pSI && pSI->CountDirChg() > 1 )
+ {
+ aTxtCrsr.SetDirection(
+ ( pTmpCrsr->GetCrsrBidiLevel() % 2 ) ?
+ CURSOR_DIRECTION_RTL :
+ CURSOR_DIRECTION_LTR );
+ }
+
+ if ( pFrm->IsRightToLeft() )
+ {
+ const OutputDevice *pOut = pCrsrShell->GetOut();
+ if ( pOut )
+ {
+ long nSize = pOut->GetSettings().GetStyleSettings().GetCursorSize();
+ Size aSize( nSize, nSize );
+ aSize = pOut->PixelToLogic( aSize );
+ aRect.Left( aRect.Left() - aSize.Width() );
+ }
+ }
+ }
+ }
+ }
+
+ if( aRect.Height() )
+ {
+ ::SwCalcPixStatics( pCrsrShell->GetOut() );
+ ::SwAlignRect( aRect, (ViewShell*)pCrsrShell );
+ }
+ if( !pCrsrShell->IsOverwriteCrsr() || bIsDragCrsr ||
+ pCrsrShell->IsSelection() )
+ aRect.Width( 0 );
+
+ aTxtCrsr.SetSize( aRect.SSize() );
+
+ aTxtCrsr.SetPos( aRect.Pos() );
+ if ( !pCrsrShell->IsCrsrReadonly() || pCrsrShell->GetViewOptions()->IsSelectionInReadonly() )
+ {
+ if ( pCrsrShell->GetDrawView() )
+ ((SwDrawView*)pCrsrShell->GetDrawView())->SetAnimationEnabled(
+ !pCrsrShell->IsSelection() );
+
+ sal_uInt16 nStyle = bIsDragCrsr ? CURSOR_SHADOW : 0;
+ if( nStyle != aTxtCrsr.GetStyle() )
+ {
+ aTxtCrsr.SetStyle( nStyle );
+ aTxtCrsr.SetWindow( bIsDragCrsr ? pCrsrShell->GetWin() : 0 );
+ }
+
+ aTxtCrsr.Show();
+ }
+}
+
+//////////////////////////////////////////////////////////////////////////////
+
+SwSelPaintRects::SwSelPaintRects( const SwCrsrShell& rCSh )
+: SwRects( 0 ),
+ pCShell( &rCSh ),
+ mpCursorOverlay(0)
+{
+}
+
+SwSelPaintRects::~SwSelPaintRects()
+{
+ Hide();
+}
+
+void SwSelPaintRects::swapContent(SwSelPaintRects& rSwap)
+{
+ SwRects aTempRects;
+ aTempRects.Insert(this, 0);
+
+ Remove(0, Count());
+ Insert(&rSwap, 0);
+
+ rSwap.Remove(0, rSwap.Count());
+ rSwap.Insert(&aTempRects, 0);
+
+ // #i75172# also swap mpCursorOverlay
+ sdr::overlay::OverlayObject* pTempOverlay = getCursorOverlay();
+ setCursorOverlay(rSwap.getCursorOverlay());
+ rSwap.setCursorOverlay(pTempOverlay);
+}
+
+void SwSelPaintRects::Hide()
+{
+ if(mpCursorOverlay)
+ {
+ delete mpCursorOverlay;
+ mpCursorOverlay = 0;
+ }
+
+ SwRects::Remove( 0, Count() );
+}
+
+void SwSelPaintRects::Show()
+{
+ SdrView* pView = (SdrView*)pCShell->GetDrawView();
+
+ if(pView && pView->PaintWindowCount())
+ {
+ // reset rects
+ SwRects::Remove( 0, SwRects::Count() );
+ FillRects();
+
+ // get new rects
+ std::vector< basegfx::B2DRange > aNewRanges;
+
+ for(sal_uInt16 a(0); a < Count(); a++)
+ {
+ const SwRect aNextRect((*this)[a]);
+ const Rectangle aPntRect(aNextRect.SVRect());
+
+ aNewRanges.push_back(basegfx::B2DRange(
+ aPntRect.Left(), aPntRect.Top(),
+ aPntRect.Right() + 1, aPntRect.Bottom() + 1));
+ }
+
+ if(mpCursorOverlay)
+ {
+ if(aNewRanges.size())
+ {
+ static_cast< sdr::overlay::OverlaySelection* >(mpCursorOverlay)->setRanges(aNewRanges);
+ }
+ else
+ {
+ delete mpCursorOverlay;
+ mpCursorOverlay = 0;
+ }
+ }
+ else if(Count())
+ {
+ SdrPaintWindow* pCandidate = pView->GetPaintWindow(0);
+ sdr::overlay::OverlayManager* pTargetOverlay = pCandidate->GetOverlayManager();
+
+ if(pTargetOverlay)
+ {
+ // #i97672# get the system's highlight color and limit it to the maximum
+ // allowed luminance. This is needed to react on too bright highlight colors
+ // which would otherwise vive a bad visualisation.
+ const OutputDevice *pOut = Application::GetDefaultDevice();
+ Color aHighlight(pOut->GetSettings().GetStyleSettings().GetHighlightColor());
+ const SvtOptionsDrawinglayer aSvtOptionsDrawinglayer;
+ const basegfx::BColor aSelection(aHighlight.getBColor());
+ const double fLuminance(aSelection.luminance());
+ const double fMaxLum(aSvtOptionsDrawinglayer.GetSelectionMaximumLuminancePercent() / 100.0);
+
+ if(fLuminance > fMaxLum)
+ {
+ const double fFactor(fMaxLum / fLuminance);
+ const basegfx::BColor aNewSelection(
+ aSelection.getRed() * fFactor,
+ aSelection.getGreen() * fFactor,
+ aSelection.getBlue() * fFactor);
+
+ aHighlight = Color(aNewSelection);
+ }
+
+ // create correct selection
+ mpCursorOverlay = new sdr::overlay::OverlaySelection(
+ sdr::overlay::OVERLAY_TRANSPARENT,
+ aHighlight,
+ aNewRanges,
+ true);
+
+ pTargetOverlay->add(*mpCursorOverlay);
+ }
+ }
+ }
+}
+
+void SwSelPaintRects::Invalidate( const SwRect& rRect )
+{
+ sal_uInt16 nSz = Count();
+ if( !nSz )
+ return;
+
+ SwRegionRects aReg( GetShell()->VisArea() );
+ aReg.Remove( 0, aReg.Count() );
+ aReg.Insert( this, 0 );
+ aReg -= rRect;
+ SwRects::Remove( 0, nSz );
+ SwRects::Insert( &aReg, 0 );
+
+ // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+ // If the selection is to the right or at the bottom, outside the
+ // visible area, it is never aligned on one pixel at the right/bottom.
+ // This has to be determined here and if that is the case the
+ // rectangle has to be expanded.
+ // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+ if( GetShell()->bVisPortChgd && 0 != ( nSz = Count()) )
+ {
+ SwSelPaintRects::Get1PixelInLogic( *GetShell() );
+ SwRect* pRect = (SwRect*)GetData();
+ for( ; nSz--; ++pRect )
+ {
+ if( pRect->Right() == GetShell()->aOldRBPos.X() )
+ pRect->Right( pRect->Right() + nPixPtX );
+ if( pRect->Bottom() == GetShell()->aOldRBPos.Y() )
+ pRect->Bottom( pRect->Bottom() + nPixPtY );
+ }
+ }
+}
+
+void SwSelPaintRects::Paint( const Rectangle& /*rRect*/ )
+{
+ // nothing to do with overlays
+}
+
+
+// check current MapMode of the shell and set possibly the static members.
+// Optional set the parameters pX, pY
+void SwSelPaintRects::Get1PixelInLogic( const ViewShell& rSh,
+ long* pX, long* pY )
+{
+ const OutputDevice* pOut = rSh.GetWin();
+ if ( ! pOut )
+ pOut = rSh.GetOut();
+
+ const MapMode& rMM = pOut->GetMapMode();
+ if( pMapMode->GetMapUnit() != rMM.GetMapUnit() ||
+ pMapMode->GetScaleX() != rMM.GetScaleX() ||
+ pMapMode->GetScaleY() != rMM.GetScaleY() )
+ {
+ *pMapMode = rMM;
+ Size aTmp( 1, 1 );
+ aTmp = pOut->PixelToLogic( aTmp );
+ nPixPtX = aTmp.Width();
+ nPixPtY = aTmp.Height();
+ }
+ if( pX )
+ *pX = nPixPtX;
+ if( pY )
+ *pY = nPixPtY;
+}
+
+
+/* */
+
+SwShellCrsr::SwShellCrsr( const SwCrsrShell& rCShell, const SwPosition &rPos )
+ : SwCursor(rPos,0,false), SwSelPaintRects(rCShell), pPt(SwPaM::GetPoint())
+{}
+
+
+SwShellCrsr::SwShellCrsr( const SwCrsrShell& rCShell, const SwPosition &rPos,
+ const Point& rPtPos, SwPaM* pRing )
+ : SwCursor(rPos, pRing, false), SwSelPaintRects(rCShell), aMkPt(rPtPos),
+ aPtPt(rPtPos), pPt(SwPaM::GetPoint())
+{}
+
+
+SwShellCrsr::SwShellCrsr( SwShellCrsr& rICrsr )
+ : SwCursor(rICrsr), SwSelPaintRects(*rICrsr.GetShell()),
+ aMkPt(rICrsr.GetMkPos()), aPtPt(rICrsr.GetPtPos()), pPt(SwPaM::GetPoint())
+{}
+
+SwShellCrsr::~SwShellCrsr() {}
+
+
+bool SwShellCrsr::IsReadOnlyAvailable() const
+{
+ return GetShell()->IsReadOnlyAvailable();
+}
+
+void SwShellCrsr::SetMark()
+{
+ if( SwPaM::GetPoint() == pPt )
+ aMkPt = aPtPt;
+ else
+ aPtPt = aMkPt;
+ SwPaM::SetMark();
+}
+
+void SwShellCrsr::FillRects()
+{
+ // calculate the new rectangles
+ if( HasMark() &&
+ GetPoint()->nNode.GetNode().IsCntntNode() &&
+ GetPoint()->nNode.GetNode().GetCntntNode()->getLayoutFrm( GetShell()->GetLayout() ) &&
+ (GetMark()->nNode == GetPoint()->nNode ||
+ (GetMark()->nNode.GetNode().IsCntntNode() &&
+ GetMark()->nNode.GetNode().GetCntntNode()->getLayoutFrm( GetShell()->GetLayout() ) ) ))
+ GetShell()->GetLayout()->CalcFrmRects( *this, GetShell()->IsTableMode() ); //swmod 071107//swmod 071225
+}
+
+
+void SwShellCrsr::Show()
+{
+ SwShellCrsr * pTmp = this;
+ do {
+ pTmp->SwSelPaintRects::Show();
+ } while( this != ( pTmp = dynamic_cast<SwShellCrsr*>(pTmp->GetNext()) ) );
+}
+
+
+ // This rectangle gets painted anew, therefore the SSelection in this
+ // area is invalid.
+void SwShellCrsr::Invalidate( const SwRect& rRect )
+{
+ SwShellCrsr * pTmp = this;
+
+ do
+ {
+ pTmp->SwSelPaintRects::Invalidate( rRect );
+
+ // skip any non SwShellCrsr objects in the ring
+ // (see:SwAutoFormat::DeleteSel()
+ Ring* pTmpRing = pTmp;
+ pTmp = 0;
+ do
+ {
+ pTmpRing = pTmpRing->GetNext();
+ pTmp = dynamic_cast<SwShellCrsr*>(pTmpRing);
+ }
+ while ( !pTmp );
+ }
+ while( this != pTmp );
+}
+
+
+void SwShellCrsr::Hide()
+{
+ SwShellCrsr * pTmp = this;
+ do {
+ pTmp->SwSelPaintRects::Hide();
+ } while( this != ( pTmp = dynamic_cast<SwShellCrsr*>(pTmp->GetNext()) ) );
+}
+
+SwCursor* SwShellCrsr::Create( SwPaM* pRing ) const
+{
+ return new SwShellCrsr( *GetShell(), *GetPoint(), GetPtPos(), pRing );
+}
+
+
+short SwShellCrsr::MaxReplaceArived()
+{
+ short nRet = RET_YES;
+ Window* pDlg = LAYOUT_THIS_WINDOW (::GetSearchDialog());
+ if( pDlg )
+ {
+ // Terminate old actions. The table-frames get constructed and
+ // a SSelection can be created.
+ SvUShorts aArr;
+ sal_uInt16 nActCnt;
+ ViewShell *pShell = const_cast< SwCrsrShell* >( GetShell() ),
+ *pSh = pShell;
+ do {
+ for( nActCnt = 0; pSh->ActionPend(); ++nActCnt )
+ pSh->EndAction();
+ aArr.Insert( nActCnt, aArr.Count() );
+ } while( pShell != ( pSh = (ViewShell*)pSh->GetNext() ) );
+
+ {
+ nRet = QueryBox( pDlg, SW_RES( MSG_COMCORE_ASKSEARCH )).Execute();
+ }
+
+ for( sal_uInt16 n = 0; n < aArr.Count(); ++n )
+ {
+ for( nActCnt = aArr[n]; nActCnt--; )
+ pSh->StartAction();
+ pSh = (ViewShell*)pSh->GetNext();
+ } //swmod 071107//swmod 071225
+ }
+ else
+ // otherwise from the Basic, and than switch to RET_YES
+ nRet = RET_YES;
+
+ return nRet;
+}
+
+void SwShellCrsr::SaveTblBoxCntnt( const SwPosition* pPos )
+{
+ ((SwCrsrShell*)GetShell())->SaveTblBoxCntnt( pPos );
+}
+
+sal_Bool SwShellCrsr::UpDown( sal_Bool bUp, sal_uInt16 nCnt )
+{
+ return SwCursor::UpDown( bUp, nCnt,
+ &GetPtPos(), GetShell()->GetUpDownX() );
+}
+
+#if OSL_DEBUG_LEVEL > 1
+
+// JP 05.03.98: To test the UNO-Crsr behavior here the implementation on the
+// visible cursor.
+
+sal_Bool SwShellCrsr::IsSelOvr( int eFlags )
+{
+ return SwCursor::IsSelOvr( eFlags );
+}
+
+#endif
+
+// TRUE: The cursor can be set to the position.
+sal_Bool SwShellCrsr::IsAtValidPos( sal_Bool bPoint ) const
+{
+ if( GetShell() && ( GetShell()->IsAllProtect() ||
+ GetShell()->GetViewOptions()->IsReadonly() ||
+ ( GetShell()->Imp()->GetDrawView() &&
+ GetShell()->Imp()->GetDrawView()->GetMarkedObjectList().GetMarkCount() )))
+ return sal_True;
+
+ return SwCursor::IsAtValidPos( bPoint );
+}
+
+/* */
+
+SwShellTableCrsr::SwShellTableCrsr( const SwCrsrShell& rCrsrSh,
+ const SwPosition& rPos )
+ : SwCursor(rPos,0,false), SwShellCrsr(rCrsrSh, rPos), SwTableCursor(rPos)
+{
+}
+
+SwShellTableCrsr::SwShellTableCrsr( const SwCrsrShell& rCrsrSh,
+ const SwPosition& rMkPos, const Point& rMkPt,
+ const SwPosition& rPtPos, const Point& rPtPt )
+ : SwCursor(rPtPos,0,false), SwShellCrsr(rCrsrSh, rPtPos), SwTableCursor(rPtPos)
+{
+ SetMark();
+ *GetMark() = rMkPos;
+ GetMkPos() = rMkPt;
+ GetPtPos() = rPtPt;
+}
+
+SwShellTableCrsr::~SwShellTableCrsr() {}
+
+void SwShellTableCrsr::SetMark() { SwShellCrsr::SetMark(); }
+
+SwCursor* SwShellTableCrsr::Create( SwPaM* pRing ) const
+{
+ return SwShellCrsr::Create( pRing );
+}
+short SwShellTableCrsr::MaxReplaceArived()
+{
+ return SwShellCrsr::MaxReplaceArived();
+}
+void SwShellTableCrsr::SaveTblBoxCntnt( const SwPosition* pPos )
+{
+ SwShellCrsr::SaveTblBoxCntnt( pPos );
+}
+
+
+void SwShellTableCrsr::FillRects()
+{
+ // Calculate the new rectangles.
+ // JP 16.01.98: If the cursor is still "parked" do nothing!!
+ if( !aSelBoxes.Count() || bParked ||
+ !GetPoint()->nNode.GetIndex() )
+ return;
+
+ SwRegionRects aReg( GetShell()->VisArea() );
+ SwNodes& rNds = GetDoc()->GetNodes();
+ for( sal_uInt16 n = 0; n < aSelBoxes.Count(); ++n )
+ {
+ const SwStartNode* pSttNd = (*(aSelBoxes.GetData() + n ))->GetSttNd();
+ const SwTableNode* pSelTblNd = pSttNd->FindTableNode();
+
+ SwNodeIndex aIdx( *pSttNd );
+ SwCntntNode* pCNd = rNds.GoNextSection( &aIdx, sal_True, sal_False );
+
+ // TABLE IN TABLE
+ // (see also lcl_FindTopLevelTable in unoobj2.cxx for a different
+ // version to do this)
+ const SwTableNode* pCurTblNd = pCNd->FindTableNode();
+ while ( pSelTblNd != pCurTblNd && pCurTblNd )
+ {
+ aIdx = pCurTblNd->EndOfSectionIndex();
+ pCNd = rNds.GoNextSection( &aIdx, sal_True, sal_False );
+ pCurTblNd = pCNd->FindTableNode();
+ }
+
+ if( !pCNd )
+ continue;
+
+ SwFrm* pFrm = pCNd->getLayoutFrm( GetShell()->GetLayout(), &GetSttPos() );
+ while( pFrm && !pFrm->IsCellFrm() )
+ pFrm = pFrm->GetUpper();
+
+ OSL_ENSURE( pFrm, "Node nicht in einer Tabelle" );
+
+ while ( pFrm )
+ {
+ if( pFrm && aReg.GetOrigin().IsOver( pFrm->Frm() ) )
+ aReg -= pFrm->Frm();
+
+ pFrm = pFrm->GetNextCellLeaf( MAKEPAGE_NONE );
+ }
+ }
+ aReg.Invert();
+ Insert( &aReg, 0 );
+}
+
+
+// Check if the SPoint is within the Table-SSelection.
+sal_Bool SwShellTableCrsr::IsInside( const Point& rPt ) const
+{
+ // Calculate the new rectangles.
+ // JP 16.01.98: If the cursor is still "parked" do nothing!!
+ if( !aSelBoxes.Count() || bParked ||
+ !GetPoint()->nNode.GetIndex() )
+ return sal_False;
+
+ SwNodes& rNds = GetDoc()->GetNodes();
+ for( sal_uInt16 n = 0; n < aSelBoxes.Count(); ++n )
+ {
+ SwNodeIndex aIdx( *(*(aSelBoxes.GetData() + n ))->GetSttNd() );
+ SwCntntNode* pCNd = rNds.GoNextSection( &aIdx, sal_True, sal_False );
+ if( !pCNd )
+ continue;
+
+ SwFrm* pFrm = pCNd->getLayoutFrm( GetShell()->GetLayout(), &GetPtPos() );
+ while( pFrm && !pFrm->IsCellFrm() )
+ pFrm = pFrm->GetUpper();
+ OSL_ENSURE( pFrm, "Node nicht in einer Tabelle" );
+ if( pFrm && pFrm->Frm().IsInside( rPt ) )
+ return sal_True;
+ }
+ return sal_False;
+}
+
+#if OSL_DEBUG_LEVEL > 1
+
+// JP 05.03.98: To test the UNO-Crsr behavior here the implementation on the
+// visible cursor.
+sal_Bool SwShellTableCrsr::IsSelOvr( int eFlags )
+{
+ return SwShellCrsr::IsSelOvr( eFlags );
+}
+
+#endif
+
+sal_Bool SwShellTableCrsr::IsAtValidPos( sal_Bool bPoint ) const
+{
+ return SwShellCrsr::IsAtValidPos( bPoint );
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/doc/SwStyleNameMapper.cxx b/sw/source/core/doc/SwStyleNameMapper.cxx
new file mode 100644
index 000000000000..eb653789da52
--- /dev/null
+++ b/sw/source/core/doc/SwStyleNameMapper.cxx
@@ -0,0 +1,1146 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+
+#include <SwStyleNameMapper.hxx>
+#define _SVSTDARR_STRINGSDTOR
+#include <svl/svstdarr.hxx>
+#include <tools/resmgr.hxx>
+#include <poolfmt.hxx>
+#include <rcid.hrc>
+#include <tools/debug.hxx>
+#ifdef _NEED_TO_DEBUG_MAPPING
+#include <stdlib.h>
+#endif
+
+extern ResMgr* pSwResMgr;
+// Initialise UI names to 0
+SvStringsDtor *SwStyleNameMapper::pTextUINameArray = 0,
+ *SwStyleNameMapper::pListsUINameArray = 0,
+ *SwStyleNameMapper::pExtraUINameArray = 0,
+ *SwStyleNameMapper::pRegisterUINameArray = 0,
+ *SwStyleNameMapper::pDocUINameArray = 0,
+ *SwStyleNameMapper::pHTMLUINameArray = 0,
+ *SwStyleNameMapper::pFrmFmtUINameArray = 0,
+ *SwStyleNameMapper::pChrFmtUINameArray = 0,
+ *SwStyleNameMapper::pHTMLChrFmtUINameArray = 0,
+ *SwStyleNameMapper::pPageDescUINameArray = 0,
+ *SwStyleNameMapper::pNumRuleUINameArray = 0,
+
+// Initialise programmatic names to 0
+ *SwStyleNameMapper::pTextProgNameArray = 0,
+ *SwStyleNameMapper::pListsProgNameArray = 0,
+ *SwStyleNameMapper::pExtraProgNameArray = 0,
+ *SwStyleNameMapper::pRegisterProgNameArray = 0,
+ *SwStyleNameMapper::pDocProgNameArray = 0,
+ *SwStyleNameMapper::pHTMLProgNameArray = 0,
+ *SwStyleNameMapper::pFrmFmtProgNameArray = 0,
+ *SwStyleNameMapper::pChrFmtProgNameArray = 0,
+ *SwStyleNameMapper::pHTMLChrFmtProgNameArray = 0,
+ *SwStyleNameMapper::pPageDescProgNameArray = 0,
+ *SwStyleNameMapper::pNumRuleProgNameArray = 0;
+
+NameToIdHash *SwStyleNameMapper::pParaUIMap = 0,
+ *SwStyleNameMapper::pCharUIMap = 0,
+ *SwStyleNameMapper::pPageUIMap = 0,
+ *SwStyleNameMapper::pFrameUIMap = 0,
+ *SwStyleNameMapper::pNumRuleUIMap = 0,
+
+ *SwStyleNameMapper::pParaProgMap = 0,
+ *SwStyleNameMapper::pCharProgMap = 0,
+ *SwStyleNameMapper::pPageProgMap = 0,
+ *SwStyleNameMapper::pFrameProgMap = 0,
+ *SwStyleNameMapper::pNumRuleProgMap = 0;
+
+// SwTableEntry so we can pass the length to the String CTOR
+struct SwTableEntry
+{
+ sal_uInt8 nLength;
+ const sal_Char *pChar;
+};
+
+#define ENTRY( s ) { sizeof (s)-1, s }
+
+// Hard coded Programmatic Name tables
+const struct SwTableEntry TextProgNameTable [] =
+{
+ ENTRY( "Standard" ), // RES_POOLCOLL_STANDARD
+ ENTRY( "Text body" ),
+ ENTRY( "First line indent" ),
+ ENTRY( "Hanging indent" ),
+ ENTRY( "Text body indent" ),
+ ENTRY( "Salutation" ),
+ ENTRY( "Signature" ),
+ ENTRY( "List Indent" ), // RES_POOLCOLL_CONFRONTATION
+ ENTRY( "Marginalia" ),
+ ENTRY( "Heading" ),
+ ENTRY( "Heading 1" ),
+ ENTRY( "Heading 2" ),
+ ENTRY( "Heading 3" ),
+ ENTRY( "Heading 4" ),
+ ENTRY( "Heading 5" ),
+ ENTRY( "Heading 6" ),
+ ENTRY( "Heading 7" ),
+ ENTRY( "Heading 8" ),
+ ENTRY( "Heading 9" ),
+ ENTRY( "Heading 10" ), // RES_POOLCOLL_TEXT_END
+ { 0, NULL }
+};
+
+const struct SwTableEntry ListsProgNameTable [] =
+{
+ ENTRY( "List" ), // STR_POCO_PRGM_NUMBUL_BASE
+ ENTRY( "Numbering 1 Start" ), // STR_POCO_PRGM_NUM_LEVEL1S
+ ENTRY( "Numbering 1" ),
+ ENTRY( "Numbering 1 End" ),
+ ENTRY( "Numbering 1 Cont." ),
+ ENTRY( "Numbering 2 Start" ),
+ ENTRY( "Numbering 2" ),
+ ENTRY( "Numbering 2 End" ),
+ ENTRY( "Numbering 2 Cont." ),
+ ENTRY( "Numbering 3 Start" ),
+ ENTRY( "Numbering 3" ),
+ ENTRY( "Numbering 3 End" ),
+ ENTRY( "Numbering 3 Cont." ),
+ ENTRY( "Numbering 4 Start" ),
+ ENTRY( "Numbering 4" ),
+ ENTRY( "Numbering 4 End" ),
+ ENTRY( "Numbering 4 Cont." ),
+ ENTRY( "Numbering 5 Start" ),
+ ENTRY( "Numbering 5" ),
+ ENTRY( "Numbering 5 End" ),
+ ENTRY( "Numbering 5 Cont." ),
+ ENTRY( "List 1 Start" ),
+ ENTRY( "List 1" ),
+ ENTRY( "List 1 End" ),
+ ENTRY( "List 1 Cont." ),
+ ENTRY( "List 2 Start" ),
+ ENTRY( "List 2" ),
+ ENTRY( "List 2 End" ),
+ ENTRY( "List 2 Cont." ),
+ ENTRY( "List 3 Start" ),
+ ENTRY( "List 3" ),
+ ENTRY( "List 3 End" ),
+ ENTRY( "List 3 Cont." ),
+ ENTRY( "List 4 Start" ),
+ ENTRY( "List 4" ),
+ ENTRY( "List 4 End" ),
+ ENTRY( "List 4 Cont." ),
+ ENTRY( "List 5 Start" ),
+ ENTRY( "List 5" ),
+ ENTRY( "List 5 End" ),
+ ENTRY( "List 5 Cont." ), // STR_POCO_PRGM_BUL_NONUM5
+ { 0, NULL }
+};
+
+const struct SwTableEntry ExtraProgNameTable [] =
+{
+ ENTRY( "Header" ), // RES_POOLCOLL_EXTRA_BEGIN
+ ENTRY( "Header left" ),
+ ENTRY( "Header right" ),
+ ENTRY( "Footer" ),
+ ENTRY( "Footer left" ),
+ ENTRY( "Footer right" ),
+ ENTRY( "Table Contents" ),
+ ENTRY( "Table Heading" ),
+ ENTRY( "Caption" ),
+ ENTRY( "Illustration" ),
+ ENTRY( "Table" ),
+ ENTRY( "Text" ),
+ ENTRY( "Frame contents" ),
+ ENTRY( "Footnote" ),
+ ENTRY( "Addressee" ),
+ ENTRY( "Sender" ),
+ ENTRY( "Endnote" ),
+ ENTRY( "Drawing" ), // RES_POOLCOLL_LABEL_DRAWING
+ { 0, NULL }
+};
+
+const struct SwTableEntry RegisterProgNameTable [] =
+{
+ ENTRY( "Index" ), // STR_POCO_PRGM_REGISTER_BASE
+ ENTRY( "Index Heading" ), // STR_POCO_PRGM_TOX_IDXH
+ ENTRY( "Index 1" ),
+ ENTRY( "Index 2" ),
+ ENTRY( "Index 3" ),
+ ENTRY( "Index Separator" ),
+ ENTRY( "Contents Heading" ),
+ ENTRY( "Contents 1" ),
+ ENTRY( "Contents 2" ),
+ ENTRY( "Contents 3" ),
+ ENTRY( "Contents 4" ),
+ ENTRY( "Contents 5" ),
+ ENTRY( "User Index Heading" ),
+ ENTRY( "User Index 1" ),
+ ENTRY( "User Index 2" ),
+ ENTRY( "User Index 3" ),
+ ENTRY( "User Index 4" ),
+ ENTRY( "User Index 5" ),
+ ENTRY( "Contents 6" ),
+ ENTRY( "Contents 7" ),
+ ENTRY( "Contents 8" ),
+ ENTRY( "Contents 9" ),
+ ENTRY( "Contents 10" ),
+ ENTRY( "Illustration Index Heading" ),
+ ENTRY( "Illustration Index 1" ),
+ ENTRY( "Object index heading" ),
+ ENTRY( "Object index 1" ),
+ ENTRY( "Table index heading" ),
+ ENTRY( "Table index 1" ),
+ ENTRY( "Bibliography Heading" ),
+ ENTRY( "Bibliography 1" ),
+ ENTRY( "User Index 6" ),
+ ENTRY( "User Index 7" ),
+ ENTRY( "User Index 8" ),
+ ENTRY( "User Index 9" ),
+ ENTRY( "User Index 10" ), // STR_POCO_PRGM_TOX_USER10
+ { 0, NULL }
+};
+
+const struct SwTableEntry DocProgNameTable [] =
+{
+ ENTRY( "Title" ), // STR_POCO_PRGM_DOC_TITEL
+ ENTRY( "Subtitle" ),
+ { 0, NULL }
+};
+
+const struct SwTableEntry HTMLProgNameTable [] =
+{
+ ENTRY( "Quotations" ),
+ ENTRY( "Preformatted Text" ),
+ ENTRY( "Horizontal Line" ),
+ ENTRY( "List Contents" ),
+ ENTRY( "List Heading" ), // STR_POCO_PRGM_HTML_DT
+ { 0, NULL }
+};
+
+const struct SwTableEntry FrmFmtProgNameTable [] =
+{
+ ENTRY( "Frame" ), // RES_POOLFRM_FRAME
+ ENTRY( "Graphics" ),
+ ENTRY( "OLE" ),
+ ENTRY( "Formula" ),
+ ENTRY( "Marginalia" ),
+ ENTRY( "Watermark" ),
+ ENTRY( "Labels" ), // RES_POOLFRM_LABEL
+ { 0, NULL }
+};
+
+const struct SwTableEntry ChrFmtProgNameTable [] =
+{
+ ENTRY( "Footnote Symbol" ), // RES_POOLCHR_FOOTNOTE
+ ENTRY( "Page Number" ),
+ ENTRY( "Caption characters" ),
+ ENTRY( "Drop Caps" ),
+ ENTRY( "Numbering Symbols" ),
+ ENTRY( "Bullet Symbols" ),
+ ENTRY( "Internet link" ),
+ ENTRY( "Visited Internet Link" ),
+ ENTRY( "Placeholder" ),
+ ENTRY( "Index Link" ),
+ ENTRY( "Endnote Symbol" ),
+ ENTRY( "Line numbering" ),
+ ENTRY( "Main index entry" ),
+ ENTRY( "Footnote anchor" ),
+ ENTRY( "Endnote anchor" ),
+ ENTRY( "Rubies" ), // RES_POOLCHR_RUBYTEXT
+ ENTRY( "Vertical Numbering Symbols" ), // RES_POOLCHR_VERT_NUMBER
+ { 0, NULL }
+};
+
+const struct SwTableEntry HTMLChrFmtProgNameTable [] =
+{
+ ENTRY( "Emphasis" ), // RES_POOLCHR_HTML_EMPHASIS
+ ENTRY( "Citation" ),
+ ENTRY( "Strong Emphasis" ),
+ ENTRY( "Source Text" ),
+ ENTRY( "Example" ),
+ ENTRY( "User Entry" ),
+ ENTRY( "Variable" ),
+ ENTRY( "Definition" ),
+ ENTRY( "Teletype" ), // RES_POOLCHR_HTML_TELETYPE
+ { 0, NULL }
+};
+
+const struct SwTableEntry PageDescProgNameTable [] =
+{
+ ENTRY( "Standard" ), // STR_POOLPAGE_PRGM_STANDARD
+ ENTRY( "First Page" ),
+ ENTRY( "Left Page" ),
+ ENTRY( "Right Page" ),
+ ENTRY( "Envelope" ),
+ ENTRY( "Index" ),
+ ENTRY( "HTML" ),
+ ENTRY( "Footnote" ),
+ ENTRY( "Endnote" ), // STR_POOLPAGE_PRGM_ENDNOTE
+ ENTRY( "Landscape" ),
+ { 0, NULL }
+};
+
+const struct SwTableEntry NumRuleProgNameTable [] =
+{
+ ENTRY( "Numbering 1" ), // STR_POOLNUMRULE_PRGM_NUM1
+ ENTRY( "Numbering 2" ),
+ ENTRY( "Numbering 3" ),
+ ENTRY( "Numbering 4" ),
+ ENTRY( "Numbering 5" ),
+ ENTRY( "List 1" ),
+ ENTRY( "List 2" ),
+ ENTRY( "List 3" ),
+ ENTRY( "List 4" ),
+ ENTRY( "List 5" ), // STR_POOLNUMRULE_PRGM_BUL5
+ { 0, NULL }
+};
+#undef ENTRY
+
+sal_Bool SwStyleNameMapper::SuffixIsUser ( const String & rString )
+{
+ const sal_Unicode *pChar = rString.GetBuffer();
+ sal_Int32 nLen = rString.Len();
+ sal_Bool bRet = sal_False;
+ if( nLen > 8 &&
+ pChar[nLen-7] == ' ' &&
+ pChar[nLen-6] == '(' &&
+ pChar[nLen-5] == 'u' &&
+ pChar[nLen-4] == 's' &&
+ pChar[nLen-3] == 'e' &&
+ pChar[nLen-2] == 'r' &&
+ pChar[nLen-1] == ')' )
+ bRet = sal_True;
+ return bRet;
+}
+void SwStyleNameMapper::CheckSuffixAndDelete ( String & rString )
+{
+ const sal_Unicode *pChar = rString.GetBuffer();
+ xub_StrLen nLen = rString.Len();
+ if (nLen > 8 &&
+ pChar[nLen-7] == ' ' &&
+ pChar[nLen-6] == '(' &&
+ pChar[nLen-5] == 'u' &&
+ pChar[nLen-4] == 's' &&
+ pChar[nLen-3] == 'e' &&
+ pChar[nLen-2] == 'r' &&
+ pChar[nLen-1] == ')')
+ {
+ rString.Erase ( nLen - 7, 7 );
+ }
+}
+const NameToIdHash & SwStyleNameMapper::getHashTable ( SwGetPoolIdFromName eFlags, sal_Bool bProgName )
+{
+ NameToIdHash *pHash = 0;
+ const SvStringsDtor *pStrings;
+
+ switch ( eFlags )
+ {
+ case nsSwGetPoolIdFromName::GET_POOLID_TXTCOLL:
+ {
+ sal_uInt16 nIndex;
+ sal_uInt16 nId;
+
+ pHash = bProgName ? pParaProgMap : pParaUIMap;
+ if ( !pHash )
+ {
+ pHash = new NameToIdHash ( RES_POOLCOLL_TEXT_END - RES_POOLCOLL_TEXT_BEGIN +
+ RES_POOLCOLL_LISTS_END - RES_POOLCOLL_LISTS_BEGIN +
+ RES_POOLCOLL_EXTRA_END - RES_POOLCOLL_EXTRA_BEGIN +
+ RES_POOLCOLL_REGISTER_END - RES_POOLCOLL_REGISTER_BEGIN +
+ RES_POOLCOLL_DOC_END - RES_POOLCOLL_DOC_BEGIN +
+ RES_POOLCOLL_HTML_END - RES_POOLCOLL_HTML_BEGIN );
+ pStrings = bProgName ? &GetTextProgNameArray() : &GetTextUINameArray();
+ for ( nIndex = 0, nId = RES_POOLCOLL_TEXT_BEGIN ; nId < RES_POOLCOLL_TEXT_END ; nId++,nIndex++ )
+ (*pHash)[(*pStrings)[nIndex]] = nId;
+ pStrings = bProgName ? &GetListsProgNameArray() : &GetListsUINameArray();
+ for ( nIndex = 0, nId = RES_POOLCOLL_LISTS_BEGIN ; nId < RES_POOLCOLL_LISTS_END ; nId++,nIndex++ )
+ (*pHash)[(*pStrings)[nIndex]] = nId;
+ pStrings = bProgName ? &GetExtraProgNameArray() : &GetExtraUINameArray();
+ for ( nIndex = 0, nId = RES_POOLCOLL_EXTRA_BEGIN ; nId < RES_POOLCOLL_EXTRA_END ; nId++,nIndex++ )
+ (*pHash)[(*pStrings)[nIndex]] = nId;
+ pStrings = bProgName ? &GetRegisterProgNameArray() : &GetRegisterUINameArray();
+ for ( nIndex = 0, nId = RES_POOLCOLL_REGISTER_BEGIN ; nId < RES_POOLCOLL_REGISTER_END ; nId++,nIndex++ )
+ (*pHash)[(*pStrings)[nIndex]] = nId;
+ pStrings = bProgName ? &GetDocProgNameArray() : &GetDocUINameArray();
+ for ( nIndex = 0, nId = RES_POOLCOLL_DOC_BEGIN ; nId < RES_POOLCOLL_DOC_END ; nId++,nIndex++ )
+ (*pHash)[(*pStrings)[nIndex]] = nId;
+ pStrings = bProgName ? &GetHTMLProgNameArray() : &GetHTMLUINameArray();
+ for ( nIndex = 0, nId = RES_POOLCOLL_HTML_BEGIN ; nId < RES_POOLCOLL_HTML_END ; nId++,nIndex++ )
+ (*pHash)[(*pStrings)[nIndex]] = nId;
+
+ if ( bProgName )
+ pParaProgMap = pHash;
+ else
+ pParaUIMap = pHash;
+ }
+ }
+ break;
+ case nsSwGetPoolIdFromName::GET_POOLID_CHRFMT:
+ {
+ pHash = bProgName ? pCharProgMap : pCharUIMap;
+ if ( !pHash )
+ {
+ sal_uInt16 nIndex;
+ sal_uInt16 nId;
+
+ pHash = new NameToIdHash ( RES_POOLCHR_NORMAL_END - RES_POOLCHR_NORMAL_BEGIN +
+ RES_POOLCHR_HTML_END - RES_POOLCHR_HTML_BEGIN );
+ pStrings = bProgName ? &GetChrFmtProgNameArray() : &GetChrFmtUINameArray();
+ for ( nIndex = 0, nId = RES_POOLCHR_NORMAL_BEGIN ; nId < RES_POOLCHR_NORMAL_END ; nId++,nIndex++ )
+ (*pHash)[(*pStrings)[nIndex]] = nId;
+ pStrings = bProgName ? &GetHTMLChrFmtProgNameArray() : &GetHTMLChrFmtUINameArray();
+ for ( nIndex = 0, nId = RES_POOLCHR_HTML_BEGIN ; nId < RES_POOLCHR_HTML_END ; nId++,nIndex++ )
+ (*pHash)[(*pStrings)[nIndex]] = nId;
+ if (bProgName )
+ pCharProgMap = pHash;
+ else
+ pCharUIMap = pHash;
+ }
+ }
+ break;
+ case nsSwGetPoolIdFromName::GET_POOLID_FRMFMT:
+ {
+ pHash = bProgName ? pFrameProgMap : pFrameUIMap;
+ if ( !pHash )
+ {
+ pHash = new NameToIdHash ( RES_POOLFRM_END - RES_POOLFRM_BEGIN );
+ pStrings = bProgName ? &GetFrmFmtProgNameArray() : &GetFrmFmtUINameArray();
+ for ( sal_uInt16 nIndex=0,nId = RES_POOLFRM_BEGIN ; nId < RES_POOLFRM_END ; nId++,nIndex++ )
+ (*pHash)[(*pStrings)[nIndex]] = nId;
+ if ( bProgName )
+ pFrameProgMap = pHash;
+ else
+ pFrameUIMap = pHash;
+ }
+ }
+ break;
+ case nsSwGetPoolIdFromName::GET_POOLID_PAGEDESC:
+ {
+ pHash = bProgName ? pPageProgMap : pPageUIMap;
+ if ( !pHash )
+ {
+ pHash = new NameToIdHash ( RES_POOLPAGE_END - RES_POOLPAGE_BEGIN );
+ pStrings = bProgName ? &GetPageDescProgNameArray() : &GetPageDescUINameArray();
+ for ( sal_uInt16 nIndex=0,nId = RES_POOLPAGE_BEGIN ; nId < RES_POOLPAGE_END ; nId++,nIndex++ )
+ (*pHash)[(*pStrings)[nIndex]] = nId;
+ if ( bProgName )
+ pPageProgMap = pHash;
+ else
+ pPageUIMap = pHash;
+ }
+ }
+ break;
+ case nsSwGetPoolIdFromName::GET_POOLID_NUMRULE:
+ {
+ pHash = bProgName ? pNumRuleProgMap : pNumRuleUIMap;
+ if ( !pHash )
+ {
+ pHash = new NameToIdHash ( RES_POOLNUMRULE_END - RES_POOLNUMRULE_BEGIN );
+ pStrings = bProgName ? &GetNumRuleProgNameArray() : &GetNumRuleUINameArray();
+ for ( sal_uInt16 nIndex=0,nId = RES_POOLNUMRULE_BEGIN ; nId < RES_POOLNUMRULE_END ; nId++,nIndex++ )
+ (*pHash)[(*pStrings)[nIndex]] = nId;
+ if ( bProgName )
+ pNumRuleProgMap = pHash;
+ else
+ pNumRuleUIMap = pHash;
+ }
+ }
+ break;
+ }
+#ifdef _NEED_TO_DEBUG_MAPPING
+ static sal_Bool bTested = sal_False;
+ if ( !bTested )
+ {
+ bTested = sal_True;
+ {
+ for ( sal_uInt16 nIndex = 0, nId = RES_POOLCOLL_TEXT_BEGIN ; nId < RES_POOLCOLL_TEXT_END ; nId++,nIndex++ )
+ {
+ String aString, bString;
+ FillUIName ( nId, aString );
+ bString = GetProgName ( nsSwGetPoolIdFromName::GET_POOLID_TXTCOLL, aString );
+ sal_uInt16 nNewId = GetPoolIdFromProgName ( bString, nsSwGetPoolIdFromName::GET_POOLID_TXTCOLL );
+ FillProgName ( nNewId, aString );
+ bString = GetUIName ( aString, nsSwGetPoolIdFromName::GET_POOLID_TXTCOLL );
+ nNewId = GetPoolIdFromUIName ( aString, nsSwGetPoolIdFromName::GET_POOLID_TXTCOLL );
+ if ( nNewId != nId )
+ abort();
+ }
+ for ( nIndex = 0, nId = RES_POOLCOLL_LISTS_BEGIN ; nId < RES_POOLCOLL_LISTS_END ; nId++,nIndex++ )
+ {
+ String aString, bString;
+ FillUIName ( nId, aString );
+ bString = GetProgName ( nsSwGetPoolIdFromName::GET_POOLID_TXTCOLL, aString );
+ sal_uInt16 nNewId = GetPoolIdFromProgName ( bString, nsSwGetPoolIdFromName::GET_POOLID_TXTCOLL );
+ FillProgName ( nNewId, aString );
+ bString = GetUIName ( aString, nsSwGetPoolIdFromName::GET_POOLID_TXTCOLL );
+ nNewId = GetPoolIdFromUIName ( aString, nsSwGetPoolIdFromName::GET_POOLID_TXTCOLL );
+ if ( nNewId != nId )
+ abort();
+ }
+ for ( nIndex = 0, nId = RES_POOLCOLL_EXTRA_BEGIN ; nId < RES_POOLCOLL_EXTRA_END ; nId++,nIndex++ )
+ {
+ String aString, bString;
+ FillUIName ( nId, aString );
+ bString = GetProgName ( nsSwGetPoolIdFromName::GET_POOLID_TXTCOLL, aString );
+ sal_uInt16 nNewId = GetPoolIdFromProgName ( bString, nsSwGetPoolIdFromName::GET_POOLID_TXTCOLL );
+ FillProgName ( nNewId, aString );
+ bString = GetUIName ( aString, nsSwGetPoolIdFromName::GET_POOLID_TXTCOLL );
+ nNewId = GetPoolIdFromUIName ( aString, nsSwGetPoolIdFromName::GET_POOLID_TXTCOLL );
+ if ( nNewId != nId )
+ abort();
+ }
+ for ( nIndex = 0, nId = RES_POOLCOLL_REGISTER_BEGIN ; nId < RES_POOLCOLL_REGISTER_END ; nId++,nIndex++ )
+ {
+ String aString, bString;
+ FillUIName ( nId, aString );
+ bString = GetProgName ( nsSwGetPoolIdFromName::GET_POOLID_TXTCOLL, aString );
+ sal_uInt16 nNewId = GetPoolIdFromProgName ( bString, nsSwGetPoolIdFromName::GET_POOLID_TXTCOLL );
+ FillProgName ( nNewId, aString );
+ bString = GetUIName ( aString, nsSwGetPoolIdFromName::GET_POOLID_TXTCOLL );
+ nNewId = GetPoolIdFromUIName ( aString, nsSwGetPoolIdFromName::GET_POOLID_TXTCOLL );
+ if ( nNewId != nId )
+ abort();
+ }
+ for ( nIndex = 0, nId = RES_POOLCOLL_DOC_BEGIN ; nId < RES_POOLCOLL_DOC_END ; nId++,nIndex++ )
+ {
+ String aString, bString;
+ FillUIName ( nId, aString );
+ bString = GetProgName ( nsSwGetPoolIdFromName::GET_POOLID_TXTCOLL, aString );
+ sal_uInt16 nNewId = GetPoolIdFromProgName ( bString, nsSwGetPoolIdFromName::GET_POOLID_TXTCOLL );
+ FillProgName ( nNewId, aString );
+ bString = GetUIName ( aString, nsSwGetPoolIdFromName::GET_POOLID_TXTCOLL );
+ nNewId = GetPoolIdFromUIName ( aString, nsSwGetPoolIdFromName::GET_POOLID_TXTCOLL );
+ if ( nNewId != nId )
+ abort();
+ }
+ for ( nIndex = 0, nId = RES_POOLCOLL_HTML_BEGIN ; nId < RES_POOLCOLL_HTML_END ; nId++,nIndex++ )
+ {
+ String aString, bString;
+ FillUIName ( nId, aString );
+ bString = GetProgName ( nsSwGetPoolIdFromName::GET_POOLID_TXTCOLL, aString );
+ sal_uInt16 nNewId = GetPoolIdFromProgName ( bString, nsSwGetPoolIdFromName::GET_POOLID_TXTCOLL );
+ FillProgName ( nNewId, aString );
+ bString = GetUIName ( aString, nsSwGetPoolIdFromName::GET_POOLID_TXTCOLL );
+ nNewId = GetPoolIdFromUIName ( aString, nsSwGetPoolIdFromName::GET_POOLID_TXTCOLL );
+ if ( nNewId != nId )
+ abort();
+ }
+ }
+ {
+ for ( sal_uInt16 nIndex = 0, nId = RES_POOLCHR_NORMAL_BEGIN ; nId < RES_POOLCHR_NORMAL_END ; nId++,nIndex++ )
+ {
+ String aString, bString;
+ FillUIName ( nId, aString );
+ bString = GetProgName ( nsSwGetPoolIdFromName::GET_POOLID_TXTCOLL, aString );
+ sal_uInt16 nNewId = GetPoolIdFromProgName ( bString, nsSwGetPoolIdFromName::GET_POOLID_TXTCOLL );
+ FillProgName ( nNewId, aString );
+ bString = GetUIName ( aString, nsSwGetPoolIdFromName::GET_POOLID_TXTCOLL );
+ nNewId = GetPoolIdFromUIName ( aString, nsSwGetPoolIdFromName::GET_POOLID_TXTCOLL );
+ if ( nNewId != nId )
+ abort();
+ }
+ for ( nIndex = 0, nId = RES_POOLCHR_HTML_BEGIN ; nId < RES_POOLCHR_HTML_END ; nId++,nIndex++ )
+ {
+ String aString, bString;
+ FillUIName ( nId, aString );
+ bString = GetProgName ( nsSwGetPoolIdFromName::GET_POOLID_TXTCOLL, aString );
+ sal_uInt16 nNewId = GetPoolIdFromProgName ( bString, nsSwGetPoolIdFromName::GET_POOLID_TXTCOLL );
+ FillProgName ( nNewId, aString );
+ bString = GetUIName ( aString, nsSwGetPoolIdFromName::GET_POOLID_TXTCOLL );
+ nNewId = GetPoolIdFromUIName ( aString, nsSwGetPoolIdFromName::GET_POOLID_TXTCOLL );
+ if ( nNewId != nId )
+ abort();
+ }
+ }
+ {
+ for ( sal_uInt16 nIndex=0,nId = RES_POOLFRM_BEGIN ; nId < RES_POOLFRM_END ; nId++,nIndex++ )
+ {
+ String aString, bString;
+ FillUIName ( nId, aString );
+ bString = GetProgName ( nsSwGetPoolIdFromName::GET_POOLID_TXTCOLL, aString );
+ sal_uInt16 nNewId = GetPoolIdFromProgName ( bString, nsSwGetPoolIdFromName::GET_POOLID_TXTCOLL );
+ FillProgName ( nNewId, aString );
+ bString = GetUIName ( aString, nsSwGetPoolIdFromName::GET_POOLID_TXTCOLL );
+ nNewId = GetPoolIdFromUIName ( aString, nsSwGetPoolIdFromName::GET_POOLID_TXTCOLL );
+ if ( nNewId != nId )
+ abort();
+ }
+ }
+ {
+ for ( sal_uInt16 nIndex=0,nId = RES_POOLPAGE_BEGIN ; nId < RES_POOLPAGE_END ; nId++,nIndex++ )
+ {
+ String aString, bString;
+ FillUIName ( nId, aString );
+ bString = GetProgName ( nsSwGetPoolIdFromName::GET_POOLID_TXTCOLL, aString );
+ sal_uInt16 nNewId = GetPoolIdFromProgName ( bString, nsSwGetPoolIdFromName::GET_POOLID_TXTCOLL );
+ FillProgName ( nNewId, aString );
+ bString = GetUIName ( aString, nsSwGetPoolIdFromName::GET_POOLID_TXTCOLL );
+ nNewId = GetPoolIdFromUIName ( aString, nsSwGetPoolIdFromName::GET_POOLID_TXTCOLL );
+ if ( nNewId != nId )
+ abort();
+ }
+ }
+ {
+ for ( sal_uInt16 nIndex=0,nId = RES_POOLNUMRULE_BEGIN ; nId < RES_POOLNUMRULE_END ; nId++,nIndex++ )
+ {
+ String aString, bString;
+ FillUIName ( nId, aString );
+ bString = GetProgName ( nsSwGetPoolIdFromName::GET_POOLID_TXTCOLL, aString );
+ sal_uInt16 nNewId = GetPoolIdFromProgName ( bString, nsSwGetPoolIdFromName::GET_POOLID_TXTCOLL );
+ FillProgName ( nNewId, aString );
+ bString = GetUIName ( aString, nsSwGetPoolIdFromName::GET_POOLID_TXTCOLL );
+ nNewId = GetPoolIdFromUIName ( aString, nsSwGetPoolIdFromName::GET_POOLID_TXTCOLL );
+ if ( nNewId != nId )
+ abort();
+ }
+ }
+ }
+#endif
+ return *pHash;
+}
+// This gets the UI Name from the programmatic name
+const String& SwStyleNameMapper::GetUIName ( const String& rName, SwGetPoolIdFromName eFlags )
+{
+ sal_uInt16 nId = GetPoolIdFromProgName ( rName, eFlags );
+ return nId != USHRT_MAX ? GetUIName( nId, rName ) : rName;
+}
+
+
+// Get the programmatic Name from the UI name
+const String& SwStyleNameMapper::GetProgName( const String& rName, SwGetPoolIdFromName eFlags )
+{
+ sal_uInt16 nId = GetPoolIdFromUIName ( rName, eFlags );
+ return nId != USHRT_MAX ? GetProgName( nId, rName ) : rName;
+}
+
+// Get the programmatic name from the UI name in rName and put it into rFillName
+void SwStyleNameMapper::FillProgName ( const String& rName, String& rFillName, SwGetPoolIdFromName eFlags, sal_Bool bDisambiguate )
+{
+ sal_uInt16 nId = GetPoolIdFromUIName ( rName, eFlags );
+ if ( bDisambiguate && nId == USHRT_MAX )
+ {
+ // rName isn't in our UI name table...check if it's in the programmatic one
+ nId = GetPoolIdFromProgName ( rName, eFlags );
+
+ rFillName = rName;
+ if (nId == USHRT_MAX )
+ {
+ // It isn't ...make sure the suffix isn't already " (user)"...if it is,
+ // we need to add another one
+ if ( SuffixIsUser ( rFillName ) )
+ rFillName.AppendAscii ( RTL_CONSTASCII_STRINGPARAM ( " (user)" ) );
+ }
+ else
+ {
+ // It's in the programmatic name table...append suffix
+ rFillName.AppendAscii ( RTL_CONSTASCII_STRINGPARAM ( " (user)" ) );
+ }
+ }
+ else
+ {
+ // If we aren't trying to disambiguate, then just do a normal fill
+ fillNameFromId ( nId, rFillName, sal_True);
+ }
+}
+// Get the UI name from the programmatic name in rName and put it into rFillName
+void SwStyleNameMapper::FillUIName ( const String& rName, String& rFillName, SwGetPoolIdFromName eFlags, sal_Bool bDisambiguate )
+{
+ sal_uInt16 nId = GetPoolIdFromProgName ( rName, eFlags );
+ if ( bDisambiguate && nId == USHRT_MAX )
+ {
+ rFillName = rName;
+ // rName isn't in our Prog name table...check if it has a " (user)" suffix, if so remove it
+ CheckSuffixAndDelete ( rFillName );
+ }
+ else
+ {
+ // If we aren't trying to disambiguate, then just do a normal fill
+ fillNameFromId ( nId, rFillName, sal_False);
+ }
+}
+
+const String& SwStyleNameMapper::getNameFromId( sal_uInt16 nId, const String& rFillName, sal_Bool bProgName )
+{
+ sal_uInt16 nStt = 0;
+ const SvStringsDtor* pStrArr = 0;
+
+ switch( (USER_FMT | COLL_GET_RANGE_BITS | POOLGRP_NOCOLLID) & nId )
+ {
+ case COLL_TEXT_BITS:
+ if( RES_POOLCOLL_TEXT_BEGIN <= nId && nId < RES_POOLCOLL_TEXT_END )
+ {
+ pStrArr = bProgName ? &GetTextProgNameArray() : &GetTextUINameArray();
+ nStt = RES_POOLCOLL_TEXT_BEGIN;
+ }
+ break;
+ case COLL_LISTS_BITS:
+ if( RES_POOLCOLL_LISTS_BEGIN <= nId && nId < RES_POOLCOLL_LISTS_END )
+ {
+ pStrArr = bProgName ? &GetListsProgNameArray() : &GetListsUINameArray();
+ nStt = RES_POOLCOLL_LISTS_BEGIN;
+ }
+ break;
+ case COLL_EXTRA_BITS:
+ if( RES_POOLCOLL_EXTRA_BEGIN <= nId && nId < RES_POOLCOLL_EXTRA_END )
+ {
+ pStrArr = bProgName ? &GetExtraProgNameArray() : &GetExtraUINameArray();
+ nStt = RES_POOLCOLL_EXTRA_BEGIN;
+ }
+ break;
+ case COLL_REGISTER_BITS:
+ if( RES_POOLCOLL_REGISTER_BEGIN <= nId && nId < RES_POOLCOLL_REGISTER_END )
+ {
+ pStrArr = bProgName ? &GetRegisterProgNameArray() : &GetRegisterUINameArray();
+ nStt = RES_POOLCOLL_REGISTER_BEGIN;
+ }
+ break;
+ case COLL_DOC_BITS:
+ if( RES_POOLCOLL_DOC_BEGIN <= nId && nId < RES_POOLCOLL_DOC_END )
+ {
+ pStrArr = bProgName ? &GetDocProgNameArray() : &GetDocUINameArray();
+ nStt = RES_POOLCOLL_DOC_BEGIN;
+ }
+ break;
+ case COLL_HTML_BITS:
+ if( RES_POOLCOLL_HTML_BEGIN <= nId && nId < RES_POOLCOLL_HTML_END )
+ {
+ pStrArr = bProgName ? &GetHTMLProgNameArray() : &GetHTMLUINameArray();
+ nStt = RES_POOLCOLL_HTML_BEGIN;
+ }
+ break;
+ case POOLGRP_CHARFMT:
+ if( RES_POOLCHR_NORMAL_BEGIN <= nId && nId < RES_POOLCHR_NORMAL_END )
+ {
+ pStrArr = bProgName ? &GetChrFmtProgNameArray() : &GetChrFmtUINameArray();
+ nStt = RES_POOLCHR_NORMAL_BEGIN;
+ }
+ else if( RES_POOLCHR_HTML_BEGIN <= nId && nId < RES_POOLCHR_HTML_END )
+ {
+ pStrArr = bProgName ? &GetHTMLChrFmtProgNameArray() : &GetHTMLChrFmtUINameArray();
+ nStt = RES_POOLCHR_HTML_BEGIN;
+ }
+ break;
+ case POOLGRP_FRAMEFMT:
+ if( RES_POOLFRM_BEGIN <= nId && nId < RES_POOLFRM_END )
+ {
+ pStrArr = bProgName ? &GetFrmFmtProgNameArray() : &GetFrmFmtUINameArray();
+ nStt = RES_POOLFRM_BEGIN;
+ }
+ break;
+ case POOLGRP_PAGEDESC:
+ if( RES_POOLPAGE_BEGIN <= nId && nId < RES_POOLPAGE_END )
+ {
+ pStrArr = bProgName ? &GetPageDescProgNameArray() : &GetPageDescUINameArray();
+ nStt = RES_POOLPAGE_BEGIN;
+ }
+ break;
+ case POOLGRP_NUMRULE:
+ if( RES_POOLNUMRULE_BEGIN <= nId && nId < RES_POOLNUMRULE_END )
+ {
+ pStrArr = bProgName ? &GetNumRuleProgNameArray() : &GetNumRuleUINameArray();
+ nStt = RES_POOLNUMRULE_BEGIN;
+ }
+ break;
+ }
+ return pStrArr ? *(pStrArr->operator[] ( nId - nStt ) ) : rFillName;
+}
+void SwStyleNameMapper::fillNameFromId( sal_uInt16 nId, String& rFillName, sal_Bool bProgName )
+{
+ sal_uInt16 nStt = 0;
+ const SvStringsDtor* pStrArr = 0;
+
+ switch( (USER_FMT | COLL_GET_RANGE_BITS | POOLGRP_NOCOLLID) & nId )
+ {
+ case COLL_TEXT_BITS:
+ if( RES_POOLCOLL_TEXT_BEGIN <= nId && nId < RES_POOLCOLL_TEXT_END )
+ {
+ pStrArr = bProgName ? &GetTextProgNameArray() : &GetTextUINameArray();
+ nStt = RES_POOLCOLL_TEXT_BEGIN;
+ }
+ break;
+ case COLL_LISTS_BITS:
+ if( RES_POOLCOLL_LISTS_BEGIN <= nId && nId < RES_POOLCOLL_LISTS_END )
+ {
+ pStrArr = bProgName ? &GetListsProgNameArray() : &GetListsUINameArray();
+ nStt = RES_POOLCOLL_LISTS_BEGIN;
+ }
+ break;
+ case COLL_EXTRA_BITS:
+ if( RES_POOLCOLL_EXTRA_BEGIN <= nId && nId < RES_POOLCOLL_EXTRA_END )
+ {
+ pStrArr = bProgName ? &GetExtraProgNameArray() : &GetExtraUINameArray();
+ nStt = RES_POOLCOLL_EXTRA_BEGIN;
+ }
+ break;
+ case COLL_REGISTER_BITS:
+ if( RES_POOLCOLL_REGISTER_BEGIN <= nId && nId < RES_POOLCOLL_REGISTER_END )
+ {
+ pStrArr = bProgName ? &GetRegisterProgNameArray() : &GetRegisterUINameArray();
+ nStt = RES_POOLCOLL_REGISTER_BEGIN;
+ }
+ break;
+ case COLL_DOC_BITS:
+ if( RES_POOLCOLL_DOC_BEGIN <= nId && nId < RES_POOLCOLL_DOC_END )
+ {
+ pStrArr = bProgName ? &GetDocProgNameArray() : &GetDocUINameArray();
+ nStt = RES_POOLCOLL_DOC_BEGIN;
+ }
+ break;
+ case COLL_HTML_BITS:
+ if( RES_POOLCOLL_HTML_BEGIN <= nId && nId < RES_POOLCOLL_HTML_END )
+ {
+ pStrArr = bProgName ? &GetHTMLProgNameArray() : &GetHTMLUINameArray();
+ nStt = RES_POOLCOLL_HTML_BEGIN;
+ }
+ break;
+ case POOLGRP_CHARFMT:
+ if( RES_POOLCHR_NORMAL_BEGIN <= nId && nId < RES_POOLCHR_NORMAL_END )
+ {
+ pStrArr = bProgName ? &GetChrFmtProgNameArray() : &GetChrFmtUINameArray();
+ nStt = RES_POOLCHR_NORMAL_BEGIN;
+ }
+ else if( RES_POOLCHR_HTML_BEGIN <= nId && nId < RES_POOLCHR_HTML_END )
+ {
+ pStrArr = bProgName ? &GetHTMLChrFmtProgNameArray() : &GetHTMLChrFmtUINameArray();
+ nStt = RES_POOLCHR_HTML_BEGIN;
+ }
+ break;
+ case POOLGRP_FRAMEFMT:
+ if( RES_POOLFRM_BEGIN <= nId && nId < RES_POOLFRM_END )
+ {
+ pStrArr = bProgName ? &GetFrmFmtProgNameArray() : &GetFrmFmtUINameArray();
+ nStt = RES_POOLFRM_BEGIN;
+ }
+ break;
+ case POOLGRP_PAGEDESC:
+ if( RES_POOLPAGE_BEGIN <= nId && nId < RES_POOLPAGE_END )
+ {
+ pStrArr = bProgName ? &GetPageDescProgNameArray() : &GetPageDescUINameArray();
+ nStt = RES_POOLPAGE_BEGIN;
+ }
+ break;
+ case POOLGRP_NUMRULE:
+ if( RES_POOLNUMRULE_BEGIN <= nId && nId < RES_POOLNUMRULE_END )
+ {
+ pStrArr = bProgName ? &GetNumRuleProgNameArray() : &GetNumRuleUINameArray();
+ nStt = RES_POOLNUMRULE_BEGIN;
+ }
+ break;
+ }
+ if (pStrArr)
+ rFillName = *(pStrArr->operator[] ( nId - nStt ) );
+}
+// Get the UI Name from the pool ID
+void SwStyleNameMapper::FillUIName ( sal_uInt16 nId, String& rFillName )
+{
+ fillNameFromId ( nId, rFillName, sal_False );
+}
+// Get the UI Name from the pool ID
+const String& SwStyleNameMapper::GetUIName ( sal_uInt16 nId, const String& rName )
+{
+ return getNameFromId ( nId, rName, sal_False );
+}
+
+// Get the programmatic Name from the pool ID
+void SwStyleNameMapper::FillProgName ( sal_uInt16 nId, String& rFillName )
+{
+ fillNameFromId ( nId, rFillName, sal_True );
+}
+// Get the programmatic Name from the pool ID
+const String& SwStyleNameMapper::GetProgName ( sal_uInt16 nId, const String& rName )
+{
+ return getNameFromId ( nId, rName, sal_True );
+}
+// This gets the PoolId from the UI Name
+sal_uInt16 SwStyleNameMapper::GetPoolIdFromUIName( const String& rName, SwGetPoolIdFromName eFlags )
+{
+ const NameToIdHash & rHashMap = getHashTable ( eFlags, sal_False );
+ NameToIdHash::const_iterator aIter = rHashMap.find ( &rName );
+ return aIter != rHashMap.end() ? (*aIter).second : USHRT_MAX;
+}
+// Get the Pool ID from the programmatic name
+sal_uInt16 SwStyleNameMapper::GetPoolIdFromProgName( const String& rName, SwGetPoolIdFromName eFlags )
+{
+ const NameToIdHash & rHashMap = getHashTable ( eFlags, sal_True );
+ NameToIdHash::const_iterator aIter = rHashMap.find ( &rName );
+ return aIter != rHashMap.end() ? (*aIter).second : USHRT_MAX;
+}
+
+SvStringsDtor* SwStyleNameMapper::NewUINameArray( SvStringsDtor*& pNameArray, sal_uInt16 nStt, sal_uInt16 nEnd )
+{
+ if( !pNameArray )
+ {
+ pNameArray = new SvStringsDtor( static_cast < sal_Int8 > (nEnd - nStt), 1 );
+ while( nStt < nEnd )
+ {
+ const ResId rRId( nStt, *pSwResMgr );
+ String* pStr = new String( rRId );
+ pNameArray->Insert( pStr, pNameArray->Count() );
+ ++nStt;
+ }
+ }
+ return pNameArray;
+}
+
+const SvStringsDtor& SwStyleNameMapper::GetTextUINameArray()
+{
+ return pTextUINameArray ? *pTextUINameArray :
+ *NewUINameArray( pTextUINameArray, RC_POOLCOLL_TEXT_BEGIN,
+ ( RC_POOLCOLL_TEXT_BEGIN +
+ (RES_POOLCOLL_TEXT_END - RES_POOLCOLL_TEXT_BEGIN )) );
+}
+
+const SvStringsDtor& SwStyleNameMapper::GetListsUINameArray()
+{
+ return pListsUINameArray ? *pListsUINameArray :
+ *NewUINameArray( pListsUINameArray, RC_POOLCOLL_LISTS_BEGIN,
+ ( RC_POOLCOLL_LISTS_BEGIN +
+ (RES_POOLCOLL_LISTS_END - RES_POOLCOLL_LISTS_BEGIN )) );
+}
+
+const SvStringsDtor& SwStyleNameMapper::GetExtraUINameArray()
+{
+ return pExtraUINameArray ? *pExtraUINameArray :
+ *NewUINameArray( pExtraUINameArray, RC_POOLCOLL_EXTRA_BEGIN,
+ ( RC_POOLCOLL_EXTRA_BEGIN +
+ (RES_POOLCOLL_EXTRA_END - RES_POOLCOLL_EXTRA_BEGIN )) );
+}
+
+const SvStringsDtor& SwStyleNameMapper::GetRegisterUINameArray()
+{
+ return pRegisterUINameArray ? *pRegisterUINameArray :
+ *NewUINameArray( pRegisterUINameArray, RC_POOLCOLL_REGISTER_BEGIN,
+ ( RC_POOLCOLL_REGISTER_BEGIN +
+ (RES_POOLCOLL_REGISTER_END - RES_POOLCOLL_REGISTER_BEGIN )) );
+}
+
+const SvStringsDtor& SwStyleNameMapper::GetDocUINameArray()
+{
+ return pDocUINameArray ? *pDocUINameArray :
+ *NewUINameArray( pDocUINameArray, RC_POOLCOLL_DOC_BEGIN,
+ ( RC_POOLCOLL_DOC_BEGIN +
+ (RES_POOLCOLL_DOC_END - RES_POOLCOLL_DOC_BEGIN )) );
+}
+
+const SvStringsDtor& SwStyleNameMapper::GetHTMLUINameArray()
+{
+ return pHTMLUINameArray ? *pHTMLUINameArray :
+ *NewUINameArray( pHTMLUINameArray, RC_POOLCOLL_HTML_BEGIN,
+ ( RC_POOLCOLL_HTML_BEGIN +
+ (RES_POOLCOLL_HTML_END - RES_POOLCOLL_HTML_BEGIN )) );
+}
+
+const SvStringsDtor& SwStyleNameMapper::GetFrmFmtUINameArray()
+{
+ return pFrmFmtUINameArray ? *pFrmFmtUINameArray :
+ *NewUINameArray( pFrmFmtUINameArray, RC_POOLFRMFMT_BEGIN,
+ ( RC_POOLFRMFMT_BEGIN +
+ (RES_POOLFRM_END - RES_POOLFRM_BEGIN )) );
+}
+
+const SvStringsDtor& SwStyleNameMapper::GetChrFmtUINameArray()
+{
+ return pChrFmtUINameArray ? *pChrFmtUINameArray :
+ *NewUINameArray( pChrFmtUINameArray, RC_POOLCHRFMT_BEGIN,
+ ( RC_POOLCHRFMT_BEGIN +
+ (RES_POOLCHR_NORMAL_END - RES_POOLCHR_NORMAL_BEGIN )) );
+}
+
+const SvStringsDtor& SwStyleNameMapper::GetHTMLChrFmtUINameArray()
+{
+ return pHTMLChrFmtUINameArray ? *pHTMLChrFmtUINameArray :
+ *NewUINameArray( pHTMLChrFmtUINameArray, RC_POOLCHRFMT_HTML_BEGIN,
+ ( RC_POOLCHRFMT_HTML_BEGIN +
+ (RES_POOLCHR_HTML_END - RES_POOLCHR_HTML_BEGIN )) );
+}
+
+const SvStringsDtor& SwStyleNameMapper::GetPageDescUINameArray()
+{
+ return pPageDescUINameArray ? *pPageDescUINameArray :
+ *NewUINameArray( pPageDescUINameArray, RC_POOLPAGEDESC_BEGIN,
+ ( RC_POOLPAGEDESC_BEGIN +
+ (RES_POOLPAGE_END - RES_POOLPAGE_BEGIN )) );
+}
+
+const SvStringsDtor& SwStyleNameMapper::GetNumRuleUINameArray()
+{
+ return pNumRuleUINameArray ? *pNumRuleUINameArray :
+ *NewUINameArray( pNumRuleUINameArray, RC_POOLNUMRULE_BEGIN,
+ ( RC_POOLNUMRULE_BEGIN +
+ (RES_POOLNUMRULE_END - RES_POOLNUMRULE_BEGIN )) );
+}
+
+SvStringsDtor* SwStyleNameMapper::NewProgNameArray( SvStringsDtor*& pProgNameArray, const SwTableEntry *pTable, sal_uInt8 nCount )
+{
+ if( !pProgNameArray )
+ {
+ pProgNameArray = new SvStringsDtor( nCount, 1 );
+ while (pTable->nLength)
+ {
+ String* pStr = new String( pTable->pChar, pTable->nLength, RTL_TEXTENCODING_ASCII_US );
+ pProgNameArray->Insert( pStr, pProgNameArray->Count() );
+ pTable++;
+ }
+ }
+ return pProgNameArray;
+}
+
+const SvStringsDtor& SwStyleNameMapper::GetTextProgNameArray()
+{
+ return pTextProgNameArray ? *pTextProgNameArray :
+ *NewProgNameArray( pTextProgNameArray, TextProgNameTable,
+ sizeof ( TextProgNameTable ) / sizeof ( SwTableEntry ) );
+}
+
+const SvStringsDtor& SwStyleNameMapper::GetListsProgNameArray()
+{
+ return pListsProgNameArray ? *pListsProgNameArray :
+ *NewProgNameArray( pListsProgNameArray, ListsProgNameTable,
+ sizeof ( ListsProgNameTable ) / sizeof ( SwTableEntry ) );
+}
+
+const SvStringsDtor& SwStyleNameMapper::GetExtraProgNameArray()
+{
+ return pExtraProgNameArray ? *pExtraProgNameArray :
+ *NewProgNameArray( pExtraProgNameArray, ExtraProgNameTable,
+ sizeof ( ExtraProgNameTable ) / sizeof ( SwTableEntry ) );
+}
+
+const SvStringsDtor& SwStyleNameMapper::GetRegisterProgNameArray()
+{
+ return pRegisterProgNameArray ? *pRegisterProgNameArray :
+ *NewProgNameArray( pRegisterProgNameArray, RegisterProgNameTable,
+ sizeof ( RegisterProgNameTable ) / sizeof ( SwTableEntry ) );
+}
+
+const SvStringsDtor& SwStyleNameMapper::GetDocProgNameArray()
+{
+ return pDocProgNameArray ? *pDocProgNameArray :
+ *NewProgNameArray( pDocProgNameArray, DocProgNameTable,
+ sizeof ( DocProgNameTable ) / sizeof ( SwTableEntry ) );
+}
+
+const SvStringsDtor& SwStyleNameMapper::GetHTMLProgNameArray()
+{
+ return pHTMLProgNameArray ? *pHTMLProgNameArray :
+ *NewProgNameArray( pHTMLProgNameArray, HTMLProgNameTable,
+ sizeof ( HTMLProgNameTable ) / sizeof ( SwTableEntry ) );
+}
+
+const SvStringsDtor& SwStyleNameMapper::GetFrmFmtProgNameArray()
+{
+ return pFrmFmtProgNameArray ? *pFrmFmtProgNameArray :
+ *NewProgNameArray( pFrmFmtProgNameArray, FrmFmtProgNameTable,
+ sizeof ( FrmFmtProgNameTable ) / sizeof ( SwTableEntry ) );
+}
+
+const SvStringsDtor& SwStyleNameMapper::GetChrFmtProgNameArray()
+{
+ return pChrFmtProgNameArray ? *pChrFmtProgNameArray :
+ *NewProgNameArray( pChrFmtProgNameArray, ChrFmtProgNameTable,
+ sizeof ( ChrFmtProgNameTable ) / sizeof ( SwTableEntry ) );
+}
+
+const SvStringsDtor& SwStyleNameMapper::GetHTMLChrFmtProgNameArray()
+{
+ return pHTMLChrFmtProgNameArray ? *pHTMLChrFmtProgNameArray :
+ *NewProgNameArray( pHTMLChrFmtProgNameArray, HTMLChrFmtProgNameTable,
+ sizeof ( HTMLChrFmtProgNameTable ) / sizeof ( SwTableEntry ) );
+}
+
+const SvStringsDtor& SwStyleNameMapper::GetPageDescProgNameArray()
+{
+ return pPageDescProgNameArray ? *pPageDescProgNameArray :
+ *NewProgNameArray( pPageDescProgNameArray, PageDescProgNameTable,
+ sizeof ( PageDescProgNameTable ) / sizeof ( SwTableEntry ) );
+}
+
+const SvStringsDtor& SwStyleNameMapper::GetNumRuleProgNameArray()
+{
+ return pNumRuleProgNameArray ? *pNumRuleProgNameArray :
+ *NewProgNameArray( pNumRuleProgNameArray, NumRuleProgNameTable,
+ sizeof ( NumRuleProgNameTable ) / sizeof ( SwTableEntry ) );
+}
+
+
+const String SwStyleNameMapper::GetSpecialExtraProgName( const String& rExtraUIName )
+{
+ String aRes = rExtraUIName;
+ sal_Bool bChgName = sal_False;
+ const SvStringsDtor& rExtraArr = GetExtraUINameArray();
+ static sal_uInt16 nIds[] =
+ {
+ RES_POOLCOLL_LABEL_DRAWING - RES_POOLCOLL_EXTRA_BEGIN,
+ RES_POOLCOLL_LABEL_ABB - RES_POOLCOLL_EXTRA_BEGIN,
+ RES_POOLCOLL_LABEL_TABLE - RES_POOLCOLL_EXTRA_BEGIN,
+ RES_POOLCOLL_LABEL_FRAME- RES_POOLCOLL_EXTRA_BEGIN,
+ 0
+ };
+ const sal_uInt16 * pIds;
+ for ( pIds = nIds; *pIds; ++pIds)
+ {
+ if (aRes == *rExtraArr[ *pIds ])
+ {
+ bChgName = sal_True;
+ break;
+ }
+ }
+ if (bChgName)
+ aRes = *GetExtraProgNameArray()[*pIds];
+ return aRes;
+}
+
+const String SwStyleNameMapper::GetSpecialExtraUIName( const String& rExtraProgName )
+{
+ String aRes = rExtraProgName;
+ sal_Bool bChgName = sal_False;
+ const SvStringsDtor& rExtraArr = GetExtraProgNameArray();
+ static sal_uInt16 nIds[] =
+ {
+ RES_POOLCOLL_LABEL_DRAWING - RES_POOLCOLL_EXTRA_BEGIN,
+ RES_POOLCOLL_LABEL_ABB - RES_POOLCOLL_EXTRA_BEGIN,
+ RES_POOLCOLL_LABEL_TABLE - RES_POOLCOLL_EXTRA_BEGIN,
+ RES_POOLCOLL_LABEL_FRAME- RES_POOLCOLL_EXTRA_BEGIN,
+ 0
+ };
+ const sal_uInt16 * pIds;
+
+ for ( pIds = nIds; *pIds; ++pIds)
+ {
+ if (aRes == *rExtraArr[ *pIds ])
+ {
+ bChgName = sal_True;
+ break;
+ }
+ }
+ if (bChgName)
+ aRes = *GetExtraUINameArray()[*pIds];
+ return aRes;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/doc/acmplwrd.cxx b/sw/source/core/doc/acmplwrd.cxx
new file mode 100644
index 000000000000..ec5c65332b1c
--- /dev/null
+++ b/sw/source/core/doc/acmplwrd.cxx
@@ -0,0 +1,443 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+
+#include <tools/urlobj.hxx>
+#include <hintids.hxx>
+#include <hints.hxx>
+#include <unotools/transliterationwrapper.hxx>
+#include <acmplwrd.hxx>
+#include <doc.hxx>
+#include <ndindex.hxx>
+#include <docary.hxx>
+#include <ndtxt.hxx>
+#include <pam.hxx>
+#include <pagedesc.hxx>
+#include <poolfmt.hxx>
+#include <calbck.hxx>
+#include <editeng/svxacorr.hxx>
+
+#include <editeng/acorrcfg.hxx>
+#include <sfx2/docfile.hxx>
+#include <docsh.hxx>
+
+#include <vector>
+
+class SwAutoCompleteClient : public SwClient
+{
+ SwAutoCompleteWord* pAutoCompleteWord;
+ SwDoc* pDoc;
+#if OSL_DEBUG_LEVEL > 1
+ static sal_uLong nSwAutoCompleteClientCount;
+#endif
+public:
+ SwAutoCompleteClient(SwAutoCompleteWord& rToTell, SwDoc& rSwDoc);
+ SwAutoCompleteClient(const SwAutoCompleteClient& rClient);
+ ~SwAutoCompleteClient();
+
+ SwAutoCompleteClient& operator=(const SwAutoCompleteClient& rClient);
+
+ const SwDoc& GetDoc(){return *pDoc;}
+#if OSL_DEBUG_LEVEL > 1
+ static sal_uLong GetElementCount() {return nSwAutoCompleteClientCount;}
+#endif
+protected:
+ virtual void Modify( const SfxPoolItem* pOld, const SfxPoolItem *pNew);
+};
+
+typedef std::vector<SwAutoCompleteClient> SwAutoCompleteClientVector;
+
+class SwAutoCompleteWord_Impl
+{
+ SwAutoCompleteClientVector aClientVector;
+ SwAutoCompleteWord& rAutoCompleteWord;
+public:
+ SwAutoCompleteWord_Impl(SwAutoCompleteWord& rParent) :
+ rAutoCompleteWord(rParent){}
+ void AddDocument(SwDoc& rDoc);
+ void RemoveDocument(const SwDoc& rDoc);
+};
+
+typedef const SwDoc* SwDocPtr;
+typedef std::vector<SwDocPtr> SwDocPtrVector;
+class SwAutoCompleteString : public String
+{
+#if OSL_DEBUG_LEVEL > 1
+ static sal_uLong nSwAutoCompleteStringCount;
+#endif
+ SwDocPtrVector aSourceDocs;
+ public:
+ SwAutoCompleteString(const String& rStr, xub_StrLen nPos, xub_StrLen nLen);
+
+ ~SwAutoCompleteString();
+ void AddDocument(const SwDoc& rDoc);
+ //returns true if last document reference has been removed
+ sal_Bool RemoveDocument(const SwDoc& rDoc);
+#if OSL_DEBUG_LEVEL > 1
+ static sal_uLong GetElementCount() {return nSwAutoCompleteStringCount;}
+#endif
+};
+#if OSL_DEBUG_LEVEL > 1
+ sal_uLong SwAutoCompleteClient::nSwAutoCompleteClientCount = 0;
+ sal_uLong SwAutoCompleteString::nSwAutoCompleteStringCount = 0;
+#endif
+
+SwAutoCompleteClient::SwAutoCompleteClient(SwAutoCompleteWord& rToTell, SwDoc& rSwDoc) :
+ pAutoCompleteWord(&rToTell),
+ pDoc(&rSwDoc)
+{
+ pDoc->GetPageDescFromPool(RES_POOLPAGE_STANDARD)->Add(this);
+#if OSL_DEBUG_LEVEL > 1
+ ++nSwAutoCompleteClientCount;
+#endif
+}
+
+SwAutoCompleteClient::SwAutoCompleteClient(const SwAutoCompleteClient& rClient) :
+ SwClient(),
+ pAutoCompleteWord(rClient.pAutoCompleteWord),
+ pDoc(rClient.pDoc)
+{
+ pDoc->GetPageDescFromPool(RES_POOLPAGE_STANDARD)->Add(this);
+#if OSL_DEBUG_LEVEL > 1
+ ++nSwAutoCompleteClientCount;
+#endif
+}
+
+SwAutoCompleteClient::~SwAutoCompleteClient()
+{
+#if OSL_DEBUG_LEVEL > 1
+ --nSwAutoCompleteClientCount;
+#endif
+}
+
+SwAutoCompleteClient& SwAutoCompleteClient::operator=(const SwAutoCompleteClient& rClient)
+{
+ pAutoCompleteWord = rClient.pAutoCompleteWord;
+ pDoc = rClient.pDoc;
+ if(rClient.GetRegisteredIn())
+ ((SwModify*)rClient.GetRegisteredIn())->Add(this);
+ else if(GetRegisteredIn())
+ GetRegisteredInNonConst()->Remove(this);
+ return *this;
+}
+
+void SwAutoCompleteClient::Modify( const SfxPoolItem* pOld, const SfxPoolItem *)
+{
+ switch( pOld ? pOld->Which() : 0 )
+ {
+ case RES_REMOVE_UNO_OBJECT:
+ case RES_OBJECTDYING:
+ if( (void*)GetRegisteredIn() == ((SwPtrMsgPoolItem *)pOld)->pObject )
+ ((SwModify*)GetRegisteredIn())->Remove(this);
+ pAutoCompleteWord->DocumentDying(*pDoc);
+ break;
+
+ }
+}
+
+void SwAutoCompleteWord_Impl::AddDocument(SwDoc& rDoc)
+{
+ SwAutoCompleteClientVector::iterator aIt;
+ for(aIt = aClientVector.begin(); aIt != aClientVector.end(); ++aIt)
+ {
+ if(&aIt->GetDoc() == &rDoc)
+ return;
+ }
+ aClientVector.push_back(SwAutoCompleteClient(rAutoCompleteWord, rDoc));
+}
+
+void SwAutoCompleteWord_Impl::RemoveDocument(const SwDoc& rDoc)
+{
+ SwAutoCompleteClientVector::iterator aIt;
+ for(aIt = aClientVector.begin(); aIt != aClientVector.end(); ++aIt)
+ {
+ if(&aIt->GetDoc() == &rDoc)
+ {
+ aClientVector.erase(aIt);
+ return;
+ }
+ }
+}
+
+SwAutoCompleteString::SwAutoCompleteString(const String& rStr, xub_StrLen nPos, xub_StrLen nLen) :
+ String( rStr, nPos, nLen )
+{
+#if OSL_DEBUG_LEVEL > 1
+ ++nSwAutoCompleteStringCount;
+#endif
+}
+
+SwAutoCompleteString::~SwAutoCompleteString()
+{
+#if OSL_DEBUG_LEVEL > 1
+ --nSwAutoCompleteStringCount;
+#endif
+}
+
+void SwAutoCompleteString::AddDocument(const SwDoc& rDoc)
+{
+ SwDocPtrVector::iterator aIt;
+ for(aIt = aSourceDocs.begin(); aIt != aSourceDocs.end(); ++aIt)
+ {
+ if(*aIt == &rDoc)
+ return;
+ }
+ SwDocPtr pNew = &rDoc;
+ aSourceDocs.push_back(pNew);
+}
+
+sal_Bool SwAutoCompleteString::RemoveDocument(const SwDoc& rDoc)
+{
+ SwDocPtrVector::iterator aIt;
+ for(aIt = aSourceDocs.begin(); aIt != aSourceDocs.end(); ++aIt)
+ {
+ if(*aIt == &rDoc)
+ {
+ aSourceDocs.erase(aIt);
+ return !aSourceDocs.size();
+ }
+ }
+ return sal_False;
+}
+
+SwAutoCompleteWord::SwAutoCompleteWord( sal_uInt16 nWords, sal_uInt16 nMWrdLen )
+ : aWordLst( 0, 255 ), aLRULst( 0, 255 ),
+ pImpl(new SwAutoCompleteWord_Impl(*this)),
+ nMaxCount( nWords ),
+ nMinWrdLen( nMWrdLen ),
+ bLockWordLst( sal_False )
+{
+}
+
+SwAutoCompleteWord::~SwAutoCompleteWord()
+{
+ for(sal_uInt16 nPos = aWordLst.Count(); nPos; nPos--)
+ {
+ SwAutoCompleteString* pCurrent = (SwAutoCompleteString*)aWordLst[ nPos - 1 ];
+ aWordLst.Remove( nPos - 1 );
+ delete pCurrent;
+ }
+ delete pImpl;
+#if OSL_DEBUG_LEVEL > 1
+ sal_uLong nStrings = SwAutoCompleteString::GetElementCount();
+ sal_uLong nClients = SwAutoCompleteClient::GetElementCount();
+ OSL_ENSURE(!nStrings && !nClients, "AutoComplete: clients or string count mismatch");
+#endif
+}
+
+sal_Bool SwAutoCompleteWord::InsertWord( const String& rWord, SwDoc& rDoc )
+{
+ SwDocShell* pDocShell = rDoc.GetDocShell();
+ SfxMedium* pMedium = pDocShell ? pDocShell->GetMedium() : 0;
+ // strings from help module should not be added
+ if( pMedium )
+ {
+ const INetURLObject& rURL = pMedium->GetURLObject();
+ if ( rURL.GetProtocol() == INET_PROT_VND_SUN_STAR_HELP )
+ return sal_False;
+ }
+
+ String aNewWord(rWord);
+ aNewWord.EraseAllChars( CH_TXTATR_INWORD );
+ aNewWord.EraseAllChars( CH_TXTATR_BREAKWORD );
+
+ pImpl->AddDocument(rDoc);
+ sal_Bool bRet = sal_False;
+ xub_StrLen nWrdLen = aNewWord.Len();
+ while( nWrdLen && '.' == aNewWord.GetChar( nWrdLen-1 ))
+ --nWrdLen;
+
+ if( !bLockWordLst && nWrdLen >= nMinWrdLen )
+ {
+ SwAutoCompleteString* pAutoString;
+ StringPtr pNew = pAutoString = new SwAutoCompleteString( aNewWord, 0, nWrdLen );
+ pAutoString->AddDocument(rDoc);
+ sal_uInt16 nInsPos;
+ if( aWordLst.Insert( pNew, nInsPos ) )
+ {
+ bRet = sal_True;
+ if( aLRULst.Count() < nMaxCount )
+ aLRULst.Insert( pNew, 0 );
+ else
+ {
+ // der letzte muss entfernt werden
+ // damit der neue vorne Platz hat
+ String* pDel = (String*)aLRULst[ nMaxCount - 1 ];
+
+ void** ppData = (void**)aLRULst.GetData();
+ memmove( ppData+1, ppData, (nMaxCount - 1) * sizeof( void* ));
+ *ppData = pNew;
+
+ aWordLst.Remove( pDel );
+ delete (SwAutoCompleteString*)pDel;
+ }
+ }
+ else
+ {
+ delete (SwAutoCompleteString*)pNew;
+ // dann aber auf jedenfall nach "oben" moven
+ pNew = aWordLst[ nInsPos ];
+
+ //add the document to the already inserted string
+ SwAutoCompleteString* pCurrent = (SwAutoCompleteString*)pNew;
+ pCurrent->AddDocument(rDoc);
+
+ nInsPos = aLRULst.GetPos( (void*)pNew );
+ OSL_ENSURE( USHRT_MAX != nInsPos, "String nicht gefunden" );
+ if( nInsPos )
+ {
+ void** ppData = (void**)aLRULst.GetData();
+ memmove( ppData+1, ppData, nInsPos * sizeof( void* ) );
+ *ppData = pNew;
+ }
+ }
+ }
+ return bRet;
+}
+
+void SwAutoCompleteWord::SetMaxCount( sal_uInt16 nNewMax )
+{
+ if( nNewMax < nMaxCount && aLRULst.Count() > nNewMax )
+ {
+ // dann die unten ueberhaengenden entfernen
+ sal_uInt16 nLRUIndex = nNewMax-1;
+ while( nNewMax < aWordLst.Count() && nLRUIndex < aLRULst.Count())
+ {
+ sal_uInt16 nPos = aWordLst.GetPos( (String*)aLRULst[ nLRUIndex++ ] );
+ OSL_ENSURE( USHRT_MAX != nPos, "String nicht gefunden" );
+ void * pDel = aWordLst[nPos];
+ aWordLst.Remove(nPos);
+ delete (SwAutoCompleteString*)pDel;
+ }
+ aLRULst.Remove( nNewMax-1, aLRULst.Count() - nNewMax );
+ }
+ nMaxCount = nNewMax;
+}
+
+void SwAutoCompleteWord::SetMinWordLen( sal_uInt16 n )
+{
+ // will man wirklich alle Worte, die kleiner als die neue Min Laenge
+ // sind entfernen?
+ // JP 02.02.99 - erstmal nicht.
+
+ // JP 11.03.99 - mal testhalber eingebaut
+ if( n < nMinWrdLen )
+ {
+ for( sal_uInt16 nPos = 0; nPos < aWordLst.Count(); ++nPos )
+ if( aWordLst[ nPos ]->Len() < n )
+ {
+ void* pDel = aWordLst[ nPos ];
+ aWordLst.Remove(nPos);
+
+ sal_uInt16 nDelPos = aLRULst.GetPos( pDel );
+ OSL_ENSURE( USHRT_MAX != nDelPos, "String nicht gefunden" );
+ aLRULst.Remove( nDelPos );
+ --nPos;
+ delete (SwAutoCompleteString*)pDel;
+ }
+ }
+
+ nMinWrdLen = n;
+}
+
+sal_Bool SwAutoCompleteWord::GetRange( const String& rWord, sal_uInt16& rStt,
+ sal_uInt16& rEnd ) const
+{
+ const StringPtr pStr = (StringPtr)&rWord;
+ aWordLst.Seek_Entry( pStr, &rStt );
+ rEnd = rStt;
+
+ const ::utl::TransliterationWrapper& rSCmp = GetAppCmpStrIgnore();
+ while( rEnd < aWordLst.Count() && rSCmp.isMatch( rWord, *aWordLst[ rEnd ]))
+ ++rEnd;
+
+ return rStt < rEnd;
+}
+
+void SwAutoCompleteWord::CheckChangedList( const SvStringsISortDtor& rNewLst )
+{
+ sal_uInt16 nMyLen = aWordLst.Count(), nNewLen = rNewLst.Count();
+ sal_uInt16 nMyPos = 0, nNewPos = 0;
+
+ for( ; nMyPos < nMyLen && nNewPos < nNewLen; ++nMyPos, ++nNewPos )
+ {
+ const StringPtr pStr = rNewLst[ nNewPos ];
+ while( aWordLst[ nMyPos ] != pStr )
+ {
+ void* pDel = aWordLst[ nMyPos ];
+ aWordLst.Remove(nMyPos);
+
+ sal_uInt16 nPos = aLRULst.GetPos( pDel );
+ OSL_ENSURE( USHRT_MAX != nPos, "String nicht gefunden" );
+ aLRULst.Remove( nPos );
+ delete (SwAutoCompleteString*)pDel;
+ if( nMyPos >= --nMyLen )
+ break;
+ }
+ }
+ //remove the elements at the end of the array
+ if( nMyPos < nMyLen )
+ {
+ //clear LRU array first then delete the string object
+ for( ; nNewPos < nMyLen; ++nNewPos )
+ {
+ void* pDel = aWordLst[ nNewPos ];
+ sal_uInt16 nPos = aLRULst.GetPos( pDel );
+ OSL_ENSURE( USHRT_MAX != nPos, "String nicht gefunden" );
+ aLRULst.Remove( nPos );
+ delete (SwAutoCompleteString*)pDel;
+ }
+ //remove from array
+ aWordLst.Remove( nMyPos, nMyLen - nMyPos );
+ }
+}
+
+void SwAutoCompleteWord::DocumentDying(const SwDoc& rDoc)
+{
+ pImpl->RemoveDocument(rDoc);
+
+ SvxAutoCorrect* pACorr = SvxAutoCorrCfg::Get()->GetAutoCorrect();
+ const sal_Bool bDelete = !pACorr->GetSwFlags().bAutoCmpltKeepList;
+ for(sal_uInt16 nPos = aWordLst.Count(); nPos; nPos--)
+ {
+ SwAutoCompleteString* pCurrent = (SwAutoCompleteString*)aWordLst[ nPos - 1 ];
+ if(pCurrent->RemoveDocument(rDoc) && bDelete)
+ {
+ aWordLst.Remove( nPos - 1 );
+ sal_uInt16 nLRUPos = aLRULst.GetPos( (void*)pCurrent );
+ DBG_ASSERT(nLRUPos < USHRT_MAX, "word not found in LRU list" );
+ aLRULst.Remove( nLRUPos );
+ delete pCurrent;
+ }
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/doc/dbgoutsw.cxx b/sw/source/core/doc/dbgoutsw.cxx
new file mode 100644
index 000000000000..4444a713ea78
--- /dev/null
+++ b/sw/source/core/doc/dbgoutsw.cxx
@@ -0,0 +1,1042 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+#ifdef DEBUG
+
+#include <tools/string.hxx>
+#include <svl/poolitem.hxx>
+#include <svl/itemiter.hxx>
+#include <string>
+#include <map>
+#include <node.hxx>
+#include <ndtxt.hxx>
+#include <ndhints.hxx>
+#include <txatbase.hxx>
+#include <pam.hxx>
+#include <docary.hxx>
+#include <swundo.hxx>
+#include <undobj.hxx>
+#include <numrule.hxx>
+#include <doc.hxx>
+#include <frmfmt.hxx>
+#include <fmtanchr.hxx>
+#include <swrect.hxx>
+#include <ndarr.hxx>
+#include <paratr.hxx>
+#include <SwNodeNum.hxx>
+#include <dbgoutsw.hxx>
+#include <SwRewriter.hxx>
+#include <iostream>
+#include <cstdio>
+
+using namespace std;
+
+static ByteString aDbgOutResult;
+bool bDbgOutStdErr = false;
+bool bDbgOutPrintAttrSet = false;
+
+char* db_pretty_print(const String* str, int flags, char* fmt)
+{
+ (void) fmt;
+ (void) flags;
+ return const_cast<char*>(dbg_out(*str));
+}
+
+template<class T>
+String lcl_dbg_out_SvPtrArr(const T & rArr)
+{
+ String aStr("[ ", RTL_TEXTENCODING_ASCII_US);
+
+ for (sal_Int16 n = 0; n < rArr.Count(); n++)
+ {
+ if (n > 0)
+ aStr += String(", ", RTL_TEXTENCODING_ASCII_US);
+
+ if (rArr[n])
+ aStr += lcl_dbg_out(*rArr[n]);
+ else
+ aStr += String("(null)", RTL_TEXTENCODING_ASCII_US);
+ }
+
+ aStr += String(" ]", RTL_TEXTENCODING_ASCII_US);
+
+ return aStr;
+}
+
+SW_DLLPUBLIC const char * dbg_out(const void * pVoid)
+{
+ char sBuffer[1024];
+
+ sprintf(sBuffer, "%p", pVoid);
+
+ String aTmpStr(sBuffer, RTL_TEXTENCODING_ASCII_US);
+
+ return dbg_out(aTmpStr);
+}
+
+SW_DLLPUBLIC const char * dbg_out(const String & aStr)
+{
+ aDbgOutResult = ByteString(aStr, RTL_TEXTENCODING_ASCII_US);
+
+ if (bDbgOutStdErr)
+ fprintf(stderr, "%s", aDbgOutResult.GetBuffer());
+
+ return aDbgOutResult.GetBuffer();
+}
+
+SW_DLLPUBLIC const char * dbg_out(const ::rtl::OUString & aStr)
+{
+ aDbgOutResult = ByteString( rtl::OUStringToOString( aStr, RTL_TEXTENCODING_ASCII_US ) );
+ return aDbgOutResult.GetBuffer();
+}
+
+
+struct CompareUShort
+{
+ bool operator()(sal_uInt16 a, sal_uInt16 b) const
+ {
+ return a < b;
+ }
+};
+
+map<sal_uInt16,String,CompareUShort> & GetItemWhichMap()
+{
+ static map<sal_uInt16,String,CompareUShort> aItemWhichMap;
+ static bool bInitialized = false;
+
+ if (! bInitialized)
+ {
+ aItemWhichMap[RES_CHRATR_CASEMAP] = String("CHRATR_CASEMAP", RTL_TEXTENCODING_ASCII_US);
+ aItemWhichMap[RES_CHRATR_CHARSETCOLOR] = String("CHRATR_CHARSETCOLOR", RTL_TEXTENCODING_ASCII_US);
+ aItemWhichMap[RES_CHRATR_COLOR] = String("CHRATR_COLOR", RTL_TEXTENCODING_ASCII_US);
+ aItemWhichMap[RES_CHRATR_CONTOUR] = String("CHRATR_CONTOUR", RTL_TEXTENCODING_ASCII_US);
+ aItemWhichMap[RES_CHRATR_CROSSEDOUT] = String("CHRATR_CROSSEDOUT", RTL_TEXTENCODING_ASCII_US);
+ aItemWhichMap[RES_CHRATR_ESCAPEMENT] = String("CHRATR_ESCAPEMENT", RTL_TEXTENCODING_ASCII_US);
+ aItemWhichMap[RES_CHRATR_FONT] = String("CHRATR_FONT", RTL_TEXTENCODING_ASCII_US);
+ aItemWhichMap[RES_CHRATR_FONTSIZE] = String("CHRATR_FONTSIZE", RTL_TEXTENCODING_ASCII_US);
+ aItemWhichMap[RES_CHRATR_KERNING] = String("CHRATR_KERNING", RTL_TEXTENCODING_ASCII_US);
+ aItemWhichMap[RES_CHRATR_LANGUAGE] = String("CHRATR_LANGUAGE", RTL_TEXTENCODING_ASCII_US);
+ aItemWhichMap[RES_CHRATR_POSTURE] = String("CHRATR_POSTURE", RTL_TEXTENCODING_ASCII_US);
+ aItemWhichMap[RES_CHRATR_PROPORTIONALFONTSIZE] = String("CHRATR_PROPORTIONALFONTSIZE", RTL_TEXTENCODING_ASCII_US);
+ aItemWhichMap[RES_CHRATR_SHADOWED] = String("CHRATR_SHADOWED", RTL_TEXTENCODING_ASCII_US);
+ aItemWhichMap[RES_CHRATR_UNDERLINE] = String("CHRATR_UNDERLINE", RTL_TEXTENCODING_ASCII_US);
+ aItemWhichMap[RES_CHRATR_OVERLINE] = String("CHRATR_OVERLINE", RTL_TEXTENCODING_ASCII_US);
+ aItemWhichMap[RES_CHRATR_WEIGHT] = String("CHRATR_WEIGHT", RTL_TEXTENCODING_ASCII_US);
+ aItemWhichMap[RES_CHRATR_WORDLINEMODE] = String("CHRATR_WORDLINEMODE", RTL_TEXTENCODING_ASCII_US);
+ aItemWhichMap[RES_CHRATR_AUTOKERN] = String("CHRATR_AUTOKERN", RTL_TEXTENCODING_ASCII_US);
+ aItemWhichMap[RES_CHRATR_BLINK] = String("CHRATR_BLINK", RTL_TEXTENCODING_ASCII_US);
+ aItemWhichMap[RES_CHRATR_NOHYPHEN] = String("CHRATR_NOHYPHEN", RTL_TEXTENCODING_ASCII_US);
+ aItemWhichMap[RES_CHRATR_NOLINEBREAK] = String("CHRATR_NOLINEBREAK", RTL_TEXTENCODING_ASCII_US);
+ aItemWhichMap[RES_CHRATR_BACKGROUND] = String("CHRATR_BACKGROUND", RTL_TEXTENCODING_ASCII_US);
+ aItemWhichMap[RES_CHRATR_CJK_FONT] = String("CHRATR_CJK_FONT", RTL_TEXTENCODING_ASCII_US);
+ aItemWhichMap[RES_CHRATR_CJK_FONTSIZE] = String("CHRATR_CJK_FONTSIZE", RTL_TEXTENCODING_ASCII_US);
+ aItemWhichMap[RES_CHRATR_CJK_LANGUAGE] = String("CHRATR_CJK_LANGUAGE", RTL_TEXTENCODING_ASCII_US);
+ aItemWhichMap[RES_CHRATR_CJK_POSTURE] = String("CHRATR_CJK_POSTURE", RTL_TEXTENCODING_ASCII_US);
+ aItemWhichMap[RES_CHRATR_CJK_WEIGHT] = String("CHRATR_CJK_WEIGHT", RTL_TEXTENCODING_ASCII_US);
+ aItemWhichMap[RES_CHRATR_CTL_FONT] = String("CHRATR_CTL_FONT", RTL_TEXTENCODING_ASCII_US);
+ aItemWhichMap[RES_CHRATR_CTL_FONTSIZE] = String("CHRATR_CTL_FONTSIZE", RTL_TEXTENCODING_ASCII_US);
+ aItemWhichMap[RES_CHRATR_CTL_LANGUAGE] = String("CHRATR_CTL_LANGUAGE", RTL_TEXTENCODING_ASCII_US);
+ aItemWhichMap[RES_CHRATR_CTL_POSTURE] = String("CHRATR_CTL_POSTURE", RTL_TEXTENCODING_ASCII_US);
+ aItemWhichMap[RES_CHRATR_CTL_WEIGHT] = String("CHRATR_CTL_WEIGHT", RTL_TEXTENCODING_ASCII_US);
+ aItemWhichMap[RES_CHRATR_ROTATE] = String("CHRATR_ROTATE", RTL_TEXTENCODING_ASCII_US);
+ aItemWhichMap[RES_CHRATR_EMPHASIS_MARK] = String("CHRATR_EMPHASIS_MARK", RTL_TEXTENCODING_ASCII_US);
+ aItemWhichMap[RES_CHRATR_TWO_LINES] = String("CHRATR_TWO_LINES", RTL_TEXTENCODING_ASCII_US);
+ aItemWhichMap[RES_CHRATR_SCALEW] = String("CHRATR_SCALEW", RTL_TEXTENCODING_ASCII_US);
+ aItemWhichMap[RES_CHRATR_RELIEF] = String("CHRATR_RELIEF", RTL_TEXTENCODING_ASCII_US);
+ aItemWhichMap[RES_CHRATR_HIDDEN] = String("CHRATR_HIDDEN", RTL_TEXTENCODING_ASCII_US);
+ aItemWhichMap[RES_TXTATR_AUTOFMT] = String("TXTATR_AUTOFMT", RTL_TEXTENCODING_ASCII_US);
+ aItemWhichMap[RES_TXTATR_INETFMT] = String("TXTATR_INETFMT", RTL_TEXTENCODING_ASCII_US);
+ aItemWhichMap[RES_TXTATR_REFMARK] = String("TXTATR_REFMARK", RTL_TEXTENCODING_ASCII_US);
+ aItemWhichMap[RES_TXTATR_TOXMARK] = String("TXTATR_TOXMARK", RTL_TEXTENCODING_ASCII_US);
+ aItemWhichMap[RES_TXTATR_CHARFMT] = String("TXTATR_CHARFMT", RTL_TEXTENCODING_ASCII_US);
+ aItemWhichMap[RES_TXTATR_DUMMY5] = String("TXTATR_DUMMY5", RTL_TEXTENCODING_ASCII_US);
+ aItemWhichMap[RES_TXTATR_CJK_RUBY] = String("TXTATR_CJK_RUBY", RTL_TEXTENCODING_ASCII_US);
+ aItemWhichMap[RES_TXTATR_UNKNOWN_CONTAINER] = String("TXTATR_UNKNOWN_CONTAINER", RTL_TEXTENCODING_ASCII_US);
+ aItemWhichMap[RES_TXTATR_META] = String("TXTATR_META", RTL_TEXTENCODING_ASCII_US);
+ aItemWhichMap[RES_TXTATR_METAFIELD] = String("TXTATR_METAFIELD", RTL_TEXTENCODING_ASCII_US);
+ aItemWhichMap[RES_TXTATR_FIELD] = String("TXTATR_FIELD", RTL_TEXTENCODING_ASCII_US);
+ aItemWhichMap[RES_TXTATR_FLYCNT] = String("TXTATR_FLYCNT", RTL_TEXTENCODING_ASCII_US);
+ aItemWhichMap[RES_TXTATR_FTN] = String("TXTATR_FTN", RTL_TEXTENCODING_ASCII_US);
+ aItemWhichMap[RES_TXTATR_DUMMY4] = String("TXTATR_DUMMY4", RTL_TEXTENCODING_ASCII_US);
+ aItemWhichMap[RES_TXTATR_DUMMY3] = String("TXTATR_DUMMY3", RTL_TEXTENCODING_ASCII_US);
+ aItemWhichMap[RES_TXTATR_DUMMY1] = String("TXTATR_DUMMY1", RTL_TEXTENCODING_ASCII_US);
+ aItemWhichMap[RES_TXTATR_DUMMY2] = String("TXTATR_DUMMY2", RTL_TEXTENCODING_ASCII_US);
+ aItemWhichMap[RES_PARATR_LINESPACING] = String("PARATR_LINESPACING", RTL_TEXTENCODING_ASCII_US);
+ aItemWhichMap[RES_PARATR_ADJUST] = String("PARATR_ADJUST", RTL_TEXTENCODING_ASCII_US);
+ aItemWhichMap[RES_PARATR_SPLIT] = String("PARATR_SPLIT", RTL_TEXTENCODING_ASCII_US);
+ aItemWhichMap[RES_PARATR_ORPHANS] = String("PARATR_ORPHANS", RTL_TEXTENCODING_ASCII_US);
+ aItemWhichMap[RES_PARATR_WIDOWS] = String("PARATR_WIDOWS", RTL_TEXTENCODING_ASCII_US);
+ aItemWhichMap[RES_PARATR_TABSTOP] = String("PARATR_TABSTOP", RTL_TEXTENCODING_ASCII_US);
+ aItemWhichMap[RES_PARATR_HYPHENZONE] = String("PARATR_HYPHENZONE", RTL_TEXTENCODING_ASCII_US);
+ aItemWhichMap[RES_PARATR_DROP] = String("PARATR_DROP", RTL_TEXTENCODING_ASCII_US);
+ aItemWhichMap[RES_PARATR_REGISTER] = String("PARATR_REGISTER", RTL_TEXTENCODING_ASCII_US);
+ aItemWhichMap[RES_PARATR_NUMRULE] = String("PARATR_NUMRULE", RTL_TEXTENCODING_ASCII_US);
+ aItemWhichMap[RES_PARATR_SCRIPTSPACE] = String("PARATR_SCRIPTSPACE", RTL_TEXTENCODING_ASCII_US);
+ aItemWhichMap[RES_PARATR_HANGINGPUNCTUATION] = String("PARATR_HANGINGPUNCTUATION", RTL_TEXTENCODING_ASCII_US);
+ aItemWhichMap[RES_PARATR_FORBIDDEN_RULES] = String("PARATR_FORBIDDEN_RULES", RTL_TEXTENCODING_ASCII_US);
+ aItemWhichMap[RES_PARATR_VERTALIGN] = String("PARATR_VERTALIGN", RTL_TEXTENCODING_ASCII_US);
+ aItemWhichMap[RES_PARATR_SNAPTOGRID] = String("PARATR_SNAPTOGRID", RTL_TEXTENCODING_ASCII_US);
+ aItemWhichMap[RES_PARATR_CONNECT_BORDER] = String("PARATR_CONNECT_BORDER", RTL_TEXTENCODING_ASCII_US);
+ aItemWhichMap[RES_FILL_ORDER] = String("FILL_ORDER", RTL_TEXTENCODING_ASCII_US);
+ aItemWhichMap[RES_FRM_SIZE] = String("FRM_SIZE", RTL_TEXTENCODING_ASCII_US);
+ aItemWhichMap[RES_PAPER_BIN] = String("PAPER_BIN", RTL_TEXTENCODING_ASCII_US);
+ aItemWhichMap[RES_LR_SPACE] = String("LR_SPACE", RTL_TEXTENCODING_ASCII_US);
+ aItemWhichMap[RES_UL_SPACE] = String("UL_SPACE", RTL_TEXTENCODING_ASCII_US);
+ aItemWhichMap[RES_PAGEDESC] = String("PAGEDESC", RTL_TEXTENCODING_ASCII_US);
+ aItemWhichMap[RES_BREAK] = String("BREAK", RTL_TEXTENCODING_ASCII_US);
+ aItemWhichMap[RES_CNTNT] = String("CNTNT", RTL_TEXTENCODING_ASCII_US);
+ aItemWhichMap[RES_HEADER] = String("HEADER", RTL_TEXTENCODING_ASCII_US);
+ aItemWhichMap[RES_FOOTER] = String("FOOTER", RTL_TEXTENCODING_ASCII_US);
+ aItemWhichMap[RES_PRINT] = String("PRINT", RTL_TEXTENCODING_ASCII_US);
+ aItemWhichMap[RES_OPAQUE] = String("OPAQUE", RTL_TEXTENCODING_ASCII_US);
+ aItemWhichMap[RES_PROTECT] = String("PROTECT", RTL_TEXTENCODING_ASCII_US);
+ aItemWhichMap[RES_SURROUND] = String("SURROUND", RTL_TEXTENCODING_ASCII_US);
+ aItemWhichMap[RES_VERT_ORIENT] = String("VERT_ORIENT", RTL_TEXTENCODING_ASCII_US);
+ aItemWhichMap[RES_HORI_ORIENT] = String("HORI_ORIENT", RTL_TEXTENCODING_ASCII_US);
+ aItemWhichMap[RES_ANCHOR] = String("ANCHOR", RTL_TEXTENCODING_ASCII_US);
+ aItemWhichMap[RES_BACKGROUND] = String("BACKGROUND", RTL_TEXTENCODING_ASCII_US);
+ aItemWhichMap[RES_BOX] = String("BOX", RTL_TEXTENCODING_ASCII_US);
+ aItemWhichMap[RES_SHADOW] = String("SHADOW", RTL_TEXTENCODING_ASCII_US);
+ aItemWhichMap[RES_FRMMACRO] = String("FRMMACRO", RTL_TEXTENCODING_ASCII_US);
+ aItemWhichMap[RES_COL] = String("COL", RTL_TEXTENCODING_ASCII_US);
+ aItemWhichMap[RES_KEEP] = String("KEEP", RTL_TEXTENCODING_ASCII_US);
+ aItemWhichMap[RES_URL] = String("URL", RTL_TEXTENCODING_ASCII_US);
+ aItemWhichMap[RES_EDIT_IN_READONLY] = String("EDIT_IN_READONLY", RTL_TEXTENCODING_ASCII_US);
+ aItemWhichMap[RES_LAYOUT_SPLIT] = String("LAYOUT_SPLIT", RTL_TEXTENCODING_ASCII_US);
+ aItemWhichMap[RES_CHAIN] = String("CHAIN", RTL_TEXTENCODING_ASCII_US);
+ aItemWhichMap[RES_TEXTGRID] = String("TEXTGRID", RTL_TEXTENCODING_ASCII_US);
+ aItemWhichMap[RES_LINENUMBER ] = String("LINENUMBER ", RTL_TEXTENCODING_ASCII_US);
+ aItemWhichMap[RES_FTN_AT_TXTEND] = String("FTN_AT_TXTEND", RTL_TEXTENCODING_ASCII_US);
+ aItemWhichMap[RES_END_AT_TXTEND] = String("END_AT_TXTEND", RTL_TEXTENCODING_ASCII_US);
+ aItemWhichMap[RES_COLUMNBALANCE] = String("COLUMNBALANCE", RTL_TEXTENCODING_ASCII_US);
+ aItemWhichMap[RES_FRAMEDIR] = String("FRAMEDIR", RTL_TEXTENCODING_ASCII_US);
+ aItemWhichMap[RES_HEADER_FOOTER_EAT_SPACING] = String("HEADER_FOOTER_EAT_SPACING", RTL_TEXTENCODING_ASCII_US);
+ aItemWhichMap[RES_ROW_SPLIT] = String("ROW_SPLIT", RTL_TEXTENCODING_ASCII_US);
+ aItemWhichMap[RES_GRFATR_MIRRORGRF] = String("GRFATR_MIRRORGRF", RTL_TEXTENCODING_ASCII_US);
+ aItemWhichMap[RES_GRFATR_CROPGRF] = String("GRFATR_CROPGRF", RTL_TEXTENCODING_ASCII_US);
+ aItemWhichMap[RES_GRFATR_ROTATION] = String("GRFATR_ROTATION", RTL_TEXTENCODING_ASCII_US);
+ aItemWhichMap[RES_GRFATR_LUMINANCE] = String("GRFATR_LUMINANCE", RTL_TEXTENCODING_ASCII_US);
+ aItemWhichMap[RES_GRFATR_CONTRAST] = String("GRFATR_CONTRAST", RTL_TEXTENCODING_ASCII_US);
+ aItemWhichMap[RES_GRFATR_CHANNELR] = String("GRFATR_CHANNELR", RTL_TEXTENCODING_ASCII_US);
+ aItemWhichMap[RES_GRFATR_CHANNELG] = String("GRFATR_CHANNELG", RTL_TEXTENCODING_ASCII_US);
+ aItemWhichMap[RES_GRFATR_CHANNELB] = String("GRFATR_CHANNELB", RTL_TEXTENCODING_ASCII_US);
+ aItemWhichMap[RES_GRFATR_GAMMA] = String("GRFATR_GAMMA", RTL_TEXTENCODING_ASCII_US);
+ aItemWhichMap[RES_GRFATR_INVERT] = String("GRFATR_INVERT", RTL_TEXTENCODING_ASCII_US);
+ aItemWhichMap[RES_GRFATR_TRANSPARENCY] = String("GRFATR_TRANSPARENCY", RTL_TEXTENCODING_ASCII_US);
+ aItemWhichMap[RES_GRFATR_DRAWMODE] = String("GRFATR_DRAWMODE", RTL_TEXTENCODING_ASCII_US);
+ aItemWhichMap[RES_BOXATR_FORMAT] = String("BOXATR_FORMAT", RTL_TEXTENCODING_ASCII_US);
+ aItemWhichMap[RES_BOXATR_FORMULA] = String("BOXATR_FORMULA", RTL_TEXTENCODING_ASCII_US);
+ aItemWhichMap[RES_BOXATR_VALUE] = String("BOXATR_VALUE", RTL_TEXTENCODING_ASCII_US);
+
+ bInitialized = true;
+ }
+
+ return aItemWhichMap;
+}
+
+const String lcl_dbg_out(const SfxPoolItem & rItem)
+{
+ String aStr("[ ", RTL_TEXTENCODING_ASCII_US);
+
+ if (GetItemWhichMap().find(rItem.Which()) != GetItemWhichMap().end())
+ aStr += GetItemWhichMap()[rItem.Which()];
+ else
+ aStr += String::CreateFromInt32(rItem.Which());
+
+ aStr += String(" ]", RTL_TEXTENCODING_ASCII_US);
+
+ return aStr;
+}
+
+SW_DLLPUBLIC const char * dbg_out(const SfxPoolItem & rItem)
+{
+ return dbg_out(lcl_dbg_out(rItem));
+}
+
+SW_DLLPUBLIC const char * dbg_out(const SfxPoolItem * pItem)
+{
+ return dbg_out(pItem ? lcl_dbg_out(*pItem) :
+ String("(nil)", RTL_TEXTENCODING_ASCII_US));
+}
+
+SW_DLLPUBLIC const String lcl_dbg_out(const SfxItemSet & rSet)
+{
+ SfxItemIter aIter(rSet);
+ const SfxPoolItem * pItem;
+ bool bFirst = true;
+ String aStr = String("[ ", RTL_TEXTENCODING_ASCII_US);
+
+ pItem = aIter.FirstItem();
+
+ while (pItem )
+ {
+ if (!bFirst)
+ aStr += String(", ", RTL_TEXTENCODING_ASCII_US);
+
+ if ((sal_uIntPtr)pItem != SAL_MAX_SIZE)
+ aStr += lcl_dbg_out(*pItem);
+ else
+ aStr += String("invalid", RTL_TEXTENCODING_ASCII_US);
+
+ bFirst = false;
+
+ pItem = aIter.NextItem();
+ }
+
+ aStr += String(" ]", RTL_TEXTENCODING_ASCII_US);
+
+ return aStr;
+}
+
+SW_DLLPUBLIC const char * dbg_out(const SfxItemSet & rSet)
+{
+ return dbg_out(lcl_dbg_out(rSet));
+}
+
+const String lcl_dbg_out(const SwTxtAttr & rAttr)
+{
+ String aStr("[ ", RTL_TEXTENCODING_ASCII_US);
+
+ aStr += String::CreateFromInt32(*rAttr.GetStart());
+ aStr += String("->", RTL_TEXTENCODING_ASCII_US);
+ aStr += String::CreateFromInt32(*rAttr.GetEnd());
+ aStr += String(" ", RTL_TEXTENCODING_ASCII_US);
+ aStr += lcl_dbg_out(rAttr.GetAttr());
+
+ aStr += String(" ]", RTL_TEXTENCODING_ASCII_US);
+
+ return aStr;
+}
+
+SW_DLLPUBLIC const char * dbg_out(const SwTxtAttr & rAttr)
+{
+ return dbg_out(lcl_dbg_out(rAttr));
+}
+
+const String lcl_dbg_out(const SwpHints & rHints)
+{
+ String aStr("[ SwpHints\n", RTL_TEXTENCODING_ASCII_US);
+
+ for (sal_uInt16 i = 0; i < rHints.Count(); i++)
+ {
+ aStr += String(" ", RTL_TEXTENCODING_ASCII_US);
+ aStr += lcl_dbg_out(*rHints[i]);
+ aStr += String("\n", RTL_TEXTENCODING_ASCII_US);
+ }
+
+ aStr += String("]\n", RTL_TEXTENCODING_ASCII_US);
+
+ return aStr;
+}
+
+SW_DLLPUBLIC const char * dbg_out(const SwpHints &rHints)
+{
+ return dbg_out(lcl_dbg_out(rHints));
+}
+
+String lcl_dbg_out(const SwPosition & rPos)
+{
+ String aStr("( ", RTL_TEXTENCODING_ASCII_US);
+
+ aStr += String::CreateFromInt32(rPos.nNode.GetIndex());
+ aStr += String(", ", RTL_TEXTENCODING_ASCII_US);
+ aStr += String::CreateFromInt32(rPos.nContent.GetIndex());
+ aStr += String(": ", RTL_TEXTENCODING_ASCII_US);
+ aStr += String::CreateFromInt32
+ (reinterpret_cast<sal_IntPtr>(rPos.nContent.GetIdxReg()), 16);
+
+ aStr += String(" )", RTL_TEXTENCODING_ASCII_US);
+
+ return aStr;
+}
+
+SW_DLLPUBLIC const char * dbg_out(const SwPosition & rPos)
+{
+ return dbg_out(lcl_dbg_out(rPos));
+}
+
+String lcl_dbg_out(const SwPaM & rPam)
+{
+ String aStr("[ Pt: ", RTL_TEXTENCODING_ASCII_US);
+
+ aStr += lcl_dbg_out(*rPam.GetPoint());
+
+ if (rPam.HasMark())
+ {
+ aStr += String(", Mk: ", RTL_TEXTENCODING_ASCII_US);
+ aStr += lcl_dbg_out(*rPam.GetMark());
+ }
+
+ aStr += String(" ]", RTL_TEXTENCODING_ASCII_US);
+
+ return aStr;
+}
+
+SW_DLLPUBLIC const char * dbg_out(const SwPaM & rPam)
+{
+ return dbg_out(lcl_dbg_out(rPam));
+}
+
+String lcl_dbg_out(const SwNodeNum & )
+{
+ return String();/*rNum.ToString();*/
+}
+
+SW_DLLPUBLIC const char * dbg_out(const SwNodeNum & rNum)
+{
+ return dbg_out(lcl_dbg_out(rNum));
+}
+
+String lcl_dbg_out(const SwRect & rRect)
+{
+ String aResult("[ [", RTL_TEXTENCODING_ASCII_US);
+
+ aResult += String::CreateFromInt32(rRect.Left());
+ aResult += String(", ", RTL_TEXTENCODING_ASCII_US);
+ aResult += String::CreateFromInt32(rRect.Top());
+ aResult += String("], [", RTL_TEXTENCODING_ASCII_US);
+ aResult += String::CreateFromInt32(rRect.Right());
+ aResult += String(", ", RTL_TEXTENCODING_ASCII_US);
+ aResult += String::CreateFromInt32(rRect.Bottom());
+
+ aResult += String("] ]", RTL_TEXTENCODING_ASCII_US);
+
+ return aResult;
+}
+
+SW_DLLPUBLIC const char * dbg_out(const SwRect & rRect)
+{
+ return dbg_out(lcl_dbg_out(rRect));
+}
+
+String lcl_dbg_out(const SwFrmFmt & rFrmFmt)
+{
+ String aResult("[ ", RTL_TEXTENCODING_ASCII_US);
+
+ char sBuffer[256];
+ sprintf(sBuffer, "%p", &rFrmFmt);
+
+ aResult += String(sBuffer, RTL_TEXTENCODING_ASCII_US);
+ aResult += String("(", RTL_TEXTENCODING_ASCII_US);
+ aResult += rFrmFmt.GetName();
+ aResult += String(")", RTL_TEXTENCODING_ASCII_US);
+
+ if (rFrmFmt.IsAuto())
+ aResult += String("*", RTL_TEXTENCODING_ASCII_US);
+
+ aResult += String(" ,", RTL_TEXTENCODING_ASCII_US);
+ aResult += lcl_dbg_out(rFrmFmt.FindLayoutRect());
+ aResult += String(" ]", RTL_TEXTENCODING_ASCII_US);
+
+ return aResult;
+}
+
+SW_DLLPUBLIC const char * dbg_out(const SwFrmFmt & rFrmFmt)
+{
+ return dbg_out(lcl_dbg_out(rFrmFmt));
+}
+
+const String lcl_AnchoredFrames(const SwNode & rNode)
+{
+ String aResult("[", RTL_TEXTENCODING_ASCII_US);
+
+ const SwDoc * pDoc = rNode.GetDoc();
+ if (pDoc)
+ {
+ const SwSpzFrmFmts * pFrmFmts = pDoc->GetSpzFrmFmts();
+
+ if (pFrmFmts)
+ {
+ bool bFirst = true;
+ for (sal_uInt16 nI = 0; nI < pFrmFmts->Count(); nI++)
+ {
+ const SwFmtAnchor & rAnchor = (*pFrmFmts)[nI]->GetAnchor();
+ const SwPosition * pPos = rAnchor.GetCntntAnchor();
+
+ if (pPos && &pPos->nNode.GetNode() == &rNode)
+ {
+ if (! bFirst)
+ aResult += String(", ", RTL_TEXTENCODING_ASCII_US);
+
+ if ((*pFrmFmts)[nI])
+ aResult += lcl_dbg_out(*(*pFrmFmts)[nI]);
+ bFirst = false;
+ }
+ }
+ }
+ }
+
+ aResult += String("]", RTL_TEXTENCODING_ASCII_US);
+
+ return aResult;
+}
+
+String lcl_dbg_out_NumType(sal_Int16 nType)
+{
+ String aTmpStr;
+
+ switch (nType)
+ {
+ case SVX_NUM_NUMBER_NONE:
+ aTmpStr += String(" NONE", RTL_TEXTENCODING_ASCII_US);
+
+ break;
+ case SVX_NUM_CHARS_UPPER_LETTER:
+ aTmpStr += String(" CHARS_UPPER_LETTER",
+ RTL_TEXTENCODING_ASCII_US);
+
+ break;
+ case SVX_NUM_CHARS_LOWER_LETTER:
+ aTmpStr += String(" CHARS_LOWER_LETTER",
+ RTL_TEXTENCODING_ASCII_US);
+
+ break;
+ case SVX_NUM_ROMAN_UPPER:
+ aTmpStr += String(" ROMAN_UPPER",
+ RTL_TEXTENCODING_ASCII_US);
+
+ break;
+ case SVX_NUM_ROMAN_LOWER:
+ aTmpStr += String(" ROMAN_LOWER",
+ RTL_TEXTENCODING_ASCII_US);
+
+ break;
+ case SVX_NUM_ARABIC:
+ aTmpStr += String(" ARABIC",
+ RTL_TEXTENCODING_ASCII_US);
+
+ break;
+ default:
+ aTmpStr += String(" ??",
+ RTL_TEXTENCODING_ASCII_US);
+
+ break;
+ }
+
+ return aTmpStr;
+}
+
+String lcl_dbg_out(const SwNode & rNode)
+{
+ String aTmpStr;
+
+ aTmpStr += String("<node ", RTL_TEXTENCODING_ASCII_US);
+ aTmpStr += String("index=\"", RTL_TEXTENCODING_ASCII_US);
+ aTmpStr += String::CreateFromInt32(rNode.GetIndex());
+ aTmpStr += String("\"", RTL_TEXTENCODING_ASCII_US);
+
+#if OSL_DEBUG_LEVEL > 1
+ aTmpStr += String(" serial=\"", RTL_TEXTENCODING_ASCII_US);
+ aTmpStr += String::CreateFromInt32(rNode.GetSerial());
+ aTmpStr += String("\"", RTL_TEXTENCODING_ASCII_US);
+#endif
+
+ aTmpStr += String(" type=\"", RTL_TEXTENCODING_ASCII_US);
+ aTmpStr += String::CreateFromInt32(sal_Int32( rNode.GetNodeType() ) );
+ aTmpStr += String("\"", RTL_TEXTENCODING_ASCII_US);
+
+ aTmpStr += String(" pointer=\"", RTL_TEXTENCODING_ASCII_US);
+
+ char aBuffer[128];
+ sprintf(aBuffer, "%p", &rNode);
+ aTmpStr += String(aBuffer, RTL_TEXTENCODING_ASCII_US);
+
+ aTmpStr += String("\">", RTL_TEXTENCODING_ASCII_US);
+
+ const SwTxtNode * pTxtNode = rNode.GetTxtNode();
+
+ if (rNode.IsTxtNode())
+ {
+ const SfxItemSet * pAttrSet = pTxtNode->GetpSwAttrSet();
+
+ aTmpStr += String("<txt>", RTL_TEXTENCODING_ASCII_US);
+ aTmpStr += pTxtNode->GetTxt().Copy(0, 10);
+ aTmpStr += String("</txt>", RTL_TEXTENCODING_ASCII_US);
+
+ if (rNode.IsTableNode())
+ aTmpStr += String("<tbl/>", RTL_TEXTENCODING_ASCII_US);
+
+ aTmpStr += String("<outlinelevel>", RTL_TEXTENCODING_ASCII_US);
+ aTmpStr += String::CreateFromInt32(pTxtNode->GetAttrOutlineLevel()-1);
+ aTmpStr += String("</outlinelevel>", RTL_TEXTENCODING_ASCII_US);
+
+ const SwNumRule * pNumRule = pTxtNode->GetNumRule();
+
+ if (pNumRule != NULL)
+ {
+ aTmpStr += String("<number>", RTL_TEXTENCODING_ASCII_US);
+ if ( pTxtNode->GetNum() )
+ {
+ aTmpStr += lcl_dbg_out(*(pTxtNode->GetNum()));
+ }
+ aTmpStr += String("</number>", RTL_TEXTENCODING_ASCII_US);
+
+ aTmpStr += String("<rule>", RTL_TEXTENCODING_ASCII_US);
+ aTmpStr += pNumRule->GetName();
+
+ const SfxPoolItem * pItem = NULL;
+
+ if (pAttrSet && SFX_ITEM_SET ==
+ pAttrSet->GetItemState(RES_PARATR_NUMRULE, sal_False, &pItem))
+ {
+ aTmpStr += String("(", RTL_TEXTENCODING_ASCII_US);
+ aTmpStr +=
+ static_cast<const SwNumRuleItem *>(pItem)->GetValue();
+ aTmpStr += String(")", RTL_TEXTENCODING_ASCII_US);
+ aTmpStr += String("*", RTL_TEXTENCODING_ASCII_US);
+ }
+
+ const SwNumFmt * pNumFmt = NULL;
+ aTmpStr += String("</rule>", RTL_TEXTENCODING_ASCII_US);
+
+ if (pTxtNode->GetActualListLevel() > 0)
+ pNumFmt = pNumRule->GetNumFmt( static_cast< sal_uInt16 >(pTxtNode->GetActualListLevel()) );
+
+ if (pNumFmt)
+ {
+ aTmpStr += String("<numformat>", RTL_TEXTENCODING_ASCII_US);
+ aTmpStr +=
+ lcl_dbg_out_NumType(pNumFmt->GetNumberingType());
+ aTmpStr += String("</numformat>", RTL_TEXTENCODING_ASCII_US);
+ }
+ }
+
+ if (pTxtNode->IsCountedInList())
+ aTmpStr += String("<counted/>", RTL_TEXTENCODING_ASCII_US);
+
+ SwFmtColl * pColl = pTxtNode->GetFmtColl();
+
+ if (pColl)
+ {
+ aTmpStr += String("<coll>", RTL_TEXTENCODING_ASCII_US);
+ aTmpStr += pColl->GetName();
+
+ aTmpStr += String("(", RTL_TEXTENCODING_ASCII_US);
+ aTmpStr += String::CreateFromInt32
+ (static_cast<SwTxtFmtColl *>(pColl)->GetAssignedOutlineStyleLevel());//<-end,zhaojianwei
+
+ const SwNumRuleItem & rItem =
+ static_cast<const SwNumRuleItem &>
+ (pColl->GetFmtAttr(RES_PARATR_NUMRULE));
+ const String sNumruleName = rItem.GetValue();
+
+ if (sNumruleName.Len() > 0)
+ {
+ aTmpStr += String(", ", RTL_TEXTENCODING_ASCII_US);
+ aTmpStr += sNumruleName;
+ }
+ aTmpStr += String(")", RTL_TEXTENCODING_ASCII_US);
+ aTmpStr += String("</coll>", RTL_TEXTENCODING_ASCII_US);
+ }
+
+ SwFmtColl * pCColl = pTxtNode->GetCondFmtColl();
+
+ if (pCColl)
+ {
+ aTmpStr += String("<ccoll>", RTL_TEXTENCODING_ASCII_US);
+ aTmpStr += pCColl->GetName();
+ aTmpStr += String("</ccoll>", RTL_TEXTENCODING_ASCII_US);
+ }
+
+ aTmpStr += String("<frms>", RTL_TEXTENCODING_ASCII_US);
+ aTmpStr += lcl_AnchoredFrames(rNode);
+ aTmpStr += String("</frms>", RTL_TEXTENCODING_ASCII_US);
+
+ if (bDbgOutPrintAttrSet)
+ {
+ aTmpStr += String("<attrs>", RTL_TEXTENCODING_ASCII_US);
+ aTmpStr += lcl_dbg_out(pTxtNode->GetSwAttrSet());
+ aTmpStr += String("</attrs>", RTL_TEXTENCODING_ASCII_US);
+ }
+ }
+ else if (rNode.IsStartNode())
+ {
+ aTmpStr += String("<start end=\"", RTL_TEXTENCODING_ASCII_US);
+
+ const SwStartNode * pStartNode = dynamic_cast<const SwStartNode *> (&rNode);
+ if (pStartNode != NULL)
+ aTmpStr += String::CreateFromInt32(pStartNode->EndOfSectionNode()->GetIndex());
+
+ aTmpStr += String("\"/>", RTL_TEXTENCODING_ASCII_US);
+ }
+ else if (rNode.IsEndNode())
+ aTmpStr += String("<end/>", RTL_TEXTENCODING_ASCII_US);
+
+ aTmpStr += String("</node>", RTL_TEXTENCODING_ASCII_US);
+
+ return aTmpStr;
+}
+
+SW_DLLPUBLIC const char * dbg_out(const SwNode & rNode)
+{
+ return dbg_out(lcl_dbg_out(rNode));
+}
+
+SW_DLLPUBLIC const char * dbg_out(const SwNode * pNode)
+{
+ if (NULL != pNode)
+ return dbg_out(*pNode);
+ else
+ return NULL;
+}
+
+SW_DLLPUBLIC const char * dbg_out(const SwCntntNode * pNode)
+{
+ if (NULL != pNode)
+ return dbg_out(*pNode);
+ else
+ return NULL;
+}
+
+SW_DLLPUBLIC const char * dbg_out(const SwTxtNode * pNode)
+{
+ if (NULL != pNode)
+ return dbg_out(*pNode);
+ else
+ return NULL;
+}
+
+sal_Bool lcl_dbg_add_node(const SwNodePtr & pNode, void * pArgs)
+{
+ if (pNode)
+ {
+ (*((String *) pArgs)) += lcl_dbg_out(*pNode);
+ (*((String *) pArgs)) += String("\n", RTL_TEXTENCODING_ASCII_US);
+ }
+
+ //MBA: this code didn't compile, needed to add a return value
+ return sal_True;
+}
+
+void lcl_dbg_nodes_inner(String & aStr, SwNodes & rNodes, sal_uLong & nIndex)
+{
+ SwNode * pNode = rNodes[nIndex];
+ SwStartNode * pStartNode = dynamic_cast<SwStartNode *> (pNode);
+
+ SwNode * pEndNode = NULL;
+ if (pStartNode != NULL)
+ pEndNode = pStartNode->EndOfSectionNode();
+
+ sal_uLong nCount = rNodes.Count();
+ sal_uLong nStartIndex = nIndex;
+
+ bool bDone = false;
+
+ String aTag;
+ if (pNode->IsTableNode())
+ aTag += String("table", RTL_TEXTENCODING_ASCII_US);
+ else if (pNode->IsSectionNode())
+ aTag += String("section", RTL_TEXTENCODING_ASCII_US);
+ else
+ aTag += String("nodes", RTL_TEXTENCODING_ASCII_US);
+
+ aStr += String("<", RTL_TEXTENCODING_ASCII_US);
+ aStr += aTag;
+ aStr += String(">", RTL_TEXTENCODING_ASCII_US);
+
+ while (! bDone)
+ {
+ if (pNode->IsStartNode() && nIndex != nStartIndex)
+ lcl_dbg_nodes_inner(aStr, rNodes, nIndex);
+ else
+ {
+ aStr += lcl_dbg_out(*pNode);
+ aStr += String("\n", RTL_TEXTENCODING_ASCII_US);
+
+ nIndex++;
+ }
+
+ if (pNode == pEndNode || nIndex >= nCount)
+ bDone = true;
+ else
+ pNode = rNodes[nIndex];
+ }
+
+ aStr += String("</", RTL_TEXTENCODING_ASCII_US);
+ aStr += aTag;
+ aStr += String(">\n", RTL_TEXTENCODING_ASCII_US);
+}
+
+String lcl_dbg_out(SwNodes & rNodes)
+{
+ String aStr("<nodes-array>", RTL_TEXTENCODING_ASCII_US);
+
+ sal_uLong nIndex = 0;
+ sal_uLong nCount = rNodes.Count();
+
+ while (nIndex < nCount)
+ {
+ lcl_dbg_nodes_inner(aStr, rNodes, nIndex);
+ }
+
+ aStr += String("</nodes-array>\n", RTL_TEXTENCODING_ASCII_US);
+
+ return aStr;
+}
+
+SW_DLLPUBLIC const char * dbg_out(SwNodes & rNodes)
+{
+ return dbg_out(lcl_dbg_out(rNodes));
+}
+
+String lcl_dbg_out(const SwUndo & rUndo)
+{
+ String aStr("[ ", RTL_TEXTENCODING_ASCII_US);
+
+ aStr += String::CreateFromInt32(
+ static_cast<SfxUndoAction const&>(rUndo).GetId());
+ aStr += String(": ", RTL_TEXTENCODING_ASCII_US);
+
+ aStr += rUndo.GetComment();
+ aStr += String(" ]", RTL_TEXTENCODING_ASCII_US);
+
+ return aStr;
+}
+
+SW_DLLPUBLIC const char * dbg_out(const SwUndo & rUndo)
+{
+ return dbg_out(lcl_dbg_out(rUndo));
+}
+
+String lcl_dbg_out(SwOutlineNodes & rNodes)
+{
+ String aStr("[\n", RTL_TEXTENCODING_ASCII_US);
+
+ for (sal_uInt16 i = 0; i < rNodes.Count(); i++)
+ {
+ aStr += lcl_dbg_out(*rNodes[i]);
+ aStr += String("\n", RTL_TEXTENCODING_ASCII_US);
+ }
+
+ aStr += String("]\n", RTL_TEXTENCODING_ASCII_US);
+
+ return aStr;
+}
+
+SW_DLLPUBLIC const char * dbg_out(SwOutlineNodes & rNodes)
+{
+ return dbg_out(lcl_dbg_out(rNodes));
+}
+
+String lcl_dbg_out(const SwRewriter & rRewriter)
+{
+ (void) rRewriter;
+ String aResult;
+
+ //aResult = rRewriter.ToString();
+
+ return aResult;
+}
+
+SW_DLLPUBLIC const char * dbg_out(const SwRewriter & rRewriter)
+{
+ return dbg_out(lcl_dbg_out(rRewriter));
+}
+
+String lcl_dbg_out(const SvxNumberFormat & rFmt)
+{
+ String aResult;
+
+ aResult = lcl_dbg_out_NumType(rFmt.GetNumberingType());
+
+ return aResult;
+}
+
+String lcl_dbg_out(const SwNumRule & rRule)
+{
+ String aResult("[ ", RTL_TEXTENCODING_ASCII_US);
+
+ aResult += rRule.GetName();
+ aResult += String(" [", RTL_TEXTENCODING_ASCII_US);
+
+ for (sal_uInt8 n = 0; n < MAXLEVEL; n++)
+ {
+ if (n > 0)
+ aResult += String(", ", RTL_TEXTENCODING_ASCII_US);
+
+ aResult += lcl_dbg_out(rRule.Get(n));
+ }
+
+ aResult += String("]", RTL_TEXTENCODING_ASCII_US);
+
+ aResult += String("]", RTL_TEXTENCODING_ASCII_US);
+
+ return aResult;
+}
+
+SW_DLLPUBLIC const char * dbg_out(const SwNumRule & rRule)
+{
+ return dbg_out(lcl_dbg_out(rRule));
+}
+
+String lcl_dbg_out(const SwTxtFmtColl & rFmt)
+{
+ String aResult(rFmt.GetName());
+
+ aResult += String("(", RTL_TEXTENCODING_ASCII_US);
+ aResult += String::CreateFromInt32(rFmt.GetAttrOutlineLevel());
+ aResult += String(")", RTL_TEXTENCODING_ASCII_US);
+
+ return aResult;
+}
+
+SW_DLLPUBLIC const char * dbg_out(const SwTxtFmtColl & rFmt)
+{
+ return dbg_out(lcl_dbg_out(rFmt));
+}
+
+String lcl_dbg_out(const SwFrmFmts & rFrmFmts)
+{
+ return lcl_dbg_out_SvPtrArr<SwFrmFmts>(rFrmFmts);
+}
+
+SW_DLLPUBLIC const char * dbg_out(const SwFrmFmts & rFrmFmts)
+{
+ return dbg_out(lcl_dbg_out(rFrmFmts));
+}
+
+String lcl_dbg_out(const SwNumRuleTbl & rTbl)
+{
+ String aResult("[", RTL_TEXTENCODING_ASCII_US);
+
+ for (sal_uInt16 n = 0; n < rTbl.Count(); n++)
+ {
+ if (n > 0)
+ aResult += String(", ", RTL_TEXTENCODING_ASCII_US);
+
+ aResult += rTbl[n]->GetName();
+
+ char sBuffer[256];
+ sprintf(sBuffer, "(%p)", rTbl[n]);
+ aResult += String(sBuffer, RTL_TEXTENCODING_ASCII_US);
+ }
+
+ aResult += String("]", RTL_TEXTENCODING_ASCII_US);
+
+ return aResult;
+}
+
+SW_DLLPUBLIC const char * dbg_out(const SwNumRuleTbl & rTbl)
+{
+ return dbg_out(lcl_dbg_out(rTbl));
+}
+
+String lcl_TokenType2Str(FormTokenType nType)
+{
+ switch(nType)
+ {
+ case TOKEN_ENTRY_NO:
+ return String("NO", RTL_TEXTENCODING_ASCII_US);
+ case TOKEN_ENTRY_TEXT:
+ return String("ENTRY_TEXT", RTL_TEXTENCODING_ASCII_US);
+ case TOKEN_ENTRY:
+ return String("ENTRY", RTL_TEXTENCODING_ASCII_US);
+ case TOKEN_TAB_STOP:
+ return String("TAB_STOP", RTL_TEXTENCODING_ASCII_US);
+ case TOKEN_TEXT:
+ return String("TOKEN_TEXT", RTL_TEXTENCODING_ASCII_US);
+ case TOKEN_PAGE_NUMS:
+ return String("NUMS", RTL_TEXTENCODING_ASCII_US);
+ case TOKEN_CHAPTER_INFO:
+ return String("CHAPTER_INFO", RTL_TEXTENCODING_ASCII_US);
+ case TOKEN_LINK_START:
+ return String("LINK_START", RTL_TEXTENCODING_ASCII_US);
+ case TOKEN_LINK_END:
+ return String("LINK_END", RTL_TEXTENCODING_ASCII_US);
+ case TOKEN_AUTHORITY:
+ return String("AUTHORITY", RTL_TEXTENCODING_ASCII_US);
+ case TOKEN_END:
+ return String("END", RTL_TEXTENCODING_ASCII_US);
+ default:
+ return String("??", RTL_TEXTENCODING_ASCII_US);
+ }
+
+ OSL_FAIL("should not be reached");
+
+ return String("??", RTL_TEXTENCODING_ASCII_US);
+}
+
+String lcl_dbg_out(const SwFormToken & rToken)
+{
+ return rToken.GetString();
+}
+
+SW_DLLPUBLIC const char * dbg_out(const SwFormToken & rToken)
+{
+ return dbg_out(lcl_dbg_out(rToken));
+}
+
+String lcl_dbg_out(const SwFormTokens & rTokens)
+{
+ String aStr("[", RTL_TEXTENCODING_ASCII_US);
+
+ SwFormTokens::const_iterator aIt;
+
+ for (aIt = rTokens.begin(); aIt != rTokens.end(); ++aIt)
+ {
+ if (aIt != rTokens.begin())
+ aStr += String(", ", RTL_TEXTENCODING_ASCII_US);
+
+ aStr += lcl_TokenType2Str(aIt->eTokenType);
+ aStr += String(": ", RTL_TEXTENCODING_ASCII_US);
+ aStr += lcl_dbg_out(*aIt);
+ }
+
+ aStr += String("]" , RTL_TEXTENCODING_ASCII_US);
+
+ return aStr;
+}
+
+SW_DLLPUBLIC const char * dbg_out(const SwFormTokens & rTokens)
+{
+ return dbg_out(lcl_dbg_out(rTokens));
+}
+
+String lcl_dbg_out(const SwNodeRange & rRange)
+{
+ String aStr("[", RTL_TEXTENCODING_ASCII_US);
+
+ aStr += lcl_dbg_out(SwPosition(rRange.aStart));
+ aStr += String(", ", RTL_TEXTENCODING_ASCII_US);
+ aStr += lcl_dbg_out(SwPosition(rRange.aEnd));
+
+ aStr += String("]" , RTL_TEXTENCODING_ASCII_US);
+
+ return aStr;
+}
+
+SW_DLLPUBLIC const char * dbg_out(const SwNodeRange & rRange)
+{
+ return dbg_out(lcl_dbg_out(rRange));
+}
+
+#endif // DEBUG
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/doc/doc.cxx b/sw/source/core/doc/doc.cxx
new file mode 100644
index 000000000000..a031aa86098f
--- /dev/null
+++ b/sw/source/core/doc/doc.cxx
@@ -0,0 +1,2737 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+#include <doc.hxx>
+#include <UndoManager.hxx>
+#include <hintids.hxx>
+
+#include <tools/shl.hxx>
+#include <tools/globname.hxx>
+#include <svx/svxids.hrc>
+#include <com/sun/star/i18n/WordType.hdl>
+#include <com/sun/star/i18n/ForbiddenCharacters.hdl>
+#include <com/sun/star/lang/XMultiServiceFactory.hpp>
+#include <com/sun/star/beans/NamedValue.hpp>
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/document/XDocumentPropertiesSupplier.hpp>
+#include <com/sun/star/document/XDocumentProperties.hpp>
+#include <comphelper/processfactory.hxx>
+#include <tools/urlobj.hxx>
+#include <tools/poly.hxx>
+#include <tools/multisel.hxx>
+#include <rtl/ustring.hxx>
+#include <vcl/virdev.hxx>
+#include <svl/itemiter.hxx>
+#include <svl/poolitem.hxx>
+#include <unotools/syslocale.hxx>
+#include <sfx2/printer.hxx>
+#include <editeng/keepitem.hxx>
+#include <editeng/cscoitem.hxx>
+#include <editeng/brkitem.hxx>
+#include <sfx2/linkmgr.hxx>
+#include <editeng/forbiddencharacterstable.hxx>
+#include <svx/svdmodel.hxx>
+#include <editeng/pbinitem.hxx>
+#include <unotools/charclass.hxx>
+#include <unotools/localedatawrapper.hxx>
+
+#include <swatrset.hxx>
+#include <swmodule.hxx>
+#include <fmtpdsc.hxx>
+#include <fmtanchr.hxx>
+#include <fmtrfmrk.hxx>
+#include <fmtinfmt.hxx>
+#include <fmtfld.hxx>
+#include <txtfld.hxx>
+#include <dbfld.hxx>
+#include <txtinet.hxx>
+#include <txtrfmrk.hxx>
+#include <frmatr.hxx>
+#include <linkenum.hxx>
+#include <pagefrm.hxx>
+#include <rootfrm.hxx>
+#include <swtable.hxx>
+#include <pam.hxx>
+#include <ndtxt.hxx>
+#include <swundo.hxx> // fuer die UndoIds
+#include <UndoCore.hxx>
+#include <UndoInsert.hxx>
+#include <UndoSplitMove.hxx>
+#include <UndoTable.hxx>
+#include <pagedesc.hxx> //DTor
+#include <breakit.hxx>
+#include <ndole.hxx>
+#include <ndgrf.hxx>
+#include <rolbck.hxx> // Undo-Attr
+#include <doctxm.hxx> // fuer die Verzeichnisse
+#include <grfatr.hxx>
+#include <poolfmt.hxx> // PoolVorlagen-Id's
+#include <mvsave.hxx> // fuer Server-Funktionalitaet
+#include <SwGrammarMarkUp.hxx>
+#include <scriptinfo.hxx>
+#include <acorrect.hxx> // Autokorrektur
+#include <mdiexp.hxx> // Statusanzeige
+#include <docstat.hxx>
+#include <docary.hxx>
+#include <redline.hxx>
+#include <fldupde.hxx>
+#include <swbaslnk.hxx>
+#include <printdata.hxx>
+#include <cmdid.h> // fuer den dflt - Printer in SetJob
+#include <statstr.hrc> // StatLine-String
+#include <comcore.hrc>
+#include <SwUndoTOXChange.hxx>
+#include <SwUndoFmt.hxx>
+#include <unocrsr.hxx>
+#include <docsh.hxx>
+#include <viewopt.hxx>
+#include <docfld.hxx> // _SetGetExpFld
+#include <docufld.hxx> // SwPostItField
+#include <viewsh.hxx>
+#include <shellres.hxx>
+#include <txtfrm.hxx>
+#include <attrhint.hxx>
+
+#include <wdocsh.hxx> // SwWebDocShell
+#include <prtopt.hxx> // SwPrintOptions
+
+#include <vector>
+#include <map>
+
+#include <osl/diagnose.h>
+#include <osl/interlck.h>
+#include <vbahelper/vbaaccesshelper.hxx>
+
+#include "switerator.hxx"
+
+/* @@@MAINTAINABILITY-HORROR@@@
+ Probably unwanted dependency on SwDocShell
+*/
+#include <layouter.hxx>
+
+using namespace ::com::sun::star;
+using ::rtl::OUString;
+
+// Seiten-Deskriptoren
+SV_IMPL_PTRARR(SwPageDescs,SwPageDescPtr);
+// Verzeichnisse
+SV_IMPL_PTRARR( SwTOXTypes, SwTOXTypePtr )
+// FeldTypen
+SV_IMPL_PTRARR( SwFldTypes, SwFldTypePtr)
+
+/* IInterface */
+sal_Int32 SwDoc::acquire()
+{
+ OSL_ENSURE(mReferenceCount >= 0, "Negative reference count detected! This is a sign for unbalanced acquire/release calls.");
+ return osl_incrementInterlockedCount(&mReferenceCount);
+}
+
+sal_Int32 SwDoc::release()
+{
+ OSL_PRECOND(mReferenceCount >= 1, "Object is already released! Releasing it again leads to a negative reference count.");
+ return osl_decrementInterlockedCount(&mReferenceCount);
+}
+
+sal_Int32 SwDoc::getReferenceCount() const
+{
+ OSL_ENSURE(mReferenceCount >= 0, "Negative reference count detected! This is a sign for unbalanced acquire/release calls.");
+ return mReferenceCount;
+}
+
+/* IDocumentSettingAccess */
+bool SwDoc::get(/*[in]*/ DocumentSettingId id) const
+{
+ switch (id)
+ {
+ // COMPATIBILITY FLAGS START
+ case PARA_SPACE_MAX: return mbParaSpaceMax; //(n8Dummy1 & DUMMY_PARASPACEMAX);
+ case PARA_SPACE_MAX_AT_PAGES: return mbParaSpaceMaxAtPages; //(n8Dummy1 & DUMMY_PARASPACEMAX_AT_PAGES);
+ case TAB_COMPAT: return mbTabCompat; //(n8Dummy1 & DUMMY_TAB_COMPAT);
+ case ADD_FLY_OFFSETS: return mbAddFlyOffsets; //(n8Dummy2 & DUMMY_ADD_FLY_OFFSETS);
+ case ADD_EXT_LEADING: return mbAddExternalLeading; //(n8Dummy2 & DUMMY_ADD_EXTERNAL_LEADING);
+ case USE_VIRTUAL_DEVICE: return mbUseVirtualDevice; //(n8Dummy1 & DUMMY_USE_VIRTUAL_DEVICE);
+ case USE_HIRES_VIRTUAL_DEVICE: return mbUseHiResolutionVirtualDevice; //(n8Dummy2 & DUMMY_USE_HIRES_VIR_DEV);
+ case OLD_NUMBERING: return mbOldNumbering;
+ case OLD_LINE_SPACING: return mbOldLineSpacing;
+ case ADD_PARA_SPACING_TO_TABLE_CELLS: return mbAddParaSpacingToTableCells;
+ case USE_FORMER_OBJECT_POS: return mbUseFormerObjectPos;
+ case USE_FORMER_TEXT_WRAPPING: return mbUseFormerTextWrapping;
+ case CONSIDER_WRAP_ON_OBJECT_POSITION: return mbConsiderWrapOnObjPos;
+ case DO_NOT_JUSTIFY_LINES_WITH_MANUAL_BREAK: return mbDoNotJustifyLinesWithManualBreak;
+ case IGNORE_FIRST_LINE_INDENT_IN_NUMBERING: return mbIgnoreFirstLineIndentInNumbering;
+ case OUTLINE_LEVEL_YIELDS_OUTLINE_RULE: return mbOutlineLevelYieldsOutlineRule;
+ case TABLE_ROW_KEEP: return mbTableRowKeep;
+ case IGNORE_TABS_AND_BLANKS_FOR_LINE_CALCULATION: return mbIgnoreTabsAndBlanksForLineCalculation;
+ case DO_NOT_CAPTURE_DRAW_OBJS_ON_PAGE: return mbDoNotCaptureDrawObjsOnPage;
+ // #i68949#
+ case CLIP_AS_CHARACTER_ANCHORED_WRITER_FLY_FRAME: return mbClipAsCharacterAnchoredWriterFlyFrames;
+ case UNIX_FORCE_ZERO_EXT_LEADING: return mbUnixForceZeroExtLeading;
+ case USE_OLD_PRINTER_METRICS: return mbOldPrinterMetrics;
+ case TABS_RELATIVE_TO_INDENT : return mbTabRelativeToIndent;
+ case PROTECT_FORM: return mbProtectForm;
+ // #i89181#
+ case TAB_AT_LEFT_INDENT_FOR_PARA_IN_LIST: return mbTabAtLeftIndentForParagraphsInList;
+ case INVERT_BORDER_SPACING: return mbInvertBorderSpacing;
+ case COLLAPSE_EMPTY_CELL_PARA: return mbCollapseEmptyCellPara;
+
+ case BROWSE_MODE: return mbLastBrowseMode; // Attention: normally the ViewShell has to be asked!
+ case HTML_MODE: return mbHTMLMode;
+ case GLOBAL_DOCUMENT: return mbIsGlobalDoc;
+ case GLOBAL_DOCUMENT_SAVE_LINKS: return mbGlblDocSaveLinks;
+ case LABEL_DOCUMENT: return mbIsLabelDoc;
+ case PURGE_OLE: return mbPurgeOLE;
+ case KERN_ASIAN_PUNCTUATION: return mbKernAsianPunctuation;
+ case DO_NOT_RESET_PARA_ATTRS_FOR_NUM_FONT: return mbDoNotResetParaAttrsForNumFont;
+ case MATH_BASELINE_ALIGNMENT: return mbMathBaselineAlignment;
+ default:
+ OSL_FAIL("Invalid setting id");
+ }
+ return false;
+}
+
+void SwDoc::set(/*[in]*/ DocumentSettingId id, /*[in]*/ bool value)
+{
+ switch (id)
+ {
+ // COMPATIBILITY FLAGS START
+ case PARA_SPACE_MAX:
+ mbParaSpaceMax = value;
+ break;
+ case PARA_SPACE_MAX_AT_PAGES:
+ mbParaSpaceMaxAtPages = value;
+ break;
+ case TAB_COMPAT:
+ mbTabCompat = value;
+ break;
+ case ADD_FLY_OFFSETS:
+ mbAddFlyOffsets = value;
+ break;
+ case ADD_EXT_LEADING:
+ mbAddExternalLeading = value;
+ break;
+ case USE_VIRTUAL_DEVICE:
+ mbUseVirtualDevice = value;
+ break;
+ case USE_HIRES_VIRTUAL_DEVICE:
+ mbUseHiResolutionVirtualDevice = value;
+ break;
+ case OLD_NUMBERING:
+ if (mbOldNumbering != value)
+ {
+ mbOldNumbering = value;
+
+ const SwNumRuleTbl& rNmTbl = GetNumRuleTbl();
+ for( sal_uInt16 n = 0; n < rNmTbl.Count(); ++n )
+ rNmTbl[n]->SetInvalidRule(sal_True);
+
+ UpdateNumRule();
+
+ if (pOutlineRule)
+ {
+ pOutlineRule->Validate();
+ // counting of phantoms depends on <IsOldNumbering()>
+ pOutlineRule->SetCountPhantoms( !mbOldNumbering );
+ }
+ }
+ break;
+ case OLD_LINE_SPACING:
+ mbOldLineSpacing = value;
+ break;
+ case ADD_PARA_SPACING_TO_TABLE_CELLS:
+ mbAddParaSpacingToTableCells = value;
+ break;
+ case USE_FORMER_OBJECT_POS:
+ mbUseFormerObjectPos = value;
+ break;
+ case USE_FORMER_TEXT_WRAPPING:
+ mbUseFormerTextWrapping = value;
+ break;
+ case CONSIDER_WRAP_ON_OBJECT_POSITION:
+ mbConsiderWrapOnObjPos = value;
+ break;
+ case DO_NOT_JUSTIFY_LINES_WITH_MANUAL_BREAK:
+ mbDoNotJustifyLinesWithManualBreak = value;
+ break;
+ case IGNORE_FIRST_LINE_INDENT_IN_NUMBERING:
+ mbIgnoreFirstLineIndentInNumbering = value;
+ break;
+
+ case OUTLINE_LEVEL_YIELDS_OUTLINE_RULE:
+ mbOutlineLevelYieldsOutlineRule = value;
+ break;
+
+ case TABLE_ROW_KEEP:
+ mbTableRowKeep = value;
+ break;
+
+ case IGNORE_TABS_AND_BLANKS_FOR_LINE_CALCULATION:
+ mbIgnoreTabsAndBlanksForLineCalculation = value;
+ break;
+
+ case DO_NOT_CAPTURE_DRAW_OBJS_ON_PAGE:
+ mbDoNotCaptureDrawObjsOnPage = value;
+ break;
+
+ // #i68949#
+ case CLIP_AS_CHARACTER_ANCHORED_WRITER_FLY_FRAME:
+ mbClipAsCharacterAnchoredWriterFlyFrames = value;
+ break;
+
+ case UNIX_FORCE_ZERO_EXT_LEADING:
+ mbUnixForceZeroExtLeading = value;
+ break;
+
+ case PROTECT_FORM:
+ mbProtectForm = value;
+ break;
+
+ case USE_OLD_PRINTER_METRICS:
+ mbOldPrinterMetrics = value;
+ break;
+ case TABS_RELATIVE_TO_INDENT:
+ mbTabRelativeToIndent = value;
+ break;
+ // #i89181#
+ case TAB_AT_LEFT_INDENT_FOR_PARA_IN_LIST:
+ mbTabAtLeftIndentForParagraphsInList = value;
+ break;
+
+ case INVERT_BORDER_SPACING:
+ mbInvertBorderSpacing = value;
+ break;
+
+ case COLLAPSE_EMPTY_CELL_PARA:
+ mbCollapseEmptyCellPara = value;
+ break;
+ // COMPATIBILITY FLAGS END
+
+ case BROWSE_MODE: //can be used temporary (load/save) when no ViewShell is avaiable
+ mbLastBrowseMode = value;
+ break;
+
+ case HTML_MODE:
+ mbHTMLMode = value;
+ break;
+
+ case GLOBAL_DOCUMENT:
+ mbIsGlobalDoc = value;
+ break;
+
+ case GLOBAL_DOCUMENT_SAVE_LINKS:
+ mbGlblDocSaveLinks = value;
+ break;
+
+ case LABEL_DOCUMENT:
+ mbIsLabelDoc = value;
+ break;
+
+ case PURGE_OLE:
+ mbPurgeOLE = value;
+ break;
+
+ case KERN_ASIAN_PUNCTUATION:
+ mbKernAsianPunctuation = value;
+ break;
+
+ case DO_NOT_RESET_PARA_ATTRS_FOR_NUM_FONT:
+ mbDoNotResetParaAttrsForNumFont = value;
+ break;
+ case MATH_BASELINE_ALIGNMENT:
+ mbMathBaselineAlignment = value;
+ break;
+ default:
+ OSL_FAIL("Invalid setting id");
+ }
+}
+
+const i18n::ForbiddenCharacters*
+ SwDoc::getForbiddenCharacters(/*[in]*/ sal_uInt16 nLang, /*[in]*/ bool bLocaleData ) const
+{
+ const i18n::ForbiddenCharacters* pRet = 0;
+ if( xForbiddenCharsTable.is() )
+ pRet = xForbiddenCharsTable->GetForbiddenCharacters( nLang, sal_False );
+ if( bLocaleData && !pRet && pBreakIt )
+ pRet = &pBreakIt->GetForbidden( (LanguageType)nLang );
+ return pRet;
+}
+
+void SwDoc::setForbiddenCharacters(/*[in]*/ sal_uInt16 nLang,
+ /*[in]*/ const com::sun::star::i18n::ForbiddenCharacters& rFChars )
+{
+ if( !xForbiddenCharsTable.is() )
+ {
+ uno::Reference<
+ lang::XMultiServiceFactory > xMSF =
+ ::comphelper::getProcessServiceFactory();
+ xForbiddenCharsTable = new SvxForbiddenCharactersTable( xMSF );
+ }
+ xForbiddenCharsTable->SetForbiddenCharacters( nLang, rFChars );
+ if( pDrawModel )
+ {
+ pDrawModel->SetForbiddenCharsTable( xForbiddenCharsTable );
+ if( !mbInReading )
+ pDrawModel->ReformatAllTextObjects();
+ }
+
+ SwRootFrm* pTmpRoot = GetCurrentLayout();
+ if( pTmpRoot && !mbInReading )
+ {
+ pTmpRoot->StartAllAction();
+ std::set<SwRootFrm*> aAllLayouts = GetAllLayouts();
+ std::for_each( aAllLayouts.begin(), aAllLayouts.end(), std::bind2nd(std::mem_fun(&SwRootFrm::InvalidateAllCntnt), INV_SIZE));
+ pTmpRoot->EndAllAction();
+ }//swmod 080310
+ SetModified();
+}
+
+rtl::Reference<SvxForbiddenCharactersTable>& SwDoc::getForbiddenCharacterTable()
+{
+ if( !xForbiddenCharsTable.is() )
+ {
+ uno::Reference<
+ lang::XMultiServiceFactory > xMSF =
+ ::comphelper::getProcessServiceFactory();
+ xForbiddenCharsTable = new SvxForbiddenCharactersTable( xMSF );
+ }
+ return xForbiddenCharsTable;
+}
+
+const rtl::Reference<SvxForbiddenCharactersTable>& SwDoc::getForbiddenCharacterTable() const
+{
+ return xForbiddenCharsTable;
+}
+
+sal_uInt16 SwDoc::getLinkUpdateMode( /*[in]*/bool bGlobalSettings ) const
+{
+ sal_uInt16 nRet = nLinkUpdMode;
+ if( bGlobalSettings && GLOBALSETTING == nRet )
+ nRet = SW_MOD()->GetLinkUpdMode(get(IDocumentSettingAccess::HTML_MODE));
+ return nRet;
+}
+
+void SwDoc::setLinkUpdateMode( /*[in]*/sal_uInt16 eMode )
+{
+ nLinkUpdMode = eMode;
+}
+
+SwFldUpdateFlags SwDoc::getFieldUpdateFlags( /*[in]*/bool bGlobalSettings ) const
+{
+ SwFldUpdateFlags eRet = eFldUpdMode;
+ if( bGlobalSettings && AUTOUPD_GLOBALSETTING == eRet )
+ eRet = SW_MOD()->GetFldUpdateFlags(get(IDocumentSettingAccess::HTML_MODE));
+ return eRet;
+}
+
+void SwDoc::setFieldUpdateFlags(/*[in]*/SwFldUpdateFlags eMode )
+{
+ eFldUpdMode = eMode;
+}
+
+SwCharCompressType SwDoc::getCharacterCompressionType() const
+{
+ return eChrCmprType;
+}
+
+void SwDoc::setCharacterCompressionType( /*[in]*/SwCharCompressType n )
+{
+ if( eChrCmprType != n )
+ {
+ eChrCmprType = n;
+ if( pDrawModel )
+ {
+ pDrawModel->SetCharCompressType( static_cast<sal_uInt16>(n) );
+ if( !mbInReading )
+ pDrawModel->ReformatAllTextObjects();
+ }
+
+ SwRootFrm* pTmpRoot = GetCurrentLayout();
+ if( pTmpRoot && !mbInReading )
+ {
+ pTmpRoot->StartAllAction();
+ std::set<SwRootFrm*> aAllLayouts = GetAllLayouts();
+ std::for_each( aAllLayouts.begin(), aAllLayouts.end(), std::bind2nd(std::mem_fun(&SwRootFrm::InvalidateAllCntnt), INV_SIZE));
+ pTmpRoot->EndAllAction();
+ }//swmod 080310
+ SetModified();
+ }
+}
+
+/* IDocumentDeviceAccess */
+SfxPrinter* SwDoc::getPrinter(/*[in]*/ bool bCreate ) const
+{
+ SfxPrinter* pRet = 0;
+ if ( !bCreate || pPrt )
+ pRet = pPrt;
+ else
+ pRet = &CreatePrinter_();
+
+ return pRet;
+}
+
+void SwDoc::setPrinter(/*[in]*/ SfxPrinter *pP,/*[in]*/ bool bDeleteOld,/*[in]*/ bool bCallPrtDataChanged )
+{
+ if ( pP != pPrt )
+ {
+ if ( bDeleteOld )
+ delete pPrt;
+ pPrt = pP;
+
+ // our printer should always use TWIP. Don't rely on this being set in ViewShell::InitPrt, there
+ // are situations where this isn't called.
+ // #i108712# / 2010-02-26 / frank.schoenheit@sun.com
+ if ( pPrt )
+ {
+ MapMode aMapMode( pPrt->GetMapMode() );
+ aMapMode.SetMapUnit( MAP_TWIP );
+ pPrt->SetMapMode( aMapMode );
+ }
+
+ if ( pDrawModel && !get( IDocumentSettingAccess::USE_VIRTUAL_DEVICE ) )
+ pDrawModel->SetRefDevice( pPrt );
+ }
+
+ if ( bCallPrtDataChanged &&
+ // #i41075# Do not call PrtDataChanged() if we do not
+ // use the printer for formatting:
+ !get(IDocumentSettingAccess::USE_VIRTUAL_DEVICE) )
+ PrtDataChanged();
+}
+
+VirtualDevice* SwDoc::getVirtualDevice(/*[in]*/ bool bCreate ) const
+{
+ VirtualDevice* pRet = 0;
+ if ( !bCreate || pVirDev )
+ pRet = pVirDev;
+ else
+ pRet = &CreateVirtualDevice_();
+
+ return pRet;
+}
+
+void SwDoc::setVirtualDevice(/*[in]*/ VirtualDevice* pVd,/*[in]*/ bool bDeleteOld, /*[in]*/ bool )
+{
+ if ( pVirDev != pVd )
+ {
+ if ( bDeleteOld )
+ delete pVirDev;
+ pVirDev = pVd;
+
+ if ( pDrawModel && get( IDocumentSettingAccess::USE_VIRTUAL_DEVICE ) )
+ pDrawModel->SetRefDevice( pVirDev );
+ }
+}
+
+OutputDevice* SwDoc::getReferenceDevice(/*[in]*/ bool bCreate ) const
+{
+ OutputDevice* pRet = 0;
+ if ( !get(IDocumentSettingAccess::USE_VIRTUAL_DEVICE) )
+ {
+ pRet = getPrinter( bCreate );
+
+ if ( bCreate && !pPrt->IsValid() )
+ {
+ pRet = getVirtualDevice( sal_True );
+ }
+ }
+ else
+ {
+ pRet = getVirtualDevice( bCreate );
+ }
+
+ return pRet;
+}
+
+void SwDoc::setReferenceDeviceType(/*[in]*/ bool bNewVirtual,/*[in]*/ bool bNewHiRes )
+{
+ if ( get(IDocumentSettingAccess::USE_VIRTUAL_DEVICE) != bNewVirtual ||
+ get(IDocumentSettingAccess::USE_HIRES_VIRTUAL_DEVICE) != bNewHiRes )
+ {
+ if ( bNewVirtual )
+ {
+ VirtualDevice* pMyVirDev = getVirtualDevice( true );
+ if ( !bNewHiRes )
+ pMyVirDev->SetReferenceDevice( VirtualDevice::REFDEV_MODE06 );
+ else
+ pMyVirDev->SetReferenceDevice( VirtualDevice::REFDEV_MODE_MSO1 );
+
+ if( pDrawModel )
+ pDrawModel->SetRefDevice( pMyVirDev );
+ }
+ else
+ {
+ // #i41075#
+ // We have to take care that a printer exists before calling
+ // PrtDataChanged() in order to prevent that PrtDataChanged()
+ // triggers this funny situation:
+ // getReferenceDevice()->getPrinter()->CreatePrinter_()
+ // ->setPrinter()-> PrtDataChanged()
+ SfxPrinter* pPrinter = getPrinter( true );
+ if( pDrawModel )
+ pDrawModel->SetRefDevice( pPrinter );
+ }
+
+ set(IDocumentSettingAccess::USE_VIRTUAL_DEVICE, bNewVirtual );
+ set(IDocumentSettingAccess::USE_HIRES_VIRTUAL_DEVICE, bNewHiRes );
+ PrtDataChanged();
+ SetModified();
+ }
+}
+
+const JobSetup* SwDoc::getJobsetup() const
+{
+ return pPrt ? &pPrt->GetJobSetup() : 0;
+}
+
+void SwDoc::setJobsetup(/*[in]*/ const JobSetup &rJobSetup )
+{
+ sal_Bool bCheckPageDescs = 0 == pPrt;
+ sal_Bool bDataChanged = sal_False;
+
+ if ( pPrt )
+ {
+ if ( pPrt->GetName() == rJobSetup.GetPrinterName() )
+ {
+ if ( pPrt->GetJobSetup() != rJobSetup )
+ {
+ pPrt->SetJobSetup( rJobSetup );
+ bDataChanged = sal_True;
+ }
+ }
+ else
+ delete pPrt, pPrt = 0;
+ }
+
+ if( !pPrt )
+ {
+ //Das ItemSet wird vom Sfx geloescht!
+ SfxItemSet *pSet = new SfxItemSet( GetAttrPool(),
+ FN_PARAM_ADDPRINTER, FN_PARAM_ADDPRINTER,
+ SID_HTML_MODE, SID_HTML_MODE,
+ SID_PRINTER_NOTFOUND_WARN, SID_PRINTER_NOTFOUND_WARN,
+ SID_PRINTER_CHANGESTODOC, SID_PRINTER_CHANGESTODOC,
+ 0 );
+ SfxPrinter *p = new SfxPrinter( pSet, rJobSetup );
+ if ( bCheckPageDescs )
+ setPrinter( p, true, true );
+ else
+ {
+ pPrt = p;
+ bDataChanged = sal_True;
+ }
+ }
+ if ( bDataChanged && !get(IDocumentSettingAccess::USE_VIRTUAL_DEVICE) )
+ PrtDataChanged();
+}
+
+const SwPrintData & SwDoc::getPrintData() const
+{
+ if(!pPrtData)
+ {
+ SwDoc * pThis = const_cast< SwDoc * >(this);
+ pThis->pPrtData = new SwPrintData;
+
+ // SwPrintData should be initialized from the configuration,
+ // the respective config item is implememted by SwPrintOptions which
+ // is also derived from SwPrintData
+ const SwDocShell *pDocSh = GetDocShell();
+ DBG_ASSERT( pDocSh, "pDocSh is 0, can't determine if this is a WebDoc or not" );
+ bool bWeb = 0 != dynamic_cast< const SwWebDocShell * >(pDocSh);
+ SwPrintOptions aPrintOptions( bWeb );
+ *pThis->pPrtData = aPrintOptions;
+ }
+ return *pPrtData;
+}
+
+void SwDoc::setPrintData(/*[in]*/ const SwPrintData& rPrtData )
+{
+ if(!pPrtData)
+ pPrtData = new SwPrintData;
+ *pPrtData = rPrtData;
+}
+
+/* Implementations the next Interface here */
+
+/*
+ * Dokumenteditieren (Doc-SS) zum Fuellen des Dokuments
+ * durch den RTF Parser und fuer die EditShell.
+ */
+void SwDoc::ChgDBData(const SwDBData& rNewData)
+{
+ if( rNewData != aDBData )
+ {
+ aDBData = rNewData;
+ SetModified();
+ }
+ GetSysFldType(RES_DBNAMEFLD)->UpdateFlds();
+}
+
+bool SwDoc::SplitNode( const SwPosition &rPos, bool bChkTableStart )
+{
+ SwCntntNode *pNode = rPos.nNode.GetNode().GetCntntNode();
+ if(0 == pNode)
+ return false;
+
+ {
+ // BUG 26675: DataChanged vorm loeschen verschicken, dann bekommt
+ // man noch mit, welche Objecte sich im Bereich befinden.
+ // Danach koennen sie vor/hinter der Position befinden.
+ SwDataChanged aTmp( this, rPos, 0 );
+ }
+
+ SwUndoSplitNode* pUndo = 0;
+ if (GetIDocumentUndoRedo().DoesUndo())
+ {
+ GetIDocumentUndoRedo().ClearRedo();
+ // einfuegen vom Undo-Object, z.Z. nur beim TextNode
+ if( pNode->IsTxtNode() )
+ {
+ pUndo = new SwUndoSplitNode( this, rPos, bChkTableStart );
+ GetIDocumentUndoRedo().AppendUndo(pUndo);
+ }
+ }
+
+ //JP 28.01.97: Sonderfall fuer SplitNode am Tabellenanfang:
+ // steht die am Doc/Fly/Footer/..-Anfang oder direkt
+ // hinter einer Tabelle, dann fuege davor
+ // einen Absatz ein
+ if( bChkTableStart && !rPos.nContent.GetIndex() && pNode->IsTxtNode() )
+ {
+ sal_uLong nPrevPos = rPos.nNode.GetIndex() - 1;
+ const SwTableNode* pTblNd;
+ const SwNode* pNd = GetNodes()[ nPrevPos ];
+ if( pNd->IsStartNode() &&
+ SwTableBoxStartNode == ((SwStartNode*)pNd)->GetStartNodeType() &&
+ 0 != ( pTblNd = GetNodes()[ --nPrevPos ]->GetTableNode() ) &&
+ ((( pNd = GetNodes()[ --nPrevPos ])->IsStartNode() &&
+ SwTableBoxStartNode != ((SwStartNode*)pNd)->GetStartNodeType() )
+ || ( pNd->IsEndNode() && pNd->StartOfSectionNode()->IsTableNode() )
+ || pNd->IsCntntNode() ))
+ {
+ if( pNd->IsCntntNode() )
+ {
+ //JP 30.04.99 Bug 65660:
+ // ausserhalb des normalen BodyBereiches gibt es keine
+ // Seitenumbrueche, also ist das hier kein gueltige
+ // Bedingung fuers einfuegen eines Absatzes
+ if( nPrevPos < GetNodes().GetEndOfExtras().GetIndex() )
+ pNd = 0;
+ else
+ {
+ // Dann nur, wenn die Tabelle Umbrueche traegt!
+ const SwFrmFmt* pFrmFmt = pTblNd->GetTable().GetFrmFmt();
+ if( SFX_ITEM_SET != pFrmFmt->GetItemState(RES_PAGEDESC, sal_False) &&
+ SFX_ITEM_SET != pFrmFmt->GetItemState( RES_BREAK, sal_False ) )
+ pNd = 0;
+ }
+ }
+
+ if( pNd )
+ {
+ SwTxtNode* pTxtNd = GetNodes().MakeTxtNode(
+ SwNodeIndex( *pTblNd ),
+ GetTxtCollFromPool( RES_POOLCOLL_TEXT ));
+ if( pTxtNd )
+ {
+ ((SwPosition&)rPos).nNode = pTblNd->GetIndex()-1;
+ ((SwPosition&)rPos).nContent.Assign( pTxtNd, 0 );
+
+ // nur im BodyBereich den SeitenUmbruch/-Vorlage umhaengem
+ if( nPrevPos > GetNodes().GetEndOfExtras().GetIndex() )
+ {
+ SwFrmFmt* pFrmFmt = pTblNd->GetTable().GetFrmFmt();
+ const SfxPoolItem *pItem;
+ if( SFX_ITEM_SET == pFrmFmt->GetItemState( RES_PAGEDESC,
+ sal_False, &pItem ) )
+ {
+ pTxtNd->SetAttr( *pItem );
+ pFrmFmt->ResetFmtAttr( RES_PAGEDESC );
+ }
+ if( SFX_ITEM_SET == pFrmFmt->GetItemState( RES_BREAK,
+ sal_False, &pItem ) )
+ {
+ pTxtNd->SetAttr( *pItem );
+ pFrmFmt->ResetFmtAttr( RES_BREAK );
+ }
+ }
+
+ if( pUndo )
+ pUndo->SetTblFlag();
+ SetModified();
+ return true;
+ }
+ }
+ }
+ }
+
+ SvULongs aBkmkArr( 15, 15 );
+ _SaveCntntIdx( this, rPos.nNode.GetIndex(), rPos.nContent.GetIndex(),
+ aBkmkArr, SAVEFLY_SPLIT );
+ // FIXME: only SwTxtNode has a valid implementation of SplitCntntNode!
+ OSL_ENSURE(pNode->IsTxtNode(), "splitting non-text node?");
+ pNode = pNode->SplitCntntNode( rPos );
+ if (pNode)
+ {
+ // verschiebe noch alle Bookmarks/TOXMarks/FlyAtCnt
+ if( aBkmkArr.Count() )
+ _RestoreCntntIdx( this, aBkmkArr, rPos.nNode.GetIndex()-1, 0, sal_True );
+
+ if( IsRedlineOn() || (!IsIgnoreRedline() && pRedlineTbl->Count() ))
+ {
+ SwPaM aPam( rPos );
+ aPam.SetMark();
+ aPam.Move( fnMoveBackward );
+ if( IsRedlineOn() )
+ AppendRedline( new SwRedline( nsRedlineType_t::REDLINE_INSERT, aPam ), true);
+ else
+ SplitRedline( aPam );
+ }
+ }
+
+ SetModified();
+ return true;
+}
+
+bool SwDoc::AppendTxtNode( SwPosition& rPos )
+{
+ // create new node before EndOfContent
+ SwTxtNode * pCurNode = rPos.nNode.GetNode().GetTxtNode();
+ if( !pCurNode )
+ {
+ // dann kann ja einer angelegt werden!
+ SwNodeIndex aIdx( rPos.nNode, 1 );
+ pCurNode = GetNodes().MakeTxtNode( aIdx,
+ GetTxtCollFromPool( RES_POOLCOLL_STANDARD ));
+ }
+ else
+ pCurNode = (SwTxtNode*)pCurNode->AppendNode( rPos );
+
+ rPos.nNode++;
+ rPos.nContent.Assign( pCurNode, 0 );
+
+ if (GetIDocumentUndoRedo().DoesUndo())
+ {
+ GetIDocumentUndoRedo().AppendUndo( new SwUndoInsert( rPos.nNode ) );
+ }
+
+ if( IsRedlineOn() || (!IsIgnoreRedline() && pRedlineTbl->Count() ))
+ {
+ SwPaM aPam( rPos );
+ aPam.SetMark();
+ aPam.Move( fnMoveBackward );
+ if( IsRedlineOn() )
+ AppendRedline( new SwRedline( nsRedlineType_t::REDLINE_INSERT, aPam ), true);
+ else
+ SplitRedline( aPam );
+ }
+
+ SetModified();
+ return sal_True;
+}
+
+bool SwDoc::InsertString( const SwPaM &rRg, const String &rStr,
+ const enum InsertFlags nInsertMode )
+{
+ if (GetIDocumentUndoRedo().DoesUndo())
+ {
+ GetIDocumentUndoRedo().ClearRedo(); // AppendUndo not always called!
+ }
+
+ const SwPosition& rPos = *rRg.GetPoint();
+
+ if( pACEWord ) // Aufnahme in die Autokorrektur
+ {
+ if( 1 == rStr.Len() && pACEWord->IsDeleted() )
+ {
+ pACEWord->CheckChar( rPos, rStr.GetChar( 0 ) );
+ }
+ delete pACEWord, pACEWord = 0;
+ }
+
+ SwTxtNode *const pNode = rPos.nNode.GetNode().GetTxtNode();
+ if(!pNode)
+ {
+ return false;
+ }
+
+ SwDataChanged aTmp( rRg, 0 );
+
+ if (!GetIDocumentUndoRedo().DoesUndo() ||
+ !GetIDocumentUndoRedo().DoesGroupUndo())
+ {
+ pNode->InsertText( rStr, rPos.nContent, nInsertMode );
+
+ if (GetIDocumentUndoRedo().DoesUndo())
+ {
+ SwUndoInsert * const pUndo( new SwUndoInsert(
+ rPos.nNode, rPos.nContent.GetIndex(), rStr.Len(), nInsertMode));
+ GetIDocumentUndoRedo().AppendUndo(pUndo);
+ }
+ }
+ else
+ { // ist Undo und Gruppierung eingeschaltet, ist alles anders !
+ SwUndoInsert * pUndo = NULL;
+
+ // don't group the start if hints at the start should be expanded
+ if (!(nInsertMode & IDocumentContentOperations::INS_FORCEHINTEXPAND))
+ {
+ SwUndo *const pLastUndo = GetUndoManager().GetLastUndo();
+ SwUndoInsert *const pUndoInsert(
+ dynamic_cast<SwUndoInsert *>(pLastUndo) );
+ if (pUndoInsert && pUndoInsert->CanGrouping(rPos))
+ {
+ pUndo = pUndoInsert;
+ }
+ }
+
+ CharClass const& rCC = GetAppCharClass();
+ xub_StrLen nInsPos = rPos.nContent.GetIndex();
+
+ if (!pUndo)
+ {
+ pUndo = new SwUndoInsert( rPos.nNode, nInsPos, 0, nInsertMode,
+ !rCC.isLetterNumeric( rStr, 0 ) );
+ GetIDocumentUndoRedo().AppendUndo( pUndo );
+ }
+
+ pNode->InsertText( rStr, rPos.nContent, nInsertMode );
+
+ for( xub_StrLen i = 0; i < rStr.Len(); ++i )
+ {
+ nInsPos++;
+ // wenn CanGrouping() sal_True returnt, ist schon alles erledigt
+ if( !pUndo->CanGrouping( rStr.GetChar( i ) ))
+ {
+ pUndo = new SwUndoInsert( rPos.nNode, nInsPos, 1, nInsertMode,
+ !rCC.isLetterNumeric( rStr, i ) );
+ GetIDocumentUndoRedo().AppendUndo( pUndo );
+ }
+ }
+ }
+
+ if( IsRedlineOn() || (!IsIgnoreRedline() && pRedlineTbl->Count() ))
+ {
+ SwPaM aPam( rPos.nNode, aTmp.GetCntnt(),
+ rPos.nNode, rPos.nContent.GetIndex());
+ if( IsRedlineOn() )
+ {
+ AppendRedline(
+ new SwRedline( nsRedlineType_t::REDLINE_INSERT, aPam ), true);
+ }
+ else
+ {
+ SplitRedline( aPam );
+ }
+ }
+
+ SetModified();
+ return true;
+}
+
+SwFlyFrmFmt* SwDoc::_InsNoTxtNode( const SwPosition& rPos, SwNoTxtNode* pNode,
+ const SfxItemSet* pFlyAttrSet,
+ const SfxItemSet* pGrfAttrSet,
+ SwFrmFmt* pFrmFmt)
+{
+ SwFlyFrmFmt *pFmt = 0;
+ if( pNode )
+ {
+ pFmt = _MakeFlySection( rPos, *pNode, FLY_AT_PARA,
+ pFlyAttrSet, pFrmFmt );
+ if( pGrfAttrSet )
+ pNode->SetAttr( *pGrfAttrSet );
+ }
+ return pFmt;
+}
+
+SwFlyFrmFmt* SwDoc::Insert( const SwPaM &rRg,
+ const String& rGrfName,
+ const String& rFltName,
+ const Graphic* pGraphic,
+ const SfxItemSet* pFlyAttrSet,
+ const SfxItemSet* pGrfAttrSet,
+ SwFrmFmt* pFrmFmt )
+{
+ if( !pFrmFmt )
+ pFrmFmt = GetFrmFmtFromPool( RES_POOLFRM_GRAPHIC );
+ return _InsNoTxtNode( *rRg.GetPoint(), GetNodes().MakeGrfNode(
+ SwNodeIndex( GetNodes().GetEndOfAutotext() ),
+ rGrfName, rFltName, pGraphic,
+ pDfltGrfFmtColl ),
+ pFlyAttrSet, pGrfAttrSet, pFrmFmt );
+}
+
+SwFlyFrmFmt* SwDoc::Insert( const SwPaM &rRg, const GraphicObject& rGrfObj,
+ const SfxItemSet* pFlyAttrSet,
+ const SfxItemSet* pGrfAttrSet,
+ SwFrmFmt* pFrmFmt )
+{
+ if( !pFrmFmt )
+ pFrmFmt = GetFrmFmtFromPool( RES_POOLFRM_GRAPHIC );
+ return _InsNoTxtNode( *rRg.GetPoint(), GetNodes().MakeGrfNode(
+ SwNodeIndex( GetNodes().GetEndOfAutotext() ),
+ rGrfObj, pDfltGrfFmtColl ),
+ pFlyAttrSet, pGrfAttrSet, pFrmFmt );
+}
+
+SwFlyFrmFmt* SwDoc::Insert(const SwPaM &rRg, const svt::EmbeddedObjectRef& xObj,
+ const SfxItemSet* pFlyAttrSet,
+ const SfxItemSet* pGrfAttrSet,
+ SwFrmFmt* pFrmFmt )
+{
+ if( !pFrmFmt )
+ {
+ sal_uInt16 nId = RES_POOLFRM_OLE;
+ SvGlobalName aClassName( xObj->getClassID() );
+ if (SotExchange::IsMath(aClassName))
+ nId = RES_POOLFRM_FORMEL;
+
+ pFrmFmt = GetFrmFmtFromPool( nId );
+ }
+ return _InsNoTxtNode( *rRg.GetPoint(), GetNodes().MakeOLENode(
+ SwNodeIndex( GetNodes().GetEndOfAutotext() ),
+ xObj,
+ pDfltGrfFmtColl ),
+ pFlyAttrSet, pGrfAttrSet,
+ pFrmFmt );
+}
+
+SwFlyFrmFmt* SwDoc::InsertOLE(const SwPaM &rRg, const String& rObjName,
+ sal_Int64 nAspect,
+ const SfxItemSet* pFlyAttrSet,
+ const SfxItemSet* pGrfAttrSet,
+ SwFrmFmt* pFrmFmt )
+{
+ if( !pFrmFmt )
+ pFrmFmt = GetFrmFmtFromPool( RES_POOLFRM_OLE );
+
+ return _InsNoTxtNode( *rRg.GetPoint(),
+ GetNodes().MakeOLENode(
+ SwNodeIndex( GetNodes().GetEndOfAutotext() ),
+ rObjName,
+ nAspect,
+ pDfltGrfFmtColl,
+ 0 ),
+ pFlyAttrSet, pGrfAttrSet,
+ pFrmFmt );
+}
+
+/*************************************************************************
+|* SwDoc::GetFldType()
+|* Beschreibung: liefert den am Doc eingerichteten Feldtypen zurueck
+*************************************************************************/
+SwFieldType *SwDoc::GetSysFldType( const sal_uInt16 eWhich ) const
+{
+ for( sal_uInt16 i = 0; i < INIT_FLDTYPES; ++i )
+ if( eWhich == (*pFldTypes)[i]->Which() )
+ return (*pFldTypes)[i];
+ return 0;
+}
+
+/*************************************************************************
+ * void SetDocStat( const SwDocStat& rStat );
+ *************************************************************************/
+void SwDoc::SetDocStat( const SwDocStat& rStat )
+{
+ *pDocStat = rStat;
+}
+
+const SwDocStat& SwDoc::GetDocStat() const
+{
+ return *pDocStat;
+}
+
+struct _PostItFld : public _SetGetExpFld
+{
+ _PostItFld( const SwNodeIndex& rNdIdx, const SwTxtFld* pFld, const SwIndex* pIdx = 0 )
+ : _SetGetExpFld( rNdIdx, pFld, pIdx ) {}
+
+ sal_uInt16 GetPageNo( const StringRangeEnumerator &rRangeEnum,
+ const std::set< sal_Int32 > &rPossiblePages,
+ sal_uInt16& rVirtPgNo, sal_uInt16& rLineNo );
+
+ SwPostItField* GetPostIt() const
+ {
+ return (SwPostItField*) GetFld()->GetFld().GetFld();
+ }
+};
+
+sal_uInt16 _PostItFld::GetPageNo(
+ const StringRangeEnumerator &rRangeEnum,
+ const std::set< sal_Int32 > &rPossiblePages,
+ /* out */ sal_uInt16& rVirtPgNo, /* out */ sal_uInt16& rLineNo )
+{
+ //Problem: Wenn ein PostItFld in einem Node steht, der von mehr als
+ //einer Layout-Instanz repraesentiert wird, steht die Frage im Raum,
+ //ob das PostIt nur ein- oder n-mal gedruck werden soll.
+ //Wahrscheinlich nur einmal, als Seitennummer soll hier keine Zufaellige
+ //sondern die des ersten Auftretens des PostIts innerhalb des selektierten
+ //Bereichs ermittelt werden.
+ rVirtPgNo = 0;
+ sal_uInt16 nPos = GetCntnt();
+ SwIterator<SwTxtFrm,SwTxtNode> aIter( GetFld()->GetTxtNode() );
+ for( SwTxtFrm* pFrm = aIter.First(); pFrm; pFrm = aIter.Next() )
+ {
+ if( pFrm->GetOfst() > nPos ||
+ (pFrm->HasFollow() && pFrm->GetFollow()->GetOfst() <= nPos) )
+ continue;
+ sal_uInt16 nPgNo = pFrm->GetPhyPageNum();
+ if( rRangeEnum.hasValue( nPgNo, &rPossiblePages ))
+ {
+ rLineNo = (sal_uInt16)(pFrm->GetLineCount( nPos ) +
+ pFrm->GetAllLines() - pFrm->GetThisLines());
+ rVirtPgNo = pFrm->GetVirtPageNum();
+ return nPgNo;
+ }
+ }
+ return 0;
+}
+
+bool lcl_GetPostIts(
+ IDocumentFieldsAccess* pIDFA,
+ _SetGetExpFlds * pSrtLst )
+{
+ bool bHasPostIts = false;
+
+ SwFieldType* pFldType = pIDFA->GetSysFldType( RES_POSTITFLD );
+ DBG_ASSERT( pFldType, "kein PostItType ? ");
+
+ if( pFldType->GetDepends() )
+ {
+ // Modify-Object gefunden, trage alle Felder ins Array ein
+ SwIterator<SwFmtFld,SwFieldType> aIter( *pFldType );
+ const SwTxtFld* pTxtFld;
+ for( SwFmtFld* pFld = aIter.First(); pFld; pFld = aIter.Next() )
+ {
+ if( 0 != ( pTxtFld = pFld->GetTxtFld() ) &&
+ pTxtFld->GetTxtNode().GetNodes().IsDocNodes() )
+ {
+ bHasPostIts = true;
+ if (pSrtLst)
+ {
+ SwNodeIndex aIdx( pTxtFld->GetTxtNode() );
+ _PostItFld* pNew = new _PostItFld( aIdx, pTxtFld );
+ pSrtLst->Insert( pNew );
+ }
+ else
+ break; // we just wanted to check for the existence of postits ...
+ }
+ }
+ }
+
+ return bHasPostIts;
+}
+
+static void lcl_FormatPostIt(
+ IDocumentContentOperations* pIDCO,
+ SwPaM& aPam,
+ SwPostItField* pField,
+ bool bNewPage, bool bIsFirstPostIt,
+ sal_uInt16 nPageNo, sal_uInt16 nLineNo )
+{
+ static char const sTmp[] = " : ";
+
+ DBG_ASSERT( ViewShell::GetShellRes(), "missing ShellRes" );
+
+ if (bNewPage)
+ {
+ pIDCO->InsertPoolItem( aPam, SvxFmtBreakItem( SVX_BREAK_PAGE_AFTER, RES_BREAK ), 0 );
+ pIDCO->SplitNode( *aPam.GetPoint(), false );
+ }
+ else if (!bIsFirstPostIt)
+ {
+ // add an empty line between different notes
+ pIDCO->SplitNode( *aPam.GetPoint(), false );
+ pIDCO->SplitNode( *aPam.GetPoint(), false );
+ }
+
+ String aStr( ViewShell::GetShellRes()->aPostItPage );
+ aStr.AppendAscii(sTmp);
+
+ aStr += XubString::CreateFromInt32( nPageNo );
+ aStr += ' ';
+ if( nLineNo )
+ {
+ aStr += ViewShell::GetShellRes()->aPostItLine;
+ aStr.AppendAscii(sTmp);
+ aStr += XubString::CreateFromInt32( nLineNo );
+ aStr += ' ';
+ }
+ aStr += ViewShell::GetShellRes()->aPostItAuthor;
+ aStr.AppendAscii(sTmp);
+ aStr += pField->GetPar1();
+ aStr += ' ';
+ SvtSysLocale aSysLocale;
+ aStr += /*(LocaleDataWrapper&)*/aSysLocale.GetLocaleData().getDate( pField->GetDate() );
+ pIDCO->InsertString( aPam, aStr );
+
+ pIDCO->SplitNode( *aPam.GetPoint(), false );
+ aStr = pField->GetPar2();
+#if defined( WNT ) || defined( PM2 )
+ // Bei Windows und Co alle CR rausschmeissen
+ aStr.EraseAllChars( '\r' );
+#endif
+ pIDCO->InsertString( aPam, aStr );
+}
+
+// provide the paper tray to use according to the page style in use,
+// but do that only if the respective item is NOT just the default item
+static sal_Int32 lcl_GetPaperBin( const SwPageFrm *pStartFrm )
+{
+ sal_Int32 nRes = -1;
+
+ const SwFrmFmt &rFmt = pStartFrm->GetPageDesc()->GetMaster();
+ const SfxPoolItem *pItem = NULL;
+ SfxItemState eState = rFmt.GetItemState( RES_PAPER_BIN, sal_False, &pItem );
+ const SvxPaperBinItem *pPaperBinItem = dynamic_cast< const SvxPaperBinItem * >(pItem);
+ if (eState > SFX_ITEM_DEFAULT && pPaperBinItem)
+ nRes = pPaperBinItem->GetValue();
+
+ return nRes;
+}
+
+void SwDoc::CalculatePagesForPrinting(
+ const SwRootFrm& rLayout,
+ /* out */ SwRenderData &rData,
+ const SwPrintUIOptions &rOptions,
+ bool bIsPDFExport,
+ sal_Int32 nDocPageCount )
+{
+ const sal_Int32 nContent = rOptions.getIntValue( "PrintContent", 0 );
+ const bool bPrintSelection = nContent == 2;
+
+ // properties to take into account when calcualting the set of pages
+ // (PDF export UI does not allow for selecting left or right pages only)
+ bool bPrintLeftPages = bIsPDFExport ? true : rOptions.IsPrintLeftPages();
+ bool bPrintRightPages = bIsPDFExport ? true : rOptions.IsPrintRightPages();
+ // #i103700# printing selections should not allow for automatic inserting empty pages
+ bool bPrintEmptyPages = bPrintSelection ? false : rOptions.IsPrintEmptyPages( bIsPDFExport );
+
+ Range aPages( 1, nDocPageCount );
+
+ MultiSelection aMulti( aPages );
+ aMulti.SetTotalRange( Range( 0, RANGE_MAX ) );
+ aMulti.Select( aPages );
+
+ const SwPageFrm *pStPage = dynamic_cast<const SwPageFrm*>( rLayout.Lower() );
+ const SwFrm *pEndPage = pStPage;
+
+ sal_uInt16 nFirstPageNo = 0;
+ sal_uInt16 nLastPageNo = 0;
+
+ for( sal_uInt16 i = 1; i <= (sal_uInt16)aPages.Max(); ++i )
+ {
+ if( i < (sal_uInt16)aPages.Min() )
+ {
+ if( !pStPage->GetNext() )
+ break;
+ pStPage = (SwPageFrm*)pStPage->GetNext();
+ pEndPage= pStPage;
+ }
+ else if( i == (sal_uInt16)aPages.Min() )
+ {
+ nFirstPageNo = i;
+ nLastPageNo = nFirstPageNo;
+ if( !pStPage->GetNext() || (i == (sal_uInt16)aPages.Max()) )
+ break;
+ pEndPage = pStPage->GetNext();
+ }
+ else if( i > (sal_uInt16)aPages.Min() )
+ {
+ nLastPageNo = i;
+ if( !pEndPage->GetNext() || (i == (sal_uInt16)aPages.Max()) )
+ break;
+ pEndPage = pEndPage->GetNext();
+ }
+ }
+
+ DBG_ASSERT( nFirstPageNo, "first page not found! Should not happen!" );
+ if (nFirstPageNo)
+ {
+// HACK: Hier muss von der MultiSelection noch eine akzeptable Moeglichkeit
+// geschaffen werden, alle Seiten von Seite x an zu deselektieren.
+// Z.B. durch SetTotalRange ....
+
+// aMulti.Select( Range( nLastPageNo+1, SELECTION_MAX ), sal_False );
+ MultiSelection aTmpMulti( Range( 1, nLastPageNo ) );
+ long nTmpIdx = aMulti.FirstSelected();
+ static long nEndOfSelection = SFX_ENDOFSELECTION;
+ while ( nEndOfSelection != nTmpIdx && nTmpIdx <= long(nLastPageNo) )
+ {
+ aTmpMulti.Select( nTmpIdx );
+ nTmpIdx = aMulti.NextSelected();
+ }
+ aMulti = aTmpMulti;
+// Ende des HACKs
+
+ sal_uInt16 nPageNo = nFirstPageNo;
+
+ std::map< sal_Int32, sal_Int32 > &rPrinterPaperTrays = rData.GetPrinterPaperTrays();
+ std::set< sal_Int32 > &rValidPages = rData.GetValidPagesSet();
+ std::map< sal_Int32, const SwPageFrm * > &rValidStartFrms = rData.GetValidStartFrames();
+ rValidPages.clear();
+ rValidStartFrms.clear();
+ while ( pStPage )
+ {
+ const sal_Bool bRightPg = pStPage->OnRightPage();
+ if ( aMulti.IsSelected( nPageNo ) &&
+ ( (bRightPg && bPrintRightPages) ||
+ (!bRightPg && bPrintLeftPages) ) )
+ {
+ // Feature - Print empty pages
+ if ( bPrintEmptyPages || pStPage->Frm().Height() )
+ {
+ rValidPages.insert( nPageNo );
+ rValidStartFrms[ nPageNo ] = pStPage;
+
+ rPrinterPaperTrays[ nPageNo ] = lcl_GetPaperBin( pStPage );
+ }
+ }
+
+ if ( pStPage == pEndPage )
+ {
+ pStPage = 0;
+ }
+ else
+ { ++nPageNo;
+ pStPage = (SwPageFrm*)pStPage->GetNext();
+ }
+ }
+ }
+
+
+ //
+ // now that we have identified the valid pages for printing according
+ // to the print settings we need to get the PageRange to use and
+ // use both results to get the actual pages to be printed
+ // (post-it settings need to be taken into account later on!)
+ //
+
+ // get PageRange value to use
+ OUString aPageRange;
+ // #i116085# - adjusting fix for i113919
+ if ( !bIsPDFExport )
+ {
+ // PageContent :
+ // 0 -> print all pages (default if aPageRange is empty)
+ // 1 -> print range according to PageRange
+ // 2 -> print selection
+ if (1 == nContent)
+ aPageRange = rOptions.getStringValue( "PageRange", OUString() );
+ if (2 == nContent)
+ {
+ // note that printing selections is actually implemented by copying
+ // the selection to a new temporary document and printing all of that one.
+ // Thus for Writer "PrintContent" must never be 2.
+ // See SwXTextDocument::GetRenderDoc for evaluating if a selection is to be
+ // printed and for creating the temporary document.
+ }
+
+ // please note
+ }
+ if (aPageRange.getLength() == 0) // empty string -> print all
+ {
+ // set page range to print to 'all pages'
+ aPageRange = OUString::valueOf( (sal_Int32)1 );
+ aPageRange += OUString::valueOf( (sal_Unicode)'-');
+ aPageRange += OUString::valueOf( nDocPageCount );
+ }
+ rData.SetPageRange( aPageRange );
+
+ // get vector of pages to print according to PageRange and valid pages set from above
+ // (result may be an empty vector, for example if the range string is not correct)
+ StringRangeEnumerator::getRangesFromString(
+ aPageRange, rData.GetPagesToPrint(),
+ 1, nDocPageCount, 0, &rData.GetValidPagesSet() );
+}
+
+void SwDoc::UpdatePagesForPrintingWithPostItData(
+ /* out */ SwRenderData &rData,
+ const SwPrintUIOptions &rOptions,
+ bool /*bIsPDFExport*/,
+ sal_Int32 nDocPageCount )
+{
+
+ sal_Int16 nPostItMode = (sal_Int16) rOptions.getIntValue( "PrintAnnotationMode", 0 );
+ DBG_ASSERT(nPostItMode == POSTITS_NONE || rData.HasPostItData(),
+ "print post-its without post-it data?" );
+ const sal_uInt16 nPostItCount = rData.HasPostItData() ? rData.m_pPostItFields->Count() : 0;
+ if (nPostItMode != POSTITS_NONE && nPostItCount > 0)
+ {
+ SET_CURR_SHELL( rData.m_pPostItShell );
+
+ // clear document and move to end of it
+ SwPaM aPam( rData.m_pPostItDoc->GetNodes().GetEndOfContent() );
+ aPam.Move( fnMoveBackward, fnGoDoc );
+ aPam.SetMark();
+ aPam.Move( fnMoveForward, fnGoDoc );
+ rData.m_pPostItDoc->DeleteRange( aPam );
+
+ const StringRangeEnumerator aRangeEnum( rData.GetPageRange(), 1, nDocPageCount, 0 );
+
+ // For mode POSTITS_ENDPAGE:
+ // maps a physical page number to the page number in post-it document that holds
+ // the first post-it for that physical page . Needed to relate the correct start frames
+ // from the post-it doc to the physical page of the document
+ std::map< sal_Int32, sal_Int32 > aPostItLastStartPageNum;
+
+ // add all post-its on valid pages within the the page range to the
+ // temporary post-it document.
+ // Since the array of post-it fileds is sorted by page and line number we will
+ // already get them in the correct order
+ sal_uInt16 nVirtPg = 0, nLineNo = 0, nLastPageNum = 0, nPhyPageNum = 0;
+ bool bIsFirstPostIt = true;
+ for (sal_uInt16 i = 0; i < nPostItCount; ++i)
+ {
+ _PostItFld& rPostIt = (_PostItFld&)*(*rData.m_pPostItFields)[ i ];
+ nLastPageNum = nPhyPageNum;
+ nPhyPageNum = rPostIt.GetPageNo(
+ aRangeEnum, rData.GetValidPagesSet(), nVirtPg, nLineNo );
+ if (nPhyPageNum)
+ {
+ // need to insert a page break?
+ // In POSTITS_ENDPAGE mode for each document page the following
+ // post-it page needs to start on a new page
+ const bool bNewPage = nPostItMode == POSTITS_ENDPAGE &&
+ !bIsFirstPostIt && nPhyPageNum != nLastPageNum;
+
+ lcl_FormatPostIt( rData.m_pPostItShell->GetDoc(), aPam,
+ rPostIt.GetPostIt(), bNewPage, bIsFirstPostIt, nVirtPg, nLineNo );
+ bIsFirstPostIt = false;
+
+ if (nPostItMode == POSTITS_ENDPAGE)
+ {
+ // get the correct number of current pages for the post-it document
+ rData.m_pPostItShell->CalcLayout();
+ const sal_Int32 nPages = rData.m_pPostItShell->GetPageCount();
+ aPostItLastStartPageNum[ nPhyPageNum ] = nPages;
+ }
+ }
+ }
+
+ // format post-it doc to get correct number of pages
+ rData.m_pPostItShell->CalcLayout();
+ const sal_Int32 nPostItDocPageCount = rData.m_pPostItShell->GetPageCount();
+
+ if (nPostItMode == POSTITS_ONLY || nPostItMode == POSTITS_ENDDOC)
+ {
+ // now add those post-it pages to the vector of pages to print
+ // or replace them if only post-its should be printed
+
+ rData.GetPostItStartFrames().clear();
+ if (nPostItMode == POSTITS_ENDDOC)
+ {
+ // set all values up to number of pages to print currently known to NULL,
+ // meaning none of the pages currently in the vector is from the
+ // post-it document, they are the documents pages.
+ rData.GetPostItStartFrames().resize( rData.GetPagesToPrint().size() );
+ }
+ else if (nPostItMode == POSTITS_ONLY)
+ {
+ // no document page to be printed
+ rData.GetPagesToPrint().clear();
+ }
+
+ // now we just need to add the post-it pages to be printed to the end
+ // of the vector of pages to print and keep the GetValidStartFrames
+ // data conform with it
+ sal_Int32 nPageNum = 0;
+ const SwPageFrm * pPageFrm = (SwPageFrm*)rData.m_pPostItShell->GetLayout()->Lower();
+ while( pPageFrm && nPageNum < nPostItDocPageCount )
+ {
+ DBG_ASSERT( pPageFrm, "Empty page frame. How are we going to print this?" );
+ ++nPageNum;
+ rData.GetPagesToPrint().push_back( 0 ); // a page number of 0 indicates this page is from the post-it doc
+ DBG_ASSERT( pPageFrm, "pPageFrm is NULL!" );
+ rData.GetPostItStartFrames().push_back( pPageFrm );
+ pPageFrm = (SwPageFrm*)pPageFrm->GetNext();
+ }
+ DBG_ASSERT( nPageNum == nPostItDocPageCount, "unexpected number of pages" );
+ }
+ else if (nPostItMode == POSTITS_ENDPAGE)
+ {
+ // the next step is to find all the start frames from the post-it
+ // document that should be printed for a given physical page of the document
+ std::map< sal_Int32, std::vector< const SwPageFrm * > > aPhysPageToPostItFrames;
+
+ // ... thus, first collect all post-it doc start frames in a vector
+ sal_Int32 nPostItPageNum = 0;
+ std::vector< const SwPageFrm * > aAllPostItStartFrames;
+ const SwPageFrm * pPageFrm = (SwPageFrm*)rData.m_pPostItShell->GetLayout()->Lower();
+ while( pPageFrm && sal_Int32(aAllPostItStartFrames.size()) < nPostItDocPageCount )
+ {
+ DBG_ASSERT( pPageFrm, "Empty page frame. How are we going to print this?" );
+ ++nPostItPageNum;
+ aAllPostItStartFrames.push_back( pPageFrm );
+ pPageFrm = (SwPageFrm*)pPageFrm->GetNext();
+ }
+ DBG_ASSERT( sal_Int32(aAllPostItStartFrames.size()) == nPostItDocPageCount,
+ "unexpected number of frames; does not match number of pages" );
+
+ // get a map that holds all post-it frames to be printed for a
+ // given physical page from the document
+ sal_Int32 nLastStartPageNum = 0;
+ std::map< sal_Int32, sal_Int32 >::const_iterator aIt;
+ for (aIt = aPostItLastStartPageNum.begin(); aIt != aPostItLastStartPageNum.end(); ++aIt)
+ {
+ const sal_Int32 nFrames = aIt->second - nLastStartPageNum;
+ const sal_Int32 nFirstStartPageNum = aIt == aPostItLastStartPageNum.begin() ?
+ 1 : aIt->second - nFrames + 1;
+ DBG_ASSERT( 1 <= nFirstStartPageNum && nFirstStartPageNum <= nPostItDocPageCount,
+ "page number for first frame out of range" );
+ std::vector< const SwPageFrm * > aStartFrames;
+ for (sal_Int32 i = 0; i < nFrames; ++i)
+ {
+ const sal_Int32 nIdx = nFirstStartPageNum - 1 + i; // -1 because lowest page num is 1
+ DBG_ASSERT( 0 <= nIdx && nIdx < sal_Int32(aAllPostItStartFrames.size()),
+ "index out of range" );
+ aStartFrames.push_back( aAllPostItStartFrames[ nIdx ] );
+ }
+ aPhysPageToPostItFrames[ aIt->first /* phys page num */ ] = aStartFrames;
+ nLastStartPageNum = aIt->second;
+ }
+
+
+ // ok, now that aPhysPageToPostItFrames can give the start frames for all
+ // post-it pages to be printed we need to merge those at the correct
+ // position into the GetPagesToPrint vector and build and maintain the
+ // GetValidStartFrames vector as well.
+ // Since inserting a larger number of entries in the middle of a vector
+ // isn't that efficient we will create new vectors by copying the required data
+ std::vector< sal_Int32 > aTmpPagesToPrint;
+ std::vector< const SwPageFrm * > aTmpPostItStartFrames;
+ const size_t nNum = rData.GetPagesToPrint().size();
+ for (size_t i = 0 ; i < nNum; ++i)
+ {
+ // add the physical page to print from the document
+ const sal_Int32 nPhysPage = rData.GetPagesToPrint()[i];
+ aTmpPagesToPrint.push_back( nPhysPage );
+ aTmpPostItStartFrames.push_back( NULL );
+
+ // add the post-it document pages to print, i.e those
+ // post-it pages that have the data for the above physical page
+ const std::vector< const SwPageFrm * > &rPostItFrames = aPhysPageToPostItFrames[ nPhysPage ];
+ const size_t nPostItFrames = rPostItFrames.size();
+ for (size_t k = 0; k < nPostItFrames; ++k)
+ {
+ aTmpPagesToPrint.push_back( 0 );
+ aTmpPostItStartFrames.push_back( rPostItFrames[k] );
+ }
+ }
+
+ // finally we need to assign those vectors to the resulting ones.
+ // swapping the data should be more efficient than assigning since
+ // we won't need the temporary vectors anymore
+ rData.GetPagesToPrint().swap( aTmpPagesToPrint );
+ rData.GetPostItStartFrames().swap( aTmpPostItStartFrames );
+ }
+ }
+}
+
+void SwDoc::CalculatePagePairsForProspectPrinting(
+ const SwRootFrm& rLayout,
+ /* out */ SwRenderData &rData,
+ const SwPrintUIOptions &rOptions,
+ sal_Int32 nDocPageCount )
+{
+ std::map< sal_Int32, sal_Int32 > &rPrinterPaperTrays = rData.GetPrinterPaperTrays();
+ std::set< sal_Int32 > &rValidPagesSet = rData.GetValidPagesSet();
+ std::map< sal_Int32, const SwPageFrm * > &rValidStartFrms = rData.GetValidStartFrames();
+ std::vector< std::pair< sal_Int32, sal_Int32 > > &rPagePairs = rData.GetPagePairsForProspectPrinting();
+
+ rPagePairs.clear();
+ rValidPagesSet.clear();
+ rValidStartFrms.clear();
+
+ rtl::OUString aPageRange = rOptions.getStringValue( "PageRange", rtl::OUString() );
+ // PageContent :
+ // 0 -> print all pages (default if aPageRange is empty)
+ // 1 -> print range according to PageRange
+ // 2 -> print selection
+ const sal_Int32 nContent = rOptions.getIntValue( "PrintContent", 0 );
+ if (0 == nContent)
+ {
+ // set page range to print to 'all pages'
+ aPageRange = OUString::valueOf( (sal_Int32)1 );
+ aPageRange += OUString::valueOf( (sal_Unicode)'-');
+ aPageRange += OUString::valueOf( nDocPageCount );
+ }
+ StringRangeEnumerator aRange( aPageRange, 1, nDocPageCount, 0 );
+
+ if ( aRange.size() <= 0)
+ return;
+
+ const SwPageFrm *pStPage = dynamic_cast<const SwPageFrm*>( rLayout.Lower() );
+ sal_Int32 i = 0;
+ for ( i = 1; pStPage && i < nDocPageCount; ++i )
+ pStPage = (SwPageFrm*)pStPage->GetNext();
+ if ( !pStPage ) // dann wars das
+ return;
+
+ // currently for prospect printing all pages are valid to be printed
+ // thus we add them all to the respective map and set for later use
+ sal_Int32 nPageNum = 0;
+ const SwPageFrm *pPageFrm = dynamic_cast<const SwPageFrm*>( rLayout.Lower() );
+ while( pPageFrm && nPageNum < nDocPageCount )
+ {
+ DBG_ASSERT( pPageFrm, "Empty page frame. How are we going to print this?" );
+ ++nPageNum;
+ rValidPagesSet.insert( nPageNum );
+ rValidStartFrms[ nPageNum ] = pPageFrm;
+ pPageFrm = (SwPageFrm*)pPageFrm->GetNext();
+
+ rPrinterPaperTrays[ nPageNum ] = lcl_GetPaperBin( pStPage );
+ }
+ DBG_ASSERT( nPageNum == nDocPageCount, "unexpected number of pages" );
+
+ // properties to take into account when calcualting the set of pages
+ // Note: here bPrintLeftPages and bPrintRightPages refer to the (virtual) resulting pages
+ // of the prospect!
+ bool bPrintLeftPages = rOptions.IsPrintLeftPages();
+ bool bPrintRightPages = rOptions.IsPrintRightPages();
+ bool bPrintProspectRTL = rOptions.getIntValue( "PrintProspectRTL", 0 ) ? true : false;
+
+ // get pages for prospect printing according to the 'PageRange'
+ // (duplicates and any order allowed!)
+ std::vector< sal_Int32 > aPagesToPrint;
+ StringRangeEnumerator::getRangesFromString(
+ aPageRange, aPagesToPrint, 1, nDocPageCount, 0 );
+
+ // now fill the vector for calculating the page pairs with the start frames
+ // from the above obtained vector
+ std::vector< const SwPageFrm * > aVec;
+ for ( i = 0; i < sal_Int32(aPagesToPrint.size()); ++i)
+ {
+ const sal_Int32 nPage = aPagesToPrint[i];
+ const SwPageFrm *pFrm = rValidStartFrms[ nPage ];
+ aVec.push_back( pFrm );
+ }
+
+ // just one page is special ...
+ if ( 1 == aVec.size() )
+ aVec.insert( aVec.begin() + 1, 0 ); // insert a second empty page
+ else
+ {
+ // now extend the number of pages to fit a multiple of 4
+ // (4 'normal' pages are needed for a single prospect paper
+ // with back and front)
+ while( aVec.size() & 3 )
+ aVec.push_back( 0 );
+ }
+
+ // dann sorge mal dafuer, das alle Seiten in der richtigen
+ // Reihenfolge stehen:
+ sal_uInt16 nSPg = 0, nEPg = aVec.size(), nStep = 1;
+ if ( 0 == (nEPg & 1 )) // ungerade gibt es nicht!
+ --nEPg;
+
+ if ( !bPrintLeftPages )
+ ++nStep;
+ else if ( !bPrintRightPages )
+ {
+ ++nStep;
+ ++nSPg, --nEPg;
+ }
+
+ // the number of 'virtual' pages to be printed
+ sal_Int32 nCntPage = (( nEPg - nSPg ) / ( 2 * nStep )) + 1;
+
+ for ( sal_uInt16 nPrintCount = 0; nSPg < nEPg &&
+ nPrintCount < nCntPage; ++nPrintCount )
+ {
+ pStPage = aVec[ nSPg ];
+ const SwPageFrm* pNxtPage = nEPg < aVec.size() ? aVec[ nEPg ] : 0;
+
+ short nRtlOfs = bPrintProspectRTL ? 1 : 0;
+ if ( 0 == (( nSPg + nRtlOfs) & 1 ) ) // switch for odd number in LTR, even number in RTL
+ {
+ const SwPageFrm* pTmp = pStPage;
+ pStPage = pNxtPage;
+ pNxtPage = pTmp;
+ }
+
+ sal_Int32 nFirst = -1, nSecond = -1;
+ for ( int nC = 0; nC < 2; ++nC )
+ {
+ sal_Int32 nPage = -1;
+ if ( pStPage )
+ nPage = pStPage->GetPhyPageNum();
+ if (nC == 0)
+ nFirst = nPage;
+ else
+ nSecond = nPage;
+
+ pStPage = pNxtPage;
+ }
+ rPagePairs.push_back( std::pair< sal_Int32, sal_Int32 >(nFirst, nSecond) );
+
+ nSPg = nSPg + nStep;
+ nEPg = nEPg - nStep;
+ }
+ DBG_ASSERT( size_t(nCntPage) == rPagePairs.size(), "size mismatch for number of page pairs" );
+
+ // luckily prospect printing does not make use of post-its so far,
+ // thus we are done here.
+}
+
+/*************************************************************************
+ * void UpdateDocStat( const SwDocStat& rStat );
+ *************************************************************************/
+void SwDoc::UpdateDocStat( SwDocStat& rStat )
+{
+ if( rStat.bModified )
+ {
+ rStat.Reset();
+ rStat.nPara = 0; // Default ist auf 1 !!
+ SwNode* pNd;
+
+ for( sal_uLong i = GetNodes().Count(); i; )
+ {
+ switch( ( pNd = GetNodes()[ --i ])->GetNodeType() )
+ {
+ case ND_TEXTNODE:
+ ((SwTxtNode*)pNd)->CountWords( rStat, 0, ((SwTxtNode*)pNd)->GetTxt().Len() );
+ break;
+ case ND_TABLENODE: ++rStat.nTbl; break;
+ case ND_GRFNODE: ++rStat.nGrf; break;
+ case ND_OLENODE: ++rStat.nOLE; break;
+ case ND_SECTIONNODE: break;
+ }
+ }
+
+ // #i93174#: notes contain paragraphs that are not nodes
+ {
+ SwFieldType * const pPostits( GetSysFldType(RES_POSTITFLD) );
+ SwIterator<SwFmtFld,SwFieldType> aIter( *pPostits );
+ for( SwFmtFld* pFmtFld = aIter.First(); pFmtFld; pFmtFld = aIter.Next() )
+ {
+ if (pFmtFld->IsFldInDoc())
+ {
+ SwPostItField const * const pField(
+ static_cast<SwPostItField const*>(pFmtFld->GetFld()));
+ rStat.nAllPara += pField->GetNumberOfParagraphs();
+ }
+ }
+ }
+
+ rStat.nPage = GetCurrentLayout() ? GetCurrentLayout()->GetPageNum() : 0; //swmod 080218
+ rStat.bModified = sal_False;
+ SetDocStat( rStat );
+
+ com::sun::star::uno::Sequence < com::sun::star::beans::NamedValue > aStat( rStat.nPage ? 8 : 7);
+ sal_Int32 n=0;
+ aStat[n].Name = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("TableCount"));
+ aStat[n++].Value <<= (sal_Int32)rStat.nTbl;
+ aStat[n].Name = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("ImageCount"));
+ aStat[n++].Value <<= (sal_Int32)rStat.nGrf;
+ aStat[n].Name = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("ObjectCount"));
+ aStat[n++].Value <<= (sal_Int32)rStat.nOLE;
+ if ( rStat.nPage )
+ {
+ aStat[n].Name = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("PageCount"));
+ aStat[n++].Value <<= (sal_Int32)rStat.nPage;
+ }
+ aStat[n].Name = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("ParagraphCount"));
+ aStat[n++].Value <<= (sal_Int32)rStat.nPara;
+ aStat[n].Name = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("WordCount"));
+ aStat[n++].Value <<= (sal_Int32)rStat.nWord;
+ aStat[n].Name = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("CharacterCount"));
+ aStat[n++].Value <<= (sal_Int32)rStat.nChar;
+ aStat[n].Name = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("NonWhitespaceCharacterCount"));
+ aStat[n++].Value <<= (sal_Int32)rStat.nCharExcludingSpaces;
+
+ // For e.g. autotext documents there is no pSwgInfo (#i79945)
+ SfxObjectShell * const pObjShell( GetDocShell() );
+ if (pObjShell)
+ {
+ const uno::Reference<document::XDocumentPropertiesSupplier> xDPS(
+ pObjShell->GetModel(), uno::UNO_QUERY_THROW);
+ const uno::Reference<document::XDocumentProperties> xDocProps(
+ xDPS->getDocumentProperties());
+ // #i96786#: do not set modified flag when updating statistics
+ const bool bDocWasModified( IsModified() );
+ const ModifyBlocker_Impl b(pObjShell);
+ xDocProps->setDocumentStatistics(aStat);
+ if (!bDocWasModified)
+ {
+ ResetModified();
+ }
+ }
+
+ // event. Stat. Felder Updaten
+ SwFieldType *pType = GetSysFldType(RES_DOCSTATFLD);
+ pType->UpdateFlds();
+ }
+}
+
+// Dokument - Info
+void SwDoc::DocInfoChgd( )
+{
+ GetSysFldType( RES_DOCINFOFLD )->UpdateFlds();
+ GetSysFldType( RES_TEMPLNAMEFLD )->UpdateFlds();
+ SetModified();
+}
+
+// returne zum Namen die im Doc gesetzte Referenz
+const SwFmtRefMark* SwDoc::GetRefMark( const String& rName ) const
+{
+ const SfxPoolItem* pItem;
+ sal_uInt32 nMaxItems = GetAttrPool().GetItemCount2( RES_TXTATR_REFMARK );
+ for( sal_uInt32 n = 0; n < nMaxItems; ++n )
+ {
+ if( 0 == (pItem = GetAttrPool().GetItem2( RES_TXTATR_REFMARK, n ) ))
+ continue;
+
+ const SwFmtRefMark* pFmtRef = (SwFmtRefMark*)pItem;
+ const SwTxtRefMark* pTxtRef = pFmtRef->GetTxtRefMark();
+ if( pTxtRef && &pTxtRef->GetTxtNode().GetNodes() == &GetNodes() &&
+ rName.Equals( pFmtRef->GetRefName() ) )
+ return pFmtRef;
+ }
+ return 0;
+}
+
+// returne die RefMark per Index - fuer Uno
+const SwFmtRefMark* SwDoc::GetRefMark( sal_uInt16 nIndex ) const
+{
+ const SfxPoolItem* pItem;
+ const SwTxtRefMark* pTxtRef;
+ const SwFmtRefMark* pRet = 0;
+
+ sal_uInt32 nMaxItems = GetAttrPool().GetItemCount2( RES_TXTATR_REFMARK );
+ sal_uInt32 nCount = 0;
+ for( sal_uInt32 n = 0; n < nMaxItems; ++n )
+ if( 0 != (pItem = GetAttrPool().GetItem2( RES_TXTATR_REFMARK, n )) &&
+ 0 != (pTxtRef = ((SwFmtRefMark*)pItem)->GetTxtRefMark()) &&
+ &pTxtRef->GetTxtNode().GetNodes() == &GetNodes() )
+ {
+ if(nCount == nIndex)
+ {
+ pRet = (SwFmtRefMark*)pItem;
+ break;
+ }
+ nCount++;
+ }
+ return pRet;
+}
+
+// returne die Namen aller im Doc gesetzten Referenzen
+//JP 24.06.96: Ist der ArrayPointer 0 dann returne nur, ob im Doc. eine
+// RefMark gesetzt ist
+// OS 25.06.96: ab jetzt wird immer die Anzahl der Referenzen returnt
+sal_uInt16 SwDoc::GetRefMarks( SvStringsDtor* pNames ) const
+{
+ const SfxPoolItem* pItem;
+ const SwTxtRefMark* pTxtRef;
+
+ sal_uInt32 nMaxItems = GetAttrPool().GetItemCount2( RES_TXTATR_REFMARK );
+ sal_uInt32 nCount = 0;
+ for( sal_uInt32 n = 0; n < nMaxItems; ++n )
+ if( 0 != (pItem = GetAttrPool().GetItem2( RES_TXTATR_REFMARK, n )) &&
+ 0 != (pTxtRef = ((SwFmtRefMark*)pItem)->GetTxtRefMark()) &&
+ &pTxtRef->GetTxtNode().GetNodes() == &GetNodes() )
+ {
+ if( pNames )
+ {
+ String* pTmp = new String( ((SwFmtRefMark*)pItem)->GetRefName() );
+ pNames->Insert( pTmp, nCount );
+ }
+ nCount ++;
+ }
+
+ return nCount;
+}
+
+bool SwDoc::IsLoaded() const
+{
+ return mbLoaded;
+}
+
+bool SwDoc::IsUpdateExpFld() const
+{
+ return mbUpdateExpFld;
+}
+
+bool SwDoc::IsNewDoc() const
+{
+ return mbNewDoc;
+}
+
+bool SwDoc::IsPageNums() const
+{
+ return mbPageNums;
+}
+
+void SwDoc::SetPageNums(bool b)
+{
+ mbPageNums = b;
+}
+
+void SwDoc::SetNewDoc(bool b)
+{
+ mbNewDoc = b;
+}
+
+void SwDoc::SetUpdateExpFldStat(bool b)
+{
+ mbUpdateExpFld = b;
+}
+
+void SwDoc::SetLoaded(bool b)
+{
+ mbLoaded = b;
+}
+
+bool SwDoc::IsModified() const
+{
+ return mbModified;
+}
+
+void SwDoc::SetModified()
+{
+ SwLayouter::ClearMovedFwdFrms( *this );
+ SwLayouter::ClearObjsTmpConsiderWrapInfluence( *this );
+ SwLayouter::ClearFrmsNotToWrap( *this );
+ // #i65250#
+ SwLayouter::ClearMoveBwdLayoutInfo( *this );
+ // dem Link wird der Status returnt, wie die Flags waren und werden
+ // Bit 0: -> alter Zustand
+ // Bit 1: -> neuer Zustand
+ long nCall = mbModified ? 3 : 2;
+ mbModified = sal_True;
+ pDocStat->bModified = sal_True;
+ if( aOle2Link.IsSet() )
+ {
+ mbInCallModified = sal_True;
+ aOle2Link.Call( (void*)nCall );
+ mbInCallModified = sal_False;
+ }
+
+ if( pACEWord && !pACEWord->IsDeleted() )
+ delete pACEWord, pACEWord = 0;
+}
+
+void SwDoc::ResetModified()
+{
+ // dem Link wird der Status returnt, wie die Flags waren und werden
+ // Bit 0: -> alter Zustand
+ // Bit 1: -> neuer Zustand
+ long nCall = mbModified ? 1 : 0;
+ mbModified = sal_False;
+ // If there is already a document statistic, we assume that
+ // it is correct. In this case we reset the modified flag.
+ if ( 0 != pDocStat->nChar )
+ pDocStat->bModified = sal_False;
+ GetIDocumentUndoRedo().SetUndoNoModifiedPosition();
+ if( nCall && aOle2Link.IsSet() )
+ {
+ mbInCallModified = sal_True;
+ aOle2Link.Call( (void*)nCall );
+ mbInCallModified = sal_False;
+ }
+}
+
+void SwDoc::ReRead( SwPaM& rPam, const String& rGrfName,
+ const String& rFltName, const Graphic* pGraphic,
+ const GraphicObject* pGrafObj )
+{
+ SwGrfNode *pGrfNd;
+ if( ( !rPam.HasMark()
+ || rPam.GetPoint()->nNode.GetIndex() == rPam.GetMark()->nNode.GetIndex() )
+ && 0 != ( pGrfNd = rPam.GetPoint()->nNode.GetNode().GetGrfNode() ) )
+ {
+ if (GetIDocumentUndoRedo().DoesUndo())
+ {
+ GetIDocumentUndoRedo().AppendUndo(new SwUndoReRead(rPam, *pGrfNd));
+ }
+
+ // Weil nicht bekannt ist, ob sich die Grafik spiegeln laesst,
+ // immer das SpiegelungsAttribut zuruecksetzen
+ if( RES_MIRROR_GRAPH_DONT != pGrfNd->GetSwAttrSet().
+ GetMirrorGrf().GetValue() )
+ pGrfNd->SetAttr( SwMirrorGrf() );
+
+ pGrfNd->ReRead( rGrfName, rFltName, pGraphic, pGrafObj, sal_True );
+ SetModified();
+ }
+}
+
+sal_Bool lcl_SpellAndGrammarAgain( const SwNodePtr& rpNd, void* pArgs )
+{
+ SwTxtNode *pTxtNode = (SwTxtNode*)rpNd->GetTxtNode();
+ sal_Bool bOnlyWrong = *(sal_Bool*)pArgs;
+ if( pTxtNode )
+ {
+ if( bOnlyWrong )
+ {
+ if( pTxtNode->GetWrong() &&
+ pTxtNode->GetWrong()->InvalidateWrong() )
+ pTxtNode->SetWrongDirty( true );
+ if( pTxtNode->GetGrammarCheck() &&
+ pTxtNode->GetGrammarCheck()->InvalidateWrong() )
+ pTxtNode->SetGrammarCheckDirty( true );
+ }
+ else
+ {
+ pTxtNode->SetWrongDirty( true );
+ if( pTxtNode->GetWrong() )
+ pTxtNode->GetWrong()->SetInvalid( 0, STRING_LEN );
+ pTxtNode->SetGrammarCheckDirty( true );
+ if( pTxtNode->GetGrammarCheck() )
+ pTxtNode->GetGrammarCheck()->SetInvalid( 0, STRING_LEN );
+ }
+ }
+ return sal_True;
+}
+
+sal_Bool lcl_CheckSmartTagsAgain( const SwNodePtr& rpNd, void* )
+{
+ SwTxtNode *pTxtNode = (SwTxtNode*)rpNd->GetTxtNode();
+// sal_Bool bOnlyWrong = *(sal_Bool*)pArgs;
+ if( pTxtNode )
+ {
+ pTxtNode->SetSmartTagDirty( true );
+ if( pTxtNode->GetSmartTags() )
+ {
+// if ( bOnlyWrong ) // only some smart tag types have been enabled or disabled
+// pTxtNode->GetSmartTags()->SetInvalid( 0, STRING_LEN );
+// else // smart tags all have been enabled or disabled
+ pTxtNode->SetSmartTags( NULL );
+ }
+ }
+ return sal_True;
+}
+
+/*************************************************************************
+ * SwDoc::SpellItAgainSam( sal_Bool bInvalid, sal_Bool bOnlyWrong )
+ *
+ * stoesst das Spelling im Idle-Handler wieder an.
+ * Wird bInvalid als sal_True uebergeben, so werden zusaetzlich die WrongListen
+ * an allen Nodes invalidiert und auf allen Seiten das SpellInvalid-Flag
+ * gesetzt.
+ * Mit bOnlyWrong kann man dann steuern, ob nur die Bereiche mit falschen
+ * Woertern oder die kompletten Bereiche neu ueberprueft werden muessen.
+ ************************************************************************/
+void SwDoc::SpellItAgainSam( sal_Bool bInvalid, sal_Bool bOnlyWrong, sal_Bool bSmartTags )
+{
+ std::set<SwRootFrm*> aAllLayouts = GetAllLayouts();//swmod 080307
+ OSL_ENSURE( GetCurrentLayout(), "SpellAgain: Where's my RootFrm?" );
+ if( bInvalid )
+ {
+ std::for_each( aAllLayouts.begin(), aAllLayouts.end(),std::bind2nd(std::mem_fun(&SwRootFrm::AllInvalidateSmartTagsOrSpelling),bSmartTags));//swmod 080305
+ std::for_each( aAllLayouts.begin(), aAllLayouts.end(),std::bind2nd(std::mem_fun(&SwRootFrm::SetNeedGrammarCheck), true) );
+ if ( bSmartTags )
+ GetNodes().ForEach( lcl_CheckSmartTagsAgain, &bOnlyWrong );
+ GetNodes().ForEach( lcl_SpellAndGrammarAgain, &bOnlyWrong );
+ }
+
+ std::for_each( aAllLayouts.begin(), aAllLayouts.end(),std::mem_fun(&SwRootFrm::SetIdleFlags));//swmod 080307
+}
+
+void SwDoc::InvalidateAutoCompleteFlag()
+{
+ SwRootFrm* pTmpRoot = GetCurrentLayout();
+ if( pTmpRoot )
+ {
+ std::set<SwRootFrm*> aAllLayouts = GetAllLayouts();
+ std::for_each( aAllLayouts.begin(), aAllLayouts.end(),std::mem_fun(&SwRootFrm::AllInvalidateAutoCompleteWords));//swmod 080305
+ for( sal_uLong nNd = 1, nCnt = GetNodes().Count(); nNd < nCnt; ++nNd )
+ {
+ SwTxtNode* pTxtNode = GetNodes()[ nNd ]->GetTxtNode();
+ if ( pTxtNode ) pTxtNode->SetAutoCompleteWordDirty( true );
+ }
+
+ std::for_each( aAllLayouts.begin(), aAllLayouts.end(),std::mem_fun(&SwRootFrm::SetIdleFlags));//swmod 080228
+ } //swmod 080219
+}
+
+const SwFmtINetFmt* SwDoc::FindINetAttr( const String& rName ) const
+{
+ const SwFmtINetFmt* pItem;
+ const SwTxtINetFmt* pTxtAttr;
+ const SwTxtNode* pTxtNd;
+ sal_uInt32 n, nMaxItems = GetAttrPool().GetItemCount2( RES_TXTATR_INETFMT );
+ for( n = 0; n < nMaxItems; ++n )
+ if( 0 != (pItem = (SwFmtINetFmt*)GetAttrPool().GetItem2(
+ RES_TXTATR_INETFMT, n ) ) &&
+ pItem->GetName().Equals( rName ) &&
+ 0 != ( pTxtAttr = pItem->GetTxtINetFmt()) &&
+ 0 != ( pTxtNd = pTxtAttr->GetpTxtNode() ) &&
+ &pTxtNd->GetNodes() == &GetNodes() )
+ {
+ return pItem;
+ }
+
+ return 0;
+}
+
+void SwDoc::Summary( SwDoc* pExtDoc, sal_uInt8 nLevel, sal_uInt8 nPara, sal_Bool bImpress )
+{
+ const SwOutlineNodes& rOutNds = GetNodes().GetOutLineNds();
+ if( pExtDoc && rOutNds.Count() )
+ {
+ sal_uInt16 i;
+ ::StartProgress( STR_STATSTR_SUMMARY, 0, rOutNds.Count(), GetDocShell() );
+ SwNodeIndex aEndOfDoc( pExtDoc->GetNodes().GetEndOfContent(), -1 );
+ for( i = 0; i < rOutNds.Count(); ++i )
+ {
+ ::SetProgressState( i, GetDocShell() );
+ const sal_uLong nIndex = rOutNds[ i ]->GetIndex();
+
+ const int nLvl = ((SwTxtNode*)GetNodes()[ nIndex ])->GetAttrOutlineLevel()-1;//<-end,zhaojianwei
+ if( nLvl > nLevel )
+ continue;
+ sal_uInt16 nEndOfs = 1;
+ sal_uInt8 nWish = nPara;
+ sal_uLong nNextOutNd = i + 1 < rOutNds.Count() ?
+ rOutNds[ i + 1 ]->GetIndex() : GetNodes().Count();
+ sal_Bool bKeep = sal_False;
+ while( ( nWish || bKeep ) && nIndex + nEndOfs < nNextOutNd &&
+ GetNodes()[ nIndex + nEndOfs ]->IsTxtNode() )
+ {
+ SwTxtNode* pTxtNode = (SwTxtNode*)GetNodes()[ nIndex+nEndOfs ];
+ if( pTxtNode->GetTxt().Len() && nWish )
+ --nWish;
+ bKeep = pTxtNode->GetSwAttrSet().GetKeep().GetValue();
+ ++nEndOfs;
+ }
+
+ SwNodeRange aRange( *rOutNds[ i ], 0, *rOutNds[ i ], nEndOfs );
+ GetNodes()._Copy( aRange, aEndOfDoc );
+ }
+ const SwTxtFmtColls *pColl = pExtDoc->GetTxtFmtColls();
+ for( i = 0; i < pColl->Count(); ++i )
+ (*pColl)[ i ]->ResetFmtAttr( RES_PAGEDESC, RES_BREAK );
+ SwNodeIndex aIndx( pExtDoc->GetNodes().GetEndOfExtras() );
+ ++aEndOfDoc;
+ while( aIndx < aEndOfDoc )
+ {
+ SwNode *pNode;
+ sal_Bool bDelete = sal_False;
+ if( (pNode = &aIndx.GetNode())->IsTxtNode() )
+ {
+ SwTxtNode *pNd = (SwTxtNode*)pNode;
+ if( pNd->HasSwAttrSet() )
+ pNd->ResetAttr( RES_PAGEDESC, RES_BREAK );
+ if( bImpress )
+ {
+ SwTxtFmtColl* pMyColl = pNd->GetTxtColl();
+
+ const sal_uInt16 nHeadLine = static_cast<sal_uInt16>(
+ !pMyColl->IsAssignedToListLevelOfOutlineStyle() //<-end,zhaojianwei
+ ? RES_POOLCOLL_HEADLINE2
+ : RES_POOLCOLL_HEADLINE1 );
+ pMyColl = pExtDoc->GetTxtCollFromPool( nHeadLine );
+ pNd->ChgFmtColl( pMyColl );
+ }
+ if( !pNd->Len() &&
+ pNd->StartOfSectionIndex()+2 < pNd->EndOfSectionIndex() )
+ {
+ bDelete = sal_True;
+ pExtDoc->GetNodes().Delete( aIndx );
+ }
+ }
+ if( !bDelete )
+ ++aIndx;
+ }
+ ::EndProgress( GetDocShell() );
+ }
+}
+
+// loesche den nicht sichtbaren Content aus dem Document, wie z.B.:
+// versteckte Bereiche, versteckte Absaetze
+bool SwDoc::RemoveInvisibleContent()
+{
+ sal_Bool bRet = sal_False;
+ GetIDocumentUndoRedo().StartUndo( UNDO_UI_DELETE_INVISIBLECNTNT, NULL );
+
+ {
+ SwTxtNode* pTxtNd;
+ SwIterator<SwFmtFld,SwFieldType> aIter( *GetSysFldType( RES_HIDDENPARAFLD ) );
+ for( SwFmtFld* pFmtFld = aIter.First(); pFmtFld; pFmtFld = aIter.Next() )
+ {
+ if( pFmtFld->GetTxtFld() &&
+ 0 != ( pTxtNd = (SwTxtNode*)pFmtFld->GetTxtFld()->GetpTxtNode() ) &&
+ pTxtNd->GetpSwpHints() && pTxtNd->HasHiddenParaField() &&
+ &pTxtNd->GetNodes() == &GetNodes() )
+ {
+ bRet = sal_True;
+ SwPaM aPam( *pTxtNd, 0, *pTxtNd, pTxtNd->GetTxt().Len() );
+
+ // Remove hidden paragraph or delete contents:
+ // Delete contents if
+ // 1. removing the paragraph would result in an empty section or
+ // 2. if the paragraph is the last paragraph in the section and
+ // there is no paragraph in front of the paragraph:
+ if ( ( 2 == pTxtNd->EndOfSectionIndex() - pTxtNd->StartOfSectionIndex() ) ||
+ ( 1 == pTxtNd->EndOfSectionIndex() - pTxtNd->GetIndex() &&
+ !GetNodes()[ pTxtNd->GetIndex() - 1 ]->GetTxtNode() ) )
+ {
+ DeleteRange( aPam );
+ }
+ else
+ {
+ aPam.DeleteMark();
+ DelFullPara( aPam );
+ }
+ }
+ }
+ }
+
+ //
+ // Remove any hidden paragraph (hidden text attribute)
+ //
+ for( sal_uLong n = GetNodes().Count(); n; )
+ {
+ SwTxtNode* pTxtNd = GetNodes()[ --n ]->GetTxtNode();
+ if ( pTxtNd )
+ {
+ bool bRemoved = false;
+ SwPaM aPam( *pTxtNd, 0, *pTxtNd, pTxtNd->GetTxt().Len() );
+ if ( pTxtNd->HasHiddenCharAttribute( true ) )
+ {
+ bRemoved = sal_True;
+ bRet = sal_True;
+
+ // Remove hidden paragraph or delete contents:
+ // Delete contents if
+ // 1. removing the paragraph would result in an empty section or
+ // 2. if the paragraph is the last paragraph in the section and
+ // there is no paragraph in front of the paragraph:
+
+ if ( ( 2 == pTxtNd->EndOfSectionIndex() - pTxtNd->StartOfSectionIndex() ) ||
+ ( 1 == pTxtNd->EndOfSectionIndex() - pTxtNd->GetIndex() &&
+ !GetNodes()[ pTxtNd->GetIndex() - 1 ]->GetTxtNode() ) )
+ {
+ DeleteRange( aPam );
+ }
+ else
+ {
+ aPam.DeleteMark();
+ DelFullPara( aPam );
+ }
+ }
+ else if ( pTxtNd->HasHiddenCharAttribute( false ) )
+ {
+ bRemoved = sal_True;
+ bRet = sal_True;
+ SwScriptInfo::DeleteHiddenRanges( *pTxtNd );
+ }
+
+ // Footnotes/Frames may have been removed, therefore we have
+ // to reset n:
+ if ( bRemoved )
+ n = aPam.GetPoint()->nNode.GetIndex();
+ }
+ }
+
+ {
+ // dann noch alle versteckten Bereiche loeschen/leeren
+ SwSectionFmts aSectFmts;
+ SwSectionFmts& rSectFmts = GetSections();
+ sal_uInt16 n;
+
+ for( n = rSectFmts.Count(); n; )
+ {
+ SwSectionFmt* pSectFmt = rSectFmts[ --n ];
+ // don't add sections in Undo/Redo
+ if( !pSectFmt->IsInNodesArr())
+ continue;
+ SwSection* pSect = pSectFmt->GetSection();
+ if( pSect->CalcHiddenFlag() )
+ {
+ SwSection* pParent = pSect, *pTmp;
+ while( 0 != (pTmp = pParent->GetParent() ))
+ {
+ if( pTmp->IsHiddenFlag() )
+ pSect = pTmp;
+ pParent = pTmp;
+ }
+
+ if( USHRT_MAX == aSectFmts.GetPos( pSect->GetFmt() ) )
+ aSectFmts.Insert( pSect->GetFmt(), 0 );
+ }
+ if( pSect->GetCondition().Len() )
+ {
+ SwSectionData aSectionData( *pSect );
+ aSectionData.SetCondition( aEmptyStr );
+ aSectionData.SetHidden( false );
+ UpdateSection( n, aSectionData );
+ }
+ }
+
+ if( 0 != ( n = aSectFmts.Count() ))
+ {
+ while( n )
+ {
+ SwSectionFmt* pSectFmt = aSectFmts[ --n ];
+ SwSectionNode* pSectNd = pSectFmt->GetSectionNode();
+ if( pSectNd )
+ {
+ bRet = sal_True;
+ SwPaM aPam( *pSectNd );
+
+ if( pSectNd->StartOfSectionNode()->StartOfSectionIndex() ==
+ pSectNd->GetIndex() - 1 &&
+ pSectNd->StartOfSectionNode()->EndOfSectionIndex() ==
+ pSectNd->EndOfSectionIndex() + 1 )
+ {
+ // nur den Inhalt loeschen
+ SwCntntNode* pCNd = GetNodes().GoNext(
+ &aPam.GetPoint()->nNode );
+ aPam.GetPoint()->nContent.Assign( pCNd, 0 );
+ aPam.SetMark();
+ aPam.GetPoint()->nNode = *pSectNd->EndOfSectionNode();
+ pCNd = GetNodes().GoPrevious(
+ &aPam.GetPoint()->nNode );
+ aPam.GetPoint()->nContent.Assign( pCNd, pCNd->Len() );
+
+ DeleteRange( aPam );
+ }
+ else
+ {
+ // die gesamte Section loeschen
+ aPam.SetMark();
+ aPam.GetPoint()->nNode = *pSectNd->EndOfSectionNode();
+ DelFullPara( aPam );
+ }
+
+ }
+ }
+ aSectFmts.Remove( 0, aSectFmts.Count() );
+ }
+ }
+
+ if( bRet )
+ SetModified();
+ GetIDocumentUndoRedo().EndUndo( UNDO_UI_DELETE_INVISIBLECNTNT, NULL );
+ return bRet;
+}
+/*-- 25.08.2010 14:18:12---------------------------------------------------
+
+ -----------------------------------------------------------------------*/
+bool SwDoc::HasInvisibleContent() const
+{
+ sal_Bool bRet = sal_False;
+
+ SwClientIter aIter( *GetSysFldType( RES_HIDDENPARAFLD ) );
+ if( aIter.First( TYPE( SwFmtFld ) ) )
+ bRet = sal_True;
+
+ //
+ // Search for any hidden paragraph (hidden text attribute)
+ //
+ if( ! bRet )
+ {
+ for( sal_uLong n = GetNodes().Count(); !bRet && (n > 0); )
+ {
+ SwTxtNode* pTxtNd = GetNodes()[ --n ]->GetTxtNode();
+ if ( pTxtNd )
+ {
+ SwPaM aPam( *pTxtNd, 0, *pTxtNd, pTxtNd->GetTxt().Len() );
+ if( pTxtNd->HasHiddenCharAttribute( true ) || ( pTxtNd->HasHiddenCharAttribute( false ) ) )
+ {
+ bRet = sal_True;
+ }
+ }
+ }
+ }
+
+ if( ! bRet )
+ {
+ const SwSectionFmts& rSectFmts = GetSections();
+ sal_uInt16 n;
+
+ for( n = rSectFmts.Count(); !bRet && (n > 0); )
+ {
+ SwSectionFmt* pSectFmt = rSectFmts[ --n ];
+ // don't add sections in Undo/Redo
+ if( !pSectFmt->IsInNodesArr())
+ continue;
+ SwSection* pSect = pSectFmt->GetSection();
+ if( pSect->IsHidden() )
+ bRet = sal_True;
+ }
+ }
+ return bRet;
+}
+
+bool SwDoc::RestoreInvisibleContent()
+{
+ bool bRet = false;
+ SwUndoId nLastUndoId(UNDO_EMPTY);
+ if (GetIDocumentUndoRedo().GetLastUndoInfo(0, & nLastUndoId)
+ && (UNDO_UI_DELETE_INVISIBLECNTNT == nLastUndoId))
+ {
+ GetIDocumentUndoRedo().Undo();
+ GetIDocumentUndoRedo().ClearRedo();
+ bRet = true;
+ }
+ return bRet;
+}
+
+
+sal_Bool SwDoc::ConvertFieldsToText()
+{
+ sal_Bool bRet = sal_False;
+ LockExpFlds();
+ GetIDocumentUndoRedo().StartUndo( UNDO_UI_REPLACE, NULL );
+
+ const SwFldTypes* pMyFldTypes = GetFldTypes();
+ sal_uInt16 nCount = pMyFldTypes->Count();
+ //go backward, field types are removed
+ for(sal_uInt16 nType = nCount; nType > 0; --nType)
+ {
+ const SwFieldType *pCurType = pMyFldTypes->GetObject(nType - 1);
+
+ if ( RES_POSTITFLD == pCurType->Which() )
+ continue;
+
+ SwIterator<SwFmtFld,SwFieldType> aIter( *pCurType );
+ ::std::vector<const SwFmtFld*> aFieldFmts;
+ for( SwFmtFld* pCurFldFmt = aIter.First(); pCurFldFmt; pCurFldFmt = aIter.Next() )
+ aFieldFmts.push_back(pCurFldFmt);
+
+ ::std::vector<const SwFmtFld*>::iterator aBegin = aFieldFmts.begin();
+ ::std::vector<const SwFmtFld*>::iterator aEnd = aFieldFmts.end();
+ while(aBegin != aEnd)
+ {
+ const SwTxtFld *pTxtFld = (*aBegin)->GetTxtFld();
+ // skip fields that are currently not in the document
+ // e.g. fields in undo or redo array
+
+ sal_Bool bSkip = !pTxtFld ||
+ !pTxtFld->GetpTxtNode()->GetNodes().IsDocNodes();
+
+ if (!bSkip)
+ {
+ sal_Bool bInHeaderFooter = IsInHeaderFooter(SwNodeIndex(*pTxtFld->GetpTxtNode()));
+ const SwFmtFld& rFmtFld = pTxtFld->GetFld();
+ const SwField* pField = rFmtFld.GetFld();
+
+ //#i55595# some fields have to be excluded in headers/footers
+ sal_uInt16 nWhich = pField->GetTyp()->Which();
+ if(!bInHeaderFooter ||
+ (nWhich != RES_PAGENUMBERFLD &&
+ nWhich != RES_CHAPTERFLD &&
+ nWhich != RES_GETEXPFLD&&
+ nWhich != RES_SETEXPFLD&&
+ nWhich != RES_INPUTFLD&&
+ nWhich != RES_REFPAGEGETFLD&&
+ nWhich != RES_REFPAGESETFLD))
+ {
+ String sText = pField->ExpandField(true);
+ //database fields should not convert their command into text
+ if( RES_DBFLD == pCurType->Which() && !static_cast<const SwDBField*>(pField)->IsInitialized())
+ sText.Erase();
+
+ //now remove the field and insert the string
+ SwPaM aPam1(*pTxtFld->GetpTxtNode(), *pTxtFld->GetStart());
+ aPam1.Move();
+ //insert first to keep the field's attributes
+ InsertString( aPam1, sText );
+ SwPaM aPam2(*pTxtFld->GetpTxtNode(), *pTxtFld->GetStart());
+ aPam2.SetMark();
+ aPam2.Move();
+ DeleteAndJoin(aPam2);//remove the field
+ }
+ }
+ ++aBegin;
+ }
+ }
+
+ if( bRet )
+ SetModified();
+ GetIDocumentUndoRedo().EndUndo( UNDO_UI_REPLACE, NULL );
+ UnlockExpFlds();
+ return bRet;
+
+}
+
+bool SwDoc::IsVisibleLinks() const
+{
+ return mbVisibleLinks;
+}
+
+void SwDoc::SetVisibleLinks(bool bFlag)
+{
+ mbVisibleLinks = bFlag;
+}
+
+sfx2::LinkManager& SwDoc::GetLinkManager()
+{
+ return *pLinkMgr;
+}
+
+const sfx2::LinkManager& SwDoc::GetLinkManager() const
+{
+ return *pLinkMgr;
+}
+
+void SwDoc::SetLinksUpdated(const bool bNewLinksUpdated)
+{
+ mbLinksUpdated = bNewLinksUpdated;
+}
+
+bool SwDoc::LinksUpdated() const
+{
+ return mbLinksUpdated;
+}
+
+// embedded alle lokalen Links (Bereiche/Grafiken)
+::sfx2::SvBaseLink* lcl_FindNextRemovableLink( const ::sfx2::SvBaseLinks& rLinks, sfx2::LinkManager& rLnkMgr )
+{
+ for( sal_uInt16 n = 0; n < rLinks.Count(); ++n )
+ {
+ ::sfx2::SvBaseLink* pLnk = &(*rLinks[ n ]);
+ if( pLnk &&
+ ( OBJECT_CLIENT_GRF == pLnk->GetObjType() ||
+ OBJECT_CLIENT_FILE == pLnk->GetObjType() ) &&
+ pLnk->ISA( SwBaseLink ) )
+ {
+ ::sfx2::SvBaseLinkRef xLink = pLnk;
+
+ String sFName;
+ rLnkMgr.GetDisplayNames( xLink, 0, &sFName, 0, 0 );
+
+ INetURLObject aURL( sFName );
+ if( INET_PROT_FILE == aURL.GetProtocol() ||
+ INET_PROT_CID == aURL.GetProtocol() )
+ return pLnk;
+ }
+ }
+ return 0;
+}
+bool SwDoc::EmbedAllLinks()
+{
+ sal_Bool bRet = sal_False;
+ sfx2::LinkManager& rLnkMgr = GetLinkManager();
+ const ::sfx2::SvBaseLinks& rLinks = rLnkMgr.GetLinks();
+ if( rLinks.Count() )
+ {
+ ::sw::UndoGuard const undoGuard(GetIDocumentUndoRedo());
+
+ ::sfx2::SvBaseLink* pLnk = 0;
+ while( 0 != (pLnk = lcl_FindNextRemovableLink( rLinks, rLnkMgr ) ) )
+ {
+ ::sfx2::SvBaseLinkRef xLink = pLnk;
+ // dem Link sagen, das er aufgeloest wird!
+ xLink->Closed();
+
+ // falls einer vergessen hat sich auszutragen
+ if( xLink.Is() )
+ rLnkMgr.Remove( xLink );
+
+ bRet = sal_True;
+ }
+
+ GetIDocumentUndoRedo().DelAllUndoObj();
+ SetModified();
+ }
+ return bRet;
+}
+
+sal_Bool SwDoc::IsInsTblFormatNum() const
+{
+ return SW_MOD()->IsInsTblFormatNum(get(IDocumentSettingAccess::HTML_MODE));
+}
+
+sal_Bool SwDoc::IsInsTblChangeNumFormat() const
+{
+ return SW_MOD()->IsInsTblChangeNumFormat(get(IDocumentSettingAccess::HTML_MODE));
+}
+
+sal_Bool SwDoc::IsInsTblAlignNum() const
+{
+ return SW_MOD()->IsInsTblAlignNum(get(IDocumentSettingAccess::HTML_MODE));
+}
+
+// setze das InsertDB als Tabelle Undo auf:
+void SwDoc::AppendUndoForInsertFromDB( const SwPaM& rPam, sal_Bool bIsTable )
+{
+ if( bIsTable )
+ {
+ const SwTableNode* pTblNd = rPam.GetPoint()->nNode.GetNode().FindTableNode();
+ if( pTblNd )
+ {
+ SwUndoCpyTbl* pUndo = new SwUndoCpyTbl;
+ pUndo->SetTableSttIdx( pTblNd->GetIndex() );
+ GetIDocumentUndoRedo().AppendUndo( pUndo );
+ }
+ }
+ else if( rPam.HasMark() )
+ {
+ SwUndoCpyDoc* pUndo = new SwUndoCpyDoc( rPam );
+ pUndo->SetInsertRange( rPam, sal_False );
+ GetIDocumentUndoRedo().AppendUndo( pUndo );
+ }
+}
+
+void SwDoc::ChgTOX(SwTOXBase & rTOX, const SwTOXBase & rNew)
+{
+ if (GetIDocumentUndoRedo().DoesUndo())
+ {
+ GetIDocumentUndoRedo().DelAllUndoObj();
+
+ SwUndo * pUndo = new SwUndoTOXChange(&rTOX, rNew);
+
+ GetIDocumentUndoRedo().AppendUndo(pUndo);
+ }
+
+ rTOX = rNew;
+
+ if (rTOX.ISA(SwTOXBaseSection))
+ {
+ static_cast<SwTOXBaseSection &>(rTOX).Update();
+ static_cast<SwTOXBaseSection &>(rTOX).UpdatePageNum();
+ }
+}
+
+String SwDoc::GetPaMDescr(const SwPaM & rPam) const
+{
+ String aResult;
+ bool bOK = false;
+
+ if (rPam.GetNode(sal_True) == rPam.GetNode(sal_False))
+ {
+ SwTxtNode * pTxtNode = rPam.GetNode(sal_True)->GetTxtNode();
+
+ if (0 != pTxtNode)
+ {
+ xub_StrLen nStart = rPam.Start()->nContent.GetIndex();
+ xub_StrLen nEnd = rPam.End()->nContent.GetIndex();
+
+ aResult += String(SW_RES(STR_START_QUOTE));
+ aResult += ShortenString(pTxtNode->GetTxt().
+ Copy(nStart, nEnd - nStart),
+ nUndoStringLength,
+ String(SW_RES(STR_LDOTS)));
+ aResult += String(SW_RES(STR_END_QUOTE));
+
+ bOK = true;
+ }
+ }
+ else if (0 != rPam.GetNode(sal_True))
+ {
+ if (0 != rPam.GetNode(sal_False))
+ aResult += String(SW_RES(STR_PARAGRAPHS));
+
+ bOK = true;
+ }
+
+ if (! bOK)
+ aResult += String("??", RTL_TEXTENCODING_ASCII_US);
+
+ return aResult;
+}
+
+SwField * SwDoc::GetField(const SwPosition & rPos)
+{
+ SwTxtFld * const pAttr = GetTxtFld(rPos);
+
+ return (pAttr) ? const_cast<SwField *>( pAttr->GetFld().GetFld() ) : 0;
+}
+
+SwTxtFld * SwDoc::GetTxtFld(const SwPosition & rPos)
+{
+ SwTxtNode * const pNode = rPos.nNode.GetNode().GetTxtNode();
+
+ return (pNode)
+ ? static_cast<SwTxtFld*>( pNode->GetTxtAttrForCharAt(
+ rPos.nContent.GetIndex(), RES_TXTATR_FIELD) )
+ : 0;
+}
+
+bool SwDoc::ContainsHiddenChars() const
+{
+ for( sal_uLong n = GetNodes().Count(); n; )
+ {
+ SwNode* pNd = GetNodes()[ --n ];
+ if ( ND_TEXTNODE == pNd->GetNodeType() &&
+ ((SwTxtNode*)pNd)->HasHiddenCharAttribute( false ) )
+ return true;
+ }
+
+ return false;
+}
+
+SwUnoCrsr* SwDoc::CreateUnoCrsr( const SwPosition& rPos, sal_Bool bTblCrsr )
+{
+ SwUnoCrsr* pNew;
+ if( bTblCrsr )
+ pNew = new SwUnoTableCrsr( rPos );
+ else
+ pNew = new SwUnoCrsr( rPos );
+
+ pUnoCrsrTbl->Insert( pNew, pUnoCrsrTbl->Count() );
+ return pNew;
+}
+
+void SwDoc::ChkCondColls()
+{
+ for (sal_uInt16 n = 0; n < pTxtFmtCollTbl->Count(); n++)
+ {
+ SwTxtFmtColl *pColl = (*pTxtFmtCollTbl)[n];
+ if (RES_CONDTXTFMTCOLL == pColl->Which())
+ pColl->CallSwClientNotify( SwAttrHint(RES_CONDTXTFMTCOLL) );
+ }
+}
+
+uno::Reference< script::vba::XVBAEventProcessor >
+SwDoc::GetVbaEventProcessor()
+{
+ if( !mxVbaEvents.is() && pDocShell && ooo::vba::isAlienWordDoc( *pDocShell ) )
+ {
+ try
+ {
+ uno::Reference< frame::XModel > xModel( pDocShell->GetModel(), uno::UNO_SET_THROW );
+ uno::Sequence< uno::Any > aArgs(1);
+ aArgs[0] <<= xModel;
+ mxVbaEvents.set( ooo::vba::createVBAUnoAPIServiceWithArgs( pDocShell, "com.sun.star.script.vba.VBATextEventProcessor" , aArgs ), uno::UNO_QUERY_THROW );
+ }
+ catch( uno::Exception& )
+ {
+ }
+ }
+ return mxVbaEvents;
+}
+
+void SwDoc::setExternalData(::sw::tExternalDataType eType,
+ ::sw::tExternalDataPointer pPayload)
+{
+ m_externalData[eType] = pPayload;
+}
+
+::sw::tExternalDataPointer SwDoc::getExternalData(::sw::tExternalDataType eType)
+{
+ return m_externalData[eType];
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/doc/docbasic.cxx b/sw/source/core/doc/docbasic.cxx
new file mode 100644
index 000000000000..00c6d40b5d91
--- /dev/null
+++ b/sw/source/core/doc/docbasic.cxx
@@ -0,0 +1,262 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+
+#include <hintids.hxx>
+
+#include <rtl/ustring.hxx>
+#include <svtools/imap.hxx>
+#include <svtools/imapobj.hxx>
+#include <basic/sbx.hxx>
+#include <frmfmt.hxx>
+#include <fmtinfmt.hxx>
+#include <fmturl.hxx>
+#include <frmatr.hxx>
+#include <docary.hxx>
+#include <doc.hxx>
+#include <docsh.hxx>
+#include <swevent.hxx>
+
+using namespace ::com::sun::star::uno;
+using ::rtl::OUString;
+
+static Sequence<Any> *lcl_docbasic_convertArgs( SbxArray& rArgs )
+{
+ Sequence<Any> *pRet = 0;
+
+ sal_uInt16 nCount = rArgs.Count();
+ if( nCount > 1 )
+ {
+ nCount--;
+ pRet = new Sequence<Any>( nCount );
+ Any *pUnoArgs = pRet->getArray();
+ for( sal_uInt16 i=0; i<nCount; i++ )
+ {
+ SbxVariable *pVar = rArgs.Get( i+1 );
+ switch( pVar->GetType() )
+ {
+ case SbxSTRING:
+ pUnoArgs[i] <<= OUString( pVar->GetString() );
+ break;
+ case SbxCHAR:
+ pUnoArgs[i] <<= (sal_Int16)pVar->GetChar() ;
+ break;
+ case SbxUSHORT:
+ pUnoArgs[i] <<= (sal_Int16)pVar->GetUShort();
+ break;
+ case SbxLONG:
+ pUnoArgs[i] <<= (sal_Int32)pVar->GetLong();
+ break;
+ default:
+ pUnoArgs[i].setValue(0, ::getVoidCppuType());
+ break;
+ }
+ }
+ }
+
+ return pRet;
+}
+
+sal_Bool SwDoc::ExecMacro( const SvxMacro& rMacro, String* pRet, SbxArray* pArgs )
+{
+ ErrCode eErr = 0;
+ switch( rMacro.GetScriptType() )
+ {
+ case STARBASIC:
+ {
+ SbxBaseRef aRef;
+ SbxValue* pRetValue = new SbxValue;
+ aRef = pRetValue;
+ eErr = pDocShell->CallBasic( rMacro.GetMacName(),
+ rMacro.GetLibName(),
+ pArgs, pRet ? pRetValue : 0 );
+
+ if( pRet && SbxNULL < pRetValue->GetType() &&
+ SbxVOID != pRetValue->GetType() )
+ // gueltiger Wert, also setzen
+ *pRet = pRetValue->GetString();
+ }
+ break;
+ case JAVASCRIPT:
+ // ignore JavaScript calls
+ break;
+ case EXTENDED_STYPE:
+ {
+ Sequence<Any> *pUnoArgs = 0;
+ if( pArgs )
+ {
+ // better to rename the local function to lcl_translateBasic2Uno and
+ // a much shorter routine can be found in sfx2/source/doc/objmisc.cxx
+ pUnoArgs = lcl_docbasic_convertArgs( *pArgs );
+ }
+
+ if (!pUnoArgs)
+ {
+ pUnoArgs = new Sequence< Any > (0);
+ }
+
+ // TODO - return value is not handled
+ Any aRet;
+ Sequence< sal_Int16 > aOutArgsIndex;
+ Sequence< Any > aOutArgs;
+
+ OSL_TRACE( "SwDoc::ExecMacro URL is %s", ByteString( rMacro.GetMacName(),
+ RTL_TEXTENCODING_UTF8).GetBuffer() );
+
+ eErr = pDocShell->CallXScript(
+ rMacro.GetMacName(), *pUnoArgs, aRet, aOutArgsIndex, aOutArgs);
+
+ delete pUnoArgs;
+ break;
+ }
+ }
+
+ return 0 == eErr;
+}
+
+
+
+sal_uInt16 SwDoc::CallEvent( sal_uInt16 nEvent, const SwCallMouseEvent& rCallEvent,
+ sal_Bool bCheckPtr, SbxArray* pArgs, const Link* )
+{
+ if( !pDocShell ) // ohne DocShell geht das nicht!
+ return 0;
+
+ sal_uInt16 nRet = 0;
+ const SvxMacroTableDtor* pTbl = 0;
+ switch( rCallEvent.eType )
+ {
+ case EVENT_OBJECT_INETATTR:
+ if( bCheckPtr )
+ {
+ const SfxPoolItem* pItem;
+ sal_uInt32 n, nMaxItems = GetAttrPool().GetItemCount2( RES_TXTATR_INETFMT );
+ for( n = 0; n < nMaxItems; ++n )
+ if( 0 != (pItem = GetAttrPool().GetItem2( RES_TXTATR_INETFMT, n ) )
+ && rCallEvent.PTR.pINetAttr == pItem )
+ {
+ bCheckPtr = sal_False; // als Flag missbrauchen
+ break;
+ }
+ }
+ if( !bCheckPtr )
+ pTbl = rCallEvent.PTR.pINetAttr->GetMacroTbl();
+ break;
+
+ case EVENT_OBJECT_URLITEM:
+ case EVENT_OBJECT_IMAGE:
+ {
+ const SwFrmFmtPtr pFmt = (SwFrmFmtPtr)rCallEvent.PTR.pFmt;
+ if( bCheckPtr )
+ {
+ sal_uInt16 nPos = GetSpzFrmFmts()->GetPos( pFmt );
+ if( USHRT_MAX != nPos )
+ bCheckPtr = sal_False; // als Flag missbrauchen
+ }
+ if( !bCheckPtr )
+ pTbl = &pFmt->GetMacro().GetMacroTable();
+ }
+ break;
+
+ case EVENT_OBJECT_IMAGEMAP:
+ {
+ const IMapObject* pIMapObj = rCallEvent.PTR.IMAP.pIMapObj;
+ if( bCheckPtr )
+ {
+ const SwFrmFmtPtr pFmt = (SwFrmFmtPtr)rCallEvent.PTR.IMAP.pFmt;
+ sal_uInt16 nPos = GetSpzFrmFmts()->GetPos( pFmt );
+ const ImageMap* pIMap;
+ if( USHRT_MAX != nPos &&
+ 0 != (pIMap = pFmt->GetURL().GetMap()) )
+ {
+ for( nPos = pIMap->GetIMapObjectCount(); nPos; )
+ if( pIMapObj == pIMap->GetIMapObject( --nPos ))
+ {
+ bCheckPtr = sal_False; // als Flag missbrauchen
+ break;
+ }
+ }
+ }
+ if( !bCheckPtr )
+ pTbl = &pIMapObj->GetMacroTable();
+ }
+ break;
+ default:
+ break;
+ }
+
+ if( pTbl )
+ {
+ nRet = 0x1;
+ if( pTbl->IsKeyValid( nEvent ) )
+ {
+ const SvxMacro& rMacro = *pTbl->Get( nEvent );
+ if( STARBASIC == rMacro.GetScriptType() )
+ {
+ nRet += 0 == pDocShell->CallBasic( rMacro.GetMacName(),
+ rMacro.GetLibName(), pArgs ) ? 1 : 0;
+ }
+ else if( EXTENDED_STYPE == rMacro.GetScriptType() )
+ {
+ Sequence<Any> *pUnoArgs = 0;
+
+ if( pArgs )
+ {
+ pUnoArgs = lcl_docbasic_convertArgs( *pArgs );
+ }
+
+ if (!pUnoArgs)
+ {
+ pUnoArgs = new Sequence <Any> (0);
+ }
+
+ Any aRet;
+ Sequence< sal_Int16 > aOutArgsIndex;
+ Sequence< Any > aOutArgs;
+
+ OSL_TRACE( "SwDoc::CallEvent URL is %s", ByteString(
+ rMacro.GetMacName(), RTL_TEXTENCODING_UTF8).GetBuffer() );
+
+ nRet += 0 == pDocShell->CallXScript(
+ rMacro.GetMacName(), *pUnoArgs,aRet, aOutArgsIndex, aOutArgs) ? 1 : 0;
+
+ delete pUnoArgs;
+ }
+ // JavaScript calls are ignored
+ }
+ }
+ return nRet;
+}
+
+
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/doc/docbm.cxx b/sw/source/core/doc/docbm.cxx
new file mode 100644
index 000000000000..85a90d2565e3
--- /dev/null
+++ b/sw/source/core/doc/docbm.cxx
@@ -0,0 +1,1740 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+
+#include <MarkManager.hxx>
+#include <bookmrk.hxx>
+#include <boost/bind.hpp>
+#include <cntfrm.hxx>
+#include <crossrefbookmark.hxx>
+#include <dcontact.hxx>
+#include <doc.hxx>
+#include <docary.hxx>
+#include <xmloff/odffields.hxx>
+#include <editsh.hxx>
+#include <fmtanchr.hxx>
+#include <frmfmt.hxx>
+#include <functional>
+#include <hintids.hxx>
+#include <mvsave.hxx>
+#include <ndtxt.hxx>
+#include <node.hxx>
+#include <pam.hxx>
+#include <redline.hxx>
+#include <rolbck.hxx>
+#include <rtl/ustrbuf.hxx>
+#include <rtl/ustring.hxx>
+#include <sal/types.h>
+#include <sortedobjs.hxx>
+#include <sfx2/linkmgr.hxx>
+#include <swserv.hxx>
+#include <swundo.hxx>
+#include <tools/pstm.hxx>
+#include <unocrsr.hxx>
+#include <viscrs.hxx>
+#include <stdio.h>
+
+
+using namespace ::std;
+using namespace ::boost;
+using namespace ::sw::mark;
+
+namespace
+{
+ static bool lcl_GreaterThan( const SwPosition& rPos, const SwNodeIndex& rNdIdx, const SwIndex* pIdx )
+ {
+ return pIdx ? ( rPos.nNode > rNdIdx || ( rPos.nNode == rNdIdx && rPos.nContent >= pIdx->GetIndex() )) : rPos.nNode >= rNdIdx;
+ }
+
+ static bool lcl_Lower( const SwPosition& rPos, const SwNodeIndex& rNdIdx, const SwIndex* pIdx )
+ {
+ return rPos.nNode < rNdIdx || ( pIdx && rPos.nNode == rNdIdx && rPos.nContent < pIdx->GetIndex() );
+ }
+
+ static bool lcl_MarkOrderingByStart(const IDocumentMarkAccess::pMark_t& rpFirst,
+ const IDocumentMarkAccess::pMark_t& rpSecond)
+ {
+ return rpFirst->GetMarkStart() < rpSecond->GetMarkStart();
+ }
+
+ static bool lcl_MarkOrderingByEnd(const IDocumentMarkAccess::pMark_t& rpFirst,
+ const IDocumentMarkAccess::pMark_t& rpSecond)
+ {
+ return rpFirst->GetMarkEnd() < rpSecond->GetMarkEnd();
+ }
+
+ static void lcl_InsertMarkSorted(IDocumentMarkAccess::container_t& io_vMarks,
+ const IDocumentMarkAccess::pMark_t& pMark)
+ {
+ io_vMarks.insert(
+ lower_bound(
+ io_vMarks.begin(),
+ io_vMarks.end(),
+ pMark,
+ &lcl_MarkOrderingByStart),
+ pMark);
+ }
+
+ static inline auto_ptr<SwPosition> lcl_PositionFromCntntNode(SwCntntNode * const pCntntNode, const bool bAtEnd=false)
+ {
+ auto_ptr<SwPosition> pResult(new SwPosition(*pCntntNode));
+ pResult->nContent.Assign(pCntntNode, bAtEnd ? pCntntNode->Len() : 0);
+ return pResult;
+ }
+
+ // return a position at the begin of rEnd, if it is a CntntNode
+ // else set it to the begin of the Node after rEnd, if there is one
+ // else set it to the end of the node before rStt
+ // else set it to the CntntNode of the Pos outside the Range
+ static inline auto_ptr<SwPosition> lcl_FindExpelPosition(const SwNodeIndex& rStt,
+ const SwNodeIndex& rEnd,
+ const SwPosition& rOtherPosition)
+ {
+ SwCntntNode * pNode = rEnd.GetNode().GetCntntNode();
+ SwNodeIndex aStt = SwNodeIndex(rStt);
+ SwNodeIndex aEnd = SwNodeIndex(rEnd);
+ bool bAtEnd = false;
+ if(!pNode)
+ pNode = rEnd.GetNodes().GoNext(&aEnd), bAtEnd = false;
+ if(!pNode)
+ pNode = rStt.GetNodes().GoPrevious(&aStt), bAtEnd = true;
+ if(pNode)
+ return lcl_PositionFromCntntNode(pNode, bAtEnd);
+ return auto_ptr<SwPosition>(new SwPosition(rOtherPosition));
+ };
+
+ static IMark* lcl_getMarkAfter(const IDocumentMarkAccess::container_t& rMarks, const SwPosition& rPos)
+ {
+ IDocumentMarkAccess::const_iterator_t pMarkAfter = upper_bound(
+ rMarks.begin(),
+ rMarks.end(),
+ rPos,
+ bind(&IMark::StartsAfter, _2, _1)); // finds the first that is starting after
+ if(pMarkAfter == rMarks.end()) return NULL;
+ return pMarkAfter->get();
+ };
+
+ static IMark* lcl_getMarkBefore(const IDocumentMarkAccess::container_t& rMarks, const SwPosition& rPos)
+ {
+ // candidates from which to choose the mark before
+ IDocumentMarkAccess::container_t vCandidates;
+ // no need to consider marks starting after rPos
+ IDocumentMarkAccess::const_iterator_t pCandidatesEnd = upper_bound(
+ rMarks.begin(),
+ rMarks.end(),
+ rPos,
+ bind(&IMark::StartsAfter, _2, _1));
+ vCandidates.reserve(pCandidatesEnd - rMarks.begin());
+ // only marks ending before are candidates
+ remove_copy_if(
+ rMarks.begin(),
+ pCandidatesEnd,
+ back_inserter(vCandidates),
+ bind(logical_not<bool>(), bind(&IMark::EndsBefore, _1, rPos)));
+ // no candidate left => we are in front of the first mark or there are none
+ if(!vCandidates.size()) return NULL;
+ // return the highest (last) candidate using mark end ordering
+ return max_element(vCandidates.begin(), vCandidates.end(), &lcl_MarkOrderingByEnd)->get();
+ }
+
+ static bool lcl_FixCorrectedMark(bool bChangedPos, bool bChangedOPos, MarkBase* io_pMark)
+ {
+ if( (bChangedPos || bChangedOPos) && io_pMark->IsExpanded() &&
+ io_pMark->GetOtherMarkPos().nNode.GetNode().FindTableBoxStartNode() !=
+ io_pMark->GetMarkPos().nNode.GetNode().FindTableBoxStartNode() )
+ {
+ if(!bChangedOPos)
+ io_pMark->SetMarkPos(io_pMark->GetOtherMarkPos());
+ io_pMark->ClearOtherMarkPos();
+ DdeBookmark * const pDdeBkmk = dynamic_cast< DdeBookmark*>(io_pMark);
+ if(pDdeBkmk && pDdeBkmk->IsServer())
+ pDdeBkmk->SetRefObject(NULL);
+ return true;
+ }
+ return false;
+ }
+
+ static IDocumentMarkAccess::iterator_t lcl_FindMark(
+ IDocumentMarkAccess::container_t& rMarks,
+ const IDocumentMarkAccess::pMark_t& rpMarkToFind)
+ {
+ IDocumentMarkAccess::iterator_t ppCurrentMark = lower_bound(
+ rMarks.begin(), rMarks.end(),
+ rpMarkToFind, &lcl_MarkOrderingByStart);
+ // since there are usually not too many marks on the same start
+ // position, we are not doing a bisect search for the upper bound
+ // but instead start to iterate from pMarkLow directly
+ while(ppCurrentMark != rMarks.end() && **ppCurrentMark == *rpMarkToFind)
+ {
+ if(ppCurrentMark->get() == rpMarkToFind.get())
+ {
+ //OSL_TRACE("found mark named '%s'",
+ // ::rtl::OUStringToOString(ppCurrentMark->get()->GetName(), RTL_TEXTENCODING_UTF8).getStr());
+ return ppCurrentMark;
+ }
+ ++ppCurrentMark;
+ }
+ // reached a mark starting on a later start pos or the end of the
+ // vector => not found
+ return rMarks.end();
+ };
+
+ static IDocumentMarkAccess::iterator_t lcl_FindMarkAtPos(
+ IDocumentMarkAccess::container_t& rMarks,
+ const SwPosition& rPos,
+ const IDocumentMarkAccess::MarkType eType)
+ {
+ for(IDocumentMarkAccess::iterator_t ppCurrentMark = lower_bound(
+ rMarks.begin(), rMarks.end(),
+ rPos,
+ bind(&IMark::StartsBefore, _1, _2));
+ ppCurrentMark != rMarks.end();
+ ++ppCurrentMark)
+ {
+ // Once we reach a mark starting after the target pos
+ // we do not need to continue
+ if(ppCurrentMark->get()->StartsAfter(rPos))
+ break;
+ if(IDocumentMarkAccess::GetType(**ppCurrentMark) == eType)
+ {
+ //OSL_TRACE("found mark named '%s'",
+ // ::rtl::OUStringToOString(ppCurrentMark->get()->GetName(), RTL_TEXTENCODING_UTF8).getStr());
+ return ppCurrentMark;
+ }
+ }
+ // reached a mark starting on a later start pos or the end of the
+ // vector => not found
+ return rMarks.end();
+ };
+
+ static IDocumentMarkAccess::const_iterator_t lcl_FindMarkByName(
+ const ::rtl::OUString& rName,
+ IDocumentMarkAccess::const_iterator_t ppMarksBegin,
+ IDocumentMarkAccess::const_iterator_t ppMarksEnd)
+ {
+ return find_if(
+ ppMarksBegin,
+ ppMarksEnd,
+ bind(&::rtl::OUString::equals, bind(&IMark::GetName, _1), rName));
+ }
+
+#if 0
+ static void lcl_DebugMarks(IDocumentMarkAccess::container_t vMarks)
+ {
+ OSL_TRACE("%d Marks", vMarks.size());
+ for(IDocumentMarkAccess::iterator_t ppMark = vMarks.begin();
+ ppMark != vMarks.end();
+ ppMark++)
+ {
+ IMark* pMark = ppMark->get();
+ ::rtl::OString sName = ::rtl::OUStringToOString(pMark->GetName(), RTL_TEXTENCODING_UTF8);
+ const SwPosition* const pStPos = &pMark->GetMarkStart();
+ const SwPosition* const pEndPos = &pMark->GetMarkEnd();
+ OSL_TRACE("%s %s %d,%d %d,%d",
+ typeid(*pMark).name(),
+ sName.getStr(),
+ pStPos->nNode.GetIndex(),
+ pStPos->nContent.GetIndex(),
+ pEndPos->nNode.GetIndex(),
+ pEndPos->nContent.GetIndex());
+ }
+ };
+#endif
+}
+
+IDocumentMarkAccess::MarkType IDocumentMarkAccess::GetType(const IMark& rBkmk)
+{
+ const std::type_info* const pMarkTypeInfo = &typeid(rBkmk);
+ // not using dynamic_cast<> here for performance
+ if(*pMarkTypeInfo == typeid(UnoMark))
+ return UNO_BOOKMARK;
+ else if(*pMarkTypeInfo == typeid(DdeBookmark))
+ return DDE_BOOKMARK;
+ else if(*pMarkTypeInfo == typeid(Bookmark))
+ return BOOKMARK;
+ else if(*pMarkTypeInfo == typeid(CrossRefHeadingBookmark))
+ return CROSSREF_HEADING_BOOKMARK;
+ else if(*pMarkTypeInfo == typeid(CrossRefNumItemBookmark))
+ return CROSSREF_NUMITEM_BOOKMARK;
+ else if(*pMarkTypeInfo == typeid(TextFieldmark))
+ return TEXT_FIELDMARK;
+ else if(*pMarkTypeInfo == typeid(CheckboxFieldmark))
+ return CHECKBOX_FIELDMARK;
+ else if(*pMarkTypeInfo == typeid(NavigatorReminder))
+ return NAVIGATOR_REMINDER;
+ else
+ {
+ OSL_FAIL("IDocumentMarkAccess::GetType(..)"
+ " - unknown MarkType. This needs to be fixed!");
+ return UNO_BOOKMARK;
+ }
+}
+
+namespace sw { namespace mark
+{
+ MarkManager::MarkManager(SwDoc& rDoc)
+ : m_pDoc(&rDoc)
+ { }
+#if OSL_DEBUG_LEVEL > 1
+ void MarkManager::dumpFieldmarks( ) const
+ {
+ const_iterator_t pIt = m_vFieldmarks.begin();
+ for (; pIt != m_vFieldmarks.end( ); pIt++)
+ {
+ rtl::OUString str = (*pIt)->ToString();
+ OSL_TRACE("%s\n",
+ ::rtl::OUStringToOString(str, RTL_TEXTENCODING_UTF8).getStr());
+ }
+ }
+#endif
+ ::sw::mark::IMark* MarkManager::makeMark(const SwPaM& rPaM,
+ const ::rtl::OUString& rName,
+ const IDocumentMarkAccess::MarkType eType)
+ {
+#if 0
+ {
+ ::rtl::OString sName = ::rtl::OUStringToOString(rName, RTL_TEXTENCODING_UTF8);
+ const SwPosition* const pPos1 = rPaM.GetPoint();
+ const SwPosition* pPos2 = pPos1;
+ if(rPaM.HasMark())
+ pPos2 = rPaM.GetMark();
+ OSL_TRACE("%s %d,%d %d,%d",
+ sName.getStr(),
+ pPos1->nNode.GetIndex(),
+ pPos1->nContent.GetIndex(),
+ pPos2->nNode.GetIndex(),
+ pPos2->nContent.GetIndex());
+ }
+#endif
+ // see for example _SaveCntntIdx, Shells
+ OSL_PRECOND(m_vMarks.size() < USHRT_MAX,
+ "MarkManager::makeMark(..)"
+ " - more than USHRT_MAX marks are not supported correctly");
+ // There should only be one CrossRefBookmark per Textnode per Type
+ OSL_PRECOND(
+ (eType != CROSSREF_NUMITEM_BOOKMARK && eType != CROSSREF_HEADING_BOOKMARK)
+ || (lcl_FindMarkAtPos(m_vBookmarks, *rPaM.GetPoint(), eType) == m_vBookmarks.end()),
+ "MarkManager::makeMark(..)"
+ " - creating duplicate CrossRefBookmark");
+
+ // create mark
+ pMark_t pMark;
+ switch(eType)
+ {
+ case IDocumentMarkAccess::TEXT_FIELDMARK:
+ pMark = boost::shared_ptr<IMark>(new TextFieldmark(rPaM));
+ break;
+ case IDocumentMarkAccess::CHECKBOX_FIELDMARK:
+ pMark = boost::shared_ptr<IMark>(new CheckboxFieldmark(rPaM));
+ break;
+ case IDocumentMarkAccess::NAVIGATOR_REMINDER:
+ pMark = boost::shared_ptr<IMark>(new NavigatorReminder(rPaM));
+ break;
+ case IDocumentMarkAccess::BOOKMARK:
+ pMark = boost::shared_ptr<IMark>(new Bookmark(rPaM, KeyCode(), rName, ::rtl::OUString()));
+ break;
+ case IDocumentMarkAccess::DDE_BOOKMARK:
+ pMark = boost::shared_ptr<IMark>(new DdeBookmark(rPaM));
+ break;
+ case IDocumentMarkAccess::CROSSREF_HEADING_BOOKMARK:
+ pMark = boost::shared_ptr<IMark>(new CrossRefHeadingBookmark(rPaM, KeyCode(), rName, ::rtl::OUString()));
+ break;
+ case IDocumentMarkAccess::CROSSREF_NUMITEM_BOOKMARK:
+ pMark = boost::shared_ptr<IMark>(new CrossRefNumItemBookmark(rPaM, KeyCode(), rName, ::rtl::OUString()));
+ break;
+ case IDocumentMarkAccess::UNO_BOOKMARK:
+ pMark = boost::shared_ptr<IMark>(new UnoMark(rPaM));
+ break;
+ }
+ OSL_ENSURE(pMark.get(),
+ "MarkManager::makeMark(..)"
+ " - Mark was not created.");
+ MarkBase* pMarkBase = dynamic_cast<MarkBase*>(pMark.get());
+
+ if(pMark->GetMarkPos() != pMark->GetMarkStart())
+ pMarkBase->Swap();
+
+ // for performance reasons, we trust UnoMarks to have a (generated) unique name
+ if(eType != IDocumentMarkAccess::UNO_BOOKMARK)
+ pMarkBase->SetName(getUniqueMarkName(pMarkBase->GetName()));
+
+ // register mark
+ lcl_InsertMarkSorted(m_vMarks, pMark);
+ switch(eType)
+ {
+ case IDocumentMarkAccess::BOOKMARK:
+ case IDocumentMarkAccess::CROSSREF_NUMITEM_BOOKMARK:
+ case IDocumentMarkAccess::CROSSREF_HEADING_BOOKMARK:
+ lcl_InsertMarkSorted(m_vBookmarks, pMark);
+ break;
+ case IDocumentMarkAccess::TEXT_FIELDMARK:
+ case IDocumentMarkAccess::CHECKBOX_FIELDMARK:
+ lcl_InsertMarkSorted(m_vFieldmarks, pMark);
+ break;
+ case IDocumentMarkAccess::NAVIGATOR_REMINDER:
+ case IDocumentMarkAccess::DDE_BOOKMARK:
+ case IDocumentMarkAccess::UNO_BOOKMARK:
+ // no special array for these
+ break;
+ }
+ pMarkBase->InitDoc(m_pDoc);
+#if 0
+ OSL_TRACE("--- makeType ---");
+ OSL_TRACE("Marks");
+ lcl_DebugMarks(m_vMarks);
+ OSL_TRACE("Bookmarks");
+ lcl_DebugMarks(m_vBookmarks);
+ OSL_TRACE("Fieldmarks");
+ lcl_DebugMarks(m_vFieldmarks);
+#endif
+
+ return pMark.get();
+ }
+
+ ::sw::mark::IFieldmark* MarkManager::makeFieldBookmark( const SwPaM& rPaM,
+ const rtl::OUString& rName,
+ const rtl::OUString& rType )
+ {
+ sw::mark::IMark* pMark = makeMark( rPaM, rName,
+ IDocumentMarkAccess::TEXT_FIELDMARK );
+ sw::mark::IFieldmark* pFieldMark = dynamic_cast<sw::mark::IFieldmark*>( pMark );
+ pFieldMark->SetFieldname( rType );
+
+ return pFieldMark;
+ }
+
+ ::sw::mark::IFieldmark* MarkManager::makeNoTextFieldBookmark( const SwPaM& rPaM,
+ const rtl::OUString& rName,
+ const rtl::OUString& rType)
+ {
+ sw::mark::IMark* pMark = makeMark( rPaM, rName,
+ IDocumentMarkAccess::CHECKBOX_FIELDMARK );
+ sw::mark::IFieldmark* pFieldMark = dynamic_cast<sw::mark::IFieldmark*>( pMark );
+ pFieldMark->SetFieldname( rType );
+
+ return pFieldMark;
+ }
+
+ ::sw::mark::IMark* MarkManager::getMarkForTxtNode(const SwTxtNode& rTxtNode,
+ const IDocumentMarkAccess::MarkType eType)
+ {
+ SwPosition aPos(rTxtNode);
+ aPos.nContent.Assign(&(const_cast<SwTxtNode&>(rTxtNode)), 0);
+ const iterator_t ppExistingMark = lcl_FindMarkAtPos(m_vBookmarks, aPos, eType);
+ if(ppExistingMark != m_vBookmarks.end())
+ return ppExistingMark->get();
+ const SwPaM aPaM(aPos);
+ return makeMark(aPaM, ::rtl::OUString(), eType);
+ }
+
+ void MarkManager::repositionMark( ::sw::mark::IMark* const io_pMark,
+ const SwPaM& rPaM)
+ {
+ OSL_PRECOND(io_pMark->GetMarkPos().GetDoc() == m_pDoc,
+ "<MarkManager::repositionMark(..)>"
+ " - Mark is not in my doc.");
+ MarkBase* const pMarkBase = dynamic_cast< MarkBase* >(io_pMark);
+ pMarkBase->SetMarkPos(*(rPaM.GetPoint()));
+ if(rPaM.HasMark())
+ pMarkBase->SetOtherMarkPos(*(rPaM.GetMark()));
+ else
+ pMarkBase->ClearOtherMarkPos();
+
+ if(pMarkBase->GetMarkPos() != pMarkBase->GetMarkStart())
+ pMarkBase->Swap();
+
+ sortMarks();
+ }
+
+ bool MarkManager::renameMark(::sw::mark::IMark* io_pMark, const ::rtl::OUString& rNewName)
+ {
+ OSL_PRECOND(io_pMark->GetMarkPos().GetDoc() == m_pDoc,
+ "<MarkManager::repositionMark(..)>"
+ " - Mark is not in my doc.");
+ if(io_pMark->GetName() == rNewName)
+ return true;
+ if(findMark(rNewName) != getMarksEnd())
+ return false;
+ dynamic_cast< ::sw::mark::MarkBase* >(io_pMark)->SetName(rNewName);
+ return true;
+ }
+
+ void MarkManager::correctMarksAbsolute(const SwNodeIndex& rOldNode, const SwPosition& rNewPos, const xub_StrLen nOffset)
+ {
+ const SwNode* const pOldNode = &rOldNode.GetNode();
+ SwPosition aNewPos(rNewPos);
+ aNewPos.nContent += nOffset;
+ bool isSortingNeeded = false;
+ for(iterator_t ppMark = m_vMarks.begin();
+ ppMark != m_vMarks.end();
+ ppMark++)
+ {
+ // is on position ??
+ bool bChangedPos = false, bChangedOPos = false;
+ ::sw::mark::MarkBase* pMark = dynamic_cast< ::sw::mark::MarkBase* >(ppMark->get());
+ if(&pMark->GetMarkPos().nNode.GetNode() == pOldNode)
+ {
+ pMark->SetMarkPos(aNewPos);
+ bChangedPos = true;
+ }
+ if (pMark->IsExpanded() &&
+ &pMark->GetOtherMarkPos().nNode.GetNode() == pOldNode)
+ {
+ pMark->SetMarkPos(aNewPos);
+ bChangedOPos= true;
+ }
+ // illegal selection? collapse the mark and restore sorting later
+ isSortingNeeded |= lcl_FixCorrectedMark(bChangedPos, bChangedOPos, pMark);
+ }
+ // restore sorting if needed
+ if(isSortingNeeded)
+ sortMarks();
+#if 0
+ OSL_TRACE("correctMarksAbsolute");
+ lcl_DebugMarks(m_vMarks);
+#endif
+ }
+
+ void MarkManager::correctMarksRelative(const SwNodeIndex& rOldNode, const SwPosition& rNewPos, const xub_StrLen nOffset)
+ {
+ const SwNode* const pOldNode = &rOldNode.GetNode();
+ SwPosition aNewPos(rNewPos);
+ aNewPos.nContent += nOffset;
+ bool isSortingNeeded = false;
+ for(iterator_t ppMark = m_vMarks.begin();
+ ppMark != m_vMarks.end();
+ ppMark++)
+ {
+ // is on position ??
+ bool bChangedPos = false, bChangedOPos = false;
+ ::sw::mark::MarkBase* const pMark = dynamic_cast< ::sw::mark::MarkBase* >(ppMark->get());
+ if(&pMark->GetMarkPos().nNode.GetNode() == pOldNode)
+ {
+ SwPosition aNewPosRel(aNewPos);
+ aNewPosRel.nContent += pMark->GetMarkPos().nContent.GetIndex();
+ pMark->SetMarkPos(aNewPosRel);
+ bChangedPos = true;
+ }
+ if(pMark->IsExpanded() &&
+ &pMark->GetOtherMarkPos().nNode.GetNode() == pOldNode)
+ {
+ SwPosition aNewPosRel(aNewPos);
+ aNewPosRel.nContent += pMark->GetOtherMarkPos().nContent.GetIndex();
+ pMark->SetOtherMarkPos(aNewPosRel);
+ bChangedOPos = true;
+ }
+ // illegal selection? collapse the mark and restore sorting later
+ isSortingNeeded |= lcl_FixCorrectedMark(bChangedPos, bChangedOPos, pMark);
+ }
+ // restore sorting if needed
+ if(isSortingNeeded)
+ sortMarks();
+#if 0
+ OSL_TRACE("correctMarksRelative");
+ lcl_DebugMarks(m_vMarks);
+#endif
+ }
+
+ void MarkManager::deleteMarks(
+ const SwNodeIndex& rStt,
+ const SwNodeIndex& rEnd,
+ ::std::vector<SaveBookmark>* pSaveBkmk,
+ const SwIndex* pSttIdx,
+ const SwIndex* pEndIdx )
+ {
+ vector<const_iterator_t> vMarksToDelete;
+ bool isSortingNeeded = false;
+ // copy all bookmarks in the move area to a vector storing all position data as offset
+ // reassignment is performed after the move
+ for(iterator_t ppMark = m_vMarks.begin();
+ ppMark != m_vMarks.end();
+ ppMark++)
+ {
+ // navigator marks should not be moved
+ // TODO: Check if this might make them invalid
+ if(IDocumentMarkAccess::GetType(**ppMark) == NAVIGATOR_REMINDER)
+ continue;
+
+ ::sw::mark::MarkBase* pMark = dynamic_cast< ::sw::mark::MarkBase* >(ppMark->get());
+ // on position ??
+ bool isPosInRange = (lcl_GreaterThan(pMark->GetMarkPos(), rStt, pSttIdx) &&
+ lcl_Lower(pMark->GetMarkPos(), rEnd, pEndIdx));
+ bool isOtherPosInRange = (pMark->IsExpanded() &&
+ lcl_GreaterThan(pMark->GetOtherMarkPos(), rStt, pSttIdx) &&
+ lcl_Lower(pMark->GetOtherMarkPos(), rEnd, pEndIdx));
+ // special case: completely in range, touching the end?
+ if(pEndIdx &&
+ ((isOtherPosInRange
+ && pMark->GetMarkPos().nNode == rEnd
+ && pMark->GetMarkPos().nContent == *pEndIdx)
+ || (isPosInRange
+ && pMark->IsExpanded()
+ && pMark->GetOtherMarkPos().nNode == rEnd
+ && pMark->GetOtherMarkPos().nContent == *pEndIdx)))
+ {
+ isPosInRange = true, isOtherPosInRange = true;
+ }
+
+ if(isPosInRange && (isOtherPosInRange || !pMark->IsExpanded()))
+ {
+ // completely in range
+
+ // #i92125#
+ bool bKeepCrossRefBkmk( false );
+ {
+ if ( rStt == rEnd &&
+ ( IDocumentMarkAccess::GetType(*pMark) ==
+ IDocumentMarkAccess::CROSSREF_HEADING_BOOKMARK ||
+ IDocumentMarkAccess::GetType(*pMark) ==
+ IDocumentMarkAccess::CROSSREF_NUMITEM_BOOKMARK ) )
+ {
+ bKeepCrossRefBkmk = true;
+ }
+ }
+ if ( !bKeepCrossRefBkmk )
+ {
+ if(pSaveBkmk)
+ pSaveBkmk->push_back(SaveBookmark(true, true, *pMark, rStt, pSttIdx));
+ vMarksToDelete.push_back(ppMark);
+ }
+ }
+ else if(isPosInRange ^ isOtherPosInRange)
+ {
+ // the bookmark is partitially in the range
+ // move position of that is in the range out of it
+ auto_ptr<SwPosition> pNewPos;
+ if(pEndIdx)
+ pNewPos = auto_ptr<SwPosition>(new SwPosition(
+ rEnd,
+ *pEndIdx));
+ else
+ pNewPos = lcl_FindExpelPosition(
+ rStt,
+ rEnd,
+ isPosInRange ? pMark->GetOtherMarkPos() : pMark->GetMarkPos());
+
+ // #i92125#
+ // no move of position for cross-reference bookmarks,
+ // if move occurs inside a certain node
+ if ( ( IDocumentMarkAccess::GetType(*pMark) !=
+ IDocumentMarkAccess::CROSSREF_HEADING_BOOKMARK &&
+ IDocumentMarkAccess::GetType(*pMark) !=
+ IDocumentMarkAccess::CROSSREF_NUMITEM_BOOKMARK ) ||
+ pMark->GetMarkPos().nNode != pNewPos->nNode )
+ {
+ if(isPosInRange)
+ pMark->SetMarkPos(*pNewPos);
+ else
+ pMark->SetOtherMarkPos(*pNewPos);
+
+ // illegal selection? collapse the mark and restore sorting later
+ isSortingNeeded |= lcl_FixCorrectedMark(isPosInRange, isOtherPosInRange, pMark);
+ }
+ }
+ }
+
+ // we just remembered the iterators to delete, so we do not need to search
+ // for the boost::shared_ptr<> (the entry in m_vMarks) again
+ // reverse iteration, since erasing an entry invalidates iterators
+ // behind it (the iterators in vMarksToDelete are sorted)
+ for(vector<const_iterator_t>::reverse_iterator pppMark = vMarksToDelete.rbegin();
+ pppMark != vMarksToDelete.rend();
+ ++pppMark)
+ {
+ deleteMark(*pppMark);
+ }
+ if(isSortingNeeded)
+ sortMarks();
+#if 0
+ OSL_TRACE("deleteMarks");
+ lcl_DebugMarks(m_vMarks);
+#endif
+ }
+
+ void MarkManager::deleteMark(const const_iterator_t ppMark)
+ {
+ if(ppMark == m_vMarks.end()) return;
+
+ switch(IDocumentMarkAccess::GetType(**ppMark))
+ {
+ case IDocumentMarkAccess::BOOKMARK:
+ case IDocumentMarkAccess::CROSSREF_HEADING_BOOKMARK:
+ case IDocumentMarkAccess::CROSSREF_NUMITEM_BOOKMARK:
+ // if(dynamic_cast<IBookmark*>)
+ {
+ IDocumentMarkAccess::iterator_t ppBookmark = lcl_FindMark(m_vBookmarks, *ppMark);
+ OSL_ENSURE(ppBookmark != m_vBookmarks.end(),
+ "<MarkManager::deleteMark(..)>"
+ " - Bookmark not found.");
+ m_vBookmarks.erase(ppBookmark);
+ break;
+ }
+ case IDocumentMarkAccess::TEXT_FIELDMARK:
+ case IDocumentMarkAccess::CHECKBOX_FIELDMARK:
+ {
+ IDocumentMarkAccess::iterator_t ppFieldmark = lcl_FindMark(m_vFieldmarks, *ppMark);
+ OSL_ENSURE(ppFieldmark != m_vFieldmarks.end(),
+ "<MarkManager::deleteMark(..)>"
+ " - Bookmark not found.");
+ m_vFieldmarks.erase(ppFieldmark);
+ break;
+ }
+ case IDocumentMarkAccess::NAVIGATOR_REMINDER:
+ case IDocumentMarkAccess::DDE_BOOKMARK:
+ case IDocumentMarkAccess::UNO_BOOKMARK:
+ // no special array for these
+ break;
+ }
+ DdeBookmark* const pDdeBookmark = dynamic_cast<DdeBookmark*>(ppMark->get());
+ if(pDdeBookmark)
+ pDdeBookmark->DeregisterFromDoc(m_pDoc);
+ m_vMarks.erase(m_vMarks.begin() + (ppMark - m_vMarks.begin())); // clumsy const-cast
+ }
+
+ void MarkManager::deleteMark(const IMark* const pMark)
+ {
+ OSL_PRECOND(pMark->GetMarkPos().GetDoc() == m_pDoc,
+ "<MarkManager::repositionMark(..)>"
+ " - Mark is not in my doc.");
+ // finds the last Mark that is starting before pMark
+ // (pMarkLow < pMark)
+ iterator_t pMarkLow = lower_bound(
+ m_vMarks.begin(), m_vMarks.end(),
+ pMark->GetMarkStart(),
+ bind(&IMark::StartsBefore, _1, _2));
+ // finds the first Mark that pMark is starting before
+ // (pMark < pMarkHigh)
+ //iterator_t pMarkHigh = upper_bound(
+ // pMarkLow, m_vMarks.end(),
+ // pMark->GetMarkStart(),
+ // bind(&IMark::StartsBefore, _2, _1));
+ // since it should be rare that pMark isnt found at all
+ // we skip the bisect search on the upper bound
+ iterator_t pMarkHigh = m_vMarks.end();
+ iterator_t pMarkFound = find_if(
+ pMarkLow, pMarkHigh,
+ bind(equal_to<const IMark*>(), bind(&boost::shared_ptr<IMark>::get, _1), pMark));
+ if(pMarkFound != pMarkHigh)
+ deleteMark(pMarkFound);
+ }
+
+ void MarkManager::clearAllMarks()
+ {
+ m_vFieldmarks.clear();
+ m_vBookmarks.clear();
+#ifdef DEBUG
+ for(iterator_t pBkmk = m_vMarks.begin();
+ pBkmk != m_vMarks.end();
+ ++pBkmk)
+ OSL_ENSURE(pBkmk->unique(),
+ "<MarkManager::clearAllMarks(..)>"
+ " - a Bookmark is still in use.");
+#endif
+ m_vMarks.clear();
+ }
+
+ IDocumentMarkAccess::const_iterator_t MarkManager::findMark(const ::rtl::OUString& rName) const
+ {
+ return lcl_FindMarkByName(rName, m_vMarks.begin(), m_vMarks.end());
+ }
+
+ IDocumentMarkAccess::const_iterator_t MarkManager::findBookmark(const ::rtl::OUString& rName) const
+ {
+ return lcl_FindMarkByName(rName, m_vBookmarks.begin(), m_vBookmarks.end());
+ }
+
+ IDocumentMarkAccess::const_iterator_t MarkManager::getMarksBegin() const
+ { return m_vMarks.begin(); }
+
+ IDocumentMarkAccess::const_iterator_t MarkManager::getMarksEnd() const
+ { return m_vMarks.end(); }
+
+ sal_Int32 MarkManager::getMarksCount() const
+ { return m_vMarks.size(); }
+
+ IDocumentMarkAccess::const_iterator_t MarkManager::getBookmarksBegin() const
+ { return m_vBookmarks.begin(); }
+
+ IDocumentMarkAccess::const_iterator_t MarkManager::getBookmarksEnd() const
+ { return m_vBookmarks.end(); }
+
+ sal_Int32 MarkManager::getBookmarksCount() const
+ { return m_vBookmarks.size(); }
+
+ IFieldmark* MarkManager::getFieldmarkFor(const SwPosition& rPos) const
+ {
+ const_iterator_t pFieldmark = find_if(
+ m_vFieldmarks.begin(),
+ m_vFieldmarks.end( ),
+ bind(&IMark::IsCoveringPosition, _1, rPos));
+ if(pFieldmark == m_vFieldmarks.end()) return NULL;
+ return dynamic_cast<IFieldmark*>(pFieldmark->get());
+ }
+
+ IFieldmark* MarkManager::getFieldmarkAfter(const SwPosition& rPos) const
+ { return dynamic_cast<IFieldmark*>(lcl_getMarkAfter(m_vFieldmarks, rPos)); }
+
+ IFieldmark* MarkManager::getFieldmarkBefore(const SwPosition& rPos) const
+ { return dynamic_cast<IFieldmark*>(lcl_getMarkBefore(m_vFieldmarks, rPos)); }
+
+
+ ::rtl::OUString MarkManager::getUniqueMarkName(const ::rtl::OUString& rName) const
+ {
+ OSL_ENSURE(rName.getLength(),
+ "<MarkManager::getUniqueMarkName(..)>"
+ " - a name should be proposed");
+ if(findMark(rName) == getMarksEnd()) return rName;
+ ::rtl::OUStringBuffer sBuf;
+ ::rtl::OUString sTmp;
+ for(sal_Int32 nCnt = 1; nCnt < SAL_MAX_INT32; nCnt++)
+ {
+ sTmp = sBuf.append(rName).append(nCnt).makeStringAndClear();
+ if(findMark(sTmp) == getMarksEnd()) break;
+ }
+ return sTmp;
+ }
+
+ void MarkManager::sortMarks()
+ {
+ sort(m_vMarks.begin(), m_vMarks.end(), &lcl_MarkOrderingByStart);
+ sort(m_vBookmarks.begin(), m_vBookmarks.end(), &lcl_MarkOrderingByStart);
+ sort(m_vFieldmarks.begin(), m_vFieldmarks.end(), &lcl_MarkOrderingByStart);
+ }
+
+}} // namespace ::sw::mark
+
+
+#define PCURCRSR (_pCurrCrsr)
+#define FOREACHPAM_START(pSttCrsr) \
+ {\
+ SwPaM *_pStartCrsr = pSttCrsr, *_pCurrCrsr = pSttCrsr; \
+ do {
+
+#define FOREACHPAM_END() \
+ } while( (_pCurrCrsr=(SwPaM *)_pCurrCrsr->GetNext()) != _pStartCrsr ); \
+ }
+#define PCURSH ((SwCrsrShell*)_pStartShell)
+#define FOREACHSHELL_START( pEShell ) \
+ {\
+ ViewShell *_pStartShell = pEShell; \
+ do { \
+ if( _pStartShell->IsA( TYPE( SwCrsrShell )) ) \
+ {
+
+#define FOREACHSHELL_END( pEShell ) \
+ } \
+ } while((_pStartShell=(ViewShell*)_pStartShell->GetNext())!= pEShell ); \
+ }
+
+namespace
+{
+ // Aufbau vom Array: 2 longs,
+ // 1. Long enthaelt Type und Position im DocArray,
+ // 2. die ContentPosition
+ //
+ // CntntType --
+ // 0x8000 = Bookmark Pos1
+ // 0x8001 = Bookmark Pos2
+ // 0x2000 = Absatzgebundener Rahmen
+ // 0x2001 = Auto-Absatzgebundener Rahmen, der umgehaengt werden soll
+ // 0x1000 = Redline Mark
+ // 0x1001 = Redline Point
+ // 0x0800 = Crsr aus der CrsrShell Mark
+ // 0x0801 = Crsr aus der CrsrShell Point
+ // 0x0400 = UnoCrsr Mark
+ // 0x0401 = UnoCrsr Point
+ //
+
+ class _SwSaveTypeCountContent
+ {
+ union {
+ struct { sal_uInt16 nType, nCount; } TC;
+ sal_uLong nTypeCount;
+ } TYPECOUNT;
+ xub_StrLen nContent;
+
+ public:
+ _SwSaveTypeCountContent() { TYPECOUNT.nTypeCount = 0; nContent = 0; }
+ _SwSaveTypeCountContent( sal_uInt16 nType )
+ {
+ SetTypeAndCount( nType, 0 );
+ nContent = 0;
+ }
+ _SwSaveTypeCountContent( const SvULongs& rArr, sal_uInt16& rPos )
+ {
+ TYPECOUNT.nTypeCount = rArr[ rPos++ ];
+ nContent = static_cast<xub_StrLen>(rArr[ rPos++ ]);
+ }
+ void Add( SvULongs& rArr )
+ {
+ rArr.Insert( TYPECOUNT.nTypeCount, rArr.Count() );
+ rArr.Insert( nContent, rArr.Count() );
+ }
+
+ void SetType( sal_uInt16 n ) { TYPECOUNT.TC.nType = n; }
+ sal_uInt16 GetType() const { return TYPECOUNT.TC.nType; }
+ void IncType() { ++TYPECOUNT.TC.nType; }
+ void DecType() { --TYPECOUNT.TC.nType; }
+
+ void SetCount( sal_uInt16 n ) { TYPECOUNT.TC.nCount = n; }
+ sal_uInt16 GetCount() const { return TYPECOUNT.TC.nCount; }
+ sal_uInt16 IncCount() { return ++TYPECOUNT.TC.nCount; }
+ sal_uInt16 DecCount() { return --TYPECOUNT.TC.nCount; }
+
+ void SetTypeAndCount( sal_uInt16 nT, sal_uInt16 nC )
+ { TYPECOUNT.TC.nCount = nC; TYPECOUNT.TC.nType = nT; }
+
+ void SetContent( xub_StrLen n ) { nContent = n; }
+ xub_StrLen GetContent() const { return nContent; }
+ };
+
+ // #i59534: If a paragraph will be splitted we have to restore some redline positions
+ // This help function checks a position compared with a node and an content index
+
+ static const int BEFORE_NODE = 0; // Position before the given node index
+ static const int BEFORE_SAME_NODE = 1; // Same node index but content index before given content index
+ static const int SAME_POSITION = 2; // Same node index and samecontent index
+ static const int BEHIND_SAME_NODE = 3; // Same node index but content index behind given content index
+ static const int BEHIND_NODE = 4; // Position behind the given node index
+
+ static int lcl_RelativePosition( const SwPosition& rPos, sal_uLong nNode, xub_StrLen nCntnt )
+ {
+ sal_uLong nIndex = rPos.nNode.GetIndex();
+ int nReturn = BEFORE_NODE;
+ if( nIndex == nNode )
+ {
+ xub_StrLen nCntIdx = rPos.nContent.GetIndex();
+ if( nCntIdx < nCntnt )
+ nReturn = BEFORE_SAME_NODE;
+ else if( nCntIdx == nCntnt )
+ nReturn = SAME_POSITION;
+ else
+ nReturn = BEHIND_SAME_NODE;
+ }
+ else if( nIndex > nNode )
+ nReturn = BEHIND_NODE;
+ return nReturn;
+ }
+
+
+ static inline int lcl_Greater( const SwPosition& rPos, const SwNodeIndex& rNdIdx, const SwIndex* pIdx )
+ {
+ return rPos.nNode > rNdIdx || ( pIdx && rPos.nNode == rNdIdx && rPos.nContent > pIdx->GetIndex() );
+ }
+
+ static void lcl_ChkPaM( SvULongs& rSaveArr, sal_uLong nNode, xub_StrLen nCntnt,
+ const SwPaM& rPam, _SwSaveTypeCountContent& rSave,
+ sal_Bool bChkSelDirection )
+ {
+ // SelektionsRichtung beachten
+ bool bBound1IsStart = !bChkSelDirection ? sal_True :
+ ( *rPam.GetPoint() < *rPam.GetMark()
+ ? rPam.GetPoint() == &rPam.GetBound()
+ : rPam.GetMark() == &rPam.GetBound());
+
+ const SwPosition* pPos = &rPam.GetBound( sal_True );
+ if( pPos->nNode.GetIndex() == nNode &&
+ ( bBound1IsStart ? pPos->nContent.GetIndex() < nCntnt
+ : pPos->nContent.GetIndex() <= nCntnt ))
+ {
+ rSave.SetContent( pPos->nContent.GetIndex() );
+ rSave.Add( rSaveArr );
+ }
+
+ pPos = &rPam.GetBound( sal_False );
+ if( pPos->nNode.GetIndex() == nNode &&
+ ( (bBound1IsStart && bChkSelDirection)
+ ? pPos->nContent.GetIndex() <= nCntnt
+ : pPos->nContent.GetIndex() < nCntnt ))
+ {
+ rSave.SetContent( pPos->nContent.GetIndex() );
+ rSave.IncType();
+ rSave.Add( rSaveArr );
+ rSave.DecType();
+ }
+ }
+
+}
+
+
+// IDocumentMarkAccess for SwDoc
+
+IDocumentMarkAccess* SwDoc::getIDocumentMarkAccess()
+ { return static_cast< IDocumentMarkAccess* >(pMarkManager.get()); }
+
+const IDocumentMarkAccess* SwDoc::getIDocumentMarkAccess() const
+ { return static_cast< IDocumentMarkAccess* >(pMarkManager.get()); }
+
+// SaveBookmark
+
+SaveBookmark::SaveBookmark(
+ bool bSavePos,
+ bool bSaveOtherPos,
+ const IMark& rBkmk,
+ const SwNodeIndex & rMvPos,
+ const SwIndex* pIdx)
+ : m_aName(rBkmk.GetName())
+ , m_aShortName()
+ , m_aCode()
+ , m_bSavePos(bSavePos)
+ , m_bSaveOtherPos(bSaveOtherPos)
+ , m_eOrigBkmType(IDocumentMarkAccess::GetType(rBkmk))
+{
+ const IBookmark* const pBookmark = dynamic_cast< const IBookmark* >(&rBkmk);
+ if(pBookmark)
+ {
+ m_aShortName = pBookmark->GetShortName();
+ m_aCode = pBookmark->GetKeyCode();
+
+ ::sfx2::Metadatable const*const pMetadatable(
+ dynamic_cast< ::sfx2::Metadatable const* >(pBookmark));
+ if (pMetadatable)
+ {
+ m_pMetadataUndo = pMetadatable->CreateUndo();
+ }
+ }
+ m_nNode1 = rBkmk.GetMarkPos().nNode.GetIndex();
+ m_nCntnt1 = rBkmk.GetMarkPos().nContent.GetIndex();
+
+ if(m_bSavePos)
+ {
+ m_nNode1 -= rMvPos.GetIndex();
+ if(pIdx && !m_nNode1)
+ m_nCntnt1 -= pIdx->GetIndex();
+ }
+
+ if(rBkmk.IsExpanded())
+ {
+ m_nNode2 = rBkmk.GetOtherMarkPos().nNode.GetIndex();
+ m_nCntnt2 = rBkmk.GetOtherMarkPos().nContent.GetIndex();
+
+ if(m_bSaveOtherPos)
+ {
+ m_nNode2 -= rMvPos.GetIndex();
+ if(pIdx && !m_nNode2)
+ m_nCntnt2 -= pIdx->GetIndex();
+ }
+ }
+ else
+ m_nNode2 = ULONG_MAX, m_nCntnt2 = STRING_NOTFOUND;
+}
+
+void SaveBookmark::SetInDoc(
+ SwDoc* pDoc,
+ const SwNodeIndex& rNewPos,
+ const SwIndex* pIdx)
+{
+ SwPaM aPam(rNewPos.GetNode());
+ if(pIdx)
+ aPam.GetPoint()->nContent = *pIdx;
+
+ if(ULONG_MAX != m_nNode2)
+ {
+ aPam.SetMark();
+
+ if(m_bSaveOtherPos)
+ {
+ aPam.GetMark()->nNode += m_nNode2;
+ if(pIdx && !m_nNode2)
+ aPam.GetMark()->nContent += m_nCntnt2;
+ else
+ aPam.GetMark()->nContent.Assign(aPam.GetCntntNode(sal_False), m_nCntnt2);
+ }
+ else
+ {
+ aPam.GetMark()->nNode = m_nNode2;
+ aPam.GetMark()->nContent.Assign(aPam.GetCntntNode(sal_False), m_nCntnt2);
+ }
+ }
+
+ if(m_bSavePos)
+ {
+ aPam.GetPoint()->nNode += m_nNode1;
+
+ if(pIdx && !m_nNode1)
+ aPam.GetPoint()->nContent += m_nCntnt1;
+ else
+ aPam.GetPoint()->nContent.Assign(aPam.GetCntntNode(), m_nCntnt1);
+ }
+ else
+ {
+ aPam.GetPoint()->nNode = m_nNode1;
+ aPam.GetPoint()->nContent.Assign(aPam.GetCntntNode(), m_nCntnt1);
+ }
+
+ if(!aPam.HasMark()
+ || CheckNodesRange(aPam.GetPoint()->nNode, aPam.GetMark()->nNode, sal_True))
+ {
+ ::sw::mark::IBookmark* const pBookmark = dynamic_cast< ::sw::mark::IBookmark* >(pDoc->getIDocumentMarkAccess()->makeMark(aPam, m_aName, m_eOrigBkmType));
+ if(pBookmark)
+ {
+ pBookmark->SetKeyCode(m_aCode);
+ pBookmark->SetShortName(m_aShortName);
+ if (m_pMetadataUndo)
+ {
+ ::sfx2::Metadatable * const pMeta(
+ dynamic_cast< ::sfx2::Metadatable* >(pBookmark));
+ OSL_ENSURE(pMeta, "metadata undo, but not metadatable?");
+ if (pMeta)
+ {
+ pMeta->RestoreMetadata(m_pMetadataUndo);
+ }
+ }
+ }
+ }
+}
+
+// _DelBookmarks, _{Save,Restore}CntntIdx
+
+void _DelBookmarks(
+ const SwNodeIndex& rStt,
+ const SwNodeIndex& rEnd,
+ ::std::vector<SaveBookmark> * pSaveBkmk,
+ const SwIndex* pSttIdx,
+ const SwIndex* pEndIdx)
+{
+ // illegal range ??
+ if(rStt.GetIndex() > rEnd.GetIndex()
+ || (rStt == rEnd && (!pSttIdx || pSttIdx->GetIndex() >= pEndIdx->GetIndex())))
+ return;
+ SwDoc* const pDoc = rStt.GetNode().GetDoc();
+
+ pDoc->getIDocumentMarkAccess()->deleteMarks(rStt, rEnd, pSaveBkmk, pSttIdx, pEndIdx);
+
+ // kopiere alle Redlines, die im Move Bereich stehen in ein
+ // Array, das alle Angaben auf die Position als Offset speichert.
+ // Die neue Zuordung erfolgt nach dem Moven.
+ SwRedlineTbl& rTbl = (SwRedlineTbl&)pDoc->GetRedlineTbl();
+ for(sal_uInt16 nCnt = 0; nCnt < rTbl.Count(); ++nCnt )
+ {
+ // liegt auf der Position ??
+ SwRedline* pRedl = rTbl[ nCnt ];
+
+ SwPosition *pRStt = &pRedl->GetBound(sal_True),
+ *pREnd = &pRedl->GetBound(sal_False);
+ if( *pRStt > *pREnd )
+ {
+ SwPosition *pTmp = pRStt; pRStt = pREnd, pREnd = pTmp;
+ }
+
+ if( lcl_Greater( *pRStt, rStt, pSttIdx ) && lcl_Lower( *pRStt, rEnd, pEndIdx ))
+ {
+ pRStt->nNode = rEnd;
+ if( pEndIdx )
+ pRStt->nContent = *pEndIdx;
+ else
+ {
+ sal_Bool bStt = sal_True;
+ SwCntntNode* pCNd = pRStt->nNode.GetNode().GetCntntNode();
+ if( !pCNd && 0 == ( pCNd = pDoc->GetNodes().GoNext( &pRStt->nNode )) )
+ {
+ bStt = sal_False;
+ pRStt->nNode = rStt;
+ if( 0 == ( pCNd = pDoc->GetNodes().GoPrevious( &pRStt->nNode )) )
+ {
+ pRStt->nNode = pREnd->nNode;
+ pCNd = pRStt->nNode.GetNode().GetCntntNode();
+ }
+ }
+ xub_StrLen nTmp = bStt ? 0 : pCNd->Len();
+ pRStt->nContent.Assign( pCNd, nTmp );
+ }
+ }
+ if( lcl_Greater( *pREnd, rStt, pSttIdx ) && lcl_Lower( *pREnd, rEnd, pEndIdx ))
+ {
+ pREnd->nNode = rStt;
+ if( pSttIdx )
+ pREnd->nContent = *pSttIdx;
+ else
+ {
+ sal_Bool bStt = sal_False;
+ SwCntntNode* pCNd = pREnd->nNode.GetNode().GetCntntNode();
+ if( !pCNd && 0 == ( pCNd = pDoc->GetNodes().GoPrevious( &pREnd->nNode )) )
+ {
+ bStt = sal_True;
+ pREnd->nNode = rEnd;
+ if( 0 == ( pCNd = pDoc->GetNodes().GoNext( &pREnd->nNode )) )
+ {
+ pREnd->nNode = pRStt->nNode;
+ pCNd = pREnd->nNode.GetNode().GetCntntNode();
+ }
+ }
+ xub_StrLen nTmp = bStt ? 0 : pCNd->Len();
+ pREnd->nContent.Assign( pCNd, nTmp );
+ }
+ }
+ }
+}
+
+void _SaveCntntIdx(SwDoc* pDoc,
+ sal_uLong nNode,
+ xub_StrLen nCntnt,
+ SvULongs& rSaveArr,
+ sal_uInt8 nSaveFly)
+{
+ // 1. Bookmarks
+ _SwSaveTypeCountContent aSave;
+ aSave.SetTypeAndCount( 0x8000, 0 );
+
+ IDocumentMarkAccess* const pMarkAccess = pDoc->getIDocumentMarkAccess();
+ const sal_Int32 nBkmks = pMarkAccess->getMarksCount();
+ for(; aSave.GetCount() < nBkmks; aSave.IncCount())
+ {
+ bool bEqual = false;
+ bool bLower = false;
+ const ::sw::mark::IMark* pBkmk = (pMarkAccess->getMarksBegin() + aSave.GetCount())->get();
+ if(pBkmk->GetMarkPos().nNode.GetIndex() == nNode
+ && pBkmk->GetMarkPos().nContent.GetIndex() <= nCntnt)
+ {
+ if(pBkmk->GetMarkPos().nContent.GetIndex() < nCntnt)
+ {
+ bLower = true; // a hint for the other position...
+ aSave.SetContent(pBkmk->GetMarkPos().nContent.GetIndex());
+ aSave.Add(rSaveArr);
+ }
+ else // if a bookmark position is equal nCntnt, the other position
+ bEqual = true; // has to decide if it is added to the array
+ }
+
+ if(pBkmk->IsExpanded()
+ && pBkmk->GetOtherMarkPos().nNode.GetIndex() == nNode
+ && pBkmk->GetOtherMarkPos().nContent.GetIndex() <= nCntnt)
+ {
+ if(bLower || pBkmk->GetOtherMarkPos().nContent.GetIndex() < nCntnt)
+ {
+ if(bEqual)
+ { // the other position is before, the (main) position is equal
+ aSave.SetContent(pBkmk->GetMarkPos().nContent.GetIndex());
+ aSave.Add(rSaveArr);
+ }
+ aSave.SetContent(pBkmk->GetOtherMarkPos().nContent.GetIndex());
+ aSave.IncType();
+ aSave.Add(rSaveArr);
+ aSave.DecType();
+ }
+ }
+ }
+
+ // 2. Redlines
+ aSave.SetTypeAndCount( 0x1000, 0 );
+ const SwRedlineTbl& rRedlTbl = pDoc->GetRedlineTbl();
+ for( ; aSave.GetCount() < rRedlTbl.Count(); aSave.IncCount() )
+ {
+ const SwRedline* pRdl = rRedlTbl[ aSave.GetCount() ];
+ int nPointPos = lcl_RelativePosition( *pRdl->GetPoint(), nNode, nCntnt );
+ int nMarkPos = pRdl->HasMark() ? lcl_RelativePosition( *pRdl->GetMark(), nNode, nCntnt ) :
+ nPointPos;
+ // #i59534: We have to store the positions inside the same node before the insert position
+ // and the one at the insert position if the corresponding Point/Mark position is before
+ // the insert position.
+ if( nPointPos == BEFORE_SAME_NODE ||
+ ( nPointPos == SAME_POSITION && nMarkPos < SAME_POSITION ) )
+ {
+ aSave.SetContent( pRdl->GetPoint()->nContent.GetIndex() );
+ aSave.IncType();
+ aSave.Add( rSaveArr );
+ aSave.DecType();
+ }
+ if( pRdl->HasMark() && ( nMarkPos == BEFORE_SAME_NODE ||
+ ( nMarkPos == SAME_POSITION && nPointPos < SAME_POSITION ) ) )
+ {
+ aSave.SetContent( pRdl->GetMark()->nContent.GetIndex() );
+ aSave.Add( rSaveArr );
+ }
+ }
+
+ // 4. Absatzgebundene Objekte
+ {
+ SwCntntNode *pNode = pDoc->GetNodes()[nNode]->GetCntntNode();
+ if( pNode )
+ {
+
+ SwFrm* pFrm = pNode->getLayoutFrm( pDoc->GetCurrentLayout() );
+#if OSL_DEBUG_LEVEL > 1
+ static sal_Bool bViaDoc = sal_False;
+ if( bViaDoc )
+ pFrm = NULL;
+#endif
+ if( pFrm ) // gibt es ein Layout? Dann ist etwas billiger...
+ {
+ if( pFrm->GetDrawObjs() )
+ {
+ const SwSortedObjs& rDObj = *pFrm->GetDrawObjs();
+ for( sal_uInt32 n = rDObj.Count(); n; )
+ {
+ SwAnchoredObject* pObj = rDObj[ --n ];
+ const SwFrmFmt& rFmt = pObj->GetFrmFmt();
+ const SwFmtAnchor& rAnchor = rFmt.GetAnchor();
+ SwPosition const*const pAPos = rAnchor.GetCntntAnchor();
+ if ( pAPos &&
+ ( ( nSaveFly &&
+ FLY_AT_PARA == rAnchor.GetAnchorId() ) ||
+ ( FLY_AT_CHAR == rAnchor.GetAnchorId() ) ) )
+ {
+ aSave.SetType( 0x2000 );
+ aSave.SetContent( pAPos->nContent.GetIndex() );
+
+ OSL_ENSURE( nNode == pAPos->nNode.GetIndex(),
+ "_SaveCntntIdx: Wrong Node-Index" );
+ if ( FLY_AT_CHAR == rAnchor.GetAnchorId() )
+ {
+ if( nCntnt <= aSave.GetContent() )
+ {
+ if( SAVEFLY_SPLIT == nSaveFly )
+ aSave.IncType(); // = 0x2001;
+ else
+ continue;
+ }
+ }
+ aSave.SetCount( pDoc->GetSpzFrmFmts()->Count() );
+ while( aSave.GetCount() &&
+ &rFmt != (*pDoc->GetSpzFrmFmts())[
+ aSave.DecCount() ] )
+ ; // nothing
+ OSL_ENSURE( &rFmt == (*pDoc->GetSpzFrmFmts())[
+ aSave.GetCount() ],
+ "_SaveCntntIdx: Lost FrameFormat" );
+ aSave.Add( rSaveArr );
+ }
+ }
+ }
+ }
+ else // Schade, kein Layout, dann ist es eben etwas teurer...
+ {
+ for( aSave.SetCount( pDoc->GetSpzFrmFmts()->Count() );
+ aSave.GetCount() ; )
+ {
+ SwFrmFmt* pFrmFmt = (*pDoc->GetSpzFrmFmts())[
+ aSave.DecCount() ];
+ if ( RES_FLYFRMFMT != pFrmFmt->Which() &&
+ RES_DRAWFRMFMT != pFrmFmt->Which() )
+ continue;
+
+ const SwFmtAnchor& rAnchor = pFrmFmt->GetAnchor();
+ SwPosition const*const pAPos = rAnchor.GetCntntAnchor();
+ if ( pAPos && ( nNode == pAPos->nNode.GetIndex() ) &&
+ ( FLY_AT_PARA == rAnchor.GetAnchorId() ||
+ FLY_AT_CHAR == rAnchor.GetAnchorId() ) )
+ {
+ aSave.SetType( 0x2000 );
+ aSave.SetContent( pAPos->nContent.GetIndex() );
+ if ( FLY_AT_CHAR == rAnchor.GetAnchorId() )
+ {
+ if( nCntnt <= aSave.GetContent() )
+ {
+ if( SAVEFLY_SPLIT == nSaveFly )
+ aSave.IncType(); // = 0x2001;
+ else
+ continue;
+ }
+ }
+ aSave.Add( rSaveArr );
+ }
+ }
+ }
+ }
+ }
+ // 5. CrsrShell
+ {
+ SwCrsrShell* pShell = pDoc->GetEditShell();
+ if( pShell )
+ {
+ aSave.SetTypeAndCount( 0x800, 0 );
+ FOREACHSHELL_START( pShell )
+ SwPaM *_pStkCrsr = PCURSH->GetStkCrsr();
+ if( _pStkCrsr )
+ do {
+ lcl_ChkPaM( rSaveArr, nNode, nCntnt, *_pStkCrsr,
+ aSave, sal_False );
+ aSave.IncCount();
+ } while ( (_pStkCrsr != 0 ) &&
+ ((_pStkCrsr=(SwPaM *)_pStkCrsr->GetNext()) != PCURSH->GetStkCrsr()) );
+
+ FOREACHPAM_START( PCURSH->_GetCrsr() )
+ lcl_ChkPaM( rSaveArr, nNode, nCntnt, *PCURCRSR,
+ aSave, sal_False );
+ aSave.IncCount();
+ FOREACHPAM_END()
+
+ FOREACHSHELL_END( pShell )
+ }
+ }
+ // 6. UnoCrsr
+ {
+ aSave.SetTypeAndCount( 0x400, 0 );
+ const SwUnoCrsrTbl& rTbl = pDoc->GetUnoCrsrTbl();
+ for( sal_uInt16 n = 0; n < rTbl.Count(); ++n )
+ {
+ FOREACHPAM_START( rTbl[ n ] )
+ lcl_ChkPaM( rSaveArr, nNode, nCntnt, *PCURCRSR, aSave, sal_False );
+ aSave.IncCount();
+ FOREACHPAM_END()
+
+ SwUnoTableCrsr* pUnoTblCrsr =
+ dynamic_cast<SwUnoTableCrsr*>(rTbl[ n ]);
+ if( pUnoTblCrsr )
+ {
+ FOREACHPAM_START( &pUnoTblCrsr->GetSelRing() )
+ lcl_ChkPaM( rSaveArr, nNode, nCntnt, *PCURCRSR, aSave, sal_False );
+ aSave.IncCount();
+ FOREACHPAM_END()
+ }
+ }
+ }
+}
+
+
+void _RestoreCntntIdx(SwDoc* pDoc,
+ SvULongs& rSaveArr,
+ sal_uLong nNode,
+ xub_StrLen nOffset,
+ sal_Bool bAuto)
+{
+ SwCntntNode* pCNd = pDoc->GetNodes()[ nNode ]->GetCntntNode();
+ const SwRedlineTbl& rRedlTbl = pDoc->GetRedlineTbl();
+ SwSpzFrmFmts* pSpz = pDoc->GetSpzFrmFmts();
+ IDocumentMarkAccess* const pMarkAccess = pDoc->getIDocumentMarkAccess();
+ sal_uInt16 n = 0;
+ while( n < rSaveArr.Count() )
+ {
+ _SwSaveTypeCountContent aSave( rSaveArr, n );
+ SwPosition* pPos = 0;
+ switch( aSave.GetType() )
+ {
+ case 0x8000:
+ {
+ MarkBase* pMark = dynamic_cast<MarkBase*>(pMarkAccess->getMarksBegin()[aSave.GetCount()].get());
+ SwPosition aNewPos(pMark->GetMarkPos());
+ aNewPos.nNode = *pCNd;
+ aNewPos.nContent.Assign(pCNd, aSave.GetContent() + nOffset);
+ pMark->SetMarkPos(aNewPos);
+ }
+ break;
+ case 0x8001:
+ {
+ MarkBase* pMark = dynamic_cast<MarkBase*>(pMarkAccess->getMarksBegin()[aSave.GetCount()].get());
+ SwPosition aNewPos(pMark->GetOtherMarkPos());
+ aNewPos.nNode = *pCNd;
+ aNewPos.nContent.Assign(pCNd, aSave.GetContent() + nOffset);
+ pMark->SetOtherMarkPos(aNewPos);
+ }
+ break;
+ case 0x1001:
+ pPos = (SwPosition*)rRedlTbl[ aSave.GetCount() ]->GetPoint();
+ break;
+ case 0x1000:
+ pPos = (SwPosition*)rRedlTbl[ aSave.GetCount() ]->GetMark();
+ break;
+ case 0x2000:
+ {
+ SwFrmFmt *pFrmFmt = (*pSpz)[ aSave.GetCount() ];
+ const SwFmtAnchor& rFlyAnchor = pFrmFmt->GetAnchor();
+ if( rFlyAnchor.GetCntntAnchor() )
+ {
+ SwFmtAnchor aNew( rFlyAnchor );
+ SwPosition aNewPos( *rFlyAnchor.GetCntntAnchor() );
+ aNewPos.nNode = *pCNd;
+ if ( FLY_AT_CHAR == rFlyAnchor.GetAnchorId() )
+ {
+ aNewPos.nContent.Assign( pCNd,
+ aSave.GetContent() + nOffset );
+ }
+ else
+ {
+ aNewPos.nContent.Assign( 0, 0 );
+ }
+ aNew.SetAnchor( &aNewPos );
+ pFrmFmt->SetFmtAttr( aNew );
+ }
+ }
+ break;
+ case 0x2001:
+ if( bAuto )
+ {
+ SwFrmFmt *pFrmFmt = (*pSpz)[ aSave.GetCount() ];
+ SfxPoolItem *pAnchor = (SfxPoolItem*)&pFrmFmt->GetAnchor();
+ pFrmFmt->NotifyClients( pAnchor, pAnchor );
+ }
+ break;
+
+ case 0x0800:
+ case 0x0801:
+ {
+ SwCrsrShell* pShell = pDoc->GetEditShell();
+ if( pShell )
+ {
+ sal_uInt16 nCnt = 0;
+ FOREACHSHELL_START( pShell )
+ SwPaM *_pStkCrsr = PCURSH->GetStkCrsr();
+ if( _pStkCrsr )
+ do {
+ if( aSave.GetCount() == nCnt )
+ {
+ pPos = &_pStkCrsr->GetBound( 0x0800 ==
+ aSave.GetType() );
+ break;
+ }
+ ++nCnt;
+ } while ( (_pStkCrsr != 0 ) &&
+ ((_pStkCrsr=(SwPaM *)_pStkCrsr->GetNext()) != PCURSH->GetStkCrsr()) );
+
+ if( pPos )
+ break;
+
+ FOREACHPAM_START( PCURSH->_GetCrsr() )
+ if( aSave.GetCount() == nCnt )
+ {
+ pPos = &PCURCRSR->GetBound( 0x0800 ==
+ aSave.GetType() );
+ break;
+ }
+ ++nCnt;
+ FOREACHPAM_END()
+ if( pPos )
+ break;
+
+ FOREACHSHELL_END( pShell )
+ }
+ }
+ break;
+
+ case 0x0400:
+ case 0x0401:
+ {
+ sal_uInt16 nCnt = 0;
+ const SwUnoCrsrTbl& rTbl = pDoc->GetUnoCrsrTbl();
+ for( sal_uInt16 i = 0; i < rTbl.Count(); ++i )
+ {
+ FOREACHPAM_START( rTbl[ i ] )
+ if( aSave.GetCount() == nCnt )
+ {
+ pPos = &PCURCRSR->GetBound( 0x0400 ==
+ aSave.GetType() );
+ break;
+ }
+ ++nCnt;
+ FOREACHPAM_END()
+ if( pPos )
+ break;
+
+ SwUnoTableCrsr* pUnoTblCrsr =
+ dynamic_cast<SwUnoTableCrsr*>(rTbl[ i ]);
+ if ( pUnoTblCrsr )
+ {
+ FOREACHPAM_START( &pUnoTblCrsr->GetSelRing() )
+ if( aSave.GetCount() == nCnt )
+ {
+ pPos = &PCURCRSR->GetBound( 0x0400 ==
+ aSave.GetType() );
+ break;
+ }
+ ++nCnt;
+ FOREACHPAM_END()
+ }
+ if ( pPos )
+ break;
+ }
+ }
+ break;
+ }
+
+ if( pPos )
+ {
+ pPos->nNode = *pCNd;
+ pPos->nContent.Assign( pCNd, aSave.GetContent() + nOffset );
+ }
+ }
+}
+
+void _RestoreCntntIdx(SvULongs& rSaveArr,
+ const SwNode& rNd,
+ xub_StrLen nLen,
+ xub_StrLen nChkLen)
+{
+ const SwDoc* pDoc = rNd.GetDoc();
+ const SwRedlineTbl& rRedlTbl = pDoc->GetRedlineTbl();
+ const SwSpzFrmFmts* pSpz = pDoc->GetSpzFrmFmts();
+ const IDocumentMarkAccess* const pMarkAccess = pDoc->getIDocumentMarkAccess();
+ SwCntntNode* pCNd = (SwCntntNode*)rNd.GetCntntNode();
+
+ sal_uInt16 n = 0;
+ while( n < rSaveArr.Count() )
+ {
+ _SwSaveTypeCountContent aSave( rSaveArr, n );
+ if( aSave.GetContent() >= nChkLen )
+ rSaveArr[ n-1 ] -= nChkLen;
+ else
+ {
+ SwPosition* pPos = 0;
+ switch( aSave.GetType() )
+ {
+ case 0x8000:
+ {
+ MarkBase* pMark = dynamic_cast<MarkBase*>(pMarkAccess->getMarksBegin()[aSave.GetCount()].get());
+ SwPosition aNewPos(pMark->GetMarkPos());
+ aNewPos.nNode = rNd;
+ aNewPos.nContent.Assign(pCNd, Min(aSave.GetContent(), nLen));
+ pMark->SetMarkPos(aNewPos);
+ }
+ break;
+ case 0x8001:
+ {
+ MarkBase* pMark = dynamic_cast<MarkBase*>(pMarkAccess->getMarksBegin()[aSave.GetCount()].get());
+ SwPosition aNewPos(pMark->GetOtherMarkPos());
+ aNewPos.nNode = rNd;
+ aNewPos.nContent.Assign(pCNd, Min(aSave.GetContent(), nLen));
+ pMark->SetOtherMarkPos(aNewPos);
+ }
+ break;
+ case 0x1001:
+ pPos = (SwPosition*)rRedlTbl[ aSave.GetCount() ]->GetPoint();
+ break;
+ case 0x1000:
+ pPos = (SwPosition*)rRedlTbl[ aSave.GetCount() ]->GetMark();
+ break;
+ case 0x2000:
+ case 0x2001:
+ {
+ SwFrmFmt *pFrmFmt = (*pSpz)[ aSave.GetCount() ];
+ const SwFmtAnchor& rFlyAnchor = pFrmFmt->GetAnchor();
+ if( rFlyAnchor.GetCntntAnchor() )
+ {
+ SwFmtAnchor aNew( rFlyAnchor );
+ SwPosition aNewPos( *rFlyAnchor.GetCntntAnchor() );
+ aNewPos.nNode = rNd;
+ if ( FLY_AT_CHAR == rFlyAnchor.GetAnchorId() )
+ {
+ aNewPos.nContent.Assign( pCNd, Min(
+ aSave.GetContent(), nLen ) );
+ }
+ else
+ {
+ aNewPos.nContent.Assign( 0, 0 );
+ }
+ aNew.SetAnchor( &aNewPos );
+ pFrmFmt->SetFmtAttr( aNew );
+ }
+ }
+ break;
+
+ case 0x0800:
+ case 0x0801:
+ {
+ SwCrsrShell* pShell = pDoc->GetEditShell();
+ if( pShell )
+ {
+ sal_uInt16 nCnt = 0;
+ FOREACHSHELL_START( pShell )
+ SwPaM *_pStkCrsr = PCURSH->GetStkCrsr();
+ if( _pStkCrsr )
+ do {
+ if( aSave.GetCount() == nCnt )
+ {
+ pPos = &_pStkCrsr->GetBound( 0x0800 ==
+ aSave.GetType() );
+ break;
+ }
+ ++nCnt;
+ } while ( (_pStkCrsr != 0 ) &&
+ ((_pStkCrsr=(SwPaM *)_pStkCrsr->GetNext()) != PCURSH->GetStkCrsr()) );
+
+ if( pPos )
+ break;
+
+ FOREACHPAM_START( PCURSH->_GetCrsr() )
+ if( aSave.GetCount() == nCnt )
+ {
+ pPos = &PCURCRSR->GetBound( 0x0800 ==
+ aSave.GetType() );
+ break;
+ }
+ ++nCnt;
+ FOREACHPAM_END()
+ if( pPos )
+ break;
+
+ FOREACHSHELL_END( pShell )
+ }
+ }
+ break;
+
+ case 0x0400:
+ case 0x0401:
+ {
+ sal_uInt16 nCnt = 0;
+ const SwUnoCrsrTbl& rTbl = pDoc->GetUnoCrsrTbl();
+ for( sal_uInt16 i = 0; i < rTbl.Count(); ++i )
+ {
+ FOREACHPAM_START( rTbl[ i ] )
+ if( aSave.GetCount() == nCnt )
+ {
+ pPos = &PCURCRSR->GetBound( 0x0400 ==
+ aSave.GetType() );
+ break;
+ }
+ ++nCnt;
+ FOREACHPAM_END()
+ if( pPos )
+ break;
+
+ SwUnoTableCrsr* pUnoTblCrsr =
+ dynamic_cast<SwUnoTableCrsr*>(rTbl[ i ]);
+ if ( pUnoTblCrsr )
+ {
+ FOREACHPAM_START( &pUnoTblCrsr->GetSelRing() )
+ if( aSave.GetCount() == nCnt )
+ {
+ pPos = &PCURCRSR->GetBound( 0x0400 ==
+ aSave.GetType() );
+ break;
+ }
+ ++nCnt;
+ FOREACHPAM_END()
+ }
+ if ( pPos )
+ break;
+ }
+ }
+ break;
+ }
+
+ if( pPos )
+ {
+ pPos->nNode = rNd;
+ pPos->nContent.Assign( pCNd, Min( aSave.GetContent(), nLen ) );
+ }
+ n -= 2;
+ rSaveArr.Remove( n, 2 );
+ }
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/doc/docchart.cxx b/sw/source/core/doc/docchart.cxx
new file mode 100644
index 000000000000..7297413eb239
--- /dev/null
+++ b/sw/source/core/doc/docchart.cxx
@@ -0,0 +1,278 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+
+#include <com/sun/star/frame/XModel.hpp>
+
+#include <com/sun/star/chart2/XChartDocument.hpp>
+
+#include <float.h>
+#include <hintids.hxx>
+#include <vcl/window.hxx>
+#include <doc.hxx>
+#include <docary.hxx>
+#include <ndindex.hxx>
+#include <swtable.hxx>
+#include <ndtxt.hxx>
+#include <calc.hxx>
+#include <frmfmt.hxx>
+#include <cellfml.hxx>
+#include <viewsh.hxx>
+#include <ndole.hxx>
+#include <calbck.hxx>
+#include <cntfrm.hxx>
+#include <swtblfmt.hxx>
+#include <tblsel.hxx>
+#include <cellatr.hxx>
+#include <osl/mutex.hxx>
+#include <vcl/svapp.hxx>
+
+#include <unochart.hxx>
+
+using namespace com::sun::star;
+using namespace com::sun::star::uno;
+
+
+void SwTable::UpdateCharts() const
+{
+ GetFrmFmt()->GetDoc()->UpdateCharts( GetFrmFmt()->GetName() );
+}
+
+sal_Bool SwTable::IsTblComplexForChart( const String& rSelection,
+ SwChartLines* pGetCLines ) const
+{
+ const SwTableBox* pSttBox, *pEndBox;
+ if( 2 < rSelection.Len() )
+ {
+ // spitze Klammern am Anfang & Ende enfernen
+ String sBox( rSelection );
+ if( '<' == sBox.GetChar( 0 ) ) sBox.Erase( 0, 1 );
+ if( '>' == sBox.GetChar( sBox.Len()-1 ) ) sBox.Erase( sBox.Len()-1 );
+
+ xub_StrLen nTrenner = sBox.Search( ':' );
+ OSL_ENSURE( STRING_NOTFOUND != nTrenner, "keine gueltige Selektion" );
+
+ pSttBox = GetTblBox( sBox.Copy( 0, nTrenner ));
+ pEndBox = GetTblBox( sBox.Copy( nTrenner+1 ));
+ }
+ else
+ {
+ const SwTableLines* pLns = &GetTabLines();
+ pSttBox = (*pLns)[ 0 ]->GetTabBoxes()[ 0 ];
+ while( !pSttBox->GetSttNd() )
+ // bis zur Content Box!
+ pSttBox = pSttBox->GetTabLines()[ 0 ]->GetTabBoxes()[ 0 ];
+
+ const SwTableBoxes* pBoxes = &(*pLns)[ pLns->Count()-1 ]->GetTabBoxes();
+ pEndBox = (*pBoxes)[ pBoxes->Count()-1 ];
+ while( !pEndBox->GetSttNd() )
+ {
+ // bis zur Content Box!
+ pLns = &pEndBox->GetTabLines();
+ pBoxes = &(*pLns)[ pLns->Count()-1 ]->GetTabBoxes();
+ pEndBox = (*pBoxes)[ pBoxes->Count()-1 ];
+ }
+ }
+
+ return !pSttBox || !pEndBox || !::ChkChartSel( *pSttBox->GetSttNd(),
+ *pEndBox->GetSttNd(), pGetCLines );
+}
+
+
+
+IMPL_LINK( SwDoc, DoUpdateAllCharts, Timer *, EMPTYARG )
+{
+ ViewShell* pVSh;
+ GetEditShell( &pVSh );
+ if( pVSh )
+ {
+ const SwFrmFmts& rTblFmts = *GetTblFrmFmts();
+ for( sal_uInt16 n = 0; n < rTblFmts.Count(); ++n )
+ {
+ SwTable* pTmpTbl;
+ const SwTableNode* pTblNd;
+ SwFrmFmt* pFmt = rTblFmts[ n ];
+
+ if( 0 != ( pTmpTbl = SwTable::FindTable( pFmt ) ) &&
+ 0 != ( pTblNd = pTmpTbl->GetTableNode() ) &&
+ pTblNd->GetNodes().IsDocNodes() )
+ {
+ _UpdateCharts( *pTmpTbl, *pVSh );
+ }
+ }
+ }
+ return 0;
+}
+
+void SwDoc::_UpdateCharts( const SwTable& rTbl, ViewShell& rVSh ) const
+{
+ String aName( rTbl.GetFrmFmt()->GetName() );
+ SwOLENode *pONd;
+ SwStartNode *pStNd;
+ SwNodeIndex aIdx( *GetNodes().GetEndOfAutotext().StartOfSectionNode(), 1 );
+ while( 0 != (pStNd = aIdx.GetNode().GetStartNode()) )
+ {
+ aIdx++;
+ SwFrm* pFrm;
+ if( 0 != ( pONd = aIdx.GetNode().GetOLENode() ) &&
+ aName.Equals( pONd->GetChartTblName() ) &&
+ 0 != ( pFrm = pONd->getLayoutFrm( rVSh.GetLayout() ) ) )
+ {
+ SwChartDataProvider *pPCD = GetChartDataProvider();
+ if (pPCD)
+ pPCD->InvalidateTable( &rTbl );
+ // following this the framework will now take care of repainting
+ // the chart or it's replacement image...
+ }
+ aIdx.Assign( *pStNd->EndOfSectionNode(), + 1 );
+ }
+}
+
+void SwDoc::UpdateCharts( const String &rName ) const
+{
+ SwTable* pTmpTbl = SwTable::FindTable( FindTblFmtByName( rName ) );
+ if( pTmpTbl )
+ {
+ ViewShell* pVSh;
+ GetEditShell( &pVSh );
+
+ if( pVSh )
+ _UpdateCharts( *pTmpTbl, *pVSh );
+ }
+}
+
+void SwDoc::SetTableName( SwFrmFmt& rTblFmt, const String &rNewName )
+{
+// sal_Bool bStop = 1;
+
+ const String aOldName( rTblFmt.GetName() );
+
+ sal_Bool bNameFound = 0 == rNewName.Len();
+ if( !bNameFound )
+ {
+ SwFrmFmt* pFmt;
+ const SwFrmFmts& rTbl = *GetTblFrmFmts();
+ for( sal_uInt16 i = rTbl.Count(); i; )
+ if( !( pFmt = rTbl[ --i ] )->IsDefault() &&
+ pFmt->GetName() == rNewName && IsUsed( *pFmt ) )
+ {
+ bNameFound = sal_True;
+ break;
+ }
+ }
+
+ if( !bNameFound )
+ rTblFmt.SetName( rNewName, sal_True );
+ else
+ rTblFmt.SetName( GetUniqueTblName(), sal_True );
+
+ SwStartNode *pStNd;
+ SwNodeIndex aIdx( *GetNodes().GetEndOfAutotext().StartOfSectionNode(), 1 );
+ while ( 0 != (pStNd = aIdx.GetNode().GetStartNode()) )
+ {
+ aIdx++;
+ SwOLENode *pNd = aIdx.GetNode().GetOLENode();
+ if( pNd && aOldName == pNd->GetChartTblName() )
+ {
+ pNd->SetChartTblName( rNewName );
+
+ ViewShell* pVSh;
+ GetEditShell( &pVSh );
+
+ SwTable* pTable = SwTable::FindTable( &rTblFmt );
+ SwChartDataProvider *pPCD = GetChartDataProvider();
+ if (pPCD)
+ pPCD->InvalidateTable( pTable );
+ // following this the framework will now take care of repainting
+ // the chart or it's replacement image...
+ }
+ aIdx.Assign( *pStNd->EndOfSectionNode(), + 1 );
+ }
+ SetModified();
+}
+
+
+SwChartDataProvider * SwDoc::GetChartDataProvider( bool bCreate ) const
+{
+ // since there must be only one instance of this object per document
+ // we need a mutex here
+ SolarMutexGuard aGuard;
+
+ if (bCreate && !aChartDataProviderImplRef.get())
+ {
+ aChartDataProviderImplRef = comphelper::ImplementationReference< SwChartDataProvider
+ , chart2::data::XDataProvider >( new SwChartDataProvider( this ) );
+ }
+ return aChartDataProviderImplRef.get();
+}
+
+
+void SwDoc::CreateChartInternalDataProviders( const SwTable *pTable )
+{
+ if (pTable)
+ {
+ String aName( pTable->GetFrmFmt()->GetName() );
+ SwOLENode *pONd;
+ SwStartNode *pStNd;
+ SwNodeIndex aIdx( *GetNodes().GetEndOfAutotext().StartOfSectionNode(), 1 );
+ while (0 != (pStNd = aIdx.GetNode().GetStartNode()))
+ {
+ aIdx++;
+ if( 0 != ( pONd = aIdx.GetNode().GetOLENode() ) &&
+ aName.Equals( pONd->GetChartTblName() ) /* OLE node is chart? */ &&
+ 0 != (pONd->getLayoutFrm( GetCurrentLayout() )) /* chart frame is not hidden */ )
+ {
+ uno::Reference < embed::XEmbeddedObject > xIP = pONd->GetOLEObj().GetOleRef();
+ if ( svt::EmbeddedObjectRef::TryRunningState( xIP ) )
+ {
+ uno::Reference< chart2::XChartDocument > xChart( xIP->getComponent(), UNO_QUERY );
+ if (xChart.is())
+ xChart->createInternalDataProvider( sal_True );
+
+ // there may be more than one chart for each table thus we need to continue the loop...
+ }
+ }
+ aIdx.Assign( *pStNd->EndOfSectionNode(), + 1 );
+ }
+ }
+}
+
+
+SwChartLockController_Helper & SwDoc::GetChartControllerHelper()
+{
+ if (!pChartControllerHelper)
+ {
+ pChartControllerHelper = new SwChartLockController_Helper( this );
+ }
+ return *pChartControllerHelper;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/doc/doccomp.cxx b/sw/source/core/doc/doccomp.cxx
new file mode 100644
index 000000000000..69c070ab3d20
--- /dev/null
+++ b/sw/source/core/doc/doccomp.cxx
@@ -0,0 +1,1848 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+#include <hintids.hxx>
+#include <vcl/vclenum.hxx>
+#include <editeng/crsditem.hxx>
+#include <editeng/colritem.hxx>
+#include <editeng/boxitem.hxx>
+#include <editeng/udlnitem.hxx>
+#include <doc.hxx>
+#include <IDocumentUndoRedo.hxx>
+#include <docary.hxx>
+#include <pam.hxx>
+#include <ndtxt.hxx>
+#include <redline.hxx>
+#include <UndoRedline.hxx>
+#include <section.hxx>
+#include <tox.hxx>
+#include <docsh.hxx>
+
+#include <com/sun/star/document/XDocumentPropertiesSupplier.hpp>
+#include <com/sun/star/document/XDocumentProperties.hpp>
+
+#include <vector>
+
+using namespace ::com::sun::star;
+
+using ::std::vector;
+
+class CompareLine
+{
+public:
+ CompareLine() {}
+ virtual ~CompareLine();
+
+ virtual sal_uLong GetHashValue() const = 0;
+ virtual sal_Bool Compare( const CompareLine& rLine ) const = 0;
+};
+
+class CompareData
+{
+ size_t* pIndex;
+ bool* pChangedFlag;
+
+protected:
+ vector< CompareLine* > aLines;
+ sal_uLong nSttLineNum;
+
+ // Anfang und Ende beschneiden und alle anderen in das
+ // LinesArray setzen
+ virtual void CheckRanges( CompareData& ) = 0;
+
+public:
+ CompareData();
+ virtual ~CompareData();
+
+ // gibt es unterschiede?
+ sal_Bool HasDiffs( const CompareData& rData ) const;
+
+ // startet das Vergleichen und Erzeugen der Unterschiede zweier
+ // Dokumente
+ void CompareLines( CompareData& rData );
+ // lasse die Unterschiede anzeigen - ruft die beiden Methoden
+ // ShowInsert / ShowDelete. Diese bekommen die Start und EndLine-Nummer
+ // uebergeben. Die Abbildung auf den tatsaechline Inhalt muss die
+ // Ableitung uebernehmen!
+ sal_uLong ShowDiffs( const CompareData& rData );
+
+ virtual void ShowInsert( sal_uLong nStt, sal_uLong nEnd );
+ virtual void ShowDelete( const CompareData& rData, sal_uLong nStt,
+ sal_uLong nEnd, sal_uLong nInsPos );
+ virtual void CheckForChangesInLine( const CompareData& rData,
+ sal_uLong& nStt, sal_uLong& nEnd,
+ sal_uLong& nThisStt, sal_uLong& nThisEnd );
+
+ // Eindeutigen Index fuer eine Line setzen. Gleiche Lines haben den
+ // selben Index; auch in den anderen CompareData!
+ void SetIndex( size_t nLine, size_t nIndex );
+ size_t GetIndex( size_t nLine ) const
+ { return nLine < aLines.size() ? pIndex[ nLine ] : 0; }
+
+ // setze/erfrage ob eine Zeile veraendert ist
+ void SetChanged( size_t nLine, bool bFlag = true );
+ bool GetChanged( size_t nLine ) const
+ {
+ return (pChangedFlag && nLine < aLines.size())
+ ? pChangedFlag[ nLine ]
+ : 0;
+ }
+
+ size_t GetLineCount() const { return aLines.size(); }
+ sal_uLong GetLineOffset() const { return nSttLineNum; }
+ const CompareLine* GetLine( size_t nLine ) const
+ { return aLines[ nLine ]; }
+ void InsertLine( CompareLine* pLine )
+ { aLines.push_back( pLine ); }
+};
+
+class Hash
+{
+ struct _HashData
+ {
+ sal_uLong nNext, nHash;
+ const CompareLine* pLine;
+
+ _HashData()
+ : nNext( 0 ), nHash( 0 ), pLine(0) {}
+ };
+
+ sal_uLong* pHashArr;
+ _HashData* pDataArr;
+ sal_uLong nCount, nPrime;
+
+public:
+ Hash( sal_uLong nSize );
+ ~Hash();
+
+ void CalcHashValue( CompareData& rData );
+
+ sal_uLong GetCount() const { return nCount; }
+};
+
+class Compare
+{
+public:
+ class MovedData
+ {
+ sal_uLong* pIndex;
+ sal_uLong* pLineNum;
+ sal_uLong nCount;
+
+ public:
+ MovedData( CompareData& rData, sal_Char* pDiscard );
+ ~MovedData();
+
+ sal_uLong GetIndex( sal_uLong n ) const { return pIndex[ n ]; }
+ sal_uLong GetLineNum( sal_uLong n ) const { return pLineNum[ n ]; }
+ sal_uLong GetCount() const { return nCount; }
+ };
+
+private:
+ // Suche die verschobenen Lines
+ class CompareSequence
+ {
+ CompareData &rData1, &rData2;
+ const MovedData &rMoved1, &rMoved2;
+ long *pMemory, *pFDiag, *pBDiag;
+
+ void Compare( sal_uLong nStt1, sal_uLong nEnd1, sal_uLong nStt2, sal_uLong nEnd2 );
+ sal_uLong CheckDiag( sal_uLong nStt1, sal_uLong nEnd1,
+ sal_uLong nStt2, sal_uLong nEnd2, sal_uLong* pCost );
+ public:
+ CompareSequence( CompareData& rData1, CompareData& rData2,
+ const MovedData& rD1, const MovedData& rD2 );
+ ~CompareSequence();
+ };
+
+
+ static void CountDifference( const CompareData& rData, sal_uLong* pCounts );
+ static void SetDiscard( const CompareData& rData,
+ sal_Char* pDiscard, sal_uLong* pCounts );
+ static void CheckDiscard( sal_uLong nLen, sal_Char* pDiscard );
+ static sal_uLong SetChangedFlag( CompareData& rData, sal_Char* pDiscard, int bFirst );
+ static void ShiftBoundaries( CompareData& rData1, CompareData& rData2 );
+
+public:
+ Compare( sal_uLong nDiff, CompareData& rData1, CompareData& rData2 );
+};
+
+CompareLine::~CompareLine() {}
+
+CompareData::CompareData()
+ : pIndex( 0 ), pChangedFlag( 0 ), nSttLineNum( 0 )
+{
+}
+
+CompareData::~CompareData()
+{
+ delete[] pIndex;
+ delete[] pChangedFlag;
+}
+
+void CompareData::SetIndex( size_t nLine, size_t nIndex )
+{
+ if( !pIndex )
+ {
+ pIndex = new size_t[ aLines.size() ];
+ memset( pIndex, 0, aLines.size() * sizeof( size_t ) );
+ }
+ if( nLine < aLines.size() )
+ pIndex[ nLine ] = nIndex;
+}
+
+void CompareData::SetChanged( size_t nLine, bool bFlag )
+{
+ if( !pChangedFlag )
+ {
+ pChangedFlag = new bool[ aLines.size() +1 ];
+ memset( pChangedFlag, 0, (aLines.size() +1) * sizeof( bool ) );
+ }
+ if( nLine < aLines.size() )
+ pChangedFlag[ nLine ] = bFlag;
+}
+
+void CompareData::CompareLines( CompareData& rData )
+{
+ CheckRanges( rData );
+
+ sal_uLong nDifferent;
+ {
+ Hash aH( GetLineCount() + rData.GetLineCount() + 1 );
+ aH.CalcHashValue( *this );
+ aH.CalcHashValue( rData );
+ nDifferent = aH.GetCount();
+ }
+ {
+ Compare aComp( nDifferent, *this, rData );
+ }
+}
+
+sal_uLong CompareData::ShowDiffs( const CompareData& rData )
+{
+ sal_uLong nLen1 = rData.GetLineCount(), nLen2 = GetLineCount();
+ sal_uLong nStt1 = 0, nStt2 = 0;
+ sal_uLong nCnt = 0;
+
+ while( nStt1 < nLen1 || nStt2 < nLen2 )
+ {
+ if( rData.GetChanged( nStt1 ) || GetChanged( nStt2 ) )
+ {
+ sal_uLong nSav1 = nStt1, nSav2 = nStt2;
+ while( nStt1 < nLen1 && rData.GetChanged( nStt1 )) ++nStt1;
+ while( nStt2 < nLen2 && GetChanged( nStt2 )) ++nStt2;
+
+ // rData ist das Original,
+ // this ist das, in das die Veraenderungen sollen
+ if( nSav2 != nStt2 && nSav1 != nStt1 )
+ CheckForChangesInLine( rData, nSav1, nStt1, nSav2, nStt2 );
+
+ if( nSav2 != nStt2 )
+ ShowInsert( nSav2, nStt2 );
+
+ if( nSav1 != nStt1 )
+ ShowDelete( rData, nSav1, nStt1, nStt2 );
+ ++nCnt;
+ }
+ ++nStt1, ++nStt2;
+ }
+ return nCnt;
+}
+
+sal_Bool CompareData::HasDiffs( const CompareData& rData ) const
+{
+ sal_Bool bRet = sal_False;
+ sal_uLong nLen1 = rData.GetLineCount(), nLen2 = GetLineCount();
+ sal_uLong nStt1 = 0, nStt2 = 0;
+
+ while( nStt1 < nLen1 || nStt2 < nLen2 )
+ {
+ if( rData.GetChanged( nStt1 ) || GetChanged( nStt2 ) )
+ {
+ bRet = sal_True;
+ break;
+ }
+ ++nStt1, ++nStt2;
+ }
+ return bRet;
+}
+
+void CompareData::ShowInsert( sal_uLong, sal_uLong )
+{
+}
+
+void CompareData::ShowDelete( const CompareData&, sal_uLong, sal_uLong, sal_uLong )
+{
+}
+
+void CompareData::CheckForChangesInLine( const CompareData& ,
+ sal_uLong&, sal_uLong&, sal_uLong&, sal_uLong& )
+{
+}
+
+Hash::Hash( sal_uLong nSize )
+ : nCount( 1 )
+{
+
+static const sal_uLong primes[] =
+{
+ 509,
+ 1021,
+ 2039,
+ 4093,
+ 8191,
+ 16381,
+ 32749,
+ 65521,
+ 131071,
+ 262139,
+ 524287,
+ 1048573,
+ 2097143,
+ 4194301,
+ 8388593,
+ 16777213,
+ 33554393,
+ 67108859, /* Preposterously large . . . */
+ 134217689,
+ 268435399,
+ 536870909,
+ 1073741789,
+ 2147483647,
+ 0
+};
+ int i;
+
+ pDataArr = new _HashData[ nSize ];
+ pDataArr[0].nNext = 0;
+ pDataArr[0].nHash = 0,
+ pDataArr[0].pLine = 0;
+
+ for( i = 0; primes[i] < nSize / 3; i++)
+ if( !primes[i] )
+ {
+ pHashArr = 0;
+ return;
+ }
+ nPrime = primes[ i ];
+ pHashArr = new sal_uLong[ nPrime ];
+ memset( pHashArr, 0, nPrime * sizeof( sal_uLong ) );
+}
+
+Hash::~Hash()
+{
+ delete[] pHashArr;
+ delete[] pDataArr;
+}
+
+void Hash::CalcHashValue( CompareData& rData )
+{
+ if( pHashArr )
+ {
+ for( size_t n = 0; n < rData.GetLineCount(); ++n )
+ {
+ const CompareLine* pLine = rData.GetLine( n );
+ OSL_ENSURE( pLine, "wo ist die Line?" );
+ sal_uLong nH = pLine->GetHashValue();
+
+ sal_uLong* pFound = &pHashArr[ nH % nPrime ];
+ size_t i;
+ for( i = *pFound; ; i = pDataArr[i].nNext )
+ if( !i )
+ {
+ i = nCount++;
+ pDataArr[i].nNext = *pFound;
+ pDataArr[i].nHash = nH;
+ pDataArr[i].pLine = pLine;
+ *pFound = i;
+ break;
+ }
+ else if( pDataArr[i].nHash == nH &&
+ pDataArr[i].pLine->Compare( *pLine ))
+ break;
+
+ rData.SetIndex( n, i );
+ }
+ }
+}
+
+Compare::Compare( sal_uLong nDiff, CompareData& rData1, CompareData& rData2 )
+{
+ MovedData *pMD1, *pMD2;
+ // Suche die unterschiedlichen Lines
+ {
+ sal_Char* pDiscard1 = new sal_Char[ rData1.GetLineCount() ];
+ sal_Char* pDiscard2 = new sal_Char[ rData2.GetLineCount() ];
+
+ sal_uLong* pCount1 = new sal_uLong[ nDiff ];
+ sal_uLong* pCount2 = new sal_uLong[ nDiff ];
+ memset( pCount1, 0, nDiff * sizeof( sal_uLong ));
+ memset( pCount2, 0, nDiff * sizeof( sal_uLong ));
+
+ // stelle fest, welche Indizies in den CompareData mehrfach vergeben wurden
+ CountDifference( rData1, pCount1 );
+ CountDifference( rData2, pCount2 );
+
+ // alle die jetzt nur einmal vorhanden sind, sind eingefuegt oder
+ // geloescht worden. Alle die im anderen auch vorhanden sind, sind
+ // verschoben worden
+ SetDiscard( rData1, pDiscard1, pCount2 );
+ SetDiscard( rData2, pDiscard2, pCount1 );
+
+ // die Arrays koennen wir wieder vergessen
+ delete [] pCount1; delete [] pCount2;
+
+ CheckDiscard( rData1.GetLineCount(), pDiscard1 );
+ CheckDiscard( rData2.GetLineCount(), pDiscard2 );
+
+ pMD1 = new MovedData( rData1, pDiscard1 );
+ pMD2 = new MovedData( rData2, pDiscard2 );
+
+ // die Arrays koennen wir wieder vergessen
+ delete [] pDiscard1; delete [] pDiscard2;
+ }
+
+ {
+ CompareSequence aTmp( rData1, rData2, *pMD1, *pMD2 );
+ }
+
+ ShiftBoundaries( rData1, rData2 );
+
+ delete pMD1;
+ delete pMD2;
+}
+
+void Compare::CountDifference( const CompareData& rData, sal_uLong* pCounts )
+{
+ sal_uLong nLen = rData.GetLineCount();
+ for( sal_uLong n = 0; n < nLen; ++n )
+ {
+ sal_uLong nIdx = rData.GetIndex( n );
+ ++pCounts[ nIdx ];
+ }
+}
+
+void Compare::SetDiscard( const CompareData& rData,
+ sal_Char* pDiscard, sal_uLong* pCounts )
+{
+ sal_uLong nLen = rData.GetLineCount();
+
+ // berechne Max in Abhanegigkeit zur LineAnzahl
+ sal_uInt16 nMax = 5;
+ sal_uLong n;
+
+ for( n = nLen / 64; ( n = n >> 2 ) > 0; )
+ nMax <<= 1;
+
+ for( n = 0; n < nLen; ++n )
+ {
+ sal_uLong nIdx = rData.GetIndex( n );
+ if( nIdx )
+ {
+ nIdx = pCounts[ nIdx ];
+ pDiscard[ n ] = !nIdx ? 1 : nIdx > nMax ? 2 : 0;
+ }
+ else
+ pDiscard[ n ] = 0;
+ }
+}
+
+void Compare::CheckDiscard( sal_uLong nLen, sal_Char* pDiscard )
+{
+ for( sal_uLong n = 0; n < nLen; ++n )
+ {
+ if( 2 == pDiscard[ n ] )
+ pDiscard[n] = 0;
+ else if( pDiscard[ n ] )
+ {
+ sal_uLong j;
+ sal_uLong length;
+ sal_uLong provisional = 0;
+
+ /* Find end of this run of discardable lines.
+ Count how many are provisionally discardable. */
+ for (j = n; j < nLen; j++)
+ {
+ if( !pDiscard[j] )
+ break;
+ if( 2 == pDiscard[j] )
+ ++provisional;
+ }
+
+ /* Cancel provisional discards at end, and shrink the run. */
+ while( j > n && 2 == pDiscard[j - 1] )
+ pDiscard[ --j ] = 0, --provisional;
+
+ /* Now we have the length of a run of discardable lines
+ whose first and last are not provisional. */
+ length = j - n;
+
+ /* If 1/4 of the lines in the run are provisional,
+ cancel discarding of all provisional lines in the run. */
+ if (provisional * 4 > length)
+ {
+ while (j > n)
+ if (pDiscard[--j] == 2)
+ pDiscard[j] = 0;
+ }
+ else
+ {
+ sal_uLong consec;
+ sal_uLong minimum = 1;
+ sal_uLong tem = length / 4;
+
+ /* MINIMUM is approximate square root of LENGTH/4.
+ A subrun of two or more provisionals can stand
+ when LENGTH is at least 16.
+ A subrun of 4 or more can stand when LENGTH >= 64. */
+ while ((tem = tem >> 2) > 0)
+ minimum *= 2;
+ minimum++;
+
+ /* Cancel any subrun of MINIMUM or more provisionals
+ within the larger run. */
+ for (j = 0, consec = 0; j < length; j++)
+ if (pDiscard[n + j] != 2)
+ consec = 0;
+ else if (minimum == ++consec)
+ /* Back up to start of subrun, to cancel it all. */
+ j -= consec;
+ else if (minimum < consec)
+ pDiscard[n + j] = 0;
+
+ /* Scan from beginning of run
+ until we find 3 or more nonprovisionals in a row
+ or until the first nonprovisional at least 8 lines in.
+ Until that point, cancel any provisionals. */
+ for (j = 0, consec = 0; j < length; j++)
+ {
+ if (j >= 8 && pDiscard[n + j] == 1)
+ break;
+ if (pDiscard[n + j] == 2)
+ consec = 0, pDiscard[n + j] = 0;
+ else if (pDiscard[n + j] == 0)
+ consec = 0;
+ else
+ consec++;
+ if (consec == 3)
+ break;
+ }
+
+ /* I advances to the last line of the run. */
+ n += length - 1;
+
+ /* Same thing, from end. */
+ for (j = 0, consec = 0; j < length; j++)
+ {
+ if (j >= 8 && pDiscard[n - j] == 1)
+ break;
+ if (pDiscard[n - j] == 2)
+ consec = 0, pDiscard[n - j] = 0;
+ else if (pDiscard[n - j] == 0)
+ consec = 0;
+ else
+ consec++;
+ if (consec == 3)
+ break;
+ }
+ }
+ }
+ }
+}
+
+Compare::MovedData::MovedData( CompareData& rData, sal_Char* pDiscard )
+ : pIndex( 0 ), pLineNum( 0 ), nCount( 0 )
+{
+ sal_uLong nLen = rData.GetLineCount();
+ sal_uLong n;
+
+ for( n = 0; n < nLen; ++n )
+ if( pDiscard[ n ] )
+ rData.SetChanged( n );
+ else
+ ++nCount;
+
+ if( nCount )
+ {
+ pIndex = new sal_uLong[ nCount ];
+ pLineNum = new sal_uLong[ nCount ];
+
+ for( n = 0, nCount = 0; n < nLen; ++n )
+ if( !pDiscard[ n ] )
+ {
+ pIndex[ nCount ] = rData.GetIndex( n );
+ pLineNum[ nCount++ ] = n;
+ }
+ }
+}
+
+Compare::MovedData::~MovedData()
+{
+ delete pIndex;
+ delete pLineNum;
+}
+
+// Suche die verschobenen Lines
+Compare::CompareSequence::CompareSequence(
+ CompareData& rD1, CompareData& rD2,
+ const MovedData& rMD1, const MovedData& rMD2 )
+ : rData1( rD1 ), rData2( rD2 ), rMoved1( rMD1 ), rMoved2( rMD2 )
+{
+ sal_uLong nSize = rMD1.GetCount() + rMD2.GetCount() + 3;
+ pMemory = new long[ nSize * 2 ];
+ pFDiag = pMemory + ( rMD2.GetCount() + 1 );
+ pBDiag = pMemory + ( nSize + rMD2.GetCount() + 1 );
+
+ Compare( 0, rMD1.GetCount(), 0, rMD2.GetCount() );
+}
+
+Compare::CompareSequence::~CompareSequence()
+{
+ delete pMemory;
+}
+
+void Compare::CompareSequence::Compare( sal_uLong nStt1, sal_uLong nEnd1,
+ sal_uLong nStt2, sal_uLong nEnd2 )
+{
+ /* Slide down the bottom initial diagonal. */
+ while( nStt1 < nEnd1 && nStt2 < nEnd2 &&
+ rMoved1.GetIndex( nStt1 ) == rMoved2.GetIndex( nStt2 ))
+ ++nStt1, ++nStt2;
+
+ /* Slide up the top initial diagonal. */
+ while( nEnd1 > nStt1 && nEnd2 > nStt2 &&
+ rMoved1.GetIndex( nEnd1 - 1 ) == rMoved2.GetIndex( nEnd2 - 1 ))
+ --nEnd1, --nEnd2;
+
+ /* Handle simple cases. */
+ if( nStt1 == nEnd1 )
+ while( nStt2 < nEnd2 )
+ rData2.SetChanged( rMoved2.GetLineNum( nStt2++ ));
+
+ else if (nStt2 == nEnd2)
+ while (nStt1 < nEnd1)
+ rData1.SetChanged( rMoved1.GetLineNum( nStt1++ ));
+
+ else
+ {
+ sal_uLong c, d, b;
+
+ /* Find a point of correspondence in the middle of the files. */
+
+ d = CheckDiag( nStt1, nEnd1, nStt2, nEnd2, &c );
+ b = pBDiag[ d ];
+
+ if( 1 != c )
+ {
+ /* Use that point to split this problem into two subproblems. */
+ Compare( nStt1, b, nStt2, b - d );
+ /* This used to use f instead of b,
+ but that is incorrect!
+ It is not necessarily the case that diagonal d
+ has a snake from b to f. */
+ Compare( b, nEnd1, b - d, nEnd2 );
+ }
+ }
+}
+
+sal_uLong Compare::CompareSequence::CheckDiag( sal_uLong nStt1, sal_uLong nEnd1,
+ sal_uLong nStt2, sal_uLong nEnd2, sal_uLong* pCost )
+{
+ const long dmin = nStt1 - nEnd2; /* Minimum valid diagonal. */
+ const long dmax = nEnd1 - nStt2; /* Maximum valid diagonal. */
+ const long fmid = nStt1 - nStt2; /* Center diagonal of top-down search. */
+ const long bmid = nEnd1 - nEnd2; /* Center diagonal of bottom-up search. */
+
+ long fmin = fmid, fmax = fmid; /* Limits of top-down search. */
+ long bmin = bmid, bmax = bmid; /* Limits of bottom-up search. */
+
+ long c; /* Cost. */
+ long odd = (fmid - bmid) & 1; /* True if southeast corner is on an odd
+ diagonal with respect to the northwest. */
+
+ pFDiag[fmid] = nStt1;
+ pBDiag[bmid] = nEnd1;
+
+ for (c = 1;; ++c)
+ {
+ long d; /* Active diagonal. */
+
+ /* Extend the top-down search by an edit step in each diagonal. */
+ fmin > dmin ? pFDiag[--fmin - 1] = -1 : ++fmin;
+ fmax < dmax ? pFDiag[++fmax + 1] = -1 : --fmax;
+ for (d = fmax; d >= fmin; d -= 2)
+ {
+ long x, y, tlo = pFDiag[d - 1], thi = pFDiag[d + 1];
+
+ if (tlo >= thi)
+ x = tlo + 1;
+ else
+ x = thi;
+ y = x - d;
+ while( sal_uLong(x) < nEnd1 && sal_uLong(y) < nEnd2 &&
+ rMoved1.GetIndex( x ) == rMoved2.GetIndex( y ))
+ ++x, ++y;
+ pFDiag[d] = x;
+ if( odd && bmin <= d && d <= bmax && pBDiag[d] <= pFDiag[d] )
+ {
+ *pCost = 2 * c - 1;
+ return d;
+ }
+ }
+
+ /* Similar extend the bottom-up search. */
+ bmin > dmin ? pBDiag[--bmin - 1] = INT_MAX : ++bmin;
+ bmax < dmax ? pBDiag[++bmax + 1] = INT_MAX : --bmax;
+ for (d = bmax; d >= bmin; d -= 2)
+ {
+ long x, y, tlo = pBDiag[d - 1], thi = pBDiag[d + 1];
+
+ if (tlo < thi)
+ x = tlo;
+ else
+ x = thi - 1;
+ y = x - d;
+ while( sal_uLong(x) > nStt1 && sal_uLong(y) > nStt2 &&
+ rMoved1.GetIndex( x - 1 ) == rMoved2.GetIndex( y - 1 ))
+ --x, --y;
+ pBDiag[d] = x;
+ if (!odd && fmin <= d && d <= fmax && pBDiag[d] <= pFDiag[d])
+ {
+ *pCost = 2 * c;
+ return d;
+ }
+ }
+ }
+}
+
+void Compare::ShiftBoundaries( CompareData& rData1, CompareData& rData2 )
+{
+ for( int iz = 0; iz < 2; ++iz )
+ {
+ CompareData* pData = &rData1;
+ CompareData* pOtherData = &rData2;
+
+ sal_uLong i = 0;
+ sal_uLong j = 0;
+ sal_uLong i_end = pData->GetLineCount();
+ sal_uLong preceding = ULONG_MAX;
+ sal_uLong other_preceding = ULONG_MAX;
+
+ while (1)
+ {
+ sal_uLong start, other_start;
+
+ /* Scan forwards to find beginning of another run of changes.
+ Also keep track of the corresponding point in the other file. */
+
+ while( i < i_end && !pData->GetChanged( i ) )
+ {
+ while( pOtherData->GetChanged( j++ ))
+ /* Non-corresponding lines in the other file
+ will count as the preceding batch of changes. */
+ other_preceding = j;
+ i++;
+ }
+
+ if (i == i_end)
+ break;
+
+ start = i;
+ other_start = j;
+
+ while (1)
+ {
+ /* Now find the end of this run of changes. */
+
+ while( pData->GetChanged( ++i ))
+ ;
+
+ /* If the first changed line matches the following unchanged one,
+ and this run does not follow right after a previous run,
+ and there are no lines deleted from the other file here,
+ then classify the first changed line as unchanged
+ and the following line as changed in its place. */
+
+ /* You might ask, how could this run follow right after another?
+ Only because the previous run was shifted here. */
+
+ if( i != i_end &&
+ pData->GetIndex( start ) == pData->GetIndex( i ) &&
+ !pOtherData->GetChanged( j ) &&
+ !( start == preceding || other_start == other_preceding ))
+ {
+ pData->SetChanged( start++, 0 );
+ pData->SetChanged( i );
+ /* Since one line-that-matches is now before this run
+ instead of after, we must advance in the other file
+ to keep in synch. */
+ ++j;
+ }
+ else
+ break;
+ }
+
+ preceding = i;
+ other_preceding = j;
+ }
+
+ pData = &rData2;
+ pOtherData = &rData1;
+ }
+}
+
+class SwCompareLine : public CompareLine
+{
+ const SwNode& rNode;
+public:
+ SwCompareLine( const SwNode& rNd );
+ virtual ~SwCompareLine();
+
+ virtual sal_uLong GetHashValue() const;
+ virtual sal_Bool Compare( const CompareLine& rLine ) const;
+
+ static sal_uLong GetTxtNodeHashValue( const SwTxtNode& rNd, sal_uLong nVal );
+ static sal_Bool CompareNode( const SwNode& rDstNd, const SwNode& rSrcNd );
+ static sal_Bool CompareTxtNd( const SwTxtNode& rDstNd,
+ const SwTxtNode& rSrcNd );
+
+ sal_Bool ChangesInLine( const SwCompareLine& rLine,
+ SwPaM *& rpInsRing, SwPaM*& rpDelRing ) const;
+
+ const SwNode& GetNode() const { return rNode; }
+
+ const SwNode& GetEndNode() const;
+
+ // fuers Debugging!
+ String GetText() const;
+};
+
+class SwCompareData : public CompareData
+{
+ SwDoc& rDoc;
+ SwPaM *pInsRing, *pDelRing;
+
+ sal_uLong PrevIdx( const SwNode* pNd );
+ sal_uLong NextIdx( const SwNode* pNd );
+
+ virtual void CheckRanges( CompareData& );
+ virtual void ShowInsert( sal_uLong nStt, sal_uLong nEnd );
+ virtual void ShowDelete( const CompareData& rData, sal_uLong nStt,
+ sal_uLong nEnd, sal_uLong nInsPos );
+
+ virtual void CheckForChangesInLine( const CompareData& rData,
+ sal_uLong& nStt, sal_uLong& nEnd,
+ sal_uLong& nThisStt, sal_uLong& nThisEnd );
+
+public:
+ SwCompareData( SwDoc& rD ) : rDoc( rD ), pInsRing(0), pDelRing(0) {}
+ virtual ~SwCompareData();
+
+ void SetRedlinesToDoc( sal_Bool bUseDocInfo );
+};
+
+SwCompareLine::SwCompareLine( const SwNode& rNd )
+ : rNode( rNd )
+{
+}
+
+SwCompareLine::~SwCompareLine()
+{
+}
+
+sal_uLong SwCompareLine::GetHashValue() const
+{
+ sal_uLong nRet = 0;
+ switch( rNode.GetNodeType() )
+ {
+ case ND_TEXTNODE:
+ nRet = GetTxtNodeHashValue( (SwTxtNode&)rNode, nRet );
+ break;
+
+ case ND_TABLENODE:
+ {
+ const SwNode* pEndNd = rNode.EndOfSectionNode();
+ SwNodeIndex aIdx( rNode );
+ while( &aIdx.GetNode() != pEndNd )
+ {
+ if( aIdx.GetNode().IsTxtNode() )
+ nRet = GetTxtNodeHashValue( (SwTxtNode&)aIdx.GetNode(), nRet );
+ aIdx++;
+ }
+ }
+ break;
+
+ case ND_SECTIONNODE:
+ {
+ String sStr( GetText() );
+ for( xub_StrLen n = 0; n < sStr.Len(); ++n )
+ ( nRet <<= 1 ) += sStr.GetChar( n );
+ }
+ break;
+
+ case ND_GRFNODE:
+ case ND_OLENODE:
+ // feste Id ? sollte aber nie auftauchen
+ break;
+ }
+ return nRet;
+}
+
+const SwNode& SwCompareLine::GetEndNode() const
+{
+ const SwNode* pNd = &rNode;
+ switch( rNode.GetNodeType() )
+ {
+ case ND_TABLENODE:
+ pNd = rNode.EndOfSectionNode();
+ break;
+
+ case ND_SECTIONNODE:
+ {
+ const SwSectionNode& rSNd = (SwSectionNode&)rNode;
+ const SwSection& rSect = rSNd.GetSection();
+ if( CONTENT_SECTION != rSect.GetType() || rSect.IsProtect() )
+ pNd = rNode.EndOfSectionNode();
+ }
+ break;
+ }
+ return *pNd;
+}
+
+sal_Bool SwCompareLine::Compare( const CompareLine& rLine ) const
+{
+ return CompareNode( rNode, ((SwCompareLine&)rLine).rNode );
+}
+
+namespace
+{
+ static String SimpleTableToText(const SwNode &rNode)
+ {
+ String sRet;
+ const SwNode* pEndNd = rNode.EndOfSectionNode();
+ SwNodeIndex aIdx( rNode );
+ while (&aIdx.GetNode() != pEndNd)
+ {
+ if (aIdx.GetNode().IsTxtNode())
+ {
+ if (sRet.Len())
+ {
+ sRet.Append( '\n' );
+ }
+ sRet.Append( aIdx.GetNode().GetTxtNode()->GetExpandTxt() );
+ }
+ aIdx++;
+ }
+ return sRet;
+ }
+}
+
+sal_Bool SwCompareLine::CompareNode( const SwNode& rDstNd, const SwNode& rSrcNd )
+{
+ if( rSrcNd.GetNodeType() != rDstNd.GetNodeType() )
+ return sal_False;
+
+ sal_Bool bRet = sal_False;
+
+ switch( rDstNd.GetNodeType() )
+ {
+ case ND_TEXTNODE:
+ bRet = CompareTxtNd( (SwTxtNode&)rDstNd, (SwTxtNode&)rSrcNd );
+ break;
+
+ case ND_TABLENODE:
+ {
+ const SwTableNode& rTSrcNd = (SwTableNode&)rSrcNd;
+ const SwTableNode& rTDstNd = (SwTableNode&)rDstNd;
+
+ bRet = ( rTSrcNd.EndOfSectionIndex() - rTSrcNd.GetIndex() ) ==
+ ( rTDstNd.EndOfSectionIndex() - rTDstNd.GetIndex() );
+
+ // --> #i107826#: compare actual table content
+ if (bRet)
+ {
+ bRet = (SimpleTableToText(rSrcNd) == SimpleTableToText(rDstNd));
+ }
+ // <--
+ }
+ break;
+
+ case ND_SECTIONNODE:
+ {
+ const SwSectionNode& rSSrcNd = (SwSectionNode&)rSrcNd,
+ & rSDstNd = (SwSectionNode&)rDstNd;
+ const SwSection& rSrcSect = rSSrcNd.GetSection(),
+ & rDstSect = rSDstNd.GetSection();
+ SectionType eSrcSectType = rSrcSect.GetType(),
+ eDstSectType = rDstSect.GetType();
+ switch( eSrcSectType )
+ {
+ case CONTENT_SECTION:
+ bRet = CONTENT_SECTION == eDstSectType &&
+ rSrcSect.IsProtect() == rDstSect.IsProtect();
+ if( bRet && rSrcSect.IsProtect() )
+ {
+ // the only have they both the same size
+ bRet = ( rSSrcNd.EndOfSectionIndex() - rSSrcNd.GetIndex() ) ==
+ ( rSDstNd.EndOfSectionIndex() - rSDstNd.GetIndex() );
+ }
+ break;
+
+ case TOX_HEADER_SECTION:
+ case TOX_CONTENT_SECTION:
+ if( TOX_HEADER_SECTION == eDstSectType ||
+ TOX_CONTENT_SECTION == eDstSectType )
+ {
+ // the same type of TOX?
+ const SwTOXBase* pSrcTOX = rSrcSect.GetTOXBase();
+ const SwTOXBase* pDstTOX = rDstSect.GetTOXBase();
+ bRet = pSrcTOX && pDstTOX
+ && pSrcTOX->GetType() == pDstTOX->GetType()
+ && pSrcTOX->GetTitle() == pDstTOX->GetTitle()
+ && pSrcTOX->GetTypeName() == pDstTOX->GetTypeName()
+// && pSrcTOX->GetTOXName() == pDstTOX->GetTOXName()
+ ;
+ }
+ break;
+
+ case DDE_LINK_SECTION:
+ case FILE_LINK_SECTION:
+ bRet = eSrcSectType == eDstSectType &&
+ rSrcSect.GetLinkFileName() ==
+ rDstSect.GetLinkFileName();
+ break;
+ }
+ }
+ break;
+
+ case ND_ENDNODE:
+ bRet = rSrcNd.StartOfSectionNode()->GetNodeType() ==
+ rDstNd.StartOfSectionNode()->GetNodeType();
+
+ // --> #i107826#: compare actual table content
+ if (bRet && rSrcNd.StartOfSectionNode()->GetNodeType() == ND_TABLENODE)
+ {
+ bRet = CompareNode(
+ *rSrcNd.StartOfSectionNode(), *rDstNd.StartOfSectionNode());
+ }
+ // <--
+
+ break;
+ }
+ return bRet;
+}
+
+String SwCompareLine::GetText() const
+{
+ String sRet;
+ switch( rNode.GetNodeType() )
+ {
+ case ND_TEXTNODE:
+ sRet = ((SwTxtNode&)rNode).GetExpandTxt();
+ break;
+
+ case ND_TABLENODE:
+ {
+ sRet = SimpleTableToText(rNode);
+ sRet.InsertAscii( "Tabelle: ", 0 );
+ }
+ break;
+
+ case ND_SECTIONNODE:
+ {
+ sRet.AssignAscii( RTL_CONSTASCII_STRINGPARAM( "Section - Node:" ));
+
+ const SwSectionNode& rSNd = (SwSectionNode&)rNode;
+ const SwSection& rSect = rSNd.GetSection();
+ switch( rSect.GetType() )
+ {
+ case CONTENT_SECTION:
+ if( rSect.IsProtect() )
+ sRet.Append( String::CreateFromInt32(
+ rSNd.EndOfSectionIndex() - rSNd.GetIndex() ));
+ break;
+
+ case TOX_HEADER_SECTION:
+ case TOX_CONTENT_SECTION:
+ {
+ const SwTOXBase* pTOX = rSect.GetTOXBase();
+ if( pTOX )
+ sRet.Append( pTOX->GetTitle() )
+ .Append( pTOX->GetTypeName() )
+// .Append( pTOX->GetTOXName() )
+ .Append( String::CreateFromInt32( pTOX->GetType() ));
+ }
+ break;
+
+ case DDE_LINK_SECTION:
+ case FILE_LINK_SECTION:
+ sRet += rSect.GetLinkFileName();
+ break;
+ }
+ }
+ break;
+
+ case ND_GRFNODE:
+ sRet.AssignAscii( RTL_CONSTASCII_STRINGPARAM( "Grafik - Node:" ));
+ break;
+ case ND_OLENODE:
+ sRet.AssignAscii( RTL_CONSTASCII_STRINGPARAM( "OLE - Node:" ));
+ break;
+ }
+ return sRet;
+}
+
+sal_uLong SwCompareLine::GetTxtNodeHashValue( const SwTxtNode& rNd, sal_uLong nVal )
+{
+ String sStr( rNd.GetExpandTxt() );
+ for( xub_StrLen n = 0; n < sStr.Len(); ++n )
+ ( nVal <<= 1 ) += sStr.GetChar( n );
+ return nVal;
+}
+
+sal_Bool SwCompareLine::CompareTxtNd( const SwTxtNode& rDstNd,
+ const SwTxtNode& rSrcNd )
+{
+ sal_Bool bRet = sal_False;
+ // erstmal ganz einfach!
+ if( rDstNd.GetTxt() == rSrcNd.GetTxt() )
+ {
+ // der Text ist gleich, aber sind die "Sonderattribute" (0xFF) auch
+ // dieselben??
+ bRet = sal_True;
+ }
+ return bRet;
+}
+
+sal_Bool SwCompareLine::ChangesInLine( const SwCompareLine& rLine,
+ SwPaM *& rpInsRing, SwPaM*& rpDelRing ) const
+{
+ sal_Bool bRet = sal_False;
+ if( ND_TEXTNODE == rNode.GetNodeType() &&
+ ND_TEXTNODE == rLine.GetNode().GetNodeType() )
+ {
+ SwTxtNode& rDestNd = *(SwTxtNode*)rNode.GetTxtNode();
+ const SwTxtNode& rSrcNd = *rLine.GetNode().GetTxtNode();
+
+ xub_StrLen nDEnd = rDestNd.GetTxt().Len(), nSEnd = rSrcNd.GetTxt().Len();
+ xub_StrLen nStt;
+ xub_StrLen nEnd;
+
+ for( nStt = 0, nEnd = Min( nDEnd, nSEnd ); nStt < nEnd; ++nStt )
+ if( rDestNd.GetTxt().GetChar( nStt ) !=
+ rSrcNd.GetTxt().GetChar( nStt ) )
+ break;
+
+ while( nStt < nDEnd && nStt < nSEnd )
+ {
+ --nDEnd, --nSEnd;
+ if( rDestNd.GetTxt().GetChar( nDEnd ) !=
+ rSrcNd.GetTxt().GetChar( nSEnd ) )
+ {
+ ++nDEnd, ++nSEnd;
+ break;
+ }
+ }
+
+ if( nStt || !nDEnd || !nSEnd || nDEnd < rDestNd.GetTxt().Len() ||
+ nSEnd < rSrcNd.GetTxt().Len() )
+ {
+ // jetzt ist zwischen nStt bis nDEnd das neu eingefuegte
+ // und zwischen nStt und nSEnd das geloeschte
+ SwDoc* pDoc = rDestNd.GetDoc();
+ SwPaM aPam( rDestNd, nDEnd );
+ if( nStt != nDEnd )
+ {
+ SwPaM* pTmp = new SwPaM( *aPam.GetPoint(), rpInsRing );
+ if( !rpInsRing )
+ rpInsRing = pTmp;
+
+ pTmp->SetMark();
+ pTmp->GetMark()->nContent = nStt;
+ }
+
+ if( nStt != nSEnd )
+ {
+ {
+ ::sw::UndoGuard const ug(pDoc->GetIDocumentUndoRedo());
+ SwPaM aCpyPam( rSrcNd, nStt );
+ aCpyPam.SetMark();
+ aCpyPam.GetPoint()->nContent = nSEnd;
+ aCpyPam.GetDoc()->CopyRange( aCpyPam, *aPam.GetPoint(),
+ false );
+ }
+
+ SwPaM* pTmp = new SwPaM( *aPam.GetPoint(), rpDelRing );
+ if( !rpDelRing )
+ rpDelRing = pTmp;
+
+ pTmp->SetMark();
+ pTmp->GetMark()->nContent = nDEnd;
+
+ if( rpInsRing )
+ {
+ SwPaM* pCorr = (SwPaM*)rpInsRing->GetPrev();
+ if( *pCorr->GetPoint() == *pTmp->GetPoint() )
+ *pCorr->GetPoint() = *pTmp->GetMark();
+ }
+ }
+ bRet = sal_True;
+ }
+ }
+ return bRet;
+}
+
+SwCompareData::~SwCompareData()
+{
+ if( pDelRing )
+ {
+ while( pDelRing->GetNext() != pDelRing )
+ delete pDelRing->GetNext();
+ delete pDelRing;
+ }
+ if( pInsRing )
+ {
+ while( pInsRing->GetNext() != pInsRing )
+ delete pInsRing->GetNext();
+ delete pInsRing;
+ }
+}
+
+sal_uLong SwCompareData::NextIdx( const SwNode* pNd )
+{
+ if( pNd->IsStartNode() )
+ {
+ const SwSectionNode* pSNd;
+ if( pNd->IsTableNode() ||
+ ( 0 != (pSNd = pNd->GetSectionNode() ) &&
+ ( CONTENT_SECTION != pSNd->GetSection().GetType() ||
+ pSNd->GetSection().IsProtect() ) ) )
+ pNd = pNd->EndOfSectionNode();
+ }
+ return pNd->GetIndex() + 1;
+}
+
+sal_uLong SwCompareData::PrevIdx( const SwNode* pNd )
+{
+ if( pNd->IsEndNode() )
+ {
+ const SwSectionNode* pSNd;
+ if( pNd->StartOfSectionNode()->IsTableNode() ||
+ ( 0 != (pSNd = pNd->StartOfSectionNode()->GetSectionNode() ) &&
+ ( CONTENT_SECTION != pSNd->GetSection().GetType() ||
+ pSNd->GetSection().IsProtect() ) ) )
+ pNd = pNd->StartOfSectionNode();
+ }
+ return pNd->GetIndex() - 1;
+}
+
+void SwCompareData::CheckRanges( CompareData& rData )
+{
+ const SwNodes& rSrcNds = ((SwCompareData&)rData).rDoc.GetNodes();
+ const SwNodes& rDstNds = rDoc.GetNodes();
+
+ const SwNode& rSrcEndNd = rSrcNds.GetEndOfContent();
+ const SwNode& rDstEndNd = rDstNds.GetEndOfContent();
+
+ sal_uLong nSrcSttIdx = NextIdx( rSrcEndNd.StartOfSectionNode() );
+ sal_uLong nSrcEndIdx = rSrcEndNd.GetIndex();
+
+ sal_uLong nDstSttIdx = NextIdx( rDstEndNd.StartOfSectionNode() );
+ sal_uLong nDstEndIdx = rDstEndNd.GetIndex();
+
+ while( nSrcSttIdx < nSrcEndIdx && nDstSttIdx < nDstEndIdx )
+ {
+ const SwNode* pSrcNd = rSrcNds[ nSrcSttIdx ];
+ const SwNode* pDstNd = rDstNds[ nDstSttIdx ];
+ if( !SwCompareLine::CompareNode( *pSrcNd, *pDstNd ))
+ break;
+
+ nSrcSttIdx = NextIdx( pSrcNd );
+ nDstSttIdx = NextIdx( pDstNd );
+ }
+
+ nSrcEndIdx = PrevIdx( &rSrcEndNd );
+ nDstEndIdx = PrevIdx( &rDstEndNd );
+ while( nSrcSttIdx < nSrcEndIdx && nDstSttIdx < nDstEndIdx )
+ {
+ const SwNode* pSrcNd = rSrcNds[ nSrcEndIdx ];
+ const SwNode* pDstNd = rDstNds[ nDstEndIdx ];
+ if( !SwCompareLine::CompareNode( *pSrcNd, *pDstNd ))
+ break;
+
+ nSrcEndIdx = PrevIdx( pSrcNd );
+ nDstEndIdx = PrevIdx( pDstNd );
+ }
+
+ while( nSrcSttIdx <= nSrcEndIdx )
+ {
+ const SwNode* pNd = rSrcNds[ nSrcSttIdx ];
+ rData.InsertLine( new SwCompareLine( *pNd ) );
+ nSrcSttIdx = NextIdx( pNd );
+ }
+
+ while( nDstSttIdx <= nDstEndIdx )
+ {
+ const SwNode* pNd = rDstNds[ nDstSttIdx ];
+ InsertLine( new SwCompareLine( *pNd ) );
+ nDstSttIdx = NextIdx( pNd );
+ }
+}
+
+void SwCompareData::ShowInsert( sal_uLong nStt, sal_uLong nEnd )
+{
+ SwPaM* pTmp = new SwPaM( ((SwCompareLine*)GetLine( nStt ))->GetNode(), 0,
+ ((SwCompareLine*)GetLine( nEnd-1 ))->GetEndNode(), 0,
+ pInsRing );
+ if( !pInsRing )
+ pInsRing = pTmp;
+
+ // #i65201#: These SwPaMs are calculated smaller than needed, see comment below
+
+}
+
+void SwCompareData::ShowDelete( const CompareData& rData, sal_uLong nStt,
+ sal_uLong nEnd, sal_uLong nInsPos )
+{
+ SwNodeRange aRg(
+ ((SwCompareLine*)rData.GetLine( nStt ))->GetNode(), 0,
+ ((SwCompareLine*)rData.GetLine( nEnd-1 ))->GetEndNode(), 1 );
+
+ sal_uInt16 nOffset = 0;
+ const CompareLine* pLine;
+ if( GetLineCount() == nInsPos )
+ {
+ pLine = GetLine( nInsPos-1 );
+ nOffset = 1;
+ }
+ else
+ pLine = GetLine( nInsPos );
+
+ const SwNode* pLineNd;
+ if( pLine )
+ {
+ if( nOffset )
+ pLineNd = &((SwCompareLine*)pLine)->GetEndNode();
+ else
+ pLineNd = &((SwCompareLine*)pLine)->GetNode();
+ }
+ else
+ {
+ pLineNd = &rDoc.GetNodes().GetEndOfContent();
+ nOffset = 0;
+ }
+
+ SwNodeIndex aInsPos( *pLineNd, nOffset );
+ SwNodeIndex aSavePos( aInsPos, -1 );
+
+ ((SwCompareData&)rData).rDoc.CopyWithFlyInFly( aRg, 0, aInsPos );
+ rDoc.SetModified();
+ aSavePos++;
+
+ // #i65201#: These SwPaMs are calculated when the (old) delete-redlines are hidden,
+ // they will be inserted when the delete-redlines are shown again.
+ // To avoid unwanted insertions of delete-redlines into these new redlines, what happens
+ // especially at the end of the document, I reduce the SwPaM by one node.
+ // Before the new redlines are inserted, they have to expand again.
+ SwPaM* pTmp = new SwPaM( aSavePos.GetNode(), aInsPos.GetNode(), 0, -1, pDelRing );
+ if( !pDelRing )
+ pDelRing = pTmp;
+
+ if( pInsRing )
+ {
+ SwPaM* pCorr = (SwPaM*)pInsRing->GetPrev();
+ if( *pCorr->GetPoint() == *pTmp->GetPoint() )
+ {
+ SwNodeIndex aTmpPos( pTmp->GetMark()->nNode, -1 );
+ *pCorr->GetPoint() = SwPosition( aTmpPos );
+ }
+ }
+}
+
+void SwCompareData::CheckForChangesInLine( const CompareData& rData,
+ sal_uLong& rStt, sal_uLong& rEnd,
+ sal_uLong& rThisStt, sal_uLong& rThisEnd )
+{
+ while( rStt < rEnd && rThisStt < rThisEnd )
+ {
+ SwCompareLine* pDstLn = (SwCompareLine*)GetLine( rThisStt );
+ SwCompareLine* pSrcLn = (SwCompareLine*)rData.GetLine( rStt );
+ if( !pDstLn->ChangesInLine( *pSrcLn, pInsRing, pDelRing ) )
+ break;
+
+ ++rStt;
+ ++rThisStt;
+ }
+}
+
+void SwCompareData::SetRedlinesToDoc( sal_Bool bUseDocInfo )
+{
+ SwPaM* pTmp = pDelRing;
+
+ // get the Author / TimeStamp from the "other" document info
+ sal_uInt16 nAuthor = rDoc.GetRedlineAuthor();
+ DateTime aTimeStamp;
+ SwDocShell *pDocShell(rDoc.GetDocShell());
+ DBG_ASSERT(pDocShell, "no SwDocShell");
+ if (pDocShell) {
+ uno::Reference<document::XDocumentPropertiesSupplier> xDPS(
+ pDocShell->GetModel(), uno::UNO_QUERY_THROW);
+ uno::Reference<document::XDocumentProperties> xDocProps(
+ xDPS->getDocumentProperties());
+ DBG_ASSERT(xDocProps.is(), "Doc has no DocumentProperties");
+
+ if( bUseDocInfo && xDocProps.is() ) {
+ String aTmp( 1 == xDocProps->getEditingCycles()
+ ? xDocProps->getAuthor()
+ : xDocProps->getModifiedBy() );
+ util::DateTime uDT( 1 == xDocProps->getEditingCycles()
+ ? xDocProps->getCreationDate()
+ : xDocProps->getModificationDate() );
+ Date d(uDT.Day, uDT.Month, uDT.Year);
+ Time t(uDT.Hours, uDT.Minutes, uDT.Seconds, uDT.HundredthSeconds);
+ DateTime aDT(d,t);
+
+ if( aTmp.Len() )
+ {
+ nAuthor = rDoc.InsertRedlineAuthor( aTmp );
+ aTimeStamp = aDT;
+ }
+ }
+ }
+
+ if( pTmp )
+ {
+ SwRedlineData aRedlnData( nsRedlineType_t::REDLINE_DELETE, nAuthor, aTimeStamp,
+ aEmptyStr, 0, 0 );
+ do {
+ // #i65201#: Expand again, see comment above.
+ if( pTmp->GetPoint()->nContent == 0 )
+ {
+ pTmp->GetPoint()->nNode++;
+ pTmp->GetPoint()->nContent.Assign( pTmp->GetCntntNode(), 0 );
+ }
+ // --> mst 2010-05-17 #i101009#
+ // prevent redlines that end on structural end node
+ if (& rDoc.GetNodes().GetEndOfContent() ==
+ & pTmp->GetPoint()->nNode.GetNode())
+ {
+ pTmp->GetPoint()->nNode--;
+ SwCntntNode *const pContentNode( pTmp->GetCntntNode() );
+ pTmp->GetPoint()->nContent.Assign( pContentNode,
+ (pContentNode) ? pContentNode->Len() : 0 );
+ }
+ // <--
+
+ rDoc.DeleteRedline( *pTmp, false, USHRT_MAX );
+
+ if (rDoc.GetIDocumentUndoRedo().DoesUndo())
+ {
+ SwUndo *const pUndo(new SwUndoCompDoc( *pTmp, sal_False )) ;
+ rDoc.GetIDocumentUndoRedo().AppendUndo(pUndo);
+ }
+ rDoc.AppendRedline( new SwRedline( aRedlnData, *pTmp ), true );
+
+ } while( pDelRing != ( pTmp = (SwPaM*)pTmp->GetNext() ));
+ }
+
+ pTmp = pInsRing;
+ if( pTmp )
+ {
+ do {
+ if( pTmp->GetPoint()->nContent == 0 )
+ {
+ pTmp->GetPoint()->nNode++;
+ pTmp->GetPoint()->nContent.Assign( pTmp->GetCntntNode(), 0 );
+ }
+ // --> mst 2010-05-17 #i101009#
+ // prevent redlines that end on structural end node
+ if (& rDoc.GetNodes().GetEndOfContent() ==
+ & pTmp->GetPoint()->nNode.GetNode())
+ {
+ pTmp->GetPoint()->nNode--;
+ SwCntntNode *const pContentNode( pTmp->GetCntntNode() );
+ pTmp->GetPoint()->nContent.Assign( pContentNode,
+ (pContentNode) ? pContentNode->Len() : 0 );
+ }
+ // <--
+ } while( pInsRing != ( pTmp = (SwPaM*)pTmp->GetNext() ));
+ SwRedlineData aRedlnData( nsRedlineType_t::REDLINE_INSERT, nAuthor, aTimeStamp,
+ aEmptyStr, 0, 0 );
+
+ // zusammenhaengende zusammenfassen
+ if( pTmp->GetNext() != pInsRing )
+ {
+ const SwCntntNode* pCNd;
+ do {
+ SwPosition& rSttEnd = *pTmp->End(),
+ & rEndStt = *((SwPaM*)pTmp->GetNext())->Start();
+ if( rSttEnd == rEndStt ||
+ (!rEndStt.nContent.GetIndex() &&
+ rEndStt.nNode.GetIndex() - 1 == rSttEnd.nNode.GetIndex() &&
+ 0 != ( pCNd = rSttEnd.nNode.GetNode().GetCntntNode() )
+ ? rSttEnd.nContent.GetIndex() == pCNd->Len()
+ : 0 ))
+ {
+ if( pTmp->GetNext() == pInsRing )
+ {
+ // liegen hintereinander also zusammen fassen
+ rEndStt = *pTmp->Start();
+ delete pTmp;
+ pTmp = pInsRing;
+ }
+ else
+ {
+ // liegen hintereinander also zusammen fassen
+ rSttEnd = *((SwPaM*)pTmp->GetNext())->End();
+ delete pTmp->GetNext();
+ }
+ }
+ else
+ pTmp = (SwPaM*)pTmp->GetNext();
+ } while( pInsRing != pTmp );
+ }
+
+ do {
+ if( rDoc.AppendRedline( new SwRedline( aRedlnData, *pTmp ), true) &&
+ rDoc.GetIDocumentUndoRedo().DoesUndo())
+ {
+ SwUndo *const pUndo(new SwUndoCompDoc( *pTmp, sal_True ));
+ rDoc.GetIDocumentUndoRedo().AppendUndo(pUndo);
+ }
+ } while( pInsRing != ( pTmp = (SwPaM*)pTmp->GetNext() ));
+ }
+}
+
+// returnt (?die Anzahl der Unterschiede?) ob etwas unterschiedlich ist
+long SwDoc::CompareDoc( const SwDoc& rDoc )
+{
+ if( &rDoc == this )
+ return 0;
+
+ long nRet = 0;
+
+ GetIDocumentUndoRedo().StartUndo(UNDO_EMPTY, NULL);
+ sal_Bool bDocWasModified = IsModified();
+ SwDoc& rSrcDoc = (SwDoc&)rDoc;
+ sal_Bool bSrcModified = rSrcDoc.IsModified();
+
+ RedlineMode_t eSrcRedlMode = rSrcDoc.GetRedlineMode();
+ rSrcDoc.SetRedlineMode( nsRedlineMode_t::REDLINE_SHOW_INSERT );
+ SetRedlineMode((RedlineMode_t)(nsRedlineMode_t::REDLINE_ON | nsRedlineMode_t::REDLINE_SHOW_INSERT));
+
+ SwCompareData aD0( rSrcDoc );
+ SwCompareData aD1( *this );
+
+ aD1.CompareLines( aD0 );
+
+ nRet = aD1.ShowDiffs( aD0 );
+
+ if( nRet )
+ {
+ SetRedlineMode((RedlineMode_t)(nsRedlineMode_t::REDLINE_ON |
+ nsRedlineMode_t::REDLINE_SHOW_INSERT | nsRedlineMode_t::REDLINE_SHOW_DELETE));
+
+ aD1.SetRedlinesToDoc( !bDocWasModified );
+ SetModified();
+ }
+
+ rSrcDoc.SetRedlineMode( eSrcRedlMode );
+ SetRedlineMode((RedlineMode_t)(nsRedlineMode_t::REDLINE_SHOW_INSERT | nsRedlineMode_t::REDLINE_SHOW_DELETE));
+
+ if( !bSrcModified )
+ rSrcDoc.ResetModified();
+
+ GetIDocumentUndoRedo().EndUndo(UNDO_EMPTY, NULL);
+
+ return nRet;
+}
+
+class _SaveMergeRedlines : public Ring
+{
+ const SwRedline* pSrcRedl;
+ SwRedline* pDestRedl;
+public:
+ _SaveMergeRedlines( const SwNode& rDstNd,
+ const SwRedline& rSrcRedl, Ring* pRing );
+ sal_uInt16 InsertRedline();
+
+ SwRedline* GetDestRedline() { return pDestRedl; }
+};
+
+_SaveMergeRedlines::_SaveMergeRedlines( const SwNode& rDstNd,
+ const SwRedline& rSrcRedl, Ring* pRing )
+ : Ring( pRing ), pSrcRedl( &rSrcRedl )
+{
+ SwPosition aPos( rDstNd );
+
+ const SwPosition* pStt = rSrcRedl.Start();
+ if( rDstNd.IsCntntNode() )
+ aPos.nContent.Assign( ((SwCntntNode*)&rDstNd), pStt->nContent.GetIndex() );
+ pDestRedl = new SwRedline( rSrcRedl.GetRedlineData(), aPos );
+
+ if( nsRedlineType_t::REDLINE_DELETE == pDestRedl->GetType() )
+ {
+ // den Bereich als geloescht kennzeichnen
+ const SwPosition* pEnd = pStt == rSrcRedl.GetPoint()
+ ? rSrcRedl.GetMark()
+ : rSrcRedl.GetPoint();
+
+ pDestRedl->SetMark();
+ pDestRedl->GetPoint()->nNode += pEnd->nNode.GetIndex() -
+ pStt->nNode.GetIndex();
+ pDestRedl->GetPoint()->nContent.Assign( pDestRedl->GetCntntNode(),
+ pEnd->nContent.GetIndex() );
+ }
+}
+
+sal_uInt16 _SaveMergeRedlines::InsertRedline()
+{
+ sal_uInt16 nIns = 0;
+ SwDoc* pDoc = pDestRedl->GetDoc();
+
+ if( nsRedlineType_t::REDLINE_INSERT == pDestRedl->GetType() )
+ {
+ // der Teil wurde eingefuegt, also kopiere ihn aus dem SourceDoc
+ ::sw::UndoGuard const undoGuard(pDoc->GetIDocumentUndoRedo());
+
+ SwNodeIndex aSaveNd( pDestRedl->GetPoint()->nNode, -1 );
+ xub_StrLen nSaveCnt = pDestRedl->GetPoint()->nContent.GetIndex();
+
+ RedlineMode_t eOld = pDoc->GetRedlineMode();
+ pDoc->SetRedlineMode_intern((RedlineMode_t)(eOld | nsRedlineMode_t::REDLINE_IGNORE));
+
+ pSrcRedl->GetDoc()->CopyRange(
+ *const_cast<SwPaM*>(static_cast<const SwPaM*>(pSrcRedl)),
+ *pDestRedl->GetPoint(), false );
+
+ pDoc->SetRedlineMode_intern( eOld );
+
+ pDestRedl->SetMark();
+ aSaveNd++;
+ pDestRedl->GetMark()->nNode = aSaveNd;
+ pDestRedl->GetMark()->nContent.Assign( aSaveNd.GetNode().GetCntntNode(),
+ nSaveCnt );
+
+ if( GetPrev() != this )
+ {
+ SwPaM* pTmpPrev = ((_SaveMergeRedlines*)GetPrev())->pDestRedl;
+ if( pTmpPrev && *pTmpPrev->GetPoint() == *pDestRedl->GetPoint() )
+ *pTmpPrev->GetPoint() = *pDestRedl->GetMark();
+ }
+ }
+ else
+ {
+ //JP 21.09.98: Bug 55909
+ // falls im Doc auf gleicher Pos aber schon ein geloeschter oder
+ // eingefuegter ist, dann muss dieser gesplittet werden!
+ SwPosition* pDStt = pDestRedl->GetMark(),
+ * pDEnd = pDestRedl->GetPoint();
+ sal_uInt16 n = 0;
+
+ // zur StartPos das erste Redline suchen
+ if( !pDoc->GetRedline( *pDStt, &n ) && n )
+ --n;
+
+ const SwRedlineTbl& rRedlineTbl = pDoc->GetRedlineTbl();
+ for( ; n < rRedlineTbl.Count(); ++n )
+ {
+ SwRedline* pRedl = rRedlineTbl[ n ];
+ SwPosition* pRStt = pRedl->Start(),
+ * pREnd = pRStt == pRedl->GetPoint() ? pRedl->GetMark()
+ : pRedl->GetPoint();
+ if( nsRedlineType_t::REDLINE_DELETE == pRedl->GetType() ||
+ nsRedlineType_t::REDLINE_INSERT == pRedl->GetType() )
+ {
+ SwComparePosition eCmpPos = ComparePosition( *pDStt, *pDEnd, *pRStt, *pREnd );
+ switch( eCmpPos )
+ {
+ case POS_COLLIDE_START:
+ case POS_BEHIND:
+ break;
+
+ case POS_INSIDE:
+ case POS_EQUAL:
+ delete pDestRedl, pDestRedl = 0;
+ // break; -> kein break !!!!
+
+ case POS_COLLIDE_END:
+ case POS_BEFORE:
+ n = rRedlineTbl.Count();
+ break;
+
+ case POS_OUTSIDE:
+ {
+ SwRedline* pCpyRedl = new SwRedline(
+ pDestRedl->GetRedlineData(), *pDStt );
+ pCpyRedl->SetMark();
+ *pCpyRedl->GetPoint() = *pRStt;
+
+ SwUndoCompDoc *const pUndo =
+ (pDoc->GetIDocumentUndoRedo().DoesUndo())
+ ? new SwUndoCompDoc( *pCpyRedl ) : 0;
+
+ // now modify doc: append redline, undo (and count)
+ pDoc->AppendRedline( pCpyRedl, true );
+ if( pUndo )
+ {
+ pDoc->GetIDocumentUndoRedo().AppendUndo(pUndo);
+ }
+ ++nIns;
+
+ *pDStt = *pREnd;
+
+ // dann solle man neu anfangen
+ n = USHRT_MAX;
+ }
+ break;
+
+ case POS_OVERLAP_BEFORE:
+ *pDEnd = *pRStt;
+ break;
+
+ case POS_OVERLAP_BEHIND:
+ *pDStt = *pREnd;
+ break;
+ }
+ }
+ else if( *pDEnd <= *pRStt )
+ break;
+ }
+
+ }
+
+ if( pDestRedl )
+ {
+ SwUndoCompDoc *const pUndo = (pDoc->GetIDocumentUndoRedo().DoesUndo())
+ ? new SwUndoCompDoc( *pDestRedl ) : 0;
+
+ // now modify doc: append redline, undo (and count)
+ bool bRedlineAccepted = pDoc->AppendRedline( pDestRedl, true );
+ if( pUndo )
+ {
+ pDoc->GetIDocumentUndoRedo().AppendUndo( pUndo );
+ }
+ ++nIns;
+
+ // if AppendRedline has deleted our redline, we may not keep a
+ // reference to it
+ if( ! bRedlineAccepted )
+ pDestRedl = NULL;
+ }
+ return nIns;
+}
+
+// merge zweier Dokumente
+long SwDoc::MergeDoc( const SwDoc& rDoc )
+{
+ if( &rDoc == this )
+ return 0;
+
+ long nRet = 0;
+
+ GetIDocumentUndoRedo().StartUndo(UNDO_EMPTY, NULL);
+
+ SwDoc& rSrcDoc = (SwDoc&)rDoc;
+ sal_Bool bSrcModified = rSrcDoc.IsModified();
+
+ RedlineMode_t eSrcRedlMode = rSrcDoc.GetRedlineMode();
+ rSrcDoc.SetRedlineMode( nsRedlineMode_t::REDLINE_SHOW_DELETE );
+ SetRedlineMode( nsRedlineMode_t::REDLINE_SHOW_DELETE );
+
+ SwCompareData aD0( rSrcDoc );
+ SwCompareData aD1( *this );
+
+ aD1.CompareLines( aD0 );
+
+ if( !aD1.HasDiffs( aD0 ) )
+ {
+ // jetzt wollen wir alle Redlines aus dem SourceDoc zu uns bekommen
+
+ // suche alle Insert - Redlines aus dem SourceDoc und bestimme
+ // deren Position im DestDoc
+ _SaveMergeRedlines* pRing = 0;
+ const SwRedlineTbl& rSrcRedlTbl = rSrcDoc.GetRedlineTbl();
+ sal_uLong nEndOfExtra = rSrcDoc.GetNodes().GetEndOfExtras().GetIndex();
+ sal_uLong nMyEndOfExtra = GetNodes().GetEndOfExtras().GetIndex();
+ for( sal_uInt16 n = 0; n < rSrcRedlTbl.Count(); ++n )
+ {
+ const SwRedline* pRedl = rSrcRedlTbl[ n ];
+ sal_uLong nNd = pRedl->GetPoint()->nNode.GetIndex();
+ RedlineType_t eType = pRedl->GetType();
+ if( nEndOfExtra < nNd &&
+ ( nsRedlineType_t::REDLINE_INSERT == eType || nsRedlineType_t::REDLINE_DELETE == eType ))
+ {
+ const SwNode* pDstNd = GetNodes()[
+ nMyEndOfExtra + nNd - nEndOfExtra ];
+
+ // Position gefunden. Dann muss im DestDoc auch
+ // in der Line das Redline eingefuegt werden
+ _SaveMergeRedlines* pTmp = new _SaveMergeRedlines(
+ *pDstNd, *pRedl, pRing );
+ if( !pRing )
+ pRing = pTmp;
+ }
+ }
+
+ if( pRing )
+ {
+ // dann alle ins DestDoc ueber nehmen
+ rSrcDoc.SetRedlineMode((RedlineMode_t)(nsRedlineMode_t::REDLINE_SHOW_INSERT | nsRedlineMode_t::REDLINE_SHOW_DELETE));
+
+ SetRedlineMode((RedlineMode_t)(
+ nsRedlineMode_t::REDLINE_ON |
+ nsRedlineMode_t::REDLINE_SHOW_INSERT |
+ nsRedlineMode_t::REDLINE_SHOW_DELETE));
+
+ _SaveMergeRedlines* pTmp = pRing;
+
+ do {
+ nRet += pTmp->InsertRedline();
+ } while( pRing != ( pTmp = (_SaveMergeRedlines*)pTmp->GetNext() ));
+
+ while( pRing != pRing->GetNext() )
+ delete pRing->GetNext();
+ delete pRing;
+ }
+ }
+
+ rSrcDoc.SetRedlineMode( eSrcRedlMode );
+ if( !bSrcModified )
+ rSrcDoc.ResetModified();
+
+ SetRedlineMode((RedlineMode_t)(nsRedlineMode_t::REDLINE_SHOW_INSERT | nsRedlineMode_t::REDLINE_SHOW_DELETE));
+
+ GetIDocumentUndoRedo().EndUndo(UNDO_EMPTY, NULL);
+
+ return nRet;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/doc/doccorr.cxx b/sw/source/core/doc/doccorr.cxx
new file mode 100644
index 000000000000..8f59503b2455
--- /dev/null
+++ b/sw/source/core/doc/doccorr.cxx
@@ -0,0 +1,360 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+
+#include <doc.hxx>
+#include <node.hxx>
+#include <rootfrm.hxx>
+#include <editsh.hxx>
+#include <viscrs.hxx>
+#include <IMark.hxx>
+#include <bookmrk.hxx>
+#include <redline.hxx>
+#include <mvsave.hxx>
+#include <docary.hxx>
+#include <unocrsr.hxx>
+#include <swundo.hxx>
+#include <hints.hxx>
+
+/*
+ * MACROS um ueber alle CrsrShells zu iterieren
+ */
+#define PCURSH ((SwCrsrShell*)_pStartShell)
+#define FOREACHSHELL_START( pEShell ) \
+ {\
+ ViewShell *_pStartShell = pEShell; \
+ do { \
+ if( _pStartShell->IsA( TYPE( SwCrsrShell )) ) \
+ {
+
+#define FOREACHSHELL_END( pEShell ) \
+ } \
+ } while((_pStartShell=(ViewShell*)_pStartShell->GetNext())!= pEShell ); \
+ }
+
+#define PCURCRSR (_pCurrCrsr)
+#define FOREACHPAM_START(pSttCrsr) \
+ {\
+ SwPaM *_pStartCrsr = pSttCrsr, *_pCurrCrsr = pSttCrsr; \
+ do {
+
+#define FOREACHPAM_END() \
+ } while( (_pCurrCrsr=(SwPaM *)_pCurrCrsr->GetNext()) != _pStartCrsr ); \
+ }
+
+namespace
+{
+ // find the relevant section in which the SwUnoCrsr may wander.
+ // returns NULL if no restrictions apply
+ static const SwStartNode* lcl_FindUnoCrsrSection( const SwNode& rNode )
+ {
+ const SwStartNode* pStartNode = rNode.StartOfSectionNode();
+ while( ( pStartNode != NULL ) &&
+ ( pStartNode->StartOfSectionNode() != pStartNode ) &&
+ ( pStartNode->GetStartNodeType() == SwNormalStartNode ) )
+ pStartNode = pStartNode->StartOfSectionNode();
+
+ return pStartNode;
+ }
+
+ static inline bool lcl_PosCorrAbs(SwPosition & rPos,
+ const SwPosition& rStart,
+ const SwPosition& rEnd,
+ const SwPosition& rNewPos)
+ {
+ if ((rStart <= rPos) && (rPos <= rEnd))
+ {
+ rPos = rNewPos;
+ return true;
+ }
+ return false;
+ };
+
+ static inline bool lcl_PaMCorrAbs(SwPaM & rPam,
+ const SwPosition& rStart,
+ const SwPosition& rEnd,
+ const SwPosition& rNewPos)
+ {
+ bool bRet = false;
+ bRet |= lcl_PosCorrAbs(rPam.GetBound(true ), rStart, rEnd, rNewPos);
+ bRet |= lcl_PosCorrAbs(rPam.GetBound(false), rStart, rEnd, rNewPos);
+ return bRet;
+ };
+
+ static inline void lcl_PaMCorrRel1(SwPaM * pPam,
+ SwNode const * const pOldNode,
+ const SwPosition& rNewPos,
+ const xub_StrLen nCntIdx)
+ {
+ for(int nb = 0; nb < 2; ++nb)
+ if(&((pPam)->GetBound(sal_Bool(nb)).nNode.GetNode()) == pOldNode)
+ {
+ (pPam)->GetBound(sal_Bool(nb)).nNode = rNewPos.nNode;
+ (pPam)->GetBound(sal_Bool(nb)).nContent.Assign(
+ const_cast<SwIndexReg*>(rNewPos.nContent.GetIdxReg()),
+ nCntIdx + (pPam)->GetBound(sal_Bool(nb)).nContent.GetIndex());
+ }
+ }
+}
+
+
+void PaMCorrAbs( const SwPaM& rRange,
+ const SwPosition& rNewPos )
+{
+ SwPosition const aStart( *rRange.Start() );
+ SwPosition const aEnd( *rRange.End() );
+ SwPosition const aNewPos( rNewPos );
+ SwDoc *const pDoc = aStart.nNode.GetNode().GetDoc();
+ SwCrsrShell *const pShell = pDoc->GetEditShell();
+
+ if( pShell )
+ {
+ FOREACHSHELL_START( pShell )
+ SwPaM *_pStkCrsr = PCURSH->GetStkCrsr();
+ if( _pStkCrsr )
+ do {
+ lcl_PaMCorrAbs( *_pStkCrsr, aStart, aEnd, aNewPos );
+ } while ( (_pStkCrsr != 0 ) &&
+ ((_pStkCrsr=(SwPaM *)_pStkCrsr->GetNext()) != PCURSH->GetStkCrsr()) );
+
+ FOREACHPAM_START( PCURSH->_GetCrsr() )
+ lcl_PaMCorrAbs( *PCURCRSR, aStart, aEnd, aNewPos );
+ FOREACHPAM_END()
+
+ if( PCURSH->IsTableMode() )
+ lcl_PaMCorrAbs( *PCURSH->GetTblCrs(), aStart, aEnd, aNewPos );
+
+ FOREACHSHELL_END( pShell )
+ }
+ {
+ SwUnoCrsrTbl& rTbl = const_cast<SwUnoCrsrTbl&>(pDoc->GetUnoCrsrTbl());
+
+ for( sal_uInt16 n = 0; n < rTbl.Count(); ++n )
+ {
+ SwUnoCrsr *const pUnoCursor = rTbl[ n ];
+
+ bool bChange = false; // has the UNO cursor been corrected?
+
+ // determine whether the UNO cursor will leave it's designated
+ // section
+ bool const bLeaveSection =
+ pUnoCursor->IsRemainInSection() &&
+ ( lcl_FindUnoCrsrSection( aNewPos.nNode.GetNode() ) !=
+ lcl_FindUnoCrsrSection(
+ pUnoCursor->GetPoint()->nNode.GetNode() ) );
+
+ FOREACHPAM_START( pUnoCursor )
+ bChange |= lcl_PaMCorrAbs( *PCURCRSR, aStart, aEnd, aNewPos );
+ FOREACHPAM_END()
+
+ SwUnoTableCrsr *const pUnoTblCrsr =
+ dynamic_cast<SwUnoTableCrsr *>(rTbl[ n ]);
+ if( pUnoTblCrsr )
+ {
+ FOREACHPAM_START( &pUnoTblCrsr->GetSelRing() )
+ bChange |=
+ lcl_PaMCorrAbs( *PCURCRSR, aStart, aEnd, aNewPos );
+ FOREACHPAM_END()
+ }
+
+ // if a UNO cursor leaves its designated section, we must inform
+ // (and invalidate) said cursor
+ if (bChange && bLeaveSection)
+ {
+ // the UNO cursor has left its section. We need to notify it!
+ SwMsgPoolItem aHint( RES_UNOCURSOR_LEAVES_SECTION );
+ pUnoCursor->ModifyNotification( &aHint, NULL );
+ }
+ }
+ }
+}
+
+void SwDoc::CorrAbs(const SwNodeIndex& rOldNode,
+ const SwPosition& rNewPos,
+ const xub_StrLen nOffset,
+ sal_Bool bMoveCrsr)
+{
+ SwCntntNode *const pCntntNode( rOldNode.GetNode().GetCntntNode() );
+ SwPaM const aPam(rOldNode, 0,
+ rOldNode, (pCntntNode) ? pCntntNode->Len() : 0);
+ SwPosition aNewPos(rNewPos);
+ aNewPos.nContent += nOffset;
+
+ getIDocumentMarkAccess()->correctMarksAbsolute(rOldNode, rNewPos, nOffset);
+ { // fix redlines
+ SwRedlineTbl& rTbl = *pRedlineTbl;
+ for( sal_uInt16 n = 0; n < rTbl.Count(); ++n )
+ {
+ // is on position ??
+ lcl_PaMCorrAbs(*rTbl[ n ], *aPam.Start(), *aPam.End(), aNewPos);
+ }
+ }
+
+ if(bMoveCrsr)
+ {
+ ::PaMCorrAbs(aPam, aNewPos);
+ }
+}
+
+void SwDoc::CorrAbs(const SwPaM& rRange,
+ const SwPosition& rNewPos,
+ sal_Bool bMoveCrsr)
+{
+ SwPosition aStart(*rRange.Start());
+ SwPosition aEnd(*rRange.End());
+ SwPosition aNewPos(rNewPos);
+
+ _DelBookmarks(aStart.nNode, aEnd.nNode, NULL,
+ &aStart.nContent, &aEnd.nContent);
+ if(bMoveCrsr)
+ ::PaMCorrAbs(rRange, rNewPos);
+}
+
+void SwDoc::CorrAbs(const SwNodeIndex& rStartNode,
+ const SwNodeIndex& rEndNode,
+ const SwPosition& rNewPos,
+ sal_Bool bMoveCrsr)
+{
+ _DelBookmarks(rStartNode, rEndNode);
+
+ if(bMoveCrsr)
+ {
+ SwCntntNode *const pCntntNode( rEndNode.GetNode().GetCntntNode() );
+ SwPaM const aPam(rStartNode, 0,
+ rEndNode, (pCntntNode) ? pCntntNode->Len() : 0);
+ ::PaMCorrAbs(aPam, rNewPos);
+ }
+}
+
+
+
+
+
+void PaMCorrRel( const SwNodeIndex &rOldNode,
+ const SwPosition &rNewPos,
+ const xub_StrLen nOffset )
+{
+ const SwNode* pOldNode = &rOldNode.GetNode();
+ SwPosition aNewPos( rNewPos );
+ const SwDoc* pDoc = pOldNode->GetDoc();
+
+ xub_StrLen nCntIdx = rNewPos.nContent.GetIndex() + nOffset;
+
+ SwCrsrShell* pShell = pDoc->GetEditShell();
+ if( pShell )
+ {
+ FOREACHSHELL_START( pShell )
+ SwPaM *_pStkCrsr = PCURSH->GetStkCrsr();
+ if( _pStkCrsr )
+ do {
+ lcl_PaMCorrRel1( _pStkCrsr, pOldNode, aNewPos, nCntIdx );
+ } while ( (_pStkCrsr != 0 ) &&
+ ((_pStkCrsr=(SwPaM *)_pStkCrsr->GetNext()) != PCURSH->GetStkCrsr()) );
+
+ FOREACHPAM_START( PCURSH->_GetCrsr() )
+ lcl_PaMCorrRel1( PCURCRSR, pOldNode, aNewPos, nCntIdx);
+ FOREACHPAM_END()
+
+ if( PCURSH->IsTableMode() )
+ lcl_PaMCorrRel1( PCURSH->GetTblCrs(), pOldNode, aNewPos, nCntIdx );
+
+ FOREACHSHELL_END( pShell )
+ }
+ {
+ SwUnoCrsrTbl& rTbl = (SwUnoCrsrTbl&)pDoc->GetUnoCrsrTbl();
+ for( sal_uInt16 n = 0; n < rTbl.Count(); ++n )
+ {
+ FOREACHPAM_START( rTbl[ n ] )
+ lcl_PaMCorrRel1( PCURCRSR, pOldNode, aNewPos, nCntIdx );
+ FOREACHPAM_END()
+
+ SwUnoTableCrsr* pUnoTblCrsr =
+ dynamic_cast<SwUnoTableCrsr*>(rTbl[ n ]);
+ if( pUnoTblCrsr )
+ {
+ FOREACHPAM_START( &pUnoTblCrsr->GetSelRing() )
+ lcl_PaMCorrRel1( PCURCRSR, pOldNode, aNewPos, nCntIdx );
+ FOREACHPAM_END()
+ }
+ }
+ }
+}
+
+void SwDoc::CorrRel(const SwNodeIndex& rOldNode,
+ const SwPosition& rNewPos,
+ const xub_StrLen nOffset,
+ sal_Bool bMoveCrsr)
+{
+ getIDocumentMarkAccess()->correctMarksRelative(rOldNode, rNewPos, nOffset);
+
+ { // dann die Redlines korrigieren
+ SwRedlineTbl& rTbl = *pRedlineTbl;
+ SwPosition aNewPos(rNewPos);
+ for( sal_uInt16 n = 0; n < rTbl.Count(); ++n )
+ {
+ // liegt auf der Position ??
+ lcl_PaMCorrRel1( rTbl[ n ], &rOldNode.GetNode(), aNewPos, aNewPos.nContent.GetIndex() + nOffset );
+ }
+ }
+
+ if(bMoveCrsr)
+ ::PaMCorrRel(rOldNode, rNewPos, nOffset);
+}
+
+
+SwEditShell* SwDoc::GetEditShell( ViewShell** ppSh ) const
+{
+ // Layout und OLE-Shells sollten vorhanden sein!
+ if( pCurrentView )
+ {
+ ViewShell *pSh = pCurrentView, *pVSh = pSh;
+ if( ppSh )
+ *ppSh = pSh;
+
+ // wir suchen uns eine EditShell, falls diese existiert
+ do {
+ if( pSh->IsA( TYPE( SwEditShell ) ) )
+ return (SwEditShell*)pSh;
+
+ } while( pVSh != ( pSh = (ViewShell*)pSh->GetNext() ));
+ }
+ else if( ppSh )
+ *ppSh = 0; //swmod 071029//swmod 071225
+
+ return 0;
+}
+
+::sw::IShellCursorSupplier * SwDoc::GetIShellCursorSupplier()
+{
+ return GetEditShell(0);
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/doc/docdde.cxx b/sw/source/core/doc/docdde.cxx
new file mode 100644
index 000000000000..10892ca2a611
--- /dev/null
+++ b/sw/source/core/doc/docdde.cxx
@@ -0,0 +1,418 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+
+
+#include <stdlib.h>
+
+#include <vcl/svapp.hxx>
+#include <tools/urlobj.hxx>
+
+#define _SVSTDARR_STRINGS
+#include <svl/svstdarr.hxx>
+#include <sfx2/linkmgr.hxx> // LinkManager
+#include <unotools/charclass.hxx>
+#include <fmtcntnt.hxx>
+#include <doc.hxx>
+#include <swserv.hxx> // fuer Server-Funktionalitaet
+#include <IMark.hxx>
+#include <bookmrk.hxx>
+#include <section.hxx> // fuer SwSectionFmt
+#include <swtable.hxx> // fuer SwTable
+#include <node.hxx>
+#include <ndtxt.hxx>
+#include <pam.hxx>
+#include <docary.hxx>
+#include <MarkManager.hxx>
+
+using namespace ::com::sun::star;
+
+namespace
+{
+
+ static ::sw::mark::DdeBookmark* lcl_FindDdeBookmark(const IDocumentMarkAccess& rMarkAccess, const String& rName, bool bCaseSensitive)
+ {
+ //Iterating over all bookmarks, checking DdeBookmarks
+ const ::rtl::OUString sNameLc = bCaseSensitive ? rName : GetAppCharClass().lower(rName);
+ for(IDocumentMarkAccess::const_iterator_t ppMark = rMarkAccess.getMarksBegin();
+ ppMark != rMarkAccess.getMarksEnd();
+ ppMark++)
+ {
+ if (::sw::mark::DdeBookmark* const pBkmk = dynamic_cast< ::sw::mark::DdeBookmark*>(ppMark->get()))
+ {
+ if (
+ (bCaseSensitive && (pBkmk->GetName() == sNameLc)) ||
+ (!bCaseSensitive && GetAppCharClass().lower(pBkmk->GetName()) == String(sNameLc))
+ )
+ {
+ return pBkmk;
+ }
+ }
+ }
+ return NULL;
+ }
+}
+
+struct _FindItem
+{
+ const String m_Item;
+ SwTableNode* pTblNd;
+ SwSectionNode* pSectNd;
+
+ _FindItem(const String& rS)
+ : m_Item(rS), pTblNd(0), pSectNd(0)
+ {}
+};
+
+sal_Bool lcl_FindSection( const SwSectionFmtPtr& rpSectFmt, void* pArgs, bool bCaseSensitive )
+{
+ _FindItem * const pItem( static_cast<_FindItem*>(pArgs) );
+ SwSection* pSect = rpSectFmt->GetSection();
+ if( pSect )
+ {
+ String sNm( (bCaseSensitive)
+ ? pSect->GetSectionName()
+ : GetAppCharClass().lower( pSect->GetSectionName() ));
+ String sCompare( (bCaseSensitive)
+ ? pItem->m_Item
+ : GetAppCharClass().lower( pItem->m_Item ) );
+ if( sNm == sCompare )
+ {
+ // gefunden, als erfrage die Daten
+ const SwNodeIndex* pIdx;
+ if( 0 != (pIdx = rpSectFmt->GetCntnt().GetCntntIdx() ) &&
+ &rpSectFmt->GetDoc()->GetNodes() == &pIdx->GetNodes() )
+ {
+ // eine Tabelle im normalen NodesArr
+ pItem->pSectNd = pIdx->GetNode().GetSectionNode();
+ return sal_False;
+ }
+//nein!! // sollte der Namen schon passen, der Rest aber nicht, dann haben wir
+ // sie nicht. Die Namen sind immer eindeutig.
+ }
+ }
+ return sal_True; // dann weiter
+}
+sal_Bool lcl_FindSectionCaseSensitive( const SwSectionFmtPtr& rpSectFmt, void* pArgs )
+{
+ return lcl_FindSection( rpSectFmt, pArgs, true );
+}
+sal_Bool lcl_FindSectionCaseInsensitive( const SwSectionFmtPtr& rpSectFmt, void* pArgs )
+{
+ return lcl_FindSection( rpSectFmt, pArgs, false );
+}
+
+
+
+sal_Bool lcl_FindTable( const SwFrmFmtPtr& rpTableFmt, void* pArgs )
+{
+ _FindItem * const pItem( static_cast<_FindItem*>(pArgs) );
+ String sNm( GetAppCharClass().lower( rpTableFmt->GetName() ));
+ if (sNm.Equals( pItem->m_Item ))
+ {
+ SwTable* pTmpTbl;
+ SwTableBox* pFBox;
+ if( 0 != ( pTmpTbl = SwTable::FindTable( rpTableFmt ) ) &&
+ 0 != ( pFBox = pTmpTbl->GetTabSortBoxes()[0] ) &&
+ pFBox->GetSttNd() &&
+ &rpTableFmt->GetDoc()->GetNodes() == &pFBox->GetSttNd()->GetNodes() )
+ {
+ // eine Tabelle im normalen NodesArr
+ pItem->pTblNd = (SwTableNode*)
+ pFBox->GetSttNd()->FindTableNode();
+ return sal_False;
+ }
+//nein! // sollte der Namen schon passen, der Rest aber nicht, dann haben wir
+ // sie nicht. Die Namen sind immer eindeutig.
+ }
+ return sal_True; // dann weiter
+}
+
+
+
+bool SwDoc::GetData( const String& rItem, const String& rMimeType,
+ uno::Any & rValue ) const
+{
+ //search for bookmarks and sections case senstive at first. If nothing is found then try again case insensitive
+ bool bCaseSensitive = true;
+ while( true )
+ {
+ ::sw::mark::DdeBookmark* const pBkmk = lcl_FindDdeBookmark(*pMarkManager, rItem, bCaseSensitive);
+ if(pBkmk)
+ return SwServerObject(*pBkmk).GetData(rValue, rMimeType);
+
+ // haben wir ueberhaupt das Item vorraetig?
+ String sItem( bCaseSensitive ? rItem : GetAppCharClass().lower(rItem));
+ _FindItem aPara( sItem );
+ ((SwSectionFmts&)*pSectionFmtTbl).ForEach( 0, pSectionFmtTbl->Count(),
+ bCaseSensitive ? lcl_FindSectionCaseSensitive : lcl_FindSectionCaseInsensitive, &aPara );
+ if( aPara.pSectNd )
+ {
+ // gefunden, als erfrage die Daten
+ return SwServerObject( *aPara.pSectNd ).GetData( rValue, rMimeType );
+ }
+ if( !bCaseSensitive )
+ break;
+ bCaseSensitive = false;
+ }
+
+ _FindItem aPara( GetAppCharClass().lower( rItem ));
+ ((SwFrmFmts*)pTblFrmFmtTbl)->ForEach( 0, pTblFrmFmtTbl->Count(),
+ lcl_FindTable, &aPara );
+ if( aPara.pTblNd )
+ {
+ return SwServerObject( *aPara.pTblNd ).GetData( rValue, rMimeType );
+ }
+
+ return sal_False;
+}
+
+
+
+bool SwDoc::SetData( const String& rItem, const String& rMimeType,
+ const uno::Any & rValue )
+{
+ //search for bookmarks and sections case senstive at first. If nothing is found then try again case insensitive
+ bool bCaseSensitive = true;
+ while( true )
+ {
+ ::sw::mark::DdeBookmark* const pBkmk = lcl_FindDdeBookmark(*pMarkManager, rItem, bCaseSensitive);
+ if(pBkmk)
+ return SwServerObject(*pBkmk).SetData(rMimeType, rValue);
+
+ // haben wir ueberhaupt das Item vorraetig?
+ String sItem( bCaseSensitive ? rItem : GetAppCharClass().lower(rItem));
+ _FindItem aPara( sItem );
+ pSectionFmtTbl->ForEach( 0, pSectionFmtTbl->Count(), bCaseSensitive ? lcl_FindSectionCaseSensitive : lcl_FindSectionCaseInsensitive, &aPara );
+ if( aPara.pSectNd )
+ {
+ // gefunden, als erfrage die Daten
+ return SwServerObject( *aPara.pSectNd ).SetData( rMimeType, rValue );
+ }
+ if( !bCaseSensitive )
+ break;
+ bCaseSensitive = false;
+ }
+
+ String sItem(GetAppCharClass().lower(rItem));
+ _FindItem aPara( sItem );
+ pTblFrmFmtTbl->ForEach( 0, pTblFrmFmtTbl->Count(), lcl_FindTable, &aPara );
+ if( aPara.pTblNd )
+ {
+ return SwServerObject( *aPara.pTblNd ).SetData( rMimeType, rValue );
+ }
+
+ return sal_False;
+}
+
+
+
+::sfx2::SvLinkSource* SwDoc::CreateLinkSource(const String& rItem)
+{
+ SwServerObject* pObj = NULL;
+
+ //search for bookmarks and sections case senstive at first. If nothing is found then try again case insensitive
+ bool bCaseSensitive = true;
+ while( true )
+ {
+ // bookmarks
+ ::sw::mark::DdeBookmark* const pBkmk = lcl_FindDdeBookmark(*pMarkManager, rItem, bCaseSensitive);
+ if(pBkmk && pBkmk->IsExpanded()
+ && (0 == (pObj = pBkmk->GetRefObject())))
+ {
+ // mark found, but no link yet -> create hotlink
+ pObj = new SwServerObject(*pBkmk);
+ pBkmk->SetRefObject(pObj);
+ GetLinkManager().InsertServer(pObj);
+ }
+ if(pObj)
+ return pObj;
+
+ _FindItem aPara(bCaseSensitive ? rItem : GetAppCharClass().lower(rItem));
+ // sections
+ ((SwSectionFmts&)*pSectionFmtTbl).ForEach(0, pSectionFmtTbl->Count(), bCaseSensitive ? lcl_FindSectionCaseSensitive : lcl_FindSectionCaseInsensitive, &aPara);
+ if(aPara.pSectNd
+ && (0 == (pObj = aPara.pSectNd->GetSection().GetObject())))
+ {
+ // section found, but no link yet -> create hotlink
+ pObj = new SwServerObject( *aPara.pSectNd );
+ aPara.pSectNd->GetSection().SetRefObject( pObj );
+ GetLinkManager().InsertServer(pObj);
+ }
+ if(pObj)
+ return pObj;
+ if( !bCaseSensitive )
+ break;
+ bCaseSensitive = false;
+ }
+
+ _FindItem aPara( GetAppCharClass().lower(rItem) );
+ // tables
+ ((SwFrmFmts*)pTblFrmFmtTbl)->ForEach(0, pTblFrmFmtTbl->Count(), lcl_FindTable, &aPara);
+ if(aPara.pTblNd
+ && (0 == (pObj = aPara.pTblNd->GetTable().GetObject())))
+ {
+ // table found, but no link yet -> create hotlink
+ pObj = new SwServerObject(*aPara.pTblNd);
+ aPara.pTblNd->GetTable().SetRefObject(pObj);
+ GetLinkManager().InsertServer(pObj);
+ }
+ return pObj;
+}
+
+sal_Bool SwDoc::SelectServerObj( const String& rStr, SwPaM*& rpPam,
+ SwNodeRange*& rpRange ) const
+{
+ // haben wir ueberhaupt das Item vorraetig?
+ rpPam = 0;
+ rpRange = 0;
+
+ String sItem( INetURLObject::decode( rStr, INET_HEX_ESCAPE,
+ INetURLObject::DECODE_WITH_CHARSET,
+ RTL_TEXTENCODING_UTF8 ));
+
+ xub_StrLen nPos = sItem.Search( cMarkSeperator );
+
+ const CharClass& rCC = GetAppCharClass();
+
+ // Erweiterung fuer die Bereiche, nicht nur Bookmarks/Bereiche linken,
+ // sondern auch Rahmen(Text!), Tabellen, Gliederungen:
+ if( STRING_NOTFOUND != nPos )
+ {
+ sal_Bool bWeiter = sal_False;
+ String sName( sItem.Copy( 0, nPos ) );
+ String sCmp( sItem.Copy( nPos + 1 ));
+ rCC.toLower( sItem );
+
+ _FindItem aPara( sName );
+
+ if( sCmp.EqualsAscii( pMarkToTable ) )
+ {
+ rCC.toLower( sName );
+ ((SwFrmFmts*)pTblFrmFmtTbl)->ForEach( 0, pTblFrmFmtTbl->Count(),
+ lcl_FindTable, &aPara );
+ if( aPara.pTblNd )
+ {
+ rpRange = new SwNodeRange( *aPara.pTblNd, 0,
+ *aPara.pTblNd->EndOfSectionNode(), 1 );
+ return sal_True;
+ }
+ }
+ else if( sCmp.EqualsAscii( pMarkToFrame ) )
+ {
+ SwNodeIndex* pIdx;
+ SwNode* pNd;
+ const SwFlyFrmFmt* pFlyFmt = FindFlyByName( sName );
+ if( pFlyFmt &&
+ 0 != ( pIdx = (SwNodeIndex*)pFlyFmt->GetCntnt().GetCntntIdx() ) &&
+ !( pNd = &pIdx->GetNode())->IsNoTxtNode() )
+ {
+ rpRange = new SwNodeRange( *pNd, 1, *pNd->EndOfSectionNode() );
+ return sal_True;
+ }
+ }
+ else if( sCmp.EqualsAscii( pMarkToRegion ) )
+ {
+ sItem = sName; // wird unten behandelt !
+ bWeiter = sal_True;
+ }
+ else if( sCmp.EqualsAscii( pMarkToOutline ) )
+ {
+ SwPosition aPos( SwNodeIndex( (SwNodes&)GetNodes() ));
+ if( GotoOutline( aPos, sName ))
+ {
+ SwNode* pNd = &aPos.nNode.GetNode();
+ //sal_uInt8 nLvl = pNd->GetTxtNode()->GetTxtColl()->GetOutlineLevel();//#outline level,zhaojianwei
+ const int nLvl = pNd->GetTxtNode()->GetAttrOutlineLevel()-1;//<-end,zhaojianwei
+
+ const SwOutlineNodes& rOutlNds = GetNodes().GetOutLineNds();
+ sal_uInt16 nTmpPos;
+ rOutlNds.Seek_Entry( pNd, &nTmpPos );
+ rpRange = new SwNodeRange( aPos.nNode, 0, aPos.nNode );
+
+ // dann suche jetzt noch das Ende vom Bereich
+ for( ++nTmpPos;
+ nTmpPos < rOutlNds.Count() &&
+ nLvl < rOutlNds[ nTmpPos ]->GetTxtNode()->
+ //GetTxtColl()->GetOutlineLevel();//#outline level,zhaojianwei
+ GetAttrOutlineLevel()-1;//<-end,zhaojianwei
+ ++nTmpPos )
+ ; // es gibt keinen Block
+
+ if( nTmpPos < rOutlNds.Count() )
+ rpRange->aEnd = *rOutlNds[ nTmpPos ];
+ else
+ rpRange->aEnd = GetNodes().GetEndOfContent();
+ return sal_True;
+ }
+ }
+
+ if( !bWeiter )
+ return sal_False;
+ }
+
+ //search for bookmarks and sections case senstive at first. If nothing is found then try again case insensitive
+ bool bCaseSensitive = true;
+ while( true )
+ {
+ ::sw::mark::DdeBookmark* const pBkmk = lcl_FindDdeBookmark(*pMarkManager, sItem, bCaseSensitive);
+ if(pBkmk)
+ {
+ if(pBkmk->IsExpanded())
+ rpPam = new SwPaM(
+ pBkmk->GetMarkPos(),
+ pBkmk->GetOtherMarkPos());
+ return static_cast<bool>(rpPam);
+ }
+
+ //
+ _FindItem aPara( bCaseSensitive ? sItem : rCC.lower( sItem ) );
+
+ if( pSectionFmtTbl->Count() )
+ {
+ ((SwSectionFmts&)*pSectionFmtTbl).ForEach( 0, pSectionFmtTbl->Count(),
+ bCaseSensitive ? lcl_FindSectionCaseSensitive : lcl_FindSectionCaseInsensitive, &aPara );
+ if( aPara.pSectNd )
+ {
+ rpRange = new SwNodeRange( *aPara.pSectNd, 1,
+ *aPara.pSectNd->EndOfSectionNode() );
+ return sal_True;
+
+ }
+ }
+ if( !bCaseSensitive )
+ break;
+ bCaseSensitive = false;
+ }
+ return sal_False;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/doc/docdesc.cxx b/sw/source/core/doc/docdesc.cxx
new file mode 100644
index 000000000000..6133185a6b7a
--- /dev/null
+++ b/sw/source/core/doc/docdesc.cxx
@@ -0,0 +1,907 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+#include <hintids.hxx>
+#include <vcl/virdev.hxx>
+#include <svx/svdmodel.hxx>
+#include <editeng/ulspitem.hxx>
+#include <editeng/lrspitem.hxx>
+#include <editeng/paperinf.hxx>
+#include "editeng/frmdiritem.hxx"
+#include <tools/urlobj.hxx>
+#include <sfx2/docfile.hxx>
+#include <sfx2/printer.hxx>
+#include <unotools/localedatawrapper.hxx>
+#include <com/sun/star/document/PrinterIndependentLayout.hpp>
+#include <fmtfsize.hxx>
+#include <fmthdft.hxx>
+#include <fmtcntnt.hxx>
+#include <fmtpdsc.hxx>
+#include <ftninfo.hxx>
+#include <fesh.hxx>
+#include <ndole.hxx>
+#include <mdiexp.hxx>
+#include <doc.hxx>
+#include <IDocumentUndoRedo.hxx>
+#include <docary.hxx>
+#include <pagefrm.hxx> //Fuer DelPageDesc
+#include <rootfrm.hxx> //Fuer DelPageDesc
+#include <ndtxt.hxx>
+#include <frmtool.hxx>
+#include <pagedesc.hxx>
+#include <poolfmt.hxx>
+#include <docsh.hxx>
+#include <ndindex.hxx>
+#include <ftnidx.hxx>
+#include <fmtftn.hxx>
+#include <txtftn.hxx>
+#include <fntcache.hxx>
+#include <viewsh.hxx>
+#include <viewopt.hxx>
+#include <fldbas.hxx>
+#include <swwait.hxx>
+#include <GetMetricVal.hxx>
+#include <unotools/syslocale.hxx>
+#include <statstr.hrc>
+#include <switerator.hxx>
+#include <hints.hxx>
+#include <SwUndoPageDesc.hxx>
+#include <pagedeschint.hxx>
+#include <tgrditem.hxx>
+
+using namespace com::sun::star;
+
+static void lcl_DefaultPageFmt( sal_uInt16 nPoolFmtId,
+ SwFrmFmt &rFmt1,
+ SwFrmFmt &rFmt2 )
+{
+ // --> FME 2005-01-21 #i41075# Printer on demand
+ // This function does not require a printer anymore.
+ // The default page size is obtained from the application
+ //locale
+ // <--
+
+ SwFmtFrmSize aFrmSize( ATT_FIX_SIZE );
+ const Size aPhysSize = SvxPaperInfo::GetDefaultPaperSize();
+ aFrmSize.SetSize( aPhysSize );
+
+ //Auf Default-Raender vorbereiten.
+ //Raender haben eine defaultmaessige Mindestgroesse.
+ //wenn der Drucker einen groesseren Rand vorgibt, so
+ //ist mir dass auch recht.
+ // The HTML page desc had A4 as page size always.
+ // This has been changed to take the page size from the printer.
+ // Unfortunately, the margins of the HTML page desc are smaller than
+ // the margins used here in general, so one extra case is required.
+ // In the long term, this needs to be changed to always keep the
+ // margins from the page desc.
+ sal_Int32 nMinTop, nMinBottom, nMinLeft, nMinRight;
+ if( RES_POOLPAGE_HTML == nPoolFmtId )
+ {
+ nMinRight = nMinTop = nMinBottom = GetMetricVal( CM_1 );
+ nMinLeft = nMinRight * 2;
+ }
+ else if( MEASURE_METRIC == SvtSysLocale().GetLocaleData().getMeasurementSystemEnum() )
+ {
+ nMinTop = nMinBottom = nMinLeft = nMinRight = 1134; //2 Zentimeter
+ }
+ else
+ {
+ nMinTop = nMinBottom = 1440; //al la WW: 1Inch
+ nMinLeft = nMinRight = 1800; // 1,25 Inch
+ }
+
+ //Raender einstellen.
+ SvxLRSpaceItem aLR( RES_LR_SPACE );
+ SvxULSpaceItem aUL( RES_UL_SPACE );
+
+ aUL.SetUpper( (sal_uInt16)nMinTop );
+ aUL.SetLower( (sal_uInt16)nMinBottom );
+ aLR.SetRight( nMinRight );
+ aLR.SetLeft( nMinLeft );
+
+ rFmt1.SetFmtAttr( aFrmSize );
+ rFmt1.SetFmtAttr( aLR );
+ rFmt1.SetFmtAttr( aUL );
+
+ rFmt2.SetFmtAttr( aFrmSize );
+ rFmt2.SetFmtAttr( aLR );
+ rFmt2.SetFmtAttr( aUL );
+}
+
+/*************************************************************************
+|*
+|* SwDoc::ChgPageDesc()
+|*
+|*************************************************************************/
+
+void lcl_DescSetAttr( const SwFrmFmt &rSource, SwFrmFmt &rDest,
+ const sal_Bool bPage = sal_True )
+{
+/////////////// !!!!!!!!!!!!!!!!
+//JP 03.03.99:
+// eigentlich sollte hier das Intersect von ItemSet benutzt werden, aber das
+// funktioniert nicht richtig, wenn man unterschiedliche WhichRanges hat.
+/////////////// !!!!!!!!!!!!!!!!
+ //Die interressanten Attribute uebernehmen.
+ sal_uInt16 const aIdArr[] = { RES_FRM_SIZE, RES_UL_SPACE,
+ RES_BACKGROUND, RES_SHADOW,
+ RES_COL, RES_COL,
+ RES_FRAMEDIR, RES_FRAMEDIR,
+ RES_TEXTGRID, RES_TEXTGRID,
+ // --> FME 2005-04-18 #i45539#
+ RES_HEADER_FOOTER_EAT_SPACING,
+ RES_HEADER_FOOTER_EAT_SPACING,
+ // <--
+ RES_UNKNOWNATR_CONTAINER,
+ RES_UNKNOWNATR_CONTAINER,
+ 0 };
+
+ const SfxPoolItem* pItem;
+ for( sal_uInt16 n = 0; aIdArr[ n ]; n += 2 )
+ {
+ for( sal_uInt16 nId = aIdArr[ n ]; nId <= aIdArr[ n+1]; ++nId )
+ {
+ // --> FME 2005-04-18 #i45539#
+ // bPage == true:
+ // All in aIdArr except from RES_HEADER_FOOTER_EAT_SPACING
+ // bPage == false:
+ // All in aIdArr except from RES_COL and RES_PAPER_BIN:
+ // <--
+ if( ( bPage && RES_HEADER_FOOTER_EAT_SPACING != nId ) ||
+ ( !bPage && RES_COL != nId && RES_PAPER_BIN != nId ))
+ {
+ if( SFX_ITEM_SET == rSource.GetItemState( nId, sal_False, &pItem ))
+ rDest.SetFmtAttr( *pItem );
+ else
+ rDest.ResetFmtAttr( nId );
+ }
+ }
+ }
+
+ // auch Pool-, Hilfe-Id's uebertragen
+ rDest.SetPoolFmtId( rSource.GetPoolFmtId() );
+ rDest.SetPoolHelpId( rSource.GetPoolHelpId() );
+ rDest.SetPoolHlpFileId( rSource.GetPoolHlpFileId() );
+}
+
+
+void SwDoc::ChgPageDesc( sal_uInt16 i, const SwPageDesc &rChged )
+{
+ OSL_ENSURE( i < aPageDescs.Count(), "PageDescs ueberindiziert." );
+
+ SwPageDesc *pDesc = aPageDescs[i];
+ SwRootFrm* pTmpRoot = GetCurrentLayout();//swmod 080219
+
+ if (GetIDocumentUndoRedo().DoesUndo())
+ {
+ SwUndo *const pUndo(new SwUndoPageDesc(*pDesc, rChged, this));
+ GetIDocumentUndoRedo().AppendUndo(pUndo);
+ }
+ ::sw::UndoGuard const undoGuard(GetIDocumentUndoRedo());
+
+ //Als erstes wird ggf. gespiegelt.
+ if ( rChged.GetUseOn() == nsUseOnPage::PD_MIRROR )
+ ((SwPageDesc&)rChged).Mirror();
+ else
+ //sonst Werte aus Master nach Left uebertragen.
+ ::lcl_DescSetAttr( ((SwPageDesc&)rChged).GetMaster(),
+ ((SwPageDesc&)rChged).GetLeft() );
+
+ //NumType uebernehmen.
+ if( rChged.GetNumType().GetNumberingType() != pDesc->GetNumType().GetNumberingType() )
+ {
+ pDesc->SetNumType( rChged.GetNumType() );
+ // JP 30.03.99: Bug 64121 - den Seitennummernfeldern bescheid sagen,
+ // das sich das Num-Format geaendert hat
+ GetSysFldType( RES_PAGENUMBERFLD )->UpdateFlds();
+ GetSysFldType( RES_REFPAGEGETFLD )->UpdateFlds();
+
+ // Wenn sich die Numerierungsart geaendert hat, koennte es QuoVadis/
+ // ErgoSum-Texte geben, die sich auf eine geaenderte Seite beziehen,
+ // deshalb werden die Fussnoten invalidiert
+ SwFtnIdxs& rFtnIdxs = GetFtnIdxs();
+ for( sal_uInt16 nPos = 0; nPos < rFtnIdxs.Count(); ++nPos )
+ {
+ SwTxtFtn *pTxtFtn = rFtnIdxs[ nPos ];
+ const SwFmtFtn &rFtn = pTxtFtn->GetFtn();
+ pTxtFtn->SetNumber( rFtn.GetNumber(), &rFtn.GetNumStr());
+ }
+ }
+
+ //Orientierung uebernehmen
+ pDesc->SetLandscape( rChged.GetLandscape() );
+
+ // #i46909# no undo if header or footer changed
+ bool bHeaderFooterChanged = false;
+
+ //Header abgleichen.
+ const SwFmtHeader &rHead = rChged.GetMaster().GetHeader();
+ if (undoGuard.UndoWasEnabled())
+ {
+ // #i46909# no undo if header or footer changed
+ // hat sich an den Nodes etwas veraendert ?
+ const SwFmtHeader &rOldHead = pDesc->GetMaster().GetHeader();
+ bHeaderFooterChanged |=
+ ( rHead.IsActive() != rOldHead.IsActive() ||
+ rChged.IsHeaderShared() != pDesc->IsHeaderShared() );
+ }
+ pDesc->GetMaster().SetFmtAttr( rHead );
+ if ( rChged.IsHeaderShared() || !rHead.IsActive() )
+ {
+ //Left teilt sich den Header mit dem Master.
+ pDesc->GetLeft().SetFmtAttr( pDesc->GetMaster().GetHeader() );
+ }
+ else if ( rHead.IsActive() )
+ { //Left bekommt einen eigenen Header verpasst wenn das Format nicht
+ //bereits einen hat.
+ //Wenn er bereits einen hat und dieser auf die gleiche Section
+ //wie der Rechte zeigt, so muss er einen eigenen bekommen. Der
+ //Inhalt wird sinnigerweise kopiert.
+ const SwFmtHeader &rLeftHead = pDesc->GetLeft().GetHeader();
+ if ( !rLeftHead.IsActive() )
+ {
+ SwFmtHeader aHead( MakeLayoutFmt( RND_STD_HEADERL, 0 ) );
+ pDesc->GetLeft().SetFmtAttr( aHead );
+ //Weitere Attribute (Raender, Umrandung...) uebernehmen.
+ ::lcl_DescSetAttr( *rHead.GetHeaderFmt(), *aHead.GetHeaderFmt(), sal_False);
+ }
+ else
+ {
+ const SwFrmFmt *pRight = rHead.GetHeaderFmt();
+ const SwFmtCntnt &aRCnt = pRight->GetCntnt();
+ const SwFmtCntnt &aLCnt = rLeftHead.GetHeaderFmt()->GetCntnt();
+ if( !aLCnt.GetCntntIdx() )
+ pDesc->GetLeft().SetFmtAttr( rChged.GetLeft().GetHeader() );
+ else if( (*aRCnt.GetCntntIdx()) == (*aLCnt.GetCntntIdx()) )
+ {
+ SwFrmFmt *pFmt = new SwFrmFmt( GetAttrPool(), "Header",
+ GetDfltFrmFmt() );
+ ::lcl_DescSetAttr( *pRight, *pFmt, sal_False );
+ //Der Bereich auf den das rechte Kopfattribut zeigt wird
+ //kopiert und der Index auf den StartNode in das linke
+ //Kopfattribut gehaengt.
+ SwNodeIndex aTmp( GetNodes().GetEndOfAutotext() );
+ SwStartNode* pSttNd = GetNodes().MakeEmptySection( aTmp, SwHeaderStartNode );
+ SwNodeRange aRange( aRCnt.GetCntntIdx()->GetNode(), 0,
+ *aRCnt.GetCntntIdx()->GetNode().EndOfSectionNode() );
+ aTmp = *pSttNd->EndOfSectionNode();
+ GetNodes()._Copy( aRange, aTmp, sal_False );
+
+ pFmt->SetFmtAttr( SwFmtCntnt( pSttNd ) );
+ pDesc->GetLeft().SetFmtAttr( SwFmtHeader( pFmt ) );
+ }
+ else
+ ::lcl_DescSetAttr( *pRight,
+ *(SwFrmFmt*)rLeftHead.GetHeaderFmt(), sal_False );
+
+ }
+ }
+ pDesc->ChgHeaderShare( rChged.IsHeaderShared() );
+
+ //Footer abgleichen.
+ const SwFmtFooter &rFoot = rChged.GetMaster().GetFooter();
+ if (undoGuard.UndoWasEnabled())
+ {
+ // #i46909# no undo if header or footer changed
+ // hat sich an den Nodes etwas veraendert ?
+ const SwFmtFooter &rOldFoot = pDesc->GetMaster().GetFooter();
+ bHeaderFooterChanged |=
+ ( rFoot.IsActive() != rOldFoot.IsActive() ||
+ rChged.IsFooterShared() != pDesc->IsFooterShared() );
+ }
+ pDesc->GetMaster().SetFmtAttr( rFoot );
+ if ( rChged.IsFooterShared() || !rFoot.IsActive() )
+ //Left teilt sich den Header mit dem Master.
+ pDesc->GetLeft().SetFmtAttr( pDesc->GetMaster().GetFooter() );
+ else if ( rFoot.IsActive() )
+ { //Left bekommt einen eigenen Footer verpasst wenn das Format nicht
+ //bereits einen hat.
+ //Wenn er bereits einen hat und dieser auf die gleiche Section
+ //wie der Rechte zeigt, so muss er einen eigenen bekommen. Der
+ //Inhalt wird sinnigerweise kopiert.
+ const SwFmtFooter &rLeftFoot = pDesc->GetLeft().GetFooter();
+ if ( !rLeftFoot.IsActive() )
+ {
+ SwFmtFooter aFoot( MakeLayoutFmt( RND_STD_FOOTER, 0 ) );
+ pDesc->GetLeft().SetFmtAttr( aFoot );
+ //Weitere Attribute (Raender, Umrandung...) uebernehmen.
+ ::lcl_DescSetAttr( *rFoot.GetFooterFmt(), *aFoot.GetFooterFmt(), sal_False);
+ }
+ else
+ {
+ const SwFrmFmt *pRight = rFoot.GetFooterFmt();
+ const SwFmtCntnt &aRCnt = pRight->GetCntnt();
+ const SwFmtCntnt &aLCnt = rLeftFoot.GetFooterFmt()->GetCntnt();
+ if( !aLCnt.GetCntntIdx() )
+ pDesc->GetLeft().SetFmtAttr( rChged.GetLeft().GetFooter() );
+ else if( (*aRCnt.GetCntntIdx()) == (*aLCnt.GetCntntIdx()) )
+ {
+ SwFrmFmt *pFmt = new SwFrmFmt( GetAttrPool(), "Footer",
+ GetDfltFrmFmt() );
+ ::lcl_DescSetAttr( *pRight, *pFmt, sal_False );
+ //Der Bereich auf den das rechte Kopfattribut zeigt wird
+ //kopiert und der Index auf den StartNode in das linke
+ //Kopfattribut gehaengt.
+ SwNodeIndex aTmp( GetNodes().GetEndOfAutotext() );
+ SwStartNode* pSttNd = GetNodes().MakeEmptySection( aTmp, SwFooterStartNode );
+ SwNodeRange aRange( aRCnt.GetCntntIdx()->GetNode(), 0,
+ *aRCnt.GetCntntIdx()->GetNode().EndOfSectionNode() );
+ aTmp = *pSttNd->EndOfSectionNode();
+ GetNodes()._Copy( aRange, aTmp, sal_False );
+
+ pFmt->SetFmtAttr( SwFmtCntnt( pSttNd ) );
+ pDesc->GetLeft().SetFmtAttr( SwFmtFooter( pFmt ) );
+ }
+ else
+ ::lcl_DescSetAttr( *pRight,
+ *(SwFrmFmt*)rLeftFoot.GetFooterFmt(), sal_False );
+ }
+ }
+ pDesc->ChgFooterShare( rChged.IsFooterShared() );
+
+ if ( pDesc->GetName() != rChged.GetName() )
+ pDesc->SetName( rChged.GetName() );
+
+ // Dadurch wird ein RegisterChange ausgeloest, wenn notwendig
+ pDesc->SetRegisterFmtColl( rChged.GetRegisterFmtColl() );
+
+ //Wenn sich das UseOn oder der Follow aendern muessen die
+ //Absaetze das erfahren.
+ sal_Bool bUseOn = sal_False;
+ sal_Bool bFollow = sal_False;
+ if ( pDesc->GetUseOn() != rChged.GetUseOn() )
+ { pDesc->SetUseOn( rChged.GetUseOn() );
+ bUseOn = sal_True;
+ }
+ if ( pDesc->GetFollow() != rChged.GetFollow() )
+ { if ( rChged.GetFollow() == &rChged )
+ { if ( pDesc->GetFollow() != pDesc )
+ { pDesc->SetFollow( pDesc );
+ bFollow = sal_True;
+ }
+ }
+ else
+ { pDesc->SetFollow( rChged.pFollow );
+ bFollow = sal_True;
+ }
+ }
+
+ if ( (bUseOn || bFollow) && pTmpRoot)
+ //Layot benachrichtigen!
+ {
+ std::set<SwRootFrm*> aAllLayouts = GetAllLayouts();
+ std::for_each( aAllLayouts.begin(), aAllLayouts.end(),std::mem_fun(&SwRootFrm::AllCheckPageDescs));//swmod 080304
+ }
+
+ //Jetzt noch die Seiten-Attribute uebernehmen.
+ ::lcl_DescSetAttr( rChged.GetMaster(), pDesc->GetMaster() );
+ ::lcl_DescSetAttr( rChged.GetLeft(), pDesc->GetLeft() );
+
+ //Wenn sich FussnotenInfo veraendert, so werden die Seiten
+ //angetriggert.
+ if( !(pDesc->GetFtnInfo() == rChged.GetFtnInfo()) )
+ {
+ pDesc->SetFtnInfo( rChged.GetFtnInfo() );
+ SwMsgPoolItem aInfo( RES_PAGEDESC_FTNINFO );
+ {
+ pDesc->GetMaster().ModifyBroadcast( &aInfo, 0, TYPE(SwFrm) );
+ }
+ {
+ pDesc->GetLeft().ModifyBroadcast( &aInfo, 0, TYPE(SwFrm) );
+ }
+ }
+ SetModified();
+
+ // #i46909# no undo if header or footer changed
+ if( bHeaderFooterChanged )
+ {
+ GetIDocumentUndoRedo().DelAllUndoObj();
+ }
+}
+
+/*************************************************************************
+|*
+|* SwDoc::DelPageDesc()
+|*
+|* Beschreibung Alle Descriptoren, deren Follow auf den zu loeschenden
+|* zeigen muessen angepasst werden.
+|*
+|*************************************************************************/
+
+// #i7983#
+void SwDoc::PreDelPageDesc(SwPageDesc * pDel)
+{
+ if (0 == pDel)
+ return;
+
+ // mba: test iteration as clients are removed while iteration
+ SwPageDescHint aHint( aPageDescs[0] );
+ pDel->CallSwClientNotify( aHint );
+
+ bool bHasLayout = HasLayout();
+ if ( pFtnInfo->DependsOn( pDel ) )
+ {
+ pFtnInfo->ChgPageDesc( aPageDescs[0] );
+ if ( bHasLayout )
+ {
+ std::set<SwRootFrm*> aAllLayouts = GetAllLayouts();
+ std::for_each( aAllLayouts.begin(), aAllLayouts.end(),std::bind2nd(std::mem_fun(&SwRootFrm::CheckFtnPageDescs), false));
+ }
+ }
+ else if ( pEndNoteInfo->DependsOn( pDel ) )
+ {
+ pEndNoteInfo->ChgPageDesc( aPageDescs[0] );
+ if ( bHasLayout )
+ {
+ std::set<SwRootFrm*> aAllLayouts = GetAllLayouts();
+ std::for_each( aAllLayouts.begin(), aAllLayouts.end(),std::bind2nd(std::mem_fun(&SwRootFrm::CheckFtnPageDescs), true));
+ }
+ }
+
+ for ( sal_uInt16 j = 0; j < aPageDescs.Count(); ++j )
+ {
+ if ( aPageDescs[j]->GetFollow() == pDel )
+ {
+ aPageDescs[j]->SetFollow( 0 );
+ if( bHasLayout )
+ {
+ std::set<SwRootFrm*> aAllLayouts = GetAllLayouts();
+ std::for_each( aAllLayouts.begin(), aAllLayouts.end(),std::mem_fun(&SwRootFrm::AllCheckPageDescs));//swmod 080228
+ }
+ }
+ }
+}
+
+void SwDoc::BroadcastStyleOperation(String rName, SfxStyleFamily eFamily,
+ sal_uInt16 nOp)
+{
+ if (pDocShell)
+ {
+ SfxStyleSheetBasePool * pPool = pDocShell->GetStyleSheetPool();
+
+ if (pPool)
+ {
+ pPool->SetSearchMask(eFamily, SFXSTYLEBIT_ALL );
+ SfxStyleSheetBase * pBase = pPool->Find(rName);
+
+ if (pBase != NULL)
+ pPool->Broadcast(SfxStyleSheetHint( nOp, *pBase ));
+ }
+ }
+}
+
+void SwDoc::DelPageDesc( sal_uInt16 i, sal_Bool bBroadcast )
+{
+ OSL_ENSURE( i < aPageDescs.Count(), "PageDescs ueberindiziert." );
+ OSL_ENSURE( i != 0, "Default Pagedesc loeschen is nicht." );
+ if ( i == 0 )
+ return;
+
+ SwPageDesc *pDel = aPageDescs[i];
+
+ if (bBroadcast)
+ BroadcastStyleOperation(pDel->GetName(), SFX_STYLE_FAMILY_PAGE,
+ SFX_STYLESHEET_ERASED);
+
+ if (GetIDocumentUndoRedo().DoesUndo())
+ {
+ SwUndo *const pUndo(new SwUndoPageDescDelete(*pDel, this));
+ GetIDocumentUndoRedo().AppendUndo(pUndo);
+ }
+
+ PreDelPageDesc(pDel); // #i7983#
+
+ aPageDescs.Remove( i );
+ delete pDel;
+ SetModified();
+}
+
+
+
+/*************************************************************************
+|*
+|* SwDoc::MakePageDesc()
+|*
+|*************************************************************************/
+
+sal_uInt16 SwDoc::MakePageDesc( const String &rName, const SwPageDesc *pCpy,
+ sal_Bool bRegardLanguage, sal_Bool bBroadcast) // #116530#
+{
+ SwPageDesc *pNew;
+ if( pCpy )
+ {
+ pNew = new SwPageDesc( *pCpy );
+ pNew->SetName( rName );
+ if( rName != pCpy->GetName() )
+ {
+ pNew->SetPoolFmtId( USHRT_MAX );
+ pNew->SetPoolHelpId( USHRT_MAX );
+ pNew->SetPoolHlpFileId( UCHAR_MAX );
+ }
+ }
+ else
+ {
+ pNew = new SwPageDesc( rName, GetDfltFrmFmt(), this );
+ //Default-Seitenformat einstellen.
+ lcl_DefaultPageFmt( USHRT_MAX, pNew->GetMaster(), pNew->GetLeft() );
+
+ SvxFrameDirection aFrameDirection = bRegardLanguage ?
+ GetDefaultFrameDirection(GetAppLanguage())
+ : FRMDIR_HORI_LEFT_TOP;
+
+ pNew->GetMaster().SetFmtAttr( SvxFrameDirectionItem(aFrameDirection, RES_FRAMEDIR) );
+ pNew->GetLeft().SetFmtAttr( SvxFrameDirectionItem(aFrameDirection, RES_FRAMEDIR) );
+ }
+ aPageDescs.Insert( pNew, aPageDescs.Count() );
+
+ if (bBroadcast)
+ BroadcastStyleOperation(rName, SFX_STYLE_FAMILY_PAGE,
+ SFX_STYLESHEET_CREATED);
+
+ if (GetIDocumentUndoRedo().DoesUndo())
+ {
+ // #116530#
+ GetIDocumentUndoRedo().AppendUndo(new SwUndoPageDescCreate(pNew, this));
+ }
+
+ SetModified();
+ return (aPageDescs.Count()-1);
+}
+
+SwPageDesc* SwDoc::FindPageDescByName( const String& rName, sal_uInt16* pPos ) const
+{
+ SwPageDesc* pRet = 0;
+ if( pPos ) *pPos = USHRT_MAX;
+
+ for( sal_uInt16 n = 0, nEnd = aPageDescs.Count(); n < nEnd; ++n )
+ if( aPageDescs[ n ]->GetName() == rName )
+ {
+ pRet = aPageDescs[ n ];
+ if( pPos )
+ *pPos = n;
+ break;
+ }
+ return pRet;
+}
+
+/******************************************************************************
+ * Methode : void SwDoc::PrtDataChanged()
+ * Beschreibung:
+ ******************************************************************************/
+
+void SwDoc::PrtDataChanged()
+{
+//!!!!!!!! Bei Aenderungen hier bitte ggf. InJobSetup im Sw3io mitpflegen
+
+ // --> FME 2005-01-21 #i41075#
+ OSL_ENSURE( get(IDocumentSettingAccess::USE_VIRTUAL_DEVICE) ||
+ 0 != getPrinter( sal_False ), "PrtDataChanged will be called recursive!" );
+ // <--
+ SwRootFrm* pTmpRoot = GetCurrentLayout();//swmod 080219
+ SwWait *pWait = 0;
+ sal_Bool bEndAction = sal_False;
+
+ if( GetDocShell() )
+ GetDocShell()->UpdateFontList();
+
+ sal_Bool bDraw = sal_True;
+ if ( pTmpRoot )
+ {
+ ViewShell *pSh = GetCurrentViewShell();
+ if( !pSh->GetViewOptions()->getBrowseMode() ||
+ pSh->GetViewOptions()->IsPrtFormat() )
+ {
+ if ( GetDocShell() )
+ pWait = new SwWait( *GetDocShell(), sal_True );
+
+ pTmpRoot->StartAllAction();
+ bEndAction = sal_True;
+
+ bDraw = sal_False;
+ if( pDrawModel )
+ {
+ pDrawModel->SetAddExtLeading( get(IDocumentSettingAccess::ADD_EXT_LEADING) );
+ pDrawModel->SetRefDevice( getReferenceDevice( false ) );
+ }
+
+ pFntCache->Flush();
+
+ std::set<SwRootFrm*> aAllLayouts = GetAllLayouts();
+ std::for_each( aAllLayouts.begin(), aAllLayouts.end(),std::bind2nd(std::mem_fun(&SwRootFrm::InvalidateAllCntnt), INV_SIZE));//swmod 080304
+
+ if ( pSh )
+ {
+ do
+ {
+ pSh->InitPrt( pPrt );
+ pSh = (ViewShell*)pSh->GetNext();
+ }
+ while ( pSh != GetCurrentViewShell() );
+ }
+
+ }
+ } //swmod 080218
+ if ( bDraw && pDrawModel )
+ {
+ const sal_Bool bTmpAddExtLeading = get(IDocumentSettingAccess::ADD_EXT_LEADING);
+ if ( bTmpAddExtLeading != pDrawModel->IsAddExtLeading() )
+ pDrawModel->SetAddExtLeading( bTmpAddExtLeading );
+
+ OutputDevice* pOutDev = getReferenceDevice( false );
+ if ( pOutDev != pDrawModel->GetRefDevice() )
+ pDrawModel->SetRefDevice( pOutDev );
+ }
+
+ PrtOLENotify( sal_True );
+
+ if ( bEndAction )
+ pTmpRoot->EndAllAction(); //swmod 080218
+ delete pWait;
+}
+
+//Zur Laufzeit sammeln wir die GlobalNames der Server, die keine
+//Benachrichtigung zu Druckerwechseln wuenschen. Dadurch sparen wir
+//das Laden vieler Objekte (gluecklicherweise werden obendrein alle
+//Fremdobjekte unter einer ID abgebuildet). Init und DeInit vom Array
+//ist in init.cxx zu finden.
+extern SvPtrarr *pGlobalOLEExcludeList;
+
+void SwDoc::PrtOLENotify( sal_Bool bAll )
+{
+ SwFEShell *pShell = 0;
+ if ( GetCurrentViewShell() )
+ {
+ ViewShell *pSh = GetCurrentViewShell();
+ if ( !pSh->ISA(SwFEShell) )
+ do
+ { pSh = (ViewShell*)pSh->GetNext();
+ } while ( !pSh->ISA(SwFEShell) &&
+ pSh != GetCurrentViewShell() );
+
+ if ( pSh->ISA(SwFEShell) )
+ pShell = (SwFEShell*)pSh;
+ } //swmod 071107//swmod 071225
+ if ( !pShell )
+ {
+ //Das hat ohne Shell und damit ohne Client keinen Sinn, weil nur darueber
+ //die Kommunikation bezueglich der Groessenaenderung implementiert ist.
+ //Da wir keine Shell haben, merken wir uns diesen unguenstigen
+ //Zustand am Dokument, dies wird dann beim Erzeugen der ersten Shell
+ //nachgeholt.
+ mbOLEPrtNotifyPending = sal_True;
+ if ( bAll )
+ mbAllOLENotify = sal_True;
+ }
+ else
+ {
+ if ( mbAllOLENotify )
+ bAll = sal_True;
+
+ mbOLEPrtNotifyPending = mbAllOLENotify = sal_False;
+
+ SwOLENodes *pNodes = SwCntntNode::CreateOLENodesArray( *GetDfltGrfFmtColl(), !bAll );
+ if ( pNodes )
+ {
+ ::StartProgress( STR_STATSTR_SWGPRTOLENOTIFY,
+ 0, pNodes->Count(), GetDocShell());
+ GetCurrentLayout()->StartAllAction(); //swmod 080218
+
+ for( sal_uInt16 i = 0; i < pNodes->Count(); ++i )
+ {
+ ::SetProgressState( i, GetDocShell() );
+
+ SwOLENode* pOLENd = (*pNodes)[i];
+ pOLENd->SetOLESizeInvalid( sal_False );
+
+ //Ersteinmal die Infos laden und festellen ob das Teil nicht
+ //schon in der Exclude-Liste steht
+ SvGlobalName aName;
+
+ svt::EmbeddedObjectRef& xObj = pOLENd->GetOLEObj().GetObject();
+ if ( xObj.is() )
+ aName = SvGlobalName( xObj->getClassID() );
+ else //Noch nicht geladen
+ {
+ // TODO/LATER: retrieve ClassID of an unloaded object
+ // aName = ????
+ }
+
+ sal_Bool bFound = sal_False;
+ for ( sal_uInt16 j = 0;
+ j < pGlobalOLEExcludeList->Count() && !bFound;
+ ++j )
+ {
+ bFound = *(SvGlobalName*)(*pGlobalOLEExcludeList)[j] ==
+ aName;
+ }
+ if ( bFound )
+ continue;
+
+ //Kennen wir nicht, also muss das Objekt geladen werden.
+ //Wenn es keine Benachrichtigung wuenscht
+ if ( xObj.is() )
+ {
+ pGlobalOLEExcludeList->Insert(
+ new SvGlobalName( aName ),
+ pGlobalOLEExcludeList->Count() );
+ }
+ }
+ delete pNodes;
+ GetCurrentLayout()->EndAllAction(); //swmod 080218
+ ::EndProgress( GetDocShell() );
+ }
+ }
+}
+
+IMPL_LINK( SwDoc, DoUpdateModifiedOLE, Timer *, )
+{
+ SwFEShell* pSh = (SwFEShell*)GetEditShell();
+ if( pSh )
+ {
+ mbOLEPrtNotifyPending = mbAllOLENotify = sal_False;
+
+ SwOLENodes *pNodes = SwCntntNode::CreateOLENodesArray( *GetDfltGrfFmtColl(), true );
+ if( pNodes )
+ {
+ ::StartProgress( STR_STATSTR_SWGPRTOLENOTIFY,
+ 0, pNodes->Count(), GetDocShell());
+ GetCurrentLayout()->StartAllAction(); //swmod 080218
+ SwMsgPoolItem aMsgHint( RES_UPDATE_ATTR );
+
+ for( sal_uInt16 i = 0; i < pNodes->Count(); ++i )
+ {
+ ::SetProgressState( i, GetDocShell() );
+
+ SwOLENode* pOLENd = (*pNodes)[i];
+ pOLENd->SetOLESizeInvalid( sal_False );
+
+ //Kennen wir nicht, also muss das Objekt geladen werden.
+ //Wenn es keine Benachrichtigung wuenscht
+ if( pOLENd->GetOLEObj().GetOleRef().is() ) //Kaputt?
+ {
+ pOLENd->ModifyNotification( &aMsgHint, &aMsgHint );
+ }
+ }
+ GetCurrentLayout()->EndAllAction(); //swmod 080218
+ ::EndProgress( GetDocShell() );
+ delete pNodes;
+ }
+ }
+ return 0;
+}
+
+sal_Bool SwDoc::FindPageDesc( const String & rName, sal_uInt16 * pFound)
+{
+ sal_Bool bResult = sal_False;
+ sal_uInt16 nI;
+ for (nI = 0; nI < aPageDescs.Count(); nI++)
+ {
+ if (aPageDescs[nI]->GetName() == rName)
+ {
+ *pFound = nI;
+ bResult = sal_True;
+ break;
+ }
+ }
+
+ return bResult;
+}
+
+SwPageDesc * SwDoc::GetPageDesc( const String & rName )
+{
+ SwPageDesc * aResult = NULL;
+
+ sal_uInt16 nI;
+
+ if (FindPageDesc(rName, &nI))
+ aResult = aPageDescs[nI];
+
+ return aResult;
+}
+
+void SwDoc::DelPageDesc( const String & rName, sal_Bool bBroadcast )
+{
+ sal_uInt16 nI;
+
+ if (FindPageDesc(rName, &nI))
+ DelPageDesc(nI, bBroadcast);
+}
+
+void SwDoc::ChgPageDesc( const String & rName, const SwPageDesc & rDesc)
+{
+ sal_uInt16 nI;
+
+ if (FindPageDesc(rName, &nI))
+ ChgPageDesc(nI, rDesc);
+}
+
+/*
+ * The HTML import cannot resist changing the page descriptions, I don't
+ * know why. This function is meant to check the page descriptors for invalid
+ * values.
+ */
+void SwDoc::CheckDefaultPageFmt()
+{
+ for ( sal_uInt16 i = 0; i < GetPageDescCnt(); ++i )
+ {
+ SwPageDesc& rDesc = _GetPageDesc( i );
+
+ SwFrmFmt& rMaster = rDesc.GetMaster();
+ SwFrmFmt& rLeft = rDesc.GetLeft();
+
+ const SwFmtFrmSize& rMasterSize = rMaster.GetFrmSize();
+ const SwFmtFrmSize& rLeftSize = rLeft.GetFrmSize();
+
+ const bool bSetSize = LONG_MAX == rMasterSize.GetWidth() ||
+ LONG_MAX == rMasterSize.GetHeight() ||
+ LONG_MAX == rLeftSize.GetWidth() ||
+ LONG_MAX == rLeftSize.GetHeight();
+
+ if ( bSetSize )
+ lcl_DefaultPageFmt( rDesc.GetPoolFmtId(), rDesc.GetMaster(), rDesc.GetLeft() );
+ }
+}
+
+void SwDoc::SetDefaultPageMode(bool bSquaredPageMode)
+{
+ if( !bSquaredPageMode == !IsSquaredPageMode() )
+ return;
+
+ const SwTextGridItem& rGrid =
+ (const SwTextGridItem&)GetDefault( RES_TEXTGRID );
+ SwTextGridItem aNewGrid = rGrid;
+ aNewGrid.SetSquaredMode(bSquaredPageMode);
+ aNewGrid.Init();
+ SetDefault(aNewGrid);
+
+ for ( sal_uInt16 i = 0; i < GetPageDescCnt(); ++i )
+ {
+ SwPageDesc& rDesc = _GetPageDesc( i );
+
+ SwFrmFmt& rMaster = rDesc.GetMaster();
+ SwFrmFmt& rLeft = rDesc.GetLeft();
+
+ SwTextGridItem aGrid((SwTextGridItem&)rMaster.GetFmtAttr(RES_TEXTGRID));
+ aGrid.SwitchPaperMode( bSquaredPageMode );
+ rMaster.SetFmtAttr(aGrid);
+ rLeft.SetFmtAttr(aGrid);
+ }
+}
+
+sal_Bool SwDoc::IsSquaredPageMode() const
+{
+ const SwTextGridItem& rGrid =
+ (const SwTextGridItem&)GetDefault( RES_TEXTGRID );
+ return rGrid.IsSquaredMode();
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/doc/docdraw.cxx b/sw/source/core/doc/docdraw.cxx
new file mode 100644
index 000000000000..bf2dcbbd93cb
--- /dev/null
+++ b/sw/source/core/doc/docdraw.cxx
@@ -0,0 +1,1041 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+#include <hintids.hxx>
+#include <rtl/logfile.hxx>
+#include <vcl/outdev.hxx>
+#include <sfx2/printer.hxx>
+#include <editeng/eeitem.hxx>
+#include <editeng/flditem.hxx>
+#include <editeng/editeng.hxx>
+#include <svx/svdoutl.hxx>
+#include <editeng/colritem.hxx>
+#include <svx/svdpage.hxx>
+#include <svx/svdogrp.hxx>
+#include <editeng/langitem.hxx>
+#include <editeng/unolingu.hxx>
+#include <editeng/measfld.hxx>
+#include <svx/svdpool.hxx>
+#include <fmtanchr.hxx>
+#include <charatr.hxx>
+#include <frmfmt.hxx>
+#include <charfmt.hxx>
+#include <viewimp.hxx>
+#include <swhints.hxx>
+#include <doc.hxx>
+#include <IDocumentUndoRedo.hxx>
+#include <docsh.hxx>
+#include <rootfrm.hxx> //Damit der RootDtor gerufen wird.
+#include <poolfmt.hxx>
+#include <viewsh.hxx> // fuer MakeDrawView
+#include <drawdoc.hxx>
+#include <UndoDraw.hxx>
+#include <swundo.hxx> // fuer die UndoIds
+#include <dcontact.hxx>
+#include <dview.hxx>
+#include <mvsave.hxx>
+#include <flyfrm.hxx>
+#include <dflyobj.hxx>
+#include <svx/svdetc.hxx>
+#include <editeng/fhgtitem.hxx>
+#include <svx/svdpagv.hxx>
+#include <txtfrm.hxx>
+#include <editeng/frmdiritem.hxx>
+#include <fmtornt.hxx>
+#include <svx/svditer.hxx>
+
+#include <vector>
+#include <switerator.hxx>
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::linguistic2;
+
+
+SV_IMPL_VARARR_SORT( _ZSortFlys, _ZSortFly )
+
+/*************************************************************************
+|*
+|* SwDoc::GroupSelection / SwDoc::UnGroupSelection
+|*
+|*************************************************************************/
+// local method to determine positioning and
+// alignment attributes for a drawing object, which is newly connected to
+// the layout. Used for a newly formed group object <SwDoc::GroupSelection(..)>
+// and the members of a destroyed group <SwDoc::UnGroupSelection(..)>
+void lcl_AdjustPositioningAttr( SwDrawFrmFmt* _pFrmFmt,
+ const SdrObject& _rSdrObj )
+{
+ const SwContact* pContact = GetUserCall( &_rSdrObj );
+ OSL_ENSURE( pContact, "<lcl_AdjustPositioningAttr(..)> - missing contact object." );
+
+ // determine position of new group object relative to its anchor frame position
+ SwTwips nHoriRelPos = 0;
+ SwTwips nVertRelPos = 0;
+ {
+ const SwFrm* pAnchorFrm = pContact->GetAnchoredObj( &_rSdrObj )->GetAnchorFrm();
+ OSL_ENSURE( !pAnchorFrm ||
+ !pAnchorFrm->IsTxtFrm() ||
+ !static_cast<const SwTxtFrm*>(pAnchorFrm)->IsFollow(),
+ "<lcl_AdjustPositioningAttr(..)> - anchor frame is a follow. Please inform OD." );
+ bool bVert = false;
+ bool bR2L = false;
+ // #i45952# - use anchor position of anchor frame, if it exist.
+ Point aAnchorPos;
+ if ( pAnchorFrm )
+ {
+ // #i45952#
+ aAnchorPos = pAnchorFrm->GetFrmAnchorPos( ::HasWrap( &_rSdrObj ) );
+ bVert = pAnchorFrm->IsVertical();
+ bR2L = pAnchorFrm->IsRightToLeft();
+ }
+ else
+ {
+ // #i45952#
+ aAnchorPos = _rSdrObj.GetAnchorPos();
+ // If no anchor frame exist - e.g. because no layout exists - the
+ // default layout direction is taken.
+ const SvxFrameDirectionItem* pDirItem =
+ static_cast<const SvxFrameDirectionItem*>(&(_pFrmFmt->GetAttrSet().GetPool()->GetDefaultItem( RES_FRAMEDIR )));
+ switch ( pDirItem->GetValue() )
+ {
+ case FRMDIR_VERT_TOP_LEFT:
+ {
+ // vertical from left-to-right - Badaa: supported now!
+ bVert = true;
+ bR2L = true;
+ OSL_FAIL( "<lcl_AdjustPositioningAttr(..)> - vertical from left-to-right not supported." );
+ }
+ break;
+ case FRMDIR_VERT_TOP_RIGHT:
+ {
+ // vertical from right-to-left
+ bVert = true;
+ bR2L = false;
+ }
+ break;
+ case FRMDIR_HORI_RIGHT_TOP:
+ {
+ // horizontal from right-to-left
+ bVert = false;
+ bR2L = true;
+ }
+ break;
+ case FRMDIR_HORI_LEFT_TOP:
+ {
+ // horizontal from left-to-right
+ bVert = false;
+ bR2L = false;
+ }
+ break;
+ }
+
+ }
+ // use geometry of drawing object
+ const SwRect aObjRect = _rSdrObj.GetSnapRect();
+
+ if ( bVert )
+ {
+ if ( bR2L ) {
+ //FRMDIR_VERT_TOP_LEFT
+ nHoriRelPos = aObjRect.Left() - aAnchorPos.X();
+ nVertRelPos = aObjRect.Top() - aAnchorPos.Y();
+ } else {
+ //FRMDIR_VERT_TOP_RIGHT
+ nHoriRelPos = aObjRect.Top() - aAnchorPos.Y();
+ nVertRelPos = aAnchorPos.X() - aObjRect.Right();
+ }
+ }
+ else if ( bR2L )
+ {
+ nHoriRelPos = aAnchorPos.X() - aObjRect.Right();
+ nVertRelPos = aObjRect.Top() - aAnchorPos.Y();
+ }
+ else
+ {
+ nHoriRelPos = aObjRect.Left() - aAnchorPos.X();
+ nVertRelPos = aObjRect.Top() - aAnchorPos.Y();
+ }
+ //End of SCMS
+ }
+
+ _pFrmFmt->SetFmtAttr( SwFmtHoriOrient( nHoriRelPos, text::HoriOrientation::NONE, text::RelOrientation::FRAME ) );
+ _pFrmFmt->SetFmtAttr( SwFmtVertOrient( nVertRelPos, text::VertOrientation::NONE, text::RelOrientation::FRAME ) );
+ // #i44334#, #i44681# - positioning attributes already set
+ _pFrmFmt->PosAttrSet();
+ // #i34750# - keep current object rectangle for drawing
+ // objects. The object rectangle is used on events from the drawing layer
+ // to adjust the positioning attributes - see <SwDrawContact::_Changed(..)>.
+ {
+ const SwAnchoredObject* pAnchoredObj = pContact->GetAnchoredObj( &_rSdrObj );
+ if ( pAnchoredObj->ISA(SwAnchoredDrawObject) )
+ {
+ const SwAnchoredDrawObject* pAnchoredDrawObj =
+ static_cast<const SwAnchoredDrawObject*>(pAnchoredObj);
+ const SwRect aObjRect = _rSdrObj.GetSnapRect();
+ const_cast<SwAnchoredDrawObject*>(pAnchoredDrawObj)
+ ->SetLastObjRect( aObjRect.SVRect() );
+ }
+ }
+}
+
+SwDrawContact* SwDoc::GroupSelection( SdrView& rDrawView )
+{
+ // replace marked 'virtual' drawing objects by the corresponding 'master'
+ // drawing objects.
+ SwDrawView::ReplaceMarkedDrawVirtObjs( rDrawView );
+
+ const SdrMarkList &rMrkList = rDrawView.GetMarkedObjectList();
+ SwDrawFrmFmt *pFmt = 0L;
+ SdrObject *pObj = rMrkList.GetMark( 0 )->GetMarkedSdrObj();
+ sal_Bool bNoGroup = ( 0 == pObj->GetUpGroup() );
+ SwDrawContact* pNewContact = 0;
+ if( bNoGroup )
+ {
+ //Ankerattribut aufheben.
+ SwDrawContact *pMyContact = (SwDrawContact*)GetUserCall(pObj);
+ const SwFmtAnchor aAnch( pMyContact->GetFmt()->GetAnchor() );
+
+ SwUndoDrawGroup *const pUndo = (!GetIDocumentUndoRedo().DoesUndo())
+ ? 0
+ : new SwUndoDrawGroup( (sal_uInt16)rMrkList.GetMarkCount() );
+
+ // #i53320#
+ bool bGroupMembersNotPositioned( false );
+ {
+ SwAnchoredDrawObject* pAnchoredDrawObj =
+ static_cast<SwAnchoredDrawObject*>(pMyContact->GetAnchoredObj( pObj ));
+ bGroupMembersNotPositioned = pAnchoredDrawObj->NotYetPositioned();
+ }
+ //ContactObjekte und Formate vernichten.
+ for( sal_uInt16 i = 0; i < rMrkList.GetMarkCount(); ++i )
+ {
+ pObj = rMrkList.GetMark( i )->GetMarkedSdrObj();
+ SwDrawContact *pContact = (SwDrawContact*)GetUserCall(pObj);
+
+ // #i53320#
+#if OSL_DEBUG_LEVEL > 1
+ SwAnchoredDrawObject* pAnchoredDrawObj =
+ static_cast<SwAnchoredDrawObject*>(pContact->GetAnchoredObj( pObj ));
+ OSL_ENSURE( bGroupMembersNotPositioned == pAnchoredDrawObj->NotYetPositioned(),
+ "<SwDoc::GroupSelection(..)> - group members have different positioning status!" );
+#endif
+
+ pFmt = (SwDrawFrmFmt*)pContact->GetFmt();
+ //loescht sich selbst!
+ pContact->Changed(*pObj, SDRUSERCALL_DELETE, pObj->GetLastBoundRect() );
+ pObj->SetUserCall( 0 );
+
+ if( pUndo )
+ pUndo->AddObj( i, pFmt, pObj );
+ else
+ DelFrmFmt( pFmt );
+
+ // #i45952# - re-introduce position normalization of group member
+ // objects, because its anchor position is cleared, when they are
+ // grouped.
+ Point aAnchorPos( pObj->GetAnchorPos() );
+ pObj->NbcSetAnchorPos( Point( 0, 0 ) );
+ pObj->NbcMove( Size( aAnchorPos.X(), aAnchorPos.Y() ) );
+ }
+
+ pFmt = MakeDrawFrmFmt( String::CreateFromAscii(
+ RTL_CONSTASCII_STRINGPARAM( "DrawObject" )),
+ GetDfltFrmFmt() );
+ pFmt->SetFmtAttr( aAnch );
+ // #i36010# - set layout direction of the position
+ pFmt->SetPositionLayoutDir(
+ text::PositionLayoutDir::PositionInLayoutDirOfAnchor );
+
+ rDrawView.GroupMarked();
+ OSL_ENSURE( rMrkList.GetMarkCount() == 1, "GroupMarked more or none groups." );
+
+ SdrObject* pNewGroupObj = rMrkList.GetMark( 0 )->GetMarkedSdrObj();
+ pNewContact = new SwDrawContact( pFmt, pNewGroupObj );
+ // #i35635#
+ pNewContact->MoveObjToVisibleLayer( pNewGroupObj );
+ pNewContact->ConnectToLayout();
+ // #i53320# - No adjustment of the positioning and alignment
+ // attributes, if group members aren't positioned yet.
+ if ( !bGroupMembersNotPositioned )
+ {
+ // #i26791# - Adjust positioning and alignment attributes.
+ lcl_AdjustPositioningAttr( pFmt, *pNewGroupObj );
+ }
+
+ if( pUndo )
+ {
+ pUndo->SetGroupFmt( pFmt );
+ GetIDocumentUndoRedo().AppendUndo( pUndo );
+ }
+ }
+ else
+ {
+ if (GetIDocumentUndoRedo().DoesUndo())
+ {
+ GetIDocumentUndoRedo().ClearRedo();
+ }
+
+ rDrawView.GroupMarked();
+ OSL_ENSURE( rMrkList.GetMarkCount() == 1, "GroupMarked more or none groups." );
+ }
+
+ return pNewContact;
+}
+
+
+void SwDoc::UnGroupSelection( SdrView& rDrawView )
+{
+ bool const bUndo = GetIDocumentUndoRedo().DoesUndo();
+ if( bUndo )
+ {
+ GetIDocumentUndoRedo().ClearRedo();
+ }
+
+ // replace marked 'virtual' drawing objects by the corresponding 'master'
+ // drawing objects.
+ SwDrawView::ReplaceMarkedDrawVirtObjs( rDrawView );
+
+ const SdrMarkList &rMrkList = rDrawView.GetMarkedObjectList();
+ std::vector< std::pair< SwDrawFrmFmt*, SdrObject* > >* pFmtsAndObjs( 0L );
+ const sal_uInt32 nMarkCount( rMrkList.GetMarkCount() );
+ if ( nMarkCount )
+ {
+ pFmtsAndObjs = new std::vector< std::pair< SwDrawFrmFmt*, SdrObject* > >[nMarkCount];
+ SdrObject *pMyObj = rMrkList.GetMark( 0 )->GetMarkedSdrObj();
+ if( !pMyObj->GetUpGroup() )
+ {
+ String sDrwFmtNm( String::CreateFromAscii(
+ RTL_CONSTASCII_STRINGPARAM("DrawObject" )));
+ for ( sal_uInt16 i = 0; i < nMarkCount; ++i )
+ {
+ SdrObject *pObj = rMrkList.GetMark( i )->GetMarkedSdrObj();
+ if ( pObj->IsA( TYPE(SdrObjGroup) ) )
+ {
+ SwDrawContact *pContact = (SwDrawContact*)GetUserCall(pObj);
+ SwFmtAnchor aAnch( pContact->GetFmt()->GetAnchor() );
+ SdrObjList *pLst = ((SdrObjGroup*)pObj)->GetSubList();
+
+ SwUndoDrawUnGroup* pUndo = 0;
+ if( bUndo )
+ {
+ pUndo = new SwUndoDrawUnGroup( (SdrObjGroup*)pObj );
+ GetIDocumentUndoRedo().AppendUndo(pUndo);
+ }
+
+ for ( sal_uInt16 i2 = 0; i2 < pLst->GetObjCount(); ++i2 )
+ {
+ SdrObject* pSubObj = pLst->GetObj( i2 );
+ SwDrawFrmFmt *pFmt = MakeDrawFrmFmt( sDrwFmtNm,
+ GetDfltFrmFmt() );
+ pFmt->SetFmtAttr( aAnch );
+ // #i36010# - set layout direction of the position
+ pFmt->SetPositionLayoutDir(
+ text::PositionLayoutDir::PositionInLayoutDirOfAnchor );
+ pFmtsAndObjs[i].push_back( std::pair< SwDrawFrmFmt*, SdrObject* >( pFmt, pSubObj ) );
+
+ if( bUndo )
+ pUndo->AddObj( i2, pFmt );
+ }
+ }
+ }
+ }
+ }
+ rDrawView.UnGroupMarked();
+ // creation of <SwDrawContact> instances for the former group members and
+ // its connection to the Writer layout.
+ for ( sal_uInt32 i = 0; i < nMarkCount; ++i )
+ {
+ SwUndoDrawUnGroupConnectToLayout* pUndo = 0;
+ if( bUndo )
+ {
+ pUndo = new SwUndoDrawUnGroupConnectToLayout();
+ GetIDocumentUndoRedo().AppendUndo(pUndo);
+ }
+
+ while ( pFmtsAndObjs[i].size() > 0 )
+ {
+ SwDrawFrmFmt* pFmt( pFmtsAndObjs[i].back().first );
+ SdrObject* pObj( pFmtsAndObjs[i].back().second );
+ pFmtsAndObjs[i].pop_back();
+
+ SwDrawContact* pContact = new SwDrawContact( pFmt, pObj );
+ pContact->MoveObjToVisibleLayer( pObj );
+ pContact->ConnectToLayout();
+ lcl_AdjustPositioningAttr( pFmt, *pObj );
+
+ if ( bUndo )
+ {
+ pUndo->AddFmtAndObj( pFmt, pObj );
+ }
+ }
+ }
+ delete [] pFmtsAndObjs;
+}
+
+/*************************************************************************
+|*
+|* SwDoc::DeleteSelection()
+|*
+|*************************************************************************/
+
+sal_Bool SwDoc::DeleteSelection( SwDrawView& rDrawView )
+{
+ sal_Bool bCallBase = sal_False;
+ const SdrMarkList &rMrkList = rDrawView.GetMarkedObjectList();
+ if( rMrkList.GetMarkCount() )
+ {
+ GetIDocumentUndoRedo().StartUndo(UNDO_EMPTY, NULL);
+ sal_uInt16 i;
+ sal_Bool bDelMarked = sal_True;
+
+ if( 1 == rMrkList.GetMarkCount() )
+ {
+ SdrObject *pObj = rMrkList.GetMark( 0 )->GetMarkedSdrObj();
+ if( pObj->ISA(SwVirtFlyDrawObj) )
+ {
+ SwFlyFrmFmt* pFrmFmt = (SwFlyFrmFmt*)
+ ((SwVirtFlyDrawObj*)pObj)->GetFlyFrm()->GetFmt();
+ if( pFrmFmt )
+ {
+ DelLayoutFmt( pFrmFmt );
+ bDelMarked = sal_False;
+ }
+ }
+ }
+
+ for( i = 0; i < rMrkList.GetMarkCount(); ++i )
+ {
+ SdrObject *pObj = rMrkList.GetMark( i )->GetMarkedSdrObj();
+ if( !pObj->ISA(SwVirtFlyDrawObj) )
+ {
+ SwDrawContact *pC = (SwDrawContact*)GetUserCall(pObj);
+ SwDrawFrmFmt *pFrmFmt = (SwDrawFrmFmt*)pC->GetFmt();
+ if( pFrmFmt &&
+ FLY_AS_CHAR == pFrmFmt->GetAnchor().GetAnchorId() )
+ {
+ rDrawView.MarkObj( pObj, rDrawView.Imp().GetPageView(), sal_True );
+ --i;
+ DelLayoutFmt( pFrmFmt );
+ }
+ }
+ }
+
+ if( rMrkList.GetMarkCount() && bDelMarked )
+ {
+ SdrObject *pObj = rMrkList.GetMark( 0 )->GetMarkedSdrObj();
+ if( !pObj->GetUpGroup() )
+ {
+ SwUndoDrawDelete *const pUndo =
+ (!GetIDocumentUndoRedo().DoesUndo())
+ ? 0
+ : new SwUndoDrawDelete( (sal_uInt16)rMrkList.GetMarkCount() );
+
+ //ContactObjekte vernichten, Formate sicherstellen.
+ for( i = 0; i < rMrkList.GetMarkCount(); ++i )
+ {
+ const SdrMark& rMark = *rMrkList.GetMark( i );
+ pObj = rMark.GetMarkedSdrObj();
+ SwDrawContact *pContact = (SwDrawContact*)pObj->GetUserCall();
+ if( pContact ) // natuerlich nicht bei gruppierten Objekten
+ {
+ SwDrawFrmFmt *pFmt = (SwDrawFrmFmt*)pContact->GetFmt();
+ // before delete of selection is performed, marked
+ // <SwDrawVirtObj>-objects have to be replaced by its
+ // reference objects. Thus, assert, if a
+ // <SwDrawVirt>-object is found in the mark list.
+ if ( pObj->ISA(SwDrawVirtObj) )
+ {
+ OSL_FAIL( "<SwDrawVirtObj> is still marked for delete. application will crash!" );
+ }
+ //loescht sich selbst!
+ pContact->Changed(*pObj, SDRUSERCALL_DELETE, pObj->GetLastBoundRect() );
+ pObj->SetUserCall( 0 );
+
+ if( pUndo )
+ pUndo->AddObj( i, pFmt, rMark );
+ else
+ DelFrmFmt( pFmt );
+ }
+ }
+
+ if( pUndo )
+ {
+ GetIDocumentUndoRedo().AppendUndo( pUndo );
+ }
+ }
+ bCallBase = sal_True;
+ }
+ SetModified();
+
+ GetIDocumentUndoRedo().EndUndo(UNDO_EMPTY, NULL);
+ }
+
+ return bCallBase;
+}
+
+/*************************************************************************
+|*
+|* SwDoc::DeleteSelection()
+|*
+|*************************************************************************/
+
+_ZSortFly::_ZSortFly( const SwFrmFmt* pFrmFmt, const SwFmtAnchor* pFlyAn,
+ sal_uInt32 nArrOrdNum )
+ : pFmt( pFrmFmt ), pAnchor( pFlyAn ), nOrdNum( nArrOrdNum )
+{
+ // #i11176#
+ // This also needs to work when no layout exists. Thus, for
+ // FlyFrames an alternative method is used now in that case.
+ if( RES_FLYFRMFMT == pFmt->Which() )
+ {
+ if( pFmt->getIDocumentLayoutAccess()->GetCurrentViewShell() ) //swmod 071107//swmod 071225
+ {
+ // Schauen, ob es ein SdrObject dafuer gibt
+ SwFlyFrm* pFly = SwIterator<SwFlyFrm,SwFmt>::FirstElement( *pFrmFmt );
+ if( pFly )
+ nOrdNum = pFly->GetVirtDrawObj()->GetOrdNum();
+ }
+ else
+ {
+ // Schauen, ob es ein SdrObject dafuer gibt
+ SwFlyDrawContact* pContact = SwIterator<SwFlyDrawContact,SwFmt>::FirstElement( *pFrmFmt );
+ if( pContact )
+ nOrdNum = pContact->GetMaster()->GetOrdNum();
+ }
+ }
+ else if( RES_DRAWFRMFMT == pFmt->Which() )
+ {
+ // Schauen, ob es ein SdrObject dafuer gibt
+ SwDrawContact* pContact = SwIterator<SwDrawContact,SwFmt>::FirstElement( *pFrmFmt );
+ if( pContact )
+ nOrdNum = pContact->GetMaster()->GetOrdNum();
+ }
+ else {
+ OSL_ENSURE( !this, "was ist das fuer ein Format?" );
+ }
+}
+
+/*************************************************************************/
+// Wird auch vom Sw3-Reader gerufen, wenn ein Fehler beim Einlesen
+// des Drawing Layers auftrat. In diesem Fall wird der Layer komplett
+// neu aufgebaut.
+
+#include <svx/sxenditm.hxx>
+
+void SwDoc::InitDrawModel()
+{
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLog, "SW", "JP93722", "SwDoc::InitDrawModel" );
+
+ //!!Achtung im sw3-Reader (sw3imp.cxx) gibt es aehnlichen Code, der
+ //mitgepfelgt werden muss.
+ if ( pDrawModel )
+ ReleaseDrawModel();
+
+ //DrawPool und EditEnginePool anlegen, diese gehoeren uns und werden
+ //dem Drawing nur mitgegeben. Im ReleaseDrawModel werden die Pools wieder
+ //zerstoert.
+ // for loading the drawing items. This must be loaded without RefCounts!
+ SfxItemPool *pSdrPool = new SdrItemPool( &GetAttrPool() );
+ // change DefaultItems for the SdrEdgeObj distance items to TWIPS.
+ if(pSdrPool)
+ {
+ const long nDefEdgeDist = ((500 * 72) / 127); // 1/100th mm in twips
+ pSdrPool->SetPoolDefaultItem(SdrEdgeNode1HorzDistItem(nDefEdgeDist));
+ pSdrPool->SetPoolDefaultItem(SdrEdgeNode1VertDistItem(nDefEdgeDist));
+ pSdrPool->SetPoolDefaultItem(SdrEdgeNode2HorzDistItem(nDefEdgeDist));
+ pSdrPool->SetPoolDefaultItem(SdrEdgeNode2VertDistItem(nDefEdgeDist));
+
+ // #i33700#
+ // Set shadow distance defaults as PoolDefaultItems. Details see bug.
+ pSdrPool->SetPoolDefaultItem(SdrShadowXDistItem((300 * 72) / 127));
+ pSdrPool->SetPoolDefaultItem(SdrShadowYDistItem((300 * 72) / 127));
+ }
+ SfxItemPool *pEEgPool = EditEngine::CreatePool( sal_False );
+ pSdrPool->SetSecondaryPool( pEEgPool );
+ if ( !GetAttrPool().GetFrozenIdRanges () )
+ GetAttrPool().FreezeIdRanges();
+ else
+ pSdrPool->FreezeIdRanges();
+
+ // set FontHeight pool defaults without changing static SdrEngineDefaults
+ GetAttrPool().SetPoolDefaultItem(SvxFontHeightItem( 240, 100, EE_CHAR_FONTHEIGHT ));
+
+ RTL_LOGFILE_CONTEXT_TRACE( aLog, "before create DrawDocument" );
+ //Das SdrModel gehoert dem Dokument, wir haben immer zwei Layer und eine
+ //Seite.
+ pDrawModel = new SwDrawDocument( this );
+
+ pDrawModel->EnableUndo( GetIDocumentUndoRedo().DoesUndo() );
+
+ String sLayerNm;
+ sLayerNm.AssignAscii(RTL_CONSTASCII_STRINGPARAM("Hell" ));
+ nHell = pDrawModel->GetLayerAdmin().NewLayer( sLayerNm )->GetID();
+
+ sLayerNm.AssignAscii(RTL_CONSTASCII_STRINGPARAM("Heaven" ));
+ nHeaven = pDrawModel->GetLayerAdmin().NewLayer( sLayerNm )->GetID();
+
+ sLayerNm.AssignAscii(RTL_CONSTASCII_STRINGPARAM("Controls" ));
+ nControls = pDrawModel->GetLayerAdmin().NewLayer( sLayerNm )->GetID();
+
+ // add invisible layers corresponding to the visible ones.
+ {
+ sLayerNm.AssignAscii(RTL_CONSTASCII_STRINGPARAM("InvisibleHell" ));
+ nInvisibleHell = pDrawModel->GetLayerAdmin().NewLayer( sLayerNm )->GetID();
+
+ sLayerNm.AssignAscii(RTL_CONSTASCII_STRINGPARAM("InvisibleHeaven" ));
+ nInvisibleHeaven = pDrawModel->GetLayerAdmin().NewLayer( sLayerNm )->GetID();
+
+ sLayerNm.AssignAscii(RTL_CONSTASCII_STRINGPARAM("InvisibleControls" ));
+ nInvisibleControls = pDrawModel->GetLayerAdmin().NewLayer( sLayerNm )->GetID();
+ }
+
+ SdrPage* pMasterPage = pDrawModel->AllocPage( sal_False );
+ pDrawModel->InsertPage( pMasterPage );
+ RTL_LOGFILE_CONTEXT_TRACE( aLog, "after create DrawDocument" );
+
+ RTL_LOGFILE_CONTEXT_TRACE( aLog, "before create Spellchecker/Hyphenator" );
+ SdrOutliner& rOutliner = pDrawModel->GetDrawOutliner();
+ uno::Reference< XSpellChecker1 > xSpell = ::GetSpellChecker();
+ rOutliner.SetSpeller( xSpell );
+ uno::Reference<XHyphenator> xHyphenator( ::GetHyphenator() );
+ rOutliner.SetHyphenator( xHyphenator );
+ RTL_LOGFILE_CONTEXT_TRACE( aLog, "after create Spellchecker/Hyphenator" );
+
+ SetCalcFieldValueHdl(&rOutliner);
+ SetCalcFieldValueHdl(&pDrawModel->GetHitTestOutliner());
+
+ //JP 16.07.98: Bug 50193 - Linkmanager am Model setzen, damit
+ // dort ggfs. verlinkte Grafiken eingefuegt werden koennen
+ //JP 28.01.99: der WinWord Import benoetigt ihn auch
+ pDrawModel->SetLinkManager( &GetLinkManager() );
+ pDrawModel->SetAddExtLeading( get(IDocumentSettingAccess::ADD_EXT_LEADING) );
+
+ OutputDevice* pRefDev = getReferenceDevice( false );
+ if ( pRefDev )
+ pDrawModel->SetRefDevice( pRefDev );
+
+ pDrawModel->SetNotifyUndoActionHdl( LINK( this, SwDoc, AddDrawUndo ));
+ if ( pCurrentView )
+ {
+ ViewShell* pViewSh = pCurrentView;
+ do
+ {
+ SwRootFrm* pRoot = pViewSh->GetLayout();
+ if( pRoot && !pRoot->GetDrawPage() )
+ {
+ // Disable "multiple layout" for the moment:
+ // use pMasterPage instead of a new created SdrPage
+ // pDrawModel->AllocPage( FALSE );
+ // pDrawModel->InsertPage( pDrawPage );
+ SdrPage* pDrawPage = pMasterPage;
+ pRoot->SetDrawPage( pDrawPage );
+ pDrawPage->SetSize( pRoot->Frm().SSize() );
+ }
+ pViewSh = (ViewShell*)pViewSh->GetNext();
+ }while( pViewSh != pCurrentView );
+ }
+}
+
+/** method to notify drawing page view about the invisible layers */
+void SwDoc::NotifyInvisibleLayers( SdrPageView& _rSdrPageView )
+{
+ String sLayerNm;
+ sLayerNm.AssignAscii(RTL_CONSTASCII_STRINGPARAM("InvisibleHell" ));
+ _rSdrPageView.SetLayerVisible( sLayerNm, sal_False );
+
+ sLayerNm.AssignAscii(RTL_CONSTASCII_STRINGPARAM("InvisibleHeaven" ));
+ _rSdrPageView.SetLayerVisible( sLayerNm, sal_False );
+
+ sLayerNm.AssignAscii(RTL_CONSTASCII_STRINGPARAM("InvisibleControls" ));
+ _rSdrPageView.SetLayerVisible( sLayerNm, sal_False );
+}
+
+/** method to determine, if a layer ID belongs to the visible ones.
+
+ Note: If given layer ID is unknown, method asserts and returns <false>.
+*/
+bool SwDoc::IsVisibleLayerId( const SdrLayerID& _nLayerId ) const
+{
+ bool bRetVal;
+
+ if ( _nLayerId == GetHeavenId() ||
+ _nLayerId == GetHellId() ||
+ _nLayerId == GetControlsId() )
+ {
+ bRetVal = true;
+ }
+ else if ( _nLayerId == GetInvisibleHeavenId() ||
+ _nLayerId == GetInvisibleHellId() ||
+ _nLayerId == GetInvisibleControlsId() )
+ {
+ bRetVal = false;
+ }
+ else
+ {
+ OSL_FAIL( "<SwDoc::IsVisibleLayerId(..)> - unknown layer ID." );
+ bRetVal = false;
+ }
+
+ return bRetVal;
+}
+
+/** method to determine, if the corresponding visible layer ID for a invisible one.
+
+ Note: If given layer ID is a visible one, method returns given layer ID.
+ Note: If given layer ID is unknown, method returns given layer ID.
+*/
+SdrLayerID SwDoc::GetVisibleLayerIdByInvisibleOne( const SdrLayerID& _nInvisibleLayerId )
+{
+ SdrLayerID nVisibleLayerId;
+
+ if ( _nInvisibleLayerId == GetInvisibleHeavenId() )
+ {
+ nVisibleLayerId = GetHeavenId();
+ }
+ else if ( _nInvisibleLayerId == GetInvisibleHellId() )
+ {
+ nVisibleLayerId = GetHellId();
+ }
+ else if ( _nInvisibleLayerId == GetInvisibleControlsId() )
+ {
+ nVisibleLayerId = GetControlsId();
+ }
+ else if ( _nInvisibleLayerId == GetHeavenId() ||
+ _nInvisibleLayerId == GetHellId() ||
+ _nInvisibleLayerId == GetControlsId() )
+ {
+ OSL_FAIL( "<SwDoc::GetVisibleLayerIdByInvisibleOne(..)> - given layer ID already an invisible one." );
+ nVisibleLayerId = _nInvisibleLayerId;
+ }
+ else
+ {
+ OSL_FAIL( "<SwDoc::GetVisibleLayerIdByInvisibleOne(..)> - given layer ID is unknown." );
+ nVisibleLayerId = _nInvisibleLayerId;
+ }
+
+ return nVisibleLayerId;
+}
+
+/** method to determine, if the corresponding invisible layer ID for a visible one.
+
+ Note: If given layer ID is a invisible one, method returns given layer ID.
+ Note: If given layer ID is unknown, method returns given layer ID.
+*/
+SdrLayerID SwDoc::GetInvisibleLayerIdByVisibleOne( const SdrLayerID& _nVisibleLayerId )
+{
+ SdrLayerID nInvisibleLayerId;
+
+ if ( _nVisibleLayerId == GetHeavenId() )
+ {
+ nInvisibleLayerId = GetInvisibleHeavenId();
+ }
+ else if ( _nVisibleLayerId == GetHellId() )
+ {
+ nInvisibleLayerId = GetInvisibleHellId();
+ }
+ else if ( _nVisibleLayerId == GetControlsId() )
+ {
+ nInvisibleLayerId = GetInvisibleControlsId();
+ }
+ else if ( _nVisibleLayerId == GetInvisibleHeavenId() ||
+ _nVisibleLayerId == GetInvisibleHellId() ||
+ _nVisibleLayerId == GetInvisibleControlsId() )
+ {
+ OSL_FAIL( "<SwDoc::GetInvisibleLayerIdByVisibleOne(..)> - given layer ID already an invisible one." );
+ nInvisibleLayerId = _nVisibleLayerId;
+ }
+ else
+ {
+ OSL_FAIL( "<SwDoc::GetInvisibleLayerIdByVisibleOne(..)> - given layer ID is unknown." );
+ nInvisibleLayerId = _nVisibleLayerId;
+ }
+
+ return nInvisibleLayerId;
+}
+
+/*************************************************************************/
+
+
+void SwDoc::ReleaseDrawModel()
+{
+ if ( pDrawModel )
+ {
+ //!!Den code im sw3io fuer Einfuegen Dokument mitpflegen!!
+
+ delete pDrawModel; pDrawModel = 0;
+ SfxItemPool *pSdrPool = GetAttrPool().GetSecondaryPool();
+
+ OSL_ENSURE( pSdrPool, "missing Pool" );
+ SfxItemPool *pEEgPool = pSdrPool->GetSecondaryPool();
+ OSL_ENSURE( !pEEgPool->GetSecondaryPool(), "i don't accept additional pools");
+ pSdrPool->Delete(); //Erst die Items vernichten lassen,
+ //dann erst die Verkettung loesen
+ GetAttrPool().SetSecondaryPool( 0 ); //Der ist ein muss!
+ pSdrPool->SetSecondaryPool( 0 ); //Der ist sicherer
+ SfxItemPool::Free(pSdrPool);
+ SfxItemPool::Free(pEEgPool);
+ }
+}
+
+/*************************************************************************/
+
+
+SdrModel* SwDoc::_MakeDrawModel()
+{
+ OSL_ENSURE( !pDrawModel, "_MakeDrawModel: Why?" );
+ InitDrawModel();
+ if ( pCurrentView )
+ {
+ ViewShell* pTmp = pCurrentView;
+ do
+ {
+ pTmp->MakeDrawView();
+ pTmp = (ViewShell*) pTmp->GetNext();
+ } while ( pTmp != pCurrentView );
+
+ //Broadcast, damit die FormShell mit der DrawView verbunden werden kann
+ if( GetDocShell() )
+ {
+ SfxSimpleHint aHnt( SW_BROADCAST_DRAWVIEWS_CREATED );
+ GetDocShell()->Broadcast( aHnt );
+ }
+ } //swmod 071029//swmod 071225
+ return pDrawModel;
+}
+
+/*************************************************************************/
+
+void SwDoc::DrawNotifyUndoHdl()
+{
+ pDrawModel->SetNotifyUndoActionHdl( Link() );
+}
+
+/*************************************************************************
+*
+* Am Outliner Link auf Methode fuer Felddarstellung in Editobjekten setzen
+*
+*************************************************************************/
+
+void SwDoc::SetCalcFieldValueHdl(Outliner* pOutliner)
+{
+ pOutliner->SetCalcFieldValueHdl(LINK(this, SwDoc, CalcFieldValueHdl));
+}
+
+/*************************************************************************
+|*
+|* Felder bzw URLs im Outliner erkennen und Darstellung festlegen
+|*
+\************************************************************************/
+
+IMPL_LINK(SwDoc, CalcFieldValueHdl, EditFieldInfo*, pInfo)
+{
+ if (pInfo)
+ {
+ const SvxFieldItem& rField = pInfo->GetField();
+ const SvxFieldData* pField = rField.GetField();
+
+ if (pField && pField->ISA(SvxDateField))
+ {
+ /******************************************************************
+ * Date-Field
+ ******************************************************************/
+ pInfo->SetRepresentation(
+ ((const SvxDateField*) pField)->GetFormatted(
+ *GetNumberFormatter( sal_True ), LANGUAGE_SYSTEM) );
+ }
+ else if (pField && pField->ISA(SvxURLField))
+ {
+ /******************************************************************
+ * URL-Field
+ ******************************************************************/
+
+ switch ( ((const SvxURLField*) pField)->GetFormat() )
+ {
+ case SVXURLFORMAT_APPDEFAULT: //!!! einstellbar an App???
+ case SVXURLFORMAT_REPR:
+ {
+ pInfo->SetRepresentation(
+ ((const SvxURLField*)pField)->GetRepresentation());
+ }
+ break;
+
+ case SVXURLFORMAT_URL:
+ {
+ pInfo->SetRepresentation(
+ ((const SvxURLField*)pField)->GetURL());
+ }
+ break;
+ }
+
+ sal_uInt16 nChrFmt;
+
+ if (IsVisitedURL(((const SvxURLField*)pField)->GetURL()))
+ nChrFmt = RES_POOLCHR_INET_VISIT;
+ else
+ nChrFmt = RES_POOLCHR_INET_NORMAL;
+
+ SwFmt *pFmt = GetCharFmtFromPool(nChrFmt);
+
+ Color aColor(COL_LIGHTBLUE);
+ if (pFmt)
+ aColor = pFmt->GetColor().GetValue();
+
+ pInfo->SetTxtColor(aColor);
+ }
+ else if (pField && pField->ISA(SdrMeasureField))
+ {
+ /******************************************************************
+ * Measure-Field
+ ******************************************************************/
+ pInfo->ClearFldColor();
+ }
+ else if ( pField && pField->ISA(SvxExtTimeField))
+ {
+ /******************************************************************
+ * Time-Field
+ ******************************************************************/
+ pInfo->SetRepresentation(
+ ((const SvxExtTimeField*) pField)->GetFormatted(
+ *GetNumberFormatter( sal_True ), LANGUAGE_SYSTEM) );
+ }
+ else
+ {
+ OSL_FAIL("unbekannter Feldbefehl");
+ pInfo->SetRepresentation( String( '?' ) );
+ }
+ }
+
+ return(0);
+}
+
+/* TFFDI: The functions formerly declared 'inline'
+ */
+const SdrModel* SwDoc::GetDrawModel() const { return pDrawModel; }
+SdrModel* SwDoc::GetDrawModel() { return pDrawModel; }
+SdrLayerID SwDoc::GetHeavenId() const { return nHeaven; }
+SdrLayerID SwDoc::GetHellId() const { return nHell; }
+SdrLayerID SwDoc::GetControlsId() const { return nControls; }
+SdrLayerID SwDoc::GetInvisibleHeavenId() const { return nInvisibleHeaven; }
+SdrLayerID SwDoc::GetInvisibleHellId() const { return nInvisibleHell; }
+SdrLayerID SwDoc::GetInvisibleControlsId() const { return nInvisibleControls; }
+SdrModel* SwDoc::GetOrCreateDrawModel() { return GetDrawModel() ? GetDrawModel() : _MakeDrawModel(); }
+
+// #i62875#
+namespace docfunc
+{
+ bool ExistsDrawObjs( SwDoc& p_rDoc )
+ {
+ bool bExistsDrawObjs( false );
+
+ if ( p_rDoc.GetDrawModel() &&
+ p_rDoc.GetDrawModel()->GetPage( 0 ) )
+ {
+ const SdrPage& rSdrPage( *(p_rDoc.GetDrawModel()->GetPage( 0 )) );
+
+ SdrObjListIter aIter( rSdrPage, IM_FLAT );
+ while( aIter.IsMore() )
+ {
+ SdrObject* pObj( aIter.Next() );
+ if ( !dynamic_cast<SwVirtFlyDrawObj*>(pObj) &&
+ !dynamic_cast<SwFlyDrawObj*>(pObj) )
+ {
+ bExistsDrawObjs = true;
+ break;
+ }
+ }
+ }
+
+ return bExistsDrawObjs;
+ }
+
+ bool AllDrawObjsOnPage( SwDoc& p_rDoc )
+ {
+ bool bAllDrawObjsOnPage( true );
+
+ if ( p_rDoc.GetDrawModel() &&
+ p_rDoc.GetDrawModel()->GetPage( 0 ) )
+ {
+ const SdrPage& rSdrPage( *(p_rDoc.GetDrawModel()->GetPage( 0 )) );
+
+ SdrObjListIter aIter( rSdrPage, IM_FLAT );
+ while( aIter.IsMore() )
+ {
+ SdrObject* pObj( aIter.Next() );
+ if ( !dynamic_cast<SwVirtFlyDrawObj*>(pObj) &&
+ !dynamic_cast<SwFlyDrawObj*>(pObj) )
+ {
+ SwDrawContact* pDrawContact =
+ dynamic_cast<SwDrawContact*>(::GetUserCall( pObj ));
+ if ( pDrawContact )
+ {
+ SwAnchoredDrawObject* pAnchoredDrawObj =
+ dynamic_cast<SwAnchoredDrawObject*>(pDrawContact->GetAnchoredObj( pObj ));
+
+ // error handling
+ {
+ if ( !pAnchoredDrawObj )
+ {
+ OSL_FAIL( "<docfunc::AllDrawObjsOnPage() - missing anchored draw object" );
+ bAllDrawObjsOnPage = false;
+ break;
+ }
+ }
+
+ if ( pAnchoredDrawObj->NotYetPositioned() )
+ {
+ // The drawing object isn't yet layouted.
+ // Thus, it isn't known, if all drawing objects are on page.
+ bAllDrawObjsOnPage = false;
+ break;
+ }
+ else if ( pAnchoredDrawObj->IsOutsidePage() )
+ {
+ bAllDrawObjsOnPage = false;
+ break;
+ }
+ }
+ else
+ {
+ // contact object of drawing object doesn't exists.
+ // Thus, the drawing object isn't yet positioned.
+ // Thus, it isn't known, if all drawing objects are on page.
+ bAllDrawObjsOnPage = false;
+ break;
+ }
+ }
+ }
+ }
+
+ return bAllDrawObjsOnPage;
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/doc/docedt.cxx b/sw/source/core/doc/docedt.cxx
new file mode 100644
index 000000000000..8d9849f547b8
--- /dev/null
+++ b/sw/source/core/doc/docedt.cxx
@@ -0,0 +1,2801 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+#include <string.h> // fuer strchr()
+#include <hintids.hxx>
+
+#include <vcl/sound.hxx>
+#include <editeng/cscoitem.hxx>
+#include <editeng/brkitem.hxx>
+#include <linguistic/lngprops.hxx>
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/i18n/WordType.hdl>
+#include <unotools/charclass.hxx>
+#include <unotools/transliterationwrapper.hxx>
+#include <fmtanchr.hxx>
+#include <fmtcntnt.hxx>
+#include <fmtpdsc.hxx>
+#include <txtftn.hxx>
+#include <acorrect.hxx> // Autokorrektur
+#include <IMark.hxx> // fuer SwBookmark
+#include <cntfrm.hxx> // fuers Spell
+#include <crsrsh.hxx>
+#include <doc.hxx>
+#include <UndoManager.hxx>
+#include <docsh.hxx>
+#include <docary.hxx>
+#include <doctxm.hxx> // beim Move: Verzeichnisse korrigieren
+#include <ftnidx.hxx>
+#include <ftninfo.hxx>
+#include <mdiexp.hxx> // Statusanzeige
+#include <mvsave.hxx> // Strukturen zum Sichern beim Move/Delete
+#include <ndtxt.hxx>
+#include <pam.hxx>
+#include <redline.hxx>
+#include <rootfrm.hxx> // fuers UpdateFtn
+#include <splargs.hxx> // fuer Spell
+#include <swtable.hxx>
+#include <swundo.hxx> // fuer die UndoIds
+#include <txtfrm.hxx>
+#include <hints.hxx>
+#include <UndoSplitMove.hxx>
+#include <UndoRedline.hxx>
+#include <UndoOverwrite.hxx>
+#include <UndoInsert.hxx>
+#include <UndoDelete.hxx>
+#include <breakit.hxx>
+#include <hhcwrp.hxx>
+#include <vcl/msgbox.hxx>
+#include "comcore.hrc"
+#include "editsh.hxx"
+#include <unoflatpara.hxx>
+#include <SwGrammarMarkUp.hxx>
+
+#include <vector>
+
+using ::rtl::OUString;
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::linguistic2;
+using namespace ::com::sun::star::i18n;
+
+#ifndef S2U
+#define S2U(rString) OUString::createFromAscii(rString)
+#endif
+
+struct _SaveRedline
+{
+ SwRedline* pRedl;
+ sal_uInt32 nStt, nEnd;
+ xub_StrLen nSttCnt, nEndCnt;
+
+ _SaveRedline( SwRedline* pR, const SwNodeIndex& rSttIdx )
+ : pRedl( pR )
+ {
+ const SwPosition* pStt = pR->Start(),
+ * pEnd = pR->GetMark() == pStt ? pR->GetPoint() : pR->GetMark();
+ sal_uInt32 nSttIdx = rSttIdx.GetIndex();
+ nStt = pStt->nNode.GetIndex() - nSttIdx;
+ nSttCnt = pStt->nContent.GetIndex();
+ if( pR->HasMark() )
+ {
+ nEnd = pEnd->nNode.GetIndex() - nSttIdx;
+ nEndCnt = pEnd->nContent.GetIndex();
+ }
+
+ pRedl->GetPoint()->nNode = 0;
+ pRedl->GetPoint()->nContent.Assign( 0, 0 );
+ pRedl->GetMark()->nNode = 0;
+ pRedl->GetMark()->nContent.Assign( 0, 0 );
+ }
+
+ _SaveRedline( SwRedline* pR, const SwPosition& rPos )
+ : pRedl( pR )
+ {
+ const SwPosition* pStt = pR->Start(),
+ * pEnd = pR->GetMark() == pStt ? pR->GetPoint() : pR->GetMark();
+ sal_uInt32 nSttIdx = rPos.nNode.GetIndex();
+ nStt = pStt->nNode.GetIndex() - nSttIdx;
+ nSttCnt = pStt->nContent.GetIndex();
+ if( nStt == 0 )
+ nSttCnt = nSttCnt - rPos.nContent.GetIndex();
+ if( pR->HasMark() )
+ {
+ nEnd = pEnd->nNode.GetIndex() - nSttIdx;
+ nEndCnt = pEnd->nContent.GetIndex();
+ if( nEnd == 0 )
+ nEndCnt = nEndCnt - rPos.nContent.GetIndex();
+ }
+
+ pRedl->GetPoint()->nNode = 0;
+ pRedl->GetPoint()->nContent.Assign( 0, 0 );
+ pRedl->GetMark()->nNode = 0;
+ pRedl->GetMark()->nContent.Assign( 0, 0 );
+ }
+
+ void SetPos( sal_uInt32 nInsPos )
+ {
+ pRedl->GetPoint()->nNode = nInsPos + nStt;
+ pRedl->GetPoint()->nContent.Assign( pRedl->GetCntntNode(), nSttCnt );
+ if( pRedl->HasMark() )
+ {
+ pRedl->GetMark()->nNode = nInsPos + nEnd;
+ pRedl->GetMark()->nContent.Assign( pRedl->GetCntntNode(sal_False), nEndCnt );
+ }
+ }
+
+ void SetPos( const SwPosition& aPos )
+ {
+ pRedl->GetPoint()->nNode = aPos.nNode.GetIndex() + nStt;
+ pRedl->GetPoint()->nContent.Assign( pRedl->GetCntntNode(), nSttCnt + ( nStt == 0 ? aPos.nContent.GetIndex() : 0 ) );
+ if( pRedl->HasMark() )
+ {
+ pRedl->GetMark()->nNode = aPos.nNode.GetIndex() + nEnd;
+ pRedl->GetMark()->nContent.Assign( pRedl->GetCntntNode(sal_False), nEndCnt + ( nEnd == 0 ? aPos.nContent.GetIndex() : 0 ) );
+ }
+ }
+};
+
+SV_DECL_PTRARR_DEL( _SaveRedlines, _SaveRedline*, 0, 4 )
+
+SV_IMPL_VARARR( _SaveFlyArr, _SaveFly )
+SV_IMPL_PTRARR( _SaveRedlines, _SaveRedline* )
+
+bool lcl_MayOverwrite( const SwTxtNode *pNode, const xub_StrLen nPos )
+{
+ sal_Unicode cChr = pNode->GetTxt().GetChar( nPos );
+ return !( ( CH_TXTATR_BREAKWORD == cChr || CH_TXTATR_INWORD == cChr ) &&
+ (0 != pNode->GetTxtAttrForCharAt( nPos ) ) );
+}
+
+void lcl_SkipAttr( const SwTxtNode *pNode, SwIndex &rIdx, xub_StrLen &rStart )
+{
+ if( !lcl_MayOverwrite( pNode, rStart ) )
+ {
+ // ueberspringe alle SonderAttribute
+ do {
+ // "Beep" bei jedem ausgelassenen
+ Sound::Beep(SOUND_ERROR);
+ rIdx++;
+ } while( (rStart = rIdx.GetIndex()) < pNode->GetTxt().Len()
+ && !lcl_MayOverwrite(pNode, rStart) );
+ }
+}
+
+void _RestFlyInRange( _SaveFlyArr & rArr, const SwNodeIndex& rSttIdx,
+ const SwNodeIndex* pInsertPos )
+{
+ SwPosition aPos( rSttIdx );
+ for( sal_uInt16 n = 0; n < rArr.Count(); ++n )
+ {
+ // neuen Anker anlegen
+ _SaveFly& rSave = rArr[n];
+ SwFrmFmt* pFmt = rSave.pFrmFmt;
+
+ if( rSave.bInsertPosition )
+ {
+ if( pInsertPos != NULL )
+ aPos.nNode = *pInsertPos;
+ else
+ aPos.nNode = rSttIdx.GetIndex();
+ }
+ else
+ aPos.nNode = rSttIdx.GetIndex() + rSave.nNdDiff;
+
+ aPos.nContent.Assign( 0, 0 );
+ SwFmtAnchor aAnchor( pFmt->GetAnchor() );
+ aAnchor.SetAnchor( &aPos );
+ pFmt->GetDoc()->GetSpzFrmFmts()->Insert(
+ pFmt, pFmt->GetDoc()->GetSpzFrmFmts()->Count() );
+ pFmt->SetFmtAttr( aAnchor );
+ SwCntntNode* pCNd = aPos.nNode.GetNode().GetCntntNode();
+ if( pCNd && pCNd->getLayoutFrm( pFmt->GetDoc()->GetCurrentLayout(), 0, 0, sal_False ) )
+ pFmt->MakeFrms();
+ }
+}
+
+void _SaveFlyInRange( const SwNodeRange& rRg, _SaveFlyArr& rArr )
+{
+ SwSpzFrmFmts& rFmts = *rRg.aStart.GetNode().GetDoc()->GetSpzFrmFmts();
+ for( sal_uInt16 n = 0; n < rFmts.Count(); ++n )
+ {
+ SwFrmFmt *const pFmt = static_cast<SwFrmFmt*>(rFmts[n]);
+ SwFmtAnchor const*const pAnchor = &pFmt->GetAnchor();
+ SwPosition const*const pAPos = pAnchor->GetCntntAnchor();
+ if (pAPos &&
+ ((FLY_AT_PARA == pAnchor->GetAnchorId()) ||
+ (FLY_AT_CHAR == pAnchor->GetAnchorId())) &&
+ rRg.aStart <= pAPos->nNode && pAPos->nNode < rRg.aEnd )
+ {
+ _SaveFly aSave( pAPos->nNode.GetIndex() - rRg.aStart.GetIndex(),
+ pFmt, sal_False );
+ rArr.Insert( aSave, rArr.Count());
+ pFmt->DelFrms();
+ rFmts.Remove( n--, 1 );
+ }
+ }
+}
+
+void _SaveFlyInRange( const SwPaM& rPam, const SwNodeIndex& rInsPos,
+ _SaveFlyArr& rArr, bool bMoveAllFlys )
+{
+ SwSpzFrmFmts& rFmts = *rPam.GetPoint()->nNode.GetNode().GetDoc()->GetSpzFrmFmts();
+ SwFrmFmt* pFmt;
+ const SwFmtAnchor* pAnchor;
+
+ const SwPosition* pPos = rPam.Start();
+ const SwNodeIndex& rSttNdIdx = pPos->nNode;
+ short nSttOff = (!bMoveAllFlys && rSttNdIdx.GetNode().IsCntntNode() &&
+ pPos->nContent.GetIndex()) ? 1 : 0;
+
+ pPos = rPam.GetPoint() == pPos ? rPam.GetMark() : rPam.GetPoint();
+ const SwNodeIndex& rEndNdIdx = pPos->nNode;
+ short nOff = ( bMoveAllFlys || ( rEndNdIdx.GetNode().IsCntntNode() &&
+ pPos->nContent == rEndNdIdx.GetNode().GetCntntNode()->Len() ))
+ ? 0 : 1;
+
+ const SwNodeIndex* pCntntIdx;
+
+ for( sal_uInt16 n = 0; n < rFmts.Count(); ++n )
+ {
+ sal_Bool bInsPos = sal_False;
+ pFmt = (SwFrmFmt*)rFmts[n];
+ pAnchor = &pFmt->GetAnchor();
+ const SwPosition* pAPos = pAnchor->GetCntntAnchor();
+ if (pAPos &&
+ ((FLY_AT_PARA == pAnchor->GetAnchorId()) ||
+ (FLY_AT_CHAR == pAnchor->GetAnchorId())) &&
+ // nicht verschieben, wenn die InsPos im CntntBereich vom Fly ist
+ ( 0 == ( pCntntIdx = pFmt->GetCntnt().GetCntntIdx() ) ||
+ !( *pCntntIdx < rInsPos &&
+ rInsPos < pCntntIdx->GetNode().EndOfSectionIndex() )) )
+ {
+ if( !bMoveAllFlys && rEndNdIdx == pAPos->nNode )
+ {
+ // wenn nur teil vom EndNode oder der EndNode und SttNode
+ // identisch sind, chaos::Anchor nicht anfassen
+ if( rSttNdIdx != pAPos->nNode )
+ {
+ // Anker nur an Anfang/Ende haengen
+ SwPosition aPos( rSttNdIdx );
+ SwFmtAnchor aAnchor( *pAnchor );
+ aAnchor.SetAnchor( &aPos );
+ pFmt->SetFmtAttr( aAnchor );
+ }
+ }
+ else if( ( rSttNdIdx.GetIndex() + nSttOff <= pAPos->nNode.GetIndex()
+ && pAPos->nNode.GetIndex() <= rEndNdIdx.GetIndex() - nOff ) ||
+ 0 != ( bInsPos = rInsPos == pAPos->nNode ))
+
+ {
+ _SaveFly aSave( pAPos->nNode.GetIndex() - rSttNdIdx.GetIndex(),
+ pFmt, bInsPos );
+ rArr.Insert( aSave, rArr.Count());
+ pFmt->DelFrms();
+ rFmts.Remove( n--, 1 );
+ }
+ }
+ }
+}
+
+// loesche und verschiebe alle "Fly's am Absatz", die in der SSelection
+// liegen. Steht am SPoint ein Fly, wird dieser auf den Mark verschoben.
+void DelFlyInRange( const SwNodeIndex& rMkNdIdx,
+ const SwNodeIndex& rPtNdIdx )
+{
+ const sal_Bool bDelFwrd = rMkNdIdx.GetIndex() <= rPtNdIdx.GetIndex();
+
+ SwDoc* pDoc = rMkNdIdx.GetNode().GetDoc();
+ SwSpzFrmFmts& rTbl = *pDoc->GetSpzFrmFmts();
+ for ( sal_uInt16 i = rTbl.Count(); i; )
+ {
+ SwFrmFmt *pFmt = rTbl[--i];
+ const SwFmtAnchor &rAnch = pFmt->GetAnchor();
+ SwPosition const*const pAPos = rAnch.GetCntntAnchor();
+ if (pAPos &&
+ ((rAnch.GetAnchorId() == FLY_AT_PARA) ||
+ (rAnch.GetAnchorId() == FLY_AT_CHAR)) &&
+ ( bDelFwrd
+ ? rMkNdIdx < pAPos->nNode && pAPos->nNode <= rPtNdIdx
+ : rPtNdIdx <= pAPos->nNode && pAPos->nNode < rMkNdIdx ))
+ {
+ // nur den Anker verschieben ??
+ if( rPtNdIdx == pAPos->nNode )
+ {
+ SwFmtAnchor aAnch( pFmt->GetAnchor() );
+ SwPosition aPos( rMkNdIdx );
+ aAnch.SetAnchor( &aPos );
+ pFmt->SetFmtAttr( aAnch );
+ }
+ else
+ {
+ // wird der Fly geloescht muss auch im seinem Inhalt alle
+ // Flys geloescht werden !!
+ const SwFmtCntnt &rCntnt = pFmt->GetCntnt();
+ if( rCntnt.GetCntntIdx() )
+ {
+ DelFlyInRange( *rCntnt.GetCntntIdx(),
+ SwNodeIndex( *rCntnt.GetCntntIdx()->
+ GetNode().EndOfSectionNode() ));
+ // Position kann sich verschoben haben !
+ if( i > rTbl.Count() )
+ i = rTbl.Count();
+ else if( pFmt != rTbl[i] )
+ i = rTbl.GetPos( pFmt );
+ }
+
+ pDoc->DelLayoutFmt( pFmt );
+
+ // DelLayoutFmt can also trigger the deletion of objects.
+ if( i > rTbl.Count() )
+ i = rTbl.Count();
+ }
+ }
+ }
+}
+
+bool lcl_SaveFtn( const SwNodeIndex& rSttNd, const SwNodeIndex& rEndNd,
+ const SwNodeIndex& rInsPos,
+ SwFtnIdxs& rFtnArr, SwFtnIdxs& rSaveArr,
+ const SwIndex* pSttCnt = 0, const SwIndex* pEndCnt = 0 )
+{
+ bool bUpdateFtn = sal_False;
+ const SwNodes& rNds = rInsPos.GetNodes();
+ const bool bDelFtn = rInsPos.GetIndex() < rNds.GetEndOfAutotext().GetIndex() &&
+ rSttNd.GetIndex() >= rNds.GetEndOfAutotext().GetIndex();
+ const bool bSaveFtn = !bDelFtn &&
+ rInsPos.GetIndex() >= rNds.GetEndOfExtras().GetIndex();
+ if( rFtnArr.Count() )
+ {
+
+ sal_uInt16 nPos;
+ rFtnArr.SeekEntry( rSttNd, &nPos );
+ SwTxtFtn* pSrch;
+ const SwNode* pFtnNd;
+
+ // loesche/sicher erstmal alle, die dahinter stehen
+ while( nPos < rFtnArr.Count() && ( pFtnNd =
+ &( pSrch = rFtnArr[ nPos ] )->GetTxtNode())->GetIndex()
+ <= rEndNd.GetIndex() )
+ {
+ xub_StrLen nFtnSttIdx = *pSrch->GetStart();
+ if( ( pEndCnt && pSttCnt )
+ ? (( &rSttNd.GetNode() == pFtnNd &&
+ pSttCnt->GetIndex() > nFtnSttIdx) ||
+ ( &rEndNd.GetNode() == pFtnNd &&
+ nFtnSttIdx >= pEndCnt->GetIndex() ))
+ : ( &rEndNd.GetNode() == pFtnNd ))
+ {
+ ++nPos; // weiter suchen
+ }
+ else
+ {
+ // dann weg damit
+ if( bDelFtn )
+ {
+ SwTxtNode& rTxtNd = (SwTxtNode&)pSrch->GetTxtNode();
+ SwIndex aIdx( &rTxtNd, nFtnSttIdx );
+ rTxtNd.EraseText( aIdx, 1 );
+ }
+ else
+ {
+ pSrch->DelFrms(0);
+ rFtnArr.Remove( nPos );
+ if( bSaveFtn )
+ rSaveArr.Insert( pSrch );
+ }
+ bUpdateFtn = sal_True;
+ }
+ }
+
+ while( nPos-- && ( pFtnNd = &( pSrch = rFtnArr[ nPos ] )->
+ GetTxtNode())->GetIndex() >= rSttNd.GetIndex() )
+ {
+ xub_StrLen nFtnSttIdx = *pSrch->GetStart();
+ if( !pEndCnt || !pSttCnt ||
+ !( (( &rSttNd.GetNode() == pFtnNd &&
+ pSttCnt->GetIndex() > nFtnSttIdx ) ||
+ ( &rEndNd.GetNode() == pFtnNd &&
+ nFtnSttIdx >= pEndCnt->GetIndex() )) ))
+ {
+ if( bDelFtn )
+ {
+ // dann weg damit
+ SwTxtNode& rTxtNd = (SwTxtNode&)pSrch->GetTxtNode();
+ SwIndex aIdx( &rTxtNd, nFtnSttIdx );
+ rTxtNd.EraseText( aIdx, 1 );
+ }
+ else
+ {
+ pSrch->DelFrms(0);
+ rFtnArr.Remove( nPos );
+ if( bSaveFtn )
+ rSaveArr.Insert( pSrch );
+ }
+ bUpdateFtn = sal_True;
+ }
+ }
+ }
+ // When moving from redline section into document content section, e.g.
+ // after loading a document with (delete-)redlines, the footnote array
+ // has to be adjusted... (#i70572)
+ if( bSaveFtn )
+ {
+ SwNodeIndex aIdx( rSttNd );
+ while( aIdx < rEndNd ) // Check the moved section
+ {
+ SwNode* pNode = &aIdx.GetNode();
+ if( pNode->IsTxtNode() ) // Looking for text nodes...
+ {
+ SwpHints *pHints =
+ static_cast<SwTxtNode*>(pNode)->GetpSwpHints();
+ if( pHints && pHints->HasFtn() ) //...with footnotes
+ {
+ bUpdateFtn = sal_True; // Heureka
+ sal_uInt16 nCount = pHints->Count();
+ for( sal_uInt16 i = 0; i < nCount; ++i )
+ {
+ SwTxtAttr *pAttr = pHints->GetTextHint( i );
+ if ( pAttr->Which() == RES_TXTATR_FTN )
+ {
+ rSaveArr.Insert( static_cast<SwTxtFtn*>(pAttr) );
+ }
+ }
+ }
+ }
+ ++aIdx;
+ }
+ }
+ return bUpdateFtn;
+}
+
+void lcl_SaveRedlines( const SwPaM& aPam, _SaveRedlines& rArr )
+{
+ SwDoc* pDoc = aPam.GetNode()->GetDoc();
+
+ const SwPosition* pStart = aPam.Start();
+ const SwPosition* pEnd = aPam.End();
+
+ // get first relevant redline
+ sal_uInt16 nCurrentRedline;
+ pDoc->GetRedline( *pStart, &nCurrentRedline );
+ if( nCurrentRedline > 0)
+ nCurrentRedline--;
+
+ // redline mode REDLINE_IGNORE|REDLINE_ON; save old mode
+ RedlineMode_t eOld = pDoc->GetRedlineMode();
+ pDoc->SetRedlineMode_intern( (RedlineMode_t)(( eOld & ~nsRedlineMode_t::REDLINE_IGNORE) | nsRedlineMode_t::REDLINE_ON ));
+
+ // iterate over relevant redlines and decide for each whether it should
+ // be saved, or split + saved
+ SwRedlineTbl& rRedlineTable = const_cast<SwRedlineTbl&>( pDoc->GetRedlineTbl() );
+ for( ; nCurrentRedline < rRedlineTable.Count(); nCurrentRedline++ )
+ {
+ SwRedline* pCurrent = rRedlineTable[ nCurrentRedline ];
+ SwComparePosition eCompare =
+ ComparePosition( *pCurrent->Start(), *pCurrent->End(),
+ *pStart, *pEnd);
+
+ // we must save this redline if it overlaps aPam
+ // (we may have to split it, too)
+ if( eCompare == POS_OVERLAP_BEHIND ||
+ eCompare == POS_OVERLAP_BEFORE ||
+ eCompare == POS_OUTSIDE ||
+ eCompare == POS_INSIDE ||
+ eCompare == POS_EQUAL )
+ {
+ rRedlineTable.Remove( nCurrentRedline-- );
+
+ // split beginning, if necessary
+ if( eCompare == POS_OVERLAP_BEFORE ||
+ eCompare == POS_OUTSIDE )
+ {
+
+ SwRedline* pNewRedline = new SwRedline( *pCurrent );
+ *pNewRedline->End() = *pStart;
+ *pCurrent->Start() = *pStart;
+ pDoc->AppendRedline( pNewRedline, true );
+ }
+
+ // split end, if necessary
+ if( eCompare == POS_OVERLAP_BEHIND ||
+ eCompare == POS_OUTSIDE )
+ {
+ SwRedline* pNewRedline = new SwRedline( *pCurrent );
+ *pNewRedline->Start() = *pEnd;
+ *pCurrent->End() = *pEnd;
+ pDoc->AppendRedline( pNewRedline, true );
+ }
+
+ // save the current redline
+ _SaveRedline* pSave = new _SaveRedline( pCurrent, *pStart );
+ rArr.C40_INSERT( _SaveRedline, pSave, rArr.Count() );
+ }
+ }
+
+ // restore old redline mode
+ pDoc->SetRedlineMode_intern( eOld );
+}
+
+void lcl_RestoreRedlines( SwDoc* pDoc, const SwPosition& rPos, _SaveRedlines& rArr )
+{
+ RedlineMode_t eOld = pDoc->GetRedlineMode();
+ pDoc->SetRedlineMode_intern( (RedlineMode_t)(( eOld & ~nsRedlineMode_t::REDLINE_IGNORE) | nsRedlineMode_t::REDLINE_ON ));
+
+ for( sal_uInt16 n = 0; n < rArr.Count(); ++n )
+ {
+ _SaveRedline* pSave = rArr[ n ];
+ pSave->SetPos( rPos );
+ pDoc->AppendRedline( pSave->pRedl, true );
+ }
+
+ pDoc->SetRedlineMode_intern( eOld );
+}
+
+void lcl_SaveRedlines( const SwNodeRange& rRg, _SaveRedlines& rArr )
+{
+ SwDoc* pDoc = rRg.aStart.GetNode().GetDoc();
+ sal_uInt16 nRedlPos;
+ SwPosition aSrchPos( rRg.aStart ); aSrchPos.nNode--;
+ aSrchPos.nContent.Assign( aSrchPos.nNode.GetNode().GetCntntNode(), 0 );
+ if( pDoc->GetRedline( aSrchPos, &nRedlPos ) && nRedlPos )
+ --nRedlPos;
+ else if( nRedlPos >= pDoc->GetRedlineTbl().Count() )
+ return ;
+
+ RedlineMode_t eOld = pDoc->GetRedlineMode();
+ pDoc->SetRedlineMode_intern( (RedlineMode_t)(( eOld & ~nsRedlineMode_t::REDLINE_IGNORE) | nsRedlineMode_t::REDLINE_ON ));
+ SwRedlineTbl& rRedlTbl = (SwRedlineTbl&)pDoc->GetRedlineTbl();
+
+ do {
+ SwRedline* pTmp = rRedlTbl[ nRedlPos ];
+
+ const SwPosition* pRStt = pTmp->Start(),
+ * pREnd = pTmp->GetMark() == pRStt
+ ? pTmp->GetPoint() : pTmp->GetMark();
+
+ if( pRStt->nNode < rRg.aStart )
+ {
+ if( pREnd->nNode > rRg.aStart && pREnd->nNode < rRg.aEnd )
+ {
+ // Kopie erzeugen und Ende vom Original ans Ende des
+ // MoveBereiches setzen. Die Kopie wird mit verschoben
+ SwRedline* pNewRedl = new SwRedline( *pTmp );
+ SwPosition* pTmpPos = pNewRedl->Start();
+ pTmpPos->nNode = rRg.aStart;
+ pTmpPos->nContent.Assign(
+ pTmpPos->nNode.GetNode().GetCntntNode(), 0 );
+
+ _SaveRedline* pSave = new _SaveRedline( pNewRedl, rRg.aStart );
+ rArr.C40_INSERT( _SaveRedline, pSave, rArr.Count() );
+
+ pTmpPos = pTmp->End();
+ pTmpPos->nNode = rRg.aEnd;
+ pTmpPos->nContent.Assign(
+ pTmpPos->nNode.GetNode().GetCntntNode(), 0 );
+ }
+ else if( pREnd->nNode == rRg.aStart )
+ {
+ SwPosition* pTmpPos = pTmp->End();
+ pTmpPos->nNode = rRg.aEnd;
+ pTmpPos->nContent.Assign(
+ pTmpPos->nNode.GetNode().GetCntntNode(), 0 );
+ }
+ }
+ else if( pRStt->nNode < rRg.aEnd )
+ {
+ rRedlTbl.Remove( nRedlPos-- );
+ if( pREnd->nNode < rRg.aEnd ||
+ ( pREnd->nNode == rRg.aEnd && !pREnd->nContent.GetIndex()) )
+ {
+ // gesamt verschieben
+ _SaveRedline* pSave = new _SaveRedline( pTmp, rRg.aStart );
+ rArr.C40_INSERT( _SaveRedline, pSave, rArr.Count() );
+ }
+ else
+ {
+ // aufsplitten
+ SwRedline* pNewRedl = new SwRedline( *pTmp );
+ SwPosition* pTmpPos = pNewRedl->End();
+ pTmpPos->nNode = rRg.aEnd;
+ pTmpPos->nContent.Assign(
+ pTmpPos->nNode.GetNode().GetCntntNode(), 0 );
+
+ _SaveRedline* pSave = new _SaveRedline( pNewRedl, rRg.aStart );
+ rArr.C40_INSERT( _SaveRedline, pSave, rArr.Count() );
+
+ pTmpPos = pTmp->Start();
+ pTmpPos->nNode = rRg.aEnd;
+ pTmpPos->nContent.Assign(
+ pTmpPos->nNode.GetNode().GetCntntNode(), 0 );
+ pDoc->AppendRedline( pTmp, true );
+ }
+ }
+ else
+ break;
+
+ } while( ++nRedlPos < pDoc->GetRedlineTbl().Count() );
+ pDoc->SetRedlineMode_intern( eOld );
+}
+
+void lcl_RestoreRedlines( SwDoc* pDoc, sal_uInt32 nInsPos, _SaveRedlines& rArr )
+{
+ RedlineMode_t eOld = pDoc->GetRedlineMode();
+ pDoc->SetRedlineMode_intern( (RedlineMode_t)(( eOld & ~nsRedlineMode_t::REDLINE_IGNORE) | nsRedlineMode_t::REDLINE_ON ));
+
+ for( sal_uInt16 n = 0; n < rArr.Count(); ++n )
+ {
+ _SaveRedline* pSave = rArr[ n ];
+ pSave->SetPos( nInsPos );
+ pDoc->AppendRedline( pSave->pRedl, true );
+ }
+
+ pDoc->SetRedlineMode_intern( eOld );
+}
+
+// #i59534: Redo of insertion of multiple text nodes runs into trouble
+// because of unnecessary expanded redlines
+// From now on this class saves the redline positions of all redlines which ends exact at the
+// insert position (node _and_ content index)
+_SaveRedlEndPosForRestore::_SaveRedlEndPosForRestore( const SwNodeIndex& rInsIdx, xub_StrLen nCnt )
+ : pSavArr( 0 ), pSavIdx( 0 ), nSavCntnt( nCnt )
+{
+ SwNode& rNd = rInsIdx.GetNode();
+ SwDoc* pDest = rNd.GetDoc();
+ if( pDest->GetRedlineTbl().Count() )
+ {
+ sal_uInt16 nFndPos;
+ const SwPosition* pEnd;
+ SwPosition aSrcPos( rInsIdx, SwIndex( rNd.GetCntntNode(), nCnt ));
+ const SwRedline* pRedl = pDest->GetRedline( aSrcPos, &nFndPos );
+ while( nFndPos-- && *( pEnd = ( pRedl =
+ pDest->GetRedlineTbl()[ nFndPos ] )->End() ) == aSrcPos && *pRedl->Start() < aSrcPos )
+ {
+ if( !pSavArr )
+ {
+ pSavArr = new SvPtrarr( 2, 2 );
+ pSavIdx = new SwNodeIndex( rInsIdx, -1 );
+ }
+ void* p = (void*)pEnd;
+ pSavArr->Insert( p, pSavArr->Count() );
+ }
+ }
+}
+
+_SaveRedlEndPosForRestore::~_SaveRedlEndPosForRestore()
+{
+ if( pSavArr )
+ {
+ delete pSavArr;
+ delete pSavIdx;
+ }
+}
+
+void _SaveRedlEndPosForRestore::_Restore()
+{
+ (*pSavIdx)++;
+ SwCntntNode* pNode = pSavIdx->GetNode().GetCntntNode();
+ // If there's no content node at the remembered position, we will not restore the old position
+ // This may happen if a table (or section?) will be inserted.
+ if( pNode )
+ {
+ SwPosition aPos( *pSavIdx, SwIndex( pNode, nSavCntnt ));
+ for( sal_uInt16 n = pSavArr->Count(); n; )
+ *((SwPosition*)pSavArr->GetObject( --n )) = aPos;
+ }
+}
+
+// Loeschen einer vollstaendigen Section des NodesArray.
+// Der uebergebene Node steht irgendwo in der gewuenschten Section
+void SwDoc::DeleteSection( SwNode *pNode )
+{
+ OSL_ENSURE( pNode, "Kein Node uebergeben." );
+ SwStartNode* pSttNd = pNode->IsStartNode() ? (SwStartNode*)pNode
+ : pNode->StartOfSectionNode();
+ SwNodeIndex aSttIdx( *pSttNd ), aEndIdx( *pNode->EndOfSectionNode() );
+
+ // dann loesche mal alle Fly's, text::Bookmarks, ...
+ DelFlyInRange( aSttIdx, aEndIdx );
+ DeleteRedline( *pSttNd, true, USHRT_MAX );
+ _DelBookmarks(aSttIdx, aEndIdx);
+
+ {
+ // alle Crsr/StkCrsr/UnoCrsr aus dem Loeschbereich verschieben
+ SwNodeIndex aMvStt( aSttIdx, 1 );
+ CorrAbs( aMvStt, aEndIdx, SwPosition( aSttIdx ), sal_True );
+ }
+
+ GetNodes().DelNodes( aSttIdx, aEndIdx.GetIndex() - aSttIdx.GetIndex() + 1 );
+}
+
+void SwDoc::SetModified(SwPaM &rPaM)
+{
+ SwDataChanged aTmp( rPaM, 0 );
+ SetModified();
+}
+
+/*************************************************************************
+ * SwDoc::Overwrite()
+ ************************************************************************/
+bool SwDoc::Overwrite( const SwPaM &rRg, const String &rStr )
+{
+ SwPosition& rPt = *(SwPosition*)rRg.GetPoint();
+ if( pACEWord ) // Aufnahme in die Autokorrektur
+ {
+ if( 1 == rStr.Len() )
+ pACEWord->CheckChar( rPt, rStr.GetChar( 0 ) );
+ delete pACEWord, pACEWord = 0;
+ }
+
+ SwTxtNode *pNode = rPt.nNode.GetNode().GetTxtNode();
+ if(!pNode)
+ return sal_False;
+
+ if (GetIDocumentUndoRedo().DoesUndo())
+ {
+ GetIDocumentUndoRedo().ClearRedo(); // AppendUndo not always called
+ }
+
+ sal_uInt16 nOldAttrCnt = pNode->GetpSwpHints()
+ ? pNode->GetpSwpHints()->Count() : 0;
+ SwDataChanged aTmp( rRg, 0 );
+ SwIndex& rIdx = rPt.nContent;
+ xub_StrLen nStart = 0;
+
+ sal_Unicode c;
+ String aStr;
+
+ sal_Bool bOldExpFlg = pNode->IsIgnoreDontExpand();
+ pNode->SetIgnoreDontExpand( sal_True );
+
+ for( xub_StrLen nCnt = 0; nCnt < rStr.Len(); ++nCnt )
+ {
+ // hinter das Zeichen (zum aufspannen der Attribute !!)
+ nStart = rIdx.GetIndex();
+ if ( nStart < pNode->GetTxt().Len() )
+ {
+ lcl_SkipAttr( pNode, rIdx, nStart );
+ }
+ c = rStr.GetChar( nCnt );
+ if (GetIDocumentUndoRedo().DoesUndo())
+ {
+ bool bMerged(false);
+ if (GetIDocumentUndoRedo().DoesGroupUndo())
+ {
+ SwUndo *const pUndo = GetUndoManager().GetLastUndo();
+ SwUndoOverwrite *const pUndoOW(
+ dynamic_cast<SwUndoOverwrite *>(pUndo) );
+ if (pUndoOW)
+ {
+ // if CanGrouping() returns true it's already merged
+ bMerged = pUndoOW->CanGrouping( this, rPt, c );
+ }
+ }
+ if (!bMerged)
+ {
+ SwUndo *const pUndoOW( new SwUndoOverwrite(this, rPt, c) );
+ GetIDocumentUndoRedo().AppendUndo(pUndoOW);
+ }
+ }
+ else
+ {
+ // hinter das Zeichen (zum Aufspannen der Attribute !!)
+ if( nStart < pNode->GetTxt().Len() )
+ rIdx++;
+ pNode->InsertText( c, rIdx, INS_EMPTYEXPAND );
+ if( nStart+1 < rIdx.GetIndex() )
+ {
+ rIdx = nStart;
+ pNode->EraseText( rIdx, 1 );
+ rIdx++;
+ }
+ }
+ }
+ pNode->SetIgnoreDontExpand( bOldExpFlg );
+
+ sal_uInt16 nNewAttrCnt = pNode->GetpSwpHints()
+ ? pNode->GetpSwpHints()->Count() : 0;
+ if( nOldAttrCnt != nNewAttrCnt )
+ {
+ SwUpdateAttr aHint( 0, 0, 0 );
+ pNode->ModifyBroadcast( 0, &aHint, TYPE( SwCrsrShell ) );
+ }
+
+ if (!GetIDocumentUndoRedo().DoesUndo() &&
+ !IsIgnoreRedline() && GetRedlineTbl().Count())
+ {
+ SwPaM aPam( rPt.nNode, nStart, rPt.nNode, rPt.nContent.GetIndex() );
+ DeleteRedline( aPam, true, USHRT_MAX );
+ }
+ else if( IsRedlineOn() )
+ {
+ // FIXME: this redline is WRONG: there is no DELETE, and the skipped
+ // characters are also included in aPam
+ SwPaM aPam( rPt.nNode, nStart, rPt.nNode, rPt.nContent.GetIndex() );
+ AppendRedline( new SwRedline( nsRedlineType_t::REDLINE_INSERT, aPam ), true);
+ }
+
+ SetModified();
+ return sal_True;
+}
+
+bool SwDoc::MoveAndJoin( SwPaM& rPaM, SwPosition& rPos, SwMoveFlags eMvFlags )
+{
+ SwNodeIndex aIdx( rPaM.Start()->nNode );
+ sal_Bool bJoinTxt = aIdx.GetNode().IsTxtNode();
+ sal_Bool bOneNode = rPaM.GetPoint()->nNode == rPaM.GetMark()->nNode;
+ aIdx--; // vor den Move Bereich !!
+
+ bool bRet = MoveRange( rPaM, rPos, eMvFlags );
+ if( bRet && !bOneNode )
+ {
+ if( bJoinTxt )
+ aIdx++;
+ SwTxtNode * pTxtNd = aIdx.GetNode().GetTxtNode();
+ SwNodeIndex aNxtIdx( aIdx );
+ if( pTxtNd && pTxtNd->CanJoinNext( &aNxtIdx ) )
+ {
+ { // Block wegen SwIndex in den Node !!
+ CorrRel( aNxtIdx, SwPosition( aIdx, SwIndex( pTxtNd,
+ pTxtNd->GetTxt().Len() ) ), 0, sal_True );
+ }
+ pTxtNd->JoinNext();
+ }
+ }
+ return bRet;
+}
+
+// mst: it seems that this is mostly used by SwDoc internals; the only
+// way to call this from the outside seems to be the special case in
+// SwDoc::CopyRange (but i have not managed to actually hit that case)
+bool SwDoc::MoveRange( SwPaM& rPaM, SwPosition& rPos, SwMoveFlags eMvFlags )
+{
+ // keine Moves-Abfangen
+ const SwPosition *pStt = rPaM.Start(), *pEnd = rPaM.End();
+ if( !rPaM.HasMark() || *pStt >= *pEnd || (*pStt <= rPos && rPos < *pEnd))
+ return false;
+
+ // sicher die absatzgebundenen Flys, damit sie verschoben werden koennen.
+ _SaveFlyArr aSaveFlyArr;
+ _SaveFlyInRange( rPaM, rPos.nNode, aSaveFlyArr, 0 != ( DOC_MOVEALLFLYS & eMvFlags ) );
+
+ // save redlines (if DOC_MOVEREDLINES is used)
+ _SaveRedlines aSaveRedl( 0, 4 );
+ if( DOC_MOVEREDLINES & eMvFlags && GetRedlineTbl().Count() )
+ {
+ lcl_SaveRedlines( rPaM, aSaveRedl );
+
+ // #i17764# unfortunately, code below relies on undos being
+ // in a particular order, and presence of bookmarks
+ // will change this order. Hence, we delete bookmarks
+ // here without undo.
+ ::sw::UndoGuard const undoGuard(GetIDocumentUndoRedo());
+ _DelBookmarks(
+ pStt->nNode,
+ pEnd->nNode,
+ NULL,
+ &pStt->nContent,
+ &pEnd->nContent);
+ }
+
+
+ int bUpdateFtn = sal_False;
+ SwFtnIdxs aTmpFntIdx;
+
+ // falls Undo eingeschaltet, erzeuge das UndoMove-Objekt
+ SwUndoMove * pUndoMove = 0;
+ if (GetIDocumentUndoRedo().DoesUndo())
+ {
+ GetIDocumentUndoRedo().ClearRedo();
+ pUndoMove = new SwUndoMove( rPaM, rPos );
+ pUndoMove->SetMoveRedlines( eMvFlags == DOC_MOVEREDLINES );
+ }
+ else
+ {
+ bUpdateFtn = lcl_SaveFtn( pStt->nNode, pEnd->nNode, rPos.nNode,
+ GetFtnIdxs(), aTmpFntIdx,
+ &pStt->nContent, &pEnd->nContent );
+ }
+
+ sal_Bool bSplit = sal_False;
+ SwPaM aSavePam( rPos, rPos );
+
+ // stelle den SPoint an den Anfang vom Bereich (Definition)
+ if( rPaM.GetPoint() == pEnd )
+ rPaM.Exchange();
+
+ // in der EditShell wird nach dem Move ein JoinNext erzeugt, wenn
+ // vor und nach dem Move ein Text-Node steht.
+ SwTxtNode* pSrcNd = rPaM.GetPoint()->nNode.GetNode().GetTxtNode();
+ sal_Bool bCorrSavePam = pSrcNd && pStt->nNode != pEnd->nNode;
+
+ // werden ein oder mehr TextNodes bewegt, so wird
+ // im SwNodes::Move ein SplitNode erzeugt. Dieser Updated aber nicht
+ // den Cursor. Um das zu verhindern, wird hier ein TextNode angelegt,
+ // um die Updaterei der Indizies zu erhalten. Nach dem Move wird
+ // evt. der Node geloescht.
+
+ SwTxtNode * pTNd = rPos.nNode.GetNode().GetTxtNode();
+ if( pTNd && rPaM.GetPoint()->nNode != rPaM.GetMark()->nNode &&
+ ( rPos.nContent.GetIndex() || ( pTNd->Len() && bCorrSavePam )) )
+ {
+ bSplit = sal_True;
+ xub_StrLen nMkCntnt = rPaM.GetMark()->nContent.GetIndex();
+
+ SvULongs aBkmkArr( 15, 15 );
+ _SaveCntntIdx( this, rPos.nNode.GetIndex(), rPos.nContent.GetIndex(),
+ aBkmkArr, SAVEFLY_SPLIT );
+
+ pTNd = static_cast<SwTxtNode*>(pTNd->SplitCntntNode( rPos ));
+
+ if( aBkmkArr.Count() )
+ _RestoreCntntIdx( this, aBkmkArr, rPos.nNode.GetIndex()-1, 0, sal_True );
+
+ // jetzt noch den Pam berichtigen !!
+ if( rPos.nNode == rPaM.GetMark()->nNode )
+ {
+ rPaM.GetMark()->nNode = rPos.nNode.GetIndex()-1;
+ rPaM.GetMark()->nContent.Assign( pTNd, nMkCntnt );
+ }
+ }
+
+ // setze den Pam um einen "Inhalt" zurueck; dadurch steht er immer
+ // ausserhalb des manipulierten Bereiches. Falls kein Inhalt mehr vor-
+ // handen, dann auf den StartNode (es ist immer einer vorhanden !!!)
+ sal_Bool bNullCntnt = !aSavePam.Move( fnMoveBackward, fnGoCntnt );
+ if( bNullCntnt )
+ {
+ aSavePam.GetPoint()->nNode--;
+ }
+
+ // kopiere alle Bookmarks, die im Move Bereich stehen in ein
+ // Array, das alle Angaben auf die Position als Offset speichert.
+ // Die neue Zuordung erfolgt nach dem Moven.
+ ::std::vector< ::sw::mark::SaveBookmark> aSaveBkmks;
+ _DelBookmarks(
+ pStt->nNode,
+ pEnd->nNode,
+ &aSaveBkmks,
+ &pStt->nContent,
+ &pEnd->nContent);
+
+ // falls durch die vorherigen Loeschungen (z.B. der Fussnoten) kein
+ // Bereich mehr existiert, ist das immernoch ein gueltiger Move!
+ if( *rPaM.GetPoint() != *rPaM.GetMark() )
+ {
+ // now do the actual move
+ GetNodes().MoveRange( rPaM, rPos, GetNodes() );
+
+ // after a MoveRange() the Mark is deleted
+ if ( rPaM.HasMark() ) // => no Move occurred!
+ {
+ delete pUndoMove;
+ return false;
+ }
+ }
+ else
+ rPaM.DeleteMark();
+
+ OSL_ENSURE( *aSavePam.GetMark() == rPos ||
+ ( aSavePam.GetMark()->nNode.GetNode().GetCntntNode() == NULL ),
+ "PaM wurde nicht verschoben, am Anfang/Ende keine ContentNodes?" );
+ *aSavePam.GetMark() = rPos;
+
+ rPaM.SetMark(); // um den neuen Bereich eine Sel. aufspannen
+ pTNd = aSavePam.GetNode()->GetTxtNode();
+ if (GetIDocumentUndoRedo().DoesUndo())
+ {
+ // korrigiere erstmal den Content vom SavePam
+ if( bNullCntnt )
+ {
+ aSavePam.GetPoint()->nContent = 0;
+ }
+
+ // die Methode SwEditShell::Move() fuegt nach dem Move den Text-Node
+ // zusammen, in dem der rPaM steht. Wurde der Inhalt nach hinten
+ // geschoben und liegt der SPoint vom SavePam im naechsten Node, so
+ // muss beim Speichern vom Undo-Object das beachtet werden !!
+ SwTxtNode * pPamTxtNd = 0;
+
+ // wird ans SwUndoMove weitergegeben, das dann beim Undo JoinNext
+ // aufruft. (falls es hier nicht moeglich ist).
+ sal_Bool bJoin = bSplit && pTNd;
+ bCorrSavePam = bCorrSavePam &&
+ 0 != ( pPamTxtNd = rPaM.GetNode()->GetTxtNode() )
+ && pPamTxtNd->CanJoinNext()
+ && (*rPaM.GetPoint() <= *aSavePam.GetPoint());
+
+ // muessen am SavePam 2 Nodes zusammengefasst werden ??
+ if( bJoin && pTNd->CanJoinNext() )
+ {
+ pTNd->JoinNext();
+ // kein temp. sdbcx::Index bei &&
+ // es sollten wohl nur die Indexwerte verglichen werden.
+ if( bCorrSavePam && rPaM.GetPoint()->nNode.GetIndex()+1 ==
+ aSavePam.GetPoint()->nNode.GetIndex() )
+ {
+ aSavePam.GetPoint()->nContent += pPamTxtNd->Len();
+ }
+ bJoin = sal_False;
+ }
+ else if ( !aSavePam.Move( fnMoveForward, fnGoCntnt ) )
+ {
+ aSavePam.GetPoint()->nNode++;
+ }
+
+ // zwischen SPoint und GetMark steht jetzt der neu eingefuegte Bereich
+ pUndoMove->SetDestRange( aSavePam, *rPaM.GetPoint(),
+ bJoin, bCorrSavePam );
+ GetIDocumentUndoRedo().AppendUndo( pUndoMove );
+ }
+ else
+ {
+ bool bRemove = true;
+ // muessen am SavePam 2 Nodes zusammengefasst werden ??
+ if( bSplit && pTNd )
+ {
+ if( pTNd->CanJoinNext())
+ {
+ // Always join next, because <pTNd> has to stay as it is.
+ // A join previous from its next would more or less delete <pTNd>
+ pTNd->JoinNext();
+ bRemove = false;
+ }
+ }
+ if( bNullCntnt )
+ {
+ aSavePam.GetPoint()->nNode++;
+ aSavePam.GetPoint()->nContent.Assign( aSavePam.GetCntntNode(), 0 );
+ }
+ else if( bRemove ) // No move forward after joining with next paragraph
+ {
+ aSavePam.Move( fnMoveForward, fnGoCntnt );
+ }
+ }
+
+ // setze jetzt wieder die text::Bookmarks in das Dokument
+ *rPaM.GetMark() = *aSavePam.Start();
+ for(
+ ::std::vector< ::sw::mark::SaveBookmark>::iterator pBkmk = aSaveBkmks.begin();
+ pBkmk != aSaveBkmks.end();
+ ++pBkmk)
+ pBkmk->SetInDoc(
+ this,
+ rPaM.GetMark()->nNode,
+ &rPaM.GetMark()->nContent);
+ *rPaM.GetPoint() = *aSavePam.End();
+
+ // verschiebe die Flys an die neue Position
+ _RestFlyInRange( aSaveFlyArr, rPaM.Start()->nNode, &(rPos.nNode) );
+
+ // restore redlines (if DOC_MOVEREDLINES is used)
+ if( aSaveRedl.Count() )
+ {
+ lcl_RestoreRedlines( this, *aSavePam.Start(), aSaveRedl );
+ }
+
+ if( bUpdateFtn )
+ {
+ if( aTmpFntIdx.Count() )
+ {
+ GetFtnIdxs().Insert( &aTmpFntIdx );
+ aTmpFntIdx.Remove( sal_uInt16( 0 ), aTmpFntIdx.Count() );
+ }
+
+ GetFtnIdxs().UpdateAllFtn();
+ }
+
+ SetModified();
+ return true;
+}
+
+bool SwDoc::MoveNodeRange( SwNodeRange& rRange, SwNodeIndex& rPos,
+ SwMoveFlags eMvFlags )
+{
+ // bewegt alle Nodes an die neue Position. Dabei werden die
+ // text::Bookmarks mit verschoben !! (zur Zeit ohne Undo)
+
+ // falls durchs Move Fussnoten in den Sonderbereich kommen sollten,
+ // dann entferne sie jetzt.
+ //JP 13.07.95:
+ // ansonsten bei allen Fussnoten, die verschoben werden, die Frames
+ // loeschen und nach dem Move wieder aufbauen lassen (Fussnoten koennen
+ // die Seite wechseln). Zusaetzlich muss natuerlich die Sortierung
+ // der FtnIdx-Array wieder korrigiert werden.
+
+ int bUpdateFtn = sal_False;
+ SwFtnIdxs aTmpFntIdx;
+
+ SwUndoMove* pUndo = 0;
+ if ((DOC_CREATEUNDOOBJ & eMvFlags ) && GetIDocumentUndoRedo().DoesUndo())
+ {
+ pUndo = new SwUndoMove( this, rRange, rPos );
+ }
+ else
+ {
+ bUpdateFtn = lcl_SaveFtn( rRange.aStart, rRange.aEnd, rPos,
+ GetFtnIdxs(), aTmpFntIdx );
+ }
+
+ _SaveRedlines aSaveRedl( 0, 4 );
+ SvPtrarr aSavRedlInsPosArr( 0, 4 );
+ if( DOC_MOVEREDLINES & eMvFlags && GetRedlineTbl().Count() )
+ {
+ lcl_SaveRedlines( rRange, aSaveRedl );
+
+ // suche alle Redlines, die an der InsPos aufhoeren. Diese muessen
+ // nach dem Move wieder an die "alte" Position verschoben werden
+ sal_uInt16 nRedlPos = GetRedlinePos( rPos.GetNode(), USHRT_MAX );
+ if( USHRT_MAX != nRedlPos )
+ {
+ const SwPosition *pRStt, *pREnd;
+ do {
+ SwRedline* pTmp = GetRedlineTbl()[ nRedlPos ];
+ pRStt = pTmp->Start();
+ pREnd = pTmp->End();
+ if( pREnd->nNode == rPos && pRStt->nNode < rPos )
+ {
+ void* p = pTmp;
+ aSavRedlInsPosArr.Insert( p, aSavRedlInsPosArr.Count() );
+ }
+ } while( pRStt->nNode < rPos && ++nRedlPos < GetRedlineTbl().Count());
+ }
+ }
+
+ // kopiere alle Bookmarks, die im Move Bereich stehen in ein
+ // Array, das alle Angaben auf die Position als Offset speichert.
+ // Die neue Zuordung erfolgt nach dem Moven.
+ ::std::vector< ::sw::mark::SaveBookmark> aSaveBkmks;
+ _DelBookmarks(rRange.aStart, rRange.aEnd, &aSaveBkmks);
+
+ // sicher die absatzgebundenen Flys, damit verschoben werden koennen.
+ _SaveFlyArr aSaveFlyArr;
+ if( GetSpzFrmFmts()->Count() )
+ _SaveFlyInRange( rRange, aSaveFlyArr );
+
+ // vor die Position setzen, damit er nicht weitergeschoben wird
+ SwNodeIndex aIdx( rPos, -1 );
+
+ SwNodeIndex* pSaveInsPos = 0;
+ if( pUndo )
+ pSaveInsPos = new SwNodeIndex( rRange.aStart, -1 );
+
+ // verschiebe die Nodes
+ sal_Bool bNoDelFrms = 0 != (DOC_NO_DELFRMS & eMvFlags);
+ if( GetNodes()._MoveNodes( rRange, GetNodes(), rPos, !bNoDelFrms ) )
+ {
+ aIdx++; // wieder auf alte Position
+ if( pSaveInsPos )
+ (*pSaveInsPos)++;
+ }
+ else
+ {
+ aIdx = rRange.aStart;
+ delete pUndo, pUndo = 0;
+ }
+
+ // verschiebe die Flys an die neue Position
+ if( aSaveFlyArr.Count() )
+ _RestFlyInRange( aSaveFlyArr, aIdx, NULL );
+
+ // setze jetzt wieder die text::Bookmarks in das Dokument
+ for(
+ ::std::vector< ::sw::mark::SaveBookmark>::iterator pBkmk = aSaveBkmks.begin();
+ pBkmk != aSaveBkmks.end();
+ ++pBkmk)
+ pBkmk->SetInDoc(this, aIdx);
+
+ if( aSavRedlInsPosArr.Count() )
+ {
+ SwNode* pNewNd = &aIdx.GetNode();
+ for( sal_uInt16 n = 0; n < aSavRedlInsPosArr.Count(); ++n )
+ {
+ SwRedline* pTmp = (SwRedline*)aSavRedlInsPosArr[ n ];
+ if( USHRT_MAX != GetRedlineTbl().GetPos( pTmp ) )
+ {
+ SwPosition* pEnd = pTmp->End();
+ pEnd->nNode = aIdx;
+ pEnd->nContent.Assign( pNewNd->GetCntntNode(), 0 );
+ }
+ }
+ }
+
+ if( aSaveRedl.Count() )
+ lcl_RestoreRedlines( this, aIdx.GetIndex(), aSaveRedl );
+
+ if( pUndo )
+ {
+ pUndo->SetDestRange( aIdx, rPos, *pSaveInsPos );
+ GetIDocumentUndoRedo().AppendUndo(pUndo);
+ }
+
+ if( pSaveInsPos )
+ delete pSaveInsPos;
+
+ if( bUpdateFtn )
+ {
+ if( aTmpFntIdx.Count() )
+ {
+ GetFtnIdxs().Insert( &aTmpFntIdx );
+ aTmpFntIdx.Remove( sal_uInt16( 0 ), aTmpFntIdx.Count() );
+ }
+
+ GetFtnIdxs().UpdateAllFtn();
+ }
+
+ SetModified();
+ return sal_True;
+}
+
+// Convert list of ranges of whichIds to a corresponding list of whichIds
+SvUShorts * lcl_RangesToUShorts(sal_uInt16 * pRanges)
+{
+ SvUShorts * pResult = new SvUShorts();
+
+ int i = 0;
+ while (pRanges[i] != 0)
+ {
+ OSL_ENSURE(pRanges[i+1] != 0, "malformed ranges");
+
+ for (sal_uInt16 j = pRanges[i]; j < pRanges[i+1]; j++)
+ pResult->Insert(j, pResult->Count());
+
+ i += 2;
+ }
+
+ return pResult;
+}
+
+bool lcl_StrLenOverFlow( const SwPaM& rPam )
+{
+ // If we try to merge two paragraph we have to test if afterwards
+ // the string doesn't exceed the allowed string length
+ bool bRet = false;
+ if( rPam.GetPoint()->nNode != rPam.GetMark()->nNode )
+ {
+ const SwPosition* pStt = rPam.Start(), *pEnd = rPam.End();
+ const SwTxtNode* pEndNd = pEnd->nNode.GetNode().GetTxtNode();
+ if( (0 != pEndNd) && pStt->nNode.GetNode().IsTxtNode() )
+ {
+ sal_uInt64 nSum = pStt->nContent.GetIndex() +
+ pEndNd->GetTxt().Len() - pEnd->nContent.GetIndex();
+ if( nSum > STRING_LEN )
+ bRet = true;
+ }
+ }
+ return bRet;
+}
+
+void lcl_GetJoinFlags( SwPaM& rPam, sal_Bool& rJoinTxt, sal_Bool& rJoinPrev )
+{
+ rJoinTxt = sal_False;
+ rJoinPrev = sal_False;
+ if( rPam.GetPoint()->nNode != rPam.GetMark()->nNode )
+ {
+ const SwPosition* pStt = rPam.Start(), *pEnd = rPam.End();
+ SwTxtNode *pSttNd = pStt->nNode.GetNode().GetTxtNode();
+ if( pSttNd )
+ {
+ SwTxtNode *pEndNd = pEnd->nNode.GetNode().GetTxtNode();
+ rJoinTxt = 0 != pEndNd;
+ if( rJoinTxt )
+ {
+ bool bExchange = pStt == rPam.GetPoint();
+ if( !pStt->nContent.GetIndex() &&
+ pEndNd->GetTxt().Len() != pEnd->nContent.GetIndex() )
+ bExchange = !bExchange;
+ if( bExchange )
+ rPam.Exchange();
+ rJoinPrev = rPam.GetPoint() == pStt;
+ OSL_ENSURE( !pStt->nContent.GetIndex() &&
+ pEndNd->GetTxt().Len() != pEnd->nContent.GetIndex()
+ ? rPam.GetPoint()->nNode < rPam.GetMark()->nNode
+ : rPam.GetPoint()->nNode > rPam.GetMark()->nNode,
+ "lcl_GetJoinFlags");
+ }
+ }
+ }
+}
+
+void lcl_JoinText( SwPaM& rPam, sal_Bool bJoinPrev )
+{
+ SwNodeIndex aIdx( rPam.GetPoint()->nNode );
+ SwTxtNode *pTxtNd = aIdx.GetNode().GetTxtNode();
+ SwNodeIndex aOldIdx( aIdx );
+ SwTxtNode *pOldTxtNd = pTxtNd;
+
+ if( pTxtNd && pTxtNd->CanJoinNext( &aIdx ) )
+ {
+ SwDoc* pDoc = rPam.GetDoc();
+ if( bJoinPrev )
+ {
+ // N.B.: we do not need to handle xmlids in this case, because
+ // it is only invoked if one paragraph is completely empty
+ // (see lcl_GetJoinFlags)
+ {
+ // falls PageBreaks geloescht / gesetzt werden, darf das
+ // nicht in die Undo-History aufgenommen werden !!
+ // (das loeschen vom Node geht auch am Undo vorbei !!!)
+ ::sw::UndoGuard const undoGuard(pDoc->GetIDocumentUndoRedo());
+
+ /* PageBreaks, PageDesc, ColumnBreaks */
+ // Sollte an der Logik zum Kopieren der PageBreak's ...
+ // etwas geaendert werden, muss es auch im SwUndoDelete
+ // geandert werden. Dort wird sich das AUTO-PageBreak
+ // aus dem GetMarkNode kopiert.!!!
+
+ /* Der GetMarkNode */
+ if( ( pTxtNd = aIdx.GetNode().GetTxtNode())->HasSwAttrSet() )
+ {
+ const SfxPoolItem* pItem;
+ if( SFX_ITEM_SET == pTxtNd->GetpSwAttrSet()->GetItemState(
+ RES_BREAK, sal_False, &pItem ) )
+ pTxtNd->ResetAttr( RES_BREAK );
+ if( pTxtNd->HasSwAttrSet() &&
+ SFX_ITEM_SET == pTxtNd->GetpSwAttrSet()->GetItemState(
+ RES_PAGEDESC, sal_False, &pItem ) )
+ pTxtNd->ResetAttr( RES_PAGEDESC );
+ }
+
+ /* Der PointNode */
+ if( pOldTxtNd->HasSwAttrSet() )
+ {
+ const SfxPoolItem* pItem;
+ SfxItemSet aSet( pDoc->GetAttrPool(), aBreakSetRange );
+ const SfxItemSet* pSet = pOldTxtNd->GetpSwAttrSet();
+ if( SFX_ITEM_SET == pSet->GetItemState( RES_BREAK,
+ sal_False, &pItem ) )
+ aSet.Put( *pItem );
+ if( SFX_ITEM_SET == pSet->GetItemState( RES_PAGEDESC,
+ sal_False, &pItem ) )
+ aSet.Put( *pItem );
+ if( aSet.Count() )
+ pTxtNd->SetAttr( aSet );
+ }
+ pOldTxtNd->FmtToTxtAttr( pTxtNd );
+
+ SvULongs aBkmkArr( 15, 15 );
+ ::_SaveCntntIdx( pDoc, aOldIdx.GetIndex(),
+ pOldTxtNd->Len(), aBkmkArr );
+
+ SwIndex aAlphaIdx(pTxtNd);
+ pOldTxtNd->CutText( pTxtNd, aAlphaIdx, SwIndex(pOldTxtNd),
+ pOldTxtNd->Len() );
+ SwPosition aAlphaPos( aIdx, aAlphaIdx );
+ pDoc->CorrRel( rPam.GetPoint()->nNode, aAlphaPos, 0, sal_True );
+
+ // verschiebe noch alle Bookmarks/TOXMarks
+ if( aBkmkArr.Count() )
+ ::_RestoreCntntIdx( pDoc, aBkmkArr, aIdx.GetIndex() );
+
+ // falls der uebergebene PaM nicht im Crsr-Ring steht,
+ // gesondert behandeln (z.B. Aufruf aus dem Auto-Format)
+ if( pOldTxtNd == rPam.GetBound( sal_True ).nContent.GetIdxReg() )
+ rPam.GetBound( sal_True ) = aAlphaPos;
+ if( pOldTxtNd == rPam.GetBound( sal_False ).nContent.GetIdxReg() )
+ rPam.GetBound( sal_False ) = aAlphaPos;
+ }
+ // jetzt nur noch den Node loeschen
+ pDoc->GetNodes().Delete( aOldIdx, 1 );
+ }
+ else
+ {
+ SwTxtNode* pDelNd = aIdx.GetNode().GetTxtNode();
+ if( pTxtNd->Len() )
+ pDelNd->FmtToTxtAttr( pTxtNd );
+ else
+ {
+ /* This case was missed:
+
+ <something></something> <-- pTxtNd
+ <other>ccc</other> <-- pDelNd
+
+ <something> and <other> are paragraph
+ attributes. The attribute <something> stayed if not
+ overwritten by an attribute in "ccc". Fixed by
+ first resetting all character attributes in first
+ paragraph (pTxtNd).
+ */
+ SvUShorts * pShorts =
+ lcl_RangesToUShorts(aCharFmtSetRange);
+ pTxtNd->ResetAttr(*pShorts);
+ delete pShorts;
+
+ if( pDelNd->HasSwAttrSet() )
+ {
+ // nur die Zeichenattribute kopieren
+ SfxItemSet aTmpSet( pDoc->GetAttrPool(), aCharFmtSetRange );
+ aTmpSet.Put( *pDelNd->GetpSwAttrSet() );
+ pTxtNd->SetAttr( aTmpSet );
+ }
+ }
+
+ pDoc->CorrRel( aIdx, *rPam.GetPoint(), 0, sal_True );
+ // #i100466# adjust given <rPam>, if it does not belong to the cursors
+ if ( pDelNd == rPam.GetBound( sal_True ).nContent.GetIdxReg() )
+ {
+ rPam.GetBound( sal_True ) = SwPosition( SwNodeIndex( *pTxtNd ), SwIndex( pTxtNd ) );
+ }
+ if( pDelNd == rPam.GetBound( sal_False ).nContent.GetIdxReg() )
+ {
+ rPam.GetBound( sal_False ) = SwPosition( SwNodeIndex( *pTxtNd ), SwIndex( pTxtNd ) );
+ }
+ pTxtNd->JoinNext();
+ }
+ }
+}
+
+static void
+lcl_CalcBreaks( ::std::vector<xub_StrLen> & rBreaks, SwPaM const & rPam )
+{
+ SwTxtNode const * const pTxtNode(
+ rPam.End()->nNode.GetNode().GetTxtNode() );
+ if (!pTxtNode)
+ return; // left-overlap only possible at end of selection...
+
+ const xub_StrLen nStart(rPam.Start()->nContent.GetIndex());
+ const xub_StrLen nEnd (rPam.End ()->nContent.GetIndex());
+ if (nEnd == pTxtNode->Len())
+ return; // paragraph selected until the end
+
+ for (xub_StrLen i = nStart; i < nEnd; ++i)
+ {
+ const sal_Unicode c(pTxtNode->GetTxt().GetChar(i));
+ if ((CH_TXTATR_INWORD == c) || (CH_TXTATR_BREAKWORD == c))
+ {
+ SwTxtAttr const * const pAttr( pTxtNode->GetTxtAttrForCharAt(i) );
+ if (pAttr && pAttr->GetEnd() && (*pAttr->GetEnd() > nEnd))
+ {
+ OSL_ENSURE(pAttr->HasDummyChar(), "GetTxtAttrForCharAt broken?");
+ rBreaks.push_back(i);
+ }
+ }
+ }
+}
+
+bool lcl_DoWithBreaks(SwDoc & rDoc, SwPaM & rPam,
+ bool (SwDoc::*pFunc)(SwPaM&, bool), const bool bForceJoinNext = false)
+{
+ ::std::vector<xub_StrLen> Breaks;
+
+ lcl_CalcBreaks(Breaks, rPam);
+
+ if (!Breaks.size())
+ {
+ return (rDoc.*pFunc)(rPam, bForceJoinNext);
+ }
+
+ // N.B.: deletion must be split into several parts if the text node
+ // contains a text attribute with end and with dummy character
+ // and the selection does not contain the text attribute completely,
+ // but overlaps its start (left), where the dummy character is.
+
+ SwPosition const & rSelectionEnd( *rPam.End() );
+
+ bool bRet( true );
+ // iterate from end to start, to avoid invalidating the offsets!
+ ::std::vector<xub_StrLen>::reverse_iterator iter( Breaks.rbegin() );
+ SwPaM aPam( rSelectionEnd, rSelectionEnd ); // end node!
+ SwPosition & rEnd( *aPam.End() );
+ SwPosition & rStart( *aPam.Start() );
+
+ while (iter != Breaks.rend())
+ {
+ rStart.nContent = *iter + 1;
+ if (rEnd.nContent > rStart.nContent) // check if part is empty
+ {
+ bRet &= (rDoc.*pFunc)(aPam, bForceJoinNext);
+ }
+ rEnd.nContent = *iter;
+ ++iter;
+ }
+
+ rStart = *rPam.Start(); // set to original start
+ if (rEnd.nContent > rStart.nContent) // check if part is empty
+ {
+ bRet &= (rDoc.*pFunc)(aPam, bForceJoinNext);
+ }
+
+ return bRet;
+}
+
+bool SwDoc::DeleteAndJoinWithRedlineImpl( SwPaM & rPam, const bool )
+{
+ OSL_ENSURE( IsRedlineOn(), "DeleteAndJoinWithRedline: redline off" );
+
+ {
+ SwUndoRedlineDelete* pUndo = 0;
+ RedlineMode_t eOld = GetRedlineMode();
+ checkRedlining(eOld);
+ if (GetIDocumentUndoRedo().DoesUndo())
+ {
+
+ //JP 06.01.98: MUSS noch optimiert werden!!!
+ SetRedlineMode(
+ (RedlineMode_t)(nsRedlineMode_t::REDLINE_ON | nsRedlineMode_t::REDLINE_SHOW_INSERT | nsRedlineMode_t::REDLINE_SHOW_DELETE ));
+
+ GetIDocumentUndoRedo().StartUndo(UNDO_EMPTY, NULL);
+ pUndo = new SwUndoRedlineDelete( rPam, UNDO_DELETE );
+ GetIDocumentUndoRedo().AppendUndo(pUndo);
+ }
+ if( *rPam.GetPoint() != *rPam.GetMark() )
+ AppendRedline( new SwRedline( nsRedlineType_t::REDLINE_DELETE, rPam ), true);
+ SetModified();
+
+ if( pUndo )
+ {
+ GetIDocumentUndoRedo().EndUndo(UNDO_EMPTY, NULL);
+ // ??? why the hell is the AppendUndo not below the
+ // CanGrouping, so this hideous cleanup wouldn't be necessary?
+ // bah, this is redlining, probably changing this would break it...
+ if (GetIDocumentUndoRedo().DoesGroupUndo())
+ {
+ SwUndo *const pLastUndo( GetUndoManager().GetLastUndo() );
+ SwUndoRedlineDelete *const pUndoRedlineDel(
+ dynamic_cast<SwUndoRedlineDelete*>(pLastUndo) );
+ if (pUndoRedlineDel)
+ {
+ bool const bMerged = pUndoRedlineDel->CanGrouping(*pUndo);
+ if (bMerged)
+ {
+ ::sw::UndoGuard const undoGuard(GetIDocumentUndoRedo());
+ SwUndo const*const pDeleted =
+ GetUndoManager().RemoveLastUndo();
+ OSL_ENSURE(pDeleted == pUndo,
+ "DeleteAndJoinWithRedlineImpl: "
+ "undo removed is not undo inserted?");
+ delete pDeleted;
+ }
+ }
+ }
+//JP 06.01.98: MUSS noch optimiert werden!!!
+SetRedlineMode( eOld );
+ }
+ return true;
+ }
+}
+
+bool SwDoc::DeleteAndJoinImpl( SwPaM & rPam,
+ const bool bForceJoinNext )
+{
+ sal_Bool bJoinTxt, bJoinPrev;
+ lcl_GetJoinFlags( rPam, bJoinTxt, bJoinPrev );
+ // #i100466#
+ if ( bForceJoinNext )
+ {
+ bJoinPrev = sal_False;
+ }
+
+ {
+ bool const bSuccess( DeleteRangeImpl( rPam ) );
+ if (!bSuccess)
+ return false;
+ }
+
+ if( bJoinTxt )
+ {
+ lcl_JoinText( rPam, bJoinPrev );
+ }
+
+ return true;
+}
+
+bool SwDoc::DeleteRangeImpl(SwPaM & rPam, const bool)
+{
+ // move all cursors out of the deleted range.
+ // but first copy the given PaM, because it could be a cursor that
+ // would be moved!
+ SwPaM aDelPam( *rPam.GetMark(), *rPam.GetPoint() );
+ ::PaMCorrAbs( aDelPam, *aDelPam.GetPoint() );
+
+ bool const bSuccess( DeleteRangeImplImpl( aDelPam ) );
+ if (bSuccess)
+ { // now copy position from temp copy to given PaM
+ *rPam.GetPoint() = *aDelPam.GetPoint();
+ }
+
+ return bSuccess;
+}
+
+bool SwDoc::DeleteRangeImplImpl(SwPaM & rPam)
+{
+ SwPosition *pStt = (SwPosition*)rPam.Start(), *pEnd = (SwPosition*)rPam.End();
+
+ if( !rPam.HasMark() || *pStt >= *pEnd )
+ return false;
+
+ if( pACEWord )
+ {
+ // ggfs. das gesicherte Word fuer die Ausnahme
+ if( pACEWord->IsDeleted() || pStt->nNode != pEnd->nNode ||
+ pStt->nContent.GetIndex() + 1 != pEnd->nContent.GetIndex() ||
+ !pACEWord->CheckDelChar( *pStt ))
+ delete pACEWord, pACEWord = 0;
+ }
+
+ {
+ // loesche alle leeren TextHints an der Mark-Position
+ SwTxtNode* pTxtNd = rPam.GetMark()->nNode.GetNode().GetTxtNode();
+ SwpHints* pHts;
+ if( pTxtNd && 0 != ( pHts = pTxtNd->GetpSwpHints()) && pHts->Count() )
+ {
+ const xub_StrLen *pEndIdx;
+ xub_StrLen nMkCntPos = rPam.GetMark()->nContent.GetIndex();
+ for( sal_uInt16 n = pHts->Count(); n; )
+ {
+ const SwTxtAttr* pAttr = (*pHts)[ --n ];
+ if( nMkCntPos > *pAttr->GetStart() )
+ break;
+
+ if( nMkCntPos == *pAttr->GetStart() &&
+ 0 != (pEndIdx = pAttr->GetEnd()) &&
+ *pEndIdx == *pAttr->GetStart() )
+ pTxtNd->DestroyAttr( pHts->Cut( n ) );
+ }
+ }
+ }
+
+ {
+ // Bug 26675: DataChanged vorm loeschen verschicken, dann bekommt
+ // man noch mit, welche Objecte sich im Bereich befinden.
+ // Danach koennen sie vor/hinter der Position befinden.
+ SwDataChanged aTmp( rPam, 0 );
+ }
+
+
+ if (GetIDocumentUndoRedo().DoesUndo())
+ {
+ GetIDocumentUndoRedo().ClearRedo();
+ bool bMerged(false);
+ if (GetIDocumentUndoRedo().DoesGroupUndo())
+ {
+ SwUndo *const pLastUndo( GetUndoManager().GetLastUndo() );
+ SwUndoDelete *const pUndoDelete(
+ dynamic_cast<SwUndoDelete *>(pLastUndo) );
+ if (pUndoDelete)
+ {
+ bMerged = pUndoDelete->CanGrouping( this, rPam );
+ // if CanGrouping() returns true it's already merged
+ }
+ }
+ if (!bMerged)
+ {
+ GetIDocumentUndoRedo().AppendUndo( new SwUndoDelete( rPam ) );
+ }
+
+ SetModified();
+
+ return true;
+ }
+
+ if( !IsIgnoreRedline() && GetRedlineTbl().Count() )
+ DeleteRedline( rPam, true, USHRT_MAX );
+
+ // loesche und verschiebe erstmal alle "Fly's am Absatz", die in der
+ // Selection liegen
+ DelFlyInRange(rPam.GetMark()->nNode, rPam.GetPoint()->nNode);
+ _DelBookmarks(
+ pStt->nNode,
+ pEnd->nNode,
+ NULL,
+ &pStt->nContent,
+ &pEnd->nContent);
+
+ SwNodeIndex aSttIdx( pStt->nNode );
+ SwCntntNode * pCNd = aSttIdx.GetNode().GetCntntNode();
+
+ do { // middle checked loop!
+ if( pCNd )
+ {
+ SwTxtNode * pStartTxtNode( pCNd->GetTxtNode() );
+ if ( pStartTxtNode )
+ {
+ // verschiebe jetzt noch den Inhalt in den neuen Node
+ sal_Bool bOneNd = pStt->nNode == pEnd->nNode;
+ xub_StrLen nLen = ( bOneNd ? pEnd->nContent.GetIndex()
+ : pCNd->Len() )
+ - pStt->nContent.GetIndex();
+
+ // falls schon leer, dann nicht noch aufrufen
+ if( nLen )
+ {
+ pStartTxtNode->EraseText( pStt->nContent, nLen );
+
+ if( !pStartTxtNode->Len() )
+ {
+ // METADATA: remove reference if empty (consider node deleted)
+ pStartTxtNode->RemoveMetadataReference();
+ }
+ }
+
+ if( bOneNd ) // das wars schon
+ break;
+
+ aSttIdx++;
+ }
+ else
+ {
+ // damit beim loeschen keine Indizies mehr angemeldet sind,
+ // wird hier der SwPaM aus dem Content entfernt !!
+ pStt->nContent.Assign( 0, 0 );
+ }
+ }
+
+ pCNd = pEnd->nNode.GetNode().GetCntntNode();
+ if( pCNd )
+ {
+ SwTxtNode * pEndTxtNode( pCNd->GetTxtNode() );
+ if( pEndTxtNode )
+ {
+ // falls schon leer, dann nicht noch aufrufen
+ if( pEnd->nContent.GetIndex() )
+ {
+ SwIndex aIdx( pCNd, 0 );
+ pEndTxtNode->EraseText( aIdx, pEnd->nContent.GetIndex() );
+
+ if( !pEndTxtNode->Len() )
+ {
+ // METADATA: remove reference if empty (consider node deleted)
+ pEndTxtNode->RemoveMetadataReference();
+ }
+ }
+ }
+ else
+ {
+ // damit beim Loeschen keine Indizies mehr angemeldet sind,
+ // wird hier der SwPaM aus dem Content entfernt !!
+ pEnd->nContent.Assign( 0, 0 );
+ }
+ }
+
+ // if the end is not a content node, delete it as well
+ sal_uInt32 nEnde = pEnd->nNode.GetIndex();
+ if( pCNd == NULL )
+ nEnde++;
+
+ if( aSttIdx != nEnde )
+ {
+ // loesche jetzt die Nodes in das NodesArary
+ GetNodes().Delete( aSttIdx, nEnde - aSttIdx.GetIndex() );
+ }
+
+ // falls der Node geloescht wurde, in dem der Cursor stand, so
+ // muss der Content im akt. Content angemeldet werden !!!
+ pStt->nContent.Assign( pStt->nNode.GetNode().GetCntntNode(),
+ pStt->nContent.GetIndex() );
+
+ // der PaM wird korrigiert, denn falls ueber Nodegrenzen geloescht
+ // wurde, so stehen sie in unterschieden Nodes. Auch die Selektion
+ // wird aufgehoben !
+ *pEnd = *pStt;
+ rPam.DeleteMark();
+
+ } while( sal_False );
+
+ if( !IsIgnoreRedline() && GetRedlineTbl().Count() )
+ CompressRedlines();
+ SetModified();
+
+ return true;
+}
+
+// #i100466# Add handling of new optional parameter <bForceJoinNext>
+bool SwDoc::DeleteAndJoin( SwPaM & rPam,
+ const bool bForceJoinNext )
+{
+ if ( lcl_StrLenOverFlow( rPam ) )
+ return false;
+
+ return lcl_DoWithBreaks( *this, rPam, (IsRedlineOn())
+ ? &SwDoc::DeleteAndJoinWithRedlineImpl
+ : &SwDoc::DeleteAndJoinImpl,
+ bForceJoinNext );
+}
+
+bool SwDoc::DeleteRange( SwPaM & rPam )
+{
+ return lcl_DoWithBreaks( *this, rPam, &SwDoc::DeleteRangeImpl );
+}
+
+
+void lcl_syncGrammarError( SwTxtNode &rTxtNode, linguistic2::ProofreadingResult& rResult,
+ xub_StrLen /*nBeginGrammarCheck*/, const ModelToViewHelper::ConversionMap* pConversionMap )
+{
+ if( rTxtNode.IsGrammarCheckDirty() )
+ return;
+ SwGrammarMarkUp* pWrong = rTxtNode.GetGrammarCheck();
+ linguistic2::SingleProofreadingError* pArray = rResult.aErrors.getArray();
+ sal_uInt16 i, j = 0;
+ if( pWrong )
+ {
+ for( i = 0; i < rResult.aErrors.getLength(); ++i )
+ {
+ const linguistic2::SingleProofreadingError &rError = rResult.aErrors[i];
+ xub_StrLen nStart = (xub_StrLen)ModelToViewHelper::ConvertToModelPosition( pConversionMap, rError.nErrorStart ).mnPos;
+ xub_StrLen nEnd = (xub_StrLen)ModelToViewHelper::ConvertToModelPosition( pConversionMap, rError.nErrorStart + rError.nErrorLength ).mnPos;
+ if( i != j )
+ pArray[j] = pArray[i];
+ if( pWrong->LookForEntry( nStart, nEnd ) )
+ ++j;
+ }
+ }
+ if( rResult.aErrors.getLength() > j )
+ rResult.aErrors.realloc( j );
+}
+
+uno::Any SwDoc::Spell( SwPaM& rPaM,
+ uno::Reference< XSpellChecker1 > &xSpeller,
+ sal_uInt16* pPageCnt, sal_uInt16* pPageSt,
+ bool bGrammarCheck,
+ SwConversionArgs *pConvArgs ) const
+{
+ SwPosition* pSttPos = rPaM.Start(), *pEndPos = rPaM.End();
+ uno::Reference< beans::XPropertySet > xProp( ::GetLinguPropertySet() );
+
+ SwSpellArgs *pSpellArgs = 0;
+ //SwConversionArgs *pConvArgs = 0;
+ if (pConvArgs)
+ {
+ pConvArgs->SetStart(pSttPos->nNode.GetNode().GetTxtNode(), pSttPos->nContent);
+ pConvArgs->SetEnd( pEndPos->nNode.GetNode().GetTxtNode(), pEndPos->nContent );
+ }
+ else
+ pSpellArgs = new SwSpellArgs( xSpeller,
+ pSttPos->nNode.GetNode().GetTxtNode(), pSttPos->nContent,
+ pEndPos->nNode.GetNode().GetTxtNode(), pEndPos->nContent,
+ bGrammarCheck );
+
+ sal_uLong nCurrNd = pSttPos->nNode.GetIndex();
+ sal_uLong nEndNd = pEndPos->nNode.GetIndex();
+
+ uno::Any aRet;
+ if( nCurrNd <= nEndNd )
+ {
+ SwCntntFrm* pCntFrm;
+ sal_Bool bGoOn = sal_True;
+ while( bGoOn )
+ {
+ SwNode* pNd = GetNodes()[ nCurrNd ];
+ switch( pNd->GetNodeType() )
+ {
+ case ND_TEXTNODE:
+ if( 0 != ( pCntFrm = ((SwTxtNode*)pNd)->getLayoutFrm( GetCurrentLayout() )) )
+ {
+ // geschutze Cellen/Flys ueberspringen, ausgeblendete
+ //ebenfalls
+ if( pCntFrm->IsProtected() )
+ {
+ nCurrNd = pNd->EndOfSectionIndex();
+ }
+ else if( !((SwTxtFrm*)pCntFrm)->IsHiddenNow() )
+ {
+ if( pPageCnt && *pPageCnt && pPageSt )
+ {
+ sal_uInt16 nPageNr = pCntFrm->GetPhyPageNum();
+ if( !*pPageSt )
+ {
+ *pPageSt = nPageNr;
+ if( *pPageCnt < *pPageSt )
+ *pPageCnt = *pPageSt;
+ }
+ long nStat;
+ if( nPageNr >= *pPageSt )
+ nStat = nPageNr - *pPageSt + 1;
+ else
+ nStat = nPageNr + *pPageCnt - *pPageSt + 1;
+ ::SetProgressState( nStat, (SwDocShell*)GetDocShell() );
+ }
+ //Spell() changes the pSpellArgs in case an error is found
+ xub_StrLen nBeginGrammarCheck = 0;
+ xub_StrLen nEndGrammarCheck = 0;
+ if( pSpellArgs && pSpellArgs->bIsGrammarCheck)
+ {
+ nBeginGrammarCheck = pSpellArgs->pStartNode == pNd ? pSpellArgs->pStartIdx->GetIndex() : 0;
+ // if grammar checking starts inside of a sentence the start position has to be adjusted
+ if( nBeginGrammarCheck )
+ {
+ SwIndex aStartIndex( dynamic_cast< SwTxtNode* >( pNd ), nBeginGrammarCheck );
+ SwPosition aStart( *pNd, aStartIndex );
+ SwCursor aCrsr(aStart, 0, false);
+ SwPosition aOrigPos = *aCrsr.GetPoint();
+ aCrsr.GoSentence( SwCursor::START_SENT );
+ if( aOrigPos != *aCrsr.GetPoint() )
+ {
+ nBeginGrammarCheck = aCrsr.GetPoint()->nContent.GetIndex();
+ }
+ }
+ nEndGrammarCheck = pSpellArgs->pEndNode == pNd ? pSpellArgs->pEndIdx->GetIndex() : ((SwTxtNode*)pNd)->GetTxt().Len();
+ }
+
+ xub_StrLen nSpellErrorPosition = ((SwTxtNode*)pNd)->GetTxt().Len();
+ if( (!pConvArgs &&
+ ((SwTxtNode*)pNd)->Spell( pSpellArgs )) ||
+ ( pConvArgs &&
+ ((SwTxtNode*)pNd)->Convert( *pConvArgs )))
+ {
+ // Abbrechen und Position merken
+ pSttPos->nNode = nCurrNd;
+ pEndPos->nNode = nCurrNd;
+ nCurrNd = nEndNd;
+ if( pSpellArgs )
+ nSpellErrorPosition = pSpellArgs->pStartIdx->GetIndex() > pSpellArgs->pEndIdx->GetIndex() ?
+ pSpellArgs->pEndIdx->GetIndex() :
+ pSpellArgs->pStartIdx->GetIndex();
+ }
+
+
+ if( pSpellArgs && pSpellArgs->bIsGrammarCheck )
+ {
+ uno::Reference< linguistic2::XProofreadingIterator > xGCIterator( GetGCIterator() );
+ if (xGCIterator.is())
+ {
+ String aText( ((SwTxtNode*)pNd)->GetTxt().Copy( nBeginGrammarCheck, nEndGrammarCheck - nBeginGrammarCheck ) );
+ uno::Reference< lang::XComponent > xDoc( ((SwDocShell*)GetDocShell())->GetBaseModel(), uno::UNO_QUERY );
+ // Expand the string:
+ rtl::OUString aExpandText;
+ const ModelToViewHelper::ConversionMap* pConversionMap =
+ ((SwTxtNode*)pNd)->BuildConversionMap( aExpandText );
+ // get XFlatParagraph to use...
+ uno::Reference< text::XFlatParagraph > xFlatPara = new SwXFlatParagraph( *((SwTxtNode*)pNd), aExpandText, pConversionMap );
+
+ // get error position of cursor in XFlatParagraph
+ linguistic2::ProofreadingResult aResult;
+ sal_Int32 nGrammarErrors;
+ do
+ {
+ ModelToViewHelper::ConvertToViewPosition( pConversionMap, nBeginGrammarCheck );
+ aResult = xGCIterator->checkSentenceAtPosition(
+ xDoc, xFlatPara, aExpandText, lang::Locale(), nBeginGrammarCheck, -1, -1 );
+
+ lcl_syncGrammarError( *((SwTxtNode*)pNd), aResult, nBeginGrammarCheck, pConversionMap );
+
+ // get suggestions to use for the specific error position
+ nGrammarErrors = aResult.aErrors.getLength();
+ // if grammar checking doesn't have any progress then quit
+ if( aResult.nStartOfNextSentencePosition <= nBeginGrammarCheck )
+ break;
+ // prepare next iteration
+ nBeginGrammarCheck = (xub_StrLen)aResult.nStartOfNextSentencePosition;
+ }
+ while( nSpellErrorPosition > aResult.nBehindEndOfSentencePosition && !nGrammarErrors && aResult.nBehindEndOfSentencePosition < nEndGrammarCheck );
+
+ if( nGrammarErrors > 0 && nSpellErrorPosition >= aResult.nBehindEndOfSentencePosition )
+ {
+ aRet <<= aResult;
+ //put the cursor to the current error
+ const linguistic2::SingleProofreadingError &rError = aResult.aErrors[0];
+ nCurrNd = pNd->GetIndex();
+ pSttPos->nNode = nCurrNd;
+ pEndPos->nNode = nCurrNd;
+ pSpellArgs->pStartNode = ((SwTxtNode*)pNd);
+ pSpellArgs->pEndNode = ((SwTxtNode*)pNd);
+ pSpellArgs->pStartIdx->Assign(((SwTxtNode*)pNd), (xub_StrLen)ModelToViewHelper::ConvertToModelPosition( pConversionMap, rError.nErrorStart ).mnPos );
+ pSpellArgs->pEndIdx->Assign(((SwTxtNode*)pNd), (xub_StrLen)ModelToViewHelper::ConvertToModelPosition( pConversionMap, rError.nErrorStart + rError.nErrorLength ).mnPos );
+ nCurrNd = nEndNd;
+ }
+ }
+ }
+ }
+ }
+ break;
+ case ND_SECTIONNODE:
+ if( ( ((SwSectionNode*)pNd)->GetSection().IsProtect() ||
+ ((SwSectionNode*)pNd)->GetSection().IsHidden() ) )
+ nCurrNd = pNd->EndOfSectionIndex();
+ break;
+ case ND_ENDNODE:
+ {
+ break;
+ }
+ }
+
+ bGoOn = nCurrNd < nEndNd;
+ ++nCurrNd;
+ }
+ }
+
+ if( !aRet.hasValue() )
+ {
+ if (pConvArgs)
+ aRet <<= pConvArgs->aConvText;
+ else
+ aRet <<= pSpellArgs->xSpellAlt;
+ }
+ delete pSpellArgs;
+
+ return aRet;
+}
+
+class SwHyphArgs : public SwInterHyphInfo
+{
+ const SwNode *pStart;
+ const SwNode *pEnd;
+ SwNode *pNode;
+ sal_uInt16 *pPageCnt;
+ sal_uInt16 *pPageSt;
+
+ sal_uInt32 nNode;
+ xub_StrLen nPamStart;
+ xub_StrLen nPamLen;
+
+public:
+ SwHyphArgs( const SwPaM *pPam, const Point &rPoint,
+ sal_uInt16* pPageCount, sal_uInt16* pPageStart );
+ void SetPam( SwPaM *pPam ) const;
+ inline void SetNode( SwNode *pNew ) { pNode = pNew; }
+ inline const SwNode *GetNode() const { return pNode; }
+ inline void SetRange( const SwNode *pNew );
+ inline void NextNode() { ++nNode; }
+ inline sal_uInt16 *GetPageCnt() { return pPageCnt; }
+ inline sal_uInt16 *GetPageSt() { return pPageSt; }
+};
+
+SwHyphArgs::SwHyphArgs( const SwPaM *pPam, const Point &rCrsrPos,
+ sal_uInt16* pPageCount, sal_uInt16* pPageStart )
+ : SwInterHyphInfo( rCrsrPos ), pNode(0),
+ pPageCnt( pPageCount ), pPageSt( pPageStart )
+{
+ // Folgende Bedingungen muessen eingehalten werden:
+ // 1) es gibt mindestens eine Selektion
+ // 2) SPoint() == Start()
+ OSL_ENSURE( pPam->HasMark(), "SwDoc::Hyphenate: blowing in the wind");
+ OSL_ENSURE( *pPam->GetPoint() <= *pPam->GetMark(),
+ "SwDoc::Hyphenate: New York, New York");
+
+ const SwPosition *pPoint = pPam->GetPoint();
+ nNode = pPoint->nNode.GetIndex();
+
+ // Start einstellen
+ pStart = pPoint->nNode.GetNode().GetTxtNode();
+ nPamStart = pPoint->nContent.GetIndex();
+
+ // Ende und Laenge einstellen.
+ const SwPosition *pMark = pPam->GetMark();
+ pEnd = pMark->nNode.GetNode().GetTxtNode();
+ nPamLen = pMark->nContent.GetIndex();
+ if( pPoint->nNode == pMark->nNode )
+ nPamLen = nPamLen - pPoint->nContent.GetIndex();
+}
+
+inline void SwHyphArgs::SetRange( const SwNode *pNew )
+{
+ nStart = pStart == pNew ? nPamStart : 0;
+ nLen = pEnd == pNew ? nPamLen : STRING_NOTFOUND;
+}
+
+void SwHyphArgs::SetPam( SwPaM *pPam ) const
+{
+ if( !pNode )
+ *pPam->GetPoint() = *pPam->GetMark();
+ else
+ {
+ pPam->GetPoint()->nNode = nNode;
+ pPam->GetPoint()->nContent.Assign( pNode->GetCntntNode(), nWordStart );
+ pPam->GetMark()->nNode = nNode;
+ pPam->GetMark()->nContent.Assign( pNode->GetCntntNode(),
+ nWordStart + nWordLen );
+ OSL_ENSURE( nNode == pNode->GetIndex(),
+ "SwHyphArgs::SetPam: Pam desaster" );
+ }
+}
+
+// liefert sal_True zurueck, wenn es weitergehen soll.
+sal_Bool lcl_HyphenateNode( const SwNodePtr& rpNd, void* pArgs )
+{
+ // Hyphenate liefert sal_True zurueck, wenn eine Trennstelle anliegt
+ // und stellt pPam ein.
+ SwTxtNode *pNode = rpNd->GetTxtNode();
+ SwHyphArgs *pHyphArgs = (SwHyphArgs*)pArgs;
+ if( pNode )
+ {
+ SwCntntFrm* pCntFrm = pNode->getLayoutFrm( pNode->GetDoc()->GetCurrentLayout() );
+ if( pCntFrm && !((SwTxtFrm*)pCntFrm)->IsHiddenNow() )
+ {
+ sal_uInt16 *pPageSt = pHyphArgs->GetPageSt();
+ sal_uInt16 *pPageCnt = pHyphArgs->GetPageCnt();
+ if( pPageCnt && *pPageCnt && pPageSt )
+ {
+ sal_uInt16 nPageNr = pCntFrm->GetPhyPageNum();
+ if( !*pPageSt )
+ {
+ *pPageSt = nPageNr;
+ if( *pPageCnt < *pPageSt )
+ *pPageCnt = *pPageSt;
+ }
+ long nStat = nPageNr >= *pPageSt ? nPageNr - *pPageSt + 1
+ : nPageNr + *pPageCnt - *pPageSt + 1;
+ ::SetProgressState( nStat, (SwDocShell*)pNode->GetDoc()->GetDocShell() );
+ }
+ pHyphArgs->SetRange( rpNd );
+ if( pNode->Hyphenate( *pHyphArgs ) )
+ {
+ pHyphArgs->SetNode( rpNd );
+ return sal_False;
+ }
+ }
+ }
+ pHyphArgs->NextNode();
+ return sal_True;
+}
+
+uno::Reference< XHyphenatedWord > SwDoc::Hyphenate(
+ SwPaM *pPam, const Point &rCrsrPos,
+ sal_uInt16* pPageCnt, sal_uInt16* pPageSt )
+{
+ OSL_ENSURE(this == pPam->GetDoc(), "SwDoc::Hyphenate: strangers in the night");
+
+ if( *pPam->GetPoint() > *pPam->GetMark() )
+ pPam->Exchange();
+
+ SwHyphArgs aHyphArg( pPam, rCrsrPos, pPageCnt, pPageSt );
+ SwNodeIndex aTmpIdx( pPam->GetMark()->nNode, 1 );
+ GetNodes().ForEach( pPam->GetPoint()->nNode, aTmpIdx,
+ lcl_HyphenateNode, &aHyphArg );
+ aHyphArg.SetPam( pPam );
+ return aHyphArg.GetHyphWord(); // will be set by lcl_HyphenateNode
+}
+
+sal_Bool lcl_GetTokenToParaBreak( String& rStr, String& rRet, sal_Bool bRegExpRplc )
+{
+ sal_Bool bRet = sal_False;
+ if( bRegExpRplc )
+ {
+ xub_StrLen nPos = 0;
+ String sPara( String::CreateFromAscii(
+ RTL_CONSTASCII_STRINGPARAM( "\\n" )));
+ while( STRING_NOTFOUND != ( nPos = rStr.Search( sPara, nPos )) )
+ {
+ // wurde das escaped?
+ if( nPos && '\\' == rStr.GetChar( nPos-1 ))
+ {
+ if( ++nPos >= rStr.Len() )
+ break;
+ }
+ else
+ {
+ rRet = rStr.Copy( 0, nPos );
+ rStr.Erase( 0, nPos + sPara.Len() );
+ bRet = sal_True;
+ break;
+ }
+ }
+ }
+ if( !bRet )
+ {
+ rRet = rStr;
+ rStr.Erase();
+ }
+ return bRet;
+}
+
+bool SwDoc::ReplaceRange( SwPaM& rPam, const String& rStr,
+ const bool bRegExReplace )
+{
+ // unfortunately replace works slightly differently from delete,
+ // so we cannot use lcl_DoWithBreaks here...
+
+ ::std::vector<xub_StrLen> Breaks;
+
+ SwPaM aPam( *rPam.GetMark(), *rPam.GetPoint() );
+ aPam.Normalize(sal_False);
+ if (aPam.GetPoint()->nNode != aPam.GetMark()->nNode)
+ {
+ aPam.Move(fnMoveBackward);
+ }
+ OSL_ENSURE((aPam.GetPoint()->nNode == aPam.GetMark()->nNode), "invalid pam?");
+
+ lcl_CalcBreaks(Breaks, aPam);
+
+ while (!Breaks.empty() // skip over prefix of dummy chars
+ && (aPam.GetMark()->nContent.GetIndex() == *Breaks.begin()) )
+ {
+ // skip!
+ ++aPam.GetMark()->nContent; // always in bounds if Breaks valid
+ Breaks.erase(Breaks.begin());
+ }
+ *rPam.Start() = *aPam.GetMark(); // update start of original pam w/ prefix
+
+ if (!Breaks.size())
+ {
+ return ReplaceRangeImpl(rPam, rStr, bRegExReplace); // original pam!
+ }
+
+ // N.B.: deletion must be split into several parts if the text node
+ // contains a text attribute with end and with dummy character
+ // and the selection does not contain the text attribute completely,
+ // but overlaps its start (left), where the dummy character is.
+
+ bool bRet( true );
+ // iterate from end to start, to avoid invalidating the offsets!
+ ::std::vector<xub_StrLen>::reverse_iterator iter( Breaks.rbegin() );
+ OSL_ENSURE(aPam.GetPoint() == aPam.End(), "wrong!");
+ SwPosition & rEnd( *aPam.End() );
+ SwPosition & rStart( *aPam.Start() );
+
+ // set end of temp pam to original end (undo Move backward above)
+ rEnd = *rPam.End();
+ // after first deletion, rEnd will point into the original text node again!
+
+ while (iter != Breaks.rend())
+ {
+ rStart.nContent = *iter + 1;
+ if (rEnd.nContent != rStart.nContent) // check if part is empty
+ {
+ bRet &= (IsRedlineOn())
+ ? DeleteAndJoinWithRedlineImpl(aPam)
+ : DeleteAndJoinImpl(aPam, false);
+ }
+ rEnd.nContent = *iter;
+ ++iter;
+ }
+
+ rStart = *rPam.Start(); // set to original start
+ OSL_ENSURE(rEnd.nContent > rStart.nContent, "replace part empty!");
+ if (rEnd.nContent > rStart.nContent) // check if part is empty
+ {
+ bRet &= ReplaceRangeImpl(aPam, rStr, bRegExReplace);
+ }
+
+ rPam = aPam; // update original pam (is this required?)
+
+ return bRet;
+}
+
+// N.B.: it is possible to call Replace with a PaM that spans 2 paragraphs:
+// search with regex for "$", then replace _all_
+bool SwDoc::ReplaceRangeImpl( SwPaM& rPam, const String& rStr,
+ const bool bRegExReplace )
+{
+ if( !rPam.HasMark() || *rPam.GetPoint() == *rPam.GetMark() )
+ return false;
+
+ sal_Bool bJoinTxt, bJoinPrev;
+ lcl_GetJoinFlags( rPam, bJoinTxt, bJoinPrev );
+
+ {
+ // dann eine Kopie vom Cursor erzeugen um alle Pams aus den
+ // anderen Sichten aus dem Loeschbereich zu verschieben
+ // ABER NICHT SICH SELBST !!
+ SwPaM aDelPam( *rPam.GetMark(), *rPam.GetPoint() );
+ ::PaMCorrAbs( aDelPam, *aDelPam.GetPoint() );
+
+ SwPosition *pStt = (SwPosition*)aDelPam.Start(),
+ *pEnd = (SwPosition*)aDelPam.End();
+ OSL_ENSURE( pStt->nNode == pEnd->nNode ||
+ ( pStt->nNode.GetIndex() + 1 == pEnd->nNode.GetIndex() &&
+ !pEnd->nContent.GetIndex() ),
+ "invalid range: Point and Mark on different nodes" );
+ sal_Bool bOneNode = pStt->nNode == pEnd->nNode;
+
+ // eigenes Undo ????
+ String sRepl( rStr );
+ SwTxtNode* pTxtNd = pStt->nNode.GetNode().GetTxtNode();
+ xub_StrLen nStt = pStt->nContent.GetIndex(),
+ nEnd = bOneNode ? pEnd->nContent.GetIndex()
+ : pTxtNd->GetTxt().Len();
+
+ SwDataChanged aTmp( aDelPam, 0 );
+
+ if( IsRedlineOn() )
+ {
+ RedlineMode_t eOld = GetRedlineMode();
+ checkRedlining(eOld);
+ if (GetIDocumentUndoRedo().DoesUndo())
+ {
+ GetIDocumentUndoRedo().StartUndo(UNDO_EMPTY, NULL);
+
+ // Bug 68584 - if any Redline will change (split!) the node
+ const ::sw::mark::IMark* pBkmk = getIDocumentMarkAccess()->makeMark( aDelPam, ::rtl::OUString(), IDocumentMarkAccess::UNO_BOOKMARK );
+
+ //JP 06.01.98: MUSS noch optimiert werden!!!
+ SetRedlineMode(
+ (RedlineMode_t)(nsRedlineMode_t::REDLINE_ON | nsRedlineMode_t::REDLINE_SHOW_INSERT | nsRedlineMode_t::REDLINE_SHOW_DELETE ));
+
+ *aDelPam.GetPoint() = pBkmk->GetMarkPos();
+ if(pBkmk->IsExpanded())
+ *aDelPam.GetMark() = pBkmk->GetOtherMarkPos();
+ getIDocumentMarkAccess()->deleteMark(pBkmk);
+ pStt = aDelPam.Start();
+ pTxtNd = pStt->nNode.GetNode().GetTxtNode();
+ nStt = pStt->nContent.GetIndex();
+ }
+
+ if( sRepl.Len() )
+ {
+ // Attribute des 1. Zeichens ueber den ReplaceText setzen
+ SfxItemSet aSet( GetAttrPool(),
+ RES_CHRATR_BEGIN, RES_TXTATR_WITHEND_END - 1,
+ RES_UNKNOWNATR_BEGIN, RES_UNKNOWNATR_END-1,
+ 0 );
+ pTxtNd->GetAttr( aSet, nStt+1, nStt+1 );
+
+ aSet.ClearItem( RES_TXTATR_REFMARK );
+ aSet.ClearItem( RES_TXTATR_TOXMARK );
+ aSet.ClearItem( RES_TXTATR_CJK_RUBY );
+ aSet.ClearItem( RES_TXTATR_INETFMT );
+ aSet.ClearItem( RES_TXTATR_META );
+ aSet.ClearItem( RES_TXTATR_METAFIELD );
+
+ if( aDelPam.GetPoint() != aDelPam.End() )
+ aDelPam.Exchange();
+
+ // das Ende merken
+ SwNodeIndex aPtNd( aDelPam.GetPoint()->nNode, -1 );
+ xub_StrLen nPtCnt = aDelPam.GetPoint()->nContent.GetIndex();
+
+ sal_Bool bFirst = sal_True;
+ String sIns;
+ while ( lcl_GetTokenToParaBreak( sRepl, sIns, bRegExReplace ) )
+ {
+ InsertString( aDelPam, sIns );
+ if( bFirst )
+ {
+ SwNodeIndex aMkNd( aDelPam.GetMark()->nNode, -1 );
+ xub_StrLen nMkCnt = aDelPam.GetMark()->nContent.GetIndex();
+
+ SplitNode( *aDelPam.GetPoint(), false );
+
+ aMkNd++;
+ aDelPam.GetMark()->nNode = aMkNd;
+ aDelPam.GetMark()->nContent.Assign(
+ aMkNd.GetNode().GetCntntNode(), nMkCnt );
+ bFirst = sal_False;
+ }
+ else
+ SplitNode( *aDelPam.GetPoint(), false );
+ }
+ if( sIns.Len() )
+ {
+ InsertString( aDelPam, sIns );
+ }
+
+ SwPaM aTmpRange( *aDelPam.GetPoint() );
+ aTmpRange.SetMark();
+
+ aPtNd++;
+ aDelPam.GetPoint()->nNode = aPtNd;
+ aDelPam.GetPoint()->nContent.Assign( aPtNd.GetNode().GetCntntNode(),
+ nPtCnt);
+ *aTmpRange.GetMark() = *aDelPam.GetPoint();
+
+ RstTxtAttrs( aTmpRange );
+ InsertItemSet( aTmpRange, aSet, 0 );
+ }
+
+ if (GetIDocumentUndoRedo().DoesUndo())
+ {
+ SwUndo *const pUndoRD =
+ new SwUndoRedlineDelete( aDelPam, UNDO_REPLACE );
+ GetIDocumentUndoRedo().AppendUndo(pUndoRD);
+ }
+ AppendRedline( new SwRedline( nsRedlineType_t::REDLINE_DELETE, aDelPam ), true);
+
+ *rPam.GetMark() = *aDelPam.GetMark();
+ if (GetIDocumentUndoRedo().DoesUndo())
+ {
+ *aDelPam.GetPoint() = *rPam.GetPoint();
+ GetIDocumentUndoRedo().EndUndo(UNDO_EMPTY, NULL);
+
+ // Bug 68584 - if any Redline will change (split!) the node
+ const ::sw::mark::IMark* pBkmk = getIDocumentMarkAccess()->makeMark( aDelPam, ::rtl::OUString(), IDocumentMarkAccess::UNO_BOOKMARK );
+
+ SwIndex& rIdx = aDelPam.GetPoint()->nContent;
+ rIdx.Assign( 0, 0 );
+ aDelPam.GetMark()->nContent = rIdx;
+ rPam.GetPoint()->nNode = 0;
+ rPam.GetPoint()->nContent = rIdx;
+ *rPam.GetMark() = *rPam.GetPoint();
+//JP 06.01.98: MUSS noch optimiert werden!!!
+SetRedlineMode( eOld );
+
+ *rPam.GetPoint() = pBkmk->GetMarkPos();
+ if(pBkmk->IsExpanded())
+ *rPam.GetMark() = pBkmk->GetOtherMarkPos();
+ getIDocumentMarkAccess()->deleteMark(pBkmk);
+ }
+ bJoinTxt = sal_False;
+ }
+ else
+ {
+ if( !IsIgnoreRedline() && GetRedlineTbl().Count() )
+ DeleteRedline( aDelPam, true, USHRT_MAX );
+
+ SwUndoReplace* pUndoRpl = 0;
+ bool const bDoesUndo = GetIDocumentUndoRedo().DoesUndo();
+ if (bDoesUndo)
+ {
+ pUndoRpl = new SwUndoReplace(aDelPam, sRepl, bRegExReplace);
+ GetIDocumentUndoRedo().AppendUndo(pUndoRpl);
+ }
+ ::sw::UndoGuard const undoGuard(GetIDocumentUndoRedo());
+
+ if( aDelPam.GetPoint() != pStt )
+ aDelPam.Exchange();
+
+ SwNodeIndex aPtNd( pStt->nNode, -1 );
+ xub_StrLen nPtCnt = pStt->nContent.GetIndex();
+
+ // die Werte nochmal setzen, falls schohn Rahmen oder Fussnoten
+ // auf dem Text entfernt wurden!
+ nStt = nPtCnt;
+ nEnd = bOneNode ? pEnd->nContent.GetIndex()
+ : pTxtNd->GetTxt().Len();
+
+ sal_Bool bFirst = sal_True;
+ String sIns;
+ while ( lcl_GetTokenToParaBreak( sRepl, sIns, bRegExReplace ) )
+ {
+ if( !bFirst || nStt == pTxtNd->GetTxt().Len() )
+ {
+ InsertString( aDelPam, sIns );
+ }
+ else if( nStt < nEnd || sIns.Len() )
+ {
+ pTxtNd->ReplaceText( pStt->nContent, nEnd - nStt, sIns );
+ }
+ SplitNode( *pStt, false);
+ bFirst = sal_False;
+ }
+
+ if( bFirst || sIns.Len() )
+ {
+ if( !bFirst || nStt == pTxtNd->GetTxt().Len() )
+ {
+ InsertString( aDelPam, sIns );
+ }
+ else if( nStt < nEnd || sIns.Len() )
+ {
+ pTxtNd->ReplaceText( pStt->nContent, nEnd - nStt, sIns );
+ }
+ }
+
+ *rPam.GetMark() = *aDelPam.GetMark();
+
+ aPtNd++;
+ rPam.GetMark()->nNode = aPtNd;
+ rPam.GetMark()->nContent.Assign( aPtNd.GetNode().GetCntntNode(),
+ nPtCnt );
+ if( bJoinTxt )
+ rPam.Move( fnMoveBackward );
+
+ if( pUndoRpl )
+ {
+ pUndoRpl->SetEnd(rPam);
+ }
+ }
+ }
+
+ if( bJoinTxt )
+ lcl_JoinText( rPam, bJoinPrev );
+
+ SetModified();
+ return true;
+}
+
+// speicher die akt. Werte fuer die automatische Aufnahme von Ausnahmen
+// in die Autokorrektur
+void SwDoc::SetAutoCorrExceptWord( SwAutoCorrExceptWord* pNew )
+{
+ if( pACEWord && pNew != pACEWord )
+ delete pACEWord;
+ pACEWord = pNew;
+}
+
+bool SwDoc::DelFullPara( SwPaM& rPam )
+{
+ const SwPosition &rStt = *rPam.Start(), &rEnd = *rPam.End();
+ const SwNode* pNd = &rStt.nNode.GetNode();
+ sal_uInt32 nSectDiff = pNd->StartOfSectionNode()->EndOfSectionIndex() -
+ pNd->StartOfSectionIndex();
+ sal_uInt32 nNodeDiff = rEnd.nNode.GetIndex() - rStt.nNode.GetIndex();
+
+ if ( nSectDiff-2 <= nNodeDiff || IsRedlineOn() ||
+ /* #i9185# Prevent getting the node after the end node (see below) */
+ rEnd.nNode.GetIndex() + 1 == GetNodes().Count() )
+ {
+ return sal_False;
+ }
+
+ // harte SeitenUmbrueche am nachfolgenden Node verschieben
+ sal_Bool bSavePageBreak = sal_False, bSavePageDesc = sal_False;
+
+ /* #i9185# This whould lead to a segmentation fault if not catched
+ above. */
+ sal_uLong nNextNd = rEnd.nNode.GetIndex() + 1;
+ SwTableNode *const pTblNd = GetNodes()[ nNextNd ]->GetTableNode();
+
+ if( pTblNd && pNd->IsCntntNode() )
+ {
+ SwFrmFmt* pTableFmt = pTblNd->GetTable().GetFrmFmt();
+
+ {
+ const SfxPoolItem *pItem;
+ const SfxItemSet* pSet = ((SwCntntNode*)pNd)->GetpSwAttrSet();
+ if( pSet && SFX_ITEM_SET == pSet->GetItemState( RES_PAGEDESC,
+ sal_False, &pItem ) )
+ {
+ pTableFmt->SetFmtAttr( *pItem );
+ bSavePageDesc = sal_True;
+ }
+
+ if( pSet && SFX_ITEM_SET == pSet->GetItemState( RES_BREAK,
+ sal_False, &pItem ) )
+ {
+ pTableFmt->SetFmtAttr( *pItem );
+ bSavePageBreak = sal_True;
+ }
+ }
+ }
+
+ bool const bDoesUndo = GetIDocumentUndoRedo().DoesUndo();
+ if( bDoesUndo )
+ {
+ if( !rPam.HasMark() )
+ rPam.SetMark();
+ else if( rPam.GetPoint() == &rStt )
+ rPam.Exchange();
+ rPam.GetPoint()->nNode++;
+
+ SwCntntNode *pTmpNode = rPam.GetPoint()->nNode.GetNode().GetCntntNode();
+ rPam.GetPoint()->nContent.Assign( pTmpNode, 0 );
+ bool bGoNext = (0 == pTmpNode);
+ pTmpNode = rPam.GetMark()->nNode.GetNode().GetCntntNode();
+ rPam.GetMark()->nContent.Assign( pTmpNode, 0 );
+
+ GetIDocumentUndoRedo().ClearRedo();
+
+ SwPaM aDelPam( *rPam.GetMark(), *rPam.GetPoint() );
+ {
+ SwPosition aTmpPos( *aDelPam.GetPoint() );
+ if( bGoNext )
+ {
+ pTmpNode = GetNodes().GoNext( &aTmpPos.nNode );
+ aTmpPos.nContent.Assign( pTmpNode, 0 );
+ }
+ ::PaMCorrAbs( aDelPam, aTmpPos );
+ }
+
+ SwUndoDelete* pUndo = new SwUndoDelete( aDelPam, sal_True );
+
+ *rPam.GetPoint() = *aDelPam.GetPoint();
+ pUndo->SetPgBrkFlags( bSavePageBreak, bSavePageDesc );
+ GetIDocumentUndoRedo().AppendUndo(pUndo);
+ }
+ else
+ {
+ SwNodeRange aRg( rStt.nNode, rEnd.nNode );
+ if( rPam.GetPoint() != &rEnd )
+ rPam.Exchange();
+
+ // versuche hinters Ende zu verschieben
+ if( !rPam.Move( fnMoveForward, fnGoNode ) )
+ {
+ // na gut, dann an den Anfang
+ rPam.Exchange();
+ if( !rPam.Move( fnMoveBackward, fnGoNode ))
+ {
+ OSL_FAIL( "kein Node mehr vorhanden" );
+ return sal_False;
+ }
+ }
+ // text::Bookmarks usw. verschieben
+ CorrAbs( aRg.aStart, aRg.aEnd, *rPam.GetPoint(), sal_True );
+
+ // was ist mit Fly's ??
+ {
+ // stehen noch FlyFrames rum, loesche auch diese
+ for( sal_uInt16 n = 0; n < GetSpzFrmFmts()->Count(); ++n )
+ {
+ SwFrmFmt* pFly = (*GetSpzFrmFmts())[n];
+ const SwFmtAnchor* pAnchor = &pFly->GetAnchor();
+ SwPosition const*const pAPos = pAnchor->GetCntntAnchor();
+ if (pAPos &&
+ ((FLY_AT_PARA == pAnchor->GetAnchorId()) ||
+ (FLY_AT_CHAR == pAnchor->GetAnchorId())) &&
+ aRg.aStart <= pAPos->nNode && pAPos->nNode <= aRg.aEnd )
+ {
+ DelLayoutFmt( pFly );
+ --n;
+ }
+ }
+ }
+
+ SwCntntNode *pTmpNode = rPam.GetBound( sal_True ).nNode.GetNode().GetCntntNode();
+ rPam.GetBound( sal_True ).nContent.Assign( pTmpNode, 0 );
+ pTmpNode = rPam.GetBound( sal_False ).nNode.GetNode().GetCntntNode();
+ rPam.GetBound( sal_False ).nContent.Assign( pTmpNode, 0 );
+ GetNodes().Delete( aRg.aStart, nNodeDiff+1 );
+ }
+ rPam.DeleteMark();
+ SetModified();
+
+ return sal_True;
+}
+
+void SwDoc::TransliterateText(
+ const SwPaM& rPaM,
+ utl::TransliterationWrapper& rTrans )
+{
+ SwUndoTransliterate *const pUndo = (GetIDocumentUndoRedo().DoesUndo())
+ ? new SwUndoTransliterate( rPaM, rTrans )
+ : 0;
+
+ const SwPosition* pStt = rPaM.Start(),
+ * pEnd = rPaM.End();
+ sal_uLong nSttNd = pStt->nNode.GetIndex(),
+ nEndNd = pEnd->nNode.GetIndex();
+ xub_StrLen nSttCnt = pStt->nContent.GetIndex(),
+ nEndCnt = pEnd->nContent.GetIndex();
+
+ SwTxtNode* pTNd = pStt->nNode.GetNode().GetTxtNode();
+ if( pStt == pEnd && pTNd ) // no selection?
+ {
+ // set current word as 'area of effect'
+
+ Boundary aBndry;
+ if( pBreakIt->GetBreakIter().is() )
+ aBndry = pBreakIt->GetBreakIter()->getWordBoundary(
+ pTNd->GetTxt(), nSttCnt,
+ pBreakIt->GetLocale( pTNd->GetLang( nSttCnt ) ),
+ WordType::ANY_WORD /*ANYWORD_IGNOREWHITESPACES*/,
+ sal_True );
+
+ if( aBndry.startPos < nSttCnt && nSttCnt < aBndry.endPos )
+ {
+ nSttCnt = (xub_StrLen)aBndry.startPos;
+ nEndCnt = (xub_StrLen)aBndry.endPos;
+ }
+ }
+
+ if( nSttNd != nEndNd ) // is more than one text node involved?
+ {
+ // iterate over all effected text nodes, the first and the last one
+ // may be incomplete because the selection starts and/or ends there
+
+ SwNodeIndex aIdx( pStt->nNode );
+ if( nSttCnt )
+ {
+ aIdx++;
+ if( pTNd )
+ pTNd->TransliterateText( rTrans, nSttCnt, pTNd->GetTxt().Len(), pUndo );
+ }
+
+ for( ; aIdx.GetIndex() < nEndNd; aIdx++ )
+ {
+ if( 0 != ( pTNd = aIdx.GetNode().GetTxtNode() ))
+ pTNd->TransliterateText( rTrans, 0, pTNd->GetTxt().Len(), pUndo );
+ }
+
+ if( nEndCnt && 0 != ( pTNd = pEnd->nNode.GetNode().GetTxtNode() ))
+ pTNd->TransliterateText( rTrans, 0, nEndCnt, pUndo );
+ }
+ else if( pTNd && nSttCnt < nEndCnt )
+ pTNd->TransliterateText( rTrans, nSttCnt, nEndCnt, pUndo );
+
+ if( pUndo )
+ {
+ if( pUndo->HasData() )
+ {
+ GetIDocumentUndoRedo().AppendUndo(pUndo);
+ }
+ else
+ delete pUndo;
+ }
+ SetModified();
+}
+
+#define MAX_REDLINE_COUNT 250
+
+void SwDoc::checkRedlining(RedlineMode_t& _rReadlineMode)
+{
+ const SwRedlineTbl& rRedlineTbl = GetRedlineTbl();
+ SwEditShell* pEditShell = GetEditShell();
+ Window* pParent = pEditShell ? pEditShell->GetWin() : NULL;
+ if ( pParent && !mbReadlineChecked && rRedlineTbl.Count() > MAX_REDLINE_COUNT
+ && !((_rReadlineMode & nsRedlineMode_t::REDLINE_SHOW_DELETE) == nsRedlineMode_t::REDLINE_SHOW_DELETE) )
+ {
+ WarningBox aWarning( pParent,SW_RES(MSG_DISABLE_READLINE_QUESTION));
+ sal_uInt16 nResult = aWarning.Execute();
+ mbReadlineChecked = sal_True;
+ if ( nResult == RET_YES )
+ {
+ sal_Int32 nMode = (sal_Int32)_rReadlineMode;
+ nMode |= nsRedlineMode_t::REDLINE_SHOW_INSERT | nsRedlineMode_t::REDLINE_SHOW_DELETE;
+ _rReadlineMode = (RedlineMode_t)nMode;
+ }
+ }
+}
+
+void SwDoc::CountWords( const SwPaM& rPaM, SwDocStat& rStat ) const
+{
+ // This is a modified version of SwDoc::TransliterateText
+ const SwPosition* pStt = rPaM.Start();
+ const SwPosition* pEnd = pStt == rPaM.GetPoint() ? rPaM.GetMark()
+ : rPaM.GetPoint();
+
+ const sal_uLong nSttNd = pStt->nNode.GetIndex();
+ const sal_uLong nEndNd = pEnd->nNode.GetIndex();
+
+ const xub_StrLen nSttCnt = pStt->nContent.GetIndex();
+ const xub_StrLen nEndCnt = pEnd->nContent.GetIndex();
+
+ const SwTxtNode* pTNd = pStt->nNode.GetNode().GetTxtNode();
+ if( pStt == pEnd && pTNd ) // no region ?
+ {
+ // do nothing
+ return;
+ }
+
+ if( nSttNd != nEndNd )
+ {
+ SwNodeIndex aIdx( pStt->nNode );
+ if( nSttCnt )
+ {
+ aIdx++;
+ if( pTNd )
+ pTNd->CountWords( rStat, nSttCnt, pTNd->GetTxt().Len() );
+ }
+
+ for( ; aIdx.GetIndex() < nEndNd; aIdx++ )
+ if( 0 != ( pTNd = aIdx.GetNode().GetTxtNode() ))
+ pTNd->CountWords( rStat, 0, pTNd->GetTxt().Len() );
+
+ if( nEndCnt && 0 != ( pTNd = pEnd->nNode.GetNode().GetTxtNode() ))
+ pTNd->CountWords( rStat, 0, nEndCnt );
+ }
+ else if( pTNd && nSttCnt < nEndCnt )
+ pTNd->CountWords( rStat, nSttCnt, nEndCnt );
+}
+
+void SwDoc::RemoveLeadingWhiteSpace(const SwPosition & rPos )
+{
+ const SwTxtNode* pTNd = rPos.nNode.GetNode().GetTxtNode();
+ if ( pTNd )
+ {
+ const String& rTxt = pTNd->GetTxt();
+ xub_StrLen nIdx = 0;
+ sal_Unicode cCh;
+ while( nIdx < rTxt.Len() &&
+ ( '\t' == ( cCh = rTxt.GetChar( nIdx ) ) ||
+ ( ' ' == cCh ) ) )
+ ++nIdx;
+
+ if ( nIdx > 0 )
+ {
+ SwPaM aPam(rPos);
+ aPam.GetPoint()->nContent = 0;
+ aPam.SetMark();
+ aPam.GetMark()->nContent = nIdx;
+ DeleteRange( aPam );
+ }
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/doc/docfld.cxx b/sw/source/core/doc/docfld.cxx
new file mode 100644
index 000000000000..16e5a7680da7
--- /dev/null
+++ b/sw/source/core/doc/docfld.cxx
@@ -0,0 +1,2703 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+
+#include <hintids.hxx>
+
+#include <string.h>
+#include <float.h>
+#include <tools/datetime.hxx>
+#ifndef _SVSTDARR_HXX
+#define _SVSTDARR_ULONGS
+#include <svl/svarray.hxx>
+#endif
+#include <vcl/svapp.hxx>
+#include <unotools/charclass.hxx>
+#include <unotools/transliterationwrapper.hxx>
+#include <doc.hxx>
+#include <IDocumentUndoRedo.hxx>
+#include <cntfrm.hxx>
+#include <pam.hxx>
+#include <ndtxt.hxx>
+#include <swtable.hxx>
+#include <calc.hxx>
+#include <txtfld.hxx>
+#include <fmtfld.hxx>
+#include <tox.hxx>
+#include <txttxmrk.hxx>
+#include <docfld.hxx> // fuer Expression-Felder
+#include <docufld.hxx>
+#include <ddefld.hxx>
+#include <usrfld.hxx>
+#include <expfld.hxx>
+#include <dbfld.hxx>
+#include <flddat.hxx>
+#include <chpfld.hxx>
+#include <reffld.hxx>
+#include <flddropdown.hxx>
+#include <dbmgr.hxx>
+#include <section.hxx>
+#include <cellatr.hxx>
+#include <docary.hxx>
+#include <authfld.hxx>
+#include <txtinet.hxx>
+#include <fmtcntnt.hxx>
+#include <poolfmt.hrc> // fuer InitFldTypes
+
+#include <SwUndoField.hxx>
+#include "switerator.hxx"
+
+using namespace ::com::sun::star::uno;
+
+extern sal_Bool IsFrameBehind( const SwTxtNode& rMyNd, sal_uInt16 nMySttPos,
+ const SwTxtNode& rBehindNd, sal_uInt16 nSttPos );
+
+SV_IMPL_OP_PTRARR_SORT( _SetGetExpFlds, _SetGetExpFldPtr )
+
+/*--------------------------------------------------------------------
+ Beschreibung: Feldtypen einfuegen
+ --------------------------------------------------------------------*/
+/*
+ * Implementierung der Feldfunktionen am Doc
+ * Return immer einen gueltigen Pointer auf den Typ. Wenn er also neu
+ * zugefuegt oder schon vorhanden ist.
+ */
+SwFieldType* SwDoc::InsertFldType(const SwFieldType &rFldTyp)
+{
+ sal_uInt16 nSize = pFldTypes->Count(),
+ nFldWhich = rFldTyp.Which();
+
+ sal_uInt16 i = INIT_FLDTYPES;
+
+ switch( nFldWhich )
+ {
+ case RES_SETEXPFLD:
+ //JP 29.01.96: SequenceFelder beginnen aber bei INIT_FLDTYPES - 3!!
+ // Sonst gibt es doppelte Nummernkreise!!
+ //MIB 14.03.95: Ab sofort verlaesst sich auch der SW3-Reader
+ //beim Aufbau der String-Pools und beim Einlesen von SetExp-Feldern
+ //hierauf
+ if( nsSwGetSetExpType::GSE_SEQ & ((SwSetExpFieldType&)rFldTyp).GetType() )
+ i -= INIT_SEQ_FLDTYPES;
+ // kein break;
+ case RES_DBFLD:
+ case RES_USERFLD:
+ case RES_DDEFLD:
+ {
+ const ::utl::TransliterationWrapper& rSCmp = GetAppCmpStrIgnore();
+ String sFldNm( rFldTyp.GetName() );
+ for( ; i < nSize; ++i )
+ if( nFldWhich == (*pFldTypes)[i]->Which() &&
+ rSCmp.isEqual( sFldNm, (*pFldTypes)[i]->GetName() ))
+ return (*pFldTypes)[i];
+ }
+ break;
+
+ case RES_AUTHORITY:
+ for( ; i < nSize; ++i )
+ if( nFldWhich == (*pFldTypes)[i]->Which() )
+ return (*pFldTypes)[i];
+ break;
+
+ default:
+ for( i = 0; i < nSize; ++i )
+ if( nFldWhich == (*pFldTypes)[i]->Which() )
+ return (*pFldTypes)[i];
+ }
+
+ SwFieldType* pNew = rFldTyp.Copy();
+ switch( nFldWhich )
+ {
+ case RES_DDEFLD:
+ ((SwDDEFieldType*)pNew)->SetDoc( this );
+ break;
+
+ case RES_DBFLD:
+ case RES_TABLEFLD:
+ case RES_DATETIMEFLD:
+ case RES_GETEXPFLD:
+ ((SwValueFieldType*)pNew)->SetDoc( this );
+ break;
+
+ case RES_USERFLD:
+ case RES_SETEXPFLD:
+ ((SwValueFieldType*)pNew)->SetDoc( this );
+ // JP 29.07.96: opt. FeldListe fuer den Calculator vorbereiten:
+ pUpdtFlds->InsertFldType( *pNew );
+ break;
+ case RES_AUTHORITY :
+ ((SwAuthorityFieldType*)pNew)->SetDoc( this );
+ break;
+ }
+
+ pFldTypes->Insert( pNew, nSize );
+ SetModified();
+
+ return (*pFldTypes)[ nSize ];
+}
+
+void SwDoc::InsDeletedFldType( SwFieldType& rFldTyp )
+{
+ // der FeldTyp wurde als geloescht gekennzeichnet und aus dem
+ // Array entfernt. Nun muss man nach diesem wieder suchen.
+ // - Ist der nicht vorhanden, dann kann er eingefuegt werden.
+ // - Wird genau der gleiche Typ gefunden, dann muss der geloeschte
+ // einen anderen Namen erhalten.
+
+ sal_uInt16 nSize = pFldTypes->Count(), nFldWhich = rFldTyp.Which();
+ sal_uInt16 i = INIT_FLDTYPES;
+
+ OSL_ENSURE( RES_SETEXPFLD == nFldWhich ||
+ RES_USERFLD == nFldWhich ||
+ RES_DDEFLD == nFldWhich, "Falscher FeldTyp" );
+
+ const ::utl::TransliterationWrapper& rSCmp = GetAppCmpStrIgnore();
+ const String& rFldNm = rFldTyp.GetName();
+ SwFieldType* pFnd;
+
+ for( ; i < nSize; ++i )
+ if( nFldWhich == (pFnd = (*pFldTypes)[i])->Which() &&
+ rSCmp.isEqual( rFldNm, pFnd->GetName() ) )
+ {
+ // neuen Namen suchen
+ sal_uInt16 nNum = 1;
+ do {
+ String sSrch( rFldNm );
+ sSrch.Append( String::CreateFromInt32( nNum ));
+ for( i = INIT_FLDTYPES; i < nSize; ++i )
+ if( nFldWhich == (pFnd = (*pFldTypes)[i])->Which() &&
+ rSCmp.isEqual( sSrch, pFnd->GetName() ) )
+ break;
+
+ if( i >= nSize ) // nicht gefunden
+ {
+ ((String&)rFldNm) = sSrch;
+ break; // raus aus der While-Schleife
+ }
+ ++nNum;
+ } while( sal_True );
+ break;
+ }
+
+ // nicht gefunden, also eintragen und Flag loeschen
+ pFldTypes->Insert( &rFldTyp, nSize );
+ switch( nFldWhich )
+ {
+ case RES_SETEXPFLD:
+ ((SwSetExpFieldType&)rFldTyp).SetDeleted( sal_False );
+ break;
+ case RES_USERFLD:
+ ((SwUserFieldType&)rFldTyp).SetDeleted( sal_False );
+ break;
+ case RES_DDEFLD:
+ ((SwDDEFieldType&)rFldTyp).SetDeleted( sal_False );
+ break;
+ }
+}
+
+/*--------------------------------------------------------------------
+ Beschreibung: Feldtypen loeschen
+ --------------------------------------------------------------------*/
+void SwDoc::RemoveFldType(sal_uInt16 nFld)
+{
+ OSL_ENSURE( INIT_FLDTYPES <= nFld, "keine InitFields loeschen" );
+ /*
+ * Abheangige Felder vorhanden -> ErrRaise
+ */
+ sal_uInt16 nSize = pFldTypes->Count();
+ if(nFld < nSize)
+ {
+ SwFieldType* pTmp = (*pFldTypes)[nFld];
+
+ // JP 29.07.96: opt. FeldListe fuer den Calculator vorbereiten:
+ sal_uInt16 nWhich = pTmp->Which();
+ switch( nWhich )
+ {
+ case RES_SETEXPFLD:
+ case RES_USERFLD:
+ pUpdtFlds->RemoveFldType( *pTmp );
+ // kein break;
+ case RES_DDEFLD:
+ if( pTmp->GetDepends() && !IsUsed( *pTmp ) )
+ {
+ if( RES_SETEXPFLD == nWhich )
+ ((SwSetExpFieldType*)pTmp)->SetDeleted( sal_True );
+ else if( RES_USERFLD == nWhich )
+ ((SwUserFieldType*)pTmp)->SetDeleted( sal_True );
+ else
+ ((SwDDEFieldType*)pTmp)->SetDeleted( sal_True );
+ nWhich = 0;
+ }
+ break;
+ }
+
+ if( nWhich )
+ {
+ OSL_ENSURE( !pTmp->GetDepends(), "Abhaengige vorh.!" );
+ // Feldtype loschen
+ delete pTmp;
+ }
+ pFldTypes->Remove( nFld );
+ SetModified();
+ }
+}
+
+const SwFldTypes* SwDoc::GetFldTypes() const
+{
+ return pFldTypes;
+}
+
+/*--------------------------------------------------------------------
+ Beschreibung: Den ersten Typen mit ResId und Namen finden
+ --------------------------------------------------------------------*/
+SwFieldType* SwDoc::GetFldType( sal_uInt16 nResId, const String& rName,
+ bool bDbFieldMatching // used in some UNO calls for RES_DBFLD
+ // to use different string matching code
+ // #i51815#
+ ) const
+{
+ sal_uInt16 nSize = pFldTypes->Count(), i = 0;
+ const ::utl::TransliterationWrapper& rSCmp = GetAppCmpStrIgnore();
+
+ switch( nResId )
+ {
+ case RES_SETEXPFLD:
+ //JP 29.01.96: SequenceFelder beginnen aber bei INIT_FLDTYPES - 3!!
+ // Sonst gibt es doppelte Nummernkreise!!
+ //MIB 14.03.95: Ab sofort verlaesst sich auch der SW3-Reader
+ //beim Aufbau der String-Pools und beim Einlesen von SetExp-Feldern
+ //hierauf
+ i = INIT_FLDTYPES - INIT_SEQ_FLDTYPES;
+ break;
+
+ case RES_DBFLD:
+ case RES_USERFLD:
+ case RES_DDEFLD:
+ case RES_AUTHORITY:
+ i = INIT_FLDTYPES;
+ break;
+ }
+
+ SwFieldType* pRet = 0;
+ for( ; i < nSize; ++i )
+ {
+ SwFieldType* pFldType = (*pFldTypes)[i];
+
+ String aFldName( pFldType->GetName() );
+ if (bDbFieldMatching && nResId == RES_DBFLD) // #i51815#
+ aFldName.SearchAndReplaceAll(DB_DELIM, '.');
+
+ if( nResId == pFldType->Which() &&
+ rSCmp.isEqual( rName, aFldName ))
+ {
+ pRet = pFldType;
+ break;
+ }
+ }
+ return pRet;
+}
+
+/*************************************************************************
+|* SwDoc::UpdateFlds()
+|* Beschreibung Felder updaten
+*************************************************************************/
+/*
+ * Alle sollen neu evaluiert werden.
+ */
+void SwDoc::UpdateFlds( SfxPoolItem *pNewHt, bool bCloseDB )
+{
+ // Modify() fuer jeden Feldtypen rufen,
+ // abhaengige SwTxtFld werden benachrichtigt ...
+
+ for( sal_uInt16 i=0; i < pFldTypes->Count(); ++i)
+ {
+ switch( (*pFldTypes)[i]->Which() )
+ {
+ // Tabellen-Felder als vorletztes Updaten
+ // Referenzen als letztes Updaten
+ case RES_GETREFFLD:
+ case RES_TABLEFLD:
+ case RES_DBFLD:
+ case RES_JUMPEDITFLD:
+ case RES_REFPAGESETFLD: // werden nie expandiert!
+ break;
+
+ case RES_DDEFLD:
+ {
+ if( !pNewHt )
+ {
+ SwMsgPoolItem aUpdateDDE( RES_UPDATEDDETBL );
+ (*pFldTypes)[i]->ModifyNotification( 0, &aUpdateDDE );
+ }
+ else
+ (*pFldTypes)[i]->ModifyNotification( 0, pNewHt );
+ break;
+ }
+ case RES_GETEXPFLD:
+ case RES_SETEXPFLD:
+ case RES_HIDDENTXTFLD:
+ case RES_HIDDENPARAFLD:
+ // Expression-Felder werden gesondert behandelt
+ if( !pNewHt )
+ break;
+ default:
+ (*pFldTypes)[i]->ModifyNotification ( 0, pNewHt );
+ }
+ }
+
+ if( !IsExpFldsLocked() )
+ UpdateExpFlds( 0, sal_False ); // Expression-Felder Updaten
+
+ // Tabellen
+ UpdateTblFlds(pNewHt);
+
+ // Referenzen
+ UpdateRefFlds(pNewHt);
+
+ if( bCloseDB )
+ GetNewDBMgr()->CloseAll();
+
+ // Nur bei KomplettUpdate evaluieren
+ SetModified();
+}
+
+/******************************************************************************
+ * void SwDoc::UpdateUsrFlds()
+ ******************************************************************************/
+void SwDoc::UpdateUsrFlds()
+{
+ SwCalc* pCalc = 0;
+ const SwFieldType* pFldType;
+ for( sal_uInt16 i = INIT_FLDTYPES; i < pFldTypes->Count(); ++i )
+ if( RES_USERFLD == ( pFldType = (*pFldTypes)[i] )->Which() )
+ {
+ if( !pCalc )
+ pCalc = new SwCalc( *this );
+ ((SwUserFieldType*)pFldType)->GetValue( *pCalc );
+ }
+
+ if( pCalc )
+ {
+ delete pCalc;
+ SetModified();
+ }
+}
+
+/*--------------------------------------------------------------------
+ Beschreibung: Referenzfelder und TableFelder erneuern
+ --------------------------------------------------------------------*/
+void SwDoc::UpdateRefFlds( SfxPoolItem* pHt )
+{
+ SwFieldType* pFldType;
+ for( sal_uInt16 i = 0; i < pFldTypes->Count(); ++i )
+ if( RES_GETREFFLD == ( pFldType = (*pFldTypes)[i] )->Which() )
+ pFldType->ModifyNotification( 0, pHt );
+}
+
+void SwDoc::UpdateTblFlds( SfxPoolItem* pHt )
+{
+ OSL_ENSURE( !pHt || RES_TABLEFML_UPDATE == pHt->Which(),
+ "Was ist das fuer ein MessageItem?" );
+
+ SwFieldType* pFldType(0);
+
+ for (sal_uInt16 i = 0; i < pFldTypes->Count(); ++i)
+ {
+ if( RES_TABLEFLD == ( pFldType = (*pFldTypes)[i] )->Which() )
+ {
+ SwTableFmlUpdate* pUpdtFld = 0;
+ if( pHt && RES_TABLEFML_UPDATE == pHt->Which() )
+ pUpdtFld = (SwTableFmlUpdate*)pHt;
+
+ SwIterator<SwFmtFld,SwFieldType> aIter( *pFldType );
+ for( SwFmtFld* pFmtFld = aIter.First(); pFmtFld; pFmtFld = aIter.Next() )
+ {
+ if( pFmtFld->GetTxtFld() )
+ {
+ SwTblField* pFld = (SwTblField*)pFmtFld->GetFld();
+
+ if( pUpdtFld )
+ {
+ // bestimme Tabelle, in der das Feld steht
+ const SwTableNode* pTblNd;
+ const SwTxtNode& rTxtNd = pFmtFld->GetTxtFld()->GetTxtNode();
+ if( !rTxtNd.GetNodes().IsDocNodes() ||
+ 0 == ( pTblNd = rTxtNd.FindTableNode() ) )
+ continue;
+
+ switch( pUpdtFld->eFlags )
+ {
+ case TBL_CALC:
+ // setze das Value-Flag zurueck
+ // JP 17.06.96: interne Darstellung auf alle Formeln
+ // (Referenzen auf andere Tabellen!!!)
+ if( nsSwExtendedSubType::SUB_CMD & pFld->GetSubType() )
+ pFld->PtrToBoxNm( pUpdtFld->pTbl );
+ else
+ pFld->ChgValid( sal_False );
+ break;
+ case TBL_BOXNAME:
+ // ist es die gesuchte Tabelle ??
+ if( &pTblNd->GetTable() == pUpdtFld->pTbl )
+ // zur externen Darstellung
+ pFld->PtrToBoxNm( pUpdtFld->pTbl );
+ break;
+ case TBL_BOXPTR:
+ // zur internen Darstellung
+ // JP 17.06.96: interne Darstellung auf alle Formeln
+ // (Referenzen auf andere Tabellen!!!)
+ pFld->BoxNmToPtr( pUpdtFld->pTbl );
+ break;
+ case TBL_RELBOXNAME:
+ // ist es die gesuchte Tabelle ??
+ if( &pTblNd->GetTable() == pUpdtFld->pTbl )
+ // zur relativen Darstellung
+ pFld->ToRelBoxNm( pUpdtFld->pTbl );
+ break;
+ default:
+ break;
+ }
+ }
+ else
+ // setze bei allen das Value-Flag zurueck
+ pFld->ChgValid( sal_False );
+ }
+ }
+
+ break;
+ }
+ pFldType = 0;
+ }
+
+ // und dann noch alle Tabellen Box Formeln abklappern
+ const SfxPoolItem* pItem;
+ sal_uInt32 nMaxItems = GetAttrPool().GetItemCount2( RES_BOXATR_FORMULA );
+ for (sal_uInt32 i = 0; i < nMaxItems; ++i)
+ {
+ if( 0 != (pItem = GetAttrPool().GetItem2( RES_BOXATR_FORMULA, i ) ) &&
+ ((SwTblBoxFormula*)pItem)->GetDefinedIn() )
+ {
+ ((SwTblBoxFormula*)pItem)->ChangeState( pHt );
+ }
+ }
+
+
+ // alle Felder/Boxen sind jetzt invalide, also kann das Rechnen anfangen
+ if( pHt && ( RES_TABLEFML_UPDATE != pHt->Which() ||
+ TBL_CALC != ((SwTableFmlUpdate*)pHt)->eFlags ))
+ return ;
+
+ SwCalc* pCalc = 0;
+
+ if( pFldType )
+ {
+ SwIterator<SwFmtFld,SwFieldType> aIter( *pFldType );
+ for( SwFmtFld* pFmtFld = aIter.Last(); pFmtFld; pFmtFld = aIter.Previous() )
+ {
+ // start calculation at the end
+ // new fields are inserted at the beginning of the modify chain
+ // that gives faster calculation on import
+ // mba: do we really need this "optimization"? Is it still valid?
+ SwTblField* pFld;
+ if( !pFmtFld->GetTxtFld() || (nsSwExtendedSubType::SUB_CMD &
+ (pFld = (SwTblField*)pFmtFld->GetFld())->GetSubType() ))
+ continue;
+
+ // muss neu berechnet werden (und ist keine textuelle Anzeige)
+ if( !pFld->IsValid() )
+ {
+ // bestimme Tabelle, in der das Feld steht
+ const SwTxtNode& rTxtNd = pFmtFld->GetTxtFld()->GetTxtNode();
+ if( !rTxtNd.GetNodes().IsDocNodes() )
+ continue;
+ const SwTableNode* pTblNd = rTxtNd.FindTableNode();
+ if( !pTblNd )
+ continue;
+
+ // falls dieses Feld nicht in der zu updatenden
+ // Tabelle steht, ueberspringen !!
+ if( pHt && &pTblNd->GetTable() !=
+ ((SwTableFmlUpdate*)pHt)->pTbl )
+ continue;
+
+ if( !pCalc )
+ pCalc = new SwCalc( *this );
+
+ // bestimme die Werte aller SetExpresion Felder, die
+ // bis zur Tabelle gueltig sind
+ SwFrm* pFrm = 0;
+ if( pTblNd->GetIndex() < GetNodes().GetEndOfExtras().GetIndex() )
+ {
+ // steht im Sonderbereich, wird teuer !!
+ Point aPt; // den im Layout 1. Frame returnen - Tab.Kopfzeile !!
+ pFrm = rTxtNd.getLayoutFrm( GetCurrentLayout(), &aPt );
+ if( pFrm )
+ {
+ SwPosition aPos( *pTblNd );
+ if( GetBodyTxtNode( *this, aPos, *pFrm ) )
+ FldsToCalc( *pCalc, _SetGetExpFld(
+ aPos.nNode, pFmtFld->GetTxtFld(),
+ &aPos.nContent ));
+ else
+ pFrm = 0;
+ }
+ }
+ if( !pFrm )
+ {
+ // einen Index fuers bestimmen vom TextNode anlegen
+ SwNodeIndex aIdx( rTxtNd );
+ FldsToCalc( *pCalc,
+ _SetGetExpFld( aIdx, pFmtFld->GetTxtFld() ));
+ }
+
+ SwTblCalcPara aPara( *pCalc, pTblNd->GetTable() );
+ pFld->CalcField( aPara );
+ if( aPara.IsStackOverFlow() )
+ {
+ if( aPara.CalcWithStackOverflow() )
+ pFld->CalcField( aPara );
+#if OSL_DEBUG_LEVEL > 1
+ else
+ {
+ // mind. ein ASSERT
+ OSL_ENSURE( !this, "die Kettenformel konnte nicht errechnet werden" );
+ }
+#endif
+ }
+ pCalc->SetCalcError( CALC_NOERR );
+ }
+ pFmtFld->ModifyNotification( 0, pHt );
+ }
+ }
+
+ // dann berechene noch die Formeln an den Boxen
+ for (sal_uInt32 i = 0; i < nMaxItems; ++i )
+ {
+ if( 0 != (pItem = GetAttrPool().GetItem2( RES_BOXATR_FORMULA, i ) ) &&
+ ((SwTblBoxFormula*)pItem)->GetDefinedIn() &&
+ !((SwTblBoxFormula*)pItem)->IsValid() )
+ {
+ SwTblBoxFormula* pFml = (SwTblBoxFormula*)pItem;
+ SwTableBox* pBox = pFml->GetTableBox();
+ if( pBox && pBox->GetSttNd() &&
+ pBox->GetSttNd()->GetNodes().IsDocNodes() )
+ {
+ const SwTableNode* pTblNd = pBox->GetSttNd()->FindTableNode();
+ if( !pHt || &pTblNd->GetTable() ==
+ ((SwTableFmlUpdate*)pHt)->pTbl )
+ {
+ double nValue;
+ if( !pCalc )
+ pCalc = new SwCalc( *this );
+
+ // bestimme die Werte aller SetExpresion Felder, die
+ // bis zur Tabelle gueltig sind
+ SwFrm* pFrm = 0;
+ if( pTblNd->GetIndex() < GetNodes().GetEndOfExtras().GetIndex() )
+ {
+ // steht im Sonderbereich, wird teuer !!
+ Point aPt; // den im Layout 1. Frame returnen - Tab.Kopfzeile !!
+ SwNodeIndex aCNdIdx( *pTblNd, +2 );
+ SwCntntNode* pCNd = aCNdIdx.GetNode().GetCntntNode();
+ if( !pCNd )
+ pCNd = GetNodes().GoNext( &aCNdIdx );
+
+ if( pCNd && 0 != (pFrm = pCNd->getLayoutFrm( GetCurrentLayout(), &aPt )) )
+ {
+ SwPosition aPos( *pCNd );
+ if( GetBodyTxtNode( *this, aPos, *pFrm ) )
+ FldsToCalc( *pCalc, _SetGetExpFld( aPos.nNode ));
+ else
+ pFrm = 0;
+ }
+ }
+ if( !pFrm )
+ {
+ // einen Index fuers bestimmen vom TextNode anlegen
+ SwNodeIndex aIdx( *pTblNd );
+ FldsToCalc( *pCalc, _SetGetExpFld( aIdx ));
+ }
+
+ SwTblCalcPara aPara( *pCalc, pTblNd->GetTable() );
+ pFml->Calc( aPara, nValue );
+
+ if( aPara.IsStackOverFlow() )
+ {
+ if( aPara.CalcWithStackOverflow() )
+ pFml->Calc( aPara, nValue );
+#if OSL_DEBUG_LEVEL > 1
+ else
+ {
+ // mind. ein ASSERT
+ OSL_ENSURE( !this, "die Kettenformel konnte nicht errechnet werden" );
+ }
+#endif
+ }
+
+ SwFrmFmt* pFmt = pBox->ClaimFrmFmt();
+ SfxItemSet aTmp( GetAttrPool(),
+ RES_BOXATR_BEGIN,RES_BOXATR_END-1 );
+
+ if( pCalc->IsCalcError() )
+ nValue = DBL_MAX;
+ aTmp.Put( SwTblBoxValue( nValue ));
+ if( SFX_ITEM_SET != pFmt->GetItemState( RES_BOXATR_FORMAT ))
+ aTmp.Put( SwTblBoxNumFormat( 0 ));
+ pFmt->SetFmtAttr( aTmp );
+
+ pCalc->SetCalcError( CALC_NOERR );
+ }
+ }
+ }
+ }
+
+ if( pCalc )
+ delete pCalc;
+}
+
+void SwDoc::UpdatePageFlds( SfxPoolItem* pMsgHnt )
+{
+ SwFieldType* pFldType;
+ for( sal_uInt16 i = 0; i < INIT_FLDTYPES; ++i )
+ switch( ( pFldType = (*pFldTypes)[ i ] )->Which() )
+ {
+ case RES_PAGENUMBERFLD:
+ case RES_CHAPTERFLD:
+ case RES_GETEXPFLD:
+ case RES_REFPAGEGETFLD:
+ pFldType->ModifyNotification( 0, pMsgHnt );
+ break;
+ case RES_DOCSTATFLD:
+ pFldType->ModifyNotification( 0, 0 );
+ break;
+ }
+ SetNewFldLst(true);
+}
+
+// ---- Loesche alle nicht referenzierten FeldTypen eines Dokumentes --
+void SwDoc::GCFieldTypes()
+{
+ for( sal_uInt16 n = pFldTypes->Count(); n > INIT_FLDTYPES; )
+ if( !(*pFldTypes)[ --n ]->GetDepends() )
+ RemoveFldType( n );
+}
+
+void SwDoc::LockExpFlds()
+{
+ ++nLockExpFld;
+}
+
+void SwDoc::UnlockExpFlds()
+{
+ if( nLockExpFld )
+ --nLockExpFld;
+}
+
+bool SwDoc::IsExpFldsLocked() const
+{
+ return 0 != nLockExpFld;
+}
+
+SwDocUpdtFld& SwDoc::GetUpdtFlds() const
+{
+ return *pUpdtFlds;
+}
+
+bool SwDoc::IsNewFldLst() const
+{
+ return mbNewFldLst;
+}
+
+void SwDoc::SetNewFldLst(bool bFlag)
+{
+ mbNewFldLst = bFlag;
+}
+
+// der StartIndex kann optional mit angegeben werden (z.B. wenn dieser
+// zuvor schon mal erfragt wurde - ist sonst eine virtuelle Methode !!)
+_SetGetExpFld::_SetGetExpFld( const SwNodeIndex& rNdIdx, const SwTxtFld* pFld,
+ const SwIndex* pIdx )
+{
+ eSetGetExpFldType = TEXTFIELD;
+ CNTNT.pTxtFld = pFld;
+ nNode = rNdIdx.GetIndex();
+ if( pIdx )
+ nCntnt = pIdx->GetIndex();
+ else if( pFld )
+ nCntnt = *pFld->GetStart();
+ else
+ nCntnt = 0;
+}
+
+_SetGetExpFld::_SetGetExpFld( const SwNodeIndex& rNdIdx,
+ const SwTxtINetFmt& rINet, const SwIndex* pIdx )
+{
+ eSetGetExpFldType = TEXTINET;
+ CNTNT.pTxtINet = &rINet;
+ nNode = rNdIdx.GetIndex();
+ if( pIdx )
+ nCntnt = pIdx->GetIndex();
+ else
+ nCntnt = *rINet.GetStart();
+}
+
+// Erweiterung fuer Sections:
+// diese haben immer als Content-Position 0xffff !!
+// Auf dieser steht nie ein Feld, maximal bis STRING_MAXLEN moeglich
+_SetGetExpFld::_SetGetExpFld( const SwSectionNode& rSectNd,
+ const SwPosition* pPos )
+{
+ eSetGetExpFldType = SECTIONNODE;
+ CNTNT.pSection = &rSectNd.GetSection();
+
+ if( pPos )
+ {
+ nNode = pPos->nNode.GetIndex();
+ nCntnt = pPos->nContent.GetIndex();
+ }
+ else
+ {
+ nNode = rSectNd.GetIndex();
+ nCntnt = 0;
+ }
+}
+
+_SetGetExpFld::_SetGetExpFld( const SwTableBox& rTBox, const SwPosition* pPos )
+{
+ eSetGetExpFldType = TABLEBOX;
+ CNTNT.pTBox = &rTBox;
+
+ if( pPos )
+ {
+ nNode = pPos->nNode.GetIndex();
+ nCntnt = pPos->nContent.GetIndex();
+ }
+ else
+ {
+ nNode = 0;
+ nCntnt = 0;
+ if( rTBox.GetSttNd() )
+ {
+ SwNodeIndex aIdx( *rTBox.GetSttNd() );
+ const SwCntntNode* pNd = aIdx.GetNode().GetNodes().GoNext( &aIdx );
+ if( pNd )
+ nNode = pNd->GetIndex();
+ }
+ }
+}
+
+_SetGetExpFld::_SetGetExpFld( const SwNodeIndex& rNdIdx,
+ const SwTxtTOXMark& rTOX,
+ const SwIndex* pIdx )
+{
+ eSetGetExpFldType = TEXTTOXMARK;
+ CNTNT.pTxtTOX = &rTOX;
+ nNode = rNdIdx.GetIndex();
+ if( pIdx )
+ nCntnt = pIdx->GetIndex();
+ else
+ nCntnt = *rTOX.GetStart();
+}
+
+_SetGetExpFld::_SetGetExpFld( const SwPosition& rPos )
+{
+ eSetGetExpFldType = CRSRPOS;
+ CNTNT.pPos = &rPos;
+ nNode = rPos.nNode.GetIndex();
+ nCntnt = rPos.nContent.GetIndex();
+}
+
+_SetGetExpFld::_SetGetExpFld( const SwFlyFrmFmt& rFlyFmt,
+ const SwPosition* pPos )
+{
+ eSetGetExpFldType = FLYFRAME;
+ CNTNT.pFlyFmt = &rFlyFmt;
+ if( pPos )
+ {
+ nNode = pPos->nNode.GetIndex();
+ nCntnt = pPos->nContent.GetIndex();
+ }
+ else
+ {
+ const SwFmtCntnt& rCntnt = rFlyFmt.GetCntnt();
+ nNode = rCntnt.GetCntntIdx()->GetIndex() + 1;
+ nCntnt = 0;
+ }
+}
+
+void _SetGetExpFld::GetPos( SwPosition& rPos ) const
+{
+ rPos.nNode = nNode;
+ rPos.nContent.Assign( rPos.nNode.GetNode().GetCntntNode(), nCntnt );
+}
+
+void _SetGetExpFld::GetPosOfContent( SwPosition& rPos ) const
+{
+ const SwNode* pNd = GetNodeFromCntnt();
+ if( pNd )
+ pNd = pNd->GetCntntNode();
+
+ if( pNd )
+ {
+ rPos.nNode = *pNd;
+ rPos.nContent.Assign( (SwCntntNode*)pNd,GetCntPosFromCntnt() );
+ }
+ else
+ {
+ rPos.nNode = nNode;
+ rPos.nContent.Assign( rPos.nNode.GetNode().GetCntntNode(), nCntnt );
+ }
+}
+
+void _SetGetExpFld::SetBodyPos( const SwCntntFrm& rFrm )
+{
+ if( !rFrm.IsInDocBody() )
+ {
+ SwNodeIndex aIdx( *rFrm.GetNode() );
+ SwDoc& rDoc = *aIdx.GetNodes().GetDoc();
+ SwPosition aPos( aIdx );
+#if OSL_DEBUG_LEVEL > 1
+ OSL_ENSURE( ::GetBodyTxtNode( rDoc, aPos, rFrm ), "wo steht das Feld" );
+#else
+ ::GetBodyTxtNode( rDoc, aPos, rFrm );
+#endif
+ nNode = aPos.nNode.GetIndex();
+ nCntnt = aPos.nContent.GetIndex();
+ }
+}
+
+sal_Bool _SetGetExpFld::operator<( const _SetGetExpFld& rFld ) const
+{
+ if( nNode < rFld.nNode || ( nNode == rFld.nNode && nCntnt < rFld.nCntnt ))
+ return sal_True;
+ else if( nNode != rFld.nNode || nCntnt != rFld.nCntnt )
+ return sal_False;
+
+ const SwNode *pFirst = GetNodeFromCntnt(),
+ *pNext = rFld.GetNodeFromCntnt();
+
+ // Position gleich: nur weiter wenn beide FeldPointer besetzt sind !!
+ if( !pFirst || !pNext )
+ return sal_False;
+
+ // gleiche Section ??
+ if( pFirst->StartOfSectionNode() != pNext->StartOfSectionNode() )
+ {
+ // sollte einer in der Tabelle stehen ?
+ const SwNode *pFirstStt, *pNextStt;
+ const SwTableNode* pTblNd = pFirst->FindTableNode();
+ if( pTblNd )
+ pFirstStt = pTblNd->StartOfSectionNode();
+ else
+ pFirstStt = pFirst->StartOfSectionNode();
+
+ if( 0 != ( pTblNd = pNext->FindTableNode() ) )
+ pNextStt = pTblNd->StartOfSectionNode();
+ else
+ pNextStt = pNext->StartOfSectionNode();
+
+ if( pFirstStt != pNextStt )
+ {
+ if( pFirst->IsTxtNode() && pNext->IsTxtNode() &&
+ ( pFirst->FindFlyStartNode() || pNext->FindFlyStartNode() ))
+ {
+ return ::IsFrameBehind( *(SwTxtNode*)pNext, nCntnt,
+ *(SwTxtNode*)pFirst, nCntnt );
+ }
+ return pFirstStt->GetIndex() < pNextStt->GetIndex();
+ }
+ }
+
+ // ist gleiche Section, dann Feld im gleichen Node ?
+ if( pFirst != pNext )
+ return pFirst->GetIndex() < pNext->GetIndex();
+
+ // gleicher Node in der Section, dann Position im Node
+ return GetCntPosFromCntnt() < rFld.GetCntPosFromCntnt();
+}
+
+const SwNode* _SetGetExpFld::GetNodeFromCntnt() const
+{
+ const SwNode* pRet = 0;
+ if( CNTNT.pTxtFld )
+ switch( eSetGetExpFldType )
+ {
+ case TEXTFIELD:
+ pRet = &CNTNT.pTxtFld->GetTxtNode();
+ break;
+
+ case TEXTINET:
+ pRet = &CNTNT.pTxtINet->GetTxtNode();
+ break;
+
+ case SECTIONNODE:
+ pRet = CNTNT.pSection->GetFmt()->GetSectionNode();
+ break;
+
+ case CRSRPOS:
+ pRet = &CNTNT.pPos->nNode.GetNode();
+ break;
+
+ case TEXTTOXMARK:
+ pRet = &CNTNT.pTxtTOX->GetTxtNode();
+ break;
+
+ case TABLEBOX:
+ if( CNTNT.pTBox->GetSttNd() )
+ {
+ SwNodeIndex aIdx( *CNTNT.pTBox->GetSttNd() );
+ pRet = aIdx.GetNode().GetNodes().GoNext( &aIdx );
+ }
+ break;
+
+ case FLYFRAME:
+ {
+ SwNodeIndex aIdx( *CNTNT.pFlyFmt->GetCntnt().GetCntntIdx() );
+ pRet = aIdx.GetNode().GetNodes().GoNext( &aIdx );
+ }
+ break;
+ }
+ return pRet;
+}
+
+xub_StrLen _SetGetExpFld::GetCntPosFromCntnt() const
+{
+ sal_uInt16 nRet = 0;
+ if( CNTNT.pTxtFld )
+ switch( eSetGetExpFldType )
+ {
+ case TEXTFIELD:
+ case TEXTINET:
+ case TEXTTOXMARK:
+ nRet = *CNTNT.pTxtFld->GetStart();
+ break;
+ case CRSRPOS:
+ nRet = CNTNT.pPos->nContent.GetIndex();
+ break;
+ default:
+ break;
+ }
+ return nRet;
+}
+
+_HashStr::_HashStr( const String& rName, const String& rText,
+ _HashStr* pNxt )
+ : SwHash( rName ), aSetStr( rText )
+{
+ pNext = pNxt;
+}
+
+// suche nach dem Namen, ist er vorhanden, returne seinen String, sonst
+// einen LeerString
+void LookString( SwHash** ppTbl, sal_uInt16 nSize, const String& rName,
+ String& rRet, sal_uInt16* pPos )
+{
+ rRet = rName;
+ rRet.EraseLeadingChars().EraseTrailingChars();
+ SwHash* pFnd = Find( rRet, ppTbl, nSize, pPos );
+ if( pFnd )
+ rRet = ((_HashStr*)pFnd)->aSetStr;
+ else
+ rRet.Erase();
+}
+
+String lcl_GetDBVarName( SwDoc& rDoc, SwDBNameInfField& rDBFld )
+{
+ SwDBData aDBData( rDBFld.GetDBData( &rDoc ));
+ String sDBNumNm;
+ SwDBData aDocData = rDoc.GetDBData();
+
+ if( aDBData != aDocData )
+ {
+ sDBNumNm = aDBData.sDataSource;
+ sDBNumNm += DB_DELIM;
+ sDBNumNm += String(aDBData.sCommand);
+ sDBNumNm += DB_DELIM;
+ }
+ sDBNumNm += SwFieldType::GetTypeStr(TYP_DBSETNUMBERFLD);
+
+ return sDBNumNm;
+}
+
+void lcl_CalcFld( SwDoc& rDoc, SwCalc& rCalc, const _SetGetExpFld& rSGEFld,
+ SwNewDBMgr* pMgr )
+{
+ const SwTxtFld* pTxtFld = rSGEFld.GetFld();
+ if( !pTxtFld )
+ return ;
+
+ const SwField* pFld = pTxtFld->GetFld().GetFld();
+ const sal_uInt16 nFldWhich = pFld->GetTyp()->Which();
+
+ if( RES_SETEXPFLD == nFldWhich )
+ {
+ SwSbxValue aValue;
+ if( nsSwGetSetExpType::GSE_EXPR & pFld->GetSubType() )
+ aValue.PutDouble( ((SwSetExpField*)pFld)->GetValue() );
+ else
+ // Erweiterung fuers Rechnen mit Strings
+ aValue.PutString( ((SwSetExpField*)pFld)->GetExpStr() );
+
+ // setze im Calculator den neuen Wert
+ rCalc.VarChange( pFld->GetTyp()->GetName(), aValue );
+ }
+ else if( pMgr )
+ {
+ switch( nFldWhich )
+ {
+ case RES_DBNUMSETFLD:
+ {
+ SwDBNumSetField* pDBFld = (SwDBNumSetField*)pFld;
+
+ SwDBData aDBData(pDBFld->GetDBData(&rDoc));
+
+ if( pDBFld->IsCondValid() &&
+ pMgr->OpenDataSource( aDBData.sDataSource, aDBData.sCommand ))
+ rCalc.VarChange( lcl_GetDBVarName( rDoc, *pDBFld),
+ pDBFld->GetFormat() );
+ }
+ break;
+ case RES_DBNEXTSETFLD:
+ {
+ SwDBNextSetField* pDBFld = (SwDBNextSetField*)pFld;
+ SwDBData aDBData(pDBFld->GetDBData(&rDoc));
+ if( !pDBFld->IsCondValid() ||
+ !pMgr->OpenDataSource( aDBData.sDataSource, aDBData.sCommand ))
+ break;
+
+ String sDBNumNm(lcl_GetDBVarName( rDoc, *pDBFld));
+ SwCalcExp* pExp = rCalc.VarLook( sDBNumNm );
+ if( pExp )
+ rCalc.VarChange( sDBNumNm, pExp->nValue.GetLong() + 1 );
+ }
+ break;
+
+ }
+ }
+}
+
+void SwDoc::FldsToCalc( SwCalc& rCalc, const _SetGetExpFld& rToThisFld )
+{
+ // erzeuge die Sortierteliste aller SetFelder
+ pUpdtFlds->MakeFldList( *this, mbNewFldLst, GETFLD_CALC );
+ mbNewFldLst = sal_False;
+
+ SwNewDBMgr* pMgr = GetNewDBMgr();
+ pMgr->CloseAll(sal_False);
+
+ if( pUpdtFlds->GetSortLst()->Count() )
+ {
+ sal_uInt16 nLast;
+ _SetGetExpFld* pFld = (_SetGetExpFld*)&rToThisFld;
+ if( pUpdtFlds->GetSortLst()->Seek_Entry( pFld, &nLast ) )
+ ++nLast;
+
+ const _SetGetExpFldPtr* ppSortLst = pUpdtFlds->GetSortLst()->GetData();
+ for( sal_uInt16 n = 0; n < nLast; ++n, ++ppSortLst )
+ lcl_CalcFld( *this, rCalc, **ppSortLst, pMgr );
+ }
+
+ pMgr->CloseAll(sal_False);
+}
+
+void SwDoc::FldsToCalc( SwCalc& rCalc, sal_uLong nLastNd, sal_uInt16 nLastCnt )
+{
+ // erzeuge die Sortierteliste aller SetFelder
+ pUpdtFlds->MakeFldList( *this, mbNewFldLst, GETFLD_CALC );
+ mbNewFldLst = sal_False;
+
+ SwNewDBMgr* pMgr = GetNewDBMgr();
+ pMgr->CloseAll(sal_False);
+
+ const _SetGetExpFldPtr* ppSortLst = pUpdtFlds->GetSortLst()->GetData();
+
+ for( sal_uInt16 n = pUpdtFlds->GetSortLst()->Count();
+ n &&
+ ( (*ppSortLst)->GetNode() < nLastNd ||
+ ( (*ppSortLst)->GetNode() == nLastNd && (*ppSortLst)->GetCntnt() <= nLastCnt )
+ );
+ --n, ++ppSortLst )
+ lcl_CalcFld( *this, rCalc, **ppSortLst, pMgr );
+
+ pMgr->CloseAll(sal_False);
+}
+
+void SwDoc::FldsToExpand( SwHash**& ppHashTbl, sal_uInt16& rTblSize,
+ const _SetGetExpFld& rToThisFld )
+{
+ // erzeuge die Sortierteliste aller SetFelder
+ pUpdtFlds->MakeFldList( *this, mbNewFldLst, GETFLD_EXPAND );
+ mbNewFldLst = sal_False;
+
+ // HashTabelle fuer alle String Ersetzungen, wird "one the fly" gefuellt
+ // (versuche eine "ungerade"-Zahl zu erzeugen)
+ rTblSize = (( pUpdtFlds->GetSortLst()->Count() / 7 ) + 1 ) * 7;
+ ppHashTbl = new SwHash*[ rTblSize ];
+ memset( ppHashTbl, 0, sizeof( _HashStr* ) * rTblSize );
+
+ sal_uInt16 nLast;
+ {
+ _SetGetExpFld* pTmp = (_SetGetExpFld*)&rToThisFld;
+ if( pUpdtFlds->GetSortLst()->Seek_Entry( pTmp, &nLast ) )
+ ++nLast;
+ }
+
+ sal_uInt16 nPos;
+ SwHash* pFnd;
+ String aNew;
+ const _SetGetExpFldPtr* ppSortLst = pUpdtFlds->GetSortLst()->GetData();
+ for( ; nLast; --nLast, ++ppSortLst )
+ {
+ const SwTxtFld* pTxtFld = (*ppSortLst)->GetFld();
+ if( !pTxtFld )
+ continue;
+
+ const SwField* pFld = pTxtFld->GetFld().GetFld();
+ switch( pFld->GetTyp()->Which() )
+ {
+ case RES_SETEXPFLD:
+ if( nsSwGetSetExpType::GSE_STRING & pFld->GetSubType() )
+ {
+ // setze in der HashTabelle den neuen Wert
+ // ist die "Formel" ein Feld ??
+ SwSetExpField* pSFld = (SwSetExpField*)pFld;
+ LookString( ppHashTbl, rTblSize, pSFld->GetFormula(), aNew );
+
+ if( !aNew.Len() ) // nichts gefunden, dann ist
+ aNew = pSFld->GetFormula(); // die Formel der neue Wert
+
+ // #i3141# - update expression of field as in method
+ // <SwDoc::UpdateExpFlds(..)> for string/text fields
+ pSFld->ChgExpStr( aNew );
+
+ // suche den Namen vom Feld
+ aNew = ((SwSetExpFieldType*)pSFld->GetTyp())->GetSetRefName();
+ // Eintrag vorhanden ?
+ pFnd = Find( aNew, ppHashTbl, rTblSize, &nPos );
+ if( pFnd )
+ // Eintrag in der HashTabelle aendern
+ ((_HashStr*)pFnd)->aSetStr = pSFld->GetExpStr();
+ else
+ // neuen Eintrag einfuegen
+ *(ppHashTbl + nPos ) = new _HashStr( aNew,
+ pSFld->GetExpStr(), (_HashStr*)*(ppHashTbl + nPos) );
+ }
+ break;
+ case RES_DBFLD:
+ {
+ const String& rName = pFld->GetTyp()->GetName();
+
+ // Eintrag in den HashTable eintragen
+ // Eintrag vorhanden ?
+ pFnd = Find( rName, ppHashTbl, rTblSize, &nPos );
+ String const value(pFld->ExpandField(IsClipBoard()));
+ if( pFnd )
+ {
+ // Eintrag in der HashTabelle aendern
+ static_cast<_HashStr*>(pFnd)->aSetStr = value;
+ }
+ else
+ {
+ // neuen Eintrag einfuegen
+ *(ppHashTbl + nPos ) = new _HashStr( rName,
+ value, static_cast<_HashStr *>(*(ppHashTbl + nPos)));
+ }
+ }
+ break;
+ }
+ }
+}
+
+void SwDoc::UpdateExpFlds( SwTxtFld* pUpdtFld, bool bUpdRefFlds )
+{
+ if( IsExpFldsLocked() || IsInReading() )
+ return;
+
+ sal_Bool bOldInUpdateFlds = pUpdtFlds->IsInUpdateFlds();
+ pUpdtFlds->SetInUpdateFlds( sal_True );
+
+ pUpdtFlds->MakeFldList( *this, sal_True, GETFLD_ALL );
+ mbNewFldLst = sal_False;
+
+ if( !pUpdtFlds->GetSortLst()->Count() )
+ {
+ if( bUpdRefFlds )
+ UpdateRefFlds(NULL);
+
+ pUpdtFlds->SetInUpdateFlds( bOldInUpdateFlds );
+ pUpdtFlds->SetFieldsDirty( sal_False );
+ return ;
+ }
+
+ sal_uInt16 nWhich, n;
+
+ // HashTabelle fuer alle String Ersetzungen, wird "one the fly" gefuellt
+ // (versuche eine "ungerade"-Zahl zu erzeugen)
+ sal_uInt16 nStrFmtCnt = (( pFldTypes->Count() / 7 ) + 1 ) * 7;
+ SwHash** pHashStrTbl = new SwHash*[ nStrFmtCnt ];
+ memset( pHashStrTbl, 0, sizeof( _HashStr* ) * nStrFmtCnt );
+
+ {
+ const SwFieldType* pFldType;
+ // gesondert behandeln:
+ for( n = pFldTypes->Count(); n; )
+ switch( ( pFldType = (*pFldTypes)[ --n ] )->Which() )
+ {
+ case RES_USERFLD:
+ {
+ // Eintrag vorhanden ?
+ sal_uInt16 nPos;
+ const String& rNm = pFldType->GetName();
+ String sExpand(((SwUserFieldType*)pFldType)->Expand(nsSwGetSetExpType::GSE_STRING, 0, 0));
+ SwHash* pFnd = Find( rNm, pHashStrTbl, nStrFmtCnt, &nPos );
+ if( pFnd )
+ // Eintrag in der HashTabelle aendern ??
+ ((_HashStr*)pFnd)->aSetStr = sExpand;
+ else
+ // neuen Eintrag einfuegen
+ *(pHashStrTbl + nPos ) = new _HashStr( rNm, sExpand,
+ (_HashStr*)*(pHashStrTbl + nPos) );
+ }
+ break;
+ case RES_SETEXPFLD:
+ ((SwSetExpFieldType*)pFldType)->SetOutlineChgNd( 0 );
+ break;
+ }
+ }
+
+ // Ok, das Array ist soweit mit allen Feldern gefuellt, dann rechne mal
+ SwCalc aCalc( *this );
+
+ String sDBNumNm( SwFieldType::GetTypeStr( TYP_DBSETNUMBERFLD ) );
+
+ // aktuelle Datensatznummer schon vorher einstellen
+ SwNewDBMgr* pMgr = GetNewDBMgr();
+ pMgr->CloseAll(sal_False);
+
+ String aNew;
+ const _SetGetExpFldPtr* ppSortLst = pUpdtFlds->GetSortLst()->GetData();
+ for( n = pUpdtFlds->GetSortLst()->Count(); n; --n, ++ppSortLst )
+ {
+ SwSection* pSect = (SwSection*)(*ppSortLst)->GetSection();
+ if( pSect )
+ {
+
+ SwSbxValue aValue = aCalc.Calculate(
+ pSect->GetCondition() );
+ if(!aValue.IsVoidValue())
+ pSect->SetCondHidden( aValue.GetBool() );
+ continue;
+ }
+
+ SwTxtFld* pTxtFld = (SwTxtFld*)(*ppSortLst)->GetFld();
+ if( !pTxtFld )
+ {
+ OSL_ENSURE( !this, "was ist es denn nun" );
+ continue;
+ }
+
+ SwFmtFld* pFmtFld = (SwFmtFld*)&pTxtFld->GetFld();
+ SwField* pFld = pFmtFld->GetFld();
+
+ switch( nWhich = pFld->GetTyp()->Which() )
+ {
+ case RES_HIDDENTXTFLD:
+ {
+ SwHiddenTxtField* pHFld = (SwHiddenTxtField*)pFld;
+ SwSbxValue aValue = aCalc.Calculate( pHFld->GetPar1() );
+ sal_Bool bValue = !aValue.GetBool();
+ if(!aValue.IsVoidValue())
+ {
+ pHFld->SetValue( bValue );
+ // Feld Evaluieren
+ pHFld->Evaluate(this);
+ }
+ }
+ break;
+ case RES_HIDDENPARAFLD:
+ {
+ SwHiddenParaField* pHPFld = (SwHiddenParaField*)pFld;
+ SwSbxValue aValue = aCalc.Calculate( pHPFld->GetPar1() );
+ sal_Bool bValue = aValue.GetBool();
+ if(!aValue.IsVoidValue())
+ pHPFld->SetHidden( bValue );
+ }
+ break;
+ case RES_DBSETNUMBERFLD:
+ {
+ ((SwDBSetNumberField*)pFld)->Evaluate(this);
+ aCalc.VarChange( sDBNumNm, ((SwDBSetNumberField*)pFld)->GetSetNumber());
+ }
+ break;
+ case RES_DBNEXTSETFLD:
+ case RES_DBNUMSETFLD:
+ UpdateDBNumFlds( *(SwDBNameInfField*)pFld, aCalc );
+ break;
+ case RES_DBFLD:
+ {
+ // Feld Evaluieren
+ ((SwDBField*)pFld)->Evaluate();
+
+ SwDBData aTmpDBData(((SwDBField*)pFld)->GetDBData());
+
+ if( pMgr->IsDataSourceOpen(aTmpDBData.sDataSource, aTmpDBData.sCommand, sal_False))
+ aCalc.VarChange( sDBNumNm, pMgr->GetSelectedRecordId(aTmpDBData.sDataSource, aTmpDBData.sCommand, aTmpDBData.nCommandType));
+
+ const String& rName = pFld->GetTyp()->GetName();
+
+ // Wert fuer den Calculator setzen
+//JP 10.02.96: GetValue macht hier doch keinen Sinn
+// ((SwDBField*)pFld)->GetValue();
+
+//!OK aCalc.VarChange(aName, ((SwDBField*)pFld)->GetValue(aCalc));
+
+ // Eintrag in den HashTable eintragen
+ // Eintrag vorhanden ?
+ sal_uInt16 nPos;
+ SwHash* pFnd = Find( rName, pHashStrTbl, nStrFmtCnt, &nPos );
+ String const value(pFld->ExpandField(IsClipBoard()));
+ if( pFnd )
+ {
+ // Eintrag in der HashTabelle aendern
+ static_cast<_HashStr*>(pFnd)->aSetStr = value;
+ }
+ else
+ {
+ // neuen Eintrag einfuegen
+ *(pHashStrTbl + nPos ) = new _HashStr( rName,
+ value, static_cast<_HashStr *>(*(pHashStrTbl + nPos)));
+ }
+ }
+ break;
+ case RES_GETEXPFLD:
+ case RES_SETEXPFLD:
+ {
+ if( nsSwGetSetExpType::GSE_STRING & pFld->GetSubType() ) // String Ersetzung
+ {
+ if( RES_GETEXPFLD == nWhich )
+ {
+ SwGetExpField* pGFld = (SwGetExpField*)pFld;
+
+ if( (!pUpdtFld || pUpdtFld == pTxtFld )
+ && pGFld->IsInBodyTxt() )
+ {
+ LookString( pHashStrTbl, nStrFmtCnt,
+ pGFld->GetFormula(), aNew );
+ pGFld->ChgExpStr( aNew );
+ }
+ }
+ else
+ {
+ SwSetExpField* pSFld = (SwSetExpField*)pFld;
+ // ist die "Formel" ein Feld ??
+ LookString( pHashStrTbl, nStrFmtCnt,
+ pSFld->GetFormula(), aNew );
+
+ if( !aNew.Len() ) // nichts gefunden, dann ist die
+ aNew = pSFld->GetFormula(); // Formel der neue Wert
+
+ // nur ein spezielles FeldUpdaten ?
+ if( !pUpdtFld || pUpdtFld == pTxtFld )
+ pSFld->ChgExpStr( aNew );
+
+ // suche den Namen vom Feld
+ aNew = ((SwSetExpFieldType*)pSFld->GetTyp())->GetSetRefName();
+ // Eintrag vorhanden ?
+ sal_uInt16 nPos;
+ SwHash* pFnd = Find( aNew, pHashStrTbl, nStrFmtCnt, &nPos );
+ if( pFnd )
+ // Eintrag in der HashTabelle aendern
+ ((_HashStr*)pFnd)->aSetStr = pSFld->GetExpStr();
+ else
+ // neuen Eintrag einfuegen
+ *(pHashStrTbl + nPos ) = pFnd = new _HashStr( aNew,
+ pSFld->GetExpStr(),
+ (_HashStr*)*(pHashStrTbl + nPos) );
+
+ // Erweiterung fuers Rechnen mit Strings
+ SwSbxValue aValue;
+ aValue.PutString( ((_HashStr*)pFnd)->aSetStr );
+ aCalc.VarChange( aNew, aValue );
+ }
+ }
+ else // Formel neu berechnen
+ {
+ if( RES_GETEXPFLD == nWhich )
+ {
+ SwGetExpField* pGFld = (SwGetExpField*)pFld;
+
+ if( (!pUpdtFld || pUpdtFld == pTxtFld )
+ && pGFld->IsInBodyTxt() )
+ {
+ SwSbxValue aValue = aCalc.Calculate(
+ pGFld->GetFormula());
+ if(!aValue.IsVoidValue())
+ pGFld->SetValue(aValue.GetDouble() );
+ }
+ }
+ else
+ {
+ SwSetExpField* pSFld = (SwSetExpField*)pFld;
+ SwSetExpFieldType* pSFldTyp = (SwSetExpFieldType*)pFld->GetTyp();
+ aNew = pSFldTyp->GetName();
+
+ SwNode* pSeqNd = 0;
+
+ if( pSFld->IsSequenceFld() )
+ {
+ const sal_uInt8 nLvl = pSFldTyp->GetOutlineLvl();
+ if( MAXLEVEL > nLvl )
+ {
+ // dann teste, ob die Nummer neu aufsetzen muss
+ pSeqNd = GetNodes()[ (*ppSortLst)->GetNode() ];
+
+ const SwTxtNode* pOutlNd = pSeqNd->
+ FindOutlineNodeOfLevel( nLvl );
+ if( pSFldTyp->GetOutlineChgNd() != pOutlNd )
+ {
+ pSFldTyp->SetOutlineChgNd( pOutlNd );
+ aCalc.VarChange( aNew, 0 );
+ }
+ }
+ }
+
+ aNew += '=';
+ aNew += pSFld->GetFormula();
+
+ SwSbxValue aValue = aCalc.Calculate( aNew );
+ double nErg = aValue.GetDouble();
+ // nur ein spezielles Feld updaten ?
+ if( !aValue.IsVoidValue() && (!pUpdtFld || pUpdtFld == pTxtFld) )
+ {
+ pSFld->SetValue( nErg );
+
+ if( pSeqNd )
+ pSFldTyp->SetChapter( *pSFld, *pSeqNd );
+ }
+ }
+ }
+ }
+ } // switch
+
+ pFmtFld->ModifyNotification( 0, 0 ); // Formatierung anstossen
+
+ if( pUpdtFld == pTxtFld ) // sollte nur dieses geupdatet werden
+ {
+ if( RES_GETEXPFLD == nWhich || // nur GetFeld oder
+ RES_HIDDENTXTFLD == nWhich || // HiddenTxt?
+ RES_HIDDENPARAFLD == nWhich) // HiddenParaFld?
+ break; // beenden
+ pUpdtFld = 0; // ab jetzt alle Updaten
+ }
+ }
+
+ pMgr->CloseAll(sal_False);
+ // HashTabelle wieder loeschen
+ ::DeleteHashTable( pHashStrTbl, nStrFmtCnt );
+
+ // Referenzfelder updaten
+ if( bUpdRefFlds )
+ UpdateRefFlds(NULL);
+
+ pUpdtFlds->SetInUpdateFlds( bOldInUpdateFlds );
+ pUpdtFlds->SetFieldsDirty( sal_False );
+}
+
+void SwDoc::UpdateDBNumFlds( SwDBNameInfField& rDBFld, SwCalc& rCalc )
+{
+ SwNewDBMgr* pMgr = GetNewDBMgr();
+
+ sal_uInt16 nFldType = rDBFld.Which();
+
+ sal_Bool bPar1 = rCalc.Calculate( rDBFld.GetPar1() ).GetBool();
+
+ if( RES_DBNEXTSETFLD == nFldType )
+ ((SwDBNextSetField&)rDBFld).SetCondValid( bPar1 );
+ else
+ ((SwDBNumSetField&)rDBFld).SetCondValid( bPar1 );
+
+ if( rDBFld.GetRealDBData().sDataSource.getLength() )
+ {
+ // Eine bestimmte Datenbank bearbeiten
+ if( RES_DBNEXTSETFLD == nFldType )
+ ((SwDBNextSetField&)rDBFld).Evaluate(this);
+ else
+ ((SwDBNumSetField&)rDBFld).Evaluate(this);
+
+ SwDBData aTmpDBData( rDBFld.GetDBData(this) );
+
+ if( pMgr->OpenDataSource( aTmpDBData.sDataSource, aTmpDBData.sCommand, -1, false ))
+ rCalc.VarChange( lcl_GetDBVarName( *this, rDBFld),
+ pMgr->GetSelectedRecordId(aTmpDBData.sDataSource, aTmpDBData.sCommand, aTmpDBData.nCommandType) );
+ }
+ else
+ {
+ OSL_FAIL("TODO: what should happen with unnamed DBFields?");
+ }
+}
+
+void SwDoc::_InitFieldTypes() // wird vom CTOR gerufen!!
+{
+ // Feldtypen
+ sal_uInt16 nFldType = 0;
+ pFldTypes->Insert( new SwDateTimeFieldType(this), nFldType++ );
+ pFldTypes->Insert( new SwChapterFieldType, nFldType++ );
+ pFldTypes->Insert( new SwPageNumberFieldType, nFldType++ );
+ pFldTypes->Insert( new SwAuthorFieldType, nFldType++ );
+ pFldTypes->Insert( new SwFileNameFieldType(this), nFldType++ );
+ pFldTypes->Insert( new SwDBNameFieldType(this), nFldType++);
+ pFldTypes->Insert( new SwGetExpFieldType(this), nFldType++ );
+ pFldTypes->Insert( new SwGetRefFieldType( this ), nFldType++ );
+ pFldTypes->Insert( new SwHiddenTxtFieldType, nFldType++ );
+ pFldTypes->Insert( new SwPostItFieldType(this), nFldType++ );
+ pFldTypes->Insert( new SwDocStatFieldType(this), nFldType++);
+ pFldTypes->Insert( new SwDocInfoFieldType(this), nFldType++);
+ pFldTypes->Insert( new SwInputFieldType( this ), nFldType++ );
+ pFldTypes->Insert( new SwTblFieldType( this ), nFldType++);
+ pFldTypes->Insert( new SwMacroFieldType(this), nFldType++ );
+ pFldTypes->Insert( new SwHiddenParaFieldType, nFldType++ );
+ pFldTypes->Insert( new SwDBNextSetFieldType, nFldType++ );
+ pFldTypes->Insert( new SwDBNumSetFieldType, nFldType++ );
+ pFldTypes->Insert( new SwDBSetNumberFieldType, nFldType++ );
+ pFldTypes->Insert( new SwTemplNameFieldType(this), nFldType++);
+ pFldTypes->Insert( new SwTemplNameFieldType(this),nFldType++);
+ pFldTypes->Insert( new SwExtUserFieldType, nFldType++ );
+ pFldTypes->Insert( new SwRefPageSetFieldType, nFldType++ );
+ pFldTypes->Insert( new SwRefPageGetFieldType( this ), nFldType++ );
+ pFldTypes->Insert( new SwJumpEditFieldType( this ), nFldType++ );
+ pFldTypes->Insert( new SwScriptFieldType( this ), nFldType++ );
+ pFldTypes->Insert( new SwCombinedCharFieldType, nFldType++ );
+ pFldTypes->Insert( new SwDropDownFieldType, nFldType++ );
+
+ // Types muessen am Ende stehen !!
+ // Im InsertFldType wird davon ausgegangen !!!!
+ // MIB 14.04.95: Im Sw3StringPool::Setup (sw3imp.cxx) und
+ // lcl_sw3io_InSetExpField (sw3field.cxx) jetzt auch
+ pFldTypes->Insert( new SwSetExpFieldType(this,
+ SW_RESSTR(STR_POOLCOLL_LABEL_ABB), nsSwGetSetExpType::GSE_SEQ), nFldType++);
+ pFldTypes->Insert( new SwSetExpFieldType(this,
+ SW_RESSTR(STR_POOLCOLL_LABEL_TABLE), nsSwGetSetExpType::GSE_SEQ),nFldType++);
+ pFldTypes->Insert( new SwSetExpFieldType(this,
+ SW_RESSTR(STR_POOLCOLL_LABEL_FRAME), nsSwGetSetExpType::GSE_SEQ),nFldType++);
+ pFldTypes->Insert( new SwSetExpFieldType(this,
+ SW_RESSTR(STR_POOLCOLL_LABEL_DRAWING), nsSwGetSetExpType::GSE_SEQ),nFldType++);
+
+ OSL_ENSURE( nFldType == INIT_FLDTYPES, "Bad initsize: SwFldTypes" );
+}
+
+void SwDoc::InsDelFldInFldLst( bool bIns, const SwTxtFld& rFld )
+{
+ if( !mbNewFldLst || !IsInDtor() )
+ pUpdtFlds->InsDelFldInFldLst( bIns, rFld );
+}
+
+SwDBData SwDoc::GetDBData()
+{
+ return GetDBDesc();
+}
+
+const SwDBData& SwDoc::GetDBDesc()
+{
+ if(!aDBData.sDataSource.getLength())
+ {
+ const sal_uInt16 nSize = pFldTypes->Count();
+ for(sal_uInt16 i = 0; i < nSize && !aDBData.sDataSource.getLength(); ++i)
+ {
+ SwFieldType& rFldType = *((*pFldTypes)[i]);
+ sal_uInt16 nWhich = rFldType.Which();
+ if(IsUsed(rFldType))
+ {
+ switch(nWhich)
+ {
+ case RES_DBFLD:
+ case RES_DBNEXTSETFLD:
+ case RES_DBNUMSETFLD:
+ case RES_DBSETNUMBERFLD:
+ {
+ SwIterator<SwFmtFld,SwFieldType> aIter( rFldType );
+ for( SwFmtFld* pFld = aIter.First(); pFld; pFld = aIter.Next() )
+ {
+ if(pFld->IsFldInDoc())
+ {
+ if(RES_DBFLD == nWhich)
+ aDBData =
+ (static_cast < SwDBFieldType * > (pFld->GetFld()->GetTyp()))
+ ->GetDBData();
+ else
+ aDBData = (static_cast < SwDBNameInfField* > (pFld->GetFld()))->GetRealDBData();
+ break;
+ }
+ }
+ }
+ break;
+ }
+ }
+ }
+ }
+ if(!aDBData.sDataSource.getLength())
+ aDBData = GetNewDBMgr()->GetAddressDBName();
+ return aDBData;
+}
+
+void SwDoc::SetInitDBFields( sal_Bool b )
+{
+ GetNewDBMgr()->SetInitDBFields( b );
+}
+
+/*--------------------------------------------------------------------
+ Beschreibung: Alle von Feldern verwendete Datenbanken herausfinden
+ --------------------------------------------------------------------*/
+String lcl_DBDataToString(const SwDBData& rData)
+{
+ String sRet = rData.sDataSource;
+ sRet += DB_DELIM;
+ sRet += (String)rData.sCommand;
+ sRet += DB_DELIM;
+ sRet += String::CreateFromInt32(rData.nCommandType);
+ return sRet;
+}
+
+void SwDoc::GetAllUsedDB( SvStringsDtor& rDBNameList,
+ const SvStringsDtor* pAllDBNames )
+{
+ SvStringsDtor aUsedDBNames;
+ SvStringsDtor aAllDBNames;
+
+ if( !pAllDBNames )
+ {
+ GetAllDBNames( aAllDBNames );
+ pAllDBNames = &aAllDBNames;
+ }
+
+ SwSectionFmts& rArr = GetSections();
+ for (sal_uInt16 n = rArr.Count(); n; )
+ {
+ SwSection* pSect = rArr[ --n ]->GetSection();
+
+ if( pSect )
+ {
+ String aCond( pSect->GetCondition() );
+ AddUsedDBToList( rDBNameList, FindUsedDBs( *pAllDBNames,
+ aCond, aUsedDBNames ) );
+ aUsedDBNames.DeleteAndDestroy( 0, aUsedDBNames.Count() );
+ }
+ }
+
+ const SfxPoolItem* pItem;
+ sal_uInt32 nMaxItems = GetAttrPool().GetItemCount2( RES_TXTATR_FIELD );
+ for (sal_uInt32 n = 0; n < nMaxItems; ++n)
+ {
+ if( 0 == (pItem = GetAttrPool().GetItem2( RES_TXTATR_FIELD, n ) ))
+ continue;
+
+ const SwFmtFld* pFmtFld = (SwFmtFld*)pItem;
+ const SwTxtFld* pTxtFld = pFmtFld->GetTxtFld();
+ if( !pTxtFld || !pTxtFld->GetTxtNode().GetNodes().IsDocNodes() )
+ continue;
+
+ const SwField* pFld = pFmtFld->GetFld();
+ switch( pFld->GetTyp()->Which() )
+ {
+ case RES_DBFLD:
+ AddUsedDBToList( rDBNameList,
+ lcl_DBDataToString(((SwDBField*)pFld)->GetDBData() ));
+ break;
+
+ case RES_DBSETNUMBERFLD:
+ case RES_DBNAMEFLD:
+ AddUsedDBToList( rDBNameList,
+ lcl_DBDataToString(((SwDBNameInfField*)pFld)->GetRealDBData() ));
+ break;
+
+ case RES_DBNUMSETFLD:
+ case RES_DBNEXTSETFLD:
+ AddUsedDBToList( rDBNameList,
+ lcl_DBDataToString(((SwDBNameInfField*)pFld)->GetRealDBData() ));
+ // kein break // JP: ist das so richtig ??
+
+ case RES_HIDDENTXTFLD:
+ case RES_HIDDENPARAFLD:
+ AddUsedDBToList(rDBNameList, FindUsedDBs( *pAllDBNames,
+ pFld->GetPar1(), aUsedDBNames ));
+ aUsedDBNames.DeleteAndDestroy( 0, aUsedDBNames.Count() );
+ break;
+
+ case RES_SETEXPFLD:
+ case RES_GETEXPFLD:
+ case RES_TABLEFLD:
+ AddUsedDBToList(rDBNameList, FindUsedDBs( *pAllDBNames,
+ pFld->GetFormula(), aUsedDBNames ));
+ aUsedDBNames.DeleteAndDestroy( 0, aUsedDBNames.Count() );
+ break;
+ }
+ }
+}
+
+void SwDoc::GetAllDBNames( SvStringsDtor& rAllDBNames )
+{
+ SwNewDBMgr* pMgr = GetNewDBMgr();
+
+ const SwDSParamArr& rArr = pMgr->GetDSParamArray();
+ for(sal_uInt16 i = 0; i < rArr.Count(); i++)
+ {
+ SwDSParam* pParam = rArr[i];
+ String* pStr = new String( pParam->sDataSource );
+ (*pStr) += DB_DELIM;
+ (*pStr) += (String)pParam->sCommand;
+ rAllDBNames.Insert( pStr, rAllDBNames.Count() );
+ }
+}
+
+SvStringsDtor& SwDoc::FindUsedDBs( const SvStringsDtor& rAllDBNames,
+ const String& rFormel,
+ SvStringsDtor& rUsedDBNames )
+{
+ const CharClass& rCC = GetAppCharClass();
+ String sFormel( rFormel);
+#ifndef UNX
+ rCC.toUpper( sFormel );
+#endif
+
+ xub_StrLen nPos;
+ for (sal_uInt16 i = 0; i < rAllDBNames.Count(); ++i )
+ {
+ const String* pStr = rAllDBNames.GetObject(i);
+
+ if( STRING_NOTFOUND != (nPos = sFormel.Search( *pStr )) &&
+ sFormel.GetChar( nPos + pStr->Len() ) == '.' &&
+ (!nPos || !rCC.isLetterNumeric( sFormel, nPos - 1 )))
+ {
+ // Tabellenname suchen
+ xub_StrLen nEndPos;
+ nPos += pStr->Len() + 1;
+ if( STRING_NOTFOUND != (nEndPos = sFormel.Search('.', nPos)) )
+ {
+ String* pDBNm = new String( *pStr );
+ pDBNm->Append( DB_DELIM );
+ pDBNm->Append( sFormel.Copy( nPos, nEndPos - nPos ));
+ rUsedDBNames.Insert( pDBNm, rUsedDBNames.Count() );
+ }
+ }
+ }
+ return rUsedDBNames;
+}
+
+void SwDoc::AddUsedDBToList( SvStringsDtor& rDBNameList,
+ const SvStringsDtor& rUsedDBNames )
+{
+ for (sal_uInt16 i = 0; i < rUsedDBNames.Count(); i++)
+ AddUsedDBToList( rDBNameList, *rUsedDBNames.GetObject(i) );
+}
+
+void SwDoc::AddUsedDBToList( SvStringsDtor& rDBNameList, const String& rDBName)
+{
+ if( !rDBName.Len() )
+ return;
+
+#ifdef UNX
+ for( sal_uInt16 i = 0; i < rDBNameList.Count(); ++i )
+ if( rDBName == rDBNameList.GetObject(i)->GetToken(0) )
+ return;
+#else
+ const ::utl::TransliterationWrapper& rSCmp = GetAppCmpStrIgnore();
+ for( sal_uInt16 i = 0; i < rDBNameList.Count(); ++i )
+ if( rSCmp.isEqual( rDBName, rDBNameList.GetObject(i)->GetToken(0) ) )
+ return;
+#endif
+
+ SwDBData aData;
+ aData.sDataSource = rDBName.GetToken(0, DB_DELIM);
+ aData.sCommand = rDBName.GetToken(1, DB_DELIM);
+ aData.nCommandType = -1;
+ GetNewDBMgr()->CreateDSData(aData);
+ String* pNew = new String( rDBName );
+ rDBNameList.Insert( pNew, rDBNameList.Count() );
+}
+
+void SwDoc::ChangeDBFields( const SvStringsDtor& rOldNames,
+ const String& rNewName )
+{
+ SwDBData aNewDBData;
+ aNewDBData.sDataSource = rNewName.GetToken(0, DB_DELIM);
+ aNewDBData.sCommand = rNewName.GetToken(1, DB_DELIM);
+ aNewDBData.nCommandType = (short)rNewName.GetToken(2, DB_DELIM).ToInt32();
+
+ String sFormel;
+
+ SwSectionFmts& rArr = GetSections();
+ for (sal_uInt16 n = rArr.Count(); n; )
+ {
+ SwSection* pSect = rArr[ --n ]->GetSection();
+
+ if( pSect )
+ {
+ sFormel = pSect->GetCondition();
+ ReplaceUsedDBs( rOldNames, rNewName, sFormel);
+ pSect->SetCondition(sFormel);
+ }
+ }
+
+ const SfxPoolItem* pItem;
+ sal_uInt32 nMaxItems = GetAttrPool().GetItemCount2( RES_TXTATR_FIELD );
+
+ for (sal_uInt32 n = 0; n < nMaxItems; ++n )
+ {
+ if( 0 == (pItem = GetAttrPool().GetItem2( RES_TXTATR_FIELD, n ) ))
+ continue;
+
+ SwFmtFld* pFmtFld = (SwFmtFld*)pItem;
+ SwTxtFld* pTxtFld = pFmtFld->GetTxtFld();
+ if( !pTxtFld || !pTxtFld->GetTxtNode().GetNodes().IsDocNodes() )
+ continue;
+
+ SwField* pFld = pFmtFld->GetFld();
+ sal_Bool bExpand = sal_False;
+
+ switch( pFld->GetTyp()->Which() )
+ {
+ case RES_DBFLD:
+ if( IsNameInArray( rOldNames, lcl_DBDataToString(((SwDBField*)pFld)->GetDBData())))
+ {
+ SwDBFieldType* pOldTyp = (SwDBFieldType*)pFld->GetTyp();
+
+ SwDBFieldType* pTyp = (SwDBFieldType*)InsertFldType(
+ SwDBFieldType(this, pOldTyp->GetColumnName(), aNewDBData));
+
+ pFmtFld->RegisterToFieldType( *pTyp );
+ pFld->ChgTyp(pTyp);
+
+ ((SwDBField*)pFld)->ClearInitialized();
+ ((SwDBField*)pFld)->InitContent();
+
+ bExpand = sal_True;
+ }
+ break;
+
+ case RES_DBSETNUMBERFLD:
+ case RES_DBNAMEFLD:
+ if( IsNameInArray( rOldNames,
+ lcl_DBDataToString(((SwDBNameInfField*)pFld)->GetRealDBData())))
+ {
+ ((SwDBNameInfField*)pFld)->SetDBData(aNewDBData);
+ bExpand = sal_True;
+ }
+ break;
+
+ case RES_DBNUMSETFLD:
+ case RES_DBNEXTSETFLD:
+ if( IsNameInArray( rOldNames,
+ lcl_DBDataToString(((SwDBNameInfField*)pFld)->GetRealDBData())))
+ {
+ ((SwDBNameInfField*)pFld)->SetDBData(aNewDBData);
+ bExpand = sal_True;
+ }
+ // kein break;
+ case RES_HIDDENTXTFLD:
+ case RES_HIDDENPARAFLD:
+ sFormel = pFld->GetPar1();
+ ReplaceUsedDBs( rOldNames, rNewName, sFormel);
+ pFld->SetPar1( sFormel );
+ bExpand = sal_True;
+ break;
+
+ case RES_SETEXPFLD:
+ case RES_GETEXPFLD:
+ case RES_TABLEFLD:
+ sFormel = pFld->GetFormula();
+ ReplaceUsedDBs( rOldNames, rNewName, sFormel);
+ pFld->SetPar2( sFormel );
+ bExpand = sal_True;
+ break;
+ }
+
+ if (bExpand)
+ pTxtFld->ExpandAlways();
+ }
+ SetModified();
+}
+
+void SwDoc::ReplaceUsedDBs( const SvStringsDtor& rUsedDBNames,
+ const String& rNewName, String& rFormel )
+{
+ const CharClass& rCC = GetAppCharClass();
+ String sFormel(rFormel);
+ String sNewName( rNewName );
+ sNewName.SearchAndReplace( DB_DELIM, '.');
+ //the command type is not part of the condition
+ sNewName = sNewName.GetToken(0, DB_DELIM);
+ String sUpperNewNm( sNewName );
+
+
+ for( sal_uInt16 i = 0; i < rUsedDBNames.Count(); ++i )
+ {
+ String sDBName( *rUsedDBNames.GetObject( i ) );
+
+ sDBName.SearchAndReplace( DB_DELIM, '.');
+ //cut off command type
+ sDBName = sDBName.GetToken(0, DB_DELIM);
+ if( !sDBName.Equals( sUpperNewNm ))
+ {
+ xub_StrLen nPos = 0;
+
+ while ((nPos = sFormel.Search(sDBName, nPos)) != STRING_NOTFOUND)
+ {
+ if( sFormel.GetChar( nPos + sDBName.Len() ) == '.' &&
+ (!nPos || !rCC.isLetterNumeric( sFormel, nPos - 1 )))
+ {
+ rFormel.Erase( nPos, sDBName.Len() );
+ rFormel.Insert( sNewName, nPos );
+ //prevent re-searching - this is useless and provokes
+ //endless loops when names containing each other and numbers are exchanged
+ //e.g.: old ?12345.12345 new: i12345.12345
+ nPos = nPos + sNewName.Len();
+ sFormel = rFormel;
+ }
+ }
+ }
+ }
+}
+
+sal_Bool SwDoc::IsNameInArray( const SvStringsDtor& rArr, const String& rName )
+{
+#ifdef UNX
+ for( sal_uInt16 i = 0; i < rArr.Count(); ++i )
+ if( rName == *rArr[ i ] )
+ return sal_True;
+#else
+ const ::utl::TransliterationWrapper& rSCmp = GetAppCmpStrIgnore();
+ for( sal_uInt16 i = 0; i < rArr.Count(); ++i )
+ if( rSCmp.isEqual( rName, *rArr[ i] ))
+ return sal_True;
+#endif
+ return sal_False;
+}
+
+void SwDoc::SetFixFields( bool bOnlyTimeDate, const DateTime* pNewDateTime )
+{
+ sal_Bool bIsModified = IsModified();
+
+ sal_uLong nDate, nTime;
+ if( pNewDateTime )
+ {
+ nDate = pNewDateTime->GetDate();
+ nTime = pNewDateTime->GetTime();
+ }
+ else
+ {
+ nDate = Date().GetDate();
+ nTime = Time().GetTime();
+ }
+
+ sal_uInt16 aTypes[5] = {
+ /*0*/ RES_DOCINFOFLD,
+ /*1*/ RES_AUTHORFLD,
+ /*2*/ RES_EXTUSERFLD,
+ /*3*/ RES_FILENAMEFLD,
+ /*4*/ RES_DATETIMEFLD }; // MUSS am Ende stehen!!
+
+ sal_uInt16 nStt = bOnlyTimeDate ? 4 : 0;
+
+ for( ; nStt < 5; ++nStt )
+ {
+ SwFieldType* pFldType = GetSysFldType( aTypes[ nStt ] );
+ SwIterator<SwFmtFld,SwFieldType> aIter( *pFldType );
+ for( SwFmtFld* pFld = aIter.First(); pFld; pFld = aIter.Next() )
+ {
+ if( pFld && pFld->GetTxtFld() )
+ {
+ sal_Bool bChgd = sal_False;
+ switch( aTypes[ nStt ] )
+ {
+ case RES_DOCINFOFLD:
+ if( ((SwDocInfoField*)pFld->GetFld())->IsFixed() )
+ {
+ bChgd = sal_True;
+ SwDocInfoField* pDocInfFld = (SwDocInfoField*)pFld->GetFld();
+ pDocInfFld->SetExpansion( ((SwDocInfoFieldType*)
+ pDocInfFld->GetTyp())->Expand(
+ pDocInfFld->GetSubType(),
+ pDocInfFld->GetFormat(),
+ pDocInfFld->GetLanguage(),
+ pDocInfFld->GetName() ) );
+ }
+ break;
+
+ case RES_AUTHORFLD:
+ if( ((SwAuthorField*)pFld->GetFld())->IsFixed() )
+ {
+ bChgd = sal_True;
+ SwAuthorField* pAuthorFld = (SwAuthorField*)pFld->GetFld();
+ pAuthorFld->SetExpansion( ((SwAuthorFieldType*)
+ pAuthorFld->GetTyp())->Expand(
+ pAuthorFld->GetFormat() ) );
+ }
+ break;
+
+ case RES_EXTUSERFLD:
+ if( ((SwExtUserField*)pFld->GetFld())->IsFixed() )
+ {
+ bChgd = sal_True;
+ SwExtUserField* pExtUserFld = (SwExtUserField*)pFld->GetFld();
+ pExtUserFld->SetExpansion( ((SwExtUserFieldType*)
+ pExtUserFld->GetTyp())->Expand(
+ pExtUserFld->GetSubType(),
+ pExtUserFld->GetFormat()));
+ }
+ break;
+
+ case RES_DATETIMEFLD:
+ if( ((SwDateTimeField*)pFld->GetFld())->IsFixed() )
+ {
+ bChgd = sal_True;
+ ((SwDateTimeField*)pFld->GetFld())->SetDateTime(
+ DateTime(Date(nDate), Time(nTime)) );
+ }
+ break;
+
+ case RES_FILENAMEFLD:
+ if( ((SwFileNameField*)pFld->GetFld())->IsFixed() )
+ {
+ bChgd = sal_True;
+ SwFileNameField* pFileNameFld =
+ (SwFileNameField*)pFld->GetFld();
+ pFileNameFld->SetExpansion( ((SwFileNameFieldType*)
+ pFileNameFld->GetTyp())->Expand(
+ pFileNameFld->GetFormat() ) );
+ }
+ break;
+ }
+
+ // Formatierung anstossen
+ if( bChgd )
+ pFld->ModifyNotification( 0, 0 );
+ }
+ }
+ }
+
+ if( !bIsModified )
+ ResetModified();
+}
+
+bool SwDoc::SetFieldsDirty( bool b, const SwNode* pChk, sal_uLong nLen )
+{
+ // teste ggfs. mal, ob die angegbenen Nodes ueberhaupt Felder beinhalten.
+ // wenn nicht, braucht das Flag nicht veraendert werden.
+ sal_Bool bFldsFnd = sal_False;
+ if( b && pChk && !GetUpdtFlds().IsFieldsDirty() && !IsInDtor()
+ // ?? was ist mit Undo, da will man es doch auch haben !!
+ /*&& &pChk->GetNodes() == &GetNodes()*/ )
+ {
+ b = sal_False;
+ if( !nLen )
+ ++nLen;
+ sal_uLong nStt = pChk->GetIndex();
+ const SwNodes& rNds = pChk->GetNodes();
+ while( nLen-- )
+ {
+ const SwTxtNode* pTNd = rNds[ nStt++ ]->GetTxtNode();
+ if( pTNd )
+ {
+ if( pTNd->GetAttrOutlineLevel() != 0 )
+ // Kapitelfelder aktualisieren
+ b = sal_True;
+ else if( pTNd->GetpSwpHints() && pTNd->GetSwpHints().Count() )
+ for( sal_uInt16 n = 0, nEnd = pTNd->GetSwpHints().Count();
+ n < nEnd; ++n )
+ {
+ const SwTxtAttr* pAttr = pTNd->GetSwpHints()[ n ];
+ if( RES_TXTATR_FIELD == pAttr->Which() )
+ {
+ b = sal_True;
+ break;
+ }
+ }
+
+ if( b )
+ break;
+ }
+ }
+ bFldsFnd = b;
+ }
+ GetUpdtFlds().SetFieldsDirty( b );
+ return bFldsFnd;
+}
+
+void SwDoc::ChangeAuthorityData( const SwAuthEntry* pNewData )
+{
+ const sal_uInt16 nSize = pFldTypes->Count();
+
+ for( sal_uInt16 i = INIT_FLDTYPES; i < nSize; ++i )
+ {
+ SwFieldType* pFldType = (*pFldTypes)[i];
+ if( RES_AUTHORITY == pFldType->Which() )
+ {
+ SwAuthorityFieldType* pAuthType = (SwAuthorityFieldType*)pFldType;
+ pAuthType->ChangeEntryContent(pNewData);
+ break;
+ }
+ }
+
+}
+
+void SwDocUpdtFld::InsDelFldInFldLst( sal_Bool bIns, const SwTxtFld& rFld )
+{
+ sal_uInt16 nWhich = rFld.GetFld().GetFld()->GetTyp()->Which();
+ switch( nWhich )
+ {
+ case RES_DBFLD:
+ case RES_SETEXPFLD:
+ case RES_HIDDENPARAFLD:
+ case RES_HIDDENTXTFLD:
+ case RES_DBNUMSETFLD:
+ case RES_DBNEXTSETFLD:
+ case RES_DBSETNUMBERFLD:
+ case RES_GETEXPFLD:
+ break; // diese muessen ein-/ausgetragen werden!
+
+ default:
+ return;
+ }
+
+ SetFieldsDirty( sal_True );
+ if( !pFldSortLst )
+ {
+ if( !bIns ) // keine Liste vorhanden und loeschen
+ return; // dann nichts tun
+ pFldSortLst = new _SetGetExpFlds( 64, 16 );
+ }
+
+ if( bIns ) // neu einfuegen:
+ GetBodyNode( rFld, nWhich );
+ else
+ {
+ // ueber den pTxtFld Pointer suchen. Ist zwar eine Sortierte
+ // Liste, aber nach Node-Positionen sortiert. Bis dieser
+ // bestimmt ist, ist das Suchen nach dem Pointer schon fertig
+ for( sal_uInt16 n = 0; n < pFldSortLst->Count(); ++n )
+ if( &rFld == (*pFldSortLst)[ n ]->GetPointer() )
+ pFldSortLst->DeleteAndDestroy( n--, 1 );
+ // ein Feld kann mehrfach vorhanden sein!
+ }
+}
+
+void SwDocUpdtFld::MakeFldList( SwDoc& rDoc, int bAll, int eGetMode )
+{
+ if( !pFldSortLst || bAll || !( eGetMode & nFldLstGetMode ) ||
+ rDoc.GetNodes().Count() != nNodes )
+ _MakeFldList( rDoc, eGetMode );
+}
+
+void SwDocUpdtFld::_MakeFldList( SwDoc& rDoc, int eGetMode )
+{
+ // neue Version: gehe ueber alle Felder vom Attribut-Pool
+ if( pFldSortLst )
+ delete pFldSortLst;
+ pFldSortLst = new _SetGetExpFlds( 64, 16 );
+
+ /// consider and unhide sections
+ /// with hide condition, only in mode GETFLD_ALL (<eGetMode == GETFLD_ALL>)
+ /// notes by OD:
+ /// eGetMode == GETFLD_CALC in call from methods SwDoc::FldsToCalc
+ /// eGetMode == GETFLD_EXPAND in call from method SwDoc::FldsToExpand
+ /// eGetMode == GETFLD_ALL in call from method SwDoc::UpdateExpFlds
+ /// I figured out that hidden section only have to be shown,
+ /// if fields have updated (call by SwDoc::UpdateExpFlds) and thus
+ /// the hide conditions of section have to be updated.
+ /// For correct updating the hide condition of a section, its position
+ /// have to be known in order to insert the hide condition as a new
+ /// expression field into the sorted field list (<pFldSortLst>).
+ if ( eGetMode == GETFLD_ALL )
+ // zuerst die Bereiche einsammeln. Alle die ueber Bedingung
+ // gehiddet sind, wieder mit Frames versorgen, damit die darin
+ // enthaltenen Felder richtig einsortiert werden!!!
+ {
+ // damit die Frames richtig angelegt werden, muessen sie in der
+ // Reihenfolgen von oben nach unten expandiert werden
+ SvULongs aTmpArr;
+ SwSectionFmts& rArr = rDoc.GetSections();
+ SwSectionNode* pSectNd;
+ sal_uInt16 nArrStt = 0;
+ sal_uLong nSttCntnt = rDoc.GetNodes().GetEndOfExtras().GetIndex();
+
+ for (sal_uInt16 n = rArr.Count(); n; )
+ {
+ SwSection* pSect = rArr[ --n ]->GetSection();
+ if( pSect && pSect->IsHidden() && pSect->GetCondition().Len() &&
+ 0 != ( pSectNd = pSect->GetFmt()->GetSectionNode() ))
+ {
+ sal_uLong nIdx = pSectNd->GetIndex();
+ sal_uInt16 i;
+
+ for( i = 0; i < aTmpArr.Count() && aTmpArr[ i ] < nIdx; ++i )
+ ;
+ aTmpArr.Insert( nIdx, i );
+ if( nIdx < nSttCntnt )
+ ++nArrStt;
+ }
+ }
+
+ // erst alle anzeigen, damit die Frames vorhanden sind. Mit deren
+ // Position wird das BodyAnchor ermittelt.
+ // Dafuer erst den ContentBereich, dann die Sonderbereiche!!!
+ for (sal_uInt16 n = nArrStt; n < aTmpArr.Count(); ++n)
+ {
+ pSectNd = rDoc.GetNodes()[ aTmpArr[ n ] ]->GetSectionNode();
+ OSL_ENSURE( pSectNd, "Wo ist mein SectionNode" );
+ pSectNd->GetSection().SetCondHidden( sal_False );
+ }
+ for (sal_uInt16 n = 0; n < nArrStt; ++n)
+ {
+ pSectNd = rDoc.GetNodes()[ aTmpArr[ n ] ]->GetSectionNode();
+ OSL_ENSURE( pSectNd, "Wo ist mein SectionNode" );
+ pSectNd->GetSection().SetCondHidden( sal_False );
+ }
+
+ // so, erst jetzt alle sortiert in die Liste eintragen
+ for (sal_uInt16 n = 0; n < aTmpArr.Count(); ++n)
+ {
+ GetBodyNode( *rDoc.GetNodes()[ aTmpArr[ n ] ]->GetSectionNode() );
+ }
+ }
+
+ String sTrue( String::CreateFromAscii(
+ RTL_CONSTASCII_STRINGPARAM( "TRUE" ))),
+ sFalse( String::CreateFromAscii(
+ RTL_CONSTASCII_STRINGPARAM( "FALSE" )));
+
+ sal_Bool bIsDBMgr = 0 != rDoc.GetNewDBMgr();
+ sal_uInt16 nWhich, n;
+ const String* pFormel = 0;
+ const SfxPoolItem* pItem;
+ sal_uInt32 nMaxItems = rDoc.GetAttrPool().GetItemCount2( RES_TXTATR_FIELD );
+ for( n = 0; n < nMaxItems; ++n )
+ {
+ if( 0 == (pItem = rDoc.GetAttrPool().GetItem2( RES_TXTATR_FIELD, n )) )
+ continue;
+
+ const SwFmtFld* pFmtFld = (SwFmtFld*)pItem;
+ const SwTxtFld* pTxtFld = pFmtFld->GetTxtFld();
+ if( !pTxtFld || !pTxtFld->GetTxtNode().GetNodes().IsDocNodes() )
+ continue;
+
+ const SwField* pFld = pFmtFld->GetFld();
+ switch( nWhich = pFld->GetTyp()->Which() )
+ {
+ case RES_DBSETNUMBERFLD:
+ case RES_GETEXPFLD:
+ if( GETFLD_ALL == eGetMode )
+ pFormel = &sTrue;
+ break;
+
+ case RES_DBFLD:
+ if( GETFLD_EXPAND & eGetMode )
+ pFormel = &sTrue;
+ break;
+
+ case RES_SETEXPFLD:
+ if ( !(eGetMode == GETFLD_EXPAND) ||
+ (nsSwGetSetExpType::GSE_STRING & pFld->GetSubType()) )
+ {
+ pFormel = &sTrue;
+ }
+ break;
+
+ case RES_HIDDENPARAFLD:
+ if( GETFLD_ALL == eGetMode )
+ {
+ pFormel = &pFld->GetPar1();
+ if( !pFormel->Len() || pFormel->Equals( sFalse ))
+ ((SwHiddenParaField*)pFld)->SetHidden( sal_False );
+ else if( pFormel->Equals( sTrue ))
+ ((SwHiddenParaField*)pFld)->SetHidden( sal_True );
+ else
+ break;
+
+ pFormel = 0;
+ // Formatierung anstossen
+ ((SwFmtFld*)pFmtFld)->ModifyNotification( 0, 0 );
+ }
+ break;
+
+ case RES_HIDDENTXTFLD:
+ if( GETFLD_ALL == eGetMode )
+ {
+ pFormel = &pFld->GetPar1();
+ if( !pFormel->Len() || pFormel->Equals( sFalse ))
+ ((SwHiddenTxtField*)pFld)->SetValue( sal_True );
+ else if( pFormel->Equals( sTrue ))
+ ((SwHiddenTxtField*)pFld)->SetValue( sal_False );
+ else
+ break;
+
+ pFormel = 0;
+
+ // Feld Evaluieren
+ ((SwHiddenTxtField*)pFld)->Evaluate(&rDoc);
+ // Formatierung anstossen
+ ((SwFmtFld*)pFmtFld)->ModifyNotification( 0, 0 );
+ }
+ break;
+
+ case RES_DBNUMSETFLD:
+ {
+ SwDBData aDBData(((SwDBNumSetField*)pFld)->GetDBData(&rDoc));
+
+ if (
+ (bIsDBMgr && rDoc.GetNewDBMgr()->OpenDataSource(aDBData.sDataSource, aDBData.sCommand)) &&
+ (GETFLD_ALL == eGetMode || (GETFLD_CALC & eGetMode && ((SwDBNumSetField*)pFld)->IsCondValid()))
+ )
+ {
+ pFormel = &pFld->GetPar1();
+ }
+ }
+ break;
+ case RES_DBNEXTSETFLD:
+ {
+ SwDBData aDBData(((SwDBNextSetField*)pFld)->GetDBData(&rDoc));
+
+ if (
+ (bIsDBMgr && rDoc.GetNewDBMgr()->OpenDataSource(aDBData.sDataSource, aDBData.sCommand)) &&
+ (GETFLD_ALL == eGetMode || (GETFLD_CALC & eGetMode && ((SwDBNextSetField*)pFld)->IsCondValid()))
+ )
+ {
+ pFormel = &pFld->GetPar1();
+ }
+ }
+ break;
+ }
+
+ if( pFormel && pFormel->Len() )
+ {
+ GetBodyNode( *pTxtFld, nWhich );
+ pFormel = 0;
+ }
+ }
+ nFldLstGetMode = static_cast<sal_uInt8>( eGetMode );
+ nNodes = rDoc.GetNodes().Count();
+}
+
+void SwDocUpdtFld::GetBodyNode( const SwTxtFld& rTFld, sal_uInt16 nFldWhich )
+{
+ const SwTxtNode& rTxtNd = rTFld.GetTxtNode();
+ const SwDoc& rDoc = *rTxtNd.GetDoc();
+
+ // immer den ersten !! (in Tab-Headline, Kopf-/Fuss )
+ Point aPt;
+ const SwCntntFrm* pFrm = rTxtNd.getLayoutFrm( rDoc.GetCurrentLayout(), &aPt, 0, sal_False );
+
+ _SetGetExpFld* pNew = NULL;
+ sal_Bool bIsInBody = sal_False;
+
+ if( !pFrm || pFrm->IsInDocBody() )
+ {
+ // einen Index fuers bestimmen vom TextNode anlegen
+ SwNodeIndex aIdx( rTxtNd );
+ bIsInBody = rDoc.GetNodes().GetEndOfExtras().GetIndex() < aIdx.GetIndex();
+
+ // We don't want to update fields in redlines, or those
+ // in frames whose anchor is in redline. However, we do want to update
+ // fields in hidden sections. So: In order to be updated, a field 1)
+ // must have a frame, or 2) it must be in the document body.
+ if( (pFrm != NULL) || bIsInBody )
+ pNew = new _SetGetExpFld( aIdx, &rTFld );
+ }
+ else
+ {
+ // einen Index fuers bestimmen vom TextNode anlegen
+ SwPosition aPos( rDoc.GetNodes().GetEndOfPostIts() );
+#if OSL_DEBUG_LEVEL > 1
+ OSL_ENSURE( GetBodyTxtNode( rDoc, aPos, *pFrm ), "wo steht das Feld" );
+#else
+ GetBodyTxtNode( rDoc, aPos, *pFrm );
+#endif
+ pNew = new _SetGetExpFld( aPos.nNode, &rTFld, &aPos.nContent );
+ }
+
+ // bei GetExp.-/DB.-Felder immer das BodyTxtFlag setzen
+ if( RES_GETEXPFLD == nFldWhich )
+ {
+ SwGetExpField* pGetFld = (SwGetExpField*)rTFld.GetFld().GetFld();
+ pGetFld->ChgBodyTxtFlag( bIsInBody );
+ }
+ else if( RES_DBFLD == nFldWhich )
+ {
+ SwDBField* pDBFld = (SwDBField*)rTFld.GetFld().GetFld();
+ pDBFld->ChgBodyTxtFlag( bIsInBody );
+ }
+
+ if( pNew != NULL )
+ if( !pFldSortLst->Insert( pNew ))
+ delete pNew;
+}
+
+void SwDocUpdtFld::GetBodyNode( const SwSectionNode& rSectNd )
+{
+ const SwDoc& rDoc = *rSectNd.GetDoc();
+ _SetGetExpFld* pNew = 0;
+
+ if( rSectNd.GetIndex() < rDoc.GetNodes().GetEndOfExtras().GetIndex() )
+ {
+ do { // middle check loop
+
+ // dann muessen wir uns mal den Anker besorgen!
+ // einen Index fuers bestimmen vom TextNode anlegen
+ SwPosition aPos( rSectNd );
+ SwCntntNode* pCNd = rDoc.GetNodes().GoNext( &aPos.nNode ); // zum naechsten ContentNode
+
+ if( !pCNd || !pCNd->IsTxtNode() )
+ break;
+
+ // immer den ersten !! (in Tab-Headline, Kopf-/Fuss )
+ Point aPt;
+ const SwCntntFrm* pFrm = pCNd->getLayoutFrm( rDoc.GetCurrentLayout(), &aPt, 0, sal_False );
+ if( !pFrm )
+ break;
+
+#if OSL_DEBUG_LEVEL > 1
+ OSL_ENSURE( GetBodyTxtNode( rDoc, aPos, *pFrm ), "wo steht das Feld" );
+#else
+ GetBodyTxtNode( rDoc, aPos, *pFrm );
+#endif
+ pNew = new _SetGetExpFld( rSectNd, &aPos );
+
+ } while( sal_False );
+ }
+
+ if( !pNew )
+ pNew = new _SetGetExpFld( rSectNd );
+
+ if( !pFldSortLst->Insert( pNew ))
+ delete pNew;
+}
+
+void SwDocUpdtFld::InsertFldType( const SwFieldType& rType )
+{
+ String sFldName;
+ switch( rType.Which() )
+ {
+ case RES_USERFLD :
+ sFldName = ((SwUserFieldType&)rType).GetName();
+ break;
+ case RES_SETEXPFLD:
+ sFldName = ((SwSetExpFieldType&)rType).GetName();
+ break;
+ default:
+ OSL_ENSURE( !this, "kein gueltiger FeldTyp" );
+ }
+
+ if( sFldName.Len() )
+ {
+ SetFieldsDirty( sal_True );
+ // suchen und aus der HashTabelle entfernen
+ GetAppCharClass().toLower( sFldName );
+ sal_uInt16 n;
+
+ SwHash* pFnd = Find( sFldName, GetFldTypeTable(), TBLSZ, &n );
+
+ if( !pFnd )
+ {
+ SwCalcFldType* pNew = new SwCalcFldType( sFldName, &rType );
+ pNew->pNext = aFldTypeTable[ n ];
+ aFldTypeTable[ n ] = pNew;
+ }
+ }
+}
+
+void SwDocUpdtFld::RemoveFldType( const SwFieldType& rType )
+{
+ String sFldName;
+ switch( rType.Which() )
+ {
+ case RES_USERFLD :
+ sFldName = ((SwUserFieldType&)rType).GetName();
+ break;
+ case RES_SETEXPFLD:
+ sFldName = ((SwSetExpFieldType&)rType).GetName();
+ break;
+ }
+
+ if( sFldName.Len() )
+ {
+ SetFieldsDirty( sal_True );
+ // suchen und aus der HashTabelle entfernen
+ GetAppCharClass().toLower( sFldName );
+ sal_uInt16 n;
+
+ SwHash* pFnd = Find( sFldName, GetFldTypeTable(), TBLSZ, &n );
+ if( pFnd )
+ {
+ if( aFldTypeTable[ n ] == pFnd )
+ aFldTypeTable[ n ] = (SwCalcFldType*)pFnd->pNext;
+ else
+ {
+ SwHash* pPrev = aFldTypeTable[ n ];
+ while( pPrev->pNext != pFnd )
+ pPrev = pPrev->pNext;
+ pPrev->pNext = pFnd->pNext;
+ }
+ pFnd->pNext = 0;
+ delete pFnd;
+ }
+ }
+}
+
+SwDocUpdtFld::SwDocUpdtFld()
+ : pFldSortLst(0), nFldUpdtPos(LONG_MAX), nFldLstGetMode(0)
+{
+ bInUpdateFlds = bFldsDirty = sal_False;
+ memset( aFldTypeTable, 0, sizeof( aFldTypeTable ) );
+}
+
+SwDocUpdtFld::~SwDocUpdtFld()
+{
+ delete pFldSortLst;
+
+ for( sal_uInt16 n = 0; n < TBLSZ; ++n )
+ delete aFldTypeTable[n];
+}
+
+bool SwDoc::UpdateFld(SwTxtFld * pDstTxtFld, SwField & rSrcFld,
+ SwMsgPoolItem * pMsgHnt,
+ bool bUpdateFlds)
+{
+ OSL_ENSURE(pDstTxtFld, "no field to update!");
+
+ sal_Bool bTblSelBreak = sal_False;
+
+ SwFmtFld * pDstFmtFld = (SwFmtFld*)&pDstTxtFld->GetFld();
+ SwField * pDstFld = pDstFmtFld->GetFld();
+ sal_uInt16 nFldWhich = rSrcFld.GetTyp()->Which();
+ SwNodeIndex aTblNdIdx(pDstTxtFld->GetTxtNode());
+
+ if (pDstFld->GetTyp()->Which() ==
+ rSrcFld.GetTyp()->Which())
+ {
+ if (GetIDocumentUndoRedo().DoesUndo())
+ {
+ SwPosition aPosition( pDstTxtFld->GetTxtNode() );
+ aPosition.nContent = *pDstTxtFld->GetStart();
+
+ SwUndo *const pUndo( new SwUndoFieldFromDoc(
+ aPosition, *pDstFld, rSrcFld, pMsgHnt, bUpdateFlds) );
+ GetIDocumentUndoRedo().AppendUndo(pUndo);
+ }
+
+ SwField * pNewFld = rSrcFld.CopyField();
+ pDstFmtFld->SetFld(pNewFld);
+
+ switch( nFldWhich )
+ {
+ case RES_SETEXPFLD:
+ case RES_GETEXPFLD:
+ case RES_HIDDENTXTFLD:
+ case RES_HIDDENPARAFLD:
+ UpdateExpFlds( pDstTxtFld, true );
+ break;
+
+ case RES_TABLEFLD:
+ {
+ const SwTableNode* pTblNd =
+ IsIdxInTbl(aTblNdIdx);
+ if( pTblNd )
+ {
+ SwTableFmlUpdate aTblUpdate( &pTblNd->
+ GetTable() );
+ if (bUpdateFlds)
+ UpdateTblFlds( &aTblUpdate );
+ else
+ pNewFld->GetTyp()->ModifyNotification(0, &aTblUpdate);
+
+ if (! bUpdateFlds)
+ bTblSelBreak = sal_True;
+ }
+ }
+ break;
+
+ case RES_MACROFLD:
+ if( bUpdateFlds && pDstTxtFld->GetpTxtNode() )
+ (pDstTxtFld->GetpTxtNode())->
+ ModifyNotification( 0, pDstFmtFld );
+ break;
+
+ case RES_DBNAMEFLD:
+ case RES_DBNEXTSETFLD:
+ case RES_DBNUMSETFLD:
+ case RES_DBSETNUMBERFLD:
+ ChgDBData(((SwDBNameInfField*) pNewFld)->GetRealDBData());
+ pNewFld->GetTyp()->UpdateFlds();
+
+ break;
+
+ case RES_DBFLD:
+ {
+ // JP 10.02.96: ChgValue aufrufen, damit
+ //die Format- aenderung den ContentString
+ //richtig setzt
+ SwDBField* pDBFld = (SwDBField*)pNewFld;
+ if (pDBFld->IsInitialized())
+ pDBFld->ChgValue( pDBFld->GetValue(), sal_True );
+
+ pDBFld->ClearInitialized();
+ pDBFld->InitContent();
+ }
+ // kein break;
+
+ default:
+ pDstFmtFld->ModifyNotification( 0, pMsgHnt );
+ }
+
+ // Die Felder die wir berechnen koennen werden hier expli.
+ // zum Update angestossen.
+ if( nFldWhich == RES_USERFLD )
+ UpdateUsrFlds();
+ }
+
+ return bTblSelBreak;
+}
+
+bool SwDoc::PutValueToField(const SwPosition & rPos,
+ const Any& rVal, sal_uInt16 nWhich)
+{
+ Any aOldVal;
+ SwField * pField = GetField(rPos);
+
+
+ if (GetIDocumentUndoRedo().DoesUndo() &&
+ pField->QueryValue(aOldVal, nWhich))
+ {
+ SwUndo *const pUndo(new SwUndoFieldFromAPI(rPos, aOldVal, rVal, nWhich));
+ GetIDocumentUndoRedo().AppendUndo(pUndo);
+ }
+
+ return pField->PutValue(rVal, nWhich);
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/doc/docfly.cxx b/sw/source/core/doc/docfly.cxx
new file mode 100644
index 000000000000..b39f329956a5
--- /dev/null
+++ b/sw/source/core/doc/docfly.cxx
@@ -0,0 +1,1015 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+#include <hintids.hxx>
+#include <svl/itemiter.hxx>
+#include <svx/svdobj.hxx>
+#include <svx/svdpage.hxx>
+#include <svx/svdmodel.hxx>
+#include <svx/svdocapt.hxx>
+#include <svx/svdmark.hxx>
+#include <fmtfsize.hxx>
+#include <fmtornt.hxx>
+#include <fmtsrnd.hxx>
+#include <dcontact.hxx>
+
+#include <ndgrf.hxx>
+#include <doc.hxx>
+#include <IDocumentUndoRedo.hxx>
+#include <ndindex.hxx>
+#include <docary.hxx>
+#include <fmtcntnt.hxx>
+#include <fmtanchr.hxx>
+#include <txtflcnt.hxx>
+#include <fmtflcnt.hxx>
+#include <txtfrm.hxx>
+#include <pagefrm.hxx>
+#include <rootfrm.hxx>
+#include <flyfrms.hxx>
+#include <frmtool.hxx>
+#include <frmfmt.hxx>
+#include <ndtxt.hxx>
+#include <pam.hxx>
+#include <tblsel.hxx>
+#include <swundo.hxx>
+#include <swtable.hxx>
+#include <crstate.hxx>
+#include <UndoCore.hxx>
+#include <UndoAttribute.hxx>
+#include <fmtcnct.hxx>
+#include <dflyobj.hxx>
+#include <undoflystrattr.hxx>
+#include <switerator.hxx>
+
+extern sal_uInt16 GetHtmlMode( const SwDocShell* );
+
+using namespace ::com::sun::star;
+
+sal_uInt16 SwDoc::GetFlyCount( FlyCntType eType ) const
+{
+ const SwSpzFrmFmts& rFmts = *GetSpzFrmFmts();
+ sal_uInt16 nSize = rFmts.Count();
+ sal_uInt16 nCount = 0;
+ const SwNodeIndex* pIdx;
+ for ( sal_uInt16 i = 0; i < nSize; i++)
+ {
+ const SwFrmFmt* pFlyFmt = rFmts[ i ];
+ if( RES_FLYFRMFMT == pFlyFmt->Which()
+ && 0 != ( pIdx = pFlyFmt->GetCntnt().GetCntntIdx() )
+ && pIdx->GetNodes().IsDocNodes()
+ )
+ {
+ const SwNode* pNd = GetNodes()[ pIdx->GetIndex() + 1 ];
+
+ switch( eType )
+ {
+ case FLYCNTTYPE_FRM:
+ if(!pNd->IsNoTxtNode())
+ nCount++;
+ break;
+
+ case FLYCNTTYPE_GRF:
+ if( pNd->IsGrfNode() )
+ nCount++;
+ break;
+
+ case FLYCNTTYPE_OLE:
+ if(pNd->IsOLENode())
+ nCount++;
+ break;
+
+ default:
+ nCount++;
+ }
+ }
+ }
+ return nCount;
+}
+
+// If you change this, also update SwXFrameEnumeration in unocoll.
+SwFrmFmt* SwDoc::GetFlyNum( sal_uInt16 nIdx, FlyCntType eType )
+{
+ SwSpzFrmFmts& rFmts = *GetSpzFrmFmts();
+ SwFrmFmt* pRetFmt = 0;
+ sal_uInt16 nSize = rFmts.Count();
+ const SwNodeIndex* pIdx;
+ sal_uInt16 nCount = 0;
+ for( sal_uInt16 i = 0; !pRetFmt && i < nSize; ++i )
+ {
+ SwFrmFmt* pFlyFmt = rFmts[ i ];
+ if( RES_FLYFRMFMT == pFlyFmt->Which()
+ && 0 != ( pIdx = pFlyFmt->GetCntnt().GetCntntIdx() )
+ && pIdx->GetNodes().IsDocNodes()
+ )
+ {
+ const SwNode* pNd = GetNodes()[ pIdx->GetIndex() + 1 ];
+ switch( eType )
+ {
+ case FLYCNTTYPE_FRM:
+ if( !pNd->IsNoTxtNode() && nIdx == nCount++)
+ pRetFmt = pFlyFmt;
+ break;
+ case FLYCNTTYPE_GRF:
+ if(pNd->IsGrfNode() && nIdx == nCount++ )
+ pRetFmt = pFlyFmt;
+ break;
+ case FLYCNTTYPE_OLE:
+ if(pNd->IsOLENode() && nIdx == nCount++)
+ pRetFmt = pFlyFmt;
+ break;
+ default:
+ if(nIdx == nCount++)
+ pRetFmt = pFlyFmt;
+ }
+ }
+ }
+ return pRetFmt;
+}
+
+Point lcl_FindAnchorLayPos( SwDoc& rDoc, const SwFmtAnchor& rAnch,
+ const SwFrmFmt* pFlyFmt )
+{
+ Point aRet;
+ if( rDoc.GetCurrentViewShell() ) //swmod 071107//swmod 071225
+ switch( rAnch.GetAnchorId() )
+ {
+ case FLY_AS_CHAR:
+ if( pFlyFmt && rAnch.GetCntntAnchor() )
+ {
+ const SwFrm* pOld = ((SwFlyFrmFmt*)pFlyFmt)->GetFrm( &aRet, sal_False );
+ if( pOld )
+ aRet = pOld->Frm().Pos();
+ }
+ break;
+
+ case FLY_AT_PARA:
+ case FLY_AT_CHAR: // LAYER_IMPL
+ if( rAnch.GetCntntAnchor() )
+ {
+ const SwPosition *pPos = rAnch.GetCntntAnchor();
+ const SwCntntNode* pNd = pPos->nNode.GetNode().GetCntntNode();
+ const SwFrm* pOld = pNd ? pNd->getLayoutFrm( rDoc.GetCurrentLayout(), &aRet, 0, sal_False ) : 0;
+ if( pOld )
+ aRet = pOld->Frm().Pos();
+ }
+ break;
+
+ case FLY_AT_FLY: // LAYER_IMPL
+ if( rAnch.GetCntntAnchor() )
+ {
+ const SwFlyFrmFmt* pFmt = (SwFlyFrmFmt*)rAnch.GetCntntAnchor()->
+ nNode.GetNode().GetFlyFmt();
+ const SwFrm* pOld = pFmt ? pFmt->GetFrm( &aRet, sal_False ) : 0;
+ if( pOld )
+ aRet = pOld->Frm().Pos();
+ }
+ break;
+
+ case FLY_AT_PAGE:
+ {
+ sal_uInt16 nPgNum = rAnch.GetPageNum();
+ const SwPageFrm *pPage = (SwPageFrm*)rDoc.GetCurrentLayout()->Lower();
+ for( sal_uInt16 i = 1; (i <= nPgNum) && pPage; ++i,
+ pPage = (const SwPageFrm*)pPage->GetNext() )
+ if( i == nPgNum )
+ {
+ aRet = pPage->Frm().Pos();
+ break;
+ }
+ }
+ break;
+ default:
+ break;
+ }
+ return aRet;
+}
+
+#define MAKEFRMS 0
+#define IGNOREANCHOR 1
+#define DONTMAKEFRMS 2
+
+sal_Int8 SwDoc::SetFlyFrmAnchor( SwFrmFmt& rFmt, SfxItemSet& rSet, sal_Bool bNewFrms )
+{
+ //Ankerwechsel sind fast immer in alle 'Richtungen' erlaubt.
+ //Ausnahme: Absatz- bzw. Zeichengebundene Rahmen duerfen wenn sie in
+ //Kopf-/Fusszeilen stehen nicht Seitengebunden werden.
+ const SwFmtAnchor &rOldAnch = rFmt.GetAnchor();
+ const RndStdIds nOld = rOldAnch.GetAnchorId();
+
+ SwFmtAnchor aNewAnch( (SwFmtAnchor&)rSet.Get( RES_ANCHOR ) );
+ RndStdIds nNew = aNewAnch.GetAnchorId();
+
+ // ist der neue ein gueltiger Anker?
+ if( !aNewAnch.GetCntntAnchor() && (FLY_AT_FLY == nNew ||
+ (FLY_AT_PARA == nNew) || (FLY_AS_CHAR == nNew) ||
+ (FLY_AT_CHAR == nNew) ))
+ {
+ return IGNOREANCHOR;
+ }
+
+ if( nOld == nNew )
+ return DONTMAKEFRMS;
+
+
+ Point aOldAnchorPos( ::lcl_FindAnchorLayPos( *this, rOldAnch, &rFmt ));
+ Point aNewAnchorPos( ::lcl_FindAnchorLayPos( *this, aNewAnch, 0 ));
+
+ //Die alten Frms vernichten. Dabei werden die Views implizit gehidet und
+ //doppeltes hiden waere so eine art Show!
+ rFmt.DelFrms();
+
+ if ( FLY_AS_CHAR == nOld )
+ {
+ //Bei InCntnt's wird es spannend: Das TxtAttribut muss vernichtet
+ //werden. Leider reisst dies neben den Frms auch noch das Format mit
+ //in sein Grab. Um dass zu unterbinden loesen wir vorher die
+ //Verbindung zwischen Attribut und Format.
+ const SwPosition *pPos = rOldAnch.GetCntntAnchor();
+ SwTxtNode *pTxtNode = pPos->nNode.GetNode().GetTxtNode();
+ OSL_ENSURE( pTxtNode->HasHints(), "Missing FlyInCnt-Hint." );
+ const xub_StrLen nIdx = pPos->nContent.GetIndex();
+ SwTxtAttr * const pHnt =
+ pTxtNode->GetTxtAttrForCharAt( nIdx, RES_TXTATR_FLYCNT );
+ OSL_ENSURE( pHnt && pHnt->Which() == RES_TXTATR_FLYCNT,
+ "Missing FlyInCnt-Hint." );
+ OSL_ENSURE( pHnt && pHnt->GetFlyCnt().GetFrmFmt() == &rFmt,
+ "Wrong TxtFlyCnt-Hint." );
+ const_cast<SwFmtFlyCnt&>(pHnt->GetFlyCnt()).SetFlyFmt();
+
+ //Die Verbindung ist geloest, jetzt muss noch das Attribut vernichtet
+ //werden.
+ pTxtNode->DeleteAttributes( RES_TXTATR_FLYCNT, nIdx, nIdx );
+ }
+
+ //Endlich kann das Attribut gesetzt werden. Es muss das erste Attribut
+ //sein; Undo depends on it!
+ rFmt.SetFmtAttr( aNewAnch );
+
+ //Positionskorrekturen
+ const SfxPoolItem* pItem;
+ switch( nNew )
+ {
+ case FLY_AS_CHAR:
+ //Wenn keine Positionsattribute hereinkommen, dann muss dafuer
+ //gesorgt werden, das keine unerlaubte automatische Ausrichtung
+ //bleibt.
+ {
+ const SwPosition *pPos = aNewAnch.GetCntntAnchor();
+ SwTxtNode *pNd = pPos->nNode.GetNode().GetTxtNode();
+ OSL_ENSURE( pNd, "Crsr steht nicht auf TxtNode." );
+
+ SwFmtFlyCnt aFmt( static_cast<SwFlyFrmFmt*>(&rFmt) );
+ pNd->InsertItem( aFmt, pPos->nContent.GetIndex(), 0 );
+ }
+
+ if( SFX_ITEM_SET != rSet.GetItemState( RES_VERT_ORIENT, sal_False, &pItem ))
+ {
+ SwFmtVertOrient aOldV( rFmt.GetVertOrient() );
+ sal_Bool bSet = sal_True;
+ switch( aOldV.GetVertOrient() )
+ {
+ case text::VertOrientation::LINE_TOP: aOldV.SetVertOrient( text::VertOrientation::TOP ); break;
+ case text::VertOrientation::LINE_CENTER: aOldV.SetVertOrient( text::VertOrientation::CENTER); break;
+ case text::VertOrientation::LINE_BOTTOM: aOldV.SetVertOrient( text::VertOrientation::BOTTOM); break;
+ case text::VertOrientation::NONE: aOldV.SetVertOrient( text::VertOrientation::CENTER); break;
+ default:
+ bSet = sal_False;
+ }
+ if( bSet )
+ rSet.Put( aOldV );
+ }
+ break;
+
+ case FLY_AT_PARA:
+ case FLY_AT_CHAR: // LAYER_IMPL
+ case FLY_AT_FLY: // LAYER_IMPL
+ case FLY_AT_PAGE:
+ {
+ //Wenn keine Positionsattribute hereinschneien korrigieren wir
+ //die Position so, dass die Dokumentkoordinaten des Flys erhalten
+ //bleiben.
+ //Chg: Wenn sich in den Positionsattributen lediglich die
+ //Ausrichtung veraendert (text::RelOrientation::FRAME vs. text::RelOrientation::PRTAREA), dann wird die
+ //Position ebenfalls korrigiert.
+ if( SFX_ITEM_SET != rSet.GetItemState( RES_HORI_ORIENT, sal_False, &pItem ))
+ pItem = 0;
+
+ SwFmtHoriOrient aOldH( rFmt.GetHoriOrient() );
+
+ if( text::HoriOrientation::NONE == aOldH.GetHoriOrient() && ( !pItem ||
+ aOldH.GetPos() == ((SwFmtHoriOrient*)pItem)->GetPos() ))
+ {
+ SwTwips nPos = (FLY_AS_CHAR == nOld) ? 0 : aOldH.GetPos();
+ nPos += aOldAnchorPos.X() - aNewAnchorPos.X();
+
+ if( pItem )
+ {
+ SwFmtHoriOrient* pH = (SwFmtHoriOrient*)pItem;
+ aOldH.SetHoriOrient( pH->GetHoriOrient() );
+ aOldH.SetRelationOrient( pH->GetRelationOrient() );
+ }
+ aOldH.SetPos( nPos );
+ rSet.Put( aOldH );
+ }
+
+ if( SFX_ITEM_SET != rSet.GetItemState( RES_VERT_ORIENT, sal_False, &pItem ))
+ pItem = 0;
+ SwFmtVertOrient aOldV( rFmt.GetVertOrient() );
+
+ // #i28922# - correction: compare <aOldV.GetVertOrient() with
+ // <text::VertOrientation::NONE>
+ if( text::VertOrientation::NONE == aOldV.GetVertOrient() && (!pItem ||
+ aOldV.GetPos() == ((SwFmtVertOrient*)pItem)->GetPos() ) )
+ {
+ SwTwips nPos = (FLY_AS_CHAR == nOld) ? 0 : aOldV.GetPos();
+ nPos += aOldAnchorPos.Y() - aNewAnchorPos.Y();
+ if( pItem )
+ {
+ SwFmtVertOrient* pV = (SwFmtVertOrient*)pItem;
+ aOldV.SetVertOrient( pV->GetVertOrient() );
+ aOldV.SetRelationOrient( pV->GetRelationOrient() );
+ }
+ aOldV.SetPos( nPos );
+ rSet.Put( aOldV );
+ }
+ }
+ break;
+ default:
+ break;
+ }
+
+ if( bNewFrms )
+ rFmt.MakeFrms();
+
+ return MAKEFRMS;
+}
+
+static bool
+lcl_SetFlyFrmAttr(SwDoc & rDoc,
+ sal_Int8 (SwDoc::*pSetFlyFrmAnchor)(SwFrmFmt &, SfxItemSet &, sal_Bool),
+ SwFrmFmt & rFlyFmt, SfxItemSet & rSet)
+{
+ // #i32968# Inserting columns in the frame causes MakeFrmFmt to put two
+ // objects of type SwUndoFrmFmt on the undo stack. We don't want them.
+ ::sw::UndoGuard const undoGuard(rDoc.GetIDocumentUndoRedo());
+
+ //Ist das Ankerattribut dabei? Falls ja ueberlassen wir die Verarbeitung
+ //desselben einer Spezialmethode. Sie Returnt sal_True wenn der Fly neu
+ //erzeugt werden muss (z.B. weil ein Wechsel des FlyTyps vorliegt).
+ sal_Int8 const nMakeFrms =
+ (SFX_ITEM_SET == rSet.GetItemState( RES_ANCHOR, sal_False ))
+ ? (rDoc.*pSetFlyFrmAnchor)( rFlyFmt, rSet, sal_False )
+ : DONTMAKEFRMS;
+
+ const SfxPoolItem* pItem;
+ SfxItemIter aIter( rSet );
+ SfxItemSet aTmpSet( rDoc.GetAttrPool(), aFrmFmtSetRange );
+ sal_uInt16 nWhich = aIter.GetCurItem()->Which();
+ do {
+ switch( nWhich )
+ {
+ case RES_FILL_ORDER:
+ case RES_BREAK:
+ case RES_PAGEDESC:
+ case RES_CNTNT:
+ case RES_FOOTER:
+ OSL_FAIL( ":-) Unbekanntes Attribut fuer Fly." );
+ // kein break;
+ case RES_CHAIN:
+ rSet.ClearItem( nWhich );
+ break;
+ case RES_ANCHOR:
+ if( DONTMAKEFRMS != nMakeFrms )
+ break;
+
+ default:
+ if( !IsInvalidItem( aIter.GetCurItem() ) && ( SFX_ITEM_SET !=
+ rFlyFmt.GetAttrSet().GetItemState( nWhich, sal_True, &pItem ) ||
+ *pItem != *aIter.GetCurItem() ))
+ aTmpSet.Put( *aIter.GetCurItem() );
+ break;
+ }
+
+ if( aIter.IsAtEnd() )
+ break;
+
+ } while( 0 != ( nWhich = aIter.NextItem()->Which() ) );
+
+ if( aTmpSet.Count() )
+ rFlyFmt.SetFmtAttr( aTmpSet );
+
+ if( MAKEFRMS == nMakeFrms )
+ rFlyFmt.MakeFrms();
+
+ return aTmpSet.Count() || MAKEFRMS == nMakeFrms;
+}
+
+sal_Bool SwDoc::SetFlyFrmAttr( SwFrmFmt& rFlyFmt, SfxItemSet& rSet )
+{
+ if( !rSet.Count() )
+ return sal_False;
+
+ ::std::auto_ptr<SwUndoFmtAttrHelper> pSaveUndo;
+
+ if (GetIDocumentUndoRedo().DoesUndo())
+ {
+ GetIDocumentUndoRedo().ClearRedo(); // AppendUndo far below, so leave it
+ pSaveUndo.reset( new SwUndoFmtAttrHelper( rFlyFmt ) );
+ }
+
+ bool const bRet =
+ lcl_SetFlyFrmAttr(*this, &SwDoc::SetFlyFrmAnchor, rFlyFmt, rSet);
+
+ if ( pSaveUndo.get() )
+ {
+ if ( pSaveUndo->GetUndo() )
+ {
+ GetIDocumentUndoRedo().AppendUndo( pSaveUndo->ReleaseUndo() );
+ }
+ }
+
+ SetModified();
+
+ return bRet;
+}
+
+// #i73249#
+void SwDoc::SetFlyFrmTitle( SwFlyFrmFmt& rFlyFrmFmt,
+ const String& sNewTitle )
+{
+ if ( rFlyFrmFmt.GetObjTitle() == sNewTitle )
+ {
+ return;
+ }
+
+ ::sw::DrawUndoGuard const drawUndoGuard(GetIDocumentUndoRedo());
+
+ if (GetIDocumentUndoRedo().DoesUndo())
+ {
+ GetIDocumentUndoRedo().AppendUndo( new SwUndoFlyStrAttr( rFlyFrmFmt,
+ UNDO_FLYFRMFMT_TITLE,
+ rFlyFrmFmt.GetObjTitle(),
+ sNewTitle ) );
+ }
+
+ rFlyFrmFmt.SetObjTitle( sNewTitle, true );
+
+ SetModified();
+}
+
+void SwDoc::SetFlyFrmDescription( SwFlyFrmFmt& rFlyFrmFmt,
+ const String& sNewDescription )
+{
+ if ( rFlyFrmFmt.GetObjDescription() == sNewDescription )
+ {
+ return;
+ }
+
+ ::sw::DrawUndoGuard const drawUndoGuard(GetIDocumentUndoRedo());
+
+ if (GetIDocumentUndoRedo().DoesUndo())
+ {
+ GetIDocumentUndoRedo().AppendUndo( new SwUndoFlyStrAttr( rFlyFrmFmt,
+ UNDO_FLYFRMFMT_DESCRIPTION,
+ rFlyFrmFmt.GetObjDescription(),
+ sNewDescription ) );
+ }
+
+ rFlyFrmFmt.SetObjDescription( sNewDescription, true );
+
+ SetModified();
+}
+
+sal_Bool SwDoc::SetFrmFmtToFly( SwFrmFmt& rFmt, SwFrmFmt& rNewFmt,
+ SfxItemSet* pSet, sal_Bool bKeepOrient )
+{
+ sal_Bool bChgAnchor = sal_False, bFrmSz = sal_False;
+
+ const SwFmtFrmSize aFrmSz( rFmt.GetFrmSize() );
+ const SwFmtVertOrient aVert( rFmt.GetVertOrient() );
+ const SwFmtHoriOrient aHori( rFmt.GetHoriOrient() );
+
+ SwUndoSetFlyFmt* pUndo = 0;
+ bool const bUndo = GetIDocumentUndoRedo().DoesUndo();
+ if (bUndo)
+ {
+ pUndo = new SwUndoSetFlyFmt( rFmt, rNewFmt );
+ GetIDocumentUndoRedo().AppendUndo(pUndo);
+ }
+
+ // #i32968# Inserting columns in the section causes MakeFrmFmt to put
+ // 2 objects of type SwUndoFrmFmt on the undo stack. We don't want them.
+ ::sw::UndoGuard const undoGuard(GetIDocumentUndoRedo());
+
+ //Erstmal die Spalten setzen, sonst gibts nix als Aerger mit dem
+ //Set/Reset/Abgleich usw.
+ const SfxPoolItem* pItem;
+ if( SFX_ITEM_SET != rNewFmt.GetAttrSet().GetItemState( RES_COL ))
+ rFmt.ResetFmtAttr( RES_COL );
+
+ if( rFmt.DerivedFrom() != &rNewFmt )
+ {
+ rFmt.SetDerivedFrom( &rNewFmt );
+
+ // 1. wenn nicht automatisch -> ignorieren, sonst -> wech
+ // 2. wech damit, MB!
+ if( SFX_ITEM_SET == rNewFmt.GetAttrSet().GetItemState( RES_FRM_SIZE, sal_False ))
+ {
+ rFmt.ResetFmtAttr( RES_FRM_SIZE );
+ bFrmSz = sal_True;
+ }
+
+ const SfxItemSet* pAsk = pSet;
+ if( !pAsk ) pAsk = &rNewFmt.GetAttrSet();
+ if( SFX_ITEM_SET == pAsk->GetItemState( RES_ANCHOR, sal_False, &pItem )
+ && ((SwFmtAnchor*)pItem)->GetAnchorId() !=
+ rFmt.GetAnchor().GetAnchorId() )
+ {
+ if( pSet )
+ bChgAnchor = MAKEFRMS == SetFlyFrmAnchor( rFmt, *pSet, sal_False );
+ else
+ {
+ //JP 23.04.98: muss den FlyFmt-Range haben, denn im SetFlyFrmAnchor
+ // werden Attribute in diesen gesetzt!
+ SfxItemSet aFlySet( *rNewFmt.GetAttrSet().GetPool(),
+ rNewFmt.GetAttrSet().GetRanges() );
+ aFlySet.Put( *pItem );
+ bChgAnchor = MAKEFRMS == SetFlyFrmAnchor( rFmt, aFlySet, sal_False);
+ }
+ }
+ }
+
+ //Hori und Vert nur dann resetten, wenn in der Vorlage eine
+ //automatische Ausrichtung eingestellt ist, anderfalls den alten Wert
+ //wieder hineinstopfen.
+ // beim Update der RahmenVorlage sollte der Fly NICHT
+ // seine Orientierng verlieren (diese wird nicht geupdatet!)
+ // text::HoriOrientation::NONE and text::VertOrientation::NONE are allowed now
+ if (!bKeepOrient)
+ {
+ rFmt.ResetFmtAttr(RES_VERT_ORIENT);
+ rFmt.ResetFmtAttr(RES_HORI_ORIENT);
+ }
+
+ rFmt.ResetFmtAttr( RES_PRINT, RES_SURROUND );
+ rFmt.ResetFmtAttr( RES_LR_SPACE, RES_UL_SPACE );
+ rFmt.ResetFmtAttr( RES_BACKGROUND, RES_COL );
+ rFmt.ResetFmtAttr( RES_URL, RES_EDIT_IN_READONLY );
+
+ if( !bFrmSz )
+ rFmt.SetFmtAttr( aFrmSz );
+
+ if( bChgAnchor )
+ rFmt.MakeFrms();
+
+ if( pUndo )
+ pUndo->DeRegisterFromFormat( rFmt );
+
+ SetModified();
+
+ return bChgAnchor;
+}
+
+void SwDoc::GetGrfNms( const SwFlyFrmFmt& rFmt, String* pGrfName,
+ String* pFltName ) const
+{
+ SwNodeIndex aIdx( *rFmt.GetCntnt().GetCntntIdx(), 1 );
+ const SwGrfNode* pGrfNd = aIdx.GetNode().GetGrfNode();
+ if( pGrfNd && pGrfNd->IsLinkedFile() )
+ pGrfNd->GetFileFilterNms( pGrfName, pFltName );
+}
+
+sal_Bool SwDoc::ChgAnchor( const SdrMarkList& _rMrkList,
+ RndStdIds _eAnchorType,
+ const sal_Bool _bSameOnly,
+ const sal_Bool _bPosCorr )
+{
+ OSL_ENSURE( GetCurrentLayout(), "Ohne Layout geht gar nichts" );
+
+ if ( !_rMrkList.GetMarkCount() ||
+ _rMrkList.GetMark( 0 )->GetMarkedSdrObj()->GetUpGroup() )
+ {
+ return false;
+ }
+
+ GetIDocumentUndoRedo().StartUndo( UNDO_INSATTR, NULL );
+
+ sal_Bool bUnmark = sal_False;
+ for ( sal_uInt16 i = 0; i < _rMrkList.GetMarkCount(); ++i )
+ {
+ SdrObject* pObj = _rMrkList.GetMark( i )->GetMarkedSdrObj();
+ if ( !pObj->ISA(SwVirtFlyDrawObj) )
+ {
+ SwDrawContact* pContact = static_cast<SwDrawContact*>(GetUserCall(pObj));
+
+ // consider, that drawing object has
+ // no user call. E.g.: a 'virtual' drawing object is disconnected by
+ // the anchor type change of the 'master' drawing object.
+ // Continue with next selected object and assert, if this isn't excepted.
+ if ( !pContact )
+ {
+#if OSL_DEBUG_LEVEL > 1
+ bool bNoUserCallExcepted =
+ pObj->ISA(SwDrawVirtObj) &&
+ !static_cast<SwDrawVirtObj*>(pObj)->IsConnected();
+ OSL_ENSURE( bNoUserCallExcepted, "SwDoc::ChgAnchor(..) - no contact at selected drawing object" );
+#endif
+ continue;
+ }
+
+ // #i26791#
+ const SwFrm* pOldAnchorFrm = pContact->GetAnchorFrm( pObj );
+ const SwFrm* pNewAnchorFrm = pOldAnchorFrm;
+
+ // #i54336#
+ // Instead of only keeping the index position for an as-character
+ // anchored object the complete <SwPosition> is kept, because the
+ // anchor index position could be moved, if the object again is
+ // anchored as character.
+ const SwPosition* pOldAsCharAnchorPos( 0L );
+ const RndStdIds eOldAnchorType = pContact->GetAnchorId();
+ if ( !_bSameOnly && eOldAnchorType == FLY_AS_CHAR )
+ {
+ pOldAsCharAnchorPos = new SwPosition( pContact->GetCntntAnchor() );
+ }
+
+ if ( _bSameOnly )
+ _eAnchorType = eOldAnchorType;
+
+ SwFmtAnchor aNewAnch( _eAnchorType );
+ Rectangle aObjRect( pContact->GetAnchoredObj( pObj )->GetObjRect().SVRect() );
+ const Point aPt( aObjRect.TopLeft() );
+
+ switch ( _eAnchorType )
+ {
+ case FLY_AT_PARA:
+ case FLY_AT_CHAR:
+ {
+ const Point aNewPoint = pOldAnchorFrm &&
+ ( pOldAnchorFrm->IsVertical() ||
+ pOldAnchorFrm->IsRightToLeft() )
+ ? aObjRect.TopRight()
+ : aPt;
+
+ // allow drawing objects in header/footer
+ pNewAnchorFrm = ::FindAnchor( pOldAnchorFrm, aNewPoint, false );
+ if ( pNewAnchorFrm->IsTxtFrm() && ((SwTxtFrm*)pNewAnchorFrm)->IsFollow() )
+ {
+ pNewAnchorFrm = ((SwTxtFrm*)pNewAnchorFrm)->FindMaster();
+ }
+ if ( pNewAnchorFrm->IsProtected() )
+ {
+ pNewAnchorFrm = 0;
+ }
+ else
+ {
+ SwPosition aPos( *((SwCntntFrm*)pNewAnchorFrm)->GetNode() );
+ aNewAnch.SetType( _eAnchorType );
+ aNewAnch.SetAnchor( &aPos );
+ }
+ }
+ break;
+
+ case FLY_AT_FLY: // LAYER_IMPL
+ {
+ //Ausgehend von der linken oberen Ecke des Fly den
+ //dichtesten SwFlyFrm suchen.
+ SwFrm *pTxtFrm;
+ {
+ SwCrsrMoveState aState( MV_SETONLYTEXT );
+ SwPosition aPos( GetNodes() );
+ Point aPoint( aPt );
+ aPoint.X() -= 1;
+ GetCurrentLayout()->GetCrsrOfst( &aPos, aPoint, &aState );
+ // consider that drawing objects can be in
+ // header/footer. Thus, <GetFrm()> by left-top-corner
+ pTxtFrm = aPos.nNode.GetNode().
+ GetCntntNode()->getLayoutFrm( GetCurrentLayout(), &aPt, 0, sal_False );
+ }
+ const SwFrm *pTmp = ::FindAnchor( pTxtFrm, aPt );
+ pNewAnchorFrm = pTmp->FindFlyFrm();
+ if( pNewAnchorFrm && !pNewAnchorFrm->IsProtected() )
+ {
+ const SwFrmFmt *pTmpFmt = ((SwFlyFrm*)pNewAnchorFrm)->GetFmt();
+ const SwFmtCntnt& rCntnt = pTmpFmt->GetCntnt();
+ SwPosition aPos( *rCntnt.GetCntntIdx() );
+ aNewAnch.SetAnchor( &aPos );
+ break;
+ }
+
+ aNewAnch.SetType( FLY_AT_PAGE );
+ // no break
+ }
+ case FLY_AT_PAGE:
+ {
+ pNewAnchorFrm = GetCurrentLayout()->Lower();
+ while ( pNewAnchorFrm && !pNewAnchorFrm->Frm().IsInside( aPt ) )
+ pNewAnchorFrm = pNewAnchorFrm->GetNext();
+ if ( !pNewAnchorFrm )
+ continue;
+
+ aNewAnch.SetPageNum( ((SwPageFrm*)pNewAnchorFrm)->GetPhyPageNum());
+ }
+ break;
+ case FLY_AS_CHAR:
+ if( _bSameOnly ) // Positions/Groessenaenderung
+ {
+ if( !pOldAnchorFrm )
+ {
+ pContact->ConnectToLayout();
+ pOldAnchorFrm = pContact->GetAnchorFrm();
+ }
+ ((SwTxtFrm*)pOldAnchorFrm)->Prepare();
+ }
+ else // Ankerwechsel
+ {
+ // allow drawing objects in header/footer
+ pNewAnchorFrm = ::FindAnchor( pOldAnchorFrm, aPt, false );
+ if( pNewAnchorFrm->IsProtected() )
+ {
+ pNewAnchorFrm = 0;
+ break;
+ }
+
+ bUnmark = ( 0 != i );
+ Point aPoint( aPt );
+ aPoint.X() -= 1; // nicht im DrawObj landen!!
+ aNewAnch.SetType( FLY_AS_CHAR );
+ SwPosition aPos( *((SwCntntFrm*)pNewAnchorFrm)->GetNode() );
+ if ( pNewAnchorFrm->Frm().IsInside( aPoint ) )
+ {
+ // es muss ein TextNode gefunden werden, denn nur dort
+ // ist ein inhaltsgebundenes DrawObjekt zu verankern
+ SwCrsrMoveState aState( MV_SETONLYTEXT );
+ GetCurrentLayout()->GetCrsrOfst( &aPos, aPoint, &aState ); //swmod 080218
+ }
+ else
+ {
+ SwCntntNode &rCNd = (SwCntntNode&)
+ *((SwCntntFrm*)pNewAnchorFrm)->GetNode();
+ if ( pNewAnchorFrm->Frm().Bottom() < aPt.Y() )
+ rCNd.MakeStartIndex( &aPos.nContent );
+ else
+ rCNd.MakeEndIndex( &aPos.nContent );
+ }
+ aNewAnch.SetAnchor( &aPos );
+ SetAttr( aNewAnch, *pContact->GetFmt() );
+ // #i26791# - adjust vertical positioning to 'center to
+ // baseline'
+ SetAttr( SwFmtVertOrient( 0, text::VertOrientation::CENTER, text::RelOrientation::FRAME ), *pContact->GetFmt() );
+ SwTxtNode *pNd = aPos.nNode.GetNode().GetTxtNode();
+ OSL_ENSURE( pNd, "Cursor not positioned at TxtNode." );
+
+ SwFmtFlyCnt aFmt( pContact->GetFmt() );
+ pNd->InsertItem( aFmt, aPos.nContent.GetIndex(), 0 );
+ }
+ break;
+ default:
+ OSL_ENSURE( !this, "unexpected AnchorId." );
+ }
+
+ if ( (FLY_AS_CHAR != _eAnchorType) &&
+ pNewAnchorFrm &&
+ ( !_bSameOnly || pNewAnchorFrm != pOldAnchorFrm ) )
+ {
+ // #i26791# - Direct object positioning no longer needed. Apply
+ // of attributes (method call <SetAttr(..)>) takes care of the
+ // invalidation of the object position.
+ SetAttr( aNewAnch, *pContact->GetFmt() );
+ if ( _bPosCorr )
+ {
+ // #i33313# - consider not connected 'virtual' drawing
+ // objects
+ if ( pObj->ISA(SwDrawVirtObj) &&
+ !static_cast<SwDrawVirtObj*>(pObj)->IsConnected() )
+ {
+ SwRect aNewObjRect( aObjRect );
+ static_cast<SwAnchoredDrawObject*>(pContact->GetAnchoredObj( 0L ))
+ ->AdjustPositioningAttr( pNewAnchorFrm,
+ &aNewObjRect );
+
+ }
+ else
+ {
+ static_cast<SwAnchoredDrawObject*>(pContact->GetAnchoredObj( pObj ))
+ ->AdjustPositioningAttr( pNewAnchorFrm );
+ }
+ }
+ }
+
+ // #i54336#
+ if ( pNewAnchorFrm && pOldAsCharAnchorPos )
+ {
+ //Bei InCntnt's wird es spannend: Das TxtAttribut muss vernichtet
+ //werden. Leider reisst dies neben den Frms auch noch das Format mit
+ //in sein Grab. Um dass zu unterbinden loesen wir vorher die
+ //Verbindung zwischen Attribut und Format.
+ const xub_StrLen nIndx( pOldAsCharAnchorPos->nContent.GetIndex() );
+ SwTxtNode* pTxtNode( pOldAsCharAnchorPos->nNode.GetNode().GetTxtNode() );
+ OSL_ENSURE( pTxtNode, "<SwDoc::ChgAnchor(..)> - missing previous anchor text node for as-character anchored object" );
+ OSL_ENSURE( pTxtNode->HasHints(), "Missing FlyInCnt-Hint." );
+ SwTxtAttr * const pHnt =
+ pTxtNode->GetTxtAttrForCharAt( nIndx, RES_TXTATR_FLYCNT );
+ const_cast<SwFmtFlyCnt&>(pHnt->GetFlyCnt()).SetFlyFmt();
+
+ //Die Verbindung ist geloest, jetzt muss noch das Attribut vernichtet
+ //werden.
+ pTxtNode->DeleteAttributes( RES_TXTATR_FLYCNT, nIndx, nIndx );
+ delete pOldAsCharAnchorPos;
+ }
+ }
+ }
+
+ GetIDocumentUndoRedo().EndUndo( UNDO_END, NULL );
+ SetModified();
+
+ return bUnmark;
+}
+
+int SwDoc::Chainable( const SwFrmFmt &rSource, const SwFrmFmt &rDest )
+{
+ //Die Source darf noch keinen Follow haben.
+ const SwFmtChain &rOldChain = rSource.GetChain();
+ if ( rOldChain.GetNext() )
+ return SW_CHAIN_SOURCE_CHAINED;
+
+ //Ziel darf natuerlich nicht gleich Source sein und es
+ //darf keine geschlossene Kette entstehen.
+ const SwFrmFmt *pFmt = &rDest;
+ do {
+ if( pFmt == &rSource )
+ return SW_CHAIN_SELF;
+ pFmt = pFmt->GetChain().GetNext();
+ } while ( pFmt );
+
+ //Auch eine Verkettung von Innen nach aussen oder von aussen
+ //nach innen ist nicht zulaessig.
+ if( rDest.IsLowerOf( rSource ) || rSource .IsLowerOf( rDest ) )
+ return SW_CHAIN_SELF;
+
+ //Das Ziel darf noch keinen Master haben.
+ const SwFmtChain &rChain = rDest.GetChain();
+ if( rChain.GetPrev() )
+ return SW_CHAIN_IS_IN_CHAIN;
+
+ //Das Ziel muss leer sein.
+ const SwNodeIndex* pCntIdx = rDest.GetCntnt().GetCntntIdx();
+ if( !pCntIdx )
+ return SW_CHAIN_NOT_FOUND;
+
+ SwNodeIndex aNxtIdx( *pCntIdx, 1 );
+ const SwTxtNode* pTxtNd = aNxtIdx.GetNode().GetTxtNode();
+ if( !pTxtNd )
+ return SW_CHAIN_NOT_FOUND;
+
+ const sal_uLong nFlySttNd = pCntIdx->GetIndex();
+ if( 2 != ( pCntIdx->GetNode().EndOfSectionIndex() - nFlySttNd ) ||
+ pTxtNd->GetTxt().Len() )
+ return SW_CHAIN_NOT_EMPTY;
+
+ sal_uInt16 nArrLen = GetSpzFrmFmts()->Count();
+ for( sal_uInt16 n = 0; n < nArrLen; ++n )
+ {
+ const SwFmtAnchor& rAnchor = (*GetSpzFrmFmts())[ n ]->GetAnchor();
+ sal_uLong nTstSttNd;
+ // #i20622# - to-frame anchored objects are allowed.
+ if ( ((rAnchor.GetAnchorId() == FLY_AT_PARA) ||
+ (rAnchor.GetAnchorId() == FLY_AT_CHAR)) &&
+ 0 != rAnchor.GetCntntAnchor() &&
+ nFlySttNd <= ( nTstSttNd =
+ rAnchor.GetCntntAnchor()->nNode.GetIndex() ) &&
+ nTstSttNd < nFlySttNd + 2 )
+ {
+ return SW_CHAIN_NOT_EMPTY;
+ }
+ }
+
+ //Auf die richtige Area muessen wir auch noch einen Blick werfen.
+ //Beide Flys muessen im selben Bereich (Body, Head/Foot, Fly) sitzen
+ //Wenn die Source nicht der selektierte Rahmen ist, so reicht es
+ //Wenn ein passender gefunden wird (Der Wunsch kann z.B. von der API
+ //kommen).
+
+ // both in the same fly, header, footer or on the page?
+ const SwFmtAnchor &rSrcAnchor = rSource.GetAnchor(),
+ &rDstAnchor = rDest.GetAnchor();
+ sal_uLong nEndOfExtras = GetNodes().GetEndOfExtras().GetIndex();
+ sal_Bool bAllowed = sal_False;
+ if ( FLY_AT_PAGE == rSrcAnchor.GetAnchorId() )
+ {
+ if ( (FLY_AT_PAGE == rDstAnchor.GetAnchorId()) ||
+ ( rDstAnchor.GetCntntAnchor() &&
+ rDstAnchor.GetCntntAnchor()->nNode.GetIndex() > nEndOfExtras ))
+ bAllowed = sal_True;
+ }
+ else if( rSrcAnchor.GetCntntAnchor() && rDstAnchor.GetCntntAnchor() )
+ {
+ const SwNodeIndex &rSrcIdx = rSrcAnchor.GetCntntAnchor()->nNode,
+ &rDstIdx = rDstAnchor.GetCntntAnchor()->nNode;
+ const SwStartNode* pSttNd = 0;
+ if( rSrcIdx == rDstIdx ||
+ ( !pSttNd &&
+ 0 != ( pSttNd = rSrcIdx.GetNode().FindFlyStartNode() ) &&
+ pSttNd == rDstIdx.GetNode().FindFlyStartNode() ) ||
+ ( !pSttNd &&
+ 0 != ( pSttNd = rSrcIdx.GetNode().FindFooterStartNode() ) &&
+ pSttNd == rDstIdx.GetNode().FindFooterStartNode() ) ||
+ ( !pSttNd &&
+ 0 != ( pSttNd = rSrcIdx.GetNode().FindHeaderStartNode() ) &&
+ pSttNd == rDstIdx.GetNode().FindHeaderStartNode() ) ||
+ ( !pSttNd && rDstIdx.GetIndex() > nEndOfExtras &&
+ rSrcIdx.GetIndex() > nEndOfExtras ))
+ bAllowed = sal_True;
+ }
+
+ return bAllowed ? SW_CHAIN_OK : SW_CHAIN_WRONG_AREA;
+}
+
+int SwDoc::Chain( SwFrmFmt &rSource, const SwFrmFmt &rDest )
+{
+ int nErr = Chainable( rSource, rDest );
+ if ( !nErr )
+ {
+ GetIDocumentUndoRedo().StartUndo( UNDO_CHAINE, NULL );
+
+ SwFlyFrmFmt& rDestFmt = (SwFlyFrmFmt&)rDest;
+
+ //Follow an den Master haengen.
+ SwFmtChain aChain = rDestFmt.GetChain();
+ aChain.SetPrev( &(SwFlyFrmFmt&)rSource );
+ SetAttr( aChain, rDestFmt );
+
+ SfxItemSet aSet( GetAttrPool(), RES_FRM_SIZE, RES_FRM_SIZE,
+ RES_CHAIN, RES_CHAIN, 0 );
+
+ //Follow an den Master haengen.
+ aChain.SetPrev( &(SwFlyFrmFmt&)rSource );
+ SetAttr( aChain, rDestFmt );
+
+ //Master an den Follow haengen und dafuer sorgen, dass der Master
+ //eine fixierte Hoehe hat.
+ aChain = rSource.GetChain();
+ aChain.SetNext( &rDestFmt );
+ aSet.Put( aChain );
+
+ SwFmtFrmSize aSize( rSource.GetFrmSize() );
+ if ( aSize.GetHeightSizeType() != ATT_FIX_SIZE )
+ {
+ SwFlyFrm *pFly = SwIterator<SwFlyFrm,SwFmt>::FirstElement( rSource );
+ if ( pFly )
+ aSize.SetHeight( pFly->Frm().Height() );
+ aSize.SetHeightSizeType( ATT_FIX_SIZE );
+ aSet.Put( aSize );
+ }
+ SetAttr( aSet, rSource );
+
+ GetIDocumentUndoRedo().EndUndo( UNDO_CHAINE, NULL );
+ }
+ return nErr;
+}
+
+void SwDoc::Unchain( SwFrmFmt &rFmt )
+{
+ SwFmtChain aChain( rFmt.GetChain() );
+ if ( aChain.GetNext() )
+ {
+ GetIDocumentUndoRedo().StartUndo( UNDO_UNCHAIN, NULL );
+ SwFrmFmt *pFollow = aChain.GetNext();
+ aChain.SetNext( 0 );
+ SetAttr( aChain, rFmt );
+ aChain = pFollow->GetChain();
+ aChain.SetPrev( 0 );
+ SetAttr( aChain, *pFollow );
+ GetIDocumentUndoRedo().EndUndo( UNDO_UNCHAIN, NULL );
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/doc/docfmt.cxx b/sw/source/core/doc/docfmt.cxx
new file mode 100644
index 000000000000..bc6c1e6f3e16
--- /dev/null
+++ b/sw/source/core/doc/docfmt.cxx
@@ -0,0 +1,2600 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+
+#define _ZFORLIST_DECLARE_TABLE
+#define _SVSTDARR_USHORTSSORT
+#define _SVSTDARR_USHORTS
+#include <hintids.hxx>
+#include <rtl/logfile.hxx>
+#include <svl/itemiter.hxx>
+#include <sfx2/app.hxx>
+#include <editeng/tstpitem.hxx>
+#include <editeng/eeitem.hxx>
+#include <editeng/langitem.hxx>
+#include <editeng/lrspitem.hxx>
+#include <editeng/brkitem.hxx>
+#include <svl/whiter.hxx>
+#ifndef _ZFORLIST_HXX //autogen
+#include <svl/zforlist.hxx>
+#endif
+#include <comphelper/processfactory.hxx>
+#include <unotools/misccfg.hxx>
+#include <com/sun/star/i18n/WordType.hdl>
+#include <fmtpdsc.hxx>
+#include <fmthdft.hxx>
+#include <fmtcntnt.hxx>
+#include <frmatr.hxx>
+#include <doc.hxx>
+#include <IDocumentUndoRedo.hxx>
+#include <rootfrm.hxx>
+#include <pagefrm.hxx>
+#include <hints.hxx> // fuer SwHyphenBug (in SetDefault)
+#include <ndtxt.hxx>
+#include <pam.hxx>
+#include <UndoCore.hxx>
+#include <UndoAttribute.hxx>
+#include <ndgrf.hxx>
+#include <pagedesc.hxx> // Fuer Sonderbehandlung in InsFrmFmt
+#include <rolbck.hxx> // Undo-Attr
+#include <mvsave.hxx> // servieren: Veraenderungen erkennen
+#include <txatbase.hxx>
+#include <swtable.hxx>
+#include <swtblfmt.hxx>
+#include <charfmt.hxx>
+#include <docary.hxx>
+#include <paratr.hxx>
+#include <redline.hxx>
+#include <reffld.hxx>
+#include <txtinet.hxx>
+#include <fmtinfmt.hxx>
+#include <breakit.hxx>
+#include <SwStyleNameMapper.hxx>
+#include <fmtautofmt.hxx>
+#include <istyleaccess.hxx>
+#include <SwUndoFmt.hxx>
+#include <docsh.hxx>
+
+using namespace ::com::sun::star::i18n;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star::uno;
+
+SV_IMPL_PTRARR(SwFrmFmts,SwFrmFmtPtr)
+SV_IMPL_PTRARR(SwCharFmts,SwCharFmtPtr)
+
+//Spezifische Frameformate (Rahmen)
+SV_IMPL_PTRARR(SwSpzFrmFmts,SwFrmFmtPtr)
+
+/*
+ * interne Funktionen
+ */
+
+sal_Bool SetTxtFmtCollNext( const SwTxtFmtCollPtr& rpTxtColl, void* pArgs )
+{
+ SwTxtFmtColl *pDel = (SwTxtFmtColl*) pArgs;
+ if ( &rpTxtColl->GetNextTxtFmtColl() == pDel )
+ {
+ rpTxtColl->SetNextTxtFmtColl( *rpTxtColl );
+ }
+ return sal_True;
+}
+
+/*
+ * Zuruecksetzen der harten Formatierung fuer Text
+ */
+
+// Uebergabeparameter fuer _Rst und lcl_SetTxtFmtColl
+struct ParaRstFmt
+{
+ SwFmtColl* pFmtColl;
+ SwHistory* pHistory;
+ const SwPosition *pSttNd, *pEndNd;
+ const SfxItemSet* pDelSet;
+ sal_uInt16 nWhich;
+ bool bReset;
+ bool bResetListAttrs; // #i62575#
+ bool bResetAll;
+ bool bInclRefToxMark;
+
+ bool bKeepOutlineLevelAttr;
+
+ ParaRstFmt( const SwPosition* pStt, const SwPosition* pEnd,
+ SwHistory* pHst, sal_uInt16 nWhch = 0, const SfxItemSet* pSet = 0 )
+ : pFmtColl(0),
+ pHistory(pHst),
+ pSttNd(pStt),
+ pEndNd(pEnd),
+ pDelSet(pSet),
+ nWhich(nWhch),
+ bReset( false ), // #i62675#
+ bResetListAttrs( false ),
+ bResetAll( true ),
+ bInclRefToxMark( false ),
+ bKeepOutlineLevelAttr( false )
+ {}
+
+ ParaRstFmt( SwHistory* pHst )
+ : pFmtColl(0),
+ pHistory(pHst),
+ pSttNd(0),
+ pEndNd(0),
+ pDelSet(0),
+ nWhich(0),
+ bReset( false ),
+ bResetListAttrs( false ), // #i62675#
+ bResetAll( true ),
+ bInclRefToxMark( false ),
+ bKeepOutlineLevelAttr( false )
+ {}
+};
+
+/* in pArgs steht die ChrFmtTablle vom Dokument
+ * (wird bei Selectionen am Start/Ende und bei keiner SSelection benoetigt)
+ */
+
+sal_Bool lcl_RstTxtAttr( const SwNodePtr& rpNd, void* pArgs )
+{
+ ParaRstFmt* pPara = (ParaRstFmt*)pArgs;
+ SwTxtNode * pTxtNode = (SwTxtNode*)rpNd->GetTxtNode();
+ if( pTxtNode && pTxtNode->GetpSwpHints() )
+ {
+ SwIndex aSt( pTxtNode, 0 );
+ sal_uInt16 nEnd = pTxtNode->Len();
+
+ if( &pPara->pSttNd->nNode.GetNode() == pTxtNode &&
+ pPara->pSttNd->nContent.GetIndex() )
+ aSt = pPara->pSttNd->nContent.GetIndex();
+
+ if( &pPara->pEndNd->nNode.GetNode() == rpNd )
+ nEnd = pPara->pEndNd->nContent.GetIndex();
+
+ if( pPara->pHistory )
+ {
+ // fuers Undo alle Attribute sichern
+ SwRegHistory aRHst( *pTxtNode, pPara->pHistory );
+ pTxtNode->GetpSwpHints()->Register( &aRHst );
+ pTxtNode->RstAttr( aSt, nEnd - aSt.GetIndex(), pPara->nWhich,
+ pPara->pDelSet, pPara->bInclRefToxMark );
+ if( pTxtNode->GetpSwpHints() )
+ pTxtNode->GetpSwpHints()->DeRegister();
+ }
+ else
+ pTxtNode->RstAttr( aSt, nEnd - aSt.GetIndex(), pPara->nWhich,
+ pPara->pDelSet, pPara->bInclRefToxMark );
+ }
+ return sal_True;
+}
+
+sal_Bool lcl_RstAttr( const SwNodePtr& rpNd, void* pArgs )
+{
+ ParaRstFmt* pPara = (ParaRstFmt*)pArgs;
+ SwCntntNode* pNode = (SwCntntNode*)rpNd->GetCntntNode();
+ if( pNode && pNode->HasSwAttrSet() )
+ {
+ const sal_Bool bLocked = pNode->IsModifyLocked();
+ pNode->LockModify();
+
+ SwDoc* pDoc = pNode->GetDoc();
+
+ // remove unused attribute RES_LR_SPACE
+ // add list attributes
+ SfxItemSet aSet( pDoc->GetAttrPool(),
+ RES_PAGEDESC, RES_BREAK,
+ RES_PARATR_NUMRULE, RES_PARATR_NUMRULE,
+ RES_PARATR_OUTLINELEVEL,RES_PARATR_OUTLINELEVEL,//#outline level,removed by zhaojianwei
+ RES_PARATR_LIST_BEGIN, RES_PARATR_LIST_END - 1,
+ 0 );
+ const SfxItemSet* pSet = pNode->GetpSwAttrSet();
+
+ SvUShorts aClearWhichIds;
+ // restoring all paragraph list attributes
+ {
+ SfxItemSet aListAttrSet( pDoc->GetAttrPool(),
+ RES_PARATR_LIST_BEGIN, RES_PARATR_LIST_END - 1,
+ 0 );
+ aListAttrSet.Set( *pSet );
+ if ( aListAttrSet.Count() )
+ {
+ aSet.Put( aListAttrSet );
+ SfxItemIter aIter( aListAttrSet );
+ const SfxPoolItem* pItem = aIter.GetCurItem();
+ while( pItem )
+ {
+ aClearWhichIds.Insert( pItem->Which(), aClearWhichIds.Count() );
+ pItem = aIter.NextItem();
+ }
+ }
+ }
+
+ const SfxPoolItem* pItem;
+
+ sal_uInt16 const aSavIds[ 4 ] = { RES_PAGEDESC, RES_BREAK, //->add by zhaojianwei
+ RES_PARATR_NUMRULE,
+ RES_PARATR_OUTLINELEVEL };
+ for( sal_uInt16 n = 0; n < 4; ++n ) //<-end,zhaojianwei
+ {
+ if( SFX_ITEM_SET == pSet->GetItemState( aSavIds[ n ], sal_False, &pItem ))
+ {
+ bool bSave = false;
+ switch( aSavIds[ n ] )
+ {
+ case RES_PAGEDESC:
+ bSave = 0 != ((SwFmtPageDesc*)pItem)->GetPageDesc();
+ break;
+ case RES_BREAK:
+ bSave = SVX_BREAK_NONE != ((SvxFmtBreakItem*)pItem)->GetBreak();
+ break;
+ case RES_PARATR_NUMRULE:
+ {
+ bSave = 0 != ((SwNumRuleItem*)pItem)->GetValue().Len();
+ }
+ break;
+ case RES_PARATR_OUTLINELEVEL: //#outline level,add by zhaojianwei
+ {
+ bSave = pPara && pPara->bKeepOutlineLevelAttr;
+ }
+ break; //<-end,zhaojianwei
+ }
+ if( bSave )
+ {
+ aSet.Put( *pItem );
+ aClearWhichIds.Insert( aSavIds[n], aClearWhichIds.Count() );
+ }
+ }
+ }
+
+ // do not clear items directly from item set and only clear to be kept
+ // attributes, if no deletion item set is found.
+ const bool bKeepAttributes =
+ !pPara || !pPara->pDelSet || pPara->pDelSet->Count() == 0;
+ if ( bKeepAttributes )
+ {
+ pNode->ResetAttr( aClearWhichIds );
+ }
+
+ if( !bLocked )
+ pNode->UnlockModify();
+
+ if( pPara )
+ {
+ SwRegHistory aRegH( pNode, *pNode, pPara->pHistory );
+
+ if( pPara->pDelSet && pPara->pDelSet->Count() )
+ {
+ OSL_ENSURE( !bKeepAttributes,
+ "<lcl_RstAttr(..)> - certain attributes are kept, but not needed. -> please inform OD" );
+ SfxItemIter aIter( *pPara->pDelSet );
+ pItem = aIter.FirstItem();
+ while( sal_True )
+ {
+ if ( ( pItem->Which() != RES_PAGEDESC &&
+ pItem->Which() != RES_BREAK &&
+ pItem->Which() != RES_PARATR_NUMRULE ) ||
+ ( aSet.GetItemState( pItem->Which(), sal_False ) != SFX_ITEM_SET ) )
+ {
+ pNode->ResetAttr( pItem->Which() );
+ }
+ if( aIter.IsAtEnd() )
+ break;
+ pItem = aIter.NextItem();
+ }
+ }
+ else if( pPara->bResetAll )
+ pNode->ResetAllAttr();
+ else
+ pNode->ResetAttr( RES_PARATR_BEGIN, POOLATTR_END - 1 );
+ }
+ else
+ pNode->ResetAllAttr();
+
+ // only restore saved attributes, if needed
+ if ( bKeepAttributes && aSet.Count() )
+ {
+ pNode->LockModify();
+
+ pNode->SetAttr( aSet );
+
+ if( !bLocked )
+ pNode->UnlockModify();
+ }
+ }
+ return sal_True;
+}
+
+void SwDoc::RstTxtAttrs(const SwPaM &rRg, sal_Bool bInclRefToxMark )
+{
+ SwHistory* pHst = 0;
+ SwDataChanged aTmp( rRg, 0 );
+ if (GetIDocumentUndoRedo().DoesUndo())
+ {
+ SwUndoResetAttr* pUndo = new SwUndoResetAttr( rRg, RES_CHRFMT );
+ pHst = &pUndo->GetHistory();
+ GetIDocumentUndoRedo().AppendUndo(pUndo);
+ }
+ const SwPosition *pStt = rRg.Start(), *pEnd = rRg.End();
+ ParaRstFmt aPara( pStt, pEnd, pHst );
+ aPara.bInclRefToxMark = ( bInclRefToxMark == sal_True );
+ GetNodes().ForEach( pStt->nNode.GetIndex(), pEnd->nNode.GetIndex()+1,
+ lcl_RstTxtAttr, &aPara );
+ SetModified();
+}
+
+void SwDoc::ResetAttrs( const SwPaM &rRg,
+ sal_Bool bTxtAttr,
+ const SvUShortsSort* pAttrs,
+ const bool bSendDataChangedEvents )
+{
+ SwPaM* pPam = (SwPaM*)&rRg;
+ if( !bTxtAttr && pAttrs && pAttrs->Count() &&
+ RES_TXTATR_END > (*pAttrs)[ 0 ] )
+ bTxtAttr = sal_True;
+
+ if( !rRg.HasMark() )
+ {
+ SwTxtNode* pTxtNd = rRg.GetPoint()->nNode.GetNode().GetTxtNode();
+ if( !pTxtNd )
+ return ;
+
+ pPam = new SwPaM( *rRg.GetPoint() );
+
+ SwIndex& rSt = pPam->GetPoint()->nContent;
+ sal_uInt16 nMkPos, nPtPos = rSt.GetIndex();
+
+ // JP 22.08.96: Sonderfall: steht der Crsr in einem URL-Attribut
+ // dann wird dessen Bereich genommen
+ SwTxtAttr const*const pURLAttr(
+ pTxtNd->GetTxtAttrAt(rSt.GetIndex(), RES_TXTATR_INETFMT));
+ if (pURLAttr && pURLAttr->GetINetFmt().GetValue().Len())
+ {
+ nMkPos = *pURLAttr->GetStart();
+ nPtPos = *pURLAttr->GetEnd();
+ }
+ else
+ {
+ Boundary aBndry;
+ if( pBreakIt->GetBreakIter().is() )
+ aBndry = pBreakIt->GetBreakIter()->getWordBoundary(
+ pTxtNd->GetTxt(), nPtPos,
+ pBreakIt->GetLocale( pTxtNd->GetLang( nPtPos ) ),
+ WordType::ANY_WORD /*ANYWORD_IGNOREWHITESPACES*/,
+ sal_True );
+
+ if( aBndry.startPos < nPtPos && nPtPos < aBndry.endPos )
+ {
+ nMkPos = (xub_StrLen)aBndry.startPos;
+ nPtPos = (xub_StrLen)aBndry.endPos;
+ }
+ else
+ {
+ nPtPos = nMkPos = rSt.GetIndex();
+ if( bTxtAttr )
+ pTxtNd->DontExpandFmt( rSt, sal_True );
+ }
+ }
+
+ rSt = nMkPos;
+ pPam->SetMark();
+ pPam->GetPoint()->nContent = nPtPos;
+ }
+
+ // #i96644#
+// SwDataChanged aTmp( *pPam, 0 );
+ std::auto_ptr< SwDataChanged > pDataChanged;
+ if ( bSendDataChangedEvents )
+ {
+ pDataChanged.reset( new SwDataChanged( *pPam, 0 ) );
+ }
+ SwHistory* pHst = 0;
+ if (GetIDocumentUndoRedo().DoesUndo())
+ {
+ SwUndoResetAttr* pUndo = new SwUndoResetAttr( rRg,
+ static_cast<sal_uInt16>(bTxtAttr ? RES_CONDTXTFMTCOLL : RES_TXTFMTCOLL ));
+ if( pAttrs && pAttrs->Count() )
+ {
+ pUndo->SetAttrs( *pAttrs );
+ }
+ pHst = &pUndo->GetHistory();
+ GetIDocumentUndoRedo().AppendUndo(pUndo);
+ }
+
+ const SwPosition *pStt = pPam->Start(), *pEnd = pPam->End();
+ ParaRstFmt aPara( pStt, pEnd, pHst );
+
+ // mst: not including META here; it seems attrs with CH_TXTATR are omitted
+ sal_uInt16 aResetableSetRange[] = {
+ RES_FRMATR_BEGIN, RES_FRMATR_END-1,
+ RES_CHRATR_BEGIN, RES_CHRATR_END-1,
+ RES_PARATR_BEGIN, RES_PARATR_END-1,
+ RES_PARATR_LIST_BEGIN, RES_PARATR_LIST_END-1,
+ RES_TXTATR_INETFMT, RES_TXTATR_INETFMT,
+ RES_TXTATR_CHARFMT, RES_TXTATR_CHARFMT,
+ RES_TXTATR_CJK_RUBY, RES_TXTATR_CJK_RUBY,
+ RES_TXTATR_UNKNOWN_CONTAINER, RES_TXTATR_UNKNOWN_CONTAINER,
+ RES_UNKNOWNATR_BEGIN, RES_UNKNOWNATR_END-1,
+ 0
+ };
+
+ SfxItemSet aDelSet( GetAttrPool(), aResetableSetRange );
+ if( pAttrs && pAttrs->Count() )
+ {
+ for( sal_uInt16 n = pAttrs->Count(); n; )
+ if( POOLATTR_END > (*pAttrs)[ --n ] )
+ aDelSet.Put( *GetDfltAttr( (*pAttrs)[ n ] ));
+
+ if( aDelSet.Count() )
+ aPara.pDelSet = &aDelSet;
+ }
+
+ sal_Bool bAdd = sal_True;
+ SwNodeIndex aTmpStt( pStt->nNode );
+ SwNodeIndex aTmpEnd( pEnd->nNode );
+ if( pStt->nContent.GetIndex() ) // nur ein Teil
+ {
+ // dann spaeter aufsetzen und alle CharFmtAttr -> TxtFmtAttr
+ SwTxtNode* pTNd = aTmpStt.GetNode().GetTxtNode();
+ if( pTNd && pTNd->HasSwAttrSet() && pTNd->GetpSwAttrSet()->Count() )
+ {
+ SfxItemIter aIter( *pTNd->GetpSwAttrSet() );
+ const SfxPoolItem* pItem = aIter.GetCurItem();
+ SfxItemSet aCharSet( GetAttrPool(), RES_CHRATR_BEGIN, RES_CHRATR_END );
+
+ while( sal_True )
+ {
+ if( IsInRange( aCharFmtSetRange, pItem->Which() ))
+ {
+ pTNd->GetOrCreateSwpHints();
+
+ aCharSet.Put( *pItem );
+
+ if( pHst )
+ {
+ SwRegHistory aRegH( pTNd, *pTNd, pHst );
+ pTNd->ResetAttr( pItem->Which() );
+ }
+ else
+ pTNd->ResetAttr( pItem->Which() );
+ }
+ if( aIter.IsAtEnd() )
+ break;
+ pItem = aIter.NextItem();
+ }
+
+ if ( aCharSet.Count() )
+ {
+ if ( pHst )
+ {
+ SwRegHistory history( pTNd, *pTNd, pHst );
+ history.InsertItems( aCharSet, 0, pTNd->GetTxt().Len(),
+ nsSetAttrMode::SETATTR_NOFORMATATTR );
+ }
+ else
+ {
+ SwTxtAttr* pNew =
+ MakeTxtAttr( *this, aCharSet, 0, pTNd->GetTxt().Len() );
+ pTNd->InsertHint( pNew );
+ }
+ }
+ }
+
+ aTmpStt++;
+ }
+ if( pEnd->nContent.GetIndex() == pEnd->nNode.GetNode().GetCntntNode()->Len() )
+ // dann spaeter aufsetzen und alle CharFmtAttr -> TxtFmtAttr
+ aTmpEnd++, bAdd = sal_False;
+ else if( pStt->nNode != pEnd->nNode || !pStt->nContent.GetIndex() )
+ {
+ SwTxtNode* pTNd = aTmpEnd.GetNode().GetTxtNode();
+ if( pTNd && pTNd->HasSwAttrSet() && pTNd->GetpSwAttrSet()->Count() )
+ {
+ SfxItemIter aIter( *pTNd->GetpSwAttrSet() );
+ const SfxPoolItem* pItem = aIter.GetCurItem();
+ while( sal_True )
+ {
+ if( IsInRange( aCharFmtSetRange, pItem->Which() ))
+ {
+ SwTxtAttr* pTAttr = MakeTxtAttr( *this,
+ const_cast<SfxPoolItem&>(*pItem),
+ 0, pTNd->GetTxt().Len() );
+ SwpHints & rHints = pTNd->GetOrCreateSwpHints();
+ rHints.SwpHintsArray::Insert( pTAttr );
+ if ( pHst )
+ {
+ SwRegHistory aRegH( pTNd, *pTNd, pHst );
+ pTNd->ResetAttr( pItem->Which() );
+ pHst->Add( pTAttr, aTmpEnd.GetIndex(), true );
+ }
+ else
+ pTNd->ResetAttr( pItem->Which() );
+ }
+ if( aIter.IsAtEnd() )
+ break;
+ pItem = aIter.NextItem();
+ }
+ }
+ }
+
+ if( aTmpStt < aTmpEnd )
+ GetNodes().ForEach( pStt->nNode, aTmpEnd, lcl_RstAttr, &aPara );
+ else if( !rRg.HasMark() )
+ {
+ aPara.bResetAll = false ;
+ ::lcl_RstAttr( &pStt->nNode.GetNode(), &aPara );
+ aPara.bResetAll = true ;
+ }
+
+ if( bTxtAttr )
+ {
+ if( bAdd )
+ aTmpEnd++;
+ GetNodes().ForEach( pStt->nNode, aTmpEnd, lcl_RstTxtAttr, &aPara );
+ }
+
+ if( pPam != &rRg )
+ delete pPam;
+
+ SetModified();
+}
+
+#define DELETECHARSETS if ( bDelete ) { delete pCharSet; delete pOtherSet; }
+
+// Einfuegen der Hints nach Inhaltsformen;
+// wird in SwDoc::Insert(..., SwFmtHint &rHt) benutzt
+
+static bool
+lcl_InsAttr(SwDoc *const pDoc, const SwPaM &rRg, const SfxItemSet& rChgSet,
+ const SetAttrMode nFlags, SwUndoAttr *const pUndo)
+{
+ // teil die Sets auf (fuer Selektion in Nodes)
+ const SfxItemSet* pCharSet = 0;
+ const SfxItemSet* pOtherSet = 0;
+ bool bDelete = false;
+ bool bCharAttr = false;
+ bool bOtherAttr = false;
+
+ // Check, if we can work with rChgSet or if we have to create additional SfxItemSets
+ if ( 1 == rChgSet.Count() )
+ {
+ SfxItemIter aIter( rChgSet );
+ const SfxPoolItem* pItem = aIter.FirstItem();
+ const sal_uInt16 nWhich = pItem->Which();
+
+ if ( isCHRATR(nWhich) ||
+ (RES_TXTATR_CHARFMT == nWhich) ||
+ (RES_TXTATR_INETFMT == nWhich) ||
+ (RES_TXTATR_AUTOFMT == nWhich) ||
+ (RES_TXTATR_UNKNOWN_CONTAINER == nWhich) )
+ {
+ pCharSet = &rChgSet;
+ bCharAttr = true;
+ }
+
+ if ( isPARATR(nWhich)
+ || isPARATR_LIST(nWhich)
+ || isFRMATR(nWhich)
+ || isGRFATR(nWhich)
+ || isUNKNOWNATR(nWhich) )
+ {
+ pOtherSet = &rChgSet;
+ bOtherAttr = true;
+ }
+ }
+
+ // Build new itemset if either
+ // - rChgSet.Count() > 1 or
+ // - The attribute in rChgSet does not belong to one of the above categories
+ if ( !bCharAttr && !bOtherAttr )
+ {
+ SfxItemSet* pTmpCharItemSet = new SfxItemSet( pDoc->GetAttrPool(),
+ RES_CHRATR_BEGIN, RES_CHRATR_END-1,
+ RES_TXTATR_AUTOFMT, RES_TXTATR_AUTOFMT,
+ RES_TXTATR_INETFMT, RES_TXTATR_INETFMT,
+ RES_TXTATR_CHARFMT, RES_TXTATR_CHARFMT,
+ RES_TXTATR_UNKNOWN_CONTAINER, RES_TXTATR_UNKNOWN_CONTAINER,
+ 0 );
+
+ SfxItemSet* pTmpOtherItemSet = new SfxItemSet( pDoc->GetAttrPool(),
+ RES_PARATR_BEGIN, RES_PARATR_END-1,
+ RES_PARATR_LIST_BEGIN, RES_PARATR_LIST_END-1,
+ RES_FRMATR_BEGIN, RES_FRMATR_END-1,
+ RES_GRFATR_BEGIN, RES_GRFATR_END-1,
+ RES_UNKNOWNATR_BEGIN, RES_UNKNOWNATR_END-1,
+ 0 );
+
+ pTmpCharItemSet->Put( rChgSet );
+ pTmpOtherItemSet->Put( rChgSet );
+
+ pCharSet = pTmpCharItemSet;
+ pOtherSet = pTmpOtherItemSet;
+
+ bDelete = true;
+ }
+
+ SwHistory* pHistory = pUndo ? &pUndo->GetHistory() : 0;
+ bool bRet = false;
+ const SwPosition *pStt = rRg.Start(), *pEnd = rRg.End();
+ SwCntntNode* pNode = pStt->nNode.GetNode().GetCntntNode();
+
+ if( pNode && pNode->IsTxtNode() )
+ {
+ // #i27615#
+ if (rRg.IsInFrontOfLabel())
+ {
+ SwTxtNode * pTxtNd = pNode->GetTxtNode();
+ SwNumRule * pNumRule = pTxtNd->GetNumRule();
+
+ // make code robust:
+ if ( !pNumRule )
+ {
+ OSL_FAIL( "<InsAttr(..)> - PaM in front of label, but text node has no numbering rule set. This is a serious defect, please inform OD." );
+ DELETECHARSETS
+ return false;
+ }
+
+ SwNumFmt aNumFmt = pNumRule->Get(static_cast<sal_uInt16>(pTxtNd->GetActualListLevel()));
+ SwCharFmt * pCharFmt =
+ pDoc->FindCharFmtByName(aNumFmt.GetCharFmtName());
+
+ if (pCharFmt)
+ {
+ if (pHistory)
+ pHistory->Add(pCharFmt->GetAttrSet(), *pCharFmt);
+
+ if ( pCharSet )
+ pCharFmt->SetFmtAttr(*pCharSet);
+ }
+
+ DELETECHARSETS
+ return true;
+ }
+
+ const SwIndex& rSt = pStt->nContent;
+
+ // Attribute ohne Ende haben keinen Bereich
+ if ( !bCharAttr && !bOtherAttr )
+ {
+ SfxItemSet aTxtSet( pDoc->GetAttrPool(),
+ RES_TXTATR_NOEND_BEGIN, RES_TXTATR_NOEND_END-1 );
+ aTxtSet.Put( rChgSet );
+ if( aTxtSet.Count() )
+ {
+ SwRegHistory history( pNode, *pNode, pHistory );
+ bRet = history.InsertItems(
+ aTxtSet, rSt.GetIndex(), rSt.GetIndex(), nFlags ) || bRet;
+
+ if (bRet && (pDoc->IsRedlineOn() || (!pDoc->IsIgnoreRedline()
+ && pDoc->GetRedlineTbl().Count())))
+ {
+ SwPaM aPam( pStt->nNode, pStt->nContent.GetIndex()-1,
+ pStt->nNode, pStt->nContent.GetIndex() );
+
+ if( pUndo )
+ pUndo->SaveRedlineData( aPam, sal_True );
+
+ if( pDoc->IsRedlineOn() )
+ pDoc->AppendRedline( new SwRedline( nsRedlineType_t::REDLINE_INSERT, aPam ), true);
+ else
+ pDoc->SplitRedline( aPam );
+ }
+ }
+ }
+
+ // TextAttribute mit Ende expandieren nie ihren Bereich
+ if ( !bCharAttr && !bOtherAttr )
+ {
+ // CharFmt wird gesondert behandelt !!!
+ // JP 22.08.96: URL-Attribute auch!!
+ // TEST_TEMP ToDo: AutoFmt!
+ SfxItemSet aTxtSet( pDoc->GetAttrPool(),
+ RES_TXTATR_REFMARK, RES_TXTATR_TOXMARK,
+ RES_TXTATR_META, RES_TXTATR_METAFIELD,
+ RES_TXTATR_CJK_RUBY, RES_TXTATR_CJK_RUBY,
+ 0 );
+
+ aTxtSet.Put( rChgSet );
+ if( aTxtSet.Count() )
+ {
+ sal_uInt16 nInsCnt = rSt.GetIndex();
+ sal_uInt16 nEnd = pStt->nNode == pEnd->nNode
+ ? pEnd->nContent.GetIndex()
+ : pNode->Len();
+ SwRegHistory history( pNode, *pNode, pHistory );
+ bRet = history.InsertItems( aTxtSet, nInsCnt, nEnd, nFlags )
+ || bRet;
+
+ if (bRet && (pDoc->IsRedlineOn() || (!pDoc->IsIgnoreRedline()
+ && pDoc->GetRedlineTbl().Count())))
+ {
+ // wurde Text-Inhalt eingefuegt? (RefMark/TOXMarks ohne Ende)
+ sal_Bool bTxtIns = nInsCnt != rSt.GetIndex();
+ // wurde Inhalt eingefuegt oder ueber die Selektion gesetzt?
+ SwPaM aPam( pStt->nNode, bTxtIns ? nInsCnt + 1 : nEnd,
+ pStt->nNode, nInsCnt );
+ if( pUndo )
+ pUndo->SaveRedlineData( aPam, bTxtIns );
+
+ if( pDoc->IsRedlineOn() )
+ pDoc->AppendRedline( new SwRedline( bTxtIns
+ ? nsRedlineType_t::REDLINE_INSERT : nsRedlineType_t::REDLINE_FORMAT, aPam ), true);
+ else if( bTxtIns )
+ pDoc->SplitRedline( aPam );
+ }
+ }
+ }
+ }
+
+ // bei PageDesc's, die am Node gesetzt werden, muss immer das
+ // Auto-Flag gesetzt werden!!
+ if( pOtherSet && pOtherSet->Count() )
+ {
+ SwTableNode* pTblNd;
+ const SwFmtPageDesc* pDesc;
+ if( SFX_ITEM_SET == pOtherSet->GetItemState( RES_PAGEDESC,
+ sal_False, (const SfxPoolItem**)&pDesc ))
+ {
+ if( pNode )
+ {
+ // Auto-Flag setzen, nur in Vorlagen ist ohne Auto !
+ SwFmtPageDesc aNew( *pDesc );
+ // Bug 38479: AutoFlag wird jetzt in der WrtShell gesetzt
+ // aNew.SetAuto();
+
+ // Tabellen kennen jetzt auch Umbrueche
+ if( 0 == (nFlags & nsSetAttrMode::SETATTR_APICALL) &&
+ 0 != ( pTblNd = pNode->FindTableNode() ) )
+ {
+ SwTableNode* pCurTblNd = pTblNd;
+ while ( 0 != ( pCurTblNd = pCurTblNd->StartOfSectionNode()->FindTableNode() ) )
+ pTblNd = pCurTblNd;
+
+ // dann am Tabellen Format setzen
+ SwFrmFmt* pFmt = pTblNd->GetTable().GetFrmFmt();
+ SwRegHistory aRegH( pFmt, *pTblNd, pHistory );
+ pFmt->SetFmtAttr( aNew );
+ bRet = true;
+ }
+ else
+ {
+ SwRegHistory aRegH( pNode, *pNode, pHistory );
+ bRet = pNode->SetAttr( aNew ) || bRet;
+ }
+ }
+
+ // bOtherAttr = true means that pOtherSet == rChgSet. In this case
+ // we know, that there is only one attribute in pOtherSet. We cannot
+ // perform the following operations, instead we return:
+ if ( bOtherAttr )
+ return bRet;
+
+ const_cast<SfxItemSet*>(pOtherSet)->ClearItem( RES_PAGEDESC );
+ if( !pOtherSet->Count() )
+ {
+ DELETECHARSETS
+ return bRet;
+ }
+ }
+
+ // Tabellen kennen jetzt auch Umbrueche
+ const SvxFmtBreakItem* pBreak;
+ if( pNode && 0 == (nFlags & nsSetAttrMode::SETATTR_APICALL) &&
+ 0 != (pTblNd = pNode->FindTableNode() ) &&
+ SFX_ITEM_SET == pOtherSet->GetItemState( RES_BREAK,
+ sal_False, (const SfxPoolItem**)&pBreak ) )
+ {
+ SwTableNode* pCurTblNd = pTblNd;
+ while ( 0 != ( pCurTblNd = pCurTblNd->StartOfSectionNode()->FindTableNode() ) )
+ pTblNd = pCurTblNd;
+
+ // dann am Tabellen Format setzen
+ SwFrmFmt* pFmt = pTblNd->GetTable().GetFrmFmt();
+ SwRegHistory aRegH( pFmt, *pTblNd, pHistory );
+ pFmt->SetFmtAttr( *pBreak );
+ bRet = true;
+
+ // bOtherAttr = true means that pOtherSet == rChgSet. In this case
+ // we know, that there is only one attribute in pOtherSet. We cannot
+ // perform the following operations, instead we return:
+ if ( bOtherAttr )
+ return bRet;
+
+ const_cast<SfxItemSet*>(pOtherSet)->ClearItem( RES_BREAK );
+ if( !pOtherSet->Count() )
+ {
+ DELETECHARSETS
+ return bRet;
+ }
+ }
+
+ {
+ // wenns eine PoolNumRule ist, diese ggfs. anlegen
+ const SwNumRuleItem* pRule;
+ sal_uInt16 nPoolId;
+ if( SFX_ITEM_SET == pOtherSet->GetItemState( RES_PARATR_NUMRULE,
+ sal_False, (const SfxPoolItem**)&pRule ) &&
+ !pDoc->FindNumRulePtr( pRule->GetValue() ) &&
+ USHRT_MAX != (nPoolId = SwStyleNameMapper::GetPoolIdFromUIName ( pRule->GetValue(),
+ nsSwGetPoolIdFromName::GET_POOLID_NUMRULE )) )
+ pDoc->GetNumRuleFromPool( nPoolId );
+ }
+
+ }
+
+ if( !rRg.HasMark() ) // kein Bereich
+ {
+ if( !pNode )
+ {
+ DELETECHARSETS
+ return bRet;
+ }
+
+ if( pNode->IsTxtNode() && pCharSet && pCharSet->Count() )
+ {
+ SwTxtNode* pTxtNd = static_cast<SwTxtNode*>(pNode);
+ const SwIndex& rSt = pStt->nContent;
+ sal_uInt16 nMkPos, nPtPos = rSt.GetIndex();
+ const String& rStr = pTxtNd->GetTxt();
+
+ // JP 22.08.96: Sonderfall: steht der Crsr in einem URL-Attribut
+ // dann wird dessen Bereich genommen
+ SwTxtAttr const*const pURLAttr(
+ pTxtNd->GetTxtAttrAt(rSt.GetIndex(), RES_TXTATR_INETFMT));
+ if (pURLAttr && pURLAttr->GetINetFmt().GetValue().Len())
+ {
+ nMkPos = *pURLAttr->GetStart();
+ nPtPos = *pURLAttr->GetEnd();
+ }
+ else
+ {
+ Boundary aBndry;
+ if( pBreakIt->GetBreakIter().is() )
+ aBndry = pBreakIt->GetBreakIter()->getWordBoundary(
+ pTxtNd->GetTxt(), nPtPos,
+ pBreakIt->GetLocale( pTxtNd->GetLang( nPtPos ) ),
+ WordType::ANY_WORD /*ANYWORD_IGNOREWHITESPACES*/,
+ sal_True );
+
+ if( aBndry.startPos < nPtPos && nPtPos < aBndry.endPos )
+ {
+ nMkPos = (xub_StrLen)aBndry.startPos;
+ nPtPos = (xub_StrLen)aBndry.endPos;
+ }
+ else
+ nPtPos = nMkPos = rSt.GetIndex();
+ }
+
+ // erstmal die zu ueberschreibenden Attribute aus dem
+ // SwpHintsArray entfernen, wenn die Selektion den gesamten
+ // Absatz umspannt. (Diese Attribute werden als FormatAttr.
+ // eingefuegt und verdraengen nie die TextAttr.!)
+ if( !(nFlags & nsSetAttrMode::SETATTR_DONTREPLACE ) &&
+ pTxtNd->HasHints() && !nMkPos && nPtPos == rStr.Len() )
+ {
+ SwIndex aSt( pTxtNd );
+ if( pHistory )
+ {
+ // fuers Undo alle Attribute sichern
+ SwRegHistory aRHst( *pTxtNd, pHistory );
+ pTxtNd->GetpSwpHints()->Register( &aRHst );
+ pTxtNd->RstAttr( aSt, nPtPos, 0, pCharSet );
+ if( pTxtNd->GetpSwpHints() )
+ pTxtNd->GetpSwpHints()->DeRegister();
+ }
+ else
+ pTxtNd->RstAttr( aSt, nPtPos, 0, pCharSet );
+ }
+
+ // the SwRegHistory inserts the attribute into the TxtNode!
+ SwRegHistory history( pNode, *pNode, pHistory );
+ bRet = history.InsertItems( *pCharSet, nMkPos, nPtPos, nFlags )
+ || bRet;
+
+ if( pDoc->IsRedlineOn() )
+ {
+ SwPaM aPam( *pNode, nMkPos, *pNode, nPtPos );
+
+ if( pUndo )
+ pUndo->SaveRedlineData( aPam, sal_False );
+ pDoc->AppendRedline( new SwRedline( nsRedlineType_t::REDLINE_FORMAT, aPam ), true);
+ }
+ }
+ if( pOtherSet && pOtherSet->Count() )
+ {
+ SwRegHistory aRegH( pNode, *pNode, pHistory );
+ bRet = pNode->SetAttr( *pOtherSet ) || bRet;
+ }
+
+ DELETECHARSETS
+ return bRet;
+ }
+
+ if( pDoc->IsRedlineOn() && pCharSet && pCharSet->Count() )
+ {
+ if( pUndo )
+ pUndo->SaveRedlineData( rRg, sal_False );
+ pDoc->AppendRedline( new SwRedline( nsRedlineType_t::REDLINE_FORMAT, rRg ), true);
+ }
+
+ /* jetzt wenn Bereich */
+ sal_uLong nNodes = 0;
+
+ SwNodeIndex aSt( pDoc->GetNodes() );
+ SwNodeIndex aEnd( pDoc->GetNodes() );
+ SwIndex aCntEnd( pEnd->nContent );
+
+ if( pNode )
+ {
+ sal_uInt16 nLen = pNode->Len();
+ if( pStt->nNode != pEnd->nNode )
+ aCntEnd.Assign( pNode, nLen );
+
+ if( pStt->nContent.GetIndex() != 0 || aCntEnd.GetIndex() != nLen )
+ {
+ // the SwRegHistory inserts the attribute into the TxtNode!
+ if( pNode->IsTxtNode() && pCharSet && pCharSet->Count() )
+ {
+ SwRegHistory history( pNode, *pNode, pHistory );
+ bRet = history.InsertItems(*pCharSet,
+ pStt->nContent.GetIndex(), aCntEnd.GetIndex(), nFlags)
+ || bRet;
+ }
+
+ if( pOtherSet && pOtherSet->Count() )
+ {
+ SwRegHistory aRegH( pNode, *pNode, pHistory );
+ bRet = pNode->SetAttr( *pOtherSet ) || bRet;
+ }
+
+ // lediglich Selektion in einem Node.
+ if( pStt->nNode == pEnd->nNode )
+ {
+ DELETECHARSETS
+ return bRet;
+ }
+ ++nNodes;
+ aSt.Assign( pStt->nNode.GetNode(), +1 );
+ }
+ else
+ aSt = pStt->nNode;
+ aCntEnd = pEnd->nContent; // aEnd wurde veraendert !!
+ }
+ else
+ aSt.Assign( pStt->nNode.GetNode(), +1 );
+
+ // aSt zeigt jetzt auf den ersten vollen Node
+
+ /*
+ * die Selektion umfasst mehr als einen Node
+ */
+ if( pStt->nNode < pEnd->nNode )
+ {
+ pNode = pEnd->nNode.GetNode().GetCntntNode();
+ if(pNode)
+ {
+ sal_uInt16 nLen = pNode->Len();
+ if( aCntEnd.GetIndex() != nLen )
+ {
+ // the SwRegHistory inserts the attribute into the TxtNode!
+ if( pNode->IsTxtNode() && pCharSet && pCharSet->Count() )
+ {
+ SwRegHistory history( pNode, *pNode, pHistory );
+ history.InsertItems(*pCharSet,
+ 0, aCntEnd.GetIndex(), nFlags);
+ }
+
+ if( pOtherSet && pOtherSet->Count() )
+ {
+ SwRegHistory aRegH( pNode, *pNode, pHistory );
+ pNode->SetAttr( *pOtherSet );
+ }
+
+ ++nNodes;
+ aEnd = pEnd->nNode;
+ }
+ else
+ aEnd.Assign( pEnd->nNode.GetNode(), +1 );
+ }
+ else
+ aEnd = pEnd->nNode;
+ }
+ else
+ aEnd.Assign( pEnd->nNode.GetNode(), +1 );
+
+ // aEnd zeigt jetzt HINTER den letzten voll Node
+
+ /* Bearbeitung der vollstaendig selektierten Nodes. */
+// alle Attribute aus dem Set zuruecksetzen !!
+ if( pCharSet && pCharSet->Count() && !( nsSetAttrMode::SETATTR_DONTREPLACE & nFlags ) )
+ {
+
+ ParaRstFmt aPara( pStt, pEnd, pHistory, 0, pCharSet );
+ pDoc->GetNodes().ForEach( aSt, aEnd, lcl_RstTxtAttr, &aPara );
+ }
+
+ sal_Bool bCreateSwpHints = pCharSet && (
+ SFX_ITEM_SET == pCharSet->GetItemState( RES_TXTATR_CHARFMT, sal_False ) ||
+ SFX_ITEM_SET == pCharSet->GetItemState( RES_TXTATR_INETFMT, sal_False ) );
+
+ for(; aSt < aEnd; aSt++ )
+ {
+ pNode = aSt.GetNode().GetCntntNode();
+ if( !pNode )
+ continue;
+
+ SwTxtNode* pTNd = pNode->GetTxtNode();
+ if( pHistory )
+ {
+ SwRegHistory aRegH( pNode, *pNode, pHistory );
+ SwpHints *pSwpHints;
+
+ if( pTNd && pCharSet && pCharSet->Count() )
+ {
+ pSwpHints = bCreateSwpHints ? &pTNd->GetOrCreateSwpHints()
+ : pTNd->GetpSwpHints();
+ if( pSwpHints )
+ pSwpHints->Register( &aRegH );
+
+ pTNd->SetAttr( *pCharSet, 0, pTNd->GetTxt().Len(), nFlags );
+ if( pSwpHints )
+ pSwpHints->DeRegister();
+ }
+ if( pOtherSet && pOtherSet->Count() )
+ pNode->SetAttr( *pOtherSet );
+ }
+ else
+ {
+ if( pTNd && pCharSet && pCharSet->Count() )
+ pTNd->SetAttr( *pCharSet, 0, pTNd->GetTxt().Len(), nFlags );
+ if( pOtherSet && pOtherSet->Count() )
+ pNode->SetAttr( *pOtherSet );
+ }
+ ++nNodes;
+ }
+
+ DELETECHARSETS
+ return (nNodes != 0) || bRet;
+}
+
+
+bool SwDoc::InsertPoolItem( const SwPaM &rRg, const SfxPoolItem &rHt,
+ const SetAttrMode nFlags )
+{
+ SwDataChanged aTmp( rRg, 0 );
+ SwUndoAttr* pUndoAttr = 0;
+ if (GetIDocumentUndoRedo().DoesUndo())
+ {
+ GetIDocumentUndoRedo().ClearRedo();
+ pUndoAttr = new SwUndoAttr( rRg, rHt, nFlags );
+ }
+
+ SfxItemSet aSet( GetAttrPool(), rHt.Which(), rHt.Which() );
+ aSet.Put( rHt );
+ bool bRet = lcl_InsAttr( this, rRg, aSet, nFlags, pUndoAttr );
+
+ if (GetIDocumentUndoRedo().DoesUndo())
+ {
+ GetIDocumentUndoRedo().AppendUndo( pUndoAttr );
+ }
+
+ if( bRet )
+ SetModified();
+ return bRet;
+}
+
+bool SwDoc::InsertItemSet ( const SwPaM &rRg, const SfxItemSet &rSet,
+ const SetAttrMode nFlags )
+{
+ SwDataChanged aTmp( rRg, 0 );
+ SwUndoAttr* pUndoAttr = 0;
+ if (GetIDocumentUndoRedo().DoesUndo())
+ {
+ GetIDocumentUndoRedo().ClearRedo();
+ pUndoAttr = new SwUndoAttr( rRg, rSet, nFlags );
+ }
+
+ bool bRet = lcl_InsAttr( this, rRg, rSet, nFlags, pUndoAttr );
+
+ if (GetIDocumentUndoRedo().DoesUndo())
+ {
+ GetIDocumentUndoRedo().AppendUndo( pUndoAttr );
+ }
+
+ if( bRet )
+ SetModified();
+ return bRet;
+}
+
+
+ // Setze das Attribut im angegebenen Format. Ist Undo aktiv, wird
+ // das alte in die Undo-History aufgenommen
+void SwDoc::SetAttr( const SfxPoolItem& rAttr, SwFmt& rFmt )
+{
+ SfxItemSet aSet( GetAttrPool(), rAttr.Which(), rAttr.Which() );
+ aSet.Put( rAttr );
+ SetAttr( aSet, rFmt );
+}
+
+
+ // Setze das Attribut im angegebenen Format. Ist Undo aktiv, wird
+ // das alte in die Undo-History aufgenommen
+void SwDoc::SetAttr( const SfxItemSet& rSet, SwFmt& rFmt )
+{
+ if (GetIDocumentUndoRedo().DoesUndo())
+ {
+ SwUndoFmtAttrHelper aTmp( rFmt );
+ rFmt.SetFmtAttr( rSet );
+ if ( aTmp.GetUndo() )
+ {
+ GetIDocumentUndoRedo().AppendUndo( aTmp.ReleaseUndo() );
+ }
+ else
+ {
+ GetIDocumentUndoRedo().ClearRedo();
+ }
+ }
+ else
+ {
+ rFmt.SetFmtAttr( rSet );
+ }
+ SetModified();
+}
+
+void SwDoc::ResetAttrAtFormat( const sal_uInt16 nWhichId,
+ SwFmt& rChangedFormat )
+{
+ SwUndo *const pUndo = (GetIDocumentUndoRedo().DoesUndo())
+ ? new SwUndoFmtResetAttr( rChangedFormat, nWhichId )
+ : 0;
+
+ const sal_Bool bAttrReset = rChangedFormat.ResetFmtAttr( nWhichId );
+
+ if ( bAttrReset )
+ {
+ if ( pUndo )
+ {
+ GetIDocumentUndoRedo().AppendUndo( pUndo );
+ }
+
+ SetModified();
+ }
+ else if ( pUndo )
+ delete pUndo;
+}
+
+int lcl_SetNewDefTabStops( SwTwips nOldWidth, SwTwips nNewWidth,
+ SvxTabStopItem& rChgTabStop )
+{
+ // dann aender bei allen TabStop die default's auf den neuen Wert
+ // !!! Achtung: hier wird immer auf dem PoolAttribut gearbeitet,
+ // damit nicht in allen Sets die gleiche Berechnung
+ // auf dem gleichen TabStop (gepoolt!) vorgenommen
+ // wird. Als Modify wird ein FmtChg verschickt.
+
+ sal_uInt16 nOldCnt = rChgTabStop.Count();
+ if( !nOldCnt || nOldWidth == nNewWidth )
+ return sal_False;
+
+ // suche den Anfang der Defaults
+ SvxTabStop* pTabs = ((SvxTabStop*)rChgTabStop.GetStart())
+ + (nOldCnt-1);
+ sal_uInt16 n;
+
+ for( n = nOldCnt; n ; --n, --pTabs )
+ if( SVX_TAB_ADJUST_DEFAULT != pTabs->GetAdjustment() )
+ break;
+ ++n;
+ if( n < nOldCnt ) // die DefTabStops loeschen
+ rChgTabStop.Remove( n, nOldCnt - n );
+ return sal_True;
+}
+
+// Setze das Attribut als neues default Attribut in diesem Dokument.
+// Ist Undo aktiv, wird das alte in die Undo-History aufgenommen
+void SwDoc::SetDefault( const SfxPoolItem& rAttr )
+{
+ SfxItemSet aSet( GetAttrPool(), rAttr.Which(), rAttr.Which() );
+ aSet.Put( rAttr );
+ SetDefault( aSet );
+}
+
+void SwDoc::SetDefault( const SfxItemSet& rSet )
+{
+ if( !rSet.Count() )
+ return;
+
+ SwModify aCallMod( 0 );
+ SwAttrSet aOld( GetAttrPool(), rSet.GetRanges() ),
+ aNew( GetAttrPool(), rSet.GetRanges() );
+ SfxItemIter aIter( rSet );
+ sal_uInt16 nWhich;
+ const SfxPoolItem* pItem = aIter.GetCurItem();
+ SfxItemPool* pSdrPool = GetAttrPool().GetSecondaryPool();
+ while( sal_True )
+ {
+ sal_Bool bCheckSdrDflt = sal_False;
+ nWhich = pItem->Which();
+ aOld.Put( GetAttrPool().GetDefaultItem( nWhich ) );
+ GetAttrPool().SetPoolDefaultItem( *pItem );
+ aNew.Put( GetAttrPool().GetDefaultItem( nWhich ) );
+
+ if (isCHRATR(nWhich) || isTXTATR(nWhich))
+ {
+ aCallMod.Add( pDfltTxtFmtColl );
+ aCallMod.Add( pDfltCharFmt );
+ bCheckSdrDflt = 0 != pSdrPool;
+ }
+ else if ( isPARATR(nWhich) ||
+ isPARATR_LIST(nWhich) )
+ {
+ aCallMod.Add( pDfltTxtFmtColl );
+ bCheckSdrDflt = 0 != pSdrPool;
+ }
+ else if (isGRFATR(nWhich))
+ {
+ aCallMod.Add( pDfltGrfFmtColl );
+ }
+ else if (isFRMATR(nWhich))
+ {
+ aCallMod.Add( pDfltGrfFmtColl );
+ aCallMod.Add( pDfltTxtFmtColl );
+ aCallMod.Add( pDfltFrmFmt );
+ }
+ else if (isBOXATR(nWhich))
+ {
+ aCallMod.Add( pDfltFrmFmt );
+ }
+
+ // copy also the defaults
+ if( bCheckSdrDflt )
+ {
+ sal_uInt16 nEdtWhich, nSlotId;
+ if( 0 != (nSlotId = GetAttrPool().GetSlotId( nWhich ) ) &&
+ nSlotId != nWhich &&
+ 0 != (nEdtWhich = pSdrPool->GetWhich( nSlotId )) &&
+ nSlotId != nEdtWhich )
+ {
+ SfxPoolItem* pCpy = pItem->Clone();
+ pCpy->SetWhich( nEdtWhich );
+ pSdrPool->SetPoolDefaultItem( *pCpy );
+ delete pCpy;
+ }
+ }
+
+ if( aIter.IsAtEnd() )
+ break;
+ pItem = aIter.NextItem();
+ }
+
+ if( aNew.Count() && aCallMod.GetDepends() )
+ {
+ if (GetIDocumentUndoRedo().DoesUndo())
+ {
+ GetIDocumentUndoRedo().AppendUndo( new SwUndoDefaultAttr( aOld ) );
+ }
+
+ const SfxPoolItem* pTmpItem;
+ if( ( SFX_ITEM_SET ==
+ aNew.GetItemState( RES_PARATR_TABSTOP, sal_False, &pTmpItem ) ) &&
+ ((SvxTabStopItem*)pTmpItem)->Count() )
+ {
+ // TabStop-Aenderungen behandeln wir erstmal anders:
+ // dann aender bei allen TabStop die dafault's auf den neuen Wert
+ // !!! Achtung: hier wird immer auf dem PoolAttribut gearbeitet,
+ // damit nicht in allen Sets die gleiche Berechnung
+ // auf dem gleichen TabStop (gepoolt!) vorgenommen
+ // wird. Als Modify wird ein FmtChg verschickt.
+ SwTwips nNewWidth = (*(SvxTabStopItem*)pTmpItem)[ 0 ].GetTabPos(),
+ nOldWidth = ((SvxTabStopItem&)aOld.Get(RES_PARATR_TABSTOP))[ 0 ].GetTabPos();
+
+ int bChg = sal_False;
+ sal_uInt32 nMaxItems = GetAttrPool().GetItemCount2( RES_PARATR_TABSTOP );
+ for( sal_uInt32 n = 0; n < nMaxItems; ++n )
+ if( 0 != (pTmpItem = GetAttrPool().GetItem2( RES_PARATR_TABSTOP, n ) ))
+ bChg |= lcl_SetNewDefTabStops( nOldWidth, nNewWidth,
+ *(SvxTabStopItem*)pTmpItem );
+
+ aNew.ClearItem( RES_PARATR_TABSTOP );
+ aOld.ClearItem( RES_PARATR_TABSTOP );
+ if( bChg )
+ {
+ SwFmtChg aChgFmt( pDfltCharFmt );
+ // dann sage mal den Frames bescheid
+ aCallMod.ModifyNotification( &aChgFmt, &aChgFmt );
+ }
+ }
+ }
+
+ if( aNew.Count() && aCallMod.GetDepends() )
+ {
+ SwAttrSetChg aChgOld( aOld, aOld );
+ SwAttrSetChg aChgNew( aNew, aNew );
+ aCallMod.ModifyNotification( &aChgOld, &aChgNew ); // alle veraenderten werden verschickt
+ }
+
+ // und die default-Formate wieder beim Object austragen
+ SwClient* pDep;
+ while( 0 != ( pDep = (SwClient*)aCallMod.GetDepends()) )
+ aCallMod.Remove( pDep );
+
+ SetModified();
+}
+
+ // Erfrage das Default Attribut in diesem Dokument.
+const SfxPoolItem& SwDoc::GetDefault( sal_uInt16 nFmtHint ) const
+{
+ return GetAttrPool().GetDefaultItem( nFmtHint );
+}
+
+/*
+ * Loeschen der Formate
+ */
+void SwDoc::DelCharFmt(sal_uInt16 nFmt, sal_Bool bBroadcast)
+{
+ SwCharFmt * pDel = (*pCharFmtTbl)[nFmt];
+
+ if (bBroadcast)
+ BroadcastStyleOperation(pDel->GetName(), SFX_STYLE_FAMILY_CHAR,
+ SFX_STYLESHEET_ERASED);
+
+ if (GetIDocumentUndoRedo().DoesUndo())
+ {
+ SwUndo * pUndo =
+ new SwUndoCharFmtDelete(pDel, this);
+
+ GetIDocumentUndoRedo().AppendUndo(pUndo);
+ }
+
+ pCharFmtTbl->DeleteAndDestroy(nFmt);
+
+ SetModified();
+}
+
+void SwDoc::DelCharFmt( SwCharFmt *pFmt, sal_Bool bBroadcast )
+{
+ sal_uInt16 nFmt = pCharFmtTbl->GetPos( pFmt );
+ OSL_ENSURE( USHRT_MAX != nFmt, "Fmt not found," );
+
+ DelCharFmt( nFmt, bBroadcast );
+}
+
+void SwDoc::DelFrmFmt( SwFrmFmt *pFmt, sal_Bool bBroadcast )
+{
+ if( pFmt->ISA( SwTableBoxFmt ) || pFmt->ISA( SwTableLineFmt ))
+ {
+ OSL_ENSURE( !this, "Format steht nicht mehr im DocArray, "
+ "kann per delete geloescht werden" );
+ delete pFmt;
+ }
+ else
+ {
+
+ //Das Format muss in einem der beiden Arrays stehen, in welchem
+ //werden wir schon merken.
+ sal_uInt16 nPos;
+ if ( USHRT_MAX != ( nPos = pFrmFmtTbl->GetPos( pFmt )) )
+ {
+ if (bBroadcast)
+ BroadcastStyleOperation(pFmt->GetName(),
+ SFX_STYLE_FAMILY_FRAME,
+ SFX_STYLESHEET_ERASED);
+
+ if (GetIDocumentUndoRedo().DoesUndo())
+ {
+ SwUndo * pUndo = new SwUndoFrmFmtDelete(pFmt, this);
+
+ GetIDocumentUndoRedo().AppendUndo(pUndo);
+ }
+
+ pFrmFmtTbl->DeleteAndDestroy( nPos );
+ }
+ else
+ {
+ nPos = GetSpzFrmFmts()->GetPos( pFmt );
+ OSL_ENSURE( nPos != USHRT_MAX, "FrmFmt not found." );
+ if( USHRT_MAX != nPos )
+ GetSpzFrmFmts()->DeleteAndDestroy( nPos );
+ }
+ }
+}
+
+void SwDoc::DelTblFrmFmt( SwTableFmt *pFmt )
+{
+ sal_uInt16 nPos = pTblFrmFmtTbl->GetPos( pFmt );
+ OSL_ENSURE( USHRT_MAX != nPos, "Fmt not found," );
+ pTblFrmFmtTbl->DeleteAndDestroy( nPos );
+}
+
+/*
+ * Erzeugen der Formate
+ */
+SwFlyFrmFmt *SwDoc::MakeFlyFrmFmt( const String &rFmtName,
+ SwFrmFmt *pDerivedFrom )
+{
+ SwFlyFrmFmt *pFmt = new SwFlyFrmFmt( GetAttrPool(), rFmtName, pDerivedFrom );
+ GetSpzFrmFmts()->Insert(pFmt, GetSpzFrmFmts()->Count());
+ SetModified();
+ return pFmt;
+}
+
+SwDrawFrmFmt *SwDoc::MakeDrawFrmFmt( const String &rFmtName,
+ SwFrmFmt *pDerivedFrom )
+{
+ SwDrawFrmFmt *pFmt = new SwDrawFrmFmt( GetAttrPool(), rFmtName, pDerivedFrom);
+ GetSpzFrmFmts()->Insert(pFmt,GetSpzFrmFmts()->Count());
+ SetModified();
+ return pFmt;
+}
+
+
+sal_uInt16 SwDoc::GetTblFrmFmtCount(sal_Bool bUsed) const
+{
+ sal_uInt16 nCount = pTblFrmFmtTbl->Count();
+ if(bUsed)
+ {
+ SwAutoFmtGetDocNode aGetHt( &GetNodes() );
+ for ( sal_uInt16 i = nCount; i; )
+ {
+ if((*pTblFrmFmtTbl)[--i]->GetInfo( aGetHt ))
+
+ --nCount;
+ }
+ }
+
+ return nCount;
+}
+
+
+SwFrmFmt& SwDoc::GetTblFrmFmt(sal_uInt16 nFmt, sal_Bool bUsed ) const
+{
+ sal_uInt16 nRemoved = 0;
+ if(bUsed)
+ {
+ SwAutoFmtGetDocNode aGetHt( &GetNodes() );
+ for ( sal_uInt16 i = 0; i <= nFmt; i++ )
+ {
+ while ( (*pTblFrmFmtTbl)[ i + nRemoved]->GetInfo( aGetHt ))
+ {
+ nRemoved++;
+ }
+ }
+ }
+ return *((*pTblFrmFmtTbl)[nRemoved + nFmt]);
+}
+
+SwTableFmt* SwDoc::MakeTblFrmFmt( const String &rFmtName,
+ SwFrmFmt *pDerivedFrom )
+{
+ SwTableFmt* pFmt = new SwTableFmt( GetAttrPool(), rFmtName, pDerivedFrom );
+ pTblFrmFmtTbl->Insert( pFmt, pTblFrmFmtTbl->Count() );
+ SetModified();
+
+ return pFmt;
+}
+
+SwFrmFmt *SwDoc::MakeFrmFmt(const String &rFmtName,
+ SwFrmFmt *pDerivedFrom,
+ sal_Bool bBroadcast, sal_Bool bAuto)
+{
+
+ SwFrmFmt *pFmt = new SwFrmFmt( GetAttrPool(), rFmtName, pDerivedFrom );
+
+ pFmt->SetAuto(bAuto);
+ pFrmFmtTbl->Insert( pFmt, pFrmFmtTbl->Count());
+ SetModified();
+
+ if (bBroadcast)
+ {
+ BroadcastStyleOperation(rFmtName, SFX_STYLE_FAMILY_PARA,
+ SFX_STYLESHEET_CREATED);
+
+ if (GetIDocumentUndoRedo().DoesUndo())
+ {
+ SwUndo * pUndo = new SwUndoFrmFmtCreate(pFmt, pDerivedFrom, this);
+
+ GetIDocumentUndoRedo().AppendUndo(pUndo);
+ }
+ }
+
+ return pFmt;
+}
+
+SwFmt *SwDoc::_MakeFrmFmt(const String &rFmtName,
+ SwFmt *pDerivedFrom,
+ sal_Bool bBroadcast, sal_Bool bAuto)
+{
+ SwFrmFmt *pFrmFmt = dynamic_cast<SwFrmFmt*>(pDerivedFrom);
+ pFrmFmt = MakeFrmFmt( rFmtName, pFrmFmt, bBroadcast, bAuto );
+ return dynamic_cast<SwFmt*>(pFrmFmt);
+}
+
+
+// #i40550# - add parameter <bAuto> - not relevant
+SwCharFmt *SwDoc::MakeCharFmt( const String &rFmtName,
+ SwCharFmt *pDerivedFrom,
+ sal_Bool bBroadcast,
+ sal_Bool )
+{
+ SwCharFmt *pFmt = new SwCharFmt( GetAttrPool(), rFmtName, pDerivedFrom );
+ pCharFmtTbl->Insert( pFmt, pCharFmtTbl->Count() );
+ pFmt->SetAuto( sal_False );
+ SetModified();
+
+ if (GetIDocumentUndoRedo().DoesUndo())
+ {
+ SwUndo * pUndo = new SwUndoCharFmtCreate(pFmt, pDerivedFrom, this);
+
+ GetIDocumentUndoRedo().AppendUndo(pUndo);
+ }
+
+ if (bBroadcast)
+ {
+ BroadcastStyleOperation(rFmtName, SFX_STYLE_FAMILY_CHAR,
+ SFX_STYLESHEET_CREATED);
+ }
+
+ return pFmt;
+}
+
+SwFmt *SwDoc::_MakeCharFmt(const String &rFmtName,
+ SwFmt *pDerivedFrom,
+ sal_Bool bBroadcast, sal_Bool bAuto)
+{
+ SwCharFmt *pCharFmt = dynamic_cast<SwCharFmt*>(pDerivedFrom);
+ pCharFmt = MakeCharFmt( rFmtName, pCharFmt, bBroadcast, bAuto );
+ return dynamic_cast<SwFmt*>(pCharFmt);
+}
+
+
+/*
+ * Erzeugen der FormatCollections
+ */
+// TXT
+// #i40550# - add parameter <bAuto> - not relevant
+SwTxtFmtColl* SwDoc::MakeTxtFmtColl( const String &rFmtName,
+ SwTxtFmtColl *pDerivedFrom,
+ sal_Bool bBroadcast,
+ sal_Bool )
+{
+ SwTxtFmtColl *pFmtColl = new SwTxtFmtColl( GetAttrPool(), rFmtName,
+ pDerivedFrom );
+ pTxtFmtCollTbl->Insert(pFmtColl, pTxtFmtCollTbl->Count());
+ pFmtColl->SetAuto( sal_False );
+ SetModified();
+
+ if (GetIDocumentUndoRedo().DoesUndo())
+ {
+ SwUndo * pUndo = new SwUndoTxtFmtCollCreate(pFmtColl, pDerivedFrom,
+ this);
+ GetIDocumentUndoRedo().AppendUndo(pUndo);
+ }
+
+ if (bBroadcast)
+ BroadcastStyleOperation(rFmtName, SFX_STYLE_FAMILY_PARA,
+ SFX_STYLESHEET_CREATED);
+
+ return pFmtColl;
+}
+
+SwFmt *SwDoc::_MakeTxtFmtColl(const String &rFmtName,
+ SwFmt *pDerivedFrom,
+ sal_Bool bBroadcast, sal_Bool bAuto)
+{
+ SwTxtFmtColl *pTxtFmtColl = dynamic_cast<SwTxtFmtColl*>(pDerivedFrom);
+ pTxtFmtColl = MakeTxtFmtColl( rFmtName, pTxtFmtColl, bBroadcast, bAuto );
+ return dynamic_cast<SwFmt*>(pTxtFmtColl);
+}
+
+
+//FEATURE::CONDCOLL
+SwConditionTxtFmtColl* SwDoc::MakeCondTxtFmtColl( const String &rFmtName,
+ SwTxtFmtColl *pDerivedFrom,
+ sal_Bool bBroadcast)
+{
+ SwConditionTxtFmtColl*pFmtColl = new SwConditionTxtFmtColl( GetAttrPool(),
+ rFmtName, pDerivedFrom );
+ pTxtFmtCollTbl->Insert(pFmtColl, pTxtFmtCollTbl->Count());
+ pFmtColl->SetAuto( sal_False );
+ SetModified();
+
+ if (bBroadcast)
+ BroadcastStyleOperation(rFmtName, SFX_STYLE_FAMILY_PARA,
+ SFX_STYLESHEET_CREATED);
+
+ return pFmtColl;
+}
+//FEATURE::CONDCOLL
+
+// GRF
+
+SwGrfFmtColl* SwDoc::MakeGrfFmtColl( const String &rFmtName,
+ SwGrfFmtColl *pDerivedFrom )
+{
+ SwGrfFmtColl *pFmtColl = new SwGrfFmtColl( GetAttrPool(), rFmtName,
+ pDerivedFrom );
+ pGrfFmtCollTbl->Insert( pFmtColl, pGrfFmtCollTbl->Count() );
+ pFmtColl->SetAuto( sal_False );
+ SetModified();
+ return pFmtColl;
+}
+
+void SwDoc::DelTxtFmtColl(sal_uInt16 nFmtColl, sal_Bool bBroadcast)
+{
+ OSL_ENSURE( nFmtColl, "Remove fuer Coll 0." );
+
+ // Wer hat die zu loeschende als Next
+ SwTxtFmtColl *pDel = (*pTxtFmtCollTbl)[nFmtColl];
+ if( pDfltTxtFmtColl == pDel )
+ return; // default nie loeschen !!
+
+ if (bBroadcast)
+ BroadcastStyleOperation(pDel->GetName(), SFX_STYLE_FAMILY_PARA,
+ SFX_STYLESHEET_ERASED);
+
+ if (GetIDocumentUndoRedo().DoesUndo())
+ {
+ SwUndoTxtFmtCollDelete * pUndo =
+ new SwUndoTxtFmtCollDelete(pDel, this);
+
+ GetIDocumentUndoRedo().AppendUndo(pUndo);
+ }
+
+ // Die FmtColl austragen
+ pTxtFmtCollTbl->Remove(nFmtColl);
+ // Next korrigieren
+ pTxtFmtCollTbl->ForEach( 1, pTxtFmtCollTbl->Count(),
+ &SetTxtFmtCollNext, pDel );
+ delete pDel;
+ SetModified();
+}
+
+void SwDoc::DelTxtFmtColl( SwTxtFmtColl *pColl, sal_Bool bBroadcast )
+{
+ sal_uInt16 nFmt = pTxtFmtCollTbl->GetPos( pColl );
+ OSL_ENSURE( USHRT_MAX != nFmt, "Collection not found," );
+ DelTxtFmtColl( nFmt, bBroadcast );
+}
+
+sal_Bool lcl_SetTxtFmtColl( const SwNodePtr& rpNode, void* pArgs )
+{
+ // ParaSetFmtColl * pPara = (ParaSetFmtColl*)pArgs;
+ SwCntntNode* pCNd = (SwCntntNode*)rpNode->GetTxtNode();
+ if( pCNd )
+ {
+ ParaRstFmt* pPara = (ParaRstFmt*)pArgs;
+
+ SwTxtFmtColl* pFmt = static_cast<SwTxtFmtColl*>(pPara->pFmtColl);
+ if ( pPara->bReset )
+ {
+
+ if( pFmt->GetAttrOutlineLevel() == 0 && pPara )
+ pPara->bKeepOutlineLevelAttr = true;
+
+ lcl_RstAttr( pCNd, pPara );
+
+ // #i62675# check, if paragraph style has changed
+ if ( pPara->bResetListAttrs &&
+ pFmt != pCNd->GetFmtColl() &&
+ pFmt->GetItemState( RES_PARATR_NUMRULE ) == SFX_ITEM_SET )
+ {
+ // Check, if the list style of the paragraph will change.
+ bool bChangeOfListStyleAtParagraph( true );
+ SwTxtNode* pTNd( dynamic_cast<SwTxtNode*>(pCNd) );
+ OSL_ENSURE( pTNd,
+ "<lcl_SetTxtFmtColl(..)> - text node expected -> crash" );
+ {
+ SwNumRule* pNumRuleAtParagraph( pTNd->GetNumRule() );
+ if ( pNumRuleAtParagraph )
+ {
+ const SwNumRuleItem& rNumRuleItemAtParagraphStyle =
+ pFmt->GetNumRule();
+ if ( rNumRuleItemAtParagraphStyle.GetValue() ==
+ pNumRuleAtParagraph->GetName() )
+ {
+ bChangeOfListStyleAtParagraph = false;
+ }
+ }
+ }
+
+ if ( bChangeOfListStyleAtParagraph )
+ {
+ std::auto_ptr< SwRegHistory > pRegH;
+ if ( pPara->pHistory )
+ {
+ pRegH.reset( new SwRegHistory( pTNd, *pTNd, pPara->pHistory ) );
+ }
+
+ pCNd->ResetAttr( RES_PARATR_NUMRULE );
+
+ // reset all list attributes
+ pCNd->ResetAttr( RES_PARATR_LIST_LEVEL );
+ pCNd->ResetAttr( RES_PARATR_LIST_ISRESTART );
+ pCNd->ResetAttr( RES_PARATR_LIST_RESTARTVALUE );
+ pCNd->ResetAttr( RES_PARATR_LIST_ISCOUNTED );
+ pCNd->ResetAttr( RES_PARATR_LIST_ID );
+ }
+ }
+ }
+
+ // erst in die History aufnehmen, damit ggfs. alte Daten
+ // gesichert werden koennen
+ if( pPara->pHistory )
+ pPara->pHistory->Add( pCNd->GetFmtColl(), pCNd->GetIndex(),
+ ND_TEXTNODE );
+
+ pCNd->ChgFmtColl( pFmt );
+
+ pPara->nWhich++;
+ }
+ return sal_True;
+}
+
+sal_Bool SwDoc::SetTxtFmtColl( const SwPaM &rRg,
+ SwTxtFmtColl *pFmt,
+ bool bReset,
+ bool bResetListAttrs )
+{
+ SwDataChanged aTmp( rRg, 0 );
+ const SwPosition *pStt = rRg.Start(), *pEnd = rRg.End();
+ SwHistory* pHst = 0;
+ sal_Bool bRet = sal_True;
+
+ if (GetIDocumentUndoRedo().DoesUndo())
+ {
+ SwUndoFmtColl* pUndo = new SwUndoFmtColl( rRg, pFmt,
+ bReset,
+ bResetListAttrs );
+ pHst = pUndo->GetHistory();
+ GetIDocumentUndoRedo().AppendUndo(pUndo);
+ }
+
+ ParaRstFmt aPara( pStt, pEnd, pHst );
+ aPara.pFmtColl = pFmt;
+ aPara.bReset = bReset;
+ // #i62675#
+ aPara.bResetListAttrs = bResetListAttrs;
+
+ GetNodes().ForEach( pStt->nNode.GetIndex(), pEnd->nNode.GetIndex()+1,
+ lcl_SetTxtFmtColl, &aPara );
+ if( !aPara.nWhich )
+ bRet = sal_False; // keinen gueltigen Node gefunden
+
+ if( bRet )
+ SetModified();
+ return bRet;
+}
+
+
+// ---- Kopiere die Formate in sich selbst (SwDoc) ----------------------
+
+SwFmt* SwDoc::CopyFmt( const SwFmt& rFmt,
+ const SvPtrarr& rFmtArr,
+ FNCopyFmt fnCopyFmt, const SwFmt& rDfltFmt )
+{
+ // kein-Autoformat || default Format || Collection-Format
+ // dann suche danach.
+ if( !rFmt.IsAuto() || !rFmt.GetRegisteredIn() )
+ for( sal_uInt16 n = 0; n < rFmtArr.Count(); n++ )
+ {
+ // ist die Vorlage schon im Doc vorhanden ??
+ if( ((SwFmt*)rFmtArr[n])->GetName().Equals( rFmt.GetName() ))
+ return (SwFmt*)rFmtArr[n];
+ }
+
+ // suche erstmal nach dem "Parent"
+ SwFmt* pParent = (SwFmt*)&rDfltFmt;
+ if( rFmt.DerivedFrom() && pParent != rFmt.DerivedFrom() )
+ pParent = CopyFmt( *rFmt.DerivedFrom(), rFmtArr,
+ fnCopyFmt, rDfltFmt );
+
+ // erzeuge das Format und kopiere die Attribute
+ // #i40550#
+ SwFmt* pNewFmt = (this->*fnCopyFmt)( rFmt.GetName(), pParent, sal_False, sal_True );
+ pNewFmt->SetAuto( rFmt.IsAuto() );
+ pNewFmt->CopyAttrs( rFmt, sal_True ); // kopiere Attribute
+
+ pNewFmt->SetPoolFmtId( rFmt.GetPoolFmtId() );
+ pNewFmt->SetPoolHelpId( rFmt.GetPoolHelpId() );
+
+ // HelpFile-Id immer auf dflt setzen !!
+ pNewFmt->SetPoolHlpFileId( UCHAR_MAX );
+
+ return pNewFmt;
+}
+
+
+// ---- kopiere das Frame-Format --------
+SwFrmFmt* SwDoc::CopyFrmFmt( const SwFrmFmt& rFmt )
+{
+
+ return (SwFrmFmt*)CopyFmt( rFmt, *GetFrmFmts(), &SwDoc::_MakeFrmFmt,
+ *GetDfltFrmFmt() );
+}
+
+// ---- kopiere das Char-Format --------
+SwCharFmt* SwDoc::CopyCharFmt( const SwCharFmt& rFmt )
+{
+ return (SwCharFmt*)CopyFmt( rFmt, *GetCharFmts(),
+ &SwDoc::_MakeCharFmt,
+ *GetDfltCharFmt() );
+}
+
+
+// --- Kopiere TextNodes ----
+
+SwTxtFmtColl* SwDoc::CopyTxtColl( const SwTxtFmtColl& rColl )
+{
+ SwTxtFmtColl* pNewColl = FindTxtFmtCollByName( rColl.GetName() );
+ if( pNewColl )
+ return pNewColl;
+
+ // suche erstmal nach dem "Parent"
+ SwTxtFmtColl* pParent = pDfltTxtFmtColl;
+ if( pParent != rColl.DerivedFrom() )
+ pParent = CopyTxtColl( *(SwTxtFmtColl*)rColl.DerivedFrom() );
+
+
+//FEATURE::CONDCOLL
+ if( RES_CONDTXTFMTCOLL == rColl.Which() )
+ {
+ pNewColl = new SwConditionTxtFmtColl( GetAttrPool(), rColl.GetName(),
+ pParent);
+ pTxtFmtCollTbl->Insert( pNewColl, pTxtFmtCollTbl->Count() );
+ pNewColl->SetAuto( sal_False );
+ SetModified();
+
+ // Kopiere noch die Bedingungen
+ ((SwConditionTxtFmtColl*)pNewColl)->SetConditions(
+ ((SwConditionTxtFmtColl&)rColl).GetCondColls() );
+ }
+ else
+//FEATURE::CONDCOLL
+ pNewColl = MakeTxtFmtColl( rColl.GetName(), pParent );
+
+ // kopiere jetzt noch die Auto-Formate oder kopiere die Attribute
+ pNewColl->CopyAttrs( rColl, sal_True );
+
+ if(rColl.IsAssignedToListLevelOfOutlineStyle())
+ pNewColl->AssignToListLevelOfOutlineStyle(rColl.GetAssignedOutlineStyleLevel());//<-end,zhaojianwei
+ //<-end
+ pNewColl->SetPoolFmtId( rColl.GetPoolFmtId() );
+ pNewColl->SetPoolHelpId( rColl.GetPoolHelpId() );
+
+ // HelpFile-Id immer auf dflt setzen !!
+ pNewColl->SetPoolHlpFileId( UCHAR_MAX );
+
+ if( &rColl.GetNextTxtFmtColl() != &rColl )
+ pNewColl->SetNextTxtFmtColl( *CopyTxtColl( rColl.GetNextTxtFmtColl() ));
+
+ // ggfs. die NumRule erzeugen
+ if( this != rColl.GetDoc() )
+ {
+ const SfxPoolItem* pItem;
+ if( SFX_ITEM_SET == pNewColl->GetItemState( RES_PARATR_NUMRULE,
+ sal_False, &pItem ))
+ {
+ const SwNumRule* pRule;
+ const String& rName = ((SwNumRuleItem*)pItem)->GetValue();
+ if( rName.Len() &&
+ 0 != ( pRule = rColl.GetDoc()->FindNumRulePtr( rName )) &&
+ !pRule->IsAutoRule() )
+ {
+ SwNumRule* pDestRule = FindNumRulePtr( rName );
+ if( pDestRule )
+ pDestRule->SetInvalidRule( sal_True );
+ else
+ MakeNumRule( rName, pRule );
+ }
+ }
+ }
+ return pNewColl;
+}
+
+// --- Kopiere GrafikNodes ----
+
+SwGrfFmtColl* SwDoc::CopyGrfColl( const SwGrfFmtColl& rColl )
+{
+ SwGrfFmtColl* pNewColl = FindGrfFmtCollByName( rColl.GetName() );
+ if( pNewColl )
+ return pNewColl;
+
+ // suche erstmal nach dem "Parent"
+ SwGrfFmtColl* pParent = pDfltGrfFmtColl;
+ if( pParent != rColl.DerivedFrom() )
+ pParent = CopyGrfColl( *(SwGrfFmtColl*)rColl.DerivedFrom() );
+
+ // falls nicht, so kopiere sie
+ pNewColl = MakeGrfFmtColl( rColl.GetName(), pParent );
+
+ // noch die Attribute kopieren
+ pNewColl->CopyAttrs( rColl );
+
+ pNewColl->SetPoolFmtId( rColl.GetPoolFmtId() );
+ pNewColl->SetPoolHelpId( rColl.GetPoolHelpId() );
+
+ // HelpFile-Id immer auf dflt setzen !!
+ pNewColl->SetPoolHlpFileId( UCHAR_MAX );
+
+ return pNewColl;
+}
+
+SwPageDesc* lcl_FindPageDesc( const SwPageDescs& rArr, const String& rName )
+{
+ for( sal_uInt16 n = rArr.Count(); n; )
+ {
+ SwPageDesc* pDesc = rArr[ --n ];
+ if( pDesc->GetName() == rName )
+ return pDesc;
+ }
+ return 0;
+}
+
+void SwDoc::CopyFmtArr( const SvPtrarr& rSourceArr,
+ SvPtrarr& rDestArr,
+ FNCopyFmt fnCopyFmt,
+ SwFmt& rDfltFmt )
+{
+ sal_uInt16 nSrc;
+ SwFmt* pSrc, *pDest;
+
+ // 1. Schritt alle Formate anlegen (das 0. ueberspringen - Default!)
+ for( nSrc = rSourceArr.Count(); nSrc > 1; )
+ {
+ pSrc = (SwFmt*)rSourceArr[ --nSrc ];
+ if( pSrc->IsDefault() || pSrc->IsAuto() )
+ continue;
+
+ if( 0 == FindFmtByName( rDestArr, pSrc->GetName() ) )
+ {
+ if( RES_CONDTXTFMTCOLL == pSrc->Which() )
+ MakeCondTxtFmtColl( pSrc->GetName(), (SwTxtFmtColl*)&rDfltFmt );
+ else
+ // #i40550#
+ (this->*fnCopyFmt)( pSrc->GetName(), &rDfltFmt, sal_False, sal_True );
+ }
+ }
+
+ // 2. Schritt alle Attribute kopieren, richtige Parents setzen
+ for( nSrc = rSourceArr.Count(); nSrc > 1; )
+ {
+ pSrc = (SwFmt*)rSourceArr[ --nSrc ];
+ if( pSrc->IsDefault() || pSrc->IsAuto() )
+ continue;
+
+ pDest = FindFmtByName( rDestArr, pSrc->GetName() );
+ pDest->SetAuto( sal_False );
+ pDest->DelDiffs( *pSrc );
+
+ // #i94285#: existing <SwFmtPageDesc> instance, before copying attributes
+ const SfxPoolItem* pItem;
+ if( &GetAttrPool() != pSrc->GetAttrSet().GetPool() &&
+ SFX_ITEM_SET == pSrc->GetAttrSet().GetItemState(
+ RES_PAGEDESC, sal_False, &pItem ) &&
+ ((SwFmtPageDesc*)pItem)->GetPageDesc() )
+ {
+ SwFmtPageDesc aPageDesc( *(SwFmtPageDesc*)pItem );
+ const String& rNm = aPageDesc.GetPageDesc()->GetName();
+ SwPageDesc* pPageDesc = ::lcl_FindPageDesc( aPageDescs, rNm );
+ if( !pPageDesc )
+ {
+ pPageDesc = aPageDescs[ MakePageDesc( rNm ) ];
+ }
+ aPageDesc.RegisterToPageDesc( *pPageDesc );
+ SwAttrSet aTmpAttrSet( pSrc->GetAttrSet() );
+ aTmpAttrSet.Put( aPageDesc );
+ pDest->SetFmtAttr( aTmpAttrSet );
+ }
+ else
+ {
+ pDest->SetFmtAttr( pSrc->GetAttrSet() );
+ }
+
+ pDest->SetPoolFmtId( pSrc->GetPoolFmtId() );
+ pDest->SetPoolHelpId( pSrc->GetPoolHelpId() );
+
+ // HelpFile-Id immer auf dflt setzen !!
+ pDest->SetPoolHlpFileId( UCHAR_MAX );
+
+ if( pSrc->DerivedFrom() )
+ pDest->SetDerivedFrom( FindFmtByName( rDestArr,
+ pSrc->DerivedFrom()->GetName() ) );
+ if( RES_TXTFMTCOLL == pSrc->Which() ||
+ RES_CONDTXTFMTCOLL == pSrc->Which() )
+ {
+ SwTxtFmtColl* pSrcColl = (SwTxtFmtColl*)pSrc,
+ * pDstColl = (SwTxtFmtColl*)pDest;
+ if( &pSrcColl->GetNextTxtFmtColl() != pSrcColl )
+ pDstColl->SetNextTxtFmtColl( *(SwTxtFmtColl*)FindFmtByName(
+ rDestArr, pSrcColl->GetNextTxtFmtColl().GetName() ) );
+
+ if(pSrcColl->IsAssignedToListLevelOfOutlineStyle())
+ pDstColl->AssignToListLevelOfOutlineStyle(pSrcColl->GetAssignedOutlineStyleLevel());//<-end,zhaojianwei
+ //<-end
+
+//FEATURE::CONDCOLL
+ if( RES_CONDTXTFMTCOLL == pSrc->Which() )
+ // Kopiere noch die Bedingungen
+ // aber erst die alten loeschen!
+ ((SwConditionTxtFmtColl*)pDstColl)->SetConditions(
+ ((SwConditionTxtFmtColl*)pSrc)->GetCondColls() );
+//FEATURE::CONDCOLL
+ }
+ }
+}
+
+void SwDoc::CopyPageDescHeaderFooterImpl( bool bCpyHeader,
+ const SwFrmFmt& rSrcFmt, SwFrmFmt& rDestFmt )
+{
+ // jetzt noch Header-/Footer-Attribute richtig behandeln
+ // Contenten Nodes Dokumentuebergreifend kopieren!
+ sal_uInt16 nAttr = static_cast<sal_uInt16>( bCpyHeader ? RES_HEADER : RES_FOOTER );
+ const SfxPoolItem* pItem;
+ if( SFX_ITEM_SET != rSrcFmt.GetAttrSet().GetItemState( nAttr, sal_False, &pItem ))
+ return ;
+
+ // Im Header steht noch der Verweis auf das Format aus dem
+ // anderen Document!!
+ SfxPoolItem* pNewItem = pItem->Clone();
+
+ SwFrmFmt* pOldFmt;
+ if( bCpyHeader )
+ pOldFmt = ((SwFmtHeader*)pNewItem)->GetHeaderFmt();
+ else
+ pOldFmt = ((SwFmtFooter*)pNewItem)->GetFooterFmt();
+
+ if( pOldFmt )
+ {
+ SwFrmFmt* pNewFmt = new SwFrmFmt( GetAttrPool(), "CpyDesc",
+ GetDfltFrmFmt() );
+ pNewFmt->CopyAttrs( *pOldFmt, sal_True );
+
+ if( SFX_ITEM_SET == pNewFmt->GetAttrSet().GetItemState(
+ RES_CNTNT, sal_False, &pItem ))
+ {
+ SwFmtCntnt* pCntnt = (SwFmtCntnt*)pItem;
+ if( pCntnt->GetCntntIdx() )
+ {
+ SwNodeIndex aTmpIdx( GetNodes().GetEndOfAutotext() );
+ const SwNodes& rSrcNds = rSrcFmt.GetDoc()->GetNodes();
+ SwStartNode* pSttNd = GetNodes().MakeEmptySection( aTmpIdx,
+ bCpyHeader
+ ? SwHeaderStartNode
+ : SwFooterStartNode );
+ const SwNode& rCSttNd = pCntnt->GetCntntIdx()->GetNode();
+ SwNodeRange aRg( rCSttNd, 0, *rCSttNd.EndOfSectionNode() );
+ aTmpIdx = *pSttNd->EndOfSectionNode();
+ rSrcNds._Copy( aRg, aTmpIdx );
+ aTmpIdx = *pSttNd;
+ rSrcFmt.GetDoc()->CopyFlyInFlyImpl( aRg, 0, aTmpIdx );
+ pNewFmt->SetFmtAttr( SwFmtCntnt( pSttNd ));
+ }
+ else
+ pNewFmt->ResetFmtAttr( RES_CNTNT );
+ }
+ if( bCpyHeader )
+ ((SwFmtHeader*)pNewItem)->RegisterToFormat(*pNewFmt);
+ else
+ ((SwFmtFooter*)pNewItem)->RegisterToFormat(*pNewFmt);
+ rDestFmt.SetFmtAttr( *pNewItem );
+ }
+ delete pNewItem;
+}
+
+void SwDoc::CopyPageDesc( const SwPageDesc& rSrcDesc, SwPageDesc& rDstDesc,
+ sal_Bool bCopyPoolIds )
+{
+ sal_Bool bNotifyLayout = sal_False;
+ SwRootFrm* pTmpRoot = GetCurrentLayout();//swmod 080219
+
+ rDstDesc.SetLandscape( rSrcDesc.GetLandscape() );
+ rDstDesc.SetNumType( rSrcDesc.GetNumType() );
+ if( rDstDesc.ReadUseOn() != rSrcDesc.ReadUseOn() )
+ {
+ rDstDesc.WriteUseOn( rSrcDesc.ReadUseOn() );
+ bNotifyLayout = sal_True;
+ }
+
+ if( bCopyPoolIds )
+ {
+ rDstDesc.SetPoolFmtId( rSrcDesc.GetPoolFmtId() );
+ rDstDesc.SetPoolHelpId( rSrcDesc.GetPoolHelpId() );
+ // HelpFile-Id immer auf dflt setzen !!
+ rDstDesc.SetPoolHlpFileId( UCHAR_MAX );
+ }
+
+ if( rSrcDesc.GetFollow() != &rSrcDesc )
+ {
+ SwPageDesc* pFollow = ::lcl_FindPageDesc( aPageDescs,
+ rSrcDesc.GetFollow()->GetName() );
+ if( !pFollow )
+ {
+ // dann mal kopieren
+ sal_uInt16 nPos = MakePageDesc( rSrcDesc.GetFollow()->GetName() );
+ pFollow = aPageDescs[ nPos ];
+ CopyPageDesc( *rSrcDesc.GetFollow(), *pFollow );
+ }
+ rDstDesc.SetFollow( pFollow );
+ bNotifyLayout = sal_True;
+ }
+
+ // die Header/Footer-Attribute werden gesondert kopiert, die Content-
+ // Sections muessen vollstaendig mitgenommen werden!
+ {
+ SfxItemSet aAttrSet( rSrcDesc.GetMaster().GetAttrSet() );
+ aAttrSet.ClearItem( RES_HEADER );
+ aAttrSet.ClearItem( RES_FOOTER );
+
+ rDstDesc.GetMaster().DelDiffs( aAttrSet );
+ rDstDesc.GetMaster().SetFmtAttr( aAttrSet );
+
+ aAttrSet.ClearItem();
+ aAttrSet.Put( rSrcDesc.GetLeft().GetAttrSet() );
+ aAttrSet.ClearItem( RES_HEADER );
+ aAttrSet.ClearItem( RES_FOOTER );
+
+ rDstDesc.GetLeft().DelDiffs( aAttrSet );
+ rDstDesc.GetLeft().SetFmtAttr( aAttrSet );
+ }
+
+ CopyHeader( rSrcDesc.GetMaster(), rDstDesc.GetMaster() );
+ CopyFooter( rSrcDesc.GetMaster(), rDstDesc.GetMaster() );
+ if( !rDstDesc.IsHeaderShared() )
+ CopyHeader( rSrcDesc.GetLeft(), rDstDesc.GetLeft() );
+ else
+ rDstDesc.GetLeft().SetFmtAttr( rDstDesc.GetMaster().GetHeader() );
+
+ if( !rDstDesc.IsFooterShared() )
+ CopyFooter( rSrcDesc.GetLeft(), rDstDesc.GetLeft() );
+ else
+ rDstDesc.GetLeft().SetFmtAttr( rDstDesc.GetMaster().GetFooter() );
+
+ if( bNotifyLayout && pTmpRoot )
+ {
+ std::set<SwRootFrm*> aAllLayouts = GetAllLayouts();//swmod 080225
+ std::for_each( aAllLayouts.begin(), aAllLayouts.end(),std::mem_fun(&SwRootFrm::AllCheckPageDescs));//swmod 080226
+ }
+
+ //Wenn sich FussnotenInfo veraendert, so werden die Seiten
+ //angetriggert.
+ if( !(rDstDesc.GetFtnInfo() == rSrcDesc.GetFtnInfo()) )
+ {
+ rDstDesc.SetFtnInfo( rSrcDesc.GetFtnInfo() );
+ SwMsgPoolItem aInfo( RES_PAGEDESC_FTNINFO );
+ {
+ rDstDesc.GetMaster().ModifyBroadcast( &aInfo, 0, TYPE(SwFrm) );
+ }
+ {
+ rDstDesc.GetLeft().ModifyBroadcast( &aInfo, 0, TYPE(SwFrm) );
+ }
+ }
+}
+
+void SwDoc::ReplaceStyles( SwDoc& rSource )
+{
+ ::sw::UndoGuard const undoGuard(GetIDocumentUndoRedo());
+
+ CopyFmtArr( *rSource.pCharFmtTbl, *pCharFmtTbl,
+ &SwDoc::_MakeCharFmt, *pDfltCharFmt );
+ CopyFmtArr( *rSource.pFrmFmtTbl, *pFrmFmtTbl,
+ &SwDoc::_MakeFrmFmt, *pDfltFrmFmt );
+ CopyFmtArr( *rSource.pTxtFmtCollTbl, *pTxtFmtCollTbl,
+ &SwDoc::_MakeTxtFmtColl, *pDfltTxtFmtColl );
+
+ // und jetzt noch die Seiten-Vorlagen
+ sal_uInt16 nCnt = rSource.aPageDescs.Count();
+ if( nCnt )
+ {
+ // ein anderes Doc -> Numberformatter muessen gemergt werden
+ SwTblNumFmtMerge aTNFM( rSource, *this );
+
+ // 1. Schritt alle Formate anlegen (das 0. ueberspringen - Default!)
+ while( nCnt )
+ {
+ SwPageDesc *pSrc = rSource.aPageDescs[ --nCnt ];
+ if( 0 == ::lcl_FindPageDesc( aPageDescs, pSrc->GetName() ) )
+ MakePageDesc( pSrc->GetName() );
+ }
+
+ // 2. Schritt alle Attribute kopieren, richtige Parents setzen
+ for( nCnt = rSource.aPageDescs.Count(); nCnt; )
+ {
+ SwPageDesc *pSrc = rSource.aPageDescs[ --nCnt ];
+ CopyPageDesc( *pSrc, *::lcl_FindPageDesc( aPageDescs, pSrc->GetName() ));
+ }
+ }
+
+ //JP 08.04.99: und dann sind da noch die Numerierungs-Vorlagen
+ nCnt = rSource.GetNumRuleTbl().Count();
+ if( nCnt )
+ {
+ const SwNumRuleTbl& rArr = rSource.GetNumRuleTbl();
+ for( sal_uInt16 n = 0; n < nCnt; ++n )
+ {
+ const SwNumRule& rR = *rArr[ n ];
+ if( !rR.IsAutoRule() )
+ {
+ SwNumRule* pNew = FindNumRulePtr( rR.GetName());
+ if( pNew )
+ pNew->CopyNumRule( this, rR );
+ else
+ MakeNumRule( rR.GetName(), &rR );
+ }
+ }
+ }
+
+ if (undoGuard.UndoWasEnabled())
+ {
+ // nodes array was modified!
+ GetIDocumentUndoRedo().DelAllUndoObj();
+ }
+
+ SetModified();
+}
+
+SwFmt* SwDoc::FindFmtByName( const SvPtrarr& rFmtArr,
+ const String& rName ) const
+{
+ SwFmt* pFnd = 0;
+ for( sal_uInt16 n = 0; n < rFmtArr.Count(); n++ )
+ {
+ // ist die Vorlage schon im Doc vorhanden ??
+ if( ((SwFmt*)rFmtArr[n])->GetName() == rName )
+ {
+ pFnd = (SwFmt*)rFmtArr[n];
+ break;
+ }
+ }
+ return pFnd;
+}
+
+void SwDoc::MoveLeftMargin( const SwPaM& rPam, sal_Bool bRight, sal_Bool bModulus )
+{
+ SwHistory* pHistory = 0;
+ if (GetIDocumentUndoRedo().DoesUndo())
+ {
+ SwUndoMoveLeftMargin* pUndo = new SwUndoMoveLeftMargin( rPam, bRight,
+ bModulus );
+ pHistory = &pUndo->GetHistory();
+ GetIDocumentUndoRedo().AppendUndo( pUndo );
+ }
+
+ const SvxTabStopItem& rTabItem = (SvxTabStopItem&)GetDefault( RES_PARATR_TABSTOP );
+ sal_uInt16 nDefDist = rTabItem.Count() ?
+ static_cast<sal_uInt16>(rTabItem[0].GetTabPos()) : 1134;
+ const SwPosition &rStt = *rPam.Start(), &rEnd = *rPam.End();
+ SwNodeIndex aIdx( rStt.nNode );
+ while( aIdx <= rEnd.nNode )
+ {
+ SwTxtNode* pTNd = aIdx.GetNode().GetTxtNode();
+ if( pTNd )
+ {
+ SvxLRSpaceItem aLS( (SvxLRSpaceItem&)pTNd->SwCntntNode::GetAttr( RES_LR_SPACE ) );
+
+ // #i93873# See also lcl_MergeListLevelIndentAsLRSpaceItem in thints.cxx
+ if ( pTNd->AreListLevelIndentsApplicable() )
+ {
+ const SwNumRule* pRule = pTNd->GetNumRule();
+ if ( pRule )
+ {
+ const int nListLevel = pTNd->GetActualListLevel();
+ if ( nListLevel >= 0 )
+ {
+ const SwNumFmt& rFmt = pRule->Get(static_cast<sal_uInt16>(nListLevel));
+ if ( rFmt.GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_ALIGNMENT )
+ {
+ aLS.SetTxtLeft( rFmt.GetIndentAt() );
+ aLS.SetTxtFirstLineOfst( static_cast<short>(rFmt.GetFirstLineIndent()) );
+ }
+ }
+ }
+ }
+
+ long nNext = aLS.GetTxtLeft();
+ if( bModulus )
+ nNext = ( nNext / nDefDist ) * nDefDist;
+
+ if( bRight )
+ nNext += nDefDist;
+ else
+ nNext -= nDefDist;
+
+ aLS.SetTxtLeft( nNext );
+
+ SwRegHistory aRegH( pTNd, *pTNd, pHistory );
+ pTNd->SetAttr( aLS );
+ }
+ aIdx++;
+ }
+ SetModified();
+}
+
+sal_Bool SwDoc::DontExpandFmt( const SwPosition& rPos, sal_Bool bFlag )
+{
+ sal_Bool bRet = sal_False;
+ SwTxtNode* pTxtNd = rPos.nNode.GetNode().GetTxtNode();
+ if( pTxtNd )
+ {
+ bRet = pTxtNd->DontExpandFmt( rPos.nContent, bFlag );
+ if( bRet && GetIDocumentUndoRedo().DoesUndo() )
+ {
+ GetIDocumentUndoRedo().AppendUndo( new SwUndoDontExpandFmt(rPos) );
+ }
+ }
+ return bRet;
+}
+
+SwTableBoxFmt* SwDoc::MakeTableBoxFmt()
+{
+ SwTableBoxFmt* pFmt = new SwTableBoxFmt( GetAttrPool(), aEmptyStr,
+ pDfltFrmFmt );
+ SetModified();
+ return pFmt;
+}
+
+SwTableLineFmt* SwDoc::MakeTableLineFmt()
+{
+ SwTableLineFmt* pFmt = new SwTableLineFmt( GetAttrPool(), aEmptyStr,
+ pDfltFrmFmt );
+ SetModified();
+ return pFmt;
+}
+
+void SwDoc::_CreateNumberFormatter()
+{
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLog, "SW", "JP93722", "SwDoc::_CreateNumberFormatter" );
+
+ OSL_ENSURE( !pNumberFormatter, "ist doch schon vorhanden" );
+
+
+ LanguageType eLang = LANGUAGE_SYSTEM;
+
+ Reference< XMultiServiceFactory > xMSF = ::comphelper::getProcessServiceFactory();
+ pNumberFormatter = new SvNumberFormatter( xMSF, eLang );
+ pNumberFormatter->SetEvalDateFormat( NF_EVALDATEFORMAT_FORMAT_INTL );
+ pNumberFormatter->SetYear2000(static_cast<sal_uInt16>(::utl::MiscCfg().GetYear2000()));
+
+}
+
+SwTblNumFmtMerge::SwTblNumFmtMerge( const SwDoc& rSrc, SwDoc& rDest )
+ : pNFmt( 0 )
+{
+ // ein anderes Doc -> Numberformatter muessen gemergt werden
+ SvNumberFormatter* pN;
+ if( &rSrc != &rDest && 0 != ( pN = ((SwDoc&)rSrc).GetNumberFormatter( sal_False ) ))
+ ( pNFmt = rDest.GetNumberFormatter( sal_True ))->MergeFormatter( *pN );
+
+ if( &rSrc != &rDest )
+ ((SwGetRefFieldType*)rSrc.GetSysFldType( RES_GETREFFLD ))->
+ MergeWithOtherDoc( rDest );
+}
+
+SwTblNumFmtMerge::~SwTblNumFmtMerge()
+{
+ if( pNFmt )
+ pNFmt->ClearMergeTable();
+}
+
+
+void SwDoc::SetTxtFmtCollByAutoFmt( const SwPosition& rPos, sal_uInt16 nPoolId,
+ const SfxItemSet* pSet )
+{
+ SwPaM aPam( rPos );
+ SwTxtNode* pTNd = rPos.nNode.GetNode().GetTxtNode();
+
+ if( mbIsAutoFmtRedline && pTNd )
+ {
+ // dann das Redline Object anlegen
+ const SwTxtFmtColl& rColl = *pTNd->GetTxtColl();
+ SwRedline* pRedl = new SwRedline( nsRedlineType_t::REDLINE_FMTCOLL, aPam );
+ pRedl->SetMark();
+
+ // interressant sind nur die Items, die vom Set NICHT wieder
+ // in den Node gesetzt werden. Also muss man die Differenz nehmen
+ SwRedlineExtraData_FmtColl aExtraData( rColl.GetName(),
+ rColl.GetPoolFmtId() );
+ if( pSet && pTNd->HasSwAttrSet() )
+ {
+ SfxItemSet aTmp( *pTNd->GetpSwAttrSet() );
+ aTmp.Differentiate( *pSet );
+ // das Adjust Item behalten wir extra
+ const SfxPoolItem* pItem;
+ if( SFX_ITEM_SET == pTNd->GetpSwAttrSet()->GetItemState(
+ RES_PARATR_ADJUST, sal_False, &pItem ))
+ aTmp.Put( *pItem );
+ aExtraData.SetItemSet( aTmp );
+ }
+ pRedl->SetExtraData( &aExtraData );
+
+// !!!!!!!!! Undo fehlt noch !!!!!!!!!!!!!!!!!!
+ AppendRedline( pRedl, true );
+ }
+
+ SetTxtFmtColl( aPam, GetTxtCollFromPool( nPoolId ) );
+
+ if( pSet && pTNd && pSet->Count() )
+ {
+ aPam.SetMark();
+ aPam.GetMark()->nContent.Assign( pTNd, pTNd->GetTxt().Len() );
+ InsertItemSet( aPam, *pSet, 0 );
+ }
+}
+
+void SwDoc::SetFmtItemByAutoFmt( const SwPaM& rPam, const SfxItemSet& rSet )
+{
+ SwTxtNode* pTNd = rPam.GetPoint()->nNode.GetNode().GetTxtNode();
+
+ RedlineMode_t eOld = GetRedlineMode();
+
+ if( mbIsAutoFmtRedline && pTNd )
+ {
+ // dann das Redline Object anlegen
+ SwRedline* pRedl = new SwRedline( nsRedlineType_t::REDLINE_FORMAT, rPam );
+ if( !pRedl->HasMark() )
+ pRedl->SetMark();
+
+ // interressant sind nur die Items, die vom Set NICHT wieder
+ // in den Node gesetzt werden. Also muss man die Differenz nehmen
+ SwRedlineExtraData_Format aExtraData( rSet );
+
+ pRedl->SetExtraData( &aExtraData );
+
+// !!!!!!!!! Undo fehlt noch !!!!!!!!!!!!!!!!!!
+ AppendRedline( pRedl, true );
+
+ SetRedlineMode_intern( (RedlineMode_t)(eOld | nsRedlineMode_t::REDLINE_IGNORE));
+ }
+
+ InsertItemSet( rPam, rSet, nsSetAttrMode::SETATTR_DONTEXPAND );
+ SetRedlineMode_intern( eOld );
+}
+
+void SwDoc::ChgFmt(SwFmt & rFmt, const SfxItemSet & rSet)
+{
+ if (GetIDocumentUndoRedo().DoesUndo())
+ {
+ // copying <rSet> to <aSet>
+ SfxItemSet aSet(rSet);
+ // remove from <aSet> all items, which are already set at the format
+ aSet.Differentiate(rFmt.GetAttrSet());
+ // <aSet> contains now all *new* items for the format
+
+ // copying current format item set to <aOldSet>
+ SfxItemSet aOldSet(rFmt.GetAttrSet());
+ // insert new items into <aOldSet>
+ aOldSet.Put(aSet);
+ // invalidate all new items in <aOldSet> in order to clear these items,
+ // if the undo action is triggered.
+ {
+ SfxItemIter aIter(aSet);
+
+ const SfxPoolItem * pItem = aIter.FirstItem();
+ while (pItem != NULL)
+ {
+ aOldSet.InvalidateItem(pItem->Which());
+
+ pItem = aIter.NextItem();
+ }
+ }
+
+ SwUndo * pUndo = new SwUndoFmtAttr(aOldSet, rFmt);
+
+ GetIDocumentUndoRedo().AppendUndo(pUndo);
+ }
+
+ rFmt.SetFmtAttr(rSet);
+}
+
+void SwDoc::RenameFmt(SwFmt & rFmt, const String & sNewName,
+ sal_Bool bBroadcast)
+{
+ SfxStyleFamily eFamily = SFX_STYLE_FAMILY_ALL;
+
+ if (GetIDocumentUndoRedo().DoesUndo())
+ {
+ SwUndo * pUndo = NULL;
+
+ switch (rFmt.Which())
+ {
+ case RES_CHRFMT:
+ pUndo = new SwUndoRenameCharFmt(rFmt.GetName(), sNewName, this);
+ eFamily = SFX_STYLE_FAMILY_PARA;
+ break;
+ case RES_TXTFMTCOLL:
+ pUndo = new SwUndoRenameFmtColl(rFmt.GetName(), sNewName, this);
+ eFamily = SFX_STYLE_FAMILY_CHAR;
+ break;
+ case RES_FRMFMT:
+ pUndo = new SwUndoRenameFrmFmt(rFmt.GetName(), sNewName, this);
+ eFamily = SFX_STYLE_FAMILY_FRAME;
+ break;
+
+ default:
+ break;
+ }
+
+ if (pUndo)
+ {
+ GetIDocumentUndoRedo().AppendUndo(pUndo);
+ }
+ }
+
+ rFmt.SetName(sNewName);
+
+ if (bBroadcast)
+ BroadcastStyleOperation(sNewName, eFamily, SFX_STYLESHEET_MODIFIED);
+}
+
+// #i69627#
+namespace docfunc
+{
+ bool HasOutlineStyleToBeWrittenAsNormalListStyle( SwDoc& rDoc )
+ {
+ // If a parent paragraph style of one of the parargraph styles, which
+ // are assigned to the list levels of the outline style, has a list style
+ // set or inherits a list style from its parent style, the outline style
+ // has to be written as a normal list style to the OpenDocument file
+ // format or the OpenOffice.org file format.
+ bool bRet( false );
+
+ const SwTxtFmtColls* pTxtFmtColls( rDoc.GetTxtFmtColls() );
+ if ( pTxtFmtColls )
+ {
+ const sal_uInt16 nCount = pTxtFmtColls->Count();
+ for ( sal_uInt16 i = 0; i < nCount; ++i )
+ {
+ SwTxtFmtColl* pTxtFmtColl = (*pTxtFmtColls)[i];
+
+ if ( pTxtFmtColl->IsDefault() ||
+ ! pTxtFmtColl->IsAssignedToListLevelOfOutlineStyle() ) //<-end,zhaojianwei
+ {
+ continue;
+ }
+
+ const SwTxtFmtColl* pParentTxtFmtColl =
+ dynamic_cast<const SwTxtFmtColl*>( pTxtFmtColl->DerivedFrom());
+ if ( !pParentTxtFmtColl )
+ continue;
+
+ if ( SFX_ITEM_SET == pParentTxtFmtColl->GetItemState( RES_PARATR_NUMRULE ) )
+ {
+ // #i106218# consider that the outline style is set
+ const SwNumRuleItem& rDirectItem = pParentTxtFmtColl->GetNumRule();
+ if ( rDirectItem.GetValue() != rDoc.GetOutlineNumRule()->GetName() )
+ {
+ bRet = true;
+ break;
+ }
+ }
+ }
+
+ }
+ return bRet;
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/doc/docftn.cxx b/sw/source/core/doc/docftn.cxx
new file mode 100644
index 000000000000..8d7c8523aa46
--- /dev/null
+++ b/sw/source/core/doc/docftn.cxx
@@ -0,0 +1,529 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+
+#include <ftnidx.hxx>
+#include <rootfrm.hxx>
+#include <txtftn.hxx>
+#include <fmtftn.hxx>
+#include <pam.hxx>
+#include <pagedesc.hxx>
+#include <charfmt.hxx>
+#include <UndoAttribute.hxx>
+#include <hints.hxx>
+#include <rolbck.hxx>
+#include <doc.hxx>
+#include <IDocumentUndoRedo.hxx>
+#include <ndtxt.hxx>
+#include <poolfmt.hxx>
+#include <ftninfo.hxx>
+
+/*********************** SwFtnInfo ***************************/
+
+SwEndNoteInfo& SwEndNoteInfo::operator=(const SwEndNoteInfo& rInfo)
+{
+ if( rInfo.GetFtnTxtColl() )
+ rInfo.GetFtnTxtColl()->Add(this);
+ else if ( GetRegisteredIn())
+ GetRegisteredInNonConst()->Remove(this);
+
+ if ( rInfo.aPageDescDep.GetRegisteredIn() )
+ ((SwModify*)rInfo.aPageDescDep.GetRegisteredIn())->Add( &aPageDescDep );
+ else if ( aPageDescDep.GetRegisteredIn() )
+ ((SwModify*)aPageDescDep.GetRegisteredIn())->Remove( &aPageDescDep );
+
+ if ( rInfo.aCharFmtDep.GetRegisteredIn() )
+ ((SwModify*)rInfo.aCharFmtDep.GetRegisteredIn())->Add( &aCharFmtDep );
+ else if ( aCharFmtDep.GetRegisteredIn() )
+ ((SwModify*)aCharFmtDep.GetRegisteredIn())->Remove( &aCharFmtDep );
+
+ if ( rInfo.aAnchorCharFmtDep.GetRegisteredIn() )
+ ((SwModify*)rInfo.aAnchorCharFmtDep.GetRegisteredIn())->Add(
+ &aAnchorCharFmtDep );
+ else if( aAnchorCharFmtDep.GetRegisteredIn() )
+ ((SwModify*)aAnchorCharFmtDep.GetRegisteredIn())->Remove(
+ &aAnchorCharFmtDep );
+
+ aFmt = rInfo.aFmt;
+ nFtnOffset = rInfo.nFtnOffset;
+ m_bEndNote = rInfo.m_bEndNote;
+ sPrefix = rInfo.sPrefix;
+ sSuffix = rInfo.sSuffix;
+ return *this;
+}
+
+
+sal_Bool SwEndNoteInfo::operator==( const SwEndNoteInfo& rInfo ) const
+{
+ return aPageDescDep.GetRegisteredIn() ==
+ rInfo.aPageDescDep.GetRegisteredIn() &&
+ aCharFmtDep.GetRegisteredIn() ==
+ rInfo.aCharFmtDep.GetRegisteredIn() &&
+ aAnchorCharFmtDep.GetRegisteredIn() ==
+ rInfo.aAnchorCharFmtDep.GetRegisteredIn() &&
+ GetFtnTxtColl() == rInfo.GetFtnTxtColl() &&
+ aFmt.GetNumberingType() == rInfo.aFmt.GetNumberingType() &&
+ nFtnOffset == rInfo.nFtnOffset &&
+ m_bEndNote == rInfo.m_bEndNote &&
+ sPrefix == rInfo.sPrefix &&
+ sSuffix == rInfo.sSuffix;
+}
+
+
+SwEndNoteInfo::SwEndNoteInfo(const SwEndNoteInfo& rInfo) :
+ SwClient( rInfo.GetFtnTxtColl() ),
+ aPageDescDep( this, 0 ),
+ aCharFmtDep( this, 0 ),
+ aAnchorCharFmtDep( this, 0 ),
+ sPrefix( rInfo.sPrefix ),
+ sSuffix( rInfo.sSuffix ),
+ m_bEndNote( true ),
+ aFmt( rInfo.aFmt ),
+ nFtnOffset( rInfo.nFtnOffset )
+{
+ if( rInfo.aPageDescDep.GetRegisteredIn() )
+ ((SwModify*)rInfo.aPageDescDep.GetRegisteredIn())->Add( &aPageDescDep );
+
+ if( rInfo.aCharFmtDep.GetRegisteredIn() )
+ ((SwModify*)rInfo.aCharFmtDep.GetRegisteredIn())->Add( &aCharFmtDep );
+
+ if( rInfo.aAnchorCharFmtDep.GetRegisteredIn() )
+ ((SwModify*)rInfo.aAnchorCharFmtDep.GetRegisteredIn())->Add(
+ &aAnchorCharFmtDep );
+}
+
+SwEndNoteInfo::SwEndNoteInfo(SwTxtFmtColl *pFmt) :
+ SwClient(pFmt),
+ aPageDescDep( this, 0 ),
+ aCharFmtDep( this, 0 ),
+ aAnchorCharFmtDep( this, 0 ),
+ m_bEndNote( true ),
+ nFtnOffset( 0 )
+{
+ aFmt.SetNumberingType(SVX_NUM_ROMAN_LOWER);
+}
+
+SwPageDesc *SwEndNoteInfo::GetPageDesc( SwDoc &rDoc ) const
+{
+ if ( !aPageDescDep.GetRegisteredIn() )
+ {
+ SwPageDesc *pDesc = rDoc.GetPageDescFromPool( static_cast<sal_uInt16>(
+ m_bEndNote ? RES_POOLPAGE_ENDNOTE : RES_POOLPAGE_FOOTNOTE ) );
+ pDesc->Add( &((SwClient&)aPageDescDep) );
+ }
+
+ return (SwPageDesc*)( aPageDescDep.GetRegisteredIn() );
+}
+
+bool SwEndNoteInfo::KnowsPageDesc() const
+{
+ return (aPageDescDep.GetRegisteredIn() != 0);
+}
+
+bool SwEndNoteInfo::DependsOn( const SwPageDesc* pDesc ) const
+{
+ return ( aPageDescDep.GetRegisteredIn() == pDesc );
+}
+
+void SwEndNoteInfo::ChgPageDesc( SwPageDesc *pDesc )
+{
+ pDesc->Add( &((SwClient&)aPageDescDep) );
+}
+
+void SwEndNoteInfo::SetFtnTxtColl(SwTxtFmtColl& rFmt)
+{
+ rFmt.Add(this);
+}
+
+SwCharFmt* SwEndNoteInfo::GetCharFmt(SwDoc &rDoc) const
+{
+ if ( !aCharFmtDep.GetRegisteredIn() )
+ {
+ SwCharFmt* pFmt = rDoc.GetCharFmtFromPool( static_cast<sal_uInt16>(
+ m_bEndNote ? RES_POOLCHR_ENDNOTE : RES_POOLCHR_FOOTNOTE ) );
+ pFmt->Add( &((SwClient&)aCharFmtDep) );
+ }
+ return (SwCharFmt*)aCharFmtDep.GetRegisteredIn();
+}
+
+void SwEndNoteInfo::SetCharFmt( SwCharFmt* pChFmt )
+{
+ DBG_ASSERT(pChFmt, "kein CharFmt?");
+ pChFmt->Add( &((SwClient&)aCharFmtDep) );
+}
+
+SwCharFmt* SwEndNoteInfo::GetAnchorCharFmt(SwDoc &rDoc) const
+{
+ if( !aAnchorCharFmtDep.GetRegisteredIn() )
+ {
+ SwCharFmt* pFmt = rDoc.GetCharFmtFromPool( static_cast<sal_uInt16>(
+ m_bEndNote ? RES_POOLCHR_ENDNOTE_ANCHOR : RES_POOLCHR_FOOTNOTE_ANCHOR ) );
+ pFmt->Add( &((SwClient&)aAnchorCharFmtDep) );
+ }
+ return (SwCharFmt*)aAnchorCharFmtDep.GetRegisteredIn();
+}
+
+void SwEndNoteInfo::SetAnchorCharFmt( SwCharFmt* pChFmt )
+{
+ DBG_ASSERT(pChFmt, "kein CharFmt?");
+ pChFmt->Add( &((SwClient&)aAnchorCharFmtDep) );
+}
+
+void SwEndNoteInfo::Modify( const SfxPoolItem* pOld, const SfxPoolItem* pNew )
+{
+ sal_uInt16 nWhich = pOld ? pOld->Which() : pNew ? pNew->Which() : 0 ;
+
+ if( RES_ATTRSET_CHG == nWhich ||
+ RES_FMT_CHG == nWhich )
+ {
+ SwDoc* pDoc;
+ if( aCharFmtDep.GetRegisteredIn() )
+ pDoc = ((SwCharFmt*)aCharFmtDep.GetRegisteredIn())->GetDoc();
+ else
+ pDoc = ((SwCharFmt*)aAnchorCharFmtDep.GetRegisteredIn())->GetDoc();
+ SwFtnIdxs& rFtnIdxs = pDoc->GetFtnIdxs();
+ for( sal_uInt16 nPos = 0; nPos < rFtnIdxs.Count(); ++nPos )
+ {
+ SwTxtFtn *pTxtFtn = rFtnIdxs[ nPos ];
+ const SwFmtFtn &rFtn = pTxtFtn->GetFtn();
+ if ( rFtn.IsEndNote() == m_bEndNote )
+ {
+ pTxtFtn->SetNumber( rFtn.GetNumber(), &rFtn.GetNumStr());
+ }
+ }
+ }
+ else
+ CheckRegistration( pOld, pNew );
+}
+
+SwFtnInfo& SwFtnInfo::operator=(const SwFtnInfo& rInfo)
+{
+ SwEndNoteInfo::operator=(rInfo);
+ aQuoVadis = rInfo.aQuoVadis;
+ aErgoSum = rInfo.aErgoSum;
+ ePos = rInfo.ePos;
+ eNum = rInfo.eNum;
+ return *this;
+}
+
+
+sal_Bool SwFtnInfo::operator==( const SwFtnInfo& rInfo ) const
+{
+ return ePos == rInfo.ePos &&
+ eNum == rInfo.eNum &&
+ SwEndNoteInfo::operator==(rInfo) &&
+ aQuoVadis == rInfo.aQuoVadis &&
+ aErgoSum == rInfo.aErgoSum;
+}
+
+
+SwFtnInfo::SwFtnInfo(const SwFtnInfo& rInfo) :
+ SwEndNoteInfo( rInfo ),
+ aQuoVadis( rInfo.aQuoVadis ),
+ aErgoSum( rInfo.aErgoSum ),
+ ePos( rInfo.ePos ),
+ eNum( rInfo.eNum )
+{
+ m_bEndNote = false;
+}
+
+SwFtnInfo::SwFtnInfo(SwTxtFmtColl *pFmt) :
+ SwEndNoteInfo( pFmt ),
+ ePos( FTNPOS_PAGE ),
+ eNum( FTNNUM_DOC )
+{
+ aFmt.SetNumberingType(SVX_NUM_ARABIC);
+ m_bEndNote = false;
+}
+
+/*********************** SwDoc ***************************/
+
+
+void SwDoc::SetFtnInfo(const SwFtnInfo& rInfo)
+{
+ SwRootFrm* pTmpRoot = GetCurrentLayout();//swmod 080219
+ if( !(GetFtnInfo() == rInfo) )
+ {
+ const SwFtnInfo &rOld = GetFtnInfo();
+
+ if (GetIDocumentUndoRedo().DoesUndo())
+ {
+ GetIDocumentUndoRedo().AppendUndo( new SwUndoFootNoteInfo(rOld) );
+ }
+
+ sal_Bool bFtnPos = rInfo.ePos != rOld.ePos;
+ sal_Bool bFtnDesc = rOld.ePos == FTNPOS_CHAPTER &&
+ rInfo.GetPageDesc( *this ) != rOld.GetPageDesc( *this );
+ sal_Bool bExtra = rInfo.aQuoVadis != rOld.aQuoVadis ||
+ rInfo.aErgoSum != rOld.aErgoSum ||
+ rInfo.aFmt.GetNumberingType() != rOld.aFmt.GetNumberingType() ||
+ rInfo.GetPrefix() != rOld.GetPrefix() ||
+ rInfo.GetSuffix() != rOld.GetSuffix();
+ SwCharFmt *pOldChrFmt = rOld.GetCharFmt( *this ),
+ *pNewChrFmt = rInfo.GetCharFmt( *this );
+ sal_Bool bFtnChrFmts = pOldChrFmt != pNewChrFmt;
+
+ *pFtnInfo = rInfo;
+
+ if (pTmpRoot)
+ {
+ std::set<SwRootFrm*> aAllLayouts = GetAllLayouts();//swmod 080304
+ if ( bFtnPos )
+ //pTmpRoot->RemoveFtns();
+ std::for_each( aAllLayouts.begin(), aAllLayouts.end(),std::mem_fun(&SwRootFrm::AllRemoveFtns));//swmod 080305
+ else
+ {
+ //pTmpRoot->UpdateFtnNums();
+ std::for_each( aAllLayouts.begin(), aAllLayouts.end(),std::mem_fun(&SwRootFrm::UpdateFtnNums));//swmod 080304
+ if ( bFtnDesc )
+ //pTmpRoot->CheckFtnPageDescs( FALSE );
+ std::for_each( aAllLayouts.begin(), aAllLayouts.end(),std::bind2nd(std::mem_fun(&SwRootFrm::CheckFtnPageDescs), sal_False));//swmod 080304
+ if ( bExtra )
+ {
+ //Fuer die Benachrichtung bezueglich ErgoSum usw. sparen wir uns
+ //extra-Code und nutzen die vorhandenen Wege.
+ SwFtnIdxs& rFtnIdxs = GetFtnIdxs();
+ for( sal_uInt16 nPos = 0; nPos < rFtnIdxs.Count(); ++nPos )
+ {
+ SwTxtFtn *pTxtFtn = rFtnIdxs[ nPos ];
+ const SwFmtFtn &rFtn = pTxtFtn->GetFtn();
+ if ( !rFtn.IsEndNote() )
+ pTxtFtn->SetNumber( rFtn.GetNumber(), &rFtn.GetNumStr());
+ }
+ }
+ }
+ } //swmod 080219
+ if( FTNNUM_PAGE != rInfo.eNum )
+ GetFtnIdxs().UpdateAllFtn();
+ else if( bFtnChrFmts )
+ {
+ SwFmtChg aOld( pOldChrFmt );
+ SwFmtChg aNew( pNewChrFmt );
+ pFtnInfo->ModifyNotification( &aOld, &aNew );
+ }
+
+ // #i81002# no update during loading
+ if ( !IsInReading() )
+ {
+ UpdateRefFlds(NULL);
+ }
+ SetModified();
+ }
+}
+
+void SwDoc::SetEndNoteInfo(const SwEndNoteInfo& rInfo)
+{
+ SwRootFrm* pTmpRoot = GetCurrentLayout();//swmod 080219
+ if( !(GetEndNoteInfo() == rInfo) )
+ {
+ if(GetIDocumentUndoRedo().DoesUndo())
+ {
+ SwUndo *const pUndo( new SwUndoEndNoteInfo( GetEndNoteInfo() ) );
+ GetIDocumentUndoRedo().AppendUndo(pUndo);
+ }
+
+ sal_Bool bNumChg = rInfo.nFtnOffset != GetEndNoteInfo().nFtnOffset;
+ // this seems to be an optimization: UpdateAllFtn() is only called
+ // if the offset changes; if the offset is the same,
+ // but type/prefix/suffix changes, just set new numbers.
+ bool const bExtra = !bNumChg &&
+ ( (rInfo.aFmt.GetNumberingType() !=
+ GetEndNoteInfo().aFmt.GetNumberingType())
+ || (rInfo.GetPrefix() != GetEndNoteInfo().GetPrefix())
+ || (rInfo.GetSuffix() != GetEndNoteInfo().GetSuffix())
+ );
+ sal_Bool bFtnDesc = rInfo.GetPageDesc( *this ) !=
+ GetEndNoteInfo().GetPageDesc( *this );
+ SwCharFmt *pOldChrFmt = GetEndNoteInfo().GetCharFmt( *this ),
+ *pNewChrFmt = rInfo.GetCharFmt( *this );
+ sal_Bool bFtnChrFmts = pOldChrFmt != pNewChrFmt;
+
+ *pEndNoteInfo = rInfo;
+
+ if ( pTmpRoot )
+ {
+ if ( bFtnDesc )
+ //pTmpRoot->CheckFtnPageDescs( TRUE );
+ {
+ std::set<SwRootFrm*> aAllLayouts = GetAllLayouts();
+ std::for_each( aAllLayouts.begin(), aAllLayouts.end(),std::bind2nd(std::mem_fun(&SwRootFrm::CheckFtnPageDescs), sal_True));//swmod 080304
+ }
+ if ( bExtra )
+ {
+ //Fuer die Benachrichtung bezueglich ErgoSum usw. sparen wir uns
+ //extra-Code und nutzen die vorhandenen Wege.
+ SwFtnIdxs& rFtnIdxs = GetFtnIdxs();
+ for( sal_uInt16 nPos = 0; nPos < rFtnIdxs.Count(); ++nPos )
+ {
+ SwTxtFtn *pTxtFtn = rFtnIdxs[ nPos ];
+ const SwFmtFtn &rFtn = pTxtFtn->GetFtn();
+ if ( rFtn.IsEndNote() )
+ pTxtFtn->SetNumber( rFtn.GetNumber(), &rFtn.GetNumStr());
+ }
+ }
+ } //swmod 080219
+ if( bNumChg )
+ GetFtnIdxs().UpdateAllFtn();
+ else if( bFtnChrFmts )
+ {
+ SwFmtChg aOld( pOldChrFmt );
+ SwFmtChg aNew( pNewChrFmt );
+ pEndNoteInfo->ModifyNotification( &aOld, &aNew );
+ }
+
+ // #i81002# no update during loading
+ if ( !IsInReading() )
+ {
+ UpdateRefFlds(NULL);
+ }
+ SetModified();
+ }
+}
+
+
+bool SwDoc::SetCurFtn( const SwPaM& rPam, const String& rNumStr,
+ sal_uInt16 nNumber, bool bIsEndNote )
+{
+ SwFtnIdxs& rFtnArr = GetFtnIdxs();
+ SwRootFrm* pTmpRoot = GetCurrentLayout();//swmod 080219
+
+ const SwPosition* pStt = rPam.Start(), *pEnd = rPam.End();
+ const sal_uLong nSttNd = pStt->nNode.GetIndex();
+ const xub_StrLen nSttCnt = pStt->nContent.GetIndex();
+ const sal_uLong nEndNd = pEnd->nNode.GetIndex();
+ const xub_StrLen nEndCnt = pEnd->nContent.GetIndex();
+
+ sal_uInt16 nPos;
+ rFtnArr.SeekEntry( pStt->nNode, &nPos );
+
+ SwUndoChangeFootNote* pUndo = 0;
+ if (GetIDocumentUndoRedo().DoesUndo())
+ {
+ GetIDocumentUndoRedo().ClearRedo(); // AppendUndo far below, so leave it
+ pUndo = new SwUndoChangeFootNote( rPam, rNumStr, nNumber, bIsEndNote );
+ }
+
+ SwTxtFtn* pTxtFtn;
+ sal_uLong nIdx;
+ sal_Bool bChg = sal_False;
+ sal_Bool bTypeChgd = sal_False;
+ sal_uInt16 n = nPos; // sichern
+ while( nPos < rFtnArr.Count() &&
+ (( nIdx = _SwTxtFtn_GetIndex((pTxtFtn = rFtnArr[ nPos++ ] )))
+ < nEndNd || ( nIdx == nEndNd &&
+ nEndCnt >= *pTxtFtn->GetStart() )) )
+ if( nIdx > nSttNd || ( nIdx == nSttNd &&
+ nSttCnt <= *pTxtFtn->GetStart() ) )
+ {
+ const SwFmtFtn& rFtn = pTxtFtn->GetFtn();
+ if( rFtn.GetNumStr() != rNumStr ||
+ rFtn.IsEndNote() != bIsEndNote )
+ {
+ bChg = sal_True;
+ if ( pUndo )
+ {
+ pUndo->GetHistory().Add( *pTxtFtn );
+ }
+
+ pTxtFtn->SetNumber( nNumber, &rNumStr );
+ if( rFtn.IsEndNote() != bIsEndNote )
+ {
+ ((SwFmtFtn&)rFtn).SetEndNote( bIsEndNote );
+ bTypeChgd = sal_True;
+ pTxtFtn->CheckCondColl();
+ //#i11339# dispose UNO wrapper when a footnote is changed to an endnote or vice versa
+ SwPtrMsgPoolItem aMsgHint( RES_FOOTNOTE_DELETED, (void*)&pTxtFtn->GetAttr() );
+ GetUnoCallBack()->ModifyNotification( &aMsgHint, &aMsgHint );
+ }
+ }
+ }
+
+ nPos = n; // nach vorne gibt es auch noch welche !
+ while( nPos &&
+ (( nIdx = _SwTxtFtn_GetIndex((pTxtFtn = rFtnArr[ --nPos ] )))
+ > nSttNd || ( nIdx == nSttNd &&
+ nSttCnt <= *pTxtFtn->GetStart() )) )
+ if( nIdx < nEndNd || ( nIdx == nEndNd &&
+ nEndCnt >= *pTxtFtn->GetStart() ) )
+ {
+ const SwFmtFtn& rFtn = pTxtFtn->GetFtn();
+ if( rFtn.GetNumStr() != rNumStr ||
+ rFtn.IsEndNote() != bIsEndNote )
+ {
+ bChg = sal_True;
+ if ( pUndo )
+ {
+ pUndo->GetHistory().Add( *pTxtFtn );
+ }
+
+ pTxtFtn->SetNumber( nNumber, &rNumStr );
+ if( rFtn.IsEndNote() != bIsEndNote )
+ {
+ ((SwFmtFtn&)rFtn).SetEndNote( bIsEndNote );
+ bTypeChgd = sal_True;
+ pTxtFtn->CheckCondColl();
+ }
+ }
+ }
+
+ // wer muss angestossen werden ??
+ if( bChg )
+ {
+ if( pUndo )
+ {
+ GetIDocumentUndoRedo().AppendUndo(pUndo);
+ }
+
+ if ( bTypeChgd )
+ rFtnArr.UpdateAllFtn();
+ if( FTNNUM_PAGE != GetFtnInfo().eNum )
+ {
+ if ( !bTypeChgd )
+ rFtnArr.UpdateAllFtn();
+ }
+ else if( pTmpRoot )
+ //
+ {
+ std::set<SwRootFrm*> aAllLayouts = GetAllLayouts();
+ std::for_each( aAllLayouts.begin(), aAllLayouts.end(),std::mem_fun(&SwRootFrm::UpdateFtnNums));
+ } //swmod 080304pTmpRoot->UpdateFtnNums(); //swmod 080219
+ SetModified();
+ }
+ else
+ delete pUndo;
+ return bChg;
+}
+
+
+
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/doc/docglbl.cxx b/sw/source/core/doc/docglbl.cxx
new file mode 100644
index 000000000000..b72e5ded4689
--- /dev/null
+++ b/sw/source/core/doc/docglbl.cxx
@@ -0,0 +1,827 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+
+#include <hintids.hxx>
+#include <unotools/tempfile.hxx>
+#include <svl/urihelper.hxx>
+#include <svl/stritem.hxx>
+#include <svl/eitem.hxx>
+#include <sfx2/app.hxx>
+#include <sfx2/docfile.hxx>
+#include <sfx2/docfilt.hxx>
+#include <sfx2/fcontnr.hxx>
+#include <sfx2/bindings.hxx>
+#include <sfx2/request.hxx>
+#include <fmtinfmt.hxx>
+#include <fmtanchr.hxx>
+#include <doc.hxx>
+#include <IDocumentUndoRedo.hxx>
+#include <docary.hxx>
+#include <pam.hxx>
+#include <ndtxt.hxx>
+#include <docsh.hxx>
+#include <globdoc.hxx>
+#include <shellio.hxx>
+#include <swundo.hxx> // fuer die UndoIds
+#include <section.hxx>
+#include <doctxm.hxx>
+#include <poolfmt.hxx>
+#include <switerator.hxx>
+#include <com/sun/star/uno/Reference.h>
+#include <com/sun/star/document/XDocumentPropertiesSupplier.hpp>
+#include <com/sun/star/document/XDocumentProperties.hpp>
+
+using namespace ::com::sun::star;
+
+enum SwSplitDocType
+{
+ SPLITDOC_TO_GLOBALDOC,
+ SPLITDOC_TO_HTML
+};
+
+sal_Bool SwDoc::GenerateGlobalDoc( const String& rPath,
+ const SwTxtFmtColl* pSplitColl )
+{
+ return SplitDoc( SPLITDOC_TO_GLOBALDOC, rPath, pSplitColl );
+}
+
+//#outline level,add by zhaojianwei
+sal_Bool SwDoc::GenerateGlobalDoc( const String& rPath, int nOutlineLevel )
+{
+ return SplitDoc( SPLITDOC_TO_GLOBALDOC, rPath, nOutlineLevel );
+}
+sal_Bool SwDoc::GenerateHTMLDoc( const String& rPath, int nOutlineLevel )
+{
+ return SplitDoc( SPLITDOC_TO_HTML, rPath, nOutlineLevel );
+}
+//<-end,zhaojianwei
+
+sal_Bool SwDoc::GenerateHTMLDoc( const String& rPath,
+ const SwTxtFmtColl* pSplitColl )
+{
+ return SplitDoc( SPLITDOC_TO_HTML, rPath, pSplitColl );
+}
+
+sal_Bool SwDoc::SplitDoc( sal_uInt16 eDocType, const String& rPath,
+ const SwTxtFmtColl* pSplitColl )
+{
+ // ueber alle Node der Vorlage Iterieren und dafuer einzelne
+ // Dokumente erzeugen und in diesem gegen
+ // - gelinkte Bereiche (GlobalDoc)
+ // - Links (HTML)
+ // austauschen.
+ // Am Ende wird dieses Doc als GlobalDoc/HTML-Doc gespreichert.
+ if( !pDocShell || !pDocShell->GetMedium() ||
+ ( SPLITDOC_TO_GLOBALDOC == eDocType && get(IDocumentSettingAccess::GLOBAL_DOCUMENT) ) )
+ return sal_False;
+
+ sal_uInt16 nOutl = 0;
+ SwOutlineNodes* pOutlNds = (SwOutlineNodes*)&GetNodes().GetOutLineNds();
+ SwNodePtr pSttNd;
+
+ if( pSplitColl )
+ {
+ // wenn keine OutlineNumerierung ist, dann benutze eigenes Array
+ // und sammel die Nodes zusammen.
+ if( pSplitColl->GetAttrOutlineLevel() == 0 )//<-end,zhaojianwei, 0814
+ {
+ pOutlNds = new SwOutlineNodes( 8, 8 );
+ SwIterator<SwTxtNode,SwFmtColl> aIter( *pSplitColl );
+ for( SwTxtNode* pTNd = aIter.First(); pTNd; pTNd = aIter.Next() )
+ if( pTNd->GetNodes().IsDocNodes() )
+ pOutlNds->Insert( pTNd );
+
+ if( !pOutlNds->Count() )
+ {
+ delete pOutlNds;
+ return sal_False;
+ }
+ }
+ }
+ else
+ {
+ // dann suche die Gliederungs - Vorlage, der 1. Ebene
+ const SwTxtFmtColls& rFmtColls =*GetTxtFmtColls();
+ for( sal_uInt16 n = rFmtColls.Count(); n; )
+ if ( rFmtColls[ --n ]->GetAttrOutlineLevel() == 1 )//<-end,zhaojianwei
+ {
+ pSplitColl = rFmtColls[ n ];
+ break;
+ }
+
+ if( !pSplitColl )
+ return sal_False;
+ }
+
+ const SfxFilter* pFilter;
+ switch( eDocType )
+ {
+ case SPLITDOC_TO_HTML:
+ pFilter = SwIoSystem::GetFilterOfFormat( String::CreateFromAscii(
+ RTL_CONSTASCII_STRINGPARAM( "HTML" )));
+ break;
+
+ default:
+ pFilter = SwIoSystem::GetFilterOfFormat(
+ String::CreateFromAscii( FILTER_XML ));
+ eDocType = SPLITDOC_TO_GLOBALDOC;
+ break;
+ }
+
+ if( !pFilter )
+ return sal_False;
+
+ // Undo/Redline aufjedenfall abschalten
+ GetIDocumentUndoRedo().DoUndo(false);
+ SetRedlineMode_intern( (RedlineMode_t)(GetRedlineMode() & ~nsRedlineMode_t::REDLINE_ON));
+
+ String sExt( pFilter->GetSuffixes().GetToken(0, ',') );
+ if( !sExt.Len() )
+ sExt.AssignAscii( "sxw" );
+ if( '.' != sExt.GetChar( 0 ) )
+ sExt.Insert( '.', 0 );
+
+ INetURLObject aEntry(rPath);
+ String sLeading(aEntry.GetBase());
+ aEntry.removeSegment();
+ String sPath = aEntry.GetMainURL( INetURLObject::NO_DECODE );
+ utl::TempFile aTemp(sLeading,&sExt,&sPath );
+ aTemp.EnableKillingFile();
+
+ DateTime aTmplDate;
+ {
+ Time a2Min( 0 ); a2Min.SetMin( 2 );
+ aTmplDate += a2Min;
+ }
+
+
+ // alle Ungueltigen ueberspringen
+ while( nOutl < pOutlNds->Count() &&
+ pOutlNds->GetObject( nOutl )->GetIndex() < GetNodes().GetEndOfExtras().GetIndex() )
+ ++nOutl;
+
+ do {
+ pSttNd = 0;
+
+ SwNodePtr pNd;
+ for( ; nOutl < pOutlNds->Count(); ++nOutl )
+ if( ( pNd = pOutlNds->GetObject( nOutl ))->GetTxtNode()->
+ GetTxtColl() == pSplitColl &&
+ !pNd->FindTableNode() )
+ {
+ pSttNd = pNd;
+ break;
+ }
+
+ if( pSttNd )
+ {
+ SwNodePtr pEndNd = 0;
+ for( ++nOutl; nOutl < pOutlNds->Count(); ++nOutl )
+ {
+ pNd = pOutlNds->GetObject( nOutl );
+ SwTxtFmtColl* pTColl = pNd->GetTxtNode()->GetTxtColl();
+
+ if( ( pTColl == pSplitColl ||
+ ( pSplitColl->GetAttrOutlineLevel() > 0 &&
+ pTColl->GetAttrOutlineLevel() > 0 &&
+ pTColl->GetAttrOutlineLevel() <
+ pSplitColl->GetAttrOutlineLevel() )) &&
+ !pNd->FindTableNode() ) //<-end,zhaojianwei
+ {
+ pEndNd = pNd;
+
+ break;
+ }
+ }
+ SwNodeIndex aEndIdx( pEndNd ? *pEndNd
+ : GetNodes().GetEndOfContent() );
+
+ // die Nodes komplett rausschreiben
+ String sFileName;
+ if( pSttNd->GetIndex() + 1 < aEndIdx.GetIndex() )
+ {
+ SfxObjectShellLock xDocSh( new SwDocShell( SFX_CREATE_MODE_INTERNAL ));
+ if( xDocSh->DoInitNew( 0 ) )
+ {
+ SwDoc* pDoc = ((SwDocShell*)(&xDocSh))->GetDoc();
+
+ uno::Reference<document::XDocumentPropertiesSupplier> xDPS(
+ ((SwDocShell*)(&xDocSh))->GetModel(),
+ uno::UNO_QUERY_THROW);
+ uno::Reference<document::XDocumentProperties> xDocProps(
+ xDPS->getDocumentProperties());
+ DBG_ASSERT(xDocProps.is(), "Doc has no DocumentProperties");
+ // the GlobalDoc is the template
+ xDocProps->setTemplateName(aEmptyStr);
+ ::util::DateTime uDT(aTmplDate.Get100Sec(),
+ aTmplDate.GetSec(), aTmplDate.GetMin(),
+ aTmplDate.GetHour(), aTmplDate.GetDay(),
+ aTmplDate.GetMonth(), aTmplDate.GetYear());
+ xDocProps->setTemplateDate(uDT);
+ xDocProps->setTemplateURL(rPath);
+ //JP 14.06.99: Set the text of the "split para" as title
+ // from the new doc. Is the current doc has
+ // a title, insert it at begin.
+ String sTitle( xDocProps->getTitle() );
+ if( sTitle.Len() )
+ sTitle.AppendAscii( RTL_CONSTASCII_STRINGPARAM( ": " ));
+ sTitle += ((SwTxtNode*)pSttNd)->GetExpandTxt();
+ xDocProps->setTitle( sTitle );
+
+ // Vorlagen ersetzen
+ pDoc->ReplaceStyles( *this );
+
+ // KapitelNumerierung uebernehmen
+ if( pOutlineRule )
+ pDoc->SetOutlineNumRule( *pOutlineRule );
+
+ SwNodeRange aRg( *pSttNd, 0, aEndIdx.GetNode() );
+ SwNodeIndex aTmpIdx( pDoc->GetNodes().GetEndOfContent() );
+ GetNodes()._Copy( aRg, aTmpIdx, sal_False );
+
+ // den initialen TextNode loeschen
+ SwNodeIndex aIdx( pDoc->GetNodes().GetEndOfExtras(), 2 );
+ if( aIdx.GetIndex() + 1 !=
+ pDoc->GetNodes().GetEndOfContent().GetIndex() )
+ pDoc->GetNodes().Delete( aIdx, 1 );
+
+ // alle Flys in dem Bereich
+ CopyFlyInFlyImpl( aRg, 0, aIdx );
+
+
+ // und noch alle Bookmarks
+ // ?????
+
+ utl::TempFile aTempFile2(sLeading,&sExt,&sPath );
+ sFileName = aTempFile2.GetURL();
+ SfxMedium* pTmpMed = new SfxMedium( sFileName,
+ STREAM_STD_READWRITE, sal_True );
+ pTmpMed->SetFilter( pFilter );
+
+ // fuer den HTML-Filter mussen wir aber ein Layout
+ // haben, damit Textrahmen/Controls/OLE-Objecte korrekt
+ // als Grafik exportiert werden koennen.
+ if( SPLITDOC_TO_HTML == eDocType &&
+ pDoc->GetSpzFrmFmts()->Count() )
+ {
+ /* SfxViewFrame* pFrame = */
+ SfxViewFrame::LoadHiddenDocument( *xDocSh, 0 );
+ }
+ xDocSh->DoSaveAs( *pTmpMed );
+ xDocSh->DoSaveCompleted( pTmpMed );
+
+ // beim Fehler wird keine FileLinkSection eingefuegt
+ if( xDocSh->GetError() )
+ sFileName.Erase();
+ }
+ xDocSh->DoClose();
+ }
+
+ // dann koennen ja die Bereiche eingefuegt werden
+ if( sFileName.Len() )
+ {
+ switch( eDocType )
+ {
+ case SPLITDOC_TO_HTML:
+ {
+ // loesche alle Nodes im Bereich und setze im "Start-
+ // Node" den Link auf das gespeicherte Doc
+ sal_uLong nNodeDiff = aEndIdx.GetIndex() -
+ pSttNd->GetIndex() - 1;
+ if( nNodeDiff )
+ {
+ SwPaM aTmp( *pSttNd, aEndIdx.GetNode(), 1, -1 );
+ aTmp.GetPoint()->nContent.Assign( 0, 0 );
+ aTmp.GetMark()->nContent.Assign( 0, 0 );
+ SwNodeIndex aSIdx( aTmp.GetMark()->nNode );
+ SwNodeIndex aEIdx( aTmp.GetPoint()->nNode );
+
+ // versuche hinters Ende zu verschieben
+ if( !aTmp.Move( fnMoveForward, fnGoNode ) )
+ {
+ // na gut, dann an den Anfang
+ aTmp.Exchange();
+ if( !aTmp.Move( fnMoveBackward, fnGoNode ))
+ {
+ OSL_FAIL( "kein Node mehr vorhanden" );
+ }
+ }
+ // Bookmarks usw. verschieben
+ CorrAbs( aSIdx, aEIdx, *aTmp.GetPoint(), sal_True);
+
+ // stehen noch FlyFrames rum, loesche auch diese
+ for( sal_uInt16 n = 0; n < GetSpzFrmFmts()->Count(); ++n )
+ {
+ SwFrmFmt* pFly = (*GetSpzFrmFmts())[n];
+ const SwFmtAnchor* pAnchor = &pFly->GetAnchor();
+ SwPosition const*const pAPos =
+ pAnchor->GetCntntAnchor();
+ if (pAPos &&
+ ((FLY_AT_PARA == pAnchor->GetAnchorId()) ||
+ (FLY_AT_CHAR == pAnchor->GetAnchorId())) &&
+ aSIdx <= pAPos->nNode &&
+ pAPos->nNode < aEIdx )
+ {
+ DelLayoutFmt( pFly );
+ --n;
+ }
+ }
+
+ GetNodes().Delete( aSIdx, nNodeDiff );
+ }
+
+ // dann setze im StartNode noch den Link:
+ SwFmtINetFmt aINet( sFileName , aEmptyStr );
+ SwTxtNode* pTNd = (SwTxtNode*)pSttNd;
+ pTNd->InsertItem( aINet, 0, pTNd->GetTxt().Len() );
+
+ // wenn der nicht mehr gefunden wird, kann das nur
+ // ein Bug sein!
+ if( !pOutlNds->Seek_Entry( pSttNd, &nOutl ))
+ pSttNd = 0;
+ ++nOutl;
+ }
+ break;
+
+ default:
+ {
+ String sNm( INetURLObject( sFileName ).GetName() );
+ SwSectionData aSectData( FILE_LINK_SECTION,
+ GetUniqueSectionName( &sNm ));
+ SwSectionFmt* pFmt = MakeSectionFmt( 0 );
+ aSectData.SetLinkFileName(sFileName);
+ aSectData.SetProtectFlag(true);
+
+ aEndIdx--; // im InsertSection ist Ende inclusive
+ while( aEndIdx.GetNode().IsStartNode() )
+ aEndIdx--;
+
+ // JP 06.07.99 - Bug 67361 - is any Section ends or
+ // starts in the new sectionrange, they must end or
+ // start before or behind the range!
+ SwSectionNode* pSectNd = pSttNd->FindSectionNode();
+ while( pSectNd && pSectNd->EndOfSectionIndex()
+ <= aEndIdx.GetIndex() )
+ {
+ const SwNode* pSectEnd = pSectNd->EndOfSectionNode();
+ if( pSectNd->GetIndex() + 1 ==
+ pSttNd->GetIndex() )
+ {
+ sal_Bool bMvIdx = aEndIdx == *pSectEnd;
+ DelSectionFmt( pSectNd->GetSection().GetFmt() );
+ if( bMvIdx )
+ aEndIdx--;
+ }
+ else
+ {
+ SwNodeRange aRg( *pSttNd, *pSectEnd );
+ SwNodeIndex aIdx( *pSectEnd, 1 );
+ GetNodes()._MoveNodes( aRg, GetNodes(), aIdx );
+ }
+ pSectNd = pSttNd->FindSectionNode();
+ }
+
+ pSectNd = aEndIdx.GetNode().FindSectionNode();
+ while( pSectNd && pSectNd->GetIndex() >
+ pSttNd->GetIndex() )
+ {
+ // #i15712# don't attempt to split sections if
+ // they are fully enclosed in [pSectNd,aEndIdx].
+ if( aEndIdx < pSectNd->EndOfSectionIndex() )
+ {
+ SwNodeRange aRg( *pSectNd, 1, aEndIdx, 1 );
+ SwNodeIndex aIdx( *pSectNd );
+ GetNodes()._MoveNodes( aRg, GetNodes(), aIdx );
+ }
+
+ pSectNd = pSttNd->FindSectionNode();
+ }
+
+ // -> #i26762#
+ // Ensure order of start and end of section is sane.
+ SwNodeIndex aStartIdx(*pSttNd);
+
+ if (aEndIdx >= aStartIdx)
+ {
+ pSectNd = GetNodes().InsertTextSection(aStartIdx,
+ *pFmt, aSectData, 0, &aEndIdx, false);
+ }
+ else
+ {
+ pSectNd = GetNodes().InsertTextSection(aEndIdx,
+ *pFmt, aSectData, 0, &aStartIdx, false);
+ }
+ // <- #i26762#
+
+ pSectNd->GetSection().CreateLink( CREATE_CONNECT );
+ }
+ break;
+ }
+ }
+ }
+ } while( pSttNd );
+
+ if( pOutlNds != &GetNodes().GetOutLineNds() )
+ delete pOutlNds;
+
+ switch( eDocType )
+ {
+ case SPLITDOC_TO_HTML:
+ if( get(IDocumentSettingAccess::GLOBAL_DOCUMENT) )
+ {
+ // dann alles verbliebenen Bereiche aufheben
+ while( GetSections().Count() )
+ DelSectionFmt( GetSections()[ 0 ] );
+
+ SfxFilterContainer* pFCntnr = pDocShell->GetFactory().GetFilterContainer();
+ pFilter = pFCntnr->GetFilter4EA( pFilter->GetTypeName(), SFX_FILTER_EXPORT );
+ }
+ break;
+
+ default:
+ // dann das Globaldoc speichern
+ set(IDocumentSettingAccess::GLOBAL_DOCUMENT, true);
+ set(IDocumentSettingAccess::GLOBAL_DOCUMENT_SAVE_LINKS, false);
+ }
+
+ // Medium istn't locked after reopen the document. Bug 91462
+ SfxRequest aReq( SID_SAVEASDOC, SFX_CALLMODE_SYNCHRON, GetAttrPool() );
+ aReq.AppendItem( SfxStringItem( SID_FILE_NAME, rPath ) );
+ aReq.AppendItem( SfxBoolItem( SID_SAVETO, sal_True ) );
+ if(pFilter)
+ aReq.AppendItem( SfxStringItem( SID_FILTER_NAME, pFilter->GetName() ) );
+ const SfxBoolItem *pRet = (const SfxBoolItem*)pDocShell->ExecuteSlot( aReq );
+
+ return pRet && pRet->GetValue();
+}
+
+//#outline level,add by zhaojianwei
+sal_Bool SwDoc::SplitDoc( sal_uInt16 eDocType, const String& rPath, int nOutlineLevel )
+{
+ if( !pDocShell || !pDocShell->GetMedium() ||
+ ( SPLITDOC_TO_GLOBALDOC == eDocType && get(IDocumentSettingAccess::GLOBAL_DOCUMENT) ) )
+ return sal_False;
+
+ sal_uInt16 nOutl = 0;
+ SwOutlineNodes* pOutlNds = (SwOutlineNodes*)&GetNodes().GetOutLineNds();
+ SwNodePtr pSttNd;
+
+ const SfxFilter* pFilter;
+ switch( eDocType )
+ {
+ case SPLITDOC_TO_HTML:
+ pFilter = SwIoSystem::GetFilterOfFormat( String::CreateFromAscii(
+ RTL_CONSTASCII_STRINGPARAM( "HTML" )));
+ break;
+
+ default:
+ pFilter = SwIoSystem::GetFilterOfFormat(
+ String::CreateFromAscii( FILTER_XML ));
+ eDocType = SPLITDOC_TO_GLOBALDOC;
+ break;
+ }
+
+ if( !pFilter )
+ return sal_False;
+
+ // Undo/Redline aufjedenfall abschalten
+ GetIDocumentUndoRedo().DoUndo(false);
+ SetRedlineMode_intern( (RedlineMode_t)(GetRedlineMode() & ~nsRedlineMode_t::REDLINE_ON));
+
+ String sExt( pFilter->GetSuffixes().GetToken(0, ',') );
+ if( !sExt.Len() )
+ sExt.AssignAscii( "sxw" );
+ if( '.' != sExt.GetChar( 0 ) )
+ sExt.Insert( '.', 0 );
+
+ INetURLObject aEntry(rPath);
+ String sLeading(aEntry.GetBase());
+ aEntry.removeSegment();
+ String sPath = aEntry.GetMainURL( INetURLObject::NO_DECODE );
+ utl::TempFile aTemp(sLeading,&sExt,&sPath );
+ aTemp.EnableKillingFile();
+
+ DateTime aTmplDate;
+ {
+ Time a2Min( 0 ); a2Min.SetMin( 2 );
+ aTmplDate += a2Min;
+ }
+
+
+ // alle Ungueltigen ueberspringen
+ while( nOutl < pOutlNds->Count() &&
+ pOutlNds->GetObject( nOutl )->GetIndex() < GetNodes().GetEndOfExtras().GetIndex() )
+ ++nOutl;
+
+ do {
+ pSttNd = 0;
+
+ SwNodePtr pNd;
+ for( ; nOutl < pOutlNds->Count(); ++nOutl )
+ if( ( pNd = pOutlNds->GetObject( nOutl ))->GetTxtNode()->GetAttrOutlineLevel() == nOutlineLevel &&
+ !pNd->FindTableNode() )
+ {
+ pSttNd = pNd;
+ break;
+ }
+
+ if( pSttNd )
+ {
+ SwNodePtr pEndNd = 0;
+ for( ++nOutl; nOutl < pOutlNds->Count(); ++nOutl )
+ {
+ pNd = pOutlNds->GetObject( nOutl );
+
+ const int nLevel = pNd->GetTxtNode()->GetAttrOutlineLevel();
+
+ if( ( 0 < nLevel && nLevel <= nOutlineLevel ) &&
+ !pNd->FindTableNode() )
+ {
+ pEndNd = pNd;
+
+ break;
+ }
+ }
+ SwNodeIndex aEndIdx( pEndNd ? *pEndNd
+ : GetNodes().GetEndOfContent() );
+
+ String sFileName;
+ if( pSttNd->GetIndex() + 1 < aEndIdx.GetIndex() )
+ {
+ SfxObjectShellLock xDocSh( new SwDocShell( SFX_CREATE_MODE_INTERNAL ));
+ if( xDocSh->DoInitNew( 0 ) )
+ {
+ SwDoc* pDoc = ((SwDocShell*)(&xDocSh))->GetDoc();
+
+ uno::Reference<document::XDocumentPropertiesSupplier> xDPS(
+ ((SwDocShell*)(&xDocSh))->GetModel(),
+ uno::UNO_QUERY_THROW);
+ uno::Reference<document::XDocumentProperties> xDocProps(
+ xDPS->getDocumentProperties());
+ DBG_ASSERT(xDocProps.is(), "Doc has no DocumentProperties");
+ // the GlobalDoc is the template
+ xDocProps->setTemplateName(aEmptyStr);
+ ::util::DateTime uDT(aTmplDate.Get100Sec(),
+ aTmplDate.GetSec(), aTmplDate.GetMin(),
+ aTmplDate.GetHour(), aTmplDate.GetDay(),
+ aTmplDate.GetMonth(), aTmplDate.GetYear());
+ xDocProps->setTemplateDate(uDT);
+ xDocProps->setTemplateURL(rPath);
+ //JP 14.06.99: Set the text of the "split para" as title
+ // from the new doc. Is the current doc has
+ // a title, insert it at begin.
+ String sTitle( xDocProps->getTitle() );
+ if( sTitle.Len() )
+ sTitle.AppendAscii( RTL_CONSTASCII_STRINGPARAM( ": " ));
+ sTitle += ((SwTxtNode*)pSttNd)->GetExpandTxt();
+ xDocProps->setTitle( sTitle );
+
+ // Vorlagen ersetzen
+ pDoc->ReplaceStyles( *this );
+
+ // KapitelNumerierung uebernehmen
+ if( pOutlineRule )
+ pDoc->SetOutlineNumRule( *pOutlineRule );
+
+ SwNodeRange aRg( *pSttNd, 0, aEndIdx.GetNode() );
+ SwNodeIndex aTmpIdx( pDoc->GetNodes().GetEndOfContent() );
+ GetNodes()._Copy( aRg, aTmpIdx, sal_False );
+
+ // den initialen TextNode loeschen
+ SwNodeIndex aIdx( pDoc->GetNodes().GetEndOfExtras(), 2 );
+ if( aIdx.GetIndex() + 1 !=
+ pDoc->GetNodes().GetEndOfContent().GetIndex() )
+ pDoc->GetNodes().Delete( aIdx, 1 );
+
+ // alle Flys in dem Bereich
+ CopyFlyInFlyImpl( aRg, 0, aIdx );
+
+
+ // und noch alle Bookmarks
+ // ?????
+
+ utl::TempFile aTempFile2(sLeading,&sExt,&sPath );
+ sFileName = aTempFile2.GetURL();
+ SfxMedium* pTmpMed = new SfxMedium( sFileName,
+ STREAM_STD_READWRITE, sal_True );
+ pTmpMed->SetFilter( pFilter );
+
+ // fuer den HTML-Filter mussen wir aber ein Layout
+ // haben, damit Textrahmen/Controls/OLE-Objecte korrekt
+ // als Grafik exportiert werden koennen.
+ if( SPLITDOC_TO_HTML == eDocType &&
+ pDoc->GetSpzFrmFmts()->Count() )
+ {
+ SfxViewFrame::LoadHiddenDocument( *xDocSh, 0 );
+ }
+ xDocSh->DoSaveAs( *pTmpMed );
+ xDocSh->DoSaveCompleted( pTmpMed );
+
+ // beim Fehler wird keine FileLinkSection eingefuegt
+ if( xDocSh->GetError() )
+ sFileName.Erase();
+ }
+ xDocSh->DoClose();
+ }
+
+ // dann koennen ja die Bereiche eingefuegt werden
+ if( sFileName.Len() )
+ {
+ switch( eDocType )
+ {
+ case SPLITDOC_TO_HTML:
+ {
+ // loesche alle Nodes im Bereich und setze im "Start-
+ // Node" den Link auf das gespeicherte Doc
+ sal_uLong nNodeDiff = aEndIdx.GetIndex() -
+ pSttNd->GetIndex() - 1;
+ if( nNodeDiff )
+ {
+ SwPaM aTmp( *pSttNd, aEndIdx.GetNode(), 1, -1 );
+ aTmp.GetPoint()->nContent.Assign( 0, 0 );
+ aTmp.GetMark()->nContent.Assign( 0, 0 );
+ SwNodeIndex aSIdx( aTmp.GetMark()->nNode );
+ SwNodeIndex aEIdx( aTmp.GetPoint()->nNode );
+
+ // versuche hinters Ende zu verschieben
+ if( !aTmp.Move( fnMoveForward, fnGoNode ) )
+ {
+ // na gut, dann an den Anfang
+ aTmp.Exchange();
+ if( !aTmp.Move( fnMoveBackward, fnGoNode ))
+ {
+ OSL_FAIL( "kein Node mehr vorhanden" );
+ }
+ }
+ // Bookmarks usw. verschieben
+ CorrAbs( aSIdx, aEIdx, *aTmp.GetPoint(), sal_True);
+
+ // stehen noch FlyFrames rum, loesche auch diese
+ for( sal_uInt16 n = 0; n < GetSpzFrmFmts()->Count(); ++n )
+ {
+ SwFrmFmt* pFly = (*GetSpzFrmFmts())[n];
+ const SwFmtAnchor* pAnchor = &pFly->GetAnchor();
+ SwPosition const*const pAPos =
+ pAnchor->GetCntntAnchor();
+ if (pAPos &&
+ ((FLY_AT_PARA == pAnchor->GetAnchorId()) ||
+ (FLY_AT_CHAR == pAnchor->GetAnchorId())) &&
+ aSIdx <= pAPos->nNode &&
+ pAPos->nNode < aEIdx )
+ {
+ DelLayoutFmt( pFly );
+ --n;
+ }
+ }
+
+ GetNodes().Delete( aSIdx, nNodeDiff );
+ }
+
+ // dann setze im StartNode noch den Link:
+ SwFmtINetFmt aINet( sFileName , aEmptyStr );
+ SwTxtNode* pTNd = (SwTxtNode*)pSttNd;
+ pTNd->InsertItem( aINet, 0, pTNd->GetTxt().Len() );
+
+ // wenn der nicht mehr gefunden wird, kann das nur
+ // ein Bug sein!
+ if( !pOutlNds->Seek_Entry( pSttNd, &nOutl ))
+ pSttNd = 0;
+ ++nOutl;
+ }
+ break;
+
+ default:
+ {
+ String sNm( INetURLObject( sFileName ).GetName() );
+ SwSectionData aSectData( FILE_LINK_SECTION,
+ GetUniqueSectionName( &sNm ));
+ SwSectionFmt* pFmt = MakeSectionFmt( 0 );
+ aSectData.SetLinkFileName(sFileName);
+ aSectData.SetProtectFlag(true);
+
+ aEndIdx--; // im InsertSection ist Ende inclusive
+ while( aEndIdx.GetNode().IsStartNode() )
+ aEndIdx--;
+
+ // JP 06.07.99 - Bug 67361 - is any Section ends or
+ // starts in the new sectionrange, they must end or
+ // start before or behind the range!
+ SwSectionNode* pSectNd = pSttNd->FindSectionNode();
+ while( pSectNd && pSectNd->EndOfSectionIndex()
+ <= aEndIdx.GetIndex() )
+ {
+ const SwNode* pSectEnd = pSectNd->EndOfSectionNode();
+ if( pSectNd->GetIndex() + 1 ==
+ pSttNd->GetIndex() )
+ {
+ sal_Bool bMvIdx = aEndIdx == *pSectEnd;
+ DelSectionFmt( pSectNd->GetSection().GetFmt() );
+ if( bMvIdx )
+ aEndIdx--;
+ }
+ else
+ {
+ SwNodeRange aRg( *pSttNd, *pSectEnd );
+ SwNodeIndex aIdx( *pSectEnd, 1 );
+ GetNodes()._MoveNodes( aRg, GetNodes(), aIdx );
+ }
+ pSectNd = pSttNd->FindSectionNode();
+ }
+
+ pSectNd = aEndIdx.GetNode().FindSectionNode();
+ while( pSectNd && pSectNd->GetIndex() >
+ pSttNd->GetIndex() )
+ {
+ if( aEndIdx < pSectNd->EndOfSectionIndex() )
+ {
+ SwNodeRange aRg( *pSectNd, 1, aEndIdx, 1 );
+ SwNodeIndex aIdx( *pSectNd );
+ GetNodes()._MoveNodes( aRg, GetNodes(), aIdx );
+ }
+
+ pSectNd = pSttNd->FindSectionNode();
+ }
+
+ SwNodeIndex aStartIdx(*pSttNd);
+
+ if (aEndIdx >= aStartIdx)
+ {
+ pSectNd = GetNodes().InsertTextSection(aStartIdx,
+ *pFmt, aSectData, 0, &aEndIdx, false);
+ }
+ else
+ {
+ pSectNd = GetNodes().InsertTextSection(aEndIdx,
+ *pFmt, aSectData, 0, &aStartIdx, false);
+ }
+
+ pSectNd->GetSection().CreateLink( CREATE_CONNECT );
+ }
+ break;
+ }
+ }
+ }
+ } while( pSttNd );
+
+ if( pOutlNds != &GetNodes().GetOutLineNds() )
+ delete pOutlNds;
+
+ switch( eDocType )
+ {
+ case SPLITDOC_TO_HTML:
+ if( get(IDocumentSettingAccess::GLOBAL_DOCUMENT) )
+ {
+ while( GetSections().Count() )
+ DelSectionFmt( GetSections()[ 0 ] );
+
+ SfxFilterContainer* pFCntnr = pDocShell->GetFactory().GetFilterContainer();
+ pFilter = pFCntnr->GetFilter4EA( pFilter->GetTypeName(), SFX_FILTER_EXPORT );
+ }
+ break;
+
+// case SPLITDOC_TO_GLOBALDOC:
+ default:
+ set(IDocumentSettingAccess::GLOBAL_DOCUMENT, true);
+ set(IDocumentSettingAccess::GLOBAL_DOCUMENT_SAVE_LINKS, false);
+ }
+
+ SfxRequest aReq( SID_SAVEASDOC, SFX_CALLMODE_SYNCHRON, GetAttrPool() );
+ aReq.AppendItem( SfxStringItem( SID_FILE_NAME, rPath ) );
+ aReq.AppendItem( SfxBoolItem( SID_SAVETO, sal_True ) );
+ if(pFilter)
+ aReq.AppendItem( SfxStringItem( SID_FILTER_NAME, pFilter->GetName() ) );
+ const SfxBoolItem *pRet = (const SfxBoolItem*)pDocShell->ExecuteSlot( aReq );
+
+ return pRet && pRet->GetValue();
+}//<-end,zhaojianwei
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/doc/docglos.cxx b/sw/source/core/doc/docglos.cxx
new file mode 100644
index 000000000000..350bde67062c
--- /dev/null
+++ b/sw/source/core/doc/docglos.cxx
@@ -0,0 +1,203 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+#include <com/sun/star/document/XDocumentPropertiesSupplier.hpp>
+#include <com/sun/star/document/XDocumentProperties.hpp>
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/beans/XPropertySetInfo.hpp>
+
+#include <doc.hxx>
+#include <IDocumentUndoRedo.hxx>
+#include <shellio.hxx>
+#include <pam.hxx>
+#include <swundo.hxx>
+#include <ndtxt.hxx>
+#include <acorrect.hxx>
+#include <crsrsh.hxx>
+#include <docsh.hxx>
+
+
+using namespace ::com::sun::star;
+
+
+/// copy document properties via public interface
+static void lcl_copyDocumentProperties(
+ uno::Reference<document::XDocumentProperties> i_xSource,
+ uno::Reference<document::XDocumentProperties> i_xTarget) {
+ DBG_ASSERT(i_xSource.is(), "null reference");
+ DBG_ASSERT(i_xTarget.is(), "null reference");
+
+ i_xTarget->setAuthor(i_xSource->getAuthor());
+ i_xTarget->setGenerator(i_xSource->getGenerator());
+ i_xTarget->setCreationDate(i_xSource->getCreationDate());
+ i_xTarget->setTitle(i_xSource->getTitle());
+ i_xTarget->setSubject(i_xSource->getSubject());
+ i_xTarget->setDescription(i_xSource->getDescription());
+ i_xTarget->setKeywords(i_xSource->getKeywords());
+ i_xTarget->setLanguage(i_xSource->getLanguage());
+ i_xTarget->setModifiedBy(i_xSource->getModifiedBy());
+ i_xTarget->setModificationDate(i_xSource->getModificationDate());
+ i_xTarget->setPrintedBy(i_xSource->getPrintedBy());
+ i_xTarget->setPrintDate(i_xSource->getPrintDate());
+ i_xTarget->setTemplateName(i_xSource->getTemplateName());
+ i_xTarget->setTemplateURL(i_xSource->getTemplateURL());
+ i_xTarget->setTemplateDate(i_xSource->getTemplateDate());
+ i_xTarget->setAutoloadURL(i_xSource->getAutoloadURL());
+ i_xTarget->setAutoloadSecs(i_xSource->getAutoloadSecs());
+ i_xTarget->setDefaultTarget(i_xSource->getDefaultTarget());
+ i_xTarget->setDocumentStatistics(i_xSource->getDocumentStatistics());
+ i_xTarget->setEditingCycles(i_xSource->getEditingCycles());
+ i_xTarget->setEditingDuration(i_xSource->getEditingDuration());
+
+ uno::Reference<beans::XPropertySet> xSourceUDSet(
+ i_xSource->getUserDefinedProperties(), uno::UNO_QUERY_THROW);
+ uno::Reference<beans::XPropertyContainer> xTargetUD(
+ i_xTarget->getUserDefinedProperties());
+ uno::Reference<beans::XPropertySet> xTargetUDSet(xTargetUD,
+ uno::UNO_QUERY_THROW);
+ uno::Sequence<beans::Property> tgtprops
+ = xTargetUDSet->getPropertySetInfo()->getProperties();
+ for (sal_Int32 i = 0; i < tgtprops.getLength(); ++i) {
+ try {
+ xTargetUD->removeProperty(tgtprops [i].Name);
+ } catch (uno::Exception &) {
+ // ignore
+ }
+ }
+ try {
+ uno::Reference<beans::XPropertySetInfo> xSetInfo
+ = xSourceUDSet->getPropertySetInfo();
+ uno::Sequence<beans::Property> srcprops = xSetInfo->getProperties();
+ for (sal_Int32 i = 0; i < srcprops.getLength(); ++i) {
+ ::rtl::OUString name = srcprops[i].Name;
+ xTargetUD->addProperty(name, srcprops[i].Attributes,
+ xSourceUDSet->getPropertyValue(name));
+ }
+ } catch (uno::Exception &) {
+ // ignore
+ }
+}
+
+/* --------------------------------------------------
+ Description: inserts an AutoText block
+ --------------------------------------------------*/
+sal_Bool SwDoc::InsertGlossary( SwTextBlocks& rBlock, const String& rEntry,
+ SwPaM& rPaM, SwCrsrShell* pShell )
+{
+ sal_Bool bRet = sal_False;
+ sal_uInt16 nIdx = rBlock.GetIndex( rEntry );
+ if( (sal_uInt16) -1 != nIdx )
+ {
+ sal_Bool bSav_IsInsGlossary = mbInsOnlyTxtGlssry;
+ mbInsOnlyTxtGlssry = rBlock.IsOnlyTextBlock( nIdx );
+
+ if( rBlock.BeginGetDoc( nIdx ) )
+ {
+ SwDoc* pGDoc = rBlock.GetDoc();
+
+ // alle FixFelder aktualisieren. Dann aber auch mit der
+ // richtigen DocInfo!
+ // FIXME: UGLY: Because we cannot limit the range in which to do
+ // field updates, we must update the fixed fields at the glossary
+ // entry document.
+ // To be able to do this, we copy the document properties of the
+ // target document to the glossary document
+// DBG_ASSERT(GetDocShell(), "no SwDocShell"); // may be clipboard!
+ DBG_ASSERT(pGDoc->GetDocShell(), "no SwDocShell at glossary");
+ if (GetDocShell() && pGDoc->GetDocShell()) {
+ uno::Reference<document::XDocumentPropertiesSupplier> xDPS(
+ GetDocShell()->GetModel(), uno::UNO_QUERY_THROW);
+ uno::Reference<document::XDocumentProperties> xDocProps(
+ xDPS->getDocumentProperties() );
+ uno::Reference<document::XDocumentPropertiesSupplier> xGlosDPS(
+ pGDoc->GetDocShell()->GetModel(), uno::UNO_QUERY_THROW);
+ uno::Reference<document::XDocumentProperties> xGlosDocProps(
+ xGlosDPS->getDocumentProperties() );
+ lcl_copyDocumentProperties(xDocProps, xGlosDocProps);
+ }
+ pGDoc->SetFixFields(false, NULL);
+
+ //StartAllAction();
+ LockExpFlds();
+
+ SwNodeIndex aStt( pGDoc->GetNodes().GetEndOfExtras(), 1 );
+ SwCntntNode* pCntntNd = pGDoc->GetNodes().GoNext( &aStt );
+ const SwTableNode* pTblNd = pCntntNd->FindTableNode();
+ SwPaM aCpyPam( pTblNd ? *(SwNode*)pTblNd : *(SwNode*)pCntntNd );
+ aCpyPam.SetMark();
+
+ // dann bis zum Ende vom Nodes Array
+ aCpyPam.GetPoint()->nNode = pGDoc->GetNodes().GetEndOfContent().GetIndex()-1;
+ pCntntNd = aCpyPam.GetCntntNode();
+ aCpyPam.GetPoint()->nContent.Assign( pCntntNd, pCntntNd->Len() );
+
+ GetIDocumentUndoRedo().StartUndo( UNDO_INSGLOSSARY, NULL );
+ SwPaM *_pStartCrsr = &rPaM, *__pStartCrsr = _pStartCrsr;
+ do {
+
+ SwPosition& rInsPos = *_pStartCrsr->GetPoint();
+ SwStartNode* pBoxSttNd = (SwStartNode*)rInsPos.nNode.GetNode().
+ FindTableBoxStartNode();
+
+ if( pBoxSttNd && 2 == pBoxSttNd->EndOfSectionIndex() -
+ pBoxSttNd->GetIndex() &&
+ aCpyPam.GetPoint()->nNode != aCpyPam.GetMark()->nNode )
+ {
+ // es wird mehr als 1 Node in die akt. Box kopiert.
+ // Dann muessen die BoxAttribute aber entfernt werden.
+ ClearBoxNumAttrs( rInsPos.nNode );
+ }
+
+ SwDontExpandItem aACD;
+ aACD.SaveDontExpandItems( rInsPos );
+
+ pGDoc->CopyRange( aCpyPam, rInsPos, false );
+
+ aACD.RestoreDontExpandItems( rInsPos );
+ if( pShell )
+ pShell->SaveTblBoxCntnt( &rInsPos );
+ } while( (_pStartCrsr=(SwPaM *)_pStartCrsr->GetNext()) !=
+ __pStartCrsr );
+ GetIDocumentUndoRedo().EndUndo( UNDO_INSGLOSSARY, NULL );
+
+ UnlockExpFlds();
+ if( !IsExpFldsLocked() )
+ UpdateExpFlds(NULL, true);
+ bRet = sal_True;
+ }
+ mbInsOnlyTxtGlssry = bSav_IsInsGlossary;
+ }
+ rBlock.EndGetDoc();
+ return bRet;
+}
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/doc/doclay.cxx b/sw/source/core/doc/doclay.cxx
new file mode 100644
index 000000000000..f6f5946cb7a4
--- /dev/null
+++ b/sw/source/core/doc/doclay.cxx
@@ -0,0 +1,2366 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+#include <unotools/linguprops.hxx>
+#include <unotools/lingucfg.hxx>
+#include <com/sun/star/embed/EmbedStates.hpp>
+#include <hintids.hxx>
+#include <com/sun/star/util/XCloseable.hpp>
+#include <sfx2/progress.hxx>
+#include <svx/svdmodel.hxx>
+#include <svx/svdpage.hxx>
+#include <editeng/keepitem.hxx>
+#include <editeng/ulspitem.hxx>
+#include <editeng/lrspitem.hxx>
+#include <editeng/boxitem.hxx>
+#include <editeng/shaditem.hxx>
+#include <editeng/protitem.hxx>
+#include <editeng/opaqitem.hxx>
+#include <editeng/prntitem.hxx>
+#include <svx/fmglob.hxx>
+#include <svx/svdouno.hxx>
+#include <svx/fmpage.hxx>
+#include <editeng/frmdiritem.hxx>
+
+#include <swmodule.hxx>
+#include <modcfg.hxx>
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <rtl/logfile.hxx>
+#include <SwStyleNameMapper.hxx>
+#include <fchrfmt.hxx>
+#include <frmatr.hxx>
+#include <txatbase.hxx>
+#include <fmtfld.hxx>
+#include <fmtornt.hxx>
+#include <fmtcntnt.hxx>
+#include <fmtanchr.hxx>
+#include <fmtfsize.hxx>
+#include <fmtsrnd.hxx>
+#include <fmtflcnt.hxx>
+#include <fmtcnct.hxx>
+#include <frmfmt.hxx>
+#include <txtflcnt.hxx>
+#include <docfld.hxx> // fuer Expression-Felder
+#include <pam.hxx>
+#include <ndtxt.hxx>
+#include <ndnotxt.hxx>
+#include <ndole.hxx>
+#include <doc.hxx>
+#include <IDocumentUndoRedo.hxx>
+#include <rootfrm.hxx>
+#include <pagefrm.hxx>
+#include <cntfrm.hxx>
+#include <flyfrm.hxx>
+#include <fesh.hxx>
+#include <docsh.hxx>
+#include <dflyobj.hxx>
+#include <dcontact.hxx>
+#include <swundo.hxx>
+#include <flypos.hxx>
+#include <UndoInsert.hxx>
+#include <expfld.hxx> // InsertLabel
+#include <poolfmt.hxx> // PoolVorlagen-Id's
+#include <docary.hxx>
+#include <swtable.hxx>
+#include <tblsel.hxx>
+#include <viewopt.hxx>
+#include <fldupde.hxx>
+#include <txtftn.hxx>
+#include <ftnidx.hxx>
+#include <ftninfo.hxx>
+#include <pagedesc.hxx>
+#include <PostItMgr.hxx>
+#include <comcore.hrc> // STR-ResId's
+
+#include <unoframe.hxx>
+
+#include <sortedobjs.hxx>
+
+#include <vector>
+
+using namespace ::com::sun::star;
+using ::rtl::OUString;
+
+#define DEF_FLY_WIDTH 2268 //Defaultbreite fuer FlyFrms (2268 == 4cm)
+
+
+static bool lcl_IsItemSet(const SwCntntNode & rNode, sal_uInt16 which)
+{
+ bool bResult = false;
+
+ if (SFX_ITEM_SET == rNode.GetSwAttrSet().GetItemState(which))
+ bResult = true;
+
+ return bResult;
+}
+
+/*************************************************************************
+|*
+|* SwDoc::MakeLayoutFmt()
+|*
+|* Beschreibung Erzeugt ein neues Format das in seinen Einstellungen
+|* Defaultmaessig zu dem Request passt. Das Format wird in das
+|* entsprechende Formate-Array gestellt.
+|* Wenn bereits ein passendes Format existiert, so wird dies
+|* zurueckgeliefert.
+|*************************************************************************/
+SwFrmFmt *SwDoc::MakeLayoutFmt( RndStdIds eRequest, const SfxItemSet* pSet )
+{
+ SwFrmFmt *pFmt = 0;
+ const sal_Bool bMod = IsModified();
+ sal_Bool bHeader = sal_False;
+
+ switch ( eRequest )
+ {
+ case RND_STD_HEADER:
+ case RND_STD_HEADERL:
+ case RND_STD_HEADERR:
+ {
+ bHeader = sal_True;
+ // kein break, es geht unten weiter
+ }
+ case RND_STD_FOOTER:
+ case RND_STD_FOOTERL:
+ case RND_STD_FOOTERR:
+ {
+ pFmt = new SwFrmFmt( GetAttrPool(),
+ (bHeader ? "Header" : "Footer"),
+ GetDfltFrmFmt() );
+
+ SwNodeIndex aTmpIdx( GetNodes().GetEndOfAutotext() );
+ SwStartNode* pSttNd =
+ GetNodes().MakeTextSection
+ ( aTmpIdx,
+ bHeader ? SwHeaderStartNode : SwFooterStartNode,
+ GetTxtCollFromPool(static_cast<sal_uInt16>( bHeader
+ ? ( eRequest == RND_STD_HEADERL
+ ? RES_POOLCOLL_HEADERL
+ : eRequest == RND_STD_HEADERR
+ ? RES_POOLCOLL_HEADERR
+ : RES_POOLCOLL_HEADER )
+ : ( eRequest == RND_STD_FOOTERL
+ ? RES_POOLCOLL_FOOTERL
+ : eRequest == RND_STD_FOOTERR
+ ? RES_POOLCOLL_FOOTERR
+ : RES_POOLCOLL_FOOTER )
+ ) ) );
+ pFmt->SetFmtAttr( SwFmtCntnt( pSttNd ));
+
+ if( pSet ) // noch ein paar Attribute setzen ?
+ pFmt->SetFmtAttr( *pSet );
+
+ // JP: warum zuruecksetzen ??? Doc. ist doch veraendert ???
+ // bei den Fly auf jedenfall verkehrt !!
+ if ( !bMod )
+ ResetModified();
+ }
+ break;
+
+ case RND_DRAW_OBJECT:
+ {
+ pFmt = MakeDrawFrmFmt( aEmptyStr, GetDfltFrmFmt() );
+ if( pSet ) // noch ein paar Attribute setzen ?
+ pFmt->SetFmtAttr( *pSet );
+
+ if (GetIDocumentUndoRedo().DoesUndo())
+ {
+ GetIDocumentUndoRedo().AppendUndo(
+ new SwUndoInsLayFmt(pFmt, 0, 0));
+ }
+ }
+ break;
+
+#if OSL_DEBUG_LEVEL > 1
+ case FLY_AT_PAGE:
+ case FLY_AT_CHAR:
+ case FLY_AT_FLY:
+ case FLY_AT_PARA:
+ case FLY_AS_CHAR:
+ OSL_FAIL( "use new interface instead: SwDoc::MakeFlySection!" );
+ break;
+#endif
+
+ default:
+ OSL_ENSURE( !this,
+ "Layoutformat mit ungueltigem Request angefordert." );
+
+ }
+ return pFmt;
+}
+
+/*************************************************************************
+|*
+|* SwDoc::DelLayoutFmt()
+|*
+|* Beschreibung Loescht das angegebene Format, der Inhalt wird mit
+|* geloescht.
+|*
+|*************************************************************************/
+void SwDoc::DelLayoutFmt( SwFrmFmt *pFmt )
+{
+ //Verkettung von Rahmen muss ggf. zusammengefuehrt werden.
+ //Bevor die Frames vernichtet werden, damit die Inhalte der Rahmen
+ //ggf. entsprechend gerichtet werden.
+ const SwFmtChain &rChain = pFmt->GetChain();
+ if ( rChain.GetPrev() )
+ {
+ SwFmtChain aChain( rChain.GetPrev()->GetChain() );
+ aChain.SetNext( rChain.GetNext() );
+ SetAttr( aChain, *rChain.GetPrev() );
+ }
+ if ( rChain.GetNext() )
+ {
+ SwFmtChain aChain( rChain.GetNext()->GetChain() );
+ aChain.SetPrev( rChain.GetPrev() );
+ SetAttr( aChain, *rChain.GetNext() );
+ }
+
+ const SwNodeIndex* pCntIdx = pFmt->GetCntnt().GetCntntIdx();
+ if (pCntIdx && !GetIDocumentUndoRedo().DoesUndo())
+ {
+ //Verbindung abbauen, falls es sich um ein OLE-Objekt handelt.
+ SwOLENode* pOLENd = GetNodes()[ pCntIdx->GetIndex()+1 ]->GetOLENode();
+ if( pOLENd && pOLENd->GetOLEObj().IsOleRef() )
+ {
+
+ // TODO/MBA: the old object closed the object, cleared all references to it, but didn't remove it from the container.
+ // I have no idea, why, nobody could explain it - so I do my very best to mimic this behavior
+ //uno::Reference < util::XCloseable > xClose( pOLENd->GetOLEObj().GetOleRef(), uno::UNO_QUERY );
+ //if ( xClose.is() )
+ {
+ try
+ {
+ pOLENd->GetOLEObj().GetOleRef()->changeState( embed::EmbedStates::LOADED );
+ }
+ catch ( uno::Exception& )
+ {
+ }
+ }
+
+ }
+ }
+
+ //Frms vernichten.
+ pFmt->DelFrms();
+
+ // erstmal sind nur Fly's Undofaehig
+ const sal_uInt16 nWh = pFmt->Which();
+ if (GetIDocumentUndoRedo().DoesUndo() &&
+ (RES_FLYFRMFMT == nWh || RES_DRAWFRMFMT == nWh))
+ {
+ GetIDocumentUndoRedo().AppendUndo( new SwUndoDelLayFmt( pFmt ));
+ }
+ else
+ {
+ // #i32089# - delete at-frame anchored objects
+ if ( nWh == RES_FLYFRMFMT )
+ {
+ // determine frame formats of at-frame anchored objects
+ const SwNodeIndex* pCntntIdx = pFmt->GetCntnt().GetCntntIdx();
+ if ( pCntntIdx )
+ {
+ const SwSpzFrmFmts* pTbl = pFmt->GetDoc()->GetSpzFrmFmts();
+ if ( pTbl )
+ {
+ std::vector<SwFrmFmt*> aToDeleteFrmFmts;
+ const sal_uLong nNodeIdxOfFlyFmt( pCntntIdx->GetIndex() );
+
+ for ( sal_uInt16 i = 0; i < pTbl->Count(); ++i )
+ {
+ SwFrmFmt* pTmpFmt = (*pTbl)[i];
+ const SwFmtAnchor &rAnch = pTmpFmt->GetAnchor();
+ if ( rAnch.GetAnchorId() == FLY_AT_FLY &&
+ rAnch.GetCntntAnchor()->nNode.GetIndex() == nNodeIdxOfFlyFmt )
+ {
+ aToDeleteFrmFmts.push_back( pTmpFmt );
+ }
+ }
+
+ // delete found frame formats
+ while ( !aToDeleteFrmFmts.empty() )
+ {
+ SwFrmFmt* pTmpFmt = aToDeleteFrmFmts.back();
+ pFmt->GetDoc()->DelLayoutFmt( pTmpFmt );
+
+ aToDeleteFrmFmts.pop_back();
+ }
+ }
+ }
+ }
+ // <--
+
+ //Inhalt Loeschen.
+ if( pCntIdx )
+ {
+ SwNode *pNode = &pCntIdx->GetNode();
+ ((SwFmtCntnt&)pFmt->GetFmtAttr( RES_CNTNT )).SetNewCntntIdx( 0 );
+ DeleteSection( pNode );
+ }
+
+ // ggfs. bei Zeichengebundenen Flys das Zeichen loeschen
+ const SwFmtAnchor& rAnchor = pFmt->GetAnchor();
+ if ((FLY_AS_CHAR == rAnchor.GetAnchorId()) && rAnchor.GetCntntAnchor())
+ {
+ const SwPosition* pPos = rAnchor.GetCntntAnchor();
+ SwTxtNode *pTxtNd = pPos->nNode.GetNode().GetTxtNode();
+
+ // attribute is still in text node, delete it
+ if ( pTxtNd )
+ {
+ SwTxtFlyCnt* const pAttr = static_cast<SwTxtFlyCnt*>(
+ pTxtNd->GetTxtAttrForCharAt( pPos->nContent.GetIndex(),
+ RES_TXTATR_FLYCNT ));
+ if ( pAttr && (pAttr->GetFlyCnt().GetFrmFmt() == pFmt) )
+ {
+ // dont delete, set pointer to 0
+ const_cast<SwFmtFlyCnt&>(pAttr->GetFlyCnt()).SetFlyFmt();
+ SwIndex aIdx( pPos->nContent );
+ pTxtNd->EraseText( aIdx, 1 );
+ }
+ }
+ }
+
+ DelFrmFmt( pFmt );
+ }
+ SetModified();
+}
+
+/*************************************************************************
+|*
+|* SwDoc::CopyLayoutFmt()
+|*
+|* Beschreibung Kopiert das angegebene Format pSrc in pDest und
+|* returnt pDest. Wenn es noch kein pDest gibt, wird
+|* eins angelegt.
+|* JP: steht das Source Format in einem anderen
+|* Dokument, so kopiere auch dann noch richtig !!
+|* Vom chaos::Anchor-Attribut wird die Position immer
+|* auf 0 gesetzt !!!
+|*
+|*************************************************************************/
+SwFrmFmt *SwDoc::CopyLayoutFmt( const SwFrmFmt& rSource,
+ const SwFmtAnchor& rNewAnchor,
+ bool bSetTxtFlyAtt, bool bMakeFrms )
+{
+ const bool bFly = RES_FLYFRMFMT == rSource.Which();
+ const bool bDraw = RES_DRAWFRMFMT == rSource.Which();
+ OSL_ENSURE( bFly || bDraw, "this method only works for fly or draw" );
+
+ SwDoc* pSrcDoc = (SwDoc*)rSource.GetDoc();
+
+ // May we copy this object?
+ // We may, unless it's 1) it's a control (and therfore a draw)
+ // 2) anchored in a header/footer
+ // 3) anchored (to paragraph?)
+ bool bMayNotCopy = false;
+ if( bDraw )
+ {
+ const SwDrawContact* pDrawContact =
+ static_cast<const SwDrawContact*>( rSource.FindContactObj() );
+
+ bMayNotCopy =
+ ((FLY_AT_PARA == rNewAnchor.GetAnchorId()) ||
+ (FLY_AT_FLY == rNewAnchor.GetAnchorId()) ||
+ (FLY_AT_CHAR == rNewAnchor.GetAnchorId())) &&
+ rNewAnchor.GetCntntAnchor() &&
+ IsInHeaderFooter( rNewAnchor.GetCntntAnchor()->nNode ) &&
+ pDrawContact != NULL &&
+ pDrawContact->GetMaster() != NULL &&
+ CheckControlLayer( pDrawContact->GetMaster() );
+ }
+
+ // just return if we can't copy this
+ if( bMayNotCopy )
+ return NULL;
+
+ SwFrmFmt* pDest = GetDfltFrmFmt();
+ if( rSource.GetRegisteredIn() != pSrcDoc->GetDfltFrmFmt() )
+ pDest = CopyFrmFmt( *(SwFrmFmt*)rSource.GetRegisteredIn() );
+ if( bFly )
+ {
+ // #i11176#
+ // To do a correct cloning concerning the ZOrder for all objects
+ // it is necessary to actually create a draw object for fly frames, too.
+ // These are then added to the DrawingLayer (which needs to exist).
+ // Together with correct sorting of all drawinglayer based objects
+ // before cloning ZOrder transfer works correctly then.
+ SwFlyFrmFmt *pFormat = MakeFlyFrmFmt( rSource.GetName(), pDest );
+ pDest = pFormat;
+
+ SwXFrame::GetOrCreateSdrObject(pFormat);
+ }
+ else
+ pDest = MakeDrawFrmFmt( aEmptyStr, pDest );
+
+ // alle anderen/neue Attribute kopieren.
+ pDest->CopyAttrs( rSource );
+
+ //Chains werden nicht kopiert.
+ pDest->ResetFmtAttr( RES_CHAIN );
+
+ if( bFly )
+ {
+ //Der Inhalt wird dupliziert.
+ const SwNode& rCSttNd = rSource.GetCntnt().GetCntntIdx()->GetNode();
+ SwNodeRange aRg( rCSttNd, 1, *rCSttNd.EndOfSectionNode() );
+
+ SwNodeIndex aIdx( GetNodes().GetEndOfAutotext() );
+ SwStartNode* pSttNd = GetNodes().MakeEmptySection( aIdx, SwFlyStartNode );
+
+ // erst den chaos::Anchor/CntntIndex setzen, innerhalb des Kopierens
+ // auf die Werte zugegriffen werden kann (DrawFmt in Kopf-/Fusszeilen)
+ aIdx = *pSttNd;
+ SwFmtCntnt aAttr( rSource.GetCntnt() );
+ aAttr.SetNewCntntIdx( &aIdx );
+ pDest->SetFmtAttr( aAttr );
+ pDest->SetFmtAttr( rNewAnchor );
+
+ if( !mbCopyIsMove || this != pSrcDoc )
+ {
+ if( mbInReading )
+ pDest->SetName( aEmptyStr );
+ else
+ {
+ // Teste erstmal ob der Name schon vergeben ist.
+ // Wenn ja -> neuen generieren
+ sal_Int8 nNdTyp = aRg.aStart.GetNode().GetNodeType();
+
+ String sOld( pDest->GetName() );
+ pDest->SetName( aEmptyStr );
+ if( FindFlyByName( sOld, nNdTyp ) ) // einen gefunden
+ switch( nNdTyp )
+ {
+ case ND_GRFNODE: sOld = GetUniqueGrfName(); break;
+ case ND_OLENODE: sOld = GetUniqueOLEName(); break;
+ default: sOld = GetUniqueFrameName(); break;
+ }
+
+ pDest->SetName( sOld );
+ }
+ }
+
+ if (GetIDocumentUndoRedo().DoesUndo())
+ {
+ GetIDocumentUndoRedo().AppendUndo(new SwUndoInsLayFmt(pDest,0,0));
+ }
+
+ // sorge dafuer das auch Fly's in Fly's kopiert werden
+ aIdx = *pSttNd->EndOfSectionNode();
+ pSrcDoc->CopyWithFlyInFly( aRg, 0, aIdx, sal_False, sal_True, sal_True );
+ }
+ else
+ {
+ OSL_ENSURE( RES_DRAWFRMFMT == rSource.Which(), "Weder Fly noch Draw." );
+ // #i52780# - Note: moving object to visible layer not needed.
+ SwDrawContact* pSourceContact = (SwDrawContact *)rSource.FindContactObj();
+
+ SwDrawContact* pContact = new SwDrawContact( (SwDrawFrmFmt*)pDest,
+ CloneSdrObj( *pSourceContact->GetMaster(),
+ mbCopyIsMove && this == pSrcDoc ) );
+ // #i49730# - notify draw frame format that position attributes are
+ // already set, if the position attributes are already set at the
+ // source draw frame format.
+ if ( pDest->ISA(SwDrawFrmFmt) &&
+ rSource.ISA(SwDrawFrmFmt) &&
+ static_cast<const SwDrawFrmFmt&>(rSource).IsPosAttrSet() )
+ {
+ static_cast<SwDrawFrmFmt*>(pDest)->PosAttrSet();
+ }
+ // <--
+
+ if( pDest->GetAnchor() == rNewAnchor )
+ {
+ // Do *not* connect to layout, if a <MakeFrms> will not be called.
+ if ( bMakeFrms )
+ {
+ pContact->ConnectToLayout( &rNewAnchor );
+ }
+ }
+ else
+ pDest->SetFmtAttr( rNewAnchor );
+
+ if (GetIDocumentUndoRedo().DoesUndo())
+ {
+ GetIDocumentUndoRedo().AppendUndo(new SwUndoInsLayFmt(pDest,0,0));
+ }
+ }
+
+ if (bSetTxtFlyAtt && (FLY_AS_CHAR == rNewAnchor.GetAnchorId()))
+ {
+ const SwPosition* pPos = rNewAnchor.GetCntntAnchor();
+ SwFmtFlyCnt aFmt( pDest );
+ pPos->nNode.GetNode().GetTxtNode()->InsertItem(
+ aFmt, pPos->nContent.GetIndex(), 0 );
+ }
+
+ if( bMakeFrms )
+ pDest->MakeFrms();
+
+ return pDest;
+}
+
+SdrObject* SwDoc::CloneSdrObj( const SdrObject& rObj, sal_Bool bMoveWithinDoc,
+ sal_Bool bInsInPage )
+{
+ // #i52858# - method name changed
+ SdrPage *pPg = GetOrCreateDrawModel()->GetPage( 0 );
+ if( !pPg )
+ {
+ pPg = GetDrawModel()->AllocPage( sal_False );
+ GetDrawModel()->InsertPage( pPg );
+ }
+
+ SdrObject *pObj = rObj.Clone();
+ if( bMoveWithinDoc && FmFormInventor == pObj->GetObjInventor() )
+ {
+ // bei Controls muss der Name erhalten bleiben
+ uno::Reference< awt::XControlModel > xModel = ((SdrUnoObj*)pObj)->GetUnoControlModel();
+ uno::Any aVal;
+ uno::Reference< beans::XPropertySet > xSet(xModel, uno::UNO_QUERY);
+ OUString sName(RTL_CONSTASCII_USTRINGPARAM("Name"));
+ if( xSet.is() )
+ aVal = xSet->getPropertyValue( sName );
+ if( bInsInPage )
+ pPg->InsertObject( pObj );
+ if( xSet.is() )
+ xSet->setPropertyValue( sName, aVal );
+ }
+ else if( bInsInPage )
+ pPg->InsertObject( pObj );
+
+ // For drawing objects: set layer of cloned object to invisible layer
+ SdrLayerID nLayerIdForClone = rObj.GetLayer();
+ if ( !pObj->ISA(SwFlyDrawObj) &&
+ !pObj->ISA(SwVirtFlyDrawObj) &&
+ !IS_TYPE(SdrObject,pObj) )
+ {
+ if ( IsVisibleLayerId( nLayerIdForClone ) )
+ {
+ nLayerIdForClone = GetInvisibleLayerIdByVisibleOne( nLayerIdForClone );
+ }
+ }
+ pObj->SetLayer( nLayerIdForClone );
+
+
+ return pObj;
+}
+
+SwFlyFrmFmt* SwDoc::_MakeFlySection( const SwPosition& rAnchPos,
+ const SwCntntNode& rNode,
+ RndStdIds eRequestId,
+ const SfxItemSet* pFlySet,
+ SwFrmFmt* pFrmFmt )
+{
+ if( !pFrmFmt )
+ pFrmFmt = GetFrmFmtFromPool( RES_POOLFRM_FRAME );
+
+ String sName;
+ if( !mbInReading )
+ switch( rNode.GetNodeType() )
+ {
+ case ND_GRFNODE: sName = GetUniqueGrfName(); break;
+ case ND_OLENODE: sName = GetUniqueOLEName(); break;
+ default: sName = GetUniqueFrameName(); break;
+ }
+ SwFlyFrmFmt* pFmt = MakeFlyFrmFmt( sName, pFrmFmt );
+
+ //Inhalt erzeugen und mit dem Format verbinden.
+ //CntntNode erzeugen und in die Autotextsection stellen
+ SwNodeRange aRange( GetNodes().GetEndOfAutotext(), -1,
+ GetNodes().GetEndOfAutotext() );
+ GetNodes().SectionDown( &aRange, SwFlyStartNode );
+
+ pFmt->SetFmtAttr( SwFmtCntnt( rNode.StartOfSectionNode() ));
+
+
+ const SwFmtAnchor* pAnchor = 0;
+ if( pFlySet )
+ {
+ pFlySet->GetItemState( RES_ANCHOR, sal_False,
+ (const SfxPoolItem**)&pAnchor );
+ if( SFX_ITEM_SET == pFlySet->GetItemState( RES_CNTNT, sal_False ))
+ {
+ SfxItemSet aTmpSet( *pFlySet );
+ aTmpSet.ClearItem( RES_CNTNT );
+ pFmt->SetFmtAttr( aTmpSet );
+ }
+ else
+ pFmt->SetFmtAttr( *pFlySet );
+ }
+
+ // Anker noch nicht gesetzt ?
+ RndStdIds eAnchorId = pAnchor ? pAnchor->GetAnchorId()
+ : pFmt->GetAnchor().GetAnchorId();
+ // #i107811# Assure that at-page anchored fly frames have a page num or a
+ // content anchor set.
+ if ( !pAnchor ||
+ ( FLY_AT_PAGE != pAnchor->GetAnchorId() &&
+ !pAnchor->GetCntntAnchor() ) ||
+ ( FLY_AT_PAGE == pAnchor->GetAnchorId() &&
+ !pAnchor->GetCntntAnchor() &&
+ pAnchor->GetPageNum() == 0 ) )
+ {
+ // dann setze ihn, wird im Undo gebraucht
+ SwFmtAnchor aAnch( pFmt->GetAnchor() );
+ if (pAnchor && (FLY_AT_FLY == pAnchor->GetAnchorId()))
+ {
+ SwPosition aPos( *rAnchPos.nNode.GetNode().FindFlyStartNode() );
+ aAnch.SetAnchor( &aPos );
+ eAnchorId = FLY_AT_FLY;
+ }
+ else
+ {
+ if( eRequestId != aAnch.GetAnchorId() &&
+ SFX_ITEM_SET != pFmt->GetItemState( RES_ANCHOR, sal_True ) )
+ {
+ aAnch.SetType( eRequestId );
+ }
+
+ eAnchorId = aAnch.GetAnchorId();
+ if ( FLY_AT_PAGE != eAnchorId ||
+ ( FLY_AT_PAGE == eAnchorId &&
+ ( !pAnchor ||
+ aAnch.GetPageNum() == 0 ) ) )
+ {
+ aAnch.SetAnchor( &rAnchPos );
+ }
+ }
+ // <--
+ pFmt->SetFmtAttr( aAnch );
+ }
+ else
+ eAnchorId = pFmt->GetAnchor().GetAnchorId();
+
+ if ( FLY_AS_CHAR == eAnchorId )
+ {
+ xub_StrLen nStt = rAnchPos.nContent.GetIndex();
+ SwTxtNode * pTxtNode = rAnchPos.nNode.GetNode().GetTxtNode();
+
+ OSL_ENSURE(pTxtNode!= 0, "There should be a SwTxtNode!");
+
+ if (pTxtNode != NULL)
+ {
+ SwFmtFlyCnt aFmt( pFmt );
+ pTxtNode->InsertItem( aFmt, nStt, nStt );
+ }
+ }
+
+ if( SFX_ITEM_SET != pFmt->GetAttrSet().GetItemState( RES_FRM_SIZE ))
+ {
+ SwFmtFrmSize aFmtSize( ATT_VAR_SIZE, 0, DEF_FLY_WIDTH );
+ const SwNoTxtNode* pNoTxtNode = rNode.GetNoTxtNode();
+ if( pNoTxtNode )
+ {
+ //Groesse einstellen.
+ Size aSize( pNoTxtNode->GetTwipSize() );
+ if( MINFLY > aSize.Width() )
+ aSize.Width() = DEF_FLY_WIDTH;
+ aFmtSize.SetWidth( aSize.Width() );
+ if( aSize.Height() )
+ {
+ aFmtSize.SetHeight( aSize.Height() );
+ aFmtSize.SetHeightSizeType( ATT_FIX_SIZE );
+ }
+ }
+ pFmt->SetFmtAttr( aFmtSize );
+ }
+
+ // Frames anlegen
+ if( GetCurrentViewShell() )
+ pFmt->MakeFrms(); // ??? //swmod 071108//swmod 071225
+
+ if (GetIDocumentUndoRedo().DoesUndo())
+ {
+ sal_uLong nNodeIdx = rAnchPos.nNode.GetIndex();
+ xub_StrLen nCntIdx = rAnchPos.nContent.GetIndex();
+ GetIDocumentUndoRedo().AppendUndo(
+ new SwUndoInsLayFmt( pFmt, nNodeIdx, nCntIdx ));
+ }
+
+ SetModified();
+ return pFmt;
+}
+
+SwFlyFrmFmt* SwDoc::MakeFlySection( RndStdIds eAnchorType,
+ const SwPosition* pAnchorPos,
+ const SfxItemSet* pFlySet,
+ SwFrmFmt* pFrmFmt, sal_Bool bCalledFromShell )
+{
+ SwFlyFrmFmt* pFmt = 0;
+ sal_Bool bCallMake = sal_True;
+ if ( !pAnchorPos && (FLY_AT_PAGE != eAnchorType) )
+ {
+ const SwFmtAnchor* pAnch;
+ if( (pFlySet && SFX_ITEM_SET == pFlySet->GetItemState(
+ RES_ANCHOR, sal_False, (const SfxPoolItem**)&pAnch )) ||
+ ( pFrmFmt && SFX_ITEM_SET == pFrmFmt->GetItemState(
+ RES_ANCHOR, sal_True, (const SfxPoolItem**)&pAnch )) )
+ {
+ if ( (FLY_AT_PAGE != pAnch->GetAnchorId()) )
+ {
+ pAnchorPos = pAnch->GetCntntAnchor();
+ if (pAnchorPos)
+ {
+ bCallMake = sal_False;
+ }
+ }
+ }
+ }
+
+ if( bCallMake )
+ {
+ if( !pFrmFmt )
+ pFrmFmt = GetFrmFmtFromPool( RES_POOLFRM_FRAME );
+
+ sal_uInt16 nCollId = static_cast<sal_uInt16>(
+ get(IDocumentSettingAccess::HTML_MODE) ? RES_POOLCOLL_TEXT : RES_POOLCOLL_FRAME );
+
+ /* If there exists no adjust item in the paragraph
+ style for the content node of the new fly section
+ propagate an existing adjust item at the anchor to the new
+ content node. */
+ SwCntntNode * pNewTxtNd = GetNodes().MakeTxtNode
+ (SwNodeIndex( GetNodes().GetEndOfAutotext()),
+ GetTxtCollFromPool( nCollId ));
+ SwCntntNode * pAnchorNode = pAnchorPos->nNode.GetNode().GetCntntNode();
+
+ const SfxPoolItem * pItem = NULL;
+
+ if (bCalledFromShell && !lcl_IsItemSet(*pNewTxtNd, RES_PARATR_ADJUST) &&
+ SFX_ITEM_SET == pAnchorNode->GetSwAttrSet().
+ GetItemState(RES_PARATR_ADJUST, sal_True, &pItem))
+ static_cast<SwCntntNode *>(pNewTxtNd)->SetAttr(*pItem);
+
+ pFmt = _MakeFlySection( *pAnchorPos, *pNewTxtNd,
+ eAnchorType, pFlySet, pFrmFmt );
+ }
+ return pFmt;
+}
+
+SwFlyFrmFmt* SwDoc::MakeFlyAndMove( const SwPaM& rPam, const SfxItemSet& rSet,
+ const SwSelBoxes* pSelBoxes,
+ SwFrmFmt *pParent )
+{
+ SwFmtAnchor& rAnch = (SwFmtAnchor&)rSet.Get( RES_ANCHOR );
+
+ GetIDocumentUndoRedo().StartUndo( UNDO_INSLAYFMT, NULL );
+
+ SwFlyFrmFmt* pFmt = MakeFlySection( rAnch.GetAnchorId(), rPam.GetPoint(),
+ &rSet, pParent );
+
+ // Wenn Inhalt selektiert ist, so wird dieser jetzt zum Inhalt des
+ // neuen Rahmen. Sprich er wird in die entspr. Sektion des NodesArr
+ //gemoved.
+
+ if( pFmt )
+ {
+ do { // middle check loop
+ const SwFmtCntnt &rCntnt = pFmt->GetCntnt();
+ OSL_ENSURE( rCntnt.GetCntntIdx(), "Kein Inhalt vorbereitet." );
+ SwNodeIndex aIndex( *(rCntnt.GetCntntIdx()), 1 );
+ SwCntntNode *pNode = aIndex.GetNode().GetCntntNode();
+
+ // ACHTUNG: nicht einen Index auf dem Stack erzeugen, sonst
+ // kann der CntntnNode am Ende nicht geloscht werden !!
+ SwPosition aPos( aIndex );
+ aPos.nContent.Assign( pNode, 0 );
+
+ if( pSelBoxes && pSelBoxes->Count() )
+ {
+ // Tabellenselection
+ // kopiere Teile aus einer Tabelle: lege eine Tabelle mit der
+ // Breite der Originalen an und move (kopiere/loesche) die
+ // selektierten Boxen. Die Groessen werden prozentual
+ // korrigiert.
+
+ SwTableNode* pTblNd = (SwTableNode*)(*pSelBoxes)[0]->
+ GetSttNd()->FindTableNode();
+ if( !pTblNd )
+ break;
+
+ SwTable& rTbl = pTblNd->GetTable();
+
+ // ist die gesamte Tabelle selektiert ?
+ if( pSelBoxes->Count() == rTbl.GetTabSortBoxes().Count() )
+ {
+ // verschiebe die gesamte Tabelle
+ SwNodeRange aRg( *pTblNd, 0, *pTblNd->EndOfSectionNode(), 1 );
+
+ // wird die gesamte Tabelle verschoben und steht diese
+ // in einem FlyFrame, dann erzeuge dahinter einen neuen
+ // TextNode. Dadurch bleibt dieser Fly erhalten !
+ if( aRg.aEnd.GetNode().IsEndNode() )
+ GetNodes().MakeTxtNode( aRg.aStart,
+ (SwTxtFmtColl*)GetDfltTxtFmtColl() );
+
+ MoveNodeRange( aRg, aPos.nNode, DOC_MOVEDEFAULT );
+ }
+ else
+ {
+ rTbl.MakeCopy( this, aPos, *pSelBoxes );
+ // Don't delete a part of a table with row span!!
+ // You could delete the content instead -> ToDo
+ //rTbl.DeleteSel( this, *pSelBoxes, 0, 0, sal_True, sal_True );
+ }
+
+ // wenn Tabelle im Rahmen, dann ohne nachfolgenden TextNode
+ aIndex = rCntnt.GetCntntIdx()->GetNode().EndOfSectionIndex() - 1;
+ OSL_ENSURE( aIndex.GetNode().GetTxtNode(),
+ "hier sollte ein TextNode stehen" );
+ aPos.nContent.Assign( 0, 0 ); // Index abmelden !!
+ GetNodes().Delete( aIndex, 1 );
+
+//JP erstmal ein Hack, solange keine Flys/Headers/Footers Undofaehig sind
+// werden erstmal alle Undo - Objecte geloescht.
+if( GetIDocumentUndoRedo().DoesUndo() )
+{
+ GetIDocumentUndoRedo().DelAllUndoObj();
+}
+
+ }
+ else
+ {
+ // copy all Pams and then delete all
+ SwPaM* pTmp = (SwPaM*)&rPam;
+ sal_Bool bOldFlag = mbCopyIsMove;
+ bool const bOldUndo = GetIDocumentUndoRedo().DoesUndo();
+ mbCopyIsMove = sal_True;
+ GetIDocumentUndoRedo().DoUndo(false);
+ do {
+ if( pTmp->HasMark() &&
+ *pTmp->GetPoint() != *pTmp->GetMark() )
+ {
+ CopyRange( *pTmp, aPos, false );
+ }
+ pTmp = static_cast<SwPaM*>(pTmp->GetNext());
+ } while ( &rPam != pTmp );
+ mbCopyIsMove = bOldFlag;
+ GetIDocumentUndoRedo().DoUndo(bOldUndo);
+
+ pTmp = (SwPaM*)&rPam;
+ do {
+ if( pTmp->HasMark() &&
+ *pTmp->GetPoint() != *pTmp->GetMark() )
+ {
+ DeleteAndJoin( *pTmp );
+ }
+ pTmp = static_cast<SwPaM*>(pTmp->GetNext());
+ } while ( &rPam != pTmp );
+ }
+ } while( sal_False );
+ }
+
+ SetModified();
+
+ GetIDocumentUndoRedo().EndUndo( UNDO_INSLAYFMT, NULL );
+
+ return pFmt;
+}
+
+// Einfuegen eines DrawObjectes. Das Object muss bereits im DrawModel
+// angemeldet sein.
+SwDrawFrmFmt* SwDoc::Insert( const SwPaM &rRg,
+ SdrObject& rDrawObj,
+ const SfxItemSet* pFlyAttrSet,
+ SwFrmFmt* pDefFmt )
+{
+ SwDrawFrmFmt *pFmt = MakeDrawFrmFmt( aEmptyStr,
+ pDefFmt ? pDefFmt : GetDfltFrmFmt() );
+
+ const SwFmtAnchor* pAnchor = 0;
+ if( pFlyAttrSet )
+ {
+ pFlyAttrSet->GetItemState( RES_ANCHOR, sal_False,
+ (const SfxPoolItem**)&pAnchor );
+ pFmt->SetFmtAttr( *pFlyAttrSet );
+ }
+
+ RndStdIds eAnchorId = pAnchor ? pAnchor->GetAnchorId()
+ : pFmt->GetAnchor().GetAnchorId();
+
+ // Anker noch nicht gesetzt ?
+ // DrawObjecte duerfen niemals in Kopf-/Fusszeilen landen.
+ const bool bIsAtCntnt = (FLY_AT_PAGE != eAnchorId);
+
+ const SwNodeIndex* pChkIdx = 0;
+ if( !pAnchor )
+ {
+ pChkIdx = &rRg.GetPoint()->nNode;
+ }
+ else if( bIsAtCntnt )
+ {
+ pChkIdx = pAnchor->GetCntntAnchor()
+ ? &pAnchor->GetCntntAnchor()->nNode
+ : &rRg.GetPoint()->nNode;
+ }
+
+ // Allow drawing objects in header/footer, but control objects aren't
+ // allowed in header/footer.
+ if( pChkIdx &&
+ ::CheckControlLayer( &rDrawObj ) &&
+ IsInHeaderFooter( *pChkIdx ) )
+ {
+ pFmt->SetFmtAttr( SwFmtAnchor( eAnchorId = FLY_AT_PAGE ) );
+ }
+ else if( !pAnchor || (bIsAtCntnt && !pAnchor->GetCntntAnchor() ))
+ {
+ // dann setze ihn, wird im Undo gebraucht
+ SwFmtAnchor aAnch( pAnchor ? *pAnchor : pFmt->GetAnchor() );
+ eAnchorId = aAnch.GetAnchorId();
+ if( FLY_AT_FLY == eAnchorId )
+ {
+ SwPosition aPos( *rRg.GetNode()->FindFlyStartNode() );
+ aAnch.SetAnchor( &aPos );
+ }
+ else
+ {
+ aAnch.SetAnchor( rRg.GetPoint() );
+ if ( FLY_AT_PAGE == eAnchorId )
+ {
+ eAnchorId = rDrawObj.ISA( SdrUnoObj )
+ ? FLY_AS_CHAR : FLY_AT_PARA;
+ aAnch.SetType( eAnchorId );
+ }
+ }
+ pFmt->SetFmtAttr( aAnch );
+ }
+
+ // bei als Zeichen gebundenen Draws das Attribut im Absatz setzen
+ if ( FLY_AS_CHAR == eAnchorId )
+ {
+ xub_StrLen nStt = rRg.GetPoint()->nContent.GetIndex();
+ SwFmtFlyCnt aFmt( pFmt );
+ rRg.GetPoint()->nNode.GetNode().GetTxtNode()->InsertItem(
+ aFmt, nStt, nStt );
+ }
+
+ SwDrawContact* pContact = new SwDrawContact( pFmt, &rDrawObj );
+
+ // ggfs. Frames anlegen
+ if( GetCurrentViewShell() )
+ {
+ pFmt->MakeFrms();
+ // #i42319# - follow-up of #i35635#
+ // move object to visible layer
+ // #i79391#
+ if ( pContact->GetAnchorFrm() )
+ {
+ pContact->MoveObjToVisibleLayer( &rDrawObj );
+ }
+ }
+
+ if (GetIDocumentUndoRedo().DoesUndo())
+ {
+ GetIDocumentUndoRedo().AppendUndo( new SwUndoInsLayFmt(pFmt, 0, 0) );
+ }
+
+ SetModified();
+ return pFmt;
+}
+
+/* ---------------------------------------------------------------------------
+ paragraph frames - o.k. if the PaM includes the paragraph from the beginning
+ to the beginning of the next paragraph at least
+ frames at character - o.k. if the pam start at least at the same position
+ as the frame
+ ---------------------------------------------------------------------------*/
+sal_Bool TstFlyRange( const SwPaM* pPam, const SwPosition* pFlyPos,
+ RndStdIds nAnchorId )
+{
+ sal_Bool bOk = sal_False;
+ const SwPaM* pTmp = pPam;
+ do {
+ const sal_uInt32 nFlyIndex = pFlyPos->nNode.GetIndex();
+ const SwPosition* pPaMStart = pTmp->Start();
+ const SwPosition* pPaMEnd = pTmp->End();
+ const sal_uInt32 nPamStartIndex = pPaMStart->nNode.GetIndex();
+ const sal_uInt32 nPamEndIndex = pPaMEnd->nNode.GetIndex();
+ if (FLY_AT_PARA == nAnchorId)
+ bOk = (nPamStartIndex < nFlyIndex && nPamEndIndex > nFlyIndex) ||
+ (((nPamStartIndex == nFlyIndex) && (pPaMStart->nContent.GetIndex() == 0)) &&
+ (nPamEndIndex > nFlyIndex));
+ else
+ {
+ xub_StrLen nFlyContentIndex = pFlyPos->nContent.GetIndex();
+ xub_StrLen nPamEndContentIndex = pPaMEnd->nContent.GetIndex();
+ bOk = (nPamStartIndex < nFlyIndex &&
+ (( nPamEndIndex > nFlyIndex )||
+ ((nPamEndIndex == nFlyIndex) &&
+ (nPamEndContentIndex > nFlyContentIndex))) )
+ ||
+ (((nPamStartIndex == nFlyIndex) &&
+ (pPaMStart->nContent.GetIndex() <= nFlyContentIndex)) &&
+ ((nPamEndIndex > nFlyIndex) ||
+ (nPamEndContentIndex > nFlyContentIndex )));
+ }
+
+ } while( !bOk && pPam != ( pTmp = (const SwPaM*)pTmp->GetNext() ));
+ return bOk;
+}
+
+void SwDoc::GetAllFlyFmts( SwPosFlyFrms& rPosFlyFmts,
+ const SwPaM* pCmpRange, sal_Bool bDrawAlso,
+ sal_Bool bAsCharAlso ) const
+{
+ SwPosFlyFrm *pFPos = 0;
+ SwFrmFmt *pFly;
+
+ // erstmal alle Absatzgebundenen einsammeln
+ for( sal_uInt16 n = 0; n < GetSpzFrmFmts()->Count(); ++n )
+ {
+ pFly = (*GetSpzFrmFmts())[ n ];
+ bool bDrawFmt = bDrawAlso ? RES_DRAWFRMFMT == pFly->Which() : false;
+ bool bFlyFmt = RES_FLYFRMFMT == pFly->Which();
+ if( bFlyFmt || bDrawFmt )
+ {
+ const SwFmtAnchor& rAnchor = pFly->GetAnchor();
+ SwPosition const*const pAPos = rAnchor.GetCntntAnchor();
+ if (pAPos &&
+ ((FLY_AT_PARA == rAnchor.GetAnchorId()) ||
+ (FLY_AT_FLY == rAnchor.GetAnchorId()) ||
+ (FLY_AT_CHAR == rAnchor.GetAnchorId()) ||
+ ((FLY_AS_CHAR == rAnchor.GetAnchorId()) && bAsCharAlso)))
+ {
+ if( pCmpRange &&
+ !TstFlyRange( pCmpRange, pAPos, rAnchor.GetAnchorId() ))
+ continue; // kein gueltiger FlyFrame
+ pFPos = new SwPosFlyFrm( pAPos->nNode, pFly, rPosFlyFmts.Count() );
+ rPosFlyFmts.Insert( pFPos );
+ }
+ }
+ }
+
+ // kein Layout oder nur ein Teil, dann wars das
+ // Seitenbezogen Flys nur, wenn vollstaendig "gewuenscht" wird !
+ if( !GetCurrentViewShell() || pCmpRange ) //swmod 071108//swmod 071225
+ return;
+
+ pFPos = 0;
+ SwPageFrm *pPage = (SwPageFrm*)GetCurrentLayout()->GetLower(); //swmod 080218
+ while( pPage )
+ {
+ if( pPage->GetSortedObjs() )
+ {
+ SwSortedObjs &rObjs = *pPage->GetSortedObjs();
+ for( sal_uInt16 i = 0; i < rObjs.Count(); ++i)
+ {
+ SwAnchoredObject* pAnchoredObj = rObjs[i];
+ if ( pAnchoredObj->ISA(SwFlyFrm) )
+ pFly = &(pAnchoredObj->GetFrmFmt());
+ else if ( bDrawAlso )
+ pFly = &(pAnchoredObj->GetFrmFmt());
+ else
+ continue;
+
+ const SwFmtAnchor& rAnchor = pFly->GetAnchor();
+ if ((FLY_AT_PARA != rAnchor.GetAnchorId()) &&
+ (FLY_AT_FLY != rAnchor.GetAnchorId()) &&
+ (FLY_AT_CHAR != rAnchor.GetAnchorId()))
+ {
+ const SwCntntFrm * pCntntFrm = pPage->FindFirstBodyCntnt();
+ if ( !pCntntFrm )
+ {
+ //Oops! Eine leere Seite. Damit der Rahmen nicht ganz
+ //verlorengeht (RTF) suchen wir schnell den letzen
+ //Cntnt der vor der Seite steht.
+ SwPageFrm *pPrv = (SwPageFrm*)pPage->GetPrev();
+ while ( !pCntntFrm && pPrv )
+ {
+ pCntntFrm = pPrv->FindFirstBodyCntnt();
+ pPrv = (SwPageFrm*)pPrv->GetPrev();
+ }
+ }
+ if ( pCntntFrm )
+ {
+ SwNodeIndex aIdx( *pCntntFrm->GetNode() );
+ pFPos = new SwPosFlyFrm( aIdx, pFly, rPosFlyFmts.Count() );
+ }
+ }
+ if ( pFPos )
+ {
+ rPosFlyFmts.Insert( pFPos );
+ pFPos = 0;
+ }
+ }
+ }
+ pPage = (SwPageFrm*)pPage->GetNext();
+ }
+}
+
+/*************************************************************************
+|*
+|* SwDoc::InsertLabel()
+|*
+|*************************************************************************/
+
+/* #i6447# changed behaviour if lcl_CpyAttr:
+
+ If the old item set contains the item to set (no inheritance) copy the item
+ into the new set.
+
+ If the old item set contains the item by inheritance and the new set
+ contains the item, too:
+ If the two items differ copy the item from the old set to the new set.
+
+ Otherwise the new set will not be changed.
+*/
+void lcl_CpyAttr( SfxItemSet &rNewSet, const SfxItemSet &rOldSet, sal_uInt16 nWhich )
+{
+ const SfxPoolItem *pOldItem = NULL, *pNewItem = NULL;
+
+ rOldSet.GetItemState( nWhich, sal_False, &pOldItem);
+ if (pOldItem != NULL)
+ rNewSet.Put( *pOldItem );
+ else
+ {
+ pOldItem = rOldSet.GetItem( nWhich, sal_True);
+ if (pOldItem != NULL)
+ {
+ pNewItem = rNewSet.GetItem( nWhich, sal_True);
+ if (pNewItem != NULL)
+ {
+ if (*pOldItem != *pNewItem)
+ rNewSet.Put( *pOldItem );
+ }
+ else {
+ OSL_FAIL("What am I doing here?");
+ }
+ }
+ else {
+ OSL_FAIL("What am I doing here?");
+ }
+ }
+
+}
+
+static SwFlyFrmFmt *
+lcl_InsertLabel(SwDoc & rDoc, SwTxtFmtColls *const pTxtFmtCollTbl,
+ SwUndoInsertLabel *const pUndo,
+ SwLabelType const eType, String const& rTxt, String const& rSeparator,
+ const String& rNumberingSeparator,
+ const sal_Bool bBefore, const sal_uInt16 nId, const sal_uLong nNdIdx,
+ const String& rCharacterStyle,
+ const sal_Bool bCpyBrd )
+{
+ ::sw::UndoGuard const undoGuard(rDoc.GetIDocumentUndoRedo());
+
+ sal_Bool bTable = sal_False; //Um etwas Code zu sparen.
+
+ //Erstmal das Feld bauen, weil ueber den Namen die TxtColl besorgt werden
+ //muss
+ OSL_ENSURE( nId == USHRT_MAX || nId < rDoc.GetFldTypes()->Count(),
+ "FldType index out of bounds." );
+ SwFieldType *pType = (nId != USHRT_MAX) ? (*rDoc.GetFldTypes())[nId] : NULL;
+ OSL_ENSURE(!pType || pType->Which() == RES_SETEXPFLD, "wrong Id for Label");
+
+ SwTxtFmtColl * pColl = NULL;
+ if( pType )
+ {
+ for( sal_uInt16 i = pTxtFmtCollTbl->Count(); i; )
+ {
+ if( (*pTxtFmtCollTbl)[ --i ]->GetName() == pType->GetName() )
+ {
+ pColl = (*pTxtFmtCollTbl)[i];
+ break;
+ }
+ }
+ DBG_ASSERT( pColl, "no text collection found" );
+ }
+
+ if( !pColl )
+ {
+ pColl = rDoc.GetTxtCollFromPool( RES_POOLCOLL_LABEL );
+ }
+
+ SwTxtNode *pNew = NULL;
+ SwFlyFrmFmt* pNewFmt = NULL;
+
+ switch ( eType )
+ {
+ case LTYPE_TABLE:
+ bTable = sal_True;
+ /* Kein Break hier */
+ case LTYPE_FLY:
+ //Am Anfang/Ende der Fly-Section den entsprechenden Node mit Feld
+ //einfuegen (Frame wird automatisch erzeugt).
+ {
+ SwStartNode *pSttNd = rDoc.GetNodes()[nNdIdx]->GetStartNode();
+ OSL_ENSURE( pSttNd, "Kein StartNode in InsertLabel." );
+ sal_uLong nNode;
+ if( bBefore )
+ {
+ nNode = pSttNd->GetIndex();
+ if( !bTable )
+ ++nNode;
+ }
+ else
+ {
+ nNode = pSttNd->EndOfSectionIndex();
+ if( bTable )
+ ++nNode;
+ }
+
+ if( pUndo )
+ pUndo->SetNodePos( nNode );
+
+ //Node fuer Beschriftungsabsatz erzeugen.
+ SwNodeIndex aIdx( rDoc.GetNodes(), nNode );
+ pNew = rDoc.GetNodes().MakeTxtNode( aIdx, pColl );
+ }
+ break;
+
+ case LTYPE_OBJECT:
+ {
+ //Rahmen zerstoeren, neuen Rahmen einfuegen, entsprechenden
+ // Node mit Feld in den neuen Rahmen, den alten Rahmen mit
+ // dem Object (Grafik/Ole) absatzgebunden in den neuen Rahmen,
+ // Frames erzeugen.
+
+ //Erstmal das Format zum Fly besorgen und das Layout entkoppeln.
+ SwFrmFmt *pOldFmt = rDoc.GetNodes()[nNdIdx]->GetFlyFmt();
+ OSL_ENSURE( pOldFmt, "Format des Fly nicht gefunden." );
+ // --> OD #i115719#
+ // <title> and <description> attributes are lost when calling <DelFrms()>.
+ // Thus, keep them and restore them after the calling <MakeFrms()>
+ const bool bIsSwFlyFrmFmtInstance( dynamic_cast<SwFlyFrmFmt*>(pOldFmt) != 0 );
+ const String sTitle( bIsSwFlyFrmFmtInstance
+ ? static_cast<SwFlyFrmFmt*>(pOldFmt)->GetObjTitle()
+ : String() );
+ const String sDescription( bIsSwFlyFrmFmtInstance
+ ? static_cast<SwFlyFrmFmt*>(pOldFmt)->GetObjDescription()
+ : String() );
+ // <--
+ pOldFmt->DelFrms();
+
+ pNewFmt = rDoc.MakeFlyFrmFmt( rDoc.GetUniqueFrameName(),
+ rDoc.GetFrmFmtFromPool(RES_POOLFRM_FRAME) );
+
+ /* #i6447#: Only the selected items are copied from the old
+ format. */
+ SfxItemSet* pNewSet = pNewFmt->GetAttrSet().Clone( sal_True );
+
+
+ //Diejenigen Attribute uebertragen die auch gesetzt sind,
+ //andere sollen weiterhin aus den Vorlagen gueltig werden.
+ lcl_CpyAttr( *pNewSet, pOldFmt->GetAttrSet(), RES_PRINT );
+ lcl_CpyAttr( *pNewSet, pOldFmt->GetAttrSet(), RES_OPAQUE );
+ lcl_CpyAttr( *pNewSet, pOldFmt->GetAttrSet(), RES_PROTECT );
+ lcl_CpyAttr( *pNewSet, pOldFmt->GetAttrSet(), RES_SURROUND );
+ lcl_CpyAttr( *pNewSet, pOldFmt->GetAttrSet(), RES_VERT_ORIENT );
+ lcl_CpyAttr( *pNewSet, pOldFmt->GetAttrSet(), RES_HORI_ORIENT );
+ lcl_CpyAttr( *pNewSet, pOldFmt->GetAttrSet(), RES_LR_SPACE );
+ lcl_CpyAttr( *pNewSet, pOldFmt->GetAttrSet(), RES_UL_SPACE );
+ lcl_CpyAttr( *pNewSet, pOldFmt->GetAttrSet(), RES_BACKGROUND );
+ if( bCpyBrd )
+ {
+ // JP 07.07.99: Bug 67029 - if at Grafik no BoxItem but
+ // in the new Format is any, then set the
+ // default item in the new Set. Because
+ // the Size of the Grafik have never been
+ // changed!
+ const SfxPoolItem *pItem;
+ if( SFX_ITEM_SET == pOldFmt->GetAttrSet().
+ GetItemState( RES_BOX, sal_True, &pItem ))
+ pNewSet->Put( *pItem );
+ else if( SFX_ITEM_SET == pNewFmt->GetAttrSet().
+ GetItemState( RES_BOX, sal_True ))
+ pNewSet->Put( *GetDfltAttr( RES_BOX ) );
+
+ if( SFX_ITEM_SET == pOldFmt->GetAttrSet().
+ GetItemState( RES_SHADOW, sal_True, &pItem ))
+ pNewSet->Put( *pItem );
+ else if( SFX_ITEM_SET == pNewFmt->GetAttrSet().
+ GetItemState( RES_SHADOW, sal_True ))
+ pNewSet->Put( *GetDfltAttr( RES_SHADOW ) );
+ }
+ else
+ {
+ //Die Attribute hart setzen, weil sie sonst aus der
+ // Vorlage kommen koenten und dann passt die
+ // Grossenberechnung nicht mehr.
+ pNewSet->Put( SvxBoxItem(RES_BOX) );
+ pNewSet->Put( SvxShadowItem(RES_SHADOW) );
+
+ }
+
+ //Anker immer uebertragen, ist sowieso ein hartes Attribut.
+ pNewSet->Put( pOldFmt->GetAnchor() );
+
+ //In der Hoehe soll der neue Varabel sein!
+ SwFmtFrmSize aFrmSize( pOldFmt->GetFrmSize() );
+ aFrmSize.SetHeightSizeType( ATT_MIN_SIZE );
+ pNewSet->Put( aFrmSize );
+
+ SwStartNode* pSttNd = rDoc.GetNodes().MakeTextSection(
+ SwNodeIndex( rDoc.GetNodes().GetEndOfAutotext() ),
+ SwFlyStartNode, pColl );
+ pNewSet->Put( SwFmtCntnt( pSttNd ));
+
+ pNewFmt->SetFmtAttr( *pNewSet );
+
+ //Bei InCntnt's wird es spannend: Das TxtAttribut muss
+ //vernichtet werden. Leider reisst dies neben den Frms auch
+ //noch das Format mit in sein Grab. Um dass zu unterbinden
+ //loesen wir vorher die Verbindung zwischen Attribut und Format.
+
+ const SwFmtAnchor& rAnchor = pNewFmt->GetAnchor();
+ if ( FLY_AS_CHAR == rAnchor.GetAnchorId() )
+ {
+ const SwPosition *pPos = rAnchor.GetCntntAnchor();
+ SwTxtNode *pTxtNode = pPos->nNode.GetNode().GetTxtNode();
+ OSL_ENSURE( pTxtNode->HasHints(), "Missing FlyInCnt-Hint." );
+ const xub_StrLen nIdx = pPos->nContent.GetIndex();
+ SwTxtAttr * const pHnt =
+ pTxtNode->GetTxtAttrForCharAt(nIdx, RES_TXTATR_FLYCNT);
+
+ OSL_ENSURE( pHnt && pHnt->Which() == RES_TXTATR_FLYCNT,
+ "Missing FlyInCnt-Hint." );
+ OSL_ENSURE( pHnt && pHnt->GetFlyCnt().GetFrmFmt() == pOldFmt,
+ "Wrong TxtFlyCnt-Hint." );
+
+ const_cast<SwFmtFlyCnt&>(pHnt->GetFlyCnt()).SetFlyFmt(
+ pNewFmt );
+ }
+
+
+ //Der Alte soll keinen Umlauf haben, und er soll oben/mittig
+ //ausgerichtet sein.
+ //Ausserdem soll die Breite 100% betragen und bei Aenderungen
+ //Die Hoehe mit anpassen.
+ pNewSet->ClearItem();
+
+ pNewSet->Put( SwFmtSurround( SURROUND_NONE ) );
+ pNewSet->Put( SvxOpaqueItem( RES_OPAQUE, sal_True ) );
+ pNewSet->Put( SwFmtVertOrient( text::VertOrientation::TOP ) );
+ pNewSet->Put( SwFmtHoriOrient( text::HoriOrientation::CENTER ) );
+
+ aFrmSize = pOldFmt->GetFrmSize();
+ aFrmSize.SetWidthPercent( 100 );
+ aFrmSize.SetHeightPercent( 255 );
+ pNewSet->Put( aFrmSize );
+
+ //Die Attribute setzen wir hart, weil sie sonst aus der Vorlage
+ //kommen koenten und dann passt die Grossenberechnung nicht mehr.
+ if( bCpyBrd )
+ {
+ pNewSet->Put( SvxBoxItem(RES_BOX) );
+ pNewSet->Put( SvxShadowItem(RES_SHADOW) );
+ }
+ pNewSet->Put( SvxLRSpaceItem(RES_LR_SPACE) );
+ pNewSet->Put( SvxULSpaceItem(RES_UL_SPACE) );
+
+ //Der Alte ist absatzgebunden, und zwar am Absatz im neuen.
+ SwFmtAnchor aAnch( FLY_AT_PARA );
+ SwNodeIndex aAnchIdx( *pNewFmt->GetCntnt().GetCntntIdx(), 1 );
+ pNew = aAnchIdx.GetNode().GetTxtNode();
+ SwPosition aPos( aAnchIdx );
+ aAnch.SetAnchor( &aPos );
+ pNewSet->Put( aAnch );
+
+ if( pUndo )
+ pUndo->SetFlys( *pOldFmt, *pNewSet, *pNewFmt );
+ else
+ pOldFmt->SetFmtAttr( *pNewSet );
+
+ delete pNewSet;
+
+ //Nun nur noch die Flys erzeugen lassen. Das ueberlassen
+ //wir vorhanden Methoden (insb. fuer InCntFlys etwas aufwendig).
+ pNewFmt->MakeFrms();
+ // --> OD #i115719#
+ if ( bIsSwFlyFrmFmtInstance )
+ {
+ static_cast<SwFlyFrmFmt*>(pOldFmt)->SetObjTitle( sTitle );
+ static_cast<SwFlyFrmFmt*>(pOldFmt)->SetObjDescription( sDescription );
+ }
+ // <--
+ }
+ break;
+
+ default:
+ OSL_ENSURE(false, "unknown LabelType?");
+ }
+ OSL_ENSURE( pNew, "No Label inserted" );
+ if( pNew )
+ {
+ //#i61007# order of captions
+ sal_Bool bOrderNumberingFirst = SW_MOD()->GetModuleConfig()->IsCaptionOrderNumberingFirst();
+ //String aufbereiten
+ String aTxt;
+ if( bOrderNumberingFirst )
+ {
+ aTxt = rNumberingSeparator;
+ }
+ if( pType)
+ {
+ aTxt += pType->GetName();
+ if( !bOrderNumberingFirst )
+ aTxt += ' ';
+ }
+ xub_StrLen nIdx = aTxt.Len();
+ if( rTxt.Len() > 0 )
+ {
+ aTxt += rSeparator;
+ }
+ xub_StrLen nSepIdx = aTxt.Len();
+ aTxt += rTxt;
+
+ //String einfuegen
+ SwIndex aIdx( pNew, 0 );
+ pNew->InsertText( aTxt, aIdx );
+
+ //
+ //Feld einfuegen
+ if(pType)
+ {
+ SwSetExpField aFld( (SwSetExpFieldType*)pType, aEmptyStr, SVX_NUM_ARABIC);
+ if( bOrderNumberingFirst )
+ nIdx = 0;
+ SwFmtFld aFmt( aFld );
+ pNew->InsertItem( aFmt, nIdx, nIdx );
+ if(rCharacterStyle.Len())
+ {
+ SwCharFmt* pCharFmt = rDoc.FindCharFmtByName(rCharacterStyle);
+ if( !pCharFmt )
+ {
+ const sal_uInt16 nMyId = SwStyleNameMapper::GetPoolIdFromUIName(rCharacterStyle, nsSwGetPoolIdFromName::GET_POOLID_CHRFMT);
+ pCharFmt = rDoc.GetCharFmtFromPool( nMyId );
+ }
+ if (pCharFmt)
+ {
+ SwFmtCharFmt aCharFmt( pCharFmt );
+ pNew->InsertItem( aCharFmt, 0,
+ nSepIdx + 1, nsSetAttrMode::SETATTR_DONTEXPAND );
+ }
+ }
+ }
+
+ if ( bTable )
+ {
+ if ( bBefore )
+ {
+ if ( !pNew->GetSwAttrSet().GetKeep().GetValue() )
+ pNew->SetAttr( SvxFmtKeepItem( sal_True, RES_KEEP ) );
+ }
+ else
+ {
+ SwTableNode *const pNd =
+ rDoc.GetNodes()[nNdIdx]->GetStartNode()->GetTableNode();
+ SwTable &rTbl = pNd->GetTable();
+ if ( !rTbl.GetFrmFmt()->GetKeep().GetValue() )
+ rTbl.GetFrmFmt()->SetFmtAttr( SvxFmtKeepItem( sal_True, RES_KEEP ) );
+ if ( pUndo )
+ pUndo->SetUndoKeep();
+ }
+ }
+ rDoc.SetModified();
+ }
+
+ return pNewFmt;
+}
+
+SwFlyFrmFmt *
+SwDoc::InsertLabel(
+ SwLabelType const eType, String const& rTxt, String const& rSeparator,
+ String const& rNumberingSeparator,
+ sal_Bool const bBefore, sal_uInt16 const nId, sal_uLong const nNdIdx,
+ String const& rCharacterStyle,
+ sal_Bool const bCpyBrd )
+{
+ SwUndoInsertLabel * pUndo(0);
+ if (GetIDocumentUndoRedo().DoesUndo())
+ {
+ pUndo = new SwUndoInsertLabel(
+ eType, rTxt, rSeparator, rNumberingSeparator,
+ bBefore, nId, rCharacterStyle, bCpyBrd );
+ }
+
+ SwFlyFrmFmt *const pNewFmt = lcl_InsertLabel(*this, pTxtFmtCollTbl, pUndo,
+ eType, rTxt, rSeparator, rNumberingSeparator, bBefore,
+ nId, nNdIdx, rCharacterStyle, bCpyBrd);
+
+ if (pUndo)
+ {
+ GetIDocumentUndoRedo().AppendUndo(pUndo);
+ }
+ else
+ {
+ GetIDocumentUndoRedo().DelAllUndoObj();
+ }
+
+ return pNewFmt;
+}
+
+
+/*************************************************************************
+|*
+|* SwDoc::InsertDrawLabel()
+|*
+|*************************************************************************/
+static SwFlyFrmFmt *
+lcl_InsertDrawLabel( SwDoc & rDoc, SwTxtFmtColls *const pTxtFmtCollTbl,
+ SwUndoInsertLabel *const pUndo, SwDrawFrmFmt *const pOldFmt,
+ String const& rTxt,
+ const String& rSeparator,
+ const String& rNumberSeparator,
+ const sal_uInt16 nId,
+ const String& rCharacterStyle,
+ SdrObject& rSdrObj )
+{
+ ::sw::UndoGuard const undoGuard(rDoc.GetIDocumentUndoRedo());
+ ::sw::DrawUndoGuard const drawUndoGuard(rDoc.GetIDocumentUndoRedo());
+
+ // Erstmal das Feld bauen, weil ueber den Namen die TxtColl besorgt
+ // werden muss
+ OSL_ENSURE( nId == USHRT_MAX || nId < rDoc.GetFldTypes()->Count(),
+ "FldType index out of bounds" );
+ SwFieldType *pType = nId != USHRT_MAX ? (*rDoc.GetFldTypes())[nId] : 0;
+ OSL_ENSURE( !pType || pType->Which() == RES_SETEXPFLD, "Wrong label id" );
+
+ SwTxtFmtColl *pColl = NULL;
+ if( pType )
+ {
+ for( sal_uInt16 i = pTxtFmtCollTbl->Count(); i; )
+ {
+ if( (*pTxtFmtCollTbl)[ --i ]->GetName() == pType->GetName() )
+ {
+ pColl = (*pTxtFmtCollTbl)[i];
+ break;
+ }
+ }
+ DBG_ASSERT( pColl, "no text collection found" );
+ }
+
+ if( !pColl )
+ {
+ pColl = rDoc.GetTxtCollFromPool( RES_POOLCOLL_LABEL );
+ }
+
+ SwTxtNode* pNew = NULL;
+ SwFlyFrmFmt* pNewFmt = NULL;
+
+ // Rahmen zerstoeren, neuen Rahmen einfuegen, entsprechenden
+ // Node mit Feld in den neuen Rahmen, den alten Rahmen mit
+ // dem Object (Grafik/Ole) absatzgebunden in den neuen Rahmen,
+ // Frames erzeugen.
+
+ // Keep layer ID of drawing object before removing
+ // its frames.
+ // Note: The layer ID is passed to the undo and have to be the correct value.
+ // Removing the frames of the drawing object changes its layer.
+ const SdrLayerID nLayerId = rSdrObj.GetLayer();
+
+ pOldFmt->DelFrms();
+
+ //Bei InCntnt's wird es spannend: Das TxtAttribut muss
+ //vernichtet werden. Leider reisst dies neben den Frms auch
+ //noch das Format mit in sein Grab. Um dass zu unterbinden
+ //loesen wir vorher die Verbindung zwischen Attribut und Format.
+ SfxItemSet* pNewSet = pOldFmt->GetAttrSet().Clone( sal_False );
+
+ // Ggf. Groesse und Position des Rahmens schuetzen
+ if ( rSdrObj.IsMoveProtect() || rSdrObj.IsResizeProtect() )
+ {
+ SvxProtectItem aProtect(RES_PROTECT);
+ aProtect.SetCntntProtect( sal_False );
+ aProtect.SetPosProtect( rSdrObj.IsMoveProtect() );
+ aProtect.SetSizeProtect( rSdrObj.IsResizeProtect() );
+ pNewSet->Put( aProtect );
+ }
+
+ // Umlauf uebernehmen
+ lcl_CpyAttr( *pNewSet, pOldFmt->GetAttrSet(), RES_SURROUND );
+
+ // Den Rahmen ggf. in den Hintergrund schicken.
+ // Consider 'invisible' hell layer.
+ if ( rDoc.GetHellId() != nLayerId &&
+ rDoc.GetInvisibleHellId() != nLayerId )
+ {
+ SvxOpaqueItem aOpaque( RES_OPAQUE );
+ aOpaque.SetValue( sal_True );
+ pNewSet->Put( aOpaque );
+ }
+
+ // Position uebernehmen
+ // #i26791# - use directly the positioning attributes of
+ // the drawing object.
+ pNewSet->Put( pOldFmt->GetHoriOrient() );
+ pNewSet->Put( pOldFmt->GetVertOrient() );
+
+ pNewSet->Put( pOldFmt->GetAnchor() );
+
+ //In der Hoehe soll der neue Varabel sein!
+ Size aSz( rSdrObj.GetCurrentBoundRect().GetSize() );
+ SwFmtFrmSize aFrmSize( ATT_MIN_SIZE, aSz.Width(), aSz.Height() );
+ pNewSet->Put( aFrmSize );
+
+ // Abstaende auf den neuen Rahmen uebertragen. Eine Umrandung
+ // gibt es beu Zeichen-Objekten nicht, also muss sie geloescht
+ // werden.
+ // MA: Falsch sie wird nicht gesetzt, denn die aus der Vorlage
+ // soll ruhig wirksam werden
+ pNewSet->Put( pOldFmt->GetLRSpace() );
+ pNewSet->Put( pOldFmt->GetULSpace() );
+
+ SwStartNode* pSttNd =
+ rDoc.GetNodes().MakeTextSection(
+ SwNodeIndex( rDoc.GetNodes().GetEndOfAutotext() ),
+ SwFlyStartNode, pColl );
+
+ pNewFmt = rDoc.MakeFlyFrmFmt( rDoc.GetUniqueFrameName(),
+ rDoc.GetFrmFmtFromPool( RES_POOLFRM_FRAME ) );
+
+ // JP 28.10.99: Bug 69487 - set border and shadow to default if the
+ // template contains any.
+ if( SFX_ITEM_SET == pNewFmt->GetAttrSet().GetItemState( RES_BOX, sal_True ))
+ pNewSet->Put( *GetDfltAttr( RES_BOX ) );
+
+ if( SFX_ITEM_SET == pNewFmt->GetAttrSet().GetItemState(RES_SHADOW,sal_True))
+ pNewSet->Put( *GetDfltAttr( RES_SHADOW ) );
+
+ pNewFmt->SetFmtAttr( SwFmtCntnt( pSttNd ));
+ pNewFmt->SetFmtAttr( *pNewSet );
+
+ const SwFmtAnchor& rAnchor = pNewFmt->GetAnchor();
+ if ( FLY_AS_CHAR == rAnchor.GetAnchorId() )
+ {
+ const SwPosition *pPos = rAnchor.GetCntntAnchor();
+ SwTxtNode *pTxtNode = pPos->nNode.GetNode().GetTxtNode();
+ OSL_ENSURE( pTxtNode->HasHints(), "Missing FlyInCnt-Hint." );
+ const xub_StrLen nIdx = pPos->nContent.GetIndex();
+ SwTxtAttr * const pHnt =
+ pTxtNode->GetTxtAttrForCharAt( nIdx, RES_TXTATR_FLYCNT );
+
+#if OSL_DEBUG_LEVEL > 1
+ OSL_ENSURE( pHnt && pHnt->Which() == RES_TXTATR_FLYCNT,
+ "Missing FlyInCnt-Hint." );
+ OSL_ENSURE( pHnt && ((SwFmtFlyCnt&)pHnt->GetFlyCnt()).
+ GetFrmFmt() == (SwFrmFmt*)pOldFmt,
+ "Wrong TxtFlyCnt-Hint." );
+#endif
+ const_cast<SwFmtFlyCnt&>(pHnt->GetFlyCnt()).SetFlyFmt( pNewFmt );
+ }
+
+
+ //Der Alte soll keinen Umlauf haben, und er soll oben/mittig
+ //ausgerichtet sein.
+ pNewSet->ClearItem();
+
+ pNewSet->Put( SwFmtSurround( SURROUND_NONE ) );
+ if (nLayerId == rDoc.GetHellId())
+ {
+ // Consider drawing objects in 'invisible' hell layer
+ rSdrObj.SetLayer( rDoc.GetHeavenId() );
+ }
+ else if (nLayerId == rDoc.GetInvisibleHellId())
+ {
+ rSdrObj.SetLayer( rDoc.GetInvisibleHeavenId() );
+ }
+ pNewSet->Put( SvxLRSpaceItem( RES_LR_SPACE ) );
+ pNewSet->Put( SvxULSpaceItem( RES_UL_SPACE ) );
+
+ // #i26791# - set position of the drawing object, which is labeled.
+ pNewSet->Put( SwFmtVertOrient( 0, text::VertOrientation::TOP, text::RelOrientation::FRAME ) );
+ pNewSet->Put( SwFmtHoriOrient( 0, text::HoriOrientation::CENTER, text::RelOrientation::FRAME ) );
+
+ //Der Alte ist absatzgebunden, und zwar am Absatz im neuen.
+ SwFmtAnchor aAnch( FLY_AT_PARA );
+ SwNodeIndex aAnchIdx( *pNewFmt->GetCntnt().GetCntntIdx(), 1 );
+ pNew = aAnchIdx.GetNode().GetTxtNode();
+ SwPosition aPos( aAnchIdx );
+ aAnch.SetAnchor( &aPos );
+ pNewSet->Put( aAnch );
+
+ if( pUndo )
+ {
+ pUndo->SetFlys( *pOldFmt, *pNewSet, *pNewFmt );
+ // #i26791# - position no longer needed
+ pUndo->SetDrawObj( nLayerId );
+ }
+ else
+ pOldFmt->SetFmtAttr( *pNewSet );
+
+ delete pNewSet;
+
+ //Nun nur noch die Flys erzeugen lassen. Das ueberlassen
+ //wir vorhanden Methoden (insb. fuer InCntFlys etwas aufwendig).
+ pNewFmt->MakeFrms();
+
+ OSL_ENSURE( pNew, "No Label inserted" );
+
+ if( pNew )
+ {
+ //#i61007# order of captions
+ sal_Bool bOrderNumberingFirst = SW_MOD()->GetModuleConfig()->IsCaptionOrderNumberingFirst();
+
+ // prepare string
+ String aTxt;
+ if( bOrderNumberingFirst )
+ {
+ aTxt = rNumberSeparator;
+ }
+ if ( pType )
+ {
+ aTxt += pType->GetName();
+ if( !bOrderNumberingFirst )
+ aTxt += ' ';
+ }
+ xub_StrLen nIdx = aTxt.Len();
+ aTxt += rSeparator;
+ xub_StrLen nSepIdx = aTxt.Len();
+ aTxt += rTxt;
+
+ // insert text
+ SwIndex aIdx( pNew, 0 );
+ pNew->InsertText( aTxt, aIdx );
+
+ // insert field
+ if ( pType )
+ {
+ SwSetExpField aFld( (SwSetExpFieldType*)pType, aEmptyStr, SVX_NUM_ARABIC );
+ if( bOrderNumberingFirst )
+ nIdx = 0;
+ SwFmtFld aFmt( aFld );
+ pNew->InsertItem( aFmt, nIdx, nIdx );
+ if ( rCharacterStyle.Len() )
+ {
+ SwCharFmt * pCharFmt = rDoc.FindCharFmtByName(rCharacterStyle);
+ if ( !pCharFmt )
+ {
+ const sal_uInt16 nMyId = SwStyleNameMapper::GetPoolIdFromUIName( rCharacterStyle, nsSwGetPoolIdFromName::GET_POOLID_CHRFMT );
+ pCharFmt = rDoc.GetCharFmtFromPool( nMyId );
+ }
+ if ( pCharFmt )
+ {
+ SwFmtCharFmt aCharFmt( pCharFmt );
+ pNew->InsertItem( aCharFmt, 0, nSepIdx + 1,
+ nsSetAttrMode::SETATTR_DONTEXPAND );
+ }
+ }
+ }
+ }
+
+ return pNewFmt;
+}
+
+SwFlyFrmFmt* SwDoc::InsertDrawLabel(
+ String const& rTxt,
+ String const& rSeparator,
+ String const& rNumberSeparator,
+ sal_uInt16 const nId,
+ String const& rCharacterStyle,
+ SdrObject& rSdrObj )
+{
+ SwDrawContact *const pContact =
+ static_cast<SwDrawContact*>(GetUserCall( &rSdrObj ));
+ OSL_ENSURE( RES_DRAWFRMFMT == pContact->GetFmt()->Which(),
+ "InsertDrawLabel(): not a DrawFrmFmt" );
+ if (!pContact)
+ return 0;
+
+ SwDrawFrmFmt* pOldFmt = (SwDrawFrmFmt *)pContact->GetFmt();
+ if (!pOldFmt)
+ return 0;
+
+ SwUndoInsertLabel * pUndo = 0;
+ if (GetIDocumentUndoRedo().DoesUndo())
+ {
+ GetIDocumentUndoRedo().ClearRedo();
+ pUndo = new SwUndoInsertLabel(
+ LTYPE_DRAW, rTxt, rSeparator, rNumberSeparator, sal_False,
+ nId, rCharacterStyle, sal_False );
+ }
+
+ SwFlyFrmFmt *const pNewFmt = lcl_InsertDrawLabel(
+ *this, pTxtFmtCollTbl, pUndo, pOldFmt,
+ rTxt, rSeparator, rNumberSeparator, nId, rCharacterStyle, rSdrObj);
+
+ if (pUndo)
+ {
+ GetIDocumentUndoRedo().AppendUndo( pUndo );
+ }
+ else
+ {
+ GetIDocumentUndoRedo().DelAllUndoObj();
+ }
+
+ return pNewFmt;
+}
+
+
+/*************************************************************************
+|*
+|* IDocumentTimerAccess-methods
+|*
+|*************************************************************************/
+void SwDoc::StartIdling()
+{
+ mbStartIdleTimer = sal_True;
+ if( !mIdleBlockCount )
+ aIdleTimer.Start();
+}
+
+void SwDoc::StopIdling()
+{
+ mbStartIdleTimer = sal_False;
+ aIdleTimer.Stop();
+}
+
+void SwDoc::BlockIdling()
+{
+ aIdleTimer.Stop();
+ ++mIdleBlockCount;
+}
+
+void SwDoc::UnblockIdling()
+{
+ --mIdleBlockCount;
+ if( !mIdleBlockCount && mbStartIdleTimer && !aIdleTimer.IsActive() )
+ aIdleTimer.Start();
+}
+
+/*************************************************************************
+|*
+|* SwDoc::DoIdleJobs()
+|*
+|*************************************************************************/
+IMPL_LINK( SwDoc, DoIdleJobs, Timer *, pTimer )
+{
+#ifdef TIMELOG
+ static ::rtl::Logfile* pModLogFile = 0;
+ if( !pModLogFile )
+ pModLogFile = new ::rtl::Logfile( "First DoIdleJobs" );
+#endif
+
+ SwRootFrm* pTmpRoot = GetCurrentLayout();//swmod 080219
+ if( pTmpRoot &&
+ !SfxProgress::GetActiveProgress( pDocShell ) )
+ {
+ ViewShell *pSh, *pStartSh;
+ pSh = pStartSh = GetCurrentViewShell();
+ do {
+ if( pSh->ActionPend() )
+ {
+ if( pTimer )
+ pTimer->Start();
+ return 0;
+ }
+ pSh = (ViewShell*)pSh->GetNext();
+ } while( pSh != pStartSh );
+
+ if( pTmpRoot->IsNeedGrammarCheck() )
+ {
+ sal_Bool bIsOnlineSpell = pSh->GetViewOptions()->IsOnlineSpell();
+ sal_Bool bIsAutoGrammar = sal_False;
+ SvtLinguConfig().GetProperty( ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
+ UPN_IS_GRAMMAR_AUTO )) ) >>= bIsAutoGrammar;
+
+ if (bIsOnlineSpell && bIsAutoGrammar)
+ StartGrammarChecking( *this );
+ }
+ SwFldUpdateFlags nFldUpdFlag;
+ std::set<SwRootFrm*> aAllLayouts = GetAllLayouts();//swmod 080320
+ std::set<SwRootFrm*>::iterator pLayIter = aAllLayouts.begin();
+ for ( ;pLayIter != aAllLayouts.end();pLayIter++ )
+ {
+ if ((*pLayIter)->IsIdleFormat())
+ {
+ (*pLayIter)->GetCurrShell()->LayoutIdle();
+ break;
+ }
+ }
+ bool bAllValid = pLayIter == aAllLayouts.end() ? 1 : 0;
+ if( bAllValid && ( AUTOUPD_FIELD_ONLY ==
+ ( nFldUpdFlag = getFieldUpdateFlags(true) )
+ || AUTOUPD_FIELD_AND_CHARTS == nFldUpdFlag ) &&
+ GetUpdtFlds().IsFieldsDirty() &&
+ !GetUpdtFlds().IsInUpdateFlds() &&
+ !IsExpFldsLocked()
+ // das umschalten der Feldname fuehrt zu keinem Update der
+ // Felder, also der "Hintergrund-Update" immer erfolgen
+ /* && !pStartSh->GetViewOptions()->IsFldName()*/ )
+ {
+ // chaos::Action-Klammerung!
+ GetUpdtFlds().SetInUpdateFlds( sal_True );
+
+ pTmpRoot->StartAllAction();
+
+ // no jump on update of fields #i85168#
+ const sal_Bool bOldLockView = pStartSh->IsViewLocked();
+ pStartSh->LockView( sal_True );
+
+ GetSysFldType( RES_CHAPTERFLD )->ModifyNotification( 0, 0 ); // KapitelFld
+ UpdateExpFlds( 0, sal_False ); // Expression-Felder Updaten
+ UpdateTblFlds(NULL); // Tabellen
+ UpdateRefFlds(NULL); // Referenzen
+
+ pTmpRoot->EndAllAction();
+
+ pStartSh->LockView( bOldLockView );
+
+ GetUpdtFlds().SetInUpdateFlds( sal_False );
+ GetUpdtFlds().SetFieldsDirty( sal_False );
+ }
+ } //swmod 080219
+#ifdef TIMELOG
+ if( pModLogFile && 1 != (long)pModLogFile )
+ delete pModLogFile, ((long&)pModLogFile) = 1;
+#endif
+ if( pTimer )
+ pTimer->Start();
+ return 0;
+}
+
+IMPL_STATIC_LINK( SwDoc, BackgroundDone, SvxBrushItem*, EMPTYARG )
+{
+ ViewShell *pSh, *pStartSh;
+ pSh = pStartSh = pThis->GetCurrentViewShell(); //swmod 071108//swmod 071225
+ if( pStartSh )
+ do {
+ if( pSh->GetWin() )
+ {
+ //Fuer Repaint mir virtuellen Device sorgen.
+ pSh->LockPaint();
+ pSh->UnlockPaint( sal_True );
+ }
+ pSh = (ViewShell*)pSh->GetNext();
+ } while( pSh != pStartSh );
+ return 0;
+}
+
+static String lcl_GetUniqueFlyName( const SwDoc* pDoc, sal_uInt16 nDefStrId )
+{
+ ResId aId( nDefStrId, *pSwResMgr );
+ String aName( aId );
+ xub_StrLen nNmLen = aName.Len();
+
+ const SwSpzFrmFmts& rFmts = *pDoc->GetSpzFrmFmts();
+
+ sal_uInt16 nNum, nTmp, nFlagSize = ( rFmts.Count() / 8 ) +2;
+ sal_uInt8* pSetFlags = new sal_uInt8[ nFlagSize ];
+ sal_uInt16 n;
+
+ memset( pSetFlags, 0, nFlagSize );
+
+ for( n = 0; n < rFmts.Count(); ++n )
+ {
+ const SwFrmFmt* pFlyFmt = rFmts[ n ];
+ if( RES_FLYFRMFMT == pFlyFmt->Which() &&
+ pFlyFmt->GetName().Match( aName ) == nNmLen )
+ {
+ // Nummer bestimmen und das Flag setzen
+ nNum = static_cast< sal_uInt16 >( pFlyFmt->GetName().Copy( nNmLen ).ToInt32() );
+ if( nNum-- && nNum < rFmts.Count() )
+ pSetFlags[ nNum / 8 ] |= (0x01 << ( nNum & 0x07 ));
+ }
+ }
+
+ // alle Nummern entsprechend geflag, also bestimme die richtige Nummer
+ nNum = rFmts.Count();
+ for( n = 0; n < nFlagSize; ++n )
+ if( 0xff != ( nTmp = pSetFlags[ n ] ))
+ {
+ // also die Nummer bestimmen
+ nNum = n * 8;
+ while( nTmp & 1 )
+ ++nNum, nTmp >>= 1;
+ break;
+ }
+
+ delete [] pSetFlags;
+ return aName += String::CreateFromInt32( ++nNum );
+}
+
+String SwDoc::GetUniqueGrfName() const
+{
+ return lcl_GetUniqueFlyName( this, STR_GRAPHIC_DEFNAME );
+}
+
+String SwDoc::GetUniqueOLEName() const
+{
+ return lcl_GetUniqueFlyName( this, STR_OBJECT_DEFNAME );
+}
+
+String SwDoc::GetUniqueFrameName() const
+{
+ return lcl_GetUniqueFlyName( this, STR_FRAME_DEFNAME );
+}
+
+const SwFlyFrmFmt* SwDoc::FindFlyByName( const String& rName, sal_Int8 nNdTyp ) const
+{
+ const SwSpzFrmFmts& rFmts = *GetSpzFrmFmts();
+ for( sal_uInt16 n = rFmts.Count(); n; )
+ {
+ const SwFrmFmt* pFlyFmt = rFmts[ --n ];
+ const SwNodeIndex* pIdx;
+ if( RES_FLYFRMFMT == pFlyFmt->Which() && pFlyFmt->GetName() == rName &&
+ 0 != ( pIdx = pFlyFmt->GetCntnt().GetCntntIdx() ) &&
+ pIdx->GetNode().GetNodes().IsDocNodes() )
+ {
+ if( nNdTyp )
+ {
+ // dann noch auf den richtigen Node-Typ abfragen
+ const SwNode* pNd = GetNodes()[ pIdx->GetIndex()+1 ];
+ if( nNdTyp == ND_TEXTNODE
+ ? !pNd->IsNoTxtNode()
+ : nNdTyp == pNd->GetNodeType() )
+ return (SwFlyFrmFmt*)pFlyFmt;
+ }
+ else
+ return (SwFlyFrmFmt*)pFlyFmt;
+ }
+ }
+ return 0;
+}
+
+void SwDoc::SetFlyName( SwFlyFrmFmt& rFmt, const String& rName )
+{
+ String sName( rName );
+ if( !rName.Len() || FindFlyByName( rName ) )
+ {
+ sal_uInt16 nTyp = STR_FRAME_DEFNAME;
+ const SwNodeIndex* pIdx = rFmt.GetCntnt().GetCntntIdx();
+ if( pIdx && pIdx->GetNode().GetNodes().IsDocNodes() )
+ switch( GetNodes()[ pIdx->GetIndex() + 1 ]->GetNodeType() )
+ {
+ case ND_GRFNODE: nTyp = STR_GRAPHIC_DEFNAME; break;
+ case ND_OLENODE: nTyp = STR_OBJECT_DEFNAME; break;
+ }
+ sName = lcl_GetUniqueFlyName( this, nTyp );
+ }
+ rFmt.SetName( sName, sal_True );
+ SetModified();
+}
+
+void SwDoc::SetAllUniqueFlyNames()
+{
+ sal_uInt16 n, nFlyNum = 0, nGrfNum = 0, nOLENum = 0;
+
+ ResId nFrmId( STR_FRAME_DEFNAME, *pSwResMgr ),
+ nGrfId( STR_GRAPHIC_DEFNAME, *pSwResMgr ),
+ nOLEId( STR_OBJECT_DEFNAME, *pSwResMgr );
+ String sFlyNm( nFrmId );
+ String sGrfNm( nGrfId );
+ String sOLENm( nOLEId );
+
+ if( 255 < ( n = GetSpzFrmFmts()->Count() ))
+ n = 255;
+ SwSpzFrmFmts aArr( (sal_Int8)n, 10 );
+ SwFrmFmtPtr pFlyFmt;
+ sal_Bool bLoadedFlag = sal_True; // noch etwas fuers Layout
+
+ for( n = GetSpzFrmFmts()->Count(); n; )
+ {
+ if( RES_FLYFRMFMT == (pFlyFmt = (*GetSpzFrmFmts())[ --n ])->Which() )
+ {
+ sal_uInt16 *pNum = 0;
+ xub_StrLen nLen;
+ const String& rNm = pFlyFmt->GetName();
+ if( rNm.Len() )
+ {
+ if( rNm.Match( sGrfNm ) == ( nLen = sGrfNm.Len() ))
+ pNum = &nGrfNum;
+ else if( rNm.Match( sFlyNm ) == ( nLen = sFlyNm.Len() ))
+ pNum = &nFlyNum;
+ else if( rNm.Match( sOLENm ) == ( nLen = sOLENm.Len() ))
+ pNum = &nOLENum;
+
+ if ( pNum && *pNum < ( nLen = static_cast< xub_StrLen >( rNm.Copy( nLen ).ToInt32() ) ) )
+ *pNum = nLen;
+ }
+ else
+ // das wollen wir nachher setzen
+ aArr.Insert( pFlyFmt, aArr.Count() );
+
+ }
+ if( bLoadedFlag )
+ {
+ const SwFmtAnchor& rAnchor = pFlyFmt->GetAnchor();
+ if (((FLY_AT_PAGE == rAnchor.GetAnchorId()) &&
+ rAnchor.GetCntntAnchor()) ||
+ // oder werden DrawObjecte rel. zu irgendetwas ausgerichtet?
+ ( RES_DRAWFRMFMT == pFlyFmt->Which() && (
+ SFX_ITEM_SET == pFlyFmt->GetItemState(
+ RES_VERT_ORIENT )||
+ SFX_ITEM_SET == pFlyFmt->GetItemState(
+ RES_HORI_ORIENT ))) )
+ {
+ bLoadedFlag = sal_False;
+ }
+ }
+ }
+
+ const SwNodeIndex* pIdx;
+
+ for( n = aArr.Count(); n; )
+ if( 0 != ( pIdx = ( pFlyFmt = aArr[ --n ])->GetCntnt().GetCntntIdx() )
+ && pIdx->GetNode().GetNodes().IsDocNodes() )
+ {
+ sal_uInt16 nNum;
+ String sNm;
+ switch( GetNodes()[ pIdx->GetIndex() + 1 ]->GetNodeType() )
+ {
+ case ND_GRFNODE:
+ sNm = sGrfNm;
+ nNum = ++nGrfNum;
+ break;
+ case ND_OLENODE:
+ sNm = sOLENm;
+ nNum = ++nOLENum;
+ break;
+ default:
+ sNm = sFlyNm;
+ nNum = ++nFlyNum;
+ break;
+ }
+ pFlyFmt->SetName( sNm += String::CreateFromInt32( nNum ));
+ }
+ aArr.Remove( 0, aArr.Count() );
+
+ if( GetFtnIdxs().Count() )
+ {
+ SwTxtFtn::SetUniqueSeqRefNo( *this );
+ // --> FME 2005-08-02 #i52775# Chapter footnotes did not
+ // get updated correctly. Calling UpdateAllFtn() instead of
+ // UpdateFtn() solves this problem, but I do not dare to
+ // call UpdateAllFtn() in all cases: Safety first.
+ if ( FTNNUM_CHAPTER == GetFtnInfo().eNum )
+ {
+ GetFtnIdxs().UpdateAllFtn();
+ }
+ // <--
+ else
+ {
+ SwNodeIndex aTmp( GetNodes() );
+ GetFtnIdxs().UpdateFtn( aTmp );
+ }
+ }
+
+ // neues Document und keine seitengebundenen Rahmen/DrawObjecte gefunden,
+ // die an einem Node verankert sind.
+ if( bLoadedFlag )
+ SetLoaded( sal_True );
+}
+
+sal_Bool SwDoc::IsInHeaderFooter( const SwNodeIndex& rIdx ) const
+{
+ // gibt es ein Layout, dann ueber das laufen!!
+ // (Das kann dann auch Fly in Fly in Kopfzeile !)
+ // MIB 9.2.98: Wird auch vom sw3io benutzt, um festzustellen, ob sich
+ // ein Redline-Objekt in einer Kopf- oder Fusszeile befindet. Da
+ // Redlines auch an Start- und Endnodes haengen, muss der Index nicht
+ // unbedingt der eines Content-Nodes sein.
+ SwNode* pNd = &rIdx.GetNode();
+ if( pNd->IsCntntNode() && pCurrentView )//swmod 071029//swmod 071225
+ {
+ const SwFrm *pFrm = pNd->GetCntntNode()->getLayoutFrm( GetCurrentLayout() );
+ if( pFrm )
+ {
+ const SwFrm *pUp = pFrm->GetUpper();
+ while ( pUp && !pUp->IsHeaderFrm() && !pUp->IsFooterFrm() )
+ {
+ if ( pUp->IsFlyFrm() )
+ pUp = ((SwFlyFrm*)pUp)->GetAnchorFrm();
+ pUp = pUp->GetUpper();
+ }
+ if ( pUp )
+ return sal_True;
+
+ return sal_False;
+ }
+ }
+
+
+ const SwNode* pFlyNd = pNd->FindFlyStartNode();
+ while( pFlyNd )
+ {
+ // dann ueber den Anker nach oben "hangeln"
+ sal_uInt16 n;
+ for( n = 0; n < GetSpzFrmFmts()->Count(); ++n )
+ {
+ const SwFrmFmt* pFmt = (*GetSpzFrmFmts())[ n ];
+ const SwNodeIndex* pIdx = pFmt->GetCntnt().GetCntntIdx();
+ if( pIdx && pFlyNd == &pIdx->GetNode() )
+ {
+ const SwFmtAnchor& rAnchor = pFmt->GetAnchor();
+ if ((FLY_AT_PAGE == rAnchor.GetAnchorId()) ||
+ !rAnchor.GetCntntAnchor() )
+ {
+ return sal_False;
+ }
+
+ pNd = &rAnchor.GetCntntAnchor()->nNode.GetNode();
+ pFlyNd = pNd->FindFlyStartNode();
+ break;
+ }
+ }
+ if( n >= GetSpzFrmFmts()->Count() )
+ {
+ OSL_ENSURE( mbInReading, "Fly-Section aber kein Format gefunden" );
+ return sal_False;
+ }
+ }
+
+ return 0 != pNd->FindHeaderStartNode() ||
+ 0 != pNd->FindFooterStartNode();
+}
+
+short SwDoc::GetTextDirection( const SwPosition& rPos,
+ const Point* pPt ) const
+{
+ short nRet = -1;
+
+ SwCntntNode *pNd = rPos.nNode.GetNode().GetCntntNode();
+
+ // #i42921# - use new method <SwCntntNode::GetTextDirection(..)>
+ if ( pNd )
+ {
+ nRet = pNd->GetTextDirection( rPos, pPt );
+ }
+ if ( nRet == -1 )
+ {
+ const SvxFrameDirectionItem* pItem = 0;
+ if( pNd )
+ {
+ // in a flyframe? Then look at that for the correct attribute
+ const SwFrmFmt* pFlyFmt = pNd->GetFlyFmt();
+ while( pFlyFmt )
+ {
+ pItem = &pFlyFmt->GetFrmDir();
+ if( FRMDIR_ENVIRONMENT == pItem->GetValue() )
+ {
+ pItem = 0;
+ const SwFmtAnchor* pAnchor = &pFlyFmt->GetAnchor();
+ if ((FLY_AT_PAGE != pAnchor->GetAnchorId()) &&
+ pAnchor->GetCntntAnchor())
+ {
+ pFlyFmt = pAnchor->GetCntntAnchor()->nNode.
+ GetNode().GetFlyFmt();
+ }
+ else
+ pFlyFmt = 0;
+ }
+ else
+ pFlyFmt = 0;
+ }
+
+ if( !pItem )
+ {
+ const SwPageDesc* pPgDsc = pNd->FindPageDesc( sal_False );
+ if( pPgDsc )
+ pItem = &pPgDsc->GetMaster().GetFrmDir();
+ }
+ }
+ if( !pItem )
+ pItem = (SvxFrameDirectionItem*)&GetAttrPool().GetDefaultItem(
+ RES_FRAMEDIR );
+ nRet = pItem->GetValue();
+ }
+ return nRet;
+}
+
+sal_Bool SwDoc::IsInVerticalText( const SwPosition& rPos, const Point* pPt ) const
+{
+ const short nDir = GetTextDirection( rPos, pPt );
+ return FRMDIR_VERT_TOP_RIGHT == nDir || FRMDIR_VERT_TOP_LEFT == nDir;
+}
+
+void SwDoc::SetCurrentViewShell( ViewShell* pNew )
+{
+ pCurrentView = pNew;
+}
+
+SwLayouter* SwDoc::GetLayouter()
+{
+ return pLayouter;
+}
+
+const SwLayouter* SwDoc::GetLayouter() const
+{
+ return pLayouter;
+}
+
+void SwDoc::SetLayouter( SwLayouter* pNew )
+{
+ pLayouter = pNew;
+}
+
+const ViewShell *SwDoc::GetCurrentViewShell() const
+{
+ return pCurrentView;
+}
+
+ViewShell *SwDoc::GetCurrentViewShell()
+{
+ return pCurrentView;
+} //swmod 080219 It must be able to communicate to a ViewShell.This is going to be removedd later.
+
+const SwRootFrm *SwDoc::GetCurrentLayout() const
+{
+ if(GetCurrentViewShell())
+ return GetCurrentViewShell()->GetLayout();
+ return 0;
+}
+
+SwRootFrm *SwDoc::GetCurrentLayout()
+{
+ if(GetCurrentViewShell())
+ return GetCurrentViewShell()->GetLayout();
+ return 0;
+}
+
+bool SwDoc::HasLayout() const
+{
+ // if there is a view, there is always a layout
+ return (pCurrentView != 0);
+}
+
+std::set<SwRootFrm*> SwDoc::GetAllLayouts()
+{
+ std::set<SwRootFrm*> aAllLayouts;
+ ViewShell *pStart = GetCurrentViewShell();
+ ViewShell *pTemp = pStart;
+ if ( pTemp )
+ {
+ do
+ {
+ if (pTemp->GetLayout())
+ {
+ aAllLayouts.insert(pTemp->GetLayout());
+ pTemp = (ViewShell*)pTemp->GetNext();
+ }
+ } while(pTemp!=pStart);
+ }
+
+ return aAllLayouts;
+}//swmod 070825
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ \ No newline at end of file
diff --git a/sw/source/core/doc/docnew.cxx b/sw/source/core/doc/docnew.cxx
new file mode 100644
index 000000000000..5c18528525f7
--- /dev/null
+++ b/sw/source/core/doc/docnew.cxx
@@ -0,0 +1,1204 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+#define ROLBCK_HISTORY_ONLY // Der Kampf gegen die CLOOK's
+#include <doc.hxx>
+#include <dcontact.hxx>
+#include <com/sun/star/document/PrinterIndependentLayout.hpp>
+#include <com/sun/star/document/UpdateDocMode.hpp>
+#include <com/sun/star/text/XTextDocument.hpp>
+#include <com/sun/star/linguistic2/XProofreadingIterator.hpp>
+#include <com/sun/star/text/XFlatParagraphIteratorProvider.hpp>
+
+#include <unotools/processfactory.hxx>
+#include <vcl/svapp.hxx>
+#include <vcl/virdev.hxx>
+#include <rtl/logfile.hxx>
+#include <sfx2/printer.hxx>
+#include <sfx2/docfile.hxx>
+#include <sfx2/frame.hxx>
+#include <sfx2/viewfrm.hxx>
+
+#include <svl/macitem.hxx>
+#include <svx/svxids.hrc>
+#include <svx/svdogrp.hxx>
+#include <sfx2/linkmgr.hxx>
+#include <editeng/forbiddencharacterstable.hxx>
+#include <svl/zforlist.hxx>
+#include <unotools/compatibility.hxx>
+#include <unotools/lingucfg.hxx>
+#include <svx/svdpage.hxx>
+#include <paratr.hxx>
+#include <fchrfmt.hxx>
+#include <fmtcntnt.hxx>
+#include <fmtanchr.hxx>
+#include <fmtfsize.hxx>
+#include <fmtfordr.hxx>
+#include <fmtpdsc.hxx>
+#include <pvprtdat.hxx>
+#include <rootfrm.hxx> //Damit der RootDtor gerufen wird.
+#include <layouter.hxx>
+#include <pagedesc.hxx> //Damit die PageDescs zerstoert werden koennen.
+#include <ndtxt.hxx>
+#include <printdata.hxx>
+#include <docfld.hxx>
+#include <ftninfo.hxx>
+#include <ftnidx.hxx>
+#include <docstat.hxx>
+#include <charfmt.hxx>
+#include <frmfmt.hxx>
+#include <rolbck.hxx> // Undo-Attr, SwHistory
+#include <poolfmt.hxx> // fuer die Pool-Vorlage
+#include <dbmgr.hxx>
+#include <docsh.hxx>
+#include <acorrect.hxx> // fuer die autom. Aufnahme von Ausnahmen
+#include <visiturl.hxx> // fuer die URL-Change Benachrichtigung
+#include <docary.hxx>
+#include <lineinfo.hxx>
+#include <drawdoc.hxx>
+#include <linkenum.hxx>
+#include <fldupde.hxx>
+#include <extinput.hxx>
+#include <viewsh.hxx>
+#include <doctxm.hxx>
+#include <shellres.hxx>
+#include <breakit.hxx>
+#include <laycache.hxx>
+#include <mvsave.hxx>
+#include <istyleaccess.hxx>
+#include <swstylemanager.hxx>
+#include <IGrammarContact.hxx>
+#include <tblsel.hxx>
+#include <MarkManager.hxx>
+#include <UndoManager.hxx>
+#include <unochart.hxx>
+
+#include <cmdid.h> // fuer den dflt - Printer in SetJob
+
+
+#include <com/sun/star/document/XDocumentInfoSupplier.hpp>
+#include <com/sun/star/beans/XPropertyContainer.hpp>
+#include <com/sun/star/beans/PropertyAttribute.hpp>
+
+#include <pausethreadstarting.hxx>
+#include <numrule.hxx>
+#include <list.hxx>
+#include <listfunc.hxx>
+
+#include <com/sun/star/document/XDocumentPropertiesSupplier.hpp>
+
+#include <sfx2/Metadatable.hxx>
+#include <fmtmeta.hxx> // MetaFieldManager
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::document;
+
+const sal_Char sFrmFmtStr[] = "Frameformat";
+const sal_Char sEmptyPageStr[] = "Empty Page";
+const sal_Char sColumnCntStr[] = "Columncontainer";
+const sal_Char sCharFmtStr[] = "Zeichenformat";
+const sal_Char sTxtCollStr[] = "Textformatvorlage";
+const sal_Char sGrfCollStr[] = "Graphikformatvorlage";
+
+SV_IMPL_PTRARR( SwNumRuleTbl, SwNumRulePtr)
+SV_IMPL_PTRARR( SwTxtFmtColls, SwTxtFmtCollPtr)
+SV_IMPL_PTRARR( SwGrfFmtColls, SwGrfFmtCollPtr)
+
+/*
+ * global functions...
+ */
+ uno::Reference< linguistic2::XProofreadingIterator > SwDoc::GetGCIterator() const
+{
+ if (!m_xGCIterator.is() && SvtLinguConfig().HasGrammarChecker())
+ {
+ uno::Reference< lang::XMultiServiceFactory > xMgr( utl::getProcessServiceFactory() );
+ if (xMgr.is())
+ {
+ try
+ {
+ rtl::OUString aServiceName(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.linguistic2.ProofreadingIterator"));
+ m_xGCIterator = uno::Reference< linguistic2::XProofreadingIterator >
+ ( xMgr->createInstance( aServiceName ), uno::UNO_QUERY_THROW );
+ }
+ catch (uno::Exception &)
+ {
+ OSL_FAIL( "No GCIterator" );
+ }
+ }
+ }
+
+ return m_xGCIterator;
+}
+
+void StartGrammarChecking( SwDoc &rDoc )
+{
+ // check for a visible view
+ bool bVisible = false;
+ const SwDocShell *pDocShell = rDoc.GetDocShell();
+ SfxViewFrame *pFrame = SfxViewFrame::GetFirst( pDocShell, sal_False );
+ while (pFrame && !bVisible)
+ {
+ if (pFrame->IsVisible())
+ bVisible = true;
+ pFrame = SfxViewFrame::GetNext( *pFrame, pDocShell, sal_False );
+ }
+
+ //!! only documents with visible views need to be checked
+ //!! (E.g. don't check temporary documents created for printing, see printing of notes and selections.
+ //!! Those get created on the fly and get hard deleted a bit later as well, and no one should have
+ //!! a uno reference to them)
+ if (bVisible)
+ {
+ uno::Reference< linguistic2::XProofreadingIterator > xGCIterator( rDoc.GetGCIterator() );
+ if ( xGCIterator.is() )
+ {
+ uno::Reference< lang::XComponent > xDoc( rDoc.GetDocShell()->GetBaseModel(), uno::UNO_QUERY );
+ uno::Reference< text::XFlatParagraphIteratorProvider > xFPIP( xDoc, uno::UNO_QUERY );
+
+ // start automatic background checking if not active already
+ if ( xFPIP.is() && !xGCIterator->isProofreading( xDoc ) )
+ xGCIterator->startProofreading( xDoc, xFPIP );
+ }
+ }
+}
+
+/*
+ * interne Funktionen
+ */
+sal_Bool lcl_DelFmtIndizes( const SwFrmFmtPtr& rpFmt, void* )
+{
+ SwFmtCntnt &rFmtCntnt = (SwFmtCntnt&)rpFmt->GetCntnt();
+ if ( rFmtCntnt.GetCntntIdx() )
+ rFmtCntnt.SetNewCntntIdx( 0 );
+ SwFmtAnchor &rFmtAnchor = (SwFmtAnchor&)rpFmt->GetAnchor();
+ if ( rFmtAnchor.GetCntntAnchor() )
+ rFmtAnchor.SetAnchor( 0 );
+ return sal_True;
+}
+
+/*
+ * exportierte Methoden
+ */
+SwDoc::SwDoc()
+ : m_pNodes( new SwNodes(this) )
+ ,
+ mpAttrPool(new SwAttrPool(this)),
+ pMarkManager(new ::sw::mark::MarkManager(*this)),
+ m_pMetaFieldManager(new ::sw::MetaFieldManager()),
+ m_pUndoManager(new ::sw::UndoManager(
+ ::std::auto_ptr<SwNodes>(new SwNodes(this)), *this, *this, *this)),
+ pDfltFrmFmt( new SwFrmFmt( GetAttrPool(), sFrmFmtStr, 0 ) ),
+ pEmptyPageFmt( new SwFrmFmt( GetAttrPool(), sEmptyPageStr, pDfltFrmFmt ) ),
+ pColumnContFmt( new SwFrmFmt( GetAttrPool(), sColumnCntStr, pDfltFrmFmt ) ),
+ pDfltCharFmt( new SwCharFmt( GetAttrPool(), sCharFmtStr, 0 ) ),
+ pDfltTxtFmtColl( new SwTxtFmtColl( GetAttrPool(), sTxtCollStr ) ),
+ pDfltGrfFmtColl( new SwGrfFmtColl( GetAttrPool(), sGrfCollStr ) ),
+ pFrmFmtTbl( new SwFrmFmts() ),
+ pCharFmtTbl( new SwCharFmts() ),
+ pSpzFrmFmtTbl( new SwSpzFrmFmts() ),
+ pSectionFmtTbl( new SwSectionFmts() ),
+ pTblFrmFmtTbl( new SwFrmFmts() ),
+ pTxtFmtCollTbl( new SwTxtFmtColls() ),
+ pGrfFmtCollTbl( new SwGrfFmtColls() ),
+ pTOXTypes( new SwTOXTypes() ),
+ pDefTOXBases( new SwDefTOXBase_Impl() ),
+ pCurrentView( 0 ), //swmod 071225
+ pDrawModel( 0 ),
+ pUpdtFlds( new SwDocUpdtFld() ),
+ pFldTypes( new SwFldTypes() ),
+ pVirDev( 0 ),
+ pPrt( 0 ),
+ pPrtData( 0 ),
+ pGlossaryDoc( 0 ),
+ pOutlineRule( 0 ),
+ pFtnInfo( new SwFtnInfo ),
+ pEndNoteInfo( new SwEndNoteInfo ),
+ pLineNumberInfo( new SwLineNumberInfo ),
+ pFtnIdxs( new SwFtnIdxs ),
+ pDocStat( new SwDocStat ),
+ pDocShell( 0 ),
+ pLinkMgr( new sfx2::LinkManager( 0 ) ),
+ pACEWord( 0 ),
+ pURLStateChgd( 0 ),
+ pNumberFormatter( 0 ),
+ pNumRuleTbl( new SwNumRuleTbl ),
+ maLists(),
+ maListStyleLists(),
+ pRedlineTbl( new SwRedlineTbl ),
+ pAutoFmtRedlnComment( 0 ),
+ pUnoCrsrTbl( new SwUnoCrsrTbl( 0, 16 ) ),
+ pPgPViewPrtData( 0 ),
+ pExtInputRing( 0 ),
+ pLayouter( 0 ),
+ pStyleAccess( 0 ),
+ pLayoutCache( 0 ),
+ pUnoCallBack(new SwModify(0)),
+ mpGrammarContact( 0 ),
+ aChartDataProviderImplRef(),
+ pChartControllerHelper( 0 ),
+ mpListItemsList( new tImplSortedNodeNumList() ), // #i83479#
+ m_pXmlIdRegistry(),
+ nAutoFmtRedlnCommentNo( 0 ),
+ nLinkUpdMode( GLOBALSETTING ),
+ eFldUpdMode( AUTOUPD_GLOBALSETTING ),
+ eRedlineMode((RedlineMode_t)(nsRedlineMode_t::REDLINE_SHOW_INSERT | nsRedlineMode_t::REDLINE_SHOW_DELETE)),
+ eChrCmprType( CHARCOMPRESS_NONE ),
+ mReferenceCount(0),
+ mIdleBlockCount(0),
+ nLockExpFld( 0 ),
+ mbReadlineChecked(false),
+ mbLinksUpdated( sal_False ), //#i38810#
+ mbClipBoard( false ),
+ mbColumnSelection( false ),
+ mbProtectForm(false), // i#78591#
+ mbLastBrowseMode( false ),
+ n32DummyCompatabilityOptions1(0),
+ n32DummyCompatabilityOptions2(0),
+ mbStartIdleTimer(sal_False)
+{
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLog, "SW", "JP93722", "SwDoc::SwDoc" );
+
+ mbGlossDoc =
+ mbModified =
+ mbDtor =
+ mbPageNums =
+ mbLoaded =
+ mbUpdateExpFld =
+ mbNewDoc =
+ mbCopyIsMove =
+ mbInReading =
+ mbInXMLImport =
+ mbUpdateTOX =
+ mbInLoadAsynchron =
+ mbHTMLMode =
+ mbInCallModified =
+ mbIsGlobalDoc =
+ mbGlblDocSaveLinks =
+ mbIsLabelDoc =
+ mbIsAutoFmtRedline =
+ mbOLEPrtNotifyPending =
+ mbAllOLENotify =
+ mbIsRedlineMove =
+ mbInsOnlyTxtGlssry =
+ mbContains_MSVBasic =
+ mbKernAsianPunctuation =
+#if OSL_DEBUG_LEVEL > 1
+ mbXMLExport =
+#endif
+ mbApplyWorkaroundForB6375613 =
+ false;
+
+ mbNewFldLst =
+ mbVisibleLinks =
+ mbPurgeOLE =
+ true;
+
+ //
+ // COMPATIBILITY FLAGS START
+ //
+
+ // Note: Any non-hidden compatibility flag should obtain its default
+ // by asking SvtCompatibilityOptions, see below.
+ //
+ const SvtCompatibilityOptions aOptions;
+ mbParaSpaceMax = aOptions.IsAddSpacing();
+ mbParaSpaceMaxAtPages = aOptions.IsAddSpacingAtPages();
+ mbTabCompat = !aOptions.IsUseOurTabStops();
+ mbUseVirtualDevice = !aOptions.IsUsePrtDevice();
+ mbAddExternalLeading = !aOptions.IsNoExtLeading();
+ mbOldLineSpacing = aOptions.IsUseLineSpacing();
+ mbAddParaSpacingToTableCells = aOptions.IsAddTableSpacing();
+ mbUseFormerObjectPos = aOptions.IsUseObjectPositioning();
+ mbUseFormerTextWrapping = aOptions.IsUseOurTextWrapping();
+ mbConsiderWrapOnObjPos = aOptions.IsConsiderWrappingStyle();
+ mbMathBaselineAlignment = false; // default for *old* documents is 'off'
+ mbAddFlyOffsets = false; // hidden
+ mbOldNumbering = false; // hidden
+ mbUseHiResolutionVirtualDevice = true; // hidden
+ mbIgnoreFirstLineIndentInNumbering = false; // hidden
+ mbDoNotJustifyLinesWithManualBreak = !aOptions.IsExpandWordSpace();
+ mbDoNotResetParaAttrsForNumFont = false; // hidden
+ mbOutlineLevelYieldsOutlineRule = false; // hidden
+ mbTableRowKeep = false; // hidden
+ mbIgnoreTabsAndBlanksForLineCalculation = false; // hidden
+ mbDoNotCaptureDrawObjsOnPage = false; // hidden
+ mbClipAsCharacterAnchoredWriterFlyFrames= false; // hidden
+ mbUnixForceZeroExtLeading = false; // hidden
+ mbOldPrinterMetrics = false; // hidden
+ mbTabRelativeToIndent = true; // hidden
+ mbTabAtLeftIndentForParagraphsInList = false; // hidden #i89181#
+ mbInvertBorderSpacing = false; // hidden
+ mbCollapseEmptyCellPara = true; // hidden
+
+ //
+ // COMPATIBILITY FLAGS END
+ //
+
+ pMacroTable = new SvxMacroTableDtor;
+
+ mpGrammarContact = ::createGrammarContact();
+
+ /*
+ * Defaultformate und DefaultFormatsammlungen (FmtColl)
+ * werden an der Position 0 in das jeweilige Array eingetragen.
+ * Die Formate der FmtColls sind von den Defaultformaten
+ * abgeleitet und stehen auch in der Liste.
+ */
+ /* Formate */
+ pFrmFmtTbl->Insert(pDfltFrmFmt, 0 );
+ pCharFmtTbl->Insert(pDfltCharFmt, 0 );
+
+ /* FmtColls */
+ // TXT
+ pTxtFmtCollTbl->Insert(pDfltTxtFmtColl, 0 );
+ // GRF
+ pGrfFmtCollTbl->Insert(pDfltGrfFmtColl, 0 );
+
+ // PageDesc, EmptyPageFmt und ColumnFmt anlegen
+ if ( !aPageDescs.Count() )
+ GetPageDescFromPool( RES_POOLPAGE_STANDARD );
+
+ //Leere Seite Einstellen.
+ pEmptyPageFmt->SetFmtAttr( SwFmtFrmSize( ATT_FIX_SIZE ) );
+ //BodyFmt fuer Spalten Einstellen.
+ pColumnContFmt->SetFmtAttr( SwFmtFillOrder( ATT_LEFT_TO_RIGHT ) );
+
+ _InitFieldTypes();
+
+ // lege (fuer die Filter) eine Default-OutlineNumRule an
+ pOutlineRule = new SwNumRule( String::CreateFromAscii( SwNumRule::GetOutlineRuleName() ),
+ // #i89178#
+ numfunc::GetDefaultPositionAndSpaceMode(),
+ OUTLINE_RULE );
+ AddNumRule(pOutlineRule);
+ // Counting of phantoms depends on <IsOldNumbering()>
+ pOutlineRule->SetCountPhantoms( !get(IDocumentSettingAccess::OLD_NUMBERING) );
+
+ new SwTxtNode(
+ SwNodeIndex(GetUndoManager().GetUndoNodes().GetEndOfContent()),
+ pDfltTxtFmtColl );
+ new SwTxtNode( SwNodeIndex( GetNodes().GetEndOfContent() ),
+ GetTxtCollFromPool( RES_POOLCOLL_STANDARD ));
+
+ // den eigenen IdleTimer setzen
+ aIdleTimer.SetTimeout( 600 );
+ aIdleTimer.SetTimeoutHdl( LINK(this, SwDoc, DoIdleJobs) );
+
+ aOLEModifiedTimer.SetTimeout( 1000 );
+ aOLEModifiedTimer.SetTimeoutHdl( LINK( this, SwDoc, DoUpdateModifiedOLE ));
+
+ // DBMgr anlegen
+ pNewDBMgr = new SwNewDBMgr;
+
+ // create TOXTypes
+ InitTOXTypes();
+
+ // pass empty item set containing the paragraph's list attributes
+ // as ignorable items to the stype manager.
+ {
+ SfxItemSet aIgnorableParagraphItems( GetAttrPool(),
+ RES_PARATR_LIST_BEGIN, RES_PARATR_LIST_END-1,
+ 0 );
+ pStyleAccess = createStyleManager( &aIgnorableParagraphItems );
+ }
+
+ ResetModified();
+}
+
+/*
+ * Besonderheiten: an der Position 0 des Arrays der Formate und
+ * der GDI-Objekte befindet sich ein Member der Klasse SwDoc.
+ * Dieser darf also keinesfalls durch delete geloescht
+ * werden!!!!!!!!!!
+ */
+SwDoc::~SwDoc()
+{
+ // nothing here should create Undo actions!
+ GetIDocumentUndoRedo().DoUndo(false);
+
+ if (pDocShell)
+ {
+ pDocShell->SetUndoManager(0);
+ }
+
+
+ // #i83479#
+ delete mpListItemsList;
+ mpListItemsList = 0;
+
+ // clean up chart related structures...
+ // Note: the chart data provider gets already diposed in ~SwDocShell
+ // since all UNO API related functionality requires an existing SwDocShell
+ // this assures that dipose gets called if there is need for it.
+ aChartDataProviderImplRef.reset();
+ delete pChartControllerHelper;
+
+ delete mpGrammarContact;
+ mpGrammarContact = 0;
+
+ //!! needs to be done to destroy a possible SwFmtDrop format that may
+ //!! be connected to a char format which may not otherwise be removed
+ //!! and thus would leave a unremoved SwFmt object. (TL)
+ //!! (this is case is not possible via UI but via API...)
+ SwFmtDrop aDrop;
+ SetDefault(aDrop);
+ //!! same for SwFmtCharFmt
+ SwFmtCharFmt aCharFmt(NULL);
+ SetDefault(aCharFmt);
+
+ StopIdling(); // stop idle timer
+
+ delete pUnoCallBack, pUnoCallBack = 0;
+ delete pURLStateChgd;
+
+ delete pLayouter;
+ pLayouter = 0L;
+
+ // Undo-Benachrichtigung vom Draw abschalten
+ if( pDrawModel )
+ {
+ DrawNotifyUndoHdl();
+ ClrContourCache();
+ }
+
+ delete pPgPViewPrtData;
+
+ mbDtor = sal_True;
+
+ delete pRedlineTbl;
+ delete pUnoCrsrTbl;
+ delete pAutoFmtRedlnComment;
+
+ if( pUpdtFlds )
+ delete pUpdtFlds;
+
+ if( pACEWord )
+ delete pACEWord;
+
+ // die BaseLinks freigeben.
+ {
+ for( sal_uInt16 n = pLinkMgr->GetServers().Count(); n; )
+ pLinkMgr->GetServers()[ --n ]->Closed();
+
+ if( pLinkMgr->GetLinks().Count() )
+ pLinkMgr->Remove( 0, pLinkMgr->GetLinks().Count() );
+ }
+
+ // die KapitelNummern / Nummern muessen vor den Vorlage geloescht werden
+ // ansonsten wird noch staendig geupdatet !!!
+ m_pNodes->pOutlineNds->Remove(sal_uInt16(0), m_pNodes->pOutlineNds->Count());
+ SwNodes & rUndoNodes( GetUndoManager().GetUndoNodes() );
+ rUndoNodes.pOutlineNds->Remove(sal_uInt16(0), rUndoNodes.pOutlineNds->Count());
+
+ pFtnIdxs->Remove( sal_uInt16(0), pFtnIdxs->Count() );
+
+ // indices could be registered in attributes
+ m_pUndoManager->DelAllUndoObj();
+
+ // in den BookMarks sind Indizies auf den Content. Diese muessen vorm
+ // loesche der Nodes geloescht werden.
+ pMarkManager->clearAllMarks();
+ DELETEZ( pMacroTable );
+
+ if( pExtInputRing )
+ {
+ Ring* pTmp = pExtInputRing;
+ pExtInputRing = 0;
+ while( pTmp->GetNext() != pTmp )
+ delete pTmp->GetNext();
+ delete pTmp;
+ }
+
+//JP: alt - loeschen ohne Flag ist teuer; Modify wird verschickt!
+// aTOXTypes.DeleteAndDestroy( 0, aTOXTypes.Count() );
+ {
+ for( sal_uInt16 n = pTOXTypes->Count(); n; )
+ {
+ (*pTOXTypes)[ --n ]->SetInDocDTOR();
+ delete (*pTOXTypes)[ n ];
+ }
+ pTOXTypes->Remove( 0, pTOXTypes->Count() );
+ }
+ delete pDefTOXBases;
+
+ //Im einen oder anderen FrmFormat koennen noch Indizes angemeldet sein,
+ //Diese muessen spaetestens jetzt zerstoert werden.
+ pFrmFmtTbl->ForEach( &lcl_DelFmtIndizes, this );
+ pSpzFrmFmtTbl->ForEach( &lcl_DelFmtIndizes, this );
+ ((SwFrmFmts&)*pSectionFmtTbl).ForEach( &lcl_DelFmtIndizes, this );
+
+ //Die Formate, die hier hinter stehen sind von den DefaultFormaten
+ //abhaengig. Erst nach dem Loeschen der FmtIndizes weil der Inhalt von
+ //Kopf-/Fussbereichen geloescht wird. Wenn dort noch Indizes von Flys
+ //angemeldet sind gibts was an die Ohren.
+ aPageDescs.DeleteAndDestroy( 0, aPageDescs.Count() );
+
+ // Inhaltssections loeschen
+ // nicht erst durch den SwNodes-DTOR, damit Formate
+ // keine Abhaengigen mehr haben.
+ m_pNodes->DelNodes( SwNodeIndex(*m_pNodes), m_pNodes->Count() );
+ rUndoNodes.DelNodes( SwNodeIndex( rUndoNodes ), rUndoNodes.Count() );
+
+ // Formate loeschen, spaeter mal permanent machen.
+
+ // Delete fuer Collections
+ // damit die Abhaengigen wech sind
+ pFtnInfo->ReleaseCollection();
+ pEndNoteInfo->ReleaseCollection();
+
+ OSL_ENSURE( pDfltTxtFmtColl == (*pTxtFmtCollTbl)[0],
+ "Default-Text-Collection muss immer am Anfang stehen" );
+
+ // JP 27.01.98: opt.: ausgehend davon, das Standard als 2. im Array
+ // steht, sollte das als letztes geloescht werden, damit
+ // die ganze Umhaengerei der Formate vermieden wird!
+ if( 2 < pTxtFmtCollTbl->Count() )
+ pTxtFmtCollTbl->DeleteAndDestroy( 2, pTxtFmtCollTbl->Count()-2 );
+ pTxtFmtCollTbl->DeleteAndDestroy( 1, pTxtFmtCollTbl->Count()-1 );
+ delete pTxtFmtCollTbl;
+
+ OSL_ENSURE( pDfltGrfFmtColl == (*pGrfFmtCollTbl)[0],
+ "Default-Grf-Collection muss immer am Anfang stehen" );
+
+ pGrfFmtCollTbl->DeleteAndDestroy( 1, pGrfFmtCollTbl->Count()-1 );
+// ergibt sich automatisch - kein _DEL Array!
+// pGrfFmtCollTbl->Remove( 0, n );
+ delete pGrfFmtCollTbl;
+
+ /*
+ * Defaultformate und DefaultFormatsammlungen (FmtColl)
+ * sind an der Position 0 der jeweiligen Arrays eingetragen.
+ * Damit sie nicht vom DTOR der Array's zum 2.mal geloescht werden,
+ * nehme sie aus dem Array.
+ */
+ pFrmFmtTbl->Remove( 0 );
+ pCharFmtTbl->Remove( 0 );
+
+ // Delete fuer pPrt
+ DELETEZ( pPrt );
+ DELETEZ( pNewDBMgr );
+
+ // Alle Flys muessen vor dem Drawing Model zerstoert werden,
+ // da Flys noch DrawContacts enthalten koennen, wenn wegen
+ // eines Lesefehlers kein Layout aufgebaut wurde.
+ pSpzFrmFmtTbl->DeleteAndDestroy( 0, pSpzFrmFmtTbl->Count() );
+
+ //Erst jetzt das Model zerstoeren, die Zeichenobjekte - die ja auch
+ //im Undo herumlungern - wollen noch ihre Attribute beim Model entfernen.
+ //Ausserdem koennen vorher noch DrawContacts existieren.
+ ReleaseDrawModel();
+ //JP 28.01.99: DrawModel vorm LinkManager zerstoeren, da am DrawModel
+ // dieser immer gesetzt ist.
+ DELETEZ( pLinkMgr );
+
+ //Tables vor dem loeschen der Defaults leeren, sonst GPF wegen Def-Abhaengigen.
+ //Die Arrays sollten (wegen includes) bei Gelegenheit auch zu Pointern werden.
+ delete pFrmFmtTbl;
+ delete pSpzFrmFmtTbl;
+
+ delete pStyleAccess;
+
+ delete pCharFmtTbl;
+ delete pSectionFmtTbl;
+ delete pTblFrmFmtTbl;
+ delete pDfltTxtFmtColl;
+ delete pDfltGrfFmtColl;
+ delete pNumRuleTbl;
+
+ {
+ for ( boost::unordered_map< String, SwList*, StringHash >::iterator
+ aListIter = maLists.begin();
+ aListIter != maLists.end();
+ ++aListIter )
+ {
+ delete (*aListIter).second;
+ }
+ maLists.clear();
+ }
+ maListStyleLists.clear();
+
+ delete pPrtData;
+ delete pNumberFormatter;
+ delete pFtnInfo;
+ delete pEndNoteInfo;
+ delete pLineNumberInfo;
+ delete pFtnIdxs;
+ delete pFldTypes;
+ delete pTOXTypes;
+ delete pDocStat;
+ delete pEmptyPageFmt;
+ delete pColumnContFmt;
+ delete pDfltCharFmt;
+ delete pDfltFrmFmt;
+ delete pLayoutCache;
+ delete pVirDev;
+
+ SfxItemPool::Free(mpAttrPool);
+}
+
+VirtualDevice& SwDoc::CreateVirtualDevice_() const
+{
+ VirtualDevice* pNewVir = new VirtualDevice( 1 );
+
+ pNewVir->SetReferenceDevice( VirtualDevice::REFDEV_MODE_MSO1 );
+
+ // #i60945# External leading compatibility for unix systems.
+ if ( get(IDocumentSettingAccess::UNIX_FORCE_ZERO_EXT_LEADING ) )
+ pNewVir->Compat_ZeroExtleadBug();
+
+ MapMode aMapMode( pNewVir->GetMapMode() );
+ aMapMode.SetMapUnit( MAP_TWIP );
+ pNewVir->SetMapMode( aMapMode );
+
+ const_cast<SwDoc*>(this)->setVirtualDevice( pNewVir, true, true );
+ return *pVirDev;
+}
+
+SfxPrinter& SwDoc::CreatePrinter_() const
+{
+ OSL_ENSURE( ! pPrt, "Do not call CreatePrinter_(), call getPrinter() instead" );
+
+#if OSL_DEBUG_LEVEL > 1
+ OSL_FAIL( "Printer will be created!" );
+#endif
+
+ // wir erzeugen einen default SfxPrinter.
+ // Das ItemSet wird vom Sfx geloescht!
+ SfxItemSet *pSet = new SfxItemSet( ((SwDoc*)this)->GetAttrPool(),
+ FN_PARAM_ADDPRINTER, FN_PARAM_ADDPRINTER,
+ SID_HTML_MODE, SID_HTML_MODE,
+ SID_PRINTER_NOTFOUND_WARN, SID_PRINTER_NOTFOUND_WARN,
+ SID_PRINTER_CHANGESTODOC, SID_PRINTER_CHANGESTODOC,
+ 0 );
+
+ SfxPrinter* pNewPrt = new SfxPrinter( pSet );
+ const_cast<SwDoc*>(this)->setPrinter( pNewPrt, true, true );
+ return *pPrt;
+}
+
+void SwDoc::SetDocShell( SwDocShell* pDSh )
+{
+ if( pDocShell != pDSh )
+ {
+ if (pDocShell)
+ {
+ pDocShell->SetUndoManager(0);
+ }
+ pDocShell = pDSh;
+ if (pDocShell)
+ {
+ pDocShell->SetUndoManager(& GetUndoManager());
+ }
+
+ pLinkMgr->SetPersist( pDocShell );
+ //JP 27.08.98: Bug 55570 - DocShell Pointer auch am DrawModel setzen
+ if( pDrawModel )
+ {
+ ((SwDrawDocument*)pDrawModel)->SetObjectShell( pDocShell );
+ pDrawModel->SetPersist( pDocShell );
+ OSL_ENSURE( pDrawModel->GetPersist() == GetPersist(),
+ "draw model's persist is out of sync" );
+ }
+ }
+}
+
+// Convenience-Methode, um uebermaessige Includes von docsh.hxx
+// zu vermeiden
+uno::Reference < embed::XStorage > SwDoc::GetDocStorage()
+{
+ if( pDocShell )
+ return pDocShell->GetStorage();
+ if( pLinkMgr->GetPersist() )
+ return pLinkMgr->GetPersist()->GetStorage();
+ return NULL;
+}
+
+SfxObjectShell* SwDoc::GetPersist() const
+{
+ return pDocShell ? pDocShell : pLinkMgr->GetPersist();
+}
+
+void SwDoc::ClearDoc()
+{
+ GetIDocumentUndoRedo().DelAllUndoObj();
+ ::sw::UndoGuard const undoGuard(GetIDocumentUndoRedo());
+
+ // Undo-Benachrichtigung vom Draw abschalten
+ if( pDrawModel )
+ {
+ DrawNotifyUndoHdl();
+ ClrContourCache();
+ }
+
+ // stehen noch FlyFrames rum, loesche auch diese
+ sal_uInt16 n;
+ while ( 0 != (n = GetSpzFrmFmts()->Count()) )
+ DelLayoutFmt((*pSpzFrmFmtTbl)[n-1]);
+ OSL_ENSURE( !pDrawModel || !pDrawModel->GetPage(0)->GetObjCount(),
+ "not all DrawObjects removed from the page" );
+
+ pRedlineTbl->DeleteAndDestroy( 0, pRedlineTbl->Count() );
+
+ if( pACEWord )
+ delete pACEWord;
+
+ // in den BookMarks sind Indizies auf den Content. Diese muessen vorm
+ // loesche der Nodes geloescht werden.
+ pMarkManager->clearAllMarks();
+ InitTOXTypes();
+
+ // create a dummy pagedesc for the layout
+ sal_uInt16 nDummyPgDsc = MakePageDesc( String::CreateFromAscii( "?DUMMY?" ));
+ SwPageDesc* pDummyPgDsc = aPageDescs[ nDummyPgDsc ];
+
+ SwNodeIndex aSttIdx( *GetNodes().GetEndOfContent().StartOfSectionNode(), 1 );
+ // den ersten immer wieder neu anlegen (ohne Attribute/Vorlagen/...)
+ SwTxtNode* pFirstNd = GetNodes().MakeTxtNode( aSttIdx, pDfltTxtFmtColl );
+
+ if( pCurrentView ) //swmod 071029//swmod 071225
+ {
+ // set the layout to the dummy pagedesc
+ pFirstNd->SetAttr( SwFmtPageDesc( pDummyPgDsc ));
+
+ SwPosition aPos( *pFirstNd, SwIndex( pFirstNd ));
+ SwPaM const tmpPaM(aSttIdx, SwNodeIndex(GetNodes().GetEndOfContent()));
+ ::PaMCorrAbs(tmpPaM, aPos);
+ }
+
+ GetNodes().Delete( aSttIdx,
+ GetNodes().GetEndOfContent().GetIndex() - aSttIdx.GetIndex() );
+
+ // #i62440#
+ // destruction of numbering rules and creation of new outline rule
+ // *after* the document nodes are deleted.
+ pOutlineRule = NULL;
+ pNumRuleTbl->DeleteAndDestroy( 0, pNumRuleTbl->Count() );
+ // creation of new outline numbering rule
+ pOutlineRule = new SwNumRule( String::CreateFromAscii( SwNumRule::GetOutlineRuleName() ),
+ // #i89178#
+ numfunc::GetDefaultPositionAndSpaceMode(),
+ OUTLINE_RULE );
+ AddNumRule(pOutlineRule);
+ // Counting of phantoms depends on <IsOldNumbering()>
+ pOutlineRule->SetCountPhantoms( !get(IDocumentSettingAccess::OLD_NUMBERING) );
+
+ //remove the dummy pagedec from the array and delete all the old ones
+ aPageDescs.Remove( nDummyPgDsc );
+ aPageDescs.DeleteAndDestroy( 0, aPageDescs.Count() );
+
+ // Delete fuer Collections
+ // damit die Abhaengigen wech sind
+ pFtnInfo->ReleaseCollection();
+ pEndNoteInfo->ReleaseCollection();
+
+ // opt.: ausgehend davon, das Standard als 2. im Array
+ // steht, sollte das als letztes geloescht werden, damit
+ // die ganze Umhaengerei der Formate vermieden wird!
+ if( 2 < pTxtFmtCollTbl->Count() )
+ pTxtFmtCollTbl->DeleteAndDestroy( 2, pTxtFmtCollTbl->Count()-2 );
+ pTxtFmtCollTbl->DeleteAndDestroy( 1, pTxtFmtCollTbl->Count()-1 );
+ pGrfFmtCollTbl->DeleteAndDestroy( 1, pGrfFmtCollTbl->Count()-1 );
+ pCharFmtTbl->DeleteAndDestroy( 1, pCharFmtTbl->Count()-1 );
+
+ if( pCurrentView )
+ {
+ // search the FrameFormat of the root frm. This is not allowed to delete
+ pFrmFmtTbl->Remove( pFrmFmtTbl->GetPos( pCurrentView->GetLayout()->GetFmt() ) );
+ pFrmFmtTbl->DeleteAndDestroy( 1, pFrmFmtTbl->Count()-1 );
+ pFrmFmtTbl->Insert( pCurrentView->GetLayout()->GetFmt(), pFrmFmtTbl->Count() );
+ }
+ else //swmod 071029//swmod 071225
+ pFrmFmtTbl->DeleteAndDestroy( 1, pFrmFmtTbl->Count()-1 );
+
+ xForbiddenCharsTable.clear();
+
+ pFldTypes->DeleteAndDestroy( INIT_FLDTYPES,
+ pFldTypes->Count() - INIT_FLDTYPES );
+
+ delete pNumberFormatter, pNumberFormatter = 0;
+
+ GetPageDescFromPool( RES_POOLPAGE_STANDARD );
+ pFirstNd->ChgFmtColl( GetTxtCollFromPool( RES_POOLCOLL_STANDARD ));
+ nDummyPgDsc = aPageDescs.Count();
+ aPageDescs.Insert( pDummyPgDsc, nDummyPgDsc );
+ // set the layout back to the new standard pagedesc
+ pFirstNd->ResetAllAttr();
+ // delete now the dummy pagedesc
+ DelPageDesc( nDummyPgDsc );
+}
+
+void SwDoc::SetPreViewPrtData( const SwPagePreViewPrtData* pNew )
+{
+ if( pNew )
+ {
+ if( pPgPViewPrtData )
+ *pPgPViewPrtData = *pNew;
+ else
+ pPgPViewPrtData = new SwPagePreViewPrtData( *pNew );
+ }
+ else if( pPgPViewPrtData )
+ DELETEZ( pPgPViewPrtData );
+ SetModified();
+}
+
+SwModify* SwDoc::GetUnoCallBack() const
+{
+ return pUnoCallBack;
+}
+
+
+/** SwDoc:
+ * Reading and writing of the layout cache.
+ *--------------------------------------------------*/
+void SwDoc::ReadLayoutCache( SvStream& rStream )
+{
+ if( !pLayoutCache )
+ pLayoutCache = new SwLayoutCache();
+ if( !pLayoutCache->IsLocked() )
+ {
+ pLayoutCache->GetLockCount() |= 0x8000;
+ pLayoutCache->Read( rStream );
+ pLayoutCache->GetLockCount() &= 0x7fff;
+ }
+}
+
+void SwDoc::WriteLayoutCache( SvStream& rStream )
+{
+ pLayoutCache->Write( rStream, *this );
+}
+
+IGrammarContact* getGrammarContact( const SwTxtNode& rTxtNode )
+{
+ const SwDoc* pDoc = rTxtNode.GetDoc();
+ if( !pDoc || pDoc->IsInDtor() )
+ return 0;
+ return pDoc->getGrammarContact();
+}
+
+// #i42634# Moved common code of SwReader::Read() and SwDocShell::UpdateLinks()
+// to new SwDoc::UpdateLinks():
+void SwDoc::UpdateLinks( sal_Bool bUI )
+{
+ SfxObjectCreateMode eMode;
+ sal_uInt16 nLinkMode = getLinkUpdateMode( true );
+ sal_uInt16 nUpdateDocMode = GetDocShell()->GetUpdateDocMode();
+ if( GetDocShell() &&
+ (nLinkMode != NEVER || document::UpdateDocMode::FULL_UPDATE == nUpdateDocMode) &&
+ GetLinkManager().GetLinks().Count() &&
+ SFX_CREATE_MODE_INTERNAL !=
+ ( eMode = GetDocShell()->GetCreateMode()) &&
+ SFX_CREATE_MODE_ORGANIZER != eMode &&
+ SFX_CREATE_MODE_PREVIEW != eMode &&
+ !GetDocShell()->IsPreview() )
+ {
+ ViewShell* pVSh = 0;
+ sal_Bool bAskUpdate = nLinkMode == MANUAL;
+ sal_Bool bUpdate = sal_True;
+ switch(nUpdateDocMode)
+ {
+ case document::UpdateDocMode::NO_UPDATE: bUpdate = sal_False;break;
+ case document::UpdateDocMode::QUIET_UPDATE:bAskUpdate = sal_False; break;
+ case document::UpdateDocMode::FULL_UPDATE: bAskUpdate = sal_True; break;
+ }
+ if( bUpdate && (bUI || !bAskUpdate) )
+ {
+ SfxMedium* pMedium = GetDocShell()->GetMedium();
+ SfxFrame* pFrm = pMedium ? pMedium->GetLoadTargetFrame() : 0;
+ Window* pDlgParent = pFrm ? &pFrm->GetWindow() : 0;
+ if( GetCurrentViewShell() && !GetEditShell( &pVSh ) && !pVSh ) //swmod 071108//swmod 071225
+ {
+ ViewShell aVSh( *this, 0, 0 );
+
+ SET_CURR_SHELL( &aVSh );
+ GetLinkManager().UpdateAllLinks( bAskUpdate , sal_True, sal_False, pDlgParent );
+ }
+ else
+ GetLinkManager().UpdateAllLinks( bAskUpdate, sal_True, sal_False, pDlgParent );
+ }
+ }
+
+}
+
+void SwDoc::SetApplyWorkaroundForB6375613( bool p_bApplyWorkaroundForB6375613 )
+{
+ if ( mbApplyWorkaroundForB6375613 != p_bApplyWorkaroundForB6375613 )
+ {
+ mbApplyWorkaroundForB6375613 = p_bApplyWorkaroundForB6375613;
+
+ uno::Reference< document::XDocumentInfoSupplier > xDoc(
+ GetDocShell()->GetBaseModel(),
+ uno::UNO_QUERY);
+ if ( xDoc.is() )
+ {
+ uno::Reference< beans::XPropertyContainer > xDocInfo(
+ xDoc->getDocumentInfo(),
+ uno::UNO_QUERY );
+ if ( xDocInfo.is() )
+ {
+ try
+ {
+ if ( mbApplyWorkaroundForB6375613 )
+ {
+ xDocInfo->addProperty(
+ rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("WorkaroundForB6375613Applied")),
+ beans::PropertyAttribute::TRANSIENT | beans::PropertyAttribute::REMOVABLE,
+ uno::makeAny( false ) );
+ }
+ else
+ {
+ xDocInfo->removeProperty( rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("WorkaroundForB6375613Applied")) );
+ }
+ }
+ catch( uno::Exception& )
+ {
+ }
+ }
+ }
+ }
+}
+
+::sfx2::IXmlIdRegistry&
+SwDoc::GetXmlIdRegistry()
+{
+ // UGLY: this relies on SetClipBoard being called before GetXmlIdRegistry!
+ if (!m_pXmlIdRegistry.get())
+ {
+ m_pXmlIdRegistry.reset( ::sfx2::createXmlIdRegistry( IsClipBoard() ) );
+ }
+ return *m_pXmlIdRegistry;
+}
+
+::sw::MetaFieldManager &
+SwDoc::GetMetaFieldManager()
+{
+ return *m_pMetaFieldManager;
+}
+
+::sw::UndoManager &
+SwDoc::GetUndoManager()
+{
+ return *m_pUndoManager;
+}
+
+::sw::UndoManager const&
+SwDoc::GetUndoManager() const
+{
+ return *m_pUndoManager;
+}
+
+IDocumentUndoRedo &
+SwDoc::GetIDocumentUndoRedo()
+{
+ return *m_pUndoManager;
+}
+
+IDocumentUndoRedo const&
+SwDoc::GetIDocumentUndoRedo() const
+{
+ return *m_pUndoManager;
+}
+
+void SwDoc::InitTOXTypes()
+{
+ ShellResource* pShellRes = ViewShell::GetShellRes();
+ SwTOXType * pNew = new SwTOXType(TOX_CONTENT, pShellRes->aTOXContentName );
+ pTOXTypes->Insert( pNew, pTOXTypes->Count() );
+ pNew = new SwTOXType(TOX_INDEX, pShellRes->aTOXIndexName );
+ pTOXTypes->Insert( pNew, pTOXTypes->Count() );
+ pNew = new SwTOXType(TOX_USER, pShellRes->aTOXUserName );
+ pTOXTypes->Insert( pNew, pTOXTypes->Count() );
+ pNew = new SwTOXType(TOX_ILLUSTRATIONS, pShellRes->aTOXIllustrationsName );
+ pTOXTypes->Insert( pNew, pTOXTypes->Count() );
+ pNew = new SwTOXType(TOX_OBJECTS, pShellRes->aTOXObjectsName );
+ pTOXTypes->Insert( pNew, pTOXTypes->Count() );
+ pNew = new SwTOXType(TOX_TABLES, pShellRes->aTOXTablesName );
+ pTOXTypes->Insert( pNew, pTOXTypes->Count() );
+ pNew = new SwTOXType(TOX_AUTHORITIES, pShellRes->aTOXAuthoritiesName );
+ pTOXTypes->Insert( pNew, pTOXTypes->Count() );
+}
+
+SfxObjectShell* SwDoc::CreateCopy(bool bCallInitNew ) const
+{
+ SwDoc* pRet = new SwDoc;
+ //copy settings
+ sal_uInt16 aRangeOfDefaults[] = {
+ RES_FRMATR_BEGIN, RES_FRMATR_END-1,
+ RES_CHRATR_BEGIN, RES_CHRATR_END-1,
+ RES_PARATR_BEGIN, RES_PARATR_END-1,
+ RES_PARATR_LIST_BEGIN, RES_PARATR_LIST_END-1,
+ RES_UNKNOWNATR_BEGIN, RES_UNKNOWNATR_END-1,
+ 0
+ };
+
+ SfxItemSet aNewDefaults( pRet->GetAttrPool(), aRangeOfDefaults );
+
+ sal_uInt16 nWhich;
+ sal_uInt16 nRange = 0;
+ while( aRangeOfDefaults[nRange] != 0)
+ {
+ for( nWhich = aRangeOfDefaults[nRange]; nWhich < aRangeOfDefaults[nRange + 1]; ++nWhich )
+ {
+ const SfxPoolItem& rSourceAttr = mpAttrPool->GetDefaultItem( nWhich );
+ if( rSourceAttr != pRet->mpAttrPool->GetDefaultItem( nWhich ) )
+ aNewDefaults.Put( rSourceAttr );
+ }
+ nRange += 2;
+ }
+ if( aNewDefaults.Count() )
+ pRet->SetDefault( aNewDefaults );
+
+ pRet->n32DummyCompatabilityOptions1 = n32DummyCompatabilityOptions1;
+ pRet->n32DummyCompatabilityOptions2 = n32DummyCompatabilityOptions2;
+ pRet->mbParaSpaceMax = mbParaSpaceMax ;
+ pRet->mbParaSpaceMaxAtPages = mbParaSpaceMaxAtPages ;
+ pRet->mbTabCompat = mbTabCompat ;
+ pRet->mbUseVirtualDevice = mbUseVirtualDevice ;
+ pRet->mbAddExternalLeading = mbAddExternalLeading ;
+ pRet->mbOldLineSpacing = mbOldLineSpacing ;
+ pRet->mbAddParaSpacingToTableCells = mbAddParaSpacingToTableCells ;
+ pRet->mbUseFormerObjectPos = mbUseFormerObjectPos ;
+ pRet->mbUseFormerTextWrapping = mbUseFormerTextWrapping ;
+ pRet->mbConsiderWrapOnObjPos = mbConsiderWrapOnObjPos ;
+ pRet->mbAddFlyOffsets = mbAddFlyOffsets ;
+ pRet->mbOldNumbering = mbOldNumbering ;
+ pRet->mbUseHiResolutionVirtualDevice = mbUseHiResolutionVirtualDevice ;
+ pRet->mbIgnoreFirstLineIndentInNumbering = mbIgnoreFirstLineIndentInNumbering ;
+ pRet->mbDoNotJustifyLinesWithManualBreak = mbDoNotJustifyLinesWithManualBreak ;
+ pRet->mbDoNotResetParaAttrsForNumFont = mbDoNotResetParaAttrsForNumFont ;
+ pRet->mbOutlineLevelYieldsOutlineRule = mbOutlineLevelYieldsOutlineRule ;
+ pRet->mbTableRowKeep = mbTableRowKeep ;
+ pRet->mbIgnoreTabsAndBlanksForLineCalculation = mbIgnoreTabsAndBlanksForLineCalculation ;
+ pRet->mbDoNotCaptureDrawObjsOnPage = mbDoNotCaptureDrawObjsOnPage ;
+ pRet->mbClipAsCharacterAnchoredWriterFlyFrames= mbClipAsCharacterAnchoredWriterFlyFrames;
+ pRet->mbUnixForceZeroExtLeading = mbUnixForceZeroExtLeading ;
+ pRet->mbOldPrinterMetrics = mbOldPrinterMetrics ;
+ pRet->mbTabRelativeToIndent = mbTabRelativeToIndent ;
+ pRet->mbTabAtLeftIndentForParagraphsInList = mbTabAtLeftIndentForParagraphsInList ;
+
+ //
+ // COMPATIBILITY FLAGS END
+ //
+ pRet->ReplaceStyles( * const_cast< SwDoc*>( this ));
+
+ // we have to use pointer here, since the callee has to decide whether SfxObjectShellLock or SfxObjectShellRef should be used
+ // sometimes the object will be returned with refcount set to 0 ( if no DoInitNew is done )
+ SfxObjectShell* pRetShell = new SwDocShell( pRet, SFX_CREATE_MODE_STANDARD );
+ if( bCallInitNew )
+ {
+ // it could happen that DoInitNew creates model, that increases the refcount of the object
+ pRetShell->DoInitNew();
+ }
+
+ //copy content
+ pRet->Paste( *this );
+
+ // remove the temporary shell if it is there as it was done before
+ pRet->SetTmpDocShell( (SfxObjectShell*)NULL );
+
+ return pRetShell;
+}
+
+/*-------------------------------------------------------------------------
+ copy document content - code from SwFEShell::Paste( SwDoc* , sal_Bool )
+ -----------------------------------------------------------------------*/
+void SwDoc::Paste( const SwDoc& rSource )
+{
+// this has to be empty const sal_uInt16 nStartPageNumber = GetPhyPageNum();
+ // until the end of the NodesArray
+ SwNodeIndex aSourceIdx( rSource.GetNodes().GetEndOfExtras(), 2 );
+ SwPaM aCpyPam( aSourceIdx ); //DocStart
+ SwNodeIndex aTargetIdx( GetNodes().GetEndOfExtras(), 2 );
+ SwPaM aInsertPam( aTargetIdx ); //replaces PCURCRSR from SwFEShell::Paste()
+
+
+ aCpyPam.SetMark();
+ aCpyPam.Move( fnMoveForward, fnGoDoc );
+
+ this->GetIDocumentUndoRedo().StartUndo( UNDO_INSGLOSSARY, NULL );
+ this->LockExpFlds();
+
+ {
+ SwPosition& rInsPos = *aInsertPam.GetPoint();
+ //find out if the clipboard document starts with a table
+ bool bStartWithTable = 0 != aCpyPam.Start()->nNode.GetNode().FindTableNode();
+ SwPosition aInsertPosition( rInsPos );
+
+ {
+ SwNodeIndex aIndexBefore(rInsPos.nNode);
+
+ aIndexBefore--;
+
+ rSource.CopyRange( aCpyPam, rInsPos, true );
+
+ {
+ aIndexBefore++;
+ SwPaM aPaM(SwPosition(aIndexBefore),
+ SwPosition(rInsPos.nNode));
+
+ MakeUniqueNumRules(aPaM);
+ }
+ }
+
+ //TODO: Is this necessary here? SaveTblBoxCntnt( &rInsPos );
+ if(/*bIncludingPageFrames && */bStartWithTable)
+ {
+ //remove the paragraph in front of the table
+ SwPaM aPara(aInsertPosition);
+ this->DelFullPara(aPara);
+ }
+ //additionally copy page bound frames
+ if( /*bIncludingPageFrames && */rSource.GetSpzFrmFmts()->Count() )
+ {
+ for ( sal_uInt16 i = 0; i < rSource.GetSpzFrmFmts()->Count(); ++i )
+ {
+ sal_Bool bInsWithFmt = sal_True;
+ const SwFrmFmt& rCpyFmt = *(*rSource.GetSpzFrmFmts())[i];
+ if( bInsWithFmt )
+ {
+ SwFmtAnchor aAnchor( rCpyFmt.GetAnchor() );
+ if (FLY_AT_PAGE == aAnchor.GetAnchorId())
+ {
+ aAnchor.SetPageNum( aAnchor.GetPageNum() /*+ nStartPageNumber - */);
+ }
+ else
+ continue;
+ this->CopyLayoutFmt( rCpyFmt, aAnchor, true, true );
+ }
+ }
+ }
+ }
+
+ this->GetIDocumentUndoRedo().EndUndo( UNDO_INSGLOSSARY, NULL );
+
+ UnlockExpFlds();
+ UpdateFlds(NULL, false);
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/doc/docnum.cxx b/sw/source/core/doc/docnum.cxx
new file mode 100644
index 000000000000..b184b636162b
--- /dev/null
+++ b/sw/source/core/doc/docnum.cxx
@@ -0,0 +1,2640 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+#include <hintids.hxx>
+#include <tools/date.hxx>
+#include <tools/time.hxx>
+#include <tools/resid.hxx>
+#include <editeng/lrspitem.hxx>
+#include <ftninfo.hxx>
+#include <ftnidx.hxx>
+#include <doc.hxx>
+#include <IDocumentUndoRedo.hxx>
+#include <pam.hxx>
+#include <ndtxt.hxx>
+#include <doctxm.hxx> // pTOXBaseRing
+#include <poolfmt.hxx>
+#include <UndoCore.hxx>
+#include <UndoRedline.hxx>
+#include <UndoNumbering.hxx>
+#include <swundo.hxx>
+#include <SwUndoFmt.hxx>
+#include <rolbck.hxx>
+#include <paratr.hxx>
+#include <docary.hxx>
+#include <mvsave.hxx>
+#include <txtfrm.hxx>
+#include <pamtyp.hxx>
+#include <redline.hxx>
+#include <comcore.hrc>
+#include <editeng/adjitem.hxx>
+#include <editeng/frmdiritem.hxx>
+#include <frmatr.hxx>
+#include <SwStyleNameMapper.hxx>
+#include <SwNodeNum.hxx>
+#include <list.hxx>
+#include <listfunc.hxx>
+#include <switerator.hxx>
+
+#include <map>
+
+inline sal_uInt8 GetUpperLvlChg( sal_uInt8 nCurLvl, sal_uInt8 nLevel, sal_uInt16 nMask )
+{
+ if( 1 < nLevel )
+ {
+ if( nCurLvl + 1 >= nLevel )
+ nCurLvl -= nLevel - 1;
+ else
+ nCurLvl = 0;
+ }
+ return static_cast<sal_uInt8>((nMask - 1) & ~(( 1 << nCurLvl ) - 1));
+}
+
+void SwDoc::SetOutlineNumRule( const SwNumRule& rRule )
+{
+ if( pOutlineRule )
+ (*pOutlineRule) = rRule;
+ else
+ {
+ pOutlineRule = new SwNumRule( rRule );
+
+ AddNumRule(pOutlineRule); // #i36749#
+ }
+
+ pOutlineRule->SetRuleType( OUTLINE_RULE );
+ pOutlineRule->SetName( String::CreateFromAscii(
+ SwNumRule::GetOutlineRuleName() ),
+ *this);
+
+ // assure that the outline numbering rule is an automatic rule
+ pOutlineRule->SetAutoRule( sal_True );
+
+ // teste ob die evt. gesetzen CharFormate in diesem Document
+ // definiert sind
+ pOutlineRule->CheckCharFmts( this );
+
+ // notify text nodes, which are registered at the outline style, about the
+ // changed outline style
+ SwNumRule::tTxtNodeList aTxtNodeList;
+ pOutlineRule->GetTxtNodeList( aTxtNodeList );
+ for ( SwNumRule::tTxtNodeList::iterator aIter = aTxtNodeList.begin();
+ aIter != aTxtNodeList.end(); ++aIter )
+ {
+ SwTxtNode* pTxtNd = *aIter;
+ pTxtNd->NumRuleChgd();
+
+ // assure that list level corresponds to outline level
+ if ( pTxtNd->GetTxtColl()->IsAssignedToListLevelOfOutlineStyle() &&
+ pTxtNd->GetAttrListLevel() != pTxtNd->GetTxtColl()->GetAssignedOutlineStyleLevel() )
+ {
+ pTxtNd->SetAttrListLevel( pTxtNd->GetTxtColl()->GetAssignedOutlineStyleLevel() );
+ }
+ }
+
+ PropagateOutlineRule();
+ pOutlineRule->SetInvalidRule(sal_True);
+ UpdateNumRule();
+
+ // gibt es Fussnoten && gilt Kapitelweises Nummerieren, dann updaten
+ if( GetFtnIdxs().Count() && FTNNUM_CHAPTER == GetFtnInfo().eNum )
+ GetFtnIdxs().UpdateAllFtn();
+
+ UpdateExpFlds(NULL, true);
+
+ SetModified();
+}
+
+void SwDoc::PropagateOutlineRule()
+{
+ for (sal_uInt16 n = 0; n < pTxtFmtCollTbl->Count(); n++)
+ {
+ SwTxtFmtColl *pColl = (*pTxtFmtCollTbl)[n];
+
+ if(pColl->IsAssignedToListLevelOfOutlineStyle())//<-end,zhaojianwei
+ {
+ // Check only the list style, which is set at the paragraph style
+ const SwNumRuleItem & rCollRuleItem = pColl->GetNumRule( sal_False );
+
+ // Check on document setting OUTLINE_LEVEL_YIELDS_OUTLINE_RULE no longer needed.
+ if ( rCollRuleItem.GetValue().Len() == 0 )
+ {
+ SwNumRule * pMyOutlineRule = GetOutlineNumRule();
+
+ if (pMyOutlineRule)
+ {
+ SwNumRuleItem aNumItem( pMyOutlineRule->GetName() );
+
+ pColl->SetFmtAttr(aNumItem);
+ }
+ }
+ }
+ }
+}
+
+// Hoch-/Runterstufen
+sal_Bool SwDoc::OutlineUpDown( const SwPaM& rPam, short nOffset )
+{
+ if( !GetNodes().GetOutLineNds().Count() || !nOffset )
+ return sal_False;
+
+ // den Bereich feststellen
+ const SwOutlineNodes& rOutlNds = GetNodes().GetOutLineNds();
+ const SwNodePtr pSttNd = (SwNodePtr)&rPam.Start()->nNode.GetNode();
+ const SwNodePtr pEndNd = (SwNodePtr)&rPam.End()->nNode.GetNode();
+ sal_uInt16 nSttPos, nEndPos;
+
+ if( !rOutlNds.Seek_Entry( pSttNd, &nSttPos ) &&
+ !nSttPos-- )
+ // wir stehen in keiner "Outline-Section"
+ return sal_False;
+
+ if( rOutlNds.Seek_Entry( pEndNd, &nEndPos ) )
+ ++nEndPos;
+
+ // jetzt haben wir unseren Bereich im OutlineNodes-Array
+ // dann prufe ersmal, ob nicht unterebenen aufgehoben werden
+ // (Stufung ueber die Grenzen)
+ sal_uInt16 n;
+
+ // so, dann koennen wir:
+ // 1. Vorlagen-Array anlegen
+ SwTxtFmtColl* aCollArr[ MAXLEVEL ];
+ memset( aCollArr, 0, sizeof( SwTxtFmtColl* ) * MAXLEVEL );
+
+ for( n = 0; n < pTxtFmtCollTbl->Count(); ++n )
+ {
+ if((*pTxtFmtCollTbl)[ n ]->IsAssignedToListLevelOfOutlineStyle())
+ {
+ const int nLevel = (*pTxtFmtCollTbl)[ n ]->GetAssignedOutlineStyleLevel();
+ aCollArr[ nLevel ] = (*pTxtFmtCollTbl)[ n ];
+ }//<-end,zhaojianwei
+ }
+
+ /* Find the last occupied level (backward). */
+ for (n = MAXLEVEL - 1; n > 0; n--)
+ {
+ if (aCollArr[n] != 0)
+ break;
+ }
+
+ /* If an occupied level is found, choose next level (which IS
+ unoccupied) until a valid level is found. If no occupied level
+ was found n is 0 and aCollArr[0] is 0. In this case no demoting
+ is possible. */
+ if (aCollArr[n] != 0)
+ {
+ while (n < MAXLEVEL - 1)
+ {
+ n++;
+
+ SwTxtFmtColl *aTmpColl =
+ GetTxtCollFromPool(static_cast<sal_uInt16>(RES_POOLCOLL_HEADLINE1 + n));
+
+ if( aTmpColl->IsAssignedToListLevelOfOutlineStyle() &&
+ aTmpColl->GetAssignedOutlineStyleLevel() == n )//<-end,zhaojianwei
+ {
+ aCollArr[n] = aTmpColl;
+ break;
+ }
+ }
+ }
+
+ /* Find the first occupied level (forward). */
+ for (n = 0; n < MAXLEVEL - 1; n++)
+ {
+ if (aCollArr[n] != 0)
+ break;
+ }
+
+ /* If an occupied level is found, choose previous level (which IS
+ unoccupied) until a valid level is found. If no occupied level
+ was found n is MAXLEVEL - 1 and aCollArr[MAXLEVEL - 1] is 0. In
+ this case no demoting is possible. */
+ if (aCollArr[n] != 0)
+ {
+ while (n > 0)
+ {
+ n--;
+
+ SwTxtFmtColl *aTmpColl =
+ GetTxtCollFromPool(static_cast<sal_uInt16>(RES_POOLCOLL_HEADLINE1 + n));
+
+ //if (aTmpColl->GetOutlineLevel() == n)//#outline level,zhaojianwei
+ if( aTmpColl->IsAssignedToListLevelOfOutlineStyle() &&
+ aTmpColl->GetAssignedOutlineStyleLevel() == n )//<-end,zhaojianwei
+ {
+ aCollArr[n] = aTmpColl;
+ break;
+ }
+ }
+ }
+
+ /* --> #i13747#
+
+ Build a move table that states from which level an outline will
+
+ be moved to which other level. */
+
+ /* the move table
+
+ aMoveArr[n] = m: replace aCollArr[n] with aCollArr[m]
+ */
+ int aMoveArr[MAXLEVEL];
+ int nStep; // step size for searching in aCollArr: -1 or 1
+ int nNum; // amount of steps for stepping in aCollArr
+
+ if (nOffset < 0)
+ {
+ nStep = -1;
+ nNum = -nOffset;
+ }
+ else
+ {
+ nStep = 1;
+ nNum = nOffset;
+ }
+
+ /* traverse aCollArr */
+ for (n = 0; n < MAXLEVEL; n++)
+ {
+ /* If outline level n has an assigned paragraph style step
+ nNum steps forwards (nStep == 1) or backwards (nStep ==
+ -1). One step is to go to the next non-null entry in
+ aCollArr in the selected direction. If nNum steps were
+ possible write the index of the entry found to aCollArr[n],
+ i.e. outline level n will be replaced by outline level
+ aCollArr[n].
+
+ If outline level n has no assigned paragraph style
+ aMoveArr[n] is set to -1.
+ */
+ if (aCollArr[n] != NULL)
+ {
+ sal_uInt16 m = n;
+ int nCount = nNum;
+
+ while (nCount > 0 && m + nStep >= 0 && m + nStep < MAXLEVEL)
+ {
+ m = static_cast<sal_uInt16>(m + nStep);
+
+ if (aCollArr[m] != NULL)
+ nCount--;
+ }
+
+ if (nCount == 0)
+ aMoveArr[n] = m;
+ else
+ aMoveArr[n] = -1;
+
+ }
+ else
+ aMoveArr[n] = -1;
+ }
+
+ /* If moving of the outline levels is applicable, i.e. for all
+ outline levels occuring in the document there has to be a valid
+ target outline level implied by aMoveArr. */
+ bool bMoveApplicable = true;
+ for (n = nSttPos; n < nEndPos; n++)
+ {
+ SwTxtNode* pTxtNd = rOutlNds[ n ]->GetTxtNode();
+ SwTxtFmtColl* pColl = pTxtNd->GetTxtColl();
+
+ if( pColl->IsAssignedToListLevelOfOutlineStyle() )
+ {
+ const int nLevel = pColl->GetAssignedOutlineStyleLevel();
+ if (aMoveArr[nLevel] == -1)
+ bMoveApplicable = false;
+ }//<-end,zhaojianwei
+
+ // Check on outline level attribute of text node, if text node is
+ // not an outline via a to outline style assigned paragraph style.
+ else
+ {
+ const int nNewOutlineLevel = pTxtNd->GetAttrOutlineLevel() + nOffset;
+ if ( nNewOutlineLevel < 1 || nNewOutlineLevel > MAXLEVEL )
+ {
+ bMoveApplicable = false;
+ }
+ }
+ }
+
+ if (! bMoveApplicable )
+ return sal_False;
+
+ if (GetIDocumentUndoRedo().DoesUndo())
+ {
+ GetIDocumentUndoRedo().StartUndo(UNDO_OUTLINE_LR, NULL);
+ SwUndo *const pUndoOLR( new SwUndoOutlineLeftRight( rPam, nOffset ) );
+ GetIDocumentUndoRedo().AppendUndo(pUndoOLR);
+ }
+
+ // 2. allen Nodes die neue Vorlage zuweisen
+
+ n = nSttPos;
+ while( n < nEndPos)
+ {
+ SwTxtNode* pTxtNd = rOutlNds[ n ]->GetTxtNode();
+ SwTxtFmtColl* pColl = pTxtNd->GetTxtColl();
+
+ if( pColl->IsAssignedToListLevelOfOutlineStyle() )
+ {
+ const int nLevel = pColl->GetAssignedOutlineStyleLevel();//#outline level,add by zhaojianwei
+
+ OSL_ENSURE(aMoveArr[nLevel] >= 0,
+ "move table: current TxtColl not found when building table!");
+
+
+ if (nLevel < MAXLEVEL && aMoveArr[nLevel] >= 0)
+ {
+ pColl = aCollArr[ aMoveArr[nLevel] ];
+
+ if (pColl != NULL)
+ pColl = (SwTxtFmtColl*)pTxtNd->ChgFmtColl( pColl );
+ }
+
+ }
+ else if( pTxtNd->GetAttrOutlineLevel() > 0) //#outline level,add by zhaojianwei
+ {
+ int nLevel = pTxtNd->GetAttrOutlineLevel() + nOffset;
+ if( 0 <= nLevel && nLevel <= MAXLEVEL)
+ pTxtNd->SetAttrOutlineLevel( nLevel );
+
+ }//<-end,zhaojianwei
+
+ n++;
+ // Undo ???
+ }
+ if (GetIDocumentUndoRedo().DoesUndo())
+ {
+ GetIDocumentUndoRedo().EndUndo(UNDO_OUTLINE_LR, NULL);
+ }
+
+ ChkCondColls();
+ SetModified();
+
+ return sal_True;
+}
+
+// Hoch-/Runter - Verschieben !
+sal_Bool SwDoc::MoveOutlinePara( const SwPaM& rPam, short nOffset )
+{
+ // kein Verschiebung in den Sonderbereichen
+ const SwPosition& rStt = *rPam.Start(),
+ & rEnd = &rStt == rPam.GetPoint() ? *rPam.GetMark()
+ : *rPam.GetPoint();
+ if( !GetNodes().GetOutLineNds().Count() || !nOffset ||
+ (rStt.nNode.GetIndex() < GetNodes().GetEndOfExtras().GetIndex()) ||
+ (rEnd.nNode.GetIndex() < GetNodes().GetEndOfExtras().GetIndex()))
+ {
+ return sal_False;
+ }
+
+ sal_uInt16 nAktPos = 0;
+ SwNodeIndex aSttRg( rStt.nNode ), aEndRg( rEnd.nNode );
+
+ int nOutLineLevel = MAXLEVEL; //<-end,zhaojianwei
+ SwNode* pSrch = &aSttRg.GetNode();
+
+ if( pSrch->IsTxtNode())
+ nOutLineLevel = static_cast<sal_uInt8>(((SwTxtNode*)pSrch)->GetAttrOutlineLevel()-1);//<-end,zhaojianwei
+ SwNode* pEndSrch = &aEndRg.GetNode();
+ if( !GetNodes().GetOutLineNds().Seek_Entry( pSrch, &nAktPos ) )
+ {
+ if( !nAktPos )
+ return sal_False; // Promoting or demoting before the first outline => no.
+ if( --nAktPos )
+ aSttRg = *GetNodes().GetOutLineNds()[ nAktPos ];
+ else if( 0 > nOffset )
+ return sal_False; // Promoting at the top of document?!
+ else
+ aSttRg = *GetNodes().GetEndOfContent().StartOfSectionNode();
+ }
+ sal_uInt16 nTmpPos = 0;
+ // If the given range ends at an outlined text node we have to decide if it has to be a part of
+ // the moving range or not. Normally it will be a sub outline of our chapter
+ // and has to be moved, too. But if the chapter ends with a table(or a section end),
+ // the next text node will be choosen and this could be the next outline of the same level.
+ // The criteria has to be the outline level: sub level => incorporate, same/higher level => no.
+ if( GetNodes().GetOutLineNds().Seek_Entry( pEndSrch, &nTmpPos ) )
+ {
+ if( !pEndSrch->IsTxtNode() || pEndSrch == pSrch ||
+ nOutLineLevel < ((SwTxtNode*)pEndSrch)->GetAttrOutlineLevel()-1 )//<-end,zhaojianwei
+ ++nTmpPos; // For sub outlines only!
+ }
+
+ aEndRg = nTmpPos < GetNodes().GetOutLineNds().Count()
+ ? *GetNodes().GetOutLineNds()[ nTmpPos ]
+ : GetNodes().GetEndOfContent();
+ if( nOffset >= 0 )
+ nAktPos = nTmpPos;
+ if( aEndRg == aSttRg )
+ {
+ OSL_FAIL( "Moving outlines: Surprising selection" );
+ aEndRg++;
+ }
+
+ const SwNode* pNd;
+ // The following code corrects the range to handle sections (start/end nodes)
+ // The range will be extended if the least node before the range is a start node
+ // which ends inside the range => The complete section will be moved.
+ // The range will be shrinked if the last position is a start node.
+ // The range will be shrinked if the last node is an end node which starts before the range.
+ aSttRg--;
+ while( aSttRg.GetNode().IsStartNode() )
+ {
+ pNd = aSttRg.GetNode().EndOfSectionNode();
+ if( pNd->GetIndex() >= aEndRg.GetIndex() )
+ break;
+ aSttRg--;
+ }
+ aSttRg++;
+
+ aEndRg--;
+ while( aEndRg.GetNode().IsStartNode() )
+ aEndRg--;
+ while( aEndRg.GetNode().IsEndNode() )
+ {
+ pNd = aEndRg.GetNode().StartOfSectionNode();
+ if( pNd->GetIndex() >= aSttRg.GetIndex() )
+ break;
+ aEndRg--;
+ }
+ aEndRg++;
+
+ // calculation of the new position
+ if( nOffset < 0 && nAktPos < sal_uInt16(-nOffset) )
+ pNd = GetNodes().GetEndOfContent().StartOfSectionNode();
+ else if( nAktPos + nOffset >= GetNodes().GetOutLineNds().Count() )
+ pNd = &GetNodes().GetEndOfContent();
+ else
+ pNd = GetNodes().GetOutLineNds()[ nAktPos + nOffset ];
+
+ sal_uLong nNewPos = pNd->GetIndex();
+
+ // And now a correction of the insert position if necessary...
+ SwNodeIndex aInsertPos( *pNd, -1 );
+ while( aInsertPos.GetNode().IsStartNode() )
+ {
+ // Just before the insert position starts a section:
+ // when I'm moving forward I do not want to enter the section,
+ // when I'm moving backward I want to stay in the section if I'm already a part of,
+ // I want to stay outside if I was outside before.
+ if( nOffset < 0 )
+ {
+ pNd = aInsertPos.GetNode().EndOfSectionNode();
+ if( pNd->GetIndex() >= aEndRg.GetIndex() )
+ break;
+ }
+ aInsertPos--;
+ --nNewPos;
+ }
+ if( nOffset >= 0 )
+ {
+ // When just before the insert position a section ends, it is okay when I'm moving backward
+ // because I want to stay outside the section.
+ // When moving forward I've to check if I started inside or outside the section
+ // because I don't want to enter of leave such a section
+ while( aInsertPos.GetNode().IsEndNode() )
+ {
+ pNd = aInsertPos.GetNode().StartOfSectionNode();
+ if( pNd->GetIndex() >= aSttRg.GetIndex() )
+ break;
+ aInsertPos--;
+ --nNewPos;
+ }
+ }
+ // We do not want to move into tables (at the moment)
+ aInsertPos++;
+ pNd = &aInsertPos.GetNode();
+ if( pNd->IsTableNode() )
+ pNd = pNd->StartOfSectionNode();
+ if( pNd->FindTableNode() )
+ return sal_False;
+
+ OSL_ENSURE( aSttRg.GetIndex() > nNewPos || nNewPos >= aEndRg.GetIndex(),
+ "Position liegt im MoveBereich" );
+
+ // wurde ein Position in den Sonderbereichen errechnet, dann
+ // setze die Position auf den Dokumentanfang.
+ // Sollten da Bereiche oder Tabellen stehen, so werden sie nach
+ // hinten verschoben.
+ nNewPos = Max( nNewPos, GetNodes().GetEndOfExtras().GetIndex() + 2 );
+
+ long nOffs = nNewPos - ( 0 < nOffset ? aEndRg.GetIndex() : aSttRg.GetIndex());
+ SwPaM aPam( aSttRg, aEndRg, 0, -1 );
+ return MoveParagraph( aPam, nOffs, sal_True );
+}
+
+sal_uInt16 lcl_FindOutlineName( const SwNodes& rNds, const String& rName,
+ sal_Bool bExact )
+{
+ sal_uInt16 nSavePos = USHRT_MAX;
+ const SwOutlineNodes& rOutlNds = rNds.GetOutLineNds();
+ for( sal_uInt16 n = 0; n < rOutlNds.Count(); ++n )
+ {
+ SwTxtNode* pTxtNd = rOutlNds[ n ]->GetTxtNode();
+ String sTxt( pTxtNd->GetExpandTxt() );
+ if( sTxt.Equals( rName ) )
+ {
+ // "exact" gefunden, setze Pos auf den Node
+ nSavePos = n;
+ break;
+ }
+ else if( !bExact && USHRT_MAX == nSavePos &&
+ COMPARE_EQUAL == sTxt.CompareTo( rName, rName.Len()) )
+ {
+ // dann vielleicht nur den den 1.Teil vom Text gefunden
+ nSavePos = n;
+ }
+ }
+
+ return nSavePos;
+}
+
+sal_uInt16 lcl_FindOutlineNum( const SwNodes& rNds, String& rName )
+{
+ // Gueltig Nummern sind (immer nur Offsets!!!):
+ // ([Nummer]+\.)+ (als regulaerer Ausdruck!)
+ // (Nummer gefolgt von Punkt, zum 5 Wiederholungen)
+ // also: "1.1.", "1.", "1.1.1."
+ xub_StrLen nPos = 0;
+ String sNum = rName.GetToken( 0, '.', nPos );
+ if( STRING_NOTFOUND == nPos )
+ return USHRT_MAX; // ungueltige Nummer!!!
+
+ sal_uInt16 nLevelVal[ MAXLEVEL ]; // Nummern aller Levels
+ memset( nLevelVal, 0, MAXLEVEL * sizeof( nLevelVal[0] ));
+ sal_uInt8 nLevel = 0;
+ String sName( rName );
+
+ while( STRING_NOTFOUND != nPos )
+ {
+ sal_uInt16 nVal = 0;
+ sal_Unicode c;
+ for( sal_uInt16 n = 0; n < sNum.Len(); ++n )
+ if( '0' <= ( c = sNum.GetChar( n )) && c <= '9' )
+ {
+ nVal *= 10; nVal += c - '0';
+ }
+ else if( nLevel )
+ break; // "fast" gueltige Nummer
+ else
+ return USHRT_MAX; // ungueltige Nummer!!!
+
+ if( MAXLEVEL > nLevel )
+ nLevelVal[ nLevel++ ] = nVal;
+
+ sName.Erase( 0, nPos );
+ nPos = 0;
+ sNum = sName.GetToken( 0, '.', nPos );
+ // #i4533# without this check all parts delimited by a dot are treated as outline numbers
+ if(!ByteString(sNum, gsl_getSystemTextEncoding()).IsNumericAscii())
+ nPos = STRING_NOTFOUND;
+ }
+ rName = sName; // das ist der nachfolgende Text.
+
+ // alle Levels gelesen, dann suche mal im Document nach dieser
+ // Gliederung:
+ const SwOutlineNodes& rOutlNds = rNds.GetOutLineNds();
+ // OS: ohne OutlineNodes lohnt die Suche nicht
+ // und man spart sich einen Absturz
+ if(!rOutlNds.Count())
+ return USHRT_MAX;
+ SwTxtNode* pNd;
+ nPos = 0;
+ //search in the existing outline nodes for the required outline num array
+ for( ; nPos < rOutlNds.Count(); ++nPos )
+ {
+ pNd = rOutlNds[ nPos ]->GetTxtNode();
+ const int nLvl = pNd->GetAttrOutlineLevel()-1; //<-end,zhaojianwei
+ if( nLvl == nLevel - 1)
+ {
+ // #i51089#, #i68289#
+ // Assure, that text node has the correct numbering level. Otherwise,
+ // its number vector will not fit to the searched level.
+ if ( pNd->GetNum() &&
+ pNd->GetActualListLevel() == ( nLevel - 1 ) )
+ // <--
+ {
+ const SwNodeNum & rNdNum = *(pNd->GetNum());
+ SwNumberTree::tNumberVector aLevelVal = rNdNum.GetNumberVector();
+ //now compare with the one searched for
+ bool bEqual = true;
+ for( sal_uInt8 n = 0; (n < nLevel) && bEqual; ++n )
+ {
+ bEqual = aLevelVal[n] == nLevelVal[n];
+ }
+ if(bEqual)
+ {
+ break;
+ }
+ }
+ else
+ {
+ // A text node, which has an outline paragraph style applied and
+ // has as hard attribute 'no numbering' set, has an outline level,
+ // but no numbering tree node. Thus, consider this situation in
+ // the assertion condition.
+ OSL_ENSURE( !pNd->GetNumRule(),
+ "<lcl_FindOutlineNum(..)> - text node with outline level and numbering rule, but without numbering tree node. This is a serious defect -> inform OD" );
+ }
+ }
+ }
+ if( nPos >= rOutlNds.Count() )
+ nPos = USHRT_MAX;
+ return nPos;
+}
+
+// zu diesem Gliederungspunkt
+
+// JP 13.06.96:
+// im Namen kann eine Nummer oder/und der Text stehen.
+// zuerst wird ueber die Nummer versucht den richtigen Eintrag zu finden.
+// Gibt es diesen, dann wird ueber den Text verglichen, od es der
+// gewuenschte ist. Ist das nicht der Fall, wird noch mal nur ueber den
+// Text gesucht. Wird dieser gefunden ist es der Eintrag. Ansonsten der,
+// der ueber die Nummer gefunden wurde.
+// Ist keine Nummer angegeben, dann nur den Text suchen.
+sal_Bool SwDoc::GotoOutline( SwPosition& rPos, const String& rName ) const
+{
+ if( rName.Len() )
+ {
+ const SwOutlineNodes& rOutlNds = GetNodes().GetOutLineNds();
+
+ // 1. Schritt: ueber die Nummer:
+ String sName( rName );
+ sal_uInt16 nFndPos = ::lcl_FindOutlineNum( GetNodes(), sName );
+ if( USHRT_MAX != nFndPos )
+ {
+ SwTxtNode* pNd = rOutlNds[ nFndPos ]->GetTxtNode();
+ String sExpandedText = pNd->GetExpandTxt();
+ //#i4533# leading numbers followed by a dot have been remove while
+ //searching for the outline position
+ //to compensate this they must be removed from the paragraphs text content, too
+ sal_uInt16 nPos = 0;
+ String sTempNum;
+ while(sExpandedText.Len() && (sTempNum = sExpandedText.GetToken(0, '.', nPos)).Len() &&
+ STRING_NOTFOUND != nPos &&
+ ByteString(sTempNum, gsl_getSystemTextEncoding()).IsNumericAscii())
+ {
+ sExpandedText.Erase(0, nPos);
+ nPos = 0;
+ }
+
+ if( !sExpandedText.Equals( sName ) )
+ {
+ sal_uInt16 nTmp = ::lcl_FindOutlineName( GetNodes(), sName, sal_True );
+ if( USHRT_MAX != nTmp ) // ueber den Namen gefunden
+ {
+ nFndPos = nTmp;
+ pNd = rOutlNds[ nFndPos ]->GetTxtNode();
+ }
+ }
+ rPos.nNode = *pNd;
+ rPos.nContent.Assign( pNd, 0 );
+ return sal_True;
+ }
+
+ nFndPos = ::lcl_FindOutlineName( GetNodes(), rName, sal_False );
+ if( USHRT_MAX != nFndPos )
+ {
+ SwTxtNode* pNd = rOutlNds[ nFndPos ]->GetTxtNode();
+ rPos.nNode = *pNd;
+ rPos.nContent.Assign( pNd, 0 );
+ return sal_True;
+ }
+
+ // #i68289# additional search on hyperlink URL without its outline numbering part
+ if ( !sName.Equals( rName ) )
+ {
+ nFndPos = ::lcl_FindOutlineName( GetNodes(), sName, sal_False );
+ if( USHRT_MAX != nFndPos )
+ {
+ SwTxtNode* pNd = rOutlNds[ nFndPos ]->GetTxtNode();
+ rPos.nNode = *pNd;
+ rPos.nContent.Assign( pNd, 0 );
+ return sal_True;
+ }
+ }
+ }
+ return sal_False;
+}
+
+void lcl_ChgNumRule( SwDoc& rDoc, const SwNumRule& rRule )
+{
+ SwNumRule* pOld = rDoc.FindNumRulePtr( rRule.GetName() );
+ OSL_ENSURE( pOld, "ohne die alte NumRule geht gar nichts" );
+
+ sal_uInt16 nChgFmtLevel = 0, nMask = 1;
+ sal_uInt8 n;
+
+ for( n = 0; n < MAXLEVEL; ++n, nMask <<= 1 )
+ {
+ const SwNumFmt& rOldFmt = pOld->Get( n ),
+ & rNewFmt = rRule.Get( n );
+
+ if( rOldFmt != rNewFmt )
+ {
+ nChgFmtLevel |= nMask;
+ }
+ else if( SVX_NUM_NUMBER_NONE > rNewFmt.GetNumberingType() && 1 < rNewFmt.GetIncludeUpperLevels() &&
+ 0 != (nChgFmtLevel & GetUpperLvlChg( n, rNewFmt.GetIncludeUpperLevels(),nMask )) )
+ nChgFmtLevel |= nMask;
+ }
+
+ if( !nChgFmtLevel ) // es wurde nichts veraendert?
+ {
+ const bool bInvalidateNumRule( pOld->IsContinusNum() != rRule.IsContinusNum() );
+ pOld->CheckCharFmts( &rDoc );
+ pOld->SetContinusNum( rRule.IsContinusNum() );
+
+ if ( bInvalidateNumRule )
+ {
+ pOld->SetInvalidRule(sal_True);
+ }
+
+ return ;
+ }
+
+ SwNumRule::tTxtNodeList aTxtNodeList;
+ pOld->GetTxtNodeList( aTxtNodeList );
+ sal_uInt8 nLvl( 0 );
+ for ( SwNumRule::tTxtNodeList::iterator aIter = aTxtNodeList.begin();
+ aIter != aTxtNodeList.end(); ++aIter )
+ {
+ SwTxtNode* pTxtNd = *aIter;
+ nLvl = static_cast<sal_uInt8>(pTxtNd->GetActualListLevel());
+
+ if( nLvl < MAXLEVEL )
+ {
+ if( nChgFmtLevel & ( 1 << nLvl ))
+ {
+ pTxtNd->NumRuleChgd();
+ }
+ }
+ }
+
+ for( n = 0; n < MAXLEVEL; ++n )
+ if( nChgFmtLevel & ( 1 << n ))
+ pOld->Set( n, rRule.GetNumFmt( n ));
+
+ pOld->CheckCharFmts( &rDoc );
+ pOld->SetInvalidRule(sal_True);
+ pOld->SetContinusNum( rRule.IsContinusNum() );
+
+ rDoc.UpdateNumRule();
+}
+
+void SwDoc::SetNumRule( const SwPaM& rPam,
+ const SwNumRule& rRule,
+ const bool bCreateNewList,
+ const String sContinuedListId,
+ sal_Bool bSetItem,
+ const bool bResetIndentAttrs )
+{
+ SwUndoInsNum * pUndo = NULL;
+ if (GetIDocumentUndoRedo().DoesUndo())
+ {
+ // Start/End for attributes!
+ GetIDocumentUndoRedo().StartUndo( UNDO_INSNUM, NULL );
+ pUndo = new SwUndoInsNum( rPam, rRule );
+ GetIDocumentUndoRedo().AppendUndo(pUndo);
+ }
+
+ SwNumRule * pNew = FindNumRulePtr( rRule.GetName() );
+ bool bUpdateRule = false;
+
+ if( !pNew )
+ {
+ pNew = (*pNumRuleTbl)[ MakeNumRule( rRule.GetName(), &rRule ) ];
+ }
+ else if (rRule != *pNew)
+ {
+ bUpdateRule = true;
+ }
+
+ if (bUpdateRule)
+ {
+ if( pUndo )
+ {
+ pUndo->SaveOldNumRule( *pNew );
+ ::lcl_ChgNumRule( *this, rRule );
+ pUndo->SetLRSpaceEndPos();
+ }
+ else
+ {
+ ::lcl_ChgNumRule( *this, rRule );
+ }
+ }
+
+ if ( bSetItem )
+ {
+ if ( bCreateNewList )
+ {
+ String sListId;
+ if ( !bUpdateRule )
+ {
+ // apply list id of list, which has been created for the new list style
+ sListId = pNew->GetDefaultListId();
+ }
+ else
+ {
+ // create new list and apply its list id
+ SwList* pNewList = createList( String(), pNew->GetName() );
+ OSL_ENSURE( pNewList,
+ "<SwDoc::SetNumRule(..)> - could not create new list. Serious defect -> please inform OD." );
+ sListId = pNewList->GetListId();
+ }
+ InsertPoolItem( rPam,
+ SfxStringItem( RES_PARATR_LIST_ID, sListId ), 0 );
+ }
+ else if ( sContinuedListId.Len() > 0 )
+ {
+ // apply given list id
+ InsertPoolItem( rPam,
+ SfxStringItem( RES_PARATR_LIST_ID, sContinuedListId ), 0 );
+ }
+ }
+
+ if ( ! rPam.HasMark())
+ {
+ SwTxtNode * pTxtNd = rPam.GetPoint()->nNode.GetNode().GetTxtNode();
+ // consider case that the PaM doesn't denote a text node - e.g. it denotes a graphic node
+ if ( pTxtNd )
+ {
+ SwNumRule * pRule = pTxtNd->GetNumRule();
+
+ if (pRule && pRule->GetName() == pNew->GetName())
+ {
+ bSetItem = sal_False;
+
+ if ( !pTxtNd->IsInList() )
+ {
+ pTxtNd->AddToList();
+ }
+ }
+ // Only clear numbering attribute at text node, if at paragraph
+ // style the new numbering rule is found.
+ else if ( !pRule )
+ {
+ SwTxtFmtColl* pColl = pTxtNd->GetTxtColl();
+ if ( pColl )
+ {
+ SwNumRule* pCollRule = FindNumRulePtr(pColl->GetNumRule().GetValue());
+ if ( pCollRule && pCollRule->GetName() == pNew->GetName() )
+ {
+ pTxtNd->ResetAttr( RES_PARATR_NUMRULE );
+ bSetItem = sal_False;
+ }
+ }
+ }
+ }
+ }
+
+ if ( bSetItem )
+ {
+ InsertPoolItem( rPam, SwNumRuleItem( pNew->GetName() ), 0 );
+ }
+
+ if ( bResetIndentAttrs &&
+ pNew && pNew->Get( 0 ).GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_ALIGNMENT )
+ {
+ SvUShortsSort aResetAttrsArray;
+ aResetAttrsArray.Insert( RES_LR_SPACE );
+ // --> OD 2010-10-05 #i114929#
+ // On a selection setup a corresponding Point-and-Mark in order to get
+ // the indentation attribute reset on all paragraphs touched by the selection
+ if ( rPam.HasMark() &&
+ rPam.End()->nNode.GetNode().GetTxtNode() )
+ {
+ SwPaM aPam( rPam.Start()->nNode,
+ rPam.End()->nNode );
+ aPam.Start()->nContent = 0;
+ aPam.End()->nContent = rPam.End()->nNode.GetNode().GetTxtNode()->Len();
+ ResetAttrs( aPam, sal_False, &aResetAttrsArray );
+ }
+ else
+ {
+ ResetAttrs( rPam, sal_False, &aResetAttrsArray );
+ }
+ // <--
+ }
+
+ if (GetIDocumentUndoRedo().DoesUndo())
+ {
+ GetIDocumentUndoRedo().EndUndo( UNDO_INSNUM, NULL );
+ }
+
+ SetModified();
+}
+
+void SwDoc::SetCounted(const SwPaM & rPam, bool bCounted)
+{
+ if ( bCounted )
+ {
+ SvUShortsSort aResetAttrsArray;
+ aResetAttrsArray.Insert( RES_PARATR_LIST_ISCOUNTED );
+ // --> OD 2010-10-05 #i114929#
+ // On a selection setup a corresponding Point-and-Mark in order to get
+ // the list-is-counted attribute reset on all paragraphs touched by the selection
+ if ( rPam.HasMark() &&
+ rPam.End()->nNode.GetNode().GetTxtNode() )
+ {
+ SwPaM aPam( rPam.Start()->nNode,
+ rPam.End()->nNode );
+ aPam.Start()->nContent = 0;
+ aPam.End()->nContent = rPam.End()->nNode.GetNode().GetTxtNode()->Len();
+ ResetAttrs( aPam, sal_False, &aResetAttrsArray );
+ }
+ else
+ {
+ ResetAttrs( rPam, sal_False, &aResetAttrsArray );
+ }
+ // <--
+ }
+ else
+ {
+ InsertPoolItem( rPam,
+ SfxBoolItem( RES_PARATR_LIST_ISCOUNTED, sal_False ), 0 );
+ }
+}
+
+void SwDoc::SetNumRuleStart( const SwPosition& rPos, sal_Bool bFlag )
+{
+ SwTxtNode* pTxtNd = rPos.nNode.GetNode().GetTxtNode();
+
+ if (pTxtNd)
+ {
+ const SwNumRule* pRule = pTxtNd->GetNumRule();
+ if( pRule && !bFlag != !pTxtNd->IsListRestart())
+ {
+ if (GetIDocumentUndoRedo().DoesUndo())
+ {
+ SwUndo *const pUndo( new SwUndoNumRuleStart(rPos, bFlag) );
+ GetIDocumentUndoRedo().AppendUndo(pUndo);
+ }
+
+ pTxtNd->SetListRestart(bFlag ? true : false);
+
+ SetModified();
+ }
+ }
+}
+
+void SwDoc::SetNodeNumStart( const SwPosition& rPos, sal_uInt16 nStt )
+{
+ SwTxtNode* pTxtNd = rPos.nNode.GetNode().GetTxtNode();
+
+ if (pTxtNd)
+ {
+ if ( !pTxtNd->HasAttrListRestartValue() ||
+ pTxtNd->GetAttrListRestartValue() != nStt )
+ {
+ if (GetIDocumentUndoRedo().DoesUndo())
+ {
+ SwUndo *const pUndo( new SwUndoNumRuleStart(rPos, nStt) );
+ GetIDocumentUndoRedo().AppendUndo(pUndo);
+ }
+ pTxtNd->SetAttrListRestartValue( nStt );
+
+ SetModified();
+ }
+ }
+}
+
+// loeschen geht nur, wenn die Rule niemand benutzt!
+sal_Bool SwDoc::DelNumRule( const String& rName, sal_Bool bBroadcast )
+{
+ sal_uInt16 nPos = FindNumRule( rName );
+
+ if ( (*pNumRuleTbl)[ nPos ] == GetOutlineNumRule() )
+ {
+ OSL_FAIL( "<SwDoc::DelNumRule(..)> - No deletion of outline list style. This is serious defect - please inform OD" );
+ return sal_False;
+ }
+
+ if( USHRT_MAX != nPos && !IsUsed( *(*pNumRuleTbl)[ nPos ] ))
+ {
+ if (GetIDocumentUndoRedo().DoesUndo())
+ {
+ SwUndo * pUndo =
+ new SwUndoNumruleDelete(*(*pNumRuleTbl)[nPos], this);
+ GetIDocumentUndoRedo().AppendUndo(pUndo);
+ }
+
+ if (bBroadcast)
+ BroadcastStyleOperation(rName, SFX_STYLE_FAMILY_PSEUDO,
+ SFX_STYLESHEET_ERASED);
+
+ deleteListForListStyle( rName );
+ {
+ // delete further list, which have the deleted list style as default list style
+ std::vector< SwList* > aListsForDeletion;
+ tHashMapForLists::iterator aListIter = maLists.begin();
+ while ( aListIter != maLists.end() )
+ {
+ SwList* pList = (*aListIter).second;
+ if ( pList->GetDefaultListStyleName() == rName )
+ {
+ aListsForDeletion.push_back( pList );
+ }
+
+ ++aListIter;
+ }
+ while ( aListsForDeletion.size() > 0 )
+ {
+ SwList* pList = aListsForDeletion.back();
+ aListsForDeletion.pop_back();
+ deleteList( pList->GetListId() );
+ }
+ }
+ // --> FME 2004-11-02 #i34097# DeleteAndDestroy deletes rName if
+ // rName is directly taken from the numrule.
+ const String aTmpName( rName );
+ // <--
+ pNumRuleTbl->DeleteAndDestroy( nPos );
+ maNumRuleMap.erase(aTmpName);
+
+ SetModified();
+ return sal_True;
+ }
+ return sal_False;
+}
+
+void SwDoc::ChgNumRuleFmts( const SwNumRule& rRule, const String * pName )
+{
+ SwNumRule* pRule = FindNumRulePtr( pName ? *pName : rRule.GetName() );
+ if( pRule )
+ {
+ SwUndoInsNum* pUndo = 0;
+ if (GetIDocumentUndoRedo().DoesUndo())
+ {
+ pUndo = new SwUndoInsNum( *pRule, rRule );
+ pUndo->GetHistory();
+ GetIDocumentUndoRedo().AppendUndo( pUndo );
+ }
+ ::lcl_ChgNumRule( *this, rRule );
+
+ if( pUndo )
+ pUndo->SetLRSpaceEndPos();
+
+ SetModified();
+ }
+}
+
+sal_Bool SwDoc::RenameNumRule(const String & rOldName, const String & rNewName,
+ sal_Bool bBroadcast)
+{
+ sal_Bool bResult = sal_False;
+ SwNumRule * pNumRule = FindNumRulePtr(rOldName);
+
+ if (pNumRule)
+ {
+ if (GetIDocumentUndoRedo().DoesUndo())
+ {
+ SwUndo * pUndo = new SwUndoNumruleRename(rOldName, rNewName, this);
+ GetIDocumentUndoRedo().AppendUndo(pUndo);
+ }
+
+ SwNumRule::tTxtNodeList aTxtNodeList;
+ pNumRule->GetTxtNodeList( aTxtNodeList );
+
+ pNumRule->SetName( rNewName, *this );
+
+ SwNumRuleItem aItem(rNewName);
+
+ for ( SwNumRule::tTxtNodeList::iterator aIter = aTxtNodeList.begin();
+ aIter != aTxtNodeList.end(); ++aIter )
+ {
+ SwTxtNode * pTxtNd = *aIter;
+ pTxtNd->SetAttr(aItem);
+ }
+
+ bResult = sal_True;
+
+ if (bBroadcast)
+ BroadcastStyleOperation(rOldName, SFX_STYLE_FAMILY_PSEUDO,
+ SFX_STYLESHEET_MODIFIED);
+ }
+
+ return bResult;
+}
+
+void SwDoc::StopNumRuleAnimations( OutputDevice* pOut )
+{
+ for( sal_uInt16 n = GetNumRuleTbl().Count(); n; )
+ {
+ SwNumRule::tTxtNodeList aTxtNodeList;
+ GetNumRuleTbl()[ --n ]->GetTxtNodeList( aTxtNodeList );
+ for ( SwNumRule::tTxtNodeList::iterator aTxtNodeIter = aTxtNodeList.begin();
+ aTxtNodeIter != aTxtNodeList.end(); ++aTxtNodeIter )
+ {
+ SwTxtNode* pTNd = *aTxtNodeIter;
+ SwIterator<SwTxtFrm,SwTxtNode> aIter(*pTNd);
+ for(SwTxtFrm* pFrm = aIter.First(); pFrm; pFrm = aIter.Next() )
+ if( pFrm->HasAnimation() )
+ pFrm->StopAnimation( pOut );
+ }
+ }
+}
+
+sal_Bool SwDoc::ReplaceNumRule( const SwPosition& rPos,
+ const String& rOldRule, const String& rNewRule )
+{
+ sal_Bool bRet = sal_False;
+ SwNumRule *pOldRule = FindNumRulePtr( rOldRule ),
+ *pNewRule = FindNumRulePtr( rNewRule );
+ if( pOldRule && pNewRule && pOldRule != pNewRule )
+ {
+ SwUndoInsNum* pUndo = 0;
+ if (GetIDocumentUndoRedo().DoesUndo())
+ {
+ // Start/End for attributes!
+ GetIDocumentUndoRedo().StartUndo( UNDO_START, NULL );
+ pUndo = new SwUndoInsNum( rPos, *pNewRule, rOldRule );
+ GetIDocumentUndoRedo().AppendUndo(pUndo);
+ }
+
+ SwNumRule::tTxtNodeList aTxtNodeList;
+ pOldRule->GetTxtNodeList( aTxtNodeList );
+ if ( aTxtNodeList.size() > 0 )
+ {
+
+ SwRegHistory aRegH( pUndo ? pUndo->GetHistory() : 0 );
+ sal_uInt16 nChgFmtLevel = 0;
+ for( sal_uInt8 n = 0; n < MAXLEVEL; ++n )
+ {
+ const SwNumFmt& rOldFmt = pOldRule->Get( n ),
+ & rNewFmt = pNewRule->Get( n );
+
+ if( rOldFmt.GetAbsLSpace() != rNewFmt.GetAbsLSpace() ||
+ rOldFmt.GetFirstLineOffset() != rNewFmt.GetFirstLineOffset() )
+ nChgFmtLevel |= ( 1 << n );
+ }
+
+ const SwTxtNode* pGivenTxtNode = rPos.nNode.GetNode().GetTxtNode();
+ SwNumRuleItem aRule( rNewRule );
+
+ for ( SwNumRule::tTxtNodeList::iterator aIter = aTxtNodeList.begin();
+ aIter != aTxtNodeList.end(); ++aIter )
+ {
+ SwTxtNode* pTxtNd = *aIter;
+
+ if ( pGivenTxtNode &&
+ pGivenTxtNode->GetListId() == pTxtNd->GetListId() )
+ {
+ aRegH.RegisterInModify( pTxtNd, *pTxtNd );
+
+ pTxtNd->SetAttr( aRule );
+ pTxtNd->NumRuleChgd();
+ }
+ }
+ GetIDocumentUndoRedo().EndUndo( UNDO_END, NULL );
+ SetModified();
+
+ bRet = sal_True;
+ }
+ }
+
+ return bRet;
+}
+
+namespace
+{
+ struct ListStyleData
+ {
+ SwNumRule* pReplaceNumRule;
+ bool bCreateNewList;
+ String sListId;
+
+ ListStyleData()
+ : pReplaceNumRule( 0 ),
+ bCreateNewList( false ),
+ sListId()
+ {}
+ };
+}
+
+void SwDoc::MakeUniqueNumRules(const SwPaM & rPaM)
+{
+ OSL_ENSURE( rPaM.GetDoc() == this, "need same doc" );
+
+ ::std::map<SwNumRule *, ListStyleData> aMyNumRuleMap;
+
+ sal_uLong nStt = rPaM.Start()->nNode.GetIndex();
+ sal_uLong nEnd = rPaM.End()->nNode.GetIndex();
+
+ bool bFirst = true;
+
+ for (sal_uLong n = nStt; n <= nEnd; n++)
+ {
+ SwTxtNode * pCNd = GetNodes()[n]->GetTxtNode();
+
+ if (pCNd)
+ {
+ SwNumRule * pRule = pCNd->GetNumRule();
+
+ if (pRule && pRule->IsAutoRule() && ! pRule->IsOutlineRule())
+ {
+ ListStyleData aListStyleData = aMyNumRuleMap[pRule];
+
+ if ( aListStyleData.pReplaceNumRule == 0 )
+ {
+ if (bFirst)
+ {
+ SwPosition aPos(*pCNd);
+ aListStyleData.pReplaceNumRule =
+ const_cast<SwNumRule *>
+ (SearchNumRule( aPos, false, pCNd->HasNumber(),
+ false, 0,
+ aListStyleData.sListId, true ));
+ }
+
+ if ( aListStyleData.pReplaceNumRule == 0 )
+ {
+ aListStyleData.pReplaceNumRule = new SwNumRule(*pRule);
+
+ aListStyleData.pReplaceNumRule->SetName(
+ GetUniqueNumRuleName(), *this );
+
+ aListStyleData.bCreateNewList = true;
+ }
+
+ aMyNumRuleMap[pRule] = aListStyleData;
+ }
+
+ SwPaM aPam(*pCNd);
+
+ SetNumRule( aPam, *aListStyleData.pReplaceNumRule,
+ aListStyleData.bCreateNewList,
+ aListStyleData.sListId );
+ if ( aListStyleData.bCreateNewList )
+ {
+ aListStyleData.bCreateNewList = false;
+ aListStyleData.sListId = pCNd->GetListId();
+ aMyNumRuleMap[pRule] = aListStyleData;
+ }
+ // <--
+
+ bFirst = false;
+ }
+ }
+ }
+}
+
+sal_Bool SwDoc::NoNum( const SwPaM& rPam )
+{
+
+ sal_Bool bRet = SplitNode( *rPam.GetPoint(), false );
+ // ist ueberhaupt Nummerierung im Spiel ?
+ if( bRet )
+ {
+ // NoNum setzen und Upaten
+ const SwNodeIndex& rIdx = rPam.GetPoint()->nNode;
+ SwTxtNode* pNd = rIdx.GetNode().GetTxtNode();
+ const SwNumRule* pRule = pNd->GetNumRule();
+ if( pRule )
+ {
+ pNd->SetCountedInList(false);
+
+ SetModified();
+ }
+ else
+ bRet = sal_False; // keine Nummerierung , ?? oder immer sal_True ??
+ }
+ return bRet;
+}
+
+void SwDoc::DelNumRules( const SwPaM& rPam )
+{
+ sal_uLong nStt = rPam.GetPoint()->nNode.GetIndex(),
+ nEnd = rPam.GetMark()->nNode.GetIndex();
+ if( nStt > nEnd )
+ {
+ sal_uLong nTmp = nStt; nStt = nEnd; nEnd = nTmp;
+ }
+
+ SwUndoDelNum* pUndo;
+ if (GetIDocumentUndoRedo().DoesUndo())
+ {
+ pUndo = new SwUndoDelNum( rPam );
+ GetIDocumentUndoRedo().AppendUndo(pUndo);
+ }
+ else
+ pUndo = 0;
+
+ SwRegHistory aRegH( pUndo ? pUndo->GetHistory() : 0 );
+
+ SwNumRuleItem aEmptyRule( aEmptyStr );
+ const SwNode* pOutlNd = 0;
+ for( ; nStt <= nEnd; ++nStt )
+ {
+ SwTxtNode* pTNd = GetNodes()[ nStt ]->GetTxtNode();
+ SwNumRule* pNumRuleOfTxtNode = pTNd ? pTNd->GetNumRule() : 0;
+ if ( pTNd && pNumRuleOfTxtNode )
+ {
+ // recognize changes of attribute for undo
+ aRegH.RegisterInModify( pTNd, *pTNd );
+
+ if( pUndo )
+ pUndo->AddNode( *pTNd, sal_False );
+
+ // directly set list style attribute is reset, otherwise empty
+ // list style is applied
+ const SfxItemSet* pAttrSet = pTNd->GetpSwAttrSet();
+ if ( pAttrSet &&
+ pAttrSet->GetItemState( RES_PARATR_NUMRULE, sal_False ) == SFX_ITEM_SET )
+ pTNd->ResetAttr( RES_PARATR_NUMRULE );
+ else
+ pTNd->SetAttr( aEmptyRule );
+
+ pTNd->ResetAttr( RES_PARATR_LIST_ID );
+ pTNd->ResetAttr( RES_PARATR_LIST_LEVEL );
+ pTNd->ResetAttr( RES_PARATR_LIST_ISRESTART );
+ pTNd->ResetAttr( RES_PARATR_LIST_RESTARTVALUE );
+ pTNd->ResetAttr( RES_PARATR_LIST_ISCOUNTED );
+
+ if( RES_CONDTXTFMTCOLL == pTNd->GetFmtColl()->Which() )
+ pTNd->ChkCondColl();
+
+ else if( !pOutlNd &&
+ ((SwTxtFmtColl*)pTNd->GetFmtColl())->IsAssignedToListLevelOfOutlineStyle() )//<-end,zhaojianwei
+ pOutlNd = pTNd;
+ }
+ }
+
+ // dann noch alle Updaten
+ UpdateNumRule();
+
+ if( pOutlNd )
+ GetNodes().UpdtOutlineIdx( *pOutlNd );
+}
+
+void SwDoc::InvalidateNumRules()
+{
+ for (sal_uInt16 n = 0; n < pNumRuleTbl->Count(); ++n)
+ (*pNumRuleTbl)[n]->SetInvalidRule(sal_True);
+}
+
+// zum naechsten/vorhergehenden Punkt auf gleicher Ebene
+sal_Bool lcl_IsNumOk( sal_uInt8 nSrchNum, sal_uInt8& rLower, sal_uInt8& rUpper,
+ sal_Bool bOverUpper, sal_uInt8 nNumber )
+{
+ OSL_ENSURE( nNumber < MAXLEVEL,
+ "<lcl_IsNumOk(..)> - misusage of method" );
+
+ sal_Bool bRet = sal_False;
+ {
+ if( bOverUpper ? nSrchNum == nNumber : nSrchNum >= nNumber )
+ bRet = sal_True;
+ else if( nNumber > rLower )
+ rLower = nNumber;
+ else if( nNumber < rUpper )
+ rUpper = nNumber;
+ }
+ return bRet;
+}
+
+sal_Bool lcl_IsValidPrevNextNumNode( const SwNodeIndex& rIdx )
+{
+ sal_Bool bRet = sal_False;
+ const SwNode& rNd = rIdx.GetNode();
+ switch( rNd.GetNodeType() )
+ {
+ case ND_ENDNODE:
+ bRet = SwTableBoxStartNode == rNd.StartOfSectionNode()->GetStartNodeType() ||
+ rNd.StartOfSectionNode()->IsSectionNode();
+ break;
+
+ case ND_STARTNODE:
+ bRet = SwTableBoxStartNode == ((SwStartNode&)rNd).GetStartNodeType();
+ break;
+
+ case ND_SECTIONNODE: // der ist erlaubt, also weiter
+ bRet = sal_True;
+ break;
+ }
+ return bRet;
+}
+
+sal_Bool lcl_GotoNextPrevNum( SwPosition& rPos, sal_Bool bNext,
+ sal_Bool bOverUpper, sal_uInt8* pUpper, sal_uInt8* pLower )
+{
+ const SwTxtNode* pNd = rPos.nNode.GetNode().GetTxtNode();
+ const SwNumRule* pRule;
+ if( !pNd || 0 == ( pRule = pNd->GetNumRule()))
+ return sal_False;
+
+ sal_uInt8 nSrchNum = static_cast<sal_uInt8>(pNd->GetActualListLevel());
+
+ SwNodeIndex aIdx( rPos.nNode );
+ if( ! pNd->IsCountedInList() )
+ {
+ // falls gerade mal NO_NUMLEVEL an ist, so such den vorherigen Node
+ // mit Nummerierung
+ sal_Bool bError = sal_False;
+ do {
+ aIdx--;
+ if( aIdx.GetNode().IsTxtNode() )
+ {
+ pNd = aIdx.GetNode().GetTxtNode();
+ pRule = pNd->GetNumRule();
+
+ sal_uInt8 nTmpNum;
+
+ if( pRule )
+ {
+ nTmpNum = static_cast<sal_uInt8>(pNd->GetActualListLevel());
+ if( !( ! pNd->IsCountedInList() &&
+ (nTmpNum >= nSrchNum )) )
+ break; // gefunden
+ }
+ else
+ bError = sal_True;
+ }
+ else
+ bError = !lcl_IsValidPrevNextNumNode( aIdx );
+
+ } while( !bError );
+ if( bError )
+ return sal_False;
+ }
+
+ sal_uInt8 nLower = nSrchNum, nUpper = nSrchNum;
+ sal_Bool bRet = sal_False;
+
+ const SwTxtNode* pLast;
+ if( bNext )
+ aIdx++, pLast = pNd;
+ else
+ aIdx--, pLast = 0;
+
+ while( bNext ? ( aIdx.GetIndex() < aIdx.GetNodes().Count() - 1 )
+ : aIdx.GetIndex() )
+ {
+ if( aIdx.GetNode().IsTxtNode() )
+ {
+ pNd = aIdx.GetNode().GetTxtNode();
+ pRule = pNd->GetNumRule();
+ if( pRule )
+ {
+ if( ::lcl_IsNumOk( nSrchNum, nLower, nUpper, bOverUpper,
+ static_cast<sal_uInt8>(pNd->GetActualListLevel()) ))
+ {
+ rPos.nNode = aIdx;
+ rPos.nContent.Assign( (SwTxtNode*)pNd, 0 );
+ bRet = sal_True;
+ break;
+ }
+ else
+ pLast = pNd;
+ }
+ else
+ break;
+ }
+ else if( !lcl_IsValidPrevNextNumNode( aIdx ))
+ break;
+
+ if( bNext )
+ aIdx++;
+ else
+ aIdx--;
+ }
+
+ if( !bRet && !bOverUpper && pLast ) // nicht ueber hoehere Nummmern, aber bis Ende
+ {
+ if( bNext )
+ {
+ rPos.nNode = aIdx;
+ if( aIdx.GetNode().IsCntntNode() )
+ rPos.nContent.Assign( aIdx.GetNode().GetCntntNode(), 0 );
+ }
+ else
+ {
+ rPos.nNode.Assign( *pLast );
+ rPos.nContent.Assign( (SwTxtNode*)pLast, 0 );
+ }
+ bRet = sal_True;
+ }
+
+ if( bRet )
+ {
+ if( pUpper )
+ *pUpper = nUpper;
+ if( pLower )
+ *pLower = nLower;
+ }
+ return bRet;
+}
+
+sal_Bool SwDoc::GotoNextNum( SwPosition& rPos, sal_Bool bOverUpper,
+ sal_uInt8* pUpper, sal_uInt8* pLower )
+{
+ return ::lcl_GotoNextPrevNum( rPos, sal_True, bOverUpper, pUpper, pLower );
+}
+
+const SwNumRule * SwDoc::SearchNumRule(const SwPosition & rPos,
+ const bool bForward,
+ const bool bNum,
+ const bool bOutline,
+ int nNonEmptyAllowed,
+ String& sListId,
+ const bool bInvestigateStartNode)
+{
+ const SwNumRule * pResult = NULL;
+ SwTxtNode * pTxtNd = rPos.nNode.GetNode().GetTxtNode();
+ SwNode * pStartFromNode = pTxtNd;
+
+ if (pTxtNd)
+ {
+ SwNodeIndex aIdx(rPos.nNode);
+
+ // - the start node has also been investigated, if requested.
+ const SwNode * pNode = NULL;
+ do
+ {
+ if ( !bInvestigateStartNode )
+ {
+ if (bForward)
+ aIdx++;
+ else
+ aIdx--;
+ }
+
+ if (aIdx.GetNode().IsTxtNode())
+ {
+ pTxtNd = aIdx.GetNode().GetTxtNode();
+
+ const SwNumRule * pNumRule = pTxtNd->GetNumRule();
+ if (pNumRule)
+ {
+ if ( ( pNumRule->IsOutlineRule() == ( bOutline ? sal_True : sal_False ) ) &&
+ ( ( bNum && pNumRule->Get(0).IsEnumeration()) ||
+ ( !bNum && pNumRule->Get(0).IsItemize() ) ) ) // #i22362#, #i29560#
+ {
+ pResult = pTxtNd->GetNumRule();
+ // provide also the list id, to which the text node belongs.
+ sListId = pTxtNd->GetListId();
+ }
+
+ break;
+ }
+ else if (pTxtNd->Len() > 0 || NULL != pTxtNd->GetNumRule())
+ {
+ if (nNonEmptyAllowed == 0)
+ break;
+
+ nNonEmptyAllowed--;
+
+ if (nNonEmptyAllowed < 0)
+ nNonEmptyAllowed = -1;
+ }
+ }
+
+ if ( bInvestigateStartNode )
+ {
+ if (bForward)
+ aIdx++;
+ else
+ aIdx--;
+ }
+
+ pNode = &aIdx.GetNode();
+ }
+ while (!(pNode == GetNodes().DocumentSectionStartNode(pStartFromNode) ||
+ pNode == GetNodes().DocumentSectionEndNode(pStartFromNode)));
+ }
+
+ return pResult;
+}
+
+
+sal_Bool SwDoc::GotoPrevNum( SwPosition& rPos, sal_Bool bOverUpper,
+ sal_uInt8* pUpper, sal_uInt8* pLower )
+{
+ return ::lcl_GotoNextPrevNum( rPos, sal_False, bOverUpper, pUpper, pLower );
+}
+
+sal_Bool SwDoc::NumUpDown( const SwPaM& rPam, sal_Bool bDown )
+{
+ sal_uLong nStt = rPam.GetPoint()->nNode.GetIndex(),
+ nEnd = rPam.GetMark()->nNode.GetIndex();
+ if( nStt > nEnd )
+ {
+ sal_uLong nTmp = nStt; nStt = nEnd; nEnd = nTmp;
+ }
+
+ // -> outline nodes are promoted or demoted differently
+ bool bOnlyOutline = true;
+ bool bOnlyNonOutline = true;
+ for (sal_uLong n = nStt; n <= nEnd; n++)
+ {
+ SwTxtNode * pTxtNd = GetNodes()[n]->GetTxtNode();
+
+ if (pTxtNd)
+ {
+ SwNumRule * pRule = pTxtNd->GetNumRule();
+
+ if (pRule)
+ {
+ if (pRule->IsOutlineRule())
+ bOnlyNonOutline = false;
+ else
+ bOnlyOutline = false;
+ }
+ }
+ }
+
+ sal_Bool bRet = sal_True;
+ char nDiff = bDown ? 1 : -1;
+
+ if (bOnlyOutline)
+ bRet = OutlineUpDown(rPam, nDiff);
+ else if (bOnlyNonOutline)
+ {
+ /* #i24560#
+
+ Only promote or demote if all selected paragraphs are
+ promotable resp. demotable.
+
+ */
+ for (sal_uLong nTmp = nStt; nTmp <= nEnd; ++nTmp)
+ {
+ SwTxtNode* pTNd = GetNodes()[ nTmp ]->GetTxtNode();
+
+ // Make code robust: consider case that the node doesn't denote a
+ // text node.
+ if ( pTNd )
+ {
+ SwNumRule * pRule = pTNd->GetNumRule();
+
+ if (pRule)
+ {
+ sal_uInt8 nLevel = static_cast<sal_uInt8>(pTNd->GetActualListLevel());
+ if( (-1 == nDiff && 0 >= nLevel) ||
+ (1 == nDiff && MAXLEVEL - 1 <= nLevel))
+ bRet = sal_False;
+ }
+ }
+ }
+
+ if( bRet )
+ {
+ if (GetIDocumentUndoRedo().DoesUndo())
+ {
+ SwUndo *const pUndo( new SwUndoNumUpDown(rPam, nDiff) );
+ GetIDocumentUndoRedo().AppendUndo(pUndo);
+ }
+
+ String sNumRule;
+
+ for(sal_uLong nTmp = nStt; nTmp <= nEnd; ++nTmp )
+ {
+ SwTxtNode* pTNd = GetNodes()[ nTmp ]->GetTxtNode();
+
+ if( pTNd)
+ {
+ SwNumRule * pRule = pTNd->GetNumRule();
+
+ if (pRule)
+ {
+ sal_uInt8 nLevel = static_cast<sal_uInt8>(pTNd->GetActualListLevel());
+ nLevel = nLevel + nDiff;
+
+ pTNd->SetAttrListLevel(nLevel);
+ }
+ }
+ }
+
+ ChkCondColls();
+ SetModified();
+ }
+ }
+
+ return bRet;
+}
+
+sal_Bool SwDoc::MoveParagraph( const SwPaM& rPam, long nOffset, sal_Bool bIsOutlMv )
+{
+ const SwPosition *pStt = rPam.Start(), *pEnd = rPam.End();
+
+ sal_uLong nStIdx = pStt->nNode.GetIndex();
+ sal_uLong nEndIdx = pEnd->nNode.GetIndex();
+
+ // Here are some sophisticated checks whether the wished PaM will be moved or not.
+ // For moving outlines (bIsOutlMv) I've already done some checks, so here are two different
+ // checks...
+ SwNode *pTmp1;
+ SwNode *pTmp2;
+ if( bIsOutlMv )
+ {
+ // For moving chapters (outline) the following reason will deny the move:
+ // if a start node is inside the moved area and its end node outside or vice versa.
+ // If a start node is the first moved paragraph, its end node has to be within the moved
+ // area, too (e.g. as last node).
+ // If an end node is the last node of the moved area, its start node has to be a part of
+ // the moved section, too.
+ pTmp1 = GetNodes()[ nStIdx ];
+ if( pTmp1->IsStartNode() )
+ { // First is a start node
+ pTmp2 = pTmp1->EndOfSectionNode();
+ if( pTmp2->GetIndex() > nEndIdx )
+ return sal_False; // Its end node is behind the moved range
+ }
+ pTmp1 = pTmp1->StartOfSectionNode()->EndOfSectionNode();
+ if( pTmp1->GetIndex() <= nEndIdx )
+ return sal_False; // End node inside but start node before moved range => no.
+ pTmp1 = GetNodes()[ nEndIdx ];
+ if( pTmp1->IsEndNode() )
+ { // The last one is an end node
+ pTmp1 = pTmp1->StartOfSectionNode();
+ if( pTmp1->GetIndex() < nStIdx )
+ return sal_False; // Its start node is before the moved range.
+ }
+ pTmp1 = pTmp1->StartOfSectionNode();
+ if( pTmp1->GetIndex() >= nStIdx )
+ return sal_False; // A start node which ends behind the moved area => no.
+ }
+
+ sal_uLong nInStIdx, nInEndIdx;
+ long nOffs = nOffset;
+ if( nOffset > 0 )
+ {
+ nInEndIdx = nEndIdx;
+ nEndIdx += nOffset;
+ ++nOffs;
+ }
+ else
+ {
+ //Impossible to move to negative index
+ if( sal_uLong(abs( nOffset )) > nStIdx)
+ return sal_False;
+
+ nInEndIdx = nStIdx - 1;
+ nStIdx += nOffset;
+ }
+ nInStIdx = nInEndIdx + 1;
+ // Folgende Absatzbloecke sollen vertauscht werden:
+ // [ nStIdx, nInEndIdx ] mit [ nInStIdx, nEndIdx ]
+
+ if( nEndIdx >= GetNodes().GetEndOfContent().GetIndex() )
+ return sal_False;
+
+ if( !bIsOutlMv )
+ { // And here the restrictions for moving paragraphs other than chapters (outlines)
+ // The plan is to exchange [nStIdx,nInEndIdx] and [nStartIdx,nEndIdx]
+ // It will checked if the both "start" nodes as well as the both "end" notes belongs to
+ // the same start-end-section. This is more restrictive than the conditions checked above.
+ // E.g. a paragraph will not escape from a section or be inserted to another section.
+ pTmp1 = GetNodes()[ nStIdx ]->StartOfSectionNode();
+ pTmp2 = GetNodes()[ nInStIdx ]->StartOfSectionNode();
+ if( pTmp1 != pTmp2 )
+ return sal_False; // "start" nodes in different sections
+ pTmp1 = GetNodes()[ nEndIdx ];
+ bool bIsEndNode = pTmp1->IsEndNode();
+ if( !pTmp1->IsStartNode() )
+ {
+ pTmp1 = pTmp1->StartOfSectionNode();
+ if( bIsEndNode ) // For end nodes the first start node is of course inside the range,
+ pTmp1 = pTmp1->StartOfSectionNode(); // I've to check the start node of the start node.
+ }
+ pTmp1 = pTmp1->EndOfSectionNode();
+ pTmp2 = GetNodes()[ nInEndIdx ];
+ if( !pTmp2->IsStartNode() )
+ {
+ bIsEndNode = pTmp2->IsEndNode();
+ pTmp2 = pTmp2->StartOfSectionNode();
+ if( bIsEndNode )
+ pTmp2 = pTmp2->StartOfSectionNode();
+ }
+ pTmp2 = pTmp2->EndOfSectionNode();
+ if( pTmp1 != pTmp2 )
+ return sal_False; // The "end" notes are in different sections
+ }
+
+ // auf Redlining testen - darf die Selektion ueberhaupt verschoben
+ // werden?
+ if( !IsIgnoreRedline() )
+ {
+ sal_uInt16 nRedlPos = GetRedlinePos( pStt->nNode.GetNode(), nsRedlineType_t::REDLINE_DELETE );
+ if( USHRT_MAX != nRedlPos )
+ {
+ SwPosition aStPos( *pStt ), aEndPos( *pEnd );
+ aStPos.nContent = 0;
+ SwCntntNode* pCNd = pEnd->nNode.GetNode().GetCntntNode();
+ aEndPos.nContent = pCNd ? pCNd->Len() : 1;
+ sal_Bool bCheckDel = sal_True;
+
+ // es existiert fuer den Bereich irgendein Redline-Delete-Object
+ for( ; nRedlPos < GetRedlineTbl().Count(); ++nRedlPos )
+ {
+ const SwRedline* pTmp = GetRedlineTbl()[ nRedlPos ];
+ if( !bCheckDel || nsRedlineType_t::REDLINE_DELETE == pTmp->GetType() )
+ {
+ const SwPosition *pRStt = pTmp->Start(), *pREnd = pTmp->End();
+ switch( ComparePosition( *pRStt, *pREnd, aStPos, aEndPos ))
+ {
+ case POS_COLLIDE_START:
+ case POS_BEHIND: // Pos1 liegt hinter Pos2
+ nRedlPos = GetRedlineTbl().Count();
+ break;
+
+ case POS_COLLIDE_END:
+ case POS_BEFORE: // Pos1 liegt vor Pos2
+ break;
+ case POS_INSIDE: // Pos1 liegt vollstaendig in Pos2
+ // ist erlaubt, aber checke dann alle nachfolgenden
+ // auf Ueberlappungen
+ bCheckDel = sal_False;
+ break;
+
+ case POS_OUTSIDE: // Pos2 liegt vollstaendig in Pos1
+ case POS_EQUAL: // Pos1 ist genauso gross wie Pos2
+ case POS_OVERLAP_BEFORE: // Pos1 ueberlappt Pos2 am Anfang
+ case POS_OVERLAP_BEHIND: // Pos1 ueberlappt Pos2 am Ende
+ return sal_False;
+ }
+ }
+ }
+ }
+ }
+
+ {
+ // DataChanged vorm verschieben verschicken, dann bekommt
+ // man noch mit, welche Objecte sich im Bereich befinden.
+ // Danach koennen sie vor/hinter der Position befinden.
+ SwDataChanged aTmp( rPam, 0 );
+ }
+
+ SwNodeIndex aIdx( nOffset > 0 ? pEnd->nNode : pStt->nNode, nOffs );
+ SwNodeRange aMvRg( pStt->nNode, 0, pEnd->nNode, +1 );
+
+ SwRedline* pOwnRedl = 0;
+ if( IsRedlineOn() )
+ {
+ // wenn der Bereich komplett im eigenen Redline liegt, kann es
+ // verschoben werden!
+ sal_uInt16 nRedlPos = GetRedlinePos( pStt->nNode.GetNode(), nsRedlineType_t::REDLINE_INSERT );
+ if( USHRT_MAX != nRedlPos )
+ {
+ SwRedline* pTmp = GetRedlineTbl()[ nRedlPos ];
+ const SwPosition *pRStt = pTmp->Start(), *pREnd = pTmp->End();
+ SwRedline aTmpRedl( nsRedlineType_t::REDLINE_INSERT, rPam );
+ const SwCntntNode* pCEndNd = pEnd->nNode.GetNode().GetCntntNode();
+ // liegt komplett im Bereich, und ist auch der eigene Redline?
+ if( aTmpRedl.IsOwnRedline( *pTmp ) &&
+ (pRStt->nNode < pStt->nNode ||
+ (pRStt->nNode == pStt->nNode && !pRStt->nContent.GetIndex()) ) &&
+ (pEnd->nNode < pREnd->nNode ||
+ (pEnd->nNode == pREnd->nNode &&
+ pCEndNd ? pREnd->nContent.GetIndex() == pCEndNd->Len()
+ : !pREnd->nContent.GetIndex() )) )
+ {
+ pOwnRedl = pTmp;
+ if( nRedlPos + 1 < GetRedlineTbl().Count() )
+ {
+ pTmp = GetRedlineTbl()[ nRedlPos+1 ];
+ if( *pTmp->Start() == *pREnd )
+ // dann doch nicht!
+ pOwnRedl = 0;
+ }
+
+ if( pOwnRedl &&
+ !( pRStt->nNode <= aIdx && aIdx <= pREnd->nNode ))
+ {
+ // nicht in sich selbst, dann auch nicht moven
+ pOwnRedl = 0;
+ }
+ }
+ }
+
+ if( !pOwnRedl )
+ {
+ GetIDocumentUndoRedo().StartUndo( UNDO_START, NULL );
+
+ // zuerst das Insert, dann das Loeschen
+ SwPosition aInsPos( aIdx );
+ aInsPos.nContent.Assign( aIdx.GetNode().GetCntntNode(), 0 );
+
+ SwPaM aPam( pStt->nNode, aMvRg.aEnd );
+
+ SwPaM& rOrigPam = (SwPaM&)rPam;
+ rOrigPam.DeleteMark();
+ rOrigPam.GetPoint()->nNode = aIdx.GetIndex() - 1;
+
+ sal_Bool bDelLastPara = !aInsPos.nNode.GetNode().IsCntntNode();
+
+ /* When copying to a non-content node Copy will
+ insert a paragraph before that node and insert before
+ that inserted node. Copy creates an SwUndoInserts that
+ does not cover the extra paragraph. Thus we insert the
+ extra paragraph ourselves, _with_ correct undo
+ information. */
+ if (bDelLastPara)
+ {
+ /* aInsPos points to the non-content node. Move it to
+ the previous content node. */
+ SwPaM aInsPam(aInsPos);
+ sal_Bool bMoved = aInsPam.Move(fnMoveBackward);
+ OSL_ENSURE(bMoved, "No content node found!");
+
+ if (bMoved)
+ {
+ /* Append the new node after the content node
+ found. The new position to insert the moved
+ paragraph at is before the inserted
+ paragraph. */
+ AppendTxtNode(*aInsPam.GetPoint());
+ aInsPos = *aInsPam.GetPoint();
+ }
+ }
+
+ CopyRange( aPam, aInsPos, false );
+ if( bDelLastPara )
+ {
+ // dann muss der letzte leere Node wieder entfernt werden
+ aIdx = aInsPos.nNode;
+ SwCntntNode* pCNd = GetNodes().GoPrevious( &aInsPos.nNode );
+ xub_StrLen nCLen = 0; if( pCNd ) nCLen = pCNd->Len();
+ aInsPos.nContent.Assign( pCNd, nCLen );
+
+ // alle die im zu loeschenden Node stehen, mussen auf den
+ // naechsten umgestezt werden
+ SwPosition* pPos;
+ for( sal_uInt16 n = 0; n < GetRedlineTbl().Count(); ++n )
+ {
+ SwRedline* pTmp = GetRedlineTbl()[ n ];
+ if( ( pPos = &pTmp->GetBound(sal_True))->nNode == aIdx )
+ {
+ pPos->nNode++;
+ pPos->nContent.Assign( pPos->nNode.GetNode().GetCntntNode(),0);
+ }
+ if( ( pPos = &pTmp->GetBound(sal_False))->nNode == aIdx )
+ {
+ pPos->nNode++;
+ pPos->nContent.Assign( pPos->nNode.GetNode().GetCntntNode(),0);
+ }
+ }
+ CorrRel( aIdx, aInsPos, 0, sal_False );
+
+ pCNd->JoinNext();
+ }
+
+ rOrigPam.GetPoint()->nNode++;
+ rOrigPam.GetPoint()->nContent.Assign( rOrigPam.GetCntntNode(), 0 );
+
+ RedlineMode_t eOld = GetRedlineMode();
+ checkRedlining(eOld);
+ if (GetIDocumentUndoRedo().DoesUndo())
+ {
+ //JP 06.01.98: MUSS noch optimiert werden!!!
+ SetRedlineMode(
+ (RedlineMode_t)(nsRedlineMode_t::REDLINE_ON | nsRedlineMode_t::REDLINE_SHOW_INSERT | nsRedlineMode_t::REDLINE_SHOW_DELETE));
+ SwUndo *const pUndo(new SwUndoRedlineDelete(aPam, UNDO_DELETE));
+ GetIDocumentUndoRedo().AppendUndo(pUndo);
+ }
+
+ SwRedline* pNewRedline = new SwRedline( nsRedlineType_t::REDLINE_DELETE, aPam );
+
+ // prevent assertion from aPam's target being deleted
+ // (Alternatively, one could just let aPam go out of scope, but
+ // that requires touching a lot of code.)
+ aPam.GetBound(sal_True).nContent.Assign( NULL, 0 );
+ aPam.GetBound(sal_False).nContent.Assign( NULL, 0 );
+
+ AppendRedline( pNewRedline, true );
+
+//JP 06.01.98: MUSS noch optimiert werden!!!
+SetRedlineMode( eOld );
+ GetIDocumentUndoRedo().EndUndo( UNDO_END, NULL );
+ SetModified();
+
+ return sal_True;
+ }
+ }
+
+ if( !pOwnRedl && !IsIgnoreRedline() && GetRedlineTbl().Count() )
+ {
+ SwPaM aTemp(aIdx);
+ SplitRedline(aTemp);
+ }
+
+ sal_uLong nRedlSttNd(0), nRedlEndNd(0);
+ if( pOwnRedl )
+ {
+ const SwPosition *pRStt = pOwnRedl->Start(), *pREnd = pOwnRedl->End();
+ nRedlSttNd = pRStt->nNode.GetIndex();
+ nRedlEndNd = pREnd->nNode.GetIndex();
+ }
+
+ SwUndoMoveNum* pUndo = 0;
+ sal_uLong nMoved = 0;
+ if (GetIDocumentUndoRedo().DoesUndo())
+ {
+ pUndo = new SwUndoMoveNum( rPam, nOffset, bIsOutlMv );
+ nMoved = rPam.End()->nNode.GetIndex() - rPam.Start()->nNode.GetIndex() + 1;
+ }
+
+
+ MoveNodeRange( aMvRg, aIdx, DOC_MOVEREDLINES );
+
+ if( pUndo )
+ {
+ // i57907: Under circumstances (sections at the end of a chapter)
+ // the rPam.Start() is not moved to the new position.
+ // But aIdx should be at the new end position and as long as the number of moved paragraphs
+ // is nMoved, I know, where the new position is.
+ pUndo->SetStartNode( aIdx.GetIndex() - nMoved );
+ GetIDocumentUndoRedo().AppendUndo(pUndo);
+ }
+
+ if( pOwnRedl )
+ {
+ SwPosition *pRStt = pOwnRedl->Start(), *pREnd = pOwnRedl->End();
+ if( pRStt->nNode.GetIndex() != nRedlSttNd )
+ {
+ pRStt->nNode = nRedlSttNd;
+ pRStt->nContent.Assign( pRStt->nNode.GetNode().GetCntntNode(),0);
+ }
+ if( pREnd->nNode.GetIndex() != nRedlEndNd )
+ {
+ pREnd->nNode = nRedlEndNd;
+ SwCntntNode* pCNd = pREnd->nNode.GetNode().GetCntntNode();
+ xub_StrLen nL = 0; if( pCNd ) nL = pCNd->Len();
+ pREnd->nContent.Assign( pCNd, nL );
+ }
+ }
+
+ SetModified();
+ return sal_True;
+}
+
+sal_Bool SwDoc::NumOrNoNum( const SwNodeIndex& rIdx, sal_Bool bDel )
+{
+ sal_Bool bResult = sal_False;
+ SwTxtNode * pTxtNd = rIdx.GetNode().GetTxtNode();
+
+ if (pTxtNd && pTxtNd->GetNumRule() != NULL &&
+ (pTxtNd->HasNumber() || pTxtNd->HasBullet()))
+ {
+ if ( !pTxtNd->IsCountedInList() == !bDel)
+ {
+ sal_Bool bOldNum = bDel; // == pTxtNd->IsCounted();
+ sal_Bool bNewNum = bDel ? sal_False : sal_True;
+ pTxtNd->SetCountedInList(bNewNum ? true : false);
+
+ SetModified();
+
+ bResult = sal_True;
+
+ if (GetIDocumentUndoRedo().DoesUndo())
+ {
+ SwUndoNumOrNoNum * pUndo =
+ new SwUndoNumOrNoNum(rIdx, bOldNum, bNewNum);
+
+ GetIDocumentUndoRedo().AppendUndo(pUndo);
+ }
+ }
+ else if (bDel && pTxtNd->GetNumRule(sal_False) &&
+ pTxtNd->GetActualListLevel() >= 0 &&
+ pTxtNd->GetActualListLevel() < MAXLEVEL)
+ {
+ SwPaM aPam(*pTxtNd);
+
+ DelNumRules(aPam);
+
+ bResult = sal_True;
+ }
+ }
+
+ return bResult;
+}
+
+SwNumRule* SwDoc::GetCurrNumRule( const SwPosition& rPos ) const
+{
+ SwNumRule* pRet = 0;
+ SwTxtNode* pTNd = rPos.nNode.GetNode().GetTxtNode();
+
+ if( pTNd )
+ {
+ pRet = pTNd->GetNumRule();
+ }
+
+ return pRet;
+}
+
+sal_uInt16 SwDoc::FindNumRule( const String& rName ) const
+{
+ for( sal_uInt16 n = pNumRuleTbl->Count(); n; )
+ if( (*pNumRuleTbl)[ --n ]->GetName() == rName )
+ return n;
+
+ return USHRT_MAX;
+}
+
+SwNumRule* SwDoc::FindNumRulePtr( const String& rName ) const
+{
+ SwNumRule * pResult = 0;
+
+ pResult = maNumRuleMap[rName];
+
+ if ( !pResult )
+ {
+ for (sal_uInt16 n = 0; n < pNumRuleTbl->Count(); ++n)
+ {
+ if ((*pNumRuleTbl)[n]->GetName() == rName)
+ {
+ pResult = (*pNumRuleTbl)[n];
+
+ break;
+ }
+ }
+ }
+
+ return pResult;
+}
+
+void SwDoc::AddNumRule(SwNumRule * pRule)
+{
+ pNumRuleTbl->Insert(pRule, pNumRuleTbl->Count());
+ maNumRuleMap[pRule->GetName()] = pRule;
+ pRule->SetNumRuleMap(&maNumRuleMap);
+
+ createListForListStyle( pRule->GetName() );
+}
+
+sal_uInt16 SwDoc::MakeNumRule( const String &rName,
+ const SwNumRule* pCpy,
+ sal_Bool bBroadcast,
+ const SvxNumberFormat::SvxNumPositionAndSpaceMode eDefaultNumberFormatPositionAndSpaceMode )
+{
+ SwNumRule* pNew;
+ if( pCpy )
+ {
+ pNew = new SwNumRule( *pCpy );
+
+ pNew->SetName( GetUniqueNumRuleName( &rName ), *this );
+
+ if( pNew->GetName() != rName )
+ {
+ pNew->SetPoolFmtId( USHRT_MAX );
+ pNew->SetPoolHelpId( USHRT_MAX );
+ pNew->SetPoolHlpFileId( UCHAR_MAX );
+ pNew->SetDefaultListId( String() );
+ }
+ pNew->CheckCharFmts( this );
+ }
+ else
+ {
+ pNew = new SwNumRule( GetUniqueNumRuleName( &rName ),
+ eDefaultNumberFormatPositionAndSpaceMode );
+ }
+
+ sal_uInt16 nRet = pNumRuleTbl->Count();
+
+ AddNumRule(pNew);
+
+ if (GetIDocumentUndoRedo().DoesUndo())
+ {
+ SwUndo * pUndo = new SwUndoNumruleCreate(pNew, this);
+ GetIDocumentUndoRedo().AppendUndo(pUndo);
+ }
+
+ if (bBroadcast)
+ BroadcastStyleOperation(pNew->GetName(), SFX_STYLE_FAMILY_PSEUDO,
+ SFX_STYLESHEET_CREATED);
+
+ return nRet;
+}
+
+String SwDoc::GetUniqueNumRuleName( const String* pChkStr, sal_Bool bAutoNum ) const
+{
+ String aName;
+ if( bAutoNum )
+ {
+ long n = Time().GetTime();
+ n += Date().GetDate();
+ aName = String::CreateFromInt32( n );
+ if( pChkStr && !pChkStr->Len() )
+ pChkStr = 0;
+ }
+ else if( pChkStr && pChkStr->Len() )
+ aName = *pChkStr;
+ else
+ {
+ pChkStr = 0;
+ aName = SW_RESSTR( STR_NUMRULE_DEFNAME );
+ }
+
+ sal_uInt16 nNum(0), nTmp, nFlagSize = ( pNumRuleTbl->Count() / 8 ) +2;
+ sal_uInt8* pSetFlags = new sal_uInt8[ nFlagSize ];
+ memset( pSetFlags, 0, nFlagSize );
+
+ xub_StrLen nNmLen = aName.Len();
+ if( !bAutoNum && pChkStr )
+ {
+ while( nNmLen-- && '0' <= aName.GetChar( nNmLen ) &&
+ '9' >= aName.GetChar( nNmLen ) )
+ ; //nop
+
+ if( ++nNmLen < aName.Len() )
+ {
+ aName.Erase( nNmLen );
+ pChkStr = 0;
+ }
+ }
+
+ const SwNumRule* pNumRule;
+ sal_uInt16 n;
+
+ for( n = 0; n < pNumRuleTbl->Count(); ++n )
+ if( 0 != ( pNumRule = (*pNumRuleTbl)[ n ] ) )
+ {
+ const String& rNm = pNumRule->GetName();
+ if( rNm.Match( aName ) == nNmLen )
+ {
+ // Nummer bestimmen und das Flag setzen
+ nNum = (sal_uInt16)rNm.Copy( nNmLen ).ToInt32();
+ if( nNum-- && nNum < pNumRuleTbl->Count() )
+ pSetFlags[ nNum / 8 ] |= (0x01 << ( nNum & 0x07 ));
+ }
+ if( pChkStr && pChkStr->Equals( rNm ) )
+ pChkStr = 0;
+ }
+
+ if( !pChkStr )
+ {
+ // alle Nummern entsprechend geflag, also bestimme die richtige Nummer
+ nNum = pNumRuleTbl->Count();
+ for( n = 0; n < nFlagSize; ++n )
+ if( 0xff != ( nTmp = pSetFlags[ n ] ))
+ {
+ // also die Nummer bestimmen
+ nNum = n * 8;
+ while( nTmp & 1 )
+ ++nNum, nTmp >>= 1;
+ break;
+ }
+
+ }
+ delete [] pSetFlags;
+ if( pChkStr && pChkStr->Len() )
+ return *pChkStr;
+ return aName += String::CreateFromInt32( ++nNum );
+}
+
+void SwDoc::UpdateNumRule()
+{
+ const SwNumRuleTbl& rNmTbl = GetNumRuleTbl();
+ for( sal_uInt16 n = 0; n < rNmTbl.Count(); ++n )
+ if( rNmTbl[ n ]->IsInvalidRule() )
+ rNmTbl[ n ]->Validate();
+}
+
+void SwDoc::MarkListLevel( const String& sListId,
+ const int nListLevel,
+ const sal_Bool bValue )
+{
+ SwList* pList = getListByName( sListId );
+
+ if ( pList )
+ {
+ MarkListLevel( *pList, nListLevel, bValue );
+ }
+}
+
+void SwDoc::MarkListLevel( SwList& rList,
+ const int nListLevel,
+ const sal_Bool bValue )
+{
+ // Set new marked list level and notify all affected nodes of the changed mark.
+ rList.MarkListLevel( nListLevel, bValue );
+}
+
+sal_Bool SwDoc::IsFirstOfNumRule(SwPosition & rPos)
+{
+ sal_Bool bResult = sal_False;
+ SwTxtNode * pTxtNode = rPos.nNode.GetNode().GetTxtNode();
+
+ if (pTxtNode)
+ {
+ SwNumRule * pNumRule = pTxtNode->GetNumRule();
+
+ if (pNumRule)
+ bResult = pTxtNode->IsFirstOfNumRule();
+ }
+
+ return bResult;
+}
+
+// implementation for interface <IDocumentListItems>
+bool SwDoc::lessThanNodeNum::operator()( const SwNodeNum* pNodeNumOne,
+ const SwNodeNum* pNodeNumTwo ) const
+{
+ return pNodeNumOne->LessThan( *pNodeNumTwo );
+}
+
+void SwDoc::addListItem( const SwNodeNum& rNodeNum )
+{
+ if ( mpListItemsList == 0 )
+ {
+ return;
+ }
+
+ const bool bAlreadyInserted(
+ mpListItemsList->find( &rNodeNum ) != mpListItemsList->end() );
+ OSL_ENSURE( !bAlreadyInserted,
+ "<SwDoc::InsertListItem(..)> - <SwNodeNum> instance already registered as numbered item!" );
+ if ( !bAlreadyInserted )
+ {
+ mpListItemsList->insert( &rNodeNum );
+ }
+}
+
+void SwDoc::removeListItem( const SwNodeNum& rNodeNum )
+{
+ if ( mpListItemsList == 0 )
+ {
+ return;
+ }
+
+ const tImplSortedNodeNumList::size_type nDeleted = mpListItemsList->erase( &rNodeNum );
+ if ( nDeleted > 1 )
+ {
+ OSL_FAIL( "<SwDoc::RemoveListItem(..)> - <SwNodeNum> was registered more than once as numbered item!" );
+ }
+}
+
+String SwDoc::getListItemText( const SwNodeNum& rNodeNum,
+ const bool bWithNumber,
+ const bool bWithSpacesForLevel ) const
+{
+ return rNodeNum.GetTxtNode()
+ ? rNodeNum.GetTxtNode()->GetExpandTxt( 0, STRING_LEN, bWithNumber,
+ bWithNumber, bWithSpacesForLevel )
+ : String();
+}
+
+void SwDoc::getListItems( tSortedNodeNumList& orNodeNumList ) const
+{
+ orNodeNumList.clear();
+ orNodeNumList.reserve( mpListItemsList->size() );
+
+ tImplSortedNodeNumList::iterator aIter;
+ tImplSortedNodeNumList::iterator aEndIter = mpListItemsList->end();
+ for ( aIter = mpListItemsList->begin(); aIter != aEndIter; ++aIter )
+ {
+ orNodeNumList.push_back( (*aIter) );
+ }
+}
+
+void SwDoc::getNumItems( tSortedNodeNumList& orNodeNumList ) const
+{
+ orNodeNumList.clear();
+ orNodeNumList.reserve( mpListItemsList->size() );
+
+ tImplSortedNodeNumList::iterator aIter;
+ tImplSortedNodeNumList::iterator aEndIter = mpListItemsList->end();
+ for ( aIter = mpListItemsList->begin(); aIter != aEndIter; ++aIter )
+ {
+ const SwNodeNum* pNodeNum = (*aIter);
+ if ( pNodeNum->IsCounted() &&
+ pNodeNum->GetTxtNode() && pNodeNum->GetTxtNode()->HasNumber() )
+ {
+ orNodeNumList.push_back( pNodeNum );
+ }
+ }
+}
+
+// implementation for interface <IDocumentOutlineNodes>
+sal_Int32 SwDoc::getOutlineNodesCount() const
+{
+ return GetNodes().GetOutLineNds().Count();
+}
+
+int SwDoc::getOutlineLevel( const sal_Int32 nIdx ) const
+{
+ return GetNodes().GetOutLineNds()[ static_cast<sal_uInt16>(nIdx) ]->
+ // GetTxtNode()->GetOutlineLevel(); //#outline level,zhaojianwei
+ GetTxtNode()->GetAttrOutlineLevel()-1; //<-end,zhaojianwei
+}
+
+String SwDoc::getOutlineText( const sal_Int32 nIdx,
+ const bool bWithNumber,
+ const bool bWithSpacesForLevel ) const
+{
+ return GetNodes().GetOutLineNds()[ static_cast<sal_uInt16>(nIdx) ]->
+ GetTxtNode()->GetExpandTxt( 0, STRING_LEN, bWithNumber,
+ bWithNumber, bWithSpacesForLevel );
+}
+
+SwTxtNode* SwDoc::getOutlineNode( const sal_Int32 nIdx ) const
+{
+ return GetNodes().GetOutLineNds()[ static_cast<sal_uInt16>(nIdx) ]->GetTxtNode();
+}
+
+void SwDoc::getOutlineNodes( IDocumentOutlineNodes::tSortedOutlineNodeList& orOutlineNodeList ) const
+{
+ orOutlineNodeList.clear();
+ orOutlineNodeList.reserve( getOutlineNodesCount() );
+
+ const sal_uInt16 nOutlCount( static_cast<sal_uInt16>(getOutlineNodesCount()) );
+ for ( sal_uInt16 i = 0; i < nOutlCount; ++i )
+ {
+ orOutlineNodeList.push_back(
+ GetNodes().GetOutLineNds()[i]->GetTxtNode() );
+ }
+}
+
+// implementation of interface IDocumentListsAccess
+SwList* SwDoc::createList( String sListId,
+ const String sDefaultListStyleName )
+{
+ if ( sListId.Len() == 0 )
+ {
+ sListId = listfunc::CreateUniqueListId( *this );
+ }
+
+ if ( getListByName( sListId ) )
+ {
+ OSL_FAIL( "<SwDoc::createList(..)> - provided list id already used. Serious defect -> please inform OD." );
+ return 0;
+ }
+
+ SwNumRule* pDefaultNumRuleForNewList = FindNumRulePtr( sDefaultListStyleName );
+ if ( !pDefaultNumRuleForNewList )
+ {
+ OSL_FAIL( "<SwDoc::createList(..)> - for provided default list style name no list style is found. Serious defect -> please inform OD." );
+ return 0;
+ }
+
+ SwList* pNewList = new SwList( sListId, *pDefaultNumRuleForNewList, GetNodes() );
+ maLists[sListId] = pNewList;
+
+ return pNewList;
+}
+
+void SwDoc::deleteList( const String sListId )
+{
+ SwList* pList = getListByName( sListId );
+ if ( pList )
+ {
+ maLists.erase( sListId );
+ delete pList;
+ }
+}
+
+SwList* SwDoc::getListByName( const String sListId ) const
+{
+ SwList* pList = 0;
+
+ boost::unordered_map< String, SwList*, StringHash >::const_iterator
+ aListIter = maLists.find( sListId );
+ if ( aListIter != maLists.end() )
+ {
+ pList = (*aListIter).second;
+ }
+
+ return pList;
+}
+
+SwList* SwDoc::createListForListStyle( const String sListStyleName )
+{
+ if ( sListStyleName.Len() == 0 )
+ {
+ OSL_FAIL( "<SwDoc::createListForListStyle(..)> - no list style name provided. Serious defect -> please inform OD." );
+ return 0;
+ }
+
+ if ( getListForListStyle( sListStyleName ) )
+ {
+ OSL_FAIL( "<SwDoc::createListForListStyle(..)> - a list for the provided list style name already exists. Serious defect -> please inform OD." );
+ return 0;
+ }
+
+ SwNumRule* pNumRule = FindNumRulePtr( sListStyleName );
+ if ( !pNumRule )
+ {
+ OSL_FAIL( "<SwDoc::createListForListStyle(..)> - for provided list style name no list style is found. Serious defect -> please inform OD." );
+ return 0;
+ }
+
+ String sListId( pNumRule->GetDefaultListId() ); // can be empty String
+ if ( getListByName( sListId ) )
+ {
+ sListId = String();
+ }
+ SwList* pNewList = createList( sListId, sListStyleName );
+ maListStyleLists[sListStyleName] = pNewList;
+ pNumRule->SetDefaultListId( pNewList->GetListId() );
+
+ return pNewList;
+}
+
+SwList* SwDoc::getListForListStyle( const String sListStyleName ) const
+{
+ SwList* pList = 0;
+
+ boost::unordered_map< String, SwList*, StringHash >::const_iterator
+ aListIter = maListStyleLists.find( sListStyleName );
+ if ( aListIter != maListStyleLists.end() )
+ {
+ pList = (*aListIter).second;
+ }
+
+ return pList;
+}
+
+void SwDoc::deleteListForListStyle( const String sListStyleName )
+{
+ String sListId;
+ {
+ SwList* pList = getListForListStyle( sListStyleName );
+ OSL_ENSURE( pList,
+ "<SwDoc::deleteListForListStyle(..)> - misusage of method: no list found for given list style name" );
+ if ( pList )
+ {
+ sListId = pList->GetListId();
+ }
+ }
+ if ( sListId.Len() > 0 )
+ {
+ maListStyleLists.erase( sListStyleName );
+ deleteList( sListId );
+ }
+}
+
+void SwDoc::trackChangeOfListStyleName( const String sListStyleName,
+ const String sNewListStyleName )
+{
+ SwList* pList = getListForListStyle( sListStyleName );
+ OSL_ENSURE( pList,
+ "<SwDoc::changeOfListStyleName(..)> - misusage of method: no list found for given list style name" );
+
+ if ( pList != 0 )
+ {
+ maListStyleLists.erase( sListStyleName );
+ maListStyleLists[sNewListStyleName] = pList;
+ }
+}
+
+namespace listfunc
+{
+ const String MakeListIdUnique( const SwDoc& rDoc,
+ const String aSuggestedUniqueListId )
+ {
+ long nHitCount = 0;
+ String aTmpStr = aSuggestedUniqueListId;
+ while ( rDoc.getListByName( aTmpStr ) )
+ {
+ ++nHitCount;
+ aTmpStr = aSuggestedUniqueListId;
+ aTmpStr += String::CreateFromInt32( nHitCount );
+ }
+
+ return aTmpStr;
+ }
+ const String CreateUniqueListId( const SwDoc& rDoc )
+ {
+ // #i92478#
+ String aNewListId = String::CreateFromAscii( "list" );
+ sal_Int64 n = Time().GetTime();
+ n += Date().GetDate();
+ n += rand();
+ // #i92478#
+ aNewListId += String::CreateFromInt64( n );
+
+ return MakeListIdUnique( rDoc, aNewListId );
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/doc/docredln.cxx b/sw/source/core/doc/docredln.cxx
new file mode 100644
index 000000000000..bbd8bc4ee608
--- /dev/null
+++ b/sw/source/core/doc/docredln.cxx
@@ -0,0 +1,3853 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+
+#include <hintids.hxx>
+#include <tools/shl.hxx>
+#include <svl/itemiter.hxx>
+#include <sfx2/app.hxx>
+#include <editeng/colritem.hxx>
+#include <editeng/udlnitem.hxx>
+#include <editeng/crsditem.hxx>
+#include <swmodule.hxx>
+#include <doc.hxx>
+#include <IDocumentUndoRedo.hxx>
+#include <docary.hxx>
+#include <ndtxt.hxx>
+#include <redline.hxx>
+#include <swundo.hxx>
+#include <UndoCore.hxx>
+#include <UndoRedline.hxx>
+#include <hints.hxx>
+#include <pamtyp.hxx>
+#include <poolfmt.hxx>
+#include <viewsh.hxx>
+#include <rootfrm.hxx>
+
+#include <comcore.hrc>
+
+using namespace com::sun::star;
+
+TYPEINIT1(SwRedlineHint, SfxHint);
+
+#if OSL_DEBUG_LEVEL > 1
+
+ #define _ERROR_PREFIX "redline table corrupted: "
+
+ // helper function for lcl_CheckRedline
+ // 1. make sure that pPos->nContent points into pPos->nNode
+ // (or into the 'special' no-content-node-IndexReg)
+ // 2. check that position is valid and doesn't point behind text
+ void lcl_CheckPosition( const SwPosition* pPos )
+ {
+ SwPosition aComparePos( *pPos );
+ aComparePos.nContent.Assign(
+ aComparePos.nNode.GetNode().GetCntntNode(), 0 );
+ DBG_ASSERT( pPos->nContent.GetIdxReg() ==
+ aComparePos.nContent.GetIdxReg(),
+ _ERROR_PREFIX "illegal position" );
+
+ SwTxtNode* pTxtNode = pPos->nNode.GetNode().GetTxtNode();
+ if( pTxtNode == NULL )
+ {
+ DBG_ASSERT( pPos->nContent == 0,
+ _ERROR_PREFIX "non-text-node with content" );
+ }
+ else
+ {
+ DBG_ASSERT( pPos->nContent >= 0 &&
+ pPos->nContent <= pTxtNode->Len(),
+ _ERROR_PREFIX "index behind text" );
+ }
+ }
+
+ void lcl_CheckPam( const SwPaM* pPam )
+ {
+ DBG_ASSERT( pPam != NULL, _ERROR_PREFIX "illegal argument" );
+ lcl_CheckPosition( pPam->GetPoint() );
+ lcl_CheckPosition( pPam->GetMark() );
+ }
+
+ // check validity of the redline table. Checks redline bounds, and make
+ // sure the redlines are sorted and non-overlapping.
+ void lcl_CheckRedline( const SwDoc* pDoc )
+ {
+ const SwRedlineTbl& rTbl = pDoc->GetRedlineTbl();
+
+ // verify valid redline positions
+ for( sal_uInt16 i = 0; i < rTbl.Count(); ++i )
+ lcl_CheckPam( rTbl[ i ] );
+
+ for( sal_uInt16 j = 0; j < rTbl.Count(); ++j )
+ {
+ // check for empty redlines
+ DBG_ASSERT( ( *(rTbl[j]->GetPoint()) != *(rTbl[j]->GetMark()) ) ||
+ ( rTbl[j]->GetContentIdx() != NULL ),
+ _ERROR_PREFIX "empty redline" );
+ }
+
+ // verify proper redline sorting
+ for( sal_uInt16 n = 1; n < rTbl.Count(); ++n )
+ {
+ const SwRedline* pPrev = rTbl[ n-1 ];
+ const SwRedline* pCurrent = rTbl[ n ];
+
+ // check redline sorting
+ DBG_ASSERT( *pPrev->Start() <= *pCurrent->Start(),
+ _ERROR_PREFIX "not sorted correctly" );
+
+ // check for overlapping redlines
+ DBG_ASSERT( *pPrev->End() <= *pCurrent->Start(),
+ _ERROR_PREFIX "overlapping redlines" );
+ }
+ }
+
+ #define _CHECK_REDLINE( pDoc ) lcl_CheckRedline( pDoc );
+
+ void lcl_DebugRedline( const SwDoc* pDoc )
+ {
+ static sal_uInt16 nWatch = 0;
+ const SwRedlineTbl& rTbl = pDoc->GetRedlineTbl();
+ for( sal_uInt16 n = 0; n < rTbl.Count(); ++n )
+ {
+ sal_uInt16 nDummy = 0;
+ const SwRedline* pCurrent = rTbl[ n ];
+ const SwRedline* pNext = n+1 < rTbl.Count() ? rTbl[ n+1 ] : 0;
+ if( pCurrent == pNext )
+ ++nDummy;
+ if( n == nWatch )
+ ++nDummy; // Possible debugger breakpoint
+ }
+ }
+
+ #define _DEBUG_REDLINE( pDoc ) lcl_DebugRedline( pDoc );
+
+
+#else
+
+ #define _CHECK_REDLINE( pDoc )
+ #define _DEBUG_REDLINE( pDoc )
+
+#endif
+
+SV_IMPL_OP_PTRARR_SORT( _SwRedlineTbl, SwRedlinePtr )
+
+RedlineMode_t SwDoc::GetRedlineMode() const
+{
+ return eRedlineMode;
+}
+
+void SwDoc::SetRedlineMode( RedlineMode_t eMode )
+{
+ if( eRedlineMode != eMode )
+ {
+ if( (nsRedlineMode_t::REDLINE_SHOW_MASK & eRedlineMode) != (nsRedlineMode_t::REDLINE_SHOW_MASK & eMode)
+ || 0 == (nsRedlineMode_t::REDLINE_SHOW_MASK & eMode) )
+ {
+ bool bSaveInXMLImportFlag = IsInXMLImport();
+ SetInXMLImport( false );
+ // und dann alles verstecken, anzeigen
+ void (SwRedline::*pFnc)( sal_uInt16 ) = 0;
+
+ switch( nsRedlineMode_t::REDLINE_SHOW_MASK & eMode )
+ {
+ case nsRedlineMode_t::REDLINE_SHOW_INSERT | nsRedlineMode_t::REDLINE_SHOW_DELETE :
+ pFnc = &SwRedline::Show;
+ break;
+ case nsRedlineMode_t::REDLINE_SHOW_INSERT:
+ pFnc = &SwRedline::Hide;
+ break;
+ case nsRedlineMode_t::REDLINE_SHOW_DELETE:
+ pFnc = &SwRedline::ShowOriginal;
+ break;
+
+ default:
+ pFnc = &SwRedline::Hide;
+ eMode = (RedlineMode_t)(eMode | nsRedlineMode_t::REDLINE_SHOW_INSERT);
+ break;
+ }
+
+ _CHECK_REDLINE( this )
+
+ if( pFnc )
+ for( sal_uInt16 nLoop = 1; nLoop <= 2; ++nLoop )
+ for( sal_uInt16 i = 0; i < pRedlineTbl->Count(); ++i )
+ ((*pRedlineTbl)[ i ]->*pFnc)( nLoop );
+ _CHECK_REDLINE( this )
+ SetInXMLImport( bSaveInXMLImportFlag );
+ }
+ eRedlineMode = eMode;
+ SetModified();
+ }
+}
+
+bool SwDoc::IsRedlineOn() const
+{
+ return IDocumentRedlineAccess::IsRedlineOn(eRedlineMode);
+}
+
+bool SwDoc::IsIgnoreRedline() const
+{
+ return (nsRedlineMode_t::REDLINE_IGNORE & eRedlineMode);
+}
+
+void SwDoc::SetRedlineMode_intern(RedlineMode_t eMode)
+{
+ eRedlineMode = eMode;
+}
+
+const SwRedlineTbl& SwDoc::GetRedlineTbl() const
+{
+ return *pRedlineTbl;
+}
+
+bool SwDoc::IsRedlineMove() const
+{
+ return mbIsRedlineMove;
+}
+
+void SwDoc::SetRedlineMove(bool bFlag)
+{
+ mbIsRedlineMove = bFlag;
+}
+
+const uno::Sequence <sal_Int8>& SwDoc::GetRedlinePassword() const
+{
+ return aRedlinePasswd;
+}
+
+inline bool IsPrevPos( const SwPosition rPos1, const SwPosition rPos2 )
+{
+ const SwCntntNode* pCNd;
+ return 0 == rPos2.nContent.GetIndex() &&
+ rPos2.nNode.GetIndex() - 1 == rPos1.nNode.GetIndex() &&
+ 0 != ( pCNd = rPos1.nNode.GetNode().GetCntntNode() )
+ ? rPos1.nContent.GetIndex() == pCNd->Len()
+ : false;
+}
+
+#ifdef DEBUG
+bool CheckPosition( const SwPosition* pStt, const SwPosition* pEnd )
+{
+ int nError = 0;
+ SwNode* pSttNode = &pStt->nNode.GetNode();
+ SwNode* pEndNode = &pEnd->nNode.GetNode();
+ SwNode* pSttTab = pSttNode->StartOfSectionNode()->FindTableNode();
+ SwNode* pEndTab = pEndNode->StartOfSectionNode()->FindTableNode();
+ SwNode* pSttStart = pSttNode;
+ while( pSttStart && (!pSttStart->IsStartNode() || pSttStart->IsSectionNode() ||
+ pSttStart->IsTableNode() ) )
+ pSttStart = pSttStart->StartOfSectionNode();
+ SwNode* pEndStart = pEndNode;
+ while( pEndStart && (!pEndStart->IsStartNode() || pEndStart->IsSectionNode() ||
+ pEndStart->IsTableNode() ) )
+ pEndStart = pEndStart->StartOfSectionNode();
+ if( pSttTab != pEndTab )
+ nError = 1;
+ if( !pSttTab && pSttStart != pEndStart )
+ nError |= 2;
+ if( nError )
+ nError += 10;
+ return nError != 0;
+}
+#endif
+
+/*
+
+Text heisst, nicht von Redline "verseuchter" Text.
+
+Verhalten von Insert-Redline:
+ - im Text - Redline Object einfuegen
+ - im InsertRedline (eigenes) - ignorieren, bestehendes wird
+ aufgespannt
+ - im InsertRedline (andere) - Insert Redline aufsplitten
+ Redline Object einfuegen
+ - in DeleteRedline - Delete Redline aufsplitten oder
+ am Ende/Anfang verschieben
+
+Verhalten von Delete-Redline:
+ - im Text - Redline Object einfuegen
+ - im DeleteRedline (eigenes/andere) - ignorieren
+ - im InsertRedline (eigenes) - ignorieren, Zeichen aber loeschen
+ - im InsertRedline (andere) - Insert Redline aufsplitten
+ Redline Object einfuegen
+ - Ueberlappung von Text und - Text in eigenen Insert loeschen,
+ eigenem Insert im andereren Text aufspannen (bis
+ zum Insert!
+ - Ueberlappung von Text und - Redline Object einfuegen, der
+ anderem Insert andere Insert wird vom Delete
+ ueberlappt
+*/
+
+bool SwDoc::AppendRedline( SwRedline* pNewRedl, bool bCallDelete )
+{
+ bool bError = true;
+ _CHECK_REDLINE( this )
+
+ if( IsRedlineOn() && !IsShowOriginal( eRedlineMode ) &&
+ pNewRedl->GetAuthorString().Len() )
+ {
+ pNewRedl->InvalidateRange();
+
+ if( mbIsAutoFmtRedline )
+ {
+ pNewRedl->SetAutoFmtFlag();
+ if( pAutoFmtRedlnComment && pAutoFmtRedlnComment->Len() )
+ {
+ pNewRedl->SetComment( *pAutoFmtRedlnComment );
+ pNewRedl->SetSeqNo( nAutoFmtRedlnCommentNo );
+ }
+ }
+
+ SwPosition* pStt = pNewRedl->Start(),
+ * pEnd = pStt == pNewRedl->GetPoint() ? pNewRedl->GetMark()
+ : pNewRedl->GetPoint();
+ {
+ SwTxtNode* pTxtNode = pStt->nNode.GetNode().GetTxtNode();
+ if( pTxtNode == NULL )
+ {
+ if( pStt->nContent > 0 )
+ {
+ DBG_ASSERT( false, "Redline start: non-text-node with content" );
+ pStt->nContent = 0;
+ }
+ }
+ else
+ {
+ if( pStt->nContent > pTxtNode->Len() )
+ {
+ DBG_ASSERT( false, "Redline start: index behind text" );
+ pStt->nContent = pTxtNode->Len();
+ }
+ }
+ pTxtNode = pEnd->nNode.GetNode().GetTxtNode();
+ if( pTxtNode == NULL )
+ {
+ if( pEnd->nContent > 0 )
+ {
+ DBG_ASSERT( false, "Redline end: non-text-node with content" );
+ pEnd->nContent = 0;
+ }
+ }
+ else
+ {
+ if( pEnd->nContent > pTxtNode->Len() )
+ {
+ DBG_ASSERT( false, "Redline end: index behind text" );
+ pEnd->nContent = pTxtNode->Len();
+ }
+ }
+ }
+ if( ( *pStt == *pEnd ) &&
+ ( pNewRedl->GetContentIdx() == NULL ) )
+ { // Do not insert empty redlines
+ delete pNewRedl;
+ return sal_False;
+ }
+ sal_Bool bCompress = sal_False;
+ sal_uInt16 n = 0;
+ // zur StartPos das erste Redline suchen
+ if( !GetRedline( *pStt, &n ) && n )
+ --n;
+ bool bDec = false;
+
+ for( ; pNewRedl && n < pRedlineTbl->Count(); bDec ? n : ++n )
+ {
+ bDec = false;
+
+ SwRedline* pRedl = (*pRedlineTbl)[ n ];
+ SwPosition* pRStt = pRedl->Start(),
+ * pREnd = pRStt == pRedl->GetPoint() ? pRedl->GetMark()
+ : pRedl->GetPoint();
+
+ // #i8518# remove empty redlines while we're at it
+ if( ( *pRStt == *pREnd ) &&
+ ( pRedl->GetContentIdx() == NULL ) )
+ {
+ pRedlineTbl->DeleteAndDestroy(n);
+ continue;
+ }
+
+ SwComparePosition eCmpPos = ComparePosition( *pStt, *pEnd, *pRStt, *pREnd );
+
+ switch( pNewRedl->GetType() )
+ {
+ case nsRedlineType_t::REDLINE_INSERT:
+ switch( pRedl->GetType() )
+ {
+ case nsRedlineType_t::REDLINE_INSERT:
+ if( pRedl->IsOwnRedline( *pNewRedl ) )
+ {
+ bool bDelete = false;
+
+ // ggfs. verschmelzen?
+ if( (( POS_BEHIND == eCmpPos &&
+ IsPrevPos( *pREnd, *pStt ) ) ||
+ ( POS_COLLIDE_START == eCmpPos ) ||
+ ( POS_OVERLAP_BEHIND == eCmpPos ) ) &&
+ pRedl->CanCombine( *pNewRedl ) &&
+ ( n+1 >= pRedlineTbl->Count() ||
+ ( *(*pRedlineTbl)[ n+1 ]->Start() >= *pEnd &&
+ *(*pRedlineTbl)[ n+1 ]->Start() != *pREnd ) ) )
+ {
+ pRedl->SetEnd( *pEnd, pREnd );
+ if( !pRedl->HasValidRange() )
+ {
+ // neu einsortieren
+ pRedlineTbl->Remove( n );
+ pRedlineTbl->Insert( pRedl );
+ }
+
+ bError = false;
+ bDelete = true;
+ }
+ else if( (( POS_BEFORE == eCmpPos &&
+ IsPrevPos( *pEnd, *pRStt ) ) ||
+ ( POS_COLLIDE_END == eCmpPos ) ||
+ ( POS_OVERLAP_BEFORE == eCmpPos ) ) &&
+ pRedl->CanCombine( *pNewRedl ) &&
+ ( !n ||
+ *(*pRedlineTbl)[ n-1 ]->End() != *pRStt ))
+ {
+ pRedl->SetStart( *pStt, pRStt );
+ // neu einsortieren
+ pRedlineTbl->Remove( n );
+ pRedlineTbl->Insert( pRedl );
+
+ bError = false;
+ bDelete = true;
+ }
+ else if ( POS_OUTSIDE == eCmpPos )
+ {
+ // own insert-over-insert redlines:
+ // just scrap the inside ones
+ pRedlineTbl->Remove( n );
+ bDec = true;
+ }
+ // <--
+ else if( POS_OVERLAP_BEHIND == eCmpPos )
+ {
+ *pStt = *pREnd;
+ if( ( *pStt == *pEnd ) &&
+ ( pNewRedl->GetContentIdx() == NULL ) )
+ bDelete = true;
+ }
+ else if( POS_OVERLAP_BEFORE == eCmpPos )
+ {
+ *pEnd = *pRStt;
+ if( ( *pStt == *pEnd ) &&
+ ( pNewRedl->GetContentIdx() == NULL ) )
+ bDelete = true;
+ }
+ else if( POS_INSIDE == eCmpPos || POS_EQUAL == eCmpPos)
+ bDelete = true;
+
+ if( bDelete )
+ {
+ delete pNewRedl, pNewRedl = 0;
+ bCompress = sal_True;
+ }
+ }
+ else if( POS_INSIDE == eCmpPos )
+ {
+ // aufsplitten
+ if( *pEnd != *pREnd )
+ {
+ SwRedline* pCpy = new SwRedline( *pRedl );
+ pCpy->SetStart( *pEnd );
+ pRedlineTbl->Insert( pCpy );
+ }
+ pRedl->SetEnd( *pStt, pREnd );
+ if( ( *pStt == *pRStt ) &&
+ ( pRedl->GetContentIdx() == NULL ) )
+ {
+ pRedlineTbl->DeleteAndDestroy( n );
+ bDec = true;
+ }
+ else if( !pRedl->HasValidRange() )
+ {
+ // neu einsortieren
+ pRedlineTbl->Remove( n );
+ pRedlineTbl->Insert( pRedl );
+ }
+ }
+ else if ( POS_OUTSIDE == eCmpPos )
+ {
+ // handle overlapping redlines in broken documents
+
+ // split up the new redline, since it covers the
+ // existing redline. Insert the first part, and
+ // progress with the remainder as usual
+ SwRedline* pSplit = new SwRedline( *pNewRedl );
+ pSplit->SetEnd( *pRStt );
+ pNewRedl->SetStart( *pREnd );
+ pRedlineTbl->Insert( pSplit );
+ if( *pStt == *pEnd && pNewRedl->GetContentIdx() == NULL )
+ {
+ delete pNewRedl;
+ pNewRedl = 0;
+ bCompress = true;
+ }
+ }
+ else if ( POS_OVERLAP_BEHIND == eCmpPos )
+ {
+ // handle overlapping redlines in broken documents
+ pNewRedl->SetStart( *pREnd );
+ }
+ else if ( POS_OVERLAP_BEFORE == eCmpPos )
+ {
+ // handle overlapping redlines in broken documents
+ *pEnd = *pRStt;
+ if( ( *pStt == *pEnd ) &&
+ ( pNewRedl->GetContentIdx() == NULL ) )
+ {
+ delete pNewRedl;
+ pNewRedl = 0;
+ bCompress = true;
+ }
+ }
+ break;
+ case nsRedlineType_t::REDLINE_DELETE:
+ if( POS_INSIDE == eCmpPos )
+ {
+ // aufsplitten
+ if( *pEnd != *pREnd )
+ {
+ SwRedline* pCpy = new SwRedline( *pRedl );
+ pCpy->SetStart( *pEnd );
+ pRedlineTbl->Insert( pCpy );
+ }
+ pRedl->SetEnd( *pStt, pREnd );
+ if( ( *pStt == *pRStt ) &&
+ ( pRedl->GetContentIdx() == NULL ) )
+ {
+ pRedlineTbl->DeleteAndDestroy( n );
+ bDec = true;
+ }
+ else if( !pRedl->HasValidRange() )
+ {
+ // neu einsortieren
+ pRedlineTbl->Remove( n );
+ pRedlineTbl->Insert( pRedl, n );
+ }
+ }
+ else if ( POS_OUTSIDE == eCmpPos )
+ {
+ // handle overlapping redlines in broken documents
+
+ // split up the new redline, since it covers the
+ // existing redline. Insert the first part, and
+ // progress with the remainder as usual
+ SwRedline* pSplit = new SwRedline( *pNewRedl );
+ pSplit->SetEnd( *pRStt );
+ pNewRedl->SetStart( *pREnd );
+ pRedlineTbl->Insert( pSplit );
+ if( *pStt == *pEnd && pNewRedl->GetContentIdx() == NULL )
+ {
+ delete pNewRedl;
+ pNewRedl = 0;
+ bCompress = true;
+ }
+ }
+ else if ( POS_EQUAL == eCmpPos )
+ {
+ // handle identical redlines in broken documents
+ // delete old (delete) redline
+ pRedlineTbl->DeleteAndDestroy( n );
+ bDec = true;
+ }
+ else if ( POS_OVERLAP_BEHIND == eCmpPos )
+ { // Another workaround for broken redlines
+ pNewRedl->SetStart( *pREnd );
+ }
+ break;
+ case nsRedlineType_t::REDLINE_FORMAT:
+ switch( eCmpPos )
+ {
+ case POS_OVERLAP_BEFORE:
+ pRedl->SetStart( *pEnd, pRStt );
+ // neu einsortieren
+ pRedlineTbl->Remove( n );
+ pRedlineTbl->Insert( pRedl, n );
+ bDec = true;
+ break;
+
+ case POS_OVERLAP_BEHIND:
+ pRedl->SetEnd( *pStt, pREnd );
+ if( *pStt == *pRStt && pRedl->GetContentIdx() == NULL )
+ {
+ pRedlineTbl->DeleteAndDestroy( n );
+ bDec = true;
+ }
+ break;
+
+ case POS_EQUAL:
+ case POS_OUTSIDE:
+ // ueberlappt den akt. komplett oder hat gleiche
+ // Ausdehung, dann muss der alte geloescht werden
+ pRedlineTbl->DeleteAndDestroy( n );
+ bDec = true;
+ break;
+
+ case POS_INSIDE:
+ // ueberlappt den akt. komplett, dann muss
+ // der neue gesplittet oder verkuertzt werden
+ if( *pEnd != *pREnd )
+ {
+ if( *pEnd != *pRStt )
+ {
+ SwRedline* pNew = new SwRedline( *pRedl );
+ pNew->SetStart( *pEnd );
+ pRedl->SetEnd( *pStt, pREnd );
+ if( *pStt == *pRStt && pRedl->GetContentIdx() == NULL )
+ pRedlineTbl->DeleteAndDestroy( n );
+ AppendRedline( pNew, bCallDelete );
+ n = 0; // neu Aufsetzen
+ bDec = true;
+ }
+ }
+ else
+ pRedl->SetEnd( *pStt, pREnd );
+ break;
+ default:
+ break;
+ }
+ break;
+ default:
+ break;
+ }
+ break;
+
+ case nsRedlineType_t::REDLINE_DELETE:
+ switch( pRedl->GetType() )
+ {
+ case nsRedlineType_t::REDLINE_DELETE:
+ switch( eCmpPos )
+ {
+ case POS_OUTSIDE:
+ {
+ // ueberlappt den akt. komplett
+ // dann muss der neue gesplittet werden
+ if( *pEnd != *pREnd )
+ {
+ SwRedline* pNew = new SwRedline( *pNewRedl );
+ pNew->SetStart( *pREnd );
+ pNewRedl->SetEnd( *pRStt, pEnd );
+ AppendRedline( pNew, bCallDelete );
+ n = 0; // neu Aufsetzen
+ bDec = true;
+ }
+ else
+ pNewRedl->SetEnd( *pRStt, pEnd );
+ }
+ break;
+
+ case POS_INSIDE:
+ case POS_EQUAL:
+ delete pNewRedl, pNewRedl = 0;
+ bCompress = sal_True;
+ break;
+
+ case POS_OVERLAP_BEFORE:
+ case POS_OVERLAP_BEHIND:
+ if( pRedl->IsOwnRedline( *pNewRedl ) &&
+// 1 == pRedl->GetStackCount() &&
+ pRedl->CanCombine( *pNewRedl ))
+ {
+ // dann kann das zusammengefasst werden, sprich
+ // der neue deckt das schon ab.
+ if( POS_OVERLAP_BEHIND == eCmpPos )
+ pNewRedl->SetStart( *pRStt, pStt );
+ else
+ pNewRedl->SetEnd( *pREnd, pEnd );
+ pRedlineTbl->DeleteAndDestroy( n );
+ bDec = true;
+ }
+ else if( POS_OVERLAP_BEHIND == eCmpPos )
+ pNewRedl->SetStart( *pREnd, pStt );
+ else
+ pNewRedl->SetEnd( *pRStt, pEnd );
+ break;
+
+ case POS_COLLIDE_START:
+ case POS_COLLIDE_END:
+ if( pRedl->IsOwnRedline( *pNewRedl ) &&
+ pRedl->CanCombine( *pNewRedl ) )
+ {
+ if( IsHideChanges( eRedlineMode ))
+ {
+ // dann erstmal sichtbar machen, bevor
+ // die zusammengefasst werden koennen!
+ // Damit pNew auch beim Verschieben der
+ // Indizies behandelt wird, erstmal
+ // temporaer einfuegen
+ pRedlineTbl->SavePtrInArr( pNewRedl );
+ pRedl->Show();
+ pRedlineTbl->Remove( pRedlineTbl->GetPos(pNewRedl ));
+ pRStt = pRedl->Start();
+ pREnd = pRedl->End();
+ }
+
+ // dann kann das zusammengefasst werden, sprich
+ // der neue deckt das schon ab.
+ if( POS_COLLIDE_START == eCmpPos )
+ pNewRedl->SetStart( *pRStt, pStt );
+ else
+ pNewRedl->SetEnd( *pREnd, pEnd );
+
+ // delete current (below), and restart process with
+ // previous
+ sal_uInt16 nToBeDeleted = n;
+ bDec = true;
+
+ if( *(pNewRedl->Start()) <= *pREnd )
+ {
+ // Whoooah, we just extended the new 'redline'
+ // beyond previous redlines, so better start
+ // again. Of course this is not supposed to
+ // happen, and in an ideal world it doesn't,
+ // but unfortunately this code is buggy and
+ // totally rotten so it does happen and we
+ // better fix it.
+ n = 0;
+ bDec = true;
+ }
+
+ pRedlineTbl->DeleteAndDestroy( nToBeDeleted );
+ }
+ break;
+ default:
+ break;
+ }
+ break;
+
+ case nsRedlineType_t::REDLINE_INSERT:
+ {
+ // b62341295: Do not throw away redlines
+ // even if they are not allowed to be combined
+ RedlineMode_t eOld = eRedlineMode;
+ if( !( eOld & nsRedlineMode_t::REDLINE_DONTCOMBINE_REDLINES ) &&
+ pRedl->IsOwnRedline( *pNewRedl ) )
+ {
+
+// auf NONE setzen, damit das Delete::Redo die RedlineDaten wieder richtig
+// zusammen fasst! Der ShowMode muss erhalten bleiben!
+ eRedlineMode = (RedlineMode_t)(eOld & ~(nsRedlineMode_t::REDLINE_ON | nsRedlineMode_t::REDLINE_IGNORE));
+ switch( eCmpPos )
+ {
+ case POS_EQUAL:
+ bCompress = sal_True;
+ pRedlineTbl->DeleteAndDestroy( n );
+ bDec = true;
+ // kein break!
+
+ case POS_INSIDE:
+ if( bCallDelete )
+ {
+ eRedlineMode = (RedlineMode_t)(eRedlineMode | nsRedlineMode_t::REDLINE_IGNOREDELETE_REDLINES);
+
+ // DeleteAndJoin does not yield the
+ // desired result if there is no paragraph to
+ // join with, i.e. at the end of the document.
+ // For this case, we completely delete the
+ // paragraphs (if, of course, we also start on
+ // a paragraph boundary).
+ if( (pStt->nContent == 0) &&
+ pEnd->nNode.GetNode().IsEndNode() )
+ {
+ pEnd->nNode--;
+ pEnd->nContent.Assign(
+ pEnd->nNode.GetNode().GetTxtNode(), 0);
+ DelFullPara( *pNewRedl );
+ }
+ else
+ DeleteAndJoin( *pNewRedl );
+
+ bCompress = sal_True;
+ }
+ delete pNewRedl, pNewRedl = 0;
+ break;
+
+ case POS_OUTSIDE:
+ {
+ pRedlineTbl->Remove( n );
+ bDec = true;
+ // damit pNew auch beim Verschieben der Indizies
+ // behandelt wird, erstmal temp. einfuegen
+ if( bCallDelete )
+ {
+ pRedlineTbl->SavePtrInArr( pNewRedl );
+ DeleteAndJoin( *pRedl );
+ sal_uInt16 nFnd = pRedlineTbl->GetPos(pNewRedl );
+ if( USHRT_MAX != nFnd )
+ pRedlineTbl->Remove( nFnd );
+ else
+ pNewRedl = 0;
+ }
+ delete pRedl;
+ }
+ break;
+
+ case POS_OVERLAP_BEFORE:
+ {
+ SwPaM aPam( *pRStt, *pEnd );
+
+ if( *pEnd == *pREnd )
+ pRedlineTbl->DeleteAndDestroy( n );
+ else
+ {
+ pRedl->SetStart( *pEnd, pRStt );
+ // neu einsortieren
+ pRedlineTbl->Remove( n );
+ pRedlineTbl->Insert( pRedl, n );
+ }
+
+ if( bCallDelete )
+ {
+ // damit pNew auch beim Verschieben der Indizies
+ // behandelt wird, erstmal temp. einfuegen
+ pRedlineTbl->SavePtrInArr( pNewRedl );
+ DeleteAndJoin( aPam );
+ sal_uInt16 nFnd = pRedlineTbl->GetPos(pNewRedl );
+ if( USHRT_MAX != nFnd )
+ pRedlineTbl->Remove( nFnd );
+ else
+ pNewRedl = 0;
+ n = 0; // neu Aufsetzen
+ }
+ bDec = true;
+ }
+ break;
+
+ case POS_OVERLAP_BEHIND:
+ {
+ SwPaM aPam( *pStt, *pREnd );
+
+ if( *pStt == *pRStt )
+ {
+ pRedlineTbl->DeleteAndDestroy( n );
+ bDec = true;
+ }
+ else
+ pRedl->SetEnd( *pStt, pREnd );
+
+ if( bCallDelete )
+ {
+ // damit pNew auch beim Verschieben der Indizies
+ // behandelt wird, erstmal temp. einfuegen
+ pRedlineTbl->SavePtrInArr( pNewRedl );
+ DeleteAndJoin( aPam );
+ sal_uInt16 nFnd = pRedlineTbl->GetPos(pNewRedl );
+ if( USHRT_MAX != nFnd )
+ pRedlineTbl->Remove( nFnd );
+ else
+ pNewRedl = 0;
+ n = 0; // neu Aufsetzen
+ bDec = true;
+ }
+ }
+ break;
+ default:
+ break;
+ }
+
+ eRedlineMode = eOld;
+ }
+ else
+ {
+ // it may be necessary to split the existing redline in
+ // two. In this case, pRedl will be changed to cover
+ // only part of it's former range, and pNew will cover
+ // the remainder.
+ SwRedline* pNew = 0;
+
+ switch( eCmpPos )
+ {
+ case POS_EQUAL:
+ {
+ pRedl->PushData( *pNewRedl );
+ delete pNewRedl, pNewRedl = 0;
+ if( IsHideChanges( eRedlineMode ))
+ pRedl->Hide();
+ bCompress = sal_True;
+ }
+ break;
+
+ case POS_INSIDE:
+ {
+ if( *pRStt == *pStt )
+ {
+ // --> mst 2010-05-17 #i97421#
+ // redline w/out extent loops
+ if (*pStt != *pEnd)
+ // <--
+ {
+ pNewRedl->PushData( *pRedl, sal_False );
+ pRedl->SetStart( *pEnd, pRStt );
+ // re-insert
+ pRedlineTbl->Remove( n );
+ pRedlineTbl->Insert( pRedl, n );
+ bDec = true;
+ }
+ }
+ else
+ {
+ pNewRedl->PushData( *pRedl, sal_False );
+ if( *pREnd != *pEnd )
+ {
+ pNew = new SwRedline( *pRedl );
+ pNew->SetStart( *pEnd );
+ }
+ pRedl->SetEnd( *pStt, pREnd );
+ if( !pRedl->HasValidRange() )
+ {
+ // neu einsortieren
+ pRedlineTbl->Remove( n );
+ pRedlineTbl->Insert( pRedl, n );
+ }
+ }
+ }
+ break;
+
+ case POS_OUTSIDE:
+ {
+ pRedl->PushData( *pNewRedl );
+ if( *pEnd == *pREnd )
+ pNewRedl->SetEnd( *pRStt, pEnd );
+ else
+ {
+ pNew = new SwRedline( *pNewRedl );
+ pNew->SetEnd( *pRStt );
+ pNewRedl->SetStart( *pREnd, pStt );
+ }
+ bCompress = sal_True;
+ }
+ break;
+
+ case POS_OVERLAP_BEFORE:
+ {
+ if( *pEnd == *pREnd )
+ {
+ pRedl->PushData( *pNewRedl );
+ pNewRedl->SetEnd( *pRStt, pEnd );
+ if( IsHideChanges( eRedlineMode ))
+ {
+ pRedlineTbl->SavePtrInArr( pNewRedl );
+ pRedl->Hide();
+ pRedlineTbl->Remove(
+ pRedlineTbl->GetPos(pNewRedl ));
+ }
+ }
+ else
+ {
+ pNew = new SwRedline( *pRedl );
+ pNew->PushData( *pNewRedl );
+ pNew->SetEnd( *pEnd );
+ pNewRedl->SetEnd( *pRStt, pEnd );
+ pRedl->SetStart( *pNew->End(), pRStt ) ;
+ // neu einsortieren
+ pRedlineTbl->Remove( n );
+ pRedlineTbl->Insert( pRedl );
+ bDec = true;
+ }
+ }
+ break;
+
+ case POS_OVERLAP_BEHIND:
+ {
+ if( *pStt == *pRStt )
+ {
+ pRedl->PushData( *pNewRedl );
+ pNewRedl->SetStart( *pREnd, pStt );
+ if( IsHideChanges( eRedlineMode ))
+ {
+ pRedlineTbl->SavePtrInArr( pNewRedl );
+ pRedl->Hide();
+ pRedlineTbl->Remove(
+ pRedlineTbl->GetPos(pNewRedl ));
+ }
+ }
+ else
+ {
+ pNew = new SwRedline( *pRedl );
+ pNew->PushData( *pNewRedl );
+ pNew->SetStart( *pStt );
+ pNewRedl->SetStart( *pREnd, pStt );
+ pRedl->SetEnd( *pNew->Start(), pREnd );
+ if( !pRedl->HasValidRange() )
+ {
+ // neu einsortieren
+ pRedlineTbl->Remove( n );
+ pRedlineTbl->Insert( pRedl );
+ }
+ }
+ }
+ break;
+ default:
+ break;
+ }
+
+ // insert the pNew part (if it exists)
+ if( pNew )
+ {
+ pRedlineTbl->Insert( pNew );
+
+ // pNew must be deleted if Insert() wasn't
+ // successful. But that can't happen, since pNew is
+ // part of the original pRedl redline.
+ // OSL_ENSURE( bRet, "Can't insert existing redline?" );
+
+ // restart (now with pRedl being split up)
+ n = 0;
+ bDec = true;
+ }
+ }
+ }
+ break;
+
+ case nsRedlineType_t::REDLINE_FORMAT:
+ switch( eCmpPos )
+ {
+ case POS_OVERLAP_BEFORE:
+ pRedl->SetStart( *pEnd, pRStt );
+ // neu einsortieren
+ pRedlineTbl->Remove( n );
+ pRedlineTbl->Insert( pRedl, n );
+ bDec = true;
+ break;
+
+ case POS_OVERLAP_BEHIND:
+ pRedl->SetEnd( *pStt, pREnd );
+ break;
+
+ case POS_EQUAL:
+ case POS_OUTSIDE:
+ // ueberlappt den akt. komplett oder hat gleiche
+ // Ausdehung, dann muss der alte geloescht werden
+ pRedlineTbl->DeleteAndDestroy( n );
+ bDec = true;
+ break;
+
+ case POS_INSIDE:
+ // ueberlappt den akt. komplett, dann muss
+ // der neue gesplittet oder verkuertzt werden
+ if( *pEnd != *pREnd )
+ {
+ if( *pEnd != *pRStt )
+ {
+ SwRedline* pNew = new SwRedline( *pRedl );
+ pNew->SetStart( *pEnd );
+ pRedl->SetEnd( *pStt, pREnd );
+ if( ( *pStt == *pRStt ) &&
+ ( pRedl->GetContentIdx() == NULL ) )
+ pRedlineTbl->DeleteAndDestroy( n );
+ AppendRedline( pNew, bCallDelete );
+ n = 0; // neu Aufsetzen
+ bDec = true;
+ }
+ }
+ else
+ pRedl->SetEnd( *pStt, pREnd );
+ break;
+ default:
+ break;
+ }
+ break;
+ default:
+ break;
+ }
+ break;
+
+ case nsRedlineType_t::REDLINE_FORMAT:
+ switch( pRedl->GetType() )
+ {
+ case nsRedlineType_t::REDLINE_INSERT:
+ case nsRedlineType_t::REDLINE_DELETE:
+ switch( eCmpPos )
+ {
+ case POS_OVERLAP_BEFORE:
+ pNewRedl->SetEnd( *pRStt, pEnd );
+ break;
+
+ case POS_OVERLAP_BEHIND:
+ pNewRedl->SetStart( *pREnd, pStt );
+ break;
+
+ case POS_EQUAL:
+ case POS_INSIDE:
+ delete pNewRedl, pNewRedl = 0;
+ break;
+
+ case POS_OUTSIDE:
+ // ueberlappt den akt. komplett, dann muss
+ // der neue gesplittet oder verkuerzt werden
+ if( *pEnd != *pREnd )
+ {
+ if( *pEnd != *pRStt )
+ {
+ SwRedline* pNew = new SwRedline( *pNewRedl );
+ pNew->SetStart( *pREnd );
+ pNewRedl->SetEnd( *pRStt, pEnd );
+ AppendRedline( pNew, bCallDelete );
+ n = 0; // neu Aufsetzen
+ bDec = true;
+ }
+ }
+ else
+ pNewRedl->SetEnd( *pRStt, pEnd );
+ break;
+ default:
+ break;
+ }
+ break;
+ case nsRedlineType_t::REDLINE_FORMAT:
+ switch( eCmpPos )
+ {
+ case POS_OUTSIDE:
+ case POS_EQUAL:
+ {
+ // ueberlappt den akt. komplett oder hat gleiche
+ // Ausdehnung, dann muss der alte geloescht werden
+ pRedlineTbl->DeleteAndDestroy( n );
+ bDec = true;
+ }
+ break;
+
+ case POS_INSIDE:
+ if( pRedl->IsOwnRedline( *pNewRedl ) &&
+ pRedl->CanCombine( *pNewRedl ))
+ // ein eigenes kann komplett ignoriert werden
+ delete pNewRedl, pNewRedl = 0;
+
+ else if( *pREnd == *pEnd )
+ // ansonsten nur den akt. verkuerzen
+ pRedl->SetEnd( *pStt, pREnd );
+ else if( *pRStt == *pStt )
+ {
+ // ansonsten nur den akt. verkuerzen
+ pRedl->SetStart( *pEnd, pRStt );
+ // neu einsortieren
+ pRedlineTbl->Remove( n );
+ pRedlineTbl->Insert( pRedl, n );
+ bDec = true;
+ }
+ else
+ {
+ // liegt komplett im akt.
+ // dann muss der gesplittet werden
+ SwRedline* pNew = new SwRedline( *pRedl );
+ pNew->SetStart( *pEnd );
+ pRedl->SetEnd( *pStt, pREnd );
+ AppendRedline( pNew, bCallDelete );
+ n = 0; // neu Aufsetzen
+ bDec = true;
+ }
+ break;
+
+ case POS_OVERLAP_BEFORE:
+ case POS_OVERLAP_BEHIND:
+ if( pRedl->IsOwnRedline( *pNewRedl ) &&
+ pRedl->CanCombine( *pNewRedl ))
+ {
+ // dann kann das zusammengefasst werden, sprich
+ // der neue deckt das schon ab.
+ if( POS_OVERLAP_BEHIND == eCmpPos )
+ pNewRedl->SetStart( *pRStt, pStt );
+ else
+ pNewRedl->SetEnd( *pREnd, pEnd );
+ pRedlineTbl->DeleteAndDestroy( n );
+ bDec = 0;
+ }
+ else if( POS_OVERLAP_BEHIND == eCmpPos )
+ pNewRedl->SetStart( *pREnd, pStt );
+ else
+ pNewRedl->SetEnd( *pRStt, pEnd );
+ break;
+
+ case POS_COLLIDE_END:
+ if( pRedl->IsOwnRedline( *pNewRedl ) &&
+ pRedl->CanCombine( *pNewRedl ) && n &&
+ *(*pRedlineTbl)[ n-1 ]->End() < *pStt )
+ {
+ // dann kann das zusammengefasst werden, sprich
+ // der neue deckt das schon ab.
+ pNewRedl->SetEnd( *pREnd, pEnd );
+ pRedlineTbl->DeleteAndDestroy( n );
+ bDec = true;
+ }
+ break;
+ case POS_COLLIDE_START:
+ if( pRedl->IsOwnRedline( *pNewRedl ) &&
+ pRedl->CanCombine( *pNewRedl ) &&
+ n+1 < pRedlineTbl->Count() &&
+ *(*pRedlineTbl)[ n+1 ]->Start() < *pEnd )
+ {
+ // dann kann das zusammengefasst werden, sprich
+ // der neue deckt das schon ab.
+ pNewRedl->SetStart( *pRStt, pStt );
+ pRedlineTbl->DeleteAndDestroy( n );
+ bDec = true;
+ }
+ break;
+ default:
+ break;
+ }
+ break;
+ default:
+ break;
+ }
+ break;
+
+
+ case nsRedlineType_t::REDLINE_FMTCOLL:
+ // wie soll das verhalten sein????
+ // erstmal so einfuegen
+ break;
+ default:
+ break;
+ }
+ }
+
+ if( pNewRedl )
+ {
+ if( ( *pStt == *pEnd ) &&
+ ( pNewRedl->GetContentIdx() == NULL ) )
+ { // Do not insert empty redlines
+ delete pNewRedl;
+ pNewRedl = 0;
+ }
+ else
+ pRedlineTbl->Insert( pNewRedl );
+ }
+
+ if( bCompress )
+ CompressRedlines();
+ }
+ else
+ {
+ if( bCallDelete && nsRedlineType_t::REDLINE_DELETE == pNewRedl->GetType() )
+ {
+ RedlineMode_t eOld = eRedlineMode;
+// auf NONE setzen, damit das Delete::Redo die RedlineDaten wieder richtig
+// zusammen fasst! Der ShowMode muss erhalten bleiben!
+ eRedlineMode = (RedlineMode_t)(eOld & ~(nsRedlineMode_t::REDLINE_ON | nsRedlineMode_t::REDLINE_IGNORE));
+ DeleteAndJoin( *pNewRedl );
+ eRedlineMode = eOld;
+ }
+ delete pNewRedl, pNewRedl = 0;
+ }
+ _CHECK_REDLINE( this )
+
+ return ( 0 != pNewRedl ) || !bError;
+}
+
+void SwDoc::CompressRedlines()
+{
+ _CHECK_REDLINE( this )
+
+ void (SwRedline::*pFnc)(sal_uInt16) = 0;
+ switch( nsRedlineMode_t::REDLINE_SHOW_MASK & eRedlineMode )
+ {
+ case nsRedlineMode_t::REDLINE_SHOW_INSERT | nsRedlineMode_t::REDLINE_SHOW_DELETE:
+ pFnc = &SwRedline::Show;
+ break;
+ case nsRedlineMode_t::REDLINE_SHOW_INSERT:
+ pFnc = &SwRedline::Hide;
+ break;
+ }
+
+ // versuche gleiche zusammenzufassen
+ for( sal_uInt16 n = 1; n < pRedlineTbl->Count(); ++n )
+ {
+ SwRedline* pPrev = (*pRedlineTbl)[ n-1 ],
+ * pCur = (*pRedlineTbl)[ n ];
+ const SwPosition* pPrevStt = pPrev->Start(),
+ * pPrevEnd = pPrevStt == pPrev->GetPoint()
+ ? pPrev->GetMark() : pPrev->GetPoint();
+ const SwPosition* pCurStt = pCur->Start(),
+ * pCurEnd = pCurStt == pCur->GetPoint()
+ ? pCur->GetMark() : pCur->GetPoint();
+ if( *pPrevEnd == *pCurStt && pPrev->CanCombine( *pCur ) &&
+ pPrevStt->nNode.GetNode().StartOfSectionNode() ==
+ pCurEnd->nNode.GetNode().StartOfSectionNode() &&
+ !pCurEnd->nNode.GetNode().StartOfSectionNode()->IsTableNode() )
+ {
+ // dann koennen die zusammen gefasst werden
+ pPrev->Show();
+ pCur->Show();
+
+ pPrev->SetEnd( *pCur->End() );
+ pRedlineTbl->DeleteAndDestroy( n );
+ --n;
+ if( pFnc )
+ (pPrev->*pFnc)(0);
+ }
+ }
+ _CHECK_REDLINE( this )
+}
+
+bool SwDoc::SplitRedline( const SwPaM& rRange )
+{
+ sal_Bool bChg = sal_False;
+ sal_uInt16 n = 0;
+ const SwPosition* pStt = rRange.Start(),
+ * pEnd = pStt == rRange.GetPoint() ? rRange.GetMark()
+ : rRange.GetPoint();
+ GetRedline( *pStt, &n );
+ for( ; n < pRedlineTbl->Count() ; ++n )
+ {
+ SwRedline* pTmp = (*pRedlineTbl)[ n ];
+ SwPosition* pTStt = pTmp->Start(),
+ * pTEnd = pTStt == pTmp->GetPoint() ? pTmp->GetMark()
+ : pTmp->GetPoint();
+ if( *pTStt <= *pStt && *pStt <= *pTEnd &&
+ *pTStt <= *pEnd && *pEnd <= *pTEnd )
+ {
+ bChg = sal_True;
+ int nn = 0;
+ if( *pStt == *pTStt )
+ nn += 1;
+ if( *pEnd == *pTEnd )
+ nn += 2;
+
+ SwRedline* pNew = 0;
+ switch( nn )
+ {
+ case 0:
+ pNew = new SwRedline( *pTmp );
+ pTmp->SetEnd( *pStt, pTEnd );
+ pNew->SetStart( *pEnd );
+ break;
+
+ case 1:
+ *pTStt = *pEnd;
+ break;
+
+ case 2:
+ *pTEnd = *pStt;
+ break;
+
+ case 3:
+ pTmp->InvalidateRange();
+ pRedlineTbl->DeleteAndDestroy( n-- );
+ pTmp = 0;
+ break;
+ }
+ if( pTmp && !pTmp->HasValidRange() )
+ {
+ // neu einsortieren
+ pRedlineTbl->Remove( n );
+ pRedlineTbl->Insert( pTmp, n );
+ }
+ if( pNew )
+ pRedlineTbl->Insert( pNew, n );
+ }
+ else if( *pEnd < *pTStt )
+ break;
+ }
+ return bChg;
+}
+
+bool SwDoc::DeleteRedline( const SwPaM& rRange, bool bSaveInUndo,
+ sal_uInt16 nDelType )
+{
+ if( nsRedlineMode_t::REDLINE_IGNOREDELETE_REDLINES & eRedlineMode ||
+ !rRange.HasMark() || *rRange.GetMark() == *rRange.GetPoint() )
+ return sal_False;
+
+ sal_Bool bChg = sal_False;
+
+ if (bSaveInUndo && GetIDocumentUndoRedo().DoesUndo())
+ {
+ SwUndoRedline* pUndo = new SwUndoRedline( UNDO_REDLINE, rRange );
+ if( pUndo->GetRedlSaveCount() )
+ {
+ GetIDocumentUndoRedo().AppendUndo(pUndo);
+ }
+ else
+ delete pUndo;
+ }
+
+ const SwPosition* pStt = rRange.Start(),
+ * pEnd = pStt == rRange.GetPoint() ? rRange.GetMark()
+ : rRange.GetPoint();
+ sal_uInt16 n = 0;
+ GetRedline( *pStt, &n );
+ for( ; n < pRedlineTbl->Count() ; ++n )
+ {
+ SwRedline* pRedl = (*pRedlineTbl)[ n ];
+ if( USHRT_MAX != nDelType && nDelType != pRedl->GetType() )
+ continue;
+
+ SwPosition* pRStt = pRedl->Start(),
+ * pREnd = pRStt == pRedl->GetPoint() ? pRedl->GetMark()
+ : pRedl->GetPoint();
+ sal_Bool bDel = sal_False;
+ switch( ComparePosition( *pStt, *pEnd, *pRStt, *pREnd ) )
+ {
+ case POS_EQUAL:
+ case POS_OUTSIDE:
+ bDel = sal_True;
+ break;
+
+ case POS_OVERLAP_BEFORE:
+ if( *pEnd == *pREnd )
+ bDel = sal_True;
+ else
+ {
+ pRedl->InvalidateRange();
+ pRedl->SetStart( *pEnd, pRStt );
+ // neu einsortieren
+ pRedlineTbl->Remove( n );
+ pRedlineTbl->Insert( pRedl );
+ --n;
+ }
+ break;
+
+ case POS_OVERLAP_BEHIND:
+ if( *pStt == *pRStt )
+ bDel = sal_True;
+ else
+ {
+ pRedl->InvalidateRange();
+ pRedl->SetEnd( *pStt, pREnd );
+ if( !pRedl->HasValidRange() )
+ {
+ // neu einsortieren
+ pRedlineTbl->Remove( n );
+ pRedlineTbl->Insert( pRedl );
+ --n;
+ }
+ }
+ break;
+
+ case POS_INSIDE:
+ {
+ // der muss gesplittet werden
+ pRedl->InvalidateRange();
+ if( *pRStt == *pStt )
+ {
+ pRedl->SetStart( *pEnd, pRStt );
+ // neu einsortieren
+ pRedlineTbl->Remove( n );
+ pRedlineTbl->Insert( pRedl );
+ --n;
+ }
+ else
+ {
+ SwRedline* pCpy;
+ if( *pREnd != *pEnd )
+ {
+ pCpy = new SwRedline( *pRedl );
+ pCpy->SetStart( *pEnd );
+ }
+ else
+ pCpy = 0;
+ pRedl->SetEnd( *pStt, pREnd );
+ if( !pRedl->HasValidRange() )
+ {
+ // neu einsortieren
+ pRedlineTbl->Remove( pRedlineTbl->GetPos( pRedl ));
+ pRedlineTbl->Insert( pRedl );
+ --n;
+ }
+ if( pCpy )
+ pRedlineTbl->Insert( pCpy );
+ }
+ }
+ break;
+
+ case POS_COLLIDE_END:
+ case POS_BEFORE:
+ n = pRedlineTbl->Count();
+ break;
+ default:
+ break;
+ }
+
+ if( bDel )
+ {
+ pRedl->InvalidateRange();
+ pRedlineTbl->DeleteAndDestroy( n-- );
+ bChg = sal_True;
+ }
+ }
+
+ if( bChg )
+ SetModified();
+
+ return bChg;
+}
+
+bool SwDoc::DeleteRedline( const SwStartNode& rNode, bool bSaveInUndo,
+ sal_uInt16 nDelType )
+{
+ SwPaM aTemp(*rNode.EndOfSectionNode(), rNode);
+ return DeleteRedline(aTemp, bSaveInUndo, nDelType);
+}
+
+sal_uInt16 SwDoc::GetRedlinePos( const SwNode& rNd, sal_uInt16 nType ) const
+{
+ const sal_uLong nNdIdx = rNd.GetIndex();
+ for( sal_uInt16 n = 0; n < pRedlineTbl->Count() ; ++n )
+ {
+ const SwRedline* pTmp = (*pRedlineTbl)[ n ];
+ sal_uLong nPt = pTmp->GetPoint()->nNode.GetIndex(),
+ nMk = pTmp->GetMark()->nNode.GetIndex();
+ if( nPt < nMk ) { long nTmp = nMk; nMk = nPt; nPt = nTmp; }
+
+ if( ( USHRT_MAX == nType || nType == pTmp->GetType()) &&
+ nMk <= nNdIdx && nNdIdx <= nPt )
+ return n;
+
+ if( nMk > nNdIdx )
+ break;
+ }
+ return USHRT_MAX;
+}
+
+const SwRedline* SwDoc::GetRedline( const SwPosition& rPos,
+ sal_uInt16* pFndPos ) const
+{
+ sal_uInt16 nO = pRedlineTbl->Count(), nM, nU = 0;
+ if( nO > 0 )
+ {
+ nO--;
+ while( nU <= nO )
+ {
+ nM = nU + ( nO - nU ) / 2;
+ const SwRedline* pRedl = (*pRedlineTbl)[ nM ];
+ const SwPosition* pStt = pRedl->Start();
+ const SwPosition* pEnd = pStt == pRedl->GetPoint()
+ ? pRedl->GetMark()
+ : pRedl->GetPoint();
+ if( pEnd == pStt
+ ? *pStt == rPos
+ : ( *pStt <= rPos && rPos < *pEnd ) )
+ {
+ while( nM && rPos == *(*pRedlineTbl)[ nM - 1 ]->End() &&
+ rPos == *(*pRedlineTbl)[ nM - 1 ]->Start() )
+ {
+ --nM;
+ pRedl = (*pRedlineTbl)[ nM ];
+ }
+ // if there are format and insert changes in the same position
+ // show insert change first.
+ // since the redlines are sorted by position, only check the redline
+ // before and after the current redline
+ if( nsRedlineType_t::REDLINE_FORMAT == pRedl->GetType() )
+ {
+ if( nM && rPos >= *(*pRedlineTbl)[ nM - 1 ]->Start() &&
+ rPos <= *(*pRedlineTbl)[ nM - 1 ]->End() &&
+ ( nsRedlineType_t::REDLINE_INSERT == (*pRedlineTbl)[ nM - 1 ]->GetType() ) )
+ {
+ --nM;
+ pRedl = (*pRedlineTbl)[ nM ];
+ }
+ else if( ( nM + 1 ) <= nO && rPos >= *(*pRedlineTbl)[ nM + 1 ]->Start() &&
+ rPos <= *(*pRedlineTbl)[ nM + 1 ]->End() &&
+ ( nsRedlineType_t::REDLINE_INSERT == (*pRedlineTbl)[ nM + 1 ]->GetType() ) )
+ {
+ ++nM;
+ pRedl = (*pRedlineTbl)[ nM ];
+ }
+ }
+
+ if( pFndPos )
+ *pFndPos = nM;
+ return pRedl;
+ }
+ else if( *pEnd <= rPos )
+ nU = nM + 1;
+ else if( nM == 0 )
+ {
+ if( pFndPos )
+ *pFndPos = nU;
+ return 0;
+ }
+ else
+ nO = nM - 1;
+ }
+ }
+ if( pFndPos )
+ *pFndPos = nU;
+ return 0;
+}
+
+typedef sal_Bool (*Fn_AcceptReject)( SwRedlineTbl& rArr, sal_uInt16& rPos,
+ sal_Bool bCallDelete,
+ const SwPosition* pSttRng,
+ const SwPosition* pEndRng);
+
+sal_Bool lcl_AcceptRedline( SwRedlineTbl& rArr, sal_uInt16& rPos,
+ sal_Bool bCallDelete,
+ const SwPosition* pSttRng = 0,
+ const SwPosition* pEndRng = 0 )
+{
+ sal_Bool bRet = sal_True;
+ SwRedline* pRedl = rArr[ rPos ];
+ SwPosition *pRStt = 0, *pREnd = 0;
+ SwComparePosition eCmp = POS_OUTSIDE;
+ if( pSttRng && pEndRng )
+ {
+ pRStt = pRedl->Start();
+ pREnd = pRedl->End();
+ eCmp = ComparePosition( *pSttRng, *pEndRng, *pRStt, *pREnd );
+ }
+
+ pRedl->InvalidateRange();
+
+ switch( pRedl->GetType() )
+ {
+ case nsRedlineType_t::REDLINE_INSERT:
+ case nsRedlineType_t::REDLINE_FORMAT:
+ {
+ sal_Bool bCheck = sal_False, bReplace = sal_False;
+ switch( eCmp )
+ {
+ case POS_INSIDE:
+ if( *pSttRng == *pRStt )
+ pRedl->SetStart( *pEndRng, pRStt );
+ else
+ {
+ if( *pEndRng != *pREnd )
+ {
+ // aufsplitten
+ SwRedline* pNew = new SwRedline( *pRedl );
+ pNew->SetStart( *pEndRng );
+ rArr.Insert( pNew ); ++rPos;
+ }
+ pRedl->SetEnd( *pSttRng, pREnd );
+ bCheck = sal_True;
+ }
+ break;
+
+ case POS_OVERLAP_BEFORE:
+ pRedl->SetStart( *pEndRng, pRStt );
+ bReplace = sal_True;
+ break;
+
+ case POS_OVERLAP_BEHIND:
+ pRedl->SetEnd( *pSttRng, pREnd );
+ bCheck = sal_True;
+ break;
+
+ case POS_OUTSIDE:
+ case POS_EQUAL:
+ rArr.DeleteAndDestroy( rPos-- );
+ break;
+
+ default:
+ bRet = sal_False;
+ }
+
+ if( bReplace || ( bCheck && !pRedl->HasValidRange() ))
+ {
+ // neu einsortieren
+ rArr.Remove( rArr.GetPos( pRedl ));
+ rArr.Insert( pRedl );
+ }
+ }
+ break;
+ case nsRedlineType_t::REDLINE_DELETE:
+ {
+ SwDoc& rDoc = *pRedl->GetDoc();
+ const SwPosition *pDelStt = 0, *pDelEnd = 0;
+ sal_Bool bDelRedl = sal_False;
+ switch( eCmp )
+ {
+ case POS_INSIDE:
+ if( bCallDelete )
+ {
+ pDelStt = pSttRng;
+ pDelEnd = pEndRng;
+ }
+ break;
+
+ case POS_OVERLAP_BEFORE:
+ if( bCallDelete )
+ {
+ pDelStt = pRStt;
+ pDelEnd = pEndRng;
+ }
+ break;
+ case POS_OVERLAP_BEHIND:
+ if( bCallDelete )
+ {
+ pDelStt = pREnd;
+ pDelEnd = pSttRng;
+ }
+ break;
+
+ case POS_OUTSIDE:
+ case POS_EQUAL:
+ {
+ rArr.Remove( rPos-- );
+ bDelRedl = sal_True;
+ if( bCallDelete )
+ {
+ pDelStt = pRedl->Start();
+ pDelEnd = pRedl->End();
+ }
+ }
+ break;
+ default:
+ bRet = sal_False;
+ }
+
+ if( pDelStt && pDelEnd )
+ {
+ SwPaM aPam( *pDelStt, *pDelEnd );
+ SwCntntNode* pCSttNd = pDelStt->nNode.GetNode().GetCntntNode();
+ SwCntntNode* pCEndNd = pDelEnd->nNode.GetNode().GetCntntNode();
+
+ if( bDelRedl )
+ delete pRedl;
+
+ RedlineMode_t eOld = rDoc.GetRedlineMode();
+ rDoc.SetRedlineMode_intern( (RedlineMode_t)(eOld & ~(nsRedlineMode_t::REDLINE_ON | nsRedlineMode_t::REDLINE_IGNORE)));
+
+ if( pCSttNd && pCEndNd )
+ rDoc.DeleteAndJoin( aPam );
+ else
+ {
+ rDoc.DeleteRange( aPam );
+
+ if( pCSttNd && !pCEndNd )
+ {
+ aPam.GetBound( sal_True ).nContent.Assign( 0, 0 );
+ aPam.GetBound( sal_False ).nContent.Assign( 0, 0 );
+ aPam.DeleteMark();
+ rDoc.DelFullPara( aPam );
+ }
+ }
+ rDoc.SetRedlineMode_intern( eOld );
+ }
+ else if( bDelRedl )
+ delete pRedl;
+ }
+ break;
+
+ case nsRedlineType_t::REDLINE_FMTCOLL:
+ rArr.DeleteAndDestroy( rPos-- );
+ break;
+
+ default:
+ bRet = sal_False;
+ }
+ return bRet;
+}
+
+sal_Bool lcl_RejectRedline( SwRedlineTbl& rArr, sal_uInt16& rPos,
+ sal_Bool bCallDelete,
+ const SwPosition* pSttRng = 0,
+ const SwPosition* pEndRng = 0 )
+{
+ sal_Bool bRet = sal_True;
+ SwRedline* pRedl = rArr[ rPos ];
+ SwPosition *pRStt = 0, *pREnd = 0;
+ SwComparePosition eCmp = POS_OUTSIDE;
+ if( pSttRng && pEndRng )
+ {
+ pRStt = pRedl->Start();
+ pREnd = pRedl->End();
+ eCmp = ComparePosition( *pSttRng, *pEndRng, *pRStt, *pREnd );
+ }
+
+ pRedl->InvalidateRange();
+
+ switch( pRedl->GetType() )
+ {
+ case nsRedlineType_t::REDLINE_INSERT:
+ {
+ SwDoc& rDoc = *pRedl->GetDoc();
+ const SwPosition *pDelStt = 0, *pDelEnd = 0;
+ sal_Bool bDelRedl = sal_False;
+ switch( eCmp )
+ {
+ case POS_INSIDE:
+ if( bCallDelete )
+ {
+ pDelStt = pSttRng;
+ pDelEnd = pEndRng;
+ }
+ break;
+
+ case POS_OVERLAP_BEFORE:
+ if( bCallDelete )
+ {
+ pDelStt = pRStt;
+ pDelEnd = pEndRng;
+ }
+ break;
+ case POS_OVERLAP_BEHIND:
+ if( bCallDelete )
+ {
+ pDelStt = pREnd;
+ pDelEnd = pSttRng;
+ }
+ break;
+ case POS_OUTSIDE:
+ case POS_EQUAL:
+ {
+ // dann den Bereich wieder loeschen
+ rArr.Remove( rPos-- );
+ bDelRedl = sal_True;
+ if( bCallDelete )
+ {
+ pDelStt = pRedl->Start();
+ pDelEnd = pRedl->End();
+ }
+ }
+ break;
+
+ default:
+ bRet = sal_False;
+ }
+ if( pDelStt && pDelEnd )
+ {
+ SwPaM aPam( *pDelStt, *pDelEnd );
+
+ SwCntntNode* pCSttNd = pDelStt->nNode.GetNode().GetCntntNode();
+ SwCntntNode* pCEndNd = pDelEnd->nNode.GetNode().GetCntntNode();
+
+ if( bDelRedl )
+ delete pRedl;
+
+ RedlineMode_t eOld = rDoc.GetRedlineMode();
+ rDoc.SetRedlineMode_intern( (RedlineMode_t)(eOld & ~(nsRedlineMode_t::REDLINE_ON | nsRedlineMode_t::REDLINE_IGNORE)));
+
+ if( pCSttNd && pCEndNd )
+ rDoc.DeleteAndJoin( aPam );
+ else
+ {
+ rDoc.DeleteRange( aPam );
+
+ if( pCSttNd && !pCEndNd )
+ {
+ aPam.GetBound( sal_True ).nContent.Assign( 0, 0 );
+ aPam.GetBound( sal_False ).nContent.Assign( 0, 0 );
+ aPam.DeleteMark();
+ rDoc.DelFullPara( aPam );
+ }
+ }
+ rDoc.SetRedlineMode_intern( eOld );
+ }
+ else if( bDelRedl )
+ delete pRedl;
+ }
+ break;
+ case nsRedlineType_t::REDLINE_DELETE:
+ {
+ SwRedline* pNew = 0;
+ sal_Bool bCheck = sal_False, bReplace = sal_False;
+
+ switch( eCmp )
+ {
+ case POS_INSIDE:
+ {
+ if( 1 < pRedl->GetStackCount() )
+ {
+ pNew = new SwRedline( *pRedl );
+ pNew->PopData();
+ }
+ if( *pSttRng == *pRStt )
+ {
+ pRedl->SetStart( *pEndRng, pRStt );
+ bReplace = sal_True;
+ if( pNew )
+ pNew->SetEnd( *pEndRng );
+ }
+ else
+ {
+ if( *pEndRng != *pREnd )
+ {
+ // aufsplitten
+ SwRedline* pCpy = new SwRedline( *pRedl );
+ pCpy->SetStart( *pEndRng );
+ rArr.Insert( pCpy ); ++rPos;
+ if( pNew )
+ pNew->SetEnd( *pEndRng );
+ }
+
+ pRedl->SetEnd( *pSttRng, pREnd );
+ bCheck = sal_True;
+ if( pNew )
+ pNew->SetStart( *pSttRng );
+ }
+ }
+ break;
+
+ case POS_OVERLAP_BEFORE:
+ if( 1 < pRedl->GetStackCount() )
+ {
+ pNew = new SwRedline( *pRedl );
+ pNew->PopData();
+ }
+ pRedl->SetStart( *pEndRng, pRStt );
+ bReplace = sal_True;
+ if( pNew )
+ pNew->SetEnd( *pEndRng );
+ break;
+
+ case POS_OVERLAP_BEHIND:
+ if( 1 < pRedl->GetStackCount() )
+ {
+ pNew = new SwRedline( *pRedl );
+ pNew->PopData();
+ }
+ pRedl->SetEnd( *pSttRng, pREnd );
+ bCheck = sal_True;
+ if( pNew )
+ pNew->SetStart( *pSttRng );
+ break;
+
+ case POS_OUTSIDE:
+ case POS_EQUAL:
+ if( !pRedl->PopData() )
+ // das RedlineObject loeschen reicht
+ rArr.DeleteAndDestroy( rPos-- );
+ break;
+
+ default:
+ bRet = sal_False;
+ }
+
+ if( pNew )
+ {
+ rArr.Insert( pNew ); ++rPos;
+ }
+
+ if( bReplace || ( bCheck && !pRedl->HasValidRange() ))
+ {
+ // neu einsortieren
+ rArr.Remove( rArr.GetPos( pRedl ));
+ rArr.Insert( pRedl );
+ }
+ }
+ break;
+
+ case nsRedlineType_t::REDLINE_FORMAT:
+ case nsRedlineType_t::REDLINE_FMTCOLL:
+ {
+ if( pRedl->GetExtraData() )
+ pRedl->GetExtraData()->Reject( *pRedl );
+ rArr.DeleteAndDestroy( rPos-- );
+ }
+ break;
+
+ default:
+ bRet = sal_False;
+ }
+ return bRet;
+}
+
+
+const SwRedline* lcl_FindCurrRedline( const SwPosition& rSttPos,
+ sal_uInt16& rPos,
+ sal_Bool bNext = sal_True )
+{
+ const SwRedline* pFnd = 0;
+ const SwRedlineTbl& rArr = rSttPos.nNode.GetNode().GetDoc()->GetRedlineTbl();
+ for( ; rPos < rArr.Count() ; ++rPos )
+ {
+ const SwRedline* pTmp = rArr[ rPos ];
+ if( pTmp->HasMark() && pTmp->IsVisible() )
+ {
+ const SwPosition* pRStt = pTmp->Start(),
+ * pREnd = pRStt == pTmp->GetPoint() ? pTmp->GetMark()
+ : pTmp->GetPoint();
+ if( bNext ? *pRStt <= rSttPos : *pRStt < rSttPos )
+ {
+ if( bNext ? *pREnd > rSttPos : *pREnd >= rSttPos )
+ {
+ pFnd = pTmp;
+ break;
+ }
+ }
+ else
+ break;
+ }
+ }
+ return pFnd;
+}
+
+int lcl_AcceptRejectRedl( Fn_AcceptReject fn_AcceptReject,
+ SwRedlineTbl& rArr, sal_Bool bCallDelete,
+ const SwPaM& rPam)
+{
+ sal_uInt16 n = 0;
+ int nCount = 0;
+
+ const SwPosition* pStt = rPam.Start(),
+ * pEnd = pStt == rPam.GetPoint() ? rPam.GetMark()
+ : rPam.GetPoint();
+ const SwRedline* pFnd = lcl_FindCurrRedline( *pStt, n, sal_True );
+ if( pFnd && // neu ein Teil davon?
+ ( *pFnd->Start() != *pStt || *pFnd->End() > *pEnd ))
+ {
+ // dann nur die TeilSelektion aufheben
+ if( (*fn_AcceptReject)( rArr, n, bCallDelete, pStt, pEnd ))
+ nCount++;
+ ++n;
+ }
+
+ for( ; n < rArr.Count(); ++n )
+ {
+ SwRedline* pTmp = rArr[ n ];
+ if( pTmp->HasMark() && pTmp->IsVisible() )
+ {
+ if( *pTmp->End() <= *pEnd )
+ {
+ if( (*fn_AcceptReject)( rArr, n, bCallDelete, 0, 0 ))
+ nCount++;
+ }
+ else
+ {
+ if( *pTmp->Start() < *pEnd )
+ {
+ // dann nur in der TeilSelektion aufheben
+ if( (*fn_AcceptReject)( rArr, n, bCallDelete, pStt, pEnd ))
+ nCount++;
+ }
+ break;
+ }
+ }
+ }
+ return nCount;
+}
+
+void lcl_AdjustRedlineRange( SwPaM& rPam )
+{
+ // die Selektion steht nur im ContentBereich. Wenn es aber Redlines
+ // davor oder dahinter auf nicht ContentNodes stehen, dann erweiter die
+ // die Selection auf diese
+ SwPosition* pStt = rPam.Start(),
+ * pEnd = pStt == rPam.GetPoint() ? rPam.GetMark()
+ : rPam.GetPoint();
+ SwDoc* pDoc = rPam.GetDoc();
+ if( !pStt->nContent.GetIndex() &&
+ !pDoc->GetNodes()[ pStt->nNode.GetIndex() - 1 ]->IsCntntNode() )
+ {
+ const SwRedline* pRedl = pDoc->GetRedline( *pStt, 0 );
+ if( pRedl )
+ {
+ const SwPosition* pRStt = pRedl->Start();
+ if( !pRStt->nContent.GetIndex() && pRStt->nNode.GetIndex() ==
+ pStt->nNode.GetIndex() - 1 )
+ *pStt = *pRStt;
+ }
+ }
+ if( pEnd->nNode.GetNode().IsCntntNode() &&
+ !pDoc->GetNodes()[ pEnd->nNode.GetIndex() + 1 ]->IsCntntNode() &&
+ pEnd->nContent.GetIndex() == pEnd->nNode.GetNode().GetCntntNode()->Len() )
+ {
+ const SwRedline* pRedl = pDoc->GetRedline( *pEnd, 0 );
+ if( pRedl )
+ {
+ const SwPosition* pREnd = pRedl->End();
+ if( !pREnd->nContent.GetIndex() && pREnd->nNode.GetIndex() ==
+ pEnd->nNode.GetIndex() + 1 )
+ *pEnd = *pREnd;
+ }
+ }
+}
+
+
+bool SwDoc::AcceptRedline( sal_uInt16 nPos, bool bCallDelete )
+{
+ sal_Bool bRet = sal_False;
+
+ // aufjedenfall auf sichtbar umschalten
+ if( (nsRedlineMode_t::REDLINE_SHOW_INSERT | nsRedlineMode_t::REDLINE_SHOW_DELETE) !=
+ (nsRedlineMode_t::REDLINE_SHOW_MASK & eRedlineMode) )
+ SetRedlineMode( (RedlineMode_t)(nsRedlineMode_t::REDLINE_SHOW_INSERT | nsRedlineMode_t::REDLINE_SHOW_DELETE | eRedlineMode));
+
+ SwRedline* pTmp = (*pRedlineTbl)[ nPos ];
+ if( pTmp->HasMark() && pTmp->IsVisible() )
+ {
+ if (GetIDocumentUndoRedo().DoesUndo())
+ {
+ SwRewriter aRewriter;
+
+ aRewriter.AddRule(UNDO_ARG1, pTmp->GetDescr());
+ GetIDocumentUndoRedo().StartUndo(UNDO_ACCEPT_REDLINE, &aRewriter);
+ }
+
+ int nLoopCnt = 2;
+ sal_uInt16 nSeqNo = pTmp->GetSeqNo();
+
+ do {
+
+ if (GetIDocumentUndoRedo().DoesUndo())
+ {
+ SwUndo *const pUndo( new SwUndoAcceptRedline(*pTmp) );
+ GetIDocumentUndoRedo().AppendUndo(pUndo);
+ }
+
+ bRet |= lcl_AcceptRedline( *pRedlineTbl, nPos, bCallDelete );
+
+ if( nSeqNo )
+ {
+ if( USHRT_MAX == nPos )
+ nPos = 0;
+ sal_uInt16 nFndPos = 2 == nLoopCnt
+ ? pRedlineTbl->FindNextSeqNo( nSeqNo, nPos )
+ : pRedlineTbl->FindPrevSeqNo( nSeqNo, nPos );
+ if( USHRT_MAX != nFndPos || ( 0 != ( --nLoopCnt ) &&
+ USHRT_MAX != ( nFndPos =
+ pRedlineTbl->FindPrevSeqNo( nSeqNo, nPos ))) )
+ pTmp = (*pRedlineTbl)[ nPos = nFndPos ];
+ else
+ nLoopCnt = 0;
+ }
+ else
+ nLoopCnt = 0;
+
+ } while( nLoopCnt );
+
+ if( bRet )
+ {
+ CompressRedlines();
+ SetModified();
+ }
+
+ if (GetIDocumentUndoRedo().DoesUndo())
+ {
+ GetIDocumentUndoRedo().EndUndo(UNDO_END, 0);
+ }
+ }
+ return bRet;
+}
+
+bool SwDoc::AcceptRedline( const SwPaM& rPam, bool bCallDelete )
+{
+ // aufjedenfall auf sichtbar umschalten
+ if( (nsRedlineMode_t::REDLINE_SHOW_INSERT | nsRedlineMode_t::REDLINE_SHOW_DELETE) !=
+ (nsRedlineMode_t::REDLINE_SHOW_MASK & eRedlineMode) )
+ SetRedlineMode( (RedlineMode_t)(nsRedlineMode_t::REDLINE_SHOW_INSERT | nsRedlineMode_t::REDLINE_SHOW_DELETE | eRedlineMode));
+
+ // die Selektion steht nur im ContentBereich. Wenn es aber Redlines
+ // davor oder dahinter auf nicht ContentNodes stehen, dann erweiter die
+ // die Selection auf diese
+ SwPaM aPam( *rPam.GetMark(), *rPam.GetPoint() );
+ lcl_AdjustRedlineRange( aPam );
+
+ if (GetIDocumentUndoRedo().DoesUndo())
+ {
+ GetIDocumentUndoRedo().StartUndo( UNDO_ACCEPT_REDLINE, NULL );
+ GetIDocumentUndoRedo().AppendUndo( new SwUndoAcceptRedline( aPam ));
+ }
+
+ int nRet = lcl_AcceptRejectRedl( lcl_AcceptRedline, *pRedlineTbl,
+ bCallDelete, aPam );
+ if( nRet > 0 )
+ {
+ CompressRedlines();
+ SetModified();
+ }
+ if (GetIDocumentUndoRedo().DoesUndo())
+ {
+ String aTmpStr;
+
+ {
+ SwRewriter aRewriter;
+ aRewriter.AddRule(UNDO_ARG1, String::CreateFromInt32(nRet));
+ aTmpStr = aRewriter.Apply(String(SW_RES(STR_N_REDLINES)));
+ }
+
+ SwRewriter aRewriter;
+ aRewriter.AddRule(UNDO_ARG1, aTmpStr);
+
+ GetIDocumentUndoRedo().EndUndo( UNDO_ACCEPT_REDLINE, &aRewriter );
+ }
+ return nRet != 0;
+}
+
+bool SwDoc::RejectRedline( sal_uInt16 nPos, bool bCallDelete )
+{
+ sal_Bool bRet = sal_False;
+
+ // aufjedenfall auf sichtbar umschalten
+ if( (nsRedlineMode_t::REDLINE_SHOW_INSERT | nsRedlineMode_t::REDLINE_SHOW_DELETE) !=
+ (nsRedlineMode_t::REDLINE_SHOW_MASK & eRedlineMode) )
+ SetRedlineMode( (RedlineMode_t)(nsRedlineMode_t::REDLINE_SHOW_INSERT | nsRedlineMode_t::REDLINE_SHOW_DELETE | eRedlineMode));
+
+ SwRedline* pTmp = (*pRedlineTbl)[ nPos ];
+ if( pTmp->HasMark() && pTmp->IsVisible() )
+ {
+ if (GetIDocumentUndoRedo().DoesUndo())
+ {
+ SwRewriter aRewriter;
+
+ aRewriter.AddRule(UNDO_ARG1, pTmp->GetDescr());
+ GetIDocumentUndoRedo().StartUndo(UNDO_REJECT_REDLINE, &aRewriter);
+ }
+
+ int nLoopCnt = 2;
+ sal_uInt16 nSeqNo = pTmp->GetSeqNo();
+
+ do {
+
+ if (GetIDocumentUndoRedo().DoesUndo())
+ {
+ SwUndo *const pUndo( new SwUndoRejectRedline( *pTmp ) );
+ GetIDocumentUndoRedo().AppendUndo(pUndo);
+ }
+
+ bRet |= lcl_RejectRedline( *pRedlineTbl, nPos, bCallDelete );
+
+ if( nSeqNo )
+ {
+ if( USHRT_MAX == nPos )
+ nPos = 0;
+ sal_uInt16 nFndPos = 2 == nLoopCnt
+ ? pRedlineTbl->FindNextSeqNo( nSeqNo, nPos )
+ : pRedlineTbl->FindPrevSeqNo( nSeqNo, nPos );
+ if( USHRT_MAX != nFndPos || ( 0 != ( --nLoopCnt ) &&
+ USHRT_MAX != ( nFndPos =
+ pRedlineTbl->FindPrevSeqNo( nSeqNo, nPos ))) )
+ pTmp = (*pRedlineTbl)[ nPos = nFndPos ];
+ else
+ nLoopCnt = 0;
+ }
+ else
+ nLoopCnt = 0;
+
+ } while( nLoopCnt );
+
+ if( bRet )
+ {
+ CompressRedlines();
+ SetModified();
+ }
+
+ if (GetIDocumentUndoRedo().DoesUndo())
+ {
+ GetIDocumentUndoRedo().EndUndo(UNDO_END, 0);
+ }
+ }
+ return bRet;
+}
+
+bool SwDoc::RejectRedline( const SwPaM& rPam, bool bCallDelete )
+{
+ // aufjedenfall auf sichtbar umschalten
+ if( (nsRedlineMode_t::REDLINE_SHOW_INSERT | nsRedlineMode_t::REDLINE_SHOW_DELETE) !=
+ (nsRedlineMode_t::REDLINE_SHOW_MASK & eRedlineMode) )
+ SetRedlineMode((RedlineMode_t)(nsRedlineMode_t::REDLINE_SHOW_INSERT | nsRedlineMode_t::REDLINE_SHOW_DELETE | eRedlineMode));
+
+ // die Selektion steht nur im ContentBereich. Wenn es aber Redlines
+ // davor oder dahinter auf nicht ContentNodes stehen, dann erweiter die
+ // die Selection auf diese
+ SwPaM aPam( *rPam.GetMark(), *rPam.GetPoint() );
+ lcl_AdjustRedlineRange( aPam );
+
+ if (GetIDocumentUndoRedo().DoesUndo())
+ {
+ GetIDocumentUndoRedo().StartUndo( UNDO_REJECT_REDLINE, NULL );
+ GetIDocumentUndoRedo().AppendUndo( new SwUndoRejectRedline(aPam) );
+ }
+
+ int nRet = lcl_AcceptRejectRedl( lcl_RejectRedline, *pRedlineTbl,
+ bCallDelete, aPam );
+ if( nRet > 0 )
+ {
+ CompressRedlines();
+ SetModified();
+ }
+ if (GetIDocumentUndoRedo().DoesUndo())
+ {
+ String aTmpStr;
+
+ {
+ SwRewriter aRewriter;
+ aRewriter.AddRule(UNDO_ARG1, String::CreateFromInt32(nRet));
+ aTmpStr = aRewriter.Apply(String(SW_RES(STR_N_REDLINES)));
+ }
+
+ SwRewriter aRewriter;
+ aRewriter.AddRule(UNDO_ARG1, aTmpStr);
+
+ GetIDocumentUndoRedo().EndUndo( UNDO_REJECT_REDLINE, &aRewriter );
+ }
+
+ return nRet != 0;
+}
+
+const SwRedline* SwDoc::SelNextRedline( SwPaM& rPam ) const
+{
+ rPam.DeleteMark();
+ rPam.SetMark();
+
+ SwPosition& rSttPos = *rPam.GetPoint();
+ SwPosition aSavePos( rSttPos );
+ sal_Bool bRestart;
+
+ // sollte die StartPos auf dem letzen gueligen ContentNode stehen,
+ // dann aufjedenfall das naechste Redline nehmen
+ sal_uInt16 n = 0;
+ const SwRedline* pFnd = lcl_FindCurrRedline( rSttPos, n, sal_True );
+ if( pFnd )
+ {
+ const SwPosition* pEnd = pFnd->End();
+ if( !pEnd->nNode.GetNode().IsCntntNode() )
+ {
+ SwNodeIndex aTmp( pEnd->nNode );
+ SwCntntNode* pCNd = GetNodes().GoPrevSection( &aTmp );
+ if( !pCNd || ( aTmp == rSttPos.nNode &&
+ pCNd->Len() == rSttPos.nContent.GetIndex() ))
+ pFnd = 0;
+ }
+ if( pFnd )
+ rSttPos = *pFnd->End();
+ }
+
+ do {
+ bRestart = sal_False;
+
+ for( ; !pFnd && n < pRedlineTbl->Count(); ++n )
+ {
+ pFnd = (*pRedlineTbl)[ n ];
+ if( pFnd->HasMark() && pFnd->IsVisible() )
+ {
+ *rPam.GetMark() = *pFnd->Start();
+ rSttPos = *pFnd->End();
+ break;
+ }
+ else
+ pFnd = 0;
+ }
+
+ if( pFnd )
+ {
+ // alle vom gleichen Typ und Author, die hinter einander liegen
+ // zu einer Selektion zusammenfassen.
+ const SwPosition* pPrevEnd = pFnd->End();
+ while( ++n < pRedlineTbl->Count() )
+ {
+ const SwRedline* pTmp = (*pRedlineTbl)[ n ];
+ if( pTmp->HasMark() && pTmp->IsVisible() )
+ {
+ const SwPosition *pRStt;
+ if( pFnd->GetType() == pTmp->GetType() &&
+ pFnd->GetAuthor() == pTmp->GetAuthor() &&
+ ( *pPrevEnd == *( pRStt = pTmp->Start() ) ||
+ IsPrevPos( *pPrevEnd, *pRStt )) )
+ {
+ pPrevEnd = pTmp->End();
+ rSttPos = *pPrevEnd;
+ }
+ else
+ break;
+ }
+ }
+ }
+
+ if( pFnd )
+ {
+ const SwRedline* pSaveFnd = pFnd;
+
+ SwCntntNode* pCNd;
+ SwNodeIndex* pIdx = &rPam.GetMark()->nNode;
+ if( !pIdx->GetNode().IsCntntNode() &&
+ 0 != ( pCNd = GetNodes().GoNextSection( pIdx )) )
+ {
+ if( *pIdx <= rPam.GetPoint()->nNode )
+ rPam.GetMark()->nContent.Assign( pCNd, 0 );
+ else
+ pFnd = 0;
+ }
+
+ if( pFnd )
+ {
+ pIdx = &rPam.GetPoint()->nNode;
+ if( !pIdx->GetNode().IsCntntNode() &&
+ 0 != ( pCNd = GetNodes().GoPrevSection( pIdx )) )
+ {
+ if( *pIdx >= rPam.GetMark()->nNode )
+ rPam.GetPoint()->nContent.Assign( pCNd, pCNd->Len() );
+ else
+ pFnd = 0;
+ }
+ }
+
+ if( !pFnd || *rPam.GetMark() == *rPam.GetPoint() )
+ {
+ if( n < pRedlineTbl->Count() )
+ {
+ bRestart = sal_True;
+ *rPam.GetPoint() = *pSaveFnd->End();
+ }
+ else
+ {
+ rPam.DeleteMark();
+ *rPam.GetPoint() = aSavePos;
+ }
+ pFnd = 0;
+ }
+ }
+ } while( bRestart );
+
+ return pFnd;
+}
+
+const SwRedline* SwDoc::SelPrevRedline( SwPaM& rPam ) const
+{
+ rPam.DeleteMark();
+ rPam.SetMark();
+
+ SwPosition& rSttPos = *rPam.GetPoint();
+ SwPosition aSavePos( rSttPos );
+ sal_Bool bRestart;
+
+ // sollte die StartPos auf dem ersten gueligen ContentNode stehen,
+ // dann aufjedenfall das vorherige Redline nehmen
+ sal_uInt16 n = 0;
+ const SwRedline* pFnd = lcl_FindCurrRedline( rSttPos, n, sal_False );
+ if( pFnd )
+ {
+ const SwPosition* pStt = pFnd->Start();
+ if( !pStt->nNode.GetNode().IsCntntNode() )
+ {
+ SwNodeIndex aTmp( pStt->nNode );
+ SwCntntNode* pCNd = GetNodes().GoNextSection( &aTmp );
+ if( !pCNd || ( aTmp == rSttPos.nNode &&
+ !rSttPos.nContent.GetIndex() ))
+ pFnd = 0;
+ }
+ if( pFnd )
+ rSttPos = *pFnd->Start();
+ }
+
+ do {
+ bRestart = sal_False;
+
+ while( !pFnd && 0 < n )
+ {
+ pFnd = (*pRedlineTbl)[ --n ];
+ if( pFnd->HasMark() && pFnd->IsVisible() )
+ {
+ *rPam.GetMark() = *pFnd->End();
+ rSttPos = *pFnd->Start();
+ }
+ else
+ pFnd = 0;
+ }
+
+ if( pFnd )
+ {
+ // alle vom gleichen Typ und Author, die hinter einander liegen
+ // zu einer Selektion zusammenfassen.
+ const SwPosition* pNextStt = pFnd->Start();
+ while( 0 < n )
+ {
+ const SwRedline* pTmp = (*pRedlineTbl)[ --n ];
+ if( pTmp->HasMark() && pTmp->IsVisible() )
+ {
+ const SwPosition *pREnd;
+ if( pFnd->GetType() == pTmp->GetType() &&
+ pFnd->GetAuthor() == pTmp->GetAuthor() &&
+ ( *pNextStt == *( pREnd = pTmp->End() ) ||
+ IsPrevPos( *pREnd, *pNextStt )) )
+ {
+ pNextStt = pTmp->Start();
+ rSttPos = *pNextStt;
+ }
+ else
+ {
+ ++n;
+ break;
+ }
+ }
+ }
+ }
+
+ if( pFnd )
+ {
+ const SwRedline* pSaveFnd = pFnd;
+
+ SwCntntNode* pCNd;
+ SwNodeIndex* pIdx = &rPam.GetMark()->nNode;
+ if( !pIdx->GetNode().IsCntntNode() &&
+ 0 != ( pCNd = GetNodes().GoPrevSection( pIdx )) )
+ {
+ if( *pIdx >= rPam.GetPoint()->nNode )
+ rPam.GetMark()->nContent.Assign( pCNd, pCNd->Len() );
+ else
+ pFnd = 0;
+ }
+
+ if( pFnd )
+ {
+ pIdx = &rPam.GetPoint()->nNode;
+ if( !pIdx->GetNode().IsCntntNode() &&
+ 0 != ( pCNd = GetNodes().GoNextSection( pIdx )) )
+ {
+ if( *pIdx <= rPam.GetMark()->nNode )
+ rPam.GetPoint()->nContent.Assign( pCNd, 0 );
+ else
+ pFnd = 0;
+ }
+ }
+
+ if( !pFnd || *rPam.GetMark() == *rPam.GetPoint() )
+ {
+ if( n )
+ {
+ bRestart = sal_True;
+ *rPam.GetPoint() = *pSaveFnd->Start();
+ }
+ else
+ {
+ rPam.DeleteMark();
+ *rPam.GetPoint() = aSavePos;
+ }
+ pFnd = 0;
+ }
+ }
+ } while( bRestart );
+
+ return pFnd;
+}
+
+// Kommentar am Redline setzen
+bool SwDoc::SetRedlineComment( const SwPaM& rPaM, const String& rS )
+{
+ sal_Bool bRet = sal_False;
+ const SwPosition* pStt = rPaM.Start(),
+ * pEnd = pStt == rPaM.GetPoint() ? rPaM.GetMark()
+ : rPaM.GetPoint();
+ sal_uInt16 n = 0;
+ if( lcl_FindCurrRedline( *pStt, n, sal_True ) )
+ {
+ for( ; n < pRedlineTbl->Count(); ++n )
+ {
+ bRet = sal_True;
+ SwRedline* pTmp = (*pRedlineTbl)[ n ];
+ if( pStt != pEnd && *pTmp->Start() > *pEnd )
+ break;
+
+ pTmp->SetComment( rS );
+ if( *pTmp->End() >= *pEnd )
+ break;
+ }
+ }
+ if( bRet )
+ SetModified();
+
+ return bRet;
+}
+
+// legt gebenenfalls einen neuen Author an
+sal_uInt16 SwDoc::GetRedlineAuthor()
+{
+ return SW_MOD()->GetRedlineAuthor();
+}
+
+ // fuer die Reader usw. - neuen Author in die Tabelle eintragen
+sal_uInt16 SwDoc::InsertRedlineAuthor( const String& rNew )
+{
+ return SW_MOD()->InsertRedlineAuthor(rNew);
+}
+
+void SwDoc::UpdateRedlineAttr()
+{
+ const SwRedlineTbl& rTbl = GetRedlineTbl();
+ for( sal_uInt16 n = 0; n < rTbl.Count(); ++n )
+ {
+ SwRedline* pRedl = rTbl[ n ];
+ if( pRedl->IsVisible() )
+ pRedl->InvalidateRange();
+ }
+}
+
+ // setze Kommentar-Text fuers Redline, das dann per AppendRedline
+ // hereinkommt. Wird vom Autoformat benutzt. 0-Pointer setzt den Modus
+ // wieder zurueck. Pointer wird nicht kopiert, muss also gueltig bleiben!
+void SwDoc::SetAutoFmtRedlineComment( const String* pTxt, sal_uInt16 nSeqNo )
+{
+ mbIsAutoFmtRedline = 0 != pTxt;
+ if( pTxt )
+ {
+ if( !pAutoFmtRedlnComment )
+ pAutoFmtRedlnComment = new String( *pTxt );
+ else
+ *pAutoFmtRedlnComment = *pTxt;
+ }
+ else if( pAutoFmtRedlnComment )
+ delete pAutoFmtRedlnComment, pAutoFmtRedlnComment = 0;
+
+ nAutoFmtRedlnCommentNo = nSeqNo;
+}
+
+void SwDoc::SetRedlinePassword(
+ /*[in]*/const uno::Sequence <sal_Int8>& rNewPassword)
+{
+ aRedlinePasswd = rNewPassword;
+ SetModified();
+}
+
+/* */
+
+sal_Bool SwRedlineTbl::Insert( SwRedlinePtr& p, sal_Bool bIns )
+{
+ sal_Bool bRet = sal_False;
+ if( p->HasValidRange() )
+ {
+ bRet = _SwRedlineTbl::Insert( p );
+ p->CallDisplayFunc();
+ }
+ else if( bIns )
+ bRet = InsertWithValidRanges( p );
+ else
+ {
+ OSL_ENSURE( !this, "Redline: falscher Bereich" );
+ }
+ return bRet;
+}
+
+sal_Bool SwRedlineTbl::Insert( SwRedlinePtr& p, sal_uInt16& rP, sal_Bool bIns )
+{
+ sal_Bool bRet = sal_False;
+ if( p->HasValidRange() )
+ {
+ bRet = _SwRedlineTbl::Insert( p, rP );
+ p->CallDisplayFunc();
+ }
+ else if( bIns )
+ bRet = InsertWithValidRanges( p, &rP );
+ else
+ {
+ OSL_ENSURE( !this, "Redline: falscher Bereich" );
+ }
+ return bRet;
+}
+
+sal_Bool SwRedlineTbl::InsertWithValidRanges( SwRedlinePtr& p, sal_uInt16* pInsPos )
+{
+ // erzeuge aus den Selektion gueltige "Teilbereiche".
+ sal_Bool bAnyIns = sal_False;
+ SwPosition* pStt = p->Start(),
+ * pEnd = pStt == p->GetPoint() ? p->GetMark() : p->GetPoint();
+ SwPosition aNewStt( *pStt );
+ SwNodes& rNds = aNewStt.nNode.GetNodes();
+ SwCntntNode* pC;
+
+ if( !aNewStt.nNode.GetNode().IsCntntNode() )
+ {
+ pC = rNds.GoNext( &aNewStt.nNode );
+ if( pC )
+ aNewStt.nContent.Assign( pC, 0 );
+ else
+ aNewStt.nNode = rNds.GetEndOfContent();
+ }
+
+ SwRedline* pNew = 0;
+ sal_uInt16 nInsPos;
+
+ if( aNewStt < *pEnd )
+ do {
+ if( !pNew )
+ pNew = new SwRedline( p->GetRedlineData(), aNewStt );
+ else
+ {
+ pNew->DeleteMark();
+ *pNew->GetPoint() = aNewStt;
+ }
+
+ pNew->SetMark();
+ GoEndSection( pNew->GetPoint() );
+ // i60396: If the redlines starts before a table but the table is the last member
+ // of the section, the GoEndSection will end inside the table.
+ // This will result in an incorrect redline, so we've to go back
+ SwNode* pTab = pNew->GetPoint()->nNode.GetNode().StartOfSectionNode()->FindTableNode();
+ // We end in a table when pTab != 0
+ if( pTab && !pNew->GetMark()->nNode.GetNode().StartOfSectionNode()->FindTableNode() )
+ { // but our Mark was outside the table => Correction
+ do
+ {
+ // We want to be before the table
+ *pNew->GetPoint() = SwPosition(*pTab);
+ pC = GoPreviousNds( &pNew->GetPoint()->nNode, sal_False ); // here we are.
+ if( pC )
+ pNew->GetPoint()->nContent.Assign( pC, 0 );
+ pTab = pNew->GetPoint()->nNode.GetNode().StartOfSectionNode()->FindTableNode();
+ }while( pTab ); // If there is another table we have to repeat our step backwards
+ }
+
+ if( *pNew->GetPoint() > *pEnd )
+ {
+ pC = 0;
+ if( aNewStt.nNode != pEnd->nNode )
+ do {
+ SwNode& rCurNd = aNewStt.nNode.GetNode();
+ if( rCurNd.IsStartNode() )
+ {
+ if( rCurNd.EndOfSectionIndex() < pEnd->nNode.GetIndex() )
+ aNewStt.nNode = *rCurNd.EndOfSectionNode();
+ else
+ break;
+ }
+ else if( rCurNd.IsCntntNode() )
+ pC = rCurNd.GetCntntNode();
+ aNewStt.nNode++;
+ } while( aNewStt.nNode.GetIndex() < pEnd->nNode.GetIndex() );
+
+ if( aNewStt.nNode == pEnd->nNode )
+ aNewStt.nContent = pEnd->nContent;
+ else if( pC )
+ {
+ aNewStt.nNode = *pC;
+ aNewStt.nContent.Assign( pC, pC->Len() );
+ }
+
+ if( aNewStt <= *pEnd )
+ *pNew->GetPoint() = aNewStt;
+ }
+ else
+ aNewStt = *pNew->GetPoint();
+#ifdef DEBUG
+ CheckPosition( pNew->GetPoint(), pNew->GetMark() );
+#endif
+ if( *pNew->GetPoint() != *pNew->GetMark() &&
+ _SwRedlineTbl::Insert( pNew, nInsPos ) )
+ {
+ pNew->CallDisplayFunc();
+ bAnyIns = sal_True;
+ pNew = 0;
+ if( pInsPos && *pInsPos < nInsPos )
+ *pInsPos = nInsPos;
+ }
+
+ if( aNewStt >= *pEnd ||
+ 0 == (pC = rNds.GoNext( &aNewStt.nNode )) )
+ break;
+
+ aNewStt.nContent.Assign( pC, 0 );
+
+ } while( aNewStt < *pEnd );
+
+ delete pNew;
+ delete p, p = 0;
+ return bAnyIns;
+}
+
+void SwRedlineTbl::Remove( sal_uInt16 nP, sal_uInt16 nL )
+{
+ SwDoc* pDoc = 0;
+ if( !nP && nL && nL == _SwRedlineTbl::Count() )
+ pDoc = _SwRedlineTbl::GetObject( 0 )->GetDoc();
+
+ _SwRedlineTbl::Remove( nP, nL );
+
+ ViewShell* pSh;
+ if( pDoc && !pDoc->IsInDtor() &&
+ 0 != ( pSh = pDoc->GetCurrentViewShell()) ) //swmod 071108//swmod 071225
+ pSh->InvalidateWindows( SwRect( 0, 0, LONG_MAX, LONG_MAX ) );
+}
+
+void SwRedlineTbl::DeleteAndDestroy( sal_uInt16 nP, sal_uInt16 nL )
+{
+ SwDoc* pDoc = 0;
+ if( !nP && nL && nL == _SwRedlineTbl::Count() )
+ pDoc = _SwRedlineTbl::GetObject( 0 )->GetDoc();
+
+ _SwRedlineTbl::DeleteAndDestroy( nP, nL );
+
+ ViewShell* pSh;
+ if( pDoc && !pDoc->IsInDtor() &&
+ 0 != ( pSh = pDoc->GetCurrentViewShell() ) ) //swmod 071108//swmod 071225
+ pSh->InvalidateWindows( SwRect( 0, 0, LONG_MAX, LONG_MAX ) );
+}
+
+// suche den naechsten oder vorherigen Redline mit dergleichen Seq.No
+// Mit dem Lookahead kann die Suche eingeschraenkt werden. 0 oder
+// USHRT_MAX suchen im gesamten Array.
+sal_uInt16 SwRedlineTbl::FindNextOfSeqNo( sal_uInt16 nSttPos, sal_uInt16 nLookahead ) const
+{
+ return nSttPos + 1 < _SwRedlineTbl::Count()
+ ? FindNextSeqNo( _SwRedlineTbl::GetObject( nSttPos )
+ ->GetSeqNo(), nSttPos+1, nLookahead )
+ : USHRT_MAX;
+}
+
+sal_uInt16 SwRedlineTbl::FindPrevOfSeqNo( sal_uInt16 nSttPos, sal_uInt16 nLookahead ) const
+{
+ return nSttPos ? FindPrevSeqNo( _SwRedlineTbl::GetObject(
+ nSttPos )->GetSeqNo(),
+ nSttPos-1, nLookahead )
+ : USHRT_MAX;
+}
+
+sal_uInt16 SwRedlineTbl::FindNextSeqNo( sal_uInt16 nSeqNo, sal_uInt16 nSttPos,
+ sal_uInt16 nLookahead ) const
+{
+ sal_uInt16 nRet = USHRT_MAX, nEnd;
+ if( nSeqNo && nSttPos < _SwRedlineTbl::Count() )
+ {
+ nEnd = _SwRedlineTbl::Count();
+ if( nLookahead && USHRT_MAX != nLookahead &&
+ nSttPos + nLookahead < _SwRedlineTbl::Count() )
+ nEnd = nSttPos + nLookahead;
+
+ for( ; nSttPos < nEnd; ++nSttPos )
+ if( nSeqNo == _SwRedlineTbl::GetObject( nSttPos )->GetSeqNo() )
+ {
+ nRet = nSttPos;
+ break;
+ }
+ }
+ return nRet;
+}
+
+sal_uInt16 SwRedlineTbl::FindPrevSeqNo( sal_uInt16 nSeqNo, sal_uInt16 nSttPos,
+ sal_uInt16 nLookahead ) const
+{
+ sal_uInt16 nRet = USHRT_MAX, nEnd;
+ if( nSeqNo && nSttPos < _SwRedlineTbl::Count() )
+ {
+ nEnd = 0;
+ if( nLookahead && USHRT_MAX != nLookahead && nSttPos > nLookahead )
+ nEnd = nSttPos - nLookahead;
+
+ ++nSttPos;
+ while( nSttPos > nEnd )
+ if( nSeqNo == _SwRedlineTbl::GetObject( --nSttPos )->GetSeqNo() )
+ {
+ nRet = nSttPos;
+ break;
+ }
+ }
+ return nRet;
+}
+
+/* */
+
+SwRedlineExtraData::~SwRedlineExtraData()
+{
+}
+
+void SwRedlineExtraData::Accept( SwPaM& ) const
+{
+}
+
+void SwRedlineExtraData::Reject( SwPaM& ) const
+{
+}
+
+int SwRedlineExtraData::operator == ( const SwRedlineExtraData& ) const
+{
+ return sal_False;
+}
+
+
+SwRedlineExtraData_FmtColl::SwRedlineExtraData_FmtColl( const String& rColl,
+ sal_uInt16 nPoolFmtId,
+ const SfxItemSet* pItemSet )
+ : sFmtNm(rColl), pSet(0), nPoolId(nPoolFmtId)
+{
+ if( pItemSet && pItemSet->Count() )
+ pSet = new SfxItemSet( *pItemSet );
+}
+
+SwRedlineExtraData_FmtColl::~SwRedlineExtraData_FmtColl()
+{
+ delete pSet;
+}
+
+SwRedlineExtraData* SwRedlineExtraData_FmtColl::CreateNew() const
+{
+ return new SwRedlineExtraData_FmtColl( sFmtNm, nPoolId, pSet );
+}
+
+void SwRedlineExtraData_FmtColl::Reject( SwPaM& rPam ) const
+{
+ SwDoc* pDoc = rPam.GetDoc();
+
+// was ist mit Undo ? ist das abgeschaltet ??
+ SwTxtFmtColl* pColl = USHRT_MAX == nPoolId
+ ? pDoc->FindTxtFmtCollByName( sFmtNm )
+ : pDoc->GetTxtCollFromPool( nPoolId );
+ if( pColl )
+ pDoc->SetTxtFmtColl( rPam, pColl, false );
+
+ if( pSet )
+ {
+ rPam.SetMark();
+ SwPosition& rMark = *rPam.GetMark();
+ SwTxtNode* pTNd = rMark.nNode.GetNode().GetTxtNode();
+ if( pTNd )
+ {
+ rMark.nContent.Assign( pTNd, pTNd->GetTxt().Len() );
+
+ if( pTNd->HasSwAttrSet() )
+ {
+ // nur die setzen, die nicht mehr vorhanden sind. Andere
+ // koennen jetzt veraendert drin stehen, aber die werden
+ // nicht angefasst.
+ SfxItemSet aTmp( *pSet );
+ aTmp.Differentiate( *pTNd->GetpSwAttrSet() );
+ pDoc->InsertItemSet( rPam, aTmp, 0 );
+ }
+ else
+ {
+ pDoc->InsertItemSet( rPam, *pSet, 0 );
+ }
+ }
+ rPam.DeleteMark();
+ }
+}
+
+int SwRedlineExtraData_FmtColl::operator == ( const SwRedlineExtraData& r) const
+{
+ const SwRedlineExtraData_FmtColl& rCmp = (SwRedlineExtraData_FmtColl&)r;
+ return sFmtNm == rCmp.sFmtNm && nPoolId == rCmp.nPoolId &&
+ ( ( !pSet && !rCmp.pSet ) ||
+ ( pSet && rCmp.pSet && *pSet == *rCmp.pSet ) );
+}
+
+void SwRedlineExtraData_FmtColl::SetItemSet( const SfxItemSet& rSet )
+{
+ delete pSet;
+ if( rSet.Count() )
+ pSet = new SfxItemSet( rSet );
+ else
+ pSet = 0;
+}
+
+
+SwRedlineExtraData_Format::SwRedlineExtraData_Format( const SfxItemSet& rSet )
+{
+ SfxItemIter aIter( rSet );
+ const SfxPoolItem* pItem = aIter.FirstItem();
+ while( sal_True )
+ {
+ aWhichIds.Insert( pItem->Which(), aWhichIds.Count() );
+ if( aIter.IsAtEnd() )
+ break;
+ pItem = aIter.NextItem();
+ }
+}
+
+SwRedlineExtraData_Format::SwRedlineExtraData_Format(
+ const SwRedlineExtraData_Format& rCpy )
+ : SwRedlineExtraData(), aWhichIds( (sal_uInt8)rCpy.aWhichIds.Count() )
+{
+ aWhichIds.Insert( &rCpy.aWhichIds, 0 );
+}
+
+SwRedlineExtraData_Format::~SwRedlineExtraData_Format()
+{
+}
+
+SwRedlineExtraData* SwRedlineExtraData_Format::CreateNew() const
+{
+ return new SwRedlineExtraData_Format( *this );
+}
+
+void SwRedlineExtraData_Format::Reject( SwPaM& rPam ) const
+{
+ SwDoc* pDoc = rPam.GetDoc();
+
+ RedlineMode_t eOld = pDoc->GetRedlineMode();
+ pDoc->SetRedlineMode_intern((RedlineMode_t)(eOld & ~(nsRedlineMode_t::REDLINE_ON | nsRedlineMode_t::REDLINE_IGNORE)));
+
+ // eigentlich muesste hier das Attribut zurueck gesetzt werden!!!
+ for( sal_uInt16 n = 0, nEnd = aWhichIds.Count(); n < nEnd; ++n )
+ {
+ pDoc->InsertPoolItem( rPam, *GetDfltAttr( aWhichIds[ n ] ),
+ nsSetAttrMode::SETATTR_DONTEXPAND );
+ }
+
+ pDoc->SetRedlineMode_intern( eOld );
+}
+
+int SwRedlineExtraData_Format::operator == ( const SwRedlineExtraData& rCmp ) const
+{
+ int nRet = 1;
+ sal_uInt16 n = 0, nEnd = aWhichIds.Count();
+ if( nEnd != ((SwRedlineExtraData_Format&)rCmp).aWhichIds.Count() )
+ nRet = 0;
+ else
+ for( ; n < nEnd; ++n )
+ if( ((SwRedlineExtraData_Format&)rCmp).aWhichIds[n] != aWhichIds[n])
+ {
+ nRet = 0;
+ break;
+ }
+ return nRet;
+}
+
+SwRedlineData::SwRedlineData( RedlineType_t eT, sal_uInt16 nAut )
+ : pNext( 0 ), pExtraData( 0 ), eType( eT ), nAuthor( nAut ), nSeqNo( 0 )
+{
+ aStamp.SetSec( 0 );
+ aStamp.Set100Sec( 0 );
+}
+
+SwRedlineData::SwRedlineData( const SwRedlineData& rCpy, sal_Bool bCpyNext )
+ :
+ pNext( (bCpyNext && rCpy.pNext) ? new SwRedlineData( *rCpy.pNext ) : 0 ),
+ pExtraData( rCpy.pExtraData ? rCpy.pExtraData->CreateNew() : 0 ),
+ sComment( rCpy.sComment ), aStamp( rCpy.aStamp ), eType( rCpy.eType ),
+ nAuthor( rCpy.nAuthor ), nSeqNo( rCpy.nSeqNo )
+{
+}
+
+ // fuer sw3io: pNext geht in eigenen Besitz ueber!
+SwRedlineData::SwRedlineData(RedlineType_t eT, sal_uInt16 nAut, const DateTime& rDT,
+ const String& rCmnt, SwRedlineData *pNxt, SwRedlineExtraData* pData)
+ : pNext(pNxt), pExtraData(pData), sComment(rCmnt), aStamp(rDT),
+ eType(eT), nAuthor(nAut), nSeqNo(0)
+{
+}
+
+SwRedlineData::~SwRedlineData()
+{
+ delete pExtraData;
+ delete pNext;
+}
+
+ // ExtraData wird kopiert, der Pointer geht also NICHT in den Besitz
+ // des RedlineObjectes!
+void SwRedlineData::SetExtraData( const SwRedlineExtraData* pData )
+{
+ delete pExtraData;
+
+ if( pData )
+ pExtraData = pData->CreateNew();
+ else
+ pExtraData = 0;
+}
+
+String SwRedlineData::GetDescr() const
+{
+ String aResult;
+
+ aResult += String(SW_RES(STR_REDLINE_INSERT + GetType()));
+
+ return aResult;
+}
+
+SwRedline::SwRedline(RedlineType_t eTyp, const SwPaM& rPam )
+ : SwPaM( *rPam.GetMark(), *rPam.GetPoint() ),
+ pRedlineData( new SwRedlineData( eTyp, GetDoc()->GetRedlineAuthor() ) ),
+ pCntntSect( 0 )
+{
+ bDelLastPara = bIsLastParaDelete = sal_False;
+ bIsVisible = sal_True;
+ if( !rPam.HasMark() )
+ DeleteMark();
+}
+
+SwRedline::SwRedline( const SwRedlineData& rData, const SwPaM& rPam )
+ : SwPaM( *rPam.GetMark(), *rPam.GetPoint() ),
+ pRedlineData( new SwRedlineData( rData )),
+ pCntntSect( 0 )
+{
+ bDelLastPara = bIsLastParaDelete = sal_False;
+ bIsVisible = sal_True;
+ if( !rPam.HasMark() )
+ DeleteMark();
+}
+
+SwRedline::SwRedline( const SwRedlineData& rData, const SwPosition& rPos )
+ : SwPaM( rPos ),
+ pRedlineData( new SwRedlineData( rData )),
+ pCntntSect( 0 )
+{
+ bDelLastPara = bIsLastParaDelete = sal_False;
+ bIsVisible = sal_True;
+}
+
+SwRedline::SwRedline( const SwRedline& rCpy )
+ : SwPaM( *rCpy.GetMark(), *rCpy.GetPoint() ),
+ pRedlineData( new SwRedlineData( *rCpy.pRedlineData )),
+ pCntntSect( 0 )
+{
+ bDelLastPara = bIsLastParaDelete = sal_False;
+ bIsVisible = sal_True;
+ if( !rCpy.HasMark() )
+ DeleteMark();
+}
+
+SwRedline::~SwRedline()
+{
+ if( pCntntSect )
+ {
+ // dann den Content Bereich loeschen
+ if( !GetDoc()->IsInDtor() )
+ GetDoc()->DeleteSection( &pCntntSect->GetNode() );
+ delete pCntntSect;
+ }
+ delete pRedlineData;
+}
+
+// liegt eine gueltige Selektion vor?
+sal_Bool SwRedline::HasValidRange() const
+{
+ const SwNode* pPtNd = &GetPoint()->nNode.GetNode(),
+ * pMkNd = &GetMark()->nNode.GetNode();
+ if( pPtNd->StartOfSectionNode() == pMkNd->StartOfSectionNode() &&
+ !pPtNd->StartOfSectionNode()->IsTableNode() &&
+ // invalid if points on the end of content
+ // end-of-content only invalid if no content index exists
+ ( pPtNd != pMkNd || GetContentIdx() != NULL ||
+ pPtNd != &pPtNd->GetNodes().GetEndOfContent() )
+ )
+ return sal_True;
+ return sal_False;
+}
+
+void SwRedline::CallDisplayFunc( sal_uInt16 nLoop )
+{
+ switch( nsRedlineMode_t::REDLINE_SHOW_MASK & GetDoc()->GetRedlineMode() )
+ {
+ case nsRedlineMode_t::REDLINE_SHOW_INSERT | nsRedlineMode_t::REDLINE_SHOW_DELETE:
+ Show( nLoop );
+ break;
+ case nsRedlineMode_t::REDLINE_SHOW_INSERT:
+ Hide( nLoop );
+ break;
+ case nsRedlineMode_t::REDLINE_SHOW_DELETE:
+ ShowOriginal( nLoop );
+ break;
+ }
+}
+
+void SwRedline::Show( sal_uInt16 nLoop )
+{
+ if( 1 <= nLoop )
+ {
+ SwDoc* pDoc = GetDoc();
+ RedlineMode_t eOld = pDoc->GetRedlineMode();
+ pDoc->SetRedlineMode_intern((RedlineMode_t)(eOld | nsRedlineMode_t::REDLINE_IGNORE));
+ ::sw::UndoGuard const undoGuard(pDoc->GetIDocumentUndoRedo());
+
+ switch( GetType() )
+ {
+ case nsRedlineType_t::REDLINE_INSERT: // Inhalt wurde eingefuegt
+ bIsVisible = sal_True;
+ MoveFromSection();
+ break;
+
+ case nsRedlineType_t::REDLINE_DELETE: // Inhalt wurde geloescht
+ bIsVisible = sal_True;
+ MoveFromSection();
+ break;
+
+ case nsRedlineType_t::REDLINE_FORMAT: // Attributierung wurde angewendet
+ case nsRedlineType_t::REDLINE_TABLE: // TabellenStruktur wurde veraendert
+ InvalidateRange();
+ break;
+ default:
+ break;
+ }
+ pDoc->SetRedlineMode_intern( eOld );
+ }
+}
+
+void SwRedline::Hide( sal_uInt16 nLoop )
+{
+ SwDoc* pDoc = GetDoc();
+ RedlineMode_t eOld = pDoc->GetRedlineMode();
+ pDoc->SetRedlineMode_intern((RedlineMode_t)(eOld | nsRedlineMode_t::REDLINE_IGNORE));
+ ::sw::UndoGuard const undoGuard(pDoc->GetIDocumentUndoRedo());
+
+ switch( GetType() )
+ {
+ case nsRedlineType_t::REDLINE_INSERT: // Inhalt wurde eingefuegt
+ bIsVisible = sal_True;
+ if( 1 <= nLoop )
+ MoveFromSection();
+ break;
+
+ case nsRedlineType_t::REDLINE_DELETE: // Inhalt wurde geloescht
+ bIsVisible = sal_False;
+ switch( nLoop )
+ {
+ case 0: MoveToSection(); break;
+ case 1: CopyToSection(); break;
+ case 2: DelCopyOfSection(); break;
+ }
+ break;
+
+ case nsRedlineType_t::REDLINE_FORMAT: // Attributierung wurde angewendet
+ case nsRedlineType_t::REDLINE_TABLE: // TabellenStruktur wurde veraendert
+ if( 1 <= nLoop )
+ InvalidateRange();
+ break;
+ default:
+ break;
+ }
+ pDoc->SetRedlineMode_intern( eOld );
+}
+
+void SwRedline::ShowOriginal( sal_uInt16 nLoop )
+{
+ SwDoc* pDoc = GetDoc();
+ RedlineMode_t eOld = pDoc->GetRedlineMode();
+ SwRedlineData* pCur;
+
+ pDoc->SetRedlineMode_intern((RedlineMode_t)(eOld | nsRedlineMode_t::REDLINE_IGNORE));
+ ::sw::UndoGuard const undoGuard(pDoc->GetIDocumentUndoRedo());
+
+ // bestimme den Type, ist der erste auf Stack
+ for( pCur = pRedlineData; pCur->pNext; )
+ pCur = pCur->pNext;
+
+ switch( pCur->eType )
+ {
+ case nsRedlineType_t::REDLINE_INSERT: // Inhalt wurde eingefuegt
+ bIsVisible = sal_False;
+ switch( nLoop )
+ {
+ case 0: MoveToSection(); break;
+ case 1: CopyToSection(); break;
+ case 2: DelCopyOfSection(); break;
+ }
+ break;
+
+ case nsRedlineType_t::REDLINE_DELETE: // Inhalt wurde geloescht
+ bIsVisible = sal_True;
+ if( 1 <= nLoop )
+ MoveFromSection();
+ break;
+
+ case nsRedlineType_t::REDLINE_FORMAT: // Attributierung wurde angewendet
+ case nsRedlineType_t::REDLINE_TABLE: // TabellenStruktur wurde veraendert
+ if( 1 <= nLoop )
+ InvalidateRange();
+ break;
+ default:
+ break;
+ }
+ pDoc->SetRedlineMode_intern( eOld );
+}
+
+
+void SwRedline::InvalidateRange() // das Layout anstossen
+{
+ sal_uLong nSttNd = GetMark()->nNode.GetIndex(),
+ nEndNd = GetPoint()->nNode.GetIndex();
+ sal_uInt16 nSttCnt = GetMark()->nContent.GetIndex(),
+ nEndCnt = GetPoint()->nContent.GetIndex();
+
+ if( nSttNd > nEndNd || ( nSttNd == nEndNd && nSttCnt > nEndCnt ))
+ {
+ sal_uLong nTmp = nSttNd; nSttNd = nEndNd; nEndNd = nTmp;
+ nTmp = nSttCnt; nSttCnt = nEndCnt; nEndCnt = (sal_uInt16)nTmp;
+ }
+
+ SwUpdateAttr aHt( 0, 0, RES_FMT_CHG );
+ SwNodes& rNds = GetDoc()->GetNodes();
+ SwNode* pNd;
+ for( sal_uLong n = nSttNd; n <= nEndNd; ++n )
+ if( ND_TEXTNODE == ( pNd = rNds[ n ] )->GetNodeType() )
+ {
+ aHt.nStart = n == nSttNd ? nSttCnt : 0;
+ aHt.nEnd = n == nEndNd ? nEndCnt : ((SwTxtNode*)pNd)->GetTxt().Len();
+ ((SwTxtNode*)pNd)->ModifyNotification( &aHt, &aHt );
+ }
+}
+
+/*************************************************************************
+ * SwRedline::CalcStartEnd()
+ * Calculates the start and end position of the intersection rTmp and
+ * text node nNdIdx
+ *************************************************************************/
+
+void SwRedline::CalcStartEnd( sal_uLong nNdIdx, sal_uInt16& nStart, sal_uInt16& nEnd ) const
+{
+ const SwPosition *pRStt = Start(), *pREnd = End();
+ if( pRStt->nNode < nNdIdx )
+ {
+ if( pREnd->nNode > nNdIdx )
+ {
+ nStart = 0; // Absatz ist komplett enthalten
+ nEnd = STRING_LEN;
+ }
+ else
+ {
+ OSL_ENSURE( pREnd->nNode == nNdIdx,
+ "SwRedlineItr::Seek: GetRedlinePos Error" );
+ nStart = 0; // Absatz wird vorne ueberlappt
+ nEnd = pREnd->nContent.GetIndex();
+ }
+ }
+ else if( pRStt->nNode == nNdIdx )
+ {
+ nStart = pRStt->nContent.GetIndex();
+ if( pREnd->nNode == nNdIdx )
+ nEnd = pREnd->nContent.GetIndex(); // Innerhalb des Absatzes
+ else
+ nEnd = STRING_LEN; // Absatz wird hinten ueberlappt
+ }
+ else
+ {
+ nStart = STRING_LEN;
+ nEnd = STRING_LEN;
+ }
+}
+
+void SwRedline::MoveToSection()
+{
+ if( !pCntntSect )
+ {
+ const SwPosition* pStt = Start(),
+ * pEnd = pStt == GetPoint() ? GetMark() : GetPoint();
+
+ SwDoc* pDoc = GetDoc();
+ SwPaM aPam( *pStt, *pEnd );
+ SwCntntNode* pCSttNd = pStt->nNode.GetNode().GetCntntNode();
+ SwCntntNode* pCEndNd = pEnd->nNode.GetNode().GetCntntNode();
+
+ if( !pCSttNd )
+ {
+ // damit die Indizies der anderen Redlines nicht mitverschoben
+ // werden, diese aufs Ende setzen (ist exclusive).
+ const SwRedlineTbl& rTbl = pDoc->GetRedlineTbl();
+ for( sal_uInt16 n = 0; n < rTbl.Count(); ++n )
+ {
+ SwRedline* pRedl = rTbl[ n ];
+ if( pRedl->GetBound(sal_True) == *pStt )
+ pRedl->GetBound(sal_True) = *pEnd;
+ if( pRedl->GetBound(sal_False) == *pStt )
+ pRedl->GetBound(sal_False) = *pEnd;
+ }
+ }
+
+ SwStartNode* pSttNd;
+ SwNodes& rNds = pDoc->GetNodes();
+ if( pCSttNd || pCEndNd )
+ {
+ SwTxtFmtColl* pColl = (pCSttNd && pCSttNd->IsTxtNode() )
+ ? ((SwTxtNode*)pCSttNd)->GetTxtColl()
+ : (pCEndNd && pCEndNd->IsTxtNode() )
+ ? ((SwTxtNode*)pCEndNd)->GetTxtColl()
+ : pDoc->GetTxtCollFromPool(
+ RES_POOLCOLL_STANDARD );
+
+ pSttNd = rNds.MakeTextSection( SwNodeIndex( rNds.GetEndOfRedlines() ),
+ SwNormalStartNode, pColl );
+ SwTxtNode* pTxtNd = rNds[ pSttNd->GetIndex() + 1 ]->GetTxtNode();
+
+ SwNodeIndex aNdIdx( *pTxtNd );
+ SwPosition aPos( aNdIdx, SwIndex( pTxtNd ));
+ if( pCSttNd && pCEndNd )
+ pDoc->MoveAndJoin( aPam, aPos, IDocumentContentOperations::DOC_MOVEDEFAULT );
+ else
+ {
+ if( pCSttNd && !pCEndNd )
+ bDelLastPara = sal_True;
+ pDoc->MoveRange( aPam, aPos,
+ IDocumentContentOperations::DOC_MOVEDEFAULT );
+ }
+ }
+ else
+ {
+ pSttNd = rNds.MakeEmptySection( SwNodeIndex( rNds.GetEndOfRedlines() ),
+ SwNormalStartNode );
+
+ SwPosition aPos( *pSttNd->EndOfSectionNode() );
+ pDoc->MoveRange( aPam, aPos,
+ IDocumentContentOperations::DOC_MOVEDEFAULT );
+ }
+ pCntntSect = new SwNodeIndex( *pSttNd );
+
+ if( pStt == GetPoint() )
+ Exchange();
+
+ DeleteMark();
+ }
+ else
+ InvalidateRange();
+}
+
+void SwRedline::CopyToSection()
+{
+ if( !pCntntSect )
+ {
+ const SwPosition* pStt = Start(),
+ * pEnd = pStt == GetPoint() ? GetMark() : GetPoint();
+
+ SwCntntNode* pCSttNd = pStt->nNode.GetNode().GetCntntNode();
+ SwCntntNode* pCEndNd = pEnd->nNode.GetNode().GetCntntNode();
+
+ SwStartNode* pSttNd;
+ SwDoc* pDoc = GetDoc();
+ SwNodes& rNds = pDoc->GetNodes();
+
+ sal_Bool bSaveCopyFlag = pDoc->IsCopyIsMove(),
+ bSaveRdlMoveFlg = pDoc->IsRedlineMove();
+ pDoc->SetCopyIsMove( sal_True );
+
+ // The IsRedlineMove() flag causes the behaviour of the
+ // SwDoc::_CopyFlyInFly method to change, which will eventually be
+ // called by the pDoc->Copy line below (through SwDoc::_Copy,
+ // SwDoc::CopyWithFlyInFly). This rather obscure bugfix
+ // apparently never really worked.
+ pDoc->SetRedlineMove( pStt->nContent == 0 );
+
+ if( pCSttNd )
+ {
+ SwTxtFmtColl* pColl = (pCSttNd && pCSttNd->IsTxtNode() )
+ ? ((SwTxtNode*)pCSttNd)->GetTxtColl()
+ : pDoc->GetTxtCollFromPool(
+ RES_POOLCOLL_STANDARD );
+
+ pSttNd = rNds.MakeTextSection( SwNodeIndex( rNds.GetEndOfRedlines() ),
+ SwNormalStartNode, pColl );
+
+ SwNodeIndex aNdIdx( *pSttNd, 1 );
+ SwTxtNode* pTxtNd = aNdIdx.GetNode().GetTxtNode();
+ SwPosition aPos( aNdIdx, SwIndex( pTxtNd ));
+ pDoc->CopyRange( *this, aPos, false );
+
+ // die Vorlage vom EndNode ggfs. mit uebernehmen
+ // - ist im Doc::Copy nicht erwuenscht
+ if( pCEndNd && pCEndNd != pCSttNd )
+ {
+ SwCntntNode* pDestNd = aPos.nNode.GetNode().GetCntntNode();
+ if( pDestNd )
+ {
+ if( pDestNd->IsTxtNode() && pCEndNd->IsTxtNode() )
+ ((SwTxtNode*)pCEndNd)->CopyCollFmt(
+ *(SwTxtNode*)pDestNd );
+ else
+ pDestNd->ChgFmtColl( pCEndNd->GetFmtColl() );
+ }
+ }
+ }
+ else
+ {
+ pSttNd = rNds.MakeEmptySection( SwNodeIndex( rNds.GetEndOfRedlines() ),
+ SwNormalStartNode );
+
+ if( pCEndNd )
+ {
+ SwPosition aPos( *pSttNd->EndOfSectionNode() );
+ pDoc->CopyRange( *this, aPos, false );
+ }
+ else
+ {
+ SwNodeIndex aInsPos( *pSttNd->EndOfSectionNode() );
+ SwNodeRange aRg( pStt->nNode, 0, pEnd->nNode, 1 );
+ pDoc->CopyWithFlyInFly( aRg, 0, aInsPos );
+ }
+ }
+ pCntntSect = new SwNodeIndex( *pSttNd );
+
+ pDoc->SetCopyIsMove( bSaveCopyFlag );
+ pDoc->SetRedlineMove( bSaveRdlMoveFlg );
+ }
+}
+
+void SwRedline::DelCopyOfSection()
+{
+ if( pCntntSect )
+ {
+ const SwPosition* pStt = Start(),
+ * pEnd = pStt == GetPoint() ? GetMark() : GetPoint();
+
+ SwDoc* pDoc = GetDoc();
+ SwPaM aPam( *pStt, *pEnd );
+ SwCntntNode* pCSttNd = pStt->nNode.GetNode().GetCntntNode();
+ SwCntntNode* pCEndNd = pEnd->nNode.GetNode().GetCntntNode();
+
+ if( !pCSttNd )
+ {
+ // damit die Indizies der anderen Redlines nicht mitverschoben
+ // werden, diese aufs Ende setzen (ist exclusive).
+ const SwRedlineTbl& rTbl = pDoc->GetRedlineTbl();
+ for( sal_uInt16 n = 0; n < rTbl.Count(); ++n )
+ {
+ SwRedline* pRedl = rTbl[ n ];
+ if( pRedl->GetBound(sal_True) == *pStt )
+ pRedl->GetBound(sal_True) = *pEnd;
+ if( pRedl->GetBound(sal_False) == *pStt )
+ pRedl->GetBound(sal_False) = *pEnd;
+ }
+ }
+
+ if( pCSttNd && pCEndNd )
+ {
+ // #i100466# - force a <join next> on <delete and join> operation
+ pDoc->DeleteAndJoin( aPam, true );
+ }
+ else if( pCSttNd || pCEndNd )
+ {
+ if( pCSttNd && !pCEndNd )
+ bDelLastPara = sal_True;
+ pDoc->DeleteRange( aPam );
+
+ if( bDelLastPara )
+ {
+ // To prevent dangling references to the paragraph to
+ // be deleted, redline that point into this paragraph should be
+ // moved to the new end position. Since redlines in the redline
+ // table are sorted and the pEnd position is an endnode (see
+ // bDelLastPara condition above), only redlines before the
+ // current ones can be affected.
+ const SwRedlineTbl& rTbl = pDoc->GetRedlineTbl();
+ sal_uInt16 n = rTbl.GetPos( this );
+ OSL_ENSURE( n != USHRT_MAX, "How strange. We don't exist!" );
+ for( sal_Bool bBreak = sal_False; !bBreak && n > 0; )
+ {
+ --n;
+ bBreak = sal_True;
+ if( rTbl[ n ]->GetBound(sal_True) == *aPam.GetPoint() )
+ {
+ rTbl[ n ]->GetBound(sal_True) = *pEnd;
+ bBreak = sal_False;
+ }
+ if( rTbl[ n ]->GetBound(sal_False) == *aPam.GetPoint() )
+ {
+ rTbl[ n ]->GetBound(sal_False) = *pEnd;
+ bBreak = sal_False;
+ }
+ }
+
+ SwPosition aEnd( *pEnd );
+ *GetPoint() = *pEnd;
+ *GetMark() = *pEnd;
+ DeleteMark();
+
+ aPam.GetBound( sal_True ).nContent.Assign( 0, 0 );
+ aPam.GetBound( sal_False ).nContent.Assign( 0, 0 );
+ aPam.DeleteMark();
+ pDoc->DelFullPara( aPam );
+ }
+ }
+ else
+ {
+ pDoc->DeleteRange( aPam );
+ }
+
+ if( pStt == GetPoint() )
+ Exchange();
+
+ DeleteMark();
+ }
+}
+
+void SwRedline::MoveFromSection()
+{
+ if( pCntntSect )
+ {
+ SwDoc* pDoc = GetDoc();
+ const SwRedlineTbl& rTbl = pDoc->GetRedlineTbl();
+ SvPtrarr aBeforeArr( 16, 16 ), aBehindArr( 16, 16 );
+ sal_uInt16 nMyPos = rTbl.GetPos( this );
+ OSL_ENSURE( this, "this nicht im Array?" );
+ sal_Bool bBreak = sal_False;
+ sal_uInt16 n;
+
+ for( n = nMyPos+1; !bBreak && n < rTbl.Count(); ++n )
+ {
+ bBreak = sal_True;
+ if( rTbl[ n ]->GetBound(sal_True) == *GetPoint() )
+ {
+ void* pTmp = &rTbl[ n ]->GetBound(sal_True);
+ aBehindArr.Insert( pTmp, aBehindArr.Count());
+ bBreak = sal_False;
+ }
+ if( rTbl[ n ]->GetBound(sal_False) == *GetPoint() )
+ {
+ void* pTmp = &rTbl[ n ]->GetBound(sal_False);
+ aBehindArr.Insert( pTmp, aBehindArr.Count() );
+ bBreak = sal_False;
+ }
+ }
+ for( bBreak = sal_False, n = nMyPos; !bBreak && n ; )
+ {
+ --n;
+ bBreak = sal_True;
+ if( rTbl[ n ]->GetBound(sal_True) == *GetPoint() )
+ {
+ void* pTmp = &rTbl[ n ]->GetBound(sal_True);
+ aBeforeArr.Insert( pTmp, aBeforeArr.Count() );
+ bBreak = sal_False;
+ }
+ if( rTbl[ n ]->GetBound(sal_False) == *GetPoint() )
+ {
+ void* pTmp = &rTbl[ n ]->GetBound(sal_False);
+ aBeforeArr.Insert( pTmp, aBeforeArr.Count() );
+ bBreak = sal_False;
+ }
+ }
+
+ const SwNode* pKeptCntntSectNode( &pCntntSect->GetNode() ); // #i95711#
+ {
+ SwPaM aPam( pCntntSect->GetNode(),
+ *pCntntSect->GetNode().EndOfSectionNode(), 1,
+ ( bDelLastPara ? -2 : -1 ) );
+ SwCntntNode* pCNd = aPam.GetCntntNode();
+ if( pCNd )
+ aPam.GetPoint()->nContent.Assign( pCNd, pCNd->Len() );
+ else
+ aPam.GetPoint()->nNode++;
+
+ SwFmtColl* pColl = pCNd && pCNd->Len() && aPam.GetPoint()->nNode !=
+ aPam.GetMark()->nNode
+ ? pCNd->GetFmtColl() : 0;
+
+ SwNodeIndex aNdIdx( GetPoint()->nNode, -1 );
+ sal_uInt16 nPos = GetPoint()->nContent.GetIndex();
+
+ SwPosition aPos( *GetPoint() );
+ if( bDelLastPara && *aPam.GetPoint() == *aPam.GetMark() )
+ {
+ aPos.nNode--;
+
+ pDoc->AppendTxtNode( aPos );
+ }
+ else
+ {
+ pDoc->MoveRange( aPam, aPos,
+ IDocumentContentOperations::DOC_MOVEALLFLYS );
+ }
+
+ SetMark();
+ *GetPoint() = aPos;
+ GetMark()->nNode = aNdIdx.GetIndex() + 1;
+ pCNd = GetMark()->nNode.GetNode().GetCntntNode();
+ GetMark()->nContent.Assign( pCNd, nPos );
+
+ if( bDelLastPara )
+ {
+ GetPoint()->nNode++;
+ GetPoint()->nContent.Assign( pCNd = GetCntntNode(), 0 );
+ bDelLastPara = sal_False;
+ }
+ else if( pColl )
+ pCNd = GetCntntNode();
+
+ if( pColl && pCNd )
+ pCNd->ChgFmtColl( pColl );
+ }
+ // #i95771#
+ // Under certain conditions the previous <SwDoc::Move(..)> has already
+ // remove the change tracking section of this <SwRedline> instance from
+ // the change tracking nodes area.
+ // Thus, check, if <pCntntSect> still points to the change tracking section
+ // by comparing it with the "indexed" <SwNode> instance copied before
+ // perform the intrinsic move.
+ // Note: Such condition is e.g. a "delete" change tracking only containing a table.
+ if ( &pCntntSect->GetNode() == pKeptCntntSectNode )
+ {
+ pDoc->DeleteSection( &pCntntSect->GetNode() );
+ }
+ // <--
+ delete pCntntSect, pCntntSect = 0;
+
+ // adjustment of redline table positions must take start and
+ // end into account, not point and mark.
+ for( n = 0; n < aBeforeArr.Count(); ++n )
+ *(SwPosition*)aBeforeArr[ n ] = *Start();
+ for( n = 0; n < aBehindArr.Count(); ++n )
+ *(SwPosition*)aBehindArr[ n ] = *End();
+ }
+ else
+ InvalidateRange();
+}
+
+// fuers Undo
+void SwRedline::SetContentIdx( const SwNodeIndex* pIdx )
+{
+ if( pIdx && !pCntntSect )
+ {
+ pCntntSect = new SwNodeIndex( *pIdx );
+ bIsVisible = sal_False;
+ }
+ else if( !pIdx && pCntntSect )
+ {
+ delete pCntntSect, pCntntSect = 0;
+ bIsVisible = sal_False;
+ }
+#if OSL_DEBUG_LEVEL > 1
+ else
+ OSL_ENSURE( !this, "das ist keine gueltige Operation" );
+#endif
+}
+
+sal_Bool SwRedline::CanCombine( const SwRedline& rRedl ) const
+{
+ return IsVisible() && rRedl.IsVisible() &&
+ pRedlineData->CanCombine( *rRedl.pRedlineData );
+}
+
+void SwRedline::PushData( const SwRedline& rRedl, sal_Bool bOwnAsNext )
+{
+ SwRedlineData* pNew = new SwRedlineData( *rRedl.pRedlineData, sal_False );
+ if( bOwnAsNext )
+ {
+ pNew->pNext = pRedlineData;
+ pRedlineData = pNew;
+ }
+ else
+ {
+ pNew->pNext = pRedlineData->pNext;
+ pRedlineData->pNext = pNew;
+ }
+}
+
+sal_Bool SwRedline::PopData()
+{
+ if( !pRedlineData->pNext )
+ return sal_False;
+ SwRedlineData* pCur = pRedlineData;
+ pRedlineData = pCur->pNext;
+ pCur->pNext = 0;
+ delete pCur;
+ return sal_True;
+}
+
+sal_uInt16 SwRedline::GetStackCount() const
+{
+ sal_uInt16 nRet = 1;
+ for( SwRedlineData* pCur = pRedlineData; pCur->pNext; ++nRet )
+ pCur = pCur->pNext;
+ return nRet;
+}
+
+sal_uInt16 SwRedline::GetAuthor( sal_uInt16 nPos ) const
+{
+ return GetRedlineData(nPos).nAuthor;
+}
+
+const String& SwRedline::GetAuthorString( sal_uInt16 nPos ) const
+{
+ return SW_MOD()->GetRedlineAuthor(GetRedlineData(nPos).nAuthor);
+}
+
+const DateTime& SwRedline::GetTimeStamp( sal_uInt16 nPos ) const
+{
+ return GetRedlineData(nPos).aStamp;
+}
+
+RedlineType_t SwRedline::GetRealType( sal_uInt16 nPos ) const
+{
+ return GetRedlineData(nPos).eType;
+}
+
+const String& SwRedline::GetComment( sal_uInt16 nPos ) const
+{
+ return GetRedlineData(nPos).sComment;
+}
+
+int SwRedline::operator==( const SwRedline& rCmp ) const
+{
+ return this == &rCmp;
+}
+
+int SwRedline::operator<( const SwRedline& rCmp ) const
+{
+ sal_Bool nResult = sal_False;
+
+ if (*Start() < *rCmp.Start())
+ nResult = sal_True;
+ else if (*Start() == *rCmp.Start())
+ if (*End() < *rCmp.End())
+ nResult = sal_True;
+
+ return nResult;
+}
+
+const SwRedlineData & SwRedline::GetRedlineData(sal_uInt16 nPos) const
+{
+ SwRedlineData * pCur = pRedlineData;
+
+ while (nPos > 0 && NULL != pCur->pNext)
+ {
+ pCur = pCur->pNext;
+
+ nPos--;
+ }
+
+ OSL_ENSURE( 0 == nPos, "Pos angabe ist zu gross" );
+
+ return *pCur;
+}
+
+String SwRedline::GetDescr(sal_uInt16 nPos)
+{
+ String aResult;
+
+ // get description of redline data (e.g.: "insert $1")
+ aResult = GetRedlineData(nPos).GetDescr();
+
+ SwPaM * pPaM = NULL;
+ bool bDeletePaM = false;
+
+ // if this redline is visible the content is in this PaM
+ if (NULL == pCntntSect)
+ {
+ pPaM = this;
+ }
+ else // otherwise it is saved in pCntntSect
+ {
+ SwNodeIndex aTmpIdx( *pCntntSect->GetNode().EndOfSectionNode() );
+ pPaM = new SwPaM(*pCntntSect, aTmpIdx );
+ bDeletePaM = true;
+ }
+
+ // replace $1 in description by description of the redlines text
+ String aTmpStr;
+ aTmpStr += String(SW_RES(STR_START_QUOTE));
+ aTmpStr += ShortenString(pPaM->GetTxt(), nUndoStringLength,
+ String(SW_RES(STR_LDOTS)));
+ aTmpStr += String(SW_RES(STR_END_QUOTE));
+
+ SwRewriter aRewriter;
+ aRewriter.AddRule(UNDO_ARG1, aTmpStr);
+
+ aResult = aRewriter.Apply(aResult);
+
+ if (bDeletePaM)
+ delete pPaM;
+
+ return aResult;
+}
+
+
+bool SwDoc::IsInRedlines(const SwNode & rNode) const
+{
+ SwPosition aPos(rNode);
+ SwNode & rEndOfRedlines = GetNodes().GetEndOfRedlines();
+ SwPaM aPam(SwPosition(*rEndOfRedlines.StartOfSectionNode()),
+ SwPosition(rEndOfRedlines));
+
+ return aPam.ContainsPosition(aPos) ? true : false;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/doc/docruby.cxx b/sw/source/core/doc/docruby.cxx
new file mode 100644
index 000000000000..564e8d7e6989
--- /dev/null
+++ b/sw/source/core/doc/docruby.cxx
@@ -0,0 +1,343 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+#include <string.h> // fuer strchr()
+
+#include <com/sun/star/i18n/UnicodeType.hdl>
+#include <com/sun/star/i18n/WordType.hdl>
+
+#include <unotools/charclass.hxx>
+
+#include <hintids.hxx>
+#include <doc.hxx>
+#include <IDocumentUndoRedo.hxx>
+#include <docary.hxx>
+#include <mvsave.hxx> // Strukturen zum Sichern beim Move/Delete
+#include <ndtxt.hxx>
+#include <txatbase.hxx>
+#include <rubylist.hxx>
+#include <pam.hxx>
+#include <swundo.hxx> // fuer die UndoIds
+#include <breakit.hxx>
+#include <crsskip.hxx>
+
+SV_IMPL_PTRARR( SwRubyList, SwRubyListEntryPtr )
+
+using namespace ::com::sun::star::i18n;
+
+
+/*
+ * Members in the list:
+ * - String - the orig text
+ * - SwFmtRuby - the ruby attribut
+ *
+ *
+ */
+sal_uInt16 SwDoc::FillRubyList( const SwPaM& rPam, SwRubyList& rList,
+ sal_uInt16 nMode )
+{
+ const SwPaM *_pStartCrsr = (SwPaM*)rPam.GetNext(),
+ *__pStartCrsr = _pStartCrsr;
+ sal_Bool bCheckEmpty = &rPam != _pStartCrsr;
+ do {
+ const SwPosition* pStt = _pStartCrsr->Start(),
+ * pEnd = pStt == _pStartCrsr->GetPoint()
+ ? _pStartCrsr->GetMark()
+ : _pStartCrsr->GetPoint();
+ if( !bCheckEmpty || ( pStt != pEnd && *pStt != *pEnd ))
+ {
+ SwPaM aPam( *pStt );
+ do {
+ SwRubyListEntry* pNew = new SwRubyListEntry;
+ if( pEnd != pStt )
+ {
+ aPam.SetMark();
+ *aPam.GetMark() = *pEnd;
+ }
+ if( _SelectNextRubyChars( aPam, *pNew, nMode ))
+ {
+ rList.Insert( pNew, rList.Count() );
+ aPam.DeleteMark();
+ }
+ else
+ {
+ delete pNew;
+ if( *aPam.GetPoint() < *pEnd )
+ {
+ // goto next paragraph
+ aPam.DeleteMark();
+ aPam.Move( fnMoveForward, fnGoNode );
+ }
+ else
+ break;
+ }
+ } while( 30 > rList.Count() && *aPam.GetPoint() < *pEnd );
+ }
+ } while( 30 > rList.Count() &&
+ (_pStartCrsr=(SwPaM *)_pStartCrsr->GetNext()) != __pStartCrsr );
+
+ return rList.Count();
+}
+
+sal_uInt16 SwDoc::SetRubyList( const SwPaM& rPam, const SwRubyList& rList,
+ sal_uInt16 nMode )
+{
+ GetIDocumentUndoRedo().StartUndo( UNDO_SETRUBYATTR, NULL );
+ SvUShortsSort aDelArr;
+ aDelArr.Insert( RES_TXTATR_CJK_RUBY );
+
+ sal_uInt16 nListEntry = 0;
+
+ const SwPaM *_pStartCrsr = (SwPaM*)rPam.GetNext(),
+ *__pStartCrsr = _pStartCrsr;
+ sal_Bool bCheckEmpty = &rPam != _pStartCrsr;
+ do {
+ const SwPosition* pStt = _pStartCrsr->Start(),
+ * pEnd = pStt == _pStartCrsr->GetPoint()
+ ? _pStartCrsr->GetMark()
+ : _pStartCrsr->GetPoint();
+ if( !bCheckEmpty || ( pStt != pEnd && *pStt != *pEnd ))
+ {
+
+ SwPaM aPam( *pStt );
+ do {
+ SwRubyListEntry aCheckEntry;
+ if( pEnd != pStt )
+ {
+ aPam.SetMark();
+ *aPam.GetMark() = *pEnd;
+ }
+ if( _SelectNextRubyChars( aPam, aCheckEntry, nMode ))
+ {
+ const SwRubyListEntry* pEntry = rList[ nListEntry++ ];
+ if( aCheckEntry.GetRubyAttr() != pEntry->GetRubyAttr() )
+ {
+ // set/reset the attribut
+ if( pEntry->GetRubyAttr().GetText().Len() )
+ {
+ InsertPoolItem( aPam, pEntry->GetRubyAttr(), 0 );
+ }
+ else
+ {
+ ResetAttrs( aPam, sal_True, &aDelArr );
+ }
+ }
+
+ if( aCheckEntry.GetText() != pEntry->GetText() &&
+ pEntry->GetText().Len() )
+ {
+ // text is changed, so replace the original
+ ReplaceRange( aPam, pEntry->GetText(), false );
+ }
+ aPam.DeleteMark();
+ }
+ else
+ {
+ if( *aPam.GetPoint() < *pEnd )
+ {
+ // goto next paragraph
+ aPam.DeleteMark();
+ aPam.Move( fnMoveForward, fnGoNode );
+ }
+ else
+ {
+ const SwRubyListEntry* pEntry = rList[ nListEntry++ ];
+
+ // set/reset the attribut
+ if( pEntry->GetRubyAttr().GetText().Len() &&
+ pEntry->GetText().Len() )
+ {
+ InsertString( aPam, pEntry->GetText() );
+ aPam.SetMark();
+ aPam.GetMark()->nContent -= pEntry->GetText().Len();
+ InsertPoolItem( aPam, pEntry->GetRubyAttr(),
+ nsSetAttrMode::SETATTR_DONTEXPAND );
+ }
+ else
+ break;
+ aPam.DeleteMark();
+ }
+ }
+ } while( nListEntry < rList.Count() && *aPam.GetPoint() < *pEnd );
+ }
+ } while( 30 > rList.Count() &&
+ (_pStartCrsr=(SwPaM *)_pStartCrsr->GetNext()) != __pStartCrsr );
+
+ GetIDocumentUndoRedo().EndUndo( UNDO_SETRUBYATTR, NULL );
+
+ return nListEntry;
+}
+
+sal_Bool SwDoc::_SelectNextRubyChars( SwPaM& rPam, SwRubyListEntry& rEntry, sal_uInt16 )
+{
+ // Point must be the startposition, Mark is optional the end position
+ SwPosition* pPos = rPam.GetPoint();
+ const SwTxtNode* pTNd = pPos->nNode.GetNode().GetTxtNode();
+ const String* pTxt = &pTNd->GetTxt();
+ xub_StrLen nStart = pPos->nContent.GetIndex(), nEnd = pTxt->Len();
+
+ sal_Bool bHasMark = rPam.HasMark();
+ if( bHasMark )
+ {
+ // in the same node?
+ if( rPam.GetMark()->nNode == pPos->nNode )
+ {
+ // then use that end
+ xub_StrLen nTEnd = rPam.GetMark()->nContent.GetIndex();
+ if( nTEnd < nEnd )
+ nEnd = nTEnd;
+ }
+ rPam.DeleteMark();
+ }
+
+ // ----- search the start
+ // --- look where a ruby attribut starts
+ sal_uInt16 nHtIdx = USHRT_MAX;
+ const SwpHints* pHts = pTNd->GetpSwpHints();
+ const SwTxtAttr* pAttr = 0;
+ if( pHts )
+ {
+ const SwTxtAttr* pHt;
+ for( nHtIdx = 0; nHtIdx < pHts->Count(); ++nHtIdx )
+ if( RES_TXTATR_CJK_RUBY == ( pHt = (*pHts)[ nHtIdx ])->Which() &&
+ *pHt->GetAnyEnd() > nStart )
+ {
+ if( *pHt->GetStart() < nEnd )
+ {
+ pAttr = pHt;
+ if( !bHasMark && nStart > *pAttr->GetStart() )
+ {
+ nStart = *pAttr->GetStart();
+ pPos->nContent = nStart;
+ }
+ }
+ break;
+ }
+ }
+
+ if( !bHasMark && nStart && ( !pAttr || nStart != *pAttr->GetStart()) )
+ {
+ // skip to the word begin!
+ long nWordStt = pBreakIt->GetBreakIter()->getWordBoundary(
+ *pTxt, nStart,
+ pBreakIt->GetLocale( pTNd->GetLang( nStart )),
+ WordType::ANYWORD_IGNOREWHITESPACES,
+ sal_True ).startPos;
+ if( nWordStt < nStart && -1 != nWordStt )
+ {
+ nStart = (xub_StrLen)nWordStt;
+ pPos->nContent = nStart;
+ }
+ }
+
+ sal_Bool bAlphaNum = sal_False;
+ long nWordEnd = nEnd;
+ CharClass& rCC = GetAppCharClass();
+ while( nStart < nEnd )
+ {
+ if( pAttr && nStart == *pAttr->GetStart() )
+ {
+ pPos->nContent = nStart;
+ if( !rPam.HasMark() )
+ {
+ rPam.SetMark();
+ pPos->nContent = *pAttr->GetAnyEnd();
+ if( pPos->nContent.GetIndex() > nEnd )
+ pPos->nContent = nEnd;
+ rEntry.SetRubyAttr( pAttr->GetRuby() );
+ }
+ break;
+ }
+
+ sal_Int32 nChType = rCC.getType( *pTxt, nStart );
+ sal_Bool bIgnoreChar = sal_False, bIsAlphaNum = sal_False, bChkNxtWrd = sal_False;
+ switch( nChType )
+ {
+ case UnicodeType::UPPERCASE_LETTER:
+ case UnicodeType::LOWERCASE_LETTER:
+ case UnicodeType::TITLECASE_LETTER:
+ case UnicodeType::DECIMAL_DIGIT_NUMBER:
+ bChkNxtWrd = bIsAlphaNum = sal_True;
+ break;
+
+ case UnicodeType::SPACE_SEPARATOR:
+ case UnicodeType::CONTROL:
+/*??*/ case UnicodeType::PRIVATE_USE:
+ case UnicodeType::START_PUNCTUATION:
+ case UnicodeType::END_PUNCTUATION:
+ bIgnoreChar = sal_True;
+ break;
+
+
+ case UnicodeType::OTHER_LETTER:
+ bChkNxtWrd = sal_True;
+
+ default:
+ bIsAlphaNum = sal_False;
+ break;
+ }
+
+ if( rPam.HasMark() )
+ {
+ if( bIgnoreChar || bIsAlphaNum != bAlphaNum || nStart >= nWordEnd )
+ break;
+ }
+ else if( !bIgnoreChar )
+ {
+ rPam.SetMark();
+ bAlphaNum = bIsAlphaNum;
+ if( bChkNxtWrd && pBreakIt->GetBreakIter().is() )
+ {
+ // search the end of this word
+ nWordEnd = pBreakIt->GetBreakIter()->getWordBoundary(
+ *pTxt, nStart,
+ pBreakIt->GetLocale( pTNd->GetLang( nStart )),
+ WordType::ANYWORD_IGNOREWHITESPACES,
+ sal_True ).endPos;
+ if( 0 > nWordEnd || nWordEnd > nEnd || nWordEnd == nStart )
+ nWordEnd = nEnd;
+ }
+ }
+ pTNd->GoNext( &pPos->nContent, CRSR_SKIP_CHARS );
+ nStart = pPos->nContent.GetIndex();
+ }
+
+ nStart = rPam.GetMark()->nContent.GetIndex();
+ rEntry.SetText( pTxt->Copy( nStart,
+ rPam.GetPoint()->nContent.GetIndex() - nStart ));
+ return rPam.HasMark();
+}
+
+SwRubyListEntry::~SwRubyListEntry()
+{
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/doc/docsort.cxx b/sw/source/core/doc/docsort.cxx
new file mode 100644
index 000000000000..62b9560151c6
--- /dev/null
+++ b/sw/source/core/doc/docsort.cxx
@@ -0,0 +1,986 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+#include <hintids.hxx>
+#include <rtl/math.hxx>
+#include <unotools/collatorwrapper.hxx>
+#include <unotools/localedatawrapper.hxx>
+#include <com/sun/star/lang/XMultiServiceFactory.hpp>
+#include <com/sun/star/i18n/CollatorOptions.hpp>
+#include <comphelper/processfactory.hxx>
+#include <editeng/unolingu.hxx>
+#include <docary.hxx>
+#include <fmtanchr.hxx>
+#include <frmfmt.hxx>
+#include <doc.hxx>
+#include <IDocumentUndoRedo.hxx>
+#include <node.hxx>
+#include <pam.hxx>
+#include <ndtxt.hxx>
+#include <swtable.hxx>
+#include <swundo.hxx>
+#include <sortopt.hxx>
+#include <docsort.hxx>
+#include <UndoSort.hxx>
+#include <UndoRedline.hxx>
+#include <hints.hxx>
+#include <tblsel.hxx>
+#include <cellatr.hxx>
+#include <redline.hxx>
+#include <node2lay.hxx>
+#include <unochart.hxx>
+
+using namespace ::com::sun::star::lang;
+
+SwSortOptions* SwSortElement::pOptions = 0;
+SwDoc* SwSortElement::pDoc = 0;
+const FlatFndBox* SwSortElement::pBox = 0;
+CollatorWrapper* SwSortElement::pSortCollator = 0;
+Locale* SwSortElement::pLocale = 0;
+String* SwSortElement::pLastAlgorithm = 0;
+LocaleDataWrapper* SwSortElement::pLclData = 0;
+
+SV_IMPL_OP_PTRARR_SORT( SwSortElements, SwSortElementPtr );
+
+/*--------------------------------------------------------------------
+ Beschreibung: Ein Sortierelement fuers Sort konstruieren
+ --------------------------------------------------------------------*/
+void SwSortElement::Init( SwDoc* pD, const SwSortOptions& rOpt,
+ FlatFndBox* pFltBx )
+{
+ OSL_ENSURE( !pDoc && !pOptions && !pBox, "wer hat das Finit vergessen?" );
+ pDoc = pD;
+ pOptions = new SwSortOptions( rOpt );
+ pBox = pFltBx;
+
+ LanguageType nLang = rOpt.nLanguage;
+ switch ( nLang )
+ {
+ case LANGUAGE_NONE:
+ case LANGUAGE_DONTKNOW:
+ nLang = (LanguageType)GetAppLanguage();
+ break;
+ }
+ pLocale = new Locale( SvxCreateLocale( nLang ) );
+
+ pSortCollator = new CollatorWrapper(
+ ::comphelper::getProcessServiceFactory() );
+}
+
+void SwSortElement::Finit()
+{
+ delete pOptions, pOptions = 0;
+ delete pLocale, pLocale = 0;
+ delete pLastAlgorithm, pLastAlgorithm = 0;
+ delete pSortCollator, pSortCollator = 0;
+ delete pLclData, pLclData = 0;
+ pDoc = 0;
+ pBox = 0;
+}
+
+SwSortElement::~SwSortElement()
+{
+}
+
+double SwSortElement::StrToDouble( const String& rStr ) const
+{
+ if( !pLclData )
+ pLclData = new LocaleDataWrapper(
+ ::comphelper::getProcessServiceFactory(), *pLocale );
+
+ rtl_math_ConversionStatus eStatus;
+ sal_Int32 nEnd;
+ double nRet = ::rtl::math::stringToDouble( rStr,
+ pLclData->getNumDecimalSep().GetChar(0),
+ pLclData->getNumThousandSep().GetChar(0),
+ &eStatus, &nEnd );
+
+ if( rtl_math_ConversionStatus_Ok != eStatus || nEnd == 0 )
+ nRet = 0.0;
+ return nRet;
+}
+
+/*--------------------------------------------------------------------
+ Beschreibung: Operatoren zum Vergleichen
+ --------------------------------------------------------------------*/
+sal_Bool SwSortElement::operator==(const SwSortElement& )
+{
+ return sal_False;
+}
+
+/*--------------------------------------------------------------------
+ Beschreibung: Kleiner-Operator fuers sortieren
+ --------------------------------------------------------------------*/
+sal_Bool SwSortElement::operator<(const SwSortElement& rCmp)
+{
+
+ // der eigentliche Vergleich
+ //
+ for(sal_uInt16 nKey = 0; nKey < pOptions->aKeys.Count(); ++nKey)
+ {
+ const SwSortElement *pOrig, *pCmp;
+
+ const SwSortKey* pSrtKey = pOptions->aKeys[ nKey ];
+ if( pSrtKey->eSortOrder == SRT_ASCENDING )
+ pOrig = this, pCmp = &rCmp;
+ else
+ pOrig = &rCmp, pCmp = this;
+
+ if( pSrtKey->bIsNumeric )
+ {
+ double n1 = pOrig->GetValue( nKey );
+ double n2 = pCmp->GetValue( nKey );
+
+ if( n1 == n2 )
+ continue;
+
+ return n1 < n2;
+ }
+ else
+ {
+ if( !pLastAlgorithm || *pLastAlgorithm != pSrtKey->sSortType )
+ {
+ if( pLastAlgorithm )
+ *pLastAlgorithm = pSrtKey->sSortType;
+ else
+ pLastAlgorithm = new String( pSrtKey->sSortType );
+ pSortCollator->loadCollatorAlgorithm( *pLastAlgorithm,
+ *pLocale,
+ pOptions->bIgnoreCase ? SW_COLLATOR_IGNORES : 0 );
+ }
+
+ sal_Int32 nCmp = pSortCollator->compareString(
+ pOrig->GetKey( nKey ), pCmp->GetKey( nKey ));
+ if( 0 == nCmp )
+ continue;
+
+ return -1 == nCmp;
+ }
+ }
+ return sal_False;
+}
+
+double SwSortElement::GetValue( sal_uInt16 nKey ) const
+{
+ return StrToDouble( GetKey( nKey ));
+}
+
+/*--------------------------------------------------------------------
+ Beschreibung: SortierElemente fuer Text
+ --------------------------------------------------------------------*/
+SwSortTxtElement::SwSortTxtElement(const SwNodeIndex& rPos)
+ : nOrg(rPos.GetIndex()), aPos(rPos)
+{
+}
+
+SwSortTxtElement::~SwSortTxtElement()
+{
+}
+
+/*--------------------------------------------------------------------
+ Beschreibung: Key ermitteln
+ --------------------------------------------------------------------*/
+String SwSortTxtElement::GetKey(sal_uInt16 nId) const
+{
+ SwTxtNode* pTxtNd = aPos.GetNode().GetTxtNode();
+ if( !pTxtNd )
+ return aEmptyStr;
+
+ // fuer TextNodes
+ const String& rStr = pTxtNd->GetTxt();
+
+ sal_Unicode nDeli = pOptions->cDeli;
+ sal_uInt16 nDCount = pOptions->aKeys[nId]->nColumnId, i = 1;
+ xub_StrLen nStart = 0;
+
+ // Den Delimitter suchen
+ while( nStart != STRING_NOTFOUND && i < nDCount)
+ if( STRING_NOTFOUND != ( nStart = rStr.Search( nDeli, nStart ) ) )
+ {
+ nStart++;
+ i++;
+ }
+
+ // naechsten Delimitter gefunden oder Ende des Strings und Kopieren
+ xub_StrLen nEnd = rStr.Search( nDeli, nStart+1 );
+ return rStr.Copy( nStart, nEnd-nStart );
+}
+
+/*--------------------------------------------------------------------
+ Beschreibung: Sortier-Elemente fuer Tabellen
+ --------------------------------------------------------------------*/
+SwSortBoxElement::SwSortBoxElement( sal_uInt16 nRC )
+ : nRow( nRC )
+{
+}
+
+SwSortBoxElement::~SwSortBoxElement()
+{
+}
+
+/*--------------------------------------------------------------------
+ Beschreibung: Schluessel zu einer Zelle ermitteln
+ --------------------------------------------------------------------*/
+String SwSortBoxElement::GetKey(sal_uInt16 nKey) const
+{
+ const _FndBox* pFndBox;
+ sal_uInt16 nCol = pOptions->aKeys[nKey]->nColumnId-1;
+
+ if( SRT_ROWS == pOptions->eDirection )
+ pFndBox = pBox->GetBox(nCol, nRow); // Zeilen sortieren
+ else
+ pFndBox = pBox->GetBox(nRow, nCol); // Spalten sortieren
+
+ // Den Text rausfieseln
+ String aRetStr;
+ if( pFndBox )
+ { // StartNode holen und ueberlesen
+ const SwTableBox* pMyBox = pFndBox->GetBox();
+ OSL_ENSURE(pMyBox, "Keine atomare Box");
+
+ if( pMyBox->GetSttNd() )
+ {
+ // ueber alle TextNodes der Box
+ const SwNode *pNd = 0, *pEndNd = pMyBox->GetSttNd()->EndOfSectionNode();
+ for( sal_uLong nIdx = pMyBox->GetSttIdx() + 1; pNd != pEndNd; ++nIdx )
+ if( ( pNd = pDoc->GetNodes()[ nIdx ])->IsTxtNode() )
+ aRetStr += ((SwTxtNode*)pNd)->GetTxt();
+ }
+ }
+ return aRetStr;
+}
+
+double SwSortBoxElement::GetValue( sal_uInt16 nKey ) const
+{
+ const _FndBox* pFndBox;
+ sal_uInt16 nCol = pOptions->aKeys[nKey]->nColumnId-1;
+
+ if( SRT_ROWS == pOptions->eDirection )
+ pFndBox = pBox->GetBox(nCol, nRow); // Zeilen sortieren
+ else
+ pFndBox = pBox->GetBox(nRow, nCol); // Spalten sortieren
+
+ double nVal;
+ if( pFndBox )
+ {
+ const SwFmt *pFmt = pFndBox->GetBox()->GetFrmFmt();
+ if (pFmt->GetTblBoxNumFmt().GetValue() & NUMBERFORMAT_TEXT)
+ nVal = SwSortElement::GetValue( nKey );
+ else
+ nVal = pFmt->GetTblBoxValue().GetValue();
+ }
+ else
+ nVal = 0;
+
+ return nVal;
+}
+
+/*--------------------------------------------------------------------
+ Beschreibung: Text sortieren im Document
+ --------------------------------------------------------------------*/
+sal_Bool SwDoc::SortText(const SwPaM& rPaM, const SwSortOptions& rOpt)
+{
+ // pruefen ob Rahmen im Text
+ const SwPosition *pStart = rPaM.Start(), *pEnd = rPaM.End();
+ // Index auf den Start der Selektion
+
+ for ( sal_uInt16 n = 0; n < GetSpzFrmFmts()->Count(); ++n )
+ {
+ SwFrmFmt *const pFmt = static_cast<SwFrmFmt*>((*GetSpzFrmFmts())[n]);
+ SwFmtAnchor const*const pAnchor = &pFmt->GetAnchor();
+ SwPosition const*const pAPos = pAnchor->GetCntntAnchor();
+
+ if (pAPos && (FLY_AT_PARA == pAnchor->GetAnchorId()) &&
+ pStart->nNode <= pAPos->nNode && pAPos->nNode <= pEnd->nNode )
+ return sal_False;
+ }
+
+ // pruefe ob nur TextNodes in der Selection liegen
+ {
+ sal_uLong nStart = pStart->nNode.GetIndex(),
+ nEnd = pEnd->nNode.GetIndex();
+ while( nStart <= nEnd )
+ // Iterieren ueber einen selektierten Bereich
+ if( !GetNodes()[ nStart++ ]->IsTxtNode() )
+ return sal_False;
+ }
+
+ bool const bUndo = GetIDocumentUndoRedo().DoesUndo();
+ if( bUndo )
+ {
+ GetIDocumentUndoRedo().StartUndo( UNDO_START, NULL );
+ }
+
+ SwPaM* pRedlPam = 0;
+ SwUndoRedlineSort* pRedlUndo = 0;
+ SwUndoSort* pUndoSort = 0;
+
+ if( IsRedlineOn() || (!IsIgnoreRedline() && pRedlineTbl->Count() ))
+ {
+ pRedlPam = new SwPaM( pStart->nNode, pEnd->nNode, -1, 1 );
+ SwCntntNode* pCNd = pRedlPam->GetCntntNode( sal_False );
+ if( pCNd )
+ pRedlPam->GetMark()->nContent = pCNd->Len();
+
+ if( IsRedlineOn() && !IsShowOriginal( GetRedlineMode() ) )
+ {
+ if( bUndo )
+ {
+ pRedlUndo = new SwUndoRedlineSort( *pRedlPam,rOpt );
+ GetIDocumentUndoRedo().DoUndo(false);
+ }
+ // erst den Bereich kopieren, dann
+ SwNodeIndex aEndIdx( pEnd->nNode, 1 );
+ SwNodeRange aRg( pStart->nNode, aEndIdx );
+ GetNodes()._Copy( aRg, aEndIdx );
+
+ // Bereich neu ist von pEnd->nNode+1 bis aEndIdx
+ DeleteRedline( *pRedlPam, true, USHRT_MAX );
+
+ pRedlPam->GetMark()->nNode.Assign( pEnd->nNode.GetNode(), 1 );
+ pCNd = pRedlPam->GetCntntNode( sal_False );
+ pRedlPam->GetMark()->nContent.Assign( pCNd, 0 );
+
+ pRedlPam->GetPoint()->nNode.Assign( aEndIdx.GetNode() );
+ pCNd = pRedlPam->GetCntntNode( sal_True );
+ xub_StrLen nCLen = 0;
+ if( !pCNd &&
+ 0 != (pCNd = GetNodes()[ aEndIdx.GetIndex()-1 ]->GetCntntNode()))
+ {
+ nCLen = pCNd->Len();
+ pRedlPam->GetPoint()->nNode.Assign( *pCNd );
+ }
+ pRedlPam->GetPoint()->nContent.Assign( pCNd, nCLen );
+
+ if( pRedlUndo )
+ pRedlUndo->SetValues( rPaM );
+ }
+ else
+ {
+ DeleteRedline( *pRedlPam, true, USHRT_MAX );
+ delete pRedlPam, pRedlPam = 0;
+ }
+ }
+
+ SwNodeIndex aStart(pStart->nNode);
+ SwSortElement::Init( this, rOpt );
+ SwSortElements aSortArr;
+ while( aStart <= pEnd->nNode )
+ {
+ // Iterieren ueber einen selektierten Bereich
+ SwSortTxtElement* pSE = new SwSortTxtElement( aStart );
+ aSortArr.Insert(pSE);
+ aStart++;
+ }
+
+ // Und jetzt der Akt: Verschieben von Nodes und immer schoen auf UNDO
+ // achten
+ //
+ sal_uLong nBeg = pStart->nNode.GetIndex();
+ SwNodeRange aRg( aStart, aStart );
+
+ if( bUndo && !pRedlUndo )
+ {
+ pUndoSort = new SwUndoSort(rPaM, rOpt);
+ GetIDocumentUndoRedo().AppendUndo(pUndoSort);
+ }
+
+ GetIDocumentUndoRedo().DoUndo(false);
+
+ for ( sal_uInt16 n = 0; n < aSortArr.Count(); ++n )
+ {
+ SwSortTxtElement* pBox = (SwSortTxtElement*)aSortArr[n];
+ aStart = nBeg + n;
+ aRg.aStart = pBox->aPos.GetIndex();
+ aRg.aEnd = aRg.aStart.GetIndex() + 1;
+
+ // Nodes verschieben
+ MoveNodeRange( aRg, aStart,
+ IDocumentContentOperations::DOC_MOVEDEFAULT );
+
+ // Undo Verschiebungen einpflegen
+ if(pUndoSort)
+ pUndoSort->Insert(pBox->nOrg, nBeg + n);
+ }
+ // Alle Elemente aus dem SortArray loeschen
+ aSortArr.DeleteAndDestroy(0, aSortArr.Count());
+ SwSortElement::Finit();
+
+ if( pRedlPam )
+ {
+ if( pRedlUndo )
+ {
+ pRedlUndo->SetSaveRange( *pRedlPam );
+ // UGLY: temp. enable Undo
+ GetIDocumentUndoRedo().DoUndo(true);
+ GetIDocumentUndoRedo().AppendUndo( pRedlUndo );
+ GetIDocumentUndoRedo().DoUndo(false);
+ }
+
+ // nBeg is start of sorted range
+ SwNodeIndex aSttIdx( GetNodes(), nBeg );
+
+ // the copied range is deleted
+ SwRedline *const pDeleteRedline(
+ new SwRedline( nsRedlineType_t::REDLINE_DELETE, *pRedlPam ));
+
+ // pRedlPam points to nodes that may be deleted (hidden) by
+ // AppendRedline, so adjust it beforehand to prevent ASSERT
+ pRedlPam->GetPoint()->nNode = aSttIdx;
+ SwCntntNode* pCNd = aSttIdx.GetNode().GetCntntNode();
+ pRedlPam->GetPoint()->nContent.Assign( pCNd, 0 );
+
+ AppendRedline(pDeleteRedline, true);
+
+ // the sorted range is inserted
+ AppendRedline( new SwRedline( nsRedlineType_t::REDLINE_INSERT, *pRedlPam ), true);
+
+ if( pRedlUndo )
+ {
+ SwNodeIndex aInsEndIdx( pRedlPam->GetMark()->nNode, -1 );
+ pRedlPam->GetMark()->nNode = aInsEndIdx;
+ SwCntntNode *const pPrevNode =
+ pRedlPam->GetMark()->nNode.GetNode().GetCntntNode();
+ pRedlPam->GetMark()->nContent.Assign( pPrevNode, pPrevNode->Len() );
+
+ pRedlUndo->SetValues( *pRedlPam );
+ }
+
+ if( pRedlUndo )
+ pRedlUndo->SetOffset( aSttIdx );
+
+ delete pRedlPam, pRedlPam = 0;
+ }
+ GetIDocumentUndoRedo().DoUndo( bUndo );
+ if( bUndo )
+ {
+ GetIDocumentUndoRedo().EndUndo( UNDO_END, NULL );
+ }
+
+ return sal_True;
+}
+
+/*--------------------------------------------------------------------
+ Beschreibung: Tabelle sortieren im Document
+ --------------------------------------------------------------------*/
+sal_Bool SwDoc::SortTbl(const SwSelBoxes& rBoxes, const SwSortOptions& rOpt)
+{
+ // uebers SwDoc fuer Undo !!
+ OSL_ENSURE( rBoxes.Count(), "keine gueltige Box-Liste" );
+ SwTableNode* pTblNd = (SwTableNode*)rBoxes[0]->GetSttNd()->FindTableNode();
+ if( !pTblNd )
+ return sal_False;
+
+ // Auf gehts sortieren
+ // suche alle Boxen / Lines
+ _FndBox aFndBox( 0, 0 );
+ {
+ _FndPara aPara( rBoxes, &aFndBox );
+ pTblNd->GetTable().GetTabLines().ForEach( &_FndLineCopyCol, &aPara );;
+ }
+
+ if(!aFndBox.GetLines().Count())
+ return sal_False;
+
+ if( !IsIgnoreRedline() && GetRedlineTbl().Count() )
+ DeleteRedline( *pTblNd, true, USHRT_MAX );
+
+ sal_uInt16 nStart = 0;
+ if( pTblNd->GetTable().GetRowsToRepeat() > 0 && rOpt.eDirection == SRT_ROWS )
+ {
+ // Oberste seleketierte Zeile
+ _FndLines& rLines = aFndBox.GetLines();
+
+ while( nStart < rLines.Count() )
+ {
+ // Verschachtelung durch Split Merge beachten,
+ // die oberste rausholen
+ SwTableLine* pLine = rLines[nStart]->GetLine();
+ while ( pLine->GetUpper() )
+ pLine = pLine->GetUpper()->GetUpper();
+
+ if( pTblNd->GetTable().IsHeadline( *pLine ) )
+ nStart++;
+ else
+ break;
+ }
+ // Alle selektierten in der HeaderLine ? -> kein Offset
+ if( nStart == rLines.Count() )
+ nStart = 0;
+ }
+
+ // umschalten auf relative Formeln
+ SwTableFmlUpdate aMsgHnt( &pTblNd->GetTable() );
+ aMsgHnt.eFlags = TBL_RELBOXNAME;
+ UpdateTblFlds( &aMsgHnt );
+
+ // Tabelle als flache Array-Struktur
+ FlatFndBox aFlatBox(this, aFndBox);
+
+ if(!aFlatBox.IsSymmetric())
+ return sal_False;
+
+ // MIB 9.7.97: HTML-Layout loeschen
+ pTblNd->GetTable().SetHTMLTableLayout( 0 );
+
+ // --> FME 2004-11-26 #i37739# A simple 'MakeFrms' after the node sorting
+ // does not work if the table is inside a frame and has no prev/next.
+ SwNode2Layout aNode2Layout( *pTblNd );
+ // <--
+
+ // loesche die Frames der Tabelle
+ pTblNd->DelFrms();
+ // ? TL_CHART2: ?
+
+ SwUndoSort* pUndoSort = 0;
+ if (GetIDocumentUndoRedo().DoesUndo())
+ {
+ pUndoSort = new SwUndoSort( rBoxes[0]->GetSttIdx(),
+ rBoxes[rBoxes.Count()-1]->GetSttIdx(),
+ *pTblNd, rOpt, aFlatBox.HasItemSets() );
+ GetIDocumentUndoRedo().AppendUndo(pUndoSort);
+ }
+ ::sw::UndoGuard const undoGuard(GetIDocumentUndoRedo());
+
+ // SchluesselElemente einsortieren
+ sal_uInt16 nCount = (rOpt.eDirection == SRT_ROWS) ?
+ aFlatBox.GetRows() : aFlatBox.GetCols();
+
+ // SortList nach Schluessel sortieren
+ SwSortElement::Init( this, rOpt, &aFlatBox );
+ SwSortElements aSortList;
+
+ // wenn die HeaderLine wiederholt wird und die
+ // Zeilen sortiert werden 1.Zeile nicht mitsortieren
+ sal_uInt16 i;
+
+ for( i = nStart; i < nCount; ++i)
+ {
+ SwSortBoxElement* pEle = new SwSortBoxElement( i );
+ aSortList.Insert(pEle);
+ }
+
+ // nach Sortierung verschieben
+ SwMovedBoxes aMovedList;
+ for(i=0; i < aSortList.Count(); ++i)
+ {
+ SwSortBoxElement* pBox = (SwSortBoxElement*)aSortList[i];
+ if(rOpt.eDirection == SRT_ROWS)
+ MoveRow(this, aFlatBox, pBox->nRow, i + nStart, aMovedList, pUndoSort);
+ else
+ MoveCol(this, aFlatBox, pBox->nRow, i + nStart, aMovedList, pUndoSort);
+ }
+
+ // Restore table frames:
+ // --> FME 2004-11-26 #i37739# A simple 'MakeFrms' after the node sorting
+ // does not work if the table is inside a frame and has no prev/next.
+ const sal_uLong nIdx = pTblNd->GetIndex();
+ aNode2Layout.RestoreUpperFrms( GetNodes(), nIdx, nIdx + 1 );
+ // <--
+
+ // TL_CHART2: need to inform chart of probably changed cell names
+ UpdateCharts( pTblNd->GetTable().GetFrmFmt()->GetName() );
+
+ // Alle Elemente aus dem SortArray loeschen
+ aSortList.DeleteAndDestroy( 0, aSortList.Count() );
+ SwSortElement::Finit();
+
+ SetModified();
+ return sal_True;
+}
+
+/*--------------------------------------------------------------------
+ Beschreibung: Zeilenweise verschieben
+ --------------------------------------------------------------------*/
+void MoveRow(SwDoc* pDoc, const FlatFndBox& rBox, sal_uInt16 nS, sal_uInt16 nT,
+ SwMovedBoxes& rMovedList, SwUndoSort* pUD)
+{
+ for( sal_uInt16 i=0; i < rBox.GetCols(); ++i )
+ { // Alte Zellen-Pos bestimmen und merken
+ const _FndBox* pSource = rBox.GetBox(i, nS);
+
+ // neue Zellen-Pos
+ const _FndBox* pTarget = rBox.GetBox(i, nT);
+
+ const SwTableBox* pT = pTarget->GetBox();
+ const SwTableBox* pS = pSource->GetBox();
+
+ sal_Bool bMoved = rMovedList.GetPos(pT) != USHRT_MAX;
+
+ // und verschieben
+ MoveCell(pDoc, pS, pT, bMoved, pUD);
+
+ rMovedList.Insert(pS, rMovedList.Count() );
+
+ if( pS != pT )
+ {
+ SwFrmFmt* pTFmt = (SwFrmFmt*)pT->GetFrmFmt();
+ const SfxItemSet* pSSet = rBox.GetItemSet( i, nS );
+
+ if( pSSet ||
+ SFX_ITEM_SET == pTFmt->GetItemState( RES_BOXATR_FORMAT ) ||
+ SFX_ITEM_SET == pTFmt->GetItemState( RES_BOXATR_FORMULA ) ||
+ SFX_ITEM_SET == pTFmt->GetItemState( RES_BOXATR_VALUE ) )
+ {
+ pTFmt = ((SwTableBox*)pT)->ClaimFrmFmt();
+ pTFmt->LockModify();
+ if( pTFmt->ResetFmtAttr( RES_BOXATR_FORMAT, RES_BOXATR_VALUE ) )
+ pTFmt->ResetFmtAttr( RES_VERT_ORIENT );
+
+ if( pSSet )
+ pTFmt->SetFmtAttr( *pSSet );
+ pTFmt->UnlockModify();
+ }
+ }
+ }
+}
+
+/*--------------------------------------------------------------------
+ Beschreibung: Spaltenweise verschieben
+ --------------------------------------------------------------------*/
+void MoveCol(SwDoc* pDoc, const FlatFndBox& rBox, sal_uInt16 nS, sal_uInt16 nT,
+ SwMovedBoxes& rMovedList, SwUndoSort* pUD)
+{
+ for(sal_uInt16 i=0; i < rBox.GetRows(); ++i)
+ { // Alte Zellen-Pos bestimmen und merken
+ const _FndBox* pSource = rBox.GetBox(nS, i);
+
+ // neue Zellen-Pos
+ const _FndBox* pTarget = rBox.GetBox(nT, i);
+
+ // und verschieben
+ const SwTableBox* pT = pTarget->GetBox();
+ const SwTableBox* pS = pSource->GetBox();
+
+ // und verschieben
+ sal_Bool bMoved = rMovedList.GetPos(pT) != USHRT_MAX;
+ MoveCell(pDoc, pS, pT, bMoved, pUD);
+
+ rMovedList.Insert(pS, rMovedList.Count() );
+
+ if( pS != pT )
+ {
+ SwFrmFmt* pTFmt = (SwFrmFmt*)pT->GetFrmFmt();
+ const SfxItemSet* pSSet = rBox.GetItemSet( nS, i );
+
+ if( pSSet ||
+ SFX_ITEM_SET == pTFmt->GetItemState( RES_BOXATR_FORMAT ) ||
+ SFX_ITEM_SET == pTFmt->GetItemState( RES_BOXATR_FORMULA ) ||
+ SFX_ITEM_SET == pTFmt->GetItemState( RES_BOXATR_VALUE ) )
+ {
+ pTFmt = ((SwTableBox*)pT)->ClaimFrmFmt();
+ pTFmt->LockModify();
+ if( pTFmt->ResetFmtAttr( RES_BOXATR_FORMAT, RES_BOXATR_VALUE ) )
+ pTFmt->ResetFmtAttr( RES_VERT_ORIENT );
+
+ if( pSSet )
+ pTFmt->SetFmtAttr( *pSSet );
+ pTFmt->UnlockModify();
+ }
+ }
+ }
+}
+
+/*--------------------------------------------------------------------
+ Beschreibung: Eine einzelne Zelle verschieben
+ --------------------------------------------------------------------*/
+void MoveCell(SwDoc* pDoc, const SwTableBox* pSource, const SwTableBox* pTar,
+ sal_Bool bMovedBefore, SwUndoSort* pUD)
+{
+ OSL_ENSURE(pSource && pTar,"Fehlende Quelle oder Ziel");
+
+ if(pSource == pTar)
+ return;
+
+ if(pUD)
+ pUD->Insert( pSource->GetName(), pTar->GetName() );
+
+ // Pam Quelle auf den ersten ContentNode setzen
+ SwNodeRange aRg( *pSource->GetSttNd(), 0, *pSource->GetSttNd() );
+ SwNode* pNd = pDoc->GetNodes().GoNext( &aRg.aStart );
+
+ // wurde die Zelle (Source) nicht verschoben
+ // -> einen Leer-Node einfuegen und den Rest verschieben
+ // ansonsten steht der Mark auf dem ersten Content-Node
+ if( pNd->StartOfSectionNode() == pSource->GetSttNd() )
+ pNd = pDoc->GetNodes().MakeTxtNode( aRg.aStart,
+ (SwTxtFmtColl*)pDoc->GetDfltTxtFmtColl() );
+ aRg.aEnd = *pNd->EndOfSectionNode();
+
+ // Ist das Ziel leer(1 leerer Node vorhanden)
+ // -> diesen loeschen und move
+ // Ziel
+ SwNodeIndex aTar( *pTar->GetSttNd() );
+ pNd = pDoc->GetNodes().GoNext( &aTar ); // naechsten ContentNode
+ sal_uLong nCount = pNd->EndOfSectionIndex() - pNd->StartOfSectionIndex();
+
+ sal_Bool bDelFirst = sal_False;
+ if( nCount == 2 )
+ {
+ OSL_ENSURE( pNd->GetCntntNode(), "Kein ContentNode");
+ bDelFirst = !pNd->GetCntntNode()->Len() && bMovedBefore;
+ }
+
+ if(!bDelFirst)
+ { // Es besteht schon Inhalt -> alter I n h a l t Section Down
+ SwNodeRange aRgTar( aTar.GetNode(), 0, *pNd->EndOfSectionNode() );
+ pDoc->GetNodes().SectionDown( &aRgTar );
+ }
+
+ // Einfuegen der Source
+ SwNodeIndex aIns( *pTar->GetSttNd()->EndOfSectionNode() );
+ pDoc->MoveNodeRange( aRg, aIns,
+ IDocumentContentOperations::DOC_MOVEDEFAULT );
+
+ // Falls erster Node leer -> weg damit
+ if(bDelFirst)
+ pDoc->GetNodes().Delete( aTar, 1 );
+}
+
+/*--------------------------------------------------------------------
+ Beschreibung: Zweidimensionales Array aus FndBoxes generieren
+ --------------------------------------------------------------------*/
+FlatFndBox::FlatFndBox(SwDoc* pDocPtr, const _FndBox& rBox) :
+ pDoc(pDocPtr),
+ rBoxRef(rBox),
+ pArr(0),
+ ppItemSets(0),
+ nRow(0),
+ nCol(0)
+{ // Ist das Array symmetrisch
+ if((bSym = CheckLineSymmetry(rBoxRef)) != 0)
+ {
+ // Spalten/Reihen-Anzahl ermitteln
+ nCols = GetColCount(rBoxRef);
+ nRows = GetRowCount(rBoxRef);
+
+ // lineares Array anlegen
+ pArr = new _FndBoxPtr[ nRows * nCols ];
+ _FndBox** ppTmp = (_FndBox**)pArr;
+ memset( ppTmp, 0, sizeof(_FndBoxPtr) * nRows * nCols );
+
+
+ FillFlat( rBoxRef );
+ }
+}
+
+FlatFndBox::~FlatFndBox()
+{
+ _FndBox** ppTmp = (_FndBox**)pArr;
+ delete [] ppTmp;
+
+ if( ppItemSets )
+ delete [] ppItemSets;
+}
+
+/*--------------------------------------------------------------------
+ Beschreibung: Alle Lines einer Box muessen gleichviel Boxen haben
+ --------------------------------------------------------------------*/
+sal_Bool FlatFndBox::CheckLineSymmetry(const _FndBox& rBox)
+{
+ const _FndLines &rLines = rBox.GetLines();
+ sal_uInt16 nBoxes(0);
+
+ // UeberLines iterieren
+ for(sal_uInt16 i=0; i < rLines.Count(); ++i)
+ { // Die Boxen einer Line
+ _FndLine* pLn = rLines[i];
+ const _FndBoxes& rBoxes = pLn->GetBoxes();
+
+ // Anzahl der Boxen aller Lines ungleich -> keine Symmetrie
+ if( i && nBoxes != rBoxes.Count())
+ return sal_False;
+
+ nBoxes = rBoxes.Count();
+ if( !CheckBoxSymmetry( *pLn ) )
+ return sal_False;
+ }
+ return sal_True;
+}
+
+/*--------------------------------------------------------------------
+ Beschreibung: Box auf Symmetrie pruefen
+ Alle Boxen einer Line muessen gleichviele Lines haben
+ --------------------------------------------------------------------*/
+sal_Bool FlatFndBox::CheckBoxSymmetry(const _FndLine& rLn)
+{
+ const _FndBoxes &rBoxes = rLn.GetBoxes();
+ sal_uInt16 nLines(0);
+
+ // Ueber Boxes iterieren
+ for(sal_uInt16 i=0; i < rBoxes.Count(); ++i)
+ { // Die Boxen einer Line
+ _FndBox* pBox = rBoxes[i];
+ const _FndLines& rLines = pBox->GetLines();
+
+ // Anzahl der Boxen aller Lines ungleich -> keine Symmetrie
+ if( i && nLines != rLines.Count() )
+ return sal_False;
+
+ nLines = rLines.Count();
+ if( nLines && !CheckLineSymmetry( *pBox ) )
+ return sal_False;
+ }
+ return sal_True;
+}
+
+/*--------------------------------------------------------------------
+ Beschreibung: max Anzahl der Spalten (Boxes)
+ --------------------------------------------------------------------*/
+sal_uInt16 FlatFndBox::GetColCount(const _FndBox& rBox)
+{
+ const _FndLines& rLines = rBox.GetLines();
+ // Ueber Lines iterieren
+ if( !rLines.Count() )
+ return 1;
+
+ sal_uInt16 nSum = 0;
+ for( sal_uInt16 i=0; i < rLines.Count(); ++i )
+ {
+ // Die Boxen einer Line
+ sal_uInt16 nCount = 0;
+ const _FndBoxes& rBoxes = rLines[i]->GetBoxes();
+ for( sal_uInt16 j=0; j < rBoxes.Count(); ++j )
+ // Rekursiv wirder ueber die Lines Iterieren
+ nCount += rBoxes[j]->GetLines().Count()
+ ? GetColCount(*rBoxes[j]) : 1;
+
+ if( nSum < nCount )
+ nSum = nCount;
+ }
+ return nSum;
+}
+
+/*--------------------------------------------------------------------
+ Beschreibung: max Anzahl der Zeilen (Lines)
+ --------------------------------------------------------------------*/
+sal_uInt16 FlatFndBox::GetRowCount(const _FndBox& rBox)
+{
+ const _FndLines& rLines = rBox.GetLines();
+ if( !rLines.Count() )
+ return 1;
+
+ sal_uInt16 nLines = 0;
+ for(sal_uInt16 i=0; i < rLines.Count(); ++i)
+ { // Die Boxen einer Line
+ const _FndBoxes& rBoxes = rLines[i]->GetBoxes();
+ sal_uInt16 nLn = 1;
+ for(sal_uInt16 j=0; j < rBoxes.Count(); ++j)
+ if( rBoxes[j]->GetLines().Count() )
+ // Rekursiv ueber die Lines Iterieren
+ nLn = Max(GetRowCount(*rBoxes[j]), nLn);
+
+ nLines = nLines + nLn;
+ }
+ return nLines;
+}
+
+/*--------------------------------------------------------------------
+ Beschreibung: lineares Array aus atomaren FndBoxes erzeugen
+ --------------------------------------------------------------------*/
+void FlatFndBox::FillFlat(const _FndBox& rBox, sal_Bool bLastBox)
+{
+ sal_Bool bModRow = sal_False;
+ const _FndLines& rLines = rBox.GetLines();
+
+ // Ueber Lines iterieren
+ sal_uInt16 nOldRow = nRow;
+ for( sal_uInt16 i=0; i < rLines.Count(); ++i )
+ {
+ // Die Boxen einer Line
+ const _FndBoxes& rBoxes = rLines[i]->GetBoxes();
+ sal_uInt16 nOldCol = nCol;
+ for( sal_uInt16 j = 0; j < rBoxes.Count(); ++j )
+ {
+ // Die Box pruefen ob es eine atomare Box ist
+ const _FndBox* pBox = rBoxes[ j ];
+
+ if( !pBox->GetLines().Count() )
+ {
+ // peichern
+ sal_uInt16 nOff = nRow * nCols + nCol;
+ *(pArr + nOff) = pBox;
+
+ // sicher die Formel/Format/Value Werte
+ const SwFrmFmt* pFmt = pBox->GetBox()->GetFrmFmt();
+ if( SFX_ITEM_SET == pFmt->GetItemState( RES_BOXATR_FORMAT ) ||
+ SFX_ITEM_SET == pFmt->GetItemState( RES_BOXATR_FORMULA ) ||
+ SFX_ITEM_SET == pFmt->GetItemState( RES_BOXATR_VALUE ) )
+ {
+ SfxItemSet* pSet = new SfxItemSet( pDoc->GetAttrPool(),
+ RES_BOXATR_FORMAT, RES_BOXATR_VALUE,
+ RES_VERT_ORIENT, RES_VERT_ORIENT, 0 );
+ pSet->Put( pFmt->GetAttrSet() );
+ if( !ppItemSets )
+ {
+ ppItemSets = new SfxItemSet*[ nRows * nCols ];
+ memset( ppItemSets, 0, sizeof(SfxItemSet*) * nRows * nCols );
+ }
+ *(ppItemSets + nOff ) = pSet;
+ }
+
+ bModRow = sal_True;
+ }
+ else
+ {
+ // Rekursiv wieder ueber die Lines einer Box Iterieren
+ FillFlat( *pBox, ( j == rBoxes.Count()-1 ) );
+ }
+ nCol++;
+ }
+ if(bModRow)
+ nRow++;
+ nCol = nOldCol;
+ }
+ if(!bLastBox)
+ nRow = nOldRow;
+}
+
+/*--------------------------------------------------------------------
+ Beschreibung: Zugriff auf eine bestimmte Zelle
+ --------------------------------------------------------------------*/
+const _FndBox* FlatFndBox::GetBox(sal_uInt16 n_Col, sal_uInt16 n_Row) const
+{
+ sal_uInt16 nOff = n_Row * nCols + n_Col;
+ const _FndBox* pTmp = *(pArr + nOff);
+
+ OSL_ENSURE(n_Col < nCols && n_Row < nRows && pTmp, "unzulaessiger Array-Zugriff");
+ return pTmp;
+}
+
+const SfxItemSet* FlatFndBox::GetItemSet(sal_uInt16 n_Col, sal_uInt16 n_Row) const
+{
+ OSL_ENSURE( !ppItemSets || ( n_Col < nCols && n_Row < nRows), "unzulaessiger Array-Zugriff");
+
+ return ppItemSets ? *(ppItemSets + (n_Row * nCols + n_Col )) : 0;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/doc/docstat.cxx b/sw/source/core/doc/docstat.cxx
new file mode 100644
index 000000000000..0b79d817a436
--- /dev/null
+++ b/sw/source/core/doc/docstat.cxx
@@ -0,0 +1,71 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+
+#include <docstat.hxx>
+
+
+/************************************************************************
+ * SwDocStat::SwDocStat()
+ ************************************************************************/
+
+SwDocStat::SwDocStat() :
+ nTbl(0),
+ nGrf(0),
+ nOLE(0),
+ nPage(1),
+ nPara(1),
+ nAllPara(1),
+ nWord(0),
+ nChar(0),
+ nCharExcludingSpaces(0),
+ bModified(sal_True)
+{}
+
+/************************************************************************
+ * void SwDocStat::Reset()
+ ************************************************************************/
+
+void SwDocStat::Reset()
+{
+ nTbl = 0;
+ nGrf = 0;
+ nOLE = 0;
+ nPage = 1;
+ nPara = 1;
+ nAllPara= 1;
+ nWord = 0;
+ nChar = 0;
+ nCharExcludingSpaces = 0;
+ bModified = sal_True;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/doc/doctxm.cxx b/sw/source/core/doc/doctxm.cxx
new file mode 100644
index 000000000000..870265cb288d
--- /dev/null
+++ b/sw/source/core/doc/doctxm.cxx
@@ -0,0 +1,2386 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+
+#include <limits.h>
+#include <hintids.hxx>
+
+#define _SVSTDARR_STRINGSSORT
+#include <svl/svstdarr.hxx>
+#include <editeng/langitem.hxx>
+#include <editeng/brkitem.hxx>
+#include <editeng/tstpitem.hxx>
+#include <editeng/lrspitem.hxx>
+#include <sot/clsids.hxx>
+#include <docsh.hxx>
+#include <ndole.hxx>
+#include <txttxmrk.hxx>
+#include <fmtinfmt.hxx>
+#include <fmtpdsc.hxx>
+#include <frmfmt.hxx>
+#include <fmtfsize.hxx>
+#include <frmatr.hxx>
+#include <pagedesc.hxx>
+#include <doc.hxx>
+#include <IDocumentUndoRedo.hxx>
+#include <pagefrm.hxx>
+#include <ndtxt.hxx>
+#include <swtable.hxx>
+#include <doctxm.hxx>
+#include <txmsrt.hxx>
+#include <rolbck.hxx>
+#include <poolfmt.hxx>
+#include <txtfrm.hxx>
+#include <rootfrm.hxx>
+#include <UndoAttribute.hxx>
+#include <swundo.hxx>
+#include <mdiexp.hxx>
+#include <docary.hxx>
+#include <charfmt.hxx>
+#include <fchrfmt.hxx>
+#include <fldbas.hxx>
+#include <fmtfld.hxx>
+#include <txtfld.hxx>
+#include <expfld.hxx>
+#include <chpfld.hxx>
+#include <mvsave.hxx>
+#include <node2lay.hxx>
+#include <SwStyleNameMapper.hxx>
+#include <breakit.hxx>
+#include <editsh.hxx>
+#include <scriptinfo.hxx>
+#include <switerator.hxx>
+
+using namespace ::com::sun::star;
+
+const sal_Unicode cNumRepl = '@';
+const sal_Unicode cEndPageNum = '~';
+const sal_Char sPageDeli[] = ", ";
+
+SV_IMPL_PTRARR(SwTOXSortTabBases, SwTOXSortTabBasePtr)
+
+TYPEINIT2( SwTOXBaseSection, SwTOXBase, SwSection ); // fuers RTTI
+
+struct LinkStruct
+{
+ SwFmtINetFmt aINetFmt;
+ xub_StrLen nStartTextPos, nEndTextPos;
+
+ LinkStruct( const String& rURL, xub_StrLen nStart, xub_StrLen nEnd )
+ : aINetFmt( rURL, aEmptyStr),
+ nStartTextPos( nStart),
+ nEndTextPos(nEnd) {}
+};
+
+typedef LinkStruct* LinkStructPtr;
+SV_DECL_PTRARR(LinkStructArr, LinkStructPtr, 0, 5 )
+SV_IMPL_PTRARR(LinkStructArr, LinkStructPtr)
+
+sal_uInt16 SwDoc::GetTOIKeys( SwTOIKeyType eTyp, SvStringsSort& rArr ) const
+{
+ if( rArr.Count() )
+ rArr.Remove( sal_uInt16(0), rArr.Count() );
+
+ // dann mal ueber den Pool und alle Primary oder Secondary heraussuchen
+ const SwTxtTOXMark* pMark;
+ const SfxPoolItem* pItem;
+ const SwTOXType* pTOXType;
+ sal_uInt32 i, nMaxItems = GetAttrPool().GetItemCount2( RES_TXTATR_TOXMARK );
+ for( i = 0; i < nMaxItems; ++i )
+ if( 0 != (pItem = GetAttrPool().GetItem2( RES_TXTATR_TOXMARK, i ) ) &&
+ 0!= ( pTOXType = ((SwTOXMark*)pItem)->GetTOXType()) &&
+ TOX_INDEX == pTOXType->GetType() &&
+ 0 != ( pMark = ((SwTOXMark*)pItem)->GetTxtTOXMark() ) &&
+ pMark->GetpTxtNd() &&
+ pMark->GetpTxtNd()->GetNodes().IsDocNodes() )
+ {
+ const String* pStr;
+ if( TOI_PRIMARY == eTyp )
+ pStr = &((SwTOXMark*)pItem)->GetPrimaryKey();
+ else
+ pStr = &((SwTOXMark*)pItem)->GetSecondaryKey();
+
+ if( pStr->Len() )
+ rArr.Insert( (StringPtr)pStr );
+ }
+
+ return rArr.Count();
+}
+
+/*--------------------------------------------------------------------
+ Beschreibung: aktuelle Verzeichnismarkierungen ermitteln
+ --------------------------------------------------------------------*/
+sal_uInt16 SwDoc::GetCurTOXMark( const SwPosition& rPos,
+ SwTOXMarks& rArr ) const
+{
+ // search on Position rPos for all SwTOXMarks
+ SwTxtNode *const pTxtNd = rPos.nNode.GetNode().GetTxtNode();
+ if( !pTxtNd || !pTxtNd->GetpSwpHints() )
+ return 0;
+
+ const SwpHints & rHts = *pTxtNd->GetpSwpHints();
+ const SwTxtAttr* pHt;
+ xub_StrLen nSttIdx;
+ const xub_StrLen *pEndIdx;
+
+ xub_StrLen nAktPos = rPos.nContent.GetIndex();
+
+ for( sal_uInt16 n = 0; n < rHts.Count(); ++n )
+ {
+ if( RES_TXTATR_TOXMARK != (pHt = rHts[n])->Which() )
+ continue;
+ if( ( nSttIdx = *pHt->GetStart() ) < nAktPos )
+ {
+ // pruefe Ende mit ab
+ if( 0 == ( pEndIdx = pHt->GetEnd() ) ||
+ *pEndIdx <= nAktPos )
+ continue; // weiter suchen
+ }
+ else if( nSttIdx > nAktPos )
+ // ist Start vom Hint groesser als rPos, dann abbrechen. Denn
+ // die Attribute sind nach Start sortiert !
+ break;
+
+ const SwTOXMark* pTMark = &pHt->GetTOXMark();
+ rArr.Insert( pTMark, rArr.Count() );
+ }
+ return rArr.Count();
+}
+
+/*--------------------------------------------------------------------
+ Beschreibung: Marke loeschen
+ --------------------------------------------------------------------*/
+void SwDoc::DeleteTOXMark( const SwTOXMark* pTOXMark )
+{
+ // hole den TextNode und
+ const SwTxtTOXMark* pTxtTOXMark = pTOXMark->GetTxtTOXMark();
+ OSL_ENSURE( pTxtTOXMark, "Kein TxtTOXMark, kann nicht geloescht werden" );
+
+ SwTxtNode& rTxtNd = const_cast<SwTxtNode&>(pTxtTOXMark->GetTxtNode());
+ OSL_ENSURE( rTxtNd.GetpSwpHints(), "kann nicht geloescht werden" );
+
+ if (GetIDocumentUndoRedo().DoesUndo())
+ {
+ // save attributes for Undo
+ SwUndoResetAttr* pUndo = new SwUndoResetAttr(
+ SwPosition( rTxtNd, SwIndex( &rTxtNd, *pTxtTOXMark->GetStart() ) ),
+ RES_TXTATR_TOXMARK );
+ GetIDocumentUndoRedo().AppendUndo( pUndo );
+
+ SwRegHistory aRHst( rTxtNd, &pUndo->GetHistory() );
+ rTxtNd.GetpSwpHints()->Register( &aRHst );
+ }
+
+ rTxtNd.DeleteAttribute( const_cast<SwTxtTOXMark*>(pTxtTOXMark) );
+
+ if (GetIDocumentUndoRedo().DoesUndo())
+ {
+ if( rTxtNd.GetpSwpHints() )
+ rTxtNd.GetpSwpHints()->DeRegister();
+ }
+ SetModified();
+}
+
+/*--------------------------------------------------------------------
+ Beschreibung: Traveln zwischen TOXMarks
+ --------------------------------------------------------------------*/
+class CompareNodeCntnt
+{
+ sal_uLong nNode;
+ xub_StrLen nCntnt;
+public:
+ CompareNodeCntnt( sal_uLong nNd, xub_StrLen nCnt )
+ : nNode( nNd ), nCntnt( nCnt ) {}
+
+ int operator==( const CompareNodeCntnt& rCmp ) const
+ { return nNode == rCmp.nNode && nCntnt == rCmp.nCntnt; }
+ int operator!=( const CompareNodeCntnt& rCmp ) const
+ { return nNode != rCmp.nNode || nCntnt != rCmp.nCntnt; }
+ int operator< ( const CompareNodeCntnt& rCmp ) const
+ { return nNode < rCmp.nNode ||
+ ( nNode == rCmp.nNode && nCntnt < rCmp.nCntnt); }
+ int operator<=( const CompareNodeCntnt& rCmp ) const
+ { return nNode < rCmp.nNode ||
+ ( nNode == rCmp.nNode && nCntnt <= rCmp.nCntnt); }
+ int operator> ( const CompareNodeCntnt& rCmp ) const
+ { return nNode > rCmp.nNode ||
+ ( nNode == rCmp.nNode && nCntnt > rCmp.nCntnt); }
+ int operator>=( const CompareNodeCntnt& rCmp ) const
+ { return nNode > rCmp.nNode ||
+ ( nNode == rCmp.nNode && nCntnt >= rCmp.nCntnt); }
+};
+
+const SwTOXMark& SwDoc::GotoTOXMark( const SwTOXMark& rCurTOXMark,
+ SwTOXSearch eDir, sal_Bool bInReadOnly )
+{
+ const SwTxtTOXMark* pMark = rCurTOXMark.GetTxtTOXMark();
+ OSL_ENSURE(pMark, "pMark==0 Ungueltige TxtTOXMark");
+
+ const SwTxtNode *pTOXSrc = pMark->GetpTxtNd();
+
+ CompareNodeCntnt aAbsIdx( pTOXSrc->GetIndex(), *pMark->GetStart() );
+ CompareNodeCntnt aPrevPos( 0, 0 );
+ CompareNodeCntnt aNextPos( ULONG_MAX, STRING_NOTFOUND );
+ CompareNodeCntnt aMax( 0, 0 );
+ CompareNodeCntnt aMin( ULONG_MAX, STRING_NOTFOUND );
+
+ const SwTOXMark* pNew = 0;
+ const SwTOXMark* pMax = &rCurTOXMark;
+ const SwTOXMark* pMin = &rCurTOXMark;
+
+ const SwTOXType* pType = rCurTOXMark.GetTOXType();
+ SwTOXMarks aMarks;
+ SwTOXMark::InsertTOXMarks( aMarks, *pType );
+
+ const SwTOXMark* pTOXMark;
+ const SwCntntFrm* pCFrm;
+ Point aPt;
+ for( sal_Int32 nMark=0; nMark<aMarks.Count(); nMark++ )
+ {
+ pTOXMark = aMarks[nMark];
+ if( pTOXMark != &rCurTOXMark &&
+ 0 != ( pMark = pTOXMark->GetTxtTOXMark()) &&
+ 0 != ( pTOXSrc = pMark->GetpTxtNd() ) &&
+ 0 != ( pCFrm = pTOXSrc->getLayoutFrm( GetCurrentLayout(), &aPt, 0, sal_False )) &&
+ ( bInReadOnly || !pCFrm->IsProtected() ))
+ {
+ CompareNodeCntnt aAbsNew( pTOXSrc->GetIndex(), *pMark->GetStart() );
+ switch( eDir )
+ {
+ //Die untenstehenden etwas komplizierter ausgefallen Ausdruecke
+ //dienen dazu auch ueber Eintraege auf der selben (!) Position
+ //traveln zu koennen. Wenn einer Zeit hat mag er sie mal
+ //optimieren.
+
+ case TOX_SAME_PRV:
+ if( pTOXMark->GetText() != rCurTOXMark.GetText() )
+ break;
+ /* no break here */
+ case TOX_PRV:
+ if ( (aAbsNew < aAbsIdx && aAbsNew > aPrevPos &&
+ aPrevPos != aAbsIdx && aAbsNew != aAbsIdx ) ||
+ (aAbsIdx == aAbsNew &&
+ (sal_uLong(&rCurTOXMark) > sal_uLong(pTOXMark) &&
+ (!pNew ||
+ (pNew && (aPrevPos < aAbsIdx ||
+ sal_uLong(pNew) < sal_uLong(pTOXMark)))))) ||
+ (aPrevPos == aAbsNew && aAbsIdx != aAbsNew &&
+ sal_uLong(pTOXMark) > sal_uLong(pNew)) )
+ {
+ pNew = pTOXMark;
+ aPrevPos = aAbsNew;
+ if ( aAbsNew >= aMax )
+ {
+ aMax = aAbsNew;
+ pMax = pTOXMark;
+ }
+ }
+ break;
+
+ case TOX_SAME_NXT:
+ if( pTOXMark->GetText() != rCurTOXMark.GetText() )
+ break;
+ /* no break here */
+ case TOX_NXT:
+ if ( (aAbsNew > aAbsIdx && aAbsNew < aNextPos &&
+ aNextPos != aAbsIdx && aAbsNew != aAbsIdx ) ||
+ (aAbsIdx == aAbsNew &&
+ (sal_uLong(&rCurTOXMark) < sal_uLong(pTOXMark) &&
+ (!pNew ||
+ (pNew && (aNextPos > aAbsIdx ||
+ sal_uLong(pNew) > sal_uLong(pTOXMark)))))) ||
+ (aNextPos == aAbsNew && aAbsIdx != aAbsNew &&
+ sal_uLong(pTOXMark) < sal_uLong(pNew)) )
+ {
+ pNew = pTOXMark;
+ aNextPos = aAbsNew;
+ if ( aAbsNew <= aMin )
+ {
+ aMin = aAbsNew;
+ pMin = pTOXMark;
+ }
+ }
+ break;
+ }
+ }
+ }
+
+
+ // kein Nachfolger wurde gefunden
+ // Min oder Max benutzen
+ if(!pNew)
+ {
+ switch(eDir)
+ {
+ case TOX_PRV:
+ case TOX_SAME_PRV:
+ pNew = pMax;
+ break;
+ case TOX_NXT:
+ case TOX_SAME_NXT:
+ pNew = pMin;
+ break;
+ default:
+ pNew = &rCurTOXMark;
+ }
+ }
+ return *pNew;
+}
+
+const SwTOXBaseSection* SwDoc::InsertTableOf( const SwPosition& rPos,
+ const SwTOXBase& rTOX,
+ const SfxItemSet* pSet,
+ sal_Bool bExpand )
+{
+ GetIDocumentUndoRedo().StartUndo( UNDO_INSTOX, NULL );
+
+ String sSectNm( rTOX.GetTOXName() );
+ sSectNm = GetUniqueTOXBaseName( *rTOX.GetTOXType(), &sSectNm );
+ SwPaM aPam( rPos );
+ SwSectionData aSectionData( TOX_CONTENT_SECTION, sSectNm );
+ SwTOXBaseSection *const pNewSection = dynamic_cast<SwTOXBaseSection *>(
+ InsertSwSection( aPam, aSectionData, & rTOX, pSet, false ));
+ if (pNewSection)
+ {
+ SwSectionNode *const pSectNd = pNewSection->GetFmt()->GetSectionNode();
+ pNewSection->SetTOXName(sSectNm); // rTOX may have had no name...
+
+ if( bExpand )
+ {
+ // add value for 2nd parameter = true to
+ // indicate, that a creation of a new table of content has to be performed.
+ // Value of 1st parameter = default value.
+ pNewSection->Update( 0, true );
+ }
+ else if( 1 == rTOX.GetTitle().Len() && IsInReading() )
+ // insert title of TOX
+ {
+ // then insert the headline section
+ SwNodeIndex aIdx( *pSectNd, +1 );
+
+ SwTxtNode* pHeadNd = GetNodes().MakeTxtNode( aIdx,
+ GetTxtCollFromPool( RES_POOLCOLL_STANDARD ) );
+
+ String sNm( pNewSection->GetTOXName() );
+// ??Resource
+sNm.AppendAscii( RTL_CONSTASCII_STRINGPARAM( "_Head" ));
+
+ SwSectionData headerData( TOX_HEADER_SECTION, sNm );
+
+ SwNodeIndex aStt( *pHeadNd ); aIdx--;
+ SwSectionFmt* pSectFmt = MakeSectionFmt( 0 );
+ GetNodes().InsertTextSection(
+ aStt, *pSectFmt, headerData, 0, &aIdx, true, false);
+ }
+ }
+
+ GetIDocumentUndoRedo().EndUndo( UNDO_INSTOX, NULL );
+
+ return pNewSection;
+}
+
+const SwTOXBaseSection* SwDoc::InsertTableOf( sal_uLong nSttNd, sal_uLong nEndNd,
+ const SwTOXBase& rTOX,
+ const SfxItemSet* pSet )
+{
+ // check for recursiv TOX
+ SwNode* pNd = GetNodes()[ nSttNd ];
+ SwSectionNode* pSectNd = pNd->FindSectionNode();
+ while( pSectNd )
+ {
+ SectionType eT = pSectNd->GetSection().GetType();
+ if( TOX_HEADER_SECTION == eT || TOX_CONTENT_SECTION == eT )
+ return 0;
+ pSectNd = pSectNd->StartOfSectionNode()->FindSectionNode();
+ }
+
+ String sSectNm( rTOX.GetTOXName() );
+ sSectNm = GetUniqueTOXBaseName(*rTOX.GetTOXType(), &sSectNm);
+
+ SwSectionData aSectionData( TOX_CONTENT_SECTION, sSectNm );
+
+ SwNodeIndex aStt( GetNodes(), nSttNd ), aEnd( GetNodes(), nEndNd );
+ SwSectionFmt* pFmt = MakeSectionFmt( 0 );
+ if(pSet)
+ pFmt->SetFmtAttr(*pSet);
+
+// --aEnd; // im InsertSection ist Ende inclusive
+
+ SwSectionNode *const pNewSectionNode =
+ GetNodes().InsertTextSection(aStt, *pFmt, aSectionData, &rTOX, &aEnd);
+ if (!pNewSectionNode)
+ {
+ DelSectionFmt( pFmt );
+ return 0;
+ }
+
+ SwTOXBaseSection *const pNewSection(
+ dynamic_cast<SwTOXBaseSection*>(& pNewSectionNode->GetSection()));
+ pNewSection->SetTOXName(sSectNm); // rTOX may have had no name...
+ return pNewSection;
+}
+
+/*--------------------------------------------------------------------
+ Beschreibung: Aktuelles Verzeichnis ermitteln
+ --------------------------------------------------------------------*/
+const SwTOXBase* SwDoc::GetCurTOX( const SwPosition& rPos ) const
+{
+ const SwNode& rNd = rPos.nNode.GetNode();
+ const SwSectionNode* pSectNd = rNd.FindSectionNode();
+ while( pSectNd )
+ {
+ SectionType eT = pSectNd->GetSection().GetType();
+ if( TOX_CONTENT_SECTION == eT )
+ {
+ OSL_ENSURE( pSectNd->GetSection().ISA( SwTOXBaseSection ),
+ "keine TOXBaseSection!" );
+ SwTOXBaseSection& rTOXSect = (SwTOXBaseSection&)
+ pSectNd->GetSection();
+ return &rTOXSect;
+ }
+ pSectNd = pSectNd->StartOfSectionNode()->FindSectionNode();
+ }
+ return 0;
+}
+
+const SwAttrSet& SwDoc::GetTOXBaseAttrSet(const SwTOXBase& rTOXBase) const
+{
+ OSL_ENSURE( rTOXBase.ISA( SwTOXBaseSection ), "no TOXBaseSection!" );
+ const SwTOXBaseSection& rTOXSect = (const SwTOXBaseSection&)rTOXBase;
+ SwSectionFmt* pFmt = rTOXSect.GetFmt();
+ OSL_ENSURE( pFmt, "invalid TOXBaseSection!" );
+ return pFmt->GetAttrSet();
+}
+
+const SwTOXBase* SwDoc::GetDefaultTOXBase( TOXTypes eTyp, sal_Bool bCreate )
+{
+ SwTOXBase** prBase = 0;
+ switch(eTyp)
+ {
+ case TOX_CONTENT: prBase = &pDefTOXBases->pContBase; break;
+ case TOX_INDEX: prBase = &pDefTOXBases->pIdxBase; break;
+ case TOX_USER: prBase = &pDefTOXBases->pUserBase; break;
+ case TOX_TABLES: prBase = &pDefTOXBases->pTblBase; break;
+ case TOX_OBJECTS: prBase = &pDefTOXBases->pObjBase; break;
+ case TOX_ILLUSTRATIONS: prBase = &pDefTOXBases->pIllBase; break;
+ case TOX_AUTHORITIES: prBase = &pDefTOXBases->pAuthBase; break;
+ }
+ if(!(*prBase) && bCreate)
+ {
+ SwForm aForm(eTyp);
+ const SwTOXType* pType = GetTOXType(eTyp, 0);
+ (*prBase) = new SwTOXBase(pType, aForm, 0, pType->GetTypeName());
+ }
+ return (*prBase);
+}
+
+void SwDoc::SetDefaultTOXBase(const SwTOXBase& rBase)
+{
+ SwTOXBase** prBase = 0;
+ switch(rBase.GetType())
+ {
+ case TOX_CONTENT: prBase = &pDefTOXBases->pContBase; break;
+ case TOX_INDEX: prBase = &pDefTOXBases->pIdxBase; break;
+ case TOX_USER: prBase = &pDefTOXBases->pUserBase; break;
+ case TOX_TABLES: prBase = &pDefTOXBases->pTblBase; break;
+ case TOX_OBJECTS: prBase = &pDefTOXBases->pObjBase; break;
+ case TOX_ILLUSTRATIONS: prBase = &pDefTOXBases->pIllBase; break;
+ case TOX_AUTHORITIES: prBase = &pDefTOXBases->pAuthBase; break;
+ }
+ if(*prBase)
+ delete (*prBase);
+ (*prBase) = new SwTOXBase(rBase);
+}
+
+/*--------------------------------------------------------------------
+ Beschreibung: Verzeichnis loeschen
+ --------------------------------------------------------------------*/
+sal_Bool SwDoc::DeleteTOX( const SwTOXBase& rTOXBase, sal_Bool bDelNodes )
+{
+ // its only delete the TOX, not the nodes
+ sal_Bool bRet = sal_False;
+ OSL_ENSURE( rTOXBase.ISA( SwTOXBaseSection ), "keine TOXBaseSection!" );
+
+ const SwTOXBaseSection& rTOXSect = (const SwTOXBaseSection&)rTOXBase;
+ SwSectionFmt* pFmt = rTOXSect.GetFmt();
+ if( pFmt )
+ {
+ GetIDocumentUndoRedo().StartUndo( UNDO_CLEARTOXRANGE, NULL );
+
+ /* Save the start node of the TOX' section. */
+ SwSectionNode * pMyNode = pFmt->GetSectionNode();
+ /* Save start node of section's surrounding. */
+ SwNode * pStartNd = pMyNode->StartOfSectionNode();
+
+ /* Look for point where to move the cursors in the area to
+ delete to. This is done by first searching forward from the
+ end of the TOX' section. If no content node is found behind
+ the TOX one is searched before it. If this is not
+ successfull, too, insert new text node behind the end of
+ the TOX' section. The cursors from the TOX' section will be
+ moved to the content node found or the new text node. */
+
+ /* Set PaM to end of TOX' section and search following content node.
+
+ aSearchPam will contain the point where to move the cursors
+ to. */
+ SwPaM aSearchPam(*pMyNode->EndOfSectionNode());
+ SwPosition aEndPos(*pStartNd->EndOfSectionNode());
+ if (! aSearchPam.Move() /* no content node found */
+ || *aSearchPam.GetPoint() >= aEndPos /* content node found
+ outside surrounding */
+ )
+ {
+ /* Set PaM to beginning of TOX' section and search previous
+ content node */
+ SwPaM aTmpPam(*pMyNode);
+ aSearchPam = aTmpPam;
+ SwPosition aStartPos(*pStartNd);
+
+ if ( ! aSearchPam.Move(fnMoveBackward) /* no content node found */
+ || *aSearchPam.GetPoint() <= aStartPos /* content node
+ found outside
+ surrounding */
+ )
+ {
+ /* There is no content node in the surrounding of
+ TOX'. Append text node behind TOX' section. */
+
+ SwPosition aInsPos(*pMyNode->EndOfSectionNode());
+ AppendTxtNode(aInsPos);
+
+ SwPaM aTmpPam1(aInsPos);
+ aSearchPam = aTmpPam1;
+ }
+ }
+
+
+ /* PaM containing the TOX. */
+ SwPaM aPam(*pMyNode->EndOfSectionNode(), *pMyNode);
+
+ /* Move cursors contained in TOX to point determined above. */
+ PaMCorrAbs(aPam, *aSearchPam.GetPoint());
+
+ if( !bDelNodes )
+ {
+ SwSections aArr( 0, 4 );
+ sal_uInt16 nCnt = pFmt->GetChildSections( aArr, SORTSECT_NOT, sal_False );
+ for( sal_uInt16 n = 0; n < nCnt; ++n )
+ {
+ SwSection* pSect = aArr[ n ];
+ if( TOX_HEADER_SECTION == pSect->GetType() )
+ {
+ DelSectionFmt( pSect->GetFmt(), bDelNodes );
+ }
+ }
+ }
+
+ DelSectionFmt( pFmt, bDelNodes );
+
+ GetIDocumentUndoRedo().EndUndo( UNDO_CLEARTOXRANGE, NULL );
+ bRet = sal_True;
+ }
+
+ return bRet;
+}
+
+/*--------------------------------------------------------------------
+ Beschreibung: Verzeichnistypen verwalten
+ --------------------------------------------------------------------*/
+sal_uInt16 SwDoc::GetTOXTypeCount(TOXTypes eTyp) const
+{
+ const SwTOXTypePtr * ppTTypes = pTOXTypes->GetData();
+ sal_uInt16 nCnt = 0;
+ for( sal_uInt16 n = 0; n < pTOXTypes->Count(); ++n, ++ppTTypes )
+ if( eTyp == (*ppTTypes)->GetType() )
+ ++nCnt;
+ return nCnt;
+}
+
+const SwTOXType* SwDoc::GetTOXType( TOXTypes eTyp, sal_uInt16 nId ) const
+{
+ const SwTOXTypePtr * ppTTypes = pTOXTypes->GetData();
+ sal_uInt16 nCnt = 0;
+ for( sal_uInt16 n = 0; n < pTOXTypes->Count(); ++n, ++ppTTypes )
+ if( eTyp == (*ppTTypes)->GetType() && nCnt++ == nId )
+ return (*ppTTypes);
+ return 0;
+}
+
+const SwTOXType* SwDoc::InsertTOXType( const SwTOXType& rTyp )
+{
+ SwTOXType * pNew = new SwTOXType( rTyp );
+ pTOXTypes->Insert( pNew, pTOXTypes->Count() );
+ return pNew;
+}
+
+String SwDoc::GetUniqueTOXBaseName( const SwTOXType& rType,
+ const String* pChkStr ) const
+{
+ sal_uInt16 n;
+ const SwSectionNode* pSectNd;
+ const SwSection* pSect;
+
+ if(pChkStr && !pChkStr->Len())
+ pChkStr = 0;
+ String aName( rType.GetTypeName() );
+ xub_StrLen nNmLen = aName.Len();
+
+ sal_uInt16 nNum = 0;
+ sal_uInt16 nTmp = 0;
+ sal_uInt16 nFlagSize = ( pSectionFmtTbl->Count() / 8 ) +2;
+ sal_uInt8* pSetFlags = new sal_uInt8[ nFlagSize ];
+ memset( pSetFlags, 0, nFlagSize );
+
+ for( n = 0; n < pSectionFmtTbl->Count(); ++n )
+ if( 0 != ( pSectNd = (*pSectionFmtTbl)[ n ]->GetSectionNode( sal_False ) )&&
+ TOX_CONTENT_SECTION == (pSect = &pSectNd->GetSection())->GetType())
+ {
+ const String& rNm = pSect->GetSectionName();
+ if( rNm.Match( aName ) == nNmLen )
+ {
+ // Nummer bestimmen und das Flag setzen
+ nNum = (sal_uInt16)rNm.Copy( nNmLen ).ToInt32();
+ if( nNum-- && nNum < pSectionFmtTbl->Count() )
+ pSetFlags[ nNum / 8 ] |= (0x01 << ( nNum & 0x07 ));
+ }
+ if( pChkStr && pChkStr->Equals( rNm ) )
+ pChkStr = 0;
+ }
+
+ if( !pChkStr )
+ {
+ // alle Nummern entsprechend geflag, also bestimme die richtige Nummer
+ nNum = pSectionFmtTbl->Count();
+ for( n = 0; n < nFlagSize; ++n )
+ if( 0xff != ( nTmp = pSetFlags[ n ] ))
+ {
+ // also die Nummer bestimmen
+ nNum = n * 8;
+ while( nTmp & 1 )
+ ++nNum, nTmp >>= 1;
+ break;
+ }
+ }
+ delete [] pSetFlags;
+ if( pChkStr )
+ return *pChkStr;
+ return aName += String::CreateFromInt32( ++nNum );
+}
+
+sal_Bool SwDoc::SetTOXBaseName(const SwTOXBase& rTOXBase, const String& rName)
+{
+ OSL_ENSURE( rTOXBase.ISA( SwTOXBaseSection ),
+ "keine TOXBaseSection!" );
+ SwTOXBaseSection* pTOX = (SwTOXBaseSection*)&rTOXBase;
+
+ String sTmp = GetUniqueTOXBaseName(*rTOXBase.GetTOXType(), &rName);
+ sal_Bool bRet = sTmp == rName;
+ if(bRet)
+ {
+ pTOX->SetTOXName(rName);
+ pTOX->SetSectionName(rName);
+ SetModified();
+ }
+ return bRet;
+}
+
+const SwTxtNode* lcl_FindChapterNode( const SwNode& rNd, sal_uInt8 nLvl = 0 )
+{
+ const SwNode* pNd = &rNd;
+ if( pNd->GetNodes().GetEndOfExtras().GetIndex() > pNd->GetIndex() )
+ {
+ // then find the "Anchor" (Body) position
+ Point aPt;
+ SwNode2Layout aNode2Layout( *pNd, pNd->GetIndex() );
+ const SwFrm* pFrm = aNode2Layout.GetFrm( &aPt, 0, sal_False );
+
+ if( pFrm )
+ {
+ SwPosition aPos( *pNd );
+ pNd = GetBodyTxtNode( *pNd->GetDoc(), aPos, *pFrm );
+ OSL_ENSURE( pNd, "wo steht der Absatz" );
+ }
+ }
+ return pNd ? pNd->FindOutlineNodeOfLevel( nLvl ) : 0;
+}
+
+/*--------------------------------------------------------------------
+ Beschreibung: Verzeichnis-Klasse
+ --------------------------------------------------------------------*/
+SwTOXBaseSection::SwTOXBaseSection(SwTOXBase const& rBase, SwSectionFmt & rFmt)
+ : SwTOXBase( rBase )
+ , SwSection( TOX_CONTENT_SECTION, aEmptyStr, rFmt )
+{
+ SetProtect( rBase.IsProtected() );
+ SetSectionName( GetTOXName() );
+}
+
+SwTOXBaseSection::~SwTOXBaseSection()
+{
+}
+
+sal_Bool SwTOXBaseSection::SetPosAtStartEnd( SwPosition& rPos, sal_Bool bAtStart ) const
+{
+ sal_Bool bRet = sal_False;
+ const SwSectionNode* pSectNd = GetFmt()->GetSectionNode();
+ if( pSectNd )
+ {
+ SwCntntNode* pCNd;
+ xub_StrLen nC = 0;
+ if( bAtStart )
+ {
+ rPos.nNode = *pSectNd;
+ pCNd = pSectNd->GetDoc()->GetNodes().GoNext( &rPos.nNode );
+ }
+ else
+ {
+ rPos.nNode = *pSectNd->EndOfSectionNode();
+ pCNd = pSectNd->GetDoc()->GetNodes().GoPrevious( &rPos.nNode );
+ if( pCNd ) nC = pCNd->Len();
+ }
+ rPos.nContent.Assign( pCNd, nC );
+ bRet = sal_True;
+ }
+ return bRet;
+}
+
+/*--------------------------------------------------------------------
+ Beschreibung: Verzeichnisinhalt zusammensammeln
+ --------------------------------------------------------------------*/
+void SwTOXBaseSection::Update(const SfxItemSet* pAttr,
+ const bool _bNewTOX )//swmodtest 080307
+{
+ const SwSectionNode* pSectNd;
+ if( !SwTOXBase::GetRegisteredIn()->GetDepends() ||
+ !GetFmt() || 0 == (pSectNd = GetFmt()->GetSectionNode() ) ||
+ !pSectNd->GetNodes().IsDocNodes() ||
+ IsHiddenFlag() )
+ return;
+
+ SwDoc* pDoc = (SwDoc*)pSectNd->GetDoc();
+
+ DBG_ASSERT(pDoc != NULL, "Where is the document?");
+
+ if(pAttr && pDoc && GetFmt())
+ pDoc->ChgFmt(*GetFmt(), *pAttr);
+
+ // determine default page description, which will be used by the content nodes,
+ // if no approriate one is found.
+ const SwPageDesc* pDefaultPageDesc;
+ {
+ pDefaultPageDesc =
+ pSectNd->GetSection().GetFmt()->GetPageDesc().GetPageDesc();
+ if ( !_bNewTOX && !pDefaultPageDesc )
+ {
+ // determine page description of table-of-content
+ sal_uInt32 nPgDescNdIdx = pSectNd->GetIndex() + 1;
+ sal_uInt32* pPgDescNdIdx = &nPgDescNdIdx;
+ pDefaultPageDesc = pSectNd->FindPageDesc( sal_False, pPgDescNdIdx );
+ if ( nPgDescNdIdx < pSectNd->GetIndex() )
+ {
+ pDefaultPageDesc = 0;
+ }
+ }
+ // consider end node of content section in the node array.
+ if ( !pDefaultPageDesc &&
+ ( pSectNd->EndOfSectionNode()->GetIndex() <
+ (pSectNd->GetNodes().GetEndOfContent().GetIndex() - 1) )
+ )
+ {
+ // determine page description of content after table-of-content
+ SwNodeIndex aIdx( *(pSectNd->EndOfSectionNode()) );
+ const SwCntntNode* pNdAfterTOX = pSectNd->GetNodes().GoNext( &aIdx );
+ const SwAttrSet& aNdAttrSet = pNdAfterTOX->GetSwAttrSet();
+ const SvxBreak eBreak = aNdAttrSet.GetBreak().GetBreak();
+ if ( !( eBreak == SVX_BREAK_PAGE_BEFORE ||
+ eBreak == SVX_BREAK_PAGE_BOTH )
+ )
+ {
+ pDefaultPageDesc = pNdAfterTOX->FindPageDesc( sal_False );
+ }
+ }
+ // consider start node of content section in the node array.
+ if ( !pDefaultPageDesc &&
+ ( pSectNd->GetIndex() >
+ (pSectNd->GetNodes().GetEndOfContent().StartOfSectionIndex() + 1) )
+ )
+ {
+ // determine page description of content before table-of-content
+ SwNodeIndex aIdx( *pSectNd );
+ pDefaultPageDesc =
+ pSectNd->GetNodes().GoPrevious( &aIdx )->FindPageDesc( sal_False );
+
+ }
+ if ( !pDefaultPageDesc )
+ {
+ // determine default page description
+ pDefaultPageDesc =
+ &const_cast<const SwDoc *>(pDoc)->GetPageDesc( 0 );
+ }
+ }
+
+ pDoc->SetModified();
+
+ // get current Language
+ SwTOXInternational aIntl( GetLanguage(),
+ TOX_INDEX == GetTOXType()->GetType() ?
+ GetOptions() : 0,
+ GetSortAlgorithm() );
+
+ aSortArr.DeleteAndDestroy( 0, aSortArr.Count() );
+
+ // find the first layout node for this TOX, if it only find the content
+ // in his own chapter
+ const SwTxtNode* pOwnChapterNode = IsFromChapter()
+ ? ::lcl_FindChapterNode( *pSectNd, 0 )
+ : 0;
+
+ SwNode2Layout aN2L( *pSectNd );
+ ((SwSectionNode*)pSectNd)->DelFrms();
+
+ // remove old content an insert one empty textnode (to hold the layout!)
+ SwTxtNode* pFirstEmptyNd;
+ {
+ pDoc->DeleteRedline( *pSectNd, true, USHRT_MAX );
+
+ SwNodeIndex aSttIdx( *pSectNd, +1 );
+ SwNodeIndex aEndIdx( *pSectNd->EndOfSectionNode() );
+ pFirstEmptyNd = pDoc->GetNodes().MakeTxtNode( aEndIdx,
+ pDoc->GetTxtCollFromPool( RES_POOLCOLL_TEXT ) );
+
+ {
+ // Task 70995 - save and restore PageDesc and Break Attributes
+ SwNodeIndex aNxtIdx( aSttIdx );
+ const SwCntntNode* pCNd = aNxtIdx.GetNode().GetCntntNode();
+ if( !pCNd )
+ pCNd = pDoc->GetNodes().GoNext( &aNxtIdx );
+ if( pCNd->HasSwAttrSet() )
+ {
+ SfxItemSet aBrkSet( pDoc->GetAttrPool(), aBreakSetRange );
+ aBrkSet.Put( *pCNd->GetpSwAttrSet() );
+ if( aBrkSet.Count() )
+ pFirstEmptyNd->SetAttr( aBrkSet );
+ }
+ }
+ aEndIdx--;
+ SwPosition aPos( aEndIdx, SwIndex( pFirstEmptyNd, 0 ));
+ pDoc->CorrAbs( aSttIdx, aEndIdx, aPos, sal_True );
+
+ // delete all before
+ DelFlyInRange( aSttIdx, aEndIdx );
+ _DelBookmarks( aSttIdx, aEndIdx );
+
+ pDoc->GetNodes().Delete( aSttIdx, aEndIdx.GetIndex() - aSttIdx.GetIndex() );
+
+ }
+
+ //
+ // insert title of TOX
+ if( GetTitle().Len() )
+ {
+ // then insert the headline section
+ SwNodeIndex aIdx( *pSectNd, +1 );
+
+ SwTxtNode* pHeadNd = pDoc->GetNodes().MakeTxtNode( aIdx,
+ GetTxtFmtColl( FORM_TITLE ) );
+ pHeadNd->InsertText( GetTitle(), SwIndex( pHeadNd ) );
+
+ String sNm( GetTOXName() );
+// ??Resource
+sNm.AppendAscii( RTL_CONSTASCII_STRINGPARAM( "_Head" ));
+
+ SwSectionData headerData( TOX_HEADER_SECTION, sNm );
+
+ SwNodeIndex aStt( *pHeadNd ); aIdx--;
+ SwSectionFmt* pSectFmt = pDoc->MakeSectionFmt( 0 );
+ pDoc->GetNodes().InsertTextSection(
+ aStt, *pSectFmt, headerData, 0, &aIdx, true, false);
+ }
+
+ // jetzt waere ein prima Zeitpunkt, um die Numerierung zu updaten
+ pDoc->UpdateNumRule();
+
+ if( GetCreateType() & nsSwTOXElement::TOX_MARK )
+ UpdateMarks( aIntl, pOwnChapterNode );
+
+ if( GetCreateType() & nsSwTOXElement::TOX_OUTLINELEVEL )
+ UpdateOutline( pOwnChapterNode );
+
+ if( GetCreateType() & nsSwTOXElement::TOX_TEMPLATE )
+ UpdateTemplate( pOwnChapterNode );
+
+ if( GetCreateType() & nsSwTOXElement::TOX_OLE ||
+ TOX_OBJECTS == SwTOXBase::GetType())
+ UpdateCntnt( nsSwTOXElement::TOX_OLE, pOwnChapterNode );
+
+ if( GetCreateType() & nsSwTOXElement::TOX_TABLE ||
+ (TOX_TABLES == SwTOXBase::GetType() && IsFromObjectNames()) )
+ UpdateTable( pOwnChapterNode );
+
+ if( GetCreateType() & nsSwTOXElement::TOX_GRAPHIC ||
+ (TOX_ILLUSTRATIONS == SwTOXBase::GetType() && IsFromObjectNames()))
+ UpdateCntnt( nsSwTOXElement::TOX_GRAPHIC, pOwnChapterNode );
+
+ if( GetSequenceName().Len() && !IsFromObjectNames() &&
+ (TOX_TABLES == SwTOXBase::GetType() ||
+ TOX_ILLUSTRATIONS == SwTOXBase::GetType() ) )
+ UpdateSequence( pOwnChapterNode );
+
+ if( GetCreateType() & nsSwTOXElement::TOX_FRAME )
+ UpdateCntnt( nsSwTOXElement::TOX_FRAME, pOwnChapterNode );
+
+ if(TOX_AUTHORITIES == SwTOXBase::GetType())
+ UpdateAuthorities( aIntl );
+
+ // Bei Bedarf Alphadelimitter einfuegen (nur bei Stichwoertern)
+ //
+ if( TOX_INDEX == SwTOXBase::GetType() &&
+ ( GetOptions() & nsSwTOIOptions::TOI_ALPHA_DELIMITTER ) )
+ InsertAlphaDelimitter( aIntl );
+
+ // sortierte Liste aller Verzeichnismarken und Verzeichnisbereiche
+ void* p = 0;
+ String* pStr = 0;
+ sal_uInt16 nCnt = 0, nFormMax = GetTOXForm().GetFormMax();
+ SvStringsDtor aStrArr( (sal_uInt8)nFormMax );
+ SvPtrarr aCollArr( (sal_uInt8)nFormMax );
+ for( ; nCnt < nFormMax; ++nCnt )
+ {
+ aCollArr.Insert( p, nCnt );
+ aStrArr.Insert( pStr, nCnt );
+ }
+
+ SwNodeIndex aInsPos( *pFirstEmptyNd, 1 );
+ for( nCnt = 0; nCnt < aSortArr.Count(); ++nCnt )
+ {
+ ::SetProgressState( 0, pDoc->GetDocShell() );
+
+ // setze den Text in das Verzeichniss
+ sal_uInt16 nLvl = aSortArr[ nCnt ]->GetLevel();
+ SwTxtFmtColl* pColl = (SwTxtFmtColl*)aCollArr[ nLvl ];
+ if( !pColl )
+ {
+ pColl = GetTxtFmtColl( nLvl );
+ aCollArr.Remove( nLvl );
+ p = pColl;
+ aCollArr.Insert( p , nLvl );
+ }
+
+ // Generierung: dynamische TabStops setzen
+ SwTxtNode* pTOXNd = pDoc->GetNodes().MakeTxtNode( aInsPos , pColl );
+ aSortArr[ nCnt ]->pTOXNd = pTOXNd;
+
+ // Generierung: Form auswerten und Platzhalter
+ // fuer die Seitennummer eintragen
+ //if it is a TOX_INDEX and the SwForm IsCommaSeparated()
+ // then a range of entries must be generated into one paragraph
+ sal_uInt16 nRange = 1;
+ if(TOX_INDEX == SwTOXBase::GetType() &&
+ GetTOXForm().IsCommaSeparated() &&
+ aSortArr[nCnt]->GetType() == TOX_SORT_INDEX)
+ {
+ const SwTOXMark& rMark = aSortArr[nCnt]->pTxtMark->GetTOXMark();
+ const String sPrimKey = rMark.GetPrimaryKey();
+ const String sSecKey = rMark.GetSecondaryKey();
+ const SwTOXMark* pNextMark = 0;
+ while(aSortArr.Count() > (nCnt + nRange)&&
+ aSortArr[nCnt + nRange]->GetType() == TOX_SORT_INDEX &&
+ 0 != (pNextMark = &(aSortArr[nCnt + nRange]->pTxtMark->GetTOXMark())) &&
+ pNextMark->GetPrimaryKey() == sPrimKey &&
+ pNextMark->GetSecondaryKey() == sSecKey)
+ nRange++;
+ }
+ // pass node index of table-of-content section and default page description
+ // to method <GenerateText(..)>.
+ GenerateText( nCnt, nRange, aStrArr, pSectNd->GetIndex(), pDefaultPageDesc );
+ nCnt += nRange - 1;
+ }
+
+ // delete the first dummy node and remove all Cursor into the prev node
+ aInsPos = *pFirstEmptyNd;
+ {
+ SwPaM aCorPam( *pFirstEmptyNd );
+ aCorPam.GetPoint()->nContent.Assign( pFirstEmptyNd, 0 );
+ if( !aCorPam.Move( fnMoveForward ) )
+ aCorPam.Move( fnMoveBackward );
+ SwNodeIndex aEndIdx( aInsPos, 1 );
+ pDoc->CorrAbs( aInsPos, aEndIdx, *aCorPam.GetPoint(), sal_True );
+
+ // Task 70995 - save and restore PageDesc and Break Attributes
+ if( pFirstEmptyNd->HasSwAttrSet() )
+ {
+ if( GetTitle().Len() )
+ aEndIdx = *pSectNd;
+ else
+ aEndIdx = *pFirstEmptyNd;
+ SwCntntNode* pCNd = pDoc->GetNodes().GoNext( &aEndIdx );
+ if( pCNd ) // Robust against defect documents, e.g. i60336
+ pCNd->SetAttr( *pFirstEmptyNd->GetpSwAttrSet() );
+ }
+ }
+
+ // now create the new Frames
+ sal_uLong nIdx = pSectNd->GetIndex();
+ // don't delete if index is empty
+ if(nIdx + 2 < pSectNd->EndOfSectionIndex())
+ pDoc->GetNodes().Delete( aInsPos, 1 );
+
+ aN2L.RestoreUpperFrms( pDoc->GetNodes(), nIdx, nIdx + 1 );
+ std::set<SwRootFrm*> aAllLayouts = pDoc->GetAllLayouts();
+ for ( std::set<SwRootFrm*>::iterator pLayoutIter = aAllLayouts.begin(); pLayoutIter != aAllLayouts.end(); pLayoutIter++)
+ {
+ SwFrm::CheckPageDescs( (SwPageFrm*)(*pLayoutIter)->Lower() );
+ }//swmod 080310
+
+ SetProtect( SwTOXBase::IsProtected() );
+}
+
+/*--------------------------------------------------------------------
+ Beschreibung: AlphaDelimitter einfuegen
+ --------------------------------------------------------------------*/
+void SwTOXBaseSection::InsertAlphaDelimitter( const SwTOXInternational& rIntl )
+{
+ SwDoc* pDoc = (SwDoc*)GetFmt()->GetDoc();
+ String sDeli, sLastDeli;
+ sal_uInt16 i = 0;
+ while( i < aSortArr.Count() )
+ {
+ ::SetProgressState( 0, pDoc->GetDocShell() );
+
+ sal_uInt16 nLevel = aSortArr[i]->GetLevel();
+
+ // Alpha-Delimitter ueberlesen
+ if( nLevel == FORM_ALPHA_DELIMITTER )
+ continue;
+
+ String sMyString, sMyStringReading;
+ aSortArr[i]->GetTxt( sMyString, sMyStringReading );
+
+ sDeli = rIntl.GetIndexKey( sMyString, sMyStringReading,
+ aSortArr[i]->GetLocale() );
+
+ // Delimitter schon vorhanden ??
+ if( sDeli.Len() && sLastDeli != sDeli )
+ {
+ // alle kleiner Blank wollen wir nicht haben -> sind Sonderzeichen
+ if( ' ' <= sDeli.GetChar( 0 ) )
+ {
+ SwTOXCustom* pCst = new SwTOXCustom( sDeli, aEmptyStr, FORM_ALPHA_DELIMITTER,
+ rIntl, aSortArr[i]->GetLocale() );
+ aSortArr.Insert( pCst, i++ );
+ }
+ sLastDeli = sDeli;
+ }
+
+ // Skippen bis gleibhes oder kleineres Level erreicht ist
+ do {
+ i++;
+ } while (i < aSortArr.Count() && aSortArr[i]->GetLevel() > nLevel);
+ }
+}
+
+/*--------------------------------------------------------------------
+ Beschreibung: Template auswerten
+ --------------------------------------------------------------------*/
+SwTxtFmtColl* SwTOXBaseSection::GetTxtFmtColl( sal_uInt16 nLevel )
+{
+ SwDoc* pDoc = (SwDoc*)GetFmt()->GetDoc();
+ const String& rName = GetTOXForm().GetTemplate( nLevel );
+ SwTxtFmtColl* pColl = rName.Len() ? pDoc->FindTxtFmtCollByName(rName) :0;
+ if( !pColl )
+ {
+ sal_uInt16 nPoolFmt = 0;
+ const TOXTypes eMyType = SwTOXBase::GetType();
+ switch( eMyType )
+ {
+ case TOX_INDEX: nPoolFmt = RES_POOLCOLL_TOX_IDXH; break;
+ case TOX_USER:
+ if( nLevel < 6 )
+ nPoolFmt = RES_POOLCOLL_TOX_USERH;
+ else
+ nPoolFmt = RES_POOLCOLL_TOX_USER6 - 6;
+ break;
+ case TOX_ILLUSTRATIONS: nPoolFmt = RES_POOLCOLL_TOX_ILLUSH; break;
+ case TOX_OBJECTS: nPoolFmt = RES_POOLCOLL_TOX_OBJECTH; break;
+ case TOX_TABLES: nPoolFmt = RES_POOLCOLL_TOX_TABLESH; break;
+ case TOX_AUTHORITIES: nPoolFmt = RES_POOLCOLL_TOX_AUTHORITIESH; break;
+
+ case TOX_CONTENT:
+ // im Content Bereich gibt es einen Sprung!
+ if( nLevel < 6 )
+ nPoolFmt = RES_POOLCOLL_TOX_CNTNTH;
+ else
+ nPoolFmt = RES_POOLCOLL_TOX_CNTNT6 - 6;
+ break;
+ }
+
+ if(eMyType == TOX_AUTHORITIES && nLevel)
+ nPoolFmt = nPoolFmt + 1;
+ else if(eMyType == TOX_INDEX && nLevel)
+ {
+ //pool: Level 1,2,3, Delimiter
+ //SwForm: Delimiter, Level 1,2,3
+ nPoolFmt += 1 == nLevel ? nLevel + 3 : nLevel - 1;
+ }
+ else
+ nPoolFmt = nPoolFmt + nLevel;
+ pColl = pDoc->GetTxtCollFromPool( nPoolFmt );
+ }
+ return pColl;
+}
+
+/*--------------------------------------------------------------------
+ Beschreibung: Aus Markierungen erzeugen
+ --------------------------------------------------------------------*/
+void SwTOXBaseSection::UpdateMarks( const SwTOXInternational& rIntl,
+ const SwTxtNode* pOwnChapterNode )
+{
+ const SwTOXType* pType = (SwTOXType*) SwTOXBase::GetRegisteredIn();
+ if( !pType->GetDepends() )
+ return;
+
+ SwDoc* pDoc = (SwDoc*)GetFmt()->GetDoc();
+ TOXTypes eTOXTyp = GetTOXType()->GetType();
+ SwIterator<SwTOXMark,SwTOXType> aIter( *pType );
+
+ SwTxtTOXMark* pTxtMark;
+ SwTOXMark* pMark;
+ for( pMark = aIter.First(); pMark; pMark = aIter.Next() )
+ {
+ ::SetProgressState( 0, pDoc->GetDocShell() );
+
+ if( pMark->GetTOXType()->GetType() == eTOXTyp &&
+ 0 != ( pTxtMark = pMark->GetTxtTOXMark() ) )
+ {
+ const SwTxtNode* pTOXSrc = pTxtMark->GetpTxtNd();
+ // nur TOXMarks einfuegen die im Doc stehen
+ // nicht die, die im UNDO stehen
+ //
+ // if selected use marks from the same chapter only
+ if( pTOXSrc->GetNodes().IsDocNodes() &&
+ pTOXSrc->GetTxt().Len() && pTOXSrc->GetDepends() &&
+ pTOXSrc->getLayoutFrm( pDoc->GetCurrentLayout() ) &&
+ (!IsFromChapter() || ::lcl_FindChapterNode( *pTOXSrc, 0 ) == pOwnChapterNode ) &&
+ !pTOXSrc->HasHiddenParaField() &&
+ !SwScriptInfo::IsInHiddenRange( *pTOXSrc, *pTxtMark->GetStart() ) )
+ {
+ SwTOXSortTabBase* pBase = 0;
+ if(TOX_INDEX == eTOXTyp)
+ {
+ // Stichwortverzeichnismarkierung
+ lang::Locale aLocale;
+ if ( pBreakIt->GetBreakIter().is() )
+ {
+ aLocale = pBreakIt->GetLocale(
+ pTOXSrc->GetLang( *pTxtMark->GetStart() ) );
+ }
+
+ pBase = new SwTOXIndex( *pTOXSrc, pTxtMark,
+ GetOptions(), FORM_ENTRY, rIntl, aLocale );
+ InsertSorted(pBase);
+ if(GetOptions() & nsSwTOIOptions::TOI_KEY_AS_ENTRY &&
+ pTxtMark->GetTOXMark().GetPrimaryKey().Len())
+ {
+ pBase = new SwTOXIndex( *pTOXSrc, pTxtMark,
+ GetOptions(), FORM_PRIMARY_KEY, rIntl, aLocale );
+ InsertSorted(pBase);
+ if(pTxtMark->GetTOXMark().GetSecondaryKey().Len())
+ {
+ pBase = new SwTOXIndex( *pTOXSrc, pTxtMark,
+ GetOptions(), FORM_SECONDARY_KEY, rIntl, aLocale );
+ InsertSorted(pBase);
+ }
+ }
+ }
+ else if( TOX_USER == eTOXTyp ||
+ pMark->GetLevel() <= GetLevel())
+ { // Inhaltsberzeichnismarkierung
+ // also used for user marks
+ pBase = new SwTOXContent( *pTOXSrc, pTxtMark, rIntl );
+ InsertSorted(pBase);
+ }
+ }
+ }
+ }
+}
+
+/*--------------------------------------------------------------------
+ Beschreibung: Verzeichnisinhalt aus Gliederungsebene generieren
+ --------------------------------------------------------------------*/
+void SwTOXBaseSection::UpdateOutline( const SwTxtNode* pOwnChapterNode )
+{
+ SwDoc* pDoc = (SwDoc*)GetFmt()->GetDoc();
+ SwNodes& rNds = pDoc->GetNodes();
+
+ const SwOutlineNodes& rOutlNds = rNds.GetOutLineNds();
+ for( sal_uInt16 n = 0; n < rOutlNds.Count(); ++n )
+ {
+ ::SetProgressState( 0, pDoc->GetDocShell() );
+ SwTxtNode* pTxtNd = rOutlNds[ n ]->GetTxtNode();
+ if( pTxtNd && pTxtNd->Len() && pTxtNd->GetDepends() &&
+ sal_uInt16( pTxtNd->GetAttrOutlineLevel()) <= GetLevel() &&
+ pTxtNd->getLayoutFrm( pDoc->GetCurrentLayout() ) &&
+ !pTxtNd->HasHiddenParaField() &&
+ !pTxtNd->HasHiddenCharAttribute( true ) &&
+ ( !IsFromChapter() ||
+ ::lcl_FindChapterNode( *pTxtNd, 0 ) == pOwnChapterNode ))
+ {
+ SwTOXPara * pNew = new SwTOXPara( *pTxtNd, nsSwTOXElement::TOX_OUTLINELEVEL );
+ InsertSorted( pNew );
+ }
+ }
+}
+
+/*--------------------------------------------------------------------
+ Beschreibung: Verzeichnisinhalt aus Vorlagenbereichen generieren
+ --------------------------------------------------------------------*/
+void SwTOXBaseSection::UpdateTemplate( const SwTxtNode* pOwnChapterNode )
+{
+ SwDoc* pDoc = (SwDoc*)GetFmt()->GetDoc();
+ for(sal_uInt16 i = 0; i < MAXLEVEL; i++)
+ {
+ String sTmpStyleNames = GetStyleNames(i);
+ sal_uInt16 nTokenCount = sTmpStyleNames.GetTokenCount(TOX_STYLE_DELIMITER);
+ for( sal_uInt16 nStyle = 0; nStyle < nTokenCount; ++nStyle )
+ {
+ SwTxtFmtColl* pColl = pDoc->FindTxtFmtCollByName(
+ sTmpStyleNames.GetToken( nStyle,
+ TOX_STYLE_DELIMITER ));
+ //TODO: no outline Collections in content indexes if OutlineLevels are already included
+ if( !pColl ||
+ ( TOX_CONTENT == SwTOXBase::GetType() &&
+ GetCreateType() & nsSwTOXElement::TOX_OUTLINELEVEL &&
+ pColl->IsAssignedToListLevelOfOutlineStyle()) )
+ continue;
+
+ SwIterator<SwTxtNode,SwFmtColl> aIter( *pColl );
+ for( SwTxtNode* pTxtNd = aIter.First(); pTxtNd; pTxtNd = aIter.Next() )
+ {
+ ::SetProgressState( 0, pDoc->GetDocShell() );
+
+ if( pTxtNd->GetTxt().Len() && pTxtNd->getLayoutFrm( pDoc->GetCurrentLayout() ) &&
+ pTxtNd->GetNodes().IsDocNodes() &&
+ ( !IsFromChapter() || pOwnChapterNode ==
+ ::lcl_FindChapterNode( *pTxtNd, 0 ) ) )
+ {
+ SwTOXPara * pNew = new SwTOXPara( *pTxtNd, nsSwTOXElement::TOX_TEMPLATE, i + 1 );
+ InsertSorted(pNew);
+ }
+ }
+ }
+ }
+}
+
+/* --------------------------------------------------
+ Description: generate content from sequence fields
+ --------------------------------------------------*/
+void SwTOXBaseSection::UpdateSequence( const SwTxtNode* pOwnChapterNode )
+{
+ SwDoc* pDoc = (SwDoc*)GetFmt()->GetDoc();
+ SwFieldType* pSeqFld = pDoc->GetFldType(RES_SETEXPFLD, GetSequenceName(), false);
+ if(!pSeqFld)
+ return;
+
+ SwIterator<SwFmtFld,SwFieldType> aIter( *pSeqFld );
+ for( SwFmtFld* pFmtFld = aIter.First(); pFmtFld; pFmtFld = aIter.Next() )
+ {
+ const SwTxtFld* pTxtFld = pFmtFld->GetTxtFld();
+ if(!pTxtFld)
+ continue;
+ const SwTxtNode& rTxtNode = pTxtFld->GetTxtNode();
+ ::SetProgressState( 0, pDoc->GetDocShell() );
+
+ if( rTxtNode.GetTxt().Len() && rTxtNode.getLayoutFrm( pDoc->GetCurrentLayout() ) &&
+ rTxtNode.GetNodes().IsDocNodes() &&
+ ( !IsFromChapter() ||
+ ::lcl_FindChapterNode( rTxtNode, 0 ) == pOwnChapterNode ) )
+ {
+ SwTOXPara * pNew = new SwTOXPara( rTxtNode, nsSwTOXElement::TOX_SEQUENCE, 1 );
+ //set indexes if the number or the reference text are to be displayed
+ if( GetCaptionDisplay() == CAPTION_TEXT )
+ {
+ pNew->SetStartIndex(
+ SwGetExpField::GetReferenceTextPos( *pFmtFld, *pDoc ));
+ }
+ else if(GetCaptionDisplay() == CAPTION_NUMBER)
+ {
+ pNew->SetEndIndex(*pTxtFld->GetStart() + 1);
+ }
+ InsertSorted(pNew);
+ }
+ }
+}
+
+void SwTOXBaseSection::UpdateAuthorities( const SwTOXInternational& rIntl )
+{
+ SwDoc* pDoc = (SwDoc*)GetFmt()->GetDoc();
+ SwFieldType* pAuthFld = pDoc->GetFldType(RES_AUTHORITY, aEmptyStr, false);
+ if(!pAuthFld)
+ return;
+
+ SwIterator<SwFmtFld,SwFieldType> aIter( *pAuthFld );
+ for( SwFmtFld* pFmtFld = aIter.First(); pFmtFld; pFmtFld = aIter.Next() )
+ {
+ const SwTxtFld* pTxtFld = pFmtFld->GetTxtFld();
+ //undo
+ if(!pTxtFld)
+ continue;
+ const SwTxtNode& rTxtNode = pTxtFld->GetTxtNode();
+ ::SetProgressState( 0, pDoc->GetDocShell() );
+
+ if( rTxtNode.GetTxt().Len() && rTxtNode.getLayoutFrm( pDoc->GetCurrentLayout() ) &&
+ rTxtNode.GetNodes().IsDocNodes() )
+ {
+ //#106485# the body node has to be used!
+ SwCntntFrm *pFrm = rTxtNode.getLayoutFrm( pDoc->GetCurrentLayout() );
+ SwPosition aFldPos(rTxtNode);
+ const SwTxtNode* pTxtNode = 0;
+ if(pFrm && !pFrm->IsInDocBody())
+ pTxtNode = GetBodyTxtNode( *pDoc, aFldPos, *pFrm );
+ if(!pTxtNode)
+ pTxtNode = &rTxtNode;
+ SwTOXAuthority* pNew = new SwTOXAuthority( *pTxtNode, *pFmtFld, rIntl );
+
+ InsertSorted(pNew);
+ }
+ }
+}
+
+long lcl_IsSOObject( const SvGlobalName& rFactoryNm )
+{
+ static struct _SoObjType {
+ long nFlag;
+ // GlobalNameId
+ struct _GlobalNameIds {
+ sal_uInt32 n1;
+ sal_uInt16 n2, n3;
+ sal_uInt8 b8, b9, b10, b11, b12, b13, b14, b15;
+ } aGlNmIds[4];
+ } aArr[] = {
+ { nsSwTOOElements::TOO_MATH,
+ { {SO3_SM_CLASSID_60},{SO3_SM_CLASSID_50},
+ {SO3_SM_CLASSID_40},{SO3_SM_CLASSID_30} } },
+ { nsSwTOOElements::TOO_CHART,
+ { {SO3_SCH_CLASSID_60},{SO3_SCH_CLASSID_50},
+ {SO3_SCH_CLASSID_40},{SO3_SCH_CLASSID_30} } },
+ { nsSwTOOElements::TOO_CALC,
+ { {SO3_SC_CLASSID_60},{SO3_SC_CLASSID_50},
+ {SO3_SC_CLASSID_40},{SO3_SC_CLASSID_30} } },
+ { nsSwTOOElements::TOO_DRAW_IMPRESS,
+ { {SO3_SIMPRESS_CLASSID_60},{SO3_SIMPRESS_CLASSID_50},
+ {SO3_SIMPRESS_CLASSID_40},{SO3_SIMPRESS_CLASSID_30} } },
+ { nsSwTOOElements::TOO_DRAW_IMPRESS,
+ { {SO3_SDRAW_CLASSID_60},{SO3_SDRAW_CLASSID_50}}},
+ { 0,{{0,0,0,0,0,0,0,0,0,0,0},{0,0,0,0,0,0,0,0,0,0,0},
+ {0,0,0,0,0,0,0,0,0,0,0},{0,0,0,0,0,0,0,0,0,0,0} } }
+ };
+
+ long nRet = 0;
+ for( const _SoObjType* pArr = aArr; !nRet && pArr->nFlag; ++pArr )
+ for ( int n = 0; n < 4; ++n )
+ {
+ const _SoObjType::_GlobalNameIds& rId = pArr->aGlNmIds[ n ];
+ if( !rId.n1 )
+ break;
+ SvGlobalName aGlbNm( rId.n1, rId.n2, rId.n3,
+ rId.b8, rId.b9, rId.b10, rId.b11,
+ rId.b12, rId.b13, rId.b14, rId.b15 );
+ if( rFactoryNm == aGlbNm )
+ {
+ nRet = pArr->nFlag;
+ break;
+ }
+ }
+
+ return nRet;
+}
+
+void SwTOXBaseSection::UpdateCntnt( SwTOXElement eMyType,
+ const SwTxtNode* pOwnChapterNode )
+{
+ SwDoc* pDoc = (SwDoc*)GetFmt()->GetDoc();
+ SwNodes& rNds = pDoc->GetNodes();
+ // auf den 1. Node der 1. Section
+ sal_uLong nIdx = rNds.GetEndOfAutotext().StartOfSectionIndex() + 2,
+ nEndIdx = rNds.GetEndOfAutotext().GetIndex();
+
+ while( nIdx < nEndIdx )
+ {
+ ::SetProgressState( 0, pDoc->GetDocShell() );
+
+ SwNode* pNd = rNds[ nIdx ];
+ SwCntntNode* pCNd = 0;
+ switch( eMyType )
+ {
+ case nsSwTOXElement::TOX_FRAME:
+ if( !pNd->IsNoTxtNode() )
+ {
+ pCNd = pNd->GetCntntNode();
+ if( !pCNd )
+ {
+ SwNodeIndex aTmp( *pNd );
+ pCNd = rNds.GoNext( &aTmp );
+ }
+ }
+ break;
+ case nsSwTOXElement::TOX_GRAPHIC:
+ if( pNd->IsGrfNode() )
+ pCNd = (SwCntntNode*)pNd;
+ break;
+ case nsSwTOXElement::TOX_OLE:
+ if( pNd->IsOLENode() )
+ {
+ sal_Bool bInclude = sal_True;
+ if(TOX_OBJECTS == SwTOXBase::GetType())
+ {
+ SwOLENode* pOLENode = pNd->GetOLENode();
+ long nMyOLEOptions = GetOLEOptions();
+ SwOLEObj& rOLEObj = pOLENode->GetOLEObj();
+
+ if( rOLEObj.IsOleRef() ) //Noch nicht geladen
+ {
+ SvGlobalName aTmpName = SvGlobalName( rOLEObj.GetOleRef()->getClassID() );
+ long nObj = ::lcl_IsSOObject( aTmpName );
+ bInclude = ( (nMyOLEOptions & nsSwTOOElements::TOO_OTHER) && 0 == nObj)
+ || (0 != (nMyOLEOptions & nObj));
+ }
+ else
+ {
+ OSL_FAIL("OLE-object nicht geladen?");
+ bInclude = sal_False;
+ }
+ }
+
+ if(bInclude)
+ pCNd = (SwCntntNode*)pNd;
+ }
+ break;
+ default: break;
+ }
+
+ if( pCNd )
+ {
+ //find node in body text
+ int nSetLevel = USHRT_MAX;
+
+ //#111105# tables of tables|illustrations|objects don't support hierarchies
+ if( IsLevelFromChapter() &&
+ TOX_TABLES != SwTOXBase::GetType() &&
+ TOX_ILLUSTRATIONS != SwTOXBase::GetType() &&
+ TOX_OBJECTS != SwTOXBase::GetType() )
+ {
+ const SwTxtNode* pOutlNd = ::lcl_FindChapterNode( *pCNd,
+ MAXLEVEL - 1 );
+ if( pOutlNd )
+ {
+ if( pOutlNd->GetTxtColl()->IsAssignedToListLevelOfOutlineStyle())
+ nSetLevel = pOutlNd->GetTxtColl()->GetAttrOutlineLevel() ;//<-end,zhaojianwei
+ }
+ }
+
+ if( pCNd->getLayoutFrm( pDoc->GetCurrentLayout() ) && ( !IsFromChapter() ||
+ ::lcl_FindChapterNode( *pCNd, 0 ) == pOwnChapterNode ))
+ {
+ SwTOXPara * pNew = new SwTOXPara( *pCNd, eMyType,
+ ( USHRT_MAX != nSetLevel )
+ ? static_cast<sal_uInt16>(nSetLevel)
+ : FORM_ALPHA_DELIMITTER );
+ InsertSorted( pNew );
+ }
+ }
+
+ nIdx = pNd->StartOfSectionNode()->EndOfSectionIndex() + 2; // 2 == End-/StartNode
+ }
+}
+
+/*--------------------------------------------------------------------
+ Beschreibung: Tabelleneintraege zusammensuchen
+ --------------------------------------------------------------------*/
+void SwTOXBaseSection::UpdateTable( const SwTxtNode* pOwnChapterNode )
+{
+ SwDoc* pDoc = (SwDoc*)GetFmt()->GetDoc();
+ SwNodes& rNds = pDoc->GetNodes();
+ const SwFrmFmts& rArr = *pDoc->GetTblFrmFmts();
+
+ for( sal_uInt16 n = 0; n < rArr.Count(); ++n )
+ {
+ ::SetProgressState( 0, pDoc->GetDocShell() );
+
+ SwTable* pTmpTbl = SwTable::FindTable( rArr[ n ] );
+ SwTableBox* pFBox;
+ if( pTmpTbl && 0 != (pFBox = pTmpTbl->GetTabSortBoxes()[0] ) &&
+ pFBox->GetSttNd() && pFBox->GetSttNd()->GetNodes().IsDocNodes() )
+ {
+ const SwTableNode* pTblNd = pFBox->GetSttNd()->FindTableNode();
+ SwNodeIndex aCntntIdx( *pTblNd, 1 );
+
+ SwCntntNode* pCNd;
+ while( 0 != ( pCNd = rNds.GoNext( &aCntntIdx ) ) &&
+ aCntntIdx.GetIndex() < pTblNd->EndOfSectionIndex() )
+ {
+ if( pCNd->getLayoutFrm( pDoc->GetCurrentLayout() ) && (!IsFromChapter() ||
+ ::lcl_FindChapterNode( *pCNd, 0 ) == pOwnChapterNode ))
+ {
+ SwTOXTable * pNew = new SwTOXTable( *pCNd );
+ if( IsLevelFromChapter() && TOX_TABLES != SwTOXBase::GetType())
+ {
+ const SwTxtNode* pOutlNd =
+ ::lcl_FindChapterNode( *pCNd, MAXLEVEL - 1 );
+ if( pOutlNd )
+ {
+ if( pOutlNd->GetTxtColl()->IsAssignedToListLevelOfOutlineStyle())
+ {
+ const int nTmp = pOutlNd->GetTxtColl()->GetAttrOutlineLevel();
+ pNew->SetLevel( static_cast<sal_uInt16>(nTmp) );//<-end ,zhaojianwei
+ }
+ }
+ }
+ InsertSorted(pNew);
+ break;
+ }
+ }
+ }
+ }
+}
+
+/*--------------------------------------------------------------------
+ Beschreibung: String generieren anhand der Form
+ SonderZeichen 0-31 und 255 entfernen
+ --------------------------------------------------------------------*/
+String lcl_GetNumString( const SwTOXSortTabBase& rBase, sal_Bool bUsePrefix, sal_uInt8 nLevel )
+{
+ String sRet;
+
+ if( !rBase.pTxtMark && rBase.aTOXSources.Count() > 0 )
+ { // nur wenn es keine Marke ist
+ const SwTxtNode* pNd = rBase.aTOXSources[0].pNd->GetTxtNode();
+ if( pNd )
+ {
+ const SwNumRule* pRule = pNd->GetNumRule();
+
+ if( pRule && pNd->GetActualListLevel() < MAXLEVEL )
+ sRet = pNd->GetNumString(bUsePrefix, nLevel);
+ }
+ }
+ return sRet;
+}
+
+// add parameter <_TOXSectNdIdx> and <_pDefaultPageDesc> in order to control,
+// which page description is used, no appropriate one is found.
+void SwTOXBaseSection::GenerateText( sal_uInt16 nArrayIdx,
+ sal_uInt16 nCount,
+ SvStringsDtor& ,
+ const sal_uInt32 _nTOXSectNdIdx,
+ const SwPageDesc* _pDefaultPageDesc )
+{
+ LinkStructArr aLinkArr;
+ SwDoc* pDoc = (SwDoc*)GetFmt()->GetDoc();
+ ::SetProgressState( 0, pDoc->GetDocShell() );
+
+ //pTOXNd is only set at the first mark
+ SwTxtNode* pTOXNd = (SwTxtNode*)aSortArr[nArrayIdx]->pTOXNd;
+ String& rTxt = (String&)pTOXNd->GetTxt();
+ rTxt.Erase();
+ for(sal_uInt16 nIndex = nArrayIdx; nIndex < nArrayIdx + nCount; nIndex++)
+ {
+ if(nIndex > nArrayIdx)
+ rTxt.AppendAscii( RTL_CONSTASCII_STRINGPARAM( ", " )); // comma separation
+ // String mit dem Pattern aus der Form initialisieren
+ const SwTOXSortTabBase& rBase = *aSortArr[nIndex];
+ sal_uInt16 nLvl = rBase.GetLevel();
+ OSL_ENSURE( nLvl < GetTOXForm().GetFormMax(), "ungueltiges FORM_LEVEL");
+
+ SvxTabStopItem aTStops( 0, 0, SVX_TAB_ADJUST_DEFAULT, RES_PARATR_TABSTOP );
+ xub_StrLen nLinkStartPosition = STRING_NOTFOUND;
+ String sLinkCharacterStyle; //default to "Default" character style - which is none
+ String sURL;
+ // create an enumerator
+ // #i21237#
+ SwFormTokens aPattern = GetTOXForm().GetPattern(nLvl);
+ SwFormTokens::iterator aIt = aPattern.begin();
+ // remove text from node
+ while(aIt != aPattern.end()) // #i21237#
+ {
+ SwFormToken aToken = *aIt; // #i21237#
+ xub_StrLen nStartCharStyle = rTxt.Len();
+ switch( aToken.eTokenType )
+ {
+ case TOKEN_ENTRY_NO:
+ // fuer Inhaltsverzeichnis Numerierung
+ rTxt.Insert( lcl_GetNumString( rBase, aToken.nChapterFormat == CF_NUMBER, static_cast<sal_uInt8>(aToken.nOutlineLevel - 1)) );
+ break;
+
+ case TOKEN_ENTRY_TEXT:
+ {
+ SwIndex aIdx( pTOXNd, rTxt.Len() );
+ rBase.FillText( *pTOXNd, aIdx );
+ }
+ break;
+
+ case TOKEN_ENTRY:
+ {
+ // fuer Inhaltsverzeichnis Numerierung
+ rTxt.Insert( lcl_GetNumString( rBase, sal_True, MAXLEVEL ));
+
+ SwIndex aIdx( pTOXNd, rTxt.Len() );
+ rBase.FillText( *pTOXNd, aIdx );
+ }
+ break;
+
+ case TOKEN_TAB_STOP:
+ if (aToken.bWithTab) // #i21237#
+ rTxt.Append('\t');
+ //
+
+ if(SVX_TAB_ADJUST_END > aToken.eTabAlign)
+ {
+ const SvxLRSpaceItem& rLR =
+ (SvxLRSpaceItem&)pTOXNd->
+ SwCntntNode::GetAttr( RES_LR_SPACE, sal_True );
+
+ long nTabPosition = aToken.nTabStopPosition;
+ if( !GetTOXForm().IsRelTabPos() && rLR.GetTxtLeft() )
+ nTabPosition -= rLR.GetTxtLeft();
+ aTStops.Insert( SvxTabStop( nTabPosition,
+ aToken.eTabAlign,
+ cDfltDecimalChar,
+ aToken.cTabFillChar ));
+ }
+ else
+ {
+ const SwPageDesc* pPageDesc = ((SwFmtPageDesc&)pTOXNd->
+ SwCntntNode::GetAttr( RES_PAGEDESC )).GetPageDesc();
+
+ sal_Bool bCallFindRect = sal_True;
+ long nRightMargin;
+ if( pPageDesc )
+ {
+ const SwFrm* pFrm = pTOXNd->getLayoutFrm( pDoc->GetCurrentLayout(), 0, 0, sal_True );
+ if( !pFrm || 0 == ( pFrm = pFrm->FindPageFrm() ) ||
+ pPageDesc != ((SwPageFrm*)pFrm)->GetPageDesc() )
+ // dann muss man ueber den PageDesc gehen
+ bCallFindRect = sal_False;
+ }
+
+ SwRect aNdRect;
+ if( bCallFindRect )
+ aNdRect = pTOXNd->FindLayoutRect( sal_True );
+
+ if( aNdRect.IsEmpty() )
+ {
+ // dann hilft alles nichts, wir muessen ueber die Seiten-
+ // vorlage gehen.
+ sal_uInt32 nPgDescNdIdx = pTOXNd->GetIndex() + 1;
+ sal_uInt32* pPgDescNdIdx = &nPgDescNdIdx;
+ pPageDesc = pTOXNd->FindPageDesc( sal_False, pPgDescNdIdx );
+ if ( !pPageDesc ||
+ *pPgDescNdIdx < _nTOXSectNdIdx )
+ {
+ // use default page description, if none is found
+ // or the found one is given by a node before the
+ // table-of-content section.
+ pPageDesc = _pDefaultPageDesc;
+ }
+
+ const SwFrmFmt& rPgDscFmt = pPageDesc->GetMaster();
+ nRightMargin = rPgDscFmt.GetFrmSize().GetWidth() -
+ rPgDscFmt.GetLRSpace().GetLeft() -
+ rPgDscFmt.GetLRSpace().GetRight();
+ }
+ else
+ nRightMargin = aNdRect.Width();
+ //#i24363# tab stops relative to indent
+ if( pDoc->get(IDocumentSettingAccess::TABS_RELATIVE_TO_INDENT) )
+ {
+ //left margin of paragraph style
+ const SvxLRSpaceItem& rLRSpace = pTOXNd->GetTxtColl()->GetLRSpace();
+ nRightMargin -= rLRSpace.GetLeft();
+ nRightMargin -= rLRSpace.GetTxtFirstLineOfst();
+ }
+
+ aTStops.Insert( SvxTabStop( nRightMargin, SVX_TAB_ADJUST_RIGHT,
+ cDfltDecimalChar,
+ aToken.cTabFillChar ));
+ }
+ break;
+
+ case TOKEN_TEXT:
+ rTxt.Append( aToken.sText );
+ break;
+
+ case TOKEN_PAGE_NUMS:
+ // Platzhalter fuer Seitennummer(n) es wird nur der erste beachtet
+ //
+ {
+ // Die Anzahl der gleichen Eintrage bestimmt die Seitennummern-Pattern
+ //
+ sal_uInt16 nSize = rBase.aTOXSources.Count();
+ if( nSize > 0 )
+ {
+ String aInsStr( cNumRepl );
+ for(sal_uInt16 i=1; i < nSize; ++i)
+ {
+ aInsStr.AppendAscii( sPageDeli );
+ aInsStr += cNumRepl;
+ }
+ aInsStr += cEndPageNum;
+ rTxt.Append( aInsStr );
+ }
+ }
+ break;
+
+ case TOKEN_CHAPTER_INFO:
+ {
+ // ein bischen trickreich: suche irgend einen Frame
+ const SwTOXSource* pTOXSource = 0;
+ if(rBase.aTOXSources.Count())
+ pTOXSource = &rBase.aTOXSources[0];
+
+ // #i53420#
+ if ( pTOXSource && pTOXSource->pNd &&
+ pTOXSource->pNd->IsCntntNode() )
+ {
+ const SwCntntFrm* pFrm = pTOXSource->pNd->getLayoutFrm( pDoc->GetCurrentLayout() );
+ if( pFrm )
+ {
+ SwChapterFieldType aFldTyp;
+ SwChapterField aFld( &aFldTyp, aToken.nChapterFormat );
+ aFld.SetLevel( static_cast<sal_uInt8>(aToken.nOutlineLevel - 1) );
+ // #i53420#
+ aFld.ChangeExpansion( pFrm,
+ dynamic_cast<const SwCntntNode*>(pTOXSource->pNd),
+ sal_True );
+ // <--
+ //---> #i89791#
+ // continue to support CF_NUMBER
+ // and CF_NUM_TITLE in order to handle ODF 1.0/1.1
+ // written by OOo 3.x in the same way as OOo 2.x
+ // would handle them.
+ if ( CF_NUM_NOPREPST_TITLE == aToken.nChapterFormat ||
+ CF_NUMBER == aToken.nChapterFormat )
+ rTxt.Insert(aFld.GetNumber()); //get the string number without pre/postfix
+ else if ( CF_NUMBER_NOPREPST == aToken.nChapterFormat ||
+ CF_NUM_TITLE == aToken.nChapterFormat )
+ //<---
+ {
+ rTxt += aFld.GetNumber();
+ rTxt += ' ';
+ rTxt += aFld.GetTitle();
+ }
+ else if(CF_TITLE == aToken.nChapterFormat)
+ rTxt += aFld.GetTitle();
+ }
+ }
+ }
+ break;
+
+ case TOKEN_LINK_START:
+ nLinkStartPosition = rTxt.Len();
+ sLinkCharacterStyle = aToken.sCharStyleName;
+ break;
+
+ case TOKEN_LINK_END:
+ //TODO: only paired start/end tokens are valid
+ if( STRING_NOTFOUND != nLinkStartPosition)
+ {
+ SwIndex aIdx( pTOXNd, nLinkStartPosition );
+ //pTOXNd->Erase( aIdx, SwForm::nFormLinkSttLen );
+ xub_StrLen nEnd = rTxt.Len();
+
+ if( !sURL.Len() )
+ {
+ sURL = rBase.GetURL();
+ if( !sURL.Len() )
+ break;
+ }
+ LinkStruct* pNewLink = new LinkStruct(sURL, nLinkStartPosition,
+ nEnd);
+ pNewLink->aINetFmt.SetVisitedFmt(sLinkCharacterStyle);
+ pNewLink->aINetFmt.SetINetFmt(sLinkCharacterStyle);
+ if(sLinkCharacterStyle.Len())
+ {
+ sal_uInt16 nPoolId =
+ SwStyleNameMapper::GetPoolIdFromUIName( sLinkCharacterStyle, nsSwGetPoolIdFromName::GET_POOLID_CHRFMT );
+ pNewLink->aINetFmt.SetVisitedFmtId(nPoolId);
+ pNewLink->aINetFmt.SetINetFmtId(nPoolId);
+ }
+ else
+ {
+ pNewLink->aINetFmt.SetVisitedFmtId(USHRT_MAX);
+ pNewLink->aINetFmt.SetINetFmtId(USHRT_MAX);
+ }
+ aLinkArr.Insert( pNewLink, aLinkArr.Count() );
+ nLinkStartPosition = STRING_NOTFOUND;
+ sLinkCharacterStyle.Erase();
+ }
+ break;
+
+ case TOKEN_AUTHORITY:
+ {
+ ToxAuthorityField eField = (ToxAuthorityField)aToken.nAuthorityField;
+ SwIndex aIdx( pTOXNd, rTxt.Len() );
+ rBase.FillText( *pTOXNd, aIdx, static_cast<sal_uInt16>(eField) );
+ }
+ break;
+ case TOKEN_END: break;
+ }
+
+ if( aToken.sCharStyleName.Len() )
+ {
+ SwCharFmt* pCharFmt;
+ if( USHRT_MAX != aToken.nPoolId )
+ pCharFmt = pDoc->GetCharFmtFromPool( aToken.nPoolId );
+ else
+ pCharFmt = pDoc->FindCharFmtByName( aToken.sCharStyleName);
+
+ if (pCharFmt)
+ {
+ SwFmtCharFmt aFmt( pCharFmt );
+ pTOXNd->InsertItem( aFmt, nStartCharStyle,
+ rTxt.Len(), nsSetAttrMode::SETATTR_DONTEXPAND );
+ }
+ }
+
+ ++aIt; // #i21237#
+ }
+
+ pTOXNd->SetAttr( aTStops );
+ }
+
+ if(aLinkArr.Count())
+ for(sal_uInt16 i = 0; i < aLinkArr.Count(); ++i )
+ {
+ LinkStruct* pTmp = aLinkArr.GetObject(i);
+ pTOXNd->InsertItem( pTmp->aINetFmt, pTmp->nStartTextPos,
+ pTmp->nEndTextPos);
+ }
+}
+
+/*--------------------------------------------------------------------
+ Beschreibung: Seitennummer errechnen und nach dem Formatieren
+ eintragen
+ --------------------------------------------------------------------*/
+void SwTOXBaseSection::UpdatePageNum()
+{
+ if( !aSortArr.Count() )
+ return ;
+
+ // die aktuellen Seitennummern ins Verzeichnis eintragen
+ SwPageFrm* pAktPage = 0;
+ sal_uInt16 nPage = 0;
+ SwDoc* pDoc = (SwDoc*)GetFmt()->GetDoc();
+
+ SwTOXInternational aIntl( GetLanguage(),
+ TOX_INDEX == GetTOXType()->GetType() ?
+ GetOptions() : 0,
+ GetSortAlgorithm() );
+
+ for( sal_uInt16 nCnt = 0; nCnt < aSortArr.Count(); ++nCnt )
+ {
+ // Schleife ueber alle SourceNodes
+ SvUShorts aNums; //Die Seitennummern
+ SvPtrarr aDescs; //Die PageDescriptoren passend zu den Seitennummern.
+ SvUShorts* pMainNums = 0; // contains page numbers of main entries
+
+ // process run in lines
+ sal_uInt16 nRange = 0;
+ if(GetTOXForm().IsCommaSeparated() &&
+ aSortArr[nCnt]->GetType() == TOX_SORT_INDEX)
+ {
+ const SwTOXMark& rMark = aSortArr[nCnt]->pTxtMark->GetTOXMark();
+ const String sPrimKey = rMark.GetPrimaryKey();
+ const String sSecKey = rMark.GetSecondaryKey();
+ const SwTOXMark* pNextMark = 0;
+ while(aSortArr.Count() > (nCnt + nRange)&&
+ aSortArr[nCnt + nRange]->GetType() == TOX_SORT_INDEX &&
+ 0 != (pNextMark = &(aSortArr[nCnt + nRange]->pTxtMark->GetTOXMark())) &&
+ pNextMark->GetPrimaryKey() == sPrimKey &&
+ pNextMark->GetSecondaryKey() == sSecKey)
+ nRange++;
+ }
+ else
+ nRange = 1;
+
+ for(sal_uInt16 nRunInEntry = nCnt; nRunInEntry < nCnt + nRange; nRunInEntry++)
+ {
+ SwTOXSortTabBase* pSortBase = aSortArr[nRunInEntry];
+ sal_uInt16 nSize = pSortBase->aTOXSources.Count();
+ sal_uInt16 i;
+ for( sal_uInt16 j = 0; j < nSize; ++j )
+ {
+ ::SetProgressState( 0, pDoc->GetDocShell() );
+
+ SwTOXSource& rTOXSource = pSortBase->aTOXSources[j];
+ if( rTOXSource.pNd )
+ {
+ SwCntntFrm* pFrm = rTOXSource.pNd->getLayoutFrm( pDoc->GetCurrentLayout() );
+ OSL_ENSURE( pFrm || pDoc->IsUpdateTOX(), "TOX, no Frame found");
+ if( !pFrm )
+ continue;
+ if( pFrm->IsTxtFrm() && ((SwTxtFrm*)pFrm)->HasFollow() )
+ {
+ // dann suche den richtigen heraus
+ SwTxtFrm* pNext = (SwTxtFrm*)pFrm;
+ while( 0 != ( pNext = (SwTxtFrm*)pFrm->GetFollow() )
+ && rTOXSource.nPos >= pNext->GetOfst() )
+ pFrm = pNext;
+ }
+
+ SwPageFrm* pTmpPage = pFrm->FindPageFrm();
+ if( pTmpPage != pAktPage )
+ {
+ nPage = pTmpPage->GetVirtPageNum();
+ pAktPage = pTmpPage;
+ }
+
+ // sortiert einfuegen
+ for( i = 0; i < aNums.Count() && aNums[i] < nPage; ++i )
+ ;
+
+ if( i >= aNums.Count() || aNums[ i ] != nPage )
+ {
+ aNums.Insert( nPage, i );
+ aDescs.Insert( (void*)pAktPage->GetPageDesc(), i );
+ }
+ // is it a main entry?
+ if(TOX_SORT_INDEX == pSortBase->GetType() &&
+ rTOXSource.bMainEntry)
+ {
+ if(!pMainNums)
+ pMainNums = new SvUShorts;
+ pMainNums->Insert(nPage, pMainNums->Count());
+ }
+ }
+ }
+ // einfuegen der Seitennummer in den Verzeichnis-Text-Node
+ const SwTOXSortTabBase* pBase = aSortArr[ nCnt ];
+ if(pBase->pTOXNd)
+ {
+ const SwTxtNode* pTxtNd = pBase->pTOXNd->GetTxtNode();
+ OSL_ENSURE( pTxtNd, "kein TextNode, falsches Verzeichnis" );
+
+ _UpdatePageNum( (SwTxtNode*)pTxtNd, aNums, aDescs, pMainNums,
+ aIntl );
+ }
+ DELETEZ(pMainNums);
+ aNums.Remove(0, aNums.Count());
+ }
+ }
+ // nach dem Setzen der richtigen Seitennummer, das Mapping-Array
+ // wieder loeschen !!
+ aSortArr.DeleteAndDestroy( 0, aSortArr.Count() );
+}
+
+/*--------------------------------------------------------------------
+ Beschreibung: Austausch der Seitennummer-Platzhalter
+ --------------------------------------------------------------------*/
+// search for the page no in the array of main entry page numbers
+sal_Bool lcl_HasMainEntry( const SvUShorts* pMainEntryNums, sal_uInt16 nToFind )
+{
+ for(sal_uInt16 i = 0; pMainEntryNums && i < pMainEntryNums->Count(); ++i)
+ if(nToFind == (*pMainEntryNums)[i])
+ return sal_True;
+ return sal_False;
+}
+
+void SwTOXBaseSection::_UpdatePageNum( SwTxtNode* pNd,
+ const SvUShorts& rNums,
+ const SvPtrarr & rDescs,
+ const SvUShorts* pMainEntryNums,
+ const SwTOXInternational& rIntl )
+{
+ //collect starts end ends of main entry character style
+ SvUShorts* pCharStyleIdx = pMainEntryNums ? new SvUShorts : 0;
+
+ String sSrchStr( cNumRepl );
+ sSrchStr.AppendAscii( sPageDeli ) += cNumRepl;
+ xub_StrLen nStartPos = pNd->GetTxt().Search( sSrchStr );
+ ( sSrchStr = cNumRepl ) += cEndPageNum;
+ xub_StrLen nEndPos = pNd->GetTxt().Search( sSrchStr );
+ sal_uInt16 i;
+
+ if( STRING_NOTFOUND == nEndPos || !rNums.Count() )
+ return;
+
+ if( STRING_NOTFOUND == nStartPos || nStartPos > nEndPos)
+ nStartPos = nEndPos;
+
+ sal_uInt16 nOld = rNums[0],
+ nBeg = nOld,
+ nCount = 0;
+ String aNumStr( SvxNumberType( ((SwPageDesc*)rDescs[0])->GetNumType() ).
+ GetNumStr( nBeg ) );
+ if( pCharStyleIdx && lcl_HasMainEntry( pMainEntryNums, nBeg ))
+ {
+ sal_uInt16 nTemp = 0;
+ pCharStyleIdx->Insert( nTemp, pCharStyleIdx->Count());
+ }
+
+ // Platzhalter loeschen
+ SwIndex aPos(pNd, nStartPos);
+ SwCharFmt* pPageNoCharFmt = 0;
+ SwpHints* pHints = pNd->GetpSwpHints();
+ if(pHints)
+ for(sal_uInt16 nHintIdx = 0; nHintIdx < pHints->GetStartCount(); nHintIdx++)
+ {
+ SwTxtAttr* pAttr = pHints->GetStart(nHintIdx);
+ xub_StrLen nTmpEnd = pAttr->GetEnd() ? *pAttr->GetEnd() : 0;
+ if( nStartPos >= *pAttr->GetStart() &&
+ (nStartPos + 2) <= nTmpEnd &&
+ pAttr->Which() == RES_TXTATR_CHARFMT)
+ {
+ pPageNoCharFmt = pAttr->GetCharFmt().GetCharFmt();
+ break;
+ }
+ }
+ pNd->EraseText(aPos, nEndPos - nStartPos + 2);
+
+ for( i = 1; i < rNums.Count(); ++i)
+ {
+ SvxNumberType aType( ((SwPageDesc*)rDescs[i])->GetNumType() );
+ if( TOX_INDEX == SwTOXBase::GetType() )
+ { // Zusammenfassen f. ff.
+ // Alle folgenden aufaddieren
+ // break up if main entry starts or ends and
+ // insert a char style index
+ sal_Bool bMainEntryChanges = lcl_HasMainEntry(pMainEntryNums, nOld)
+ != lcl_HasMainEntry(pMainEntryNums, rNums[i]);
+
+ if(nOld == rNums[i]-1 && !bMainEntryChanges &&
+ 0 != (GetOptions() & (nsSwTOIOptions::TOI_FF|nsSwTOIOptions::TOI_DASH)))
+ nCount++;
+ else
+ {
+ // ff. f. alten Wert flushen
+ if(GetOptions() & nsSwTOIOptions::TOI_FF)
+ {
+ if ( nCount >= 1 )
+ aNumStr += rIntl.GetFollowingText( nCount > 1 );
+ }
+ else
+ {
+ if(nCount >= 2 )
+ aNumStr += '-';
+ else if(nCount == 1 )
+ aNumStr.AppendAscii( sPageDeli );
+//#58127# Wenn nCount == 0, dann steht die einzige Seitenzahl schon im aNumStr!
+ if(nCount)
+ aNumStr += aType.GetNumStr( nBeg + nCount );
+ }
+
+ // neuen String anlegen
+ nBeg = rNums[i];
+ aNumStr.AppendAscii( sPageDeli );
+ //the change of the character style must apply after sPageDeli is appended
+ if(pCharStyleIdx && bMainEntryChanges)
+ pCharStyleIdx->Insert(aNumStr.Len(),
+ pCharStyleIdx->Count());
+ aNumStr += aType.GetNumStr( nBeg );
+ nCount = 0;
+ }
+ nOld = rNums[i];
+ }
+ else
+ { // Alle Nummern eintragen
+ aNumStr += aType.GetNumStr( sal_uInt16(rNums[i]) );
+ if(i != (rNums.Count()-1))
+ aNumStr.AppendAscii( sPageDeli );
+ }
+ }
+ // Bei Ende und ff. alten Wert flushen
+ if( TOX_INDEX == SwTOXBase::GetType() )
+ {
+ if(GetOptions() & nsSwTOIOptions::TOI_FF)
+ {
+ if( nCount >= 1 )
+ aNumStr += rIntl.GetFollowingText( nCount > 1 );
+ }
+ else
+ {
+ if(nCount >= 2)
+ aNumStr +='-';
+ else if(nCount == 1)
+ aNumStr.AppendAscii( sPageDeli );
+//#58127# Wenn nCount == 0, dann steht die einzige Seitenzahl schon im aNumStr!
+ if(nCount)
+ aNumStr += SvxNumberType( ((SwPageDesc*)rDescs[i-1])->
+ GetNumType() ).GetNumStr( nBeg+nCount );
+ }
+ }
+ pNd->InsertText( aNumStr, aPos,
+ static_cast<IDocumentContentOperations::InsertFlags>(
+ IDocumentContentOperations::INS_EMPTYEXPAND |
+ IDocumentContentOperations::INS_FORCEHINTEXPAND) );
+ if(pPageNoCharFmt)
+ {
+ SwFmtCharFmt aCharFmt( pPageNoCharFmt );
+ pNd->InsertItem(aCharFmt, nStartPos, nStartPos + aNumStr.Len(), nsSetAttrMode::SETATTR_DONTEXPAND);
+ }
+
+ //now the main entries should get there character style
+ if(pCharStyleIdx && pCharStyleIdx->Count() && GetMainEntryCharStyle().Len())
+ {
+ // eventually the last index must me appended
+ if(pCharStyleIdx->Count()&0x01)
+ pCharStyleIdx->Insert(aNumStr.Len(), pCharStyleIdx->Count());
+
+ //search by name
+ SwDoc* pDoc = pNd->GetDoc();
+ sal_uInt16 nPoolId = SwStyleNameMapper::GetPoolIdFromUIName( GetMainEntryCharStyle(), nsSwGetPoolIdFromName::GET_POOLID_CHRFMT );
+ SwCharFmt* pCharFmt = 0;
+ if(USHRT_MAX != nPoolId)
+ pCharFmt = pDoc->GetCharFmtFromPool(nPoolId);
+ else
+ pCharFmt = pDoc->FindCharFmtByName( GetMainEntryCharStyle() );
+ if(!pCharFmt)
+ pCharFmt = pDoc->MakeCharFmt(GetMainEntryCharStyle(), 0);
+
+ //find the page numbers in aNumStr and set the character style
+ xub_StrLen nOffset = pNd->GetTxt().Len() - aNumStr.Len();
+ SwFmtCharFmt aCharFmt(pCharFmt);
+ for(sal_uInt16 j = 0; j < pCharStyleIdx->Count(); j += 2)
+ {
+ xub_StrLen nStartIdx = (*pCharStyleIdx)[j] + nOffset;
+ xub_StrLen nEndIdx = (*pCharStyleIdx)[j + 1] + nOffset;
+ pNd->InsertItem(aCharFmt, nStartIdx, nEndIdx, nsSetAttrMode::SETATTR_DONTEXPAND);
+ }
+
+ }
+ delete pCharStyleIdx;
+}
+
+/*--------------------------------------------------------------------
+ Beschreibung: Sortiert einfuegen in das SortArr
+ --------------------------------------------------------------------*/
+void SwTOXBaseSection::InsertSorted(SwTOXSortTabBase* pNew)
+{
+ Range aRange(0, aSortArr.Count());
+ if( TOX_INDEX == SwTOXBase::GetType() && pNew->pTxtMark )
+ {
+ const SwTOXMark& rMark = pNew->pTxtMark->GetTOXMark();
+ // Schluessel auswerten
+ // Den Bereich ermitteln, in dem einzufuegen ist
+ if( 0 == (GetOptions() & nsSwTOIOptions::TOI_KEY_AS_ENTRY) &&
+ rMark.GetPrimaryKey().Len() )
+ {
+ aRange = GetKeyRange( rMark.GetPrimaryKey(),
+ rMark.GetPrimaryKeyReading(),
+ *pNew, FORM_PRIMARY_KEY, aRange );
+
+ if( rMark.GetSecondaryKey().Len() )
+ aRange = GetKeyRange( rMark.GetSecondaryKey(),
+ rMark.GetSecondaryKeyReading(),
+ *pNew, FORM_SECONDARY_KEY, aRange );
+ }
+ }
+ //search for identical entries and remove the trailing one
+ if(TOX_AUTHORITIES == SwTOXBase::GetType())
+ {
+ for(short i = (short)aRange.Min(); i < (short)aRange.Max(); ++i)
+ {
+ SwTOXSortTabBase* pOld = aSortArr[i];
+ if(*pOld == *pNew)
+ {
+ if(*pOld < *pNew)
+ {
+ delete pNew;
+ return;
+ }
+ else
+ {
+ // remove the old content
+ aSortArr.DeleteAndDestroy( i, 1 );
+ aRange.Max()--;
+ break;
+ }
+ }
+ }
+ }
+
+ // find position and insert
+ //
+ short i;
+
+ for( i = (short)aRange.Min(); i < (short)aRange.Max(); ++i)
+ { // nur auf gleicher Ebene pruefen
+ //
+ SwTOXSortTabBase* pOld = aSortArr[i];
+ if(*pOld == *pNew)
+ {
+ if(TOX_AUTHORITIES != SwTOXBase::GetType())
+ {
+ // Eigener Eintrag fuer Doppelte oder Keywords
+ //
+ if( pOld->GetType() == TOX_SORT_CUSTOM &&
+ pNew->GetOptions() & nsSwTOIOptions::TOI_KEY_AS_ENTRY)
+ continue;
+
+ if(!(pNew->GetOptions() & nsSwTOIOptions::TOI_SAME_ENTRY))
+ { // Eigener Eintrag
+ aSortArr.Insert(pNew, i );
+ return;
+ }
+ // Eintrag schon vorhanden in Referenzliste aufnehmen
+ pOld->aTOXSources.Insert( pNew->aTOXSources[0],
+ pOld->aTOXSources.Count() );
+
+ delete pNew;
+ return;
+ }
+#if OSL_DEBUG_LEVEL > 1
+ else
+ OSL_FAIL("Bibliography entries cannot be found here");
+#endif
+ }
+ if(*pNew < *pOld)
+ break;
+ }
+ // SubLevel Skippen
+ while( TOX_INDEX == SwTOXBase::GetType() && i < aRange.Max() &&
+ aSortArr[i]->GetLevel() > pNew->GetLevel() )
+ i++;
+
+ // An Position i wird eingefuegt
+ aSortArr.Insert(pNew, i );
+}
+
+/*--------------------------------------------------------------------
+ Beschreibung: Schluessel-Bereich suchen und evtl einfuegen
+ --------------------------------------------------------------------*/
+Range SwTOXBaseSection::GetKeyRange(const String& rStr, const String& rStrReading,
+ const SwTOXSortTabBase& rNew,
+ sal_uInt16 nLevel, const Range& rRange )
+{
+ const SwTOXInternational& rIntl = *rNew.pTOXIntl;
+ String sToCompare(rStr);
+ String sToCompareReading(rStrReading);
+
+ if( 0 != (nsSwTOIOptions::TOI_INITIAL_CAPS & GetOptions()) )
+ {
+ String sUpper( rIntl.ToUpper( sToCompare, 0 ));
+ sToCompare.Erase( 0, 1 ).Insert( sUpper, 0 );
+ }
+
+ OSL_ENSURE(rRange.Min() >= 0 && rRange.Max() >= 0, "Min Max < 0");
+
+ const sal_uInt16 nMin = (sal_uInt16)rRange.Min();
+ const sal_uInt16 nMax = (sal_uInt16)rRange.Max();
+
+ sal_uInt16 i;
+
+ for( i = nMin; i < nMax; ++i)
+ {
+ SwTOXSortTabBase* pBase = aSortArr[i];
+
+ String sMyString, sMyStringReading;
+ pBase->GetTxt( sMyString, sMyStringReading );
+
+ if( rIntl.IsEqual( sMyString, sMyStringReading, pBase->GetLocale(),
+ sToCompare, sToCompareReading, rNew.GetLocale() ) &&
+ pBase->GetLevel() == nLevel )
+ break;
+ }
+ if(i == nMax)
+ { // Falls nicht vorhanden erzeugen und einfuegen
+ //
+ SwTOXCustom* pKey = new SwTOXCustom( sToCompare, sToCompareReading, nLevel, rIntl,
+ rNew.GetLocale() );
+ for(i = nMin; i < nMax; ++i)
+ {
+ if(nLevel == aSortArr[i]->GetLevel() && *pKey < *(aSortArr[i]))
+ break;
+ }
+ aSortArr.Insert(pKey, i );
+ }
+ sal_uInt16 nStart = i+1;
+ sal_uInt16 nEnd = aSortArr.Count();
+
+ // Ende des Bereiches suchen
+ for(i = nStart; i < aSortArr.Count(); ++i)
+ {
+ if(aSortArr[i]->GetLevel() <= nLevel)
+ { nEnd = i;
+ break;
+ }
+ }
+ return Range(nStart, nEnd);
+}
+
+sal_Bool SwTOXBase::IsTOXBaseInReadonly() const
+{
+ const SwTOXBaseSection *pSect = PTR_CAST(SwTOXBaseSection, this);
+ sal_Bool bRet = sal_False;
+ const SwSectionNode* pSectNode;
+ if(pSect && pSect->GetFmt() &&
+ 0 != (pSectNode = pSect->GetFmt()->GetSectionNode()))
+ {
+ const SwDocShell* pDocSh;
+ bRet = (0 != (pDocSh = pSectNode->GetDoc()->GetDocShell()) &&
+ pDocSh->IsReadOnly()) ||
+ (0 != (pSectNode = pSectNode->StartOfSectionNode()->FindSectionNode())&&
+ pSectNode->GetSection().IsProtectFlag());
+
+ }
+ return bRet;
+}
+
+const SfxItemSet* SwTOXBase::GetAttrSet() const
+{
+ const SwTOXBaseSection *pSect = PTR_CAST(SwTOXBaseSection, this);
+ if(pSect && pSect->GetFmt())
+ return &pSect->GetFmt()->GetAttrSet();
+ return 0;
+}
+
+void SwTOXBase::SetAttrSet( const SfxItemSet& rSet )
+{
+ SwTOXBaseSection *pSect = PTR_CAST(SwTOXBaseSection, this);
+ if( pSect && pSect->GetFmt() )
+ pSect->GetFmt()->SetFmtAttr( rSet );
+}
+
+sal_Bool SwTOXBase::GetInfo( SfxPoolItem& rInfo ) const
+{
+ switch( rInfo.Which() )
+ {
+ case RES_CONTENT_VISIBLE:
+ {
+ SwTOXBaseSection *pSect = PTR_CAST(SwTOXBaseSection, this);
+ if( pSect && pSect->GetFmt() )
+ pSect->GetFmt()->GetInfo( rInfo );
+ }
+ return sal_False;
+ }
+ return sal_True;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/doc/docxforms.cxx b/sw/source/core/doc/docxforms.cxx
new file mode 100644
index 000000000000..bf34f2a64699
--- /dev/null
+++ b/sw/source/core/doc/docxforms.cxx
@@ -0,0 +1,126 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+
+
+
+#include <doc.hxx>
+#include <docsh.hxx>
+#include <com/sun/star/uno/Reference.hxx>
+#include <com/sun/star/container/XNameContainer.hpp>
+#include <com/sun/star/lang/XMultiServiceFactory.hpp>
+#include <com/sun/star/frame/XModule.hpp>
+#include <com/sun/star/xforms/XModel.hpp>
+#include <com/sun/star/xforms/XFormsUIHelper1.hpp>
+#include <unotools/processfactory.hxx>
+#include <tools/diagnose_ex.h>
+
+
+using namespace ::com::sun::star;
+
+using uno::Reference;
+using uno::XInterface;
+using uno::UNO_QUERY;
+using uno::makeAny;
+using uno::Exception;
+using container::XNameContainer;
+using xforms::XModel;
+using frame::XModule;
+using xforms::XFormsUIHelper1;
+using rtl::OUString;
+
+
+Reference<XNameContainer> SwDoc::getXForms() const
+{
+ return xXForms;
+}
+
+bool SwDoc::isXForms() const
+{
+ return xXForms.is();
+}
+
+Reference<XInterface> lcl_createInstance( const sal_Char* pServiceName )
+{
+ DBG_ASSERT( pServiceName != NULL, "no service name" );
+ return utl::getProcessServiceFactory()->createInstance(
+ OUString::createFromAscii( pServiceName ) );
+}
+
+void SwDoc::initXForms( bool bCreateDefaultModel )
+{
+ DBG_ASSERT( ! isXForms(), "please initialize only once" );
+
+ try
+ {
+ // create XForms components
+ xXForms.set( lcl_createInstance( "com.sun.star.xforms.XForms" ),
+ UNO_QUERY );
+ DBG_ASSERT( xXForms.is(), "can't create XForms container" );
+
+ // change our module identifier, to be able to have a dedicated UI
+ Reference< XModule > xModule;
+ SwDocShell* pShell( GetDocShell() );
+ if ( pShell )
+ xModule = xModule.query( pShell->GetModel() );
+ DBG_ASSERT( xModule.is(), "SwDoc::initXForms: no XModule at the document!" );
+ if ( xModule.is() )
+ xModule->setIdentifier( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.xforms.XMLFormDocument" ) ) );
+
+ // create default model
+ if( bCreateDefaultModel && xXForms.is() )
+ {
+ OUString sName(RTL_CONSTASCII_USTRINGPARAM("Model 1"));
+ Reference<XModel> xModel(
+ lcl_createInstance( "com.sun.star.xforms.Model" ),
+ UNO_QUERY );
+ DBG_ASSERT( xModel.is(), "no model?" );
+ if( xModel.is() )
+ {
+ xModel->setID( sName );
+ Reference<XFormsUIHelper1>( xModel, UNO_QUERY )->newInstance(
+ OUString(RTL_CONSTASCII_USTRINGPARAM("Instance 1")),
+ OUString(), sal_True );
+ xModel->initialize();
+ xXForms->insertByName( sName, makeAny( xModel ) );
+ }
+ DBG_ASSERT( xXForms->hasElements(), "can't create XForms model" );
+ }
+
+ DBG_ASSERT( isXForms(), "initialization failed" );
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION();
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/doc/extinput.cxx b/sw/source/core/doc/extinput.cxx
new file mode 100644
index 000000000000..6ed12fd4cce5
--- /dev/null
+++ b/sw/source/core/doc/extinput.cxx
@@ -0,0 +1,302 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+#include <com/sun/star/i18n/ScriptType.hpp>
+
+#include <editeng/langitem.hxx>
+#include <editeng/scripttypeitem.hxx>
+
+#include <vcl/keycodes.hxx>
+#include <vcl/cmdevt.hxx>
+
+#include <hintids.hxx>
+#include <extinput.hxx>
+#include <doc.hxx>
+#include <IDocumentUndoRedo.hxx>
+#include <index.hxx>
+#include <ndtxt.hxx>
+#include <txtfrm.hxx>
+#include <swundo.hxx>
+
+
+using namespace ::com::sun::star;
+
+SwExtTextInput::SwExtTextInput( const SwPaM& rPam, Ring* pRing )
+ : SwPaM( *rPam.GetPoint(), (SwPaM*)pRing ),
+ eInputLanguage(LANGUAGE_DONTKNOW)
+{
+ bIsOverwriteCursor = sal_False;
+ bInsText = sal_True;
+}
+
+SwExtTextInput::~SwExtTextInput()
+{
+ SwDoc *const pDoc = GetDoc();
+ if (pDoc->IsInDtor()) { return; /* #i58606# */ }
+
+ SwTxtNode* pTNd = GetPoint()->nNode.GetNode().GetTxtNode();
+ if( pTNd )
+ {
+ SwIndex& rIdx = GetPoint()->nContent;
+ xub_StrLen nSttCnt = rIdx.GetIndex(),
+ nEndCnt = GetMark()->nContent.GetIndex();
+ if( nEndCnt != nSttCnt )
+ {
+ if( nEndCnt < nSttCnt )
+ {
+ xub_StrLen n = nEndCnt; nEndCnt = nSttCnt; nSttCnt = n;
+ }
+
+ // damit Undo / Redlining usw. richtig funktioniert,
+ // muss ueber die Doc-Schnittstellen gegangen werden !!!
+ if(eInputLanguage != LANGUAGE_DONTKNOW)
+ {
+ // --> FME 2005-02-11 #i41974# Only set language attribute
+ // for CJK/CTL scripts.
+ bool bLang = true;
+ // <--
+ sal_uInt16 nWhich = RES_CHRATR_LANGUAGE;
+ switch(GetI18NScriptTypeOfLanguage(eInputLanguage))
+ {
+ case i18n::ScriptType::ASIAN: nWhich = RES_CHRATR_CJK_LANGUAGE; break;
+ case i18n::ScriptType::COMPLEX: nWhich = RES_CHRATR_CTL_LANGUAGE; break;
+ default: bLang = false;
+ }
+ if ( bLang )
+ {
+ SvxLanguageItem aLangItem( eInputLanguage, nWhich );
+ pDoc->InsertPoolItem(*this, aLangItem, 0 );
+ }
+ }
+ rIdx = nSttCnt;
+ String sTxt( pTNd->GetTxt().Copy( nSttCnt, nEndCnt - nSttCnt ));
+ if( bIsOverwriteCursor && sOverwriteText.Len() )
+ {
+ xub_StrLen nLen = sTxt.Len();
+ if( nLen > sOverwriteText.Len() )
+ {
+ rIdx += sOverwriteText.Len();
+ pTNd->EraseText( rIdx, nLen - sOverwriteText.Len() );
+ rIdx = nSttCnt;
+ pTNd->ReplaceText( rIdx, sOverwriteText.Len(),
+ sOverwriteText );
+ if( bInsText )
+ {
+ rIdx = nSttCnt;
+ pDoc->GetIDocumentUndoRedo().StartUndo(
+ UNDO_OVERWRITE, NULL );
+ pDoc->Overwrite( *this, sTxt.Copy( 0,
+ sOverwriteText.Len() ));
+ pDoc->InsertString( *this,
+ sTxt.Copy( sOverwriteText.Len() ) );
+ pDoc->GetIDocumentUndoRedo().EndUndo(
+ UNDO_OVERWRITE, NULL );
+ }
+ }
+ else
+ {
+ pTNd->ReplaceText( rIdx, nLen,
+ sOverwriteText.Copy( 0, nLen ));
+ if( bInsText )
+ {
+ rIdx = nSttCnt;
+ pDoc->Overwrite( *this, sTxt );
+ }
+ }
+ }
+ else
+ {
+ pTNd->EraseText( rIdx, nEndCnt - nSttCnt );
+
+ if( bInsText )
+ {
+ pDoc->InsertString( *this, sTxt );
+ }
+ }
+ }
+ }
+}
+
+void SwExtTextInput::SetInputData( const CommandExtTextInputData& rData )
+{
+ SwTxtNode* pTNd = GetPoint()->nNode.GetNode().GetTxtNode();
+ if( pTNd )
+ {
+ xub_StrLen nSttCnt = GetPoint()->nContent.GetIndex(),
+ nEndCnt = GetMark()->nContent.GetIndex();
+ if( nEndCnt < nSttCnt )
+ {
+ xub_StrLen n = nEndCnt; nEndCnt = nSttCnt; nSttCnt = n;
+ }
+
+ SwIndex aIdx( pTNd, nSttCnt );
+ const String& rNewStr = rData.GetText();
+
+ if( bIsOverwriteCursor && sOverwriteText.Len() )
+ {
+ xub_StrLen nReplace = nEndCnt - nSttCnt;
+ if( rNewStr.Len() < nReplace )
+ {
+ // then we must insert from the saved original text
+ // some characters
+ nReplace = nReplace - rNewStr.Len();
+ aIdx += rNewStr.Len();
+ pTNd->ReplaceText( aIdx, nReplace,
+ sOverwriteText.Copy( rNewStr.Len(), nReplace ));
+ aIdx = nSttCnt;
+ nReplace = rNewStr.Len();
+ }
+ else if( sOverwriteText.Len() < nReplace )
+ {
+ nReplace = nReplace - sOverwriteText.Len();
+ aIdx += sOverwriteText.Len();
+ pTNd->EraseText( aIdx, nReplace );
+ aIdx = nSttCnt;
+ nReplace = sOverwriteText.Len();
+ }
+ else if( (nReplace = sOverwriteText.Len()) > rNewStr.Len() )
+ nReplace = rNewStr.Len();
+
+ pTNd->ReplaceText( aIdx, nReplace, rNewStr );
+ if( !HasMark() )
+ SetMark();
+ GetMark()->nContent = aIdx;
+ }
+ else
+ {
+ if( nSttCnt < nEndCnt )
+ {
+ pTNd->EraseText( aIdx, nEndCnt - nSttCnt );
+ }
+
+ pTNd->InsertText( rNewStr, aIdx,
+ IDocumentContentOperations::INS_EMPTYEXPAND );
+ if( !HasMark() )
+ SetMark();
+ }
+
+ GetPoint()->nContent = nSttCnt;
+
+ if( aAttrs.Count() )
+ aAttrs.Remove( 0, aAttrs.Count() );
+ if( rData.GetTextAttr() )
+ aAttrs.Insert( rData.GetTextAttr(), rData.GetText().Len(), 0 );
+ }
+}
+
+void SwExtTextInput::SetOverwriteCursor( sal_Bool bFlag )
+{
+ bIsOverwriteCursor = bFlag;
+
+ SwTxtNode* pTNd;
+ if( bIsOverwriteCursor &&
+ 0 != (pTNd = GetPoint()->nNode.GetNode().GetTxtNode()) )
+ {
+ xub_StrLen nSttCnt = GetPoint()->nContent.GetIndex(),
+ nEndCnt = GetMark()->nContent.GetIndex();
+ sOverwriteText = pTNd->GetTxt().Copy( nEndCnt < nSttCnt ? nEndCnt
+ : nSttCnt );
+ if( sOverwriteText.Len() )
+ {
+ xub_StrLen nInWrdAttrPos = sOverwriteText.Search( CH_TXTATR_INWORD ),
+ nWrdAttrPos = sOverwriteText.Search( CH_TXTATR_BREAKWORD );
+ if( nWrdAttrPos < nInWrdAttrPos )
+ nInWrdAttrPos = nWrdAttrPos;
+ if( STRING_NOTFOUND != nInWrdAttrPos )
+ sOverwriteText.Erase( nInWrdAttrPos );
+ }
+ }
+}
+
+// die Doc Schnittstellen:
+
+SwExtTextInput* SwDoc::CreateExtTextInput( const SwPaM& rPam )
+{
+ SwExtTextInput* pNew = new SwExtTextInput( rPam, pExtInputRing );
+ if( !pExtInputRing )
+ pExtInputRing = pNew;
+ pNew->SetMark();
+ return pNew;
+}
+
+void SwDoc::DeleteExtTextInput( SwExtTextInput* pDel )
+{
+ if( pDel == pExtInputRing )
+ {
+ if( pDel->GetNext() != pExtInputRing )
+ pExtInputRing = (SwPaM*)pDel->GetNext();
+ else
+ pExtInputRing = 0;
+ }
+ delete pDel;
+}
+
+SwExtTextInput* SwDoc::GetExtTextInput( const SwNode& rNd,
+ xub_StrLen nCntntPos ) const
+{
+ SwExtTextInput* pRet = 0;
+ if( pExtInputRing )
+ {
+ sal_uLong nNdIdx = rNd.GetIndex();
+ SwExtTextInput* pTmp = (SwExtTextInput*)pExtInputRing;
+ do {
+ sal_uLong nPt = pTmp->GetPoint()->nNode.GetIndex(),
+ nMk = pTmp->GetMark()->nNode.GetIndex();
+ xub_StrLen nPtCnt = pTmp->GetPoint()->nContent.GetIndex(),
+ nMkCnt = pTmp->GetMark()->nContent.GetIndex();
+
+ if( nPt < nMk || ( nPt == nMk && nPtCnt < nMkCnt ))
+ {
+ sal_uLong nTmp = nMk; nMk = nPt; nPt = nTmp;
+ nTmp = nMkCnt; nMkCnt = nPtCnt; nPtCnt = (xub_StrLen)nTmp;
+ }
+
+ if( nMk <= nNdIdx && nNdIdx <= nPt &&
+ ( STRING_NOTFOUND == nCntntPos ||
+ ( nMkCnt <= nCntntPos && nCntntPos <= nPtCnt )))
+ {
+ pRet = pTmp;
+ break;
+ }
+ } while( pExtInputRing != (pTmp = (SwExtTextInput*)pExtInputRing ) );
+ }
+ return pRet;
+}
+
+SwExtTextInput* SwDoc::GetExtTextInput() const
+{
+ OSL_ENSURE( !pExtInputRing || pExtInputRing == pExtInputRing->GetNext(),
+ "more then one InputEngine available" );
+ return (SwExtTextInput*)pExtInputRing;
+}
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/doc/fmtcol.cxx b/sw/source/core/doc/fmtcol.cxx
new file mode 100644
index 000000000000..be40cb0fb67f
--- /dev/null
+++ b/sw/source/core/doc/fmtcol.cxx
@@ -0,0 +1,709 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+#include <sal/macros.h>
+#include <hintids.hxx>
+#include <editeng/ulspitem.hxx>
+#include <editeng/lrspitem.hxx>
+#include <editeng/fhgtitem.hxx>
+#include <doc.hxx> // fuer GetAttrPool
+#include <fmtcol.hxx>
+#include <fmtcolfunc.hxx>
+#include <hints.hxx>
+#include <calc.hxx>
+#include <node.hxx>
+#include <numrule.hxx>
+#include <paratr.hxx>
+#include <switerator.hxx>
+#include <svl/intitem.hxx>
+
+TYPEINIT1( SwTxtFmtColl, SwFmtColl );
+TYPEINIT1( SwGrfFmtColl, SwFmtColl );
+TYPEINIT1( SwConditionTxtFmtColl, SwTxtFmtColl );
+TYPEINIT1( SwCollCondition, SwClient );
+
+SV_IMPL_PTRARR( SwFmtCollConditions, SwCollConditionPtr );
+
+namespace TxtFmtCollFunc
+{
+
+ // #i71574#
+ void CheckTxtFmtCollForDeletionOfAssignmentToOutlineStyle(
+ SwFmt* pFmt,
+ const SwNumRuleItem* pNewNumRuleItem )
+ {
+ SwTxtFmtColl* pTxtFmtColl = dynamic_cast<SwTxtFmtColl*>(pFmt);
+ if ( !pTxtFmtColl )
+ {
+ #if OSL_DEBUG_LEVEL > 1
+ OSL_FAIL( "<TxtFmtCollFunc::CheckTxtFmtCollFuncForDeletionOfAssignmentToOutlineStyle> - misuse of method - it's only for instances of <SwTxtFmtColl>" );
+ #endif
+ return;
+ }
+
+ // #i73790#
+ if ( !pTxtFmtColl->StayAssignedToListLevelOfOutlineStyle() &&
+ pTxtFmtColl->IsAssignedToListLevelOfOutlineStyle() )
+ // <--
+ {
+ if ( !pNewNumRuleItem )
+ {
+ pTxtFmtColl->GetItemState( RES_PARATR_NUMRULE, sal_False, (const SfxPoolItem**)&pNewNumRuleItem );
+ }
+ if ( pNewNumRuleItem )
+ {
+ String sNumRuleName = pNewNumRuleItem->GetValue();
+ if ( sNumRuleName.Len() == 0 ||
+ sNumRuleName != pTxtFmtColl->GetDoc()->GetOutlineNumRule()->GetName() )
+ {
+ // delete assignment of paragraph style to list level of outline style.
+ pTxtFmtColl->DeleteAssignmentToListLevelOfOutlineStyle();
+ }
+ }
+ }
+ }
+ // <--
+
+ SwNumRule* GetNumRule( SwTxtFmtColl& rTxtFmtColl )
+ {
+ SwNumRule* pNumRule( 0 );
+
+ const SwNumRuleItem* pNumRuleItem( 0 );
+ rTxtFmtColl.GetItemState( RES_PARATR_NUMRULE, sal_False, (const SfxPoolItem**)&pNumRuleItem );
+ if ( pNumRuleItem )
+ {
+ const String sNumRuleName = pNumRuleItem->GetValue();
+ if ( sNumRuleName.Len() > 0 )
+ {
+ pNumRule = rTxtFmtColl.GetDoc()->FindNumRulePtr( sNumRuleName );
+ }
+ }
+
+ return pNumRule;
+ }
+
+ void AddToNumRule( SwTxtFmtColl& rTxtFmtColl )
+ {
+ SwNumRule* pNumRule = GetNumRule( rTxtFmtColl );
+ if ( pNumRule )
+ {
+ pNumRule->AddParagraphStyle( rTxtFmtColl );
+ }
+ }
+
+ void RemoveFromNumRule( SwTxtFmtColl& rTxtFmtColl )
+ {
+ SwNumRule* pNumRule = GetNumRule( rTxtFmtColl );
+ if ( pNumRule )
+ {
+ pNumRule->RemoveParagraphStyle( rTxtFmtColl );
+ }
+ }
+} // end of namespace TxtFmtCollFunc
+// <--
+
+/*
+ * SwTxtFmtColl TXT
+ */
+
+void SwTxtFmtColl::Modify( const SfxPoolItem* pOld, const SfxPoolItem* pNew )
+{
+ if( GetDoc()->IsInDtor() )
+ {
+ SwFmtColl::Modify( pOld, pNew );
+ return;
+ }
+
+ bool bNewParent( false ); // #i66431# - adjust type of <bNewParent>
+ SvxULSpaceItem *pNewULSpace = 0, *pOldULSpace = 0;
+ SvxLRSpaceItem *pNewLRSpace = 0, *pOldLRSpace = 0;
+ SvxFontHeightItem* aFontSizeArr[3] = {0,0,0};
+ // #i70223#
+ const bool bAssignedToListLevelOfOutlineStyle(IsAssignedToListLevelOfOutlineStyle());//#outline level ,zhaojianwei
+ const SwNumRuleItem* pNewNumRuleItem( 0L );
+
+ SwAttrSetChg *pNewChgSet = 0, *pOldChgSet = 0;
+
+ switch( pOld ? pOld->Which() : pNew ? pNew->Which() : 0 )
+ {
+ case RES_ATTRSET_CHG:
+ // nur neu berechnen, wenn nicht wir der "Versender" sind !!!
+ pNewChgSet = (SwAttrSetChg*)pNew;
+ pOldChgSet = (SwAttrSetChg*)pOld;
+ pNewChgSet->GetChgSet()->GetItemState(
+ RES_LR_SPACE, sal_False, (const SfxPoolItem**)&pNewLRSpace );
+ pNewChgSet->GetChgSet()->GetItemState(
+ RES_UL_SPACE, sal_False, (const SfxPoolItem**)&pNewULSpace );
+ pNewChgSet->GetChgSet()->GetItemState( RES_CHRATR_FONTSIZE,
+ sal_False, (const SfxPoolItem**)&(aFontSizeArr[0]) );
+ pNewChgSet->GetChgSet()->GetItemState( RES_CHRATR_CJK_FONTSIZE,
+ sal_False, (const SfxPoolItem**)&(aFontSizeArr[1]) );
+ pNewChgSet->GetChgSet()->GetItemState( RES_CHRATR_CTL_FONTSIZE,
+ sal_False, (const SfxPoolItem**)&(aFontSizeArr[2]) );
+ // #i70223#, #i84745#
+ // check, if attribute set is applied to this paragraph style
+ if ( bAssignedToListLevelOfOutlineStyle &&
+ pNewChgSet->GetTheChgdSet() == &GetAttrSet() )
+ {
+ pNewChgSet->GetChgSet()->GetItemState( RES_PARATR_NUMRULE, sal_False,
+ (const SfxPoolItem**)&pNewNumRuleItem );
+ }
+ // <--
+
+ break;
+
+ case RES_FMT_CHG:
+ if( GetAttrSet().GetParent() )
+ {
+ const SfxItemSet* pParent = GetAttrSet().GetParent();
+ pNewLRSpace = (SvxLRSpaceItem*)&pParent->Get( RES_LR_SPACE );
+ pNewULSpace = (SvxULSpaceItem*)&pParent->Get( RES_UL_SPACE );
+ aFontSizeArr[0] = (SvxFontHeightItem*)&pParent->Get( RES_CHRATR_FONTSIZE );
+ aFontSizeArr[1] = (SvxFontHeightItem*)&pParent->Get( RES_CHRATR_CJK_FONTSIZE );
+ aFontSizeArr[2] = (SvxFontHeightItem*)&pParent->Get( RES_CHRATR_CTL_FONTSIZE );
+ // #i66431# - modify has to be propagated, because of new parent format.
+ bNewParent = true;
+ }
+ break;
+
+ case RES_LR_SPACE:
+ pNewLRSpace = (SvxLRSpaceItem*)pNew;
+ break;
+ case RES_UL_SPACE:
+ pNewULSpace = (SvxULSpaceItem*)pNew;
+ break;
+ case RES_CHRATR_FONTSIZE:
+ aFontSizeArr[0] = (SvxFontHeightItem*)pNew;
+ break;
+ case RES_CHRATR_CJK_FONTSIZE:
+ aFontSizeArr[1] = (SvxFontHeightItem*)pNew;
+ break;
+ case RES_CHRATR_CTL_FONTSIZE:
+ aFontSizeArr[2] = (SvxFontHeightItem*)pNew;
+ break;
+ // #i70223#
+ case RES_PARATR_NUMRULE:
+ {
+ if ( bAssignedToListLevelOfOutlineStyle )
+ {
+ pNewNumRuleItem = (SwNumRuleItem*)pNew;
+ }
+ }
+ default:
+ break;
+ }
+
+ // #i70223#
+ if ( bAssignedToListLevelOfOutlineStyle && pNewNumRuleItem )
+ {
+ TxtFmtCollFunc::CheckTxtFmtCollForDeletionOfAssignmentToOutlineStyle(
+ this, pNewNumRuleItem );
+ }
+ // <--
+
+ int bWeiter = sal_True;
+
+ // dann pruefe doch mal gegen die eigenen Attribute
+ if( pNewLRSpace && SFX_ITEM_SET == GetItemState( RES_LR_SPACE, sal_False,
+ (const SfxPoolItem**)&pOldLRSpace ))
+ {
+ int bChg = sal_False;
+ if( pOldLRSpace != pNewLRSpace ) // verhinder Rekursion (SetAttr!!)
+ {
+ SvxLRSpaceItem aNew( *pOldLRSpace );
+ // wir hatten eine relative Angabe -> neu berechnen
+ if( 100 != aNew.GetPropLeft() )
+ {
+ long nTmp = aNew.GetLeft(); // alten zum Vergleichen
+ aNew.SetLeft( pNewLRSpace->GetLeft(), aNew.GetPropLeft() );
+ bChg |= nTmp != aNew.GetLeft();
+ }
+ // wir hatten eine relative Angabe -> neu berechnen
+ if( 100 != aNew.GetPropRight() )
+ {
+ long nTmp = aNew.GetRight(); // alten zum Vergleichen
+ aNew.SetRight( pNewLRSpace->GetRight(), aNew.GetPropRight() );
+ bChg |= nTmp != aNew.GetRight();
+ }
+ // wir hatten eine relative Angabe -> neu berechnen
+ if( 100 != aNew.GetPropTxtFirstLineOfst() )
+ {
+ short nTmp = aNew.GetTxtFirstLineOfst(); // alten zum Vergleichen
+ aNew.SetTxtFirstLineOfst( pNewLRSpace->GetTxtFirstLineOfst(),
+ aNew.GetPropTxtFirstLineOfst() );
+ bChg |= nTmp != aNew.GetTxtFirstLineOfst();
+ }
+ if( bChg )
+ {
+ SetFmtAttr( aNew );
+ bWeiter = 0 != pOldChgSet || bNewParent;
+ }
+ // bei uns absolut gesetzt -> nicht weiter propagieren, es sei
+ // denn es wird bei uns gesetzt!
+ else if( pNewChgSet )
+ bWeiter = pNewChgSet->GetTheChgdSet() == &GetAttrSet();
+ }
+ }
+
+ if( pNewULSpace && SFX_ITEM_SET == GetItemState(
+ RES_UL_SPACE, sal_False, (const SfxPoolItem**)&pOldULSpace ) &&
+ pOldULSpace != pNewULSpace ) // verhinder Rekursion (SetAttr!!)
+ {
+ SvxULSpaceItem aNew( *pOldULSpace );
+ int bChg = sal_False;
+ // wir hatten eine relative Angabe -> neu berechnen
+ if( 100 != aNew.GetPropUpper() )
+ {
+ sal_uInt16 nTmp = aNew.GetUpper(); // alten zum Vergleichen
+ aNew.SetUpper( pNewULSpace->GetUpper(), aNew.GetPropUpper() );
+ bChg |= nTmp != aNew.GetUpper();
+ }
+ // wir hatten eine relative Angabe -> neu berechnen
+ if( 100 != aNew.GetPropLower() )
+ {
+ sal_uInt16 nTmp = aNew.GetLower(); // alten zum Vergleichen
+ aNew.SetLower( pNewULSpace->GetLower(), aNew.GetPropLower() );
+ bChg |= nTmp != aNew.GetLower();
+ }
+ if( bChg )
+ {
+ SetFmtAttr( aNew );
+ bWeiter = 0 != pOldChgSet || bNewParent;
+ }
+ // bei uns absolut gesetzt -> nicht weiter propagieren, es sei
+ // denn es wird bei uns gesetzt!
+ else if( pNewChgSet )
+ bWeiter = pNewChgSet->GetTheChgdSet() == &GetAttrSet();
+ }
+
+
+ for( int nC = 0, nArrLen = SAL_N_ELEMENTS(aFontSizeArr);
+ nC < nArrLen; ++nC )
+ {
+ SvxFontHeightItem *pFSize = aFontSizeArr[ nC ], *pOldFSize;
+ if( pFSize && SFX_ITEM_SET == GetItemState(
+ pFSize->Which(), sal_False, (const SfxPoolItem**)&pOldFSize ) &&
+ // verhinder Rekursion (SetAttr!!)
+ pFSize != pOldFSize )
+ {
+ if( 100 == pOldFSize->GetProp() &&
+ SFX_MAPUNIT_RELATIVE == pOldFSize->GetPropUnit() )
+ {
+ // bei uns absolut gesetzt -> nicht weiter propagieren, es sei
+ // denn es wird bei uns gesetzt!
+ if( pNewChgSet )
+ bWeiter = pNewChgSet->GetTheChgdSet() == &GetAttrSet();
+ }
+ else
+ {
+ // wir hatten eine relative Angabe -> neu berechnen
+ sal_uInt32 nTmp = pOldFSize->GetHeight(); // alten zum Vergleichen
+ SvxFontHeightItem aNew(240 , 100, pFSize->Which());
+ aNew.SetHeight( pFSize->GetHeight(), pOldFSize->GetProp(),
+ pOldFSize->GetPropUnit() );
+ if( nTmp != aNew.GetHeight() )
+ {
+ SetFmtAttr( aNew );
+ bWeiter = 0 != pOldChgSet || bNewParent;
+ }
+ // bei uns absolut gesetzt -> nicht weiter propagieren, es sei
+ // denn es wird bei uns gesetzt!
+ else if( pNewChgSet )
+ bWeiter = pNewChgSet->GetTheChgdSet() == &GetAttrSet();
+ }
+ }
+ }
+
+ if( bWeiter )
+ SwFmtColl::Modify( pOld, pNew );
+}
+
+sal_Bool SwTxtFmtColl::IsAtDocNodeSet() const
+{
+ SwIterator<SwCntntNode,SwFmtColl> aIter( *this );
+ const SwNodes& rNds = GetDoc()->GetNodes();
+ for( SwCntntNode* pNode = aIter.First(); pNode; pNode = aIter.Next() )
+ if( &(pNode->GetNodes()) == &rNds )
+ return sal_True;
+
+ return sal_False;
+}
+
+sal_Bool SwTxtFmtColl::SetFmtAttr( const SfxPoolItem& rAttr )
+{
+ const bool bIsNumRuleItem = rAttr.Which() == RES_PARATR_NUMRULE;
+ if ( bIsNumRuleItem )
+ {
+ TxtFmtCollFunc::RemoveFromNumRule( *this );
+ }
+
+ const sal_Bool bRet = SwFmtColl::SetFmtAttr( rAttr );
+
+ if ( bIsNumRuleItem )
+ {
+ TxtFmtCollFunc::AddToNumRule( *this );
+ }
+
+ return bRet;
+}
+
+sal_Bool SwTxtFmtColl::SetFmtAttr( const SfxItemSet& rSet )
+{
+ const bool bIsNumRuleItemAffected =
+ rSet.GetItemState( RES_PARATR_NUMRULE, sal_False ) == SFX_ITEM_SET;
+ if ( bIsNumRuleItemAffected )
+ {
+ TxtFmtCollFunc::RemoveFromNumRule( *this );
+ }
+
+ const sal_Bool bRet = SwFmtColl::SetFmtAttr( rSet );
+
+ if ( bIsNumRuleItemAffected )
+ {
+ TxtFmtCollFunc::AddToNumRule( *this );
+ }
+
+ return bRet;
+}
+
+sal_Bool SwTxtFmtColl::ResetFmtAttr( sal_uInt16 nWhich1, sal_uInt16 nWhich2 )
+{
+ const bool bIsNumRuleItemAffected =
+ ( nWhich2 != 0 && nWhich2 > nWhich1 )
+ ? ( nWhich1 <= RES_PARATR_NUMRULE &&
+ RES_PARATR_NUMRULE <= nWhich2 )
+ : nWhich1 == RES_PARATR_NUMRULE;
+ if ( bIsNumRuleItemAffected )
+ {
+ TxtFmtCollFunc::RemoveFromNumRule( *this );
+ }
+
+ const sal_Bool bRet = SwFmtColl::ResetFmtAttr( nWhich1, nWhich2 );
+
+ return bRet;
+}
+// <--
+
+// #i73790#
+sal_uInt16 SwTxtFmtColl::ResetAllFmtAttr()
+{
+ const bool bOldState( mbStayAssignedToListLevelOfOutlineStyle );
+ mbStayAssignedToListLevelOfOutlineStyle = true;
+ // #i70748#
+ // Outline level is no longer a member, it is a attribute now.
+ // Thus, it needs to be restored, if the paragraph style is assigned
+ // to the outline style
+ const int nAssignedOutlineStyleLevel = IsAssignedToListLevelOfOutlineStyle()
+ ? GetAssignedOutlineStyleLevel()
+ : -1;
+ // <--
+
+ sal_uInt16 nRet = SwFmtColl::ResetAllFmtAttr();
+
+ // #i70748#
+ if ( nAssignedOutlineStyleLevel != -1 )
+ {
+ AssignToListLevelOfOutlineStyle( nAssignedOutlineStyleLevel );
+ }
+ // <--
+
+ mbStayAssignedToListLevelOfOutlineStyle = bOldState;
+
+ return nRet;
+}
+// <--
+
+bool SwTxtFmtColl::AreListLevelIndentsApplicable() const
+{
+ bool bAreListLevelIndentsApplicable( true );
+
+ if ( GetItemState( RES_PARATR_NUMRULE ) != SFX_ITEM_SET )
+ {
+ // no list style applied to paragraph style
+ bAreListLevelIndentsApplicable = false;
+ }
+ else if ( GetItemState( RES_LR_SPACE, sal_False ) == SFX_ITEM_SET )
+ {
+ // paragraph style has hard-set indent attributes
+ bAreListLevelIndentsApplicable = false;
+ }
+ else if ( GetItemState( RES_PARATR_NUMRULE, sal_False ) == SFX_ITEM_SET )
+ {
+ // list style is directly applied to paragraph style and paragraph
+ // style has no hard-set indent attributes
+ bAreListLevelIndentsApplicable = true;
+ }
+ else
+ {
+ // list style is applied through one of the parent paragraph styles and
+ // paragraph style has no hard-set indent attributes
+
+ // check parent paragraph styles
+ const SwTxtFmtColl* pColl = dynamic_cast<const SwTxtFmtColl*>(DerivedFrom());
+ while ( pColl )
+ {
+ if ( pColl->GetAttrSet().GetItemState( RES_LR_SPACE, sal_False ) == SFX_ITEM_SET )
+ {
+ // indent attributes found in the paragraph style hierarchy.
+ bAreListLevelIndentsApplicable = false;
+ break;
+ }
+
+ if ( pColl->GetAttrSet().GetItemState( RES_PARATR_NUMRULE, sal_False ) == SFX_ITEM_SET )
+ {
+ // paragraph style with the list style found and until now no
+ // indent attributes are found in the paragraph style hierarchy.
+ bAreListLevelIndentsApplicable = true;
+ break;
+ }
+
+ pColl = dynamic_cast<const SwTxtFmtColl*>(pColl->DerivedFrom());
+ OSL_ENSURE( pColl,
+ "<SwTxtFmtColl::AreListLevelIndentsApplicable()> - something wrong in paragraph style hierarchy. The applied list style is not found." );
+ }
+ }
+
+ return bAreListLevelIndentsApplicable;
+}
+// <--
+
+//FEATURE::CONDCOLL
+
+SwCollCondition::SwCollCondition( SwTxtFmtColl* pColl, sal_uLong nMasterCond,
+ sal_uLong nSubCond )
+ : SwClient( pColl ), nCondition( nMasterCond )
+{
+ aSubCondition.nSubCondition = nSubCond;
+}
+
+
+SwCollCondition::SwCollCondition( SwTxtFmtColl* pColl, sal_uLong nMasterCond,
+ const String& rSubExp )
+ : SwClient( pColl ), nCondition( nMasterCond )
+{
+ if( USRFLD_EXPRESSION & nCondition )
+ aSubCondition.pFldExpression = new String( rSubExp );
+ else
+ aSubCondition.nSubCondition = 0;
+}
+
+
+SwCollCondition::SwCollCondition( const SwCollCondition& rCopy )
+ : SwClient( (SwModify*)rCopy.GetRegisteredIn() ), nCondition( rCopy.nCondition )
+{
+ if( USRFLD_EXPRESSION & rCopy.nCondition )
+ aSubCondition.pFldExpression = new String( *rCopy.GetFldExpression() );
+ else
+ aSubCondition.nSubCondition = rCopy.aSubCondition.nSubCondition;
+}
+
+
+SwCollCondition::~SwCollCondition()
+{
+ if( USRFLD_EXPRESSION & nCondition )
+ delete aSubCondition.pFldExpression;
+}
+
+void SwCollCondition::RegisterToFormat( SwFmt& rFmt )
+{
+ rFmt.Add( this );
+}
+
+
+
+int SwCollCondition::operator==( const SwCollCondition& rCmp ) const
+{
+ int nRet = 0;
+ if( nCondition == rCmp.nCondition )
+ {
+ if( USRFLD_EXPRESSION & nCondition )
+ {
+ // in der SubCondition steht die Expression fuer das UserFeld
+ const String* pTmp = aSubCondition.pFldExpression;
+ if( !pTmp )
+ pTmp = rCmp.aSubCondition.pFldExpression;
+ if( pTmp )
+ {
+ SwTxtFmtColl* pColl = GetTxtFmtColl();
+ if( !pColl )
+ pColl = rCmp.GetTxtFmtColl();
+
+ if( pColl )
+ {
+ SwCalc aCalc( *pColl->GetDoc() );
+ nRet = 0 != aCalc.Calculate( *pTmp ).GetBool();
+ }
+ }
+ }
+ else if( aSubCondition.nSubCondition ==
+ rCmp.aSubCondition.nSubCondition )
+ nRet = 1;
+ }
+ return nRet;
+}
+
+
+void SwCollCondition::SetCondition( sal_uLong nCond, sal_uLong nSubCond )
+{
+ if( USRFLD_EXPRESSION & nCondition )
+ delete aSubCondition.pFldExpression;
+ nCondition = nCond;
+ aSubCondition.nSubCondition = nSubCond;
+}
+
+
+SwConditionTxtFmtColl::~SwConditionTxtFmtColl()
+{
+}
+
+const SwCollCondition* SwConditionTxtFmtColl::HasCondition(
+ const SwCollCondition& rCond ) const
+{
+ const SwCollCondition* pFnd = 0;
+ sal_uInt16 n;
+
+ for( n = 0; n < aCondColls.Count(); ++n )
+ if( *( pFnd = aCondColls[ n ]) == rCond )
+ break;
+
+ return n < aCondColls.Count() ? pFnd : 0;
+}
+
+
+void SwConditionTxtFmtColl::InsertCondition( const SwCollCondition& rCond )
+{
+ for( sal_uInt16 n = 0; n < aCondColls.Count(); ++n )
+ if( *aCondColls[ n ] == rCond )
+ {
+ aCondColls.DeleteAndDestroy( n );
+ break;
+ }
+
+ // nicht gefunden -> als einfuegen
+ SwCollCondition* pNew = new SwCollCondition( rCond );
+ aCondColls.Insert( pNew, aCondColls.Count() );
+}
+
+
+sal_Bool SwConditionTxtFmtColl::RemoveCondition( const SwCollCondition& rCond )
+{
+ sal_Bool bRet = sal_False;
+ for( sal_uInt16 n = 0; n < aCondColls.Count(); ++n )
+ if( *aCondColls[ n ] == rCond )
+ {
+ aCondColls.DeleteAndDestroy( n );
+ bRet = sal_True;
+ }
+
+ return bRet;
+}
+
+void SwConditionTxtFmtColl::SetConditions( const SwFmtCollConditions& rCndClls )
+{
+ // Kopiere noch die Bedingungen
+ // aber erst die alten loeschen!
+ if( aCondColls.Count() )
+ aCondColls.DeleteAndDestroy( 0, aCondColls.Count() );
+ SwDoc& rDoc = *GetDoc();
+ for( sal_uInt16 n = 0; n < rCndClls.Count(); ++n )
+ {
+ SwCollCondition* pFnd = rCndClls[ n ];
+ SwTxtFmtColl* pTmpColl = pFnd->GetTxtFmtColl()
+ ? rDoc.CopyTxtColl( *pFnd->GetTxtFmtColl() )
+ : 0;
+ SwCollCondition* pNew;
+ if( USRFLD_EXPRESSION & pFnd->GetCondition() )
+ pNew = new SwCollCondition( pTmpColl, pFnd->GetCondition(),
+ *pFnd->GetFldExpression() );
+ else
+ pNew = new SwCollCondition( pTmpColl, pFnd->GetCondition(),
+ pFnd->GetSubCondition() );
+ aCondColls.Insert( pNew, n );
+ }
+}
+//#outline level, zhaojianwei
+void SwTxtFmtColl::SetAttrOutlineLevel( int nLevel)
+{
+ OSL_ENSURE( 0 <= nLevel && nLevel <= MAXLEVEL ,"SwTxtFmtColl: Level Out Of Range" );
+ SetFmtAttr( SfxUInt16Item( RES_PARATR_OUTLINELEVEL,
+ static_cast<sal_uInt16>(nLevel) ) );
+}
+
+int SwTxtFmtColl::GetAttrOutlineLevel() const
+{
+ return ((const SfxUInt16Item &)GetFmtAttr(RES_PARATR_OUTLINELEVEL)).GetValue();
+}
+
+int SwTxtFmtColl::GetAssignedOutlineStyleLevel() const
+{
+ OSL_ENSURE( IsAssignedToListLevelOfOutlineStyle(),
+ "<SwTxtFmtColl::GetAssignedOutlineStyleLevel()> - misuse of method");
+ return GetAttrOutlineLevel() - 1;
+}
+
+void SwTxtFmtColl::AssignToListLevelOfOutlineStyle(const int nAssignedListLevel)
+{
+ mbAssignedToOutlineStyle = true;
+ SetAttrOutlineLevel(nAssignedListLevel+1);
+
+ // #i100277#
+ SwIterator<SwTxtFmtColl,SwFmtColl> aIter( *this );
+ SwTxtFmtColl* pDerivedTxtFmtColl = aIter.First();
+ while ( pDerivedTxtFmtColl != 0 )
+ {
+ if ( !pDerivedTxtFmtColl->IsAssignedToListLevelOfOutlineStyle() )
+ {
+ if ( pDerivedTxtFmtColl->GetItemState( RES_PARATR_NUMRULE, sal_False ) == SFX_ITEM_DEFAULT )
+ {
+ SwNumRuleItem aItem(aEmptyStr);
+ pDerivedTxtFmtColl->SetFmtAttr( aItem );
+ }
+ if ( pDerivedTxtFmtColl->GetItemState( RES_PARATR_OUTLINELEVEL, sal_False ) == SFX_ITEM_DEFAULT )
+ {
+ pDerivedTxtFmtColl->SetAttrOutlineLevel( 0 );
+ }
+ }
+
+ pDerivedTxtFmtColl = aIter.Next();
+ }
+ // <--
+}
+
+void SwTxtFmtColl::DeleteAssignmentToListLevelOfOutlineStyle()
+{
+ mbAssignedToOutlineStyle = false;
+ ResetFmtAttr(RES_PARATR_OUTLINELEVEL);
+}
+//<-end,zhaojianwei
+
+//FEATURE::CONDCOLL
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/doc/ftnidx.cxx b/sw/source/core/doc/ftnidx.cxx
new file mode 100644
index 000000000000..0304d41ddf3d
--- /dev/null
+++ b/sw/source/core/doc/ftnidx.cxx
@@ -0,0 +1,401 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+
+#include <txtftn.hxx>
+#include <fmtftn.hxx>
+#include <ftninfo.hxx>
+#include <doc.hxx>
+#include <ftnidx.hxx>
+#include <ndtxt.hxx>
+#include <ndindex.hxx>
+#include <section.hxx>
+#include <fmtftntx.hxx>
+#include <rootfrm.hxx>
+
+
+_SV_IMPL_SORTAR_ALG( _SwFtnIdxs, SwTxtFtnPtr )
+sal_Bool _SwFtnIdxs::Seek_Entry( const SwTxtFtnPtr rSrch, sal_uInt16* pFndPos ) const
+{
+ sal_uLong nIdx = _SwTxtFtn_GetIndex( rSrch );
+ xub_StrLen nCntIdx = *rSrch->GetStart();
+
+ sal_uInt16 nO = Count(), nM, nU = 0;
+ if( nO > 0 )
+ {
+ nO--;
+ while( nU <= nO )
+ {
+ nM = nU + ( nO - nU ) / 2;
+ sal_uLong nFndIdx = _SwTxtFtn_GetIndex( (*this)[ nM ] );
+ if( nFndIdx == nIdx && *(*this)[ nM ]->GetStart() == nCntIdx )
+ {
+ if( pFndPos )
+ *pFndPos = nM;
+ return sal_True;
+ }
+ else if( nFndIdx < nIdx ||
+ (nFndIdx == nIdx && *(*this)[ nM ]->GetStart() < nCntIdx ))
+ nU = nM + 1;
+ else if( nM == 0 )
+ {
+ if( pFndPos )
+ *pFndPos = nU;
+ return sal_False;
+ }
+ else
+ nO = nM - 1;
+ }
+ }
+ if( pFndPos )
+ *pFndPos = nU;
+ return sal_False;
+}
+
+
+void SwFtnIdxs::UpdateFtn( const SwNodeIndex& rStt )
+{
+ if( !Count() )
+ return;
+
+ // besorge erstmal das Nodes-Array ueber den StartIndex der ersten Fussnote
+ SwDoc* pDoc = rStt.GetNode().GetDoc();
+ if( pDoc->IsInReading() )
+ return ;
+ SwTxtFtn* pTxtFtn;
+
+ const SwEndNoteInfo& rEndInfo = pDoc->GetEndNoteInfo();
+ const SwFtnInfo& rFtnInfo = pDoc->GetFtnInfo();
+
+ //Fuer normale Fussnoten werden Chapter- und Dokumentweise Nummerierung
+ //getrennt behandelt. Fuer Endnoten gibt es nur die Dokumentweise
+ //Nummerierung.
+ if( FTNNUM_CHAPTER == rFtnInfo.eNum )
+ {
+ const SwOutlineNodes& rOutlNds = pDoc->GetNodes().GetOutLineNds();
+ const SwNode* pCapStt = &pDoc->GetNodes().GetEndOfExtras();
+ sal_uLong nCapEnd = pDoc->GetNodes().GetEndOfContent().GetIndex();
+ if( rOutlNds.Count() )
+ {
+ // suche den Start des Kapitels, in den rStt steht.
+ sal_uInt16 n;
+
+ for( n = 0; n < rOutlNds.Count(); ++n )
+ if( rOutlNds[ n ]->GetIndex() > rStt.GetIndex() )
+ break; // gefunden
+ //else if( !rOutlNds[ n ]->GetTxtNode()->GetTxtColl()->GetOutlineLevel() ) //#outline level,zhaojianwei
+ else if ( rOutlNds[ n ]->GetTxtNode()->GetAttrOutlineLevel() == 1 ) //<-end,zhaojianwei
+ pCapStt = rOutlNds[ n ]; // Start eines neuen Kapitels
+ // dann suche jetzt noch das Ende vom Bereich
+ for( ; n < rOutlNds.Count(); ++n )
+ //if( !rOutlNds[ n ]->GetTxtNode()->GetTxtColl()->GetOutlineLevel() )//#outline level,zhaojianwei
+ if ( rOutlNds[ n ]->GetTxtNode()->GetAttrOutlineLevel() == 1 )//<-end,zhaojianwei
+ {
+ nCapEnd = rOutlNds[ n ]->GetIndex(); // Ende des gefundenen Kapitels
+ break;
+ }
+ }
+
+ sal_uInt16 nPos, nFtnNo = 1;
+ if( SeekEntry( *pCapStt, &nPos ) && nPos )
+ {
+ // gehe nach vorne bis der Index nicht mehr gleich ist
+ const SwNode* pCmpNd = &rStt.GetNode();
+ while( nPos && pCmpNd == &((*this)[ --nPos ]->GetTxtNode()) )
+ ;
+ ++nPos;
+ }
+
+ if( nPos == Count() ) // nichts gefunden
+ return;
+
+ if( !rOutlNds.Count() )
+ nFtnNo = nPos+1;
+
+ for( ; nPos < Count(); ++nPos )
+ {
+ pTxtFtn = (*this)[ nPos ];
+ if( pTxtFtn->GetTxtNode().GetIndex() >= nCapEnd )
+ break;
+
+ const SwFmtFtn &rFtn = pTxtFtn->GetFtn();
+ if( !rFtn.GetNumStr().Len() && !rFtn.IsEndNote() &&
+ !SwUpdFtnEndNtAtEnd::FindSectNdWithEndAttr( *pTxtFtn ))
+ pTxtFtn->SetNumber( rFtnInfo.nFtnOffset + nFtnNo++,
+ &rFtn.GetNumStr() );
+ }
+ }
+
+ SwUpdFtnEndNtAtEnd aNumArr;
+
+ // sal_Bool, damit hier auch bei Chapter-Einstellung die Endnoten
+ // durchlaufen.
+ const sal_Bool bEndNoteOnly = FTNNUM_DOC != rFtnInfo.eNum;
+
+ sal_uInt16 nPos, nFtnNo = 1, nEndNo = 1;
+ sal_uLong nUpdNdIdx = rStt.GetIndex();
+ for( nPos = 0; nPos < Count(); ++nPos )
+ {
+ pTxtFtn = (*this)[ nPos ];
+ if( nUpdNdIdx <= pTxtFtn->GetTxtNode().GetIndex() )
+ break;
+
+ const SwFmtFtn &rFtn = pTxtFtn->GetFtn();
+ if( !rFtn.GetNumStr().Len() )
+ {
+ if( !aNumArr.ChkNumber( *pTxtFtn ) )
+ {
+ if( pTxtFtn->GetFtn().IsEndNote() )
+ nEndNo++;
+ else
+ nFtnNo++;
+ }
+ }
+ }
+
+ // ab nPos bei allen FootNotes die Array-Nummer setzen
+ for( ; nPos < Count(); ++nPos )
+ {
+ pTxtFtn = (*this)[ nPos ];
+ const SwFmtFtn &rFtn = pTxtFtn->GetFtn();
+ if( !rFtn.GetNumStr().Len() )
+ {
+ sal_uInt16 nSectNo = aNumArr.ChkNumber( *pTxtFtn );
+ if( !nSectNo && ( rFtn.IsEndNote() || !bEndNoteOnly ))
+ nSectNo = rFtn.IsEndNote()
+ ? rEndInfo.nFtnOffset + nEndNo++
+ : rFtnInfo.nFtnOffset + nFtnNo++;
+
+ if( nSectNo )
+ {
+ if( rFtn.IsEndNote() )
+ pTxtFtn->SetNumber( nSectNo, &rFtn.GetNumStr() );
+ else
+ pTxtFtn->SetNumber( nSectNo, &rFtn.GetNumStr() );
+ }
+ }
+ }
+ // Pageweise wird vom MA erfuellt !!
+}
+
+
+void SwFtnIdxs::UpdateAllFtn()
+{
+ if( !Count() )
+ return;
+
+ // besorge erstmal das Nodes-Array ueber den StartIndex der
+ // ersten Fussnote
+ SwDoc* pDoc = (SwDoc*) (*this)[ 0 ]->GetTxtNode().GetDoc();
+ SwTxtFtn* pTxtFtn;
+ const SwEndNoteInfo& rEndInfo = pDoc->GetEndNoteInfo();
+ const SwFtnInfo& rFtnInfo = pDoc->GetFtnInfo();
+
+ SwUpdFtnEndNtAtEnd aNumArr;
+
+ SwRootFrm* pTmpRoot = pDoc->GetCurrentLayout();//swmod 080305
+ std::set<SwRootFrm*> aAllLayouts = pDoc->GetAllLayouts();
+ //Fuer normale Fussnoten werden Chapter- und Dokumentweise Nummerierung
+ //getrennt behandelt. Fuer Endnoten gibt es nur die Dokumentweise
+ //Nummerierung.
+ if( FTNNUM_CHAPTER == rFtnInfo.eNum )
+ {
+ const SwOutlineNodes& rOutlNds = pDoc->GetNodes().GetOutLineNds();
+ sal_uInt16 nNo = 1, // Nummer fuer die Fussnoten
+ nFtnIdx = 0; // Index in das FtnIdx-Array
+ for( sal_uInt16 n = 0; n < rOutlNds.Count(); ++n )
+ {
+ if ( rOutlNds[ n ]->GetTxtNode()->GetAttrOutlineLevel() == 1 )//<-end,zhaojianwei
+ {
+ sal_uLong nCapStt = rOutlNds[ n ]->GetIndex(); // Start eines neuen Kapitels
+ for( ; nFtnIdx < Count(); ++nFtnIdx )
+ {
+ pTxtFtn = (*this)[ nFtnIdx ];
+ if( pTxtFtn->GetTxtNode().GetIndex() >= nCapStt )
+ break;
+
+ // Endnoten nur Dokumentweise
+ const SwFmtFtn &rFtn = pTxtFtn->GetFtn();
+ if( !rFtn.IsEndNote() && !rFtn.GetNumStr().Len() &&
+ !SwUpdFtnEndNtAtEnd::FindSectNdWithEndAttr( *pTxtFtn ))
+ pTxtFtn->SetNumber( rFtnInfo.nFtnOffset + nNo++,
+ &rFtn.GetNumStr() );
+ }
+ if( nFtnIdx >= Count() )
+ break; // ok alles geupdatet
+ nNo = 1;
+ }
+ }
+
+ for( nNo = 1; nFtnIdx < Count(); ++nFtnIdx )
+ {
+ //Endnoten nur Dokumentweise
+ pTxtFtn = (*this)[ nFtnIdx ];
+ const SwFmtFtn &rFtn = pTxtFtn->GetFtn();
+ if( !rFtn.IsEndNote() && !rFtn.GetNumStr().Len() &&
+ !SwUpdFtnEndNtAtEnd::FindSectNdWithEndAttr( *pTxtFtn ))
+ pTxtFtn->SetNumber( rFtnInfo.nFtnOffset + nNo++,
+ &rFtn.GetNumStr() );
+ }
+
+ }
+
+ // sal_Bool, damit hier auch bei Chapter-Einstellung die Endnoten
+ // durchlaufen.
+ const sal_Bool bEndNoteOnly = FTNNUM_DOC != rFtnInfo.eNum;
+ sal_uInt16 nFtnNo = 0, nEndNo = 0;
+ for( sal_uInt16 nPos = 0; nPos < Count(); ++nPos )
+ {
+ pTxtFtn = (*this)[ nPos ];
+ const SwFmtFtn &rFtn = pTxtFtn->GetFtn();
+ if( !rFtn.GetNumStr().Len() )
+ {
+ sal_uInt16 nSectNo = aNumArr.ChkNumber( *pTxtFtn );
+ if( !nSectNo && ( rFtn.IsEndNote() || !bEndNoteOnly ))
+ nSectNo = rFtn.IsEndNote()
+ ? rEndInfo.nFtnOffset + (++nEndNo)
+ : rFtnInfo.nFtnOffset + (++nFtnNo);
+
+ if( nSectNo )
+ {
+ if( rFtn.IsEndNote() )
+ pTxtFtn->SetNumber( nSectNo, &rFtn.GetNumStr() );
+ else
+ pTxtFtn->SetNumber( nSectNo, &rFtn.GetNumStr() );
+ }
+ }
+ }
+
+ if( pTmpRoot && FTNNUM_PAGE == rFtnInfo.eNum )
+ std::for_each( aAllLayouts.begin(), aAllLayouts.end(),std::mem_fun(&SwRootFrm::UpdateFtnNums));//swmod 0
+}
+
+SwTxtFtn* SwFtnIdxs::SeekEntry( const SwNodeIndex& rPos, sal_uInt16* pFndPos ) const
+{
+ sal_uLong nIdx = rPos.GetIndex();
+
+ sal_uInt16 nO = Count(), nM, nU = 0;
+ if( nO > 0 )
+ {
+ nO--;
+ while( nU <= nO )
+ {
+ nM = nU + ( nO - nU ) / 2;
+ sal_uLong nNdIdx = _SwTxtFtn_GetIndex( (*this)[ nM ] );
+ if( nNdIdx == nIdx )
+ {
+ if( pFndPos )
+ *pFndPos = nM;
+ return (*this)[ nM ];
+ }
+ else if( nNdIdx < nIdx )
+ nU = nM + 1;
+ else if( nM == 0 )
+ {
+ if( pFndPos )
+ *pFndPos = nU;
+ return 0;
+ }
+ else
+ nO = nM - 1;
+ }
+ }
+ if( pFndPos )
+ *pFndPos = nU;
+ return 0;
+}
+
+/* */
+
+const SwSectionNode* SwUpdFtnEndNtAtEnd::FindSectNdWithEndAttr(
+ const SwTxtFtn& rTxtFtn )
+{
+ sal_uInt16 nWh = static_cast<sal_uInt16>( rTxtFtn.GetFtn().IsEndNote() ?
+ RES_END_AT_TXTEND : RES_FTN_AT_TXTEND );
+ sal_uInt16 nVal;
+ const SwSectionNode* pNd = rTxtFtn.GetTxtNode().FindSectionNode();
+ while( pNd && FTNEND_ATTXTEND_OWNNUMSEQ != ( nVal =
+ ((const SwFmtFtnAtTxtEnd&)pNd->GetSection().GetFmt()->
+ GetFmtAttr( nWh, sal_True )).GetValue() ) &&
+ FTNEND_ATTXTEND_OWNNUMANDFMT != nVal )
+ pNd = pNd->StartOfSectionNode()->FindSectionNode();
+
+ return pNd;
+}
+
+sal_uInt16 SwUpdFtnEndNtAtEnd::GetNumber( const SwTxtFtn& rTxtFtn,
+ const SwSectionNode& rNd )
+{
+ sal_uInt16 nRet = 0, nWh;
+ SvPtrarr* pArr;
+ SvUShorts* pNum;
+ if( rTxtFtn.GetFtn().IsEndNote() )
+ {
+ pArr = &aEndSects;
+ pNum = &aEndNums;
+ nWh = RES_END_AT_TXTEND;
+ }
+ else
+ {
+ pArr = &aFtnSects;
+ pNum = &aFtnNums;
+ nWh = RES_FTN_AT_TXTEND;
+ }
+ void* pNd = (void*)&rNd;
+
+ for( sal_uInt16 n = pArr->Count(); n; )
+ if( pArr->GetObject( --n ) == pNd )
+ {
+ nRet = ++pNum->GetObject( n );
+ break;
+ }
+
+ if( !nRet )
+ {
+ pArr->Insert( pNd, pArr->Count() );
+ nRet = ((SwFmtFtnEndAtTxtEnd&)rNd.GetSection().GetFmt()->
+ GetFmtAttr( nWh )).GetOffset();
+ ++nRet;
+ pNum->Insert( nRet, pNum->Count() );
+ }
+ return nRet;
+}
+
+sal_uInt16 SwUpdFtnEndNtAtEnd::ChkNumber( const SwTxtFtn& rTxtFtn )
+{
+ const SwSectionNode* pSectNd = FindSectNdWithEndAttr( rTxtFtn );
+ return pSectNd ? GetNumber( rTxtFtn, *pSectNd ) : 0;
+}
+
+
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/doc/gctable.cxx b/sw/source/core/doc/gctable.cxx
new file mode 100644
index 000000000000..bcdf8e0921aa
--- /dev/null
+++ b/sw/source/core/doc/gctable.cxx
@@ -0,0 +1,454 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+
+#include <hintids.hxx>
+#include <editeng/boxitem.hxx>
+#include <tblrwcl.hxx>
+#include <swtblfmt.hxx>
+
+using namespace ::editeng;
+
+inline const SvxBorderLine* GetLineTB( const SvxBoxItem* pBox, sal_Bool bTop )
+{
+ return bTop ? pBox->GetTop() : pBox->GetBottom();
+}
+
+
+sal_Bool _SwGCBorder_BoxBrd::CheckLeftBorderOfFormat( const SwFrmFmt& rFmt )
+{
+ const SvxBorderLine* pBrd;
+ const SfxPoolItem* pItem;
+ if( SFX_ITEM_SET == rFmt.GetItemState( RES_BOX, sal_True, &pItem ) &&
+ 0 != ( pBrd = ((SvxBoxItem*)pItem)->GetLeft() ) )
+ {
+ if( *pBrdLn == *pBrd )
+ bAnyBorderFnd = sal_True;
+ return sal_True;
+ }
+ return sal_False;
+}
+
+
+
+sal_Bool lcl_GCBorder_ChkBoxBrd_L( const SwTableLine*& rpLine, void* pPara )
+{
+ const SwTableBox* pBox = rpLine->GetTabBoxes()[ 0 ];
+ return lcl_GCBorder_ChkBoxBrd_B( pBox, pPara );
+}
+
+sal_Bool lcl_GCBorder_ChkBoxBrd_B( const SwTableBox*& rpBox, void* pPara )
+{
+ sal_Bool bRet = sal_True;
+ if( rpBox->GetTabLines().Count() )
+ {
+ for( sal_uInt16 n = 0, nLines = rpBox->GetTabLines().Count();
+ n < nLines && bRet; ++n )
+ {
+ const SwTableLine* pLine = rpBox->GetTabLines()[ n ];
+ bRet = lcl_GCBorder_ChkBoxBrd_L( pLine, pPara );
+ }
+ }
+ else
+ {
+ _SwGCBorder_BoxBrd* pBPara = (_SwGCBorder_BoxBrd*)pPara;
+ bRet = pBPara->CheckLeftBorderOfFormat( *rpBox->GetFrmFmt() );
+ }
+ return bRet;
+}
+
+sal_Bool lcl_GCBorder_GetLastBox_L( const SwTableLine*& rpLine, void* pPara )
+{
+ const SwTableBoxes& rBoxes = rpLine->GetTabBoxes();
+ const SwTableBox* pBox = rBoxes[ rBoxes.Count()-1 ];
+ ::lcl_GCBorder_GetLastBox_B( pBox, pPara );
+ return sal_True;
+}
+
+sal_Bool lcl_GCBorder_GetLastBox_B( const SwTableBox*& rpBox, void* pPara )
+{
+ SwTableLines& rLines = (SwTableLines&)rpBox->GetTabLines();
+ if( rLines.Count() )
+ rLines.ForEach( &lcl_GCBorder_GetLastBox_L, pPara );
+ else
+ ((SwTableBoxes*)pPara)->Insert( rpBox, ((SwTableBoxes*)pPara)->Count() );
+ return sal_True;
+}
+
+// suche das "Ende" der vorgegebene BorderLine. Returnt wird die "Layout"Pos!
+sal_uInt16 lcl_FindEndPosOfBorder( const SwCollectTblLineBoxes& rCollTLB,
+ const SvxBorderLine& rBrdLn, sal_uInt16& rStt, sal_Bool bTop )
+{
+ sal_uInt16 nPos, nLastPos = 0;
+ for( sal_uInt16 nEnd = rCollTLB.Count(); rStt < nEnd; ++rStt )
+ {
+ const SfxPoolItem* pItem;
+ const SvxBorderLine* pBrd;
+ const SwTableBox& rBox = rCollTLB.GetBox( rStt, &nPos );
+
+ if( SFX_ITEM_SET != rBox.GetFrmFmt()->GetItemState(RES_BOX,sal_True, &pItem )
+ || 0 == ( pBrd = GetLineTB( (SvxBoxItem*)pItem, bTop ))
+ || !( *pBrd == rBrdLn ))
+ break;
+ nLastPos = nPos;
+ }
+ return nLastPos;
+}
+
+inline const SvxBorderLine* lcl_GCBorder_GetBorder( const SwTableBox& rBox,
+ sal_Bool bTop,
+ const SfxPoolItem** ppItem )
+{
+ return SFX_ITEM_SET == rBox.GetFrmFmt()->GetItemState( RES_BOX, sal_True, ppItem )
+ ? GetLineTB( (SvxBoxItem*)*ppItem, bTop )
+ : 0;
+}
+
+void lcl_GCBorder_DelBorder( const SwCollectTblLineBoxes& rCollTLB,
+ sal_uInt16& rStt, sal_Bool bTop,
+ const SvxBorderLine& rLine,
+ const SfxPoolItem* pItem,
+ sal_uInt16 nEndPos,
+ SwShareBoxFmts* pShareFmts )
+{
+ SwTableBox* pBox = (SwTableBox*)&rCollTLB.GetBox( rStt );
+ sal_uInt16 nNextPos;
+ const SvxBorderLine* pLn = &rLine;
+
+ do {
+ if( pLn && *pLn == rLine )
+ {
+ SvxBoxItem aBox( *(SvxBoxItem*)pItem );
+ if( bTop )
+ aBox.SetLine( 0, BOX_LINE_TOP );
+ else
+ aBox.SetLine( 0, BOX_LINE_BOTTOM );
+
+ if( pShareFmts )
+ pShareFmts->SetAttr( *pBox, aBox );
+ else
+ pBox->ClaimFrmFmt()->SetFmtAttr( aBox );
+ }
+
+ if( ++rStt >= rCollTLB.Count() )
+ break;
+
+ pBox = (SwTableBox*)&rCollTLB.GetBox( rStt, &nNextPos );
+ if( nNextPos > nEndPos )
+ break;
+
+ pLn = lcl_GCBorder_GetBorder( *pBox, bTop, &pItem );
+
+ } while( sal_True );
+}
+
+
+sal_Bool lcl_GC_Line_Border( const SwTableLine*& rpLine, void* pPara )
+{
+ _SwGCLineBorder* pGCPara = (_SwGCLineBorder*)pPara;
+
+ // zuerst die rechte Kante mit der linken Kante der naechsten Box
+ // innerhalb dieser Line
+ {
+ _SwGCBorder_BoxBrd aBPara;
+ const SvxBorderLine* pBrd;
+ const SfxPoolItem* pItem;
+ const SwTableBoxes& rBoxes = rpLine->GetTabBoxes();
+ for( sal_uInt16 n = 0, nBoxes = rBoxes.Count() - 1; n < nBoxes; ++n )
+ {
+ SwTableBoxes aBoxes;
+ {
+ const SwTableBox* pBox = rBoxes[ n ];
+ if( pBox->GetSttNd() )
+ aBoxes.Insert( pBox, 0 );
+ else
+ lcl_GCBorder_GetLastBox_B( pBox, &aBoxes );
+ }
+
+ SwTableBox* pBox;
+ for( sal_uInt16 i = aBoxes.Count(); i; )
+ if( SFX_ITEM_SET == (pBox = aBoxes[ --i ])->GetFrmFmt()->
+ GetItemState( RES_BOX, sal_True, &pItem ) &&
+ 0 != ( pBrd = ((SvxBoxItem*)pItem)->GetRight() ) )
+ {
+ aBPara.SetBorder( *pBrd );
+ const SwTableBox* pNextBox = rBoxes[n+1];
+ if( lcl_GCBorder_ChkBoxBrd_B( pNextBox, &aBPara ) &&
+ aBPara.IsAnyBorderFound() )
+ {
+ SvxBoxItem aBox( *(SvxBoxItem*)pItem );
+ aBox.SetLine( 0, BOX_LINE_RIGHT );
+ if( pGCPara->pShareFmts )
+ pGCPara->pShareFmts->SetAttr( *pBox, aBox );
+ else
+ pBox->ClaimFrmFmt()->SetFmtAttr( aBox );
+ }
+ }
+
+ aBoxes.Remove( 0, aBoxes.Count() );
+ }
+ }
+
+ // und jetzt die eigene untere Kante mit der nachfolgenden oberen Kante
+ if( !pGCPara->IsLastLine() )
+ {
+ SwCollectTblLineBoxes aBottom( sal_False );
+ SwCollectTblLineBoxes aTop( sal_True );
+
+ ::lcl_Line_CollectBox( rpLine, &aBottom );
+
+ const SwTableLine* pNextLine = (*pGCPara->pLines)[ pGCPara->nLinePos+1 ];
+ ::lcl_Line_CollectBox( pNextLine, &aTop );
+
+ // dann entferne mal alle "doppelten" gleichen Lines
+ sal_uInt16 nBtmPos, nTopPos,
+ nSttBtm = 0, nSttTop = 0,
+ nEndBtm = aBottom.Count(), nEndTop = aTop.Count();
+
+ const SwTableBox *pBtmBox = &aBottom.GetBox( nSttBtm++, &nBtmPos ),
+ *pTopBox = &aTop.GetBox( nSttTop++, &nTopPos );
+ const SfxPoolItem *pBtmItem = 0, *pTopItem = 0;
+ const SvxBorderLine *pBtmLine(0), *pTopLine(0);
+ sal_Bool bGetTopItem = sal_True, bGetBtmItem = sal_True;
+
+ do {
+ if( bGetBtmItem )
+ pBtmLine = lcl_GCBorder_GetBorder( *pBtmBox, sal_False, &pBtmItem );
+ if( bGetTopItem )
+ pTopLine = lcl_GCBorder_GetBorder( *pTopBox, sal_True, &pTopItem );
+
+ if( pTopLine && pBtmLine && *pTopLine == *pBtmLine )
+ {
+ // dann kann einer entfernt werden, aber welche?
+ sal_uInt16 nSavSttBtm = nSttBtm, nSavSttTop = nSttTop;
+ sal_uInt16 nBtmEndPos = ::lcl_FindEndPosOfBorder( aBottom,
+ *pTopLine, nSttBtm, sal_False );
+ if( !nBtmEndPos ) nBtmEndPos = nBtmPos;
+ sal_uInt16 nTopEndPos = ::lcl_FindEndPosOfBorder( aTop,
+ *pTopLine, nSttTop, sal_True );
+ if( !nTopEndPos ) nTopEndPos = nTopPos;
+
+
+ if( nTopEndPos <= nBtmEndPos )
+ {
+ // dann die TopBorder bis zur BottomEndPos loeschen
+ nSttTop = nSavSttTop;
+ if( nTopPos <= nBtmEndPos )
+ lcl_GCBorder_DelBorder( aTop, --nSttTop, sal_True,
+ *pBtmLine, pTopItem, nBtmEndPos,
+ pGCPara->pShareFmts );
+ else
+ nSttBtm = nSavSttBtm;
+ }
+ else
+ {
+ // sonst die BottomBorder bis zur TopEndPos loeschen
+ nSttBtm = nSavSttBtm;
+ if( nBtmPos <= nTopEndPos )
+ lcl_GCBorder_DelBorder( aBottom, --nSttBtm, sal_False,
+ *pTopLine, pBtmItem, nTopEndPos,
+ pGCPara->pShareFmts );
+ else
+ nSttTop = nSavSttTop;
+ }
+ nTopPos = nBtmPos;
+ }
+
+ if( nTopPos == nBtmPos )
+ {
+ if( nSttBtm >= nEndBtm || nSttTop >= nEndTop )
+ break;
+
+ pBtmBox = &aBottom.GetBox( nSttBtm++, &nBtmPos );
+ pTopBox = &aTop.GetBox( nSttTop++, &nTopPos );
+ bGetTopItem = bGetBtmItem = sal_True;
+ }
+ else if( nTopPos < nBtmPos )
+ {
+ if( nSttTop >= nEndTop )
+ break;
+ pTopBox = &aTop.GetBox( nSttTop++, &nTopPos );
+ bGetTopItem = sal_True;
+ bGetBtmItem = sal_False;
+ }
+ else
+ {
+ if( nSttBtm >= nEndBtm )
+ break;
+ pBtmBox = &aBottom.GetBox( nSttBtm++, &nBtmPos );
+ bGetTopItem = sal_False;
+ bGetBtmItem = sal_True;
+ }
+
+ } while( sal_True );
+ }
+
+ ((SwTableLine*)rpLine)->GetTabBoxes().ForEach( &lcl_GC_Box_Border, pPara );
+
+ ++pGCPara->nLinePos;
+
+ return sal_True;
+}
+
+sal_Bool lcl_GC_Box_Border( const SwTableBox*& rpBox, void* pPara )
+{
+ if( rpBox->GetTabLines().Count() )
+ {
+ _SwGCLineBorder aPara( *rpBox );
+ aPara.pShareFmts = ((_SwGCLineBorder*)pPara)->pShareFmts;
+ ((SwTableBox*)rpBox)->GetTabLines().ForEach( &lcl_GC_Line_Border, &aPara );
+ }
+ return sal_True;
+}
+
+struct _GCLinePara
+{
+ SwTableLines* pLns;
+ SwShareBoxFmts* pShareFmts;
+
+ _GCLinePara( SwTableLines& rLns, _GCLinePara* pPara = 0 )
+ : pLns( &rLns ), pShareFmts( pPara ? pPara->pShareFmts : 0 )
+ {}
+};
+
+sal_Bool lcl_MergeGCBox( const SwTableBox*& rpTblBox, void* pPara )
+{
+ SwTableBox*& rpBox = (SwTableBox*&)rpTblBox;
+ sal_uInt16 n, nLen = rpBox->GetTabLines().Count();
+ if( nLen )
+ {
+ // ACHTUNG: die Anzahl der Lines kann sich aendern!
+ _GCLinePara aPara( rpBox->GetTabLines(), (_GCLinePara*)pPara );
+ for( n = 0; n < rpBox->GetTabLines().Count() &&
+ lcl_MergeGCLine( *(rpBox->GetTabLines().GetData() + n), &aPara );
+ ++n )
+ ;
+
+ if( 1 == rpBox->GetTabLines().Count() )
+ {
+ // Box mit einer Line, dann verschiebe alle Boxen der Line
+ // hinter diese Box in der Parent-Line und loesche diese Box
+ SwTableLine* pInsLine = rpBox->GetUpper();
+ SwTableLine* pCpyLine = rpBox->GetTabLines()[0];
+ sal_uInt16 nInsPos = pInsLine->GetTabBoxes().C40_GETPOS( SwTableBox, rpBox );
+ for( n = 0; n < pCpyLine->GetTabBoxes().Count(); ++n )
+ pCpyLine->GetTabBoxes()[n]->SetUpper( pInsLine );
+
+ pInsLine->GetTabBoxes().Insert( &pCpyLine->GetTabBoxes(), nInsPos+1 );
+ pCpyLine->GetTabBoxes().Remove( 0, n );
+ // loesche alte die Box mit der Line
+ pInsLine->GetTabBoxes().DeleteAndDestroy( nInsPos );
+
+ return sal_False; // neu aufsetzen
+ }
+ }
+ return sal_True;
+}
+
+sal_Bool lcl_MergeGCLine( const SwTableLine*& rpLine, void* pPara )
+{
+ SwTableLine* pLn = (SwTableLine*)rpLine;
+ sal_uInt16 nLen = pLn->GetTabBoxes().Count();
+ if( nLen )
+ {
+ _GCLinePara* pGCPara = (_GCLinePara*)pPara;
+ while( 1 == nLen )
+ {
+ // es gibt eine Box mit Lines
+ SwTableBox* pBox = pLn->GetTabBoxes()[0];
+ if( !pBox->GetTabLines().Count() )
+ break;
+
+ SwTableLine* pLine = pBox->GetTabLines()[0];
+
+ // pLine wird zu der aktuellen, also der rpLine,
+ // die restlichen werden ins LinesArray hinter der akt.
+ // verschoben.
+ // Das LinesArray ist im pPara!
+ nLen = pBox->GetTabLines().Count();
+
+ SwTableLines& rLns = *pGCPara->pLns;
+ const SwTableLine* pTmp = pLn;
+ sal_uInt16 nInsPos = rLns.GetPos( pTmp );
+ OSL_ENSURE( USHRT_MAX != nInsPos, "Line nicht gefunden!" );
+
+ SwTableBox* pUpper = pLn->GetUpper();
+
+ rLns.Remove( nInsPos, 1 ); // die Line dem aus Array loeschen
+ rLns.Insert( &pBox->GetTabLines(), nInsPos );
+
+ // JP 31.03.99: Bug 60000 - die Attribute der zu loeschenden
+ // Line an die "eingefuegten" uebertragen
+ const SfxPoolItem* pItem;
+ if( SFX_ITEM_SET == pLn->GetFrmFmt()->GetItemState(
+ RES_BACKGROUND, sal_True, &pItem ))
+ {
+ SwTableLines& rBoxLns = pBox->GetTabLines();
+ for( sal_uInt16 nLns = 0; nLns < nLen; ++nLns )
+ if( SFX_ITEM_SET != rBoxLns[ nLns ]->GetFrmFmt()->
+ GetItemState( RES_BACKGROUND, sal_True ))
+ pGCPara->pShareFmts->SetAttr( *rBoxLns[ nLns ], *pItem );
+ }
+
+ pBox->GetTabLines().Remove( 0, nLen ); // Lines aus Array loeschen
+
+ delete pLn;
+
+ // Abhaengigkeit neu setzen
+ while( nLen-- )
+ rLns[ nInsPos++ ]->SetUpper( pUpper );
+
+ pLn = pLine; // und neu setzen
+ nLen = pLn->GetTabBoxes().Count();
+ }
+
+ // ACHTUNG: die Anzahl der Boxen kann sich aendern!
+ for( nLen = 0; nLen < pLn->GetTabBoxes().Count(); ++nLen )
+ if( !lcl_MergeGCBox( *(pLn->GetTabBoxes().GetData() + nLen ), pPara ))
+ --nLen;
+ }
+ return sal_True;
+}
+
+ // Struktur ein wenig aufraeumen
+void SwTable::GCLines()
+{
+ // ACHTUNG: die Anzahl der Lines kann sich aendern!
+ _GCLinePara aPara( GetTabLines() );
+ SwShareBoxFmts aShareFmts;
+ aPara.pShareFmts = &aShareFmts;
+ for( sal_uInt16 n = 0; n < GetTabLines().Count() &&
+ lcl_MergeGCLine( *(GetTabLines().GetData() + n ), &aPara ); ++n )
+ ;
+}
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/doc/htmltbl.cxx b/sw/source/core/doc/htmltbl.cxx
new file mode 100644
index 000000000000..0147bdce47ca
--- /dev/null
+++ b/sw/source/core/doc/htmltbl.cxx
@@ -0,0 +1,1844 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+#include "hintids.hxx"
+
+#include <vcl/wrkwin.hxx>
+#include <vcl/svapp.hxx>
+#include <sot/storage.hxx>
+#include <fmtornt.hxx>
+#include <fmtfsize.hxx>
+#include <frmfmt.hxx>
+#include <docary.hxx>
+#include "ndtxt.hxx"
+#include "doc.hxx"
+#include "swtable.hxx"
+#include "rootfrm.hxx"
+#include "docsh.hxx"
+#include "flyfrm.hxx"
+#include "poolfmt.hxx"
+#include "viewsh.hxx"
+#include "tabfrm.hxx"
+#include "viewopt.hxx"
+#include "htmltbl.hxx"
+#include "ndindex.hxx"
+#include "switerator.hxx"
+
+using namespace ::com::sun::star;
+
+
+#define COLFUZZY 20
+#define MAX_TABWIDTH (USHRT_MAX - 2001)
+
+
+class SwHTMLTableLayoutConstraints
+{
+ sal_uInt16 nRow; // Start-Zeile
+ sal_uInt16 nCol; // Start-Spalte
+ sal_uInt16 nColSpan; // COLSPAN der Zelle
+
+ SwHTMLTableLayoutConstraints *pNext; // die naechste Bedingung
+
+ sal_uLong nMinNoAlign, nMaxNoAlign; // Zwischenergebnisse AL-Pass 1
+
+public:
+
+ SwHTMLTableLayoutConstraints( sal_uLong nMin, sal_uLong nMax, sal_uInt16 nRow,
+ sal_uInt16 nCol, sal_uInt16 nColSp );
+ ~SwHTMLTableLayoutConstraints();
+
+ sal_uLong GetMinNoAlign() const { return nMinNoAlign; }
+ sal_uLong GetMaxNoAlign() const { return nMaxNoAlign; }
+
+ SwHTMLTableLayoutConstraints *InsertNext( SwHTMLTableLayoutConstraints *pNxt );
+ SwHTMLTableLayoutConstraints* GetNext() const { return pNext; }
+
+ sal_uInt16 GetRow() const { return nRow; }
+
+ sal_uInt16 GetColSpan() const { return nColSpan; }
+ sal_uInt16 GetColumn() const { return nCol; }
+};
+
+
+SwHTMLTableLayoutCnts::SwHTMLTableLayoutCnts( const SwStartNode *pSttNd,
+ SwHTMLTableLayout* pTab,
+ sal_Bool bNoBrTag,
+ SwHTMLTableLayoutCnts* pNxt ) :
+ pNext( pNxt ), pBox( 0 ), pTable( pTab ), pStartNode( pSttNd ),
+ nPass1Done( 0 ), nWidthSet( 0 ), bNoBreakTag( bNoBrTag )
+{}
+
+SwHTMLTableLayoutCnts::~SwHTMLTableLayoutCnts()
+{
+ delete pNext;
+ delete pTable;
+}
+
+const SwStartNode *SwHTMLTableLayoutCnts::GetStartNode() const
+{
+ return pBox ? pBox->GetSttNd() : pStartNode;
+}
+
+
+SwHTMLTableLayoutCell::SwHTMLTableLayoutCell( SwHTMLTableLayoutCnts *pCnts,
+ sal_uInt16 nRSpan, sal_uInt16 nCSpan,
+ sal_uInt16 nWidth, sal_Bool bPrcWidth,
+ sal_Bool bNWrapOpt ) :
+ pContents( pCnts ),
+ nRowSpan( nRSpan ), nColSpan( nCSpan ),
+ nWidthOption( nWidth ), bPrcWidthOption( bPrcWidth ),
+ bNoWrapOption( bNWrapOpt )
+{}
+
+SwHTMLTableLayoutCell::~SwHTMLTableLayoutCell()
+{
+ if( nRowSpan==1 && nColSpan==1 )
+ {
+ delete pContents;
+ }
+}
+
+
+SwHTMLTableLayoutColumn::SwHTMLTableLayoutColumn( sal_uInt16 nWidth,
+ sal_Bool bRelWidth,
+ sal_Bool bLBorder ) :
+ nMinNoAlign(MINLAY), nMaxNoAlign(MINLAY), nAbsMinNoAlign(MINLAY),
+ nMin(0), nMax(0),
+ nAbsColWidth(0), nRelColWidth(0),
+ nWidthOption( nWidth ), bRelWidthOption( bRelWidth ),
+ bLeftBorder( bLBorder )
+{}
+
+
+SwHTMLTableLayoutConstraints::SwHTMLTableLayoutConstraints(
+ sal_uLong nMin, sal_uLong nMax, sal_uInt16 nRw, sal_uInt16 nColumn, sal_uInt16 nColSp ):
+ nRow( nRw ), nCol( nColumn ), nColSpan( nColSp ),
+ pNext( 0 ),
+ nMinNoAlign( nMin ), nMaxNoAlign( nMax )
+{}
+
+SwHTMLTableLayoutConstraints::~SwHTMLTableLayoutConstraints()
+{
+ delete pNext;
+}
+
+SwHTMLTableLayoutConstraints *SwHTMLTableLayoutConstraints::InsertNext(
+ SwHTMLTableLayoutConstraints *pNxt )
+{
+ SwHTMLTableLayoutConstraints *pPrev = 0;
+ SwHTMLTableLayoutConstraints *pConstr = this;
+ while( pConstr )
+ {
+ if( pConstr->GetRow() > pNxt->GetRow() ||
+ pConstr->GetColumn() > pNxt->GetColumn() )
+ break;
+ pPrev = pConstr;
+ pConstr = pConstr->GetNext();
+ }
+
+ if( pPrev )
+ {
+ pNxt->pNext = pPrev->GetNext();
+ pPrev->pNext = pNxt;
+ pConstr = this;
+ }
+ else
+ {
+ pNxt->pNext = this;
+ pConstr = pNxt;
+ }
+
+ return pConstr;
+}
+
+
+typedef SwHTMLTableLayoutColumn *SwHTMLTableLayoutColumnPtr;
+typedef SwHTMLTableLayoutCell *SwHTMLTableLayoutCellPtr;
+
+SwHTMLTableLayout::SwHTMLTableLayout(
+ const SwTable * pSwTbl,
+ sal_uInt16 nRws, sal_uInt16 nCls, sal_Bool bColsOpt, sal_Bool bColTgs,
+ sal_uInt16 nWdth, sal_Bool bPrcWdth, sal_uInt16 nBorderOpt,
+ sal_uInt16 nCellPad, sal_uInt16 nCellSp, SvxAdjust eAdjust,
+ sal_uInt16 nLMargin, sal_uInt16 nRMargin,
+ sal_uInt16 nBWidth, sal_uInt16 nLeftBWidth,
+ sal_uInt16 nRightBWidth,
+ sal_uInt16 nInhLeftBWidth, sal_uInt16 nInhRightBWidth ) :
+ aColumns( new SwHTMLTableLayoutColumnPtr[nCls] ),
+ aCells( new SwHTMLTableLayoutCellPtr[nRws*nCls] ),
+ pSwTable( pSwTbl ), pLeftFillerBox( 0 ), pRightFillerBox( 0 ),
+ nMin( 0 ), nMax( 0 ),
+ nRows( nRws ), nCols( nCls ),
+ nLeftMargin( nLMargin ), nRightMargin( nRMargin ),
+ nInhAbsLeftSpace( 0 ), nInhAbsRightSpace( 0 ),
+ nRelLeftFill( 0 ), nRelRightFill( 0 ),
+ nRelTabWidth( 0 ), nWidthOption( nWdth ),
+ nCellPadding( nCellPad ), nCellSpacing( nCellSp ), nBorder( nBorderOpt ),
+ nLeftBorderWidth( nLeftBWidth ), nRightBorderWidth( nRightBWidth ),
+ nInhLeftBorderWidth( nInhLeftBWidth ),
+ nInhRightBorderWidth( nInhRightBWidth ),
+ nBorderWidth( nBWidth ),
+ nDelayedResizeAbsAvail( 0 ), nLastResizeAbsAvail( 0 ),
+ nPass1Done( 0 ), nWidthSet( 0 ), eTableAdjust( eAdjust ),
+ bColsOption( bColsOpt ), bColTags( bColTgs ),
+ bPrcWidthOption( bPrcWdth ), bUseRelWidth( sal_False ),
+ bMustResize( sal_True ), bExportable( sal_True ), bBordersChanged( sal_False ),
+ bMustNotResize( sal_False ), bMustNotRecalc( sal_False )
+{
+ aResizeTimer.SetTimeoutHdl( STATIC_LINK( this, SwHTMLTableLayout,
+ DelayedResize_Impl ) );
+}
+
+SwHTMLTableLayout::~SwHTMLTableLayout()
+{
+ sal_uInt16 i;
+
+ for( i = 0; i < nCols; i++ )
+ delete aColumns[i];
+ delete[] aColumns;
+
+ sal_uInt16 nCount = nRows*nCols;
+ for( i=0; i<nCount; i++ )
+ delete aCells[i];
+ delete[] aCells;
+}
+
+// Die Breiten der Umrandung werden zunaechst wie in Netscape berechnet:
+// Aussere Umrandung: BORDER + CELLSPACING + CELLPADDING
+// Innere Umrandung: CELLSPACING + CELLPADDING
+// Allerdings wird die Breite der Umrandung im SW trotzdem beachtet, wenn
+// bSwBorders gesetzt ist, damit nicht faellschlich umgebrochen wird.
+// MIB 27.6.97: Dabei muss auch der Abstand zum Inhalt berueckichtigt werden,
+// und zwar auch dann, wenn wenn nur die gegenueberliegende Seite
+// eine Umrandung hat.
+sal_uInt16 SwHTMLTableLayout::GetLeftCellSpace( sal_uInt16 nCol, sal_uInt16 nColSpan,
+ sal_Bool bSwBorders ) const
+{
+ sal_uInt16 nSpace = nCellSpacing + nCellPadding;
+
+ if( nCol == 0 )
+ {
+ nSpace = nSpace + nBorder;
+
+ if( bSwBorders && nSpace < nLeftBorderWidth )
+ nSpace = nLeftBorderWidth;
+ }
+ else if( bSwBorders )
+ {
+ if( GetColumn(nCol)->HasLeftBorder() )
+ {
+ if( nSpace < nBorderWidth )
+ nSpace = nBorderWidth;
+ }
+ else if( nCol+nColSpan == nCols && nRightBorderWidth &&
+ nSpace < MIN_BORDER_DIST )
+ {
+ OSL_ENSURE( !nCellPadding, "GetLeftCellSpace: CELLPADDING!=0" );
+ // Wenn die Gegenueberliegende Seite umrandet ist muessen
+ // wir zumindest den minimalen Abstand zum Inhalt
+ // beruecksichtigen. (Koennte man zusaetzlich auch an
+ // nCellPadding festmachen.)
+ nSpace = MIN_BORDER_DIST;
+ }
+ }
+
+ return nSpace;
+}
+
+sal_uInt16 SwHTMLTableLayout::GetRightCellSpace( sal_uInt16 nCol, sal_uInt16 nColSpan,
+ sal_Bool bSwBorders ) const
+{
+ sal_uInt16 nSpace = nCellPadding;
+
+ if( nCol+nColSpan == nCols )
+ {
+ nSpace += nBorder + nCellSpacing;
+ if( bSwBorders && nSpace < nRightBorderWidth )
+ nSpace = nRightBorderWidth;
+ }
+ else if( bSwBorders && GetColumn(nCol)->HasLeftBorder() &&
+ nSpace < MIN_BORDER_DIST )
+ {
+ OSL_ENSURE( !nCellPadding, "GetRightCellSpace: CELLPADDING!=0" );
+ // Wenn die Gegenueberliegende Seite umrandet ist muessen
+ // wir zumindest den minimalen Abstand zum Inhalt
+ // beruecksichtigen. (Koennte man zusaetzlich auch an
+ // nCellPadding festmachen.)
+ nSpace = MIN_BORDER_DIST;
+ }
+
+ return nSpace;
+}
+
+void SwHTMLTableLayout::AddBorderWidth( sal_uLong &rMin, sal_uLong &rMax,
+ sal_uLong &rAbsMin,
+ sal_uInt16 nCol, sal_uInt16 nColSpan,
+ sal_Bool bSwBorders ) const
+{
+ sal_uLong nAdd = GetLeftCellSpace( nCol, nColSpan, bSwBorders ) +
+ GetRightCellSpace( nCol, nColSpan, bSwBorders );
+
+ rMin += nAdd;
+ rMax += nAdd;
+ rAbsMin += nAdd;
+}
+
+void SwHTMLTableLayout::SetBoxWidth( SwTableBox *pBox, sal_uInt16 nCol,
+ sal_uInt16 nColSpan ) const
+{
+ SwFrmFmt *pFrmFmt = pBox->GetFrmFmt();
+
+ // die Breite der Box berechnen
+ SwTwips nFrmWidth = 0;
+ while( nColSpan-- )
+ nFrmWidth += GetColumn( nCol++ )->GetRelColWidth();
+
+ // und neu setzen
+
+ pFrmFmt->SetFmtAttr( SwFmtFrmSize( ATT_VAR_SIZE, nFrmWidth, 0 ));
+}
+
+void SwHTMLTableLayout::GetAvail( sal_uInt16 nCol, sal_uInt16 nColSpan,
+ sal_uInt16& rAbsAvail, sal_uInt16& rRelAvail ) const
+{
+ rAbsAvail = 0;
+ rRelAvail = 0;
+ for( sal_uInt16 i=nCol; i<nCol+nColSpan;i++ )
+ {
+ const SwHTMLTableLayoutColumn *pColumn = GetColumn(i);
+ rAbsAvail = rAbsAvail + pColumn->GetAbsColWidth();
+ rRelAvail = rRelAvail + pColumn->GetRelColWidth();
+ }
+}
+
+sal_uInt16 SwHTMLTableLayout::GetBrowseWidthByVisArea( const SwDoc& rDoc )
+{
+ ViewShell *pVSh = 0;
+ rDoc.GetEditShell( &pVSh );
+ if( pVSh )
+ {
+ return (sal_uInt16)pVSh->GetBrowseWidth();
+ }
+
+ return 0;
+}
+
+sal_uInt16 SwHTMLTableLayout::GetBrowseWidth( const SwDoc& rDoc )
+{
+ // Wenn ein Layout da ist, koennen wir die Breite dort herholen.
+ const SwRootFrm *pRootFrm = rDoc.GetCurrentLayout(); //swmod 080218
+ if( pRootFrm )
+ {
+ const SwFrm *pPageFrm = pRootFrm->GetLower();
+ if( pPageFrm )
+ return (sal_uInt16)pPageFrm->Prt().Width();
+ }
+
+ // #i91658#
+ // Assertion removed which state that no browse width is available.
+ // Investigation reveals that all calls can handle the case that no browse
+ // width is provided.
+ return GetBrowseWidthByVisArea( rDoc );
+ // <--
+}
+
+sal_uInt16 SwHTMLTableLayout::GetBrowseWidthByTabFrm(
+ const SwTabFrm& rTabFrm ) const
+{
+ SwTwips nWidth = 0;
+
+ const SwFrm *pUpper = rTabFrm.GetUpper();
+ if( MayBeInFlyFrame() && pUpper->IsFlyFrm() &&
+ ((const SwFlyFrm *)pUpper)->GetAnchorFrm() )
+ {
+ // Wenn die Tabelle in einem selbst angelegten Rahmen steht, dann ist
+ // die Breite Ankers und nicht die Breite Rahmens von Bedeutung.
+ // Bei Absatz-gebundenen Rahmen werden Absatz-Einzuege nicht beachtet.
+ const SwFrm *pAnchor = ((const SwFlyFrm *)pUpper)->GetAnchorFrm();
+ if( pAnchor->IsTxtFrm() )
+ nWidth = pAnchor->Frm().Width();
+ else
+ nWidth = pAnchor->Prt().Width();
+ }
+ else
+ {
+ nWidth = pUpper->Prt().Width();
+ }
+
+ SwTwips nUpperDummy = 0;
+ long nRightOffset = 0,
+ nLeftOffset = 0;
+ rTabFrm.CalcFlyOffsets( nUpperDummy, nLeftOffset, nRightOffset );
+ nWidth -= (nLeftOffset + nRightOffset);
+
+ return nWidth < USHRT_MAX ? static_cast<sal_uInt16>(nWidth) : USHRT_MAX;
+}
+
+sal_uInt16 SwHTMLTableLayout::GetBrowseWidthByTable( const SwDoc& rDoc ) const
+{
+ sal_uInt16 nBrowseWidth = 0;
+ SwTabFrm* pFrm = SwIterator<SwTabFrm,SwFmt>::FirstElement( *pSwTable->GetFrmFmt() );
+ if( pFrm )
+ {
+ nBrowseWidth = GetBrowseWidthByTabFrm( *pFrm );
+ }
+ else
+ {
+ nBrowseWidth = SwHTMLTableLayout::GetBrowseWidth( rDoc );
+ }
+
+ return nBrowseWidth;
+}
+
+const SwStartNode *SwHTMLTableLayout::GetAnyBoxStartNode() const
+{
+ const SwStartNode *pBoxSttNd;
+
+ const SwTableBox* pBox = pSwTable->GetTabLines()[0]->GetTabBoxes()[0];
+ while( 0 == (pBoxSttNd = pBox->GetSttNd()) )
+ {
+ OSL_ENSURE( pBox->GetTabLines().Count() > 0,
+ "Box ohne Start-Node und Lines" );
+ OSL_ENSURE( pBox->GetTabLines()[0]->GetTabBoxes().Count() > 0,
+ "Line ohne Boxen" );
+ pBox = pBox->GetTabLines()[0]->GetTabBoxes()[0];
+ }
+
+ return pBoxSttNd;
+}
+
+SwFrmFmt *SwHTMLTableLayout::FindFlyFrmFmt() const
+{
+ const SwTableNode *pTblNd = GetAnyBoxStartNode()->FindTableNode();
+ OSL_ENSURE( pTblNd, "Kein Table-Node?" );
+ return pTblNd->GetFlyFmt();
+}
+
+static void lcl_GetMinMaxSize( sal_uLong& rMinNoAlignCnts, sal_uLong& rMaxNoAlignCnts,
+ sal_uLong& rAbsMinNoAlignCnts,
+ SwTxtNode *pTxtNd, sal_uLong nIdx, sal_Bool bNoBreak )
+{
+ pTxtNd->GetMinMaxSize( nIdx, rMinNoAlignCnts, rMaxNoAlignCnts,
+ rAbsMinNoAlignCnts );
+ OSL_ENSURE( rAbsMinNoAlignCnts <= rMinNoAlignCnts,
+ "GetMinMaxSize: absmin > min" );
+ OSL_ENSURE( rMinNoAlignCnts <= rMaxNoAlignCnts,
+ "GetMinMaxSize: max > min" );
+
+ //Bei einen <PRE>-Absatz entspricht die maximale Breite der
+ // minimalen breite
+ const SwFmtColl *pColl = &pTxtNd->GetAnyFmtColl();
+ while( pColl && !pColl->IsDefault() &&
+ (USER_FMT & pColl->GetPoolFmtId()) )
+ {
+ pColl = (const SwFmtColl *)pColl->DerivedFrom();
+ }
+
+ // <NOBR> in der gesamten Zelle bezieht sich auf Text, aber nicht
+ // auf Tabellen. Netscape beruecksichtigt dies nur fuer Grafiken.
+ if( (pColl && RES_POOLCOLL_HTML_PRE==pColl->GetPoolFmtId()) || bNoBreak )
+ {
+ rMinNoAlignCnts = rMaxNoAlignCnts;
+ rAbsMinNoAlignCnts = rMaxNoAlignCnts;
+ }
+}
+
+void SwHTMLTableLayout::AutoLayoutPass1()
+{
+ nPass1Done++;
+
+ ClearPass1Info();
+
+ sal_Bool bFixRelWidths = sal_False;
+ sal_uInt16 i;
+
+ SwHTMLTableLayoutConstraints *pConstraints = 0;
+
+ for( i=0; i<nCols; i++ )
+ {
+ SwHTMLTableLayoutColumn *pColumn = GetColumn( i );
+ pColumn->ClearPass1Info( !HasColTags() );
+ sal_uInt16 nMinColSpan = USHRT_MAX; // Spaltenzahl, auf die sich dir
+ // berechnete Breite bezieht
+ sal_uInt16 nColSkip = USHRT_MAX; // Wie viele Spalten muessen
+ // uebersprungen werden
+
+ for( sal_uInt16 j=0; j<nRows; j++ )
+ {
+ SwHTMLTableLayoutCell *pCell = GetCell(j,i);
+ SwHTMLTableLayoutCnts *pCnts = pCell->GetContents();
+
+ // Zum Ermitteln der naechsten zu berechnenden
+ // Spalte muessen alle Zeilen herangezogen werden
+ sal_uInt16 nColSpan = pCell->GetColSpan();
+ if( nColSpan < nColSkip )
+ nColSkip = nColSpan;
+
+ if( !pCnts || (pCnts && !pCnts->IsPass1Done(nPass1Done)) )
+ {
+ // die Zelle ist leer oder ihr Inhalt wurde nich nicht
+ // bearbeitet
+ if( nColSpan < nMinColSpan )
+ nMinColSpan = nColSpan;
+
+ sal_uLong nMinNoAlignCell = 0;
+ sal_uLong nMaxNoAlignCell = 0;
+ sal_uLong nAbsMinNoAlignCell = 0;
+ sal_uLong nMaxTableCell = 0;
+ sal_uLong nAbsMinTableCell = 0;
+
+ while( pCnts )
+ {
+ const SwStartNode *pSttNd = pCnts->GetStartNode();
+ if( pSttNd )
+ {
+ const SwDoc *pDoc = pSttNd->GetDoc();
+ sal_uLong nIdx = pSttNd->GetIndex();
+ while( !(pDoc->GetNodes()[nIdx])->IsEndNode() )
+ {
+ SwTxtNode *pTxtNd = (pDoc->GetNodes()[nIdx])->GetTxtNode();
+ if( pTxtNd )
+ {
+ sal_uLong nMinNoAlignCnts = 0;
+ sal_uLong nMaxNoAlignCnts = 0;
+ sal_uLong nAbsMinNoAlignCnts = 0;
+
+ lcl_GetMinMaxSize( nMinNoAlignCnts,
+ nMaxNoAlignCnts,
+ nAbsMinNoAlignCnts,
+ pTxtNd, nIdx,
+ pCnts->HasNoBreakTag() );
+
+ if( nMinNoAlignCnts > nMinNoAlignCell )
+ nMinNoAlignCell = nMinNoAlignCnts;
+ if( nMaxNoAlignCnts > nMaxNoAlignCell )
+ nMaxNoAlignCell = nMaxNoAlignCnts;
+ if( nAbsMinNoAlignCnts > nAbsMinNoAlignCell )
+ nAbsMinNoAlignCell = nAbsMinNoAlignCnts;
+ }
+ else
+ {
+ SwTableNode *pTabNd = (pDoc->GetNodes()[nIdx])->GetTableNode();
+ if( pTabNd )
+ {
+ SwHTMLTableLayout *pChild = pTabNd->GetTable().GetHTMLTableLayout();
+ if( pChild )
+ {
+ pChild->AutoLayoutPass1();
+ sal_uLong nMaxTableCnts = pChild->nMax;
+ sal_uLong nAbsMinTableCnts = pChild->nMin;
+
+ // Eine feste Tabellen-Breite wird als Minimum
+ // und Maximum gleichzeitig uebernommen
+ if( !pChild->bPrcWidthOption && pChild->nWidthOption )
+ {
+ sal_uLong nTabWidth = pChild->nWidthOption;
+ if( nTabWidth >= nAbsMinTableCnts )
+ {
+ nMaxTableCnts = nTabWidth;
+ nAbsMinTableCnts = nTabWidth;
+ }
+ else
+ {
+ nMaxTableCnts = nAbsMinTableCnts;
+ }
+ }
+
+ if( nMaxTableCnts > nMaxTableCell )
+ nMaxTableCell = nMaxTableCnts;
+ if( nAbsMinTableCnts > nAbsMinTableCell )
+ nAbsMinTableCell = nAbsMinTableCnts;
+ }
+ nIdx = pTabNd->EndOfSectionNode()->GetIndex();
+ }
+ }
+ nIdx++;
+ }
+ }
+ else
+ {
+ OSL_ENSURE( !this, "Sub tables in HTML import?" );
+ SwHTMLTableLayout *pChild = pCnts->GetTable();
+ pChild->AutoLayoutPass1();
+ sal_uLong nMaxTableCnts = pChild->nMax;
+ sal_uLong nAbsMinTableCnts = pChild->nMin;
+
+ // Eine feste Tabellen-Breite wird als Minimum
+ // und Maximum gleichzeitig uebernommen
+ if( !pChild->bPrcWidthOption && pChild->nWidthOption )
+ {
+ sal_uLong nTabWidth = pChild->nWidthOption;
+ if( nTabWidth >= nAbsMinTableCnts )
+ {
+ nMaxTableCnts = nTabWidth;
+ nAbsMinTableCnts = nTabWidth;
+ }
+ else
+ {
+ nMaxTableCnts = nAbsMinTableCnts;
+ }
+ }
+
+ if( nMaxTableCnts > nMaxTableCell )
+ nMaxTableCell = nMaxTableCnts;
+ if( nAbsMinTableCnts > nAbsMinTableCell )
+ nAbsMinTableCell = nAbsMinTableCnts;
+ }
+ pCnts->SetPass1Done( nPass1Done );
+ pCnts = pCnts->GetNext();
+ }
+
+// War frueher hinter AddBorderWidth
+ // Wenn die Breite einer Tabelle in der Zelle breiter ist als
+ // das, was wir fuer sonstigen Inhalt berechnet haben, mussen
+ // wir die Breite der Tabelle nutzen
+ if( nMaxTableCell > nMaxNoAlignCell )
+ nMaxNoAlignCell = nMaxTableCell;
+ if( nAbsMinTableCell > nAbsMinNoAlignCell )
+ {
+ nAbsMinNoAlignCell = nAbsMinTableCell;
+ if( nMinNoAlignCell < nAbsMinNoAlignCell )
+ nMinNoAlignCell = nAbsMinNoAlignCell;
+ if( nMaxNoAlignCell < nMinNoAlignCell )
+ nMaxNoAlignCell = nMinNoAlignCell;
+ }
+// War frueher hinter AddBorderWidth
+
+ sal_Bool bRelWidth = pCell->IsPrcWidthOption();
+ sal_uInt16 nWidth = pCell->GetWidthOption();
+
+ // Eine NOWRAP-Option bezieht sich auf Text und auf
+ // Tabellen, wird aber bei fester Zellenbreite
+ // nicht uebernommen. Stattdessen wirkt die angegebene
+ // Zellenbreite wie eine Mindestbreite.
+ if( pCell->HasNoWrapOption() )
+ {
+ if( nWidth==0 || bRelWidth )
+ {
+ nMinNoAlignCell = nMaxNoAlignCell;
+ nAbsMinNoAlignCell = nMaxNoAlignCell;
+ }
+ else
+ {
+ if( nWidth>nMinNoAlignCell )
+ nMinNoAlignCell = nWidth;
+ if( nWidth>nAbsMinNoAlignCell )
+ nAbsMinNoAlignCell = nWidth;
+ }
+ }
+
+ // Mindestbreite fuer Inhalt einhalten
+ if( nMinNoAlignCell < MINLAY )
+ nMinNoAlignCell = MINLAY;
+ if( nMaxNoAlignCell < MINLAY )
+ nMaxNoAlignCell = MINLAY;
+ if( nAbsMinNoAlignCell < MINLAY )
+ nAbsMinNoAlignCell = MINLAY;
+
+ // Umrandung und Abstand zum Inhalt beachten.
+ AddBorderWidth( nMinNoAlignCell, nMaxNoAlignCell,
+ nAbsMinNoAlignCell, i, nColSpan );
+
+ if( 1==nColSpan )
+ {
+ // die Werte direkt uebernehmen
+ pColumn->MergeMinMaxNoAlign( nMinNoAlignCell,
+ nMaxNoAlignCell,
+ nAbsMinNoAlignCell );
+
+ // bei den WIDTH angaben gewinnt die breiteste
+ if( !HasColTags() )
+ pColumn->MergeCellWidthOption( nWidth, bRelWidth );
+ }
+ else
+ {
+ // die Angaben erst am Ende, und zwar zeilenweise von
+ // links nach rechts bearbeiten
+
+ // Wann welche Werte wie uebernommen werden ist weiter
+ // unten erklaert.
+ if( !HasColTags() && nWidth && !bRelWidth )
+ {
+ sal_uLong nAbsWidth = nWidth, nDummy = 0, nDummy2 = 0;
+ AddBorderWidth( nAbsWidth, nDummy, nDummy2,
+ i, nColSpan, sal_False );
+
+ if( nAbsWidth >= nMinNoAlignCell )
+ {
+ nMaxNoAlignCell = nAbsWidth;
+ if( HasColsOption() )
+ nMinNoAlignCell = nAbsWidth;
+ }
+ else if( nAbsWidth >= nAbsMinNoAlignCell )
+ {
+ nMaxNoAlignCell = nAbsWidth;
+ nMinNoAlignCell = nAbsWidth;
+ }
+ else
+ {
+ nMaxNoAlignCell = nAbsMinNoAlignCell;
+ nMinNoAlignCell = nAbsMinNoAlignCell;
+ }
+ }
+ else if( HasColsOption() || HasColTags() )
+ nMinNoAlignCell = nAbsMinNoAlignCell;
+
+ SwHTMLTableLayoutConstraints *pConstr =
+ new SwHTMLTableLayoutConstraints( nMinNoAlignCell,
+ nMaxNoAlignCell, j, i, nColSpan );
+ if( pConstraints )
+ pConstraints = pConstraints->InsertNext( pConstr );
+ else
+ pConstraints = pConstr;
+ }
+ }
+ }
+
+ OSL_ENSURE( nMinColSpan>0 && nColSkip>0 && nColSkip <= nMinColSpan,
+ "Layout Pass 1: Da werden Spalten vergessen!" );
+ OSL_ENSURE( nMinColSpan!=USHRT_MAX,
+ "Layout Pass 1: unnoetiger Schleifendurchlauf oder Bug" );
+
+ if( 1==nMinColSpan )
+ {
+ // es gibt Zellen mit COLSPAN 1 und demnach auch sinnvolle
+ // Werte in pColumn
+
+ // Werte anhand folgender Tabelle (Netscape 4.0 pv 3) uebernehmen:
+ //
+ // WIDTH: kein COLS COLS
+ //
+ // keine min = min min = absmin
+ // max = max max = max
+ //
+ // >= min min = min min = width
+ // max = width max = width
+ //
+ // >= absmin min = wdith(*) min = width
+ // max = width max = width
+ //
+ // < absmin min = absmin min = absmin
+ // max = absmin max = absmin
+ //
+ // (*) Netscape benutzt hier die Mindestbreite ohne einen
+ // Umbruch vor der letzten Grafik. Haben wir (noch?) nicht,
+ // also belassen wir es bei width.^
+
+ if( pColumn->GetWidthOption() && !pColumn->IsRelWidthOption() )
+ {
+ // absolute Breiten als Minimal- und Maximalbreite
+ // uebernehmen.
+ sal_uLong nAbsWidth = pColumn->GetWidthOption();
+ sal_uLong nDummy = 0, nDummy2 = 0;
+ AddBorderWidth( nAbsWidth, nDummy, nDummy2, i, 1, sal_False );
+
+ if( nAbsWidth >= pColumn->GetMinNoAlign() )
+ {
+ pColumn->SetMinMax( HasColsOption() ? nAbsWidth
+ : pColumn->GetMinNoAlign(),
+ nAbsWidth );
+ }
+ else if( nAbsWidth >= pColumn->GetAbsMinNoAlign() )
+ {
+ pColumn->SetMinMax( nAbsWidth, nAbsWidth );
+ }
+ else
+ {
+ pColumn->SetMinMax( pColumn->GetAbsMinNoAlign(),
+ pColumn->GetAbsMinNoAlign() );
+ }
+ }
+ else
+ {
+ pColumn->SetMinMax( HasColsOption() ? pColumn->GetAbsMinNoAlign()
+ : pColumn->GetMinNoAlign(),
+ pColumn->GetMaxNoAlign() );
+ }
+ }
+ else if( USHRT_MAX!=nMinColSpan )
+ {
+ // kann irgendwas !=0 sein, weil es durch die Constraints
+ // angepasst wird.
+ pColumn->SetMinMax( MINLAY, MINLAY );
+
+ // die naechsten Spalten muessen nicht bearbeitet werden
+ i += (nColSkip-1);
+ }
+
+ nMin += pColumn->GetMin();
+ nMax += pColumn->GetMax();
+ bFixRelWidths |= pColumn->IsRelWidthOption();
+ }
+
+ // jetzt noch die Constrains verarbeiten
+ SwHTMLTableLayoutConstraints *pConstr = pConstraints;
+ while( pConstr )
+ {
+ // Erstmal muss die Breite analog zu den den Spaltenbreiten
+ // aufbereitet werden
+ sal_uInt16 nCol = pConstr->GetColumn();
+ sal_uInt16 nColSpan = pConstr->GetColSpan();
+ sal_uLong nConstrMin = pConstr->GetMinNoAlign();
+ sal_uLong nConstrMax = pConstr->GetMaxNoAlign();
+
+ // jetzt holen wir uns die bisherige Breite der ueberspannten
+ // Spalten
+ sal_uLong nColsMin = 0;
+ sal_uLong nColsMax = 0;
+ for( sal_uInt16 j=nCol; j<nCol+nColSpan; j++ )
+ {
+ SwHTMLTableLayoutColumn *pColumn = GetColumn( j );
+ nColsMin += pColumn->GetMin();
+ nColsMax += pColumn->GetMax();
+ }
+
+ if( nColsMin<nConstrMin )
+ {
+ // den Minimalwert anteilig auf die Spalten verteilen
+ sal_uLong nMinD = nConstrMin-nColsMin;
+
+ if( nConstrMin > nColsMax )
+ {
+ // Anteilig anhand der Mindestbreiten
+ sal_uInt16 nEndCol = nCol+nColSpan;
+ sal_uLong nDiff = nMinD;
+ for( sal_uInt16 ic=nCol; ic<nEndCol; ic++ )
+ {
+ SwHTMLTableLayoutColumn *pColumn = GetColumn( ic );
+
+ sal_uLong nColMin = pColumn->GetMin();
+ sal_uLong nColMax = pColumn->GetMax();
+
+ nMin -= nColMin;
+ sal_uLong nAdd = ic<nEndCol-1 ? (nColMin * nMinD) / nColsMin
+ : nDiff;
+ nColMin += nAdd;
+ nMin += nColMin;
+ OSL_ENSURE( nDiff >= nAdd, "Ooops: nDiff stimmt nicht mehr" );
+ nDiff -= nAdd;
+
+ if( nColMax < nColMin )
+ {
+ nMax -= nColMax;
+ nColsMax -= nColMax;
+ nColMax = nColMin;
+ nMax += nColMax;
+ nColsMax += nColMax;
+ }
+
+ pColumn->SetMinMax( nColMin, nColMax );
+ }
+ }
+ else
+ {
+ // Anteilig anhand der Differenz zwischen Max und Min
+ for( sal_uInt16 ic=nCol; ic<nCol+nColSpan; ic++ )
+ {
+ SwHTMLTableLayoutColumn *pColumn = GetColumn( ic );
+
+ sal_uLong nDiff = pColumn->GetMax()-pColumn->GetMin();
+ if( nMinD < nDiff )
+ nDiff = nMinD;
+
+ pColumn->AddToMin( nDiff );
+
+ OSL_ENSURE( pColumn->GetMax() >= pColumn->GetMin(),
+ "Wieso ist die SPalte auf einmal zu schmal?" );
+
+ nMin += nDiff;
+ nMinD -= nDiff;
+ }
+ }
+ }
+
+ if( !HasColTags() && nColsMax<nConstrMax )
+ {
+ sal_uLong nMaxD = nConstrMax-nColsMax;
+
+ for( sal_uInt16 ic=nCol; ic<nCol+nColSpan; ic++ )
+ {
+ SwHTMLTableLayoutColumn *pColumn = GetColumn( ic );
+
+ nMax -= pColumn->GetMax();
+
+ pColumn->AddToMax( (pColumn->GetMax() * nMaxD) / nColsMax );
+
+ nMax += pColumn->GetMax();
+ }
+ }
+
+ pConstr = pConstr->GetNext();
+ }
+
+
+ if( bFixRelWidths )
+ {
+ if( HasColTags() )
+ {
+ // Zum Anpassen der relativen Breiten werden im 1. Schritt die
+ // Minmalbreiten aller anzupassenden Zellen jeweils mit der
+ // relativen Breite einer Spalte multipliziert. Dadurch stimmen
+ // dann die Breitenverhaeltnisse der Spalten untereinander.
+ // Ausserdem wird der Faktor berechnet, um den die Zelle dadurch
+ // breiter gworden ist als die Minmalbreite.
+ // Im 2. Schritt werden dann die berechneten Breiten durch diesen
+ // Faktor geteilt. Dadurch bleibt die Breite (nimd.) einer Zelle
+ // erhalten und dient als Ausgangsbasis fuer die andern Breiten.
+ // Es werden auch hier nur die Maximalbreiten beeinflusst!
+
+ sal_uLong nAbsMin = 0; // absolte Min-Breite alter Spalten mit
+ // relativer Breite
+ sal_uLong nRel = 0; // Summe der relativen Breiten aller Spalten
+ for( i=0; i<nCols; i++ )
+ {
+ SwHTMLTableLayoutColumn *pColumn = GetColumn( i );
+ if( pColumn->IsRelWidthOption() && pColumn->GetWidthOption() )
+ {
+ nAbsMin += pColumn->GetMin();
+ nRel += pColumn->GetWidthOption();
+ }
+ }
+
+ sal_uLong nQuot = ULONG_MAX;
+ for( i=0; i<nCols; i++ )
+ {
+ SwHTMLTableLayoutColumn *pColumn = GetColumn( i );
+ if( pColumn->IsRelWidthOption() )
+ {
+ nMax -= pColumn->GetMax();
+ if( pColumn->GetWidthOption() && pColumn->GetMin() )
+ {
+ pColumn->SetMax( nAbsMin * pColumn->GetWidthOption() );
+ sal_uLong nColQuot = pColumn->GetMax() / pColumn->GetMin();
+ if( nColQuot<nQuot )
+ nQuot = nColQuot;
+ }
+ }
+ }
+ OSL_ENSURE( 0==nRel || nQuot!=ULONG_MAX,
+ "Wo sind die relativen Spalten geblieben?" );
+ for( i=0; i<nCols; i++ )
+ {
+ SwHTMLTableLayoutColumn *pColumn = GetColumn( i );
+ if( pColumn->IsRelWidthOption() )
+ {
+ if( pColumn->GetWidthOption() )
+ pColumn->SetMax( pColumn->GetMax() / nQuot );
+ else
+ pColumn->SetMax( pColumn->GetMin() );
+ OSL_ENSURE( pColumn->GetMax() >= pColumn->GetMin(),
+ "Maximale Spaltenbreite kleiner als Minimale" );
+ nMax += pColumn->GetMax();
+ }
+ }
+ }
+ else
+ {
+ sal_uInt16 nRel = 0; // Summe der relativen Breiten aller Spalten
+ sal_uInt16 nRelCols = 0; // Anzahl Spalten mit relativer Angabe
+ sal_uLong nRelMax = 0; // Anteil am Maximum dieser Spalten
+ for( i=0; i<nCols; i++ )
+ {
+ OSL_ENSURE( nRel<=100, "relative Breite aller Spalten>100%" );
+ SwHTMLTableLayoutColumn *pColumn = GetColumn( i );
+ if( pColumn->IsRelWidthOption() && pColumn->GetWidthOption() )
+ {
+ // Sicherstellen, dass die relativen breiten nicht
+ // ueber 100% landen
+ sal_uInt16 nColWidth = pColumn->GetWidthOption();
+ if( nRel+nColWidth > 100 )
+ {
+ nColWidth = 100 - nRel;
+ pColumn->SetWidthOption( nColWidth, sal_True, sal_False );
+ }
+ nRelMax += pColumn->GetMax();
+ nRel = nRel + nColWidth;
+ nRelCols++;
+ }
+ else if( !pColumn->GetMin() )
+ {
+ // Die Spalte ist leer (wurde also auschliesslich
+ // durch COLSPAN erzeugt) und darf deshalb auch
+ // keine %-Breite zugewiesen bekommen.
+ nRelCols++;
+ }
+ }
+
+ // Eventuell noch vorhandene Prozente werden auf die Spalten ohne
+ // eine Breiten-Angabe verteilt. Wie in Netscape werden die
+ // verbleibenden Prozente enstprechend der Verhaeltnisse
+ // der Maximalbreiten der in Frage kommenden Spalten
+ // untereinander verteilt.
+ // ??? Wie beruecksichtigen bei den Maximalbreiten auch Spalten
+ // mit fester Breite. Ist das richtig???
+ if( nRel < 100 && nRelCols < nCols )
+ {
+ sal_uInt16 nRelLeft = 100 - nRel;
+ sal_uLong nFixMax = nMax - nRelMax;
+ for( i=0; i<nCols; i++ )
+ {
+ SwHTMLTableLayoutColumn *pColumn = GetColumn( i );
+ if( !pColumn->IsRelWidthOption() &&
+ !pColumn->GetWidthOption() &&
+ pColumn->GetMin() )
+ {
+ // den Rest bekommt die naechste Spalte
+ sal_uInt16 nColWidth =
+ (sal_uInt16)((pColumn->GetMax() * nRelLeft) / nFixMax);
+ pColumn->SetWidthOption( nColWidth, sal_True, sal_False );
+ }
+ }
+ }
+
+ // nun die Maximalbreiten entsprechend anpassen
+ sal_uLong nQuotMax = ULONG_MAX;
+ sal_uLong nOldMax = nMax;
+ nMax = 0;
+ for( i=0; i<nCols; i++ )
+ {
+ // Spalten mit %-Angaben werden enstprechend angepasst.
+ // Spalten, die
+ // - keine %-Angabe besitzen und in einer Tabelle mit COLS
+ // oder WIDTH vorkommen, oder
+ // - als Breite 0% angegeben haben erhalten die Minimalbreite
+ SwHTMLTableLayoutColumn *pColumn = GetColumn( i );
+ if( pColumn->IsRelWidthOption() && pColumn->GetWidthOption() )
+ {
+ sal_uLong nNewMax;
+ sal_uLong nColQuotMax;
+ if( !nWidthOption )
+ {
+ nNewMax = nOldMax * pColumn->GetWidthOption();
+ nColQuotMax = nNewMax / pColumn->GetMax();
+ }
+ else
+ {
+ nNewMax = nMin * pColumn->GetWidthOption();
+ nColQuotMax = nNewMax / pColumn->GetMin();
+ }
+ pColumn->SetMax( nNewMax );
+ if( nColQuotMax < nQuotMax )
+ nQuotMax = nColQuotMax;
+ }
+ else if( HasColsOption() || nWidthOption ||
+ (pColumn->IsRelWidthOption() &&
+ !pColumn->GetWidthOption()) )
+ pColumn->SetMax( pColumn->GetMin() );
+ }
+ // und durch den Quotienten teilen
+ OSL_ENSURE( nQuotMax!=ULONG_MAX, "Wo sind die relativen Spalten geblieben?" );
+ for( i=0; i<nCols; i++ )
+ {
+ SwHTMLTableLayoutColumn *pColumn = GetColumn( i );
+ if( pColumn->IsRelWidthOption() && pColumn->GetWidthOption() )
+ {
+ if( pColumn->GetWidthOption() )
+ {
+ pColumn->SetMax( pColumn->GetMax() / nQuotMax );
+ OSL_ENSURE( pColumn->GetMax() >= pColumn->GetMin(),
+ "Minimalbreite ein Spalte Groesser Maximum" );
+ if( pColumn->GetMax() < pColumn->GetMin() )
+ pColumn->SetMax( pColumn->GetMin() );
+ }
+ }
+ nMax += pColumn->GetMax();
+ }
+ }
+ }
+
+ delete pConstraints;
+}
+
+// nAbsAvail ist der verfuegbare Platz in TWIPS.
+// nRelAvail ist der auf USHRT_MAX bezogene verfuegbare Platz oder 0
+// nAbsSpace ist der Anteil von nAbsAvail, der durch der umgebende Zelle
+// fur die Umrandung und den Abstand zum Inhalt reserviert ist.
+void SwHTMLTableLayout::AutoLayoutPass2( sal_uInt16 nAbsAvail, sal_uInt16 nRelAvail,
+ sal_uInt16 nAbsLeftSpace,
+ sal_uInt16 nAbsRightSpace,
+ sal_uInt16 nParentInhAbsSpace )
+{
+ // Erstmal fuehren wie jede Menge Plausibilaets-Test durch
+
+ // Eine abolute zur Verfuegung stehende Breite muss immer uebergeben
+ // werden.
+ OSL_ENSURE( nAbsAvail, "AutoLayout Pass 2: Keine absolute Breite gegeben" );
+
+ // Eine realtive zur Verfuegung stehende Breite darf nur und muss fuer
+ // Tabellen in Tabellen uebergeben
+ OSL_ENSURE( IsTopTable() == (nRelAvail==0),
+ "AutoLayout Pass 2: Rel. Breite bei Tab in Tab oder umgekehrt" );
+
+ // Die Minimalbreite der Tabelle darf natuerlich nie groesser sein
+ // als das die Maximalbreite.
+ OSL_ENSURE( nMin<=nMax, "AutoLayout Pass2: nMin > nMax" );
+
+ // Die verfuegbare Breite, fuer die die Tabelle berechnet wurde, merken.
+ // (Dies ist ein guter Ort, denn hier kommer wir bei der Erstberechnung
+ // der Tabelle aus dem Parser und bei jedem _Resize-Aufruf vorbei.)
+ nLastResizeAbsAvail = nAbsAvail;
+
+ // Schritt 1: Der verfuegbar Platz wird an linke/rechte Raender,
+ // vorhandene Filler-Zellen und Abstande angepasst
+
+ // Abstand zum Inhalt und Unrandung
+ sal_uInt16 nAbsLeftFill = 0, nAbsRightFill = 0;
+ if( !IsTopTable() &&
+ GetMin() + nAbsLeftSpace + nAbsRightSpace <= nAbsAvail )
+ {
+ nAbsLeftFill = nAbsLeftSpace;
+ nAbsRightFill = nAbsRightSpace;
+ }
+
+ // Linker und rechter Abstand
+ if( nLeftMargin || nRightMargin )
+ {
+ if( IsTopTable() )
+ {
+ // fuer die Top-Table beruecksichtigen wir die Raender immer,
+ // den die Minimalbreite der Tabelle wird hier nie unterschritten
+ nAbsAvail -= (nLeftMargin + nRightMargin);
+ }
+ else if( GetMin() + nLeftMargin + nRightMargin <= nAbsAvail )
+ {
+ // sonst beruecksichtigen wir die Raender nur, wenn auch Platz
+ // fuer sie da ist (nMin ist hier bereits berechnet!)
+ nAbsLeftFill = nAbsLeftFill + nLeftMargin;
+ nAbsRightFill = nAbsRightFill + nRightMargin;
+ }
+ }
+
+ // Filler-Zellen
+ if( !IsTopTable() )
+ {
+ if( pLeftFillerBox && nAbsLeftFill<MINLAY+nInhLeftBorderWidth )
+ nAbsLeftFill = MINLAY+nInhLeftBorderWidth;
+ if( pRightFillerBox && nAbsRightFill<MINLAY+nInhRightBorderWidth )
+ nAbsRightFill = MINLAY+nInhRightBorderWidth;
+ }
+
+ // Anpassen des verfuegbaren Platzes.
+ nRelLeftFill = 0;
+ nRelRightFill = 0;
+ if( !IsTopTable() && (nAbsLeftFill>0 || nAbsRightFill) )
+ {
+ sal_uLong nAbsLeftFillL = nAbsLeftFill, nAbsRightFillL = nAbsRightFill;
+
+ nRelLeftFill = (sal_uInt16)((nAbsLeftFillL * nRelAvail) / nAbsAvail);
+ nRelRightFill = (sal_uInt16)((nAbsRightFillL * nRelAvail) / nAbsAvail);
+
+ nAbsAvail -= (nAbsLeftFill + nAbsRightFill);
+ if( nRelAvail )
+ nRelAvail -= (nRelLeftFill + nRelRightFill);
+ }
+
+
+ // Schritt 2: Die absolute Tabellenbreite wird berechnet.
+ sal_uInt16 nAbsTabWidth = 0;
+ bUseRelWidth = sal_False;
+ if( nWidthOption )
+ {
+ if( bPrcWidthOption )
+ {
+ OSL_ENSURE( nWidthOption<=100, "Prozentangabe zu gross" );
+ if( nWidthOption > 100 )
+ nWidthOption = 100;
+
+ // Die absolute Breite entspricht den angegeben Prozent der
+ // zur Verfuegung stehenden Breite.
+ // Top-Tabellen bekommen nur eine relative Breite, wenn der
+ // verfuegbare Platz *echt groesser* ist als die Minimalbreite.
+ // ACHTUNG: Das "echte groesser" ist noetig, weil der Wechsel
+ // von einer relativen Breite zu einer absoluten Breite durch
+ // Resize sonst zu einer Endlosschleife fuehrt.
+ // Weil bei Tabellen in Rahmen kein Resize aufgerufen wird,
+ // wenn der Rahmen eine nicht-relative Breite besitzt, koennen
+ // wir da solche Spielchen nicht spielen
+ // Spielen wir solche Spielchen
+ // jetzt doch. Dort war eine Grafik in einer 1%-breiten
+ // Tabelle und hat da natuerlich nicht hineingepasst.
+ nAbsTabWidth = (sal_uInt16)( ((sal_uLong)nAbsAvail * nWidthOption) / 100 );
+ if( IsTopTable() &&
+ ( /*MayBeInFlyFrame() ||*/ (sal_uLong)nAbsTabWidth > nMin ) )
+ {
+ nRelAvail = USHRT_MAX;
+ bUseRelWidth = sal_True;
+ }
+ }
+ else
+ {
+ nAbsTabWidth = nWidthOption;
+ if( nAbsTabWidth > MAX_TABWIDTH )
+ nAbsTabWidth = MAX_TABWIDTH;
+
+ // Tabellen in Tabellen duerfen niemals breiter werden als der
+ // verfuegbare Platz.
+ if( !IsTopTable() && nAbsTabWidth > nAbsAvail )
+ nAbsTabWidth = nAbsAvail;
+ }
+ }
+
+ OSL_ENSURE( IsTopTable() || nAbsTabWidth<=nAbsAvail,
+ "AutoLayout Pass2: nAbsTabWidth > nAbsAvail fuer Tab in Tab" );
+ OSL_ENSURE( !nRelAvail || nAbsTabWidth<=nAbsAvail,
+ "AutoLayout Pass2: nAbsTabWidth > nAbsAvail fuer relative Breite" );
+
+ // Catch fuer die beiden Asserts von oben (man weiss ja nie!)
+ if( (!IsTopTable() || nRelAvail>0) && nAbsTabWidth>nAbsAvail )
+ nAbsTabWidth = nAbsAvail;
+
+
+ // Schritt 3: Bestimmen der Spaltenbreiten und ggf. auch der
+ // absoluten und relativen Tabellenbreiten.
+ if( (!IsTopTable() && nMin > (sal_uLong)nAbsAvail) ||
+ nMin > MAX_TABWIDTH )
+ {
+ // Wenn
+ // - das Minumum einer inneren Tabelle groesser ist als der
+ // verfuegbare Platz, oder
+ // - das Minumum einer Top-Table groesser ist als USHRT_MAX
+ // muss die Tabelle an den verfuegbaren Platz bzw. USHRT_MAX
+ // abgepasst werden. Dabei bleiben die Verhaeltnisse der Breiten
+ // untereinander erhalten.
+
+ nAbsTabWidth = IsTopTable() ? MAX_TABWIDTH : nAbsAvail;
+ nRelTabWidth = (nRelAvail ? nRelAvail : nAbsTabWidth );
+
+ // First of all, we check wether we can fit the layout constrains,
+ // that are: Every cell's width excluding the borders must be at least
+ // MINLAY:
+
+ sal_uLong nRealMin = 0;
+ for( sal_uInt16 i=0; i<nCols; i++ )
+ {
+ sal_uLong nRealColMin = MINLAY, nDummy1, nDummy2;
+ AddBorderWidth( nRealColMin, nDummy1, nDummy2, i, 1 );
+ nRealMin += nRealColMin;
+ }
+ if( (nRealMin >= nAbsTabWidth) || (nRealMin >= nMin) )
+ {
+ // "Nichts geht mehr". We cannot get the minimum column widths
+ // the layout wants to have.
+
+ sal_uInt16 nAbs = 0, nRel = 0;
+ SwHTMLTableLayoutColumn *pColumn;
+ for( sal_uInt16 i=0; i<nCols-1; i++ )
+ {
+ pColumn = GetColumn( i );
+ sal_uLong nColMin = pColumn->GetMin();
+ if( nColMin <= USHRT_MAX )
+ {
+ pColumn->SetAbsColWidth(
+ (sal_uInt16)((nColMin * nAbsTabWidth) / nMin) );
+ pColumn->SetRelColWidth(
+ (sal_uInt16)((nColMin * nRelTabWidth) / nMin) );
+ }
+ else
+ {
+ double nColMinD = nColMin;
+ pColumn->SetAbsColWidth(
+ (sal_uInt16)((nColMinD * nAbsTabWidth) / nMin) );
+ pColumn->SetRelColWidth(
+ (sal_uInt16)((nColMinD * nRelTabWidth) / nMin) );
+ }
+
+ nAbs = nAbs + (sal_uInt16)pColumn->GetAbsColWidth();
+ nRel = nRel + (sal_uInt16)pColumn->GetRelColWidth();
+ }
+ pColumn = GetColumn( nCols-1 );
+ pColumn->SetAbsColWidth( nAbsTabWidth - nAbs );
+ pColumn->SetRelColWidth( nRelTabWidth - nRel );
+ }
+ else
+ {
+ sal_uLong nDistAbs = nAbsTabWidth - nRealMin;
+ sal_uLong nDistRel = nRelTabWidth - nRealMin;
+ sal_uLong nDistMin = nMin - nRealMin;
+ sal_uInt16 nAbs = 0, nRel = 0;
+ SwHTMLTableLayoutColumn *pColumn;
+ for( sal_uInt16 i=0; i<nCols-1; i++ )
+ {
+ pColumn = GetColumn( i );
+ sal_uLong nColMin = pColumn->GetMin();
+ sal_uLong nRealColMin = MINLAY, nDummy1, nDummy2;
+ AddBorderWidth( nRealColMin, nDummy1, nDummy2, i, 1 );
+
+ if( nColMin <= USHRT_MAX )
+ {
+ pColumn->SetAbsColWidth(
+ (sal_uInt16)((((nColMin-nRealColMin) * nDistAbs) / nDistMin) + nRealColMin) );
+ pColumn->SetRelColWidth(
+ (sal_uInt16)((((nColMin-nRealColMin) * nDistRel) / nDistMin) + nRealColMin) );
+ }
+ else
+ {
+ double nColMinD = nColMin;
+ pColumn->SetAbsColWidth(
+ (sal_uInt16)((((nColMinD-nRealColMin) * nDistAbs) / nDistMin) + nRealColMin) );
+ pColumn->SetRelColWidth(
+ (sal_uInt16)((((nColMinD-nRealColMin) * nDistRel) / nDistMin) + nRealColMin) );
+ }
+
+ nAbs = nAbs + (sal_uInt16)pColumn->GetAbsColWidth();
+ nRel = nRel + (sal_uInt16)pColumn->GetRelColWidth();
+ }
+ pColumn = GetColumn( nCols-1 );
+ pColumn->SetAbsColWidth( nAbsTabWidth - nAbs );
+ pColumn->SetRelColWidth( nRelTabWidth - nRel );
+ }
+ }
+ else if( nMax <= (sal_uLong)(nAbsTabWidth ? nAbsTabWidth : nAbsAvail) )
+ {
+ // Wenn
+ // - die Tabelle eine fixe Breite besitzt und das Maximum der
+ // Tabelle kleiner ist, oder
+ // - das Maximum kleiner ist als der verfuegbare Platz
+ // kann das Maximum direkt uebernommen werden bzw. die Tabelle nur
+ // unter Beruecksichtigung des Maxumums an die fixe Breite
+ // angepasst werden.
+
+ // Keine fixe Breite, dann das Maximum nehmen.
+ if( !nAbsTabWidth )
+ nAbsTabWidth = (sal_uInt16)nMax;
+
+ // Eine Top-Table darf auch beriter werden als der verfuegbare Platz.
+ if( nAbsTabWidth > nAbsAvail )
+ {
+ OSL_ENSURE( IsTopTable(),
+ "Tabelle in Tabelle soll breiter werden als umgebende Zelle" );
+ nAbsAvail = nAbsTabWidth;
+ }
+
+ // Nur den Anteil der relativen Breite verwenden, der auch fuer
+ // die absolute Breite verwendet wuerde.
+ sal_uLong nAbsTabWidthL = nAbsTabWidth;
+ nRelTabWidth =
+ ( nRelAvail ? (sal_uInt16)((nAbsTabWidthL * nRelAvail) / nAbsAvail)
+ : nAbsTabWidth );
+
+ // Gibt es Spalten mit und Spalten ohne %-Angabe?
+ sal_uLong nFixMax = nMax;
+ for( sal_uInt16 i=0; i<nCols; i++ )
+ {
+ const SwHTMLTableLayoutColumn *pColumn = GetColumn( i );
+ if( pColumn->IsRelWidthOption() && pColumn->GetWidthOption()>0 )
+ nFixMax -= pColumn->GetMax();
+ }
+
+ if( nFixMax > 0 && nFixMax < nMax )
+ {
+ // ja, dann den zu verteilenden Platz nur auf die Spalten
+ // mit %-Angabe verteilen.
+
+ // In diesem (und nur in diesem) Fall gibt es Spalten,
+ // die ihre Maximalbreite genau einhalten, also weder
+ // schmaler noch breiter werden. Beim zurueckrechnen der
+ // absoluten Breite aus der relativen Breite kann es
+ // zu Rundungsfehlern kommen. Um die auszugeleichen
+ // werden zuerst die fixen Breiten entsprechend korrigiert
+ // eingestellt und erst danach die relativen.
+
+ sal_uInt16 nAbs = 0, nRel = 0;
+ sal_uInt16 nFixedCols = 0;
+ sal_uInt16 i;
+
+ for( i = 0; i < nCols; i++ )
+ {
+ SwHTMLTableLayoutColumn *pColumn = GetColumn( i );
+ if( !pColumn->IsRelWidthOption() || !pColumn->GetWidthOption() )
+ {
+ // Die Spalte behaelt ihre Breite bei.
+ nFixedCols++;
+ sal_uLong nColMax = pColumn->GetMax();
+ pColumn->SetAbsColWidth( (sal_uInt16)nColMax );
+
+ sal_uLong nRelColWidth =
+ (nColMax * nRelTabWidth) / nAbsTabWidth;
+ sal_uLong nChkWidth =
+ (nRelColWidth * nAbsTabWidth) / nRelTabWidth;
+ if( nChkWidth < nColMax )
+ nRelColWidth++;
+ else if( nChkWidth > nColMax )
+ nRelColWidth--;
+ pColumn->SetRelColWidth( (sal_uInt16)nRelColWidth );
+
+ nAbs = nAbs + (sal_uInt16)nColMax;
+ nRel = nRel + (sal_uInt16)nRelColWidth;
+ }
+ }
+
+ // Zu verteilende Anteile des Maximums und der relativen und
+ // absoluten Breiten. nFixMax entspricht an dieser Stelle
+ // nAbs, so dass man gleich nFixMax haette nehmen koennen.
+ // Der Code ist so aber verstaendlicher.
+ OSL_ENSURE( nFixMax == nAbs, "Zwei Schleifen, zwei Summen?" );
+ sal_uLong nDistMax = nMax - nFixMax;
+ sal_uInt16 nDistAbsTabWidth = nAbsTabWidth - nAbs;
+ sal_uInt16 nDistRelTabWidth = nRelTabWidth - nRel;
+
+ for( i=0; i<nCols; i++ )
+ {
+ SwHTMLTableLayoutColumn *pColumn = GetColumn( i );
+ if( pColumn->IsRelWidthOption() && pColumn->GetWidthOption() > 0 )
+ {
+ // Die Spalte wird anteilig breiter.
+ nFixedCols++;
+ if( nFixedCols == nCols )
+ {
+ pColumn->SetAbsColWidth( nAbsTabWidth-nAbs );
+ pColumn->SetRelColWidth( nRelTabWidth-nRel );
+ }
+ else
+ {
+ sal_uLong nColMax = pColumn->GetMax();
+ pColumn->SetAbsColWidth(
+ (sal_uInt16)((nColMax * nDistAbsTabWidth) / nDistMax) );
+ pColumn->SetRelColWidth(
+ (sal_uInt16)((nColMax * nDistRelTabWidth) / nDistMax) );
+ }
+ nAbs = nAbs + pColumn->GetAbsColWidth();
+ nRel = nRel + pColumn->GetRelColWidth();
+ }
+ }
+ OSL_ENSURE( nCols==nFixedCols, "Spalte vergessen!" );
+ }
+ else
+ {
+ // nein, dann den zu verteilenden Platz auf alle Spalten
+ // gleichmaessig vertilen.
+ for( sal_uInt16 i=0; i<nCols; i++ )
+ {
+ sal_uLong nColMax = GetColumn( i )->GetMax();
+ GetColumn( i )->SetAbsColWidth(
+ (sal_uInt16)((nColMax * nAbsTabWidth) / nMax) );
+ GetColumn( i )->SetRelColWidth(
+ (sal_uInt16)((nColMax * nRelTabWidth) / nMax) );
+ }
+ }
+ }
+ else
+ {
+ // den ueber die Minimalbreite herausgehenden Platz entsprechend
+ // den einzelnen Spalten anteilig zuschlagen
+ if( !nAbsTabWidth )
+ nAbsTabWidth = nAbsAvail;
+ if( nAbsTabWidth < nMin )
+ nAbsTabWidth = (sal_uInt16)nMin;
+
+ if( nAbsTabWidth > nAbsAvail )
+ {
+ OSL_ENSURE( IsTopTable(),
+ "Tabelle in Tabelle soll breiter werden als Platz da ist" );
+ nAbsAvail = nAbsTabWidth;
+ }
+
+ sal_uLong nAbsTabWidthL = nAbsTabWidth;
+ nRelTabWidth =
+ ( nRelAvail ? (sal_uInt16)((nAbsTabWidthL * nRelAvail) / nAbsAvail)
+ : nAbsTabWidth );
+ double nW = nAbsTabWidth - nMin;
+ double nD = (nMax==nMin ? 1 : nMax-nMin);
+ sal_uInt16 nAbs = 0, nRel = 0;
+ for( sal_uInt16 i=0; i<nCols-1; i++ )
+ {
+ double nd = GetColumn( i )->GetMax() - GetColumn( i )->GetMin();
+ sal_uLong nAbsColWidth = GetColumn( i )->GetMin() + (sal_uLong)((nd*nW)/nD);
+ sal_uLong nRelColWidth = nRelAvail
+ ? (nAbsColWidth * nRelTabWidth) / nAbsTabWidth
+ : nAbsColWidth;
+
+ GetColumn( i )->SetAbsColWidth( (sal_uInt16)nAbsColWidth );
+ GetColumn( i )->SetRelColWidth( (sal_uInt16)nRelColWidth );
+ nAbs = nAbs + (sal_uInt16)nAbsColWidth;
+ nRel = nRel + (sal_uInt16)nRelColWidth;
+ }
+ GetColumn( nCols-1 )->SetAbsColWidth( nAbsTabWidth - nAbs );
+ GetColumn( nCols-1 )->SetRelColWidth( nRelTabWidth - nRel );
+
+ }
+
+ // Schritt 4: Fuer Tabellen in Tabellen kann es links und/oder rechts
+ // noch Ausgleichzellen geben. Deren Breite wird jetzt berechnet.
+ nInhAbsLeftSpace = 0;
+ nInhAbsRightSpace = 0;
+ if( !IsTopTable() && (nRelLeftFill>0 || nRelRightFill>0 ||
+ nAbsTabWidth<nAbsAvail) )
+ {
+ // Die Breite von zusaetzlichen Zellen zur Ausrichtung der
+ // inneren Tabelle bestimmen
+ sal_uInt16 nAbsDist = (sal_uInt16)(nAbsAvail-nAbsTabWidth);
+ sal_uInt16 nRelDist = (sal_uInt16)(nRelAvail-nRelTabWidth);
+ sal_uInt16 nParentInhAbsLeftSpace = 0, nParentInhAbsRightSpace = 0;
+
+ // Groesse und Position der zusaetzlichen Zellen bestimmen
+ switch( eTableAdjust )
+ {
+ case SVX_ADJUST_RIGHT:
+ nAbsLeftFill = nAbsLeftFill + nAbsDist;
+ nRelLeftFill = nRelLeftFill + nRelDist;
+ nParentInhAbsLeftSpace = nParentInhAbsSpace;
+ break;
+ case SVX_ADJUST_CENTER:
+ {
+ sal_uInt16 nAbsLeftDist = nAbsDist / 2;
+ nAbsLeftFill = nAbsLeftFill + nAbsLeftDist;
+ nAbsRightFill += nAbsDist - nAbsLeftDist;
+ sal_uInt16 nRelLeftDist = nRelDist / 2;
+ nRelLeftFill = nRelLeftFill + nRelLeftDist;
+ nRelRightFill += nRelDist - nRelLeftDist;
+ nParentInhAbsLeftSpace = nParentInhAbsSpace / 2;
+ nParentInhAbsRightSpace = nParentInhAbsSpace -
+ nParentInhAbsLeftSpace;
+ }
+ break;
+ case SVX_ADJUST_LEFT:
+ default:
+ nAbsRightFill = nAbsRightFill + nAbsDist;
+ nRelRightFill = nRelRightFill + nRelDist;
+ nParentInhAbsRightSpace = nParentInhAbsSpace;
+ break;
+ }
+
+ OSL_ENSURE( !pLeftFillerBox || nRelLeftFill>0,
+ "Fuer linke Filler-Box ist keine Breite da!" );
+ OSL_ENSURE( !pRightFillerBox || nRelRightFill>0,
+ "Fuer rechte Filler-Box ist keine Breite da!" );
+
+ // Filler-Breiten werden auf die ausseren Spalten geschlagen, wenn
+ // es nach dem ersten Durchlauf keine Boxen fuer sie gibt (nWidth>0)
+ // oder ihre Breite zu klein wuerde oder wenn es COL-Tags gibt und
+ // die Filler-Breite der Umrandung-Breite entspricht (dann haben wir
+ // die Tabelle wahrscheinlich selbst exportiert)
+ if( nRelLeftFill && !pLeftFillerBox &&
+ ( nWidthSet>0 || nAbsLeftFill<MINLAY+nInhLeftBorderWidth ||
+ (HasColTags() && nAbsLeftFill < nAbsLeftSpace+nParentInhAbsLeftSpace+20) ) )
+ {
+ SwHTMLTableLayoutColumn *pColumn = GetColumn( 0 );
+ pColumn->SetAbsColWidth( pColumn->GetAbsColWidth()+nAbsLeftFill );
+ pColumn->SetRelColWidth( pColumn->GetRelColWidth()+nRelLeftFill );
+ nRelLeftFill = 0;
+ nInhAbsLeftSpace = nAbsLeftSpace + nParentInhAbsLeftSpace;
+ }
+ if( nRelRightFill && !pRightFillerBox &&
+ ( nWidthSet>0 || nAbsRightFill<MINLAY+nInhRightBorderWidth ||
+ (HasColTags() && nAbsRightFill < nAbsRightSpace+nParentInhAbsRightSpace+20) ) )
+ {
+ SwHTMLTableLayoutColumn *pColumn = GetColumn( nCols-1 );
+ pColumn->SetAbsColWidth( pColumn->GetAbsColWidth()+nAbsRightFill );
+ pColumn->SetRelColWidth( pColumn->GetRelColWidth()+nRelRightFill );
+ nRelRightFill = 0;
+ nInhAbsRightSpace = nAbsRightSpace + nParentInhAbsRightSpace;
+ }
+ }
+}
+
+static sal_Bool lcl_ResizeLine( const SwTableLine*& rpLine, void* pPara );
+
+static sal_Bool lcl_ResizeBox( const SwTableBox*& rpBox, void* pPara )
+{
+ sal_uInt16 *pWidth = (sal_uInt16 *)pPara;
+
+ if( !rpBox->GetSttNd() )
+ {
+ sal_uInt16 nWidth = 0;
+ ((SwTableBox *)rpBox)->GetTabLines().ForEach( &lcl_ResizeLine, &nWidth );
+ rpBox->GetFrmFmt()->SetFmtAttr( SwFmtFrmSize( ATT_VAR_SIZE, nWidth, 0 ));
+ *pWidth = *pWidth + nWidth;
+ }
+ else
+ {
+ *pWidth = *pWidth + (sal_uInt16)rpBox->GetFrmFmt()->GetFrmSize().GetSize().Width();
+ }
+
+ return sal_True;
+}
+
+static sal_Bool lcl_ResizeLine( const SwTableLine*& rpLine, void* pPara )
+{
+ sal_uInt16 *pWidth = (sal_uInt16 *)pPara;
+#if OSL_DEBUG_LEVEL > 1
+ sal_uInt16 nOldWidth = *pWidth;
+#endif
+ *pWidth = 0;
+ ((SwTableLine *)rpLine)->GetTabBoxes().ForEach( &lcl_ResizeBox, pWidth );
+
+#if OSL_DEBUG_LEVEL > 1
+ OSL_ENSURE( !nOldWidth || Abs(*pWidth-nOldWidth) < COLFUZZY,
+ "Zeilen einer Box sind unterschiedlich lang" );
+#endif
+
+ return sal_True;
+}
+
+void SwHTMLTableLayout::SetWidths( sal_Bool bCallPass2, sal_uInt16 nAbsAvail,
+ sal_uInt16 nRelAvail, sal_uInt16 nAbsLeftSpace,
+ sal_uInt16 nAbsRightSpace,
+ sal_uInt16 nParentInhAbsSpace )
+{
+ // SetWidth muss am Ende einmal mehr fuer jede Zelle durchlaufen
+ // worden sein.
+ nWidthSet++;
+
+ // Schritt 0: Wenn noetig, wird hier noch der Pass2 des Layout-Alogithmus
+ // aufgerufen.
+ if( bCallPass2 )
+ AutoLayoutPass2( nAbsAvail, nRelAvail, nAbsLeftSpace, nAbsRightSpace,
+ nParentInhAbsSpace );
+
+ // Schritt 1: Setzten der neuen Breite an allen Content-Boxen.
+ // Da die Boxen nichts von der HTML-Tabellen-Struktur wissen, wird
+ // ueber die HTML-Tabellen-Struktur iteriert. Fuer Tabellen in Tabellen
+ // in Tabellen wird rekursiv SetWidth aufgerufen.
+ for( sal_uInt16 i=0; i<nRows; i++ )
+ {
+ for( sal_uInt16 j=0; j<nCols; j++ )
+ {
+ SwHTMLTableLayoutCell *pCell = GetCell( i, j );
+
+ SwHTMLTableLayoutCnts* pCntnts = pCell->GetContents();
+ while( pCntnts && !pCntnts->IsWidthSet(nWidthSet) )
+ {
+ SwTableBox *pBox = pCntnts->GetTableBox();
+ if( pBox )
+ {
+ SetBoxWidth( pBox, j, pCell->GetColSpan() );
+ }
+ else
+ {
+ sal_uInt16 nAbs = 0, nRel = 0, nLSpace = 0, nRSpace = 0,
+ nInhSpace = 0;
+ if( bCallPass2 )
+ {
+ sal_uInt16 nColSpan = pCell->GetColSpan();
+ GetAvail( j, nColSpan, nAbs, nRel );
+ nLSpace = GetLeftCellSpace( j, nColSpan );
+ nRSpace = GetRightCellSpace( j, nColSpan );
+ nInhSpace = GetInhCellSpace( j, nColSpan );
+ }
+ pCntnts->GetTable()->SetWidths( bCallPass2, nAbs, nRel,
+ nLSpace, nRSpace,
+ nInhSpace );
+ }
+
+ pCntnts->SetWidthSet( nWidthSet );
+ pCntnts = pCntnts->GetNext();
+ }
+ }
+ }
+
+ // Schritt 2: Wenn eine Top-Tabelle vorliegt, werden jetzt die Formate
+ // der Nicht-Content-Boxen angepasst. Da diese aufgrund der
+ // Garbage-Collection in der HTML-Tabelle nicht bekannt sind, muessen
+ // wir hier ueber die Tabelle iterieren. Bei der Gelegenheit wird auch
+ // das Tabellen-Frameformat angepasst. Fuer Tabellen in Tabellen werden
+ // stattdessen die Breiten der Filler-Zellen gesetzt.
+ if( IsTopTable() )
+ {
+ sal_uInt16 nCalcTabWidth = 0;
+ ((SwTable *)pSwTable)->GetTabLines().ForEach( &lcl_ResizeLine,
+ &nCalcTabWidth );
+ OSL_ENSURE( Abs( nRelTabWidth-nCalcTabWidth ) < COLFUZZY,
+ "Tabellebreite stimmt nicht mit Zeilenbreite ueberein." );
+
+ // Beim Anpassen des Tabellen-Formats dieses locken, weil sonst
+ // die Boxformate erneut angepasst werden. Ausserdem muss eine
+ // evtl. vorhandene %-Angabe in jedem Fall erhalten bleiben.
+ SwFrmFmt *pFrmFmt = pSwTable->GetFrmFmt();
+ ((SwTable *)pSwTable)->LockModify();
+ SwFmtFrmSize aFrmSize( pFrmFmt->GetFrmSize() );
+ aFrmSize.SetWidth( nRelTabWidth );
+ sal_Bool bRel = bUseRelWidth &&
+ text::HoriOrientation::FULL!=pFrmFmt->GetHoriOrient().GetHoriOrient();
+ aFrmSize.SetWidthPercent( (sal_uInt8)(bRel ? nWidthOption : 0) );
+ pFrmFmt->SetFmtAttr( aFrmSize );
+ ((SwTable *)pSwTable)->UnlockModify();
+
+ // Wenn die Tabelle in einem Rahmen steht, muss auch noch dessen
+ // breite angepasst werden.
+ if( MayBeInFlyFrame() )
+ {
+ SwFrmFmt *pFlyFrmFmt = FindFlyFrmFmt();
+ if( pFlyFrmFmt )
+ {
+ SwFmtFrmSize aFlyFrmSize( ATT_VAR_SIZE, nRelTabWidth, MINLAY );
+
+ if( bUseRelWidth )
+ {
+ // Bei %-Angaben wird die Breite auf das Minimum gesetzt.
+ aFlyFrmSize.SetWidth( nMin > USHRT_MAX ? USHRT_MAX
+ : nMin );
+ aFlyFrmSize.SetWidthPercent( (sal_uInt8)nWidthOption );
+ }
+ pFlyFrmFmt->SetFmtAttr( aFlyFrmSize );
+ }
+ }
+
+#if OSL_DEBUG_LEVEL > 1
+ {
+ // steht im tblrwcl.cxx
+ extern void _CheckBoxWidth( const SwTableLine&, SwTwips );
+
+ // checke doch mal ob die Tabellen korrekte Breiten haben
+ SwTwips nSize = pSwTable->GetFrmFmt()->GetFrmSize().GetWidth();
+ const SwTableLines& rLines = pSwTable->GetTabLines();
+ for( sal_uInt16 n = 0; n < rLines.Count(); ++n )
+ _CheckBoxWidth( *rLines[ n ], nSize );
+ }
+#endif
+
+ }
+ else
+ {
+ if( pLeftFillerBox )
+ {
+ pLeftFillerBox->GetFrmFmt()->SetFmtAttr(
+ SwFmtFrmSize( ATT_VAR_SIZE, nRelLeftFill, 0 ));
+ }
+ if( pRightFillerBox )
+ {
+ pRightFillerBox->GetFrmFmt()->SetFmtAttr(
+ SwFmtFrmSize( ATT_VAR_SIZE, nRelRightFill, 0 ));
+ }
+ }
+}
+
+void SwHTMLTableLayout::_Resize( sal_uInt16 nAbsAvail, sal_Bool bRecalc )
+{
+ // Wenn bRecalc gestzt ist, hat sich am Inhalt der Tabelle etwas
+ // geaendert. Es muss dann der erste Pass noch einmal durchgefuehrt
+ // werden.
+ if( bRecalc )
+ AutoLayoutPass1();
+
+ SwRootFrm *pRoot = (SwRootFrm*)GetDoc()->GetCurrentViewShell()->GetLayout();
+ if ( pRoot && pRoot->IsCallbackActionEnabled() )
+ pRoot->StartAllAction(); //swmod 071108//swmod 071225
+
+ // Sonst koennen die Breiten gesetzt werden, wobei zuvor aber jewils
+ // noch der Pass 2 laufen muss.
+ SetWidths( sal_True, nAbsAvail );
+
+ if ( pRoot && pRoot->IsCallbackActionEnabled() )
+ pRoot->EndAllAction( sal_True ); //True per VirDev (Browsen ruhiger) //swmod 071108//swmod 071225
+}
+
+IMPL_STATIC_LINK( SwHTMLTableLayout, DelayedResize_Impl, void*, EMPTYARG )
+{
+ pThis->aResizeTimer.Stop();
+ pThis->_Resize( pThis->nDelayedResizeAbsAvail,
+ pThis->bDelayedResizeRecalc );
+
+ return 0;
+}
+
+
+sal_Bool SwHTMLTableLayout::Resize( sal_uInt16 nAbsAvail, sal_Bool bRecalc,
+ sal_Bool bForce, sal_uLong nDelay )
+{
+ if( 0 == nAbsAvail )
+ return sal_False;
+ OSL_ENSURE( IsTopTable(), "Resize darf nur an Top-Tabellen aufgerufen werden" );
+
+ // Darf die Tabelle uberhaupt Resized werden oder soll sie es trotzdem?
+ if( bMustNotResize && !bForce )
+ return sal_False;
+
+ // Darf ein Recalc der Tabelle durchgefuehrt werden?
+ if( bMustNotRecalc && !bForce )
+ bRecalc = sal_False;
+
+ const SwDoc *pDoc = GetDoc();
+
+ // Wenn es ein Layout gibt, wurde evtl. die Groesse der Root-Frames
+ // und nicht die der VisArea uebergeben. Wenn wir nicht in einem Rahmen
+ // stehen, muss die Tabelle allerdings fuer die VisArea berechnet werden,
+ // weil sond die Umschaltung von relativ nach absolut nicht funktioniert.
+ if( pDoc->GetCurrentViewShell() && pDoc->GetCurrentViewShell()->GetViewOptions()->getBrowseMode() )
+ {
+ const sal_uInt16 nVisAreaWidth = GetBrowseWidthByVisArea( *pDoc );
+ if( nVisAreaWidth < nAbsAvail && !FindFlyFrmFmt() )
+ nAbsAvail = nVisAreaWidth;
+ }
+
+ if( nDelay==0 && aResizeTimer.IsActive() )
+ {
+ // Wenn beim Aufruf eines synchronen Resize noch ein asynchrones
+ // Resize aussteht, dann werden nur die neuen Werte uebernommen.
+
+ bRecalc |= bDelayedResizeRecalc;
+ nDelayedResizeAbsAvail = nAbsAvail;
+ return sal_False;
+ }
+
+ // Optimierung:
+ // Wenn die Minima/Maxima nicht neu berechnet werden sollen und
+ // - die Breite der Tabelle nie neu berechnet werden muss, oder
+ // - die Tabelle schon fuer die uebergebene Breite berechnet wurde, oder
+ // - der verfuegbare Platz kleiner oder gleich der Minimalbreite ist
+ // und die Tabelle bereits die Minimalbreite besitzt, oder
+ // - der verfuegbare Platz groesser ist als die Maximalbreite und
+ // die Tabelle bereits die Maximalbreite besitzt
+ // wird sich an der Tabelle nichts aendern.
+ if( !bRecalc && ( !bMustResize ||
+ (nLastResizeAbsAvail==nAbsAvail) ||
+ (nAbsAvail<=nMin && nRelTabWidth==nMin) ||
+ (!bPrcWidthOption && nAbsAvail>=nMax && nRelTabWidth==nMax) ) )
+ return sal_False;
+
+ if( nDelay==HTMLTABLE_RESIZE_NOW )
+ {
+ if( aResizeTimer.IsActive() )
+ aResizeTimer.Stop();
+ _Resize( nAbsAvail, bRecalc );
+ }
+ else if( nDelay > 0 )
+ {
+ nDelayedResizeAbsAvail = nAbsAvail;
+ bDelayedResizeRecalc = bRecalc;
+ aResizeTimer.SetTimeout( nDelay );
+ aResizeTimer.Start();
+ }
+ else
+ {
+ _Resize( nAbsAvail, bRecalc );
+ }
+
+ return sal_True;
+}
+
+void SwHTMLTableLayout::BordersChanged( sal_uInt16 nAbsAvail, sal_Bool bRecalc )
+{
+ bBordersChanged = sal_True;
+
+ Resize( nAbsAvail, bRecalc );
+}
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/doc/lineinfo.cxx b/sw/source/core/doc/lineinfo.cxx
new file mode 100644
index 000000000000..3fa6e2e0867d
--- /dev/null
+++ b/sw/source/core/doc/lineinfo.cxx
@@ -0,0 +1,159 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+#include "doc.hxx"
+#include "lineinfo.hxx"
+#include "charfmt.hxx"
+#include "poolfmt.hxx"
+#include "rootfrm.hxx"
+#include "viewsh.hxx"
+#include <set>
+void SwDoc::SetLineNumberInfo( const SwLineNumberInfo &rNew )
+{
+ SwRootFrm* pTmpRoot = GetCurrentLayout();//swmod 080219
+ if ( pTmpRoot &&
+ (rNew.IsCountBlankLines() != pLineNumberInfo->IsCountBlankLines() ||
+ rNew.IsRestartEachPage() != pLineNumberInfo->IsRestartEachPage()) )
+ {
+ std::set<SwRootFrm*> aAllLayouts = GetAllLayouts();//swmod 080225
+ pTmpRoot->StartAllAction();
+ // FME 2007-08-14 #i80120# Invalidate size, because ChgThisLines()
+ // is only (onny may only be) called by the formatting routines
+ //pTmpRoot->InvalidateAllCntnt( INV_LINENUM | INV_SIZE );
+ std::for_each( aAllLayouts.begin(), aAllLayouts.end(),std::bind2nd(std::mem_fun(&SwRootFrm::InvalidateAllCntnt), INV_LINENUM | INV_SIZE));//swmod 080226
+ pTmpRoot->EndAllAction();
+ } //swmod 080219
+ *pLineNumberInfo = rNew;
+ SetModified();
+}
+
+const SwLineNumberInfo& SwDoc::GetLineNumberInfo() const
+{
+ return *pLineNumberInfo;
+}
+
+SwLineNumberInfo::SwLineNumberInfo() :
+ nPosFromLeft( MM50 ),
+ nCountBy( 5 ),
+ nDividerCountBy( 3 ),
+ ePos( LINENUMBER_POS_LEFT ),
+ bPaintLineNumbers( sal_False ),
+ bCountBlankLines( sal_True ),
+ bCountInFlys( sal_False ),
+ bRestartEachPage( sal_False )
+{
+}
+
+SwLineNumberInfo::SwLineNumberInfo(const SwLineNumberInfo &rCpy ) : SwClient(),
+ aType( rCpy.GetNumType() ),
+ aDivider( rCpy.GetDivider() ),
+ nPosFromLeft( rCpy.GetPosFromLeft() ),
+ nCountBy( rCpy.GetCountBy() ),
+ nDividerCountBy( rCpy.GetDividerCountBy() ),
+ ePos( rCpy.GetPos() ),
+ bPaintLineNumbers( rCpy.IsPaintLineNumbers() ),
+ bCountBlankLines( rCpy.IsCountBlankLines() ),
+ bCountInFlys( rCpy.IsCountInFlys() ),
+ bRestartEachPage( rCpy.IsRestartEachPage() )
+{
+ if ( rCpy.GetRegisteredIn() )
+ ((SwModify*)rCpy.GetRegisteredIn())->Add( this );
+}
+
+SwLineNumberInfo& SwLineNumberInfo::operator=(const SwLineNumberInfo &rCpy)
+{
+ if ( rCpy.GetRegisteredIn() )
+ ((SwModify*)rCpy.GetRegisteredIn())->Add( this );
+ else if ( GetRegisteredIn() )
+ GetRegisteredInNonConst()->Remove( this );
+
+ aType = rCpy.GetNumType();
+ aDivider = rCpy.GetDivider();
+ nPosFromLeft = rCpy.GetPosFromLeft();
+ nCountBy = rCpy.GetCountBy();
+ nDividerCountBy = rCpy.GetDividerCountBy();
+ ePos = rCpy.GetPos();
+ bPaintLineNumbers = rCpy.IsPaintLineNumbers();
+ bCountBlankLines = rCpy.IsCountBlankLines();
+ bCountInFlys = rCpy.IsCountInFlys();
+ bRestartEachPage = rCpy.IsRestartEachPage();
+
+ return *this;
+}
+
+sal_Bool SwLineNumberInfo::operator==( const SwLineNumberInfo& rInf ) const
+{
+ return GetRegisteredIn() == rInf.GetRegisteredIn() &&
+ aType.GetNumberingType() == rInf.GetNumType().GetNumberingType() &&
+ aDivider == rInf.GetDivider() &&
+ nPosFromLeft == rInf.GetPosFromLeft() &&
+ nCountBy == rInf.GetCountBy() &&
+ nDividerCountBy == rInf.GetDividerCountBy() &&
+ ePos == rInf.GetPos() &&
+ bPaintLineNumbers == rInf.IsPaintLineNumbers() &&
+ bCountBlankLines == rInf.IsCountBlankLines() &&
+ bCountInFlys == rInf.IsCountInFlys() &&
+ bRestartEachPage == rInf.IsRestartEachPage();
+}
+
+
+SwCharFmt* SwLineNumberInfo::GetCharFmt( IDocumentStylePoolAccess& rIDSPA ) const
+{
+ if ( !GetRegisteredIn() )
+ {
+ SwCharFmt* pFmt = rIDSPA.GetCharFmtFromPool( RES_POOLCHR_LINENUM );
+ pFmt->Add( (SwClient*)this );
+ }
+ return (SwCharFmt*)GetRegisteredIn();
+}
+
+void SwLineNumberInfo::SetCharFmt( SwCharFmt *pChFmt )
+{
+ OSL_ENSURE( pChFmt, "SetCharFmt, 0 is not a valid pointer" );
+ pChFmt->Add( this );
+}
+
+void SwLineNumberInfo::Modify( const SfxPoolItem* pOld, const SfxPoolItem* pNew )
+{
+ CheckRegistration( pOld, pNew );
+ SwDoc *pDoc = ((SwCharFmt*)GetRegisteredIn())->GetDoc();
+ SwRootFrm* pRoot = pDoc->GetCurrentLayout();
+ if( pRoot )
+ {
+ pRoot->StartAllAction();
+ std::set<SwRootFrm*> aAllLayouts = pDoc->GetAllLayouts();
+ std::for_each( aAllLayouts.begin(), aAllLayouts.end(),std::mem_fun(&SwRootFrm::AllAddPaintRect));//swmod 080305
+ //pRoot->GetCurrShell()->AddPaintRect( pRoot->Frm() );
+ pRoot->EndAllAction();
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/doc/list.cxx b/sw/source/core/doc/list.cxx
new file mode 100644
index 000000000000..3fc2ee0500dd
--- /dev/null
+++ b/sw/source/core/doc/list.cxx
@@ -0,0 +1,293 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#include "precompiled_sw.hxx"
+
+#include <list.hxx>
+
+#include <vector>
+#include <numrule.hxx>
+#include <ndarr.hxx>
+#include <node.hxx>
+#include <pam.hxx>
+#include <SwNodeNum.hxx>
+
+// ----------------------------------------------------------------------------
+// SwListImpl
+// implementation class for SwList
+// ----------------------------------------------------------------------------
+class SwListImpl
+{
+ public:
+ SwListImpl( const String sListId,
+ SwNumRule& rDefaultListStyle,
+ const SwNodes& rNodes );
+ ~SwListImpl();
+
+ const String GetListId() const;
+
+ const String GetDefaultListStyleName() const;
+
+ void InsertListItem( SwNodeNum& rNodeNum,
+ const int nLevel );
+ void RemoveListItem( SwNodeNum& rNodeNum );
+
+ void InvalidateListTree();
+ void ValidateListTree();
+
+ void MarkListLevel( const int nListLevel,
+ const sal_Bool bValue );
+
+ bool IsListLevelMarked( const int nListLevel ) const;
+
+ private:
+ // unique identifier of the list
+ const String msListId;
+ // default list style for the list items, identified by the list style name
+ String msDefaultListStyleName;
+
+ // list trees for certain document ranges
+ typedef std::pair<SwNodeNum*, SwPaM*> tListTreeForRange;
+ typedef std::vector<tListTreeForRange> tListTrees;
+ tListTrees maListTrees;
+
+ int mnMarkedListLevel;
+
+ void NotifyItemsOnListLevel( const int nLevel );
+};
+
+SwListImpl::SwListImpl( const String sListId,
+ SwNumRule& rDefaultListStyle,
+ const SwNodes& rNodes )
+ : msListId( sListId ),
+ msDefaultListStyleName( rDefaultListStyle.GetName() ),
+ maListTrees(),
+ mnMarkedListLevel( MAXLEVEL )
+{
+ // create empty list trees for the document ranges
+ const SwNode* pNode = rNodes[0];
+ do
+ {
+ SwPaM aPam( *pNode, *pNode->EndOfSectionNode() );
+
+ SwNodeNum* pNumberTreeRootNode = new SwNodeNum( &rDefaultListStyle );
+ SwPaM* pPam = new SwPaM( *(aPam.Start()), *(aPam.End()) );
+ tListTreeForRange aListTreeForRange( pNumberTreeRootNode, pPam );
+ maListTrees.push_back( aListTreeForRange );
+
+ pNode = pNode->EndOfSectionNode();
+ if (pNode != &rNodes.GetEndOfContent())
+ {
+ sal_uLong nIndex = pNode->GetIndex();
+ nIndex++;
+ pNode = rNodes[nIndex];
+ }
+ }
+ while ( pNode != &rNodes.GetEndOfContent() );
+}
+
+SwListImpl::~SwListImpl()
+{
+ tListTrees::iterator aNumberTreeIter;
+ for ( aNumberTreeIter = maListTrees.begin();
+ aNumberTreeIter != maListTrees.end();
+ ++aNumberTreeIter )
+ {
+ SwNodeNum::HandleNumberTreeRootNodeDelete( *((*aNumberTreeIter).first) );
+ delete (*aNumberTreeIter).first;
+ delete (*aNumberTreeIter).second;
+ }
+}
+
+const String SwListImpl::GetListId() const
+{
+ return msListId;
+}
+
+const String SwListImpl::GetDefaultListStyleName() const
+{
+ return msDefaultListStyleName;
+}
+
+void SwListImpl::InsertListItem( SwNodeNum& rNodeNum,
+ const int nLevel )
+{
+ const SwPosition aPosOfNodeNum( rNodeNum.GetPosition() );
+ const SwNodes* pNodesOfNodeNum = &(aPosOfNodeNum.nNode.GetNode().GetNodes());
+
+ tListTrees::const_iterator aNumberTreeIter;
+ for ( aNumberTreeIter = maListTrees.begin();
+ aNumberTreeIter != maListTrees.end();
+ ++aNumberTreeIter )
+ {
+ const SwPosition* pStart = (*aNumberTreeIter).second->Start();
+ const SwPosition* pEnd = (*aNumberTreeIter).second->End();
+ const SwNodes* pRangeNodes = &(pStart->nNode.GetNode().GetNodes());
+
+ if ( pRangeNodes == pNodesOfNodeNum &&
+ *pStart <= aPosOfNodeNum && aPosOfNodeNum <= *pEnd)
+ {
+ (*aNumberTreeIter).first->AddChild( &rNodeNum, nLevel );
+
+ break;
+ }
+ }
+}
+
+void SwListImpl::RemoveListItem( SwNodeNum& rNodeNum )
+{
+ rNodeNum.RemoveMe();
+}
+
+void SwListImpl::InvalidateListTree()
+{
+ tListTrees::iterator aNumberTreeIter;
+ for ( aNumberTreeIter = maListTrees.begin();
+ aNumberTreeIter != maListTrees.end();
+ ++aNumberTreeIter )
+ {
+ (*aNumberTreeIter).first->InvalidateTree();
+ }
+}
+
+void SwListImpl::ValidateListTree()
+{
+ tListTrees::iterator aNumberTreeIter;
+ for ( aNumberTreeIter = maListTrees.begin();
+ aNumberTreeIter != maListTrees.end();
+ ++aNumberTreeIter )
+ {
+ (*aNumberTreeIter).first->NotifyInvalidChildren();
+ }
+}
+
+void SwListImpl::MarkListLevel( const int nListLevel,
+ const sal_Bool bValue )
+{
+ if ( bValue )
+ {
+ if ( nListLevel != mnMarkedListLevel )
+ {
+ if ( mnMarkedListLevel != MAXLEVEL )
+ {
+ // notify former marked list nodes
+ NotifyItemsOnListLevel( mnMarkedListLevel );
+ }
+
+ mnMarkedListLevel = nListLevel;
+
+ // notify new marked list nodes
+ NotifyItemsOnListLevel( mnMarkedListLevel );
+ }
+ }
+ else
+ {
+ if ( mnMarkedListLevel != MAXLEVEL )
+ {
+ // notify former marked list nodes
+ NotifyItemsOnListLevel( mnMarkedListLevel );
+ }
+
+ mnMarkedListLevel = MAXLEVEL;
+ }
+}
+
+bool SwListImpl::IsListLevelMarked( const int nListLevel ) const
+{
+ return nListLevel == mnMarkedListLevel;
+}
+
+void SwListImpl::NotifyItemsOnListLevel( const int nLevel )
+{
+ tListTrees::iterator aNumberTreeIter;
+ for ( aNumberTreeIter = maListTrees.begin();
+ aNumberTreeIter != maListTrees.end();
+ ++aNumberTreeIter )
+ {
+ (*aNumberTreeIter).first->NotifyNodesOnListLevel( nLevel );
+ }
+}
+
+// ----------------------------------------------------------------------------
+// SwList
+// ----------------------------------------------------------------------------
+SwList::SwList( const String sListId,
+ SwNumRule& rDefaultListStyle,
+ const SwNodes& rNodes )
+ : mpListImpl( new SwListImpl( sListId, rDefaultListStyle, rNodes ) )
+{
+}
+
+SwList::~SwList()
+{
+ delete mpListImpl;
+}
+
+const String SwList::GetListId() const
+{
+ return mpListImpl->GetListId();
+}
+
+const String SwList::GetDefaultListStyleName() const
+{
+ return mpListImpl->GetDefaultListStyleName();
+}
+
+void SwList::InsertListItem( SwNodeNum& rNodeNum,
+ const int nLevel )
+{
+ mpListImpl->InsertListItem( rNodeNum, nLevel );
+}
+
+void SwList::RemoveListItem( SwNodeNum& rNodeNum )
+{
+ mpListImpl->RemoveListItem( rNodeNum );
+}
+
+void SwList::InvalidateListTree()
+{
+ mpListImpl->InvalidateListTree();
+}
+
+void SwList::ValidateListTree()
+{
+ mpListImpl->ValidateListTree();
+}
+
+void SwList::MarkListLevel( const int nListLevel,
+ const sal_Bool bValue )
+{
+ mpListImpl->MarkListLevel( nListLevel, bValue );
+}
+
+bool SwList::IsListLevelMarked( const int nListLevel ) const
+{
+ return mpListImpl->IsListLevelMarked( nListLevel );
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/doc/notxtfrm.cxx b/sw/source/core/doc/notxtfrm.cxx
new file mode 100644
index 000000000000..d00e8d6415c8
--- /dev/null
+++ b/sw/source/core/doc/notxtfrm.cxx
@@ -0,0 +1,1046 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+
+#include <hintids.hxx>
+#include <tools/urlobj.hxx>
+#include <vcl/print.hxx>
+#include <vcl/virdev.hxx>
+#include <vcl/svapp.hxx>
+#include <svtools/imapobj.hxx>
+#include <svtools/imap.hxx>
+#include <svl/urihelper.hxx>
+#include <svtools/soerr.hxx>
+#include <sfx2/progress.hxx>
+#include <sfx2/docfile.hxx>
+#include <sfx2/printer.hxx>
+#include <editeng/udlnitem.hxx>
+#include <editeng/colritem.hxx>
+#include <svx/xoutbmp.hxx>
+#include <vcl/window.hxx>
+#include <fmturl.hxx>
+#include <fmtsrnd.hxx>
+#include <frmfmt.hxx>
+#include <swrect.hxx>
+#include <fesh.hxx>
+#include <doc.hxx>
+#include <flyfrm.hxx>
+#include <frmtool.hxx>
+#include <viewopt.hxx>
+#include <viewimp.hxx>
+#include <pam.hxx>
+#include <hints.hxx>
+#include <rootfrm.hxx>
+#include <dflyobj.hxx>
+#include <pagefrm.hxx>
+#include <notxtfrm.hxx>
+#include <grfatr.hxx>
+#include <charatr.hxx>
+#include <fmtornt.hxx>
+#include <ndnotxt.hxx>
+#include <ndgrf.hxx>
+#include <ndole.hxx>
+#include <swregion.hxx>
+#include <poolfmt.hxx>
+#include <mdiexp.hxx>
+#include <swwait.hxx>
+#include <comcore.hrc>
+#include <accessibilityoptions.hxx>
+#include <com/sun/star/embed/EmbedMisc.hpp>
+#include <com/sun/star/embed/EmbedStates.hpp>
+
+#include <svtools/embedhlp.hxx>
+#include <svtools/chartprettypainter.hxx>
+#include <dview.hxx> // #i99665#
+
+using namespace com::sun::star;
+
+#define DEFTEXTSIZE 12
+
+extern void ClrContourCache( const SdrObject *pObj ); // TxtFly.Cxx
+
+
+inline sal_Bool GetRealURL( const SwGrfNode& rNd, String& rTxt )
+{
+ sal_Bool bRet = rNd.GetFileFilterNms( &rTxt, 0 );
+ if( bRet )
+ rTxt = URIHelper::removePassword( rTxt, INetURLObject::WAS_ENCODED,
+ INetURLObject::DECODE_UNAMBIGUOUS);
+ return bRet;
+}
+
+void lcl_PaintReplacement( const SwRect &rRect, const String &rText,
+ const ViewShell &rSh, const SwNoTxtFrm *pFrm,
+ sal_Bool bDefect )
+{
+ static Font *pFont = 0;
+ if ( !pFont )
+ {
+ pFont = new Font();
+ pFont->SetWeight( WEIGHT_BOLD );
+ pFont->SetStyleName( aEmptyStr );
+ pFont->SetName( String::CreateFromAscii(
+ RTL_CONSTASCII_STRINGPARAM( "Arial Unicode" )));
+ pFont->SetFamily( FAMILY_SWISS );
+ pFont->SetTransparent( sal_True );
+ }
+
+ Color aCol( COL_RED );
+ FontUnderline eUnderline = UNDERLINE_NONE;
+ const SwFmtURL &rURL = pFrm->FindFlyFrm()->GetFmt()->GetURL();
+ if( rURL.GetURL().Len() || rURL.GetMap() )
+ {
+ sal_Bool bVisited = sal_False;
+ if ( rURL.GetMap() )
+ {
+ ImageMap *pMap = (ImageMap*)rURL.GetMap();
+ for( sal_uInt16 i = 0; i < pMap->GetIMapObjectCount(); i++ )
+ {
+ IMapObject *pObj = pMap->GetIMapObject( i );
+ if( rSh.GetDoc()->IsVisitedURL( pObj->GetURL() ) )
+ {
+ bVisited = sal_True;
+ break;
+ }
+ }
+ }
+ else if ( rURL.GetURL().Len() )
+ bVisited = rSh.GetDoc()->IsVisitedURL( rURL.GetURL() );
+
+ SwFmt *pFmt = rSh.GetDoc()->GetFmtFromPool( static_cast<sal_uInt16>
+ (bVisited ? RES_POOLCHR_INET_VISIT : RES_POOLCHR_INET_NORMAL ) );
+ aCol = pFmt->GetColor().GetValue();
+ eUnderline = pFmt->GetUnderline().GetLineStyle();
+ }
+
+ pFont->SetUnderline( eUnderline );
+ pFont->SetColor( aCol );
+
+ const BitmapEx& rBmp = ViewShell::GetReplacementBitmap( bDefect != sal_False );
+ Graphic::DrawEx( rSh.GetOut(), rText, *pFont, rBmp, rRect.Pos(), rRect.SSize() );
+}
+
+/*************************************************************************
+|*
+|* SwGrfFrm::SwGrfFrm(ViewShell * const,SwGrfNode *)
+|*
+*************************************************************************/
+
+
+SwNoTxtFrm::SwNoTxtFrm(SwNoTxtNode * const pNode, SwFrm* pSib )
+ : SwCntntFrm( pNode, pSib )
+{
+ InitCtor();
+}
+
+// Initialisierung: z.Zt. Eintragen des Frames im Cache
+
+
+void SwNoTxtFrm::InitCtor()
+{
+ nType = FRMC_NOTXT;
+ // Das Gewicht der Grafik ist 0, wenn sie noch nicht
+ // gelesen ist, < 0, wenn ein Lesefehler auftrat und
+ // Ersatzdarstellung angewendet werden musste und >0,
+ // wenn sie zur Verfuegung steht.
+ nWeight = 0;
+}
+
+/*************************************************************************
+|*
+|* SwNoTxtNode::MakeFrm()
+|*
+*************************************************************************/
+
+
+SwCntntFrm *SwNoTxtNode::MakeFrm( SwFrm* pSib )
+{
+ return new SwNoTxtFrm(this, pSib);
+}
+
+/*************************************************************************
+|*
+|* SwNoTxtFrm::~SwNoTxtFrm()
+|*
+*************************************************************************/
+
+SwNoTxtFrm::~SwNoTxtFrm()
+{
+ StopAnimation();
+}
+
+/*************************************************************************
+|*
+|* void SwNoTxtFrm::Modify( SwHint * pOld, SwHint * pNew )
+|*
+*************************************************************************/
+
+void SetOutDev( ViewShell *pSh, OutputDevice *pOut )
+{
+ pSh->pOut = pOut;
+}
+
+
+
+
+void lcl_ClearArea( const SwFrm &rFrm,
+ OutputDevice &rOut, const SwRect& rPtArea,
+ const SwRect &rGrfArea )
+{
+ SwRegionRects aRegion( rPtArea, 4, 4 );
+ aRegion -= rGrfArea;
+
+ if ( aRegion.Count() )
+ {
+ const SvxBrushItem *pItem; const Color *pCol; SwRect aOrigRect;
+ if ( rFrm.GetBackgroundBrush( pItem, pCol, aOrigRect, sal_False ) )
+ for( sal_uInt16 i = 0; i < aRegion.Count(); ++i )
+ ::DrawGraphic( pItem, &rOut, aOrigRect, aRegion[i] );
+ else
+ {
+ rOut.Push( PUSH_FILLCOLOR|PUSH_LINECOLOR );
+ rOut.SetFillColor( rFrm.getRootFrm()->GetCurrShell()->Imp()->GetRetoucheColor());
+ rOut.SetLineColor();
+ for( sal_uInt16 i = 0; i < aRegion.Count(); ++i )
+ rOut.DrawRect( aRegion[i].SVRect() );
+ rOut.Pop();
+ }
+ }
+}
+
+/*************************************************************************
+|*
+|* void SwNoTxtFrm::Paint()
+|*
+*************************************************************************/
+
+void SwNoTxtFrm::Paint(SwRect const& rRect, SwPrintData const*const) const
+{
+ if ( Frm().IsEmpty() )
+ return;
+
+ const ViewShell* pSh = getRootFrm()->GetCurrShell();
+ if( !pSh->GetViewOptions()->IsGraphic() )
+ {
+ StopAnimation();
+ // #i6467# - no paint of placeholder for page preview
+ if ( pSh->GetWin() && !pSh->IsPreView() )
+ {
+ const SwNoTxtNode* pNd = GetNode()->GetNoTxtNode();
+ String aTxt( pNd->GetTitle() );
+ if ( !aTxt.Len() && pNd->IsGrfNode() )
+ GetRealURL( *(SwGrfNode*)pNd, aTxt );
+ if( !aTxt.Len() )
+ aTxt = FindFlyFrm()->GetFmt()->GetName();
+ lcl_PaintReplacement( Frm(), aTxt, *pSh, this, sal_False );
+ }
+ return;
+ }
+
+ if( pSh->GetAccessibilityOptions()->IsStopAnimatedGraphics() ||
+ // --> FME 2004-06-21 #i9684# Stop animation during printing/pdf export
+ !pSh->GetWin() )
+ // <--
+ StopAnimation();
+
+ SfxProgress::EnterLock(); //Keine Progress-Reschedules im Paint (SwapIn)
+
+ OutputDevice *pOut = pSh->GetOut();
+ pOut->Push();
+ sal_Bool bClip = sal_True;
+ PolyPolygon aPoly;
+
+ SwNoTxtNode& rNoTNd = *(SwNoTxtNode*)GetNode();
+ SwGrfNode* pGrfNd = rNoTNd.GetGrfNode();
+ if( pGrfNd )
+ pGrfNd->SetFrameInPaint( sal_True );
+
+ // #i13147# - add 2nd parameter with value <sal_True> to
+ // method call <FindFlyFrm().GetContour(..)> to indicate that it is called
+ // for paint in order to avoid load of the intrinsic graphic.
+ if ( ( !pOut->GetConnectMetaFile() ||
+ !pSh->GetWin() ) &&
+ FindFlyFrm()->GetContour( aPoly, sal_True )
+ )
+ {
+ pOut->SetClipRegion( aPoly );
+ bClip = sal_False;
+ }
+
+ SwRect aOrigPaint( rRect );
+ if ( HasAnimation() && pSh->GetWin() )
+ {
+ aOrigPaint = Frm(); aOrigPaint += Prt().Pos();
+ }
+
+ SwRect aGrfArea( Frm() );
+ SwRect aPaintArea( aGrfArea );
+ aPaintArea._Intersection( aOrigPaint );
+
+ SwRect aNormal( Frm().Pos() + Prt().Pos(), Prt().SSize() );
+ aNormal.Justify(); //Normalisiertes Rechteck fuer die Vergleiche
+
+ if( aPaintArea.IsOver( aNormal ) )
+ {
+ // berechne die 4 zu loeschenden Rechtecke
+ if( pSh->GetWin() )
+ ::lcl_ClearArea( *this, *pSh->GetOut(), aPaintArea, aNormal );
+
+ // in der Schnittmenge vom PaintBereich und der Bitmap liegt
+ // der absolut sichtbare Bereich vom Frame
+ aPaintArea._Intersection( aNormal );
+
+ if ( bClip )
+ pOut->IntersectClipRegion( aPaintArea.SVRect() );
+ /// delete unused 3rd parameter
+ PaintPicture( pOut, aGrfArea );
+ }
+ else
+ // wenn nicht sichtbar, loesche einfach den angegebenen Bereich
+ lcl_ClearArea( *this, *pSh->GetOut(), aPaintArea, SwRect() );
+ if( pGrfNd )
+ pGrfNd->SetFrameInPaint( sal_False );
+
+ pOut->Pop();
+ SfxProgress::LeaveLock();
+}
+
+/*************************************************************************
+|*
+|* void lcl_CalcRect( Point & aPt, Size & aDim,
+|* sal_uInt16 nMirror )
+|*
+|* Beschreibung Errechne die Position und die Groesse der Grafik im
+|* Frame, entsprechen der aktuellen Grafik-Attribute
+|*
+|* Parameter Point& die Position im Frame ( auch Return-Wert )
+|* Size& die Groesse der Grafik ( auch Return-Wert )
+|* MirrorGrf akt. Spiegelungs-Attribut
+|*
+*************************************************************************/
+
+
+void lcl_CalcRect( Point& rPt, Size& rDim, sal_uInt16 nMirror )
+{
+ if( nMirror == RES_MIRROR_GRAPH_VERT || nMirror == RES_MIRROR_GRAPH_BOTH )
+ {
+ rPt.X() += rDim.Width() -1;
+ rDim.Width() = -rDim.Width();
+ }
+
+ if( nMirror == RES_MIRROR_GRAPH_HOR || nMirror == RES_MIRROR_GRAPH_BOTH )
+ {
+ rPt.Y() += rDim.Height() -1;
+ rDim.Height() = -rDim.Height();
+ }
+}
+
+/*************************************************************************
+|*
+|* void SwNoTxtFrm::GetGrfArea()
+|*
+|* Beschreibung Errechne die Position und die Groesse der Bitmap
+|* innerhalb des uebergebenem Rechtecks.
+|*
+*************************************************************************/
+
+void SwNoTxtFrm::GetGrfArea( SwRect &rRect, SwRect* pOrigRect,
+ sal_Bool ) const
+{
+ //currently only used for scaling, cropping and mirroring the contour of graphics!
+ //all other is handled by the GraphicObject
+
+ //In rRect wird das sichbare Rechteck der Grafik gesteckt.
+ //In pOrigRect werden Pos+Size der Gesamtgrafik gesteck.
+
+ const SwAttrSet& rAttrSet = GetNode()->GetSwAttrSet();
+ const SwCropGrf& rCrop = rAttrSet.GetCropGrf();
+ sal_uInt16 nMirror = rAttrSet.GetMirrorGrf().GetValue();
+
+ if( rAttrSet.GetMirrorGrf().IsGrfToggle() )
+ {
+ if( !(FindPageFrm()->GetVirtPageNum() % 2) )
+ {
+ switch ( nMirror )
+ {
+ case RES_MIRROR_GRAPH_DONT: nMirror = RES_MIRROR_GRAPH_VERT; break;
+ case RES_MIRROR_GRAPH_VERT: nMirror = RES_MIRROR_GRAPH_DONT; break;
+ case RES_MIRROR_GRAPH_HOR: nMirror = RES_MIRROR_GRAPH_BOTH; break;
+ default: nMirror = RES_MIRROR_GRAPH_HOR; break;
+ }
+ }
+ }
+
+ //Grafik wird vom Node eingelesen falls notwendig. Kann aber schiefgehen.
+ long nLeftCrop, nRightCrop, nTopCrop, nBottomCrop;
+ Size aOrigSz( ((SwNoTxtNode*)GetNode())->GetTwipSize() );
+ if ( !aOrigSz.Width() )
+ {
+ aOrigSz.Width() = Prt().Width();
+ nLeftCrop = -rCrop.GetLeft();
+ nRightCrop = -rCrop.GetRight();
+ }
+ else
+ {
+ nLeftCrop = Max( aOrigSz.Width() -
+ (rCrop.GetRight() + rCrop.GetLeft()), long(1) );
+ const double nScale = double(Prt().Width()) / double(nLeftCrop);
+ nLeftCrop = long(nScale * -rCrop.GetLeft() );
+ nRightCrop = long(nScale * -rCrop.GetRight() );
+ }
+
+ // crop values have to be mirrored too
+ if( nMirror == RES_MIRROR_GRAPH_VERT || nMirror == RES_MIRROR_GRAPH_BOTH )
+ {
+ long nTmpCrop = nLeftCrop;
+ nLeftCrop = nRightCrop;
+ nRightCrop= nTmpCrop;
+ }
+
+ if( !aOrigSz.Height() )
+ {
+ aOrigSz.Height() = Prt().Height();
+ nTopCrop = -rCrop.GetTop();
+ nBottomCrop= -rCrop.GetBottom();
+ }
+ else
+ {
+ nTopCrop = Max( aOrigSz.Height() - (rCrop.GetTop() + rCrop.GetBottom()), long(1) );
+ const double nScale = double(Prt().Height()) / double(nTopCrop);
+ nTopCrop = long(nScale * -rCrop.GetTop() );
+ nBottomCrop= long(nScale * -rCrop.GetBottom() );
+ }
+
+ // crop values have to be mirrored too
+ if( nMirror == RES_MIRROR_GRAPH_HOR || nMirror == RES_MIRROR_GRAPH_BOTH )
+ {
+ long nTmpCrop = nTopCrop;
+ nTopCrop = nBottomCrop;
+ nBottomCrop= nTmpCrop;
+ }
+
+ Size aVisSz( Prt().SSize() );
+ Size aGrfSz( aVisSz );
+ Point aVisPt( Frm().Pos() + Prt().Pos() );
+ Point aGrfPt( aVisPt );
+
+ //Erst das 'sichtbare' Rect einstellen.
+ if ( nLeftCrop > 0 )
+ {
+ aVisPt.X() += nLeftCrop;
+ aVisSz.Width() -= nLeftCrop;
+ }
+ if ( nTopCrop > 0 )
+ {
+ aVisPt.Y() += nTopCrop;
+ aVisSz.Height() -= nTopCrop;
+ }
+ if ( nRightCrop > 0 )
+ aVisSz.Width() -= nRightCrop;
+ if ( nBottomCrop > 0 )
+ aVisSz.Height() -= nBottomCrop;
+
+ rRect.Pos ( aVisPt );
+ rRect.SSize( aVisSz );
+
+ //Ggf. Die Gesamtgrafik berechnen
+ if ( pOrigRect )
+ {
+ Size aTmpSz( aGrfSz );
+ aGrfPt.X() += nLeftCrop;
+ aTmpSz.Width() -= nLeftCrop + nRightCrop;
+ aGrfPt.Y() += nTopCrop;
+ aTmpSz.Height()-= nTopCrop + nBottomCrop;
+
+ if( RES_MIRROR_GRAPH_DONT != nMirror )
+ lcl_CalcRect( aGrfPt, aTmpSz, nMirror );
+
+ pOrigRect->Pos ( aGrfPt );
+ pOrigRect->SSize( aTmpSz );
+ }
+}
+
+/*************************************************************************
+|*
+|* Size SwNoTxtFrm::GetSize()
+|*
+|* Beschreibung Gebe die Groesse des umgebenen FLys und
+|* damit die der Grafik zurueck.
+|*
+*************************************************************************/
+
+
+const Size& SwNoTxtFrm::GetSize() const
+{
+ // gebe die Groesse des Frames zurueck
+ const SwFrm *pFly = FindFlyFrm();
+ if( !pFly )
+ pFly = this;
+ return pFly->Prt().SSize();
+}
+
+/*************************************************************************
+|*
+|* SwNoTxtFrm::MakeAll()
+|*
+*************************************************************************/
+
+
+void SwNoTxtFrm::MakeAll()
+{
+ SwCntntNotify aNotify( this );
+ SwBorderAttrAccess aAccess( SwFrm::GetCache(), this );
+ const SwBorderAttrs &rAttrs = *aAccess.Get();
+
+ while ( !bValidPos || !bValidSize || !bValidPrtArea )
+ {
+ MakePos();
+
+ if ( !bValidSize )
+ Frm().Width( GetUpper()->Prt().Width() );
+
+ MakePrtArea( rAttrs );
+
+ if ( !bValidSize )
+ { bValidSize = sal_True;
+ Format();
+ }
+ }
+}
+
+/*************************************************************************
+|*
+|* SwNoTxtFrm::Format()
+|*
+|* Beschreibung Errechne die Groesse der Bitmap, wenn noetig
+|*
+*************************************************************************/
+
+
+void SwNoTxtFrm::Format( const SwBorderAttrs * )
+{
+ const Size aNewSize( GetSize() );
+
+ // hat sich die Hoehe geaendert?
+ SwTwips nChgHght = IsVertical() ?
+ (SwTwips)(aNewSize.Width() - Prt().Width()) :
+ (SwTwips)(aNewSize.Height() - Prt().Height());
+ if( nChgHght > 0)
+ Grow( nChgHght );
+ else if( nChgHght < 0)
+ Shrink( Min(Prt().Height(), -nChgHght) );
+}
+
+/*************************************************************************
+|*
+|* SwNoTxtFrm::GetCharRect()
+|*
+|*************************************************************************/
+
+
+sal_Bool SwNoTxtFrm::GetCharRect( SwRect &rRect, const SwPosition& rPos,
+ SwCrsrMoveState *pCMS ) const
+{
+ if ( &rPos.nNode.GetNode() != (SwNode*)GetNode() )
+ return sal_False;
+
+ Calc();
+ SwRect aFrameRect( Frm() );
+ rRect = aFrameRect;
+ rRect.Pos( Frm().Pos() + Prt().Pos() );
+ rRect.SSize( Prt().SSize() );
+
+ rRect.Justify();
+
+ // liegt die Bitmap ueberhaupt im sichtbaren Berich ?
+ if( !aFrameRect.IsOver( rRect ) )
+ {
+ // wenn nicht dann steht der Cursor auf dem Frame
+ rRect = aFrameRect;
+ rRect.Width( 1 );
+ }
+ else
+ rRect._Intersection( aFrameRect );
+
+ if ( pCMS )
+ {
+ if ( pCMS->bRealHeight )
+ {
+ pCMS->aRealHeight.Y() = rRect.Height();
+ pCMS->aRealHeight.X() = 0;
+ }
+ }
+
+ return sal_True;
+}
+
+
+sal_Bool SwNoTxtFrm::GetCrsrOfst(SwPosition* pPos, Point& ,
+ SwCrsrMoveState* ) const
+{
+ SwCntntNode* pCNd = (SwCntntNode*)GetNode();
+ pPos->nNode = *pCNd;
+ pPos->nContent.Assign( pCNd, 0 );
+ return sal_True;
+}
+
+#define CLEARCACHE( pNd ) {\
+ (pNd)->GetGrfObj().ReleaseFromCache();\
+ SwFlyFrm* pFly = FindFlyFrm();\
+ if( pFly && pFly->GetFmt()->GetSurround().IsContour() )\
+ {\
+ ClrContourCache( pFly->GetVirtDrawObj() );\
+ pFly->NotifyBackground( FindPageFrm(), Prt(), PREP_FLY_ATTR_CHG );\
+ }\
+}
+
+void SwNoTxtFrm::Modify( const SfxPoolItem* pOld, const SfxPoolItem* pNew )
+{
+ sal_uInt16 nWhich = pNew ? pNew->Which() : pOld ? pOld->Which() : 0;
+
+ // #i73788#
+ // no <SwCntntFrm::Modify(..)> for RES_LINKED_GRAPHIC_STREAM_ARRIVED
+ if ( RES_GRAPHIC_PIECE_ARRIVED != nWhich &&
+ RES_GRAPHIC_ARRIVED != nWhich &&
+ RES_GRF_REREAD_AND_INCACHE != nWhich &&
+ RES_LINKED_GRAPHIC_STREAM_ARRIVED != nWhich )
+ // <--
+ {
+ SwCntntFrm::Modify( pOld, pNew );
+ }
+
+ sal_Bool bComplete = sal_True;
+
+ switch( nWhich )
+ {
+ case RES_OBJECTDYING:
+ break;
+
+ case RES_GRF_REREAD_AND_INCACHE:
+ if( ND_GRFNODE == GetNode()->GetNodeType() )
+ {
+ bComplete = sal_False;
+ SwGrfNode* pNd = (SwGrfNode*) GetNode();
+
+ ViewShell *pVSh = 0;
+ pNd->GetDoc()->GetEditShell( &pVSh );
+ if( pVSh )
+ {
+ GraphicAttr aAttr;
+ if( pNd->GetGrfObj().IsCached( pVSh->GetOut(), Point(),
+ Prt().SSize(), &pNd->GetGraphicAttr( aAttr, this ) ))
+ {
+ ViewShell *pSh = pVSh;
+ do {
+ SET_CURR_SHELL( pSh );
+ if( pSh->GetWin() )
+ {
+ if( pSh->IsPreView() )
+ ::RepaintPagePreview( pSh, Frm().SVRect() );
+ else
+ pSh->GetWin()->Invalidate( Frm().SVRect() );
+ }
+ } while( pVSh != (pSh = (ViewShell*)pSh->GetNext() ));
+ }
+ else
+ pNd->SwapIn();
+ }
+ }
+ break;
+
+ case RES_UPDATE_ATTR:
+ case RES_FMT_CHG:
+ CLEARCACHE( (SwGrfNode*) GetNode() )
+ break;
+
+ case RES_ATTRSET_CHG:
+ {
+ sal_uInt16 n;
+ for( n = RES_GRFATR_BEGIN; n < RES_GRFATR_END; ++n )
+ if( SFX_ITEM_SET == ((SwAttrSetChg*)pOld)->GetChgSet()->
+ GetItemState( n, sal_False ))
+ {
+ CLEARCACHE( (SwGrfNode*) GetNode() )
+ break;
+ }
+ if( RES_GRFATR_END == n ) // not found
+ return ;
+ }
+ break;
+
+ case RES_GRAPHIC_PIECE_ARRIVED:
+ case RES_GRAPHIC_ARRIVED:
+ // i73788# - handle RES_LINKED_GRAPHIC_STREAM_ARRIVED as RES_GRAPHIC_ARRIVED
+ case RES_LINKED_GRAPHIC_STREAM_ARRIVED:
+ if ( GetNode()->GetNodeType() == ND_GRFNODE )
+ {
+ bComplete = sal_False;
+ SwGrfNode* pNd = (SwGrfNode*) GetNode();
+
+ CLEARCACHE( pNd )
+
+ SwRect aRect( Frm() );
+
+ ViewShell *pVSh = 0;
+ pNd->GetDoc()->GetEditShell( &pVSh );
+ if( !pVSh )
+ break;
+
+ ViewShell *pSh = pVSh;
+ do {
+ SET_CURR_SHELL( pSh );
+ if( pSh->IsPreView() )
+ {
+ if( pSh->GetWin() )
+ ::RepaintPagePreview( pSh, aRect );
+ }
+ else if ( pSh->VisArea().IsOver( aRect ) &&
+ OUTDEV_WINDOW == pSh->GetOut()->GetOutDevType() )
+ {
+ //invalidate instead of painting
+ pSh->GetWin()->Invalidate( aRect.SVRect() );
+ }
+
+ pSh = (ViewShell *)pSh->GetNext();
+ } while( pSh != pVSh );
+ }
+ break;
+
+ default:
+ if ( !pNew || !isGRFATR(nWhich) )
+ return;
+ }
+
+ if( bComplete )
+ {
+ InvalidatePrt();
+ SetCompletePaint();
+ }
+}
+
+void lcl_correctlyAlignRect( SwRect& rAlignedGrfArea, const SwRect& rInArea, OutputDevice* pOut )
+{
+
+ if(!pOut)
+ return;
+ Rectangle aPxRect = pOut->LogicToPixel( rInArea.SVRect() );
+ Rectangle aNewPxRect( aPxRect );
+ while( aNewPxRect.Left() < aPxRect.Left() )
+ {
+ rAlignedGrfArea.Left( rAlignedGrfArea.Left()+1 );
+ aNewPxRect = pOut->LogicToPixel( rAlignedGrfArea.SVRect() );
+ }
+ while( aNewPxRect.Top() < aPxRect.Top() )
+ {
+ rAlignedGrfArea.Top( rAlignedGrfArea.Top()+1 );
+ aNewPxRect = pOut->LogicToPixel( rAlignedGrfArea.SVRect() );
+ }
+ while( aNewPxRect.Bottom() > aPxRect.Bottom() )
+ {
+ rAlignedGrfArea.Bottom( rAlignedGrfArea.Bottom()-1 );
+ aNewPxRect = pOut->LogicToPixel( rAlignedGrfArea.SVRect() );
+ }
+ while( aNewPxRect.Right() > aPxRect.Right() )
+ {
+ rAlignedGrfArea.Right( rAlignedGrfArea.Right()-1 );
+ aNewPxRect = pOut->LogicToPixel( rAlignedGrfArea.SVRect() );
+ }
+}
+
+// Ausgabe der Grafik. Hier wird entweder eine QuickDraw-Bmp oder
+// eine Grafik vorausgesetzt. Ist nichts davon vorhanden, wird
+// eine Ersatzdarstellung ausgegeben.
+/// delete unused 3rd parameter.
+/// use aligned rectangle for drawing graphic.
+/// pixel-align coordinations for drawing graphic.
+void SwNoTxtFrm::PaintPicture( OutputDevice* pOut, const SwRect &rGrfArea ) const
+{
+ ViewShell* pShell = getRootFrm()->GetCurrShell();
+
+ SwNoTxtNode& rNoTNd = *(SwNoTxtNode*)GetNode();
+ SwGrfNode* pGrfNd = rNoTNd.GetGrfNode();
+ SwOLENode* pOLENd = rNoTNd.GetOLENode();
+
+ const sal_Bool bPrn = pOut == rNoTNd.getIDocumentDeviceAccess()->getPrinter( false ) ||
+ pOut->GetConnectMetaFile();
+
+ const bool bIsChart = pOLENd && ChartPrettyPainter::IsChart( pOLENd->GetOLEObj().GetObject() );
+
+ /// calculate aligned rectangle from parameter <rGrfArea>.
+ /// Use aligned rectangle <aAlignedGrfArea> instead of <rGrfArea> in
+ /// the following code.
+ SwRect aAlignedGrfArea = rGrfArea;
+ ::SwAlignRect( aAlignedGrfArea, pShell );
+
+ if( !bIsChart )
+ {
+ /// Because for drawing a graphic left-top-corner and size coordinations are
+ /// used, these coordinations have to be determined on pixel level.
+ ::SwAlignGrfRect( &aAlignedGrfArea, *pOut );
+ }
+ else //if( bIsChart )
+ {
+ //#i78025# charts own borders are not completely visible
+ //the above pixel correction is not correct - at least not for charts
+ //so a different pixel correction is choosen here
+ //this might be a good idea for all other OLE objects also,
+ //but as I cannot oversee the consequences I fix it only for charts for now
+ lcl_correctlyAlignRect( aAlignedGrfArea, rGrfArea, pOut );
+ }
+
+ if( pGrfNd )
+ {
+ sal_Bool bForceSwap = sal_False, bContinue = sal_True;
+ GraphicObject& rGrfObj = pGrfNd->GetGrfObj();
+
+ GraphicAttr aGrfAttr;
+ pGrfNd->GetGraphicAttr( aGrfAttr, this );
+
+ if( !bPrn )
+ {
+ // #i73788#
+ if ( pGrfNd->IsLinkedInputStreamReady() )
+ {
+ pGrfNd->UpdateLinkWithInputStream();
+ }
+ // <--
+ // #i85717#, #i90395# - check, if asynchronous retrieval
+ // if input stream for the graphic is possible
+// else if( GRAPHIC_DEFAULT == rGrfObj.GetType() &&
+ else if ( ( rGrfObj.GetType() == GRAPHIC_DEFAULT ||
+ rGrfObj.GetType() == GRAPHIC_NONE ) &&
+ pGrfNd->IsLinkedFile() &&
+ pGrfNd->IsAsyncRetrieveInputStreamPossible() )
+ // <--
+ {
+ Size aTmpSz;
+ ::sfx2::SvLinkSource* pGrfObj = pGrfNd->GetLink()->GetObj();
+ if( !pGrfObj ||
+ !pGrfObj->IsDataComplete() ||
+ !(aTmpSz = pGrfNd->GetTwipSize()).Width() ||
+ !aTmpSz.Height() || !pGrfNd->GetAutoFmtLvl() )
+ {
+ pGrfNd->TriggerAsyncRetrieveInputStream(); // #i73788#
+ }
+ String aTxt( pGrfNd->GetTitle() );
+ if ( !aTxt.Len() )
+ GetRealURL( *pGrfNd, aTxt );
+ ::lcl_PaintReplacement( aAlignedGrfArea, aTxt, *pShell, this, sal_False );
+ bContinue = sal_False;
+ }
+ else if( rGrfObj.IsCached( pOut, aAlignedGrfArea.Pos(),
+ aAlignedGrfArea.SSize(), &aGrfAttr ))
+ {
+ rGrfObj.DrawWithPDFHandling( *pOut,
+ aAlignedGrfArea.Pos(), aAlignedGrfArea.SSize(),
+ &aGrfAttr );
+ bContinue = sal_False;
+ }
+ }
+
+ if( bContinue )
+ {
+ const sal_Bool bSwapped = rGrfObj.IsSwappedOut();
+ const sal_Bool bSwappedIn = 0 != pGrfNd->SwapIn( bPrn );
+ if( bSwappedIn && rGrfObj.GetGraphic().IsSupportedGraphic())
+ {
+ const sal_Bool bAnimate = rGrfObj.IsAnimated() &&
+ !pShell->IsPreView() &&
+ !pShell->GetAccessibilityOptions()->IsStopAnimatedGraphics() &&
+ // --> FME 2004-06-21 #i9684# Stop animation during printing/pdf export
+ pShell->GetWin();
+ // <--
+
+ if( bAnimate &&
+ FindFlyFrm() != ::GetFlyFromMarked( 0, pShell ))
+ {
+ OutputDevice* pVout;
+ if( pOut == pShell->GetOut() && SwRootFrm::FlushVout() )
+ pVout = pOut, pOut = pShell->GetOut();
+ else if( pShell->GetWin() &&
+ OUTDEV_VIRDEV == pOut->GetOutDevType() )
+ pVout = pOut, pOut = pShell->GetWin();
+ else
+ pVout = 0;
+
+ OSL_ENSURE( OUTDEV_VIRDEV != pOut->GetOutDevType() ||
+ pShell->GetViewOptions()->IsPDFExport(),
+ "pOut sollte kein virtuelles Device sein" );
+
+ rGrfObj.StartAnimation( pOut, aAlignedGrfArea.Pos(),
+ aAlignedGrfArea.SSize(), long(this),
+ 0, GRFMGR_DRAW_STANDARD, pVout );
+ }
+ else
+ rGrfObj.DrawWithPDFHandling( *pOut,
+ aAlignedGrfArea.Pos(), aAlignedGrfArea.SSize(),
+ &aGrfAttr );
+ }
+ else
+ {
+ sal_uInt16 nResId = 0;
+ if( bSwappedIn )
+ {
+ if( GRAPHIC_NONE == rGrfObj.GetType() )
+ nResId = STR_COMCORE_READERROR;
+ else if ( !rGrfObj.GetGraphic().IsSupportedGraphic() )
+ nResId = STR_COMCORE_CANT_SHOW;
+ }
+ ((SwNoTxtFrm*)this)->nWeight = -1;
+ String aText;
+ if ( !nResId &&
+ !(aText = pGrfNd->GetTitle()).Len() &&
+ (!GetRealURL( *pGrfNd, aText ) || !aText.Len()))
+ {
+ nResId = STR_COMCORE_READERROR;
+ }
+ if ( nResId )
+ aText = SW_RESSTR( nResId );
+
+ ::lcl_PaintReplacement( aAlignedGrfArea, aText, *pShell, this, sal_True );
+ }
+
+ //Beim Drucken duerfen wir nicht die Grafiken sammeln...
+ if( bSwapped && bPrn )
+ bForceSwap = sal_True;
+ }
+ if( bForceSwap )
+ pGrfNd->SwapOut();
+ }
+ else if( bIsChart
+ //charts must be painted resolution dependent!! #i82893#, #i75867#
+ && ChartPrettyPainter::ShouldPrettyPaintChartOnThisDevice( pOut )
+ && svt::EmbeddedObjectRef::TryRunningState( pOLENd->GetOLEObj().GetOleRef() )
+ && ChartPrettyPainter::DoPrettyPaintChart( uno::Reference< frame::XModel >(
+ pOLENd->GetOLEObj().GetOleRef()->getComponent(), uno::UNO_QUERY), pOut, aAlignedGrfArea.SVRect() ) )
+ {
+ (void)(0);//all was done in if statement
+ }
+ else if( pOLENd )
+ {
+ // #i99665#
+ // Adjust AntiAliasing mode at output device for chart OLE
+ const sal_uInt16 nFormerAntialiasingAtOutput( pOut->GetAntialiasing() );
+ if ( pOLENd->IsChart() &&
+ pShell->Imp()->GetDrawView()->IsAntiAliasing() )
+ {
+ const sal_uInt16 nAntialiasingForChartOLE =
+ nFormerAntialiasingAtOutput | ANTIALIASING_PIXELSNAPHAIRLINE;
+ pOut->SetAntialiasing( nAntialiasingForChartOLE );
+ }
+ // <--
+
+ Point aPosition(aAlignedGrfArea.Pos());
+ Size aSize(aAlignedGrfArea.SSize());
+
+ // Im BrowseModus gibt es nicht unbedingt einen Drucker und
+ // damit kein JobSetup, also legen wir eines an ...
+ const JobSetup* pJobSetup = pOLENd->getIDocumentDeviceAccess()->getJobsetup();
+ sal_Bool bDummyJobSetup = 0 == pJobSetup;
+ if( bDummyJobSetup )
+ pJobSetup = new JobSetup();
+
+ // #i42323#
+ //TODO/LATER: is it a problem that the JopSetup isn't used?
+ //xRef->DoDraw( pOut, aAlignedGrfArea.Pos(), aAlignedGrfArea.SSize(), *pJobSetup );
+
+ Graphic* pGraphic = pOLENd->GetGraphic();
+
+ if ( pGraphic && pGraphic->GetType() != GRAPHIC_NONE )
+ {
+ pGraphic->Draw( pOut, aPosition, aSize );
+
+ // shade the representation if the object is activated outplace
+ uno::Reference < embed::XEmbeddedObject > xObj = pOLENd->GetOLEObj().GetOleRef();
+ if ( xObj.is() && xObj->getCurrentState() == embed::EmbedStates::ACTIVE )
+ {
+ ::svt::EmbeddedObjectRef::DrawShading( Rectangle( aPosition, aSize ), pOut );
+ }
+ }
+ else
+ ::svt::EmbeddedObjectRef::DrawPaintReplacement( Rectangle( aPosition, aSize ), pOLENd->GetOLEObj().GetCurrentPersistName(), pOut );
+
+ if( bDummyJobSetup )
+ delete pJobSetup; // ... und raeumen wieder auf.
+
+ sal_Int64 nMiscStatus = pOLENd->GetOLEObj().GetOleRef()->getStatus( pOLENd->GetAspect() );
+ if ( !bPrn && pShell->ISA( SwCrsrShell ) &&
+ nMiscStatus & embed::EmbedMisc::MS_EMBED_ACTIVATEWHENVISIBLE )
+ {
+ const SwFlyFrm *pFly = FindFlyFrm();
+ OSL_ENSURE( pFly, "OLE not in FlyFrm" );
+ ((SwFEShell*)pShell)->ConnectObj( pOLENd->GetOLEObj().GetObject(), pFly->Prt(), pFly->Frm());
+ }
+
+ // #i99665#
+ if ( pOLENd->IsChart() &&
+ pShell->Imp()->GetDrawView()->IsAntiAliasing() )
+ {
+ pOut->SetAntialiasing( nFormerAntialiasingAtOutput );
+ }
+ // <--
+ }
+}
+
+
+sal_Bool SwNoTxtFrm::IsTransparent() const
+{
+ const ViewShell* pSh = getRootFrm()->GetCurrShell();
+ if ( !pSh || !pSh->GetViewOptions()->IsGraphic() )
+ return sal_True;
+
+ const SwGrfNode *pNd;
+ if( 0 != (pNd = GetNode()->GetGrfNode()) )
+ return pNd->IsTransparent();
+
+ //#29381# OLE sind immer Transparent.
+ return sal_True;
+}
+
+
+void SwNoTxtFrm::StopAnimation( OutputDevice* pOut ) const
+{
+ //animierte Grafiken anhalten
+ SwGrfNode* pGrfNd = (SwGrfNode*)GetNode()->GetGrfNode();
+ if( pGrfNd && pGrfNd->IsAnimated() )
+ pGrfNd->GetGrfObj().StopAnimation( pOut, long(this) );
+}
+
+
+sal_Bool SwNoTxtFrm::HasAnimation() const
+{
+ const SwGrfNode* pGrfNd = GetNode()->GetGrfNode();
+ return pGrfNd && pGrfNd->IsAnimated();
+}
+
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/doc/number.cxx b/sw/source/core/doc/number.cxx
new file mode 100644
index 000000000000..a5d12082f8fd
--- /dev/null
+++ b/sw/source/core/doc/number.cxx
@@ -0,0 +1,1457 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+
+#include <hintids.hxx>
+
+#include <string.h>
+#include <vcl/font.hxx>
+#include <editeng/brshitem.hxx>
+#include <editeng/lrspitem.hxx>
+#include <editeng/numitem.hxx>
+#include <fmtornt.hxx>
+#include <doc.hxx>
+#include <pam.hxx>
+#include <charfmt.hxx>
+#include <paratr.hxx>
+#include <frmfmt.hxx>
+#include <ndtxt.hxx>
+#include <docary.hxx>
+#include <docsh.hxx>
+#include <SwStyleNameMapper.hxx>
+
+// Needed to load default bullet list configuration
+#include <unotools/configitem.hxx>
+
+#include <numrule.hxx>
+#include <SwNodeNum.hxx>
+
+#include <boost/unordered_map.hpp>
+
+#include <list.hxx>
+#include <algorithm>
+
+#include <unotools/saveopt.hxx>
+
+#include <IDocumentListsAccess.hxx>
+
+using namespace ::com::sun::star;
+
+
+sal_uInt16 SwNumRule::nRefCount = 0;
+SwNumFmt* SwNumRule::aBaseFmts[ RULE_END ][ MAXLEVEL ] = {
+ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } };
+
+SwNumFmt* SwNumRule::aLabelAlignmentBaseFmts[ RULE_END ][ MAXLEVEL ] = {
+ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } };
+
+char sOutline[] = "Outline";
+char* SwNumRule::pDefOutlineName = sOutline;
+
+sal_uInt16 SwNumRule::aDefNumIndents[ MAXLEVEL ] = {
+//inch: 0,5 1,0 1,5 2,0 2,5 3,0 3,5 4,0 4,5 5,0
+ 1440/4, 1440/2, 1440*3/4, 1440, 1440*5/4, 1440*3/2, 1440*7/4, 1440*2,
+ 1440*9/4, 1440*5/2
+};
+
+const SwNumFmt& SwNumRule::Get( sal_uInt16 i ) const
+{
+ OSL_ASSERT( i < MAXLEVEL && eRuleType < RULE_END );
+ return aFmts[ i ]
+ ? *aFmts[ i ]
+ : ( meDefaultNumberFormatPositionAndSpaceMode == SvxNumberFormat::LABEL_WIDTH_AND_POSITION
+ ? *aBaseFmts[ eRuleType ][ i ]
+ : *aLabelAlignmentBaseFmts[ eRuleType ][ i ] );
+}
+
+const SwNumFmt* SwNumRule::GetNumFmt( sal_uInt16 i ) const
+{
+ const SwNumFmt * pResult = NULL;
+
+ OSL_ASSERT( i < MAXLEVEL && eRuleType < RULE_END );
+ if ( i < MAXLEVEL && eRuleType < RULE_END)
+ {
+ pResult = aFmts[ i ];
+ }
+
+ return pResult;
+}
+
+// #i91400#
+void SwNumRule::SetName( const String & rName,
+ IDocumentListsAccess& rDocListAccess)
+// <--
+{
+ if ( sName != rName )
+ {
+ if (pNumRuleMap)
+ {
+ pNumRuleMap->erase(sName);
+ (*pNumRuleMap)[rName] = this;
+
+ if ( GetDefaultListId().Len() > 0 )
+ {
+ rDocListAccess.trackChangeOfListStyleName( sName, rName );
+ }
+ }
+
+ sName = rName;
+ }
+}
+
+
+void SwNumRule::GetTxtNodeList( SwNumRule::tTxtNodeList& rTxtNodeList ) const
+{
+ rTxtNodeList = maTxtNodeList;
+}
+
+
+SwNumRule::tTxtNodeList::size_type SwNumRule::GetTxtNodeListSize() const
+{
+ return maTxtNodeList.size();
+}
+
+
+void SwNumRule::AddTxtNode( SwTxtNode& rTxtNode )
+{
+ tTxtNodeList::iterator aIter =
+ std::find( maTxtNodeList.begin(), maTxtNodeList.end(), &rTxtNode );
+
+ if ( aIter == maTxtNodeList.end() )
+ {
+ maTxtNodeList.push_back( &rTxtNode );
+ }
+}
+
+
+void SwNumRule::RemoveTxtNode( SwTxtNode& rTxtNode )
+{
+ tTxtNodeList::iterator aIter =
+ std::find( maTxtNodeList.begin(), maTxtNodeList.end(), &rTxtNode );
+
+ if ( aIter != maTxtNodeList.end() )
+ {
+ maTxtNodeList.erase( aIter );
+ }
+}
+
+
+void SwNumRule::SetNumRuleMap(boost::unordered_map<String, SwNumRule *, StringHash> *
+ _pNumRuleMap)
+{
+ pNumRuleMap = _pNumRuleMap;
+}
+
+sal_uInt16 SwNumRule::GetNumIndent( sal_uInt8 nLvl )
+{
+ OSL_ENSURE( MAXLEVEL > nLvl, "NumLevel is out of range" );
+ return aDefNumIndents[ nLvl ];
+}
+
+sal_uInt16 SwNumRule::GetBullIndent( sal_uInt8 nLvl )
+{
+ OSL_ENSURE( MAXLEVEL > nLvl, "NumLevel is out of range" );
+ return aDefNumIndents[ nLvl ];
+}
+
+static void lcl_SetRuleChgd( SwTxtNode& rNd, sal_uInt8 nLevel )
+{
+ if( rNd.GetActualListLevel() == nLevel )
+ rNd.NumRuleChgd();
+}
+
+SwNumFmt::SwNumFmt() :
+ SvxNumberFormat(SVX_NUM_ARABIC),
+ SwClient( 0 ),
+ pVertOrient(new SwFmtVertOrient( 0, text::VertOrientation::NONE))
+{
+}
+
+SwNumFmt::SwNumFmt( const SwNumFmt& rFmt) :
+ SvxNumberFormat(rFmt),
+ SwClient( rFmt.GetRegisteredInNonConst() ),
+ pVertOrient(new SwFmtVertOrient( 0, rFmt.GetVertOrient()))
+{
+ sal_Int16 eMyVertOrient = rFmt.GetVertOrient();
+ SetGraphicBrush( rFmt.GetBrush(), &rFmt.GetGraphicSize(),
+ &eMyVertOrient);
+}
+
+SwNumFmt::SwNumFmt(const SvxNumberFormat& rNumFmt, SwDoc* pDoc) :
+ SvxNumberFormat(rNumFmt),
+ pVertOrient(new SwFmtVertOrient( 0, rNumFmt.GetVertOrient()))
+{
+ sal_Int16 eMyVertOrient = rNumFmt.GetVertOrient();
+ SetGraphicBrush( rNumFmt.GetBrush(), &rNumFmt.GetGraphicSize(),
+ &eMyVertOrient);
+ const String& rCharStyleName = rNumFmt.SvxNumberFormat::GetCharFmtName();
+ if( rCharStyleName.Len() )
+ {
+ SwCharFmt* pCFmt = pDoc->FindCharFmtByName( rCharStyleName );
+ if( !pCFmt )
+ {
+ sal_uInt16 nId = SwStyleNameMapper::GetPoolIdFromUIName( rCharStyleName,
+ nsSwGetPoolIdFromName::GET_POOLID_CHRFMT );
+ pCFmt = nId != USHRT_MAX
+ ? pDoc->GetCharFmtFromPool( nId )
+ : pDoc->MakeCharFmt( rCharStyleName, 0 );
+ }
+ pCFmt->Add( this );
+ }
+ else if( GetRegisteredIn() )
+ GetRegisteredInNonConst()->Remove( this );
+
+}
+
+SwNumFmt::~SwNumFmt()
+{
+ delete pVertOrient;
+}
+
+void SwNumFmt::NotifyGraphicArrived()
+{
+ if( GetCharFmt() )
+ UpdateNumNodes( (SwDoc*)GetCharFmt()->GetDoc() );
+}
+
+// #i22362#
+sal_Bool SwNumFmt::IsEnumeration() const
+{
+ // --> FME 2004-08-12 #i30655# native numbering did not work any longer
+ // using this code. Therefore HBRINKM and I agreed upon defining
+ // IsEnumeration() as !IsItemize()
+ return !IsItemize();
+}
+
+
+sal_Bool SwNumFmt::IsItemize() const
+{
+ sal_Bool bResult;
+
+ switch(GetNumberingType())
+ {
+ case SVX_NUM_CHAR_SPECIAL:
+ case SVX_NUM_BITMAP:
+ bResult = sal_True;
+
+ break;
+
+ default:
+ bResult = sal_False;
+ }
+
+ return bResult;
+
+}
+
+SwNumFmt& SwNumFmt::operator=( const SwNumFmt& rNumFmt)
+{
+ SvxNumberFormat::operator=(rNumFmt);
+ if( rNumFmt.GetRegisteredIn() )
+ rNumFmt.GetRegisteredInNonConst()->Add( this );
+ else if( GetRegisteredIn() )
+ GetRegisteredInNonConst()->Remove( this );
+ return *this;
+}
+
+sal_Bool SwNumFmt::operator==( const SwNumFmt& rNumFmt) const
+{
+ sal_Bool bRet = SvxNumberFormat::operator==(rNumFmt) &&
+ GetRegisteredIn() == rNumFmt.GetRegisteredIn();
+ return bRet;
+}
+
+void SwNumFmt::SetCharFmt( SwCharFmt* pChFmt)
+{
+ if( pChFmt )
+ pChFmt->Add( this );
+ else if( GetRegisteredIn() )
+ GetRegisteredInNonConst()->Remove( this );
+}
+
+void SwNumFmt::Modify( const SfxPoolItem* pOld, const SfxPoolItem* pNew )
+{
+ // dann suche mal in dem Doc nach dem NumRules-Object, in dem dieses
+ // NumFormat gesetzt ist. Das Format muss es nicht geben!
+ const SwCharFmt* pFmt = 0;
+ sal_uInt16 nWhich = pOld ? pOld->Which() : pNew ? pNew->Which() : 0;
+ switch( nWhich )
+ {
+ case RES_ATTRSET_CHG:
+ case RES_FMT_CHG:
+ pFmt = GetCharFmt();
+ break;
+ }
+
+ if( pFmt && !pFmt->GetDoc()->IsInDtor() )
+ UpdateNumNodes( (SwDoc*)pFmt->GetDoc() );
+ else
+ CheckRegistration( pOld, pNew );
+}
+
+void SwNumFmt::SetCharFmtName(const String& rSet)
+{
+ SvxNumberFormat::SetCharFmtName(rSet);
+}
+
+const String& SwNumFmt::GetCharFmtName() const
+{
+ if((SwCharFmt*)GetRegisteredIn())
+ return ((SwCharFmt*)GetRegisteredIn())->GetName();
+ else
+ return aEmptyStr;
+}
+
+void SwNumFmt::ForgetCharFmt()
+{
+ if ( GetRegisteredIn() )
+ GetRegisteredInNonConst()->Remove( this );
+}
+
+
+void SwNumFmt::SetGraphicBrush( const SvxBrushItem* pBrushItem, const Size* pSize,
+ const sal_Int16* pOrient)
+{
+ if(pOrient)
+ pVertOrient->SetVertOrient( *pOrient );
+ SvxNumberFormat::SetGraphicBrush( pBrushItem, pSize, pOrient);
+}
+
+void SwNumFmt::SetVertOrient(sal_Int16 eSet)
+{
+ SvxNumberFormat::SetVertOrient(eSet);
+}
+
+sal_Int16 SwNumFmt::GetVertOrient() const
+{
+ return SvxNumberFormat::GetVertOrient();
+}
+
+void SwNumFmt::UpdateNumNodes( SwDoc* pDoc )
+{
+ sal_Bool bDocIsModified = pDoc->IsModified();
+ sal_Bool bFnd = sal_False;
+ const SwNumRule* pRule;
+ for( sal_uInt16 n = pDoc->GetNumRuleTbl().Count(); !bFnd && n; )
+ {
+ pRule = pDoc->GetNumRuleTbl()[ --n ];
+ for( sal_uInt8 i = 0; i < MAXLEVEL; ++i )
+ if( pRule->GetNumFmt( i ) == this )
+ {
+ SwNumRule::tTxtNodeList aTxtNodeList;
+ pRule->GetTxtNodeList( aTxtNodeList );
+ for ( SwNumRule::tTxtNodeList::iterator aIter = aTxtNodeList.begin();
+ aIter != aTxtNodeList.end(); ++aIter )
+ {
+ lcl_SetRuleChgd( *(*aIter), i );
+ }
+ // <--
+ bFnd = sal_True;
+ break;
+ }
+ }
+
+ if( bFnd && !bDocIsModified )
+ pDoc->ResetModified();
+}
+
+const SwFmtVertOrient* SwNumFmt::GetGraphicOrientation() const
+{
+ sal_Int16 eOrient = SvxNumberFormat::GetVertOrient();
+ if(text::VertOrientation::NONE == eOrient)
+ return 0;
+ else
+ {
+ pVertOrient->SetVertOrient(eOrient);
+ return pVertOrient;
+ }
+}
+
+#if OSL_DEBUG_LEVEL > 1
+long int SwNumRule::nInstances = 0;
+#endif
+
+// handle new parameter <eDefaultNumberFormatPositionAndSpaceMode>
+SwNumRule::SwNumRule( const String& rNm,
+ const SvxNumberFormat::SvxNumPositionAndSpaceMode eDefaultNumberFormatPositionAndSpaceMode,
+ SwNumRuleType eType,
+ sal_Bool bAutoFlg )
+ : maTxtNodeList(),
+ maParagraphStyleList(),
+ pNumRuleMap(0),
+ sName( rNm ),
+ eRuleType( eType ),
+ nPoolFmtId( USHRT_MAX ),
+ nPoolHelpId( USHRT_MAX ),
+ nPoolHlpFileId( UCHAR_MAX ),
+ bAutoRuleFlag( bAutoFlg ),
+ bInvalidRuleFlag( sal_True ),
+ bContinusNum( sal_False ),
+ bAbsSpaces( sal_False ),
+ mbCountPhantoms( true ),
+ meDefaultNumberFormatPositionAndSpaceMode( eDefaultNumberFormatPositionAndSpaceMode ),
+ msDefaultListId()
+{
+#if OSL_DEBUG_LEVEL > 1
+ nSerial = nInstances++;
+#endif
+
+ if( !nRefCount++ ) // zum erstmal, also initialisiern
+ {
+ SwNumFmt* pFmt;
+ sal_uInt8 n;
+
+ // numbering:
+ // position-and-space mode LABEL_WIDTH_AND_POSITION:
+ for( n = 0; n < MAXLEVEL; ++n )
+ {
+ pFmt = new SwNumFmt;
+ pFmt->SetIncludeUpperLevels( 1 );
+ pFmt->SetStart( 1 );
+ pFmt->SetLSpace( lNumIndent );
+ pFmt->SetAbsLSpace( lNumIndent + SwNumRule::GetNumIndent( n ) );
+ pFmt->SetFirstLineOffset( lNumFirstLineOffset );
+ pFmt->SetSuffix( aDotStr );
+ pFmt->SetBulletChar( numfunc::GetBulletChar(n));
+ SwNumRule::aBaseFmts[ NUM_RULE ][ n ] = pFmt;
+ }
+ // position-and-space mode LABEL_ALIGNMENT
+ // first line indent of general numbering in inch: -0,25 inch
+ const long cFirstLineIndent = -1440/4;
+ // indent values of general numbering in inch:
+ // 0,5 0,75 1,0 1,25 1,5
+ // 1,75 2,0 2,25 2,5 2,75
+ const long cIndentAt[ MAXLEVEL ] = {
+ 1440/2, 1440*3/4, 1440, 1440*5/4, 1440*3/2,
+ 1440*7/4, 1440*2, 1440*9/4, 1440*5/2, 1440*11/4 };
+ for( n = 0; n < MAXLEVEL; ++n )
+ {
+ pFmt = new SwNumFmt;
+ pFmt->SetIncludeUpperLevels( 1 );
+ pFmt->SetStart( 1 );
+ pFmt->SetPositionAndSpaceMode( SvxNumberFormat::LABEL_ALIGNMENT );
+ pFmt->SetLabelFollowedBy( SvxNumberFormat::LISTTAB );
+ pFmt->SetListtabPos( cIndentAt[ n ] );
+ pFmt->SetFirstLineIndent( cFirstLineIndent );
+ pFmt->SetIndentAt( cIndentAt[ n ] );
+ pFmt->SetSuffix( aDotStr );
+ pFmt->SetBulletChar( numfunc::GetBulletChar(n));
+ SwNumRule::aLabelAlignmentBaseFmts[ NUM_RULE ][ n ] = pFmt;
+ }
+
+ // outline:
+ // position-and-space mode LABEL_WIDTH_AND_POSITION:
+ for( n = 0; n < MAXLEVEL; ++n )
+ {
+ pFmt = new SwNumFmt;
+ pFmt->SetNumberingType(SVX_NUM_NUMBER_NONE);
+ pFmt->SetIncludeUpperLevels( MAXLEVEL );
+ pFmt->SetStart( 1 );
+ pFmt->SetCharTextDistance( lOutlineMinTextDistance );
+ pFmt->SetBulletChar( numfunc::GetBulletChar(n));
+ SwNumRule::aBaseFmts[ OUTLINE_RULE ][ n ] = pFmt;
+ }
+ // position-and-space mode LABEL_ALIGNMENT:
+ // indent values of default outline numbering in inch:
+ // 0,3 0,4 0,5 0,6 0,7
+ // 0,8 0,9 1,0 1,1 1,2
+ const long cOutlineIndentAt[ MAXLEVEL ] = {
+ 1440*3/10, 1440*2/5, 1440/2, 1440*3/5, 1440*7/10,
+ 1440*4/5, 1440*9/10, 1440, 1440*11/10, 1440*6/5 };
+ for( n = 0; n < MAXLEVEL; ++n )
+ {
+ pFmt = new SwNumFmt;
+ pFmt->SetNumberingType(SVX_NUM_NUMBER_NONE);
+ pFmt->SetIncludeUpperLevels( MAXLEVEL );
+ pFmt->SetStart( 1 );
+ pFmt->SetPositionAndSpaceMode( SvxNumberFormat::LABEL_ALIGNMENT );
+ pFmt->SetLabelFollowedBy( SvxNumberFormat::LISTTAB );
+ pFmt->SetListtabPos( cOutlineIndentAt[ n ] );
+ pFmt->SetFirstLineIndent( -cOutlineIndentAt[ n ] );
+ pFmt->SetIndentAt( cOutlineIndentAt[ n ] );
+ pFmt->SetBulletChar( numfunc::GetBulletChar(n));
+ SwNumRule::aLabelAlignmentBaseFmts[ OUTLINE_RULE ][ n ] = pFmt;
+ }
+ }
+ memset( aFmts, 0, sizeof( aFmts ));
+ OSL_ENSURE( sName.Len(), "NumRule ohne Namen!" );
+}
+
+SwNumRule::SwNumRule( const SwNumRule& rNumRule )
+ : maTxtNodeList(),
+ maParagraphStyleList(),
+ pNumRuleMap(0),
+ sName( rNumRule.sName ),
+ eRuleType( rNumRule.eRuleType ),
+ nPoolFmtId( rNumRule.GetPoolFmtId() ),
+ nPoolHelpId( rNumRule.GetPoolHelpId() ),
+ nPoolHlpFileId( rNumRule.GetPoolHlpFileId() ),
+ bAutoRuleFlag( rNumRule.bAutoRuleFlag ),
+ bInvalidRuleFlag( sal_True ),
+ bContinusNum( rNumRule.bContinusNum ),
+ bAbsSpaces( rNumRule.bAbsSpaces ),
+ mbCountPhantoms( true ),
+ meDefaultNumberFormatPositionAndSpaceMode( rNumRule.meDefaultNumberFormatPositionAndSpaceMode ),
+ msDefaultListId( rNumRule.msDefaultListId )
+{
+#if OSL_DEBUG_LEVEL > 1
+ nSerial = nInstances++;
+#endif
+
+ ++nRefCount;
+ memset( aFmts, 0, sizeof( aFmts ));
+ for( sal_uInt16 n = 0; n < MAXLEVEL; ++n )
+ if( rNumRule.aFmts[ n ] )
+ Set( n, *rNumRule.aFmts[ n ] );
+}
+
+SwNumRule::~SwNumRule()
+{
+ for( sal_uInt16 n = 0; n < MAXLEVEL; ++n )
+ delete aFmts[ n ];
+
+ if (pNumRuleMap)
+ {
+ pNumRuleMap->erase(GetName());
+ }
+
+ if( !--nRefCount ) // der letzte macht die Tuer zu
+ {
+ // Nummerierung:
+ SwNumFmt** ppFmts = (SwNumFmt**)SwNumRule::aBaseFmts;
+ int n;
+
+ for( n = 0; n < MAXLEVEL; ++n, ++ppFmts )
+ delete *ppFmts, *ppFmts = 0;
+
+ // Gliederung:
+ for( n = 0; n < MAXLEVEL; ++n, ++ppFmts )
+ delete *ppFmts, *ppFmts = 0;
+
+ ppFmts = (SwNumFmt**)SwNumRule::aLabelAlignmentBaseFmts;
+ for( n = 0; n < MAXLEVEL; ++n, ++ppFmts )
+ delete *ppFmts, *ppFmts = 0;
+ for( n = 0; n < MAXLEVEL; ++n, ++ppFmts )
+ delete *ppFmts, *ppFmts = 0;
+ }
+
+ maTxtNodeList.clear();
+ maParagraphStyleList.clear();
+}
+
+void SwNumRule::CheckCharFmts( SwDoc* pDoc )
+{
+ SwCharFmt* pFmt;
+ for( sal_uInt8 n = 0; n < MAXLEVEL; ++n )
+ if( aFmts[ n ] && 0 != ( pFmt = aFmts[ n ]->GetCharFmt() ) &&
+ pFmt->GetDoc() != pDoc )
+ {
+ // dann kopieren!
+ SwNumFmt* pNew = new SwNumFmt( *aFmts[ n ] );
+ pNew->SetCharFmt( pDoc->CopyCharFmt( *pFmt ) );
+ delete aFmts[ n ];
+ aFmts[ n ] = pNew;
+ }
+}
+
+SwNumRule& SwNumRule::operator=( const SwNumRule& rNumRule )
+{
+ if( this != &rNumRule )
+ {
+ for( sal_uInt16 n = 0; n < MAXLEVEL; ++n )
+ Set( n, rNumRule.aFmts[ n ] );
+
+ eRuleType = rNumRule.eRuleType;
+ sName = rNumRule.sName;
+ bAutoRuleFlag = rNumRule.bAutoRuleFlag;
+ bInvalidRuleFlag = sal_True;
+ bContinusNum = rNumRule.bContinusNum;
+ bAbsSpaces = rNumRule.bAbsSpaces;
+ nPoolFmtId = rNumRule.GetPoolFmtId();
+ nPoolHelpId = rNumRule.GetPoolHelpId();
+ nPoolHlpFileId = rNumRule.GetPoolHlpFileId();
+ }
+ return *this;
+}
+
+sal_Bool SwNumRule::operator==( const SwNumRule& rRule ) const
+{
+ sal_Bool bRet = eRuleType == rRule.eRuleType &&
+ sName == rRule.sName &&
+ bAutoRuleFlag == rRule.bAutoRuleFlag &&
+ bContinusNum == rRule.bContinusNum &&
+ bAbsSpaces == rRule.bAbsSpaces &&
+ nPoolFmtId == rRule.GetPoolFmtId() &&
+ nPoolHelpId == rRule.GetPoolHelpId() &&
+ nPoolHlpFileId == rRule.GetPoolHlpFileId();
+ if( bRet )
+ {
+ for( sal_uInt8 n = 0; n < MAXLEVEL; ++n )
+ if( !( rRule.Get( n ) == Get( n ) ))
+ {
+ bRet = sal_False;
+ break;
+ }
+ }
+ return bRet;
+}
+
+void SwNumRule::Set( sal_uInt16 i, const SwNumFmt& rNumFmt )
+{
+ OSL_ENSURE( i < MAXLEVEL, "Serious defect, please inform OD" );
+ if( i < MAXLEVEL )
+ {
+ if( !aFmts[ i ] || !(rNumFmt == Get( i )) )
+ {
+ delete aFmts[ i ];
+ aFmts[ i ] = new SwNumFmt( rNumFmt );
+ bInvalidRuleFlag = sal_True;
+ }
+ }
+}
+
+void SwNumRule::Set( sal_uInt16 i, const SwNumFmt* pNumFmt )
+{
+ OSL_ENSURE( i < MAXLEVEL, "Serious defect, please inform OD" );
+ if( i >= MAXLEVEL )
+ return;
+ SwNumFmt* pOld = aFmts[ i ];
+ if( !pOld )
+ {
+ if( pNumFmt )
+ {
+ aFmts[ i ] = new SwNumFmt( *pNumFmt );
+ bInvalidRuleFlag = sal_True;
+ }
+ }
+ else if( !pNumFmt )
+ delete pOld, aFmts[ i ] = 0, bInvalidRuleFlag = sal_True;
+ else if( *pOld != *pNumFmt )
+ *pOld = *pNumFmt, bInvalidRuleFlag = sal_True;
+}
+
+String SwNumRule::MakeNumString( const SwNodeNum& rNum, sal_Bool bInclStrings,
+ sal_Bool bOnlyArabic ) const
+{
+ String aStr;
+
+ if (rNum.IsCounted())
+ aStr = MakeNumString(rNum.GetNumberVector(),
+ bInclStrings, bOnlyArabic, MAXLEVEL);
+
+ return aStr;
+}
+
+String SwNumRule::MakeNumString( const SwNumberTree::tNumberVector & rNumVector,
+ const sal_Bool bInclStrings,
+ const sal_Bool bOnlyArabic,
+ const unsigned int _nRestrictToThisLevel ) const
+{
+ String aStr;
+
+ unsigned int nLevel = rNumVector.size() - 1;
+
+ if ( nLevel > _nRestrictToThisLevel )
+ {
+ nLevel = _nRestrictToThisLevel;
+ }
+
+ if (nLevel < MAXLEVEL)
+ {
+ const SwNumFmt& rMyNFmt = Get( static_cast<sal_uInt16>(nLevel) );
+
+ {
+ sal_uInt8 i = static_cast<sal_uInt8>(nLevel);
+
+ if( !IsContinusNum() &&
+ // - do not include upper levels, if level isn't numbered.
+ rMyNFmt.GetNumberingType() != SVX_NUM_NUMBER_NONE &&
+ rMyNFmt.GetIncludeUpperLevels() ) // nur der eigene Level ?
+ {
+ sal_uInt8 n = rMyNFmt.GetIncludeUpperLevels();
+ if( 1 < n )
+ {
+ if( i+1 >= n )
+ i -= n - 1;
+ else
+ i = 0;
+ }
+ }
+
+ for( ; i <= nLevel; ++i )
+ {
+ const SwNumFmt& rNFmt = Get( i );
+ if( SVX_NUM_NUMBER_NONE == rNFmt.GetNumberingType() )
+ {
+ // Soll aus 1.1.1 --> 2. NoNum --> 1..1 oder 1.1 ??
+ // if( i != rNum.nMyLevel )
+ // aStr += aDotStr;
+ continue;
+ }
+
+ if( rNumVector[ i ] )
+ {
+ if( bOnlyArabic )
+ aStr += String::CreateFromInt32( rNumVector[ i ] );
+ else
+ aStr += rNFmt.GetNumStr( rNumVector[ i ] );
+ }
+ else
+ aStr += '0'; // alle 0-Level sind eine 0
+ if( i != nLevel && aStr.Len() )
+ aStr += aDotStr;
+ }
+
+ //JP 14.12.99: the type dont have any number, so dont append
+ // the Post-/Prefix String
+ if( bInclStrings && !bOnlyArabic &&
+ SVX_NUM_CHAR_SPECIAL != rMyNFmt.GetNumberingType() &&
+ SVX_NUM_BITMAP != rMyNFmt.GetNumberingType() )
+ {
+ aStr.Insert( rMyNFmt.GetPrefix(), 0 );
+ aStr += rMyNFmt.GetSuffix();
+ }
+ }
+ }
+
+ return aStr;
+}
+
+
+String SwNumRule::MakeRefNumString( const SwNodeNum& rNodeNum,
+ const bool bInclSuperiorNumLabels,
+ const sal_uInt8 nRestrictInclToThisLevel ) const
+{
+ String aRefNumStr;
+
+ if ( rNodeNum.GetLevelInListTree() >= 0 )
+ {
+ const SwNodeNum* pWorkingNodeNum( &rNodeNum );
+ do
+ {
+ bool bMakeNumStringForPhantom( false );
+ if ( pWorkingNodeNum->IsPhantom() )
+ {
+ SwNumFmt aFmt( Get( static_cast<sal_uInt16>(pWorkingNodeNum->GetLevelInListTree()) ) );
+ bMakeNumStringForPhantom = aFmt.IsEnumeration() &&
+ SVX_NUM_NUMBER_NONE != aFmt.GetNumberingType();
+
+ }
+ if ( bMakeNumStringForPhantom ||
+ ( !pWorkingNodeNum->IsPhantom() &&
+ pWorkingNodeNum->GetTxtNode() &&
+ pWorkingNodeNum->GetTxtNode()->HasNumber() ) )
+ {
+ aRefNumStr.Insert( MakeNumString( pWorkingNodeNum->GetNumberVector() ), 0 );
+ }
+ else if ( aRefNumStr.Len() > 0 )
+ {
+ aRefNumStr.Insert( String::CreateFromAscii(" "), 0 );
+ }
+
+ if ( bInclSuperiorNumLabels && pWorkingNodeNum->GetLevelInListTree() > 0 )
+ {
+ sal_uInt8 n = Get( static_cast<sal_uInt16>(pWorkingNodeNum->GetLevelInListTree()) ).GetIncludeUpperLevels();
+ pWorkingNodeNum = dynamic_cast<SwNodeNum*>(pWorkingNodeNum->GetParent());
+ // skip parents, whose list label is already contained in the actual list label.
+ while ( pWorkingNodeNum && n > 1 )
+ {
+ pWorkingNodeNum = dynamic_cast<SwNodeNum*>(pWorkingNodeNum->GetParent());
+ --n;
+ }
+ }
+ else
+ {
+ break;
+ }
+ } while ( pWorkingNodeNum &&
+ pWorkingNodeNum->GetLevelInListTree() >= 0 &&
+ static_cast<sal_uInt8>(pWorkingNodeNum->GetLevelInListTree()) >= nRestrictInclToThisLevel );
+ }
+
+ return aRefNumStr;
+}
+
+// ----- Copy-Methode vom SwNumRule ------
+
+ // eine Art Copy-Constructor, damit die Num-Formate auch an den
+ // richtigen CharFormaten eines Dokumentes haengen !!
+ // (Kopiert die NumFormate und returnt sich selbst)
+SwNumRule& SwNumRule::CopyNumRule( SwDoc* pDoc, const SwNumRule& rNumRule )
+{
+ for( sal_uInt16 n = 0; n < MAXLEVEL; ++n )
+ {
+ Set( n, rNumRule.aFmts[ n ] );
+ if( aFmts[ n ] && aFmts[ n ]->GetCharFmt() &&
+ USHRT_MAX == pDoc->GetCharFmts()->GetPos( aFmts[n]->GetCharFmt() ))
+ // ueber unterschiedliche Dokumente kopieren, dann
+ // kopiere das entsprechende Char-Format ins neue
+ // Dokument.
+ aFmts[n]->SetCharFmt( pDoc->CopyCharFmt( *aFmts[n]->
+ GetCharFmt() ) );
+ }
+ eRuleType = rNumRule.eRuleType;
+ sName = rNumRule.sName;
+ bAutoRuleFlag = rNumRule.bAutoRuleFlag;
+ nPoolFmtId = rNumRule.GetPoolFmtId();
+ nPoolHelpId = rNumRule.GetPoolHelpId();
+ nPoolHlpFileId = rNumRule.GetPoolHlpFileId();
+ bInvalidRuleFlag = sal_True;
+ return *this;
+}
+
+void SwNumRule::SetSvxRule(const SvxNumRule& rNumRule, SwDoc* pDoc)
+{
+ for( sal_uInt16 n = 0; n < MAXLEVEL; ++n )
+ {
+ const SvxNumberFormat* pSvxFmt = rNumRule.Get(n);
+ delete aFmts[n];
+ aFmts[n] = pSvxFmt ? new SwNumFmt(*pSvxFmt, pDoc) : 0;
+ }
+
+ bInvalidRuleFlag = sal_True;
+ bContinusNum = rNumRule.IsContinuousNumbering();
+}
+
+SvxNumRule SwNumRule::MakeSvxNumRule() const
+{
+ SvxNumRule aRule(NUM_CONTINUOUS|NUM_CHAR_TEXT_DISTANCE|NUM_CHAR_STYLE|
+ NUM_ENABLE_LINKED_BMP|NUM_ENABLE_EMBEDDED_BMP,
+ MAXLEVEL, bContinusNum,
+ eRuleType ==
+ NUM_RULE ?
+ SVX_RULETYPE_NUMBERING :
+ SVX_RULETYPE_OUTLINE_NUMBERING );
+ for( sal_uInt16 n = 0; n < MAXLEVEL; ++n )
+ {
+ SwNumFmt aNumFmt = Get(n);
+ if(aNumFmt.GetCharFmt())
+ aNumFmt.SetCharFmtName(aNumFmt.GetCharFmt()->GetName());
+ aRule.SetLevel(n, aNumFmt, aFmts[n] != 0);
+ }
+ return aRule;
+}
+
+void SwNumRule::SetInvalidRule(sal_Bool bFlag)
+{
+ if (bFlag)
+ {
+ std::set< SwList* > aLists;
+ tTxtNodeList::iterator aIter;
+ for ( aIter = maTxtNodeList.begin(); aIter != maTxtNodeList.end(); ++aIter )
+ {
+ const SwTxtNode* pTxtNode = *aIter;
+ // #i111681# - applying patch from cmc
+ SwList* pList = pTxtNode->GetDoc()->getListByName( pTxtNode->GetListId() );
+ OSL_ENSURE( pList, "<SwNumRule::SetInvalidRule(..)> - list at which the text node is registered at does not exist. This is a serious issue --> please inform OD.");
+ if ( pList )
+ {
+ aLists.insert( pList );
+ }
+ // <--
+ }
+ std::for_each( aLists.begin(), aLists.end(),
+ std::mem_fun( &SwList::InvalidateListTree ) );
+ // <--
+ }
+
+ bInvalidRuleFlag = bFlag;
+}
+
+
+// change indent of all list levels by given difference
+void SwNumRule::ChangeIndent( const short nDiff )
+{
+ for ( sal_uInt16 i = 0; i < MAXLEVEL; ++i )
+ {
+ SwNumFmt aTmpNumFmt( Get(i) );
+
+ const SvxNumberFormat::SvxNumPositionAndSpaceMode ePosAndSpaceMode(
+ aTmpNumFmt.GetPositionAndSpaceMode() );
+ if ( ePosAndSpaceMode == SvxNumberFormat::LABEL_WIDTH_AND_POSITION )
+ {
+ short nNewIndent = nDiff +
+ aTmpNumFmt.GetAbsLSpace();
+ if ( nNewIndent < 0 )
+ {
+ nNewIndent = 0;
+ }
+ aTmpNumFmt.SetAbsLSpace( nNewIndent );
+ }
+ else if ( ePosAndSpaceMode == SvxNumberFormat::LABEL_ALIGNMENT )
+ {
+ // adjust also the list tab position, if a list tab stop is applied
+ if ( aTmpNumFmt.GetLabelFollowedBy() == SvxNumberFormat::LISTTAB )
+ {
+ const long nNewListTab = aTmpNumFmt.GetListtabPos() + nDiff;
+ aTmpNumFmt.SetListtabPos( nNewListTab );
+ }
+
+ const long nNewIndent = nDiff +
+ aTmpNumFmt.GetIndentAt();
+ aTmpNumFmt.SetIndentAt( nNewIndent );
+ }
+
+ Set( i, aTmpNumFmt );
+ }
+
+ SetInvalidRule( sal_True );
+}
+
+// set indent of certain list level to given value
+void SwNumRule::SetIndent( const short nNewIndent,
+ const sal_uInt16 nListLevel )
+{
+ SwNumFmt aTmpNumFmt( Get(nListLevel) );
+
+ const SvxNumberFormat::SvxNumPositionAndSpaceMode ePosAndSpaceMode(
+ aTmpNumFmt.GetPositionAndSpaceMode() );
+ if ( ePosAndSpaceMode == SvxNumberFormat::LABEL_WIDTH_AND_POSITION )
+ {
+ aTmpNumFmt.SetAbsLSpace( nNewIndent );
+ }
+ else if ( ePosAndSpaceMode == SvxNumberFormat::LABEL_ALIGNMENT )
+ {
+ // adjust also the list tab position, if a list tab stop is applied
+ if ( aTmpNumFmt.GetLabelFollowedBy() == SvxNumberFormat::LISTTAB )
+ {
+ const long nNewListTab = aTmpNumFmt.GetListtabPos() +
+ ( nNewIndent - aTmpNumFmt.GetIndentAt() );
+ aTmpNumFmt.SetListtabPos( nNewListTab );
+ }
+
+ aTmpNumFmt.SetIndentAt( nNewIndent );
+ }
+
+ SetInvalidRule( sal_True );
+}
+
+// set indent of first list level to given value and change other list level's
+// indents accordingly
+void SwNumRule::SetIndentOfFirstListLevelAndChangeOthers( const short nNewIndent )
+{
+ SwNumFmt aTmpNumFmt( Get(0) );
+
+ short nDiff( 0 );
+ const SvxNumberFormat::SvxNumPositionAndSpaceMode ePosAndSpaceMode(
+ aTmpNumFmt.GetPositionAndSpaceMode() );
+ if ( ePosAndSpaceMode == SvxNumberFormat::LABEL_WIDTH_AND_POSITION )
+ {
+ nDiff = nNewIndent
+ - aTmpNumFmt.GetFirstLineOffset()
+ - aTmpNumFmt.GetAbsLSpace();
+ }
+ else if ( ePosAndSpaceMode == SvxNumberFormat::LABEL_ALIGNMENT )
+ {
+ nDiff = static_cast<short>(nNewIndent
+ - aTmpNumFmt.GetIndentAt());
+ }
+ if ( nDiff != 0 )
+ {
+ ChangeIndent( nDiff );
+ }
+}
+
+
+void SwNumRule::Validate()
+{
+ std::set< SwList* > aLists;
+ tTxtNodeList::iterator aIter;
+ for ( aIter = maTxtNodeList.begin(); aIter != maTxtNodeList.end(); ++aIter )
+ {
+ const SwTxtNode* pTxtNode = *aIter;
+ aLists.insert( pTxtNode->GetDoc()->getListByName( pTxtNode->GetListId() ) );
+ }
+ std::for_each( aLists.begin(), aLists.end(),
+ std::mem_fun( &SwList::ValidateListTree ) );
+
+
+ SetInvalidRule(sal_False);
+}
+
+
+bool SwNumRule::IsCountPhantoms() const
+{
+ return mbCountPhantoms;
+}
+
+
+void SwNumRule::SetCountPhantoms(bool bCountPhantoms)
+{
+ mbCountPhantoms = bCountPhantoms;
+}
+
+
+SwNumRule::tParagraphStyleList::size_type SwNumRule::GetParagraphStyleListSize() const
+{
+ return maParagraphStyleList.size();
+}
+
+
+void SwNumRule::AddParagraphStyle( SwTxtFmtColl& rTxtFmtColl )
+{
+ tParagraphStyleList::iterator aIter =
+ std::find( maParagraphStyleList.begin(), maParagraphStyleList.end(), &rTxtFmtColl );
+
+ if ( aIter == maParagraphStyleList.end() )
+ {
+ maParagraphStyleList.push_back( &rTxtFmtColl );
+ }
+}
+
+
+void SwNumRule::RemoveParagraphStyle( SwTxtFmtColl& rTxtFmtColl )
+{
+ tParagraphStyleList::iterator aIter =
+ std::find( maParagraphStyleList.begin(), maParagraphStyleList.end(), &rTxtFmtColl );
+
+ if ( aIter != maParagraphStyleList.end() )
+ {
+ maParagraphStyleList.erase( aIter );
+ }
+}
+
+
+namespace numfunc
+{
+ /** class containing default bullet list configuration data
+
+ @author OD
+ */
+ class SwDefBulletConfig : private utl::ConfigItem
+ {
+ public:
+ static SwDefBulletConfig* getInstance()
+ {
+ if ( mpInstance == 0 )
+ {
+ mpInstance = new SwDefBulletConfig;
+ }
+
+ return mpInstance;
+ }
+
+ inline const String& GetFontname() const
+ {
+ return msFontname;
+ }
+
+ inline bool IsFontnameUserDefined() const
+ {
+ return mbUserDefinedFontname;
+ }
+
+ inline const Font& GetFont() const
+ {
+ return *mpFont;
+ }
+
+ inline short GetFontWeight() const
+ {
+ return static_cast<short>(meFontWeight);
+ }
+
+ inline short GetFontItalic() const
+ {
+ return static_cast<short>(meFontItalic);
+ }
+ inline sal_Unicode GetChar( sal_uInt8 p_nListLevel ) const
+ {
+ if ( p_nListLevel > MAXLEVEL )
+ {
+ p_nListLevel = MAXLEVEL;
+ }
+
+ return mnLevelChars[p_nListLevel];
+ }
+
+ private:
+ SwDefBulletConfig();
+
+ /** sets internal default bullet configuration data to default values
+
+ @author OD
+ */
+ void SetToDefault();
+
+ /** returns sequence of default bullet configuration property names
+
+ @author OD
+ */
+ uno::Sequence<rtl::OUString> GetPropNames() const;
+
+ /** loads default bullet configuration properties and applies
+ values to internal data
+
+ @author OD
+ */
+ void LoadConfig();
+
+ /** initialize font instance for default bullet list
+
+ @author OD
+ */
+ void InitFont();
+
+ /** catches notification about changed default bullet configuration data
+
+ @author OD
+ */
+ virtual void Notify( const uno::Sequence<rtl::OUString>& aPropertyNames );
+ virtual void Commit();
+
+ static SwDefBulletConfig* mpInstance;
+
+ // default bullet list configuration data
+ String msFontname;
+ bool mbUserDefinedFontname;
+ FontWeight meFontWeight;
+ FontItalic meFontItalic;
+ sal_Unicode mnLevelChars[MAXLEVEL];
+
+ // default bullet list font instance
+ Font* mpFont;
+ };
+
+ SwDefBulletConfig* SwDefBulletConfig::mpInstance = 0;
+
+ SwDefBulletConfig::SwDefBulletConfig()
+ : ConfigItem( rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Office.Writer/Numbering/DefaultBulletList")) ),
+ // default bullet font is now OpenSymbol
+ msFontname( String::CreateFromAscii("OpenSymbol") ),
+ mbUserDefinedFontname( false ),
+ meFontWeight( WEIGHT_DONTKNOW ),
+ meFontItalic( ITALIC_NONE ),
+ mpFont( 0 )
+ {
+ SetToDefault();
+ LoadConfig();
+ InitFont();
+
+ // enable notification for changes on default bullet configuration change
+ EnableNotification( GetPropNames() );
+ }
+
+ void SwDefBulletConfig::SetToDefault()
+ {
+ msFontname = String::CreateFromAscii("OpenSymbol");
+ mbUserDefinedFontname = false;
+ // <--
+ meFontWeight = WEIGHT_DONTKNOW;
+ meFontItalic = ITALIC_NONE;
+
+ mnLevelChars[0] = 0x2022;
+ mnLevelChars[1] = 0x25e6;
+ mnLevelChars[2] = 0x25aa;
+ mnLevelChars[3] = 0x2022;
+ mnLevelChars[4] = 0x25e6;
+ mnLevelChars[5] = 0x25aa;
+ mnLevelChars[6] = 0x2022;
+ mnLevelChars[7] = 0x25e6;
+ mnLevelChars[8] = 0x25aa;
+ mnLevelChars[9] = 0x2022;
+ }
+
+ uno::Sequence<rtl::OUString> SwDefBulletConfig::GetPropNames() const
+ {
+ uno::Sequence<rtl::OUString> aPropNames(13);
+ rtl::OUString* pNames = aPropNames.getArray();
+ pNames[0] = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("BulletFont/FontFamilyname"));
+ pNames[1] = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("BulletFont/FontWeight"));
+ pNames[2] = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("BulletFont/FontItalic"));
+ pNames[3] = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("BulletCharLvl1"));
+ pNames[4] = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("BulletCharLvl2"));
+ pNames[5] = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("BulletCharLvl3"));
+ pNames[6] = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("BulletCharLvl4"));
+ pNames[7] = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("BulletCharLvl5"));
+ pNames[8] = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("BulletCharLvl6"));
+ pNames[9] = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("BulletCharLvl7"));
+ pNames[10] = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("BulletCharLvl8"));
+ pNames[11] = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("BulletCharLvl9"));
+ pNames[12] = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("BulletCharLvl10"));
+
+ return aPropNames;
+ }
+
+ void SwDefBulletConfig::LoadConfig()
+ {
+ uno::Sequence<rtl::OUString> aPropNames = GetPropNames();
+ uno::Sequence<uno::Any> aValues =
+ GetProperties( aPropNames );
+ const uno::Any* pValues = aValues.getConstArray();
+ OSL_ENSURE( aValues.getLength() == aPropNames.getLength(),
+ "<SwDefBulletConfig::SwDefBulletConfig()> - GetProperties failed");
+ if ( aValues.getLength() == aPropNames.getLength() )
+ {
+ for ( int nProp = 0; nProp < aPropNames.getLength(); ++nProp )
+ {
+ if ( pValues[nProp].hasValue() )
+ {
+ switch ( nProp )
+ {
+ case 0:
+ {
+ rtl::OUString aStr;
+ pValues[nProp] >>= aStr;
+ msFontname = aStr;
+ mbUserDefinedFontname = true;
+ }
+ break;
+ case 1:
+ case 2:
+ {
+ sal_uInt8 nTmp = 0;
+ pValues[nProp] >>= nTmp;
+ if ( nProp == 1 )
+ meFontWeight = static_cast<FontWeight>(nTmp);
+ else if ( nProp == 2 )
+ meFontItalic = static_cast<FontItalic>(nTmp);
+ }
+ break;
+ case 3:
+ case 4:
+ case 5:
+ case 6:
+ case 7:
+ case 8:
+ case 9:
+ case 10:
+ case 11:
+ case 12:
+ {
+ sal_Unicode cChar = sal_Unicode();
+ pValues[nProp] >>= cChar;
+ mnLevelChars[nProp-3] = cChar;
+ }
+ break;
+ }
+ }
+ }
+ }
+
+ }
+
+ void SwDefBulletConfig::InitFont()
+ {
+ delete mpFont;
+
+ mpFont = new Font( msFontname, aEmptyStr, Size( 0, 14 ) );
+ mpFont->SetWeight( meFontWeight );
+ mpFont->SetItalic( meFontItalic );
+ }
+
+ void SwDefBulletConfig::Notify( const uno::Sequence<rtl::OUString>& )
+ {
+ SetToDefault();
+ LoadConfig();
+ InitFont();
+ }
+
+ void SwDefBulletConfig::Commit()
+ {
+ }
+
+ const String& GetDefBulletFontname()
+ {
+ return SwDefBulletConfig::getInstance()->GetFontname();
+ }
+
+ bool IsDefBulletFontUserDefined()
+ {
+ return SwDefBulletConfig::getInstance()->IsFontnameUserDefined();
+ }
+
+ const Font& GetDefBulletFont()
+ {
+ return SwDefBulletConfig::getInstance()->GetFont();
+ }
+
+ sal_Unicode GetBulletChar( sal_uInt8 nLevel )
+ {
+ return SwDefBulletConfig::getInstance()->GetChar( nLevel );
+ }
+
+ /** class containing configuration data about user interface behavior
+ regarding lists and list items.
+ configuration item about behavior of <TAB>/<SHIFT-TAB>-key at first
+ position of first list item
+
+ @author OD
+ */
+ class SwNumberingUIBehaviorConfig : private utl::ConfigItem
+ {
+ public:
+ static SwNumberingUIBehaviorConfig* getInstance()
+ {
+ if ( mpInstance == 0 )
+ {
+ mpInstance = new SwNumberingUIBehaviorConfig();
+ }
+
+ return mpInstance;
+ }
+
+ inline sal_Bool ChangeIndentOnTabAtFirstPosOfFirstListItem() const
+ {
+ return mbChangeIndentOnTabAtFirstPosOfFirstListItem;
+ }
+
+ private:
+ SwNumberingUIBehaviorConfig();
+
+ /** sets internal configuration data to default values
+
+ @author OD
+ */
+ void SetToDefault();
+
+ /** returns sequence of configuration property names
+
+ @author OD
+ */
+ com::sun::star::uno::Sequence<rtl::OUString> GetPropNames() const;
+
+ /** loads configuration properties and applies values to internal data
+
+ @author OD
+ */
+ void LoadConfig();
+
+ /** catches notification about changed configuration data
+
+ @author OD
+ */
+ virtual void Notify( const com::sun::star::uno::Sequence<rtl::OUString>& aPropertyNames );
+ virtual void Commit();
+
+ static SwNumberingUIBehaviorConfig* mpInstance;
+
+ // configuration data
+ sal_Bool mbChangeIndentOnTabAtFirstPosOfFirstListItem;
+ };
+
+ SwNumberingUIBehaviorConfig* SwNumberingUIBehaviorConfig::mpInstance = 0;
+
+ SwNumberingUIBehaviorConfig::SwNumberingUIBehaviorConfig()
+ : ConfigItem( rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Office.Writer/Numbering/UserInterfaceBehavior")) ),
+ mbChangeIndentOnTabAtFirstPosOfFirstListItem( sal_True )
+ {
+ SetToDefault();
+ LoadConfig();
+
+ // enable notification for changes on configuration change
+ EnableNotification( GetPropNames() );
+ }
+
+ void SwNumberingUIBehaviorConfig::SetToDefault()
+ {
+ mbChangeIndentOnTabAtFirstPosOfFirstListItem = sal_True;
+ }
+
+ com::sun::star::uno::Sequence<rtl::OUString> SwNumberingUIBehaviorConfig::GetPropNames() const
+ {
+ com::sun::star::uno::Sequence<rtl::OUString> aPropNames(1);
+ rtl::OUString* pNames = aPropNames.getArray();
+ pNames[0] = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("ChangeIndentOnTabAtFirstPosOfFirstListItem"));
+
+ return aPropNames;
+ }
+
+ void SwNumberingUIBehaviorConfig::Commit() {}
+
+ void SwNumberingUIBehaviorConfig::LoadConfig()
+ {
+ com::sun::star::uno::Sequence<rtl::OUString> aPropNames = GetPropNames();
+ com::sun::star::uno::Sequence<com::sun::star::uno::Any> aValues =
+ GetProperties( aPropNames );
+ const com::sun::star::uno::Any* pValues = aValues.getConstArray();
+ OSL_ENSURE( aValues.getLength() == aPropNames.getLength(),
+ "<SwNumberingUIBehaviorConfig::LoadConfig()> - GetProperties failed");
+ if ( aValues.getLength() == aPropNames.getLength() )
+ {
+ for ( int nProp = 0; nProp < aPropNames.getLength(); ++nProp )
+ {
+ if ( pValues[nProp].hasValue() )
+ {
+ switch ( nProp )
+ {
+ case 0:
+ {
+ pValues[nProp] >>= mbChangeIndentOnTabAtFirstPosOfFirstListItem;
+ }
+ break;
+ default:
+ {
+ OSL_FAIL( "<SwNumberingUIBehaviorConfig::LoadConfig()> - unknown configuration property");
+ }
+ }
+ }
+ }
+ }
+ }
+
+ void SwNumberingUIBehaviorConfig::Notify( const com::sun::star::uno::Sequence<rtl::OUString>& aPropertyNames )
+ {
+ (void) aPropertyNames;
+ SetToDefault();
+ LoadConfig();
+ }
+
+ sal_Bool ChangeIndentOnTabAtFirstPosOfFirstListItem()
+ {
+ return SwNumberingUIBehaviorConfig::getInstance()->ChangeIndentOnTabAtFirstPosOfFirstListItem();
+ }
+
+ SvxNumberFormat::SvxNumPositionAndSpaceMode GetDefaultPositionAndSpaceMode()
+ {
+ SvxNumberFormat::SvxNumPositionAndSpaceMode ePosAndSpaceMode;
+ SvtSaveOptions aSaveOptions;
+ switch ( aSaveOptions.GetODFDefaultVersion() )
+ {
+ case SvtSaveOptions::ODFVER_010:
+ case SvtSaveOptions::ODFVER_011:
+ {
+ ePosAndSpaceMode = SvxNumberFormat::LABEL_WIDTH_AND_POSITION;
+ }
+ break;
+ default: // ODFVER_UNKNOWN or ODFVER_012
+ {
+ ePosAndSpaceMode = SvxNumberFormat::LABEL_ALIGNMENT;
+ }
+ }
+
+ return ePosAndSpaceMode;
+ }
+ // <--
+}
+// <--
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/doc/poolfmt.cxx b/sw/source/core/doc/poolfmt.cxx
new file mode 100644
index 000000000000..5212f709f1ee
--- /dev/null
+++ b/sw/source/core/doc/poolfmt.cxx
@@ -0,0 +1,2507 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+#include <hintids.hxx>
+#include <i18npool/mslangid.hxx>
+#include <unotools/localedatawrapper.hxx>
+#include <editeng/paperinf.hxx>
+#include <editeng/wghtitem.hxx>
+#include <editeng/fontitem.hxx>
+#include <editeng/fhgtitem.hxx>
+#include <editeng/tstpitem.hxx>
+#include <editeng/lrspitem.hxx>
+#include <editeng/ulspitem.hxx>
+#include <editeng/adjitem.hxx>
+#include <editeng/postitem.hxx>
+#include <editeng/keepitem.hxx>
+#include <editeng/opaqitem.hxx>
+#include <editeng/boxitem.hxx>
+#include <editeng/cmapitem.hxx>
+#include <editeng/udlnitem.hxx>
+#include <editeng/colritem.hxx>
+#include <editeng/protitem.hxx>
+#include <editeng/escpitem.hxx>
+#include <editeng/langitem.hxx>
+#include <editeng/charrotateitem.hxx>
+#include <editeng/frmdiritem.hxx>
+#include <editeng/emphitem.hxx>
+#include <editeng/scriptspaceitem.hxx>
+#include <viewopt.hxx>
+#include <doc.hxx>
+#include <IDocumentUndoRedo.hxx>
+#include <fmtanchr.hxx>
+#include <fmtornt.hxx>
+#include <fmtsrnd.hxx>
+#include <fmtfsize.hxx>
+#include <poolfmt.hxx>
+#include <paratr.hxx>
+#include <pagedesc.hxx>
+#include <frmtool.hxx>
+#include <charfmt.hxx>
+#include <docary.hxx>
+#include <fmtcol.hxx>
+#include <ndtxt.hxx>
+#include <fmtline.hxx>
+#include <poolfmt.hrc>
+#include <GetMetricVal.hxx>
+#include <numrule.hxx>
+
+
+using namespace ::editeng;
+using namespace ::com::sun::star;
+
+const sal_uInt16 PT_3 = 3 * 20; // 3 pt
+const sal_uInt16 PT_6 = 6 * 20; // 6 pt
+const sal_uInt16 PT_7 = 7 * 20; // 6 pt
+const sal_uInt16 PT_8 = 8 * 20; // 8 pt
+const sal_uInt16 PT_9 = 9 * 20; // 9 pt
+const sal_uInt16 PT_10 = 10 * 20; // 10 pt
+const sal_uInt16 PT_11 = 11 * 20; // 11 pt
+const sal_uInt16 PT_12 = 12 * 20; // 12 pt
+const sal_uInt16 PT_14 = 14 * 20; // 14 pt
+const sal_uInt16 PT_16 = 16 * 20; // 16 pt
+const sal_uInt16 PT_18 = 18 * 20; // 18 pt
+const sal_uInt16 PT_22 = 22 * 20; // 22 pt
+const sal_uInt16 PT_24 = 24 * 20; // 22 pt
+
+
+//const sal_uInt16 HTML_PARSPACE = ((CM_05 * 7) / 10);
+#define HTML_PARSPACE GetMetricVal( CM_05 )
+
+static const sal_Char sKomma[] = ", ";
+
+static const sal_uInt16 aHeadlineSizes[ 2 * MAXLEVEL ] = {
+// PT_16, PT_14, PT_14, PT_12, PT_12, // normal
+//JP 10.12.96: jetzt soll alles prozentual sein:
+ 115, 100, 100, 85, 85,
+ 75, 75, 75, 75, 75, // normal
+// PT_22, PT_16, PT_12, PT_11, PT_9 // HTML-Mode
+ PT_24, PT_18, PT_14, PT_12, PT_10,
+ PT_7, PT_7, PT_7, PT_7, PT_7 // HTML-Mode
+};
+
+long lcl_GetRightMargin( SwDoc& rDoc )
+{
+ // sorge dafuer, dass die Druckereinstellungen in die Standard-
+ // Seitenvorlage uebernommen wurden.
+ const SwFrmFmt& rPgDscFmt =
+ const_cast<const SwDoc *>(&rDoc)->GetPageDesc( 0 ).GetMaster();
+ const SvxLRSpaceItem& rLR = rPgDscFmt.GetLRSpace();
+ const long nLeft = rLR.GetLeft();
+ const long nRight = rLR.GetRight();
+ const long nWidth = rPgDscFmt.GetFrmSize().GetWidth();
+ return nWidth - nLeft - nRight;
+}
+
+void SetAllScriptItem( SfxItemSet& rSet, const SfxPoolItem& rItem )
+{
+ rSet.Put( rItem );
+ sal_uInt16 nWhCJK = 0, nWhCTL = 0;
+ switch( rItem.Which() )
+ {
+ case RES_CHRATR_FONTSIZE:
+ nWhCJK = RES_CHRATR_CJK_FONTSIZE, nWhCTL = RES_CHRATR_CTL_FONTSIZE;
+ break;
+ case RES_CHRATR_FONT:
+ nWhCJK = RES_CHRATR_CJK_FONT, nWhCTL = RES_CHRATR_CTL_FONT;
+ break;
+ case RES_CHRATR_LANGUAGE:
+ nWhCJK = RES_CHRATR_CJK_LANGUAGE, nWhCTL = RES_CHRATR_CTL_LANGUAGE;
+ break;
+ case RES_CHRATR_POSTURE:
+ nWhCJK = RES_CHRATR_CJK_POSTURE, nWhCTL = RES_CHRATR_CTL_POSTURE;
+ break;
+ case RES_CHRATR_WEIGHT:
+ nWhCJK = RES_CHRATR_CJK_WEIGHT, nWhCTL = RES_CHRATR_CTL_WEIGHT;
+ break;
+ }
+
+ if( nWhCJK )
+ rSet.Put( rItem, nWhCJK );
+ if( nWhCTL )
+ rSet.Put( rItem, nWhCTL );
+}
+
+void lcl_SetDfltFont( sal_uInt16 nFntType, SfxItemSet& rSet )
+{
+ static struct {
+ sal_uInt16 nResLngId;
+ sal_uInt16 nResFntId;
+ } aArr[ 3 ] = {
+ { RES_CHRATR_LANGUAGE, RES_CHRATR_FONT },
+ { RES_CHRATR_CJK_LANGUAGE, RES_CHRATR_CJK_FONT },
+ { RES_CHRATR_CTL_LANGUAGE, RES_CHRATR_CTL_FONT }
+ };
+ for( sal_uInt16 n = 0; n < 3; ++n )
+ {
+ sal_uInt16 nLng = ((SvxLanguageItem&)rSet.GetPool()->GetDefaultItem(
+ aArr[n].nResLngId )).GetLanguage();
+ Font aFnt( OutputDevice::GetDefaultFont( nFntType,
+ nLng, DEFAULTFONT_FLAGS_ONLYONE ) );
+
+ rSet.Put( SvxFontItem( aFnt.GetFamily(), aFnt.GetName(),
+ aEmptyStr, aFnt.GetPitch(),
+ aFnt.GetCharSet(), aArr[n].nResFntId ));
+ }
+}
+
+void lcl_SetDfltFont( sal_uInt16 nLatinFntType, sal_uInt16 nCJKFntType,
+ sal_uInt16 nCTLFntType, SfxItemSet& rSet )
+{
+ static struct {
+ sal_uInt16 nResLngId;
+ sal_uInt16 nResFntId;
+ sal_uInt16 nFntType;
+ } aArr[ 3 ] = {
+ { RES_CHRATR_LANGUAGE, RES_CHRATR_FONT, 0 },
+ { RES_CHRATR_CJK_LANGUAGE, RES_CHRATR_CJK_FONT, 0 },
+ { RES_CHRATR_CTL_LANGUAGE, RES_CHRATR_CTL_FONT, 0 }
+ };
+ aArr[0].nFntType = nLatinFntType;
+ aArr[1].nFntType = nCJKFntType;
+ aArr[2].nFntType = nCTLFntType;
+
+ for( sal_uInt16 n = 0; n < 3; ++n )
+ {
+ sal_uInt16 nLng = ((SvxLanguageItem&)rSet.GetPool()->GetDefaultItem(
+ aArr[n].nResLngId )).GetLanguage();
+ Font aFnt( OutputDevice::GetDefaultFont( aArr[n].nFntType,
+ nLng, DEFAULTFONT_FLAGS_ONLYONE ) );
+
+ rSet.Put( SvxFontItem( aFnt.GetFamily(), aFnt.GetName(),
+ aEmptyStr, aFnt.GetPitch(),
+ aFnt.GetCharSet(), aArr[n].nResFntId ));
+ }
+}
+
+void lcl_SetHeadline( SwDoc* pDoc, SwTxtFmtColl* pColl,
+ SfxItemSet& rSet,
+ sal_uInt16 nOutLvlBits, sal_uInt8 nLevel, sal_Bool bItalic )
+{
+ SetAllScriptItem( rSet, SvxWeightItem( WEIGHT_BOLD, RES_CHRATR_WEIGHT ) );
+ SvxFontHeightItem aHItem(240, 100, RES_CHRATR_FONTSIZE);
+ const bool bHTMLMode = pDoc->get(IDocumentSettingAccess::HTML_MODE);
+ if( bHTMLMode )
+ aHItem.SetHeight( aHeadlineSizes[ MAXLEVEL + nLevel ] );
+ else
+ aHItem.SetHeight( PT_14, aHeadlineSizes[ nLevel ] );
+ SetAllScriptItem( rSet, aHItem );
+
+ if( bItalic && !bHTMLMode )
+ SetAllScriptItem( rSet, SvxPostureItem( ITALIC_NORMAL, RES_CHRATR_POSTURE ) );
+
+ if( bHTMLMode )
+ {
+ ::lcl_SetDfltFont( DEFAULTFONT_LATIN_TEXT, DEFAULTFONT_CJK_TEXT,
+ DEFAULTFONT_CTL_TEXT, rSet );
+ }
+
+ if( pColl )
+ {
+ if( !( nOutLvlBits & ( 1 << nLevel )) )
+ {
+ pColl->AssignToListLevelOfOutlineStyle(nLevel);//<-end,zhaojianwei
+ if( !bHTMLMode )
+ {
+ SwNumRule * pOutlineRule = pDoc->GetOutlineNumRule();
+ const SwNumFmt& rNFmt = pOutlineRule->Get( nLevel );
+
+ if ( rNFmt.GetPositionAndSpaceMode() ==
+ SvxNumberFormat::LABEL_WIDTH_AND_POSITION &&
+ ( rNFmt.GetAbsLSpace() || rNFmt.GetFirstLineOffset() ) )
+ {
+ SvxLRSpaceItem aLR( (SvxLRSpaceItem&)pColl->GetFmtAttr( RES_LR_SPACE ) );
+ aLR.SetTxtFirstLineOfstValue( rNFmt.GetFirstLineOffset() );
+ aLR.SetTxtLeft( rNFmt.GetAbsLSpace() );
+ pColl->SetFmtAttr( aLR );
+ }
+
+ // #i71764#
+ // Check on document setting OUTLINE_LEVEL_YIELDS_OUTLINE_RULE no longer needed.
+ // All paragraph styles, which are assigned to a level of the
+ // outline style has to have the outline style set as its list style.
+ {
+ SwNumRuleItem aItem(pOutlineRule->GetName());
+
+ pColl->SetFmtAttr(aItem);
+ }
+ // <--
+ }
+ }
+ pColl->SetNextTxtFmtColl( *pDoc->GetTxtCollFromPool(
+ RES_POOLCOLL_TEXT ));
+ }
+}
+
+
+
+void lcl_SetRegister( SwDoc* pDoc, SfxItemSet& rSet, sal_uInt16 nFact,
+ sal_Bool bHeader, sal_Bool bTab )
+{
+ SvxLRSpaceItem aLR( RES_LR_SPACE );
+ sal_uInt16 nLeft = nFact ? GetMetricVal( CM_05 ) * nFact : 0;
+ aLR.SetTxtLeft( nLeft );
+
+ rSet.Put( aLR );
+ if( bHeader )
+ {
+ SetAllScriptItem( rSet, SvxWeightItem( WEIGHT_BOLD, RES_CHRATR_WEIGHT ) );
+ SetAllScriptItem( rSet, SvxFontHeightItem( PT_16, 100, RES_CHRATR_FONTSIZE ) );
+ }
+ if( bTab )
+ {
+ long nRightMargin = lcl_GetRightMargin( *pDoc );
+ SvxTabStopItem aTStops( 0, 0, SVX_TAB_ADJUST_DEFAULT, RES_PARATR_TABSTOP );
+ aTStops.Insert( SvxTabStop( nRightMargin - nLeft,
+ SVX_TAB_ADJUST_RIGHT,
+ cDfltDecimalChar, '.' ));
+ rSet.Put( aTStops );
+ }
+}
+
+
+
+void lcl_SetNumBul( SwDoc* pDoc, SwTxtFmtColl* pColl,
+ SfxItemSet& rSet,
+ sal_uInt16 nNxt, SwTwips nEZ, SwTwips nLeft,
+ SwTwips nUpper, SwTwips nLower )
+{
+
+ SvxLRSpaceItem aLR( RES_LR_SPACE ); SvxULSpaceItem aUL( RES_UL_SPACE );
+ aLR.SetTxtFirstLineOfst( sal_uInt16(nEZ) ); aLR.SetTxtLeft( sal_uInt16(nLeft) );
+ aUL.SetUpper( sal_uInt16(nUpper) ); aUL.SetLower( sal_uInt16(nLower) );
+ rSet.Put( aLR );
+ rSet.Put( aUL );
+
+ if( pColl )
+ pColl->SetNextTxtFmtColl( *pDoc->GetTxtCollFromPool( nNxt ));
+}
+
+
+
+// Gebe die "Auto-Collection" mit der Id zurueck. Existiert
+// sie noch nicht, dann erzeuge sie
+// Ist der String-Pointer definiert, dann erfrage nur die
+// Beschreibung der Attribute, !! es legt keine Vorlage an !!
+
+SvxFrameDirection GetDefaultFrameDirection(sal_uLong nLanguage)
+{
+ SvxFrameDirection eResult = (MsLangId::isRightToLeft( static_cast<LanguageType>(nLanguage)) ?
+ FRMDIR_HORI_RIGHT_TOP : FRMDIR_HORI_LEFT_TOP);
+ return eResult;
+}
+
+SwTxtFmtColl* SwDoc::GetTxtCollFromPool( sal_uInt16 nId, bool bRegardLanguage )
+{
+ OSL_ENSURE(
+ (RES_POOLCOLL_TEXT_BEGIN <= nId && nId < RES_POOLCOLL_TEXT_END) ||
+ (RES_POOLCOLL_LISTS_BEGIN <= nId && nId < RES_POOLCOLL_LISTS_END) ||
+ (RES_POOLCOLL_EXTRA_BEGIN <= nId && nId < RES_POOLCOLL_EXTRA_END) ||
+ (RES_POOLCOLL_REGISTER_BEGIN <= nId && nId < RES_POOLCOLL_REGISTER_END) ||
+ (RES_POOLCOLL_DOC_BEGIN <= nId && nId < RES_POOLCOLL_DOC_END) ||
+ (RES_POOLCOLL_HTML_BEGIN <= nId && nId < RES_POOLCOLL_HTML_END),
+ "Falsche AutoFormat-Id" );
+
+ SwTxtFmtColl* pNewColl;
+ sal_uInt16 nOutLvlBits = 0;
+ for( sal_uInt16 n = 0; n < pTxtFmtCollTbl->Count(); ++n )
+ {
+ if( nId == ( pNewColl = (*pTxtFmtCollTbl)[ n ] )->GetPoolFmtId() )
+ {
+ return pNewColl;
+ }
+
+ if( pNewColl->IsAssignedToListLevelOfOutlineStyle())
+ nOutLvlBits |= ( 1 << pNewColl->GetAssignedOutlineStyleLevel() );//<-end,zhaojianwei
+ }
+
+ // bis hierher nicht gefunden -> neu anlegen
+ sal_uInt16 nResId = 0;
+ if( RES_POOLCOLL_TEXT_BEGIN <= nId && nId < RES_POOLCOLL_TEXT_END )
+ nResId = RC_POOLCOLL_TEXT_BEGIN - RES_POOLCOLL_TEXT_BEGIN;
+ else if (RES_POOLCOLL_LISTS_BEGIN <= nId && nId < RES_POOLCOLL_LISTS_END)
+ nResId = RC_POOLCOLL_LISTS_BEGIN - RES_POOLCOLL_LISTS_BEGIN;
+ else if (RES_POOLCOLL_EXTRA_BEGIN <= nId && nId < RES_POOLCOLL_EXTRA_END)
+ nResId = RC_POOLCOLL_EXTRA_BEGIN - RES_POOLCOLL_EXTRA_BEGIN;
+ else if (RES_POOLCOLL_REGISTER_BEGIN <= nId && nId < RES_POOLCOLL_REGISTER_END)
+ nResId = RC_POOLCOLL_REGISTER_BEGIN - RES_POOLCOLL_REGISTER_BEGIN;
+ else if (RES_POOLCOLL_DOC_BEGIN <= nId && nId < RES_POOLCOLL_DOC_END)
+ nResId = RC_POOLCOLL_DOC_BEGIN - RES_POOLCOLL_DOC_BEGIN;
+ else if (RES_POOLCOLL_HTML_BEGIN <= nId && nId < RES_POOLCOLL_HTML_END)
+ nResId = RC_POOLCOLL_HTML_BEGIN - RES_POOLCOLL_HTML_BEGIN;
+
+ OSL_ENSURE( nResId, "Ungueltige Pool-ID" );
+ if( !nResId )
+ return GetTxtCollFromPool( RES_POOLCOLL_STANDARD );
+
+ ResId aResId( nResId + nId, *pSwResMgr );
+ String aNm( aResId );
+
+ // ein Set fuer alle zusetzenden Attribute
+ SwAttrSet aSet( GetAttrPool(), aTxtFmtCollSetRange );
+ sal_uInt16 nParent = GetPoolParent( nId );
+
+ {
+
+//FEATURE::CONDCOLL
+ if(::IsConditionalByPoolId( nId ))
+ pNewColl = new SwConditionTxtFmtColl( GetAttrPool(), aNm, !nParent
+ ? pDfltTxtFmtColl
+ : GetTxtCollFromPool( nParent ));
+ else
+//FEATURE::CONDCOLL
+ pNewColl = new SwTxtFmtColl( GetAttrPool(), aNm, !nParent
+ ? pDfltTxtFmtColl
+ : GetTxtCollFromPool( nParent ));
+ pNewColl->SetPoolFmtId( nId );
+ pTxtFmtCollTbl->Insert( pNewColl, pTxtFmtCollTbl->Count() );
+ }
+
+ switch( nId )
+ {
+ // allgemeine Inhaltsformen
+ case RES_POOLCOLL_STANDARD:
+ /* koreans do not like SvxScriptItem(TRUE) */
+ if (bRegardLanguage)
+ {
+ sal_uLong nAppLanguage = GetAppLanguage();
+ if (GetDefaultFrameDirection(nAppLanguage) ==
+ FRMDIR_HORI_RIGHT_TOP)
+ {
+ SvxAdjustItem aAdjust(SVX_ADJUST_RIGHT, RES_PARATR_ADJUST );
+ aSet.Put(aAdjust);
+ }
+ if (nAppLanguage == LANGUAGE_KOREAN)
+ {
+ SvxScriptSpaceItem aScriptSpace(sal_False, RES_PARATR_SCRIPTSPACE);
+ aSet.Put(aScriptSpace);
+ }
+ }
+ break;
+
+ case RES_POOLCOLL_TEXT: // Textkoerper
+ {
+ SvxULSpaceItem aUL( 0, PT_6, RES_UL_SPACE );
+ if( get(IDocumentSettingAccess::HTML_MODE) ) aUL.SetLower( HTML_PARSPACE );
+ aSet.Put( aUL );
+ }
+ break;
+ case RES_POOLCOLL_TEXT_IDENT: // Textkoerper Einzug
+ {
+ SvxLRSpaceItem aLR( RES_LR_SPACE );
+ aLR.SetTxtFirstLineOfst( GetMetricVal( CM_05 ));
+ aSet.Put( aLR );
+ }
+ break;
+ case RES_POOLCOLL_TEXT_NEGIDENT: // Textkoerper neg. Einzug
+ {
+ SvxLRSpaceItem aLR( RES_LR_SPACE );
+ aLR.SetTxtFirstLineOfst( -(short)GetMetricVal( CM_05 ));
+ aLR.SetTxtLeft( GetMetricVal( CM_1 ));
+ SvxTabStopItem aTStops(RES_PARATR_TABSTOP); aTStops.Insert( SvxTabStop( 0 ));
+
+ aSet.Put( aLR );
+ aSet.Put( aTStops );
+ }
+ break;
+ case RES_POOLCOLL_TEXT_MOVE: // Textkoerper Einrueckung
+ {
+ SvxLRSpaceItem aLR( RES_LR_SPACE );
+ aLR.SetTxtLeft( GetMetricVal( CM_05 ));
+ aSet.Put( aLR );
+ }
+ break;
+
+ case RES_POOLCOLL_CONFRONTATION: // Textkoerper Gegenueberstellung
+ {
+ SvxLRSpaceItem aLR( RES_LR_SPACE );
+ aLR.SetTxtFirstLineOfst( - short( GetMetricVal( CM_1 ) * 4 +
+ GetMetricVal( CM_05)) );
+ aLR.SetTxtLeft( GetMetricVal( CM_1 ) * 5 );
+ SvxTabStopItem aTStops( RES_PARATR_TABSTOP ); aTStops.Insert( SvxTabStop( 0 ));
+
+ aSet.Put( aLR );
+ aSet.Put( aTStops );
+ }
+ break;
+ case RES_POOLCOLL_MARGINAL: // Textkoerper maginalie
+ {
+ SvxLRSpaceItem aLR( RES_LR_SPACE );
+ aLR.SetTxtLeft( GetMetricVal( CM_1 ) * 4 );
+ aSet.Put( aLR );
+ }
+ break;
+
+ case RES_POOLCOLL_HEADLINE_BASE: // Basis Ueberschrift
+ {
+ static const sal_uInt16 aFntInit[] = {
+ DEFAULTFONT_LATIN_HEADING, RES_CHRATR_FONT,
+ RES_CHRATR_LANGUAGE, LANGUAGE_ENGLISH_US,
+ DEFAULTFONT_CJK_HEADING, RES_CHRATR_CJK_FONT,
+ RES_CHRATR_CJK_LANGUAGE, LANGUAGE_ENGLISH_US,
+ DEFAULTFONT_CTL_HEADING, RES_CHRATR_CTL_FONT,
+ RES_CHRATR_CTL_LANGUAGE, LANGUAGE_ARABIC_SAUDI_ARABIA,
+ 0
+ };
+
+ for( const sal_uInt16* pArr = aFntInit; *pArr; pArr += 4 )
+ {
+ sal_uInt16 nLng = ((SvxLanguageItem&)GetDefault( *(pArr+2) )).GetLanguage();
+ if( LANGUAGE_DONTKNOW == nLng )
+ nLng = *(pArr+3);
+
+ Font aFnt( OutputDevice::GetDefaultFont( *pArr,
+ nLng, DEFAULTFONT_FLAGS_ONLYONE ) );
+
+ aSet.Put( SvxFontItem( aFnt.GetFamily(), aFnt.GetName(),
+ aEmptyStr, aFnt.GetPitch(),
+ aFnt.GetCharSet(), *(pArr+1) ));
+ }
+
+ SvxFontHeightItem aFntSize( PT_14, 100, RES_CHRATR_FONTSIZE );
+ SvxULSpaceItem aUL( PT_12, PT_6, RES_UL_SPACE );
+ if( get(IDocumentSettingAccess::HTML_MODE) )
+ aUL.SetLower( HTML_PARSPACE );
+ aSet.Put( SvxFmtKeepItem( sal_True, RES_KEEP ));
+
+ pNewColl->SetNextTxtFmtColl( *GetTxtCollFromPool( RES_POOLCOLL_TEXT ));
+
+ aSet.Put( aUL );
+ SetAllScriptItem( aSet, aFntSize );
+ }
+ break;
+
+ case RES_POOLCOLL_NUMBUL_BASE: // Basis Numerierung/Aufzaehlung
+ break;
+
+ case RES_POOLCOLL_GREETING: // Grussformel
+ case RES_POOLCOLL_REGISTER_BASE: // Basis Verzeichnisse
+ case RES_POOLCOLL_SIGNATURE: // Unterschrift
+ case RES_POOLCOLL_TABLE: // Tabelle-Inhalt
+ {
+ SwFmtLineNumber aLN; aLN.SetCountLines( sal_False );
+ aSet.Put( aLN );
+ }
+ break;
+
+ case RES_POOLCOLL_HEADLINE1: // Ueberschrift 1
+ lcl_SetHeadline( this, pNewColl, aSet, nOutLvlBits, 0, sal_False );
+ break;
+ case RES_POOLCOLL_HEADLINE2: // Ueberschrift 2
+ lcl_SetHeadline( this, pNewColl, aSet, nOutLvlBits, 1, sal_True );
+ break;
+ case RES_POOLCOLL_HEADLINE3: // Ueberschrift 3
+ lcl_SetHeadline( this, pNewColl, aSet, nOutLvlBits, 2, sal_False );
+ break;
+ case RES_POOLCOLL_HEADLINE4: // Ueberschrift 4
+ lcl_SetHeadline( this, pNewColl, aSet, nOutLvlBits, 3, sal_True );
+ break;
+ case RES_POOLCOLL_HEADLINE5: // Ueberschrift 5
+ lcl_SetHeadline( this, pNewColl, aSet, nOutLvlBits, 4, sal_False );
+ break;
+ case RES_POOLCOLL_HEADLINE6: // Ueberschrift 6
+ lcl_SetHeadline( this, pNewColl, aSet, nOutLvlBits, 5, sal_False );
+ break;
+ case RES_POOLCOLL_HEADLINE7: // Ueberschrift 7
+ lcl_SetHeadline( this, pNewColl, aSet, nOutLvlBits, 6, sal_False );
+ break;
+ case RES_POOLCOLL_HEADLINE8: // Ueberschrift 8
+ lcl_SetHeadline( this, pNewColl, aSet, nOutLvlBits, 7, sal_False );
+ break;
+ case RES_POOLCOLL_HEADLINE9: // Ueberschrift 9
+ lcl_SetHeadline( this, pNewColl, aSet, nOutLvlBits, 8, sal_False );
+ break;
+ case RES_POOLCOLL_HEADLINE10: // Ueberschrift 10
+ lcl_SetHeadline( this, pNewColl, aSet, nOutLvlBits, 9, sal_False );
+ break;
+
+
+ // Sonderbereiche:
+ // Kopfzeilen
+ case RES_POOLCOLL_HEADER:
+ case RES_POOLCOLL_HEADERL:
+ case RES_POOLCOLL_HEADERR:
+ // Fusszeilen
+ case RES_POOLCOLL_FOOTER:
+ case RES_POOLCOLL_FOOTERL:
+ case RES_POOLCOLL_FOOTERR:
+ {
+ SwFmtLineNumber aLN; aLN.SetCountLines( sal_False );
+ aSet.Put( aLN );
+
+ long nRightMargin = lcl_GetRightMargin( *this );
+
+ SvxTabStopItem aTStops( 0, 0, SVX_TAB_ADJUST_DEFAULT, RES_PARATR_TABSTOP );
+ aTStops.Insert( SvxTabStop( nRightMargin / 2, SVX_TAB_ADJUST_CENTER ) );
+ aTStops.Insert( SvxTabStop( nRightMargin, SVX_TAB_ADJUST_RIGHT ) );
+
+ aSet.Put( aTStops );
+ }
+ break;
+
+ case RES_POOLCOLL_TABLE_HDLN:
+ {
+ SetAllScriptItem( aSet, SvxWeightItem( WEIGHT_BOLD, RES_CHRATR_WEIGHT ) );
+ aSet.Put( SvxAdjustItem( SVX_ADJUST_CENTER, RES_PARATR_ADJUST ) );
+ SwFmtLineNumber aLN; aLN.SetCountLines( sal_False );
+ aSet.Put( aLN );
+ }
+ break;
+
+ case RES_POOLCOLL_FOOTNOTE: // Fussnote
+ case RES_POOLCOLL_ENDNOTE:
+ {
+ SvxLRSpaceItem aLR( RES_LR_SPACE );
+ aLR.SetTxtFirstLineOfst( -(short)GetMetricVal( CM_05 ));
+ aLR.SetTxtLeft( GetMetricVal( CM_05 ));
+ SetAllScriptItem( aSet, SvxFontHeightItem( PT_10, 100, RES_CHRATR_FONTSIZE ) );
+ aSet.Put( aLR );
+ SwFmtLineNumber aLN; aLN.SetCountLines( sal_False );
+ aSet.Put( aLN );
+ }
+ break;
+
+ case RES_POOLCOLL_LABEL: // Beschriftung-Basis
+ {
+ SvxULSpaceItem aUL( RES_UL_SPACE ); aUL.SetUpper( PT_6 ); aUL.SetLower( PT_6 );
+ aSet.Put( aUL );
+ SetAllScriptItem( aSet, SvxPostureItem( ITALIC_NORMAL, RES_CHRATR_POSTURE ) );
+ SetAllScriptItem( aSet, SvxFontHeightItem( PT_10, 100, RES_CHRATR_FONTSIZE ) );
+ SwFmtLineNumber aLN; aLN.SetCountLines( sal_False );
+ aSet.Put( aLN );
+ }
+ break;
+
+ case RES_POOLCOLL_FRAME: // Rahmen Inhalt
+ case RES_POOLCOLL_LABEL_ABB: // Beschriftung-Abbildung
+ case RES_POOLCOLL_LABEL_TABLE: // Beschriftung-Tabelle
+ case RES_POOLCOLL_LABEL_FRAME: // Beschriftung-Rahmen
+ case RES_POOLCOLL_LABEL_DRAWING: // Beschriftung-Zeichnung
+ break;
+
+ case RES_POOLCOLL_JAKETADRESS: // UmschlagAdresse
+ {
+ SvxULSpaceItem aUL( RES_UL_SPACE ); aUL.SetLower( PT_3 );
+ aSet.Put( aUL );
+ SwFmtLineNumber aLN; aLN.SetCountLines( sal_False );
+ aSet.Put( aLN );
+ }
+ break;
+
+ case RES_POOLCOLL_SENDADRESS: // AbsenderAdresse
+ {
+ if( get(IDocumentSettingAccess::HTML_MODE) )
+ SetAllScriptItem( aSet, SvxPostureItem(ITALIC_NORMAL, RES_CHRATR_POSTURE) );
+ else
+ {
+ SvxULSpaceItem aUL( RES_UL_SPACE ); aUL.SetLower( PT_3 );
+ aSet.Put( aUL );
+ }
+ SwFmtLineNumber aLN; aLN.SetCountLines( sal_False );
+ aSet.Put( aLN );
+ }
+ break;
+
+ // Benutzer-Verzeichnisse:
+ case RES_POOLCOLL_TOX_USERH: // Header
+ lcl_SetRegister( this, aSet, 0, sal_True, sal_False );
+ {
+ SwFmtLineNumber aLN; aLN.SetCountLines( sal_False );
+ aSet.Put( aLN );
+ }
+ break;
+ case RES_POOLCOLL_TOX_USER1: // 1. Ebene
+ lcl_SetRegister( this, aSet, 0, sal_False, sal_True );
+ break;
+ case RES_POOLCOLL_TOX_USER2: // 2. Ebene
+ lcl_SetRegister( this, aSet, 1, sal_False, sal_True );
+ break;
+ case RES_POOLCOLL_TOX_USER3: // 3. Ebene
+ lcl_SetRegister( this, aSet, 2, sal_False, sal_True );
+ break;
+ case RES_POOLCOLL_TOX_USER4: // 4. Ebene
+ lcl_SetRegister( this, aSet, 3, sal_False, sal_True );
+ break;
+ case RES_POOLCOLL_TOX_USER5: // 5. Ebene
+ lcl_SetRegister( this, aSet, 4, sal_False, sal_True );
+ break;
+ case RES_POOLCOLL_TOX_USER6: // 6. Ebene
+ lcl_SetRegister( this, aSet, 5, sal_False, sal_True );
+ break;
+ case RES_POOLCOLL_TOX_USER7: // 7. Ebene
+ lcl_SetRegister( this, aSet, 6, sal_False, sal_True );
+ break;
+ case RES_POOLCOLL_TOX_USER8: // 8. Ebene
+ lcl_SetRegister( this, aSet, 7, sal_False, sal_True );
+ break;
+ case RES_POOLCOLL_TOX_USER9: // 9. Ebene
+ lcl_SetRegister( this, aSet, 8, sal_False, sal_True );
+ break;
+ case RES_POOLCOLL_TOX_USER10: // 10. Ebene
+ lcl_SetRegister( this, aSet, 9, sal_False, sal_True );
+ break;
+
+ // Index-Verzeichnisse
+ case RES_POOLCOLL_TOX_IDXH: // Header
+ lcl_SetRegister( this, aSet, 0, sal_True, sal_False );
+ {
+ SwFmtLineNumber aLN; aLN.SetCountLines( sal_False );
+ aSet.Put( aLN );
+ }
+ break;
+ case RES_POOLCOLL_TOX_IDX1: // 1. Ebene
+ lcl_SetRegister( this, aSet, 0, sal_False, sal_False );
+ break;
+ case RES_POOLCOLL_TOX_IDX2: // 2. Ebene
+ lcl_SetRegister( this, aSet, 1, sal_False, sal_False );
+ break;
+ case RES_POOLCOLL_TOX_IDX3: // 3. Ebene
+ lcl_SetRegister( this, aSet, 2, sal_False, sal_False );
+ break;
+ case RES_POOLCOLL_TOX_IDXBREAK: // Trenner
+ lcl_SetRegister( this, aSet, 0, sal_False, sal_False );
+ break;
+
+ // Inhalts-Verzeichnisse
+ case RES_POOLCOLL_TOX_CNTNTH: // Header
+ lcl_SetRegister( this, aSet, 0, sal_True, sal_False );
+ {
+ SwFmtLineNumber aLN; aLN.SetCountLines( sal_False );
+ aSet.Put( aLN );
+ }
+ break;
+ case RES_POOLCOLL_TOX_CNTNT1: // 1. Ebene
+ lcl_SetRegister( this, aSet, 0, sal_False, sal_True );
+ break;
+ case RES_POOLCOLL_TOX_CNTNT2: // 2. Ebene
+ lcl_SetRegister( this, aSet, 1, sal_False, sal_True );
+ break;
+ case RES_POOLCOLL_TOX_CNTNT3: // 3. Ebene
+ lcl_SetRegister( this, aSet, 2, sal_False, sal_True );
+ break;
+ case RES_POOLCOLL_TOX_CNTNT4: // 4. Ebene
+ lcl_SetRegister( this, aSet, 3, sal_False, sal_True );
+ break;
+ case RES_POOLCOLL_TOX_CNTNT5: // 5. Ebene
+ lcl_SetRegister( this, aSet, 4, sal_False, sal_True );
+ break;
+ case RES_POOLCOLL_TOX_CNTNT6: // 6. Ebene
+ lcl_SetRegister( this, aSet, 5, sal_False, sal_True );
+ break;
+ case RES_POOLCOLL_TOX_CNTNT7: // 7. Ebene
+ lcl_SetRegister( this, aSet, 6, sal_False, sal_True );
+ break;
+ case RES_POOLCOLL_TOX_CNTNT8: // 8. Ebene
+ lcl_SetRegister( this, aSet, 7, sal_False, sal_True );
+ break;
+ case RES_POOLCOLL_TOX_CNTNT9: // 9. Ebene
+ lcl_SetRegister( this, aSet, 8, sal_False, sal_True );
+ break;
+ case RES_POOLCOLL_TOX_CNTNT10: // 10. Ebene
+ lcl_SetRegister( this, aSet, 9, sal_False, sal_True );
+ break;
+
+ case RES_POOLCOLL_TOX_ILLUSH:
+ case RES_POOLCOLL_TOX_OBJECTH:
+ case RES_POOLCOLL_TOX_TABLESH:
+ case RES_POOLCOLL_TOX_AUTHORITIESH:
+ lcl_SetRegister( this, aSet, 0, sal_True, sal_False );
+ {
+ SwFmtLineNumber aLN; aLN.SetCountLines( sal_False );
+ aSet.Put( aLN );
+ }
+ break;
+ case RES_POOLCOLL_TOX_ILLUS1:
+ case RES_POOLCOLL_TOX_OBJECT1:
+ case RES_POOLCOLL_TOX_TABLES1:
+ case RES_POOLCOLL_TOX_AUTHORITIES1:
+ lcl_SetRegister( this, aSet, 0, sal_False, sal_True );
+ break;
+
+
+
+ case RES_POOLCOLL_NUM_LEVEL1S:
+ lcl_SetNumBul( this, pNewColl, aSet, RES_POOLCOLL_NUM_LEVEL1,
+ lNumFirstLineOffset, SwNumRule::GetNumIndent( 0 ),
+ PT_12, PT_6 );
+ break;
+ case RES_POOLCOLL_NUM_LEVEL1:
+ lcl_SetNumBul( this, pNewColl, aSet, RES_POOLCOLL_NUM_LEVEL1,
+ lNumFirstLineOffset, SwNumRule::GetNumIndent( 0 ),
+ 0, PT_6 );
+ break;
+ case RES_POOLCOLL_NUM_LEVEL1E:
+ lcl_SetNumBul( this, pNewColl, aSet, RES_POOLCOLL_NUM_LEVEL1,
+ lNumFirstLineOffset, SwNumRule::GetNumIndent( 0 ),
+ 0, PT_12 );
+ break;
+ case RES_POOLCOLL_NUM_NONUM1:
+ lcl_SetNumBul( this, pNewColl, aSet, RES_POOLCOLL_NUM_NONUM1,
+ 0, SwNumRule::GetNumIndent( 0 ), 0, PT_6 );
+ break;
+ case RES_POOLCOLL_NUM_LEVEL2S:
+ lcl_SetNumBul( this, pNewColl, aSet, RES_POOLCOLL_NUM_LEVEL2,
+ lNumFirstLineOffset, SwNumRule::GetNumIndent( 1 ),
+ PT_12, PT_6 );
+ break;
+ case RES_POOLCOLL_NUM_LEVEL2:
+ lcl_SetNumBul( this, pNewColl, aSet, RES_POOLCOLL_NUM_LEVEL2,
+ lNumFirstLineOffset, SwNumRule::GetNumIndent( 1 ),
+ 0, PT_6 );
+ break;
+ case RES_POOLCOLL_NUM_LEVEL2E:
+ lcl_SetNumBul( this, pNewColl, aSet, RES_POOLCOLL_NUM_LEVEL2,
+ lNumFirstLineOffset, SwNumRule::GetNumIndent( 1 ),
+ 0, PT_12 );
+ break;
+ case RES_POOLCOLL_NUM_NONUM2:
+ lcl_SetNumBul( this, pNewColl, aSet, RES_POOLCOLL_NUM_NONUM2,
+ 0, SwNumRule::GetNumIndent( 1 ), 0, PT_6 );
+ break;
+ case RES_POOLCOLL_NUM_LEVEL3S:
+ lcl_SetNumBul( this, pNewColl, aSet, RES_POOLCOLL_NUM_LEVEL3,
+ lNumFirstLineOffset, SwNumRule::GetNumIndent( 2 ),
+ PT_12, PT_6 );
+ break;
+ case RES_POOLCOLL_NUM_LEVEL3:
+ lcl_SetNumBul( this, pNewColl, aSet, RES_POOLCOLL_NUM_LEVEL3,
+ lNumFirstLineOffset, SwNumRule::GetNumIndent( 2 ),
+ 0, PT_6 );
+ break;
+ case RES_POOLCOLL_NUM_LEVEL3E:
+ lcl_SetNumBul( this, pNewColl, aSet, RES_POOLCOLL_NUM_LEVEL3,
+ lNumFirstLineOffset, SwNumRule::GetNumIndent( 2 ),
+ 0, PT_12 );
+ break;
+ case RES_POOLCOLL_NUM_NONUM3:
+ lcl_SetNumBul( this, pNewColl, aSet, RES_POOLCOLL_NUM_NONUM3,
+ 0, SwNumRule::GetNumIndent( 2 ), 0, PT_6 );
+ break;
+ case RES_POOLCOLL_NUM_LEVEL4S:
+ lcl_SetNumBul( this, pNewColl, aSet, RES_POOLCOLL_NUM_LEVEL4,
+ lNumFirstLineOffset, SwNumRule::GetNumIndent( 3 ),
+ PT_12, PT_6 );
+ break;
+ case RES_POOLCOLL_NUM_LEVEL4:
+ lcl_SetNumBul( this, pNewColl, aSet, RES_POOLCOLL_NUM_LEVEL4,
+ lNumFirstLineOffset, SwNumRule::GetNumIndent( 3 ),
+ 0, PT_6 );
+ break;
+ case RES_POOLCOLL_NUM_LEVEL4E:
+ lcl_SetNumBul( this, pNewColl, aSet, RES_POOLCOLL_NUM_LEVEL4,
+ lNumFirstLineOffset, SwNumRule::GetNumIndent( 3 ),
+ 0, PT_12 );
+ break;
+ case RES_POOLCOLL_NUM_NONUM4:
+ lcl_SetNumBul( this, pNewColl, aSet, RES_POOLCOLL_NUM_NONUM4,
+ 0, SwNumRule::GetNumIndent( 3 ), 0, PT_6 );
+ break;
+ case RES_POOLCOLL_NUM_LEVEL5S:
+ lcl_SetNumBul( this, pNewColl, aSet, RES_POOLCOLL_NUM_LEVEL5,
+ lNumFirstLineOffset, SwNumRule::GetNumIndent( 4 ),
+ PT_12, PT_6 );
+ break;
+ case RES_POOLCOLL_NUM_LEVEL5:
+ lcl_SetNumBul( this, pNewColl, aSet, RES_POOLCOLL_NUM_LEVEL5,
+ lNumFirstLineOffset, SwNumRule::GetNumIndent( 4 ),
+ 0, PT_6 );
+ break;
+ case RES_POOLCOLL_NUM_LEVEL5E:
+ lcl_SetNumBul( this, pNewColl, aSet, RES_POOLCOLL_NUM_LEVEL5,
+ lNumFirstLineOffset, SwNumRule::GetNumIndent( 4 ),
+ 0, PT_12 );
+ break;
+ case RES_POOLCOLL_NUM_NONUM5:
+ lcl_SetNumBul( this, pNewColl, aSet, RES_POOLCOLL_NUM_NONUM5,
+ 0, SwNumRule::GetNumIndent( 4 ), 0, PT_6 );
+ break;
+
+ case RES_POOLCOLL_BUL_LEVEL1S:
+ lcl_SetNumBul( this, pNewColl, aSet, RES_POOLCOLL_BUL_LEVEL1,
+ lBullFirstLineOffset, SwNumRule::GetBullIndent( 0 ),
+ PT_12, PT_6 );
+ break;
+ case RES_POOLCOLL_BUL_LEVEL1:
+ lcl_SetNumBul( this, pNewColl, aSet, RES_POOLCOLL_BUL_LEVEL1,
+ lBullFirstLineOffset, SwNumRule::GetBullIndent( 0 ),
+ 0, PT_6 );
+ break;
+ case RES_POOLCOLL_BUL_LEVEL1E:
+ lcl_SetNumBul( this, pNewColl, aSet, RES_POOLCOLL_BUL_LEVEL1,
+ lBullFirstLineOffset, SwNumRule::GetBullIndent( 0 ),
+ 0, PT_12 );
+ break;
+ case RES_POOLCOLL_BUL_NONUM1:
+ lcl_SetNumBul( this, pNewColl, aSet, RES_POOLCOLL_BUL_NONUM1,
+ 0, SwNumRule::GetBullIndent( 0 ), 0, PT_6 );
+ break;
+ case RES_POOLCOLL_BUL_LEVEL2S:
+ lcl_SetNumBul( this, pNewColl, aSet, RES_POOLCOLL_BUL_LEVEL2,
+ lBullFirstLineOffset, SwNumRule::GetBullIndent( 1 ),
+ PT_12, PT_6 );
+ break;
+ case RES_POOLCOLL_BUL_LEVEL2:
+ lcl_SetNumBul( this, pNewColl, aSet, RES_POOLCOLL_BUL_LEVEL2,
+ lBullFirstLineOffset, SwNumRule::GetBullIndent( 1 ),
+ 0, PT_6 );
+ break;
+ case RES_POOLCOLL_BUL_LEVEL2E:
+ lcl_SetNumBul( this, pNewColl, aSet, RES_POOLCOLL_BUL_LEVEL2,
+ lBullFirstLineOffset, SwNumRule::GetBullIndent( 1 ),
+ 0, PT_12 );
+ break;
+ case RES_POOLCOLL_BUL_NONUM2:
+ lcl_SetNumBul( this, pNewColl, aSet, RES_POOLCOLL_BUL_NONUM2,
+ 0, SwNumRule::GetBullIndent( 1 ), 0, PT_6 );
+ break;
+ case RES_POOLCOLL_BUL_LEVEL3S:
+ lcl_SetNumBul( this, pNewColl, aSet, RES_POOLCOLL_BUL_LEVEL3,
+ lBullFirstLineOffset, SwNumRule::GetBullIndent( 2 ),
+ PT_12, PT_6 );
+ break;
+ case RES_POOLCOLL_BUL_LEVEL3:
+ lcl_SetNumBul( this, pNewColl, aSet, RES_POOLCOLL_BUL_LEVEL3,
+ lBullFirstLineOffset, SwNumRule::GetBullIndent( 2 ),
+ 0, PT_6 );
+ break;
+ case RES_POOLCOLL_BUL_LEVEL3E:
+ lcl_SetNumBul( this, pNewColl, aSet, RES_POOLCOLL_BUL_LEVEL3,
+ lBullFirstLineOffset, SwNumRule::GetBullIndent( 2 ),
+ 0, PT_12 );
+ break;
+ case RES_POOLCOLL_BUL_NONUM3:
+ lcl_SetNumBul( this, pNewColl, aSet, RES_POOLCOLL_BUL_NONUM3,
+ 0, SwNumRule::GetBullIndent( 2 ), 0, PT_6 );
+ break;
+ case RES_POOLCOLL_BUL_LEVEL4S:
+ lcl_SetNumBul( this, pNewColl, aSet, RES_POOLCOLL_BUL_LEVEL4,
+ lBullFirstLineOffset, SwNumRule::GetBullIndent( 3 ),
+ PT_12, PT_6 );
+ break;
+ case RES_POOLCOLL_BUL_LEVEL4:
+ lcl_SetNumBul( this, pNewColl, aSet, RES_POOLCOLL_BUL_LEVEL4,
+ lBullFirstLineOffset, SwNumRule::GetBullIndent( 3 ),
+ 0, PT_6 );
+ break;
+ case RES_POOLCOLL_BUL_LEVEL4E:
+ lcl_SetNumBul( this, pNewColl, aSet, RES_POOLCOLL_BUL_LEVEL4,
+ lBullFirstLineOffset, SwNumRule::GetBullIndent( 3 ),
+ 0, PT_12 );
+ break;
+ case RES_POOLCOLL_BUL_NONUM4:
+ lcl_SetNumBul( this, pNewColl, aSet, RES_POOLCOLL_BUL_NONUM4,
+ 0, SwNumRule::GetBullIndent( 3 ), 0, PT_6 );
+ break;
+ case RES_POOLCOLL_BUL_LEVEL5S:
+ lcl_SetNumBul( this, pNewColl, aSet, RES_POOLCOLL_BUL_LEVEL5,
+ lBullFirstLineOffset, SwNumRule::GetBullIndent( 4 ),
+ PT_12, PT_6 );
+ break;
+ case RES_POOLCOLL_BUL_LEVEL5:
+ lcl_SetNumBul( this, pNewColl, aSet, RES_POOLCOLL_BUL_LEVEL5,
+ lBullFirstLineOffset, SwNumRule::GetBullIndent( 4 ),
+ 0, PT_6 );
+ break;
+ case RES_POOLCOLL_BUL_LEVEL5E:
+ lcl_SetNumBul( this, pNewColl, aSet, RES_POOLCOLL_BUL_LEVEL5,
+ lBullFirstLineOffset, SwNumRule::GetBullIndent( 4 ),
+ 0, PT_12 );
+ break;
+ case RES_POOLCOLL_BUL_NONUM5:
+ lcl_SetNumBul( this, pNewColl, aSet, RES_POOLCOLL_BUL_NONUM5,
+ 0, SwNumRule::GetBullIndent( 4 ), 0, PT_6 );
+ break;
+
+ case RES_POOLCOLL_DOC_TITEL: // Doc. Titel
+ {
+ SetAllScriptItem( aSet, SvxWeightItem( WEIGHT_BOLD, RES_CHRATR_WEIGHT ) );
+ SetAllScriptItem( aSet, SvxFontHeightItem( PT_18, 100, RES_CHRATR_FONTSIZE ) );
+
+ aSet.Put( SvxAdjustItem( SVX_ADJUST_CENTER, RES_PARATR_ADJUST ) );
+
+ pNewColl->SetNextTxtFmtColl( *GetTxtCollFromPool(
+ RES_POOLCOLL_DOC_SUBTITEL ));
+ }
+ break;
+
+ case RES_POOLCOLL_DOC_SUBTITEL: // Doc. UnterTitel
+ {
+ SetAllScriptItem( aSet, SvxPostureItem( ITALIC_NORMAL, RES_CHRATR_POSTURE ));
+ SetAllScriptItem( aSet, SvxFontHeightItem( PT_14, 100, RES_CHRATR_FONTSIZE ));
+
+ aSet.Put( SvxAdjustItem( SVX_ADJUST_CENTER, RES_PARATR_ADJUST ));
+
+ pNewColl->SetNextTxtFmtColl( *GetTxtCollFromPool(
+ RES_POOLCOLL_TEXT ));
+ }
+ break;
+
+ case RES_POOLCOLL_HTML_BLOCKQUOTE:
+ {
+ SvxLRSpaceItem aLR( RES_LR_SPACE );
+ aLR.SetLeft( GetMetricVal( CM_1 ));
+ aLR.SetRight( GetMetricVal( CM_1 ));
+ aSet.Put( aLR );
+ SvxULSpaceItem aUL( RES_UL_SPACE );
+ aUL = pNewColl->GetULSpace();
+ aUL.SetLower( HTML_PARSPACE );
+ aSet.Put( aUL);
+ }
+ break;
+
+ case RES_POOLCOLL_HTML_PRE:
+ {
+ ::lcl_SetDfltFont( DEFAULTFONT_FIXED, aSet );
+
+// WORKAROUND: PRE auf 10pt setzten
+ SetAllScriptItem( aSet, SvxFontHeightItem(PT_10, 100, RES_CHRATR_FONTSIZE) );
+// WORKAROUND: PRE auf 10pt setzten
+
+ // der untere Absatz-Abstand wird explizit gesetzt (macht
+ // die harte Attributierung einfacher)
+ SvxULSpaceItem aULSpaceItem( RES_UL_SPACE );
+ aULSpaceItem = pNewColl->GetULSpace();
+ aULSpaceItem.SetLower( 0 );
+ aSet.Put( aULSpaceItem );
+ }
+ break;
+
+ case RES_POOLCOLL_HTML_HR:
+ {
+ SvxBoxItem aBox( RES_BOX );
+ Color aColor( COL_GRAY );
+ SvxBorderLine aNew( &aColor, 1, DOUBLE );
+ aBox.SetLine( &aNew, BOX_LINE_BOTTOM );
+
+ aSet.Put( aBox );
+ aSet.Put( SwParaConnectBorderItem( sal_False ) );
+ SetAllScriptItem( aSet, SvxFontHeightItem(120, 100, RES_CHRATR_FONTSIZE) );
+
+ SvxULSpaceItem aUL( RES_UL_SPACE );
+ {
+ pNewColl->SetNextTxtFmtColl( *GetTxtCollFromPool(
+ RES_POOLCOLL_TEXT ));
+ aUL = pNewColl->GetULSpace();
+ }
+ aUL.SetLower( HTML_PARSPACE );
+ aSet.Put( aUL);
+ SwFmtLineNumber aLN; aLN.SetCountLines( sal_False );
+ aSet.Put( aLN );
+ }
+ break;
+
+ case RES_POOLCOLL_HTML_DD:
+ {
+ SvxLRSpaceItem aLR( RES_LR_SPACE );
+ aLR = pNewColl->GetLRSpace();
+ // es wird um 1cm eingerueckt. Die IDs liegen immer 2 auseinander!
+ aLR.SetLeft( GetMetricVal( CM_1 ));
+ aSet.Put( aLR );
+ }
+ break;
+ case RES_POOLCOLL_HTML_DT:
+ {
+ SvxLRSpaceItem aLR( RES_LR_SPACE );
+ {
+ pNewColl->SetNextTxtFmtColl( *GetTxtCollFromPool(
+ RES_POOLCOLL_HTML_DD ));
+ aLR = pNewColl->GetLRSpace();
+ }
+ // es wird um 0cm eingerueckt. Die IDs liegen immer 2 auseinander!
+ aLR.SetLeft( 0 );
+ aSet.Put( aLR );
+ }
+ break;
+ }
+
+ if( aSet.Count() )
+ {
+ {
+ pNewColl->SetFmtAttr( aSet );
+ }
+ }
+ return pNewColl;
+}
+
+
+
+ // pruefe, ob diese "Auto-Collection" in Dokument schon/noch
+ // benutzt wird
+bool SwDoc::IsPoolTxtCollUsed( sal_uInt16 nId ) const
+{
+ OSL_ENSURE(
+ (RES_POOLCOLL_TEXT_BEGIN <= nId && nId < RES_POOLCOLL_TEXT_END) ||
+ (RES_POOLCOLL_LISTS_BEGIN <= nId && nId < RES_POOLCOLL_LISTS_END) ||
+ (RES_POOLCOLL_EXTRA_BEGIN <= nId && nId < RES_POOLCOLL_EXTRA_END) ||
+ (RES_POOLCOLL_REGISTER_BEGIN <= nId && nId < RES_POOLCOLL_REGISTER_END) ||
+ (RES_POOLCOLL_DOC_BEGIN <= nId && nId < RES_POOLCOLL_DOC_END) ||
+ (RES_POOLCOLL_HTML_BEGIN <= nId && nId < RES_POOLCOLL_HTML_END),
+ "Falsche AutoFormat-Id" );
+
+ SwTxtFmtColl* pNewColl = 0;
+ sal_Bool bFnd = sal_False;
+ for( sal_uInt16 n = 0; !bFnd && n < pTxtFmtCollTbl->Count(); ++n )
+ {
+ pNewColl = (*pTxtFmtCollTbl)[ n ];
+ if( nId == pNewColl->GetPoolFmtId() )
+ bFnd = sal_True;
+ }
+
+ if( !bFnd || !pNewColl->GetDepends() )
+ return sal_False;
+
+ SwAutoFmtGetDocNode aGetHt( &GetNodes() );
+ return !pNewColl->GetInfo( aGetHt );
+}
+
+ // Gebe das "Auto[matische]-Format" mit der Id zurueck. Existiert
+ // es noch nicht, dann erzeuge es
+
+SwFmt* SwDoc::GetFmtFromPool( sal_uInt16 nId )
+{
+ SwFmt *pNewFmt = 0;
+ SwFmt *pDeriveFmt = 0;
+
+ SvPtrarr* pArray[ 2 ];
+ sal_uInt16 nArrCnt = 1, nRCId = 0;
+ sal_uInt16* pWhichRange = 0;
+
+ switch( nId & (COLL_GET_RANGE_BITS + POOLGRP_NOCOLLID) )
+ {
+ case POOLGRP_CHARFMT:
+ {
+ pArray[0] = pCharFmtTbl;
+ pDeriveFmt = pDfltCharFmt;
+
+ if( nId > RES_POOLCHR_NORMAL_END )
+ nRCId = RC_POOLCHRFMT_HTML_BEGIN - RES_POOLCHR_HTML_BEGIN;
+ else
+ nRCId = RC_POOLCHRFMT_BEGIN - RES_POOLCHR_BEGIN;
+ pWhichRange = aCharFmtSetRange;
+
+ // Fehlerfall: unbekanntes Format, aber CharFormat
+ // -> returne das erste
+ if( RES_POOLCHR_BEGIN > nId || nId >= RES_POOLCHR_END )
+ {
+ OSL_ENSURE( !this, "ungueltige Id" );
+ nId = RES_POOLCHR_BEGIN;
+ }
+ }
+ break;
+ case POOLGRP_FRAMEFMT:
+ {
+ pArray[0] = pFrmFmtTbl;
+ pArray[1] = pSpzFrmFmtTbl;
+ pDeriveFmt = pDfltFrmFmt;
+ nArrCnt = 2;
+ nRCId = RC_POOLFRMFMT_BEGIN - RES_POOLFRM_BEGIN;
+ pWhichRange = aFrmFmtSetRange;
+
+ // Fehlerfall: unbekanntes Format, aber FrameFormat
+ // -> returne das erste
+ if( RES_POOLFRM_BEGIN > nId || nId >= RES_POOLFRM_END )
+ {
+ OSL_ENSURE( !this, "ungueltige Id" );
+ nId = RES_POOLFRM_BEGIN;
+ }
+ }
+ break;
+
+ default:
+ // Fehlerfall, unbekanntes Format
+ OSL_ENSURE( nId, "ungueltige Id" );
+ return 0;
+ }
+ OSL_ENSURE( nRCId, "ungueltige Id" );
+
+ while( nArrCnt-- )
+ for( sal_uInt16 n = 0; n < (*pArray[nArrCnt]).Count(); ++n )
+ if( nId == ( pNewFmt = (SwFmt*)(*pArray[ nArrCnt ] )[ n ] )->
+ GetPoolFmtId() )
+ {
+ return pNewFmt;
+ }
+
+ ResId aResId( nRCId + nId, *pSwResMgr );
+ String aNm( aResId );
+ SwAttrSet aSet( GetAttrPool(), pWhichRange );
+
+ {
+ sal_Bool bIsModified = IsModified();
+
+ {
+ ::sw::UndoGuard const undoGuard(GetIDocumentUndoRedo());
+ switch (nId & (COLL_GET_RANGE_BITS + POOLGRP_NOCOLLID) )
+ {
+ case POOLGRP_CHARFMT:
+ pNewFmt = _MakeCharFmt(aNm, pDeriveFmt, sal_False, sal_True);
+ break;
+ case POOLGRP_FRAMEFMT:
+ pNewFmt = _MakeFrmFmt(aNm, pDeriveFmt, sal_False, sal_True);
+ break;
+ default:
+ break;
+ }
+ }
+
+ if( !bIsModified )
+ ResetModified();
+ pNewFmt->SetPoolFmtId( nId );
+ pNewFmt->SetAuto( sal_False ); // kein Auto-Format
+ }
+
+ switch( nId )
+ {
+ case RES_POOLCHR_FOOTNOTE: // Fussnote
+ case RES_POOLCHR_PAGENO: // Seiten/Feld
+ case RES_POOLCHR_LABEL: // Beschriftung
+ case RES_POOLCHR_DROPCAPS: // Initialien
+ case RES_POOLCHR_NUM_LEVEL: // Aufzaehlungszeichen
+ case RES_POOLCHR_TOXJUMP: // Verzeichnissprung
+ case RES_POOLCHR_ENDNOTE: // Endnote
+ case RES_POOLCHR_LINENUM: // Zeilennummerierung
+ break;
+
+ case RES_POOLCHR_ENDNOTE_ANCHOR: // Endnotenanker
+ case RES_POOLCHR_FOOTNOTE_ANCHOR: // Fussnotenanker
+ {
+ aSet.Put( SvxEscapementItem( DFLT_ESC_AUTO_SUPER, 58, RES_CHRATR_ESCAPEMENT ) );
+ }
+ break;
+
+
+ case RES_POOLCHR_BUL_LEVEL: // Aufzaehlungszeichen
+ {
+ const Font& rBulletFont = numfunc::GetDefBulletFont();
+ SetAllScriptItem( aSet, SvxFontItem( rBulletFont.GetFamily(),
+ rBulletFont.GetName(), rBulletFont.GetStyleName(),
+ rBulletFont.GetPitch(), rBulletFont.GetCharSet(), RES_CHRATR_FONT ));
+ }
+ break;
+
+ case RES_POOLCHR_INET_NORMAL:
+ {
+ Color aCol( COL_BLUE );
+ aSet.Put( SvxColorItem( aCol, RES_CHRATR_COLOR ) );
+ aSet.Put( SvxUnderlineItem( UNDERLINE_SINGLE, RES_CHRATR_UNDERLINE ) );
+ // i40133: patch submitted by rail: set language to 'none' to prevent spell checking:
+ aSet.Put( SvxLanguageItem( LANGUAGE_NONE, RES_CHRATR_LANGUAGE ) );
+ aSet.Put( SvxLanguageItem( LANGUAGE_NONE, RES_CHRATR_CJK_LANGUAGE ) );
+ aSet.Put( SvxLanguageItem( LANGUAGE_NONE, RES_CHRATR_CTL_LANGUAGE ) );
+ }
+ break;
+ case RES_POOLCHR_INET_VISIT:
+ {
+ Color aCol( COL_RED );
+ aSet.Put( SvxColorItem( aCol, RES_CHRATR_COLOR ) );
+ aSet.Put( SvxUnderlineItem( UNDERLINE_SINGLE, RES_CHRATR_UNDERLINE ) );
+ aSet.Put( SvxLanguageItem( LANGUAGE_NONE, RES_CHRATR_LANGUAGE ) );
+ aSet.Put( SvxLanguageItem( LANGUAGE_NONE, RES_CHRATR_CJK_LANGUAGE ) );
+ aSet.Put( SvxLanguageItem( LANGUAGE_NONE, RES_CHRATR_CTL_LANGUAGE ) );
+ }
+ break;
+ case RES_POOLCHR_JUMPEDIT:
+ {
+ Color aCol( COL_CYAN );
+ aSet.Put( SvxColorItem( aCol, RES_CHRATR_COLOR ) );
+ aSet.Put( SvxUnderlineItem( UNDERLINE_DOTTED, RES_CHRATR_UNDERLINE ) );
+ aSet.Put( SvxCaseMapItem( SVX_CASEMAP_KAPITAELCHEN, RES_CHRATR_CASEMAP ) );
+ }
+ break;
+
+ case RES_POOLCHR_RUBYTEXT:
+ {
+ long nH = ((SvxFontHeightItem*)GetDfltAttr(
+ RES_CHRATR_CJK_FONTSIZE ))->GetHeight() / 2;
+ SetAllScriptItem( aSet, SvxFontHeightItem( nH, 100, RES_CHRATR_FONTSIZE));
+ aSet.Put(SvxUnderlineItem( UNDERLINE_NONE, RES_CHRATR_UNDERLINE ));
+ aSet.Put(SvxEmphasisMarkItem( EMPHASISMARK_NONE, RES_CHRATR_EMPHASIS_MARK) );
+ }
+ break;
+
+ case RES_POOLCHR_HTML_EMPHASIS:
+ case RES_POOLCHR_HTML_CITIATION:
+ case RES_POOLCHR_HTML_VARIABLE:
+ {
+ SetAllScriptItem( aSet, SvxPostureItem( ITALIC_NORMAL, RES_CHRATR_POSTURE) );
+ }
+ break;
+
+ case RES_POOLCHR_IDX_MAIN_ENTRY:
+ case RES_POOLCHR_HTML_STRONG:
+ {
+ SetAllScriptItem( aSet, SvxWeightItem( WEIGHT_BOLD, RES_CHRATR_WEIGHT ));
+ }
+ break;
+
+ case RES_POOLCHR_HTML_CODE:
+ case RES_POOLCHR_HTML_SAMPLE:
+ case RES_POOLCHR_HTML_KEYBOARD:
+ case RES_POOLCHR_HTML_TELETYPE:
+ {
+ ::lcl_SetDfltFont( DEFAULTFONT_FIXED, aSet );
+ }
+ break;
+ case RES_POOLCHR_VERT_NUM:
+ aSet.Put( SvxCharRotateItem( 900, sal_False, RES_CHRATR_ROTATE ) );
+ break;
+
+ case RES_POOLFRM_FRAME:
+ {
+ if ( get(IDocumentSettingAccess::HTML_MODE) )
+ {
+ aSet.Put( SwFmtAnchor( FLY_AS_CHAR ));
+ aSet.Put( SwFmtVertOrient( 0, text::VertOrientation::LINE_CENTER, text::RelOrientation::PRINT_AREA ) );
+ aSet.Put( SwFmtSurround( SURROUND_NONE ) );
+ }
+ else
+ {
+ aSet.Put( SwFmtAnchor( FLY_AT_PARA ));
+ aSet.Put( SwFmtSurround( SURROUND_PARALLEL ) );
+ aSet.Put( SwFmtHoriOrient( 0, text::HoriOrientation::CENTER, text::RelOrientation::PRINT_AREA ) );
+ aSet.Put( SwFmtVertOrient( 0, text::VertOrientation::TOP, text::RelOrientation::PRINT_AREA ) );
+ Color aCol( COL_BLACK );
+ SvxBorderLine aLine( &aCol, DEF_LINE_WIDTH_0 );
+ SvxBoxItem aBox( RES_BOX );
+ aBox.SetLine( &aLine, BOX_LINE_TOP );
+ aBox.SetLine( &aLine, BOX_LINE_BOTTOM );
+ aBox.SetLine( &aLine, BOX_LINE_LEFT );
+ aBox.SetLine( &aLine, BOX_LINE_RIGHT );
+ aBox.SetDistance( 85 );
+ aSet.Put( aBox );
+ aSet.Put( SvxLRSpaceItem( 114, 114, 0, 0, RES_LR_SPACE ) );
+ aSet.Put( SvxULSpaceItem( 114, 114, RES_UL_SPACE ) );
+ }
+ }
+ break;
+ case RES_POOLFRM_GRAPHIC:
+ case RES_POOLFRM_OLE:
+ {
+ aSet.Put( SwFmtAnchor( FLY_AT_PARA ));
+ aSet.Put( SwFmtHoriOrient( 0, text::HoriOrientation::CENTER, text::RelOrientation::FRAME ));
+ aSet.Put( SwFmtVertOrient( 0, text::VertOrientation::TOP, text::RelOrientation::FRAME ));
+ aSet.Put( SwFmtSurround( SURROUND_IDEAL ));
+ }
+ break;
+ case RES_POOLFRM_FORMEL:
+ {
+ aSet.Put( SwFmtAnchor( FLY_AS_CHAR ) );
+ aSet.Put( SwFmtVertOrient( 0, text::VertOrientation::CHAR_CENTER, text::RelOrientation::FRAME ) );
+ aSet.Put( SvxLRSpaceItem( 114, 114, 0, 0, RES_LR_SPACE ) );
+ }
+ break;
+ case RES_POOLFRM_MARGINAL:
+ {
+ aSet.Put( SwFmtAnchor( FLY_AT_PARA ));
+ aSet.Put( SwFmtHoriOrient( 0, text::HoriOrientation::LEFT, text::RelOrientation::FRAME ));
+ aSet.Put( SwFmtVertOrient( 0, text::VertOrientation::TOP, text::RelOrientation::FRAME ));
+ aSet.Put( SwFmtSurround( SURROUND_PARALLEL ));
+ // Breite 3.5 centimeter vorgegeben, als Hoehe nur den
+ // min. Wert benutzen
+ aSet.Put( SwFmtFrmSize( ATT_MIN_SIZE,
+ GetMetricVal( CM_1 ) * 3 + GetMetricVal( CM_05 ),
+ MM50 ));
+ }
+ break;
+ case RES_POOLFRM_WATERSIGN:
+ {
+ aSet.Put( SwFmtAnchor( FLY_AT_PAGE ));
+ aSet.Put( SwFmtHoriOrient( 0, text::HoriOrientation::CENTER, text::RelOrientation::FRAME ));
+ aSet.Put( SwFmtVertOrient( 0, text::VertOrientation::CENTER, text::RelOrientation::FRAME ));
+ aSet.Put( SvxOpaqueItem( sal_False ));
+ aSet.Put( SwFmtSurround( SURROUND_THROUGHT ));
+ }
+ break;
+
+ case RES_POOLFRM_LABEL:
+ {
+ aSet.Put( SwFmtAnchor( FLY_AS_CHAR ) );
+ aSet.Put( SwFmtVertOrient( 0, text::VertOrientation::TOP, text::RelOrientation::FRAME ) );
+ aSet.Put( SvxLRSpaceItem( 114, 114, 0, 0, RES_LR_SPACE ) );
+
+ SvxProtectItem aProtect( RES_PROTECT );
+ aProtect.SetSizeProtect( sal_True );
+ aProtect.SetPosProtect( sal_True );
+ aSet.Put( aProtect );
+
+ pNewFmt->SetAutoUpdateFmt( sal_True );
+ }
+ break;
+ }
+ if( aSet.Count() )
+ {
+ {
+ pNewFmt->SetFmtAttr( aSet );
+ }
+ }
+ return pNewFmt;
+}
+
+SwFrmFmt* SwDoc::GetFrmFmtFromPool( sal_uInt16 nId )
+{
+ return (SwFrmFmt*)GetFmtFromPool( nId );
+}
+
+SwCharFmt* SwDoc::GetCharFmtFromPool( sal_uInt16 nId )
+{
+ return (SwCharFmt*)GetFmtFromPool( nId );
+}
+
+ // pruefe, ob diese "Auto-Collection" in Dokument schon/noch
+ // benutzt wird
+bool SwDoc::IsPoolFmtUsed( sal_uInt16 nId ) const
+{
+ SwFmt *pNewFmt = 0;
+ const SvPtrarr* pArray[ 2 ];
+ sal_uInt16 nArrCnt = 1;
+ sal_Bool bFnd = sal_True;
+
+ if( RES_POOLCHR_BEGIN <= nId && nId < RES_POOLCHR_END )
+ {
+ pArray[0] = pCharFmtTbl;
+ }
+ if( RES_POOLFRM_BEGIN <= nId && nId < RES_POOLFRM_END )
+ {
+ pArray[0] = pFrmFmtTbl;
+ pArray[1] = pSpzFrmFmtTbl;
+ nArrCnt = 2;
+ }
+ else
+ {
+ OSL_FAIL( "ungueltige Id" );
+ bFnd = sal_False;
+ }
+
+ if( bFnd )
+ {
+ bFnd = sal_False;
+ while( nArrCnt-- && !bFnd )
+ for( sal_uInt16 n = 0; !bFnd && n < (*pArray[nArrCnt]).Count(); ++n )
+ if( nId == ( pNewFmt = (SwFmt*)(*pArray[ nArrCnt ] )[ n ] )->
+ GetPoolFmtId() )
+ bFnd = sal_True;
+ }
+
+ // nicht gefunden oder keine Abhaengigen ?
+ if( bFnd && pNewFmt->GetDepends() )
+ {
+ // dann teste mal, ob es abhaengige ContentNodes im Nodes Array gibt
+ // (auch indirekte fuer Format-Ableitung! )
+ SwAutoFmtGetDocNode aGetHt( &GetNodes() );
+ bFnd = !pNewFmt->GetInfo( aGetHt );
+ }
+ else
+ bFnd = sal_False;
+
+ return bFnd;
+}
+
+
+
+void lcl_GetStdPgSize( SwDoc* pDoc, SfxItemSet& rSet )
+{
+ SwPageDesc* pStdPgDsc = pDoc->GetPageDescFromPool( RES_POOLPAGE_STANDARD );
+ SwFmtFrmSize aFrmSz( pStdPgDsc->GetMaster().GetFrmSize() );
+ if( pStdPgDsc->GetLandscape() )
+ {
+ SwTwips nTmp = aFrmSz.GetHeight();
+ aFrmSz.SetHeight( aFrmSz.GetWidth() );
+ aFrmSz.SetWidth( nTmp );
+ }
+ rSet.Put( aFrmSz );
+}
+
+SwPageDesc* SwDoc::GetPageDescFromPool( sal_uInt16 nId, bool bRegardLanguage )
+{
+ OSL_ENSURE( RES_POOLPAGE_BEGIN <= nId && nId < RES_POOLPAGE_END,
+ "Falsche AutoFormat-Id" );
+
+ SwPageDesc *pNewPgDsc;
+ sal_uInt16 n;
+
+ for( n = 0; n < aPageDescs.Count(); ++n )
+ if( nId == ( pNewPgDsc = aPageDescs[ n ] )->GetPoolFmtId() )
+ {
+ return pNewPgDsc;
+ }
+
+ // Fehlerfall: unbekannte Poolvorlage
+ if( RES_POOLPAGE_BEGIN > nId || nId >= RES_POOLPAGE_END )
+ {
+ OSL_ENSURE( !this, "ungueltige Id" );
+ nId = RES_POOLPAGE_BEGIN;
+ }
+
+ ResId aResId( sal_uInt32(RC_POOLPAGEDESC_BEGIN + nId - RES_POOLPAGE_BEGIN), *pSwResMgr );
+ String aNm( aResId );
+ {
+ sal_Bool bIsModified = IsModified();
+
+ {
+ ::sw::UndoGuard const undoGuard(GetIDocumentUndoRedo());
+ n = MakePageDesc( aNm, 0, bRegardLanguage );
+ }
+
+ pNewPgDsc = aPageDescs[ n ];
+ pNewPgDsc->SetPoolFmtId( nId );
+ if( !bIsModified )
+ ResetModified();
+ }
+
+
+ SvxLRSpaceItem aLR( RES_LR_SPACE );
+ aLR.SetLeft( GetMetricVal( CM_1 ) * 2 );
+ aLR.SetRight( aLR.GetLeft() );
+ SvxULSpaceItem aUL( RES_UL_SPACE );
+ aUL.SetUpper( (sal_uInt16)aLR.GetLeft() );
+ aUL.SetLower( (sal_uInt16)aLR.GetLeft() );
+
+ SwAttrSet aSet( GetAttrPool(), aPgFrmFmtSetRange );
+ sal_Bool bSetLeft = sal_True;
+
+ switch( nId )
+ {
+ case RES_POOLPAGE_STANDARD: // Standard-Seite
+ {
+ aSet.Put( aLR );
+ aSet.Put( aUL );
+ if( pNewPgDsc )
+ pNewPgDsc->SetUseOn( nsUseOnPage::PD_ALL );
+ }
+ break;
+
+ case RES_POOLPAGE_FIRST: // Erste Seite
+ case RES_POOLPAGE_REGISTER: // Verzeichnis
+ {
+ lcl_GetStdPgSize( this, aSet );
+ aSet.Put( aLR );
+ aSet.Put( aUL );
+ if( pNewPgDsc )
+ {
+ pNewPgDsc->SetUseOn( nsUseOnPage::PD_ALL );
+ if( RES_POOLPAGE_FIRST == nId )
+ pNewPgDsc->SetFollow( GetPageDescFromPool( RES_POOLPAGE_STANDARD ));
+ }
+ }
+ break;
+
+ case RES_POOLPAGE_LEFT: // Linke Seite
+ {
+ lcl_GetStdPgSize( this, aSet );
+ aSet.Put( aLR );
+ aSet.Put( aUL );
+ bSetLeft = sal_False;
+ if( pNewPgDsc )
+ {
+ pNewPgDsc->SetUseOn( nsUseOnPage::PD_LEFT );
+ // this relies on GetPageDescFromPool() not going into infinite recursion
+ // (by this point RES_POOLPAGE_LEFT will not reach this place again)
+ pNewPgDsc->SetFollow( GetPageDescFromPool( RES_POOLPAGE_RIGHT ));
+ }
+ }
+ break;
+ case RES_POOLPAGE_RIGHT: // Rechte Seite
+ {
+ lcl_GetStdPgSize( this, aSet );
+ aSet.Put( aLR );
+ aSet.Put( aUL );
+ bSetLeft = sal_False;
+ if( pNewPgDsc )
+ {
+ pNewPgDsc->SetUseOn( nsUseOnPage::PD_RIGHT );
+ pNewPgDsc->SetFollow( GetPageDescFromPool( RES_POOLPAGE_LEFT ));
+ }
+ }
+ break;
+
+ case RES_POOLPAGE_JAKET: // Umschlag
+ {
+ aLR.SetLeft( 0 ); aLR.SetRight( 0 );
+ aUL.SetUpper( 0 ); aUL.SetLower( 0 );
+ Size aPSize( SvxPaperInfo::GetPaperSize( PAPER_ENV_C65 ) );
+ LandscapeSwap( aPSize );
+ aSet.Put( SwFmtFrmSize( ATT_FIX_SIZE, aPSize.Width(), aPSize.Height() ));
+ aSet.Put( aLR );
+ aSet.Put( aUL );
+
+ if( pNewPgDsc )
+ {
+ pNewPgDsc->SetUseOn( nsUseOnPage::PD_ALL );
+ pNewPgDsc->SetLandscape( sal_True );
+ }
+ }
+ break;
+
+ case RES_POOLPAGE_HTML: // HTML
+ {
+ lcl_GetStdPgSize( this, aSet );
+ aLR.SetRight( GetMetricVal( CM_1 ));
+ aUL.SetUpper( (sal_uInt16)aLR.GetRight() );
+ aUL.SetLower( (sal_uInt16)aLR.GetRight() );
+ aSet.Put( aLR );
+ aSet.Put( aUL );
+
+ if( pNewPgDsc )
+ pNewPgDsc->SetUseOn( nsUseOnPage::PD_ALL );
+ }
+ break;
+ case RES_POOLPAGE_FOOTNOTE:
+ case RES_POOLPAGE_ENDNOTE:
+ {
+ lcl_GetStdPgSize( this, aSet );
+ aSet.Put( aLR );
+ aSet.Put( aUL );
+ if( pNewPgDsc )
+ pNewPgDsc->SetUseOn( nsUseOnPage::PD_ALL );
+ SwPageFtnInfo aInf( pNewPgDsc->GetFtnInfo() );
+ aInf.SetLineWidth( 0 );
+ aInf.SetTopDist( 0 );
+ aInf.SetBottomDist( 0 );
+ pNewPgDsc->SetFtnInfo( aInf );
+ }
+ break;
+ case RES_POOLPAGE_LANDSCAPE:
+ {
+ SwPageDesc* pStdPgDsc = this->GetPageDescFromPool( RES_POOLPAGE_STANDARD );
+ SwFmtFrmSize aFrmSz( pStdPgDsc->GetMaster().GetFrmSize() );
+ SwTwips nTmp = aFrmSz.GetHeight();
+ aFrmSz.SetHeight( aFrmSz.GetWidth() );
+ aFrmSz.SetWidth( nTmp );
+ aSet.Put( aFrmSz );
+ aSet.Put( aLR );
+ aSet.Put( aUL );
+ if( pNewPgDsc )
+ {
+ pNewPgDsc->SetUseOn( nsUseOnPage::PD_ALL );
+ pNewPgDsc->SetLandscape( sal_True );
+ }
+ }
+ break;
+
+ }
+
+ if( aSet.Count() )
+ {
+ {
+ if( bSetLeft )
+ pNewPgDsc->GetLeft().SetFmtAttr( aSet );
+ pNewPgDsc->GetMaster().SetFmtAttr( aSet );
+ }
+ }
+ return pNewPgDsc;
+}
+
+SwNumRule* SwDoc::GetNumRuleFromPool( sal_uInt16 nId )
+{
+ OSL_ENSURE( RES_POOLNUMRULE_BEGIN <= nId && nId < RES_POOLNUMRULE_END,
+ "Falsche AutoFormat-Id" );
+
+ SwNumRule* pNewRule;
+ sal_uInt16 n;
+
+ for( n = 0; n < GetNumRuleTbl().Count(); ++n )
+ if( nId == ( pNewRule = GetNumRuleTbl()[ n ] )->GetPoolFmtId() )
+ {
+ return pNewRule;
+ }
+
+ // Fehlerfall: unbekannte Poolvorlage
+ if( RES_POOLNUMRULE_BEGIN > nId || nId >= RES_POOLNUMRULE_END )
+ {
+ OSL_ENSURE( !this, "ungueltige Id" );
+ nId = RES_POOLNUMRULE_BEGIN;
+ }
+
+ ResId aResId( sal_uInt32(RC_POOLNUMRULE_BEGIN + nId - RES_POOLNUMRULE_BEGIN), *pSwResMgr );
+ String aNm( aResId );
+
+ SwCharFmt *pNumCFmt = 0, *pBullCFmt = 0;
+
+ const SvxNumberFormat::SvxNumPositionAndSpaceMode eNumberFormatPositionAndSpaceMode
+ = numfunc::GetDefaultPositionAndSpaceMode(); //#i89178#
+ // <--
+ {
+ sal_Bool bIsModified = IsModified();
+
+ n = MakeNumRule( aNm, 0, sal_False, eNumberFormatPositionAndSpaceMode );
+
+ pNewRule = GetNumRuleTbl()[ n ];
+ pNewRule->SetPoolFmtId( nId );
+ pNewRule->SetAutoRule( sal_False );
+
+ if( RES_POOLNUMRULE_NUM1 <= nId && nId <= RES_POOLNUMRULE_NUM5 )
+ pNumCFmt = GetCharFmtFromPool( RES_POOLCHR_NUM_LEVEL );
+
+ if( ( RES_POOLNUMRULE_BUL1 <= nId && nId <= RES_POOLNUMRULE_BUL5 ) ||
+ RES_POOLNUMRULE_NUM5 == nId )
+ pBullCFmt = GetCharFmtFromPool( RES_POOLCHR_NUM_LEVEL );
+
+ if( !bIsModified )
+ ResetModified();
+ }
+
+ switch( nId )
+ {
+ case RES_POOLNUMRULE_NUM1:
+ {
+ SwNumFmt aFmt;
+ aFmt.SetPositionAndSpaceMode( eNumberFormatPositionAndSpaceMode );
+ aFmt.SetNumberingType(SVX_NUM_ARABIC);
+ aFmt.SetCharFmt( pNumCFmt );
+ aFmt.SetStart( 1 );
+ aFmt.SetIncludeUpperLevels( 1 );
+ aFmt.SetSuffix( aDotStr );
+
+ static const sal_uInt16 aAbsSpace[ MAXLEVEL ] =
+ {
+// cm: 0,5 1,0 1,5 2,0 2,5 3,0 3,5 4,0 4,5 5,0
+ 283, 567, 850, 1134, 1417, 1701, 1984, 2268, 2551, 2835
+ };
+#ifdef USE_MEASUREMENT
+ static const sal_uInt16 aAbsSpaceInch[ MAXLEVEL ] =
+ {
+ 283, 567, 850, 1134, 1417, 1701, 1984, 2268, 2551, 2835
+ };
+ const sal_uInt16* pArr = MEASURE_METRIC ==
+ SvtSysLocale().GetLocaleData().getMeasurementSystemEnum()
+ ? aAbsSpace
+ : aAbsSpaceInch;
+#else
+ const sal_uInt16* pArr = aAbsSpace;
+#endif
+
+ if ( eNumberFormatPositionAndSpaceMode == SvxNumberFormat::LABEL_WIDTH_AND_POSITION )
+ {
+ aFmt.SetFirstLineOffset( - (*pArr) );
+ }
+ else if ( eNumberFormatPositionAndSpaceMode == SvxNumberFormat::LABEL_ALIGNMENT )
+ {
+ aFmt.SetLabelFollowedBy( SvxNumberFormat::LISTTAB );
+ aFmt.SetFirstLineIndent( - (*pArr) );
+ }
+
+ for( n = 0; n < MAXLEVEL; ++n, ++pArr )
+ {
+ if ( eNumberFormatPositionAndSpaceMode == SvxNumberFormat::LABEL_WIDTH_AND_POSITION )
+ {
+ aFmt.SetAbsLSpace( *pArr );
+ }
+ else if ( eNumberFormatPositionAndSpaceMode == SvxNumberFormat::LABEL_ALIGNMENT )
+ {
+ aFmt.SetListtabPos( *pArr );
+ aFmt.SetIndentAt( *pArr );
+ }
+
+ pNewRule->Set( n, aFmt );
+ }
+ }
+ break;
+
+ case RES_POOLNUMRULE_NUM2:
+ {
+ static const sal_uInt16 aAbsSpace[ MAXLEVEL ] =
+ {
+ 283, 283, 567, 709, // 0.50, 0.50, 1.00, 1.25
+ 850, 1021, 1304, 1474, // 1.50, 1.80, 2.30, 2.60
+ 1588, 1758 // 2.80, 3.10
+ };
+
+#ifdef USE_MEASUREMENT
+ static const sal_uInt16 aAbsSpaceInch[ MAXLEVEL ] =
+ {
+ 385, 385, 770, 963,
+ 1155, 1386, 1771, 2002,
+ 2156, 2387
+ };
+
+ const sal_uInt16* pArr = MEASURE_METRIC ==
+ SvtSysLocale().GetLocaleData().getMeasurementSystemEnum()
+ ? aAbsSpace
+ : aAbsSpaceInch;
+#else
+ const sal_uInt16* pArr = aAbsSpace;
+#endif
+ SwNumFmt aFmt;
+
+ aFmt.SetPositionAndSpaceMode( eNumberFormatPositionAndSpaceMode );
+ aFmt.SetNumberingType(SVX_NUM_ARABIC);
+ aFmt.SetCharFmt( pNumCFmt );
+ aFmt.SetIncludeUpperLevels( 1 );
+
+ if ( eNumberFormatPositionAndSpaceMode == SvxNumberFormat::LABEL_ALIGNMENT )
+ {
+ aFmt.SetLabelFollowedBy( SvxNumberFormat::LISTTAB );
+ }
+
+ sal_uInt16 nSpace = 0;
+ for( n = 0; n < MAXLEVEL; ++n )
+ {
+ if ( eNumberFormatPositionAndSpaceMode == SvxNumberFormat::LABEL_WIDTH_AND_POSITION )
+ {
+ aFmt.SetAbsLSpace( nSpace = nSpace + pArr[ n ] );
+ aFmt.SetFirstLineOffset( - pArr[ n ] );
+ }
+ else if ( eNumberFormatPositionAndSpaceMode == SvxNumberFormat::LABEL_ALIGNMENT )
+ {
+ aFmt.SetListtabPos( nSpace = nSpace + pArr[ n ] );
+ aFmt.SetIndentAt( nSpace );
+ aFmt.SetFirstLineIndent( - pArr[ n ] );
+ }
+
+ aFmt.SetStart( n+1 );
+ pNewRule->Set( n, aFmt );
+ }
+ }
+ break;
+ case RES_POOLNUMRULE_NUM3:
+ {
+ SwNumFmt aFmt;
+
+ aFmt.SetPositionAndSpaceMode( eNumberFormatPositionAndSpaceMode );
+ aFmt.SetNumberingType(SVX_NUM_ARABIC);
+ aFmt.SetCharFmt( pNumCFmt );
+ aFmt.SetIncludeUpperLevels( 1 );
+
+ sal_uInt16 nOffs = GetMetricVal( CM_1 ) * 3;
+
+ if ( eNumberFormatPositionAndSpaceMode == SvxNumberFormat::LABEL_WIDTH_AND_POSITION )
+ {
+ aFmt.SetFirstLineOffset( - nOffs );
+ }
+ else if ( eNumberFormatPositionAndSpaceMode == SvxNumberFormat::LABEL_ALIGNMENT )
+ {
+ aFmt.SetLabelFollowedBy( SvxNumberFormat::LISTTAB );
+ aFmt.SetFirstLineIndent( - nOffs );
+ }
+
+ for( n = 0; n < MAXLEVEL; ++n )
+ {
+ if ( eNumberFormatPositionAndSpaceMode == SvxNumberFormat::LABEL_WIDTH_AND_POSITION )
+ {
+ aFmt.SetAbsLSpace( (n+1) * nOffs );
+ }
+ else if ( eNumberFormatPositionAndSpaceMode == SvxNumberFormat::LABEL_ALIGNMENT )
+ {
+ aFmt.SetListtabPos( (n+1) * nOffs );
+ aFmt.SetIndentAt( (n+1) * nOffs );
+ }
+
+ aFmt.SetStart( n+1 );
+ pNewRule->Set( n, aFmt );
+ }
+ }
+ break;
+ case RES_POOLNUMRULE_NUM4:
+ {
+ SwNumFmt aFmt;
+
+ aFmt.SetPositionAndSpaceMode( eNumberFormatPositionAndSpaceMode );
+ aFmt.SetNumberingType(SVX_NUM_ROMAN_UPPER);
+ aFmt.SetCharFmt( pNumCFmt );
+ aFmt.SetIncludeUpperLevels( 1 );
+ aFmt.SetSuffix( aDotStr );
+
+ static const sal_uInt16 aAbsSpace[ MAXLEVEL ] =
+ {
+// cm: 0,5 1,0 1,5 2,0 2,5 3,0 3,5 4,0 4,5 5,0
+ 283, 567, 850, 1134, 1417, 1701, 1984, 2268, 2551, 2835
+ };
+#ifdef USE_MEASUREMENT
+ static const sal_uInt16 aAbsSpaceInch[ MAXLEVEL ] =
+ {
+ 283, 567, 850, 1134, 1417, 1701, 1984, 2268, 2551, 2835
+ };
+ const sal_uInt16* pArr = MEASURE_METRIC ==
+ SvtSysLocale().GetLocaleData().getMeasurementSystemEnum()
+ ? aAbsSpace
+ : aAbsSpaceInch;
+#else
+ const sal_uInt16* pArr = aAbsSpace;
+#endif
+
+ if ( eNumberFormatPositionAndSpaceMode == SvxNumberFormat::LABEL_WIDTH_AND_POSITION )
+ {
+ aFmt.SetFirstLineOffset( - (*pArr) );
+ }
+ else if ( eNumberFormatPositionAndSpaceMode == SvxNumberFormat::LABEL_ALIGNMENT )
+ {
+ aFmt.SetLabelFollowedBy( SvxNumberFormat::SPACE );
+ aFmt.SetFirstLineIndent( - (*pArr) );
+ }
+
+ for( n = 0; n < MAXLEVEL; ++n, ++pArr )
+ {
+ aFmt.SetStart( n + 1 );
+
+ if ( eNumberFormatPositionAndSpaceMode == SvxNumberFormat::LABEL_WIDTH_AND_POSITION )
+ {
+ aFmt.SetAbsLSpace( *pArr );
+ }
+ else if ( eNumberFormatPositionAndSpaceMode == SvxNumberFormat::LABEL_ALIGNMENT )
+ {
+ aFmt.SetListtabPos( *pArr );
+ aFmt.SetIndentAt( *pArr );
+ }
+
+ pNewRule->Set( n, aFmt );
+ }
+ }
+ break;
+ case RES_POOLNUMRULE_NUM5:
+ {
+ // [ First, LSpace ]
+ static const sal_uInt16 aAbsSpace0to2[] =
+ {
+ 227, 227, // 0.40, 0.40,
+ 369, 624, // 0.65, 1.10,
+ 255, 879 // 0.45, 1.55
+ };
+
+#ifdef USE_MEASUREMENT
+ static const sal_uInt16 aAbsSpaceInch0to2[] =
+ {
+ 308, 308,
+ 501, 847,
+ 347, 1194
+ };
+ const sal_uInt16* pArr0to2 = MEASURE_METRIC ==
+ SvtSysLocale().GetLocaleData().getMeasurementSystemEnum()
+ ? aAbsSpace0to2
+ : aAbsSpaceInch0to2;
+#else
+ const sal_uInt16* pArr0to2 = aAbsSpace0to2;
+#endif
+ SwNumFmt aFmt;
+
+ aFmt.SetPositionAndSpaceMode( eNumberFormatPositionAndSpaceMode );
+ aFmt.SetNumberingType(SVX_NUM_ARABIC);
+ aFmt.SetStart( 1 );
+ aFmt.SetIncludeUpperLevels( 1 );
+ aFmt.SetSuffix( aDotStr );
+
+ if ( eNumberFormatPositionAndSpaceMode == SvxNumberFormat::LABEL_ALIGNMENT )
+ {
+ aFmt.SetLabelFollowedBy( SvxNumberFormat::LISTTAB );
+ }
+
+ if ( eNumberFormatPositionAndSpaceMode == SvxNumberFormat::LABEL_WIDTH_AND_POSITION )
+ {
+ aFmt.SetFirstLineOffset( -pArr0to2[0] ); // == 0.40 cm
+ aFmt.SetAbsLSpace( pArr0to2[1] ); // == 0.40 cm
+ }
+ else if ( eNumberFormatPositionAndSpaceMode == SvxNumberFormat::LABEL_ALIGNMENT )
+ {
+ aFmt.SetFirstLineIndent( -pArr0to2[0] );
+ aFmt.SetListtabPos( pArr0to2[1] );
+ aFmt.SetIndentAt( pArr0to2[1] );
+ }
+
+ aFmt.SetCharFmt( pNumCFmt );
+ pNewRule->Set( 0, aFmt );
+
+ aFmt.SetIncludeUpperLevels( 2 );
+ aFmt.SetStart( 2 );
+
+ if ( eNumberFormatPositionAndSpaceMode == SvxNumberFormat::LABEL_WIDTH_AND_POSITION )
+ {
+ aFmt.SetFirstLineOffset( -pArr0to2[2] ); // == 0.65 cm
+ aFmt.SetAbsLSpace( pArr0to2[3] ); // == 1.10 cm
+ }
+ else if ( eNumberFormatPositionAndSpaceMode == SvxNumberFormat::LABEL_ALIGNMENT )
+ {
+ aFmt.SetFirstLineIndent( -pArr0to2[2] );
+ aFmt.SetListtabPos( pArr0to2[3] );
+ aFmt.SetIndentAt( pArr0to2[3] );
+ }
+
+ pNewRule->Set( 1, aFmt );
+
+ aFmt.SetNumberingType(SVX_NUM_CHARS_LOWER_LETTER);
+ aFmt.SetSuffix( ')');
+ aFmt.SetIncludeUpperLevels( 1 );
+ aFmt.SetStart( 3 );
+
+ if ( eNumberFormatPositionAndSpaceMode == SvxNumberFormat::LABEL_WIDTH_AND_POSITION )
+ {
+ aFmt.SetFirstLineOffset( - pArr0to2[4] ); // == 0.45cm
+ aFmt.SetAbsLSpace( pArr0to2[5] ); // == 1.55 cm
+ }
+ else if ( eNumberFormatPositionAndSpaceMode == SvxNumberFormat::LABEL_ALIGNMENT )
+ {
+ aFmt.SetFirstLineIndent( -pArr0to2[4] );
+ aFmt.SetListtabPos( pArr0to2[5] );
+ aFmt.SetIndentAt( pArr0to2[5] );
+ }
+
+ pNewRule->Set( 2, aFmt );
+
+
+ aFmt.SetNumberingType(SVX_NUM_CHAR_SPECIAL);
+ aFmt.SetCharFmt( pBullCFmt );
+ aFmt.SetBulletFont( &numfunc::GetDefBulletFont() );
+ aFmt.SetBulletChar( cBulletChar );
+ sal_uInt16 nOffs = GetMetricVal( CM_01 ) * 4,
+ nOffs2 = GetMetricVal( CM_1 ) * 2;
+
+ if ( eNumberFormatPositionAndSpaceMode == SvxNumberFormat::LABEL_WIDTH_AND_POSITION )
+ {
+ aFmt.SetFirstLineOffset( - nOffs );
+ }
+ else if ( eNumberFormatPositionAndSpaceMode == SvxNumberFormat::LABEL_ALIGNMENT )
+ {
+ aFmt.SetFirstLineIndent( - nOffs );
+ }
+
+ aFmt.SetSuffix( aEmptyStr );
+ for( n = 3; n < MAXLEVEL; ++n )
+ {
+ aFmt.SetStart( n+1 );
+
+ if ( eNumberFormatPositionAndSpaceMode == SvxNumberFormat::LABEL_WIDTH_AND_POSITION )
+ {
+ aFmt.SetAbsLSpace( nOffs2 + ((n-3) * nOffs) );
+ }
+ else if ( eNumberFormatPositionAndSpaceMode == SvxNumberFormat::LABEL_ALIGNMENT )
+ {
+ aFmt.SetListtabPos( nOffs2 + ((n-3) * nOffs) );
+ aFmt.SetIndentAt( nOffs2 + ((n-3) * nOffs) );
+ }
+
+ pNewRule->Set( n, aFmt );
+ }
+ }
+ break;
+
+ case RES_POOLNUMRULE_BUL1:
+ {
+ SwNumFmt aFmt;
+
+ aFmt.SetPositionAndSpaceMode( eNumberFormatPositionAndSpaceMode );
+ aFmt.SetNumberingType(SVX_NUM_CHAR_SPECIAL);
+ aFmt.SetCharFmt( pBullCFmt );
+ aFmt.SetStart( 1 );
+ aFmt.SetIncludeUpperLevels( 1 );
+ aFmt.SetBulletFont( &numfunc::GetDefBulletFont() );
+ aFmt.SetBulletChar( cBulletChar );
+
+ static const sal_uInt16 aAbsSpace[ MAXLEVEL ] =
+ {
+// cm: 0,4 0,8 1,2 1,6 2,0 2,4 2,8 3,2 3,6 4,0
+ 227, 454, 680, 907, 1134, 1361, 1587, 1814, 2041, 2268
+ };
+#ifdef USE_MEASUREMENT
+ static const sal_uInt16 aAbsSpaceInch[ MAXLEVEL ] =
+ {
+ 227, 454, 680, 907, 1134, 1361, 1587, 1814, 2041, 2268
+ };
+ const sal_uInt16* pArr = MEASURE_METRIC ==
+ SvtSysLocale().GetLocaleData().getMeasurementSystemEnum()
+ ? aAbsSpace
+ : aAbsSpaceInch;
+#else
+ const sal_uInt16* pArr = aAbsSpace;
+#endif
+
+ if ( eNumberFormatPositionAndSpaceMode == SvxNumberFormat::LABEL_WIDTH_AND_POSITION )
+ {
+ aFmt.SetFirstLineOffset( - (*pArr) );
+ }
+ else if ( eNumberFormatPositionAndSpaceMode == SvxNumberFormat::LABEL_ALIGNMENT )
+ {
+ aFmt.SetLabelFollowedBy( SvxNumberFormat::LISTTAB );
+ aFmt.SetFirstLineIndent( - (*pArr) );
+ }
+
+ for( n = 0; n < MAXLEVEL; ++n, ++pArr )
+ {
+ if ( eNumberFormatPositionAndSpaceMode == SvxNumberFormat::LABEL_WIDTH_AND_POSITION )
+ {
+ aFmt.SetAbsLSpace( *pArr );
+ }
+ else if ( eNumberFormatPositionAndSpaceMode == SvxNumberFormat::LABEL_ALIGNMENT )
+ {
+ aFmt.SetListtabPos( *pArr );
+ aFmt.SetIndentAt( *pArr );
+ }
+
+ pNewRule->Set( n, aFmt );
+ }
+ }
+ break;
+ case RES_POOLNUMRULE_BUL2:
+ {
+ SwNumFmt aFmt;
+
+ aFmt.SetPositionAndSpaceMode( eNumberFormatPositionAndSpaceMode );
+ aFmt.SetNumberingType(SVX_NUM_CHAR_SPECIAL);
+ aFmt.SetCharFmt( pBullCFmt );
+ aFmt.SetStart( 1 );
+ aFmt.SetIncludeUpperLevels( 1 );
+ aFmt.SetBulletFont( &numfunc::GetDefBulletFont() );
+ aFmt.SetBulletChar( 0x2013 );
+
+ static const sal_uInt16 aAbsSpace[ MAXLEVEL ] =
+ {
+// cm: 0,3 0,6 0,9 1,2 1,5 1,8 2,1 2,4 2,7 3,0
+ 170, 340, 510, 680, 850, 1020, 1191, 1361, 1531, 1701
+ };
+#ifdef USE_MEASUREMENT
+ static const sal_uInt16 aAbsSpaceInch[ MAXLEVEL ] =
+ {
+ 170, 340, 510, 680, 850, 1020, 1191, 1361, 1531, 1701
+ };
+ const sal_uInt16* pArr = MEASURE_METRIC ==
+ SvtSysLocale().GetLocaleData().getMeasurementSystemEnum()
+ ? aAbsSpace
+ : aAbsSpaceInch;
+#else
+ const sal_uInt16* pArr = aAbsSpace;
+#endif
+
+ if ( eNumberFormatPositionAndSpaceMode == SvxNumberFormat::LABEL_WIDTH_AND_POSITION )
+ {
+ aFmt.SetFirstLineOffset( - (*pArr) );
+ }
+ else if ( eNumberFormatPositionAndSpaceMode == SvxNumberFormat::LABEL_ALIGNMENT )
+ {
+ aFmt.SetLabelFollowedBy( SvxNumberFormat::LISTTAB );
+ aFmt.SetFirstLineIndent( - (*pArr) );
+ }
+
+ for( n = 0; n < MAXLEVEL; ++n, ++pArr )
+ {
+ if ( eNumberFormatPositionAndSpaceMode == SvxNumberFormat::LABEL_WIDTH_AND_POSITION )
+ {
+ aFmt.SetAbsLSpace( *pArr );
+ }
+ else if ( eNumberFormatPositionAndSpaceMode == SvxNumberFormat::LABEL_ALIGNMENT )
+ {
+ aFmt.SetListtabPos( *pArr );
+ aFmt.SetIndentAt( *pArr );
+ }
+
+ pNewRule->Set( n, aFmt );
+ }
+ }
+ break;
+ case RES_POOLNUMRULE_BUL3:
+ {
+ SwNumFmt aFmt;
+
+ aFmt.SetPositionAndSpaceMode( eNumberFormatPositionAndSpaceMode );
+
+ aFmt.SetNumberingType(SVX_NUM_CHAR_SPECIAL);
+ aFmt.SetCharFmt( pBullCFmt );
+ aFmt.SetStart( 1 );
+ aFmt.SetIncludeUpperLevels( 1 );
+ aFmt.SetBulletFont( &numfunc::GetDefBulletFont() );
+
+ sal_uInt16 nOffs = GetMetricVal( CM_01 ) * 4;
+
+ if ( eNumberFormatPositionAndSpaceMode == SvxNumberFormat::LABEL_WIDTH_AND_POSITION )
+ {
+ aFmt.SetFirstLineOffset( - nOffs );
+ }
+ else if ( eNumberFormatPositionAndSpaceMode == SvxNumberFormat::LABEL_ALIGNMENT )
+ {
+ aFmt.SetLabelFollowedBy( SvxNumberFormat::LISTTAB );
+ aFmt.SetFirstLineIndent( - nOffs );
+ }
+
+ for( n = 0; n < MAXLEVEL; ++n )
+ {
+ aFmt.SetBulletChar( ( n & 1 ? 0x25a1 : 0x2611 ) );
+
+ if ( eNumberFormatPositionAndSpaceMode == SvxNumberFormat::LABEL_WIDTH_AND_POSITION )
+ {
+ aFmt.SetAbsLSpace( ((n & 1) +1) * nOffs );
+ }
+ else if ( eNumberFormatPositionAndSpaceMode == SvxNumberFormat::LABEL_ALIGNMENT )
+ {
+ aFmt.SetListtabPos( ((n & 1) +1) * nOffs );
+ aFmt.SetIndentAt( ((n & 1) +1) * nOffs );
+ }
+
+ pNewRule->Set( n, aFmt );
+ }
+ }
+ break;
+ case RES_POOLNUMRULE_BUL4:
+ {
+ SwNumFmt aFmt;
+
+ aFmt.SetPositionAndSpaceMode( eNumberFormatPositionAndSpaceMode );
+ aFmt.SetNumberingType(SVX_NUM_CHAR_SPECIAL);
+ aFmt.SetCharFmt( pBullCFmt );
+ aFmt.SetStart( 1 );
+ aFmt.SetIncludeUpperLevels( 1 );
+ aFmt.SetBulletFont( &numfunc::GetDefBulletFont() );
+
+ static const sal_uInt16 aAbsSpace[ MAXLEVEL ] =
+ {
+// cm: 0,4 0,8 1,2 1,6 2,0 2,4 2,8 3,2 3,6 4,0
+ 227, 454, 680, 907, 1134, 1361, 1587, 1814, 2041, 2268
+ };
+#ifdef USE_MEASUREMENT
+ static const sal_uInt16 aAbsSpaceInch[ MAXLEVEL ] =
+ {
+ 227, 454, 680, 907, 1134, 1361, 1587, 1814, 2041, 2268
+ };
+ const sal_uInt16* pArr = MEASURE_METRIC ==
+ SvtSysLocale().GetLocaleData().getMeasurementSystemEnum()
+ ? aAbsSpace
+ : aAbsSpaceInch;
+#else
+ const sal_uInt16* pArr = aAbsSpace;
+#endif
+
+ if ( eNumberFormatPositionAndSpaceMode == SvxNumberFormat::LABEL_WIDTH_AND_POSITION )
+ {
+ aFmt.SetFirstLineOffset( - (*pArr) );
+ }
+ else if ( eNumberFormatPositionAndSpaceMode == SvxNumberFormat::LABEL_ALIGNMENT )
+ {
+ aFmt.SetLabelFollowedBy( SvxNumberFormat::SPACE );
+ aFmt.SetFirstLineIndent( - (*pArr) );
+ }
+
+ for( n = 0; n < MAXLEVEL; ++n, ++pArr )
+ {
+ switch( n )
+ {
+ case 0: aFmt.SetBulletChar( 0x27a2 ); break;
+ case 1: aFmt.SetBulletChar( 0xE006 ); break;
+ default: aFmt.SetBulletChar( 0xE004 ); break;
+ }
+
+ if ( eNumberFormatPositionAndSpaceMode == SvxNumberFormat::LABEL_WIDTH_AND_POSITION )
+ {
+ aFmt.SetAbsLSpace( *pArr );
+ }
+ else if ( eNumberFormatPositionAndSpaceMode == SvxNumberFormat::LABEL_ALIGNMENT )
+ {
+ aFmt.SetListtabPos( *pArr );
+ aFmt.SetIndentAt( *pArr );
+ }
+
+ pNewRule->Set( n, aFmt );
+ }
+ }
+ break;
+ case RES_POOLNUMRULE_BUL5:
+ {
+ SwNumFmt aFmt;
+
+ aFmt.SetPositionAndSpaceMode( eNumberFormatPositionAndSpaceMode );
+ aFmt.SetNumberingType(SVX_NUM_CHAR_SPECIAL);
+ aFmt.SetCharFmt( pBullCFmt );
+ aFmt.SetStart( 1 );
+ aFmt.SetIncludeUpperLevels( 1 );
+ aFmt.SetBulletChar( 0x2717 );
+ aFmt.SetBulletFont( &numfunc::GetDefBulletFont() );
+
+ static const sal_uInt16 aAbsSpace[ MAXLEVEL ] =
+ {
+// cm: 0,4 0,8 1,2 1,6 2,0 2,4 2,8 3,2 3,6 4,0
+ 227, 454, 680, 907, 1134, 1361, 1587, 1814, 2041, 2268
+ };
+#ifdef USE_MEASUREMENT
+ static const sal_uInt16 aAbsSpaceInch[ MAXLEVEL ] =
+ {
+ 227, 454, 680, 907, 1134, 1361, 1587, 1814, 2041, 2268
+ };
+ const sal_uInt16* pArr = MEASURE_METRIC ==
+ SvtSysLocale().GetLocaleData().getMeasurementSystemEnum()
+ ? aAbsSpace
+ : aAbsSpaceInch;
+#else
+ const sal_uInt16* pArr = aAbsSpace;
+#endif
+
+ if ( eNumberFormatPositionAndSpaceMode == SvxNumberFormat::LABEL_WIDTH_AND_POSITION )
+ {
+ aFmt.SetFirstLineOffset( - (*pArr) );
+ }
+ else if ( eNumberFormatPositionAndSpaceMode == SvxNumberFormat::LABEL_ALIGNMENT )
+ {
+ aFmt.SetLabelFollowedBy( SvxNumberFormat::LISTTAB );
+ aFmt.SetFirstLineIndent( - (*pArr) );
+ }
+
+ for( n = 0; n < MAXLEVEL; ++n, ++pArr )
+ {
+ if ( eNumberFormatPositionAndSpaceMode == SvxNumberFormat::LABEL_WIDTH_AND_POSITION )
+ {
+ aFmt.SetAbsLSpace( *pArr );
+ }
+ else if ( eNumberFormatPositionAndSpaceMode == SvxNumberFormat::LABEL_ALIGNMENT )
+ {
+ aFmt.SetListtabPos( *pArr );
+ aFmt.SetIndentAt( *pArr );
+ }
+
+ pNewRule->Set( n, aFmt );
+ }
+ }
+ break;
+ }
+
+ return pNewRule;
+}
+
+
+
+ // pruefe, ob diese "Auto-Collection" in Dokument schon/noch
+ // benutzt wird
+bool SwDoc::IsPoolPageDescUsed( sal_uInt16 nId ) const
+{
+ OSL_ENSURE( RES_POOLPAGE_BEGIN <= nId && nId < RES_POOLPAGE_END,
+ "Falsche AutoFormat-Id" );
+ SwPageDesc *pNewPgDsc = 0;
+ sal_Bool bFnd = sal_False;
+ for( sal_uInt16 n = 0; !bFnd && n < aPageDescs.Count(); ++n )
+ {
+ pNewPgDsc = aPageDescs[ n ];
+ if( nId == pNewPgDsc->GetPoolFmtId() )
+ bFnd = sal_True;
+ }
+
+ // nicht gefunden oder keine Abhaengigen ?
+ if( !bFnd || !pNewPgDsc->GetDepends() ) // ??????
+ return sal_False;
+
+ // dann teste mal, ob es abhaengige ContentNodes im Nodes Array gibt
+ // (auch indirekte fuer Format-Ableitung! )
+ SwAutoFmtGetDocNode aGetHt( &GetNodes() );
+ return !pNewPgDsc->GetInfo( aGetHt );
+}
+
+// erfrage ob die Absatz-/Zeichen-/Rahmen-/Seiten - Vorlage benutzt wird
+sal_Bool SwDoc::IsUsed( const SwModify& rModify ) const
+{
+ // dann teste mal, ob es abhaengige ContentNodes im Nodes Array gibt
+ // (auch indirekte fuer Format-Ableitung! )
+ SwAutoFmtGetDocNode aGetHt( &GetNodes() );
+ return !rModify.GetInfo( aGetHt );
+}
+
+// erfrage ob die NumRule benutzt wird
+sal_Bool SwDoc::IsUsed( const SwNumRule& rRule ) const
+{
+ sal_Bool bUsed = rRule.GetTxtNodeListSize() > 0 ||
+ rRule.GetParagraphStyleListSize() > 0;
+
+ return bUsed;
+ // <--
+}
+
+ // Suche die Position vom Vorlagen-Namen. Ist nicht vorhanden
+ // dann fuege neu ein
+sal_uInt16 SwDoc::SetDocPattern( const String& rPatternName )
+{
+ OSL_ENSURE( rPatternName.Len(), "kein Dokument-Vorlagenname" );
+
+ sal_uInt16 nNewPos = aPatternNms.Count();
+ for( sal_uInt16 n = 0; n < aPatternNms.Count(); ++n )
+ if( !aPatternNms[n] )
+ {
+ if( nNewPos == aPatternNms.Count() )
+ nNewPos = n;
+ }
+ else if( rPatternName == *aPatternNms[n] )
+ return n;
+
+ if( nNewPos < aPatternNms.Count() )
+ aPatternNms.Remove( nNewPos ); // Platz wieder frei machen
+
+ String* pNewNm = new String( rPatternName );
+ aPatternNms.Insert( pNewNm, nNewPos );
+ SetModified();
+ return nNewPos;
+}
+
+sal_uInt16 GetPoolParent( sal_uInt16 nId )
+{
+ sal_uInt16 nRet = USHRT_MAX;
+ if( POOLGRP_NOCOLLID & nId ) // 1 == Formate / 0 == Collections
+ {
+ switch( ( COLL_GET_RANGE_BITS | POOLGRP_NOCOLLID ) & nId )
+ {
+ case POOLGRP_CHARFMT:
+ case POOLGRP_FRAMEFMT:
+ nRet = 0; // vom default abgeleitet
+ break;
+ case POOLGRP_PAGEDESC:
+ case POOLGRP_NUMRULE:
+ break; // es gibt keine Ableitung
+ }
+ }
+ else
+ {
+ switch( COLL_GET_RANGE_BITS & nId )
+ {
+ case COLL_TEXT_BITS:
+ switch( nId )
+ {
+ case RES_POOLCOLL_STANDARD:
+ nRet = 0; break;
+ case RES_POOLCOLL_TEXT_IDENT:
+ case RES_POOLCOLL_TEXT_NEGIDENT:
+ case RES_POOLCOLL_TEXT_MOVE:
+ case RES_POOLCOLL_CONFRONTATION:
+ case RES_POOLCOLL_MARGINAL:
+ nRet = RES_POOLCOLL_TEXT; break;
+
+ case RES_POOLCOLL_TEXT:
+ case RES_POOLCOLL_GREETING:
+ case RES_POOLCOLL_SIGNATURE:
+ case RES_POOLCOLL_HEADLINE_BASE:
+ nRet = RES_POOLCOLL_STANDARD; break;
+
+ case RES_POOLCOLL_HEADLINE1:
+ case RES_POOLCOLL_HEADLINE2:
+ case RES_POOLCOLL_HEADLINE3:
+ case RES_POOLCOLL_HEADLINE4:
+ case RES_POOLCOLL_HEADLINE5:
+ case RES_POOLCOLL_HEADLINE6:
+ case RES_POOLCOLL_HEADLINE7:
+ case RES_POOLCOLL_HEADLINE8:
+ case RES_POOLCOLL_HEADLINE9:
+ case RES_POOLCOLL_HEADLINE10:
+ nRet = RES_POOLCOLL_HEADLINE_BASE; break;
+ }
+ break;
+
+ case COLL_LISTS_BITS:
+ switch( nId )
+ {
+ case RES_POOLCOLL_NUMBUL_BASE:
+ nRet = RES_POOLCOLL_TEXT; break;
+
+ default:
+ nRet = RES_POOLCOLL_NUMBUL_BASE; break;
+ }
+ break;
+
+ case COLL_EXTRA_BITS:
+ switch( nId )
+ {
+ case RES_POOLCOLL_FRAME:
+ nRet = RES_POOLCOLL_TEXT; break;
+
+ case RES_POOLCOLL_TABLE_HDLN:
+ nRet = RES_POOLCOLL_TABLE; break;
+
+ case RES_POOLCOLL_TABLE:
+ case RES_POOLCOLL_FOOTNOTE:
+ case RES_POOLCOLL_ENDNOTE:
+ case RES_POOLCOLL_JAKETADRESS:
+ case RES_POOLCOLL_SENDADRESS:
+ case RES_POOLCOLL_HEADER:
+ case RES_POOLCOLL_HEADERL:
+ case RES_POOLCOLL_HEADERR:
+ case RES_POOLCOLL_FOOTER:
+ case RES_POOLCOLL_FOOTERL:
+ case RES_POOLCOLL_FOOTERR:
+ case RES_POOLCOLL_LABEL:
+ nRet = RES_POOLCOLL_STANDARD; break;
+
+ case RES_POOLCOLL_LABEL_ABB:
+ case RES_POOLCOLL_LABEL_TABLE:
+ case RES_POOLCOLL_LABEL_FRAME:
+ case RES_POOLCOLL_LABEL_DRAWING:
+ nRet = RES_POOLCOLL_LABEL; break;
+ }
+ break;
+
+ case COLL_REGISTER_BITS:
+ switch( nId )
+ {
+ case RES_POOLCOLL_REGISTER_BASE:
+ nRet = RES_POOLCOLL_STANDARD; break;
+
+ case RES_POOLCOLL_TOX_USERH:
+ case RES_POOLCOLL_TOX_CNTNTH:
+ case RES_POOLCOLL_TOX_IDXH:
+ case RES_POOLCOLL_TOX_ILLUSH:
+ case RES_POOLCOLL_TOX_OBJECTH:
+ case RES_POOLCOLL_TOX_TABLESH:
+ case RES_POOLCOLL_TOX_AUTHORITIESH:
+ nRet = RES_POOLCOLL_HEADLINE_BASE; break;
+
+ default:
+ nRet = RES_POOLCOLL_REGISTER_BASE; break;
+ }
+ break;
+
+ case COLL_DOC_BITS:
+ nRet = RES_POOLCOLL_HEADLINE_BASE;
+ break;
+
+ case COLL_HTML_BITS:
+ nRet = RES_POOLCOLL_STANDARD;
+ break;
+ }
+ }
+
+ return nRet;
+}
+
+void SwDoc::RemoveAllFmtLanguageDependencies()
+{
+ /* Restore the language independ pool defaults and styles. */
+ GetAttrPool().ResetPoolDefaultItem( RES_PARATR_ADJUST );
+
+ SwTxtFmtColl * pTxtFmtColl = GetTxtCollFromPool( RES_POOLCOLL_STANDARD );
+
+ pTxtFmtColl->ResetFmtAttr( RES_PARATR_ADJUST );
+ /* koreans do not like SvxScriptItem(TRUE) */
+ pTxtFmtColl->ResetFmtAttr( RES_PARATR_SCRIPTSPACE );
+
+ SvxFrameDirectionItem aFrameDir( FRMDIR_HORI_LEFT_TOP, RES_FRAMEDIR );
+
+ sal_uInt16 nCount = GetPageDescCnt();
+ for( sal_uInt16 i=0; i<nCount; ++i )
+ {
+ SwPageDesc& rDesc = _GetPageDesc( i );
+ rDesc.GetMaster().SetFmtAttr( aFrameDir );
+ rDesc.GetLeft().SetFmtAttr( aFrameDir );
+ }
+
+ // #i18732# - restore static pool default for item
+ // RES_FOLLOW_TEXT_FLOW.
+ GetAttrPool().ResetPoolDefaultItem( RES_FOLLOW_TEXT_FLOW );
+
+ //#i16874# AutoKerning as default for new documents
+ GetAttrPool().ResetPoolDefaultItem( RES_CHRATR_AUTOKERN );
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/doc/sortopt.cxx b/sw/source/core/doc/sortopt.cxx
new file mode 100644
index 000000000000..eaee0fddd513
--- /dev/null
+++ b/sw/source/core/doc/sortopt.cxx
@@ -0,0 +1,96 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+
+#include <tools/debug.hxx>
+#include <i18npool/lang.h>
+#include <sortopt.hxx>
+
+SV_IMPL_PTRARR(SwSortKeys, SwSortKey*)
+
+/*--------------------------------------------------------------------
+ Beschreibung: Sortier-Schluessel
+ --------------------------------------------------------------------*/
+SwSortKey::SwSortKey() :
+ eSortOrder( SRT_ASCENDING ),
+ nColumnId( 0 ),
+ bIsNumeric( sal_True )
+{
+}
+
+SwSortKey::SwSortKey(sal_uInt16 nId, const String& rSrtType, SwSortOrder eOrder) :
+ sSortType( rSrtType ),
+ eSortOrder( eOrder ),
+ nColumnId( nId ),
+ bIsNumeric( 0 == rSrtType.Len() )
+{
+}
+
+SwSortKey::SwSortKey(const SwSortKey& rOld) :
+ sSortType( rOld.sSortType ),
+ eSortOrder( rOld.eSortOrder ),
+ nColumnId( rOld.nColumnId ),
+ bIsNumeric( rOld.bIsNumeric )
+{
+}
+
+/*--------------------------------------------------------------------
+ Beschreibung: Sortieroptionen fuers Sortieren
+ --------------------------------------------------------------------*/
+SwSortOptions::SwSortOptions()
+ : eDirection( SRT_ROWS ),
+ cDeli( 9 ),
+ nLanguage( LANGUAGE_SYSTEM ),
+ bTable( sal_False ),
+ bIgnoreCase( sal_False )
+{
+}
+
+SwSortOptions::SwSortOptions(const SwSortOptions& rOpt) :
+ eDirection( rOpt.eDirection ),
+ cDeli( rOpt.cDeli ),
+ nLanguage( rOpt.nLanguage ),
+ bTable( rOpt.bTable ),
+ bIgnoreCase( rOpt.bIgnoreCase )
+{
+ for( sal_uInt16 i=0; i < rOpt.aKeys.Count(); ++i )
+ {
+ SwSortKey* pNew = new SwSortKey(*rOpt.aKeys[i]);
+ aKeys.C40_INSERT( SwSortKey, pNew, aKeys.Count());
+ }
+}
+
+SwSortOptions::~SwSortOptions()
+{
+ aKeys.DeleteAndDestroy(0, aKeys.Count());
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/doc/swserv.cxx b/sw/source/core/doc/swserv.cxx
new file mode 100644
index 000000000000..7290240d1151
--- /dev/null
+++ b/sw/source/core/doc/swserv.cxx
@@ -0,0 +1,359 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+
+#include <sot/storage.hxx>
+#include <sfx2/linkmgr.hxx>
+#include <com/sun/star/uno/Sequence.h>
+#include <doc.hxx>
+#include <swtypes.hxx>
+#include <swserv.hxx>
+#include <swbaslnk.hxx>
+#include <mvsave.hxx>
+#include <IMark.hxx>
+#include <bookmrk.hxx>
+#include <pam.hxx>
+#include <shellio.hxx>
+#include <swerror.h>
+
+using namespace ::com::sun::star;
+
+SV_IMPL_REF( SwServerObject )
+
+SwServerObject::~SwServerObject()
+{
+}
+
+
+sal_Bool SwServerObject::GetData( uno::Any & rData,
+ const String & rMimeType, sal_Bool )
+{
+ sal_Bool bRet = sal_False;
+ WriterRef xWrt;
+ switch( SotExchange::GetFormatIdFromMimeType( rMimeType ) )
+ {
+ case FORMAT_STRING:
+ ::GetASCWriter( aEmptyStr, String(), xWrt );
+ break;
+
+ case FORMAT_RTF:
+ // mba: no BaseURL for data exchange
+ ::GetRTFWriter( aEmptyStr, String(), xWrt );
+ break;
+ }
+
+ if( xWrt.Is() )
+ {
+ SwPaM* pPam = 0;
+ switch( eType )
+ {
+ case BOOKMARK_SERVER:
+ if( CNTNT_TYPE.pBkmk->IsExpanded() )
+ {
+ // Bereich aufspannen
+ pPam = new SwPaM( CNTNT_TYPE.pBkmk->GetMarkPos(),
+ CNTNT_TYPE.pBkmk->GetOtherMarkPos() );
+ }
+ break;
+
+ case TABLE_SERVER:
+ pPam = new SwPaM( *CNTNT_TYPE.pTblNd,
+ *CNTNT_TYPE.pTblNd->EndOfSectionNode() );
+ break;
+
+ case SECTION_SERVER:
+ pPam = new SwPaM( SwPosition( *CNTNT_TYPE.pSectNd ) );
+ pPam->Move( fnMoveForward );
+ pPam->SetMark();
+ pPam->GetPoint()->nNode = *CNTNT_TYPE.pSectNd->EndOfSectionNode();
+ pPam->Move( fnMoveBackward );
+ break;
+ case NONE_SERVER: break;
+ }
+
+ if( pPam )
+ {
+ // Stream anlegen
+ SvMemoryStream aMemStm( 65535, 65535 );
+ SwWriter aWrt( aMemStm, *pPam, sal_False );
+ if( !IsError( aWrt.Write( xWrt )) )
+ {
+ aMemStm << '\0'; // append a zero char
+ rData <<= uno::Sequence< sal_Int8 >(
+ (sal_Int8*)aMemStm.GetData(),
+ aMemStm.Seek( STREAM_SEEK_TO_END ) );
+ bRet = sal_True;
+ }
+
+ delete pPam;
+ }
+ }
+ return bRet;
+}
+
+
+sal_Bool SwServerObject::SetData( const String & ,
+ const uno::Any& )
+{
+ // set new data into the "server" -> at first nothing to do
+ return sal_False;
+}
+
+
+void SwServerObject::SendDataChanged( const SwPosition& rPos )
+{
+ // ist an unseren Aenderungen jemand interessiert ?
+ if( HasDataLinks() )
+ {
+ int bCall = sal_False;
+ const SwStartNode* pNd = 0;
+ switch( eType )
+ {
+ case BOOKMARK_SERVER:
+ if( CNTNT_TYPE.pBkmk->IsExpanded() )
+ {
+ bCall = CNTNT_TYPE.pBkmk->GetMarkStart() <= rPos
+ && rPos < CNTNT_TYPE.pBkmk->GetMarkEnd();
+ }
+ break;
+
+ case TABLE_SERVER: pNd = CNTNT_TYPE.pTblNd; break;
+ case SECTION_SERVER: pNd = CNTNT_TYPE.pSectNd; break;
+ case NONE_SERVER: break;
+ }
+ if( pNd )
+ {
+ sal_uLong nNd = rPos.nNode.GetIndex();
+ bCall = pNd->GetIndex() < nNd && nNd < pNd->EndOfSectionIndex();
+ }
+
+ if( bCall )
+ {
+ // Recursionen erkennen und flaggen
+ IsLinkInServer( 0 );
+ SvLinkSource::NotifyDataChanged();
+ }
+ }
+}
+
+
+void SwServerObject::SendDataChanged( const SwPaM& rRange )
+{
+ // ist an unseren Aenderungen jemand interessiert ?
+ if( HasDataLinks() )
+ {
+ int bCall = sal_False;
+ const SwStartNode* pNd = 0;
+ const SwPosition* pStt = rRange.Start(), *pEnd = rRange.End();
+ switch( eType )
+ {
+ case BOOKMARK_SERVER:
+ if(CNTNT_TYPE.pBkmk->IsExpanded())
+ {
+ bCall = *pStt <= CNTNT_TYPE.pBkmk->GetMarkEnd()
+ && *pEnd > CNTNT_TYPE.pBkmk->GetMarkStart();
+ }
+ break;
+
+ case TABLE_SERVER: pNd = CNTNT_TYPE.pTblNd; break;
+ case SECTION_SERVER: pNd = CNTNT_TYPE.pSectNd; break;
+ case NONE_SERVER: break;
+ }
+ if( pNd )
+ {
+ // liegt der Start-Bereich im Node Bereich ?
+ bCall = pStt->nNode.GetIndex() < pNd->EndOfSectionIndex() &&
+ pEnd->nNode.GetIndex() >= pNd->GetIndex();
+ }
+
+ if( bCall )
+ {
+ // Recursionen erkennen und flaggen
+ IsLinkInServer( 0 );
+ SvLinkSource::NotifyDataChanged();
+ }
+ }
+}
+
+
+sal_Bool SwServerObject::IsLinkInServer( const SwBaseLink* pChkLnk ) const
+{
+ sal_uLong nSttNd = 0, nEndNd = 0;
+ xub_StrLen nStt = 0;
+ xub_StrLen nEnd = 0;
+ const SwNode* pNd = 0;
+ const SwNodes* pNds = 0;
+
+ switch( eType )
+ {
+ case BOOKMARK_SERVER:
+ if( CNTNT_TYPE.pBkmk->IsExpanded() )
+ {
+ const SwPosition* pStt = &CNTNT_TYPE.pBkmk->GetMarkStart(),
+ * pEnd = &CNTNT_TYPE.pBkmk->GetMarkEnd();
+
+ nSttNd = pStt->nNode.GetIndex();
+ nStt = pStt->nContent.GetIndex();
+ nEndNd = pEnd->nNode.GetIndex();
+ nEnd = pEnd->nContent.GetIndex();
+ pNds = &pStt->nNode.GetNodes();
+ }
+ break;
+
+ case TABLE_SERVER: pNd = CNTNT_TYPE.pTblNd; break;
+ case SECTION_SERVER: pNd = CNTNT_TYPE.pSectNd; break;
+
+ case SECTION_SERVER+1:
+ return sal_True;
+ }
+
+ if( pNd )
+ {
+ nSttNd = pNd->GetIndex();
+ nEndNd = pNd->EndOfSectionIndex();
+ nStt = 0, nEnd = USHRT_MAX;
+ pNds = &pNd->GetNodes();
+ }
+
+ if( nSttNd && nEndNd )
+ {
+ // LinkManager besorgen:
+ const ::sfx2::SvBaseLinks& rLnks = pNds->GetDoc()->GetLinkManager().GetLinks();
+
+// um Rekursionen zu Verhindern: ServerType umsetzen!
+SwServerObject::ServerModes eSave = eType;
+if( !pChkLnk )
+ ((SwServerObject*)this)->eType = NONE_SERVER;
+ for( sal_uInt16 n = rLnks.Count(); n; )
+ {
+ const ::sfx2::SvBaseLink* pLnk = &(*rLnks[ --n ]);
+ if( pLnk && OBJECT_CLIENT_GRF != pLnk->GetObjType() &&
+ pLnk->ISA( SwBaseLink ) &&
+ !((SwBaseLink*)pLnk)->IsNoDataFlag() &&
+ ((SwBaseLink*)pLnk)->IsInRange( nSttNd, nEndNd, nStt, nEnd ))
+ {
+ if( pChkLnk )
+ {
+ if( pLnk == pChkLnk ||
+ ((SwBaseLink*)pLnk)->IsRecursion( pChkLnk ) )
+ return sal_True;
+ }
+ else if( ((SwBaseLink*)pLnk)->IsRecursion( (SwBaseLink*)pLnk ) )
+ ((SwBaseLink*)pLnk)->SetNoDataFlag();
+ }
+ }
+if( !pChkLnk )
+ // *((int*)&eType) = eSave;
+ ((SwServerObject*)this)->eType = eSave;
+ }
+
+ return sal_False;
+}
+
+void SwServerObject::SetNoServer()
+{
+ if(eType == BOOKMARK_SERVER && CNTNT_TYPE.pBkmk)
+ {
+ ::sw::mark::DdeBookmark* const pDdeBookmark = dynamic_cast< ::sw::mark::DdeBookmark* >(CNTNT_TYPE.pBkmk);
+ if(pDdeBookmark)
+ {
+ CNTNT_TYPE.pBkmk = 0, eType = NONE_SERVER;
+ pDdeBookmark->SetRefObject(NULL);
+ }
+ }
+}
+
+void SwServerObject::SetDdeBookmark( ::sw::mark::IMark& rBookmark)
+{
+ ::sw::mark::DdeBookmark* const pDdeBookmark = dynamic_cast< ::sw::mark::DdeBookmark* >(&rBookmark);
+ if(pDdeBookmark)
+ {
+ eType = BOOKMARK_SERVER;
+ CNTNT_TYPE.pBkmk = &rBookmark;
+ pDdeBookmark->SetRefObject(this);
+ }
+ else
+ OSL_FAIL("SwServerObject::SetNoServer(..)"
+ " - setting an bookmark that is not DDE-capable");
+}
+
+/* */
+
+
+SwDataChanged::SwDataChanged( const SwPaM& rPam, sal_uInt16 nTyp )
+ : pPam( &rPam ), pPos( 0 ), pDoc( rPam.GetDoc() ), nType( nTyp )
+{
+ nNode = rPam.GetPoint()->nNode.GetIndex();
+ nCntnt = rPam.GetPoint()->nContent.GetIndex();
+}
+
+
+SwDataChanged::SwDataChanged( SwDoc* pDc, const SwPosition& rPos, sal_uInt16 nTyp )
+ : pPam( 0 ), pPos( &rPos ), pDoc( pDc ), nType( nTyp )
+{
+ nNode = rPos.nNode.GetIndex();
+ nCntnt = rPos.nContent.GetIndex();
+}
+
+SwDataChanged::~SwDataChanged()
+{
+ // JP 09.04.96: nur wenn das Layout vorhanden ist ( also waehrend der
+ // Eingabe)
+ if( pDoc->GetCurrentViewShell() ) //swmod 071108//swmod 071225
+ {
+ const ::sfx2::SvLinkSources& rServers = pDoc->GetLinkManager().GetServers();
+
+ for( sal_uInt16 nCnt = rServers.Count(); nCnt; )
+ {
+ ::sfx2::SvLinkSourceRef refObj( rServers[ --nCnt ] );
+ // noch jemand am Object interessiert ?
+ if( refObj->HasDataLinks() && refObj->ISA( SwServerObject ))
+ {
+ SwServerObject& rObj = *(SwServerObject*)&refObj;
+ if( pPos )
+ rObj.SendDataChanged( *pPos );
+ else
+ rObj.SendDataChanged( *pPam );
+ }
+
+ // sollte jetzt gar keine Verbindung mehr bestehen
+ if( !refObj->HasDataLinks() )
+ {
+ // dann raus aus der Liste (Object bleibt aber bestehen!)
+ // falls es noch da ist !!
+ if( nCnt < rServers.Count() && &refObj == rServers[ nCnt ] )
+ pDoc->GetLinkManager().RemoveServer( nCnt, 1 );
+ }
+ }
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/doc/swstylemanager.cxx b/sw/source/core/doc/swstylemanager.cxx
new file mode 100644
index 000000000000..5336acb92164
--- /dev/null
+++ b/sw/source/core/doc/swstylemanager.cxx
@@ -0,0 +1,172 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+
+#include "swstylemanager.hxx"
+#include <boost/unordered_map.hpp>
+#include <svl/stylepool.hxx>
+#include <doc.hxx>
+#include <charfmt.hxx>
+#include <docary.hxx>
+#include <swtypes.hxx>
+#include <istyleaccess.hxx>
+
+typedef ::boost::unordered_map< const ::rtl::OUString,
+ StylePool::SfxItemSet_Pointer_t,
+ ::rtl::OUStringHash,
+ ::std::equal_to< ::rtl::OUString > > SwStyleNameCache;
+
+class SwStyleCache
+{
+ SwStyleNameCache mMap;
+public:
+ SwStyleCache() {}
+ void addStyleName( StylePool::SfxItemSet_Pointer_t pStyle )
+ { mMap[ StylePool::nameOf(pStyle) ] = pStyle; }
+ void addCompletePool( StylePool& rPool );
+ StylePool::SfxItemSet_Pointer_t getByName( const rtl::OUString& rName ) { return mMap[rName]; }
+};
+
+void SwStyleCache::addCompletePool( StylePool& rPool )
+{
+ IStylePoolIteratorAccess *pIter = rPool.createIterator();
+ StylePool::SfxItemSet_Pointer_t pStyle = pIter->getNext();
+ while( pStyle.get() )
+ {
+ rtl::OUString aName( StylePool::nameOf(pStyle) );
+ mMap[ aName ] = pStyle;
+ pStyle = pIter->getNext();
+ }
+ delete pIter;
+}
+
+class SwStyleManager : public IStyleAccess
+{
+ StylePool aAutoCharPool;
+ StylePool aAutoParaPool;
+ SwStyleCache *mpCharCache;
+ SwStyleCache *mpParaCache;
+
+public:
+ // accept empty item set for ignorable paragraph items.
+ SwStyleManager( SfxItemSet* pIgnorableParagraphItems )
+ : aAutoCharPool(),
+ aAutoParaPool( pIgnorableParagraphItems ),
+ mpCharCache(0),
+ mpParaCache(0)
+ {}
+ virtual ~SwStyleManager();
+ virtual StylePool::SfxItemSet_Pointer_t getAutomaticStyle( const SfxItemSet& rSet,
+ IStyleAccess::SwAutoStyleFamily eFamily );
+ virtual StylePool::SfxItemSet_Pointer_t getByName( const rtl::OUString& rName,
+ IStyleAccess::SwAutoStyleFamily eFamily );
+ virtual void getAllStyles( std::vector<StylePool::SfxItemSet_Pointer_t> &rStyles,
+ IStyleAccess::SwAutoStyleFamily eFamily );
+ virtual StylePool::SfxItemSet_Pointer_t cacheAutomaticStyle( const SfxItemSet& rSet,
+ SwAutoStyleFamily eFamily );
+ virtual void clearCaches();
+};
+
+IStyleAccess *createStyleManager( SfxItemSet* pIgnorableParagraphItems )
+{
+ return new SwStyleManager( pIgnorableParagraphItems );
+}
+
+SwStyleManager::~SwStyleManager()
+{
+ delete mpCharCache;
+ delete mpParaCache;
+}
+
+void SwStyleManager::clearCaches()
+{
+ delete mpCharCache;
+ mpCharCache = 0;
+ delete mpParaCache;
+ mpParaCache = 0;
+}
+
+StylePool::SfxItemSet_Pointer_t SwStyleManager::getAutomaticStyle( const SfxItemSet& rSet,
+ IStyleAccess::SwAutoStyleFamily eFamily )
+{
+ StylePool& rAutoPool = eFamily == IStyleAccess::AUTO_STYLE_CHAR ? aAutoCharPool : aAutoParaPool;
+ return rAutoPool.insertItemSet( rSet );
+}
+
+StylePool::SfxItemSet_Pointer_t SwStyleManager::cacheAutomaticStyle( const SfxItemSet& rSet,
+ IStyleAccess::SwAutoStyleFamily eFamily )
+{
+ StylePool& rAutoPool = eFamily == IStyleAccess::AUTO_STYLE_CHAR ? aAutoCharPool : aAutoParaPool;
+ StylePool::SfxItemSet_Pointer_t pStyle = rAutoPool.insertItemSet( rSet );
+ SwStyleCache* &rpCache = eFamily == IStyleAccess::AUTO_STYLE_CHAR ?
+ mpCharCache : mpParaCache;
+ if( !rpCache )
+ rpCache = new SwStyleCache();
+ rpCache->addStyleName( pStyle );
+ return pStyle;
+}
+
+StylePool::SfxItemSet_Pointer_t SwStyleManager::getByName( const rtl::OUString& rName,
+ IStyleAccess::SwAutoStyleFamily eFamily )
+{
+ StylePool& rAutoPool = eFamily == IStyleAccess::AUTO_STYLE_CHAR ? aAutoCharPool : aAutoParaPool;
+ SwStyleCache* &rpCache = eFamily == IStyleAccess::AUTO_STYLE_CHAR ? mpCharCache : mpParaCache;
+ if( !rpCache )
+ rpCache = new SwStyleCache();
+ StylePool::SfxItemSet_Pointer_t pStyle = rpCache->getByName( rName );
+ if( !pStyle.get() )
+ {
+ // Ok, ok, it's allowed to ask for uncached styles (from UNO) but it should not be done
+ // during loading a document
+ OSL_FAIL( "Don't ask for uncached styles" );
+ rpCache->addCompletePool( rAutoPool );
+ pStyle = rpCache->getByName( rName );
+ }
+ return pStyle;
+}
+
+void SwStyleManager::getAllStyles( std::vector<StylePool::SfxItemSet_Pointer_t> &rStyles,
+ IStyleAccess::SwAutoStyleFamily eFamily )
+{
+ StylePool& rAutoPool = eFamily == IStyleAccess::AUTO_STYLE_CHAR ? aAutoCharPool : aAutoParaPool;
+ // setup <StylePool> iterator, which skips unused styles and ignorable items
+ IStylePoolIteratorAccess *pIter = rAutoPool.createIterator( true, true );
+ StylePool::SfxItemSet_Pointer_t pStyle = pIter->getNext();
+ while( pStyle.get() )
+ {
+ rStyles.push_back( pStyle );
+
+ pStyle = pIter->getNext();
+ }
+ delete pIter;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/doc/swstylemanager.hxx b/sw/source/core/doc/swstylemanager.hxx
new file mode 100644
index 000000000000..486d751ba8d1
--- /dev/null
+++ b/sw/source/core/doc/swstylemanager.hxx
@@ -0,0 +1,37 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+#ifndef _SWSTYLEMANAGER_HXX
+#define _SWSTYLEMANAGER_HXX
+
+class IStyleAccess;
+class SfxItemSet;
+
+IStyleAccess *createStyleManager( SfxItemSet* pIgnorableParagraphItems = 0 );
+#endif //_SWSTYLEMANAGER_HXX
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/doc/tblafmt.cxx b/sw/source/core/doc/tblafmt.cxx
new file mode 100644
index 000000000000..69da092a312c
--- /dev/null
+++ b/sw/source/core/doc/tblafmt.cxx
@@ -0,0 +1,1106 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+
+#include <tools/resid.hxx>
+#include <tools/stream.hxx>
+#include <tools/shl.hxx>
+#include <vcl/svapp.hxx>
+#include <sfx2/docfile.hxx>
+#include <svl/urihelper.hxx>
+#include <svl/zforlist.hxx>
+#include <svl/zformat.hxx>
+#include <unotools/pathoptions.hxx>
+#include <sfx2/app.hxx>
+#include <svx/dialmgr.hxx>
+#include <svx/dialogs.hrc>
+
+#define READ_OLDVERS // erstmal noch alte Versionen lesen
+#include <swtypes.hxx>
+#include <doc.hxx>
+#include <poolfmt.hxx>
+#include <tblafmt.hxx>
+#include <cellatr.hxx>
+#include <SwStyleNameMapper.hxx>
+
+using ::editeng::SvxBorderLine;
+
+// bis SO5PF
+const sal_uInt16 AUTOFORMAT_ID_X = 9501;
+const sal_uInt16 AUTOFORMAT_ID_358 = 9601;
+const sal_uInt16 AUTOFORMAT_DATA_ID_X = 9502;
+
+// ab SO5
+//! in nachfolgenden Versionen muss der Betrag dieser IDs groesser sein
+const sal_uInt16 AUTOFORMAT_ID_504 = 9801;
+const sal_uInt16 AUTOFORMAT_DATA_ID_504 = 9802;
+
+const sal_uInt16 AUTOFORMAT_ID_552 = 9901;
+const sal_uInt16 AUTOFORMAT_DATA_ID_552 = 9902;
+
+// --- from 641 on: CJK and CTL font settings
+const sal_uInt16 AUTOFORMAT_ID_641 = 10001;
+const sal_uInt16 AUTOFORMAT_DATA_ID_641 = 10002;
+
+// --- from 680/dr14 on: diagonal frame lines
+const sal_uInt16 AUTOFORMAT_ID_680DR14 = 10011;
+const sal_uInt16 AUTOFORMAT_DATA_ID_680DR14 = 10012;
+
+// --- from 680/dr25 on: store strings as UTF-8
+const sal_uInt16 AUTOFORMAT_ID_680DR25 = 10021;
+const sal_uInt16 AUTOFORMAT_DATA_ID_680DR25 = 10022;
+
+// --- from DEV300/overline2 on: overline
+const sal_uInt16 AUTOFORMAT_ID_300OVRLN = 10031;
+const sal_uInt16 AUTOFORMAT_DATA_ID_300OVRLN = 10032;
+
+// current version
+const sal_uInt16 AUTOFORMAT_ID = AUTOFORMAT_ID_300OVRLN;
+const sal_uInt16 AUTOFORMAT_DATA_ID = AUTOFORMAT_DATA_ID_300OVRLN;
+
+
+#ifdef READ_OLDVERS
+const sal_uInt16 AUTOFORMAT_OLD_ID = 8201;
+const sal_uInt16 AUTOFORMAT_OLD_ID1 = 8301;
+const sal_uInt16 AUTOFORMAT_OLD_DATA_ID = 8202;
+#endif
+
+
+SwBoxAutoFmt* SwTableAutoFmt::pDfltBoxAutoFmt = 0;
+
+#define sAutoTblFmtName "autotbl.fmt"
+
+// SwTable Auto-Format-Tabelle
+SV_IMPL_PTRARR( _SwTableAutoFmtTbl, SwTableAutoFmt* )
+
+
+// Struct mit Versionsnummern der Items
+
+struct SwAfVersions
+{
+public:
+ sal_uInt16 nFontVersion;
+ sal_uInt16 nFontHeightVersion;
+ sal_uInt16 nWeightVersion;
+ sal_uInt16 nPostureVersion;
+ sal_uInt16 nUnderlineVersion;
+ sal_uInt16 nOverlineVersion;
+ sal_uInt16 nCrossedOutVersion;
+ sal_uInt16 nContourVersion;
+ sal_uInt16 nShadowedVersion;
+ sal_uInt16 nColorVersion;
+ sal_uInt16 nBoxVersion;
+ sal_uInt16 nLineVersion;
+ sal_uInt16 nBrushVersion;
+
+ sal_uInt16 nAdjustVersion;
+
+ sal_uInt16 nHorJustifyVersion;
+ sal_uInt16 nVerJustifyVersion;
+ sal_uInt16 nOrientationVersion;
+ sal_uInt16 nMarginVersion;
+ sal_uInt16 nBoolVersion;
+ sal_uInt16 nInt32Version;
+ sal_uInt16 nRotateModeVersion;
+
+ sal_uInt16 nNumFmtVersion;
+
+ SwAfVersions();
+ void Load( SvStream& rStream, sal_uInt16 nVer );
+};
+
+SwAfVersions::SwAfVersions() :
+ nFontVersion(0),
+ nFontHeightVersion(0),
+ nWeightVersion(0),
+ nPostureVersion(0),
+ nUnderlineVersion(0),
+ nOverlineVersion(0),
+ nCrossedOutVersion(0),
+ nContourVersion(0),
+ nShadowedVersion(0),
+ nColorVersion(0),
+ nBoxVersion(0),
+ nLineVersion(0),
+ nBrushVersion(0),
+ nAdjustVersion(0),
+ nHorJustifyVersion(0),
+ nVerJustifyVersion(0),
+ nOrientationVersion(0),
+ nMarginVersion(0),
+ nBoolVersion(0),
+ nInt32Version(0),
+ nRotateModeVersion(0),
+ nNumFmtVersion(0)
+{
+}
+
+void SwAfVersions::Load( SvStream& rStream, sal_uInt16 nVer )
+{
+ rStream >> nFontVersion;
+ rStream >> nFontHeightVersion;
+ rStream >> nWeightVersion;
+ rStream >> nPostureVersion;
+ rStream >> nUnderlineVersion;
+ if ( nVer >= AUTOFORMAT_ID_300OVRLN )
+ rStream >> nOverlineVersion;
+ rStream >> nCrossedOutVersion;
+ rStream >> nContourVersion;
+ rStream >> nShadowedVersion;
+ rStream >> nColorVersion;
+ rStream >> nBoxVersion;
+ if ( nVer >= AUTOFORMAT_ID_680DR14 )
+ rStream >> nLineVersion;
+ rStream >> nBrushVersion;
+ rStream >> nAdjustVersion;
+ rStream >> nHorJustifyVersion;
+ rStream >> nVerJustifyVersion;
+ rStream >> nOrientationVersion;
+ rStream >> nMarginVersion;
+ rStream >> nBoolVersion;
+ if ( nVer >= AUTOFORMAT_ID_504 )
+ {
+ rStream >> nInt32Version;
+ rStream >> nRotateModeVersion;
+ }
+ rStream >> nNumFmtVersion;
+}
+
+// ---------------------------------------------------------------------------
+
+SwBoxAutoFmt::SwBoxAutoFmt()
+ : aFont( *(SvxFontItem*)GetDfltAttr( RES_CHRATR_FONT ) ),
+ aHeight( 240, 100, RES_CHRATR_FONTSIZE ),
+ aWeight( WEIGHT_NORMAL, RES_CHRATR_WEIGHT ),
+ aPosture( ITALIC_NONE, RES_CHRATR_POSTURE ),
+
+ aCJKFont( *(SvxFontItem*)GetDfltAttr( RES_CHRATR_CJK_FONT ) ),
+ aCJKHeight( 240, 100, RES_CHRATR_CJK_FONTSIZE ),
+ aCJKWeight( WEIGHT_NORMAL, RES_CHRATR_CJK_WEIGHT ),
+ aCJKPosture( ITALIC_NONE, RES_CHRATR_CJK_POSTURE ),
+
+ aCTLFont( *(SvxFontItem*)GetDfltAttr( RES_CHRATR_CTL_FONT ) ),
+ aCTLHeight( 240, 100, RES_CHRATR_CTL_FONTSIZE ),
+ aCTLWeight( WEIGHT_NORMAL, RES_CHRATR_CTL_WEIGHT ),
+ aCTLPosture( ITALIC_NONE, RES_CHRATR_CTL_POSTURE ),
+
+ aUnderline( UNDERLINE_NONE, RES_CHRATR_UNDERLINE ),
+ aOverline( UNDERLINE_NONE, RES_CHRATR_OVERLINE ),
+ aCrossedOut( STRIKEOUT_NONE, RES_CHRATR_CROSSEDOUT ),
+ aContour( sal_False, RES_CHRATR_CONTOUR ),
+ aShadowed( sal_False, RES_CHRATR_SHADOWED ),
+ aColor( RES_CHRATR_COLOR ),
+ aBox( RES_BOX ),
+ aTLBR( 0 ),
+ aBLTR( 0 ),
+ aBackground( RES_BACKGROUND ),
+ aAdjust( SVX_ADJUST_LEFT, RES_PARATR_ADJUST ),
+ aHorJustify( SVX_HOR_JUSTIFY_STANDARD, 0),
+ aVerJustify( SVX_VER_JUSTIFY_STANDARD, 0),
+ aStacked( 0 ),
+ aMargin( 0 ),
+ aLinebreak( 0 ),
+ aRotateAngle( 0 ),
+
+// FIXME - add attribute IDs for the diagonal line items
+// aTLBR( RES_... ),
+// aBLTR( RES_... ),
+ aRotateMode( SVX_ROTATE_MODE_STANDARD, 0 )
+{
+ eSysLanguage = eNumFmtLanguage = static_cast<LanguageType>(::GetAppLanguage());
+ aBox.SetDistance( 55 );
+}
+
+
+SwBoxAutoFmt::SwBoxAutoFmt( const SwBoxAutoFmt& rNew )
+ : aFont( rNew.aFont ),
+ aHeight( rNew.aHeight ),
+ aWeight( rNew.aWeight ),
+ aPosture( rNew.aPosture ),
+ aCJKFont( rNew.aCJKFont ),
+ aCJKHeight( rNew.aCJKHeight ),
+ aCJKWeight( rNew.aCJKWeight ),
+ aCJKPosture( rNew.aCJKPosture ),
+ aCTLFont( rNew.aCTLFont ),
+ aCTLHeight( rNew.aCTLHeight ),
+ aCTLWeight( rNew.aCTLWeight ),
+ aCTLPosture( rNew.aCTLPosture ),
+ aUnderline( rNew.aUnderline ),
+ aOverline( rNew.aOverline ),
+ aCrossedOut( rNew.aCrossedOut ),
+ aContour( rNew.aContour ),
+ aShadowed( rNew.aShadowed ),
+ aColor( rNew.aColor ),
+ aBox( rNew.aBox ),
+ aTLBR( rNew.aTLBR ),
+ aBLTR( rNew.aBLTR ),
+ aBackground( rNew.aBackground ),
+ aAdjust( rNew.aAdjust ),
+ aHorJustify( rNew.aHorJustify ),
+ aVerJustify( rNew.aVerJustify ),
+ aStacked( rNew.aStacked ),
+ aMargin( rNew.aMargin ),
+ aLinebreak( rNew.aLinebreak ),
+ aRotateAngle( rNew.aRotateAngle ),
+ aRotateMode( rNew.aRotateMode ),
+ sNumFmtString( rNew.sNumFmtString ),
+ eSysLanguage( rNew.eSysLanguage ),
+ eNumFmtLanguage( rNew.eNumFmtLanguage )
+{
+}
+
+
+SwBoxAutoFmt::~SwBoxAutoFmt()
+{
+}
+
+SwBoxAutoFmt& SwBoxAutoFmt::operator=( const SwBoxAutoFmt& rNew )
+{
+ aFont = rNew.aFont;
+ aHeight = rNew.aHeight;
+ aWeight = rNew.aWeight;
+ aPosture = rNew.aPosture;
+ aCJKFont = rNew.aCJKFont;
+ aCJKHeight = rNew.aCJKHeight;
+ aCJKWeight = rNew.aCJKWeight;
+ aCJKPosture = rNew.aCJKPosture;
+ aCTLFont = rNew.aCTLFont;
+ aCTLHeight = rNew.aCTLHeight;
+ aCTLWeight = rNew.aCTLWeight;
+ aCTLPosture = rNew.aCTLPosture;
+ aUnderline = rNew.aUnderline;
+ aOverline = rNew.aOverline;
+ aCrossedOut = rNew.aCrossedOut;
+ aContour = rNew.aContour;
+ aShadowed = rNew.aShadowed;
+ aColor = rNew.aColor;
+ SetAdjust( rNew.aAdjust );
+ aBox = rNew.aBox;
+ aTLBR = rNew.aTLBR;
+ aBLTR = rNew.aBLTR;
+ aBackground = rNew.aBackground;
+
+ aHorJustify = rNew.aHorJustify;
+ aVerJustify = rNew.aVerJustify;
+ aStacked.SetValue( rNew.aStacked.GetValue() );
+ aMargin = rNew.aMargin;
+ aLinebreak.SetValue( rNew.aLinebreak.GetValue() );
+ aRotateAngle.SetValue( rNew.aRotateAngle.GetValue() );
+ aRotateMode.SetValue( rNew.aRotateMode.GetValue() );
+
+ sNumFmtString = rNew.sNumFmtString;
+ eSysLanguage = rNew.eSysLanguage;
+ eNumFmtLanguage = rNew.eNumFmtLanguage;
+
+ return *this;
+}
+
+
+#define READ( aItem, aItemType, nVers )\
+ pNew = aItem.Create(rStream, nVers ); \
+ aItem = *(aItemType*)pNew; \
+ delete pNew;
+
+sal_Bool SwBoxAutoFmt::Load( SvStream& rStream, const SwAfVersions& rVersions, sal_uInt16 nVer )
+{
+ SfxPoolItem* pNew;
+ SvxOrientationItem aOrientation( SVX_ORIENTATION_STANDARD, 0);
+
+ READ( aFont, SvxFontItem , rVersions.nFontVersion)
+
+ if( rStream.GetStreamCharSet() == aFont.GetCharSet() )
+ aFont.SetCharSet(::gsl_getSystemTextEncoding());
+
+ READ( aHeight, SvxFontHeightItem , rVersions.nFontHeightVersion)
+ READ( aWeight, SvxWeightItem , rVersions.nWeightVersion)
+ READ( aPosture, SvxPostureItem , rVersions.nPostureVersion)
+ // --- from 641 on: CJK and CTL font settings
+ if( AUTOFORMAT_DATA_ID_641 <= nVer )
+ {
+ READ( aCJKFont, SvxFontItem , rVersions.nFontVersion)
+ READ( aCJKHeight, SvxFontHeightItem , rVersions.nFontHeightVersion)
+ READ( aCJKWeight, SvxWeightItem , rVersions.nWeightVersion)
+ READ( aCJKPosture, SvxPostureItem , rVersions.nPostureVersion)
+ READ( aCTLFont, SvxFontItem , rVersions.nFontVersion)
+ READ( aCTLHeight, SvxFontHeightItem , rVersions.nFontHeightVersion)
+ READ( aCTLWeight, SvxWeightItem , rVersions.nWeightVersion)
+ READ( aCTLPosture, SvxPostureItem , rVersions.nPostureVersion)
+ }
+ READ( aUnderline, SvxUnderlineItem , rVersions.nUnderlineVersion)
+ if( nVer >= AUTOFORMAT_DATA_ID_300OVRLN )
+ {
+ READ( aOverline, SvxOverlineItem , rVersions.nOverlineVersion)
+ }
+ READ( aCrossedOut, SvxCrossedOutItem , rVersions.nCrossedOutVersion)
+ READ( aContour, SvxContourItem , rVersions.nContourVersion)
+ READ( aShadowed, SvxShadowedItem , rVersions.nShadowedVersion)
+ READ( aColor, SvxColorItem , rVersions.nColorVersion)
+
+ READ( aBox, SvxBoxItem , rVersions.nBoxVersion)
+
+ // --- from 680/dr14 on: diagonal frame lines
+ if( nVer >= AUTOFORMAT_DATA_ID_680DR14 )
+ {
+ READ( aTLBR, SvxLineItem, rVersions.nLineVersion)
+ READ( aBLTR, SvxLineItem, rVersions.nLineVersion)
+ }
+
+ READ( aBackground, SvxBrushItem , rVersions.nBrushVersion)
+
+ pNew = aAdjust.Create(rStream, rVersions.nAdjustVersion );
+ SetAdjust( *(SvxAdjustItem*)pNew );
+ delete pNew;
+
+ READ( aHorJustify, SvxHorJustifyItem , rVersions.nHorJustifyVersion)
+ READ( aVerJustify, SvxVerJustifyItem , rVersions.nVerJustifyVersion)
+ READ( aOrientation, SvxOrientationItem , rVersions.nOrientationVersion)
+ READ( aMargin, SvxMarginItem , rVersions.nMarginVersion)
+
+ pNew = aLinebreak.Create(rStream, rVersions.nBoolVersion );
+ aLinebreak.SetValue( ((SfxBoolItem*)pNew)->GetValue() );
+ delete pNew;
+
+ if ( nVer >= AUTOFORMAT_DATA_ID_504 )
+ {
+ pNew = aRotateAngle.Create( rStream, rVersions.nInt32Version );
+ aRotateAngle.SetValue( ((SfxInt32Item*)pNew)->GetValue() );
+ delete pNew;
+ pNew = aRotateMode.Create( rStream, rVersions.nRotateModeVersion );
+ aRotateMode.SetValue( ((SvxRotateModeItem*)pNew)->GetValue() );
+ delete pNew;
+ }
+
+ if( 0 == rVersions.nNumFmtVersion )
+ {
+ sal_uInt16 eSys, eLge;
+ // --- from 680/dr25 on: store strings as UTF-8
+ CharSet eCharSet = (nVer >= AUTOFORMAT_ID_680DR25) ? RTL_TEXTENCODING_UTF8 : rStream.GetStreamCharSet();
+ rStream.ReadByteString( sNumFmtString, eCharSet )
+ >> eSys >> eLge;
+ eSysLanguage = (LanguageType) eSys;
+ eNumFmtLanguage = (LanguageType) eLge;
+ if ( eSysLanguage == LANGUAGE_SYSTEM ) // von alten Versionen (Calc)
+ eSysLanguage = static_cast<LanguageType>(::GetAppLanguage());
+ }
+
+ aStacked.SetValue( aOrientation.IsStacked() );
+ aRotateAngle.SetValue( aOrientation.GetRotation( aRotateAngle.GetValue() ) );
+
+ return 0 == rStream.GetError();
+}
+
+#ifdef READ_OLDVERS
+
+sal_Bool SwBoxAutoFmt::LoadOld( SvStream& rStream, sal_uInt16 aLoadVer[] )
+{
+ SfxPoolItem* pNew;
+ READ( aFont, SvxFontItem , 0)
+
+ if( rStream.GetStreamCharSet() == aFont.GetCharSet() )
+ aFont.SetCharSet(::gsl_getSystemTextEncoding());
+
+ READ( aHeight, SvxFontHeightItem , 1)
+ READ( aWeight, SvxWeightItem , 2)
+ READ( aPosture, SvxPostureItem , 3)
+ READ( aUnderline, SvxUnderlineItem , 4)
+ READ( aCrossedOut, SvxCrossedOutItem , 5)
+ READ( aContour, SvxContourItem , 6)
+ READ( aShadowed, SvxShadowedItem , 7)
+ READ( aColor, SvxColorItem , 8)
+
+ pNew = aAdjust.Create(rStream, aLoadVer[ 9 ] );
+ SetAdjust( *(SvxAdjustItem*)pNew );
+ delete pNew;
+
+ READ( aBox, SvxBoxItem , 10)
+ READ( aBackground, SvxBrushItem , 11)
+
+ return 0 == rStream.GetError();
+}
+
+#endif
+
+
+sal_Bool SwBoxAutoFmt::Save( SvStream& rStream ) const
+{
+ SvxOrientationItem aOrientation( aRotateAngle.GetValue(), aStacked.GetValue(), 0 );
+
+ aFont.Store( rStream, aFont.GetVersion(SOFFICE_FILEFORMAT_40) );
+ aHeight.Store( rStream, aHeight.GetVersion(SOFFICE_FILEFORMAT_40) );
+ aWeight.Store( rStream, aWeight.GetVersion(SOFFICE_FILEFORMAT_40) );
+ aPosture.Store( rStream, aPosture.GetVersion(SOFFICE_FILEFORMAT_40) );
+ aCJKFont.Store( rStream, aCJKFont.GetVersion(SOFFICE_FILEFORMAT_40) );
+ aCJKHeight.Store( rStream, aCJKHeight.GetVersion(SOFFICE_FILEFORMAT_40) );
+ aCJKWeight.Store( rStream, aCJKWeight.GetVersion(SOFFICE_FILEFORMAT_40) );
+ aCJKPosture.Store( rStream, aCJKPosture.GetVersion(SOFFICE_FILEFORMAT_40) );
+ aCTLFont.Store( rStream, aCTLFont.GetVersion(SOFFICE_FILEFORMAT_40) );
+ aCTLHeight.Store( rStream, aCTLHeight.GetVersion(SOFFICE_FILEFORMAT_40) );
+ aCTLWeight.Store( rStream, aCTLWeight.GetVersion(SOFFICE_FILEFORMAT_40) );
+ aCTLPosture.Store( rStream, aCTLPosture.GetVersion(SOFFICE_FILEFORMAT_40) );
+ aUnderline.Store( rStream, aUnderline.GetVersion(SOFFICE_FILEFORMAT_40) );
+ aOverline.Store( rStream, aOverline.GetVersion(SOFFICE_FILEFORMAT_40) );
+ aCrossedOut.Store( rStream, aCrossedOut.GetVersion(SOFFICE_FILEFORMAT_40) );
+ aContour.Store( rStream, aContour.GetVersion(SOFFICE_FILEFORMAT_40) );
+ aShadowed.Store( rStream, aShadowed.GetVersion(SOFFICE_FILEFORMAT_40) );
+ aColor.Store( rStream, aColor.GetVersion(SOFFICE_FILEFORMAT_40) );
+ aBox.Store( rStream, aBox.GetVersion(SOFFICE_FILEFORMAT_40) );
+ aTLBR.Store( rStream, aTLBR.GetVersion(SOFFICE_FILEFORMAT_40) );
+ aBLTR.Store( rStream, aBLTR.GetVersion(SOFFICE_FILEFORMAT_40) );
+ aBackground.Store( rStream, aBackground.GetVersion(SOFFICE_FILEFORMAT_40) );
+
+ aAdjust.Store( rStream, aAdjust.GetVersion(SOFFICE_FILEFORMAT_40) );
+
+ aHorJustify.Store( rStream, aHorJustify.GetVersion(SOFFICE_FILEFORMAT_40) );
+ aVerJustify.Store( rStream, aVerJustify.GetVersion(SOFFICE_FILEFORMAT_40) );
+ aOrientation.Store( rStream, aOrientation.GetVersion(SOFFICE_FILEFORMAT_40) );
+ aMargin.Store( rStream, aMargin.GetVersion(SOFFICE_FILEFORMAT_40) );
+ aLinebreak.Store( rStream, aLinebreak.GetVersion(SOFFICE_FILEFORMAT_40) );
+ // Calc Rotation ab SO5
+ aRotateAngle.Store( rStream, aRotateAngle.GetVersion(SOFFICE_FILEFORMAT_40) );
+ aRotateMode.Store( rStream, aRotateMode.GetVersion(SOFFICE_FILEFORMAT_40) );
+
+ // --- from 680/dr25 on: store strings as UTF-8
+ rStream.WriteByteString( sNumFmtString, RTL_TEXTENCODING_UTF8 )
+ << (sal_uInt16)eSysLanguage << (sal_uInt16)eNumFmtLanguage;
+
+ return 0 == rStream.GetError();
+}
+
+
+sal_Bool SwBoxAutoFmt::SaveVerionNo( SvStream& rStream ) const
+{
+ rStream << aFont.GetVersion( SOFFICE_FILEFORMAT_40 );
+ rStream << aHeight.GetVersion( SOFFICE_FILEFORMAT_40 );
+ rStream << aWeight.GetVersion( SOFFICE_FILEFORMAT_40 );
+ rStream << aPosture.GetVersion( SOFFICE_FILEFORMAT_40 );
+ rStream << aUnderline.GetVersion( SOFFICE_FILEFORMAT_40 );
+ rStream << aOverline.GetVersion( SOFFICE_FILEFORMAT_40 );
+ rStream << aCrossedOut.GetVersion( SOFFICE_FILEFORMAT_40 );
+ rStream << aContour.GetVersion( SOFFICE_FILEFORMAT_40 );
+ rStream << aShadowed.GetVersion( SOFFICE_FILEFORMAT_40 );
+ rStream << aColor.GetVersion( SOFFICE_FILEFORMAT_40 );
+ rStream << aBox.GetVersion( SOFFICE_FILEFORMAT_40 );
+ rStream << aTLBR.GetVersion( SOFFICE_FILEFORMAT_40 );
+ rStream << aBackground.GetVersion( SOFFICE_FILEFORMAT_40 );
+
+ rStream << aAdjust.GetVersion( SOFFICE_FILEFORMAT_40 );
+
+ rStream << aHorJustify.GetVersion( SOFFICE_FILEFORMAT_40 );
+ rStream << aVerJustify.GetVersion( SOFFICE_FILEFORMAT_40 );
+ rStream << SvxOrientationItem(SVX_ORIENTATION_STANDARD, 0).GetVersion( SOFFICE_FILEFORMAT_40 );
+ rStream << aMargin.GetVersion( SOFFICE_FILEFORMAT_40 );
+ rStream << aLinebreak.GetVersion( SOFFICE_FILEFORMAT_40 );
+ rStream << aRotateAngle.GetVersion( SOFFICE_FILEFORMAT_40 );
+ rStream << aRotateMode.GetVersion( SOFFICE_FILEFORMAT_40 );
+
+ rStream << (sal_uInt16)0; // NumberFormat
+
+ return 0 == rStream.GetError();
+}
+
+/* */
+
+
+SwTableAutoFmt::SwTableAutoFmt( const String& rName )
+ : aName( rName ), nStrResId( USHRT_MAX )
+{
+ bInclFont = sal_True;
+ bInclJustify = sal_True;
+ bInclFrame = sal_True;
+ bInclBackground = sal_True;
+ bInclValueFormat = sal_True;
+ bInclWidthHeight = sal_True;
+
+ memset( aBoxAutoFmt, 0, sizeof( aBoxAutoFmt ) );
+}
+
+
+SwTableAutoFmt::SwTableAutoFmt( const SwTableAutoFmt& rNew )
+{
+ for( sal_uInt8 n = 0; n < 16; ++n )
+ aBoxAutoFmt[ n ] = 0;
+ *this = rNew;
+}
+
+SwTableAutoFmt& SwTableAutoFmt::operator=( const SwTableAutoFmt& rNew )
+{
+ for( sal_uInt8 n = 0; n < 16; ++n )
+ {
+ if( aBoxAutoFmt[ n ] )
+ delete aBoxAutoFmt[ n ];
+
+ SwBoxAutoFmt* pFmt = rNew.aBoxAutoFmt[ n ];
+ if( pFmt ) // ist gesetzt -> kopieren
+ aBoxAutoFmt[ n ] = new SwBoxAutoFmt( *pFmt );
+ else // sonst default
+ aBoxAutoFmt[ n ] = 0;
+ }
+
+ aName = rNew.aName;
+ nStrResId = rNew.nStrResId;
+ bInclFont = rNew.bInclFont;
+ bInclJustify = rNew.bInclJustify;
+ bInclFrame = rNew.bInclFrame;
+ bInclBackground = rNew.bInclBackground;
+ bInclValueFormat = rNew.bInclValueFormat;
+ bInclWidthHeight = rNew.bInclWidthHeight;
+
+ return *this;
+}
+
+
+SwTableAutoFmt::~SwTableAutoFmt()
+{
+ SwBoxAutoFmt** ppFmt = aBoxAutoFmt;
+ for( sal_uInt8 n = 0; n < 16; ++n, ++ppFmt )
+ if( *ppFmt )
+ delete *ppFmt;
+}
+
+
+void SwTableAutoFmt::SetBoxFmt( const SwBoxAutoFmt& rNew, sal_uInt8 nPos )
+{
+ OSL_ENSURE( nPos < 16, "falscher Bereich" );
+
+ SwBoxAutoFmt* pFmt = aBoxAutoFmt[ nPos ];
+ if( pFmt ) // ist gesetzt -> kopieren
+ *aBoxAutoFmt[ nPos ] = rNew;
+ else // sonst neu setzen
+ aBoxAutoFmt[ nPos ] = new SwBoxAutoFmt( rNew );
+}
+
+
+const SwBoxAutoFmt& SwTableAutoFmt::GetBoxFmt( sal_uInt8 nPos ) const
+{
+ OSL_ENSURE( nPos < 16, "falscher Bereich" );
+
+ SwBoxAutoFmt* pFmt = aBoxAutoFmt[ nPos ];
+ if( pFmt ) // ist gesetzt -> kopieren
+ return *pFmt;
+ else // sonst den default returnen
+ {
+ // falls noch nicht vorhanden:
+ if( !pDfltBoxAutoFmt )
+ pDfltBoxAutoFmt = new SwBoxAutoFmt;
+ return *pDfltBoxAutoFmt;
+ }
+}
+
+
+
+SwBoxAutoFmt& SwTableAutoFmt::UpdateFromSet( sal_uInt8 nPos,
+ const SfxItemSet& rSet,
+ UpdateFlags eFlags,
+ SvNumberFormatter* pNFmtr )
+{
+ OSL_ENSURE( nPos < 16, "falscher Bereich" );
+
+ SwBoxAutoFmt* pFmt = aBoxAutoFmt[ nPos ];
+ if( !pFmt ) // ist gesetzt -> kopieren
+ {
+ pFmt = new SwBoxAutoFmt;
+ aBoxAutoFmt[ nPos ] = pFmt;
+ }
+
+ if( UPDATE_CHAR & eFlags )
+ {
+ pFmt->SetFont( (SvxFontItem&)rSet.Get( RES_CHRATR_FONT ) );
+ pFmt->SetHeight( (SvxFontHeightItem&)rSet.Get( RES_CHRATR_FONTSIZE ) );
+ pFmt->SetWeight( (SvxWeightItem&)rSet.Get( RES_CHRATR_WEIGHT ) );
+ pFmt->SetPosture( (SvxPostureItem&)rSet.Get( RES_CHRATR_POSTURE ) );
+ pFmt->SetCJKFont( (SvxFontItem&)rSet.Get( RES_CHRATR_CJK_FONT ) );
+ pFmt->SetCJKHeight( (SvxFontHeightItem&)rSet.Get( RES_CHRATR_CJK_FONTSIZE ) );
+ pFmt->SetCJKWeight( (SvxWeightItem&)rSet.Get( RES_CHRATR_CJK_WEIGHT ) );
+ pFmt->SetCJKPosture( (SvxPostureItem&)rSet.Get( RES_CHRATR_CJK_POSTURE ) );
+ pFmt->SetCTLFont( (SvxFontItem&)rSet.Get( RES_CHRATR_CTL_FONT ) );
+ pFmt->SetCTLHeight( (SvxFontHeightItem&)rSet.Get( RES_CHRATR_CTL_FONTSIZE ) );
+ pFmt->SetCTLWeight( (SvxWeightItem&)rSet.Get( RES_CHRATR_CTL_WEIGHT ) );
+ pFmt->SetCTLPosture( (SvxPostureItem&)rSet.Get( RES_CHRATR_CTL_POSTURE ) );
+ pFmt->SetUnderline( (SvxUnderlineItem&)rSet.Get( RES_CHRATR_UNDERLINE ) );
+ pFmt->SetOverline( (SvxOverlineItem&)rSet.Get( RES_CHRATR_OVERLINE ) );
+ pFmt->SetCrossedOut( (SvxCrossedOutItem&)rSet.Get( RES_CHRATR_CROSSEDOUT ) );
+ pFmt->SetContour( (SvxContourItem&)rSet.Get( RES_CHRATR_CONTOUR ) );
+ pFmt->SetShadowed( (SvxShadowedItem&)rSet.Get( RES_CHRATR_SHADOWED ) );
+ pFmt->SetColor( (SvxColorItem&)rSet.Get( RES_CHRATR_COLOR ) );
+ pFmt->SetAdjust( (SvxAdjustItem&)rSet.Get( RES_PARATR_ADJUST ) );
+ }
+ if( UPDATE_BOX & eFlags )
+ {
+ pFmt->SetBox( (SvxBoxItem&)rSet.Get( RES_BOX ) );
+// FIXME - add attribute IDs for the diagonal line items
+// pFmt->SetTLBR( (SvxLineItem&)rSet.Get( RES_... ) );
+// pFmt->SetBLTR( (SvxLineItem&)rSet.Get( RES_... ) );
+ pFmt->SetBackground( (SvxBrushItem&)rSet.Get( RES_BACKGROUND ) );
+
+ const SwTblBoxNumFormat* pNumFmtItem;
+ const SvNumberformat* pNumFormat = 0;
+ if( SFX_ITEM_SET == rSet.GetItemState( RES_BOXATR_FORMAT, sal_True,
+ (const SfxPoolItem**)&pNumFmtItem ) && pNFmtr &&
+ 0 != (pNumFormat = pNFmtr->GetEntry( pNumFmtItem->GetValue() )) )
+ pFmt->SetValueFormat( ((SvNumberformat*)pNumFormat)->GetFormatstring(),
+ pNumFormat->GetLanguage(),
+ static_cast<LanguageType>(::GetAppLanguage()));
+ else
+ {
+ // defaulten
+ pFmt->SetValueFormat( aEmptyStr, LANGUAGE_SYSTEM,
+ static_cast<LanguageType>(::GetAppLanguage() ));
+ }
+ }
+ // den Rest koennen wir nicht, StarCalc spezifisch
+
+ return *pFmt;
+}
+
+
+void SwTableAutoFmt::UpdateToSet( sal_uInt8 nPos, SfxItemSet& rSet,
+ UpdateFlags eFlags, SvNumberFormatter* pNFmtr ) const
+{
+ const SwBoxAutoFmt& rChg = GetBoxFmt( nPos );
+
+ if( UPDATE_CHAR & eFlags )
+ {
+ if( IsFont() )
+ {
+ rSet.Put( rChg.GetFont() );
+ rSet.Put( rChg.GetHeight() );
+ rSet.Put( rChg.GetWeight() );
+ rSet.Put( rChg.GetPosture() );
+ // do not insert empty CJK font
+ const SvxFontItem& rCJKFont = rChg.GetCJKFont();
+ if( rCJKFont.GetStyleName().Len() )
+ {
+ rSet.Put( rChg.GetCJKFont() );
+ rSet.Put( rChg.GetCJKHeight() );
+ rSet.Put( rChg.GetCJKWeight() );
+ rSet.Put( rChg.GetCJKPosture() );
+ }
+ else
+ {
+ rSet.Put( rChg.GetHeight(), RES_CHRATR_CJK_FONTSIZE );
+ rSet.Put( rChg.GetWeight(), RES_CHRATR_CJK_WEIGHT );
+ rSet.Put( rChg.GetPosture(), RES_CHRATR_CJK_POSTURE );
+ }
+ // do not insert empty CTL font
+ const SvxFontItem& rCTLFont = rChg.GetCTLFont();
+ if( rCTLFont.GetStyleName().Len() )
+ {
+ rSet.Put( rChg.GetCTLFont() );
+ rSet.Put( rChg.GetCTLHeight() );
+ rSet.Put( rChg.GetCTLWeight() );
+ rSet.Put( rChg.GetCTLPosture() );
+ }
+ else
+ {
+ rSet.Put( rChg.GetHeight(), RES_CHRATR_CTL_FONTSIZE );
+ rSet.Put( rChg.GetWeight(), RES_CHRATR_CTL_WEIGHT );
+ rSet.Put( rChg.GetPosture(), RES_CHRATR_CTL_POSTURE );
+ }
+ rSet.Put( rChg.GetUnderline() );
+ rSet.Put( rChg.GetOverline() );
+ rSet.Put( rChg.GetCrossedOut() );
+ rSet.Put( rChg.GetContour() );
+ rSet.Put( rChg.GetShadowed() );
+ rSet.Put( rChg.GetColor() );
+ }
+ if( IsJustify() )
+ rSet.Put( rChg.GetAdjust() );
+ }
+
+ if( UPDATE_BOX & eFlags )
+ {
+ if( IsFrame() )
+ {
+ rSet.Put( rChg.GetBox() );
+// FIXME - uncomment the lines to put the diagonal line items
+// rSet.Put( rChg.GetTLBR() );
+// rSet.Put( rChg.GetBLTR() );
+ }
+ if( IsBackground() )
+ rSet.Put( rChg.GetBackground() );
+
+ if( IsValueFormat() && pNFmtr )
+ {
+ String sFmt; LanguageType eLng, eSys;
+ rChg.GetValueFormat( sFmt, eLng, eSys );
+ if( sFmt.Len() )
+ {
+ short nType;
+ sal_Bool bNew;
+ xub_StrLen nCheckPos;
+ sal_uInt32 nKey = pNFmtr->GetIndexPuttingAndConverting( sFmt, eLng,
+ eSys, nType, bNew, nCheckPos);
+ rSet.Put( SwTblBoxNumFormat( nKey ));
+ }
+ else
+ rSet.ClearItem( RES_BOXATR_FORMAT );
+ }
+ }
+
+ // den Rest koennen wir nicht, StarCalc spezifisch
+}
+
+
+sal_Bool SwTableAutoFmt::Load( SvStream& rStream, const SwAfVersions& rVersions )
+{
+ sal_Bool bRet = sal_True;
+ sal_uInt16 nVal = 0;
+ rStream >> nVal;
+ bRet = 0 == rStream.GetError();
+
+ if( bRet && (nVal == AUTOFORMAT_DATA_ID_X ||
+ (AUTOFORMAT_DATA_ID_504 <= nVal && nVal <= AUTOFORMAT_DATA_ID)) )
+ {
+ sal_Bool b;
+ // --- from 680/dr25 on: store strings as UTF-8
+ CharSet eCharSet = (nVal >= AUTOFORMAT_ID_680DR25) ? RTL_TEXTENCODING_UTF8 : rStream.GetStreamCharSet();
+ rStream.ReadByteString( aName, eCharSet );
+ if( AUTOFORMAT_DATA_ID_552 <= nVal )
+ {
+ rStream >> nStrResId;
+ sal_uInt16 nId = RID_SVXSTR_TBLAFMT_BEGIN + nStrResId;
+ if( RID_SVXSTR_TBLAFMT_BEGIN <= nId &&
+ nId < RID_SVXSTR_TBLAFMT_END )
+ {
+ aName = SVX_RESSTR( nId );
+ }
+ else
+ nStrResId = USHRT_MAX;
+ }
+ rStream >> b; bInclFont = b;
+ rStream >> b; bInclJustify = b;
+ rStream >> b; bInclFrame = b;
+ rStream >> b; bInclBackground = b;
+ rStream >> b; bInclValueFormat = b;
+ rStream >> b; bInclWidthHeight = b;
+
+ bRet = 0 == rStream.GetError();
+
+ for( sal_uInt8 i = 0; i < 16; ++i )
+ {
+ SwBoxAutoFmt* pFmt = new SwBoxAutoFmt;
+ bRet = pFmt->Load( rStream, rVersions, nVal );
+ if( bRet )
+ aBoxAutoFmt[ i ] = pFmt;
+ else
+ {
+ delete pFmt;
+ break;
+ }
+ }
+ }
+ return bRet;
+}
+
+#ifdef READ_OLDVERS
+
+sal_Bool SwTableAutoFmt::LoadOld( SvStream& rStream, sal_uInt16 aLoadVer[] )
+{
+ sal_Bool bRet = sal_True;
+ sal_uInt16 nVal = 0;
+ rStream >> nVal;
+ bRet = 0 == rStream.GetError();
+
+ if( bRet && ( AUTOFORMAT_OLD_DATA_ID == nVal ))
+ {
+ sal_Bool b;
+ rStream.ReadByteString( aName, rStream.GetStreamCharSet() );
+ rStream >> b; bInclFont = b;
+ rStream >> b; bInclJustify = b;
+ rStream >> b; bInclFrame = b;
+ rStream >> b; bInclBackground = b;
+ bRet = (rStream.GetError() == 0);
+
+ for( int i = 0; i < 16; i++)
+ {
+ SwBoxAutoFmt* pFmt = new SwBoxAutoFmt;
+ bRet = pFmt->LoadOld( rStream, aLoadVer );
+ if( bRet )
+ aBoxAutoFmt[ i ] = pFmt;
+ else
+ {
+ delete pFmt;
+ break;
+ }
+ }
+ }
+ return bRet;
+}
+#endif
+
+
+sal_Bool SwTableAutoFmt::Save( SvStream& rStream ) const
+{
+ sal_uInt16 nVal = AUTOFORMAT_DATA_ID;
+ sal_Bool b;
+ rStream << nVal;
+ // --- from 680/dr25 on: store strings as UTF-8
+ rStream.WriteByteString( aName, RTL_TEXTENCODING_UTF8 );
+ rStream << nStrResId;
+ rStream << ( b = bInclFont );
+ rStream << ( b = bInclJustify );
+ rStream << ( b = bInclFrame );
+ rStream << ( b = bInclBackground );
+ rStream << ( b = bInclValueFormat );
+ rStream << ( b = bInclWidthHeight );
+
+ sal_Bool bRet = 0 == rStream.GetError();
+
+ for( int i = 0; bRet && i < 16; ++i )
+ {
+ SwBoxAutoFmt* pFmt = aBoxAutoFmt[ i ];
+ if( !pFmt ) // nicht gesetzt -> default schreiben
+ {
+ // falls noch nicht vorhanden:
+ if( !pDfltBoxAutoFmt )
+ pDfltBoxAutoFmt = new SwBoxAutoFmt;
+ pFmt = pDfltBoxAutoFmt;
+ }
+ bRet = pFmt->Save( rStream );
+ }
+ return bRet;
+}
+
+
+SwTableAutoFmtTbl::SwTableAutoFmtTbl()
+{
+ String sNm;
+ SwTableAutoFmt* pNew = new SwTableAutoFmt(
+ SwStyleNameMapper::GetUIName( RES_POOLCOLL_STANDARD, sNm ) );
+
+ SwBoxAutoFmt aNew;
+
+ sal_uInt8 i;
+
+ Color aColor( COL_BLUE );
+ SvxBrushItem aBrushItem( aColor, RES_BACKGROUND );
+ aNew.SetBackground( aBrushItem );
+ aNew.SetColor( SvxColorItem(Color( COL_WHITE ), RES_CHRATR_COLOR) );
+
+ for( i = 0; i < 4; ++i )
+ pNew->SetBoxFmt( aNew, i );
+
+ // 70% Grau
+ aBrushItem.SetColor( RGB_COLORDATA( 0x4d, 0x4d, 0x4d ) );
+ aNew.SetBackground( aBrushItem );
+ for( i = 4; i <= 12; i += 4 )
+ pNew->SetBoxFmt( aNew, i );
+
+ // 20% Grau
+ aBrushItem.SetColor( RGB_COLORDATA( 0xcc, 0xcc, 0xcc ) );
+ aNew.SetBackground( aBrushItem );
+ aColor.SetColor( COL_BLACK );
+ aNew.SetColor( SvxColorItem( aColor, RES_CHRATR_COLOR) );
+ for( i = 7; i <= 15; i += 4 )
+ pNew->SetBoxFmt( aNew, i );
+ for( i = 13; i <= 14; ++i )
+ pNew->SetBoxFmt( aNew, i );
+
+ aBrushItem.SetColor( Color( COL_WHITE ) );
+ aNew.SetBackground( aBrushItem );
+ for( i = 5; i <= 6; ++i )
+ pNew->SetBoxFmt( aNew, i );
+ for( i = 9; i <= 10; ++i )
+ pNew->SetBoxFmt( aNew, i );
+
+
+ SvxBoxItem aBox( RES_BOX );
+ aBox.SetDistance( 55 );
+ SvxBorderLine aLn( &aColor, DEF_LINE_WIDTH_0 );
+ aBox.SetLine( &aLn, BOX_LINE_LEFT );
+ aBox.SetLine( &aLn, BOX_LINE_BOTTOM );
+
+ for( i = 0; i <= 15; ++i )
+ {
+ aBox.SetLine( i <= 3 ? &aLn : 0, BOX_LINE_TOP );
+ aBox.SetLine( (3 == ( i & 3 )) ? &aLn : 0, BOX_LINE_RIGHT );
+ ((SwBoxAutoFmt&)pNew->GetBoxFmt( i )).SetBox( aBox );
+ }
+
+ Insert( pNew, Count() );
+}
+
+sal_Bool SwTableAutoFmtTbl::Load()
+{
+ sal_Bool bRet = sal_False;
+ String sNm( String::CreateFromAscii(
+ RTL_CONSTASCII_STRINGPARAM( sAutoTblFmtName )));
+ SvtPathOptions aOpt;
+ if( aOpt.SearchFile( sNm, SvtPathOptions::PATH_USERCONFIG ))
+ {
+ SfxMedium aStream( sNm, STREAM_STD_READ, sal_True );
+ bRet = Load( *aStream.GetInStream() );
+ }
+ else
+ bRet = sal_False;
+ return bRet;
+}
+
+sal_Bool SwTableAutoFmtTbl::Save() const
+{
+ SvtPathOptions aPathOpt;
+ String sNm( aPathOpt.GetUserConfigPath() );
+ sNm += INET_PATH_TOKEN;
+ sNm.AppendAscii( RTL_CONSTASCII_STRINGPARAM( sAutoTblFmtName ));
+ SfxMedium aStream(sNm, STREAM_STD_WRITE, sal_True );
+ return Save( *aStream.GetOutStream() ) && aStream.Commit();
+}
+
+sal_Bool SwTableAutoFmtTbl::Load( SvStream& rStream )
+{
+ sal_Bool bRet = 0 == rStream.GetError();
+ if (bRet)
+ {
+ // Achtung hier muss ein allgemeiner Header gelesen werden
+ sal_uInt16 nVal = 0;
+ rStream >> nVal;
+ bRet = 0 == rStream.GetError();
+
+ if( bRet )
+ {
+ SwAfVersions aVersions;
+
+ if( nVal == AUTOFORMAT_ID_358 ||
+ (AUTOFORMAT_ID_504 <= nVal && nVal <= AUTOFORMAT_ID) )
+ {
+ sal_uInt16 nFileVers = SOFFICE_FILEFORMAT_40;
+ sal_uInt8 nChrSet, nCnt;
+ long nPos = rStream.Tell();
+ rStream >> nCnt >> nChrSet;
+// if( 4 <= nCnt )
+// rStream >> nFileVers;
+ if( rStream.Tell() != sal_uLong(nPos + nCnt) )
+ {
+ OSL_ENSURE( !this, "Der Header enthaelt mehr/neuere Daten" );
+ rStream.Seek( nPos + nCnt );
+ }
+ rStream.SetStreamCharSet( (CharSet)nChrSet );
+ rStream.SetVersion( nFileVers );
+ }
+
+ if( nVal == AUTOFORMAT_ID_358 || nVal == AUTOFORMAT_ID_X ||
+ (AUTOFORMAT_ID_504 <= nVal && nVal <= AUTOFORMAT_ID) )
+ {
+ aVersions.Load( rStream, nVal ); // Item-Versionen
+
+ SwTableAutoFmt* pNew;
+ sal_uInt16 nAnz = 0;
+ rStream >> nAnz;
+
+ bRet = 0 == rStream.GetError();
+
+ for( sal_uInt16 i = 0; i < nAnz; ++i )
+ {
+ pNew = new SwTableAutoFmt( aEmptyStr );
+ bRet = pNew->Load( rStream, aVersions );
+ if( bRet )
+ {
+ Insert( pNew, Count() );
+ }
+ else
+ {
+ delete pNew;
+ break;
+ }
+ }
+ }
+#ifdef READ_OLDVERS
+ else if( AUTOFORMAT_OLD_ID == nVal || AUTOFORMAT_OLD_ID1 == nVal )
+ {
+ SwTableAutoFmt* pNew;
+ sal_uInt16 nAnz = 0;
+ rStream >> nAnz;
+
+ sal_uInt16 aArr[ 12 ];
+ memset( aArr, 0, 12 * sizeof( sal_uInt16 ) );
+ if( AUTOFORMAT_OLD_ID1 == nVal )
+ for( sal_uInt16 n = 0; n < 12; ++n )
+ rStream >> aArr[ n ];
+
+ bRet = 0 == rStream.GetError();
+
+ for( sal_uInt16 i = 0; i < nAnz; ++i )
+ {
+ pNew = new SwTableAutoFmt( aEmptyStr );
+ bRet = pNew->LoadOld( rStream, aArr );
+ if( bRet )
+ {
+ Insert( pNew, Count() );
+ }
+ else
+ {
+ delete pNew;
+ break;
+ }
+ }
+ }
+#endif
+ }
+ }
+ return bRet;
+}
+
+
+sal_Bool SwTableAutoFmtTbl::Save( SvStream& rStream ) const
+{
+ sal_Bool bRet = 0 == rStream.GetError();
+ if (bRet)
+ {
+ rStream.SetVersion( SOFFICE_FILEFORMAT_40 );
+
+ // Achtung hier muss ein allgemeiner Header gespeichert werden
+ sal_uInt16 nVal = AUTOFORMAT_ID;
+ rStream << nVal
+ << (sal_uInt8)2 // Anzahl von Zeichen des Headers incl. diesem
+ << (sal_uInt8)GetStoreCharSet( ::gsl_getSystemTextEncoding() );
+
+ bRet = 0 == rStream.GetError();
+
+ //-----------------------------------------------------------
+ // die VersionsNummer fuer alle Attribute schreiben
+ (*this)[ 0 ]->GetBoxFmt( 0 ).SaveVerionNo( rStream );
+
+ rStream << (sal_uInt16)(Count() - 1);
+ bRet = 0 == rStream.GetError();
+
+ for( sal_uInt16 i = 1; bRet && i < Count(); ++i )
+ {
+ SwTableAutoFmt* pFmt = (*this)[ i ];
+ bRet = pFmt->Save( rStream );
+ }
+ }
+ rStream.Flush();
+ return bRet;
+}
+
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/doc/tblcpy.cxx b/sw/source/core/doc/tblcpy.cxx
new file mode 100644
index 000000000000..d83bf854c645
--- /dev/null
+++ b/sw/source/core/doc/tblcpy.cxx
@@ -0,0 +1,1077 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+
+#include <hintids.hxx>
+
+#define _ZFORLIST_DECLARE_TABLE
+#include <svl/zforlist.hxx>
+#include <frmfmt.hxx>
+#include <doc.hxx>
+#include <IDocumentUndoRedo.hxx>
+#include <cntfrm.hxx>
+#include <pam.hxx>
+#include <swtable.hxx>
+#include <ndtxt.hxx>
+#include <fldbas.hxx>
+#include <tblsel.hxx>
+#include <tabfrm.hxx>
+#include <poolfmt.hxx>
+#include <cellatr.hxx>
+#include <mvsave.hxx>
+#include <docary.hxx>
+#include <fmtanchr.hxx>
+#include <hints.hxx>
+#include <UndoTable.hxx>
+#include <redline.hxx>
+#include <fmtfsize.hxx>
+#include <list>
+
+sal_Bool _FndCntntLine( const SwTableLine*& rpLine, void* pPara );
+sal_Bool _FndCntntBox( const SwTableBox*& rpBox, void* pPara );
+void lcl_CpyBox( const SwTable& rCpyTbl, const SwTableBox* pCpyBox,
+ SwTable& rDstTbl, SwTableBox* pDstBox,
+ sal_Bool bDelCntnt, SwUndoTblCpyTbl* pUndo );
+
+// The following type will be used by table copy functions to describe
+// the structure of tables (or parts of tables).
+// It's for new table model only.
+
+namespace
+{
+ struct BoxSpanInfo
+ {
+ SwTableBox* mpBox;
+ SwTableBox* mpCopy;
+ sal_uInt16 mnColSpan;
+ bool mbSelected;
+ };
+
+ typedef std::vector< BoxSpanInfo > BoxStructure;
+ typedef std::vector< BoxStructure > LineStructure;
+ typedef std::list< sal_uLong > ColumnStructure;
+
+ struct SubBox
+ {
+ SwTableBox *mpBox;
+ bool mbCovered;
+ };
+
+ typedef std::list< SubBox > SubLine;
+ typedef std::list< SubLine > SubTable;
+
+ class TableStructure
+ {
+ public:
+ LineStructure maLines;
+ ColumnStructure maCols;
+ sal_uInt16 mnStartCol;
+ sal_uInt16 mnAddLine;
+ void addLine( sal_uInt16 &rLine, const SwTableBoxes&, const SwSelBoxes*,
+ bool bNewModel );
+ void addBox( sal_uInt16 nLine, const SwSelBoxes*, SwTableBox *pBox,
+ sal_uLong &rnB, sal_uInt16 &rnC, ColumnStructure::iterator& rpCl,
+ BoxStructure::iterator& rpSel, bool &rbSel, bool bCover );
+ void incColSpan( sal_uInt16 nLine, sal_uInt16 nCol );
+ TableStructure( const SwTable& rTable );
+ TableStructure( const SwTable& rTable, _FndBox &rFndBox,
+ const SwSelBoxes& rSelBoxes,
+ LineStructure::size_type nMinSize );
+ LineStructure::size_type getLineCount() const
+ { return maLines.size(); }
+ void moreLines( const SwTable& rTable );
+ void assignBoxes( const TableStructure &rSource );
+ void copyBoxes( const SwTable& rSource, SwTable& rDstTbl,
+ SwUndoTblCpyTbl* pUndo ) const;
+ };
+
+ SubTable::iterator insertSubLine( SubTable& rSubTable, SwTableLine& rLine,
+ SubTable::iterator pStartLn );
+
+ SubTable::iterator insertSubBox( SubTable& rSubTable, SwTableBox& rBox,
+ SubTable::iterator pStartLn, SubTable::iterator pEndLn )
+ {
+ if( rBox.GetTabLines().Count() )
+ {
+ SubTable::difference_type nSize = std::distance( pStartLn, pEndLn );
+ if( nSize < rBox.GetTabLines().Count() )
+ {
+ SubLine aSubLine;
+ SubLine::iterator pBox = pStartLn->begin();
+ SubLine::iterator pEnd = pStartLn->end();
+ while( pBox != pEnd )
+ {
+ SubBox aSub;
+ aSub.mpBox = pBox->mpBox;
+ aSub.mbCovered = true;
+ aSubLine.push_back( aSub );
+ ++pBox;
+ }
+ do
+ {
+ rSubTable.insert( pEndLn, aSubLine );
+ } while( ++nSize < rBox.GetTabLines().Count() );
+ }
+ for( sal_uInt16 nLine = 0; nLine < rBox.GetTabLines().Count(); ++nLine )
+ pStartLn = insertSubLine( rSubTable, *rBox.GetTabLines()[nLine],
+ pStartLn );
+ OSL_ENSURE( pStartLn == pEndLn, "Sub line confusion" );
+ }
+ else
+ {
+ SubBox aSub;
+ aSub.mpBox = &rBox;
+ aSub.mbCovered = false;
+ while( pStartLn != pEndLn )
+ {
+ pStartLn->push_back( aSub );
+ aSub.mbCovered = true;
+ ++pStartLn;
+ }
+ }
+ return pStartLn;
+ }
+
+ SubTable::iterator insertSubLine( SubTable& rSubTable, SwTableLine& rLine,
+ SubTable::iterator pStartLn )
+ {
+ SubTable::iterator pMax = pStartLn;
+ ++pMax;
+ SubTable::difference_type nMax = 1;
+ for( sal_uInt16 nBox = 0; nBox < rLine.GetTabBoxes().Count(); ++nBox )
+ {
+ SubTable::iterator pTmp = insertSubBox( rSubTable,
+ *rLine.GetTabBoxes()[nBox], pStartLn, pMax );
+ SubTable::difference_type nTmp = std::distance( pStartLn, pTmp );
+ if( nTmp > nMax )
+ {
+ pMax = pTmp;
+ nMax = nTmp;
+ }
+ }
+ return pMax;
+ }
+
+ TableStructure::TableStructure( const SwTable& rTable ) :
+ maLines( rTable.GetTabLines().Count() ), mnStartCol(USHRT_MAX),
+ mnAddLine(0)
+ {
+ maCols.push_front(0);
+ const SwTableLines &rLines = rTable.GetTabLines();
+ sal_uInt16 nCnt = 0;
+ for( sal_uInt16 nLine = 0; nLine < rLines.Count(); ++nLine )
+ addLine( nCnt, rLines[nLine]->GetTabBoxes(), 0, rTable.IsNewModel() );
+ }
+
+ TableStructure::TableStructure( const SwTable& rTable,
+ _FndBox &rFndBox, const SwSelBoxes& rSelBoxes,
+ LineStructure::size_type nMinSize )
+ : mnStartCol(USHRT_MAX), mnAddLine(0)
+ {
+ if( rFndBox.GetLines().Count() )
+ {
+ bool bNoSelection = rSelBoxes.Count() < 2;
+ _FndLines &rFndLines = rFndBox.GetLines();
+ maCols.push_front(0);
+ const SwTableLine* pLine = rFndLines[0]->GetLine();
+ sal_uInt16 nStartLn = rTable.GetTabLines().C40_GETPOS( SwTableLine, pLine );
+ sal_uInt16 nEndLn = nStartLn;
+ if( rFndLines.Count() > 1 )
+ {
+ pLine = rFndLines[ rFndLines.Count()-1 ]->GetLine();
+ nEndLn = rTable.GetTabLines().C40_GETPOS( SwTableLine, pLine );
+ }
+ if( nStartLn < USHRT_MAX && nEndLn < USHRT_MAX )
+ {
+ const SwTableLines &rLines = rTable.GetTabLines();
+ if( bNoSelection &&
+ (sal_uInt16)nMinSize > nEndLn - nStartLn + 1 )
+ {
+ sal_uInt16 nNewEndLn = nStartLn + (sal_uInt16)nMinSize - 1;
+ if( nNewEndLn >= rLines.Count() )
+ {
+ mnAddLine = nNewEndLn - rLines.Count() + 1;
+ nNewEndLn = rLines.Count() - 1;
+ }
+ while( nEndLn < nNewEndLn )
+ {
+ SwTableLine *pLine2 = rLines[ ++nEndLn ];
+ SwTableBox *pTmpBox = pLine2->GetTabBoxes()[0];
+ _FndLine *pInsLine = new _FndLine( pLine2, &rFndBox );
+ _FndBox *pFndBox = new _FndBox( pTmpBox, pInsLine );
+ pInsLine->GetBoxes().C40_INSERT( _FndBox, pFndBox, 0 );
+ rFndLines.C40_INSERT( _FndLine, pInsLine, rFndLines.Count() );
+ }
+ }
+ maLines.resize( nEndLn - nStartLn + 1 );
+ const SwSelBoxes* pSelBoxes = &rSelBoxes;
+ sal_uInt16 nCnt = 0;
+ for( sal_uInt16 nLine = nStartLn; nLine <= nEndLn; ++nLine )
+ {
+ addLine( nCnt, rLines[nLine]->GetTabBoxes(),
+ pSelBoxes, rTable.IsNewModel() );
+ if( bNoSelection )
+ pSelBoxes = 0;
+ }
+ }
+ if( bNoSelection && mnStartCol < USHRT_MAX )
+ {
+ BoxStructure::iterator pC = maLines[0].begin();
+ BoxStructure::iterator pEnd = maLines[0].end();
+ sal_uInt16 nIdx = mnStartCol;
+ mnStartCol = 0;
+ while( nIdx && pC != pEnd )
+ {
+ mnStartCol = mnStartCol + pC->mnColSpan;
+ --nIdx;
+ ++pC;
+ }
+ }
+ else
+ mnStartCol = USHRT_MAX;
+ }
+ }
+
+ void TableStructure::addLine( sal_uInt16 &rLine, const SwTableBoxes& rBoxes,
+ const SwSelBoxes* pSelBoxes, bool bNewModel )
+ {
+ bool bComplex = false;
+ if( !bNewModel )
+ for( sal_uInt16 nBox = 0; !bComplex && nBox < rBoxes.Count(); ++nBox )
+ bComplex = rBoxes[nBox]->GetTabLines().Count() > 0;
+ if( bComplex )
+ {
+ SubTable aSubTable;
+ SubLine aSubLine;
+ aSubTable.push_back( aSubLine );
+ SubTable::iterator pStartLn = aSubTable.begin();
+ SubTable::iterator pEndLn = aSubTable.end();
+ for( sal_uInt16 nBox = 0; nBox < rBoxes.Count(); ++nBox )
+ insertSubBox( aSubTable, *rBoxes[nBox], pStartLn, pEndLn );
+ SubTable::size_type nSize = aSubTable.size();
+ if( nSize )
+ {
+ maLines.resize( maLines.size() + nSize - 1 );
+ while( pStartLn != pEndLn )
+ {
+ bool bSelected = false;
+ sal_uLong nBorder = 0;
+ sal_uInt16 nCol = 0;
+ maLines[rLine].reserve( pStartLn->size() );
+ BoxStructure::iterator pSel = maLines[rLine].end();
+ ColumnStructure::iterator pCol = maCols.begin();
+ SubLine::iterator pBox = pStartLn->begin();
+ SubLine::iterator pEnd = pStartLn->end();
+ while( pBox != pEnd )
+ {
+ addBox( rLine, pSelBoxes, pBox->mpBox, nBorder, nCol,
+ pCol, pSel, bSelected, pBox->mbCovered );
+ ++pBox;
+ }
+ ++rLine;
+ ++pStartLn;
+ }
+ }
+ }
+ else
+ {
+ bool bSelected = false;
+ sal_uLong nBorder = 0;
+ sal_uInt16 nCol = 0;
+ maLines[rLine].reserve( rBoxes.Count() );
+ ColumnStructure::iterator pCol = maCols.begin();
+ BoxStructure::iterator pSel = maLines[rLine].end();
+ for( sal_uInt16 nBox = 0; nBox < rBoxes.Count(); ++nBox )
+ addBox( rLine, pSelBoxes, rBoxes[nBox], nBorder, nCol,
+ pCol, pSel, bSelected, false );
+ ++rLine;
+ }
+ }
+
+ void TableStructure::addBox( sal_uInt16 nLine, const SwSelBoxes* pSelBoxes,
+ SwTableBox *pBox, sal_uLong &rnBorder, sal_uInt16 &rnCol,
+ ColumnStructure::iterator& rpCol, BoxStructure::iterator& rpSel,
+ bool &rbSelected, bool bCovered )
+ {
+ BoxSpanInfo aInfo;
+ if( pSelBoxes &&
+ USHRT_MAX != pSelBoxes->GetPos( pBox ) )
+ {
+ aInfo.mbSelected = true;
+ if( mnStartCol == USHRT_MAX )
+ {
+ mnStartCol = (sal_uInt16)maLines[nLine].size();
+ if( pSelBoxes->Count() < 2 )
+ {
+ pSelBoxes = 0;
+ aInfo.mbSelected = false;
+ }
+ }
+ }
+ else
+ aInfo.mbSelected = false;
+ rnBorder += pBox->GetFrmFmt()->GetFrmSize().GetWidth();
+ sal_uInt16 nLeftCol = rnCol;
+ while( rpCol != maCols.end() && *rpCol < rnBorder )
+ {
+ ++rnCol;
+ ++rpCol;
+ }
+ if( rpCol == maCols.end() || *rpCol > rnBorder )
+ {
+ maCols.insert( rpCol, rnBorder );
+ --rpCol;
+ incColSpan( nLine, rnCol );
+ }
+ aInfo.mnColSpan = rnCol - nLeftCol;
+ aInfo.mpCopy = 0;
+ aInfo.mpBox = bCovered ? 0 : pBox;
+ maLines[nLine].push_back( aInfo );
+ if( aInfo.mbSelected )
+ {
+ if( rbSelected )
+ {
+ while( rpSel != maLines[nLine].end() )
+ {
+ rpSel->mbSelected = true;
+ ++rpSel;
+ }
+ }
+ else
+ {
+ rpSel = maLines[nLine].end();
+ rbSelected = true;
+ }
+ --rpSel;
+ }
+ }
+
+ void TableStructure::moreLines( const SwTable& rTable )
+ {
+ if( mnAddLine )
+ {
+ const SwTableLines &rLines = rTable.GetTabLines();
+ sal_uInt16 nLineCount = rLines.Count();
+ if( nLineCount < mnAddLine )
+ mnAddLine = nLineCount;
+ sal_uInt16 nLine = (sal_uInt16)maLines.size();
+ maLines.resize( nLine + mnAddLine );
+ while( mnAddLine )
+ {
+ SwTableLine *pLine = rLines[ nLineCount - mnAddLine ];
+ addLine( nLine, pLine->GetTabBoxes(), 0, rTable.IsNewModel() );
+ --mnAddLine;
+ }
+ }
+ }
+
+ void TableStructure::incColSpan( sal_uInt16 nLineMax, sal_uInt16 nNewCol )
+ {
+ for( sal_uInt16 nLine = 0; nLine < nLineMax; ++nLine )
+ {
+ BoxStructure::iterator pInfo = maLines[nLine].begin();
+ BoxStructure::iterator pEnd = maLines[nLine].end();
+ long nCol = pInfo->mnColSpan;
+ while( nNewCol > nCol && ++pInfo != pEnd )
+ nCol += pInfo->mnColSpan;
+ if( pInfo != pEnd )
+ ++(pInfo->mnColSpan);
+ }
+ }
+
+ void TableStructure::assignBoxes( const TableStructure &rSource )
+ {
+ LineStructure::const_iterator pFirstLine = rSource.maLines.begin();
+ LineStructure::const_iterator pLastLine = rSource.maLines.end();
+ if( pFirstLine == pLastLine )
+ return;
+ LineStructure::const_iterator pCurrLine = pFirstLine;
+ LineStructure::size_type nLineCount = maLines.size();
+ sal_uInt16 nFirstStartCol = 0;
+ {
+ BoxStructure::const_iterator pFirstBox = pFirstLine->begin();
+ if( pFirstBox != pFirstLine->end() && pFirstBox->mpBox &&
+ pFirstBox->mpBox->getDummyFlag() )
+ nFirstStartCol = pFirstBox->mnColSpan;
+ }
+ for( LineStructure::size_type nLine = 0; nLine < nLineCount; ++nLine )
+ {
+ BoxStructure::const_iterator pFirstBox = pCurrLine->begin();
+ BoxStructure::const_iterator pLastBox = pCurrLine->end();
+ sal_uInt16 nCurrStartCol = mnStartCol;
+ if( pFirstBox != pLastBox )
+ {
+ BoxStructure::const_iterator pTmpBox = pLastBox;
+ --pTmpBox;
+ if( pTmpBox->mpBox && pTmpBox->mpBox->getDummyFlag() )
+ --pLastBox;
+ if( pFirstBox != pLastBox && pFirstBox->mpBox &&
+ pFirstBox->mpBox->getDummyFlag() )
+ {
+ if( nCurrStartCol < USHRT_MAX )
+ {
+ if( pFirstBox->mnColSpan > nFirstStartCol )
+ nCurrStartCol = pFirstBox->mnColSpan - nFirstStartCol
+ + nCurrStartCol;
+ }
+ ++pFirstBox;
+ }
+ }
+ if( pFirstBox != pLastBox )
+ {
+ BoxStructure::const_iterator pCurrBox = pFirstBox;
+ BoxStructure &rBox = maLines[nLine];
+ BoxStructure::size_type nBoxCount = rBox.size();
+ sal_uInt16 nCol = 0;
+ for( BoxStructure::size_type nBox = 0; nBox < nBoxCount; ++nBox )
+ {
+ BoxSpanInfo& rInfo = rBox[nBox];
+ nCol = nCol + rInfo.mnColSpan;
+ if( rInfo.mbSelected || nCol > nCurrStartCol )
+ {
+ rInfo.mpCopy = pCurrBox->mpBox;
+ if( rInfo.mbSelected && rInfo.mpCopy->getDummyFlag() )
+ {
+ ++pCurrBox;
+ if( pCurrBox == pLastBox )
+ {
+ pCurrBox = pFirstBox;
+ if( pCurrBox->mpBox->getDummyFlag() )
+ ++pCurrBox;
+ }
+ rInfo.mpCopy = pCurrBox->mpBox;
+ }
+ ++pCurrBox;
+ if( pCurrBox == pLastBox )
+ {
+ if( rInfo.mbSelected )
+ pCurrBox = pFirstBox;
+ else
+ {
+ rInfo.mbSelected = rInfo.mpCopy == 0;
+ break;
+ }
+ }
+ rInfo.mbSelected = rInfo.mpCopy == 0;
+ }
+ }
+ }
+ ++pCurrLine;
+ if( pCurrLine == pLastLine )
+ pCurrLine = pFirstLine;
+ }
+ }
+
+ void TableStructure::copyBoxes( const SwTable& rSource, SwTable& rDstTbl,
+ SwUndoTblCpyTbl* pUndo ) const
+ {
+ LineStructure::size_type nLineCount = maLines.size();
+ for( LineStructure::size_type nLine = 0; nLine < nLineCount; ++nLine )
+ {
+ const BoxStructure &rBox = maLines[nLine];
+ BoxStructure::size_type nBoxCount = rBox.size();
+ for( BoxStructure::size_type nBox = 0; nBox < nBoxCount; ++nBox )
+ {
+ const BoxSpanInfo& rInfo = rBox[nBox];
+ if( ( rInfo.mpCopy && !rInfo.mpCopy->getDummyFlag() )
+ || rInfo.mbSelected )
+ {
+ SwTableBox *pBox = rInfo.mpBox;
+ if( pBox && pBox->getRowSpan() > 0 )
+ lcl_CpyBox( rSource, rInfo.mpCopy, rDstTbl, pBox,
+ sal_True, pUndo );
+ }
+ }
+ }
+ }
+}
+
+// ---------------------------------------------------------------
+
+// kopiere die Tabelle in diese.
+// Kopiere alle Boxen einer Line in entsprechenden Boxen. Der alte Inhalt
+// wird dabei geloescht.
+// Ist keine mehr vorhanden, kommt der restliche Inhalt in die letzte
+// Box einer "GrundLine".
+// Ist auch keine Line mehr vorhanden, -> auch in die letzte Box
+// einer "GrundLine"
+
+
+void lcl_CpyBox( const SwTable& rCpyTbl, const SwTableBox* pCpyBox,
+ SwTable& rDstTbl, SwTableBox* pDstBox,
+ sal_Bool bDelCntnt, SwUndoTblCpyTbl* pUndo )
+{
+ OSL_ENSURE( ( !pCpyBox || pCpyBox->GetSttNd() ) && pDstBox->GetSttNd(),
+ "Keine inhaltstragende Box" );
+
+ SwDoc* pCpyDoc = rCpyTbl.GetFrmFmt()->GetDoc();
+ SwDoc* pDoc = rDstTbl.GetFrmFmt()->GetDoc();
+
+ // kopiere erst den neuen und loeschen dann den alten Inhalt
+ // (keine leeren Section erzeugen; werden sonst geloescht!)
+ std::auto_ptr< SwNodeRange > pRg( pCpyBox ?
+ new SwNodeRange ( *pCpyBox->GetSttNd(), 1,
+ *pCpyBox->GetSttNd()->EndOfSectionNode() ) : 0 );
+
+ SwNodeIndex aInsIdx( *pDstBox->GetSttNd(), bDelCntnt ? 1 :
+ pDstBox->GetSttNd()->EndOfSectionIndex() -
+ pDstBox->GetSttIdx() );
+
+ if( pUndo )
+ pUndo->AddBoxBefore( *pDstBox, bDelCntnt );
+
+ bool bUndoRedline = pUndo && pDoc->IsRedlineOn();
+ ::sw::UndoGuard const undoGuard(pDoc->GetIDocumentUndoRedo());
+
+ SwNodeIndex aSavePos( aInsIdx, -1 );
+ if( pRg.get() )
+ pCpyDoc->CopyWithFlyInFly( *pRg, 0, aInsIdx, sal_False );
+ else
+ pDoc->GetNodes().MakeTxtNode( aInsIdx, (SwTxtFmtColl*)pDoc->GetDfltTxtFmtColl() );
+ aSavePos++;
+
+ SwTableLine* pLine = pDstBox->GetUpper();
+ while( pLine->GetUpper() )
+ pLine = pLine->GetUpper()->GetUpper();
+
+ sal_Bool bReplaceColl = sal_True;
+ if( bDelCntnt && !bUndoRedline )
+ {
+ // zuerst die Fly loeschen, dann die entsprechenden Nodes
+ SwNodeIndex aEndNdIdx( *aInsIdx.GetNode().EndOfSectionNode() );
+
+ // Bookmarks usw. verschieben
+ {
+ SwPosition aMvPos( aInsIdx );
+ SwCntntNode* pCNd = pDoc->GetNodes().GoPrevious( &aMvPos.nNode );
+ aMvPos.nContent.Assign( pCNd, pCNd->Len() );
+ pDoc->CorrAbs( aInsIdx, aEndNdIdx, aMvPos, /*sal_True*/sal_False );
+ }
+
+ // stehen noch FlyFrames rum, loesche auch diese
+ for( sal_uInt16 n = 0; n < pDoc->GetSpzFrmFmts()->Count(); ++n )
+ {
+ SwFrmFmt *const pFly = (*pDoc->GetSpzFrmFmts())[n];
+ SwFmtAnchor const*const pAnchor = &pFly->GetAnchor();
+ SwPosition const*const pAPos = pAnchor->GetCntntAnchor();
+ if (pAPos &&
+ ((FLY_AT_PARA == pAnchor->GetAnchorId()) ||
+ (FLY_AT_CHAR == pAnchor->GetAnchorId())) &&
+ aInsIdx <= pAPos->nNode && pAPos->nNode <= aEndNdIdx )
+ {
+ pDoc->DelLayoutFmt( pFly );
+ }
+ }
+
+ // ist DestBox eine Headline-Box und hat Tabellen-Vorlage gesetzt,
+ // dann NICHT die TabellenHeadline-Vorlage automatisch setzen
+ if( 1 < rDstTbl.GetTabLines().Count() &&
+ pLine == rDstTbl.GetTabLines()[0] )
+ {
+ SwCntntNode* pCNd = aInsIdx.GetNode().GetCntntNode();
+ if( !pCNd )
+ {
+ SwNodeIndex aTmp( aInsIdx );
+ pCNd = pDoc->GetNodes().GoNext( &aTmp );
+ }
+
+ if( pCNd &&
+ RES_POOLCOLL_TABLE_HDLN !=
+ pCNd->GetFmtColl()->GetPoolFmtId() )
+ bReplaceColl = sal_False;
+ }
+
+ pDoc->GetNodes().Delete( aInsIdx, aEndNdIdx.GetIndex() - aInsIdx.GetIndex() );
+ }
+
+ //b6341295: Table copy redlining will be managed by AddBoxAfter()
+ if( pUndo )
+ pUndo->AddBoxAfter( *pDstBox, aInsIdx, bDelCntnt );
+
+ // heading
+ SwTxtNode *const pTxtNd = aSavePos.GetNode().GetTxtNode();
+ if( pTxtNd )
+ {
+ sal_uInt16 nPoolId = pTxtNd->GetTxtColl()->GetPoolFmtId();
+ if( bReplaceColl &&
+ (( 1 < rDstTbl.GetTabLines().Count() &&
+ pLine == rDstTbl.GetTabLines()[0] )
+ // gilt noch die Tabellen-Inhalt ??
+ ? RES_POOLCOLL_TABLE == nPoolId
+ : RES_POOLCOLL_TABLE_HDLN == nPoolId ) )
+ {
+ SwTxtFmtColl* pColl = pDoc->GetTxtCollFromPool(
+ static_cast<sal_uInt16>(
+ RES_POOLCOLL_TABLE == nPoolId
+ ? RES_POOLCOLL_TABLE_HDLN
+ : RES_POOLCOLL_TABLE ) );
+ if( pColl ) // Vorlage umsetzen
+ {
+ SwPaM aPam( aSavePos );
+ aPam.SetMark();
+ aPam.Move( fnMoveForward, fnGoSection );
+ pDoc->SetTxtFmtColl( aPam, pColl );
+ }
+ }
+
+ // loesche die akt. Formel/Format/Value Werte
+ if( SFX_ITEM_SET == pDstBox->GetFrmFmt()->GetItemState( RES_BOXATR_FORMAT ) ||
+ SFX_ITEM_SET == pDstBox->GetFrmFmt()->GetItemState( RES_BOXATR_FORMULA ) ||
+ SFX_ITEM_SET == pDstBox->GetFrmFmt()->GetItemState( RES_BOXATR_VALUE ) )
+ {
+ pDstBox->ClaimFrmFmt()->ResetFmtAttr( RES_BOXATR_FORMAT,
+ RES_BOXATR_VALUE );
+ }
+
+ // kopiere die TabellenBoxAttribute - Formel/Format/Value
+ if( pCpyBox )
+ {
+ SfxItemSet aBoxAttrSet( pCpyDoc->GetAttrPool(), RES_BOXATR_FORMAT,
+ RES_BOXATR_VALUE );
+ aBoxAttrSet.Put( pCpyBox->GetFrmFmt()->GetAttrSet() );
+ if( aBoxAttrSet.Count() )
+ {
+ const SfxPoolItem* pItem;
+ SvNumberFormatter* pN = pDoc->GetNumberFormatter( sal_False );
+ if( pN && pN->HasMergeFmtTbl() && SFX_ITEM_SET == aBoxAttrSet.
+ GetItemState( RES_BOXATR_FORMAT, sal_False, &pItem ) )
+ {
+ sal_uLong nOldIdx = ((SwTblBoxNumFormat*)pItem)->GetValue();
+ sal_uLong nNewIdx = pN->GetMergeFmtIndex( nOldIdx );
+ if( nNewIdx != nOldIdx )
+ aBoxAttrSet.Put( SwTblBoxNumFormat( nNewIdx ));
+ }
+ pDstBox->ClaimFrmFmt()->SetFmtAttr( aBoxAttrSet );
+ }
+ }
+ }
+}
+
+sal_Bool SwTable::InsNewTable( const SwTable& rCpyTbl, const SwSelBoxes& rSelBoxes,
+ SwUndoTblCpyTbl* pUndo )
+{
+ SwDoc* pDoc = GetFrmFmt()->GetDoc();
+ SwDoc* pCpyDoc = rCpyTbl.GetFrmFmt()->GetDoc();
+
+ SwTblNumFmtMerge aTNFM( *pCpyDoc, *pDoc );
+
+ // analyse source structure
+ TableStructure aCopyStruct( rCpyTbl );
+
+ // analyse target structure (from start box) and selected substructure
+ _FndBox aFndBox( 0, 0 );
+ { // get all boxes/lines
+ _FndPara aPara( rSelBoxes, &aFndBox );
+ GetTabLines().ForEach( &_FndLineCopyCol, &aPara );
+ }
+ TableStructure aTarget( *this, aFndBox, rSelBoxes, aCopyStruct.getLineCount() );
+
+ bool bClear = false;
+ if( aTarget.mnAddLine && IsNewModel() )
+ {
+ SwSelBoxes aBoxes;
+ aBoxes.Insert( GetTabLines()[ GetTabLines().Count()-1 ]->GetTabBoxes()[0] );
+ if( pUndo )
+ pUndo->InsertRow( *this, aBoxes, aTarget.mnAddLine );
+ else
+ InsertRow( pDoc, aBoxes, aTarget.mnAddLine, sal_True );
+
+ aTarget.moreLines( *this );
+ bClear = true;
+ }
+
+ // find mapping, if needed extend target table and/or selection
+ aTarget.assignBoxes( aCopyStruct );
+
+ {
+ // Change table formulas into relative representation
+ SwTableFmlUpdate aMsgHnt( &rCpyTbl );
+ aMsgHnt.eFlags = TBL_RELBOXNAME;
+ pCpyDoc->UpdateTblFlds( &aMsgHnt );
+ }
+
+ // delete frames
+ aFndBox.SetTableLines( *this );
+ if( bClear )
+ aFndBox.ClearLineBehind();
+ aFndBox.DelFrms( *this );
+
+ // copy boxes
+ aTarget.copyBoxes( rCpyTbl, *this, pUndo );
+
+ // adjust row span attributes accordingly
+
+ // make frames
+ aFndBox.MakeFrms( *this );
+
+ return sal_True;
+}
+
+// kopiere die Tabelle in diese.
+// Kopiere alle Boxen einer Line in entsprechenden Boxen. Der alte Inhalt
+// wird dabei geloescht.
+// Ist keine mehr vorhanden, kommt der restliche Inhalt in die letzte
+// Box einer "GrundLine".
+// Ist auch keine Line mehr vorhanden, -> auch in die letzte Box
+// einer "GrundLine"
+sal_Bool SwTable::InsTable( const SwTable& rCpyTbl, const SwNodeIndex& rSttBox,
+ SwUndoTblCpyTbl* pUndo )
+{
+ SetHTMLTableLayout( 0 ); // MIB 9.7.97: HTML-Layout loeschen
+
+ SwDoc* pDoc = GetFrmFmt()->GetDoc();
+
+ SwTableNode* pTblNd = pDoc->IsIdxInTbl( rSttBox );
+
+ // suche erstmal die Box, in die kopiert werden soll:
+ SwTableBox* pMyBox = (SwTableBox*)GetTblBox(
+ rSttBox.GetNode().FindTableBoxStartNode()->GetIndex() );
+
+ OSL_ENSURE( pMyBox, "Index steht nicht in dieser Tabelle in einer Box" );
+
+ // loesche erstmal die Frames der Tabelle
+ _FndBox aFndBox( 0, 0 );
+ aFndBox.DelFrms( pTblNd->GetTable() );
+
+ SwDoc* pCpyDoc = rCpyTbl.GetFrmFmt()->GetDoc();
+
+ {
+ // Tabellen-Formeln in die relative Darstellung umwandeln
+ SwTableFmlUpdate aMsgHnt( &rCpyTbl );
+ aMsgHnt.eFlags = TBL_RELBOXNAME;
+ pCpyDoc->UpdateTblFlds( &aMsgHnt );
+ }
+
+ SwTblNumFmtMerge aTNFM( *pCpyDoc, *pDoc );
+
+ sal_Bool bDelCntnt = sal_True;
+ const SwTableBox* pTmp;
+
+ for( sal_uInt16 nLines = 0; nLines < rCpyTbl.GetTabLines().Count(); ++nLines )
+ {
+ // hole die erste Box von der Copy-Line
+ const SwTableBox* pCpyBox = rCpyTbl.GetTabLines()[nLines]
+ ->GetTabBoxes()[0];
+ while( pCpyBox->GetTabLines().Count() )
+ pCpyBox = pCpyBox->GetTabLines()[0]->GetTabBoxes()[0];
+
+ do {
+ // kopiere erst den neuen und loeschen dann den alten Inhalt
+ // (keine leeren Section erzeugen, werden sonst geloescht!)
+ lcl_CpyBox( rCpyTbl, pCpyBox, *this, pMyBox, bDelCntnt, pUndo );
+
+ if( 0 == (pTmp = pCpyBox->FindNextBox( rCpyTbl, pCpyBox, sal_False )))
+ break; // es folgt keine weitere Box mehr
+ pCpyBox = pTmp;
+
+ if( 0 == ( pTmp = pMyBox->FindNextBox( *this, pMyBox, sal_False )))
+ bDelCntnt = sal_False; // kein Platz mehr ??
+ else
+ pMyBox = (SwTableBox*)pTmp;
+
+ } while( sal_True );
+
+ // suche die oberste Line
+ SwTableLine* pNxtLine = pMyBox->GetUpper();
+ while( pNxtLine->GetUpper() )
+ pNxtLine = pNxtLine->GetUpper()->GetUpper();
+ sal_uInt16 nPos = GetTabLines().C40_GETPOS( SwTableLine, pNxtLine );
+ // gibt es eine naechste ??
+ if( nPos + 1 >= GetTabLines().Count() )
+ bDelCntnt = sal_False; // es gibt keine, alles in die letzte Box
+ else
+ {
+ // suche die naechste "Inhaltstragende Box"
+ pNxtLine = GetTabLines()[ nPos+1 ];
+ pMyBox = pNxtLine->GetTabBoxes()[0];
+ while( pMyBox->GetTabLines().Count() )
+ pMyBox = pMyBox->GetTabLines()[0]->GetTabBoxes()[0];
+ bDelCntnt = sal_True;
+ }
+ }
+
+ aFndBox.MakeFrms( pTblNd->GetTable() ); // erzeuge die Frames neu
+ return sal_True;
+}
+
+sal_Bool SwTable::InsTable( const SwTable& rCpyTbl, const SwSelBoxes& rSelBoxes,
+ SwUndoTblCpyTbl* pUndo )
+{
+ OSL_ENSURE( rSelBoxes.Count(), "Missing selection" );
+
+ SetHTMLTableLayout( 0 ); // MIB 9.7.97: HTML-Layout loeschen
+
+ if( IsNewModel() || rCpyTbl.IsNewModel() )
+ return InsNewTable( rCpyTbl, rSelBoxes, pUndo );
+
+ OSL_ENSURE( !rCpyTbl.IsTblComplex(), "Table too complex" );
+
+ SwDoc* pDoc = GetFrmFmt()->GetDoc();
+ SwDoc* pCpyDoc = rCpyTbl.GetFrmFmt()->GetDoc();
+
+ SwTblNumFmtMerge aTNFM( *pCpyDoc, *pDoc );
+
+ SwTableBox *pTmpBox, *pSttBox = (SwTableBox*)rSelBoxes[0];
+
+ sal_uInt16 nLn, nBx;
+ _FndLine *pFLine, *pInsFLine = 0;
+ _FndBox aFndBox( 0, 0 );
+ // suche alle Boxen / Lines
+ {
+ _FndPara aPara( rSelBoxes, &aFndBox );
+ ((SwTableLines&)GetTabLines()).ForEach( &_FndLineCopyCol, &aPara );
+ }
+
+ // JP 06.09.96: Sonderfall - eine Box in der Tabelle -> in alle
+ // selektierten Boxen kopieren!
+ if( 1 != rCpyTbl.GetTabSortBoxes().Count() )
+ {
+ SwTableLine* pSttLine = pSttBox->GetUpper();
+ sal_uInt16 nSttBox = pSttLine->GetTabBoxes().C40_GETPOS( SwTableBox, pSttBox );
+ sal_uInt16 nSttLine = GetTabLines().C40_GETPOS( SwTableLine, pSttLine );
+ _FndBox* pFndBox;
+
+ sal_uInt16 nFndCnt = aFndBox.GetLines().Count();
+ if( !nFndCnt )
+ return sal_False;
+
+ // teste ob genug Platz fuer die einzelnen Lines und Boxen ist:
+ sal_uInt16 nTstLns = 0;
+ pFLine = aFndBox.GetLines()[ 0 ];
+ pSttLine = pFLine->GetLine();
+ nSttLine = GetTabLines().C40_GETPOS( SwTableLine, pSttLine );
+ // sind ueberhaupt soviele Zeilen vorhanden
+ if( 1 == nFndCnt )
+ {
+ // in der Tabelle noch genug Platz ??
+ if( (GetTabLines().Count() - nSttLine ) <
+ rCpyTbl.GetTabLines().Count() )
+ {
+ // sollte nicht mehr soviele Lines vorhanden sein, dann
+ // teste, ob man durch einfuegen neuer zum Ziel kommt. Aber
+ // nur wenn die SSelection eine Box umfasst !!
+ if( 1 < rSelBoxes.Count() )
+ return sal_False;
+
+ sal_uInt16 nNewLns = rCpyTbl.GetTabLines().Count() -
+ (GetTabLines().Count() - nSttLine );
+
+ // Dann teste mal ob die Anzahl der Boxen fuer die Lines reicht
+ SwTableLine* pLastLn = GetTabLines()[ GetTabLines().Count()-1 ];
+
+ pSttBox = pFLine->GetBoxes()[0]->GetBox();
+ nSttBox = pFLine->GetLine()->GetTabBoxes().C40_GETPOS( SwTableBox, pSttBox );
+ for( sal_uInt16 n = rCpyTbl.GetTabLines().Count() - nNewLns;
+ n < rCpyTbl.GetTabLines().Count(); ++n )
+ {
+ SwTableLine* pCpyLn = rCpyTbl.GetTabLines()[ n ];
+
+ if( pLastLn->GetTabBoxes().Count() < nSttBox ||
+ ( pLastLn->GetTabBoxes().Count() - nSttBox ) <
+ pCpyLn->GetTabBoxes().Count() )
+ return sal_False;
+
+ // Test auf Verschachtelungen
+ for( nBx = 0; nBx < pCpyLn->GetTabBoxes().Count(); ++nBx )
+ if( !( pTmpBox = pLastLn->GetTabBoxes()[ nSttBox + nBx ])
+ ->GetSttNd() )
+ return sal_False;
+ }
+ // es ist also Platz fuer das zu kopierende vorhanden, also
+ // fuege entsprechend neue Zeilen ein.
+ SwTableBox* pInsBox = pLastLn->GetTabBoxes()[ nSttBox ];
+ OSL_ENSURE( pInsBox && pInsBox->GetSttNd(),
+ "kein CntntBox oder steht nicht in dieser Tabelle" );
+ SwSelBoxes aBoxes;
+
+ if( pUndo
+ ? !pUndo->InsertRow( *this, SelLineFromBox( pInsBox,
+ aBoxes, sal_True ), nNewLns )
+ : !InsertRow( pDoc, SelLineFromBox( pInsBox,
+ aBoxes, sal_True ), nNewLns, sal_True ) )
+ return sal_False;
+ }
+
+ nTstLns = rCpyTbl.GetTabLines().Count(); // soviele Kopieren
+ }
+ else if( 0 == (nFndCnt % rCpyTbl.GetTabLines().Count()) )
+ nTstLns = nFndCnt;
+ else
+ return sal_False; // kein Platz fuer die Zeilen
+
+ for( nLn = 0; nLn < nTstLns; ++nLn )
+ {
+ // Zeilen sind genug vorhanden, dann ueberpruefe die Boxen
+ // je Zeile
+ pFLine = aFndBox.GetLines()[ nLn % nFndCnt ];
+ SwTableLine* pLine = pFLine->GetLine();
+ pSttBox = pFLine->GetBoxes()[0]->GetBox();
+ nSttBox = pLine->GetTabBoxes().C40_GETPOS( SwTableBox, pSttBox );
+ if( nLn >= nFndCnt )
+ {
+ // es sind im ClipBoard mehr Zeilen als selectiert wurden
+ pInsFLine = new _FndLine( GetTabLines()[ nSttLine + nLn ],
+ &aFndBox );
+ pLine = pInsFLine->GetLine();
+ }
+ SwTableLine* pCpyLn = rCpyTbl.GetTabLines()[ nLn %
+ rCpyTbl.GetTabLines().Count() ];
+
+ // zu wenig Zeilen selektiert ?
+ if( pInsFLine )
+ {
+ // eine neue Zeile wird in die FndBox eingefuegt,
+ if( pLine->GetTabBoxes().Count() < nSttBox ||
+ ( pLine->GetTabBoxes().Count() - nSttBox ) <
+ pFLine->GetBoxes().Count() )
+ return sal_False;
+
+ // Test auf Verschachtelungen
+ for( nBx = 0; nBx < pFLine->GetBoxes().Count(); ++nBx )
+ {
+ if( !( pTmpBox = pLine->GetTabBoxes()[ nSttBox + nBx ])
+ ->GetSttNd() )
+ return sal_False;
+ // wenn Ok, fuege die Box in die FndLine zu
+ pFndBox = new _FndBox( pTmpBox, pInsFLine );
+ pInsFLine->GetBoxes().C40_INSERT( _FndBox, pFndBox, nBx );
+ }
+ aFndBox.GetLines().C40_INSERT( _FndLine, pInsFLine, nLn );
+ }
+ else if( pFLine->GetBoxes().Count() == 1 )
+ {
+ if( pLine->GetTabBoxes().Count() < nSttBox ||
+ ( pLine->GetTabBoxes().Count() - nSttBox ) <
+ pCpyLn->GetTabBoxes().Count() )
+ return sal_False;
+
+ // Test auf Verschachtelungen
+ for( nBx = 0; nBx < pCpyLn->GetTabBoxes().Count(); ++nBx )
+ {
+ if( !( pTmpBox = pLine->GetTabBoxes()[ nSttBox + nBx ])
+ ->GetSttNd() )
+ return sal_False;
+ // wenn Ok, fuege die Box in die FndLine zu
+ if( nBx == pFLine->GetBoxes().Count() )
+ {
+ pFndBox = new _FndBox( pTmpBox, pFLine );
+ pFLine->GetBoxes().C40_INSERT( _FndBox, pFndBox, nBx );
+ }
+ }
+ }
+ else
+ {
+ // ueberpruefe die selektierten Boxen mit denen im Clipboard
+ // (n-Fach)
+ if( 0 != ( pFLine->GetBoxes().Count() %
+ pCpyLn->GetTabBoxes().Count() ))
+ return sal_False;
+
+ // Test auf Verschachtelungen
+ for( nBx = 0; nBx < pFLine->GetBoxes().Count(); ++nBx )
+ if( !pFLine->GetBoxes()[ nBx ]->GetBox()->GetSttNd() )
+ return sal_False;
+ }
+ }
+
+ if( !aFndBox.GetLines().Count() )
+ return sal_False;
+ }
+
+ {
+ // Tabellen-Formeln in die relative Darstellung umwandeln
+ SwTableFmlUpdate aMsgHnt( &rCpyTbl );
+ aMsgHnt.eFlags = TBL_RELBOXNAME;
+ pCpyDoc->UpdateTblFlds( &aMsgHnt );
+ }
+
+ // loesche die Frames
+ aFndBox.SetTableLines( *this );
+ aFndBox.DelFrms( *this );
+
+ if( 1 == rCpyTbl.GetTabSortBoxes().Count() )
+ {
+ SwTableBox *pTmpBx = rCpyTbl.GetTabSortBoxes()[0];
+ for( sal_uInt16 n = 0; n < rSelBoxes.Count(); ++n )
+ lcl_CpyBox( rCpyTbl, pTmpBx, *this,
+ (SwTableBox*)rSelBoxes[n], sal_True, pUndo );
+ }
+ else
+ for( nLn = 0; nLn < aFndBox.GetLines().Count(); ++nLn )
+ {
+ pFLine = aFndBox.GetLines()[ nLn ];
+ SwTableLine* pCpyLn = rCpyTbl.GetTabLines()[
+ nLn % rCpyTbl.GetTabLines().Count() ];
+ for( nBx = 0; nBx < pFLine->GetBoxes().Count(); ++nBx )
+ {
+ // Kopiere in pMyBox die pCpyBox
+ lcl_CpyBox( rCpyTbl, pCpyLn->GetTabBoxes()[
+ nBx % pCpyLn->GetTabBoxes().Count() ],
+ *this, pFLine->GetBoxes()[ nBx ]->GetBox(), sal_True, pUndo );
+ }
+ }
+
+ aFndBox.MakeFrms( *this );
+ return sal_True;
+}
+
+sal_Bool _FndCntntBox( const SwTableBox*& rpBox, void* pPara )
+{
+ SwTableBox* pBox = (SwTableBox*)rpBox;
+ if( rpBox->GetTabLines().Count() )
+ pBox->GetTabLines().ForEach( &_FndCntntLine, pPara );
+ else
+ ((SwSelBoxes*)pPara)->Insert( pBox );
+ return sal_True;
+}
+
+sal_Bool _FndCntntLine( const SwTableLine*& rpLine, void* pPara )
+{
+ ((SwTableLine*)rpLine)->GetTabBoxes().ForEach( &_FndCntntBox, pPara );
+ return sal_True;
+}
+
+// suche alle Inhaltstragenden-Boxen dieser Box
+SwSelBoxes& SwTable::SelLineFromBox( const SwTableBox* pBox,
+ SwSelBoxes& rBoxes, sal_Bool bToTop ) const
+{
+ SwTableLine* pLine = (SwTableLine*)pBox->GetUpper();
+ if( bToTop )
+ while( pLine->GetUpper() )
+ pLine = pLine->GetUpper()->GetUpper();
+
+ // alle alten loeschen
+ rBoxes.Remove( sal_uInt16(0), rBoxes.Count() );
+ pLine->GetTabBoxes().ForEach( &_FndCntntBox, &rBoxes );
+ return rBoxes;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/doc/tblrwcl.cxx b/sw/source/core/doc/tblrwcl.cxx
new file mode 100644
index 000000000000..5cdc3d5dc850
--- /dev/null
+++ b/sw/source/core/doc/tblrwcl.cxx
@@ -0,0 +1,4712 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+#include <com/sun/star/text/HoriOrientation.hpp>
+#include <com/sun/star/chart2/XChartDocument.hpp>
+#include <hintids.hxx>
+
+#define _ZFORLIST_DECLARE_TABLE
+#include <editeng/brshitem.hxx>
+#include <editeng/lrspitem.hxx>
+#include <editeng/protitem.hxx>
+#include <editeng/boxitem.hxx>
+#include <tools/fract.hxx>
+#include <fmtfsize.hxx>
+#include <fmtornt.hxx>
+#include <doc.hxx>
+#include <cntfrm.hxx>
+#include <tabfrm.hxx>
+#include <frmtool.hxx>
+#include <pam.hxx>
+#include <swtable.hxx>
+#include <ndtxt.hxx>
+#include <tblsel.hxx>
+#include <fldbas.hxx>
+#include <swundo.hxx>
+#include <rowfrm.hxx>
+#include <ddefld.hxx>
+#include <hints.hxx>
+#include <UndoTable.hxx>
+#include <cellatr.hxx>
+#include <mvsave.hxx>
+#include <swtblfmt.hxx>
+#include <swddetbl.hxx>
+#include <poolfmt.hxx>
+#include <tblrwcl.hxx>
+#include <unochart.hxx>
+#include <boost/shared_ptr.hpp>
+#include <switerator.hxx>
+
+using namespace com::sun::star;
+using namespace com::sun::star::uno;
+
+
+#define COLFUZZY 20
+#define ROWFUZZY 10
+
+using namespace ::com::sun::star;
+
+#if OSL_DEBUG_LEVEL > 2
+#define CHECK_TABLE(t) (t).CheckConsistency();
+#else
+#define CHECK_TABLE(t)
+#endif
+
+typedef SwTableLine* SwTableLinePtr;
+SV_DECL_PTRARR_SORT( SwSortTableLines, SwTableLinePtr, 16, 16 )
+SV_IMPL_PTRARR_SORT( SwSortTableLines, SwTableLinePtr );
+
+SV_IMPL_PTRARR( _SwShareBoxFmts, SwShareBoxFmt* )
+
+// fuers setzen der Frame-Formate an den Boxen reicht es, das aktuelle
+// im Array zu suchen. Ist es vorhanden, so gebe das neue zurueck
+struct _CpyTabFrm
+{
+ union {
+ SwTableBoxFmt *pFrmFmt; // fuer CopyCol
+ SwTwips nSize; // fuer DelCol
+ } Value;
+ SwTableBoxFmt *pNewFrmFmt;
+
+ _CpyTabFrm( SwTableBoxFmt* pAktFrmFmt ) : pNewFrmFmt( 0 )
+ { Value.pFrmFmt = pAktFrmFmt; }
+
+ _CpyTabFrm& operator=( const _CpyTabFrm& );
+
+ sal_Bool operator==( const _CpyTabFrm& rCpyTabFrm )
+ { return (sal_uLong)Value.nSize == (sal_uLong)rCpyTabFrm.Value.nSize; }
+ sal_Bool operator<( const _CpyTabFrm& rCpyTabFrm )
+ { return (sal_uLong)Value.nSize < (sal_uLong)rCpyTabFrm.Value.nSize; }
+};
+
+struct CR_SetBoxWidth
+{
+ SwSelBoxes aBoxes;
+ SwSortTableLines aLines;
+ SvUShorts aLinesWidth;
+ SwShareBoxFmts aShareFmts;
+ SwTableNode* pTblNd;
+ SwUndoTblNdsChg* pUndo;
+ SwTwips nDiff, nSide, nMaxSize, nLowerDiff;
+ TblChgMode nMode;
+ sal_uInt16 nTblWidth, nRemainWidth, nBoxWidth;
+ sal_Bool bBigger, bLeft, bSplittBox, bAnyBoxFnd;
+
+ CR_SetBoxWidth( sal_uInt16 eType, SwTwips nDif, SwTwips nSid, SwTwips nTblW,
+ SwTwips nMax, SwTableNode* pTNd )
+ : pTblNd( pTNd ),
+ nDiff( nDif ), nSide( nSid ), nMaxSize( nMax ), nLowerDiff( 0 ),
+ nTblWidth( (sal_uInt16)nTblW ), nRemainWidth( 0 ), nBoxWidth( 0 ),
+ bSplittBox( sal_False ), bAnyBoxFnd( sal_False )
+ {
+ bLeft = nsTblChgWidthHeightType::WH_COL_LEFT == ( eType & 0xff ) ||
+ nsTblChgWidthHeightType::WH_CELL_LEFT == ( eType & 0xff );
+ bBigger = 0 != (eType & nsTblChgWidthHeightType::WH_FLAG_BIGGER );
+ nMode = pTblNd->GetTable().GetTblChgMode();
+ }
+ CR_SetBoxWidth( const CR_SetBoxWidth& rCpy )
+ : pTblNd( rCpy.pTblNd ),
+ pUndo( rCpy.pUndo ),
+ nDiff( rCpy.nDiff ), nSide( rCpy.nSide ),
+ nMaxSize( rCpy.nMaxSize ), nLowerDiff( 0 ),
+ nMode( rCpy.nMode ), nTblWidth( rCpy.nTblWidth ),
+ nRemainWidth( rCpy.nRemainWidth ), nBoxWidth( nBoxWidth ),
+ bBigger( rCpy.bBigger ), bLeft( rCpy.bLeft ),
+ bSplittBox( rCpy.bSplittBox ), bAnyBoxFnd( rCpy.bAnyBoxFnd )
+ {
+ aLines.Insert( &rCpy.aLines );
+ aLinesWidth.Insert( &rCpy.aLinesWidth, 0 );
+ }
+
+ SwUndoTblNdsChg* CreateUndo( SwUndoId eUndoType )
+ {
+ return pUndo = new SwUndoTblNdsChg( eUndoType, aBoxes, *pTblNd );
+ }
+
+ void LoopClear()
+ {
+ nLowerDiff = 0; nRemainWidth = 0;
+ }
+
+ void AddBoxWidth( const SwTableBox& rBox, sal_uInt16 nWidth )
+ {
+ SwTableLinePtr p = (SwTableLine*)rBox.GetUpper();
+ sal_uInt16 nFndPos;
+ if( aLines.Insert( p, nFndPos ))
+ aLinesWidth.Insert( nWidth, nFndPos );
+ else
+ aLinesWidth[ nFndPos ] = aLinesWidth[ nFndPos ] + nWidth;
+ }
+
+ sal_uInt16 GetBoxWidth( const SwTableLine& rLn ) const
+ {
+ SwTableLinePtr p = (SwTableLine*)&rLn;
+ sal_uInt16 nFndPos;
+ if( aLines.Seek_Entry( p, &nFndPos ) )
+ nFndPos = aLinesWidth[ nFndPos ];
+ else
+ nFndPos = 0;
+ return nFndPos;
+ }
+};
+
+sal_Bool lcl_SetSelBoxWidth( SwTableLine* pLine, CR_SetBoxWidth& rParam,
+ SwTwips nDist, sal_Bool bCheck );
+sal_Bool lcl_SetOtherBoxWidth( SwTableLine* pLine, CR_SetBoxWidth& rParam,
+ SwTwips nDist, sal_Bool bCheck );
+sal_Bool lcl_InsSelBox( SwTableLine* pLine, CR_SetBoxWidth& rParam,
+ SwTwips nDist, sal_Bool bCheck );
+sal_Bool lcl_InsOtherBox( SwTableLine* pLine, CR_SetBoxWidth& rParam,
+ SwTwips nDist, sal_Bool bCheck );
+sal_Bool lcl_DelSelBox( SwTableLine* pLine, CR_SetBoxWidth& rParam,
+ SwTwips nDist, sal_Bool bCheck );
+sal_Bool lcl_DelOtherBox( SwTableLine* pLine, CR_SetBoxWidth& rParam,
+ SwTwips nDist, sal_Bool bCheck );
+
+typedef sal_Bool (*FN_lcl_SetBoxWidth)(SwTableLine*, CR_SetBoxWidth&, SwTwips, sal_Bool );
+
+#if OSL_DEBUG_LEVEL > 1
+
+void _CheckBoxWidth( const SwTableLine& rLine, SwTwips nSize );
+
+#define CHECKBOXWIDTH \
+ { \
+ SwTwips nSize = GetFrmFmt()->GetFrmSize().GetWidth(); \
+ for( sal_uInt16 nTmp = 0; nTmp < aLines.Count(); ++nTmp ) \
+ ::_CheckBoxWidth( *aLines[ nTmp ], nSize ); \
+ }
+
+#define CHECKTABLELAYOUT \
+ { \
+ for ( sal_uInt16 i = 0; i < GetTabLines().Count(); ++i ) \
+ { \
+ SwFrmFmt* pFmt = GetTabLines()[i]->GetFrmFmt(); \
+ SwIterator<SwRowFrm,SwFmt> aIter( *pFmt ); \
+ for (SwRowFrm* pFrm=aIter.First(); pFrm; pFrm=aIter.Next())\
+ { \
+ if ( pFrm->GetTabLine() == GetTabLines()[i] ) \
+ { \
+ OSL_ENSURE( pFrm->GetUpper()->IsTabFrm(), \
+ "Table layout does not match table structure" ); \
+ } \
+ } \
+ } \
+ }
+
+#else
+
+#define CHECKBOXWIDTH
+#define CHECKTABLELAYOUT
+
+#endif
+
+struct CR_SetLineHeight
+{
+ SwSelBoxes aBoxes;
+ SwShareBoxFmts aShareFmts;
+ SwTableNode* pTblNd;
+ SwUndoTblNdsChg* pUndo;
+ SwTwips nMaxSpace, nMaxHeight;
+ TblChgMode nMode;
+ sal_uInt16 nLines;
+ sal_Bool bBigger, bTop, bSplittBox, bAnyBoxFnd;
+
+ CR_SetLineHeight( sal_uInt16 eType, SwTableNode* pTNd )
+ : pTblNd( pTNd ), pUndo( 0 ),
+ nMaxSpace( 0 ), nMaxHeight( 0 ), nLines( 0 ),
+ bSplittBox( sal_False ), bAnyBoxFnd( sal_False )
+ {
+ bTop = nsTblChgWidthHeightType::WH_ROW_TOP == ( eType & 0xff ) || nsTblChgWidthHeightType::WH_CELL_TOP == ( eType & 0xff );
+ bBigger = 0 != (eType & nsTblChgWidthHeightType::WH_FLAG_BIGGER );
+ if( eType & nsTblChgWidthHeightType::WH_FLAG_INSDEL )
+ bBigger = !bBigger;
+ nMode = pTblNd->GetTable().GetTblChgMode();
+ }
+ CR_SetLineHeight( const CR_SetLineHeight& rCpy )
+ : pTblNd( rCpy.pTblNd ), pUndo( rCpy.pUndo ),
+ nMaxSpace( rCpy.nMaxSpace ), nMaxHeight( rCpy.nMaxHeight ),
+ nMode( rCpy.nMode ), nLines( rCpy.nLines ),
+ bBigger( rCpy.bBigger ), bTop( rCpy.bTop ),
+ bSplittBox( rCpy.bSplittBox ), bAnyBoxFnd( rCpy.bAnyBoxFnd )
+ {}
+
+ SwUndoTblNdsChg* CreateUndo( SwUndoId nUndoType )
+ {
+ return pUndo = new SwUndoTblNdsChg( nUndoType, aBoxes, *pTblNd );
+ }
+};
+
+sal_Bool lcl_SetSelLineHeight( SwTableLine* pLine, CR_SetLineHeight& rParam,
+ SwTwips nDist, sal_Bool bCheck );
+sal_Bool lcl_SetOtherLineHeight( SwTableLine* pLine, CR_SetLineHeight& rParam,
+ SwTwips nDist, sal_Bool bCheck );
+sal_Bool lcl_InsDelSelLine( SwTableLine* pLine, CR_SetLineHeight& rParam,
+ SwTwips nDist, sal_Bool bCheck );
+
+typedef sal_Bool (*FN_lcl_SetLineHeight)(SwTableLine*, CR_SetLineHeight&, SwTwips, sal_Bool );
+
+_CpyTabFrm& _CpyTabFrm::operator=( const _CpyTabFrm& rCpyTabFrm )
+{
+ pNewFrmFmt = rCpyTabFrm.pNewFrmFmt;
+ Value = rCpyTabFrm.Value;
+ return *this;
+}
+
+SV_DECL_VARARR_SORT( _CpyTabFrms, _CpyTabFrm, 0, 50 )
+SV_IMPL_VARARR_SORT( _CpyTabFrms, _CpyTabFrm )
+
+void lcl_DelCpyTabFrmFmts( _CpyTabFrm& rArr );
+
+struct _CpyPara
+{
+ boost::shared_ptr< std::vector< std::vector< sal_uLong > > > pWidths;
+ SwDoc* pDoc;
+ SwTableNode* pTblNd;
+ _CpyTabFrms& rTabFrmArr;
+ SwTableLine* pInsLine;
+ SwTableBox* pInsBox;
+ sal_uLong nOldSize, nNewSize; // zum Korrigieren der Size-Attribute
+ sal_uLong nMinLeft, nMaxRight;
+ sal_uInt16 nCpyCnt, nInsPos;
+ sal_uInt16 nLnIdx, nBoxIdx;
+ sal_uInt8 nDelBorderFlag;
+ sal_Bool bCpyCntnt;
+
+ _CpyPara( SwTableNode* pNd, sal_uInt16 nCopies, _CpyTabFrms& rFrmArr,
+ sal_Bool bCopyContent = sal_True )
+ : pDoc( pNd->GetDoc() ), pTblNd( pNd ), rTabFrmArr(rFrmArr),
+ pInsLine(0), pInsBox(0), nOldSize(0), nNewSize(0),
+ nMinLeft(ULONG_MAX), nMaxRight(0),
+ nCpyCnt(nCopies), nInsPos(0),
+ nLnIdx(0), nBoxIdx(0),
+ nDelBorderFlag(0), bCpyCntnt( bCopyContent )
+ {}
+ _CpyPara( const _CpyPara& rPara, SwTableLine* pLine )
+ : pWidths( rPara.pWidths ), pDoc(rPara.pDoc), pTblNd(rPara.pTblNd),
+ rTabFrmArr(rPara.rTabFrmArr), pInsLine(pLine), pInsBox(rPara.pInsBox),
+ nOldSize(0), nNewSize(rPara.nNewSize), nMinLeft( rPara.nMinLeft ),
+ nMaxRight( rPara.nMaxRight ), nCpyCnt(rPara.nCpyCnt), nInsPos(0),
+ nLnIdx( rPara.nLnIdx), nBoxIdx( rPara.nBoxIdx ),
+ nDelBorderFlag( rPara.nDelBorderFlag ), bCpyCntnt( rPara.bCpyCntnt )
+ {}
+ _CpyPara( const _CpyPara& rPara, SwTableBox* pBox )
+ : pWidths( rPara.pWidths ), pDoc(rPara.pDoc), pTblNd(rPara.pTblNd),
+ rTabFrmArr(rPara.rTabFrmArr), pInsLine(rPara.pInsLine), pInsBox(pBox),
+ nOldSize(rPara.nOldSize), nNewSize(rPara.nNewSize),
+ nMinLeft( rPara.nMinLeft ), nMaxRight( rPara.nMaxRight ),
+ nCpyCnt(rPara.nCpyCnt), nInsPos(0), nLnIdx(rPara.nLnIdx), nBoxIdx(rPara.nBoxIdx),
+ nDelBorderFlag( rPara.nDelBorderFlag ), bCpyCntnt( rPara.bCpyCntnt )
+ {}
+ void SetBoxWidth( SwTableBox* pBox );
+};
+
+sal_Bool lcl_CopyCol( const _FndBox*& rpFndBox, void* pPara )
+{
+ _CpyPara* pCpyPara = (_CpyPara*)pPara;
+
+ // suche das FrmFmt im Array aller Frame-Formate
+ SwTableBox* pBox = (SwTableBox*)rpFndBox->GetBox();
+ _CpyTabFrm aFindFrm( (SwTableBoxFmt*)pBox->GetFrmFmt() );
+
+ sal_uInt16 nFndPos;
+ if( pCpyPara->nCpyCnt )
+ {
+ if( !pCpyPara->rTabFrmArr.Seek_Entry( aFindFrm, &nFndPos ))
+ {
+ // fuer das verschachtelte Kopieren sicher auch das neue Format
+ // als alt.
+ SwTableBoxFmt* pNewFmt = (SwTableBoxFmt*)pBox->ClaimFrmFmt();
+
+ // suche die selektierten Boxen in der Line:
+ _FndLine* pCmpLine = NULL;
+ SwFmtFrmSize aFrmSz( pNewFmt->GetFrmSize() );
+
+ bool bDiffCount = false;
+ if( pBox->GetTabLines().Count() )
+ {
+ pCmpLine = rpFndBox->GetLines()[ 0 ];
+ if ( pCmpLine->GetBoxes().Count() != pCmpLine->GetLine()->GetTabBoxes().Count() )
+ bDiffCount = true;
+ }
+
+ if( bDiffCount )
+ {
+ // die erste Line sollte reichen
+ _FndBoxes& rFndBoxes = pCmpLine->GetBoxes();
+ long nSz = 0;
+ for( sal_uInt16 n = rFndBoxes.Count(); n; )
+ nSz += rFndBoxes[ --n ]->GetBox()->GetFrmFmt()->GetFrmSize().GetWidth();
+ aFrmSz.SetWidth( aFrmSz.GetWidth() -
+ nSz / ( pCpyPara->nCpyCnt + 1 ) );
+ pNewFmt->SetFmtAttr( aFrmSz );
+ aFrmSz.SetWidth( nSz / ( pCpyPara->nCpyCnt + 1 ) );
+
+ // fuer die neue Box ein neues Format mit der Groesse anlegen!
+ aFindFrm.pNewFrmFmt = (SwTableBoxFmt*)pNewFmt->GetDoc()->
+ MakeTableLineFmt();
+ *aFindFrm.pNewFrmFmt = *pNewFmt;
+ aFindFrm.pNewFrmFmt->SetFmtAttr( aFrmSz );
+ }
+ else
+ {
+ aFrmSz.SetWidth( aFrmSz.GetWidth() / ( pCpyPara->nCpyCnt + 1 ) );
+ pNewFmt->SetFmtAttr( aFrmSz );
+
+ aFindFrm.pNewFrmFmt = pNewFmt;
+ pCpyPara->rTabFrmArr.Insert( aFindFrm );
+ aFindFrm.Value.pFrmFmt = pNewFmt;
+ pCpyPara->rTabFrmArr.Insert( aFindFrm );
+ }
+ }
+ else
+ {
+ aFindFrm = pCpyPara->rTabFrmArr[ nFndPos ];
+ pBox->ChgFrmFmt( (SwTableBoxFmt*)aFindFrm.pNewFrmFmt );
+ }
+ }
+ else
+ {
+ if( pCpyPara->nDelBorderFlag &&
+ pCpyPara->rTabFrmArr.Seek_Entry( aFindFrm, &nFndPos ))
+ aFindFrm = pCpyPara->rTabFrmArr[ nFndPos ];
+ else
+ aFindFrm.pNewFrmFmt = (SwTableBoxFmt*)pBox->GetFrmFmt();
+ }
+
+ if( rpFndBox->GetLines().Count() )
+ {
+ pBox = new SwTableBox( aFindFrm.pNewFrmFmt,
+ rpFndBox->GetLines().Count(), pCpyPara->pInsLine );
+ pCpyPara->pInsLine->GetTabBoxes().C40_INSERT( SwTableBox, pBox, pCpyPara->nInsPos++);
+ _CpyPara aPara( *pCpyPara, pBox );
+ aPara.nDelBorderFlag &= 7;
+
+ ((_FndBox*)rpFndBox)->GetLines().ForEach( &lcl_CopyRow, &aPara );
+ }
+ else
+ {
+ ::_InsTblBox( pCpyPara->pDoc, pCpyPara->pTblNd, pCpyPara->pInsLine,
+ aFindFrm.pNewFrmFmt, pBox, pCpyPara->nInsPos++ );
+
+ const _FndBoxes& rFndBxs = rpFndBox->GetUpper()->GetBoxes();
+ if( 8 > pCpyPara->nDelBorderFlag
+ ? pCpyPara->nDelBorderFlag
+ : rpFndBox == rFndBxs[ rFndBxs.Count() - 1 ] )
+ {
+ const SvxBoxItem& rBoxItem = pBox->GetFrmFmt()->GetBox();
+ if( 8 > pCpyPara->nDelBorderFlag
+ ? rBoxItem.GetTop()
+ : rBoxItem.GetRight() )
+ {
+ aFindFrm.Value.pFrmFmt = (SwTableBoxFmt*)pBox->GetFrmFmt();
+
+ SvxBoxItem aNew( rBoxItem );
+ if( 8 > pCpyPara->nDelBorderFlag )
+ aNew.SetLine( 0, BOX_LINE_TOP );
+ else
+ aNew.SetLine( 0, BOX_LINE_RIGHT );
+
+ if( 1 == pCpyPara->nDelBorderFlag ||
+ 8 == pCpyPara->nDelBorderFlag )
+ {
+ // es wird dahinter kopiert, bei allen Boxen die
+ // TopBorderLine loeschen
+ pBox = pCpyPara->pInsLine->GetTabBoxes()[
+ pCpyPara->nInsPos - 1 ];
+ }
+
+ aFindFrm.pNewFrmFmt = (SwTableBoxFmt*)pBox->GetFrmFmt();
+
+ // ansonsten wird davor kopiert und die erste Line behaelt
+ // die TopLine und an der originalen wird sie entfernt
+ pBox->ClaimFrmFmt()->SetFmtAttr( aNew );
+
+ if( !pCpyPara->nCpyCnt )
+ pCpyPara->rTabFrmArr.Insert( aFindFrm );
+ }
+ }
+ }
+ return sal_True;
+}
+
+sal_Bool lcl_CopyRow( const _FndLine*& rpFndLine, void* pPara )
+{
+ _CpyPara* pCpyPara = (_CpyPara*)pPara;
+ SwTableLine* pNewLine = new SwTableLine(
+ (SwTableLineFmt*)rpFndLine->GetLine()->GetFrmFmt(),
+ rpFndLine->GetBoxes().Count(), pCpyPara->pInsBox );
+ if( pCpyPara->pInsBox )
+ {
+ pCpyPara->pInsBox->GetTabLines().C40_INSERT( SwTableLine, pNewLine, pCpyPara->nInsPos++ );
+ }
+ else
+ {
+ pCpyPara->pTblNd->GetTable().GetTabLines().C40_INSERT( SwTableLine, pNewLine,
+ pCpyPara->nInsPos++ );
+ }
+
+ _CpyPara aPara( *pCpyPara, pNewLine );
+ ((_FndLine*)rpFndLine)->GetBoxes().ForEach( &lcl_CopyCol, &aPara );
+
+ pCpyPara->nDelBorderFlag &= 0xf8;
+ return sal_True;
+}
+
+void lcl_InsCol( _FndLine* pFndLn, _CpyPara& rCpyPara, sal_uInt16 nCpyCnt,
+ sal_Bool bBehind )
+{
+ // Bug 29124: nicht nur in den Grundlines kopieren. Wenns geht, so weit
+ // runter wie moeglich.
+ _FndBox* pFBox;
+ if( 1 == pFndLn->GetBoxes().Count() &&
+ !( pFBox = pFndLn->GetBoxes()[ 0 ] )->GetBox()->GetSttNd() )
+ {
+ // eine Box mit mehreren Lines, also in diese Lines einfuegen
+ for( sal_uInt16 n = 0; n < pFBox->GetLines().Count(); ++n )
+ lcl_InsCol( pFBox->GetLines()[ n ], rCpyPara, nCpyCnt, bBehind );
+ }
+ else
+ {
+ rCpyPara.pInsLine = pFndLn->GetLine();
+ SwTableBox* pBox = pFndLn->GetBoxes()[ bBehind ?
+ pFndLn->GetBoxes().Count()-1 : 0 ]->GetBox();
+ rCpyPara.nInsPos = pFndLn->GetLine()->GetTabBoxes().C40_GETPOS( SwTableBox, pBox );
+ if( bBehind )
+ ++rCpyPara.nInsPos;
+
+ for( sal_uInt16 n = 0; n < nCpyCnt; ++n )
+ {
+ if( n + 1 == nCpyCnt && bBehind )
+ rCpyPara.nDelBorderFlag = 9;
+ else
+ rCpyPara.nDelBorderFlag = 8;
+ pFndLn->GetBoxes().ForEach( &lcl_CopyCol, &rCpyPara );
+ }
+ }
+}
+
+SwRowFrm* GetRowFrm( SwTableLine& rLine )
+{
+ SwIterator<SwRowFrm,SwFmt> aIter( *rLine.GetFrmFmt() );
+ for( SwRowFrm* pFrm = aIter.First(); pFrm; pFrm = aIter.Next() )
+ if( pFrm->GetTabLine() == &rLine )
+ return pFrm;
+ return 0;
+}
+
+sal_Bool SwTable::InsertCol( SwDoc* pDoc, const SwSelBoxes& rBoxes, sal_uInt16 nCnt, sal_Bool bBehind )
+{
+ OSL_ENSURE( rBoxes.Count() && nCnt, "keine gueltige Box-Liste" );
+ SwTableNode* pTblNd = (SwTableNode*)rBoxes[0]->GetSttNd()->FindTableNode();
+ if( !pTblNd )
+ return sal_False;
+
+ sal_Bool bRes = sal_True;
+ if( IsNewModel() )
+ bRes = NewInsertCol( pDoc, rBoxes, nCnt, bBehind );
+ else
+ {
+ // suche alle Boxen / Lines
+ _FndBox aFndBox( 0, 0 );
+ {
+ _FndPara aPara( rBoxes, &aFndBox );
+ GetTabLines().ForEach( &_FndLineCopyCol, &aPara );
+ }
+ if( !aFndBox.GetLines().Count() )
+ return sal_False;
+
+ SetHTMLTableLayout( 0 ); // MIB 9.7.97: HTML-Layout loeschen
+
+ //Lines fuer das Layout-Update herausuchen.
+ aFndBox.SetTableLines( *this );
+ aFndBox.DelFrms( *this );
+
+ // TL_CHART2: nothing to be done since chart2 currently does not want to
+ // get notified about new rows/cols.
+
+ _CpyTabFrms aTabFrmArr;
+ _CpyPara aCpyPara( pTblNd, nCnt, aTabFrmArr );
+
+ for( sal_uInt16 n = 0; n < aFndBox.GetLines().Count(); ++n )
+ lcl_InsCol( aFndBox.GetLines()[ n ], aCpyPara, nCnt, bBehind );
+
+ // dann raeume die Struktur dieser Line noch mal auf, generell alle
+ GCLines();
+
+ //Layout updaten
+ aFndBox.MakeFrms( *this );
+
+ CHECKBOXWIDTH;
+ CHECKTABLELAYOUT;
+ bRes = sal_True;
+ }
+
+ SwChartDataProvider *pPCD = pDoc->GetChartDataProvider();
+ if (pPCD && nCnt)
+ pPCD->AddRowCols( *this, rBoxes, nCnt, bBehind );
+ pDoc->UpdateCharts( GetFrmFmt()->GetName() );
+
+ return bRes;
+}
+
+sal_Bool SwTable::_InsertRow( SwDoc* pDoc, const SwSelBoxes& rBoxes,
+ sal_uInt16 nCnt, sal_Bool bBehind )
+{
+ OSL_ENSURE( pDoc && rBoxes.Count() && nCnt, "keine gueltige Box-Liste" );
+ SwTableNode* pTblNd = (SwTableNode*)rBoxes[0]->GetSttNd()->FindTableNode();
+ if( !pTblNd )
+ return sal_False;
+
+ // suche alle Boxen / Lines
+ _FndBox aFndBox( 0, 0 );
+ {
+ _FndPara aPara( rBoxes, &aFndBox );
+ GetTabLines().ForEach( &_FndLineCopyCol, &aPara );
+ }
+ if( !aFndBox.GetLines().Count() )
+ return sal_False;
+
+ SetHTMLTableLayout( 0 ); // MIB 9.7.97: HTML-Layout loeschen
+
+ _FndBox* pFndBox = &aFndBox;
+ {
+ _FndLine* pFndLine;
+ while( 1 == pFndBox->GetLines().Count() &&
+ 1 == ( pFndLine = pFndBox->GetLines()[ 0 ])->GetBoxes().Count() )
+ {
+ // nicht zu weit runter, eine Line mit Boxen muss nachbleiben!!
+ _FndBox* pTmpBox = pFndLine->GetBoxes()[ 0 ];
+ if( pTmpBox->GetLines().Count() )
+ pFndBox = pTmpBox;
+ else
+ break;
+ }
+ }
+
+ //Lines fuer das Layout-Update herausuchen.
+ const sal_Bool bLayout = !IsNewModel() &&
+ 0 != SwIterator<SwTabFrm,SwFmt>::FirstElement( *GetFrmFmt() );
+
+ if ( bLayout )
+ {
+ aFndBox.SetTableLines( *this );
+ if( pFndBox != &aFndBox )
+ aFndBox.DelFrms( *this );
+ // TL_CHART2: nothing to be done since chart2 currently does not want to
+ // get notified about new rows/cols.
+ }
+
+ _CpyTabFrms aTabFrmArr;
+ _CpyPara aCpyPara( pTblNd, 0, aTabFrmArr );
+
+ SwTableLine* pLine = pFndBox->GetLines()[ bBehind ?
+ pFndBox->GetLines().Count()-1 : 0 ]->GetLine();
+ if( &aFndBox == pFndBox )
+ aCpyPara.nInsPos = GetTabLines().C40_GETPOS( SwTableLine, pLine );
+ else
+ {
+ aCpyPara.pInsBox = pFndBox->GetBox();
+ aCpyPara.nInsPos = pFndBox->GetBox()->GetTabLines().C40_GETPOS( SwTableLine, pLine );
+ }
+
+ if( bBehind )
+ {
+ ++aCpyPara.nInsPos;
+ aCpyPara.nDelBorderFlag = 1;
+ }
+ else
+ aCpyPara.nDelBorderFlag = 2;
+
+ for( sal_uInt16 nCpyCnt = 0; nCpyCnt < nCnt; ++nCpyCnt )
+ {
+ if( bBehind )
+ aCpyPara.nDelBorderFlag = 1;
+ pFndBox->GetLines().ForEach( &lcl_CopyRow, &aCpyPara );
+ }
+
+ // dann raeume die Struktur dieser Line noch mal auf, generell alle
+ if( !pDoc->IsInReading() )
+ GCLines();
+
+ //Layout updaten
+ if ( bLayout )
+ {
+ if( pFndBox != &aFndBox )
+ aFndBox.MakeFrms( *this );
+ else
+ aFndBox.MakeNewFrms( *this, nCnt, bBehind );
+ }
+
+ CHECKBOXWIDTH;
+ CHECKTABLELAYOUT;
+
+ SwChartDataProvider *pPCD = pDoc->GetChartDataProvider();
+ if (pPCD && nCnt)
+ pPCD->AddRowCols( *this, rBoxes, nCnt, bBehind );
+ pDoc->UpdateCharts( GetFrmFmt()->GetName() );
+
+ return sal_True;
+}
+
+sal_Bool _FndBoxAppendRowLine( const SwTableLine*& rpLine, void* pPara );
+
+sal_Bool _FndBoxAppendRowBox( const SwTableBox*& rpBox, void* pPara )
+{
+ _FndPara* pFndPara = (_FndPara*)pPara;
+ _FndBox* pFndBox = new _FndBox( (SwTableBox*)rpBox, pFndPara->pFndLine );
+ if( rpBox->GetTabLines().Count() )
+ {
+ _FndPara aPara( *pFndPara, pFndBox );
+ pFndBox->GetBox()->GetTabLines().ForEach( &_FndBoxAppendRowLine, &aPara );
+ if( !pFndBox->GetLines().Count() )
+ delete pFndBox;
+ }
+ else
+ pFndPara->pFndLine->GetBoxes().C40_INSERT( _FndBox, pFndBox,
+ pFndPara->pFndLine->GetBoxes().Count() );
+ return sal_True;
+}
+
+sal_Bool _FndBoxAppendRowLine( const SwTableLine*& rpLine, void* pPara )
+{
+ _FndPara* pFndPara = (_FndPara*)pPara;
+ _FndLine* pFndLine = new _FndLine( (SwTableLine*)rpLine, pFndPara->pFndBox );
+ _FndPara aPara( *pFndPara, pFndLine );
+ pFndLine->GetLine()->GetTabBoxes().ForEach( &_FndBoxAppendRowBox, &aPara );
+ if( pFndLine->GetBoxes().Count() )
+ {
+ pFndPara->pFndBox->GetLines().C40_INSERT( _FndLine, pFndLine,
+ pFndPara->pFndBox->GetLines().Count() );
+ }
+ else
+ delete pFndLine;
+ return sal_True;
+}
+
+sal_Bool SwTable::AppendRow( SwDoc* pDoc, sal_uInt16 nCnt )
+{
+ SwTableNode* pTblNd = (SwTableNode*)aSortCntBoxes[0]->GetSttNd()->FindTableNode();
+ if( !pTblNd )
+ return sal_False;
+
+ // suche alle Boxen / Lines
+ _FndBox aFndBox( 0, 0 );
+ {
+ const SwTableLine* pLLine = GetTabLines()[ GetTabLines().Count()-1 ];
+
+ const SwSelBoxes* pBxs = 0; // Dummy !!!
+ _FndPara aPara( *pBxs, &aFndBox );
+
+ _FndBoxAppendRowLine( pLLine, &aPara );
+ }
+ if( !aFndBox.GetLines().Count() )
+ return sal_False;
+
+ SetHTMLTableLayout( 0 ); // MIB 9.7.97: HTML-Layout loeschen
+
+ //Lines fuer das Layout-Update herausuchen.
+ bool bLayout = 0 != SwIterator<SwTabFrm,SwFmt>::FirstElement( *GetFrmFmt() );
+ if( bLayout )
+ {
+ aFndBox.SetTableLines( *this );
+ // TL_CHART2: nothing to be done since chart2 currently does not want to
+ // get notified about new rows/cols.
+ }
+
+ _CpyTabFrms aTabFrmArr;
+ _CpyPara aCpyPara( pTblNd, 0, aTabFrmArr );
+ aCpyPara.nInsPos = GetTabLines().Count();
+ aCpyPara.nDelBorderFlag = 1;
+
+ for( sal_uInt16 nCpyCnt = 0; nCpyCnt < nCnt; ++nCpyCnt )
+ {
+ aCpyPara.nDelBorderFlag = 1;
+ aFndBox.GetLines().ForEach( &lcl_CopyRow, &aCpyPara );
+ }
+
+ // dann raeume die Struktur dieser Line noch mal auf, generell alle
+ if( !pDoc->IsInReading() )
+ GCLines();
+
+ //Layout updaten
+ if ( bLayout )
+ {
+ aFndBox.MakeNewFrms( *this, nCnt, sal_True );
+ }
+ // TL_CHART2: need to inform chart of probably changed cell names
+ pDoc->UpdateCharts( GetFrmFmt()->GetName() );
+
+ CHECKBOXWIDTH;
+ CHECKTABLELAYOUT;
+
+ return sal_True;
+}
+
+void lcl_LastBoxSetWidth( SwTableBoxes &rBoxes, const long nOffset,
+ sal_Bool bFirst, SwShareBoxFmts& rShareFmts );
+
+void lcl_LastBoxSetWidthLine( SwTableLines &rLines, const long nOffset,
+ sal_Bool bFirst, SwShareBoxFmts& rShareFmts )
+{
+ for ( sal_uInt16 i = 0; i < rLines.Count(); ++i )
+ ::lcl_LastBoxSetWidth( rLines[i]->GetTabBoxes(), nOffset, bFirst,
+ rShareFmts );
+}
+
+void lcl_LastBoxSetWidth( SwTableBoxes &rBoxes, const long nOffset,
+ sal_Bool bFirst, SwShareBoxFmts& rShareFmts )
+{
+ SwTableBox& rBox = *rBoxes[ bFirst ? 0 : rBoxes.Count() - 1 ];
+ if( !rBox.GetSttNd() )
+ ::lcl_LastBoxSetWidthLine( rBox.GetTabLines(), nOffset,
+ bFirst, rShareFmts );
+
+ //Die Box anpassen
+ SwFrmFmt *pBoxFmt = rBox.GetFrmFmt();
+ SwFmtFrmSize aNew( pBoxFmt->GetFrmSize() );
+ aNew.SetWidth( aNew.GetWidth() + nOffset );
+ SwFrmFmt *pFmt = rShareFmts.GetFormat( *pBoxFmt, aNew );
+ if( pFmt )
+ rBox.ChgFrmFmt( (SwTableBoxFmt*)pFmt );
+ else
+ {
+ pFmt = rBox.ClaimFrmFmt();
+
+ pFmt->LockModify();
+ pFmt->SetFmtAttr( aNew );
+ pFmt->UnlockModify();
+
+ rShareFmts.AddFormat( *pBoxFmt, *pFmt );
+ }
+}
+
+void _DeleteBox( SwTable& rTbl, SwTableBox* pBox, SwUndo* pUndo,
+ sal_Bool bCalcNewSize, const sal_Bool bCorrBorder,
+ SwShareBoxFmts* pShareFmts )
+{
+ do {
+ SwTwips nBoxSz = bCalcNewSize ?
+ pBox->GetFrmFmt()->GetFrmSize().GetWidth() : 0;
+ SwTableLine* pLine = pBox->GetUpper();
+ SwTableBoxes& rTblBoxes = pLine->GetTabBoxes();
+ sal_uInt16 nDelPos = rTblBoxes.C40_GETPOS( SwTableBox, pBox );
+ SwTableBox* pUpperBox = pBox->GetUpper()->GetUpper();
+
+ // Sonderbehandlung fuer Umrandung:
+ if( bCorrBorder && 1 < rTblBoxes.Count() )
+ {
+ sal_Bool bChgd = sal_False;
+ const SvxBoxItem& rBoxItem = pBox->GetFrmFmt()->GetBox();
+
+ if( rBoxItem.GetLeft() || rBoxItem.GetRight() )
+ {
+ //JP 02.04.97: 1.Teil fuer Bug 36271
+ // zuerst die linken/rechten Kanten
+ if( nDelPos + 1 < rTblBoxes.Count() )
+ {
+ SwTableBox* pNxtBox = rTblBoxes[ nDelPos + 1 ];
+ const SvxBoxItem& rNxtBoxItem = pNxtBox->GetFrmFmt()->GetBox();
+
+ SwTableBox* pPrvBox = nDelPos ? rTblBoxes[ nDelPos - 1 ] : 0;
+
+ if( pNxtBox->GetSttNd() && !rNxtBoxItem.GetLeft() &&
+ ( !pPrvBox || !pPrvBox->GetFrmFmt()->GetBox().GetRight()) )
+ {
+ SvxBoxItem aTmp( rNxtBoxItem );
+ aTmp.SetLine( rBoxItem.GetLeft() ? rBoxItem.GetLeft()
+ : rBoxItem.GetRight(),
+ BOX_LINE_LEFT );
+ if( pShareFmts )
+ pShareFmts->SetAttr( *pNxtBox, aTmp );
+ else
+ pNxtBox->ClaimFrmFmt()->SetFmtAttr( aTmp );
+ bChgd = sal_True;
+ }
+ }
+ if( !bChgd && nDelPos )
+ {
+ SwTableBox* pPrvBox = rTblBoxes[ nDelPos - 1 ];
+ const SvxBoxItem& rPrvBoxItem = pPrvBox->GetFrmFmt()->GetBox();
+
+ SwTableBox* pNxtBox = nDelPos + 1 < rTblBoxes.Count()
+ ? rTblBoxes[ nDelPos + 1 ] : 0;
+
+ if( pPrvBox->GetSttNd() && !rPrvBoxItem.GetRight() &&
+ ( !pNxtBox || !pNxtBox->GetFrmFmt()->GetBox().GetLeft()) )
+ {
+ SvxBoxItem aTmp( rPrvBoxItem );
+ aTmp.SetLine( rBoxItem.GetLeft() ? rBoxItem.GetLeft()
+ : rBoxItem.GetRight(),
+ BOX_LINE_RIGHT );
+ if( pShareFmts )
+ pShareFmts->SetAttr( *pPrvBox, aTmp );
+ else
+ pPrvBox->ClaimFrmFmt()->SetFmtAttr( aTmp );
+ }
+ }
+ }
+
+ }
+
+ // erst die Box, dann die Nodes loeschen!!
+ SwStartNode* pSttNd = (SwStartNode*)pBox->GetSttNd();
+ if( pShareFmts )
+ pShareFmts->RemoveFormat( *rTblBoxes[ nDelPos ]->GetFrmFmt() );
+ rTblBoxes.DeleteAndDestroy( nDelPos );
+
+ if( pSttNd )
+ {
+ // ist das UndoObject zum speichern der Section vorbereitet?
+ if( pUndo && pUndo->IsDelBox() )
+ ((SwUndoTblNdsChg*)pUndo)->SaveSection( pSttNd );
+ else
+ pSttNd->GetDoc()->DeleteSection( pSttNd );
+ }
+
+ // auch die Zeile noch loeschen ??
+ if( rTblBoxes.Count() )
+ {
+ // dann passe noch die Frame-SSize an
+ sal_Bool bLastBox = nDelPos == rTblBoxes.Count();
+ if( bLastBox )
+ --nDelPos;
+ pBox = rTblBoxes[nDelPos];
+ if( bCalcNewSize )
+ {
+ SwFmtFrmSize aNew( pBox->GetFrmFmt()->GetFrmSize() );
+ aNew.SetWidth( aNew.GetWidth() + nBoxSz );
+ if( pShareFmts )
+ pShareFmts->SetSize( *pBox, aNew );
+ else
+ pBox->ClaimFrmFmt()->SetFmtAttr( aNew );
+
+ if( !pBox->GetSttNd() )
+ {
+ // dann muss es auch rekursiv in allen Zeilen, in allen
+ // Zellen erfolgen!
+ SwShareBoxFmts aShareFmts;
+ ::lcl_LastBoxSetWidthLine( pBox->GetTabLines(), nBoxSz,
+ !bLastBox,
+ pShareFmts ? *pShareFmts
+ : aShareFmts );
+ }
+ }
+ break; // nichts mehr loeschen
+ }
+ // loesche die Line aus Tabelle/Box
+ if( !pUpperBox )
+ {
+ // dann loesche auch noch die Line aus der Tabelle
+ nDelPos = rTbl.GetTabLines().C40_GETPOS( SwTableLine, pLine );
+ if( pShareFmts )
+ pShareFmts->RemoveFormat( *rTbl.GetTabLines()[ nDelPos ]->GetFrmFmt() );
+ rTbl.GetTabLines().DeleteAndDestroy( nDelPos );
+ break; // mehr kann nicht geloescht werden
+ }
+
+ // dann loesche auch noch die Line
+ pBox = pUpperBox;
+ nDelPos = pBox->GetTabLines().C40_GETPOS( SwTableLine, pLine );
+ if( pShareFmts )
+ pShareFmts->RemoveFormat( *pBox->GetTabLines()[ nDelPos ]->GetFrmFmt() );
+ pBox->GetTabLines().DeleteAndDestroy( nDelPos );
+ } while( !pBox->GetTabLines().Count() );
+}
+
+SwTableBox* lcl_FndNxtPrvDelBox( const SwTableLines& rTblLns,
+ SwTwips nBoxStt, SwTwips nBoxWidth,
+ sal_uInt16 nLinePos, sal_Bool bNxt,
+ SwSelBoxes* pAllDelBoxes, sal_uInt16* pCurPos )
+{
+ SwTableBox* pFndBox = 0;
+ do {
+ if( bNxt )
+ ++nLinePos;
+ else
+ --nLinePos;
+ SwTableLine* pLine = rTblLns[ nLinePos ];
+ SwTwips nFndBoxWidth = 0;
+ SwTwips nFndWidth = nBoxStt + nBoxWidth;
+ sal_uInt16 nBoxCnt = pLine->GetTabBoxes().Count();
+
+ pFndBox = pLine->GetTabBoxes()[ 0 ];
+ for( sal_uInt16 n = 0; 0 < nFndWidth && n < nBoxCnt; ++n )
+ {
+ pFndBox = pLine->GetTabBoxes()[ n ];
+ nFndWidth -= (nFndBoxWidth = pFndBox->GetFrmFmt()->
+ GetFrmSize().GetWidth());
+ }
+
+ // suche die erste ContentBox
+ while( !pFndBox->GetSttNd() )
+ {
+ const SwTableLines& rLowLns = pFndBox->GetTabLines();
+ if( bNxt )
+ pFndBox = rLowLns[ 0 ]->GetTabBoxes()[ 0 ];
+ else
+ pFndBox = rLowLns[ rLowLns.Count() - 1 ]->GetTabBoxes()[ 0 ];
+ }
+
+ if( Abs( nFndWidth ) > COLFUZZY ||
+ Abs( nBoxWidth - nFndBoxWidth ) > COLFUZZY )
+ pFndBox = 0;
+ else if( pAllDelBoxes )
+ {
+ // falls der Vorganger auch geloscht wird, ist nicht zu tun
+ sal_uInt16 nFndPos;
+ if( !pAllDelBoxes->Seek_Entry( pFndBox, &nFndPos ) )
+ break;
+
+ // sonst noch mal weitersuchen
+ // Die Box muessen wir aber nicht nochmal abpruefen
+ pFndBox = 0;
+ if( nFndPos <= *pCurPos )
+ --*pCurPos;
+ pAllDelBoxes->Remove( nFndPos );
+ }
+ } while( bNxt ? ( nLinePos + 1 < rTblLns.Count() ) : nLinePos );
+ return pFndBox;
+}
+
+void lcl_SaveUpperLowerBorder( SwTable& rTbl, const SwTableBox& rBox,
+ SwShareBoxFmts& rShareFmts,
+ SwSelBoxes* pAllDelBoxes = 0,
+ sal_uInt16* pCurPos = 0 )
+{
+//JP 16.04.97: 2.Teil fuer Bug 36271
+ sal_Bool bChgd = sal_False;
+ const SwTableLine* pLine = rBox.GetUpper();
+ const SwTableBoxes& rTblBoxes = pLine->GetTabBoxes();
+ const SwTableBox* pUpperBox = &rBox;
+ sal_uInt16 nDelPos = rTblBoxes.C40_GETPOS( SwTableBox, pUpperBox );
+ pUpperBox = rBox.GetUpper()->GetUpper();
+ const SvxBoxItem& rBoxItem = rBox.GetFrmFmt()->GetBox();
+
+ // dann die unteren/oberen Kanten
+ if( rBoxItem.GetTop() || rBoxItem.GetBottom() )
+ {
+ bChgd = sal_False;
+ const SwTableLines* pTblLns;
+ if( pUpperBox )
+ pTblLns = &pUpperBox->GetTabLines();
+ else
+ pTblLns = &rTbl.GetTabLines();
+
+ sal_uInt16 nLnPos = pTblLns->GetPos( pLine );
+
+ // bestimme die Attr.Position der akt. zu loeschenden Box
+ // und suche dann in der unteren / oberen Line die entspr.
+ // Gegenstuecke
+ SwTwips nBoxStt = 0;
+ for( sal_uInt16 n = 0; n < nDelPos; ++n )
+ nBoxStt += rTblBoxes[ n ]->GetFrmFmt()->GetFrmSize().GetWidth();
+ SwTwips nBoxWidth = rBox.GetFrmFmt()->GetFrmSize().GetWidth();
+
+ SwTableBox *pPrvBox = 0, *pNxtBox = 0;
+ if( nLnPos ) // Vorgaenger?
+ pPrvBox = ::lcl_FndNxtPrvDelBox( *pTblLns, nBoxStt, nBoxWidth,
+ nLnPos, sal_False, pAllDelBoxes, pCurPos );
+
+ if( nLnPos + 1 < pTblLns->Count() ) // Nachfolger?
+ pNxtBox = ::lcl_FndNxtPrvDelBox( *pTblLns, nBoxStt, nBoxWidth,
+ nLnPos, sal_True, pAllDelBoxes, pCurPos );
+
+ if( pNxtBox && pNxtBox->GetSttNd() )
+ {
+ const SvxBoxItem& rNxtBoxItem = pNxtBox->GetFrmFmt()->GetBox();
+ if( !rNxtBoxItem.GetTop() && ( !pPrvBox ||
+ !pPrvBox->GetFrmFmt()->GetBox().GetBottom()) )
+ {
+ SvxBoxItem aTmp( rNxtBoxItem );
+ aTmp.SetLine( rBoxItem.GetTop() ? rBoxItem.GetTop()
+ : rBoxItem.GetBottom(),
+ BOX_LINE_TOP );
+ rShareFmts.SetAttr( *pNxtBox, aTmp );
+ bChgd = sal_True;
+ }
+ }
+ if( !bChgd && pPrvBox && pPrvBox->GetSttNd() )
+ {
+ const SvxBoxItem& rPrvBoxItem = pPrvBox->GetFrmFmt()->GetBox();
+ if( !rPrvBoxItem.GetTop() && ( !pNxtBox ||
+ !pNxtBox->GetFrmFmt()->GetBox().GetTop()) )
+ {
+ SvxBoxItem aTmp( rPrvBoxItem );
+ aTmp.SetLine( rBoxItem.GetTop() ? rBoxItem.GetTop()
+ : rBoxItem.GetBottom(),
+ BOX_LINE_BOTTOM );
+ rShareFmts.SetAttr( *pPrvBox, aTmp );
+ }
+ }
+
+ }
+}
+
+sal_Bool SwTable::DeleteSel(
+ SwDoc* pDoc
+ ,
+ const SwSelBoxes& rBoxes,
+ const SwSelBoxes* pMerged, SwUndo* pUndo,
+ const sal_Bool bDelMakeFrms, const sal_Bool bCorrBorder )
+{
+ OSL_ENSURE( pDoc, "No doc?" );
+ SwTableNode* pTblNd = 0;
+ if( rBoxes.Count() )
+ {
+ pTblNd = (SwTableNode*)rBoxes[0]->GetSttNd()->FindTableNode();
+ if( !pTblNd )
+ return sal_False;
+ }
+
+ SetHTMLTableLayout( 0 ); // MIB 9.7.97: HTML-Layout loeschen
+
+ //Lines fuer das Layout-Update herausuchen.
+ _FndBox aFndBox( 0, 0 );
+ if ( bDelMakeFrms )
+ {
+ if( pMerged && pMerged->Count() )
+ aFndBox.SetTableLines( *pMerged, *this );
+ else if( rBoxes.Count() )
+ aFndBox.SetTableLines( rBoxes, *this );
+ aFndBox.DelFrms( *this );
+ }
+
+ SwShareBoxFmts aShareFmts;
+
+ // erst die Umrandung umsetzen, dann loeschen
+ if( bCorrBorder )
+ {
+ SwSelBoxes aBoxes;
+ aBoxes.Insert( &rBoxes );
+ for( sal_uInt16 n = 0; n < aBoxes.Count(); ++n )
+ ::lcl_SaveUpperLowerBorder( *this, *rBoxes[ n ], aShareFmts,
+ &aBoxes, &n );
+ }
+
+ PrepareDelBoxes( rBoxes );
+
+ SwChartDataProvider *pPCD = pDoc->GetChartDataProvider();
+ //
+ // delete boxes from last to first
+ for( sal_uInt16 n = 0; n < rBoxes.Count(); ++n )
+ {
+ sal_uInt16 nIdx = rBoxes.Count() - 1 - n;
+
+ // first adapt the data-sequence for chart if necessary
+ // (needed to move the implementation cursor properly to it's new
+ // position which can't be done properly if the cell is already gone)
+ if (pPCD && pTblNd)
+ pPCD->DeleteBox( &pTblNd->GetTable(), *rBoxes[nIdx] );
+
+ // ... then delete the boxes
+ _DeleteBox( *this, rBoxes[nIdx], pUndo, sal_True, bCorrBorder, &aShareFmts );
+ }
+
+ // dann raeume die Struktur aller Lines auf
+ GCLines();
+
+ if( bDelMakeFrms && aFndBox.AreLinesToRestore( *this ) )
+ aFndBox.MakeFrms( *this );
+
+ // TL_CHART2: now inform chart that sth has changed
+ pDoc->UpdateCharts( GetFrmFmt()->GetName() );
+
+ CHECKTABLELAYOUT;
+ CHECK_TABLE( *this );
+
+ return sal_True;
+}
+
+sal_Bool SwTable::OldSplitRow( SwDoc* pDoc, const SwSelBoxes& rBoxes, sal_uInt16 nCnt,
+ sal_Bool bSameHeight )
+{
+ OSL_ENSURE( pDoc && rBoxes.Count() && nCnt, "keine gueltigen Werte" );
+ SwTableNode* pTblNd = (SwTableNode*)rBoxes[0]->GetSttNd()->FindTableNode();
+ if( !pTblNd )
+ return sal_False;
+
+ // TL_CHART2: splitting/merging of a number of cells or rows will usually make
+ // the table to complex to be handled with chart.
+ // Thus we tell the charts to use their own data provider and forget about this table
+ pDoc->CreateChartInternalDataProviders( this );
+
+ SetHTMLTableLayout( 0 ); // MIB 9.7.97: HTML-Layout loeschen
+
+ // If the rows should get the same (min) height, we first have
+ // to store the old row heights before deleting the frames
+ long* pRowHeights = 0;
+ if ( bSameHeight )
+ {
+ pRowHeights = new long[ rBoxes.Count() ];
+ for( sal_uInt16 n = 0; n < rBoxes.Count(); ++n )
+ {
+ SwTableBox* pSelBox = *( rBoxes.GetData() + n );
+ const SwRowFrm* pRow = GetRowFrm( *pSelBox->GetUpper() );
+ OSL_ENSURE( pRow, "wo ist der Frm von der SwTableLine?" );
+ SWRECTFN( pRow )
+ pRowHeights[ n ] = (pRow->Frm().*fnRect->fnGetHeight)();
+ }
+ }
+
+ //Lines fuer das Layout-Update herausuchen.
+ _FndBox aFndBox( 0, 0 );
+ aFndBox.SetTableLines( rBoxes, *this );
+ aFndBox.DelFrms( *this );
+
+ for( sal_uInt16 n = 0; n < rBoxes.Count(); ++n )
+ {
+ SwTableBox* pSelBox = *( rBoxes.GetData() + n );
+ OSL_ENSURE( pSelBox, "Box steht nicht in der Tabelle" );
+
+ // dann fuege in die Box nCnt neue Zeilen ein
+ SwTableLine* pInsLine = pSelBox->GetUpper();
+ SwTableBoxFmt* pFrmFmt = (SwTableBoxFmt*)pSelBox->GetFrmFmt();
+
+ // Hoehe der Line beachten, gegebenenfalls neu setzen
+ SwFmtFrmSize aFSz( pInsLine->GetFrmFmt()->GetFrmSize() );
+ if ( bSameHeight && ATT_VAR_SIZE == aFSz.GetHeightSizeType() )
+ aFSz.SetHeightSizeType( ATT_MIN_SIZE );
+
+ sal_Bool bChgLineSz = 0 != aFSz.GetHeight() || bSameHeight;
+ if ( bChgLineSz )
+ aFSz.SetHeight( ( bSameHeight ? pRowHeights[ n ] : aFSz.GetHeight() ) /
+ (nCnt + 1) );
+
+ SwTableBox* pNewBox = new SwTableBox( pFrmFmt, nCnt, pInsLine );
+ sal_uInt16 nBoxPos = pInsLine->GetTabBoxes().C40_GETPOS( SwTableBox, pSelBox );
+ pInsLine->GetTabBoxes().Remove( nBoxPos ); // alte loeschen
+ pInsLine->GetTabBoxes().C40_INSERT( SwTableBox, pNewBox, nBoxPos );
+
+ // Hintergrund- / Rand Attribut loeschen
+ SwTableBox* pLastBox = pSelBox; // zum verteilen der TextNodes !!
+ // sollte Bereiche in der Box stehen, dann bleibt sie so bestehen
+ // !! FALLS DAS GEAENDERT WIRD MUSS DAS UNDO ANGEPASST WERDEN !!!
+ sal_Bool bMoveNodes = sal_True;
+ {
+ sal_uLong nSttNd = pLastBox->GetSttIdx() + 1,
+ nEndNd = pLastBox->GetSttNd()->EndOfSectionIndex();
+ while( nSttNd < nEndNd )
+ if( !pDoc->GetNodes()[ nSttNd++ ]->IsTxtNode() )
+ {
+ bMoveNodes = sal_False;
+ break;
+ }
+ }
+
+ SwTableBoxFmt* pCpyBoxFrmFmt = (SwTableBoxFmt*)pSelBox->GetFrmFmt();
+ sal_Bool bChkBorder = 0 != pCpyBoxFrmFmt->GetBox().GetTop();
+ if( bChkBorder )
+ pCpyBoxFrmFmt = (SwTableBoxFmt*)pSelBox->ClaimFrmFmt();
+
+ for( sal_uInt16 i = 0; i <= nCnt; ++i )
+ {
+ // also erstmal eine neue Linie in der neuen Box
+ SwTableLine* pNewLine = new SwTableLine(
+ (SwTableLineFmt*)pInsLine->GetFrmFmt(), 1, pNewBox );
+ if( bChgLineSz )
+ {
+ pNewLine->ClaimFrmFmt()->SetFmtAttr( aFSz );
+ }
+
+ pNewBox->GetTabLines().C40_INSERT( SwTableLine, pNewLine, i );
+ // dann eine neue Box in der Line
+ if( !i ) // haenge die originale Box ein
+ {
+ pSelBox->SetUpper( pNewLine );
+ pNewLine->GetTabBoxes().C40_INSERT( SwTableBox, pSelBox, 0 );
+ }
+ else
+ {
+ ::_InsTblBox( pDoc, pTblNd, pNewLine, pCpyBoxFrmFmt,
+ pLastBox, 0 );
+
+ if( bChkBorder )
+ {
+ pCpyBoxFrmFmt = (SwTableBoxFmt*)pNewLine->GetTabBoxes()[ 0 ]->ClaimFrmFmt();
+ SvxBoxItem aTmp( pCpyBoxFrmFmt->GetBox() );
+ aTmp.SetLine( 0, BOX_LINE_TOP );
+ pCpyBoxFrmFmt->SetFmtAttr( aTmp );
+ bChkBorder = sal_False;
+ }
+
+ if( bMoveNodes )
+ {
+ const SwNode* pEndNd = pLastBox->GetSttNd()->EndOfSectionNode();
+ if( pLastBox->GetSttIdx()+2 != pEndNd->GetIndex() )
+ {
+ // TextNodes verschieben
+ SwNodeRange aRg( *pLastBox->GetSttNd(), +2, *pEndNd );
+ pLastBox = pNewLine->GetTabBoxes()[0]; // neu setzen
+ SwNodeIndex aInsPos( *pLastBox->GetSttNd(), 1 );
+ pDoc->GetNodes()._MoveNodes(aRg, pDoc->GetNodes(), aInsPos, sal_False);
+ pDoc->GetNodes().Delete( aInsPos, 1 ); // den leeren noch loeschen
+ }
+ }
+ }
+ }
+ // in Boxen mit Lines darf es nur noch Size/Fillorder geben
+ pFrmFmt = (SwTableBoxFmt*)pNewBox->ClaimFrmFmt();
+ pFrmFmt->ResetFmtAttr( RES_LR_SPACE, RES_FRMATR_END - 1 );
+ pFrmFmt->ResetFmtAttr( RES_BOXATR_BEGIN, RES_BOXATR_END - 1 );
+ }
+
+ delete[] pRowHeights;
+
+ GCLines();
+
+ aFndBox.MakeFrms( *this );
+
+ CHECKBOXWIDTH
+ CHECKTABLELAYOUT
+ return sal_True;
+}
+
+sal_Bool SwTable::SplitCol( SwDoc* pDoc, const SwSelBoxes& rBoxes, sal_uInt16 nCnt )
+{
+ OSL_ENSURE( pDoc && rBoxes.Count() && nCnt, "keine gueltigen Werte" );
+ SwTableNode* pTblNd = (SwTableNode*)rBoxes[0]->GetSttNd()->FindTableNode();
+ if( !pTblNd )
+ return sal_False;
+
+ // TL_CHART2: splitting/merging of a number of cells or rows will usually make
+ // the table to complex to be handled with chart.
+ // Thus we tell the charts to use their own data provider and forget about this table
+ pDoc->CreateChartInternalDataProviders( this );
+
+ SetHTMLTableLayout( 0 ); // MIB 9.7.97: HTML-Layout loeschen
+ SwSelBoxes aSelBoxes;
+ aSelBoxes.Insert(rBoxes.GetData(), rBoxes.Count());
+ ExpandSelection( aSelBoxes );
+
+ //Lines fuer das Layout-Update herausuchen.
+ _FndBox aFndBox( 0, 0 );
+ aFndBox.SetTableLines( aSelBoxes, *this );
+ aFndBox.DelFrms( *this );
+
+ _CpyTabFrms aFrmArr;
+ SvPtrarr aLastBoxArr;
+ sal_uInt16 nFndPos;
+ for( sal_uInt16 n = 0; n < aSelBoxes.Count(); ++n )
+ {
+ SwTableBox* pSelBox = *( aSelBoxes.GetData() + n );
+ OSL_ENSURE( pSelBox, "Box steht nicht in der Tabelle" );
+
+ // We don't want to split small table cells into very very small cells
+ if( pSelBox->GetFrmFmt()->GetFrmSize().GetWidth()/( nCnt + 1 ) < 10 )
+ continue;
+
+ // dann teile die Box nCnt in nCnt Boxen
+ SwTableLine* pInsLine = pSelBox->GetUpper();
+ sal_uInt16 nBoxPos = pInsLine->GetTabBoxes().C40_GETPOS( SwTableBox, pSelBox );
+
+ // suche das FrmFmt im Array aller Frame-Formate
+ SwTableBoxFmt* pLastBoxFmt;
+ _CpyTabFrm aFindFrm( (SwTableBoxFmt*)pSelBox->GetFrmFmt() );
+ if( !aFrmArr.Seek_Entry( aFindFrm, &nFndPos ))
+ {
+ // aender das FrmFmt
+ aFindFrm.pNewFrmFmt = (SwTableBoxFmt*)pSelBox->ClaimFrmFmt();
+ SwTwips nBoxSz = aFindFrm.pNewFrmFmt->GetFrmSize().GetWidth();
+ SwTwips nNewBoxSz = nBoxSz / ( nCnt + 1 );
+ aFindFrm.pNewFrmFmt->SetFmtAttr( SwFmtFrmSize( ATT_VAR_SIZE,
+ nNewBoxSz, 0 ) );
+ aFrmArr.Insert( aFindFrm );
+
+ pLastBoxFmt = aFindFrm.pNewFrmFmt;
+ if( nBoxSz != ( nNewBoxSz * (nCnt + 1)))
+ {
+ // es bleibt ein Rest, also muss fuer die letzte Box ein
+ // eigenes Format definiert werden
+ pLastBoxFmt = new SwTableBoxFmt( *aFindFrm.pNewFrmFmt );
+ pLastBoxFmt->SetFmtAttr( SwFmtFrmSize( ATT_VAR_SIZE,
+ nBoxSz - ( nNewBoxSz * nCnt ), 0 ) );
+ }
+ void* p = pLastBoxFmt;
+ aLastBoxArr.Insert( p, nFndPos );
+ }
+ else
+ {
+ aFindFrm = aFrmArr[ nFndPos ];
+ pSelBox->ChgFrmFmt( (SwTableBoxFmt*)aFindFrm.pNewFrmFmt );
+ pLastBoxFmt = (SwTableBoxFmt*)aLastBoxArr[ nFndPos ];
+ }
+
+ // dann fuege mal an der Position die neuen Boxen ein
+ for( sal_uInt16 i = 1; i < nCnt; ++i )
+ ::_InsTblBox( pDoc, pTblNd, pInsLine, aFindFrm.pNewFrmFmt,
+ pSelBox, nBoxPos + i ); // dahinter einfuegen
+
+ ::_InsTblBox( pDoc, pTblNd, pInsLine, pLastBoxFmt,
+ pSelBox, nBoxPos + nCnt ); // dahinter einfuegen
+
+ // Sonderbehandlung fuer die Umrandung:
+ const SvxBoxItem& aSelBoxItem = aFindFrm.pNewFrmFmt->GetBox();
+ if( aSelBoxItem.GetRight() )
+ {
+ pInsLine->GetTabBoxes()[ nBoxPos + nCnt ]->ClaimFrmFmt();
+
+ SvxBoxItem aTmp( aSelBoxItem );
+ aTmp.SetLine( 0, BOX_LINE_RIGHT );
+ aFindFrm.pNewFrmFmt->SetFmtAttr( aTmp );
+
+ // und dann das Format aus dem "cache" entfernen
+ for( sal_uInt16 i = aFrmArr.Count(); i; )
+ {
+ const _CpyTabFrm& rCTF = aFrmArr[ --i ];
+ if( rCTF.pNewFrmFmt == aFindFrm.pNewFrmFmt ||
+ rCTF.Value.pFrmFmt == aFindFrm.pNewFrmFmt )
+ {
+ aFrmArr.Remove( i );
+ aLastBoxArr.Remove( i );
+ }
+ }
+ }
+ }
+
+ //Layout updaten
+ aFndBox.MakeFrms( *this );
+
+ CHECKBOXWIDTH
+ CHECKTABLELAYOUT
+ return sal_True;
+}
+
+/*
+ ----------------------- >> MERGE << ------------------------
+ Algorithmus:
+ ist in der _FndBox nur eine Line angegeben, nehme die Line
+ und teste die Anzahl der Boxen
+ - ist mehr als 1 Box angegeben, so wird auf Boxenebene zusammen-
+ gefasst, d.H. die neue Box wird so Breit wie die alten.
+ - Alle Lines die ueber/unter dem Bereich liegen werden in die
+ Box als Line + Box mit Lines eingefuegt
+ - Alle Lines die vor/hinter dem Bereich liegen werden in
+ die Boxen Left/Right eingetragen
+
+ ----------------------- >> MERGE << ------------------------
+*/
+void lcl_CpyLines( sal_uInt16 nStt, sal_uInt16 nEnd,
+ SwTableLines& rLines,
+ SwTableBox* pInsBox,
+ sal_uInt16 nPos = USHRT_MAX )
+{
+ for( sal_uInt16 n = nStt; n < nEnd; ++n )
+ rLines[n]->SetUpper( pInsBox );
+ if( USHRT_MAX == nPos )
+ nPos = pInsBox->GetTabLines().Count();
+ pInsBox->GetTabLines().Insert( &rLines, nPos, nStt, nEnd );
+ rLines.Remove( nStt, nEnd - nStt );
+}
+
+void lcl_CpyBoxes( sal_uInt16 nStt, sal_uInt16 nEnd,
+ SwTableBoxes& rBoxes,
+ SwTableLine* pInsLine,
+ sal_uInt16 nPos = USHRT_MAX )
+{
+ for( sal_uInt16 n = nStt; n < nEnd; ++n )
+ rBoxes[n]->SetUpper( pInsLine );
+ if( USHRT_MAX == nPos )
+ nPos = pInsLine->GetTabBoxes().Count();
+ pInsLine->GetTabBoxes().Insert( &rBoxes, nPos, nStt, nEnd );
+ rBoxes.Remove( nStt, nEnd - nStt );
+}
+
+void lcl_CalcWidth( SwTableBox* pBox )
+{
+ // Annahme: jede Line in der Box ist gleich gross
+ SwFrmFmt* pFmt = pBox->ClaimFrmFmt();
+ OSL_ENSURE( pBox->GetTabLines().Count(), "Box hat keine Lines" );
+
+ SwTableLine* pLine = pBox->GetTabLines()[0];
+ OSL_ENSURE( pLine, "Box steht in keiner Line" );
+
+ long nWidth = 0;
+ for( sal_uInt16 n = 0; n < pLine->GetTabBoxes().Count(); ++n )
+ nWidth += pLine->GetTabBoxes()[n]->GetFrmFmt()->GetFrmSize().GetWidth();
+
+ pFmt->SetFmtAttr( SwFmtFrmSize( ATT_VAR_SIZE, nWidth, 0 ));
+
+ // in Boxen mit Lines darf es nur noch Size/Fillorder geben
+ pFmt->ResetFmtAttr( RES_LR_SPACE, RES_FRMATR_END - 1 );
+ pFmt->ResetFmtAttr( RES_BOXATR_BEGIN, RES_BOXATR_END - 1 );
+}
+
+struct _InsULPara
+{
+ SwTableNode* pTblNd;
+ SwTableLine* pInsLine;
+ SwTableBox* pInsBox;
+ sal_Bool bUL_LR : 1; // Upper-Lower(sal_True) oder Left-Right(sal_False) ?
+ sal_Bool bUL : 1; // Upper-Left(sal_True) oder Lower-Right(sal_False) ?
+
+ SwTableBox* pLeftBox;
+ SwTableBox* pRightBox;
+ SwTableBox* pMergeBox;
+
+ _InsULPara( SwTableNode* pTNd, sal_Bool bUpperLower, sal_Bool bUpper,
+ SwTableBox* pLeft, SwTableBox* pMerge, SwTableBox* pRight,
+ SwTableLine* pLine=0, SwTableBox* pBox=0 )
+ : pTblNd( pTNd ), pInsLine( pLine ), pInsBox( pBox ),
+ pLeftBox( pLeft ), pRightBox( pRight ), pMergeBox( pMerge )
+ { bUL_LR = bUpperLower; bUL = bUpper; }
+
+ void SetLeft( SwTableBox* pBox=0 )
+ { bUL_LR = sal_False; bUL = sal_True; if( pBox ) pInsBox = pBox; }
+ void SetRight( SwTableBox* pBox=0 )
+ { bUL_LR = sal_False; bUL = sal_False; if( pBox ) pInsBox = pBox; }
+ void SetUpper( SwTableLine* pLine=0 )
+ { bUL_LR = sal_True; bUL = sal_True; if( pLine ) pInsLine = pLine; }
+ void SetLower( SwTableLine* pLine=0 )
+ { bUL_LR = sal_True; bUL = sal_False; if( pLine ) pInsLine = pLine; }
+};
+
+sal_Bool lcl_Merge_MoveBox( const _FndBox*& rpFndBox, void* pPara )
+{
+ _InsULPara* pULPara = (_InsULPara*)pPara;
+ SwTableBoxes* pBoxes;
+
+ sal_uInt16 nStt = 0, nEnd = rpFndBox->GetLines().Count();
+ sal_uInt16 nInsPos = USHRT_MAX;
+ if( !pULPara->bUL_LR ) // Left/Right
+ {
+ sal_uInt16 nPos;
+ SwTableBox* pFndBox = (SwTableBox*)rpFndBox->GetBox();
+ pBoxes = &pFndBox->GetUpper()->GetTabBoxes();
+ if( pULPara->bUL ) // Left ?
+ {
+ // gibt es noch davor Boxen, dann move sie
+ if( 0 != ( nPos = pBoxes->C40_GETPOS( SwTableBox, pFndBox )) )
+ lcl_CpyBoxes( 0, nPos, *pBoxes, pULPara->pInsLine );
+ }
+ else // Right
+ // gibt es noch dahinter Boxen, dann move sie
+ if( (nPos = pBoxes->C40_GETPOS( SwTableBox, pFndBox )) +1 < pBoxes->Count() )
+ {
+ nInsPos = pULPara->pInsLine->GetTabBoxes().Count();
+ lcl_CpyBoxes( nPos+1, pBoxes->Count(),
+ *pBoxes, pULPara->pInsLine );
+ }
+ }
+ // Upper/Lower und gehts noch tiefer ??
+ else if( rpFndBox->GetLines().Count() )
+ {
+ // suche nur die Line, ab der Verschoben werden muss
+ nStt = pULPara->bUL ? 0 : rpFndBox->GetLines().Count()-1;
+ nEnd = nStt+1;
+ }
+
+ pBoxes = &pULPara->pInsLine->GetTabBoxes();
+
+ // geht es noch eine weitere Stufe runter?
+ if( rpFndBox->GetBox()->GetTabLines().Count() )
+ {
+ SwTableBox* pBox = new SwTableBox(
+ (SwTableBoxFmt*)rpFndBox->GetBox()->GetFrmFmt(), 0, pULPara->pInsLine );
+ _InsULPara aPara( *pULPara );
+ aPara.pInsBox = pBox;
+ ((_FndBox*)rpFndBox)->GetLines().ForEach( nStt, nEnd,
+ &lcl_Merge_MoveLine, &aPara );
+ if( pBox->GetTabLines().Count() )
+ {
+ if( USHRT_MAX == nInsPos )
+ nInsPos = pBoxes->Count();
+ pBoxes->C40_INSERT( SwTableBox, pBox, nInsPos );
+ lcl_CalcWidth( pBox ); // bereche die Breite der Box
+ }
+ else
+ delete pBox;
+ }
+ return sal_True;
+}
+
+sal_Bool lcl_Merge_MoveLine( const _FndLine*& rpFndLine, void* pPara )
+{
+ _InsULPara* pULPara = (_InsULPara*)pPara;
+ SwTableLines* pLines;
+
+ sal_uInt16 nStt = 0, nEnd = rpFndLine->GetBoxes().Count();
+ sal_uInt16 nInsPos = USHRT_MAX;
+ if( pULPara->bUL_LR ) // UpperLower ?
+ {
+ sal_uInt16 nPos;
+ SwTableLine* pFndLn = (SwTableLine*)rpFndLine->GetLine();
+ pLines = pFndLn->GetUpper() ?
+ &pFndLn->GetUpper()->GetTabLines() :
+ &pULPara->pTblNd->GetTable().GetTabLines();
+
+ SwTableBox* pLBx = rpFndLine->GetBoxes()[0]->GetBox();
+ SwTableBox* pRBx = rpFndLine->GetBoxes()[
+ rpFndLine->GetBoxes().Count()-1]->GetBox();
+ sal_uInt16 nLeft = pFndLn->GetTabBoxes().C40_GETPOS( SwTableBox, pLBx );
+ sal_uInt16 nRight = pFndLn->GetTabBoxes().C40_GETPOS( SwTableBox, pRBx );
+
+ if( !nLeft || nRight == pFndLn->GetTabBoxes().Count() )
+ {
+ if( pULPara->bUL ) // Upper ?
+ {
+ // gibt es noch davor Zeilen, dann move sie
+ if( 0 != ( nPos = pLines->C40_GETPOS( SwTableLine, pFndLn )) )
+ lcl_CpyLines( 0, nPos, *pLines, pULPara->pInsBox );
+ }
+ else
+ // gibt es noch dahinter Zeilen, dann move sie
+ if( (nPos = pLines->C40_GETPOS( SwTableLine, pFndLn )) +1 < pLines->Count() )
+ {
+ nInsPos = pULPara->pInsBox->GetTabLines().Count();
+ lcl_CpyLines( nPos+1, pLines->Count(), *pLines,
+ pULPara->pInsBox );
+ }
+ }
+ else if( nLeft )
+ {
+ // es gibt links noch weitere Boxen, also setze Left-
+ // und Merge-Box in eine Box und Line, fuege davor/dahinter
+ // eine Line mit Box ein, in die die oberen/unteren Lines
+ // eingefuegt werden
+ SwTableLine* pInsLine = pULPara->pLeftBox->GetUpper();
+ SwTableBox* pLMBox = new SwTableBox(
+ (SwTableBoxFmt*)pULPara->pLeftBox->GetFrmFmt(), 0, pInsLine );
+ SwTableLine* pLMLn = new SwTableLine(
+ (SwTableLineFmt*)pInsLine->GetFrmFmt(), 2, pLMBox );
+ pLMLn->ClaimFrmFmt()->ResetFmtAttr( RES_FRM_SIZE );
+
+ pLMBox->GetTabLines().C40_INSERT( SwTableLine, pLMLn, 0 );
+
+ lcl_CpyBoxes( 0, 2, pInsLine->GetTabBoxes(), pLMLn );
+
+ pInsLine->GetTabBoxes().C40_INSERT( SwTableBox, pLMBox, 0 );
+
+ if( pULPara->bUL ) // Upper ?
+ {
+ // gibt es noch davor Zeilen, dann move sie
+ if( 0 != ( nPos = pLines->C40_GETPOS( SwTableLine, pFndLn )) )
+ lcl_CpyLines( 0, nPos, *pLines, pLMBox, 0 );
+ }
+ else
+ // gibt es noch dahinter Zeilen, dann move sie
+ if( (nPos = pLines->C40_GETPOS( SwTableLine, pFndLn )) +1 < pLines->Count() )
+ lcl_CpyLines( nPos+1, pLines->Count(), *pLines,
+ pLMBox );
+ lcl_CalcWidth( pLMBox ); // bereche die Breite der Box
+ }
+ else if( nRight+1 < pFndLn->GetTabBoxes().Count() )
+ {
+ // es gibt rechts noch weitere Boxen, also setze Right-
+ // und Merge-Box in eine Box und Line, fuege davor/dahinter
+ // eine Line mit Box ein, in die die oberen/unteren Lines
+ // eingefuegt werden
+ SwTableLine* pInsLine = pULPara->pRightBox->GetUpper();
+ SwTableBox* pRMBox;
+ if( pULPara->pLeftBox->GetUpper() == pInsLine )
+ {
+ pRMBox = new SwTableBox(
+ (SwTableBoxFmt*)pULPara->pRightBox->GetFrmFmt(), 0, pInsLine );
+ SwTableLine* pRMLn = new SwTableLine(
+ (SwTableLineFmt*)pInsLine->GetFrmFmt(), 2, pRMBox );
+ pRMLn->ClaimFrmFmt()->ResetFmtAttr( RES_FRM_SIZE );
+ pRMBox->GetTabLines().C40_INSERT( SwTableLine, pRMLn, 0 );
+
+ lcl_CpyBoxes( 1, 3, pInsLine->GetTabBoxes(), pRMLn );
+
+ pInsLine->GetTabBoxes().C40_INSERT( SwTableBox, pRMBox, 0 );
+ }
+ else
+ {
+ // Left und Merge wurden schon zusammengefuegt, also move
+ // Right auch mit in die Line
+
+ pInsLine = pULPara->pLeftBox->GetUpper();
+ sal_uInt16 nMvPos = pULPara->pRightBox->GetUpper()->GetTabBoxes().
+ C40_GETPOS( SwTableBox, pULPara->pRightBox );
+ lcl_CpyBoxes( nMvPos, nMvPos+1,
+ pULPara->pRightBox->GetUpper()->GetTabBoxes(),
+ pInsLine );
+ pRMBox = pInsLine->GetUpper();
+
+ // sind schon Lines vorhanden, dann muessen diese in eine
+ // neue Line und Box
+ nMvPos = pRMBox->GetTabLines().C40_GETPOS( SwTableLine, pInsLine );
+ if( pULPara->bUL ? nMvPos
+ : nMvPos+1 < pRMBox->GetTabLines().Count() )
+ {
+ // alle Lines zu einer neuen Line und Box zusammenfassen
+ SwTableLine* pNewLn = new SwTableLine(
+ (SwTableLineFmt*)pInsLine->GetFrmFmt(), 1, pRMBox );
+ pNewLn->ClaimFrmFmt()->ResetFmtAttr( RES_FRM_SIZE );
+ pRMBox->GetTabLines().C40_INSERT( SwTableLine, pNewLn,
+ pULPara->bUL ? nMvPos : nMvPos+1 );
+ pRMBox = new SwTableBox( (SwTableBoxFmt*)pRMBox->GetFrmFmt(), 0, pNewLn );
+ pNewLn->GetTabBoxes().C40_INSERT( SwTableBox, pRMBox, 0 );
+
+ sal_uInt16 nPos1, nPos2;
+ if( pULPara->bUL )
+ nPos1 = 0,
+ nPos2 = nMvPos;
+ else
+ nPos1 = nMvPos+2,
+ nPos2 = pNewLn->GetUpper()->GetTabLines().Count();
+
+ lcl_CpyLines( nPos1, nPos2,
+ pNewLn->GetUpper()->GetTabLines(), pRMBox );
+ lcl_CalcWidth( pRMBox ); // bereche die Breite der Box
+
+ pRMBox = new SwTableBox( (SwTableBoxFmt*)pRMBox->GetFrmFmt(), 0, pNewLn );
+ pNewLn->GetTabBoxes().C40_INSERT( SwTableBox, pRMBox,
+ pNewLn->GetTabBoxes().Count() );
+ }
+ }
+ if( pULPara->bUL ) // Upper ?
+ {
+ // gibt es noch davor Zeilen, dann move sie
+ if( 0 != ( nPos = pLines->C40_GETPOS( SwTableLine, pFndLn )) )
+ lcl_CpyLines( 0, nPos, *pLines, pRMBox, 0 );
+ }
+ else
+ // gibt es noch dahinter Zeilen, dann move sie
+ if( (nPos = pLines->C40_GETPOS( SwTableLine, pFndLn )) +1 < pLines->Count() )
+ lcl_CpyLines( nPos+1, pLines->Count(), *pLines,
+ pRMBox );
+ lcl_CalcWidth( pRMBox ); // bereche die Breite der Box
+ }
+ else {
+ OSL_FAIL( "Was denn nun" );
+ }
+ }
+ // Left/Right
+ else
+ {
+ // suche nur die Line, ab der Verschoben werden muss
+ nStt = pULPara->bUL ? 0 : rpFndLine->GetBoxes().Count()-1;
+ nEnd = nStt+1;
+ }
+ pLines = &pULPara->pInsBox->GetTabLines();
+
+ SwTableLine* pNewLine = new SwTableLine(
+ (SwTableLineFmt*)rpFndLine->GetLine()->GetFrmFmt(), 0, pULPara->pInsBox );
+ _InsULPara aPara( *pULPara ); // kopieren
+ aPara.pInsLine = pNewLine;
+ ((_FndLine*)rpFndLine)->GetBoxes().ForEach( nStt, nEnd,
+ &lcl_Merge_MoveBox, &aPara );
+ if( pNewLine->GetTabBoxes().Count() )
+ {
+ if( USHRT_MAX == nInsPos )
+ nInsPos = pLines->Count();
+ pLines->C40_INSERT( SwTableLine, pNewLine, nInsPos );
+ }
+ else
+ delete pNewLine;
+
+ return sal_True;
+}
+
+sal_Bool SwTable::OldMerge( SwDoc* pDoc, const SwSelBoxes& rBoxes,
+ SwTableBox* pMergeBox, SwUndoTblMerge* pUndo )
+{
+ OSL_ENSURE( rBoxes.Count() && pMergeBox, "keine gueltigen Werte" );
+ SwTableNode* pTblNd = (SwTableNode*)rBoxes[0]->GetSttNd()->FindTableNode();
+ if( !pTblNd )
+ return sal_False;
+
+ // suche alle Boxen / Lines
+ _FndBox aFndBox( 0, 0 );
+ {
+ _FndPara aPara( rBoxes, &aFndBox );
+ GetTabLines().ForEach( &_FndLineCopyCol, &aPara );
+ }
+ if( !aFndBox.GetLines().Count() )
+ return sal_False;
+
+ // TL_CHART2: splitting/merging of a number of cells or rows will usually make
+ // the table to complex to be handled with chart.
+ // Thus we tell the charts to use their own data provider and forget about this table
+ pDoc->CreateChartInternalDataProviders( this );
+
+ SetHTMLTableLayout( 0 ); // MIB 9.7.97: HTML-Layout loeschen
+
+ if( pUndo )
+ pUndo->SetSelBoxes( rBoxes );
+
+ //Lines fuer das Layout-Update herausuchen.
+ aFndBox.SetTableLines( *this );
+ aFndBox.DelFrms( *this );
+
+ _FndBox* pFndBox = &aFndBox;
+ while( 1 == pFndBox->GetLines().Count() &&
+ 1 == pFndBox->GetLines()[0]->GetBoxes().Count() )
+ pFndBox = pFndBox->GetLines()[0]->GetBoxes()[0];
+
+ SwTableLine* pInsLine = new SwTableLine(
+ (SwTableLineFmt*)pFndBox->GetLines()[0]->GetLine()->GetFrmFmt(), 0,
+ !pFndBox->GetUpper() ? 0 : pFndBox->GetBox() );
+ pInsLine->ClaimFrmFmt()->ResetFmtAttr( RES_FRM_SIZE );
+
+ // trage die neue Line ein
+ SwTableLines* pLines = pFndBox->GetUpper() ?
+ &pFndBox->GetBox()->GetTabLines() : &GetTabLines();
+
+ SwTableLine* pNewLine = pFndBox->GetLines()[0]->GetLine();
+ sal_uInt16 nInsPos = pLines->C40_GETPOS( SwTableLine, pNewLine );
+ pLines->C40_INSERT( SwTableLine, pInsLine, nInsPos );
+
+ SwTableBox* pLeftBox = new SwTableBox( (SwTableBoxFmt*)pMergeBox->GetFrmFmt(), 0, pInsLine );
+ SwTableBox* pRightBox = new SwTableBox( (SwTableBoxFmt*)pMergeBox->GetFrmFmt(), 0, pInsLine );
+ pMergeBox->SetUpper( pInsLine );
+ pInsLine->GetTabBoxes().C40_INSERT( SwTableBox, pLeftBox, 0 );
+ pLeftBox->ClaimFrmFmt();
+ pInsLine->GetTabBoxes().C40_INSERT( SwTableBox, pMergeBox, 1 );
+ pInsLine->GetTabBoxes().C40_INSERT( SwTableBox, pRightBox, 2 );
+ pRightBox->ClaimFrmFmt();
+
+ // in diese kommen alle Lines, die ueber dem selektierten Bereich stehen
+ // Sie bilden also eine Upper/Lower Line
+ _InsULPara aPara( pTblNd, sal_True, sal_True, pLeftBox, pMergeBox, pRightBox, pInsLine );
+
+ // move die oben/unten ueberhaengenden Lines vom selektierten Bereich
+ pFndBox->GetLines()[0]->GetBoxes().ForEach( &lcl_Merge_MoveBox,
+ &aPara );
+ aPara.SetLower( pInsLine );
+ sal_uInt16 nEnd = pFndBox->GetLines().Count()-1;
+ pFndBox->GetLines()[nEnd]->GetBoxes().ForEach( &lcl_Merge_MoveBox,
+ &aPara );
+
+ // move die links/rechts hereinreichenden Boxen vom selektierten Bereich
+ aPara.SetLeft( pLeftBox );
+ pFndBox->GetLines().ForEach( &lcl_Merge_MoveLine, &aPara );
+
+ aPara.SetRight( pRightBox );
+ pFndBox->GetLines().ForEach( &lcl_Merge_MoveLine, &aPara );
+
+ if( !pLeftBox->GetTabLines().Count() )
+ _DeleteBox( *this, pLeftBox, 0, sal_False, sal_False );
+ else
+ {
+ lcl_CalcWidth( pLeftBox ); // bereche die Breite der Box
+ if( pUndo && pLeftBox->GetSttNd() )
+ pUndo->AddNewBox( pLeftBox->GetSttIdx() );
+ }
+ if( !pRightBox->GetTabLines().Count() )
+ _DeleteBox( *this, pRightBox, 0, sal_False, sal_False );
+ else
+ {
+ lcl_CalcWidth( pRightBox ); // bereche die Breite der Box
+ if( pUndo && pRightBox->GetSttNd() )
+ pUndo->AddNewBox( pRightBox->GetSttIdx() );
+ }
+
+ DeleteSel( pDoc, rBoxes, 0, 0, sal_False, sal_False );
+
+ // dann raeume die Struktur dieser Line noch mal auf:
+ // generell alle Aufraeumen
+ GCLines();
+
+ GetTabLines()[0]->GetTabBoxes().ForEach( &lcl_BoxSetHeadCondColl, 0 );
+
+ aFndBox.MakeFrms( *this );
+
+ CHECKBOXWIDTH
+ CHECKTABLELAYOUT
+
+ return sal_True;
+}
+
+void lcl_CheckRowSpan( SwTable &rTbl )
+{
+ sal_uInt16 nLineCount = rTbl.GetTabLines().Count();
+ sal_uInt16 nMaxSpan = nLineCount;
+ long nMinSpan = 1;
+ while( nMaxSpan )
+ {
+ SwTableLine* pLine = rTbl.GetTabLines()[ nLineCount - nMaxSpan ];
+ for( sal_uInt16 nBox = 0; nBox < pLine->GetTabBoxes().Count(); ++nBox )
+ {
+ SwTableBox* pBox = pLine->GetTabBoxes()[nBox];
+ long nRowSpan = pBox->getRowSpan();
+ if( nRowSpan > nMaxSpan )
+ pBox->setRowSpan( nMaxSpan );
+ else if( nRowSpan < nMinSpan )
+ pBox->setRowSpan( nMinSpan > 0 ? nMaxSpan : nMinSpan );
+ }
+ --nMaxSpan;
+ nMinSpan = -nMaxSpan;
+ }
+}
+
+sal_uInt16 lcl_GetBoxOffset( const _FndBox& rBox )
+{
+ // suche die erste Box
+ const _FndBox* pFirstBox = &rBox;
+ while( pFirstBox->GetLines().Count() )
+ pFirstBox = pFirstBox->GetLines()[ 0 ]->GetBoxes()[ 0 ];
+
+ sal_uInt16 nRet = 0;
+ // dann ueber die Lines nach oben die Position bestimmen
+ const SwTableBox* pBox = pFirstBox->GetBox();
+ do {
+ const SwTableBoxes& rBoxes = pBox->GetUpper()->GetTabBoxes();
+ const SwTableBox* pCmp;
+ for( sal_uInt16 n = 0; pBox != ( pCmp = rBoxes[ n ] ); ++n )
+ nRet = nRet + (sal_uInt16) pCmp->GetFrmFmt()->GetFrmSize().GetWidth();
+ pBox = pBox->GetUpper()->GetUpper();
+ } while( pBox );
+ return nRet;
+}
+
+sal_uInt16 lcl_GetLineWidth( const _FndLine& rLine )
+{
+ sal_uInt16 nRet = 0;
+ for( sal_uInt16 n = rLine.GetBoxes().Count(); n; )
+ nRet = nRet + (sal_uInt16)rLine.GetBoxes()[ --n ]->GetBox()->GetFrmFmt()
+ ->GetFrmSize().GetWidth();
+ return nRet;
+}
+
+void lcl_CalcNewWidths( const _FndLines& rFndLines, _CpyPara& rPara )
+{
+ rPara.pWidths.reset();
+ sal_uInt16 nLineCount = rFndLines.Count();
+ if( nLineCount )
+ {
+ rPara.pWidths = boost::shared_ptr< std::vector< std::vector< sal_uLong > > >
+ ( new std::vector< std::vector< sal_uLong > >( nLineCount ));
+ // First we collect information about the left/right borders of all
+ // selected cells
+ for( sal_uInt16 nLine = 0; nLine < nLineCount; ++nLine )
+ {
+ std::vector< sal_uLong > &rWidth = (*rPara.pWidths.get())[ nLine ];
+ const _FndLine *pFndLine = rFndLines[ nLine ];
+ if( pFndLine && pFndLine->GetBoxes().Count() )
+ {
+ const SwTableLine *pLine = pFndLine->GetLine();
+ if( pLine && pLine->GetTabBoxes().Count() )
+ {
+ sal_uInt16 nBoxCount = pLine->GetTabBoxes().Count();
+ sal_uLong nPos = 0;
+ // The first selected box...
+ const SwTableBox *pSel = pFndLine->GetBoxes()[0]->GetBox();
+ sal_uInt16 nBox = 0;
+ // Sum up the width of all boxes before the first selected box
+ while( nBox < nBoxCount )
+ {
+ SwTableBox* pBox = pLine->GetTabBoxes()[nBox++];
+ if( pBox != pSel )
+ nPos += pBox->GetFrmFmt()->GetFrmSize().GetWidth();
+ else
+ break;
+ }
+ // nPos is now the left border of the first selceted box
+ if( rPara.nMinLeft > nPos )
+ rPara.nMinLeft = nPos;
+ nBoxCount = pFndLine->GetBoxes().Count();
+ rWidth = std::vector< sal_uLong >( nBoxCount+2 );
+ rWidth[ 0 ] = nPos;
+ // Add now the widths of all selected boxes and store
+ // the positions in the vector
+ for( nBox = 0; nBox < nBoxCount; )
+ {
+ nPos += pFndLine->GetBoxes()[nBox]
+ ->GetBox()->GetFrmFmt()->GetFrmSize().GetWidth();
+ rWidth[ ++nBox ] = nPos;
+ }
+ // nPos: The right border of the last selected box
+ if( rPara.nMaxRight < nPos )
+ rPara.nMaxRight = nPos;
+ if( nPos <= rWidth[ 0 ] )
+ rWidth.clear();
+ }
+ }
+ }
+ }
+ // Second step: calculate the new widths for the copied cells
+ sal_uLong nSelSize = rPara.nMaxRight - rPara.nMinLeft;
+ if( nSelSize )
+ {
+ for( sal_uInt16 nLine = 0; nLine < nLineCount; ++nLine )
+ {
+ std::vector< sal_uLong > &rWidth = (*rPara.pWidths.get())[ nLine ];
+ sal_uInt16 nCount = (sal_uInt16)rWidth.size();
+ if( nCount > 2 )
+ {
+ rWidth[ nCount - 1 ] = rPara.nMaxRight;
+ sal_uLong nLastPos = 0;
+ for( sal_uInt16 nBox = 0; nBox < nCount; ++nBox )
+ {
+ sal_uInt64 nNextPos = rWidth[ nBox ];
+ nNextPos -= rPara.nMinLeft;
+ nNextPos *= rPara.nNewSize;
+ nNextPos /= nSelSize;
+ rWidth[ nBox ] = (sal_uLong)(nNextPos - nLastPos);
+ nLastPos = (sal_uLong)nNextPos;
+ }
+ }
+ }
+ }
+}
+
+sal_Bool lcl_CopyBoxToDoc( const _FndBox*& rpFndBox, void* pPara )
+{
+ _CpyPara* pCpyPara = (_CpyPara*)pPara;
+
+ // Calculation of new size
+ sal_uLong nRealSize;
+ sal_uLong nDummy1 = 0;
+ sal_uLong nDummy2 = 0;
+ if( pCpyPara->pTblNd->GetTable().IsNewModel() )
+ {
+ if( pCpyPara->nBoxIdx == 1 )
+ nDummy1 = (*pCpyPara->pWidths.get())[pCpyPara->nLnIdx][0];
+ nRealSize = (*pCpyPara->pWidths.get())[pCpyPara->nLnIdx][pCpyPara->nBoxIdx++];
+ if( pCpyPara->nBoxIdx == (*pCpyPara->pWidths.get())[pCpyPara->nLnIdx].size()-1 )
+ nDummy2 = (*pCpyPara->pWidths.get())[pCpyPara->nLnIdx][pCpyPara->nBoxIdx];
+ }
+ else
+ {
+ nRealSize = pCpyPara->nNewSize;
+ nRealSize *= rpFndBox->GetBox()->GetFrmFmt()->GetFrmSize().GetWidth();
+ nRealSize /= pCpyPara->nOldSize;
+ }
+
+ sal_uLong nSize;
+ bool bDummy = nDummy1 > 0;
+ if( bDummy )
+ nSize = nDummy1;
+ else
+ {
+ nSize = nRealSize;
+ nRealSize = 0;
+ }
+ do
+ {
+ // suche das Frame-Format in der Liste aller Frame-Formate
+ _CpyTabFrm aFindFrm( (SwTableBoxFmt*)rpFndBox->GetBox()->GetFrmFmt() );
+
+ SwFmtFrmSize aFrmSz;
+ sal_uInt16 nFndPos;
+ if( !pCpyPara->rTabFrmArr.Seek_Entry( aFindFrm, &nFndPos ) ||
+ ( aFrmSz = ( aFindFrm = pCpyPara->rTabFrmArr[ nFndPos ]).pNewFrmFmt->
+ GetFrmSize()).GetWidth() != (SwTwips)nSize )
+ {
+ // es ist noch nicht vorhanden, also kopiere es
+ aFindFrm.pNewFrmFmt = pCpyPara->pDoc->MakeTableBoxFmt();
+ aFindFrm.pNewFrmFmt->CopyAttrs( *rpFndBox->GetBox()->GetFrmFmt() );
+ if( !pCpyPara->bCpyCntnt )
+ aFindFrm.pNewFrmFmt->ResetFmtAttr( RES_BOXATR_FORMULA, RES_BOXATR_VALUE );
+ aFrmSz.SetWidth( nSize );
+ aFindFrm.pNewFrmFmt->SetFmtAttr( aFrmSz );
+ pCpyPara->rTabFrmArr.Insert( aFindFrm );
+ }
+
+ SwTableBox* pBox;
+ if( rpFndBox->GetLines().Count() )
+ {
+ pBox = new SwTableBox( aFindFrm.pNewFrmFmt,
+ rpFndBox->GetLines().Count(), pCpyPara->pInsLine );
+ pCpyPara->pInsLine->GetTabBoxes().C40_INSERT( SwTableBox, pBox, pCpyPara->nInsPos++ );
+ _CpyPara aPara( *pCpyPara, pBox );
+ aPara.nNewSize = nSize; // hole die Groesse
+ ((_FndBox*)rpFndBox)->GetLines().ForEach( &lcl_CopyLineToDoc, &aPara );
+ }
+ else
+ {
+ // erzeuge eine leere Box
+ pCpyPara->pDoc->GetNodes().InsBoxen( pCpyPara->pTblNd, pCpyPara->pInsLine,
+ aFindFrm.pNewFrmFmt,
+ (SwTxtFmtColl*)pCpyPara->pDoc->GetDfltTxtFmtColl(),
+ 0, pCpyPara->nInsPos );
+ pBox = pCpyPara->pInsLine->GetTabBoxes()[ pCpyPara->nInsPos ];
+ if( bDummy )
+ pBox->setDummyFlag( true );
+ else if( pCpyPara->bCpyCntnt )
+ {
+ // dann kopiere mal den Inhalt in diese leere Box
+ pBox->setRowSpan( rpFndBox->GetBox()->getRowSpan() );
+
+ // der Inhalt kopiert wird, dann koennen auch Formeln&Values
+ // kopiert werden.
+ {
+ SfxItemSet aBoxAttrSet( pCpyPara->pDoc->GetAttrPool(),
+ RES_BOXATR_FORMAT, RES_BOXATR_VALUE );
+ aBoxAttrSet.Put( rpFndBox->GetBox()->GetFrmFmt()->GetAttrSet() );
+ if( aBoxAttrSet.Count() )
+ {
+ const SfxPoolItem* pItem;
+ SvNumberFormatter* pN = pCpyPara->pDoc->GetNumberFormatter( sal_False );
+ if( pN && pN->HasMergeFmtTbl() && SFX_ITEM_SET == aBoxAttrSet.
+ GetItemState( RES_BOXATR_FORMAT, sal_False, &pItem ) )
+ {
+ sal_uLong nOldIdx = ((SwTblBoxNumFormat*)pItem)->GetValue();
+ sal_uLong nNewIdx = pN->GetMergeFmtIndex( nOldIdx );
+ if( nNewIdx != nOldIdx )
+ aBoxAttrSet.Put( SwTblBoxNumFormat( nNewIdx ));
+ }
+ pBox->ClaimFrmFmt()->SetFmtAttr( aBoxAttrSet );
+ }
+ }
+ SwDoc* pFromDoc = rpFndBox->GetBox()->GetFrmFmt()->GetDoc();
+ SwNodeRange aCpyRg( *rpFndBox->GetBox()->GetSttNd(), 1,
+ *rpFndBox->GetBox()->GetSttNd()->EndOfSectionNode() );
+ SwNodeIndex aInsIdx( *pBox->GetSttNd(), 1 );
+
+ pFromDoc->CopyWithFlyInFly( aCpyRg, 0, aInsIdx, sal_False );
+ // den initialen TextNode loeschen
+ pCpyPara->pDoc->GetNodes().Delete( aInsIdx, 1 );
+ }
+ ++pCpyPara->nInsPos;
+ }
+ if( nRealSize )
+ {
+ bDummy = false;
+ nSize = nRealSize;
+ nRealSize = 0;
+ }
+ else
+ {
+ bDummy = true;
+ nSize = nDummy2;
+ nDummy2 = 0;
+ }
+ }
+ while( nSize );
+ return sal_True;
+}
+
+sal_Bool lcl_CopyLineToDoc( const _FndLine*& rpFndLine, void* pPara )
+{
+ _CpyPara* pCpyPara = (_CpyPara*)pPara;
+
+ // suche das Format in der Liste aller Formate
+ _CpyTabFrm aFindFrm( (SwTableBoxFmt*)rpFndLine->GetLine()->GetFrmFmt() );
+ sal_uInt16 nFndPos;
+ if( !pCpyPara->rTabFrmArr.Seek_Entry( aFindFrm, &nFndPos ))
+ {
+ // es ist noch nicht vorhanden, also kopiere es
+ aFindFrm.pNewFrmFmt = (SwTableBoxFmt*)pCpyPara->pDoc->MakeTableLineFmt();
+ aFindFrm.pNewFrmFmt->CopyAttrs( *rpFndLine->GetLine()->GetFrmFmt() );
+ pCpyPara->rTabFrmArr.Insert( aFindFrm );
+ }
+ else
+ aFindFrm = pCpyPara->rTabFrmArr[ nFndPos ];
+
+ SwTableLine* pNewLine = new SwTableLine( (SwTableLineFmt*)aFindFrm.pNewFrmFmt,
+ rpFndLine->GetBoxes().Count(), pCpyPara->pInsBox );
+ if( pCpyPara->pInsBox )
+ {
+ pCpyPara->pInsBox->GetTabLines().C40_INSERT( SwTableLine, pNewLine, pCpyPara->nInsPos++ );
+ }
+ else
+ {
+ pCpyPara->pTblNd->GetTable().GetTabLines().C40_INSERT( SwTableLine, pNewLine,
+ pCpyPara->nInsPos++ );
+ }
+
+ _CpyPara aPara( *pCpyPara, pNewLine );
+
+ if( pCpyPara->pTblNd->GetTable().IsNewModel() )
+ {
+ aPara.nOldSize = 0; // will not be used
+ aPara.nBoxIdx = 1;
+ }
+ else if( rpFndLine->GetBoxes().Count() ==
+ rpFndLine->GetLine()->GetTabBoxes().Count() )
+ {
+ // hole die Size vom Parent
+ const SwFrmFmt* pFmt;
+
+ if( rpFndLine->GetLine()->GetUpper() )
+ pFmt = rpFndLine->GetLine()->GetUpper()->GetFrmFmt();
+ else
+ pFmt = pCpyPara->pTblNd->GetTable().GetFrmFmt();
+ aPara.nOldSize = pFmt->GetFrmSize().GetWidth();
+ }
+ else
+ // errechne sie
+ for( sal_uInt16 n = 0; n < rpFndLine->GetBoxes().Count(); ++n )
+ aPara.nOldSize += rpFndLine->GetBoxes()[n]
+ ->GetBox()->GetFrmFmt()->GetFrmSize().GetWidth();
+
+ ((_FndLine*)rpFndLine)->GetBoxes().ForEach( &lcl_CopyBoxToDoc, &aPara );
+ if( pCpyPara->pTblNd->GetTable().IsNewModel() )
+ ++pCpyPara->nLnIdx;
+ return sal_True;
+}
+
+sal_Bool SwTable::CopyHeadlineIntoTable( SwTableNode& rTblNd )
+{
+ // suche alle Boxen / Lines
+ SwSelBoxes aSelBoxes;
+ SwTableBox* pBox = GetTabSortBoxes()[ 0 ];
+ pBox = GetTblBox( pBox->GetSttNd()->StartOfSectionNode()->GetIndex() + 1 );
+ SelLineFromBox( pBox, aSelBoxes, sal_True );
+
+ _FndBox aFndBox( 0, 0 );
+ {
+ _FndPara aPara( aSelBoxes, &aFndBox );
+ ((SwTableLines&)GetTabLines()).ForEach( &_FndLineCopyCol, &aPara );
+ }
+ if( !aFndBox.GetLines().Count() )
+ return sal_False;
+
+ {
+ // Tabellen-Formeln in die relative Darstellung umwandeln
+ SwTableFmlUpdate aMsgHnt( this );
+ aMsgHnt.eFlags = TBL_RELBOXNAME;
+ GetFrmFmt()->GetDoc()->UpdateTblFlds( &aMsgHnt );
+ }
+
+ _CpyTabFrms aCpyFmt;
+ _CpyPara aPara( &rTblNd, 1, aCpyFmt, sal_True );
+ aPara.nNewSize = aPara.nOldSize = rTblNd.GetTable().GetFrmFmt()->GetFrmSize().GetWidth();
+ // dann kopiere mal
+ if( IsNewModel() )
+ lcl_CalcNewWidths( aFndBox.GetLines(), aPara );
+ aFndBox.GetLines().ForEach( &lcl_CopyLineToDoc, &aPara );
+ if( rTblNd.GetTable().IsNewModel() )
+ { // The copied line must not contain any row span attributes > 1
+ SwTableLine* pLine = rTblNd.GetTable().GetTabLines()[0];
+ sal_uInt16 nColCount = pLine->GetTabBoxes().Count();
+ OSL_ENSURE( nColCount, "Empty Table Line" );
+ for( sal_uInt16 nCurrCol = 0; nCurrCol < nColCount; ++nCurrCol )
+ {
+ SwTableBox* pTableBox = pLine->GetTabBoxes()[nCurrCol];
+ OSL_ENSURE( pTableBox, "Missing Table Box" );
+ pTableBox->setRowSpan( 1 );
+ }
+ }
+
+ return sal_True;
+}
+
+sal_Bool SwTable::MakeCopy( SwDoc* pInsDoc, const SwPosition& rPos,
+ const SwSelBoxes& rSelBoxes, sal_Bool bCpyNds,
+ sal_Bool bCpyName ) const
+{
+ // suche alle Boxen / Lines
+ _FndBox aFndBox( 0, 0 );
+ {
+ _FndPara aPara( rSelBoxes, &aFndBox );
+ ((SwTableLines&)GetTabLines()).ForEach( &_FndLineCopyCol, &aPara );
+ }
+ if( !aFndBox.GetLines().Count() )
+ return sal_False;
+
+ // erst die Poolvorlagen fuer die Tabelle kopieren, damit die dann
+ // wirklich kopiert und damit die gueltigen Werte haben.
+ SwDoc* pSrcDoc = GetFrmFmt()->GetDoc();
+ if( pSrcDoc != pInsDoc )
+ {
+ pInsDoc->CopyTxtColl( *pSrcDoc->GetTxtCollFromPool( RES_POOLCOLL_TABLE ) );
+ pInsDoc->CopyTxtColl( *pSrcDoc->GetTxtCollFromPool( RES_POOLCOLL_TABLE_HDLN ) );
+ }
+
+ SwTable* pNewTbl = (SwTable*)pInsDoc->InsertTable(
+ SwInsertTableOptions( tabopts::HEADLINE_NO_BORDER, 1 ),
+ rPos, 1, 1, GetFrmFmt()->GetHoriOrient().GetHoriOrient(),
+ 0, 0, sal_False, IsNewModel() );
+ if( !pNewTbl )
+ return sal_False;
+
+ SwNodeIndex aIdx( rPos.nNode, -1 );
+ SwTableNode* pTblNd = aIdx.GetNode().FindTableNode();
+ aIdx++;
+ OSL_ENSURE( pTblNd, "wo ist denn nun der TableNode?" );
+
+ pTblNd->GetTable().SetRowsToRepeat( GetRowsToRepeat() );
+
+ if( IS_TYPE( SwDDETable, this ))
+ {
+ // es wird eine DDE-Tabelle kopiert
+ // ist im neuen Dokument ueberhaupt der FeldTyp vorhanden ?
+ SwFieldType* pFldType = pInsDoc->InsertFldType(
+ *((SwDDETable*)this)->GetDDEFldType() );
+ OSL_ENSURE( pFldType, "unbekannter FieldType" );
+
+ // tauschen am Node den Tabellen-Pointer aus
+ pNewTbl = new SwDDETable( *pNewTbl,
+ (SwDDEFieldType*)pFldType );
+ pTblNd->SetNewTable( pNewTbl, sal_False );
+ }
+
+ pNewTbl->GetFrmFmt()->CopyAttrs( *GetFrmFmt() );
+ pNewTbl->SetTblChgMode( GetTblChgMode() );
+
+ //Vernichten der Frms die bereits angelegt wurden.
+ pTblNd->DelFrms();
+
+ {
+ // Tabellen-Formeln in die relative Darstellung umwandeln
+ SwTableFmlUpdate aMsgHnt( this );
+ aMsgHnt.eFlags = TBL_RELBOXNAME;
+ pSrcDoc->UpdateTblFlds( &aMsgHnt );
+ }
+
+ SwTblNumFmtMerge aTNFM( *pSrcDoc, *pInsDoc );
+
+ // Namen auch kopieren oder neuen eindeutigen erzeugen
+ if( bCpyName )
+ pNewTbl->GetFrmFmt()->SetName( GetFrmFmt()->GetName() );
+
+ _CpyTabFrms aCpyFmt;
+ _CpyPara aPara( pTblNd, 1, aCpyFmt, bCpyNds );
+ aPara.nNewSize = aPara.nOldSize = GetFrmFmt()->GetFrmSize().GetWidth();
+
+ if( IsNewModel() )
+ lcl_CalcNewWidths( aFndBox.GetLines(), aPara );
+ // dann kopiere mal
+ aFndBox.GetLines().ForEach( &lcl_CopyLineToDoc, &aPara );
+
+ // dann setze oben und unten noch die "richtigen" Raender:
+ {
+ _FndLine* pFndLn = aFndBox.GetLines()[ 0 ];
+ SwTableLine* pLn = pFndLn->GetLine();
+ const SwTableLine* pTmp = pLn;
+ sal_uInt16 nLnPos = GetTabLines().GetPos( pTmp );
+ if( USHRT_MAX != nLnPos && nLnPos )
+ {
+ // es gibt eine Line davor
+ SwCollectTblLineBoxes aLnPara( sal_False, HEADLINE_BORDERCOPY );
+
+ pLn = GetTabLines()[ nLnPos - 1 ];
+ pLn->GetTabBoxes().ForEach( &lcl_Box_CollectBox, &aLnPara );
+
+ if( aLnPara.Resize( lcl_GetBoxOffset( aFndBox ),
+ lcl_GetLineWidth( *pFndLn )) )
+ {
+ aLnPara.SetValues( sal_True );
+ pLn = pNewTbl->GetTabLines()[ 0 ];
+ pLn->GetTabBoxes().ForEach( &lcl_BoxSetSplitBoxFmts, &aLnPara );
+ }
+ }
+
+ pFndLn = aFndBox.GetLines()[ aFndBox.GetLines().Count() -1 ];
+ pLn = pFndLn->GetLine();
+ pTmp = pLn;
+ nLnPos = GetTabLines().GetPos( pTmp );
+ if( nLnPos < GetTabLines().Count() - 1 )
+ {
+ // es gibt eine Line dahinter
+ SwCollectTblLineBoxes aLnPara( sal_True, HEADLINE_BORDERCOPY );
+
+ pLn = GetTabLines()[ nLnPos + 1 ];
+ pLn->GetTabBoxes().ForEach( &lcl_Box_CollectBox, &aLnPara );
+
+ if( aLnPara.Resize( lcl_GetBoxOffset( aFndBox ),
+ lcl_GetLineWidth( *pFndLn )) )
+ {
+ aLnPara.SetValues( sal_False );
+ pLn = pNewTbl->GetTabLines()[ pNewTbl->GetTabLines().Count()-1 ];
+ pLn->GetTabBoxes().ForEach( &lcl_BoxSetSplitBoxFmts, &aLnPara );
+ }
+ }
+ }
+
+ // die initiale Box muss noch geloescht werden
+ _DeleteBox( *pNewTbl, pNewTbl->GetTabLines()[
+ pNewTbl->GetTabLines().Count() - 1 ]->GetTabBoxes()[0],
+ 0, sal_False, sal_False );
+
+ if( pNewTbl->IsNewModel() )
+ lcl_CheckRowSpan( *pNewTbl );
+ // Mal kurz aufraeumen:
+ pNewTbl->GCLines();
+
+ pTblNd->MakeFrms( &aIdx ); // erzeuge die Frames neu
+
+ CHECKTABLELAYOUT
+
+ return sal_True;
+}
+
+// suche ab dieser Line nach der naechsten Box mit Inhalt
+SwTableBox* SwTableLine::FindNextBox( const SwTable& rTbl,
+ const SwTableBox* pSrchBox, sal_Bool bOvrTblLns ) const
+{
+ const SwTableLine* pLine = this; // fuer M800
+ SwTableBox* pBox;
+ sal_uInt16 nFndPos;
+ if( GetTabBoxes().Count() && pSrchBox &&
+ USHRT_MAX != ( nFndPos = GetTabBoxes().GetPos( pSrchBox )) &&
+ nFndPos + 1 != GetTabBoxes().Count() )
+ {
+ pBox = GetTabBoxes()[ nFndPos + 1 ];
+ while( pBox->GetTabLines().Count() )
+ pBox = pBox->GetTabLines()[0]->GetTabBoxes()[0];
+ return pBox;
+ }
+
+ if( GetUpper() )
+ {
+ nFndPos = GetUpper()->GetTabLines().GetPos( pLine );
+ OSL_ENSURE( USHRT_MAX != nFndPos, "Line nicht in der Tabelle" );
+ // gibts eine weitere Line
+ if( nFndPos+1 >= GetUpper()->GetTabLines().Count() )
+ return GetUpper()->GetUpper()->FindNextBox( rTbl, GetUpper(), bOvrTblLns );
+ pLine = GetUpper()->GetTabLines()[nFndPos+1];
+ }
+ else if( bOvrTblLns ) // ueber die "GrundLines" einer Tabelle ?
+ {
+ // suche in der Tabelle nach der naechsten Line
+ nFndPos = rTbl.GetTabLines().GetPos( pLine );
+ if( nFndPos + 1 >= rTbl.GetTabLines().Count() )
+ return 0; // es gibt keine weitere Box mehr
+
+ pLine = rTbl.GetTabLines()[ nFndPos+1 ];
+ }
+ else
+ return 0;
+
+ if( pLine->GetTabBoxes().Count() )
+ {
+ pBox = pLine->GetTabBoxes()[0];
+ while( pBox->GetTabLines().Count() )
+ pBox = pBox->GetTabLines()[0]->GetTabBoxes()[0];
+ return pBox;
+ }
+ return pLine->FindNextBox( rTbl, 0, bOvrTblLns );
+}
+
+// suche ab dieser Line nach der vorherigen Box
+SwTableBox* SwTableLine::FindPreviousBox( const SwTable& rTbl,
+ const SwTableBox* pSrchBox, sal_Bool bOvrTblLns ) const
+{
+ const SwTableLine* pLine = this; // fuer M800
+ SwTableBox* pBox;
+ sal_uInt16 nFndPos;
+ if( GetTabBoxes().Count() && pSrchBox &&
+ USHRT_MAX != ( nFndPos = GetTabBoxes().GetPos( pSrchBox )) &&
+ nFndPos )
+ {
+ pBox = GetTabBoxes()[ nFndPos - 1 ];
+ while( pBox->GetTabLines().Count() )
+ {
+ pLine = pBox->GetTabLines()[pBox->GetTabLines().Count()-1];
+ pBox = pLine->GetTabBoxes()[pLine->GetTabBoxes().Count()-1];
+ }
+ return pBox;
+ }
+
+ if( GetUpper() )
+ {
+ nFndPos = GetUpper()->GetTabLines().GetPos( pLine );
+ OSL_ENSURE( USHRT_MAX != nFndPos, "Line nicht in der Tabelle" );
+ // gibts eine weitere Line
+ if( !nFndPos )
+ return GetUpper()->GetUpper()->FindPreviousBox( rTbl, GetUpper(), bOvrTblLns );
+ pLine = GetUpper()->GetTabLines()[nFndPos-1];
+ }
+ else if( bOvrTblLns ) // ueber die "GrundLines" einer Tabelle ?
+ {
+ // suche in der Tabelle nach der naechsten Line
+ nFndPos = rTbl.GetTabLines().GetPos( pLine );
+ if( !nFndPos )
+ return 0; // es gibt keine weitere Box mehr
+
+ pLine = rTbl.GetTabLines()[ nFndPos-1 ];
+ }
+ else
+ return 0;
+
+ if( pLine->GetTabBoxes().Count() )
+ {
+ pBox = pLine->GetTabBoxes()[pLine->GetTabBoxes().Count()-1];
+ while( pBox->GetTabLines().Count() )
+ {
+ pLine = pBox->GetTabLines()[pBox->GetTabLines().Count()-1];
+ pBox = pLine->GetTabBoxes()[pLine->GetTabBoxes().Count()-1];
+ }
+ return pBox;
+ }
+ return pLine->FindPreviousBox( rTbl, 0, bOvrTblLns );
+}
+
+// suche ab dieser Line nach der naechsten Box mit Inhalt
+SwTableBox* SwTableBox::FindNextBox( const SwTable& rTbl,
+ const SwTableBox* pSrchBox, sal_Bool bOvrTblLns ) const
+{
+ if( !pSrchBox && !GetTabLines().Count() )
+ return (SwTableBox*)this;
+ return GetUpper()->FindNextBox( rTbl, pSrchBox ? pSrchBox : this,
+ bOvrTblLns );
+
+}
+
+// suche ab dieser Line nach der naechsten Box mit Inhalt
+SwTableBox* SwTableBox::FindPreviousBox( const SwTable& rTbl,
+ const SwTableBox* pSrchBox, sal_Bool bOvrTblLns ) const
+{
+ if( !pSrchBox && !GetTabLines().Count() )
+ return (SwTableBox*)this;
+ return GetUpper()->FindPreviousBox( rTbl, pSrchBox ? pSrchBox : this,
+ bOvrTblLns );
+}
+
+sal_Bool lcl_BoxSetHeadCondColl( const SwTableBox*& rpBox, void* )
+{
+ // in der HeadLine sind die Absaetze mit BedingtenVorlage anzupassen
+ const SwStartNode* pSttNd = rpBox->GetSttNd();
+ if( pSttNd )
+ pSttNd->CheckSectionCondColl();
+ else
+ ((SwTableBox*)rpBox)->GetTabLines().ForEach( &lcl_LineSetHeadCondColl, 0 );
+ return sal_True;
+}
+
+sal_Bool lcl_LineSetHeadCondColl( const SwTableLine*& rpLine, void* )
+{
+ ((SwTableLine*)rpLine)->GetTabBoxes().ForEach( &lcl_BoxSetHeadCondColl, 0 );
+ return sal_True;
+}
+
+SwTwips lcl_GetDistance( SwTableBox* pBox, sal_Bool bLeft )
+{
+ sal_Bool bFirst = sal_True;
+ SwTwips nRet = 0;
+ SwTableLine* pLine;
+ while( pBox && 0 != ( pLine = pBox->GetUpper() ) )
+ {
+ sal_uInt16 nStt = 0, nPos = pLine->GetTabBoxes().C40_GETPOS( SwTableBox, pBox );
+
+ if( bFirst && !bLeft )
+ ++nPos;
+ bFirst = sal_False;
+
+ while( nStt < nPos )
+ nRet += pLine->GetTabBoxes()[ nStt++ ]->GetFrmFmt()
+ ->GetFrmSize().GetWidth();
+ pBox = pLine->GetUpper();
+ }
+ return nRet;
+}
+
+sal_Bool lcl_SetSelBoxWidth( SwTableLine* pLine, CR_SetBoxWidth& rParam,
+ SwTwips nDist, sal_Bool bCheck )
+{
+ SwTableBoxes& rBoxes = pLine->GetTabBoxes();
+ for( sal_uInt16 n = 0; n < rBoxes.Count(); ++n )
+ {
+ SwTableBox* pBox = rBoxes[ n ];
+ SwFrmFmt* pFmt = pBox->GetFrmFmt();
+ const SwFmtFrmSize& rSz = pFmt->GetFrmSize();
+ SwTwips nWidth = rSz.GetWidth();
+ sal_Bool bGreaterBox = sal_False;
+
+ if( bCheck )
+ {
+ for( sal_uInt16 i = 0; i < pBox->GetTabLines().Count(); ++i )
+ if( !::lcl_SetSelBoxWidth( pBox->GetTabLines()[ i ], rParam,
+ nDist, sal_True ))
+ return sal_False;
+
+ // dann noch mal alle "ContentBoxen" sammeln
+ if( ( 0 != ( bGreaterBox = TBLFIX_CHGABS != rParam.nMode && ( nDist + ( rParam.bLeft ? 0 : nWidth ) ) >= rParam.nSide)) ||
+ ( !rParam.bBigger && ( Abs( nDist + (( rParam.nMode && rParam.bLeft ) ? 0 : nWidth ) - rParam.nSide ) < COLFUZZY ) ) )
+ {
+ rParam.bAnyBoxFnd = sal_True;
+ SwTwips nLowerDiff;
+ if( bGreaterBox && TBLFIX_CHGPROP == rParam.nMode )
+ {
+ // die "anderen Boxen" wurden angepasst,
+ // also sich um diesen Betrag aendern
+ nLowerDiff = (nDist + ( rParam.bLeft ? 0 : nWidth ) ) - rParam.nSide;
+ nLowerDiff *= rParam.nDiff;
+ nLowerDiff /= rParam.nMaxSize;
+ nLowerDiff = rParam.nDiff - nLowerDiff;
+ }
+ else
+ nLowerDiff = rParam.nDiff;
+
+ if( nWidth < nLowerDiff || nWidth - nLowerDiff < MINLAY )
+ return sal_False;
+ }
+ }
+ else
+ {
+ SwTwips nLowerDiff = 0, nOldLower = rParam.nLowerDiff;
+ for( sal_uInt16 i = 0; i < pBox->GetTabLines().Count(); ++i )
+ {
+ rParam.nLowerDiff = 0;
+ lcl_SetSelBoxWidth( pBox->GetTabLines()[ i ], rParam, nDist, sal_False );
+
+ if( nLowerDiff < rParam.nLowerDiff )
+ nLowerDiff = rParam.nLowerDiff;
+ }
+ rParam.nLowerDiff = nOldLower;
+
+
+ if( nLowerDiff ||
+ ( 0 != ( bGreaterBox = !nOldLower && TBLFIX_CHGABS != rParam.nMode &&
+ ( nDist + ( rParam.bLeft ? 0 : nWidth ) ) >= rParam.nSide)) ||
+ ( Abs( nDist + ( (rParam.nMode && rParam.bLeft) ? 0 : nWidth )
+ - rParam.nSide ) < COLFUZZY ))
+ {
+ // in dieser Spalte ist der Cursor - also verkleinern / vergroessern
+ SwFmtFrmSize aNew( rSz );
+
+ if( !nLowerDiff )
+ {
+ if( bGreaterBox && TBLFIX_CHGPROP == rParam.nMode )
+ {
+ // die "anderen Boxen" wurden angepasst,
+ // also sich um diesen Betrag aendern
+ nLowerDiff = (nDist + ( rParam.bLeft ? 0 : nWidth ) ) - rParam.nSide;
+ nLowerDiff *= rParam.nDiff;
+ nLowerDiff /= rParam.nMaxSize;
+ nLowerDiff = rParam.nDiff - nLowerDiff;
+ }
+ else
+ nLowerDiff = rParam.nDiff;
+ }
+
+ rParam.nLowerDiff += nLowerDiff;
+
+ if( rParam.bBigger )
+ aNew.SetWidth( nWidth + nLowerDiff );
+ else
+ aNew.SetWidth( nWidth - nLowerDiff );
+ rParam.aShareFmts.SetSize( *pBox, aNew );
+ break;
+ }
+ }
+
+ if( rParam.bLeft && rParam.nMode && nDist >= rParam.nSide )
+ break;
+
+ nDist += nWidth;
+
+ // wenns groesser wird, dann wars das
+ if( ( TBLFIX_CHGABS == rParam.nMode || !rParam.bLeft ) &&
+ nDist >= rParam.nSide )
+ break;
+ }
+ return sal_True;
+}
+
+sal_Bool lcl_SetOtherBoxWidth( SwTableLine* pLine, CR_SetBoxWidth& rParam,
+ SwTwips nDist, sal_Bool bCheck )
+{
+ SwTableBoxes& rBoxes = pLine->GetTabBoxes();
+ for( sal_uInt16 n = 0; n < rBoxes.Count(); ++n )
+ {
+ SwTableBox* pBox = rBoxes[ n ];
+ SwFrmFmt* pFmt = pBox->GetFrmFmt();
+ const SwFmtFrmSize& rSz = pFmt->GetFrmSize();
+ SwTwips nWidth = rSz.GetWidth();
+
+ if( bCheck )
+ {
+ for( sal_uInt16 i = 0; i < pBox->GetTabLines().Count(); ++i )
+ if( !::lcl_SetOtherBoxWidth( pBox->GetTabLines()[ i ],
+ rParam, nDist, sal_True ))
+ return sal_False;
+
+ if( rParam.bBigger && ( TBLFIX_CHGABS == rParam.nMode
+ ? Abs( nDist - rParam.nSide ) < COLFUZZY
+ : ( rParam.bLeft ? nDist < rParam.nSide - COLFUZZY
+ : nDist >= rParam.nSide - COLFUZZY )) )
+ {
+ rParam.bAnyBoxFnd = sal_True;
+ SwTwips nDiff;
+ if( TBLFIX_CHGPROP == rParam.nMode ) // Tabelle fix, proport.
+ {
+ // relativ berechnen
+ nDiff = nWidth;
+ nDiff *= rParam.nDiff;
+ nDiff /= rParam.nMaxSize;
+ }
+ else
+ nDiff = rParam.nDiff;
+
+ if( nWidth < nDiff || nWidth - nDiff < MINLAY )
+ return sal_False;
+ }
+ }
+ else
+ {
+ SwTwips nLowerDiff = 0, nOldLower = rParam.nLowerDiff;
+ for( sal_uInt16 i = 0; i < pBox->GetTabLines().Count(); ++i )
+ {
+ rParam.nLowerDiff = 0;
+ lcl_SetOtherBoxWidth( pBox->GetTabLines()[ i ], rParam,
+ nDist, sal_False );
+
+ if( nLowerDiff < rParam.nLowerDiff )
+ nLowerDiff = rParam.nLowerDiff;
+ }
+ rParam.nLowerDiff = nOldLower;
+
+ if( nLowerDiff ||
+ ( TBLFIX_CHGABS == rParam.nMode
+ ? Abs( nDist - rParam.nSide ) < COLFUZZY
+ : ( rParam.bLeft ? nDist < rParam.nSide - COLFUZZY
+ : nDist >= rParam.nSide - COLFUZZY)
+ ) )
+ {
+ SwFmtFrmSize aNew( rSz );
+
+ if( !nLowerDiff )
+ {
+ if( TBLFIX_CHGPROP == rParam.nMode ) // Tabelle fix, proport.
+ {
+ // relativ berechnen
+ nLowerDiff = nWidth;
+ nLowerDiff *= rParam.nDiff;
+ nLowerDiff /= rParam.nMaxSize;
+ }
+ else
+ nLowerDiff = rParam.nDiff;
+ }
+
+ rParam.nLowerDiff += nLowerDiff;
+
+ if( rParam.bBigger )
+ aNew.SetWidth( nWidth - nLowerDiff );
+ else
+ aNew.SetWidth( nWidth + nLowerDiff );
+
+ rParam.aShareFmts.SetSize( *pBox, aNew );
+ }
+ }
+
+ nDist += nWidth;
+ if( ( TBLFIX_CHGABS == rParam.nMode || rParam.bLeft ) &&
+ nDist > rParam.nSide )
+ break;
+ }
+ return sal_True;
+}
+
+sal_Bool lcl_InsSelBox( SwTableLine* pLine, CR_SetBoxWidth& rParam,
+ SwTwips nDist, sal_Bool bCheck )
+{
+ SwTableBoxes& rBoxes = pLine->GetTabBoxes();
+ sal_uInt16 n, nCmp;
+ for( n = 0; n < rBoxes.Count(); ++n )
+ {
+ SwTableBox* pBox = rBoxes[ n ];
+ SwTableBoxFmt* pFmt = (SwTableBoxFmt*)pBox->GetFrmFmt();
+ const SwFmtFrmSize& rSz = pFmt->GetFrmSize();
+ SwTwips nWidth = rSz.GetWidth();
+
+ if( bCheck )
+ {
+ for( sal_uInt16 i = 0; i < pBox->GetTabLines().Count(); ++i )
+ if( !::lcl_InsSelBox( pBox->GetTabLines()[ i ], rParam,
+ nDist, sal_True ))
+ return sal_False;
+
+ // dann noch mal alle "ContentBoxen" sammeln
+ if( Abs( nDist + ( rParam.bLeft ? 0 : nWidth )
+ - rParam.nSide ) < COLFUZZY )
+ nCmp = 1;
+ else if( nDist + ( rParam.bLeft ? 0 : nWidth/2 ) > rParam.nSide )
+ nCmp = 2;
+ else
+ nCmp = 0;
+
+ if( nCmp )
+ {
+ rParam.bAnyBoxFnd = sal_True;
+ if( pFmt->GetProtect().IsCntntProtected() )
+ return sal_False;
+
+ if( rParam.bSplittBox &&
+ nWidth - rParam.nDiff <= COLFUZZY +
+ ( 567 / 2 /* min. 0,5 cm Platz lassen*/) )
+ return sal_False;
+
+ if( pBox->GetSttNd() )
+ rParam.aBoxes.Insert( pBox );
+
+ break;
+ }
+ }
+ else
+ {
+ SwTwips nLowerDiff = 0, nOldLower = rParam.nLowerDiff;
+ for( sal_uInt16 i = 0; i < pBox->GetTabLines().Count(); ++i )
+ {
+ rParam.nLowerDiff = 0;
+ lcl_InsSelBox( pBox->GetTabLines()[ i ], rParam, nDist, sal_False );
+
+ if( nLowerDiff < rParam.nLowerDiff )
+ nLowerDiff = rParam.nLowerDiff;
+ }
+ rParam.nLowerDiff = nOldLower;
+
+ if( nLowerDiff )
+ nCmp = 1;
+ else if( Abs( nDist + ( rParam.bLeft ? 0 : nWidth )
+ - rParam.nSide ) < COLFUZZY )
+ nCmp = 2;
+ else if( nDist + nWidth / 2 > rParam.nSide )
+ nCmp = 3;
+ else
+ nCmp = 0;
+
+ if( nCmp )
+ {
+ // in dieser Spalte ist der Cursor - also verkleinern / vergroessern
+ if( 1 == nCmp )
+ {
+ if( !rParam.bSplittBox )
+ {
+ // die akt. Box auf
+ SwFmtFrmSize aNew( rSz );
+ aNew.SetWidth( nWidth + rParam.nDiff );
+ rParam.aShareFmts.SetSize( *pBox, aNew );
+ }
+ }
+ else
+ {
+ OSL_ENSURE( pBox->GetSttNd(), "Das muss eine EndBox sein!");
+
+ if( !rParam.bLeft && 3 != nCmp )
+ ++n;
+
+ ::_InsTblBox( pFmt->GetDoc(), rParam.pTblNd,
+ pLine, pFmt, pBox, n );
+
+ SwTableBox* pNewBox = rBoxes[ n ];
+ SwFmtFrmSize aNew( rSz );
+ aNew.SetWidth( rParam.nDiff );
+ rParam.aShareFmts.SetSize( *pNewBox, aNew );
+
+ // Sonderfall: kein Platz in den anderen Boxen
+ // aber in der Zelle
+ if( rParam.bSplittBox )
+ {
+ // die akt. Box auf
+ SwFmtFrmSize aNewSize( rSz );
+ aNewSize.SetWidth( nWidth - rParam.nDiff );
+ rParam.aShareFmts.SetSize( *pBox, aNewSize );
+ }
+
+ // Sonderbehandlung fuer Umrandung die Rechte muss
+ // entfernt werden
+ {
+ const SvxBoxItem& rBoxItem = pBox->GetFrmFmt()->GetBox();
+ if( rBoxItem.GetRight() )
+ {
+ SvxBoxItem aTmp( rBoxItem );
+ aTmp.SetLine( 0, BOX_LINE_RIGHT );
+ rParam.aShareFmts.SetAttr( rParam.bLeft
+ ? *pNewBox
+ : *pBox, aTmp );
+ }
+ }
+ }
+
+ rParam.nLowerDiff = rParam.nDiff;
+ break;
+ }
+ }
+
+ if( rParam.bLeft && rParam.nMode && nDist >= rParam.nSide )
+ break;
+
+ nDist += nWidth;
+ }
+ return sal_True;
+}
+
+sal_Bool lcl_InsOtherBox( SwTableLine* pLine, CR_SetBoxWidth& rParam,
+ SwTwips nDist, sal_Bool bCheck )
+{
+ // Sonderfall: kein Platz in den anderen Boxen aber in der Zelle
+ if( rParam.bSplittBox )
+ return sal_True;
+
+ SwTableBoxes& rBoxes = pLine->GetTabBoxes();
+ sal_uInt16 n;
+
+ // Tabelle fix, proport.
+ if( !rParam.nRemainWidth && TBLFIX_CHGPROP == rParam.nMode )
+ {
+ // dann die richtige Breite suchen, auf die sich die relative
+ // Breitenanpassung bezieht.
+ SwTwips nTmpDist = nDist;
+ for( n = 0; n < rBoxes.Count(); ++n )
+ {
+ SwTwips nWidth = rBoxes[ n ]->GetFrmFmt()->GetFrmSize().GetWidth();
+ if( (nTmpDist + nWidth / 2 ) > rParam.nSide )
+ {
+ rParam.nRemainWidth = rParam.bLeft
+ ? sal_uInt16(nTmpDist)
+ : sal_uInt16(rParam.nTblWidth - nTmpDist);
+ break;
+ }
+ nTmpDist += nWidth;
+ }
+ }
+
+ for( n = 0; n < rBoxes.Count(); ++n )
+ {
+ SwTableBox* pBox = rBoxes[ n ];
+ SwFrmFmt* pFmt = pBox->GetFrmFmt();
+ const SwFmtFrmSize& rSz = pFmt->GetFrmSize();
+ SwTwips nWidth = rSz.GetWidth();
+
+ if( bCheck )
+ {
+ for( sal_uInt16 i = 0; i < pBox->GetTabLines().Count(); ++i )
+ if( !::lcl_InsOtherBox( pBox->GetTabLines()[ i ],
+ rParam, nDist, sal_True ))
+ return sal_False;
+
+ if(
+ rParam.bLeft ? ((nDist + nWidth / 2 ) <= rParam.nSide &&
+ (TBLFIX_CHGABS != rParam.nMode ||
+ (n < rBoxes.Count() &&
+ (nDist + nWidth + rBoxes[ n+1 ]->
+ GetFrmFmt()->GetFrmSize().GetWidth() / 2)
+ > rParam.nSide) ))
+ : (nDist + nWidth / 2 ) > rParam.nSide
+ )
+ {
+ rParam.bAnyBoxFnd = sal_True;
+ SwTwips nDiff;
+ if( TBLFIX_CHGPROP == rParam.nMode ) // Tabelle fix, proport.
+ {
+ // relativ berechnen
+ nDiff = nWidth;
+ nDiff *= rParam.nDiff;
+ nDiff /= rParam.nRemainWidth;
+
+ if( nWidth < nDiff || nWidth - nDiff < MINLAY )
+ return sal_False;
+ }
+ else
+ {
+ nDiff = rParam.nDiff;
+
+ // teste ob die linke oder rechte Box gross genug
+ // ist, um den Platz abzugeben!
+ // es wird davor oder dahinter eine Box eingefuegt!
+ SwTwips nTmpWidth = nWidth;
+ if( rParam.bLeft && pBox->GetUpper()->GetUpper() )
+ {
+ const SwTableBox* pTmpBox = pBox;
+ sal_uInt16 nBoxPos = n;
+ while( !nBoxPos && pTmpBox->GetUpper()->GetUpper() )
+ {
+ pTmpBox = pTmpBox->GetUpper()->GetUpper();
+ nBoxPos = pTmpBox->GetUpper()->GetTabBoxes().GetPos( pTmpBox );
+ }
+// if( nBoxPos )
+ nTmpWidth = pTmpBox->GetFrmFmt()->GetFrmSize().GetWidth();
+// else
+// nTmpWidth = 0;
+ }
+
+ if( nTmpWidth < nDiff || nTmpWidth - nDiff < MINLAY )
+ return sal_False;
+ break;
+ }
+ }
+ }
+ else
+ {
+ SwTwips nLowerDiff = 0, nOldLower = rParam.nLowerDiff;
+ for( sal_uInt16 i = 0; i < pBox->GetTabLines().Count(); ++i )
+ {
+ rParam.nLowerDiff = 0;
+ lcl_InsOtherBox( pBox->GetTabLines()[ i ], rParam,
+ nDist, sal_False );
+
+ if( nLowerDiff < rParam.nLowerDiff )
+ nLowerDiff = rParam.nLowerDiff;
+ }
+ rParam.nLowerDiff = nOldLower;
+
+ if( nLowerDiff ||
+ (rParam.bLeft ? ((nDist + nWidth / 2 ) <= rParam.nSide &&
+ (TBLFIX_CHGABS != rParam.nMode ||
+ (n < rBoxes.Count() &&
+ (nDist + nWidth + rBoxes[ n+1 ]->
+ GetFrmFmt()->GetFrmSize().GetWidth() / 2)
+ > rParam.nSide) ))
+ : (nDist + nWidth / 2 ) > rParam.nSide ))
+ {
+ if( !nLowerDiff )
+ {
+ if( TBLFIX_CHGPROP == rParam.nMode ) // Tabelle fix, proport.
+ {
+ // relativ berechnen
+ nLowerDiff = nWidth;
+ nLowerDiff *= rParam.nDiff;
+ nLowerDiff /= rParam.nRemainWidth;
+ }
+ else
+ nLowerDiff = rParam.nDiff;
+ }
+
+ SwFmtFrmSize aNew( rSz );
+ rParam.nLowerDiff += nLowerDiff;
+
+ if( rParam.bBigger )
+ aNew.SetWidth( nWidth - nLowerDiff );
+ else
+ aNew.SetWidth( nWidth + nLowerDiff );
+ rParam.aShareFmts.SetSize( *pBox, aNew );
+
+ if( TBLFIX_CHGABS == rParam.nMode )
+ break;
+ }
+ }
+
+ nDist += nWidth;
+ }
+ return sal_True;
+}
+
+// das Ergebnis des Positions Vergleiches
+// POS_BEFORE, // Box liegt davor
+// POS_BEHIND, // Box liegt dahinter
+// POS_INSIDE, // Box liegt vollstaendig in Start/End
+// POS_OUTSIDE, // Box ueberlappt Start/End vollstaendig
+// POS_EQUAL, // Box und Start/End sind gleich
+// POS_OVERLAP_BEFORE, // Box ueberlappt den Start
+// POS_OVERLAP_BEHIND // Box ueberlappt das Ende
+SwComparePosition _CheckBoxInRange( sal_uInt16 nStt, sal_uInt16 nEnd,
+ sal_uInt16 nBoxStt, sal_uInt16 nBoxEnd )
+{
+// COLFUZZY noch beachten!!
+ SwComparePosition nRet;
+ if( nBoxStt + COLFUZZY < nStt )
+ {
+ if( nBoxEnd > nStt + COLFUZZY )
+ {
+ if( nBoxEnd >= nEnd + COLFUZZY )
+ nRet = POS_OUTSIDE;
+ else
+ nRet = POS_OVERLAP_BEFORE;
+ }
+ else
+ nRet = POS_BEFORE;
+ }
+ else if( nEnd > nBoxStt + COLFUZZY )
+ {
+ if( nEnd + COLFUZZY >= nBoxEnd )
+ {
+ if( COLFUZZY > Abs( long(nEnd) - long(nBoxEnd) ) &&
+ COLFUZZY > Abs( long(nStt) - long(nBoxStt) ) )
+ nRet = POS_EQUAL;
+ else
+ nRet = POS_INSIDE;
+ }
+ else
+ nRet = POS_OVERLAP_BEHIND;
+ }
+ else
+ nRet = POS_BEHIND;
+
+ return nRet;
+}
+
+void lcl_DelSelBox_CorrLowers( SwTableLine& rLine, CR_SetBoxWidth& rParam,
+ SwTwips nWidth )
+{
+ // 1. Schritt die eigene Breite feststellen
+ SwTableBoxes& rBoxes = rLine.GetTabBoxes();
+ SwTwips nBoxWidth = 0;
+ sal_uInt16 n;
+
+ for( n = rBoxes.Count(); n; )
+ nBoxWidth += rBoxes[ --n ]->GetFrmFmt()->GetFrmSize().GetWidth();
+
+ if( COLFUZZY < Abs( nWidth - nBoxWidth ))
+ {
+ // sie muessen also angepasst werden
+ for( n = rBoxes.Count(); n; )
+ {
+ SwTableBox* pBox = rBoxes[ --n ];
+ SwFmtFrmSize aNew( pBox->GetFrmFmt()->GetFrmSize() );
+ long nDiff = aNew.GetWidth();
+ nDiff *= nWidth;
+ nDiff /= nBoxWidth;
+ aNew.SetWidth( nDiff );
+
+ rParam.aShareFmts.SetSize( *pBox, aNew );
+
+ if( !pBox->GetSttNd() )
+ {
+ // hat selbst auch Lower, also auch die anpassen
+ for( sal_uInt16 i = pBox->GetTabLines().Count(); i; )
+ ::lcl_DelSelBox_CorrLowers( *pBox->GetTabLines()[ --i ],
+ rParam, nDiff );
+ }
+ }
+ }
+}
+
+void lcl_ChgBoxSize( SwTableBox& rBox, CR_SetBoxWidth& rParam,
+ const SwFmtFrmSize& rOldSz,
+ sal_uInt16& rDelWidth, SwTwips nDist )
+{
+ long nDiff = 0;
+ sal_Bool bSetSize = sal_False;
+
+ switch( rParam.nMode )
+ {
+ case TBLFIX_CHGABS: // Tabelle feste Breite, den Nachbar andern
+ nDiff = rDelWidth + rParam.nLowerDiff;
+ bSetSize = sal_True;
+ break;
+
+ case TBLFIX_CHGPROP: // Tabelle feste Breite, alle Nachbarn aendern
+ if( !rParam.nRemainWidth )
+ {
+ // dann kurz berechnen:
+ if( rParam.bLeft )
+ rParam.nRemainWidth = sal_uInt16(nDist);
+ else
+ rParam.nRemainWidth = sal_uInt16(rParam.nTblWidth - nDist);
+ }
+
+ // relativ berechnen
+ nDiff = rOldSz.GetWidth();
+ nDiff *= rDelWidth + rParam.nLowerDiff;
+ nDiff /= rParam.nRemainWidth;
+
+ bSetSize = sal_True;
+ break;
+
+ case TBLVAR_CHGABS: // Tabelle variable, alle Nachbarn aendern
+ if( COLFUZZY < Abs( rParam.nBoxWidth -
+ ( rDelWidth + rParam.nLowerDiff )))
+ {
+ nDiff = rDelWidth + rParam.nLowerDiff - rParam.nBoxWidth;
+ if( 0 < nDiff )
+ rDelWidth = rDelWidth - sal_uInt16(nDiff);
+ else
+ rDelWidth = rDelWidth + sal_uInt16(-nDiff);
+ bSetSize = sal_True;
+ }
+ break;
+ }
+
+ if( bSetSize )
+ {
+ SwFmtFrmSize aNew( rOldSz );
+ aNew.SetWidth( aNew.GetWidth() + nDiff );
+ rParam.aShareFmts.SetSize( rBox, aNew );
+
+ // dann leider nochmals die Lower anpassen
+ for( sal_uInt16 i = rBox.GetTabLines().Count(); i; )
+ ::lcl_DelSelBox_CorrLowers( *rBox.GetTabLines()[ --i ], rParam,
+ aNew.GetWidth() );
+ }
+}
+
+sal_Bool lcl_DeleteBox_Rekursiv( CR_SetBoxWidth& rParam, SwTableBox& rBox,
+ sal_Bool bCheck )
+{
+ sal_Bool bRet = sal_True;
+ if( rBox.GetSttNd() )
+ {
+ if( bCheck )
+ {
+ rParam.bAnyBoxFnd = sal_True;
+ if( rBox.GetFrmFmt()->GetProtect().IsCntntProtected() )
+ bRet = sal_False;
+ else
+ {
+ SwTableBox* pBox = &rBox;
+ rParam.aBoxes.Insert( pBox );
+ }
+ }
+ else
+ ::_DeleteBox( rParam.pTblNd->GetTable(), &rBox,
+ rParam.pUndo, sal_False, sal_True, &rParam.aShareFmts );
+ }
+ else
+ {
+ // die muessen leider alle sequentiel ueber die
+ // Contentboxen geloescht werden
+ for( sal_uInt16 i = rBox.GetTabLines().Count(); i; )
+ {
+ SwTableLine& rLine = *rBox.GetTabLines()[ --i ];
+ for( sal_uInt16 n = rLine.GetTabBoxes().Count(); n; )
+ if( !::lcl_DeleteBox_Rekursiv( rParam,
+ *rLine.GetTabBoxes()[ --n ], bCheck ))
+ return sal_False;
+ }
+ }
+ return bRet;
+}
+
+sal_Bool lcl_DelSelBox( SwTableLine* pTabLine, CR_SetBoxWidth& rParam,
+ SwTwips nDist, sal_Bool bCheck )
+{
+ SwTableBoxes& rBoxes = pTabLine->GetTabBoxes();
+ sal_uInt16 n, nCntEnd, nBoxChkStt, nBoxChkEnd, nDelWidth = 0;
+ if( rParam.bLeft )
+ {
+ n = rBoxes.Count();
+ nCntEnd = 0;
+ nBoxChkStt = (sal_uInt16)rParam.nSide;
+ nBoxChkEnd = static_cast<sal_uInt16>(rParam.nSide + rParam.nBoxWidth);
+ }
+ else
+ {
+ n = 0;
+ nCntEnd = rBoxes.Count();
+ nBoxChkStt = static_cast<sal_uInt16>(rParam.nSide - rParam.nBoxWidth);
+ nBoxChkEnd = (sal_uInt16)rParam.nSide;
+ }
+
+
+ while( n != nCntEnd )
+ {
+ SwTableBox* pBox;
+ if( rParam.bLeft )
+ pBox = rBoxes[ --n ];
+ else
+ pBox = rBoxes[ n++ ];
+
+ SwFrmFmt* pFmt = pBox->GetFrmFmt();
+ const SwFmtFrmSize& rSz = pFmt->GetFrmSize();
+ long nWidth = rSz.GetWidth();
+ sal_Bool bDelBox = sal_False, bChgLowers = sal_False;
+
+ // die Boxenbreite testen und entpsrechend reagieren
+ SwComparePosition ePosType = ::_CheckBoxInRange(
+ nBoxChkStt, nBoxChkEnd,
+ sal_uInt16(rParam.bLeft ? nDist - nWidth : nDist),
+ sal_uInt16(rParam.bLeft ? nDist : nDist + nWidth));
+
+ switch( ePosType )
+ {
+ case POS_BEFORE:
+ if( bCheck )
+ {
+ if( rParam.bLeft )
+ return sal_True;
+ }
+ else if( rParam.bLeft )
+ {
+ ::lcl_ChgBoxSize( *pBox, rParam, rSz, nDelWidth, nDist );
+ if( TBLFIX_CHGABS == rParam.nMode )
+ n = nCntEnd;
+ }
+ break;
+
+ case POS_BEHIND:
+ if( bCheck )
+ {
+ if( !rParam.bLeft )
+ return sal_True;
+ }
+ else if( !rParam.bLeft )
+ {
+ ::lcl_ChgBoxSize( *pBox, rParam, rSz, nDelWidth, nDist );
+ if( TBLFIX_CHGABS == rParam.nMode )
+ n = nCntEnd;
+ }
+ break;
+
+ case POS_OUTSIDE: // Box ueberlappt Start/End vollstaendig
+ case POS_INSIDE: // Box liegt vollstaendig in Start/End
+ case POS_EQUAL: // Box und Start/End sind gleich
+ bDelBox = sal_True;
+ break;
+
+ case POS_OVERLAP_BEFORE: // Box ueberlappt den Start
+ if( nBoxChkStt <= ( nDist + (rParam.bLeft ? - nWidth / 2
+ : nWidth / 2 )))
+ {
+ if( !pBox->GetSttNd() )
+ bChgLowers = sal_True;
+ else
+ bDelBox = sal_True;
+ }
+ else if( !bCheck && rParam.bLeft )
+ {
+ if( !pBox->GetSttNd() )
+ bChgLowers = sal_True;
+ else
+ {
+ ::lcl_ChgBoxSize( *pBox, rParam, rSz, nDelWidth, nDist );
+ if( TBLFIX_CHGABS == rParam.nMode )
+ n = nCntEnd;
+ }
+ }
+ break;
+
+ case POS_OVERLAP_BEHIND: // Box ueberlappt das Ende
+ // JP 10.02.99:
+ // generell loeschen oder wie beim OVERLAP_Before nur die, die
+ // bis zur Haelfte in die "Loesch-"Box reicht ???
+ if( !pBox->GetSttNd() )
+ bChgLowers = sal_True;
+ else
+ bDelBox = sal_True;
+ break;
+ default: break;
+ }
+
+ if( bDelBox )
+ {
+ nDelWidth = nDelWidth + sal_uInt16(nWidth);
+ if( bCheck )
+ {
+ // die letzte/erste Box kann nur bei Tbl-Var geloescht werden,
+ // wenn diese so gross ist, wie die Aenderung an der Tabelle
+ if( (( TBLVAR_CHGABS != rParam.nMode ||
+ nDelWidth != rParam.nBoxWidth ) &&
+ COLFUZZY > Abs( rParam.bLeft
+ ? nWidth - nDist
+ : (nDist + nWidth - rParam.nTblWidth )))
+ || !::lcl_DeleteBox_Rekursiv( rParam, *pBox, bCheck ) )
+ return sal_False;
+
+ if( pFmt->GetProtect().IsCntntProtected() )
+ return sal_False;
+ }
+ else
+ {
+ ::lcl_DeleteBox_Rekursiv( rParam, *pBox, bCheck );
+
+ if( !rParam.bLeft )
+ --n, --nCntEnd;
+ }
+ }
+ else if( bChgLowers )
+ {
+ sal_Bool bFirst = sal_True, bCorrLowers = sal_False;
+ long nLowerDiff = 0;
+ long nOldLower = rParam.nLowerDiff;
+ sal_uInt16 nOldRemain = rParam.nRemainWidth;
+ sal_uInt16 i;
+
+ for( i = pBox->GetTabLines().Count(); i; )
+ {
+ rParam.nLowerDiff = nDelWidth + nOldLower;
+ rParam.nRemainWidth = nOldRemain;
+ SwTableLine* pLine = pBox->GetTabLines()[ --i ];
+ if( !::lcl_DelSelBox( pLine, rParam, nDist, bCheck ))
+ return sal_False;
+
+ // gibt es die Box und die darin enthaltenen Lines noch??
+ if( n < rBoxes.Count() &&
+ pBox == rBoxes[ rParam.bLeft ? n : n-1 ] &&
+ i < pBox->GetTabLines().Count() &&
+ pLine == pBox->GetTabLines()[ i ] )
+ {
+ if( !bFirst && !bCorrLowers &&
+ COLFUZZY < Abs( nLowerDiff - rParam.nLowerDiff ) )
+ bCorrLowers = sal_True;
+
+ // die groesste "loesch" Breite entscheidet, aber nur wenn
+ // nicht die gesamte Line geloescht wurde
+ if( nLowerDiff < rParam.nLowerDiff )
+ nLowerDiff = rParam.nLowerDiff;
+
+ bFirst = sal_False;
+ }
+ }
+ rParam.nLowerDiff = nOldLower;
+ rParam.nRemainWidth = nOldRemain;
+
+ // wurden alle Boxen geloescht? Dann ist die DelBreite natuerlich
+ // die Boxenbreite
+ if( !nLowerDiff )
+ nLowerDiff = nWidth;
+
+ // DelBreite anpassen!!
+ nDelWidth = nDelWidth + sal_uInt16(nLowerDiff);
+
+ if( !bCheck )
+ {
+ // wurde die Box schon entfernt?
+ if( n > rBoxes.Count() ||
+ pBox != rBoxes[ ( rParam.bLeft ? n : n-1 ) ] )
+ {
+ // dann beim Loeschen nach rechts die Laufvar. anpassen
+ if( !rParam.bLeft )
+ --n, --nCntEnd;
+ }
+ else
+ {
+ // sonst muss die Groesse der Box angepasst werden
+ SwFmtFrmSize aNew( rSz );
+ sal_Bool bCorrRel = sal_False;
+
+ if( TBLVAR_CHGABS != rParam.nMode )
+ {
+ switch( ePosType )
+ {
+ case POS_OVERLAP_BEFORE: // Box ueberlappt den Start
+ if( TBLFIX_CHGPROP == rParam.nMode )
+ bCorrRel = rParam.bLeft;
+ else if( rParam.bLeft ) // TBLFIX_CHGABS
+ {
+ nLowerDiff = nLowerDiff - nDelWidth;
+ bCorrLowers = sal_True;
+ n = nCntEnd;
+ }
+ break;
+
+ case POS_OVERLAP_BEHIND: // Box ueberlappt das Ende
+ if( TBLFIX_CHGPROP == rParam.nMode )
+ bCorrRel = !rParam.bLeft;
+ else if( !rParam.bLeft ) // TBLFIX_CHGABS
+ {
+ nLowerDiff = nLowerDiff - nDelWidth;
+ bCorrLowers = sal_True;
+ n = nCntEnd;
+ }
+ break;
+
+ default:
+ OSL_ENSURE( !pBox, "hier sollte man nie hinkommen" );
+ break;
+ }
+ }
+
+ if( bCorrRel )
+ {
+ if( !rParam.nRemainWidth )
+ {
+ // dann kurz berechnen:
+ if( rParam.bLeft )
+ rParam.nRemainWidth = sal_uInt16(nDist - nLowerDiff);
+ else
+ rParam.nRemainWidth = sal_uInt16(rParam.nTblWidth - nDist
+ - nLowerDiff );
+ }
+
+ long nDiff = aNew.GetWidth() - nLowerDiff;
+ nDiff *= nDelWidth + rParam.nLowerDiff;
+ nDiff /= rParam.nRemainWidth;
+
+ aNew.SetWidth( aNew.GetWidth() - nLowerDiff + nDiff );
+ }
+ else
+ aNew.SetWidth( aNew.GetWidth() - nLowerDiff );
+ rParam.aShareFmts.SetSize( *pBox, aNew );
+
+ if( bCorrLowers )
+ {
+ // dann leider nochmals die Lower anpassen
+ for( i = pBox->GetTabLines().Count(); i; )
+ ::lcl_DelSelBox_CorrLowers( *pBox->
+ GetTabLines()[ --i ], rParam, aNew.GetWidth() );
+ }
+ }
+ }
+ }
+
+ if( rParam.bLeft )
+ nDist -= nWidth;
+ else
+ nDist += nWidth;
+ }
+ rParam.nLowerDiff = nDelWidth;
+ return sal_True;
+}
+
+// Dummy Funktion fuer die Methode SetColWidth
+sal_Bool lcl_DelOtherBox( SwTableLine* , CR_SetBoxWidth& , SwTwips , sal_Bool )
+{
+ return sal_True;
+}
+
+void lcl_AjustLines( SwTableLine* pLine, CR_SetBoxWidth& rParam )
+{
+ SwTableBoxes& rBoxes = pLine->GetTabBoxes();
+ for( sal_uInt16 n = 0; n < rBoxes.Count(); ++n )
+ {
+ SwTableBox* pBox = rBoxes[ n ];
+
+ SwFmtFrmSize aSz( pBox->GetFrmFmt()->GetFrmSize() );
+ SwTwips nWidth = aSz.GetWidth();
+ nWidth *= rParam.nDiff;
+ nWidth /= rParam.nMaxSize;
+ aSz.SetWidth( nWidth );
+ rParam.aShareFmts.SetSize( *pBox, aSz );
+
+ for( sal_uInt16 i = 0; i < pBox->GetTabLines().Count(); ++i )
+ ::lcl_AjustLines( pBox->GetTabLines()[ i ], rParam );
+ }
+}
+
+#if OSL_DEBUG_LEVEL > 1
+
+void _CheckBoxWidth( const SwTableLine& rLine, SwTwips nSize )
+{
+ const SwTableBoxes& rBoxes = rLine.GetTabBoxes();
+
+ SwTwips nAktSize = 0;
+ // checke doch mal ob die Tabellen korrekte Breiten haben
+ for( sal_uInt16 n = 0; n < rBoxes.Count(); ++n )
+ {
+ const SwTableBox* pBox = rBoxes[ n ];
+ const SwTwips nBoxW = pBox->GetFrmFmt()->GetFrmSize().GetWidth();
+ nAktSize += nBoxW;
+
+ for( sal_uInt16 i = 0; i < pBox->GetTabLines().Count(); ++i )
+ _CheckBoxWidth( *pBox->GetTabLines()[ i ], nBoxW );
+ }
+
+ if( Abs( nAktSize - nSize ) > ( COLFUZZY * rBoxes.Count() ) )
+ {
+ OSL_FAIL( "Boxen der Line zu klein/gross" );
+ }
+}
+
+#endif
+
+_FndBox* lcl_SaveInsDelData( CR_SetBoxWidth& rParam, SwUndo** ppUndo,
+ SwTableSortBoxes& rTmpLst, SwTwips nDistStt )
+{
+ // suche alle Boxen / Lines
+ SwTable& rTbl = rParam.pTblNd->GetTable();
+
+ if( !rParam.aBoxes.Count() )
+ {
+ // erstmal die Boxen besorgen !
+ if( rParam.bBigger )
+ for( sal_uInt16 n = 0; n < rTbl.GetTabLines().Count(); ++n )
+ ::lcl_DelSelBox( rTbl.GetTabLines()[ n ], rParam, nDistStt, sal_True );
+ else
+ for( sal_uInt16 n = 0; n < rTbl.GetTabLines().Count(); ++n )
+ ::lcl_InsSelBox( rTbl.GetTabLines()[ n ], rParam, nDistStt, sal_True );
+ }
+
+ // loeschen der gesamten Tabelle verhindern
+ if( rParam.bBigger && rParam.aBoxes.Count() ==
+ rTbl.GetTabSortBoxes().Count() )
+ return 0;
+
+ _FndBox* pFndBox = new _FndBox( 0, 0 );
+ if( rParam.bBigger )
+ pFndBox->SetTableLines( rParam.aBoxes, rTbl );
+ else
+ {
+ _FndPara aPara( rParam.aBoxes, pFndBox );
+ rTbl.GetTabLines().ForEach( &_FndLineCopyCol, &aPara );
+ OSL_ENSURE( pFndBox->GetLines().Count(), "Wo sind die Boxen" );
+ pFndBox->SetTableLines( rTbl );
+
+ if( ppUndo )
+ rTmpLst.Insert( &rTbl.GetTabSortBoxes(), 0, rTbl.GetTabSortBoxes().Count() );
+ }
+
+ //Lines fuer das Layout-Update herausuchen.
+ pFndBox->DelFrms( rTbl );
+
+ // TL_CHART2: this function gest called from SetColWidth exclusively,
+ // thus it is currently speculated that nothing needs to be done here.
+ // Note: that SetColWidth is currently not completely understood though :-(
+
+ return pFndBox;
+}
+
+sal_Bool SwTable::SetColWidth( SwTableBox& rAktBox, sal_uInt16 eType,
+ SwTwips nAbsDiff, SwTwips nRelDiff, SwUndo** ppUndo )
+{
+ SetHTMLTableLayout( 0 ); // MIB 9.7.97: HTML-Layout loeschen
+
+ const SwFmtFrmSize& rSz = GetFrmFmt()->GetFrmSize();
+ const SvxLRSpaceItem& rLR = GetFrmFmt()->GetLRSpace();
+
+ _FndBox* pFndBox = 0; // fuers Einfuegen/Loeschen
+ SwTableSortBoxes aTmpLst( 0, 5 ); // fuers Undo
+ sal_Bool bBigger,
+ bRet = sal_False,
+ bLeft = nsTblChgWidthHeightType::WH_COL_LEFT == ( eType & 0xff ) ||
+ nsTblChgWidthHeightType::WH_CELL_LEFT == ( eType & 0xff ),
+ bInsDel = 0 != (eType & nsTblChgWidthHeightType::WH_FLAG_INSDEL );
+ sal_uInt16 n;
+ sal_uLong nBoxIdx = rAktBox.GetSttIdx();
+
+ // bestimme die akt. Kante der Box
+ // wird nur fuer die Breitenmanipulation benoetigt!
+ const SwTwips nDist = ::lcl_GetDistance( &rAktBox, bLeft );
+ SwTwips nDistStt = 0;
+ CR_SetBoxWidth aParam( eType, nRelDiff, nDist, rSz.GetWidth(),
+ bLeft ? nDist : rSz.GetWidth() - nDist,
+ (SwTableNode*)rAktBox.GetSttNd()->FindTableNode() );
+ bBigger = aParam.bBigger;
+
+ FN_lcl_SetBoxWidth fnSelBox, fnOtherBox;
+ if( bInsDel )
+ {
+ if( bBigger )
+ {
+ fnSelBox = lcl_DelSelBox;
+ fnOtherBox = lcl_DelOtherBox;
+ aParam.nBoxWidth = (sal_uInt16)rAktBox.GetFrmFmt()->GetFrmSize().GetWidth();
+ if( bLeft )
+ nDistStt = rSz.GetWidth();
+ }
+ else
+ {
+ fnSelBox = lcl_InsSelBox;
+ fnOtherBox = lcl_InsOtherBox;
+ }
+ }
+ else
+ {
+ fnSelBox = lcl_SetSelBoxWidth;
+ fnOtherBox = lcl_SetOtherBoxWidth;
+ }
+
+
+ switch( eType & 0xff )
+ {
+ case nsTblChgWidthHeightType::WH_COL_RIGHT:
+ case nsTblChgWidthHeightType::WH_COL_LEFT:
+ if( TBLVAR_CHGABS == eTblChgMode )
+ {
+ if( bInsDel )
+ bBigger = !bBigger;
+
+ // erstmal testen, ob ueberhaupt Platz ist
+ sal_Bool bChgLRSpace = sal_True;
+ if( bBigger )
+ {
+ if( GetFrmFmt()->getIDocumentSettingAccess()->get(IDocumentSettingAccess::BROWSE_MODE) &&
+ !rSz.GetWidthPercent() )
+ {
+ bRet = rSz.GetWidth() < USHRT_MAX - nRelDiff;
+ bChgLRSpace = bLeft ? rLR.GetLeft() >= nAbsDiff
+ : rLR.GetRight() >= nAbsDiff;
+ }
+ else
+ bRet = bLeft ? rLR.GetLeft() >= nAbsDiff
+ : rLR.GetRight() >= nAbsDiff;
+
+ if( !bRet && bInsDel &&
+ // auf der anderen Seite Platz?
+ ( bLeft ? rLR.GetRight() >= nAbsDiff
+ : rLR.GetLeft() >= nAbsDiff ))
+ {
+ bRet = sal_True; bLeft = !bLeft;
+ }
+
+ if( !bRet )
+ {
+ // dann sich selbst rekursiv aufrufen; nur mit
+ // einem anderen Mode -> proprotional
+ TblChgMode eOld = eTblChgMode;
+ eTblChgMode = TBLFIX_CHGPROP;
+
+ bRet = SetColWidth( rAktBox, eType, nAbsDiff, nRelDiff,
+ ppUndo );
+ eTblChgMode = eOld;
+ return bRet;
+ }
+ }
+ else
+ {
+ bRet = sal_True;
+ for( n = 0; n < aLines.Count(); ++n )
+ {
+ aParam.LoopClear();
+ if( !(*fnSelBox)( aLines[ n ], aParam, nDistStt, sal_True ))
+ {
+ bRet = sal_False;
+ break;
+ }
+ }
+ }
+
+ if( bRet )
+ {
+ if( bInsDel )
+ {
+ pFndBox = ::lcl_SaveInsDelData( aParam, ppUndo,
+ aTmpLst, nDistStt );
+ if( aParam.bBigger && aParam.aBoxes.Count() ==
+ aSortCntBoxes.Count() )
+ {
+ // dies gesamte Tabelle soll geloescht werden!!
+ GetFrmFmt()->GetDoc()->DeleteRowCol( aParam.aBoxes );
+ return sal_False;
+ }
+
+ if( ppUndo )
+ *ppUndo = aParam.CreateUndo(
+ aParam.bBigger ? UNDO_COL_DELETE
+ : UNDO_TABLE_INSCOL );
+ }
+ else if( ppUndo )
+ *ppUndo = new SwUndoAttrTbl( *aParam.pTblNd, sal_True );
+
+ long nFrmWidth = LONG_MAX;
+ LockModify();
+ SwFmtFrmSize aSz( rSz );
+ SvxLRSpaceItem aLR( rLR );
+ if( bBigger )
+ {
+ // falls die Tabelle keinen Platz zum Wachsen hat, dann
+ // muessen wir welchen schaffen!
+ if( aSz.GetWidth() + nRelDiff > USHRT_MAX )
+ {
+ // dann mal herunterbrechen auf USHRT_MAX / 2
+ CR_SetBoxWidth aTmpPara( 0, aSz.GetWidth() / 2,
+ 0, aSz.GetWidth(), aSz.GetWidth(), aParam.pTblNd );
+ for( sal_uInt16 nLn = 0; nLn < aLines.Count(); ++nLn )
+ ::lcl_AjustLines( aLines[ nLn ], aTmpPara );
+ aSz.SetWidth( aSz.GetWidth() / 2 );
+ aParam.nDiff = nRelDiff /= 2;
+ aParam.nSide /= 2;
+ aParam.nMaxSize /= 2;
+ }
+
+ if( bLeft )
+ aLR.SetLeft( sal_uInt16( aLR.GetLeft() - nAbsDiff ) );
+ else
+ aLR.SetRight( sal_uInt16( aLR.GetRight() - nAbsDiff ) );
+ }
+ else if( bLeft )
+ aLR.SetLeft( sal_uInt16( aLR.GetLeft() + nAbsDiff ) );
+ else
+ aLR.SetRight( sal_uInt16( aLR.GetRight() + nAbsDiff ) );
+
+ if( bChgLRSpace )
+ GetFrmFmt()->SetFmtAttr( aLR );
+ const SwFmtHoriOrient& rHOri = GetFrmFmt()->GetHoriOrient();
+ if( text::HoriOrientation::FULL == rHOri.GetHoriOrient() ||
+ (text::HoriOrientation::LEFT == rHOri.GetHoriOrient() && aLR.GetLeft()) ||
+ (text::HoriOrientation::RIGHT == rHOri.GetHoriOrient() && aLR.GetRight()))
+ {
+ SwFmtHoriOrient aHOri( rHOri );
+ aHOri.SetHoriOrient( text::HoriOrientation::NONE );
+ GetFrmFmt()->SetFmtAttr( aHOri );
+
+ // sollte die Tabelle noch auf relativen Werten
+ // (USHRT_MAX) stehen dann muss es jetzt auf absolute
+ // umgerechnet werden. Bug 61494
+ if( GetFrmFmt()->getIDocumentSettingAccess()->get(IDocumentSettingAccess::BROWSE_MODE) &&
+ !rSz.GetWidthPercent() )
+ {
+ SwTabFrm* pTabFrm = SwIterator<SwTabFrm,SwFmt>::FirstElement( *GetFrmFmt() );
+ if( pTabFrm &&
+ pTabFrm->Prt().Width() != rSz.GetWidth() )
+ {
+ nFrmWidth = pTabFrm->Prt().Width();
+ if( bBigger )
+ nFrmWidth += nAbsDiff;
+ else
+ nFrmWidth -= nAbsDiff;
+ }
+ }
+ }
+
+ if( bBigger )
+ aSz.SetWidth( aSz.GetWidth() + nRelDiff );
+ else
+ aSz.SetWidth( aSz.GetWidth() - nRelDiff );
+
+ if( rSz.GetWidthPercent() )
+ aSz.SetWidthPercent( static_cast<sal_uInt8>(( aSz.GetWidth() * 100 ) /
+ ( aSz.GetWidth() + aLR.GetRight() + aLR.GetLeft())));
+
+ GetFrmFmt()->SetFmtAttr( aSz );
+ aParam.nTblWidth = sal_uInt16( aSz.GetWidth() );
+
+ UnlockModify();
+
+ for( n = aLines.Count(); n; )
+ {
+ --n;
+ aParam.LoopClear();
+ (*fnSelBox)( aLines[ n ], aParam, nDistStt, sal_False );
+ }
+
+ // sollte die Tabelle noch auf relativen Werten
+ // (USHRT_MAX) stehen dann muss es jetzt auf absolute
+ // umgerechnet werden. Bug 61494
+ if( LONG_MAX != nFrmWidth )
+ {
+ SwFmtFrmSize aAbsSz( aSz );
+ aAbsSz.SetWidth( nFrmWidth );
+ GetFrmFmt()->SetFmtAttr( aAbsSz );
+ }
+ }
+ }
+ else if( bInsDel ||
+ ( bLeft ? nDist : Abs( rSz.GetWidth() - nDist ) > COLFUZZY ) )
+ {
+ bRet = sal_True;
+ if( bLeft && TBLFIX_CHGABS == eTblChgMode && !bInsDel )
+ aParam.bBigger = !bBigger;
+
+ // erstmal testen, ob ueberhaupt Platz ist
+ if( bInsDel )
+ {
+ if( aParam.bBigger )
+ {
+ for( n = 0; n < aLines.Count(); ++n )
+ {
+ aParam.LoopClear();
+ if( !(*fnSelBox)( aLines[ n ], aParam, nDistStt, sal_True ))
+ {
+ bRet = sal_False;
+ break;
+ }
+ }
+ }
+ else
+ {
+ if( 0 != ( bRet = bLeft ? nDist != 0
+ : ( rSz.GetWidth() - nDist ) > COLFUZZY ) )
+ {
+ for( n = 0; n < aLines.Count(); ++n )
+ {
+ aParam.LoopClear();
+ if( !(*fnOtherBox)( aLines[ n ], aParam, 0, sal_True ))
+ {
+ bRet = sal_False;
+ break;
+ }
+ }
+ if( bRet && !aParam.bAnyBoxFnd )
+ bRet = sal_False;
+ }
+
+ if( !bRet && rAktBox.GetFrmFmt()->GetFrmSize().GetWidth()
+ - nRelDiff > COLFUZZY +
+ ( 567 / 2 /* min. 0,5 cm Platz lassen*/) )
+ {
+ // dann den Platz von der akt. Zelle nehmen
+ aParam.bSplittBox = sal_True;
+ // aber das muss auch mal getestet werden!
+ bRet = sal_True;
+
+ for( n = 0; n < aLines.Count(); ++n )
+ {
+ aParam.LoopClear();
+ if( !(*fnSelBox)( aLines[ n ], aParam, nDistStt, sal_True ))
+ {
+ bRet = sal_False;
+ break;
+ }
+ }
+ }
+ }
+ }
+ else if( aParam.bBigger )
+ {
+ for( n = 0; n < aLines.Count(); ++n )
+ {
+ aParam.LoopClear();
+ if( !(*fnOtherBox)( aLines[ n ], aParam, 0, sal_True ))
+ {
+ bRet = sal_False;
+ break;
+ }
+ }
+ }
+ else
+ {
+ for( n = 0; n < aLines.Count(); ++n )
+ {
+ aParam.LoopClear();
+ if( !(*fnSelBox)( aLines[ n ], aParam, nDistStt, sal_True ))
+ {
+ bRet = sal_False;
+ break;
+ }
+ }
+ }
+
+ // wenn ja, dann setzen
+ if( bRet )
+ {
+ CR_SetBoxWidth aParam1( aParam );
+ if( bInsDel )
+ {
+ aParam1.bBigger = !aParam.bBigger;
+ pFndBox = ::lcl_SaveInsDelData( aParam, ppUndo,
+ aTmpLst, nDistStt );
+ if( ppUndo )
+ *ppUndo = aParam.CreateUndo(
+ aParam.bBigger ? UNDO_TABLE_DELBOX
+ : UNDO_TABLE_INSCOL );
+ }
+ else if( ppUndo )
+ *ppUndo = new SwUndoAttrTbl( *aParam.pTblNd, sal_True );
+
+ if( bInsDel
+ ? ( TBLFIX_CHGABS == eTblChgMode ? bLeft : bLeft )
+ : ( TBLFIX_CHGABS != eTblChgMode && bLeft ) )
+ {
+ for( n = aLines.Count(); n; )
+ {
+ --n;
+ aParam.LoopClear();
+ aParam1.LoopClear();
+ (*fnSelBox)( aLines[ n ], aParam, nDistStt, sal_False );
+ (*fnOtherBox)( aLines[ n ], aParam1, nDistStt, sal_False );
+ }
+ }
+ else
+ for( n = aLines.Count(); n; )
+ {
+ --n;
+ aParam.LoopClear();
+ aParam1.LoopClear();
+ (*fnOtherBox)( aLines[ n ], aParam1, nDistStt, sal_False );
+ (*fnSelBox)( aLines[ n ], aParam, nDistStt, sal_False );
+ }
+ }
+ }
+ break;
+
+ case nsTblChgWidthHeightType::WH_CELL_RIGHT:
+ case nsTblChgWidthHeightType::WH_CELL_LEFT:
+ if( TBLVAR_CHGABS == eTblChgMode )
+ {
+ // dann sich selbst rekursiv aufrufen; nur mit
+ // einem anderen Mode -> Nachbarn
+ TblChgMode eOld = eTblChgMode;
+ eTblChgMode = TBLFIX_CHGABS;
+
+ bRet = SetColWidth( rAktBox, eType, nAbsDiff, nRelDiff,
+ ppUndo );
+ eTblChgMode = eOld;
+ return bRet;
+ }
+ else if( bInsDel || ( bLeft ? nDist
+ : (rSz.GetWidth() - nDist) > COLFUZZY ))
+ {
+ if( bLeft && TBLFIX_CHGABS == eTblChgMode && !bInsDel )
+ aParam.bBigger = !bBigger;
+
+ // erstmal testen, ob ueberhaupt Platz ist
+ SwTableBox* pBox = &rAktBox;
+ SwTableLine* pLine = rAktBox.GetUpper();
+ while( pLine->GetUpper() )
+ {
+ sal_uInt16 nPos = pLine->GetTabBoxes().C40_GETPOS( SwTableBox, pBox );
+ if( bLeft ? nPos : nPos + 1 != pLine->GetTabBoxes().Count() )
+ break;
+
+ pBox = pLine->GetUpper();
+ pLine = pBox->GetUpper();
+ }
+
+ if( pLine->GetUpper() )
+ {
+ // dann muss die Distanz wieder korriegiert werden!
+ aParam.nSide -= ::lcl_GetDistance( pLine->GetUpper(), sal_True );
+
+ if( bLeft )
+ aParam.nMaxSize = aParam.nSide;
+ else
+ aParam.nMaxSize = pLine->GetUpper()->GetFrmFmt()->
+ GetFrmSize().GetWidth() - aParam.nSide;
+ }
+
+ // erstmal testen, ob ueberhaupt Platz ist
+ if( bInsDel )
+ {
+ if( 0 != ( bRet = bLeft ? nDist != 0
+ : ( rSz.GetWidth() - nDist ) > COLFUZZY ) &&
+ !aParam.bBigger )
+ {
+ bRet = (*fnOtherBox)( pLine, aParam, 0, sal_True );
+ if( bRet && !aParam.bAnyBoxFnd )
+ bRet = sal_False;
+ }
+
+ if( !bRet && !aParam.bBigger && rAktBox.GetFrmFmt()->
+ GetFrmSize().GetWidth() - nRelDiff > COLFUZZY +
+ ( 567 / 2 /* min. 0,5 cm Platz lassen*/) )
+ {
+ // dann den Platz von der akt. Zelle nehmen
+ aParam.bSplittBox = sal_True;
+ bRet = sal_True;
+ }
+ }
+ else
+ {
+ FN_lcl_SetBoxWidth fnTmp = aParam.bBigger ? fnOtherBox : fnSelBox;
+ bRet = (*fnTmp)( pLine, aParam, nDistStt, sal_True );
+ }
+
+ // wenn ja, dann setzen
+ if( bRet )
+ {
+ CR_SetBoxWidth aParam1( aParam );
+ if( bInsDel )
+ {
+ aParam1.bBigger = !aParam.bBigger;
+ pFndBox = ::lcl_SaveInsDelData( aParam, ppUndo, aTmpLst, nDistStt );
+ if( ppUndo )
+ *ppUndo = aParam.CreateUndo(
+ aParam.bBigger ? UNDO_TABLE_DELBOX
+ : UNDO_TABLE_INSCOL );
+ }
+ else if( ppUndo )
+ *ppUndo = new SwUndoAttrTbl( *aParam.pTblNd, sal_True );
+
+ if( bInsDel
+ ? ( TBLFIX_CHGABS == eTblChgMode ? (bBigger && bLeft) : bLeft )
+ : ( TBLFIX_CHGABS != eTblChgMode && bLeft ) )
+ {
+ (*fnSelBox)( pLine, aParam, nDistStt, sal_False );
+ (*fnOtherBox)( pLine, aParam1, nDistStt, sal_False );
+ }
+ else
+ {
+ (*fnOtherBox)( pLine, aParam1, nDistStt, sal_False );
+ (*fnSelBox)( pLine, aParam, nDistStt, sal_False );
+ }
+ }
+ }
+ break;
+
+ }
+
+ if( pFndBox )
+ {
+ // dann raeume die Struktur aller Lines auf
+ GCLines();
+
+ //Layout updaten
+ if( !bBigger || pFndBox->AreLinesToRestore( *this ) )
+ pFndBox->MakeFrms( *this );
+
+ // TL_CHART2: it is currently unclear if sth has to be done here.
+ // The function name hints that nothing needs to be done, on the other
+ // hand there is a case where sth gets deleted. :-(
+
+ delete pFndBox;
+
+ if( ppUndo && *ppUndo )
+ {
+ aParam.pUndo->SetColWidthParam( nBoxIdx, static_cast<sal_uInt16>(eTblChgMode), eType,
+ nAbsDiff, nRelDiff );
+ if( !aParam.bBigger )
+ aParam.pUndo->SaveNewBoxes( *aParam.pTblNd, aTmpLst );
+ }
+ }
+
+ if( bRet )
+ {
+ CHECKBOXWIDTH
+ CHECKTABLELAYOUT
+ }
+
+ return bRet;
+}
+
+_FndBox* lcl_SaveInsDelData( CR_SetLineHeight& rParam, SwUndo** ppUndo,
+ SwTableSortBoxes& rTmpLst )
+{
+ // suche alle Boxen / Lines
+ SwTable& rTbl = rParam.pTblNd->GetTable();
+
+ OSL_ENSURE( rParam.aBoxes.Count(), "ohne Boxen ist nichts zu machen!" );
+
+ // loeschen der gesamten Tabelle verhindern
+ if( !rParam.bBigger && rParam.aBoxes.Count() ==
+ rTbl.GetTabSortBoxes().Count() )
+ return 0;
+
+ _FndBox* pFndBox = new _FndBox( 0, 0 );
+ if( !rParam.bBigger )
+ pFndBox->SetTableLines( rParam.aBoxes, rTbl );
+ else
+ {
+ _FndPara aPara( rParam.aBoxes, pFndBox );
+ rTbl.GetTabLines().ForEach( &_FndLineCopyCol, &aPara );
+ OSL_ENSURE( pFndBox->GetLines().Count(), "Wo sind die Boxen" );
+ pFndBox->SetTableLines( rTbl );
+
+ if( ppUndo )
+ rTmpLst.Insert( &rTbl.GetTabSortBoxes(), 0, rTbl.GetTabSortBoxes().Count() );
+ }
+
+ //Lines fuer das Layout-Update heraussuchen.
+ pFndBox->DelFrms( rTbl );
+
+ // TL_CHART2: it is currently unclear if sth has to be done here.
+
+ return pFndBox;
+}
+
+void SetLineHeight( SwTableLine& rLine, SwTwips nOldHeight, SwTwips nNewHeight,
+ sal_Bool bMinSize )
+{
+ SwLayoutFrm* pLineFrm = GetRowFrm( rLine );
+ OSL_ENSURE( pLineFrm, "wo ist der Frm von der SwTableLine?" );
+
+ SwFrmFmt* pFmt = rLine.ClaimFrmFmt();
+
+ SwTwips nMyNewH, nMyOldH = pLineFrm->Frm().Height();
+ if( !nOldHeight ) // die BaseLine und absolut
+ nMyNewH = nMyOldH + nNewHeight;
+ else
+ {
+ // moeglichst genau rechnen
+ Fraction aTmp( nMyOldH );
+ aTmp *= Fraction( nNewHeight, nOldHeight );
+ aTmp += Fraction( 1, 2 ); // ggfs. aufrunden
+ nMyNewH = aTmp;
+ }
+
+ SwFrmSize eSize = ATT_MIN_SIZE;
+ if( !bMinSize &&
+ ( nMyOldH - nMyNewH ) > ( CalcRowRstHeight( pLineFrm ) + ROWFUZZY ))
+ eSize = ATT_FIX_SIZE;
+
+ pFmt->SetFmtAttr( SwFmtFrmSize( eSize, 0, nMyNewH ) );
+
+ // erst alle inneren anpassen
+ SwTableBoxes& rBoxes = rLine.GetTabBoxes();
+ for( sal_uInt16 n = 0; n < rBoxes.Count(); ++n )
+ {
+ SwTableBox& rBox = *rBoxes[ n ];
+ for( sal_uInt16 i = 0; i < rBox.GetTabLines().Count(); ++i )
+ SetLineHeight( *rBox.GetTabLines()[ i ], nMyOldH, nMyNewH, bMinSize );
+ }
+}
+
+sal_Bool lcl_SetSelLineHeight( SwTableLine* pLine, CR_SetLineHeight& rParam,
+ SwTwips nDist, sal_Bool bCheck )
+{
+ sal_Bool bRet = sal_True;
+ if( !bCheck )
+ {
+ // Zeilenhoehe einstellen
+ SetLineHeight( *pLine, 0, rParam.bBigger ? nDist : -nDist,
+ rParam.bBigger );
+ }
+ else if( !rParam.bBigger )
+ {
+ // anhand der alten Size die neue relative errechnen
+ SwLayoutFrm* pLineFrm = GetRowFrm( *pLine );
+ OSL_ENSURE( pLineFrm, "wo ist der Frm von der SwTableLine?" );
+ SwTwips nRstHeight = CalcRowRstHeight( pLineFrm );
+ if( (nRstHeight + ROWFUZZY) < nDist )
+ bRet = sal_False;
+ }
+ return bRet;
+}
+
+sal_Bool lcl_SetOtherLineHeight( SwTableLine* pLine, CR_SetLineHeight& rParam,
+ SwTwips nDist, sal_Bool bCheck )
+{
+ sal_Bool bRet = sal_True;
+ if( bCheck )
+ {
+ if( rParam.bBigger )
+ {
+ // anhand der alten Size die neue relative errechnen
+ SwLayoutFrm* pLineFrm = GetRowFrm( *pLine );
+ OSL_ENSURE( pLineFrm, "wo ist der Frm von der SwTableLine?" );
+
+ if( TBLFIX_CHGPROP == rParam.nMode )
+ {
+ nDist *= pLineFrm->Frm().Height();
+ nDist /= rParam.nMaxHeight;
+ }
+ bRet = nDist <= CalcRowRstHeight( pLineFrm );
+ }
+ }
+ else
+ {
+ // Zeilenhoehe einstellen
+ // pLine ist die nachfolgende / vorhergehende -> also anpassen
+ if( TBLFIX_CHGPROP == rParam.nMode )
+ {
+ SwLayoutFrm* pLineFrm = GetRowFrm( *pLine );
+ OSL_ENSURE( pLineFrm, "wo ist der Frm von der SwTableLine?" );
+
+ // aus der alten Size die neue relative errechnen
+ // Wird die selektierte Box groesser ueber den MaxSpace anpassen,
+ // sonst ueber die MaxHeight
+ if( 1 /*!rParam.bBigger*/ )
+ {
+ nDist *= pLineFrm->Frm().Height();
+ nDist /= rParam.nMaxHeight;
+ }
+ else
+ {
+ // aus der alten Size die neue relative errechnen
+ nDist *= CalcRowRstHeight( pLineFrm );
+ nDist /= rParam.nMaxSpace;
+ }
+ }
+ SetLineHeight( *pLine, 0, rParam.bBigger ? -nDist : nDist,
+ !rParam.bBigger );
+ }
+ return bRet;
+}
+
+sal_Bool lcl_InsDelSelLine( SwTableLine* pLine, CR_SetLineHeight& rParam,
+ SwTwips nDist, sal_Bool bCheck )
+{
+ sal_Bool bRet = sal_True;
+ if( !bCheck )
+ {
+ SwTableBoxes& rBoxes = pLine->GetTabBoxes();
+ SwDoc* pDoc = pLine->GetFrmFmt()->GetDoc();
+ if( !rParam.bBigger )
+ {
+ sal_uInt16 n;
+
+ for( n = rBoxes.Count(); n; )
+ ::lcl_SaveUpperLowerBorder( rParam.pTblNd->GetTable(),
+ *rBoxes[ --n ],
+ rParam.aShareFmts );
+ for( n = rBoxes.Count(); n; )
+ ::_DeleteBox( rParam.pTblNd->GetTable(),
+ rBoxes[ --n ], rParam.pUndo, sal_False,
+ sal_False, &rParam.aShareFmts );
+ }
+ else
+ {
+ // Zeile einfuegen
+ SwTableLine* pNewLine = new SwTableLine( (SwTableLineFmt*)pLine->GetFrmFmt(),
+ rBoxes.Count(), pLine->GetUpper() );
+ SwTableLines* pLines;
+ if( pLine->GetUpper() )
+ pLines = &pLine->GetUpper()->GetTabLines();
+ else
+ pLines = &rParam.pTblNd->GetTable().GetTabLines();
+ sal_uInt16 nPos = pLines->C40_GETPOS( SwTableLine, pLine );
+ if( !rParam.bTop )
+ ++nPos;
+ pLines->C40_INSERT( SwTableLine, pNewLine, nPos );
+
+ SwFrmFmt* pNewFmt = pNewLine->ClaimFrmFmt();
+ pNewFmt->SetFmtAttr( SwFmtFrmSize( ATT_MIN_SIZE, 0, nDist ) );
+
+ // und noch mal die Anzahl Boxen erzeugen
+ SwTableBoxes& rNewBoxes = pNewLine->GetTabBoxes();
+ for( sal_uInt16 n = 0; n < rBoxes.Count(); ++n )
+ {
+ SwTwips nWidth = 0;
+ SwTableBox* pOld = rBoxes[ n ];
+ if( !pOld->GetSttNd() )
+ {
+ // keine normale "Content"-Box also auf die 1. naechste
+ // Box zurueckfallen
+ nWidth = pOld->GetFrmFmt()->GetFrmSize().GetWidth();
+ while( !pOld->GetSttNd() )
+ pOld = pOld->GetTabLines()[ 0 ]->GetTabBoxes()[ 0 ];
+ }
+ ::_InsTblBox( pDoc, rParam.pTblNd, pNewLine,
+ (SwTableBoxFmt*)pOld->GetFrmFmt(), pOld, n );
+
+ // Sonderbehandlung fuer Umrandung die Obere muss
+ // entfernt werden
+ const SvxBoxItem& rBoxItem = pOld->GetFrmFmt()->GetBox();
+ if( rBoxItem.GetTop() )
+ {
+ SvxBoxItem aTmp( rBoxItem );
+ aTmp.SetLine( 0, BOX_LINE_TOP );
+ rParam.aShareFmts.SetAttr( rParam.bTop
+ ? *pOld
+ : *rNewBoxes[ n ], aTmp );
+ }
+
+ if( nWidth )
+ rParam.aShareFmts.SetAttr( *rNewBoxes[ n ],
+ SwFmtFrmSize( ATT_FIX_SIZE, nWidth, 0 ) );
+ }
+ }
+ }
+ else
+ {
+ // Boxen einsammeln!
+ SwTableBoxes& rBoxes = pLine->GetTabBoxes();
+ for( sal_uInt16 n = rBoxes.Count(); n; )
+ {
+ SwTableBox* pBox = rBoxes[ --n ];
+ if( pBox->GetFrmFmt()->GetProtect().IsCntntProtected() )
+ return sal_False;
+
+ if( pBox->GetSttNd() )
+ rParam.aBoxes.Insert( pBox );
+ else
+ {
+ for( sal_uInt16 i = pBox->GetTabLines().Count(); i; )
+ lcl_InsDelSelLine( pBox->GetTabLines()[ --i ],
+ rParam, 0, sal_True );
+ }
+ }
+ }
+ return bRet;
+}
+
+sal_Bool SwTable::SetRowHeight( SwTableBox& rAktBox, sal_uInt16 eType,
+ SwTwips nAbsDiff, SwTwips nRelDiff,SwUndo** ppUndo )
+{
+ SwTableLine* pLine = rAktBox.GetUpper();
+
+ SwTableLine* pBaseLine = pLine;
+ while( pBaseLine->GetUpper() )
+ pBaseLine = pBaseLine->GetUpper()->GetUpper();
+
+ _FndBox* pFndBox = 0; // fuers Einfuegen/Loeschen
+ SwTableSortBoxes aTmpLst( 0, 5 ); // fuers Undo
+ sal_Bool bBigger,
+ bRet = sal_False,
+ bTop = nsTblChgWidthHeightType::WH_ROW_TOP == ( eType & 0xff ) ||
+ nsTblChgWidthHeightType::WH_CELL_TOP == ( eType & 0xff ),
+ bInsDel = 0 != (eType & nsTblChgWidthHeightType::WH_FLAG_INSDEL );
+ sal_uInt16 n, nBaseLinePos = GetTabLines().C40_GETPOS( SwTableLine, pBaseLine );
+ sal_uLong nBoxIdx = rAktBox.GetSttIdx();
+
+ CR_SetLineHeight aParam( eType,
+ (SwTableNode*)rAktBox.GetSttNd()->FindTableNode() );
+ bBigger = aParam.bBigger;
+
+ FN_lcl_SetLineHeight fnSelLine, fnOtherLine = lcl_SetOtherLineHeight;
+ if( bInsDel )
+ fnSelLine = lcl_InsDelSelLine;
+ else
+ fnSelLine = lcl_SetSelLineHeight;
+
+ SwTableLines* pLines = &aLines;
+
+ // wie kommt man an die Hoehen heran?
+ switch( eType & 0xff )
+ {
+ case nsTblChgWidthHeightType::WH_CELL_TOP:
+ case nsTblChgWidthHeightType::WH_CELL_BOTTOM:
+ if( pLine == pBaseLine )
+ break; // dann geht es nicht!
+
+ // ist eine verschachtelte Line (Box!)
+ pLines = &pLine->GetUpper()->GetTabLines();
+ nBaseLinePos = pLines->C40_GETPOS( SwTableLine, pLine );
+ pBaseLine = pLine;
+ // kein break!
+
+ case nsTblChgWidthHeightType::WH_ROW_TOP:
+ case nsTblChgWidthHeightType::WH_ROW_BOTTOM:
+ {
+ if( bInsDel && !bBigger ) // um wieviel wird es Hoeher?
+ {
+ nAbsDiff = GetRowFrm( *pBaseLine )->Frm().Height();
+ }
+
+ if( TBLVAR_CHGABS == eTblChgMode )
+ {
+ // erstmal testen, ob ueberhaupt Platz ist
+ if( bBigger )
+ {
+ bRet = sal_True;
+// was ist mit Top, was ist mit Tabelle im Rahmen oder in Kopf-/Fusszeile
+// mit fester Hoehe ??
+ if( !bRet )
+ {
+ // dann sich selbst rekursiv aufrufen; nur mit
+ // einem anderen Mode -> proprotional
+ TblChgMode eOld = eTblChgMode;
+ eTblChgMode = TBLFIX_CHGPROP;
+
+ bRet = SetRowHeight( rAktBox, eType, nAbsDiff,
+ nRelDiff, ppUndo );
+
+ eTblChgMode = eOld;
+ return bRet;
+ }
+ }
+ else
+ bRet = (*fnSelLine)( (*pLines)[ nBaseLinePos ], aParam,
+ nAbsDiff, sal_True );
+
+ if( bRet )
+ {
+ if( bInsDel )
+ {
+ if( !aParam.aBoxes.Count() )
+ ::lcl_InsDelSelLine( (*pLines)[ nBaseLinePos ],
+ aParam, 0, sal_True );
+
+ pFndBox = ::lcl_SaveInsDelData( aParam, ppUndo, aTmpLst );
+
+ // delete complete table when last row is deleted
+ if( !bBigger &&
+ aParam.aBoxes.Count() == aSortCntBoxes.Count() )
+ {
+ GetFrmFmt()->GetDoc()->DeleteRowCol( aParam.aBoxes );
+ return sal_False;
+ }
+
+
+ if( ppUndo )
+ *ppUndo = aParam.CreateUndo(
+ bBigger ? UNDO_TABLE_INSROW
+ : UNDO_ROW_DELETE );
+ }
+ else if( ppUndo )
+ *ppUndo = new SwUndoAttrTbl( *aParam.pTblNd, sal_True );
+
+ (*fnSelLine)( (*pLines)[ nBaseLinePos ], aParam,
+ nAbsDiff, sal_False );
+ }
+ }
+ else
+ {
+ bRet = sal_True;
+ sal_uInt16 nStt, nEnd;
+ if( bTop )
+ nStt = 0, nEnd = nBaseLinePos;
+ else
+ nStt = nBaseLinePos + 1, nEnd = pLines->Count();
+
+ // die akt. Hoehe der Lines besorgen
+ if( TBLFIX_CHGPROP == eTblChgMode )
+ {
+ for( n = nStt; n < nEnd; ++n )
+ {
+ SwLayoutFrm* pLineFrm = GetRowFrm( *(*pLines)[ n ] );
+ OSL_ENSURE( pLineFrm, "wo ist der Frm von der SwTableLine?" );
+ aParam.nMaxSpace += CalcRowRstHeight( pLineFrm );
+ aParam.nMaxHeight += pLineFrm->Frm().Height();
+ }
+ if( bBigger && aParam.nMaxSpace < nAbsDiff )
+ bRet = sal_False;
+ }
+ else
+ {
+ if( bTop ? nEnd : nStt < nEnd )
+ {
+ if( bTop )
+ nStt = nEnd - 1;
+ else
+ nEnd = nStt + 1;
+ }
+ else
+ bRet = sal_False;
+ }
+
+ if( bRet )
+ {
+ if( bBigger )
+ {
+ for( n = nStt; n < nEnd; ++n )
+ {
+ if( !(*fnOtherLine)( (*pLines)[ n ], aParam,
+ nAbsDiff, sal_True ))
+ {
+ bRet = sal_False;
+ break;
+ }
+ }
+ }
+ else
+ bRet = (*fnSelLine)( (*pLines)[ nBaseLinePos ], aParam,
+ nAbsDiff, sal_True );
+ }
+
+ if( bRet )
+ {
+ // dann mal anpassen
+ if( bInsDel )
+ {
+ if( !aParam.aBoxes.Count() )
+ ::lcl_InsDelSelLine( (*pLines)[ nBaseLinePos ],
+ aParam, 0, sal_True );
+ pFndBox = ::lcl_SaveInsDelData( aParam, ppUndo, aTmpLst );
+ if( ppUndo )
+ *ppUndo = aParam.CreateUndo(
+ bBigger ? UNDO_TABLE_INSROW
+ : UNDO_ROW_DELETE );
+ }
+ else if( ppUndo )
+ *ppUndo = new SwUndoAttrTbl( *aParam.pTblNd, sal_True );
+
+ CR_SetLineHeight aParam1( aParam );
+ if( TBLFIX_CHGPROP == eTblChgMode && !bBigger &&
+ !aParam.nMaxSpace )
+ {
+ // dann muss der gesamte Platz auf alle Lines
+ // gleichmaessig verteilt werden. Dafuer wird die
+ // Anzahl benoetigt
+ aParam1.nLines = nEnd - nStt;
+ }
+
+ if( bTop )
+ {
+ (*fnSelLine)( (*pLines)[ nBaseLinePos ], aParam,
+ nAbsDiff, sal_False );
+ for( n = nStt; n < nEnd; ++n )
+ (*fnOtherLine)( (*pLines)[ n ], aParam1,
+ nAbsDiff, sal_False );
+ }
+ else
+ {
+ for( n = nStt; n < nEnd; ++n )
+ (*fnOtherLine)( (*pLines)[ n ], aParam1,
+ nAbsDiff, sal_False );
+ (*fnSelLine)( (*pLines)[ nBaseLinePos ], aParam,
+ nAbsDiff, sal_False );
+ }
+ }
+ else
+ {
+ // dann sich selbst rekursiv aufrufen; nur mit
+ // einem anderen Mode -> proprotional
+ TblChgMode eOld = eTblChgMode;
+ eTblChgMode = TBLVAR_CHGABS;
+
+ bRet = SetRowHeight( rAktBox, eType, nAbsDiff,
+ nRelDiff, ppUndo );
+
+ eTblChgMode = eOld;
+ pFndBox = 0;
+ }
+ }
+ }
+ break;
+ }
+
+ if( pFndBox )
+ {
+ // dann raeume die Struktur aller Lines auf
+ GCLines();
+
+ //Layout updaten
+ if( bBigger || pFndBox->AreLinesToRestore( *this ) )
+ pFndBox->MakeFrms( *this );
+
+ // TL_CHART2: it is currently unclear if sth has to be done here.
+
+ delete pFndBox;
+
+ if( ppUndo && *ppUndo )
+ {
+ aParam.pUndo->SetColWidthParam( nBoxIdx, static_cast<sal_uInt16>(eTblChgMode), eType,
+ nAbsDiff, nRelDiff );
+ if( bBigger )
+ aParam.pUndo->SaveNewBoxes( *aParam.pTblNd, aTmpLst );
+ }
+ }
+
+ CHECKTABLELAYOUT
+
+ return bRet;
+}
+
+SwFrmFmt* SwShareBoxFmt::GetFormat( long nWidth ) const
+{
+ SwFrmFmt *pRet = 0, *pTmp;
+ for( sal_uInt16 n = aNewFmts.Count(); n; )
+ if( ( pTmp = (SwFrmFmt*)aNewFmts[ --n ])->GetFrmSize().GetWidth()
+ == nWidth )
+ {
+ pRet = pTmp;
+ break;
+ }
+ return pRet;
+}
+
+SwFrmFmt* SwShareBoxFmt::GetFormat( const SfxPoolItem& rItem ) const
+{
+ const SfxPoolItem* pItem;
+ sal_uInt16 nWhich = rItem.Which();
+ SwFrmFmt *pRet = 0, *pTmp;
+ const SfxPoolItem& rFrmSz = pOldFmt->GetFmtAttr( RES_FRM_SIZE, sal_False );
+ for( sal_uInt16 n = aNewFmts.Count(); n; )
+ if( SFX_ITEM_SET == ( pTmp = (SwFrmFmt*)aNewFmts[ --n ])->
+ GetItemState( nWhich, sal_False, &pItem ) && *pItem == rItem &&
+ pTmp->GetFmtAttr( RES_FRM_SIZE, sal_False ) == rFrmSz )
+ {
+ pRet = pTmp;
+ break;
+ }
+ return pRet;
+}
+
+void SwShareBoxFmt::AddFormat( const SwFrmFmt& rNew )
+{
+ void* pFmt = (void*)&rNew;
+ aNewFmts.Insert( pFmt, aNewFmts.Count() );
+}
+
+sal_Bool SwShareBoxFmt::RemoveFormat( const SwFrmFmt& rFmt )
+{
+ // returnt sal_True, wenn geloescht werden kann
+ if( pOldFmt == &rFmt )
+ return sal_True;
+
+ void* p = (void*)&rFmt;
+ sal_uInt16 nFnd = aNewFmts.GetPos( p );
+ if( USHRT_MAX != nFnd )
+ aNewFmts.Remove( nFnd );
+ return 0 == aNewFmts.Count();
+}
+
+SwShareBoxFmts::~SwShareBoxFmts()
+{
+}
+
+SwFrmFmt* SwShareBoxFmts::GetFormat( const SwFrmFmt& rFmt, long nWidth ) const
+{
+ sal_uInt16 nPos;
+ return Seek_Entry( rFmt, &nPos )
+ ? aShareArr[ nPos ]->GetFormat( nWidth )
+ : 0;
+}
+SwFrmFmt* SwShareBoxFmts::GetFormat( const SwFrmFmt& rFmt,
+ const SfxPoolItem& rItem ) const
+{
+ sal_uInt16 nPos;
+ return Seek_Entry( rFmt, &nPos )
+ ? aShareArr[ nPos ]->GetFormat( rItem )
+ : 0;
+}
+
+void SwShareBoxFmts::AddFormat( const SwFrmFmt& rOld, const SwFrmFmt& rNew )
+{
+ {
+ sal_uInt16 nPos;
+ SwShareBoxFmt* pEntry;
+ if( !Seek_Entry( rOld, &nPos ))
+ {
+ pEntry = new SwShareBoxFmt( rOld );
+ aShareArr.C40_INSERT( SwShareBoxFmt, pEntry, nPos );
+ }
+ else
+ pEntry = aShareArr[ nPos ];
+
+ pEntry->AddFormat( rNew );
+ }
+}
+
+void SwShareBoxFmts::ChangeFrmFmt( SwTableBox* pBox, SwTableLine* pLn,
+ SwFrmFmt& rFmt )
+{
+ SwClient aCl;
+ SwFrmFmt* pOld = 0;
+ if( pBox )
+ {
+ pOld = pBox->GetFrmFmt();
+ pOld->Add( &aCl );
+ pBox->ChgFrmFmt( (SwTableBoxFmt*)&rFmt );
+ }
+ else if( pLn )
+ {
+ pOld = pLn->GetFrmFmt();
+ pOld->Add( &aCl );
+ pLn->ChgFrmFmt( (SwTableLineFmt*)&rFmt );
+ }
+ if( pOld && pOld->IsLastDepend() )
+ {
+ RemoveFormat( *pOld );
+ delete pOld;
+ }
+}
+
+void SwShareBoxFmts::SetSize( SwTableBox& rBox, const SwFmtFrmSize& rSz )
+{
+ SwFrmFmt *pBoxFmt = rBox.GetFrmFmt(),
+ *pRet = GetFormat( *pBoxFmt, rSz.GetWidth() );
+ if( pRet )
+ ChangeFrmFmt( &rBox, 0, *pRet );
+ else
+ {
+ pRet = rBox.ClaimFrmFmt();
+ pRet->SetFmtAttr( rSz );
+ AddFormat( *pBoxFmt, *pRet );
+ }
+}
+
+void SwShareBoxFmts::SetAttr( SwTableBox& rBox, const SfxPoolItem& rItem )
+{
+ SwFrmFmt *pBoxFmt = rBox.GetFrmFmt(),
+ *pRet = GetFormat( *pBoxFmt, rItem );
+ if( pRet )
+ ChangeFrmFmt( &rBox, 0, *pRet );
+ else
+ {
+ pRet = rBox.ClaimFrmFmt();
+ pRet->SetFmtAttr( rItem );
+ AddFormat( *pBoxFmt, *pRet );
+ }
+}
+
+void SwShareBoxFmts::SetAttr( SwTableLine& rLine, const SfxPoolItem& rItem )
+{
+ SwFrmFmt *pLineFmt = rLine.GetFrmFmt(),
+ *pRet = GetFormat( *pLineFmt, rItem );
+ if( pRet )
+ ChangeFrmFmt( 0, &rLine, *pRet );
+ else
+ {
+ pRet = rLine.ClaimFrmFmt();
+ pRet->SetFmtAttr( rItem );
+ AddFormat( *pLineFmt, *pRet );
+ }
+}
+
+void SwShareBoxFmts::RemoveFormat( const SwFrmFmt& rFmt )
+{
+ for( sal_uInt16 i = aShareArr.Count(); i; )
+ if( aShareArr[ --i ]->RemoveFormat( rFmt ))
+ aShareArr.DeleteAndDestroy( i );
+}
+
+sal_Bool SwShareBoxFmts::Seek_Entry( const SwFrmFmt& rFmt, sal_uInt16* pPos ) const
+{
+ sal_uLong nIdx = (sal_uLong)&rFmt;
+ sal_uInt16 nO = aShareArr.Count(), nM, nU = 0;
+ if( nO > 0 )
+ {
+ nO--;
+ while( nU <= nO )
+ {
+ nM = nU + ( nO - nU ) / 2;
+ sal_uLong nFmt = (sal_uLong)&aShareArr[ nM ]->GetOldFormat();
+ if( nFmt == nIdx )
+ {
+ if( pPos )
+ *pPos = nM;
+ return sal_True;
+ }
+ else if( nFmt < nIdx )
+ nU = nM + 1;
+ else if( nM == 0 )
+ {
+ if( pPos )
+ *pPos = nU;
+ return sal_False;
+ }
+ else
+ nO = nM - 1;
+ }
+ }
+ if( pPos )
+ *pPos = nU;
+ return sal_False;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/doc/visiturl.cxx b/sw/source/core/doc/visiturl.cxx
new file mode 100644
index 000000000000..b269451ac512
--- /dev/null
+++ b/sw/source/core/doc/visiturl.cxx
@@ -0,0 +1,141 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+
+#include <sfx2/docfile.hxx>
+#include <svl/inethist.hxx>
+#include <fmtinfmt.hxx>
+#include <txtinet.hxx>
+#include <doc.hxx>
+#include <visiturl.hxx>
+#include <hints.hxx>
+#include <ndtxt.hxx>
+#include <editsh.hxx>
+#include <docsh.hxx>
+
+
+SwURLStateChanged::SwURLStateChanged( const SwDoc* pD )
+ : pDoc( pD )
+{
+ StartListening( *INetURLHistory::GetOrCreate() );
+}
+
+SwURLStateChanged::~SwURLStateChanged()
+{
+ EndListening( *INetURLHistory::GetOrCreate() );
+}
+
+void SwURLStateChanged::Notify( SfxBroadcaster& , const SfxHint& rHint )
+{
+ if( rHint.ISA( INetURLHistoryHint ) && pDoc->GetCurrentViewShell() ) //swmod 071108//swmod 071225
+ {
+ // diese URL wurde veraendert:
+ const INetURLObject* pIURL = ((INetURLHistoryHint&)rHint).GetObject();
+ String sURL( pIURL->GetMainURL( INetURLObject::NO_DECODE ) ), sBkmk;
+
+ SwEditShell* pESh = pDoc->GetEditShell();
+
+ if( pDoc->GetDocShell() && pDoc->GetDocShell()->GetMedium() &&
+ // falls das unser Doc ist, kann es auch lokale Spruenge geben!
+ sURL == pDoc->GetDocShell()->GetMedium()->GetName() )
+ (sBkmk = pIURL->GetMark()).Insert( INET_MARK_TOKEN, 0 );
+
+ sal_Bool bAction = sal_False, bUnLockView = sal_False;
+ const SwFmtINetFmt* pItem;
+ const SwTxtINetFmt* pTxtAttr;
+ const SwTxtNode* pTxtNd;
+ sal_uInt32 n, nMaxItems = pDoc->GetAttrPool().GetItemCount2( RES_TXTATR_INETFMT );
+ for( n = 0; n < nMaxItems; ++n )
+ if( 0 != (pItem = (SwFmtINetFmt*)pDoc->GetAttrPool().GetItem2(
+ RES_TXTATR_INETFMT, n ) ) &&
+ ( pItem->GetValue() == sURL ||
+ ( sBkmk.Len() && pItem->GetValue() == sBkmk )) &&
+ 0 != ( pTxtAttr = pItem->GetTxtINetFmt()) &&
+ 0 != ( pTxtNd = pTxtAttr->GetpTxtNode() ) )
+ {
+ if( !bAction && pESh )
+ {
+ pESh->StartAllAction();
+ bAction = sal_True;
+ bUnLockView = !pESh->IsViewLocked();
+ pESh->LockView( sal_True );
+ }
+ const_cast<SwTxtINetFmt*>(pTxtAttr)->SetVisitedValid( false );
+ const SwTxtAttr* pAttr = pTxtAttr;
+ SwUpdateAttr aUpdateAttr( *pAttr->GetStart(),
+ *pAttr->GetEnd(),
+ RES_FMT_CHG );
+ ((SwTxtNode*)pTxtNd)->ModifyNotification( &aUpdateAttr, &aUpdateAttr );
+ }
+
+ if( bAction )
+ pESh->EndAllAction();
+ if( bUnLockView )
+ pESh->LockView( sal_False );
+ }
+}
+
+ // erfrage ob die URL besucht war. Uebers Doc, falls nur ein Bookmark
+ // angegeben ist. Dann muss der Doc. Name davor gesetzt werden!
+sal_Bool SwDoc::IsVisitedURL( const String& rURL ) const
+{
+#if OSL_DEBUG_LEVEL > 1
+ static long nTmp = 0;
+ ++nTmp;
+#endif
+
+ sal_Bool bRet = sal_False;
+ if( rURL.Len() )
+ {
+ INetURLHistory *pHist = INetURLHistory::GetOrCreate();
+ if( '#' == rURL.GetChar( 0 ) && pDocShell && pDocShell->GetMedium() )
+ {
+ INetURLObject aIObj( pDocShell->GetMedium()->GetURLObject() );
+ aIObj.SetMark( rURL.Copy( 1 ) );
+ bRet = pHist->QueryUrl( aIObj );
+ }
+ else
+ bRet = pHist->QueryUrl( rURL );
+
+ // dann wollen wird auch ueber Statusaenderungen in der History
+ // informiert werden!
+ if( !pURLStateChgd )
+ {
+ SwDoc* pD = (SwDoc*)this;
+ pD->pURLStateChgd = new SwURLStateChanged( this );
+ }
+ }
+ return bRet;
+}
+
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/docnode/cancellablejob.cxx b/sw/source/core/docnode/cancellablejob.cxx
new file mode 100644
index 000000000000..ec32c602137f
--- /dev/null
+++ b/sw/source/core/docnode/cancellablejob.cxx
@@ -0,0 +1,43 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+#include "precompiled_sw.hxx"
+#include <cancellablejob.hxx>
+#include <observablethread.hxx>
+
+CancellableJob::CancellableJob( const rtl::Reference< ObservableThread >& rThread ) :
+ mrThread( rThread )
+{
+}
+
+// ::com::sun::star::util::XCancellable:
+void SAL_CALL CancellableJob::cancel() throw (com::sun::star::uno::RuntimeException)
+{
+ mrThread->join();
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/docnode/cancellablejob.hxx b/sw/source/core/docnode/cancellablejob.hxx
new file mode 100644
index 000000000000..d675159f757b
--- /dev/null
+++ b/sw/source/core/docnode/cancellablejob.hxx
@@ -0,0 +1,56 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+#ifndef _CANCELLABLEJOB_HXX
+#define _CANCELLABLEJOB_HXX
+
+#include "sal/config.h"
+#include "cppuhelper/implbase1.hxx"
+#include "com/sun/star/util/XCancellable.hpp"
+
+#include <rtl/ref.hxx>
+
+class ObservableThread;
+
+class CancellableJob : public ::cppu::WeakImplHelper1<com::sun::star::util::XCancellable>
+{
+public:
+ explicit CancellableJob( const ::rtl::Reference< ObservableThread >& rThread );
+ ~CancellableJob() {}
+
+ // ::com::sun::star::util::XCancellable:
+ virtual void SAL_CALL cancel() throw (com::sun::star::uno::RuntimeException);
+
+private:
+ CancellableJob( CancellableJob& ); // not defined
+ void operator =( CancellableJob& ); // not defined
+
+ ::rtl::Reference< ObservableThread > mrThread;
+};
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/docnode/finalthreadmanager.cxx b/sw/source/core/docnode/finalthreadmanager.cxx
new file mode 100644
index 000000000000..f1ab71a0f1eb
--- /dev/null
+++ b/sw/source/core/docnode/finalthreadmanager.cxx
@@ -0,0 +1,505 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+#include "precompiled_sw.hxx"
+#include <finalthreadmanager.hxx>
+
+#include <osl/thread.hxx>
+#include <pausethreadstarting.hxx>
+#include <swthreadjoiner.hxx>
+
+#include <com/sun/star/frame/XDesktop.hpp>
+#include <rtl/ustring.hxx>
+#include <com/sun/star/frame/XFramesSupplier.hpp>
+
+namespace css = ::com::sun::star;
+
+/** thread to cancel a give list of cancellable jobs
+
+ helper class for FinalThreadManager
+
+ @author OD
+*/
+class CancelJobsThread : public osl::Thread
+{
+ public:
+ CancelJobsThread( std::list< css::uno::Reference< css::util::XCancellable > > aJobs )
+ : osl::Thread(),
+ maMutex(),
+ maJobs( aJobs ),
+ mbAllJobsCancelled( false ),
+ mbStopped( false )
+ {
+ }
+
+ virtual ~CancelJobsThread() {}
+
+ void addJobs( std::list< css::uno::Reference< css::util::XCancellable > >& rJobs );
+ bool allJobsCancelled() const;
+ void stopWhenAllJobsCancelled();
+
+ private:
+ bool existJobs() const;
+
+ css::uno::Reference< css::util::XCancellable > getNextJob();
+
+ bool stopped() const;
+ virtual void SAL_CALL run();
+ mutable osl::Mutex maMutex;
+
+ std::list< css::uno::Reference< css::util::XCancellable > > maJobs;
+
+ bool mbAllJobsCancelled;
+ bool mbStopped;
+};
+
+void CancelJobsThread::addJobs( std::list< css::uno::Reference< css::util::XCancellable > >& rJobs )
+{
+ osl::MutexGuard aGuard(maMutex);
+
+ maJobs.insert( maJobs.end(), rJobs.begin(), rJobs.end() );
+ mbAllJobsCancelled = !maJobs.empty();
+}
+
+bool CancelJobsThread::existJobs() const
+{
+ osl::MutexGuard aGuard(maMutex);
+
+ return !maJobs.empty();
+}
+
+bool CancelJobsThread::allJobsCancelled() const
+{
+ osl::MutexGuard aGuard(maMutex);
+
+ return maJobs.empty() && mbAllJobsCancelled;
+}
+void CancelJobsThread::stopWhenAllJobsCancelled()
+{
+ osl::MutexGuard aGuard(maMutex);
+
+ mbStopped = true;
+}
+
+css::uno::Reference< css::util::XCancellable > CancelJobsThread::getNextJob()
+{
+ css::uno::Reference< css::util::XCancellable > xRet;
+
+ {
+ osl::MutexGuard aGuard(maMutex);
+
+ if ( !maJobs.empty() )
+ {
+ xRet = maJobs.front();
+ maJobs.pop_front();
+ }
+ }
+
+ return xRet;
+}
+
+bool CancelJobsThread::stopped() const
+{
+ osl::MutexGuard aGuard(maMutex);
+
+ return mbStopped;
+}
+
+void SAL_CALL CancelJobsThread::run()
+{
+ while ( !stopped() )
+ {
+ while ( existJobs() )
+ {
+ css::uno::Reference< css::util::XCancellable > aJob( getNextJob() );
+ if ( aJob.is() )
+ aJob->cancel();
+ }
+
+ mbAllJobsCancelled = true;
+
+ {
+ TimeValue aSleepTime;
+ aSleepTime.Seconds = 1;
+ aSleepTime.Nanosec = 0;
+ osl_waitThread( &aSleepTime );
+ }
+ }
+}
+
+/** thread to terminate office, when all jobs are cancelled.
+
+ helper class for FinalThreadManager
+
+ @author OD
+*/
+class TerminateOfficeThread : public osl::Thread
+{
+ public:
+ TerminateOfficeThread( CancelJobsThread& rCancelJobsThread,
+ css::uno::Reference< css::uno::XComponentContext > const & xContext )
+ : osl::Thread(),
+ maMutex(),
+ mrCancelJobsThread( rCancelJobsThread ),
+ mbStopOfficeTermination( false ),
+ mxContext( xContext )
+ {
+ }
+
+ virtual ~TerminateOfficeThread() {}
+ void StopOfficeTermination();
+
+ private:
+ virtual void SAL_CALL run();
+ virtual void SAL_CALL onTerminated();
+ bool OfficeTerminationStopped();
+ void PerformOfficeTermination();
+
+ osl::Mutex maMutex;
+
+ const CancelJobsThread& mrCancelJobsThread;
+ bool mbStopOfficeTermination;
+
+ css::uno::Reference< css::uno::XComponentContext > mxContext;
+};
+
+void TerminateOfficeThread::StopOfficeTermination()
+{
+ osl::MutexGuard aGuard(maMutex);
+
+ mbStopOfficeTermination = true;
+}
+
+bool TerminateOfficeThread::OfficeTerminationStopped()
+{
+ osl::MutexGuard aGuard(maMutex);
+
+ return mbStopOfficeTermination;
+}
+
+void SAL_CALL TerminateOfficeThread::run()
+{
+ while ( !OfficeTerminationStopped() )
+ {
+ osl::MutexGuard aGuard(maMutex);
+
+ if ( mrCancelJobsThread.allJobsCancelled() )
+ break;
+ }
+
+ if ( !OfficeTerminationStopped() )
+ PerformOfficeTermination();
+}
+
+void TerminateOfficeThread::PerformOfficeTermination()
+{
+ css::uno::Reference< css::frame::XFramesSupplier > xTasksSupplier(
+ mxContext->getServiceManager()->createInstanceWithContext(
+ ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.frame.Desktop") ),
+ mxContext ),
+ css::uno::UNO_QUERY );
+ if ( !xTasksSupplier.is() )
+ {
+ OSL_FAIL( "<TerminateOfficeThread::PerformOfficeTermination()> - no XFramesSupplier!" );
+ return;
+ }
+
+ css::uno::Reference< css::container::XElementAccess > xList( xTasksSupplier->getFrames(), css::uno::UNO_QUERY );
+ if ( !xList.is() )
+ {
+ OSL_FAIL( "<TerminateOfficeThread::PerformOfficeTermination()> - no XElementAccess!" );
+ return;
+ }
+
+ if ( !xList->hasElements() )
+ {
+ css::uno::Reference< css::frame::XDesktop > xDesktop( xTasksSupplier, css::uno::UNO_QUERY );
+ if ( xDesktop.is() && !OfficeTerminationStopped() )
+ xDesktop->terminate();
+ }
+}
+
+void SAL_CALL TerminateOfficeThread::onTerminated()
+{
+ if ( OfficeTerminationStopped() )
+ delete this;
+}
+
+
+/** class FinalThreadManager
+
+ @author OD
+*/
+FinalThreadManager::FinalThreadManager(css::uno::Reference< css::uno::XComponentContext > const & context)
+ : m_xContext(context),
+ maMutex(),
+ maThreads(),
+ mpCancelJobsThread( 0 ),
+ mpTerminateOfficeThread( 0 ),
+ mpPauseThreadStarting( 0 ),
+ mbRegisteredAtDesktop( false )
+{
+
+}
+
+void FinalThreadManager::registerAsListenerAtDesktop()
+{
+ css::uno::Reference< css::frame::XDesktop > xDesktop(
+ m_xContext->getServiceManager()->createInstanceWithContext(
+ ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.frame.Desktop") ),
+ m_xContext ),
+ css::uno::UNO_QUERY );
+
+ if ( xDesktop.is() )
+ xDesktop->addTerminateListener( css::uno::Reference< css::frame::XTerminateListener >( static_cast< cppu::OWeakObject* >( this ), css::uno::UNO_QUERY ) );
+}
+
+FinalThreadManager::~FinalThreadManager()
+{
+ if ( mpPauseThreadStarting != 0 )
+ {
+ delete mpPauseThreadStarting;
+ mpPauseThreadStarting = 0;
+ }
+
+ if ( mpTerminateOfficeThread != 0 )
+ {
+ mpTerminateOfficeThread->StopOfficeTermination(); // thread kills itself.
+ mpTerminateOfficeThread = 0;
+ }
+
+ if ( !maThreads.empty() )
+ {
+ OSL_FAIL( "<FinalThreadManager::~FinalThreadManager()> - still registered jobs are existing -> perform cancellation" );
+ cancelAllJobs();
+ }
+
+ if ( mpCancelJobsThread != 0 )
+ {
+ if ( !mpCancelJobsThread->allJobsCancelled() )
+ OSL_FAIL( "<FinalThreadManager::~FinalThreadManager()> - cancellation of registered jobs not yet finished -> wait for its finish" );
+
+ mpCancelJobsThread->stopWhenAllJobsCancelled();
+ mpCancelJobsThread->join();
+ delete mpCancelJobsThread;
+ mpCancelJobsThread = 0;
+ }
+}
+
+// com.sun.star.uno.XServiceInfo:
+::rtl::OUString SAL_CALL FinalThreadManager::getImplementationName() throw (css::uno::RuntimeException)
+{
+ return comp_FinalThreadManager::_getImplementationName();
+}
+
+::sal_Bool SAL_CALL FinalThreadManager::supportsService(::rtl::OUString const & serviceName) throw (css::uno::RuntimeException)
+{
+ css::uno::Sequence< ::rtl::OUString > serviceNames = comp_FinalThreadManager::_getSupportedServiceNames();
+ for (::sal_Int32 i = 0; i < serviceNames.getLength(); ++i) {
+ if (serviceNames[i] == serviceName)
+ return sal_True;
+ }
+ return sal_False;
+}
+
+css::uno::Sequence< ::rtl::OUString > SAL_CALL FinalThreadManager::getSupportedServiceNames() throw (css::uno::RuntimeException)
+{
+ return comp_FinalThreadManager::_getSupportedServiceNames();
+}
+
+// ::com::sun::star::util::XJobManager:
+void SAL_CALL FinalThreadManager::registerJob(const css::uno::Reference< css::util::XCancellable > & Job) throw (css::uno::RuntimeException)
+{
+ osl::MutexGuard aGuard(maMutex);
+
+ maThreads.push_back( Job );
+
+ if ( !mbRegisteredAtDesktop )
+ {
+ registerAsListenerAtDesktop();
+ mbRegisteredAtDesktop = true;
+ }
+}
+
+void SAL_CALL FinalThreadManager::releaseJob(const css::uno::Reference< css::util::XCancellable > & Job) throw (css::uno::RuntimeException)
+{
+ osl::MutexGuard aGuard(maMutex);
+
+ maThreads.remove( Job );
+}
+
+void SAL_CALL FinalThreadManager::cancelAllJobs() throw (css::uno::RuntimeException)
+{
+ std::list< css::uno::Reference< css::util::XCancellable > > aThreads;
+ {
+ osl::MutexGuard aGuard(maMutex);
+
+ aThreads.insert( aThreads.end(), maThreads.begin(), maThreads.end() );
+ maThreads.clear();
+ }
+
+ if ( !aThreads.empty() )
+ {
+ osl::MutexGuard aGuard(maMutex);
+
+ if ( mpCancelJobsThread == 0 )
+ {
+ mpCancelJobsThread = new CancelJobsThread( aThreads );;
+ if ( !mpCancelJobsThread->create() )
+ {
+ delete mpCancelJobsThread;
+ mpCancelJobsThread = 0;
+ while ( !aThreads.empty() )
+ {
+ aThreads.front()->cancel();
+ aThreads.pop_front();
+ }
+ }
+ }
+ else
+ mpCancelJobsThread->addJobs( aThreads );
+ }
+}
+
+// ::com::sun::star::frame::XTerminateListener
+void SAL_CALL FinalThreadManager::queryTermination( const css::lang::EventObject& ) throw (css::frame::TerminationVetoException, css::uno::RuntimeException)
+{
+ osl::MutexGuard aGuard(maMutex);
+
+ cancelAllJobs();
+ // Sleep 1 second to give the thread for job cancellation some time.
+ // Probably, all started threads have already finished its work.
+ if ( mpCancelJobsThread != 0 &&
+ !mpCancelJobsThread->allJobsCancelled() )
+ {
+ TimeValue aSleepTime;
+ aSleepTime.Seconds = 1;
+ aSleepTime.Nanosec = 0;
+ osl_waitThread( &aSleepTime );
+ }
+
+ if ( mpCancelJobsThread != 0 &&
+ !mpCancelJobsThread->allJobsCancelled() )
+ {
+ if ( mpTerminateOfficeThread != 0 )
+ {
+ if ( mpTerminateOfficeThread->isRunning() )
+ mpTerminateOfficeThread->StopOfficeTermination(); // thread kills itself.
+ else
+ delete mpTerminateOfficeThread;
+
+ mpTerminateOfficeThread = 0;
+ }
+ mpTerminateOfficeThread = new TerminateOfficeThread( *mpCancelJobsThread,
+ m_xContext );
+ if ( !mpTerminateOfficeThread->create() )
+ {
+ delete mpTerminateOfficeThread;
+ mpTerminateOfficeThread = 0;
+ }
+
+ throw css::frame::TerminationVetoException();
+ }
+
+ mpPauseThreadStarting = new SwPauseThreadStarting();
+
+ return;
+}
+
+void SAL_CALL FinalThreadManager::cancelTermination( const css::lang::EventObject& ) throw (css::uno::RuntimeException)
+{
+ if ( mpPauseThreadStarting != 0 )
+ {
+ delete mpPauseThreadStarting;
+ mpPauseThreadStarting = 0;
+ }
+
+ return;
+}
+
+void SAL_CALL FinalThreadManager::notifyTermination( const css::lang::EventObject& ) throw (css::uno::RuntimeException)
+{
+ if ( mpTerminateOfficeThread != 0 )
+ {
+ if ( mpTerminateOfficeThread->isRunning() )
+ mpTerminateOfficeThread->StopOfficeTermination(); // thread kills itself.
+ else
+ delete mpTerminateOfficeThread;
+
+ mpTerminateOfficeThread = 0;
+ }
+
+ if ( !maThreads.empty() )
+ cancelAllJobs();
+
+ if ( mpCancelJobsThread != 0 )
+ {
+ mpCancelJobsThread->stopWhenAllJobsCancelled();
+ mpCancelJobsThread->join();
+ delete mpCancelJobsThread;
+ mpCancelJobsThread = 0;
+ }
+
+ // get reference of this
+ css::uno::Reference< css::uno::XInterface > aOwnRef( static_cast< cppu::OWeakObject* >( this ));
+ // notify <SwThreadJoiner> to release its reference
+ SwThreadJoiner::ReleaseThreadJoiner();
+}
+
+// ::com::sun:star::lang::XEventListener (inherited via com::sun::star::frame::XTerminateListener)
+void SAL_CALL FinalThreadManager::disposing( const css::lang::EventObject& ) throw (css::uno::RuntimeException)
+{
+ // nothing to do, because instance doesn't hold any references of observed objects
+}
+
+// component helper namespace
+namespace comp_FinalThreadManager {
+
+ ::rtl::OUString SAL_CALL _getImplementationName()
+ {
+ return ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
+ "com.sun.star.util.comp.FinalThreadManager"));
+ }
+
+ css::uno::Sequence< ::rtl::OUString > SAL_CALL _getSupportedServiceNames()
+ {
+ css::uno::Sequence< ::rtl::OUString > s(1);
+ s[0] = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
+ "com.sun.star.util.JobManager"));
+ return s;
+ }
+
+ css::uno::Reference< css::uno::XInterface > SAL_CALL _create(
+ const css::uno::Reference< css::uno::XComponentContext > & context)
+ SAL_THROW((css::uno::Exception))
+ {
+ return static_cast< ::cppu::OWeakObject * >(new FinalThreadManager(context));
+ }
+
+} // closing component helper namespace
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/docnode/ndcopy.cxx b/sw/source/core/docnode/ndcopy.cxx
new file mode 100644
index 000000000000..090c9654b501
--- /dev/null
+++ b/sw/source/core/docnode/ndcopy.cxx
@@ -0,0 +1,1620 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+#include <editeng/brkitem.hxx>
+
+#define _ZFORLIST_DECLARE_TABLE
+#include <hintids.hxx>
+#include <fmtpdsc.hxx>
+#include <fmtanchr.hxx>
+#include <fmtcntnt.hxx>
+#include <doc.hxx>
+#include <IDocumentUndoRedo.hxx>
+#include <pam.hxx>
+#include <ndtxt.hxx>
+#include <fldbas.hxx>
+#include <swtable.hxx>
+#include <ddefld.hxx>
+#include <undobj.hxx>
+#include <IMark.hxx>
+#include <mvsave.hxx>
+#include <cellatr.hxx>
+#include <swtblfmt.hxx>
+#include <swddetbl.hxx>
+#include <docary.hxx>
+#include <fmtcnct.hxx>
+#include <redline.hxx>
+#include <paratr.hxx>
+#include <pagedesc.hxx>
+#include <poolfmt.hxx>
+#include <SwNodeNum.hxx>
+
+#if OSL_DEBUG_LEVEL > 1
+#define CHECK_TABLE(t) (t).CheckConsistency();
+#else
+#define CHECK_TABLE(t)
+#endif
+
+namespace
+{
+ /*
+ The lcl_CopyBookmarks function has to copy bookmarks from the source to the destination nodes
+ array. It is called after a call of the _CopyNodes(..) function. But this function does not copy
+ every node (at least at the moment: 2/08/2006 ), section start and end nodes will not be copied if the corresponding end/start node is outside the copied pam.
+ The lcl_NonCopyCount function counts the number of these nodes, given the copied pam and a node
+ index inside the pam.
+ rPam is the original source pam, rLastIdx is the last calculated position, rDelCount the number
+ of "non-copy" nodes between rPam.Start() and rLastIdx.
+ nNewIdx is the new position of interest.
+ */
+
+ static void lcl_NonCopyCount( const SwPaM& rPam, SwNodeIndex& rLastIdx, const sal_uLong nNewIdx, sal_uLong& rDelCount )
+ {
+ sal_uLong nStart = rPam.Start()->nNode.GetIndex();
+ sal_uLong nEnd = rPam.End()->nNode.GetIndex();
+ if( rLastIdx.GetIndex() < nNewIdx ) // Moving forward?
+ {
+ do // count "non-copy" nodes
+ {
+ SwNode& rNode = rLastIdx.GetNode();
+ if( ( rNode.IsSectionNode() && rNode.EndOfSectionIndex() >= nEnd )
+ || ( rNode.IsEndNode() && rNode.StartOfSectionNode()->GetIndex() < nStart ) )
+ ++rDelCount;
+ rLastIdx++;
+ }
+ while( rLastIdx.GetIndex() < nNewIdx );
+ }
+ else if( rDelCount ) // optimization: if there are no "non-copy" nodes until now,
+ // no move backward needed
+ {
+ while( rLastIdx.GetIndex() > nNewIdx )
+ {
+ SwNode& rNode = rLastIdx.GetNode();
+ if( ( rNode.IsSectionNode() && rNode.EndOfSectionIndex() >= nEnd )
+ || ( rNode.IsEndNode() && rNode.StartOfSectionNode()->GetIndex() < nStart ) )
+ --rDelCount;
+ rLastIdx--;
+ }
+ }
+ }
+
+ static void lcl_SetCpyPos( const SwPosition& rOrigPos,
+ const SwPosition& rOrigStt,
+ const SwPosition& rCpyStt,
+ SwPosition& rChgPos,
+ sal_uLong nDelCount )
+ {
+ sal_uLong nNdOff = rOrigPos.nNode.GetIndex();
+ nNdOff -= rOrigStt.nNode.GetIndex();
+ nNdOff -= nDelCount;
+ xub_StrLen nCntntPos = rOrigPos.nContent.GetIndex();
+
+ // Always adjust <nNode> at to be changed <SwPosition> instance <rChgPos>
+ rChgPos.nNode = nNdOff + rCpyStt.nNode.GetIndex();
+ if( !nNdOff )
+ {
+ // dann nur den Content anpassen
+ if( nCntntPos > rOrigStt.nContent.GetIndex() )
+ nCntntPos = nCntntPos - rOrigStt.nContent.GetIndex();
+ else
+ nCntntPos = 0;
+ nCntntPos = nCntntPos + rCpyStt.nContent.GetIndex();
+ }
+ rChgPos.nContent.Assign( rChgPos.nNode.GetNode().GetCntntNode(), nCntntPos );
+ }
+
+ // TODO: use SaveBookmark (from _DelBookmarks)
+ static void lcl_CopyBookmarks(const SwPaM& rPam, SwPaM& rCpyPam)
+ {
+ const SwDoc* pSrcDoc = rPam.GetDoc();
+ SwDoc* pDestDoc = rCpyPam.GetDoc();
+ const IDocumentMarkAccess* const pSrcMarkAccess = pSrcDoc->getIDocumentMarkAccess();
+ ::sw::UndoGuard const undoGuard(pDestDoc->GetIDocumentUndoRedo());
+
+ const SwPosition &rStt = *rPam.Start(), &rEnd = *rPam.End();
+ SwPosition* pCpyStt = rCpyPam.Start();
+
+ typedef ::std::vector< const ::sw::mark::IMark* > mark_vector_t;
+ mark_vector_t vMarksToCopy;
+ for(IDocumentMarkAccess::const_iterator_t ppMark = pSrcMarkAccess->getMarksBegin();
+ ppMark != pSrcMarkAccess->getMarksEnd();
+ ppMark++)
+ {
+ const ::sw::mark::IMark* const pMark = ppMark->get();
+ const SwPosition& rMarkStart = pMark->GetMarkStart();
+ const SwPosition& rMarkEnd = pMark->GetMarkEnd();
+ // only include marks that are in the range and not touching
+ // both start and end
+ bool bIsNotOnBoundary = pMark->IsExpanded()
+ ? (rMarkStart != rStt || rMarkEnd != rEnd) // rMarkStart != rMarkEnd
+ : (rMarkStart != rStt && rMarkEnd != rEnd); // rMarkStart == rMarkEnd
+ if(rMarkStart >= rStt && rMarkEnd <= rEnd && bIsNotOnBoundary)
+ {
+ vMarksToCopy.push_back(pMark);
+ }
+ }
+ // We have to count the "non-copied" nodes..
+ SwNodeIndex aCorrIdx(rStt.nNode);
+ sal_uLong nDelCount = 0;
+ for(mark_vector_t::const_iterator ppMark = vMarksToCopy.begin();
+ ppMark != vMarksToCopy.end();
+ ++ppMark)
+ {
+ const ::sw::mark::IMark* const pMark = *ppMark;
+ SwPaM aTmpPam(*pCpyStt);
+ lcl_NonCopyCount(rPam, aCorrIdx, pMark->GetMarkPos().nNode.GetIndex(), nDelCount);
+ lcl_SetCpyPos( pMark->GetMarkPos(), rStt, *pCpyStt, *aTmpPam.GetPoint(), nDelCount);
+ if(pMark->IsExpanded())
+ {
+ aTmpPam.SetMark();
+ lcl_NonCopyCount(rPam, aCorrIdx, pMark->GetOtherMarkPos().nNode.GetIndex(), nDelCount);
+ lcl_SetCpyPos(pMark->GetOtherMarkPos(), rStt, *pCpyStt, *aTmpPam.GetMark(), nDelCount);
+ }
+
+ ::sw::mark::IMark* const pNewMark = pDestDoc->getIDocumentMarkAccess()->makeMark(
+ aTmpPam,
+ pMark->GetName(),
+ IDocumentMarkAccess::GetType(*pMark));
+ // Explicitly try to get exactly the same name as in the source
+ // because NavigatorReminders, DdeBookmarks etc. ignore the proposed name
+ pDestDoc->getIDocumentMarkAccess()->renameMark(pNewMark, pMark->GetName());
+ ::sw::mark::IBookmark* const pNewBookmark =
+ dynamic_cast< ::sw::mark::IBookmark* const >(pNewMark);
+ if(pNewBookmark) /* copying additional attributes for bookmarks */
+ {
+ const ::sw::mark::IBookmark* const pOldBookmark = dynamic_cast< const ::sw::mark::IBookmark* >(pMark);
+ pNewBookmark->SetKeyCode(pOldBookmark->GetKeyCode());
+ pNewBookmark->SetShortName(pOldBookmark->GetShortName());
+ }
+ ::sfx2::Metadatable const*const pMetadatable(
+ dynamic_cast< ::sfx2::Metadatable const* >(pMark));
+ ::sfx2::Metadatable *const pNewMetadatable(
+ dynamic_cast< ::sfx2::Metadatable * >(pNewMark));
+ if (pMetadatable && pNewMetadatable)
+ {
+ pNewMetadatable->RegisterAsCopyOf(*pMetadatable);
+ }
+ }
+ }
+}
+
+// Struktur fuer das Mappen von alten und neuen Frame-Formaten an den
+// Boxen und Lines einer Tabelle
+
+struct _MapTblFrmFmt
+{
+ const SwFrmFmt *pOld, *pNew;
+ _MapTblFrmFmt( const SwFrmFmt *pOldFmt, const SwFrmFmt*pNewFmt )
+ : pOld( pOldFmt ), pNew( pNewFmt )
+ {}
+};
+
+SV_DECL_VARARR( _MapTblFrmFmts, _MapTblFrmFmt, 0, 10 )
+SV_IMPL_VARARR( _MapTblFrmFmts, _MapTblFrmFmt );
+
+SwCntntNode* SwTxtNode::MakeCopy( SwDoc* pDoc, const SwNodeIndex& rIdx ) const
+{
+ // the Copy-Textnode is the Node with the Text, the Copy-Attrnode is the
+ // node with the collection and hard attributes. Normally ist the same
+ // node, but if insert a glossary without formatting, then the Attrnode
+ // is the prev node of the destionation position in dest. document.
+ SwTxtNode* pCpyTxtNd = (SwTxtNode*)this;
+ SwTxtNode* pCpyAttrNd = pCpyTxtNd;
+
+ // kopiere die Formate in das andere Dokument:
+ SwTxtFmtColl* pColl = 0;
+ if( pDoc->IsInsOnlyTextGlossary() )
+ {
+ SwNodeIndex aIdx( rIdx, -1 );
+ if( aIdx.GetNode().IsTxtNode() )
+ {
+ pCpyAttrNd = aIdx.GetNode().GetTxtNode();
+ pColl = &pCpyAttrNd->GetTxtColl()->GetNextTxtFmtColl();
+ }
+ }
+ if( !pColl )
+ pColl = pDoc->CopyTxtColl( *GetTxtColl() );
+
+ SwTxtNode* pTxtNd = pDoc->GetNodes().MakeTxtNode( rIdx, pColl );
+
+ // METADATA: register copy
+ pTxtNd->RegisterAsCopyOf(*pCpyTxtNd);
+
+ // kopiere Attribute/Text
+ if( !pCpyAttrNd->HasSwAttrSet() )
+ // wurde ein AttrSet fuer die Numerierung angelegt, so loesche diesen!
+ pCpyAttrNd->ResetAllAttr();
+
+ // if Copy-Textnode unequal to Copy-Attrnode, then copy first
+ // the attributes into the new Node.
+ if( pCpyAttrNd != pCpyTxtNd )
+ {
+ pCpyAttrNd->CopyAttr( pTxtNd, 0, 0 );
+ if( pCpyAttrNd->HasSwAttrSet() )
+ {
+ SwAttrSet aSet( *pCpyAttrNd->GetpSwAttrSet() );
+ aSet.ClearItem( RES_PAGEDESC );
+ aSet.ClearItem( RES_BREAK );
+ aSet.CopyToModify( *pTxtNd );
+ }
+ }
+
+ // ??? reicht das ??? was ist mit PostIts/Feldern/FeldTypen ???
+ // #i96213# - force copy of all attributes
+ pCpyTxtNd->CopyText( pTxtNd, SwIndex( pCpyTxtNd ),
+ pCpyTxtNd->GetTxt().Len(), true );
+ // <--
+
+//FEATURE::CONDCOLL
+ if( RES_CONDTXTFMTCOLL == pColl->Which() )
+ pTxtNd->ChkCondColl();
+//FEATURE::CONDCOLL
+
+ return pTxtNd;
+}
+
+
+sal_Bool lcl_SrchNew( const _MapTblFrmFmt& rMap, void * pPara )
+{
+ if( rMap.pOld != *(const SwFrmFmt**)pPara )
+ return sal_True;
+ *((const SwFrmFmt**)pPara) = rMap.pNew;
+ return sal_False; // abbrechen, Pointer gefunden
+}
+
+
+struct _CopyTable
+{
+ SwDoc* pDoc;
+ sal_uLong nOldTblSttIdx;
+ _MapTblFrmFmts& rMapArr;
+ SwTableLine* pInsLine;
+ SwTableBox* pInsBox;
+ SwTableNode *pTblNd;
+ const SwTable *pOldTable;
+
+ _CopyTable( SwDoc* pDc, _MapTblFrmFmts& rArr, sal_uLong nOldStt,
+ SwTableNode& rTblNd, const SwTable* pOldTbl )
+ : pDoc(pDc), nOldTblSttIdx(nOldStt), rMapArr(rArr),
+ pInsLine(0), pInsBox(0), pTblNd(&rTblNd), pOldTable( pOldTbl )
+ {}
+};
+
+sal_Bool lcl_CopyTblBox( const SwTableBox*& rpBox, void* pPara );
+
+sal_Bool lcl_CopyTblLine( const SwTableLine*& rpLine, void* pPara );
+
+sal_Bool lcl_CopyTblBox( const SwTableBox*& rpBox, void* pPara )
+{
+ _CopyTable* pCT = (_CopyTable*)pPara;
+
+ SwTableBoxFmt* pBoxFmt = (SwTableBoxFmt*)rpBox->GetFrmFmt();
+ pCT->rMapArr.ForEach( lcl_SrchNew, &pBoxFmt );
+ if( pBoxFmt == rpBox->GetFrmFmt() ) // ein neues anlegen ??
+ {
+ const SfxPoolItem* pItem;
+ if( SFX_ITEM_SET == pBoxFmt->GetItemState( RES_BOXATR_FORMULA, sal_False,
+ &pItem ) && ((SwTblBoxFormula*)pItem)->IsIntrnlName() )
+ {
+ ((SwTblBoxFormula*)pItem)->PtrToBoxNm( pCT->pOldTable );
+ }
+
+ pBoxFmt = pCT->pDoc->MakeTableBoxFmt();
+ pBoxFmt->CopyAttrs( *rpBox->GetFrmFmt() );
+
+ if( rpBox->GetSttIdx() )
+ {
+ SvNumberFormatter* pN = pCT->pDoc->GetNumberFormatter( sal_False );
+ if( pN && pN->HasMergeFmtTbl() && SFX_ITEM_SET == pBoxFmt->
+ GetItemState( RES_BOXATR_FORMAT, sal_False, &pItem ) )
+ {
+ sal_uLong nOldIdx = ((SwTblBoxNumFormat*)pItem)->GetValue();
+ sal_uLong nNewIdx = pN->GetMergeFmtIndex( nOldIdx );
+ if( nNewIdx != nOldIdx )
+ pBoxFmt->SetFmtAttr( SwTblBoxNumFormat( nNewIdx ));
+
+ }
+ }
+
+ pCT->rMapArr.Insert( _MapTblFrmFmt( rpBox->GetFrmFmt(), pBoxFmt ),
+ pCT->rMapArr.Count() );
+ }
+
+ sal_uInt16 nLines = rpBox->GetTabLines().Count();
+ SwTableBox* pNewBox;
+ if( nLines )
+ pNewBox = new SwTableBox( pBoxFmt, nLines, pCT->pInsLine );
+ else
+ {
+ SwNodeIndex aNewIdx( *pCT->pTblNd,
+ rpBox->GetSttIdx() - pCT->nOldTblSttIdx );
+ OSL_ENSURE( aNewIdx.GetNode().IsStartNode(), "Index nicht auf einem StartNode" );
+ pNewBox = new SwTableBox( pBoxFmt, aNewIdx, pCT->pInsLine );
+ pNewBox->setRowSpan( rpBox->getRowSpan() );
+ }
+
+ pCT->pInsLine->GetTabBoxes().C40_INSERT( SwTableBox, pNewBox,
+ pCT->pInsLine->GetTabBoxes().Count() );
+
+ if( nLines )
+ {
+ _CopyTable aPara( *pCT );
+ aPara.pInsBox = pNewBox;
+ ((SwTableBox*)rpBox)->GetTabLines().ForEach( &lcl_CopyTblLine, &aPara );
+ }
+ else if( pNewBox->IsInHeadline( &pCT->pTblNd->GetTable() ))
+ // in der HeadLine sind die Absaetze mit BedingtenVorlage anzupassen
+ pNewBox->GetSttNd()->CheckSectionCondColl();
+ return sal_True;
+}
+
+sal_Bool lcl_CopyTblLine( const SwTableLine*& rpLine, void* pPara )
+{
+ _CopyTable* pCT = (_CopyTable*)pPara;
+ SwTableLineFmt* pLineFmt = (SwTableLineFmt*)rpLine->GetFrmFmt();
+ pCT->rMapArr.ForEach( lcl_SrchNew, &pLineFmt );
+ if( pLineFmt == rpLine->GetFrmFmt() ) // ein neues anlegen ??
+ {
+ pLineFmt = pCT->pDoc->MakeTableLineFmt();
+ pLineFmt->CopyAttrs( *rpLine->GetFrmFmt() );
+ pCT->rMapArr.Insert( _MapTblFrmFmt( rpLine->GetFrmFmt(), pLineFmt ),
+ pCT->rMapArr.Count());
+ }
+ SwTableLine* pNewLine = new SwTableLine( pLineFmt,
+ rpLine->GetTabBoxes().Count(), pCT->pInsBox );
+ // die neue Zeile in die Tabelle eintragen
+ if( pCT->pInsBox )
+ {
+ pCT->pInsBox->GetTabLines().C40_INSERT( SwTableLine, pNewLine,
+ pCT->pInsBox->GetTabLines().Count() );
+ }
+ else
+ {
+ pCT->pTblNd->GetTable().GetTabLines().C40_INSERT( SwTableLine, pNewLine,
+ pCT->pTblNd->GetTable().GetTabLines().Count() );
+ }
+ pCT->pInsLine = pNewLine;
+ ((SwTableLine*)rpLine)->GetTabBoxes().ForEach( &lcl_CopyTblBox, pCT );
+ return sal_True;
+}
+
+SwTableNode* SwTableNode::MakeCopy( SwDoc* pDoc, const SwNodeIndex& rIdx ) const
+{
+ // in welchen Array steht ich denn Nodes, UndoNodes ??
+ SwNodes& rNds = (SwNodes&)GetNodes();
+
+ {
+ if( rIdx < pDoc->GetNodes().GetEndOfInserts().GetIndex() &&
+ rIdx >= pDoc->GetNodes().GetEndOfInserts().StartOfSectionIndex() )
+ return 0;
+ }
+
+ // das TableFrmFmt kopieren
+ String sTblName( GetTable().GetFrmFmt()->GetName() );
+ if( !pDoc->IsCopyIsMove() )
+ {
+ const SwFrmFmts& rTblFmts = *pDoc->GetTblFrmFmts();
+ for( sal_uInt16 n = rTblFmts.Count(); n; )
+ if( rTblFmts[ --n ]->GetName() == sTblName )
+ {
+ sTblName = pDoc->GetUniqueTblName();
+ break;
+ }
+ }
+
+ SwFrmFmt* pTblFmt = pDoc->MakeTblFrmFmt( sTblName, pDoc->GetDfltFrmFmt() );
+ pTblFmt->CopyAttrs( *GetTable().GetFrmFmt() );
+ SwTableNode* pTblNd = new SwTableNode( rIdx );
+ SwEndNode* pEndNd = new SwEndNode( rIdx, *pTblNd );
+ SwNodeIndex aInsPos( *pEndNd );
+
+ SwTable& rTbl = (SwTable&)pTblNd->GetTable();
+ rTbl.RegisterToFormat( *pTblFmt );
+
+ rTbl.SetRowsToRepeat( GetTable().GetRowsToRepeat() );
+ rTbl.SetTblChgMode( GetTable().GetTblChgMode() );
+ rTbl.SetTableModel( GetTable().IsNewModel() );
+
+ SwDDEFieldType* pDDEType = 0;
+ if( IS_TYPE( SwDDETable, &GetTable() ))
+ {
+ // es wird eine DDE-Tabelle kopiert
+ // ist im neuen Dokument ueberhaupt der FeldTyp vorhanden ?
+ pDDEType = ((SwDDETable&)GetTable()).GetDDEFldType();
+ if( pDDEType->IsDeleted() )
+ pDoc->InsDeletedFldType( *pDDEType );
+ else
+ pDDEType = (SwDDEFieldType*)pDoc->InsertFldType( *pDDEType );
+ OSL_ENSURE( pDDEType, "unbekannter FieldType" );
+
+ // tauschen am Node den Tabellen-Pointer aus
+ SwDDETable* pNewTable = new SwDDETable( pTblNd->GetTable(), pDDEType );
+ pTblNd->SetNewTable( pNewTable, sal_False );
+ }
+ // dann kopiere erstmal den Inhalt der Tabelle, die Zuordnung der
+ // Boxen/Lines und das anlegen der Frames erfolgt spaeter
+ SwNodeRange aRg( *this, +1, *EndOfSectionNode() ); // (wo stehe in denn nun ??)
+
+ // If there is a table in this table, the table format for the outer table
+ // does not seem to be used, because the table does not have any contents yet
+ // (see IsUsed). Therefore the inner table gets the same name as the outer table.
+ // We have to make sure that the table node of the SwTable is accessible, even
+ // without any content in aSortCntBoxes. #i26629#
+ pTblNd->GetTable().SetTableNode( pTblNd );
+ rNds._Copy( aRg, aInsPos, sal_False );
+ pTblNd->GetTable().SetTableNode( 0 );
+
+ // Sonderbehandlung fuer eine einzelne Box
+ if( 1 == GetTable().GetTabSortBoxes().Count() )
+ {
+ aRg.aStart.Assign( *pTblNd, 1 );
+ aRg.aEnd.Assign( *pTblNd->EndOfSectionNode() );
+ pDoc->GetNodes().SectionDown( &aRg, SwTableBoxStartNode );
+ }
+
+ // loesche alle Frames vom kopierten Bereich, diese werden beim
+ // erzeugen des TableFrames angelegt !
+ pTblNd->DelFrms();
+
+ _MapTblFrmFmts aMapArr;
+ _CopyTable aPara( pDoc, aMapArr, GetIndex(), *pTblNd, &GetTable() );
+
+ ((SwTable&)GetTable()).GetTabLines().ForEach( &lcl_CopyTblLine, &aPara );
+
+ if( pDDEType )
+ pDDEType->IncRefCnt();
+
+ CHECK_TABLE( GetTable() );
+ return pTblNd;
+}
+
+void SwTxtNode::CopyCollFmt( SwTxtNode& rDestNd )
+{
+ // kopiere die Formate in das andere Dokument:
+
+ // Sonderbehandlung fuer PageBreak/PageDesc/ColBrk
+ SwDoc* pDestDoc = rDestNd.GetDoc();
+ SwAttrSet aPgBrkSet( pDestDoc->GetAttrPool(), aBreakSetRange );
+ const SwAttrSet* pSet;
+
+ if( 0 != ( pSet = rDestNd.GetpSwAttrSet() ) )
+ {
+ // Sonderbehandlung fuer unsere Break-Attribute
+ const SfxPoolItem* pAttr;
+ if( SFX_ITEM_SET == pSet->GetItemState( RES_BREAK, sal_False, &pAttr ) )
+ aPgBrkSet.Put( *pAttr );
+
+ if( SFX_ITEM_SET == pSet->GetItemState( RES_PAGEDESC, sal_False, &pAttr ) )
+ aPgBrkSet.Put( *pAttr );
+ }
+
+ rDestNd.ChgFmtColl( pDestDoc->CopyTxtColl( *GetTxtColl() ));
+ if( 0 != ( pSet = GetpSwAttrSet() ) )
+ pSet->CopyToModify( rDestNd );
+
+ if( aPgBrkSet.Count() )
+ rDestNd.SetAttr( aPgBrkSet );
+}
+
+
+// ----- Copy-Methode vom SwDoc ------
+
+ // verhinder das Kopieren in Fly's, die im Bereich verankert sind.
+sal_Bool lcl_ChkFlyFly( SwDoc* pDoc, sal_uLong nSttNd, sal_uLong nEndNd,
+ sal_uLong nInsNd )
+{
+ const SwSpzFrmFmts& rFrmFmtTbl = *pDoc->GetSpzFrmFmts();
+
+ for( sal_uInt16 n = 0; n < rFrmFmtTbl.Count(); ++n )
+ {
+ SwFrmFmt const*const pFmt = rFrmFmtTbl[n];
+ SwFmtAnchor const*const pAnchor = &pFmt->GetAnchor();
+ SwPosition const*const pAPos = pAnchor->GetCntntAnchor();
+ if (pAPos &&
+ ((FLY_AS_CHAR == pAnchor->GetAnchorId()) ||
+ (FLY_AT_CHAR == pAnchor->GetAnchorId()) ||
+ (FLY_AT_FLY == pAnchor->GetAnchorId()) ||
+ (FLY_AT_PARA == pAnchor->GetAnchorId())) &&
+ nSttNd <= pAPos->nNode.GetIndex() &&
+ pAPos->nNode.GetIndex() < nEndNd )
+ {
+ const SwFmtCntnt& rCntnt = pFmt->GetCntnt();
+ SwStartNode* pSNd;
+ if( !rCntnt.GetCntntIdx() ||
+ 0 == ( pSNd = rCntnt.GetCntntIdx()->GetNode().GetStartNode() ))
+ continue;
+
+ if( pSNd->GetIndex() < nInsNd &&
+ nInsNd < pSNd->EndOfSectionIndex() )
+ return sal_True; // nicht kopieren !!
+
+ if( lcl_ChkFlyFly( pDoc, pSNd->GetIndex(),
+ pSNd->EndOfSectionIndex(), nInsNd ) )
+ return sal_True; // nicht kopieren !!
+ }
+ }
+
+ return sal_False;
+}
+
+void lcl_DeleteRedlines( const SwPaM& rPam, SwPaM& rCpyPam )
+{
+ const SwDoc* pSrcDoc = rPam.GetDoc();
+ const SwRedlineTbl& rTbl = pSrcDoc->GetRedlineTbl();
+ if( rTbl.Count() )
+ {
+ SwDoc* pDestDoc = rCpyPam.GetDoc();
+ SwPosition* pCpyStt = rCpyPam.Start(), *pCpyEnd = rCpyPam.End();
+ SwPaM* pDelPam = 0;
+ const SwPosition *pStt = rPam.Start(), *pEnd = rPam.End();
+ // We have to count the "non-copied" nodes
+ sal_uLong nDelCount = 0;
+ SwNodeIndex aCorrIdx( pStt->nNode );
+
+ sal_uInt16 n = 0;
+ pSrcDoc->GetRedline( *pStt, &n );
+ for( ; n < rTbl.Count(); ++n )
+ {
+ const SwRedline* pRedl = rTbl[ n ];
+ if( nsRedlineType_t::REDLINE_DELETE == pRedl->GetType() && pRedl->IsVisible() )
+ {
+ const SwPosition *pRStt = pRedl->Start(), *pREnd = pRedl->End();
+
+ SwComparePosition eCmpPos = ComparePosition( *pStt, *pEnd, *pRStt, *pREnd );
+ switch( eCmpPos )
+ {
+ case POS_COLLIDE_END:
+ case POS_BEFORE: // Pos1 liegt vor Pos2
+ break;
+
+ case POS_COLLIDE_START:
+ case POS_BEHIND: // Pos1 liegt hinter Pos2
+ n = rTbl.Count();
+ break;
+
+ default:
+ {
+ pDelPam = new SwPaM( *pCpyStt, pDelPam );
+ if( *pStt < *pRStt )
+ {
+ lcl_NonCopyCount( rPam, aCorrIdx, pRStt->nNode.GetIndex(), nDelCount );
+ lcl_SetCpyPos( *pRStt, *pStt, *pCpyStt,
+ *pDelPam->GetPoint(), nDelCount );
+ }
+ pDelPam->SetMark();
+
+ if( *pEnd < *pREnd )
+ *pDelPam->GetPoint() = *pCpyEnd;
+ else
+ {
+ lcl_NonCopyCount( rPam, aCorrIdx, pREnd->nNode.GetIndex(), nDelCount );
+ lcl_SetCpyPos( *pREnd, *pStt, *pCpyStt,
+ *pDelPam->GetPoint(), nDelCount );
+ }
+ }
+ }
+ }
+ }
+
+ if( pDelPam )
+ {
+ RedlineMode_t eOld = pDestDoc->GetRedlineMode();
+ pDestDoc->SetRedlineMode_intern( (RedlineMode_t)(eOld | nsRedlineMode_t::REDLINE_IGNORE));
+
+ ::sw::UndoGuard const undoGuard(pDestDoc->GetIDocumentUndoRedo());
+
+ do {
+ pDestDoc->DeleteAndJoin( *(SwPaM*)pDelPam->GetNext() );
+ if( pDelPam->GetNext() == pDelPam )
+ break;
+ delete pDelPam->GetNext();
+ } while( sal_True );
+ delete pDelPam;
+
+ pDestDoc->SetRedlineMode_intern( eOld );
+ }
+ }
+}
+
+void lcl_DeleteRedlines( const SwNodeRange& rRg, SwNodeRange& rCpyRg )
+{
+ SwDoc* pSrcDoc = rRg.aStart.GetNode().GetDoc();
+ if( pSrcDoc->GetRedlineTbl().Count() )
+ {
+ SwPaM aRgTmp( rRg.aStart, rRg.aEnd );
+ SwPaM aCpyTmp( rCpyRg.aStart, rCpyRg.aEnd );
+ lcl_DeleteRedlines( aRgTmp, aCpyTmp );
+ }
+}
+
+// Kopieren eines Bereiches im oder in ein anderes Dokument !
+
+bool
+SwDoc::CopyRange( SwPaM& rPam, SwPosition& rPos, const bool bCopyAll ) const
+{
+ const SwPosition *pStt = rPam.Start(), *pEnd = rPam.End();
+
+ SwDoc* pDoc = rPos.nNode.GetNode().GetDoc();
+ bool bColumnSel = pDoc->IsClipBoard() && pDoc->IsColumnSelection();
+
+ // kein Copy abfangen.
+ if( !rPam.HasMark() || ( *pStt >= *pEnd && !bColumnSel ) )
+ return false;
+
+ // verhinder das Kopieren in Fly's, die im Bereich verankert sind.
+ if( pDoc == this )
+ {
+ // Start-/EndNode noch korrigieren
+ sal_uLong nStt = pStt->nNode.GetIndex(),
+ nEnd = pEnd->nNode.GetIndex(),
+ nDiff = nEnd - nStt +1;
+ SwNode* pNd = GetNodes()[ nStt ];
+ if( pNd->IsCntntNode() && pStt->nContent.GetIndex() )
+ ++nStt, --nDiff;
+ if( (pNd = GetNodes()[ nEnd ])->IsCntntNode() &&
+ ((SwCntntNode*)pNd)->Len() != pEnd->nContent.GetIndex() )
+ --nEnd, --nDiff;
+ if( nDiff &&
+ lcl_ChkFlyFly( pDoc, nStt, nEnd, rPos.nNode.GetIndex() ) )
+ {
+ return false;
+ }
+ }
+
+ SwPaM* pRedlineRange = 0;
+ if( pDoc->IsRedlineOn() ||
+ (!pDoc->IsIgnoreRedline() && pDoc->GetRedlineTbl().Count() ) )
+ pRedlineRange = new SwPaM( rPos );
+
+ RedlineMode_t eOld = pDoc->GetRedlineMode();
+
+ bool bRet = false;
+
+ if( pDoc != this )
+ { // ordinary copy
+ bRet = CopyImpl( rPam, rPos, true, bCopyAll, pRedlineRange );
+ }
+ // Copy in sich selbst (ueber mehrere Nodes wird hier gesondert
+ // behandelt; in einem TextNode wird normal behandelt)
+ else if( ! ( *pStt <= rPos && rPos < *pEnd &&
+ ( pStt->nNode != pEnd->nNode ||
+ !pStt->nNode.GetNode().IsTxtNode() )) )
+ { // ordinary copy
+ bRet = CopyImpl( rPam, rPos, true, bCopyAll, pRedlineRange );
+ }
+ else
+ {
+ OSL_ENSURE( this == pDoc, " falscher Copy-Zweig!" );
+ OSL_FAIL("mst: i thought this could be dead code;"
+ "please tell me what you did to get here!");
+ pDoc->SetRedlineMode_intern((RedlineMode_t)(eOld | nsRedlineMode_t::REDLINE_IGNORE));
+
+ // dann kopiere den Bereich im unteren DokumentBereich,
+ // (mit Start/End-Nodes geklammert) und verschiebe diese
+ // dann an die gewuenschte Stelle.
+
+ SwUndoCpyDoc* pUndo = 0;
+ SwPaM aPam( rPos ); // UndoBereich sichern
+ if (pDoc->GetIDocumentUndoRedo().DoesUndo())
+ {
+ pDoc->GetIDocumentUndoRedo().ClearRedo();
+ pUndo = new SwUndoCpyDoc( aPam );
+ }
+
+ {
+ ::sw::UndoGuard const undoGuard(pDoc->GetIDocumentUndoRedo());
+ SwStartNode* pSttNd = pDoc->GetNodes().MakeEmptySection(
+ SwNodeIndex( GetNodes().GetEndOfAutotext() ));
+ aPam.GetPoint()->nNode = *pSttNd->EndOfSectionNode();
+ // copy without Frames
+ pDoc->CopyImpl( rPam, *aPam.GetPoint(), false, bCopyAll, 0 );
+
+ aPam.GetPoint()->nNode = pDoc->GetNodes().GetEndOfAutotext();
+ aPam.SetMark();
+ SwCntntNode* pNode =
+ pDoc->GetNodes().GoPrevious( &aPam.GetMark()->nNode );
+ pNode->MakeEndIndex( &aPam.GetMark()->nContent );
+
+ aPam.GetPoint()->nNode = *aPam.GetNode()->StartOfSectionNode();
+ pNode = pDoc->GetNodes().GoNext( &aPam.GetPoint()->nNode );
+ pNode->MakeStartIndex( &aPam.GetPoint()->nContent );
+ // move to desired position
+ pDoc->MoveRange( aPam, rPos, DOC_MOVEDEFAULT );
+
+ pNode = aPam.GetCntntNode();
+ *aPam.GetPoint() = rPos; // Cursor umsetzen fuers Undo !
+ aPam.SetMark(); // auch den Mark umsetzen !!
+ aPam.DeleteMark(); // aber keinen Bereich makieren !!
+ pDoc->DeleteSection( pNode ); // Bereich wieder loeschen
+ }
+
+ // if Undo is enabled, store the insertion range
+ if (pDoc->GetIDocumentUndoRedo().DoesUndo())
+ {
+ pUndo->SetInsertRange( aPam );
+ pDoc->GetIDocumentUndoRedo().AppendUndo(pUndo);
+ }
+
+ if( pRedlineRange )
+ {
+ pRedlineRange->SetMark();
+ *pRedlineRange->GetPoint() = *aPam.GetPoint();
+ *pRedlineRange->GetMark() = *aPam.GetMark();
+ }
+
+ pDoc->SetModified();
+ bRet = true;
+ }
+
+ pDoc->SetRedlineMode_intern( eOld );
+ if( pRedlineRange )
+ {
+ if( pDoc->IsRedlineOn() )
+ pDoc->AppendRedline( new SwRedline( nsRedlineType_t::REDLINE_INSERT, *pRedlineRange ), true);
+ else
+ pDoc->SplitRedline( *pRedlineRange );
+ delete pRedlineRange;
+ }
+
+ return bRet;
+}
+
+// Kopieren eines Bereiches im oder in ein anderes Dokument !
+// Die Position darf nicht im Bereich liegen !!
+
+bool lcl_MarksWholeNode(const SwPaM & rPam)
+{
+ bool bResult = false;
+ const SwPosition* pStt = rPam.Start();
+ const SwPosition* pEnd = rPam.End();
+
+ if (NULL != pStt && NULL != pEnd)
+ {
+ const SwTxtNode* pSttNd = pStt->nNode.GetNode().GetTxtNode();
+ const SwTxtNode* pEndNd = pEnd->nNode.GetNode().GetTxtNode();
+
+ if (NULL != pSttNd && NULL != pEndNd &&
+ pStt->nContent.GetIndex() == 0 &&
+ pEnd->nContent.GetIndex() == pEndNd->Len())
+ {
+ bResult = true;
+ }
+ }
+
+ return bResult;
+}
+
+// #i86492#
+bool lcl_ContainsOnlyParagraphsInList( const SwPaM& rPam )
+{
+ bool bRet = false;
+
+ const SwTxtNode* pTxtNd = rPam.Start()->nNode.GetNode().GetTxtNode();
+ const SwTxtNode* pEndTxtNd = rPam.End()->nNode.GetNode().GetTxtNode();
+ if ( pTxtNd && pTxtNd->IsInList() &&
+ pEndTxtNd && pEndTxtNd->IsInList() )
+ {
+ bRet = true;
+ SwNodeIndex aIdx(rPam.Start()->nNode);
+
+ do
+ {
+ aIdx++;
+ pTxtNd = aIdx.GetNode().GetTxtNode();
+
+ if ( !pTxtNd || !pTxtNd->IsInList() )
+ {
+ bRet = false;
+ break;
+ }
+ } while ( pTxtNd && pTxtNd != pEndTxtNd );
+ }
+
+
+ return bRet;
+}
+// <--
+
+bool SwDoc::CopyImpl( SwPaM& rPam, SwPosition& rPos,
+ const bool bMakeNewFrms, const bool bCopyAll,
+ SwPaM *const pCpyRange ) const
+{
+ SwDoc* pDoc = rPos.nNode.GetNode().GetDoc();
+ const bool bColumnSel = pDoc->IsClipBoard() && pDoc->IsColumnSelection();
+
+ SwPosition* pStt = rPam.Start();
+ SwPosition* pEnd = rPam.End();
+
+ // kein Copy abfangen.
+ if( !rPam.HasMark() || ( *pStt >= *pEnd && !bColumnSel ) ||
+ //JP 29.6.2001: 88963 - dont copy if inspos is in region of start to end
+ //JP 15.11.2001: don't test inclusive the end, ever exclusive
+ ( pDoc == this && *pStt <= rPos && rPos < *pEnd ))
+ {
+ return false;
+ }
+
+ const bool bEndEqualIns = pDoc == this && rPos == *pEnd;
+
+ // falls Undo eingeschaltet, erzeuge das UndoCopy-Objekt
+ SwUndoCpyDoc* pUndo = 0;
+ SwPaM aCpyPam( rPos );
+
+ SwTblNumFmtMerge aTNFM( *this, *pDoc );
+
+ if (pDoc->GetIDocumentUndoRedo().DoesUndo())
+ {
+ pUndo = new SwUndoCpyDoc( aCpyPam );
+ pDoc->GetIDocumentUndoRedo().AppendUndo( pUndo );
+ }
+
+ RedlineMode_t eOld = pDoc->GetRedlineMode();
+ pDoc->SetRedlineMode_intern((RedlineMode_t)(eOld | nsRedlineMode_t::REDLINE_IGNORE));
+
+
+ // bewege den Pam von der Insert-Position ein zurueck, dadurch wird
+ // die Position nicht "verschoben"
+ aCpyPam.SetMark();
+ sal_Bool bCanMoveBack = aCpyPam.Move( fnMoveBackward, fnGoCntnt );
+ // If the position was shifted from more than one node, an end node has been skipped
+ bool bAfterTable = false;
+ if ( ( rPos.nNode.GetIndex() - aCpyPam.GetPoint()->nNode.GetIndex() ) > 1 )
+ {
+ // First go back to the original place
+ aCpyPam.GetPoint()->nNode = rPos.nNode;
+ aCpyPam.GetPoint()->nContent = rPos.nContent;
+
+ bCanMoveBack = false;
+ bAfterTable = true;
+ }
+ if( !bCanMoveBack )
+ aCpyPam.GetPoint()->nNode--;
+
+ SwNodeRange aRg( pStt->nNode, pEnd->nNode );
+ SwNodeIndex aInsPos( rPos.nNode );
+ const bool bOneNode = pStt->nNode == pEnd->nNode;
+ SwTxtNode* pSttTxtNd = pStt->nNode.GetNode().GetTxtNode();
+ SwTxtNode* pEndTxtNd = pEnd->nNode.GetNode().GetTxtNode();
+ SwTxtNode* pDestTxtNd = aInsPos.GetNode().GetTxtNode();
+ bool bCopyCollFmt = !pDoc->IsInsOnlyTextGlossary() &&
+ ( ( pDestTxtNd && !pDestTxtNd->GetTxt().Len() ) ||
+ ( !bOneNode && !rPos.nContent.GetIndex() ) );
+ bool bCopyBookmarks = true;
+ sal_Bool bStartIsTxtNode = 0 != pSttTxtNd;
+
+ // #i104585# copy outline num rule to clipboard (for ASCII filter)
+ if (pDoc->IsClipBoard() && GetOutlineNumRule())
+ {
+ pDoc->SetOutlineNumRule(*GetOutlineNumRule());
+ }
+
+ // #i86492#
+ // Correct the search for a previous list:
+ // First search for non-outline numbering list. Then search for non-outline
+ // bullet list.
+ // Keep also the <ListId> value for possible propagation.
+ String aListIdToPropagate;
+ const SwNumRule* pNumRuleToPropagate =
+ pDoc->SearchNumRule( rPos, false, true, false, 0, aListIdToPropagate, true );
+ if ( !pNumRuleToPropagate )
+ {
+ pNumRuleToPropagate =
+ pDoc->SearchNumRule( rPos, false, false, false, 0, aListIdToPropagate, true );
+ }
+ // <--
+ // #i86492#
+ // Do not propagate previous found list, if
+ // - destination is an empty paragraph which is not in a list and
+ // - source contains at least one paragraph which is not in a list
+ if ( pNumRuleToPropagate &&
+ pDestTxtNd && !pDestTxtNd->GetTxt().Len() && !pDestTxtNd->IsInList() &&
+ !lcl_ContainsOnlyParagraphsInList( rPam ) )
+ {
+ pNumRuleToPropagate = 0;
+ }
+ // <--
+
+ // Block, damit aus diesem gesprungen werden kann !!
+ do {
+ if( pSttTxtNd )
+ {
+ // den Anfang nicht komplett kopieren ?
+ if( !bCopyCollFmt || bColumnSel || pStt->nContent.GetIndex() )
+ {
+ SwIndex aDestIdx( rPos.nContent );
+ sal_Bool bCopyOk = sal_False;
+ if( !pDestTxtNd )
+ {
+ if( pStt->nContent.GetIndex() || bOneNode )
+ pDestTxtNd = pDoc->GetNodes().MakeTxtNode( aInsPos,
+ pDoc->GetTxtCollFromPool(RES_POOLCOLL_STANDARD));
+ else
+ {
+ pDestTxtNd = static_cast<SwTxtNode*>(pSttTxtNd->MakeCopy( pDoc, aInsPos ));
+ bCopyOk = sal_True;
+ }
+ aDestIdx.Assign( pDestTxtNd, 0 );
+ bCopyCollFmt = true;
+ }
+ else if( !bOneNode || bColumnSel )
+ {
+ xub_StrLen nCntntEnd = pEnd->nContent.GetIndex();
+ {
+ ::sw::UndoGuard const ug(pDoc->GetIDocumentUndoRedo());
+ pDoc->SplitNode( rPos, false );
+ }
+
+ if( bCanMoveBack && rPos == *aCpyPam.GetPoint() )
+ {
+ // nach dem SplitNode, den CpyPam wieder richtig aufspannen
+ aCpyPam.Move( fnMoveBackward, fnGoCntnt );
+ aCpyPam.Move( fnMoveBackward, fnGoCntnt );
+ }
+
+ pDestTxtNd = pDoc->GetNodes()[ aInsPos.GetIndex()-1 ]->GetTxtNode();
+ aDestIdx.Assign( pDestTxtNd, pDestTxtNd->GetTxt().Len() );
+
+ // korrigiere den Bereich wieder !!
+ if( bEndEqualIns )
+ {
+ sal_Bool bChg = pEnd != rPam.GetPoint();
+ if( bChg )
+ rPam.Exchange();
+ rPam.Move( fnMoveBackward, fnGoCntnt );
+ if( bChg )
+ rPam.Exchange();
+
+ aRg.aEnd = pEnd->nNode;
+ pEndTxtNd = pEnd->nNode.GetNode().GetTxtNode();
+ }
+ else if( rPos == *pEnd ) // Wurde das Ende auch verschoben
+ {
+ pEnd->nNode--;
+ pEnd->nContent.Assign( pDestTxtNd, nCntntEnd );
+ aRg.aEnd = pEnd->nNode;
+ pEndTxtNd = pEnd->nNode.GetNode().GetTxtNode();
+ }
+ }
+
+ // Safe numrule item at destination.
+ // #i86492# - Safe also <ListId> item of destination.
+ int aNumRuleState = SFX_ITEM_UNKNOWN;
+ SwNumRuleItem aNumRuleItem;
+ int aListIdState = SFX_ITEM_UNKNOWN;
+ SfxStringItem aListIdItem( RES_PARATR_LIST_ID, String() );
+ {
+ const SfxItemSet * pAttrSet = pDestTxtNd->GetpSwAttrSet();
+ if (pAttrSet != NULL)
+ {
+ const SfxPoolItem * pItem = NULL;
+ aNumRuleState = pAttrSet->GetItemState(RES_PARATR_NUMRULE, sal_False, &pItem);
+ if (SFX_ITEM_SET == aNumRuleState)
+ aNumRuleItem = *((SwNumRuleItem *) pItem);
+
+ aListIdState =
+ pAttrSet->GetItemState(RES_PARATR_LIST_ID, sal_False, &pItem);
+ if (SFX_ITEM_SET == aListIdState)
+ {
+ aListIdItem.SetValue( static_cast<const SfxStringItem*>(pItem)->GetValue() );
+ }
+ }
+ }
+ // <--
+
+ if( !bCopyOk )
+ {
+ const xub_StrLen nCpyLen = ( (bOneNode)
+ ? pEnd->nContent.GetIndex()
+ : pSttTxtNd->GetTxt().Len() )
+ - pStt->nContent.GetIndex();
+ pSttTxtNd->CopyText( pDestTxtNd, aDestIdx,
+ pStt->nContent, nCpyLen );
+ if( bEndEqualIns )
+ pEnd->nContent -= nCpyLen;
+ }
+
+ if( bOneNode )
+ {
+ if( bCopyCollFmt )
+ {
+ pSttTxtNd->CopyCollFmt( *pDestTxtNd );
+
+ /* If only a part of one paragraph is copied
+ restore the numrule at the destination. */
+ // #i86492# - restore also <ListId> item
+ if ( !lcl_MarksWholeNode(rPam) )
+ {
+ if (SFX_ITEM_SET == aNumRuleState)
+ {
+ pDestTxtNd->SetAttr(aNumRuleItem);
+ }
+ else
+ {
+ pDestTxtNd->ResetAttr(RES_PARATR_NUMRULE);
+ }
+ if (SFX_ITEM_SET == aListIdState)
+ {
+ pDestTxtNd->SetAttr(aListIdItem);
+ }
+ else
+ {
+ pDestTxtNd->ResetAttr(RES_PARATR_LIST_ID);
+ }
+ }
+ }
+
+ break;
+ }
+
+ aRg.aStart++;
+ }
+ }
+ else if( pDestTxtNd )
+ {
+ // Problems with insertion of table selections into "normal" text solved.
+ // We have to set the correct PaM for Undo, if this PaM starts in a textnode,
+ // the undo operation will try to merge this node after removing the table.
+ // If we didn't split a textnode, the PaM should start at the inserted table node
+ if( rPos.nContent.GetIndex() == pDestTxtNd->Len() )
+ { // Insertion at the last position of a textnode (empty or not)
+ aInsPos++; // The table will be inserted behind the text node
+ }
+ else if( rPos.nContent.GetIndex() )
+ { // Insertion in the middle of a text node, it has to be split
+ // (and joined from undo)
+ bStartIsTxtNode = sal_True;
+ // splitte den TextNode, bei dem Eingefuegt wird.
+
+ xub_StrLen nCntntEnd = pEnd->nContent.GetIndex();
+ {
+ ::sw::UndoGuard const ug(pDoc->GetIDocumentUndoRedo());
+ pDoc->SplitNode( rPos, false );
+ }
+
+ if( bCanMoveBack && rPos == *aCpyPam.GetPoint() )
+ {
+ // nach dem SplitNode, den CpyPam wieder richtig aufspannen
+ aCpyPam.Move( fnMoveBackward, fnGoCntnt );
+ aCpyPam.Move( fnMoveBackward, fnGoCntnt );
+ }
+
+ // korrigiere den Bereich wieder !!
+ if( bEndEqualIns )
+ aRg.aEnd--;
+ else if( rPos == *pEnd ) // Wurde das Ende auch verschoben
+ {
+ rPos.nNode-=2;
+ rPos.nContent.Assign( rPos.nNode.GetNode().GetCntntNode(),
+ nCntntEnd );
+ rPos.nNode++;
+ aRg.aEnd--;
+ }
+ }
+ else if( bCanMoveBack )
+ { //Insertion at the first position of a text node. It will not be splitted, the table
+ // will be inserted before the text node.
+ // See below, before the SetInsertRange funciton of the undo object will be called,
+ // the CpyPam would be moved to the next content position. This has to be avoided
+ // We want to be moved to the table node itself thus we have to set bCanMoveBack
+ // and to manipulate aCpyPam.
+ bCanMoveBack = false;
+ aCpyPam.GetPoint()->nNode--;
+ }
+ }
+
+ pDestTxtNd = aInsPos.GetNode().GetTxtNode();
+ if( pEndTxtNd )
+ {
+ SwIndex aDestIdx( rPos.nContent );
+ if( !pDestTxtNd )
+ {
+ pDestTxtNd = pDoc->GetNodes().MakeTxtNode( aInsPos,
+ pDoc->GetTxtCollFromPool(RES_POOLCOLL_STANDARD));
+ aDestIdx.Assign( pDestTxtNd, 0 );
+ aInsPos--;
+
+ // if we have to insert an extra text node
+ // at the destination, this node will be our new destination
+ // (text) node, and thus we set bStartisTxtNode to true. This
+ // will ensure that this node will be deleted during Undo
+ // using JoinNext.
+ DBG_ASSERT( !bStartIsTxtNode, "Oops, undo may be instable now." );
+ bStartIsTxtNode = sal_True;
+ }
+
+ // Save numrule at destination
+ // #i86492# - Safe also <ListId> item of destination.
+ int aNumRuleState = SFX_ITEM_UNKNOWN;
+ SwNumRuleItem aNumRuleItem;
+ int aListIdState = SFX_ITEM_UNKNOWN;
+ SfxStringItem aListIdItem( RES_PARATR_LIST_ID, String() );
+ {
+ const SfxItemSet* pAttrSet = pDestTxtNd->GetpSwAttrSet();
+ if (pAttrSet != NULL)
+ {
+ const SfxPoolItem * pItem = NULL;
+
+ aNumRuleState =
+ pAttrSet->GetItemState(RES_PARATR_NUMRULE, sal_False, &pItem);
+ if (SFX_ITEM_SET == aNumRuleState)
+ aNumRuleItem = *((SwNumRuleItem *) pItem);
+
+ aListIdState =
+ pAttrSet->GetItemState(RES_PARATR_LIST_ID, sal_False, &pItem);
+ if (SFX_ITEM_SET == aListIdState)
+ aListIdItem.SetValue( static_cast<const SfxStringItem*>(pItem)->GetValue() );
+ }
+ }
+ // <--
+
+ const bool bEmptyDestNd = 0 == pDestTxtNd->GetTxt().Len();
+ pEndTxtNd->CopyText( pDestTxtNd, aDestIdx, SwIndex( pEndTxtNd ),
+ pEnd->nContent.GetIndex() );
+
+ // auch alle FormatVorlagen kopieren
+ if( bCopyCollFmt && ( bOneNode || bEmptyDestNd ))
+ {
+ pEndTxtNd->CopyCollFmt( *pDestTxtNd );
+
+ if ( bOneNode )
+ {
+ /* If only a part of one paragraph is copied
+ restore the numrule at the destination. */
+ // #i86492# - restore also <ListId> item
+ if ( !lcl_MarksWholeNode(rPam) )
+ {
+ if (SFX_ITEM_SET == aNumRuleState)
+ {
+ pDestTxtNd->SetAttr(aNumRuleItem);
+ }
+ else
+ {
+ pDestTxtNd->ResetAttr(RES_PARATR_NUMRULE);
+ }
+ if (SFX_ITEM_SET == aListIdState)
+ {
+ pDestTxtNd->SetAttr(aListIdItem);
+ }
+ else
+ {
+ pDestTxtNd->ResetAttr(RES_PARATR_LIST_ID);
+ }
+ }
+ }
+ }
+ }
+
+ if( bCopyAll || aRg.aStart != aRg.aEnd )
+ {
+ SfxItemSet aBrkSet( pDoc->GetAttrPool(), aBreakSetRange );
+ if( pSttTxtNd && bCopyCollFmt && pDestTxtNd->HasSwAttrSet() )
+ {
+ aBrkSet.Put( *pDestTxtNd->GetpSwAttrSet() );
+ if( SFX_ITEM_SET == aBrkSet.GetItemState( RES_BREAK, sal_False ) )
+ pDestTxtNd->ResetAttr( RES_BREAK );
+ if( SFX_ITEM_SET == aBrkSet.GetItemState( RES_PAGEDESC, sal_False ) )
+ pDestTxtNd->ResetAttr( RES_PAGEDESC );
+ }
+
+ if( aInsPos == pEnd->nNode )
+ {
+ SwNodeIndex aSaveIdx( aInsPos, -1 );
+ CopyWithFlyInFly( aRg, 0,aInsPos, bMakeNewFrms, sal_False );
+ aSaveIdx++;
+ pEnd->nNode = aSaveIdx;
+ pEnd->nContent.Assign( aSaveIdx.GetNode().GetTxtNode(), 0 );
+ }
+ else
+ CopyWithFlyInFly( aRg, pEnd->nContent.GetIndex(), aInsPos, bMakeNewFrms, sal_False );
+
+ bCopyBookmarks = false;
+
+ // harte Umbrueche wieder in den ersten Node setzen
+ if( aBrkSet.Count() && 0 != ( pDestTxtNd = pDoc->GetNodes()[
+ aCpyPam.GetPoint()->nNode.GetIndex()+1 ]->GetTxtNode() ) )
+ {
+ pDestTxtNd->SetAttr( aBrkSet );
+ }
+ }
+ } while( sal_False );
+
+ // Position ummelden ( falls verschoben / im anderen Node )
+ rPos.nContent.Assign( rPos.nNode.GetNode().GetCntntNode(),
+ rPos.nContent.GetIndex() );
+
+ if( rPos.nNode != aInsPos )
+ {
+ aCpyPam.GetMark()->nNode = aInsPos;
+ aCpyPam.GetMark()->nContent.Assign( aCpyPam.GetCntntNode(sal_False), 0 );
+ rPos = *aCpyPam.GetMark();
+ }
+ else
+ *aCpyPam.GetMark() = rPos;
+
+ if ( !bAfterTable )
+ aCpyPam.Move( fnMoveForward, bCanMoveBack ? fnGoCntnt : fnGoNode );
+ else
+ {
+ // Reset the offset to 0 as it was before the insertion
+ aCpyPam.GetPoint( )->nContent -= aCpyPam.GetPoint( )->nContent;
+
+ aCpyPam.GetPoint( )->nNode++;
+ // If the next node is a start node, then step back: the start node
+ // has been copied and needs to be in the selection for the undo
+ if ( aCpyPam.GetPoint()->nNode.GetNode().IsStartNode() )
+ aCpyPam.GetPoint( )->nNode--;
+
+ }
+ aCpyPam.Exchange();
+
+ // dann kopiere noch alle Bookmarks
+ if( bCopyBookmarks && getIDocumentMarkAccess()->getMarksCount() )
+ lcl_CopyBookmarks( rPam, aCpyPam );
+
+ if( nsRedlineMode_t::REDLINE_DELETE_REDLINES & eOld )
+ lcl_DeleteRedlines( rPam, aCpyPam );
+
+ // falls Undo eingeschaltet ist, so speicher den eingefuegten Bereich
+ if (pDoc->GetIDocumentUndoRedo().DoesUndo())
+ {
+ pUndo->SetInsertRange( aCpyPam, sal_True, bStartIsTxtNode );
+ }
+
+ if( pCpyRange )
+ {
+ pCpyRange->SetMark();
+ *pCpyRange->GetPoint() = *aCpyPam.GetPoint();
+ *pCpyRange->GetMark() = *aCpyPam.GetMark();
+ }
+
+ if ( pNumRuleToPropagate )
+ {
+ // #i86492# - use <SwDoc::SetNumRule(..)>, because it also handles the <ListId>
+ pDoc->SetNumRule( aCpyPam, *pNumRuleToPropagate, false,
+ aListIdToPropagate, sal_True, true );
+ }
+
+ pDoc->SetRedlineMode_intern( eOld );
+ pDoc->SetModified();
+
+ return true;
+}
+
+
+// ----- Copy-Methode vom SwDoc - "kopiere Fly's in Fly's" ------
+
+void SwDoc::CopyWithFlyInFly( const SwNodeRange& rRg, const xub_StrLen nEndContentIndex,
+ const SwNodeIndex& rInsPos, sal_Bool bMakeNewFrms,
+ sal_Bool bDelRedlines, sal_Bool bCopyFlyAtFly ) const
+{
+ SwDoc* pDest = rInsPos.GetNode().GetDoc();
+
+ _SaveRedlEndPosForRestore aRedlRest( rInsPos, 0 );
+
+ SwNodeIndex aSavePos( rInsPos, -1 );
+ sal_Bool bEndIsEqualEndPos = rInsPos == rRg.aEnd;
+ GetNodes()._CopyNodes( rRg, rInsPos, bMakeNewFrms, sal_True );
+ aSavePos++;
+ if( bEndIsEqualEndPos )
+ ((SwNodeIndex&)rRg.aEnd) = aSavePos;
+
+ aRedlRest.Restore();
+
+#if OSL_DEBUG_LEVEL > 1
+ {
+ //JP 17.06.99: Bug 66973 - check count only if the selection is in
+ // the same (or no) section. Becaus not full selected
+ // section are not copied.
+ const SwSectionNode* pSSectNd = rRg.aStart.GetNode().FindSectionNode();
+ SwNodeIndex aTmpI( rRg.aEnd, -1 );
+ const SwSectionNode* pESectNd = aTmpI.GetNode().FindSectionNode();
+ if( pSSectNd == pESectNd &&
+ !rRg.aStart.GetNode().IsSectionNode() &&
+ !aTmpI.GetNode().IsEndNode() )
+ {
+ OSL_ENSURE( rInsPos.GetIndex() - aSavePos.GetIndex() ==
+ rRg.aEnd.GetIndex() - rRg.aStart.GetIndex(),
+ "Es wurden zu wenig Nodes kopiert!" );
+ }
+ }
+#endif
+
+ {
+ ::sw::UndoGuard const undoGuard(pDest->GetIDocumentUndoRedo());
+ CopyFlyInFlyImpl( rRg, nEndContentIndex, aSavePos, bCopyFlyAtFly );
+ }
+
+ SwNodeRange aCpyRange( aSavePos, rInsPos );
+
+ // dann kopiere noch alle Bookmarks
+ if( getIDocumentMarkAccess()->getMarksCount() )
+ {
+ SwPaM aRgTmp( rRg.aStart, rRg.aEnd );
+ SwPaM aCpyTmp( aCpyRange.aStart, aCpyRange.aEnd );
+
+ lcl_CopyBookmarks( aRgTmp, aCpyTmp );
+ }
+
+ if( bDelRedlines && ( nsRedlineMode_t::REDLINE_DELETE_REDLINES & pDest->GetRedlineMode() ))
+ lcl_DeleteRedlines( rRg, aCpyRange );
+
+ pDest->GetNodes()._DelDummyNodes( aCpyRange );
+}
+
+void lcl_ChainFmts( SwFlyFrmFmt *pSrc, SwFlyFrmFmt *pDest )
+{
+ SwFmtChain aSrc( pSrc->GetChain() );
+ if ( !aSrc.GetNext() )
+ {
+ aSrc.SetNext( pDest );
+ pSrc->SetFmtAttr( aSrc );
+ }
+ SwFmtChain aDest( pDest->GetChain() );
+ if ( !aDest.GetPrev() )
+ {
+ aDest.SetPrev( pSrc );
+ pDest->SetFmtAttr( aDest );
+ }
+}
+
+void SwDoc::CopyFlyInFlyImpl( const SwNodeRange& rRg,
+ const xub_StrLen nEndContentIndex, const SwNodeIndex& rStartIdx,
+ const bool bCopyFlyAtFly ) const
+{
+ // Bug 22727: suche erst mal alle Flys zusammen, sortiere sie entsprechend
+ // ihrer Ordnungsnummer und kopiere sie erst dann. Damit wird
+ // die Ordnungsnummer (wird nur im DrawModel verwaltet)
+ // beibehalten.
+ SwDoc *const pDest = rStartIdx.GetNode().GetDoc();
+ _ZSortFlys aArr;
+ sal_uInt16 nArrLen = GetSpzFrmFmts()->Count();
+
+ for ( sal_uInt16 n = 0; n < nArrLen; ++n )
+ {
+ SwFrmFmt const*const pFmt = (*GetSpzFrmFmts())[n];
+ SwFmtAnchor const*const pAnchor = &pFmt->GetAnchor();
+ SwPosition const*const pAPos = pAnchor->GetCntntAnchor();
+ bool bAtCntnt = (pAnchor->GetAnchorId() == FLY_AT_PARA);
+ if ( pAPos &&
+ ( bAtCntnt ||
+ (pAnchor->GetAnchorId() == FLY_AT_FLY) ||
+ (pAnchor->GetAnchorId() == FLY_AT_CHAR)) &&
+ (( bCopyFlyAtFly && FLY_AT_FLY == pAnchor->GetAnchorId() )
+ ? rRg.aStart <= pAPos->nNode.GetIndex() + 1
+ : ( IsRedlineMove()
+ ? rRg.aStart < pAPos->nNode
+ : rRg.aStart <= pAPos->nNode )) &&
+ pAPos->nNode <= rRg.aEnd )
+ {
+ //frames at the last source node are not always copied:
+ //- if the node is empty and is the last node of the document or a table cell
+ // or a text frame then tey have to be copied
+ //- if the content index in this node is > 0 then paragph and frame bound objects are copied
+ //- to-character bound objects are copied if their index is <= nEndContentIndex
+ bool bAdd = false;
+ if( pAPos->nNode < rRg.aEnd )
+ bAdd = true;
+ if( !bAdd )
+ {
+ bool bEmptyNode = false;
+ bool bLastNode = false;
+ // is the node empty?
+ const SwNodes& rNodes = pAPos->nNode.GetNodes();
+ SwTxtNode* pTxtNode;
+ if( 0 != ( pTxtNode = pAPos->nNode.GetNode().GetTxtNode() ))
+ {
+ bEmptyNode = !pTxtNode->GetTxt().Len();
+ if( bEmptyNode )
+ {
+ //last node information is only necessary to know for the last TextNode
+ SwNodeIndex aTmp( pAPos->nNode );
+ ++aTmp;//goto next node
+ while (aTmp.GetNode().IsEndNode())
+ {
+ if( aTmp == rNodes.GetEndOfContent().GetIndex() )
+ {
+ bLastNode = true;
+ break;
+ }
+ ++aTmp;
+ }
+ }
+ }
+ bAdd = bLastNode && bEmptyNode;
+ if( !bAdd )
+ {
+ if( bAtCntnt )
+ bAdd = nEndContentIndex > 0;
+ else
+ bAdd = pAPos->nContent <= nEndContentIndex;
+ }
+ }
+ if( bAdd )
+ aArr.Insert( _ZSortFly( pFmt, pAnchor, nArrLen + aArr.Count() ));
+ }
+ }
+
+ //Alle kopierten (also die neu erzeugten) Rahmen in ein weiteres Array
+ //stopfen. Dort sizten sie passend zu den Originalen, damit hinterher
+ //die Chains entsprechend aufgebaut werden koennen.
+ SvPtrarr aNewArr( 10, 10 );
+
+ for ( sal_uInt16 n = 0; n < aArr.Count(); ++n )
+ {
+ const _ZSortFly& rZSortFly = aArr[ n ];
+
+ // #i59964#
+ // correct determination of new anchor position
+ SwFmtAnchor aAnchor( *rZSortFly.GetAnchor() );
+ SwPosition* pNewPos = (SwPosition*)aAnchor.GetCntntAnchor();
+ // for at-paragraph and at-character anchored objects the new anchor
+ // position can *not* be determined by the difference of the current
+ // anchor position to the start of the copied range, because not
+ // complete selected sections in the copied range aren't copied - see
+ // method <SwNodes::_CopyNodes(..)>.
+ // Thus, the new anchor position in the destination document is found
+ // by counting the text nodes.
+ if ((aAnchor.GetAnchorId() == FLY_AT_PARA) ||
+ (aAnchor.GetAnchorId() == FLY_AT_CHAR) )
+ {
+ // First, determine number of anchor text node in the copied range.
+ // Note: The anchor text node *have* to be inside the copied range.
+ sal_uLong nAnchorTxtNdNumInRange( 0L );
+ bool bAnchorTxtNdFound( false );
+ SwNodeIndex aIdx( rRg.aStart );
+ while ( !bAnchorTxtNdFound && aIdx <= rRg.aEnd )
+ {
+ if ( aIdx.GetNode().IsTxtNode() )
+ {
+ ++nAnchorTxtNdNumInRange;
+ bAnchorTxtNdFound = aAnchor.GetCntntAnchor()->nNode == aIdx;
+ }
+
+ ++aIdx;
+ }
+ if ( !bAnchorTxtNdFound )
+ {
+ // This case can *not* happen, but to be robust take the first
+ // text node in the destination document.
+ OSL_FAIL( "<SwDoc::_CopyFlyInFly(..)> - anchor text node in copied range not found" );
+ nAnchorTxtNdNumInRange = 1;
+ }
+ // Second, search corresponding text node in destination document
+ // by counting forward from start insert position <rStartIdx> the
+ // determined number of text nodes.
+ aIdx = rStartIdx;
+ SwNodeIndex aAnchorNdIdx( rStartIdx );
+ const SwNode& aEndOfContentNd =
+ aIdx.GetNode().GetNodes().GetEndOfContent();
+ while ( nAnchorTxtNdNumInRange > 0 &&
+ &(aIdx.GetNode()) != &aEndOfContentNd )
+ {
+ if ( aIdx.GetNode().IsTxtNode() )
+ {
+ --nAnchorTxtNdNumInRange;
+ aAnchorNdIdx = aIdx;
+ }
+
+ ++aIdx;
+ }
+ if ( !aAnchorNdIdx.GetNode().IsTxtNode() )
+ {
+ // This case can *not* happen, but to be robust take the first
+ // text node in the destination document.
+ OSL_FAIL( "<SwDoc::_CopyFlyInFly(..)> - found anchor node index isn't a text node" );
+ aAnchorNdIdx = rStartIdx;
+ while ( !aAnchorNdIdx.GetNode().IsTxtNode() )
+ {
+ ++aAnchorNdIdx;
+ }
+ }
+ // apply found anchor text node as new anchor position
+ pNewPos->nNode = aAnchorNdIdx;
+ }
+ else
+ {
+ long nOffset = pNewPos->nNode.GetIndex() - rRg.aStart.GetIndex();
+ SwNodeIndex aIdx( rStartIdx, nOffset );
+ pNewPos->nNode = aIdx;
+ }
+ // <--
+ // die am Zeichen Flys wieder ans das vorgegebene Zeichen setzen
+ if ((FLY_AT_CHAR == aAnchor.GetAnchorId()) &&
+ pNewPos->nNode.GetNode().IsTxtNode() )
+ {
+ pNewPos->nContent.Assign( (SwTxtNode*)&pNewPos->nNode.GetNode(),
+ pNewPos->nContent.GetIndex() );
+ }
+ else
+ {
+ pNewPos->nContent.Assign( 0, 0 );
+ }
+
+ // ueberpruefe Rekursion: Inhalt in "seinen eigenen" Frame
+ // kopieren. Dann nicht kopieren
+ sal_Bool bMakeCpy = sal_True;
+ if( pDest == this )
+ {
+ const SwFmtCntnt& rCntnt = rZSortFly.GetFmt()->GetCntnt();
+ const SwStartNode* pSNd;
+ if( rCntnt.GetCntntIdx() &&
+ 0 != ( pSNd = rCntnt.GetCntntIdx()->GetNode().GetStartNode() ) &&
+ pSNd->GetIndex() < rStartIdx.GetIndex() &&
+ rStartIdx.GetIndex() < pSNd->EndOfSectionIndex() )
+ {
+ bMakeCpy = sal_False;
+ aArr.Remove( n, 1 );
+ --n;
+ }
+ }
+
+ // Format kopieren und den neuen Anker setzen
+ if( bMakeCpy )
+ aNewArr.Insert( pDest->CopyLayoutFmt( *rZSortFly.GetFmt(),
+ aAnchor, false, true ), aNewArr.Count() );
+ }
+
+ //Alle chains, die im Original vorhanden sind, soweit wie moeglich wieder
+ //aufbauen.
+ OSL_ENSURE( aArr.Count() == aNewArr.Count(), "Missing new Flys" );
+ if ( aArr.Count() == aNewArr.Count() )
+ {
+ for ( sal_uInt16 n = 0; n < aArr.Count(); ++n )
+ {
+ const SwFrmFmt *pFmt = aArr[n].GetFmt();
+ const SwFmtChain &rChain = pFmt->GetChain();
+ int nCnt = 0 != rChain.GetPrev();
+ nCnt += rChain.GetNext() ? 1: 0;
+ for ( sal_uInt16 k = 0; nCnt && k < aArr.Count(); ++k )
+ {
+ const _ZSortFly &rTmp = aArr[k];
+ const SwFrmFmt *pTmp = rTmp.GetFmt();
+ if ( rChain.GetPrev() == pTmp )
+ {
+ ::lcl_ChainFmts( (SwFlyFrmFmt*)aNewArr[k],
+ (SwFlyFrmFmt*)aNewArr[n] );
+ --nCnt;
+ }
+ else if ( rChain.GetNext() == pTmp )
+ {
+ ::lcl_ChainFmts( (SwFlyFrmFmt*)aNewArr[n],
+ (SwFlyFrmFmt*)aNewArr[k] );
+ --nCnt;
+ }
+ }
+ }
+ }
+}
+
+
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/docnode/ndindex.cxx b/sw/source/core/docnode/ndindex.cxx
new file mode 100644
index 000000000000..3b064674d7bd
--- /dev/null
+++ b/sw/source/core/docnode/ndindex.cxx
@@ -0,0 +1,166 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+#include "ndindex.hxx"
+
+#if OSL_DEBUG_LEVEL > 1
+int SwNodeIndex::nSerial = 0;
+#endif
+
+
+SwNodeRange::SwNodeRange( const SwNodeIndex &rS, const SwNodeIndex &rE )
+ : aStart( rS ), aEnd( rE )
+{}
+
+SwNodeRange::SwNodeRange( const SwNodeRange &rRange )
+ : aStart( rRange.aStart ), aEnd( rRange.aEnd )
+{}
+
+SwNodeRange::SwNodeRange( SwNodes& rNds, sal_uLong nSttIdx, sal_uLong nEndIdx )
+ : aStart( rNds, nSttIdx ), aEnd( rNds, nEndIdx )
+{}
+
+
+SwNodeRange::SwNodeRange( const SwNodeIndex& rS, long nSttDiff,
+ const SwNodeIndex& rE, long nEndDiff )
+ : aStart( rS, nSttDiff ), aEnd( rE, nEndDiff )
+{}
+
+SwNodeRange::SwNodeRange( const SwNode& rS, long nSttDiff,
+ const SwNode& rE, long nEndDiff )
+ : aStart( rS, nSttDiff ), aEnd( rE, nEndDiff )
+{}
+
+
+SwNodeIndex::SwNodeIndex( SwNodes& rNds, sal_uLong nIdx )
+ : pNd( rNds[ nIdx ] ), pNext( 0 ), pPrev( 0 )
+{
+ rNds.RegisterIndex( *this );
+
+#if OSL_DEBUG_LEVEL > 1
+ MySerial = ++nSerial; // nur in der nicht PRODUCT-Version
+#endif
+}
+
+
+SwNodeIndex::SwNodeIndex( const SwNodeIndex& rIdx, long nDiff )
+ : pNext( 0 ), pPrev( 0 )
+{
+ if( nDiff )
+ pNd = rIdx.GetNodes()[ rIdx.GetIndex() + nDiff ];
+ else
+ pNd = rIdx.pNd;
+
+ pNd->GetNodes().RegisterIndex( *this );
+#if OSL_DEBUG_LEVEL > 1
+ MySerial = ++nSerial; // nur in der nicht PRODUCT-Version
+#endif
+}
+
+
+SwNodeIndex::SwNodeIndex( const SwNode& rNd, long nDiff )
+ : pNext( 0 ), pPrev( 0 )
+{
+ if( nDiff )
+ pNd = rNd.GetNodes()[ rNd.GetIndex() + nDiff ];
+ else
+ pNd = (SwNode*)&rNd;
+
+ pNd->GetNodes().RegisterIndex( *this );
+#if OSL_DEBUG_LEVEL > 1
+ MySerial = ++nSerial; // nur in der nicht PRODUCT-Version
+#endif
+}
+
+
+void SwNodeIndex::Remove()
+{
+ pNd->GetNodes().DeRegisterIndex( *this );
+}
+
+SwNodeIndex& SwNodeIndex::operator=( const SwNodeIndex& rIdx )
+{
+ if( &pNd->GetNodes() != &rIdx.pNd->GetNodes() )
+ {
+ pNd->GetNodes().DeRegisterIndex( *this );
+ pNd = rIdx.pNd;
+ pNd->GetNodes().RegisterIndex( *this );
+ }
+ else
+ pNd = rIdx.pNd;
+ return *this;
+}
+
+SwNodeIndex& SwNodeIndex::operator=( const SwNode& rNd )
+{
+ if( &pNd->GetNodes() != &rNd.GetNodes() )
+ {
+ pNd->GetNodes().DeRegisterIndex( *this );
+ pNd = (SwNode*)&rNd;
+ pNd->GetNodes().RegisterIndex( *this );
+ }
+ else
+ pNd = (SwNode*)&rNd;
+ return *this;
+}
+
+SwNodeIndex& SwNodeIndex::Assign( SwNodes& rNds, sal_uLong nIdx )
+{
+ if( &pNd->GetNodes() != &rNds )
+ {
+ pNd->GetNodes().DeRegisterIndex( *this );
+ pNd = rNds[ nIdx ];
+ pNd->GetNodes().RegisterIndex( *this );
+ }
+ else
+ pNd = rNds[ nIdx ];
+ return *this;
+}
+
+SwNodeIndex& SwNodeIndex::Assign( const SwNode& rNd, long nOffset )
+{
+ if( &pNd->GetNodes() != &rNd.GetNodes() )
+ {
+ pNd->GetNodes().DeRegisterIndex( *this );
+ pNd = (SwNode*)&rNd;
+ pNd->GetNodes().RegisterIndex( *this );
+ }
+ else
+ pNd = (SwNode*)&rNd;
+
+ if( nOffset )
+ pNd = pNd->GetNodes()[ pNd->GetIndex() + nOffset ];
+
+ return *this;
+}
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/docnode/ndnotxt.cxx b/sw/source/core/docnode/ndnotxt.cxx
new file mode 100644
index 000000000000..c244e14267c4
--- /dev/null
+++ b/sw/source/core/docnode/ndnotxt.cxx
@@ -0,0 +1,308 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+
+#include <hintids.hxx>
+#include <tools/poly.hxx>
+#include <svl/stritem.hxx>
+#include <svx/contdlg.hxx>
+#include <vcl/svapp.hxx>
+#include <docary.hxx>
+#include <doc.hxx>
+#include <fmtcol.hxx>
+#include <ndnotxt.hxx>
+#include <ndgrf.hxx>
+#include <ndole.hxx>
+#include <ndindex.hxx>
+#include <hints.hxx> // fuer SwFmtChg
+#include <istyleaccess.hxx>
+#include <SwStyleNameMapper.hxx>
+
+#include <frmfmt.hxx> // #i73249#
+
+SwNoTxtNode::SwNoTxtNode( const SwNodeIndex & rWhere,
+ const sal_uInt8 nNdType,
+ SwGrfFmtColl *pGrfColl,
+ SwAttrSet* pAutoAttr ) :
+ SwCntntNode( rWhere, nNdType, pGrfColl ),
+ pContour( 0 ),
+ bAutomaticContour( sal_False ),
+ bContourMapModeValid( sal_True ),
+ bPixelContour( sal_False )
+{
+ // soll eine Harte-Attributierung gesetzt werden?
+ if( pAutoAttr )
+ SetAttr( *pAutoAttr );
+}
+
+
+SwNoTxtNode::~SwNoTxtNode()
+{
+ delete pContour;
+}
+
+
+// erzeugt fuer alle Ableitungen einen AttrSet mit Bereichen
+// fuer Frame- und Grafik-Attributen
+void SwNoTxtNode::NewAttrSet( SwAttrPool& rPool )
+{
+ OSL_ENSURE( !mpAttrSet.get(), "AttrSet ist doch gesetzt" );
+ SwAttrSet aNewAttrSet( rPool, aNoTxtNodeSetRange );
+
+ // put names of parent style and conditional style:
+ const SwFmtColl* pFmtColl = GetFmtColl();
+ String sVal;
+ SwStyleNameMapper::FillProgName( pFmtColl->GetName(), sVal, nsSwGetPoolIdFromName::GET_POOLID_TXTCOLL, sal_True );
+ SfxStringItem aFmtColl( RES_FRMATR_STYLE_NAME, sVal );
+ aNewAttrSet.Put( aFmtColl );
+
+ aNewAttrSet.SetParent( &GetFmtColl()->GetAttrSet() );
+ mpAttrSet = GetDoc()->GetIStyleAccess().getAutomaticStyle( aNewAttrSet, IStyleAccess::AUTO_STYLE_NOTXT );
+}
+
+// Dummies fuer das Laden/Speichern von persistenten Daten
+// bei Grafiken und OLE-Objekten
+
+
+sal_Bool SwNoTxtNode::RestorePersistentData()
+{
+ return sal_True;
+}
+
+
+sal_Bool SwNoTxtNode::SavePersistentData()
+{
+ return sal_True;
+}
+
+
+void SwNoTxtNode::SetContour( const PolyPolygon *pPoly, sal_Bool bAutomatic )
+{
+ delete pContour;
+ if ( pPoly )
+ pContour = new PolyPolygon( *pPoly );
+ else
+ pContour = 0;
+ bAutomaticContour = bAutomatic;
+ bContourMapModeValid = sal_True;
+ bPixelContour = sal_False;
+}
+
+
+void SwNoTxtNode::CreateContour()
+{
+ OSL_ENSURE( !pContour, "Contour available." );
+ pContour = new PolyPolygon(SvxContourDlg::CreateAutoContour(GetGraphic()));
+ bAutomaticContour = sal_True;
+ bContourMapModeValid = sal_True;
+ bPixelContour = sal_False;
+}
+
+const PolyPolygon *SwNoTxtNode::HasContour() const
+{
+ if( !bContourMapModeValid )
+ {
+ const MapMode aGrfMap( GetGraphic().GetPrefMapMode() );
+ sal_Bool bPixelGrf = aGrfMap.GetMapUnit() == MAP_PIXEL;
+ const MapMode aContourMap( bPixelGrf ? MAP_PIXEL : MAP_100TH_MM );
+ if( bPixelGrf ? !bPixelContour : aGrfMap != aContourMap )
+ {
+ OSL_ENSURE( !bPixelGrf || aGrfMap == aContourMap,
+ "scale factor for pixel unsupported" );
+ OutputDevice* pOutDev =
+ (bPixelGrf || bPixelContour) ? Application::GetDefaultDevice()
+ : 0;
+ sal_uInt16 nPolyCount = pContour->Count();
+ for( sal_uInt16 j=0; j<nPolyCount; j++ )
+ {
+ Polygon& rPoly = (*pContour)[j];
+
+ sal_uInt16 nCount = rPoly.GetSize();
+ for( sal_uInt16 i=0 ; i<nCount; i++ )
+ {
+ if( bPixelGrf )
+ rPoly[i] = pOutDev->LogicToPixel( rPoly[i],
+ aContourMap );
+ else if( bPixelContour )
+ rPoly[i] = pOutDev->PixelToLogic( rPoly[i], aGrfMap );
+ else
+ rPoly[i] = OutputDevice::LogicToLogic( rPoly[i],
+ aContourMap,
+ aGrfMap );
+ }
+ }
+ }
+ ((SwNoTxtNode *)this)->bContourMapModeValid = sal_True;
+ ((SwNoTxtNode *)this)->bPixelContour = sal_False;
+ }
+
+ return pContour;
+}
+
+void SwNoTxtNode::GetContour( PolyPolygon &rPoly ) const
+{
+ OSL_ENSURE( pContour, "Contour not available." );
+ rPoly = *HasContour();
+}
+
+void SwNoTxtNode::SetContourAPI( const PolyPolygon *pPoly )
+{
+ delete pContour;
+ if ( pPoly )
+ pContour = new PolyPolygon( *pPoly );
+ else
+ pContour = 0;
+ bContourMapModeValid = sal_False;
+}
+
+sal_Bool SwNoTxtNode::GetContourAPI( PolyPolygon &rContour ) const
+{
+ if( !pContour )
+ return sal_False;
+
+ rContour = *pContour;
+ if( bContourMapModeValid )
+ {
+ const MapMode aGrfMap( GetGraphic().GetPrefMapMode() );
+ const MapMode aContourMap( MAP_100TH_MM );
+ OSL_ENSURE( aGrfMap.GetMapUnit() != MAP_PIXEL ||
+ aGrfMap == MapMode( MAP_PIXEL ),
+ "scale factor for pixel unsupported" );
+ if( aGrfMap.GetMapUnit() != MAP_PIXEL &&
+ aGrfMap != aContourMap )
+ {
+ sal_uInt16 nPolyCount = rContour.Count();
+ for( sal_uInt16 j=0; j<nPolyCount; j++ )
+ {
+ Polygon& rPoly = (*pContour)[j];
+
+ sal_uInt16 nCount = rPoly.GetSize();
+ for( sal_uInt16 i=0 ; i<nCount; i++ )
+ {
+ rPoly[i] = OutputDevice::LogicToLogic( rPoly[i], aGrfMap,
+ aContourMap );
+ }
+ }
+ }
+ }
+
+ return sal_True;
+}
+
+sal_Bool SwNoTxtNode::IsPixelContour() const
+{
+ sal_Bool bRet;
+ if( bContourMapModeValid )
+ {
+ const MapMode aGrfMap( GetGraphic().GetPrefMapMode() );
+ bRet = aGrfMap.GetMapUnit() == MAP_PIXEL;
+ }
+ else
+ {
+ bRet = bPixelContour;
+ }
+
+ return bRet;
+}
+
+
+Graphic SwNoTxtNode::GetGraphic() const
+{
+ Graphic aRet;
+ if ( GetGrfNode() )
+ {
+ ((SwGrfNode*)this)->SwapIn( sal_True );
+ aRet = ((SwGrfNode*)this)->GetGrf();
+ }
+ else
+ {
+ OSL_ENSURE( GetOLENode(), "new type of Node?" );
+ aRet = *((SwOLENode*)this)->SwOLENode::GetGraphic();
+ }
+ return aRet;
+}
+
+// #i73249#
+void SwNoTxtNode::SetTitle( const String& rTitle, bool bBroadcast )
+{
+ // Title attribute of <SdrObject> replaces own AlternateText attribute
+ SwFlyFrmFmt* pFlyFmt = dynamic_cast<SwFlyFrmFmt*>(GetFlyFmt());
+ OSL_ENSURE( pFlyFmt,
+ "<SwNoTxtNode::SetTitle(..)> - missing <SwFlyFrmFmt> instance" );
+ if ( !pFlyFmt )
+ {
+ return;
+ }
+
+ pFlyFmt->SetObjTitle( rTitle, bBroadcast );
+}
+
+const String SwNoTxtNode::GetTitle() const
+{
+ const SwFlyFrmFmt* pFlyFmt = dynamic_cast<const SwFlyFrmFmt*>(GetFlyFmt());
+ OSL_ENSURE( pFlyFmt,
+ "<SwNoTxtNode::GetTitle(..)> - missing <SwFlyFrmFmt> instance" );
+ if ( !pFlyFmt )
+ {
+ return aEmptyStr;
+ }
+
+ return pFlyFmt->GetObjTitle();
+}
+
+void SwNoTxtNode::SetDescription( const String& rDescription, bool bBroadcast )
+{
+ SwFlyFrmFmt* pFlyFmt = dynamic_cast<SwFlyFrmFmt*>(GetFlyFmt());
+ OSL_ENSURE( pFlyFmt,
+ "<SwNoTxtNode::SetDescription(..)> - missing <SwFlyFrmFmt> instance" );
+ if ( !pFlyFmt )
+ {
+ return;
+ }
+
+ pFlyFmt->SetObjDescription( rDescription, bBroadcast );
+}
+
+const String SwNoTxtNode::GetDescription() const
+{
+ const SwFlyFrmFmt* pFlyFmt = dynamic_cast<const SwFlyFrmFmt*>(GetFlyFmt());
+ OSL_ENSURE( pFlyFmt,
+ "<SwNoTxtNode::GetDescription(..)> - missing <SwFlyFrmFmt> instance" );
+ if ( !pFlyFmt )
+ {
+ return aEmptyStr;
+ }
+
+ return pFlyFmt->GetObjDescription();
+}
+// <--
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/docnode/ndnum.cxx b/sw/source/core/docnode/ndnum.cxx
new file mode 100644
index 000000000000..5cbce94d072c
--- /dev/null
+++ b/sw/source/core/docnode/ndnum.cxx
@@ -0,0 +1,148 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+
+#include <node.hxx>
+#include <doc.hxx>
+#include <pam.hxx>
+#include <ndtxt.hxx>
+#include <fldbas.hxx> // UpdateFlds der KapitelNummerierung
+#include <docary.hxx>
+
+_SV_IMPL_SORTAR_ALG( SwOutlineNodes, SwNodePtr )
+sal_Bool SwOutlineNodes::Seek_Entry( const SwNodePtr rSrch, sal_uInt16* pFndPos ) const
+{
+ sal_uLong nIdx = rSrch->GetIndex();
+
+ sal_uInt16 nO = Count(), nM, nU = 0;
+ if( nO > 0 )
+ {
+//JP 17.03.98: aufgrund des Bug 48592 - wo unter anderem nach Undo/Redo
+// Nodes aus dem falschen NodesArray im OutlineArray standen,
+// jetzt mal einen Check eingebaut.
+#if OSL_DEBUG_LEVEL > 1
+ {
+ for( sal_uInt16 n = 1; n < nO; ++n )
+ if( &(*this)[ n-1 ]->GetNodes() !=
+ &(*this)[ n ]->GetNodes() )
+ {
+ OSL_ENSURE( !this, "Node im falschen Outline-Array" );
+ }
+ }
+#endif
+
+ nO--;
+ while( nU <= nO )
+ {
+ nM = nU + ( nO - nU ) / 2;
+ if( (*this)[ nM ] == rSrch )
+ {
+ if( pFndPos )
+ *pFndPos = nM;
+ return sal_True;
+ }
+ else if( (*this)[ nM ]->GetIndex() < nIdx )
+ nU = nM + 1;
+ else if( nM == 0 )
+ {
+ if( pFndPos )
+ *pFndPos = nU;
+ return sal_False;
+ }
+ else
+ nO = nM - 1;
+ }
+ }
+ if( pFndPos )
+ *pFndPos = nU;
+ return sal_False;
+}
+
+void SwNodes::UpdateOutlineNode(SwNode & rNd)
+{
+ SwTxtNode * pTxtNd = rNd.GetTxtNode();
+
+ if (pTxtNd && pTxtNd->IsOutlineStateChanged())
+ {
+ sal_Bool bFound = pOutlineNds->Seek_Entry(pTxtNd);
+
+ if (pTxtNd->IsOutline())
+ {
+ if (! bFound)
+ {
+ // assure that text is in the correct nodes array
+ if ( &(pTxtNd->GetNodes()) == this )
+ {
+ pOutlineNds->Insert(pTxtNd);
+ }
+ else
+ {
+ OSL_FAIL( "<SwNodes::UpdateOutlineNode(..)> - given text node isn't in the correct nodes array. This is a serious defect -> inform OD" );
+ }
+ }
+ }
+ else
+ {
+ if (bFound)
+ pOutlineNds->Remove(pTxtNd);
+ }
+
+ pTxtNd->UpdateOutlineState();
+
+ // die Gliederungs-Felder Updaten
+ GetDoc()->GetSysFldType( RES_CHAPTERFLD )->UpdateFlds();
+ }
+}
+
+void SwNodes::UpdtOutlineIdx( const SwNode& rNd )
+{
+ if( !pOutlineNds->Count() ) // keine OutlineNodes vorhanden ?
+ return;
+
+ const SwNodePtr pSrch = (SwNodePtr)&rNd;
+ sal_uInt16 nPos;
+ pOutlineNds->Seek_Entry( pSrch, &nPos );
+ if( nPos == pOutlineNds->Count() ) // keine zum Updaten vorhanden ?
+ return;
+
+ if( nPos )
+ --nPos;
+
+ if( !GetDoc()->IsInDtor() && IsDocNodes() )
+ UpdateOutlineNode( *(*pOutlineNds)[ nPos ]);
+}
+
+const SwOutlineNodes & SwNodes::GetOutLineNds() const
+{
+ return *pOutlineNds;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/docnode/ndsect.cxx b/sw/source/core/docnode/ndsect.cxx
new file mode 100644
index 000000000000..00cee7bacd14
--- /dev/null
+++ b/sw/source/core/docnode/ndsect.cxx
@@ -0,0 +1,1479 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+#include <svl/smplhint.hxx>
+#include <hintids.hxx>
+#include <sfx2/linkmgr.hxx>
+#include <svl/itemiter.hxx>
+#include <tools/resid.hxx>
+#include <fmtcntnt.hxx>
+#include <fmtanchr.hxx>
+#include <txtftn.hxx>
+#include <fmtclds.hxx>
+#include <doc.hxx>
+#include <IDocumentUndoRedo.hxx>
+#include <rootfrm.hxx>
+#include <pam.hxx>
+#include <ndtxt.hxx>
+#include <section.hxx>
+#include <UndoSection.hxx>
+#include <UndoDelete.hxx>
+#include <swundo.hxx>
+#include <calc.hxx>
+#include <swtable.hxx>
+#include <swserv.hxx>
+#include <frmfmt.hxx>
+#include <frmtool.hxx>
+#include <ftnidx.hxx>
+#include <docary.hxx>
+#include <redline.hxx>
+#include <sectfrm.hxx>
+#include <pagefrm.hxx>
+#include <cntfrm.hxx>
+#include <node2lay.hxx>
+#include <doctxm.hxx>
+#include <fmtftntx.hxx>
+#include <comcore.hrc>
+// #i27138#
+#include <viewsh.hxx>
+#include <txtfrm.hxx>
+// <--
+
+
+// #i21457# - new implementation of local method <lcl_IsInSameTblBox(..)>.
+// Method now determines the previous/next on its own. Thus, it can be controlled,
+// for which previous/next is checked, if it's visible.
+bool lcl_IsInSameTblBox( SwNodes& _rNds,
+ const SwNode& _rNd,
+ const bool _bPrev )
+{
+ const SwTableNode* pTblNd = _rNd.FindTableNode();
+ if ( !pTblNd )
+ {
+ return true;
+ }
+
+ // determine index to be checked. Its assumed that a previous/next exist.
+ SwNodeIndex aChkIdx( _rNd );
+ {
+ // determine index of previous/next - skip hidden ones, which are
+ // inside the table.
+ // If found one is before/after table, this one isn't in the same
+ // table box as <_rNd>.
+ bool bFound = false;
+ do
+ {
+ if ( _bPrev
+ ? !_rNds.GoPrevSection( &aChkIdx, sal_False, sal_False )
+ : !_rNds.GoNextSection( &aChkIdx, sal_False, sal_False ) )
+ {
+ OSL_FAIL( "<lcl_IsInSameTblBox(..)> - no previous/next!" );
+ return false;
+ }
+ else
+ {
+ if ( aChkIdx < pTblNd->GetIndex() ||
+ aChkIdx > pTblNd->EndOfSectionNode()->GetIndex() )
+ {
+ return false;
+ }
+ else
+ {
+ // check, if found one isn't inside a hidden section, which
+ // is also inside the table.
+ SwSectionNode* pSectNd = aChkIdx.GetNode().FindSectionNode();
+ if ( !pSectNd ||
+ pSectNd->GetIndex() < pTblNd->GetIndex() ||
+ !pSectNd->GetSection().IsHiddenFlag() )
+ {
+ bFound = true;
+ }
+ }
+ }
+ } while ( !bFound );
+ }
+
+ // dann suche den StartNode der Box
+ const SwTableSortBoxes& rSortBoxes = pTblNd->GetTable().GetTabSortBoxes();
+ sal_uLong nIdx = _rNd.GetIndex();
+ for( sal_uInt16 n = 0; n < rSortBoxes.Count(); ++n )
+ {
+ const SwStartNode* pNd = rSortBoxes[ n ]->GetSttNd();
+ if ( pNd->GetIndex() < nIdx && nIdx < pNd->EndOfSectionIndex() )
+ {
+ // dann muss der andere Index in derselben Section liegen
+ nIdx = aChkIdx.GetIndex();
+ return pNd->GetIndex() < nIdx && nIdx < pNd->EndOfSectionIndex();
+ }
+ }
+
+ return true;
+}
+
+void lcl_CheckEmptyLayFrm( SwNodes& rNds, SwSectionData& rSectionData,
+ const SwNode& rStt, const SwNode& rEnd )
+{
+ SwNodeIndex aIdx( rStt );
+ if( !rNds.GoPrevSection( &aIdx, sal_True, sal_False ) ||
+ !CheckNodesRange( rStt, aIdx, sal_True ) ||
+ // #i21457#
+ !lcl_IsInSameTblBox( rNds, rStt, true ))
+ {
+ aIdx = rEnd;
+ if( !rNds.GoNextSection( &aIdx, sal_True, sal_False ) ||
+ !CheckNodesRange( rEnd, aIdx, sal_True ) ||
+ // #i21457#
+ !lcl_IsInSameTblBox( rNds, rEnd, false ))
+ {
+ rSectionData.SetHidden( false );
+ }
+ }
+}
+
+SwSection *
+SwDoc::InsertSwSection(SwPaM const& rRange, SwSectionData & rNewData,
+ SwTOXBase const*const pTOXBase,
+ SfxItemSet const*const pAttr, bool const bUpdate)
+{
+ const SwNode* pPrvNd = 0;
+ sal_uInt16 nRegionRet = 0;
+ if( rRange.HasMark() &&
+ 0 == ( nRegionRet = IsInsRegionAvailable( rRange, &pPrvNd ) ))
+ {
+ OSL_ENSURE( !this, "Selection ueber verschiedene Sections" );
+ return 0;
+ }
+
+ // Teste ob das gesamte Dokument versteckt werden soll,
+ // koennen wir zur Zeit nicht !!!!
+ if (rNewData.IsHidden() && rRange.HasMark())
+ {
+ const SwPosition *pStt = rRange.Start(), *pEnd = rRange.End();
+ if( !pStt->nContent.GetIndex() &&
+ pEnd->nNode.GetNode().GetCntntNode()->Len() ==
+ pEnd->nContent.GetIndex() )
+ {
+ ::lcl_CheckEmptyLayFrm( GetNodes(),
+ rNewData,
+ pStt->nNode.GetNode(),
+ pEnd->nNode.GetNode() );
+ }
+ }
+
+ SwUndoInsSection* pUndoInsSect = 0;
+ bool const bUndo(GetIDocumentUndoRedo().DoesUndo());
+ if (bUndo)
+ {
+ pUndoInsSect = new SwUndoInsSection(rRange, rNewData, pAttr, pTOXBase);
+ GetIDocumentUndoRedo().AppendUndo( pUndoInsSect );
+ GetIDocumentUndoRedo().DoUndo(false);
+ }
+
+ SwSectionFmt* const pFmt = MakeSectionFmt( 0 );
+ if ( pAttr )
+ {
+ pFmt->SetFmtAttr( *pAttr );
+ }
+
+ SwSectionNode* pNewSectNode = 0;
+
+ RedlineMode_t eOld = GetRedlineMode();
+ SetRedlineMode_intern( (RedlineMode_t)((eOld & ~nsRedlineMode_t::REDLINE_SHOW_MASK) | nsRedlineMode_t::REDLINE_IGNORE));
+
+ if( rRange.HasMark() )
+ {
+ SwPosition *pSttPos = (SwPosition*)rRange.Start(),
+ *pEndPos = (SwPosition*)rRange.End();
+ if( pPrvNd && 3 == nRegionRet )
+ {
+ OSL_ENSURE( pPrvNd, "der SectionNode fehlt" );
+ SwNodeIndex aStt( pSttPos->nNode ), aEnd( pEndPos->nNode, +1 );
+ while( pPrvNd != aStt.GetNode().StartOfSectionNode() )
+ aStt--;
+ while( pPrvNd != aEnd.GetNode().StartOfSectionNode() )
+ aEnd++;
+
+ --aEnd; // im InsertSection ist Ende inclusive
+ pNewSectNode = GetNodes().InsertTextSection(
+ aStt, *pFmt, rNewData, pTOXBase, & aEnd);
+ }
+ else
+ {
+ if( pUndoInsSect )
+ {
+ if( !( pPrvNd && 1 == nRegionRet ) &&
+ pSttPos->nContent.GetIndex() )
+ {
+ SwTxtNode* const pTNd =
+ pSttPos->nNode.GetNode().GetTxtNode();
+ if (pTNd)
+ {
+ pUndoInsSect->SaveSplitNode( pTNd, sal_True );
+ }
+ }
+
+ if ( !( pPrvNd && 2 == nRegionRet ) )
+ {
+ SwTxtNode *const pTNd =
+ pEndPos->nNode.GetNode().GetTxtNode();
+ if (pTNd &&
+ (pTNd->GetTxt().Len() != pEndPos->nContent.GetIndex()))
+ {
+ pUndoInsSect->SaveSplitNode( pTNd, sal_False );
+ }
+ }
+ }
+
+ const SwCntntNode* pCNd;
+ if( pPrvNd && 1 == nRegionRet )
+ {
+ pSttPos->nNode.Assign( *pPrvNd );
+ pSttPos->nContent.Assign( pSttPos->nNode.GetNode().GetCntntNode(), 0 );
+ }
+ else if( pSttPos->nContent.GetIndex() )
+ {
+ SplitNode( *pSttPos, false );
+ }
+
+ if( pPrvNd && 2 == nRegionRet )
+ {
+ pEndPos->nNode.Assign( *pPrvNd );
+ pEndPos->nContent.Assign( pEndPos->nNode.GetNode().GetCntntNode(), 0 );
+ }
+ else
+ {
+ pCNd = pEndPos->nNode.GetNode().GetCntntNode();
+ if( pCNd && pCNd->Len() != pEndPos->nContent.GetIndex() )
+ {
+ xub_StrLen nCntnt = pSttPos->nContent.GetIndex();
+ SplitNode( *pEndPos, false );
+
+ SwTxtNode* pTNd;
+ if( pEndPos->nNode.GetIndex() == pSttPos->nNode.GetIndex() )
+ {
+ pSttPos->nNode--;
+ pEndPos->nNode--;
+ pTNd = pSttPos->nNode.GetNode().GetTxtNode();
+ pSttPos->nContent.Assign( pTNd, nCntnt );
+ }
+ else
+ {
+ // wieder ans Ende vom vorherigen setzen
+ pEndPos->nNode--;
+ pTNd = pEndPos->nNode.GetNode().GetTxtNode();
+ }
+ if( pTNd ) nCntnt = pTNd->GetTxt().Len(); else nCntnt = 0;
+ pEndPos->nContent.Assign( pTNd, nCntnt );
+ }
+ }
+ pNewSectNode = GetNodes().InsertTextSection(
+ pSttPos->nNode, *pFmt, rNewData, pTOXBase, &pEndPos->nNode);
+ }
+ }
+ else
+ {
+ const SwPosition* pPos = rRange.GetPoint();
+ const SwCntntNode* pCNd = pPos->nNode.GetNode().GetCntntNode();
+ if( !pPos->nContent.GetIndex() )
+ {
+ pNewSectNode = GetNodes().InsertTextSection(
+ pPos->nNode, *pFmt, rNewData, pTOXBase, 0, true);
+ }
+ else if( pPos->nContent.GetIndex() == pCNd->Len() )
+ {
+ pNewSectNode = GetNodes().InsertTextSection(
+ pPos->nNode, *pFmt, rNewData, pTOXBase, 0, false);
+ }
+ else
+ {
+ if( pUndoInsSect && pCNd->IsTxtNode() )
+ {
+ pUndoInsSect->SaveSplitNode( (SwTxtNode*)pCNd, sal_True );
+ }
+ SplitNode( *pPos, false );
+ pNewSectNode = GetNodes().InsertTextSection(
+ pPos->nNode, *pFmt, rNewData, pTOXBase, 0, true);
+ }
+ }
+
+//FEATURE::CONDCOLL
+ pNewSectNode->CheckSectionCondColl();
+//FEATURE::CONDCOLL
+
+ SetRedlineMode_intern( eOld );
+
+ if( IsRedlineOn() || (!IsIgnoreRedline() && pRedlineTbl->Count() ))
+ {
+ SwPaM aPam( *pNewSectNode->EndOfSectionNode(), *pNewSectNode, 1 );
+ if( IsRedlineOn() )
+ {
+ AppendRedline( new SwRedline( nsRedlineType_t::REDLINE_INSERT, aPam ), true);
+ }
+ else
+ {
+ SplitRedline( aPam );
+ }
+ }
+
+ // ist eine Condition gesetzt
+ if (rNewData.IsHidden() && rNewData.GetCondition().Len())
+ {
+ // dann berechne bis zu dieser Position
+ SwCalc aCalc( *this );
+ if( ! IsInReading() )
+ {
+ FldsToCalc( aCalc, pNewSectNode->GetIndex(), USHRT_MAX );
+ }
+ SwSection& rNewSect = pNewSectNode->GetSection();
+ rNewSect.SetCondHidden( aCalc.Calculate( rNewSect.GetCondition() ).GetBool() );
+ }
+
+ sal_Bool bUpdateFtn = sal_False;
+ if( GetFtnIdxs().Count() && pAttr )
+ {
+ sal_uInt16 nVal = ((SwFmtFtnAtTxtEnd&)pAttr->Get(
+ RES_FTN_AT_TXTEND )).GetValue();
+ if( ( FTNEND_ATTXTEND_OWNNUMSEQ == nVal ||
+ FTNEND_ATTXTEND_OWNNUMANDFMT == nVal ) ||
+ ( FTNEND_ATTXTEND_OWNNUMSEQ == ( nVal = ((SwFmtEndAtTxtEnd&)
+ pAttr->Get( RES_END_AT_TXTEND )).GetValue() ) ||
+ FTNEND_ATTXTEND_OWNNUMANDFMT == nVal ))
+ {
+ bUpdateFtn = sal_True;
+ }
+ }
+
+ if( pUndoInsSect )
+ {
+ pUndoInsSect->SetSectNdPos( pNewSectNode->GetIndex() );
+ pUndoInsSect->SetUpdtFtnFlag( bUpdateFtn );
+ GetIDocumentUndoRedo().DoUndo(bUndo);
+ }
+
+ if (rNewData.IsLinkType())
+ {
+ pNewSectNode->GetSection().CreateLink( bUpdate ? CREATE_UPDATE : CREATE_CONNECT );
+ }
+
+ if( bUpdateFtn )
+ {
+ GetFtnIdxs().UpdateFtn( SwNodeIndex( *pNewSectNode ));
+ }
+
+ SetModified();
+ return &pNewSectNode->GetSection();
+}
+
+sal_uInt16 SwDoc::IsInsRegionAvailable( const SwPaM& rRange,
+ const SwNode** ppSttNd ) const
+{
+ sal_uInt16 nRet = 1;
+ if( rRange.HasMark() )
+ {
+ // teste ob es sich um eine gueltige Selektion handelt
+ const SwPosition* pStt = rRange.Start(),
+ * pEnd = rRange.End();
+
+ const SwCntntNode* pCNd = pEnd->nNode.GetNode().GetCntntNode();
+ const SwNode* pNd = &pStt->nNode.GetNode();
+ const SwSectionNode* pSectNd = pNd->FindSectionNode();
+ const SwSectionNode* pEndSectNd = pCNd ? pCNd->FindSectionNode() : 0;
+ if( pSectNd && pEndSectNd && pSectNd != pEndSectNd )
+ {
+ // versuche eine umschliessende Section zu erzeugen
+ // Aber, nur wenn der Start am Sectionanfang und das Ende am
+ // Section Ende liegt!
+ nRet = 0;
+ if( !pStt->nContent.GetIndex() && pSectNd->GetIndex()
+ == pStt->nNode.GetIndex() - 1 && pEnd->nContent.GetIndex() ==
+ pCNd->Len() )
+ {
+ SwNodeIndex aIdx( pStt->nNode, -1 );
+ sal_uLong nCmp = pEnd->nNode.GetIndex();
+ const SwStartNode* pPrvNd;
+ const SwEndNode* pNxtNd;
+ while( 0 != ( pPrvNd = (pNd = &aIdx.GetNode())->GetSectionNode() ) &&
+ !( aIdx.GetIndex() < nCmp &&
+ nCmp < pPrvNd->EndOfSectionIndex() ) )
+ {
+ aIdx--;
+ }
+ if( !pPrvNd )
+ pPrvNd = pNd->IsStartNode() ? (SwStartNode*)pNd
+ : pNd->StartOfSectionNode();
+
+ aIdx = pEnd->nNode.GetIndex() + 1;
+ nCmp = pStt->nNode.GetIndex();
+ while( 0 != ( pNxtNd = (pNd = &aIdx.GetNode())->GetEndNode() ) &&
+ pNxtNd->StartOfSectionNode()->IsSectionNode() &&
+ !( pNxtNd->StartOfSectionIndex() < nCmp &&
+ nCmp < aIdx.GetIndex() ) )
+ {
+ aIdx++;
+ }
+ if( !pNxtNd )
+ pNxtNd = pNd->EndOfSectionNode();
+
+ if( pPrvNd && pNxtNd && pPrvNd == pNxtNd->StartOfSectionNode() )
+ {
+ nRet = 3;
+
+ if( ppSttNd )
+ *ppSttNd = pPrvNd;
+ }
+ }
+ }
+ else if( !pSectNd && pEndSectNd )
+ {
+ // versuche eine umschliessende Section zu erzeugen
+ // Aber, nur wenn das Ende am Section Ende liegt!
+ nRet = 0;
+ if( pEnd->nContent.GetIndex() == pCNd->Len() )
+ {
+ SwNodeIndex aIdx( pEnd->nNode, 1 );
+ if( aIdx.GetNode().IsEndNode() &&
+ 0 != aIdx.GetNode().FindSectionNode() )
+ {
+ do {
+ aIdx++;
+ } while( aIdx.GetNode().IsEndNode() &&
+ 0 != aIdx.GetNode().FindSectionNode() );
+ {
+ nRet = 2;
+ if( ppSttNd )
+ {
+ aIdx--;
+ *ppSttNd = &aIdx.GetNode();
+ }
+ }
+ }
+ }
+ }
+ else if( pSectNd && !pEndSectNd )
+ {
+ // versuche eine umschliessende Section zu erzeugen
+ // Aber, nur wenn der Start am Section Anfang liegt!
+ nRet = 0;
+ if( !pStt->nContent.GetIndex() )
+ {
+ SwNodeIndex aIdx( pStt->nNode, -1 );
+ if( aIdx.GetNode().IsSectionNode() )
+ {
+ do {
+ aIdx--;
+ } while( aIdx.GetNode().IsSectionNode() );
+ if( !aIdx.GetNode().IsSectionNode() )
+ {
+ nRet = 1;
+ if( ppSttNd )
+ {
+ aIdx++;
+ *ppSttNd = &aIdx.GetNode();
+ }
+ }
+ }
+ }
+ }
+ }
+ return nRet;
+}
+
+SwSection* SwDoc::GetCurrSection( const SwPosition& rPos ) const
+{
+ const SwSectionNode* pSectNd = rPos.nNode.GetNode().FindSectionNode();
+ if( pSectNd )
+ return (SwSection*)&pSectNd->GetSection();
+ return 0;
+}
+
+SwSectionFmt* SwDoc::MakeSectionFmt( SwSectionFmt *pDerivedFrom )
+{
+ if( !pDerivedFrom )
+ pDerivedFrom = (SwSectionFmt*)pDfltFrmFmt;
+ SwSectionFmt* pNew = new SwSectionFmt( pDerivedFrom, this );
+ pSectionFmtTbl->Insert( pNew, pSectionFmtTbl->Count() );
+ return pNew;
+}
+
+void SwDoc::DelSectionFmt( SwSectionFmt *pFmt, sal_Bool bDelNodes )
+{
+ sal_uInt16 nPos = pSectionFmtTbl->GetPos( pFmt );
+
+ GetIDocumentUndoRedo().StartUndo(UNDO_DELSECTION, NULL);
+
+ if( USHRT_MAX != nPos )
+ {
+ const SwNodeIndex* pIdx = pFmt->GetCntnt( sal_False ).GetCntntIdx();
+ const SfxPoolItem* pFtnEndAtTxtEnd;
+ if( SFX_ITEM_SET != pFmt->GetItemState(
+ RES_FTN_AT_TXTEND, sal_True, &pFtnEndAtTxtEnd ) ||
+ SFX_ITEM_SET != pFmt->GetItemState(
+ RES_END_AT_TXTEND, sal_True, &pFtnEndAtTxtEnd ))
+ pFtnEndAtTxtEnd = 0;
+
+ const SwSectionNode* pSectNd;
+
+ if( GetIDocumentUndoRedo().DoesUndo() )
+ {
+ if( bDelNodes && pIdx && &GetNodes() == &pIdx->GetNodes() &&
+ 0 != (pSectNd = pIdx->GetNode().GetSectionNode() ))
+ {
+ SwNodeIndex aUpdIdx( *pIdx );
+ SwPaM aPaM( *pSectNd->EndOfSectionNode(), *pSectNd );
+ GetIDocumentUndoRedo().AppendUndo( new SwUndoDelete( aPaM ));
+ if( pFtnEndAtTxtEnd )
+ GetFtnIdxs().UpdateFtn( aUpdIdx );
+ SetModified();
+ //#126178# start/end undo have to be pairs!
+ GetIDocumentUndoRedo().EndUndo(UNDO_DELSECTION, NULL);
+ return ;
+ }
+ GetIDocumentUndoRedo().AppendUndo( MakeUndoDelSection( *pFmt ) );
+ }
+ else if( bDelNodes && pIdx && &GetNodes() == &pIdx->GetNodes() &&
+ 0 != (pSectNd = pIdx->GetNode().GetSectionNode() ))
+ {
+ SwNodeIndex aUpdIdx( *pIdx );
+ DeleteSection( (SwNode*)pSectNd );
+ if( pFtnEndAtTxtEnd )
+ GetFtnIdxs().UpdateFtn( aUpdIdx );
+ SetModified();
+ //#126178# start/end undo have to be pairs!
+ GetIDocumentUndoRedo().EndUndo(UNDO_DELSECTION, NULL);
+ return ;
+ }
+
+ {
+ SwPtrMsgPoolItem aMsgHint( RES_REMOVE_UNO_OBJECT, pFmt );
+ pFmt->ModifyNotification( &aMsgHint, &aMsgHint );
+ }
+
+ // A ClearRedo could result in a rekursive call of this function and delete some section
+ // formats => the position iside the SectionFmtTbl could have changed
+ nPos = pSectionFmtTbl->GetPos( pFmt );
+
+ // ACHTUNG: erst aus dem Array entfernen und dann loeschen.
+ // Der Section-DTOR versucht selbst noch sein Format
+ // zu loeschen!
+ pSectionFmtTbl->Remove( nPos );
+//FEATURE::CONDCOLL
+ sal_uLong nCnt = 0, nSttNd = 0;
+ if( pIdx && &GetNodes() == &pIdx->GetNodes() &&
+ 0 != (pSectNd = pIdx->GetNode().GetSectionNode() ))
+ {
+ nSttNd = pSectNd->GetIndex();
+ nCnt = pSectNd->EndOfSectionIndex() - nSttNd - 1;
+ }
+//FEATURE::CONDCOLL
+
+ delete pFmt;
+
+ if( nSttNd && pFtnEndAtTxtEnd )
+ {
+ SwNodeIndex aUpdIdx( GetNodes(), nSttNd );
+ GetFtnIdxs().UpdateFtn( aUpdIdx );
+ }
+
+//FEATURE::CONDCOLL
+ SwCntntNode* pCNd;
+ for( ; nCnt--; ++nSttNd )
+ if( 0 != (pCNd = GetNodes()[ nSttNd ]->GetCntntNode() ) &&
+ RES_CONDTXTFMTCOLL == pCNd->GetFmtColl()->Which() )
+ pCNd->ChkCondColl();
+//FEATURE::CONDCOLL
+ }
+
+ GetIDocumentUndoRedo().EndUndo(UNDO_DELSECTION, NULL);
+
+ SetModified();
+}
+
+void SwDoc::UpdateSection(sal_uInt16 const nPos, SwSectionData & rNewData,
+ SfxItemSet const*const pAttr, bool const bPreventLinkUpdate)
+{
+ SwSectionFmt* pFmt = (*pSectionFmtTbl)[ nPos ];
+ SwSection* pSection = pFmt->GetSection();
+
+ /// remember hidden condition flag of SwSection before changes
+ bool bOldCondHidden = pSection->IsCondHidden() ? true : false;
+
+ if (pSection->DataEquals(rNewData))
+ {
+ // die Attribute ueberpruefen
+ sal_Bool bOnlyAttrChg = sal_False;
+ if( pAttr && pAttr->Count() )
+ {
+ SfxItemIter aIter( *pAttr );
+ sal_uInt16 nWhich = aIter.GetCurItem()->Which();
+ while( sal_True )
+ {
+ if( pFmt->GetFmtAttr( nWhich ) != *aIter.GetCurItem() )
+ {
+ bOnlyAttrChg = sal_True;
+ break;
+ }
+
+ if( aIter.IsAtEnd() )
+ break;
+ nWhich = aIter.NextItem()->Which();
+ }
+ }
+
+ if( bOnlyAttrChg )
+ {
+ if (GetIDocumentUndoRedo().DoesUndo())
+ {
+ GetIDocumentUndoRedo().AppendUndo(
+ MakeUndoUpdateSection( *pFmt, true ) );
+ }
+ // #i32968# Inserting columns in the section causes MakeFrmFmt
+ // to put two objects of type SwUndoFrmFmt on the undo stack.
+ // We don't want them.
+ ::sw::UndoGuard const undoGuard(GetIDocumentUndoRedo());
+ pFmt->SetFmtAttr( *pAttr );
+ SetModified();
+ }
+ return;
+ }
+
+ // Teste ob eine gesamte Content-Section (Dokument/TabellenBox/Fly)
+ // versteckt werden soll, koennen wir zur Zeit nicht !!!!
+ const SwNodeIndex* pIdx = 0;
+ {
+ if (rNewData.IsHidden())
+ {
+ pIdx = pFmt->GetCntnt().GetCntntIdx();
+ if (pIdx)
+ {
+ const SwSectionNode* pSectNd =
+ pIdx->GetNode().GetSectionNode();
+ if (pSectNd)
+ {
+ ::lcl_CheckEmptyLayFrm( GetNodes(), rNewData,
+ *pSectNd, *pSectNd->EndOfSectionNode() );
+ }
+ }
+ }
+ }
+
+ if (GetIDocumentUndoRedo().DoesUndo())
+ {
+ GetIDocumentUndoRedo().AppendUndo(MakeUndoUpdateSection(*pFmt, false));
+ }
+ // #i32968# Inserting columns in the section causes MakeFrmFmt to put two
+ // objects of type SwUndoFrmFmt on the undo stack. We don't want them.
+ ::sw::UndoGuard const undoGuard(GetIDocumentUndoRedo());
+
+ // Der LinkFileName koennte auch nur aus Separatoren bestehen
+ String sCompareString = sfx2::cTokenSeperator;
+ sCompareString += sfx2::cTokenSeperator;
+ const bool bUpdate =
+ (!pSection->IsLinkType() && rNewData.IsLinkType())
+ || ( rNewData.GetLinkFileName().Len()
+ && (rNewData.GetLinkFileName() != sCompareString)
+ && (rNewData.GetLinkFileName() != pSection->GetLinkFileName()));
+
+ String sSectName( rNewData.GetSectionName() );
+ if (sSectName != pSection->GetSectionName())
+ GetUniqueSectionName( &sSectName );
+ else
+ sSectName.Erase();
+
+ /// In SwSection::operator=(..) class member bCondHiddenFlag is always set to sal_True.
+ /// IMHO this have to be changed, but I can't estimate the consequences:
+ /// Either it is set to sal_True using corresponding method <SwSection.SetCondHidden(..)>,
+ /// or it is set to the value of SwSection which is assigned to it.
+ /// Discussion with AMA results that the adjustment to the assignment operator
+ /// could be very risky.
+ pSection->SetSectionData(rNewData);
+
+ if( pAttr )
+ pSection->GetFmt()->SetFmtAttr( *pAttr );
+
+ if( sSectName.Len() )
+ {
+ pSection->SetSectionName( sSectName );
+ }
+
+ // ist eine Condition gesetzt
+ if( pSection->IsHidden() && pSection->GetCondition().Len() )
+ {
+ // dann berechne bis zu dieser Position
+ SwCalc aCalc( *this );
+ if( !pIdx )
+ pIdx = pFmt->GetCntnt().GetCntntIdx();
+ FldsToCalc( aCalc, pIdx->GetIndex(), USHRT_MAX );
+
+ /// Because on using SwSection::operator=() to set up <pSection>
+ /// with <rNewData> and the above given note, the hidden condition flag
+ /// has to be set to sal_False, if hidden condition flag of <pFmt->GetSection()>
+ /// (SwSection before the changes) is sal_False (already saved in <bOldCondHidden>)
+ /// and new calculated condition is sal_True.
+ /// This is necessary, because otherwise the <SetCondHidden> would have
+ /// no effect.
+ bool bCalculatedCondHidden =
+ aCalc.Calculate( pSection->GetCondition() ).GetBool() ? true : false;
+ if ( bCalculatedCondHidden && !bOldCondHidden )
+ {
+ pSection->SetCondHidden( false );
+ }
+ pSection->SetCondHidden( bCalculatedCondHidden );
+ }
+
+ if( bUpdate )
+ pSection->CreateLink( bPreventLinkUpdate ? CREATE_CONNECT : CREATE_UPDATE );
+ else if( !pSection->IsLinkType() && pSection->IsConnected() )
+ {
+ pSection->Disconnect();
+ GetLinkManager().Remove( &pSection->GetBaseLink() );
+ }
+
+ SetModified();
+}
+
+/* --------------------------------------------------
+ * LockFrms wurde im InsertSection genutzt, um zu verhindern, dass
+ * SectionFrms durch das DelFrms zerstoert werden. Dies ist durch
+ * den Destroy-Listen-Mechanismus ueberfluessig geworden.
+ * Falls diese Methode doch noch einmal reanimiert wird, bietet es
+ * sich vielleicht an, beim Entlocken die SectionFrms auf Inhalt zu
+ * pruefen und dann ggf. zur Zerstoerung anzumelden.
+ * --------------------------------------------------*/
+
+// und dann waren da noch die Fussnoten:
+void lcl_DeleteFtn( SwSectionNode *pNd, sal_uLong nStt, sal_uLong nEnd )
+{
+ SwFtnIdxs& rFtnArr = pNd->GetDoc()->GetFtnIdxs();
+ if( rFtnArr.Count() )
+ {
+ sal_uInt16 nPos;
+ rFtnArr.SeekEntry( SwNodeIndex( *pNd ), &nPos );
+ SwTxtFtn* pSrch;
+
+ // loesche erstmal alle, die dahinter stehen
+ while( nPos < rFtnArr.Count() &&
+ _SwTxtFtn_GetIndex( (pSrch = rFtnArr[ nPos ]) ) <= nEnd )
+ {
+ // Werden die Nodes nicht geloescht mussen sie bei den Seiten
+ // abmeldet (Frms loeschen) werden, denn sonst bleiben sie
+ // stehen (Undo loescht sie nicht!)
+ pSrch->DelFrms(0);
+ ++nPos;
+ }
+
+ while( nPos-- &&
+ _SwTxtFtn_GetIndex( (pSrch = rFtnArr[ nPos ]) ) >= nStt )
+ {
+ // Werden die Nodes nicht geloescht mussen sie bei den Seiten
+ // abmeldet (Frms loeschen) werden, denn sonst bleiben sie
+ // stehen (Undo loescht sie nicht!)
+ pSrch->DelFrms(0);
+ }
+ }
+}
+
+static inline bool lcl_IsTOXSection(SwSectionData const& rSectionData)
+{
+ return (TOX_CONTENT_SECTION == rSectionData.GetType())
+ || (TOX_HEADER_SECTION == rSectionData.GetType());
+}
+
+SwSectionNode* SwNodes::InsertTextSection(SwNodeIndex const& rNdIdx,
+ SwSectionFmt& rSectionFmt,
+ SwSectionData const& rSectionData,
+ SwTOXBase const*const pTOXBase,
+ SwNodeIndex const*const pEnde,
+ bool const bInsAtStart, bool const bCreateFrms)
+{
+ SwNodeIndex aInsPos( rNdIdx );
+ if( !pEnde ) // kein Bereich also neue Section davor/hinter anlegen
+ {
+ // #i26762#
+ OSL_ENSURE(!pEnde || rNdIdx <= *pEnde,
+ "Section start and end in wrong order!");
+
+ if( bInsAtStart )
+ {
+ if (!lcl_IsTOXSection(rSectionData))
+ {
+ do {
+ aInsPos--;
+ } while( aInsPos.GetNode().IsSectionNode() );
+ aInsPos++;
+ }
+ }
+ else
+ {
+ SwNode* pNd;
+ aInsPos++;
+ if (!lcl_IsTOXSection(rSectionData))
+ {
+ while( aInsPos.GetIndex() < Count() - 1 &&
+ ( pNd = &aInsPos.GetNode())->IsEndNode() &&
+ pNd->StartOfSectionNode()->IsSectionNode())
+ {
+ aInsPos++;
+ }
+ }
+ }
+ }
+
+ SwSectionNode *const pSectNd =
+ new SwSectionNode(aInsPos, rSectionFmt, pTOXBase);
+ if( pEnde )
+ {
+ // Sonderfall fuer die Reader/Writer
+ if( &pEnde->GetNode() != &GetEndOfContent() )
+ aInsPos = pEnde->GetIndex()+1;
+ // #i58710: We created a RTF document with a section break inside a table cell
+ // We are not able to handle a section start inside a table and the section end outside.
+ const SwNode* pLastNode = pSectNd->StartOfSectionNode()->EndOfSectionNode();
+ if( aInsPos > pLastNode->GetIndex() )
+ aInsPos = pLastNode->GetIndex();
+ // Another way round: if the section starts outside a table but the end is inside...
+ // aInsPos is at the moment the Position where my EndNode will be inserted
+ const SwStartNode* pStartNode = aInsPos.GetNode().StartOfSectionNode();
+ // This StartNode should be in front of me, but if not, I wanna survive
+ sal_uLong nMyIndex = pSectNd->GetIndex();
+ if( pStartNode->GetIndex() > nMyIndex ) // Suspicious!
+ {
+ const SwNode* pTemp;
+ do
+ {
+ pTemp = pStartNode; // pTemp is a suspicious one
+ pStartNode = pStartNode->StartOfSectionNode();
+ }
+ while( pStartNode->GetIndex() > nMyIndex );
+ pTemp = pTemp->EndOfSectionNode();
+ // If it starts behind me but ends behind my end...
+ if( pTemp->GetIndex() >= aInsPos.GetIndex() )
+ aInsPos = pTemp->GetIndex()+1; // ...I have to correct my end position
+ }
+
+ }
+ else
+ {
+ SwTxtNode* pCpyTNd = rNdIdx.GetNode().GetTxtNode();
+ if( pCpyTNd )
+ {
+ SwTxtNode* pTNd = new SwTxtNode( aInsPos, pCpyTNd->GetTxtColl() );
+ if( pCpyTNd->HasSwAttrSet() )
+ {
+ // Task 70955 - move PageDesc/Break to the first Node of the
+ // section
+ const SfxItemSet& rSet = *pCpyTNd->GetpSwAttrSet();
+ if( SFX_ITEM_SET == rSet.GetItemState( RES_BREAK ) ||
+ SFX_ITEM_SET == rSet.GetItemState( RES_PAGEDESC ))
+ {
+ SfxItemSet aSet( rSet );
+ if( bInsAtStart )
+ pCpyTNd->ResetAttr( RES_PAGEDESC, RES_BREAK );
+ else
+ {
+ aSet.ClearItem( RES_PAGEDESC );
+ aSet.ClearItem( RES_BREAK );
+ }
+ pTNd->SetAttr( aSet );
+ }
+ else
+ pTNd->SetAttr( rSet );
+ }
+ // den Frame anlegen nicht vergessen !!
+ pCpyTNd->MakeFrms( *pTNd );
+ }
+ else
+ new SwTxtNode( aInsPos, (SwTxtFmtColl*)GetDoc()->GetDfltTxtFmtColl() );
+ }
+ new SwEndNode( aInsPos, *pSectNd );
+
+ pSectNd->GetSection().SetSectionData(rSectionData);
+ SwSectionFmt* pSectFmt = pSectNd->GetSection().GetFmt();
+
+ // Hier bietet sich als Optimierung an, vorhandene Frames nicht zu
+ // zerstoeren und wieder neu anzulegen, sondern nur umzuhaengen.
+ sal_Bool bInsFrm = bCreateFrms && !pSectNd->GetSection().IsHidden() &&
+ GetDoc()->GetCurrentViewShell(); //swmod 071108//swmod 071225
+ SwNode2Layout *pNode2Layout = NULL;
+ if( bInsFrm )
+ {
+ SwNodeIndex aTmp( *pSectNd );
+ if( !pSectNd->GetNodes().FindPrvNxtFrmNode( aTmp, pSectNd->EndOfSectionNode() ) )
+ // dann sammel mal alle Uppers ein
+ pNode2Layout = new SwNode2Layout( *pSectNd );
+ }
+
+ // jetzt noch bei allen im Bereich den richtigen StartNode setzen
+ sal_uLong nEnde = pSectNd->EndOfSectionIndex();
+ sal_uLong nStart = pSectNd->GetIndex()+1;
+ sal_uLong nSkipIdx = ULONG_MAX;
+ for( sal_uLong n = nStart; n < nEnde; ++n )
+ {
+ SwNode* pNd = (*this)[n];
+
+ //JP 30.04.99: Bug 65644 - alle in der NodeSection liegenden
+ // Sections unter die neue haengen
+ if( ULONG_MAX == nSkipIdx )
+ pNd->pStartOfSection = pSectNd;
+ else if( n >= nSkipIdx )
+ nSkipIdx = ULONG_MAX;
+
+ if( pNd->IsStartNode() )
+ {
+ // die Verschachtelung der Formate herstellen!
+ if( pNd->IsSectionNode() )
+ {
+ ((SwSectionNode*)pNd)->GetSection().GetFmt()->
+ SetDerivedFrom( pSectFmt );
+ ((SwSectionNode*)pNd)->DelFrms();
+ n = pNd->EndOfSectionIndex();
+ }
+ else
+ {
+ if( pNd->IsTableNode() )
+ ((SwTableNode*)pNd)->DelFrms();
+
+ if( ULONG_MAX == nSkipIdx )
+ nSkipIdx = pNd->EndOfSectionIndex();
+ }
+ }
+ else if( pNd->IsCntntNode() )
+ ((SwCntntNode*)pNd)->DelFrms();
+ }
+
+ lcl_DeleteFtn( pSectNd, nStart, nEnde );
+
+ if( bInsFrm )
+ {
+ if( pNode2Layout )
+ {
+ sal_uLong nIdx = pSectNd->GetIndex();
+ pNode2Layout->RestoreUpperFrms( pSectNd->GetNodes(), nIdx, nIdx + 1 );
+ delete pNode2Layout;
+ }
+ else
+ pSectNd->MakeFrms( &aInsPos );
+ }
+
+ return pSectNd;
+}
+
+SwSectionNode* SwNode::FindSectionNode()
+{
+ if( IsSectionNode() )
+ return GetSectionNode();
+ SwStartNode* pTmp = pStartOfSection;
+ while( !pTmp->IsSectionNode() && pTmp->GetIndex() )
+#if defined( ALPHA ) && defined( UNX )
+ pTmp = ((SwNode*)pTmp)->pStartOfSection;
+#else
+ pTmp = pTmp->pStartOfSection;
+#endif
+ return pTmp->GetSectionNode();
+}
+
+
+//---------
+// SwSectionNode
+//---------
+
+// ugly hack to make m_pSection const
+static SwSectionFmt &
+lcl_initParent(SwSectionNode & rThis, SwSectionFmt & rFmt)
+{
+ SwSectionNode *const pParent =
+ rThis.StartOfSectionNode()->FindSectionNode();
+ if( pParent )
+ {
+ // das Format beim richtigen Parent anmelden.
+ rFmt.SetDerivedFrom( pParent->GetSection().GetFmt() );
+ }
+ return rFmt;
+}
+
+SwSectionNode::SwSectionNode(SwNodeIndex const& rIdx,
+ SwSectionFmt & rFmt, SwTOXBase const*const pTOXBase)
+ : SwStartNode( rIdx, ND_SECTIONNODE )
+ , m_pSection( (pTOXBase)
+ ? new SwTOXBaseSection(*pTOXBase, lcl_initParent(*this, rFmt))
+ : new SwSection( CONTENT_SECTION, rFmt.GetName(),
+ lcl_initParent(*this, rFmt) ) )
+{
+ // jetzt noch die Verbindung von Format zum Node setzen
+ // Modify unterdruecken, interresiert keinen
+ rFmt.LockModify();
+ rFmt.SetFmtAttr( SwFmtCntnt( this ) );
+ rFmt.UnlockModify();
+}
+
+#if OSL_DEBUG_LEVEL > 1
+//Hier werden ueberfluessige SectionFrms entfernt
+SwFrm* SwClearDummies( SwFrm* pFrm )
+{
+ SwFrm* pTmp = pFrm;
+ while( pTmp )
+ {
+ OSL_ENSURE( !pTmp->GetUpper(), "SwClearDummies: No Upper allowed!" );
+ if( pTmp->IsSctFrm() )
+ {
+ SwSectionFrm* pSectFrm = (SwSectionFrm*)pFrm;
+ pTmp = pTmp->GetNext();
+ if( !pSectFrm->GetLower() )
+ {
+ if( pSectFrm->GetPrev() )
+ pSectFrm->GetPrev()->pNext = pTmp;
+ else
+ pFrm = pTmp;
+ if( pTmp )
+ pTmp->pPrev = pSectFrm->GetPrev();
+ delete pSectFrm;
+ }
+ }
+ else
+ pTmp = pTmp->GetNext();
+ }
+ return pFrm;
+}
+#endif
+
+SwSectionNode::~SwSectionNode()
+{
+ // mba: test if iteration works as clients will be removed in callback
+ m_pSection->GetFmt()->CallSwClientNotify( SfxSimpleHint( SFX_HINT_DYING ) );
+ SwSectionFmt* pFmt = m_pSection->GetFmt();
+ if( pFmt )
+ {
+ // das Attribut entfernen, weil die Section ihr Format loescht
+ // und falls das Cntnt-Attribut vorhanden ist, die Section aufhebt.
+ pFmt->LockModify();
+ pFmt->ResetFmtAttr( RES_CNTNT );
+ pFmt->UnlockModify();
+ }
+}
+
+
+SwFrm *SwSectionNode::MakeFrm( SwFrm *pSib )
+{
+ m_pSection->m_Data.SetHiddenFlag(false);
+ return new SwSectionFrm( *m_pSection, pSib );
+}
+
+//Methode erzeugt fuer den vorhergehenden Node alle Ansichten vom
+//Dokument. Die erzeugten Contentframes werden in das entsprechende
+//Layout gehaengt.
+void SwSectionNode::MakeFrms(const SwNodeIndex & rIdx )
+{
+ // also nehme meinen nachfolgenden oder vorhergehenden ContentFrame:
+ SwNodes& rNds = GetNodes();
+ if( rNds.IsDocNodes() && rNds.GetDoc()->GetCurrentViewShell() ) //swmod 071108//swmod 071225
+ {
+ if( GetSection().IsHidden() || IsCntntHidden() )
+ {
+ SwNodeIndex aIdx( *EndOfSectionNode() );
+ SwCntntNode* pCNd = rNds.GoNextSection( &aIdx, sal_True, sal_False );
+ if( !pCNd )
+ {
+ aIdx = *this;
+ if( 0 == ( pCNd = rNds.GoPrevSection( &aIdx, sal_True, sal_False )) )
+ return ;
+ }
+ pCNd = aIdx.GetNode().GetCntntNode();
+ pCNd->MakeFrms( (SwCntntNode&)rIdx.GetNode() );
+ }
+ else
+ {
+ SwNode2Layout aNode2Layout( *this, rIdx.GetIndex() );
+ SwFrm *pFrm, *pNew;
+ while( 0 != (pFrm = aNode2Layout.NextFrm()) )
+ {
+ OSL_ENSURE( pFrm->IsSctFrm(), "Depend von Section keine Section." );
+ pNew = rIdx.GetNode().GetCntntNode()->MakeFrm( pFrm );
+
+ SwSectionNode* pS = rIdx.GetNode().FindSectionNode();
+
+ // Assure that node is not inside a table, which is inside the
+ // found section.
+ if ( pS )
+ {
+ SwTableNode* pTableNode = rIdx.GetNode().FindTableNode();
+ if ( pTableNode &&
+ pTableNode->GetIndex() > pS->GetIndex() )
+ {
+ pS = 0;
+ }
+ }
+
+ // if the node is in a section, the sectionframe now
+ // has to be created..
+ // boolean to control <Init()> of a new section frame.
+ bool bInitNewSect = false;
+ if( pS )
+ {
+ SwSectionFrm *pSct = new SwSectionFrm( pS->GetSection(), pFrm );
+ // prepare <Init()> of new section frame.
+ bInitNewSect = true;
+ SwLayoutFrm* pUp = pSct;
+ while( pUp->Lower() ) // for columned sections
+ {
+ OSL_ENSURE( pUp->Lower()->IsLayoutFrm(),"Who's in there?" );
+ pUp = (SwLayoutFrm*)pUp->Lower();
+ }
+ pNew->Paste( pUp, NULL );
+ // #i27138#
+ // notify accessibility paragraphs objects about changed
+ // CONTENT_FLOWS_FROM/_TO relation.
+ // Relation CONTENT_FLOWS_FROM for next paragraph will change
+ // and relation CONTENT_FLOWS_TO for previous paragraph will change.
+ if ( pNew->IsTxtFrm() )
+ {
+ ViewShell* pViewShell( pNew->getRootFrm()->GetCurrShell() );
+ if ( pViewShell && pViewShell->GetLayout() &&
+ pViewShell->GetLayout()->IsAnyShellAccessible() )
+ {
+ pViewShell->InvalidateAccessibleParaFlowRelation(
+ dynamic_cast<SwTxtFrm*>(pNew->FindNextCnt( true )),
+ dynamic_cast<SwTxtFrm*>(pNew->FindPrevCnt( true )) );
+ }
+ }
+ // <--
+ pNew = pSct;
+ }
+
+ // wird ein Node vorher oder nachher mit Frames versehen
+ if ( rIdx < GetIndex() )
+ // der neue liegt vor mir
+ pNew->Paste( pFrm->GetUpper(), pFrm );
+ else
+ // der neue liegt hinter mir
+ pNew->Paste( pFrm->GetUpper(), pFrm->GetNext() );
+ // #i27138#
+ // notify accessibility paragraphs objects about changed
+ // CONTENT_FLOWS_FROM/_TO relation.
+ // Relation CONTENT_FLOWS_FROM for next paragraph will change
+ // and relation CONTENT_FLOWS_TO for previous paragraph will change.
+ if ( pNew->IsTxtFrm() )
+ {
+ ViewShell* pViewShell( pNew->getRootFrm()->GetCurrShell() );
+ if ( pViewShell && pViewShell->GetLayout() &&
+ pViewShell->GetLayout()->IsAnyShellAccessible() )
+ {
+ pViewShell->InvalidateAccessibleParaFlowRelation(
+ dynamic_cast<SwTxtFrm*>(pNew->FindNextCnt( true )),
+ dynamic_cast<SwTxtFrm*>(pNew->FindPrevCnt( true )) );
+ }
+ }
+ // <--
+ if ( bInitNewSect )
+ static_cast<SwSectionFrm*>(pNew)->Init();
+ }
+ }
+ }
+}
+
+//Fuer jedes vorkommen im Layout einen SectionFrm anlegen und vor den
+//entsprechenden CntntFrm pasten.
+
+void SwSectionNode::MakeFrms( SwNodeIndex* pIdxBehind, SwNodeIndex* pEndIdx )
+{
+ OSL_ENSURE( pIdxBehind, "kein Index" );
+ SwNodes& rNds = GetNodes();
+ SwDoc* pDoc = rNds.GetDoc();
+
+ *pIdxBehind = *this;
+
+ m_pSection->m_Data.SetHiddenFlag(true);
+
+ if( rNds.IsDocNodes() )
+ {
+ SwNodeIndex *pEnd = pEndIdx ? pEndIdx :
+ new SwNodeIndex( *EndOfSectionNode(), 1 );
+ ::MakeFrms( pDoc, *pIdxBehind, *pEnd );
+ if( !pEndIdx )
+ delete pEnd;
+ }
+
+}
+
+void SwSectionNode::DelFrms()
+{
+ sal_uLong nStt = GetIndex()+1, nEnd = EndOfSectionIndex();
+ if( nStt >= nEnd )
+ {
+ return ;
+ }
+
+ SwNodes& rNds = GetNodes();
+ m_pSection->GetFmt()->DelFrms();
+
+ // unser Flag muessen wir noch aktualisieren
+ m_pSection->m_Data.SetHiddenFlag(true);
+
+ // Bug 30582: falls der Bereich in Fly oder TabellenBox ist, dann
+ // kann er nur "gehiddet" werden, wenn weiterer Content
+ // vorhanden ist, der "Frames" haelt. Sonst hat der
+ // Fly/TblBox-Frame keinen Lower !!!
+ {
+ SwNodeIndex aIdx( *this );
+ if( !rNds.GoPrevSection( &aIdx, sal_True, sal_False ) ||
+ !CheckNodesRange( *this, aIdx, sal_True ) ||
+ // #i21457#
+ !lcl_IsInSameTblBox( rNds, *this, true ))
+ {
+ aIdx = *EndOfSectionNode();
+ if( !rNds.GoNextSection( &aIdx, sal_True, sal_False ) ||
+ !CheckNodesRange( *EndOfSectionNode(), aIdx, sal_True ) ||
+ // #i21457#
+ !lcl_IsInSameTblBox( rNds, *EndOfSectionNode(), false ))
+ {
+ m_pSection->m_Data.SetHiddenFlag(false);
+ }
+ }
+ }
+}
+
+SwSectionNode* SwSectionNode::MakeCopy( SwDoc* pDoc, const SwNodeIndex& rIdx ) const
+{
+ // in welchen Array steht ich denn: Nodes, UndoNodes ??
+ const SwNodes& rNds = GetNodes();
+
+ // das SectionFrmFmt kopieren
+ SwSectionFmt* pSectFmt = pDoc->MakeSectionFmt( 0 );
+ pSectFmt->CopyAttrs( *GetSection().GetFmt() );
+
+ ::std::auto_ptr<SwTOXBase> pTOXBase;
+ if (TOX_CONTENT_SECTION == GetSection().GetType())
+ {
+ OSL_ENSURE( GetSection().ISA( SwTOXBaseSection ), "no TOXBaseSection!" );
+ SwTOXBaseSection const& rTBS(
+ dynamic_cast<SwTOXBaseSection const&>(GetSection()));
+ pTOXBase.reset( new SwTOXBase(rTBS, pDoc) );
+ }
+
+ SwSectionNode *const pSectNd =
+ new SwSectionNode(rIdx, *pSectFmt, pTOXBase.get());
+ SwEndNode* pEndNd = new SwEndNode( rIdx, *pSectNd );
+ SwNodeIndex aInsPos( *pEndNd );
+
+ // Werte uebertragen
+ SwSection *const pNewSect = pSectNd->m_pSection.get();
+
+ if (TOX_CONTENT_SECTION != GetSection().GetType())
+ {
+ // beim Move den Namen beibehalten
+ if( rNds.GetDoc() == pDoc && pDoc->IsCopyIsMove() )
+ {
+ pNewSect->SetSectionName( GetSection().GetSectionName() );
+ }
+ else
+ {
+ pNewSect->SetSectionName(
+ pDoc->GetUniqueSectionName( &GetSection().GetSectionName() ));
+ }
+ }
+
+
+ pNewSect->SetType( GetSection().GetType() );
+ pNewSect->SetCondition( GetSection().GetCondition() );
+ pNewSect->SetLinkFileName( GetSection().GetLinkFileName() );
+ if( !pNewSect->IsHiddenFlag() && GetSection().IsHidden() )
+ pNewSect->SetHidden( sal_True );
+ if( !pNewSect->IsProtectFlag() && GetSection().IsProtect() )
+ pNewSect->SetProtect( sal_True );
+ // edit in readonly sections
+ if( !pNewSect->IsEditInReadonlyFlag() && GetSection().IsEditInReadonly() )
+ pNewSect->SetEditInReadonly( sal_True );
+
+ SwNodeRange aRg( *this, +1, *EndOfSectionNode() ); // (wo stehe in denn nun ??)
+ rNds._Copy( aRg, aInsPos, sal_False );
+
+ // loesche alle Frames vom kopierten Bereich, diese werden beim
+ // erzeugen des SectionFrames angelegt !
+ pSectNd->DelFrms();
+
+ // dann kopiere auch noch die Links/Server
+ if( pNewSect->IsLinkType() ) // den Link eintragen
+ pNewSect->CreateLink( pDoc->GetCurrentViewShell() ? CREATE_CONNECT //swmod 071108//swmod 071225
+ : CREATE_NONE );
+
+ // falls als Server aus dem Undo kopiert wird, wieder eintragen
+ if (m_pSection->IsServer()
+ && pDoc->GetIDocumentUndoRedo().IsUndoNodes(rNds))
+ {
+ pNewSect->SetRefObject( m_pSection->GetObject() );
+ pDoc->GetLinkManager().InsertServer( pNewSect->GetObject() );
+ }
+
+ // METADATA: copy xml:id; must be done after insertion of node
+ pSectFmt->RegisterAsCopyOf(*GetSection().GetFmt());
+
+ return pSectNd;
+}
+
+sal_Bool SwSectionNode::IsCntntHidden() const
+{
+ OSL_ENSURE( !m_pSection->IsHidden(),
+ "That's simple: Hidden Section => Hidden Content" );
+ SwNodeIndex aTmp( *this, 1 );
+ sal_uLong nEnd = EndOfSectionIndex();
+ while( aTmp < nEnd )
+ {
+ if( aTmp.GetNode().IsSectionNode() )
+ {
+ const SwSection& rSect = ((SwSectionNode&)aTmp.GetNode()).GetSection();
+ if( rSect.IsHiddenFlag() )
+ // dann diese Section ueberspringen
+ aTmp = *aTmp.GetNode().EndOfSectionNode();
+ }
+ else
+ {
+ if( aTmp.GetNode().IsCntntNode() || aTmp.GetNode().IsTableNode() )
+ return sal_False; // Nicht versteckter Inhalt wurde gefunden
+ OSL_ENSURE( aTmp.GetNode().IsEndNode(), "EndNode expected" );
+ }
+ aTmp++;
+ }
+ return sal_True; // Alles versteckt
+}
+
+
+void SwSectionNode::NodesArrChgd()
+{
+ SwSectionFmt *const pFmt = m_pSection->GetFmt();
+ if( pFmt )
+ {
+ SwNodes& rNds = GetNodes();
+ SwDoc* pDoc = pFmt->GetDoc();
+
+ if( !rNds.IsDocNodes() )
+ {
+ SwPtrMsgPoolItem aMsgHint( RES_REMOVE_UNO_OBJECT, pFmt );
+ pFmt->ModifyNotification( &aMsgHint, &aMsgHint );
+ }
+
+ pFmt->LockModify();
+ pFmt->SetFmtAttr( SwFmtCntnt( this ));
+ pFmt->UnlockModify();
+
+ SwSectionNode* pSectNd = StartOfSectionNode()->FindSectionNode();
+ // set the correct parent from the new section
+ pFmt->SetDerivedFrom( pSectNd ? pSectNd->GetSection().GetFmt()
+ : pDoc->GetDfltFrmFmt() );
+
+ // jetzt noch bei allen im Bereich den richtigen StartNode setzen
+ sal_uLong nStart = GetIndex()+1, nEnde = EndOfSectionIndex();
+ for( sal_uLong n = nStart; n < nEnde; ++n )
+ // die Verschachtelung der Formate herstellen!
+ if( 0 != ( pSectNd = rNds[ n ]->GetSectionNode() ) )
+ {
+ pSectNd->GetSection().GetFmt()->SetDerivedFrom( pFmt );
+ n = pSectNd->EndOfSectionIndex();
+ }
+
+ // verschieben vom Nodes- ins UndoNodes-Array?
+ if( rNds.IsDocNodes() )
+ {
+ OSL_ENSURE( pDoc == GetDoc(),
+ "verschieben in unterschiedliche Documente?" );
+ if( m_pSection->IsLinkType() ) // den Link austragen
+ m_pSection->CreateLink( pDoc->GetCurrentViewShell() ? CREATE_CONNECT //swmod 071108
+ : CREATE_NONE );//swmod 071225
+ if (m_pSection->IsServer())
+ {
+ pDoc->GetLinkManager().InsertServer( m_pSection->GetObject() );
+ }
+ }
+ else
+ {
+ if (CONTENT_SECTION != m_pSection->GetType())
+ {
+ pDoc->GetLinkManager().Remove( &m_pSection->GetBaseLink() );
+ }
+
+ if (m_pSection->IsServer())
+ {
+ pDoc->GetLinkManager().RemoveServer( m_pSection->GetObject() );
+ }
+ }
+ }
+}
+
+
+String SwDoc::GetUniqueSectionName( const String* pChkStr ) const
+{
+ ResId aId( STR_REGION_DEFNAME, *pSwResMgr );
+ String aName( aId );
+ xub_StrLen nNmLen = aName.Len();
+
+ sal_uInt16 nNum = 0;
+ sal_uInt16 nTmp, nFlagSize = ( pSectionFmtTbl->Count() / 8 ) +2;
+ sal_uInt8* pSetFlags = new sal_uInt8[ nFlagSize ];
+ memset( pSetFlags, 0, nFlagSize );
+
+ const SwSectionNode* pSectNd;
+ sal_uInt16 n;
+
+ for( n = 0; n < pSectionFmtTbl->Count(); ++n )
+ if( 0 != ( pSectNd = (*pSectionFmtTbl)[ n ]->GetSectionNode( sal_False ) ))
+ {
+ const String& rNm = pSectNd->GetSection().GetSectionName();
+ if( rNm.Match( aName ) == nNmLen )
+ {
+ // Nummer bestimmen und das Flag setzen
+ nNum = static_cast<sal_uInt16>(rNm.Copy( nNmLen ).ToInt32());
+ if( nNum-- && nNum < pSectionFmtTbl->Count() )
+ pSetFlags[ nNum / 8 ] |= (0x01 << ( nNum & 0x07 ));
+ }
+ if( pChkStr && pChkStr->Equals( rNm ) )
+ pChkStr = 0;
+ }
+
+ if( !pChkStr )
+ {
+ // alle Nummern entsprechend geflag, also bestimme die richtige Nummer
+ nNum = pSectionFmtTbl->Count();
+ for( n = 0; n < nFlagSize; ++n )
+ if( 0xff != ( nTmp = pSetFlags[ n ] ))
+ {
+ // also die Nummer bestimmen
+ nNum = n * 8;
+ while( nTmp & 1 )
+ ++nNum, nTmp >>= 1;
+ break;
+ }
+
+ }
+ delete [] pSetFlags;
+ if( pChkStr )
+ return *pChkStr;
+ return aName += String::CreateFromInt32( ++nNum );
+}
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/docnode/ndtbl.cxx b/sw/source/core/docnode/ndtbl.cxx
new file mode 100644
index 000000000000..a17567e7d04f
--- /dev/null
+++ b/sw/source/core/docnode/ndtbl.cxx
@@ -0,0 +1,4563 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+#include <com/sun/star/chart2/XChartDocument.hpp>
+#include <hintids.hxx>
+#include <editeng/lrspitem.hxx>
+#include <editeng/brkitem.hxx>
+#include <editeng/protitem.hxx>
+#include <editeng/boxitem.hxx>
+#include <svl/stritem.hxx>
+// #i17174#
+#include <editeng/shaditem.hxx>
+#include <fmtfsize.hxx>
+#include <fmtornt.hxx>
+#include <fmtfordr.hxx>
+#include <fmtpdsc.hxx>
+#include <fmtanchr.hxx>
+#include <fmtlsplt.hxx>
+#include <frmatr.hxx>
+#include <charatr.hxx>
+#include <cellfrm.hxx>
+#include <pagefrm.hxx>
+#include <tabcol.hxx>
+#include <doc.hxx>
+#include <IDocumentUndoRedo.hxx>
+#include <UndoManager.hxx>
+#include <cntfrm.hxx>
+#include <pam.hxx>
+#include <swcrsr.hxx>
+#include <viscrs.hxx>
+#include <swtable.hxx>
+#include <swundo.hxx>
+#include <tblsel.hxx>
+#include <fldbas.hxx>
+#include <poolfmt.hxx>
+#include <tabfrm.hxx>
+#include <UndoCore.hxx>
+#include <UndoRedline.hxx>
+#include <UndoDelete.hxx>
+#include <UndoNumbering.hxx>
+#include <UndoTable.hxx>
+#include <hints.hxx>
+#include <tblafmt.hxx>
+#include <swcache.hxx>
+#include <ddefld.hxx>
+#include <frminf.hxx>
+#include <cellatr.hxx>
+#include <swtblfmt.hxx>
+#include <swddetbl.hxx>
+#include <mvsave.hxx>
+#include <docary.hxx>
+#include <redline.hxx>
+#include <rolbck.hxx>
+#include <tblrwcl.hxx>
+#include <editsh.hxx>
+#include <txtfrm.hxx>
+#include <ftnfrm.hxx>
+#include <section.hxx>
+#include <frmtool.hxx>
+#include <node2lay.hxx>
+#include <comcore.hrc>
+#include "docsh.hxx"
+#include <unochart.hxx>
+#include <node.hxx>
+#include <ndtxt.hxx>
+#include <map>
+#include <algorithm>
+#include <rootfrm.hxx>
+#include <fldupde.hxx>
+#include <switerator.hxx>
+#if OSL_DEBUG_LEVEL > 1
+#define CHECK_TABLE(t) (t).CheckConsistency();
+#else
+#define CHECK_TABLE(t)
+#endif
+
+using ::editeng::SvxBorderLine;
+using namespace ::com::sun::star;
+
+const sal_Unicode T2T_PARA = 0x0a;
+
+extern void ClearFEShellTabCols();
+
+// steht im gctable.cxx
+extern sal_Bool lcl_GC_Line_Border( const SwTableLine*& , void* pPara );
+
+void lcl_SetDfltBoxAttr( SwFrmFmt& rFmt, sal_uInt8 nId )
+{
+ sal_Bool bTop = sal_False, bBottom = sal_False, bLeft = sal_False, bRight = sal_False;
+ switch ( nId )
+ {
+ case 0: bTop = bBottom = bLeft = sal_True; break;
+ case 1: bTop = bBottom = bLeft = bRight = sal_True; break;
+ case 2: bBottom = bLeft = sal_True; break;
+ case 3: bBottom = bLeft = bRight = sal_True; break;
+ }
+
+ const sal_Bool bHTML = rFmt.getIDocumentSettingAccess()->get(IDocumentSettingAccess::HTML_MODE);
+ Color aCol( bHTML ? COL_GRAY : COL_BLACK );
+ SvxBorderLine aLine( &aCol, DEF_LINE_WIDTH_0 );
+ if ( bHTML )
+ {
+ aLine.SetStyle( editeng::DOUBLE );
+ aLine.SetWidth( DEF_LINE_WIDTH_0 );
+ }
+ SvxBoxItem aBox(RES_BOX); aBox.SetDistance( 55 );
+ if ( bTop )
+ aBox.SetLine( &aLine, BOX_LINE_TOP );
+ if ( bBottom )
+ aBox.SetLine( &aLine, BOX_LINE_BOTTOM );
+ if ( bLeft )
+ aBox.SetLine( &aLine, BOX_LINE_LEFT );
+ if ( bRight )
+ aBox.SetLine( &aLine, BOX_LINE_RIGHT );
+ rFmt.SetFmtAttr( aBox );
+}
+
+void lcl_SetDfltBoxAttr( SwTableBox& rBox, SvPtrarr &rBoxFmtArr, sal_uInt8 nId,
+ const SwTableAutoFmt* pAutoFmt = 0 )
+{
+ SvPtrarr* pArr = (SvPtrarr*)rBoxFmtArr[ nId ];
+ if( !pArr )
+ {
+ pArr = new SvPtrarr;
+ rBoxFmtArr.Replace( pArr, nId );
+ }
+
+ SwTableBoxFmt* pNewBoxFmt = 0;
+ SwFrmFmt* pBoxFmt = rBox.GetFrmFmt();
+ for( sal_uInt16 n = 0; n < pArr->Count(); n += 2 )
+ if( pArr->GetObject( n ) == pBoxFmt )
+ {
+ pNewBoxFmt = (SwTableBoxFmt*)pArr->GetObject( n + 1 );
+ break;
+ }
+
+ if( !pNewBoxFmt )
+ {
+ SwDoc* pDoc = pBoxFmt->GetDoc();
+ // das Format ist also nicht vorhanden, also neu erzeugen
+ pNewBoxFmt = pDoc->MakeTableBoxFmt();
+ pNewBoxFmt->SetFmtAttr( pBoxFmt->GetAttrSet().Get( RES_FRM_SIZE ) );
+
+ if( pAutoFmt )
+ pAutoFmt->UpdateToSet( nId, (SfxItemSet&)pNewBoxFmt->GetAttrSet(),
+ SwTableAutoFmt::UPDATE_BOX,
+ pDoc->GetNumberFormatter( sal_True ) );
+ else
+ ::lcl_SetDfltBoxAttr( *pNewBoxFmt, nId );
+
+ void* p = pBoxFmt;
+ pArr->Insert( p, pArr->Count() );
+ p = pNewBoxFmt;
+ pArr->Insert( p, pArr->Count() );
+ }
+ rBox.ChgFrmFmt( pNewBoxFmt );
+}
+
+SwTableBoxFmt *lcl_CreateDfltBoxFmt( SwDoc &rDoc, SvPtrarr &rBoxFmtArr,
+ sal_uInt16 nCols, sal_uInt8 nId )
+{
+ if ( !rBoxFmtArr[nId] )
+ {
+ SwTableBoxFmt* pBoxFmt = rDoc.MakeTableBoxFmt();
+ if( USHRT_MAX != nCols )
+ pBoxFmt->SetFmtAttr( SwFmtFrmSize( ATT_VAR_SIZE,
+ USHRT_MAX / nCols, 0 ));
+ ::lcl_SetDfltBoxAttr( *pBoxFmt, nId );
+ rBoxFmtArr.Replace( pBoxFmt, nId );
+ }
+ return (SwTableBoxFmt*)rBoxFmtArr[nId];
+}
+
+SwTableBoxFmt *lcl_CreateAFmtBoxFmt( SwDoc &rDoc, SvPtrarr &rBoxFmtArr,
+ const SwTableAutoFmt& rAutoFmt,
+ sal_uInt16 nCols, sal_uInt8 nId )
+{
+ if( !rBoxFmtArr[nId] )
+ {
+ SwTableBoxFmt* pBoxFmt = rDoc.MakeTableBoxFmt();
+ rAutoFmt.UpdateToSet( nId, (SfxItemSet&)pBoxFmt->GetAttrSet(),
+ SwTableAutoFmt::UPDATE_BOX,
+ rDoc.GetNumberFormatter( sal_True ) );
+ if( USHRT_MAX != nCols )
+ pBoxFmt->SetFmtAttr( SwFmtFrmSize( ATT_VAR_SIZE,
+ USHRT_MAX / nCols, 0 ));
+ rBoxFmtArr.Replace( pBoxFmt, nId );
+ }
+ return (SwTableBoxFmt*)rBoxFmtArr[nId];
+}
+
+SwTableNode* SwDoc::IsIdxInTbl(const SwNodeIndex& rIdx)
+{
+ SwTableNode* pTableNd = 0;
+ sal_uLong nIndex = rIdx.GetIndex();
+ do {
+ SwNode* pNd = (SwNode*)GetNodes()[ nIndex ]->StartOfSectionNode();
+ if( 0 != ( pTableNd = pNd->GetTableNode() ) )
+ break;
+
+ nIndex = pNd->GetIndex();
+ } while ( nIndex );
+ return pTableNd;
+}
+
+
+// --------------- einfuegen einer neuen Box --------------
+
+ // fuege in der Line, vor der InsPos eine neue Box ein.
+
+sal_Bool SwNodes::InsBoxen( SwTableNode* pTblNd,
+ SwTableLine* pLine,
+ SwTableBoxFmt* pBoxFmt,
+ SwTxtFmtColl* pTxtColl,
+ const SfxItemSet* pAutoAttr,
+ sal_uInt16 nInsPos,
+ sal_uInt16 nCnt )
+{
+ if( !nCnt )
+ return sal_False;
+ OSL_ENSURE( pLine, "keine gueltige Zeile" );
+
+ // Index hinter die letzte Box der Line
+ sal_uLong nIdxPos = 0;
+ SwTableBox *pPrvBox = 0, *pNxtBox = 0;
+ if( pLine->GetTabBoxes().Count() )
+ {
+ if( nInsPos < pLine->GetTabBoxes().Count() )
+ {
+ if( 0 == (pPrvBox = pLine->FindPreviousBox( pTblNd->GetTable(),
+ pLine->GetTabBoxes()[ nInsPos ] )))
+ pPrvBox = pLine->FindPreviousBox( pTblNd->GetTable() );
+ }
+ else
+ {
+ if( 0 == (pNxtBox = pLine->FindNextBox( pTblNd->GetTable(),
+ pLine->GetTabBoxes()[ pLine->GetTabBoxes().Count()-1 ] )))
+ pNxtBox = pLine->FindNextBox( pTblNd->GetTable() );
+ }
+ }
+ else if( 0 == ( pNxtBox = pLine->FindNextBox( pTblNd->GetTable() )))
+ pPrvBox = pLine->FindPreviousBox( pTblNd->GetTable() );
+
+ if( !pPrvBox && !pNxtBox )
+ {
+ sal_Bool bSetIdxPos = sal_True;
+ if( pTblNd->GetTable().GetTabLines().Count() && !nInsPos )
+ {
+ const SwTableLine* pTblLn = pLine;
+ while( pTblLn->GetUpper() )
+ pTblLn = pTblLn->GetUpper()->GetUpper();
+
+ if( pTblNd->GetTable().GetTabLines()[ 0 ] == pTblLn )
+ {
+ // also vor die erste Box der Tabelle
+ while( ( pNxtBox = pLine->GetTabBoxes()[0])->GetTabLines().Count() )
+ pLine = pNxtBox->GetTabLines()[0];
+ nIdxPos = pNxtBox->GetSttIdx();
+ bSetIdxPos = sal_False;
+ }
+ }
+ if( bSetIdxPos )
+ // Tabelle ohne irgendeinen Inhalt oder am Ende, also vors Ende
+ nIdxPos = pTblNd->EndOfSectionIndex();
+ }
+ else if( pNxtBox ) // es gibt einen Nachfolger
+ nIdxPos = pNxtBox->GetSttIdx();
+ else // es gibt einen Vorgaenger
+ nIdxPos = pPrvBox->GetSttNd()->EndOfSectionIndex() + 1;
+
+ SwNodeIndex aEndIdx( *this, nIdxPos );
+ for( sal_uInt16 n = 0; n < nCnt; ++n )
+ {
+ SwStartNode* pSttNd = new SwStartNode( aEndIdx, ND_STARTNODE,
+ SwTableBoxStartNode );
+ pSttNd->pStartOfSection = pTblNd;
+ new SwEndNode( aEndIdx, *pSttNd );
+
+ pPrvBox = new SwTableBox( pBoxFmt, *pSttNd, pLine );
+
+ SwTableBoxes & rTabBoxes = pLine->GetTabBoxes();
+ sal_uInt16 nRealInsPos = nInsPos + n;
+ if (nRealInsPos > rTabBoxes.Count())
+ nRealInsPos = rTabBoxes.Count();
+
+ rTabBoxes.C40_INSERT( SwTableBox, pPrvBox, nRealInsPos );
+
+ if( ! pTxtColl->IsAssignedToListLevelOfOutlineStyle()//<-end,zhaojianwei
+//FEATURE::CONDCOLL
+ && RES_CONDTXTFMTCOLL != pTxtColl->Which()
+//FEATURE::CONDCOLL
+ )
+ new SwTxtNode( SwNodeIndex( *pSttNd->EndOfSectionNode() ),
+ pTxtColl, pAutoAttr );
+ else
+ {
+ // Outline-Numerierung richtig behandeln !!!
+ SwTxtNode* pTNd = new SwTxtNode(
+ SwNodeIndex( *pSttNd->EndOfSectionNode() ),
+ (SwTxtFmtColl*)GetDoc()->GetDfltTxtFmtColl(),
+ pAutoAttr );
+ pTNd->ChgFmtColl( pTxtColl );
+ }
+ }
+ return sal_True;
+}
+
+// --------------- einfuegen einer neuen Tabelle --------------
+
+const SwTable* SwDoc::InsertTable( const SwInsertTableOptions& rInsTblOpts,
+ const SwPosition& rPos, sal_uInt16 nRows,
+ sal_uInt16 nCols, sal_Int16 eAdjust,
+ const SwTableAutoFmt* pTAFmt,
+ const SvUShorts* pColArr,
+ sal_Bool bCalledFromShell,
+ sal_Bool bNewModel )
+{
+ OSL_ENSURE( nRows, "Tabelle ohne Zeile?" );
+ OSL_ENSURE( nCols, "Tabelle ohne Spalten?" );
+
+ {
+ // nicht in Fussnoten kopieren !!
+ if( rPos.nNode < GetNodes().GetEndOfInserts().GetIndex() &&
+ rPos.nNode >= GetNodes().GetEndOfInserts().StartOfSectionIndex() )
+ return 0;
+
+ // sollte das ColumnArray die falsche Anzahl haben wird es ignoriert!
+ if( pColArr &&
+ (nCols + ( text::HoriOrientation::NONE == eAdjust ? 2 : 1 )) != pColArr->Count() )
+ pColArr = 0;
+ }
+
+ String aTblName = GetUniqueTblName();
+
+ if( GetIDocumentUndoRedo().DoesUndo() )
+ {
+ GetIDocumentUndoRedo().AppendUndo(
+ new SwUndoInsTbl( rPos, nCols, nRows, static_cast<sal_uInt16>(eAdjust),
+ rInsTblOpts, pTAFmt, pColArr,
+ aTblName));
+ }
+
+ // fuege erstmal die Nodes ein
+ // hole das Auto-Format fuer die Tabelle
+ SwTxtFmtColl *pBodyColl = GetTxtCollFromPool( RES_POOLCOLL_TABLE ),
+ *pHeadColl = pBodyColl;
+
+ sal_Bool bDfltBorders = 0 != ( rInsTblOpts.mnInsMode & tabopts::DEFAULT_BORDER );
+
+ if( (rInsTblOpts.mnInsMode & tabopts::HEADLINE) && (1 != nRows || !bDfltBorders) )
+ pHeadColl = GetTxtCollFromPool( RES_POOLCOLL_TABLE_HDLN );
+
+ const sal_uInt16 nRowsToRepeat =
+ tabopts::HEADLINE == (rInsTblOpts.mnInsMode & tabopts::HEADLINE) ?
+ rInsTblOpts.mnRowsToRepeat :
+ 0;
+
+ /* Save content node to extract FRAMEDIR from. */
+ const SwCntntNode * pCntntNd = rPos.nNode.GetNode().GetCntntNode();
+
+ /* If we are called from a shell pass the attrset from
+ pCntntNd (aka the node the table is inserted at) thus causing
+ SwNodes::InsertTable to propagate an adjust item if
+ necessary. */
+ SwTableNode *pTblNd = GetNodes().InsertTable(
+ rPos.nNode,
+ nCols,
+ pBodyColl,
+ nRows,
+ nRowsToRepeat,
+ pHeadColl,
+ bCalledFromShell ? &pCntntNd->GetSwAttrSet() : 0 );
+
+ // dann erstelle die Box/Line/Table-Struktur
+ SwTableLineFmt* pLineFmt = MakeTableLineFmt();
+ SwTableFmt* pTableFmt = MakeTblFrmFmt( aTblName, GetDfltFrmFmt() );
+
+ /* If the node to insert the table at is a context node and has a
+ non-default FRAMEDIR propagate it to the table. */
+ if (pCntntNd)
+ {
+ const SwAttrSet & aNdSet = pCntntNd->GetSwAttrSet();
+ const SfxPoolItem *pItem = NULL;
+
+ if (SFX_ITEM_SET == aNdSet.GetItemState( RES_FRAMEDIR, sal_True, &pItem )
+ && pItem != NULL)
+ {
+ pTableFmt->SetFmtAttr( *pItem );
+ }
+ }
+
+ //Orientation am Fmt der Table setzen
+ pTableFmt->SetFmtAttr( SwFmtHoriOrient( 0, eAdjust ) );
+ // alle Zeilen haben die Fill-Order von links nach rechts !
+ pLineFmt->SetFmtAttr( SwFmtFillOrder( ATT_LEFT_TO_RIGHT ));
+
+ // die Tabelle bekommt USHRT_MAX als default SSize
+ SwTwips nWidth = USHRT_MAX;
+ if( pColArr )
+ {
+ sal_uInt16 nSttPos = (*pColArr)[ 0 ];
+ sal_uInt16 nLastPos = (*pColArr)[ sal_uInt16(pColArr->Count()-1)];
+ if( text::HoriOrientation::NONE == eAdjust )
+ {
+ sal_uInt16 nFrmWidth = nLastPos;
+ nLastPos = (*pColArr)[ sal_uInt16(pColArr->Count()-2)];
+ pTableFmt->SetFmtAttr( SvxLRSpaceItem( nSttPos, nFrmWidth - nLastPos, 0, 0, RES_LR_SPACE ) );
+ }
+ nWidth = nLastPos - nSttPos;
+ }
+ else if( nCols )
+ {
+ nWidth /= nCols;
+ nWidth *= nCols; // to avoid rounding problems
+ }
+ pTableFmt->SetFmtAttr( SwFmtFrmSize( ATT_VAR_SIZE, nWidth ));
+ if( !(rInsTblOpts.mnInsMode & tabopts::SPLIT_LAYOUT) )
+ pTableFmt->SetFmtAttr( SwFmtLayoutSplit( sal_False ));
+
+ // verschiebe ggfs. die harten PageDesc/PageBreak Attribute:
+ SwCntntNode* pNextNd = GetNodes()[ pTblNd->EndOfSectionIndex()+1 ]
+ ->GetCntntNode();
+ if( pNextNd && pNextNd->HasSwAttrSet() )
+ {
+ const SfxItemSet* pNdSet = pNextNd->GetpSwAttrSet();
+ const SfxPoolItem *pItem;
+ if( SFX_ITEM_SET == pNdSet->GetItemState( RES_PAGEDESC, sal_False,
+ &pItem ) )
+ {
+ pTableFmt->SetFmtAttr( *pItem );
+ pNextNd->ResetAttr( RES_PAGEDESC );
+ pNdSet = pNextNd->GetpSwAttrSet();
+ }
+ if( pNdSet && SFX_ITEM_SET == pNdSet->GetItemState( RES_BREAK, sal_False,
+ &pItem ) )
+ {
+ pTableFmt->SetFmtAttr( *pItem );
+ pNextNd->ResetAttr( RES_BREAK );
+ }
+ }
+
+ SwTable * pNdTbl = &pTblNd->GetTable();
+ pNdTbl->RegisterToFormat( *pTableFmt );
+
+ pNdTbl->SetRowsToRepeat( nRowsToRepeat );
+ pNdTbl->SetTableModel( bNewModel );
+
+ SvPtrarr aBoxFmtArr( 0, 16 );
+ SwTableBoxFmt* pBoxFmt = 0;
+ if( !bDfltBorders && !pTAFmt )
+ {
+ pBoxFmt = MakeTableBoxFmt();
+ pBoxFmt->SetFmtAttr( SwFmtFrmSize( ATT_VAR_SIZE, USHRT_MAX / nCols, 0 ));
+ }
+ else
+ {
+ const sal_uInt16 nBoxArrLen = pTAFmt ? 16 : 4;
+ for( sal_uInt16 i = 0; i < nBoxArrLen; ++i )
+ aBoxFmtArr.Insert( (void*)0, i );
+ }
+ SfxItemSet aCharSet( GetAttrPool(), RES_CHRATR_BEGIN, RES_PARATR_LIST_END-1 );
+
+ SwNodeIndex aNdIdx( *pTblNd, 1 ); // auf den ersten Box-StartNode
+ SwTableLines& rLines = pNdTbl->GetTabLines();
+ for( sal_uInt16 n = 0; n < nRows; ++n )
+ {
+ SwTableLine* pLine = new SwTableLine( pLineFmt, nCols, 0 );
+ rLines.C40_INSERT( SwTableLine, pLine, n );
+ SwTableBoxes& rBoxes = pLine->GetTabBoxes();
+ for( sal_uInt16 i = 0; i < nCols; ++i )
+ {
+ SwTableBoxFmt *pBoxF;
+ if( pTAFmt )
+ {
+ sal_uInt8 nId = static_cast<sal_uInt8>(!n ? 0 : (( n+1 == nRows )
+ ? 12 : (4 * (1 + ((n-1) & 1 )))));
+ nId = nId + static_cast<sal_uInt8>( !i ? 0 :
+ ( i+1 == nCols ? 3 : (1 + ((i-1) & 1))));
+ pBoxF = ::lcl_CreateAFmtBoxFmt( *this, aBoxFmtArr, *pTAFmt,
+ nCols, nId );
+
+ // ggfs. noch die Absatz/ZeichenAttribute setzen
+ if( pTAFmt->IsFont() || pTAFmt->IsJustify() )
+ {
+ aCharSet.ClearItem();
+ pTAFmt->UpdateToSet( nId, aCharSet,
+ SwTableAutoFmt::UPDATE_CHAR, 0 );
+ if( aCharSet.Count() )
+ GetNodes()[ aNdIdx.GetIndex()+1 ]->GetCntntNode()->
+ SetAttr( aCharSet );
+ }
+ }
+ else if( bDfltBorders )
+ {
+ sal_uInt8 nBoxId = (i < nCols - 1 ? 0 : 1) + (n ? 2 : 0 );
+ pBoxF = ::lcl_CreateDfltBoxFmt( *this, aBoxFmtArr, nCols, nBoxId);
+ }
+ else
+ pBoxF = pBoxFmt;
+
+ // fuer AutoFormat bei der Eingabe: beim Einfuegen der Tabelle
+ // werden gleich die Spalten gesetzt. Im Array stehen die
+ // Positionen der Spalten!! (nicht deren Breite!)
+ if( pColArr )
+ {
+ nWidth = (*pColArr)[ sal_uInt16(i + 1) ] - (*pColArr)[ i ];
+ if( pBoxF->GetFrmSize().GetWidth() != nWidth )
+ {
+ if( pBoxF->GetDepends() ) // neues Format erzeugen!
+ {
+ SwTableBoxFmt *pNewFmt = MakeTableBoxFmt();
+ *pNewFmt = *pBoxF;
+ pBoxF = pNewFmt;
+ }
+ pBoxF->SetFmtAttr( SwFmtFrmSize( ATT_VAR_SIZE, nWidth ));
+ }
+ }
+
+ SwTableBox *pBox = new SwTableBox( pBoxF, aNdIdx, pLine);
+ rBoxes.C40_INSERT( SwTableBox, pBox, i );
+ aNdIdx += 3; // StartNode, TextNode, EndNode == 3 Nodes
+ }
+ }
+ // und Frms einfuegen.
+ GetNodes().GoNext( &aNdIdx ); // zum naechsten ContentNode
+ pTblNd->MakeFrms( &aNdIdx );
+
+ if( IsRedlineOn() || (!IsIgnoreRedline() && pRedlineTbl->Count() ))
+ {
+ SwPaM aPam( *pTblNd->EndOfSectionNode(), *pTblNd, 1 );
+ if( IsRedlineOn() )
+ AppendRedline( new SwRedline( nsRedlineType_t::REDLINE_INSERT, aPam ), true);
+ else
+ SplitRedline( aPam );
+ }
+
+ SetModified();
+ CHECK_TABLE( *pNdTbl );
+ return pNdTbl;
+}
+
+SwTableNode* SwNodes::InsertTable( const SwNodeIndex& rNdIdx,
+ sal_uInt16 nBoxes,
+ SwTxtFmtColl* pCntntTxtColl,
+ sal_uInt16 nLines,
+ sal_uInt16 nRepeat,
+ SwTxtFmtColl* pHeadlineTxtColl,
+ const SwAttrSet * pAttrSet)
+{
+ if( !nBoxes )
+ return 0;
+
+ // wenn Lines angegeben, erzeuge die Matrix aus Lines & Boxen
+ if( !pHeadlineTxtColl || !nLines )
+ pHeadlineTxtColl = pCntntTxtColl;
+
+ SwTableNode * pTblNd = new SwTableNode( rNdIdx );
+ SwEndNode* pEndNd = new SwEndNode( rNdIdx, *pTblNd );
+
+ if( !nLines ) // fuer die FOR-Schleife
+ ++nLines;
+
+ SwNodeIndex aIdx( *pEndNd );
+ SwTxtFmtColl* pTxtColl = pHeadlineTxtColl;
+ for( sal_uInt16 nL = 0; nL < nLines; ++nL )
+ {
+ for( sal_uInt16 nB = 0; nB < nBoxes; ++nB )
+ {
+ SwStartNode* pSttNd = new SwStartNode( aIdx, ND_STARTNODE,
+ SwTableBoxStartNode );
+ pSttNd->pStartOfSection = pTblNd;
+
+ SwTxtNode * pTmpNd = new SwTxtNode( aIdx, pTxtColl );
+
+ // --> FME 2006-04-13 #i60422# Propagate some more attributes.
+ const SfxPoolItem* pItem = NULL;
+ if ( NULL != pAttrSet )
+ {
+ static const sal_uInt16 aPropagateItems[] = {
+ RES_PARATR_ADJUST,
+ RES_CHRATR_FONT, RES_CHRATR_FONTSIZE,
+ RES_CHRATR_CJK_FONT, RES_CHRATR_CJK_FONTSIZE,
+ RES_CHRATR_CTL_FONT, RES_CHRATR_CTL_FONTSIZE, 0 };
+
+ const sal_uInt16* pIdx = aPropagateItems;
+ while ( *pIdx != 0 )
+ {
+ if ( SFX_ITEM_SET != pTmpNd->GetSwAttrSet().GetItemState( *pIdx ) &&
+ SFX_ITEM_SET == pAttrSet->GetItemState( *pIdx, sal_True, &pItem ) )
+ static_cast<SwCntntNode *>(pTmpNd)->SetAttr(*pItem);
+ ++pIdx;
+ }
+ }
+ // <--
+
+ new SwEndNode( aIdx, *pSttNd );
+ }
+ if ( nL + 1 >= nRepeat )
+ pTxtColl = pCntntTxtColl;
+ }
+ return pTblNd;
+}
+
+
+//---------------- Text -> Tabelle -----------------------
+
+const SwTable* SwDoc::TextToTable( const SwInsertTableOptions& rInsTblOpts,
+ const SwPaM& rRange, sal_Unicode cCh,
+ sal_Int16 eAdjust,
+ const SwTableAutoFmt* pTAFmt )
+{
+ // pruefe ob in der Selection eine Tabelle liegt
+ const SwPosition *pStt = rRange.Start(), *pEnd = rRange.End();
+ {
+ sal_uLong nCnt = pStt->nNode.GetIndex();
+ for( ; nCnt <= pEnd->nNode.GetIndex(); ++nCnt )
+ if( !GetNodes()[ nCnt ]->IsTxtNode() )
+ return 0;
+ }
+
+ /* Save first node in the selection if it is a context node. */
+ SwCntntNode * pSttCntntNd = pStt->nNode.GetNode().GetCntntNode();
+
+ SwPaM aOriginal( *pStt, *pEnd );
+ pStt = aOriginal.GetMark();
+ pEnd = aOriginal.GetPoint();
+
+ SwUndoTxtToTbl* pUndo = 0;
+ if( GetIDocumentUndoRedo().DoesUndo() )
+ {
+ GetIDocumentUndoRedo().StartUndo( UNDO_TEXTTOTABLE, NULL );
+ pUndo = new SwUndoTxtToTbl( aOriginal, rInsTblOpts, cCh,
+ static_cast<sal_uInt16>(eAdjust), pTAFmt );
+ GetIDocumentUndoRedo().AppendUndo( pUndo );
+
+ // das Splitten vom TextNode nicht in die Undohistory aufnehmen
+ GetIDocumentUndoRedo().DoUndo( false );
+ }
+
+ ::PaMCorrAbs( aOriginal, *pEnd );
+
+ // sorge dafuer, das der Bereich auf Node-Grenzen liegt
+ SwNodeRange aRg( pStt->nNode, pEnd->nNode );
+ if( pStt->nContent.GetIndex() )
+ SplitNode( *pStt, false );
+
+ sal_Bool bEndCntnt = 0 != pEnd->nContent.GetIndex();
+ // nicht splitten am Ende der Zeile (aber am Ende vom Doc!!)
+ if( bEndCntnt )
+ {
+ if( pEnd->nNode.GetNode().GetCntntNode()->Len() != pEnd->nContent.GetIndex()
+ || pEnd->nNode.GetIndex() >= GetNodes().GetEndOfContent().GetIndex()-1 )
+ {
+ SplitNode( *pEnd, false );
+ ((SwNodeIndex&)pEnd->nNode)--;
+ ((SwIndex&)pEnd->nContent).Assign(
+ pEnd->nNode.GetNode().GetCntntNode(), 0 );
+ // ein Node und am Ende ??
+ if( pStt->nNode.GetIndex() >= pEnd->nNode.GetIndex() )
+ aRg.aStart--;
+ }
+ else
+ aRg.aEnd++;
+ }
+
+
+ if( aRg.aEnd.GetIndex() == aRg.aStart.GetIndex() )
+ {
+ OSL_FAIL( "Kein Bereich" );
+ aRg.aEnd++;
+ }
+
+ // Wir gehen jetzt immer ueber die Upper, um die Tabelle einzufuegen:
+ SwNode2Layout aNode2Layout( aRg.aStart.GetNode() );
+
+ GetIDocumentUndoRedo().DoUndo( 0 != pUndo );
+
+ // dann erstelle die Box/Line/Table-Struktur
+ SwTableBoxFmt* pBoxFmt = MakeTableBoxFmt();
+ SwTableLineFmt* pLineFmt = MakeTableLineFmt();
+ SwTableFmt* pTableFmt = MakeTblFrmFmt( GetUniqueTblName(), GetDfltFrmFmt() );
+
+ // alle Zeilen haben die Fill-Order von links nach rechts !
+ pLineFmt->SetFmtAttr( SwFmtFillOrder( ATT_LEFT_TO_RIGHT ));
+ // die Tabelle bekommt USHRT_MAX als default SSize
+ pTableFmt->SetFmtAttr( SwFmtFrmSize( ATT_VAR_SIZE, USHRT_MAX ));
+ if( !(rInsTblOpts.mnInsMode & tabopts::SPLIT_LAYOUT) )
+ pTableFmt->SetFmtAttr( SwFmtLayoutSplit( sal_False ));
+
+ /* If the first node in the selection is a context node and if it
+ has an item FRAMEDIR set (no default) propagate the item to the
+ replacing table. */
+ if (pSttCntntNd)
+ {
+ const SwAttrSet & aNdSet = pSttCntntNd->GetSwAttrSet();
+ const SfxPoolItem *pItem = NULL;
+
+ if (SFX_ITEM_SET == aNdSet.GetItemState( RES_FRAMEDIR, sal_True, &pItem )
+ && pItem != NULL)
+ {
+ pTableFmt->SetFmtAttr( *pItem );
+ }
+ }
+
+ SwTableNode* pTblNd = GetNodes().TextToTable(
+ aRg, cCh, pTableFmt, pLineFmt, pBoxFmt,
+ GetTxtCollFromPool( RES_POOLCOLL_STANDARD ), pUndo );
+
+ SwTable * pNdTbl = &pTblNd->GetTable();
+ OSL_ENSURE( pNdTbl, "kein Tabellen-Node angelegt." );
+
+ const sal_uInt16 nRowsToRepeat =
+ tabopts::HEADLINE == (rInsTblOpts.mnInsMode & tabopts::HEADLINE) ?
+ rInsTblOpts.mnRowsToRepeat :
+ 0;
+ pNdTbl->SetRowsToRepeat( nRowsToRepeat );
+
+ sal_Bool bUseBoxFmt = sal_False;
+ if( !pBoxFmt->GetDepends() )
+ {
+ // die Formate an den Boxen haben schon die richtige Size, es darf
+ // also nur noch die richtige Umrandung/AutoFmt gesetzt werden.
+ bUseBoxFmt = sal_True;
+ pTableFmt->SetFmtAttr( pBoxFmt->GetFrmSize() );
+ delete pBoxFmt;
+ eAdjust = text::HoriOrientation::NONE;
+ }
+
+ //Orientation am Fmt der Table setzen
+ pTableFmt->SetFmtAttr( SwFmtHoriOrient( 0, eAdjust ) );
+ pNdTbl->RegisterToFormat( *pTableFmt );
+
+ if( pTAFmt || ( rInsTblOpts.mnInsMode & tabopts::DEFAULT_BORDER) )
+ {
+ sal_uInt8 nBoxArrLen = pTAFmt ? 16 : 4;
+ SvPtrarr aBoxFmtArr( nBoxArrLen, 0 );
+ {
+ for( sal_uInt8 i = 0; i < nBoxArrLen; ++i )
+ aBoxFmtArr.Insert( (void*)0, i );
+ }
+
+ SfxItemSet aCharSet( GetAttrPool(), RES_CHRATR_BEGIN, RES_PARATR_LIST_END-1 );
+
+ SwHistory* pHistory = pUndo ? &pUndo->GetHistory() : 0;
+
+ SwTableBoxFmt *pBoxF = 0;
+ SwTableLines& rLines = pNdTbl->GetTabLines();
+ sal_uInt16 nRows = rLines.Count();
+ for( sal_uInt16 n = 0; n < nRows; ++n )
+ {
+ SwTableBoxes& rBoxes = rLines[ n ]->GetTabBoxes();
+ sal_uInt16 nCols = rBoxes.Count();
+ for( sal_uInt16 i = 0; i < nCols; ++i )
+ {
+ SwTableBox* pBox = rBoxes[ i ];
+ sal_Bool bChgSz = sal_False;
+
+ if( pTAFmt )
+ {
+ sal_uInt8 nId = static_cast<sal_uInt8>(!n ? 0 : (( n+1 == nRows )
+ ? 12 : (4 * (1 + ((n-1) & 1 )))));
+ nId = nId + static_cast<sal_uInt8>(!i ? 0 :
+ ( i+1 == nCols ? 3 : (1 + ((i-1) & 1))));
+ if( bUseBoxFmt )
+ ::lcl_SetDfltBoxAttr( *pBox, aBoxFmtArr, nId, pTAFmt );
+ else
+ {
+ bChgSz = 0 == aBoxFmtArr[ nId ];
+ pBoxF = ::lcl_CreateAFmtBoxFmt( *this, aBoxFmtArr,
+ *pTAFmt, USHRT_MAX, nId );
+ }
+
+ // ggfs. noch die Absatz/ZeichenAttribute setzen
+ if( pTAFmt->IsFont() || pTAFmt->IsJustify() )
+ {
+ aCharSet.ClearItem();
+ pTAFmt->UpdateToSet( nId, aCharSet,
+ SwTableAutoFmt::UPDATE_CHAR, 0 );
+ if( aCharSet.Count() )
+ {
+ sal_uLong nSttNd = pBox->GetSttIdx()+1;
+ sal_uLong nEndNd = pBox->GetSttNd()->EndOfSectionIndex();
+ for( ; nSttNd < nEndNd; ++nSttNd )
+ {
+ SwCntntNode* pNd = GetNodes()[ nSttNd ]->GetCntntNode();
+ if( pNd )
+ {
+ if( pHistory )
+ {
+ SwRegHistory aReg( pNd, *pNd, pHistory );
+ pNd->SetAttr( aCharSet );
+ }
+ else
+ pNd->SetAttr( aCharSet );
+ }
+ }
+ }
+ }
+ }
+ else
+ {
+ sal_uInt8 nId = (i < nCols - 1 ? 0 : 1) + (n ? 2 : 0 );
+ if( bUseBoxFmt )
+ ::lcl_SetDfltBoxAttr( *pBox, aBoxFmtArr, nId );
+ else
+ {
+ bChgSz = 0 == aBoxFmtArr[ nId ];
+ pBoxF = ::lcl_CreateDfltBoxFmt( *this, aBoxFmtArr,
+ USHRT_MAX, nId );
+ }
+ }
+
+ if( !bUseBoxFmt )
+ {
+ if( bChgSz )
+ pBoxF->SetFmtAttr( pBox->GetFrmFmt()->GetFrmSize() );
+ pBox->ChgFrmFmt( pBoxF );
+ }
+ }
+ }
+
+ if( bUseBoxFmt )
+ {
+ for( sal_uInt8 i = 0; i < nBoxArrLen; ++i )
+ {
+ SvPtrarr* pArr = (SvPtrarr*)aBoxFmtArr[ i ];
+ delete pArr;
+ }
+ }
+ }
+
+ // JP 03.04.97: Inhalt der Boxen auf Zahlen abpruefen
+ if( IsInsTblFormatNum() )
+ {
+ for( sal_uInt16 nBoxes = pNdTbl->GetTabSortBoxes().Count(); nBoxes; )
+ ChkBoxNumFmt( *pNdTbl->GetTabSortBoxes()[ --nBoxes ], sal_False );
+ }
+
+ sal_uLong nIdx = pTblNd->GetIndex();
+ aNode2Layout.RestoreUpperFrms( GetNodes(), nIdx, nIdx + 1 );
+
+ {
+ SwPaM& rTmp = (SwPaM&)rRange; // Point immer an den Anfang
+ rTmp.DeleteMark();
+ rTmp.GetPoint()->nNode = *pTblNd;
+ SwCntntNode* pCNd = GetNodes().GoNext( &rTmp.GetPoint()->nNode );
+ rTmp.GetPoint()->nContent.Assign( pCNd, 0 );
+ }
+
+ if( pUndo )
+ {
+ GetIDocumentUndoRedo().EndUndo( UNDO_TEXTTOTABLE, NULL );
+ }
+
+ SetModified();
+ SetFieldsDirty(true, NULL, 0);
+ return pNdTbl;
+}
+
+SwTableNode* SwNodes::TextToTable( const SwNodeRange& rRange, sal_Unicode cCh,
+ SwTableFmt* pTblFmt,
+ SwTableLineFmt* pLineFmt,
+ SwTableBoxFmt* pBoxFmt,
+ SwTxtFmtColl* pTxtColl,
+ SwUndoTxtToTbl* pUndo )
+{
+ if( rRange.aStart >= rRange.aEnd )
+ return 0;
+
+ SwTableNode * pTblNd = new SwTableNode( rRange.aStart );
+ new SwEndNode( rRange.aEnd, *pTblNd );
+
+ SwDoc* pDoc = GetDoc();
+ SvUShorts aPosArr( 0, 16 );
+ SwTable * pTable = &pTblNd->GetTable();
+ SwTableLine* pLine;
+ SwTableBox* pBox;
+ sal_uInt16 nBoxes, nLines, nMaxBoxes = 0;
+
+ SwNodeIndex aSttIdx( *pTblNd, 1 );
+ SwNodeIndex aEndIdx( rRange.aEnd, -1 );
+ for( nLines = 0, nBoxes = 0;
+ aSttIdx.GetIndex() < aEndIdx.GetIndex();
+ aSttIdx += 2, nLines++, nBoxes = 0 )
+ {
+ SwTxtNode* pTxtNd = aSttIdx.GetNode().GetTxtNode();
+ OSL_ENSURE( pTxtNd, "nur TextNodes in der Tabelle aufnehmen" );
+
+ if( !nLines && 0x0b == cCh )
+ {
+ cCh = 0x09;
+
+ // JP 28.10.96: vom 1. Node die Positionen des Trenners besorgen,
+ // damit die Boxen entsprechend eingestellt werden
+ SwTxtFrmInfo aFInfo( (SwTxtFrm*)pTxtNd->getLayoutFrm( pTxtNd->GetDoc()->GetCurrentLayout() ) );
+ if( aFInfo.IsOneLine() ) // nur dann sinnvoll!
+ {
+ const sal_Unicode* pTxt = pTxtNd->GetTxt().GetBuffer();
+ for( xub_StrLen nChPos = 0; *pTxt; ++nChPos, ++pTxt )
+ {
+ if( *pTxt == cCh )
+ {
+ aPosArr.Insert( static_cast<sal_uInt16>(
+ aFInfo.GetCharPos( nChPos+1, sal_False )),
+ aPosArr.Count() );
+ }
+ }
+
+ aPosArr.Insert(
+ static_cast<sal_uInt16>(aFInfo.GetFrm()->IsVertical() ?
+ aFInfo.GetFrm()->Prt().Bottom() :
+ aFInfo.GetFrm()->Prt().Right()),
+ aPosArr.Count() );
+ }
+ }
+
+ // die alten Frames loeschen, es werden neue erzeugt
+ pTxtNd->DelFrms();
+
+ // PageBreaks/PageDesc/ColBreak rausschmeissen.
+ const SfxItemSet* pSet = pTxtNd->GetpSwAttrSet();
+ if( pSet )
+ {
+ const SfxPoolItem* pItem;
+ if( SFX_ITEM_SET == pSet->GetItemState( RES_BREAK, sal_False, &pItem ) )
+ {
+ if( !nLines )
+ pTblFmt->SetFmtAttr( *pItem );
+ pTxtNd->ResetAttr( RES_BREAK );
+ pSet = pTxtNd->GetpSwAttrSet();
+ }
+
+ if( pSet && SFX_ITEM_SET == pSet->GetItemState(
+ RES_PAGEDESC, sal_False, &pItem ) &&
+ ((SwFmtPageDesc*)pItem)->GetPageDesc() )
+ {
+ if( !nLines )
+ pTblFmt->SetFmtAttr( *pItem );
+ pTxtNd->ResetAttr( RES_PAGEDESC );
+ }
+ }
+
+ // setze den bei allen TextNode in der Tabelle den TableNode
+ // als StartNode
+ pTxtNd->pStartOfSection = pTblNd;
+
+ pLine = new SwTableLine( pLineFmt, 1, 0 );
+ pTable->GetTabLines().C40_INSERT( SwTableLine, pLine, nLines );
+
+ SwStartNode* pSttNd;
+ SwPosition aCntPos( aSttIdx, SwIndex( pTxtNd ));
+
+ SvULongs aBkmkArr( 15, 15 );
+ _SaveCntntIdx( pDoc, aSttIdx.GetIndex(), pTxtNd->GetTxt().Len(), aBkmkArr );
+
+ const sal_Unicode* pTxt = pTxtNd->GetTxt().GetBuffer();
+
+ if( T2T_PARA != cCh )
+ for( xub_StrLen nChPos = 0; *pTxt; ++nChPos, ++pTxt )
+ if( *pTxt == cCh )
+ {
+ aCntPos.nContent = nChPos;
+ SwCntntNode* pNewNd = pTxtNd->SplitCntntNode( aCntPos );
+
+ if( aBkmkArr.Count() )
+ _RestoreCntntIdx( aBkmkArr, *pNewNd, nChPos,
+ nChPos + 1 );
+
+ // Trennzeichen loeschen und SuchString korrigieren
+ pTxtNd->EraseText( aCntPos.nContent, 1 );
+ pTxt = pTxtNd->GetTxt().GetBuffer();
+ nChPos = 0;
+ --nChPos, --pTxt; // for the ++ in the for loop !!!
+
+ // setze bei allen TextNodes in der Tabelle den TableNode
+ // als StartNode
+ const SwNodeIndex aTmpIdx( aCntPos.nNode, -1 );
+ pSttNd = new SwStartNode( aTmpIdx, ND_STARTNODE,
+ SwTableBoxStartNode );
+ new SwEndNode( aCntPos.nNode, *pSttNd );
+ pNewNd->pStartOfSection = pSttNd;
+
+ // Section der Box zuweisen
+ pBox = new SwTableBox( pBoxFmt, *pSttNd, pLine );
+ pLine->GetTabBoxes().C40_INSERT( SwTableBox, pBox, nBoxes++ );
+ }
+
+ // und jetzt den letzten Teil-String
+ if( aBkmkArr.Count() )
+ _RestoreCntntIdx( aBkmkArr, *pTxtNd, pTxtNd->GetTxt().Len(),
+ pTxtNd->GetTxt().Len()+1 );
+
+ pSttNd = new SwStartNode( aCntPos.nNode, ND_STARTNODE, SwTableBoxStartNode );
+ const SwNodeIndex aTmpIdx( aCntPos.nNode, 1 );
+ new SwEndNode( aTmpIdx, *pSttNd );
+ pTxtNd->pStartOfSection = pSttNd;
+
+ pBox = new SwTableBox( pBoxFmt, *pSttNd, pLine );
+ pLine->GetTabBoxes().C40_INSERT( SwTableBox, pBox, nBoxes++ );
+ if( nMaxBoxes < nBoxes )
+ nMaxBoxes = nBoxes;
+ }
+
+ // die Tabelle ausgleichen, leere Sections einfuegen
+ sal_uInt16 n;
+
+ for( n = 0; n < pTable->GetTabLines().Count(); ++n )
+ {
+ SwTableLine* pCurrLine = pTable->GetTabLines()[ n ];
+ if( nMaxBoxes != ( nBoxes = pCurrLine->GetTabBoxes().Count() ))
+ {
+ InsBoxen( pTblNd, pCurrLine, pBoxFmt, pTxtColl, 0,
+ nBoxes, nMaxBoxes - nBoxes );
+
+ if( pUndo )
+ for( sal_uInt16 i = nBoxes; i < nMaxBoxes; ++i )
+ pUndo->AddFillBox( *pCurrLine->GetTabBoxes()[ i ] );
+
+ // fehlen der 1. Line Boxen, dann kann man das Breiten Array
+ // vergessen!
+ if( !n )
+ aPosArr.Remove( 0, aPosArr.Count() );
+ }
+ }
+
+ if( aPosArr.Count() )
+ {
+ SwTableLines& rLns = pTable->GetTabLines();
+ sal_uInt16 nLastPos = 0;
+ for( n = 0; n < aPosArr.Count(); ++n )
+ {
+ SwTableBoxFmt *pNewFmt = pDoc->MakeTableBoxFmt();
+ pNewFmt->SetFmtAttr( SwFmtFrmSize( ATT_VAR_SIZE,
+ aPosArr[ n ] - nLastPos ));
+ for( sal_uInt16 nTmpLine = 0; nTmpLine < rLns.Count(); ++nTmpLine )
+ //JP 24.06.98: hier muss ein Add erfolgen, da das BoxFormat
+ // von der rufenden Methode noch gebraucht wird!
+ pNewFmt->Add( rLns[ nTmpLine ]->GetTabBoxes()[ n ] );
+
+ nLastPos = aPosArr[ n ];
+ }
+
+ // damit die Tabelle die richtige Groesse bekommt, im BoxFormat die
+ // Groesse nach "oben" transportieren.
+ OSL_ENSURE( !pBoxFmt->GetDepends(), "wer ist in dem Format noch angemeldet" );
+ pBoxFmt->SetFmtAttr( SwFmtFrmSize( ATT_VAR_SIZE, nLastPos ));
+ }
+ else
+ pBoxFmt->SetFmtAttr( SwFmtFrmSize( ATT_VAR_SIZE, USHRT_MAX / nMaxBoxes ));
+
+ // das wars doch wohl ??
+ return pTblNd;
+}
+
+const SwTable* SwDoc::TextToTable( const std::vector< std::vector<SwNodeRange> >& rTableNodes )
+{
+ /* Save first node in the selection if it is a content node. */
+ SwCntntNode * pSttCntntNd = rTableNodes.begin()->begin()->aStart.GetNode().GetCntntNode();
+
+ /**debug**/
+#if OSL_DEBUG_LEVEL > 1
+ const SwNodeRange& rStartRange = *rTableNodes.begin()->begin();
+ const SwNodeRange& rEndRange = *rTableNodes.rbegin()->rbegin();
+ (void) rStartRange;
+ (void) rEndRange;
+#endif
+ /**debug**/
+
+ //!!! not necessarily TextNodes !!!
+ SwPaM aOriginal( rTableNodes.begin()->begin()->aStart, rTableNodes.rbegin()->rbegin()->aEnd );
+ const SwPosition *pStt = aOriginal.GetMark();
+ const SwPosition *pEnd = aOriginal.GetPoint();
+
+// SwUndoTxtToTbl* pUndo = 0;
+ bool const bUndo(GetIDocumentUndoRedo().DoesUndo());
+ if (bUndo)
+ {
+ // das Splitten vom TextNode nicht in die Undohistory aufnehmen
+ GetIDocumentUndoRedo().DoUndo(false);
+ }
+
+ ::PaMCorrAbs( aOriginal, *pEnd );
+
+ // sorge dafuer, das der Bereich auf Node-Grenzen liegt
+ SwNodeRange aRg( pStt->nNode, pEnd->nNode );
+ if( pStt->nContent.GetIndex() )
+ SplitNode( *pStt, false );
+
+ sal_Bool bEndCntnt = 0 != pEnd->nContent.GetIndex();
+ // nicht splitten am Ende der Zeile (aber am Ende vom Doc!!)
+ if( bEndCntnt )
+ {
+ if( pEnd->nNode.GetNode().GetCntntNode()->Len() != pEnd->nContent.GetIndex()
+ || pEnd->nNode.GetIndex() >= GetNodes().GetEndOfContent().GetIndex()-1 )
+ {
+ SplitNode( *pEnd, false );
+ ((SwNodeIndex&)pEnd->nNode)--;
+ ((SwIndex&)pEnd->nContent).Assign(
+ pEnd->nNode.GetNode().GetCntntNode(), 0 );
+ // ein Node und am Ende ??
+ if( pStt->nNode.GetIndex() >= pEnd->nNode.GetIndex() )
+ aRg.aStart--;
+ }
+ else
+ aRg.aEnd++;
+ }
+
+
+ if( aRg.aEnd.GetIndex() == aRg.aStart.GetIndex() )
+ {
+ OSL_FAIL( "Kein Bereich" );
+ aRg.aEnd++;
+ }
+
+ // Wir gehen jetzt immer ueber die Upper, um die Tabelle einzufuegen:
+ SwNode2Layout aNode2Layout( aRg.aStart.GetNode() );
+
+ GetIDocumentUndoRedo().DoUndo(bUndo);
+
+ // dann erstelle die Box/Line/Table-Struktur
+ SwTableBoxFmt* pBoxFmt = MakeTableBoxFmt();
+ SwTableLineFmt* pLineFmt = MakeTableLineFmt();
+ SwTableFmt* pTableFmt = MakeTblFrmFmt( GetUniqueTblName(), GetDfltFrmFmt() );
+
+ // alle Zeilen haben die Fill-Order von links nach rechts !
+ pLineFmt->SetFmtAttr( SwFmtFillOrder( ATT_LEFT_TO_RIGHT ));
+ // die Tabelle bekommt USHRT_MAX als default SSize
+ pTableFmt->SetFmtAttr( SwFmtFrmSize( ATT_VAR_SIZE, USHRT_MAX ));
+
+ /* If the first node in the selection is a context node and if it
+ has an item FRAMEDIR set (no default) propagate the item to the
+ replacing table. */
+ if (pSttCntntNd)
+ {
+ const SwAttrSet & aNdSet = pSttCntntNd->GetSwAttrSet();
+ const SfxPoolItem *pItem = NULL;
+
+ if (SFX_ITEM_SET == aNdSet.GetItemState( RES_FRAMEDIR, sal_True, &pItem )
+ && pItem != NULL)
+ {
+ pTableFmt->SetFmtAttr( *pItem );
+ }
+ }
+
+ SwTableNode* pTblNd = GetNodes().TextToTable(
+ rTableNodes, pTableFmt, pLineFmt, pBoxFmt,
+ GetTxtCollFromPool( RES_POOLCOLL_STANDARD )/*, pUndo*/ );
+
+ SwTable * pNdTbl = &pTblNd->GetTable();
+ OSL_ENSURE( pNdTbl, "kein Tabellen-Node angelegt." );
+ pNdTbl->RegisterToFormat( *pTableFmt );
+
+ if( !pBoxFmt->GetDepends() )
+ {
+ // die Formate an den Boxen haben schon die richtige Size, es darf
+ // also nur noch die richtige Umrandung/AutoFmt gesetzt werden.
+ pTableFmt->SetFmtAttr( pBoxFmt->GetFrmSize() );
+ delete pBoxFmt;
+ }
+
+ sal_uLong nIdx = pTblNd->GetIndex();
+ aNode2Layout.RestoreUpperFrms( GetNodes(), nIdx, nIdx + 1 );
+
+ SetModified();
+ SetFieldsDirty( true, NULL, 0 );
+ return pNdTbl;
+}
+
+SwNodeRange * SwNodes::ExpandRangeForTableBox(const SwNodeRange & rRange)
+{
+ SwNodeRange * pResult = NULL;
+ bool bChanged = false;
+
+ SwNodeIndex aNewStart = rRange.aStart;
+ SwNodeIndex aNewEnd = rRange.aEnd;
+
+ SwNodeIndex aEndIndex = rRange.aEnd;
+ SwNodeIndex aIndex = rRange.aStart;
+
+ while (aIndex < aEndIndex)
+ {
+ SwNode& rNode = aIndex.GetNode();
+
+ if (rNode.IsStartNode())
+ {
+ // advance aIndex to the end node of this start node
+ SwNode * pEndNode = rNode.EndOfSectionNode();
+ aIndex = *pEndNode;
+
+ if (aIndex > aNewEnd)
+ {
+ aNewEnd = aIndex;
+ bChanged = true;
+ }
+ }
+ else if (rNode.IsEndNode())
+ {
+ SwNode * pStartNode = rNode.StartOfSectionNode();
+ SwNodeIndex aStartIndex = *pStartNode;
+
+ if (aStartIndex < aNewStart)
+ {
+ aNewStart = aStartIndex;
+ bChanged = true;
+ }
+ }
+
+ if (aIndex < aEndIndex)
+ ++aIndex;
+ }
+
+ SwNode * pNode = &aIndex.GetNode();
+ while (pNode->IsEndNode())
+ {
+ SwNode * pStartNode = pNode->StartOfSectionNode();
+ SwNodeIndex aStartIndex(*pStartNode);
+ aNewStart = aStartIndex;
+ aNewEnd = aIndex;
+ bChanged = true;
+
+ ++aIndex;
+ pNode = &aIndex.GetNode();
+ }
+
+ if (bChanged)
+ pResult = new SwNodeRange(aNewStart, aNewEnd);
+
+ return pResult;
+}
+
+SwTableNode* SwNodes::TextToTable( const SwNodes::TableRanges_t & rTableNodes,
+ SwTableFmt* pTblFmt,
+ SwTableLineFmt* pLineFmt,
+ SwTableBoxFmt* pBoxFmt,
+ SwTxtFmtColl* /*pTxtColl*/ /*, SwUndo... pUndo*/ )
+{
+ if( !rTableNodes.size() )
+ return 0;
+
+ SwTableNode * pTblNd = new SwTableNode( rTableNodes.begin()->begin()->aStart );
+ //insert the end node after the last text node
+ SwNodeIndex aInsertIndex( rTableNodes.rbegin()->rbegin()->aEnd );
+ ++aInsertIndex;
+
+ //!! owner ship will be transferred in c-tor to SwNodes array.
+ //!! Thus no real problem here...
+ new SwEndNode( aInsertIndex, *pTblNd );
+
+#if OSL_DEBUG_LEVEL > 1
+ /**debug**/
+ const SwNodeRange& rStartRange = *rTableNodes.begin()->begin();
+ const SwNodeRange& rEndRange = *rTableNodes.rbegin()->rbegin();
+ (void) rStartRange;
+ (void) rEndRange;
+ /**debug**/
+#endif
+
+ SwDoc* pDoc = GetDoc();
+ SvUShorts aPosArr( 0, 16 );
+ SwTable * pTable = &pTblNd->GetTable();
+ SwTableLine* pLine;
+ SwTableBox* pBox;
+ sal_uInt16 nBoxes, nLines, nMaxBoxes = 0;
+
+ SwNodeIndex aNodeIndex = rTableNodes.begin()->begin()->aStart;
+ // delete frames of all contained content nodes
+ for( nLines = 0; aNodeIndex <= rTableNodes.rbegin()->rbegin()->aEnd; ++aNodeIndex,++nLines )
+ {
+ SwNode& rNode = aNodeIndex.GetNode();
+ if( rNode.IsCntntNode() )
+ {
+ static_cast<SwCntntNode&>(rNode).DelFrms();
+ if(rNode.IsTxtNode())
+ {
+ SwTxtNode& rTxtNode = static_cast<SwTxtNode&>(rNode);
+ // setze den bei allen TextNode in der Tabelle den TableNode
+ // als StartNode
+
+ // remove PageBreaks/PageDesc/ColBreak
+ const SwAttrSet* pSet = rTxtNode.GetpSwAttrSet();
+ if( pSet )
+ {
+ const SfxPoolItem* pItem;
+ if( SFX_ITEM_SET == pSet->GetItemState( RES_BREAK, sal_False, &pItem ) )
+ {
+ if( !nLines )
+ pTblFmt->SetFmtAttr( *pItem );
+ rTxtNode.ResetAttr( RES_BREAK );
+ pSet = rTxtNode.GetpSwAttrSet();
+ }
+
+ if( pSet && SFX_ITEM_SET == pSet->GetItemState(
+ RES_PAGEDESC, sal_False, &pItem ) &&
+ ((SwFmtPageDesc*)pItem)->GetPageDesc() )
+ {
+ if( !nLines )
+ pTblFmt->SetFmtAttr( *pItem );
+ rTxtNode.ResetAttr( RES_PAGEDESC );
+ }
+ }
+ }
+ }
+ }
+
+ std::vector<std::vector < SwNodeRange > >::const_iterator aRowIter = rTableNodes.begin();
+ for( nLines = 0, nBoxes = 0;
+ aRowIter != rTableNodes.end();
+ ++aRowIter, nLines++, nBoxes = 0 )
+ {
+ pLine = new SwTableLine( pLineFmt, 1, 0 );
+ pTable->GetTabLines().C40_INSERT( SwTableLine, pLine, nLines );
+
+ std::vector< SwNodeRange >::const_iterator aCellIter = aRowIter->begin();
+
+ for( ; aCellIter != aRowIter->end(); ++aCellIter )
+ {
+ const SwNodeIndex aTmpIdx( aCellIter->aStart, 0 );
+
+ SwNodeIndex aCellEndIdx(aCellIter->aEnd);
+ ++aCellEndIdx;
+ SwStartNode* pSttNd = new SwStartNode( aTmpIdx, ND_STARTNODE,
+ SwTableBoxStartNode );
+ new SwEndNode( aCellEndIdx, *pSttNd );
+ //set the start node on all node of the current cell
+ SwNodeIndex aCellNodeIdx = aCellIter->aStart;
+ for(;aCellNodeIdx <= aCellIter->aEnd; ++aCellNodeIdx )
+ {
+ aCellNodeIdx.GetNode().pStartOfSection = pSttNd;
+ //skip start/end node pairs
+ if( aCellNodeIdx.GetNode().IsStartNode() )
+ aCellNodeIdx = SwNodeIndex( *aCellNodeIdx.GetNode().EndOfSectionNode() );
+ }
+
+ // Section der Box zuweisen
+ pBox = new SwTableBox( pBoxFmt, *pSttNd, pLine );
+ pLine->GetTabBoxes().C40_INSERT( SwTableBox, pBox, nBoxes++ );
+ }
+ if( nMaxBoxes < nBoxes )
+ nMaxBoxes = nBoxes;
+ }
+
+ // die Tabelle ausgleichen, leere Sections einfuegen
+ sal_uInt16 n;
+
+ if( aPosArr.Count() )
+ {
+ SwTableLines& rLns = pTable->GetTabLines();
+ sal_uInt16 nLastPos = 0;
+ for( n = 0; n < aPosArr.Count(); ++n )
+ {
+ SwTableBoxFmt *pNewFmt = pDoc->MakeTableBoxFmt();
+ pNewFmt->SetFmtAttr( SwFmtFrmSize( ATT_VAR_SIZE,
+ aPosArr[ n ] - nLastPos ));
+ for( sal_uInt16 nLines2 = 0; nLines2 < rLns.Count(); ++nLines2 )
+ //JP 24.06.98: hier muss ein Add erfolgen, da das BoxFormat
+ // von der rufenden Methode noch gebraucht wird!
+ pNewFmt->Add( rLns[ nLines2 ]->GetTabBoxes()[ n ] );
+
+ nLastPos = aPosArr[ n ];
+ }
+
+ // damit die Tabelle die richtige Groesse bekommt, im BoxFormat die
+ // Groesse nach "oben" transportieren.
+ OSL_ENSURE( !pBoxFmt->GetDepends(), "wer ist in dem Format noch angemeldet" );
+ pBoxFmt->SetFmtAttr( SwFmtFrmSize( ATT_VAR_SIZE, nLastPos ));
+ }
+ else
+ pBoxFmt->SetFmtAttr( SwFmtFrmSize( ATT_VAR_SIZE, USHRT_MAX / nMaxBoxes ));
+
+ // das wars doch wohl ??
+ return pTblNd;
+}
+
+
+//---------------- Tabelle -> Text -----------------------
+
+
+sal_Bool SwDoc::TableToText( const SwTableNode* pTblNd, sal_Unicode cCh )
+{
+ if( !pTblNd )
+ return sal_False;
+
+ // --> FME 2004-09-28 #i34471#
+ // If this is trigged by SwUndoTblToTxt::Repeat() nobody ever deleted
+ // the table cursor.
+ SwEditShell* pESh = GetEditShell();
+ if( pESh && pESh->IsTableMode() )
+ pESh->ClearMark();
+ // <--
+
+ SwNodeRange aRg( *pTblNd, 0, *pTblNd->EndOfSectionNode() );
+ SwUndoTblToTxt* pUndo = 0;
+ SwNodeRange* pUndoRg = 0;
+ if (GetIDocumentUndoRedo().DoesUndo())
+ {
+ GetIDocumentUndoRedo().ClearRedo();
+ pUndoRg = new SwNodeRange( aRg.aStart, -1, aRg.aEnd, +1 );
+ pUndo = new SwUndoTblToTxt( pTblNd->GetTable(), cCh );
+ }
+
+ SwTableFmlUpdate aMsgHnt( &pTblNd->GetTable() );
+ aMsgHnt.eFlags = TBL_BOXNAME;
+ UpdateTblFlds( &aMsgHnt );
+
+ sal_Bool bRet = GetNodes().TableToText( aRg, cCh, pUndo );
+ if( pUndoRg )
+ {
+ pUndoRg->aStart++;
+ pUndoRg->aEnd--;
+ pUndo->SetRange( *pUndoRg );
+ GetIDocumentUndoRedo().AppendUndo(pUndo);
+ delete pUndoRg;
+ }
+
+ if( bRet )
+ SetModified();
+
+ return bRet;
+}
+
+// -- benutze die ForEach Methode vom PtrArray um aus einer Tabelle wieder
+// Text zuerzeugen. (Die Boxen koennen auch noch Lines enthalten !!)
+struct _DelTabPara
+{
+ SwTxtNode* pLastNd;
+ SwNodes& rNds;
+ SwUndoTblToTxt* pUndo;
+ sal_Unicode cCh;
+
+ _DelTabPara( SwNodes& rNodes, sal_Unicode cChar, SwUndoTblToTxt* pU ) :
+ pLastNd(0), rNds( rNodes ), pUndo( pU ), cCh( cChar ) {}
+ _DelTabPara( const _DelTabPara& rPara ) :
+ pLastNd(rPara.pLastNd), rNds( rPara.rNds ),
+ pUndo( rPara.pUndo ), cCh( rPara.cCh ) {}
+};
+
+// forward deklarieren damit sich die Lines und Boxen rekursiv aufrufen
+// koennen.
+sal_Bool lcl_DelBox( const SwTableBox*&, void *pPara );
+
+sal_Bool lcl_DelLine( const SwTableLine*& rpLine, void* pPara )
+{
+ OSL_ENSURE( pPara, "die Parameter fehlen" );
+ _DelTabPara aPara( *(_DelTabPara*)pPara );
+ ((SwTableLine*&)rpLine)->GetTabBoxes().ForEach( &lcl_DelBox, &aPara );
+ if( rpLine->GetUpper() ) // gibt es noch eine uebergeordnete Box ??
+ // dann gebe den letzten TextNode zurueck
+ ((_DelTabPara*)pPara)->pLastNd = aPara.pLastNd;
+ return sal_True;
+}
+
+
+sal_Bool lcl_DelBox( const SwTableBox*& rpBox, void* pPara )
+{
+ OSL_ENSURE( pPara, "die Parameter fehlen" );
+
+ // loesche erstmal die Lines der Box
+ _DelTabPara* pDelPara = (_DelTabPara*)pPara;
+ if( rpBox->GetTabLines().Count() )
+ ((SwTableBox*&)rpBox)->GetTabLines().ForEach( &lcl_DelLine, pDelPara );
+ else
+ {
+ SwDoc* pDoc = pDelPara->rNds.GetDoc();
+ SwNodeRange aDelRg( *rpBox->GetSttNd(), 0,
+ *rpBox->GetSttNd()->EndOfSectionNode() );
+ // loesche die Section
+ pDelPara->rNds.SectionUp( &aDelRg );
+ const SwTxtNode* pCurTxtNd;
+ if( T2T_PARA != pDelPara->cCh && pDelPara->pLastNd &&
+ 0 != ( pCurTxtNd = aDelRg.aStart.GetNode().GetTxtNode() ))
+ {
+ // Join the current text node with the last from the previous box if possible
+ sal_uLong nNdIdx = aDelRg.aStart.GetIndex();
+ aDelRg.aStart--;
+ if( pDelPara->pLastNd == &aDelRg.aStart.GetNode() )
+ {
+ // Inserting the seperator
+ SwIndex aCntIdx( pDelPara->pLastNd, pDelPara->pLastNd->GetTxt().Len());
+ pDelPara->pLastNd->InsertText( pDelPara->cCh, aCntIdx,
+ IDocumentContentOperations::INS_EMPTYEXPAND );
+ if( pDelPara->pUndo )
+ pDelPara->pUndo->AddBoxPos( *pDoc, nNdIdx, aDelRg.aEnd.GetIndex(),
+ aCntIdx.GetIndex() );
+
+ SvULongs aBkmkArr( 4, 4 );
+ xub_StrLen nOldTxtLen = aCntIdx.GetIndex();
+ _SaveCntntIdx( pDoc, nNdIdx, pCurTxtNd->GetTxt().Len(),
+ aBkmkArr );
+
+ pDelPara->pLastNd->JoinNext();
+
+ if( aBkmkArr.Count() )
+ _RestoreCntntIdx( pDoc, aBkmkArr,
+ pDelPara->pLastNd->GetIndex(),
+ nOldTxtLen );
+ }
+ else if( pDelPara->pUndo )
+ {
+ aDelRg.aStart++;
+ pDelPara->pUndo->AddBoxPos( *pDoc, nNdIdx, aDelRg.aEnd.GetIndex() );
+ }
+ }
+ else if( pDelPara->pUndo )
+ pDelPara->pUndo->AddBoxPos( *pDoc, aDelRg.aStart.GetIndex(), aDelRg.aEnd.GetIndex() );
+ aDelRg.aEnd--;
+ pDelPara->pLastNd = aDelRg.aEnd.GetNode().GetTxtNode();
+
+ //JP 03.04.97: die Ausrichtung der ZahlenFormatierung auf
+ // keinen Fall uebernehmen
+ if( pDelPara->pLastNd && pDelPara->pLastNd->HasSwAttrSet() )
+ pDelPara->pLastNd->ResetAttr( RES_PARATR_ADJUST );
+ }
+ return sal_True;
+}
+
+
+sal_Bool SwNodes::TableToText( const SwNodeRange& rRange, sal_Unicode cCh,
+ SwUndoTblToTxt* pUndo )
+{
+ // ist eine Tabelle selektiert ?
+ SwTableNode* pTblNd;
+ if( rRange.aStart.GetIndex() >= rRange.aEnd.GetIndex() ||
+ 0 == ( pTblNd = rRange.aStart.GetNode().GetTableNode()) ||
+ &rRange.aEnd.GetNode() != pTblNd->EndOfSectionNode() )
+ return sal_False;
+
+ // stand die Tabelle ganz alleine in einer Section ?
+ // dann ueber den Upper der Tabelle die Frames anlegen
+ SwNode2Layout* pNode2Layout = 0;
+ SwNodeIndex aFrmIdx( rRange.aStart );
+ SwNode* pFrmNd = FindPrvNxtFrmNode( aFrmIdx, &rRange.aEnd.GetNode() );
+ if( !pFrmNd )
+ // dann sammel mal alle Uppers ein
+ pNode2Layout = new SwNode2Layout( *pTblNd );
+
+ // loesche schon mal die Frames
+ pTblNd->DelFrms();
+
+ // dann "loeschen" die Tabellen und fasse alle Lines/Boxen zusammen
+ _DelTabPara aDelPara( *this, cCh, pUndo );
+ pTblNd->pTable->GetTabLines().ForEach( &lcl_DelLine, &aDelPara );
+
+ // jetzt ist aus jeder TableLine ein TextNode mit dem entsprechenden
+ // Trenner erzeugt worden. Es braucht nur noch die Table-Section
+ // geloescht und fuer die neuen TextNode die Frames erzeugt werden.
+ SwNodeRange aDelRg( rRange.aStart, rRange.aEnd );
+
+ // JP 14.01.97: hat die Tabelle PageDesc-/Break-Attribute? Dann in den
+ // ersten TextNode uebernehmen
+ {
+// was ist mit UNDO???
+ const SfxItemSet& rTblSet = pTblNd->pTable->GetFrmFmt()->GetAttrSet();
+ const SfxPoolItem *pBreak, *pDesc;
+ if( SFX_ITEM_SET != rTblSet.GetItemState( RES_PAGEDESC, sal_False, &pDesc ))
+ pDesc = 0;
+ if( SFX_ITEM_SET != rTblSet.GetItemState( RES_BREAK, sal_False, &pBreak ))
+ pBreak = 0;
+
+ if( pBreak || pDesc )
+ {
+ SwNodeIndex aIdx( *pTblNd );
+ SwCntntNode* pCNd = GoNext( &aIdx );
+ if( pBreak )
+ pCNd->SetAttr( *pBreak );
+ if( pDesc )
+ pCNd->SetAttr( *pDesc );
+ }
+ }
+
+ SectionUp( &aDelRg ); // loesche die Section und damit die Tabelle
+ // #i28006#
+ sal_uLong nStt = aDelRg.aStart.GetIndex(), nEnd = aDelRg.aEnd.GetIndex();
+ if( !pFrmNd )
+ {
+ pNode2Layout->RestoreUpperFrms( *this,
+ aDelRg.aStart.GetIndex(), aDelRg.aEnd.GetIndex() );
+ delete pNode2Layout;
+ }
+ else
+ {
+ SwCntntNode *pCNd;
+ SwSectionNode *pSNd;
+ while( aDelRg.aStart.GetIndex() < nEnd )
+ {
+ if( 0 != ( pCNd = aDelRg.aStart.GetNode().GetCntntNode()))
+ {
+ if( pFrmNd->IsCntntNode() )
+ ((SwCntntNode*)pFrmNd)->MakeFrms( *pCNd );
+ else if( pFrmNd->IsTableNode() )
+ ((SwTableNode*)pFrmNd)->MakeFrms( aDelRg.aStart );
+ else if( pFrmNd->IsSectionNode() )
+ ((SwSectionNode*)pFrmNd)->MakeFrms( aDelRg.aStart );
+ pFrmNd = pCNd;
+ }
+ else if( 0 != ( pSNd = aDelRg.aStart.GetNode().GetSectionNode()))
+ {
+ if( !pSNd->GetSection().IsHidden() && !pSNd->IsCntntHidden() )
+ {
+ pSNd->MakeFrms( &aFrmIdx, &aDelRg.aEnd );
+ pFrmNd = pSNd;
+ break;
+ }
+ aDelRg.aStart = *pSNd->EndOfSectionNode();
+ }
+ aDelRg.aStart++;
+ }
+ }
+
+ // #i28006# Fly frames have to be restored even if the table was
+ // #alone in the section
+ const SwSpzFrmFmts& rFlyArr = *GetDoc()->GetSpzFrmFmts();
+ for( sal_uInt16 n = 0; n < rFlyArr.Count(); ++n )
+ {
+ SwFrmFmt *const pFmt = (SwFrmFmt*)rFlyArr[n];
+ const SwFmtAnchor& rAnchor = pFmt->GetAnchor();
+ SwPosition const*const pAPos = rAnchor.GetCntntAnchor();
+ if (pAPos &&
+ ((FLY_AT_PARA == rAnchor.GetAnchorId()) ||
+ (FLY_AT_CHAR == rAnchor.GetAnchorId())) &&
+ nStt <= pAPos->nNode.GetIndex() &&
+ pAPos->nNode.GetIndex() < nEnd )
+ {
+ pFmt->MakeFrms();
+ }
+ }
+
+ return sal_True;
+}
+
+
+// ----- einfuegen von Spalten/Zeilen ------------------------
+
+sal_Bool SwDoc::InsertCol( const SwCursor& rCursor, sal_uInt16 nCnt, sal_Bool bBehind )
+{
+ if( !::CheckSplitCells( rCursor, nCnt + 1, nsSwTblSearchType::TBLSEARCH_COL ) )
+ return sal_False;
+
+ // lasse ueber das Layout die Boxen suchen
+ SwSelBoxes aBoxes;
+ ::GetTblSel( rCursor, aBoxes, nsSwTblSearchType::TBLSEARCH_COL );
+
+ sal_Bool bRet = sal_False;
+ if( aBoxes.Count() )
+ bRet = InsertCol( aBoxes, nCnt, bBehind );
+ return bRet;
+}
+
+sal_Bool SwDoc::InsertCol( const SwSelBoxes& rBoxes, sal_uInt16 nCnt, sal_Bool bBehind )
+{
+ // uebers SwDoc fuer Undo !!
+ OSL_ENSURE( rBoxes.Count(), "keine gueltige Box-Liste" );
+ SwTableNode* pTblNd = (SwTableNode*)rBoxes[0]->GetSttNd()->FindTableNode();
+ if( !pTblNd )
+ return sal_False;
+
+ SwTable& rTbl = pTblNd->GetTable();
+ if( rTbl.ISA( SwDDETable ))
+ return sal_False;
+
+ SwTableSortBoxes aTmpLst( 0, 5 );
+ SwUndoTblNdsChg* pUndo = 0;
+ if (GetIDocumentUndoRedo().DoesUndo())
+ {
+ pUndo = new SwUndoTblNdsChg( UNDO_TABLE_INSCOL, rBoxes, *pTblNd,
+ 0, 0, nCnt, bBehind, sal_False );
+ aTmpLst.Insert( &rTbl.GetTabSortBoxes(), 0, rTbl.GetTabSortBoxes().Count() );
+ }
+
+ bool bRet(false);
+ {
+ ::sw::UndoGuard const undoGuard(GetIDocumentUndoRedo());
+
+ SwTableFmlUpdate aMsgHnt( &rTbl );
+ aMsgHnt.eFlags = TBL_BOXPTR;
+ UpdateTblFlds( &aMsgHnt );
+
+ bRet = rTbl.InsertCol( this, rBoxes, nCnt, bBehind );
+ if (bRet)
+ {
+ SetModified();
+ ::ClearFEShellTabCols();
+ SetFieldsDirty( true, NULL, 0 );
+ }
+ }
+
+ if( pUndo )
+ {
+ if( bRet )
+ {
+ pUndo->SaveNewBoxes( *pTblNd, aTmpLst );
+ GetIDocumentUndoRedo().AppendUndo( pUndo );
+ }
+ else
+ delete pUndo;
+ }
+ return bRet;
+}
+
+sal_Bool SwDoc::InsertRow( const SwCursor& rCursor, sal_uInt16 nCnt, sal_Bool bBehind )
+{
+ // lasse ueber das Layout die Boxen suchen
+ SwSelBoxes aBoxes;
+ GetTblSel( rCursor, aBoxes, nsSwTblSearchType::TBLSEARCH_ROW );
+
+ sal_Bool bRet = sal_False;
+ if( aBoxes.Count() )
+ bRet = InsertRow( aBoxes, nCnt, bBehind );
+ return bRet;
+}
+
+sal_Bool SwDoc::InsertRow( const SwSelBoxes& rBoxes, sal_uInt16 nCnt, sal_Bool bBehind )
+{
+ // uebers SwDoc fuer Undo !!
+ OSL_ENSURE( rBoxes.Count(), "keine gueltige Box-Liste" );
+ SwTableNode* pTblNd = (SwTableNode*)rBoxes[0]->GetSttNd()->FindTableNode();
+ if( !pTblNd )
+ return sal_False;
+
+ SwTable& rTbl = pTblNd->GetTable();
+ if( rTbl.ISA( SwDDETable ))
+ return sal_False;
+
+ SwTableSortBoxes aTmpLst( 0, 5 );
+ SwUndoTblNdsChg* pUndo = 0;
+ if (GetIDocumentUndoRedo().DoesUndo())
+ {
+ pUndo = new SwUndoTblNdsChg( UNDO_TABLE_INSROW,rBoxes, *pTblNd,
+ 0, 0, nCnt, bBehind, sal_False );
+ aTmpLst.Insert( &rTbl.GetTabSortBoxes(), 0, rTbl.GetTabSortBoxes().Count() );
+ }
+
+ bool bRet(false);
+ {
+ ::sw::UndoGuard const undoGuard(GetIDocumentUndoRedo());
+
+ SwTableFmlUpdate aMsgHnt( &rTbl );
+ aMsgHnt.eFlags = TBL_BOXPTR;
+ UpdateTblFlds( &aMsgHnt );
+
+ bRet = rTbl.InsertRow( this, rBoxes, nCnt, bBehind );
+ if (bRet)
+ {
+ SetModified();
+ ::ClearFEShellTabCols();
+ SetFieldsDirty( true, NULL, 0 );
+ }
+ }
+
+ if( pUndo )
+ {
+ if( bRet )
+ {
+ pUndo->SaveNewBoxes( *pTblNd, aTmpLst );
+ GetIDocumentUndoRedo().AppendUndo( pUndo );
+ }
+ else
+ delete pUndo;
+ }
+ return bRet;
+
+}
+
+// ----- loeschen von Spalten/Zeilen ------------------------
+
+sal_Bool SwDoc::DeleteRow( const SwCursor& rCursor )
+{
+ // lasse ueber das Layout die Boxen suchen
+ SwSelBoxes aBoxes;
+ GetTblSel( rCursor, aBoxes, nsSwTblSearchType::TBLSEARCH_ROW );
+ if( ::HasProtectedCells( aBoxes ))
+ return sal_False;
+
+ // die Crsr aus dem Loeschbereich entfernen.
+ // Der Cursor steht danach:
+ // - es folgt noch eine Zeile, in dieser
+ // - vorher steht noch eine Zeile, in dieser
+ // - sonst immer dahinter
+ {
+ SwTableNode* pTblNd = rCursor.GetNode()->FindTableNode();
+
+ if( pTblNd->GetTable().ISA( SwDDETable ))
+ return sal_False;
+
+ // suche alle Boxen / Lines
+ _FndBox aFndBox( 0, 0 );
+ {
+ _FndPara aPara( aBoxes, &aFndBox );
+ pTblNd->GetTable().GetTabLines().ForEach( &_FndLineCopyCol, &aPara );
+ }
+
+ if( !aFndBox.GetLines().Count() )
+ return sal_False;
+
+ SwEditShell* pESh = GetEditShell();
+ if( pESh )
+ {
+ pESh->KillPams();
+ // JP: eigentlich sollte man ueber alle Shells iterieren!!
+ }
+
+ _FndBox* pFndBox = &aFndBox;
+ while( 1 == pFndBox->GetLines().Count() &&
+ 1 == pFndBox->GetLines()[0]->GetBoxes().Count() )
+ {
+ _FndBox* pTmp = pFndBox->GetLines()[0]->GetBoxes()[0];
+ if( pTmp->GetBox()->GetSttNd() )
+ break; // das ist sonst zu weit
+ pFndBox = pTmp;
+ }
+
+ SwTableLine* pDelLine = pFndBox->GetLines()[
+ pFndBox->GetLines().Count()-1 ]->GetLine();
+ SwTableBox* pDelBox = pDelLine->GetTabBoxes()[
+ pDelLine->GetTabBoxes().Count() - 1 ];
+ while( !pDelBox->GetSttNd() )
+ {
+ SwTableLine* pLn = pDelBox->GetTabLines()[
+ pDelBox->GetTabLines().Count()-1 ];
+ pDelBox = pLn->GetTabBoxes()[ pLn->GetTabBoxes().Count() - 1 ];
+ }
+ SwTableBox* pNextBox = pDelLine->FindNextBox( pTblNd->GetTable(),
+ pDelBox, sal_True );
+ while( pNextBox &&
+ pNextBox->GetFrmFmt()->GetProtect().IsCntntProtected() )
+ pNextBox = pNextBox->FindNextBox( pTblNd->GetTable(), pNextBox );
+
+ if( !pNextBox ) // keine nachfolgende? dann die vorhergehende
+ {
+ pDelLine = pFndBox->GetLines()[ 0 ]->GetLine();
+ pDelBox = pDelLine->GetTabBoxes()[ 0 ];
+ while( !pDelBox->GetSttNd() )
+ pDelBox = pDelBox->GetTabLines()[0]->GetTabBoxes()[0];
+ pNextBox = pDelLine->FindPreviousBox( pTblNd->GetTable(),
+ pDelBox, sal_True );
+ while( pNextBox &&
+ pNextBox->GetFrmFmt()->GetProtect().IsCntntProtected() )
+ pNextBox = pNextBox->FindPreviousBox( pTblNd->GetTable(), pNextBox );
+ }
+
+ sal_uLong nIdx;
+ if( pNextBox ) // dann den Cursor hier hinein
+ nIdx = pNextBox->GetSttIdx() + 1;
+ else // ansonsten hinter die Tabelle
+ nIdx = pTblNd->EndOfSectionIndex() + 1;
+
+ SwNodeIndex aIdx( GetNodes(), nIdx );
+ SwCntntNode* pCNd = aIdx.GetNode().GetCntntNode();
+ if( !pCNd )
+ pCNd = GetNodes().GoNext( &aIdx );
+
+ if( pCNd )
+ {
+ // die Cursor von der Shell oder den uebergebenen Cursor aendern?
+ SwPaM* pPam = (SwPaM*)&rCursor;
+ pPam->GetPoint()->nNode = aIdx;
+ pPam->GetPoint()->nContent.Assign( pCNd, 0 );
+ pPam->SetMark(); // beide wollen etwas davon haben
+ pPam->DeleteMark();
+ }
+ }
+
+ // dann loesche doch die Zeilen
+
+ GetIDocumentUndoRedo().StartUndo(UNDO_ROW_DELETE, NULL);
+ sal_Bool bResult = DeleteRowCol( aBoxes );
+ GetIDocumentUndoRedo().EndUndo(UNDO_ROW_DELETE, NULL);
+
+ return bResult;
+}
+
+sal_Bool SwDoc::DeleteCol( const SwCursor& rCursor )
+{
+ // lasse ueber das Layout die Boxen suchen
+ SwSelBoxes aBoxes;
+ GetTblSel( rCursor, aBoxes, nsSwTblSearchType::TBLSEARCH_COL );
+ if( ::HasProtectedCells( aBoxes ))
+ return sal_False;
+
+ // die Crsr muessen noch aus dem Loesch Bereich entfernt
+ // werden. Setze sie immer hinter/auf die Tabelle; ueber die
+ // Dokument-Position werden sie dann immer an die alte Position gesetzt.
+ SwEditShell* pESh = GetEditShell();
+ if( pESh )
+ {
+ const SwNode* pNd = rCursor.GetNode()->FindTableBoxStartNode();
+ pESh->ParkCrsr( SwNodeIndex( *pNd ) );
+ }
+
+ // dann loesche doch die Spalten
+ GetIDocumentUndoRedo().StartUndo(UNDO_COL_DELETE, NULL);
+ sal_Bool bResult = DeleteRowCol( aBoxes, true );
+ GetIDocumentUndoRedo().EndUndo(UNDO_COL_DELETE, NULL);
+
+ return bResult;
+}
+
+sal_Bool SwDoc::DeleteRowCol( const SwSelBoxes& rBoxes, bool bColumn )
+{
+ if( ::HasProtectedCells( rBoxes ))
+ return sal_False;
+
+ // uebers SwDoc fuer Undo !!
+ OSL_ENSURE( rBoxes.Count(), "keine gueltige Box-Liste" );
+ SwTableNode* pTblNd = (SwTableNode*)rBoxes[0]->GetSttNd()->FindTableNode();
+ if( !pTblNd )
+ return sal_False;
+
+ if( pTblNd->GetTable().ISA( SwDDETable ))
+ return sal_False;
+
+ ::ClearFEShellTabCols();
+ SwSelBoxes aSelBoxes;
+ aSelBoxes.Insert(rBoxes.GetData(), rBoxes.Count());
+ SwTable &rTable = pTblNd->GetTable();
+ long nMin = 0;
+ long nMax = 0;
+ if( rTable.IsNewModel() )
+ {
+ if( bColumn )
+ rTable.ExpandColumnSelection( aSelBoxes, nMin, nMax );
+ else
+ rTable.FindSuperfluousRows( aSelBoxes );
+ }
+
+ // soll die gesamte Tabelle geloescht werden ??
+ const sal_uLong nTmpIdx1 = pTblNd->GetIndex();
+ const sal_uLong nTmpIdx2 = aSelBoxes[ aSelBoxes.Count()-1 ]->GetSttNd()->
+ EndOfSectionIndex()+1;
+ if( pTblNd->GetTable().GetTabSortBoxes().Count() == aSelBoxes.Count() &&
+ aSelBoxes[0]->GetSttIdx()-1 == nTmpIdx1 &&
+ nTmpIdx2 == pTblNd->EndOfSectionIndex() )
+ {
+ sal_Bool bNewTxtNd = sal_False;
+ // steht diese auch noch alleine in einem FlyFrame ?
+ SwNodeIndex aIdx( *pTblNd, -1 );
+ const SwStartNode* pSttNd = aIdx.GetNode().GetStartNode();
+ if( pSttNd )
+ {
+ const sal_uLong nTblEnd = pTblNd->EndOfSectionIndex() + 1;
+ const sal_uLong nSectEnd = pSttNd->EndOfSectionIndex();
+ if( nTblEnd == nSectEnd )
+ {
+ if( SwFlyStartNode == pSttNd->GetStartNodeType() )
+ {
+ SwFrmFmt* pFmt = pSttNd->GetFlyFmt();
+ if( pFmt )
+ {
+ // Ok, das ist das gesuchte FlyFormat
+ DelLayoutFmt( pFmt );
+ return sal_True;
+ }
+ }
+ // kein Fly ?? also Kopf- oder Fusszeile: dann immer einen
+ // TextNode ueberig lassen.
+ // Undo koennen wir dann vergessen !!
+ bNewTxtNd = sal_True;
+ }
+ }
+
+ // kein Fly ?? also Kopf- oder Fusszeile: dann immer einen
+ // TextNode ueberig lassen.
+ aIdx++;
+ if (GetIDocumentUndoRedo().DoesUndo())
+ {
+ GetIDocumentUndoRedo().ClearRedo();
+ SwPaM aPaM( *pTblNd->EndOfSectionNode(), aIdx.GetNode() );
+
+ if( bNewTxtNd )
+ {
+ const SwNodeIndex aTmpIdx( *pTblNd->EndOfSectionNode(), 1 );
+ GetNodes().MakeTxtNode( aTmpIdx,
+ GetTxtCollFromPool( RES_POOLCOLL_STANDARD ) );
+ }
+
+ // save the cursors (UNO and otherwise)
+ SwPaM aSavePaM( SwNodeIndex( *pTblNd->EndOfSectionNode() ) );
+ if( ! aSavePaM.Move( fnMoveForward, fnGoNode ) )
+ {
+ *aSavePaM.GetMark() = SwPosition( *pTblNd );
+ aSavePaM.Move( fnMoveBackward, fnGoNode );
+ }
+ {
+ SwPaM const tmpPaM(*pTblNd, *pTblNd->EndOfSectionNode());
+ ::PaMCorrAbs(tmpPaM, *aSavePaM.GetMark());
+ }
+
+ // harte SeitenUmbrueche am nachfolgenden Node verschieben
+ sal_Bool bSavePageBreak = sal_False, bSavePageDesc = sal_False;
+ sal_uLong nNextNd = pTblNd->EndOfSectionIndex()+1;
+ SwCntntNode* pNextNd = GetNodes()[ nNextNd ]->GetCntntNode();
+ if( pNextNd )
+ {
+ {
+ SwFrmFmt* pTableFmt = pTblNd->GetTable().GetFrmFmt();
+ const SfxPoolItem *pItem;
+ if( SFX_ITEM_SET == pTableFmt->GetItemState( RES_PAGEDESC,
+ sal_False, &pItem ) )
+ {
+ pNextNd->SetAttr( *pItem );
+ bSavePageDesc = sal_True;
+ }
+
+ if( SFX_ITEM_SET == pTableFmt->GetItemState( RES_BREAK,
+ sal_False, &pItem ) )
+ {
+ pNextNd->SetAttr( *pItem );
+ bSavePageBreak = sal_True;
+ }
+ }
+ }
+ SwUndoDelete* pUndo = new SwUndoDelete( aPaM );
+ if( bNewTxtNd )
+ pUndo->SetTblDelLastNd();
+ pUndo->SetPgBrkFlags( bSavePageBreak, bSavePageDesc );
+ pUndo->SetTableName(pTblNd->GetTable().GetFrmFmt()->GetName());
+ GetIDocumentUndoRedo().AppendUndo( pUndo );
+ }
+ else
+ {
+ if( bNewTxtNd )
+ {
+ const SwNodeIndex aTmpIdx( *pTblNd->EndOfSectionNode(), 1 );
+ GetNodes().MakeTxtNode( aTmpIdx,
+ GetTxtCollFromPool( RES_POOLCOLL_STANDARD ) );
+ }
+
+ // save the cursors (UNO and otherwise)
+ SwPaM aSavePaM( SwNodeIndex( *pTblNd->EndOfSectionNode() ) );
+ if( ! aSavePaM.Move( fnMoveForward, fnGoNode ) )
+ {
+ *aSavePaM.GetMark() = SwPosition( *pTblNd );
+ aSavePaM.Move( fnMoveBackward, fnGoNode );
+ }
+ {
+ SwPaM const tmpPaM(*pTblNd, *pTblNd->EndOfSectionNode());
+ ::PaMCorrAbs(tmpPaM, *aSavePaM.GetMark());
+ }
+
+ // harte SeitenUmbrueche am nachfolgenden Node verschieben
+ SwCntntNode* pNextNd = GetNodes()[ pTblNd->EndOfSectionIndex()+1 ]->GetCntntNode();
+ if( pNextNd )
+ {
+ SwFrmFmt* pTableFmt = pTblNd->GetTable().GetFrmFmt();
+ const SfxPoolItem *pItem;
+ if( SFX_ITEM_SET == pTableFmt->GetItemState( RES_PAGEDESC,
+ sal_False, &pItem ) )
+ pNextNd->SetAttr( *pItem );
+
+ if( SFX_ITEM_SET == pTableFmt->GetItemState( RES_BREAK,
+ sal_False, &pItem ) )
+ pNextNd->SetAttr( *pItem );
+ }
+
+ pTblNd->DelFrms();
+ DeleteSection( pTblNd );
+ }
+ SetModified();
+ SetFieldsDirty( true, NULL, 0 );
+ return sal_True;
+ }
+
+ SwUndoTblNdsChg* pUndo = 0;
+ if (GetIDocumentUndoRedo().DoesUndo())
+ {
+ pUndo = new SwUndoTblNdsChg( UNDO_TABLE_DELBOX, aSelBoxes, *pTblNd,
+ nMin, nMax, 0, sal_False, sal_False );
+ }
+
+ bool bRet(false);
+ {
+ ::sw::UndoGuard const undoGuard(GetIDocumentUndoRedo());
+
+ SwTableFmlUpdate aMsgHnt( &pTblNd->GetTable() );
+ aMsgHnt.eFlags = TBL_BOXPTR;
+ UpdateTblFlds( &aMsgHnt );
+
+ if (rTable.IsNewModel())
+ {
+ if (bColumn)
+ rTable.PrepareDeleteCol( nMin, nMax );
+ rTable.FindSuperfluousRows( aSelBoxes );
+ if (pUndo)
+ pUndo->ReNewBoxes( aSelBoxes );
+ }
+ bRet = rTable.DeleteSel( this, aSelBoxes, 0, pUndo, sal_True, sal_True );
+ if (bRet)
+ {
+ SetModified();
+ SetFieldsDirty( true, NULL, 0 );
+ }
+ }
+
+ if( pUndo )
+ {
+ if( bRet )
+ {
+ GetIDocumentUndoRedo().AppendUndo( pUndo );
+ }
+ else
+ delete pUndo;
+ }
+
+ return bRet;
+}
+
+
+// ---------- teilen / zusammenfassen von Boxen in der Tabelle --------
+
+sal_Bool SwDoc::SplitTbl( const SwSelBoxes& rBoxes, sal_Bool bVert, sal_uInt16 nCnt,
+ sal_Bool bSameHeight )
+{
+ // uebers SwDoc fuer Undo !!
+ OSL_ENSURE( rBoxes.Count() && nCnt, "keine gueltige Box-Liste" );
+ SwTableNode* pTblNd = (SwTableNode*)rBoxes[0]->GetSttNd()->FindTableNode();
+ if( !pTblNd )
+ return sal_False;
+
+ SwTable& rTbl = pTblNd->GetTable();
+ if( rTbl.ISA( SwDDETable ))
+ return sal_False;
+
+ SvULongs aNdsCnts;
+ SwTableSortBoxes aTmpLst( 0, 5 );
+ SwUndoTblNdsChg* pUndo = 0;
+ if (GetIDocumentUndoRedo().DoesUndo())
+ {
+ pUndo = new SwUndoTblNdsChg( UNDO_TABLE_SPLIT, rBoxes, *pTblNd, 0, 0,
+ nCnt, bVert, bSameHeight );
+
+ aTmpLst.Insert( &rTbl.GetTabSortBoxes(), 0, rTbl.GetTabSortBoxes().Count() );
+ if( !bVert )
+ {
+ for( sal_uInt16 n = 0; n < rBoxes.Count(); ++n )
+ {
+ const SwStartNode* pSttNd = rBoxes[ n ]->GetSttNd();
+ aNdsCnts.Insert( pSttNd->EndOfSectionIndex() -
+ pSttNd->GetIndex(), n );
+ }
+ }
+ }
+
+ bool bRet(false);
+ {
+ ::sw::UndoGuard const undoGuard(GetIDocumentUndoRedo());
+
+ SwTableFmlUpdate aMsgHnt( &rTbl );
+ aMsgHnt.eFlags = TBL_BOXPTR;
+ UpdateTblFlds( &aMsgHnt );
+
+ if (bVert)
+ bRet = rTbl.SplitCol( this, rBoxes, nCnt );
+ else
+ bRet = rTbl.SplitRow( this, rBoxes, nCnt, bSameHeight );
+
+ if (bRet)
+ {
+ SetModified();
+ SetFieldsDirty( true, NULL, 0 );
+ }
+ }
+
+ if( pUndo )
+ {
+ if( bRet )
+ {
+ if( bVert )
+ pUndo->SaveNewBoxes( *pTblNd, aTmpLst );
+ else
+ pUndo->SaveNewBoxes( *pTblNd, aTmpLst, rBoxes, aNdsCnts );
+ GetIDocumentUndoRedo().AppendUndo( pUndo );
+ }
+ else
+ delete pUndo;
+ }
+
+ return bRet;
+}
+
+
+sal_uInt16 SwDoc::MergeTbl( SwPaM& rPam )
+{
+ // pruefe ob vom aktuellen Crsr der SPoint/Mark in einer Tabelle stehen
+ SwTableNode* pTblNd = rPam.GetNode()->FindTableNode();
+ if( !pTblNd )
+ return TBLMERGE_NOSELECTION;
+ SwTable& rTable = pTblNd->GetTable();
+ if( rTable.ISA(SwDDETable) )
+ return TBLMERGE_NOSELECTION;
+ sal_uInt16 nRet = TBLMERGE_NOSELECTION;
+ if( !rTable.IsNewModel() )
+ {
+ nRet =::CheckMergeSel( rPam );
+ if( TBLMERGE_OK != nRet )
+ return nRet;
+ nRet = TBLMERGE_NOSELECTION;
+ }
+
+ // --> FME 2004-10-08 #i33394#
+ GetIDocumentUndoRedo().StartUndo( UNDO_TABLE_MERGE, NULL );
+ // <--
+
+ RedlineMode_t eOld = GetRedlineMode();
+ SetRedlineMode_intern((RedlineMode_t)(eOld | nsRedlineMode_t::REDLINE_IGNORE));
+
+ SwUndoTblMerge *const pUndo( (GetIDocumentUndoRedo().DoesUndo())
+ ? new SwUndoTblMerge( rPam )
+ : 0 );
+
+ // lasse ueber das Layout die Boxen suchen
+ SwSelBoxes aBoxes;
+ SwSelBoxes aMerged;
+ SwTableBox* pMergeBox;
+
+ if( !rTable.PrepareMerge( rPam, aBoxes, aMerged, &pMergeBox, pUndo ) )
+ { // no cells found to merge
+ SetRedlineMode_intern( eOld );
+ if( pUndo )
+ {
+ delete pUndo;
+ SwUndoId nLastUndoId(UNDO_EMPTY);
+ if (GetIDocumentUndoRedo().GetLastUndoInfo(0, & nLastUndoId)
+ && (UNDO_REDLINE == nLastUndoId))
+ {
+ // FIXME: why is this horrible cleanup necessary?
+ SwUndoRedline *const pU = dynamic_cast<SwUndoRedline*>(
+ GetUndoManager().RemoveLastUndo());
+ if( pU->GetRedlSaveCount() )
+ {
+ SwEditShell *const pEditShell(GetEditShell(0));
+ OSL_ASSERT(pEditShell);
+ ::sw::UndoRedoContext context(*this, *pEditShell);
+ static_cast<SfxUndoAction *>(pU)->UndoWithContext(context);
+ }
+ delete pU;
+ }
+ }
+ }
+ else
+ {
+ // die PaMs muessen noch aus dem Loesch Bereich entfernt
+ // werden. Setze sie immer hinter/auf die Tabelle; ueber die
+ // Dokument-Position werden sie dann immer an die alte Position gesetzt.
+ // Erstmal einen Index auf die Parkposition merken, denn nach GetMergeSel
+ // komme ich nicht mehr dran.
+ {
+ rPam.DeleteMark();
+ rPam.GetPoint()->nNode = *pMergeBox->GetSttNd();
+ rPam.GetPoint()->nContent.Assign( 0, 0 );
+ rPam.SetMark();
+ rPam.DeleteMark();
+
+ SwPaM* pTmp = &rPam;
+ while( &rPam != ( pTmp = (SwPaM*)pTmp->GetNext() ))
+ for( int i = 0; i < 2; ++i )
+ pTmp->GetBound( (sal_Bool)i ) = *rPam.GetPoint();
+ }
+
+ // dann fuege sie zusammen
+ SwTableFmlUpdate aMsgHnt( &pTblNd->GetTable() );
+ aMsgHnt.eFlags = TBL_BOXPTR;
+ UpdateTblFlds( &aMsgHnt );
+
+ if( pTblNd->GetTable().Merge( this, aBoxes, aMerged, pMergeBox, pUndo ))
+ {
+ nRet = TBLMERGE_OK;
+ SetModified();
+ SetFieldsDirty( true, NULL, 0 );
+ if( pUndo )
+ {
+ GetIDocumentUndoRedo().AppendUndo( pUndo );
+ }
+ }
+ else if( pUndo )
+ delete pUndo;
+
+ rPam.GetPoint()->nNode = *pMergeBox->GetSttNd();
+ rPam.Move();
+
+ ::ClearFEShellTabCols();
+ SetRedlineMode_intern( eOld );
+ }
+ GetIDocumentUndoRedo().EndUndo( UNDO_TABLE_MERGE, NULL );
+ return nRet;
+}
+
+
+
+// -------------------------------------------------------
+
+//---------
+// SwTableNode
+//---------
+
+SwTableNode::SwTableNode( const SwNodeIndex& rIdx )
+ : SwStartNode( rIdx, ND_TABLENODE )
+{
+ pTable = new SwTable( 0 );
+}
+
+SwTableNode::~SwTableNode()
+{
+ //don't forget to notify uno wrappers
+ SwFrmFmt* pTblFmt = GetTable().GetFrmFmt();
+ SwPtrMsgPoolItem aMsgHint( RES_REMOVE_UNO_OBJECT,
+ pTblFmt );
+ pTblFmt->ModifyNotification( &aMsgHint, &aMsgHint );
+ DelFrms();
+ delete pTable;
+}
+
+SwTabFrm *SwTableNode::MakeFrm( SwFrm* pSib )
+{
+ return new SwTabFrm( *pTable, pSib );
+}
+
+//Methode erzeugt fuer den vorhergehenden Node alle Ansichten vom
+//Dokument. Die erzeugten Contentframes werden in das entsprechende
+//Layout gehaengt.
+void SwTableNode::MakeFrms(const SwNodeIndex & rIdx )
+{
+ if( !GetTable().GetFrmFmt()->GetDepends())//gibt es ueberhaupt Frames ??
+ return;
+
+ SwFrm *pFrm, *pNew;
+ SwCntntNode * pNode = rIdx.GetNode().GetCntntNode();
+
+ OSL_ENSURE( pNode, "Kein Contentnode oder Copy-Node und neuer Node identisch.");
+
+ sal_Bool bBefore = rIdx < GetIndex();
+
+ SwNode2Layout aNode2Layout( *this, rIdx.GetIndex() );
+
+ while( 0 != (pFrm = aNode2Layout.NextFrm()) )
+ {
+ pNew = pNode->MakeFrm( pFrm );
+ // wird ein Node vorher oder nachher mit Frames versehen
+ if ( bBefore )
+ // der neue liegt vor mir
+ pNew->Paste( pFrm->GetUpper(), pFrm );
+ else
+ // der neue liegt hinter mir
+ pNew->Paste( pFrm->GetUpper(), pFrm->GetNext() );
+ }
+}
+
+//Fuer jede Shell einen TblFrm anlegen und vor den entsprechenden
+//CntntFrm pasten.
+
+void SwTableNode::MakeFrms( SwNodeIndex* pIdxBehind )
+{
+ OSL_ENSURE( pIdxBehind, "kein Index" );
+ *pIdxBehind = *this;
+ SwNode *pNd = GetNodes().FindPrvNxtFrmNode( *pIdxBehind, EndOfSectionNode() );
+ if( !pNd )
+ return ;
+
+ SwFrm *pFrm( 0L );
+ SwLayoutFrm *pUpper( 0L );
+ SwNode2Layout aNode2Layout( *pNd, GetIndex() );
+ while( 0 != (pUpper = aNode2Layout.UpperFrm( pFrm, *this )) )
+ {
+ SwTabFrm* pNew = MakeFrm( pUpper );
+ pNew->Paste( pUpper, pFrm );
+ // #i27138#
+ // notify accessibility paragraphs objects about changed
+ // CONTENT_FLOWS_FROM/_TO relation.
+ // Relation CONTENT_FLOWS_FROM for next paragraph will change
+ // and relation CONTENT_FLOWS_TO for previous paragraph will change.
+ {
+ ViewShell* pViewShell( pNew->getRootFrm()->GetCurrShell() );
+ if ( pViewShell && pViewShell->GetLayout() &&
+ pViewShell->GetLayout()->IsAnyShellAccessible() )
+ {
+ pViewShell->InvalidateAccessibleParaFlowRelation(
+ dynamic_cast<SwTxtFrm*>(pNew->FindNextCnt( true )),
+ dynamic_cast<SwTxtFrm*>(pNew->FindPrevCnt( true )) );
+ }
+ }
+ // <--
+ ((SwTabFrm*)pNew)->RegistFlys();
+ }
+}
+
+void SwTableNode::DelFrms()
+{
+ //Erstmal die TabFrms ausschneiden und deleten, die Columns und Rows
+ //nehmen sie mit in's Grab.
+ //Die TabFrms haengen am FrmFmt des SwTable.
+ //Sie muessen etwas umstaendlich zerstort werden, damit die Master
+ //die Follows mit in's Grab nehmen.
+
+ SwIterator<SwTabFrm,SwFmt> aIter( *(pTable->GetFrmFmt()) );
+ SwTabFrm *pFrm = aIter.First();
+ while ( pFrm )
+ {
+ sal_Bool bAgain = sal_False;
+ {
+ if ( !pFrm->IsFollow() )
+ {
+ while ( pFrm->HasFollow() )
+ pFrm->JoinAndDelFollows();
+ // #i27138#
+ // notify accessibility paragraphs objects about changed
+ // CONTENT_FLOWS_FROM/_TO relation.
+ // Relation CONTENT_FLOWS_FROM for current next paragraph will change
+ // and relation CONTENT_FLOWS_TO for current previous paragraph will change.
+ {
+ ViewShell* pViewShell( pFrm->getRootFrm()->GetCurrShell() );
+ if ( pViewShell && pViewShell->GetLayout() &&
+ pViewShell->GetLayout()->IsAnyShellAccessible() )
+ {
+ pViewShell->InvalidateAccessibleParaFlowRelation(
+ dynamic_cast<SwTxtFrm*>(pFrm->FindNextCnt( true )),
+ dynamic_cast<SwTxtFrm*>(pFrm->FindPrevCnt( true )) );
+ }
+ }
+ // <--
+ pFrm->Cut();
+ delete pFrm;
+ bAgain = sal_True;
+ }
+ }
+ pFrm = bAgain ? aIter.First() : aIter.Next();
+ }
+}
+
+
+void SwTableNode::SetNewTable( SwTable* pNewTable, sal_Bool bNewFrames )
+{
+ DelFrms();
+ delete pTable;
+ pTable = pNewTable;
+ if( bNewFrames )
+ {
+ SwNodeIndex aIdx( *EndOfSectionNode());
+ GetNodes().GoNext( &aIdx );
+ MakeFrms( &aIdx );
+ }
+}
+
+void SwDoc::GetTabCols( SwTabCols &rFill, const SwCursor* pCrsr,
+ const SwCellFrm* pBoxFrm ) const
+{
+ const SwTableBox* pBox = 0;
+ SwTabFrm *pTab = 0;
+
+ if( pBoxFrm )
+ {
+ pTab = ((SwFrm*)pBoxFrm)->ImplFindTabFrm();
+ pBox = pBoxFrm->GetTabBox();
+ }
+ else if( pCrsr )
+ {
+ const SwCntntNode* pCNd = pCrsr->GetCntntNode();
+ if( !pCNd )
+ return ;
+
+ Point aPt;
+ const SwShellCrsr *pShCrsr = dynamic_cast<const SwShellCrsr*>(pCrsr);
+ if( pShCrsr )
+ aPt = pShCrsr->GetPtPos();
+
+ const SwFrm* pTmpFrm = pCNd->getLayoutFrm( pCNd->GetDoc()->GetCurrentLayout(), &aPt, 0, sal_False );
+ do {
+ pTmpFrm = pTmpFrm->GetUpper();
+ } while ( !pTmpFrm->IsCellFrm() );
+
+ pBoxFrm = (SwCellFrm*)pTmpFrm;
+ pTab = ((SwFrm*)pBoxFrm)->ImplFindTabFrm();
+ pBox = pBoxFrm->GetTabBox();
+ }
+ else if( !pCrsr && !pBoxFrm )
+ {
+ OSL_ENSURE( !this, "einer von beiden muss angegeben werden!" );
+ return ;
+ }
+
+ //Fix-Punkte setzen, LeftMin in Dokumentkoordinaten die anderen relativ.
+ SWRECTFN( pTab )
+ const SwPageFrm* pPage = pTab->FindPageFrm();
+ const sal_uLong nLeftMin = (pTab->Frm().*fnRect->fnGetLeft)() -
+ (pPage->Frm().*fnRect->fnGetLeft)();
+ const sal_uLong nRightMax = (pTab->Frm().*fnRect->fnGetRight)() -
+ (pPage->Frm().*fnRect->fnGetLeft)();
+
+ rFill.SetLeftMin ( nLeftMin );
+ rFill.SetLeft ( (pTab->Prt().*fnRect->fnGetLeft)() );
+ rFill.SetRight ( (pTab->Prt().*fnRect->fnGetRight)());
+ rFill.SetRightMax( nRightMax - nLeftMin );
+
+ pTab->GetTable()->GetTabCols( rFill, pBox );
+}
+
+//
+// Here are some little helpers used in SwDoc::GetTabRows
+//
+
+#define ROWFUZZY 25
+
+struct FuzzyCompare
+{
+ bool operator() ( long s1, long s2 ) const;
+};
+
+bool FuzzyCompare::operator() ( long s1, long s2 ) const
+{
+ return ( s1 < s2 && abs( s1 - s2 ) > ROWFUZZY );
+}
+
+bool lcl_IsFrmInColumn( const SwCellFrm& rFrm, SwSelBoxes& rBoxes )
+{
+ for( sal_uInt16 i = 0; i < rBoxes.Count(); ++i )
+ {
+ if ( rFrm.GetTabBox() == rBoxes[ i ] )
+ return true;
+ }
+
+ return false;
+}
+
+//
+// SwDoc::GetTabRows()
+//
+
+void SwDoc::GetTabRows( SwTabCols &rFill, const SwCursor* ,
+ const SwCellFrm* pBoxFrm ) const
+{
+ OSL_ENSURE( pBoxFrm, "GetTabRows called without pBoxFrm" );
+
+ // Make code robust:
+ if ( !pBoxFrm )
+ return;
+
+ // --> FME 2005-01-06 #i39552# Collection of the boxes of the current
+ // column has to be done at the beginning of this function, because
+ // the table may be formatted in ::GetTblSel.
+ SwDeletionChecker aDelCheck( pBoxFrm );
+
+ SwSelBoxes aBoxes;
+ const SwCntntFrm* pCntnt = ::GetCellCntnt( *pBoxFrm );
+ if ( pCntnt && pCntnt->IsTxtFrm() )
+ {
+ const SwPosition aPos( *((SwTxtFrm*)pCntnt)->GetTxtNode() );
+ const SwCursor aTmpCrsr( aPos, 0, false );
+ ::GetTblSel( aTmpCrsr, aBoxes, nsSwTblSearchType::TBLSEARCH_COL );
+ }
+ // <--
+
+ // Make code robust:
+ if ( aDelCheck.HasBeenDeleted() )
+ {
+ OSL_FAIL( "Current box has been deleted during GetTabRows()" );
+ return;
+ }
+
+ // Make code robust:
+ const SwTabFrm* pTab = pBoxFrm->FindTabFrm();
+ OSL_ENSURE( pTab, "GetTabRows called without a table" );
+ if ( !pTab )
+ return;
+
+ const SwFrm* pFrm = pTab->GetNextLayoutLeaf();
+
+ //Fix-Punkte setzen, LeftMin in Dokumentkoordinaten die anderen relativ.
+ SWRECTFN( pTab )
+ const SwPageFrm* pPage = pTab->FindPageFrm();
+ const long nLeftMin = ( bVert ?
+ pTab->GetPrtLeft() - pPage->Frm().Left() :
+ pTab->GetPrtTop() - pPage->Frm().Top() );
+ const long nLeft = bVert ? LONG_MAX : 0;
+ const long nRight = (pTab->Prt().*fnRect->fnGetHeight)();
+ const long nRightMax = bVert ? nRight : LONG_MAX;
+
+ rFill.SetLeftMin( nLeftMin );
+ rFill.SetLeft( nLeft );
+ rFill.SetRight( nRight );
+ rFill.SetRightMax( nRightMax );
+
+ typedef std::map< long, std::pair< long, long >, FuzzyCompare > BoundaryMap;
+ BoundaryMap aBoundaries;
+ BoundaryMap::iterator aIter;
+ std::pair< long, long > aPair;
+
+ typedef std::map< long, bool > HiddenMap;
+ HiddenMap aHidden;
+ HiddenMap::iterator aHiddenIter;
+
+ while ( pFrm && pTab->IsAnLower( pFrm ) )
+ {
+ if ( pFrm->IsCellFrm() && pFrm->FindTabFrm() == pTab )
+ {
+ // upper and lower borders of current cell frame:
+ long nUpperBorder = (pFrm->Frm().*fnRect->fnGetTop)();
+ long nLowerBorder = (pFrm->Frm().*fnRect->fnGetBottom)();
+
+ // get boundaries for nUpperBorder:
+ aIter = aBoundaries.find( nUpperBorder );
+ if ( aIter == aBoundaries.end() )
+ {
+ aPair.first = nUpperBorder; aPair.second = LONG_MAX;
+ aBoundaries[ nUpperBorder ] = aPair;
+ }
+
+ // get boundaries for nLowerBorder:
+ aIter = aBoundaries.find( nLowerBorder );
+ if ( aIter == aBoundaries.end() )
+ {
+ aPair.first = nUpperBorder; aPair.second = LONG_MAX;
+ }
+ else
+ {
+ nLowerBorder = (*aIter).first;
+ long nNewLowerBorderUpperBoundary = Max( (*aIter).second.first, nUpperBorder );
+ aPair.first = nNewLowerBorderUpperBoundary; aPair.second = LONG_MAX;
+ }
+ aBoundaries[ nLowerBorder ] = aPair;
+
+ // calculate hidden flags for entry nUpperBorder/nLowerBorder:
+ long nTmpVal = nUpperBorder;
+ for ( sal_uInt8 i = 0; i < 2; ++i )
+ {
+ aHiddenIter = aHidden.find( nTmpVal );
+ if ( aHiddenIter == aHidden.end() )
+ aHidden[ nTmpVal ] = !lcl_IsFrmInColumn( *((SwCellFrm*)pFrm), aBoxes );
+ else
+ {
+ if ( aHidden[ nTmpVal ] &&
+ lcl_IsFrmInColumn( *((SwCellFrm*)pFrm), aBoxes ) )
+ aHidden[ nTmpVal ] = false;
+ }
+ nTmpVal = nLowerBorder;
+ }
+ }
+
+ pFrm = pFrm->GetNextLayoutLeaf();
+ }
+
+ // transfer calculated values from BoundaryMap and HiddenMap into rFill:
+ sal_uInt16 nIdx = 0;
+ for ( aIter = aBoundaries.begin(); aIter != aBoundaries.end(); ++aIter )
+ {
+ const long nTabTop = (pTab->*fnRect->fnGetPrtTop)();
+ const long nKey = (*fnRect->fnYDiff)( (*aIter).first, nTabTop );
+ const std::pair< long, long > aTmpPair = (*aIter).second;
+ const long nFirst = (*fnRect->fnYDiff)( aTmpPair.first, nTabTop );
+ const long nSecond = aTmpPair.second;
+
+ aHiddenIter = aHidden.find( (*aIter).first );
+ const bool bHidden = aHiddenIter != aHidden.end() && (*aHiddenIter).second;
+ rFill.Insert( nKey, nFirst, nSecond, bHidden, nIdx++ );
+ }
+
+ // delete first and last entry
+ OSL_ENSURE( rFill.Count(), "Deleting from empty vector. Fasten your seatbelts!" );
+ // --> FME 2006-01-19 #i60818# There may be only one entry in rFill. Make
+ // code robust by checking count of rFill.
+ if ( rFill.Count() ) rFill.Remove( 0, 1 );
+ if ( rFill.Count() ) rFill.Remove( rFill.Count() - 1 , 1 );
+ // <--
+ rFill.SetLastRowAllowedToChange( !pTab->HasFollowFlowLine() );
+}
+
+void SwDoc::SetTabCols( const SwTabCols &rNew, sal_Bool bCurRowOnly,
+ const SwCursor* pCrsr, const SwCellFrm* pBoxFrm )
+{
+ const SwTableBox* pBox = 0;
+ SwTabFrm *pTab = 0;
+
+ if( pBoxFrm )
+ {
+ pTab = ((SwFrm*)pBoxFrm)->ImplFindTabFrm();
+ pBox = pBoxFrm->GetTabBox();
+ }
+ else if( pCrsr )
+ {
+ const SwCntntNode* pCNd = pCrsr->GetCntntNode();
+ if( !pCNd )
+ return ;
+
+ Point aPt;
+ const SwShellCrsr *pShCrsr = dynamic_cast<const SwShellCrsr*>(pCrsr);
+ if( pShCrsr )
+ aPt = pShCrsr->GetPtPos();
+
+ const SwFrm* pTmpFrm = pCNd->getLayoutFrm( pCNd->GetDoc()->GetCurrentLayout(), &aPt, 0, sal_False );
+ do {
+ pTmpFrm = pTmpFrm->GetUpper();
+ } while ( !pTmpFrm->IsCellFrm() );
+
+ pBoxFrm = (SwCellFrm*)pTmpFrm;
+ pTab = ((SwFrm*)pBoxFrm)->ImplFindTabFrm();
+ pBox = pBoxFrm->GetTabBox();
+ }
+ else if( !pCrsr && !pBoxFrm )
+ {
+ OSL_ENSURE( !this, "einer von beiden muss angegeben werden!" );
+ return ;
+ }
+
+ // sollte die Tabelle noch auf relativen Werten (USHRT_MAX) stehen
+ // dann muss es jetzt auf absolute umgerechnet werden.
+ SwTable& rTab = *pTab->GetTable();
+ const SwFmtFrmSize& rTblFrmSz = rTab.GetFrmFmt()->GetFrmSize();
+ SWRECTFN( pTab )
+ // #i17174# - With fix for #i9040# the shadow size is taken
+ // from the table width. Thus, add its left and right size to current table
+ // printing area width in order to get the correct table size attribute.
+ SwTwips nPrtWidth = (pTab->Prt().*fnRect->fnGetWidth)();
+ {
+ SvxShadowItem aShadow( rTab.GetFrmFmt()->GetShadow() );
+ nPrtWidth += aShadow.CalcShadowSpace( SHADOW_LEFT ) +
+ aShadow.CalcShadowSpace( SHADOW_RIGHT );
+ }
+ if( nPrtWidth != rTblFrmSz.GetWidth() )
+ {
+ SwFmtFrmSize aSz( rTblFrmSz );
+ aSz.SetWidth( nPrtWidth );
+ rTab.GetFrmFmt()->SetFmtAttr( aSz );
+ }
+
+ SwTabCols aOld( rNew.Count() );
+
+ const SwPageFrm* pPage = pTab->FindPageFrm();
+ const sal_uLong nLeftMin = (pTab->Frm().*fnRect->fnGetLeft)() -
+ (pPage->Frm().*fnRect->fnGetLeft)();
+ const sal_uLong nRightMax = (pTab->Frm().*fnRect->fnGetRight)() -
+ (pPage->Frm().*fnRect->fnGetLeft)();
+
+ //Fix-Punkte setzen, LeftMin in Dokumentkoordinaten die anderen relativ.
+ aOld.SetLeftMin ( nLeftMin );
+ aOld.SetLeft ( (pTab->Prt().*fnRect->fnGetLeft)() );
+ aOld.SetRight ( (pTab->Prt().*fnRect->fnGetRight)());
+ aOld.SetRightMax( nRightMax - nLeftMin );
+
+ rTab.GetTabCols( aOld, pBox );
+ SetTabCols(rTab, rNew, aOld, pBox, bCurRowOnly );
+}
+
+void SwDoc::SetTabRows( const SwTabCols &rNew, sal_Bool bCurColOnly, const SwCursor*,
+ const SwCellFrm* pBoxFrm )
+{
+ const SwTableBox* pBox;
+ SwTabFrm *pTab;
+
+ OSL_ENSURE( pBoxFrm, "SetTabRows called without pBoxFrm" );
+
+ pTab = ((SwFrm*)pBoxFrm)->ImplFindTabFrm();
+ pBox = pBoxFrm->GetTabBox();
+
+ // sollte die Tabelle noch auf relativen Werten (USHRT_MAX) stehen
+ // dann muss es jetzt auf absolute umgerechnet werden.
+ SWRECTFN( pTab )
+ SwTabCols aOld( rNew.Count() );
+
+ //Fix-Punkte setzen, LeftMin in Dokumentkoordinaten die anderen relativ.
+ const SwPageFrm* pPage = pTab->FindPageFrm();
+
+ aOld.SetRight( (pTab->Prt().*fnRect->fnGetHeight)() );
+ long nLeftMin;
+ if ( bVert )
+ {
+ nLeftMin = pTab->GetPrtLeft() - pPage->Frm().Left();
+ aOld.SetLeft ( LONG_MAX );
+ aOld.SetRightMax( aOld.GetRight() );
+
+ }
+ else
+ {
+ nLeftMin = pTab->GetPrtTop() - pPage->Frm().Top();
+ aOld.SetLeft ( 0 );
+ aOld.SetRightMax( LONG_MAX );
+ }
+ aOld.SetLeftMin ( nLeftMin );
+
+ GetTabRows( aOld, 0, pBoxFrm );
+
+ GetIDocumentUndoRedo().StartUndo( UNDO_TABLE_ATTR, NULL );
+
+ // check for differences between aOld and rNew:
+ const sal_uInt16 nCount = rNew.Count();
+ const SwTable* pTable = pTab->GetTable();
+ OSL_ENSURE( pTable, "My colleague told me, this couldn't happen" );
+
+ for ( sal_uInt16 i = 0; i <= nCount; ++i )
+ {
+ const sal_uInt16 nIdxStt = bVert ? nCount - i : i - 1;
+ const sal_uInt16 nIdxEnd = bVert ? nCount - i - 1 : i;
+
+ const long nOldRowStart = i == 0 ? 0 : aOld[ nIdxStt ];
+ const long nOldRowEnd = i == nCount ? aOld.GetRight() : aOld[ nIdxEnd ];
+ const long nOldRowHeight = nOldRowEnd - nOldRowStart;
+
+ const long nNewRowStart = i == 0 ? 0 : rNew[ nIdxStt ];
+ const long nNewRowEnd = i == nCount ? rNew.GetRight() : rNew[ nIdxEnd ];
+ const long nNewRowHeight = nNewRowEnd - nNewRowStart;
+
+ const long nDiff = nNewRowHeight - nOldRowHeight;
+ if ( abs( nDiff ) >= ROWFUZZY )
+ {
+ // For the old table model pTxtFrm and pLine will be set for every box.
+ // For the new table model pTxtFrm will be set if the box is not covered,
+ // but the pLine will be set if the box is not an overlapping box
+ // In the new table model the row height can be adjusted,
+ // when both variables are set.
+ SwTxtFrm* pTxtFrm = 0;
+ const SwTableLine* pLine = 0;
+
+ // Iterate over all SwCellFrms with Bottom = nOldPos
+ const SwFrm* pFrm = pTab->GetNextLayoutLeaf();
+ while ( pFrm && pTab->IsAnLower( pFrm ) )
+ {
+ if ( pFrm->IsCellFrm() && pFrm->FindTabFrm() == pTab )
+ {
+ const long nLowerBorder = (pFrm->Frm().*fnRect->fnGetBottom)();
+ const sal_uLong nTabTop = (pTab->*fnRect->fnGetPrtTop)();
+ if ( abs( (*fnRect->fnYInc)( nTabTop, nOldRowEnd ) - nLowerBorder ) <= ROWFUZZY )
+ {
+ if ( !bCurColOnly || pFrm == pBoxFrm )
+ {
+ const SwFrm* pCntnt = ::GetCellCntnt( static_cast<const SwCellFrm&>(*pFrm) );
+
+ if ( pCntnt && pCntnt->IsTxtFrm() )
+ {
+ pBox = ((SwCellFrm*)pFrm)->GetTabBox();
+ const long nRowSpan = pBox->getRowSpan();
+ if( nRowSpan > 0 ) // Not overlapped
+ pTxtFrm = (SwTxtFrm*)pCntnt;
+ if( nRowSpan < 2 ) // Not overlapping for row height
+ pLine = pBox->GetUpper();
+ if( pLine && pTxtFrm ) // always for old table model
+ {
+ // The new row height must not to be calculated from a overlapping box
+ SwFmtFrmSize aNew( pLine->GetFrmFmt()->GetFrmSize() );
+ const long nNewSize = (pFrm->Frm().*fnRect->fnGetHeight)() + nDiff;
+ if( nNewSize != aNew.GetHeight() )
+ {
+ aNew.SetHeight( nNewSize );
+ if ( ATT_VAR_SIZE == aNew.GetHeightSizeType() )
+ aNew.SetHeightSizeType( ATT_MIN_SIZE );
+ // This position must not be in an overlapped box
+ const SwPosition aPos( *((SwTxtFrm*)pCntnt)->GetTxtNode() );
+ const SwCursor aTmpCrsr( aPos, 0, false );
+ SetRowHeight( aTmpCrsr, aNew );
+ // For the new table model we're done, for the old one
+ // there might be another (sub)row to adjust...
+ if( pTable->IsNewModel() )
+ break;
+ }
+ pLine = 0;
+ }
+ }
+ }
+ }
+ }
+ pFrm = pFrm->GetNextLayoutLeaf();
+ }
+ }
+ }
+
+ GetIDocumentUndoRedo().EndUndo( UNDO_TABLE_ATTR, NULL );
+
+ ::ClearFEShellTabCols();
+}
+
+/* --------------------------------------------------
+ * Direktzugriff fuer UNO
+ * --------------------------------------------------*/
+void SwDoc::SetTabCols(SwTable& rTab, const SwTabCols &rNew, const SwTabCols &rOld,
+ const SwTableBox *pStart, sal_Bool bCurRowOnly )
+{
+ if (GetIDocumentUndoRedo().DoesUndo())
+ {
+ GetIDocumentUndoRedo().AppendUndo(
+ new SwUndoAttrTbl( *rTab.GetTableNode(), sal_True ));
+ }
+ rTab.SetTabCols( rNew, rOld, pStart, bCurRowOnly );
+ ::ClearFEShellTabCols();
+ SetModified();
+}
+
+void SwDoc::SetRowsToRepeat( SwTable &rTable, sal_uInt16 nSet )
+{
+ if( nSet == rTable.GetRowsToRepeat() )
+ return;
+
+ if (GetIDocumentUndoRedo().DoesUndo())
+ {
+ GetIDocumentUndoRedo().AppendUndo(
+ new SwUndoTblHeadline(rTable, rTable.GetRowsToRepeat(), nSet) );
+ }
+
+ SwMsgPoolItem aChg( RES_TBLHEADLINECHG );
+ rTable.SetRowsToRepeat( nSet );
+ rTable.GetFrmFmt()->ModifyNotification( &aChg, &aChg );
+ SetModified();
+}
+
+
+
+
+// Splittet eine Tabelle in der Grund-Zeile, in der der Index steht.
+// Alle GrundZeilen dahinter wandern in eine neue Tabelle/-Node.
+// Ist das Flag bCalcNewSize auf sal_True, wird fuer beide neuen Tabellen
+// die neue Size aus dem Max der Boxen errechnet; vorrausgesetzt,
+// die Size ist "absolut" gesetzt (USHRT_MAX)
+
+void SwCollectTblLineBoxes::AddToUndoHistory( const SwCntntNode& rNd )
+{
+ if( pHst )
+ pHst->Add( rNd.GetFmtColl(), rNd.GetIndex(), ND_TEXTNODE );
+}
+
+void SwCollectTblLineBoxes::AddBox( const SwTableBox& rBox )
+{
+ aPosArr.Insert( nWidth, aPosArr.Count() );
+ SwTableBox* p = (SwTableBox*)&rBox;
+ aBoxes.Insert( p, aBoxes.Count() );
+ nWidth = nWidth + (sal_uInt16)rBox.GetFrmFmt()->GetFrmSize().GetWidth();
+}
+
+const SwTableBox* SwCollectTblLineBoxes::GetBoxOfPos( const SwTableBox& rBox )
+{
+ const SwTableBox* pRet = 0;
+ sal_uInt16 n;
+
+ if( aPosArr.Count() )
+ {
+ for( n = 0; n < aPosArr.Count(); ++n )
+ if( aPosArr[ n ] == nWidth )
+ break;
+ else if( aPosArr[ n ] > nWidth )
+ {
+ if( n )
+ --n;
+ break;
+ }
+
+ if( n >= aPosArr.Count() )
+ --n;
+
+ nWidth = nWidth + (sal_uInt16)rBox.GetFrmFmt()->GetFrmSize().GetWidth();
+ pRet = aBoxes[ n ];
+ }
+ return pRet;
+}
+
+sal_Bool SwCollectTblLineBoxes::Resize( sal_uInt16 nOffset, sal_uInt16 nOldWidth )
+{
+ sal_uInt16 n;
+
+ if( aPosArr.Count() )
+ {
+ for( n = 0; n < aPosArr.Count(); ++n )
+ if( aPosArr[ n ] == nOffset )
+ break;
+ else if( aPosArr[ n ] > nOffset )
+ {
+ if( n )
+ --n;
+ break;
+ }
+
+ aPosArr.Remove( 0, n );
+ aBoxes.Remove( 0, n );
+
+ // dann die Positionen der neuen Size anpassen
+ for( n = 0; n < aPosArr.Count(); ++n )
+ {
+ sal_uLong nSize = nWidth;
+ nSize *= ( aPosArr[ n ] - nOffset );
+ nSize /= nOldWidth;
+ aPosArr[ n ] = sal_uInt16( nSize );
+ }
+ }
+ return 0 != aPosArr.Count();
+}
+
+sal_Bool lcl_Line_CollectBox( const SwTableLine*& rpLine, void* pPara )
+{
+ SwCollectTblLineBoxes* pSplPara = (SwCollectTblLineBoxes*)pPara;
+ if( pSplPara->IsGetValues() )
+ ((SwTableLine*)rpLine)->GetTabBoxes().ForEach( &lcl_Box_CollectBox, pPara );
+ else
+ ((SwTableLine*)rpLine)->GetTabBoxes().ForEach( &lcl_BoxSetSplitBoxFmts, pPara );
+ return sal_True;
+}
+
+sal_Bool lcl_Box_CollectBox( const SwTableBox*& rpBox, void* pPara )
+{
+ SwCollectTblLineBoxes* pSplPara = (SwCollectTblLineBoxes*)pPara;
+ sal_uInt16 nLen = rpBox->GetTabLines().Count();
+ if( nLen )
+ {
+ // dann mit der richtigen Line weitermachen
+ if( pSplPara->IsGetFromTop() )
+ nLen = 0;
+ else
+ --nLen;
+
+ const SwTableLine* pLn = rpBox->GetTabLines()[ nLen ];
+ lcl_Line_CollectBox( pLn, pPara );
+ }
+ else
+ pSplPara->AddBox( *rpBox );
+ return sal_True;
+}
+
+sal_Bool lcl_BoxSetSplitBoxFmts( const SwTableBox*& rpBox, void* pPara )
+{
+ SwCollectTblLineBoxes* pSplPara = (SwCollectTblLineBoxes*)pPara;
+ sal_uInt16 nLen = rpBox->GetTabLines().Count();
+ if( nLen )
+ {
+ // dann mit der richtigen Line weitermachen
+ if( pSplPara->IsGetFromTop() )
+ nLen = 0;
+ else
+ --nLen;
+
+ const SwTableLine* pLn = rpBox->GetTabLines()[ nLen ];
+ lcl_Line_CollectBox( pLn, pPara );
+ }
+ else
+ {
+ const SwTableBox* pSrcBox = pSplPara->GetBoxOfPos( *rpBox );
+ SwFrmFmt* pFmt = pSrcBox->GetFrmFmt();
+ SwTableBox* pBox = (SwTableBox*)rpBox;
+
+ if( HEADLINE_BORDERCOPY == pSplPara->GetMode() )
+ {
+ const SvxBoxItem& rBoxItem = pBox->GetFrmFmt()->GetBox();
+ if( !rBoxItem.GetTop() )
+ {
+ SvxBoxItem aNew( rBoxItem );
+ aNew.SetLine( pFmt->GetBox().GetBottom(), BOX_LINE_TOP );
+ if( aNew != rBoxItem )
+ pBox->ClaimFrmFmt()->SetFmtAttr( aNew );
+ }
+ }
+ else
+ {
+sal_uInt16 aTableSplitBoxSetRange[] = {
+ RES_LR_SPACE, RES_UL_SPACE,
+ RES_BACKGROUND, RES_SHADOW,
+ RES_PROTECT, RES_PROTECT,
+ RES_VERT_ORIENT, RES_VERT_ORIENT,
+ 0 };
+ SfxItemSet aTmpSet( pFmt->GetDoc()->GetAttrPool(),
+ aTableSplitBoxSetRange );
+ aTmpSet.Put( pFmt->GetAttrSet() );
+ if( aTmpSet.Count() )
+ pBox->ClaimFrmFmt()->SetFmtAttr( aTmpSet );
+
+ if( HEADLINE_BOXATRCOLLCOPY == pSplPara->GetMode() )
+ {
+ SwNodeIndex aIdx( *pSrcBox->GetSttNd(), 1 );
+ SwCntntNode* pCNd = aIdx.GetNode().GetCntntNode();
+ if( !pCNd )
+ pCNd = aIdx.GetNodes().GoNext( &aIdx );
+ aIdx = *pBox->GetSttNd();
+ SwCntntNode* pDNd = aIdx.GetNodes().GoNext( &aIdx );
+
+ // nur wenn der Node alleine in der Section steht
+ if( 2 == pDNd->EndOfSectionIndex() -
+ pDNd->StartOfSectionIndex() )
+ {
+ pSplPara->AddToUndoHistory( *pDNd );
+ pDNd->ChgFmtColl( pCNd->GetFmtColl() );
+ }
+ }
+
+ // bedingte Vorlage beachten
+ pBox->GetSttNd()->CheckSectionCondColl();
+ }
+ }
+ return sal_True;
+}
+
+
+sal_Bool SwDoc::SplitTable( const SwPosition& rPos, sal_uInt16 eHdlnMode,
+ sal_Bool bCalcNewSize )
+{
+ SwNode* pNd = &rPos.nNode.GetNode();
+ SwTableNode* pTNd = pNd->FindTableNode();
+ if( !pTNd || pNd->IsTableNode() )
+ return 0;
+
+ if( pTNd->GetTable().ISA( SwDDETable ))
+ return sal_False;
+
+ SwTable& rTbl = pTNd->GetTable();
+ rTbl.SetHTMLTableLayout( 0 ); // MIB 9.7.97: HTML-Layout loeschen
+
+ SwTableFmlUpdate aMsgHnt( &rTbl );
+
+ SwHistory aHistory;
+ if (GetIDocumentUndoRedo().DoesUndo())
+ {
+ aMsgHnt.pHistory = &aHistory;
+ }
+
+ {
+ sal_uLong nSttIdx = pNd->FindTableBoxStartNode()->GetIndex();
+
+ // Suche die Grund-Line dieser Box:
+ SwTableBox* pBox = rTbl.GetTblBox( nSttIdx );
+ if( pBox )
+ {
+ SwTableLine* pLine = pBox->GetUpper();
+ while( pLine->GetUpper() )
+ pLine = pLine->GetUpper()->GetUpper();
+
+ // in pLine steht jetzt die GrundLine.
+ aMsgHnt.nSplitLine = rTbl.GetTabLines().C40_GETPOS( SwTableLine, pLine );
+ }
+
+ String sNewTblNm( GetUniqueTblName() );
+ aMsgHnt.DATA.pNewTblNm = &sNewTblNm;
+ aMsgHnt.eFlags = TBL_SPLITTBL;
+ UpdateTblFlds( &aMsgHnt );
+ }
+
+ //Lines fuer das Layout-Update heraussuchen.
+ _FndBox aFndBox( 0, 0 );
+ aFndBox.SetTableLines( rTbl );
+ aFndBox.DelFrms( rTbl );
+
+ SwTableNode* pNew = GetNodes().SplitTable( rPos.nNode, sal_False, bCalcNewSize );
+
+ if( pNew )
+ {
+ SwSaveRowSpan* pSaveRowSp = pNew->GetTable().CleanUpTopRowSpan( rTbl.GetTabLines().Count() );
+ SwUndoSplitTbl* pUndo = 0;
+ if (GetIDocumentUndoRedo().DoesUndo())
+ {
+ pUndo = new SwUndoSplitTbl(
+ *pNew, pSaveRowSp, eHdlnMode, bCalcNewSize);
+ GetIDocumentUndoRedo().AppendUndo(pUndo);
+ if( aHistory.Count() )
+ pUndo->SaveFormula( aHistory );
+ }
+
+ switch( eHdlnMode )
+ {
+ // setze die untere Border der vorherige Line,
+ // an der aktuellen als obere
+ case HEADLINE_BORDERCOPY:
+ {
+ SwCollectTblLineBoxes aPara( sal_False, eHdlnMode );
+ SwTableLine* pLn = rTbl.GetTabLines()[
+ rTbl.GetTabLines().Count() - 1 ];
+ pLn->GetTabBoxes().ForEach( &lcl_Box_CollectBox, &aPara );
+
+ aPara.SetValues( sal_True );
+ pLn = pNew->GetTable().GetTabLines()[ 0 ];
+ pLn->GetTabBoxes().ForEach( &lcl_BoxSetSplitBoxFmts, &aPara );
+
+ // Kopfzeile wiederholen abschalten
+ pNew->GetTable().SetRowsToRepeat( 0 );
+ }
+ break;
+
+ // setze die Attributierung der ersten Line an der neuen ersten
+ case HEADLINE_BOXATTRCOPY:
+ case HEADLINE_BOXATRCOLLCOPY:
+ {
+ SwHistory* pHst = 0;
+ if( HEADLINE_BOXATRCOLLCOPY == eHdlnMode && pUndo )
+ pHst = pUndo->GetHistory();
+
+ SwCollectTblLineBoxes aPara( sal_True, eHdlnMode, pHst );
+ SwTableLine* pLn = rTbl.GetTabLines()[ 0 ];
+ pLn->GetTabBoxes().ForEach( &lcl_Box_CollectBox, &aPara );
+
+ aPara.SetValues( sal_True );
+ pLn = pNew->GetTable().GetTabLines()[ 0 ];
+ pLn->GetTabBoxes().ForEach( &lcl_BoxSetSplitBoxFmts, &aPara );
+ }
+ break;
+
+ case HEADLINE_CNTNTCOPY:
+ rTbl.CopyHeadlineIntoTable( *pNew );
+ if( pUndo )
+ pUndo->SetTblNodeOffset( pNew->GetIndex() );
+ break;
+
+ case HEADLINE_NONE:
+ // Kopfzeile wiederholen abschalten
+ pNew->GetTable().SetRowsToRepeat( 0 );
+ break;
+ }
+
+ // und Frms einfuegen.
+ SwNodeIndex aNdIdx( *pNew->EndOfSectionNode() );
+ GetNodes().GoNext( &aNdIdx ); // zum naechsten ContentNode
+ pNew->MakeFrms( &aNdIdx );
+
+ //Zwischen die Tabellen wird ein Absatz geschoben
+ GetNodes().MakeTxtNode( SwNodeIndex( *pNew ),
+ GetTxtCollFromPool( RES_POOLCOLL_TEXT ) );
+ }
+
+ //Layout updaten
+ aFndBox.MakeFrms( rTbl );
+
+ // TL_CHART2: need to inform chart of probably changed cell names
+ UpdateCharts( rTbl.GetFrmFmt()->GetName() );
+
+ SetFieldsDirty( true, NULL, 0 );
+
+ return 0 != pNew;
+}
+
+sal_Bool lcl_ChgTblSize( SwTable& rTbl )
+{
+ // das Attribut darf nicht ueber das Modify an der
+ // Tabelle gesetzt werden, denn sonst werden alle
+ // Boxen wieder auf 0 zurueck gesetzt. Also locke das Format
+ SwFrmFmt* pFmt = rTbl.GetFrmFmt();
+ SwFmtFrmSize aTblMaxSz( pFmt->GetFrmSize() );
+
+ if( USHRT_MAX == aTblMaxSz.GetWidth() )
+ return sal_False;
+
+ sal_Bool bLocked = pFmt->IsModifyLocked();
+ pFmt->LockModify();
+
+ aTblMaxSz.SetWidth( 0 );
+
+ SwTableLines& rLns = rTbl.GetTabLines();
+ for( sal_uInt16 nLns = 0; nLns < rLns.Count(); ++nLns )
+ {
+ SwTwips nMaxLnWidth = 0;
+ SwTableBoxes& rBoxes = rLns[ nLns ]->GetTabBoxes();
+ for( sal_uInt16 nBox = 0; nBox < rBoxes.Count(); ++nBox )
+ nMaxLnWidth += rBoxes[nBox]->GetFrmFmt()->GetFrmSize().GetWidth();
+
+ if( nMaxLnWidth > aTblMaxSz.GetWidth() )
+ aTblMaxSz.SetWidth( nMaxLnWidth );
+ }
+ pFmt->SetFmtAttr( aTblMaxSz );
+ if( !bLocked ) // und gegebenenfalls Lock wieder freigeben
+ pFmt->UnlockModify();
+
+ return sal_True;
+}
+
+class _SplitTable_Para
+{
+ SvPtrarr aSrc, aDest;
+ SwTableNode* pNewTblNd;
+ SwTable& rOldTbl;
+
+public:
+ _SplitTable_Para( SwTableNode* pNew, SwTable& rOld )
+ : aSrc( 16, 16 ), aDest( 16, 16 ), pNewTblNd( pNew ), rOldTbl( rOld )
+ {}
+ sal_uInt16 SrcFmt_GetPos( void* pFmt ) const
+ { return aSrc.GetPos( pFmt ); }
+
+ void DestFmt_Insert( void* pFmt )
+ { aDest.Insert( pFmt, aDest.Count() ); }
+
+ void SrcFmt_Insert( void* pFmt )
+ { aSrc.Insert( pFmt, aSrc.Count() ); }
+
+ SwFrmFmt* DestFmt_Get( sal_uInt16 nPos ) const
+ { return (SwFrmFmt*)aDest[ nPos ]; }
+
+ void ChgBox( SwTableBox* pBox )
+ {
+ rOldTbl.GetTabSortBoxes().Remove( pBox );
+ pNewTblNd->GetTable().GetTabSortBoxes().Insert( pBox );
+ }
+};
+
+
+sal_Bool lcl_SplitTable_CpyBox( const SwTableBox*& rpBox, void* pPara );
+
+sal_Bool lcl_SplitTable_CpyLine( const SwTableLine*& rpLine, void* pPara )
+{
+ SwTableLine* pLn = (SwTableLine*)rpLine;
+ _SplitTable_Para& rPara = *(_SplitTable_Para*)pPara;
+
+ SwFrmFmt *pSrcFmt = pLn->GetFrmFmt();
+ sal_uInt16 nPos = rPara.SrcFmt_GetPos( pSrcFmt );
+ if( USHRT_MAX == nPos )
+ {
+ rPara.DestFmt_Insert( pLn->ClaimFrmFmt() );
+ rPara.SrcFmt_Insert( pSrcFmt );
+ }
+ else
+ pLn->ChgFrmFmt( (SwTableLineFmt*)rPara.DestFmt_Get( nPos ) );
+
+ pLn->GetTabBoxes().ForEach( &lcl_SplitTable_CpyBox, pPara );
+ return sal_True;
+}
+
+sal_Bool lcl_SplitTable_CpyBox( const SwTableBox*& rpBox, void* pPara )
+{
+ SwTableBox* pBox = (SwTableBox*)rpBox;
+ _SplitTable_Para& rPara = *(_SplitTable_Para*)pPara;
+
+ SwFrmFmt *pSrcFmt = pBox->GetFrmFmt();
+ sal_uInt16 nPos = rPara.SrcFmt_GetPos( pSrcFmt );
+ if( USHRT_MAX == nPos )
+ {
+ rPara.DestFmt_Insert( pBox->ClaimFrmFmt() );
+ rPara.SrcFmt_Insert( pSrcFmt );
+ }
+ else
+ pBox->ChgFrmFmt( (SwTableBoxFmt*)rPara.DestFmt_Get( nPos ) );
+
+ if( pBox->GetSttNd() )
+ rPara.ChgBox( pBox );
+ else
+ pBox->GetTabLines().ForEach( &lcl_SplitTable_CpyLine, pPara );
+ return sal_True;
+}
+
+SwTableNode* SwNodes::SplitTable( const SwNodeIndex& rPos, sal_Bool bAfter,
+ sal_Bool bCalcNewSize )
+{
+ SwNode* pNd = &rPos.GetNode();
+ SwTableNode* pTNd = pNd->FindTableNode();
+ if( !pTNd || pNd->IsTableNode() )
+ return 0;
+
+ sal_uLong nSttIdx = pNd->FindTableBoxStartNode()->GetIndex();
+
+ // Suche die Grund-Line dieser Box:
+ SwTable& rTbl = pTNd->GetTable();
+ SwTableBox* pBox = rTbl.GetTblBox( nSttIdx );
+ if( !pBox )
+ return 0;
+
+ SwTableLine* pLine = pBox->GetUpper();
+ while( pLine->GetUpper() )
+ pLine = pLine->GetUpper()->GetUpper();
+
+ // in pLine steht jetzt die GrundLine.
+ sal_uInt16 nLinePos = rTbl.GetTabLines().C40_GETPOS( SwTableLine, pLine );
+ if( USHRT_MAX == nLinePos ||
+ ( bAfter ? ++nLinePos >= rTbl.GetTabLines().Count() : !nLinePos ))
+ return 0; // nicht gefunden oder letze Line !!
+
+ // Suche jetzt die 1. Box der nachfolgenden Line
+ SwTableLine* pNextLine = rTbl.GetTabLines()[ nLinePos ];
+ pBox = pNextLine->GetTabBoxes()[0];
+ while( !pBox->GetSttNd() )
+ pBox = pBox->GetTabLines()[0]->GetTabBoxes()[0];
+
+ // dann fuege mal einen End- und TabelleNode ins Nodes-Array ein.
+ SwTableNode * pNewTblNd;
+ {
+ SwEndNode* pOldTblEndNd = (SwEndNode*)pTNd->EndOfSectionNode()->GetEndNode();
+ OSL_ENSURE( pOldTblEndNd, "wo ist der EndNode?" );
+
+ SwNodeIndex aIdx( *pBox->GetSttNd() );
+ new SwEndNode( aIdx, *pTNd );
+ pNewTblNd = new SwTableNode( aIdx );
+ pNewTblNd->GetTable().SetTableModel( rTbl.IsNewModel() );
+
+ pOldTblEndNd->pStartOfSection = pNewTblNd;
+ pNewTblNd->pEndOfSection = pOldTblEndNd;
+
+ SwNode* pBoxNd = aIdx.GetNode().GetStartNode();
+ do {
+ OSL_ENSURE( pBoxNd->IsStartNode(), "das muss ein StartNode sein!" );
+ pBoxNd->pStartOfSection = pNewTblNd;
+ pBoxNd = (*this)[ pBoxNd->EndOfSectionIndex() + 1 ];
+ } while( pBoxNd != pOldTblEndNd );
+ }
+
+ {
+ // die Lines ruebermoven...
+ SwTable& rNewTbl = pNewTblNd->GetTable();
+ rNewTbl.GetTabLines().Insert( &rTbl.GetTabLines(), 0, nLinePos );
+ //
+ // von hinten (unten-rechts) nach vorn (oben-links) alle Boxen
+ // beim chart data provider austragen (das modified event wird dann
+ // in der aufrufenden Funktion getriggert.
+ // TL_CHART2:
+ SwChartDataProvider *pPCD = rTbl.GetFrmFmt()->getIDocumentChartDataProviderAccess()->GetChartDataProvider();
+ if( pPCD )
+ {
+ for (sal_uInt16 k = nLinePos; k < rTbl.GetTabLines().Count(); ++k)
+ {
+ sal_uInt16 nLineIdx = (rTbl.GetTabLines().Count() - 1) - k + nLinePos;
+ sal_uInt16 nBoxCnt = rTbl.GetTabLines()[ nLineIdx ]->GetTabBoxes().Count();
+ for (sal_uInt16 j = 0; j < nBoxCnt; ++j)
+ {
+ sal_uInt16 nIdx = nBoxCnt - 1 - j;
+ pPCD->DeleteBox( &rTbl, *rTbl.GetTabLines()[ nLineIdx ]->GetTabBoxes()[nIdx] );
+ }
+ }
+ }
+ //
+ // ...und loeschen
+ sal_uInt16 nDeleted = rTbl.GetTabLines().Count() - nLinePos;
+ rTbl.GetTabLines().Remove( nLinePos, nDeleted );
+
+ // und die betr. Boxen verschieben. Dabei die Formate eindeutig
+ // machen und die StartNodes korrigieren
+ _SplitTable_Para aPara( pNewTblNd, rTbl );
+ rNewTbl.GetTabLines().ForEach( &lcl_SplitTable_CpyLine, &aPara );
+ rTbl.CleanUpBottomRowSpan( nDeleted );
+ }
+
+ {
+ // Das Tabellen-FrmFormat kopieren
+ SwFrmFmt* pOldTblFmt = rTbl.GetFrmFmt();
+ SwFrmFmt* pNewTblFmt = pOldTblFmt->GetDoc()->MakeTblFrmFmt(
+ pOldTblFmt->GetDoc()->GetUniqueTblName(),
+ pOldTblFmt->GetDoc()->GetDfltFrmFmt() );
+
+ *pNewTblFmt = *pOldTblFmt;
+ pNewTblNd->GetTable().RegisterToFormat( *pNewTblFmt );
+
+ // neue Size errechnen ? (lcl_ChgTblSize nur das 2. aufrufen, wenn es
+ // beim 1. schon geklappt hat; also absolute Groesse hat)
+ if( bCalcNewSize && lcl_ChgTblSize( rTbl ) )
+ lcl_ChgTblSize( pNewTblNd->GetTable() );
+ }
+
+ // TL_CHART2: need to inform chart of probably changed cell names
+ rTbl.UpdateCharts();
+
+ return pNewTblNd; // das wars
+}
+
+// und die Umkehrung davon. rPos muss in der Tabelle stehen, die bestehen
+// bleibt. Das Flag besagt ob die aktuelle mit der davor oder dahinter
+// stehenden vereint wird.
+sal_Bool SwDoc::MergeTable( const SwPosition& rPos, sal_Bool bWithPrev, sal_uInt16 nMode )
+{
+ SwTableNode* pTblNd = rPos.nNode.GetNode().FindTableNode(), *pDelTblNd;
+ if( !pTblNd )
+ return sal_False;
+
+ SwNodes& rNds = GetNodes();
+ if( bWithPrev )
+ pDelTblNd = rNds[ pTblNd->GetIndex() - 1 ]->FindTableNode();
+ else
+ pDelTblNd = rNds[ pTblNd->EndOfSectionIndex() + 1 ]->GetTableNode();
+ if( !pDelTblNd )
+ return sal_False;
+
+ if( pTblNd->GetTable().ISA( SwDDETable ) ||
+ pDelTblNd->GetTable().ISA( SwDDETable ))
+ return sal_False;
+
+ // MIB 9.7.97: HTML-Layout loeschen
+ pTblNd->GetTable().SetHTMLTableLayout( 0 );
+ pDelTblNd->GetTable().SetHTMLTableLayout( 0 );
+
+ // beide Tabellen vorhanden, also kanns losgehen
+ SwUndoMergeTbl* pUndo = 0;
+ SwHistory* pHistory = 0;
+ if (GetIDocumentUndoRedo().DoesUndo())
+ {
+ pUndo = new SwUndoMergeTbl( *pTblNd, *pDelTblNd, bWithPrev, nMode );
+ GetIDocumentUndoRedo().AppendUndo(pUndo);
+ pHistory = new SwHistory;
+ }
+
+ // alle "Tabellenformeln" anpassen
+ SwTableFmlUpdate aMsgHnt( &pTblNd->GetTable() );
+ aMsgHnt.DATA.pDelTbl = &pDelTblNd->GetTable();
+ aMsgHnt.eFlags = TBL_MERGETBL;
+ aMsgHnt.pHistory = pHistory;
+ UpdateTblFlds( &aMsgHnt );
+
+ // das eigentliche Mergen
+ SwNodeIndex aIdx( bWithPrev ? *pTblNd : *pDelTblNd );
+ sal_Bool bRet = rNds.MergeTable( aIdx, !bWithPrev, nMode, pHistory );
+
+ if( pHistory )
+ {
+ if( pHistory->Count() )
+ pUndo->SaveFormula( *pHistory );
+ delete pHistory;
+ }
+ if( bRet )
+ {
+ SetModified();
+ SetFieldsDirty( true, NULL, 0 );
+ }
+ return bRet;
+}
+
+sal_Bool SwNodes::MergeTable( const SwNodeIndex& rPos, sal_Bool bWithPrev,
+ sal_uInt16 nMode, SwHistory* )
+{
+ SwTableNode* pDelTblNd = rPos.GetNode().GetTableNode();
+ OSL_ENSURE( pDelTblNd, "wo ist der TableNode geblieben?" );
+
+ SwTableNode* pTblNd = (*this)[ rPos.GetIndex() - 1]->FindTableNode();
+ OSL_ENSURE( pTblNd, "wo ist der TableNode geblieben?" );
+
+ if( !pDelTblNd || !pTblNd )
+ return sal_False;
+
+ pDelTblNd->DelFrms();
+
+ SwTable& rDelTbl = pDelTblNd->GetTable();
+ SwTable& rTbl = pTblNd->GetTable();
+
+ //Lines fuer das Layout-Update herausuchen.
+ _FndBox aFndBox( 0, 0 );
+ aFndBox.SetTableLines( rTbl );
+ aFndBox.DelFrms( rTbl );
+
+ // TL_CHART2: since chart currently does not want to get informed about
+ // additional rows/cols there is no need for a modified event in the
+ // remaining first table. Also, if it is required it should be done
+ // after the merging and not here...
+ // pDoc->UpdateCharts( rTbl.GetFrmFmt()->GetName() );
+
+
+ // TL_CHART2:
+ // tell the charts about the table to be deleted and have them use their own data
+ GetDoc()->CreateChartInternalDataProviders( &rDelTbl );
+
+ // die Breite der TabellenFormate abgleichen:
+ {
+ const SwFmtFrmSize& rTblSz = rTbl.GetFrmFmt()->GetFrmSize();
+ const SwFmtFrmSize& rDelTblSz = rDelTbl.GetFrmFmt()->GetFrmSize();
+ if( rTblSz != rDelTblSz )
+ {
+ // dann sollten die mal schleunigst korrigiert werden
+ if( bWithPrev )
+ rDelTbl.GetFrmFmt()->SetFmtAttr( rTblSz );
+ else
+ rTbl.GetFrmFmt()->SetFmtAttr( rDelTblSz );
+ }
+ }
+
+ if( !bWithPrev )
+ {
+ // dann mussen alle Attruibute der hinteren Tabelle auf die
+ // vordere uebertragen werden, weil die hintere ueber das loeschen
+ // des Node geloescht wird.
+ rTbl.SetRowsToRepeat( rDelTbl.GetRowsToRepeat() );
+ rTbl.SetTblChgMode( rDelTbl.GetTblChgMode() );
+
+ rTbl.GetFrmFmt()->LockModify();
+ *rTbl.GetFrmFmt() = *rDelTbl.GetFrmFmt();
+ // auch den Namen umsetzen!
+ rTbl.GetFrmFmt()->SetName( rDelTbl.GetFrmFmt()->GetName() );
+ rTbl.GetFrmFmt()->UnlockModify();
+ }
+
+ // die Lines und Boxen ruebermoven
+ sal_uInt16 nOldSize = rTbl.GetTabLines().Count();
+ rTbl.GetTabLines().Insert( &rDelTbl.GetTabLines(), nOldSize );
+ rDelTbl.GetTabLines().Remove( 0, rDelTbl.GetTabLines().Count() );
+
+ rTbl.GetTabSortBoxes().Insert( &rDelTbl.GetTabSortBoxes() );
+ rDelTbl.GetTabSortBoxes().Remove( (sal_uInt16)0, rDelTbl.GetTabSortBoxes().Count() );
+
+ // die vordere Tabelle bleibt immer stehen, die hintere wird geloescht
+ SwEndNode* pTblEndNd = pDelTblNd->EndOfSectionNode();
+ pTblNd->pEndOfSection = pTblEndNd;
+
+ SwNodeIndex aIdx( *pDelTblNd, 1 );
+
+ SwNode* pBoxNd = aIdx.GetNode().GetStartNode();
+ do {
+ OSL_ENSURE( pBoxNd->IsStartNode(), "das muss ein StartNode sein!" );
+ pBoxNd->pStartOfSection = pTblNd;
+ pBoxNd = (*this)[ pBoxNd->EndOfSectionIndex() + 1 ];
+ } while( pBoxNd != pTblEndNd );
+ pBoxNd->pStartOfSection = pTblNd;
+
+ aIdx -= 2;
+ DelNodes( aIdx, 2 );
+
+ // jetzt an der 1. eingefuegten Line die bedingten Vorlagen umschubsen
+ const SwTableLine* pFirstLn = rTbl.GetTabLines()[ nOldSize ];
+ if( 1 == nMode ) //
+ {
+ // Header-Vorlagen in der Zeile setzen
+ // und ggfs. in der History speichern fuers Undo!!!
+ }
+ lcl_LineSetHeadCondColl( pFirstLn, 0 );
+
+ // und die Borders "aufrauemen"
+ if( nOldSize )
+ {
+ _SwGCLineBorder aPara( rTbl );
+ aPara.nLinePos = --nOldSize;
+ pFirstLn = rTbl.GetTabLines()[ nOldSize ];
+ lcl_GC_Line_Border( pFirstLn, &aPara );
+ }
+
+ //Layout updaten
+ aFndBox.MakeFrms( rTbl );
+
+ return sal_True;
+}
+
+// -------------------------------------------------------------------
+
+
+// -- benutze die ForEach Methode vom PtrArray
+struct _SetAFmtTabPara
+{
+ SwTableAutoFmt& rTblFmt;
+ SwUndoTblAutoFmt* pUndo;
+ sal_uInt16 nEndBox, nCurBox;
+ sal_uInt8 nAFmtLine, nAFmtBox;
+
+ _SetAFmtTabPara( const SwTableAutoFmt& rNew )
+ : rTblFmt( (SwTableAutoFmt&)rNew ), pUndo( 0 ),
+ nEndBox( 0 ), nCurBox( 0 ), nAFmtLine( 0 ), nAFmtBox( 0 )
+ {}
+};
+
+// forward deklarieren damit sich die Lines und Boxen rekursiv aufrufen
+// koennen.
+sal_Bool lcl_SetAFmtBox( const _FndBox*&, void *pPara );
+sal_Bool lcl_SetAFmtLine( const _FndLine*&, void *pPara );
+
+sal_Bool lcl_SetAFmtLine( const _FndLine*& rpLine, void *pPara )
+{
+ ((_FndLine*&)rpLine)->GetBoxes().ForEach( &lcl_SetAFmtBox, pPara );
+ return sal_True;
+}
+
+sal_Bool lcl_SetAFmtBox( const _FndBox*& rpBox, void *pPara )
+{
+ _SetAFmtTabPara* pSetPara = (_SetAFmtTabPara*)pPara;
+
+ if( !rpBox->GetUpper()->GetUpper() ) // Box auf 1. Ebene ?
+ {
+ if( !pSetPara->nCurBox )
+ pSetPara->nAFmtBox = 0;
+ else if( pSetPara->nCurBox == pSetPara->nEndBox )
+ pSetPara->nAFmtBox = 3;
+ else
+ pSetPara->nAFmtBox = (sal_uInt8)(1 + ((pSetPara->nCurBox-1) & 1));
+ }
+
+ if( rpBox->GetBox()->GetSttNd() )
+ {
+ SwTableBox* pSetBox = (SwTableBox*)rpBox->GetBox();
+ SwDoc* pDoc = pSetBox->GetFrmFmt()->GetDoc();
+ SfxItemSet aCharSet( pDoc->GetAttrPool(), RES_CHRATR_BEGIN, RES_PARATR_LIST_END-1 );
+ SfxItemSet aBoxSet( pDoc->GetAttrPool(), aTableBoxSetRange );
+ sal_uInt8 nPos = pSetPara->nAFmtLine * 4 + pSetPara->nAFmtBox;
+ pSetPara->rTblFmt.UpdateToSet( nPos, aCharSet,
+ SwTableAutoFmt::UPDATE_CHAR, 0 );
+ pSetPara->rTblFmt.UpdateToSet( nPos, aBoxSet,
+ SwTableAutoFmt::UPDATE_BOX,
+ pDoc->GetNumberFormatter( sal_True ) );
+ if( aCharSet.Count() )
+ {
+ sal_uLong nSttNd = pSetBox->GetSttIdx()+1;
+ sal_uLong nEndNd = pSetBox->GetSttNd()->EndOfSectionIndex();
+ for( ; nSttNd < nEndNd; ++nSttNd )
+ {
+ SwCntntNode* pNd = pDoc->GetNodes()[ nSttNd ]->GetCntntNode();
+ if( pNd )
+ pNd->SetAttr( aCharSet );
+ }
+ }
+
+ if( aBoxSet.Count() )
+ {
+ if( pSetPara->pUndo &&
+ SFX_ITEM_SET == aBoxSet.GetItemState( RES_BOXATR_FORMAT ))
+ pSetPara->pUndo->SaveBoxCntnt( *pSetBox );
+
+ pSetBox->ClaimFrmFmt()->SetFmtAttr( aBoxSet );
+ }
+ }
+ else
+ ((_FndBox*&)rpBox)->GetLines().ForEach( &lcl_SetAFmtLine, pPara );
+
+ if( !rpBox->GetUpper()->GetUpper() ) // eine BaseLine
+ ++pSetPara->nCurBox;
+ return sal_True;
+}
+
+
+ // AutoFormat fuer die Tabelle/TabellenSelection
+sal_Bool SwDoc::SetTableAutoFmt( const SwSelBoxes& rBoxes, const SwTableAutoFmt& rNew )
+{
+ OSL_ENSURE( rBoxes.Count(), "keine gueltige Box-Liste" );
+ SwTableNode* pTblNd = (SwTableNode*)rBoxes[0]->GetSttNd()->FindTableNode();
+ if( !pTblNd )
+ return sal_False;
+
+ // suche alle Boxen / Lines
+ _FndBox aFndBox( 0, 0 );
+ {
+ _FndPara aPara( rBoxes, &aFndBox );
+ pTblNd->GetTable().GetTabLines().ForEach( &_FndLineCopyCol, &aPara );
+ }
+ if( !aFndBox.GetLines().Count() )
+ return sal_False;
+
+ pTblNd->GetTable().SetHTMLTableLayout( 0 );
+
+ _FndBox* pFndBox = &aFndBox;
+ while( 1 == pFndBox->GetLines().Count() &&
+ 1 == pFndBox->GetLines()[0]->GetBoxes().Count() )
+ pFndBox = pFndBox->GetLines()[0]->GetBoxes()[0];
+
+ if( !pFndBox->GetLines().Count() ) // eine zu weit? (nur 1 sel.Box)
+ pFndBox = pFndBox->GetUpper()->GetUpper();
+
+
+ // Undo abschalten, Attribute werden sich vorher gemerkt
+ SwUndoTblAutoFmt* pUndo = 0;
+ bool const bUndo(GetIDocumentUndoRedo().DoesUndo());
+ if (bUndo)
+ {
+ pUndo = new SwUndoTblAutoFmt( *pTblNd, rNew );
+ GetIDocumentUndoRedo().AppendUndo(pUndo);
+ GetIDocumentUndoRedo().DoUndo(false);
+ }
+
+ _SetAFmtTabPara aPara( rNew );
+ _FndLines& rFLns = pFndBox->GetLines();
+ _FndLine* pLine;
+
+ for( sal_uInt16 n = 0; n < rFLns.Count(); ++n )
+ {
+ pLine = rFLns[n];
+
+ // Upper auf 0 setzen (Base-Line simulieren!)
+ _FndBox* pSaveBox = pLine->GetUpper();
+ pLine->SetUpper( 0 );
+
+ if( !n )
+ aPara.nAFmtLine = 0;
+ else if( n+1 == rFLns.Count() )
+ aPara.nAFmtLine = 3;
+ else
+ aPara.nAFmtLine = (sal_uInt8)(1 + ((n-1) & 1 ));
+
+ aPara.nAFmtBox = 0;
+ aPara.nCurBox = 0;
+ aPara.nEndBox = pLine->GetBoxes().Count()-1;
+ aPara.pUndo = pUndo;
+ pLine->GetBoxes().ForEach( &lcl_SetAFmtBox, &aPara );
+
+ pLine->SetUpper( pSaveBox );
+ }
+
+ if( pUndo )
+ {
+ GetIDocumentUndoRedo().DoUndo(bUndo);
+ }
+
+ SetModified();
+ SetFieldsDirty( true, NULL, 0 );
+
+ return sal_True;
+}
+
+
+ // Erfrage wie attributiert ist
+sal_Bool SwDoc::GetTableAutoFmt( const SwSelBoxes& rBoxes, SwTableAutoFmt& rGet )
+{
+ OSL_ENSURE( rBoxes.Count(), "keine gueltige Box-Liste" );
+ SwTableNode* pTblNd = (SwTableNode*)rBoxes[0]->GetSttNd()->FindTableNode();
+ if( !pTblNd )
+ return sal_False;
+
+ // suche alle Boxen / Lines
+ _FndBox aFndBox( 0, 0 );
+ {
+ _FndPara aPara( rBoxes, &aFndBox );
+ pTblNd->GetTable().GetTabLines().ForEach( &_FndLineCopyCol, &aPara );
+ }
+ if( !aFndBox.GetLines().Count() )
+ return sal_False;
+
+ _FndBox* pFndBox = &aFndBox;
+ while( 1 == pFndBox->GetLines().Count() &&
+ 1 == pFndBox->GetLines()[0]->GetBoxes().Count() )
+ pFndBox = pFndBox->GetLines()[0]->GetBoxes()[0];
+
+ if( !pFndBox->GetLines().Count() ) // eine zu weit? (nur 1 sel.Box)
+ pFndBox = pFndBox->GetUpper()->GetUpper();
+
+ _FndLines& rFLns = pFndBox->GetLines();
+
+ sal_uInt16 aLnArr[4];
+ aLnArr[0] = 0;
+ aLnArr[1] = 1 < rFLns.Count() ? 1 : 0;
+ aLnArr[2] = 2 < rFLns.Count() ? 2 : aLnArr[1];
+ aLnArr[3] = rFLns.Count() - 1;
+
+ for( sal_uInt8 nLine = 0; nLine < 4; ++nLine )
+ {
+ _FndLine& rLine = *rFLns[ aLnArr[ nLine ] ];
+
+ sal_uInt16 aBoxArr[4];
+ aBoxArr[0] = 0;
+ aBoxArr[1] = 1 < rLine.GetBoxes().Count() ? 1 : 0;
+ aBoxArr[2] = 2 < rLine.GetBoxes().Count() ? 2 : aBoxArr[1];
+ aBoxArr[3] = rLine.GetBoxes().Count() - 1;
+
+ for( sal_uInt8 nBox = 0; nBox < 4; ++nBox )
+ {
+ SwTableBox* pFBox = rLine.GetBoxes()[ aBoxArr[ nBox ] ]->GetBox();
+ // immer auf die 1. runterfallen
+ while( !pFBox->GetSttNd() )
+ pFBox = pFBox->GetTabLines()[0]->GetTabBoxes()[0];
+
+ sal_uInt8 nPos = nLine * 4 + nBox;
+ SwNodeIndex aIdx( *pFBox->GetSttNd(), 1 );
+ SwCntntNode* pCNd = aIdx.GetNode().GetCntntNode();
+ if( !pCNd )
+ pCNd = GetNodes().GoNext( &aIdx );
+
+ if( pCNd )
+ rGet.UpdateFromSet( nPos, pCNd->GetSwAttrSet(),
+ SwTableAutoFmt::UPDATE_CHAR, 0 );
+ rGet.UpdateFromSet( nPos, pFBox->GetFrmFmt()->GetAttrSet(),
+ SwTableAutoFmt::UPDATE_BOX,
+ GetNumberFormatter( sal_True ) );
+ }
+ }
+
+ return sal_True;
+}
+
+String SwDoc::GetUniqueTblName() const
+{
+ ResId aId( STR_TABLE_DEFNAME, *pSwResMgr );
+ String aName( aId );
+ xub_StrLen nNmLen = aName.Len();
+
+ sal_uInt16 nNum, nTmp, nFlagSize = ( pTblFrmFmtTbl->Count() / 8 ) +2;
+ sal_uInt16 n;
+
+ sal_uInt8* pSetFlags = new sal_uInt8[ nFlagSize ];
+ memset( pSetFlags, 0, nFlagSize );
+
+ for( n = 0; n < pTblFrmFmtTbl->Count(); ++n )
+ {
+ const SwFrmFmt* pFmt = (*pTblFrmFmtTbl)[ n ];
+ if( !pFmt->IsDefault() && IsUsed( *pFmt ) &&
+ pFmt->GetName().Match( aName ) == nNmLen )
+ {
+ // Nummer bestimmen und das Flag setzen
+ nNum = static_cast<sal_uInt16>(pFmt->GetName().Copy( nNmLen ).ToInt32());
+ if( nNum-- && nNum < pTblFrmFmtTbl->Count() )
+ pSetFlags[ nNum / 8 ] |= (0x01 << ( nNum & 0x07 ));
+ }
+ }
+
+ // alle Nummern entsprechend geflag, also bestimme die richtige Nummer
+ nNum = pTblFrmFmtTbl->Count();
+ for( n = 0; n < nFlagSize; ++n )
+ if( 0xff != ( nTmp = pSetFlags[ n ] ))
+ {
+ // also die Nummer bestimmen
+ nNum = n * 8;
+ while( nTmp & 1 )
+ ++nNum, nTmp >>= 1;
+ break;
+ }
+
+ delete [] pSetFlags;
+ return aName += String::CreateFromInt32( ++nNum );
+}
+
+SwTableFmt* SwDoc::FindTblFmtByName( const String& rName, sal_Bool bAll ) const
+{
+ const SwFmt* pRet = 0;
+ if( bAll )
+ pRet = FindFmtByName( (SvPtrarr&)*pTblFrmFmtTbl, rName );
+ else
+ {
+ // dann nur die, die im Doc gesetzt sind
+ for( sal_uInt16 n = 0; n < pTblFrmFmtTbl->Count(); ++n )
+ {
+ const SwFrmFmt* pFmt = (*pTblFrmFmtTbl)[ n ];
+ if( !pFmt->IsDefault() && IsUsed( *pFmt ) &&
+ pFmt->GetName() == rName )
+ {
+ pRet = pFmt;
+ break;
+ }
+ }
+ }
+ return (SwTableFmt*)pRet;
+}
+
+sal_Bool SwDoc::SetColRowWidthHeight( SwTableBox& rAktBox, sal_uInt16 eType,
+ SwTwips nAbsDiff, SwTwips nRelDiff )
+{
+ SwTableNode* pTblNd = (SwTableNode*)rAktBox.GetSttNd()->FindTableNode();
+ SwUndo* pUndo = 0;
+
+ if( nsTblChgWidthHeightType::WH_FLAG_INSDEL & eType && pTblNd->GetTable().ISA( SwDDETable ))
+ return sal_False;
+
+ SwTableFmlUpdate aMsgHnt( &pTblNd->GetTable() );
+ aMsgHnt.eFlags = TBL_BOXPTR;
+ UpdateTblFlds( &aMsgHnt );
+
+ bool const bUndo(GetIDocumentUndoRedo().DoesUndo());
+ sal_Bool bRet = sal_False;
+ switch( eType & 0xff )
+ {
+ case nsTblChgWidthHeightType::WH_COL_LEFT:
+ case nsTblChgWidthHeightType::WH_COL_RIGHT:
+ case nsTblChgWidthHeightType::WH_CELL_LEFT:
+ case nsTblChgWidthHeightType::WH_CELL_RIGHT:
+ {
+ bRet = pTblNd->GetTable().SetColWidth( rAktBox,
+ eType, nAbsDiff, nRelDiff,
+ (bUndo) ? &pUndo : 0 );
+ }
+ break;
+ case nsTblChgWidthHeightType::WH_ROW_TOP:
+ case nsTblChgWidthHeightType::WH_ROW_BOTTOM:
+ case nsTblChgWidthHeightType::WH_CELL_TOP:
+ case nsTblChgWidthHeightType::WH_CELL_BOTTOM:
+ bRet = pTblNd->GetTable().SetRowHeight( rAktBox,
+ eType, nAbsDiff, nRelDiff,
+ (bUndo) ? &pUndo : 0 );
+ break;
+ }
+
+ GetIDocumentUndoRedo().DoUndo(bUndo); // SetColWidth can turn it off
+ if( pUndo )
+ {
+ GetIDocumentUndoRedo().AppendUndo( pUndo );
+ }
+
+ if( bRet )
+ {
+ SetModified();
+ if( nsTblChgWidthHeightType::WH_FLAG_INSDEL & eType )
+ SetFieldsDirty( true, NULL, 0 );
+ }
+ return bRet;
+}
+
+
+void SwDoc::ChkBoxNumFmt( SwTableBox& rBox, sal_Bool bCallUpdate )
+{
+ //JP 09.07.97: Optimierung: wenn die Box schon sagt, das es Text
+ // sein soll, dann bleibt das auch Text!
+ const SfxPoolItem* pNumFmtItem = 0;
+ if( SFX_ITEM_SET == rBox.GetFrmFmt()->GetItemState( RES_BOXATR_FORMAT,
+ sal_False, &pNumFmtItem ) && GetNumberFormatter()->IsTextFormat(
+ ((SwTblBoxNumFormat*)pNumFmtItem)->GetValue() ))
+ return ;
+
+ SwUndoTblNumFmt* pUndo = 0;
+
+ sal_Bool bIsEmptyTxtNd, bChgd = sal_True;
+ sal_uInt32 nFmtIdx;
+ double fNumber;
+ if( rBox.HasNumCntnt( fNumber, nFmtIdx, bIsEmptyTxtNd ) )
+ {
+ if( !rBox.IsNumberChanged() )
+ bChgd = sal_False;
+ else
+ {
+ if (GetIDocumentUndoRedo().DoesUndo())
+ {
+ GetIDocumentUndoRedo().StartUndo( UNDO_TABLE_AUTOFMT, NULL );
+ pUndo = new SwUndoTblNumFmt( rBox );
+ pUndo->SetNumFmt( nFmtIdx, fNumber );
+ }
+
+ SwTableBoxFmt* pBoxFmt = (SwTableBoxFmt*)rBox.GetFrmFmt();
+ SfxItemSet aBoxSet( GetAttrPool(), RES_BOXATR_FORMAT, RES_BOXATR_VALUE );
+
+ sal_Bool bSetNumFmt = IsInsTblFormatNum(), bLockModify = sal_True;
+ if( bSetNumFmt )
+ {
+ if( !IsInsTblChangeNumFormat() )
+ {
+ if( !pNumFmtItem )
+ bSetNumFmt = sal_False;
+ else
+ {
+ sal_uLong nOldNumFmt = ((SwTblBoxNumFormat*)pNumFmtItem)->
+ GetValue();
+ SvNumberFormatter* pNumFmtr = GetNumberFormatter();
+
+ short nFmtType = pNumFmtr->GetType( nFmtIdx );
+ if( nFmtType == pNumFmtr->GetType( nOldNumFmt ) ||
+ NUMBERFORMAT_NUMBER == nFmtType )
+ // eingstelltes und vorgegebenes NumFormat
+ // stimmen ueberein -> altes Format beibehalten
+ nFmtIdx = nOldNumFmt;
+ else
+ // eingstelltes und vorgegebenes NumFormat
+ // stimmen nicht ueberein -> als Text einfuegen
+ bLockModify = bSetNumFmt = sal_False;
+ }
+ }
+
+ if( bSetNumFmt )
+ {
+ pBoxFmt = (SwTableBoxFmt*)rBox.ClaimFrmFmt();
+
+ aBoxSet.Put( SwTblBoxValue( fNumber ));
+ aBoxSet.Put( SwTblBoxNumFormat( nFmtIdx ));
+ }
+ }
+
+ // JP 28.04.98: Nur Formel zuruecksetzen reicht nicht.
+ // Sorge dafuer, das der Text auch entsprechend
+ // formatiert wird!
+
+ if( !bSetNumFmt && !bIsEmptyTxtNd && pNumFmtItem )
+ {
+ // JP 15.01.99: Nur Attribute zuruecksetzen reicht nicht.
+ // Sorge dafuer, das der Text auch entsprechend
+ // formatiert wird!
+ pBoxFmt->SetFmtAttr( *GetDfltAttr( RES_BOXATR_FORMAT ));
+ }
+
+ if( bLockModify ) pBoxFmt->LockModify();
+ pBoxFmt->ResetFmtAttr( RES_BOXATR_FORMAT, RES_BOXATR_VALUE );
+ if( bLockModify ) pBoxFmt->UnlockModify();
+
+ if( bSetNumFmt )
+ pBoxFmt->SetFmtAttr( aBoxSet );
+ }
+ }
+ else
+ {
+ // es ist keine Zahl
+ const SfxPoolItem* pValueItem = 0, *pFmtItem = 0;
+ SwTableBoxFmt* pBoxFmt = (SwTableBoxFmt*)rBox.GetFrmFmt();
+ if( SFX_ITEM_SET == pBoxFmt->GetItemState( RES_BOXATR_FORMAT,
+ sal_False, &pFmtItem ) ||
+ SFX_ITEM_SET == pBoxFmt->GetItemState( RES_BOXATR_VALUE,
+ sal_False, &pValueItem ))
+ {
+ if (GetIDocumentUndoRedo().DoesUndo())
+ {
+ GetIDocumentUndoRedo().StartUndo( UNDO_TABLE_AUTOFMT, NULL );
+ pUndo = new SwUndoTblNumFmt( rBox );
+ }
+
+ pBoxFmt = (SwTableBoxFmt*)rBox.ClaimFrmFmt();
+
+ // alle Zahlenformate entfernen
+ sal_uInt16 nWhich1 = RES_BOXATR_FORMULA;
+ if( !bIsEmptyTxtNd )
+ {
+ nWhich1 = RES_BOXATR_FORMAT;
+
+ // JP 15.01.99: Nur Attribute zuruecksetzen reicht nicht.
+ // Sorge dafuer, das der Text auch entsprechend
+ // formatiert wird!
+ pBoxFmt->SetFmtAttr( *GetDfltAttr( nWhich1 ));
+ }
+ pBoxFmt->ResetFmtAttr( nWhich1, RES_BOXATR_VALUE );
+ }
+ else
+ bChgd = sal_False;
+ }
+
+ if( bChgd )
+ {
+ if( pUndo )
+ {
+ pUndo->SetBox( rBox );
+ GetIDocumentUndoRedo().AppendUndo(pUndo);
+ GetIDocumentUndoRedo().EndUndo( UNDO_END, NULL );
+ }
+
+ const SwTableNode* pTblNd = rBox.GetSttNd()->FindTableNode();
+ if( bCallUpdate )
+ {
+ SwTableFmlUpdate aTblUpdate( &pTblNd->GetTable() );
+ UpdateTblFlds( &aTblUpdate );
+
+ // TL_CHART2: update charts (when cursor leaves cell and
+ // automatic update is enabled)
+ if (AUTOUPD_FIELD_AND_CHARTS == getFieldUpdateFlags(true))
+ pTblNd->GetTable().UpdateCharts();
+ }
+ SetModified();
+ }
+}
+
+void SwDoc::SetTblBoxFormulaAttrs( SwTableBox& rBox, const SfxItemSet& rSet )
+{
+ if (GetIDocumentUndoRedo().DoesUndo())
+ {
+ GetIDocumentUndoRedo().AppendUndo( new SwUndoTblNumFmt(rBox, &rSet) );
+ }
+
+ SwFrmFmt* pBoxFmt = rBox.ClaimFrmFmt();
+ if( SFX_ITEM_SET == rSet.GetItemState( RES_BOXATR_FORMULA ))
+ {
+ pBoxFmt->LockModify();
+ pBoxFmt->ResetFmtAttr( RES_BOXATR_VALUE );
+ pBoxFmt->UnlockModify();
+ }
+ else if( SFX_ITEM_SET == rSet.GetItemState( RES_BOXATR_VALUE ))
+ {
+ pBoxFmt->LockModify();
+ pBoxFmt->ResetFmtAttr( RES_BOXATR_FORMULA );
+ pBoxFmt->UnlockModify();
+ }
+ pBoxFmt->SetFmtAttr( rSet );
+ SetModified();
+}
+
+void SwDoc::ClearLineNumAttrs( SwPosition & rPos )
+{
+ SwPaM aPam(rPos);
+ aPam.Move(fnMoveBackward);
+ SwCntntNode *pNode = aPam.GetCntntNode();
+ if ( 0 == pNode )
+ return ;
+ if( pNode->IsTxtNode() )
+ {
+ SwTxtNode * pTxtNode = pNode->GetTxtNode();
+ if ( pTxtNode && pTxtNode->IsNumbered() && pTxtNode->GetTxt().Len()==0 )
+ {
+ const SfxPoolItem* pFmtItem = 0;
+ SfxItemSet rSet( const_cast<SwAttrPool&>(pTxtNode->GetDoc()->GetAttrPool()),
+ RES_PARATR_BEGIN, RES_PARATR_END - 1,
+ 0);
+ pTxtNode->SwCntntNode::GetAttr( rSet );
+ if ( SFX_ITEM_SET == rSet.GetItemState( RES_PARATR_NUMRULE , sal_False , &pFmtItem ) )
+ {
+ SwUndoDelNum * pUndo;
+ if( GetIDocumentUndoRedo().DoesUndo() )
+ {
+ GetIDocumentUndoRedo().ClearRedo();
+ GetIDocumentUndoRedo().AppendUndo( pUndo = new SwUndoDelNum( aPam ) );
+ }
+ else
+ pUndo = 0;
+ SwRegHistory aRegH( pUndo ? pUndo->GetHistory() : 0 );
+ aRegH.RegisterInModify( pTxtNode , *pTxtNode );
+ if ( pUndo )
+ pUndo->AddNode( *pTxtNode , sal_False );
+ String aStyle = String::CreateFromAscii("");
+ SfxStringItem * pNewItem = (SfxStringItem*)pFmtItem->Clone();
+ pNewItem->SetValue( aStyle );
+ rSet.Put( *pNewItem );
+ pTxtNode->SetAttr( rSet );
+ delete pNewItem;
+ }
+ }
+ }
+}
+
+void SwDoc::ClearBoxNumAttrs( const SwNodeIndex& rNode )
+{
+ SwStartNode* pSttNd;
+ if( 0 != ( pSttNd = rNode.GetNode().
+ FindSttNodeByType( SwTableBoxStartNode )) &&
+ 2 == pSttNd->EndOfSectionIndex() - pSttNd->GetIndex() )
+ {
+ SwTableBox* pBox = pSttNd->FindTableNode()->GetTable().
+ GetTblBox( pSttNd->GetIndex() );
+
+ const SfxPoolItem* pFmtItem = 0;
+ const SfxItemSet& rSet = pBox->GetFrmFmt()->GetAttrSet();
+ if( SFX_ITEM_SET == rSet.GetItemState( RES_BOXATR_FORMAT, sal_False, &pFmtItem ) ||
+ SFX_ITEM_SET == rSet.GetItemState( RES_BOXATR_FORMULA, sal_False ) ||
+ SFX_ITEM_SET == rSet.GetItemState( RES_BOXATR_VALUE, sal_False ))
+ {
+ if (GetIDocumentUndoRedo().DoesUndo())
+ {
+ GetIDocumentUndoRedo().AppendUndo(new SwUndoTblNumFmt(*pBox));
+ }
+
+ SwFrmFmt* pBoxFmt = pBox->ClaimFrmFmt();
+
+ //JP 01.09.97: TextFormate bleiben erhalten!
+ sal_uInt16 nWhich1 = RES_BOXATR_FORMAT;
+ if( pFmtItem && GetNumberFormatter()->IsTextFormat(
+ ((SwTblBoxNumFormat*)pFmtItem)->GetValue() ))
+ nWhich1 = RES_BOXATR_FORMULA;
+ else
+ // JP 15.01.99: Nur Attribute zuruecksetzen reicht nicht.
+ // Sorge dafuer, das der Text auch entsprechend
+ // formatiert wird!
+ pBoxFmt->SetFmtAttr( *GetDfltAttr( RES_BOXATR_FORMAT ));
+
+ pBoxFmt->ResetFmtAttr( nWhich1, RES_BOXATR_VALUE );
+ SetModified();
+ }
+ }
+}
+
+// kopiert eine Tabelle aus dem selben oder einem anderen Doc in sich
+// selbst. Dabei wird eine neue Tabelle angelegt oder eine bestehende
+// mit dem Inhalt gefuellt; wobei entweder der Inhalt ab einer Box oder
+// in eine bestehende TblSelektion gefuellt wird.
+// Gerufen wird es von: edglss.cxx/fecopy.cxx
+
+sal_Bool SwDoc::InsCopyOfTbl( SwPosition& rInsPos, const SwSelBoxes& rBoxes,
+ const SwTable* pCpyTbl, sal_Bool bCpyName, sal_Bool bCorrPos )
+{
+ sal_Bool bRet;
+
+ const SwTableNode* pSrcTblNd = pCpyTbl
+ ? pCpyTbl->GetTableNode()
+ : rBoxes[ 0 ]->GetSttNd()->FindTableNode();
+
+ SwTableNode * pInsTblNd = rInsPos.nNode.GetNode().FindTableNode();
+
+ bool const bUndo( GetIDocumentUndoRedo().DoesUndo() );
+ if( !pCpyTbl && !pInsTblNd )
+ {
+ SwUndoCpyTbl* pUndo = 0;
+ if (bUndo)
+ {
+ GetIDocumentUndoRedo().ClearRedo();
+ pUndo = new SwUndoCpyTbl;
+ }
+
+ {
+ ::sw::UndoGuard const undoGuard(GetIDocumentUndoRedo());
+ bRet = pSrcTblNd->GetTable().MakeCopy( this, rInsPos, rBoxes,
+ sal_True, bCpyName );
+ }
+
+ if( pUndo )
+ {
+ if( !bRet )
+ {
+ delete pUndo;
+ pUndo = 0;
+ }
+ else
+ {
+ pInsTblNd = GetNodes()[ rInsPos.nNode.GetIndex() - 1 ]->FindTableNode();
+
+ pUndo->SetTableSttIdx( pInsTblNd->GetIndex() );
+ GetIDocumentUndoRedo().AppendUndo( pUndo );
+ }
+ }
+ }
+ else
+ {
+ RedlineMode_t eOld = GetRedlineMode();
+ if( IsRedlineOn() )
+ SetRedlineMode( (RedlineMode_t)(nsRedlineMode_t::REDLINE_ON |
+ nsRedlineMode_t::REDLINE_SHOW_INSERT |
+ nsRedlineMode_t::REDLINE_SHOW_DELETE));
+
+ SwUndoTblCpyTbl* pUndo = 0;
+ if (bUndo)
+ {
+ GetIDocumentUndoRedo().ClearRedo();
+ pUndo = new SwUndoTblCpyTbl;
+ GetIDocumentUndoRedo().DoUndo(false);
+ }
+
+ SwDoc* pCpyDoc = (SwDoc*)pSrcTblNd->GetDoc();
+ sal_Bool bDelCpyDoc = pCpyDoc == this;
+
+ if( bDelCpyDoc )
+ {
+ // kopiere die Tabelle erstmal in ein temp. Doc
+ pCpyDoc = new SwDoc;
+ pCpyDoc->acquire();
+
+ SwPosition aPos( SwNodeIndex( pCpyDoc->GetNodes().GetEndOfContent() ));
+ if( !pSrcTblNd->GetTable().MakeCopy( pCpyDoc, aPos, rBoxes, sal_True, sal_True ))
+ {
+ if( pCpyDoc->release() == 0 )
+ delete pCpyDoc;
+
+ if( pUndo )
+ {
+ GetIDocumentUndoRedo().DoUndo(bUndo);
+ delete pUndo;
+ pUndo = 0;
+ }
+ return sal_False;
+ }
+ aPos.nNode -= 1; // auf den EndNode der Tabelle
+ pSrcTblNd = aPos.nNode.GetNode().FindTableNode();
+ }
+
+ const SwStartNode* pSttNd = rInsPos.nNode.GetNode().FindTableBoxStartNode();
+
+ rInsPos.nContent.Assign( 0, 0 );
+
+ // no complex into complex, but copy into or from new model is welcome
+ if( ( !pSrcTblNd->GetTable().IsTblComplex() || pInsTblNd->GetTable().IsNewModel() )
+ && ( bDelCpyDoc || rBoxes.Count() ) )
+ {
+ // dann die Tabelle "relativ" kopieren
+ const SwSelBoxes* pBoxes;
+ SwSelBoxes aBoxes;
+
+ if( bDelCpyDoc )
+ {
+ SwTableBox* pBox = pInsTblNd->GetTable().GetTblBox(
+ pSttNd->GetIndex() );
+ OSL_ENSURE( pBox, "Box steht nicht in dieser Tabelle" );
+ aBoxes.Insert( pBox );
+ pBoxes = &aBoxes;
+ }
+ else
+ pBoxes = &rBoxes;
+
+ // kopiere die Tabelle in die selktierten Zellen.
+ bRet = pInsTblNd->GetTable().InsTable( pSrcTblNd->GetTable(),
+ *pBoxes, pUndo );
+ }
+ else
+ {
+ SwNodeIndex aNdIdx( *pSttNd, 1 );
+ bRet = pInsTblNd->GetTable().InsTable( pSrcTblNd->GetTable(),
+ aNdIdx, pUndo );
+ }
+
+ if( bDelCpyDoc )
+ {
+ if( pCpyDoc->release() == 0 )
+ delete pCpyDoc;
+ }
+
+ if( pUndo )
+ {
+ // falls die Tabelle nicht kopiert werden konnte, das Undo-Object
+ // wieder loeschen
+ GetIDocumentUndoRedo().DoUndo(bUndo);
+ if( !bRet && pUndo->IsEmpty() )
+ delete pUndo;
+ else
+ {
+ GetIDocumentUndoRedo().AppendUndo(pUndo);
+ }
+ }
+
+ if( bCorrPos )
+ {
+ rInsPos.nNode = *pSttNd;
+ rInsPos.nContent.Assign( GetNodes().GoNext( &rInsPos.nNode ), 0 );
+ }
+ SetRedlineMode( eOld );
+ }
+
+ if( bRet )
+ {
+ SetModified();
+ SetFieldsDirty( true, NULL, 0 );
+ }
+ return bRet;
+}
+
+
+
+sal_Bool SwDoc::_UnProtectTblCells( SwTable& rTbl )
+{
+ sal_Bool bChgd = sal_False;
+ SwUndoAttrTbl *const pUndo = (GetIDocumentUndoRedo().DoesUndo())
+ ? new SwUndoAttrTbl( *rTbl.GetTableNode() )
+ : 0;
+
+ SwTableSortBoxes& rSrtBox = rTbl.GetTabSortBoxes();
+ for( sal_uInt16 i = rSrtBox.Count(); i; )
+ {
+ SwFrmFmt *pBoxFmt = rSrtBox[ --i ]->GetFrmFmt();
+ if( pBoxFmt->GetProtect().IsCntntProtected() )
+ {
+ pBoxFmt->ResetFmtAttr( RES_PROTECT );
+ bChgd = sal_True;
+ }
+ }
+
+ if( pUndo )
+ {
+ if( bChgd )
+ {
+ GetIDocumentUndoRedo().AppendUndo( pUndo );
+ }
+ else
+ delete pUndo;
+ }
+ return bChgd;
+}
+
+
+sal_Bool SwDoc::UnProtectCells( const String& rName )
+{
+ sal_Bool bChgd = sal_False;
+ SwTableFmt* pFmt = FindTblFmtByName( rName );
+ if( pFmt )
+ {
+ bChgd = _UnProtectTblCells( *SwTable::FindTable( pFmt ) );
+ if( bChgd )
+ SetModified();
+ }
+
+ return bChgd;
+}
+
+sal_Bool SwDoc::UnProtectCells( const SwSelBoxes& rBoxes )
+{
+ sal_Bool bChgd = sal_False;
+ if( rBoxes.Count() )
+ {
+ SwUndoAttrTbl *const pUndo = (GetIDocumentUndoRedo().DoesUndo())
+ ? new SwUndoAttrTbl( *rBoxes[0]->GetSttNd()->FindTableNode() )
+ : 0;
+
+ SvPtrarr aFmts( 16 ), aNewFmts( 16 );
+ for( sal_uInt16 i = rBoxes.Count(); i; )
+ {
+ SwTableBox* pBox = rBoxes[ --i ];
+ SwFrmFmt* pBoxFmt = pBox->GetFrmFmt();
+ if( pBoxFmt->GetProtect().IsCntntProtected() )
+ {
+ sal_uInt16 nFnd = aFmts.GetPos( pBoxFmt );
+ if( USHRT_MAX != nFnd )
+ pBox->ChgFrmFmt( (SwTableBoxFmt*)aNewFmts[ nFnd ] );
+ else
+ {
+ aFmts.Insert( pBoxFmt, aFmts.Count() );
+ pBoxFmt = pBox->ClaimFrmFmt();
+ pBoxFmt->ResetFmtAttr( RES_PROTECT );
+ aNewFmts.Insert( pBoxFmt, aNewFmts.Count() );
+ }
+ bChgd = sal_True;
+ }
+ }
+
+ if( pUndo )
+ {
+ if( bChgd )
+ {
+ GetIDocumentUndoRedo().AppendUndo( pUndo );
+ }
+ else
+ delete pUndo;
+ }
+ }
+ return bChgd;
+}
+
+sal_Bool SwDoc::UnProtectTbls( const SwPaM& rPam )
+{
+ GetIDocumentUndoRedo().StartUndo(UNDO_EMPTY, NULL);
+
+ sal_Bool bChgd = sal_False, bHasSel = rPam.HasMark() ||
+ rPam.GetNext() != (SwPaM*)&rPam;
+ SwFrmFmts& rFmts = *GetTblFrmFmts();
+ SwTable* pTbl;
+ const SwTableNode* pTblNd;
+ for( sal_uInt16 n = rFmts.Count(); n ; )
+ if( 0 != (pTbl = SwTable::FindTable( rFmts[ --n ] )) &&
+ 0 != (pTblNd = pTbl->GetTableNode() ) &&
+ pTblNd->GetNodes().IsDocNodes() )
+ {
+ sal_uLong nTblIdx = pTblNd->GetIndex();
+
+ // dann ueberpruefe ob Tabelle in der Selection liegt
+ if( bHasSel )
+ {
+ int bFound = sal_False;
+ SwPaM* pTmp = (SwPaM*)&rPam;
+ do {
+ const SwPosition *pStt = pTmp->Start(),
+ *pEnd = pTmp->End();
+ bFound = pStt->nNode.GetIndex() < nTblIdx &&
+ nTblIdx < pEnd->nNode.GetIndex();
+
+ } while( !bFound && &rPam != ( pTmp = (SwPaM*)pTmp->GetNext() ) );
+ if( !bFound )
+ continue; // weitersuchen
+ }
+
+ // dann mal den Schutz aufheben
+ bChgd |= _UnProtectTblCells( *pTbl );
+ }
+
+ GetIDocumentUndoRedo().EndUndo(UNDO_EMPTY, NULL);
+ if( bChgd )
+ SetModified();
+
+ return bChgd;
+}
+
+sal_Bool SwDoc::HasTblAnyProtection( const SwPosition* pPos,
+ const String* pTblName,
+ sal_Bool* pFullTblProtection )
+{
+ sal_Bool bHasProtection = sal_False;
+ SwTable* pTbl = 0;
+ if( pTblName )
+ pTbl = SwTable::FindTable( FindTblFmtByName( *pTblName ) );
+ else if( pPos )
+ {
+ SwTableNode* pTblNd = pPos->nNode.GetNode().FindTableNode();
+ if( pTblNd )
+ pTbl = &pTblNd->GetTable();
+ }
+
+ if( pTbl )
+ {
+ SwTableSortBoxes& rSrtBox = pTbl->GetTabSortBoxes();
+ for( sal_uInt16 i = rSrtBox.Count(); i; )
+ {
+ SwFrmFmt *pBoxFmt = rSrtBox[ --i ]->GetFrmFmt();
+ if( pBoxFmt->GetProtect().IsCntntProtected() )
+ {
+ if( !bHasProtection )
+ {
+ bHasProtection = sal_True;
+ if( !pFullTblProtection )
+ break;
+ *pFullTblProtection = sal_True;
+ }
+ }
+ else if( bHasProtection && pFullTblProtection )
+ {
+ *pFullTblProtection = sal_False;
+ break;
+ }
+ }
+ }
+ return bHasProtection;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/docnode/ndtbl1.cxx b/sw/source/core/docnode/ndtbl1.cxx
new file mode 100644
index 000000000000..5f66a3d17fbd
--- /dev/null
+++ b/sw/source/core/docnode/ndtbl1.cxx
@@ -0,0 +1,1598 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+#include "hintids.hxx"
+#include <editeng/lrspitem.hxx>
+#include <editeng/boxitem.hxx>
+#include <editeng/brshitem.hxx>
+#include <editeng/frmdiritem.hxx>
+#include <fmtornt.hxx>
+#include <fmtfsize.hxx>
+#include <fmtlsplt.hxx>
+#include <fmtrowsplt.hxx>
+#include <tabcol.hxx>
+#include <frmatr.hxx>
+#include <cellfrm.hxx>
+#include <tabfrm.hxx>
+#include <cntfrm.hxx>
+#include <txtfrm.hxx>
+#include <svx/svxids.hrc>
+#include <doc.hxx>
+#include <IDocumentUndoRedo.hxx>
+#include "pam.hxx"
+#include "swcrsr.hxx"
+#include "viscrs.hxx"
+#include "swtable.hxx"
+#include "htmltbl.hxx"
+#include "tblsel.hxx"
+#include "swtblfmt.hxx"
+#include "docary.hxx"
+#include "ndindex.hxx"
+#include "undobj.hxx"
+#include "switerator.hxx"
+#include <UndoTable.hxx>
+
+using ::editeng::SvxBorderLine;
+using namespace ::com::sun::star;
+
+
+extern void ClearFEShellTabCols();
+
+//siehe auch swtable.cxx
+#define COLFUZZY 20L
+
+inline sal_Bool IsSame( long nA, long nB ) { return Abs(nA-nB) <= COLFUZZY; }
+
+class SwTblFmtCmp
+{
+public:
+ SwFrmFmt *pOld,
+ *pNew;
+ sal_Int16 nType;
+
+ SwTblFmtCmp( SwFrmFmt *pOld, SwFrmFmt *pNew, sal_Int16 nType );
+
+ static SwFrmFmt *FindNewFmt( SvPtrarr &rArr, SwFrmFmt*pOld, sal_Int16 nType );
+ static void Delete( SvPtrarr &rArr );
+};
+
+
+SwTblFmtCmp::SwTblFmtCmp( SwFrmFmt *pO, SwFrmFmt *pN, sal_Int16 nT )
+ : pOld ( pO ), pNew ( pN ), nType( nT )
+{
+}
+
+SwFrmFmt *SwTblFmtCmp::FindNewFmt( SvPtrarr &rArr, SwFrmFmt *pOld, sal_Int16 nType )
+{
+ for ( sal_uInt16 i = 0; i < rArr.Count(); ++i )
+ {
+ SwTblFmtCmp *pCmp = (SwTblFmtCmp*)rArr[i];
+ if ( pCmp->pOld == pOld && pCmp->nType == nType )
+ return pCmp->pNew;
+ }
+ return 0;
+}
+
+void SwTblFmtCmp::Delete( SvPtrarr &rArr )
+{
+ for ( sal_uInt16 i = 0; i < rArr.Count(); ++i )
+ delete (SwTblFmtCmp*)rArr[i];
+}
+
+void lcl_GetStartEndCell( const SwCursor& rCrsr,
+ SwLayoutFrm *&prStart, SwLayoutFrm *&prEnd )
+{
+ OSL_ENSURE( rCrsr.GetCntntNode() && rCrsr.GetCntntNode( sal_False ),
+ "Tabselection nicht auf Cnt." );
+
+ Point aPtPos, aMkPos;
+ const SwShellCrsr* pShCrsr = dynamic_cast<const SwShellCrsr*>(&rCrsr);
+ if( pShCrsr )
+ {
+ aPtPos = pShCrsr->GetPtPos();
+ aMkPos = pShCrsr->GetMkPos();
+ }
+
+ // robust:
+ SwCntntNode* pPointNd = rCrsr.GetCntntNode();
+ SwCntntNode* pMarkNd = rCrsr.GetCntntNode(sal_False);
+
+ SwFrm* pPointFrm = pPointNd ? pPointNd->getLayoutFrm( pPointNd->GetDoc()->GetCurrentLayout(), &aPtPos ) : 0;
+ SwFrm* pMarkFrm = pMarkNd ? pMarkNd->getLayoutFrm( pMarkNd->GetDoc()->GetCurrentLayout(), &aMkPos ) : 0;
+
+ prStart = pPointFrm ? pPointFrm->GetUpper() : 0;
+ prEnd = pMarkFrm ? pMarkFrm->GetUpper() : 0;
+}
+
+sal_Bool lcl_GetBoxSel( const SwCursor& rCursor, SwSelBoxes& rBoxes,
+ sal_Bool bAllCrsr = sal_False )
+{
+ const SwTableCursor* pTblCrsr =
+ dynamic_cast<const SwTableCursor*>(&rCursor);
+ if( pTblCrsr )
+ ::GetTblSelCrs( *pTblCrsr, rBoxes );
+ else
+ {
+ const SwPaM *pCurPam = &rCursor, *pSttPam = pCurPam;
+ do {
+ const SwNode* pNd = pCurPam->GetNode()->FindTableBoxStartNode();
+ if( pNd )
+ {
+ SwTableBox* pBox = (SwTableBox*)pNd->FindTableNode()->GetTable().
+ GetTblBox( pNd->GetIndex() );
+ rBoxes.Insert( pBox );
+ }
+ } while( bAllCrsr &&
+ pSttPam != ( pCurPam = (SwPaM*)pCurPam->GetNext()) );
+ }
+ return 0 != rBoxes.Count();
+}
+
+/***********************************************************************
+#* Class : SwDoc
+#* Methoden : SetRowHeight(), GetRowHeight()
+#***********************************************************************/
+//Die Zeilenhoehe wird ausgehend von der Selektion ermittelt/gesetzt.
+//Ausgehend von jeder Zelle innerhalb der Selektion werden nach oben alle
+//Zeilen abgeklappert, die oberste Zeile erhaelt den gewuenschten Wert alle
+//tieferliegenden Zeilen einen entsprechenden Wert der sich aus der
+//Relation der alten und neuen Groesse der obersten Zeile und ihrer
+//eigenen Groesse ergiebt.
+//Alle veraenderten Zeilen erhalten ggf. ein eigenes FrmFmt.
+//Natuerlich darf jede Zeile nur einmal angefasst werden.
+
+inline void InsertLine( SvPtrarr& rLineArr, SwTableLine* pLine )
+{
+ if( USHRT_MAX == rLineArr.GetPos( pLine ) )
+ rLineArr.Insert( pLine, rLineArr.Count() );
+}
+
+//-----------------------------------------------------------------------------
+
+sal_Bool lcl_IsAnLower( const SwTableLine *pLine, const SwTableLine *pAssumed )
+{
+ const SwTableLine *pTmp = pAssumed->GetUpper() ?
+ pAssumed->GetUpper()->GetUpper() : 0;
+ while ( pTmp )
+ {
+ if ( pTmp == pLine )
+ return sal_True;
+ pTmp = pTmp->GetUpper() ? pTmp->GetUpper()->GetUpper() : 0;
+ }
+ return sal_False;
+}
+//-----------------------------------------------------------------------------
+
+struct LinesAndTable
+{
+ SvPtrarr &rLines;
+ const SwTable &rTable;
+ sal_Bool bInsertLines;
+
+ LinesAndTable( SvPtrarr &rL, const SwTable &rTbl ) :
+ rLines( rL ), rTable( rTbl ), bInsertLines( sal_True ) {}
+};
+
+
+sal_Bool _FindLine( const _FndLine*& rpLine, void* pPara );
+
+sal_Bool _FindBox( const _FndBox*& rpBox, void* pPara )
+{
+ if ( rpBox->GetLines().Count() )
+ {
+ ((LinesAndTable*)pPara)->bInsertLines = sal_True;
+ ((_FndBox*)rpBox)->GetLines().ForEach( _FindLine, pPara );
+ if ( ((LinesAndTable*)pPara)->bInsertLines )
+ {
+ const SwTableLines &rLines = rpBox->GetBox()
+ ? rpBox->GetBox()->GetTabLines()
+ : ((LinesAndTable*)pPara)->rTable.GetTabLines();
+ if ( rpBox->GetLines().Count() == rLines.Count() )
+ {
+ for ( sal_uInt16 i = 0; i < rLines.Count(); ++i )
+ ::InsertLine( ((LinesAndTable*)pPara)->rLines,
+ (SwTableLine*)rLines[i] );
+ }
+ else
+ ((LinesAndTable*)pPara)->bInsertLines = sal_False;
+ }
+ }
+ else if ( rpBox->GetBox() )
+ ::InsertLine( ((LinesAndTable*)pPara)->rLines,
+ (SwTableLine*)rpBox->GetBox()->GetUpper() );
+ return sal_True;
+}
+
+sal_Bool _FindLine( const _FndLine*& rpLine, void* pPara )
+{
+ ((_FndLine*)rpLine)->GetBoxes().ForEach( _FindBox, pPara );
+ return sal_True;
+}
+
+void lcl_CollectLines( SvPtrarr &rArr, const SwCursor& rCursor, bool bRemoveLines )
+{
+ //Zuerst die selektierten Boxen einsammeln.
+ SwSelBoxes aBoxes;
+ if( !::lcl_GetBoxSel( rCursor, aBoxes ))
+ return ;
+
+ //Die selektierte Struktur kopieren.
+ const SwTable &rTable = aBoxes[0]->GetSttNd()->FindTableNode()->GetTable();
+ LinesAndTable aPara( rArr, rTable );
+ _FndBox aFndBox( 0, 0 );
+ {
+ _FndPara aTmpPara( aBoxes, &aFndBox );
+ ((SwTableLines&)rTable.GetTabLines()).ForEach( &_FndLineCopyCol, &aTmpPara );
+ }
+
+ //Diejenigen Lines einsammeln, die nur selektierte Boxen enthalten.
+ const _FndBox *pTmp = &aFndBox;
+ ::_FindBox( pTmp, &aPara );
+
+ // Remove lines, that have a common superordinate row.
+ // (Not for row split)
+ if ( bRemoveLines )
+ {
+ for ( sal_uInt16 i = 0; i < rArr.Count(); ++i )
+ {
+ SwTableLine *pUpLine = (SwTableLine*)rArr[i];
+ for ( sal_uInt16 k = 0; k < rArr.Count(); ++k )
+ {
+ if ( k != i && ::lcl_IsAnLower( pUpLine, (SwTableLine*)rArr[k] ) )
+ {
+ rArr.Remove( k );
+ if ( k <= i )
+ --i;
+ --k;
+ }
+ }
+ }
+ }
+}
+
+//-----------------------------------------------------------------------------
+
+void lcl_ProcessRowAttr( SvPtrarr& rFmtCmp, SwTableLine* pLine, const SfxPoolItem& rNew )
+{
+ SwFrmFmt *pNewFmt;
+ if ( 0 != (pNewFmt = SwTblFmtCmp::FindNewFmt( rFmtCmp, pLine->GetFrmFmt(), 0 )))
+ pLine->ChgFrmFmt( (SwTableLineFmt*)pNewFmt );
+ else
+ {
+ SwFrmFmt *pOld = pLine->GetFrmFmt();
+ SwFrmFmt *pNew = pLine->ClaimFrmFmt();
+ pNew->SetFmtAttr( rNew );
+ rFmtCmp.Insert( new SwTblFmtCmp( pOld, pNew, 0 ), rFmtCmp.Count());
+ }
+}
+
+//-----------------------------------------------------------------------------
+
+void lcl_ProcessBoxSize( SvPtrarr &rFmtCmp, SwTableBox *pBox, const SwFmtFrmSize &rNew );
+
+void lcl_ProcessRowSize( SvPtrarr &rFmtCmp, SwTableLine *pLine, const SwFmtFrmSize &rNew )
+{
+ lcl_ProcessRowAttr( rFmtCmp, pLine, rNew );
+ SwTableBoxes &rBoxes = pLine->GetTabBoxes();
+ for ( sal_uInt16 i = 0; i < rBoxes.Count(); ++i )
+ ::lcl_ProcessBoxSize( rFmtCmp, rBoxes[i], rNew );
+}
+
+//-----------------------------------------------------------------------------
+
+void lcl_ProcessBoxSize( SvPtrarr &rFmtCmp, SwTableBox *pBox, const SwFmtFrmSize &rNew )
+{
+ SwTableLines &rLines = pBox->GetTabLines();
+ if ( rLines.Count() )
+ {
+ SwFmtFrmSize aSz( rNew );
+ aSz.SetHeight( rNew.GetHeight() ? rNew.GetHeight() / rLines.Count() : 0 );
+ for ( sal_uInt16 i = 0; i < rLines.Count(); ++i )
+ ::lcl_ProcessRowSize( rFmtCmp, rLines[i], aSz );
+ }
+}
+
+//-----------------------------------------------------------------------------
+
+/******************************************************************************
+ * void SwDoc::SetRowSplit()
+ ******************************************************************************/
+void SwDoc::SetRowSplit( const SwCursor& rCursor, const SwFmtRowSplit &rNew )
+{
+ SwTableNode* pTblNd = rCursor.GetPoint()->nNode.GetNode().FindTableNode();
+ if( pTblNd )
+ {
+ SvPtrarr aRowArr( 25, 50 ); //Zum sammeln Lines.
+ ::lcl_CollectLines( aRowArr, rCursor, false );
+
+ if( aRowArr.Count() )
+ {
+ if (GetIDocumentUndoRedo().DoesUndo())
+ {
+ GetIDocumentUndoRedo().AppendUndo(new SwUndoAttrTbl(*pTblNd));
+ }
+
+ SvPtrarr aFmtCmp( Max( sal_uInt8(255), sal_uInt8(aRowArr.Count()) ), 255 );
+
+ for( sal_uInt16 i = 0; i < aRowArr.Count(); ++i )
+ ::lcl_ProcessRowAttr( aFmtCmp, (SwTableLine*)aRowArr[i], rNew );
+
+ SwTblFmtCmp::Delete( aFmtCmp );
+ SetModified();
+ }
+ }
+}
+
+
+/******************************************************************************
+ * SwTwips SwDoc::GetRowSplit() const
+ ******************************************************************************/
+void SwDoc::GetRowSplit( const SwCursor& rCursor, SwFmtRowSplit *& rpSz ) const
+{
+ rpSz = 0;
+
+ SwTableNode* pTblNd = rCursor.GetPoint()->nNode.GetNode().FindTableNode();
+ if( pTblNd )
+ {
+ SvPtrarr aRowArr( 25, 50 ); //Zum sammeln der Lines.
+ ::lcl_CollectLines( aRowArr, rCursor, false );
+
+ if( aRowArr.Count() )
+ {
+ rpSz = &(SwFmtRowSplit&)((SwTableLine*)aRowArr[0])->
+ GetFrmFmt()->GetRowSplit();
+
+ for ( sal_uInt16 i = 1; i < aRowArr.Count() && rpSz; ++i )
+ {
+ if ( (*rpSz).GetValue() != ((SwTableLine*)aRowArr[i])->GetFrmFmt()->GetRowSplit().GetValue() )
+ rpSz = 0;
+ }
+ if ( rpSz )
+ rpSz = new SwFmtRowSplit( *rpSz );
+ }
+ }
+}
+
+
+/******************************************************************************
+ * void SwDoc::SetRowHeight( SwTwips nNew )
+ ******************************************************************************/
+void SwDoc::SetRowHeight( const SwCursor& rCursor, const SwFmtFrmSize &rNew )
+{
+ SwTableNode* pTblNd = rCursor.GetPoint()->nNode.GetNode().FindTableNode();
+ if( pTblNd )
+ {
+ SvPtrarr aRowArr( 25, 50 ); //Zum sammeln Lines.
+ ::lcl_CollectLines( aRowArr, rCursor, true );
+
+ if( aRowArr.Count() )
+ {
+ if (GetIDocumentUndoRedo().DoesUndo())
+ {
+ GetIDocumentUndoRedo().AppendUndo(new SwUndoAttrTbl(*pTblNd));
+ }
+
+ SvPtrarr aFmtCmp( Max( sal_uInt8(255), sal_uInt8(aRowArr.Count()) ), 255 );
+ for ( sal_uInt16 i = 0; i < aRowArr.Count(); ++i )
+ ::lcl_ProcessRowSize( aFmtCmp, (SwTableLine*)aRowArr[i], rNew );
+ SwTblFmtCmp::Delete( aFmtCmp );
+
+ SetModified();
+ }
+ }
+}
+
+
+/******************************************************************************
+ * SwTwips SwDoc::GetRowHeight() const
+ ******************************************************************************/
+void SwDoc::GetRowHeight( const SwCursor& rCursor, SwFmtFrmSize *& rpSz ) const
+{
+ rpSz = 0;
+
+ SwTableNode* pTblNd = rCursor.GetPoint()->nNode.GetNode().FindTableNode();
+ if( pTblNd )
+ {
+ SvPtrarr aRowArr( 25, 50 ); //Zum sammeln der Lines.
+ ::lcl_CollectLines( aRowArr, rCursor, true );
+
+ if( aRowArr.Count() )
+ {
+ rpSz = &(SwFmtFrmSize&)((SwTableLine*)aRowArr[0])->
+ GetFrmFmt()->GetFrmSize();
+
+ for ( sal_uInt16 i = 1; i < aRowArr.Count() && rpSz; ++i )
+ {
+ if ( *rpSz != ((SwTableLine*)aRowArr[i])->GetFrmFmt()->GetFrmSize() )
+ rpSz = 0;
+ }
+ if ( rpSz )
+ rpSz = new SwFmtFrmSize( *rpSz );
+ }
+ }
+}
+
+sal_Bool SwDoc::BalanceRowHeight( const SwCursor& rCursor, sal_Bool bTstOnly )
+{
+ sal_Bool bRet = sal_False;
+ SwTableNode* pTblNd = rCursor.GetPoint()->nNode.GetNode().FindTableNode();
+ if( pTblNd )
+ {
+ SvPtrarr aRowArr( 25, 50 ); //Zum sammeln der Lines.
+ ::lcl_CollectLines( aRowArr, rCursor, true );
+
+ if( 1 < aRowArr.Count() )
+ {
+ if( !bTstOnly )
+ {
+ long nHeight = 0;
+ sal_uInt16 i;
+
+ for ( i = 0; i < aRowArr.Count(); ++i )
+ {
+ SwIterator<SwFrm,SwFmt> aIter( *((SwTableLine*)aRowArr[i])->GetFrmFmt() );
+ SwFrm* pFrm = aIter.First();
+ while ( pFrm )
+ {
+ nHeight = Max( nHeight, pFrm->Frm().Height() );
+ pFrm = aIter.Next();
+ }
+ }
+ SwFmtFrmSize aNew( ATT_MIN_SIZE, 0, nHeight );
+
+ if (GetIDocumentUndoRedo().DoesUndo())
+ {
+ GetIDocumentUndoRedo().AppendUndo(
+ new SwUndoAttrTbl(*pTblNd));
+ }
+
+ SvPtrarr aFmtCmp( Max( sal_uInt8(255), sal_uInt8(aRowArr.Count()) ), 255 );
+ for( i = 0; i < aRowArr.Count(); ++i )
+ ::lcl_ProcessRowSize( aFmtCmp, (SwTableLine*)aRowArr[i], aNew );
+ SwTblFmtCmp::Delete( aFmtCmp );
+
+ SetModified();
+ }
+ bRet = sal_True;
+ }
+ }
+ return bRet;
+}
+
+/******************************************************************************
+ * void SwDoc::SetRowBackground()
+ ******************************************************************************/
+void SwDoc::SetRowBackground( const SwCursor& rCursor, const SvxBrushItem &rNew )
+{
+ SwTableNode* pTblNd = rCursor.GetPoint()->nNode.GetNode().FindTableNode();
+ if( pTblNd )
+ {
+ SvPtrarr aRowArr( 25, 50 ); //Zum sammeln Lines.
+ ::lcl_CollectLines( aRowArr, rCursor, true );
+
+ if( aRowArr.Count() )
+ {
+ if (GetIDocumentUndoRedo().DoesUndo())
+ {
+ GetIDocumentUndoRedo().AppendUndo(new SwUndoAttrTbl(*pTblNd));
+ }
+
+ SvPtrarr aFmtCmp( Max( sal_uInt8(255), sal_uInt8(aRowArr.Count()) ), 255 );
+
+ for( sal_uInt16 i = 0; i < aRowArr.Count(); ++i )
+ ::lcl_ProcessRowAttr( aFmtCmp, (SwTableLine*)aRowArr[i], rNew );
+
+ SwTblFmtCmp::Delete( aFmtCmp );
+ SetModified();
+ }
+ }
+}
+
+/******************************************************************************
+ * SwTwips SwDoc::GetRowBackground() const
+ ******************************************************************************/
+sal_Bool SwDoc::GetRowBackground( const SwCursor& rCursor, SvxBrushItem &rToFill ) const
+{
+ sal_Bool bRet = sal_False;
+ SwTableNode* pTblNd = rCursor.GetPoint()->nNode.GetNode().FindTableNode();
+ if( pTblNd )
+ {
+ SvPtrarr aRowArr( 25, 50 ); //Zum sammeln Lines.
+ ::lcl_CollectLines( aRowArr, rCursor, true );
+
+ if( aRowArr.Count() )
+ {
+ rToFill = ((SwTableLine*)aRowArr[0])->GetFrmFmt()->GetBackground();
+
+ bRet = sal_True;
+ for ( sal_uInt16 i = 1; i < aRowArr.Count(); ++i )
+ if ( rToFill != ((SwTableLine*)aRowArr[i])->GetFrmFmt()->GetBackground() )
+ {
+ bRet = sal_False;
+ break;
+ }
+ }
+ }
+ return bRet;
+}
+
+/***********************************************************************
+#* Class : SwDoc
+#* Methoden : SetTabBorders(), GetTabBorders()
+#***********************************************************************/
+inline void InsertCell( SvPtrarr& rCellArr, SwCellFrm* pCellFrm )
+{
+ if( USHRT_MAX == rCellArr.GetPos( pCellFrm ) )
+ rCellArr.Insert( pCellFrm, rCellArr.Count() );
+}
+
+//-----------------------------------------------------------------------------
+void lcl_CollectCells( SvPtrarr &rArr, const SwRect &rUnion,
+ SwTabFrm *pTab )
+{
+ SwLayoutFrm *pCell = pTab->FirstCell();
+ do
+ {
+ // Wenn in der Zelle ein spaltiger Bereich sitzt, muessen wir
+ // uns erst wieder zur Zelle hochhangeln
+ while ( !pCell->IsCellFrm() )
+ pCell = pCell->GetUpper();
+ OSL_ENSURE( pCell, "Frame ist keine Zelle." );
+ if ( rUnion.IsOver( pCell->Frm() ) )
+ ::InsertCell( rArr, (SwCellFrm*)pCell );
+ //Dafuer sorgen, dass die Zelle auch verlassen wird (Bereiche)
+ SwLayoutFrm *pTmp = pCell;
+ do
+ { pTmp = pTmp->GetNextLayoutLeaf();
+ } while ( pCell->IsAnLower( pTmp ) );
+ pCell = pTmp;
+ } while( pCell && pTab->IsAnLower( pCell ) );
+}
+
+void SwDoc::SetTabBorders( const SwCursor& rCursor, const SfxItemSet& rSet )
+{
+ SwCntntNode* pCntNd = rCursor.GetPoint()->nNode.GetNode().GetCntntNode();
+ SwTableNode* pTblNd = pCntNd ? pCntNd->FindTableNode() : 0;
+ if( !pTblNd )
+ return ;
+
+ SwLayoutFrm *pStart, *pEnd;
+ ::lcl_GetStartEndCell( rCursor, pStart, pEnd );
+
+ SwSelUnions aUnions;
+ ::MakeSelUnions( aUnions, pStart, pEnd );
+
+ if( aUnions.Count() )
+ {
+ SwTable& rTable = pTblNd->GetTable();
+ if (GetIDocumentUndoRedo().DoesUndo())
+ {
+ GetIDocumentUndoRedo().AppendUndo( new SwUndoAttrTbl(*pTblNd) );
+ }
+
+ SvPtrarr aFmtCmp( 255, 255 );
+ const SvxBoxItem* pSetBox;
+ const SvxBoxInfoItem *pSetBoxInfo;
+
+ const SvxBorderLine* pLeft = 0;
+ const SvxBorderLine* pRight = 0;
+ const SvxBorderLine* pTop = 0;
+ const SvxBorderLine* pBottom = 0;
+ const SvxBorderLine* pHori = 0;
+ const SvxBorderLine* pVert = 0;
+ sal_Bool bHoriValid = sal_True, bVertValid = sal_True,
+ bTopValid = sal_True, bBottomValid = sal_True,
+ bLeftValid = sal_True, bRightValid = sal_True;
+
+ // JP 21.07.95: die Flags im BoxInfo-Item entscheiden, wann eine
+ // BorderLine gueltig ist!!
+ if( SFX_ITEM_SET == rSet.GetItemState( SID_ATTR_BORDER_INNER, sal_False,
+ (const SfxPoolItem**)&pSetBoxInfo) )
+ {
+ pHori = pSetBoxInfo->GetHori();
+ pVert = pSetBoxInfo->GetVert();
+
+ bHoriValid = pSetBoxInfo->IsValid(VALID_HORI);
+ bVertValid = pSetBoxInfo->IsValid(VALID_VERT);
+
+ // wollen wir die auswerten ??
+ bTopValid = pSetBoxInfo->IsValid(VALID_TOP);
+ bBottomValid = pSetBoxInfo->IsValid(VALID_BOTTOM);
+ bLeftValid = pSetBoxInfo->IsValid(VALID_LEFT);
+ bRightValid = pSetBoxInfo->IsValid(VALID_RIGHT);
+ }
+
+ if( SFX_ITEM_SET == rSet.GetItemState( RES_BOX, sal_False,
+ (const SfxPoolItem**)&pSetBox) )
+ {
+ pLeft = pSetBox->GetLeft();
+ pRight = pSetBox->GetRight();
+ pTop = pSetBox->GetTop();
+ pBottom = pSetBox->GetBottom();
+ }
+ else
+ {
+ // nicht gesetzt, also keine gueltigen Werte
+ bTopValid = bBottomValid = bLeftValid = bRightValid = sal_False;
+ pSetBox = 0;
+ }
+
+ sal_Bool bFirst = sal_True;
+ for ( sal_uInt16 i = 0; i < aUnions.Count(); ++i )
+ {
+ SwSelUnion *pUnion = aUnions[i];
+ SwTabFrm *pTab = pUnion->GetTable();
+ const SwRect &rUnion = pUnion->GetUnion();
+ const sal_Bool bLast = i == aUnions.Count() - 1 ? sal_True : sal_False;
+
+ SvPtrarr aCellArr( 255, 255 );
+ ::lcl_CollectCells( aCellArr, pUnion->GetUnion(), pTab );
+
+ //Alle Zellenkanten, die mit dem UnionRect uebereinstimmen oder
+ //darueber hinausragen sind Aussenkanten. Alle anderen sind
+ //Innenkanten.
+ //neu: Die Aussenkanten koennen abhaengig davon, ob es sich um eine
+ //Start/Mittlere/Folge -Tabelle (bei Selektionen ueber FollowTabs)
+ //handelt doch keine Aussenkanten sein.
+ //Aussenkanten werden links, rechts, oben und unten gesetzt.
+ //Innenkanten werden nur oben und links gesetzt.
+ for ( sal_uInt16 j = 0; j < aCellArr.Count(); ++j )
+ {
+ SwCellFrm *pCell = (SwCellFrm*)aCellArr[j];
+ const sal_Bool bVert = pTab->IsVertical();
+ const sal_Bool bRTL = pTab->IsRightToLeft();
+ sal_Bool bTopOver, bLeftOver, bRightOver, bBottomOver;
+ if ( bVert )
+ {
+ bTopOver = pCell->Frm().Right() >= rUnion.Right();
+ bLeftOver = pCell->Frm().Top() <= rUnion.Top();
+ bRightOver = pCell->Frm().Bottom() >= rUnion.Bottom();
+ bBottomOver = pCell->Frm().Left() <= rUnion.Left();
+ }
+ else
+ {
+ bTopOver = pCell->Frm().Top() <= rUnion.Top();
+ bLeftOver = pCell->Frm().Left() <= rUnion.Left();
+ bRightOver = pCell->Frm().Right() >= rUnion.Right();
+ bBottomOver = pCell->Frm().Bottom() >= rUnion.Bottom();
+ }
+
+ if ( bRTL )
+ {
+ sal_Bool bTmp = bRightOver;
+ bRightOver = bLeftOver;
+ bLeftOver = bTmp;
+ }
+
+ //Grundsaetzlich nichts setzen in HeadlineRepeats.
+ if ( pTab->IsFollow() &&
+ ( pTab->IsInHeadline( *pCell ) ||
+ // Same holds for follow flow rows.
+ pCell->IsInFollowFlowRow() ) )
+ continue;
+
+ SvxBoxItem aBox( pCell->GetFmt()->GetBox() );
+
+ sal_Int16 nType = 0;
+
+ //Obere Kante
+ if( bTopValid )
+ {
+ if ( bFirst && bTopOver )
+ {
+ aBox.SetLine( pTop, BOX_LINE_TOP );
+ nType |= 0x0001;
+ }
+ else if ( bHoriValid )
+ {
+ aBox.SetLine( 0, BOX_LINE_TOP );
+ nType |= 0x0002;
+ }
+ }
+
+ //Linke Kante
+ if ( bLeftOver )
+ {
+ if( bLeftValid )
+ {
+ aBox.SetLine( pLeft, BOX_LINE_LEFT );
+ nType |= 0x0004;
+ }
+ }
+ else if( bVertValid )
+ {
+ aBox.SetLine( pVert, BOX_LINE_LEFT );
+ nType |= 0x0008;
+ }
+
+ //Rechte Kante
+ if( bRightValid )
+ {
+ if ( bRightOver )
+ {
+ aBox.SetLine( pRight, BOX_LINE_RIGHT );
+ nType |= 0x0010;
+ }
+ else if ( bVertValid )
+ {
+ aBox.SetLine( 0, BOX_LINE_RIGHT );
+ nType |= 0x0020;
+ }
+ }
+
+ //Untere Kante
+ if ( bLast && bBottomOver )
+ {
+ if( bBottomValid )
+ {
+ aBox.SetLine( pBottom, BOX_LINE_BOTTOM );
+ nType |= 0x0040;
+ }
+ }
+ else if( bHoriValid )
+ {
+ aBox.SetLine( pHori, BOX_LINE_BOTTOM );
+ nType |= 0x0080;
+ }
+
+ if( pSetBox )
+ {
+ static sal_uInt16 const aBorders[] = {
+ BOX_LINE_BOTTOM, BOX_LINE_TOP,
+ BOX_LINE_RIGHT, BOX_LINE_LEFT };
+ const sal_uInt16* pBrd = aBorders;
+ for( int k = 0; k < 4; ++k, ++pBrd )
+ aBox.SetDistance( pSetBox->GetDistance( *pBrd ), *pBrd );
+ }
+
+ SwTableBox *pBox = (SwTableBox*)pCell->GetTabBox();
+ SwFrmFmt *pNewFmt;
+ if ( 0 != (pNewFmt = SwTblFmtCmp::FindNewFmt( aFmtCmp, pBox->GetFrmFmt(), nType )))
+ pBox->ChgFrmFmt( (SwTableBoxFmt*)pNewFmt );
+ else
+ {
+ SwFrmFmt *pOld = pBox->GetFrmFmt();
+ SwFrmFmt *pNew = pBox->ClaimFrmFmt();
+ pNew->SetFmtAttr( aBox );
+ aFmtCmp.Insert( new SwTblFmtCmp( pOld, pNew, nType ), aFmtCmp.Count());
+ }
+ }
+
+ bFirst = sal_False;
+ }
+
+ SwHTMLTableLayout *pTableLayout = rTable.GetHTMLTableLayout();
+ if( pTableLayout )
+ {
+ SwCntntFrm* pFrm = rCursor.GetCntntNode()->getLayoutFrm( rCursor.GetCntntNode()->GetDoc()->GetCurrentLayout() );
+ SwTabFrm* pTabFrm = pFrm->ImplFindTabFrm();
+
+ pTableLayout->BordersChanged(
+ pTableLayout->GetBrowseWidthByTabFrm( *pTabFrm ), sal_True );
+ }
+ SwTblFmtCmp::Delete( aFmtCmp );
+ ::ClearFEShellTabCols();
+ SetModified();
+ }
+}
+
+void lcl_SetLineStyle( SvxBorderLine *pToSet,
+ const Color *pColor, const SvxBorderLine *pBorderLine)
+{
+ if ( pBorderLine )
+ {
+ if ( !pColor )
+ {
+ Color aTmp( pToSet->GetColor() );
+ *pToSet = *pBorderLine;
+ pToSet->SetColor( aTmp );
+ }
+ else
+ *pToSet = *pBorderLine;
+ }
+ if ( pColor )
+ pToSet->SetColor( *pColor );
+}
+
+void SwDoc::SetTabLineStyle( const SwCursor& rCursor,
+ const Color* pColor, sal_Bool bSetLine,
+ const SvxBorderLine* pBorderLine )
+{
+ SwCntntNode* pCntNd = rCursor.GetPoint()->nNode.GetNode().GetCntntNode();
+ SwTableNode* pTblNd = pCntNd ? pCntNd->FindTableNode() : 0;
+ if( !pTblNd )
+ return ;
+
+ SwLayoutFrm *pStart, *pEnd;
+ ::lcl_GetStartEndCell( rCursor, pStart, pEnd );
+
+ SwSelUnions aUnions;
+ ::MakeSelUnions( aUnions, pStart, pEnd );
+
+ if( aUnions.Count() )
+ {
+ SwTable& rTable = pTblNd->GetTable();
+ if (GetIDocumentUndoRedo().DoesUndo())
+ {
+ GetIDocumentUndoRedo().AppendUndo(new SwUndoAttrTbl(*pTblNd));
+ }
+
+ for( sal_uInt16 i = 0; i < aUnions.Count(); ++i )
+ {
+ SwSelUnion *pUnion = aUnions[i];
+ SwTabFrm *pTab = pUnion->GetTable();
+ SvPtrarr aCellArr( 255, 255 );
+ ::lcl_CollectCells( aCellArr, pUnion->GetUnion(), pTab );
+
+ for ( sal_uInt16 j = 0; j < aCellArr.Count(); ++j )
+ {
+ SwCellFrm *pCell = ( SwCellFrm* )aCellArr[j];
+
+ //Grundsaetzlich nichts setzen in HeadlineRepeats.
+ if ( pTab->IsFollow() && pTab->IsInHeadline( *pCell ) )
+ continue;
+
+ ((SwTableBox*)pCell->GetTabBox())->ClaimFrmFmt();
+ SwFrmFmt *pFmt = pCell->GetFmt();
+ SvxBoxItem aBox( pFmt->GetBox() );
+
+ if ( !pBorderLine && bSetLine )
+ aBox = *(SvxBoxItem*)::GetDfltAttr( RES_BOX );
+ else
+ {
+ if ( aBox.GetTop() )
+ ::lcl_SetLineStyle( (SvxBorderLine*)aBox.GetTop(),
+ pColor, pBorderLine );
+ if ( aBox.GetBottom() )
+ ::lcl_SetLineStyle( (SvxBorderLine*)aBox.GetBottom(),
+ pColor, pBorderLine );
+ if ( aBox.GetLeft() )
+ ::lcl_SetLineStyle( (SvxBorderLine*)aBox.GetLeft(),
+ pColor, pBorderLine );
+ if ( aBox.GetRight() )
+ ::lcl_SetLineStyle( (SvxBorderLine*)aBox.GetRight(),
+ pColor, pBorderLine );
+ }
+ pFmt->SetFmtAttr( aBox );
+ }
+ }
+
+ SwHTMLTableLayout *pTableLayout = rTable.GetHTMLTableLayout();
+ if( pTableLayout )
+ {
+ SwCntntFrm* pFrm = rCursor.GetCntntNode()->getLayoutFrm( rCursor.GetCntntNode()->GetDoc()->GetCurrentLayout() );
+ SwTabFrm* pTabFrm = pFrm->ImplFindTabFrm();
+
+ pTableLayout->BordersChanged(
+ pTableLayout->GetBrowseWidthByTabFrm( *pTabFrm ), sal_True );
+ }
+ ::ClearFEShellTabCols();
+ SetModified();
+ }
+}
+
+void SwDoc::GetTabBorders( const SwCursor& rCursor, SfxItemSet& rSet ) const
+{
+ SwCntntNode* pCntNd = rCursor.GetPoint()->nNode.GetNode().GetCntntNode();
+ SwTableNode* pTblNd = pCntNd ? pCntNd->FindTableNode() : 0;
+ if( !pTblNd )
+ return ;
+
+ SwLayoutFrm *pStart, *pEnd;
+ ::lcl_GetStartEndCell( rCursor, pStart, pEnd );
+
+ SwSelUnions aUnions;
+ ::MakeSelUnions( aUnions, pStart, pEnd );
+
+ if( aUnions.Count() )
+ {
+ SvxBoxItem aSetBox ((const SvxBoxItem &) rSet.Get(RES_BOX ));
+ SvxBoxInfoItem aSetBoxInfo((const SvxBoxInfoItem&) rSet.Get(SID_ATTR_BORDER_INNER));
+
+ sal_Bool bTopSet = sal_False,
+ bBottomSet = sal_False,
+ bLeftSet = sal_False,
+ bRightSet = sal_False,
+ bHoriSet = sal_False,
+ bVertSet = sal_False,
+ bDistanceSet = sal_False;
+
+ aSetBoxInfo.ResetFlags();
+
+ for ( sal_uInt16 i = 0; i < aUnions.Count(); ++i )
+ {
+ SwSelUnion *pUnion = aUnions[i];
+ const SwTabFrm *pTab = pUnion->GetTable();
+ const SwRect &rUnion = pUnion->GetUnion();
+ const sal_Bool bFirst = i == 0 ? sal_True : sal_False;
+ const sal_Bool bLast = i == aUnions.Count() - 1 ? sal_True : sal_False;
+
+ SvPtrarr aCellArr( 255, 255 );
+ ::lcl_CollectCells( aCellArr, rUnion, (SwTabFrm*)pTab );
+
+ for ( sal_uInt16 j = 0; j < aCellArr.Count(); ++j )
+ {
+ const SwCellFrm *pCell = (const SwCellFrm*)aCellArr[j];
+ const sal_Bool bVert = pTab->IsVertical();
+ const sal_Bool bRTL = pTab->IsRightToLeft();
+ sal_Bool bTopOver, bLeftOver, bRightOver, bBottomOver;
+ if ( bVert )
+ {
+ bTopOver = pCell->Frm().Right() >= rUnion.Right();
+ bLeftOver = pCell->Frm().Top() <= rUnion.Top();
+ bRightOver = pCell->Frm().Bottom() >= rUnion.Bottom();
+ bBottomOver = pCell->Frm().Left() <= rUnion.Left();
+ }
+ else
+ {
+ bTopOver = pCell->Frm().Top() <= rUnion.Top();
+ bLeftOver = pCell->Frm().Left() <= rUnion.Left();
+ bRightOver = pCell->Frm().Right() >= rUnion.Right();
+ bBottomOver = pCell->Frm().Bottom() >= rUnion.Bottom();
+ }
+
+ if ( bRTL )
+ {
+ sal_Bool bTmp = bRightOver;
+ bRightOver = bLeftOver;
+ bLeftOver = bTmp;
+ }
+
+ const SwFrmFmt *pFmt = pCell->GetFmt();
+ const SvxBoxItem &rBox = pFmt->GetBox();
+
+ //Obere Kante
+ if ( bFirst && bTopOver )
+ {
+ if (aSetBoxInfo.IsValid(VALID_TOP))
+ {
+ if ( !bTopSet )
+ { bTopSet = sal_True;
+ aSetBox.SetLine( rBox.GetTop(), BOX_LINE_TOP );
+ }
+ else if ((aSetBox.GetTop() && rBox.GetTop() &&
+ !(*aSetBox.GetTop() == *rBox.GetTop())) ||
+ ((!aSetBox.GetTop()) ^ (!rBox.GetTop()))) // XOR-Ausdruck ist sal_True, wenn genau einer der beiden Pointer 0 ist
+ {
+ aSetBoxInfo.SetValid(VALID_TOP, sal_False );
+ aSetBox.SetLine( 0, BOX_LINE_TOP );
+ }
+ }
+ }
+
+ //Linke Kante
+ if ( bLeftOver )
+ {
+ if (aSetBoxInfo.IsValid(VALID_LEFT))
+ {
+ if ( !bLeftSet )
+ { bLeftSet = sal_True;
+ aSetBox.SetLine( rBox.GetLeft(), BOX_LINE_LEFT );
+ }
+ else if ((aSetBox.GetLeft() && rBox.GetLeft() &&
+ !(*aSetBox.GetLeft() == *rBox.GetLeft())) ||
+ ((!aSetBox.GetLeft()) ^ (!rBox.GetLeft())))
+ {
+ aSetBoxInfo.SetValid(VALID_LEFT, sal_False );
+ aSetBox.SetLine( 0, BOX_LINE_LEFT );
+ }
+ }
+ }
+ else
+ {
+ if (aSetBoxInfo.IsValid(VALID_VERT))
+ {
+ if ( !bVertSet )
+ { bVertSet = sal_True;
+ aSetBoxInfo.SetLine( rBox.GetLeft(), BOXINFO_LINE_VERT );
+ }
+ else if ((aSetBoxInfo.GetVert() && rBox.GetLeft() &&
+ !(*aSetBoxInfo.GetVert() == *rBox.GetLeft())) ||
+ ((!aSetBoxInfo.GetVert()) ^ (!rBox.GetLeft())))
+ { aSetBoxInfo.SetValid( VALID_VERT, sal_False );
+ aSetBoxInfo.SetLine( 0, BOXINFO_LINE_VERT );
+ }
+ }
+ }
+
+ //Rechte Kante
+ if ( aSetBoxInfo.IsValid(VALID_RIGHT) && bRightOver )
+ {
+ if ( !bRightSet )
+ { bRightSet = sal_True;
+ aSetBox.SetLine( rBox.GetRight(), BOX_LINE_RIGHT );
+ }
+ else if ((aSetBox.GetRight() && rBox.GetRight() &&
+ !(*aSetBox.GetRight() == *rBox.GetRight())) ||
+ (!aSetBox.GetRight() ^ !rBox.GetRight()))
+ { aSetBoxInfo.SetValid( VALID_RIGHT, sal_False );
+ aSetBox.SetLine( 0, BOX_LINE_RIGHT );
+ }
+ }
+
+ //Untere Kante
+ if ( bLast && bBottomOver )
+ {
+ if ( aSetBoxInfo.IsValid(VALID_BOTTOM) )
+ {
+ if ( !bBottomSet )
+ { bBottomSet = sal_True;
+ aSetBox.SetLine( rBox.GetBottom(), BOX_LINE_BOTTOM );
+ }
+ else if ((aSetBox.GetBottom() && rBox.GetBottom() &&
+ !(*aSetBox.GetBottom() == *rBox.GetBottom())) ||
+ (!aSetBox.GetBottom() ^ !rBox.GetBottom()))
+ { aSetBoxInfo.SetValid( VALID_BOTTOM, sal_False );
+ aSetBox.SetLine( 0, BOX_LINE_BOTTOM );
+ }
+ }
+ }
+ //in allen Zeilen ausser der letzten werden die
+ // horiz. Linien aus der Bottom-Linie entnommen
+ else
+ {
+ if (aSetBoxInfo.IsValid(VALID_HORI))
+ {
+ if ( !bHoriSet )
+ { bHoriSet = sal_True;
+ aSetBoxInfo.SetLine( rBox.GetBottom(), BOXINFO_LINE_HORI );
+ }
+ else if ((aSetBoxInfo.GetHori() && rBox.GetBottom() &&
+ !(*aSetBoxInfo.GetHori() == *rBox.GetBottom())) ||
+ ((!aSetBoxInfo.GetHori()) ^ (!rBox.GetBottom())))
+ {
+ aSetBoxInfo.SetValid( VALID_HORI, sal_False );
+ aSetBoxInfo.SetLine( 0, BOXINFO_LINE_HORI );
+ }
+ }
+ }
+
+ // Abstand zum Text
+ if (aSetBoxInfo.IsValid(VALID_DISTANCE))
+ {
+ static sal_uInt16 const aBorders[] = {
+ BOX_LINE_BOTTOM, BOX_LINE_TOP,
+ BOX_LINE_RIGHT, BOX_LINE_LEFT };
+ const sal_uInt16* pBrd = aBorders;
+
+ if( !bDistanceSet ) // bei 1. Durchlauf erstmal setzen
+ {
+ bDistanceSet = sal_True;
+ for( int k = 0; k < 4; ++k, ++pBrd )
+ aSetBox.SetDistance( rBox.GetDistance( *pBrd ),
+ *pBrd );
+ }
+ else
+ {
+ for( int k = 0; k < 4; ++k, ++pBrd )
+ if( aSetBox.GetDistance( *pBrd ) !=
+ rBox.GetDistance( *pBrd ) )
+ {
+ aSetBoxInfo.SetValid( VALID_DISTANCE, sal_False );
+ aSetBox.SetDistance( (sal_uInt16) 0 );
+ break;
+ }
+ }
+ }
+ }
+ }
+ rSet.Put( aSetBox );
+ rSet.Put( aSetBoxInfo );
+ }
+}
+
+/***********************************************************************
+#* Class : SwDoc
+#* Methoden : SetBoxAttr
+#***********************************************************************/
+void SwDoc::SetBoxAttr( const SwCursor& rCursor, const SfxPoolItem &rNew )
+{
+ SwTableNode* pTblNd = rCursor.GetPoint()->nNode.GetNode().FindTableNode();
+ SwSelBoxes aBoxes;
+ if( pTblNd && ::lcl_GetBoxSel( rCursor, aBoxes, sal_True ) )
+ {
+ SwTable& rTable = pTblNd->GetTable();
+ if (GetIDocumentUndoRedo().DoesUndo())
+ {
+ GetIDocumentUndoRedo().AppendUndo( new SwUndoAttrTbl(*pTblNd) );
+ }
+
+ SvPtrarr aFmtCmp( Max( sal_uInt8(255), sal_uInt8(aBoxes.Count()) ), 255 );
+ for ( sal_uInt16 i = 0; i < aBoxes.Count(); ++i )
+ {
+ SwTableBox *pBox = aBoxes[i];
+
+ SwFrmFmt *pNewFmt;
+ if ( 0 != (pNewFmt = SwTblFmtCmp::FindNewFmt( aFmtCmp, pBox->GetFrmFmt(), 0 )))
+ pBox->ChgFrmFmt( (SwTableBoxFmt*)pNewFmt );
+ else
+ {
+ SwFrmFmt *pOld = pBox->GetFrmFmt();
+ SwFrmFmt *pNew = pBox->ClaimFrmFmt();
+ pNew->SetFmtAttr( rNew );
+ aFmtCmp.Insert( new SwTblFmtCmp( pOld, pNew, 0 ), aFmtCmp.Count());
+ }
+ }
+
+ SwHTMLTableLayout *pTableLayout = rTable.GetHTMLTableLayout();
+ if( pTableLayout )
+ {
+ SwCntntFrm* pFrm = rCursor.GetCntntNode()->getLayoutFrm( rCursor.GetCntntNode()->GetDoc()->GetCurrentLayout() );
+ SwTabFrm* pTabFrm = pFrm->ImplFindTabFrm();
+
+ pTableLayout->Resize(
+ pTableLayout->GetBrowseWidthByTabFrm( *pTabFrm ), sal_True );
+ }
+ SwTblFmtCmp::Delete( aFmtCmp );
+ SetModified();
+ }
+}
+
+/***********************************************************************
+#* Class : SwDoc
+#* Methoden : GetBoxAttr()
+#***********************************************************************/
+
+sal_Bool SwDoc::GetBoxAttr( const SwCursor& rCursor, SfxPoolItem& rToFill ) const
+{
+ sal_Bool bRet = sal_False;
+ SwTableNode* pTblNd = rCursor.GetPoint()->nNode.GetNode().FindTableNode();
+ SwSelBoxes aBoxes;
+ if( pTblNd && lcl_GetBoxSel( rCursor, aBoxes ))
+ {
+ bRet = sal_True;
+ sal_Bool bOneFound = sal_False;
+ const sal_uInt16 nWhich = rToFill.Which();
+ for( sal_uInt16 i = 0; i < aBoxes.Count(); ++i )
+ {
+ switch ( nWhich )
+ {
+ case RES_BACKGROUND:
+ {
+ const SvxBrushItem &rBack =
+ aBoxes[i]->GetFrmFmt()->GetBackground();
+ if( !bOneFound )
+ {
+ (SvxBrushItem&)rToFill = rBack;
+ bOneFound = sal_True;
+ }
+ else if( rToFill != rBack )
+ bRet = sal_False;
+ }
+ break;
+
+ case RES_FRAMEDIR:
+ {
+ const SvxFrameDirectionItem& rDir =
+ aBoxes[i]->GetFrmFmt()->GetFrmDir();
+ if( !bOneFound )
+ {
+ (SvxFrameDirectionItem&)rToFill = rDir;
+ bOneFound = sal_True;
+ }
+ else if( rToFill != rDir )
+ bRet = sal_False;
+ }
+ case RES_VERT_ORIENT:
+ {
+ const SwFmtVertOrient& rOrient =
+ aBoxes[i]->GetFrmFmt()->GetVertOrient();
+ if( !bOneFound )
+ {
+ (SwFmtVertOrient&)rToFill = rOrient;
+ bOneFound = sal_True;
+ }
+ else if( rToFill != rOrient )
+ bRet = sal_False;
+ }
+ }
+
+ if ( sal_False == bRet )
+ break;
+ }
+ }
+ return bRet;
+}
+
+/***********************************************************************
+#* Class : SwDoc
+#* Methoden : SetBoxAlign, SetBoxAlign
+#***********************************************************************/
+void SwDoc::SetBoxAlign( const SwCursor& rCursor, sal_uInt16 nAlign )
+{
+ OSL_ENSURE( nAlign == text::VertOrientation::NONE ||
+ nAlign == text::VertOrientation::CENTER ||
+ nAlign == text::VertOrientation::BOTTOM, "wrong alignment" );
+ SwFmtVertOrient aVertOri( 0, nAlign );
+ SetBoxAttr( rCursor, aVertOri );
+}
+
+sal_uInt16 SwDoc::GetBoxAlign( const SwCursor& rCursor ) const
+{
+ sal_uInt16 nAlign = USHRT_MAX;
+ SwTableNode* pTblNd = rCursor.GetPoint()->nNode.GetNode().FindTableNode();
+ SwSelBoxes aBoxes;
+ if( pTblNd && ::lcl_GetBoxSel( rCursor, aBoxes ))
+ for( sal_uInt16 i = 0; i < aBoxes.Count(); ++i )
+ {
+ const SwFmtVertOrient &rOri =
+ aBoxes[i]->GetFrmFmt()->GetVertOrient();
+ if( USHRT_MAX == nAlign )
+ nAlign = static_cast<sal_uInt16>(rOri.GetVertOrient());
+ else if( rOri.GetVertOrient() != nAlign )
+ {
+ nAlign = USHRT_MAX;
+ break;
+ }
+ }
+ return nAlign;
+}
+
+
+/***********************************************************************
+#* Class : SwDoc
+#* Methoden : AdjustCellWidth()
+#***********************************************************************/
+sal_uInt16 lcl_CalcCellFit( const SwLayoutFrm *pCell )
+{
+ SwTwips nRet = 0;
+ const SwFrm *pFrm = pCell->Lower(); //Die ganze Zelle.
+ SWRECTFN( pCell )
+ while ( pFrm )
+ {
+ const SwTwips nAdd = (pFrm->Frm().*fnRect->fnGetWidth)() -
+ (pFrm->Prt().*fnRect->fnGetWidth)();
+
+ // pFrm does not necessarily have to be a SwTxtFrm!
+ const SwTwips nCalcFitToContent = pFrm->IsTxtFrm() ?
+ ((SwTxtFrm*)pFrm)->CalcFitToContent() :
+ (pFrm->Prt().*fnRect->fnGetWidth)();
+
+ nRet = Max( nRet, nCalcFitToContent + nAdd );
+ pFrm = pFrm->GetNext();
+ }
+ //Umrandung und linker/rechter Rand wollen mit kalkuliert werden.
+ nRet += (pCell->Frm().*fnRect->fnGetWidth)() -
+ (pCell->Prt().*fnRect->fnGetWidth)();
+
+ //Um Rechenungenauikeiten, die spaeter bei SwTable::SetTabCols enstehen,
+ //auszugleichen, addieren wir noch ein bischen.
+ nRet += COLFUZZY;
+ return (sal_uInt16)Max( long(MINLAY), nRet );
+}
+
+/*Die Zelle ist in der Selektion, wird aber nicht von den TabCols beschrieben.
+ *Das bedeutet, dass die Zelle aufgrund der zweidimensionalen Darstellung von
+ *anderen Zellen "geteilt" wurde. Wir muessen also den Wunsch- bzw. Minimalwert
+ *der Zelle auf die Spalten, durch die sie geteilt wurde verteilen.
+ *
+ *Dazu sammeln wir zuerst die Spalten - nicht die Spaltentrenner! - ein, die
+ *sich mit der Zelle ueberschneiden. Den Wunschwert der Zelle verteilen wir
+ *dann anhand des Betrages der Ueberschneidung auf die Zellen.
+ *Wenn eine Zelle bereits einen groesseren Wunschwert angemeldet hat, so bleibt
+ *dieser erhalten, kleinere Wuensche werden ueberschrieben.
+ */
+
+void lcl_CalcSubColValues( SvUShorts &rToFill, const SwTabCols &rCols,
+ const SwLayoutFrm *pCell, const SwLayoutFrm *pTab,
+ sal_Bool bWishValues )
+{
+ const sal_uInt16 nWish = bWishValues ?
+ ::lcl_CalcCellFit( pCell ) :
+ MINLAY + sal_uInt16(pCell->Frm().Width() - pCell->Prt().Width());
+
+ SWRECTFN( pTab )
+
+ for ( sal_uInt16 i = 0 ; i <= rCols.Count(); ++i )
+ {
+ long nColLeft = i == 0 ? rCols.GetLeft() : rCols[i-1];
+ long nColRight = i == rCols.Count() ? rCols.GetRight() : rCols[i];
+ nColLeft += rCols.GetLeftMin();
+ nColRight += rCols.GetLeftMin();
+
+ //Werte auf die Verhaeltnisse der Tabelle (Follows) anpassen.
+ if ( rCols.GetLeftMin() != sal_uInt16((pTab->Frm().*fnRect->fnGetLeft)()) )
+ {
+ const long nDiff = (pTab->Frm().*fnRect->fnGetLeft)() - rCols.GetLeftMin();
+ nColLeft += nDiff;
+ nColRight += nDiff;
+ }
+ const long nCellLeft = (pCell->Frm().*fnRect->fnGetLeft)();
+ const long nCellRight = (pCell->Frm().*fnRect->fnGetRight)();
+
+ //Ueberschneidungsbetrag ermitteln.
+ long nWidth = 0;
+ if ( nColLeft <= nCellLeft && nColRight >= (nCellLeft+COLFUZZY) )
+ nWidth = nColRight - nCellLeft;
+ else if ( nColLeft <= (nCellRight-COLFUZZY) && nColRight >= nCellRight )
+ nWidth = nCellRight - nColLeft;
+ else if ( nColLeft >= nCellLeft && nColRight <= nCellRight )
+ nWidth = nColRight - nColLeft;
+ if ( nWidth && pCell->Frm().Width() )
+ {
+ long nTmp = nWidth * nWish / pCell->Frm().Width();
+ if ( sal_uInt16(nTmp) > rToFill[i] )
+ rToFill[i] = sal_uInt16(nTmp);
+ }
+ }
+}
+
+/*Besorgt neue Werte zu Einstellung der TabCols.
+ *Es wird nicht ueber die Eintrage in den TabCols itereriert, sondern
+ *quasi ueber die Zwischenraeume, die ja die Zellen beschreiben.
+ *
+ *bWishValues == sal_True: Es werden zur aktuellen Selektion bzw. zur aktuellen
+ * Zelle die Wunschwerte aller betroffen Zellen ermittelt.
+ * Sind mehrere Zellen in einer Spalte, so wird der
+ * groesste Wunschwert als Ergebnis geliefert.
+ * Fuer die TabCol-Eintraege, zu denen keine Zellen
+ * ermittelt wurden, werden 0-en eingetragen.
+ *
+ *bWishValues == sal_False: Die Selektion wird senkrecht ausgedehnt. Zu jeder
+ * Spalte in den TabCols, die sich mit der Selektion
+ * schneidet wird der Minimalwert ermittelt.
+ */
+
+void lcl_CalcColValues( SvUShorts &rToFill, const SwTabCols &rCols,
+ const SwLayoutFrm *pStart, const SwLayoutFrm *pEnd,
+ sal_Bool bWishValues )
+{
+ SwSelUnions aUnions;
+ ::MakeSelUnions( aUnions, pStart, pEnd,
+ bWishValues ? nsSwTblSearchType::TBLSEARCH_NONE : nsSwTblSearchType::TBLSEARCH_COL );
+
+ for ( sal_uInt16 i2 = 0; i2 < aUnions.Count(); ++i2 )
+ {
+ SwSelUnion *pSelUnion = aUnions[i2];
+ const SwTabFrm *pTab = pSelUnion->GetTable();
+ const SwRect &rUnion = pSelUnion->GetUnion();
+
+ SWRECTFN( pTab )
+ sal_Bool bRTL = pTab->IsRightToLeft();
+
+ const SwLayoutFrm *pCell = pTab->FirstCell();
+ do
+ {
+ if ( pCell->IsCellFrm() && pCell->FindTabFrm() == pTab && ::IsFrmInTblSel( rUnion, pCell ) )
+ {
+ const long nCLeft = (pCell->Frm().*fnRect->fnGetLeft)();
+ const long nCRight = (pCell->Frm().*fnRect->fnGetRight)();
+
+ sal_Bool bNotInCols = sal_True;
+
+ for ( sal_uInt16 i = 0; i <= rCols.Count(); ++i )
+ {
+ sal_uInt16 nFit = rToFill[i];
+ long nColLeft = i == 0 ? rCols.GetLeft() : rCols[i-1];
+ long nColRight = i == rCols.Count() ? rCols.GetRight() : rCols[i];
+
+ if ( bRTL )
+ {
+ long nTmpRight = nColRight;
+ nColRight = rCols.GetRight() - nColLeft;
+ nColLeft = rCols.GetRight() - nTmpRight;
+ }
+
+ nColLeft += rCols.GetLeftMin();
+ nColRight += rCols.GetLeftMin();
+
+ //Werte auf die Verhaeltnisse der Tabelle (Follows) anpassen.
+ long nLeftA = nColLeft;
+ long nRightA = nColRight;
+ if ( rCols.GetLeftMin() != sal_uInt16((pTab->Frm().*fnRect->fnGetLeft)()) )
+ {
+ const long nDiff = (pTab->Frm().*fnRect->fnGetLeft)() - rCols.GetLeftMin();
+ nLeftA += nDiff;
+ nRightA += nDiff;
+ }
+
+ //Wir wollen nicht allzu genau hinsehen.
+ if ( ::IsSame(nCLeft, nLeftA) && ::IsSame(nCRight, nRightA))
+ {
+ bNotInCols = sal_False;
+ if ( bWishValues )
+ {
+ const sal_uInt16 nWish = ::lcl_CalcCellFit( pCell );
+ if ( nWish > nFit )
+ nFit = nWish;
+ }
+ else
+ { const sal_uInt16 nMin = MINLAY + sal_uInt16(pCell->Frm().Width() -
+ pCell->Prt().Width());
+ if ( !nFit || nMin < nFit )
+ nFit = nMin;
+ }
+ if ( rToFill[i] < nFit )
+ rToFill[i] = nFit;
+ }
+ }
+ if ( bNotInCols )
+ ::lcl_CalcSubColValues( rToFill, rCols, pCell, pTab, bWishValues );
+ }
+ do {
+ pCell = pCell->GetNextLayoutLeaf();
+ }while( pCell && pCell->Frm().Width() == 0 );
+ } while ( pCell && pTab->IsAnLower( pCell ) );
+ }
+}
+
+
+void SwDoc::AdjustCellWidth( const SwCursor& rCursor, sal_Bool bBalance )
+{
+ // pruefe ob vom aktuellen Crsr der Point/Mark in einer Tabelle stehen
+ SwCntntNode* pCntNd = rCursor.GetPoint()->nNode.GetNode().GetCntntNode();
+ SwTableNode* pTblNd = pCntNd ? pCntNd->FindTableNode() : 0;
+ if( !pTblNd )
+ return ;
+
+ SwLayoutFrm *pStart, *pEnd;
+ ::lcl_GetStartEndCell( rCursor, pStart, pEnd );
+
+ //TabCols besorgen, den ueber diese stellen wir die Tabelle neu ein.
+ SwFrm* pBoxFrm = pStart;
+ while( pBoxFrm && !pBoxFrm->IsCellFrm() )
+ pBoxFrm = pBoxFrm->GetUpper();
+
+ if ( !pBoxFrm )
+ return; // robust
+
+ SwTabCols aTabCols;
+ GetTabCols( aTabCols, 0, (SwCellFrm*)pBoxFrm );
+
+ if ( ! aTabCols.Count() )
+ return;
+
+ const sal_uInt8 nTmp = (sal_uInt8)Max( sal_uInt16(255), sal_uInt16(aTabCols.Count() + 1) );
+ SvUShorts aWish( nTmp, nTmp ),
+ aMins( nTmp, nTmp );
+ sal_uInt16 i;
+
+ for ( i = 0; i <= aTabCols.Count(); ++i )
+ {
+ aWish.Insert( sal_uInt16(0), aWish.Count() );
+ aMins.Insert( sal_uInt16(0), aMins.Count() );
+ }
+ ::lcl_CalcColValues( aWish, aTabCols, pStart, pEnd, sal_True );
+
+ //Es ist Robuster wenn wir die Min-Werte fuer die ganze Tabelle berechnen.
+ const SwTabFrm *pTab = pStart->ImplFindTabFrm();
+ pStart = (SwLayoutFrm*)pTab->FirstCell();
+ pEnd = (SwLayoutFrm*)pTab->FindLastCntnt()->GetUpper();
+ while( !pEnd->IsCellFrm() )
+ pEnd = pEnd->GetUpper();
+ ::lcl_CalcColValues( aMins, aTabCols, pStart, pEnd, sal_False );
+
+ if( bBalance )
+ {
+ //Alle Spalten, die makiert sind haben jetzt einen Wunschwert
+ //eingtragen. Wir addieren die aktuellen Werte, teilen das Ergebnis
+ //durch die Anzahl und haben eine Wunschwert fuer den ausgleich.
+ sal_uInt16 nWish = 0, nCnt = 0;
+ for ( i = 0; i <= aTabCols.Count(); ++i )
+ {
+ int nDiff = aWish[i];
+ if ( nDiff )
+ {
+ if ( i == 0 )
+ nWish = static_cast<sal_uInt16>( nWish + aTabCols[i] - aTabCols.GetLeft() );
+ else if ( i == aTabCols.Count() )
+ nWish = static_cast<sal_uInt16>(nWish + aTabCols.GetRight() - aTabCols[i-1] );
+ else
+ nWish = static_cast<sal_uInt16>(nWish + aTabCols[i] - aTabCols[i-1] );
+ ++nCnt;
+ }
+ }
+ nWish = nWish / nCnt;
+ for ( i = 0; i < aWish.Count(); ++i )
+ if ( aWish[i] )
+ aWish[i] = nWish;
+ }
+
+ const sal_uInt16 nOldRight = static_cast<sal_uInt16>(aTabCols.GetRight());
+
+ //Um die Impl. einfach zu gestalten, aber trotzdem in den meissten Faellen
+ //den Platz richtig auszunutzen laufen wir zweimal.
+ //Problem: Erste Spalte wird breiter, die anderen aber erst danach
+ //schmaler. Die Wunschbreite der ersten Spalte wuerde abgelehnt, weil
+ //mit ihr die max. Breite der Tabelle ueberschritten wuerde.
+ for ( sal_uInt16 k= 0; k < 2; ++k )
+ {
+ for ( i = 0; i <= aTabCols.Count(); ++i )
+ {
+ int nDiff = aWish[i];
+ if ( nDiff )
+ {
+ int nMin = aMins[i];
+ if ( nMin > nDiff )
+ nDiff = nMin;
+
+ if ( i == 0 )
+ {
+ if( aTabCols.Count() )
+ nDiff -= aTabCols[0] - aTabCols.GetLeft();
+ else
+ nDiff -= aTabCols.GetRight() - aTabCols.GetLeft();
+ }
+ else if ( i == aTabCols.Count() )
+ nDiff -= aTabCols.GetRight() - aTabCols[i-1];
+ else
+ nDiff -= aTabCols[i] - aTabCols[i-1];
+
+ long nTabRight = aTabCols.GetRight() + nDiff;
+
+ //Wenn die Tabelle zu breit wuerde begrenzen wir die Anpassung
+ //auf das erlaubte Maximum.
+ if ( !bBalance && nTabRight > aTabCols.GetRightMax() )
+ {
+ const long nTmpD = nTabRight - aTabCols.GetRightMax();
+ nDiff -= nTmpD;
+ nTabRight -= nTmpD;
+ }
+ for ( sal_uInt16 i2 = i; i2 < aTabCols.Count(); ++i2 )
+ aTabCols[i2] += nDiff;
+ aTabCols.SetRight( nTabRight );
+ }
+ }
+ }
+
+ const sal_uInt16 nNewRight = static_cast<sal_uInt16>(aTabCols.GetRight());
+
+ SwFrmFmt *pFmt = pTblNd->GetTable().GetFrmFmt();
+ const sal_Int16 nOriHori = pFmt->GetHoriOrient().GetHoriOrient();
+
+ //So, die richtige Arbeit koennen wir jetzt der SwTable ueberlassen.
+ SetTabCols( aTabCols, sal_False, 0, (SwCellFrm*)pBoxFrm );
+
+ // i54248: lijian/fme
+ // alignment might have been changed in SetTabCols, restore old value:
+ const SwFmtHoriOrient &rHori = pFmt->GetHoriOrient();
+ SwFmtHoriOrient aHori( rHori );
+ if ( aHori.GetHoriOrient() != nOriHori )
+ {
+ aHori.SetHoriOrient( nOriHori );
+ pFmt->SetFmtAttr( aHori );
+ }
+
+ //Bei Automatischer Breite wird auf Linksbuendig umgeschaltet.
+ //Bei Randattributen wird der Rechte Rand angepasst.
+ if( !bBalance && nNewRight < nOldRight )
+ {
+ if( aHori.GetHoriOrient() == text::HoriOrientation::FULL )
+ {
+ aHori.SetHoriOrient( text::HoriOrientation::LEFT );
+ pFmt->SetFmtAttr( aHori );
+ }
+ }
+
+ SetModified();
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/docnode/node.cxx b/sw/source/core/docnode/node.cxx
new file mode 100644
index 000000000000..26521624abb7
--- /dev/null
+++ b/sw/source/core/docnode/node.cxx
@@ -0,0 +1,2028 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+#include <hintids.hxx>
+#include <editeng/frmdiritem.hxx>
+#include <editeng/protitem.hxx>
+#include <com/sun/star/i18n/CharacterIteratorMode.hdl>
+#include <fmtcntnt.hxx>
+#include <fmtanchr.hxx>
+#include <frmfmt.hxx>
+#include <txtftn.hxx>
+#include <ftnfrm.hxx>
+#include <doc.hxx>
+#include <docary.hxx>
+#include <node.hxx>
+#include <ndindex.hxx>
+#include <numrule.hxx>
+#include <swtable.hxx>
+#include <ndtxt.hxx>
+#include <pam.hxx>
+#include <swcache.hxx>
+#include <section.hxx>
+#include <cntfrm.hxx>
+#include <flyfrm.hxx>
+#include <txtfrm.hxx>
+#include <tabfrm.hxx> // SwTabFrm
+#include <viewsh.hxx>
+#include <paratr.hxx>
+#include <ftnidx.hxx>
+#include <fmtftn.hxx>
+#include <fmthdft.hxx>
+#include <frmatr.hxx>
+#include <fmtautofmt.hxx>
+#include <frmtool.hxx>
+#include <pagefrm.hxx>
+#include <node2lay.hxx>
+#include <pagedesc.hxx>
+#include <fmtpdsc.hxx>
+#include <breakit.hxx>
+#include <crsskip.hxx>
+#include <SwStyleNameMapper.hxx>
+#include <scriptinfo.hxx>
+#include <rootfrm.hxx>
+#include <istyleaccess.hxx>
+#include <IDocumentListItems.hxx>
+#include <switerator.hxx>
+#include "ndole.hxx"
+
+using namespace ::com::sun::star::i18n;
+
+TYPEINIT2( SwCntntNode, SwModify, SwIndexReg )
+
+/*
+ * Some local helper functions for the attribute set handle of a content node.
+ * Since the attribute set of a content node may not be modified directly,
+ * we always have to create a new SwAttrSet, do the modifications, and get
+ * a new handle from the style access
+ */
+
+namespace AttrSetHandleHelper
+{
+
+void GetNewAutoStyle( boost::shared_ptr<const SfxItemSet>& mrpAttrSet,
+ const SwCntntNode& rNode,
+ SwAttrSet& rNewAttrSet )
+{
+ const SwAttrSet* pAttrSet = static_cast<const SwAttrSet*>(mrpAttrSet.get());
+ if( rNode.GetModifyAtAttr() )
+ const_cast<SwAttrSet*>(pAttrSet)->SetModifyAtAttr( 0 );
+ IStyleAccess& rSA = pAttrSet->GetPool()->GetDoc()->GetIStyleAccess();
+ mrpAttrSet = rSA.getAutomaticStyle( rNewAttrSet, rNode.IsTxtNode() ?
+ IStyleAccess::AUTO_STYLE_PARA :
+ IStyleAccess::AUTO_STYLE_NOTXT );
+ const bool bSetModifyAtAttr = ((SwAttrSet*)mrpAttrSet.get())->SetModifyAtAttr( &rNode );
+ rNode.SetModifyAtAttr( bSetModifyAtAttr );
+}
+
+
+void SetParent( boost::shared_ptr<const SfxItemSet>& mrpAttrSet,
+ const SwCntntNode& rNode,
+ const SwFmt* pParentFmt,
+ const SwFmt* pConditionalFmt )
+{
+ const SwAttrSet* pAttrSet = static_cast<const SwAttrSet*>(mrpAttrSet.get());
+ OSL_ENSURE( pAttrSet, "no SwAttrSet" );
+ OSL_ENSURE( pParentFmt || !pConditionalFmt, "ConditionalFmt without ParentFmt?" );
+
+ const SwAttrSet* pParentSet = pParentFmt ? &pParentFmt->GetAttrSet() : 0;
+
+ if ( pParentSet != pAttrSet->GetParent() )
+ {
+ SwAttrSet aNewSet( *pAttrSet );
+ aNewSet.SetParent( pParentSet );
+ aNewSet.ClearItem( RES_FRMATR_STYLE_NAME );
+ aNewSet.ClearItem( RES_FRMATR_CONDITIONAL_STYLE_NAME );
+ String sVal;
+
+ if ( pParentFmt )
+ {
+ SwStyleNameMapper::FillProgName( pParentFmt->GetName(), sVal, nsSwGetPoolIdFromName::GET_POOLID_TXTCOLL, sal_True );
+ const SfxStringItem aAnyFmtColl( RES_FRMATR_STYLE_NAME, sVal );
+ aNewSet.Put( aAnyFmtColl );
+
+ if ( pConditionalFmt != pParentFmt )
+ SwStyleNameMapper::FillProgName( pConditionalFmt->GetName(), sVal, nsSwGetPoolIdFromName::GET_POOLID_TXTCOLL, sal_True );
+
+ const SfxStringItem aFmtColl( RES_FRMATR_CONDITIONAL_STYLE_NAME, sVal );
+ aNewSet.Put( aFmtColl );
+ }
+
+ GetNewAutoStyle( mrpAttrSet, rNode, aNewSet );
+ }
+}
+
+const SfxPoolItem* Put( boost::shared_ptr<const SfxItemSet>& mrpAttrSet,
+ const SwCntntNode& rNode,
+ const SfxPoolItem& rAttr )
+{
+ SwAttrSet aNewSet( (SwAttrSet&)*mrpAttrSet );
+ const SfxPoolItem* pRet = aNewSet.Put( rAttr );
+ if ( pRet )
+ GetNewAutoStyle( mrpAttrSet, rNode, aNewSet );
+ return pRet;
+}
+
+int Put( boost::shared_ptr<const SfxItemSet>& mrpAttrSet, const SwCntntNode& rNode,
+ const SfxItemSet& rSet )
+{
+ SwAttrSet aNewSet( (SwAttrSet&)*mrpAttrSet );
+
+ // --> FME 2007-4-12 #i76273# Robust: Save the style name items:
+ SfxItemSet* pStyleNames = 0;
+ if ( SFX_ITEM_SET == rSet.GetItemState( RES_FRMATR_STYLE_NAME, sal_False ) )
+ {
+ pStyleNames = new SfxItemSet( *aNewSet.GetPool(), RES_FRMATR_STYLE_NAME, RES_FRMATR_CONDITIONAL_STYLE_NAME );
+ pStyleNames->Put( aNewSet );
+ }
+ // <--
+
+ const int nRet = aNewSet.Put( rSet );
+
+ // --> FME 2007-4-12 #i76273# Robust: Save the style name items:
+ if ( pStyleNames )
+ {
+ aNewSet.Put( *pStyleNames );
+ delete pStyleNames;
+ }
+ // <--
+
+ if ( nRet )
+ GetNewAutoStyle( mrpAttrSet, rNode, aNewSet );
+
+ return nRet;
+}
+
+int Put_BC( boost::shared_ptr<const SfxItemSet>& mrpAttrSet,
+ const SwCntntNode& rNode, const SfxPoolItem& rAttr,
+ SwAttrSet* pOld, SwAttrSet* pNew )
+{
+ SwAttrSet aNewSet( (SwAttrSet&)*mrpAttrSet );
+
+ // for a correct broadcast, we need to do a SetModifyAtAttr with the items
+ // from aNewSet. The 'regular' SetModifyAtAttr is done in GetNewAutoStyle
+ if( rNode.GetModifyAtAttr() )
+ aNewSet.SetModifyAtAttr( &rNode );
+
+ const int nRet = aNewSet.Put_BC( rAttr, pOld, pNew );
+
+ if ( nRet )
+ GetNewAutoStyle( mrpAttrSet, rNode, aNewSet );
+
+ return nRet;
+}
+
+int Put_BC( boost::shared_ptr<const SfxItemSet>& mrpAttrSet,
+ const SwCntntNode& rNode, const SfxItemSet& rSet,
+ SwAttrSet* pOld, SwAttrSet* pNew )
+{
+ SwAttrSet aNewSet( (SwAttrSet&)*mrpAttrSet );
+
+ // --> FME 2007-4-12 #i76273# Robust: Save the style name items:
+ SfxItemSet* pStyleNames = 0;
+ if ( SFX_ITEM_SET == rSet.GetItemState( RES_FRMATR_STYLE_NAME, sal_False ) )
+ {
+ pStyleNames = new SfxItemSet( *aNewSet.GetPool(), RES_FRMATR_STYLE_NAME, RES_FRMATR_CONDITIONAL_STYLE_NAME );
+ pStyleNames->Put( aNewSet );
+ }
+ // <--
+
+ // for a correct broadcast, we need to do a SetModifyAtAttr with the items
+ // from aNewSet. The 'regular' SetModifyAtAttr is done in GetNewAutoStyle
+ if( rNode.GetModifyAtAttr() )
+ aNewSet.SetModifyAtAttr( &rNode );
+
+ const int nRet = aNewSet.Put_BC( rSet, pOld, pNew );
+
+ // --> FME 2007-4-12 #i76273# Robust: Save the style name items:
+ if ( pStyleNames )
+ {
+ aNewSet.Put( *pStyleNames );
+ delete pStyleNames;
+ }
+ // <--
+
+ if ( nRet )
+ GetNewAutoStyle( mrpAttrSet, rNode, aNewSet );
+
+ return nRet;
+}
+
+sal_uInt16 ClearItem_BC( boost::shared_ptr<const SfxItemSet>& mrpAttrSet,
+ const SwCntntNode& rNode, sal_uInt16 nWhich,
+ SwAttrSet* pOld, SwAttrSet* pNew )
+{
+ SwAttrSet aNewSet( (SwAttrSet&)*mrpAttrSet );
+ if( rNode.GetModifyAtAttr() )
+ aNewSet.SetModifyAtAttr( &rNode );
+ const sal_uInt16 nRet = aNewSet.ClearItem_BC( nWhich, pOld, pNew );
+ if ( nRet )
+ GetNewAutoStyle( mrpAttrSet, rNode, aNewSet );
+ return nRet;
+}
+
+sal_uInt16 ClearItem_BC( boost::shared_ptr<const SfxItemSet>& mrpAttrSet,
+ const SwCntntNode& rNode,
+ sal_uInt16 nWhich1, sal_uInt16 nWhich2,
+ SwAttrSet* pOld, SwAttrSet* pNew )
+{
+ SwAttrSet aNewSet( (SwAttrSet&)*mrpAttrSet );
+ if( rNode.GetModifyAtAttr() )
+ aNewSet.SetModifyAtAttr( &rNode );
+ const sal_uInt16 nRet = aNewSet.ClearItem_BC( nWhich1, nWhich2, pOld, pNew );
+ if ( nRet )
+ GetNewAutoStyle( mrpAttrSet, rNode, aNewSet );
+ return nRet;
+}
+
+}
+
+/*******************************************************************
+|*
+|* SwNode::GetSectionLevel
+|*
+|* Beschreibung
+|* Die Funktion liefert den Sectionlevel an der durch
+|* aIndex bezeichneten Position.
+|*
+|* Die Logik ist wie folgt: ( S -> Start, E -> End, C -> CntntNode)
+|* Level 0 E
+|* 1 S E
+|* 2 SC
+|*
+|* alle EndNodes der GrundSection haben den Level 0
+|* alle StartNodes der GrundSection haben den Level 1
+|*
+*******************************************************************/
+
+
+sal_uInt16 SwNode::GetSectionLevel() const
+{
+ // EndNode einer Grund-Section ?? diese sind immer 0 !!
+ if( IsEndNode() && 0 == pStartOfSection->StartOfSectionIndex() )
+ return 0;
+
+ sal_uInt16 nLevel;
+ const SwNode* pNode = IsStartNode() ? this : pStartOfSection;
+ for( nLevel = 1; 0 != pNode->StartOfSectionIndex(); ++nLevel )
+ pNode = pNode->pStartOfSection;
+ return IsEndNode() ? nLevel-1 : nLevel;
+}
+
+/*******************************************************************
+|*
+|* SwNode::SwNode
+|*
+|* Beschreibung
+|* Konstruktor; dieser fuegt einen Node in das Array rNodes
+|* an der Position rWhere ein. Dieser bekommt als
+|* theEndOfSection den EndOfSection-Index des Nodes
+|* unmittelbar vor ihm. Falls er sich an der Position 0
+|* innerhalb des variablen Arrays befindet, wird
+|* theEndOfSection 0 (der neue selbst).
+|*
+|* Parameter
+|* IN
+|* rNodes bezeichnet das variable Array, in das der Node
+|* eingefuegt werden soll
+|* IN
+|* rWhere bezeichnet die Position innerhalb dieses Arrays,
+|* an der der Node eingefuegt werden soll
+|*
+*******************************************************************/
+
+#if OSL_DEBUG_LEVEL > 1
+long SwNode::nSerial = 0;
+#endif
+
+SwNode::SwNode( const SwNodeIndex &rWhere, const sal_uInt8 nNdType )
+ : nNodeType( nNdType ), pStartOfSection( 0 )
+{
+ bSetNumLSpace = bIgnoreDontExpand = sal_False;
+ nAFmtNumLvl = 0;
+
+ SwNodes& rNodes = (SwNodes&)rWhere.GetNodes();
+ SwNode* pInsNd = this; // der MAC kann this nicht einfuegen !!
+ if( rWhere.GetIndex() )
+ {
+ SwNode* pNd = rNodes[ rWhere.GetIndex() -1 ];
+ rNodes.InsertNode( pInsNd, rWhere );
+ if( 0 == ( pStartOfSection = pNd->GetStartNode()) )
+ {
+ pStartOfSection = pNd->pStartOfSection;
+ if( pNd->GetEndNode() ) // EndNode ? Section ueberspringen!
+ {
+ pNd = pStartOfSection;
+ pStartOfSection = pNd->pStartOfSection;
+ }
+ }
+ }
+ else
+ {
+ rNodes.InsertNode( pInsNd, rWhere );
+ pStartOfSection = (SwStartNode*)this;
+ }
+
+#if OSL_DEBUG_LEVEL > 1
+ nMySerial = nSerial;
+ nSerial++;
+#endif
+}
+
+SwNode::SwNode( SwNodes& rNodes, sal_uLong nPos, const sal_uInt8 nNdType )
+ : nNodeType( nNdType ), pStartOfSection( 0 )
+{
+ bSetNumLSpace = bIgnoreDontExpand = sal_False;
+ nAFmtNumLvl = 0;
+
+ SwNode* pInsNd = this; // der MAC kann this nicht einfuegen !!
+ if( nPos )
+ {
+ SwNode* pNd = rNodes[ nPos - 1 ];
+ rNodes.InsertNode( pInsNd, nPos );
+ if( 0 == ( pStartOfSection = pNd->GetStartNode()) )
+ {
+ pStartOfSection = pNd->pStartOfSection;
+ if( pNd->GetEndNode() ) // EndNode ? Section ueberspringen!
+ {
+ pNd = pStartOfSection;
+ pStartOfSection = pNd->pStartOfSection;
+ }
+ }
+ }
+ else
+ {
+ rNodes.InsertNode( pInsNd, nPos );
+ pStartOfSection = (SwStartNode*)this;
+ }
+
+#if OSL_DEBUG_LEVEL > 1
+ nMySerial = nSerial;
+ nSerial++;
+#endif
+}
+
+SwNode::~SwNode()
+{
+}
+
+// suche den TabellenNode, in dem dieser steht. Wenn in keiner
+// Tabelle wird 0 returnt.
+
+
+SwTableNode* SwNode::FindTableNode()
+{
+ if( IsTableNode() )
+ return GetTableNode();
+ SwStartNode* pTmp = pStartOfSection;
+ while( !pTmp->IsTableNode() && pTmp->GetIndex() )
+#if defined( ALPHA ) && defined( UNX )
+ pTmp = ((SwNode*)pTmp)->pStartOfSection;
+#else
+ pTmp = pTmp->pStartOfSection;
+#endif
+ return pTmp->GetTableNode();
+}
+
+
+// liegt der Node im Sichtbarenbereich der Shell ?
+sal_Bool SwNode::IsInVisibleArea( ViewShell* pSh ) const
+{
+ sal_Bool bRet = sal_False;
+ const SwCntntNode* pNd;
+
+ if( ND_STARTNODE & nNodeType )
+ {
+ SwNodeIndex aIdx( *this );
+ pNd = GetNodes().GoNext( &aIdx );
+ }
+ else if( ND_ENDNODE & nNodeType )
+ {
+ SwNodeIndex aIdx( *EndOfSectionNode() );
+ pNd = GetNodes().GoPrevious( &aIdx );
+ }
+ else
+ pNd = GetCntntNode();
+
+ if( !pSh )
+ // dann die Shell vom Doc besorgen:
+ GetDoc()->GetEditShell( &pSh );
+
+ if( pSh )
+ {
+ const SwFrm* pFrm;
+ if( pNd && 0 != ( pFrm = pNd->getLayoutFrm( pSh->GetLayout(), 0, 0, sal_False ) ) )
+ {
+
+ if ( pFrm->IsInTab() )
+ pFrm = pFrm->FindTabFrm();
+
+ if( !pFrm->IsValid() )
+ do
+ { pFrm = pFrm->FindPrev();
+ } while ( pFrm && !pFrm->IsValid() );
+
+ if( !pFrm || pSh->VisArea().IsOver( pFrm->Frm() ) )
+ bRet = sal_True;
+ }
+ }
+
+ return bRet;
+}
+
+sal_Bool SwNode::IsInProtectSect() const
+{
+ const SwNode* pNd = ND_SECTIONNODE == nNodeType ? pStartOfSection : this;
+ const SwSectionNode* pSectNd = pNd->FindSectionNode();
+ return pSectNd && pSectNd->GetSection().IsProtectFlag();
+}
+
+ // befindet sich der Node in irgendetwas geschuetzten ?
+ // (Bereich/Rahmen/Tabellenzellen/... incl. des Ankers bei
+ // Rahmen/Fussnoten/..)
+sal_Bool SwNode::IsProtect() const
+{
+ const SwNode* pNd = ND_SECTIONNODE == nNodeType ? pStartOfSection : this;
+ const SwStartNode* pSttNd = pNd->FindSectionNode();
+ if( pSttNd && ((SwSectionNode*)pSttNd)->GetSection().IsProtectFlag() )
+ return sal_True;
+
+ if( 0 != ( pSttNd = FindTableBoxStartNode() ) )
+ {
+ SwCntntFrm* pCFrm;
+ if( IsCntntNode() && 0 != (pCFrm = ((SwCntntNode*)this)->getLayoutFrm( GetDoc()->GetCurrentLayout() ) ))
+ return pCFrm->IsProtected();
+
+ const SwTableBox* pBox = pSttNd->FindTableNode()->GetTable().
+ GetTblBox( pSttNd->GetIndex() );
+ //Robust #149568
+ if( pBox && pBox->GetFrmFmt()->GetProtect().IsCntntProtected() )
+ return sal_True;
+ }
+
+ SwFrmFmt* pFlyFmt = GetFlyFmt();
+ if( pFlyFmt )
+ {
+ if( pFlyFmt->GetProtect().IsCntntProtected() )
+ return sal_True;
+ const SwFmtAnchor& rAnchor = pFlyFmt->GetAnchor();
+ return rAnchor.GetCntntAnchor()
+ ? rAnchor.GetCntntAnchor()->nNode.GetNode().IsProtect()
+ : sal_False;
+ }
+
+ if( 0 != ( pSttNd = FindFootnoteStartNode() ) )
+ {
+ const SwTxtFtn* pTFtn = GetDoc()->GetFtnIdxs().SeekEntry(
+ SwNodeIndex( *pSttNd ) );
+ if( pTFtn )
+ return pTFtn->GetTxtNode().IsProtect();
+ }
+
+ return sal_False;
+}
+
+ // suche den PageDesc, mit dem dieser Node formatiert ist. Wenn das
+ // Layout vorhanden ist wird ueber das gesucht, ansonsten gibt es nur
+ // die harte Tour ueber die Nodes nach vorne suchen!!
+const SwPageDesc* SwNode::FindPageDesc( sal_Bool bCalcLay,
+ sal_uInt32* pPgDescNdIdx ) const
+{
+ if ( !GetNodes().IsDocNodes() )
+ {
+ return 0;
+ }
+
+ const SwPageDesc* pPgDesc = 0;
+
+ const SwCntntNode* pNode;
+ if( ND_STARTNODE & nNodeType )
+ {
+ SwNodeIndex aIdx( *this );
+ pNode = GetNodes().GoNext( &aIdx );
+ }
+ else if( ND_ENDNODE & nNodeType )
+ {
+ SwNodeIndex aIdx( *EndOfSectionNode() );
+ pNode = GetNodes().GoPrevious( &aIdx );
+ }
+ else
+ {
+ pNode = GetCntntNode();
+ if( pNode )
+ pPgDesc = ((SwFmtPageDesc&)pNode->GetAttr( RES_PAGEDESC )).GetPageDesc();
+ }
+
+ // geht es uebers Layout?
+ if( !pPgDesc )
+ {
+ const SwFrm* pFrm;
+ const SwPageFrm* pPage;
+ if( pNode && 0 != ( pFrm = pNode->getLayoutFrm( pNode->GetDoc()->GetCurrentLayout(), 0, 0, bCalcLay ) ) &&
+ 0 != ( pPage = pFrm->FindPageFrm() ) )
+ {
+ pPgDesc = pPage->GetPageDesc();
+ if ( pPgDescNdIdx )
+ {
+ *pPgDescNdIdx = pNode->GetIndex();
+ }
+ }
+ }
+
+ if( !pPgDesc )
+ {
+ // dann also uebers Nodes-Array
+ const SwDoc* pDoc = GetDoc();
+ const SwNode* pNd = this;
+ const SwStartNode* pSttNd;
+ if( pNd->GetIndex() < GetNodes().GetEndOfExtras().GetIndex() &&
+ 0 != ( pSttNd = pNd->FindFlyStartNode() ) )
+ {
+ // dann erstmal den richtigen Anker finden
+ const SwFrmFmt* pFmt = 0;
+ const SwSpzFrmFmts& rFmts = *pDoc->GetSpzFrmFmts();
+ sal_uInt16 n;
+
+ for( n = 0; n < rFmts.Count(); ++n )
+ {
+ SwFrmFmt* pFrmFmt = rFmts[ n ];
+ const SwFmtCntnt& rCntnt = pFrmFmt->GetCntnt();
+ if( rCntnt.GetCntntIdx() &&
+ &rCntnt.GetCntntIdx()->GetNode() == (SwNode*)pSttNd )
+ {
+ pFmt = pFrmFmt;
+ break;
+ }
+ }
+
+ if( pFmt )
+ {
+ const SwFmtAnchor* pAnchor = &pFmt->GetAnchor();
+ if ((FLY_AT_PAGE != pAnchor->GetAnchorId()) &&
+ pAnchor->GetCntntAnchor() )
+ {
+ pNd = &pAnchor->GetCntntAnchor()->nNode.GetNode();
+ const SwNode* pFlyNd = pNd->FindFlyStartNode();
+ while( pFlyNd )
+ {
+ // dann ueber den Anker nach oben "hangeln"
+ for( n = 0; n < rFmts.Count(); ++n )
+ {
+ const SwFrmFmt* pFrmFmt = rFmts[ n ];
+ const SwNodeIndex* pIdx = pFrmFmt->GetCntnt().
+ GetCntntIdx();
+ if( pIdx && pFlyNd == &pIdx->GetNode() )
+ {
+ if( pFmt == pFrmFmt )
+ {
+ pNd = pFlyNd;
+ pFlyNd = 0;
+ break;
+ }
+ pAnchor = &pFrmFmt->GetAnchor();
+ if ((FLY_AT_PAGE == pAnchor->GetAnchorId()) ||
+ !pAnchor->GetCntntAnchor() )
+ {
+ pFlyNd = 0;
+ break;
+ }
+
+ pFlyNd = pAnchor->GetCntntAnchor()->nNode.
+ GetNode().FindFlyStartNode();
+ break;
+ }
+ }
+ if( n >= rFmts.Count() )
+ {
+ OSL_ENSURE( !this, "Fly-Section aber kein Format gefunden" );
+ return sal_False;
+ }
+ }
+ }
+ }
+ // in pNd sollte jetzt der richtige Anker Node stehen oder
+ // immer noch der this
+ }
+
+ if( pNd->GetIndex() < GetNodes().GetEndOfExtras().GetIndex() )
+ {
+ if( pNd->GetIndex() > GetNodes().GetEndOfAutotext().GetIndex() )
+ {
+ pPgDesc = &pDoc->GetPageDesc( 0 );
+ pNd = 0;
+ }
+ else
+ {
+ // suche den Body Textnode
+ if( 0 != ( pSttNd = pNd->FindHeaderStartNode() ) ||
+ 0 != ( pSttNd = pNd->FindFooterStartNode() ))
+ {
+ // dann in den PageDescs diesen StartNode suchen
+ sal_uInt16 nId;
+ UseOnPage eAskUse;
+ if( SwHeaderStartNode == pSttNd->GetStartNodeType())
+ {
+ nId = RES_HEADER;
+ eAskUse = nsUseOnPage::PD_HEADERSHARE;
+ }
+ else
+ {
+ nId = RES_FOOTER;
+ eAskUse = nsUseOnPage::PD_FOOTERSHARE;
+ }
+
+ for( sal_uInt16 n = pDoc->GetPageDescCnt(); n && !pPgDesc; )
+ {
+ const SwPageDesc& rPgDsc = pDoc->GetPageDesc( --n );
+ const SwFrmFmt* pFmt = &rPgDsc.GetMaster();
+ int nStt = 0, nLast = 1;
+ if( !( eAskUse & rPgDsc.ReadUseOn() )) ++nLast;
+
+ for( ; nStt < nLast; ++nStt, pFmt = &rPgDsc.GetLeft() )
+ {
+ const SwFmtHeader& rHdFt = (SwFmtHeader&)
+ pFmt->GetFmtAttr( nId );
+ if( rHdFt.GetHeaderFmt() )
+ {
+ const SwFmtCntnt& rCntnt =
+ rHdFt.GetHeaderFmt()->GetCntnt();
+ if( rCntnt.GetCntntIdx() &&
+ &rCntnt.GetCntntIdx()->GetNode() ==
+ (SwNode*)pSttNd )
+ {
+ pPgDesc = &rPgDsc;
+ break;
+ }
+ }
+ }
+ }
+
+ if( !pPgDesc )
+ pPgDesc = &pDoc->GetPageDesc( 0 );
+ pNd = 0;
+ }
+ else if( 0 != ( pSttNd = pNd->FindFootnoteStartNode() ))
+ {
+ // der Anker kann nur im Bodytext sein
+ const SwTxtFtn* pTxtFtn;
+ const SwFtnIdxs& rFtnArr = pDoc->GetFtnIdxs();
+ for( sal_uInt16 n = 0; n < rFtnArr.Count(); ++n )
+ if( 0 != ( pTxtFtn = rFtnArr[ n ])->GetStartNode() &&
+ (SwNode*)pSttNd ==
+ &pTxtFtn->GetStartNode()->GetNode() )
+ {
+ pNd = &pTxtFtn->GetTxtNode();
+ break;
+ }
+ }
+ else
+ {
+ // kann jetzt nur noch ein Seitengebundener Fly sein
+ // oder irgendetwas neueres.
+ // Hier koennen wir nur noch den Standard returnen
+ OSL_ENSURE( pNd->FindFlyStartNode(),
+ "wo befindet sich dieser Node?" );
+
+ pPgDesc = &pDoc->GetPageDesc( 0 );
+ pNd = 0;
+ }
+ }
+ }
+
+ if( pNd )
+ {
+ SwFindNearestNode aInfo( *pNd );
+ // dann ueber alle Nodes aller PageDesc
+ const SfxPoolItem* pItem;
+ sal_uInt32 i, nMaxItems = pDoc->GetAttrPool().GetItemCount2( RES_PAGEDESC );
+ for( i = 0; i < nMaxItems; ++i )
+ if( 0 != (pItem = pDoc->GetAttrPool().GetItem2( RES_PAGEDESC, i ) ) &&
+ ((SwFmtPageDesc*)pItem)->GetDefinedIn() )
+ {
+ const SwModify* pMod = ((SwFmtPageDesc*)pItem)->GetDefinedIn();
+ if( pMod->ISA( SwCntntNode ) )
+ aInfo.CheckNode( *(SwCntntNode*)pMod );
+ else if( pMod->ISA( SwFmt ))
+ ((SwFmt*)pMod)->GetInfo( aInfo );
+ }
+
+ if( 0 != ( pNd = aInfo.GetFoundNode() ))
+ {
+ if( pNd->IsCntntNode() )
+ pPgDesc = ((SwFmtPageDesc&)pNd->GetCntntNode()->
+ GetAttr( RES_PAGEDESC )).GetPageDesc();
+ else if( pNd->IsTableNode() )
+ pPgDesc = pNd->GetTableNode()->GetTable().
+ GetFrmFmt()->GetPageDesc().GetPageDesc();
+ else if( pNd->IsSectionNode() )
+ pPgDesc = pNd->GetSectionNode()->GetSection().
+ GetFmt()->GetPageDesc().GetPageDesc();
+ if ( pPgDescNdIdx )
+ {
+ *pPgDescNdIdx = pNd->GetIndex();
+ }
+ }
+ if( !pPgDesc )
+ pPgDesc = &pDoc->GetPageDesc( 0 );
+ }
+ }
+ return pPgDesc;
+}
+
+
+ // falls der Node in einem Fly steht, dann wird das entsprechende Format
+ // returnt
+SwFrmFmt* SwNode::GetFlyFmt() const
+{
+ SwFrmFmt* pRet = 0;
+ const SwNode* pSttNd = FindFlyStartNode();
+ if( pSttNd )
+ {
+ if( IsCntntNode() )
+ {
+ SwCntntFrm* pFrm = SwIterator<SwCntntFrm,SwCntntNode>::FirstElement( *(SwCntntNode*)this );
+ if( pFrm )
+ pRet = pFrm->FindFlyFrm()->GetFmt();
+ }
+ if( !pRet )
+ {
+ // dann gibts noch harten steinigen Weg uebers Dokument:
+ const SwSpzFrmFmts& rFrmFmtTbl = *GetDoc()->GetSpzFrmFmts();
+ for( sal_uInt16 n = 0; n < rFrmFmtTbl.Count(); ++n )
+ {
+ SwFrmFmt* pFmt = rFrmFmtTbl[n];
+ const SwFmtCntnt& rCntnt = pFmt->GetCntnt();
+ if( rCntnt.GetCntntIdx() &&
+ &rCntnt.GetCntntIdx()->GetNode() == pSttNd )
+ {
+ pRet = pFmt;
+ break;
+ }
+ }
+ }
+ }
+ return pRet;
+}
+
+SwTableBox* SwNode::GetTblBox() const
+{
+ SwTableBox* pBox = 0;
+ const SwNode* pSttNd = FindTableBoxStartNode();
+ if( pSttNd )
+ pBox = (SwTableBox*)pSttNd->FindTableNode()->GetTable().GetTblBox(
+ pSttNd->GetIndex() );
+ return pBox;
+}
+
+SwStartNode* SwNode::FindSttNodeByType( SwStartNodeType eTyp )
+{
+ SwStartNode* pTmp = IsStartNode() ? (SwStartNode*)this : pStartOfSection;
+
+ while( eTyp != pTmp->GetStartNodeType() && pTmp->GetIndex() )
+#if defined( ALPHA ) && defined( UNX )
+ pTmp = ((SwNode*)pTmp)->pStartOfSection;
+#else
+ pTmp = pTmp->pStartOfSection;
+#endif
+ return eTyp == pTmp->GetStartNodeType() ? pTmp : 0;
+}
+
+const SwTxtNode* SwNode::FindOutlineNodeOfLevel( sal_uInt8 nLvl ) const
+{
+ const SwTxtNode* pRet = 0;
+ const SwOutlineNodes& rONds = GetNodes().GetOutLineNds();
+ if( MAXLEVEL > nLvl && rONds.Count() )
+ {
+ sal_uInt16 nPos;
+ SwNode* pNd = (SwNode*)this;
+ sal_Bool bCheckFirst = sal_False;
+ if( !rONds.Seek_Entry( pNd, &nPos ))
+ {
+ if( nPos )
+ nPos = nPos-1;
+ else
+ bCheckFirst = sal_True;
+ }
+
+ if( bCheckFirst )
+ {
+ // der 1.GliederungsNode liegt hinter dem Fragenden. Dann
+ // teste mal, ob dieser auf der gleichen Seite steht. Wenn
+ // nicht, ist das ein ungueltiger. Bug 61865
+ pRet = rONds[0]->GetTxtNode();
+
+ const SwCntntNode* pCNd = GetCntntNode();
+
+ Point aPt( 0, 0 );
+ const SwFrm* pFrm = pRet->getLayoutFrm( pRet->GetDoc()->GetCurrentLayout(), &aPt, 0, sal_False ),
+ * pMyFrm = pCNd ? pCNd->getLayoutFrm( pCNd->GetDoc()->GetCurrentLayout(), &aPt, 0, sal_False ) : 0;
+ const SwPageFrm* pPgFrm = pFrm ? pFrm->FindPageFrm() : 0;
+ if( pPgFrm && pMyFrm &&
+ pPgFrm->Frm().Top() > pMyFrm->Frm().Top() )
+ {
+ // der Fragende liegt vor der Seite, also ist er ungueltig
+ pRet = 0;
+ }
+ }
+ else
+ {
+ // oder ans Feld und von dort holen !!
+ while( nPos &&
+ nLvl < ( pRet = rONds[nPos]->GetTxtNode() )
+ ->GetAttrOutlineLevel() - 1 ) //<-end,zhaojianwei
+ --nPos;
+
+ if( !nPos ) // bei 0 gesondert holen !!
+ pRet = rONds[0]->GetTxtNode();
+ }
+ }
+ return pRet;
+}
+
+inline sal_Bool IsValidNextPrevNd( const SwNode& rNd )
+{
+ return ND_TABLENODE == rNd.GetNodeType() ||
+ ( ND_CONTENTNODE & rNd.GetNodeType() ) ||
+ ( ND_ENDNODE == rNd.GetNodeType() && rNd.StartOfSectionNode() &&
+ ND_TABLENODE == rNd.StartOfSectionNode()->GetNodeType() );
+}
+
+sal_uInt8 SwNode::HasPrevNextLayNode() const
+{
+ // assumption: <this> node is a node inside the document nodes array section.
+
+ sal_uInt8 nRet = 0;
+ if( IsValidNextPrevNd( *this ))
+ {
+ SwNodeIndex aIdx( *this, -1 );
+ // #i77805# - skip section start and end nodes
+ while ( aIdx.GetNode().IsSectionNode() ||
+ ( aIdx.GetNode().IsEndNode() &&
+ aIdx.GetNode().StartOfSectionNode()->IsSectionNode() ) )
+ {
+ --aIdx;
+ }
+ // <--
+ if( IsValidNextPrevNd( aIdx.GetNode() ))
+ nRet |= ND_HAS_PREV_LAYNODE;
+ // #i77805# - skip section start and end nodes
+ aIdx = SwNodeIndex( *this, +1 );
+ while ( aIdx.GetNode().IsSectionNode() ||
+ ( aIdx.GetNode().IsEndNode() &&
+ aIdx.GetNode().StartOfSectionNode()->IsSectionNode() ) )
+ {
+ ++aIdx;
+ }
+ if( IsValidNextPrevNd( aIdx.GetNode() ))
+ nRet |= ND_HAS_NEXT_LAYNODE;
+ }
+ return nRet;
+}
+
+/*******************************************************************
+|*
+|* SwNode::StartOfSection
+|*
+|* Beschreibung
+|* Die Funktion liefert die StartOfSection des Nodes.
+|*
+|* Parameter
+|* IN
+|* rNodes bezeichnet das variable Array, in dem sich der Node
+|* befindet
+|*
+*******************************************************************/
+
+
+SwStartNode::SwStartNode( const SwNodeIndex &rWhere, const sal_uInt8 nNdType,
+ SwStartNodeType eSttNd )
+ : SwNode( rWhere, nNdType ), eSttNdTyp( eSttNd )
+{
+ // erstmal temporaer, bis der EndNode eingefuegt wird.
+ pEndOfSection = (SwEndNode*)this;
+}
+
+SwStartNode::SwStartNode( SwNodes& rNodes, sal_uLong nPos )
+ : SwNode( rNodes, nPos, ND_STARTNODE ), eSttNdTyp( SwNormalStartNode )
+{
+ // erstmal temporaer, bis der EndNode eingefuegt wird.
+ pEndOfSection = (SwEndNode*)this;
+}
+
+
+void SwStartNode::CheckSectionCondColl() const
+{
+//FEATURE::CONDCOLL
+ SwNodeIndex aIdx( *this );
+ sal_uLong nEndIdx = EndOfSectionIndex();
+ const SwNodes& rNds = GetNodes();
+ SwCntntNode* pCNd;
+ while( 0 != ( pCNd = rNds.GoNext( &aIdx )) && pCNd->GetIndex() < nEndIdx )
+ pCNd->ChkCondColl();
+//FEATURE::CONDCOLL
+}
+
+/*******************************************************************
+|*
+|* SwEndNode::SwEndNode
+|*
+|* Beschreibung
+|* Konstruktor; dieser fuegt einen Node in das Array rNodes
+|* an der Position aWhere ein. Der
+|* theStartOfSection-Pointer wird entsprechend gesetzt,
+|* und der EndOfSection-Pointer des zugehoerigen
+|* Startnodes -- durch rStartOfSection bezeichnet --
+|* wird auf diesen Node gesetzt.
+|*
+|* Parameter
+|* IN
+|* rNodes bezeichnet das variable Array, in das der Node
+|* eingefuegt werden soll
+|* IN
+|* aWhere bezeichnet die Position innerhalb dieses Arrays,
+|* an der der Node eingefuegt werden soll
+|* !!!!!!!!!!!!
+|* Es wird eine Kopie uebergeben!
+|*
+*******************************************************************/
+
+
+SwEndNode::SwEndNode( const SwNodeIndex &rWhere, SwStartNode& rSttNd )
+ : SwNode( rWhere, ND_ENDNODE )
+{
+ pStartOfSection = &rSttNd;
+ pStartOfSection->pEndOfSection = this;
+}
+
+SwEndNode::SwEndNode( SwNodes& rNds, sal_uLong nPos, SwStartNode& rSttNd )
+ : SwNode( rNds, nPos, ND_ENDNODE )
+{
+ pStartOfSection = &rSttNd;
+ pStartOfSection->pEndOfSection = this;
+}
+
+
+
+// --------------------
+// SwCntntNode
+// --------------------
+
+
+SwCntntNode::SwCntntNode( const SwNodeIndex &rWhere, const sal_uInt8 nNdType,
+ SwFmtColl *pColl )
+ : SwModify( pColl ), // CrsrsShell, FrameFmt,
+ SwNode( rWhere, nNdType ),
+ pCondColl( 0 ),
+ mbSetModifyAtAttr( false )
+{
+}
+
+
+SwCntntNode::~SwCntntNode()
+{
+ // Die Basisklasse SwClient vom SwFrm nimmt sich aus
+ // der Abhaengikeitsliste raus!
+ // Daher muessen alle Frames in der Abhaengigkeitsliste geloescht werden.
+ if( GetDepends() )
+ DelFrms();
+
+ if( pCondColl )
+ delete pCondColl;
+
+ if ( mpAttrSet.get() && mbSetModifyAtAttr )
+ ((SwAttrSet*)mpAttrSet.get())->SetModifyAtAttr( 0 );
+}
+
+void SwCntntNode::Modify( const SfxPoolItem* pOldValue, const SfxPoolItem* pNewValue )
+{
+ sal_uInt16 nWhich = pOldValue ? pOldValue->Which() :
+ pNewValue ? pNewValue->Which() : 0 ;
+
+ switch( nWhich )
+ {
+ case RES_OBJECTDYING :
+ {
+ SwFmt * pFmt = (SwFmt *) ((SwPtrMsgPoolItem *)pNewValue)->pObject;
+
+ // nicht umhaengen wenn dieses das oberste Format ist !!
+ if( GetRegisteredIn() == pFmt )
+ {
+ if( pFmt->GetRegisteredIn() )
+ {
+ // wenn Parent, dann im neuen Parent wieder anmelden
+ ((SwModify*)pFmt->GetRegisteredIn())->Add( this );
+ if ( GetpSwAttrSet() )
+ AttrSetHandleHelper::SetParent( mpAttrSet, *this, GetFmtColl(), GetFmtColl() );
+ }
+ else
+ {
+ // sonst auf jeden Fall beim sterbenden abmelden
+ ((SwModify*)GetRegisteredIn())->Remove( this );
+ if ( GetpSwAttrSet() )
+ AttrSetHandleHelper::SetParent( mpAttrSet, *this, 0, 0 );
+ }
+ }
+ }
+ break;
+
+
+ case RES_FMT_CHG:
+ // falls mein Format Parent umgesetzt wird, dann melde ich
+ // meinen Attrset beim Neuen an.
+
+ // sein eigenes Modify ueberspringen !!
+ if( GetpSwAttrSet() &&
+ ((SwFmtChg*)pNewValue)->pChangedFmt == GetRegisteredIn() )
+ {
+ // den Set an den neuen Parent haengen
+ AttrSetHandleHelper::SetParent( mpAttrSet, *this, GetFmtColl(), GetFmtColl() );
+ }
+ break;
+//FEATURE::CONDCOLL
+ case RES_CONDCOLL_CONDCHG:
+ if( ((SwCondCollCondChg*)pNewValue)->pChangedFmt == GetRegisteredIn() &&
+ &GetNodes() == &GetDoc()->GetNodes() )
+ {
+ ChkCondColl();
+ }
+ return ; // nicht an die Basisklasse / Frames weitergeben
+//FEATURE::CONDCOLL
+
+ case RES_ATTRSET_CHG:
+ if( GetNodes().IsDocNodes() && IsTxtNode() )
+ {
+ if( SFX_ITEM_SET == ((SwAttrSetChg*)pOldValue)->GetChgSet()->GetItemState(
+ RES_CHRATR_HIDDEN, sal_False ) )
+ {
+ ((SwTxtNode*)this)->SetCalcHiddenCharFlags();
+ }
+ }
+ break;
+
+ case RES_UPDATE_ATTR:
+ if( GetNodes().IsDocNodes() && IsTxtNode() )
+ {
+ const sal_uInt16 nTmp = ((SwUpdateAttr*)pNewValue)->nWhichAttr;
+ if ( RES_ATTRSET_CHG == nTmp )
+ {
+ // anybody wants to do some optimization here?
+ ((SwTxtNode*)this)->SetCalcHiddenCharFlags();
+ }
+ }
+ break;
+ }
+
+ NotifyClients( pOldValue, pNewValue );
+}
+
+sal_Bool SwCntntNode::InvalidateNumRule()
+{
+ SwNumRule* pRule = 0;
+ const SfxPoolItem* pItem;
+ if( GetNodes().IsDocNodes() &&
+ 0 != ( pItem = GetNoCondAttr( RES_PARATR_NUMRULE, sal_True )) &&
+ ((SwNumRuleItem*)pItem)->GetValue().Len() &&
+ 0 != (pRule = GetDoc()->FindNumRulePtr(
+ ((SwNumRuleItem*)pItem)->GetValue() ) ) )
+ {
+ pRule->SetInvalidRule( sal_True );
+ }
+ return 0 != pRule;
+}
+
+SwCntntFrm *SwCntntNode::getLayoutFrm( const SwRootFrm* _pRoot,
+ const Point* pPoint, const SwPosition *pPos, const sal_Bool bCalcFrm ) const
+{
+ return (SwCntntFrm*) ::GetFrmOfModify( _pRoot, *(SwModify*)this, FRM_CNTNT,
+ pPoint, pPos, bCalcFrm );
+}
+
+SwRect SwCntntNode::FindLayoutRect( const sal_Bool bPrtArea, const Point* pPoint,
+ const sal_Bool bCalcFrm ) const
+{
+ SwRect aRet;
+ SwCntntFrm* pFrm = (SwCntntFrm*)::GetFrmOfModify( 0, *(SwModify*)this,
+ FRM_CNTNT, pPoint, 0, bCalcFrm );
+ if( pFrm )
+ aRet = bPrtArea ? pFrm->Prt() : pFrm->Frm();
+ return aRet;
+}
+
+SwRect SwCntntNode::FindPageFrmRect( const sal_Bool bPrtArea, const Point* pPoint,
+ const sal_Bool bCalcFrm ) const
+{
+ SwRect aRet;
+ SwFrm* pFrm = ::GetFrmOfModify( 0, *(SwModify*)this,
+ FRM_CNTNT, pPoint, 0, bCalcFrm );
+ if( pFrm && 0 != ( pFrm = pFrm->FindPageFrm() ))
+ aRet = bPrtArea ? pFrm->Prt() : pFrm->Frm();
+ return aRet;
+}
+
+xub_StrLen SwCntntNode::Len() const { return 0; }
+
+
+
+SwFmtColl *SwCntntNode::ChgFmtColl( SwFmtColl *pNewColl )
+{
+ OSL_ENSURE( pNewColl, "Collectionpointer ist 0." );
+ SwFmtColl *pOldColl = GetFmtColl();
+
+ if( pNewColl != pOldColl )
+ {
+ pNewColl->Add( this );
+
+ // setze den Parent von unseren Auto-Attributen auf die neue
+ // Collection:
+ if( GetpSwAttrSet() )
+ AttrSetHandleHelper::SetParent( mpAttrSet, *this, pNewColl, pNewColl );
+
+//FEATURE::CONDCOLL
+ // HACK: hier muss die entsprechend der neuen Vorlage die Bedingungen
+ // neu ueberprueft werden!
+ if( sal_True /*pNewColl */ )
+ {
+ SetCondFmtColl( 0 );
+ }
+//FEATURE::CONDCOLL
+
+ if( !IsModifyLocked() )
+ {
+ SwFmtChg aTmp1( pOldColl );
+ SwFmtChg aTmp2( pNewColl );
+ SwCntntNode::Modify( &aTmp1, &aTmp2 );
+ }
+ }
+ if ( IsInCache() )
+ {
+ SwFrm::GetCache().Delete( this );
+ SetInCache( sal_False );
+ }
+ return pOldColl;
+}
+
+
+sal_Bool SwCntntNode::GoNext(SwIndex * pIdx, sal_uInt16 nMode ) const
+{
+ sal_Bool bRet = sal_True;
+ if( pIdx->GetIndex() < Len() )
+ {
+ if( !IsTxtNode() )
+ (*pIdx)++;
+ else
+ {
+ const SwTxtNode& rTNd = *GetTxtNode();
+ xub_StrLen nPos = pIdx->GetIndex();
+ if( pBreakIt->GetBreakIter().is() )
+ {
+ sal_Int32 nDone = 0;
+ sal_uInt16 nItrMode = ( CRSR_SKIP_CELLS & nMode ) ?
+ CharacterIteratorMode::SKIPCELL :
+ CharacterIteratorMode::SKIPCONTROLCHARACTER;
+ nPos = (xub_StrLen)pBreakIt->GetBreakIter()->nextCharacters( rTNd.GetTxt(), nPos,
+ pBreakIt->GetLocale( rTNd.GetLang( nPos ) ),
+ nItrMode, 1, nDone );
+
+ // Check if nPos is inside hidden text range:
+ if ( CRSR_SKIP_HIDDEN & nMode )
+ {
+ xub_StrLen nHiddenStart;
+ xub_StrLen nHiddenEnd;
+ SwScriptInfo::GetBoundsOfHiddenRange( rTNd, nPos, nHiddenStart, nHiddenEnd );
+ if ( nHiddenStart != STRING_LEN && nHiddenStart != nPos )
+ nPos = nHiddenEnd;
+ }
+
+ if( 1 == nDone )
+ *pIdx = nPos;
+ else
+ bRet = sal_False;
+ }
+ else if( nPos < rTNd.GetTxt().Len() )
+ (*pIdx)++;
+ else
+ bRet = sal_False;
+ }
+ }
+ else
+ bRet = sal_False;
+ return bRet;
+}
+
+
+sal_Bool SwCntntNode::GoPrevious(SwIndex * pIdx, sal_uInt16 nMode ) const
+{
+ sal_Bool bRet = sal_True;
+ if( pIdx->GetIndex() > 0 )
+ {
+ if( !IsTxtNode() )
+ (*pIdx)--;
+ else
+ {
+ const SwTxtNode& rTNd = *GetTxtNode();
+ xub_StrLen nPos = pIdx->GetIndex();
+ if( pBreakIt->GetBreakIter().is() )
+ {
+ sal_Int32 nDone = 0;
+ sal_uInt16 nItrMode = ( CRSR_SKIP_CELLS & nMode ) ?
+ CharacterIteratorMode::SKIPCELL :
+ CharacterIteratorMode::SKIPCONTROLCHARACTER;
+ nPos = (xub_StrLen)pBreakIt->GetBreakIter()->previousCharacters( rTNd.GetTxt(), nPos,
+ pBreakIt->GetLocale( rTNd.GetLang( nPos ) ),
+ nItrMode, 1, nDone );
+
+ // Check if nPos is inside hidden text range:
+ if ( CRSR_SKIP_HIDDEN & nMode )
+ {
+ xub_StrLen nHiddenStart;
+ xub_StrLen nHiddenEnd;
+ SwScriptInfo::GetBoundsOfHiddenRange( rTNd, nPos, nHiddenStart, nHiddenEnd );
+ if ( nHiddenStart != STRING_LEN )
+ nPos = nHiddenStart;
+ }
+
+ if( 1 == nDone )
+ *pIdx = nPos;
+ else
+ bRet = sal_False;
+ }
+ else if( nPos )
+ (*pIdx)--;
+ else
+ bRet = sal_False;
+ }
+ }
+ else
+ bRet = sal_False;
+ return bRet;
+}
+
+
+/*
+ * Methode erzeugt fuer den vorhergehenden Node alle Ansichten vom
+ * Dokument. Die erzeugten Contentframes werden in das entsprechende
+ * Layout gehaengt.
+ */
+
+
+void SwCntntNode::MakeFrms( SwCntntNode& rNode )
+{
+ OSL_ENSURE( &rNode != this,
+ "Kein Contentnode oder Copy-Node und neuer Node identisch." );
+
+ if( !GetDepends() || &rNode == this ) // gibt es ueberhaupt Frames ??
+ return;
+
+ SwFrm *pFrm, *pNew;
+ SwLayoutFrm *pUpper;
+ // Frames anlegen fuer Nodes, die vor oder hinter der Tabelle stehen ??
+ OSL_ENSURE( FindTableNode() == rNode.FindTableNode(), "Table confusion" );
+
+ SwNode2Layout aNode2Layout( *this, rNode.GetIndex() );
+
+ while( 0 != (pUpper = aNode2Layout.UpperFrm( pFrm, rNode )) )
+ {
+ pNew = rNode.MakeFrm( pUpper );
+ pNew->Paste( pUpper, pFrm );
+ // #i27138#
+ // notify accessibility paragraphs objects about changed
+ // CONTENT_FLOWS_FROM/_TO relation.
+ // Relation CONTENT_FLOWS_FROM for next paragraph will change
+ // and relation CONTENT_FLOWS_TO for previous paragraph will change.
+ if ( pNew->IsTxtFrm() )
+ {
+ ViewShell* pViewShell( pNew->getRootFrm()->GetCurrShell() );
+ if ( pViewShell && pViewShell->GetLayout() &&
+ pViewShell->GetLayout()->IsAnyShellAccessible() )
+ {
+ pViewShell->InvalidateAccessibleParaFlowRelation(
+ dynamic_cast<SwTxtFrm*>(pNew->FindNextCnt( true )),
+ dynamic_cast<SwTxtFrm*>(pNew->FindPrevCnt( true )) );
+ }
+ }
+ // <--
+ }
+}
+
+/*
+ * Methode loescht fuer den Node alle Ansichten vom
+ * Dokument. Die Contentframes werden aus dem entsprechenden
+ * Layout ausgehaengt.
+ */
+
+
+void SwCntntNode::DelFrms()
+{
+ if( !GetDepends() )
+ return;
+
+ SwCntntFrm::DelFrms(*this);
+ if( IsTxtNode() )
+ {
+ ((SwTxtNode*)this)->SetWrong( NULL );
+ ((SwTxtNode*)this)->SetWrongDirty( true );
+
+ ((SwTxtNode*)this)->SetGrammarCheck( NULL );
+ ((SwTxtNode*)this)->SetGrammarCheckDirty( true );
+ // SMARTTAGS
+ ((SwTxtNode*)this)->SetSmartTags( NULL );
+ ((SwTxtNode*)this)->SetSmartTagDirty( true );
+
+ ((SwTxtNode*)this)->SetWordCountDirty( true );
+ ((SwTxtNode*)this)->SetAutoCompleteWordDirty( true );
+ }
+}
+
+
+SwCntntNode *SwCntntNode::JoinNext()
+{
+ return this;
+}
+
+
+SwCntntNode *SwCntntNode::JoinPrev()
+{
+ return this;
+}
+
+
+
+ // erfrage vom Modify Informationen
+sal_Bool SwCntntNode::GetInfo( SfxPoolItem& rInfo ) const
+{
+ switch( rInfo.Which() )
+ {
+ case RES_AUTOFMT_DOCNODE:
+ if( &GetNodes() == ((SwAutoFmtGetDocNode&)rInfo).pNodes )
+ {
+ ((SwAutoFmtGetDocNode&)rInfo).pCntntNode = this;
+ return sal_False;
+ }
+ break;
+
+ case RES_FINDNEARESTNODE:
+ if( ((SwFmtPageDesc&)GetAttr( RES_PAGEDESC )).GetPageDesc() )
+ ((SwFindNearestNode&)rInfo).CheckNode( *this );
+ return sal_True;
+
+ case RES_CONTENT_VISIBLE:
+ {
+ ((SwPtrMsgPoolItem&)rInfo).pObject =
+ SwIterator<SwFrm,SwCntntNode>::FirstElement(*this);
+ }
+ return sal_False;
+ }
+
+ return SwModify::GetInfo( rInfo );
+}
+
+
+ // setze ein Attribut
+sal_Bool SwCntntNode::SetAttr(const SfxPoolItem& rAttr )
+{
+ if( !GetpSwAttrSet() ) // lasse von den entsprechenden Nodes die
+ NewAttrSet( GetDoc()->GetAttrPool() ); // AttrSets anlegen
+
+ OSL_ENSURE( GetpSwAttrSet(), "warum wurde kein AttrSet angelegt?" );
+
+ if ( IsInCache() )
+ {
+ SwFrm::GetCache().Delete( this );
+ SetInCache( sal_False );
+ }
+
+ sal_Bool bRet = sal_False;
+ // wenn Modify gelockt ist, werden keine Modifies verschickt
+ if( IsModifyLocked() ||
+ ( !GetDepends() && RES_PARATR_NUMRULE != rAttr.Which() ))
+ {
+ bRet = 0 != AttrSetHandleHelper::Put( mpAttrSet, *this, rAttr );
+ }
+ else
+ {
+ SwAttrSet aOld( *GetpSwAttrSet()->GetPool(), GetpSwAttrSet()->GetRanges() ),
+ aNew( *GetpSwAttrSet()->GetPool(), GetpSwAttrSet()->GetRanges() );
+ if( 0 != ( bRet = 0 != AttrSetHandleHelper::Put_BC( mpAttrSet, *this, rAttr, &aOld, &aNew ) ))
+ {
+ SwAttrSetChg aChgOld( *GetpSwAttrSet(), aOld );
+ SwAttrSetChg aChgNew( *GetpSwAttrSet(), aNew );
+ ModifyNotification( &aChgOld, &aChgNew ); // alle veraenderten werden verschickt
+ }
+ }
+ return bRet;
+}
+#include <svl/itemiter.hxx>
+
+sal_Bool SwCntntNode::SetAttr( const SfxItemSet& rSet )
+{
+ if ( IsInCache() )
+ {
+ SwFrm::GetCache().Delete( this );
+ SetInCache( sal_False );
+ }
+
+ const SfxPoolItem* pFnd = 0;
+ if( SFX_ITEM_SET == rSet.GetItemState( RES_AUTO_STYLE, sal_False, &pFnd ) )
+ {
+ OSL_ENSURE( rSet.Count() == 1, "SetAutoStyle mixed with other attributes?!" );
+ const SwFmtAutoFmt* pTmp = static_cast<const SwFmtAutoFmt*>(pFnd);
+
+ // If there already is an attribute set (usually containing a numbering
+ // item), we have to merge the attribute of the new set into the old set:
+ bool bSetParent = true;
+ if ( GetpSwAttrSet() )
+ {
+ bSetParent = false;
+ AttrSetHandleHelper::Put( mpAttrSet, *this, *pTmp->GetStyleHandle() );
+ }
+ else
+ {
+ mpAttrSet = pTmp->GetStyleHandle();
+ }
+
+ if ( bSetParent )
+ {
+ // If the content node has a conditional style, we have to set the
+ // string item containing the correct conditional style name (the
+ // style name property has already been set during the import!)
+ // In case we do not have a conditional style, we make use of the
+ // fact that nobody else uses the attribute set behind the handle.
+ // FME 2007-07-10 #i78124# If autostyle does not have a parent,
+ // the string is empty.
+ const SfxPoolItem* pNameItem = 0;
+ if ( 0 != GetCondFmtColl() ||
+ SFX_ITEM_SET != mpAttrSet->GetItemState( RES_FRMATR_STYLE_NAME, sal_False, &pNameItem ) ||
+ 0 == static_cast<const SfxStringItem*>(pNameItem)->GetValue().Len() )
+ AttrSetHandleHelper::SetParent( mpAttrSet, *this, &GetAnyFmtColl(), GetFmtColl() );
+ else
+ const_cast<SfxItemSet*>(mpAttrSet.get())->SetParent( &GetFmtColl()->GetAttrSet() );
+ }
+
+ return sal_True;
+ }
+
+ if( !GetpSwAttrSet() ) // lasse von den entsprechenden Nodes die
+ NewAttrSet( GetDoc()->GetAttrPool() ); // AttrSets anlegen
+
+ sal_Bool bRet = sal_False;
+ // wenn Modify gelockt ist, werden keine Modifies verschickt
+ if ( IsModifyLocked() ||
+ ( !GetDepends() &&
+ SFX_ITEM_SET != rSet.GetItemState( RES_PARATR_NUMRULE, sal_False ) ) )
+ {
+ // einige Sonderbehandlungen fuer Attribute
+ bRet = 0 != AttrSetHandleHelper::Put( mpAttrSet, *this, rSet );
+ }
+ else
+ {
+ SwAttrSet aOld( *GetpSwAttrSet()->GetPool(), GetpSwAttrSet()->GetRanges() ),
+ aNew( *GetpSwAttrSet()->GetPool(), GetpSwAttrSet()->GetRanges() );
+ if( 0 != (bRet = 0 != AttrSetHandleHelper::Put_BC( mpAttrSet, *this, rSet, &aOld, &aNew )) )
+ {
+ // einige Sonderbehandlungen fuer Attribute
+ SwAttrSetChg aChgOld( *GetpSwAttrSet(), aOld );
+ SwAttrSetChg aChgNew( *GetpSwAttrSet(), aNew );
+ ModifyNotification( &aChgOld, &aChgNew ); // alle veraenderten werden verschickt
+ }
+ }
+ return bRet;
+}
+
+// Nimmt den Hint mit nWhich aus dem Delta-Array
+
+
+sal_Bool SwCntntNode::ResetAttr( sal_uInt16 nWhich1, sal_uInt16 nWhich2 )
+{
+ if( !GetpSwAttrSet() )
+ return sal_False;
+
+ if ( IsInCache() )
+ {
+ SwFrm::GetCache().Delete( this );
+ SetInCache( sal_False );
+ }
+
+ // wenn Modify gelockt ist, werden keine Modifies verschickt
+ if( IsModifyLocked() )
+ {
+ sal_uInt16 nDel = 0;
+ if ( !nWhich2 || nWhich2 < nWhich1 )
+ {
+ std::vector<sal_uInt16> aClearWhichIds;
+ aClearWhichIds.push_back( nWhich1 );
+ nDel = ClearItemsFromAttrSet( aClearWhichIds );
+ }
+ else
+ nDel = AttrSetHandleHelper::ClearItem_BC( mpAttrSet, *this, nWhich1, nWhich2, 0, 0 );
+
+ if( !GetpSwAttrSet()->Count() ) // leer, dann loeschen
+ mpAttrSet.reset();//DELETEZ( mpAttrSet );
+ return 0 != nDel;
+ }
+
+ // sollte kein gueltiger Bereich definiert sein ?
+ if( !nWhich2 || nWhich2 < nWhich1 )
+ nWhich2 = nWhich1; // dann setze auf 1. Id, nur dieses Item
+
+ SwAttrSet aOld( *GetpSwAttrSet()->GetPool(), GetpSwAttrSet()->GetRanges() ),
+ aNew( *GetpSwAttrSet()->GetPool(), GetpSwAttrSet()->GetRanges() );
+ sal_Bool bRet = 0 != AttrSetHandleHelper::ClearItem_BC( mpAttrSet, *this, nWhich1, nWhich2, &aOld, &aNew );
+
+ if( bRet )
+ {
+ SwAttrSetChg aChgOld( *GetpSwAttrSet(), aOld );
+ SwAttrSetChg aChgNew( *GetpSwAttrSet(), aNew );
+ ModifyNotification( &aChgOld, &aChgNew ); // alle veraenderten werden verschickt
+
+ if( !GetpSwAttrSet()->Count() ) // leer, dann loeschen
+ mpAttrSet.reset();//DELETEZ( mpAttrSet );
+ }
+ return bRet;
+}
+sal_Bool SwCntntNode::ResetAttr( const SvUShorts& rWhichArr )
+{
+ if( !GetpSwAttrSet() )
+ return sal_False;
+
+ if ( IsInCache() )
+ {
+ SwFrm::GetCache().Delete( this );
+ SetInCache( sal_False );
+ }
+
+ // wenn Modify gelockt ist, werden keine Modifies verschickt
+ sal_uInt16 nDel = 0;
+ if( IsModifyLocked() )
+ {
+ std::vector<sal_uInt16> aClearWhichIds;
+ for( sal_uInt16 n = 0, nEnd = rWhichArr.Count(); n < nEnd; ++n )
+ aClearWhichIds.push_back( rWhichArr[ n ] );
+
+ nDel = ClearItemsFromAttrSet( aClearWhichIds );
+ }
+ else
+ {
+ SwAttrSet aOld( *GetpSwAttrSet()->GetPool(), GetpSwAttrSet()->GetRanges() ),
+ aNew( *GetpSwAttrSet()->GetPool(), GetpSwAttrSet()->GetRanges() );
+
+ for( sal_uInt16 n = 0, nEnd = rWhichArr.Count(); n < nEnd; ++n )
+ if( AttrSetHandleHelper::ClearItem_BC( mpAttrSet, *this, rWhichArr[ n ], &aOld, &aNew ))
+ ++nDel;
+
+ if( nDel )
+ {
+ SwAttrSetChg aChgOld( *GetpSwAttrSet(), aOld );
+ SwAttrSetChg aChgNew( *GetpSwAttrSet(), aNew );
+ ModifyNotification( &aChgOld, &aChgNew ); // alle veraenderten werden verschickt
+ }
+ }
+ if( !GetpSwAttrSet()->Count() ) // leer, dann loeschen
+ mpAttrSet.reset();//DELETEZ( mpAttrSet );
+ return 0 != nDel ;
+}
+
+
+sal_uInt16 SwCntntNode::ResetAllAttr()
+{
+ if( !GetpSwAttrSet() )
+ return 0;
+
+ if ( IsInCache() )
+ {
+ SwFrm::GetCache().Delete( this );
+ SetInCache( sal_False );
+ }
+
+ // wenn Modify gelockt ist, werden keine Modifies verschickt
+ if( IsModifyLocked() )
+ {
+ std::vector<sal_uInt16> aClearWhichIds;
+ aClearWhichIds.push_back(0);
+ sal_uInt16 nDel = ClearItemsFromAttrSet( aClearWhichIds );
+ if( !GetpSwAttrSet()->Count() ) // leer, dann loeschen
+ mpAttrSet.reset(); // DELETEZ( mpAttrSet );
+ return nDel;
+ }
+
+ SwAttrSet aOld( *GetpSwAttrSet()->GetPool(), GetpSwAttrSet()->GetRanges() ),
+ aNew( *GetpSwAttrSet()->GetPool(), GetpSwAttrSet()->GetRanges() );
+ sal_Bool bRet = 0 != AttrSetHandleHelper::ClearItem_BC( mpAttrSet, *this, 0, &aOld, &aNew );
+
+ if( bRet )
+ {
+ SwAttrSetChg aChgOld( *GetpSwAttrSet(), aOld );
+ SwAttrSetChg aChgNew( *GetpSwAttrSet(), aNew );
+ ModifyNotification( &aChgOld, &aChgNew ); // alle veraenderten werden verschickt
+
+ if( !GetpSwAttrSet()->Count() ) // leer, dann loeschen
+ mpAttrSet.reset();//DELETEZ( mpAttrSet );
+ }
+ return aNew.Count();
+}
+
+
+sal_Bool SwCntntNode::GetAttr( SfxItemSet& rSet, sal_Bool bInParent ) const
+{
+ if( rSet.Count() )
+ rSet.ClearItem();
+
+ const SwAttrSet& rAttrSet = GetSwAttrSet();
+ if( bInParent )
+ return rSet.Set( rAttrSet, sal_True ) ? sal_True : sal_False;
+
+ rSet.Put( rAttrSet );
+ return rSet.Count() ? sal_True : sal_False;
+}
+
+sal_uInt16 SwCntntNode::ClearItemsFromAttrSet( const std::vector<sal_uInt16>& rWhichIds )
+{
+ sal_uInt16 nRet = 0;
+ if ( 0 == rWhichIds.size() )
+ return nRet;
+
+ OSL_ENSURE( GetpSwAttrSet(), "no item set" );
+ SwAttrSet aNewAttrSet( *GetpSwAttrSet() );
+ for ( std::vector<sal_uInt16>::const_iterator aIter = rWhichIds.begin();
+ aIter != rWhichIds.end();
+ ++aIter )
+ {
+ nRet = nRet + aNewAttrSet.ClearItem( *aIter );
+ }
+ if ( nRet )
+ AttrSetHandleHelper::GetNewAutoStyle( mpAttrSet, *this, aNewAttrSet );
+
+ return nRet;
+}
+
+const SfxPoolItem* SwCntntNode::GetNoCondAttr( sal_uInt16 nWhich,
+ sal_Bool bInParents ) const
+{
+ const SfxPoolItem* pFnd = 0;
+ if( pCondColl && pCondColl->GetRegisteredIn() )
+ {
+ if( !GetpSwAttrSet() || ( SFX_ITEM_SET != GetpSwAttrSet()->GetItemState(
+ nWhich, sal_False, &pFnd ) && bInParents ))
+ ((SwFmt*)GetRegisteredIn())->GetItemState( nWhich, bInParents, &pFnd );
+ }
+ // undo change of issue #i51029#
+ // Note: <GetSwAttrSet()> returns <mpAttrSet>, if set, otherwise it returns
+ // the attribute set of the paragraph style, which is valid for the
+ // content node - see file <node.hxx>
+ else
+ // <--
+ {
+ GetSwAttrSet().GetItemState( nWhich, bInParents, &pFnd );
+ }
+ return pFnd;
+}
+
+ // koennen 2 Nodes zusammengefasst werden ?
+ // in pIdx kann die 2. Position returnt werden.
+int SwCntntNode::CanJoinNext( SwNodeIndex* pIdx ) const
+{
+ const SwNodes& rNds = GetNodes();
+ sal_uInt8 nNdType = GetNodeType();
+ SwNodeIndex aIdx( *this, 1 );
+
+ const SwNode* pNd = this;
+ while( aIdx < rNds.Count()-1 &&
+ (( pNd = &aIdx.GetNode())->IsSectionNode() ||
+ ( pNd->IsEndNode() && pNd->StartOfSectionNode()->IsSectionNode() )))
+ aIdx++;
+
+ if( pNd->GetNodeType() != nNdType || rNds.Count()-1 == aIdx.GetIndex() )
+ return sal_False;
+ if( IsTxtNode() )
+ { // Do not merge strings if the result exceeds the allowed string length
+ const SwTxtNode* pTxtNd = static_cast<const SwTxtNode*>(this);
+ sal_uInt64 nSum = pTxtNd->GetTxt().Len();
+ pTxtNd = static_cast<const SwTxtNode*>(pNd);
+ nSum += pTxtNd->GetTxt().Len();
+ if( nSum > STRING_LEN )
+ return sal_False;
+ }
+ if( pIdx )
+ *pIdx = aIdx;
+ return sal_True;
+}
+
+
+ // koennen 2 Nodes zusammengefasst werden ?
+ // in pIdx kann die 2. Position returnt werden.
+int SwCntntNode::CanJoinPrev( SwNodeIndex* pIdx ) const
+{
+ sal_uInt8 nNdType = GetNodeType();
+ SwNodeIndex aIdx( *this, -1 );
+
+ const SwNode* pNd = this;
+ while( aIdx.GetIndex() &&
+ (( pNd = &aIdx.GetNode())->IsSectionNode() ||
+ ( pNd->IsEndNode() && pNd->StartOfSectionNode()->IsSectionNode() )))
+ aIdx--;
+
+ if( pNd->GetNodeType() != nNdType || 0 == aIdx.GetIndex() )
+ return sal_False;
+ if( pIdx )
+ *pIdx = aIdx;
+ return sal_True;
+}
+
+
+//FEATURE::CONDCOLL
+
+
+void SwCntntNode::SetCondFmtColl( SwFmtColl* pColl )
+{
+ if( (!pColl && pCondColl) || ( pColl && !pCondColl ) ||
+ ( pColl && pColl != pCondColl->GetRegisteredIn() ) )
+ {
+ SwFmtColl* pOldColl = GetCondFmtColl();
+ delete pCondColl;
+ if( pColl )
+ pCondColl = new SwDepend( this, pColl );
+ else
+ pCondColl = 0;
+
+ if( GetpSwAttrSet() )
+ {
+ AttrSetHandleHelper::SetParent( mpAttrSet, *this, &GetAnyFmtColl(), GetFmtColl() );
+ }
+
+ if( !IsModifyLocked() )
+ {
+ SwFmtChg aTmp1( pOldColl ? pOldColl : GetFmtColl() );
+ SwFmtChg aTmp2( pColl ? pColl : GetFmtColl() );
+ NotifyClients( &aTmp1, &aTmp2 );
+ }
+ if( IsInCache() )
+ {
+ SwFrm::GetCache().Delete( this );
+ SetInCache( sal_False );
+ }
+ }
+}
+
+
+sal_Bool SwCntntNode::IsAnyCondition( SwCollCondition& rTmp ) const
+{
+ const SwNodes& rNds = GetNodes();
+ {
+ int nCond = 0;
+ const SwStartNode* pSttNd = StartOfSectionNode();
+ while( pSttNd )
+ {
+ switch( pSttNd->GetNodeType() )
+ {
+ case ND_TABLENODE: nCond = PARA_IN_TABLEBODY; break;
+ case ND_SECTIONNODE: nCond = PARA_IN_SECTION; break;
+
+ default:
+ switch( pSttNd->GetStartNodeType() )
+ {
+ case SwTableBoxStartNode:
+ {
+ nCond = PARA_IN_TABLEBODY;
+ const SwTableNode* pTblNd = pSttNd->FindTableNode();
+ const SwTableBox* pBox;
+ if( pTblNd && 0 != ( pBox = pTblNd->GetTable().
+ GetTblBox( pSttNd->GetIndex() ) ) && pBox &&
+ pBox->IsInHeadline( &pTblNd->GetTable() ) )
+ nCond = PARA_IN_TABLEHEAD;
+ }
+ break;
+ case SwFlyStartNode: nCond = PARA_IN_FRAME; break;
+ case SwFootnoteStartNode:
+ {
+ nCond = PARA_IN_FOOTENOTE;
+ const SwFtnIdxs& rFtnArr = rNds.GetDoc()->GetFtnIdxs();
+ const SwTxtFtn* pTxtFtn;
+ const SwNode* pSrchNd = pSttNd;
+
+ for( sal_uInt16 n = 0; n < rFtnArr.Count(); ++n )
+ if( 0 != ( pTxtFtn = rFtnArr[ n ])->GetStartNode() &&
+ pSrchNd == &pTxtFtn->GetStartNode()->GetNode() )
+ {
+ if( pTxtFtn->GetFtn().IsEndNote() )
+ nCond = PARA_IN_ENDNOTE;
+ break;
+ }
+ }
+ break;
+ case SwHeaderStartNode: nCond = PARA_IN_HEADER; break;
+ case SwFooterStartNode: nCond = PARA_IN_FOOTER; break;
+ case SwNormalStartNode: break;
+ }
+ }
+
+ if( nCond )
+ {
+ rTmp.SetCondition( (Master_CollConditions)nCond, 0 );
+ return sal_True;
+ }
+ pSttNd = pSttNd->GetIndex()
+ ? pSttNd->StartOfSectionNode()
+ : 0;
+ }
+ }
+
+ {
+ sal_uInt16 nPos;
+ const SwOutlineNodes& rOutlNds = rNds.GetOutLineNds();
+ if( rOutlNds.Count() )
+ {
+ if( !rOutlNds.Seek_Entry( (SwCntntNode*)this, &nPos ) && nPos )
+ --nPos;
+ if( nPos < rOutlNds.Count() &&
+ rOutlNds[ nPos ]->GetIndex() < GetIndex() )
+ {
+ SwTxtNode* pOutlNd = rOutlNds[ nPos ]->GetTxtNode();
+
+ if( pOutlNd->IsOutline())
+ {
+ rTmp.SetCondition( PARA_IN_OUTLINE, pOutlNd->GetAttrOutlineLevel() - 1 );
+ return sal_True;
+ }
+ }
+ }
+ }
+
+ return sal_False;
+}
+
+
+void SwCntntNode::ChkCondColl()
+{
+ // zur Sicherheit abfragen
+ if( RES_CONDTXTFMTCOLL == GetFmtColl()->Which() )
+ {
+ SwCollCondition aTmp( 0, 0, 0 );
+ const SwCollCondition* pCColl;
+
+ bool bDone = false;
+
+ if( IsAnyCondition( aTmp ))
+ {
+ pCColl = static_cast<SwConditionTxtFmtColl*>(GetFmtColl())
+ ->HasCondition( aTmp );
+
+ if (pCColl)
+ {
+ SetCondFmtColl( pCColl->GetTxtFmtColl() );
+ bDone = true;
+ }
+ }
+
+ if (!bDone)
+ {
+ if( IsTxtNode() && ((SwTxtNode*)this)->GetNumRule())
+ {
+ // steht in einer Numerierung
+ // welcher Level?
+ aTmp.SetCondition( PARA_IN_LIST,
+ ((SwTxtNode*)this)->GetActualListLevel() );
+ pCColl = ((SwConditionTxtFmtColl*)GetFmtColl())->
+ HasCondition( aTmp );
+ }
+ else
+ pCColl = 0;
+
+ if( pCColl )
+ SetCondFmtColl( pCColl->GetTxtFmtColl() );
+ else if( pCondColl )
+ SetCondFmtColl( 0 );
+ }
+ }
+}
+
+// #i42921#
+short SwCntntNode::GetTextDirection( const SwPosition& rPos,
+ const Point* pPt ) const
+{
+ short nRet = -1;
+
+ Point aPt;
+ if( pPt )
+ aPt = *pPt;
+
+ // #i72024# - No format of the frame, because this can cause recursive layout actions
+ SwFrm* pFrm = getLayoutFrm( GetDoc()->GetCurrentLayout(), &aPt, &rPos, sal_False );
+
+ if ( pFrm )
+ {
+ if ( pFrm->IsVertical() )
+ {
+ if ( pFrm->IsRightToLeft() )
+ nRet = FRMDIR_VERT_TOP_LEFT;
+ else
+ nRet = FRMDIR_VERT_TOP_RIGHT;
+ }
+ else
+ {
+ if ( pFrm->IsRightToLeft() )
+ nRet = FRMDIR_HORI_RIGHT_TOP;
+ else
+ nRet = FRMDIR_HORI_LEFT_TOP;
+ }
+ }
+
+
+ return nRet;
+}
+// <--
+
+SwOLENodes* SwCntntNode::CreateOLENodesArray( const SwFmtColl& rColl, bool bOnlyWithInvalidSize )
+{
+ SwOLENodes *pNodes = 0;
+ SwIterator<SwCntntNode,SwFmtColl> aIter( rColl );
+ for( SwCntntNode* pNd = aIter.First(); pNd; pNd = aIter.Next() )
+ {
+ SwOLENode *pONd = pNd->GetOLENode();
+ if ( pONd && (!bOnlyWithInvalidSize || pONd->IsOLESizeInvalid()) )
+ {
+ if ( !pNodes )
+ pNodes = new SwOLENodes;
+ pNodes->Insert( pONd, pNodes->Count() );
+ }
+ }
+
+ return pNodes;
+}
+
+//FEATURE::CONDCOLL
+// Metoden aus Node.hxx - erst hier ist der TxtNode bekannt !!
+// os: nur fuer ICC, da der zum optimieren zu dumm ist
+#ifdef ICC
+SwTxtNode *SwNode::GetTxtNode()
+{
+ return ND_TEXTNODE == nNodeType ? (SwTxtNode*)this : 0;
+}
+const SwTxtNode *SwNode::GetTxtNode() const
+{
+ return ND_TEXTNODE == nNodeType ? (const SwTxtNode*)this : 0;
+}
+#endif
+
+/*
+ * Document Interface Access
+ */
+const IDocumentSettingAccess* SwNode::getIDocumentSettingAccess() const { return GetDoc(); }
+const IDocumentDeviceAccess* SwNode::getIDocumentDeviceAccess() const { return GetDoc(); }
+const IDocumentMarkAccess* SwNode::getIDocumentMarkAccess() const { return GetDoc()->getIDocumentMarkAccess(); }
+const IDocumentRedlineAccess* SwNode::getIDocumentRedlineAccess() const { return GetDoc(); }
+const IDocumentStylePoolAccess* SwNode::getIDocumentStylePoolAccess() const { return GetDoc(); }
+const IDocumentLineNumberAccess* SwNode::getIDocumentLineNumberAccess() const { return GetDoc(); }
+const IDocumentDrawModelAccess* SwNode::getIDocumentDrawModelAccess() const { return GetDoc(); }
+const IDocumentLayoutAccess* SwNode::getIDocumentLayoutAccess() const { return GetDoc(); }
+IDocumentLayoutAccess* SwNode::getIDocumentLayoutAccess() { return GetDoc(); }
+const IDocumentLinksAdministration* SwNode::getIDocumentLinksAdministration() const { return GetDoc(); }
+IDocumentLinksAdministration* SwNode::getIDocumentLinksAdministration() { return GetDoc(); }
+const IDocumentFieldsAccess* SwNode::getIDocumentFieldsAccess() const { return GetDoc(); }
+IDocumentFieldsAccess* SwNode::getIDocumentFieldsAccess() { return GetDoc(); }
+IDocumentContentOperations* SwNode::getIDocumentContentOperations() { return GetDoc(); }
+IStyleAccess& SwNode::getIDocumentStyleAccess() { return GetDoc()->GetIStyleAccess(); }
+// #i83479#
+IDocumentListItems& SwNode::getIDocumentListItems()
+{
+ return *GetDoc();
+}
+
+sal_Bool SwNode::IsInRedlines() const
+{
+ const SwDoc * pDoc = GetDoc();
+ sal_Bool bResult = sal_False;
+
+ if (pDoc != NULL)
+ bResult = pDoc->IsInRedlines(*this);
+
+ return bResult;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/docnode/node2lay.cxx b/sw/source/core/docnode/node2lay.cxx
new file mode 100644
index 000000000000..16bc2fef53ae
--- /dev/null
+++ b/sw/source/core/docnode/node2lay.cxx
@@ -0,0 +1,474 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+#include <switerator.hxx>
+#include <calbck.hxx>
+#include <node.hxx>
+#include <ndindex.hxx>
+#include <swtable.hxx>
+#include <ftnfrm.hxx>
+#include <sectfrm.hxx>
+#include "frmfmt.hxx"
+#include "cntfrm.hxx"
+#include "tabfrm.hxx"
+#include "frmtool.hxx"
+#include "section.hxx"
+#include "node2lay.hxx"
+
+/* --------------------------------------------------
+ * Die SwNode2LayImpl-Klasse erledigt die eigentliche Arbeit,
+ * die SwNode2Layout-Klasse ist nur die der Oefffentlichkeit bekannte Schnittstelle
+ * --------------------------------------------------*/
+class SwNode2LayImpl
+{
+ SwIterator<SwFrm,SwModify>* pIter;
+ SwModify* pMod;
+ SvPtrarr *pUpperFrms;// Zum Einsammeln der Upper
+ sal_uLong nIndex; // Der Index des einzufuegenden Nodes
+ sal_Bool bMaster : 1; // sal_True => nur Master , sal_False => nur Frames ohne Follow
+ sal_Bool bInit : 1; // Ist am SwClient bereits ein First()-Aufruf erfolgt?
+public:
+ SwNode2LayImpl( const SwNode& rNode, sal_uLong nIdx, sal_Bool bSearch );
+ ~SwNode2LayImpl() { delete pIter; delete pUpperFrms; }
+ SwFrm* NextFrm(); // liefert den naechsten "sinnvollen" Frame
+ SwLayoutFrm* UpperFrm( SwFrm* &rpFrm, const SwNode &rNode );
+ void SaveUpperFrms(); // Speichert (und lockt ggf.) die pUpper
+ // Fuegt unter jeden pUpper des Arrays einen Frame ein.
+ void RestoreUpperFrms( SwNodes& rNds, sal_uLong nStt, sal_uLong nEnd );
+
+ SwFrm* GetFrm( const Point* pDocPos = 0,
+ const SwPosition *pPos = 0,
+ const sal_Bool bCalcFrm = sal_True ) const;
+};
+
+/* --------------------------------------------------
+ * Hauptaufgabe des Ctor: Das richtige SwModify zu ermitteln,
+ * ueber das iteriert wird.
+ * Uebergibt man bSearch == sal_True, so wird der naechste Cntnt- oder TableNode
+ * gesucht, der Frames besitzt ( zum Einsammeln der pUpper ), ansonsten wird
+ * erwartet, das rNode bereits auf einem solchen Cntnt- oder TableNode sitzt,
+ * vor oder hinter den eingefuegt werden soll.
+ * --------------------------------------------------*/
+
+SwNode* GoNextWithFrm(const SwNodes& rNodes, SwNodeIndex *pIdx)
+{
+ if( pIdx->GetIndex() >= rNodes.Count() - 1 )
+ return 0;
+
+ SwNodeIndex aTmp(*pIdx, +1);
+ SwNode* pNd = 0;
+ while( aTmp < rNodes.Count()-1 )
+ {
+ pNd = &aTmp.GetNode();
+ bool bFound = false;
+ if ( pNd->IsCntntNode() )
+ bFound = ( SwIterator<SwFrm,SwCntntNode>::FirstElement(*(SwCntntNode*)pNd) != 0);
+ else if ( pNd->IsTableNode() )
+ bFound = ( SwIterator<SwFrm,SwFmt>::FirstElement(*((SwTableNode*)pNd)->GetTable().GetFrmFmt()) != 0 );
+ else if( pNd->IsEndNode() && !pNd->StartOfSectionNode()->IsSectionNode() )
+ {
+ pNd = 0;
+ break;
+ }
+ if ( bFound )
+ break;
+ aTmp++;
+ }
+
+ if( aTmp == rNodes.Count()-1 )
+ pNd = 0;
+ else if( pNd )
+ (*pIdx) = aTmp;
+ return pNd;
+}
+
+SwNode* GoPreviousWithFrm(SwNodeIndex *pIdx)
+{
+ if( !pIdx->GetIndex() )
+ return 0;
+
+ SwNodeIndex aTmp( *pIdx, -1 );
+ SwNode* pNd(0);
+ while( aTmp.GetIndex() )
+ {
+ pNd = &aTmp.GetNode();
+ bool bFound = false;
+ if ( pNd->IsCntntNode() )
+ bFound = ( SwIterator<SwFrm,SwCntntNode>::FirstElement(*(SwCntntNode*)pNd) != 0);
+ else if ( pNd->IsTableNode() )
+ bFound = ( SwIterator<SwFrm,SwFmt>::FirstElement(*((SwTableNode*)pNd)->GetTable().GetFrmFmt()) != 0 );
+ else if( pNd->IsStartNode() && !pNd->IsSectionNode() )
+ {
+ pNd = 0;
+ break;
+ }
+ if ( bFound )
+ break;
+ aTmp--;
+ }
+
+ if( !aTmp.GetIndex() )
+ pNd = 0;
+ else if( pNd )
+ (*pIdx) = aTmp;
+ return pNd;
+}
+
+
+SwNode2LayImpl::SwNode2LayImpl( const SwNode& rNode, sal_uLong nIdx, sal_Bool bSearch )
+ : pUpperFrms( NULL ), nIndex( nIdx ), bInit( sal_False )
+{
+ const SwNode* pNd;
+ if( bSearch || rNode.IsSectionNode() )
+ {
+ // Suche den naechsten Cntnt/TblNode, der einen Frame besitzt,
+ // damit wir uns vor/hinter ihn haengen koennen
+ if( !bSearch && rNode.GetIndex() < nIndex )
+ {
+ SwNodeIndex aTmp( *rNode.EndOfSectionNode(), +1 );
+ pNd = GoPreviousWithFrm( &aTmp );
+ if( !bSearch && pNd && rNode.GetIndex() > pNd->GetIndex() )
+ pNd = NULL; // Nicht ueber den Bereich hinausschiessen
+ bMaster = sal_False;
+ }
+ else
+ {
+ SwNodeIndex aTmp( rNode, -1 );
+ pNd = GoNextWithFrm( rNode.GetNodes(), &aTmp );
+ bMaster = sal_True;
+ if( !bSearch && pNd && rNode.EndOfSectionIndex() < pNd->GetIndex() )
+ pNd = NULL; // Nicht ueber den Bereich hinausschiessen
+ }
+ }
+ else
+ {
+ pNd = &rNode;
+ bMaster = nIndex < rNode.GetIndex();
+ }
+ if( pNd )
+ {
+ if( pNd->IsCntntNode() )
+ pMod = (SwModify*)pNd->GetCntntNode();
+ else
+ {
+ OSL_ENSURE( pNd->IsTableNode(), "For Tablenodes only" );
+ pMod = pNd->GetTableNode()->GetTable().GetFrmFmt();
+ }
+ pIter = new SwIterator<SwFrm,SwModify>( *pMod );
+ }
+ else
+ {
+ pIter = NULL;
+ pMod = 0;
+ }
+}
+
+/* --------------------------------------------------
+ * SwNode2LayImpl::NextFrm() liefert den naechsten "sinnvollen" Frame,
+ * beim ersten Aufruf wird am eigentlichen Iterator ein First gerufen,
+ * danach die Next-Methode. Das Ergebnis wird auf Brauchbarkeit untersucht,
+ * so werden keine Follows akzeptiert, ein Master wird beim Einsammeln der
+ * pUpper und beim Einfuegen vor ihm akzeptiert. Beim Einfuegen dahinter
+ * wird vom Master ausgehend der letzte Follow gesucht und zurueckgegeben.
+ * Wenn der Frame innerhalb eines SectionFrms liegt, wird noch festgestellt,
+ * ob statt des Frames der SectionFrm der geeignete Rueckgabewert ist, dies
+ * ist der Fall, wenn der neu einzufuegende Node ausserhalb des Bereichs liegt.
+ * --------------------------------------------------*/
+SwFrm* SwNode2LayImpl::NextFrm()
+{
+ SwFrm* pRet;
+ if( !pIter )
+ return sal_False;
+ if( !bInit )
+ {
+ pRet = pIter->First();
+ bInit = sal_True;
+ }
+ else
+ pRet = pIter->Next();
+ while( pRet )
+ {
+ SwFlowFrm* pFlow = SwFlowFrm::CastFlowFrm( pRet );
+ OSL_ENSURE( pFlow, "Cntnt or Table expected?!" );
+ // Follows sind fluechtige Gestalten, deshalb werden sie ignoriert.
+ // Auch wenn wir hinter dem Frame eingefuegt werden sollen, nehmen wir
+ // zunaechst den Master, hangeln uns dann aber zum letzten Follow durch.
+ if( !pFlow->IsFollow() )
+ {
+ if( !bMaster )
+ {
+ while( pFlow->HasFollow() )
+ pFlow = pFlow->GetFollow();
+ pRet = pFlow->GetFrm();
+ }
+ if( pRet->IsInSct() )
+ {
+ SwSectionFrm* pSct = pRet->FindSctFrm();
+ // Vorsicht: Wenn wir in einer Fussnote sind, so kann diese
+ // Layoutmaessig in einem spaltigen Bereich liegen, obwohl
+ // sie nodemaessig ausserhalb liegt. Deshalb muss bei Fussnoten
+ // ueberprueft werden, ob auch der SectionFrm in der Fussnote
+ // und nicht ausserhalb liegt.
+ if( !pRet->IsInFtn() || pSct->IsInFtn() )
+ {
+ OSL_ENSURE( pSct && pSct->GetSection(), "Where's my section?" );
+ SwSectionNode* pNd = pSct->GetSection()->GetFmt()->GetSectionNode();
+ OSL_ENSURE( pNd, "Lost SectionNode" );
+ // Wenn der erhaltene Frame in einem Bereichsframe steht,
+ // dessen Bereich den Ausgangsnode nicht umfasst, so kehren
+ // wir mit dem SectionFrm zurueck, sonst mit dem Cntnt/TabFrm
+ if( bMaster )
+ {
+ if( pNd->GetIndex() >= nIndex )
+ pRet = pSct;
+ }
+ else if( pNd->EndOfSectionIndex() < nIndex )
+ pRet = pSct;
+ }
+ }
+ return pRet;
+ }
+ pRet = pIter->Next();
+ }
+ return NULL;
+}
+
+void SwNode2LayImpl::SaveUpperFrms()
+{
+ pUpperFrms = new SvPtrarr( 0, 20 );
+ SwFrm* pFrm;
+ while( 0 != (pFrm = NextFrm()) )
+ {
+ SwFrm* pPrv = pFrm->GetPrev();
+ pFrm = pFrm->GetUpper();
+ if( pFrm )
+ {
+ if( pFrm->IsFtnFrm() )
+ ((SwFtnFrm*)pFrm)->ColLock();
+ else if( pFrm->IsInSct() )
+ pFrm->FindSctFrm()->ColLock();
+ if( pPrv && pPrv->IsSctFrm() )
+ ((SwSectionFrm*)pPrv)->LockJoin();
+ pUpperFrms->Insert( (void*)pPrv, pUpperFrms->Count() );
+ pUpperFrms->Insert( (void*)pFrm, pUpperFrms->Count() );
+ }
+ }
+ delete pIter;
+ pIter = NULL;
+ pMod = 0;
+}
+
+SwLayoutFrm* SwNode2LayImpl::UpperFrm( SwFrm* &rpFrm, const SwNode &rNode )
+{
+ rpFrm = NextFrm();
+ if( !rpFrm )
+ return NULL;
+ SwLayoutFrm* pUpper = rpFrm->GetUpper();
+ if( rpFrm->IsSctFrm() )
+ {
+ const SwNode* pNode = rNode.StartOfSectionNode();
+ if( pNode->IsSectionNode() )
+ {
+ SwFrm* pFrm = bMaster ? rpFrm->FindPrev() : rpFrm->FindNext();
+ if( pFrm && pFrm->IsSctFrm() )
+ {
+ // pFrm could be a "dummy"-section
+ if( ((SwSectionFrm*)pFrm)->GetSection() &&
+ (&((SwSectionNode*)pNode)->GetSection() ==
+ ((SwSectionFrm*)pFrm)->GetSection()) )
+ {
+ // #i22922# - consider columned sections
+ // 'Go down' the section frame as long as the layout frame
+ // is found, which would contain content.
+ while ( pFrm->IsLayoutFrm() &&
+ static_cast<SwLayoutFrm*>(pFrm)->Lower() &&
+ !static_cast<SwLayoutFrm*>(pFrm)->Lower()->IsFlowFrm() &&
+ static_cast<SwLayoutFrm*>(pFrm)->Lower()->IsLayoutFrm() )
+ {
+ pFrm = static_cast<SwLayoutFrm*>(pFrm)->Lower();
+ }
+ OSL_ENSURE( pFrm->IsLayoutFrm(),
+ "<SwNode2LayImpl::UpperFrm(..)> - expected upper frame isn't a layout frame." );
+ rpFrm = bMaster ? NULL
+ : static_cast<SwLayoutFrm*>(pFrm)->Lower();
+ OSL_ENSURE( !rpFrm || rpFrm->IsFlowFrm(),
+ "<SwNode2LayImpl::UpperFrm(..)> - expected sibling isn't a flow frame." );
+ return static_cast<SwLayoutFrm*>(pFrm);
+ }
+
+ pUpper = new SwSectionFrm(((SwSectionNode*)pNode)->GetSection(), rpFrm);
+ pUpper->Paste( rpFrm->GetUpper(),
+ bMaster ? rpFrm : rpFrm->GetNext() );
+ static_cast<SwSectionFrm*>(pUpper)->Init();
+ rpFrm = NULL;
+ // 'Go down' the section frame as long as the layout frame
+ // is found, which would contain content.
+ while ( pUpper->Lower() &&
+ !pUpper->Lower()->IsFlowFrm() &&
+ pUpper->Lower()->IsLayoutFrm() )
+ {
+ pUpper = static_cast<SwLayoutFrm*>(pUpper->Lower());
+ }
+ return pUpper;
+ }
+ }
+ };
+ if( !bMaster )
+ rpFrm = rpFrm->GetNext();
+ return pUpper;
+}
+
+void SwNode2LayImpl::RestoreUpperFrms( SwNodes& rNds, sal_uLong nStt, sal_uLong nEnd )
+{
+ OSL_ENSURE( pUpperFrms, "RestoreUpper without SaveUpper?" );
+ SwNode* pNd;
+ SwDoc *pDoc = rNds.GetDoc();
+ sal_Bool bFirst = sal_True;
+ for( ; nStt < nEnd; ++nStt )
+ {
+ SwFrm* pNew = 0;
+ SwFrm* pNxt;
+ SwLayoutFrm* pUp;
+ if( (pNd = rNds[nStt])->IsCntntNode() )
+ for( sal_uInt16 n = 0; n < pUpperFrms->Count(); )
+ {
+ pNxt = (SwFrm*)(*pUpperFrms)[n++];
+ if( bFirst && pNxt && pNxt->IsSctFrm() )
+ ((SwSectionFrm*)pNxt)->UnlockJoin();
+ pUp = (SwLayoutFrm*)(*pUpperFrms)[n++];
+ if( pNxt )
+ pNxt = pNxt->GetNext();
+ else
+ pNxt = pUp->Lower();
+ pNew = ((SwCntntNode*)pNd)->MakeFrm( pUp );
+ pNew->Paste( pUp, pNxt );
+ (*pUpperFrms)[n-2] = pNew;
+ }
+ else if( pNd->IsTableNode() )
+ for( sal_uInt16 x = 0; x < pUpperFrms->Count(); )
+ {
+ pNxt = (SwFrm*)(*pUpperFrms)[x++];
+ if( bFirst && pNxt && pNxt->IsSctFrm() )
+ ((SwSectionFrm*)pNxt)->UnlockJoin();
+ pUp = (SwLayoutFrm*)(*pUpperFrms)[x++];
+ if( pNxt )
+ pNxt = pNxt->GetNext();
+ else
+ pNxt = pUp->Lower();
+ pNew = ((SwTableNode*)pNd)->MakeFrm( pUp );
+ OSL_ENSURE( pNew->IsTabFrm(), "Table exspected" );
+ pNew->Paste( pUp, pNxt );
+ ((SwTabFrm*)pNew)->RegistFlys();
+ (*pUpperFrms)[x-2] = pNew;
+ }
+ else if( pNd->IsSectionNode() )
+ {
+ nStt = pNd->EndOfSectionIndex();
+ for( sal_uInt16 x = 0; x < pUpperFrms->Count(); )
+ {
+ pNxt = (SwFrm*)(*pUpperFrms)[x++];
+ if( bFirst && pNxt && pNxt->IsSctFrm() )
+ ((SwSectionFrm*)pNxt)->UnlockJoin();
+ pUp = (SwLayoutFrm*)(*pUpperFrms)[x++];
+ OSL_ENSURE( pUp->GetUpper() || pUp->IsFlyFrm(), "Lost Upper" );
+ ::_InsertCnt( pUp, pDoc, pNd->GetIndex(), sal_False, nStt+1, pNxt );
+ pNxt = pUp->GetLastLower();
+ (*pUpperFrms)[x-2] = pNxt;
+ }
+ }
+ bFirst = sal_False;
+ }
+ for( sal_uInt16 x = 0; x < pUpperFrms->Count(); ++x )
+ {
+ SwFrm* pTmp = (SwFrm*)(*pUpperFrms)[++x];
+ if( pTmp->IsFtnFrm() )
+ ((SwFtnFrm*)pTmp)->ColUnlock();
+ else if ( pTmp->IsInSct() )
+ {
+ SwSectionFrm* pSctFrm = pTmp->FindSctFrm();
+ pSctFrm->ColUnlock();
+ // #i18103# - invalidate size of section in order to
+ // assure, that the section is formatted, unless it was 'Collocked'
+ // from its 'collection' until its 'restoration'.
+ pSctFrm->_InvalidateSize();
+ }
+ }
+}
+
+SwFrm* SwNode2LayImpl::GetFrm( const Point* pDocPos,
+ const SwPosition *pPos,
+ const sal_Bool bCalcFrm ) const
+{
+ // mba: test if change of member pIter -> pMod broke anything
+ return pMod ? ::GetFrmOfModify( 0, *pMod, USHRT_MAX, pDocPos, pPos, bCalcFrm ) : 0;
+}
+
+SwNode2Layout::SwNode2Layout( const SwNode& rNd, sal_uLong nIdx )
+{
+ pImpl = new SwNode2LayImpl( rNd, nIdx, sal_False );
+}
+
+SwNode2Layout::SwNode2Layout( const SwNode& rNd )
+{
+ pImpl = new SwNode2LayImpl( rNd, rNd.GetIndex(), sal_True );
+ pImpl->SaveUpperFrms();
+}
+
+void SwNode2Layout::RestoreUpperFrms( SwNodes& rNds, sal_uLong nStt, sal_uLong nEnd )
+{
+ OSL_ENSURE( pImpl, "RestoreUpperFrms without SaveUpperFrms" );
+ pImpl->RestoreUpperFrms( rNds, nStt, nEnd );
+}
+
+SwFrm* SwNode2Layout::NextFrm()
+{
+ return pImpl->NextFrm();
+}
+
+SwLayoutFrm* SwNode2Layout::UpperFrm( SwFrm* &rpFrm, const SwNode &rNode )
+{
+ return pImpl->UpperFrm( rpFrm, rNode );
+}
+
+SwNode2Layout::~SwNode2Layout()
+{
+ delete pImpl;
+}
+
+SwFrm* SwNode2Layout::GetFrm( const Point* pDocPos,
+ const SwPosition *pPos,
+ const sal_Bool bCalcFrm ) const
+{
+ return pImpl->GetFrm( pDocPos, pPos, bCalcFrm );
+}
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/docnode/nodes.cxx b/sw/source/core/docnode/nodes.cxx
new file mode 100644
index 000000000000..dbd0f4194bf8
--- /dev/null
+++ b/sw/source/core/docnode/nodes.cxx
@@ -0,0 +1,2508 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+#include <stdlib.h>
+
+#include <node.hxx>
+#include <doc.hxx>
+#include <IDocumentUndoRedo.hxx>
+#include <pam.hxx>
+#include <txtfld.hxx>
+#include <fmtfld.hxx>
+#include <hints.hxx>
+#include <numrule.hxx>
+#include <ndtxt.hxx>
+#include <ndnotxt.hxx>
+#include <swtable.hxx> // fuer erzuegen / loeschen der Table-Frames
+#include <tblsel.hxx>
+#include <section.hxx>
+#include <ddefld.hxx>
+#include <swddetbl.hxx>
+#include <frame.hxx>
+#include <txtatr.hxx>
+#include <tox.hxx> // InvalidateTOXMark
+
+#include <docsh.hxx>
+#include <svl/smplhint.hxx>
+
+extern sal_Bool CheckNodesRange( const SwNodeIndex& rStt,
+ const SwNodeIndex& rEnd, sal_Bool bChkSection );
+
+SV_DECL_PTRARR(SwSttNdPtrs,SwStartNode*,2,2)
+
+
+// Funktion zum bestimmen des hoechsten Levels innerhalb des Bereiches
+
+sal_uInt16 HighestLevel( SwNodes & rNodes, const SwNodeRange & rRange );
+
+//-----------------------------------------------------------------------
+
+/*******************************************************************
+|* SwNodes::SwNodes
+|*
+|* Beschreibung
+|* Konstruktor; legt die vier Grundsektions (PostIts,
+|* Inserts, Icons, Inhalt) an
+*******************************************************************/
+SwNodes::SwNodes( SwDoc* pDocument )
+ : pRoot( 0 ), pMyDoc( pDocument )
+{
+ bInNodesDel = bInDelUpdOutl = bInDelUpdNum = sal_False;
+
+ OSL_ENSURE( pMyDoc, "in welchem Doc stehe ich denn?" );
+
+ sal_uLong nPos = 0;
+ SwStartNode* pSttNd = new SwStartNode( *this, nPos++ );
+ pEndOfPostIts = new SwEndNode( *this, nPos++, *pSttNd );
+
+ SwStartNode* pTmp = new SwStartNode( *this, nPos++ );
+ pEndOfInserts = new SwEndNode( *this, nPos++, *pTmp );
+
+ pTmp = new SwStartNode( *this, nPos++ );
+ pTmp->pStartOfSection = pSttNd;
+ pEndOfAutotext = new SwEndNode( *this, nPos++, *pTmp );
+
+ pTmp = new SwStartNode( *this, nPos++ );
+ pTmp->pStartOfSection = pSttNd;
+ pEndOfRedlines = new SwEndNode( *this, nPos++, *pTmp );
+
+ pTmp = new SwStartNode( *this, nPos++ );
+ pTmp->pStartOfSection = pSttNd;
+ pEndOfContent = new SwEndNode( *this, nPos++, *pTmp );
+
+ pOutlineNds = new SwOutlineNodes;
+}
+
+/*******************************************************************
+|*
+|* SwNodes::~SwNodes
+|*
+|* Beschreibung
+|* dtor, loescht alle Nodes, deren Pointer in diesem dynamischen
+|* Array sind. Ist kein Problem, da Nodes ausserhalb dieses
+|* Arrays nicht erzeugt werden koennen und somit auch nicht
+|* in mehreren drin sein koennen
+|*
+*******************************************************************/
+
+SwNodes::~SwNodes()
+{
+ delete pOutlineNds;
+
+ {
+ SwNode *pNode;
+ SwNodeIndex aNdIdx( *this );
+ while( sal_True )
+ {
+ pNode = &aNdIdx.GetNode();
+ if( pNode == pEndOfContent )
+ break;
+
+ aNdIdx++;
+ delete pNode;
+ }
+ }
+
+ // jetzt muessen alle SwNodeIndizies abgemeldet sein!!!
+ delete pEndOfContent;
+}
+
+void SwNodes::ChgNode( SwNodeIndex& rDelPos, sal_uLong nSz,
+ SwNodeIndex& rInsPos, sal_Bool bNewFrms )
+{
+ // im UndoBereich brauchen wir keine Frames
+ SwNodes& rNds = rInsPos.GetNodes();
+ const SwNode* pPrevInsNd = rNds[ rInsPos.GetIndex() -1 ];
+
+ //JP 03.02.99: alle Felder als invalide erklaeren, aktu. erfolgt im
+ // Idle-Handler des Docs
+ if( GetDoc()->SetFieldsDirty( sal_True, &rDelPos.GetNode(), nSz ) &&
+ rNds.GetDoc() != GetDoc() )
+ rNds.GetDoc()->SetFieldsDirty( true, NULL, 0 );
+
+ //JP 12.03.99: 63293 - Nodes vom RedlineBereich NIE aufnehmen
+ sal_uLong nNd = rInsPos.GetIndex();
+ sal_Bool bInsOutlineIdx = !(
+ rNds.GetEndOfRedlines().StartOfSectionNode()->GetIndex() < nNd &&
+ nNd < rNds.GetEndOfRedlines().GetIndex() );
+
+ if( &rNds == this ) // im gleichen Nodes-Array -> moven !!
+ {
+ // wird von vorne nach hinten gemovt, so wird nach vorne immer
+ // nachgeschoben, d.H. die Loeschposition ist immer gleich
+ sal_uInt16 nDiff = rDelPos.GetIndex() < rInsPos.GetIndex() ? 0 : 1;
+
+ for( sal_uLong n = rDelPos.GetIndex(); nSz; n += nDiff, --nSz )
+ {
+ SwNodeIndex aDelIdx( *this, n );
+ SwNode& rNd = aDelIdx.GetNode();
+
+ // #i57920# - correction of refactoring done by cws swnumtree:
+ // - <SwTxtNode::SetLevel( NO_NUMBERING ) is deprecated and
+ // set <IsCounted> state of the text node to <false>, which
+ // isn't correct here.
+ if ( rNd.IsTxtNode() )
+ {
+ SwTxtNode* pTxtNode = rNd.GetTxtNode();
+
+ pTxtNode->RemoveFromList();
+
+ if ( pTxtNode->GetAttrOutlineLevel() != 0 )//<-end,zhaojianwei
+ {
+ const SwNodePtr pSrch = (SwNodePtr)&rNd;
+ pOutlineNds->Remove( pSrch );
+ }
+ }
+ // <--
+
+ BigPtrArray::Move( aDelIdx.GetIndex(), rInsPos.GetIndex() );
+
+ if( rNd.IsTxtNode() )
+ {
+ SwTxtNode& rTxtNd = (SwTxtNode&)rNd;
+
+ rTxtNd.AddToList();
+
+ if( bInsOutlineIdx &&
+ 0 != rTxtNd.GetAttrOutlineLevel() )//<-end,zhaojianwei
+ {
+ const SwNodePtr pSrch = (SwNodePtr)&rNd;
+ pOutlineNds->Insert( pSrch );
+ }
+ rTxtNd.InvalidateNumRule();
+
+//FEATURE::CONDCOLL
+ if( RES_CONDTXTFMTCOLL == rTxtNd.GetTxtColl()->Which() )
+ rTxtNd.ChkCondColl();
+//FEATURE::CONDCOLL
+ }
+ else if( rNd.IsCntntNode() )
+ ((SwCntntNode&)rNd).InvalidateNumRule();
+ }
+ }
+ else
+ {
+ bool bSavePersData(GetDoc()->GetIDocumentUndoRedo().IsUndoNodes(rNds));
+ bool bRestPersData(GetDoc()->GetIDocumentUndoRedo().IsUndoNodes(*this));
+ SwDoc* pDestDoc = rNds.GetDoc() != GetDoc() ? rNds.GetDoc() : 0;
+ OSL_ENSURE(!pDestDoc, "SwNodes::ChgNode(): "
+ "the code to handle text fields here looks broken\n"
+ "if the target is in a different document.");
+ if( !bRestPersData && !bSavePersData && pDestDoc )
+ bSavePersData = bRestPersData = sal_True;
+
+ String sNumRule;
+ SwNodeIndex aInsPos( rInsPos );
+ for( sal_uLong n = 0; n < nSz; n++ )
+ {
+ SwNode* pNd = &rDelPos.GetNode();
+
+ // NoTextNode muessen ihre Persitenten Daten mitnehmen
+ if( pNd->IsNoTxtNode() )
+ {
+ if( bSavePersData )
+ ((SwNoTxtNode*)pNd)->SavePersistentData();
+ }
+ else if( pNd->IsTxtNode() )
+ {
+ SwTxtNode* pTxtNd = (SwTxtNode*)pNd;
+
+ // loesche die Gliederungs-Indizies aus dem alten Nodes-Array
+ if( 0 != pTxtNd->GetAttrOutlineLevel() )//<-end,zhaojianwei
+ pOutlineNds->Remove( pNd );
+
+ // muss die Rule kopiere werden?
+ if( pDestDoc )
+ {
+ const SwNumRule* pNumRule = pTxtNd->GetNumRule();
+ if( pNumRule && sNumRule != pNumRule->GetName() )
+ {
+ sNumRule = pNumRule->GetName();
+ SwNumRule* pDestRule = pDestDoc->FindNumRulePtr( sNumRule );
+ if( pDestRule )
+ pDestRule->SetInvalidRule( sal_True );
+ else
+ pDestDoc->MakeNumRule( sNumRule, pNumRule );
+ }
+ }
+ else
+ // wenns ins UndoNodes-Array gemoved wird, sollten die
+ // Numerierungen auch aktualisiert werden.
+ pTxtNd->InvalidateNumRule();
+
+ pTxtNd->RemoveFromList();
+ }
+
+ RemoveNode( rDelPos.GetIndex(), 1, sal_False ); // Indizies verschieben !!
+ SwCntntNode * pCNd = pNd->GetCntntNode();
+ rNds.InsertNode( pNd, aInsPos );
+
+ if( pCNd )
+ {
+ SwTxtNode* pTxtNd = pCNd->GetTxtNode();
+ if( pTxtNd )
+ {
+ SwpHints * const pHts = pTxtNd->GetpSwpHints();
+ // OultineNodes set the new nodes in the array
+ if( bInsOutlineIdx &&
+ 0 != pTxtNd->GetAttrOutlineLevel() ) //#outline level,added by zhaojianwei
+ {
+ rNds.pOutlineNds->Insert( pTxtNd );
+ }
+
+ pTxtNd->AddToList();
+
+ // Sonderbehandlung fuer die Felder!
+ if( pHts && pHts->Count() )
+ {
+ // this looks fishy if pDestDoc != 0
+ bool const bToUndo = !pDestDoc &&
+ GetDoc()->GetIDocumentUndoRedo().IsUndoNodes(rNds);
+ for( sal_uInt16 i = pHts->Count(); i; )
+ {
+ sal_uInt16 nDelMsg = 0;
+ SwTxtAttr * const pAttr = pHts->GetTextHint( --i );
+ switch ( pAttr->Which() )
+ {
+ case RES_TXTATR_FIELD:
+ {
+ SwTxtFld* pTxtFld =
+ static_cast<SwTxtFld*>(pAttr);
+ rNds.GetDoc()->InsDelFldInFldLst( !bToUndo, *pTxtFld );
+
+ const SwFieldType* pTyp = pTxtFld->GetFld().GetFld()->GetTyp();
+ if ( RES_POSTITFLD == pTyp->Which() )
+ {
+ rNds.GetDoc()->GetDocShell()->Broadcast( SwFmtFldHint( &pTxtFld->GetFld(), pTxtFld->GetFld().IsFldInDoc() ? SWFMTFLD_INSERTED : SWFMTFLD_REMOVED ) );
+ }
+ else
+ if( RES_DDEFLD == pTyp->Which() )
+ {
+ if( bToUndo )
+ ((SwDDEFieldType*)pTyp)->DecRefCnt();
+ else
+ ((SwDDEFieldType*)pTyp)->IncRefCnt();
+ }
+ nDelMsg = RES_FIELD_DELETED;
+ }
+ break;
+ case RES_TXTATR_FTN:
+ nDelMsg = RES_FOOTNOTE_DELETED;
+ break;
+
+ case RES_TXTATR_TOXMARK:
+ static_cast<SwTOXMark&>(pAttr->GetAttr())
+ .InvalidateTOXMark();
+ break;
+
+ case RES_TXTATR_REFMARK:
+ nDelMsg = RES_REFMARK_DELETED;
+ break;
+
+ case RES_TXTATR_META:
+ case RES_TXTATR_METAFIELD:
+ {
+ SwTxtMeta *const pTxtMeta(
+ static_cast<SwTxtMeta*>(pAttr));
+ // force removal of UNO object
+ pTxtMeta->ChgTxtNode(0);
+ pTxtMeta->ChgTxtNode(pTxtNd);
+ }
+ break;
+
+ default:
+ break;
+ }
+ if( nDelMsg && bToUndo )
+ {
+ SwPtrMsgPoolItem aMsgHint( nDelMsg,
+ (void*)&pAttr->GetAttr() );
+ rNds.GetDoc()->GetUnoCallBack()->
+ ModifyNotification( &aMsgHint, &aMsgHint );
+ }
+ }
+ }
+//FEATURE::CONDCOLL
+ if( RES_CONDTXTFMTCOLL == pTxtNd->GetTxtColl()->Which() )
+ pTxtNd->ChkCondColl();
+//FEATURE::CONDCOLL
+ }
+ else
+ {
+ // in unterschiedliche Docs gemoved ?
+ // dann die Daten wieder persistent machen
+ if( pCNd->IsNoTxtNode() && bRestPersData )
+ ((SwNoTxtNode*)pCNd)->RestorePersistentData();
+ }
+ }
+ }
+ }
+
+ //JP 03.02.99: alle Felder als invalide erklaeren, aktu. erfolgt im
+ // Idle-Handler des Docs
+ GetDoc()->SetFieldsDirty( true, NULL, 0 );
+ if( rNds.GetDoc() != GetDoc() )
+ rNds.GetDoc()->SetFieldsDirty( true, NULL, 0 );
+
+
+ if( bNewFrms )
+ bNewFrms = &GetDoc()->GetNodes() == (const SwNodes*)&rNds &&
+ GetDoc()->GetCurrentViewShell(); //swmod 071108//swmod 071225
+ if( bNewFrms )
+ {
+ // Frames besorgen:
+ SwNodeIndex aIdx( *pPrevInsNd, 1 );
+ SwNodeIndex aFrmNdIdx( aIdx );
+ SwNode* pFrmNd = rNds.FindPrvNxtFrmNode( aFrmNdIdx,
+ rNds[ rInsPos.GetIndex() - 1 ] );
+
+ if( !pFrmNd && aFrmNdIdx > rNds.GetEndOfExtras().GetIndex() )
+ {
+ OSL_ENSURE( !this, "ob das so richtig ist ??" );
+ aFrmNdIdx = rNds.GetEndOfContent();
+ pFrmNd = rNds.GoPrevSection( &aFrmNdIdx, sal_True, sal_False );
+ if( pFrmNd && !((SwCntntNode*)pFrmNd)->GetDepends() )
+ pFrmNd = 0;
+
+#if OSL_DEBUG_LEVEL > 1
+ if( !pFrmNd )
+ OSL_ENSURE( !this, "ChgNode() - kein FrameNode gefunden" );
+#endif
+ }
+ if( pFrmNd )
+ while( aIdx != rInsPos )
+ {
+ SwCntntNode* pCNd = aIdx.GetNode().GetCntntNode();
+ if( pCNd )
+ {
+ if( pFrmNd->IsTableNode() )
+ ((SwTableNode*)pFrmNd)->MakeFrms( aIdx );
+ else if( pFrmNd->IsSectionNode() )
+ ((SwSectionNode*)pFrmNd)->MakeFrms( aIdx );
+ else
+ ((SwCntntNode*)pFrmNd)->MakeFrms( *pCNd );
+ pFrmNd = pCNd;
+ }
+ aIdx++;
+ }
+ }
+}
+
+
+/***********************************************************************
+|*
+|* SwNodes::Move
+|*
+|* Beschreibung
+|* Move loescht die Node-Pointer ab und einschliesslich der Startposition
+|* bis zu und ausschliesslich der Endposition und fuegt sie an
+|* der vor der Zielposition ein.
+|* Wenn das Ziel vor dem ersten oder dem letzten zu bewegenden Element oder
+|* dazwischen liegt, geschieht nichts.
+|* Wenn der zu bewegende Bereich leer ist oder das Ende vor
+|* dem Anfang liegt, geschieht nichts.
+|*
+|* Allg.: aRange beschreibt den Bereich -exklusive- aEnd !!
+|* ( 1.Node: aStart, letzer Node: aEnd-1 !! )
+|*
+***********************************************************************/
+
+sal_Bool SwNodes::_MoveNodes( const SwNodeRange& aRange, SwNodes & rNodes,
+ const SwNodeIndex& aIndex, sal_Bool bNewFrms )
+{
+ SwNode * pAktNode;
+ if( aIndex == 0 ||
+ ( (pAktNode = &aIndex.GetNode())->GetStartNode() &&
+ !pAktNode->StartOfSectionIndex() ))
+ return sal_False;
+
+ SwNodeRange aRg( aRange );
+
+ // "einfache" StartNodes oder EndNodes ueberspringen
+ while( ND_STARTNODE == (pAktNode = &aRg.aStart.GetNode())->GetNodeType()
+ || ( pAktNode->IsEndNode() &&
+ !pAktNode->pStartOfSection->IsSectionNode() ) )
+ aRg.aStart++;
+ aRg.aStart--;
+
+ // falls aEnd-1 auf keinem ContentNode steht, dann suche den vorherigen
+ aRg.aEnd--;
+ while( ( (( pAktNode = &aRg.aEnd.GetNode())->GetStartNode() &&
+ !pAktNode->IsSectionNode() ) ||
+ ( pAktNode->IsEndNode() &&
+ ND_STARTNODE == pAktNode->pStartOfSection->GetNodeType()) ) &&
+ aRg.aEnd > aRg.aStart )
+ aRg.aEnd--;
+
+
+ // wird im selben Array's verschoben, dann ueberpruefe die Einfuegepos.
+ if( aRg.aStart >= aRg.aEnd )
+ return sal_False;
+
+ if( this == &rNodes )
+ {
+ if( ( aIndex.GetIndex()-1 >= aRg.aStart.GetIndex() &&
+ aIndex.GetIndex()-1 < aRg.aEnd.GetIndex()) ||
+ ( aIndex.GetIndex()-1 == aRg.aEnd.GetIndex() ) )
+ return sal_False;
+ }
+
+ sal_uInt16 nLevel = 0; // Level-Counter
+ sal_uLong nInsPos = 0; // Cnt fuer das TmpArray
+
+ // das Array bildet einen Stack, es werden alle StartOfSelction's gesichert
+ SwSttNdPtrs aSttNdStack( 1, 5 );
+
+ // setze den Start-Index
+ SwNodeIndex aIdx( aIndex );
+
+ SwStartNode* pStartNode = aIdx.GetNode().pStartOfSection;
+ aSttNdStack.C40_INSERT( SwStartNode, pStartNode, 0 );
+
+ SwNodeRange aOrigInsPos( aIdx, -1, aIdx ); // Originale Insert Pos
+
+ //JP 16.01.98: SectionNodes: DelFrms/MakeFrms beim obersten SectionNode!
+ sal_uInt16 nSectNdCnt = 0;
+ sal_Bool bSaveNewFrms = bNewFrms;
+
+ // bis alles verschoben ist
+ while( aRg.aStart < aRg.aEnd )
+ switch( (pAktNode = &aRg.aEnd.GetNode())->GetNodeType() )
+ {
+ case ND_ENDNODE:
+ {
+ if( nInsPos ) // verschieb schon mal alle bis hier her
+ {
+ // loeschen und kopieren. ACHTUNG: die Indizies ab
+ // "aRg.aEnd+1" werden mit verschoben !!
+ SwNodeIndex aSwIndex( aRg.aEnd, 1 );
+ ChgNode( aSwIndex, nInsPos, aIdx, bNewFrms );
+ aIdx -= nInsPos;
+ nInsPos = 0;
+ }
+
+ SwStartNode* pSttNd = pAktNode->pStartOfSection;
+ if( pSttNd->IsTableNode() )
+ {
+ SwTableNode* pTblNd = (SwTableNode*)pSttNd;
+
+ // dann bewege die gesamte Tabelle/den Bereich !!
+ nInsPos = (aRg.aEnd.GetIndex() -
+ pSttNd->GetIndex() )+1;
+ aRg.aEnd -= nInsPos;
+
+ //JP 12.03.99: 63293 - Nodes vom RedlineBereich NIE aufnehmen
+ sal_uLong nNd = aIdx.GetIndex();
+ sal_Bool bInsOutlineIdx = !( rNodes.GetEndOfRedlines().
+ StartOfSectionNode()->GetIndex() < nNd &&
+ nNd < rNodes.GetEndOfRedlines().GetIndex() );
+
+ if( bNewFrms )
+ // loesche erstmal die Frames
+ pTblNd->DelFrms();
+ if( &rNodes == this ) // in sich selbst moven ??
+ {
+ // dann bewege alle Start/End/ContentNodes. Loesche
+ // bei den ContentNodes auch die Frames !!
+ pTblNd->pStartOfSection = aIdx.GetNode().pStartOfSection;
+ for( sal_uLong n = 0; n < nInsPos; ++n )
+ {
+ SwNodeIndex aMvIdx( aRg.aEnd, 1 );
+ SwCntntNode* pCNd = 0;
+ SwNode* pTmpNd = &aMvIdx.GetNode();
+ if( pTmpNd->IsCntntNode() )
+ {
+ pCNd = (SwCntntNode*)pTmpNd;
+ if( pTmpNd->IsTxtNode() )
+ ((SwTxtNode*)pTmpNd)->RemoveFromList();
+
+ // setze bei Start/EndNodes die richtigen Indizies
+ // loesche die Gliederungs-Indizies aus
+ // dem alten Nodes-Array
+ if( pCNd->IsTxtNode() && 0 !=
+ ((SwTxtNode*)pCNd)->GetAttrOutlineLevel() )//<-end,by zhaojianwei
+ pOutlineNds->Remove( pCNd );
+ else
+ pCNd = 0;
+ }
+
+ BigPtrArray::Move( aMvIdx.GetIndex(), aIdx.GetIndex() );
+
+ if( bInsOutlineIdx && pCNd )
+ pOutlineNds->Insert( pCNd );
+ if( pTmpNd->IsTxtNode() )
+ ((SwTxtNode*)pTmpNd)->AddToList();
+ }
+ }
+ else
+ {
+ // StartNode holen
+ // Even aIdx points to a startnode, we need the startnode
+ // of the environment of aIdx (#i80941)
+ SwStartNode* pSttNode = aIdx.GetNode().pStartOfSection;
+
+ // Hole alle Boxen mit Inhalt. Deren Indizies auf die
+ // StartNodes muessen umgemeldet werden !!
+ // (Array kopieren und alle gefunden wieder loeschen;
+ // erleichtert das suchen!!)
+ SwNodeIndex aMvIdx( aRg.aEnd, 1 );
+ for( sal_uLong n = 0; n < nInsPos; ++n )
+ {
+ SwNode* pNd = &aMvIdx.GetNode();
+
+ const bool bOutlNd = pNd->IsTxtNode() &&
+ 0 != ((SwTxtNode*)pNd)->GetAttrOutlineLevel();//<-end,zhaojianwei
+ // loesche die Gliederungs-Indizies aus
+ // dem alten Nodes-Array
+ if( bOutlNd )
+ pOutlineNds->Remove( pNd );
+
+ RemoveNode( aMvIdx.GetIndex(), 1, sal_False );
+ pNd->pStartOfSection = pSttNode;
+ rNodes.InsertNode( pNd, aIdx );
+
+ // setze bei Start/EndNodes die richtigen Indizies
+ if( bInsOutlineIdx && bOutlNd )
+ // und setze sie im neuen Nodes-Array
+ rNodes.pOutlineNds->Insert( pNd );
+ else if( pNd->IsStartNode() )
+ pSttNode = (SwStartNode*)pNd;
+ else if( pNd->IsEndNode() )
+ {
+ pSttNode->pEndOfSection = (SwEndNode*)pNd;
+ if( pSttNode->IsSectionNode() )
+ ((SwSectionNode*)pSttNode)->NodesArrChgd();
+ pSttNode = pSttNode->pStartOfSection;
+ }
+ }
+
+ if( pTblNd->GetTable().IsA( TYPE( SwDDETable ) ))
+ {
+ SwDDEFieldType* pTyp = ((SwDDETable&)pTblNd->
+ GetTable()).GetDDEFldType();
+ if( pTyp )
+ {
+ if( rNodes.IsDocNodes() )
+ pTyp->IncRefCnt();
+ else
+ pTyp->DecRefCnt();
+ }
+ }
+
+ if (GetDoc()->GetIDocumentUndoRedo().IsUndoNodes(
+ rNodes))
+ {
+ SwFrmFmt* pTblFmt = pTblNd->GetTable().GetFrmFmt();
+ SwPtrMsgPoolItem aMsgHint( RES_REMOVE_UNO_OBJECT,
+ pTblFmt );
+ pTblFmt->ModifyNotification( &aMsgHint, &aMsgHint );
+ }
+ }
+ if( bNewFrms )
+ {
+ SwNodeIndex aTmp( aIdx );
+ pTblNd->MakeFrms( &aTmp );
+ }
+ aIdx -= nInsPos;
+ nInsPos = 0;
+ }
+ else if( pSttNd->GetIndex() < aRg.aStart.GetIndex() )
+ {
+ // SectionNode: es wird nicht die gesamte Section
+ // verschoben, also bewege nur die
+ // ContentNodes
+ // StartNode: erzeuge an der Postion eine neue Section
+ do { // middle check loop
+ if( !pSttNd->IsSectionNode() )
+ {
+ // Start und EndNode an der InsertPos erzeugen
+ SwStartNode* pTmp = new SwStartNode( aIdx,
+ ND_STARTNODE,
+/*?? welcher NodeTyp ??*/
+ SwNormalStartNode );
+
+ nLevel++; // den Index auf StartNode auf den Stack
+ aSttNdStack.C40_INSERT( SwStartNode, pTmp, nLevel );
+
+ // noch den EndNode erzeugen
+ new SwEndNode( aIdx, *pTmp );
+ }
+ else if (GetDoc()->GetIDocumentUndoRedo().IsUndoNodes(
+ rNodes))
+ {
+ // im UndoNodes-Array spendieren wir einen
+ // Platzhalter
+ new SwNode( aIdx, ND_SECTIONDUMMY );
+ }
+ else
+ {
+ // JP 18.5.2001: neue Section anlegen?? Bug 70454
+ aRg.aEnd--;
+ break;
+
+ }
+
+ aRg.aEnd--;
+ aIdx--;
+ } while( sal_False );
+ }
+ else
+ {
+ // Start und EndNode komplett verschieben
+// s. u. SwIndex aOldStt( pSttNd->theIndex );
+//JP 21.05.97: sollte der Start genau der Start des Bereiches sein, so muss
+// der Node auf jedenfall noch besucht werden!
+ if( &aRg.aStart.GetNode() == pSttNd )
+ --aRg.aStart;
+
+ SwSectionNode* pSctNd = pSttNd->GetSectionNode();
+ if( bNewFrms && pSctNd )
+ pSctNd->DelFrms();
+
+ RemoveNode( aRg.aEnd.GetIndex(), 1, sal_False ); // EndNode loeschen
+ sal_uLong nSttPos = pSttNd->GetIndex();
+
+ // dieser StartNode wird spaeter wieder entfernt!
+ SwStartNode* pTmpSttNd = new SwStartNode( *this, nSttPos+1 );
+ pTmpSttNd->pStartOfSection = pSttNd->pStartOfSection;
+
+ RemoveNode( nSttPos, 1, sal_False ); // SttNode loeschen
+
+ pSttNd->pStartOfSection = aIdx.GetNode().pStartOfSection;
+ rNodes.InsertNode( pSttNd, aIdx );
+ rNodes.InsertNode( pAktNode, aIdx );
+ aIdx--;
+ pSttNd->pEndOfSection = (SwEndNode*)pAktNode;
+
+ aRg.aEnd--;
+
+ nLevel++; // den Index auf StartNode auf den Stack
+ aSttNdStack.C40_INSERT( SwStartNode, pSttNd, nLevel );
+
+ // SectionNode muss noch ein paar Indizies ummelden
+ if( pSctNd )
+ {
+ pSctNd->NodesArrChgd();
+ ++nSectNdCnt;
+ bNewFrms = sal_False;
+ }
+ }
+ }
+ break;
+
+
+
+ case ND_SECTIONNODE:
+ if( !nLevel &&
+ GetDoc()->GetIDocumentUndoRedo().IsUndoNodes(rNodes))
+ {
+ // dann muss an der akt. InsPos ein SectionDummyNode
+ // eingefuegt werden
+ if( nInsPos ) // verschieb schon mal alle bis hier her
+ {
+ // loeschen und kopieren. ACHTUNG: die Indizies ab
+ // "aRg.aEnd+1" werden mit verschoben !!
+ SwNodeIndex aSwIndex( aRg.aEnd, 1 );
+ ChgNode( aSwIndex, nInsPos, aIdx, bNewFrms );
+ aIdx -= nInsPos;
+ nInsPos = 0;
+ }
+ new SwNode( aIdx, ND_SECTIONDUMMY );
+ aRg.aEnd--;
+ aIdx--;
+ break;
+ }
+ // kein break !!
+ case ND_TABLENODE:
+ case ND_STARTNODE:
+ {
+ // empty section -> nothing to do
+ // and only if it's a top level section
+ if( !nInsPos && !nLevel )
+ {
+ aRg.aEnd--;
+ break;
+ }
+
+ if( !nLevel ) // es wird eine Stufe runter gestuft
+ {
+ // erzeuge die Runterstufung
+ SwNodeIndex aTmpSIdx( aOrigInsPos.aStart, 1 );
+ SwStartNode* pTmpStt = new SwStartNode( aTmpSIdx,
+ ND_STARTNODE,
+ ((SwStartNode*)pAktNode)->GetStartNodeType() );
+
+ aTmpSIdx--;
+
+ SwNodeIndex aTmpEIdx( aOrigInsPos.aEnd );
+ new SwEndNode( aTmpEIdx, *pTmpStt );
+ aTmpEIdx--;
+ aTmpSIdx++;
+
+ // setze die StartOfSection richtig
+ aRg.aEnd++;
+ {
+ SwNodeIndex aCntIdx( aRg.aEnd );
+ for( sal_uLong n = 0; n < nInsPos; n++, aCntIdx++)
+ aCntIdx.GetNode().pStartOfSection = pTmpStt;
+ }
+
+ // Setze auch bei allen runtergestuften den richtigen StartNode
+ while( aTmpSIdx < aTmpEIdx )
+ if( 0 != (( pAktNode = &aTmpEIdx.GetNode())->GetEndNode()) )
+ aTmpEIdx = pAktNode->StartOfSectionIndex();
+ else
+ {
+ pAktNode->pStartOfSection = pTmpStt;
+ aTmpEIdx--;
+ }
+
+ aIdx--; // hinter den eingefuegten StartNode
+ aRg.aEnd--; // vor den StartNode
+ // kopiere jetzt das Array. ACHTUNG: die Indizies ab
+ // "aRg.aEnd+1" werden mit verschoben !!
+ SwNodeIndex aSwIndex( aRg.aEnd, 1 );
+ ChgNode( aSwIndex, nInsPos, aIdx, bNewFrms );
+ aIdx -= nInsPos+1;
+ nInsPos = 0;
+ }
+ else // es wurden alle Nodes innerhalb eines
+ { // Start- und End-Nodes verschoben
+ OSL_ENSURE( pAktNode == aSttNdStack[nLevel] ||
+ ( pAktNode->IsStartNode() &&
+ aSttNdStack[nLevel]->IsSectionNode()),
+ "falscher StartNode" );
+
+ SwNodeIndex aSwIndex( aRg.aEnd, 1 );
+ ChgNode( aSwIndex, nInsPos, aIdx, bNewFrms );
+ aIdx -= nInsPos+1; // vor den eingefuegten StartNode
+ nInsPos = 0;
+
+ // loesche nur noch den Pointer aus dem Nodes-Array.
+ RemoveNode( aRg.aEnd.GetIndex(), 1, sal_True );
+ aRg.aEnd--;
+
+ SwSectionNode* pSectNd = aSttNdStack[ nLevel ]->GetSectionNode();
+ if( pSectNd && !--nSectNdCnt )
+ {
+ SwNodeIndex aTmp( *pSectNd );
+ pSectNd->MakeFrms( &aTmp );
+ bNewFrms = bSaveNewFrms;
+ }
+ aSttNdStack.Remove( nLevel ); // vom Stack loeschen
+ nLevel--;
+ }
+
+ // loesche alle entstehenden leeren Start-/End-Node-Paare
+ SwNode* pTmpNode = (*this)[ aRg.aEnd.GetIndex()+1 ]->GetEndNode();
+ if( pTmpNode && ND_STARTNODE == (pAktNode = &aRg.aEnd.GetNode())
+ ->GetNodeType() && pAktNode->StartOfSectionIndex() &&
+ pTmpNode->StartOfSectionNode() == pAktNode )
+ {
+ DelNodes( aRg.aEnd, 2 );
+ aRg.aEnd--;
+ }
+ }
+ break;
+
+ case ND_TEXTNODE:
+ case ND_GRFNODE:
+ case ND_OLENODE:
+ {
+ if( bNewFrms && pAktNode->GetCntntNode() )
+ ((SwCntntNode*)pAktNode)->DelFrms();
+
+ pAktNode->pStartOfSection = aSttNdStack[ nLevel ];
+ nInsPos++;
+ aRg.aEnd--;
+ }
+ break;
+
+ case ND_SECTIONDUMMY:
+ if (GetDoc()->GetIDocumentUndoRedo().IsUndoNodes(*this))
+ {
+ if( &rNodes == this ) // innerhalb vom UndoNodesArray
+ {
+ // mit verschieben
+ pAktNode->pStartOfSection = aSttNdStack[ nLevel ];
+ nInsPos++;
+ }
+ else // in ein "normales" Nodes-Array verschieben
+ {
+ // dann muss an der akt. InsPos auch ein SectionNode
+ // (Start/Ende) stehen; dann diesen ueberspringen.
+ // Andernfalls nicht weiter beachten.
+ if( nInsPos ) // verschieb schon mal alle bis hier her
+ {
+ // loeschen und kopieren. ACHTUNG: die Indizies ab
+ // "aRg.aEnd+1" werden mit verschoben !!
+ SwNodeIndex aSwIndex( aRg.aEnd, 1 );
+ ChgNode( aSwIndex, nInsPos, aIdx, bNewFrms );
+ aIdx -= nInsPos;
+ nInsPos = 0;
+ }
+ SwNode* pTmpNd = &aIdx.GetNode();
+ if( pTmpNd->IsSectionNode() ||
+ pTmpNd->StartOfSectionNode()->IsSectionNode() )
+ aIdx--; // ueberspringen
+ }
+ }
+ else {
+ OSL_FAIL( "wie kommt diser Node ins Nodes-Array??" );
+ }
+ aRg.aEnd--;
+ break;
+
+ default:
+ OSL_FAIL( "was ist das fuer ein Node??" );
+ break;
+ }
+
+ if( nInsPos ) // kopiere den Rest
+ {
+ // der Rest muesste so stimmen
+ SwNodeIndex aSwIndex( aRg.aEnd, 1 );
+ ChgNode( aSwIndex, nInsPos, aIdx, bNewFrms );
+ }
+ aRg.aEnd++; // wieder exklusive Ende
+
+ // loesche alle leeren Start-/End-Node-Paare
+ if( ( pAktNode = &aRg.aStart.GetNode())->GetStartNode() &&
+ pAktNode->StartOfSectionIndex() &&
+ aRg.aEnd.GetNode().GetEndNode() )
+ DelNodes( aRg.aStart, 2 );
+
+ // rufe jetzt noch das Update fuer die Gliederung/Nummerierung auf
+ aOrigInsPos.aStart++;
+ // im gleichen Nodes-Array verschoben ??,
+ // dann von oben nach unten das Update aufrufen !!
+ if( this == &rNodes &&
+ aRg.aEnd.GetIndex() >= aOrigInsPos.aStart.GetIndex() )
+ {
+ UpdtOutlineIdx( aOrigInsPos.aStart.GetNode() );
+ UpdtOutlineIdx( aRg.aEnd.GetNode() );
+ }
+ else
+ {
+ UpdtOutlineIdx( aRg.aEnd.GetNode() );
+ rNodes.UpdtOutlineIdx( aOrigInsPos.aStart.GetNode() );
+ }
+
+ return sal_True;
+}
+
+
+/*******************************************************************
+|*
+|* SwNodes::SectionDown
+|*
+|* Beschreibung
+|* SectionDown() legt ein Paar von Start- und EndSection-Node
+|* (andere Nodes koennen dazwischen liegen) an.
+|*
+|* Zustand des SRange beim Verlassen der Funktion: nStart ist der
+|* Index des ersten Node hinter dem Start Section Node, nEnd ist
+|* der Index des End Section Nodes. Beispiel: Wird Insert Section
+|* mehrmals hintereinander aufgerufen, so werden mehrere
+|* unmittelbar geschachtelte Sections (keine Content Nodes
+|* zwischen Start- bzw. End Nodes) angelegt.
+|*
+|* Allg.: aRange beschreibt den Bereich -exklusive- aEnd !!
+|* ( 1.Node: aStart, letzer Node: aEnd-1 !! )
+|*
+|* Parameter
+|* SwRange &rRange
+|* IO:
+|* IN
+|* rRange.aStart: Einfuegeposition des StartNodes
+|* rRange.aEnd: Einfuegeposition des EndNodes
+|* OUT
+|* rRange.aStart: steht hinter dem eingefuegten Startnode
+|* rRange.aEnd: steht auf dem eingefuegen Endnode
+|*
+|* Ausnahmen
+|* 1. SRange-Anfang und SRange-Ende muessen auf dem gleichen Level sein
+|* 2. duerfen nicht auf dem obersten Level sein
+|* Ist dies nicht der Fall, wird die
+|* Funktion durch Aufruf von ERR_RAISE verlassen.
+|*
+|* Debug-Funktionen
+|* die Debugging Tools geben rRange beim Eintritt und beim
+|* Verlassen der Funktion aus
+|*
+*******************************************************************/
+void SwNodes::SectionDown(SwNodeRange *pRange, SwStartNodeType eSttNdTyp )
+{
+ if( pRange->aStart >= pRange->aEnd ||
+ pRange->aEnd >= Count() ||
+ !CheckNodesRange( pRange->aStart, pRange->aEnd ))
+ return;
+
+ // Ist der Anfang vom Bereich vor oder auf einem EndNode, so loesche
+ // diesen, denn sonst wuerden leere S/E-Nodes oder E/S-Nodes enstehen.
+ // Bei anderen Nodes wird eine neuer StartNode eingefuegt
+ SwNode * pAktNode = &pRange->aStart.GetNode();
+ SwNodeIndex aTmpIdx( *pAktNode->StartOfSectionNode() );
+
+ if( pAktNode->GetEndNode() )
+ DelNodes( pRange->aStart, 1 ); // verhinder leere Section
+ else
+ {
+ // fuege einen neuen StartNode ein
+ SwNode* pSttNd = new SwStartNode( pRange->aStart, ND_STARTNODE, eSttNdTyp );
+ pRange->aStart = *pSttNd;
+ aTmpIdx = pRange->aStart;
+ }
+
+ // Ist das Ende vom Bereich vor oder auf einem StartNode, so loesche
+ // diesen, denn sonst wuerden leere S/E-Nodes oder E/S-Nodes enstehen
+ // Bei anderen Nodes wird eine neuer EndNode eingefuegt
+ pRange->aEnd--;
+ if( pRange->aEnd.GetNode().GetStartNode() )
+ DelNodes( pRange->aEnd, 1 );
+ else
+ {
+ pRange->aEnd++;
+ // fuege einen neuen EndNode ein
+ new SwEndNode( pRange->aEnd, *pRange->aStart.GetNode().GetStartNode() );
+ }
+ pRange->aEnd--;
+
+ SectionUpDown( aTmpIdx, pRange->aEnd );
+}
+
+/*******************************************************************
+|*
+|* SwNodes::SectionUp
+|*
+|* Beschreibung
+|* Der von rRange umspannte Bereich wird auf die naechst hoehere
+|* Ebene gehoben. Das geschieht dadurch, dass bei
+|* rRange.aStart ein Endnode und bei rRange.aEnd ein
+|* Startnode eingefuegt wird. Die Indices fuer den Bereich
+|* innerhalb von rRange werden geupdated.
+|*
+|* Allg.: aRange beschreibt den Bereich -exklusive- aEnd !!
+|* ( 1.Node: aStart, letzer Node: aEnd-1 !! )
+|*
+|* Parameter
+|* SwRange &rRange
+|* IO:
+|* IN
+|* rRange.aStart: Anfang des hoeher zubewegenden Bereiches
+|* rRange.aEnd: der 1.Node hinter dem Bereich
+|* OUT
+|* rRange.aStart: an der ersten Position innerhalb des
+|* hochbewegten Bereiches
+|* rRange.aEnd: an der letzten Position innerhalb des
+|* hochbewegten Bereiches
+|*
+|* Debug-Funktionen
+|* die Debugging Tools geben rRange beim Eintritt und beim
+|* Verlassen der Funktion aus
+|*
+*******************************************************************/
+void SwNodes::SectionUp(SwNodeRange *pRange)
+{
+ if( pRange->aStart >= pRange->aEnd ||
+ pRange->aEnd >= Count() ||
+ !CheckNodesRange( pRange->aStart, pRange->aEnd ) ||
+ !( HighestLevel( *this, *pRange ) > 1 ))
+ return;
+
+ // Ist der Anfang vom Bereich vor oder auf einem StartNode, so loesche
+ // diesen, denn sonst wuerden leere S/E-Nodes oder E/S-Nodes enstehen.
+ // Bei anderen Nodes wird eine neuer EndNode eingefuegt
+ SwNode * pAktNode = &pRange->aStart.GetNode();
+ SwNodeIndex aIdx( *pAktNode->StartOfSectionNode() );
+ if( pAktNode->IsStartNode() ) // selbst StartNode
+ {
+ SwEndNode* pEndNd = pRange->aEnd.GetNode().GetEndNode();
+ if( pAktNode == pEndNd->pStartOfSection )
+ {
+ // dann wurde paarig aufgehoben, also nur die im Berich neu anpassen
+ SwStartNode* pTmpSttNd = pAktNode->pStartOfSection;
+ RemoveNode( pRange->aStart.GetIndex(), 1, sal_True );
+ RemoveNode( pRange->aEnd.GetIndex(), 1, sal_True );
+
+ SwNodeIndex aTmpIdx( pRange->aStart );
+ while( aTmpIdx < pRange->aEnd )
+ {
+ pAktNode = &aTmpIdx.GetNode();
+ pAktNode->pStartOfSection = pTmpSttNd;
+ if( pAktNode->IsStartNode() )
+ aTmpIdx = pAktNode->EndOfSectionIndex() + 1;
+ else
+ aTmpIdx++;
+ }
+ return ;
+ }
+ DelNodes( pRange->aStart, 1 );
+ }
+ else if( aIdx == pRange->aStart.GetIndex()-1 ) // vor StartNode
+ DelNodes( aIdx, 1 );
+ else
+ new SwEndNode( pRange->aStart, *aIdx.GetNode().GetStartNode() );
+
+ // Ist das Ende vom Bereich vor oder auf einem StartNode, so loesche
+ // diesen, denn sonst wuerden leere S/E-Nodes oder E/S-Nodes entstehen
+ // Bei anderen Nodes wird eine neuer EndNode eingefuegt
+ SwNodeIndex aTmpIdx( pRange->aEnd );
+ if( pRange->aEnd.GetNode().IsEndNode() )
+ DelNodes( pRange->aEnd, 1 );
+ else
+ {
+ pAktNode = new SwStartNode( pRange->aEnd );
+/*?? welcher NodeTyp ??*/
+ aTmpIdx = *pRange->aEnd.GetNode().EndOfSectionNode();
+ pRange->aEnd--;
+ }
+
+ SectionUpDown( aIdx, aTmpIdx );
+}
+
+
+/*************************************************************************
+|*
+|* SwNodes::SectionUpDown()
+|*
+|* Beschreibung
+|* Methode setzt die Indizies die bei SectionUp oder SectionDwon
+|* veraendert wurden wieder richtig, sodass die Ebenen wieder
+|* Konsistent sind.
+|*
+|* Parameter
+|* SwIndex & aStart StartNode !!!
+|* SwIndex & aEnd EndPunkt
+|*
+*************************************************************************/
+void SwNodes::SectionUpDown( const SwNodeIndex & aStart, const SwNodeIndex & aEnd )
+{
+ SwNode * pAktNode;
+ SwNodeIndex aTmpIdx( aStart, +1 );
+ // das Array bildet einen Stack, es werden alle StartOfSelction's gesichert
+ SwSttNdPtrs aSttNdStack( 1, 5 );
+ SwStartNode* pTmp = aStart.GetNode().GetStartNode();
+ aSttNdStack.C40_INSERT( SwStartNode, pTmp, 0 );
+
+ // durchlaufe bis der erste zu aendernde Start-Node gefunden wurde
+ // ( Es wird vom eingefuegten EndNode bis nach vorne die Indexe gesetzt )
+ for( ;; aTmpIdx++ )
+ {
+ pAktNode = &aTmpIdx.GetNode();
+ pAktNode->pStartOfSection = aSttNdStack[ aSttNdStack.Count()-1 ];
+
+ if( pAktNode->GetStartNode() )
+ {
+ pTmp = (SwStartNode*)pAktNode;
+ aSttNdStack.C40_INSERT( SwStartNode, pTmp, aSttNdStack.Count() );
+ }
+ else if( pAktNode->GetEndNode() )
+ {
+ SwStartNode* pSttNd = aSttNdStack[ aSttNdStack.Count() - 1 ];
+ pSttNd->pEndOfSection = (SwEndNode*)pAktNode;
+ aSttNdStack.Remove( aSttNdStack.Count() - 1 );
+ if( aSttNdStack.Count() )
+ continue; // noch genuegend EndNodes auf dem Stack
+
+ else if( aTmpIdx < aEnd ) // Uebergewicht an StartNodes
+ // ist das Ende noch nicht erreicht, so hole den Start von
+ // der uebergeordneten Section
+ {
+ aSttNdStack.C40_INSERT( SwStartNode, pSttNd->pStartOfSection, 0 );
+ }
+ else // wenn ueber den Bereich hinaus, dann Ende
+ break;
+ }
+ }
+}
+
+
+
+
+/*******************************************************************
+|*
+|* SwNodes::Delete
+|*
+|* Beschreibung
+|* Spezielle Implementierung der Delete-Funktion des
+|* variablen Array. Diese spezielle Implementierung ist
+|* notwendig, da durch das Loeschen von Start- bzw.
+|* Endnodes Inkonsistenzen entstehen koennen. Diese werden
+|* durch diese Funktion beseitigt.
+|*
+|* Parameter
+|* IN
+|* SwIndex &rIndex bezeichnet die Position, an der
+|* geloescht wird
+|* rIndex ist nach Aufruf der Funktion unveraendert (Kopie?!)
+|* sal_uInt16 nNodes bezeichnet die Anzahl der zu loeschenden
+|* Nodes; ist auf 1 defaulted
+|*
+|* Debug-Funktionen
+|* geben beim Eintritt in die Funktion Position und Anzahl
+|* der zu loeschenden Nodes aus.
+|*
+*******************************************************************/
+void SwNodes::Delete(const SwNodeIndex &rIndex, sal_uLong nNodes)
+{
+ sal_uInt16 nLevel = 0; // Level-Counter
+ SwNode * pAktNode;
+
+ sal_uLong nCnt = Count() - rIndex.GetIndex() - 1;
+ if( nCnt > nNodes ) nCnt = nNodes;
+
+ if( nCnt == 0 ) // keine Anzahl -> return
+ return;
+
+ SwNodeRange aRg( rIndex, 0, rIndex, nCnt-1 );
+ // ueberprufe ob rIndex..rIndex + nCnt ueber einen Bereich hinausragt !!
+ if( ( !aRg.aStart.GetNode().StartOfSectionIndex() &&
+ !aRg.aStart.GetIndex() ) ||
+ ! CheckNodesRange( aRg.aStart, aRg.aEnd ) )
+ return;
+
+
+ // falls aEnd auf keinem ContentNode steht, dann suche den vorherigen
+ while( ( pAktNode = &aRg.aEnd.GetNode())->GetStartNode() ||
+ ( pAktNode->GetEndNode() &&
+ !pAktNode->pStartOfSection->IsTableNode() ))
+ aRg.aEnd--;
+
+ nCnt = 0;
+ // Start erhoehen, damit auf < abgefragt wird. ( bei <= kann es zu
+ // Problemen fuehren; ist aEnd == aStart und wird aEnd geloscht,
+ // so ist aEnd <= aStart
+ aRg.aStart--;
+
+ sal_Bool bSaveInNodesDel = bInNodesDel;
+ bInNodesDel = sal_True;
+ sal_Bool bUpdateOutline = sal_False;
+
+ // bis alles geloescht ist
+ while( aRg.aStart < aRg.aEnd )
+ {
+ pAktNode = &aRg.aEnd.GetNode();
+
+ if( pAktNode->GetEndNode() )
+ {
+ // die gesamte Section loeschen ?
+ if( pAktNode->StartOfSectionIndex() > aRg.aStart.GetIndex() )
+ {
+ SwTableNode* pTblNd = pAktNode->pStartOfSection->GetTableNode();
+ if( pTblNd )
+ pTblNd->DelFrms();
+
+ SwNode *pNd, *pChkNd = pAktNode->pStartOfSection;
+ sal_uInt16 nIdxPos;
+ do {
+ pNd = &aRg.aEnd.GetNode();
+
+ if( pNd->IsTxtNode() )
+ {
+ if( 0 != ((SwTxtNode*)pNd)->GetAttrOutlineLevel() &&//<-end,zhaojianwei
+ pOutlineNds->Seek_Entry( pNd, &nIdxPos ))
+ {
+ // loesche die Gliederungs-Indizies.
+ pOutlineNds->Remove( nIdxPos );
+ bUpdateOutline = sal_True;
+ }
+ ((SwTxtNode*)pNd)->InvalidateNumRule();
+ }
+ else if( pNd->IsEndNode() &&
+ pNd->pStartOfSection->IsTableNode() )
+ ((SwTableNode*)pNd->pStartOfSection)->DelFrms();
+
+ aRg.aEnd--;
+ nCnt++;
+
+ } while( pNd != pChkNd );
+ }
+ else
+ {
+ RemoveNode( aRg.aEnd.GetIndex()+1, nCnt, sal_True ); // loesche
+ nCnt = 0;
+ aRg.aEnd--; // vor den EndNode
+ nLevel++;
+ }
+ }
+ else if( pAktNode->GetStartNode() ) // StartNode gefunden
+ {
+ if( nLevel == 0 ) // es wird eine Stufe runter gestuft
+ {
+ if( nCnt )
+ {
+ // loesche jetzt das Array
+ aRg.aEnd++;
+ RemoveNode( aRg.aEnd.GetIndex(), nCnt, sal_True );
+ nCnt = 0;
+ }
+ }
+ else // es werden alle Nodes Innerhalb eines Start- und
+ { // End-Nodes geloescht, loesche mit Start/EndNode
+ RemoveNode( aRg.aEnd.GetIndex(), nCnt + 2, sal_True ); // loesche Array
+ nCnt = 0;
+ nLevel--;
+ }
+
+ // nach dem loeschen kann aEnd auf einem EndNode stehen
+ // loesche alle leeren Start-/End-Node-Paare
+ SwNode* pTmpNode = aRg.aEnd.GetNode().GetEndNode();
+ aRg.aEnd--;
+ while( pTmpNode &&
+ ( pAktNode = &aRg.aEnd.GetNode())->GetStartNode() &&
+ pAktNode->StartOfSectionIndex() )
+ {
+ // loesche den EndNode und StartNode
+ DelNodes( aRg.aEnd, 2 );
+ pTmpNode = aRg.aEnd.GetNode().GetEndNode();
+ aRg.aEnd--;
+ }
+ }
+ else // normaler Node, also ins TmpArray einfuegen
+ {
+ SwTxtNode* pTxtNd = pAktNode->GetTxtNode();
+ if( pTxtNd )
+ {
+ if( pTxtNd->IsOutline())
+ { // loesche die Gliederungs-Indizies.
+ pOutlineNds->Remove( pTxtNd );
+ bUpdateOutline = sal_True;
+ }
+ pTxtNd->InvalidateNumRule();
+ }
+ else if( pAktNode->IsCntntNode() )
+ ((SwCntntNode*)pAktNode)->InvalidateNumRule();
+
+ aRg.aEnd--;
+ nCnt++;
+ }
+ }
+
+ aRg.aEnd++;
+ if( nCnt != 0 )
+ RemoveNode( aRg.aEnd.GetIndex(), nCnt, sal_True ); // loesche den Rest
+
+ // loesche alle leeren Start-/End-Node-Paare
+ while( aRg.aEnd.GetNode().GetEndNode() &&
+ ( pAktNode = &aRg.aStart.GetNode())->GetStartNode() &&
+ pAktNode->StartOfSectionIndex() )
+ // aber ja keinen der heiligen 5.
+ {
+ DelNodes( aRg.aStart, 2 ); // loesche den Start- und EndNode
+ aRg.aStart--;
+ }
+
+ bInNodesDel = bSaveInNodesDel;
+
+ if( !bInNodesDel )
+ {
+ // rufe jetzt noch das Update fuer die Gliederung/Nummerierung auf
+ if( bUpdateOutline || bInDelUpdOutl )
+ {
+ UpdtOutlineIdx( aRg.aEnd.GetNode() );
+ bInDelUpdOutl = sal_False;
+ }
+
+ }
+ else
+ {
+ if( bUpdateOutline )
+ bInDelUpdOutl = sal_True;
+ }
+}
+
+/*******************************************************************
+|*
+|* SwNodes::GetSectionLevel
+|*
+|* Beschreibung
+|* Die Funktion liefert den Sectionlevel an der durch
+|* aIndex bezeichneten Position. Die Funktion ruft die
+|* GetSectionlevel-Funktion des durch aIndex bezeichneten
+|* Nodes. Diese ist eine virtuelle Funktion, die fuer
+|* Endnodes speziell implementiert werden musste.
+|* Die Sectionlevels werden ermittelt, indem rekursiv durch
+|* die Nodesstruktur (jeweils zum naechsten theEndOfSection)
+|* gegangen wird, bis die oberste Ebene erreicht ist
+|* (theEndOfSection == 0)
+|*
+|* Parameter
+|* aIndex bezeichnet die Position des Nodes, dessen
+|* Sectionlevel ermittelt werden soll. Hier wird eine Kopie
+|* uebergeben, da eine Veraenderung der Variablen in der
+|* rufenden Funktion nicht wuenschenswert ist.
+|*
+|* Ausnahmen
+|* Der erste Node im Array sollte immer ein Startnode sein.
+|* Dieser erfaehrt in der Funktion SwNodes::GetSectionLevel()
+|* eine Sonderbehandlung; es wird davon ausgegangen, dass der
+|* erste Node auch ein Startnode ist.
+|*
+*******************************************************************/
+sal_uInt16 SwNodes::GetSectionLevel(const SwNodeIndex &rIdx) const {
+ // Sonderbehandlung 1. Node
+ if(rIdx == 0) return 1;
+ /*
+ * Keine Rekursion! - hier wird das SwNode::GetSectionLevel
+ * aufgerufen
+ */
+ return rIdx.GetNode().GetSectionLevel();
+}
+
+void SwNodes::GoStartOfSection(SwNodeIndex *pIdx) const
+{
+ // hinter den naechsten Startnode
+ SwNodeIndex aTmp( *pIdx->GetNode().StartOfSectionNode(), +1 );
+
+ // steht der Index auf keinem ContentNode, dann gehe dahin. Ist aber
+ // kein weiterer vorhanden, dann lasse den Index an alter Pos stehen !!!
+ while( !aTmp.GetNode().IsCntntNode() )
+ { // gehe vom StartNode ( es kann nur ein StartNode sein ! ) an sein
+ // Ende
+ if( *pIdx <= aTmp )
+ return; // FEHLER: Steht schon hinter der Sektion
+ aTmp = aTmp.GetNode().EndOfSectionIndex()+1;
+ if( *pIdx <= aTmp )
+ return; // FEHLER: Steht schon hinter der Sektion
+ }
+ (*pIdx) = aTmp; // steht auf einem ContentNode
+}
+
+void SwNodes::GoEndOfSection(SwNodeIndex *pIdx) const
+{
+ // falls er vor einem Endnode steht --> nichts tun
+ if( !pIdx->GetNode().IsEndNode() )
+ (*pIdx) = *pIdx->GetNode().EndOfSectionNode();
+}
+
+SwCntntNode* SwNodes::GoNext(SwNodeIndex *pIdx) const
+{
+ if( pIdx->GetIndex() >= Count() - 1 )
+ return 0;
+
+ SwNodeIndex aTmp(*pIdx, +1);
+ SwNode* pNd = 0;
+ while( aTmp < Count()-1 && 0 == ( pNd = &aTmp.GetNode())->IsCntntNode() )
+ aTmp++;
+
+ if( aTmp == Count()-1 )
+ pNd = 0;
+ else
+ (*pIdx) = aTmp;
+ return (SwCntntNode*)pNd;
+}
+
+SwCntntNode* SwNodes::GoPrevious(SwNodeIndex *pIdx) const
+{
+ if( !pIdx->GetIndex() )
+ return 0;
+
+ SwNodeIndex aTmp( *pIdx, -1 );
+ SwNode* pNd = 0;
+ while( aTmp.GetIndex() && 0 == ( pNd = &aTmp.GetNode())->IsCntntNode() )
+ aTmp--;
+
+ if( !aTmp.GetIndex() )
+ pNd = 0;
+ else
+ (*pIdx) = aTmp;
+ return (SwCntntNode*)pNd;
+}
+
+/*************************************************************************
+|*
+|* sal_Bool SwNodes::CheckNodesRange()
+|*
+|* Beschreibung
+|* Teste ob der uebergene SRange nicht ueber die Grenzen der
+|* einzelnen Bereiche (PosIts, Autotext, Content, Icons und Inserts )
+|* hinaus reicht.
+|* Nach Wahrscheinlichkeit des Ranges sortiert.
+|*
+|* Alg.: Da festgelegt ist, das aRange.aEnd den 1.Node hinter dem Bereich
+|* bezeichnet, wird hier auf aEnd <= End.. getestet !!
+|*
+|* Parameter SwIndex & Start-Index vom Bereich
+|* SwIndex & End-Index vom Bereich
+|* sal_Bool sal_True: Start+End in gleicher Section!
+|* sal_False: Start+End in verschiedenen Sect.
+|* Return-Wert sal_Bool sal_True: gueltiger SRange
+|* sal_False: ungueltiger SRange
+|*
+*************************************************************************/
+
+inline int TstIdx( sal_uLong nSttIdx, sal_uLong nEndIdx, sal_uLong nStt, sal_uLong nEnd )
+{
+ return nStt < nSttIdx && nEnd >= nSttIdx &&
+ nStt < nEndIdx && nEnd >= nEndIdx;
+}
+
+sal_Bool SwNodes::CheckNodesRange( const SwNodeIndex& rStt, const SwNodeIndex& rEnd ) const
+{
+ sal_uLong nStt = rStt.GetIndex(), nEnd = rEnd.GetIndex();
+ if( TstIdx( nStt, nEnd, pEndOfContent->StartOfSectionIndex(),
+ pEndOfContent->GetIndex() )) return sal_True;
+ if( TstIdx( nStt, nEnd, pEndOfAutotext->StartOfSectionIndex(),
+ pEndOfAutotext->GetIndex() )) return sal_True;
+ if( TstIdx( nStt, nEnd, pEndOfPostIts->StartOfSectionIndex(),
+ pEndOfPostIts->GetIndex() )) return sal_True;
+ if( TstIdx( nStt, nEnd, pEndOfInserts->StartOfSectionIndex(),
+ pEndOfInserts->GetIndex() )) return sal_True;
+ if( TstIdx( nStt, nEnd, pEndOfRedlines->StartOfSectionIndex(),
+ pEndOfRedlines->GetIndex() )) return sal_True;
+
+ return sal_False; // liegt irgendwo dazwischen, FEHLER
+}
+
+
+/*************************************************************************
+|*
+|* void SwNodes::DelNodes()
+|*
+|* Beschreibung
+|* Loesche aus den NodesArray ab einer Position entsprechend Node's.
+|*
+|* Parameter SwIndex & Der Startpunkt im Nodes-Array
+|* sal_uInt16 die Anzahl
+|*
+*************************************************************************/
+void SwNodes::DelNodes( const SwNodeIndex & rStart, sal_uLong nCnt )
+{
+ sal_uLong nSttIdx = rStart.GetIndex();
+
+ if( !nSttIdx && nCnt == GetEndOfContent().GetIndex()+1 )
+ {
+ // es wird das gesamte Nodes-Array zerstoert, man ist im Doc DTOR!
+ // Die initialen Start-/End-Nodes duerfen nur im SwNodes-DTOR
+ // zerstoert werden!
+ SwNode* aEndNdArr[] = { pEndOfContent,
+ pEndOfPostIts, pEndOfInserts,
+ pEndOfAutotext, pEndOfRedlines,
+ 0
+ };
+
+ SwNode** ppEndNdArr = aEndNdArr;
+ while( *ppEndNdArr )
+ {
+ nSttIdx = (*ppEndNdArr)->StartOfSectionIndex() + 1;
+ sal_uLong nEndIdx = (*ppEndNdArr)->GetIndex();
+
+ if( nSttIdx != nEndIdx )
+ RemoveNode( nSttIdx, nEndIdx - nSttIdx, sal_True );
+
+ ++ppEndNdArr;
+ }
+ }
+ else
+ {
+ int bUpdateNum = 0;
+ for( sal_uLong n = nSttIdx, nEnd = nSttIdx + nCnt; n < nEnd; ++n )
+ {
+ SwNode* pNd = (*this)[ n ];
+
+ if( pNd->IsTxtNode() &&
+ 0 != ((SwTxtNode*)pNd)->GetAttrOutlineLevel() ) //<-end,zhaojianwei
+ { // loesche die Gliederungs-Indizies.
+ sal_uInt16 nIdxPos;
+ if( pOutlineNds->Seek_Entry( pNd, &nIdxPos ))
+ {
+ pOutlineNds->Remove( nIdxPos );
+ bUpdateNum = 1;
+ }
+ }
+ if( pNd->IsCntntNode() )
+ {
+ ((SwCntntNode*)pNd)->InvalidateNumRule();
+ ((SwCntntNode*)pNd)->DelFrms();
+ }
+ }
+ RemoveNode( nSttIdx, nCnt, sal_True );
+
+ // rufe noch das Update fuer die Gliederungsnumerierung auf
+ if( bUpdateNum )
+ UpdtOutlineIdx( rStart.GetNode() );
+ }
+}
+
+
+/*************************************************************************
+|*
+|* sal_uInt16 HighestLevel( SwNodes & rNodes, const SwNodeRange & rRange )
+|*
+|* Beschreibung
+|* Berechne den hoehsten Level innerhalb des Bereiches
+|*
+|* Parameter SwNodes & das Node-Array
+|* SwNodeRange & der zu ueberpruefende Bereich
+|* Return sal_uInt16 der hoechste Level
+|*
+*************************************************************************/
+
+struct HighLevel
+{
+ sal_uInt16 nLevel, nTop;
+ HighLevel( sal_uInt16 nLv ) : nLevel( nLv ), nTop( nLv ) {}
+
+};
+
+sal_Bool _HighestLevel( const SwNodePtr& rpNode, void * pPara )
+{
+ HighLevel * pHL = (HighLevel*)pPara;
+ if( rpNode->GetStartNode() )
+ pHL->nLevel++;
+ else if( rpNode->GetEndNode() )
+ pHL->nLevel--;
+ if( pHL->nTop > pHL->nLevel )
+ pHL->nTop = pHL->nLevel;
+ return sal_True;
+
+}
+
+sal_uInt16 HighestLevel( SwNodes & rNodes, const SwNodeRange & rRange )
+{
+ HighLevel aPara( rNodes.GetSectionLevel( rRange.aStart ));
+ rNodes.ForEach( rRange.aStart, rRange.aEnd, _HighestLevel, &aPara );
+ return aPara.nTop;
+
+}
+
+/*************************************************************************
+|*
+|* SwNodes::Move()
+|*
+|* Beschreibung
+|* Parameter SwPaM& zu kopierender Bereich
+|* SwNodes& in dieses Nodes-Array
+|* SwPosition& auf diese Position im Nodes-Array
+|*
+*************************************************************************/
+void SwNodes::MoveRange( SwPaM & rPam, SwPosition & rPos, SwNodes& rNodes )
+{
+ SwPosition * const pStt = rPam.Start();
+ SwPosition * const pEnd = rPam.End();
+
+ if( !rPam.HasMark() || *pStt >= *pEnd )
+ return;
+
+ if( this == &rNodes && *pStt <= rPos && rPos < *pEnd )
+ return;
+
+ SwNodeIndex aEndIdx( pEnd->nNode );
+ SwNodeIndex aSttIdx( pStt->nNode );
+ SwTxtNode *const pSrcNd = aSttIdx.GetNode().GetTxtNode();
+ SwTxtNode * pDestNd = rPos.nNode.GetNode().GetTxtNode();
+ sal_Bool bSplitDestNd = sal_True;
+ sal_Bool bCopyCollFmt = pDestNd && !pDestNd->GetTxt().Len();
+
+ if( pSrcNd )
+ {
+ // ist der 1.Node ein TextNode, dann muss im NodesArray auch
+ // ein TextNode vorhanden sein, in den der Inhalt geschoben wird
+ if( !pDestNd )
+ {
+ pDestNd = rNodes.MakeTxtNode( rPos.nNode, pSrcNd->GetTxtColl() );
+ rPos.nNode--;
+ rPos.nContent.Assign( pDestNd, 0 );
+ bCopyCollFmt = sal_True;
+ }
+ bSplitDestNd = pDestNd->Len() > rPos.nContent.GetIndex() ||
+ pEnd->nNode.GetNode().IsTxtNode();
+
+ // verschiebe jetzt noch den Inhalt in den neuen Node
+ sal_Bool bOneNd = pStt->nNode == pEnd->nNode;
+ const xub_StrLen nLen =
+ ( (bOneNd) ? pEnd->nContent.GetIndex() : pSrcNd->Len() )
+ - pStt->nContent.GetIndex();
+
+ if( !pEnd->nNode.GetNode().IsCntntNode() )
+ {
+ bOneNd = sal_True;
+ sal_uLong nSttNdIdx = pStt->nNode.GetIndex() + 1;
+ const sal_uLong nEndNdIdx = pEnd->nNode.GetIndex();
+ for( ; nSttNdIdx < nEndNdIdx; ++nSttNdIdx )
+ {
+ if( (*this)[ nSttNdIdx ]->IsCntntNode() )
+ {
+ bOneNd = sal_False;
+ break;
+ }
+ }
+ }
+
+ // das kopieren / setzen der Vorlagen darf erst nach
+ // dem Splitten erfolgen
+ if( !bOneNd && bSplitDestNd )
+ {
+ if( !rPos.nContent.GetIndex() )
+ {
+ bCopyCollFmt = sal_True;
+ }
+ if( rNodes.IsDocNodes() )
+ {
+ SwDoc* const pInsDoc = pDestNd->GetDoc();
+ ::sw::UndoGuard const ug(pInsDoc->GetIDocumentUndoRedo());
+ pInsDoc->SplitNode( rPos, false );
+ }
+ else
+ {
+ pDestNd->SplitCntntNode( rPos );
+ }
+
+ if( rPos.nNode == aEndIdx )
+ {
+ aEndIdx--;
+ }
+ bSplitDestNd = sal_True;
+
+ pDestNd = rNodes[ rPos.nNode.GetIndex() - 1 ]->GetTxtNode();
+ if( nLen )
+ {
+ pSrcNd->CutText( pDestNd, SwIndex( pDestNd, pDestNd->Len()),
+ pStt->nContent, nLen );
+ }
+ }
+ else if ( nLen )
+ {
+ pSrcNd->CutText( pDestNd, rPos.nContent, pStt->nContent, nLen );
+ }
+
+ if( bCopyCollFmt )
+ {
+ SwDoc* const pInsDoc = pDestNd->GetDoc();
+ ::sw::UndoGuard const undoGuard(pInsDoc->GetIDocumentUndoRedo());
+ pSrcNd->CopyCollFmt( *pDestNd );
+ bCopyCollFmt = sal_False;
+ }
+
+ if( bOneNd ) // das wars schon
+ {
+ // der PaM wird korrigiert, denn falls ueber Nodegrenzen verschoben
+ // wurde, so stehen sie in unterschieden Nodes. Auch die Selektion
+ // wird aufgehoben !
+ pEnd->nContent = pStt->nContent;
+ rPam.DeleteMark();
+ GetDoc()->GetDocShell()->Broadcast( SwFmtFldHint( 0,
+ rNodes.IsDocNodes() ? SWFMTFLD_INSERTED : SWFMTFLD_REMOVED ) );
+ return;
+ }
+
+ aSttIdx++;
+ }
+ else if( pDestNd )
+ {
+ if( rPos.nContent.GetIndex() )
+ {
+ if( rPos.nContent.GetIndex() == pDestNd->Len() )
+ {
+ rPos.nNode++;
+ }
+ else if( rPos.nContent.GetIndex() )
+ {
+ // falls im EndNode gesplittet wird, dann muss der EndIdx
+ // korrigiert werden !!
+ const bool bCorrEnd = aEndIdx == rPos.nNode;
+ // es wird kein Text an den TextNode angehaengt, also splitte ihn
+
+ if( rNodes.IsDocNodes() )
+ {
+ SwDoc* const pInsDoc = pDestNd->GetDoc();
+ ::sw::UndoGuard const ug(pInsDoc->GetIDocumentUndoRedo());
+ pInsDoc->SplitNode( rPos, false );
+ }
+ else
+ {
+ pDestNd->SplitCntntNode( rPos );
+ }
+
+ pDestNd = rPos.nNode.GetNode().GetTxtNode();
+
+ if ( bCorrEnd )
+ {
+ aEndIdx--;
+ }
+ }
+ }
+ // am Ende steht noch ein leerer Text Node herum.
+ bSplitDestNd = sal_True;
+ }
+
+ SwTxtNode* const pEndSrcNd = aEndIdx.GetNode().GetTxtNode();
+ if ( pEndSrcNd )
+ {
+ {
+ // am Bereichsende entsteht ein neuer TextNode
+ if( !bSplitDestNd )
+ {
+ if( rPos.nNode < rNodes.GetEndOfContent().GetIndex() )
+ {
+ rPos.nNode++;
+ }
+
+ pDestNd =
+ rNodes.MakeTxtNode( rPos.nNode, pEndSrcNd->GetTxtColl() );
+ rPos.nNode--;
+ rPos.nContent.Assign( pDestNd, 0 );
+ }
+ else
+ {
+ pDestNd = rPos.nNode.GetNode().GetTxtNode();
+ }
+
+ if( pDestNd && pEnd->nContent.GetIndex() )
+ {
+ // verschiebe jetzt noch den Inhalt in den neuen Node
+ SwIndex aIdx( pEndSrcNd, 0 );
+ pEndSrcNd->CutText( pDestNd, rPos.nContent, aIdx,
+ pEnd->nContent.GetIndex());
+ }
+
+ if( bCopyCollFmt )
+ {
+ SwDoc* const pInsDoc = pDestNd->GetDoc();
+ ::sw::UndoGuard const ug(pInsDoc->GetIDocumentUndoRedo());
+ pEndSrcNd->CopyCollFmt( *pDestNd );
+ }
+ }
+ }
+ else
+ {
+ if ( pSrcNd && aEndIdx.GetNode().IsCntntNode() )
+ {
+ aEndIdx++;
+ }
+ if( !bSplitDestNd )
+ {
+ rPos.nNode++;
+ rPos.nContent.Assign( rPos.nNode.GetNode().GetCntntNode(), 0 );
+ }
+ }
+
+ if( aEndIdx != aSttIdx )
+ {
+ // verschiebe jetzt die Nodes in das NodesArary
+ const sal_uLong nSttDiff = aSttIdx.GetIndex() - pStt->nNode.GetIndex();
+ SwNodeRange aRg( aSttIdx, aEndIdx );
+ _MoveNodes( aRg, rNodes, rPos.nNode );
+ // falls ins gleiche Nodes-Array verschoben wurde, stehen die
+ // Indizies jetzt auch an der neuen Position !!!!
+ // (also alles wieder umsetzen)
+ if( &rNodes == this )
+ {
+ pStt->nNode = aRg.aEnd.GetIndex() - nSttDiff;
+ }
+ }
+
+ // falls der Start-Node verschoben wurde, in dem der Cursor stand, so
+ // muss der Content im akt. Content angemeldet werden !!!
+ if ( &pStt->nNode.GetNode() == &GetEndOfContent() )
+ {
+ const bool bSuccess = GoPrevious( &pStt->nNode );
+ OSL_ENSURE( bSuccess, "Move() - no ContentNode here" );
+ (void) bSuccess;
+ }
+ pStt->nContent.Assign( pStt->nNode.GetNode().GetCntntNode(),
+ pStt->nContent.GetIndex() );
+ // der PaM wird korrigiert, denn falls ueber Nodegrenzen verschoben
+ // wurde, so stehen sie in unterschielichen Nodes. Auch die Selektion
+ // wird aufgehoben !
+ *pEnd = *pStt;
+ rPam.DeleteMark();
+ GetDoc()->GetDocShell()->Broadcast( SwFmtFldHint( 0,
+ rNodes.IsDocNodes() ? SWFMTFLD_INSERTED : SWFMTFLD_REMOVED ) );
+}
+
+
+
+/*************************************************************************
+|*
+|* SwNodes::_Copy()
+|*
+|* Beschreibung
+|* Parameter SwNodeRange& zu kopierender Bereich
+|* SwDoc& in dieses Dokument
+|* SwIndex& auf diese Position im Nodes-Array
+|*
+*************************************************************************/
+
+inline sal_uInt8 MaxLvl( sal_uInt8 nMin, sal_uInt8 nMax, short nNew )
+{
+ return (sal_uInt8)(nNew < nMin ? nMin : nNew > nMax ? nMax : nNew);
+}
+
+void SwNodes::_CopyNodes( const SwNodeRange& rRange,
+ const SwNodeIndex& rIndex, sal_Bool bNewFrms, sal_Bool bTblInsDummyNode ) const
+{
+ SwDoc* pDoc = rIndex.GetNode().GetDoc();
+
+ SwNode * pAktNode;
+ if( rIndex == 0 ||
+ ( (pAktNode = &rIndex.GetNode())->GetStartNode() &&
+ !pAktNode->StartOfSectionIndex() ))
+ return;
+
+ SwNodeRange aRg( rRange );
+
+ // "einfache" StartNodes oder EndNodes ueberspringen
+ while( ND_STARTNODE == (pAktNode = & aRg.aStart.GetNode())->GetNodeType()
+ || ( pAktNode->IsEndNode() &&
+ !pAktNode->pStartOfSection->IsSectionNode() ) )
+ aRg.aStart++;
+
+ // falls aEnd-1 auf keinem ContentNode steht, dann suche den vorherigen
+ aRg.aEnd--;
+ // #i107142#: if aEnd is start node of a special section, do nothing.
+ // Otherwise this could lead to crash: going through all previous
+ // special section nodes and then one before the first.
+ if (aRg.aEnd.GetNode().StartOfSectionIndex() != 0)
+ {
+ while( ((pAktNode = & aRg.aEnd.GetNode())->GetStartNode() &&
+ !pAktNode->IsSectionNode() ) ||
+ ( pAktNode->IsEndNode() &&
+ ND_STARTNODE == pAktNode->pStartOfSection->GetNodeType()) )
+ {
+ aRg.aEnd--;
+ }
+ }
+ aRg.aEnd++;
+
+ // wird im selben Array's verschoben, dann ueberpruefe die Einfuegepos.
+ if( aRg.aStart >= aRg.aEnd )
+ return;
+
+ // when inserting into the source range, nothing need to be done
+ DBG_ASSERT( &aRg.aStart.GetNodes() == this,
+ "aRg should use thisnodes array" );
+ DBG_ASSERT( &aRg.aStart.GetNodes() == &aRg.aEnd.GetNodes(),
+ "Range across different nodes arrays? You deserve punishment!");
+ if( &rIndex.GetNodes() == &aRg.aStart.GetNodes() &&
+ rIndex.GetIndex() >= aRg.aStart.GetIndex() &&
+ rIndex.GetIndex() < aRg.aEnd.GetIndex() )
+ return;
+
+ SwNodeIndex aInsPos( rIndex );
+ SwNodeIndex aOrigInsPos( rIndex, -1 ); // Originale Insert Pos
+ sal_uInt16 nLevel = 0; // Level-Counter
+
+ for( sal_uLong nNodeCnt = aRg.aEnd.GetIndex() - aRg.aStart.GetIndex();
+ nNodeCnt > 0; --nNodeCnt )
+ {
+ pAktNode = &aRg.aStart.GetNode();
+ switch( pAktNode->GetNodeType() )
+ {
+ case ND_TABLENODE:
+ // dann kopiere mal den TableNode
+ // Tabell in Fussnote kopieren ?
+ if( aInsPos < pDoc->GetNodes().GetEndOfInserts().GetIndex() &&
+ pDoc->GetNodes().GetEndOfInserts().StartOfSectionIndex()
+ < aInsPos.GetIndex() )
+ {
+ sal_uLong nDistance =
+ ( pAktNode->EndOfSectionIndex() -
+ aRg.aStart.GetIndex() );
+ if (nDistance < nNodeCnt)
+ nNodeCnt -= nDistance;
+ else
+ nNodeCnt = 1;
+
+ // dann alle Nodes der Tabelle in die akt. Zelle kopieren
+ // fuer den TabellenNode einen DummyNode einfuegen?
+ if( bTblInsDummyNode )
+ new SwNode( aInsPos, ND_SECTIONDUMMY );
+
+ for( aRg.aStart++; aRg.aStart.GetIndex() <
+ pAktNode->EndOfSectionIndex();
+ aRg.aStart++ )
+ {
+ // fuer den Box-StartNode einen DummyNode einfuegen?
+ if( bTblInsDummyNode )
+ new SwNode( aInsPos, ND_SECTIONDUMMY );
+
+ SwStartNode* pSttNd = aRg.aStart.GetNode().GetStartNode();
+ _CopyNodes( SwNodeRange( *pSttNd, + 1,
+ *pSttNd->EndOfSectionNode() ),
+ aInsPos, bNewFrms, sal_False );
+
+ // fuer den Box-EndNode einen DummyNode einfuegen?
+ if( bTblInsDummyNode )
+ new SwNode( aInsPos, ND_SECTIONDUMMY );
+ aRg.aStart = *pSttNd->EndOfSectionNode();
+ }
+ // fuer den TabellenEndNode einen DummyNode einfuegen?
+ if( bTblInsDummyNode )
+ new SwNode( aInsPos, ND_SECTIONDUMMY );
+ aRg.aStart = *pAktNode->EndOfSectionNode();
+ }
+ else
+ {
+ SwNodeIndex nStt( aInsPos, -1 );
+ SwTableNode* pTblNd = ((SwTableNode*)pAktNode)->
+ MakeCopy( pDoc, aInsPos );
+ sal_uLong nDistance = aInsPos.GetIndex() - nStt.GetIndex() - 2;
+ if (nDistance < nNodeCnt)
+ nNodeCnt -= nDistance;
+ else
+ nNodeCnt = 1;
+
+ aRg.aStart = pAktNode->EndOfSectionIndex();
+
+ if( bNewFrms && pTblNd )
+ {
+ nStt = aInsPos;
+ pTblNd->MakeFrms( &nStt );
+ }
+ }
+ break;
+
+ case ND_SECTIONNODE: // SectionNode
+ // If the end of the section is outside the copy range,
+ // the section node will skipped, not copied!
+ // If someone want to change this behaviour, he has to adjust the function
+ // lcl_NonCopyCount(..) in ndcopy.cxx which relies on it.
+ if( pAktNode->EndOfSectionIndex() < aRg.aEnd.GetIndex() )
+ {
+ // also der gesamte, lege einen neuen SectionNode an
+ SwNodeIndex nStt( aInsPos, -1 );
+ SwSectionNode* pSectNd = ((SwSectionNode*)pAktNode)->
+ MakeCopy( pDoc, aInsPos );
+
+ sal_uLong nDistance = aInsPos.GetIndex() - nStt.GetIndex() - 2;
+ if (nDistance < nNodeCnt)
+ nNodeCnt -= nDistance;
+ else
+ nNodeCnt = 1;
+ aRg.aStart = pAktNode->EndOfSectionIndex();
+
+ if( bNewFrms && pSectNd &&
+ !pSectNd->GetSection().IsHidden() )
+ pSectNd->MakeFrms( &nStt );
+ }
+ break;
+
+ case ND_STARTNODE: // StartNode gefunden
+ {
+ SwStartNode* pTmp = new SwStartNode( aInsPos, ND_STARTNODE,
+ ((SwStartNode*)pAktNode)->GetStartNodeType() );
+ new SwEndNode( aInsPos, *pTmp );
+ aInsPos--;
+ nLevel++;
+ }
+ break;
+
+ case ND_ENDNODE:
+ if( nLevel ) // vollstaendige Section
+ {
+ --nLevel;
+ aInsPos++; // EndNode schon vorhanden
+ }
+ else if( !pAktNode->pStartOfSection->IsSectionNode() )
+ {
+ // erzeuge eine Section an der originalen InsertPosition
+ SwNodeRange aTmpRg( aOrigInsPos, 1, aInsPos );
+ pDoc->GetNodes().SectionDown( &aTmpRg,
+ pAktNode->pStartOfSection->GetStartNodeType() );
+ }
+ break;
+
+ case ND_TEXTNODE:
+ case ND_GRFNODE:
+ case ND_OLENODE:
+ {
+ SwCntntNode* pNew = ((SwCntntNode*)pAktNode)->MakeCopy(
+ pDoc, aInsPos );
+ if( !bNewFrms ) // dflt. werden die Frames immer angelegt
+ pNew->DelFrms();
+ }
+ break;
+
+ case ND_SECTIONDUMMY:
+ if (GetDoc()->GetIDocumentUndoRedo().IsUndoNodes(*this))
+ {
+ // dann muss an der akt. InsPos auch ein SectionNode
+ // (Start/Ende) stehen; dann diesen ueberspringen.
+ // Andernfalls nicht weiter beachten.
+ SwNode *const pTmpNd = & aInsPos.GetNode();
+ if( pTmpNd->IsSectionNode() ||
+ pTmpNd->StartOfSectionNode()->IsSectionNode() )
+ aInsPos++; // ueberspringen
+ }
+ else {
+ OSL_FAIL( "wie kommt diser Node ins Nodes-Array??" );
+ }
+ break;
+
+ default:
+ OSL_FAIL( "weder Start-/End-/Content-Node, unbekannter Typ" );
+ }
+ aRg.aStart++;
+ }
+}
+
+void SwNodes::_DelDummyNodes( const SwNodeRange& rRg )
+{
+ SwNodeIndex aIdx( rRg.aStart );
+ while( aIdx.GetIndex() < rRg.aEnd.GetIndex() )
+ {
+ if( ND_SECTIONDUMMY == aIdx.GetNode().GetNodeType() )
+ RemoveNode( aIdx.GetIndex(), 1, sal_True );
+ else
+ aIdx++;
+ }
+}
+
+SwStartNode* SwNodes::MakeEmptySection( const SwNodeIndex& rIdx,
+ SwStartNodeType eSttNdTyp )
+{
+ SwStartNode* pSttNd = new SwStartNode( rIdx, ND_STARTNODE, eSttNdTyp );
+ new SwEndNode( rIdx, *pSttNd );
+ return pSttNd;
+}
+
+
+SwStartNode* SwNodes::MakeTextSection( const SwNodeIndex & rWhere,
+ SwStartNodeType eSttNdTyp,
+ SwTxtFmtColl *pColl,
+ SwAttrSet* pAutoAttr )
+{
+ SwStartNode* pSttNd = new SwStartNode( rWhere, ND_STARTNODE, eSttNdTyp );
+ new SwEndNode( rWhere, *pSttNd );
+ MakeTxtNode( SwNodeIndex( rWhere, - 1 ), pColl, pAutoAttr );
+ return pSttNd;
+}
+
+ // zum naechsten Content-Node, der nicht geschuetzt oder versteckt ist
+ // (beides auf sal_False ==> GoNext/GoPrevious!!!)
+SwCntntNode* SwNodes::GoNextSection( SwNodeIndex * pIdx,
+ int bSkipHidden, int bSkipProtect ) const
+{
+ int bFirst = sal_True;
+ SwNodeIndex aTmp( *pIdx );
+ const SwNode* pNd;
+ while( aTmp < Count() - 1 )
+ {
+ pNd = & aTmp.GetNode();
+ if (ND_SECTIONNODE == pNd->GetNodeType())
+ {
+ const SwSection& rSect = ((SwSectionNode*)pNd)->GetSection();
+ if( (bSkipHidden && rSect.IsHiddenFlag()) ||
+ (bSkipProtect && rSect.IsProtectFlag()) )
+ // dann diese Section ueberspringen
+ aTmp = *pNd->EndOfSectionNode();
+ bFirst = sal_False;
+ }
+ else if( bFirst )
+ {
+ bFirst = sal_False;
+ if( pNd->pStartOfSection->IsSectionNode() )
+ {
+ const SwSection& rSect = ((SwSectionNode*)pNd->
+ pStartOfSection)->GetSection();
+ if( (bSkipHidden && rSect.IsHiddenFlag()) ||
+ (bSkipProtect && rSect.IsProtectFlag()) )
+ // dann diese Section ueberspringen
+ aTmp = *pNd->EndOfSectionNode();
+ }
+ }
+ else if( ND_CONTENTNODE & pNd->GetNodeType() )
+ {
+ const SwSectionNode* pSectNd;
+ if( ( bSkipHidden || bSkipProtect ) &&
+ 0 != (pSectNd = pNd->FindSectionNode() ) &&
+ ( ( bSkipHidden && pSectNd->GetSection().IsHiddenFlag() ) ||
+ ( bSkipProtect && pSectNd->GetSection().IsProtectFlag() )) )
+ {
+ aTmp = *pSectNd->EndOfSectionNode();
+ }
+ else
+ {
+ (*pIdx) = aTmp;
+ return (SwCntntNode*)pNd;
+ }
+ }
+ aTmp++;
+ bFirst = sal_False;
+ }
+ return 0;
+}
+
+SwCntntNode* SwNodes::GoPrevSection( SwNodeIndex * pIdx,
+ int bSkipHidden, int bSkipProtect ) const
+{
+ int bFirst = sal_True;
+ SwNodeIndex aTmp( *pIdx );
+ const SwNode* pNd;
+ while( aTmp > 0 )
+ {
+ pNd = & aTmp.GetNode();
+ if (ND_ENDNODE == pNd->GetNodeType())
+ {
+ if( pNd->pStartOfSection->IsSectionNode() )
+ {
+ const SwSection& rSect = ((SwSectionNode*)pNd->
+ pStartOfSection)->GetSection();
+ if( (bSkipHidden && rSect.IsHiddenFlag()) ||
+ (bSkipProtect && rSect.IsProtectFlag()) )
+ // dann diese Section ueberspringen
+ aTmp = *pNd->StartOfSectionNode();
+ }
+ bFirst = sal_False;
+ }
+ else if( bFirst )
+ {
+ bFirst = sal_False;
+ if( pNd->pStartOfSection->IsSectionNode() )
+ {
+ const SwSection& rSect = ((SwSectionNode*)pNd->
+ pStartOfSection)->GetSection();
+ if( (bSkipHidden && rSect.IsHiddenFlag()) ||
+ (bSkipProtect && rSect.IsProtectFlag()) )
+ // dann diese Section ueberspringen
+ aTmp = *pNd->StartOfSectionNode();
+ }
+ }
+ else if( ND_CONTENTNODE & pNd->GetNodeType() )
+ {
+ const SwSectionNode* pSectNd;
+ if( ( bSkipHidden || bSkipProtect ) &&
+ 0 != (pSectNd = pNd->FindSectionNode() ) &&
+ ( ( bSkipHidden && pSectNd->GetSection().IsHiddenFlag() ) ||
+ ( bSkipProtect && pSectNd->GetSection().IsProtectFlag() )) )
+ {
+ aTmp = *pSectNd;
+ }
+ else
+ {
+ (*pIdx) = aTmp;
+ return (SwCntntNode*)pNd;
+ }
+ }
+ aTmp--;
+ }
+ return 0;
+}
+
+
+ // suche den vorhergehenden [/nachfolgenden ] ContentNode oder
+ // TabellenNode mit Frames. Wird kein Ende angeben, dann wird mit
+ // dem FrameIndex begonnen; ansonsten, wird mit dem vor rFrmIdx und
+ // dem hintern pEnd die Suche gestartet. Sollte kein gueltiger Node
+ // gefunden werden, wird 0 returnt. rFrmIdx zeigt auf dem Node mit
+ // Frames
+SwNode* SwNodes::FindPrvNxtFrmNode( SwNodeIndex& rFrmIdx,
+ const SwNode* pEnd ) const
+{
+ SwNode* pFrmNd = 0;
+
+ // habe wir gar kein Layout, vergiss es
+ if( GetDoc()->GetCurrentViewShell() ) //swmod 071108//swmod 071225
+ {
+ SwNode* pSttNd = &rFrmIdx.GetNode();
+
+ // wird in eine versteckte Section verschoben ??
+ SwSectionNode* pSectNd = pSttNd->IsSectionNode()
+ ? pSttNd->StartOfSectionNode()->FindSectionNode()
+ : pSttNd->FindSectionNode();
+ if( !( pSectNd && pSectNd->GetSection().CalcHiddenFlag()/*IsHiddenFlag()*/ ) )
+ {
+ // in a table in table situation we have to assure that we don't leave the
+ // outer table cell when the inner table is looking for a PrvNxt...
+ SwTableNode* pTableNd = pSttNd->IsTableNode()
+ ? pSttNd->StartOfSectionNode()->FindTableNode()
+ : pSttNd->FindTableNode();
+ SwNodeIndex aIdx( rFrmIdx );
+ SwNode* pNd;
+ if( pEnd )
+ {
+ aIdx--;
+ pNd = &aIdx.GetNode();
+ }
+ else
+ pNd = pSttNd;
+
+ if( ( pFrmNd = pNd )->IsCntntNode() )
+ rFrmIdx = aIdx;
+
+ // suche nach vorne/hinten nach einem Content Node
+ else if( 0 != ( pFrmNd = GoPrevSection( &aIdx, sal_True, sal_False )) &&
+ ::CheckNodesRange( aIdx, rFrmIdx, sal_True ) &&
+ // nach vorne nie aus der Tabelle hinaus!
+ pFrmNd->FindTableNode() == pTableNd &&
+ // Bug 37652: nach hinten nie aus der Tabellenzelle hinaus!
+ (!pFrmNd->FindTableNode() || pFrmNd->FindTableBoxStartNode()
+ == pSttNd->FindTableBoxStartNode() ) &&
+ (!pSectNd || pSttNd->IsSectionNode() ||
+ pSectNd->GetIndex() < pFrmNd->GetIndex())
+ )
+ {
+ rFrmIdx = aIdx;
+ }
+ else
+ {
+ if( pEnd )
+ aIdx = pEnd->GetIndex() + 1;
+ else
+ aIdx = rFrmIdx;
+
+ // JP 19.09.93: aber nie die Section dafuer verlassen !!
+ if( ( pEnd && ( pFrmNd = &aIdx.GetNode())->IsCntntNode() ) ||
+ ( 0 != ( pFrmNd = GoNextSection( &aIdx, sal_True, sal_False )) &&
+ ::CheckNodesRange( aIdx, rFrmIdx, sal_True ) &&
+ ( pFrmNd->FindTableNode() == pTableNd &&
+ // Bug 37652: nach hinten nie aus der Tabellenzelle hinaus!
+ (!pFrmNd->FindTableNode() || pFrmNd->FindTableBoxStartNode()
+ == pSttNd->FindTableBoxStartNode() ) ) &&
+ (!pSectNd || pSttNd->IsSectionNode() ||
+ pSectNd->EndOfSectionIndex() > pFrmNd->GetIndex())
+ ))
+ {
+ //JP 18.02.99: Undo von Merge einer Tabelle mit der
+ // der vorherigen, wenn dahinter auch noch eine steht
+ // falls aber der Node in einer Tabelle steht, muss
+ // natuerlich dieser returnt werden, wenn der SttNode eine
+ // Section oder Tabelle ist!
+ SwTableNode* pTblNd;
+ if( pSttNd->IsTableNode() &&
+ 0 != ( pTblNd = pFrmNd->FindTableNode() ) &&
+ // TABLE IN TABLE:
+ pTblNd != pSttNd->StartOfSectionNode()->FindTableNode() )
+ {
+ pFrmNd = pTblNd;
+ rFrmIdx = *pFrmNd;
+ }
+ else
+ rFrmIdx = aIdx;
+ }
+ else if( pNd->IsEndNode() && pNd->StartOfSectionNode()->IsTableNode() )
+ {
+ pFrmNd = pNd->StartOfSectionNode();
+ rFrmIdx = *pFrmNd;
+ }
+ else
+ {
+ if( pEnd )
+ aIdx = pEnd->GetIndex() + 1;
+ else
+ aIdx = rFrmIdx.GetIndex() + 1;
+
+ if( (pFrmNd = &aIdx.GetNode())->IsTableNode() )
+ rFrmIdx = aIdx;
+ else
+ {
+ pFrmNd = 0;
+
+ // is there some sectionnodes before a tablenode?
+ while( aIdx.GetNode().IsSectionNode() )
+ {
+ const SwSection& rSect = aIdx.GetNode().
+ GetSectionNode()->GetSection();
+ if( rSect.IsHiddenFlag() )
+ aIdx = aIdx.GetNode().EndOfSectionIndex()+1;
+ else
+ aIdx++;
+ }
+ if( aIdx.GetNode().IsTableNode() )
+ {
+ rFrmIdx = aIdx;
+ pFrmNd = &aIdx.GetNode();
+ }
+ }
+ }
+ }
+ }
+ }
+ return pFrmNd;
+}
+
+void SwNodes::ForEach( const SwNodeIndex& rStart, const SwNodeIndex& rEnd,
+ FnForEach_SwNodes fnForEach, void* pArgs )
+{
+ BigPtrArray::ForEach( rStart.GetIndex(), rEnd.GetIndex(),
+ (FnForEach) fnForEach, pArgs );
+}
+
+struct _TempBigPtrEntry : public BigPtrEntry
+{
+ _TempBigPtrEntry() {}
+};
+
+
+void SwNodes::RemoveNode( sal_uLong nDelPos, sal_uLong nSz, sal_Bool bDel )
+{
+ sal_uLong nEnd = nDelPos + nSz;
+ SwNode* pNew = (*this)[ nEnd ];
+
+ if( pRoot )
+ {
+ SwNodeIndex *p = pRoot;
+ while( p )
+ {
+ sal_uLong nIdx = p->GetIndex();
+ SwNodeIndex* pNext = p->pNext;
+ if( nDelPos <= nIdx && nIdx < nEnd )
+ (*p) = *pNew;
+
+ p = pNext;
+ }
+
+ p = pRoot->pPrev;
+ while( p )
+ {
+ sal_uLong nIdx = p->GetIndex();
+ SwNodeIndex* pPrev = p->pPrev;
+ if( nDelPos <= nIdx && nIdx < nEnd )
+ (*p) = *pNew;
+
+ p = pPrev;
+ }
+ }
+
+ {
+ for (sal_uLong nCnt = 0; nCnt < nSz; nCnt++)
+ {
+ SwTxtNode * pTxtNd = ((*this)[ nDelPos + nCnt ])->GetTxtNode();
+
+ if (pTxtNd)
+ {
+ pTxtNd->RemoveFromList();
+ }
+ }
+ }
+
+ if( bDel )
+ {
+ sal_uLong nCnt = nSz;
+ SwNode *pDel = (*this)[ nDelPos+nCnt-1 ], *pPrev = (*this)[ nDelPos+nCnt-2 ];
+
+// temp. Object setzen
+ //JP 24.08.98: muessten eigentlich einzeln removed werden, weil
+ // das Remove auch rekursiv gerufen werden kann, z.B. bei
+ // zeichengebundenen Rahmen. Da aber dabei viel zu viel
+ // ablaueft, wird hier ein temp. Objekt eingefuegt, das
+ // dann mit dem Remove wieder entfernt wird.
+ // siehe Bug 55406
+ _TempBigPtrEntry aTempEntry;
+ BigPtrEntry* pTempEntry = &aTempEntry;
+
+ while( nCnt-- )
+ {
+ delete pDel;
+ pDel = pPrev;
+ sal_uLong nPrevNdIdx = pPrev->GetIndex();
+ BigPtrArray::Replace( nPrevNdIdx+1, pTempEntry );
+ if( nCnt )
+ pPrev = (*this)[ nPrevNdIdx - 1 ];
+ }
+ nDelPos = pDel->GetIndex() + 1;
+ }
+
+ BigPtrArray::Remove( nDelPos, nSz );
+}
+
+void SwNodes::RegisterIndex( SwNodeIndex& rIdx )
+{
+ if( !pRoot ) // noch keine Root gesetzt?
+ {
+ pRoot = &rIdx;
+ pRoot->pPrev = 0;
+ pRoot->pNext = 0;
+ }
+ else
+ {
+ // immer hinter die Root haengen
+ rIdx.pNext = pRoot->pNext;
+ pRoot->pNext = &rIdx;
+ rIdx.pPrev = pRoot;
+ if( rIdx.pNext )
+ rIdx.pNext->pPrev = &rIdx;
+ }
+}
+
+void SwNodes::DeRegisterIndex( SwNodeIndex& rIdx )
+{
+ SwNodeIndex* pN = rIdx.pNext;
+ SwNodeIndex* pP = rIdx.pPrev;
+
+ if( pRoot == &rIdx )
+ pRoot = pP ? pP : pN;
+
+ if( pP )
+ pP->pNext = pN;
+ if( pN )
+ pN->pPrev = pP;
+
+ rIdx.pNext = 0;
+ rIdx.pPrev = 0;
+}
+
+void SwNodes::InsertNode( const SwNodePtr pNode,
+ const SwNodeIndex& rPos )
+{
+ const ElementPtr pIns = pNode;
+ BigPtrArray::Insert( pIns, rPos.GetIndex() );
+}
+
+void SwNodes::InsertNode( const SwNodePtr pNode,
+ sal_uLong nPos )
+{
+ const ElementPtr pIns = pNode;
+ BigPtrArray::Insert( pIns, nPos );
+}
+
+// ->#112139#
+SwNode * SwNodes::DocumentSectionStartNode(SwNode * pNode) const
+{
+ if (NULL != pNode)
+ {
+ SwNodeIndex aIdx(*pNode);
+
+ if (aIdx <= (*this)[0]->EndOfSectionIndex())
+ pNode = (*this)[0];
+ else
+ {
+ while ((*this)[0] != pNode->StartOfSectionNode())
+ pNode = pNode->StartOfSectionNode();
+ }
+ }
+
+ return pNode;
+}
+
+SwNode * SwNodes::DocumentSectionEndNode(SwNode * pNode) const
+{
+ return DocumentSectionStartNode(pNode)->EndOfSectionNode();
+}
+
+sal_Bool SwNodes::IsDocNodes() const
+{
+ return this == &pMyDoc->GetNodes();
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/docnode/observablethread.cxx b/sw/source/core/docnode/observablethread.cxx
new file mode 100644
index 000000000000..cafeb9b610b1
--- /dev/null
+++ b/sw/source/core/docnode/observablethread.cxx
@@ -0,0 +1,100 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+#include "precompiled_sw.hxx"
+#include <observablethread.hxx>
+
+#include <boost/shared_ptr.hpp>
+
+/** class for an observable thread
+
+ #i73788#
+
+ @author OD
+*/
+ObservableThread::ObservableThread()
+ : mnRefCount( 0 ),
+ mnThreadID( 0 ),
+ mpThreadListener()
+{
+}
+
+ObservableThread::~ObservableThread()
+{
+}
+
+oslInterlockedCount ObservableThread::acquire()
+{
+ return osl_incrementInterlockedCount( &mnRefCount );
+}
+
+oslInterlockedCount ObservableThread::release()
+{
+ oslInterlockedCount nCount( osl_decrementInterlockedCount( &mnRefCount ) );
+ if ( nCount == 0 )
+ {
+ delete this;
+ return nCount;
+ }
+
+ return nCount;
+}
+
+void ObservableThread::SetListener( boost::weak_ptr< IFinishedThreadListener > pThreadListener,
+ const oslInterlockedCount nThreadID )
+{
+ mpThreadListener = pThreadListener;
+ mnThreadID = nThreadID;
+}
+
+void SAL_CALL ObservableThread::run()
+{
+ acquire();
+
+ threadFunction();
+}
+
+void SAL_CALL ObservableThread::onTerminated()
+{
+ threadFinished();
+
+ // notify observer
+ boost::shared_ptr< IFinishedThreadListener > pThreadListener = mpThreadListener.lock();
+ if ( pThreadListener )
+ {
+ pThreadListener->NotifyAboutFinishedThread( mnThreadID );
+ }
+
+ release();
+}
+
+void ObservableThread::threadFinished()
+{
+ // empty default implementation
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/docnode/pausethreadstarting.cxx b/sw/source/core/docnode/pausethreadstarting.cxx
new file mode 100644
index 000000000000..df4a060dea67
--- /dev/null
+++ b/sw/source/core/docnode/pausethreadstarting.cxx
@@ -0,0 +1,58 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+#include "precompiled_sw.hxx"
+#include <pausethreadstarting.hxx>
+#include <swthreadmanager.hxx>
+
+/** Helper class to pause starting of threads during existence of an instance
+ of this class
+
+ #i73788#
+
+ @author OD
+*/
+SwPauseThreadStarting::SwPauseThreadStarting()
+ : mbPausedThreadStarting( false )
+{
+ if ( SwThreadManager::ExistsThreadManager() &&
+ !SwThreadManager::GetThreadManager().StartingOfThreadsSuspended() )
+ {
+ SwThreadManager::GetThreadManager().SuspendStartingOfThreads();
+ mbPausedThreadStarting = true;
+ }
+}
+
+SwPauseThreadStarting::~SwPauseThreadStarting()
+{
+ if ( mbPausedThreadStarting )
+ {
+ SwThreadManager::GetThreadManager().ResumeStartingOfThreads();
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/docnode/retrievedinputstreamdata.cxx b/sw/source/core/docnode/retrievedinputstreamdata.cxx
new file mode 100644
index 000000000000..78bf5b144e05
--- /dev/null
+++ b/sw/source/core/docnode/retrievedinputstreamdata.cxx
@@ -0,0 +1,169 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+#include "precompiled_sw.hxx"
+#include <retrievedinputstreamdata.hxx>
+#include <retrieveinputstreamconsumer.hxx>
+#include <vcl/svapp.hxx>
+
+/** implementation of class <SwRetrievedInputStreamDataManager>
+
+ #i73788#
+*/
+SwRetrievedInputStreamDataManager* SwRetrievedInputStreamDataManager::mpManager = 0;
+SwRetrievedInputStreamDataManager::tDataKey SwRetrievedInputStreamDataManager::mnNextKeyValue = 1;
+osl::Mutex SwRetrievedInputStreamDataManager::maGetManagerMutex;
+
+SwRetrievedInputStreamDataManager& SwRetrievedInputStreamDataManager::GetManager()
+{
+ osl::MutexGuard aGuard(maGetManagerMutex);
+
+ if ( mpManager == 0 )
+ {
+ mpManager = new SwRetrievedInputStreamDataManager();
+ }
+
+ return *mpManager;
+}
+
+SwRetrievedInputStreamDataManager::tDataKey SwRetrievedInputStreamDataManager::ReserveData(
+ boost::weak_ptr< SwAsyncRetrieveInputStreamThreadConsumer > pThreadConsumer )
+{
+ osl::MutexGuard aGuard(maMutex);
+
+ // create empty data container for given thread Consumer
+ tDataKey nDataKey( mnNextKeyValue );
+ tData aNewEntry( pThreadConsumer );
+ maInputStreamData[ nDataKey ] = aNewEntry;
+
+ // prepare next data key value
+ if ( mnNextKeyValue < SAL_MAX_UINT64 )
+ {
+ ++mnNextKeyValue;
+ }
+ else
+ {
+ mnNextKeyValue = 1;
+ }
+
+ return nDataKey;
+}
+
+void SwRetrievedInputStreamDataManager::PushData(
+ const tDataKey nDataKey,
+ com::sun::star::uno::Reference<com::sun::star::io::XInputStream> xInputStream,
+ const sal_Bool bIsStreamReadOnly )
+{
+ osl::MutexGuard aGuard(maMutex);
+
+ std::map< tDataKey, tData >::iterator aIter = maInputStreamData.find( nDataKey );
+
+ if ( aIter != maInputStreamData.end() )
+ {
+ // Fill data container.
+ (*aIter).second.mxInputStream = xInputStream;
+ (*aIter).second.mbIsStreamReadOnly = bIsStreamReadOnly;
+
+ // post user event to process the retrieved input stream data
+ if ( GetpApp() )
+ {
+
+ tDataKey* pDataKey = new tDataKey;
+ *pDataKey = nDataKey;
+ GetpApp()->PostUserEvent( LINK( this, SwRetrievedInputStreamDataManager, LinkedInputStreamReady ), pDataKey );
+ }
+ else
+ {
+ // no application available -> discard data
+ maInputStreamData.erase( aIter );
+ }
+ }
+}
+
+bool SwRetrievedInputStreamDataManager::PopData( const tDataKey nDataKey,
+ tData& rData )
+{
+ osl::MutexGuard aGuard(maMutex);
+
+ bool bDataProvided( false );
+
+ std::map< tDataKey, tData >::iterator aIter = maInputStreamData.find( nDataKey );
+
+ if ( aIter != maInputStreamData.end() )
+ {
+ rData.mpThreadConsumer = (*aIter).second.mpThreadConsumer;
+ rData.mxInputStream = (*aIter).second.mxInputStream;
+ rData.mbIsStreamReadOnly = (*aIter).second.mbIsStreamReadOnly;
+
+ maInputStreamData.erase( aIter );
+
+ bDataProvided = true;
+ }
+
+ return bDataProvided;
+}
+
+/** callback function, which is triggered by input stream data manager on
+ filling of the data container to provide retrieved input stream to the
+ thread Consumer using <Application::PostUserEvent(..)>
+
+ #i73788#
+ Note: This method has to be run in the main thread.
+
+ @author OD
+*/
+IMPL_LINK( SwRetrievedInputStreamDataManager,
+ LinkedInputStreamReady,
+ SwRetrievedInputStreamDataManager::tDataKey*,
+ pDataKey )
+{
+ if ( !pDataKey )
+ {
+ return 0;
+ }
+
+ osl::MutexGuard aGuard(maMutex);
+
+ SwRetrievedInputStreamDataManager& rDataManager =
+ SwRetrievedInputStreamDataManager::GetManager();
+ SwRetrievedInputStreamDataManager::tData aInputStreamData;
+ if ( rDataManager.PopData( *pDataKey, aInputStreamData ) )
+ {
+ boost::shared_ptr< SwAsyncRetrieveInputStreamThreadConsumer > pThreadConsumer =
+ aInputStreamData.mpThreadConsumer.lock();
+ if ( pThreadConsumer )
+ {
+ pThreadConsumer->ApplyInputStream( aInputStreamData.mxInputStream,
+ aInputStreamData.mbIsStreamReadOnly );
+ }
+ }
+ delete pDataKey;
+
+ return 0;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/docnode/retrieveinputstream.cxx b/sw/source/core/docnode/retrieveinputstream.cxx
new file mode 100644
index 000000000000..848c5769621c
--- /dev/null
+++ b/sw/source/core/docnode/retrieveinputstream.cxx
@@ -0,0 +1,87 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+#include "precompiled_sw.hxx"
+#include <retrieveinputstream.hxx>
+#include <comphelper/mediadescriptor.hxx>
+#include <com/sun/star/io/XStream.hpp>
+
+/** class for a thread to retrieve an input stream given by an URL
+
+ #i73788#
+
+ @author OD
+*/
+::rtl::Reference< ObservableThread > SwAsyncRetrieveInputStreamThread::createThread(
+ const SwRetrievedInputStreamDataManager::tDataKey nDataKey,
+ const String& rLinkedURL )
+{
+ SwAsyncRetrieveInputStreamThread* pNewThread =
+ new SwAsyncRetrieveInputStreamThread( nDataKey, rLinkedURL );
+ return pNewThread;
+}
+
+SwAsyncRetrieveInputStreamThread::SwAsyncRetrieveInputStreamThread(
+ const SwRetrievedInputStreamDataManager::tDataKey nDataKey,
+ const String& rLinkedURL )
+ : ObservableThread(),
+ mnDataKey( nDataKey ),
+ mrLinkedURL( rLinkedURL )
+{
+}
+
+SwAsyncRetrieveInputStreamThread::~SwAsyncRetrieveInputStreamThread()
+{
+}
+
+void SwAsyncRetrieveInputStreamThread::threadFunction()
+{
+ com::sun::star::uno::Sequence < com::sun::star::beans::PropertyValue > xProps( 1 );
+ xProps[0].Name = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("URL"));
+ xProps[0].Value <<= ::rtl::OUString( mrLinkedURL );
+ comphelper::MediaDescriptor aMedium( xProps );
+
+ aMedium.addInputStream();
+
+ com::sun::star::uno::Reference<com::sun::star::io::XInputStream> xInputStream;
+ aMedium[comphelper::MediaDescriptor::PROP_INPUTSTREAM()] >>= xInputStream;
+ if ( !xInputStream.is() )
+ {
+ com::sun::star::uno::Reference<com::sun::star::io::XStream> xStream;
+ aMedium[comphelper::MediaDescriptor::PROP_STREAM()] >>= xStream;
+ if ( xStream.is() )
+ {
+ xInputStream = xStream->getInputStream();
+ }
+ }
+
+ SwRetrievedInputStreamDataManager::GetManager().PushData( mnDataKey,
+ xInputStream,
+ aMedium.isStreamReadOnly() );
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/docnode/retrieveinputstreamconsumer.cxx b/sw/source/core/docnode/retrieveinputstreamconsumer.cxx
new file mode 100644
index 000000000000..82ae987f43f5
--- /dev/null
+++ b/sw/source/core/docnode/retrieveinputstreamconsumer.cxx
@@ -0,0 +1,74 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+#include "precompiled_sw.hxx"
+#include <retrieveinputstreamconsumer.hxx>
+#include <ndgrf.hxx>
+#include <retrieveinputstream.hxx>
+#include <swthreadmanager.hxx>
+
+/** class to provide creation of a thread to retrieve an input stream given by
+ an URL and to consume the retrieved input stream.
+
+ #i73788#
+
+ @author OD
+*/
+SwAsyncRetrieveInputStreamThreadConsumer::SwAsyncRetrieveInputStreamThreadConsumer(
+ SwGrfNode& rGrfNode )
+ : mrGrfNode( rGrfNode ),
+ mnThreadID( 0 )
+{
+}
+
+SwAsyncRetrieveInputStreamThreadConsumer::~SwAsyncRetrieveInputStreamThreadConsumer()
+{
+ SwThreadManager::GetThreadManager().RemoveThread( mnThreadID );
+}
+
+void SwAsyncRetrieveInputStreamThreadConsumer::CreateThread( const String& rURL )
+{
+ // Get new data container for input stream data
+ SwRetrievedInputStreamDataManager::tDataKey nDataKey =
+ SwRetrievedInputStreamDataManager::GetManager().ReserveData(
+ mrGrfNode.GetThreadConsumer() );
+
+ rtl::Reference< ObservableThread > pNewThread =
+ SwAsyncRetrieveInputStreamThread::createThread( nDataKey, rURL );
+
+ // Add thread to thread manager and pass ownership of thread to thread manager.
+ mnThreadID = SwThreadManager::GetThreadManager().AddThread( pNewThread );
+}
+
+void SwAsyncRetrieveInputStreamThreadConsumer::ApplyInputStream(
+ com::sun::star::uno::Reference<com::sun::star::io::XInputStream> xInputStream,
+ const sal_Bool bIsStreamReadOnly )
+{
+ mrGrfNode.ApplyInputStream( xInputStream, bIsStreamReadOnly );
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/docnode/section.cxx b/sw/source/core/docnode/section.cxx
new file mode 100644
index 000000000000..a5bcf822af03
--- /dev/null
+++ b/sw/source/core/docnode/section.cxx
@@ -0,0 +1,1777 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+#include <stdlib.h>
+#include <hintids.hxx>
+#include <svl/intitem.hxx>
+#include <svl/stritem.hxx>
+#include <sfx2/docfile.hxx>
+#include <sfx2/docfilt.hxx>
+#include <editeng/protitem.hxx>
+#include <sfx2/linkmgr.hxx>
+#include <tools/urlobj.hxx>
+#include <sfx2/sfxsids.hrc>
+#include <sfx2/fcontnr.hxx>
+#include <docary.hxx>
+#include <fmtcntnt.hxx>
+#include <fmtpdsc.hxx>
+#include <doc.hxx>
+#include <IDocumentUndoRedo.hxx>
+#include <node.hxx>
+#include <pam.hxx>
+#include <frmtool.hxx>
+#include <editsh.hxx>
+#include <hints.hxx>
+#include <docsh.hxx>
+#include <ndtxt.hxx>
+#include <section.hxx>
+#include <swserv.hxx>
+#include <shellio.hxx>
+#include <poolfmt.hxx>
+#include <expfld.hxx>
+#include <swbaslnk.hxx>
+#include <mvsave.hxx>
+#include <sectfrm.hxx>
+#include <fmtftntx.hxx>
+#include <ftnidx.hxx>
+#include <doctxm.hxx>
+#include <fmteiro.hxx>
+#include <swerror.h>
+#include <unosection.hxx>
+#include <switerator.hxx>
+#include <svl/smplhint.hxx>
+
+using namespace ::com::sun::star;
+
+
+SV_IMPL_REF( SwServerObject )
+
+#define sSectionFmtNm aEmptyStr
+
+class SwIntrnlSectRefLink : public SwBaseLink
+{
+ SwSectionFmt& rSectFmt;
+public:
+ SwIntrnlSectRefLink( SwSectionFmt& rFmt, sal_uInt16 nUpdateType, sal_uInt16 nFmt )
+ : SwBaseLink( nUpdateType, nFmt ),
+ rSectFmt( rFmt )
+ {}
+
+ virtual void Closed();
+ virtual void DataChanged( const String& rMimeType,
+ const uno::Any & rValue );
+
+ virtual const SwNode* GetAnchor() const;
+ virtual sal_Bool IsInRange( sal_uLong nSttNd, sal_uLong nEndNd, xub_StrLen nStt = 0,
+ xub_StrLen nEnd = STRING_NOTFOUND ) const;
+
+ inline SwSectionNode* GetSectNode()
+ {
+ const SwNode* pSectNd( const_cast<SwIntrnlSectRefLink*>(this)->GetAnchor() );
+ return const_cast<SwSectionNode*>( dynamic_cast<const SwSectionNode*>( pSectNd ) );
+ }
+};
+
+
+TYPEINIT1(SwSectionFmt,SwFrmFmt );
+TYPEINIT1(SwSection,SwClient );
+
+typedef SwSection* SwSectionPtr;
+
+SV_IMPL_PTRARR( SwSections, SwSection*)
+SV_IMPL_PTRARR(SwSectionFmts,SwSectionFmt*)
+
+
+SwSectionData::SwSectionData(SectionType const eType, String const& rName)
+ : m_eType(eType)
+ , m_sSectionName(rName)
+ , m_bHiddenFlag(false)
+ , m_bProtectFlag(false)
+ , m_bEditInReadonlyFlag(false) // edit in readonly sections
+ , m_bHidden(false)
+ , m_bCondHiddenFlag(true)
+ , m_bConnectFlag(true)
+{
+}
+
+// this must have the same semantics as operator=()
+SwSectionData::SwSectionData(SwSection const& rSection)
+ : m_eType(rSection.GetType())
+ , m_sSectionName(rSection.GetSectionName())
+ , m_sCondition(rSection.GetCondition())
+ , m_sLinkFileName(rSection.GetLinkFileName())
+ , m_sLinkFilePassword(rSection.GetLinkFilePassword())
+ , m_Password(rSection.GetPassword())
+ , m_bHiddenFlag(rSection.IsHiddenFlag())
+ , m_bProtectFlag(rSection.IsProtect())
+ // edit in readonly sections
+ , m_bEditInReadonlyFlag(rSection.IsEditInReadonly())
+ , m_bHidden(rSection.IsHidden())
+ , m_bCondHiddenFlag(true)
+ , m_bConnectFlag(rSection.IsConnectFlag())
+{
+}
+
+// this must have the same semantics as operator=()
+SwSectionData::SwSectionData(SwSectionData const& rOther)
+ : m_eType(rOther.m_eType)
+ , m_sSectionName(rOther.m_sSectionName)
+ , m_sCondition(rOther.m_sCondition)
+ , m_sLinkFileName(rOther.m_sLinkFileName)
+ , m_sLinkFilePassword(rOther.m_sLinkFilePassword)
+ , m_Password(rOther.m_Password)
+ , m_bHiddenFlag(rOther.m_bHiddenFlag)
+ , m_bProtectFlag(rOther.m_bProtectFlag)
+ // edit in readonly sections
+ , m_bEditInReadonlyFlag(rOther.m_bEditInReadonlyFlag)
+ , m_bHidden(rOther.m_bHidden)
+ , m_bCondHiddenFlag(true)
+ , m_bConnectFlag(rOther.m_bConnectFlag)
+{
+}
+
+// the semantics here are weird for reasons of backward compatibility
+SwSectionData & SwSectionData::operator= (SwSectionData const& rOther)
+{
+ m_eType = rOther.m_eType;
+ m_sSectionName = rOther.m_sSectionName;
+ m_sCondition = rOther.m_sCondition;
+ m_sLinkFileName = rOther.m_sLinkFileName;
+ m_sLinkFilePassword = rOther.m_sLinkFilePassword;
+ m_bConnectFlag = rOther.m_bConnectFlag;
+ m_Password = rOther.m_Password;
+
+ m_bEditInReadonlyFlag = rOther.m_bEditInReadonlyFlag;
+ m_bProtectFlag = rOther.m_bProtectFlag;
+
+ m_bHidden = rOther.m_bHidden;
+ // FIXME: old code did not assign m_bHiddenFlag ?
+ // FIXME: why should m_bCondHiddenFlag always default to true?
+ m_bCondHiddenFlag = true;
+
+ return *this;
+}
+
+// the semantics here are weird for reasons of backward compatibility
+bool SwSectionData::operator==(SwSectionData const& rOther) const
+{
+ return (m_eType == rOther.m_eType)
+ && (m_sSectionName == rOther.m_sSectionName)
+ && (m_sCondition == rOther.m_sCondition)
+ && (m_bHidden == rOther.m_bHidden)
+ && (m_bProtectFlag == rOther.m_bProtectFlag)
+ && (m_bEditInReadonlyFlag == rOther.m_bEditInReadonlyFlag)
+ && (m_sLinkFileName == rOther.m_sLinkFileName)
+ && (m_sLinkFilePassword == rOther.m_sLinkFilePassword)
+ && (m_Password == rOther.m_Password);
+ // FIXME: old code ignored m_bCondHiddenFlag m_bHiddenFlag m_bConnectFlag
+}
+
+// SwSection ===========================================================
+
+SwSection::SwSection(
+ SectionType const eType, String const& rName, SwSectionFmt & rFormat)
+ : SwClient(& rFormat)
+ , m_Data(eType, rName)
+{
+ SwSection *const pParentSect = GetParent();
+ if( pParentSect )
+ {
+ if( pParentSect->IsHiddenFlag() )
+ {
+ SetHidden( true );
+ }
+
+ m_Data.SetProtectFlag( pParentSect->IsProtectFlag() );
+ // edit in readonly sections
+ m_Data.SetEditInReadonlyFlag( pParentSect->IsEditInReadonlyFlag() );
+ }
+
+ if (!m_Data.IsProtectFlag())
+ {
+ m_Data.SetProtectFlag( rFormat.GetProtect().IsCntntProtected() );
+ }
+
+ if (!m_Data.IsEditInReadonlyFlag()) // edit in readonly sections
+ {
+ m_Data.SetEditInReadonlyFlag( rFormat.GetEditInReadonly().GetValue() );
+ }
+}
+
+
+SwSection::~SwSection()
+{
+ SwSectionFmt* pFmt = GetFmt();
+ if( !pFmt )
+ return;
+
+ SwDoc* pDoc = pFmt->GetDoc();
+ if( pDoc->IsInDtor() )
+ {
+ // dann melden wir noch schnell unser Format um ans dflt FrameFmt,
+ // damit es keine Abhaengigkeiten gibt
+ if( pFmt->DerivedFrom() != pDoc->GetDfltFrmFmt() )
+ pFmt->RegisterToFormat( *pDoc->GetDfltFrmFmt() );
+ }
+ else
+ {
+ pFmt->Remove( this ); // austragen,
+
+ if (CONTENT_SECTION != m_Data.GetType())
+ {
+ pDoc->GetLinkManager().Remove( m_RefLink );
+ }
+
+ if (m_RefObj.Is())
+ {
+ pDoc->GetLinkManager().RemoveServer( &m_RefObj );
+ }
+
+ // ist die Section der letzte Client im Format, kann dieses
+ // geloescht werden
+ SwPtrMsgPoolItem aMsgHint( RES_REMOVE_UNO_OBJECT, pFmt );
+ pFmt->ModifyNotification( &aMsgHint, &aMsgHint );
+ if( !pFmt->GetDepends() )
+ {
+ // Bug: 28191 - nicht ins Undo aufnehmen, sollte schon vorher
+ // geschehen sein!!
+ ::sw::UndoGuard const undoGuard(pDoc->GetIDocumentUndoRedo());
+ pDoc->DelSectionFmt( pFmt ); // und loeschen
+ }
+ }
+ if (m_RefObj.Is())
+ {
+ m_RefObj->Closed();
+ }
+}
+
+void SwSection::SetSectionData(SwSectionData const& rData)
+{
+ bool const bOldHidden( m_Data.IsHidden() );
+ m_Data = rData;
+ // next 2 may actually overwrite m_Data.m_b{Protect,EditInReadonly}Flag
+ // in Modify, which should result in same flag value as the old code!
+ SetProtect(m_Data.IsProtectFlag());
+ SetEditInReadonly(m_Data.IsEditInReadonlyFlag());
+ if (bOldHidden != m_Data.IsHidden()) // check if changed...
+ {
+ ImplSetHiddenFlag(m_Data.IsHidden(), m_Data.IsCondHidden());
+ }
+}
+
+bool SwSection::DataEquals(SwSectionData const& rCmp) const
+{
+ // note that the old code compared the flags of the parameter with the
+ // format attributes of this; the following mess should do the same...
+ (void) GetLinkFileName(); // updates m_sLinkFileName
+ bool const bProtect(m_Data.IsProtectFlag());
+ bool const bEditInReadonly(m_Data.IsEditInReadonlyFlag());
+ const_cast<SwSection*>(this)->m_Data.SetProtectFlag(IsProtect());
+ const_cast<SwSection*>(this)->m_Data
+ .SetEditInReadonlyFlag(IsEditInReadonly());
+ bool const bResult( m_Data == rCmp );
+ const_cast<SwSection*>(this)->m_Data.SetProtectFlag(bProtect);
+ const_cast<SwSection*>(this)->m_Data.SetEditInReadonlyFlag(bEditInReadonly);
+ return bResult;
+}
+
+
+void SwSection::ImplSetHiddenFlag(bool const bTmpHidden, bool const bCondition)
+{
+ SwSectionFmt* pFmt = GetFmt();
+ OSL_ENSURE(pFmt, "ImplSetHiddenFlag: no format?");
+ if( pFmt )
+ {
+ const bool bHide = bTmpHidden && bCondition;
+
+ if (bHide) // should be hidden
+ {
+ if (!m_Data.IsHiddenFlag()) // is not hidden
+ {
+ // wie sieht es mit dem Parent aus, ist der versteckt ?
+ // (eigentlich muesste das vom bHiddenFlag angezeigt werden!)
+
+ // erstmal allen Childs sagen, das sie versteckt sind
+ SwMsgPoolItem aMsgItem( RES_SECTION_HIDDEN );
+ pFmt->ModifyNotification( &aMsgItem, &aMsgItem );
+
+ // alle Frames loeschen
+ pFmt->DelFrms();
+ }
+ }
+ else if (m_Data.IsHiddenFlag()) // show Nodes again
+ {
+ // alle Frames sichtbar machen ( Childs Sections werden vom
+ // MakeFrms beruecksichtigt). Aber nur wenn die ParentSection
+ // nichts dagegen hat !
+ SwSection* pParentSect = pFmt->GetParentSection();
+ if( !pParentSect || !pParentSect->IsHiddenFlag() )
+ {
+ // erstmal allen Childs sagen, das der Parent nicht mehr
+ // versteckt ist
+ SwMsgPoolItem aMsgItem( RES_SECTION_NOT_HIDDEN );
+ pFmt->ModifyNotification( &aMsgItem, &aMsgItem );
+
+ pFmt->MakeFrms();
+ }
+ }
+ }
+}
+
+sal_Bool SwSection::CalcHiddenFlag() const
+{
+ const SwSection* pSect = this;
+ do {
+ if( pSect->IsHidden() && pSect->IsCondHidden() )
+ return sal_True;
+ } while( 0 != ( pSect = pSect->GetParent()) );
+
+ return sal_False;
+}
+
+bool SwSection::IsProtect() const
+{
+ SwSectionFmt *const pFmt( GetFmt() );
+ OSL_ENSURE(pFmt, "SwSection::IsProtect: no format?");
+ return (pFmt)
+ ? pFmt->GetProtect().IsCntntProtected()
+ : IsProtectFlag();
+}
+
+// edit in readonly sections
+bool SwSection::IsEditInReadonly() const
+{
+ SwSectionFmt *const pFmt( GetFmt() );
+ OSL_ENSURE(pFmt, "SwSection::IsEditInReadonly: no format?");
+ return (pFmt)
+ ? pFmt->GetEditInReadonly().GetValue()
+ : IsEditInReadonlyFlag();
+}
+
+void SwSection::SetHidden(bool const bFlag)
+{
+ if (!m_Data.IsHidden() == !bFlag)
+ return;
+
+ m_Data.SetHidden(bFlag);
+ ImplSetHiddenFlag(bFlag, m_Data.IsCondHidden());
+}
+
+
+void SwSection::SetProtect(bool const bFlag)
+{
+ SwSectionFmt *const pFormat( GetFmt() );
+ OSL_ENSURE(pFormat, "SwSection::SetProtect: no format?");
+ if (pFormat)
+ {
+ SvxProtectItem aItem( RES_PROTECT );
+ aItem.SetCntntProtect( (sal_Bool)bFlag );
+ pFormat->SetFmtAttr( aItem );
+ // note: this will call m_Data.SetProtectFlag via Modify!
+ }
+ else
+ {
+ m_Data.SetProtectFlag(bFlag);
+ }
+}
+
+// edit in readonly sections
+void SwSection::SetEditInReadonly(bool const bFlag)
+{
+ SwSectionFmt *const pFormat( GetFmt() );
+ OSL_ENSURE(pFormat, "SwSection::SetEditInReadonly: no format?");
+ if (pFormat)
+ {
+ SwFmtEditInReadonly aItem;
+ aItem.SetValue( (sal_Bool)bFlag );
+ pFormat->SetFmtAttr( aItem );
+ // note: this will call m_Data.SetEditInReadonlyFlag via Modify!
+ }
+ else
+ {
+ m_Data.SetEditInReadonlyFlag(bFlag);
+ }
+}
+
+void SwSection::Modify( const SfxPoolItem* pOld, const SfxPoolItem* pNew )
+{
+ bool bRemake = false;
+ bool bUpdateFtn = false;
+ switch( pOld ? pOld->Which() : pNew ? pNew->Which() : 0 )
+ {
+ case RES_ATTRSET_CHG:
+ {
+ SfxItemSet* pNewSet = ((SwAttrSetChg*)pNew)->GetChgSet();
+ SfxItemSet* pOldSet = ((SwAttrSetChg*)pOld)->GetChgSet();
+ const SfxPoolItem* pItem;
+
+ if( SFX_ITEM_SET == pNewSet->GetItemState(
+ RES_PROTECT, sal_False, &pItem ) )
+ {
+ m_Data.SetProtectFlag( static_cast<SvxProtectItem const*>(pItem)
+ ->IsCntntProtected() );
+ pNewSet->ClearItem( RES_PROTECT );
+ pOldSet->ClearItem( RES_PROTECT );
+ }
+
+ // --> edit in readonly sections
+ if( SFX_ITEM_SET == pNewSet->GetItemState(
+ RES_EDIT_IN_READONLY, sal_False, &pItem ) )
+ {
+ m_Data.SetEditInReadonlyFlag(
+ static_cast<SwFmtEditInReadonly const*>(pItem)->GetValue());
+ pNewSet->ClearItem( RES_EDIT_IN_READONLY );
+ pOldSet->ClearItem( RES_EDIT_IN_READONLY );
+ }
+ // <--
+
+ if( SFX_ITEM_SET == pNewSet->GetItemState(
+ RES_FTN_AT_TXTEND, sal_False, &pItem ) ||
+ SFX_ITEM_SET == pNewSet->GetItemState(
+ RES_END_AT_TXTEND, sal_False, &pItem ))
+ {
+ bUpdateFtn = true;
+ }
+
+ if( !pNewSet->Count() )
+ return;
+ }
+ break;
+
+ case RES_PROTECT:
+ if( pNew )
+ {
+ bool bNewFlag =
+ static_cast<const SvxProtectItem*>(pNew)->IsCntntProtected();
+ if( !bNewFlag )
+ {
+ // Abschalten: teste ob nicht vielleich ueber die Parents
+ // doch ein Schutzt besteht!
+ const SwSection* pSect = this;
+ do {
+ if( pSect->IsProtect() )
+ {
+ bNewFlag = true;
+ break;
+ }
+ pSect = pSect->GetParent();
+ } while (pSect);
+ }
+
+ m_Data.SetProtectFlag( bNewFlag );
+ }
+ return;
+ // edit in readonly sections
+ case RES_EDIT_IN_READONLY:
+ if( pNew )
+ {
+ const bool bNewFlag =
+ static_cast<const SwFmtEditInReadonly*>(pNew)->GetValue();
+ m_Data.SetEditInReadonlyFlag( bNewFlag );
+ }
+ return;
+
+ case RES_SECTION_HIDDEN:
+ m_Data.SetHiddenFlag(true);
+ return;
+
+ case RES_SECTION_NOT_HIDDEN:
+ case RES_SECTION_RESETHIDDENFLAG:
+ m_Data.SetHiddenFlag( m_Data.IsHidden() && m_Data.IsCondHidden() );
+ return;
+
+ case RES_COL:
+ /* wird ggf. vom Layout erledigt */
+ break;
+
+ case RES_FTN_AT_TXTEND:
+ if( pNew && pOld )
+ {
+ bUpdateFtn = true;
+ }
+ break;
+
+ case RES_END_AT_TXTEND:
+ if( pNew && pOld )
+ {
+ bUpdateFtn = true;
+ }
+ break;
+
+ default:
+ CheckRegistration( pOld, pNew );
+ break;
+ }
+
+ if( bRemake )
+ {
+ GetFmt()->DelFrms();
+ GetFmt()->MakeFrms();
+ }
+
+ if( bUpdateFtn )
+ {
+ SwSectionNode* pSectNd = GetFmt()->GetSectionNode( sal_False );
+ if( pSectNd )
+ pSectNd->GetDoc()->GetFtnIdxs().UpdateFtn(SwNodeIndex( *pSectNd ));
+ }
+}
+
+void SwSection::SetRefObject( SwServerObject* pObj )
+{
+ m_RefObj = pObj;
+}
+
+
+void SwSection::SetCondHidden(bool const bFlag)
+{
+ if (!m_Data.IsCondHidden() == !bFlag)
+ return;
+
+ m_Data.SetCondHidden(bFlag);
+ ImplSetHiddenFlag(m_Data.IsHidden(), bFlag);
+}
+
+
+// setze/erfrage den gelinkten FileNamen
+const String& SwSection::GetLinkFileName() const
+{
+ if (m_RefLink.Is())
+ {
+ String sTmp;
+ switch (m_Data.GetType())
+ {
+ case DDE_LINK_SECTION:
+ sTmp = m_RefLink->GetLinkSourceName();
+ break;
+
+ case FILE_LINK_SECTION:
+ {
+ String sRange, sFilter;
+ if (m_RefLink->GetLinkManager() &&
+ m_RefLink->GetLinkManager()->GetDisplayNames(
+ m_RefLink, 0, &sTmp, &sRange, &sFilter ))
+ {
+ ( sTmp += sfx2::cTokenSeperator ) += sFilter;
+ ( sTmp += sfx2::cTokenSeperator ) += sRange;
+ }
+ else if( GetFmt() && !GetFmt()->GetSectionNode() )
+ {
+ // ist die Section im UndoNodesArray, dann steht
+ // der Link nicht im LinkManager, kann also auch nicht
+ // erfragt werden. Dann returne den akt. Namen
+ return m_Data.GetLinkFileName();
+ }
+ }
+ break;
+ default: break;
+ }
+ const_cast<SwSection*>(this)->m_Data.SetLinkFileName(sTmp);
+ }
+ return m_Data.GetLinkFileName();
+}
+
+
+void SwSection::SetLinkFileName(const String& rNew, String const*const pPassWd)
+{
+ if (m_RefLink.Is())
+ {
+ m_RefLink->SetLinkSourceName( rNew );
+ }
+ m_Data.SetLinkFileName(rNew);
+ if( pPassWd )
+ {
+ SetLinkFilePassword( *pPassWd );
+ }
+}
+
+// falls es ein gelinkter Bereich war, dann muessen alle
+// Child-Verknuepfungen sichtbar bemacht werden.
+void SwSection::MakeChildLinksVisible( const SwSectionNode& rSectNd )
+{
+ const SwNode* pNd;
+ const ::sfx2::SvBaseLinks& rLnks = rSectNd.GetDoc()->GetLinkManager().GetLinks();
+ for( sal_uInt16 n = rLnks.Count(); n; )
+ {
+ ::sfx2::SvBaseLink* pBLnk = &(*rLnks[ --n ]);
+ if( pBLnk && !pBLnk->IsVisible() &&
+ pBLnk->ISA( SwBaseLink ) &&
+ 0 != ( pNd = ((SwBaseLink*)pBLnk)->GetAnchor() ) )
+ {
+ pNd = pNd->StartOfSectionNode(); // falls SectionNode ist!
+ const SwSectionNode* pParent;
+ while( 0 != ( pParent = pNd->FindSectionNode() ) &&
+ ( CONTENT_SECTION == pParent->GetSection().GetType()
+ || pNd == &rSectNd ))
+ pNd = pParent->StartOfSectionNode();
+
+ // steht nur noch in einer normalen Section, also
+ // wieder anzeigen
+ if( !pParent )
+ pBLnk->SetVisible( sal_True );
+ }
+ }
+}
+
+const SwTOXBase* SwSection::GetTOXBase() const
+{
+ const SwTOXBase* pRet = 0;
+ if( TOX_CONTENT_SECTION == GetType() )
+ pRet = PTR_CAST( SwTOXBaseSection, this );
+ return pRet;
+}
+
+// SwSectionFmt ========================================================
+
+SwSectionFmt::SwSectionFmt( SwSectionFmt* pDrvdFrm, SwDoc *pDoc )
+ : SwFrmFmt( pDoc->GetAttrPool(), sSectionFmtNm, pDrvdFrm )
+{
+ LockModify();
+ SetFmtAttr( *GetDfltAttr( RES_COL ) );
+ UnlockModify();
+}
+
+SwSectionFmt::~SwSectionFmt()
+{
+ if( !GetDoc()->IsInDtor() )
+ {
+ SwSectionNode* pSectNd;
+ const SwNodeIndex* pIdx = GetCntnt( sal_False ).GetCntntIdx();
+ if( pIdx && &GetDoc()->GetNodes() == &pIdx->GetNodes() &&
+ 0 != (pSectNd = pIdx->GetNode().GetSectionNode() ))
+ {
+ SwSection& rSect = pSectNd->GetSection();
+ // falls es ein gelinkter Bereich war, dann muessen alle
+ // Child-Verknuepfungen sichtbar bemacht werden.
+ if( rSect.IsConnected() )
+ rSect.MakeChildLinksVisible( *pSectNd );
+
+ // vorm loeschen der Nodes pruefe, ob wir uns nicht
+ // noch anzeigen muessen!
+ if( rSect.IsHiddenFlag() )
+ {
+ SwSectionPtr pParentSect = rSect.GetParent();
+ if( !pParentSect || !pParentSect->IsHiddenFlag() )
+ {
+ // Nodes wieder anzeigen
+ rSect.SetHidden(false);
+ }
+ }
+ // mba: test iteration; objects are removed while iterating
+ CallSwClientNotify( SfxSimpleHint(SFX_HINT_DYING) );
+
+ // hebe die Section doch mal auf
+ SwNodeRange aRg( *pSectNd, 0, *pSectNd->EndOfSectionNode() );
+ GetDoc()->GetNodes().SectionUp( &aRg );
+ }
+ LockModify();
+ ResetFmtAttr( RES_CNTNT );
+ UnlockModify();
+ }
+}
+
+
+SwSection * SwSectionFmt::GetSection() const
+{
+ return SwIterator<SwSection,SwSectionFmt>::FirstElement( *this );
+}
+
+extern void lcl_DeleteFtn( SwSectionNode *pNd, sal_uLong nStt, sal_uLong nEnd );
+
+//Vernichtet alle Frms in aDepend (Frms werden per PTR_CAST erkannt).
+void SwSectionFmt::DelFrms()
+{
+ SwSectionNode* pSectNd;
+ const SwNodeIndex* pIdx = GetCntnt(sal_False).GetCntntIdx();
+ if( pIdx && &GetDoc()->GetNodes() == &pIdx->GetNodes() &&
+ 0 != (pSectNd = pIdx->GetNode().GetSectionNode() ))
+ {
+ // #147431# : First delete the <SwSectionFrm> of the <SwSectionFmt> instance
+ // mba: test iteration as objects are removed in iteration
+ CallSwClientNotify( SfxSimpleHint(SFX_HINT_DYING) );
+
+ // Then delete frames of the nested <SwSectionFmt> instances
+ SwIterator<SwSectionFmt,SwSectionFmt> aIter( *this );
+ SwSectionFmt *pLast = aIter.First();
+ while ( pLast )
+ {
+ pLast->DelFrms();
+ pLast = aIter.Next();
+ }
+
+ sal_uLong nEnde = pSectNd->EndOfSectionIndex();
+ sal_uLong nStart = pSectNd->GetIndex()+1;
+ lcl_DeleteFtn( pSectNd, nStart, nEnde );
+ }
+ if( pIdx )
+ {
+ //Hint fuer Pagedesc versenden. Das mueste eigntlich das Layout im
+ //Paste der Frames selbst erledigen, aber das fuehrt dann wiederum
+ //zu weiteren Folgefehlern, die mit Laufzeitkosten geloest werden
+ //muesten.
+ SwNodeIndex aNextNd( *pIdx );
+ SwCntntNode* pCNd = GetDoc()->GetNodes().GoNextSection( &aNextNd, sal_True, sal_False );
+ if( pCNd )
+ {
+ const SfxPoolItem& rItem = pCNd->GetSwAttrSet().Get( RES_PAGEDESC );
+ pCNd->ModifyNotification( (SfxPoolItem*)&rItem, (SfxPoolItem*)&rItem );
+ }
+ }
+}
+
+
+//Erzeugt die Ansichten
+void SwSectionFmt::MakeFrms()
+{
+ SwSectionNode* pSectNd;
+ const SwNodeIndex* pIdx = GetCntnt(sal_False).GetCntntIdx();
+
+ if( pIdx && &GetDoc()->GetNodes() == &pIdx->GetNodes() &&
+ 0 != (pSectNd = pIdx->GetNode().GetSectionNode() ))
+ {
+ SwNodeIndex aIdx( *pIdx );
+ pSectNd->MakeFrms( &aIdx );
+ }
+}
+
+void SwSectionFmt::Modify( const SfxPoolItem* pOld, const SfxPoolItem* pNew )
+{
+ sal_Bool bClients = sal_False;
+ sal_uInt16 nWhich = pOld ? pOld->Which() : pNew ? pNew->Which() : 0;
+ switch( nWhich )
+ {
+ case RES_ATTRSET_CHG:
+ if( GetDepends() )
+ {
+ SfxItemSet* pNewSet = ((SwAttrSetChg*)pNew)->GetChgSet();
+ SfxItemSet* pOldSet = ((SwAttrSetChg*)pOld)->GetChgSet();
+ const SfxPoolItem *pItem;
+ if( SFX_ITEM_SET == pNewSet->GetItemState(
+ RES_PROTECT, sal_False, &pItem ))
+ {
+ ModifyBroadcast( (SfxPoolItem*)pItem, (SfxPoolItem*)pItem );
+ pNewSet->ClearItem( RES_PROTECT );
+ pOldSet->ClearItem( RES_PROTECT );
+ }
+
+ // --> edit in readonly sections
+ if( SFX_ITEM_SET == pNewSet->GetItemState(
+ RES_EDIT_IN_READONLY, sal_False, &pItem ) )
+ {
+ ModifyBroadcast( (SfxPoolItem*)pItem, (SfxPoolItem*)pItem );
+ pNewSet->ClearItem( RES_EDIT_IN_READONLY );
+ pOldSet->ClearItem( RES_EDIT_IN_READONLY );
+ }
+ // <--
+
+ if( SFX_ITEM_SET == pNewSet->GetItemState(
+ RES_FTN_AT_TXTEND, sal_False, &pItem ))
+ {
+ ModifyBroadcast( (SfxPoolItem*)&pOldSet->Get( RES_FTN_AT_TXTEND ), (SfxPoolItem*)pItem );
+ pNewSet->ClearItem( RES_FTN_AT_TXTEND );
+ pOldSet->ClearItem( RES_FTN_AT_TXTEND );
+ }
+ if( SFX_ITEM_SET == pNewSet->GetItemState(
+ RES_END_AT_TXTEND, sal_False, &pItem ))
+ {
+ ModifyBroadcast( (SfxPoolItem*)&pOldSet->Get( RES_END_AT_TXTEND ), (SfxPoolItem*)pItem );
+ pNewSet->ClearItem( RES_END_AT_TXTEND );
+ pOldSet->ClearItem( RES_END_AT_TXTEND );
+ }
+ if( !((SwAttrSetChg*)pOld)->GetChgSet()->Count() )
+ return;
+ }
+ break;
+
+ case RES_SECTION_RESETHIDDENFLAG:
+ case RES_FTN_AT_TXTEND:
+ case RES_END_AT_TXTEND : bClients = sal_True;
+ // no break !!
+ case RES_SECTION_HIDDEN:
+ case RES_SECTION_NOT_HIDDEN:
+ {
+ SwSection* pSect = GetSection();
+ if( pSect && ( bClients || ( RES_SECTION_HIDDEN == nWhich ?
+ !pSect->IsHiddenFlag() : pSect->IsHiddenFlag() ) ) )
+ {
+ ModifyBroadcast( pOld, pNew );
+ }
+ }
+ return ;
+
+
+ case RES_PROTECT:
+ case RES_EDIT_IN_READONLY: // edit in readonly sections
+ // diese Messages bis zum Ende des Baums durchreichen !
+ if( GetDepends() )
+ {
+ ModifyBroadcast( pOld, pNew );
+ }
+ return; // das wars
+
+ case RES_OBJECTDYING:
+ if( !GetDoc()->IsInDtor() &&
+ ((SwPtrMsgPoolItem *)pOld)->pObject == (void*)GetRegisteredIn() )
+ {
+ // mein Parent wird vernichtet, dann an den Parent vom Parent
+ // umhaengen und wieder aktualisieren
+ SwFrmFmt::Modify( pOld, pNew ); // erst umhaengen !!!
+ UpdateParent();
+ return;
+ }
+ break;
+
+ case RES_FMT_CHG:
+ if( !GetDoc()->IsInDtor() &&
+ ((SwFmtChg*)pNew)->pChangedFmt == (void*)GetRegisteredIn() &&
+ ((SwFmtChg*)pNew)->pChangedFmt->IsA( TYPE( SwSectionFmt )) )
+ {
+ // mein Parent wird veraendert, muss mich aktualisieren
+ SwFrmFmt::Modify( pOld, pNew ); // erst umhaengen !!!
+ UpdateParent();
+ return;
+ }
+ break;
+ }
+ SwFrmFmt::Modify( pOld, pNew );
+
+ if (pOld && (RES_REMOVE_UNO_OBJECT == pOld->Which()))
+ { // invalidate cached uno object
+ SetXTextSection(uno::Reference<text::XTextSection>(0));
+ }
+}
+
+ // erfrage vom Format Informationen
+sal_Bool SwSectionFmt::GetInfo( SfxPoolItem& rInfo ) const
+{
+ switch( rInfo.Which() )
+ {
+ case RES_FINDNEARESTNODE:
+ if( ((SwFmtPageDesc&)GetFmtAttr( RES_PAGEDESC )).GetPageDesc() )
+ {
+ const SwSectionNode* pNd = GetSectionNode();
+ if( pNd )
+ ((SwFindNearestNode&)rInfo).CheckNode( *pNd );
+ }
+ return sal_True;
+
+ case RES_CONTENT_VISIBLE:
+ {
+ SwFrm* pFrm = SwIterator<SwFrm,SwFmt>::FirstElement(*this);
+ // if the current section has no own frame search for the children
+ if(!pFrm)
+ {
+ SwIterator<SwSectionFmt,SwSectionFmt> aFormatIter(*this);
+ SwSectionFmt* pChild = aFormatIter.First();
+ while(pChild && !pFrm)
+ {
+ pFrm = SwIterator<SwFrm,SwFmt>::FirstElement(*pChild);
+ pChild = aFormatIter.Next();
+ }
+ }
+ ((SwPtrMsgPoolItem&)rInfo).pObject = pFrm;
+ }
+ return sal_False;
+ }
+ return SwModify::GetInfo( rInfo );
+}
+
+extern "C" {
+
+ int
+#if defined( WNT )
+ __cdecl
+#endif
+#if defined( ICC )
+ _Optlink
+#endif
+ lcl_SectionCmpPos( const void *pFirst, const void *pSecond)
+ {
+ const SwSectionFmt* pFSectFmt = (*(SwSectionPtr*)pFirst)->GetFmt();
+ const SwSectionFmt* pSSectFmt = (*(SwSectionPtr*)pSecond)->GetFmt();
+ OSL_ENSURE( pFSectFmt && pSSectFmt &&
+ pFSectFmt->GetCntnt(sal_False).GetCntntIdx() &&
+ pSSectFmt->GetCntnt(sal_False).GetCntntIdx(),
+ "ungueltige Sections" );
+ return (int)((long)pFSectFmt->GetCntnt(sal_False).GetCntntIdx()->GetIndex()) -
+ pSSectFmt->GetCntnt(sal_False).GetCntntIdx()->GetIndex();
+ }
+
+ int
+#if defined( WNT )
+ __cdecl
+#endif
+#if defined( ICC )
+ _Optlink
+#endif
+ lcl_SectionCmpNm( const void *pFirst, const void *pSecond)
+ {
+ const SwSectionPtr pFSect = *(SwSectionPtr*)pFirst;
+ const SwSectionPtr pSSect = *(SwSectionPtr*)pSecond;
+ OSL_ENSURE( pFSect && pSSect, "ungueltige Sections" );
+ StringCompare const eCmp =
+ pFSect->GetSectionName().CompareTo( pSSect->GetSectionName() );
+ return eCmp == COMPARE_EQUAL ? 0
+ : eCmp == COMPARE_LESS ? 1 : -1;
+ }
+}
+
+ // alle Sections, die von dieser abgeleitet sind
+sal_uInt16 SwSectionFmt::GetChildSections( SwSections& rArr,
+ SectionSort eSort,
+ sal_Bool bAllSections ) const
+{
+ rArr.Remove( 0, rArr.Count() );
+
+ if( GetDepends() )
+ {
+ SwIterator<SwSectionFmt,SwSectionFmt> aIter(*this);
+ const SwNodeIndex* pIdx;
+ for( SwSectionFmt* pLast = aIter.First(); pLast; pLast = aIter.Next() )
+ if( bAllSections ||
+ ( 0 != ( pIdx = pLast->GetCntnt(sal_False).
+ GetCntntIdx()) && &pIdx->GetNodes() == &GetDoc()->GetNodes() ))
+ {
+ const SwSection* Dummy = pLast->GetSection();
+ rArr.C40_INSERT( SwSection,
+ Dummy,
+ rArr.Count() );
+ }
+
+ // noch eine Sortierung erwuenscht ?
+ if( 1 < rArr.Count() )
+ switch( eSort )
+ {
+ case SORTSECT_NAME:
+ qsort( (void*)rArr.GetData(),
+ rArr.Count(),
+ sizeof( SwSectionPtr ),
+ lcl_SectionCmpNm );
+ break;
+
+ case SORTSECT_POS:
+ qsort( (void*)rArr.GetData(),
+ rArr.Count(),
+ sizeof( SwSectionPtr ),
+ lcl_SectionCmpPos );
+ break;
+ case SORTSECT_NOT: break;
+ }
+ }
+ return rArr.Count();
+}
+
+ // erfrage, ob sich die Section im Nodes-Array oder UndoNodes-Array
+ // befindet.
+sal_Bool SwSectionFmt::IsInNodesArr() const
+{
+ const SwNodeIndex* pIdx = GetCntnt(sal_False).GetCntntIdx();
+ return pIdx && &pIdx->GetNodes() == &GetDoc()->GetNodes();
+}
+
+
+void SwSectionFmt::UpdateParent() // Parent wurde veraendert
+{
+ if( !GetDepends() )
+ return;
+
+ SwSectionPtr pSection = 0;
+ const SvxProtectItem* pProtect(0);
+ // edit in readonly sections
+ const SwFmtEditInReadonly* pEditInReadonly = 0;
+ bool bIsHidden = false;
+
+ SwClientIter aIter( *this ); // TODO
+ ::SwClient * pLast = aIter.GoStart();
+ if( pLast ) // konnte zum Anfang gesprungen werden ??
+ do {
+ if( pLast->IsA( TYPE(SwSectionFmt) ) )
+ {
+ if( !pSection )
+ {
+ pSection = GetSection();
+ if( GetRegisteredIn() )
+ {
+ const SwSectionPtr pPS = GetParentSection();
+ pProtect = &pPS->GetFmt()->GetProtect();
+ // edit in readonly sections
+ pEditInReadonly = &pPS->GetFmt()->GetEditInReadonly();
+ bIsHidden = pPS->IsHiddenFlag();
+ }
+ else
+ {
+ pProtect = &GetProtect();
+ // edit in readonly sections
+ pEditInReadonly = &GetEditInReadonly();
+ bIsHidden = pSection->IsHidden();
+ }
+ }
+ if (!pProtect->IsCntntProtected() !=
+ !pSection->IsProtectFlag())
+ {
+ pLast->ModifyNotification( (SfxPoolItem*)pProtect,
+ (SfxPoolItem*)pProtect );
+ }
+
+ // edit in readonly sections
+ if (!pEditInReadonly->GetValue() !=
+ !pSection->IsEditInReadonlyFlag())
+ {
+ pLast->ModifyNotification( (SfxPoolItem*)pEditInReadonly,
+ (SfxPoolItem*)pEditInReadonly );
+ }
+
+ if( bIsHidden == pSection->IsHiddenFlag() )
+ {
+ SwMsgPoolItem aMsgItem( static_cast<sal_uInt16>(bIsHidden
+ ? RES_SECTION_HIDDEN
+ : RES_SECTION_NOT_HIDDEN ) );
+ pLast->ModifyNotification( &aMsgItem, &aMsgItem );
+ }
+ }
+ else if( !pSection &&
+ pLast->IsA( TYPE(SwSection) ) )
+ {
+ pSection = (SwSectionPtr)pLast;
+ if( GetRegisteredIn() )
+ {
+ const SwSectionPtr pPS = GetParentSection();
+ pProtect = &pPS->GetFmt()->GetProtect();
+ // edit in readonly sections
+ pEditInReadonly = &pPS->GetFmt()->GetEditInReadonly();
+ bIsHidden = pPS->IsHiddenFlag();
+ }
+ else
+ {
+ pProtect = &GetProtect();
+ // edit in readonly sections
+ pEditInReadonly = &GetEditInReadonly();
+ bIsHidden = pSection->IsHidden();
+ }
+ }
+ } while( 0 != ( pLast = aIter++ ));
+}
+
+
+SwSectionNode* SwSectionFmt::GetSectionNode(bool const bAlways)
+{
+ const SwNodeIndex* pIdx = GetCntnt(sal_False).GetCntntIdx();
+ if( pIdx && ( bAlways || &pIdx->GetNodes() == &GetDoc()->GetNodes() ))
+ return pIdx->GetNode().GetSectionNode();
+ return 0;
+}
+
+ // ist die Section eine gueltige fuers GlobalDocument?
+const SwSection* SwSectionFmt::GetGlobalDocSection() const
+{
+ const SwSectionNode* pNd = GetSectionNode();
+ if( pNd &&
+ ( FILE_LINK_SECTION == pNd->GetSection().GetType() ||
+ TOX_CONTENT_SECTION == pNd->GetSection().GetType() ) &&
+ pNd->GetIndex() > pNd->GetNodes().GetEndOfExtras().GetIndex() &&
+ !pNd->StartOfSectionNode()->IsSectionNode() &&
+ !pNd->StartOfSectionNode()->FindSectionNode() )
+ return &pNd->GetSection();
+ return 0;
+}
+
+// sw::Metadatable
+::sfx2::IXmlIdRegistry& SwSectionFmt::GetRegistry()
+{
+ return GetDoc()->GetXmlIdRegistry();
+}
+
+bool SwSectionFmt::IsInClipboard() const
+{
+ return GetDoc()->IsClipBoard();
+}
+
+bool SwSectionFmt::IsInUndo() const
+{
+ return !IsInNodesArr();
+}
+
+bool SwSectionFmt::IsInContent() const
+{
+ SwNodeIndex const*const pIdx = GetCntnt(sal_False).GetCntntIdx();
+ OSL_ENSURE(pIdx, "SwSectionFmt::IsInContent: no index?");
+ return (pIdx) ? !GetDoc()->IsInHeaderFooter(*pIdx) : true;
+}
+
+// n.b.: if the section format represents an index, then there is both a
+// SwXDocumentIndex and a SwXTextSection instance for this single core object.
+// these two can both implement XMetadatable and forward to the same core
+// section format. but here only one UNO object can be returned,
+// so always return the text section.
+uno::Reference< rdf::XMetadatable >
+SwSectionFmt::MakeUnoObject()
+{
+ uno::Reference<rdf::XMetadatable> xMeta;
+ SwSection *const pSection( GetSection() );
+ if (pSection)
+ {
+ xMeta.set( SwXTextSection::CreateXTextSection(this,
+ TOX_HEADER_SECTION == pSection->GetType()),
+ uno::UNO_QUERY );
+ }
+ return xMeta;
+}
+
+
+// Method to break section links inside a linked section
+void lcl_BreakSectionLinksInSect( const SwSectionNode& rSectNd )
+{
+ if ( !rSectNd.GetDoc() )
+ {
+ OSL_FAIL( "method <lcl_RemoveSectionLinksInSect(..)> - no Doc at SectionNode" );
+ return;
+ }
+
+ if ( !rSectNd.GetSection().IsConnected() )
+ {
+ OSL_FAIL( "method <lcl_RemoveSectionLinksInSect(..)> - no Link at Section of SectionNode" );
+ return;
+ }
+ const ::sfx2::SvBaseLink* pOwnLink( &(rSectNd.GetSection().GetBaseLink() ) );
+ const ::sfx2::SvBaseLinks& rLnks = rSectNd.GetDoc()->GetLinkManager().GetLinks();
+ for ( sal_uInt16 n = rLnks.Count(); n > 0; )
+ {
+ SwIntrnlSectRefLink* pSectLnk = dynamic_cast<SwIntrnlSectRefLink*>(&(*rLnks[ --n ]));
+ if ( pSectLnk && pSectLnk != pOwnLink &&
+ pSectLnk->IsInRange( rSectNd.GetIndex(), rSectNd.EndOfSectionIndex() ) )
+ {
+ // break the link of the corresponding section.
+ // the link is also removed from the link manager
+ pSectLnk->GetSectNode()->GetSection().BreakLink();
+
+ // for robustness, because link is removed from the link manager
+ if ( n > rLnks.Count() )
+ {
+ n = rLnks.Count();
+ }
+ }
+ }
+}
+
+void lcl_UpdateLinksInSect( SwBaseLink& rUpdLnk, SwSectionNode& rSectNd )
+{
+ SwDoc* pDoc = rSectNd.GetDoc();
+ SwDocShell* pDShell = pDoc->GetDocShell();
+ if( !pDShell || !pDShell->GetMedium() )
+ return ;
+
+ String sName( pDShell->GetMedium()->GetName() );
+ SwBaseLink* pBLink;
+ String sMimeType( SotExchange::GetFormatMimeType( FORMAT_FILE ));
+ uno::Any aValue;
+ aValue <<= ::rtl::OUString( sName ); // beliebiger Name
+
+ const ::sfx2::SvBaseLinks& rLnks = pDoc->GetLinkManager().GetLinks();
+ for( sal_uInt16 n = rLnks.Count(); n; )
+ {
+ ::sfx2::SvBaseLink* pLnk = &(*rLnks[ --n ]);
+ if( pLnk && pLnk != &rUpdLnk &&
+ OBJECT_CLIENT_FILE == pLnk->GetObjType() &&
+ pLnk->ISA( SwBaseLink ) &&
+ ( pBLink = (SwBaseLink*)pLnk )->IsInRange( rSectNd.GetIndex(),
+ rSectNd.EndOfSectionIndex() ) )
+ {
+ // liegt in dem Bereich: also updaten. Aber nur wenns nicht
+ // im gleichen File liegt
+ String sFName;
+ pDoc->GetLinkManager().GetDisplayNames( pBLink, 0, &sFName, 0, 0 );
+ if( sFName != sName )
+ {
+ pBLink->DataChanged( sMimeType, aValue );
+
+ // ggfs. neu den Link-Pointer wieder suchen, damit nicht einer
+ // ausgelassen oder doppelt gerufen wird.
+ if( n >= rLnks.Count() && 0 != ( n = rLnks.Count() ))
+ --n;
+
+ if( n && pLnk != &(*rLnks[ n ]) )
+ {
+ // suchen - kann nur davor liegen!!
+ while( n )
+ if( pLnk == &(*rLnks[ --n ] ) )
+ break;
+ }
+ }
+ }
+ }
+}
+
+
+// sucht sich die richtige DocShell raus oder erzeugt eine neue:
+// Der Return-Wert gibt an, was mit der Shell zu geschehen hat:
+// 0 - Fehler, konnte DocShell nicht finden
+// 1 - DocShell ist ein existieren Document
+// 2 - DocShell wurde neu angelegt, muss also wieder geschlossen werden ( will be assigned to xLockRef additionaly )
+
+int lcl_FindDocShell( SfxObjectShellRef& xDocSh,
+ SfxObjectShellLock& xLockRef,
+ const String& rFileName,
+ const String& rPasswd,
+ String& rFilter,
+ sal_Int16 nVersion,
+ SwDocShell* pDestSh )
+{
+ if( !rFileName.Len() )
+ return 0;
+
+ // 1. existiert die Datei schon in der Liste aller Dokumente?
+ INetURLObject aTmpObj( rFileName );
+ aTmpObj.SetMark( aEmptyStr );
+
+ // erstmal nur ueber die DocumentShells laufen und die mit dem
+ // Namen heraussuchen:
+ TypeId aType( TYPE(SwDocShell) );
+
+ SfxObjectShell* pShell = pDestSh;
+ sal_Bool bFirst = 0 != pShell;
+
+ if( !bFirst )
+ // keine DocShell uebergeben, also beginne mit der ersten aus der
+ // DocShell Liste
+ pShell = SfxObjectShell::GetFirst( &aType );
+
+ while( pShell )
+ {
+ // die wollen wir haben
+ SfxMedium* pMed = pShell->GetMedium();
+ if( pMed && pMed->GetURLObject() == aTmpObj )
+ {
+ const SfxPoolItem* pItem;
+ if( ( SFX_ITEM_SET == pMed->GetItemSet()->GetItemState(
+ SID_VERSION, sal_False, &pItem ) )
+ ? (nVersion == ((SfxInt16Item*)pItem)->GetValue())
+ : !nVersion )
+ {
+ // gefunden also returnen
+ xDocSh = pShell;
+ return 1;
+ }
+ }
+
+ if( bFirst )
+ {
+ bFirst = sal_False;
+ pShell = SfxObjectShell::GetFirst( &aType );
+ }
+ else
+ pShell = SfxObjectShell::GetNext( *pShell, &aType );
+ }
+
+ // 2. selbst die Date oeffnen
+ SfxMedium* pMed = new SfxMedium( aTmpObj.GetMainURL(
+ INetURLObject::NO_DECODE ), STREAM_READ, sal_True );
+ if( INET_PROT_FILE == aTmpObj.GetProtocol() )
+ pMed->DownLoad(); // nur mal das Medium anfassen (DownLoaden)
+
+ const SfxFilter* pSfxFlt = 0;
+ if( !pMed->GetError() )
+ {
+ String sFactory(String::CreateFromAscii(SwDocShell::Factory().GetShortName()));
+ SfxFilterMatcher aMatcher( sFactory );
+
+ // kein Filter, dann suche ihn. Ansonsten teste, ob der angegebene
+ // ein gueltiger ist
+ if( rFilter.Len() )
+ {
+ pSfxFlt = aMatcher.GetFilter4FilterName( rFilter );
+ }
+
+ if( nVersion )
+ pMed->GetItemSet()->Put( SfxInt16Item( SID_VERSION, nVersion ));
+
+ if( rPasswd.Len() )
+ pMed->GetItemSet()->Put( SfxStringItem( SID_PASSWORD, rPasswd ));
+
+ if( !pSfxFlt )
+ aMatcher.DetectFilter( *pMed, &pSfxFlt, sal_False, sal_False );
+
+ if( pSfxFlt )
+ {
+ // ohne Filter geht gar nichts
+ pMed->SetFilter( pSfxFlt );
+
+ // if the new shell is created, SfxObjectShellLock should be used to let it be closed later for sure
+ xLockRef = new SwDocShell( SFX_CREATE_MODE_INTERNAL );
+ xDocSh = (SfxObjectShell*)xLockRef;
+ if( xDocSh->DoLoad( pMed ) )
+ return 2;
+ }
+ }
+
+ if( !xDocSh.Is() ) // Medium muss noch geloescht werden
+ delete pMed;
+
+ return 0; // das war wohl nichts
+}
+
+
+void SwIntrnlSectRefLink::DataChanged( const String& rMimeType,
+ const uno::Any & rValue )
+{
+ SwSectionNode* pSectNd = rSectFmt.GetSectionNode( sal_False );
+ SwDoc* pDoc = rSectFmt.GetDoc();
+
+ sal_uLong nDataFormat = SotExchange::GetFormatIdFromMimeType( rMimeType );
+
+ if( !pSectNd || !pDoc || pDoc->IsInDtor() || ChkNoDataFlag() ||
+ sfx2::LinkManager::RegisterStatusInfoId() == nDataFormat )
+ {
+ // sollten wir schon wieder im Undo stehen?
+ return ;
+ }
+
+ // #i38810# - Due to possible existing signatures, the
+ // document has to be modified after updating a link.
+ pDoc->SetModified();
+ // set additional flag that links have been updated, in order to check this
+ // during load.
+ pDoc->SetLinksUpdated( sal_True );
+ // <--
+
+ // Undo immer abschalten
+ bool const bWasUndo = pDoc->GetIDocumentUndoRedo().DoesUndo();
+ pDoc->GetIDocumentUndoRedo().DoUndo(false);
+ sal_Bool bWasVisibleLinks = pDoc->IsVisibleLinks();
+ pDoc->SetVisibleLinks( sal_False );
+
+ SwPaM* pPam;
+ ViewShell* pVSh = 0;
+ SwEditShell* pESh = pDoc->GetEditShell( &pVSh );
+ pDoc->LockExpFlds();
+ {
+ // am Anfang des Bereichs einen leeren TextNode einfuegen
+ SwNodeIndex aIdx( *pSectNd, +1 );
+ SwNodeIndex aEndIdx( *pSectNd->EndOfSectionNode() );
+ SwTxtNode* pNewNd = pDoc->GetNodes().MakeTxtNode( aIdx,
+ pDoc->GetTxtCollFromPool( RES_POOLCOLL_TEXT ) );
+
+ if( pESh )
+ pESh->StartAllAction();
+ else if( pVSh )
+ pVSh->StartAction();
+
+ SwPosition aPos( aIdx, SwIndex( pNewNd, 0 ));
+ aPos.nNode--;
+ pDoc->CorrAbs( aIdx, aEndIdx, aPos, sal_True );
+
+ pPam = new SwPaM( aPos );
+
+ //und alles dahinter liegende loeschen
+ aIdx--;
+ DelFlyInRange( aIdx, aEndIdx );
+ _DelBookmarks(aIdx, aEndIdx);
+ aIdx++;
+
+ pDoc->GetNodes().Delete( aIdx, aEndIdx.GetIndex() - aIdx.GetIndex() );
+ }
+
+ SwSection& rSection = pSectNd->GetSection();
+ rSection.SetConnectFlag(false);
+
+ ::rtl::OUString sNewFileName;
+ Reader* pRead = 0;
+ switch( nDataFormat )
+ {
+ case FORMAT_STRING:
+ pRead = ReadAscii;
+ break;
+
+ case FORMAT_RTF:
+ pRead = SwReaderWriter::GetReader( READER_WRITER_RTF );
+ break;
+
+ case FORMAT_FILE:
+ if( rValue.hasValue() && ( rValue >>= sNewFileName ) )
+ {
+ String sFilter, sRange, sFileName( sNewFileName );
+ pDoc->GetLinkManager().GetDisplayNames( this, 0, &sFileName,
+ &sRange, &sFilter );
+
+ RedlineMode_t eOldRedlineMode = nsRedlineMode_t::REDLINE_NONE;
+ SfxObjectShellRef xDocSh;
+ SfxObjectShellLock xLockRef;
+ int nRet;
+ if( !sFileName.Len() )
+ {
+ xDocSh = pDoc->GetDocShell();
+ nRet = 1;
+ }
+ else
+ {
+ nRet = lcl_FindDocShell( xDocSh, xLockRef, sFileName,
+ rSection.GetLinkFilePassword(),
+ sFilter, 0, pDoc->GetDocShell() );
+ if( nRet )
+ {
+ SwDoc* pSrcDoc = ((SwDocShell*)&xDocSh)->GetDoc();
+ eOldRedlineMode = pSrcDoc->GetRedlineMode();
+ pSrcDoc->SetRedlineMode( nsRedlineMode_t::REDLINE_SHOW_INSERT );
+ }
+ }
+
+ if( nRet )
+ {
+ rSection.SetConnectFlag(true);
+
+ SwNodeIndex aSave( pPam->GetPoint()->nNode, -1 );
+ SwNodeRange* pCpyRg = 0;
+
+ if( xDocSh->GetMedium() &&
+ !rSection.GetLinkFilePassword().Len() )
+ {
+ const SfxPoolItem* pItem;
+ if( SFX_ITEM_SET == xDocSh->GetMedium()->GetItemSet()->
+ GetItemState( SID_PASSWORD, sal_False, &pItem ) )
+ rSection.SetLinkFilePassword(
+ ((SfxStringItem*)pItem)->GetValue() );
+ }
+
+ SwDoc* pSrcDoc = ((SwDocShell*)&xDocSh)->GetDoc();
+
+ if( sRange.Len() )
+ {
+ // Rekursionen abfangen
+ sal_Bool bRecursion = sal_False;
+ if( pSrcDoc == pDoc )
+ {
+ SwServerObjectRef refObj( (SwServerObject*)
+ pDoc->CreateLinkSource( sRange ));
+ if( refObj.Is() )
+ {
+ bRecursion = refObj->IsLinkInServer( this ) ||
+ ChkNoDataFlag();
+ }
+ }
+
+ SwNodeIndex& rInsPos = pPam->GetPoint()->nNode;
+
+ SwPaM* pCpyPam = 0;
+ if( !bRecursion &&
+ pSrcDoc->SelectServerObj( sRange, pCpyPam, pCpyRg )
+ && pCpyPam )
+ {
+ if( pSrcDoc != pDoc ||
+ pCpyPam->Start()->nNode > rInsPos ||
+ rInsPos >= pCpyPam->End()->nNode )
+ {
+ pSrcDoc->CopyRange( *pCpyPam, *pPam->GetPoint(),
+ false );
+ }
+ delete pCpyPam;
+ }
+ if( pCpyRg && pSrcDoc == pDoc &&
+ pCpyRg->aStart < rInsPos && rInsPos < pCpyRg->aEnd )
+ delete pCpyRg, pCpyRg = 0;
+ }
+ else if( pSrcDoc != pDoc )
+ pCpyRg = new SwNodeRange( pSrcDoc->GetNodes().GetEndOfExtras(), 2,
+ pSrcDoc->GetNodes().GetEndOfContent() );
+
+ // #i81653#
+ // Update links of extern linked document or extern linked
+ // document section, if section is protected.
+ if ( pSrcDoc != pDoc &&
+ rSection.IsProtectFlag() )
+ {
+ pSrcDoc->GetLinkManager().UpdateAllLinks( sal_False, sal_True, sal_False, 0 );
+ }
+ // <--
+ if( pCpyRg )
+ {
+ SwNodeIndex& rInsPos = pPam->GetPoint()->nNode;
+ sal_Bool bCreateFrm = rInsPos.GetIndex() <=
+ pDoc->GetNodes().GetEndOfExtras().GetIndex() ||
+ rInsPos.GetNode().FindTableNode();
+
+ SwTblNumFmtMerge aTNFM( *pSrcDoc, *pDoc );
+
+ pSrcDoc->CopyWithFlyInFly( *pCpyRg, 0, rInsPos, bCreateFrm );
+ aSave++;
+
+ if( !bCreateFrm )
+ ::MakeFrms( pDoc, aSave, rInsPos );
+
+ // den letzten Node noch loeschen, aber nur wenn
+ // erfolgreich kopiert werden konnte, also der Bereich
+ // mehr als 1 Node enthaelt
+ if( 2 < pSectNd->EndOfSectionIndex() - pSectNd->GetIndex() )
+ {
+ aSave = rInsPos;
+ pPam->Move( fnMoveBackward, fnGoNode );
+ pPam->SetMark(); // beide SwPositions ummelden!
+
+ pDoc->CorrAbs( aSave, *pPam->GetPoint(), 0, sal_True );
+ pDoc->GetNodes().Delete( aSave, 1 );
+ }
+ delete pCpyRg;
+ }
+
+ lcl_BreakSectionLinksInSect( *pSectNd );
+
+ // update alle Links in diesem Bereich
+ lcl_UpdateLinksInSect( *this, *pSectNd );
+ }
+ if( xDocSh.Is() )
+ {
+ if( 2 == nRet )
+ xDocSh->DoClose();
+ else if( ((SwDocShell*)&xDocSh)->GetDoc() )
+ ((SwDocShell*)&xDocSh)->GetDoc()->SetRedlineMode(
+ eOldRedlineMode );
+ }
+ }
+ break;
+ }
+
+ // !!!! DDE nur updaten wenn Shell vorhanden ist??
+ uno::Sequence< sal_Int8 > aSeq;
+ if( pRead && rValue.hasValue() && ( rValue >>= aSeq ) )
+ {
+ if( pESh )
+ {
+ pESh->Push();
+ SwPaM* pCrsr = pESh->GetCrsr();
+ *pCrsr->GetPoint() = *pPam->GetPoint();
+ delete pPam;
+ pPam = pCrsr;
+ }
+
+ SvMemoryStream aStrm( (void*)aSeq.getConstArray(), aSeq.getLength(),
+ STREAM_READ );
+ aStrm.Seek( 0 );
+
+#if OSL_DEBUG_LEVEL > 1
+ {
+ SvFileStream aDeb( String::CreateFromAscii(
+ "file:///d|/temp/update.txt" ), STREAM_WRITE );
+ aDeb << aStrm;
+ }
+ aStrm.Seek( 0 );
+#endif
+
+ // TODO/MBA: it's impossible to set a BaseURL here!
+ SwReader aTmpReader( aStrm, aEmptyStr, pDoc->GetDocShell()->GetMedium()->GetBaseURL(), *pPam );
+
+ if( !IsError( aTmpReader.Read( *pRead ) ))
+ {
+ rSection.SetConnectFlag(true);
+ }
+
+ if( pESh )
+ {
+ pESh->Pop( sal_False );
+ pPam = 0; // pam is deleted before
+ }
+ }
+
+
+ // remove all undo actions and turn undo on again
+ pDoc->GetIDocumentUndoRedo().DelAllUndoObj();
+ pDoc->GetIDocumentUndoRedo().DoUndo(bWasUndo);
+ pDoc->SetVisibleLinks( bWasVisibleLinks );
+
+ pDoc->UnlockExpFlds();
+ if( !pDoc->IsExpFldsLocked() )
+ pDoc->UpdateExpFlds(NULL, true);
+
+ if( pESh )
+ pESh->EndAllAction();
+ else if( pVSh )
+ pVSh->EndAction();
+ delete pPam; // wurde am Anfang angelegt
+}
+
+
+void SwIntrnlSectRefLink::Closed()
+{
+ SwDoc* pDoc = rSectFmt.GetDoc();
+ if( pDoc && !pDoc->IsInDtor() )
+ {
+ // Advise verabschiedet sich, den Bereich als nicht geschuetzt
+ // kennzeichnen und das Flag umsetzen
+
+ const SwSectionFmts& rFmts = pDoc->GetSections();
+ for( sal_uInt16 n = rFmts.Count(); n; )
+ if( rFmts[ --n ] == &rSectFmt )
+ {
+ ViewShell* pSh;
+ SwEditShell* pESh = pDoc->GetEditShell( &pSh );
+
+ if( pESh )
+ pESh->StartAllAction();
+ else
+ pSh->StartAction();
+
+ SwSectionData aSectionData(*rSectFmt.GetSection());
+ aSectionData.SetType( CONTENT_SECTION );
+ aSectionData.SetLinkFileName( aEmptyStr );
+ aSectionData.SetHidden( false );
+ aSectionData.SetProtectFlag( false );
+ // edit in readonly sections
+ aSectionData.SetEditInReadonlyFlag( false );
+
+ aSectionData.SetConnectFlag( false );
+
+ pDoc->UpdateSection( n, aSectionData );
+
+ // alle in der Section liegenden Links werden sichtbar
+ SwSectionNode* pSectNd = rSectFmt.GetSectionNode( sal_False );
+ if( pSectNd )
+ pSectNd->GetSection().MakeChildLinksVisible( *pSectNd );
+
+ if( pESh )
+ pESh->EndAllAction();
+ else
+ pSh->EndAction();
+ break;
+ }
+ }
+ SvBaseLink::Closed();
+}
+
+
+void SwSection::CreateLink( LinkCreateType eCreateType )
+{
+ SwSectionFmt* pFmt = GetFmt();
+ OSL_ENSURE(pFmt, "SwSection::CreateLink: no format?");
+ if (!pFmt || (CONTENT_SECTION == m_Data.GetType()))
+ return ;
+
+ sal_uInt16 nUpdateType = sfx2::LINKUPDATE_ALWAYS;
+
+ if (!m_RefLink.Is())
+ {
+ // create BaseLink
+ m_RefLink = new SwIntrnlSectRefLink( *pFmt, nUpdateType, FORMAT_RTF );
+ }
+ else
+ {
+ pFmt->GetDoc()->GetLinkManager().Remove( m_RefLink );
+ }
+
+ SwIntrnlSectRefLink *const pLnk =
+ static_cast<SwIntrnlSectRefLink*>(& m_RefLink);
+
+ String sCmd( m_Data.GetLinkFileName() );
+ xub_StrLen nPos;
+ while( STRING_NOTFOUND != (nPos = sCmd.SearchAscii( " " )) )
+ sCmd.Erase( nPos, 1 );
+
+ pLnk->SetUpdateMode( nUpdateType );
+ pLnk->SetVisible( pFmt->GetDoc()->IsVisibleLinks() );
+
+ switch (m_Data.GetType())
+ {
+ case DDE_LINK_SECTION:
+ pLnk->SetLinkSourceName( sCmd );
+ pFmt->GetDoc()->GetLinkManager().InsertDDELink( pLnk );
+ break;
+ case FILE_LINK_SECTION:
+ {
+ pLnk->SetContentType( FORMAT_FILE );
+ String sFltr( sCmd.GetToken( 1, sfx2::cTokenSeperator ) );
+ String sRange( sCmd.GetToken( 2, sfx2::cTokenSeperator ) );
+ pFmt->GetDoc()->GetLinkManager().InsertFileLink( *pLnk,
+ static_cast<sal_uInt16>(m_Data.GetType()),
+ sCmd.GetToken( 0, sfx2::cTokenSeperator ),
+ ( sFltr.Len() ? &sFltr : 0 ),
+ ( sRange.Len() ? &sRange : 0 ) );
+ }
+ break;
+ default:
+ OSL_ENSURE( !this, "Was ist das fuer ein Link?" );
+ }
+
+ switch( eCreateType )
+ {
+ case CREATE_CONNECT: // Link gleich connecten
+ pLnk->Connect();
+ break;
+
+ case CREATE_UPDATE: // Link connecten und updaten
+ pLnk->Update();
+ break;
+ case CREATE_NONE: break;
+ }
+}
+
+void SwSection::BreakLink()
+{
+ const SectionType eCurrentType( GetType() );
+ if ( eCurrentType == CONTENT_SECTION ||
+ eCurrentType == TOX_HEADER_SECTION ||
+ eCurrentType == TOX_CONTENT_SECTION )
+ {
+ // nothing to do
+ return;
+ }
+
+ // release link, if it exists
+ if (m_RefLink.Is())
+ {
+ SwSectionFmt *const pFormat( GetFmt() );
+ OSL_ENSURE(pFormat, "SwSection::BreakLink: no format?");
+ if (pFormat)
+ {
+ pFormat->GetDoc()->GetLinkManager().Remove( m_RefLink );
+ }
+ m_RefLink.Clear();
+ }
+ // change type
+ SetType( CONTENT_SECTION );
+ // reset linked file data
+ SetLinkFileName( aEmptyStr );
+ SetLinkFilePassword( aEmptyStr );
+}
+
+const SwNode* SwIntrnlSectRefLink::GetAnchor() const
+{
+ return rSectFmt.GetSectionNode( sal_False );
+}
+
+
+sal_Bool SwIntrnlSectRefLink::IsInRange( sal_uLong nSttNd, sal_uLong nEndNd,
+ xub_StrLen , xub_StrLen ) const
+{
+ SwStartNode* pSttNd = rSectFmt.GetSectionNode( sal_False );
+ return pSttNd &&
+ nSttNd < pSttNd->GetIndex() &&
+ pSttNd->EndOfSectionIndex() < nEndNd;
+}
+
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/docnode/swbaslnk.cxx b/sw/source/core/docnode/swbaslnk.cxx
new file mode 100644
index 000000000000..d04fd3fee03b
--- /dev/null
+++ b/sw/source/core/docnode/swbaslnk.cxx
@@ -0,0 +1,502 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+#include <hintids.hxx>
+#include <vcl/svapp.hxx>
+#include <vcl/outdev.hxx>
+
+#include <osl/thread.hxx>
+#include <salhelper/condition.hxx>
+#include <comphelper/mediadescriptor.hxx>
+#include <sfx2/docfile.hxx>
+#include <sfx2/lnkbase.hxx>
+#include <sfx2/objsh.hxx>
+#include <editeng/boxitem.hxx>
+#include <svx/svxids.hrc> // fuer die EventIds
+#include <sfx2/linkmgr.hxx>
+#include <svtools/soerr.hxx>
+#include <fmtfsize.hxx>
+#include <fmtanchr.hxx>
+#include <frmatr.hxx>
+#include <frmfmt.hxx>
+#include <doc.hxx>
+#include <pam.hxx>
+#include <editsh.hxx>
+#include <swtable.hxx>
+#include <docary.hxx>
+#include <swevent.hxx>
+#include <swbaslnk.hxx>
+#include <swserv.hxx>
+#include <ndgrf.hxx>
+#include <ndole.hxx>
+#include <hints.hxx>
+#include <tabfrm.hxx>
+#include <cntfrm.hxx>
+#include <htmltbl.hxx>
+
+using namespace com::sun::star;
+
+sal_Bool SetGrfFlySize( const Size& rGrfSz, const Size& rFrmSz, SwGrfNode* pGrfNd );
+
+TYPEINIT1( SwBaseLink, ::sfx2::SvBaseLink );
+
+SV_IMPL_REF( SwServerObject )
+
+void lcl_CallModify( SwGrfNode& rGrfNd, SfxPoolItem& rItem )
+{
+ //call fist all not SwNoTxtFrames, then the SwNoTxtFrames.
+ // The reason is, that in the SwNoTxtFrames the Graphic
+ // after a Paint will be swapped out! So all other "behind"
+ // them havent't a loaded Graphic.
+ rGrfNd.LockModify();
+
+ SwClientIter aIter( rGrfNd ); // TODO
+ for( int n = 0; n < 2; ++n )
+ {
+ SwClient * pLast = aIter.GoStart();
+ if( pLast ) // konnte zum Anfang gesprungen werden ??
+ {
+ do {
+ if( (0 == n) ^ ( 0 != pLast->ISA( SwCntntFrm )) )
+ pLast->ModifyNotification( &rItem, &rItem );
+ } while( 0 != ( pLast = aIter++ ));
+ }
+ }
+ rGrfNd.UnlockModify();
+}
+
+
+void SwBaseLink::DataChanged( const String& rMimeType,
+ const uno::Any & rValue )
+{
+ if( !pCntntNode )
+ {
+ OSL_ENSURE(!this, "DataChanged ohne ContentNode" );
+ return ;
+ }
+
+ SwDoc* pDoc = pCntntNode->GetDoc();
+ if( pDoc->IsInDtor() || ChkNoDataFlag() || bIgnoreDataChanged )
+ {
+ bIgnoreDataChanged = sal_False;
+ return ;
+ }
+
+ sal_uLong nFmt = SotExchange::GetFormatIdFromMimeType( rMimeType );
+
+ if( pCntntNode->IsNoTxtNode() &&
+ nFmt == sfx2::LinkManager::RegisterStatusInfoId() )
+ {
+ // nur eine Statusaenderung - Events bedienen ?
+ ::rtl::OUString sState;
+ if( rValue.hasValue() && ( rValue >>= sState ))
+ {
+ sal_uInt16 nEvent = 0;
+ switch( sState.toInt32() )
+ {
+ case sfx2::LinkManager::STATE_LOAD_OK: nEvent = SVX_EVENT_IMAGE_LOAD; break;
+ case sfx2::LinkManager::STATE_LOAD_ERROR: nEvent = SVX_EVENT_IMAGE_ERROR; break;
+ case sfx2::LinkManager::STATE_LOAD_ABORT: nEvent = SVX_EVENT_IMAGE_ABORT; break;
+ }
+
+ SwFrmFmt* pFmt;
+ if( nEvent && 0 != ( pFmt = pCntntNode->GetFlyFmt() ))
+ {
+ SwCallMouseEvent aCallEvent;
+ aCallEvent.Set( EVENT_OBJECT_IMAGE, pFmt );
+ pDoc->CallEvent( nEvent, aCallEvent );
+ }
+ }
+ return; // das wars!
+ }
+
+ sal_Bool bUpdate = sal_False;
+ sal_Bool bGraphicArrived = sal_False;
+ sal_Bool bGraphicPieceArrived = sal_False;
+ sal_Bool bDontNotify = sal_False;
+ Size aGrfSz, aFrmFmtSz;
+
+ if( pCntntNode->IsGrfNode() )
+ {
+ GraphicObject& rGrfObj = ((SwGrfNode*)pCntntNode)->GetGrfObj();
+
+ bDontNotify = ((SwGrfNode*)pCntntNode)->IsFrameInPaint();
+
+ bGraphicArrived = GetObj()->IsDataComplete();
+ bGraphicPieceArrived = GetObj()->IsPending();
+ ((SwGrfNode*)pCntntNode)->SetGrafikArrived( bGraphicArrived );
+
+ Graphic aGrf;
+ if( sfx2::LinkManager::GetGraphicFromAny( rMimeType, rValue, aGrf ) &&
+ ( GRAPHIC_DEFAULT != aGrf.GetType() ||
+ GRAPHIC_DEFAULT != rGrfObj.GetType() ) )
+ {
+ aGrfSz = ::GetGraphicSizeTwip( aGrf, 0 );
+ if( static_cast< const SwGrfNode * >( pCntntNode )->IsChgTwipSizeFromPixel() )
+ {
+ const MapMode aMapTwip( MAP_TWIP );
+ aFrmFmtSz =
+ Application::GetDefaultDevice()->PixelToLogic(
+ aGrf.GetSizePixel(), aMapTwip );
+
+ }
+ else
+ {
+ aFrmFmtSz = aGrfSz;
+ }
+ Size aSz( ((SwGrfNode*)pCntntNode)->GetTwipSize() );
+
+ if( bGraphicPieceArrived && GRAPHIC_DEFAULT != aGrf.GetType() &&
+ ( !aSz.Width() || !aSz.Height() ) )
+ {
+ // wenn nur ein Teil ankommt, aber die Groesse nicht
+ // gesetzt ist, dann muss "unten" der Teil von
+ // bGraphicArrived durchlaufen werden!
+ // (ansonten wird die Grafik in deft. Size gepaintet)
+ bGraphicArrived = sal_True;
+ bGraphicPieceArrived = sal_False;
+ }
+
+ rGrfObj.SetGraphic( aGrf, rGrfObj.GetLink() );
+ bUpdate = sal_True;
+
+ // Bug 33999: damit der Node den Transparent-Status
+ // richtig gesetzt hat, ohne auf die Grafik
+ // zugreifen zu muessen (sonst erfolgt ein SwapIn!).
+ if( bGraphicArrived )
+ {
+ // immer mit der korrekten Grafik-Size arbeiten
+ if( aGrfSz.Height() && aGrfSz.Width() &&
+ aSz.Height() && aSz.Width() &&
+ aGrfSz != aSz )
+ ((SwGrfNode*)pCntntNode)->SetTwipSize( aGrfSz );
+ }
+ }
+ if ( bUpdate && !bGraphicArrived && !bGraphicPieceArrived )
+ ((SwGrfNode*)pCntntNode)->SetTwipSize( Size(0,0) );
+ }
+ else if( pCntntNode->IsOLENode() )
+ bUpdate = sal_True;
+
+ ViewShell *pSh = 0;
+ SwEditShell* pESh = pDoc->GetEditShell( &pSh );
+
+ if ( bUpdate && bGraphicPieceArrived && !(bSwapIn || bDontNotify) )
+ {
+ //Hint ohne Actions verschicken, loest direktes Paint aus.
+ if ( (!pSh || !pSh->ActionPend()) && (!pESh || !pESh->ActionPend()) )
+ {
+ SwMsgPoolItem aMsgHint( RES_GRAPHIC_PIECE_ARRIVED );
+ pCntntNode->ModifyNotification( &aMsgHint, &aMsgHint );
+ bUpdate = sal_False;
+ }
+ }
+
+ static sal_Bool bInNotifyLinks = sal_False;
+ if( bUpdate && !bDontNotify && (!bSwapIn || bGraphicArrived) &&
+ !bInNotifyLinks)
+ {
+ sal_Bool bLockView = sal_False;
+ if( pSh )
+ {
+ bLockView = pSh->IsViewLocked();
+ pSh->LockView( sal_True );
+ }
+
+ if( pESh )
+ pESh->StartAllAction();
+ else if( pSh )
+ pSh->StartAction();
+
+ SwMsgPoolItem aMsgHint( static_cast<sal_uInt16>(
+ bGraphicArrived ? RES_GRAPHIC_ARRIVED : RES_UPDATE_ATTR ) );
+
+ if ( bGraphicArrived )
+ {
+ //Alle benachrichtigen, die am gleichen Link horchen.
+ bInNotifyLinks = sal_True;
+
+ const ::sfx2::SvBaseLinks& rLnks = pDoc->GetLinkManager().GetLinks();
+ for( sal_uInt16 n = rLnks.Count(); n; )
+ {
+ ::sfx2::SvBaseLink* pLnk = &(*rLnks[ --n ]);
+ if( pLnk && OBJECT_CLIENT_GRF == pLnk->GetObjType() &&
+ pLnk->ISA( SwBaseLink ) && pLnk->GetObj() == GetObj() )
+ {
+ SwBaseLink* pBLink = (SwBaseLink*)pLnk;
+ SwGrfNode* pGrfNd = (SwGrfNode*)pBLink->pCntntNode;
+
+ if( pBLink != this &&
+ ( !bSwapIn ||
+ GRAPHIC_DEFAULT == pGrfNd->GetGrfObj().GetType()))
+ {
+ pBLink->bIgnoreDataChanged = sal_False;
+ pBLink->DataChanged( rMimeType, rValue );
+ pBLink->bIgnoreDataChanged = sal_True;
+
+ pGrfNd->SetGrafikArrived( ((SwGrfNode*)pCntntNode)->
+ IsGrafikArrived() );
+
+ // Fly der Grafik anpassen !
+ if( !::SetGrfFlySize( aGrfSz, aFrmFmtSz, pGrfNd ) )
+ ::lcl_CallModify( *pGrfNd, aMsgHint );
+ }
+ else if( pBLink == this &&
+ !::SetGrfFlySize( aGrfSz, aFrmFmtSz, pGrfNd ) )
+ // Fly der Grafik anpassen !
+ ::lcl_CallModify( *pGrfNd, aMsgHint );
+ }
+ }
+
+ bInNotifyLinks = sal_False;
+ }
+ else
+ {
+ pCntntNode->ModifyNotification( &aMsgHint, &aMsgHint );
+ }
+
+
+ if( pESh )
+ {
+ const sal_Bool bEndActionByVirDev = pESh->IsEndActionByVirDev();
+ pESh->SetEndActionByVirDev( sal_True );
+ pESh->EndAllAction();
+ pESh->SetEndActionByVirDev( bEndActionByVirDev );
+ }
+ else if( pSh )
+ pSh->EndAction();
+
+ if( pSh && !bLockView )
+ pSh->LockView( sal_False );
+ }
+}
+
+sal_Bool SetGrfFlySize( const Size& rGrfSz, const Size& rFrmSz, SwGrfNode* pGrfNd )
+{
+ sal_Bool bRet = sal_False;
+ ViewShell *pSh;
+ CurrShell *pCurr = 0;
+ if ( pGrfNd->GetDoc()->GetEditShell( &pSh ) )
+ pCurr = new CurrShell( pSh );
+
+ Size aSz = pGrfNd->GetTwipSize();
+ if ( !(aSz.Width() && aSz.Height()) &&
+ rGrfSz.Width() && rGrfSz.Height() )
+ {
+ SwFrmFmt* pFmt;
+ if( pGrfNd->IsChgTwipSize() &&
+ 0 != (pFmt = pGrfNd->GetFlyFmt()) )
+ {
+ Size aCalcSz( aSz );
+ if ( !aSz.Height() && aSz.Width() )
+ //passende Hoehe ausrechnen.
+ aCalcSz.Height() = rFrmSz.Height() *
+ aSz.Width() / rFrmSz.Width();
+ else if ( !aSz.Width() && aSz.Height() )
+ //passende Breite ausrechnen
+ aCalcSz.Width() = rFrmSz.Width() *
+ aSz.Height() / rFrmSz.Height();
+ else
+ //Hoehe und Breite uebernehmen
+ aCalcSz = rFrmSz;
+
+ const SvxBoxItem &rBox = pFmt->GetBox();
+ aCalcSz.Width() += rBox.CalcLineSpace(BOX_LINE_LEFT) +
+ rBox.CalcLineSpace(BOX_LINE_RIGHT);
+ aCalcSz.Height()+= rBox.CalcLineSpace(BOX_LINE_TOP) +
+ rBox.CalcLineSpace(BOX_LINE_BOTTOM);
+ const SwFmtFrmSize& rOldAttr = pFmt->GetFrmSize();
+ if( rOldAttr.GetSize() != aCalcSz )
+ {
+ SwFmtFrmSize aAttr( rOldAttr );
+ aAttr.SetSize( aCalcSz );
+ pFmt->SetFmtAttr( aAttr );
+ bRet = sal_True;
+ }
+
+ if( !aSz.Width() )
+ {
+ // Wenn die Grafik in einer Tabelle verankert ist, muess
+ // die Tabellen-Spalten neu berechnet werden
+ const SwDoc *pDoc = pGrfNd->GetDoc();
+ const SwPosition* pAPos = pFmt->GetAnchor().GetCntntAnchor();
+ SwNode *pANd;
+ SwTableNode *pTblNd;
+ if( pAPos &&
+ 0 != (pANd = & pAPos->nNode.GetNode()) &&
+ 0 != (pTblNd = pANd->FindTableNode()) )
+ {
+ const sal_Bool bLastGrf = !pTblNd->GetTable().DecGrfsThatResize();
+ SwHTMLTableLayout *pLayout =
+ pTblNd->GetTable().GetHTMLTableLayout();
+ if( pLayout )
+ {
+ const sal_uInt16 nBrowseWidth =
+ pLayout->GetBrowseWidthByTable( *pDoc );
+ if ( nBrowseWidth )
+ {
+ pLayout->Resize( nBrowseWidth, sal_True, sal_True,
+ bLastGrf ? HTMLTABLE_RESIZE_NOW
+ : 500 );
+ }
+ }
+ }
+ }
+ }
+
+ // SetTwipSize skaliert ggf. eine ImageMap neu und
+ // braucht dazu das Frame-Format
+ pGrfNd->SetTwipSize( rGrfSz );
+ }
+
+ delete pCurr;
+
+ return bRet;
+}
+
+
+sal_Bool SwBaseLink::SwapIn( sal_Bool bWaitForData, sal_Bool bNativFormat )
+{
+ bSwapIn = sal_True;
+
+ sal_Bool bRes;
+
+ if( !GetObj() && ( bNativFormat || ( !IsSynchron() && bWaitForData ) ))
+ {
+ AddNextRef();
+ _GetRealObject();
+ ReleaseRef();
+ }
+
+#if OSL_DEBUG_LEVEL > 1
+ {
+ String sGrfNm;
+ if(GetLinkManager())
+ GetLinkManager()->GetDisplayNames( this, 0, &sGrfNm, 0, 0 );
+ int x = 0;
+ ++x;
+ }
+#endif
+
+ if( GetObj() )
+ {
+ String aMimeType( SotExchange::GetFormatMimeType( GetContentType() ));
+ uno::Any aValue;
+ GetObj()->GetData( aValue, aMimeType, !IsSynchron() && bWaitForData );
+
+ if( bWaitForData && !GetObj() )
+ {
+ OSL_ENSURE( !this, "das SvxFileObject wurde in einem GetData geloescht!" );
+ bRes = sal_False;
+ }
+ else if( 0 != ( bRes = aValue.hasValue() ) )
+ {
+ //JP 14.04.99: Bug 64820 - das Flag muss beim SwapIn natuerlich
+ // zurueckgesetzt werden. Die Daten sollen ja neu
+ // uebernommen werden
+ bIgnoreDataChanged = sal_False;
+ DataChanged( aMimeType, aValue );
+ }
+ }
+ else if( !IsSynchron() && bWaitForData )
+ {
+ SetSynchron( sal_True );
+ bRes = Update();
+ SetSynchron( sal_False );
+ }
+ else
+ bRes = Update();
+
+ bSwapIn = sal_False;
+ return bRes;
+}
+
+void SwBaseLink::Closed()
+{
+ if( pCntntNode && !pCntntNode->GetDoc()->IsInDtor() )
+ {
+ // wir heben die Verbindung auf
+ if( pCntntNode->IsGrfNode() )
+ ((SwGrfNode*)pCntntNode)->ReleaseLink();
+ }
+ SvBaseLink::Closed();
+}
+
+const SwNode* SwBaseLink::GetAnchor() const
+{
+ if (pCntntNode)
+ {
+ SwFrmFmt *const pFmt = pCntntNode->GetFlyFmt();
+ if (pFmt)
+ {
+ const SwFmtAnchor& rAnchor = pFmt->GetAnchor();
+ SwPosition const*const pAPos = rAnchor.GetCntntAnchor();
+ if (pAPos &&
+ ((FLY_AS_CHAR == rAnchor.GetAnchorId()) ||
+ (FLY_AT_CHAR == rAnchor.GetAnchorId()) ||
+ (FLY_AT_FLY == rAnchor.GetAnchorId()) ||
+ (FLY_AT_PARA == rAnchor.GetAnchorId())))
+ {
+ return &pAPos->nNode.GetNode();
+ }
+ return 0;
+ }
+ }
+
+ OSL_ENSURE( !this, "GetAnchor nicht ueberlagert" );
+ return 0;
+}
+
+sal_Bool SwBaseLink::IsRecursion( const SwBaseLink* pChkLnk ) const
+{
+ SwServerObjectRef aRef( (SwServerObject*)GetObj() );
+ if( aRef.Is() )
+ {
+ // es ist ein ServerObject, also frage nach allen darin
+ // befindlichen Links, ob wir darin enthalten sind. Ansonsten
+ // handelt es sich um eine Rekursion.
+ return aRef->IsLinkInServer( pChkLnk );
+ }
+ return sal_False;
+}
+
+sal_Bool SwBaseLink::IsInRange( sal_uLong, sal_uLong, xub_StrLen, xub_StrLen ) const
+{
+ // Grafik oder OLE-Links nicht,
+ // Felder oder Sections haben eigene Ableitung!
+ return sal_False;
+}
+
+SwBaseLink::~SwBaseLink()
+{
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/docnode/swthreadjoiner.cxx b/sw/source/core/docnode/swthreadjoiner.cxx
new file mode 100644
index 000000000000..70997287e0ae
--- /dev/null
+++ b/sw/source/core/docnode/swthreadjoiner.cxx
@@ -0,0 +1,64 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+#include "precompiled_sw.hxx"
+#include <swthreadjoiner.hxx>
+#include <finalthreadmanager.hxx>
+#include <com/sun/star/lang/XMultiServiceFactory.hpp>
+#include <comphelper/processfactory.hxx>
+
+/** Testing
+
+ @author OD
+*/
+using namespace ::com::sun::star;
+
+uno::Reference< util::XJobManager > SwThreadJoiner::mpThreadJoiner;
+osl::Mutex* SwThreadJoiner::mpGetJoinerMutex = new osl::Mutex();
+
+uno::Reference< util::XJobManager >& SwThreadJoiner::GetThreadJoiner()
+{
+ osl::MutexGuard aGuard(*mpGetJoinerMutex);
+
+ if ( !mpThreadJoiner.is() )
+ {
+ mpThreadJoiner =
+ uno::Reference< util::XJobManager >(
+ ::comphelper::getProcessServiceFactory()->createInstance(
+ ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.util.JobManager")) ),
+ uno::UNO_QUERY );
+ }
+
+ return mpThreadJoiner;
+}
+
+void SwThreadJoiner::ReleaseThreadJoiner()
+{
+ mpThreadJoiner.clear();
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/docnode/swthreadmanager.cxx b/sw/source/core/docnode/swthreadmanager.cxx
new file mode 100644
index 000000000000..989ee9348961
--- /dev/null
+++ b/sw/source/core/docnode/swthreadmanager.cxx
@@ -0,0 +1,90 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+#include "precompiled_sw.hxx"
+#include <swthreadmanager.hxx>
+#include <swthreadjoiner.hxx>
+#include <observablethread.hxx>
+#include <threadmanager.hxx>
+
+/** class to manage threads in Writer - it conforms the singleton pattern
+
+ #i73788#
+
+ @author OD
+*/
+bool SwThreadManager::mbThreadManagerInstantiated = false;
+
+SwThreadManager::SwThreadManager()
+ : mpThreadManagerImpl( new ThreadManager( SwThreadJoiner::GetThreadJoiner() ) )
+{
+ mpThreadManagerImpl->Init();
+ mbThreadManagerInstantiated = true;
+}
+
+SwThreadManager::~SwThreadManager()
+{
+}
+
+struct InitInstance : public rtl::Static<SwThreadManager, InitInstance> {};
+
+SwThreadManager& SwThreadManager::GetThreadManager()
+{
+ return InitInstance::get();
+}
+
+bool SwThreadManager::ExistsThreadManager()
+{
+ return mbThreadManagerInstantiated;
+}
+
+oslInterlockedCount SwThreadManager::AddThread( const rtl::Reference< ObservableThread >& rThread )
+{
+ return mpThreadManagerImpl->AddThread( rThread );
+}
+
+void SwThreadManager::RemoveThread( const oslInterlockedCount nThreadID )
+{
+ mpThreadManagerImpl->RemoveThread( nThreadID );
+}
+
+void SwThreadManager::SuspendStartingOfThreads()
+{
+ mpThreadManagerImpl->SuspendStartingOfThreads();
+}
+
+void SwThreadManager::ResumeStartingOfThreads()
+{
+ mpThreadManagerImpl->ResumeStartingOfThreads();
+}
+
+bool SwThreadManager::StartingOfThreadsSuspended()
+{
+ return mpThreadManagerImpl->StartingOfThreadsSuspended();
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/docnode/threadlistener.cxx b/sw/source/core/docnode/threadlistener.cxx
new file mode 100644
index 000000000000..c06fa618d2e8
--- /dev/null
+++ b/sw/source/core/docnode/threadlistener.cxx
@@ -0,0 +1,59 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+#include "precompiled_sw.hxx"
+#include <threadlistener.hxx>
+
+/** helper class to observe threads
+
+ #i73788#
+
+ @author OD
+*/
+ThreadListener::ThreadListener( IThreadListenerOwner& rThreadListenerOwner )
+ : IFinishedThreadListener(),
+ mrThreadListenerOwner( rThreadListenerOwner )
+{
+}
+
+ThreadListener::~ThreadListener()
+{
+}
+
+void ThreadListener::ListenToThread( const oslInterlockedCount nThreadID,
+ ObservableThread& rThread )
+{
+ rThread.SetListener( mrThreadListenerOwner.GetThreadListenerWeakRef(),
+ nThreadID );
+}
+
+void ThreadListener::NotifyAboutFinishedThread( const oslInterlockedCount nThreadID )
+{
+ mrThreadListenerOwner.NotifyAboutFinishedThread( nThreadID );
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/docnode/threadmanager.cxx b/sw/source/core/docnode/threadmanager.cxx
new file mode 100644
index 000000000000..b7819527470f
--- /dev/null
+++ b/sw/source/core/docnode/threadmanager.cxx
@@ -0,0 +1,260 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+#include "precompiled_sw.hxx"
+#include <threadmanager.hxx>
+
+#include <algorithm>
+
+using namespace ::com::sun::star;
+
+/** class to manage threads
+
+ #i73788#
+
+ @author OD
+*/
+const std::deque< ThreadManager::tThreadData >::size_type ThreadManager::mnStartedSize = 10;
+
+ThreadManager::ThreadManager( uno::Reference< util::XJobManager >& rThreadJoiner )
+ : maMutex(),
+ mrThreadJoiner( rThreadJoiner ),
+ mpThreadListener(),
+ mnThreadIDCounter( 0 ),
+ maWaitingForStartThreads(),
+ maStartedThreads(),
+ maStartNewThreadTimer(),
+ mbStartingOfThreadsSuspended( false )
+{
+}
+
+void ThreadManager::Init()
+{
+ mpThreadListener.reset( new ThreadListener( *this ) );
+
+ maStartNewThreadTimer.SetTimeout( 2000 );
+ maStartNewThreadTimer.SetTimeoutHdl( LINK( this, ThreadManager, TryToStartNewThread ) );
+}
+
+ThreadManager::~ThreadManager()
+{
+ maWaitingForStartThreads.clear();
+ maStartedThreads.clear();
+}
+
+boost::weak_ptr< IFinishedThreadListener > ThreadManager::GetThreadListenerWeakRef()
+{
+ return mpThreadListener;
+}
+
+void ThreadManager::NotifyAboutFinishedThread( const oslInterlockedCount nThreadID )
+{
+ RemoveThread( nThreadID, true );
+}
+
+oslInterlockedCount ThreadManager::AddThread(
+ const rtl::Reference< ObservableThread >& rThread )
+
+{
+ osl::MutexGuard aGuard(maMutex);
+
+ // create new thread
+ tThreadData aThreadData;
+ oslInterlockedCount nNewThreadID( RetrieveNewThreadID() );
+ {
+ aThreadData.nThreadID = nNewThreadID;
+
+ aThreadData.pThread = rThread;
+ aThreadData.aJob = new CancellableJob( aThreadData.pThread );
+
+ aThreadData.pThread->setPriority( osl_Thread_PriorityBelowNormal );
+ mpThreadListener->ListenToThread( aThreadData.nThreadID,
+ *(aThreadData.pThread) );
+ }
+
+ // add thread to manager
+ if ( maStartedThreads.size() < mnStartedSize &&
+ !StartingOfThreadsSuspended() )
+ {
+ // Try to start thread
+ if ( !StartThread( aThreadData ) )
+ {
+ // No success on starting thread
+ // If no more started threads exist, but still threads are waiting,
+ // setup Timer to start thread from waiting ones
+ if ( maStartedThreads.empty() && !maWaitingForStartThreads.empty() )
+ {
+ maStartNewThreadTimer.Start();
+ }
+ }
+ }
+ else
+ {
+ // Thread will be started later
+ maWaitingForStartThreads.push_back( aThreadData );
+ }
+
+ return nNewThreadID;
+}
+
+void ThreadManager::RemoveThread( const oslInterlockedCount nThreadID,
+ const bool bThreadFinished )
+{
+ // --> SAFE ----
+ osl::MutexGuard aGuard(maMutex);
+
+ std::deque< tThreadData >::iterator aIter =
+ std::find_if( maStartedThreads.begin(), maStartedThreads.end(),
+ ThreadPred( nThreadID ) );
+
+ if ( aIter != maStartedThreads.end() )
+ {
+ tThreadData aTmpThreadData( (*aIter) );
+
+ maStartedThreads.erase( aIter );
+
+ if ( bThreadFinished )
+ {
+ // release thread as job from thread joiner instance
+ ::com::sun::star::uno::Reference< ::com::sun::star::util::XJobManager > rThreadJoiner( mrThreadJoiner );
+ if ( rThreadJoiner.is() )
+ {
+ rThreadJoiner->releaseJob( aTmpThreadData.aJob );
+ }
+ else
+ {
+ OSL_FAIL( "<ThreadManager::RemoveThread(..)> - ThreadJoiner already gone!" );
+ }
+ }
+
+ // Try to start thread from waiting ones
+ TryToStartNewThread( 0 );
+ }
+ else
+ {
+ aIter = std::find_if( maWaitingForStartThreads.begin(),
+ maWaitingForStartThreads.end(), ThreadPred( nThreadID ) );
+
+ if ( aIter != maWaitingForStartThreads.end() )
+ {
+ maWaitingForStartThreads.erase( aIter );
+ }
+ }
+ // <-- SAFE ----
+}
+
+bool ThreadManager::StartWaitingThread()
+{
+ if ( !maWaitingForStartThreads.empty() )
+ {
+ tThreadData aThreadData( maWaitingForStartThreads.front() );
+ maWaitingForStartThreads.pop_front();
+ return StartThread( aThreadData );
+ }
+ else
+ {
+ return false;
+ }
+}
+
+bool ThreadManager::StartThread( const tThreadData& rThreadData )
+{
+ bool bThreadStarted( false );
+
+ if ( rThreadData.pThread->create() )
+ {
+ // start of thread successful.
+ bThreadStarted = true;
+
+ maStartedThreads.push_back( rThreadData );
+
+ // register thread as job at thread joiner instance
+ ::com::sun::star::uno::Reference< ::com::sun::star::util::XJobManager > rThreadJoiner( mrThreadJoiner );
+ if ( rThreadJoiner.is() )
+ {
+ rThreadJoiner->registerJob( rThreadData.aJob );
+ }
+ else
+ {
+ OSL_FAIL( "<ThreadManager::StartThread(..)> - ThreadJoiner already gone!" );
+ }
+ }
+ else
+ {
+ // thread couldn't be started.
+ maWaitingForStartThreads.push_front( rThreadData );
+ }
+
+ return bThreadStarted;
+}
+
+IMPL_LINK( ThreadManager, TryToStartNewThread, Timer *, EMPTYARG )
+{
+ osl::MutexGuard aGuard(maMutex);
+
+ if ( !StartingOfThreadsSuspended() )
+ {
+ // Try to start thread from waiting ones
+ if ( !StartWaitingThread() )
+ {
+ // No success on starting thread
+ // If no more started threads exist, but still threads are waiting,
+ // setup Timer to start thread from waiting ones
+ if ( maStartedThreads.empty() && !maWaitingForStartThreads.empty() )
+ {
+ maStartNewThreadTimer.Start();
+ }
+ }
+ }
+
+ return sal_True;
+}
+
+void ThreadManager::ResumeStartingOfThreads()
+{
+ osl::MutexGuard aGuard(maMutex);
+
+ mbStartingOfThreadsSuspended = false;
+
+ while ( maStartedThreads.size() < mnStartedSize &&
+ !maWaitingForStartThreads.empty() )
+ {
+ if ( !StartWaitingThread() )
+ {
+ // No success on starting thread
+ // If no more started threads exist, but still threads are waiting,
+ // setup Timer to start thread from waiting ones
+ if ( maStartedThreads.empty() && !maWaitingForStartThreads.empty() )
+ {
+ maStartNewThreadTimer.Start();
+ break;
+ }
+ }
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/draw/dcontact.cxx b/sw/source/core/draw/dcontact.cxx
new file mode 100644
index 000000000000..d1b6e3783cfd
--- /dev/null
+++ b/sw/source/core/draw/dcontact.cxx
@@ -0,0 +1,2663 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+#include "hintids.hxx"
+#include <editeng/protitem.hxx>
+#include <editeng/opaqitem.hxx>
+#include <editeng/ulspitem.hxx>
+#include <editeng/lrspitem.hxx>
+#include <svx/svdpage.hxx>
+#include <svx/svditer.hxx>
+#include <svx/fmglob.hxx>
+#include <svx/svdogrp.hxx>
+#include <svx/svdotext.hxx>
+#include <svx/svdmodel.hxx>
+#include <svx/svdpagv.hxx>
+#include <svx/svdviter.hxx>
+#include <svx/svdview.hxx>
+#include <svx/shapepropertynotifier.hxx>
+#include <svx/sdr/contact/objectcontactofobjlistpainter.hxx>
+#include <svx/sdr/contact/displayinfo.hxx>
+#include <fmtornt.hxx>
+#include <viewimp.hxx>
+#include <fmtsrnd.hxx>
+#include <fmtanchr.hxx>
+#include <node.hxx>
+#include <fmtcntnt.hxx>
+#include <pagefrm.hxx>
+#include <rootfrm.hxx>
+#include <frmtool.hxx> // Notify_Background
+#include <flyfrm.hxx>
+#include <frmfmt.hxx>
+#include <dflyobj.hxx>
+#include <dcontact.hxx>
+#include <unodraw.hxx>
+#include <IDocumentDrawModelAccess.hxx>
+#include <doc.hxx>
+#include <hints.hxx>
+#include <txtfrm.hxx>
+#include <editsh.hxx>
+#include <docary.hxx>
+#include <flyfrms.hxx>
+#include <sortedobjs.hxx>
+#include <basegfx/matrix/b2dhommatrix.hxx>
+#include <basegfx/matrix/b2dhommatrixtools.hxx>
+#include <svx/sdr/contact/viewcontactofvirtobj.hxx>
+#include <drawinglayer/primitive2d/transformprimitive2d.hxx>
+#include <svx/sdr/contact/viewobjectcontactofsdrobj.hxx>
+#include <com/sun/star/text/WritingMode2.hpp>
+#include <switerator.hxx>
+#include <algorithm>
+
+using namespace ::com::sun::star;
+
+
+TYPEINIT1( SwContact, SwClient )
+TYPEINIT1( SwFlyDrawContact, SwContact )
+TYPEINIT1( SwDrawContact, SwContact )
+
+void setContextWritingMode( SdrObject* pObj, SwFrm* pAnchor )
+{
+ if( pObj && pAnchor )
+ {
+ short nWritingDirection = text::WritingMode2::LR_TB;
+ if( pAnchor->IsVertical() )
+ {
+ nWritingDirection = text::WritingMode2::TB_RL;
+ } else if( pAnchor->IsRightToLeft() )
+ {
+ nWritingDirection = text::WritingMode2::RL_TB;
+ }
+ pObj->SetContextWritingMode( nWritingDirection );
+ }
+}
+
+
+//Der Umgekehrte Weg: Sucht das Format zum angegebenen Objekt.
+//Wenn das Object ein SwVirtFlyDrawObj ist so wird das Format von
+//selbigem besorgt.
+//Anderfalls ist es eben ein einfaches Zeichenobjekt. Diese hat einen
+//UserCall und der ist Client vom gesuchten Format.
+
+SwFrmFmt *FindFrmFmt( SdrObject *pObj )
+{
+ SwFrmFmt* pRetval = 0L;
+
+ if ( pObj->ISA(SwVirtFlyDrawObj) )
+ {
+ pRetval = ((SwVirtFlyDrawObj*)pObj)->GetFmt();
+ }
+ else
+ {
+ SwDrawContact* pContact = static_cast<SwDrawContact*>(GetUserCall( pObj ));
+ if ( pContact )
+ {
+ pRetval = pContact->GetFmt();
+ }
+ }
+ return pRetval;
+}
+
+sal_Bool HasWrap( const SdrObject* pObj )
+{
+ if ( pObj )
+ {
+ const SwFrmFmt* pFmt = ::FindFrmFmt( pObj );
+ if ( pFmt )
+ {
+ return SURROUND_THROUGHT != pFmt->GetSurround().GetSurround();
+ }
+ }
+
+ return sal_False;
+}
+
+/*****************************************************************************
+ *
+ * GetBoundRect liefert das BoundRect _inklusive_ Abstand des Objekts.
+ *
+ *****************************************************************************/
+
+// --> OD 2006-08-15 #i68520# - change naming
+SwRect GetBoundRectOfAnchoredObj( const SdrObject* pObj )
+// <--
+{
+ SwRect aRet( pObj->GetCurrentBoundRect() );
+ // --> OD 2006-08-10 #i68520# - call cache of <SwAnchoredObject>
+ SwContact* pContact( GetUserCall( pObj ) );
+ if ( pContact )
+ {
+ const SwAnchoredObject* pAnchoredObj( pContact->GetAnchoredObj( pObj ) );
+ if ( pAnchoredObj )
+ {
+ aRet = pAnchoredObj->GetObjRectWithSpaces();
+ }
+ }
+ // <--
+ return aRet;
+}
+
+//Liefert den UserCall ggf. vom Gruppenobjekt
+// OD 2004-03-31 #i26791# - change return type
+SwContact* GetUserCall( const SdrObject* pObj )
+{
+ SdrObject *pTmp;
+ while ( !pObj->GetUserCall() && 0 != (pTmp = pObj->GetUpGroup()) )
+ pObj = pTmp;
+ OSL_ENSURE( !pObj->GetUserCall() || pObj->GetUserCall()->ISA(SwContact),
+ "<::GetUserCall(..)> - wrong type of found object user call." );
+ return static_cast<SwContact*>(pObj->GetUserCall());
+}
+
+// liefert sal_True falls das SrdObject ein Marquee-Object (Lauftext) ist
+sal_Bool IsMarqueeTextObj( const SdrObject& rObj )
+{
+ SdrTextAniKind eTKind;
+ return SdrInventor == rObj.GetObjInventor() &&
+ OBJ_TEXT == rObj.GetObjIdentifier() &&
+ ( SDRTEXTANI_SCROLL == ( eTKind = ((SdrTextObj&)rObj).GetTextAniKind())
+ || SDRTEXTANI_ALTERNATE == eTKind || SDRTEXTANI_SLIDE == eTKind );
+}
+
+/*************************************************************************
+|*
+|* SwContact, Ctor und Dtor
+|*
+|*************************************************************************/
+
+SwContact::SwContact( SwFrmFmt *pToRegisterIn ) :
+ SwClient( pToRegisterIn ),
+ mbInDTOR( false )
+{}
+
+SwContact::~SwContact()
+{
+ SetInDTOR();
+}
+
+bool SwContact::IsInDTOR() const
+{
+ return mbInDTOR;
+}
+
+void SwContact::SetInDTOR()
+{
+ mbInDTOR = true;
+}
+
+/** method to move drawing object to corresponding visible layer
+
+ @author OD
+*/
+void SwContact::MoveObjToVisibleLayer( SdrObject* _pDrawObj )
+{
+ // --> OD 2005-06-08 #i46297# - notify background about the arriving of
+ // the object and invalidate its position.
+ const bool bNotify( !GetFmt()->getIDocumentDrawModelAccess()->IsVisibleLayerId( _pDrawObj->GetLayer() ) );
+ // <--
+
+ _MoveObjToLayer( true, _pDrawObj );
+
+ // --> OD 2005-05-23 #i46297#
+ if ( bNotify )
+ {
+ SwAnchoredObject* pAnchoredObj = GetAnchoredObj( _pDrawObj );
+ OSL_ENSURE( pAnchoredObj,
+ "<SwContact::MoveObjToInvisibleLayer(..)> - missing anchored object" );
+ if ( pAnchoredObj )
+ {
+ ::setContextWritingMode( _pDrawObj, pAnchoredObj->GetAnchorFrmContainingAnchPos() );
+ // Note: as-character anchored objects aren't registered at a page frame and
+ // a notification of its background isn't needed.
+ if ( pAnchoredObj->GetPageFrm() )
+ {
+ ::Notify_Background( _pDrawObj, pAnchoredObj->GetPageFrm(),
+ pAnchoredObj->GetObjRect(), PREP_FLY_ARRIVE, sal_True );
+ }
+
+ pAnchoredObj->InvalidateObjPos();
+ }
+ }
+ // <--
+}
+
+/** method to move drawing object to corresponding invisible layer
+
+ OD 21.08.2003 #i18447#
+
+ @author OD
+*/
+void SwContact::MoveObjToInvisibleLayer( SdrObject* _pDrawObj )
+{
+ // --> OD 2005-06-08 #i46297# - notify background about the leaving of the object.
+ const bool bNotify( GetFmt()->getIDocumentDrawModelAccess()->IsVisibleLayerId( _pDrawObj->GetLayer() ) );
+ // <--
+
+ _MoveObjToLayer( false, _pDrawObj );
+
+ // --> OD 2005-05-19 #i46297#
+ if ( bNotify )
+ {
+ SwAnchoredObject* pAnchoredObj = GetAnchoredObj( _pDrawObj );
+ OSL_ENSURE( pAnchoredObj,
+ "<SwContact::MoveObjToInvisibleLayer(..)> - missing anchored object" );
+ // Note: as-character anchored objects aren't registered at a page frame and
+ // a notification of its background isn't needed.
+ if ( pAnchoredObj && pAnchoredObj->GetPageFrm() )
+ {
+ ::Notify_Background( _pDrawObj, pAnchoredObj->GetPageFrm(),
+ pAnchoredObj->GetObjRect(), PREP_FLY_LEAVE, sal_True );
+ }
+ }
+ // <--
+}
+
+/** method to move object to visible/invisible layer
+
+ OD 21.08.2003 #i18447#
+ implementation for the public method <MoveObjToVisibleLayer(..)>
+ and <MoveObjToInvisibleLayer(..)>
+
+ @author OD
+*/
+void SwContact::_MoveObjToLayer( const bool _bToVisible,
+ SdrObject* _pDrawObj )
+{
+ if ( !_pDrawObj )
+ {
+ OSL_FAIL( "SwDrawContact::_MoveObjToLayer(..) - no drawing object!" );
+ return;
+ }
+
+ if ( !GetRegisteredIn() )
+ {
+ OSL_FAIL( "SwDrawContact::_MoveObjToLayer(..) - no drawing frame format!" );
+ return;
+ }
+
+ const IDocumentDrawModelAccess* pIDDMA = static_cast<SwFrmFmt*>(GetRegisteredInNonConst())->getIDocumentDrawModelAccess();
+ if ( !pIDDMA )
+ {
+ OSL_FAIL( "SwDrawContact::_MoveObjToLayer(..) - no writer document!" );
+ return;
+ }
+
+ SdrLayerID nToHellLayerId =
+ _bToVisible ? pIDDMA->GetHellId() : pIDDMA->GetInvisibleHellId();
+ SdrLayerID nToHeavenLayerId =
+ _bToVisible ? pIDDMA->GetHeavenId() : pIDDMA->GetInvisibleHeavenId();
+ SdrLayerID nToControlLayerId =
+ _bToVisible ? pIDDMA->GetControlsId() : pIDDMA->GetInvisibleControlsId();
+ SdrLayerID nFromHellLayerId =
+ _bToVisible ? pIDDMA->GetInvisibleHellId() : pIDDMA->GetHellId();
+ SdrLayerID nFromHeavenLayerId =
+ _bToVisible ? pIDDMA->GetInvisibleHeavenId() : pIDDMA->GetHeavenId();
+ SdrLayerID nFromControlLayerId =
+ _bToVisible ? pIDDMA->GetInvisibleControlsId() : pIDDMA->GetControlsId();
+
+ if ( _pDrawObj->ISA( SdrObjGroup ) )
+ {
+ // determine layer for group object
+ {
+ // proposed layer of a group object is the hell layer
+ SdrLayerID nNewLayerId = nToHellLayerId;
+ if ( ::CheckControlLayer( _pDrawObj ) )
+ {
+ // it has to be the control layer, if one of the member
+ // is a control
+ nNewLayerId = nToControlLayerId;
+ }
+ else if ( _pDrawObj->GetLayer() == pIDDMA->GetHeavenId() ||
+ _pDrawObj->GetLayer() == pIDDMA->GetInvisibleHeavenId() )
+ {
+ // it has to be the heaven layer, if method <GetLayer()> reveals
+ // a heaven layer
+ nNewLayerId = nToHeavenLayerId;
+ }
+ // set layer at group object, but do *not* broadcast and
+ // no propagation to the members.
+ // Thus, call <NbcSetLayer(..)> at super class
+ _pDrawObj->SdrObject::NbcSetLayer( nNewLayerId );
+ }
+
+ // call method recursively for group object members
+ const SdrObjList* pLst =
+ static_cast<SdrObjGroup*>(_pDrawObj)->GetSubList();
+ if ( pLst )
+ {
+ for ( sal_uInt16 i = 0; i < pLst->GetObjCount(); ++i )
+ {
+ _MoveObjToLayer( _bToVisible, pLst->GetObj( i ) );
+ }
+ }
+ }
+ else
+ {
+ const SdrLayerID nLayerIdOfObj = _pDrawObj->GetLayer();
+ if ( nLayerIdOfObj == nFromHellLayerId )
+ {
+ _pDrawObj->SetLayer( nToHellLayerId );
+ }
+ else if ( nLayerIdOfObj == nFromHeavenLayerId )
+ {
+ _pDrawObj->SetLayer( nToHeavenLayerId );
+ }
+ else if ( nLayerIdOfObj == nFromControlLayerId )
+ {
+ _pDrawObj->SetLayer( nToControlLayerId );
+ }
+ }
+}
+
+// -------------------------------------------------------------------------
+// some virtual helper methods for information
+// about the object (Writer fly frame resp. drawing object)
+
+const SwIndex& SwContact::GetCntntAnchorIndex() const
+{
+ return GetCntntAnchor().nContent;
+}
+
+/** get minimum order number of anchored objects handled by with contact
+
+ @author
+*/
+sal_uInt32 SwContact::GetMinOrdNum() const
+{
+ sal_uInt32 nMinOrdNum( SAL_MAX_UINT32 );
+
+ std::list< SwAnchoredObject* > aObjs;
+ GetAnchoredObjs( aObjs );
+
+ while ( !aObjs.empty() )
+ {
+ sal_uInt32 nTmpOrdNum = aObjs.back()->GetDrawObj()->GetOrdNum();
+
+ if ( nTmpOrdNum < nMinOrdNum )
+ {
+ nMinOrdNum = nTmpOrdNum;
+ }
+
+ aObjs.pop_back();
+ }
+
+ OSL_ENSURE( nMinOrdNum != SAL_MAX_UINT32,
+ "<SwContact::GetMinOrdNum()> - no order number found." );
+ return nMinOrdNum;
+}
+
+/** get maximum order number of anchored objects handled by with contact
+
+ @author
+*/
+sal_uInt32 SwContact::GetMaxOrdNum() const
+{
+ sal_uInt32 nMaxOrdNum( 0L );
+
+ std::list< SwAnchoredObject* > aObjs;
+ GetAnchoredObjs( aObjs );
+
+ while ( !aObjs.empty() )
+ {
+ sal_uInt32 nTmpOrdNum = aObjs.back()->GetDrawObj()->GetOrdNum();
+
+ if ( nTmpOrdNum > nMaxOrdNum )
+ {
+ nMaxOrdNum = nTmpOrdNum;
+ }
+
+ aObjs.pop_back();
+ }
+
+ return nMaxOrdNum;
+}
+// -------------------------------------------------------------------------
+
+/*************************************************************************
+|*
+|* SwFlyDrawContact, Ctor und Dtor
+|*
+|*************************************************************************/
+
+SwFlyDrawContact::SwFlyDrawContact( SwFlyFrmFmt *pToRegisterIn, SdrModel * ) :
+ SwContact( pToRegisterIn )
+{
+ // OD 2004-04-01 #i26791# - class <SwFlyDrawContact> contains the 'master'
+ // drawing object of type <SwFlyDrawObj> on its own.
+ mpMasterObj = new SwFlyDrawObj;
+ mpMasterObj->SetOrdNum( 0xFFFFFFFE );
+ mpMasterObj->SetUserCall( this );
+}
+
+SwFlyDrawContact::~SwFlyDrawContact()
+{
+ if ( mpMasterObj )
+ {
+ mpMasterObj->SetUserCall( 0 );
+ if ( mpMasterObj->GetPage() )
+ mpMasterObj->GetPage()->RemoveObject( mpMasterObj->GetOrdNum() );
+ delete mpMasterObj;
+ }
+}
+
+// OD 2004-03-29 #i26791#
+const SwAnchoredObject* SwFlyDrawContact::GetAnchoredObj( const SdrObject* _pSdrObj ) const
+{
+ OSL_ENSURE( _pSdrObj,
+ "<SwFlyDrawContact::GetAnchoredObj(..)> - no object provided" );
+ OSL_ENSURE( _pSdrObj->ISA(SwVirtFlyDrawObj),
+ "<SwFlyDrawContact::GetAnchoredObj(..)> - wrong object type object provided" );
+ OSL_ENSURE( GetUserCall( _pSdrObj ) == const_cast<SwFlyDrawContact*>(this),
+ "<SwFlyDrawContact::GetAnchoredObj(..)> - provided object doesn't belongs to this contact" );
+
+ const SwAnchoredObject* pRetAnchoredObj = 0L;
+
+ if ( _pSdrObj && _pSdrObj->ISA(SwVirtFlyDrawObj) )
+ {
+ pRetAnchoredObj = static_cast<const SwVirtFlyDrawObj*>(_pSdrObj)->GetFlyFrm();
+ }
+
+ return pRetAnchoredObj;
+}
+
+SwAnchoredObject* SwFlyDrawContact::GetAnchoredObj( SdrObject* _pSdrObj )
+{
+ OSL_ENSURE( _pSdrObj,
+ "<SwFlyDrawContact::GetAnchoredObj(..)> - no object provided" );
+ OSL_ENSURE( _pSdrObj->ISA(SwVirtFlyDrawObj),
+ "<SwFlyDrawContact::GetAnchoredObj(..)> - wrong object type provided" );
+ OSL_ENSURE( GetUserCall( _pSdrObj ) == this,
+ "<SwFlyDrawContact::GetAnchoredObj(..)> - provided object doesn't belongs to this contact" );
+
+ SwAnchoredObject* pRetAnchoredObj = 0L;
+
+ if ( _pSdrObj && _pSdrObj->ISA(SwVirtFlyDrawObj) )
+ {
+ pRetAnchoredObj = static_cast<SwVirtFlyDrawObj*>(_pSdrObj)->GetFlyFrm();
+ }
+
+ return pRetAnchoredObj;
+}
+
+const SdrObject* SwFlyDrawContact::GetMaster() const
+{
+ return mpMasterObj;
+}
+
+SdrObject* SwFlyDrawContact::GetMaster()
+{
+ return mpMasterObj;
+}
+
+void SwFlyDrawContact::SetMaster( SdrObject* _pNewMaster )
+{
+ OSL_ENSURE( _pNewMaster->ISA(SwFlyDrawObj),
+ "<SwFlyDrawContact::SetMaster(..)> - wrong type of new master object" );
+ mpMasterObj = static_cast<SwFlyDrawObj *>(_pNewMaster);
+}
+
+/*************************************************************************
+|*
+|* SwFlyDrawContact::Modify()
+|*
+|*************************************************************************/
+
+void SwFlyDrawContact::Modify( const SfxPoolItem*, const SfxPoolItem * )
+{
+}
+
+// override method to control Writer fly frames,
+// which are linked, and to assure that all objects anchored at/inside the
+// Writer fly frame are also made visible.
+void SwFlyDrawContact::MoveObjToVisibleLayer( SdrObject* _pDrawObj )
+{
+ OSL_ENSURE( _pDrawObj->ISA(SwVirtFlyDrawObj),
+ "<SwFlyDrawContact::MoveObjToVisibleLayer(..)> - wrong SdrObject type -> crash" );
+
+ if ( GetFmt()->getIDocumentDrawModelAccess()->IsVisibleLayerId( _pDrawObj->GetLayer() ) )
+ {
+ // nothing to do
+ return;
+ }
+
+ SwFlyFrm* pFlyFrm = static_cast<SwVirtFlyDrawObj*>(_pDrawObj)->GetFlyFrm();
+
+ // --> OD 2005-03-09 #i44464# - consider, that Writer fly frame content
+ // already exists - (e.g. WW8 document is inserted into a existing document).
+ if ( !pFlyFrm->Lower() )
+ {
+ pFlyFrm->InsertColumns();
+ pFlyFrm->Chain( pFlyFrm->AnchorFrm() );
+ pFlyFrm->InsertCnt();
+ }
+ if ( pFlyFrm->GetDrawObjs() )
+ {
+ for ( sal_uInt8 i = 0; i < pFlyFrm->GetDrawObjs()->Count(); ++i)
+ {
+ // --> OD 2004-07-01 #i28701# - consider type of objects in sorted object list.
+ SdrObject* pObj = (*pFlyFrm->GetDrawObjs())[i]->DrawObj();
+ SwContact* pContact = static_cast<SwContact*>(pObj->GetUserCall());
+ pContact->MoveObjToVisibleLayer( pObj );
+ }
+ }
+
+ // make fly frame visible
+ SwContact::MoveObjToVisibleLayer( _pDrawObj );
+}
+
+// override method to control Writer fly frames,
+// which are linked, and to assure that all objects anchored at/inside the
+// Writer fly frame are also made invisible.
+void SwFlyDrawContact::MoveObjToInvisibleLayer( SdrObject* _pDrawObj )
+{
+ OSL_ENSURE( _pDrawObj->ISA(SwVirtFlyDrawObj),
+ "<SwFlyDrawContact::MoveObjToInvisibleLayer(..)> - wrong SdrObject type -> crash" );
+
+ if ( !GetFmt()->getIDocumentDrawModelAccess()->IsVisibleLayerId( _pDrawObj->GetLayer() ) )
+ {
+ // nothing to do
+ return;
+ }
+
+ SwFlyFrm* pFlyFrm = static_cast<SwVirtFlyDrawObj*>(_pDrawObj)->GetFlyFrm();
+
+ pFlyFrm->Unchain();
+ pFlyFrm->DeleteCnt();
+ if ( pFlyFrm->GetDrawObjs() )
+ {
+ for ( sal_uInt8 i = 0; i < pFlyFrm->GetDrawObjs()->Count(); ++i)
+ {
+ // --> OD 2004-07-01 #i28701# - consider type of objects in sorted object list.
+ SdrObject* pObj = (*pFlyFrm->GetDrawObjs())[i]->DrawObj();
+ SwContact* pContact = static_cast<SwContact*>(pObj->GetUserCall());
+ pContact->MoveObjToInvisibleLayer( pObj );
+ }
+ }
+
+ // make fly frame invisible
+ SwContact::MoveObjToInvisibleLayer( _pDrawObj );
+}
+
+/** get data collection of anchored objects, handled by with contact
+
+ @author
+*/
+void SwFlyDrawContact::GetAnchoredObjs( std::list<SwAnchoredObject*>& _roAnchoredObjs ) const
+{
+ const SwFrmFmt* pFmt = GetFmt();
+ SwFlyFrm::GetAnchoredObjects( _roAnchoredObjs, *pFmt );
+}
+
+/*************************************************************************
+|*
+|* SwDrawContact, Ctor+Dtor
+|*
+|*************************************************************************/
+bool CheckControlLayer( const SdrObject *pObj )
+{
+ if ( FmFormInventor == pObj->GetObjInventor() )
+ return true;
+ if ( pObj->ISA( SdrObjGroup ) )
+ {
+ const SdrObjList *pLst = ((SdrObjGroup*)pObj)->GetSubList();
+ for ( sal_uInt16 i = 0; i < pLst->GetObjCount(); ++i )
+ {
+ if ( ::CheckControlLayer( pLst->GetObj( i ) ) )
+ {
+ // OD 21.08.2003 #i18447# - return correct value ;-)
+ return true;
+ }
+ }
+ }
+ return false;
+}
+
+SwDrawContact::SwDrawContact( SwFrmFmt* pToRegisterIn, SdrObject* pObj ) :
+ SwContact( pToRegisterIn ),
+ maAnchoredDrawObj(),
+ mbMasterObjCleared( false ),
+ mbDisconnectInProgress( false ),
+ mbUserCallActive( false ),
+ // Note: value of <meEventTypeOfCurrentUserCall> isn't of relevance, because
+ // <mbUserCallActive> is sal_False.
+ meEventTypeOfCurrentUserCall( SDRUSERCALL_MOVEONLY )
+{
+ // clear list containing 'virtual' drawing objects.
+ maDrawVirtObjs.clear();
+
+ // --> #i33909# - assure, that drawing object is inserted
+ // in the drawing page.
+ if ( !pObj->IsInserted() )
+ {
+ pToRegisterIn->getIDocumentDrawModelAccess()->GetDrawModel()->GetPage(0)->
+ InsertObject( pObj, pObj->GetOrdNumDirect() );
+ }
+ // <--
+
+ //Controls muessen immer im Control-Layer liegen. Das gilt auch fuer
+ //Gruppenobjekte, wenn diese Controls enthalten.
+ if ( ::CheckControlLayer( pObj ) )
+ {
+ // set layer of object to corresponding invisible layer.
+ pObj->SetLayer( pToRegisterIn->getIDocumentDrawModelAccess()->GetInvisibleControlsId() );
+ }
+
+ // #i26791#
+ pObj->SetUserCall( this );
+ maAnchoredDrawObj.SetDrawObj( *pObj );
+
+ // if there already exists an SwXShape for the object, ensure it knows about us, and the SdrObject
+ // #i99056#
+ SwXShape::AddExistingShapeToFmt( *pObj );
+}
+
+SwDrawContact::~SwDrawContact()
+{
+ SetInDTOR();
+
+ DisconnectFromLayout();
+
+ // remove 'master' from drawing page
+ RemoveMasterFromDrawPage();
+
+ // remove and destroy 'virtual' drawing objects.
+ RemoveAllVirtObjs();
+
+ if ( !mbMasterObjCleared )
+ {
+ SdrObject* pObject = const_cast< SdrObject* >( maAnchoredDrawObj.GetDrawObj() );
+ SdrObject::Free( pObject );
+ }
+}
+
+void SwDrawContact::GetTextObjectsFromFmt( std::list<SdrTextObj*>& rTextObjects, SwDoc* pDoc )
+{
+ for( sal_Int32 n=0; n<pDoc->GetSpzFrmFmts()->Count(); n++ )
+ {
+ SwFrmFmt* pFly = (*pDoc->GetSpzFrmFmts())[n];
+ if( pFly->IsA( TYPE(SwDrawFrmFmt) ) )
+ {
+ std::list<SdrTextObj*> aTextObjs;
+ SwDrawContact* pContact = SwIterator<SwDrawContact,SwFrmFmt>::FirstElement(*pFly);
+ if( pContact )
+ {
+ SdrObject* pSdrO = pContact->GetMaster();
+ if ( pSdrO )
+ {
+ if ( pSdrO->IsA( TYPE(SdrObjGroup) ) )
+ {
+ SdrObjListIter aListIter( *pSdrO, IM_DEEPNOGROUPS );
+ //iterate inside of a grouped object
+ while( aListIter.IsMore() )
+ {
+ SdrObject* pSdrOElement = aListIter.Next();
+ if( pSdrOElement && pSdrOElement->IsA( TYPE(SdrTextObj) ) &&
+ static_cast<SdrTextObj*>( pSdrOElement)->HasText() )
+ {
+ rTextObjects.push_back((SdrTextObj*) pSdrOElement);
+ }
+ }
+ }
+ else if( pSdrO->IsA( TYPE(SdrTextObj) ) &&
+ static_cast<SdrTextObj*>( pSdrO )->HasText() )
+ {
+ rTextObjects.push_back((SdrTextObj*) pSdrO);
+ }
+ }
+ }
+ }
+ }
+}
+
+// OD 2004-03-29 #i26791#
+const SwAnchoredObject* SwDrawContact::GetAnchoredObj( const SdrObject* _pSdrObj ) const
+{
+ // handle default parameter value
+ if ( !_pSdrObj )
+ {
+ _pSdrObj = GetMaster();
+ }
+
+ OSL_ENSURE( _pSdrObj,
+ "<SwDrawContact::GetAnchoredObj(..)> - no object provided" );
+ OSL_ENSURE( _pSdrObj->ISA(SwDrawVirtObj) ||
+ ( !_pSdrObj->ISA(SdrVirtObj) && !_pSdrObj->ISA(SwDrawVirtObj) ),
+ "<SwDrawContact::GetAnchoredObj(..)> - wrong object type object provided" );
+ OSL_ENSURE( GetUserCall( _pSdrObj ) == const_cast<SwDrawContact*>(this) ||
+ _pSdrObj == GetMaster(),
+ "<SwDrawContact::GetAnchoredObj(..)> - provided object doesn't belongs to this contact" );
+
+ const SwAnchoredObject* pRetAnchoredObj = 0L;
+
+ if ( _pSdrObj )
+ {
+ if ( _pSdrObj->ISA(SwDrawVirtObj) )
+ {
+ pRetAnchoredObj = static_cast<const SwDrawVirtObj*>(_pSdrObj)->GetAnchoredObj();
+ }
+ else if ( !_pSdrObj->ISA(SdrVirtObj) && !_pSdrObj->ISA(SwDrawVirtObj) )
+ {
+ pRetAnchoredObj = &maAnchoredDrawObj;
+ }
+ }
+
+ return pRetAnchoredObj;
+}
+
+SwAnchoredObject* SwDrawContact::GetAnchoredObj( SdrObject* _pSdrObj )
+{
+ // handle default parameter value
+ if ( !_pSdrObj )
+ {
+ _pSdrObj = GetMaster();
+ }
+
+ OSL_ENSURE( _pSdrObj,
+ "<SwDrawContact::GetAnchoredObj(..)> - no object provided" );
+ OSL_ENSURE( _pSdrObj->ISA(SwDrawVirtObj) ||
+ ( !_pSdrObj->ISA(SdrVirtObj) && !_pSdrObj->ISA(SwDrawVirtObj) ),
+ "<SwDrawContact::GetAnchoredObj(..)> - wrong object type object provided" );
+ OSL_ENSURE( GetUserCall( _pSdrObj ) == this || _pSdrObj == GetMaster(),
+ "<SwDrawContact::GetAnchoredObj(..)> - provided object doesn't belongs to this contact" );
+
+ SwAnchoredObject* pRetAnchoredObj = 0L;
+
+ if ( _pSdrObj )
+ {
+ if ( _pSdrObj->ISA(SwDrawVirtObj) )
+ {
+ pRetAnchoredObj = static_cast<SwDrawVirtObj*>(_pSdrObj)->AnchoredObj();
+ }
+ else if ( !_pSdrObj->ISA(SdrVirtObj) && !_pSdrObj->ISA(SwDrawVirtObj) )
+ {
+ pRetAnchoredObj = &maAnchoredDrawObj;
+ }
+ }
+
+ return pRetAnchoredObj;
+}
+
+const SdrObject* SwDrawContact::GetMaster() const
+{
+ return !mbMasterObjCleared
+ ? maAnchoredDrawObj.GetDrawObj()
+ : 0L;
+}
+
+SdrObject* SwDrawContact::GetMaster()
+{
+ return !mbMasterObjCleared
+ ? maAnchoredDrawObj.DrawObj()
+ : 0L;
+}
+
+// overload <SwContact::SetMaster(..)> in order to
+// assert, if the 'master' drawing object is replaced.
+// replace of master object correctly handled, if
+// handled by method <SwDrawContact::ChangeMasterObject(..)>. Thus, assert
+// only, if a debug level is given.
+void SwDrawContact::SetMaster( SdrObject* _pNewMaster )
+{
+ if ( _pNewMaster )
+ {
+#if OSL_DEBUG_LEVEL > 1
+ OSL_FAIL( "debug notification - master replaced!" );
+#endif
+ maAnchoredDrawObj.SetDrawObj( *_pNewMaster );
+ }
+ else
+ {
+ mbMasterObjCleared = true;
+ }
+}
+
+const SwFrm* SwDrawContact::GetAnchorFrm( const SdrObject* _pDrawObj ) const
+{
+ const SwFrm* pAnchorFrm = 0L;
+ if ( !_pDrawObj ||
+ _pDrawObj == GetMaster() ||
+ ( !_pDrawObj->GetUserCall() &&
+ GetUserCall( _pDrawObj ) == static_cast<const SwContact* const>(this) ) )
+ {
+ pAnchorFrm = maAnchoredDrawObj.GetAnchorFrm();
+ }
+ else if ( _pDrawObj->ISA(SwDrawVirtObj) )
+ {
+ pAnchorFrm = static_cast<const SwDrawVirtObj*>(_pDrawObj)->GetAnchorFrm();
+ }
+ else
+ {
+ OSL_FAIL( "<SwDrawContact::GetAnchorFrm(..)> - unknown drawing object." );
+ }
+
+ return pAnchorFrm;
+}
+SwFrm* SwDrawContact::GetAnchorFrm( SdrObject* _pDrawObj )
+{
+ SwFrm* pAnchorFrm = 0L;
+ if ( !_pDrawObj ||
+ _pDrawObj == GetMaster() ||
+ ( !_pDrawObj->GetUserCall() &&
+ GetUserCall( _pDrawObj ) == this ) )
+ {
+ pAnchorFrm = maAnchoredDrawObj.AnchorFrm();
+ }
+ else
+ {
+ OSL_ENSURE( _pDrawObj->ISA(SwDrawVirtObj),
+ "<SwDrawContact::GetAnchorFrm(..)> - unknown drawing object." );
+ pAnchorFrm = static_cast<SwDrawVirtObj*>(_pDrawObj)->AnchorFrm();
+ }
+
+ return pAnchorFrm;
+}
+
+// method to create a new 'virtual' drawing object.
+SwDrawVirtObj* SwDrawContact::CreateVirtObj()
+{
+ // determine 'master'
+ SdrObject* pOrgMasterSdrObj = GetMaster();
+
+ // create 'virtual' drawing object
+ SwDrawVirtObj* pNewDrawVirtObj = new SwDrawVirtObj ( *(pOrgMasterSdrObj), *(this) );
+
+ // add new 'virtual' drawing object managing data structure
+ maDrawVirtObjs.push_back( pNewDrawVirtObj );
+
+ return pNewDrawVirtObj;
+}
+
+// destroys a given 'virtual' drawing object.
+// side effect: 'virtual' drawing object is removed from data structure
+// <maDrawVirtObjs>.
+void SwDrawContact::DestroyVirtObj( SwDrawVirtObj* _pVirtObj )
+{
+ if ( _pVirtObj )
+ {
+ delete _pVirtObj;
+ _pVirtObj = 0;
+ }
+}
+
+// add a 'virtual' drawing object to drawing page.
+// Use an already created one, which isn't used, or create a new one.
+SwDrawVirtObj* SwDrawContact::AddVirtObj()
+{
+ SwDrawVirtObj* pAddedDrawVirtObj = 0L;
+
+ // check, if a disconnected 'virtual' drawing object exist and use it
+ std::list<SwDrawVirtObj*>::const_iterator aFoundVirtObjIter =
+ std::find_if( maDrawVirtObjs.begin(), maDrawVirtObjs.end(),
+ UsedOrUnusedVirtObjPred( false ) );
+
+ if ( aFoundVirtObjIter != maDrawVirtObjs.end() )
+ {
+ // use already created, disconnected 'virtual' drawing object
+ pAddedDrawVirtObj = (*aFoundVirtObjIter);
+ }
+ else
+ {
+ // create new 'virtual' drawing object.
+ pAddedDrawVirtObj = CreateVirtObj();
+ }
+ pAddedDrawVirtObj->AddToDrawingPage();
+
+ return pAddedDrawVirtObj;
+}
+
+// remove 'virtual' drawing objects and destroy them.
+void SwDrawContact::RemoveAllVirtObjs()
+{
+ for ( std::list<SwDrawVirtObj*>::iterator aDrawVirtObjsIter = maDrawVirtObjs.begin();
+ aDrawVirtObjsIter != maDrawVirtObjs.end();
+ ++aDrawVirtObjsIter )
+ {
+ // remove and destroy 'virtual object'
+ SwDrawVirtObj* pDrawVirtObj = (*aDrawVirtObjsIter);
+ pDrawVirtObj->RemoveFromWriterLayout();
+ pDrawVirtObj->RemoveFromDrawingPage();
+ DestroyVirtObj( pDrawVirtObj );
+ }
+ maDrawVirtObjs.clear();
+}
+
+SwDrawContact::VirtObjAnchoredAtFrmPred::VirtObjAnchoredAtFrmPred(
+ const SwFrm& _rAnchorFrm )
+ : mpAnchorFrm( &_rAnchorFrm )
+{
+ if ( mpAnchorFrm->IsCntntFrm() )
+ {
+ const SwCntntFrm* pTmpFrm =
+ static_cast<const SwCntntFrm*>( mpAnchorFrm );
+ while ( pTmpFrm->IsFollow() )
+ {
+ pTmpFrm = pTmpFrm->FindMaster();
+ }
+ mpAnchorFrm = pTmpFrm;
+ }
+}
+
+// OD 2004-04-14 #i26791# - compare with master frame
+bool SwDrawContact::VirtObjAnchoredAtFrmPred::operator() ( const SwDrawVirtObj* _pDrawVirtObj )
+{
+ const SwFrm* pObjAnchorFrm = _pDrawVirtObj->GetAnchorFrm();
+ if ( pObjAnchorFrm && pObjAnchorFrm->IsCntntFrm() )
+ {
+ const SwCntntFrm* pTmpFrm =
+ static_cast<const SwCntntFrm*>( pObjAnchorFrm );
+ while ( pTmpFrm->IsFollow() )
+ {
+ pTmpFrm = pTmpFrm->FindMaster();
+ }
+ pObjAnchorFrm = pTmpFrm;
+ }
+
+ return ( pObjAnchorFrm == mpAnchorFrm );
+}
+
+// get drawing object ('master' or 'virtual') by frame.
+SdrObject* SwDrawContact::GetDrawObjectByAnchorFrm( const SwFrm& _rAnchorFrm )
+{
+ SdrObject* pRetDrawObj = 0L;
+
+ // #i26791# - compare master frames instead of direct frames
+ const SwFrm* pProposedAnchorFrm = &_rAnchorFrm;
+ if ( pProposedAnchorFrm->IsCntntFrm() )
+ {
+ const SwCntntFrm* pTmpFrm =
+ static_cast<const SwCntntFrm*>( pProposedAnchorFrm );
+ while ( pTmpFrm->IsFollow() )
+ {
+ pTmpFrm = pTmpFrm->FindMaster();
+ }
+ pProposedAnchorFrm = pTmpFrm;
+ }
+
+ const SwFrm* pMasterObjAnchorFrm = GetAnchorFrm();
+ if ( pMasterObjAnchorFrm && pMasterObjAnchorFrm->IsCntntFrm() )
+ {
+ const SwCntntFrm* pTmpFrm =
+ static_cast<const SwCntntFrm*>( pMasterObjAnchorFrm );
+ while ( pTmpFrm->IsFollow() )
+ {
+ pTmpFrm = pTmpFrm->FindMaster();
+ }
+ pMasterObjAnchorFrm = pTmpFrm;
+ }
+
+ if ( pMasterObjAnchorFrm && pMasterObjAnchorFrm == pProposedAnchorFrm )
+ {
+ pRetDrawObj = GetMaster();
+ }
+ else
+ {
+ std::list<SwDrawVirtObj*>::const_iterator aFoundVirtObjIter =
+ std::find_if( maDrawVirtObjs.begin(), maDrawVirtObjs.end(),
+ VirtObjAnchoredAtFrmPred( *pProposedAnchorFrm ) );
+
+ if ( aFoundVirtObjIter != maDrawVirtObjs.end() )
+ {
+ pRetDrawObj = (*aFoundVirtObjIter);
+ }
+ }
+
+ return pRetDrawObj;
+}
+
+/*************************************************************************
+|*
+|* SwDrawContact::Changed
+|*
+|*************************************************************************/
+
+void SwDrawContact::NotifyBackgrdOfAllVirtObjs( const Rectangle* pOldBoundRect )
+{
+ for ( std::list<SwDrawVirtObj*>::iterator aDrawVirtObjIter = maDrawVirtObjs.begin();
+ aDrawVirtObjIter != maDrawVirtObjs.end();
+ ++aDrawVirtObjIter )
+ {
+ SwDrawVirtObj* pDrawVirtObj = (*aDrawVirtObjIter);
+ if ( pDrawVirtObj->GetAnchorFrm() )
+ {
+ // #i34640# - determine correct page frame
+ SwPageFrm* pPage = pDrawVirtObj->AnchoredObj()->FindPageFrmOfAnchor();
+ if( pOldBoundRect && pPage )
+ {
+ SwRect aOldRect( *pOldBoundRect );
+ aOldRect.Pos() += pDrawVirtObj->GetOffset();
+ if( aOldRect.HasArea() )
+ ::Notify_Background( pDrawVirtObj, pPage,
+ aOldRect, PREP_FLY_LEAVE,sal_True);
+ }
+ // #i34640# - include spacing for wrapping
+ SwRect aRect( pDrawVirtObj->GetAnchoredObj()->GetObjRectWithSpaces() );
+ if( aRect.HasArea() )
+ {
+ SwPageFrm* pPg = (SwPageFrm*)::FindPage( aRect, pPage );
+ if ( pPg )
+ ::Notify_Background( pDrawVirtObj, pPg, aRect,
+ PREP_FLY_ARRIVE, sal_True );
+ }
+ ::ClrContourCache( pDrawVirtObj );
+ }
+ }
+}
+
+// OD 2004-04-08 #i26791# - local method to notify the background for a drawing object
+void lcl_NotifyBackgroundOfObj( SwDrawContact& _rDrawContact,
+ const SdrObject& _rObj,
+ const Rectangle* _pOldObjRect )
+{
+ // --> OD 2004-10-21 #i34640#
+ SwAnchoredObject* pAnchoredObj =
+ const_cast<SwAnchoredObject*>(_rDrawContact.GetAnchoredObj( &_rObj ));
+ if ( pAnchoredObj && pAnchoredObj->GetAnchorFrm() )
+ // <--
+ {
+ // --> OD 2004-10-21 #i34640# - determine correct page frame
+ SwPageFrm* pPageFrm = pAnchoredObj->FindPageFrmOfAnchor();
+ // <--
+ if( _pOldObjRect && pPageFrm )
+ {
+ SwRect aOldRect( *_pOldObjRect );
+ if( aOldRect.HasArea() )
+ {
+ // --> OD 2004-10-21 #i34640# - determine correct page frame
+ SwPageFrm* pOldPageFrm = (SwPageFrm*)::FindPage( aOldRect, pPageFrm );
+ // <--
+ ::Notify_Background( &_rObj, pOldPageFrm, aOldRect,
+ PREP_FLY_LEAVE, sal_True);
+ }
+ }
+ // --> OD 2004-10-21 #i34640# - include spacing for wrapping
+ SwRect aNewRect( pAnchoredObj->GetObjRectWithSpaces() );
+ // <--
+ if( aNewRect.HasArea() && pPageFrm )
+ {
+ pPageFrm = (SwPageFrm*)::FindPage( aNewRect, pPageFrm );
+ ::Notify_Background( &_rObj, pPageFrm, aNewRect,
+ PREP_FLY_ARRIVE, sal_True );
+ }
+ ClrContourCache( &_rObj );
+ }
+}
+
+void SwDrawContact::Changed( const SdrObject& rObj,
+ SdrUserCallType eType,
+ const Rectangle& rOldBoundRect )
+{
+ // OD 2004-06-01 #i26791# - no event handling, if existing <ViewShell>
+ // is in contruction
+ SwDoc* pDoc = GetFmt()->GetDoc();
+ if ( pDoc->GetCurrentViewShell() &&
+ pDoc->GetCurrentViewShell()->IsInConstructor() )
+ {
+ return;
+ }
+
+ // --> OD 2005-03-08 #i44339#
+ // no event handling, if document is in destruction.
+ // Exception: It's the SDRUSERCALL_DELETE event
+ if ( pDoc->IsInDtor() && eType != SDRUSERCALL_DELETE )
+ {
+ return;
+ }
+ // <--
+
+ //Action aufsetzen, aber nicht wenn gerade irgendwo eine Action laeuft.
+ ViewShell *pSh = 0, *pOrg;
+ SwRootFrm *pTmpRoot = pDoc->GetCurrentLayout();//swmod 080317
+ if ( pTmpRoot && pTmpRoot->IsCallbackActionEnabled() )
+ {
+ pDoc->GetEditShell( &pOrg );
+ pSh = pOrg;
+ if ( pSh )
+ do
+ { if ( pSh->Imp()->IsAction() || pSh->Imp()->IsIdleAction() )
+ pSh = 0;
+ else
+ pSh = (ViewShell*)pSh->GetNext();
+
+ } while ( pSh && pSh != pOrg );
+
+ if ( pSh )
+ pTmpRoot->StartAllAction();
+ }
+ SdrObjUserCall::Changed( rObj, eType, rOldBoundRect );
+ _Changed( rObj, eType, &rOldBoundRect ); //Achtung, ggf. Suizid!
+
+ if ( pSh )
+ pTmpRoot->EndAllAction();
+}
+
+// helper class for method <SwDrawContact::_Changed(..)> for handling nested
+// <SdrObjUserCall> events
+class NestedUserCallHdl
+{
+ private:
+ SwDrawContact* mpDrawContact;
+ bool mbParentUserCallActive;
+ SdrUserCallType meParentUserCallEventType;
+
+ public:
+ NestedUserCallHdl( SwDrawContact* _pDrawContact,
+ SdrUserCallType _eEventType )
+ : mpDrawContact( _pDrawContact ),
+ mbParentUserCallActive( _pDrawContact->mbUserCallActive ),
+ meParentUserCallEventType( _pDrawContact->meEventTypeOfCurrentUserCall )
+ {
+ mpDrawContact->mbUserCallActive = true;
+ mpDrawContact->meEventTypeOfCurrentUserCall = _eEventType;
+ }
+
+ ~NestedUserCallHdl()
+ {
+ if ( mpDrawContact )
+ {
+ mpDrawContact->mbUserCallActive = mbParentUserCallActive;
+ mpDrawContact->meEventTypeOfCurrentUserCall = meParentUserCallEventType;
+ }
+ }
+
+ void DrawContactDeleted()
+ {
+ mpDrawContact = 0;
+ }
+
+ bool IsNestedUserCall() const
+ {
+ return mbParentUserCallActive;
+ }
+
+ void AssertNestedUserCall()
+ {
+ if ( IsNestedUserCall() )
+ {
+ bool bTmpAssert( true );
+ // Currently its known, that a nested event SDRUSERCALL_RESIZE
+ // could occur during parent user call SDRUSERCALL_INSERTED,
+ // SDRUSERCALL_DELETE and SDRUSERCALL_RESIZE for edge objects.
+ // Also possible are nested SDRUSERCALL_CHILD_RESIZE events for
+ // edge objects
+ // Thus, assert all other combinations
+ if ( ( meParentUserCallEventType == SDRUSERCALL_INSERTED ||
+ meParentUserCallEventType == SDRUSERCALL_DELETE ||
+ meParentUserCallEventType == SDRUSERCALL_RESIZE ) &&
+ mpDrawContact->meEventTypeOfCurrentUserCall == SDRUSERCALL_RESIZE )
+ {
+ bTmpAssert = false;
+ }
+ else if ( meParentUserCallEventType == SDRUSERCALL_CHILD_RESIZE &&
+ mpDrawContact->meEventTypeOfCurrentUserCall == SDRUSERCALL_CHILD_RESIZE )
+ {
+ bTmpAssert = false;
+ }
+
+ if ( bTmpAssert )
+ {
+ OSL_FAIL( "<SwDrawContact::_Changed(..)> - unknown nested <UserCall> event. This is serious, please inform OD." );
+ }
+ }
+ }
+};
+
+// <--
+//
+// !!!ACHTUNG!!! The object may commit suicide!!!
+//
+void SwDrawContact::_Changed( const SdrObject& rObj,
+ SdrUserCallType eType,
+ const Rectangle* pOldBoundRect )
+{
+ // suppress handling of nested <SdrObjUserCall> events
+ NestedUserCallHdl aNestedUserCallHdl( this, eType );
+ if ( aNestedUserCallHdl.IsNestedUserCall() )
+ {
+ aNestedUserCallHdl.AssertNestedUserCall();
+ return;
+ }
+ // do *not* notify, if document is destructing
+ // --> OD 2004-10-21 #i35912# - do *not* notify for as-character anchored
+ // drawing objects.
+ // --> OD 2004-11-11 #i35007#
+ // improvement: determine as-character anchored object flag only once.
+ const bool bAnchoredAsChar = ObjAnchoredAsChar();
+ const bool bNotify = !(GetFmt()->GetDoc()->IsInDtor()) &&
+ ( SURROUND_THROUGHT != GetFmt()->GetSurround().GetSurround() ) &&
+ !bAnchoredAsChar;
+ // <--
+ switch( eType )
+ {
+ case SDRUSERCALL_DELETE:
+ {
+ if ( bNotify )
+ {
+ lcl_NotifyBackgroundOfObj( *this, rObj, pOldBoundRect );
+ // --> #i36181# - background of 'virtual'
+ // drawing objects have also been notified.
+ NotifyBackgrdOfAllVirtObjs( pOldBoundRect );
+ // <--
+ }
+ DisconnectFromLayout( false );
+ SetMaster( NULL );
+ delete this;
+ // --> #i65784# Prevent memory corruption
+ aNestedUserCallHdl.DrawContactDeleted();
+ // <--
+ break;
+ }
+ case SDRUSERCALL_INSERTED:
+ {
+ if ( mbDisconnectInProgress )
+ {
+ OSL_FAIL( "<SwDrawContact::_Changed(..)> - Insert event during disconnection from layout is invalid." );
+ }
+ else
+ {
+ ConnectToLayout();
+ if ( bNotify )
+ {
+ lcl_NotifyBackgroundOfObj( *this, rObj, pOldBoundRect );
+ }
+ }
+ break;
+ }
+ case SDRUSERCALL_REMOVED:
+ {
+ if ( bNotify )
+ {
+ lcl_NotifyBackgroundOfObj( *this, rObj, pOldBoundRect );
+ }
+ DisconnectFromLayout( false );
+ break;
+ }
+ case SDRUSERCALL_CHILD_INSERTED :
+ case SDRUSERCALL_CHILD_REMOVED :
+ {
+ // --> #i113730#
+ // force layer of controls for group objects containing control objects
+ if(dynamic_cast< SdrObjGroup* >(maAnchoredDrawObj.DrawObj()))
+ {
+ if(::CheckControlLayer(maAnchoredDrawObj.DrawObj()))
+ {
+ const IDocumentDrawModelAccess* pIDDMA = static_cast<SwFrmFmt*>(GetRegisteredInNonConst())->getIDocumentDrawModelAccess();
+ const SdrLayerID aCurrentLayer(maAnchoredDrawObj.DrawObj()->GetLayer());
+ const SdrLayerID aControlLayerID(pIDDMA->GetControlsId());
+ const SdrLayerID aInvisibleControlLayerID(pIDDMA->GetInvisibleControlsId());
+
+ if(aCurrentLayer != aControlLayerID && aCurrentLayer != aInvisibleControlLayerID)
+ {
+ if ( aCurrentLayer == pIDDMA->GetInvisibleHellId() ||
+ aCurrentLayer == pIDDMA->GetInvisibleHeavenId() )
+ {
+ maAnchoredDrawObj.DrawObj()->SetLayer(aInvisibleControlLayerID);
+ }
+ else
+ {
+ maAnchoredDrawObj.DrawObj()->SetLayer(aControlLayerID);
+ }
+ }
+ }
+ }
+ // fallthrough intended here
+ // <--
+ }
+ case SDRUSERCALL_MOVEONLY:
+ case SDRUSERCALL_RESIZE:
+ case SDRUSERCALL_CHILD_MOVEONLY :
+ case SDRUSERCALL_CHILD_RESIZE :
+ case SDRUSERCALL_CHILD_CHGATTR :
+ case SDRUSERCALL_CHILD_DELETE :
+ case SDRUSERCALL_CHILD_COPY :
+ {
+ // --> OD 2004-08-04 #i31698# - improvement:
+ // get instance <SwAnchoredDrawObject> only once
+ const SwAnchoredDrawObject* pAnchoredDrawObj =
+ static_cast<const SwAnchoredDrawObject*>( GetAnchoredObj( &rObj ) );
+ // <--
+ // OD 2004-04-06 #i26791# - adjust positioning and alignment attributes,
+ // if positioning of drawing object isn't in progress.
+ // --> OD 2005-08-15 #i53320# - no adjust of positioning attributes,
+ // if drawing object isn't positioned.
+ if ( !pAnchoredDrawObj->IsPositioningInProgress() &&
+ !pAnchoredDrawObj->NotYetPositioned() )
+ // <--
+ {
+ // --> OD 2004-09-29 #i34748# - If no last object rectangle is
+ // provided by the anchored object, use parameter <pOldBoundRect>.
+ const Rectangle& aOldObjRect = pAnchoredDrawObj->GetLastObjRect()
+ ? *(pAnchoredDrawObj->GetLastObjRect())
+ : *(pOldBoundRect);
+ // <--
+ // --> OD 2008-02-18 #i79400#
+ // always invalidate object rectangle inclusive spaces
+ pAnchoredDrawObj->InvalidateObjRectWithSpaces();
+ // <--
+ // --> OD 2005-01-28 #i41324# - notify background before
+ // adjusting position
+ if ( bNotify )
+ {
+ // --> OD 2004-07-20 #i31573# - correction: Only invalidate
+ // background of given drawing object.
+ lcl_NotifyBackgroundOfObj( *this, rObj, &aOldObjRect );
+ }
+ // <--
+ // --> OD 2004-08-04 #i31698# - determine layout direction
+ // via draw frame format.
+ SwFrmFmt::tLayoutDir eLayoutDir =
+ pAnchoredDrawObj->GetFrmFmt().GetLayoutDir();
+ // <--
+ // use geometry of drawing object
+ SwRect aObjRect( rObj.GetSnapRect() );
+ // If drawing object is a member of a group, the adjustment
+ // of the positioning and the alignment attributes has to
+ // be done for the top group object.
+ if ( rObj.GetUpGroup() )
+ {
+ const SdrObject* pGroupObj = rObj.GetUpGroup();
+ while ( pGroupObj->GetUpGroup() )
+ {
+ pGroupObj = pGroupObj->GetUpGroup();
+ }
+ // use geometry of drawing object
+ aObjRect = pGroupObj->GetSnapRect();
+ }
+ SwTwips nXPosDiff(0L);
+ SwTwips nYPosDiff(0L);
+ switch ( eLayoutDir )
+ {
+ case SwFrmFmt::HORI_L2R:
+ {
+ nXPosDiff = aObjRect.Left() - aOldObjRect.Left();
+ nYPosDiff = aObjRect.Top() - aOldObjRect.Top();
+ }
+ break;
+ case SwFrmFmt::HORI_R2L:
+ {
+ nXPosDiff = aOldObjRect.Right() - aObjRect.Right();
+ nYPosDiff = aObjRect.Top() - aOldObjRect.Top();
+ }
+ break;
+ case SwFrmFmt::VERT_R2L:
+ {
+ nXPosDiff = aObjRect.Top() - aOldObjRect.Top();
+ nYPosDiff = aOldObjRect.Right() - aObjRect.Right();
+ }
+ break;
+ default:
+ {
+ OSL_FAIL( "<SwDrawContact::_Changed(..)> - unsupported layout direction" );
+ }
+ }
+ SfxItemSet aSet( GetFmt()->GetDoc()->GetAttrPool(),
+ RES_VERT_ORIENT, RES_HORI_ORIENT, 0 );
+ const SwFmtVertOrient& rVert = GetFmt()->GetVertOrient();
+ if ( nYPosDiff != 0 )
+ {
+
+ if ( rVert.GetRelationOrient() == text::RelOrientation::CHAR ||
+ rVert.GetRelationOrient() == text::RelOrientation::TEXT_LINE )
+ {
+ nYPosDiff = -nYPosDiff;
+ }
+ aSet.Put( SwFmtVertOrient( rVert.GetPos()+nYPosDiff,
+ text::VertOrientation::NONE,
+ rVert.GetRelationOrient() ) );
+ }
+
+ const SwFmtHoriOrient& rHori = GetFmt()->GetHoriOrient();
+ if ( !bAnchoredAsChar && nXPosDiff != 0 )
+ {
+ aSet.Put( SwFmtHoriOrient( rHori.GetPos()+nXPosDiff,
+ text::HoriOrientation::NONE,
+ rHori.GetRelationOrient() ) );
+ }
+
+ if ( nYPosDiff ||
+ ( !bAnchoredAsChar && nXPosDiff != 0 ) )
+ {
+ GetFmt()->GetDoc()->SetFlyFrmAttr( *(GetFmt()), aSet );
+ // keep new object rectangle, to avoid multiple
+ // changes of the attributes by multiple event from
+ // the drawing layer - e.g. group objects and its members
+ // --> OD 2004-09-29 #i34748# - use new method
+ // <SwAnchoredDrawObject::SetLastObjRect(..)>.
+ const_cast<SwAnchoredDrawObject*>(pAnchoredDrawObj)
+ ->SetLastObjRect( aObjRect.SVRect() );
+ }
+ else if ( aObjRect.SSize() != aOldObjRect.GetSize() )
+ {
+ _InvalidateObjs();
+ // --> OD 2004-11-11 #i35007# - notify anchor frame
+ // of as-character anchored object
+ if ( bAnchoredAsChar )
+ {
+ const_cast<SwAnchoredDrawObject*>(pAnchoredDrawObj)
+ ->AnchorFrm()->Prepare( PREP_FLY_ATTR_CHG, GetFmt() );
+ }
+ // <--
+ }
+ }
+ }
+ break;
+ case SDRUSERCALL_CHGATTR:
+ if ( bNotify )
+ {
+ lcl_NotifyBackgroundOfObj( *this, rObj, pOldBoundRect );
+ }
+ break;
+ default:
+ break;
+ }
+}
+
+namespace
+{
+ static const SwFmtAnchor* lcl_getAnchorFmt( const SfxPoolItem& _rItem )
+ {
+ sal_uInt16 nWhich = _rItem.Which();
+ const SwFmtAnchor* pAnchorFmt = NULL;
+ if ( RES_ATTRSET_CHG == nWhich )
+ {
+ static_cast<const SwAttrSetChg&>(_rItem).GetChgSet()->
+ GetItemState( RES_ANCHOR, sal_False, (const SfxPoolItem**)&pAnchorFmt );
+ }
+ else if ( RES_ANCHOR == nWhich )
+ {
+ pAnchorFmt = &static_cast<const SwFmtAnchor&>(_rItem);
+ }
+ return pAnchorFmt;
+ }
+}
+
+/*************************************************************************
+|*
+|* SwDrawContact::Modify()
+|*
+|*************************************************************************/
+
+void SwDrawContact::Modify( const SfxPoolItem* pOld, const SfxPoolItem *pNew )
+{
+ OSL_ENSURE( !mbDisconnectInProgress,
+ "<SwDrawContact::Modify(..)> called during disconnection.");
+
+ sal_uInt16 nWhich = pNew ? pNew->Which() : 0;
+ const SwFmtAnchor* pNewAnchorFmt = pNew ? lcl_getAnchorFmt( *pNew ) : NULL;
+
+ if ( pNewAnchorFmt )
+ {
+ // nicht auf ein Reset Anchor reagieren !!!!!
+ if ( SFX_ITEM_SET ==
+ GetFmt()->GetAttrSet().GetItemState( RES_ANCHOR, sal_False ) )
+ {
+ // no connect to layout during disconnection
+ if ( !mbDisconnectInProgress )
+ {
+ // determine old object retangle of 'master' drawing object
+ // for notification
+ const Rectangle* pOldRect = 0L;
+ Rectangle aOldRect;
+ if ( GetAnchorFrm() )
+ {
+ // --> #i36181# - include spacing in object
+ // rectangle for notification.
+ aOldRect = maAnchoredDrawObj.GetObjRectWithSpaces().SVRect();
+ pOldRect = &aOldRect;
+ // <--
+ }
+ // re-connect to layout due to anchor format change
+ ConnectToLayout( pNewAnchorFmt );
+ // notify background of drawing objects
+ lcl_NotifyBackgroundOfObj( *this, *GetMaster(), pOldRect );
+ NotifyBackgrdOfAllVirtObjs( pOldRect );
+
+ const SwFmtAnchor* pOldAnchorFmt = pOld ? lcl_getAnchorFmt( *pOld ) : NULL;
+ if ( !pOldAnchorFmt || ( pOldAnchorFmt->GetAnchorId() != pNewAnchorFmt->GetAnchorId() ) )
+ {
+ OSL_ENSURE( maAnchoredDrawObj.DrawObj(), "SwDrawContact::Modify: no draw object here?" );
+ if ( maAnchoredDrawObj.DrawObj() )
+ {
+ // --> #i102752#
+ // assure that a ShapePropertyChangeNotifier exists
+ maAnchoredDrawObj.DrawObj()->notifyShapePropertyChange( ::svx::eTextShapeAnchorType );
+ // <--
+ }
+ }
+ }
+ }
+ else
+ DisconnectFromLayout();
+ }
+ // --> #i62875# - no further notification, if not connected to Writer layout
+ else if ( maAnchoredDrawObj.GetAnchorFrm() &&
+ maAnchoredDrawObj.GetDrawObj()->GetUserCall() )
+ {
+ // --> #i28701# - on change of wrapping style, hell|heaven layer,
+ // or wrapping style influence an update of the <SwSortedObjs> list,
+ // the drawing object is registered in, has to be performed. This is triggered
+ // by the 1st parameter of method call <_InvalidateObjs(..)>.
+ if ( RES_SURROUND == nWhich ||
+ RES_OPAQUE == nWhich ||
+ RES_WRAP_INFLUENCE_ON_OBJPOS == nWhich ||
+ ( RES_ATTRSET_CHG == nWhich &&
+ ( SFX_ITEM_SET == ((SwAttrSetChg*)pNew)->GetChgSet()->GetItemState(
+ RES_SURROUND, sal_False ) ||
+ SFX_ITEM_SET == ((SwAttrSetChg*)pNew)->GetChgSet()->GetItemState(
+ RES_OPAQUE, sal_False ) ||
+ SFX_ITEM_SET == ((SwAttrSetChg*)pNew)->GetChgSet()->GetItemState(
+ RES_WRAP_INFLUENCE_ON_OBJPOS, sal_False ) ) ) )
+ {
+ lcl_NotifyBackgroundOfObj( *this, *GetMaster(), 0L );
+ NotifyBackgrdOfAllVirtObjs( 0L );
+ _InvalidateObjs( true );
+ }
+ else if ( RES_UL_SPACE == nWhich || RES_LR_SPACE == nWhich ||
+ RES_HORI_ORIENT == nWhich || RES_VERT_ORIENT == nWhich ||
+ // --> OD 2004-07-01 #i28701# - add attribute 'Follow text flow'
+ RES_FOLLOW_TEXT_FLOW == nWhich ||
+ ( RES_ATTRSET_CHG == nWhich &&
+ ( SFX_ITEM_SET == ((SwAttrSetChg*)pNew)->GetChgSet()->GetItemState(
+ RES_LR_SPACE, sal_False ) ||
+ SFX_ITEM_SET == ((SwAttrSetChg*)pNew)->GetChgSet()->GetItemState(
+ RES_UL_SPACE, sal_False ) ||
+ SFX_ITEM_SET == ((SwAttrSetChg*)pNew)->GetChgSet()->GetItemState(
+ RES_HORI_ORIENT, sal_False ) ||
+ SFX_ITEM_SET == ((SwAttrSetChg*)pNew)->GetChgSet()->GetItemState(
+ RES_VERT_ORIENT, sal_False ) ||
+ SFX_ITEM_SET == ((SwAttrSetChg*)pNew)->GetChgSet()->GetItemState(
+ RES_FOLLOW_TEXT_FLOW, sal_False ) ) ) )
+ {
+ lcl_NotifyBackgroundOfObj( *this, *GetMaster(), 0L );
+ NotifyBackgrdOfAllVirtObjs( 0L );
+ _InvalidateObjs();
+ }
+ // --> OD 2004-10-26 #i35443#
+ else if ( RES_ATTRSET_CHG == nWhich )
+ {
+ lcl_NotifyBackgroundOfObj( *this, *GetMaster(), 0L );
+ NotifyBackgrdOfAllVirtObjs( 0L );
+ _InvalidateObjs();
+ }
+ // <--
+ else if ( RES_REMOVE_UNO_OBJECT == nWhich )
+ {
+ // nothing to do
+ }
+#if OSL_DEBUG_LEVEL > 1
+ else
+ {
+ OSL_FAIL( "<SwDrawContact::Modify(..)> - unhandled attribute? - please inform od@openoffice.org" );
+ }
+#endif
+ }
+
+ // --> OD 2005-07-18 #i51474#
+ GetAnchoredObj( 0L )->ResetLayoutProcessBools();
+ // <--
+}
+
+// OD 2004-03-31 #i26791#
+// --> OD 2004-07-01 #i28701# - added parameter <_bUpdateSortedObjsList>
+void SwDrawContact::_InvalidateObjs( const bool _bUpdateSortedObjsList )
+{
+ // invalidate position of existing 'virtual' drawing objects
+ for ( std::list<SwDrawVirtObj*>::iterator aDisconnectIter = maDrawVirtObjs.begin();
+ aDisconnectIter != maDrawVirtObjs.end();
+ ++aDisconnectIter )
+ {
+ SwDrawVirtObj* pDrawVirtObj = (*aDisconnectIter);
+ // --> OD 2004-08-23 #i33313# - invalidation only for connected
+ // 'virtual' drawing objects
+ if ( pDrawVirtObj->IsConnected() )
+ {
+ pDrawVirtObj->AnchoredObj()->InvalidateObjPos();
+ // --> OD 2004-07-01 #i28701#
+ if ( _bUpdateSortedObjsList )
+ {
+ pDrawVirtObj->AnchoredObj()->UpdateObjInSortedList();
+ }
+ // <--
+ }
+ // <--
+ }
+
+ // invalidate position of 'master' drawing object
+ SwAnchoredObject* pAnchoredObj = GetAnchoredObj( 0L );
+ pAnchoredObj->InvalidateObjPos();
+ // --> OD 2004-07-01 #i28701#
+ if ( _bUpdateSortedObjsList )
+ {
+ pAnchoredObj->UpdateObjInSortedList();
+ }
+ // <--
+}
+
+/*************************************************************************
+|*
+|* SwDrawContact::DisconnectFromLayout()
+|*
+|*************************************************************************/
+
+void SwDrawContact::DisconnectFromLayout( bool _bMoveMasterToInvisibleLayer )
+{
+ mbDisconnectInProgress = true;
+
+ // --> #i36181# - notify background of drawing object
+ if ( _bMoveMasterToInvisibleLayer &&
+ !(GetFmt()->GetDoc()->IsInDtor()) &&
+ GetAnchorFrm() )
+ {
+ const Rectangle aOldRect( maAnchoredDrawObj.GetObjRectWithSpaces().SVRect() );
+ lcl_NotifyBackgroundOfObj( *this, *GetMaster(), &aOldRect );
+ NotifyBackgrdOfAllVirtObjs( &aOldRect );
+ }
+ // <--
+
+ // remove 'virtual' drawing objects from writer
+ // layout and from drawing page
+ for ( std::list<SwDrawVirtObj*>::iterator aDisconnectIter = maDrawVirtObjs.begin();
+ aDisconnectIter != maDrawVirtObjs.end();
+ ++aDisconnectIter )
+ {
+ SwDrawVirtObj* pDrawVirtObj = (*aDisconnectIter);
+ pDrawVirtObj->RemoveFromWriterLayout();
+ pDrawVirtObj->RemoveFromDrawingPage();
+ }
+
+ if ( maAnchoredDrawObj.GetAnchorFrm() )
+ {
+ maAnchoredDrawObj.AnchorFrm()->RemoveDrawObj( maAnchoredDrawObj );
+ }
+
+ if ( _bMoveMasterToInvisibleLayer && GetMaster() && GetMaster()->IsInserted() )
+ {
+ SdrViewIter aIter( GetMaster() );
+ for( SdrView* pView = aIter.FirstView(); pView;
+ pView = aIter.NextView() )
+ {
+ pView->MarkObj( GetMaster(), pView->GetSdrPageView(), sal_True );
+ }
+
+ // Instead of removing 'master' object from drawing page, move the
+ // 'master' drawing object into the corresponding invisible layer.
+ {
+ //((SwFrmFmt*)GetRegisteredIn())->getIDocumentDrawModelAccess()->GetDrawModel()->GetPage(0)->
+ // RemoveObject( GetMaster()->GetOrdNum() );
+ // #i18447# - in order to consider group object correct
+ // use new method <SwDrawContact::MoveObjToInvisibleLayer(..)>
+ MoveObjToInvisibleLayer( GetMaster() );
+ }
+ }
+
+ mbDisconnectInProgress = false;
+}
+
+// method to remove 'master' drawing object from drawing page.
+void SwDrawContact::RemoveMasterFromDrawPage()
+{
+ if ( GetMaster() )
+ {
+ GetMaster()->SetUserCall( 0 );
+ if ( GetMaster()->IsInserted() )
+ {
+ ((SwFrmFmt*)GetRegisteredIn())->getIDocumentDrawModelAccess()->GetDrawModel()->GetPage(0)->
+ RemoveObject( GetMaster()->GetOrdNum() );
+ }
+ }
+}
+
+// disconnect for a dedicated drawing object - could be 'master' or 'virtual'.
+// a 'master' drawing object will disconnect a 'virtual' drawing object
+// in order to take its place.
+// #i19919# - no special case, if drawing object isn't in
+// page header/footer, in order to get drawing objects in repeating table headers
+// also working.
+void SwDrawContact::DisconnectObjFromLayout( SdrObject* _pDrawObj )
+{
+ if ( _pDrawObj->ISA(SwDrawVirtObj) )
+ {
+ SwDrawVirtObj* pDrawVirtObj = static_cast<SwDrawVirtObj*>(_pDrawObj);
+ pDrawVirtObj->RemoveFromWriterLayout();
+ pDrawVirtObj->RemoveFromDrawingPage();
+ }
+ else
+ {
+ std::list<SwDrawVirtObj*>::const_iterator aFoundVirtObjIter =
+ std::find_if( maDrawVirtObjs.begin(), maDrawVirtObjs.end(),
+ UsedOrUnusedVirtObjPred( true ) );
+ if ( aFoundVirtObjIter != maDrawVirtObjs.end() )
+ {
+ // replace found 'virtual' drawing object by 'master' drawing
+ // object and disconnect the 'virtual' one
+ SwDrawVirtObj* pDrawVirtObj = (*aFoundVirtObjIter);
+ SwFrm* pNewAnchorFrmOfMaster = pDrawVirtObj->AnchorFrm();
+ // disconnect 'virtual' drawing object
+ pDrawVirtObj->RemoveFromWriterLayout();
+ pDrawVirtObj->RemoveFromDrawingPage();
+ // disconnect 'master' drawing object from current frame
+ GetAnchorFrm()->RemoveDrawObj( maAnchoredDrawObj );
+ // re-connect 'master' drawing object to frame of found 'virtual'
+ // drawing object.
+ pNewAnchorFrmOfMaster->AppendDrawObj( maAnchoredDrawObj );
+ }
+ else
+ {
+ // no connected 'virtual' drawing object found. Thus, disconnect
+ // completely from layout.
+ DisconnectFromLayout();
+ }
+ }
+}
+
+/*************************************************************************
+|*
+|* SwDrawContact::ConnectToLayout()
+|*
+|*************************************************************************/
+SwTxtFrm* lcl_GetFlyInCntntAnchor( SwTxtFrm* _pProposedAnchorFrm,
+ const xub_StrLen _nTxtOfs )
+{
+ SwTxtFrm* pAct = _pProposedAnchorFrm;
+ SwTxtFrm* pTmp;
+ do
+ {
+ pTmp = pAct;
+ pAct = pTmp->GetFollow();
+ }
+ while( pAct && _nTxtOfs >= pAct->GetOfst() );
+ return pTmp;
+}
+
+void SwDrawContact::ConnectToLayout( const SwFmtAnchor* pAnch )
+{
+ // *no* connect to layout during disconnection from layout.
+ if ( mbDisconnectInProgress )
+ {
+ OSL_FAIL( "<SwDrawContact::ConnectToLayout(..)> called during disconnection.");
+ return;
+ }
+
+ // --> #i33909# - *no* connect to layout, if 'master' drawing
+ // object isn't inserted in the drawing page
+ if ( !GetMaster()->IsInserted() )
+ {
+ OSL_FAIL( "<SwDrawContact::ConnectToLayout(..)> - master drawing object not inserted -> no connect to layout. Please inform od@openoffice.org" );
+ return;
+ }
+ // <--
+
+ SwFrmFmt* pDrawFrmFmt = (SwFrmFmt*)GetRegisteredIn();
+
+ if( !pDrawFrmFmt->getIDocumentLayoutAccess()->GetCurrentViewShell() )
+ return;
+
+ // remove 'virtual' drawing objects from writer
+ // layout and from drawing page, and remove 'master' drawing object from
+ // writer layout - 'master' object will remain in drawing page.
+ DisconnectFromLayout( false );
+
+ if ( !pAnch )
+ {
+ pAnch = &(pDrawFrmFmt->GetAnchor());
+ }
+
+ switch ( pAnch->GetAnchorId() )
+ {
+ case FLY_AT_PAGE:
+ {
+ sal_uInt16 nPgNum = pAnch->GetPageNum();
+ ViewShell *pShell = pDrawFrmFmt->getIDocumentLayoutAccess()->GetCurrentViewShell();
+ if( !pShell )
+ break;
+ SwRootFrm* pRoot = pShell->GetLayout();
+ SwPageFrm *pPage = static_cast<SwPageFrm*>(pRoot->Lower());
+
+ for ( sal_uInt16 i = 1; i < nPgNum && pPage; ++i )
+ {
+ pPage = static_cast<SwPageFrm*>(pPage->GetNext());
+ }
+
+ if ( pPage )
+ {
+ pPage->AppendDrawObj( maAnchoredDrawObj );
+ }
+ else
+ //Sieht doof aus, ist aber erlaubt (vlg. SwFEShell::SetPageObjsNewPage)
+ pRoot->SetAssertFlyPages();
+ }
+ break;
+
+ case FLY_AT_CHAR:
+ case FLY_AT_PARA:
+ case FLY_AT_FLY:
+ case FLY_AS_CHAR:
+ {
+ if ( pAnch->GetAnchorId() == FLY_AS_CHAR )
+ {
+ ClrContourCache( GetMaster() );
+ }
+ // support drawing objects in header/footer,
+ // but not control objects:
+ // anchor at first found frame the 'master' object and
+ // at the following frames 'virtual' drawing objects.
+ // Note: method is similar to <SwFlyFrmFmt::MakeFrms(..)>
+ SwModify *pModify = 0;
+ if( pAnch->GetCntntAnchor() )
+ {
+ if ( pAnch->GetAnchorId() == FLY_AT_FLY )
+ {
+ SwNodeIndex aIdx( pAnch->GetCntntAnchor()->nNode );
+ SwCntntNode* pCNd = pDrawFrmFmt->GetDoc()->GetNodes().GoNext( &aIdx );
+ if ( SwIterator<SwFrm,SwCntntNode>::FirstElement( *pCNd ) )
+ pModify = pCNd;
+ else
+ {
+ const SwNodeIndex& rIdx = pAnch->GetCntntAnchor()->nNode;
+ SwSpzFrmFmts& rFmts = *(pDrawFrmFmt->GetDoc()->GetSpzFrmFmts());
+ for( sal_uInt16 i = 0; i < rFmts.Count(); ++i )
+ {
+ SwFrmFmt* pFlyFmt = rFmts[i];
+ if( pFlyFmt->GetCntnt().GetCntntIdx() &&
+ rIdx == *(pFlyFmt->GetCntnt().GetCntntIdx()) )
+ {
+ pModify = pFlyFmt;
+ break;
+ }
+ }
+ }
+ // --> OD 2004-06-15 #i29199# - It is possible, that
+ // the anchor doesn't exist - E.g., reordering the
+ // sub-documents in a master document.
+ // Note: The anchor will be inserted later.
+ if ( !pModify )
+ {
+ // break to end of the current switch case.
+ break;
+ }
+ }
+ else
+ {
+ pModify = pAnch->GetCntntAnchor()->nNode.GetNode().GetCntntNode();
+ }
+ }
+ SwIterator<SwFrm,SwModify> aIter( *pModify );
+ SwFrm* pAnchorFrmOfMaster = 0;
+ for( SwFrm *pFrm = aIter.First(); pFrm; pFrm = aIter.Next() )
+ {
+ // append drawing object, if
+ // (1) proposed anchor frame isn't a follow and
+ // (2) drawing object isn't a control object to be anchored
+ // in header/footer.
+ const bool bAdd = ( !pFrm->IsCntntFrm() ||
+ !((SwCntntFrm*)pFrm)->IsFollow() ) &&
+ ( !::CheckControlLayer( GetMaster() ) ||
+ !pFrm->FindFooterOrHeader() );
+
+ if( bAdd )
+ {
+ if ( FLY_AT_FLY == pAnch->GetAnchorId() && !pFrm->IsFlyFrm() )
+ {
+ pFrm = pFrm->FindFlyFrm();
+ OSL_ENSURE( pFrm,
+ "<SwDrawContact::ConnectToLayout(..)> - missing fly frame -> crash." );
+ }
+
+ // find correct follow for as character anchored objects
+ if ((pAnch->GetAnchorId() == FLY_AS_CHAR) &&
+ pFrm->IsTxtFrm() )
+ {
+ pFrm = lcl_GetFlyInCntntAnchor(
+ static_cast<SwTxtFrm*>(pFrm),
+ pAnch->GetCntntAnchor()->nContent.GetIndex() );
+ }
+
+ if ( !pAnchorFrmOfMaster )
+ {
+ // append 'master' drawing object
+ pAnchorFrmOfMaster = pFrm;
+ pFrm->AppendDrawObj( maAnchoredDrawObj );
+ }
+ else
+ {
+ // append 'virtual' drawing object
+ SwDrawVirtObj* pDrawVirtObj = AddVirtObj();
+ if ( pAnch->GetAnchorId() == FLY_AS_CHAR )
+ {
+ ClrContourCache( pDrawVirtObj );
+ }
+ pFrm->AppendDrawObj( *(pDrawVirtObj->AnchoredObj()) );
+
+ pDrawVirtObj->ActionChanged();
+ }
+
+ if ( pAnch->GetAnchorId() == FLY_AS_CHAR )
+ {
+ pFrm->InvalidatePrt();
+ }
+ }
+ }
+ }
+ break;
+ default:
+ OSL_FAIL( "Unknown Anchor." );
+ break;
+ }
+ if ( GetAnchorFrm() )
+ {
+ ::setContextWritingMode( maAnchoredDrawObj.DrawObj(), GetAnchorFrm() );
+ // #i26791# - invalidate objects instead of direct positioning
+ _InvalidateObjs();
+ }
+}
+
+// insert 'master' drawing object into drawing page
+void SwDrawContact::InsertMasterIntoDrawPage()
+{
+ if ( !GetMaster()->IsInserted() )
+ {
+ GetFmt()->getIDocumentDrawModelAccess()->GetDrawModel()->GetPage(0)
+ ->InsertObject( GetMaster(), GetMaster()->GetOrdNumDirect() );
+ }
+ GetMaster()->SetUserCall( this );
+}
+
+/*************************************************************************
+|*
+|* SwDrawContact::FindPage(), ChkPage()
+|*
+|*************************************************************************/
+
+SwPageFrm* SwDrawContact::FindPage( const SwRect &rRect )
+{
+ // --> #i28701# - use method <GetPageFrm()>
+ SwPageFrm* pPg = GetPageFrm();
+ if ( !pPg && GetAnchorFrm() )
+ pPg = GetAnchorFrm()->FindPageFrm();
+ if ( pPg )
+ pPg = (SwPageFrm*)::FindPage( rRect, pPg );
+ return pPg;
+}
+
+void SwDrawContact::ChkPage()
+{
+ if ( mbDisconnectInProgress )
+ {
+ OSL_FAIL( "<SwDrawContact::ChkPage()> called during disconnection." );
+ return;
+ }
+
+ // --> #i28701#
+ SwPageFrm* pPg = ( maAnchoredDrawObj.GetAnchorFrm() &&
+ maAnchoredDrawObj.GetAnchorFrm()->IsPageFrm() )
+ ? GetPageFrm()
+ : FindPage( GetMaster()->GetCurrentBoundRect() );
+ if ( GetPageFrm() != pPg )
+ {
+ // if drawing object is anchor in header/footer a change of the page
+ // is a dramatic change. Thus, completely re-connect to the layout
+ if ( maAnchoredDrawObj.GetAnchorFrm() &&
+ maAnchoredDrawObj.GetAnchorFrm()->FindFooterOrHeader() )
+ {
+ ConnectToLayout();
+ }
+ else
+ {
+ // --> #i28701# - use methods <GetPageFrm()> and <SetPageFrm>
+ if ( GetPageFrm() )
+ GetPageFrm()->RemoveDrawObjFromPage( maAnchoredDrawObj );
+ pPg->AppendDrawObjToPage( maAnchoredDrawObj );
+ SetPageFrm( pPg );
+ }
+ }
+}
+
+/*************************************************************************
+|*
+|* SwDrawContact::ChangeMasterObject()
+|*
+|*************************************************************************/
+// Important note:
+// method is called by method <SwDPage::ReplaceObject(..)>, which called its
+// corresponding superclass method <FmFormPage::ReplaceObject(..)>.
+// Note: 'master' drawing object *has* to be connected to layout triggered
+// by the caller of this, if method is called.
+void SwDrawContact::ChangeMasterObject( SdrObject *pNewMaster )
+{
+ DisconnectFromLayout( false );
+ // consider 'virtual' drawing objects
+ RemoveAllVirtObjs();
+
+ GetMaster()->SetUserCall( 0 );
+ SetMaster( pNewMaster );
+ GetMaster()->SetUserCall( this );
+
+ _InvalidateObjs();
+}
+
+// get data collection of anchored objects, handled by with contact
+void SwDrawContact::GetAnchoredObjs( std::list<SwAnchoredObject*>& _roAnchoredObjs ) const
+{
+ _roAnchoredObjs.push_back( const_cast<SwAnchoredDrawObject*>(&maAnchoredDrawObj) );
+
+ for ( std::list<SwDrawVirtObj*>::const_iterator aDrawVirtObjsIter = maDrawVirtObjs.begin();
+ aDrawVirtObjsIter != maDrawVirtObjs.end();
+ ++aDrawVirtObjsIter )
+ {
+ _roAnchoredObjs.push_back( (*aDrawVirtObjsIter)->AnchoredObj() );
+ }
+}
+
+//////////////////////////////////////////////////////////////////////////////////////
+// AW: own sdr::contact::ViewContact (VC) sdr::contact::ViewObjectContact (VOC) needed
+// since offset is defined different from SdrVirtObj's sdr::contact::ViewContactOfVirtObj.
+// For paint, that offset is used by setting at the OutputDevice; for primitives this is
+// not possible since we have no OutputDevice, but define the geometry itself.
+
+namespace sdr
+{
+ namespace contact
+ {
+ class VOCOfDrawVirtObj : public ViewObjectContactOfSdrObj
+ {
+ protected:
+ // This method is responsible for creating the graphical visualisation data which is
+ // stored/cached in the local primitive. Default gets view-independent Primitive
+ // from the ViewContact using ViewContact::getViewIndependentPrimitive2DSequence(), takes care of
+ // visibility, handles glue and ghosted.
+ // This method will not handle included hierarchies and not check geometric visibility.
+ virtual drawinglayer::primitive2d::Primitive2DSequence createPrimitive2DSequence(const DisplayInfo& rDisplayInfo) const;
+
+ public:
+ VOCOfDrawVirtObj(ObjectContact& rObjectContact, ViewContact& rViewContact)
+ : ViewObjectContactOfSdrObj(rObjectContact, rViewContact)
+ {
+ }
+
+ virtual ~VOCOfDrawVirtObj();
+ };
+
+ class VCOfDrawVirtObj : public ViewContactOfVirtObj
+ {
+ protected:
+ // Create a Object-Specific ViewObjectContact, set ViewContact and
+ // ObjectContact. Always needs to return something. Default is to create
+ // a standard ViewObjectContact containing the given ObjectContact and *this
+ virtual ViewObjectContact& CreateObjectSpecificViewObjectContact(ObjectContact& rObjectContact);
+
+ public:
+ // basic constructor, used from SdrObject.
+ VCOfDrawVirtObj(SwDrawVirtObj& rObj)
+ : ViewContactOfVirtObj(rObj)
+ {
+ }
+ virtual ~VCOfDrawVirtObj();
+
+ // access to SwDrawVirtObj
+ SwDrawVirtObj& GetSwDrawVirtObj() const
+ {
+ return (SwDrawVirtObj&)mrObject;
+ }
+ };
+ } // end of namespace contact
+} // end of namespace sdr
+
+namespace sdr
+{
+ namespace contact
+ {
+ // recursively collect primitive data from given VOC with given offset
+ void impAddPrimitivesFromGroup(const ViewObjectContact& rVOC, const basegfx::B2DHomMatrix& rOffsetMatrix, const DisplayInfo& rDisplayInfo, drawinglayer::primitive2d::Primitive2DSequence& rxTarget)
+ {
+ const sal_uInt32 nSubHierarchyCount(rVOC.GetViewContact().GetObjectCount());
+
+ for(sal_uInt32 a(0L); a < nSubHierarchyCount; a++)
+ {
+ const ViewObjectContact& rCandidate(rVOC.GetViewContact().GetViewContact(a).GetViewObjectContact(rVOC.GetObjectContact()));
+
+ if(rCandidate.GetViewContact().GetObjectCount())
+ {
+ // is a group object itself, call resursively
+ impAddPrimitivesFromGroup(rCandidate, rOffsetMatrix, rDisplayInfo, rxTarget);
+ }
+ else
+ {
+ // single object, add primitives; check model-view visibility
+ if(rCandidate.isPrimitiveVisible(rDisplayInfo))
+ {
+ drawinglayer::primitive2d::Primitive2DSequence aNewSequence(rCandidate.getPrimitive2DSequence(rDisplayInfo));
+
+ if(aNewSequence.hasElements())
+ {
+ // get ranges
+ const drawinglayer::geometry::ViewInformation2D& rViewInformation2D(rCandidate.GetObjectContact().getViewInformation2D());
+ const basegfx::B2DRange aViewRange(rViewInformation2D.getViewport());
+ basegfx::B2DRange aObjectRange(rCandidate.getObjectRange());
+
+ // correct with virtual object's offset
+ aObjectRange.transform(rOffsetMatrix);
+
+ // check geometrical visibility (with offset)
+ if(!aViewRange.overlaps(aObjectRange))
+ {
+ // not visible, release
+ aNewSequence.realloc(0);
+ }
+ }
+
+ if(aNewSequence.hasElements())
+ {
+ drawinglayer::primitive2d::appendPrimitive2DSequenceToPrimitive2DSequence(rxTarget, aNewSequence);
+ }
+ }
+ }
+ }
+ }
+
+ drawinglayer::primitive2d::Primitive2DSequence VOCOfDrawVirtObj::createPrimitive2DSequence(const DisplayInfo& rDisplayInfo) const
+ {
+ const VCOfDrawVirtObj& rVC = static_cast< const VCOfDrawVirtObj& >(GetViewContact());
+ const SdrObject& rReferencedObject = rVC.GetSwDrawVirtObj().GetReferencedObj();
+ drawinglayer::primitive2d::Primitive2DSequence xRetval;
+
+ // create offset transformation
+ basegfx::B2DHomMatrix aOffsetMatrix;
+ const Point aLocalOffset(rVC.GetSwDrawVirtObj().GetOffset());
+
+ if(aLocalOffset.X() || aLocalOffset.Y())
+ {
+ aOffsetMatrix.set(0, 2, aLocalOffset.X());
+ aOffsetMatrix.set(1, 2, aLocalOffset.Y());
+ }
+
+ if(rReferencedObject.ISA(SdrObjGroup))
+ {
+ // group object. Since the VOC/OC/VC hierarchy does not represent the
+ // hierarchy virtual objects when they have group objects
+ // (ViewContactOfVirtObj::GetObjectCount() returns null for that purpose)
+ // to avoid multiple usages of VOCs (which would not work), the primitives
+ // for the sub-hierarchy need to be collected here
+
+ // Get the VOC of the referenced object (the Group) and fetch primitives from it
+ const ViewObjectContact& rVOCOfRefObj = rReferencedObject.GetViewContact().GetViewObjectContact(GetObjectContact());
+ impAddPrimitivesFromGroup(rVOCOfRefObj, aOffsetMatrix, rDisplayInfo, xRetval);
+ }
+ else
+ {
+ // single object, use method from referenced object to get the Primitive2DSequence
+ xRetval = rReferencedObject.GetViewContact().getViewIndependentPrimitive2DSequence();
+ }
+
+ if(xRetval.hasElements())
+ {
+ // create transform primitive
+ const drawinglayer::primitive2d::Primitive2DReference xReference(new drawinglayer::primitive2d::TransformPrimitive2D(aOffsetMatrix, xRetval));
+ xRetval = drawinglayer::primitive2d::Primitive2DSequence(&xReference, 1);
+ }
+
+ return xRetval;
+ }
+
+ VOCOfDrawVirtObj::~VOCOfDrawVirtObj()
+ {
+ }
+
+ ViewObjectContact& VCOfDrawVirtObj::CreateObjectSpecificViewObjectContact(ObjectContact& rObjectContact)
+ {
+ return *(new VOCOfDrawVirtObj(rObjectContact, *this));
+ }
+
+ VCOfDrawVirtObj::~VCOfDrawVirtObj()
+ {
+ }
+ } // end of namespace contact
+} // end of namespace sdr
+
+//////////////////////////////////////////////////////////////////////////////////////
+
+// =============================================================================
+/** implementation of class <SwDrawVirtObj>
+
+ @author OD
+*/
+
+TYPEINIT1(SwDrawVirtObj,SdrVirtObj);
+
+sdr::contact::ViewContact* SwDrawVirtObj::CreateObjectSpecificViewContact()
+{
+ return new sdr::contact::VCOfDrawVirtObj(*this);
+}
+
+// implemetation of SwDrawVirtObj
+SwDrawVirtObj::SwDrawVirtObj( SdrObject& _rNewObj,
+ SwDrawContact& _rDrawContact )
+ : SdrVirtObj( _rNewObj ),
+ // OD 2004-03-29 #i26791# - init new member <maAnchoredDrawObj>
+ maAnchoredDrawObj(),
+ mrDrawContact( _rDrawContact )
+{
+ // OD 2004-03-29 #i26791#
+ maAnchoredDrawObj.SetDrawObj( *this );
+ // --> OD 2004-11-17 #i35635# - set initial position out of sight
+ NbcMove( Size( -RECT_EMPTY, -RECT_EMPTY ) );
+ // <--
+}
+
+SwDrawVirtObj::~SwDrawVirtObj()
+{}
+
+SwDrawVirtObj& SwDrawVirtObj::operator=( const SwDrawVirtObj& rObj )
+{
+ SdrVirtObj::operator=(rObj);
+ // Note: Members <maAnchoredDrawObj> and <mrDrawContact>
+ // haven't to be considered.
+ return *this;
+}
+
+SwDrawVirtObj* SwDrawVirtObj::Clone() const
+{
+ SwDrawVirtObj* pObj = new SwDrawVirtObj( rRefObj, mrDrawContact );
+
+ if ( pObj )
+ {
+ pObj->operator=( *this );
+ // Note: Member <maAnchoredDrawObj> hasn't to be considered.
+ }
+
+ return pObj;
+}
+
+// --------------------------------------------------------------------
+// connection to writer layout: <GetAnchoredObj()>, <SetAnchorFrm(..)>,
+// <GetAnchorFrm()>, <SetPageFrm(..)>, <GetPageFrm()> and <RemoveFromWriterLayout()>
+// --------------------------------------------------------------------
+const SwAnchoredObject* SwDrawVirtObj::GetAnchoredObj() const
+{
+ return &maAnchoredDrawObj;
+}
+
+SwAnchoredObject* SwDrawVirtObj::AnchoredObj()
+{
+ return &maAnchoredDrawObj;
+}
+
+const SwFrm* SwDrawVirtObj::GetAnchorFrm() const
+{
+ // OD 2004-03-29 #i26791# - use new member <maAnchoredDrawObj>
+ return maAnchoredDrawObj.GetAnchorFrm();
+}
+
+SwFrm* SwDrawVirtObj::AnchorFrm()
+{
+ // OD 2004-03-29 #i26791# - use new member <maAnchoredDrawObj>
+ return maAnchoredDrawObj.AnchorFrm();
+}
+
+void SwDrawVirtObj::RemoveFromWriterLayout()
+{
+ // remove contact object from frame for 'virtual' drawing object
+ // OD 2004-03-29 #i26791# - use new member <maAnchoredDrawObj>
+ if ( maAnchoredDrawObj.GetAnchorFrm() )
+ {
+ maAnchoredDrawObj.AnchorFrm()->RemoveDrawObj( maAnchoredDrawObj );
+ }
+}
+
+// --------------------------------------------------------------------
+// connection to writer layout: <AddToDrawingPage()>, <RemoveFromDrawingPage()>
+// --------------------------------------------------------------------
+void SwDrawVirtObj::AddToDrawingPage()
+{
+ // determine 'master'
+ SdrObject* pOrgMasterSdrObj = mrDrawContact.GetMaster();
+
+ // insert 'virtual' drawing object into page, set layer and user call.
+ SdrPage* pDrawPg;
+ // --> OD 2004-08-16 #i27030# - apply order number of referenced object
+ if ( 0 != ( pDrawPg = pOrgMasterSdrObj->GetPage() ) )
+ {
+ // --> OD 2004-08-16 #i27030# - apply order number of referenced object
+ pDrawPg->InsertObject( this, GetReferencedObj().GetOrdNum() );
+ }
+ else
+ {
+ pDrawPg = GetPage();
+ if ( pDrawPg )
+ {
+ pDrawPg->SetObjectOrdNum( GetOrdNumDirect(),
+ GetReferencedObj().GetOrdNum() );
+ }
+ else
+ {
+ SetOrdNum( GetReferencedObj().GetOrdNum() );
+ }
+ }
+ // <--
+ SetUserCall( &mrDrawContact );
+}
+
+void SwDrawVirtObj::RemoveFromDrawingPage()
+{
+ SetUserCall( 0 );
+ if ( GetPage() )
+ {
+ GetPage()->RemoveObject( GetOrdNum() );
+ }
+}
+
+// is 'virtual' drawing object connected to writer layout and to drawing layer.
+bool SwDrawVirtObj::IsConnected() const
+{
+ bool bRetVal = GetAnchorFrm() &&
+ ( GetPage() && GetUserCall() );
+
+ return bRetVal;
+}
+
+void SwDrawVirtObj::NbcSetAnchorPos(const Point& rPnt)
+{
+ SdrObject::NbcSetAnchorPos( rPnt );
+}
+
+//////////////////////////////////////////////////////////////////////////////
+// #i97197#
+// the methods relevant for positioning
+
+const Rectangle& SwDrawVirtObj::GetCurrentBoundRect() const
+{
+ if(aOutRect.IsEmpty())
+ {
+ const_cast<SwDrawVirtObj*>(this)->RecalcBoundRect();
+ }
+
+ return aOutRect;
+}
+
+const Rectangle& SwDrawVirtObj::GetLastBoundRect() const
+{
+ return aOutRect;
+}
+
+const Point SwDrawVirtObj::GetOffset() const
+{
+ // do NOT use IsEmpty() here, there is already a useful offset
+ // in the position
+ if(aOutRect == Rectangle())
+ {
+ return Point();
+ }
+ else
+ {
+ return aOutRect.TopLeft() - GetReferencedObj().GetCurrentBoundRect().TopLeft();
+ }
+}
+
+void SwDrawVirtObj::SetBoundRectDirty()
+{
+ // do nothing to not lose model information in aOutRect
+}
+
+void SwDrawVirtObj::RecalcBoundRect()
+{
+ // OD 2004-04-05 #i26791# - switch order of calling <GetOffset()> and
+ // <ReferencedObj().GetCurrentBoundRect()>, because <GetOffset()> calculates
+ // its value by the 'BoundRect' of the referenced object.
+
+ const Point aOffset(GetOffset());
+ aOutRect = ReferencedObj().GetCurrentBoundRect() + aOffset;
+}
+
+basegfx::B2DPolyPolygon SwDrawVirtObj::TakeXorPoly() const
+{
+ basegfx::B2DPolyPolygon aRetval(rRefObj.TakeXorPoly());
+ aRetval.transform(basegfx::tools::createTranslateB2DHomMatrix(GetOffset().X(), GetOffset().Y()));
+
+ return aRetval;
+}
+
+basegfx::B2DPolyPolygon SwDrawVirtObj::TakeContour() const
+{
+ basegfx::B2DPolyPolygon aRetval(rRefObj.TakeContour());
+ aRetval.transform(basegfx::tools::createTranslateB2DHomMatrix(GetOffset().X(), GetOffset().Y()));
+
+ return aRetval;
+}
+
+SdrHdl* SwDrawVirtObj::GetHdl(sal_uInt32 nHdlNum) const
+{
+ SdrHdl* pHdl = rRefObj.GetHdl(nHdlNum);
+ Point aP(pHdl->GetPos() + GetOffset());
+ pHdl->SetPos(aP);
+
+ return pHdl;
+}
+
+SdrHdl* SwDrawVirtObj::GetPlusHdl(const SdrHdl& rHdl, sal_uInt16 nPlNum) const
+{
+ SdrHdl* pHdl = rRefObj.GetPlusHdl(rHdl, nPlNum);
+
+ if (pHdl)
+ pHdl->SetPos(pHdl->GetPos() + GetOffset());
+
+ return pHdl;
+}
+
+void SwDrawVirtObj::NbcMove(const Size& rSiz)
+{
+ SdrObject::NbcMove( rSiz );
+}
+
+void SwDrawVirtObj::NbcResize(const Point& rRef, const Fraction& xFact, const Fraction& yFact)
+{
+ rRefObj.NbcResize(rRef - GetOffset(), xFact, yFact);
+ SetRectsDirty();
+}
+
+void SwDrawVirtObj::NbcRotate(const Point& rRef, long nWink, double sn, double cs)
+{
+ rRefObj.NbcRotate(rRef - GetOffset(), nWink, sn, cs);
+ SetRectsDirty();
+}
+
+void SwDrawVirtObj::NbcMirror(const Point& rRef1, const Point& rRef2)
+{
+ rRefObj.NbcMirror(rRef1 - GetOffset(), rRef2 - GetOffset());
+ SetRectsDirty();
+}
+
+void SwDrawVirtObj::NbcShear(const Point& rRef, long nWink, double tn, bool bVShear)
+{
+ rRefObj.NbcShear(rRef - GetOffset(), nWink, tn, bVShear);
+ SetRectsDirty();
+}
+
+void SwDrawVirtObj::Move(const Size& rSiz)
+{
+ SdrObject::Move( rSiz );
+}
+
+void SwDrawVirtObj::Resize(const Point& rRef, const Fraction& xFact, const Fraction& yFact)
+{
+ if(xFact.GetNumerator() != xFact.GetDenominator() || yFact.GetNumerator() != yFact.GetDenominator())
+ {
+ Rectangle aBoundRect0; if(pUserCall) aBoundRect0 = GetLastBoundRect();
+ rRefObj.Resize(rRef - GetOffset(), xFact, yFact);
+ SetRectsDirty();
+ SendUserCall(SDRUSERCALL_RESIZE, aBoundRect0);
+ }
+}
+
+void SwDrawVirtObj::Rotate(const Point& rRef, long nWink, double sn, double cs)
+{
+ if(nWink)
+ {
+ Rectangle aBoundRect0; if(pUserCall) aBoundRect0 = GetLastBoundRect();
+ rRefObj.Rotate(rRef - GetOffset(), nWink, sn, cs);
+ SetRectsDirty();
+ SendUserCall(SDRUSERCALL_RESIZE, aBoundRect0);
+ }
+}
+
+void SwDrawVirtObj::Mirror(const Point& rRef1, const Point& rRef2)
+{
+ Rectangle aBoundRect0; if(pUserCall) aBoundRect0 = GetLastBoundRect();
+ rRefObj.Mirror(rRef1 - GetOffset(), rRef2 - GetOffset());
+ SetRectsDirty();
+ SendUserCall(SDRUSERCALL_RESIZE, aBoundRect0);
+}
+
+void SwDrawVirtObj::Shear(const Point& rRef, long nWink, double tn, bool bVShear)
+{
+ if(nWink)
+ {
+ Rectangle aBoundRect0; if(pUserCall) aBoundRect0 = GetLastBoundRect();
+ rRefObj.Shear(rRef - GetOffset(), nWink, tn, bVShear);
+ SetRectsDirty();
+ SendUserCall(SDRUSERCALL_RESIZE, aBoundRect0);
+ }
+}
+
+void SwDrawVirtObj::RecalcSnapRect()
+{
+ aSnapRect = rRefObj.GetSnapRect();
+ aSnapRect += GetOffset();
+}
+
+const Rectangle& SwDrawVirtObj::GetSnapRect() const
+{
+ ((SwDrawVirtObj*)this)->aSnapRect = rRefObj.GetSnapRect();
+ ((SwDrawVirtObj*)this)->aSnapRect += GetOffset();
+
+ return aSnapRect;
+}
+
+void SwDrawVirtObj::SetSnapRect(const Rectangle& rRect)
+{
+ Rectangle aBoundRect0; if(pUserCall) aBoundRect0 = GetLastBoundRect();
+ Rectangle aR(rRect);
+ aR -= GetOffset();
+ rRefObj.SetSnapRect(aR);
+ SetRectsDirty();
+ SendUserCall(SDRUSERCALL_RESIZE, aBoundRect0);
+}
+
+void SwDrawVirtObj::NbcSetSnapRect(const Rectangle& rRect)
+{
+ Rectangle aR(rRect);
+ aR -= GetOffset();
+ SetRectsDirty();
+ rRefObj.NbcSetSnapRect(aR);
+}
+
+const Rectangle& SwDrawVirtObj::GetLogicRect() const
+{
+ ((SwDrawVirtObj*)this)->aSnapRect = rRefObj.GetLogicRect();
+ ((SwDrawVirtObj*)this)->aSnapRect += GetOffset();
+
+ return aSnapRect;
+}
+
+void SwDrawVirtObj::SetLogicRect(const Rectangle& rRect)
+{
+ Rectangle aBoundRect0; if(pUserCall) aBoundRect0 = GetLastBoundRect();
+ Rectangle aR(rRect);
+ aR -= GetOffset();
+ rRefObj.SetLogicRect(aR);
+ SetRectsDirty();
+ SendUserCall(SDRUSERCALL_RESIZE, aBoundRect0);
+}
+
+void SwDrawVirtObj::NbcSetLogicRect(const Rectangle& rRect)
+{
+ Rectangle aR(rRect);
+ aR -= GetOffset();
+ rRefObj.NbcSetLogicRect(aR);
+ SetRectsDirty();
+}
+
+Point SwDrawVirtObj::GetSnapPoint(sal_uInt32 i) const
+{
+ Point aP(rRefObj.GetSnapPoint(i));
+ aP += GetOffset();
+
+ return aP;
+}
+
+Point SwDrawVirtObj::GetPoint(sal_uInt32 i) const
+{
+ return Point(rRefObj.GetPoint(i) + GetOffset());
+}
+
+void SwDrawVirtObj::NbcSetPoint(const Point& rPnt, sal_uInt32 i)
+{
+ Point aP(rPnt);
+ aP -= GetOffset();
+ rRefObj.SetPoint(aP, i);
+ SetRectsDirty();
+}
+
+bool SwDrawVirtObj::HasTextEdit() const
+{
+ return rRefObj.HasTextEdit();
+}
+
+// overloaded 'layer' methods for 'virtual' drawing object to assure,
+// that layer of 'virtual' object is the layer of the referenced object.
+SdrLayerID SwDrawVirtObj::GetLayer() const
+{
+ return GetReferencedObj().GetLayer();
+}
+
+void SwDrawVirtObj::NbcSetLayer(SdrLayerID nLayer)
+{
+ ReferencedObj().NbcSetLayer( nLayer );
+ SdrVirtObj::NbcSetLayer( ReferencedObj().GetLayer() );
+}
+
+void SwDrawVirtObj::SetLayer(SdrLayerID nLayer)
+{
+ ReferencedObj().SetLayer( nLayer );
+ SdrVirtObj::NbcSetLayer( ReferencedObj().GetLayer() );
+}
+
+bool SwDrawVirtObj::supportsFullDrag() const
+{
+ // call parent
+ return SdrVirtObj::supportsFullDrag();
+}
+
+SdrObject* SwDrawVirtObj::getFullDragClone() const
+{
+ // call parent
+ return SdrVirtObj::getFullDragClone();
+}
+
+// eof
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/draw/dflyobj.cxx b/sw/source/core/draw/dflyobj.cxx
new file mode 100644
index 000000000000..a350cc1772e1
--- /dev/null
+++ b/sw/source/core/draw/dflyobj.cxx
@@ -0,0 +1,957 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+#include "hintids.hxx"
+#include <svx/svdtrans.hxx>
+#include <editeng/protitem.hxx>
+#include <editeng/opaqitem.hxx>
+#include <svx/svdpage.hxx>
+
+
+#include <fmtclds.hxx>
+#include <fmtornt.hxx>
+#include <fmtfsize.hxx>
+#include <fmturl.hxx>
+#include "viewsh.hxx"
+#include "viewimp.hxx"
+#include "cntfrm.hxx"
+#include "frmatr.hxx"
+#include "doc.hxx"
+#include <IDocumentUndoRedo.hxx>
+#include "dview.hxx"
+#include "dflyobj.hxx"
+#include "flyfrm.hxx"
+#include "frmfmt.hxx"
+#include "viewopt.hxx"
+#include "frmtool.hxx"
+#include "flyfrms.hxx"
+#include "ndnotxt.hxx"
+#include "grfatr.hxx"
+#include "pagefrm.hxx"
+#include "rootfrm.hxx"
+
+
+using namespace ::com::sun::star;
+
+
+#include <svx/sdr/properties/defaultproperties.hxx>
+#include <basegfx/range/b2drange.hxx>
+#include <basegfx/polygon/b2dpolygontools.hxx>
+#include <basegfx/polygon/b2dpolygon.hxx>
+
+// AW: For VCOfDrawVirtObj and stuff
+#include <svx/sdr/contact/viewcontactofvirtobj.hxx>
+#include <drawinglayer/primitive2d/baseprimitive2d.hxx>
+#include <sw_primitivetypes2d.hxx>
+#include <drawinglayer/primitive2d/sdrdecompositiontools2d.hxx>
+
+using namespace ::com::sun::star;
+
+static sal_Bool bInResize = sal_False;
+
+TYPEINIT1( SwFlyDrawObj, SdrObject )
+TYPEINIT1( SwVirtFlyDrawObj, SdrVirtObj )
+
+/*************************************************************************
+|*
+|* SwFlyDrawObj::Ctor
+|*
+*************************************************************************/
+
+////////////////////////////////////////////////////////////////////////////////////////////////////
+
+namespace sdr
+{
+ namespace contact
+ {
+ // #i95264# currently needed since createViewIndependentPrimitive2DSequence()
+ // is called when RecalcBoundRect() is used. There should currently no VOCs being
+ // constructed since it gets not visualized (instead the corresponding SwVirtFlyDrawObj's
+ // referencing this one are visualized).
+ class VCOfSwFlyDrawObj : public ViewContactOfSdrObj
+ {
+ protected:
+ // This method is responsible for creating the graphical visualisation data
+ // ONLY based on model data
+ virtual drawinglayer::primitive2d::Primitive2DSequence createViewIndependentPrimitive2DSequence() const;
+
+ public:
+ // basic constructor, used from SdrObject.
+ VCOfSwFlyDrawObj(SwFlyDrawObj& rObj)
+ : ViewContactOfSdrObj(rObj)
+ {
+ }
+ virtual ~VCOfSwFlyDrawObj();
+ };
+
+ drawinglayer::primitive2d::Primitive2DSequence VCOfSwFlyDrawObj::createViewIndependentPrimitive2DSequence() const
+ {
+ // currently gets not visualized, return empty sequence
+ return drawinglayer::primitive2d::Primitive2DSequence();
+ }
+
+ VCOfSwFlyDrawObj::~VCOfSwFlyDrawObj()
+ {
+ }
+ } // end of namespace contact
+} // end of namespace sdr
+
+////////////////////////////////////////////////////////////////////////////////////////////////////
+
+sdr::properties::BaseProperties* SwFlyDrawObj::CreateObjectSpecificProperties()
+{
+ // create default properties
+ return new sdr::properties::DefaultProperties(*this);
+}
+
+sdr::contact::ViewContact* SwFlyDrawObj::CreateObjectSpecificViewContact()
+{
+ // needs an own VC since createViewIndependentPrimitive2DSequence()
+ // is called when RecalcBoundRect() is used
+ return new sdr::contact::VCOfSwFlyDrawObj(*this);
+}
+
+SwFlyDrawObj::SwFlyDrawObj()
+{
+}
+
+SwFlyDrawObj::~SwFlyDrawObj()
+{
+}
+
+/*************************************************************************
+|*
+|* SwFlyDrawObj::Factory-Methoden
+|*
+*************************************************************************/
+
+sal_uInt32 SwFlyDrawObj::GetObjInventor() const
+{
+ return SWGInventor;
+}
+
+
+sal_uInt16 SwFlyDrawObj::GetObjIdentifier() const
+{
+ return SwFlyDrawObjIdentifier;
+}
+
+
+sal_uInt16 SwFlyDrawObj::GetObjVersion() const
+{
+ return SwDrawFirst;
+}
+
+/*************************************************************************
+|*
+|* SwVirtFlyDrawObj::CToren, Dtor
+|*
+*************************************************************************/
+
+//////////////////////////////////////////////////////////////////////////////////////
+// AW: Need own primitive to get the FlyFrame paint working
+
+namespace drawinglayer
+{
+ namespace primitive2d
+ {
+ class SwVirtFlyDrawObjPrimitive : public BufferedDecompositionPrimitive2D
+ {
+ private:
+ const SwVirtFlyDrawObj& mrSwVirtFlyDrawObj;
+ const basegfx::B2DRange maOuterRange;
+
+ protected:
+ // method which is to be used to implement the local decomposition of a 2D primitive
+ virtual Primitive2DSequence create2DDecomposition(const geometry::ViewInformation2D& rViewInformation) const;
+
+ public:
+ SwVirtFlyDrawObjPrimitive(
+ const SwVirtFlyDrawObj& rSwVirtFlyDrawObj,
+ const basegfx::B2DRange &rOuterRange)
+ : BufferedDecompositionPrimitive2D(),
+ mrSwVirtFlyDrawObj(rSwVirtFlyDrawObj),
+ maOuterRange(rOuterRange)
+ {
+ }
+
+ // compare operator
+ virtual bool operator==(const BasePrimitive2D& rPrimitive) const;
+
+ // get range
+ virtual basegfx::B2DRange getB2DRange(const geometry::ViewInformation2D& rViewInformation) const;
+
+ // overloaded to allow callbacks to wrap_DoPaintObject
+ virtual Primitive2DSequence get2DDecomposition(const geometry::ViewInformation2D& rViewInformation) const;
+
+ // data read access
+ const SwVirtFlyDrawObj& getSwVirtFlyDrawObj() const { return mrSwVirtFlyDrawObj; }
+ const basegfx::B2DRange& getOuterRange() const { return maOuterRange; }
+
+ // provide unique ID
+ DeclPrimitrive2DIDBlock()
+ };
+ } // end of namespace primitive2d
+} // end of namespace drawinglayer
+
+namespace drawinglayer
+{
+ namespace primitive2d
+ {
+ Primitive2DSequence SwVirtFlyDrawObjPrimitive::create2DDecomposition(const geometry::ViewInformation2D& /*rViewInformation*/) const
+ {
+ Primitive2DSequence aRetval;
+
+ if(!getOuterRange().isEmpty())
+ {
+ // currently this SW object has no primitive representation. As long as this is the case,
+ // create invisible geometry to allow corfect HitTest and BoundRect calculations for the
+ // object. Use a filled primitive to get 'inside' as default object hit. The special cases from
+ // the old SwVirtFlyDrawObj::CheckHit implementation are handled now in SwDrawView::PickObj;
+ // this removed the 'hack' to get a view from inside model data or to react on null-tolerance
+ // as it was done in the old implementation
+ const Primitive2DReference aHitTestReference(
+ createHiddenGeometryPrimitives2D(
+ true,
+ getOuterRange()));
+
+ aRetval = Primitive2DSequence(&aHitTestReference, 1);
+ }
+
+ return aRetval;
+ }
+
+ bool SwVirtFlyDrawObjPrimitive::operator==(const BasePrimitive2D& rPrimitive) const
+ {
+ if(BufferedDecompositionPrimitive2D::operator==(rPrimitive))
+ {
+ const SwVirtFlyDrawObjPrimitive& rCompare = (SwVirtFlyDrawObjPrimitive&)rPrimitive;
+
+ return (&getSwVirtFlyDrawObj() == &rCompare.getSwVirtFlyDrawObj()
+ && getOuterRange() == rCompare.getOuterRange());
+ }
+
+ return false;
+ }
+
+ basegfx::B2DRange SwVirtFlyDrawObjPrimitive::getB2DRange(const geometry::ViewInformation2D& /*rViewInformation*/) const
+ {
+ return getOuterRange();
+ }
+
+ Primitive2DSequence SwVirtFlyDrawObjPrimitive::get2DDecomposition(const geometry::ViewInformation2D& rViewInformation) const
+ {
+ // This is the callback to keep the FlyFrame painting in SW alive as long as it
+ // is not changed to primitives. This is the method which will be called by the processors
+ // when they do not know this primitive (and they do not). Inside wrap_DoPaintObject
+ // there needs to be a test that paint is only done during SW repaints (see there).
+ // Using this mechanism guarantees the correct Z-Order of the VirtualObject-based FlyFrames.
+ getSwVirtFlyDrawObj().wrap_DoPaintObject();
+
+ // call parent
+ return BufferedDecompositionPrimitive2D::get2DDecomposition(rViewInformation);
+ }
+
+ // provide unique ID
+ ImplPrimitrive2DIDBlock(SwVirtFlyDrawObjPrimitive, PRIMITIVE2D_ID_SWVIRTFLYDRAWOBJPRIMITIVE2D)
+
+ } // end of namespace primitive2d
+} // end of namespace drawinglayer
+
+//////////////////////////////////////////////////////////////////////////////////////
+// AW: own sdr::contact::ViewContact (VC) sdr::contact::ViewObjectContact (VOC) needed
+// since offset is defined different from SdrVirtObj's sdr::contact::ViewContactOfVirtObj.
+// For paint, that offset is used by setting at the OutputDevice; for primitives this is
+// not possible since we have no OutputDevice, but define the geometry itself.
+
+namespace sdr
+{
+ namespace contact
+ {
+ class VCOfSwVirtFlyDrawObj : public ViewContactOfVirtObj
+ {
+ protected:
+ // This method is responsible for creating the graphical visualisation data
+ // ONLY based on model data
+ virtual drawinglayer::primitive2d::Primitive2DSequence createViewIndependentPrimitive2DSequence() const;
+
+ public:
+ // basic constructor, used from SdrObject.
+ VCOfSwVirtFlyDrawObj(SwVirtFlyDrawObj& rObj)
+ : ViewContactOfVirtObj(rObj)
+ {
+ }
+ virtual ~VCOfSwVirtFlyDrawObj();
+
+ // access to SwVirtFlyDrawObj
+ SwVirtFlyDrawObj& GetSwVirtFlyDrawObj() const
+ {
+ return (SwVirtFlyDrawObj&)mrObject;
+ }
+ };
+ } // end of namespace contact
+} // end of namespace sdr
+
+namespace sdr
+{
+ namespace contact
+ {
+ drawinglayer::primitive2d::Primitive2DSequence VCOfSwVirtFlyDrawObj::createViewIndependentPrimitive2DSequence() const
+ {
+ drawinglayer::primitive2d::Primitive2DSequence xRetval;
+ const SdrObject& rReferencedObject = GetSwVirtFlyDrawObj().GetReferencedObj();
+
+ if(rReferencedObject.ISA(SwFlyDrawObj))
+ {
+ // create an own specialized primitive which is used as repaint callpoint and HitTest
+ // for HitTest processor (see primitive implementation above)
+ const basegfx::B2DRange aOuterRange(GetSwVirtFlyDrawObj().getOuterBound());
+
+ if(!aOuterRange.isEmpty())
+ {
+ const drawinglayer::primitive2d::Primitive2DReference xPrimitive(
+ new drawinglayer::primitive2d::SwVirtFlyDrawObjPrimitive(
+ GetSwVirtFlyDrawObj(),
+ aOuterRange));
+
+ xRetval = drawinglayer::primitive2d::Primitive2DSequence(&xPrimitive, 1);
+ }
+ }
+
+ return xRetval;
+ }
+
+ VCOfSwVirtFlyDrawObj::~VCOfSwVirtFlyDrawObj()
+ {
+ }
+ } // end of namespace contact
+} // end of namespace sdr
+
+//////////////////////////////////////////////////////////////////////////////////////
+
+basegfx::B2DRange SwVirtFlyDrawObj::getOuterBound() const
+{
+ basegfx::B2DRange aOuterRange;
+ const SdrObject& rReferencedObject = GetReferencedObj();
+
+ if(rReferencedObject.ISA(SwFlyDrawObj))
+ {
+ const SwFlyFrm* pFlyFrame = GetFlyFrm();
+
+ if(pFlyFrame)
+ {
+ const Rectangle aOuterRectangle(pFlyFrame->Frm().Pos(), pFlyFrame->Frm().SSize());
+
+ if(!aOuterRectangle.IsEmpty()
+ && RECT_EMPTY != aOuterRectangle.Right()
+ && RECT_EMPTY != aOuterRectangle.Bottom())
+ {
+ aOuterRange.expand(basegfx::B2DTuple(aOuterRectangle.Left(), aOuterRectangle.Top()));
+ aOuterRange.expand(basegfx::B2DTuple(aOuterRectangle.Right(), aOuterRectangle.Bottom()));
+ }
+ }
+ }
+
+ return aOuterRange;
+}
+
+basegfx::B2DRange SwVirtFlyDrawObj::getInnerBound() const
+{
+ basegfx::B2DRange aInnerRange;
+ const SdrObject& rReferencedObject = GetReferencedObj();
+
+ if(rReferencedObject.ISA(SwFlyDrawObj))
+ {
+ const SwFlyFrm* pFlyFrame = GetFlyFrm();
+
+ if(pFlyFrame)
+ {
+ const Rectangle aInnerRectangle(pFlyFrame->Frm().Pos() + pFlyFrame->Prt().Pos(), pFlyFrame->Prt().SSize());
+
+ if(!aInnerRectangle.IsEmpty()
+ && RECT_EMPTY != aInnerRectangle.Right()
+ && RECT_EMPTY != aInnerRectangle.Bottom())
+ {
+ aInnerRange.expand(basegfx::B2DTuple(aInnerRectangle.Left(), aInnerRectangle.Top()));
+ aInnerRange.expand(basegfx::B2DTuple(aInnerRectangle.Right(), aInnerRectangle.Bottom()));
+ }
+ }
+ }
+
+ return aInnerRange;
+}
+
+sdr::contact::ViewContact* SwVirtFlyDrawObj::CreateObjectSpecificViewContact()
+{
+ // need an own ViewContact (VC) to allow creation of a specialized primitive
+ // for being able to visualize the FlyFrames in primitive renderers
+ return new sdr::contact::VCOfSwVirtFlyDrawObj(*this);
+}
+
+SwVirtFlyDrawObj::SwVirtFlyDrawObj(SdrObject& rNew, SwFlyFrm* pFly) :
+ SdrVirtObj( rNew ),
+ pFlyFrm( pFly )
+{
+ //#110094#-1
+ // bNotPersistent = bNeedColorRestore = bWriterFlyFrame = sal_True;
+ const SvxProtectItem &rP = pFlyFrm->GetFmt()->GetProtect();
+ bMovProt = rP.IsPosProtected();
+ bSizProt = rP.IsSizeProtected();
+}
+
+
+SwVirtFlyDrawObj::~SwVirtFlyDrawObj()
+{
+ if ( GetPage() ) //Der SdrPage die Verantwortung entziehen.
+ GetPage()->RemoveObject( GetOrdNum() );
+}
+
+/*************************************************************************
+|*
+|* SwVirtFlyDrawObj::GetFmt()
+|*
+*************************************************************************/
+
+const SwFrmFmt *SwVirtFlyDrawObj::GetFmt() const
+{
+ return GetFlyFrm()->GetFmt();
+}
+
+
+SwFrmFmt *SwVirtFlyDrawObj::GetFmt()
+{
+ return GetFlyFrm()->GetFmt();
+}
+
+/*************************************************************************
+|*
+|* SwVirtFlyDrawObj::Paint()
+|*
+*************************************************************************/
+
+void SwVirtFlyDrawObj::wrap_DoPaintObject() const
+{
+ ViewShell* pShell = pFlyFrm->getRootFrm()->GetCurrShell();
+
+ // Only paint when we have a current shell and a DrawingLayer paint is in progress.
+ // This avcoids evtl. problems with renderers which do processing stuff,
+ // but no paints. IsPaintInProgress() depends on SW repaint, so, as long
+ // as SW paints self and calls DrawLayer() for Heaven and Hell, this will
+ // be correct
+ if(pShell && pShell->IsDrawingLayerPaintInProgress())
+ {
+ sal_Bool bDrawObject(sal_True);
+
+ if(!SwFlyFrm::IsPaint((SdrObject*)this, pShell))
+ {
+ bDrawObject = sal_False;
+ }
+
+ if(bDrawObject)
+ {
+ if(!pFlyFrm->IsFlyInCntFrm())
+ {
+ // it is also necessary to restore the VCL MapMode from ViewInformation since e.g.
+ // the VCL PixelRenderer resets it at the used OutputDevice. Unfortunately, this
+ // excludes shears and rotates which are not expressable in MapMode.
+ OutputDevice* pOut = pShell->GetOut();
+
+ pOut->Push(PUSH_MAPMODE);
+ pOut->SetMapMode(pShell->getPrePostMapMode());
+
+ // paint the FlyFrame (use standard VCL-Paint)
+ pFlyFrm->Paint(GetFlyFrm()->Frm());
+
+ pOut->Pop();
+ }
+ }
+ }
+}
+
+/*************************************************************************
+|*
+|* SwVirtFlyDrawObj::TakeObjInfo()
+|*
+*************************************************************************/
+
+void SwVirtFlyDrawObj::TakeObjInfo( SdrObjTransformInfoRec& rInfo ) const
+{
+ rInfo.bSelectAllowed = rInfo.bMoveAllowed =
+ rInfo.bResizeFreeAllowed = rInfo.bResizePropAllowed = sal_True;
+
+ rInfo.bRotateFreeAllowed = rInfo.bRotate90Allowed =
+ rInfo.bMirrorFreeAllowed = rInfo.bMirror45Allowed =
+ rInfo.bMirror90Allowed = rInfo.bShearAllowed =
+ rInfo.bCanConvToPath = rInfo.bCanConvToPoly =
+ rInfo.bCanConvToPathLineToArea = rInfo.bCanConvToPolyLineToArea = sal_False;
+}
+
+
+/*************************************************************************
+|*
+|* SwVirtFlyDrawObj::Groessenermittlung
+|*
+*************************************************************************/
+
+void SwVirtFlyDrawObj::SetRect() const
+{
+ if ( GetFlyFrm()->Frm().HasArea() )
+ ((SwVirtFlyDrawObj*)this)->aOutRect = GetFlyFrm()->Frm().SVRect();
+ else
+ ((SwVirtFlyDrawObj*)this)->aOutRect = Rectangle();
+}
+
+
+const Rectangle& SwVirtFlyDrawObj::GetCurrentBoundRect() const
+{
+ SetRect();
+ return aOutRect;
+}
+
+const Rectangle& SwVirtFlyDrawObj::GetLastBoundRect() const
+{
+ return GetCurrentBoundRect();
+}
+
+
+void SwVirtFlyDrawObj::RecalcBoundRect()
+{
+ SetRect();
+}
+
+
+void SwVirtFlyDrawObj::RecalcSnapRect()
+{
+ SetRect();
+}
+
+
+const Rectangle& SwVirtFlyDrawObj::GetSnapRect() const
+{
+ SetRect();
+ return aOutRect;
+}
+
+
+void SwVirtFlyDrawObj::SetSnapRect(const Rectangle& )
+{
+ Rectangle aTmp( GetLastBoundRect() );
+ SetRect();
+ SetChanged();
+ BroadcastObjectChange();
+ if (pUserCall!=NULL)
+ pUserCall->Changed(*this, SDRUSERCALL_RESIZE, aTmp);
+}
+
+
+void SwVirtFlyDrawObj::NbcSetSnapRect(const Rectangle& )
+{
+ SetRect();
+}
+
+
+const Rectangle& SwVirtFlyDrawObj::GetLogicRect() const
+{
+ SetRect();
+ return aOutRect;
+}
+
+
+void SwVirtFlyDrawObj::SetLogicRect(const Rectangle& )
+{
+ Rectangle aTmp( GetLastBoundRect() );
+ SetRect();
+ SetChanged();
+ BroadcastObjectChange();
+ if (pUserCall!=NULL)
+ pUserCall->Changed(*this, SDRUSERCALL_RESIZE, aTmp);
+}
+
+
+void SwVirtFlyDrawObj::NbcSetLogicRect(const Rectangle& )
+{
+ SetRect();
+}
+
+
+::basegfx::B2DPolyPolygon SwVirtFlyDrawObj::TakeXorPoly() const
+{
+ const Rectangle aSourceRectangle(GetFlyFrm()->Frm().SVRect());
+ const ::basegfx::B2DRange aSourceRange(aSourceRectangle.Left(), aSourceRectangle.Top(), aSourceRectangle.Right(), aSourceRectangle.Bottom());
+ ::basegfx::B2DPolyPolygon aRetval;
+
+ aRetval.append(::basegfx::tools::createPolygonFromRect(aSourceRange));
+
+ return aRetval;
+}
+
+/*************************************************************************
+|*
+|* SwVirtFlyDrawObj::Move() und Resize()
+|*
+*************************************************************************/
+
+void SwVirtFlyDrawObj::NbcMove(const Size& rSiz)
+{
+ MoveRect( aOutRect, rSiz );
+ const Point aOldPos( GetFlyFrm()->Frm().Pos() );
+ const Point aNewPos( aOutRect.TopLeft() );
+ const SwRect aFlyRect( aOutRect );
+
+ //Wenn der Fly eine automatische Ausrichtung hat (rechts oder oben),
+ //so soll die Automatik erhalten bleiben
+ SwFrmFmt *pFmt = GetFlyFrm()->GetFmt();
+ const sal_Int16 eHori = pFmt->GetHoriOrient().GetHoriOrient();
+ const sal_Int16 eVert = pFmt->GetVertOrient().GetVertOrient();
+ const sal_Int16 eRelHori = pFmt->GetHoriOrient().GetRelationOrient();
+ const sal_Int16 eRelVert = pFmt->GetVertOrient().GetRelationOrient();
+ //Bei Absatzgebundenen Flys muss ausgehend von der neuen Position ein
+ //neuer Anker gesetzt werden. Anker und neue RelPos werden vom Fly selbst
+ //berechnet und gesetzt.
+ if( GetFlyFrm()->IsFlyAtCntFrm() )
+ ((SwFlyAtCntFrm*)GetFlyFrm())->SetAbsPos( aNewPos );
+ else
+ {
+ const SwFrmFmt *pTmpFmt = GetFmt();
+ const SwFmtVertOrient &rVert = pTmpFmt->GetVertOrient();
+ const SwFmtHoriOrient &rHori = pTmpFmt->GetHoriOrient();
+ long lXDiff = aNewPos.X() - aOldPos.X();
+ if( rHori.IsPosToggle() && text::HoriOrientation::NONE == eHori &&
+ !GetFlyFrm()->FindPageFrm()->OnRightPage() )
+ lXDiff = -lXDiff;
+
+ if( GetFlyFrm()->GetAnchorFrm()->IsRightToLeft() &&
+ text::HoriOrientation::NONE == eHori )
+ lXDiff = -lXDiff;
+
+ long lYDiff = aNewPos.Y() - aOldPos.Y();
+ if( GetFlyFrm()->GetAnchorFrm()->IsVertical() )
+ {
+ //lXDiff -= rVert.GetPos();
+ //lYDiff += rHori.GetPos();
+ //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin
+ if ( GetFlyFrm()->GetAnchorFrm()->IsVertLR() )
+ {
+ lXDiff += rVert.GetPos();
+ lXDiff = -lXDiff;
+ }
+ else
+ {
+ lXDiff -= rVert.GetPos();
+ lYDiff += rHori.GetPos();
+ }
+ }
+ else
+ {
+ lXDiff += rHori.GetPos();
+ lYDiff += rVert.GetPos();
+ }
+
+ if( GetFlyFrm()->GetAnchorFrm()->IsRightToLeft() &&
+ text::HoriOrientation::NONE != eHori )
+ lXDiff = GetFlyFrm()->GetAnchorFrm()->Frm().Width() -
+ aFlyRect.Width() - lXDiff;
+
+ const Point aTmp( lXDiff, lYDiff );
+ GetFlyFrm()->ChgRelPos( aTmp );
+ }
+
+ SwAttrSet aSet( pFmt->GetDoc()->GetAttrPool(),
+ RES_VERT_ORIENT, RES_HORI_ORIENT );
+ SwFmtHoriOrient aHori( pFmt->GetHoriOrient() );
+ SwFmtVertOrient aVert( pFmt->GetVertOrient() );
+ sal_Bool bPut = sal_False;
+
+ if( !GetFlyFrm()->IsFlyLayFrm() &&
+ ::GetHtmlMode(pFmt->GetDoc()->GetDocShell()) )
+ {
+ //Im HTML-Modus sind nur automatische Ausrichtungen erlaubt.
+ //Einzig einen Snap auf Links/Rechts bzw. Linker-/Rechter-Rand koennen
+ //wir versuchen.
+ const SwFrm* pAnch = GetFlyFrm()->GetAnchorFrm();
+ sal_Bool bNextLine = sal_False;
+
+ if( !GetFlyFrm()->IsAutoPos() || text::RelOrientation::PAGE_FRAME != aHori.GetRelationOrient() )
+ {
+ if( text::RelOrientation::CHAR == eRelHori )
+ {
+ aHori.SetHoriOrient( text::HoriOrientation::LEFT );
+ aHori.SetRelationOrient( text::RelOrientation::CHAR );
+ }
+ else
+ {
+ bNextLine = sal_True;
+ //Horizontale Ausrichtung:
+ const sal_Bool bLeftFrm =
+ aFlyRect.Left() < pAnch->Frm().Left() + pAnch->Prt().Left(),
+ bLeftPrt = aFlyRect.Left() + aFlyRect.Width() <
+ pAnch->Frm().Left() + pAnch->Prt().Width()/2;
+ if ( bLeftFrm || bLeftPrt )
+ {
+ aHori.SetHoriOrient( text::HoriOrientation::LEFT );
+ aHori.SetRelationOrient( bLeftFrm ? text::RelOrientation::FRAME : text::RelOrientation::PRINT_AREA );
+ }
+ else
+ {
+ const sal_Bool bRightFrm = aFlyRect.Left() >
+ pAnch->Frm().Left() + pAnch->Prt().Width();
+ aHori.SetHoriOrient( text::HoriOrientation::RIGHT );
+ aHori.SetRelationOrient( bRightFrm ? text::RelOrientation::FRAME : text::RelOrientation::PRINT_AREA );
+ }
+ }
+ aSet.Put( aHori );
+ }
+ //Vertikale Ausrichtung bleibt grundsaetzlich schlicht erhalten,
+ //nur bei nicht automatischer Ausrichtung wird umgeschaltet.
+ sal_Bool bRelChar = text::RelOrientation::CHAR == eRelVert;
+ aVert.SetVertOrient( eVert != text::VertOrientation::NONE ? eVert :
+ GetFlyFrm()->IsFlyInCntFrm() ? text::VertOrientation::CHAR_CENTER :
+ bRelChar && bNextLine ? text::VertOrientation::CHAR_TOP : text::VertOrientation::TOP );
+ if( bRelChar )
+ aVert.SetRelationOrient( text::RelOrientation::CHAR );
+ else
+ aVert.SetRelationOrient( text::RelOrientation::PRINT_AREA );
+ aSet.Put( aVert );
+ bPut = sal_True;
+ }
+
+ //Automatische Ausrichtungen wollen wir moeglichst nicht verlieren.
+ if ( !bPut && bInResize )
+ {
+ if ( text::HoriOrientation::NONE != eHori )
+ {
+ aHori.SetHoriOrient( eHori );
+ aHori.SetRelationOrient( eRelHori );
+ aSet.Put( aHori );
+ bPut = sal_True;
+ }
+ if ( text::VertOrientation::NONE != eVert )
+ {
+ aVert.SetVertOrient( eVert );
+ aVert.SetRelationOrient( eRelVert );
+ aSet.Put( aVert );
+ bPut = sal_True;
+ }
+ }
+ if ( bPut )
+ pFmt->SetFmtAttr( aSet );
+}
+
+
+void SwVirtFlyDrawObj::NbcResize(const Point& rRef,
+ const Fraction& xFact, const Fraction& yFact)
+{
+ ResizeRect( aOutRect, rRef, xFact, yFact );
+
+ const SwFrm* pTmpFrm = GetFlyFrm()->GetAnchorFrm();
+ if( !pTmpFrm )
+ pTmpFrm = GetFlyFrm();
+ const bool bVertX = pTmpFrm->IsVertical();
+
+ const sal_Bool bRTL = pTmpFrm->IsRightToLeft();
+
+ //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin
+ const bool bVertL2RX = pTmpFrm->IsVertLR();
+ const Point aNewPos( ( bVertX && !bVertL2RX ) || bRTL ?
+ aOutRect.Right() + 1 :
+ aOutRect.Left(),
+ aOutRect.Top() );
+
+ Size aSz( aOutRect.Right() - aOutRect.Left() + 1,
+ aOutRect.Bottom()- aOutRect.Top() + 1 );
+ if( aSz != GetFlyFrm()->Frm().SSize() )
+ {
+ //Die Breite darf bei Spalten nicht zu schmal werden
+ if ( GetFlyFrm()->Lower() && GetFlyFrm()->Lower()->IsColumnFrm() )
+ {
+ SwBorderAttrAccess aAccess( SwFrm::GetCache(), GetFlyFrm() );
+ const SwBorderAttrs &rAttrs = *aAccess.Get();
+ long nMin = rAttrs.CalcLeftLine()+rAttrs.CalcRightLine();
+ const SwFmtCol& rCol = rAttrs.GetAttrSet().GetCol();
+ if ( rCol.GetColumns().Count() > 1 )
+ {
+ for ( sal_uInt16 i = 0; i < rCol.GetColumns().Count(); ++i )
+ {
+ nMin += rCol.GetColumns()[i]->GetLeft() +
+ rCol.GetColumns()[i]->GetRight() +
+ MINFLY;
+ }
+ nMin -= MINFLY;
+ }
+ aSz.Width() = Max( aSz.Width(), nMin );
+ }
+
+ SwFrmFmt *pFmt = GetFmt();
+ const SwFmtFrmSize aOldFrmSz( pFmt->GetFrmSize() );
+ GetFlyFrm()->ChgSize( aSz );
+ SwFmtFrmSize aFrmSz( pFmt->GetFrmSize() );
+ if ( aFrmSz.GetWidthPercent() || aFrmSz.GetHeightPercent() )
+ {
+ long nRelWidth, nRelHeight;
+ const SwFrm *pRel = GetFlyFrm()->IsFlyLayFrm() ?
+ GetFlyFrm()->GetAnchorFrm() :
+ GetFlyFrm()->GetAnchorFrm()->GetUpper();
+ const ViewShell *pSh = GetFlyFrm()->getRootFrm()->GetCurrShell();
+ if ( pSh && pRel->IsBodyFrm() &&
+ pSh->GetViewOptions()->getBrowseMode() &&
+ pSh->VisArea().HasArea() )
+ {
+ nRelWidth = pSh->GetBrowseWidth();
+ nRelHeight = pSh->VisArea().Height();
+ const Size aBorder = pSh->GetOut()->PixelToLogic( pSh->GetBrowseBorder() );
+ nRelHeight -= 2*aBorder.Height();
+ }
+ else
+ {
+ nRelWidth = pRel->Prt().Width();
+ nRelHeight = pRel->Prt().Height();
+ }
+ if ( aFrmSz.GetWidthPercent() && aFrmSz.GetWidthPercent() != 0xFF &&
+ aOldFrmSz.GetWidth() != aFrmSz.GetWidth() )
+ aFrmSz.SetWidthPercent( sal_uInt8(aSz.Width() * 100L / nRelWidth + 0.5) );
+ if ( aFrmSz.GetHeightPercent() && aFrmSz.GetHeightPercent() != 0xFF &&
+ aOldFrmSz.GetHeight() != aFrmSz.GetHeight() )
+ aFrmSz.SetHeightPercent( sal_uInt8(aSz.Height() * 100L / nRelHeight + 0.5) );
+ pFmt->GetDoc()->SetAttr( aFrmSz, *pFmt );
+ }
+ }
+
+ //Position kann auch veraendert sein!
+ const Point aOldPos( ( bVertX && !bVertL2RX ) || bRTL ?
+ GetFlyFrm()->Frm().TopRight() :
+ GetFlyFrm()->Frm().Pos() );
+ if ( aNewPos != aOldPos )
+ {
+ //Kann sich durch das ChgSize veraendert haben!
+ if( bVertX || bRTL )
+ {
+ if( aOutRect.TopRight() != aNewPos )
+ {
+ //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin
+ SwTwips nDeltaX;
+ if ( bVertL2RX )
+ nDeltaX = aNewPos.X() - aOutRect.Left();
+ else
+ nDeltaX = aNewPos.X() - aOutRect.Right();
+ SwTwips nDeltaY = aNewPos.Y() - aOutRect.Top();
+ MoveRect( aOutRect, Size( nDeltaX, nDeltaY ) );
+ }
+ }
+ else if ( aOutRect.TopLeft() != aNewPos )
+ aOutRect.SetPos( aNewPos );
+ bInResize = sal_True;
+ NbcMove( Size( 0, 0 ) );
+ bInResize = sal_False;
+ }
+}
+
+
+void SwVirtFlyDrawObj::Move(const Size& rSiz)
+{
+ NbcMove( rSiz );
+ SetChanged();
+ GetFmt()->GetDoc()->GetIDocumentUndoRedo().DoDrawUndo(false);
+}
+
+
+void SwVirtFlyDrawObj::Resize(const Point& rRef,
+ const Fraction& xFact, const Fraction& yFact)
+{
+ NbcResize( rRef, xFact, yFact );
+ SetChanged();
+ GetFmt()->GetDoc()->GetIDocumentUndoRedo().DoDrawUndo(false);
+}
+
+
+Pointer SwVirtFlyDrawObj::GetMacroPointer(
+ const SdrObjMacroHitRec& ) const
+{
+ return Pointer( POINTER_REFHAND );
+}
+
+
+bool SwVirtFlyDrawObj::HasMacro() const
+{
+ const SwFmtURL &rURL = pFlyFrm->GetFmt()->GetURL();
+ return rURL.GetMap() || rURL.GetURL().Len();
+}
+
+
+SdrObject* SwVirtFlyDrawObj::CheckMacroHit( const SdrObjMacroHitRec& rRec ) const
+{
+ const SwFmtURL &rURL = pFlyFrm->GetFmt()->GetURL();
+ if( rURL.GetMap() || rURL.GetURL().Len() )
+ {
+ SwRect aRect;
+ if ( pFlyFrm->Lower() && pFlyFrm->Lower()->IsNoTxtFrm() )
+ {
+ aRect = pFlyFrm->Prt();
+ aRect += pFlyFrm->Frm().Pos();
+ }
+ else
+ aRect = pFlyFrm->Frm();
+
+ if( aRect.IsInside( rRec.aPos ) )
+ {
+ SwRect aActRect( aRect );
+ Size aActSz( aRect.SSize() );
+ aRect.Pos().X() += rRec.nTol;
+ aRect.Pos().Y() += rRec.nTol;
+ aRect.SSize().Height()-= 2 * rRec.nTol;
+ aRect.SSize().Width() -= 2 * rRec.nTol;
+
+ if( aRect.IsInside( rRec.aPos ) )
+ {
+ if( !rURL.GetMap() ||
+ pFlyFrm->GetFmt()->GetIMapObject( rRec.aPos, pFlyFrm ))
+ return (SdrObject*)this;
+
+ return 0;
+ }
+ }
+ }
+ return SdrObject::CheckMacroHit( rRec );
+}
+
+bool SwVirtFlyDrawObj::supportsFullDrag() const
+{
+ // call parent
+ return SdrVirtObj::supportsFullDrag();
+}
+
+SdrObject* SwVirtFlyDrawObj::getFullDragClone() const
+{
+ // call parent
+ return SdrVirtObj::getFullDragClone();
+}
+
+// eof
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/draw/dobjfac.cxx b/sw/source/core/draw/dobjfac.cxx
new file mode 100644
index 000000000000..cecf6ef03c14
--- /dev/null
+++ b/sw/source/core/draw/dobjfac.cxx
@@ -0,0 +1,58 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+
+#include <dpage.hxx>
+#include <dobjfac.hxx>
+#include <dflyobj.hxx>
+
+SwObjectFactory aSwObjectFactory;
+
+/*************************************************************************
+|*
+|* void SwObjectFactory::MakeObject()
+|*
+\************************************************************************/
+
+IMPL_LINK( SwObjectFactory, MakeObject, SdrObjFactory*, pObjFactory )
+{
+ if ( pObjFactory->nInventor == SWGInventor )
+ {
+ //Kein switch, derzeit gibt es nur einen.
+ OSL_ENSURE( pObjFactory->nIdentifier == SwFlyDrawObjIdentifier,
+ "Falscher Inventor oder identifier." );
+ pObjFactory->pNewObj = new SwFlyDrawObj();
+ }
+ return 0;
+}
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/draw/dpage.cxx b/sw/source/core/draw/dpage.cxx
new file mode 100644
index 000000000000..b47d1a1c134c
--- /dev/null
+++ b/sw/source/core/draw/dpage.cxx
@@ -0,0 +1,254 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+#include <basic/basmgr.hxx>
+#include <svtools/imapobj.hxx>
+#include <svl/urihelper.hxx>
+#include <unotools/securityoptions.hxx>
+#include <vcl/help.hxx>
+#include <svx/svdview.hxx>
+#include <fmturl.hxx>
+#include <frmfmt.hxx>
+#include <doc.hxx>
+#include <shellres.hxx>
+#include <viewimp.hxx>
+#include <pagefrm.hxx>
+#include <cntfrm.hxx>
+#include <rootfrm.hxx>
+#include <frmatr.hxx>
+#include <viewsh.hxx>
+#include <drawdoc.hxx>
+#include <dpage.hxx>
+#include <dcontact.hxx>
+#include <dflyobj.hxx>
+#include <docsh.hxx>
+#include <usrfld.hxx>
+#include <flyfrm.hxx>
+#include <ndnotxt.hxx>
+#include <grfatr.hxx>
+#include <com/sun/star/drawing/XDrawPageSupplier.hpp>
+
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::drawing;
+using namespace ::com::sun::star::frame;
+
+SwDPage::SwDPage(SwDrawDocument& rNewModel, sal_Bool bMasterPage) :
+ FmFormPage(rNewModel, 0, bMasterPage),
+ pGridLst( 0 ),
+ rDoc(rNewModel.GetDoc())
+{
+}
+
+
+SwDPage::~SwDPage()
+{
+ delete pGridLst;
+}
+
+/*************************************************************************
+|*
+|* SwDPage::ReplaceObject()
+|*
+*************************************************************************/
+
+SdrObject* SwDPage::ReplaceObject( SdrObject* pNewObj, sal_uLong nObjNum )
+{
+ SdrObject *pOld = GetObj( nObjNum );
+ OSL_ENSURE( pOld, "Oups, Object not replaced" );
+ SdrObjUserCall* pContact;
+ if ( 0 != ( pContact = GetUserCall(pOld) ) &&
+ RES_DRAWFRMFMT == ((SwContact*)pContact)->GetFmt()->Which())
+ ((SwDrawContact*)pContact)->ChangeMasterObject( pNewObj );
+ return FmFormPage::ReplaceObject( pNewObj, nObjNum );
+}
+
+/*************************************************************************
+|*
+|* SwDPage::GetGridFrameList()
+|*
+*************************************************************************/
+
+void InsertGridFrame( SdrPageGridFrameList *pLst, const SwFrm *pPg )
+{
+ SwRect aPrt( pPg->Prt() );
+ aPrt += pPg->Frm().Pos();
+ const Rectangle aUser( aPrt.SVRect() );
+ const Rectangle aPaper( pPg->Frm().SVRect() );
+ pLst->Insert( SdrPageGridFrame( aPaper, aUser ) );
+}
+
+
+const SdrPageGridFrameList* SwDPage::GetGridFrameList(
+ const SdrPageView* pPV, const Rectangle *pRect ) const
+{
+ ViewShell *pSh = ((SwDrawDocument*)GetModel())->GetDoc().GetCurrentViewShell(); //swmod 071108//swmod 071225
+ if ( pSh )
+ {
+ while ( pSh->Imp()->GetPageView() != pPV )
+ pSh = (ViewShell*)pSh->GetNext();
+ if ( pSh )
+ {
+ if ( pGridLst )
+ ((SwDPage*)this)->pGridLst->Clear();
+ else
+ ((SwDPage*)this)->pGridLst = new SdrPageGridFrameList;
+
+ if ( pRect )
+ {
+ //Das Drawing verlang alle Seiten, die mit dem Rect ueberlappen.
+ const SwRect aRect( *pRect );
+ const SwFrm *pPg = pSh->GetLayout()->Lower();
+ do
+ { if ( pPg->Frm().IsOver( aRect ) )
+ ::InsertGridFrame( ((SwDPage*)this)->pGridLst, pPg );
+ pPg = pPg->GetNext();
+ } while ( pPg );
+ }
+ else
+ {
+ //Das Drawing verlangt alle sichbaren Seiten
+ const SwFrm *pPg = pSh->Imp()->GetFirstVisPage();
+ if ( pPg )
+ do
+ { ::InsertGridFrame( ((SwDPage*)this)->pGridLst, pPg );
+ pPg = pPg->GetNext();
+ } while ( pPg && pPg->Frm().IsOver( pSh->VisArea() ) );
+ }
+ }
+ }
+ return pGridLst;
+}
+
+sal_Bool SwDPage::RequestHelp( Window* pWindow, SdrView* pView,
+ const HelpEvent& rEvt )
+{
+ sal_Bool bWeiter = sal_True;
+
+ if( rEvt.GetMode() & ( HELPMODE_QUICK | HELPMODE_BALLOON ))
+ {
+ Point aPos( rEvt.GetMousePosPixel() );
+ aPos = pWindow->ScreenToOutputPixel( aPos );
+ aPos = pWindow->PixelToLogic( aPos );
+
+ SdrPageView* pPV;
+ SdrObject* pObj;
+ if( pView->PickObj( aPos, 0, pObj, pPV, SDRSEARCH_PICKMACRO ) &&
+ pObj->ISA(SwVirtFlyDrawObj) )
+ {
+ SwFlyFrm *pFly = ((SwVirtFlyDrawObj*)pObj)->GetFlyFrm();
+ const SwFmtURL &rURL = pFly->GetFmt()->GetURL();
+ String sTxt;
+ if( rURL.GetMap() )
+ {
+ IMapObject *pTmpObj = pFly->GetFmt()->GetIMapObject( aPos, pFly );
+ if( pTmpObj )
+ {
+ sTxt = pTmpObj->GetAltText();
+ if ( !sTxt.Len() )
+ sTxt = URIHelper::removePassword( pTmpObj->GetURL(),
+ INetURLObject::WAS_ENCODED,
+ INetURLObject::DECODE_UNAMBIGUOUS);
+ }
+ }
+ else if ( rURL.GetURL().Len() )
+ {
+ sTxt = URIHelper::removePassword( rURL.GetURL(),
+ INetURLObject::WAS_ENCODED,
+ INetURLObject::DECODE_UNAMBIGUOUS);
+
+ if( rURL.IsServerMap() )
+ {
+ // dann die rel. Pixel Position anhaengen !!
+ Point aPt( aPos );
+ aPt -= pFly->Frm().Pos();
+ // ohne MapMode-Offset !!!!!
+ // ohne MapMode-Offset, ohne Offset, o ... !!!!!
+ aPt = pWindow->LogicToPixel(
+ aPt, MapMode( MAP_TWIP ) );
+ ((( sTxt += '?' ) += String::CreateFromInt32( aPt.X() ))
+ += ',' ) += String::CreateFromInt32( aPt.Y() );
+ }
+ }
+
+ if ( sTxt.Len() )
+ {
+ // --> OD 2007-07-26 #i80029#
+ sal_Bool bExecHyperlinks = rDoc.GetDocShell()->IsReadOnly();
+ if ( !bExecHyperlinks )
+ {
+ SvtSecurityOptions aSecOpts;
+ bExecHyperlinks = !aSecOpts.IsOptionSet( SvtSecurityOptions::E_CTRLCLICK_HYPERLINK );
+
+ if ( !bExecHyperlinks )
+ {
+ sTxt.InsertAscii( ": ", 0 );
+ sTxt.Insert( ViewShell::GetShellRes()->aHyperlinkClick, 0 );
+ }
+ }
+
+ // <--
+
+ if( rEvt.GetMode() & HELPMODE_BALLOON )
+ {
+ Help::ShowBalloon( pWindow, rEvt.GetMousePosPixel(), sTxt );
+ }
+ else
+ {
+ // dann zeige die Hilfe mal an:
+ Rectangle aRect( rEvt.GetMousePosPixel(), Size(1,1) );
+ Help::ShowQuickHelp( pWindow, aRect, sTxt );
+ }
+ bWeiter = sal_False;
+ }
+ }
+ }
+
+ if( bWeiter )
+ bWeiter = !FmFormPage::RequestHelp( pWindow, pView, rEvt );
+
+ return bWeiter;
+}
+
+Reference< XInterface > SwDPage::createUnoPage()
+{
+ Reference < XInterface > xRet;
+ SwDocShell* pDocShell = rDoc.GetDocShell();
+ if ( pDocShell )
+ {
+ Reference<XModel> xModel = pDocShell->GetBaseModel();
+ Reference<XDrawPageSupplier> xPageSupp(xModel, UNO_QUERY);
+ xRet = xPageSupp->getDrawPage();
+ }
+ return xRet;
+}
+
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/draw/drawdoc.cxx b/sw/source/core/draw/drawdoc.cxx
new file mode 100644
index 000000000000..5e2a2c138e83
--- /dev/null
+++ b/sw/source/core/draw/drawdoc.cxx
@@ -0,0 +1,234 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+#include <svx/svxids.hrc>
+#include <tools/stream.hxx>
+#include <unotools/pathoptions.hxx>
+#include <sot/storage.hxx>
+#include <svl/intitem.hxx>
+#include <editeng/forbiddencharacterstable.hxx>
+
+#include <unotools/ucbstreamhelper.hxx>
+#include <svx/xtable.hxx>
+#include <svx/drawitem.hxx>
+#include <viewsh.hxx>
+#include <doc.hxx>
+#include <rootfrm.hxx>
+#include <drawdoc.hxx>
+#include <dpage.hxx>
+#include <docsh.hxx>
+#include <shellio.hxx>
+#include <hintids.hxx>
+#include <com/sun/star/embed/ElementModes.hpp>
+
+using namespace com::sun::star;
+
+/*************************************************************************
+|*
+|* Konstruktor
+|*
+\************************************************************************/
+
+const String GetPalettePath()
+{
+ SvtPathOptions aPathOpt;
+ return aPathOpt.GetPalettePath();
+}
+
+SwDrawDocument::SwDrawDocument( SwDoc* pD ) :
+ FmFormModel( ::GetPalettePath(), &pD->GetAttrPool(),
+ pD->GetDocShell(), sal_True ),
+ pDoc( pD )
+{
+ SetScaleUnit( MAP_TWIP );
+ SetSwapGraphics( sal_True );
+
+ SwDocShell* pDocSh = pDoc->GetDocShell();
+ if ( pDocSh )
+ {
+ SetObjectShell( pDocSh );
+ SvxColorTableItem* pColItem = ( SvxColorTableItem* )
+ ( pDocSh->GetItem( SID_COLOR_TABLE ) );
+ XColorTable *pXCol = pColItem ? pColItem->GetColorTable() :
+ XColorTable::GetStdColorTable();
+ SetColorTable( pXCol );
+
+ if ( !pColItem )
+ pDocSh->PutItem( SvxColorTableItem( pXCol, SID_COLOR_TABLE ) );
+
+ pDocSh->PutItem( SvxGradientListItem( GetGradientList(), SID_GRADIENT_LIST ));
+ pDocSh->PutItem( SvxHatchListItem( GetHatchList(), SID_HATCH_LIST ) );
+ pDocSh->PutItem( SvxBitmapListItem( GetBitmapList(), SID_BITMAP_LIST ) );
+ pDocSh->PutItem( SvxDashListItem( GetDashList(), SID_DASH_LIST ) );
+ pDocSh->PutItem( SvxLineEndListItem( GetLineEndList(), SID_LINEEND_LIST ) );
+ pDocSh->PutItem( SfxUInt16Item(SID_ATTR_LINEEND_WIDTH_DEFAULT, 111) );
+ SetObjectShell( pDocSh );
+ }
+ else
+ SetColorTable( XColorTable::GetStdColorTable() );
+
+ // copy all the default values to the SdrModel
+ SfxItemPool* pSdrPool = pD->GetAttrPool().GetSecondaryPool();
+ if( pSdrPool )
+ {
+ const sal_uInt16 aWhichRanges[] =
+ {
+ RES_CHRATR_BEGIN, RES_CHRATR_END,
+ RES_PARATR_BEGIN, RES_PARATR_END,
+ 0
+ };
+
+ SfxItemPool& rDocPool = pD->GetAttrPool();
+ sal_uInt16 nEdtWhich, nSlotId;
+ const SfxPoolItem* pItem;
+ for( const sal_uInt16* pRangeArr = aWhichRanges;
+ *pRangeArr; pRangeArr += 2 )
+ for( sal_uInt16 nW = *pRangeArr, nEnd = *(pRangeArr+1);
+ nW < nEnd; ++nW )
+ if( 0 != (pItem = rDocPool.GetPoolDefaultItem( nW )) &&
+ 0 != (nSlotId = rDocPool.GetSlotId( nW ) ) &&
+ nSlotId != nW &&
+ 0 != (nEdtWhich = pSdrPool->GetWhich( nSlotId )) &&
+ nSlotId != nEdtWhich )
+ {
+ SfxPoolItem* pCpy = pItem->Clone();
+ pCpy->SetWhich( nEdtWhich );
+ pSdrPool->SetPoolDefaultItem( *pCpy );
+ delete pCpy;
+ }
+ }
+
+ SetForbiddenCharsTable( pD->getForbiddenCharacterTable() );
+ // Implementation for asian compression
+ SetCharCompressType( static_cast<sal_uInt16>(pD->getCharacterCompressionType() ));
+}
+
+/*************************************************************************
+|*
+|* Destruktor
+|*
+\************************************************************************/
+
+
+SwDrawDocument::~SwDrawDocument()
+{
+ Broadcast(SdrHint(HINT_MODELCLEARED));
+
+ ClearModel(sal_True);
+}
+
+/*************************************************************************
+|*
+|* Diese Methode erzeugt eine neue Seite (SdPage) und gibt einen Zeiger
+|* darauf zurueck. Die Drawing Engine benutzt diese Methode beim Laden
+|* zur Erzeugung von Seiten (deren Typ sie ja nicht kennt, da es ABLEITUNGEN
+|* der SdrPage sind).
+|*
+\************************************************************************/
+
+
+SdrPage* SwDrawDocument::AllocPage(bool bMasterPage)
+{
+ SwDPage* pPage = new SwDPage(*this, 0 != bMasterPage);
+ pPage->SetName( String::CreateFromAscii(
+ RTL_CONSTASCII_STRINGPARAM( "Controls" )) );
+ return pPage;
+}
+
+
+SvStream* SwDrawDocument::GetDocumentStream( SdrDocumentStreamInfo& rInfo ) const
+{
+ SvStream* pRet = NULL;
+ uno::Reference < embed::XStorage > xRoot( pDoc->GetDocStorage() );
+ if( xRoot.is() )
+ {
+ if( rInfo.maUserData.Len() &&
+ ( rInfo.maUserData.GetToken( 0, ':' ) ==
+ String( RTL_CONSTASCII_USTRINGPARAM( "vnd.sun.star.Package" ) ) ) )
+ {
+ const String aPicturePath( rInfo.maUserData.GetToken( 1, ':' ) );
+
+ // graphic from picture stream in picture storage in XML package
+ if( aPicturePath.GetTokenCount( '/' ) == 2 )
+ {
+ const String aPictureStorageName( aPicturePath.GetToken( 0, '/' ) );
+ const String aPictureStreamName( aPicturePath.GetToken( 1, '/' ) );
+
+ try
+ {
+ uno::Reference < embed::XStorage > xPictureStorage = xRoot->openStorageElement(
+ aPictureStorageName, embed::ElementModes::READ );
+ uno::Reference < io::XStream > xStream = xPictureStorage->openStreamElement(
+ aPictureStreamName, embed::ElementModes::READ );
+ pRet = utl::UcbStreamHelper::CreateStream( xStream );
+ if( pRet )
+ {
+ rInfo.mbDeleteAfterUse = sal_True;
+ rInfo.mxStorageRef = xPictureStorage;
+ }
+ }
+ catch ( uno::Exception& )
+ {
+ }
+ }
+ }
+ }
+ return pRet;
+}
+
+SdrLayerID SwDrawDocument::GetControlExportLayerId( const SdrObject & ) const
+{
+ //fuer Versionen < 5.0, es gab nur Hell und Heaven
+ return (SdrLayerID)pDoc->GetHeavenId();
+}
+
+uno::Reference< uno::XInterface > SwDrawDocument::createUnoModel()
+{
+
+ uno::Reference< uno::XInterface > xModel;
+
+ try
+ {
+ if ( GetDoc().GetDocShell() )
+ {
+ xModel = GetDoc().GetDocShell()->GetModel();
+ }
+ }
+ catch( uno::RuntimeException& )
+ {
+ OSL_FAIL( "<SwDrawDocument::createUnoModel()> - could *not* retrieve model at <SwDocShell>" );
+ }
+
+ return xModel;
+}
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/draw/dview.cxx b/sw/source/core/draw/dview.cxx
new file mode 100644
index 000000000000..4827627f6ef1
--- /dev/null
+++ b/sw/source/core/draw/dview.cxx
@@ -0,0 +1,1071 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+#include "hintids.hxx"
+#include <editeng/protitem.hxx>
+#include <svx/svdpagv.hxx>
+#include <svx/fmmodel.hxx>
+#include <sot/exchange.hxx>
+
+#include "swtypes.hxx"
+#include "pagefrm.hxx"
+#include "rootfrm.hxx"
+#include "cntfrm.hxx"
+#include "flyfrm.hxx"
+#include "frmfmt.hxx"
+#include "dflyobj.hxx"
+#include "dcontact.hxx"
+#include "frmatr.hxx"
+#include "viewsh.hxx"
+#include "viewimp.hxx"
+#include "dview.hxx"
+#include "dpage.hxx"
+#include "doc.hxx"
+#include "mdiexp.hxx"
+#include <ndole.hxx>
+#include <fmtanchr.hxx>
+#include "shellres.hxx"
+#include <IDocumentUndoRedo.hxx>
+
+// #i7672#
+#include <editeng/outliner.hxx>
+
+#include <com/sun/star/embed/EmbedMisc.hpp>
+
+#include <vector>
+// --> OD 2004-06-24 #i28701#
+#include <sortedobjs.hxx>
+#include <flyfrms.hxx>
+// <--
+
+
+using namespace com::sun::star;
+
+
+class SwSdrHdl : public SdrHdl
+{
+public:
+ SwSdrHdl(const Point& rPnt, bool bTopRight ) :
+ SdrHdl( rPnt, bTopRight ? HDL_ANCHOR_TR : HDL_ANCHOR ) {}
+ virtual sal_Bool IsFocusHdl() const;
+};
+
+sal_Bool SwSdrHdl::IsFocusHdl() const
+{
+ if( HDL_ANCHOR == eKind || HDL_ANCHOR_TR == eKind )
+ return sal_True;
+ return SdrHdl::IsFocusHdl();
+}
+
+const SwFrm *lcl_FindAnchor( const SdrObject *pObj, sal_Bool bAll )
+{
+ const SwVirtFlyDrawObj *pVirt = pObj->ISA(SwVirtFlyDrawObj) ?
+ (SwVirtFlyDrawObj*)pObj : 0;
+ if ( pVirt )
+ {
+ if ( bAll || !pVirt->GetFlyFrm()->IsFlyInCntFrm() )
+ return pVirt->GetFlyFrm()->GetAnchorFrm();
+ }
+ else
+ {
+ const SwDrawContact *pCont = (const SwDrawContact*)GetUserCall(pObj);
+ if ( pCont )
+ return pCont->GetAnchorFrm( pObj );
+ }
+ return 0;
+}
+
+/*************************************************************************
+|*
+|* SwDrawView::Ctor
+|*
+*************************************************************************/
+
+
+
+SwDrawView::SwDrawView( SwViewImp &rI, SdrModel *pMd, OutputDevice *pOutDev) :
+ FmFormView( (FmFormModel*)pMd, pOutDev ),
+ rImp( rI )
+{
+ SetPageVisible( sal_False );
+ SetBordVisible( sal_False );
+ SetGridVisible( sal_False );
+ SetHlplVisible( sal_False );
+ SetGlueVisible( sal_False );
+ SetFrameDragSingles( sal_True );
+ SetVirtualObjectBundling( sal_True );
+ SetSwapAsynchron( sal_True );
+
+ EnableExtendedKeyInputDispatcher( sal_False );
+ EnableExtendedMouseEventDispatcher( sal_False );
+ EnableExtendedCommandEventDispatcher( sal_False );
+
+ SetHitTolerancePixel( GetMarkHdlSizePixel()/2 );
+
+ SetPrintPreview( rI.GetShell()->IsPreView() );
+
+ // #i73602# Use default from the configuration
+ SetBufferedOverlayAllowed(getOptionsDrawinglayer().IsOverlayBuffer_Writer());
+
+ // #i74769#, #i75172# Use default from the configuration
+ SetBufferedOutputAllowed(getOptionsDrawinglayer().IsPaintBuffer_Writer());
+}
+
+// --> OD 2009-03-05 #i99665#
+sal_Bool SwDrawView::IsAntiAliasing() const
+{
+ return getOptionsDrawinglayer().IsAntiAliasing();
+}
+// <--
+
+//////////////////////////////////////////////////////////////////////////////
+
+SdrObject* impLocalHitCorrection(SdrObject* pRetval, const Point& rPnt, sal_uInt16 nTol, const SdrMarkList &rMrkList)
+{
+ if(!nTol)
+ {
+ // the old method forced back to outer bounds test when nTol == 0, so
+ // do not try to correct when nTol is not set (used from HelpContent)
+ }
+ else
+ {
+ // rebuild logic from former SwVirtFlyDrawObj::CheckSdrObjectHit. This is needed since
+ // the SdrObject-specific CheckHit implementations are now replaced with primitives and
+ // 'tricks' like in the old implementation (e.g. using a view from a model-data class to
+ // detect if object is selected) are no longer valid.
+ // The standard primitive hit-test for SwVirtFlyDrawObj now is the outer bound. The old
+ // implementation reduced this excluding the inner bound when the object was not selected.
+ SwVirtFlyDrawObj* pSwVirtFlyDrawObj = dynamic_cast< SwVirtFlyDrawObj* >(pRetval);
+
+ if(pSwVirtFlyDrawObj)
+ {
+ if(pSwVirtFlyDrawObj->GetFlyFrm()->Lower() && pSwVirtFlyDrawObj->GetFlyFrm()->Lower()->IsNoTxtFrm())
+ {
+ // the old method used IsNoTxtFrm (should be for SW's own OLE and
+ // graphic's) to accept hit only based on outer bounds; nothing to do
+ }
+ else
+ {
+ // check if the object is selected in this view
+ const sal_uInt32 nMarkCount(rMrkList.GetMarkCount());
+ bool bSelected(false);
+
+ for(sal_uInt32 a(0); !bSelected && a < nMarkCount; a++)
+ {
+ if(pSwVirtFlyDrawObj == rMrkList.GetMark(a)->GetMarkedSdrObj())
+ {
+ bSelected = true;
+ }
+ }
+
+ if(!bSelected)
+ {
+ // when not selected, the object is not hit when hit position is inside
+ // inner range. Get and shrink inner range
+ basegfx::B2DRange aInnerBound(pSwVirtFlyDrawObj->getInnerBound());
+
+ aInnerBound.grow(-1.0 * nTol);
+
+ if(aInnerBound.isInside(basegfx::B2DPoint(rPnt.X(), rPnt.Y())))
+ {
+ // exclude this hit
+ pRetval = 0;
+ }
+ }
+ }
+ }
+ }
+
+ return pRetval;
+}
+
+SdrObject* SwDrawView::CheckSingleSdrObjectHit(const Point& rPnt, sal_uInt16 nTol, SdrObject* pObj, SdrPageView* pPV, sal_uLong nOptions, const SetOfByte* pMVisLay) const
+{
+ // call parent
+ SdrObject* pRetval = FmFormView::CheckSingleSdrObjectHit(rPnt, nTol, pObj, pPV, nOptions, pMVisLay);
+
+ if(pRetval)
+ {
+ // overloaded to allow extra handling when picking SwVirtFlyDrawObj's
+ pRetval = impLocalHitCorrection(pRetval, rPnt, nTol, GetMarkedObjectList());
+ }
+
+ return pRetval;
+}
+
+/*************************************************************************
+|*
+|* SwDrawView::AddCustomHdl()
+|*
+|* Gets called every time the handles need to be build
+|*
+*************************************************************************/
+
+void SwDrawView::AddCustomHdl()
+{
+ const SdrMarkList &rMrkList = GetMarkedObjectList();
+
+ if(rMrkList.GetMarkCount() != 1 || !GetUserCall(rMrkList.GetMark( 0 )->GetMarkedSdrObj()))
+ return;
+
+ SdrObject *pObj = rMrkList.GetMark(0)->GetMarkedSdrObj();
+ // make code robust
+ SwFrmFmt* pFrmFmt( ::FindFrmFmt( pObj ) );
+ if ( !pFrmFmt )
+ {
+ OSL_FAIL( "<SwDrawView::AddCustomHdl()> - missing frame format!" );
+ return;
+ }
+ const SwFmtAnchor &rAnchor = pFrmFmt->GetAnchor();
+
+ if (FLY_AS_CHAR == rAnchor.GetAnchorId())
+ return;
+
+ const SwFrm* pAnch;
+ if(0 == (pAnch = CalcAnchor()))
+ return;
+
+ Point aPos(aAnchorPoint);
+
+ if ( FLY_AT_CHAR == rAnchor.GetAnchorId() )
+ {
+ // --> OD 2004-06-24 #i28701# - use last character rectangle saved at object
+ // in order to avoid a format of the anchor frame
+ SwAnchoredObject* pAnchoredObj = ::GetUserCall( pObj )->GetAnchoredObj( pObj );
+ SwRect aAutoPos = pAnchoredObj->GetLastCharRect();
+ if ( aAutoPos.Height() )
+ {
+ aPos = aAutoPos.Pos();
+ }
+ }
+
+ // add anchor handle:
+ //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin
+ aHdl.AddHdl( new SwSdrHdl( aPos, ( pAnch->IsVertical() && !pAnch->IsVertLR() ) ||
+ pAnch->IsRightToLeft() ) );
+}
+
+/*************************************************************************
+|*
+|* SwDrawView::GetMaxToTopObj(), _GetMaxToTopObj()
+|*
+*************************************************************************/
+
+
+SdrObject* SwDrawView::GetMaxToTopObj( SdrObject* pObj ) const
+{
+ if ( GetUserCall(pObj) )
+ {
+ const SwFrm *pAnch = ::lcl_FindAnchor( pObj, sal_False );
+ if ( pAnch )
+ {
+ //Das oberste Obj innerhalb des Ankers darf nicht ueberholt
+ //werden.
+ const SwFlyFrm *pFly = pAnch->FindFlyFrm();
+ if ( pFly )
+ {
+ const SwPageFrm *pPage = pFly->FindPageFrm();
+ if ( pPage->GetSortedObjs() )
+ {
+ sal_uInt32 nOrdNum = 0;
+ for ( sal_uInt16 i = 0; i < pPage->GetSortedObjs()->Count(); ++i )
+ {
+ const SdrObject *pO =
+ (*pPage->GetSortedObjs())[i]->GetDrawObj();
+
+ if ( pO->GetOrdNumDirect() > nOrdNum )
+ {
+ const SwFrm *pTmpAnch = ::lcl_FindAnchor( pO, sal_False );
+ if ( pFly->IsAnLower( pTmpAnch ) )
+ {
+ nOrdNum = pO->GetOrdNumDirect();
+ }
+ }
+ }
+ if ( nOrdNum )
+ {
+ SdrPage *pTmpPage = GetModel()->GetPage( 0 );
+ ++nOrdNum;
+ if ( nOrdNum < pTmpPage->GetObjCount() )
+ {
+ return pTmpPage->GetObj( nOrdNum );
+ }
+ }
+ }
+ }
+ }
+ }
+ return 0;
+}
+
+/*************************************************************************
+|*
+|* SwDrawView::GetMaxToBtmObj()
+|*
+*************************************************************************/
+
+
+SdrObject* SwDrawView::GetMaxToBtmObj(SdrObject* pObj) const
+{
+ if ( GetUserCall(pObj) )
+ {
+ const SwFrm *pAnch = ::lcl_FindAnchor( pObj, sal_False );
+ if ( pAnch )
+ {
+ //Der Fly des Ankers darf nicht "unterflogen" werden.
+ const SwFlyFrm *pFly = pAnch->FindFlyFrm();
+ if ( pFly )
+ {
+ SdrObject *pRet = (SdrObject*)pFly->GetVirtDrawObj();
+ return pRet != pObj ? pRet : 0;
+ }
+ }
+ }
+ return 0;
+}
+
+/*************************************************************************
+|*
+|* SwDrawView::ObjOrderChanged()
+|*
+*************************************************************************/
+
+inline sal_Bool lcl_IsChild( SdrObject *pParent, SdrObject *pChild )
+{
+ if ( pParent->ISA(SwVirtFlyDrawObj) )
+ {
+ const SwFrm *pAnch = lcl_FindAnchor( pChild, sal_False );
+ if ( pAnch && ((SwVirtFlyDrawObj*)pParent)->GetFlyFrm()->IsAnLower( pAnch ))
+ {
+ return sal_True;
+ }
+ }
+ return sal_False;
+}
+
+inline SdrObject *lcl_FindParent( SdrObject *pObj )
+{
+ const SwFrm *pAnch = lcl_FindAnchor( pObj, sal_False );
+ if ( pAnch && pAnch->IsInFly() )
+ return (SdrObject*)pAnch->FindFlyFrm()->GetVirtDrawObj();
+ return 0;
+}
+
+/** determine maximal order number for a 'child' object of given 'parent' object
+
+ @author OD
+*/
+sal_uInt32 SwDrawView::_GetMaxChildOrdNum( const SwFlyFrm& _rParentObj,
+ const SdrObject* _pExclChildObj ) const
+{
+ sal_uInt32 nMaxChildOrdNum = _rParentObj.GetDrawObj()->GetOrdNum();
+
+ const SdrPage* pDrawPage = _rParentObj.GetDrawObj()->GetPage();
+ OSL_ENSURE( pDrawPage,
+ "<SwDrawView::_GetMaxChildOrdNum(..) - missing drawing page at parent object - crash!" );
+
+ sal_uInt32 nObjCount = pDrawPage->GetObjCount();
+ for ( sal_uInt32 i = nObjCount-1; i > _rParentObj.GetDrawObj()->GetOrdNum() ; --i )
+ {
+ const SdrObject* pObj = pDrawPage->GetObj( i );
+
+ // Don't consider 'child' object <_pExclChildObj>
+ if ( pObj == _pExclChildObj )
+ {
+ continue;
+ }
+
+ if ( pObj->GetOrdNum() > nMaxChildOrdNum &&
+ _rParentObj.IsAnLower( lcl_FindAnchor( pObj, sal_True ) ) )
+ {
+ nMaxChildOrdNum = pObj->GetOrdNum();
+ break;
+ }
+ }
+
+ return nMaxChildOrdNum;
+}
+
+/** method to move 'repeated' objects of the given moved object to the
+ according level
+
+ @author OD
+*/
+void SwDrawView::_MoveRepeatedObjs( const SwAnchoredObject& _rMovedAnchoredObj,
+ const std::vector<SdrObject*>& _rMovedChildObjs ) const
+{
+ // determine 'repeated' objects of already moved object <_rMovedAnchoredObj>
+ std::list<SwAnchoredObject*> aAnchoredObjs;
+ {
+ const SwContact* pContact = ::GetUserCall( _rMovedAnchoredObj.GetDrawObj() );
+ OSL_ENSURE( pContact,
+ "SwDrawView::_MoveRepeatedObjs(..) - missing contact object -> crash." );
+ pContact->GetAnchoredObjs( aAnchoredObjs );
+ }
+
+ // check, if 'repeated' objects exists.
+ if ( aAnchoredObjs.size() > 1 )
+ {
+ SdrPage* pDrawPage = GetModel()->GetPage( 0 );
+
+ // move 'repeated' ones to the same order number as the already moved one.
+ sal_uInt32 nNewPos = _rMovedAnchoredObj.GetDrawObj()->GetOrdNum();
+ while ( !aAnchoredObjs.empty() )
+ {
+ SwAnchoredObject* pAnchoredObj = aAnchoredObjs.back();
+ if ( pAnchoredObj != &_rMovedAnchoredObj )
+ {
+ pDrawPage->SetObjectOrdNum( pAnchoredObj->GetDrawObj()->GetOrdNum(),
+ nNewPos );
+ pDrawPage->RecalcObjOrdNums();
+ // adjustments for accessibility API
+ if ( pAnchoredObj->ISA(SwFlyFrm) )
+ {
+ const SwFlyFrm *pTmpFlyFrm = static_cast<SwFlyFrm*>(pAnchoredObj);
+ rImp.DisposeAccessibleFrm( pTmpFlyFrm );
+ rImp.AddAccessibleFrm( pTmpFlyFrm );
+ }
+ else
+ {
+ rImp.DisposeAccessibleObj( pAnchoredObj->GetDrawObj() );
+ rImp.AddAccessibleObj( pAnchoredObj->GetDrawObj() );
+ }
+ }
+ aAnchoredObjs.pop_back();
+ }
+
+ // move 'repeated' ones of 'child' objects
+ for ( std::vector<SdrObject*>::const_iterator aObjIter = _rMovedChildObjs.begin();
+ aObjIter != _rMovedChildObjs.end(); ++aObjIter )
+ {
+ SdrObject* pChildObj = (*aObjIter);
+ {
+ const SwContact* pContact = ::GetUserCall( pChildObj );
+ OSL_ENSURE( pContact,
+ "SwDrawView::_MoveRepeatedObjs(..) - missing contact object -> crash." );
+ pContact->GetAnchoredObjs( aAnchoredObjs );
+ }
+ // move 'repeated' ones to the same order number as the already moved one.
+ const sal_uInt32 nTmpNewPos = pChildObj->GetOrdNum();
+ while ( !aAnchoredObjs.empty() )
+ {
+ SwAnchoredObject* pAnchoredObj = aAnchoredObjs.back();
+ if ( pAnchoredObj->GetDrawObj() != pChildObj )
+ {
+ pDrawPage->SetObjectOrdNum( pAnchoredObj->GetDrawObj()->GetOrdNum(),
+ nTmpNewPos );
+ pDrawPage->RecalcObjOrdNums();
+ // adjustments for accessibility API
+ if ( pAnchoredObj->ISA(SwFlyFrm) )
+ {
+ const SwFlyFrm *pTmpFlyFrm = static_cast<SwFlyFrm*>(pAnchoredObj);
+ rImp.DisposeAccessibleFrm( pTmpFlyFrm );
+ rImp.AddAccessibleFrm( pTmpFlyFrm );
+ }
+ else
+ {
+ rImp.DisposeAccessibleObj( pAnchoredObj->GetDrawObj() );
+ rImp.AddAccessibleObj( pAnchoredObj->GetDrawObj() );
+ }
+ }
+ aAnchoredObjs.pop_back();
+ }
+ }
+ }
+}
+
+// --> adjustment and re-factoring of method
+void SwDrawView::ObjOrderChanged( SdrObject* pObj, sal_uLong nOldPos,
+ sal_uLong nNewPos )
+{
+ // nothing to do for group members
+ if ( pObj->GetUpGroup() )
+ {
+ return;
+ }
+
+ // determine drawing page and assure that the order numbers are correct.
+ SdrPage* pDrawPage = GetModel()->GetPage( 0 );
+ if ( pDrawPage->IsObjOrdNumsDirty() )
+ pDrawPage->RecalcObjOrdNums();
+ const sal_uInt32 nObjCount = pDrawPage->GetObjCount();
+
+ SwAnchoredObject* pMovedAnchoredObj =
+ ::GetUserCall( pObj )->GetAnchoredObj( pObj );
+ const SwFlyFrm* pParentAnchoredObj =
+ pMovedAnchoredObj->GetAnchorFrm()->FindFlyFrm();
+
+ const bool bMovedForward = nOldPos < nNewPos;
+
+ // assure for a 'child' object, that it doesn't exceed the limits of its 'parent'
+ if ( pParentAnchoredObj )
+ {
+ if ( bMovedForward )
+ {
+ sal_uInt32 nMaxChildOrdNumWithoutMoved =
+ _GetMaxChildOrdNum( *pParentAnchoredObj, pMovedAnchoredObj->GetDrawObj() );
+ if ( nNewPos > nMaxChildOrdNumWithoutMoved+1 )
+ {
+ // set position to the top of the 'child' object group
+ pDrawPage->SetObjectOrdNum( nNewPos, nMaxChildOrdNumWithoutMoved+1 );
+ nNewPos = nMaxChildOrdNumWithoutMoved+1;
+ }
+ }
+ else
+ {
+ const sal_uInt32 nParentOrdNum = pParentAnchoredObj->GetDrawObj()->GetOrdNum();
+ if ( nNewPos < nParentOrdNum )
+ {
+ // set position to the bottom of the 'child' object group
+ pDrawPage->SetObjectOrdNum( nNewPos, nParentOrdNum );
+ nNewPos = nParentOrdNum;
+ }
+ }
+ if ( pDrawPage->IsObjOrdNumsDirty() )
+ pDrawPage->RecalcObjOrdNums();
+ }
+
+ // Assure, that object isn't positioned between 'repeated' ones
+ if ( ( bMovedForward && nNewPos < nObjCount - 1 ) ||
+ ( !bMovedForward && nNewPos > 0 ) )
+ {
+ const SdrObject* pTmpObj =
+ pDrawPage->GetObj( bMovedForward ? nNewPos - 1 : nNewPos + 1 );
+ if ( pTmpObj )
+ {
+ sal_uInt32 nTmpNewPos( nNewPos );
+ if ( bMovedForward )
+ {
+ // move before the top 'repeated' object
+ const sal_uInt32 nTmpMaxOrdNum =
+ ::GetUserCall( pTmpObj )->GetMaxOrdNum();
+ if ( nTmpMaxOrdNum > nNewPos )
+ nTmpNewPos = nTmpMaxOrdNum;
+ }
+ else
+ {
+ // move behind the bottom 'repeated' object
+ const sal_uInt32 nTmpMinOrdNum =
+ ::GetUserCall( pTmpObj )->GetMinOrdNum();
+ if ( nTmpMinOrdNum < nNewPos )
+ nTmpNewPos = nTmpMinOrdNum;
+ }
+ if ( nTmpNewPos != nNewPos )
+ {
+ pDrawPage->SetObjectOrdNum( nNewPos, nTmpNewPos );
+ nNewPos = nTmpNewPos;
+ pDrawPage->RecalcObjOrdNums();
+ }
+ }
+ }
+
+ // On move forward, assure that object is moved before its own childs.
+ // Only Writer fly frames can have childs.
+ if ( pMovedAnchoredObj->ISA(SwFlyFrm) &&
+ bMovedForward && nNewPos < nObjCount - 1 )
+ {
+ sal_uInt32 nMaxChildOrdNum =
+ _GetMaxChildOrdNum( *(static_cast<const SwFlyFrm*>(pMovedAnchoredObj)) );
+ if ( nNewPos < nMaxChildOrdNum )
+ {
+ // determine position before the object before its top 'child' object
+ const SdrObject* pTmpObj = pDrawPage->GetObj( nMaxChildOrdNum );
+ sal_uInt32 nTmpNewPos = ::GetUserCall( pTmpObj )->GetMaxOrdNum() + 1;
+ if ( nTmpNewPos >= nObjCount )
+ {
+ --nTmpNewPos;
+ }
+ // assure, that determined position isn't between 'repeated' objects
+ pTmpObj = pDrawPage->GetObj( nTmpNewPos );
+ nTmpNewPos = ::GetUserCall( pTmpObj )->GetMaxOrdNum();
+ // apply new position
+ pDrawPage->SetObjectOrdNum( nNewPos, nTmpNewPos );
+ nNewPos = nTmpNewPos;
+ pDrawPage->RecalcObjOrdNums();
+ }
+ }
+
+ // Assure, that object isn't positioned between nested objects
+ if ( ( bMovedForward && nNewPos < nObjCount - 1 ) ||
+ ( !bMovedForward && nNewPos > 0 ) )
+ {
+ sal_uInt32 nTmpNewPos( nNewPos );
+ const SwFrmFmt* pParentFrmFmt =
+ pParentAnchoredObj ? &(pParentAnchoredObj->GetFrmFmt()) : 0L;
+ const SdrObject* pTmpObj = pDrawPage->GetObj( nNewPos + 1 );
+ while ( pTmpObj )
+ {
+ // --> OD 2004-12-07 #i38563# - assure, that anchor frame exists.
+ // If object is anchored inside a invisible part of the document
+ // (e.g. page header, whose page style isn't applied, or hidden
+ // section), no anchor frame exists.
+ const SwFrm* pTmpAnchorFrm = lcl_FindAnchor( pTmpObj, sal_True );
+ const SwFlyFrm* pTmpParentObj = pTmpAnchorFrm
+ ? pTmpAnchorFrm->FindFlyFrm() : 0L;
+ // <--
+ if ( pTmpParentObj &&
+ &(pTmpParentObj->GetFrmFmt()) != pParentFrmFmt )
+ {
+ if ( bMovedForward )
+ {
+ nTmpNewPos = ::GetUserCall( pTmpObj )->GetMaxOrdNum();
+ pTmpObj = pDrawPage->GetObj( nTmpNewPos + 1 );
+ }
+ else
+ {
+ nTmpNewPos = ::GetUserCall( pTmpParentObj->GetDrawObj() )
+ ->GetMinOrdNum();
+ pTmpObj = pTmpParentObj->GetDrawObj();
+ }
+ }
+ else
+ break;
+ }
+ if ( nTmpNewPos != nNewPos )
+ {
+ pDrawPage->SetObjectOrdNum( nNewPos, nTmpNewPos );
+ nNewPos = nTmpNewPos;
+ pDrawPage->RecalcObjOrdNums();
+ }
+ }
+
+ // setup collection of moved 'child' objects to move its 'repeated' objects.
+ std::vector< SdrObject* > aMovedChildObjs;
+
+ // move 'childs' accordingly
+ if ( pMovedAnchoredObj->ISA(SwFlyFrm) )
+ {
+ const SwFlyFrm* pFlyFrm = static_cast<SwFlyFrm*>(pMovedAnchoredObj);
+
+ // adjustments for accessibility API
+ rImp.DisposeAccessibleFrm( pFlyFrm );
+ rImp.AddAccessibleFrm( pFlyFrm );
+
+ const sal_uInt32 nChildNewPos = bMovedForward ? nNewPos : nNewPos+1;
+ sal_uInt32 i = bMovedForward ? nOldPos : nObjCount-1;
+ do
+ {
+ SdrObject* pTmpObj = pDrawPage->GetObj( i );
+ if ( pTmpObj == pObj )
+ break;
+
+ // --> OD 2004-12-07 #i38563# - assure, that anchor frame exists.
+ // If object is anchored inside a invisible part of the document
+ // (e.g. page header, whose page style isn't applied, or hidden
+ // section), no anchor frame exists.
+ const SwFrm* pTmpAnchorFrm = lcl_FindAnchor( pTmpObj, sal_True );
+ const SwFlyFrm* pTmpParentObj = pTmpAnchorFrm
+ ? pTmpAnchorFrm->FindFlyFrm() : 0L;
+ // <--
+ if ( pTmpParentObj &&
+ ( ( pTmpParentObj == pFlyFrm ) ||
+ ( pFlyFrm->IsUpperOf( *pTmpParentObj ) ) ) )
+ {
+ // move child object.,
+ pDrawPage->SetObjectOrdNum( i, nChildNewPos );
+ pDrawPage->RecalcObjOrdNums();
+ // collect 'child' object
+ aMovedChildObjs.push_back( pTmpObj );
+ // adjustments for accessibility API
+ if ( pTmpObj->ISA(SwVirtFlyDrawObj) )
+ {
+ const SwFlyFrm *pTmpFlyFrm =
+ static_cast<SwVirtFlyDrawObj*>(pTmpObj)->GetFlyFrm();
+ rImp.DisposeAccessibleFrm( pTmpFlyFrm );
+ rImp.AddAccessibleFrm( pTmpFlyFrm );
+ }
+ else
+ {
+ rImp.DisposeAccessibleObj( pTmpObj );
+ rImp.AddAccessibleObj( pTmpObj );
+ }
+ }
+ else
+ {
+ // adjust loop counter
+ if ( bMovedForward )
+ ++i;
+ else if ( !bMovedForward && i > 0 )
+ --i;
+ }
+
+ } while ( ( bMovedForward && i < ( nObjCount - aMovedChildObjs.size() ) ) ||
+ ( !bMovedForward && i > ( nNewPos + aMovedChildObjs.size() ) ) );
+ }
+ else
+ {
+ // adjustments for accessibility API
+ rImp.DisposeAccessibleObj( pObj );
+ rImp.AddAccessibleObj( pObj );
+ }
+
+ _MoveRepeatedObjs( *pMovedAnchoredObj, aMovedChildObjs );
+}
+// <--
+
+/*************************************************************************
+|*
+|* SwDrawView::TakeDragLimit()
+|*
+*************************************************************************/
+
+
+sal_Bool SwDrawView::TakeDragLimit( SdrDragMode eMode,
+ Rectangle& rRect ) const
+{
+ const SdrMarkList &rMrkList = GetMarkedObjectList();
+ sal_Bool bRet = sal_False;
+ if( 1 == rMrkList.GetMarkCount() )
+ {
+ const SdrObject *pObj = rMrkList.GetMark( 0 )->GetMarkedSdrObj();
+ SwRect aRect;
+ if( ::CalcClipRect( pObj, aRect, eMode == SDRDRAG_MOVE ) )
+ {
+ rRect = aRect.SVRect();
+ bRet = sal_True;
+ }
+ }
+ return bRet;
+}
+
+/*************************************************************************
+|*
+|* SwDrawView::CalcAnchor()
+|*
+*************************************************************************/
+
+
+const SwFrm* SwDrawView::CalcAnchor()
+{
+ const SdrMarkList &rMrkList = GetMarkedObjectList();
+ if ( rMrkList.GetMarkCount() != 1 )
+ return NULL;
+
+ SdrObject* pObj = rMrkList.GetMark( 0 )->GetMarkedSdrObj();
+
+ //Fuer Absatzgebundene Objekte suchen, andernfalls einfach nur
+ //der aktuelle Anker. Nur suchen wenn wir gerade draggen.
+ const SwFrm* pAnch;
+ Rectangle aMyRect;
+ const sal_Bool bFly = pObj->ISA(SwVirtFlyDrawObj);
+ if ( bFly )
+ {
+ pAnch = ((SwVirtFlyDrawObj*)pObj)->GetFlyFrm()->GetAnchorFrm();
+ aMyRect = ((SwVirtFlyDrawObj*)pObj)->GetFlyFrm()->Frm().SVRect();
+ }
+ else
+ {
+ SwDrawContact *pC = (SwDrawContact*)GetUserCall(pObj);
+ // determine correct anchor position for 'virtual' drawing objects.
+ // #i26791#
+ pAnch = pC->GetAnchorFrm( pObj );
+ if( !pAnch )
+ {
+ pC->ConnectToLayout();
+ // determine correct anchor position for 'virtual' drawing objects.
+ // #i26791#
+ pAnch = pC->GetAnchorFrm( pObj );
+ }
+ aMyRect = pObj->GetSnapRect();
+ }
+
+ //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin
+ const sal_Bool bTopRight = pAnch && ( ( pAnch->IsVertical() &&
+ !pAnch->IsVertLR() ) ||
+ pAnch->IsRightToLeft() );
+ const Point aMyPt = bTopRight ? aMyRect.TopRight() : aMyRect.TopLeft();
+
+ Point aPt;
+ if ( IsAction() )
+ {
+ if ( !TakeDragObjAnchorPos( aPt, bTopRight ) )
+ return NULL;
+ }
+ else
+ {
+ Rectangle aRect = pObj->GetSnapRect();
+ aPt = bTopRight ? aRect.TopRight() : aRect.TopLeft();
+ }
+
+ if ( aPt != aMyPt )
+ {
+ if ( pAnch->IsCntntFrm() )
+ {
+ // allow drawing objects in header/footer,
+ // but exclude control objects.
+ bool bBodyOnly = CheckControlLayer( pObj );
+ pAnch = ::FindAnchor( (SwCntntFrm*)pAnch, aPt, bBodyOnly );
+ }
+ else if ( !bFly )
+ {
+ const SwRect aRect( aPt.X(), aPt.Y(), 1, 1 );
+
+ SwDrawContact* pContact = (SwDrawContact*)GetUserCall(pObj);
+ if ( pContact->GetAnchorFrm( pObj ) &&
+ pContact->GetAnchorFrm( pObj )->IsPageFrm() )
+ pAnch = pContact->GetPageFrm();
+ else
+ pAnch = pContact->FindPage( aRect );
+ }
+ }
+ if( pAnch && !pAnch->IsProtected() )
+ aAnchorPoint = pAnch->GetFrmAnchorPos( ::HasWrap( pObj ) );
+ else
+ pAnch = 0;
+ return pAnch;
+}
+
+/*************************************************************************
+|*
+|* SwDrawView::ShowDragXor(), HideDragXor()
+|*
+*************************************************************************/
+
+
+void SwDrawView::ShowDragAnchor()
+{
+ SdrHdl* pHdl = aHdl.GetHdl(HDL_ANCHOR);
+ if ( ! pHdl )
+ pHdl = aHdl.GetHdl(HDL_ANCHOR_TR);
+
+ if(pHdl)
+ {
+ CalcAnchor();
+ pHdl->SetPos(aAnchorPoint);
+ }
+}
+
+/*************************************************************************
+|*
+|* SwDrawView::MarkListHasChanged()
+|*
+*************************************************************************/
+
+
+void SwDrawView::MarkListHasChanged()
+{
+ Imp().GetShell()->DrawSelChanged();
+ FmFormView::MarkListHasChanged();
+}
+
+// #i7672#
+void SwDrawView::ModelHasChanged()
+{
+ // The ModelHasChanged() call in DrawingLayer also updates
+ // a eventually active text edit view (OutlinerView). This also leads
+ // to newly setting the background color for that edit view. Thus,
+ // this method rescues the current background color if a OutlinerView
+ // exists and re-establishes it then. To be more safe, the OutlinerView
+ // will be fetched again (maybe textedit has ended).
+ OutlinerView* pView = GetTextEditOutlinerView();
+ Color aBackColor;
+ sal_Bool bColorWasSaved(sal_False);
+
+ if(pView)
+ {
+ aBackColor = pView->GetBackgroundColor();
+ bColorWasSaved = sal_True;
+ }
+
+ // call parent
+ FmFormView::ModelHasChanged();
+
+ if(bColorWasSaved)
+ {
+ pView = GetTextEditOutlinerView();
+
+ if(pView)
+ {
+ pView->SetBackgroundColor(aBackColor);
+ }
+ }
+}
+
+void SwDrawView::MakeVisible( const Rectangle &rRect, Window & )
+{
+ OSL_ENSURE( rImp.GetShell()->GetWin(), "MakeVisible, unknown Window");
+ rImp.GetShell()->MakeVisible( SwRect( rRect ) );
+}
+
+void SwDrawView::CheckPossibilities()
+{
+ FmFormView::CheckPossibilities();
+
+ //Zusaetzlich zu den bestehenden Flags der Objekte selbst, die von der
+ //DrawingEngine ausgewertet werden, koennen weitere Umstaende zu einem
+ //Schutz fuehren.
+ //Objekte, die in Rahmen verankert sind, muessen genau dann geschuetzt
+ //sein, wenn der Inhalt des Rahmens geschuetzt ist.
+ //OLE-Objekte konnen selbst einen Resize-Schutz wuenschen (StarMath)
+
+ const SdrMarkList &rMrkList = GetMarkedObjectList();
+ sal_Bool bProtect = sal_False,
+ bSzProtect = sal_False;
+ for ( sal_uInt16 i = 0; !bProtect && i < rMrkList.GetMarkCount(); ++i )
+ {
+ const SdrObject *pObj = rMrkList.GetMark( i )->GetMarkedSdrObj();
+ const SwFrm *pFrm = NULL;
+ if ( pObj->ISA(SwVirtFlyDrawObj) )
+ {
+ const SwFlyFrm *pFly = ((SwVirtFlyDrawObj*)pObj)->GetFlyFrm();
+ if ( pFly )
+ {
+ pFrm = pFly->GetAnchorFrm();
+ if ( pFly->Lower() && pFly->Lower()->IsNoTxtFrm() )
+ {
+ SwOLENode *pNd = ((SwCntntFrm*)pFly->Lower())->GetNode()->GetOLENode();
+ if ( pNd )
+ {
+ uno::Reference < embed::XEmbeddedObject > xObj = pNd->GetOLEObj().GetOleRef();
+ if ( xObj.is() )
+ {
+ // --> improvement for the future, when more
+ // than one Writer fly frame can be selected.
+
+ // TODO/LATER: retrieve Aspect - from where?!
+ bSzProtect |= ( embed::EmbedMisc::EMBED_NEVERRESIZE & xObj->getStatus( embed::Aspects::MSOLE_CONTENT ) ) ? sal_True : sal_False;
+
+ // <--
+
+ // #i972: protect position if it is a Math object anchored 'as char' and baseline alignment is activated
+ SwDoc* pDoc = Imp().GetShell()->GetDoc();
+ const bool bProtectMathPos = SotExchange::IsMath( xObj->getClassID() )
+ && FLY_AS_CHAR == pFly->GetFmt()->GetAnchor().GetAnchorId()
+ && pDoc->get( IDocumentSettingAccess::MATH_BASELINE_ALIGNMENT );
+ if (bProtectMathPos)
+ bMoveProtect = true;
+ }
+ }
+ }
+ }
+ }
+ else
+ {
+ SwDrawContact *pC = (SwDrawContact*)GetUserCall(pObj);
+ if ( pC )
+ pFrm = pC->GetAnchorFrm( pObj );
+ }
+ if ( pFrm )
+ bProtect = pFrm->IsProtected(); //Rahmen, Bereiche usw.
+ {
+ SwFrmFmt* pFrmFmt( ::FindFrmFmt( const_cast<SdrObject*>(pObj) ) );
+ if ( !pFrmFmt )
+ {
+ OSL_FAIL( "<SwDrawView::CheckPossibilities()> - missing frame format" );
+ bProtect = sal_True;
+ }
+ else if ((FLY_AS_CHAR == pFrmFmt->GetAnchor().GetAnchorId()) &&
+ rMrkList.GetMarkCount() > 1 )
+ {
+ bProtect = sal_True;
+ }
+ }
+ }
+ bMoveProtect |= bProtect;
+ bResizeProtect |= bProtect | bSzProtect;
+}
+
+/** replace marked <SwDrawVirtObj>-objects by its reference object for delete
+ marked objects.
+
+ @author OD
+*/
+void SwDrawView::ReplaceMarkedDrawVirtObjs( SdrMarkView& _rMarkView )
+{
+ SdrPageView* pDrawPageView = _rMarkView.GetSdrPageView();
+ const SdrMarkList& rMarkList = _rMarkView.GetMarkedObjectList();
+
+ if( rMarkList.GetMarkCount() )
+ {
+ // collect marked objects in a local data structure
+ std::vector<SdrObject*> aMarkedObjs;
+ for( sal_uInt32 i = 0; i < rMarkList.GetMarkCount(); ++i )
+ {
+ SdrObject* pMarkedObj = rMarkList.GetMark( i )->GetMarkedSdrObj();
+ aMarkedObjs.push_back( pMarkedObj );
+ }
+ // unmark all objects
+ _rMarkView.UnmarkAllObj();
+ // re-mark objects, but for marked <SwDrawVirtObj>-objects marked its
+ // reference object.
+ while ( !aMarkedObjs.empty() )
+ {
+ SdrObject* pMarkObj = aMarkedObjs.back();
+ if ( pMarkObj->ISA(SwDrawVirtObj) )
+ {
+ SdrObject* pRefObj = &(static_cast<SwDrawVirtObj*>(pMarkObj)->ReferencedObj());
+ if ( !_rMarkView.IsObjMarked( pRefObj ) )
+ {
+ _rMarkView.MarkObj( pRefObj, pDrawPageView );
+ }
+ }
+ else
+ {
+ _rMarkView.MarkObj( pMarkObj, pDrawPageView );
+ }
+
+ aMarkedObjs.pop_back();
+ }
+ // sort marked list in order to assure consistent state in drawing layer
+ _rMarkView.SortMarkedObjects();
+ }
+}
+
+void SwDrawView::DeleteMarked()
+{
+ SwDoc* pDoc = Imp().GetShell()->GetDoc();
+ SwRootFrm *pTmpRoot = pDoc->GetCurrentLayout();//swmod 080317
+ if ( pTmpRoot )
+ pTmpRoot->StartAllAction();
+ pDoc->GetIDocumentUndoRedo().StartUndo(UNDO_EMPTY, NULL);
+ // replace marked <SwDrawVirtObj>-objects by its reference objects.
+ {
+ SdrPageView* pDrawPageView = rImp.GetPageView();
+ if ( pDrawPageView )
+ {
+ SdrMarkView* pMarkView = PTR_CAST( SdrMarkView, &(pDrawPageView->GetView()) );
+ if ( pMarkView )
+ {
+ ReplaceMarkedDrawVirtObjs( *pMarkView );
+ }
+ }
+ }
+ if ( pDoc->DeleteSelection( *this ) )
+ {
+ FmFormView::DeleteMarked();
+ ::FrameNotify( Imp().GetShell(), FLY_DRAG_END );
+ }
+ pDoc->GetIDocumentUndoRedo().EndUndo(UNDO_EMPTY, NULL);
+ if( pTmpRoot )
+ pTmpRoot->EndAllAction(); //swmod 080218
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/edit/acorrect.cxx b/sw/source/core/edit/acorrect.cxx
new file mode 100644
index 000000000000..a9ab99f2ee4b
--- /dev/null
+++ b/sw/source/core/edit/acorrect.cxx
@@ -0,0 +1,545 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+
+#define _STD_VAR_ARRAYS
+#include <hintids.hxx>
+
+#include <svx/svxids.hrc>
+#include <editeng/langitem.hxx>
+#include <fmtinfmt.hxx>
+#include <txtatr.hxx>
+#include <txtinet.hxx>
+#include <editsh.hxx>
+#include <doc.hxx>
+#include <pam.hxx>
+#include <ndtxt.hxx>
+#include <acorrect.hxx>
+#include <shellio.hxx>
+#include <swundo.hxx>
+#include <viscrs.hxx>
+
+#include <editeng/acorrcfg.hxx>
+
+using namespace ::com::sun::star;
+
+
+class _PaMIntoCrsrShellRing
+{
+ SwCrsrShell& rSh;
+ SwPaM &rDelPam, &rCrsr;
+ Ring *pPrevDelPam, *pPrevCrsr;
+
+ void RemoveFromRing( SwPaM& rPam, Ring* pPrev );
+public:
+ _PaMIntoCrsrShellRing( SwCrsrShell& rSh, SwPaM& rCrsr, SwPaM& rPam );
+ ~_PaMIntoCrsrShellRing();
+};
+
+_PaMIntoCrsrShellRing::_PaMIntoCrsrShellRing( SwCrsrShell& rCSh,
+ SwPaM& rShCrsr, SwPaM& rPam )
+ : rSh( rCSh ), rDelPam( rPam ), rCrsr( rShCrsr )
+{
+ SwPaM* pShCrsr = rSh._GetCrsr();
+
+ pPrevDelPam = rDelPam.GetPrev();
+ pPrevCrsr = rCrsr.GetPrev();
+
+ rDelPam.MoveRingTo( pShCrsr );
+ rCrsr.MoveRingTo( pShCrsr );
+}
+_PaMIntoCrsrShellRing::~_PaMIntoCrsrShellRing()
+{
+ // und den Pam wieder herausnehmen:
+ RemoveFromRing( rDelPam, pPrevDelPam );
+ RemoveFromRing( rCrsr, pPrevCrsr );
+}
+void _PaMIntoCrsrShellRing::RemoveFromRing( SwPaM& rPam, Ring* pPrev )
+{
+ Ring *p, *pNext = (Ring*)&rPam;
+ do {
+ p = pNext;
+ pNext = p->GetNext();
+ p->MoveTo( &rPam );
+ } while( p != pPrev );
+}
+
+
+SwAutoCorrDoc::SwAutoCorrDoc( SwEditShell& rEditShell, SwPaM& rPam,
+ sal_Unicode cIns )
+ : rEditSh( rEditShell ), rCrsr( rPam ), pIdx( 0 )
+ , m_nEndUndoCounter(0)
+ , bUndoIdInitialized( cIns ? false : true )
+{
+}
+
+
+SwAutoCorrDoc::~SwAutoCorrDoc()
+{
+ for (int i = 0; i < m_nEndUndoCounter; ++i)
+ {
+ rEditSh.EndUndo();
+ }
+ delete pIdx;
+}
+
+void SwAutoCorrDoc::DeleteSel( SwPaM& rDelPam )
+{
+ SwDoc* pDoc = rEditSh.GetDoc();
+ if( pDoc->IsAutoFmtRedline() )
+ {
+ // damit der DelPam auch verschoben wird, in den Shell-Cursr-Ring
+ // mit aufnehmen !!
+ _PaMIntoCrsrShellRing aTmp( rEditSh, rCrsr, rDelPam );
+ pDoc->DeleteAndJoin( rDelPam );
+ }
+ else
+ {
+ pDoc->DeleteRange( rDelPam );
+ }
+}
+
+sal_Bool SwAutoCorrDoc::Delete( xub_StrLen nStt, xub_StrLen nEnd )
+{
+ const SwNodeIndex& rNd = rCrsr.GetPoint()->nNode;
+ SwPaM aSel( rNd, nStt, rNd, nEnd );
+ DeleteSel( aSel );
+
+ if( bUndoIdInitialized )
+ bUndoIdInitialized = true;
+ return sal_True;
+}
+
+
+sal_Bool SwAutoCorrDoc::Insert( xub_StrLen nPos, const String& rTxt )
+{
+ SwPaM aPam( rCrsr.GetPoint()->nNode.GetNode(), nPos );
+ rEditSh.GetDoc()->InsertString( aPam, rTxt );
+ if( !bUndoIdInitialized )
+ {
+ bUndoIdInitialized = true;
+ if( 1 == rTxt.Len() )
+ {
+ rEditSh.StartUndo( UNDO_AUTOCORRECT );
+ ++m_nEndUndoCounter;
+ }
+ }
+ return sal_True;
+}
+
+
+sal_Bool SwAutoCorrDoc::Replace( xub_StrLen nPos, const String& rTxt )
+{
+ return ReplaceRange( nPos, rTxt.Len(), rTxt );
+}
+sal_Bool SwAutoCorrDoc::ReplaceRange( xub_StrLen nPos, xub_StrLen nSourceLength, const String& rTxt )
+{
+ SwPaM* pPam = &rCrsr;
+ if( pPam->GetPoint()->nContent.GetIndex() != nPos )
+ {
+ pPam = new SwPaM( *rCrsr.GetPoint() );
+ pPam->GetPoint()->nContent = nPos;
+ }
+
+ SwTxtNode * const pNd = pPam->GetNode()->GetTxtNode();
+ if ( !pNd )
+ {
+ return sal_False;
+ }
+
+ // text attributes with dummy characters must not be replaced!
+ bool bDoReplace = true;
+ xub_StrLen const nLen = rTxt.Len();
+ for ( xub_StrLen n = 0; n < nLen; ++n )
+ {
+ sal_Unicode const Char = pNd->GetTxt().GetChar( n + nPos );
+ if ( ( CH_TXTATR_BREAKWORD == Char || CH_TXTATR_INWORD == Char )
+ && pNd->GetTxtAttrForCharAt( n + nPos ) )
+ {
+ bDoReplace = false;
+ break;
+ }
+ }
+
+ if ( bDoReplace )
+ {
+ SwDoc* pDoc = rEditSh.GetDoc();
+
+ if( pDoc->IsAutoFmtRedline() )
+ {
+ if( nPos == pNd->GetTxt().Len() ) // am Ende erfolgt ein Insert
+ {
+ pDoc->InsertString( *pPam, rTxt );
+ }
+ else
+ {
+ _PaMIntoCrsrShellRing aTmp( rEditSh, rCrsr, *pPam );
+
+ pPam->SetMark();
+ pPam->GetPoint()->nContent = Min( pNd->GetTxt().Len(),
+ xub_StrLen( nPos + nSourceLength ));
+ pDoc->ReplaceRange( *pPam, rTxt, false );
+ pPam->Exchange();
+ pPam->DeleteMark();
+ }
+ }
+ else
+ {
+ if( nSourceLength != rTxt.Len() )
+ {
+ pPam->SetMark();
+ pPam->GetPoint()->nContent = Min( pNd->GetTxt().Len(),
+ xub_StrLen( nPos + nSourceLength ));
+ pDoc->ReplaceRange( *pPam, rTxt, false );
+ pPam->Exchange();
+ pPam->DeleteMark();
+ }
+ else
+ pDoc->Overwrite( *pPam, rTxt );
+ }
+
+// pDoc->SetRedlineMode_intern( eOld );
+ if( bUndoIdInitialized )
+ {
+ bUndoIdInitialized = true;
+ if( 1 == rTxt.Len() )
+ {
+ rEditSh.StartUndo( UNDO_AUTOCORRECT );
+ ++m_nEndUndoCounter;
+ }
+ }
+ }
+
+ if( pPam != &rCrsr )
+ delete pPam;
+
+ return sal_True;
+}
+
+
+
+sal_Bool SwAutoCorrDoc::SetAttr( xub_StrLen nStt, xub_StrLen nEnd, sal_uInt16 nSlotId,
+ SfxPoolItem& rItem )
+{
+ const SwNodeIndex& rNd = rCrsr.GetPoint()->nNode;
+ SwPaM aPam( rNd, nStt, rNd, nEnd );
+
+ SfxItemPool& rPool = rEditSh.GetDoc()->GetAttrPool();
+ sal_uInt16 nWhich = rPool.GetWhich( nSlotId, sal_False );
+ if( nWhich )
+ {
+ rItem.SetWhich( nWhich );
+
+ SfxItemSet aSet( rPool, aCharFmtSetRange );
+ SetAllScriptItem( aSet, rItem );
+
+ rEditSh.GetDoc()->SetFmtItemByAutoFmt( aPam, aSet );
+
+ if( bUndoIdInitialized )
+ bUndoIdInitialized = true;
+ }
+ return 0 != nWhich;
+}
+
+
+
+sal_Bool SwAutoCorrDoc::SetINetAttr( xub_StrLen nStt, xub_StrLen nEnd, const String& rURL )
+{
+ const SwNodeIndex& rNd = rCrsr.GetPoint()->nNode;
+ SwPaM aPam( rNd, nStt, rNd, nEnd );
+
+ SfxItemSet aSet( rEditSh.GetDoc()->GetAttrPool(),
+ RES_TXTATR_INETFMT, RES_TXTATR_INETFMT );
+ aSet.Put( SwFmtINetFmt( rURL, aEmptyStr ));
+ rEditSh.GetDoc()->SetFmtItemByAutoFmt( aPam, aSet );
+ if( bUndoIdInitialized )
+ bUndoIdInitialized = true;
+ return sal_True;
+}
+
+ // returne den Text eines vorherigen Absatzes.
+ // Dieser darf nicht leer sein!
+ // Gibt es diesen nicht oder gibt es davor nur Leere, dann returne 0
+ // Das Flag gibt an:
+ // sal_True: den, vor der normalen Einfuegeposition (sal_True)
+ // sal_False: den, in den das korrigierte Wort eingfuegt wurde.
+ // (Muss nicht der gleiche Absatz sein!!!!)
+const String* SwAutoCorrDoc::GetPrevPara( sal_Bool bAtNormalPos )
+{
+ const String* pStr = 0;
+
+ if( bAtNormalPos || !pIdx )
+ pIdx = new SwNodeIndex( rCrsr.GetPoint()->nNode, -1 );
+ else
+ (*pIdx)--;
+
+ SwTxtNode* pTNd = pIdx->GetNode().GetTxtNode();
+ while( pTNd && !pTNd->GetTxt().Len() )
+ {
+ (*pIdx)--;
+ pTNd = pIdx->GetNode().GetTxtNode();
+ }
+ if( pTNd && 0 == pTNd->GetAttrOutlineLevel() )//#outline level,zhaojianwei
+ pStr = &pTNd->GetTxt();
+
+ if( bUndoIdInitialized )
+ bUndoIdInitialized = true;
+ return pStr;
+}
+
+
+sal_Bool SwAutoCorrDoc::ChgAutoCorrWord( xub_StrLen & rSttPos, xub_StrLen nEndPos,
+ SvxAutoCorrect& rACorrect,
+ const String** ppPara )
+{
+ if( bUndoIdInitialized )
+ bUndoIdInitialized = true;
+
+ // Absatz-Anfang oder ein Blank gefunden, suche nach dem Wort
+ // Kuerzel im Auto
+ SwTxtNode* pTxtNd = rCrsr.GetNode()->GetTxtNode();
+ OSL_ENSURE( pTxtNd, "wo ist denn der TextNode?" );
+
+ sal_Bool bRet = sal_False;
+ if( nEndPos == rSttPos )
+ return bRet;
+
+ LanguageType eLang = GetLanguage(nEndPos, sal_False);
+ if(LANGUAGE_SYSTEM == eLang)
+ eLang = (LanguageType)GetAppLanguage();
+
+ //JP 22.04.99: Bug 63883 - Sonderbehandlung fuer Punkte.
+ sal_Bool bLastCharIsPoint = nEndPos < pTxtNd->GetTxt().Len() &&
+ '.' == pTxtNd->GetTxt().GetChar( nEndPos );
+
+ const SvxAutocorrWord* pFnd = rACorrect.SearchWordsInList(
+ pTxtNd->GetTxt(), rSttPos, nEndPos, *this, eLang );
+ SwDoc* pDoc = rEditSh.GetDoc();
+ if( pFnd )
+ {
+ const SwNodeIndex& rNd = rCrsr.GetPoint()->nNode;
+ SwPaM aPam( rNd, rSttPos, rNd, nEndPos );
+
+ if( pFnd->IsTextOnly() )
+ {
+ //JP 22.04.99: Bug 63883 - Sonderbehandlung fuer Punkte.
+ if( !bLastCharIsPoint || !pFnd->GetLong().Len() ||
+ '.' != pFnd->GetLong().GetChar( pFnd->GetLong().Len() - 1 ) )
+ {
+ // replace the selection
+ pDoc->ReplaceRange( aPam, pFnd->GetLong(), false);
+ bRet = sal_True;
+ }
+ }
+ else
+ {
+ SwTextBlocks aTBlks( rACorrect.GetAutoCorrFileName( eLang, sal_False, sal_True ));
+ sal_uInt16 nPos = aTBlks.GetIndex( pFnd->GetShort() );
+ if( USHRT_MAX != nPos && aTBlks.BeginGetDoc( nPos ) )
+ {
+ DeleteSel( aPam );
+ pDoc->DontExpandFmt( *aPam.GetPoint() );
+
+ if( ppPara )
+ {
+ OSL_ENSURE( !pIdx, "wer hat seinen Index nicht geloescht?" );
+ pIdx = new SwNodeIndex( rCrsr.GetPoint()->nNode, -1 );
+ }
+
+ //
+ SwDoc* pAutoDoc = aTBlks.GetDoc();
+ SwNodeIndex aSttIdx( pAutoDoc->GetNodes().GetEndOfExtras(), 1 );
+ SwCntntNode* pCntntNd = pAutoDoc->GetNodes().GoNext( &aSttIdx );
+ SwPaM aCpyPam( aSttIdx );
+
+ const SwTableNode* pTblNd = pCntntNd->FindTableNode();
+ if( pTblNd )
+ {
+ aCpyPam.GetPoint()->nContent.Assign( 0, 0 );
+ aCpyPam.GetPoint()->nNode = *pTblNd;
+ }
+ aCpyPam.SetMark();
+
+ // dann bis zum Ende vom Nodes Array
+ aCpyPam.GetPoint()->nNode.Assign( pAutoDoc->GetNodes().GetEndOfContent(), -1 );
+ pCntntNd = aCpyPam.GetCntntNode();
+ aCpyPam.GetPoint()->nContent.Assign( pCntntNd, pCntntNd->Len() );
+
+ SwDontExpandItem aExpItem;
+ aExpItem.SaveDontExpandItems( *aPam.GetPoint() );
+
+ pAutoDoc->CopyRange( aCpyPam, *aPam.GetPoint(), false );
+
+ aExpItem.RestoreDontExpandItems( *aPam.GetPoint() );
+
+ if( ppPara )
+ {
+ (*pIdx)++;
+ pTxtNd = pIdx->GetNode().GetTxtNode();
+ }
+ bRet = sal_True;
+ }
+ aTBlks.EndGetDoc();
+ }
+ }
+
+ if( bRet && ppPara && pTxtNd )
+ *ppPara = &pTxtNd->GetTxt();
+
+ return bRet;
+}
+
+
+ // wird nach dem austauschen der Zeichen von den Funktionen
+ // - FnCptlSttWrd
+ // - FnCptlSttSntnc
+ // gerufen. Dann koennen die Worte ggfs. in die Ausnahmelisten
+ // aufgenommen werden.
+void SwAutoCorrDoc::SaveCpltSttWord( sal_uLong nFlag, xub_StrLen nPos,
+ const String& rExceptWord,
+ sal_Unicode cChar )
+{
+ sal_uLong nNode = pIdx ? pIdx->GetIndex() : rCrsr.GetPoint()->nNode.GetIndex();
+ LanguageType eLang = GetLanguage(nPos, sal_False);
+ rEditSh.GetDoc()->SetAutoCorrExceptWord( new SwAutoCorrExceptWord( nFlag,
+ nNode, nPos, rExceptWord, cChar, eLang ));
+}
+
+LanguageType SwAutoCorrDoc::GetLanguage( xub_StrLen nPos, sal_Bool bPrevPara ) const
+{
+ LanguageType eRet = LANGUAGE_SYSTEM;
+
+ SwTxtNode* pNd = (( bPrevPara && pIdx )
+ ? *pIdx
+ : rCrsr.GetPoint()->nNode ).GetNode().GetTxtNode();
+
+ if( pNd )
+ eRet = pNd->GetLang( nPos, 0 );
+ if(LANGUAGE_SYSTEM == eRet)
+ eRet = (LanguageType)GetAppLanguage();
+ return eRet;
+}
+
+void SwAutoCorrExceptWord::CheckChar( const SwPosition& rPos, sal_Unicode cChr )
+{
+ // nur testen ob es eine Verbesserung ist. Wenn ja, dann das Wort
+ // in die Ausnahmeliste aufnehmen.
+ if( cChar == cChr && rPos.nNode.GetIndex() == nNode &&
+ rPos.nContent.GetIndex() == nCntnt )
+ {
+ // die akt. Autokorrektur besorgen:
+ SvxAutoCorrect* pACorr = SvxAutoCorrCfg::Get()->GetAutoCorrect();
+
+ // dann in die Liste aufnehmen:
+ if( CptlSttWrd & nFlags )
+ pACorr->AddWrtSttException( sWord, eLanguage );
+ else if( CptlSttSntnc & nFlags )
+ pACorr->AddCplSttException( sWord, eLanguage );
+ }
+}
+
+
+sal_Bool SwAutoCorrExceptWord::CheckDelChar( const SwPosition& rPos )
+{
+ sal_Bool bRet = sal_False;
+ if( !bDeleted && rPos.nNode.GetIndex() == nNode &&
+ rPos.nContent.GetIndex() == nCntnt )
+ bDeleted = bRet = sal_True;
+ return bRet;
+}
+
+SwDontExpandItem::~SwDontExpandItem()
+{
+ delete pDontExpItems;
+}
+
+void SwDontExpandItem::SaveDontExpandItems( const SwPosition& rPos )
+{
+ const SwTxtNode* pTxtNd = rPos.nNode.GetNode().GetTxtNode();
+ if( pTxtNd )
+ {
+ pDontExpItems = new SfxItemSet( ((SwDoc*)pTxtNd->GetDoc())->GetAttrPool(),
+ aCharFmtSetRange );
+ xub_StrLen n = rPos.nContent.GetIndex();
+ if( !pTxtNd->GetAttr( *pDontExpItems, n, n,
+ n != pTxtNd->GetTxt().Len() ))
+ delete pDontExpItems, pDontExpItems = 0;
+ }
+}
+
+void SwDontExpandItem::RestoreDontExpandItems( const SwPosition& rPos )
+{
+ SwTxtNode* pTxtNd = rPos.nNode.GetNode().GetTxtNode();
+ if( pTxtNd )
+ {
+ xub_StrLen nStart = rPos.nContent.GetIndex();
+ if( nStart == pTxtNd->GetTxt().Len() )
+ pTxtNd->FmtToTxtAttr( pTxtNd );
+
+ if( pTxtNd->GetpSwpHints() && pTxtNd->GetpSwpHints()->Count() )
+ {
+ const sal_uInt16 nSize = pTxtNd->GetpSwpHints()->Count();
+ sal_uInt16 n;
+ xub_StrLen nAttrStart;
+ const xub_StrLen* pAttrEnd;
+
+ for( n = 0; n < nSize; ++n )
+ {
+ SwTxtAttr* pHt = pTxtNd->GetpSwpHints()->GetTextHint( n );
+ nAttrStart = *pHt->GetStart();
+ if( nAttrStart > nStart ) // ueber den Bereich hinaus
+ break;
+
+ if( 0 != ( pAttrEnd = pHt->GetEnd() ) &&
+ ( ( nAttrStart < nStart &&
+ ( pHt->DontExpand() ? nStart < *pAttrEnd
+ : nStart <= *pAttrEnd )) ||
+ ( nStart == nAttrStart &&
+ ( nAttrStart == *pAttrEnd || !nStart ))) )
+ {
+ const SfxPoolItem* pItem;
+ if( !pDontExpItems || SFX_ITEM_SET != pDontExpItems->
+ GetItemState( pHt->Which(), sal_False, &pItem ) ||
+ *pItem != pHt->GetAttr() )
+ {
+ // das Attribut war vorher nicht in dieser Form im Absatz
+ // gesetzt, also kann es nur durchs einfuegen/kopieren erzeugt
+ // worden sein. Damit ist es ein Kandiadat fuers DontExpand
+ pHt->SetDontExpand( sal_True );
+ }
+ }
+ }
+ }
+ }
+}
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/edit/autofmt.cxx b/sw/source/core/edit/autofmt.cxx
new file mode 100644
index 000000000000..14df0bd9749e
--- /dev/null
+++ b/sw/source/core/edit/autofmt.cxx
@@ -0,0 +1,2754 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+#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> // for the UndoId's
+#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;
+
+// Number of num-/bullet-paragraph templates. MAXLEVEL will soon be raised
+// to x, but not the number of templates. (Artifact from <= 4.0)
+const sal_uInt16 cnNumBullColls = 4;
+
+class SwAutoFormat
+{
+ SvxSwAutoFmtFlags aFlags;
+ SwPaM aDelPam; // a Pam that can be used
+ SwNodeIndex aNdIdx; // the index on the current TextNode
+ SwNodeIndex aEndNdIdx; // index on the end of the area
+
+ SwEditShell* pEditShell;
+ SwDoc* pDoc;
+ SwTxtNode* pAktTxtNd; // the current TextNode
+ SwTxtFrm* pAktTxtFrm; // frame of the current TextNode
+ CharClass* pCharClass; // Character classification
+ sal_uLong nEndNdIdx; // for the percentage-display
+ 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 methods
+ 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;
+ // get the FORMATED 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 );
+ // delete in the node start and/or end
+ void DeleteAktPara( sal_Bool bStart = sal_True, sal_Bool nEnd = sal_True );
+ void DelEmptyLine( sal_Bool bTstNextPara = sal_True );
+ // when using multiline paragraphs delete the "left" and/or
+ // "right" margins
+ void DelMoreLinesBlanks( sal_Bool bWithLineBreaks = sal_False );
+ // delete the previous paragraph
+ void DelPrevPara();
+ // execute AutoCorrect on current TextNode
+ 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 );
+ }
+
+ // is a dot at the end ??
+ 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
+{
+ // get the Frame
+ const SwCntntFrm *pFrm = rTxtNd.getLayoutFrm( pEditShell->GetLayout() );
+ OSL_ENSURE( 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();
+
+ // not a TextNode ->
+ // TableNode : skip table
+ // NoTxtNode : skip nodes
+ // EndNode : at the end, terminate
+ 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 )
+{
+ // Is there something bound to the paragraph in the paragraph
+ // like borders, DrawObjects, ...
+ 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;
+
+ // -, +, * separated by blank ??
+ if( 2 < nLen && IsSpace( rTxt.GetChar( nBlnks + 1 ) ) )
+ {
+ if( StrChr( pBulletChar, rTxt.GetChar( nBlnks ) ) )
+ return sal_True;
+ // Should there be a symbol font at the position?
+ 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
+{
+ // Search more that 5 blanks/tabs in the string.
+ String sTmp( rNd.GetTxt() );
+ DelTrailingBlanks( DelLeadingBlanks( sTmp ));
+ const sal_Unicode* pTmp = sTmp.GetBuffer();
+ while( *pTmp )
+ {
+ if( IsSpace( *pTmp ) )
+ {
+ if( IsSpace( *++pTmp )) // 2 spaces after each other
+ {
+ 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 )
+ // test 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 )
+ {
+ 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;
+
+ editeng::SvxBorderLine aLine;
+ switch( eState )
+ {
+ case 1: // einfach, 0,05 pt
+ aLine.SetStyle( editeng::SOLID );
+ aLine.SetWidth( DEF_LINE_WIDTH_0 );
+ break;
+ case 2: // einfach, 1,0 pt
+ aLine.SetStyle( editeng::SOLID );
+ aLine.SetWidth( DEF_LINE_WIDTH_1 );
+ break;
+ case 3: // doppelt, 1,1 pt
+ aLine.SetStyle( editeng::DOUBLE );
+ aLine.SetWidth( DEF_LINE_WIDTH_0 );
+ break;
+ case 4: // doppelt, 4,5 pt
+ aLine.SetStyle( editeng::THICKTHIN_SMALLGAP );
+ aLine.SetWidth( DEF_LINE_WIDTH_1 );
+ break;
+ case 5: // doppelt, 6,0 pt
+ aLine.SetStyle( editeng::THINTHICK_SMALLGAP );
+ aLine.SetWidth( DEF_LINE_WIDTH_2 );
+ break;
+ case 6: // doppelt, 9,0 pt
+ aLine.SetStyle( editeng::DOUBLE );
+ aLine.SetWidth( DEF_LINE_WIDTH_2 );
+ 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!
+#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 ) ))
+ 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 )))
+ 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();
+ 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
+ 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.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 );
+
+ // 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;
+ default:
+ 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 )
+{
+ OSL_ENSURE( (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;
+
+ }
+ 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 ) )
+ {
+ {
+ 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 ))
+
+ )
+ {
+
+ // 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;
+ }
+ 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(), sal_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;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/edit/edatmisc.cxx b/sw/source/core/edit/edatmisc.cxx
new file mode 100644
index 000000000000..bb5d650484b2
--- /dev/null
+++ b/sw/source/core/edit/edatmisc.cxx
@@ -0,0 +1,181 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+#include <editsh.hxx>
+#include <doc.hxx> // fuer aNodes
+#include <IDocumentUndoRedo.hxx>
+#include <pam.hxx> // fuer SwPaM
+#include <edimp.hxx> // fuer MACROS
+#include <swundo.hxx> // fuer die UndoIds
+#include <ndtxt.hxx> // fuer Get-/ChgFmt Set-/GetAttrXXX
+
+
+
+/*************************************
+ * harte Formatierung (Attribute)
+ *************************************/
+
+
+void SwEditShell::ResetAttr( const SvUShortsSort* pAttrs )
+{
+ SET_CURR_SHELL( this );
+ StartAllAction();
+ sal_Bool bUndoGroup = GetCrsr()->GetNext() != GetCrsr();
+ if( bUndoGroup )
+ {
+ GetDoc()->GetIDocumentUndoRedo().StartUndo(UNDO_RESETATTR, NULL);
+ }
+
+ FOREACHPAM_START(this)
+
+ GetDoc()->ResetAttrs(*PCURCRSR, sal_True, pAttrs);
+ FOREACHPAM_END()
+
+ if( bUndoGroup )
+ {
+ GetDoc()->GetIDocumentUndoRedo().EndUndo(UNDO_RESETATTR, NULL);
+ }
+ CallChgLnk();
+ EndAllAction();
+}
+
+
+
+void SwEditShell::GCAttr()
+{
+ FOREACHPAM_START(this)
+ if ( !PCURCRSR->HasMark() )
+ {
+ SwTxtNode *const pTxtNode =
+ PCURCRSR->GetPoint()->nNode.GetNode().GetTxtNode();
+ if (pTxtNode)
+ {
+ pTxtNode->GCAttr();
+ }
+ }
+ else
+ {
+ const SwNodeIndex& rEnd = PCURCRSR->End()->nNode;
+ SwNodeIndex aIdx( PCURCRSR->Start()->nNode );
+ SwNode* pNd = &aIdx.GetNode();
+ do {
+ if( pNd->IsTxtNode() )
+ ((SwTxtNode*)pNd)->GCAttr();
+ }
+ while( 0 != ( pNd = GetDoc()->GetNodes().GoNext( &aIdx )) &&
+ aIdx <= rEnd );
+ }
+ FOREACHPAM_END()
+}
+
+// Setze das Attribut als neues default Attribut im Dokument.
+
+
+void SwEditShell::SetDefault( const SfxPoolItem& rFmtHint )
+{
+ // 7502: Action-Klammerung
+ StartAllAction();
+ GetDoc()->SetDefault( rFmtHint );
+ EndAllAction();
+}
+
+// Erfrage das Default Attribut in diesem Dokument.
+
+const SfxPoolItem& SwEditShell::GetDefault( sal_uInt16 nFmtHint ) const
+{
+ return GetDoc()->GetDefault( nFmtHint );
+
+}
+
+
+void SwEditShell::SetAttr( const SfxPoolItem& rHint, sal_uInt16 nFlags )
+{
+ SET_CURR_SHELL( this );
+ StartAllAction();
+ SwPaM* pCrsr = GetCrsr();
+ if( pCrsr->GetNext() != pCrsr ) // Ring von Cursorn
+ {
+ sal_Bool bIsTblMode = IsTableMode();
+ GetDoc()->GetIDocumentUndoRedo().StartUndo(UNDO_INSATTR, NULL);
+
+ FOREACHPAM_START(this)
+ if( PCURCRSR->HasMark() && ( bIsTblMode ||
+ *PCURCRSR->GetPoint() != *PCURCRSR->GetMark() ))
+ {
+ GetDoc()->InsertPoolItem(*PCURCRSR, rHint, nFlags );
+ }
+ FOREACHPAM_END()
+
+ GetDoc()->GetIDocumentUndoRedo().EndUndo(UNDO_INSATTR, NULL);
+ }
+ else
+ {
+ if( !HasSelection() )
+ UpdateAttr();
+ GetDoc()->InsertPoolItem( *pCrsr, rHint, nFlags );
+ }
+ EndAllAction();
+}
+
+
+void SwEditShell::SetAttr( const SfxItemSet& rSet, sal_uInt16 nFlags )
+{
+ SET_CURR_SHELL( this );
+ StartAllAction();
+ SwPaM* pCrsr = GetCrsr();
+ if( pCrsr->GetNext() != pCrsr ) // Ring von Cursorn
+ {
+ sal_Bool bIsTblMode = IsTableMode();
+ GetDoc()->GetIDocumentUndoRedo().StartUndo(UNDO_INSATTR, NULL);
+
+ FOREACHPAM_START(this)
+ if( PCURCRSR->HasMark() && ( bIsTblMode ||
+ *PCURCRSR->GetPoint() != *PCURCRSR->GetMark() ))
+ {
+ GetDoc()->InsertItemSet(*PCURCRSR, rSet, nFlags );
+ }
+ FOREACHPAM_END()
+
+ GetDoc()->GetIDocumentUndoRedo().EndUndo(UNDO_INSATTR, NULL);
+ }
+ else
+ {
+ if( !HasSelection() )
+ UpdateAttr();
+ GetDoc()->InsertItemSet( *pCrsr, rSet, nFlags );
+ }
+ EndAllAction();
+}
+
+
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/edit/edattr.cxx b/sw/source/core/edit/edattr.cxx
new file mode 100644
index 000000000000..a67663445a85
--- /dev/null
+++ b/sw/source/core/edit/edattr.cxx
@@ -0,0 +1,630 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+
+#include <hintids.hxx>
+
+#include <editeng/tstpitem.hxx>
+#include <editeng/lrspitem.hxx>
+#include <editeng/scripttypeitem.hxx>
+#include <com/sun/star/i18n/ScriptType.hdl>
+#include <txatbase.hxx>
+#include <txtftn.hxx>
+#include <fmtftn.hxx>
+#include <editsh.hxx>
+#include <edimp.hxx> // fuer MACROS
+#include <doc.hxx>
+#include <swundo.hxx> // fuer UNDO-Ids
+#include <ndtxt.hxx>
+#include <ftnidx.hxx>
+#include <expfld.hxx>
+#include <rootfrm.hxx>
+#include <cntfrm.hxx>
+#include <breakit.hxx>
+#include <txtfld.hxx>
+#include <fmtfld.hxx>
+#include <crsskip.hxx>
+#include <txtfrm.hxx> // SwTxtFrm
+#include <scriptinfo.hxx>
+#include <svl/ctloptions.hxx>
+#include <charfmt.hxx> // #i27615#
+#include <numrule.hxx>
+
+
+/*************************************
+ * harte Formatierung (Attribute)
+ *************************************/
+
+// wenn Selektion groesser Max Nodes oder mehr als Max Selektionen
+// => keine Attribute
+const sal_uInt16& getMaxLookup()
+{
+ static const sal_uInt16 nMaxLookup = 1000;
+ return nMaxLookup;
+}
+
+sal_Bool SwEditShell::GetCurAttr( SfxItemSet& rSet,
+ const bool bMergeIndentValuesOfNumRule ) const
+{
+ if( GetCrsrCnt() > getMaxLookup() )
+ {
+ rSet.InvalidateAllItems();
+ return sal_False;
+ }
+
+ SfxItemSet aSet( *rSet.GetPool(), rSet.GetRanges() );
+ SfxItemSet *pSet = &rSet;
+
+ FOREACHPAM_START(this)
+
+ // #i27615# if the cursor is in front of the numbering label
+ // the attributes to get are those from the numbering format.
+ if (PCURCRSR->IsInFrontOfLabel())
+ {
+ SwTxtNode * pTxtNd =
+ PCURCRSR->GetPoint()->nNode.GetNode().GetTxtNode();
+
+ if (pTxtNd)
+ {
+ SwNumRule * pNumRule = pTxtNd->GetNumRule();
+
+ if (pNumRule)
+ {
+ const String & aCharFmtName =
+ pNumRule->Get(static_cast<sal_uInt16>(pTxtNd->GetActualListLevel())).GetCharFmtName();
+ SwCharFmt * pCharFmt =
+ GetDoc()->FindCharFmtByName(aCharFmtName);
+
+ if (pCharFmt)
+ rSet.Put(pCharFmt->GetAttrSet());
+ }
+ }
+
+ continue;
+ }
+
+ sal_uLong nSttNd = PCURCRSR->GetMark()->nNode.GetIndex(),
+ nEndNd = PCURCRSR->GetPoint()->nNode.GetIndex();
+ xub_StrLen nSttCnt = PCURCRSR->GetMark()->nContent.GetIndex(),
+ nEndCnt = PCURCRSR->GetPoint()->nContent.GetIndex();
+
+ if( nSttNd > nEndNd || ( nSttNd == nEndNd && nSttCnt > nEndCnt ))
+ {
+ sal_uLong nTmp = nSttNd; nSttNd = nEndNd; nEndNd = nTmp;
+ nTmp = nSttCnt; nSttCnt = nEndCnt; nEndCnt = (xub_StrLen)nTmp;
+ }
+
+ if( nEndNd - nSttNd >= getMaxLookup() )
+ {
+ rSet.ClearItem();
+ rSet.InvalidateAllItems();
+ return sal_False;
+ }
+
+ // beim 1.Node traegt der Node die Werte in den GetSet ein (Initial)
+ // alle weiteren Nodes werden zum GetSet zu gemergt
+ for( sal_uLong n = nSttNd; n <= nEndNd; ++n )
+ {
+ SwNode* pNd = GetDoc()->GetNodes()[ n ];
+ switch( pNd->GetNodeType() )
+ {
+ case ND_TEXTNODE:
+ {
+ xub_StrLen nStt = n == nSttNd ? nSttCnt : 0,
+ nEnd = n == nEndNd ? nEndCnt
+ : ((SwTxtNode*)pNd)->GetTxt().Len();
+
+ ((SwTxtNode*)pNd)->GetAttr( *pSet, nStt, nEnd,
+ sal_False, sal_True,
+ bMergeIndentValuesOfNumRule );
+ }
+ break;
+ case ND_GRFNODE:
+ case ND_OLENODE:
+ ((SwCntntNode*)pNd)->GetAttr( *pSet );
+ break;
+
+ default:
+ pNd = 0;
+ }
+
+ if( pNd )
+ {
+ if( pSet != &rSet )
+ rSet.MergeValues( aSet );
+
+ if( aSet.Count() )
+ aSet.ClearItem();
+ }
+ pSet = &aSet;
+ }
+
+ FOREACHPAM_END()
+
+ return sal_True;
+}
+
+SwTxtFmtColl* SwEditShell::GetCurTxtFmtColl() const
+{
+ SwTxtFmtColl *pFmt = 0;
+
+ if ( GetCrsrCnt() > getMaxLookup() )
+ return 0;
+
+ FOREACHPAM_START(this)
+
+ sal_uLong nSttNd = PCURCRSR->GetMark()->nNode.GetIndex(),
+ nEndNd = PCURCRSR->GetPoint()->nNode.GetIndex();
+ xub_StrLen nSttCnt = PCURCRSR->GetMark()->nContent.GetIndex(),
+ nEndCnt = PCURCRSR->GetPoint()->nContent.GetIndex();
+
+ if( nSttNd > nEndNd || ( nSttNd == nEndNd && nSttCnt > nEndCnt ))
+ {
+ sal_uLong nTmp = nSttNd; nSttNd = nEndNd; nEndNd = nTmp;
+ nTmp = nSttCnt; nSttCnt = nEndCnt; nEndCnt = (xub_StrLen)nTmp;
+ }
+
+ if( nEndNd - nSttNd >= getMaxLookup() )
+ {
+ pFmt = 0;
+ break;
+ }
+
+ for( sal_uLong n = nSttNd; n <= nEndNd; ++n )
+ {
+ SwNode* pNd = GetDoc()->GetNodes()[ n ];
+ if( pNd->IsTxtNode() )
+ {
+ if( !pFmt )
+ pFmt = ((SwTxtNode*)pNd)->GetTxtColl();
+ else if( pFmt == ((SwTxtNode*)pNd)->GetTxtColl() ) // ???
+ break;
+ }
+ }
+
+ FOREACHPAM_END()
+ return pFmt;
+}
+
+
+
+sal_Bool SwEditShell::GetCurFtn( SwFmtFtn* pFillFtn )
+{
+ // der Cursor muss auf dem akt. Fussnoten-Anker stehen:
+ SwPaM* pCrsr = GetCrsr();
+ SwTxtNode* pTxtNd = pCrsr->GetNode()->GetTxtNode();
+ if( !pTxtNd )
+ return sal_False;
+
+ SwTxtAttr *const pFtn = pTxtNd->GetTxtAttrForCharAt(
+ pCrsr->GetPoint()->nContent.GetIndex(), RES_TXTATR_FTN);
+ if( pFtn && pFillFtn )
+ {
+ // Daten vom Attribut uebertragen
+ const SwFmtFtn &rFtn = ((SwTxtFtn*)pFtn)->GetFtn();
+ pFillFtn->SetNumber( rFtn );
+ pFillFtn->SetEndNote( rFtn.IsEndNote() );
+ }
+ return 0 != pFtn;
+}
+
+
+bool SwEditShell::SetCurFtn( const SwFmtFtn& rFillFtn )
+{
+ bool bChgd = false;
+ StartAllAction();
+
+ SwPaM* pCrsr = GetCrsr(), *pFirst = pCrsr;
+ do {
+ bChgd |= pDoc->SetCurFtn( *pCrsr, rFillFtn.GetNumStr(),
+ rFillFtn.GetNumber(),
+ rFillFtn.IsEndNote() );
+
+ } while( pFirst != ( pCrsr = (SwPaM*)pCrsr->GetNext() ));
+
+ EndAllAction();
+ return bChgd;
+}
+
+
+bool SwEditShell::HasFtns( bool bEndNotes ) const
+{
+ const SwFtnIdxs &rIdxs = pDoc->GetFtnIdxs();
+ for ( sal_uInt16 i = 0; i < rIdxs.Count(); ++i )
+ {
+ const SwFmtFtn &rFtn = rIdxs[i]->GetFtn();
+ if ( bEndNotes == rFtn.IsEndNote() )
+ return sal_True;
+ }
+ return sal_False;
+}
+
+
+ // gebe Liste aller Fussnoten und deren Anfangstexte
+sal_uInt16 SwEditShell::GetSeqFtnList( SwSeqFldList& rList, bool bEndNotes )
+{
+ if( rList.Count() )
+ rList.Remove( 0, rList.Count() );
+
+ sal_uInt16 n, nFtnCnt = pDoc->GetFtnIdxs().Count();
+ SwTxtFtn* pTxtFtn;
+ for( n = 0; n < nFtnCnt; ++n )
+ {
+ pTxtFtn = pDoc->GetFtnIdxs()[ n ];
+ const SwFmtFtn& rFtn = pTxtFtn->GetFtn();
+ if ( rFtn.IsEndNote() != bEndNotes )
+ continue;
+
+ SwNodeIndex* pIdx = pTxtFtn->GetStartNode();
+ if( pIdx )
+ {
+ SwNodeIndex aIdx( *pIdx, 1 );
+ SwTxtNode* pTxtNd = aIdx.GetNode().GetTxtNode();
+ if( !pTxtNd )
+ pTxtNd = (SwTxtNode*)pDoc->GetNodes().GoNext( &aIdx );
+
+ if( pTxtNd )
+ {
+ String sTxt( rFtn.GetViewNumStr( *pDoc ));
+ if( sTxt.Len() )
+ sTxt += ' ';
+ sTxt += pTxtNd->GetExpandTxt( 0, USHRT_MAX );
+
+ _SeqFldLstElem* pNew = new _SeqFldLstElem( sTxt,
+ pTxtFtn->GetSeqRefNo() );
+ while( rList.InsertSort( pNew ) )
+ pNew->sDlgEntry += ' ';
+ }
+ }
+ }
+
+ return rList.Count();
+}
+
+
+// linken Rand ueber Objectleiste einstellen (aenhlich dem Stufen von
+// Numerierungen)
+sal_Bool SwEditShell::IsMoveLeftMargin( sal_Bool bRight, sal_Bool bModulus ) const
+{
+ sal_Bool bRet = sal_True;
+
+ const SvxTabStopItem& rTabItem = (SvxTabStopItem&)GetDoc()->
+ GetDefault( RES_PARATR_TABSTOP );
+ sal_uInt16 nDefDist = static_cast<sal_uInt16>(rTabItem.Count() ? rTabItem[0].GetTabPos() : 1134);
+ if( !nDefDist )
+ return sal_False;
+
+ FOREACHPAM_START(this)
+
+ sal_uLong nSttNd = PCURCRSR->GetMark()->nNode.GetIndex(),
+ nEndNd = PCURCRSR->GetPoint()->nNode.GetIndex();
+
+ if( nSttNd > nEndNd )
+ {
+ sal_uLong nTmp = nSttNd; nSttNd = nEndNd; nEndNd = nTmp;
+ }
+
+ SwCntntNode* pCNd;
+ for( sal_uLong n = nSttNd; bRet && n <= nEndNd; ++n )
+ if( 0 != ( pCNd = GetDoc()->GetNodes()[ n ]->GetTxtNode() ))
+ {
+ const SvxLRSpaceItem& rLS = (SvxLRSpaceItem&)
+ pCNd->GetAttr( RES_LR_SPACE );
+ if( bRight )
+ {
+ long nNext = rLS.GetTxtLeft() + nDefDist;
+ if( bModulus )
+ nNext = ( nNext / nDefDist ) * nDefDist;
+ SwFrm* pFrm = pCNd->getLayoutFrm( GetLayout() );
+ if ( pFrm )
+ {
+ const sal_uInt16 nFrmWidth = static_cast<sal_uInt16>( pFrm->IsVertical() ?
+ pFrm->Frm().Height() :
+ pFrm->Frm().Width() );
+ bRet = nFrmWidth > ( nNext + MM50 );
+ }
+ else
+ bRet = sal_False;
+ }
+ }
+
+ if( !bRet )
+ break;
+
+ FOREACHPAM_END()
+ return bRet;
+}
+
+void SwEditShell::MoveLeftMargin( sal_Bool bRight, sal_Bool bModulus )
+{
+ StartAllAction();
+ StartUndo( UNDO_START );
+
+ SwPaM* pCrsr = GetCrsr();
+ if( pCrsr->GetNext() != pCrsr ) // Mehrfachselektion ?
+ {
+ SwPamRanges aRangeArr( *pCrsr );
+ SwPaM aPam( *pCrsr->GetPoint() );
+ for( sal_uInt16 n = 0; n < aRangeArr.Count(); ++n )
+ GetDoc()->MoveLeftMargin( aRangeArr.SetPam( n, aPam ),
+ bRight, bModulus );
+ }
+ else
+ GetDoc()->MoveLeftMargin( *pCrsr, bRight, bModulus );
+
+ EndUndo( UNDO_END );
+ EndAllAction();
+}
+
+
+inline sal_uInt16 lcl_SetScriptFlags( sal_uInt16 nType )
+{
+ sal_uInt16 nRet;
+ switch( nType )
+ {
+ case ::com::sun::star::i18n::ScriptType::LATIN: nRet = SCRIPTTYPE_LATIN; break;
+ case ::com::sun::star::i18n::ScriptType::ASIAN: nRet = SCRIPTTYPE_ASIAN; break;
+ case ::com::sun::star::i18n::ScriptType::COMPLEX: nRet = SCRIPTTYPE_COMPLEX; break;
+ default: nRet = 0;
+ }
+ return nRet;
+}
+
+sal_Bool lcl_IsNoEndTxtAttrAtPos( const SwTxtNode& rTNd, xub_StrLen nPos,
+ sal_uInt16 &rScrpt, sal_Bool bInSelection, sal_Bool bNum )
+{
+ sal_Bool bRet = sal_False;
+ const String& rTxt = rTNd.GetTxt();
+ String sExp;
+
+ // consider numbering
+ if ( bNum )
+ {
+ bRet = sal_False;
+
+ if ( rTNd.IsInList() )
+ {
+ OSL_ENSURE( rTNd.GetNumRule(),
+ "<lcl_IsNoEndTxtAttrAtPos(..)> - no list style found at text node. Serious defect -> please inform OD." );
+ const SwNumRule* pNumRule = rTNd.GetNumRule();
+ const SwNumFmt &rNumFmt = pNumRule->Get( static_cast<sal_uInt16>(rTNd.GetActualListLevel()) );
+ if( SVX_NUM_BITMAP != rNumFmt.GetNumberingType() )
+ {
+ if ( SVX_NUM_CHAR_SPECIAL == rNumFmt.GetNumberingType() )
+ sExp = rNumFmt.GetBulletChar();
+ else
+ sExp = rTNd.GetNumString();
+ }
+ }
+ }
+
+ // and fields
+ if ( CH_TXTATR_BREAKWORD == rTxt.GetChar( nPos ) )
+ {
+ const SwTxtAttr* const pAttr = rTNd.GetTxtAttrForCharAt( nPos );
+ if (pAttr)
+ {
+ bRet = sal_True; // all other than fields can be
+ // defined as weak-script ?
+ if ( RES_TXTATR_FIELD == pAttr->Which() )
+ {
+ const SwField* const pFld = pAttr->GetFld().GetFld();
+ if (pFld)
+ {
+ sExp += pFld->ExpandField(true);
+ }
+ }
+ }
+ }
+
+ xub_StrLen nEnd = sExp.Len();
+ if ( nEnd )
+ {
+ xub_StrLen n;
+ if( bInSelection )
+ {
+ sal_uInt16 nScript;
+ for( n = 0; n < nEnd; n = (xub_StrLen)
+ pBreakIt->GetBreakIter()->endOfScript( sExp, n, nScript ))
+ {
+ nScript = pBreakIt->GetBreakIter()->getScriptType( sExp, n );
+ rScrpt |= lcl_SetScriptFlags( nScript );
+ }
+ }
+ else
+ rScrpt |= lcl_SetScriptFlags( pBreakIt->GetBreakIter()->
+ getScriptType( sExp, nEnd-1 ));
+ }
+
+ return bRet;
+}
+
+
+// returns the scripttpye of the selection
+sal_uInt16 SwEditShell::GetScriptType() const
+{
+ sal_uInt16 nRet = 0;
+
+ {
+ FOREACHPAM_START(this)
+
+ const SwPosition *pStt = PCURCRSR->Start(),
+ *pEnd = pStt == PCURCRSR->GetMark()
+ ? PCURCRSR->GetPoint()
+ : PCURCRSR->GetMark();
+ if( pStt == pEnd || *pStt == *pEnd )
+ {
+ const SwTxtNode* pTNd = pStt->nNode.GetNode().GetTxtNode();
+ if( pTNd )
+ {
+ // try to get SwScriptInfo
+ const SwScriptInfo* pScriptInfo = SwScriptInfo::GetScriptInfo( *pTNd );
+
+ xub_StrLen nPos = pStt->nContent.GetIndex();
+ //Task 90448: we need the scripttype of the previous
+ // position, if no selection exist!
+ if( nPos )
+ {
+ SwIndex aIdx( pStt->nContent );
+ if( pTNd->GoPrevious( &aIdx, CRSR_SKIP_CHARS ) )
+ nPos = aIdx.GetIndex();
+ }
+
+ sal_uInt16 nScript;
+
+ if ( pTNd->GetTxt().Len() )
+ {
+ nScript = pScriptInfo ?
+ pScriptInfo->ScriptType( nPos ) :
+ pBreakIt->GetBreakIter()->getScriptType( pTNd->GetTxt(), nPos );
+ }
+ else
+ nScript = GetI18NScriptTypeOfLanguage( (sal_uInt16)GetAppLanguage() );
+
+ if( !lcl_IsNoEndTxtAttrAtPos( *pTNd, nPos, nRet, sal_False, sal_False ))
+ nRet |= lcl_SetScriptFlags( nScript );
+ }
+ }
+ else if ( pBreakIt->GetBreakIter().is() )
+ {
+ sal_uLong nEndIdx = pEnd->nNode.GetIndex();
+ SwNodeIndex aIdx( pStt->nNode );
+ for( ; aIdx.GetIndex() <= nEndIdx; aIdx++ )
+ if( aIdx.GetNode().IsTxtNode() )
+ {
+ const SwTxtNode* pTNd = aIdx.GetNode().GetTxtNode();
+ const String& rTxt = pTNd->GetTxt();
+
+ // try to get SwScriptInfo
+ const SwScriptInfo* pScriptInfo = SwScriptInfo::GetScriptInfo( *pTNd );
+
+ xub_StrLen nChg = aIdx == pStt->nNode
+ ? pStt->nContent.GetIndex()
+ : 0,
+ nEndPos = aIdx == nEndIdx
+ ? pEnd->nContent.GetIndex()
+ : rTxt.Len();
+
+ OSL_ENSURE( nEndPos <= rTxt.Len(), "Index outside the range - endless loop!" );
+ if( nEndPos > rTxt.Len() )
+ nEndPos = rTxt.Len();
+
+ sal_uInt16 nScript;
+ while( nChg < nEndPos )
+ {
+ nScript = pScriptInfo ?
+ pScriptInfo->ScriptType( nChg ) :
+ pBreakIt->GetBreakIter()->getScriptType(
+ rTxt, nChg );
+
+ if( !lcl_IsNoEndTxtAttrAtPos( *pTNd, nChg, nRet, sal_True,
+ 0 == nChg && rTxt.Len() == nEndPos ) )
+ nRet |= lcl_SetScriptFlags( nScript );
+
+ if( (SCRIPTTYPE_LATIN | SCRIPTTYPE_ASIAN |
+ SCRIPTTYPE_COMPLEX) == nRet )
+ break;
+
+ xub_StrLen nFldPos = nChg+1;
+
+ nChg = pScriptInfo ?
+ pScriptInfo->NextScriptChg( nChg ) :
+ (xub_StrLen)pBreakIt->GetBreakIter()->endOfScript(
+ rTxt, nChg, nScript );
+
+ nFldPos = rTxt.Search(
+ CH_TXTATR_BREAKWORD, nFldPos );
+ if( nFldPos < nChg )
+ nChg = nFldPos;
+ }
+ if( (SCRIPTTYPE_LATIN | SCRIPTTYPE_ASIAN |
+ SCRIPTTYPE_COMPLEX) == nRet )
+ break;
+ }
+ }
+ if( (SCRIPTTYPE_LATIN | SCRIPTTYPE_ASIAN |
+ SCRIPTTYPE_COMPLEX) == nRet )
+ break;
+
+ FOREACHPAM_END()
+ }
+ if( !nRet )
+ nRet = SvtLanguageOptions::GetScriptTypeOfLanguage( LANGUAGE_SYSTEM );
+ return nRet;
+}
+
+
+sal_uInt16 SwEditShell::GetCurLang() const
+{
+ const SwPaM* pCrsr = GetCrsr();
+ const SwPosition& rPos = *pCrsr->GetPoint();
+ const SwTxtNode* pTNd = rPos.nNode.GetNode().GetTxtNode();
+ sal_uInt16 nLang;
+ if( pTNd )
+ {
+ //JP 24.9.2001: if exist no selection, then get the language before
+ // the current character!
+ xub_StrLen nPos = rPos.nContent.GetIndex();
+ if( nPos && !pCrsr->HasMark() )
+ --nPos;
+ nLang = pTNd->GetLang( nPos );
+ }
+ else
+ nLang = LANGUAGE_DONTKNOW;
+ return nLang;
+}
+
+sal_uInt16 SwEditShell::GetScalingOfSelectedText() const
+{
+ const SwPaM* pCrsr = GetCrsr();
+ const SwPosition* pStt = pCrsr->Start();
+ const SwTxtNode* pTNd = pStt->nNode.GetNode().GetTxtNode();
+ OSL_ENSURE( pTNd, "no textnode available" );
+
+ sal_uInt16 nScaleWidth;
+ if( pTNd )
+ {
+ xub_StrLen nStt = pStt->nContent.GetIndex(), nEnd;
+ const SwPosition* pEnd = pStt == pCrsr->GetPoint()
+ ? pCrsr->GetMark()
+ : pCrsr->GetPoint();
+ if( pStt->nNode == pEnd->nNode )
+ nEnd = pEnd->nContent.GetIndex();
+ else
+ nEnd = pTNd->GetTxt().Len();
+ nScaleWidth = pTNd->GetScalingOfSelectedText( nStt, nEnd );
+ }
+ else
+ nScaleWidth = 100; // default are no scaling -> 100%
+ return nScaleWidth;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/edit/eddel.cxx b/sw/source/core/edit/eddel.cxx
new file mode 100644
index 000000000000..494f780898df
--- /dev/null
+++ b/sw/source/core/edit/eddel.cxx
@@ -0,0 +1,358 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+
+#include <hintids.hxx>
+#include <doc.hxx>
+#include <IDocumentUndoRedo.hxx>
+#include <editsh.hxx>
+#include <cntfrm.hxx>
+#include <pam.hxx>
+#include <swundo.hxx> // fuer die UndoIds
+#include <edimp.hxx>
+#include <IMark.hxx>
+#include <docary.hxx>
+#include <SwRewriter.hxx>
+#include <globals.hrc>
+
+#include <comcore.hrc>
+#include <list>
+
+/************************************************************
+ * Loeschen
+ ************************************************************/
+
+void SwEditShell::DeleteSel( SwPaM& rPam, sal_Bool* pUndo )
+{
+ // nur bei Selektion
+ if( !rPam.HasMark() || *rPam.GetPoint() == *rPam.GetMark())
+ return;
+
+ // besteht eine Selection in einer Tabelle ?
+ // dann nur den Inhalt der selektierten Boxen loeschen
+ // jetzt gibt es 2 Faelle die beachtet werden muessen:
+ // 1. Point und Mark stehen in einer Box, Selection normal loeschen
+ // 2. Point und Mark stehen in unterschiedlichen Boxen, alle
+ // selektierten Boxen suchen in den Inhalt loeschen
+ if( rPam.GetNode()->FindTableNode() &&
+ rPam.GetNode()->StartOfSectionNode() !=
+ rPam.GetNode(sal_False)->StartOfSectionNode() )
+ {
+ // in Tabellen das Undo gruppieren
+ if( pUndo && !*pUndo )
+ {
+ GetDoc()->GetIDocumentUndoRedo().StartUndo( UNDO_START, NULL );
+ *pUndo = sal_True;
+ }
+ SwPaM aDelPam( *rPam.Start() );
+ const SwPosition* pEndSelPos = rPam.End();
+ do {
+ aDelPam.SetMark();
+ SwNode* pNd = aDelPam.GetNode();
+ const SwNode& rEndNd = *pNd->EndOfSectionNode();
+ if( pEndSelPos->nNode.GetIndex() <= rEndNd.GetIndex() )
+ {
+ *aDelPam.GetPoint() = *pEndSelPos;
+ pEndSelPos = 0; // Pointer als Flag missbrauchen
+ }
+ else
+ {
+ // dann ans Ende der Section
+ aDelPam.GetPoint()->nNode = rEndNd;
+ aDelPam.Move( fnMoveBackward, fnGoCntnt );
+ }
+ // geschuetze Boxen ueberspringen !
+ if( !pNd->IsCntntNode() ||
+ !((SwCntntNode*)pNd)->getLayoutFrm( GetLayout() )->IsProtected() )
+ {
+ // alles loeschen
+ GetDoc()->DeleteAndJoin( aDelPam );
+ SaveTblBoxCntnt( aDelPam.GetPoint() );
+ }
+
+ if( !pEndSelPos ) // am Ende der Selection
+ break;
+ aDelPam.DeleteMark();
+ aDelPam.Move( fnMoveForward, fnGoCntnt ); // naechste Box
+ } while( pEndSelPos );
+ }
+ else
+ {
+ // alles loeschen
+ GetDoc()->DeleteAndJoin( rPam );
+ SaveTblBoxCntnt( rPam.GetPoint() );
+ }
+
+ // Selection wird nicht mehr benoetigt.
+ rPam.DeleteMark();
+}
+
+
+long SwEditShell::Delete()
+{
+ SET_CURR_SHELL( this );
+ long nRet = 0;
+ if( !HasReadonlySel() )
+ {
+ StartAllAction();
+
+ sal_Bool bUndo = GetCrsr()->GetNext() != GetCrsr();
+ if( bUndo ) // mehr als eine Selection ?
+ {
+ SwRewriter aRewriter;
+ aRewriter.AddRule(UNDO_ARG1, String(SW_RES(STR_MULTISEL)));
+
+ GetDoc()->GetIDocumentUndoRedo().StartUndo(UNDO_DELETE, &aRewriter);
+ }
+
+ FOREACHPAM_START(this)
+ DeleteSel( *PCURCRSR, &bUndo );
+ FOREACHPAM_END()
+
+ // falls eine Undo-Klammerung, dann hier beenden
+ if( bUndo )
+ {
+ GetDoc()->GetIDocumentUndoRedo().EndUndo(UNDO_END, 0);
+ }
+ EndAllAction();
+ nRet = 1;
+ }
+ return nRet;
+}
+
+long SwEditShell::Copy( SwEditShell* pDestShell )
+{
+ if( !pDestShell )
+ pDestShell = this;
+
+ SET_CURR_SHELL( pDestShell );
+
+ // List of insert positions for smart insert of block selections
+ std::list< boost::shared_ptr<SwPosition> > aInsertList;
+
+ // Fill list of insert positions
+ {
+ SwPosition * pPos = 0;
+ boost::shared_ptr<SwPosition> pInsertPos;
+ sal_uInt16 nMove = 0;
+ FOREACHPAM_START(this)
+
+ if( !pPos )
+ {
+ if( pDestShell == this )
+ {
+ // First cursor represents the target position!!
+ PCURCRSR->DeleteMark();
+ pPos = (SwPosition*)PCURCRSR->GetPoint();
+ continue;
+ }
+ else
+ pPos = pDestShell->GetCrsr()->GetPoint();
+ }
+ if( IsBlockMode() )
+ { // In block mode different insert positions will be calculated
+ // by simulated cursor movements from the given first insert position
+ if( nMove )
+ {
+ SwCursor aCrsr( *pPos, 0, false);
+ if( aCrsr.UpDown( sal_False, nMove, 0, 0 ) )
+ {
+ pInsertPos.reset( new SwPosition( *aCrsr.GetPoint() ) );
+ aInsertList.push_back( pInsertPos );
+ }
+ }
+ else
+ pInsertPos.reset( new SwPosition( *pPos ) );
+ ++nMove;
+ }
+ SwPosition *pTmp = IsBlockMode() ? pInsertPos.get() : pPos;
+ // Check if a selection would be copied into itself
+ if( pDestShell->GetDoc() == GetDoc() &&
+ *PCURCRSR->Start() <= *pTmp && *pTmp < *PCURCRSR->End() )
+ return sal_False;
+ FOREACHPAM_END()
+ }
+
+ pDestShell->StartAllAction();
+ SwPosition *pPos = 0;
+ sal_Bool bRet = sal_False;
+ sal_Bool bFirstMove = sal_True;
+ SwNodeIndex aSttNdIdx( pDestShell->GetDoc()->GetNodes() );
+ xub_StrLen nSttCntIdx = 0;
+ // For block selection this list is filled with the insert positions
+ std::list< boost::shared_ptr<SwPosition> >::iterator pNextInsert = aInsertList.begin();
+
+ pDestShell->GetDoc()->GetIDocumentUndoRedo().StartUndo( UNDO_START, NULL );
+ FOREACHPAM_START(this)
+
+ if( !pPos )
+ {
+ if( pDestShell == this )
+ {
+ // First cursor represents the target position!!
+ PCURCRSR->DeleteMark();
+ pPos = (SwPosition*)PCURCRSR->GetPoint();
+ continue;
+ }
+ else
+ pPos = pDestShell->GetCrsr()->GetPoint();
+ }
+ if( !bFirstMove )
+ {
+ if( pNextInsert != aInsertList.end() )
+ {
+ pPos = pNextInsert->get();
+ ++pNextInsert;
+ }
+ else if( IsBlockMode() )
+ GetDoc()->SplitNode( *pPos, false );
+ }
+
+ // nur bei Selektion (nicht Textnodes haben Selection,
+ // aber Point/GetMark sind gleich
+ if( !PCURCRSR->HasMark() || *PCURCRSR->GetPoint() == *PCURCRSR->GetMark() )
+ continue;
+
+ if( bFirstMove )
+ {
+ // Anfangs-Position vom neuen Bereich merken
+ aSttNdIdx = pPos->nNode.GetIndex()-1;
+ nSttCntIdx = pPos->nContent.GetIndex();
+ bFirstMove = sal_False;
+ }
+
+ const bool bSuccess( GetDoc()->CopyRange( *PCURCRSR, *pPos, false ) );
+ if (!bSuccess)
+ continue;
+
+ SwPaM aInsertPaM(*pPos, SwPosition(aSttNdIdx));
+ pDestShell->GetDoc()->MakeUniqueNumRules(aInsertPaM);
+
+ bRet = sal_True;
+ FOREACHPAM_END()
+
+
+ // Maybe nothing has been moved?
+ if( !bFirstMove )
+ {
+ SwPaM* pCrsr = pDestShell->GetCrsr();
+ pCrsr->SetMark();
+ pCrsr->GetPoint()->nNode = aSttNdIdx.GetIndex()+1;
+ pCrsr->GetPoint()->nContent.Assign( pCrsr->GetCntntNode(),nSttCntIdx);
+ pCrsr->Exchange();
+ }
+ else
+ {
+ // falls beim Move der Cursor "gewandert" ist, so setze hier auch
+ // seinen GetMark um, damit dieser nie in den Wald zeigt.
+ pDestShell->GetCrsr()->SetMark();
+ pDestShell->GetCrsr()->DeleteMark();
+ }
+#if OSL_DEBUG_LEVEL > 1
+// pruefe ob die Indizies auch in den richtigen Nodes angemeldet sind
+{
+ SwPaM* pCmp = (SwPaM*)pDestShell->GetCrsr(); // sicher den Pointer auf Cursor
+ do {
+ OSL_ENSURE( pCmp->GetPoint()->nContent.GetIdxReg()
+ == pCmp->GetCntntNode(), "Point im falschen Node" );
+ OSL_ENSURE( pCmp->GetMark()->nContent.GetIdxReg()
+ == pCmp->GetCntntNode(sal_False), "Mark im falschen Node" );
+ sal_Bool bTst = *pCmp->GetPoint() == *pCmp->GetMark();
+ (void) bTst;
+ } while( pDestShell->GetCrsr() != ( pCmp = (SwPaM*)pCmp->GetNext() ) );
+}
+#endif
+
+ // Undo-Klammerung hier beenden
+ pDestShell->GetDoc()->GetIDocumentUndoRedo().EndUndo( UNDO_END, NULL );
+ pDestShell->EndAllAction();
+
+ pDestShell->SaveTblBoxCntnt( pDestShell->GetCrsr()->GetPoint() );
+
+ return (long)bRet;
+}
+
+
+ // Ersetz einen selektierten Bereich in einem TextNode mit dem
+ // String. Ist fuers Suchen&Ersetzen gedacht.
+ // bRegExpRplc - ersetze Tabs (\\t) und setze den gefundenen String
+ // ein ( nicht \& )
+ // z.B.: Fnd: "zzz", Repl: "xx\t\\t..&..\&"
+ // --> "xx\t<Tab>..zzz..&"
+sal_Bool SwEditShell::Replace( const String& rNewStr, sal_Bool bRegExpRplc )
+{
+ SET_CURR_SHELL( this );
+
+ sal_Bool bRet = sal_False;
+ if( !HasReadonlySel() )
+ {
+ StartAllAction();
+ GetDoc()->GetIDocumentUndoRedo().StartUndo(UNDO_EMPTY, NULL);
+
+ FOREACHPAM_START(this)
+ if( PCURCRSR->HasMark() && *PCURCRSR->GetMark() != *PCURCRSR->GetPoint() )
+ {
+ bRet = GetDoc()->ReplaceRange( *PCURCRSR, rNewStr, bRegExpRplc )
+ || bRet;
+ SaveTblBoxCntnt( PCURCRSR->GetPoint() );
+ }
+ FOREACHPAM_END()
+
+ // Undo-Klammerung hier beenden
+ GetDoc()->GetIDocumentUndoRedo().EndUndo(UNDO_EMPTY, NULL);
+ EndAllAction();
+ }
+ return bRet;
+}
+
+
+ // Special-Methode fuer JOE's- Wizzards
+sal_Bool SwEditShell::DelFullPara()
+{
+ sal_Bool bRet = sal_False;
+ if( !IsTableMode() )
+ {
+ SwPaM* pCrsr = GetCrsr();
+ // keine Mehrfach-Selection
+ if( pCrsr->GetNext() == pCrsr && !HasReadonlySel() )
+ {
+ SET_CURR_SHELL( this );
+ StartAllAction();
+ bRet = GetDoc()->DelFullPara( *pCrsr );
+ EndAllAction();
+ }
+ }
+ return bRet;
+}
+
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/edit/edfcol.cxx b/sw/source/core/edit/edfcol.cxx
new file mode 100644
index 000000000000..5f1b07d5315d
--- /dev/null
+++ b/sw/source/core/edit/edfcol.cxx
@@ -0,0 +1,161 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+
+#include <hintids.hxx>
+#include <editeng/brkitem.hxx>
+#include <editsh.hxx>
+#include <doc.hxx> // fuer SwTxtFmtColls
+#include <IDocumentUndoRedo.hxx>
+#include <edimp.hxx> // fuer MACROS
+#include <ndtxt.hxx>
+#include <paratr.hxx>
+#include <fmtpdsc.hxx>
+#include <viewopt.hxx> // Formular view
+#include <SwRewriter.hxx>
+#include <numrule.hxx>
+#include <swundo.hxx>
+
+/*************************************
+ * FormatColl
+ *************************************/
+// TXT
+
+
+SwTxtFmtColl& SwEditShell::GetDfltTxtFmtColl() const
+{
+ return *((SwTxtFmtColl*) (GetDoc()->GetDfltTxtFmtColl()));
+}
+
+
+sal_uInt16 SwEditShell::GetTxtFmtCollCount() const
+{
+ return GetDoc()->GetTxtFmtColls()->Count();
+}
+
+
+SwTxtFmtColl& SwEditShell::GetTxtFmtColl( sal_uInt16 nFmtColl) const
+{
+ return *((*(GetDoc()->GetTxtFmtColls()))[nFmtColl]);
+}
+
+// --> OD 2007-11-06 #i62675#
+void SwEditShell::SetTxtFmtColl( SwTxtFmtColl *pFmt,
+ bool bResetListAttrs )
+{
+ SwTxtFmtColl *pLocal = pFmt? pFmt: (*GetDoc()->GetTxtFmtColls())[0];
+ StartAllAction();
+
+ SwRewriter aRewriter;
+ aRewriter.AddRule(UNDO_ARG1, pLocal->GetName());
+
+ GetDoc()->GetIDocumentUndoRedo().StartUndo(UNDO_SETFMTCOLL, &aRewriter);
+ FOREACHPAM_START(this)
+
+ if( !PCURCRSR->HasReadonlySel(
+ // Formular view
+ GetViewOptions()->IsFormView() ) )
+ GetDoc()->SetTxtFmtColl( *PCURCRSR, pLocal, true, bResetListAttrs );
+
+ FOREACHPAM_END()
+ GetDoc()->GetIDocumentUndoRedo().EndUndo(UNDO_SETFMTCOLL, &aRewriter);
+ EndAllAction();
+}
+// <--
+
+
+SwTxtFmtColl* SwEditShell::MakeTxtFmtColl(const String& rFmtCollName,
+ SwTxtFmtColl* pParent)
+{
+ SwTxtFmtColl *pColl;
+ if ( pParent == 0 )
+ pParent = &GetTxtFmtColl(0);
+ if ( (pColl=GetDoc()->MakeTxtFmtColl(rFmtCollName, pParent)) == 0 )
+ {
+ OSL_FAIL( "MakeTxtFmtColl failed" );
+ }
+ return pColl;
+
+}
+
+
+void SwEditShell::FillByEx(SwTxtFmtColl* pColl, sal_Bool bReset)
+{
+ if( bReset )
+ {
+ // --> OD 2007-01-25 #i73790# - method renamed
+ pColl->ResetAllFmtAttr();
+ // <--
+ }
+
+ SwPaM * pCrsr = GetCrsr();
+ SwCntntNode * pCnt = pCrsr->GetCntntNode();
+ const SfxItemSet* pSet = pCnt->GetpSwAttrSet();
+ if( pSet )
+ {
+ // JP 05.10.98: falls eines der Attribute Break/PageDesc/NumRule(auto)
+ // im ItemSet steht, so entferne die VORM setzen an der Collection.
+ // Ansonst wird zu viel gemacht oder falsche gemacht (NumRules!)
+ // Bug 57568
+
+ // AutoNumRules NICHT in die Vorlagen uebernehmen
+ const SfxPoolItem* pItem;
+ const SwNumRule* pRule = 0;
+ if( SFX_ITEM_SET == pSet->GetItemState( RES_BREAK, sal_False ) ||
+ SFX_ITEM_SET == pSet->GetItemState( RES_PAGEDESC,sal_False ) ||
+ ( SFX_ITEM_SET == pSet->GetItemState( RES_PARATR_NUMRULE,
+ sal_False, &pItem ) && 0 != (pRule = GetDoc()->FindNumRulePtr(
+ ((SwNumRuleItem*)pItem)->GetValue() )) &&
+ pRule && pRule->IsAutoRule() )
+ )
+ {
+ SfxItemSet aSet( *pSet );
+ aSet.ClearItem( RES_BREAK );
+ aSet.ClearItem( RES_PAGEDESC );
+
+ if( pRule || (SFX_ITEM_SET == pSet->GetItemState( RES_PARATR_NUMRULE,
+ sal_False, &pItem ) && 0 != (pRule = GetDoc()->FindNumRulePtr(
+ ((SwNumRuleItem*)pItem)->GetValue() )) &&
+ pRule && pRule->IsAutoRule() ))
+ aSet.ClearItem( RES_PARATR_NUMRULE );
+
+ if( aSet.Count() )
+ GetDoc()->ChgFmt(*pColl, aSet );
+ }
+ else
+ GetDoc()->ChgFmt(*pColl, *pSet );
+ }
+}
+
+
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/edit/edfld.cxx b/sw/source/core/edit/edfld.cxx
new file mode 100644
index 000000000000..58005a97832b
--- /dev/null
+++ b/sw/source/core/edit/edfld.cxx
@@ -0,0 +1,557 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+
+#include <unotools/charclass.hxx>
+#include <editsh.hxx>
+#include <fldbas.hxx>
+#include <ndtxt.hxx> // GetCurFld
+#include <doc.hxx>
+#include <docary.hxx>
+#include <fmtfld.hxx>
+#include <txtfld.hxx>
+#include <edimp.hxx>
+#include <dbfld.hxx>
+#include <expfld.hxx>
+#include <flddat.hxx>
+#include <swundo.hxx>
+#include <dbmgr.hxx>
+#include <swddetbl.hxx>
+#include <hints.hxx>
+#include <switerator.hxx>
+#include <fieldhint.hxx>
+
+/*--------------------------------------------------------------------
+ Beschreibung: Feldtypen zu einer ResId zaehlen
+ wenn 0 alle zaehlen
+ --------------------------------------------------------------------*/
+
+sal_uInt16 SwEditShell::GetFldTypeCount(sal_uInt16 nResId, sal_Bool bUsed ) const
+{
+ const SwFldTypes* pFldTypes = GetDoc()->GetFldTypes();
+ const sal_uInt16 nSize = pFldTypes->Count();
+
+ if(nResId == USHRT_MAX)
+ {
+ if(!bUsed)
+ return nSize;
+ else
+ {
+ sal_uInt16 nUsed = 0;
+ for ( sal_uInt16 i = 0; i < nSize; i++ )
+ {
+ if(IsUsed(*(*pFldTypes)[i]))
+ nUsed++;
+ }
+ return nUsed;
+ }
+ }
+
+ // Alle Typen mit gleicher ResId
+ sal_uInt16 nIdx = 0;
+ for(sal_uInt16 i = 0; i < nSize; ++i)
+ { // Gleiche ResId -> Index erhoehen
+ SwFieldType& rFldType = *((*pFldTypes)[i]);
+ if(rFldType.Which() == nResId)
+ nIdx++;
+ }
+ return nIdx;
+}
+
+/*--------------------------------------------------------------------
+ Beschreibung: Feldtypen zu einer ResId finden
+ wenn 0 alle finden
+ --------------------------------------------------------------------*/
+SwFieldType* SwEditShell::GetFldType(sal_uInt16 nFld, sal_uInt16 nResId, sal_Bool bUsed ) const
+{
+ const SwFldTypes* pFldTypes = GetDoc()->GetFldTypes();
+ const sal_uInt16 nSize = pFldTypes->Count();
+
+ if(nResId == USHRT_MAX && nFld < nSize)
+ {
+ if(!bUsed)
+ return (*pFldTypes)[nFld];
+ else
+ {
+ sal_uInt16 i, nUsed = 0;
+ for ( i = 0; i < nSize; i++ )
+ {
+ if(IsUsed(*(*pFldTypes)[i]))
+ {
+ if(nUsed == nFld)
+ break;
+ nUsed++;
+ }
+ }
+ return i < nSize ? (*pFldTypes)[i] : 0;
+ }
+ }
+
+ sal_uInt16 nIdx = 0;
+ for(sal_uInt16 i = 0; i < nSize; ++i)
+ { // Gleiche ResId -> Index erhoehen
+ SwFieldType* pFldType = (*pFldTypes)[i];
+ if(pFldType->Which() == nResId)
+ {
+ if (!bUsed || IsUsed(*pFldType))
+ {
+ if(nIdx == nFld)
+ return pFldType;
+ nIdx++;
+ }
+ }
+ }
+ return 0;
+}
+
+/*--------------------------------------------------------------------
+ Beschreibung: Den ersten Typen mit ResId und Namen finden
+ --------------------------------------------------------------------*/
+SwFieldType* SwEditShell::GetFldType(sal_uInt16 nResId, const String& rName) const
+{
+ return GetDoc()->GetFldType( nResId, rName, false );
+}
+
+/*--------------------------------------------------------------------
+ Beschreibung: Feldtypen loeschen
+ --------------------------------------------------------------------*/
+void SwEditShell::RemoveFldType(sal_uInt16 nFld, sal_uInt16 nResId)
+{
+ if( USHRT_MAX == nResId )
+ {
+ GetDoc()->RemoveFldType(nFld);
+ return;
+ }
+
+ const SwFldTypes* pFldTypes = GetDoc()->GetFldTypes();
+ const sal_uInt16 nSize = pFldTypes->Count();
+ sal_uInt16 nIdx = 0;
+ for( sal_uInt16 i = 0; i < nSize; ++i )
+ // Gleiche ResId -> Index erhoehen
+ if( (*pFldTypes)[i]->Which() == nResId &&
+ nIdx++ == nFld )
+ {
+ GetDoc()->RemoveFldType( i );
+ return;
+ }
+}
+
+/*--------------------------------------------------------------------
+ Beschreibung: FieldType ueber Name loeschen
+ --------------------------------------------------------------------*/
+void SwEditShell::RemoveFldType(sal_uInt16 nResId, const String& rStr)
+{
+ const SwFldTypes* pFldTypes = GetDoc()->GetFldTypes();
+ const sal_uInt16 nSize = pFldTypes->Count();
+ const CharClass& rCC = GetAppCharClass();
+
+ String aTmp( rCC.lower( rStr ));
+
+ for(sal_uInt16 i = 0; i < nSize; ++i)
+ {
+ // Gleiche ResId -> Index erhoehen
+ SwFieldType* pFldType = (*pFldTypes)[i];
+ if( pFldType->Which() == nResId )
+ {
+ if( aTmp.Equals( rCC.lower( pFldType->GetName() ) ))
+ {
+ GetDoc()->RemoveFldType(i);
+ return;
+ }
+ }
+ }
+}
+
+
+void SwEditShell::FieldToText( SwFieldType* pType )
+{
+ if( !pType->GetDepends() )
+ return;
+
+ SET_CURR_SHELL( this );
+ StartAllAction();
+ StartUndo( UNDO_DELETE );
+ Push();
+ SwPaM* pPaM = GetCrsr();
+
+ SwFieldHint aHint( pPaM );
+ SwClientIter aIter( *pType );
+ for ( SwClient* pClient = aIter.GoStart(); pClient; aIter++ )
+ {
+ pPaM->DeleteMark();
+ pClient->SwClientNotifyCall( *pType, aHint );
+ }
+
+ Pop( sal_False );
+ EndAllAction();
+ EndUndo( UNDO_DELETE );
+}
+
+/*************************************************************************
+|*
+|* SwEditShell::Insert( SwField )
+|*
+|* Beschreibung an der Cursorposition ein Feld einfuegen
+|* Quelle: vgl. SwEditShell::Insert( String )
+|*
+*************************************************************************/
+void SwEditShell::Insert2(SwField& rFld, const bool bForceExpandHints)
+{
+ SET_CURR_SHELL( this );
+ StartAllAction();
+ SwFmtFld aFld( rFld );
+
+ const SetAttrMode nInsertFlags = (bForceExpandHints)
+ ? nsSetAttrMode::SETATTR_FORCEHINTEXPAND
+ : nsSetAttrMode::SETATTR_DEFAULT;
+
+ FOREACHPAM_START(this) // fuer jeden PaM
+ bool bSuccess(GetDoc()->InsertPoolItem(*PCURCRSR, aFld, nInsertFlags));
+ OSL_ENSURE( bSuccess, "Doc->Insert(Field) failed");
+ (void) bSuccess;
+ FOREACHPAM_END() // fuer jeden PaM
+
+ EndAllAction();
+}
+
+/*************************************************************************
+|*
+|* SwEditShell::GetCurFld()
+|*
+|* Beschreibung Stehen die PaMs auf Feldern ?
+|* Quelle: edtfrm.cxx:
+|*
+*************************************************************************/
+
+inline SwTxtFld *GetDocTxtFld( const SwPosition* pPos )
+{
+ SwTxtNode * const pNode = pPos->nNode.GetNode().GetTxtNode();
+ return (pNode)
+ ? static_cast<SwTxtFld*>( pNode->GetTxtAttrForCharAt(
+ pPos->nContent.GetIndex(), RES_TXTATR_FIELD ))
+ : 0;
+}
+
+SwField* SwEditShell::GetCurFld() const
+{
+ // Wenn es keine Selektionen gibt, gilt der Wert der aktuellen
+ // Cursor-Position.
+
+ SwPaM* pCrsr = GetCrsr();
+ SwTxtFld *pTxtFld = GetDocTxtFld( pCrsr->Start() );
+ SwField *pCurFld = NULL;
+
+ /* Field was only recognized if no selection was
+ present. Now it is recognized if either the cursor is in the
+ field or the selection spans exactly over the field. */
+ if( pTxtFld &&
+ pCrsr->GetNext() == pCrsr &&
+ pCrsr->Start()->nNode == pCrsr->End()->nNode &&
+ (pCrsr->End()->nContent.GetIndex() -
+ pCrsr->Start()->nContent.GetIndex()) <= 1)
+ {
+ pCurFld = (SwField*)pTxtFld->GetFld().GetFld();
+ // TabellenFormel ? wandel internen in externen Namen um
+ if( RES_TABLEFLD == pCurFld->GetTyp()->Which() )
+ {
+ const SwTableNode* pTblNd = IsCrsrInTbl();
+ ((SwTblField*)pCurFld)->PtrToBoxNm( pTblNd ? &pTblNd->GetTable() : 0 );
+ }
+
+ }
+
+ /* removed handling of multi-selections */
+
+ return pCurFld;
+}
+
+
+/*************************************************************************
+|*
+|* SwEditShell::UpdateFlds()
+|*
+|* Beschreibung Stehen die PaMs auf Feldern ?
+|*
+*************************************************************************/
+SwTxtFld* lcl_FindInputFld( SwDoc* pDoc, SwField& rFld )
+{
+ // suche das Feld ueber seine Addresse. Muss fuer InputFelder in
+ // geschuetzten Feldern erfolgen
+ SwTxtFld* pTFld = 0;
+ if( RES_INPUTFLD == rFld.Which() || ( RES_SETEXPFLD == rFld.Which() &&
+ ((SwSetExpField&)rFld).GetInputFlag() ) )
+ {
+ const SfxPoolItem* pItem;
+ sal_uInt32 n, nMaxItems =
+ pDoc->GetAttrPool().GetItemCount2( RES_TXTATR_FIELD );
+ for( n = 0; n < nMaxItems; ++n )
+ if( 0 != (pItem =
+ pDoc->GetAttrPool().GetItem2( RES_TXTATR_FIELD, n ) )
+ && ((SwFmtFld*)pItem)->GetFld() == &rFld )
+ {
+ pTFld = ((SwFmtFld*)pItem)->GetTxtFld();
+ break;
+ }
+ }
+ return pTFld;
+}
+
+void SwEditShell::UpdateFlds( SwField &rFld )
+{
+ SET_CURR_SHELL( this );
+ StartAllAction();
+ {
+ SwField *pCurFld = 0;
+
+ // Wenn es keine Selektionen gibt, gilt der Wert der aktuellen
+ // Cursor-Position.
+ SwMsgPoolItem* pMsgHnt = 0;
+ SwRefMarkFldUpdate aRefMkHt( GetOut() );
+ sal_uInt16 nFldWhich = rFld.GetTyp()->Which();
+ if( RES_GETREFFLD == nFldWhich )
+ pMsgHnt = &aRefMkHt;
+
+ SwPaM* pCrsr = GetCrsr();
+ SwTxtFld *pTxtFld;
+ SwFmtFld *pFmtFld;
+
+ if ( pCrsr->GetNext() == pCrsr && !pCrsr->HasMark())
+ {
+ pTxtFld = GetDocTxtFld(pCrsr->Start());
+
+ if (!pTxtFld) // #i30221#
+ pTxtFld = lcl_FindInputFld( GetDoc(), rFld);
+
+ if (pTxtFld != 0)
+ GetDoc()->UpdateFld(pTxtFld, rFld, pMsgHnt, sal_True);
+ }
+
+ // bOkay (statt return wg. EndAllAction) wird sal_False,
+ // 1) wenn nur ein Pam mehr als ein Feld enthaelt oder
+ // 2) bei gemischten Feldtypen
+ sal_Bool bOkay = sal_True;
+ sal_Bool bTblSelBreak = sal_False;
+
+ SwMsgPoolItem aHint( RES_TXTATR_FIELD ); // Such-Hint
+ FOREACHPAM_START(this) // fuer jeden PaM
+ if( PCURCRSR->HasMark() && bOkay ) // ... mit Selektion
+ {
+ // Kopie des PaM
+ SwPaM aCurPam( *PCURCRSR->GetMark(), *PCURCRSR->GetPoint() );
+ SwPaM aPam( *PCURCRSR->GetPoint() );
+
+ SwPosition *pCurStt = aCurPam.Start(), *pCurEnd =
+ aCurPam.End();
+ /*
+ * Fuer den Fall, dass zwei aneinanderliegende Felder in einem
+ * PaM liegen, hangelt sich aPam portionsweise bis zum Ende.
+ * aCurPam wird dabei nach jeder Schleifenrunde verkuerzt.
+ * Wenn aCurPam vollstaendig durchsucht wurde, ist Start = End
+ * und die Schleife terminiert.
+ */
+
+ // Suche nach SwTxtFld ...
+ while( bOkay
+ && pCurStt->nContent != pCurEnd->nContent
+ && aPam.Find( aHint, sal_False, fnMoveForward, &aCurPam ) )
+ {
+ // wenn nur ein Pam mehr als ein Feld enthaelt ...
+ if( aPam.Start()->nContent != pCurStt->nContent )
+ bOkay = sal_False;
+
+ if( 0 != (pTxtFld = GetDocTxtFld( pCurStt )) )
+ {
+ pFmtFld = (SwFmtFld*)&pTxtFld->GetFld();
+ pCurFld = pFmtFld->GetFld();
+
+ // bei gemischten Feldtypen
+ if( pCurFld->GetTyp()->Which() !=
+ rFld.GetTyp()->Which() )
+ bOkay = sal_False;
+
+ bTblSelBreak = GetDoc()->UpdateFld(pTxtFld, rFld,
+ pMsgHnt, sal_False);
+ }
+ // Der Suchbereich wird um den gefundenen Bereich
+ // verkuerzt.
+ pCurStt->nContent++;
+ }
+ }
+
+ if( bTblSelBreak ) // wenn Tabellen Selektion und Tabellen-
+ break; // Formel aktualisiert wurde -> beenden
+
+ FOREACHPAM_END() // fuer jeden PaM
+ }
+ GetDoc()->SetModified();
+ EndAllAction();
+}
+
+/*--------------------------------------------------
+ Liefert den logischen fuer die Datenbank zurueck
+ --------------------------------------------------*/
+
+SwDBData SwEditShell::GetDBData() const
+{
+ return GetDoc()->GetDBData();
+}
+
+const SwDBData& SwEditShell::GetDBDesc() const
+{
+ return GetDoc()->GetDBDesc();
+}
+
+void SwEditShell::ChgDBData(const SwDBData& rNewData)
+{
+ GetDoc()->ChgDBData(rNewData);
+}
+
+void SwEditShell::GetAllUsedDB( SvStringsDtor& rDBNameList,
+ SvStringsDtor* pAllDBNames )
+{
+ GetDoc()->GetAllUsedDB( rDBNameList, pAllDBNames );
+}
+
+void SwEditShell::ChangeDBFields( const SvStringsDtor& rOldNames,
+ const String& rNewName )
+{
+ GetDoc()->ChangeDBFields( rOldNames, rNewName );
+}
+
+/*--------------------------------------------------------------------
+ Beschreibung: Alle Expression-Felder erneuern
+ --------------------------------------------------------------------*/
+void SwEditShell::UpdateExpFlds(sal_Bool bCloseDB)
+{
+ SET_CURR_SHELL( this );
+ StartAllAction();
+ GetDoc()->UpdateExpFlds(NULL, true);
+ if (bCloseDB)
+ GetDoc()->GetNewDBMgr()->CloseAll(); // Alle Datenbankverbindungen dichtmachen
+ EndAllAction();
+}
+
+SwNewDBMgr* SwEditShell::GetNewDBMgr() const
+{
+ return GetDoc()->GetNewDBMgr();
+}
+
+/*--------------------------------------------------------------------
+ Beschreibung: Feldtypen einfuegen
+ --------------------------------------------------------------------*/
+SwFieldType* SwEditShell::InsertFldType(const SwFieldType& rFldType)
+{
+ return GetDoc()->InsertFldType(rFldType);
+}
+
+void SwEditShell::LockExpFlds()
+{
+ GetDoc()->LockExpFlds();
+}
+
+void SwEditShell::UnlockExpFlds()
+{
+ GetDoc()->UnlockExpFlds();
+}
+
+
+void SwEditShell::SetFldUpdateFlags( SwFldUpdateFlags eFlags )
+{
+ getIDocumentSettingAccess()->setFieldUpdateFlags( eFlags );
+}
+
+SwFldUpdateFlags SwEditShell::GetFldUpdateFlags(sal_Bool bDocSettings) const
+{
+ return getIDocumentSettingAccess()->getFieldUpdateFlags( !bDocSettings );
+}
+
+void SwEditShell::SetFixFields( sal_Bool bOnlyTimeDate,
+ const DateTime* pNewDateTime )
+{
+ SET_CURR_SHELL( this );
+ sal_Bool bUnLockView = !IsViewLocked();
+ LockView( sal_True );
+ StartAllAction();
+ GetDoc()->SetFixFields( bOnlyTimeDate, pNewDateTime );
+ EndAllAction();
+ if( bUnLockView )
+ LockView( sal_False );
+}
+
+void SwEditShell::SetLabelDoc( sal_Bool bFlag )
+{
+ GetDoc()->set(IDocumentSettingAccess::LABEL_DOCUMENT, bFlag );
+}
+
+sal_Bool SwEditShell::IsLabelDoc() const
+{
+ return getIDocumentSettingAccess()->get(IDocumentSettingAccess::LABEL_DOCUMENT);
+}
+
+void SwEditShell::ChangeAuthorityData(const SwAuthEntry* pNewData)
+{
+ GetDoc()->ChangeAuthorityData(pNewData);
+}
+
+sal_Bool SwEditShell::IsAnyDatabaseFieldInDoc()const
+{
+ const SwFldTypes * pFldTypes = GetDoc()->GetFldTypes();
+ const sal_uInt16 nSize = pFldTypes->Count();
+ for(sal_uInt16 i = 0; i < nSize; ++i)
+ {
+ SwFieldType& rFldType = *((*pFldTypes)[i]);
+ sal_uInt16 nWhich = rFldType.Which();
+ if(IsUsed(rFldType))
+ {
+ switch(nWhich)
+ {
+ case RES_DBFLD:
+ case RES_DBNEXTSETFLD:
+ case RES_DBNUMSETFLD:
+ case RES_DBSETNUMBERFLD:
+ {
+ SwIterator<SwFmtFld,SwFieldType> aIter( rFldType );
+ SwFmtFld* pFld = aIter.First();
+ while(pFld)
+ {
+ if(pFld->IsFldInDoc())
+ return sal_True;
+ pFld = aIter.Next();
+ }
+ }
+ break;
+ }
+ }
+ }
+ return sal_False;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/edit/edfldexp.cxx b/sw/source/core/edit/edfldexp.cxx
new file mode 100644
index 000000000000..0bc650313adc
--- /dev/null
+++ b/sw/source/core/edit/edfldexp.cxx
@@ -0,0 +1,99 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+#include <editsh.hxx>
+#include <dbfld.hxx>
+#include <dbmgr.hxx>
+#include <com/sun/star/container/XNameAccess.hpp>
+#include <comphelper/processfactory.hxx>
+#include <com/sun/star/lang/XMultiServiceFactory.hpp>
+#include <doc.hxx>
+#include <docary.hxx>
+#include <ndtxt.hxx> // GetCurFld
+#include <txtfld.hxx>
+#include <fmtfld.hxx>
+#include <edimp.hxx>
+#include <flddat.hxx>
+#include <switerator.hxx>
+
+using namespace com::sun::star;
+using ::rtl::OUString;
+
+sal_Bool SwEditShell::IsFieldDataSourceAvailable(String& rUsedDataSource) const
+{
+ const SwFldTypes * pFldTypes = GetDoc()->GetFldTypes();
+ const sal_uInt16 nSize = pFldTypes->Count();
+ uno::Reference< lang::XMultiServiceFactory > xMgr( ::comphelper::getProcessServiceFactory() );
+ if( !xMgr.is() )
+ return sal_False;
+ uno::Reference<uno::XInterface> xInstance = xMgr->createInstance(OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.sdb.DatabaseContext")));
+ uno::Reference<container::XNameAccess> xDBContext(xInstance, uno::UNO_QUERY) ;
+ if(!xDBContext.is())
+ return sal_False;
+ for(sal_uInt16 i = 0; i < nSize; ++i)
+ {
+ SwFieldType& rFldType = *((*pFldTypes)[i]);
+ sal_uInt16 nWhich = rFldType.Which();
+ if(IsUsed(rFldType))
+ {
+ switch(nWhich)
+ {
+ case RES_DBFLD:
+ {
+ SwIterator<SwFmtFld,SwFieldType> aIter( rFldType );
+ SwFmtFld* pFld = aIter.First();
+ while(pFld)
+ {
+ if(pFld->IsFldInDoc())
+ {
+ const SwDBData& rData =
+ ((SwDBFieldType*)pFld->GetFld()->GetTyp())->GetDBData();
+ try
+ {
+ return xDBContext->getByName(rData.sDataSource).hasValue();
+ }
+ catch(uno::Exception const &)
+ {
+ rUsedDataSource = rData.sDataSource;
+ return sal_False;
+ }
+ }
+ pFld = aIter.Next();
+ }
+ }
+ break;
+ }
+ }
+ }
+ return sal_True;
+}
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/edit/edfmt.cxx b/sw/source/core/edit/edfmt.cxx
new file mode 100644
index 000000000000..e597cac10d02
--- /dev/null
+++ b/sw/source/core/edit/edfmt.cxx
@@ -0,0 +1,200 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+
+
+#include "doc.hxx"
+#include "editsh.hxx"
+#include "swtable.hxx"
+#include "pam.hxx"
+#include <docary.hxx>
+#include <fchrfmt.hxx>
+#include <frmfmt.hxx>
+#include <charfmt.hxx>
+#include "ndtxt.hxx" // for GetXXXFmt
+#include "hints.hxx"
+
+/*************************************
+ * Formate
+ *************************************/
+// Char
+// OPT: inline
+
+
+sal_uInt16 SwEditShell::GetCharFmtCount() const
+{
+ return GetDoc()->GetCharFmts()->Count();
+}
+
+
+SwCharFmt& SwEditShell::GetCharFmt(sal_uInt16 nFmt) const
+{
+ return *((*(GetDoc()->GetCharFmts()))[nFmt]);
+}
+
+
+SwCharFmt* SwEditShell::GetCurCharFmt() const
+{
+ SwCharFmt *pFmt = 0;
+ SfxItemSet aSet( GetDoc()->GetAttrPool(), RES_TXTATR_CHARFMT,
+ RES_TXTATR_CHARFMT );
+ const SfxPoolItem* pItem;
+ if( GetCurAttr( aSet ) && SFX_ITEM_SET ==
+ aSet.GetItemState( RES_TXTATR_CHARFMT, sal_False, &pItem ) )
+ pFmt = ((SwFmtCharFmt*)pItem)->GetCharFmt();
+
+ return pFmt;
+}
+
+
+void SwEditShell::FillByEx(SwCharFmt* pCharFmt, sal_Bool bReset)
+{
+ if ( bReset )
+ {
+ // --> OD 2007-01-25 #i73790# - method renamed
+ pCharFmt->ResetAllFmtAttr();
+ // <--
+ }
+
+ SwPaM* pPam = GetCrsr();
+ const SwCntntNode* pCNd = pPam->GetCntntNode();
+ if( pCNd->IsTxtNode() )
+ {
+ xub_StrLen nStt, nEnd;
+ if( pPam->HasMark() )
+ {
+ const SwPosition* pPtPos = pPam->GetPoint();
+ const SwPosition* pMkPos = pPam->GetMark();
+ if( pPtPos->nNode == pMkPos->nNode ) // in the same node?
+ {
+ nStt = pPtPos->nContent.GetIndex();
+ if( nStt < pMkPos->nContent.GetIndex() )
+ nEnd = pMkPos->nContent.GetIndex();
+ else
+ {
+ nEnd = nStt;
+ nStt = pMkPos->nContent.GetIndex();
+ }
+ }
+ else
+ {
+ nStt = pMkPos->nContent.GetIndex();
+ if( pPtPos->nNode < pMkPos->nNode )
+ {
+ nEnd = nStt;
+ nStt = 0;
+ }
+ else
+ nEnd = ((SwTxtNode*)pCNd)->GetTxt().Len();
+ }
+ }
+ else
+ nStt = nEnd = pPam->GetPoint()->nContent.GetIndex();
+
+ SfxItemSet aSet( pDoc->GetAttrPool(),
+ pCharFmt->GetAttrSet().GetRanges() );
+ ((SwTxtNode*)pCNd)->GetAttr( aSet, nStt, nEnd );
+ pCharFmt->SetFmtAttr( aSet );
+ }
+ else if( pCNd->HasSwAttrSet() )
+ pCharFmt->SetFmtAttr( *pCNd->GetpSwAttrSet() );
+}
+
+// Frm
+sal_uInt16 SwEditShell::GetTblFrmFmtCount(sal_Bool bUsed) const
+{
+ return GetDoc()->GetTblFrmFmtCount(bUsed);
+}
+
+SwFrmFmt& SwEditShell::GetTblFrmFmt(sal_uInt16 nFmt, sal_Bool bUsed ) const
+{
+ return GetDoc()->GetTblFrmFmt(nFmt, bUsed );
+}
+
+String SwEditShell::GetUniqueTblName() const
+{
+ return GetDoc()->GetUniqueTblName();
+}
+
+
+SwCharFmt* SwEditShell::MakeCharFmt( const String& rName,
+ SwCharFmt* pDerivedFrom )
+{
+ if( !pDerivedFrom )
+ pDerivedFrom = GetDoc()->GetDfltCharFmt();
+
+ return GetDoc()->MakeCharFmt( rName, pDerivedFrom );
+}
+
+//----------------------------------
+// inlines in product
+
+
+SwTxtFmtColl* SwEditShell::GetTxtCollFromPool( sal_uInt16 nId )
+{
+ return GetDoc()->GetTxtCollFromPool( nId );
+}
+
+
+ // return the demanded automatic format - base-class !
+SwFmt* SwEditShell::GetFmtFromPool( sal_uInt16 nId )
+{
+ return GetDoc()->GetFmtFromPool( nId );
+}
+
+
+SwPageDesc* SwEditShell::GetPageDescFromPool( sal_uInt16 nId )
+{
+ return GetDoc()->GetPageDescFromPool( nId );
+}
+
+
+sal_Bool SwEditShell::IsUsed( const SwModify& rModify ) const
+{
+ return pDoc->IsUsed( rModify );
+}
+
+const SwFlyFrmFmt* SwEditShell::FindFlyByName( const String& rName, sal_uInt8 nNdTyp ) const
+{
+ return pDoc->FindFlyByName(rName, nNdTyp);
+}
+
+SwCharFmt* SwEditShell::FindCharFmtByName( const String& rName ) const
+{
+ return pDoc->FindCharFmtByName( rName );
+}
+
+SwTxtFmtColl* SwEditShell::FindTxtFmtCollByName( const String& rName ) const
+{
+ return pDoc->FindTxtFmtCollByName( rName );
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/edit/edglbldc.cxx b/sw/source/core/edit/edglbldc.cxx
new file mode 100644
index 000000000000..94cc61bc0499
--- /dev/null
+++ b/sw/source/core/edit/edglbldc.cxx
@@ -0,0 +1,412 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+#include <doc.hxx>
+#include <IDocumentUndoRedo.hxx>
+#include <editsh.hxx>
+#include <pam.hxx>
+#include <ndtxt.hxx>
+#include <docary.hxx>
+#include <swwait.hxx>
+#include <swundo.hxx> // fuer die UndoIds
+#include <section.hxx>
+#include <doctxm.hxx>
+#include <edglbldc.hxx>
+
+
+SV_IMPL_OP_PTRARR_SORT( SwGlblDocContents, SwGlblDocContentPtr )
+
+sal_Bool SwEditShell::IsGlobalDoc() const
+{
+ return getIDocumentSettingAccess()->get(IDocumentSettingAccess::GLOBAL_DOCUMENT);
+}
+
+void SwEditShell::SetGlblDocSaveLinks( sal_Bool bFlag )
+{
+ getIDocumentSettingAccess()->set(IDocumentSettingAccess::GLOBAL_DOCUMENT_SAVE_LINKS, bFlag);
+ if( !GetDoc()->IsModified() ) // Bug 57028
+ {
+ GetDoc()->GetIDocumentUndoRedo().SetUndoNoResetModified();
+ }
+ GetDoc()->SetModified();
+}
+
+sal_Bool SwEditShell::IsGlblDocSaveLinks() const
+{
+ return getIDocumentSettingAccess()->get(IDocumentSettingAccess::GLOBAL_DOCUMENT_SAVE_LINKS);
+}
+
+sal_uInt16 SwEditShell::GetGlobalDocContent( SwGlblDocContents& rArr ) const
+{
+ if( rArr.Count() )
+ rArr.DeleteAndDestroy( 0, rArr.Count() );
+
+ if( !getIDocumentSettingAccess()->get(IDocumentSettingAccess::GLOBAL_DOCUMENT) )
+ return 0;
+
+ // dann alle gelinkten Bereiche auf der obersten Ebene
+ SwDoc* pMyDoc = GetDoc();
+ const SwSectionFmts& rSectFmts = pMyDoc->GetSections();
+ sal_uInt16 n;
+
+ for( n = rSectFmts.Count(); n; )
+ {
+ const SwSection* pSect = rSectFmts[ --n ]->GetGlobalDocSection();
+ if( pSect )
+ {
+ SwGlblDocContentPtr pNew;
+ switch( pSect->GetType() )
+ {
+ case TOX_HEADER_SECTION: break; // ignore
+ case TOX_CONTENT_SECTION:
+ OSL_ENSURE( pSect->ISA( SwTOXBaseSection ), "keine TOXBaseSection!" );
+ pNew = new SwGlblDocContent( (SwTOXBaseSection*)pSect );
+ break;
+
+ default:
+ pNew = new SwGlblDocContent( pSect );
+ break;
+ }
+ if( !rArr.Insert( pNew ) )
+ delete pNew;
+ }
+ }
+
+ // und als letztes die Dummies (sonstiger Text) einfuegen
+ SwNode* pNd;
+ sal_uLong nSttIdx = pMyDoc->GetNodes().GetEndOfExtras().GetIndex() + 2;
+ for( n = 0; n < rArr.Count(); ++n )
+ {
+ const SwGlblDocContent& rNew = *rArr[ n ];
+ // suche von StartPos bis rNew.DocPos nach einem Content Node.
+ // Existiert dieser, so muss ein DummyEintrag eingefuegt werden.
+ for( ; nSttIdx < rNew.GetDocPos(); ++nSttIdx )
+ if( ( pNd = pMyDoc->GetNodes()[ nSttIdx ])->IsCntntNode()
+ || pNd->IsSectionNode() || pNd->IsTableNode() )
+ {
+ SwGlblDocContentPtr pNew = new SwGlblDocContent( nSttIdx );
+ if( !rArr.Insert( pNew ) )
+ delete pNew;
+ else
+ ++n; // auf die naechste Position
+ break;
+ }
+
+ // StartPosition aufs Ende setzen
+ nSttIdx = pMyDoc->GetNodes()[ rNew.GetDocPos() ]->EndOfSectionIndex();
+ ++nSttIdx;
+ }
+
+ // sollte man das Ende auch noch setzen??
+ if( rArr.Count() )
+ {
+ sal_uLong nNdEnd = pMyDoc->GetNodes().GetEndOfContent().GetIndex();
+ for( ; nSttIdx < nNdEnd; ++nSttIdx )
+ if( ( pNd = pMyDoc->GetNodes()[ nSttIdx ])->IsCntntNode()
+ || pNd->IsSectionNode() || pNd->IsTableNode() )
+ {
+ SwGlblDocContentPtr pNew = new SwGlblDocContent( nSttIdx );
+ if( !rArr.Insert( pNew ) )
+ delete pNew;
+ break;
+ }
+ }
+ else
+ {
+ SwGlblDocContentPtr pNew = new SwGlblDocContent(
+ pMyDoc->GetNodes().GetEndOfExtras().GetIndex() + 2 );
+ rArr.Insert( pNew );
+ }
+ return rArr.Count();
+}
+
+sal_Bool SwEditShell::InsertGlobalDocContent( const SwGlblDocContent& rInsPos,
+ SwSectionData & rNew)
+{
+ if( !getIDocumentSettingAccess()->get(IDocumentSettingAccess::GLOBAL_DOCUMENT) )
+ return sal_False;
+
+ SET_CURR_SHELL( this );
+ StartAllAction();
+
+ SwPaM* pCrsr = GetCrsr();
+ if( pCrsr->GetNext() != pCrsr || IsTableMode() )
+ ClearMark();
+
+ SwPosition& rPos = *pCrsr->GetPoint();
+ rPos.nNode = rInsPos.GetDocPos();
+
+ sal_Bool bEndUndo = sal_False;
+ SwDoc* pMyDoc = GetDoc();
+ SwTxtNode *const pTxtNd = rPos.nNode.GetNode().GetTxtNode();
+ if( pTxtNd )
+ rPos.nContent.Assign( pTxtNd, 0 );
+ else
+ {
+ bEndUndo = sal_True;
+ pMyDoc->GetIDocumentUndoRedo().StartUndo( UNDO_START, NULL );
+ rPos.nNode--;
+ pMyDoc->AppendTxtNode( rPos );
+ pCrsr->SetMark();
+ }
+
+ InsertSection( rNew );
+
+ if( bEndUndo )
+ {
+ pMyDoc->GetIDocumentUndoRedo().EndUndo( UNDO_END, NULL );
+ }
+ EndAllAction();
+
+ return sal_True;
+}
+
+sal_Bool SwEditShell::InsertGlobalDocContent( const SwGlblDocContent& rInsPos,
+ const SwTOXBase& rTOX )
+{
+ if( !getIDocumentSettingAccess()->get(IDocumentSettingAccess::GLOBAL_DOCUMENT) )
+ return sal_False;
+
+ SET_CURR_SHELL( this );
+ StartAllAction();
+
+ SwPaM* pCrsr = GetCrsr();
+ if( pCrsr->GetNext() != pCrsr || IsTableMode() )
+ ClearMark();
+
+ SwPosition& rPos = *pCrsr->GetPoint();
+ rPos.nNode = rInsPos.GetDocPos();
+
+ sal_Bool bEndUndo = sal_False;
+ SwDoc* pMyDoc = GetDoc();
+ SwTxtNode* pTxtNd = rPos.nNode.GetNode().GetTxtNode();
+ if( pTxtNd && pTxtNd->GetTxt().Len() && rPos.nNode.GetIndex() + 1 !=
+ pMyDoc->GetNodes().GetEndOfContent().GetIndex() )
+ rPos.nContent.Assign( pTxtNd, 0 );
+ else
+ {
+ bEndUndo = sal_True;
+ pMyDoc->GetIDocumentUndoRedo().StartUndo( UNDO_START, NULL );
+ rPos.nNode--;
+ pMyDoc->AppendTxtNode( rPos );
+ }
+
+ InsertTableOf( rTOX );
+
+ if( bEndUndo )
+ {
+ pMyDoc->GetIDocumentUndoRedo().EndUndo( UNDO_END, NULL );
+ }
+ EndAllAction();
+
+ return sal_True;
+}
+
+sal_Bool SwEditShell::InsertGlobalDocContent( const SwGlblDocContent& rInsPos )
+{
+ if( !getIDocumentSettingAccess()->get(IDocumentSettingAccess::GLOBAL_DOCUMENT) )
+ return sal_False;
+
+ SET_CURR_SHELL( this );
+ StartAllAction();
+
+ SwPaM* pCrsr = GetCrsr();
+ if( pCrsr->GetNext() != pCrsr || IsTableMode() )
+ ClearMark();
+
+ SwPosition& rPos = *pCrsr->GetPoint();
+ rPos.nNode = rInsPos.GetDocPos() - 1;
+ rPos.nContent.Assign( 0, 0 );
+
+ SwDoc* pMyDoc = GetDoc();
+ pMyDoc->AppendTxtNode( rPos );
+ EndAllAction();
+ return sal_True;
+}
+
+sal_Bool SwEditShell::DeleteGlobalDocContent( const SwGlblDocContents& rArr ,
+ sal_uInt16 nDelPos )
+{
+ if( !getIDocumentSettingAccess()->get(IDocumentSettingAccess::GLOBAL_DOCUMENT) )
+ return sal_False;
+
+ SET_CURR_SHELL( this );
+ StartAllAction();
+ StartUndo( UNDO_START );
+
+ SwPaM* pCrsr = GetCrsr();
+ if( pCrsr->GetNext() != pCrsr || IsTableMode() )
+ ClearMark();
+
+ SwPosition& rPos = *pCrsr->GetPoint();
+
+ SwDoc* pMyDoc = GetDoc();
+ const SwGlblDocContent& rDelPos = *rArr[ nDelPos ];
+ sal_uLong nDelIdx = rDelPos.GetDocPos();
+ if( 1 == rArr.Count() )
+ {
+ // ein Node muss aber da bleiben!
+ rPos.nNode = nDelIdx - 1;
+ rPos.nContent.Assign( 0, 0 );
+
+ pMyDoc->AppendTxtNode( rPos );
+ ++nDelIdx;
+ }
+
+ switch( rDelPos.GetType() )
+ {
+ case GLBLDOC_UNKNOWN:
+ {
+ rPos.nNode = nDelIdx;
+ pCrsr->SetMark();
+ if( ++nDelPos < rArr.Count() )
+ rPos.nNode = rArr[ nDelPos ]->GetDocPos();
+ else
+ rPos.nNode = pMyDoc->GetNodes().GetEndOfContent();
+ rPos.nNode--;
+ if( !pMyDoc->DelFullPara( *pCrsr ) )
+ Delete();
+ }
+ break;
+
+ case GLBLDOC_TOXBASE:
+ {
+ SwTOXBaseSection* pTOX = (SwTOXBaseSection*)rDelPos.GetTOX();
+ pMyDoc->DeleteTOX( *pTOX, sal_True );
+ }
+ break;
+
+ case GLBLDOC_SECTION:
+ {
+ SwSectionFmt* pSectFmt = (SwSectionFmt*)rDelPos.GetSection()->GetFmt();
+ pMyDoc->DelSectionFmt( pSectFmt, sal_True );
+ }
+ break;
+ }
+
+ EndUndo( UNDO_END );
+ EndAllAction();
+ return sal_True;
+}
+
+sal_Bool SwEditShell::MoveGlobalDocContent( const SwGlblDocContents& rArr ,
+ sal_uInt16 nFromPos, sal_uInt16 nToPos,
+ sal_uInt16 nInsPos )
+{
+ if( !getIDocumentSettingAccess()->get(IDocumentSettingAccess::GLOBAL_DOCUMENT) ||
+ nFromPos >= rArr.Count() || nToPos > rArr.Count() ||
+ nInsPos > rArr.Count() || nFromPos >= nToPos ||
+ ( nFromPos <= nInsPos && nInsPos <= nToPos ) )
+ return sal_False;
+
+ SET_CURR_SHELL( this );
+ StartAllAction();
+
+ SwPaM* pCrsr = GetCrsr();
+ if( pCrsr->GetNext() != pCrsr || IsTableMode() )
+ ClearMark();
+
+ SwDoc* pMyDoc = GetDoc();
+ SwNodeRange aRg( pMyDoc->GetNodes(), rArr[ nFromPos ]->GetDocPos() );
+ if( nToPos < rArr.Count() )
+ aRg.aEnd = rArr[ nToPos ]->GetDocPos();
+ else
+ aRg.aEnd = pMyDoc->GetNodes().GetEndOfContent();
+
+ SwNodeIndex aInsPos( pMyDoc->GetNodes() );
+ if( nInsPos < rArr.Count() )
+ aInsPos = rArr[ nInsPos ]->GetDocPos();
+ else
+ aInsPos = pMyDoc->GetNodes().GetEndOfContent();
+
+ bool bRet = pMyDoc->MoveNodeRange( aRg, aInsPos,
+ static_cast<IDocumentContentOperations::SwMoveFlags>(
+ IDocumentContentOperations::DOC_MOVEALLFLYS
+ | IDocumentContentOperations::DOC_CREATEUNDOOBJ ));
+
+ EndAllAction();
+ return bRet;
+}
+
+sal_Bool SwEditShell::GotoGlobalDocContent( const SwGlblDocContent& rPos )
+{
+ if( !getIDocumentSettingAccess()->get(IDocumentSettingAccess::GLOBAL_DOCUMENT) )
+ return sal_False;
+
+ SET_CURR_SHELL( this );
+ SttCrsrMove();
+
+ SwPaM* pCrsr = GetCrsr();
+ if( pCrsr->GetNext() != pCrsr || IsTableMode() )
+ ClearMark();
+
+ SwPosition& rCrsrPos = *pCrsr->GetPoint();
+ rCrsrPos.nNode = rPos.GetDocPos();
+
+ SwDoc* pMyDoc = GetDoc();
+ SwCntntNode * pCNd = rCrsrPos.nNode.GetNode().GetCntntNode();
+ if( !pCNd )
+ pCNd = pMyDoc->GetNodes().GoNext( &rCrsrPos.nNode );
+
+ rCrsrPos.nContent.Assign( pCNd, 0 );
+
+ EndCrsrMove();
+ return sal_True;
+}
+
+SwGlblDocContent::SwGlblDocContent( sal_uLong nPos )
+{
+ eType = GLBLDOC_UNKNOWN;
+ PTR.pTOX = 0;
+ nDocPos = nPos;
+}
+
+SwGlblDocContent::SwGlblDocContent( const SwTOXBaseSection* pTOX )
+{
+ eType = GLBLDOC_TOXBASE;
+ PTR.pTOX = pTOX;
+
+ const SwSectionNode* pSectNd = pTOX->GetFmt()->GetSectionNode();
+ nDocPos = pSectNd ? pSectNd->GetIndex() : 0;
+}
+
+SwGlblDocContent::SwGlblDocContent( const SwSection* pSect )
+{
+ eType = GLBLDOC_SECTION;
+ PTR.pSect = pSect;
+
+ const SwSectionNode* pSectNd = pSect->GetFmt()->GetSectionNode();
+ nDocPos = pSectNd ? pSectNd->GetIndex() : 0;
+}
+
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/edit/edglss.cxx b/sw/source/core/edit/edglss.cxx
new file mode 100644
index 000000000000..a559edc840a0
--- /dev/null
+++ b/sw/source/core/edit/edglss.cxx
@@ -0,0 +1,373 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+
+#include <osl/endian.h>
+#include <hintids.hxx>
+#include <svl/urihelper.hxx>
+#include <tools/cachestr.hxx>
+#include <doc.hxx>
+#include <pam.hxx>
+#include <docary.hxx>
+#include <editsh.hxx>
+#include <edimp.hxx>
+#include <frmfmt.hxx>
+#include <swundo.hxx> // fuer die UndoIds
+#include <ndtxt.hxx>
+#include <swtable.hxx> // fuers kopieren von Tabellen
+#include <shellio.hxx> // SwTextBlocks
+#include <acorrect.hxx>
+#include <swerror.h> // SwTextBlocks
+
+/******************************************************************************
+ * jetzt mit einem verkappten Reader/Writer/Dokument
+ ******************************************************************************/
+
+void SwEditShell::InsertGlossary( SwTextBlocks& rGlossary, const String& rStr )
+{
+ StartAllAction();
+ GetDoc()->InsertGlossary( rGlossary, rStr, *GetCrsr(), this );
+ EndAllAction();
+}
+
+
+/******************************************************************************
+ * aktuelle Selektion zum Textbaustein machen und ins
+ * Textbausteindokument einfuegen, einschliesslich Vorlagen
+ ******************************************************************************/
+
+
+sal_uInt16 SwEditShell::MakeGlossary( SwTextBlocks& rBlks, const String& rName, const String& rShortName,
+ sal_Bool bSaveRelFile, const String* pOnlyTxt )
+{
+ SwDoc* pGDoc = rBlks.GetDoc();
+
+ String sBase;
+ if(bSaveRelFile)
+ {
+ INetURLObject aURL( rBlks.GetFileName() );
+ sBase = aURL.GetMainURL( INetURLObject::NO_DECODE );
+ }
+ rBlks.SetBaseURL( sBase );
+
+ sal_uInt16 nRet;
+
+ if( pOnlyTxt )
+ nRet = rBlks.PutText( rShortName, rName, *pOnlyTxt );
+ else
+ {
+ rBlks.ClearDoc();
+ if( rBlks.BeginPutDoc( rShortName, rName ) )
+ {
+ rBlks.GetDoc()->SetRedlineMode_intern( nsRedlineMode_t::REDLINE_DELETE_REDLINES );
+ _CopySelToDoc( pGDoc );
+ rBlks.GetDoc()->SetRedlineMode_intern( (RedlineMode_t)0 );
+ nRet = rBlks.PutDoc();
+ }
+ else
+ nRet = (sal_uInt16) -1;
+ }
+
+ return nRet;
+}
+
+sal_uInt16 SwEditShell::SaveGlossaryDoc( SwTextBlocks& rBlock,
+ const String& rName,
+ const String& rShortName,
+ sal_Bool bSaveRelFile,
+ sal_Bool bOnlyTxt )
+{
+ StartAllAction();
+
+ SwDoc* pGDoc = rBlock.GetDoc();
+ SwDoc* pMyDoc = GetDoc();
+
+ String sBase;
+ if(bSaveRelFile)
+ {
+ INetURLObject aURL( rBlock.GetFileName() );
+ sBase = aURL.GetMainURL( INetURLObject::NO_DECODE );
+ }
+ rBlock.SetBaseURL( sBase );
+ sal_uInt16 nRet = USHRT_MAX;
+
+ if( bOnlyTxt )
+ {
+ KillPams();
+
+ SwPaM* pCrsr = GetCrsr();
+
+ SwNodeIndex aStt( pMyDoc->GetNodes().GetEndOfExtras(), 1 );
+ SwCntntNode* pCntntNd = pMyDoc->GetNodes().GoNext( &aStt );
+ const SwNode* pNd = pCntntNd->FindTableNode();
+ if( !pNd )
+ pNd = pCntntNd;
+
+ pCrsr->GetPoint()->nNode = *pNd;
+ if( pNd == pCntntNd )
+ pCrsr->GetPoint()->nContent.Assign( pCntntNd, 0 );
+ pCrsr->SetMark();
+
+ // dann bis zum Ende vom Nodes Array
+ pCrsr->GetPoint()->nNode = pMyDoc->GetNodes().GetEndOfContent().GetIndex()-1;
+ pCntntNd = pCrsr->GetCntntNode();
+ if( pCntntNd )
+ pCrsr->GetPoint()->nContent.Assign( pCntntNd, pCntntNd->Len() );
+
+ String sBuf;
+ if( GetSelectedText( sBuf, GETSELTXT_PARABRK_TO_ONLYCR ) && sBuf.Len() )
+ nRet = rBlock.PutText( rShortName, rName, sBuf );
+ }
+ else
+ {
+ rBlock.ClearDoc();
+ if( rBlock.BeginPutDoc( rShortName, rName ) )
+ {
+ SwNodeIndex aStt( pMyDoc->GetNodes().GetEndOfExtras(), 1 );
+ SwCntntNode* pCntntNd = pMyDoc->GetNodes().GoNext( &aStt );
+ const SwNode* pNd = pCntntNd->FindTableNode();
+ if( !pNd ) pNd = pCntntNd;
+ SwPaM aCpyPam( *pNd );
+ aCpyPam.SetMark();
+
+ // dann bis zum Ende vom Nodes Array
+ aCpyPam.GetPoint()->nNode = pMyDoc->GetNodes().GetEndOfContent().GetIndex()-1;
+ pCntntNd = aCpyPam.GetCntntNode();
+ aCpyPam.GetPoint()->nContent.Assign( pCntntNd, pCntntNd->Len() );
+
+ aStt = pGDoc->GetNodes().GetEndOfExtras();
+ pCntntNd = pGDoc->GetNodes().GoNext( &aStt );
+ SwPosition aInsPos( aStt, SwIndex( pCntntNd ));
+ pMyDoc->CopyRange( aCpyPam, aInsPos, false );
+
+ nRet = rBlock.PutDoc();
+ }
+ }
+ EndAllAction();
+ return nRet;
+}
+
+/******************************************************************************
+ * kopiere alle Selectionen und das Doc
+ ******************************************************************************/
+
+
+sal_Bool SwEditShell::_CopySelToDoc( SwDoc* pInsDoc, SwNodeIndex* pSttNd )
+{
+ OSL_ENSURE( pInsDoc, "kein Ins.Dokument" );
+
+ SwNodes& rNds = pInsDoc->GetNodes();
+
+ SwNodeIndex aIdx( rNds.GetEndOfContent(), -1 );
+ SwCntntNode * pNd = aIdx.GetNode().GetCntntNode();
+ SwPosition aPos( aIdx, SwIndex( pNd, pNd->Len() ));
+
+ // soll der Index auf Anfang returnt werden ?
+ if( pSttNd )
+ {
+ *pSttNd = aPos.nNode;
+ (*pSttNd)--;
+ }
+
+ sal_Bool bRet = sal_False;
+ SET_CURR_SHELL( this );
+
+ pInsDoc->LockExpFlds();
+
+ if( IsTableMode() )
+ {
+ // kopiere Teile aus einer Tabelle: lege eine Tabelle mit der Breite
+ // von der Originalen an und kopiere die selectierten Boxen.
+ // Die Groessen werden prozentual korrigiert.
+
+ // lasse ueber das Layout die Boxen suchen
+ SwTableNode* pTblNd;
+ SwSelBoxes aBoxes;
+ GetTblSel( *this, aBoxes );
+ if( aBoxes.Count() && 0 != (pTblNd = (SwTableNode*)aBoxes[0]
+ ->GetSttNd()->FindTableNode() ))
+ {
+ // teste ob der TabellenName kopiert werden kann
+ sal_Bool bCpyTblNm = aBoxes.Count() == pTblNd->GetTable().GetTabSortBoxes().Count();
+ if( bCpyTblNm )
+ {
+ const String& rTblName = pTblNd->GetTable().GetFrmFmt()->GetName();
+ const SwFrmFmts& rTblFmts = *pInsDoc->GetTblFrmFmts();
+ for( sal_uInt16 n = rTblFmts.Count(); n; )
+ if( rTblFmts[ --n ]->GetName() == rTblName )
+ {
+ bCpyTblNm = sal_False;
+ break;
+ }
+ }
+ bRet = pInsDoc->InsCopyOfTbl( aPos, aBoxes, 0, bCpyTblNm, sal_False );
+ }
+ else
+ bRet = sal_False;
+ }
+ else
+ {
+ bool bColSel = _GetCrsr()->IsColumnSelection();
+ if( bColSel && pInsDoc->IsClipBoard() )
+ pInsDoc->SetColumnSelection( true );
+ {
+ FOREACHPAM_START(this)
+
+ if( !PCURCRSR->HasMark() )
+ {
+ if( 0 != (pNd = PCURCRSR->GetCntntNode()) &&
+ ( bColSel || !pNd->GetTxtNode() ) )
+ {
+ PCURCRSR->SetMark();
+ PCURCRSR->Move( fnMoveForward, fnGoCntnt );
+ bRet = GetDoc()->CopyRange( *PCURCRSR, aPos, false )
+ || bRet;
+ PCURCRSR->Exchange();
+ PCURCRSR->DeleteMark();
+ }
+ }
+ else
+ {
+ bRet = GetDoc()->CopyRange( *PCURCRSR, aPos, false ) || bRet;
+ }
+
+ FOREACHPAM_END()
+ }
+ }
+
+ pInsDoc->UnlockExpFlds();
+ if( !pInsDoc->IsExpFldsLocked() )
+ pInsDoc->UpdateExpFlds(NULL, true);
+
+ // die gemerkte Node-Position wieder auf den richtigen Node
+ if( bRet && pSttNd )
+ (*pSttNd)++;
+
+
+ return bRet;
+}
+
+/*------------------------------------------------------------------------
+ Beschreibung: Text innerhalb der Selektion erfragen
+ Returnwert: liefert sal_False, wenn der selektierte Bereich
+ zu gross ist, um in den Stringpuffer kopiert zu werden.
+------------------------------------------------------------------------*/
+
+sal_Bool SwEditShell::GetSelectedText( String &rBuf, int nHndlParaBrk )
+{
+ GetCrsr(); // ggfs. alle Cursor erzeugen lassen
+ if( IsSelOnePara() )
+ {
+ rBuf = GetSelTxt();
+ if( GETSELTXT_PARABRK_TO_BLANK == nHndlParaBrk )
+ {
+ xub_StrLen nPos = 0;
+ while( STRING_NOTFOUND !=
+ ( nPos = rBuf.SearchAndReplace( 0x0a, ' ', nPos )) )
+ ;
+ }
+ else if( IsSelFullPara() &&
+ GETSELTXT_PARABRK_TO_ONLYCR != nHndlParaBrk )
+ {
+#if defined(UNX)
+ rBuf += '\012';
+#else
+ rBuf += String::CreateFromAscii(
+ RTL_CONSTASCII_STRINGPARAM( "\015\012" ));
+#endif
+ }
+ }
+ else if( IsSelection() )
+ {
+ SvCacheStream aStream(20480);
+#ifdef OSL_BIGENDIAN
+ aStream.SetNumberFormatInt( NUMBERFORMAT_INT_BIGENDIAN );
+#else
+ aStream.SetNumberFormatInt( NUMBERFORMAT_INT_LITTLEENDIAN );
+#endif
+ WriterRef xWrt;
+ SwReaderWriter::GetWriter( String::CreateFromAscii( FILTER_TEXT ), String(), xWrt );
+ if( xWrt.Is() )
+ {
+ // Selektierte Bereiche in ein ASCII Dokument schreiben
+ SwWriter aWriter( aStream, *this);
+ xWrt->SetShowProgress( sal_False );
+
+ switch( nHndlParaBrk )
+ {
+ case GETSELTXT_PARABRK_TO_BLANK:
+ xWrt->bASCII_ParaAsBlanc = sal_True;
+ xWrt->bASCII_NoLastLineEnd = sal_True;
+ break;
+
+ case GETSELTXT_PARABRK_TO_ONLYCR:
+ xWrt->bASCII_ParaAsCR = sal_True;
+ xWrt->bASCII_NoLastLineEnd = sal_True;
+ break;
+ }
+
+ //JP 09.05.00: write as UNICODE ! (and not as ANSI)
+ SwAsciiOptions aAsciiOpt( xWrt->GetAsciiOptions() );
+ aAsciiOpt.SetCharSet( RTL_TEXTENCODING_UCS2 );
+ xWrt->SetAsciiOptions( aAsciiOpt );
+ xWrt->bUCS2_WithStartChar = sal_False;
+
+ long lLen;
+ if( !IsError( aWriter.Write( xWrt ) ) &&
+ STRING_MAXLEN > (( lLen = aStream.GetSize() )
+ / sizeof( sal_Unicode )) + 1 )
+ {
+ aStream << (sal_Unicode)'\0';
+
+ const sal_Unicode *p = (sal_Unicode*)aStream.GetBuffer();
+ if( p )
+ rBuf = p;
+ else
+ {
+ sal_Unicode* pStrBuf = rBuf.AllocBuffer( xub_StrLen(
+ ( lLen / sizeof( sal_Unicode ))) );
+ aStream.Seek( 0 );
+ aStream.ResetError();
+ aStream.Read( pStrBuf, lLen );
+ pStrBuf[ lLen / sizeof( sal_Unicode ) ] = '\0';
+ }
+ }
+ }
+ }
+
+ return sal_True;
+}
+
+
+
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/edit/editsh.cxx b/sw/source/core/edit/editsh.cxx
new file mode 100644
index 000000000000..5f428d85c4f9
--- /dev/null
+++ b/sw/source/core/edit/editsh.cxx
@@ -0,0 +1,1167 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+#include <hintids.hxx>
+#include <tools/urlobj.hxx>
+#include <vcl/cmdevt.hxx>
+#include <unotools/charclass.hxx>
+#include <comphelper/processfactory.hxx>
+#include <unotools/transliterationwrapper.hxx>
+#include <swwait.hxx>
+#include <fmtsrnd.hxx>
+#include <fmtinfmt.hxx>
+#include <txtinet.hxx>
+#include <frmfmt.hxx>
+#include <charfmt.hxx>
+#include <doc.hxx>
+#include <IDocumentUndoRedo.hxx>
+#include <docary.hxx>
+#include <editsh.hxx>
+#include <frame.hxx>
+#include <cntfrm.hxx>
+#include <pam.hxx>
+#include <ndtxt.hxx> // fuer SwTxtNode
+#include <grfatr.hxx>
+#include <flyfrm.hxx>
+#include <swtable.hxx>
+#include <swundo.hxx> // UNDO_START, UNDO_END
+#include <calc.hxx>
+#include <edimp.hxx>
+#include <ndgrf.hxx>
+#include <ndole.hxx>
+#include <txtfrm.hxx>
+#include <rootfrm.hxx>
+#include <extinput.hxx>
+#include <crsskip.hxx>
+#include <scriptinfo.hxx>
+#include <unocrsrhelper.hxx>
+#include <section.hxx>
+#include <unochart.hxx>
+#include <numrule.hxx>
+#include <SwNodeNum.hxx>
+#include <unocrsr.hxx>
+#include <switerator.hxx>
+
+using namespace com::sun::star;
+
+
+SV_IMPL_PTRARR(SwGetINetAttrs, SwGetINetAttr*)
+
+/******************************************************************************
+ * void SwEditShell::Insert(char c)
+ ******************************************************************************/
+
+
+void SwEditShell::Insert( sal_Unicode c, sal_Bool bOnlyCurrCrsr )
+{
+ StartAllAction();
+ FOREACHPAM_START(this)
+
+ const bool bSuccess = GetDoc()->InsertString(*PCURCRSR, c);
+ OSL_ENSURE( bSuccess, "Doc->Insert() failed." );
+ (void) bSuccess;
+
+ SaveTblBoxCntnt( PCURCRSR->GetPoint() );
+ if( bOnlyCurrCrsr )
+ break;
+
+ FOREACHPAM_END()
+
+ EndAllAction();
+}
+
+
+/******************************************************************************
+ * void SwEditShell::Insert(const String &rStr)
+ ******************************************************************************/
+
+
+void SwEditShell::Insert2(const String &rStr, const bool bForceExpandHints )
+{
+ StartAllAction();
+ {
+ const enum IDocumentContentOperations::InsertFlags nInsertFlags =
+ (bForceExpandHints)
+ ? static_cast<IDocumentContentOperations::InsertFlags>(
+ IDocumentContentOperations::INS_FORCEHINTEXPAND |
+ IDocumentContentOperations::INS_EMPTYEXPAND)
+ : IDocumentContentOperations::INS_EMPTYEXPAND;
+
+ SwPaM *_pStartCrsr = getShellCrsr( true ), *__pStartCrsr = _pStartCrsr;
+ do {
+ //OPT: GetSystemCharSet
+ const bool bSuccess =
+ GetDoc()->InsertString(*_pStartCrsr, rStr, nInsertFlags);
+ OSL_ENSURE( bSuccess, "Doc->Insert() failed." );
+ (void) bSuccess;
+
+ SaveTblBoxCntnt( _pStartCrsr->GetPoint() );
+
+ } while( (_pStartCrsr=(SwPaM *)_pStartCrsr->GetNext()) != __pStartCrsr );
+ }
+
+ // calculate cursor bidi level
+ SwCursor* pTmpCrsr = _GetCrsr();
+ const sal_Bool bDoNotSetBidiLevel = ! pTmpCrsr ||
+ ( 0 != dynamic_cast<SwUnoCrsr*>(pTmpCrsr) );
+
+ if ( ! bDoNotSetBidiLevel )
+ {
+ SwNode& rNode = pTmpCrsr->GetPoint()->nNode.GetNode();
+ if ( rNode.IsTxtNode() )
+ {
+ SwIndex& rIdx = pTmpCrsr->GetPoint()->nContent;
+ xub_StrLen nPos = rIdx.GetIndex();
+ xub_StrLen nPrevPos = nPos;
+ if ( nPrevPos )
+ --nPrevPos;
+
+ SwScriptInfo* pSI = SwScriptInfo::GetScriptInfo( ((SwTxtNode&)rNode),
+ sal_True );
+
+ sal_uInt8 nLevel = 0;
+ if ( ! pSI )
+ {
+ // seems to be an empty paragraph.
+ Point aPt;
+ SwCntntFrm* pFrm =
+ ((SwTxtNode&)rNode).getLayoutFrm( GetLayout(), &aPt, pTmpCrsr->GetPoint(),
+ sal_False );
+
+ SwScriptInfo aScriptInfo;
+ aScriptInfo.InitScriptInfo( (SwTxtNode&)rNode, pFrm->IsRightToLeft() );
+ nLevel = aScriptInfo.DirType( nPrevPos );
+ }
+ else
+ {
+ if ( STRING_LEN != pSI->GetInvalidity() )
+ pSI->InitScriptInfo( (SwTxtNode&)rNode );
+ nLevel = pSI->DirType( nPrevPos );
+ }
+
+ pTmpCrsr->SetCrsrBidiLevel( nLevel );
+ }
+ }
+
+ SetInFrontOfLabel( sal_False ); // #i27615#
+
+ EndAllAction();
+}
+
+
+/******************************************************************************
+ * void SwEditShell::Overwrite(const String &rStr)
+ ******************************************************************************/
+
+
+void SwEditShell::Overwrite(const String &rStr)
+{
+ StartAllAction();
+ FOREACHPAM_START(this)
+ if( !GetDoc()->Overwrite(*PCURCRSR, rStr ) )
+ {
+ OSL_FAIL( "Doc->Overwrite(Str) failed." );
+ }
+ SaveTblBoxCntnt( PCURCRSR->GetPoint() );
+ FOREACHPAM_END()
+ EndAllAction();
+}
+
+
+/******************************************************************************
+ * long SwEditShell::SplitNode()
+ ******************************************************************************/
+
+long SwEditShell::SplitNode( sal_Bool bAutoFormat, sal_Bool bCheckTableStart )
+{
+ StartAllAction();
+ GetDoc()->GetIDocumentUndoRedo().StartUndo(UNDO_EMPTY, NULL);
+
+ FOREACHPAM_START(this)
+ // eine Tabellen Zelle wird jetzt zu einer normalen Textzelle!
+ GetDoc()->ClearBoxNumAttrs( PCURCRSR->GetPoint()->nNode );
+ GetDoc()->SplitNode( *PCURCRSR->GetPoint(), bCheckTableStart );
+ FOREACHPAM_END()
+
+ GetDoc()->GetIDocumentUndoRedo().EndUndo(UNDO_EMPTY, NULL);
+
+ if( bAutoFormat )
+ AutoFmtBySplitNode();
+
+ ClearTblBoxCntnt();
+
+ EndAllAction();
+ return(1L);
+}
+
+sal_Bool SwEditShell::AppendTxtNode()
+{
+ sal_Bool bRet = sal_False;
+ StartAllAction();
+ GetDoc()->GetIDocumentUndoRedo().StartUndo(UNDO_EMPTY, NULL);
+
+ FOREACHPAM_START(this)
+ GetDoc()->ClearBoxNumAttrs( PCURCRSR->GetPoint()->nNode );
+ bRet = GetDoc()->AppendTxtNode( *PCURCRSR->GetPoint()) || bRet;
+ FOREACHPAM_END()
+
+ GetDoc()->GetIDocumentUndoRedo().EndUndo(UNDO_EMPTY, NULL);
+
+ ClearTblBoxCntnt();
+
+ EndAllAction();
+ return bRet;
+}
+
+/******************************************************************************
+ * liefert einen Pointer auf einen SwGrfNode; dieser wird von
+ * GetGraphic() und GetGraphicSize() verwendet.
+ ******************************************************************************/
+
+
+SwGrfNode * SwEditShell::_GetGrfNode() const
+{
+ SwGrfNode *pGrfNode = 0;
+ SwPaM* pCrsr = GetCrsr();
+ if( !pCrsr->HasMark() ||
+ pCrsr->GetPoint()->nNode == pCrsr->GetMark()->nNode )
+ pGrfNode = pCrsr->GetPoint()->nNode.GetNode().GetGrfNode();
+
+ return pGrfNode;
+}
+/******************************************************************************
+ * liefert Pointer auf eine Graphic, wenn CurCrsr->GetPoint() auf
+ * einen SwGrfNode zeigt (und GetMark nicht gesetzt ist
+ * oder auf die gleiche Graphic zeigt)
+ ******************************************************************************/
+
+const Graphic* SwEditShell::GetGraphic( sal_Bool bWait ) const
+{
+ SwGrfNode* pGrfNode = _GetGrfNode();
+ const Graphic* pGrf( 0L );
+ if ( pGrfNode )
+ {
+ pGrf = &(pGrfNode->GetGrf());
+ // --> #i73788#
+ // no load of linked graphic, if its not needed now (bWait = sal_False).
+ if ( bWait )
+ {
+ if( pGrf->IsSwapOut() ||
+ ( pGrfNode->IsLinkedFile() && GRAPHIC_DEFAULT == pGrf->GetType() ) )
+ {
+#if OSL_DEBUG_LEVEL > 1
+ OSL_ENSURE( pGrfNode->SwapIn( bWait ) || !bWait, "Grafik konnte nicht geladen werden" );
+#else
+ pGrfNode->SwapIn( bWait );
+#endif
+ }
+ }
+ else
+ {
+ if ( pGrf->IsSwapOut() && !pGrfNode->IsLinkedFile() )
+ {
+#if OSL_DEBUG_LEVEL > 1
+ OSL_ENSURE( pGrfNode->SwapIn( bWait ) || !bWait, "Grafik konnte nicht geladen werden" );
+#else
+ pGrfNode->SwapIn( bWait );
+#endif
+ }
+ }
+ // <--
+ }
+ return pGrf;
+ // <--
+}
+
+sal_Bool SwEditShell::IsGrfSwapOut( sal_Bool bOnlyLinked ) const
+{
+ SwGrfNode *pGrfNode = _GetGrfNode();
+ return pGrfNode &&
+ (bOnlyLinked ? ( pGrfNode->IsLinkedFile() &&
+ ( GRAPHIC_DEFAULT == pGrfNode->GetGrfObj().GetType()||
+ pGrfNode->GetGrfObj().IsSwappedOut()))
+ : pGrfNode->GetGrfObj().IsSwappedOut());
+}
+
+const GraphicObject* SwEditShell::GetGraphicObj() const
+{
+ SwGrfNode* pGrfNode = _GetGrfNode();
+ return pGrfNode ? &(pGrfNode->GetGrfObj()) : 0L;
+}
+
+sal_uInt16 SwEditShell::GetGraphicType() const
+{
+ SwGrfNode *pGrfNode = _GetGrfNode();
+ return static_cast<sal_uInt16>(pGrfNode ? pGrfNode->GetGrfObj().GetType() : GRAPHIC_NONE);
+}
+
+/******************************************************************************
+ * liefert die Groesse der Graphic, wenn CurCrsr->GetPoint() auf
+ * einen SwGrfNode zeigt (und GetMark nicht gesetzt ist
+ * oder auf die gleiche Graphic zeigt)
+ ******************************************************************************/
+
+sal_Bool SwEditShell::GetGrfSize(Size& rSz) const
+{
+ SwNoTxtNode* pNoTxtNd;
+ SwPaM* pCurrentCrsr = GetCrsr();
+ if( ( !pCurrentCrsr->HasMark()
+ || pCurrentCrsr->GetPoint()->nNode == pCurrentCrsr->GetMark()->nNode )
+ && 0 != ( pNoTxtNd = pCurrentCrsr->GetNode()->GetNoTxtNode() ) )
+ {
+ rSz = pNoTxtNd->GetTwipSize();
+ return sal_True;
+ }
+ return sal_False;
+
+}
+/******************************************************************************
+ * erneutes Einlesen, falls Graphic nicht Ok ist. Die
+ * aktuelle wird durch die neue ersetzt.
+ ******************************************************************************/
+
+void SwEditShell::ReRead( const String& rGrfName, const String& rFltName,
+ const Graphic* pGraphic, const GraphicObject* pGrfObj )
+{
+ StartAllAction();
+ pDoc->ReRead( *GetCrsr(), rGrfName, rFltName, pGraphic, pGrfObj );
+ EndAllAction();
+}
+
+
+/******************************************************************************
+ * liefert den Namen und den FilterNamen einer Graphic, wenn der Cursor
+ * auf einer Graphic steht
+ * Ist ein String-Ptr != 0 dann returne den entsp. Namen
+ ******************************************************************************/
+
+
+void SwEditShell::GetGrfNms( String* pGrfName, String* pFltName,
+ const SwFlyFrmFmt* pFmt ) const
+{
+ OSL_ENSURE( pGrfName || pFltName, "was wird denn nun erfragt?" );
+ if( pFmt )
+ GetDoc()->GetGrfNms( *pFmt, pGrfName, pFltName );
+ else
+ {
+ SwGrfNode *pGrfNode = _GetGrfNode();
+ if( pGrfNode && pGrfNode->IsLinkedFile() )
+ pGrfNode->GetFileFilterNms( pGrfName, pFltName );
+ }
+}
+
+
+const PolyPolygon *SwEditShell::GetGraphicPolygon() const
+{
+ SwNoTxtNode *pNd = GetCrsr()->GetNode()->GetNoTxtNode();
+ return pNd->HasContour();
+}
+
+
+void SwEditShell::SetGraphicPolygon( const PolyPolygon *pPoly )
+{
+ SwNoTxtNode *pNd = GetCrsr()->GetNode()->GetNoTxtNode();
+ StartAllAction();
+ pNd->SetContour( pPoly );
+ SwFlyFrm *pFly = (SwFlyFrm*)pNd->getLayoutFrm(GetLayout())->GetUpper();
+ const SwFmtSurround &rSur = pFly->GetFmt()->GetSurround();
+ pFly->GetFmt()->NotifyClients( (SwFmtSurround*)&rSur, (SwFmtSurround*)&rSur );
+ GetDoc()->SetModified();
+ EndAllAction();
+}
+
+void SwEditShell::ClearAutomaticContour()
+{
+ SwNoTxtNode *pNd = GetCrsr()->GetNode()->GetNoTxtNode();
+ OSL_ENSURE( pNd, "is no NoTxtNode!" );
+ if( pNd->HasAutomaticContour() )
+ {
+ StartAllAction();
+ pNd->SetContour( NULL, sal_False );
+ SwFlyFrm *pFly = (SwFlyFrm*)pNd->getLayoutFrm(GetLayout())->GetUpper();
+ const SwFmtSurround &rSur = pFly->GetFmt()->GetSurround();
+ pFly->GetFmt()->NotifyClients( (SwFmtSurround*)&rSur, (SwFmtSurround*)&rSur );
+ GetDoc()->SetModified();
+ EndAllAction();
+ }
+}
+
+/******************************************************************************
+ * liefert Pointer auf ein SvInPlaceObjectRef, wenn CurCrsr->GetPoint() auf
+ * einen SwOLENode zeigt (und GetMark nicht gesetzt ist
+ * oder auf das gleiche SvInPlaceObjectRef zeigt)
+ * besorgt den Pointer vom Doc wenn das Objekt per Namen gesucht werden
+ * soll
+ ******************************************************************************/
+
+svt::EmbeddedObjectRef& SwEditShell::GetOLEObject() const
+{
+ OSL_ENSURE( CNT_OLE == GetCntType(), "GetOLEObj: kein OLENode." );
+ OSL_ENSURE( !GetCrsr()->HasMark() ||
+ (GetCrsr()->HasMark() &&
+ GetCrsr()->GetPoint()->nNode == GetCrsr()->GetMark()->nNode),
+ "GetOLEObj: kein OLENode." );
+
+ SwOLENode *pOLENode = GetCrsr()->GetNode()->GetOLENode();
+ OSL_ENSURE( pOLENode, "GetOLEObj: kein OLENode." );
+ SwOLEObj& rOObj = pOLENode->GetOLEObj();
+ return rOObj.GetObject();
+}
+
+
+sal_Bool SwEditShell::HasOLEObj( const String &rName ) const
+{
+ SwStartNode *pStNd;
+ SwNodeIndex aIdx( *GetNodes().GetEndOfAutotext().StartOfSectionNode(), 1 );
+ while ( 0 != (pStNd = aIdx.GetNode().GetStartNode()) )
+ {
+ aIdx++;
+ SwNode& rNd = aIdx.GetNode();
+ if( rNd.IsOLENode() &&
+ rName == ((SwOLENode&)rNd).GetChartTblName() &&
+ ((SwOLENode&)rNd).getLayoutFrm( GetLayout() ) )
+ return sal_True;
+
+ aIdx.Assign( *pStNd->EndOfSectionNode(), + 1 );
+ }
+ return sal_False;
+}
+
+
+void SwEditShell::SetChartName( const String &rName )
+{
+ SwOLENode *pONd = GetCrsr()->GetNode()->GetOLENode();
+ OSL_ENSURE( pONd, "ChartNode not found" );
+ pONd->SetChartTblName( rName );
+}
+
+void SwEditShell::UpdateCharts( const String &rName )
+{
+ GetDoc()->UpdateCharts( rName );
+}
+
+
+/******************************************************************************
+ * Aenderung des Tabellennamens
+ ******************************************************************************/
+
+void SwEditShell::SetTableName( SwFrmFmt& rTblFmt, const String &rNewName )
+{
+ GetDoc()->SetTableName( rTblFmt, rNewName );
+}
+
+// erfragen des akt. Wortes
+
+String SwEditShell::GetCurWord()
+{
+ const SwPaM& rPaM = *GetCrsr();
+ const SwTxtNode* pNd = rPaM.GetNode()->GetTxtNode();
+ String aString = pNd ?
+ pNd->GetCurWord(rPaM.GetPoint()->nContent.GetIndex()) :
+ aEmptyStr;
+ return aString;
+}
+
+/****************************************************************************
+ * void SwEditShell::UpdateDocStat( SwDocStat& rStat )
+ ****************************************************************************/
+
+
+void SwEditShell::UpdateDocStat( SwDocStat& rStat )
+{
+ StartAllAction();
+ GetDoc()->UpdateDocStat( rStat );
+ EndAllAction();
+}
+
+// OPT: eddocinl.cxx
+
+
+ // returne zum Namen die im Doc gesetzte Referenz
+const SwFmtRefMark* SwEditShell::GetRefMark( const String& rName ) const
+{
+ return GetDoc()->GetRefMark( rName );
+}
+
+ // returne die Namen aller im Doc gesetzten Referenzen
+sal_uInt16 SwEditShell::GetRefMarks( SvStringsDtor* pStrings ) const
+{
+ return GetDoc()->GetRefMarks( pStrings );
+}
+
+/******************************************************************************
+ * DropCap-SS
+ ******************************************************************************/
+
+
+String SwEditShell::GetDropTxt( const sal_uInt16 nChars ) const
+{
+ /**
+ * pb: made changes for #i74939#
+ *
+ * always return a string even though there is a selection
+ */
+
+ String aTxt;
+ SwPaM* pCrsr = GetCrsr();
+ if ( IsMultiSelection() )
+ {
+ // if a multi selection exists, search for the first line
+ // -> it is the cursor with the lowest index
+ sal_uLong nIndex = pCrsr->GetMark()->nNode.GetIndex();
+ bool bPrev = true;
+ SwPaM* pLast = pCrsr;
+ SwPaM* pTemp = pCrsr;
+ while ( bPrev )
+ {
+ SwPaM* pPrev2 = dynamic_cast< SwPaM* >( pTemp->GetPrev() );
+ bPrev = ( pPrev2 && pPrev2 != pLast );
+ if ( bPrev )
+ {
+ pTemp = pPrev2;
+ sal_uLong nTemp = pPrev2->GetMark()->nNode.GetIndex();
+ if ( nTemp < nIndex )
+ {
+ nIndex = nTemp;
+ pCrsr = pPrev2;
+ }
+ }
+ }
+ }
+
+ SwTxtNode* pTxtNd = pCrsr->GetNode( !pCrsr->HasMark() )->GetTxtNode();
+ if( pTxtNd )
+ {
+ xub_StrLen nDropLen = pTxtNd->GetDropLen( nChars );
+ if( nDropLen )
+ aTxt = pTxtNd->GetTxt().Copy( 0, nDropLen );
+ }
+
+ return aTxt;
+}
+
+void SwEditShell::ReplaceDropTxt( const String &rStr )
+{
+ SwPaM* pCrsr = GetCrsr();
+ if( pCrsr->GetPoint()->nNode == pCrsr->GetMark()->nNode &&
+ pCrsr->GetNode()->GetTxtNode()->IsTxtNode() )
+ {
+ StartAllAction();
+
+ const SwNodeIndex& rNd = pCrsr->GetPoint()->nNode;
+ SwPaM aPam( rNd, rStr.Len(), rNd, 0 );
+ if( !GetDoc()->Overwrite( aPam, rStr ) )
+ {
+ OSL_FAIL( "Doc->Overwrite(Str) failed." );
+ }
+
+ EndAllAction();
+ }
+}
+
+
+String SwEditShell::Calculate()
+{
+ String aFormel; // die entgueltige Formel
+ SwPaM *pPaMLast = (SwPaM*)GetCrsr()->GetNext(),
+ *pPaM = pPaMLast; // die Pointer auf Cursor
+ SwCalc aCalc( *GetDoc() );
+ const CharClass& rCC = GetAppCharClass();
+
+ do {
+ SwTxtNode* pTxtNd = pPaM->GetNode()->GetTxtNode();
+ if(pTxtNd)
+ {
+ const SwPosition *pStart = pPaM->Start(), *pEnd = pPaM->End();
+ xub_StrLen nStt = pStart->nContent.GetIndex();
+ String aStr = pTxtNd->GetExpandTxt( nStt, pEnd->nContent.
+ GetIndex() - nStt );
+
+ rCC.toLower( aStr );
+
+ sal_Unicode ch;
+ sal_Bool bValidFlds = sal_False;
+ xub_StrLen nPos = 0;
+
+ while( nPos < aStr.Len() )
+ {
+ ch = aStr.GetChar( nPos++ );
+ if( rCC.isLetter( aStr, nPos-1 ) || ch == '_' )
+ {
+ xub_StrLen nTmpStt = nPos-1;
+ while( nPos < aStr.Len() &&
+ 0 != ( ch = aStr.GetChar( nPos++ )) &&
+ (rCC.isLetterNumeric( aStr, nPos - 1 ) ||
+ ch == '_'|| ch == '.' ))
+ ;
+
+ if( nPos < aStr.Len() )
+ --nPos;
+
+ String sVar( aStr.Copy( nTmpStt, nPos - nTmpStt ));
+ if( !::FindOperator( sVar ) &&
+ (::Find( sVar, aCalc.GetVarTable(),TBLSZ) ||
+ aCalc.VarLook( sVar )) )
+ {
+ if( !bValidFlds )
+ {
+ GetDoc()->FldsToCalc( aCalc,
+ pStart->nNode.GetIndex(),
+ pStart->nContent.GetIndex() );
+ bValidFlds = sal_True;
+ }
+ (( aFormel += '(' ) +=
+ aCalc.GetStrResult( aCalc.VarLook( sVar )
+ ->nValue )) += ')';
+ }
+ else
+ aFormel += sVar;
+ }
+ else
+ aFormel += ch;
+ }
+ }
+ } while( pPaMLast != (pPaM = (SwPaM*)pPaM->GetNext()) );
+
+ return aCalc.GetStrResult( aCalc.Calculate(aFormel) );
+}
+
+
+sfx2::LinkManager& SwEditShell::GetLinkManager()
+{
+ return pDoc->GetLinkManager();
+}
+
+
+void *SwEditShell::GetIMapInventor() const
+{
+ //Als eindeutige Identifikation sollte der Node, auf dem der Crsr steht
+ //genuegen.
+ return (void*)GetCrsr()->GetNode();
+}
+
+// --> OD 2007-03-01 #i73788#
+// remove default parameter, because method is always called this default value
+Graphic SwEditShell::GetIMapGraphic() const
+{
+ //Liefert immer eine Graphic, wenn der Crsr in einem Fly steht.
+ SET_CURR_SHELL( (ViewShell*)this );
+ Graphic aRet;
+ SwPaM* pCrsr = GetCrsr();
+ if ( !pCrsr->HasMark() )
+ {
+ SwNode *pNd =pCrsr->GetNode();
+ if( pNd->IsGrfNode() )
+ {
+ const Graphic& rGrf = ((SwGrfNode*)pNd)->GetGrf();
+ if( rGrf.IsSwapOut() || ( ((SwGrfNode*)pNd)->IsLinkedFile() &&
+ GRAPHIC_DEFAULT == rGrf.GetType() ) )
+ {
+#if OSL_DEBUG_LEVEL > 1
+ OSL_ENSURE( ((SwGrfNode*)pNd)->SwapIn( sal_True ), "Grafik konnte nicht geladen werden" );
+#else
+ ((SwGrfNode*)pNd)->SwapIn( sal_True );
+#endif
+ }
+ aRet = rGrf;
+ }
+ else if ( pNd->IsOLENode() )
+ {
+ aRet = *((SwOLENode*)pNd)->GetGraphic();
+ }
+ else
+ {
+ SwFlyFrm* pFlyFrm = pNd->GetCntntNode()->getLayoutFrm( GetLayout() )->FindFlyFrm();
+ if(pFlyFrm)
+ aRet = pFlyFrm->GetFmt()->MakeGraphic();
+ }
+ }
+ return aRet;
+}
+
+
+sal_Bool SwEditShell::InsertURL( const SwFmtINetFmt& rFmt, const String& rStr, sal_Bool bKeepSelection )
+{
+ // URL und Hinweistext (direkt oder via Selektion) notwendig
+ if( !rFmt.GetValue().Len() || ( !rStr.Len() && !HasSelection() ) )
+ return sal_False;
+ StartAllAction();
+ GetDoc()->GetIDocumentUndoRedo().StartUndo( UNDO_UI_INSERT_URLTXT, NULL);
+ sal_Bool bInsTxt = sal_True;
+
+ if( rStr.Len() )
+ {
+ SwPaM* pCrsr = GetCrsr();
+ if( pCrsr->HasMark() && *pCrsr->GetPoint() != *pCrsr->GetMark() )
+ {
+ // Selection vorhanden, MehrfachSelektion?
+ sal_Bool bDelTxt = sal_True;
+ if( pCrsr->GetNext() == pCrsr )
+ {
+ // einfach Selection -> Text ueberpruefen
+ String sTxt( GetSelTxt() );
+ sTxt.EraseTrailingChars();
+ if( sTxt == rStr )
+ bDelTxt = bInsTxt = sal_False;
+ }
+ else if( rFmt.GetValue() == rStr ) // Name und URL gleich?
+ bDelTxt = bInsTxt = sal_False;
+
+ if( bDelTxt )
+ Delete();
+ }
+ else if( pCrsr->GetNext() != pCrsr && rFmt.GetValue() == rStr )
+ bInsTxt = sal_False;
+
+ if( bInsTxt )
+ {
+ Insert2( rStr );
+ SetMark();
+ ExtendSelection( sal_False, rStr.Len() );
+ }
+ }
+ else
+ bInsTxt = sal_False;
+
+ SetAttr( rFmt );
+ if (bInsTxt && !IsCrsrPtAtEnd())
+ SwapPam();
+ if(!bKeepSelection)
+ ClearMark();
+ if( bInsTxt )
+ DontExpandFmt();
+ GetDoc()->GetIDocumentUndoRedo().EndUndo( UNDO_UI_INSERT_URLTXT, NULL );
+ EndAllAction();
+ return sal_True;
+}
+
+
+sal_uInt16 SwEditShell::GetINetAttrs( SwGetINetAttrs& rArr )
+{
+ if( rArr.Count() )
+ rArr.DeleteAndDestroy( 0, rArr.Count() );
+
+ const SwTxtNode* pTxtNd;
+ const SwCharFmts* pFmts = GetDoc()->GetCharFmts();
+ for( sal_uInt16 n = pFmts->Count(); 1 < n; )
+ {
+ SwIterator<SwTxtINetFmt,SwCharFmt> aIter(*(*pFmts)[--n]);
+ for( SwTxtINetFmt* pFnd = aIter.First(); pFnd; pFnd = aIter.Next() )
+ {
+ if( 0 != ( pTxtNd = pFnd->GetpTxtNode()) &&
+ pTxtNd->GetNodes().IsDocNodes() )
+ {
+ SwTxtINetFmt& rAttr = *pFnd;
+ String sTxt( pTxtNd->GetExpandTxt( *rAttr.GetStart(),
+ *rAttr.GetEnd() - *rAttr.GetStart() ) );
+
+ sTxt.EraseAllChars( 0x0a );
+ sTxt.EraseLeadingChars().EraseTrailingChars();
+
+ if( sTxt.Len() )
+ {
+ SwGetINetAttr* pNew = new SwGetINetAttr( sTxt, rAttr );
+ rArr.C40_INSERT( SwGetINetAttr, pNew, rArr.Count() );
+ }
+ }
+ }
+ }
+ return rArr.Count();
+}
+
+
+ // ist der Cursor in eine INetAttribut, dann wird das komplett
+ // geloescht; inclusive des Hinweistextes (wird beim Drag&Drop gebraucht)
+sal_Bool SwEditShell::DelINetAttrWithText()
+{
+ sal_Bool bRet = SelectTxtAttr( RES_TXTATR_INETFMT, sal_False );
+ if( bRet )
+ DeleteSel( *GetCrsr() );
+ return bRet;
+}
+
+
+// setzen an den Textzeichenattributen das DontExpand-Flag
+sal_Bool SwEditShell::DontExpandFmt()
+{
+ sal_Bool bRet = sal_False;
+ if( !IsTableMode() && GetDoc()->DontExpandFmt( *GetCrsr()->GetPoint() ))
+ {
+ bRet = sal_True;
+ CallChgLnk();
+ }
+ return bRet;
+}
+
+SvNumberFormatter* SwEditShell::GetNumberFormatter()
+{
+ return GetDoc()->GetNumberFormatter();
+}
+
+sal_Bool SwEditShell::RemoveInvisibleContent()
+{
+ StartAllAction();
+ sal_Bool bRet = GetDoc()->RemoveInvisibleContent();
+ EndAllAction();
+ return bRet;
+}
+sal_Bool SwEditShell::ConvertFieldsToText()
+{
+ StartAllAction();
+ sal_Bool bRet = GetDoc()->ConvertFieldsToText();
+ EndAllAction();
+ return bRet;
+}
+void SwEditShell::SetNumberingRestart()
+{
+ StartAllAction();
+ Push();
+ //iterate over all text contents - body, frames, header, footer, footnote text
+ SwPaM* pCrsr = GetCrsr();
+ for(sal_uInt16 i = 0; i < 2; i++)
+ {
+ if(!i)
+ MakeFindRange(DOCPOS_START, DOCPOS_END, pCrsr); //body content
+ else
+ MakeFindRange(DOCPOS_OTHERSTART, DOCPOS_OTHEREND, pCrsr); //extra content
+ SwPosition* pSttPos = pCrsr->Start(), *pEndPos = pCrsr->End();
+ sal_uLong nCurrNd = pSttPos->nNode.GetIndex();
+ sal_uLong nEndNd = pEndPos->nNode.GetIndex();
+ if( nCurrNd <= nEndNd )
+ {
+ SwCntntFrm* pCntFrm;
+ sal_Bool bGoOn = sal_True;
+ //iterate over all paragraphs
+ while( bGoOn )
+ {
+ SwNode* pNd = GetDoc()->GetNodes()[ nCurrNd ];
+ switch( pNd->GetNodeType() )
+ {
+ case ND_TEXTNODE:
+ if( 0 != ( pCntFrm = ((SwTxtNode*)pNd)->getLayoutFrm( GetLayout() )) )
+ {
+ //jump over hidden frames - ignore protection!
+ if( !((SwTxtFrm*)pCntFrm)->IsHiddenNow() )
+ {
+ //if the node is numbered and the starting value of the numbering equals the
+ //start value of the numbering rule then set this value as hard starting value
+
+ //get the node num
+ // OD 2005-11-09
+ SwTxtNode* pTxtNd( static_cast<SwTxtNode*>(pNd) );
+ SwNumRule* pNumRule( pTxtNd->GetNumRule() );
+
+ if ( pNumRule && pTxtNd->GetNum() &&
+ ( pTxtNd->HasNumber() || pTxtNd->HasBullet() ) &&
+ pTxtNd->IsCountedInList() &&
+ !pTxtNd->IsListRestart() &&
+ pTxtNd->GetNum()->GetNumber() ==
+ pNumRule->Get( static_cast<sal_uInt16>(pTxtNd->GetActualListLevel()) ).GetStart() )
+ {
+ //now set a the start value as attribute
+ SwPosition aCurrentNode(*pNd);
+ GetDoc()->SetNumRuleStart( aCurrentNode, sal_True );
+ }
+ }
+ }
+ break;
+ case ND_SECTIONNODE:
+ // jump over hidden sections - ignore protection!
+ if(((SwSectionNode*)pNd)->GetSection().IsHidden() )
+ nCurrNd = pNd->EndOfSectionIndex();
+ break;
+ case ND_ENDNODE:
+ {
+ break;
+ }
+ }
+
+ bGoOn = nCurrNd < nEndNd;
+ ++nCurrNd;
+ }
+ }
+ }
+
+
+ Pop(sal_False);
+ EndAllAction();
+}
+
+sal_uInt16 SwEditShell::GetLineCount( sal_Bool bActPos )
+{
+ sal_uInt16 nRet = 0;
+ CalcLayout();
+ SwPaM* pPam = GetCrsr();
+ SwNodeIndex& rPtIdx = pPam->GetPoint()->nNode;
+ SwNodeIndex aStart( rPtIdx );
+ SwCntntNode* pCNd;
+ SwCntntFrm *pCntFrm = 0;
+ sal_uLong nTmpPos;
+
+ if( !bActPos )
+ aStart = 0;
+ else if( rPtIdx > ( nTmpPos = GetDoc()->GetNodes().GetEndOfExtras().GetIndex()) )
+ // BodyBereich => Start ist EndOfIcons + 1
+ aStart = nTmpPos + 1;
+ else
+ {
+ if( 0 != ( pCNd = pPam->GetCntntNode() ) &&
+ 0 != ( pCntFrm = pCNd->getLayoutFrm( GetLayout() ) ) )
+ {
+ const SwStartNode *pTmp;
+ if( pCntFrm->IsInFly() ) // Fly
+ pTmp = pCNd->FindFlyStartNode();
+ else if( pCntFrm->IsInFtn() ) // Footnote
+ pTmp = pCNd->FindFootnoteStartNode();
+ else
+ { // Footer/Header
+ const sal_uInt16 nTyp = FRM_HEADER | FRM_FOOTER;
+ SwFrm* pFrm = pCntFrm;
+ while( pFrm && !(pFrm->GetType() & nTyp) )
+ pFrm = pFrm->GetUpper();
+ OSL_ENSURE( pFrm, "Wo bin ich?" );
+ if( pFrm && ( pFrm->GetType() & FRM_FOOTER ) )
+ pTmp = pCNd->FindFooterStartNode();
+ else
+ pTmp = pCNd->FindHeaderStartNode();
+ }
+ OSL_ENSURE( pTmp, "Missing StartNode" );
+ aStart = *pTmp;
+ }
+ OSL_ENSURE( pCNd && pCntFrm, "Missing Layout-Information" );
+ }
+
+ while( 0 != ( pCNd = GetDoc()->GetNodes().GoNextSection(
+ &aStart, sal_True, sal_False )) && ( !bActPos || aStart <= rPtIdx ) )
+ {
+ if( 0 != ( pCntFrm = pCNd->getLayoutFrm( GetLayout() ) ) && pCntFrm->IsTxtFrm() )
+ {
+ xub_StrLen nActPos = bActPos && aStart == rPtIdx ?
+ pPam->GetPoint()->nContent.GetIndex() : USHRT_MAX;
+ nRet = nRet + ((SwTxtFrm*)pCntFrm)->GetLineCount( nActPos );
+ }
+ }
+ return nRet;
+}
+
+long SwEditShell::CompareDoc( const SwDoc& rDoc )
+{
+ StartAllAction();
+ long nRet = GetDoc()->CompareDoc( rDoc );
+ EndAllAction();
+ return nRet;
+}
+
+long SwEditShell::MergeDoc( const SwDoc& rDoc )
+{
+ StartAllAction();
+ long nRet = GetDoc()->MergeDoc( rDoc );
+ EndAllAction();
+ return nRet;
+}
+
+
+const SwFtnInfo& SwEditShell::GetFtnInfo() const
+{
+ return GetDoc()->GetFtnInfo();
+}
+
+void SwEditShell::SetFtnInfo(const SwFtnInfo& rInfo)
+{
+ StartAllAction();
+ SET_CURR_SHELL( this );
+ GetDoc()->SetFtnInfo(rInfo);
+ CallChgLnk();
+ EndAllAction();
+}
+
+const SwEndNoteInfo& SwEditShell::GetEndNoteInfo() const
+{
+ return GetDoc()->GetEndNoteInfo();
+}
+
+void SwEditShell::SetEndNoteInfo(const SwEndNoteInfo& rInfo)
+{
+ StartAllAction();
+ SET_CURR_SHELL( this );
+ GetDoc()->SetEndNoteInfo(rInfo);
+ EndAllAction();
+}
+
+const SwLineNumberInfo& SwEditShell::GetLineNumberInfo() const
+{
+ return GetDoc()->GetLineNumberInfo();
+}
+
+void SwEditShell::SetLineNumberInfo(const SwLineNumberInfo& rInfo)
+{
+ StartAllAction();
+ SET_CURR_SHELL( this );
+ GetDoc()->SetLineNumberInfo(rInfo);
+ AddPaintRect( GetLayout()->Frm() );
+ EndAllAction();
+}
+
+sal_uInt16 SwEditShell::GetLinkUpdMode(sal_Bool bDocSettings) const
+{
+ return getIDocumentSettingAccess()->getLinkUpdateMode( !bDocSettings );
+}
+
+void SwEditShell::SetLinkUpdMode( sal_uInt16 nMode )
+{
+ getIDocumentSettingAccess()->setLinkUpdateMode( nMode );
+}
+
+
+// Schnittstelle fuer die TextInputDaten - ( fuer die Texteingabe
+// von japanischen/chinesischen Zeichen)
+SwExtTextInput* SwEditShell::CreateExtTextInput(LanguageType eInputLanguage)
+{
+ SwExtTextInput* pRet = GetDoc()->CreateExtTextInput( *GetCrsr() );
+ pRet->SetLanguage(eInputLanguage);
+ pRet->SetOverwriteCursor( SwCrsrShell::IsOverwriteCrsr() );
+ return pRet;
+}
+
+String SwEditShell::DeleteExtTextInput( SwExtTextInput* pDel, sal_Bool bInsText )
+{
+ if( !pDel )
+ {
+ const SwPosition& rPos = *GetCrsr()->GetPoint();
+ pDel = GetDoc()->GetExtTextInput( rPos.nNode.GetNode(),
+ rPos.nContent.GetIndex() );
+ if( !pDel )
+ {
+ //JP 25.10.2001: under UNIX the cursor is moved before the Input-
+ // Engine event comes in. So take any - normally there
+ // exist only one at the time. -- Task 92016
+ pDel = GetDoc()->GetExtTextInput();
+ }
+ }
+ String sRet;
+ if( pDel )
+ {
+ rtl::OUString sTmp;
+ SwUnoCursorHelper::GetTextFromPam(*pDel, sTmp);
+ sRet = sTmp;
+ SET_CURR_SHELL( this );
+ StartAllAction();
+ pDel->SetInsText( bInsText );
+ SetOverwriteCrsr( pDel->IsOverwriteCursor() );
+ const SwPosition aPos( *pDel->GetPoint() );
+ GetDoc()->DeleteExtTextInput( pDel );
+
+ // In this case, the "replace" function did not set the cursor
+ // to the original position. Therefore we have to do this manually.
+ if ( ! bInsText && IsOverwriteCrsr() )
+ *GetCrsr()->GetPoint() = aPos;
+
+ EndAllAction();
+ }
+ return sRet;
+}
+
+void SwEditShell::SetExtTextInputData( const CommandExtTextInputData& rData )
+{
+ const SwPosition& rPos = *GetCrsr()->GetPoint();
+ SwExtTextInput* pInput = GetDoc()->GetExtTextInput( rPos.nNode.GetNode()
+ /*, rPos.nContent.GetIndex()*/ );
+ if( pInput )
+ {
+ StartAllAction();
+ SET_CURR_SHELL( this );
+
+ if( !rData.IsOnlyCursorChanged() )
+ pInput->SetInputData( rData );
+ // Cursor positionieren:
+ const SwPosition& rStt = *pInput->Start();
+ xub_StrLen nNewCrsrPos = rStt.nContent.GetIndex() + rData.GetCursorPos();
+
+ // zwar unschoen aber was hilfts
+ ShowCrsr();
+ long nDiff = nNewCrsrPos - rPos.nContent.GetIndex();
+ if( 0 > nDiff )
+ Left( (xub_StrLen)-nDiff, CRSR_SKIP_CHARS );
+ else if( 0 < nDiff )
+ Right( (xub_StrLen)nDiff, CRSR_SKIP_CHARS );
+
+ SetOverwriteCrsr( rData.IsCursorOverwrite() );
+
+ EndAllAction();
+
+ if( !rData.IsCursorVisible() ) // must be called after the EndAction
+ HideCrsr();
+ }
+}
+
+void SwEditShell::TransliterateText( sal_uInt32 nType )
+{
+ utl::TransliterationWrapper aTrans( ::comphelper::getProcessServiceFactory(), nType );
+ StartAllAction();
+ SET_CURR_SHELL( this );
+
+ SwPaM* pCrsr = GetCrsr();
+ if( pCrsr->GetNext() != pCrsr )
+ {
+ GetDoc()->GetIDocumentUndoRedo().StartUndo(UNDO_EMPTY, NULL);
+ FOREACHPAM_START( this )
+
+ if( PCURCRSR->HasMark() )
+ GetDoc()->TransliterateText( *PCURCRSR, aTrans );
+
+ FOREACHPAM_END()
+ GetDoc()->GetIDocumentUndoRedo().EndUndo(UNDO_EMPTY, NULL);
+ }
+ else
+ GetDoc()->TransliterateText( *pCrsr, aTrans );
+
+ EndAllAction();
+}
+
+void SwEditShell::CountWords( SwDocStat& rStat ) const
+{
+ FOREACHPAM_START( this )
+
+ if( PCURCRSR->HasMark() )
+ GetDoc()->CountWords( *PCURCRSR, rStat );
+
+ FOREACHPAM_END()
+}
+
+void SwEditShell::ApplyViewOptions( const SwViewOption &rOpt )
+{
+ SwCrsrShell::StartAction();
+ ViewShell::ApplyViewOptions( rOpt );
+ SwEditShell::EndAction();
+}
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/edit/edlingu.cxx b/sw/source/core/edit/edlingu.cxx
new file mode 100644
index 000000000000..f90ebe45748f
--- /dev/null
+++ b/sw/source/core/edit/edlingu.cxx
@@ -0,0 +1,1927 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+#include <com/sun/star/linguistic2/ProofreadingResult.hpp>
+#include <com/sun/star/linguistic2/XProofreader.hpp>
+#include <com/sun/star/linguistic2/XProofreadingIterator.hpp>
+#include <com/sun/star/text/XFlatParagraph.hpp>
+
+#include <unoflatpara.hxx>
+
+#include <comcore.hrc>
+#include <hintids.hxx>
+#include <linguistic/lngprops.hxx>
+#include <vcl/msgbox.hxx>
+#include <editeng/unolingu.hxx>
+#include <editeng/svxacorr.hxx>
+#include <editeng/langitem.hxx>
+#include <editeng/SpellPortions.hxx>
+#include <editeng/scripttypeitem.hxx>
+#include <charatr.hxx>
+#include <editsh.hxx>
+#include <doc.hxx>
+#include <IDocumentUndoRedo.hxx>
+#include <rootfrm.hxx> // SwRootFrm
+#include <pam.hxx>
+#include <swundo.hxx> // fuer die UndoIds
+#include <ndtxt.hxx> // AdjHyphPos
+#include <viewopt.hxx> // HyphStart/End
+#include <viscrs.hxx> // SwShellCrsr
+#include <SwGrammarMarkUp.hxx> // SwWrongList
+#include <mdiexp.hxx> // Statusanzeige
+#include <statstr.hrc> // StatLine-String
+#include <cntfrm.hxx>
+#include <crsskip.hxx>
+#include <splargs.hxx>
+#include <redline.hxx> // SwRedline
+#include <docary.hxx> // SwRedlineTbl
+#include <docsh.hxx>
+#include <txatbase.hxx>
+#include <txtfrm.hxx>
+
+using namespace ::svx;
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::beans;
+using namespace ::com::sun::star::linguistic2;
+
+/*************************************************************************
+ * class SwLinguIter
+ *************************************************************************/
+
+class SwLinguIter
+{
+ SwEditShell *pSh;
+ SwPosition *pStart;
+ SwPosition *pEnd;
+ SwPosition *pCurr;
+ SwPosition *pCurrX;
+ sal_uInt16 nCrsrCnt;
+public:
+ SwLinguIter();
+
+ inline SwEditShell *GetSh() { return pSh; }
+ inline const SwEditShell *GetSh() const { return pSh; }
+
+ inline const SwPosition *GetEnd() const { return pEnd; }
+ inline void SetEnd( SwPosition* pNew ){ delete pEnd; pEnd = pNew; }
+
+ inline const SwPosition *GetStart() const { return pStart; }
+ inline void SetStart( SwPosition* pNew ){ delete pStart; pStart = pNew; }
+
+ inline const SwPosition *GetCurr() const { return pCurr; }
+ inline void SetCurr( SwPosition* pNew ){ delete pCurr; pCurr = pNew; }
+
+ inline const SwPosition *GetCurrX() const { return pCurrX; }
+ inline void SetCurrX( SwPosition* pNew ){ delete pCurrX; pCurrX = pNew; }
+
+ inline sal_uInt16& GetCrsrCnt(){ return nCrsrCnt; }
+
+ // Der UI-Bauchladen:
+ void _Start( SwEditShell *pSh, SwDocPositions eStart,
+ SwDocPositions eEnd );
+ void _End(bool bRestoreSelection = true);
+};
+
+/*************************************************************************
+ * class SwSpellIter
+ *************************************************************************/
+
+// #i18881# to be able to identify the postions of the changed words
+// the content positions of each portion need to be saved
+struct SpellContentPosition
+{
+ sal_uInt16 nLeft;
+ sal_uInt16 nRight;
+};
+typedef std::vector<SpellContentPosition> SpellContentPositions;
+class SwSpellIter : public SwLinguIter
+{
+ uno::Reference< XSpellChecker1 > xSpeller;
+ ::svx::SpellPortions aLastPortions;
+
+ SpellContentPositions aLastPositions;
+ bool bBackToStartOfSentence;
+ bool bMoveToEndOfSentence;
+
+
+ void CreatePortion(uno::Reference< XSpellAlternatives > xAlt,
+ linguistic2::ProofreadingResult* pGrammarResult,
+ bool bIsField, bool bIsHidden);
+
+ void AddPortion(uno::Reference< XSpellAlternatives > xAlt,
+ linguistic2::ProofreadingResult* pGrammarResult,
+ const SpellContentPositions& rDeletedRedlines);
+public:
+ SwSpellIter() :
+ bBackToStartOfSentence(false), bMoveToEndOfSentence(false) {}
+
+ void Start( SwEditShell *pSh, SwDocPositions eStart, SwDocPositions eEnd );
+
+ uno::Any Continue( sal_uInt16* pPageCnt, sal_uInt16* pPageSt );
+
+ bool SpellSentence(::svx::SpellPortions& rPortions, bool bIsGrammarCheck);
+ void ToSentenceStart();
+ const ::svx::SpellPortions GetLastPortions() const { return aLastPortions;}
+ SpellContentPositions GetLastPositions() const {return aLastPositions;}
+ void ContinueAfterThisSentence() { bMoveToEndOfSentence = true; }
+};
+
+/*************************************************************************
+ * class SwConvIter
+ * used for text conversion
+ *************************************************************************/
+
+class SwConvIter : public SwLinguIter
+{
+ SwConversionArgs &rArgs;
+public:
+ SwConvIter( SwConversionArgs &rConvArgs ) :
+ rArgs( rConvArgs )
+ {}
+
+ void Start( SwEditShell *pSh, SwDocPositions eStart, SwDocPositions eEnd );
+
+ uno::Any Continue( sal_uInt16* pPageCnt, sal_uInt16* pPageSt );
+};
+
+/*************************************************************************
+ * class SwHyphIter
+ *************************************************************************/
+
+class SwHyphIter : public SwLinguIter
+{
+ sal_Bool bOldIdle;
+ void DelSoftHyph( SwPaM &rPam );
+
+public:
+ SwHyphIter() : bOldIdle(sal_False) {}
+
+ void Start( SwEditShell *pSh, SwDocPositions eStart, SwDocPositions eEnd );
+ void End();
+
+ void Ignore();
+
+ uno::Any Continue( sal_uInt16* pPageCnt, sal_uInt16* pPageSt );
+
+ sal_Bool IsAuto();
+ void InsertSoftHyph( const xub_StrLen nHyphPos );
+ void ShowSelection();
+};
+
+static SwSpellIter* pSpellIter = 0;
+static SwConvIter* pConvIter = 0;
+static SwHyphIter* pHyphIter = 0;
+
+// Wir ersparen uns in Hyphenate ein GetFrm()
+// Achtung: in txtedt.cxx stehen extern-Deklarationen auf diese Pointer!
+const SwTxtNode *pLinguNode;
+ SwTxtFrm *pLinguFrm;
+
+/*************************************************************************
+ * SwLinguIter::SwLinguIter
+ *************************************************************************/
+
+SwLinguIter::SwLinguIter()
+ : pSh( 0 ), pStart( 0 ), pEnd( 0 ), pCurr( 0 ), pCurrX( 0 )
+{
+ // @@@ es fehlt: Sicherstellen der Reentrance, OSL_ENSURE( etc.
+}
+
+/*************************************************************************
+ * SwLinguIter::Start
+ *************************************************************************/
+
+
+
+void SwLinguIter::_Start( SwEditShell *pShell, SwDocPositions eStart,
+ SwDocPositions eEnd )
+{
+ // es fehlt: Sicherstellen der Reentrance, Locking
+ if( pSh )
+ return;
+
+ sal_Bool bSetCurr;
+
+ pSh = pShell;
+
+ SET_CURR_SHELL( pSh );
+
+ OSL_ENSURE( !pEnd, "LinguStart ohne End?");
+
+ SwPaM *pCrsr = pSh->GetCrsr();
+
+ if( pShell->HasSelection() || pCrsr != pCrsr->GetNext() )
+ {
+ bSetCurr = 0 != GetCurr();
+ nCrsrCnt = pSh->GetCrsrCnt();
+ if( pSh->IsTableMode() )
+ pSh->TblCrsrToCursor();
+
+ pSh->Push();
+ sal_uInt16 n;
+ for( n = 0; n < nCrsrCnt; ++n )
+ {
+ pSh->Push();
+ pSh->DestroyCrsr();
+ }
+ pSh->Pop( sal_False );
+ }
+ else
+ {
+ bSetCurr = sal_False;
+ nCrsrCnt = 1;
+ pSh->Push();
+ pSh->SetLinguRange( eStart, eEnd );
+ }
+
+ pCrsr = pSh->GetCrsr();
+ if ( *pCrsr->GetPoint() > *pCrsr->GetMark() )
+ pCrsr->Exchange();
+
+ pStart = new SwPosition( *pCrsr->GetPoint() );
+ pEnd = new SwPosition( *pCrsr->GetMark() );
+ if( bSetCurr )
+ {
+ SwPosition* pNew = new SwPosition( *GetStart() );
+ SetCurr( pNew );
+ pNew = new SwPosition( *pNew );
+ SetCurrX( pNew );
+ }
+
+ pCrsr->SetMark();
+
+ pLinguFrm = 0;
+ pLinguNode = 0;
+}
+
+/*************************************************************************
+ * SwLinguIter::End
+ *************************************************************************/
+
+
+
+void SwLinguIter::_End(bool bRestoreSelection)
+{
+ if( !pSh )
+ return;
+
+ OSL_ENSURE( pEnd, "SwEditShell::SpellEnd() ohne Start?");
+ if(bRestoreSelection)
+ {
+ while( nCrsrCnt-- )
+ pSh->Pop( sal_False );
+
+ pSh->KillPams();
+ pSh->ClearMark();
+ }
+ DELETEZ(pStart);
+ DELETEZ(pEnd);
+ DELETEZ(pCurr);
+ DELETEZ(pCurrX);
+
+ pSh = 0;
+}
+
+/*************************************************************************
+ * virtual SwSpellIter::Start()
+ *************************************************************************/
+
+
+
+void SwSpellIter::Start( SwEditShell *pShell, SwDocPositions eStart,
+ SwDocPositions eEnd )
+{
+ if( GetSh() )
+ return;
+
+ uno::Reference< beans::XPropertySet > xProp( ::GetLinguPropertySet() );
+ xSpeller = ::GetSpellChecker();
+ if ( xSpeller.is() )
+ _Start( pShell, eStart, eEnd );
+ aLastPortions.clear();
+ aLastPositions.clear();
+}
+
+/*************************************************************************
+ * SwSpellIter::Continue
+ *************************************************************************/
+
+// SwSpellIter::Continue ist das alte Original von
+// SwEditShell::SpellContinue()
+
+uno::Any SwSpellIter::Continue( sal_uInt16* pPageCnt, sal_uInt16* pPageSt )
+{
+ //!!
+ //!! Please check SwConvIter also when modifying this
+ //!!
+
+ uno::Any aSpellRet;
+ SwEditShell *pMySh = GetSh();
+ if( !pMySh )
+ return aSpellRet;
+
+ OSL_ENSURE( GetEnd(), "SwEditShell::SpellContinue() ohne Start?");
+
+ uno::Reference< uno::XInterface > xSpellRet;
+ sal_Bool bGoOn = sal_True;
+ do {
+ SwPaM *pCrsr = pMySh->GetCrsr();
+ if ( !pCrsr->HasMark() )
+ pCrsr->SetMark();
+
+ uno::Reference< beans::XPropertySet > xProp( GetLinguPropertySet() );
+ *pMySh->GetCrsr()->GetPoint() = *GetCurr();
+ *pMySh->GetCrsr()->GetMark() = *GetEnd();
+ pMySh->GetDoc()->Spell(*pMySh->GetCrsr(),
+ xSpeller, pPageCnt, pPageSt, false ) >>= xSpellRet;
+ bGoOn = GetCrsrCnt() > 1;
+ if( xSpellRet.is() )
+ {
+ bGoOn = sal_False;
+ SwPosition* pNewPoint = new SwPosition( *pCrsr->GetPoint() );
+ SwPosition* pNewMark = new SwPosition( *pCrsr->GetMark() );
+ SetCurr( pNewPoint );
+ SetCurrX( pNewMark );
+ }
+ if( bGoOn )
+ {
+ pMySh->Pop( sal_False );
+ pCrsr = pMySh->GetCrsr();
+ if ( *pCrsr->GetPoint() > *pCrsr->GetMark() )
+ pCrsr->Exchange();
+ SwPosition* pNew = new SwPosition( *pCrsr->GetPoint() );
+ SetStart( pNew );
+ pNew = new SwPosition( *pCrsr->GetMark() );
+ SetEnd( pNew );
+ pNew = new SwPosition( *GetStart() );
+ SetCurr( pNew );
+ pNew = new SwPosition( *pNew );
+ SetCurrX( pNew );
+ pCrsr->SetMark();
+ --GetCrsrCnt();
+ }
+ }while ( bGoOn );
+ aSpellRet <<= xSpellRet;
+ return aSpellRet;
+}
+
+/*************************************************************************
+ * virtual SwConvIter::Start()
+ *************************************************************************/
+
+
+
+void SwConvIter::Start( SwEditShell *pShell, SwDocPositions eStart,
+ SwDocPositions eEnd )
+{
+ if( GetSh() )
+ return;
+ _Start( pShell, eStart, eEnd );
+}
+
+/*************************************************************************
+ * SwConvIter::Continue
+ *************************************************************************/
+
+uno::Any SwConvIter::Continue( sal_uInt16* pPageCnt, sal_uInt16* pPageSt )
+{
+ //!!
+ //!! Please check SwSpellIter also when modifying this
+ //!!
+
+ uno::Any aConvRet( makeAny( rtl::OUString() ) );
+ SwEditShell *pMySh = GetSh();
+ if( !pMySh )
+ return aConvRet;
+
+ OSL_ENSURE( GetEnd(), "SwConvIter::Continue() ohne Start?");
+
+ rtl::OUString aConvText;
+ sal_Bool bGoOn = sal_True;
+ do {
+ SwPaM *pCrsr = pMySh->GetCrsr();
+ if ( !pCrsr->HasMark() )
+ pCrsr->SetMark();
+
+ *pMySh->GetCrsr()->GetPoint() = *GetCurr();
+ *pMySh->GetCrsr()->GetMark() = *GetEnd();
+
+ // call function to find next text portion to be converted
+ uno::Reference< linguistic2::XSpellChecker1 > xEmpty;
+ pMySh->GetDoc()->Spell( *pMySh->GetCrsr(),
+ xEmpty, pPageCnt, pPageSt, false, &rArgs ) >>= aConvText;
+
+ bGoOn = GetCrsrCnt() > 1;
+ if( aConvText.getLength() )
+ {
+ bGoOn = sal_False;
+ SwPosition* pNewPoint = new SwPosition( *pCrsr->GetPoint() );
+ SwPosition* pNewMark = new SwPosition( *pCrsr->GetMark() );
+
+ SetCurr( pNewPoint );
+ SetCurrX( pNewMark );
+ }
+ if( bGoOn )
+ {
+ pMySh->Pop( sal_False );
+ pCrsr = pMySh->GetCrsr();
+ if ( *pCrsr->GetPoint() > *pCrsr->GetMark() )
+ pCrsr->Exchange();
+ SwPosition* pNew = new SwPosition( *pCrsr->GetPoint() );
+ SetStart( pNew );
+ pNew = new SwPosition( *pCrsr->GetMark() );
+ SetEnd( pNew );
+ pNew = new SwPosition( *GetStart() );
+ SetCurr( pNew );
+ pNew = new SwPosition( *pNew );
+ SetCurrX( pNew );
+ pCrsr->SetMark();
+ --GetCrsrCnt();
+ }
+ }while ( bGoOn );
+ return makeAny( aConvText );
+}
+
+
+/*************************************************************************
+ * SwHyphIter
+ *************************************************************************/
+
+
+sal_Bool SwHyphIter::IsAuto()
+{
+ uno::Reference< beans::XPropertySet > xProp( ::GetLinguPropertySet() );
+ return xProp.is() ? *(sal_Bool*)xProp->getPropertyValue(
+ rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(UPN_IS_HYPH_AUTO)) ).getValue()
+ : sal_False;
+}
+
+
+void SwHyphIter::ShowSelection()
+{
+ SwEditShell *pMySh = GetSh();
+ if( pMySh )
+ {
+ pMySh->StartAction();
+ // Ganz fatal: durch das EndAction() werden Formatierungen
+ // angeregt, die dazu fuehren koennen, dass im Hyphenator
+ // neue Worte eingestellt werden. Deswegen sichern!
+ pMySh->EndAction();
+ }
+}
+
+/*************************************************************************
+ * virtual SwHyphIter::Start()
+ *************************************************************************/
+
+
+
+void SwHyphIter::Start( SwEditShell *pShell, SwDocPositions eStart, SwDocPositions eEnd )
+{
+ // robust
+ if( GetSh() || GetEnd() )
+ {
+ OSL_ENSURE( !GetSh(), "+SwEditShell::HyphStart: missing HyphEnd()" );
+ return;
+ }
+
+// nothing to be done (at least not in the way as in the "else" part)
+ bOldIdle = pShell->GetViewOptions()->IsIdle();
+ ((SwViewOption*)pShell->GetViewOptions())->SetIdle( sal_False );
+ _Start( pShell, eStart, eEnd );
+}
+
+/*************************************************************************
+ * virtual SwHyphIter::End
+ *************************************************************************/
+
+// Selektionen wiederherstellen
+
+
+
+void SwHyphIter::End()
+{
+ if( !GetSh() )
+ return;
+ ((SwViewOption*)GetSh()->GetViewOptions())->SetIdle( bOldIdle );
+ _End();
+}
+
+/*************************************************************************
+ * SwHyphIter::Continue
+ *************************************************************************/
+
+uno::Any SwHyphIter::Continue( sal_uInt16* pPageCnt, sal_uInt16* pPageSt )
+{
+ uno::Any aHyphRet;
+ SwEditShell *pMySh = GetSh();
+ if( !pMySh )
+ return aHyphRet;
+
+ const sal_Bool bAuto = IsAuto();
+ uno::Reference< XHyphenatedWord > xHyphWord;
+ sal_Bool bGoOn = sal_False;
+ do {
+ SwPaM *pCrsr;
+ do {
+ OSL_ENSURE( GetEnd(), "SwEditShell::SpellContinue() ohne Start?" );
+ pCrsr = pMySh->GetCrsr();
+ if ( !pCrsr->HasMark() )
+ pCrsr->SetMark();
+ if ( *pCrsr->GetPoint() < *pCrsr->GetMark() )
+ {
+ pCrsr->Exchange();
+ pCrsr->SetMark();
+ }
+
+ if ( *pCrsr->End() <= *GetEnd() )
+ {
+ *pCrsr->GetMark() = *GetEnd();
+
+ // Muss an der aktuellen Cursorpos das Wort getrennt werden ?
+ const Point aCrsrPos( pMySh->GetCharRect().Pos() );
+ xHyphWord = pMySh->GetDoc()->Hyphenate( pCrsr, aCrsrPos,
+ pPageCnt, pPageSt );
+ }
+
+ if( bAuto && xHyphWord.is() )
+ {
+ pMySh->InsertSoftHyph( xHyphWord->getHyphenationPos() + 1);
+ }
+ } while( bAuto && xHyphWord.is() ); //end of do-while
+ bGoOn = !xHyphWord.is() && GetCrsrCnt() > 1;
+
+ if( bGoOn )
+ {
+ pMySh->Pop( sal_False );
+ pCrsr = pMySh->GetCrsr();
+ if ( *pCrsr->GetPoint() > *pCrsr->GetMark() )
+ pCrsr->Exchange();
+ SwPosition* pNew = new SwPosition(*pCrsr->End());
+ SetEnd( pNew );
+ pCrsr->SetMark();
+ --GetCrsrCnt();
+ }
+ } while ( bGoOn );
+ aHyphRet <<= xHyphWord;
+ return aHyphRet;
+}
+
+/*************************************************************************
+ * SwHyphIter::HyphIgnore
+ *************************************************************************/
+
+// Beschreibung: Trennstelle ignorieren
+
+void SwHyphIter::Ignore()
+{
+ SwEditShell *pMySh = GetSh();
+ SwPaM *pCrsr = pMySh->GetCrsr();
+
+ // Alten SoftHyphen loeschen
+ DelSoftHyph( *pCrsr );
+
+ // und weiter
+ pCrsr->Start()->nContent = pCrsr->End()->nContent;
+ pCrsr->SetMark();
+}
+
+/*************************************************************************
+ * SwHyphIter::DelSoftHyph
+ *************************************************************************/
+
+void SwHyphIter::DelSoftHyph( SwPaM &rPam )
+{
+ const SwPosition* pStt = rPam.Start();
+ const xub_StrLen nStart = pStt->nContent.GetIndex();
+ const xub_StrLen nEnd = rPam.End()->nContent.GetIndex();
+ SwTxtNode *pNode = pStt->nNode.GetNode().GetTxtNode();
+ pNode->DelSoftHyph( nStart, nEnd );
+}
+
+/*************************************************************************
+ * SwHyphIter::InsertSoftHyph
+ *************************************************************************/
+
+
+void SwHyphIter::InsertSoftHyph( const xub_StrLen nHyphPos )
+{
+ SwEditShell *pMySh = GetSh();
+ OSL_ENSURE( pMySh, "+SwEditShell::InsertSoftHyph: missing HyphStart()");
+ if( !pMySh )
+ return;
+
+ SwPaM *pCrsr = pMySh->GetCrsr();
+ SwPosition* pSttPos = pCrsr->Start();
+ SwPosition* pEndPos = pCrsr->End();
+
+ xub_StrLen nLastHyphLen = GetEnd()->nContent.GetIndex() -
+ pSttPos->nContent.GetIndex();
+
+ if( pSttPos->nNode != pEndPos->nNode || !nLastHyphLen )
+ {
+ OSL_ENSURE( pSttPos->nNode == pEndPos->nNode,
+ "+SwEditShell::InsertSoftHyph: node warp during hyphenation" );
+ OSL_ENSURE(nLastHyphLen, "+SwEditShell::InsertSoftHyph: missing HyphContinue()");
+ *pSttPos = *pEndPos;
+ return;
+ }
+
+ pMySh->StartAction();
+ {
+ SwDoc *pDoc = pMySh->GetDoc();
+ DelSoftHyph( *pCrsr );
+ pSttPos->nContent += nHyphPos;
+ SwPaM aRg( *pSttPos );
+ pDoc->InsertString( aRg, CHAR_SOFTHYPHEN );
+ // Durch das Einfuegen des SoftHyphs ist ein Zeichen hinzugekommen
+//JP 18.07.95: warum, ist doch ein SwIndex, dieser wird doch mitverschoben !!
+// pSttPos->nContent++;
+ }
+ // Die Selektion wird wieder aufgehoben
+ pCrsr->DeleteMark();
+ pMySh->EndAction();
+ pCrsr->SetMark();
+}
+
+// --------------------- Methoden der SwEditShell ------------------------
+
+bool SwEditShell::HasLastSentenceGotGrammarChecked() const
+{
+ bool bTextWasGrammarChecked = false;
+ if (pSpellIter)
+ {
+ ::svx::SpellPortions aLastPortions( pSpellIter->GetLastPortions() );
+ for (size_t i = 0; i < aLastPortions.size() && !bTextWasGrammarChecked; ++i)
+ {
+ // bIsGrammarError is also true if the text was only checked but no
+ // grammar error was found. (That is if a ProofreadingResult was obtained in
+ // SwDoc::Spell and in turn bIsGrammarError was set in SwSpellIter::CreatePortion)
+ if (aLastPortions[i].bIsGrammarError)
+ bTextWasGrammarChecked = true;
+ }
+ }
+ return bTextWasGrammarChecked;
+}
+
+/*************************************************************************
+ * SwEditShell::HasConvIter
+ *************************************************************************/
+
+sal_Bool SwEditShell::HasConvIter() const
+{
+ return 0 != pConvIter;
+}
+
+/*************************************************************************
+ * SwEditShell::HasHyphIter
+ *************************************************************************/
+
+sal_Bool SwEditShell::HasHyphIter() const
+{
+ return 0 != pHyphIter;
+}
+
+/*************************************************************************
+ * SwEditShell::SetFindRange
+ *************************************************************************/
+
+void SwEditShell::SetLinguRange( SwDocPositions eStart, SwDocPositions eEnd )
+{
+ SwPaM *pCrsr = GetCrsr();
+ MakeFindRange( static_cast<sal_uInt16>(eStart), static_cast<sal_uInt16>(eEnd), pCrsr );
+ if( *pCrsr->GetPoint() > *pCrsr->GetMark() )
+ pCrsr->Exchange();
+}
+
+/*************************************************************************
+ * SwEditShell::SpellStart
+ *************************************************************************/
+
+void SwEditShell::SpellStart(
+ SwDocPositions eStart, SwDocPositions eEnd, SwDocPositions eCurr,
+ SwConversionArgs *pConvArgs )
+{
+ SwLinguIter *pLinguIter = 0;
+
+ // do not spell if interactive spelling is active elsewhere
+ if (!pConvArgs && !pSpellIter)
+ {
+ OSL_ENSURE( !pSpellIter, "wer ist da schon am spellen?" );
+ pSpellIter = new SwSpellIter;
+ pLinguIter = pSpellIter;
+ }
+ // do not do text conversion if it is active elsewhere
+ if (pConvArgs && !pConvIter)
+ {
+ OSL_ENSURE( !pConvIter, "text conversion already active!" );
+ pConvIter = new SwConvIter( *pConvArgs );
+ pLinguIter = pConvIter;
+ }
+
+ if (pLinguIter)
+ {
+ SwCursor* pSwCrsr = GetSwCrsr();
+
+ SwPosition *pTmp = new SwPosition( *pSwCrsr->GetPoint() );
+ pSwCrsr->FillFindPos( eCurr, *pTmp );
+ pLinguIter->SetCurr( pTmp );
+
+ pTmp = new SwPosition( *pTmp );
+ pLinguIter->SetCurrX( pTmp );
+ }
+
+ if (!pConvArgs && pSpellIter)
+ pSpellIter->Start( this, eStart, eEnd );
+ if (pConvArgs && pConvIter)
+ pConvIter->Start( this, eStart, eEnd );
+}
+
+/*************************************************************************
+ * SwEditShell::SpellEnd
+ *************************************************************************/
+
+void SwEditShell::SpellEnd( SwConversionArgs *pConvArgs, bool bRestoreSelection )
+{
+ if (!pConvArgs && pSpellIter && pSpellIter->GetSh() == this)
+ {
+ OSL_ENSURE( pSpellIter, "wo ist mein Iterator?" );
+ pSpellIter->_End(bRestoreSelection);
+ delete pSpellIter, pSpellIter = 0;
+ }
+ if (pConvArgs && pConvIter && pConvIter->GetSh() == this)
+ {
+ OSL_ENSURE( pConvIter, "wo ist mein Iterator?" );
+ pConvIter->_End();
+ delete pConvIter, pConvIter = 0;
+ }
+}
+
+/*************************************************************************
+ * SwEditShell::SpellContinue
+ *************************************************************************/
+
+// liefert Rueckgabewerte entsprechend SPL_ in splchk.hxx
+
+uno::Any SwEditShell::SpellContinue(
+ sal_uInt16* pPageCnt, sal_uInt16* pPageSt,
+ SwConversionArgs *pConvArgs )
+{
+ uno::Any aRes;
+
+ if ((!pConvArgs && pSpellIter->GetSh() != this) ||
+ ( pConvArgs && pConvIter->GetSh() != this))
+ return aRes;
+
+ if( pPageCnt && !*pPageCnt )
+ {
+ sal_uInt16 nEndPage = GetLayout()->GetPageNum();
+ nEndPage += nEndPage * 10 / 100;
+ *pPageCnt = nEndPage;
+ if( nEndPage )
+ ::StartProgress( STR_STATSTR_SPELL, 0, nEndPage, GetDoc()->GetDocShell() );
+ }
+
+ OSL_ENSURE( pConvArgs || pSpellIter, "SpellIter missing" );
+ OSL_ENSURE( !pConvArgs || pConvIter, "ConvIter missing" );
+ //JP 18.07.95: verhinder bei Fehlermeldungen die Anzeige der Selektionen
+ // KEIN StartAction, da damit auch die Paints abgeschaltet
+ // werden !!!!!
+ ++nStartAction;
+ rtl::OUString aRet;
+ uno::Reference< uno::XInterface > xRet;
+ if (pConvArgs)
+ {
+ pConvIter->Continue( pPageCnt, pPageSt ) >>= aRet;
+ aRes <<= aRet;
+ }
+ else
+ {
+ pSpellIter->Continue( pPageCnt, pPageSt ) >>= xRet;
+ aRes <<= xRet;
+ }
+ --nStartAction;
+
+ if( aRet.getLength() || xRet.is() )
+ {
+ // dann die awt::Selection sichtbar machen
+ StartAction();
+ EndAction();
+ }
+ return aRes;
+}
+/*************************************************************************
+ * SwEditShell::HyphStart
+ *************************************************************************/
+
+/* Interaktive Trennung, BP 10.03.93
+ *
+ * 1) HyphStart
+ * - Aufheben aller Selektionen
+ * - Sichern des aktuellen Cursors
+ * - falls keine Selektion vorhanden:
+ * - neue Selektion bis zum Dokumentende
+ * 2) HyphContinue
+ * - nLastHyphLen wird auf den Selektionsstart addiert
+ * - iteriert ueber alle selektierten Bereiche
+ * - pDoc->Hyphenate() iteriert ueber alle Nodes der Selektion
+ * - pTxtNode->Hyphenate() ruft das SwTxtFrm::Hyphenate zur EditShell
+ * - SwTxtFrm:Hyphenate() iteriert ueber die Zeilen des Pams
+ * - LineIter::Hyphenate() stellt den Hyphenator
+ * und den Pam auf das zu trennende Wort ein.
+ * - Es gibt nur zwei Returnwerte sal_True, wenn eine Trennstelle anliegt
+ * und sal_False, wenn der Pam abgearbeitet wurde.
+ * - Bei sal_True wird das selektierte Wort zur Anzeige gebracht und
+ * nLastHyphLen gesetzt.
+ * - Bei sal_False wird die aktuelle Selektion geloescht und die naechste
+ * zur aktuellen gewaehlt. Return HYPH_OK, wenn keine mehr vorhanden.
+ * 3) InsertSoftHyph (wird ggf. von der UI gerufen)
+ * - Der aktuelle Cursor wird plaziert und das Attribut eingefuegt.
+ * 4) HyphEnd
+ * - Wiederherstellen des alten Cursors, EndAction
+ */
+
+
+
+void SwEditShell::HyphStart( SwDocPositions eStart, SwDocPositions eEnd )
+{
+ // do not hyphenate if interactive hyphenationg is active elsewhere
+ if (!pHyphIter)
+ {
+ OSL_ENSURE( !pHyphIter, "wer ist da schon am hyphinieren?" );
+ pHyphIter = new SwHyphIter;
+ pHyphIter->Start( this, eStart, eEnd );
+ }
+}
+
+/*************************************************************************
+ * SwEditShell::HyphEnd
+ *************************************************************************/
+
+// Selektionen wiederherstellen
+
+
+
+void SwEditShell::HyphEnd()
+{
+ if (pHyphIter->GetSh() == this)
+ {
+ OSL_ENSURE( pHyphIter, "wo ist mein Iterator?" );
+ pHyphIter->End();
+ delete pHyphIter, pHyphIter = 0;
+ }
+}
+
+/*************************************************************************
+ * SwEditShell::HyphContinue
+ *************************************************************************/
+
+// Returnwerte: (BP: ich wuerde es genau umdrehen, aber die UI wuenscht es so)
+// HYPH_CONTINUE, wenn eine Trennstelle anliegt
+// HYPH_OK, wenn der selektierte Bereich abgearbeitet wurde.
+
+
+uno::Reference< uno::XInterface >
+ SwEditShell::HyphContinue( sal_uInt16* pPageCnt, sal_uInt16* pPageSt )
+{
+ if (pHyphIter->GetSh() != this)
+ return 0;
+
+ if( pPageCnt && !*pPageCnt && !*pPageSt )
+ {
+ sal_uInt16 nEndPage = GetLayout()->GetPageNum();
+ nEndPage += nEndPage * 10 / 100;
+ if( nEndPage > 14 )
+ {
+ *pPageCnt = nEndPage;
+ ::StartProgress( STR_STATSTR_HYPHEN, 0, nEndPage, GetDoc()->GetDocShell());
+ }
+ else // Hiermit unterdruecken wir ein fuer allemal
+ *pPageSt = 1; // das StatLineStartPercent
+ }
+
+ OSL_ENSURE( pHyphIter, "wo ist mein Iterator?" );
+ //JP 18.07.95: verhinder bei Fehlermeldungen die Anzeige der Selektionen
+ // KEIN StartAction, da damit auch die Paints abgeschaltet
+ // werden !!!!!
+ ++nStartAction;
+ uno::Reference< uno::XInterface > xRet;
+ pHyphIter->Continue( pPageCnt, pPageSt ) >>= xRet;
+ --nStartAction;
+
+ if( xRet.is() )
+ pHyphIter->ShowSelection();
+
+ return xRet;
+}
+
+
+/*************************************************************************
+ * SwEditShell::InsertSoftHyph
+ *************************************************************************/
+
+// Zum Einfuegen des SoftHyphens, Position ist der Offset
+// innerhalb des getrennten Wortes.
+
+
+void SwEditShell::InsertSoftHyph( const xub_StrLen nHyphPos )
+{
+ OSL_ENSURE( pHyphIter, "wo ist mein Iterator?" );
+ pHyphIter->InsertSoftHyph( nHyphPos );
+}
+
+
+/*************************************************************************
+ * SwEditShell::HyphIgnore
+ *************************************************************************/
+
+// Beschreibung: Trennstelle ignorieren
+
+void SwEditShell::HyphIgnore()
+{
+ OSL_ENSURE( pHyphIter, "wo ist mein Iterator?" );
+ //JP 18.07.95: verhinder bei Fehlermeldungen die Anzeige der Selektionen
+ // KEIN StartAction, da damit auch die Paints abgeschaltet
+ // werden !!!!!
+ ++nStartAction;
+ pHyphIter->Ignore();
+ --nStartAction;
+
+ pHyphIter->ShowSelection();
+}
+
+/*************************************************************************
+ * SwEditShell::GetCorrection()
+ * liefert eine Liste von Vorschlaegen fuer falsch geschriebene Worte,
+ * ein NULL-Pointer signalisiert, dass das Wort richtig geschrieben ist,
+ * eine leere Liste, dass das Wort zwar unbekannt ist, aber keine Alternativen
+ * geliefert werden koennen.
+ *************************************************************************/
+
+
+uno::Reference< XSpellAlternatives >
+ SwEditShell::GetCorrection( const Point* pPt, SwRect& rSelectRect )
+{
+ uno::Reference< XSpellAlternatives > xSpellAlt;
+
+ if( IsTableMode() )
+ return NULL;
+ SwPaM* pCrsr = GetCrsr();
+ SwPosition aPos( *pCrsr->GetPoint() );
+ Point aPt( *pPt );
+ SwCrsrMoveState eTmpState( MV_SETONLYTEXT );
+ SwTxtNode *pNode;
+ SwWrongList *pWrong;
+ if( GetLayout()->GetCrsrOfst( &aPos, aPt, &eTmpState ) &&
+ 0 != (pNode = aPos.nNode.GetNode().GetTxtNode()) &&
+ 0 != (pWrong = pNode->GetWrong()) &&
+ !pNode->IsInProtectSect() )
+ {
+ xub_StrLen nBegin = aPos.nContent.GetIndex();
+ xub_StrLen nLen = 1;
+ if( pWrong->InWrongWord(nBegin,nLen) && !pNode->IsSymbol(nBegin) )
+ {
+ String aText( pNode->GetTxt().Copy( nBegin, nLen ) );
+ String aWord( aText );
+ aWord.EraseAllChars( CH_TXTATR_BREAKWORD ).EraseAllChars( CH_TXTATR_INWORD );
+
+ uno::Reference< XSpellChecker1 > xSpell( ::GetSpellChecker() );
+ if( xSpell.is() )
+ {
+ LanguageType eActLang = (LanguageType)pNode->GetLang( nBegin, nLen );
+ if( xSpell->hasLanguage( eActLang ))
+ {
+ // restrict the maximal number of suggestions displayed
+ // in the context menu.
+ // Note: That could of course be done by clipping the
+ // resulting sequence but the current third party
+ // implementations result differs greatly if the number of
+ // suggestions to be retuned gets changed. Statistically
+ // it gets much better if told to return e.g. only 7 strings
+ // than returning e.g. 16 suggestions and using only the
+ // first 7. Thus we hand down the value to use to that
+ // implementation here by providing an additional parameter.
+ Sequence< PropertyValue > aPropVals(1);
+ PropertyValue &rVal = aPropVals.getArray()[0];
+ rVal.Name = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( UPN_MAX_NUMBER_OF_SUGGESTIONS ));
+ rVal.Value <<= (sal_Int16) 7;
+
+ xSpellAlt = xSpell->spell( aWord, eActLang, aPropVals );
+ }
+ }
+
+ if ( xSpellAlt.is() ) // error found?
+ {
+ //save the start and end positons of the line and the starting point
+ Push();
+ LeftMargin();
+ xub_StrLen nLineStart = GetCrsr()->GetPoint()->nContent.GetIndex();
+ RightMargin();
+ xub_StrLen nLineEnd = GetCrsr()->GetPoint()->nContent.GetIndex();
+ Pop(sal_False);
+
+ // make sure the selection build later from the
+ // data below does not include footnotes and other
+ // "in word" character to the left and right in order
+ // to preserve those. Therefore count those "in words"
+ // in order to modify the selection accordingly.
+ const sal_Unicode* pChar = aText.GetBuffer();
+ xub_StrLen nLeft = 0;
+ while (pChar && *pChar++ == CH_TXTATR_INWORD)
+ ++nLeft;
+ pChar = aText.Len() ? aText.GetBuffer() + aText.Len() - 1 : 0;
+ xub_StrLen nRight = 0;
+ while (pChar && *pChar-- == CH_TXTATR_INWORD)
+ ++nRight;
+
+ aPos.nContent = nBegin + nLeft;
+ pCrsr = GetCrsr();
+ *pCrsr->GetPoint() = aPos;
+ pCrsr->SetMark();
+ ExtendSelection( sal_True, nLen - nLeft - nRight );
+ //no determine the rectangle in the current line
+ xub_StrLen nWordStart = (nBegin + nLeft) < nLineStart ? nLineStart : nBegin + nLeft;
+ //take one less than the line end - otherwise the next line would be calculated
+ xub_StrLen nWordEnd = (nBegin + nLen - nLeft - nRight) > nLineEnd ? nLineEnd: (nBegin + nLen - nLeft - nRight);
+ Push();
+ pCrsr->DeleteMark();
+ SwIndex& rContent = GetCrsr()->GetPoint()->nContent;
+ rContent = nWordStart;
+ SwRect aStartRect;
+ SwCrsrMoveState aState;
+ aState.bRealWidth = sal_True;
+ SwCntntNode* pCntntNode = pCrsr->GetCntntNode();
+ SwCntntFrm *pCntntFrame = pCntntNode->getLayoutFrm( GetLayout(), pPt, pCrsr->GetPoint(), sal_False);
+
+ pCntntFrame->GetCharRect( aStartRect, *pCrsr->GetPoint(), &aState );
+ rContent = nWordEnd - 1;
+ SwRect aEndRect;
+ pCntntFrame->GetCharRect( aEndRect, *pCrsr->GetPoint(),&aState );
+ rSelectRect = aStartRect.Union( aEndRect );
+ Pop(sal_False);
+ }
+ }
+ }
+ return xSpellAlt;
+}
+
+
+
+bool SwEditShell::GetGrammarCorrection(
+ linguistic2::ProofreadingResult /*out*/ &rResult, // the complete result
+ sal_Int32 /*out*/ &rErrorPosInText, // offset of error position in string that was grammar checked...
+ sal_Int32 /*out*/ &rErrorIndexInResult, // index of error in rResult.aGrammarErrors
+ uno::Sequence< rtl::OUString > /*out*/ &rSuggestions, // suggestions to be used for the error found
+ const Point *pPt, SwRect &rSelectRect )
+{
+ bool bRes = false;
+
+ if( IsTableMode() )
+ return bRes;
+
+ SwPaM* pCrsr = GetCrsr();
+ SwPosition aPos( *pCrsr->GetPoint() );
+ Point aPt( *pPt );
+ SwCrsrMoveState eTmpState( MV_SETONLYTEXT );
+ SwTxtNode *pNode;
+ SwGrammarMarkUp *pWrong;
+ if( GetLayout()->GetCrsrOfst( &aPos, aPt, &eTmpState ) &&
+ 0 != (pNode = aPos.nNode.GetNode().GetTxtNode()) &&
+ 0 != (pWrong = pNode->GetGrammarCheck()) &&
+ !pNode->IsInProtectSect() )
+ {
+ xub_StrLen nBegin = aPos.nContent.GetIndex();
+ xub_StrLen nLen = 1;
+ if (pWrong->InWrongWord(nBegin, nLen))
+ {
+ String aText( pNode->GetTxt().Copy( nBegin, nLen ) );
+ String aWord( aText );
+ aWord.EraseAllChars( CH_TXTATR_BREAKWORD ).EraseAllChars( CH_TXTATR_INWORD );
+
+ uno::Reference< linguistic2::XProofreadingIterator > xGCIterator( pDoc->GetGCIterator() );
+ if (xGCIterator.is())
+ {
+// LanguageType eActLang = (LanguageType)pNode->GetLang( nBegin, nLen );
+ uno::Reference< lang::XComponent > xDoc( pDoc->GetDocShell()->GetBaseModel(), uno::UNO_QUERY );
+
+ // Expand the string:
+ rtl::OUString aExpandText;
+ const ModelToViewHelper::ConversionMap* pConversionMap =
+ pNode->BuildConversionMap( aExpandText );
+ // get XFlatParagraph to use...
+ uno::Reference< text::XFlatParagraph > xFlatPara = new SwXFlatParagraph( *pNode, aExpandText, pConversionMap );
+
+ // get error position of cursor in XFlatParagraph
+ rErrorPosInText = ModelToViewHelper::ConvertToViewPosition( pConversionMap, nBegin );
+
+ sal_Int32 nStartOfSentence = ModelToViewHelper::ConvertToViewPosition( pConversionMap, pWrong->getSentenceStart( nBegin ) );
+ sal_Int32 nEndOfSentence = ModelToViewHelper::ConvertToViewPosition( pConversionMap, pWrong->getSentenceEnd( nBegin ) );
+ if( nEndOfSentence == STRING_LEN )
+ {
+ nEndOfSentence = aExpandText.getLength();
+ }
+
+ rResult = xGCIterator->checkSentenceAtPosition(
+ xDoc, xFlatPara, aExpandText, lang::Locale(), nStartOfSentence, nEndOfSentence, rErrorPosInText );
+ bRes = true;
+
+ // get suggestions to use for the specific error position
+ sal_Int32 nErrors = rResult.aErrors.getLength();
+ rSuggestions.realloc( 0 );
+ for (sal_Int32 i = 0; i < nErrors; ++i )
+ {
+ // return suggestions for first error that includes the given error position
+ const linguistic2::SingleProofreadingError &rError = rResult.aErrors[i];
+ if (rError.nErrorStart <= rErrorPosInText &&
+ rErrorPosInText < rError.nErrorStart + rError.nErrorLength)
+ {
+ rSuggestions = rError.aSuggestions;
+ rErrorIndexInResult = i;
+ break;
+ }
+ }
+ }
+
+ if (rResult.aErrors.getLength() > 0) // error found?
+ {
+ //save the start and end positons of the line and the starting point
+ Push();
+ LeftMargin();
+ xub_StrLen nLineStart = GetCrsr()->GetPoint()->nContent.GetIndex();
+ RightMargin();
+ xub_StrLen nLineEnd = GetCrsr()->GetPoint()->nContent.GetIndex();
+ Pop(sal_False);
+
+ // make sure the selection build later from the
+ // data below does not include footnotes and other
+ // "in word" character to the left and right in order
+ // to preserve those. Therefore count those "in words"
+ // in order to modify the selection accordingly.
+ const sal_Unicode* pChar = aText.GetBuffer();
+ xub_StrLen nLeft = 0;
+ while (pChar && *pChar++ == CH_TXTATR_INWORD)
+ ++nLeft;
+ pChar = aText.Len() ? aText.GetBuffer() + aText.Len() - 1 : 0;
+ xub_StrLen nRight = 0;
+ while (pChar && *pChar-- == CH_TXTATR_INWORD)
+ ++nRight;
+
+ aPos.nContent = nBegin + nLeft;
+ pCrsr = GetCrsr();
+ *pCrsr->GetPoint() = aPos;
+ pCrsr->SetMark();
+ ExtendSelection( sal_True, nLen - nLeft - nRight );
+ //no determine the rectangle in the current line
+ xub_StrLen nWordStart = (nBegin + nLeft) < nLineStart ? nLineStart : nBegin + nLeft;
+ //take one less than the line end - otherwise the next line would be calculated
+ xub_StrLen nWordEnd = (nBegin + nLen - nLeft - nRight) > nLineEnd ? nLineEnd: (nBegin + nLen - nLeft - nRight);
+ Push();
+ pCrsr->DeleteMark();
+ SwIndex& rContent = GetCrsr()->GetPoint()->nContent;
+ rContent = nWordStart;
+ SwRect aStartRect;
+ SwCrsrMoveState aState;
+ aState.bRealWidth = sal_True;
+ SwCntntNode* pCntntNode = pCrsr->GetCntntNode();
+ SwCntntFrm *pCntntFrame = pCntntNode->getLayoutFrm( GetLayout(), pPt, pCrsr->GetPoint(), sal_False);
+
+ pCntntFrame->GetCharRect( aStartRect, *pCrsr->GetPoint(), &aState );
+ rContent = nWordEnd - 1;
+ SwRect aEndRect;
+ pCntntFrame->GetCharRect( aEndRect, *pCrsr->GetPoint(),&aState );
+ rSelectRect = aStartRect.Union( aEndRect );
+ Pop(sal_False);
+ }
+ }
+ }
+
+ return bRes;
+}
+
+bool SwEditShell::SpellSentence(::svx::SpellPortions& rPortions, bool bIsGrammarCheck)
+{
+ OSL_ENSURE( pSpellIter, "SpellIter missing" );
+ if(!pSpellIter)
+ return false;
+ bool bRet = pSpellIter->SpellSentence(rPortions, bIsGrammarCheck);
+
+ // make Selection visible - this should simply move the
+ // cursor to the end of the sentence
+ StartAction();
+ EndAction();
+ return bRet;
+}
+/*-------------------------------------------------------------------------
+ make SpellIter start with the current sentence when called next time
+ -----------------------------------------------------------------------*/
+void SwEditShell::PutSpellingToSentenceStart()
+{
+ OSL_ENSURE( pSpellIter, "SpellIter missing" );
+ if(!pSpellIter)
+ return;
+ pSpellIter->ToSentenceStart();
+}
+
+sal_uInt32 lcl_CountRedlines(
+ const ::svx::SpellPortions& rLastPortions)
+{
+ sal_uInt32 nRet = 0;
+ SpellPortions::const_iterator aIter = rLastPortions.begin();
+ for( ; aIter != rLastPortions.end(); ++aIter)
+ {
+ if( aIter->bIsHidden )
+ ++nRet;
+ }
+ return nRet;
+}
+
+void SwEditShell::MoveContinuationPosToEndOfCheckedSentence()
+{
+ // give hint that continuation position for spell/grammar checking is
+ // at the end of this sentence
+ if (pSpellIter)
+ {
+ pSpellIter->SetCurr( new SwPosition( *pSpellIter->GetCurrX() ) );
+ pSpellIter->ContinueAfterThisSentence();
+ }
+}
+
+
+void SwEditShell::ApplyChangedSentence(const ::svx::SpellPortions& rNewPortions, bool bRecheck)
+{
+ // Note: rNewPortions.size() == 0 is valid and happens when the whole
+ // sentence got removed in the dialog
+
+ OSL_ENSURE( pSpellIter, "SpellIter missing" );
+ if(pSpellIter &&
+ pSpellIter->GetLastPortions().size() > 0) // no portions -> no text to be changed
+ {
+ const SpellPortions& rLastPortions = pSpellIter->GetLastPortions();
+ const SpellContentPositions rLastPositions = pSpellIter->GetLastPositions();
+ OSL_ENSURE(rLastPortions.size() > 0 &&
+ rLastPortions.size() == rLastPositions.size(),
+ "last vectors of spelling results are not set or not equal");
+
+ // iterate over the new portions, beginning at the end to take advantage of the previously
+ // saved content positions
+
+ pDoc->GetIDocumentUndoRedo().StartUndo( UNDO_OVERWRITE, NULL );
+ StartAction();
+
+ SwPaM *pCrsr = GetCrsr();
+ // save cursor position (which should be at the end of the current sentence)
+ // for later restoration
+ Push();
+
+ sal_uInt32 nRedlinePortions = lcl_CountRedlines(rLastPortions);
+ if((rLastPortions.size() - nRedlinePortions) == rNewPortions.size())
+ {
+ DBG_ASSERT( rNewPortions.size() > 0, "rNewPortions should not be empty here" );
+ DBG_ASSERT( rLastPortions.size() > 0, "rLastPortions should not be empty here" );
+ DBG_ASSERT( rLastPositions.size() > 0, "rLastPositions should not be empty here" );
+
+ //the simple case: the same number of elements on both sides
+ //each changed element has to be applied to the corresponding source element
+ svx::SpellPortions::const_iterator aCurrentNewPortion = rNewPortions.end();
+ SpellPortions::const_iterator aCurrentOldPortion = rLastPortions.end();
+ SpellContentPositions::const_iterator aCurrentOldPosition = rLastPositions.end();
+ do
+ {
+ --aCurrentNewPortion;
+ --aCurrentOldPortion;
+ --aCurrentOldPosition;
+ //jump over redline portions
+ while(aCurrentOldPortion->bIsHidden)
+ {
+ if (aCurrentOldPortion != rLastPortions.begin() &&
+ aCurrentOldPosition != rLastPositions.begin())
+ {
+ --aCurrentOldPortion;
+ --aCurrentOldPosition;
+ }
+ else
+ {
+ DBG_ASSERT( 0, "ApplyChangedSentence: iterator positions broken" );
+ break;
+ }
+ }
+ if ( !pCrsr->HasMark() )
+ pCrsr->SetMark();
+ pCrsr->GetPoint()->nContent = aCurrentOldPosition->nLeft;
+ pCrsr->GetMark()->nContent = aCurrentOldPosition->nRight;
+ sal_uInt16 nScriptType = GetI18NScriptTypeOfLanguage( aCurrentNewPortion->eLanguage );
+ sal_uInt16 nLangWhichId = RES_CHRATR_LANGUAGE;
+ switch(nScriptType)
+ {
+ case SCRIPTTYPE_ASIAN : nLangWhichId = RES_CHRATR_CJK_LANGUAGE; break;
+ case SCRIPTTYPE_COMPLEX : nLangWhichId = RES_CHRATR_CTL_LANGUAGE; break;
+ }
+ if(aCurrentNewPortion->sText != aCurrentOldPortion->sText)
+ {
+ //change text ...
+ pDoc->DeleteAndJoin(*pCrsr);
+ // ... and apply language if necessary
+ if(aCurrentNewPortion->eLanguage != aCurrentOldPortion->eLanguage)
+ SetAttr( SvxLanguageItem(aCurrentNewPortion->eLanguage, nLangWhichId), nLangWhichId );
+ pDoc->InsertString(*pCrsr, aCurrentNewPortion->sText);
+ }
+ else if(aCurrentNewPortion->eLanguage != aCurrentOldPortion->eLanguage)
+ {
+ //apply language
+ SetAttr( SvxLanguageItem(aCurrentNewPortion->eLanguage, nLangWhichId), nLangWhichId );
+ }
+ else if( aCurrentNewPortion->bIgnoreThisError )
+ {
+ //add the 'ignore' markup to the TextNode's grammar ignore markup list
+ IgnoreGrammarErrorAt( *pCrsr );
+ OSL_FAIL("TODO: add ignore mark to text node");
+ }
+ if(aCurrentNewPortion == rNewPortions.begin())
+ break;
+ }
+ while(aCurrentNewPortion != rNewPortions.begin());
+ }
+ else
+ {
+ DBG_ASSERT( rLastPositions.size() > 0, "rLastPositions should not be empty here" );
+
+ //select the complete sentence
+ SpellContentPositions::const_iterator aCurrentEndPosition = rLastPositions.end();
+ --aCurrentEndPosition;
+ SpellContentPositions::const_iterator aCurrentStartPosition = rLastPositions.begin();
+ pCrsr->GetPoint()->nContent = aCurrentStartPosition->nLeft;
+ pCrsr->GetMark()->nContent = aCurrentEndPosition->nRight;
+
+ //delete the sentence completely
+ pDoc->DeleteAndJoin(*pCrsr);
+ svx::SpellPortions::const_iterator aCurrentNewPortion = rNewPortions.begin();
+ while(aCurrentNewPortion != rNewPortions.end())
+ {
+ //set the language attribute
+ sal_uInt16 nScriptType = GetScriptType();
+ sal_uInt16 nLangWhichId = RES_CHRATR_LANGUAGE;
+ switch(nScriptType)
+ {
+ case SCRIPTTYPE_ASIAN : nLangWhichId = RES_CHRATR_CJK_LANGUAGE; break;
+ case SCRIPTTYPE_COMPLEX : nLangWhichId = RES_CHRATR_CTL_LANGUAGE; break;
+ }
+ SfxItemSet aSet(GetAttrPool(), nLangWhichId, nLangWhichId, 0);
+ GetCurAttr( aSet );
+ const SvxLanguageItem& rLang = static_cast<const SvxLanguageItem& >(aSet.Get(nLangWhichId));
+ if(rLang.GetLanguage() != aCurrentNewPortion->eLanguage)
+ SetAttr( SvxLanguageItem(aCurrentNewPortion->eLanguage, nLangWhichId) );
+ //insert the new string
+ pDoc->InsertString(*pCrsr, aCurrentNewPortion->sText);
+
+ //set the cursor to the end of the inserted string
+ *pCrsr->Start() = *pCrsr->End();
+ ++aCurrentNewPortion;
+ }
+ }
+
+ // restore cursor to the end of the sentence
+ // (will work also if the sentence length has changed,
+ // since cursors get updated automatically!)
+ Pop( sal_False );
+
+ // collapse cursor to the end of the modified sentence
+ *pCrsr->Start() = *pCrsr->End();
+ if (bRecheck)
+ {
+ //in grammar check the current sentence has to be checked again
+ GoStartSentence();
+ }
+ // set continuation position for spell/grammar checking to the end of this sentence
+ pSpellIter->SetCurr( new SwPosition( *pCrsr->Start() ) );
+
+ pDoc->GetIDocumentUndoRedo().EndUndo( UNDO_OVERWRITE, NULL );
+ EndAction();
+ }
+}
+/*-------------------------------------------------------------------------
+ collect all deleted redlines of the current text node beginning at the
+ start of the cursor position
+ -----------------------------------------------------------------------*/
+SpellContentPositions lcl_CollectDeletedRedlines(SwEditShell* pSh)
+{
+ SpellContentPositions aRedlines;
+ SwDoc* pDoc = pSh->GetDoc();
+ const bool bShowChg = IDocumentRedlineAccess::IsShowChanges( pDoc->GetRedlineMode() );
+ if ( bShowChg )
+ {
+ SwPaM *pCrsr = pSh->GetCrsr();
+ const SwPosition* pStartPos = pCrsr->Start();
+ const SwTxtNode* pTxtNode = pCrsr->GetNode()->GetTxtNode();
+
+ sal_uInt16 nAct = pDoc->GetRedlinePos( *pTxtNode, USHRT_MAX );
+ const xub_StrLen nStartIndex = pStartPos->nContent.GetIndex();
+ for ( ; nAct < pDoc->GetRedlineTbl().Count(); nAct++ )
+ {
+ const SwRedline* pRed = pDoc->GetRedlineTbl()[ nAct ];
+
+ if ( pRed->Start()->nNode > pTxtNode->GetIndex() )
+ break;
+
+ if( nsRedlineType_t::REDLINE_DELETE == pRed->GetType() )
+ {
+ xub_StrLen nStart, nEnd;
+ pRed->CalcStartEnd( pTxtNode->GetIndex(), nStart, nEnd );
+ if(nStart >= nStartIndex || nEnd >= nStartIndex)
+ {
+ SpellContentPosition aAdd;
+ aAdd.nLeft = nStart;
+ aAdd.nRight = nEnd;
+ aRedlines.push_back(aAdd);
+ }
+ }
+ }
+ }
+ return aRedlines;
+}
+/*-------------------------------------------------------------------------
+ remove the redline positions after the current selection
+ -----------------------------------------------------------------------*/
+void lcl_CutRedlines( SpellContentPositions& aDeletedRedlines, SwEditShell* pSh )
+{
+ if(!aDeletedRedlines.empty())
+ {
+ SwPaM *pCrsr = pSh->GetCrsr();
+ const SwPosition* pEndPos = pCrsr->End();
+ xub_StrLen nEnd = pEndPos->nContent.GetIndex();
+ while(!aDeletedRedlines.empty() &&
+ aDeletedRedlines.back().nLeft > nEnd)
+ {
+ aDeletedRedlines.pop_back();
+ }
+ }
+}
+
+SpellContentPosition lcl_FindNextDeletedRedline(
+ const SpellContentPositions& rDeletedRedlines,
+ xub_StrLen nSearchFrom )
+{
+ SpellContentPosition aRet;
+ aRet.nLeft = aRet.nRight = STRING_MAXLEN;
+ if(!rDeletedRedlines.empty())
+ {
+ SpellContentPositions::const_iterator aIter = rDeletedRedlines.begin();
+ for( ; aIter != rDeletedRedlines.end(); ++aIter)
+ {
+ if(aIter->nLeft < nSearchFrom)
+ continue;
+ aRet = *aIter;
+ break;
+ }
+ }
+ return aRet;
+}
+
+bool SwSpellIter::SpellSentence(::svx::SpellPortions& rPortions, bool bIsGrammarCheck)
+{
+ bool bRet = false;
+ aLastPortions.clear();
+ aLastPositions.clear();
+
+ SwEditShell *pMySh = GetSh();
+ if( !pMySh )
+ return false;
+
+ OSL_ENSURE( GetEnd(), "SwEditShell::SpellSentence() ohne Start?");
+
+ uno::Reference< XSpellAlternatives > xSpellRet;
+ linguistic2::ProofreadingResult aGrammarResult;
+ sal_Bool bGoOn = sal_True;
+ bool bGrammarErrorFound = false;
+ do {
+ SwPaM *pCrsr = pMySh->GetCrsr();
+ if ( !pCrsr->HasMark() )
+ pCrsr->SetMark();
+
+ *pCrsr->GetPoint() = *GetCurr();
+ *pCrsr->GetMark() = *GetEnd();
+
+ if( bBackToStartOfSentence )
+ {
+ pMySh->GoStartSentence();
+ bBackToStartOfSentence = false;
+ }
+ uno::Any aSpellRet =
+ pMySh->GetDoc()->Spell(*pCrsr,
+ xSpeller, 0, 0, bIsGrammarCheck );
+ aSpellRet >>= xSpellRet;
+ aSpellRet >>= aGrammarResult;
+ bGoOn = GetCrsrCnt() > 1;
+ bGrammarErrorFound = aGrammarResult.aErrors.getLength() > 0;
+ if( xSpellRet.is() || bGrammarErrorFound )
+ {
+ bGoOn = sal_False;
+ SwPosition* pNewPoint = new SwPosition( *pCrsr->GetPoint() );
+ SwPosition* pNewMark = new SwPosition( *pCrsr->GetMark() );
+
+ SetCurr( pNewPoint );
+ SetCurrX( pNewMark );
+ }
+ if( bGoOn )
+ {
+ pMySh->Pop( sal_False );
+ pCrsr = pMySh->GetCrsr();
+ if ( *pCrsr->GetPoint() > *pCrsr->GetMark() )
+ pCrsr->Exchange();
+ SwPosition* pNew = new SwPosition( *pCrsr->GetPoint() );
+ SetStart( pNew );
+ pNew = new SwPosition( *pCrsr->GetMark() );
+ SetEnd( pNew );
+ pNew = new SwPosition( *GetStart() );
+ SetCurr( pNew );
+ pNew = new SwPosition( *pNew );
+ SetCurrX( pNew );
+ pCrsr->SetMark();
+ --GetCrsrCnt();
+ }
+ }
+ while ( bGoOn );
+ if(xSpellRet.is() || bGrammarErrorFound)
+ {
+ //an error has been found
+ //To fill the spell portions the beginning of the sentence has to be found
+ SwPaM *pCrsr = pMySh->GetCrsr();
+ //set the mark to the right if necessary
+ if ( *pCrsr->GetPoint() > *pCrsr->GetMark() )
+ pCrsr->Exchange();
+ //the cursor has to be collapsed on the left to go to the start of the sentence - if sentence ends inside of the error
+ pCrsr->DeleteMark();
+ pCrsr->SetMark();
+ sal_Bool bStartSent = 0 != pMySh->GoStartSentence();
+ SpellContentPositions aDeletedRedlines = lcl_CollectDeletedRedlines(pMySh);
+ if(bStartSent)
+ {
+ //create a portion from the start part
+ AddPortion(0, 0, aDeletedRedlines);
+ }
+ //Set the cursor to the error already found
+ *pCrsr->GetPoint() = *GetCurrX();
+ *pCrsr->GetMark() = *GetCurr();
+ AddPortion(xSpellRet, &aGrammarResult, aDeletedRedlines);
+
+
+ //save the end position of the error to continue from here
+ SwPosition aSaveStartPos = *pCrsr->End();
+ //determine the end of the current sentence
+ if ( *pCrsr->GetPoint() < *pCrsr->GetMark() )
+ pCrsr->Exchange();
+ //again collapse to start marking after the end of the error
+ pCrsr->DeleteMark();
+ pCrsr->SetMark();
+
+ pMySh->GoEndSentence();
+ if( bGrammarErrorFound )
+ {
+ rtl::OUString aExpandText;
+ const ModelToViewHelper::ConversionMap* pConversionMap = ((SwTxtNode*)pCrsr->GetNode())->BuildConversionMap( aExpandText );
+ xub_StrLen nSentenceEnd = (xub_StrLen)ModelToViewHelper::ConvertToViewPosition( pConversionMap, aGrammarResult.nBehindEndOfSentencePosition );
+ // remove trailing space
+ if( aExpandText[nSentenceEnd - 1] == ' ' )
+ --nSentenceEnd;
+ if( pCrsr->End()->nContent.GetIndex() < nSentenceEnd )
+ {
+ pCrsr->End()->nContent.Assign(
+ pCrsr->End()->nNode.GetNode().GetCntntNode(), nSentenceEnd);
+ }
+ }
+
+ lcl_CutRedlines( aDeletedRedlines, pMySh );
+ //save the 'global' end of the spellchecking
+ const SwPosition aSaveEndPos = *GetEnd();
+ //set the sentence end as 'local' end
+ SetEnd( new SwPosition( *pCrsr->End() ));
+
+ *pCrsr->GetPoint() = aSaveStartPos;
+ *pCrsr->GetMark() = *GetEnd();
+ //now the rest of the sentence has to be searched for errors
+ // for each error the non-error text between the current and the last error has
+ // to be added to the portions - if necessary broken into same-language-portions
+ if( !bGrammarErrorFound ) //in grammar check there's only one error returned
+ {
+ do
+ {
+ xSpellRet = 0;
+ // don't search for grammar errors here anymore!
+ pMySh->GetDoc()->Spell(*pCrsr,
+ xSpeller, 0, 0, false ) >>= xSpellRet;
+ if ( *pCrsr->GetPoint() > *pCrsr->GetMark() )
+ pCrsr->Exchange();
+ SetCurr( new SwPosition( *pCrsr->GetPoint() ));
+ SetCurrX( new SwPosition( *pCrsr->GetMark() ));
+
+ //if an error has been found go back to the text
+ //preceeding the error
+ if(xSpellRet.is())
+ {
+ *pCrsr->GetPoint() = aSaveStartPos;
+ *pCrsr->GetMark() = *GetCurr();
+ }
+ //add the portion
+ AddPortion(0, 0, aDeletedRedlines);
+
+ if(xSpellRet.is())
+ {
+ *pCrsr->GetPoint() = *GetCurr();
+ *pCrsr->GetMark() = *GetCurrX();
+ AddPortion(xSpellRet, 0, aDeletedRedlines);
+ //move the cursor to the end of the error string
+ *pCrsr->GetPoint() = *GetCurrX();
+ //and save the end of the error as new start position
+ aSaveStartPos = *GetCurrX();
+ //and the end of the sentence
+ *pCrsr->GetMark() = *GetEnd();
+ }
+ // if the end of the sentence has already been reached then break here
+ if(*GetCurrX() >= *GetEnd())
+ break;
+ }
+ while(xSpellRet.is());
+ }
+ else
+ {
+ //go to the end of sentence as the grammar check returned it
+ // at this time the Point is behind the grammar error
+ // and the mark points to the sentence end as
+ if ( *pCrsr->GetPoint() < *pCrsr->GetMark() )
+ pCrsr->Exchange();
+ }
+
+ // the part between the last error and the end of the sentence has to be added
+ *pMySh->GetCrsr()->GetPoint() = *GetEnd();
+ if(*GetCurrX() < *GetEnd())
+ {
+ AddPortion(0, 0, aDeletedRedlines);
+ }
+ //set the shell cursor to the end of the sentence to prevent a visible selection
+ *pCrsr->GetMark() = *GetEnd();
+ if( !bIsGrammarCheck )
+ {
+ //set the current position to the end of the sentence
+ SetCurr( new SwPosition(*GetEnd()) );
+ }
+ //restore the 'global' end
+ SetEnd( new SwPosition(aSaveEndPos) );
+ rPortions = aLastPortions;
+ bRet = true;
+ }
+ else
+ {
+ //if no error could be found the selection has to be corrected - at least if it's not in the body
+ *pMySh->GetCrsr()->GetPoint() = *GetEnd();
+ pMySh->GetCrsr()->DeleteMark();
+ }
+
+ return bRet;
+}
+
+void SwSpellIter::ToSentenceStart()
+{
+ bBackToStartOfSentence = true;
+}
+
+LanguageType lcl_GetLanguage(SwEditShell& rSh)
+{
+ sal_uInt16 nScriptType = rSh.GetScriptType();
+ sal_uInt16 nLangWhichId = RES_CHRATR_LANGUAGE;
+
+ switch(nScriptType)
+ {
+ case SCRIPTTYPE_ASIAN : nLangWhichId = RES_CHRATR_CJK_LANGUAGE; break;
+ case SCRIPTTYPE_COMPLEX : nLangWhichId = RES_CHRATR_CTL_LANGUAGE; break;
+ }
+ SfxItemSet aSet(rSh.GetAttrPool(), nLangWhichId, nLangWhichId, 0);
+ rSh.GetCurAttr( aSet );
+ const SvxLanguageItem& rLang = static_cast<const SvxLanguageItem& >(aSet.Get(nLangWhichId));
+ return rLang.GetLanguage();
+}
+/*-------------------------------------------------------------------------
+ create a text portion at the given position
+ -----------------------------------------------------------------------*/
+void SwSpellIter::CreatePortion(uno::Reference< XSpellAlternatives > xAlt,
+ linguistic2::ProofreadingResult* pGrammarResult,
+ bool bIsField, bool bIsHidden)
+{
+ svx::SpellPortion aPortion;
+ String sText;
+ GetSh()->GetSelectedText( sText );
+ if(sText.Len())
+ {
+ //in case of redlined deletions the selection of an error is not
+ //the same as the _real_ word
+ if(xAlt.is())
+ aPortion.sText = xAlt->getWord();
+ else if(pGrammarResult)
+ {
+ aPortion.bIsGrammarError = true;
+ if(pGrammarResult->aErrors.getLength())
+ {
+ aPortion.aGrammarError = pGrammarResult->aErrors[0];
+ aPortion.sText = pGrammarResult->aText.copy( aPortion.aGrammarError.nErrorStart, aPortion.aGrammarError.nErrorLength );
+ aPortion.xGrammarChecker = pGrammarResult->xProofreader;
+ const beans::PropertyValue* pProperties = pGrammarResult->aProperties.getConstArray();
+ for( sal_Int32 nProp = 0; nProp < pGrammarResult->aProperties.getLength(); ++nProp )
+ {
+ if( pProperties->Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("DialogTitle") ) )
+ {
+ pProperties->Value >>= aPortion.sDialogTitle;
+ break;
+ }
+ }
+ }
+ }
+ else
+ aPortion.sText = sText;
+ aPortion.eLanguage = lcl_GetLanguage(*GetSh());
+ aPortion.bIsField = bIsField;
+ aPortion.bIsHidden = bIsHidden;
+ aPortion.xAlternatives = xAlt;
+ SpellContentPosition aPosition;
+ SwPaM *pCrsr = GetSh()->GetCrsr();
+ aPosition.nLeft = pCrsr->Start()->nContent.GetIndex();
+ aPosition.nRight = pCrsr->End()->nContent.GetIndex();
+ aLastPortions.push_back(aPortion);
+ aLastPositions.push_back(aPosition);
+ }
+}
+
+void SwSpellIter::AddPortion(uno::Reference< XSpellAlternatives > xAlt,
+ linguistic2::ProofreadingResult* pGrammarResult,
+ const SpellContentPositions& rDeletedRedlines)
+{
+ SwEditShell *pMySh = GetSh();
+ String sText;
+ pMySh->GetSelectedText( sText );
+ if(sText.Len())
+ {
+ if(xAlt.is() || pGrammarResult != 0)
+ {
+ CreatePortion(xAlt, pGrammarResult, false, false);
+ }
+ else
+ {
+ SwPaM *pCrsr = GetSh()->GetCrsr();
+ if ( *pCrsr->GetPoint() > *pCrsr->GetMark() )
+ pCrsr->Exchange();
+ //save the start and end positions
+ SwPosition aStart(*pCrsr->GetPoint());
+ SwPosition aEnd(*pCrsr->GetMark());
+ //iterate over the text to find changes in language
+ //set the mark equal to the point
+ *pCrsr->GetMark() = aStart;
+ SwTxtNode* pTxtNode = pCrsr->GetNode()->GetTxtNode();
+ LanguageType eStartLanguage = lcl_GetLanguage(*GetSh());
+ SpellContentPosition aNextRedline = lcl_FindNextDeletedRedline(
+ rDeletedRedlines, aStart.nContent.GetIndex() );
+ if( aNextRedline.nLeft == aStart.nContent.GetIndex() )
+ {
+ //select until the end of the current redline
+ xub_StrLen nEnd = aEnd.nContent.GetIndex() < aNextRedline.nRight ?
+ aEnd.nContent.GetIndex() : aNextRedline.nRight;
+ pCrsr->GetPoint()->nContent.Assign( pTxtNode, nEnd );
+ CreatePortion(xAlt, pGrammarResult, false, true);
+ aStart = *pCrsr->End();
+ //search for next redline
+ aNextRedline = lcl_FindNextDeletedRedline(
+ rDeletedRedlines, aStart.nContent.GetIndex() );
+ }
+ while(*pCrsr->GetPoint() < aEnd)
+ {
+ //#125786 in table cell with fixed row height the cursor might not move forward
+ if(!GetSh()->Right(1, CRSR_SKIP_CELLS))
+ break;
+
+ bool bField = false;
+ //read the character at the current position to check if it's a field
+ xub_Unicode cChar = pTxtNode->GetTxt().GetChar( pCrsr->GetMark()->nContent.GetIndex() );
+ if( CH_TXTATR_BREAKWORD == cChar || CH_TXTATR_INWORD == cChar)
+ {
+ const SwTxtAttr* pTxtAttr = pTxtNode->GetTxtAttrForCharAt(
+ pCrsr->GetMark()->nContent.GetIndex() );
+ const sal_uInt16 nWhich = pTxtAttr
+ ? pTxtAttr->Which()
+ : static_cast<sal_uInt16>(RES_TXTATR_END);
+ switch (nWhich)
+ {
+ case RES_TXTATR_FIELD:
+ case RES_TXTATR_FTN:
+ case RES_TXTATR_FLYCNT:
+ bField = true;
+ break;
+ }
+ }
+
+ LanguageType eCurLanguage = lcl_GetLanguage(*GetSh());
+ bool bRedline = aNextRedline.nLeft == pCrsr->GetPoint()->nContent.GetIndex();
+ // create a portion if the next character
+ // - is a field,
+ // - is at the beginning of a deleted redline
+ // - has a different language
+ if(bField || bRedline || eCurLanguage != eStartLanguage)
+ {
+ eStartLanguage = eCurLanguage;
+ //go one step back - the cursor currently selects the first character
+ //with a different language
+ //in the case of redlining it's different
+ if(eCurLanguage != eStartLanguage || bField)
+ *pCrsr->GetPoint() = *pCrsr->GetMark();
+ //set to the last start
+ *pCrsr->GetMark() = aStart;
+ //create portion should only be called if a selection exists
+ //there's no selection if there's a field at the beginning
+ if(*pCrsr->Start() != *pCrsr->End())
+ CreatePortion(xAlt, pGrammarResult, false, false);
+ aStart = *pCrsr->End();
+ //now export the field - if there is any
+ if(bField)
+ {
+ *pCrsr->GetMark() = *pCrsr->GetPoint();
+ GetSh()->Right(1, CRSR_SKIP_CELLS);
+ CreatePortion(xAlt, pGrammarResult, true, false);
+ aStart = *pCrsr->End();
+ }
+ }
+ // if a redline start then create a portion for it
+ if(bRedline)
+ {
+ *pCrsr->GetMark() = *pCrsr->GetPoint();
+ //select until the end of the current redline
+ xub_StrLen nEnd = aEnd.nContent.GetIndex() < aNextRedline.nRight ?
+ aEnd.nContent.GetIndex() : aNextRedline.nRight;
+ pCrsr->GetPoint()->nContent.Assign( pTxtNode, nEnd );
+ CreatePortion(xAlt, pGrammarResult, false, true);
+ aStart = *pCrsr->End();
+ //search for next redline
+ aNextRedline = lcl_FindNextDeletedRedline(
+ rDeletedRedlines, aStart.nContent.GetIndex() );
+ }
+ *pCrsr->GetMark() = *pCrsr->GetPoint();
+ }
+ pCrsr->SetMark();
+ *pCrsr->GetMark() = aStart;
+ CreatePortion(xAlt, pGrammarResult, false, false);
+ }
+ }
+}
+
+void SwEditShell::IgnoreGrammarErrorAt( SwPaM& rErrorPosition )
+{
+ SwTxtNode *pNode;
+ SwWrongList *pWrong;
+ SwNodeIndex aIdx = rErrorPosition.Start()->nNode;
+ SwNodeIndex aEndIdx = rErrorPosition.Start()->nNode;
+ xub_StrLen nStart = rErrorPosition.Start()->nContent.GetIndex();
+ xub_StrLen nEnd = STRING_LEN;
+ while( aIdx <= aEndIdx )
+ {
+ pNode = aIdx.GetNode().GetTxtNode();
+ if( pNode ) {
+ if( aIdx == aEndIdx )
+ nEnd = rErrorPosition.End()->nContent.GetIndex();
+ pWrong = pNode->GetGrammarCheck();
+ if( pWrong )
+ pWrong->RemoveEntry( nStart, nEnd );
+ pWrong = pNode->GetWrong();
+ if( pWrong )
+ pWrong->RemoveEntry( nStart, nEnd );
+ SwTxtFrm::repaintTextFrames( *pNode );
+ }
+ ++aIdx;
+ nStart = 0;
+ }
+}
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/edit/ednumber.cxx b/sw/source/core/edit/ednumber.cxx
new file mode 100644
index 000000000000..f4b54f774903
--- /dev/null
+++ b/sw/source/core/edit/ednumber.cxx
@@ -0,0 +1,801 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+
+#include <hintids.hxx>
+#include <editsh.hxx>
+#include <edimp.hxx>
+#include <doc.hxx>
+#include <IDocumentUndoRedo.hxx>
+#include <ndtxt.hxx>
+#include <paratr.hxx>
+#include <swundo.hxx>
+#include <numrule.hxx>
+
+SV_IMPL_VARARR_SORT( _SwPamRanges, SwPamRange )
+
+
+SwPamRanges::SwPamRanges( const SwPaM& rRing )
+{
+ const SwPaM* pTmp = &rRing;
+ do {
+ Insert( pTmp->GetMark()->nNode, pTmp->GetPoint()->nNode );
+ } while( &rRing != ( pTmp = (const SwPaM*)pTmp->GetNext() ));
+}
+
+
+void SwPamRanges::Insert( const SwNodeIndex& rIdx1, const SwNodeIndex& rIdx2 )
+{
+ SwPamRange aRg( rIdx1.GetIndex(), rIdx2.GetIndex() );
+ if( aRg.nEnd < aRg.nStart )
+ { aRg.nStart = aRg.nEnd; aRg.nEnd = rIdx1.GetIndex(); }
+
+ sal_uInt16 nPos = 0;
+ const SwPamRange* pTmp;
+ if( Count() && Seek_Entry( aRg, &nPos )) // suche Insert Position
+ {
+ // ist der im Array stehende kleiner ??
+ if( ( pTmp = GetData()+ nPos )->nEnd < aRg.nEnd )
+ {
+ aRg.nEnd = pTmp->nEnd;
+ Remove( nPos, 1 ); // zusammenfassen
+ }
+ else
+ return; // ende, weil schon alle zusammengefasst waren
+ }
+
+ sal_Bool bEnde;
+ do {
+ bEnde = sal_True;
+
+ // mit dem Vorgaenger zusammenfassen ??
+ if( nPos > 0 )
+ {
+ if( ( pTmp = GetData()+( nPos-1 ))->nEnd == aRg.nStart
+ || pTmp->nEnd+1 == aRg.nStart )
+ {
+ aRg.nStart = pTmp->nStart;
+ bEnde = sal_False;
+ Remove( --nPos, 1 ); // zusammenfassen
+ }
+ // SSelection im Bereich ??
+ else if( pTmp->nStart <= aRg.nStart && aRg.nEnd <= pTmp->nEnd )
+ return;
+ }
+ // mit dem Nachfolger zusammenfassen ??
+ if( nPos < Count() )
+ {
+ if( ( pTmp = GetData() + nPos )->nStart == aRg.nEnd ||
+ pTmp->nStart == aRg.nEnd+1 )
+ {
+ aRg.nEnd = pTmp->nEnd;
+ bEnde = sal_False;
+ Remove( nPos, 1 ); // zusammenfassen
+ }
+
+ // SSelection im Bereich ??
+ else if( pTmp->nStart <= aRg.nStart && aRg.nEnd <= pTmp->nEnd )
+ return;
+ }
+ } while( !bEnde );
+
+ _SwPamRanges::Insert( aRg );
+}
+
+
+
+SwPaM& SwPamRanges::SetPam( sal_uInt16 nArrPos, SwPaM& rPam )
+{
+ OSL_ASSERT( nArrPos < Count() );
+ const SwPamRange& rTmp = *(GetData() + nArrPos );
+ rPam.GetPoint()->nNode = rTmp.nStart;
+ rPam.GetPoint()->nContent.Assign( rPam.GetCntntNode(), 0 );
+ rPam.SetMark();
+ rPam.GetPoint()->nNode = rTmp.nEnd;
+ rPam.GetPoint()->nContent.Assign( rPam.GetCntntNode(), 0 );
+ return rPam;
+}
+
+
+
+// Numerierung Outline Regelwerk
+
+
+void SwEditShell::SetOutlineNumRule(const SwNumRule& rRule)
+{
+ StartAllAction(); // Klammern fuers Updaten !!
+ GetDoc()->SetOutlineNumRule(rRule);
+ EndAllAction();
+}
+
+
+const SwNumRule* SwEditShell::GetOutlineNumRule() const
+{
+ return GetDoc()->GetOutlineNumRule();
+}
+
+// setzt, wenn noch keine Numerierung, sonst wird geaendert
+// arbeitet mit alten und neuen Regeln, nur Differenzen aktualisieren
+
+// Absaetze ohne Numerierung, aber mit Einzuegen
+
+sal_Bool SwEditShell::NoNum()
+{
+ sal_Bool bRet = sal_True;
+ StartAllAction();
+
+ SwPaM* pCrsr = GetCrsr();
+ if( pCrsr->GetNext() != pCrsr ) // Mehrfachselektion ?
+ {
+ GetDoc()->GetIDocumentUndoRedo().StartUndo( UNDO_START, NULL );
+ SwPamRanges aRangeArr( *pCrsr );
+ SwPaM aPam( *pCrsr->GetPoint() );
+ for( sal_uInt16 n = 0; n < aRangeArr.Count(); ++n )
+ bRet = bRet && GetDoc()->NoNum( aRangeArr.SetPam( n, aPam ));
+ GetDoc()->GetIDocumentUndoRedo().EndUndo( UNDO_END, NULL );
+ }
+ else
+ bRet = GetDoc()->NoNum( *pCrsr );
+
+ EndAllAction();
+ return bRet;
+}
+// Loeschen, Splitten der Aufzaehlungsliste
+
+// -> #i29560#
+sal_Bool SwEditShell::HasNumber() const
+{
+ sal_Bool bResult = sal_False;
+
+ const SwTxtNode * pTxtNd =
+ GetCrsr()->GetPoint()->nNode.GetNode().GetTxtNode();
+
+ if (pTxtNd)
+ {
+ bResult = pTxtNd->HasNumber();
+
+ // special case: outline numbered, not counted paragraph
+ if ( bResult &&
+ pTxtNd->GetNumRule() == GetDoc()->GetOutlineNumRule() &&
+ !pTxtNd->IsCountedInList() )
+ {
+ bResult = sal_False;
+ }
+ }
+
+ return bResult;
+}
+
+sal_Bool SwEditShell::HasBullet() const
+{
+ sal_Bool bResult = sal_False;
+
+ const SwTxtNode * pTxtNd =
+ GetCrsr()->GetPoint()->nNode.GetNode().GetTxtNode();
+
+ if (pTxtNd)
+ {
+ bResult = pTxtNd->HasBullet();
+ }
+
+ return bResult;
+}
+// <- #i29560#
+
+void SwEditShell::DelNumRules()
+{
+ StartAllAction();
+
+ SwPaM* pCrsr = GetCrsr();
+ if( pCrsr->GetNext() != pCrsr ) // Mehrfachselektion ?
+ {
+ GetDoc()->GetIDocumentUndoRedo().StartUndo( UNDO_START, NULL );
+ SwPamRanges aRangeArr( *pCrsr );
+ SwPaM aPam( *pCrsr->GetPoint() );
+ for( sal_uInt16 n = 0; n < aRangeArr.Count(); ++n )
+ {
+ GetDoc()->DelNumRules( aRangeArr.SetPam( n, aPam ) );
+ }
+ GetDoc()->GetIDocumentUndoRedo().EndUndo( UNDO_END, NULL );
+ }
+ else
+ GetDoc()->DelNumRules( *pCrsr );
+
+ // rufe das AttrChangeNotify auf der UI-Seite. Sollte eigentlich
+ // ueberfluessig sein, aber VB hatte darueber eine Bugrep.
+ CallChgLnk();
+
+ // cursor can not be anymore in front of a label,
+ // because numbering/bullet is deleted.
+ SetInFrontOfLabel( sal_False );
+
+ GetDoc()->SetModified();
+ EndAllAction();
+}
+
+// Hoch-/Runterstufen
+
+
+sal_Bool SwEditShell::NumUpDown( sal_Bool bDown )
+{
+ StartAllAction();
+
+ sal_Bool bRet = sal_True;
+ SwPaM* pCrsr = GetCrsr();
+ if( pCrsr->GetNext() == pCrsr ) // keine Mehrfachselektion ?
+ bRet = GetDoc()->NumUpDown( *pCrsr, bDown );
+ else
+ {
+ GetDoc()->GetIDocumentUndoRedo().StartUndo( UNDO_START, NULL );
+ SwPamRanges aRangeArr( *pCrsr );
+ SwPaM aPam( *pCrsr->GetPoint() );
+ for( sal_uInt16 n = 0; n < aRangeArr.Count(); ++n )
+ bRet = bRet && GetDoc()->NumUpDown( aRangeArr.SetPam( n, aPam ), bDown );
+ GetDoc()->GetIDocumentUndoRedo().EndUndo( UNDO_END, NULL );
+ }
+ GetDoc()->SetModified();
+
+ // --> FME 2005-09-19 #i54693# Update marked numbering levels
+ if ( IsInFrontOfLabel() )
+ UpdateMarkedListLevel();
+ // <--
+
+ CallChgLnk();
+
+ EndAllAction();
+ return bRet;
+}
+// -> #i23726#
+sal_Bool SwEditShell::IsFirstOfNumRule() const
+{
+ sal_Bool bResult = sal_False;
+
+ SwPaM * pCrsr = GetCrsr();
+ if (pCrsr->GetNext() == pCrsr)
+ {
+ bResult = IsFirstOfNumRule(*pCrsr);
+ }
+
+ return bResult;
+}
+
+sal_Bool SwEditShell::IsFirstOfNumRule(const SwPaM & rPaM) const
+{
+ sal_Bool bResult = sal_False;
+
+ SwPosition aPos(*rPaM.GetPoint());
+ bResult = GetDoc()->IsFirstOfNumRule(aPos);
+
+ return bResult;
+}
+// <- #i23726#
+
+// -> #i23725#
+// --> OD 2008-06-09 #i90078#
+// Remove unused default parameter <nLevel> and <bRelative>.
+// Adjust method name and parameter name
+void SwEditShell::ChangeIndentOfAllListLevels( short nDiff )
+{
+ StartAllAction();
+
+ const SwNumRule *pCurNumRule = GetCurNumRule();
+ //#120911# check if numbering rule really exists
+ if (pCurNumRule)
+ {
+ SwNumRule aRule(*pCurNumRule);
+ // --> OD 2008-06-09 #i90078#
+ aRule.ChangeIndent( nDiff );
+ // <--
+
+ // no start of new list
+ SetCurNumRule( aRule, false );
+ }
+
+ EndAllAction();
+}
+
+// --> OD 2008-06-09 #i90078#
+// Adjust method name
+void SwEditShell::SetIndent(short nIndent, const SwPosition & rPos)
+// <--
+{
+ StartAllAction();
+
+ SwNumRule *pCurNumRule = GetDoc()->GetCurrNumRule(rPos);
+
+ if (pCurNumRule)
+ {
+ SwPaM aPaM(rPos);
+ SwTxtNode * pTxtNode = aPaM.GetNode()->GetTxtNode();
+
+ // --> OD 2008-06-09 #i90078#
+
+ SwNumRule aRule(*pCurNumRule);
+
+ if ( IsFirstOfNumRule() )
+ {
+ aRule.SetIndentOfFirstListLevelAndChangeOthers( nIndent );
+ }
+ else if ( pTxtNode->GetActualListLevel() >= 0 )
+ {
+ aRule.SetIndent( nIndent,
+ static_cast<sal_uInt16>(pTxtNode->GetActualListLevel()) );
+ }
+ // <--
+
+ // --> OD 2005-02-18 #i42921# - 3rd parameter = false in order to
+ // suppress setting of num rule at <aPaM>.
+ // do not apply any list
+ GetDoc()->SetNumRule( aPaM, aRule, false, String(), sal_False );
+ // <--
+ }
+
+ EndAllAction();
+}
+// <- #i23725#
+
+sal_Bool SwEditShell::MoveParagraph( long nOffset )
+{
+ StartAllAction();
+
+ SwPaM *pCrsr = GetCrsr();
+ if( !pCrsr->HasMark() )
+ {
+ // sorge dafuer, das Bound1 und Bound2 im gleichen Node stehen
+ pCrsr->SetMark();
+ pCrsr->DeleteMark();
+ }
+
+ sal_Bool bRet = GetDoc()->MoveParagraph( *pCrsr, nOffset );
+
+ GetDoc()->SetModified();
+ EndAllAction();
+ return bRet;
+}
+
+//#outline level add by zhaojianwei
+int SwEditShell::GetCurrentParaOutlineLevel( ) const
+{
+ int nLevel = 0;
+
+ SwPaM* pCrsr = GetCrsr();
+ const SwTxtNode* pTxtNd = pCrsr->GetNode()->GetTxtNode();
+ if( pTxtNd )
+ nLevel = pTxtNd->GetAttrOutlineLevel();
+ return nLevel;
+}
+//<-end,zhaojianwei
+
+void SwEditShell::GetCurrentOutlineLevels( sal_uInt8& rUpper, sal_uInt8& rLower )
+{
+ SwPaM* pCrsr = GetCrsr();
+ SwPaM aCrsr( *pCrsr->Start() );
+ aCrsr.SetMark();
+ if( pCrsr->HasMark() )
+ *aCrsr.GetPoint() = *pCrsr->End();
+ GetDoc()->GotoNextNum( *aCrsr.GetPoint(), sal_False,
+ &rUpper, &rLower );
+}
+
+sal_Bool SwEditShell::MoveNumParas( sal_Bool bUpperLower, sal_Bool bUpperLeft )
+{
+ StartAllAction();
+
+ // auf alle Selektionen ??
+ SwPaM* pCrsr = GetCrsr();
+ SwPaM aCrsr( *pCrsr->Start() );
+ aCrsr.SetMark();
+
+ if( pCrsr->HasMark() )
+ *aCrsr.GetPoint() = *pCrsr->End();
+
+ sal_Bool bRet = sal_False;
+ sal_uInt8 nUpperLevel, nLowerLevel;
+ if( GetDoc()->GotoNextNum( *aCrsr.GetPoint(), sal_False,
+ &nUpperLevel, &nLowerLevel ))
+ {
+ if( bUpperLower )
+ {
+ // ueber die naechste Nummerierung
+ long nOffset = 0;
+ const SwNode* pNd;
+
+ if( bUpperLeft ) // verschiebe nach oben
+ {
+ SwPosition aPos( *aCrsr.GetMark() );
+ if( GetDoc()->GotoPrevNum( aPos, sal_False ) )
+ nOffset = aPos.nNode.GetIndex() -
+ aCrsr.GetMark()->nNode.GetIndex();
+ else
+ {
+ sal_uLong nStt = aPos.nNode.GetIndex(), nIdx = nStt - 1;
+ while( nIdx && (
+ ( pNd = GetDoc()->GetNodes()[ nIdx ])->IsSectionNode() ||
+ ( pNd->IsEndNode() && pNd->StartOfSectionNode()->IsSectionNode())))
+ --nIdx;
+ if( GetDoc()->GetNodes()[ nIdx ]->IsTxtNode() )
+ nOffset = nIdx - nStt;
+ }
+ }
+ else // verschiebe nach unten
+ {
+ const SwNumRule* pOrig = aCrsr.GetNode(sal_False)->GetTxtNode()->GetNumRule();
+ if( aCrsr.GetNode()->IsTxtNode() &&
+ pOrig == aCrsr.GetNode()->GetTxtNode()->GetNumRule() )
+ {
+ sal_uLong nStt = aCrsr.GetPoint()->nNode.GetIndex(), nIdx = nStt+1;
+
+ while (nIdx < GetDoc()->GetNodes().Count()-1)
+ {
+ pNd = GetDoc()->GetNodes()[ nIdx ];
+
+ if (pNd->IsSectionNode() ||
+ ( pNd->IsEndNode() && pNd->StartOfSectionNode()->IsSectionNode()) ||
+ ( pNd->IsTxtNode() && pOrig == ((SwTxtNode*)pNd)->GetNumRule() &&
+ ((SwTxtNode*)pNd)->GetActualListLevel() > nUpperLevel ))
+ {
+ ++nIdx;
+ }
+ // --> OD 2005-11-14 #i57856#
+ else
+ {
+ break;
+ }
+ // <--
+ }
+
+ if( nStt == nIdx || !GetDoc()->GetNodes()[ nIdx ]->IsTxtNode() )
+ nOffset = 1;
+ else
+ nOffset = nIdx - nStt;
+ }
+ else
+ nOffset = 1;
+ }
+
+ if( nOffset )
+ {
+ aCrsr.Move( fnMoveBackward, fnGoNode );
+ bRet = GetDoc()->MoveParagraph( aCrsr, nOffset );
+ }
+ }
+ else if( bUpperLeft ? nUpperLevel : nLowerLevel+1 < MAXLEVEL )
+ {
+ aCrsr.Move( fnMoveBackward, fnGoNode );
+ bRet = GetDoc()->NumUpDown( aCrsr, !bUpperLeft );
+ }
+ }
+
+ GetDoc()->SetModified();
+ EndAllAction();
+ return bRet;
+}
+
+sal_Bool SwEditShell::OutlineUpDown( short nOffset )
+{
+ StartAllAction();
+
+ sal_Bool bRet = sal_True;
+ SwPaM* pCrsr = GetCrsr();
+ if( pCrsr->GetNext() == pCrsr ) // keine Mehrfachselektion ?
+ bRet = GetDoc()->OutlineUpDown( *pCrsr, nOffset );
+ else
+ {
+ GetDoc()->GetIDocumentUndoRedo().StartUndo( UNDO_START, NULL );
+ SwPamRanges aRangeArr( *pCrsr );
+ SwPaM aPam( *pCrsr->GetPoint() );
+ for( sal_uInt16 n = 0; n < aRangeArr.Count(); ++n )
+ bRet = bRet && GetDoc()->OutlineUpDown(
+ aRangeArr.SetPam( n, aPam ), nOffset );
+ GetDoc()->GetIDocumentUndoRedo().EndUndo( UNDO_END, NULL );
+ }
+ GetDoc()->SetModified();
+ EndAllAction();
+ return bRet;
+}
+
+
+sal_Bool SwEditShell::MoveOutlinePara( short nOffset )
+{
+ StartAllAction();
+ sal_Bool bRet = GetDoc()->MoveOutlinePara( *GetCrsr(), nOffset );
+ EndAllAction();
+ return bRet;
+}
+
+// Outlines and SubOutline are ReadOnly?
+sal_Bool SwEditShell::IsProtectedOutlinePara() const
+{
+ sal_Bool bRet = sal_False;
+ const SwNode& rNd = GetCrsr()->Start()->nNode.GetNode();
+ if( rNd.IsTxtNode() )
+ {
+ const SwOutlineNodes& rOutlNd = GetDoc()->GetNodes().GetOutLineNds();
+ SwNodePtr pNd = (SwNodePtr)&rNd;
+ sal_Bool bFirst = sal_True;
+ sal_uInt16 nPos;
+ int nLvl(0);
+ if( !rOutlNd.Seek_Entry( pNd, &nPos ) && nPos )
+ --nPos;
+
+ for( ; nPos < rOutlNd.Count(); ++nPos )
+ {
+ SwNodePtr pTmpNd = rOutlNd[ nPos ];
+
+ int nTmpLvl = pTmpNd->GetTxtNode()->GetAttrOutlineLevel();
+
+ OSL_ENSURE( nTmpLvl >= 0 && nTmpLvl <= MAXLEVEL,
+ "<SwEditShell::IsProtectedOutlinePara()>" );
+
+ if( bFirst )
+ {
+ nLvl = nTmpLvl;
+ bFirst = sal_False;
+ }
+ else if( nLvl >= nTmpLvl )
+ break;
+
+ if( pTmpNd->IsProtect() )
+ {
+ bRet = sal_True;
+ break;
+ }
+ }
+ }
+#if OSL_DEBUG_LEVEL > 1
+ else
+ {
+ OSL_ENSURE(!this, "Cursor not on an outline node" );
+ }
+#endif
+ return bRet;
+}
+
+/** Test whether outline may be moved (bCopy == false)
+ * or copied (bCopy == true)
+ * Verify these conditions:
+ * 1) outline must be within main body (and not in redline)
+ * 2) outline must not be within table
+ * 3) if bCopy is set, outline must not be write protected
+ */
+sal_Bool lcl_IsOutlineMoveAndCopyable( const SwDoc* pDoc, sal_uInt16 nIdx, bool bCopy )
+{
+ const SwNodes& rNds = pDoc->GetNodes();
+ const SwNode* pNd = rNds.GetOutLineNds()[ nIdx ];
+ return pNd->GetIndex() >= rNds.GetEndOfExtras().GetIndex() && // 1) body
+ !pNd->FindTableNode() && // 2) table
+ ( bCopy || !pNd->IsProtect() ); // 3) write
+}
+
+sal_Bool SwEditShell::IsOutlineMovable( sal_uInt16 nIdx ) const
+{
+ return lcl_IsOutlineMoveAndCopyable( GetDoc(), nIdx, false );
+}
+
+sal_Bool SwEditShell::IsOutlineCopyable( sal_uInt16 nIdx ) const
+{
+ return lcl_IsOutlineMoveAndCopyable( GetDoc(), nIdx, true );
+}
+
+
+sal_Bool SwEditShell::NumOrNoNum( sal_Bool bNumOn, sal_Bool bChkStart )
+{
+ sal_Bool bRet = sal_False;
+ SwPaM* pCrsr = GetCrsr();
+ if( pCrsr->GetNext() == pCrsr && !pCrsr->HasMark() &&
+ ( !bChkStart || !pCrsr->GetPoint()->nContent.GetIndex()) )
+ {
+ StartAllAction(); // Klammern fuers Updaten !!
+ bRet = GetDoc()->NumOrNoNum( pCrsr->GetPoint()->nNode, !bNumOn ); // #i29560#
+ EndAllAction();
+ }
+ return bRet;
+}
+
+sal_Bool SwEditShell::IsNoNum( sal_Bool bChkStart ) const
+{
+ // ein Backspace im Absatz ohne Nummer wird zum Delete
+ sal_Bool bResult = sal_False;
+ SwPaM* pCrsr = GetCrsr();
+
+ if (pCrsr->GetNext() == pCrsr && !pCrsr->HasMark() &&
+ (!bChkStart || !pCrsr->GetPoint()->nContent.GetIndex()))
+ {
+ const SwTxtNode* pTxtNd = pCrsr->GetNode()->GetTxtNode();
+
+ if (pTxtNd)
+ {
+ bResult = ! pTxtNd->IsCountedInList();
+ }
+ }
+
+ return bResult;
+}
+
+sal_uInt8 SwEditShell::GetNumLevel() const
+{
+ // gebe die akt. Ebene zurueck, auf der sich der Point vom Cursor befindet
+ sal_uInt8 nLevel = MAXLEVEL; //end,zhaojianwei
+
+ SwPaM* pCrsr = GetCrsr();
+ const SwTxtNode* pTxtNd = pCrsr->GetNode()->GetTxtNode();
+
+ OSL_ENSURE( pTxtNd, "GetNumLevel() without text node" );
+ if ( !pTxtNd )
+ return nLevel;
+
+ const SwNumRule* pRule = pTxtNd->GetNumRule();
+ if(pRule)
+ {
+ const int nListLevelOfTxtNode( pTxtNd->GetActualListLevel() );
+ if ( nListLevelOfTxtNode >= 0 )
+ {
+ nLevel = static_cast<sal_uInt8>( nListLevelOfTxtNode );
+ }
+ }
+
+ return nLevel;
+}
+
+const SwNumRule* SwEditShell::GetCurNumRule() const
+{
+ return GetDoc()->GetCurrNumRule( *GetCrsr()->GetPoint() );
+}
+
+void SwEditShell::SetCurNumRule( const SwNumRule& rRule,
+ const bool bCreateNewList,
+ const String sContinuedListId,
+ const bool bResetIndentAttrs )
+{
+ StartAllAction();
+
+ GetDoc()->GetIDocumentUndoRedo().StartUndo( UNDO_START, NULL );
+
+ SwPaM* pCrsr = GetCrsr();
+ if( pCrsr->GetNext() != pCrsr ) // Mehrfachselektion ?
+ {
+ SwPamRanges aRangeArr( *pCrsr );
+ SwPaM aPam( *pCrsr->GetPoint() );
+ for( sal_uInt16 n = 0; n < aRangeArr.Count(); ++n )
+ {
+ aRangeArr.SetPam( n, aPam );
+ GetDoc()->SetNumRule( aPam, rRule,
+ bCreateNewList, sContinuedListId,
+ sal_True, bResetIndentAttrs );
+ GetDoc()->SetCounted( aPam, true );
+ }
+ }
+ else
+ {
+ GetDoc()->SetNumRule( *pCrsr, rRule,
+ bCreateNewList, sContinuedListId,
+ sal_True, bResetIndentAttrs );
+ GetDoc()->SetCounted( *pCrsr, true );
+ }
+ GetDoc()->GetIDocumentUndoRedo().EndUndo( UNDO_END, NULL );
+
+ EndAllAction();
+}
+
+String SwEditShell::GetUniqueNumRuleName( const String* pChkStr, sal_Bool bAutoNum ) const
+{
+ return GetDoc()->GetUniqueNumRuleName( pChkStr, bAutoNum );
+}
+
+void SwEditShell::ChgNumRuleFmts( const SwNumRule& rRule )
+{
+ StartAllAction();
+ GetDoc()->ChgNumRuleFmts( rRule );
+ EndAllAction();
+}
+
+sal_Bool SwEditShell::ReplaceNumRule( const String& rOldRule, const String& rNewRule )
+{
+ StartAllAction();
+ sal_Bool bRet = GetDoc()->ReplaceNumRule( *GetCrsr()->GetPoint(), rOldRule, rNewRule );
+ EndAllAction();
+ return bRet;
+}
+
+void SwEditShell::SetNumRuleStart( sal_Bool bFlag )
+{
+ StartAllAction();
+
+ SwPaM* pCrsr = GetCrsr();
+ if( pCrsr->GetNext() != pCrsr ) // Mehrfachselektion ?
+ {
+ GetDoc()->GetIDocumentUndoRedo().StartUndo( UNDO_START, NULL );
+ SwPamRanges aRangeArr( *pCrsr );
+ SwPaM aPam( *pCrsr->GetPoint() );
+ for( sal_uInt16 n = 0; n < aRangeArr.Count(); ++n )
+ GetDoc()->SetNumRuleStart( *aRangeArr.SetPam( n, aPam ).GetPoint(), bFlag );
+ GetDoc()->GetIDocumentUndoRedo().EndUndo( UNDO_END, NULL );
+ }
+ else
+ GetDoc()->SetNumRuleStart( *pCrsr->GetPoint(), bFlag );
+
+ EndAllAction();
+}
+
+sal_Bool SwEditShell::IsNumRuleStart() const
+{
+ sal_Bool bResult = sal_False;
+ const SwTxtNode* pTxtNd = GetCrsr()->GetNode()->GetTxtNode();
+ if( pTxtNd )
+ bResult = pTxtNd->IsListRestart() ? sal_True : sal_False;
+ return bResult;
+}
+
+void SwEditShell::SetNodeNumStart( sal_uInt16 nStt )
+{
+ StartAllAction();
+
+ SwPaM* pCrsr = GetCrsr();
+ if( pCrsr->GetNext() != pCrsr ) // Mehrfachselektion ?
+ {
+ GetDoc()->GetIDocumentUndoRedo().StartUndo( UNDO_START, NULL );
+ SwPamRanges aRangeArr( *pCrsr );
+ SwPaM aPam( *pCrsr->GetPoint() );
+ for( sal_uInt16 n = 0; n < aRangeArr.Count(); ++n )
+ GetDoc()->SetNodeNumStart( *aRangeArr.SetPam( n, aPam ).GetPoint(), nStt );
+ GetDoc()->GetIDocumentUndoRedo().EndUndo( UNDO_END, NULL );
+ }
+ else
+ GetDoc()->SetNodeNumStart( *pCrsr->GetPoint(), nStt );
+
+ EndAllAction();
+}
+
+sal_uInt16 SwEditShell::GetNodeNumStart() const
+{
+ const SwTxtNode* pTxtNd = GetCrsr()->GetNode()->GetTxtNode();
+ // correction: check, if list restart value is set at text node and
+ // use new method <SwTxtNode::GetAttrListRestartValue()>.
+ // return USHRT_MAX, if no list restart value is found.
+ if ( pTxtNd && pTxtNd->HasAttrListRestartValue() )
+ {
+ return static_cast<sal_uInt16>(pTxtNd->GetAttrListRestartValue());
+ }
+ return USHRT_MAX;
+}
+
+const SwNumRule * SwEditShell::SearchNumRule( const bool bForward,
+ const bool bNum,
+ const bool bOutline,
+ int nNonEmptyAllowed,
+ String& sListId )
+{
+ return GetDoc()->SearchNumRule( *(bForward ? GetCrsr()->End() : GetCrsr()->Start()),
+ bForward, bNum, bOutline, nNonEmptyAllowed,
+ sListId );
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/edit/edredln.cxx b/sw/source/core/edit/edredln.cxx
new file mode 100644
index 000000000000..44116e4ebf5c
--- /dev/null
+++ b/sw/source/core/edit/edredln.cxx
@@ -0,0 +1,152 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+
+#include <docary.hxx>
+#include <vcl/window.hxx>
+#include "redline.hxx"
+#include "doc.hxx"
+#include "swundo.hxx"
+#include "editsh.hxx"
+#include "edimp.hxx"
+#include "frmtool.hxx"
+
+
+sal_uInt16 SwEditShell::GetRedlineMode() const
+{
+ return GetDoc()->GetRedlineMode();
+}
+
+void SwEditShell::SetRedlineMode( sal_uInt16 eMode )
+{
+ if( eMode != GetDoc()->GetRedlineMode() )
+ {
+ SET_CURR_SHELL( this );
+ StartAllAction();
+ GetDoc()->SetRedlineMode( (RedlineMode_t)eMode );
+ EndAllAction();
+ }
+}
+
+sal_Bool SwEditShell::IsRedlineOn() const
+{
+ return GetDoc()->IsRedlineOn();
+}
+
+sal_uInt16 SwEditShell::GetRedlineCount() const
+{
+ return GetDoc()->GetRedlineTbl().Count();
+}
+
+const SwRedline& SwEditShell::GetRedline( sal_uInt16 nPos ) const
+{
+ return *GetDoc()->GetRedlineTbl()[ nPos ];
+}
+
+void lcl_InvalidateAll( ViewShell* pSh )
+{
+ ViewShell *pStop = pSh;
+ do
+ {
+ if ( pSh->GetWin() )
+ pSh->GetWin()->Invalidate();
+ pSh = (ViewShell*)pSh->GetNext();
+
+ } while ( pSh != pStop );
+}
+
+sal_Bool SwEditShell::AcceptRedline( sal_uInt16 nPos )
+{
+ SET_CURR_SHELL( this );
+ StartAllAction();
+ sal_Bool bRet = GetDoc()->AcceptRedline( nPos, true );
+ if( !nPos && !::IsExtraData( GetDoc() ) )
+ lcl_InvalidateAll( this );
+ EndAllAction();
+ return bRet;
+}
+
+sal_Bool SwEditShell::RejectRedline( sal_uInt16 nPos )
+{
+ SET_CURR_SHELL( this );
+ StartAllAction();
+ sal_Bool bRet = GetDoc()->RejectRedline( nPos, true );
+ if( !nPos && !::IsExtraData( GetDoc() ) )
+ lcl_InvalidateAll( this );
+ EndAllAction();
+ return bRet;
+}
+
+// Kommentar am Redline setzen
+sal_Bool SwEditShell::SetRedlineComment( const String& rS )
+{
+ sal_Bool bRet = sal_False;
+ FOREACHPAM_START(this)
+ bRet = bRet || GetDoc()->SetRedlineComment( *PCURCRSR, rS );
+ FOREACHPAM_END()
+
+ return bRet;
+}
+
+const SwRedline* SwEditShell::GetCurrRedline() const
+{
+ return GetDoc()->GetRedline( *GetCrsr()->GetPoint(), 0 );
+}
+
+void SwEditShell::UpdateRedlineAttr()
+{
+ if( ( nsRedlineMode_t::REDLINE_SHOW_INSERT | nsRedlineMode_t::REDLINE_SHOW_DELETE ) ==
+ ( nsRedlineMode_t::REDLINE_SHOW_MASK & GetDoc()->GetRedlineMode() ))
+ {
+ SET_CURR_SHELL( this );
+ StartAllAction();
+
+ GetDoc()->UpdateRedlineAttr();
+
+ EndAllAction();
+ }
+}
+
+ // suche das Redline zu diesem Data und returne die Pos im Array
+ // USHRT_MAX wird returnt, falls nicht vorhanden
+sal_uInt16 SwEditShell::FindRedlineOfData( const SwRedlineData& rData ) const
+{
+ const SwRedlineTbl& rTbl = GetDoc()->GetRedlineTbl();
+
+ for( sal_uInt16 i = 0, nCnt = rTbl.Count(); i < nCnt; ++i )
+ if( &rTbl[ i ]->GetRedlineData() == &rData )
+ return i;
+ return USHRT_MAX;
+}
+
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/edit/edsect.cxx b/sw/source/core/edit/edsect.cxx
new file mode 100644
index 000000000000..25e4dcb434af
--- /dev/null
+++ b/sw/source/core/edit/edsect.cxx
@@ -0,0 +1,455 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+#include <editsh.hxx>
+#include <doc.hxx>
+#include <IDocumentUndoRedo.hxx>
+#include <pam.hxx>
+#include <docary.hxx>
+#include <swundo.hxx> // fuer die UndoIds
+#include <section.hxx>
+#include <edimp.hxx>
+#include <sectfrm.hxx> // SwSectionFrm
+#include <cntfrm.hxx> // SwCntntFrm
+#include <tabfrm.hxx> // SwTabFrm
+#include <rootfrm.hxx> // SwRootFrm
+
+
+SwSection const*
+SwEditShell::InsertSection(
+ SwSectionData & rNewData, SfxItemSet const*const pAttr)
+{
+ const SwSection* pRet = 0;
+ if( !IsTableMode() )
+ {
+ StartAllAction();
+ GetDoc()->GetIDocumentUndoRedo().StartUndo( UNDO_INSSECTION, NULL );
+
+ FOREACHPAM_START(this)
+ SwSection const*const pNew =
+ GetDoc()->InsertSwSection( *PCURCRSR, rNewData, 0, pAttr );
+ if( !pRet )
+ pRet = pNew;
+ FOREACHPAM_END()
+
+ GetDoc()->GetIDocumentUndoRedo().EndUndo( UNDO_INSSECTION, NULL );
+ EndAllAction();
+ }
+ return pRet;
+}
+
+
+sal_Bool SwEditShell::IsInsRegionAvailable() const
+{
+ if( IsTableMode() )
+ return sal_False;
+ SwPaM* pCrsr = GetCrsr();
+ if( pCrsr->GetNext() != pCrsr )
+ return sal_False;
+ if( pCrsr->HasMark() )
+ return 0 != GetDoc()->IsInsRegionAvailable( *pCrsr );
+
+ return sal_True;
+}
+
+
+const SwSection* SwEditShell::GetCurrSection() const
+{
+ if( IsTableMode() )
+ return 0;
+
+ return GetDoc()->GetCurrSection( *GetCrsr()->GetPoint() );
+}
+
+/*--------------------------------------------------
+ * SwEditShell::GetAnySection liefert den fuer Spalten
+ * zustaendigen Bereich, bei Fussnoten kann es nicht der
+ * Bereich innerhalb der Fussnote sein.
+ * --------------------------------------------------*/
+
+const SwSection* SwEditShell::GetAnySection( sal_Bool bOutOfTab, const Point* pPt ) const
+{
+ SwFrm *pFrm;
+ if ( pPt )
+ {
+ SwPosition aPos( *GetCrsr()->GetPoint() );
+ Point aPt( *pPt );
+ GetLayout()->GetCrsrOfst( &aPos, aPt );
+ SwCntntNode *pNd = aPos.nNode.GetNode().GetCntntNode();
+ pFrm = pNd->getLayoutFrm( GetLayout(), pPt );
+ }
+ else
+ pFrm = GetCurrFrm( sal_False );
+
+ if( bOutOfTab && pFrm )
+ pFrm = pFrm->FindTabFrm();
+ if( pFrm && pFrm->IsInSct() )
+ {
+ SwSectionFrm* pSect = pFrm->FindSctFrm();
+ OSL_ENSURE( pSect, "GetAnySection: Where's my Sect?" );
+ if( pSect->IsInFtn() && pSect->GetUpper()->IsInSct() )
+ {
+ pSect = pSect->GetUpper()->FindSctFrm();
+ OSL_ENSURE( pSect, "GetAnySection: Where's my SectFrm?" );
+ }
+ return pSect->GetSection();
+ }
+ return NULL;
+}
+
+sal_uInt16 SwEditShell::GetSectionFmtCount() const
+{
+ return GetDoc()->GetSections().Count();
+}
+
+
+sal_Bool SwEditShell::IsAnySectionInDoc( sal_Bool bChkReadOnly, sal_Bool bChkHidden, sal_Bool bChkTOX ) const
+{
+ const SwSectionFmts& rFmts = GetDoc()->GetSections();
+ sal_uInt16 nCnt = rFmts.Count();
+ sal_uInt16 n;
+
+ for( n = 0; n < nCnt; ++n )
+ {
+ SectionType eTmpType;
+ const SwSectionFmt* pFmt = rFmts[ n ];
+ if( pFmt->IsInNodesArr() &&
+ (bChkTOX ||
+ ( (eTmpType = pFmt->GetSection()->GetType()) != TOX_CONTENT_SECTION
+ && TOX_HEADER_SECTION != eTmpType ) ) )
+ {
+ const SwSection& rSect = *rFmts[ n ]->GetSection();
+ if( (!bChkReadOnly && !bChkHidden ) ||
+ (bChkReadOnly && rSect.IsProtectFlag() ) ||
+ (bChkHidden && rSect.IsHiddenFlag() ) )
+ break;
+ }
+ }
+ return n != nCnt;
+}
+
+sal_uInt16 SwEditShell::GetSectionFmtPos( const SwSectionFmt& rFmt ) const
+{
+ SwSectionFmt* pFmt = (SwSectionFmt*)&rFmt;
+ return GetDoc()->GetSections().GetPos( pFmt );
+}
+
+const SwSectionFmt& SwEditShell::GetSectionFmt( sal_uInt16 nFmt ) const
+{
+ return *GetDoc()->GetSections()[ nFmt ];
+}
+
+
+void SwEditShell::DelSectionFmt( sal_uInt16 nFmt )
+{
+ StartAllAction();
+ GetDoc()->DelSectionFmt( GetDoc()->GetSections()[ nFmt ] );
+ // rufe das AttrChangeNotify auf der UI-Seite.
+ CallChgLnk();
+ EndAllAction();
+}
+
+
+void SwEditShell::UpdateSection(sal_uInt16 const nSect,
+ SwSectionData & rNewData, SfxItemSet const*const pAttr)
+{
+ StartAllAction();
+ GetDoc()->UpdateSection( nSect, rNewData, pAttr );
+ // rufe das AttrChangeNotify auf der UI-Seite.
+ CallChgLnk();
+ EndAllAction();
+}
+
+String SwEditShell::GetUniqueSectionName( const String* pChkStr ) const
+{
+ return GetDoc()->GetUniqueSectionName( pChkStr );
+}
+
+void SwEditShell::SetSectionAttr( const SfxItemSet& rSet,
+ SwSectionFmt* pSectFmt )
+{
+ if( pSectFmt )
+ _SetSectionAttr( *pSectFmt, rSet );
+ else
+ {
+ // for all section in the selection
+
+ FOREACHPAM_START(this)
+
+ const SwPosition* pStt = PCURCRSR->Start(),
+ * pEnd = PCURCRSR->End();
+
+ const SwSectionNode* pSttSectNd = pStt->nNode.GetNode().FindSectionNode(),
+ * pEndSectNd = pEnd->nNode.GetNode().FindSectionNode();
+
+ if( pSttSectNd || pEndSectNd )
+ {
+ if( pSttSectNd )
+ _SetSectionAttr( *pSttSectNd->GetSection().GetFmt(),
+ rSet );
+ if( pEndSectNd && pSttSectNd != pEndSectNd )
+ _SetSectionAttr( *pEndSectNd->GetSection().GetFmt(),
+ rSet );
+
+ if( pSttSectNd && pEndSectNd )
+ {
+ SwNodeIndex aSIdx( pStt->nNode );
+ SwNodeIndex aEIdx( pEnd->nNode );
+ if( pSttSectNd->EndOfSectionIndex() <
+ pEndSectNd->GetIndex() )
+ {
+ aSIdx = pSttSectNd->EndOfSectionIndex() + 1;
+ aEIdx = *pEndSectNd;
+ }
+
+ while( aSIdx < aEIdx )
+ {
+ if( 0 != (pSttSectNd = aSIdx.GetNode().GetSectionNode())
+ || ( aSIdx.GetNode().IsEndNode() &&
+ 0 != ( pSttSectNd = aSIdx.GetNode().
+ StartOfSectionNode()->GetSectionNode())) )
+ _SetSectionAttr( *pSttSectNd->GetSection().GetFmt(),
+ rSet );
+ aSIdx++;
+ }
+ }
+ }
+
+ FOREACHPAM_END()
+ }
+}
+
+void SwEditShell::_SetSectionAttr( SwSectionFmt& rSectFmt,
+ const SfxItemSet& rSet )
+{
+ StartAllAction();
+ if(SFX_ITEM_SET == rSet.GetItemState(RES_CNTNT, sal_False))
+ {
+ SfxItemSet aSet(rSet);
+ aSet.ClearItem(RES_CNTNT);
+ GetDoc()->SetAttr( aSet, rSectFmt );
+ }
+ else
+ GetDoc()->SetAttr( rSet, rSectFmt );
+
+ // rufe das AttrChangeNotify auf der UI-Seite.
+ CallChgLnk();
+ EndAllAction();
+}
+
+// search inside the cursor selection for full selected sections.
+// if any part of section in the selection return 0.
+// if more than one in the selection return the count
+sal_uInt16 SwEditShell::GetFullSelectedSectionCount() const
+{
+ sal_uInt16 nRet = 0;
+ FOREACHPAM_START(this)
+
+ const SwPosition* pStt = PCURCRSR->Start(),
+ * pEnd = PCURCRSR->End();
+ const SwCntntNode* pCNd;
+ // check the selection, if Start at Node begin and End at Node end
+ if( pStt->nContent.GetIndex() ||
+ ( 0 == ( pCNd = pEnd->nNode.GetNode().GetCntntNode() )) ||
+ pCNd->Len() != pEnd->nContent.GetIndex() )
+ {
+ nRet = 0;
+ break;
+ }
+
+// !!!!!!!!!!!!!!!!!!!!!!!!!!
+// what about table at start or end ?
+// There is no selection possible!
+// What about only a table inside the section ?
+// There is only a table selection possible!
+
+ SwNodeIndex aSIdx( pStt->nNode, -1 ), aEIdx( pEnd->nNode, +1 );
+ if( !aSIdx.GetNode().IsSectionNode() ||
+ !aEIdx.GetNode().IsEndNode() ||
+ !aEIdx.GetNode().StartOfSectionNode()->IsSectionNode() )
+ {
+ nRet = 0;
+ break;
+ }
+
+ ++nRet;
+ if( &aSIdx.GetNode() != aEIdx.GetNode().StartOfSectionNode() )
+ ++nRet;
+
+ FOREACHPAM_END()
+ return nRet;
+}
+
+
+/**
+ * Find the suitable node for a special insert (alt-enter).
+ * This should enable inserting text before/after sections and tables.
+ *
+ * A node is found if:
+ * 1) the innermost table/section is not in a write-protected area
+ * 2) pCurrentPos is at or just before an end node
+ * (or at or just after a start node)
+ * 3) there are only start/end nodes between pCurrentPos and the innermost
+ * table/section
+ *
+ * If a suitable node is found, an SwNode* is returned; else it is NULL.
+ */
+const SwNode* lcl_SpecialInsertNode(const SwPosition* pCurrentPos)
+{
+ const SwNode* pReturn = NULL;
+
+ // the current position
+ // const SwPosition* pCurrentPos = GetCrsr()->GetPoint();
+ DBG_ASSERT( pCurrentPos != NULL, "Strange, we have no position!" );
+ const SwNode& rCurrentNode = pCurrentPos->nNode.GetNode();
+
+
+ // find innermost section or table. At the end of this scope,
+ // pInntermostNode contain the section/table before/after which we should
+ // insert our empty paragraph, or it will be NULL if none is found.
+ const SwNode* pInnermostNode = NULL;
+ {
+ const SwNode* pTableNode = rCurrentNode.FindTableNode();
+ const SwNode* pSectionNode = rCurrentNode.FindSectionNode();
+
+ // find the table/section which is close
+ if( pTableNode == NULL )
+ pInnermostNode = pSectionNode;
+ else if ( pSectionNode == NULL )
+ pInnermostNode = pTableNode;
+ else
+ {
+ // compare and choose the larger one
+ pInnermostNode =
+ ( pSectionNode->GetIndex() > pTableNode->GetIndex() )
+ ? pSectionNode : pTableNode;
+ }
+ }
+
+ // The previous version had a check to skip empty read-only sections. Those
+ // shouldn't occur, so we only need to check whether our pInnermostNode is
+ // inside a protected area.
+
+ // Now, pInnermostNode is NULL or the innermost section or table node.
+ if( (pInnermostNode != NULL) && !pInnermostNode->IsProtect() )
+ {
+ DBG_ASSERT( pInnermostNode->IsTableNode() ||
+ pInnermostNode->IsSectionNode(), "wrong node found" );
+ DBG_ASSERT( ( pInnermostNode->GetIndex() <= rCurrentNode.GetIndex() )&&
+ ( pInnermostNode->EndOfSectionNode()->GetIndex() >=
+ rCurrentNode.GetIndex() ), "wrong node found" );
+
+ // we now need to find the possible start/end positions
+
+ // we found a start if
+ // - we're at or just before a start node
+ // - there are only start nodes between the current and pInnermostNode
+ SwNodeIndex aBegin( pCurrentPos->nNode );
+ if( rCurrentNode.IsCntntNode() &&
+ (pCurrentPos->nContent.GetIndex() == 0))
+ aBegin--;
+ while( (aBegin != pInnermostNode->GetIndex()) &&
+ aBegin.GetNode().IsStartNode() )
+ aBegin--;
+ bool bStart = ( aBegin == pInnermostNode->GetIndex() );
+
+ // we found an end if
+ // - we're at or just before an end node
+ // - there are only end nodes between the current node and
+ // pInnermostNode's end node
+ SwNodeIndex aEnd( pCurrentPos->nNode );
+ if( rCurrentNode.IsCntntNode() &&
+ ( pCurrentPos->nContent.GetIndex() ==
+ rCurrentNode.GetCntntNode()->Len() ) )
+ aEnd++;
+ while( (aEnd != pInnermostNode->EndOfSectionNode()->GetIndex()) &&
+ aEnd.GetNode().IsEndNode() )
+ aEnd++;
+ bool bEnd = ( aEnd == pInnermostNode->EndOfSectionNode()->GetIndex() );
+
+ // evalutate result: if both start + end, end is preferred
+ if( bEnd )
+ pReturn = pInnermostNode->EndOfSectionNode();
+ else if ( bStart )
+ pReturn = pInnermostNode;
+ }
+
+
+ DBG_ASSERT( ( pReturn == NULL ) || pReturn->IsStartNode() ||
+ pReturn->IsEndNode(),
+ "SpecialInsertNode failed" );
+ return pReturn;
+}
+
+
+/** a node can be special-inserted (alt-Enter) whenever lcl_SpecialInsertNode
+ finds a suitable position
+*/
+bool SwEditShell::CanSpecialInsert() const
+{
+ return NULL != lcl_SpecialInsertNode( GetCrsr()->GetPoint() );
+}
+
+
+/** check whether a node cen be special-inserted (alt-Enter), and do so. Return
+ whether insertion was possible.
+ */
+bool SwEditShell::DoSpecialInsert()
+{
+ bool bRet = false;
+
+ // get current node
+ SwPosition* pCursorPos = GetCrsr()->GetPoint();
+ const SwNode* pInsertNode = lcl_SpecialInsertNode( pCursorPos );
+ if( pInsertNode != NULL )
+ {
+ StartAllAction();
+
+ // adjust insert position to insert before start nodes and after end
+ // nodes
+ SwNodeIndex aInsertIndex( *pInsertNode,
+ pInsertNode->IsStartNode() ? -1 : 0 );
+ SwPosition aInsertPos( aInsertIndex );
+
+ // insert a new text node, and set the cursor
+ bRet = GetDoc()->AppendTxtNode( aInsertPos );
+ *pCursorPos = aInsertPos;
+
+ // call AttrChangeNotify for the UI
+ CallChgLnk();
+
+ EndAllAction();
+ }
+
+ return bRet;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/edit/edtab.cxx b/sw/source/core/edit/edtab.cxx
new file mode 100644
index 000000000000..edf9b2a9d150
--- /dev/null
+++ b/sw/source/core/edit/edtab.cxx
@@ -0,0 +1,493 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+#include <com/sun/star/chart2/XChartDocument.hpp>
+#include <hintids.hxx>
+#include <hints.hxx>
+
+#define _SVSTDARR_ULONGS
+#include <svl/svstdarr.hxx>
+
+#include <vcl/svapp.hxx>
+#include <vcl/window.hxx>
+#include <editeng/boxitem.hxx>
+#include <swwait.hxx>
+#include <fmtfsize.hxx>
+#include <frmatr.hxx>
+#include <editsh.hxx>
+#include <doc.hxx>
+#include <IDocumentUndoRedo.hxx>
+#include <cntfrm.hxx>
+#include <pam.hxx>
+#include <ndtxt.hxx>
+#include <fldbas.hxx>
+#include <swtable.hxx>
+#include <swundo.hxx>
+#include <tblsel.hxx>
+#include <edimp.hxx>
+#include <tabfrm.hxx>
+#include <cellfrm.hxx>
+#include <cellatr.hxx>
+#include <swtblfmt.hxx>
+#include <swddetbl.hxx>
+#include <mdiexp.hxx>
+#include <unochart.hxx>
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::uno;
+
+extern void ClearFEShellTabCols();
+
+const SwTable& SwEditShell::InsertTable( const SwInsertTableOptions& rInsTblOpts,
+ sal_uInt16 nRows, sal_uInt16 nCols,
+ sal_Int16 eAdj,
+ const SwTableAutoFmt* pTAFmt )
+{
+ StartAllAction();
+ SwPosition* pPos = GetCrsr()->GetPoint();
+
+ sal_Bool bEndUndo = 0 != pPos->nContent.GetIndex();
+ if( bEndUndo )
+ {
+ StartUndo( UNDO_START );
+ GetDoc()->SplitNode( *pPos, false );
+ }
+
+ /* If called from a shell the adjust item is propagated
+ from pPos to the new content nodes in the table.
+ */
+ const SwTable *pTable = GetDoc()->InsertTable( rInsTblOpts, *pPos,
+ nRows, nCols,
+ eAdj, pTAFmt,
+ 0, sal_True );
+ if( bEndUndo )
+ EndUndo( UNDO_END );
+
+ EndAllAction();
+ return *pTable;
+}
+
+sal_Bool SwEditShell::TextToTable( const SwInsertTableOptions& rInsTblOpts,
+ sal_Unicode cCh,
+ sal_Int16 eAdj,
+ const SwTableAutoFmt* pTAFmt )
+{
+ SwWait aWait( *GetDoc()->GetDocShell(), sal_True );
+ sal_Bool bRet = sal_False;
+ StartAllAction();
+ FOREACHPAM_START(this)
+ if( PCURCRSR->HasMark() )
+ bRet |= 0 != GetDoc()->TextToTable( rInsTblOpts, *PCURCRSR, cCh,
+ eAdj, pTAFmt );
+ FOREACHPAM_END()
+ EndAllAction();
+ return bRet;
+}
+
+sal_Bool SwEditShell::TableToText( sal_Unicode cCh )
+{
+ SwWait aWait( *GetDoc()->GetDocShell(), sal_True );
+ sal_Bool bRet = sal_False;
+ SwPaM* pCrsr = GetCrsr();
+ const SwTableNode* pTblNd =
+ GetDoc()->IsIdxInTbl( pCrsr->GetPoint()->nNode );
+ if( IsTableMode() )
+ {
+ ClearMark();
+ pCrsr = GetCrsr();
+ }
+ else if( !pTblNd || pCrsr->GetNext() != pCrsr )
+ return bRet;
+
+ // TL_CHART2:
+ // tell the charts about the table to be deleted and have them use their own data
+ GetDoc()->CreateChartInternalDataProviders( &pTblNd->GetTable() );
+
+ StartAllAction();
+
+ // verschiebe den akt. Cursor aus dem Tabellen Bereich
+ // angemeldet ist
+ SwNodeIndex aTabIdx( *pTblNd );
+ pCrsr->DeleteMark();
+ pCrsr->GetPoint()->nNode = *pTblNd->EndOfSectionNode();
+ pCrsr->GetPoint()->nContent.Assign( 0, 0 );
+ // SPoint und Mark aus dem Bereich verschieben !!!
+ pCrsr->SetMark();
+ pCrsr->DeleteMark();
+
+ bRet = GetDoc()->TableToText( pTblNd, cCh );
+ pCrsr->GetPoint()->nNode = aTabIdx;
+
+ SwCntntNode* pCNd = pCrsr->GetCntntNode();
+ if( !pCNd )
+ pCrsr->Move( fnMoveForward, fnGoCntnt );
+ else
+ pCrsr->GetPoint()->nContent.Assign( pCNd, 0 );
+
+ EndAllAction();
+ return bRet;
+}
+
+sal_Bool SwEditShell::IsTextToTableAvailable() const
+{
+ sal_Bool bOnlyText = sal_False;
+ FOREACHPAM_START(this)
+ if( PCURCRSR->HasMark() && *PCURCRSR->GetPoint() != *PCURCRSR->GetMark() )
+ {
+ bOnlyText = sal_True;
+
+ // pruefe ob in der Selection eine Tabelle liegt
+ sal_uLong nStt = PCURCRSR->GetMark()->nNode.GetIndex(),
+ nEnd = PCURCRSR->GetPoint()->nNode.GetIndex();
+ if( nStt > nEnd ) { sal_uLong n = nStt; nStt = nEnd; nEnd = n; }
+
+ for( ; nStt <= nEnd; ++nStt )
+ if( !GetDoc()->GetNodes()[ nStt ]->IsTxtNode() )
+ {
+ bOnlyText = sal_False;
+ break;
+ }
+
+ if( !bOnlyText )
+ break;
+ }
+ FOREACHPAM_END()
+
+ return bOnlyText;
+}
+
+void SwEditShell::InsertDDETable( const SwInsertTableOptions& rInsTblOpts,
+ SwDDEFieldType* pDDEType,
+ sal_uInt16 nRows, sal_uInt16 nCols,
+ sal_Int16 eAdj )
+{
+ SwPosition* pPos = GetCrsr()->GetPoint();
+
+ StartAllAction();
+
+ sal_Bool bEndUndo = 0 != pPos->nContent.GetIndex();
+ if( bEndUndo )
+ {
+ StartUndo( UNDO_START );
+ GetDoc()->SplitNode( *pPos, false );
+ }
+
+ const SwInsertTableOptions aInsTblOpts( rInsTblOpts.mnInsMode | tabopts::DEFAULT_BORDER,
+ rInsTblOpts.mnRowsToRepeat );
+ SwTable* pTbl = (SwTable*)GetDoc()->InsertTable( aInsTblOpts, *pPos,
+ nRows, nCols, eAdj );
+
+ SwTableNode* pTblNode = (SwTableNode*)pTbl->GetTabSortBoxes()[ 0 ]->
+ GetSttNd()->FindTableNode();
+ SwDDETable* pDDETbl = new SwDDETable( *pTbl, pDDEType );
+ pTblNode->SetNewTable( pDDETbl ); // setze die DDE-Tabelle
+
+ if( bEndUndo )
+ EndUndo( UNDO_END );
+
+ EndAllAction();
+}
+
+/*--------------------------------------------------------------------
+ Beschreibung: Tabellenfelder einer Tabelle updaten
+ --------------------------------------------------------------------*/
+void SwEditShell::UpdateTable()
+{
+ const SwTableNode* pTblNd = IsCrsrInTbl();
+
+ // Keine Arme keine Kekse
+ if( pTblNd )
+ {
+ StartAllAction();
+ if( DoesUndo() )
+ StartUndo();
+ EndAllTblBoxEdit();
+ SwTableFmlUpdate aTblUpdate( (SwTable*)&pTblNd->GetTable() );
+ GetDoc()->UpdateTblFlds( &aTblUpdate );
+ if( DoesUndo() )
+ EndUndo();
+ EndAllAction();
+ }
+}
+
+ // Change Modus erfragen/setzen
+TblChgMode SwEditShell::GetTblChgMode() const
+{
+ TblChgMode eMode;
+ const SwTableNode* pTblNd = IsCrsrInTbl();
+ if( pTblNd )
+ eMode = pTblNd->GetTable().GetTblChgMode();
+ else
+ eMode = GetTblChgDefaultMode();
+ return eMode;
+}
+
+void SwEditShell::SetTblChgMode( TblChgMode eMode )
+{
+ const SwTableNode* pTblNd = IsCrsrInTbl();
+
+ // Keine Arme keine Kekse
+ if( pTblNd )
+ {
+ ((SwTable&)pTblNd->GetTable()).SetTblChgMode( eMode );
+ if( !GetDoc()->IsModified() ) // Bug 57028
+ {
+ GetDoc()->GetIDocumentUndoRedo().SetUndoNoResetModified();
+ }
+ GetDoc()->SetModified();
+ }
+}
+
+sal_Bool SwEditShell::GetTblBoxFormulaAttrs( SfxItemSet& rSet ) const
+{
+ SwSelBoxes aBoxes;
+ if( IsTableMode() )
+ ::GetTblSelCrs( *this, aBoxes );
+ else
+ {
+ do {
+ SwFrm *pFrm = GetCurrFrm();
+ do {
+ pFrm = pFrm->GetUpper();
+ } while ( pFrm && !pFrm->IsCellFrm() );
+ if ( pFrm )
+ {
+ SwTableBox *pBox = (SwTableBox*)((SwCellFrm*)pFrm)->GetTabBox();
+ aBoxes.Insert( pBox );
+ }
+ } while( sal_False );
+ }
+
+ for( sal_uInt16 n = 0; n < aBoxes.Count(); ++n )
+ {
+ const SwTableBox* pSelBox = aBoxes[ n ];
+ const SwTableBoxFmt* pTblFmt = (SwTableBoxFmt*)pSelBox->GetFrmFmt();
+ if( !n )
+ {
+ // Formeln in die externe Darstellung bringen!
+ const SwTable& rTbl = pSelBox->GetSttNd()->FindTableNode()->GetTable();
+
+ SwTableFmlUpdate aTblUpdate( (SwTable*)&rTbl );
+ aTblUpdate.eFlags = TBL_BOXNAME;
+ ((SwDoc*)GetDoc())->UpdateTblFlds( &aTblUpdate );
+
+ rSet.Put( pTblFmt->GetAttrSet() );
+ }
+ else
+ rSet.MergeValues( pTblFmt->GetAttrSet() );
+ }
+ return 0 != rSet.Count();
+}
+
+void SwEditShell::SetTblBoxFormulaAttrs( const SfxItemSet& rSet )
+{
+ SET_CURR_SHELL( this );
+ SwSelBoxes aBoxes;
+ if( IsTableMode() )
+ ::GetTblSelCrs( *this, aBoxes );
+ else
+ {
+ do {
+ SwFrm *pFrm = GetCurrFrm();
+ do {
+ pFrm = pFrm->GetUpper();
+ } while ( pFrm && !pFrm->IsCellFrm() );
+ if ( pFrm )
+ {
+ SwTableBox *pBox = (SwTableBox*)((SwCellFrm*)pFrm)->GetTabBox();
+ aBoxes.Insert( pBox );
+ }
+ } while( sal_False );
+ }
+
+ // beim setzen einer Formel keine Ueberpruefung mehr vornehmen!
+ if( SFX_ITEM_SET == rSet.GetItemState( RES_BOXATR_FORMULA ))
+ ClearTblBoxCntnt();
+
+ StartAllAction();
+ GetDoc()->GetIDocumentUndoRedo().StartUndo( UNDO_START, NULL );
+ for( sal_uInt16 n = 0; n < aBoxes.Count(); ++n )
+ GetDoc()->SetTblBoxFormulaAttrs( *aBoxes[ n ], rSet );
+ GetDoc()->GetIDocumentUndoRedo().EndUndo( UNDO_END, NULL );
+ EndAllAction();
+}
+
+sal_Bool SwEditShell::IsTableBoxTextFormat() const
+{
+ if( IsTableMode() )
+ return sal_False;
+
+ SwTableBox *pBox = 0;
+ {
+ SwFrm *pFrm = GetCurrFrm();
+ do {
+ pFrm = pFrm->GetUpper();
+ } while ( pFrm && !pFrm->IsCellFrm() );
+ if ( pFrm )
+ pBox = (SwTableBox*)((SwCellFrm*)pFrm)->GetTabBox();
+ }
+
+ if( !pBox )
+ return sal_False;
+
+ sal_uInt32 nFmt;
+ const SfxPoolItem* pItem;
+ if( SFX_ITEM_SET == pBox->GetFrmFmt()->GetAttrSet().GetItemState(
+ RES_BOXATR_FORMAT, sal_True, &pItem ))
+ {
+ nFmt = ((SwTblBoxNumFormat*)pItem)->GetValue();
+ return GetDoc()->GetNumberFormatter()->IsTextFormat( nFmt ) ||
+ NUMBERFORMAT_TEXT == nFmt;
+ }
+
+ sal_uLong nNd = pBox->IsValidNumTxtNd();
+ if( ULONG_MAX == nNd )
+ return sal_True;
+
+ const String& rTxt = GetDoc()->GetNodes()[ nNd ]->GetTxtNode()->GetTxt();
+ if( !rTxt.Len() )
+ return sal_False;
+
+ double fVal;
+ return !GetDoc()->GetNumberFormatter()->IsNumberFormat( rTxt, nFmt, fVal );
+}
+
+String SwEditShell::GetTableBoxText() const
+{
+ String sRet;
+ if( !IsTableMode() )
+ {
+ SwTableBox *pBox = 0;
+ {
+ SwFrm *pFrm = GetCurrFrm();
+ do {
+ pFrm = pFrm->GetUpper();
+ } while ( pFrm && !pFrm->IsCellFrm() );
+ if ( pFrm )
+ pBox = (SwTableBox*)((SwCellFrm*)pFrm)->GetTabBox();
+ }
+
+ sal_uLong nNd;
+ if( pBox && ULONG_MAX != ( nNd = pBox->IsValidNumTxtNd() ) )
+ sRet = GetDoc()->GetNodes()[ nNd ]->GetTxtNode()->GetTxt();
+ }
+ return sRet;
+}
+
+sal_Bool SwEditShell::SplitTable( sal_uInt16 eMode )
+{
+ sal_Bool bRet = sal_False;
+ SwPaM *pCrsr = GetCrsr();
+ if( pCrsr->GetNode()->FindTableNode() )
+ {
+ StartAllAction();
+ GetDoc()->GetIDocumentUndoRedo().StartUndo(UNDO_EMPTY, NULL);
+
+ bRet = GetDoc()->SplitTable( *pCrsr->GetPoint(), eMode, sal_True );
+
+ GetDoc()->GetIDocumentUndoRedo().EndUndo(UNDO_EMPTY, NULL);
+ ClearFEShellTabCols();
+ EndAllAction();
+ }
+ return bRet;
+}
+
+sal_Bool SwEditShell::MergeTable( sal_Bool bWithPrev, sal_uInt16 nMode )
+{
+ sal_Bool bRet = sal_False;
+ SwPaM *pCrsr = GetCrsr();
+ if( pCrsr->GetNode()->FindTableNode() )
+ {
+ StartAllAction();
+ GetDoc()->GetIDocumentUndoRedo().StartUndo(UNDO_EMPTY, NULL);
+
+ bRet = GetDoc()->MergeTable( *pCrsr->GetPoint(), bWithPrev, nMode );
+
+ GetDoc()->GetIDocumentUndoRedo().EndUndo(UNDO_EMPTY, NULL);
+ ClearFEShellTabCols();
+ EndAllAction();
+ }
+ return bRet;
+}
+
+sal_Bool SwEditShell::CanMergeTable( sal_Bool bWithPrev, sal_Bool* pChkNxtPrv ) const
+{
+ sal_Bool bRet = sal_False;
+ const SwPaM *pCrsr = GetCrsr();
+ const SwTableNode* pTblNd = pCrsr->GetNode()->FindTableNode();
+ if( pTblNd && !pTblNd->GetTable().ISA( SwDDETable ))
+ {
+ sal_Bool bNew = pTblNd->GetTable().IsNewModel();
+ const SwNodes& rNds = GetDoc()->GetNodes();
+ if( pChkNxtPrv )
+ {
+ const SwTableNode* pChkNd = rNds[ pTblNd->GetIndex() - 1 ]->FindTableNode();
+ if( pChkNd && !pChkNd->GetTable().ISA( SwDDETable ) &&
+ bNew == pChkNd->GetTable().IsNewModel() &&
+ // Consider table in table case
+ pChkNd->EndOfSectionIndex() == pTblNd->GetIndex() - 1 )
+ *pChkNxtPrv = sal_True, bRet = sal_True; // mit Prev ist moeglich
+ else
+ {
+ pChkNd = rNds[ pTblNd->EndOfSectionIndex() + 1 ]->GetTableNode();
+ if( pChkNd && !pChkNd->GetTable().ISA( SwDDETable ) &&
+ bNew == pChkNd->GetTable().IsNewModel() )
+ *pChkNxtPrv = sal_False, bRet = sal_True; // mit Next ist moeglich
+ }
+ }
+ else
+ {
+ const SwTableNode* pTmpTblNd = 0;
+
+ if( bWithPrev )
+ {
+ pTmpTblNd = rNds[ pTblNd->GetIndex() - 1 ]->FindTableNode();
+ // Consider table in table case
+ if ( pTmpTblNd && pTmpTblNd->EndOfSectionIndex() != pTblNd->GetIndex() - 1 )
+ pTmpTblNd = 0;
+ }
+ else
+ pTmpTblNd = rNds[ pTblNd->EndOfSectionIndex() + 1 ]->GetTableNode();
+
+ bRet = pTmpTblNd && !pTmpTblNd->GetTable().ISA( SwDDETable ) &&
+ bNew == pTmpTblNd->GetTable().IsNewModel();
+ }
+ }
+ return bRet;
+}
+
+ // setze das InsertDB als Tabelle Undo auf:
+void SwEditShell::AppendUndoForInsertFromDB( sal_Bool bIsTable )
+{
+ GetDoc()->AppendUndoForInsertFromDB( *GetCrsr(), bIsTable );
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/edit/edtox.cxx b/sw/source/core/edit/edtox.cxx
new file mode 100644
index 000000000000..1bbf0b3b9e9a
--- /dev/null
+++ b/sw/source/core/edit/edtox.cxx
@@ -0,0 +1,467 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+#include <com/sun/star/util/SearchOptions.hpp>
+#include <com/sun/star/util/SearchFlags.hpp>
+#include <com/sun/star/i18n/TransliterationModules.hpp>
+
+#include <tools/urlobj.hxx>
+
+#include <svl/fstathelper.hxx>
+
+#include <svtools/txtcmp.hxx>
+
+#include <sfx2/docfile.hxx>
+
+#include <xmloff/odffields.hxx>
+
+#include <editeng/unolingu.hxx>
+
+#include <swtypes.hxx>
+#include <editsh.hxx>
+#include <doc.hxx>
+#include <IDocumentUndoRedo.hxx>
+#include <pam.hxx>
+#include <viewopt.hxx>
+#include <ndtxt.hxx>
+#include <swundo.hxx>
+#include <txttxmrk.hxx>
+#include <edimp.hxx>
+#include <tox.hxx>
+#include <doctxm.hxx>
+#include <docary.hxx>
+#include <mdiexp.hxx>
+#include <statstr.hrc>
+#include <bookmrk.hxx>
+
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::i18n;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star::util;
+
+/*--------------------------------------------------------------------
+ Beschreibung: Verzeichnismarkierung ins Dokument einfuegen/loeschen
+ --------------------------------------------------------------------*/
+
+
+void SwEditShell::Insert(const SwTOXMark& rMark)
+{
+ sal_Bool bInsAtPos = rMark.IsAlternativeText();
+ StartAllAction();
+ FOREACHPAM_START(this)
+
+ const SwPosition *pStt = PCURCRSR->Start(),
+ *pEnd = PCURCRSR->End();
+ if( bInsAtPos )
+ {
+ SwPaM aTmp( *pStt );
+ GetDoc()->InsertPoolItem( aTmp, rMark, 0 );
+ }
+ else if( *pEnd != *pStt )
+ {
+ GetDoc()->InsertPoolItem( *PCURCRSR, rMark,
+ nsSetAttrMode::SETATTR_DONTEXPAND );
+ }
+
+ FOREACHPAM_END()
+ EndAllAction();
+}
+
+
+
+void SwEditShell::DeleteTOXMark( SwTOXMark* pMark )
+{
+ SET_CURR_SHELL( this );
+ StartAllAction();
+
+ pDoc->DeleteTOXMark( pMark );
+
+ EndAllAction();
+}
+
+
+/*--------------------------------------------------------------------
+ Beschreibung: Alle Verzeichnismarkierungen am SPoint zusammensuchen
+ --------------------------------------------------------------------*/
+
+sal_uInt16 SwEditShell::GetCurTOXMarks(SwTOXMarks& rMarks) const
+{
+ return GetDoc()->GetCurTOXMark( *GetCrsr()->Start(), rMarks );
+}
+
+sal_Bool SwEditShell::IsTOXBaseReadonly(const SwTOXBase& rTOXBase) const
+{
+ OSL_ENSURE( rTOXBase.ISA( SwTOXBaseSection ), "no TOXBaseSection!" );
+ const SwTOXBaseSection& rTOXSect = (const SwTOXBaseSection&)rTOXBase;
+ return rTOXSect.IsProtect();
+}
+
+void SwEditShell::SetTOXBaseReadonly(const SwTOXBase& rTOXBase, sal_Bool bReadonly)
+{
+ OSL_ENSURE( rTOXBase.ISA( SwTOXBaseSection ), "no TOXBaseSection!" );
+ const SwTOXBaseSection& rTOXSect = (const SwTOXBaseSection&)rTOXBase;
+ ((SwTOXBase&)rTOXBase).SetProtected(bReadonly);
+ OSL_ENSURE( rTOXSect.SwSection::GetType() == TOX_CONTENT_SECTION, "not a TOXContentSection" );
+
+ SwSectionData aSectionData(rTOXSect);
+ aSectionData.SetProtectFlag(bReadonly);
+ UpdateSection( GetSectionFmtPos( *rTOXSect.GetFmt() ), aSectionData, 0 );
+}
+
+const SwTOXBase* SwEditShell::GetDefaultTOXBase( TOXTypes eTyp, sal_Bool bCreate )
+{
+ return GetDoc()->GetDefaultTOXBase( eTyp, bCreate );
+}
+
+void SwEditShell::SetDefaultTOXBase(const SwTOXBase& rBase)
+{
+ GetDoc()->SetDefaultTOXBase(rBase);
+}
+
+/*--------------------------------------------------------------------
+ Beschreibung: Verzeichnis einfuegen, und Inhalt erzeugen
+ --------------------------------------------------------------------*/
+
+void SwEditShell::InsertTableOf( const SwTOXBase& rTOX, const SfxItemSet* pSet )
+{
+ SET_CURR_SHELL( this );
+ StartAllAction();
+
+ SwDocShell* pDocSh = GetDoc()->GetDocShell();
+ ::StartProgress( STR_STATSTR_TOX_INSERT, 0, 0, pDocSh );
+ ::SetProgressText( STR_STATSTR_TOX_INSERT, pDocSh );
+
+ // Einfuegen des Verzeichnisses
+ const SwTOXBaseSection* pTOX = pDoc->InsertTableOf(
+ *GetCrsr()->GetPoint(), rTOX, pSet, sal_True );
+ OSL_ENSURE(pTOX, "Kein aktuelles Verzeichnis");
+
+ // Formatierung anstossen
+ CalcLayout();
+
+ // Seitennummern eintragen
+ ((SwTOXBaseSection*)pTOX)->UpdatePageNum();
+
+ pTOX->SetPosAtStartEnd( *GetCrsr()->GetPoint() );
+
+ // Fix fuer leere Verzeichnisse
+ InvalidateWindows( aVisArea );
+ ::EndProgress( pDocSh );
+ EndAllAction();
+}
+
+/*--------------------------------------------------------------------
+ Beschreibung: Verzeichnisinhalt erneuern
+ --------------------------------------------------------------------*/
+
+sal_Bool SwEditShell::UpdateTableOf( const SwTOXBase& rTOX, const SfxItemSet* pSet )
+{
+ sal_Bool bRet = sal_False;
+
+ OSL_ENSURE( rTOX.ISA( SwTOXBaseSection ), "keine TOXBaseSection!" );
+ SwTOXBaseSection* pTOX = (SwTOXBaseSection*)&rTOX;
+ OSL_ENSURE(pTOX, "Keine aktuelles Verzeichnis");
+ const SwSectionNode* pSectNd;
+ if( pTOX && 0 != ( pSectNd = pTOX->GetFmt()->GetSectionNode() ) )
+ {
+ SwDoc* pMyDoc = GetDoc();
+ SwDocShell* pDocSh = pMyDoc->GetDocShell();
+
+ sal_Bool bInIndex = pTOX == GetCurTOX();
+ SET_CURR_SHELL( this );
+ StartAllAction();
+
+ ::StartProgress( STR_STATSTR_TOX_UPDATE, 0, 0, pDocSh );
+ ::SetProgressText( STR_STATSTR_TOX_UPDATE, pDocSh );
+
+ pMyDoc->GetIDocumentUndoRedo().StartUndo(UNDO_TOXCHANGE, NULL);
+
+ // Verzeichnisrumpf erzeugen
+ pTOX->Update(pSet);
+
+ // Cursor korrigieren
+ if( bInIndex )
+ pTOX->SetPosAtStartEnd( *GetCrsr()->GetPoint() );
+
+ // Formatierung anstossen
+ CalcLayout();
+
+ // Seitennummern eintragen
+ pTOX->UpdatePageNum();
+
+ pMyDoc->GetIDocumentUndoRedo().EndUndo(UNDO_TOXCHANGE, NULL);
+
+ ::EndProgress( pDocSh );
+ EndAllAction();
+ }
+ return bRet;
+}
+
+/*--------------------------------------------------------------------
+ Beschreibung: Aktuelles Verzeichnis vor oder in dem der Cursor
+ steht
+ --------------------------------------------------------------------*/
+
+const SwTOXBase* SwEditShell::GetCurTOX() const
+{
+ return GetDoc()->GetCurTOX( *GetCrsr()->GetPoint() );
+}
+
+sal_Bool SwEditShell::DeleteTOX( const SwTOXBase& rTOXBase, sal_Bool bDelNodes )
+{
+ return GetDoc()->DeleteTOX( (SwTOXBase&)rTOXBase, bDelNodes );
+}
+
+/*--------------------------------------------------------------------
+ Beschreibung: Typen der Verzeichnisse verwalten
+ --------------------------------------------------------------------*/
+
+const SwTOXType* SwEditShell::GetTOXType(TOXTypes eTyp, sal_uInt16 nId) const
+{
+ return pDoc->GetTOXType(eTyp, nId);
+}
+
+/*--------------------------------------------------------------------
+ Beschreibung: Schluessel fuer Stichwortverzeichnisse verwalten
+ --------------------------------------------------------------------*/
+
+sal_uInt16 SwEditShell::GetTOIKeys( SwTOIKeyType eTyp, SvStringsSort& rArr ) const
+{
+ return GetDoc()->GetTOIKeys( eTyp, rArr );
+}
+
+
+sal_uInt16 SwEditShell::GetTOXCount() const
+{
+ const SwSectionFmts& rFmts = GetDoc()->GetSections();
+ sal_uInt16 nRet = 0;
+ for( sal_uInt16 n = rFmts.Count(); n; )
+ {
+ const SwSection* pSect = rFmts[ --n ]->GetSection();
+ if( TOX_CONTENT_SECTION == pSect->GetType() &&
+ pSect->GetFmt()->GetSectionNode() )
+ ++nRet;
+ }
+ return nRet;
+}
+
+
+const SwTOXBase* SwEditShell::GetTOX( sal_uInt16 nPos ) const
+{
+ const SwSectionFmts& rFmts = GetDoc()->GetSections();
+ for( sal_uInt16 n = 0, nCnt = 0; n < rFmts.Count(); ++n )
+ {
+ const SwSection* pSect = rFmts[ n ]->GetSection();
+ if( TOX_CONTENT_SECTION == pSect->GetType() &&
+ pSect->GetFmt()->GetSectionNode() &&
+ nCnt++ == nPos )
+ {
+ OSL_ENSURE( pSect->ISA( SwTOXBaseSection ), "keine TOXBaseSection!" );
+ return (SwTOXBaseSection*)pSect;
+ }
+ }
+ return 0;
+}
+
+
+ // nach einlesen einer Datei alle Verzeichnisse updaten
+void SwEditShell::SetUpdateTOX( sal_Bool bFlag )
+{
+ GetDoc()->SetUpdateTOX( bFlag );
+}
+
+
+sal_Bool SwEditShell::IsUpdateTOX() const
+{
+ return GetDoc()->IsUpdateTOX();
+}
+
+const String& SwEditShell::GetTOIAutoMarkURL() const
+{
+ return GetDoc()->GetTOIAutoMarkURL();
+}
+
+void SwEditShell::SetTOIAutoMarkURL(const String& rSet)
+{
+ GetDoc()->SetTOIAutoMarkURL(rSet);
+}
+
+void SwEditShell::ApplyAutoMark()
+{
+ StartAllAction();
+ sal_Bool bDoesUndo = DoesUndo();
+ DoUndo(sal_False);
+ //1. remove all automatic generated index entries if AutoMarkURL has a
+ // length and the file exists
+ //2. load file
+ //3. select all occurrences of the searched words
+ //4. apply index entries
+
+ String sAutoMarkURL(GetDoc()->GetTOIAutoMarkURL());
+ if( sAutoMarkURL.Len() && FStatHelper::IsDocument( sAutoMarkURL ))
+ {
+ //1.
+ const SwTOXType* pTOXType = GetTOXType(TOX_INDEX, 0);
+
+ SwTOXMarks aMarks;
+ SwTOXMark::InsertTOXMarks( aMarks, *pTOXType );
+ for( sal_uInt16 nMark=0; nMark<aMarks.Count(); nMark++ )
+ {
+ SwTOXMark* pMark = aMarks[nMark];
+ if(pMark->IsAutoGenerated() && pMark->GetTxtTOXMark())
+ // mba: test iteration; objects are deleted in iteration
+ DeleteTOXMark(pMark);
+ }
+
+ //2.
+ SfxMedium aMedium( sAutoMarkURL, STREAM_STD_READ, sal_True );
+ SvStream& rStrm = *aMedium.GetInStream();
+ const String sZero('0');
+ Push();
+ rtl_TextEncoding eChrSet = ::gsl_getSystemTextEncoding();
+
+ //
+ // SearchOptions to be used in loop below
+ //
+ sal_Bool bCaseSensitive = sal_True;
+ sal_Bool bWordOnly = sal_False;
+ sal_Bool bSrchInSel = sal_False;
+ sal_Bool bLEV_Relaxed = sal_True;
+ sal_Int32 nLEV_Other = 2; // -> changedChars;
+ sal_Int32 nLEV_Longer = 3; //! -> deletedChars;
+ sal_Int32 nLEV_Shorter = 1; //! -> insertedChars;
+ sal_Int32 nTransliterationFlags = 0;
+ //
+ sal_Int32 nSrchFlags = 0;
+ if (!bCaseSensitive)
+ {
+ nSrchFlags |= SearchFlags::ALL_IGNORE_CASE;
+ nTransliterationFlags |= TransliterationModules_IGNORE_CASE;
+ }
+ if ( bWordOnly)
+ nSrchFlags |= SearchFlags::NORM_WORD_ONLY;
+ if ( bLEV_Relaxed)
+ nSrchFlags |= SearchFlags::LEV_RELAXED;
+ if ( bSrchInSel)
+ nSrchFlags |= (SearchFlags::REG_NOT_BEGINOFLINE |
+ SearchFlags::REG_NOT_ENDOFLINE );
+ //
+ rtl::OUString sEmpty;
+ SearchOptions aSearchOpt(
+ SearchAlgorithms_ABSOLUTE, nSrchFlags,
+ sEmpty, sEmpty,
+ SvxCreateLocale( LANGUAGE_SYSTEM ),
+ nLEV_Other, nLEV_Longer, nLEV_Shorter,
+ nTransliterationFlags );
+
+ while( !rStrm.GetError() && !rStrm.IsEof() )
+ {
+ ByteString aRdLine;
+ rStrm.ReadLine( aRdLine );
+
+ // # -> comment
+ // ; -> delimiter between entries ->
+ // Format: TextToSearchFor;AlternativeString;PrimaryKey;SecondaryKey;CaseSensitive;WordOnly
+ // Leading and trailing blanks are ignored
+ if( aRdLine.Len() && '#' != aRdLine.GetChar(0) )
+ {
+ String sLine( aRdLine, eChrSet );
+
+ xub_StrLen nTokenPos = 0;
+ String sToSelect( sLine.GetToken(0, ';', nTokenPos ) );
+ if( sToSelect.Len() )
+ {
+ String sAlternative = sLine.GetToken(0, ';', nTokenPos);
+ String sPrimary = sLine.GetToken(0, ';', nTokenPos);
+ String sSecondary = sLine.GetToken(0, ';', nTokenPos);
+ String sCase = sLine.GetToken(0, ';', nTokenPos);
+ String sWordOnly = sLine.GetToken(0, ';', nTokenPos);
+
+ //3.
+ bCaseSensitive = sCase.Len() && sCase != sZero;
+ bWordOnly = sWordOnly.Len() && sWordOnly != sZero;
+ //
+ if (!bCaseSensitive)
+ {
+ aSearchOpt.transliterateFlags |=
+ TransliterationModules_IGNORE_CASE;
+ }
+ else
+ {
+ aSearchOpt.transliterateFlags &=
+ ~TransliterationModules_IGNORE_CASE;
+ }
+ if ( bWordOnly)
+ aSearchOpt.searchFlag |= SearchFlags::NORM_WORD_ONLY;
+ else
+ aSearchOpt.searchFlag &= ~SearchFlags::NORM_WORD_ONLY;
+ //
+ aSearchOpt.searchString = sToSelect;
+
+ KillPams();
+ sal_Bool bCancel;
+
+ // todo/mba: assuming that notes shouldn't be searched
+ sal_Bool bSearchInNotes = sal_False;
+ sal_uLong nRet = Find( aSearchOpt, bSearchInNotes, DOCPOS_START, DOCPOS_END, bCancel,
+ (FindRanges)(FND_IN_SELALL|FND_IN_BODYONLY),
+ sal_False );
+
+ if(nRet)
+ {
+ SwTOXMark* pTmpMark = new SwTOXMark(pTOXType);
+ if( sPrimary.Len() )
+ {
+ pTmpMark->SetPrimaryKey( sPrimary );
+ if( sSecondary.Len() )
+ pTmpMark->SetSecondaryKey( sSecondary );
+ }
+ if(sAlternative.Len())
+ pTmpMark->SetAlternativeText(sAlternative);
+ pTmpMark->SetMainEntry(sal_False);
+ pTmpMark->SetAutoGenerated(sal_True);
+ //4.
+ SwEditShell::Insert(*pTmpMark);
+ }
+ }
+ }
+ }
+ KillPams();
+ Pop(sal_False);
+ }
+ DoUndo(bDoesUndo);
+ EndAllAction();
+}
+
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/edit/edundo.cxx b/sw/source/core/edit/edundo.cxx
new file mode 100644
index 000000000000..0ee3879c48c5
--- /dev/null
+++ b/sw/source/core/edit/edundo.cxx
@@ -0,0 +1,260 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+#include <svx/svdview.hxx>
+
+#include <editsh.hxx>
+#include <fesh.hxx>
+#include <doc.hxx>
+#include <IDocumentUndoRedo.hxx>
+#include <pam.hxx>
+#include <UndoCore.hxx>
+#include <swundo.hxx>
+#include <dcontact.hxx>
+#include <flyfrm.hxx>
+#include <frmfmt.hxx>
+#include <viewimp.hxx>
+#include <docsh.hxx>
+
+
+/** helper function to select all objects in an SdrMarkList;
+ * implementation: see below */
+void lcl_SelectSdrMarkList( SwEditShell* pShell,
+ const SdrMarkList* pSdrMarkList );
+
+bool SwEditShell::CursorsLocked() const
+{
+
+ return GetDoc()->GetDocShell()->GetModel()->hasControllersLocked();
+}
+
+void
+SwEditShell::HandleUndoRedoContext(::sw::UndoRedoContext & rContext)
+{
+ // do nothing if somebody has locked controllers!
+ if (CursorsLocked())
+ {
+ return;
+ }
+
+ SwFrmFmt * pSelFmt(0);
+ SdrMarkList * pMarkList(0);
+ rContext.GetSelections(pSelFmt, pMarkList);
+
+ if (pSelFmt) // select frame
+ {
+ if (RES_DRAWFRMFMT == pSelFmt->Which())
+ {
+ SdrObject* pSObj = pSelFmt->FindSdrObject();
+ static_cast<SwFEShell*>(this)->SelectObj(
+ pSObj->GetCurrentBoundRect().Center() );
+ }
+ else
+ {
+ Point aPt;
+ SwFlyFrm *const pFly =
+ static_cast<SwFlyFrmFmt*>(pSelFmt)->GetFrm(& aPt, false);
+ if (pFly)
+ {
+ static_cast<SwFEShell*>(this)->SelectFlyFrm(*pFly, true);
+ }
+ }
+ }
+ else if (pMarkList)
+ {
+ lcl_SelectSdrMarkList( this, pMarkList );
+ }
+ else if (GetCrsr()->GetNext() != GetCrsr())
+ {
+ // current cursor is the last one:
+ // go around the ring, to the first cursor
+ GoNextCrsr();
+ }
+}
+
+bool SwEditShell::Undo(sal_uInt16 const nCount)
+{
+ SET_CURR_SHELL( this );
+
+ // current undo state was not saved
+ ::sw::UndoGuard const undoGuard(GetDoc()->GetIDocumentUndoRedo());
+ sal_Bool bRet = sal_False;
+
+ StartAllAction();
+ {
+ // eigentlich muesste ja nur der aktuelle Cursor berarbeitet
+ // werden, d.H. falls ein Ring besteht, diesen temporaer aufheben,
+ // damit nicht bei Einfuge-Operationen innerhalb von Undo
+ // an allen Bereichen eingefuegt wird.
+ KillPams();
+ SetMark(); // Bound1 und Bound2 in den gleichen Node
+ ClearMark();
+
+ // JP 02.04.98: Cursor merken - beim Auto-Format/-Korrektur
+ // soll dieser wieder an die Position
+ SwUndoId nLastUndoId(UNDO_EMPTY);
+ GetDoc()->GetIDocumentUndoRedo().GetLastUndoInfo(0, & nLastUndoId);
+ bool bRestoreCrsr = 1 == nCount && (UNDO_AUTOFORMAT == nLastUndoId ||
+ UNDO_AUTOCORRECT == nLastUndoId );
+ Push();
+
+ //JP 18.09.97: gesicherten TabellenBoxPtr zerstoeren, eine autom.
+ // Erkennung darf nur noch fuer die neue "Box" erfolgen!
+ ClearTblBoxCntnt();
+
+ RedlineMode_t eOld = GetDoc()->GetRedlineMode();
+
+ try {
+ for (sal_uInt16 i = 0; i < nCount; ++i)
+ {
+ bRet = GetDoc()->GetIDocumentUndoRedo().Undo()
+ || bRet;
+ }
+ } catch (::com::sun::star::uno::Exception & e) {
+ OSL_TRACE("SwEditShell::Undo(): exception caught:\n %s",
+ ::rtl::OUStringToOString(e.Message, RTL_TEXTENCODING_UTF8)
+ .getStr());
+ }
+
+ Pop( !bRestoreCrsr );
+
+ GetDoc()->SetRedlineMode( eOld );
+ GetDoc()->CompressRedlines();
+
+ // autom. Erkennung fuer die neue "Box"
+ SaveTblBoxCntnt();
+ }
+ EndAllAction();
+
+ return bRet;
+}
+
+bool SwEditShell::Redo(sal_uInt16 const nCount)
+{
+ SET_CURR_SHELL( this );
+
+ sal_Bool bRet = sal_False;
+
+ // undo state was not saved
+ ::sw::UndoGuard const undoGuard(GetDoc()->GetIDocumentUndoRedo());
+
+ StartAllAction();
+
+ {
+ // eigentlich muesste ja nur der aktuelle Cursor berarbeitet
+ // werden, d.H. falls ein Ring besteht, diesen temporaer aufheben,
+ // damit nicht bei Einfuge-Operationen innerhalb von Undo
+ // an allen Bereichen eingefuegt wird.
+ KillPams();
+ SetMark(); // Bound1 und Bound2 in den gleichen Node
+ ClearMark();
+
+ //JP 18.09.97: gesicherten TabellenBoxPtr zerstoeren, eine autom.
+ // Erkennung darf nur noch fuer die neue "Box" erfolgen!
+ ClearTblBoxCntnt();
+
+ RedlineMode_t eOld = GetDoc()->GetRedlineMode();
+
+ try {
+ for (sal_uInt16 i = 0; i < nCount; ++i)
+ {
+ bRet = GetDoc()->GetIDocumentUndoRedo().Redo()
+ || bRet;
+ }
+ } catch (::com::sun::star::uno::Exception & e) {
+ OSL_TRACE("SwEditShell::Redo(): exception caught:\n %s",
+ ::rtl::OUStringToOString(e.Message, RTL_TEXTENCODING_UTF8)
+ .getStr());
+ }
+
+ GetDoc()->SetRedlineMode( eOld );
+ GetDoc()->CompressRedlines();
+
+ // autom. Erkennung fuer die neue "Box"
+ SaveTblBoxCntnt();
+ }
+
+ EndAllAction();
+
+ return bRet;
+}
+
+
+bool SwEditShell::Repeat(sal_uInt16 const nCount)
+{
+ SET_CURR_SHELL( this );
+
+ sal_Bool bRet = sal_False;
+ StartAllAction();
+
+ try {
+ ::sw::RepeatContext context(*GetDoc(), *GetCrsr());
+ bRet = GetDoc()->GetIDocumentUndoRedo().Repeat( context, nCount )
+ || bRet;
+ } catch (::com::sun::star::uno::Exception & e) {
+ OSL_TRACE("SwEditShell::Repeat(): exception caught:\n %s",
+ ::rtl::OUStringToOString(e.Message, RTL_TEXTENCODING_UTF8)
+ .getStr());
+ }
+
+ EndAllAction();
+ return bRet;
+}
+
+
+void lcl_SelectSdrMarkList( SwEditShell* pShell,
+ const SdrMarkList* pSdrMarkList )
+{
+ OSL_ENSURE( pShell != NULL, "need shell!" );
+ OSL_ENSURE( pSdrMarkList != NULL, "need mark list" );
+
+ if( pShell->ISA( SwFEShell ) )
+ {
+ SwFEShell* pFEShell = static_cast<SwFEShell*>( pShell );
+ bool bFirst = true;
+ for( sal_uInt16 i = 0; i < pSdrMarkList->GetMarkCount(); ++i )
+ {
+ SdrObject *pObj = pSdrMarkList->GetMark( i )->GetMarkedSdrObj();
+ if( pObj )
+ {
+ pFEShell->SelectObj( Point(), bFirst ? 0 : SW_ADD_SELECT, pObj );
+ bFirst = false;
+ }
+ }
+
+ // the old implementation would always unselect
+ // objects, even if no new ones were selected. If this
+ // is a problem, we need to re-work this a little.
+ OSL_ENSURE( pSdrMarkList->GetMarkCount() != 0, "empty mark list" );
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/edit/edws.cxx b/sw/source/core/edit/edws.cxx
new file mode 100644
index 000000000000..bb34343dc65e
--- /dev/null
+++ b/sw/source/core/edit/edws.cxx
@@ -0,0 +1,367 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+#include <vcl/window.hxx>
+
+#include <editsh.hxx>
+#include <doc.hxx>
+#include <IDocumentUndoRedo.hxx>
+#include <pam.hxx>
+#include <docary.hxx>
+#include <acorrect.hxx>
+#include <swtable.hxx>
+#include <ndtxt.hxx>
+#include <swundo.hxx>
+#include <SwRewriter.hxx>
+
+/********************************************************
+ * Ctor/Dtor
+ ********************************************************/
+// verkleideter Copy-Constructor
+
+
+SwEditShell::SwEditShell( SwEditShell& rEdSH, Window *pWindow )
+ : SwCrsrShell( rEdSH, pWindow )
+{
+}
+
+// ctor/dtor
+
+
+SwEditShell::SwEditShell( SwDoc& rDoc, Window *pWindow, const SwViewOption *pOptions )
+ : SwCrsrShell( rDoc, pWindow, pOptions )
+{
+ GetDoc()->GetIDocumentUndoRedo().DoUndo(true);
+}
+
+
+SwEditShell::~SwEditShell() // USED
+{
+}
+
+/******************************************************************************
+ * sal_Bool SwEditShell::IsModified() const
+ ******************************************************************************/
+
+
+sal_Bool SwEditShell::IsModified() const
+{
+ return GetDoc()->IsModified();
+}
+/******************************************************************************
+ * void SwEditShell::SetModified()
+ ******************************************************************************/
+
+
+void SwEditShell::SetModified()
+{
+ GetDoc()->SetModified();
+}
+/******************************************************************************
+ * void SwEditShell::ResetModified()
+ ******************************************************************************/
+
+
+void SwEditShell::ResetModified()
+{
+ GetDoc()->ResetModified();
+}
+
+void SwEditShell::SetUndoNoResetModified()
+{
+ GetDoc()->SetModified();
+ GetDoc()->GetIDocumentUndoRedo().SetUndoNoResetModified();
+}
+
+/******************************************************************************
+ * void SwEditShell::StartAllAction()
+ ******************************************************************************/
+
+
+void SwEditShell::StartAllAction()
+{
+ ViewShell *pSh = this;
+ do {
+ if( pSh->IsA( TYPE( SwEditShell ) ) )
+ ((SwEditShell*)pSh)->StartAction();
+ else
+ pSh->StartAction();
+ pSh = (ViewShell *)pSh->GetNext();
+ } while(pSh != this);
+}
+/******************************************************************************
+ * void SwEditShell::EndAllAction()
+ ******************************************************************************/
+
+
+void SwEditShell::EndAllAction()
+{
+ ViewShell *pSh = this;
+ do {
+ if( pSh->IsA( TYPE( SwEditShell ) ) )
+ ((SwEditShell*)pSh)->EndAction();
+ else
+ pSh->EndAction();
+ pSh = (ViewShell *)pSh->GetNext();
+ } while(pSh != this);
+}
+
+/******************************************************************************
+ * void SwEditShell::CalcLayout()
+ ******************************************************************************/
+
+
+void SwEditShell::CalcLayout()
+{
+ StartAllAction();
+ ViewShell::CalcLayout();
+
+ ViewShell *pSh = this;
+ do
+ {
+ if ( pSh->GetWin() )
+ pSh->GetWin()->Invalidate();
+ pSh = (ViewShell*)pSh->GetNext();
+
+ } while ( pSh != this );
+
+ EndAllAction();
+}
+
+/******************************************************************************
+ * Inhaltsform bestimmen, holen
+ ******************************************************************************/
+// OPT: wird fuer jedes Attribut gerufen?
+
+
+sal_uInt16 SwEditShell::GetCntType() const
+{
+ // nur noch am SPoint ist der Inhalt interessant
+ sal_uInt16 nRet = 0;
+ if( IsTableMode() )
+ nRet = CNT_TXT;
+ else
+ switch( GetCrsr()->GetNode()->GetNodeType() )
+ {
+ case ND_TEXTNODE: nRet = CNT_TXT; break;
+ case ND_GRFNODE: nRet = CNT_GRF; break;
+ case ND_OLENODE: nRet = CNT_OLE; break;
+ }
+
+ OSL_ASSERT( nRet );
+ return nRet;
+}
+
+//------------------------------------------------------------------------------
+
+
+sal_Bool SwEditShell::HasOtherCnt() const
+
+{
+ if ( GetDoc()->GetSpzFrmFmts()->Count() )
+ return sal_True;
+
+ const SwNodes &rNds = GetDoc()->GetNodes();
+ const SwNode *pNd;
+
+ pNd = &rNds.GetEndOfInserts();
+ if ( 1 != (pNd->GetIndex() - pNd->StartOfSectionIndex()) )
+ return sal_True;
+
+ pNd = &rNds.GetEndOfAutotext();
+ if ( 1 != (pNd->GetIndex() - pNd->StartOfSectionIndex()) )
+ return sal_True;
+
+ return sal_False;
+}
+
+/******************************************************************************
+ * Zugriffsfunktionen fuer Filename-Behandlung
+ ******************************************************************************/
+
+
+SwActKontext::SwActKontext(SwEditShell *pShell)
+ : pSh(pShell)
+{
+ pSh->StartAction();
+}
+
+
+SwActKontext::~SwActKontext()
+{
+ pSh->EndAction();
+}
+
+/******************************************************************************
+ * Klasse fuer den automatisierten Aufruf von Start- und
+ * EndCrsrMove();
+ ******************************************************************************/
+
+
+SwMvKontext::SwMvKontext(SwEditShell *pShell ) : pSh(pShell)
+{
+ pSh->SttCrsrMove();
+}
+
+
+SwMvKontext::~SwMvKontext()
+{
+ pSh->EndCrsrMove();
+}
+
+
+SwFrmFmt *SwEditShell::GetTableFmt() // OPT: schnellster Test auf Tabelle?
+{
+ const SwTableNode* pTblNd = IsCrsrInTbl();
+ return pTblNd ? (SwFrmFmt*)pTblNd->GetTable().GetFrmFmt() : 0;
+}
+
+// OPT: wieso 3x beim neuen Dokument
+
+
+sal_uInt16 SwEditShell::GetTOXTypeCount(TOXTypes eTyp) const
+{
+ return pDoc->GetTOXTypeCount(eTyp);
+}
+
+
+void SwEditShell::InsertTOXType(const SwTOXType& rTyp)
+{
+ pDoc->InsertTOXType(rTyp);
+}
+
+
+
+void SwEditShell::DoUndo( sal_Bool bOn )
+{ GetDoc()->GetIDocumentUndoRedo().DoUndo( bOn ); }
+
+
+sal_Bool SwEditShell::DoesUndo() const
+{ return GetDoc()->GetIDocumentUndoRedo().DoesUndo(); }
+
+
+void SwEditShell::DoGroupUndo( sal_Bool bOn )
+{ GetDoc()->GetIDocumentUndoRedo().DoGroupUndo( bOn ); }
+
+
+sal_Bool SwEditShell::DoesGroupUndo() const
+{ return GetDoc()->GetIDocumentUndoRedo().DoesGroupUndo(); }
+
+
+void SwEditShell::DelAllUndoObj()
+{
+ GetDoc()->GetIDocumentUndoRedo().DelAllUndoObj();
+}
+
+// Zusammenfassen von Kontinuierlichen Insert/Delete/Overwrite von
+// Charaktern. Default ist sdbcx::Group-Undo.
+
+// setzt Undoklammerung auf, liefert nUndoId der Klammerung
+
+
+SwUndoId SwEditShell::StartUndo( SwUndoId eUndoId,
+ const SwRewriter *pRewriter )
+{ return GetDoc()->GetIDocumentUndoRedo().StartUndo( eUndoId, pRewriter ); }
+
+// schliesst Klammerung der nUndoId, nicht vom UI benutzt
+
+
+SwUndoId SwEditShell::EndUndo(SwUndoId eUndoId,
+ const SwRewriter *pRewriter)
+{ return GetDoc()->GetIDocumentUndoRedo().EndUndo(eUndoId, pRewriter); }
+
+
+bool SwEditShell::GetLastUndoInfo(::rtl::OUString *const o_pStr,
+ SwUndoId *const o_pId) const
+{ return GetDoc()->GetIDocumentUndoRedo().GetLastUndoInfo(o_pStr, o_pId); }
+
+bool SwEditShell::GetFirstRedoInfo(::rtl::OUString *const o_pStr) const
+{ return GetDoc()->GetIDocumentUndoRedo().GetFirstRedoInfo(o_pStr); }
+
+SwUndoId SwEditShell::GetRepeatInfo(::rtl::OUString *const o_pStr) const
+{ return GetDoc()->GetIDocumentUndoRedo().GetRepeatInfo(o_pStr); }
+
+
+
+// AutoKorrektur - JP 27.01.94
+void SwEditShell::AutoCorrect( SvxAutoCorrect& rACorr, sal_Bool bInsert,
+ sal_Unicode cChar )
+{
+ SET_CURR_SHELL( this );
+
+ StartAllAction();
+
+ SwPaM* pCrsr = getShellCrsr( true );
+ SwTxtNode* pTNd = pCrsr->GetNode()->GetTxtNode();
+
+ SwAutoCorrDoc aSwAutoCorrDoc( *this, *pCrsr, cChar );
+ rACorr.AutoCorrect( aSwAutoCorrDoc,
+ pTNd->GetTxt(), pCrsr->GetPoint()->nContent.GetIndex(),
+ cChar, bInsert, GetWin() );
+ if( cChar )
+ SaveTblBoxCntnt( pCrsr->GetPoint() );
+ EndAllAction();
+}
+
+
+void SwEditShell::SetNewDoc(sal_Bool bNew)
+{
+ GetDoc()->SetNewDoc(bNew);
+}
+
+
+sal_Bool SwEditShell::GetPrevAutoCorrWord( SvxAutoCorrect& rACorr, String& rWord )
+{
+ SET_CURR_SHELL( this );
+
+ sal_Bool bRet;
+ SwPaM* pCrsr = getShellCrsr( true );
+ xub_StrLen nPos = pCrsr->GetPoint()->nContent.GetIndex();
+ SwTxtNode* pTNd = pCrsr->GetNode()->GetTxtNode();
+ if( pTNd && nPos )
+ {
+ SwAutoCorrDoc aSwAutoCorrDoc( *this, *pCrsr, 0 );
+ bRet = rACorr.GetPrevAutoCorrWord( aSwAutoCorrDoc,
+ pTNd->GetTxt(), nPos, rWord );
+ }
+ else
+ bRet = sal_False;
+ return bRet;
+}
+
+SwAutoCompleteWord& SwEditShell::GetAutoCompleteWords()
+{
+ return SwDoc::GetAutoCompleteWords();
+}
+
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/fields/authfld.cxx b/sw/source/core/fields/authfld.cxx
new file mode 100644
index 000000000000..53052fb9ef08
--- /dev/null
+++ b/sw/source/core/fields/authfld.cxx
@@ -0,0 +1,756 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+
+#define _SVSTDARR_STRINGSDTOR
+#define _SVSTDARR_USHORTS
+#define _SVSTDARR_ULONGS
+#include <hintids.hxx>
+
+#include <svl/svstdarr.hxx>
+#include <editeng/unolingu.hxx>
+#include <editeng/langitem.hxx>
+#include <swtypes.hxx>
+#include <tools/resid.hxx>
+#include <comcore.hrc>
+#include <authfld.hxx>
+#include <expfld.hxx>
+#include <pam.hxx>
+#include <cntfrm.hxx>
+#include <tox.hxx>
+#include <txmsrt.hxx>
+#include <doctxm.hxx>
+#include <fmtfld.hxx>
+#include <txtfld.hxx>
+#include <ndtxt.hxx>
+#include <doc.hxx>
+#include <unofldmid.h>
+#include <unoprnms.hxx>
+#include <switerator.hxx>
+#include <unomid.h>
+
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::beans;
+using namespace ::com::sun::star::lang;
+using rtl::OUString;
+
+
+typedef SwAuthEntry* SwAuthEntryPtr;
+SV_DECL_PTRARR_DEL( SwAuthDataArr, SwAuthEntryPtr, 5, 5 )
+SV_IMPL_PTRARR( SwAuthDataArr, SwAuthEntryPtr )
+
+
+typedef SwTOXSortKey* TOXSortKeyPtr;
+SV_DECL_PTRARR_DEL( SortKeyArr, TOXSortKeyPtr, 5, 5 )
+SV_IMPL_PTRARR( SortKeyArr, TOXSortKeyPtr )
+
+SwAuthEntry::SwAuthEntry(const SwAuthEntry& rCopy)
+ : nRefCount(0)
+{
+ for(sal_uInt16 i = 0; i < AUTH_FIELD_END; i++)
+ aAuthFields[i] = rCopy.aAuthFields[i];
+}
+// --------------------------------------------------------
+sal_Bool SwAuthEntry::operator==(const SwAuthEntry& rComp)
+{
+ for(sal_uInt16 i = 0; i < AUTH_FIELD_END; i++)
+ if(aAuthFields[i] != rComp.aAuthFields[i])
+ return sal_False;
+ return sal_True;
+}
+// --------------------------------------------------------
+SwAuthorityFieldType::SwAuthorityFieldType(SwDoc* pDoc)
+ : SwFieldType( RES_AUTHORITY ),
+ m_pDoc(pDoc),
+ m_pDataArr(new SwAuthDataArr ),
+ m_pSortKeyArr(new SortKeyArr(3, 3)),
+ m_cPrefix('['),
+ m_cSuffix(']'),
+ m_bIsSequence(sal_False),
+ m_bSortByDocument(sal_True),
+ m_eLanguage((LanguageType)::GetAppLanguage())
+{
+}
+
+SwAuthorityFieldType::SwAuthorityFieldType( const SwAuthorityFieldType& rFType)
+ : SwFieldType( RES_AUTHORITY ),
+ m_pDataArr(new SwAuthDataArr ),
+ m_pSortKeyArr(new SortKeyArr(3, 3)),
+ m_cPrefix(rFType.m_cPrefix),
+ m_cSuffix(rFType.m_cSuffix),
+ m_bIsSequence(rFType.m_bIsSequence),
+ m_bSortByDocument(rFType.m_bSortByDocument),
+ m_eLanguage(rFType.m_eLanguage),
+ m_sSortAlgorithm(rFType.m_sSortAlgorithm)
+{
+ for(sal_uInt16 i = 0; i < rFType.m_pSortKeyArr->Count(); i++)
+ m_pSortKeyArr->Insert((*rFType.m_pSortKeyArr)[i], i);
+}
+
+SwAuthorityFieldType::~SwAuthorityFieldType()
+{
+ m_pSortKeyArr->DeleteAndDestroy(0, m_pSortKeyArr->Count());
+ delete m_pSortKeyArr;
+ m_SequArr.clear();
+ delete m_pDataArr;
+}
+
+SwFieldType* SwAuthorityFieldType::Copy() const
+{
+ return new SwAuthorityFieldType(m_pDoc);
+}
+
+void SwAuthorityFieldType::RemoveField(long nHandle)
+{
+#if OSL_DEBUG_LEVEL > 1
+ sal_Bool bRemoved = sal_False;
+#endif
+ for(sal_uInt16 j = 0; j < m_pDataArr->Count(); j++)
+ {
+ SwAuthEntry* pTemp = m_pDataArr->GetObject(j);
+ long nRet = (long)(void*)pTemp;
+ if(nRet == nHandle)
+ {
+#if OSL_DEBUG_LEVEL > 1
+ bRemoved = sal_True;
+#endif
+ pTemp->RemoveRef();
+ if(!pTemp->GetRefCount())
+ {
+ m_pDataArr->DeleteAndDestroy(j, 1);
+ //re-generate positions of the fields
+ DelSequenceArray();
+ }
+ break;
+ }
+ }
+#if OSL_DEBUG_LEVEL > 1
+ DBG_ASSERT(bRemoved, "Field unknown" );
+#endif
+}
+
+long SwAuthorityFieldType::AddField(const String& rFieldContents)
+{
+ long nRet = 0;
+ SwAuthEntry* pEntry = new SwAuthEntry;
+ for( sal_uInt16 i = 0; i < AUTH_FIELD_END; ++i )
+ pEntry->SetAuthorField( (ToxAuthorityField)i,
+ rFieldContents.GetToken( i, TOX_STYLE_DELIMITER ));
+
+ for(sal_uInt16 j = 0; j < m_pDataArr->Count() && pEntry; j++)
+ {
+ SwAuthEntry* pTemp = m_pDataArr->GetObject(j);
+ if(*pTemp == *pEntry)
+ {
+ DELETEZ(pEntry);
+ nRet = (long)(void*)pTemp;
+ pTemp->AddRef();
+ }
+ }
+ //if it is a new Entry - insert
+ if(pEntry)
+ {
+ nRet = (long)(void*)pEntry;
+ pEntry->AddRef();
+ m_pDataArr->Insert(pEntry, m_pDataArr->Count());
+ //re-generate positions of the fields
+ DelSequenceArray();
+ }
+ return nRet;
+}
+
+sal_Bool SwAuthorityFieldType::AddField(long nHandle)
+{
+ sal_Bool bRet = sal_False;
+ for( sal_uInt16 j = 0; j < m_pDataArr->Count(); j++ )
+ {
+ SwAuthEntry* pTemp = m_pDataArr->GetObject(j);
+ long nTmp = (long)(void*)pTemp;
+ if( nTmp == nHandle )
+ {
+ bRet = sal_True;
+ pTemp->AddRef();
+ //re-generate positions of the fields
+ DelSequenceArray();
+ break;
+ }
+ }
+ DBG_ASSERT(bRet, "::AddField(long) failed");
+ return bRet;
+}
+
+const SwAuthEntry* SwAuthorityFieldType::GetEntryByHandle(long nHandle) const
+{
+ const SwAuthEntry* pRet = 0;
+ for(sal_uInt16 j = 0; j < m_pDataArr->Count(); j++)
+ {
+ const SwAuthEntry* pTemp = m_pDataArr->GetObject(j);
+ long nTmp = (long)(void*)pTemp;
+ if( nTmp == nHandle )
+ {
+ pRet = pTemp;
+ break;
+ }
+ }
+ OSL_ENSURE( pRet, "invalid Handle" );
+ return pRet;
+}
+
+void SwAuthorityFieldType::GetAllEntryIdentifiers(
+ SvStringsDtor& rToFill )const
+{
+ for(sal_uInt16 j = 0; j < m_pDataArr->Count(); j++)
+ {
+ SwAuthEntry* pTemp = m_pDataArr->GetObject(j);
+ rToFill.Insert( new String( pTemp->GetAuthorField(
+ AUTH_FIELD_IDENTIFIER )), rToFill.Count() );
+ }
+}
+
+const SwAuthEntry* SwAuthorityFieldType::GetEntryByIdentifier(
+ const String& rIdentifier)const
+{
+ const SwAuthEntry* pRet = 0;
+ for( sal_uInt16 j = 0; j < m_pDataArr->Count(); ++j )
+ {
+ const SwAuthEntry* pTemp = m_pDataArr->GetObject(j);
+ if( rIdentifier == pTemp->GetAuthorField( AUTH_FIELD_IDENTIFIER ))
+ {
+ pRet = pTemp;
+ break;
+ }
+ }
+ return pRet;
+}
+
+bool SwAuthorityFieldType::ChangeEntryContent(const SwAuthEntry* pNewEntry)
+{
+ bool bChanged = false;
+ for( sal_uInt16 j = 0; j < m_pDataArr->Count(); ++j )
+ {
+ SwAuthEntry* pTemp = m_pDataArr->GetObject(j);
+ if(pTemp->GetAuthorField(AUTH_FIELD_IDENTIFIER) ==
+ pNewEntry->GetAuthorField(AUTH_FIELD_IDENTIFIER))
+ {
+ for(sal_uInt16 i = 0; i < AUTH_FIELD_END; i++)
+ pTemp->SetAuthorField((ToxAuthorityField) i,
+ pNewEntry->GetAuthorField((ToxAuthorityField)i));
+ bChanged = true;
+ break;
+ }
+ }
+ return bChanged;
+}
+
+/*-------------------------------------------------------------------------
+ appends a new entry (if new) and returns the array position
+ -----------------------------------------------------------------------*/
+sal_uInt16 SwAuthorityFieldType::AppendField( const SwAuthEntry& rInsert )
+{
+ sal_uInt16 nRet = 0;
+ for( nRet = 0; nRet < m_pDataArr->Count(); ++nRet )
+ {
+ SwAuthEntry* pTemp = m_pDataArr->GetObject( nRet );
+ if( *pTemp == rInsert )
+ {
+ break;
+ //ref count unchanged
+ }
+ }
+
+ //if it is a new Entry - insert
+ if( nRet == m_pDataArr->Count() )
+ m_pDataArr->Insert( new SwAuthEntry( rInsert ), nRet );
+
+ return nRet;
+}
+
+long SwAuthorityFieldType::GetHandle(sal_uInt16 nPos)
+{
+ long nRet = 0;
+ if( nPos < m_pDataArr->Count() )
+ {
+ SwAuthEntry* pTemp = m_pDataArr->GetObject(nPos);
+ nRet = (long)(void*)pTemp;
+ }
+ return nRet;
+}
+
+sal_uInt16 SwAuthorityFieldType::GetSequencePos(long nHandle)
+{
+ //find the field in a sorted array of handles,
+#if OSL_DEBUG_LEVEL > 1
+ sal_Bool bCurrentFieldWithoutTextNode = sal_False;
+#endif
+ if(!m_SequArr.empty() && m_SequArr.size() != m_pDataArr->Count())
+ DelSequenceArray();
+ if(m_SequArr.empty())
+ {
+ SwTOXSortTabBases aSortArr;
+ SwIterator<SwFmtFld,SwFieldType> aIter( *this );
+
+ SwTOXInternational aIntl(m_eLanguage, 0, m_sSortAlgorithm);
+
+ for( SwFmtFld* pFmtFld = aIter.First(); pFmtFld; pFmtFld = aIter.Next() )
+ {
+ const SwTxtFld* pTxtFld = pFmtFld->GetTxtFld();
+ if(!pTxtFld || !pTxtFld->GetpTxtNode())
+ {
+#if OSL_DEBUG_LEVEL > 1
+ if(nHandle == ((SwAuthorityField*)pFmtFld->GetFld())->GetHandle())
+ bCurrentFieldWithoutTextNode = sal_True;
+#endif
+ continue;
+ }
+ const SwTxtNode& rFldTxtNode = pTxtFld->GetTxtNode();
+ SwPosition aFldPos(rFldTxtNode);
+ SwDoc& rDoc = *(SwDoc*)rFldTxtNode.GetDoc();
+ SwCntntFrm *pFrm = rFldTxtNode.getLayoutFrm( rDoc.GetCurrentLayout() );
+ const SwTxtNode* pTxtNode = 0;
+ if(pFrm && !pFrm->IsInDocBody())
+ pTxtNode = GetBodyTxtNode( rDoc, aFldPos, *pFrm );
+ //if no text node could be found or the field is in the document
+ //body the directly available text node will be used
+ if(!pTxtNode)
+ pTxtNode = &rFldTxtNode;
+ if( pTxtNode->GetTxt().Len() && pTxtNode->getLayoutFrm( rDoc.GetCurrentLayout() ) &&
+ pTxtNode->GetNodes().IsDocNodes() )
+ {
+ SwTOXAuthority* pNew = new SwTOXAuthority( *pTxtNode,
+ *pFmtFld, aIntl );
+
+ for(short i = 0; i < aSortArr.Count(); ++i)
+ {
+ SwTOXSortTabBase* pOld = aSortArr[i];
+ if(*pOld == *pNew)
+ {
+ //only the first occurrence in the document
+ //has to be in the array
+ if(*pOld < *pNew)
+ DELETEZ(pNew);
+ else // remove the old content
+ aSortArr.DeleteAndDestroy( i, 1 );
+ break;
+ }
+ }
+ //if it still exists - insert at the correct position
+ if(pNew)
+ {
+ short j;
+
+ for( j = 0; j < aSortArr.Count(); ++j)
+ {
+ SwTOXSortTabBase* pOld = aSortArr[j];
+ if(*pNew < *pOld)
+ break;
+ }
+ aSortArr.Insert(pNew, j );
+ }
+ }
+ }
+
+ for(sal_uInt16 i = 0; i < aSortArr.Count(); i++)
+ {
+ const SwTOXSortTabBase& rBase = *aSortArr[i];
+ SwFmtFld& rFmtFld = ((SwTOXAuthority&)rBase).GetFldFmt();
+ SwAuthorityField* pAFld = (SwAuthorityField*)rFmtFld.GetFld();
+ m_SequArr.push_back(pAFld->GetHandle());
+ }
+ aSortArr.DeleteAndDestroy(0, aSortArr.Count());
+ }
+ //find nHandle
+ sal_uInt16 nRet = 0;
+ for(sal_uInt16 i = 0; i < m_SequArr.size(); ++i)
+ {
+ if(m_SequArr[i] == nHandle)
+ {
+ nRet = i + 1;
+ break;
+ }
+ }
+#if OSL_DEBUG_LEVEL > 1
+ OSL_ENSURE(bCurrentFieldWithoutTextNode || nRet, "Handle not found");
+#endif
+ return nRet;
+}
+
+bool SwAuthorityFieldType::QueryValue( Any& rVal, sal_uInt16 nWhichId ) const
+{
+ switch( nWhichId )
+ {
+ case FIELD_PROP_PAR1:
+ case FIELD_PROP_PAR2:
+ {
+ OUString sVal;
+ sal_Unicode uRet = FIELD_PROP_PAR1 == nWhichId ? m_cPrefix : m_cSuffix;
+ if(uRet)
+ sVal = OUString(uRet);
+ rVal <<= sVal;
+ }
+ break;
+ case FIELD_PROP_PAR3:
+ rVal <<= OUString(GetSortAlgorithm());
+ break;
+
+ case FIELD_PROP_BOOL1:
+ case FIELD_PROP_BOOL2:
+ {
+ sal_Bool bVal = FIELD_PROP_BOOL1 == nWhichId ? m_bIsSequence: m_bSortByDocument;
+ rVal.setValue(&bVal, ::getBooleanCppuType());
+ }
+ break;
+
+ case FIELD_PROP_LOCALE:
+ rVal <<= SvxCreateLocale(GetLanguage());
+ break;
+
+ case FIELD_PROP_PROP_SEQ:
+ {
+ Sequence<PropertyValues> aRet(m_pSortKeyArr->Count());
+ PropertyValues* pValues = aRet.getArray();
+ OUString sProp1( rtl::OUString::createFromAscii(SW_PROP_NAME_STR(UNO_NAME_SORT_KEY)) ),
+ sProp2( rtl::OUString::createFromAscii(SW_PROP_NAME_STR(UNO_NAME_IS_SORT_ASCENDING)));
+ for(sal_uInt16 i = 0; i < m_pSortKeyArr->Count(); i++)
+ {
+ const SwTOXSortKey* pKey = (*m_pSortKeyArr)[i];
+ pValues[i].realloc(2);
+ PropertyValue* pValue = pValues[i].getArray();
+ pValue[0].Name = sProp1;
+ pValue[0].Value <<= sal_Int16(pKey->eField);
+ pValue[1].Name = sProp2;
+ pValue[1].Value.setValue(&pKey->bSortAscending, ::getBooleanCppuType());
+ }
+ rVal <<= aRet;
+ }
+ break;
+ default:
+ OSL_FAIL("illegal property");
+ }
+ return true;
+}
+
+bool SwAuthorityFieldType::PutValue( const Any& rAny, sal_uInt16 nWhichId )
+{
+ bool bRet = true;
+ String sTmp;
+ switch( nWhichId )
+ {
+ case FIELD_PROP_PAR1:
+ case FIELD_PROP_PAR2:
+ {
+ ::GetString( rAny, sTmp );
+ sal_Unicode uSet = sTmp.GetChar(0);
+ if( FIELD_PROP_PAR1 == nWhichId )
+ m_cPrefix = uSet;
+ else
+ m_cSuffix = uSet;
+ }
+ break;
+ case FIELD_PROP_PAR3:
+ SetSortAlgorithm( ::GetString( rAny, sTmp ));
+ break;
+
+ case FIELD_PROP_BOOL1:
+ m_bIsSequence = *(sal_Bool*)rAny.getValue();
+ break;
+ case FIELD_PROP_BOOL2:
+ m_bSortByDocument = *(sal_Bool*)rAny.getValue();
+ break;
+
+ case FIELD_PROP_LOCALE:
+ {
+ Locale aLocale;
+ if( 0 != (bRet = rAny >>= aLocale ))
+ SetLanguage( SvxLocaleToLanguage( aLocale ));
+ }
+ break;
+
+ case FIELD_PROP_PROP_SEQ:
+ {
+ Sequence<PropertyValues> aSeq;
+ if( 0 != (bRet = rAny >>= aSeq) )
+ {
+ m_pSortKeyArr->DeleteAndDestroy(0, m_pSortKeyArr->Count());
+ const PropertyValues* pValues = aSeq.getConstArray();
+ for(sal_Int32 i = 0; i < aSeq.getLength() && i < USHRT_MAX / 4; i++)
+ {
+ const PropertyValue* pValue = pValues[i].getConstArray();
+ SwTOXSortKey* pSortKey = new SwTOXSortKey;
+ for(sal_Int32 j = 0; j < pValues[i].getLength(); j++)
+ {
+ if(pValue[j].Name.equalsAsciiL(SW_PROP_NAME(UNO_NAME_SORT_KEY)))
+ {
+ sal_Int16 nVal = -1; pValue[j].Value >>= nVal;
+ if(nVal >= 0 && nVal < AUTH_FIELD_END)
+ pSortKey->eField = (ToxAuthorityField) nVal;
+ else
+ bRet = false;
+ }
+ else if(pValue[j].Name.equalsAsciiL(SW_PROP_NAME(UNO_NAME_IS_SORT_ASCENDING)))
+ {
+ pSortKey->bSortAscending = *(sal_Bool*)pValue[j].Value.getValue();
+ }
+ }
+ m_pSortKeyArr->Insert(pSortKey, m_pSortKeyArr->Count());
+ }
+ }
+ }
+ break;
+ default:
+ OSL_FAIL("illegal property");
+ }
+ return bRet;
+}
+
+void SwAuthorityFieldType::Modify( const SfxPoolItem* pOld, const SfxPoolItem *pNew )
+{
+ //re-generate positions of the fields
+ DelSequenceArray();
+ NotifyClients( pOld, pNew );
+}
+
+sal_uInt16 SwAuthorityFieldType::GetSortKeyCount() const
+{
+ return m_pSortKeyArr->Count();
+}
+
+const SwTOXSortKey* SwAuthorityFieldType::GetSortKey(sal_uInt16 nIdx) const
+{
+ SwTOXSortKey* pRet = 0;
+ if(m_pSortKeyArr->Count() > nIdx)
+ pRet = (*m_pSortKeyArr)[nIdx];
+ DBG_ASSERT(pRet, "Sort key not found");
+ return pRet;
+}
+
+void SwAuthorityFieldType::SetSortKeys(sal_uInt16 nKeyCount, SwTOXSortKey aKeys[])
+{
+ m_pSortKeyArr->DeleteAndDestroy(0, m_pSortKeyArr->Count());
+ sal_uInt16 nArrIdx = 0;
+ for(sal_uInt16 i = 0; i < nKeyCount; i++)
+ if(aKeys[i].eField < AUTH_FIELD_END)
+ m_pSortKeyArr->Insert(new SwTOXSortKey(aKeys[i]), nArrIdx++);
+}
+
+SwAuthorityField::SwAuthorityField( SwAuthorityFieldType* pInitType,
+ const String& rFieldContents )
+ : SwField(pInitType),
+ m_nTempSequencePos( -1 )
+{
+ m_nHandle = pInitType->AddField( rFieldContents );
+}
+
+SwAuthorityField::SwAuthorityField( SwAuthorityFieldType* pInitType,
+ long nSetHandle )
+ : SwField( pInitType ),
+ m_nHandle( nSetHandle ),
+ m_nTempSequencePos( -1 )
+{
+ pInitType->AddField( m_nHandle );
+}
+
+SwAuthorityField::~SwAuthorityField()
+{
+ ((SwAuthorityFieldType* )GetTyp())->RemoveField(m_nHandle);
+}
+
+String SwAuthorityField::Expand() const
+{
+ SwAuthorityFieldType* pAuthType = (SwAuthorityFieldType*)GetTyp();
+ String sRet;
+ if(pAuthType->GetPrefix())
+ sRet.Assign(pAuthType->GetPrefix());
+
+ if( pAuthType->IsSequence() )
+ {
+ if(!pAuthType->GetDoc()->IsExpFldsLocked())
+ m_nTempSequencePos = pAuthType->GetSequencePos( m_nHandle );
+ if( m_nTempSequencePos >= 0 )
+ sRet += String::CreateFromInt32( m_nTempSequencePos );
+ }
+ else
+ {
+ const SwAuthEntry* pEntry = pAuthType->GetEntryByHandle(m_nHandle);
+ //TODO: Expand to: identifier, number sequence, ...
+ if(pEntry)
+ sRet += pEntry->GetAuthorField(AUTH_FIELD_IDENTIFIER);
+ }
+ if(pAuthType->GetSuffix())
+ sRet += pAuthType->GetSuffix();
+ return sRet;
+}
+
+SwField* SwAuthorityField::Copy() const
+{
+ SwAuthorityFieldType* pAuthType = (SwAuthorityFieldType*)GetTyp();
+ return new SwAuthorityField(pAuthType, m_nHandle);
+}
+
+const String& SwAuthorityField::GetFieldText(ToxAuthorityField eField) const
+{
+ SwAuthorityFieldType* pAuthType = (SwAuthorityFieldType*)GetTyp();
+ const SwAuthEntry* pEntry = pAuthType->GetEntryByHandle( m_nHandle );
+ return pEntry->GetAuthorField( eField );
+}
+
+void SwAuthorityField::SetPar1(const String& rStr)
+{
+ SwAuthorityFieldType* pInitType = (SwAuthorityFieldType* )GetTyp();
+ pInitType->RemoveField(m_nHandle);
+ m_nHandle = pInitType->AddField(rStr);
+}
+
+String SwAuthorityField::GetDescription() const
+{
+ return SW_RES(STR_AUTHORITY_ENTRY);
+}
+
+const char* aFieldNames[] =
+{
+ "Identifier",
+ "BibiliographicType",
+ "Address",
+ "Annote",
+ "Author",
+ "Booktitle",
+ "Chapter",
+ "Edition",
+ "Editor",
+ "Howpublished",
+ "Institution",
+ "Journal",
+ "Month",
+ "Note",
+ "Number",
+ "Organizations",
+ "Pages",
+ "Publisher",
+ "School",
+ "Series",
+ "Title",
+ "Report_Type",
+ "Volume",
+ "Year",
+ "URL",
+ "Custom1",
+ "Custom2",
+ "Custom3",
+ "Custom4",
+ "Custom5",
+ "ISBN"
+};
+
+bool SwAuthorityField::QueryValue( Any& rAny, sal_uInt16 /*nWhichId*/ ) const
+{
+ if(!GetTyp())
+ return false;
+ const SwAuthEntry* pAuthEntry = ((SwAuthorityFieldType*)GetTyp())->GetEntryByHandle(m_nHandle);
+ if(!pAuthEntry)
+ return false;
+ Sequence <PropertyValue> aRet(AUTH_FIELD_END);
+ PropertyValue* pValues = aRet.getArray();
+ for(sal_Int16 i = 0; i < AUTH_FIELD_END; i++)
+ {
+ pValues[i].Name = rtl::OUString::createFromAscii(aFieldNames[i]);
+ const String& rField = pAuthEntry->GetAuthorField((ToxAuthorityField) i);
+ if(i == AUTH_FIELD_AUTHORITY_TYPE)
+ pValues[i].Value <<= sal_Int16(rField.ToInt32());
+ else
+ pValues[i].Value <<= OUString(rField);
+ }
+ rAny <<= aRet;
+ /* FIXME: it is weird that we always return false here */
+ return false;
+}
+
+sal_Int16 lcl_Find(const OUString& rFieldName)
+{
+ for(sal_Int16 i = 0; i < AUTH_FIELD_END; i++)
+ if(!rFieldName.compareToAscii(aFieldNames[i]))
+ return i;
+ return -1;
+}
+//----------------------------------------------------------------------------
+bool SwAuthorityField::PutValue( const Any& rAny, sal_uInt16 /*nWhichId*/ )
+{
+ if(!GetTyp() || !((SwAuthorityFieldType*)GetTyp())->GetEntryByHandle(m_nHandle))
+ return false;
+
+ Sequence <PropertyValue> aParam;
+ if(!(rAny >>= aParam))
+ return false;
+
+ String sToSet;
+ sToSet.Fill(AUTH_FIELD_ISBN, TOX_STYLE_DELIMITER);
+ const PropertyValue* pParam = aParam.getConstArray();
+ for(sal_Int32 i = 0; i < aParam.getLength(); i++)
+ {
+ sal_Int16 nFound = lcl_Find(pParam[i].Name);
+ if(nFound >= 0)
+ {
+ OUString sContent;
+ if(AUTH_FIELD_AUTHORITY_TYPE == nFound)
+ {
+ sal_Int16 nVal = 0;
+ pParam[i].Value >>= nVal;
+ sContent = OUString::valueOf((sal_Int32)nVal);
+ }
+ else
+ pParam[i].Value >>= sContent;
+ sToSet.SetToken(nFound, TOX_STYLE_DELIMITER, sContent);
+ }
+ }
+
+ ((SwAuthorityFieldType*)GetTyp())->RemoveField(m_nHandle);
+ m_nHandle = ((SwAuthorityFieldType*)GetTyp())->AddField(sToSet);
+
+ /* FIXME: it is weird that we always return false here */
+ return false;
+}
+
+SwFieldType* SwAuthorityField::ChgTyp( SwFieldType* pFldTyp )
+{
+ SwAuthorityFieldType* pSrcTyp = (SwAuthorityFieldType*)GetTyp(),
+ * pDstTyp = (SwAuthorityFieldType*)pFldTyp;
+ if( pSrcTyp != pDstTyp )
+ {
+
+ const SwAuthEntry* pEntry = pSrcTyp->GetEntryByHandle( m_nHandle );
+ sal_uInt16 nHdlPos = pDstTyp->AppendField( *pEntry );
+ pSrcTyp->RemoveField( m_nHandle );
+ m_nHandle = pDstTyp->GetHandle( nHdlPos );
+ pDstTyp->AddField( m_nHandle );
+ SwField::ChgTyp( pFldTyp );
+ }
+ return pSrcTyp;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/fields/cellfml.cxx b/sw/source/core/fields/cellfml.cxx
new file mode 100644
index 000000000000..c27498819ee7
--- /dev/null
+++ b/sw/source/core/fields/cellfml.cxx
@@ -0,0 +1,1215 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+
+#include <float.h>
+#include <hintids.hxx>
+#include <hints.hxx>
+#include <fmtfld.hxx>
+#include <txtfld.hxx>
+#include <frmfmt.hxx>
+#include <layfrm.hxx>
+#include <cntfrm.hxx>
+#include <tabfrm.hxx>
+#include <doc.hxx>
+#include <docary.hxx>
+#include <ndtxt.hxx>
+#include <swtable.hxx>
+#include <tblsel.hxx>
+#include <cellfml.hxx>
+#include <calc.hxx>
+#include <expfld.hxx>
+#include <usrfld.hxx>
+#include <flddat.hxx>
+#include <cellatr.hxx>
+#include <ndindex.hxx>
+
+const sal_Unicode cRelTrenner = ',';
+const sal_Unicode cRelKennung = ''; // CTRL-R
+
+const sal_uInt16 cMAXSTACKSIZE = 50;
+
+const SwFrm* lcl_GetBoxFrm( const SwTableBox& rBox );
+long lcl_GetLongBoxNum( String& rStr );
+const SwTableBox* lcl_RelToBox( const SwTable&, const SwTableBox*, const String& );
+String lcl_BoxNmToRel( const SwTable&, const SwTableNode&,
+ const String& , const String& , bool );
+
+
+/*************************************************************************
+|*
+|* double SwTableBox::GetValue() const
+|* gebe den Wert dieser Box zurueck. Der Wert ergibt sich aus dem 1.
+|* TextNode. Beginnt dieser mit einer Zahl/Formel, so berechne diese;
+|* oder mit einem Feld, dann hole den Wert.
+|* Alle anderen Bedingungen returnen einen Fehler (oder 0 ?)
+|*
+|*************************************************************************/
+
+double SwTableBox::GetValue( SwTblCalcPara& rCalcPara ) const
+{
+ double nRet = 0;
+
+ if( rCalcPara.rCalc.IsCalcError() )
+ return nRet; // schon ein Fehler in der Berechnung
+
+ rCalcPara.rCalc.SetCalcError( CALC_SYNTAX ); // default immer Fehler
+
+ // keine Content Box ?
+ if( !pSttNd )
+ return nRet;
+
+ if( rCalcPara.IncStackCnt() )
+ return nRet;
+
+ rCalcPara.SetLastTblBox( this );
+
+ // wird eine Rekursion erzeugt ?
+ SwTableBox* pBox = (SwTableBox*)this;
+ if( rCalcPara.pBoxStk->Seek_Entry( pBox ))
+ return nRet; // steht schon auf dem Stack: FEHLER
+
+ // bei dieser Box nochmal aufsetzen
+ rCalcPara.SetLastTblBox( this );
+
+ rCalcPara.pBoxStk->Insert( pBox ); // eintragen
+ do { // Middle-Check-Loop, damit aus dieser gesprungen werden kann
+ // hier aufgespannt, damit am Ende der Box-Pointer aus dem
+ // Stack ausgetragen wird
+ SwDoc* pDoc = GetFrmFmt()->GetDoc();
+
+ const SfxPoolItem* pItem;
+ if( SFX_ITEM_SET == GetFrmFmt()->GetItemState(
+ RES_BOXATR_FORMULA, sal_False, &pItem ) )
+ {
+ rCalcPara.rCalc.SetCalcError( CALC_NOERR ); // wieder zuruecksetzen
+ if( !((SwTblBoxFormula*)pItem)->IsValid() )
+ {
+ // dann berechnen
+ const SwTable* pTmp = rCalcPara.pTbl;
+ rCalcPara.pTbl = &pBox->GetSttNd()->FindTableNode()->GetTable();
+ ((SwTblBoxFormula*)pItem)->Calc( rCalcPara, nRet );
+
+ if( !rCalcPara.IsStackOverFlow() )
+ {
+ SwFrmFmt* pFmt = pBox->ClaimFrmFmt();
+ SfxItemSet aTmp( pDoc->GetAttrPool(),
+ RES_BOXATR_BEGIN,RES_BOXATR_END-1 );
+ aTmp.Put( SwTblBoxValue( nRet ) );
+ if( SFX_ITEM_SET != pFmt->GetItemState( RES_BOXATR_FORMAT ))
+ aTmp.Put( SwTblBoxNumFormat( 0 ));
+ pFmt->SetFmtAttr( aTmp );
+ }
+ rCalcPara.pTbl = pTmp;
+ }
+ else
+ nRet = GetFrmFmt()->GetTblBoxValue().GetValue();
+ break;
+ }
+ else if( SFX_ITEM_SET == pBox->GetFrmFmt()->GetItemState(
+ RES_BOXATR_VALUE, sal_False, &pItem ) )
+ {
+ rCalcPara.rCalc.SetCalcError( CALC_NOERR ); // wieder zuruecksetzen
+ nRet = ((SwTblBoxValue*)pItem)->GetValue();
+ break;
+ }
+
+ SwTxtNode* pTxtNd = pDoc->GetNodes()[ pSttNd->GetIndex() + 1 ]->GetTxtNode();
+ if( !pTxtNd )
+ break;
+
+ xub_StrLen nSttPos = 0;
+ const String& rTxt = pTxtNd->GetTxt();
+ while( nSttPos < rTxt.Len() &&
+ ( ' ' == rTxt.GetChar( nSttPos ) || '\t' == rTxt.GetChar( nSttPos ) ) )
+ ++nSttPos;
+
+ // beginnt an erster Position ein "RechenFeld", dann erfrage den Wert
+ // von diesem
+ sal_Unicode const Char = rTxt.GetChar(nSttPos);
+ if ( nSttPos < rTxt.Len() &&
+ ( CH_TXTATR_BREAKWORD == Char || CH_TXTATR_INWORD == Char ) )
+ {
+ SwIndex aIdx( pTxtNd, nSttPos );
+ SwTxtFld * const pTxtFld = static_cast<SwTxtFld*>(
+ pTxtNd->GetTxtAttrForCharAt(aIdx.GetIndex(), RES_TXTATR_FIELD));
+ if( !pTxtFld )
+ break;
+
+ rCalcPara.rCalc.SetCalcError( CALC_NOERR ); // wieder zuruecksetzen
+
+ const SwField* pFld = pTxtFld->GetFld().GetFld();
+ switch( pFld->GetTyp()->Which() )
+ {
+ case RES_SETEXPFLD:
+ nRet = ((SwSetExpField*)pFld)->GetValue();
+ break;
+ case RES_USERFLD:
+ nRet = ((SwUserFieldType*)pFld)->GetValue();
+ break;
+ case RES_TABLEFLD:
+ {
+ SwTblField* pTblFld = (SwTblField*)pFld;
+ if( !pTblFld->IsValid() ) // ist der Wert gueltig ??
+ {
+ // die richtige Tabelle mitgeben!
+ const SwTable* pTmp = rCalcPara.pTbl;
+ rCalcPara.pTbl = &pTxtNd->FindTableNode()->GetTable();
+ pTblFld->CalcField( rCalcPara );
+ rCalcPara.pTbl = pTmp;
+ }
+ nRet = pTblFld->GetValue();
+ }
+ break;
+
+ case RES_DATETIMEFLD:
+ nRet = ((SwDateTimeField*)pFld)->GetValue();
+ break;
+
+ case RES_JUMPEDITFLD:
+ //JP 14.09.98: Bug 56112 - der Platzhalter kann nie einen
+ // gueltigen Inhalt haben!
+ nRet = 0;
+ break;
+
+ default:
+ String const value(pFld->ExpandField(true));
+ nRet = rCalcPara.rCalc.Calculate(value).GetDouble();
+ }
+ }
+ else
+ {
+ // Ergebnis ist 0 und kein Fehler!
+ rCalcPara.rCalc.SetCalcError( CALC_NOERR ); // wieder zuruecksetzen
+
+ double aNum;
+ String sTxt( rTxt.Copy( nSttPos ) );
+ sal_uInt32 nFmtIndex = GetFrmFmt()->GetTblBoxNumFmt().GetValue();
+
+ SvNumberFormatter* pNumFmtr = pDoc->GetNumberFormatter();
+
+ if( NUMBERFORMAT_TEXT == nFmtIndex )
+ nFmtIndex = 0;
+ // JP 22.04.98: Bug 49659 - Sonderbehandlung fuer Prozent
+ else if( sTxt.Len() &&
+ NUMBERFORMAT_PERCENT == pNumFmtr->GetType( nFmtIndex ))
+ {
+ sal_uInt32 nTmpFmt = 0;
+ if( pNumFmtr->IsNumberFormat( sTxt, nTmpFmt, aNum ) &&
+ NUMBERFORMAT_NUMBER == pNumFmtr->GetType( nTmpFmt ))
+ sTxt += '%';
+ }
+
+ if( pNumFmtr->IsNumberFormat( sTxt, nFmtIndex, aNum ))
+ nRet = aNum;
+ }
+
+// ?? sonst ist das ein Fehler
+ } while( sal_False );
+
+ if( !rCalcPara.IsStackOverFlow() )
+ {
+ rCalcPara.pBoxStk->Remove( pBox ); // raus aus dem Stack
+ rCalcPara.DecStackCnt();
+ }
+
+ //JP 12.01.99: mit Fehlererkennung, Bug 60794
+ if( DBL_MAX == nRet )
+ rCalcPara.rCalc.SetCalcError( CALC_SYNTAX ); // Fehler setzen
+
+ return nRet;
+}
+
+/* */
+
+// Struktur, die zum TabelleRechnen benoetigt wird
+
+SwTblCalcPara::SwTblCalcPara( SwCalc& rCalculator, const SwTable& rTable )
+ : pLastTblBox( 0 ), nStackCnt( 0 ), nMaxSize( cMAXSTACKSIZE ),
+ rCalc( rCalculator ), pTbl( &rTable )
+{
+ pBoxStk = new SwTableSortBoxes;
+}
+
+SwTblCalcPara::~SwTblCalcPara()
+{
+ delete pBoxStk;
+}
+
+sal_Bool SwTblCalcPara::CalcWithStackOverflow()
+{
+ // falls ein StackUeberlauf erkannt wurde, sollte mit
+ // der letzten Box noch mal aufgesetzt werden. Irgend
+ // ein Weg sollte dann
+ sal_uInt16 nSaveMaxSize = nMaxSize;
+
+ nMaxSize = cMAXSTACKSIZE - 5;
+ sal_uInt16 nCnt = 0;
+ SwTableBoxes aStackOverFlows;
+ do {
+ SwTableBox* pBox = (SwTableBox*)pLastTblBox;
+ nStackCnt = 0;
+ rCalc.SetCalcError( CALC_NOERR );
+ aStackOverFlows.C40_INSERT( SwTableBox, pBox, nCnt++ );
+
+ pBoxStk->Remove( pBox );
+ pBox->GetValue( *this );
+ } while( IsStackOverFlow() );
+
+ nMaxSize = cMAXSTACKSIZE - 3; // es muss mind. 1 Stufe tiefer gehen!
+
+ // falls Rekursionen erkannt wurden
+ nStackCnt = 0;
+ rCalc.SetCalcError( CALC_NOERR );
+ pBoxStk->Remove( sal_uInt16(0), pBoxStk->Count() );
+
+ while( !rCalc.IsCalcError() && nCnt )
+ {
+ aStackOverFlows[ --nCnt ]->GetValue( *this );
+ if( IsStackOverFlow() && !CalcWithStackOverflow() )
+ break;
+ }
+
+ nMaxSize = nSaveMaxSize;
+ aStackOverFlows.Remove( 0, aStackOverFlows.Count() );
+ return !rCalc.IsCalcError();
+}
+
+/* */
+
+SwTableFormula::SwTableFormula( const String& rFormel )
+ : sFormel( rFormel )
+{
+ eNmType = EXTRNL_NAME;
+ bValidValue = false;
+}
+
+SwTableFormula::~SwTableFormula()
+{
+}
+
+void SwTableFormula::_MakeFormel( const SwTable& rTbl, String& rNewStr,
+ String& rFirstBox, String* pLastBox, void* pPara ) const
+{
+ SwTblCalcPara* pCalcPara = (SwTblCalcPara*)pPara;
+ if( pCalcPara->rCalc.IsCalcError() ) // ist schon Fehler gesetzt ?
+ return;
+
+ SwTableBox* pSttBox, *pEndBox = 0;
+
+ rFirstBox.Erase(0,1); // Kennung fuer Box loeschen
+ // ein Bereich in dieser Klammer ?
+ if( pLastBox )
+ {
+ pEndBox = reinterpret_cast<SwTableBox*>(sal::static_int_cast<sal_IntPtr>(pLastBox->ToInt64()));
+
+ // ist das ueberhaupt ein gueltiger Pointer ??
+ if( !rTbl.GetTabSortBoxes().Seek_Entry( pEndBox ))
+ pEndBox = 0;
+ rFirstBox.Erase( 0, pLastBox->Len()+1 );
+ }
+ pSttBox = reinterpret_cast<SwTableBox*>(sal::static_int_cast<sal_IntPtr>(rFirstBox.ToInt64()));
+ // ist das ueberhaupt ein gueltiger Pointer ??
+ if( !rTbl.GetTabSortBoxes().Seek_Entry( pSttBox ))
+ pSttBox = 0;
+
+ rNewStr += ' ';
+ if( pEndBox && pSttBox ) // Bereich ?
+ {
+ // hole ueber das Layout alle "selectierten" Boxen und berechne
+ // deren Werte
+ SwSelBoxes aBoxes;
+ GetBoxes( *pSttBox, *pEndBox, aBoxes );
+
+ rNewStr += '(';
+ bool bDelim = false;
+ for( sal_uInt16 n = 0; n < aBoxes.Count() &&
+ !pCalcPara->rCalc.IsCalcError(); ++n )
+ {
+ const SwTableBox* pTblBox = aBoxes[n];
+ if ( pTblBox->getRowSpan() >= 1 )
+ {
+ if( bDelim )
+ rNewStr += cListDelim;
+ bDelim = true;
+ rNewStr += pCalcPara->rCalc.GetStrResult(
+ pTblBox->GetValue( *pCalcPara ), sal_False );
+ }
+ }
+ rNewStr += ')';
+ }
+ else if( pSttBox && !pLastBox ) // nur die StartBox ?
+ {
+ //JP 12.01.99: und keine EndBox in der Formel!
+ // Berechne den Wert der Box
+ if ( pSttBox->getRowSpan() >= 1 )
+ {
+ rNewStr += pCalcPara->rCalc.GetStrResult(
+ pSttBox->GetValue( *pCalcPara ), sal_False );
+ }
+ }
+ else
+ pCalcPara->rCalc.SetCalcError( CALC_SYNTAX ); // Fehler setzen
+ rNewStr += ' ';
+}
+
+void SwTableFormula::RelNmsToBoxNms( const SwTable& rTbl, String& rNewStr,
+ String& rFirstBox, String* pLastBox, void* pPara ) const
+{
+ // relativen Namen zu Box-Namen (externe Darstellung)
+ SwNode* pNd = (SwNode*)pPara;
+ OSL_ENSURE( pNd, "Feld steht in keinem TextNode" );
+ const SwTableBox *pRelBox, *pBox = (SwTableBox *)rTbl.GetTblBox(
+ pNd->FindTableBoxStartNode()->GetIndex() );
+
+ rNewStr += rFirstBox.Copy(0,1); // Kennung fuer Box erhalten
+ rFirstBox.Erase(0,1);
+ if( pLastBox )
+ {
+ if( 0 != ( pRelBox = lcl_RelToBox( rTbl, pBox, *pLastBox )) )
+ rNewStr += pRelBox->GetName();
+ else
+ rNewStr.AppendAscii("A1");
+ rNewStr += ':';
+ rFirstBox.Erase( 0, pLastBox->Len()+1 );
+ }
+
+ if( 0 != ( pRelBox = lcl_RelToBox( rTbl, pBox, rFirstBox )) )
+ rNewStr += pRelBox->GetName();
+ else
+ rNewStr.AppendAscii("A1");
+
+ // Kennung fuer Box erhalten
+ rNewStr += rFirstBox.GetChar( rFirstBox.Len() - 1 );
+}
+
+void SwTableFormula::RelBoxNmsToPtr( const SwTable& rTbl, String& rNewStr,
+ String& rFirstBox, String* pLastBox, void* pPara ) const
+{
+ // relativen Namen zu Box-Pointern (interne Darstellung)
+ SwNode* pNd = (SwNode*)pPara;
+ OSL_ENSURE( pNd, "Feld steht in keinem Node" );
+ const SwTableBox *pRelBox, *pBox = (SwTableBox*)rTbl.GetTblBox(
+ pNd->FindTableBoxStartNode()->GetIndex() );
+
+ rNewStr += rFirstBox.Copy(0,1); // Kennung fuer Box erhalten
+ rFirstBox.Erase(0,1);
+ if( pLastBox )
+ {
+ if( 0 != ( pRelBox = lcl_RelToBox( rTbl, pBox, *pLastBox )) )
+ rNewStr += String::CreateFromInt64( (sal_PtrDiff)pRelBox );
+ else
+ rNewStr += '0';
+ rNewStr += ':';
+ rFirstBox.Erase( 0, pLastBox->Len()+1 );
+ }
+
+ if( 0 != ( pRelBox = lcl_RelToBox( rTbl, pBox, rFirstBox )) )
+ rNewStr += String::CreateFromInt64( (sal_PtrDiff)pRelBox );
+ else
+ rNewStr += '0';
+
+ // Kennung fuer Box erhalten
+ rNewStr += rFirstBox.GetChar( rFirstBox.Len() - 1 );
+}
+
+
+void SwTableFormula::BoxNmsToRelNm( const SwTable& rTbl, String& rNewStr,
+ String& rFirstBox, String* pLastBox, void* pPara ) const
+{
+ // Box-Namen (externe Darstellung) zu relativen Namen
+ SwNode* pNd = (SwNode*)pPara;
+ OSL_ENSURE( pNd, "Feld steht in keinem Node" );
+ const SwTableNode* pTblNd = pNd->FindTableNode();
+
+ String sRefBoxNm;
+ if( &pTblNd->GetTable() == &rTbl )
+ {
+ const SwTableBox *pBox = rTbl.GetTblBox(
+ pNd->FindTableBoxStartNode()->GetIndex() );
+ OSL_ENSURE( pBox, "Feld steht in keiner Tabelle" );
+ sRefBoxNm = pBox->GetName();
+ }
+
+ rNewStr += rFirstBox.Copy(0,1); // Kennung fuer Box erhalten
+ rFirstBox.Erase(0,1);
+ if( pLastBox )
+ {
+ rNewStr += lcl_BoxNmToRel( rTbl, *pTblNd, sRefBoxNm, *pLastBox,
+ eNmType == EXTRNL_NAME );
+ rNewStr += ':';
+ rFirstBox.Erase( 0, pLastBox->Len()+1 );
+ }
+
+ rNewStr += lcl_BoxNmToRel( rTbl, *pTblNd, sRefBoxNm, rFirstBox,
+ eNmType == EXTRNL_NAME );
+
+ // Kennung fuer Box erhalten
+ rNewStr += rFirstBox.GetChar( rFirstBox.Len() - 1 );
+}
+
+
+void SwTableFormula::PtrToBoxNms( const SwTable& rTbl, String& rNewStr,
+ String& rFirstBox, String* pLastBox, void* ) const
+{
+ // ein Bereich in dieser Klammer ?
+ SwTableBox* pBox;
+
+ rNewStr += rFirstBox.Copy(0,1); // Kennung fuer Box erhalten
+ rFirstBox.Erase(0,1);
+ if( pLastBox )
+ {
+ pBox = reinterpret_cast<SwTableBox*>(sal::static_int_cast<sal_IntPtr>(pLastBox->ToInt64()));
+
+ // ist das ueberhaupt ein gueltiger Pointer ??
+ if( rTbl.GetTabSortBoxes().Seek_Entry( pBox ))
+ rNewStr += pBox->GetName();
+ else
+ rNewStr += '?';
+ rNewStr += ':';
+ rFirstBox.Erase( 0, pLastBox->Len()+1 );
+ }
+
+ pBox = reinterpret_cast<SwTableBox*>(sal::static_int_cast<sal_IntPtr>(rFirstBox.ToInt64()));
+ // ist das ueberhaupt ein gueltiger Pointer ??
+ if( rTbl.GetTabSortBoxes().Seek_Entry( pBox ))
+ rNewStr += pBox->GetName();
+ else
+ rNewStr += '?';
+
+ // Kennung fuer Box erhalten
+ rNewStr += rFirstBox.GetChar( rFirstBox.Len() - 1 );
+}
+
+void SwTableFormula::BoxNmsToPtr( const SwTable& rTbl, String& rNewStr,
+ String& rFirstBox, String* pLastBox, void* ) const
+{
+ // ein Bereich in dieser Klammer ?
+ const SwTableBox* pBox;
+
+ rNewStr += rFirstBox.Copy(0,1); // Kennung fuer Box erhalten
+ rFirstBox.Erase(0,1);
+ if( pLastBox )
+ {
+ pBox = rTbl.GetTblBox( *pLastBox );
+ rNewStr += String::CreateFromInt64( (sal_PtrDiff)pBox );
+ rNewStr += ':';
+ rFirstBox.Erase( 0, pLastBox->Len()+1 );
+ }
+
+ pBox = rTbl.GetTblBox( rFirstBox );
+ rNewStr += String::CreateFromInt64( (sal_PtrDiff)pBox );
+
+ // Kennung fuer Box erhalten
+ rNewStr += rFirstBox.GetChar( rFirstBox.Len() - 1 );
+}
+
+ // erzeuge die externe (fuer UI) Formel
+void SwTableFormula::PtrToBoxNm( const SwTable* pTbl )
+{
+ const SwNode* pNd = 0;
+ FnScanFormel fnFormel = 0;
+ switch( eNmType)
+ {
+ case INTRNL_NAME:
+ if( pTbl )
+ fnFormel = &SwTableFormula::PtrToBoxNms;
+ break;
+ case REL_NAME:
+ if( pTbl )
+ {
+ fnFormel = &SwTableFormula::RelNmsToBoxNms;
+ pNd = GetNodeOfFormula();
+ }
+ break;
+ case EXTRNL_NAME:
+ return;
+ }
+ sFormel = ScanString( fnFormel, *pTbl, (void*)pNd );
+ eNmType = EXTRNL_NAME;
+}
+
+ // erzeuge die interne (in CORE) Formel
+void SwTableFormula::BoxNmToPtr( const SwTable* pTbl )
+{
+ const SwNode* pNd = 0;
+ FnScanFormel fnFormel = 0;
+ switch( eNmType)
+ {
+ case EXTRNL_NAME:
+ if( pTbl )
+ fnFormel = &SwTableFormula::BoxNmsToPtr;
+ break;
+ case REL_NAME:
+ if( pTbl )
+ {
+ fnFormel = &SwTableFormula::RelBoxNmsToPtr;
+ pNd = GetNodeOfFormula();
+ }
+ break;
+ case INTRNL_NAME:
+ return;
+ }
+ sFormel = ScanString( fnFormel, *pTbl, (void*)pNd );
+ eNmType = INTRNL_NAME;
+}
+
+ // erzeuge die relative (fuers Kopieren) Formel
+void SwTableFormula::ToRelBoxNm( const SwTable* pTbl )
+{
+ const SwNode* pNd = 0;
+ FnScanFormel fnFormel = 0;
+ switch( eNmType)
+ {
+ case INTRNL_NAME:
+ case EXTRNL_NAME:
+ if( pTbl )
+ {
+ fnFormel = &SwTableFormula::BoxNmsToRelNm;
+ pNd = GetNodeOfFormula();
+ }
+ break;
+ case REL_NAME:
+ return;
+ }
+ sFormel = ScanString( fnFormel, *pTbl, (void*)pNd );
+ eNmType = REL_NAME;
+}
+
+
+String SwTableFormula::ScanString( FnScanFormel fnFormel, const SwTable& rTbl,
+ void* pPara ) const
+{
+ String aStr;
+ sal_uInt16 nFml = 0, nStt = 0, nEnd = 0, nTrenner;
+
+ do {
+ // falls der Formel ein Name vorangestellt ist, diese Tabelle
+ // benutzen !!
+ const SwTable* pTbl = &rTbl;
+
+ nStt = sFormel.Search( '<', nFml );
+ if( STRING_NOTFOUND != nStt )
+ {
+ while( STRING_NOTFOUND != nStt &&
+ ( ' ' == sFormel.GetChar( nStt + 1 ) ||
+ '=' == sFormel.GetChar( nStt + 1 ) ) )
+ nStt = sFormel.Search( '<', nStt + 1 );
+
+ if( STRING_NOTFOUND != nStt )
+ nEnd = sFormel.Search( '>', nStt+1 );
+ }
+ if( STRING_NOTFOUND == nStt || STRING_NOTFOUND == nEnd )
+ {
+ // den Rest setzen und beenden
+ aStr.Insert( sFormel, nFml, sFormel.Len() - nFml );
+ break;
+ }
+ aStr.Insert( sFormel, nFml, nStt - nFml ); // Anfang schreiben
+
+ if( fnFormel != NULL )
+ {
+ // ist ein TabellenName vorangestellt ??
+ // JP 16.02.99: SplitMergeBoxNm behandeln den Namen selbst
+ // JP 22.02.99: der CAST muss fuer den Linux-Compiler sein
+ // JP 28.06.99: rel. BoxName have no preceding tablename!
+ if( fnFormel != (FnScanFormel)&SwTableFormula::_SplitMergeBoxNm &&
+ 1 < sFormel.Len() && cRelKennung != sFormel.GetChar( 1 ) &&
+ STRING_NOTFOUND != ( nTrenner = sFormel.Search( '.', nStt ))
+ && nTrenner < nEnd )
+ {
+ String sTblNm( sFormel.Copy( nStt, nEnd - nStt ));
+
+ // falls im Namen schon die Punkte enthalten sind,
+ // treten diese immer paarig auf!!! (A1.1.1 !!)
+ if( (sTblNm.GetTokenCount( '.' ) - 1 ) & 1 )
+ {
+ sTblNm.Erase( nTrenner - nStt );
+
+ // beim Bauen der Formel ist der TabellenName unerwuenscht
+ //JP 22.02.99: der CAST muss fuer den Linux-Compiler sein
+ if( fnFormel != (FnScanFormel)&SwTableFormula::_MakeFormel )
+ aStr += sTblNm;
+ nStt = nTrenner;
+
+ sTblNm.Erase( 0, 1 ); // Trenner loeschen
+ if( sTblNm != rTbl.GetFrmFmt()->GetName() )
+ {
+ // dann suchen wir uns mal unsere Tabelle:
+ const SwTable* pFnd = FindTable(
+ *rTbl.GetFrmFmt()->GetDoc(),
+ sTblNm );
+ if( pFnd )
+ pTbl = pFnd;
+ // ??
+ OSL_ENSURE( pFnd, "Tabelle nicht gefunden, was nun?" );
+ }
+ }
+ }
+
+ String sBox( sFormel.Copy( nStt, nEnd - nStt + 1 ));
+ // ein Bereich in dieser Klammer ?
+ if( STRING_NOTFOUND != ( nTrenner = sFormel.Search( ':', nStt ))
+ && nTrenner < nEnd )
+ {
+ // ohne die Anfangsklammer
+ String aFirstBox( sFormel.Copy( nStt+1, nTrenner - nStt - 1 ));
+ (this->*fnFormel)( *pTbl, aStr, sBox, &aFirstBox, pPara );
+ }
+ else
+ (this->*fnFormel)( *pTbl, aStr, sBox, 0, pPara );
+ }
+
+ nFml = nEnd+1;
+ } while( sal_True );
+ return aStr;
+}
+
+const SwTable* SwTableFormula::FindTable( SwDoc& rDoc, const String& rNm ) const
+{
+ const SwFrmFmts& rTblFmts = *rDoc.GetTblFrmFmts();
+ const SwTable* pTmpTbl, *pRet = 0;
+ for( sal_uInt16 nFmtCnt = rTblFmts.Count(); nFmtCnt; )
+ {
+ SwFrmFmt* pFmt = rTblFmts[ --nFmtCnt ];
+ // falls wir von Sw3Writer gerufen werden, dann ist dem
+ // FormatNamen eine Nummer anhaengig
+ SwTableBox* pFBox;
+ if( COMPARE_EQUAL == rNm.CompareTo( pFmt->GetName(),
+ pFmt->GetName().Search( 0x0a ) ) &&
+ 0 != ( pTmpTbl = SwTable::FindTable( pFmt ) ) &&
+ 0 != (pFBox = pTmpTbl->GetTabSortBoxes()[0] ) &&
+ pFBox->GetSttNd() &&
+ pFBox->GetSttNd()->GetNodes().IsDocNodes() )
+ {
+ // eine Tabelle im normalen NodesArr
+ pRet = pTmpTbl;
+ break;
+ }
+ }
+ return pRet;
+}
+
+const SwFrm* lcl_GetBoxFrm( const SwTableBox& rBox )
+{
+ SwNodeIndex aIdx( *rBox.GetSttNd() );
+ SwCntntNode* pCNd = aIdx.GetNodes().GoNext( &aIdx );
+ OSL_ENSURE( pCNd, "Box hat keinen TextNode" );
+ Point aPt; // den im Layout 1. Frame returnen - Tab.Kopfzeile !!
+ return pCNd->getLayoutFrm( pCNd->GetDoc()->GetCurrentLayout(), &aPt, NULL, sal_False );
+}
+
+long lcl_GetLongBoxNum( String& rStr )
+{
+ sal_uInt16 nPos;
+ long nRet;
+ if( STRING_NOTFOUND == ( nPos = rStr.Search( cRelTrenner ) ))
+ {
+ nRet = rStr.ToInt32();
+ rStr.Erase();
+ }
+ else
+ {
+ nRet = rStr.Copy( 0, nPos ).ToInt32();
+ rStr.Erase( 0, nPos+1 );
+ }
+ return nRet;
+}
+
+const SwTableBox* lcl_RelToBox( const SwTable& rTbl,
+ const SwTableBox* pRefBox,
+ const String& rGetName )
+{
+ // hole die Line
+ const SwTableBox* pBox = 0;
+ String sGetName( rGetName );
+
+ // ist es denn wirklich eine relative Angabe??
+ if( cRelKennung == sGetName.GetChar(0) ) // ja, ...
+ {
+ if( !pRefBox )
+ return 0;
+
+ sGetName.Erase( 0, 1 );
+
+ const SwTableLines* pLines = (SwTableLines*)&rTbl.GetTabLines();
+ const SwTableBoxes* pBoxes;
+ const SwTableLine* pLine;
+
+ // bestimme erst mal die Start-Werte der Box:
+ pBox = (SwTableBox*)pRefBox;
+ pLine = pBox->GetUpper();
+ while( pLine->GetUpper() )
+ {
+ pBox = pLine->GetUpper();
+ pLine = pBox->GetUpper();
+ }
+ sal_uInt16 nSttBox = pLine->GetTabBoxes().GetPos( pBox );
+ sal_uInt16 nSttLine = rTbl.GetTabLines().GetPos( pLine );
+
+ long nBoxOffset = lcl_GetLongBoxNum( sGetName ) + nSttBox;
+ long nLineOffset = lcl_GetLongBoxNum( sGetName ) + nSttLine;
+
+ if( nBoxOffset < 0 || nBoxOffset >= USHRT_MAX ||
+ nLineOffset < 0 || nLineOffset >= USHRT_MAX )
+ return 0;
+
+ if( nLineOffset >= long(pLines->Count()) )
+ return 0;
+
+ pLine = (*pLines)[ sal_uInt16(nLineOffset) ];
+
+ // dann suche die Box
+ pBoxes = &pLine->GetTabBoxes();
+ if( nBoxOffset >= long(pBoxes->Count()) )
+ return 0;
+ pBox = (*pBoxes)[ sal_uInt16(nBoxOffset) ];
+
+ while( sGetName.Len() )
+ {
+ nSttBox = SwTable::_GetBoxNum( sGetName );
+ pLines = &pBox->GetTabLines();
+ if( nSttBox )
+ --nSttBox;
+
+ nSttLine = SwTable::_GetBoxNum( sGetName );
+
+ // bestimme die Line
+ if( !nSttLine || nSttLine > pLines->Count() )
+ break;
+ pLine = (*pLines)[ nSttLine-1 ];
+
+ // bestimme die Box
+ pBoxes = &pLine->GetTabBoxes();
+ if( nSttBox >= pBoxes->Count() )
+ break;
+ pBox = (*pBoxes)[ nSttBox ];
+ }
+
+ if( pBox )
+ {
+ if( !pBox->GetSttNd() )
+ // "herunterfallen lassen" bis zur ersten Box
+ while( pBox->GetTabLines().Count() )
+ pBox = pBox->GetTabLines()[0]->GetTabBoxes()[0];
+ }
+ }
+ else
+ {
+ // sonst ist es eine absolute externe Darstellung:
+ pBox = rTbl.GetTblBox( sGetName );
+ }
+ return pBox;
+}
+
+String lcl_BoxNmToRel( const SwTable& rTbl, const SwTableNode& rTblNd,
+ const String& rRefBoxNm, const String& rGetStr,
+ bool bExtrnlNm )
+{
+ String sCpy( rRefBoxNm );
+ String sTmp( rGetStr );
+ if( !bExtrnlNm )
+ {
+ // in die Externe Darstellung umwandeln.
+ SwTableBox* pBox = reinterpret_cast<SwTableBox*>(sal::static_int_cast<sal_IntPtr>(sTmp.ToInt64()));
+ if( !rTbl.GetTabSortBoxes().Seek_Entry( pBox ))
+ return '?';
+ sTmp = pBox->GetName();
+ }
+
+ // sollte die es eine Tabellen uebergreifende Formel sein, dann behalte
+ // die externe Darstellung bei:
+ if( &rTbl == &rTblNd.GetTable() )
+ {
+ long nBox = SwTable::_GetBoxNum( sTmp, sal_True );
+ nBox -= SwTable::_GetBoxNum( sCpy, sal_True );
+ long nLine = SwTable::_GetBoxNum( sTmp );
+ nLine -= SwTable::_GetBoxNum( sCpy );
+
+ sCpy = sTmp; //JP 01.11.95: den Rest aus dem BoxNamen anhaengen
+
+ sTmp = cRelKennung;
+ sTmp += String::CreateFromInt32( nBox );
+ sTmp += cRelTrenner;
+ sTmp += String::CreateFromInt32( nLine );
+
+ if( sCpy.Len() )
+ {
+ sTmp += cRelTrenner;
+ sTmp += sCpy;
+ }
+ }
+
+ if( sTmp.Len() && '>' == sTmp.GetChar( sTmp.Len() - 1 ))
+ sTmp.Erase( sTmp.Len()-1 );
+
+ return sTmp;
+}
+
+sal_uInt16 SwTableFormula::GetBoxesOfFormula( const SwTable& rTbl,
+ SwSelBoxes& rBoxes )
+{
+ if( rBoxes.Count() )
+ rBoxes.Remove( sal_uInt16(0), rBoxes.Count() );
+
+ BoxNmToPtr( &rTbl );
+ ScanString( &SwTableFormula::_GetFmlBoxes, rTbl, &rBoxes );
+ return rBoxes.Count();
+}
+
+void SwTableFormula::_GetFmlBoxes( const SwTable& rTbl, String& ,
+ String& rFirstBox, String* pLastBox, void* pPara ) const
+{
+ SwSelBoxes* pBoxes = (SwSelBoxes*)pPara;
+ SwTableBox* pSttBox, *pEndBox = 0;
+
+ rFirstBox.Erase(0,1); // Kennung fuer Box loeschen
+ // ein Bereich in dieser Klammer ?
+ if( pLastBox )
+ {
+ pEndBox = reinterpret_cast<SwTableBox*>(sal::static_int_cast<sal_IntPtr>(pLastBox->ToInt64()));
+
+ // ist das ueberhaupt ein gueltiger Pointer ??
+ if( !rTbl.GetTabSortBoxes().Seek_Entry( pEndBox ))
+ pEndBox = 0;
+ rFirstBox.Erase( 0, pLastBox->Len()+1 );
+ }
+
+ pSttBox = reinterpret_cast<SwTableBox*>(sal::static_int_cast<sal_IntPtr>(rFirstBox.ToInt64()));
+ // ist das ueberhaupt ein gueltiger Pointer ??
+ if( !rTbl.GetTabSortBoxes().Seek_Entry( pSttBox ))
+ pSttBox = 0;
+
+ if( pEndBox && pSttBox ) // Bereich ?
+ {
+ // ueber das Layout alle "selectierten" Boxen und berechne
+ // deren Werte
+ SwSelBoxes aBoxes;
+ GetBoxes( *pSttBox, *pEndBox, aBoxes );
+ pBoxes->Insert( &aBoxes );
+ }
+ else if( pSttBox ) // nur die StartBox ?
+ pBoxes->Insert( pSttBox );
+}
+
+void SwTableFormula::GetBoxes( const SwTableBox& rSttBox,
+ const SwTableBox& rEndBox,
+ SwSelBoxes& rBoxes ) const
+{
+ // hole ueber das Layout alle "selektierten" Boxen
+ const SwLayoutFrm *pStt, *pEnd;
+ const SwFrm* pFrm = lcl_GetBoxFrm( rSttBox );
+ pStt = pFrm ? pFrm->GetUpper() : 0;
+ pEnd = ( 0 != (pFrm = lcl_GetBoxFrm( rEndBox ))) ? pFrm->GetUpper() : 0;
+ if( !pStt || !pEnd )
+ return ; // no valid selection
+
+ GetTblSel( pStt, pEnd, rBoxes, 0 );
+
+ const SwTable* pTbl = pStt->FindTabFrm()->GetTable();
+
+ // filter die Kopfzeilen-Boxen heraus:
+ if( pTbl->GetRowsToRepeat() > 0 )
+ {
+ do { // middle-check loop
+ const SwTableLine* pLine = rSttBox.GetUpper();
+ while( pLine->GetUpper() )
+ pLine = pLine->GetUpper()->GetUpper();
+
+ if( pTbl->IsHeadline( *pLine ) )
+ break; // Headline mit im Bereich !
+
+ // vielleicht ist ja Start und Ende vertauscht
+ pLine = rEndBox.GetUpper();
+ while ( pLine->GetUpper() )
+ pLine = pLine->GetUpper()->GetUpper();
+
+ if( pTbl->IsHeadline( *pLine ) )
+ break; // Headline mit im Bereich !
+
+ const SwTabFrm *pTable = pStt->FindTabFrm();
+ const SwTabFrm *pEndTable = pEnd->FindTabFrm();
+
+ if( pTable == pEndTable ) // keine gespl. Tabelle
+ break;
+
+ // dann mal die Tabellenkoepfe raus:
+ for( sal_uInt16 n = 0; n < rBoxes.Count(); ++n )
+ {
+ pLine = rBoxes[n]->GetUpper();
+ while( pLine->GetUpper() )
+ pLine = pLine->GetUpper()->GetUpper();
+
+ if( pTbl->IsHeadline( *pLine ) )
+ rBoxes.Remove( n--, 1 );
+ }
+ } while( sal_False );
+ }
+}
+
+ // sind alle Boxen gueltig, auf die sich die Formel bezieht?
+void SwTableFormula::_HasValidBoxes( const SwTable& rTbl, String& ,
+ String& rFirstBox, String* pLastBox, void* pPara ) const
+{
+ bool* pBValid = (bool*)pPara;
+ if( *pBValid ) // einmal falsch, immer falsch
+ {
+ SwTableBox* pSttBox = 0, *pEndBox = 0;
+ rFirstBox.Erase(0,1); // Kennung fuer Box loeschen
+
+ // ein Bereich in dieser Klammer ?
+ if( pLastBox )
+ rFirstBox.Erase( 0, pLastBox->Len()+1 );
+
+ switch( eNmType)
+ {
+ case INTRNL_NAME:
+ if( pLastBox )
+ pEndBox = reinterpret_cast<SwTableBox*>(sal::static_int_cast<sal_IntPtr>(pLastBox->ToInt64()));
+ pSttBox = reinterpret_cast<SwTableBox*>(sal::static_int_cast<sal_IntPtr>(rFirstBox.ToInt64()));
+ break;
+
+ case REL_NAME:
+ {
+ const SwNode* pNd = GetNodeOfFormula();
+ const SwTableBox* pBox = !pNd ? 0
+ : (SwTableBox *)rTbl.GetTblBox(
+ pNd->FindTableBoxStartNode()->GetIndex() );
+ if( pLastBox )
+ pEndBox = (SwTableBox*)lcl_RelToBox( rTbl, pBox, *pLastBox );
+ pSttBox = (SwTableBox*)lcl_RelToBox( rTbl, pBox, rFirstBox );
+ }
+ break;
+
+ case EXTRNL_NAME:
+ if( pLastBox )
+ pEndBox = (SwTableBox*)rTbl.GetTblBox( *pLastBox );
+ pSttBox = (SwTableBox*)rTbl.GetTblBox( rFirstBox );
+ break;
+ }
+
+ // sind das gueltige Pointer ?
+ if( ( pLastBox &&
+ ( !pEndBox || !rTbl.GetTabSortBoxes().Seek_Entry( pEndBox ) ) ) ||
+ ( !pSttBox || !rTbl.GetTabSortBoxes().Seek_Entry( pSttBox ) ) )
+ *pBValid = false;
+ }
+}
+
+bool SwTableFormula::HasValidBoxes() const
+{
+ bool bRet = true;
+ const SwNode* pNd = GetNodeOfFormula();
+ if( pNd && 0 != ( pNd = pNd->FindTableNode() ) )
+ ScanString( &SwTableFormula::_HasValidBoxes,
+ ((SwTableNode*)pNd)->GetTable(), &bRet );
+ return bRet;
+}
+
+
+sal_uInt16 SwTableFormula::GetLnPosInTbl( const SwTable& rTbl, const SwTableBox* pBox )
+{
+ sal_uInt16 nRet = USHRT_MAX;
+ if( pBox )
+ {
+ const SwTableLine* pLn = pBox->GetUpper();
+ while( pLn->GetUpper() )
+ pLn = pLn->GetUpper()->GetUpper();
+ nRet = rTbl.GetTabLines().GetPos( pLn );
+ }
+ return nRet;
+}
+
+void SwTableFormula::_SplitMergeBoxNm( const SwTable& rTbl, String& rNewStr,
+ String& rFirstBox, String* pLastBox, void* pPara ) const
+{
+ SwTableFmlUpdate& rTblUpd = *(SwTableFmlUpdate*)pPara;
+
+ rNewStr += rFirstBox.Copy(0,1); // Kennung fuer Box erhalten
+ rFirstBox.Erase(0,1);
+
+ String sTblNm;
+ const SwTable* pTbl = &rTbl;
+
+ String* pTblNmBox = pLastBox ? pLastBox : &rFirstBox;
+
+ sal_uInt16 nLastBoxLen = pTblNmBox->Len();
+ sal_uInt16 nTrenner = pTblNmBox->Search( '.' );
+ if( STRING_NOTFOUND != nTrenner &&
+ // falls im Namen schon die Punkte enthalten sind,
+ // treten diese immer paarig auf!!! (A1.1.1 !!)
+ (pTblNmBox->GetTokenCount( '.' ) - 1 ) & 1 )
+ {
+ sTblNm = pTblNmBox->Copy( 0, nTrenner );
+ pTblNmBox->Erase( 0, nTrenner + 1);// den Punkt entfernen
+ const SwTable* pFnd = FindTable( *rTbl.GetFrmFmt()->GetDoc(), sTblNm );
+ if( pFnd )
+ pTbl = pFnd;
+
+ if( TBL_MERGETBL == rTblUpd.eFlags )
+ {
+ if( pFnd )
+ {
+ if( pFnd == rTblUpd.DATA.pDelTbl )
+ {
+ if( rTblUpd.pTbl != &rTbl ) // es ist nicht die akt.
+ (rNewStr += rTblUpd.pTbl->GetFrmFmt()->GetName() )
+ += '.'; // den neuen Tabellen Namen setzen
+ rTblUpd.bModified = sal_True;
+ }
+ else if( pFnd != rTblUpd.pTbl ||
+ ( rTblUpd.pTbl != &rTbl && &rTbl != rTblUpd.DATA.pDelTbl))
+ (rNewStr += sTblNm ) += '.'; // den Tabellen Namen behalten
+ else
+ rTblUpd.bModified = sal_True;
+ }
+ else
+ (rNewStr += sTblNm ) += '.'; // den Tabellen Namen behalten
+
+ }
+ }
+ if( pTblNmBox == pLastBox )
+ rFirstBox.Erase( 0, nLastBoxLen + 1 );
+
+ SwTableBox* pSttBox = 0, *pEndBox = 0;
+ switch( eNmType )
+ {
+ case INTRNL_NAME:
+ if( pLastBox )
+ pEndBox = reinterpret_cast<SwTableBox*>(sal::static_int_cast<sal_IntPtr>(pLastBox->ToInt64()));
+ pSttBox = reinterpret_cast<SwTableBox*>(sal::static_int_cast<sal_IntPtr>(rFirstBox.ToInt64()));
+ break;
+
+ case REL_NAME:
+ {
+ const SwNode* pNd = GetNodeOfFormula();
+ const SwTableBox* pBox = pNd ? pTbl->GetTblBox(
+ pNd->FindTableBoxStartNode()->GetIndex() ) : 0;
+ if( pLastBox )
+ pEndBox = (SwTableBox*)lcl_RelToBox( *pTbl, pBox, *pLastBox );
+ pSttBox = (SwTableBox*)lcl_RelToBox( *pTbl, pBox, rFirstBox );
+ }
+ break;
+
+ case EXTRNL_NAME:
+ if( pLastBox )
+ pEndBox = (SwTableBox*)pTbl->GetTblBox( *pLastBox );
+ pSttBox = (SwTableBox*)pTbl->GetTblBox( rFirstBox );
+ break;
+ }
+
+ if( pLastBox && !pTbl->GetTabSortBoxes().Seek_Entry( pEndBox ))
+ pEndBox = 0;
+ if( !pTbl->GetTabSortBoxes().Seek_Entry( pSttBox ))
+ pSttBox = 0;
+
+ if( TBL_SPLITTBL == rTblUpd.eFlags )
+ {
+ // wo liegen die Boxen, in der "alten" oder in der neuen Tabelle?
+ bool bInNewTbl = false;
+ if( pLastBox )
+ {
+ // das ist die "erste" Box in der Selektion. Die bestimmt ob die
+ // Formel in der alten oder neuen Tabelle steht.
+ sal_uInt16 nEndLnPos = SwTableFormula::GetLnPosInTbl( *pTbl, pEndBox ),
+ nSttLnPos = SwTableFormula::GetLnPosInTbl( *pTbl, pSttBox );
+
+ if( USHRT_MAX != nSttLnPos && USHRT_MAX != nEndLnPos &&
+ ((rTblUpd.nSplitLine <= nSttLnPos) ==
+ (rTblUpd.nSplitLine <= nEndLnPos)) )
+ {
+ // bleiben in der gleichen Tabelle
+ bInNewTbl = rTblUpd.nSplitLine <= nEndLnPos &&
+ pTbl == rTblUpd.pTbl;
+ }
+ else
+ {
+ // das ist aufjedenfall eine ungueltige Formel, also fuers
+ // Undo auf Modified setzen
+ rTblUpd.bModified = sal_True;
+ if( pEndBox )
+ bInNewTbl = USHRT_MAX != nEndLnPos &&
+ rTblUpd.nSplitLine <= nEndLnPos &&
+ pTbl == rTblUpd.pTbl;
+ }
+ }
+ else
+ {
+ sal_uInt16 nSttLnPos = SwTableFormula::GetLnPosInTbl( *pTbl, pSttBox );
+ // dann landet das Teil in der neuen Tabelle?
+ bInNewTbl = USHRT_MAX != nSttLnPos &&
+ rTblUpd.nSplitLine <= nSttLnPos &&
+ pTbl == rTblUpd.pTbl;
+ }
+
+ // wenn die Formel selbst in der neuen Tabellen landet
+ if( rTblUpd.bBehindSplitLine )
+ {
+ if( !bInNewTbl )
+ {
+ rTblUpd.bModified = sal_True;
+ ( rNewStr += rTblUpd.pTbl->GetFrmFmt()->GetName() ) += '.';
+ }
+ else if( sTblNm.Len() )
+ ( rNewStr += sTblNm ) += '.';
+ }
+ else if( bInNewTbl )
+ {
+ rTblUpd.bModified = sal_True;
+ ( rNewStr += *rTblUpd.DATA.pNewTblNm ) += '.';
+ }
+ else if( sTblNm.Len() )
+ ( rNewStr += sTblNm ) += '.';
+ }
+
+ if( pLastBox )
+ ( rNewStr += String::CreateFromInt64((sal_PtrDiff)pEndBox)) += ':';
+ ( rNewStr += String::CreateFromInt64((sal_PtrDiff)pSttBox))
+ += rFirstBox.GetChar( rFirstBox.Len() - 1 );
+}
+
+ // erzeuge die externe Formel, beachte aber das die Formel
+ // in einer gesplitteten/gemergten Tabelle landet
+void SwTableFormula::ToSplitMergeBoxNm( SwTableFmlUpdate& rTblUpd )
+{
+ const SwTable* pTbl;
+ const SwNode* pNd = GetNodeOfFormula();
+ if( pNd && 0 != ( pNd = pNd->FindTableNode() ))
+ pTbl = &((SwTableNode*)pNd)->GetTable();
+ else
+ pTbl = rTblUpd.pTbl;
+
+ sFormel = ScanString( &SwTableFormula::_SplitMergeBoxNm, *pTbl, (void*)&rTblUpd );
+ eNmType = INTRNL_NAME;
+}
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/fields/chpfld.cxx b/sw/source/core/fields/chpfld.cxx
new file mode 100644
index 000000000000..0fc69d1c244c
--- /dev/null
+++ b/sw/source/core/fields/chpfld.cxx
@@ -0,0 +1,280 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+
+#include <com/sun/star/text/ChapterFormat.hpp>
+#include <doc.hxx>
+#include <frame.hxx> // SwChapterFieldType::ChangeExpansion()
+#include <pam.hxx> // fuer GetBodyTxtNode
+#include <ndtxt.hxx>
+#include <chpfld.hxx>
+#include <expfld.hxx> // fuer GetBodyTxtNode
+#include <unofldmid.h>
+#include <numrule.hxx>
+
+using namespace ::com::sun::star;
+
+/*--------------------------------------------------------------------
+ Beschreibung: SwChapterFieldType
+ --------------------------------------------------------------------*/
+
+
+SwChapterFieldType::SwChapterFieldType()
+ : SwFieldType( RES_CHAPTERFLD )
+{
+}
+
+
+SwFieldType* SwChapterFieldType::Copy() const
+{
+ return new SwChapterFieldType();
+}
+
+
+/*--------------------------------------------------------------------
+ Beschreibung: Kapittelfeld
+ --------------------------------------------------------------------*/
+
+
+SwChapterField::SwChapterField(SwChapterFieldType* pTyp, sal_uInt32 nFmt)
+ : SwField(pTyp, nFmt), nLevel( 0 )
+{}
+
+
+String SwChapterField::Expand() const
+{
+ String sStr( sNumber );
+ switch( GetFormat() )
+ {
+ case CF_TITLE: sStr = sTitle; break;
+
+ case CF_NUMBER:
+ case CF_NUM_TITLE: sStr.Insert( sPre, 0 );
+ sStr += sPost;
+ if( CF_NUM_TITLE == GetFormat() )
+ sStr += sTitle;
+ break;
+
+ case CF_NUM_NOPREPST_TITLE: sStr += sTitle; break;
+ }
+ return sStr;
+}
+
+
+SwField* SwChapterField::Copy() const
+{
+ SwChapterField *pTmp =
+ new SwChapterField((SwChapterFieldType*)GetTyp(), GetFormat());
+ pTmp->nLevel = nLevel;
+ pTmp->sTitle = sTitle;
+ pTmp->sNumber = sNumber;
+ pTmp->sPost = sPost;
+ pTmp->sPre = sPre;
+
+ return pTmp;
+}
+
+// #i53420#
+void SwChapterField::ChangeExpansion(const SwFrm* pFrm,
+ const SwCntntNode* pCntntNode,
+ sal_Bool bSrchNum )
+{
+ OSL_ENSURE( pFrm, "in welchem Frame stehe ich denn?" );
+ SwDoc* pDoc = (SwDoc*)pCntntNode->GetDoc();
+
+ const SwTxtNode* pTxtNode = dynamic_cast<const SwTxtNode*>(pCntntNode);
+ if ( !pTxtNode || !pFrm->IsInDocBody() )
+ {
+ SwPosition aDummyPos( pDoc->GetNodes().GetEndOfContent() );
+ pTxtNode = GetBodyTxtNode( *pDoc, aDummyPos, *pFrm );
+ }
+
+ if ( pTxtNode )
+ {
+ ChangeExpansion( *pTxtNode, bSrchNum );
+ }
+}
+
+void SwChapterField::ChangeExpansion(const SwTxtNode &rTxtNd, sal_Bool bSrchNum)
+{
+ SwDoc* pDoc = (SwDoc*)rTxtNd.GetDoc();
+ const SwTxtNode *pTxtNd = rTxtNd.FindOutlineNodeOfLevel( nLevel );
+ if( pTxtNd )
+ {
+ if( bSrchNum )
+ {
+ const SwTxtNode* pONd = pTxtNd;
+ do {
+ if( pONd && pONd->GetTxtColl() )
+ {
+ sal_uInt8 nPrevLvl = nLevel;
+
+ OSL_ENSURE( pONd->GetAttrOutlineLevel() >= 0 && pONd->GetAttrOutlineLevel() <= MAXLEVEL,
+ "<SwChapterField::ChangeExpansion(..)> - outline node with inconsistent outline level. Serious defect -> please inform OD." );
+ nLevel = static_cast<sal_uInt8>(pONd->GetAttrOutlineLevel());
+
+ if( nPrevLvl < nLevel )
+ nLevel = nPrevLvl;
+ else if( SVX_NUM_NUMBER_NONE != pDoc->GetOutlineNumRule()
+ ->Get( nLevel ).GetNumberingType() )
+ {
+ pTxtNd = pONd;
+ break;
+ }
+
+ if( !nLevel-- )
+ break;
+ pONd = pTxtNd->FindOutlineNodeOfLevel( nLevel );
+ }
+ else
+ break;
+ } while( sal_True );
+ }
+
+ // nur die Nummer besorgen, ohne Pre-/Post-fixstrings
+
+ if ( pTxtNd->IsOutline() )
+ {
+ // correction of refactoring done by cws swnumtree:
+ // retrieve numbering string without prefix and suffix strings
+ // as stated in the above german comment.
+ sNumber = pTxtNd->GetNumString( false );
+
+ SwNumRule* pRule( pTxtNd->GetNumRule() );
+ if ( pTxtNd->IsCountedInList() && pRule )
+ {
+ const SwNumFmt& rNFmt = pRule->Get( static_cast<sal_uInt16>(pTxtNd->GetActualListLevel()) );
+ sPost = rNFmt.GetSuffix();
+ sPre = rNFmt.GetPrefix();
+ }
+ else
+ sPost = aEmptyStr, sPre = aEmptyStr;
+ }
+ else
+ {
+ sPost = aEmptyStr;
+ sPre = aEmptyStr;
+ sNumber = String("??", RTL_TEXTENCODING_ASCII_US);
+ }
+
+ sTitle = pTxtNd->GetExpandTxt();
+
+ for( xub_StrLen i = 0; i < sTitle.Len(); ++i )
+ if( ' ' > sTitle.GetChar( i ) )
+ sTitle.Erase( i--, 1 );
+ }
+ else
+ {
+ sNumber = aEmptyStr;
+ sTitle = aEmptyStr;
+ sPost = aEmptyStr;
+ sPre = aEmptyStr;
+ }
+}
+
+bool SwChapterField::QueryValue( uno::Any& rAny, sal_uInt16 nWhichId ) const
+{
+ switch( nWhichId )
+ {
+ case FIELD_PROP_BYTE1:
+ rAny <<= (sal_Int8)nLevel;
+ break;
+
+ case FIELD_PROP_USHORT1:
+ {
+ sal_Int16 nRet;
+ switch( GetFormat() )
+ {
+ case CF_NUMBER: nRet = text::ChapterFormat::NUMBER; break;
+ case CF_TITLE: nRet = text::ChapterFormat::NAME; break;
+ case CF_NUMBER_NOPREPST:
+ nRet = text::ChapterFormat::DIGIT;
+ break;
+ case CF_NUM_NOPREPST_TITLE:
+ nRet = text::ChapterFormat::NO_PREFIX_SUFFIX;
+ break;
+ case CF_NUM_TITLE:
+ default: nRet = text::ChapterFormat::NAME_NUMBER;
+ }
+ rAny <<= nRet;
+ }
+ break;
+
+ default:
+ OSL_FAIL("illegal property");
+ }
+ return true;
+}
+
+bool SwChapterField::PutValue( const uno::Any& rAny, sal_uInt16 nWhichId )
+{
+ sal_Bool bRet = sal_True;
+ switch( nWhichId )
+ {
+ case FIELD_PROP_BYTE1:
+ {
+ sal_Int8 nTmp = 0;
+ rAny >>= nTmp;
+ if(nTmp >= 0 && nTmp < MAXLEVEL)
+ nLevel = nTmp;
+ else
+ bRet = false;
+ break;
+ }
+
+ case FIELD_PROP_USHORT1:
+ {
+ sal_Int16 nVal = 0;
+ rAny >>= nVal;
+ switch( nVal )
+ {
+ case text::ChapterFormat::NAME: SetFormat(CF_TITLE); break;
+ case text::ChapterFormat::NUMBER: SetFormat(CF_NUMBER); break;
+ case text::ChapterFormat::NO_PREFIX_SUFFIX:
+ SetFormat(CF_NUM_NOPREPST_TITLE);
+ break;
+ case text::ChapterFormat::DIGIT:
+ SetFormat(CF_NUMBER_NOPREPST);
+ break;
+
+ default: SetFormat(CF_NUM_TITLE);
+ }
+ }
+ break;
+
+ default:
+ OSL_FAIL("illegal property");
+ bRet = false;
+ }
+ return bRet;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/fields/dbfld.cxx b/sw/source/core/fields/dbfld.cxx
new file mode 100644
index 000000000000..3eb1f758f3ee
--- /dev/null
+++ b/sw/source/core/fields/dbfld.cxx
@@ -0,0 +1,995 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+#include <float.h>
+#include <sfx2/app.hxx>
+#include <svl/zforlist.hxx>
+#include <svx/pageitem.hxx>
+#include <svx/dataaccessdescriptor.hxx>
+#include <com/sun/star/sdbc/DataType.hpp>
+#include <fmtfld.hxx>
+#include <txtfld.hxx>
+#include <doc.hxx>
+#include <docary.hxx>
+#include <frame.hxx>
+#include <fldbas.hxx>
+#include <pam.hxx>
+#include <ndtxt.hxx>
+#include <dbfld.hxx>
+#include <dbmgr.hxx>
+#include <docfld.hxx>
+#include <expfld.hxx>
+#include <txtatr.hxx>
+#include <unofldmid.h>
+#include <switerator.hxx>
+
+using namespace ::com::sun::star::sdbc;
+using namespace ::com::sun::star;
+using ::rtl::OUString;
+
+/*--------------------------------------------------------------------
+ Beschreibung: Datenbanktrenner durch Punkte fuer Anzeige ersetzen
+ --------------------------------------------------------------------*/
+
+String lcl_DBTrennConv(const String& aContent)
+{
+ String sTmp(aContent);
+ sal_Unicode* pStr = sTmp.GetBufferAccess();
+ for( sal_uInt16 i = sTmp.Len(); i; --i, ++pStr )
+ if( DB_DELIM == *pStr )
+ *pStr = '.';
+ return sTmp;
+}
+
+/*--------------------------------------------------------------------
+ Beschreibung: DatenbankFeldTyp
+ --------------------------------------------------------------------*/
+
+SwDBFieldType::SwDBFieldType(SwDoc* pDocPtr, const String& rNam, const SwDBData& rDBData ) :
+ SwValueFieldType( pDocPtr, RES_DBFLD ),
+ aDBData(rDBData),
+ sColumn(rNam),
+ nRefCnt(0)
+{
+ if(aDBData.sDataSource.getLength() || aDBData.sCommand.getLength())
+ {
+ sName = aDBData.sDataSource;
+ sName += DB_DELIM;
+ sName += (String)aDBData.sCommand;
+ sName += DB_DELIM;
+ }
+ sName += GetColumnName();
+}
+//------------------------------------------------------------------------------
+SwDBFieldType::~SwDBFieldType()
+{
+}
+//------------------------------------------------------------------------------
+
+SwFieldType* SwDBFieldType::Copy() const
+{
+ SwDBFieldType* pTmp = new SwDBFieldType(GetDoc(), sColumn, aDBData);
+ return pTmp;
+}
+
+//------------------------------------------------------------------------------
+const String& SwDBFieldType::GetName() const
+{
+ return sName;
+}
+
+//------------------------------------------------------------------------------
+
+void SwDBFieldType::ReleaseRef()
+{
+ OSL_ENSURE(nRefCnt > 0, "RefCount kleiner 0!");
+
+ if (--nRefCnt <= 0)
+ {
+ sal_uInt16 nPos = GetDoc()->GetFldTypes()->GetPos(this);
+
+ if (nPos != USHRT_MAX)
+ {
+ GetDoc()->RemoveFldType(nPos);
+ delete this;
+ }
+ }
+}
+
+bool SwDBFieldType::QueryValue( uno::Any& rAny, sal_uInt16 nWhichId ) const
+{
+ switch( nWhichId )
+ {
+ case FIELD_PROP_PAR1:
+ rAny <<= aDBData.sDataSource;
+ break;
+ case FIELD_PROP_PAR2:
+ rAny <<= aDBData.sCommand;
+ break;
+ case FIELD_PROP_PAR3:
+ rAny <<= OUString(sColumn);
+ break;
+ case FIELD_PROP_SHORT1:
+ rAny <<= aDBData.nCommandType;
+ break;
+ default:
+ OSL_FAIL("illegal property");
+ }
+ return true;
+}
+
+bool SwDBFieldType::PutValue( const uno::Any& rAny, sal_uInt16 nWhichId )
+{
+ switch( nWhichId )
+ {
+ case FIELD_PROP_PAR1:
+ rAny >>= aDBData.sDataSource;
+ break;
+ case FIELD_PROP_PAR2:
+ rAny >>= aDBData.sCommand;
+ break;
+ case FIELD_PROP_PAR3:
+ {
+ String sTmp;
+ ::GetString( rAny, sTmp );
+ if( sTmp != sColumn )
+ {
+ sColumn = sTmp;
+ SwIterator<SwFmtFld,SwFieldType> aIter( *this );
+ SwFmtFld* pFld = aIter.First();
+ while(pFld)
+ {
+ // Feld im Undo?
+ SwTxtFld *pTxtFld = pFld->GetTxtFld();
+ if(pTxtFld && pTxtFld->GetTxtNode().GetNodes().IsDocNodes() )
+ {
+ SwDBField* pDBField = (SwDBField*)pFld->GetFld();
+ pDBField->ClearInitialized();
+ pDBField->InitContent();
+ }
+ pFld = aIter.Next();
+ }
+ }
+ }
+ break;
+ case FIELD_PROP_SHORT1:
+ rAny >>= aDBData.nCommandType;
+ break;
+ default:
+ OSL_FAIL("illegal property");
+ }
+ return true;
+}
+/*--------------------------------------------------------------------
+ Beschreibung: SwDBField
+ --------------------------------------------------------------------*/
+
+SwDBField::SwDBField(SwDBFieldType* pTyp, sal_uLong nFmt)
+ : SwValueField(pTyp, nFmt),
+ nSubType(0),
+ bIsInBodyTxt(sal_True),
+ bValidValue(sal_False),
+ bInitialized(sal_False)
+{
+ if (GetTyp())
+ ((SwDBFieldType*)GetTyp())->AddRef();
+ InitContent();
+}
+
+//------------------------------------------------------------------------------
+
+SwDBField::~SwDBField()
+{
+ if (GetTyp())
+ ((SwDBFieldType*)GetTyp())->ReleaseRef();
+}
+
+//------------------------------------------------------------------------------
+
+void SwDBField::InitContent()
+{
+ if (!IsInitialized())
+ {
+ aContent = '<';
+ aContent += ((SwDBFieldType*)GetTyp())->GetColumnName();
+ aContent += '>';
+ }
+}
+
+//------------------------------------------------------------------------------
+
+void SwDBField::InitContent(const String& rExpansion)
+{
+ if (rExpansion.Len() > 2)
+ {
+ if (rExpansion.GetChar(0) == '<' &&
+ rExpansion.GetChar(rExpansion.Len() - 1) == '>')
+ {
+ String sColumn( rExpansion.Copy( 1, rExpansion.Len() - 2 ) );
+ if( ::GetAppCmpStrIgnore().isEqual( sColumn,
+ ((SwDBFieldType *)GetTyp())->GetColumnName() ))
+ {
+ InitContent();
+ return;
+ }
+ }
+ }
+ SetExpansion( rExpansion );
+}
+
+//------------------------------------------------------------------------------
+
+String SwDBField::Expand() const
+{
+ String sRet;
+
+ if(0 ==(GetSubType() & nsSwExtendedSubType::SUB_INVISIBLE))
+ sRet = lcl_DBTrennConv(aContent);
+ return sRet;
+}
+
+//------------------------------------------------------------------------------
+
+SwField* SwDBField::Copy() const
+{
+ SwDBField *pTmp = new SwDBField((SwDBFieldType*)GetTyp(), GetFormat());
+ pTmp->aContent = aContent;
+ pTmp->bIsInBodyTxt = bIsInBodyTxt;
+ pTmp->bValidValue = bValidValue;
+ pTmp->bInitialized = bInitialized;
+ pTmp->nSubType = nSubType;
+ pTmp->SetValue(GetValue());
+ pTmp->sFieldCode = sFieldCode;
+
+ return pTmp;
+}
+
+String SwDBField::GetFieldName() const
+{
+ const String& rDBName = static_cast<SwDBFieldType*>(GetTyp())->GetName();
+
+ String sContent( rDBName.GetToken(0, DB_DELIM) );
+
+ if (sContent.Len() > 1)
+ {
+ sContent += DB_DELIM;
+ sContent += rDBName.GetToken(1, DB_DELIM);
+ sContent += DB_DELIM;
+ sContent += rDBName.GetToken(2, DB_DELIM);
+ }
+ return lcl_DBTrennConv(sContent);
+}
+
+//------------------------------------------------------------------------------
+
+void SwDBField::ChgValue( double d, sal_Bool bVal )
+{
+ bValidValue = bVal;
+ SetValue(d);
+
+ if( bValidValue )
+ aContent = ((SwValueFieldType*)GetTyp())->ExpandValue(d, GetFormat(), GetLanguage());
+}
+
+SwFieldType* SwDBField::ChgTyp( SwFieldType* pNewType )
+{
+ SwFieldType* pOld = SwValueField::ChgTyp( pNewType );
+
+ ((SwDBFieldType*)pNewType)->AddRef();
+ ((SwDBFieldType*)pOld)->ReleaseRef();
+
+ return pOld;
+}
+
+/*--------------------------------------------------------------------
+ Beschreibung: Aktuellen Field-Value holen und chachen
+ --------------------------------------------------------------------*/
+
+void SwDBField::Evaluate()
+{
+ SwNewDBMgr* pMgr = GetDoc()->GetNewDBMgr();
+
+ // erstmal loeschen
+ bValidValue = sal_False;
+ double nValue = DBL_MAX;
+ const SwDBData& aTmpData = GetDBData();
+
+ if(!pMgr || !pMgr->IsDataSourceOpen(aTmpData.sDataSource, aTmpData.sCommand, sal_True))
+ return ;
+
+ sal_uInt32 nFmt;
+
+ // Passenden Spaltennamen suchen
+ String aColNm( ((SwDBFieldType*)GetTyp())->GetColumnName() );
+
+ SvNumberFormatter* pDocFormatter = GetDoc()->GetNumberFormatter();
+ pMgr->GetMergeColumnCnt(aColNm, GetLanguage(), aContent, &nValue, &nFmt);
+ if( !( nSubType & nsSwExtendedSubType::SUB_OWN_FMT ) )
+ SetFormat( nFmt = pMgr->GetColumnFmt( aTmpData.sDataSource, aTmpData.sCommand,
+ aColNm, pDocFormatter, GetLanguage() ));
+
+ if( DBL_MAX != nValue )
+ {
+ sal_Int32 nColumnType = pMgr->GetColumnType(aTmpData.sDataSource, aTmpData.sCommand, aColNm);
+ if( DataType::DATE == nColumnType || DataType::TIME == nColumnType ||
+ DataType::TIMESTAMP == nColumnType)
+
+ {
+ Date aStandard(1,1,1900);
+ if (*pDocFormatter->GetNullDate() != aStandard)
+ nValue += (aStandard - *pDocFormatter->GetNullDate());
+ }
+ bValidValue = sal_True;
+ SetValue(nValue);
+ aContent = ((SwValueFieldType*)GetTyp())->ExpandValue(nValue, GetFormat(), GetLanguage());
+ }
+ else
+ {
+ SwSbxValue aVal;
+ aVal.PutString( aContent );
+
+ if (aVal.IsNumeric())
+ {
+ SetValue(aVal.GetDouble());
+
+ SvNumberFormatter* pFormatter = GetDoc()->GetNumberFormatter();
+ if (nFmt && nFmt != SAL_MAX_UINT32 && !pFormatter->IsTextFormat(nFmt))
+ bValidValue = sal_True; // Wegen Bug #60339 nicht mehr bei allen Strings
+ }
+ else
+ {
+ // Bei Strings sal_True wenn Laenge > 0 sonst sal_False
+ SetValue(aContent.Len() ? 1 : 0);
+ }
+ }
+ bInitialized = sal_True;
+}
+
+/*--------------------------------------------------------------------
+ Beschreibung: Namen erfragen
+ --------------------------------------------------------------------*/
+
+const String& SwDBField::GetPar1() const
+{
+ return ((SwDBFieldType*)GetTyp())->GetName();
+}
+
+sal_uInt16 SwDBField::GetSubType() const
+{
+ return nSubType;
+}
+
+void SwDBField::SetSubType(sal_uInt16 nType)
+{
+ nSubType = nType;
+}
+
+bool SwDBField::QueryValue( uno::Any& rAny, sal_uInt16 nWhichId ) const
+{
+ switch( nWhichId )
+ {
+ case FIELD_PROP_BOOL1:
+ {
+ sal_Bool bTemp = 0 == (GetSubType()&nsSwExtendedSubType::SUB_OWN_FMT);
+ rAny.setValue(&bTemp, ::getBooleanCppuType());
+ }
+ break;
+ case FIELD_PROP_BOOL2:
+ {
+ sal_Bool bVal = 0 == (GetSubType() & nsSwExtendedSubType::SUB_INVISIBLE);
+ rAny.setValue(&bVal, ::getBooleanCppuType());
+ }
+ break;
+ case FIELD_PROP_FORMAT:
+ rAny <<= (sal_Int32)GetFormat();
+ break;
+ case FIELD_PROP_PAR1:
+ rAny <<= OUString(aContent);
+ break;
+ case FIELD_PROP_PAR2:
+ rAny <<= OUString(sFieldCode);
+ break;
+ default:
+ OSL_FAIL("illegal property");
+ }
+ return true;
+
+}
+
+bool SwDBField::PutValue( const uno::Any& rAny, sal_uInt16 nWhichId )
+{
+ switch( nWhichId )
+ {
+ case FIELD_PROP_BOOL1:
+ if( *(sal_Bool*)rAny.getValue() )
+ SetSubType(GetSubType()&~nsSwExtendedSubType::SUB_OWN_FMT);
+ else
+ SetSubType(GetSubType()|nsSwExtendedSubType::SUB_OWN_FMT);
+ break;
+ case FIELD_PROP_BOOL2:
+ {
+ sal_uInt16 nSubTyp = GetSubType();
+ sal_Bool bVisible = sal_False;
+ if(!(rAny >>= bVisible))
+ return sal_False;
+ if(bVisible)
+ nSubTyp &= ~nsSwExtendedSubType::SUB_INVISIBLE;
+ else
+ nSubTyp |= nsSwExtendedSubType::SUB_INVISIBLE;
+ SetSubType(nSubTyp);
+ //invalidate text node
+ if(GetTyp())
+ {
+ SwIterator<SwFmtFld,SwFieldType> aIter( *GetTyp() );
+ SwFmtFld* pFld = aIter.First();
+ while(pFld)
+ {
+ SwTxtFld *pTxtFld = pFld->GetTxtFld();
+ if(pTxtFld && (SwDBField*)pFld->GetFld() == this )
+ {
+ //notify the change
+ pTxtFld->NotifyContentChange(*pFld);
+ break;
+ }
+ pFld = aIter.Next();
+ }
+ }
+ }
+ break;
+ case FIELD_PROP_FORMAT:
+ {
+ sal_Int32 nTemp = 0;
+ rAny >>= nTemp;
+ SetFormat(nTemp);
+ }
+ break;
+ case FIELD_PROP_PAR1:
+ ::GetString( rAny, aContent );
+ break;
+ case FIELD_PROP_PAR2:
+ ::GetString( rAny, sFieldCode );
+ break;
+ default:
+ OSL_FAIL("illegal property");
+ }
+ return true;
+}
+
+/*--------------------------------------------------------------------
+ Beschreibung: Basisklasse fuer alle weiteren Datenbankfelder
+ --------------------------------------------------------------------*/
+
+SwDBNameInfField::SwDBNameInfField(SwFieldType* pTyp, const SwDBData& rDBData, sal_uLong nFmt) :
+ SwField(pTyp, nFmt),
+ aDBData(rDBData),
+ nSubType(0)
+{
+}
+
+//------------------------------------------------------------------------------
+
+SwDBData SwDBNameInfField::GetDBData(SwDoc* pDoc)
+{
+ SwDBData aRet;
+ if(aDBData.sDataSource.getLength())
+ aRet = aDBData;
+ else
+ aRet = pDoc->GetDBData();
+ return aRet;
+}
+
+void SwDBNameInfField::SetDBData(const SwDBData & rDBData)
+{
+ aDBData = rDBData;
+}
+
+//------------------------------------------------------------------------------
+
+String SwDBNameInfField::GetFieldName() const
+{
+ String sStr( SwField::GetFieldName() );
+ if (aDBData.sDataSource.getLength())
+ {
+ sStr += ':';
+ sStr += String(aDBData.sDataSource);
+ sStr += DB_DELIM;
+ sStr += String(aDBData.sCommand);
+ }
+ return lcl_DBTrennConv(sStr);
+}
+
+bool SwDBNameInfField::QueryValue( uno::Any& rAny, sal_uInt16 nWhichId ) const
+{
+ switch( nWhichId )
+ {
+ case FIELD_PROP_PAR1:
+ rAny <<= aDBData.sDataSource;
+ break;
+ case FIELD_PROP_PAR2:
+ rAny <<= aDBData.sCommand;
+ break;
+ case FIELD_PROP_SHORT1:
+ rAny <<= aDBData.nCommandType;
+ break;
+ case FIELD_PROP_BOOL2:
+ {
+ sal_Bool bVal = 0 == (GetSubType() & nsSwExtendedSubType::SUB_INVISIBLE);
+ rAny.setValue(&bVal, ::getBooleanCppuType());
+ }
+ break;
+ default:
+ OSL_FAIL("illegal property");
+ }
+ return true;
+}
+
+bool SwDBNameInfField::PutValue( const uno::Any& rAny, sal_uInt16 nWhichId )
+{
+ switch( nWhichId )
+ {
+ case FIELD_PROP_PAR1:
+ rAny >>= aDBData.sDataSource;
+ break;
+ case FIELD_PROP_PAR2:
+ rAny >>= aDBData.sCommand;
+ break;
+ case FIELD_PROP_SHORT1:
+ rAny >>= aDBData.nCommandType;
+ break;
+ case FIELD_PROP_BOOL2:
+ {
+ sal_uInt16 nSubTyp = GetSubType();
+ sal_Bool bVisible = sal_False;
+ if(!(rAny >>= bVisible))
+ return false;
+ if(bVisible)
+ nSubTyp &= ~nsSwExtendedSubType::SUB_INVISIBLE;
+ else
+ nSubTyp |= nsSwExtendedSubType::SUB_INVISIBLE;
+ SetSubType(nSubTyp);
+ }
+ break;
+ default:
+ OSL_FAIL("illegal property");
+ }
+ return true;
+}
+
+sal_uInt16 SwDBNameInfField::GetSubType() const
+{
+ return nSubType;
+}
+
+void SwDBNameInfField::SetSubType(sal_uInt16 nType)
+{
+ nSubType = nType;
+}
+
+/*--------------------------------------------------------------------
+ Beschreibung: NaechsterDatensatz
+ --------------------------------------------------------------------*/
+
+SwDBNextSetFieldType::SwDBNextSetFieldType()
+ : SwFieldType( RES_DBNEXTSETFLD )
+{
+}
+
+//------------------------------------------------------------------------------
+
+SwFieldType* SwDBNextSetFieldType::Copy() const
+{
+ SwDBNextSetFieldType* pTmp = new SwDBNextSetFieldType();
+ return pTmp;
+}
+/*--------------------------------------------------------------------
+ Beschreibung: SwDBSetField
+ --------------------------------------------------------------------*/
+
+SwDBNextSetField::SwDBNextSetField(SwDBNextSetFieldType* pTyp,
+ const String& rCond,
+ const String& ,
+ const SwDBData& rDBData) :
+ SwDBNameInfField(pTyp, rDBData), aCond(rCond), bCondValid(sal_True)
+{}
+
+//------------------------------------------------------------------------------
+
+String SwDBNextSetField::Expand() const
+{
+ return aEmptyStr;
+}
+
+//------------------------------------------------------------------------------
+
+SwField* SwDBNextSetField::Copy() const
+{
+ SwDBNextSetField *pTmp = new SwDBNextSetField((SwDBNextSetFieldType*)GetTyp(),
+ aCond, aEmptyStr, GetDBData());
+ pTmp->SetSubType(GetSubType());
+ pTmp->bCondValid = bCondValid;
+ return pTmp;
+}
+//------------------------------------------------------------------------------
+
+void SwDBNextSetField::Evaluate(SwDoc* pDoc)
+{
+ SwNewDBMgr* pMgr = pDoc->GetNewDBMgr();
+ const SwDBData& rData = GetDBData();
+ if( !bCondValid ||
+ !pMgr || !pMgr->IsDataSourceOpen(rData.sDataSource, rData.sCommand, sal_False))
+ return ;
+ pMgr->ToNextRecord(rData.sDataSource, rData.sCommand);
+}
+
+/*--------------------------------------------------------------------
+ Beschreibung: Bedingung
+ --------------------------------------------------------------------*/
+
+const String& SwDBNextSetField::GetPar1() const
+{
+ return aCond;
+}
+
+void SwDBNextSetField::SetPar1(const String& rStr)
+{
+ aCond = rStr;
+}
+
+bool SwDBNextSetField::QueryValue( uno::Any& rAny, sal_uInt16 nWhichId ) const
+{
+ bool bRet = true;
+ switch( nWhichId )
+ {
+ case FIELD_PROP_PAR3:
+ rAny <<= OUString(aCond);
+ break;
+ default:
+ bRet = SwDBNameInfField::QueryValue( rAny, nWhichId );
+ }
+ return bRet;
+}
+
+bool SwDBNextSetField::PutValue( const uno::Any& rAny, sal_uInt16 nWhichId )
+{
+ bool bRet = true;
+ switch( nWhichId )
+ {
+ case FIELD_PROP_PAR3:
+ ::GetString( rAny, aCond );
+ break;
+ default:
+ bRet = SwDBNameInfField::PutValue( rAny, nWhichId );
+ }
+ return bRet;
+}
+
+/*--------------------------------------------------------------------
+ Beschreibung: Datensatz mit bestimmter ID
+ --------------------------------------------------------------------*/
+
+SwDBNumSetFieldType::SwDBNumSetFieldType() :
+ SwFieldType( RES_DBNUMSETFLD )
+{
+}
+
+//------------------------------------------------------------------------------
+
+SwFieldType* SwDBNumSetFieldType::Copy() const
+{
+ SwDBNumSetFieldType* pTmp = new SwDBNumSetFieldType();
+ return pTmp;
+}
+
+/*--------------------------------------------------------------------
+ Beschreibung: SwDBSetField
+ --------------------------------------------------------------------*/
+
+SwDBNumSetField::SwDBNumSetField(SwDBNumSetFieldType* pTyp,
+ const String& rCond,
+ const String& rDBNum,
+ const SwDBData& rDBData) :
+ SwDBNameInfField(pTyp, rDBData),
+ aCond(rCond),
+ aPar2(rDBNum),
+ bCondValid(sal_True)
+{}
+
+//------------------------------------------------------------------------------
+
+String SwDBNumSetField::Expand() const
+{
+ return aEmptyStr;
+}
+
+//------------------------------------------------------------------------------
+
+SwField* SwDBNumSetField::Copy() const
+{
+ SwDBNumSetField *pTmp = new SwDBNumSetField((SwDBNumSetFieldType*)GetTyp(),
+ aCond, aPar2, GetDBData());
+ pTmp->bCondValid = bCondValid;
+ pTmp->SetSubType(GetSubType());
+ return pTmp;
+}
+
+void SwDBNumSetField::Evaluate(SwDoc* pDoc)
+{
+ SwNewDBMgr* pMgr = pDoc->GetNewDBMgr();
+ const SwDBData& aTmpData = GetDBData();
+
+ if( bCondValid && pMgr && pMgr->IsInMerge() &&
+ pMgr->IsDataSourceOpen(aTmpData.sDataSource, aTmpData.sCommand, sal_True))
+ { // Bedingug OK -> aktuellen Set einstellen
+ pMgr->ToRecordId(Max((sal_uInt16)aPar2.ToInt32(), sal_uInt16(1))-1);
+ }
+}
+
+/*--------------------------------------------------------------------
+ Beschreibung: LogDBName
+ --------------------------------------------------------------------*/
+
+const String& SwDBNumSetField::GetPar1() const
+{
+ return aCond;
+}
+
+void SwDBNumSetField::SetPar1(const String& rStr)
+{
+ aCond = rStr;
+}
+
+/*--------------------------------------------------------------------
+ Beschreibung: Bedingung
+ --------------------------------------------------------------------*/
+
+String SwDBNumSetField::GetPar2() const
+{
+ return aPar2;
+}
+
+void SwDBNumSetField::SetPar2(const String& rStr)
+{
+ aPar2 = rStr;
+}
+
+bool SwDBNumSetField::QueryValue( uno::Any& rAny, sal_uInt16 nWhichId ) const
+{
+ bool bRet = true;
+ switch( nWhichId )
+ {
+ case FIELD_PROP_PAR3:
+ rAny <<= OUString(aCond);
+ break;
+ case FIELD_PROP_FORMAT:
+ rAny <<= (sal_Int32)aPar2.ToInt32();
+ break;
+ default:
+ bRet = SwDBNameInfField::QueryValue(rAny, nWhichId );
+ }
+ return bRet;
+}
+
+bool SwDBNumSetField::PutValue( const uno::Any& rAny, sal_uInt16 nWhichId )
+{
+ bool bRet = true;
+ switch( nWhichId )
+ {
+ case FIELD_PROP_PAR3:
+ ::GetString( rAny, aCond );
+ break;
+ case FIELD_PROP_FORMAT:
+ {
+ sal_Int32 nVal = 0;
+ rAny >>= nVal;
+ aPar2 = String::CreateFromInt32(nVal);
+ }
+ break;
+ default:
+ bRet = SwDBNameInfField::PutValue(rAny, nWhichId );
+ }
+ return bRet;
+}
+
+/*--------------------------------------------------------------------
+ Beschreibung: SwDBNameFieldType
+ --------------------------------------------------------------------*/
+
+SwDBNameFieldType::SwDBNameFieldType(SwDoc* pDocument)
+ : SwFieldType( RES_DBNAMEFLD )
+{
+ pDoc = pDocument;
+}
+//------------------------------------------------------------------------------
+
+String SwDBNameFieldType::Expand(sal_uLong ) const
+{
+ const SwDBData aData = pDoc->GetDBData();
+ String sRet(aData.sDataSource);
+ sRet += '.';
+ sRet += (String)aData.sCommand;
+ return sRet;
+}
+//------------------------------------------------------------------------------
+
+SwFieldType* SwDBNameFieldType::Copy() const
+{
+ SwDBNameFieldType *pTmp = new SwDBNameFieldType(pDoc);
+ return pTmp;
+}
+
+//------------------------------------------------------------------------------
+
+/*--------------------------------------------------------------------
+ Beschreibung: Name der angedockten DB
+ --------------------------------------------------------------------*/
+
+SwDBNameField::SwDBNameField(SwDBNameFieldType* pTyp, const SwDBData& rDBData, sal_uLong nFmt)
+ : SwDBNameInfField(pTyp, rDBData, nFmt)
+{}
+
+//------------------------------------------------------------------------------
+
+String SwDBNameField::Expand() const
+{
+ String sRet;
+ if(0 ==(GetSubType() & nsSwExtendedSubType::SUB_INVISIBLE))
+ sRet = ((SwDBNameFieldType*)GetTyp())->Expand(GetFormat());
+ return sRet;
+}
+
+//------------------------------------------------------------------------------
+
+SwField* SwDBNameField::Copy() const
+{
+ SwDBNameField *pTmp = new SwDBNameField((SwDBNameFieldType*)GetTyp(), GetDBData());
+ pTmp->ChangeFormat(GetFormat());
+ pTmp->SetLanguage(GetLanguage());
+ pTmp->SetSubType(GetSubType());
+ return pTmp;
+}
+
+bool SwDBNameField::QueryValue( uno::Any& rAny, sal_uInt16 nWhichId ) const
+{
+ return SwDBNameInfField::QueryValue(rAny, nWhichId );
+}
+
+bool SwDBNameField::PutValue( const uno::Any& rAny, sal_uInt16 nWhichId )
+{
+ return SwDBNameInfField::PutValue(rAny, nWhichId );
+}
+/*--------------------------------------------------------------------
+ Beschreibung: SwDBNameFieldType
+ --------------------------------------------------------------------*/
+
+SwDBSetNumberFieldType::SwDBSetNumberFieldType()
+ : SwFieldType( RES_DBSETNUMBERFLD )
+{
+}
+
+//------------------------------------------------------------------------------
+
+SwFieldType* SwDBSetNumberFieldType::Copy() const
+{
+ SwDBSetNumberFieldType *pTmp = new SwDBSetNumberFieldType;
+ return pTmp;
+}
+
+//------------------------------------------------------------------------------
+
+/*--------------------------------------------------------------------
+ Beschreibung: SetNumber der angedockten DB
+ --------------------------------------------------------------------*/
+
+SwDBSetNumberField::SwDBSetNumberField(SwDBSetNumberFieldType* pTyp,
+ const SwDBData& rDBData,
+ sal_uLong nFmt)
+ : SwDBNameInfField(pTyp, rDBData, nFmt), nNumber(0)
+{}
+
+//------------------------------------------------------------------------------
+
+String SwDBSetNumberField::Expand() const
+{
+ if(0 !=(GetSubType() & nsSwExtendedSubType::SUB_INVISIBLE) || nNumber == 0)
+ return aEmptyStr;
+ else
+ return FormatNumber((sal_uInt16)nNumber, GetFormat());
+}
+
+//------------------------------------------------------------------------------
+
+void SwDBSetNumberField::Evaluate(SwDoc* pDoc)
+{
+ SwNewDBMgr* pMgr = pDoc->GetNewDBMgr();
+
+ const SwDBData& aTmpData = GetDBData();
+ if (!pMgr || !pMgr->IsInMerge() ||
+ !pMgr->IsDataSourceOpen(aTmpData.sDataSource, aTmpData.sCommand, sal_False))
+ return;
+ nNumber = pMgr->GetSelectedRecordId();
+}
+
+
+//------------------------------------------------------------------------------
+
+SwField* SwDBSetNumberField::Copy() const
+{
+ SwDBSetNumberField *pTmp =
+ new SwDBSetNumberField((SwDBSetNumberFieldType*)GetTyp(), GetDBData(), GetFormat());
+ pTmp->SetLanguage(GetLanguage());
+ pTmp->SetSetNumber(nNumber);
+ pTmp->SetSubType(GetSubType());
+ return pTmp;
+}
+
+bool SwDBSetNumberField::QueryValue( uno::Any& rAny, sal_uInt16 nWhichId ) const
+{
+ bool bRet = true;
+ switch( nWhichId )
+ {
+ case FIELD_PROP_USHORT1:
+ rAny <<= (sal_Int16)GetFormat();
+ break;
+ case FIELD_PROP_FORMAT:
+ rAny <<= nNumber;
+ break;
+ default:
+ bRet = SwDBNameInfField::QueryValue( rAny, nWhichId );
+ }
+ return bRet;
+}
+
+bool SwDBSetNumberField::PutValue( const uno::Any& rAny, sal_uInt16 nWhichId )
+{
+ bool bRet = true;
+ switch( nWhichId )
+ {
+ case FIELD_PROP_USHORT1:
+ {
+ sal_Int16 nSet = 0;
+ rAny >>= nSet;
+ if(nSet < (sal_Int16) SVX_NUMBER_NONE )
+ SetFormat(nSet);
+ else {
+ }
+ }
+ break;
+ case FIELD_PROP_FORMAT:
+ rAny >>= nNumber;
+ break;
+ default:
+ bRet = SwDBNameInfField::PutValue( rAny, nWhichId );
+ }
+ return bRet;
+}
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/fields/ddefld.cxx b/sw/source/core/fields/ddefld.cxx
new file mode 100644
index 000000000000..4c6e08187c75
--- /dev/null
+++ b/sw/source/core/fields/ddefld.cxx
@@ -0,0 +1,443 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+
+#include <sfx2/linkmgr.hxx>
+#include <doc.hxx>
+#include <editsh.hxx>
+#include <ndtxt.hxx>
+#include <fmtfld.hxx>
+#include <txtfld.hxx>
+#include <ddefld.hxx>
+#include <swtable.hxx>
+#include <swbaslnk.hxx>
+#include <swddetbl.hxx>
+#include <unofldmid.h>
+#include <hints.hxx>
+
+using rtl::OUString;
+using namespace ::com::sun::star;
+
+#define DDE_TXT_ENCODING gsl_getSystemTextEncoding()
+
+/*--------------------------------------------------------------------
+ Beschreibung: Globale Variablen
+ --------------------------------------------------------------------*/
+
+class SwIntrnlRefLink : public SwBaseLink
+{
+ SwDDEFieldType& rFldType;
+public:
+ SwIntrnlRefLink( SwDDEFieldType& rType, sal_uInt16 nUpdateType, sal_uInt16 nFmt )
+ : SwBaseLink( nUpdateType, nFmt ),
+ rFldType( rType )
+ {}
+
+ virtual void Closed();
+ virtual void DataChanged( const String& rMimeType,
+ const uno::Any & rValue );
+
+ virtual const SwNode* GetAnchor() const;
+ virtual sal_Bool IsInRange( sal_uLong nSttNd, sal_uLong nEndNd, xub_StrLen nStt = 0,
+ xub_StrLen nEnd = STRING_NOTFOUND ) const;
+};
+
+
+void SwIntrnlRefLink::DataChanged( const String& rMimeType,
+ const uno::Any & rValue )
+{
+ switch( SotExchange::GetFormatIdFromMimeType( rMimeType ) )
+ {
+ case FORMAT_STRING:
+ if( !IsNoDataFlag() )
+ {
+ uno::Sequence< sal_Int8 > aSeq;
+ rValue >>= aSeq;
+ String sStr( (sal_Char*)aSeq.getConstArray(), static_cast<xub_StrLen>(aSeq.getLength()),
+ DDE_TXT_ENCODING );
+
+ // CR-LF am Ende entfernen, ist ueberfluessig!
+ xub_StrLen n = sStr.Len();
+ while( n && 0 == sStr.GetChar( n-1 ) )
+ --n;
+ if( n && 0x0a == sStr.GetChar( n-1 ) )
+ --n;
+ if( n && 0x0d == sStr.GetChar( n-1 ) )
+ --n;
+
+ sal_Bool bDel = n != sStr.Len();
+ if( bDel )
+ sStr.Erase( n );
+
+ rFldType.SetExpansion( sStr );
+ // erst Expansion setzen! (sonst wird das Flag geloescht!)
+ rFldType.SetCRLFDelFlag( bDel );
+ }
+ break;
+
+ // weitere Formate ...
+ default:
+ return;
+ }
+
+ OSL_ENSURE( rFldType.GetDoc(), "Kein pDoc" );
+
+ // keine Abhaengigen mehr?
+ if( rFldType.GetDepends() && !rFldType.IsModifyLocked() && !ChkNoDataFlag() )
+ {
+ ViewShell* pSh;
+ SwEditShell* pESh = rFldType.GetDoc()->GetEditShell( &pSh );
+
+ // dann suchen wir uns mal alle Felder. Wird kein gueltiges
+ // gefunden, dann Disconnecten wir uns!
+ SwMsgPoolItem aUpdateDDE( RES_UPDATEDDETBL );
+ int bCallModify = sal_False;
+ rFldType.LockModify();
+
+ SwClientIter aIter( rFldType ); // TODO
+ SwClient * pLast = aIter.GoStart();
+ if( pLast ) // konnte zum Anfang gesprungen werden ??
+ do {
+ // eine DDE-Tabelle oder ein DDE-FeldAttribut im Text
+ if( !pLast->IsA( TYPE( SwFmtFld ) ) ||
+ ((SwFmtFld*)pLast)->GetTxtFld() )
+ {
+ if( !bCallModify )
+ {
+ if( pESh )
+ pESh->StartAllAction();
+ else if( pSh )
+ pSh->StartAction();
+ }
+ pLast->ModifyNotification( 0, &aUpdateDDE );
+ bCallModify = sal_True;
+ }
+ } while( 0 != ( pLast = aIter++ ));
+
+ rFldType.UnlockModify();
+
+ if( bCallModify )
+ {
+ if( pESh )
+ pESh->EndAllAction();
+ else if( pSh )
+ pSh->EndAction();
+
+ if( pSh )
+ pSh->GetDoc()->SetModified();
+ }
+ }
+}
+
+void SwIntrnlRefLink::Closed()
+{
+ if( rFldType.GetDoc() && !rFldType.GetDoc()->IsInDtor() )
+ {
+ // Advise verabschiedet sich, alle Felder in Text umwandeln ?
+ ViewShell* pSh;
+ SwEditShell* pESh = rFldType.GetDoc()->GetEditShell( &pSh );
+ if( pESh )
+ {
+ pESh->StartAllAction();
+ pESh->FieldToText( &rFldType );
+ pESh->EndAllAction();
+ }
+ else
+ {
+ pSh->StartAction();
+ // am Doc aufrufen ??
+ pSh->EndAction();
+ }
+ }
+ SvBaseLink::Closed();
+}
+
+const SwNode* SwIntrnlRefLink::GetAnchor() const
+{
+ // hier sollte irgend ein Anchor aus dem normalen Nodes-Array reichen
+ const SwNode* pNd = 0;
+ SwClientIter aIter( rFldType ); // TODO
+ SwClient * pLast = aIter.GoStart();
+ if( pLast ) // konnte zum Anfang gesprungen werden ??
+ do {
+ // eine DDE-Tabelle oder ein DDE-FeldAttribut im Text
+ if( !pLast->IsA( TYPE( SwFmtFld ) ))
+ {
+ SwDepend* pDep = (SwDepend*)pLast;
+ SwDDETable* pDDETbl = (SwDDETable*)pDep->GetToTell();
+ pNd = pDDETbl->GetTabSortBoxes()[0]->GetSttNd();
+ }
+ else if( ((SwFmtFld*)pLast)->GetTxtFld() )
+ pNd = ((SwFmtFld*)pLast)->GetTxtFld()->GetpTxtNode();
+
+ if( pNd && &rFldType.GetDoc()->GetNodes() == &pNd->GetNodes() )
+ break;
+ pNd = 0;
+ } while( 0 != ( pLast = aIter++ ));
+
+ return pNd;
+}
+
+sal_Bool SwIntrnlRefLink::IsInRange( sal_uLong nSttNd, sal_uLong nEndNd,
+ xub_StrLen nStt, xub_StrLen nEnd ) const
+{
+ // hier sollte irgend ein Anchor aus dem normalen Nodes-Array reichen
+ SwNodes* pNds = &rFldType.GetDoc()->GetNodes();
+ SwClientIter aIter( rFldType ); // TODO
+ SwClient * pLast = aIter.GoStart();
+ if( pLast ) // konnte zum Anfang gesprungen werden ??
+ do {
+ // eine DDE-Tabelle oder ein DDE-FeldAttribut im Text
+ if( !pLast->IsA( TYPE( SwFmtFld ) ))
+ {
+ SwDepend* pDep = (SwDepend*)pLast;
+ SwDDETable* pDDETbl = (SwDDETable*)pDep->GetToTell();
+ const SwTableNode* pTblNd = pDDETbl->GetTabSortBoxes()[0]->
+ GetSttNd()->FindTableNode();
+ if( pTblNd->GetNodes().IsDocNodes() &&
+ nSttNd < pTblNd->EndOfSectionIndex() &&
+ nEndNd > pTblNd->GetIndex() )
+ return sal_True;
+ }
+ else if( ((SwFmtFld*)pLast)->GetTxtFld() )
+ {
+ const SwTxtFld* pTFld = ((SwFmtFld*)pLast)->GetTxtFld();
+ const SwTxtNode* pNd = pTFld->GetpTxtNode();
+ if( pNd && pNds == &pNd->GetNodes() )
+ {
+ sal_uLong nNdPos = pNd->GetIndex();
+ if( nSttNd <= nNdPos && nNdPos <= nEndNd &&
+ ( nNdPos != nSttNd || *pTFld->GetStart() >= nStt ) &&
+ ( nNdPos != nEndNd || *pTFld->GetStart() < nEnd ))
+ return sal_True;
+ }
+ }
+ } while( 0 != ( pLast = aIter++ ));
+
+ return sal_False;
+}
+
+SwDDEFieldType::SwDDEFieldType(const String& rName,
+ const String& rCmd, sal_uInt16 nUpdateType )
+ : SwFieldType( RES_DDEFLD ),
+ aName( rName ), pDoc( 0 ), nRefCnt( 0 )
+{
+ bCRLFFlag = bDeleted = sal_False;
+ refLink = new SwIntrnlRefLink( *this, nUpdateType, FORMAT_STRING );
+ SetCmd( rCmd );
+}
+
+SwDDEFieldType::~SwDDEFieldType()
+{
+ if( pDoc && !pDoc->IsInDtor() )
+ pDoc->GetLinkManager().Remove( refLink );
+ refLink->Disconnect();
+}
+
+SwFieldType* SwDDEFieldType::Copy() const
+{
+ SwDDEFieldType* pType = new SwDDEFieldType( aName, GetCmd(), GetType() );
+ pType->aExpansion = aExpansion;
+ pType->bCRLFFlag = bCRLFFlag;
+ pType->bDeleted = bDeleted;
+ pType->SetDoc( pDoc );
+ return pType;
+}
+
+const String& SwDDEFieldType::GetName() const
+{
+ return aName;
+}
+
+void SwDDEFieldType::SetCmd( const String& rStr )
+{
+ String sCmd( rStr );
+ xub_StrLen nPos;
+ while( STRING_NOTFOUND != (nPos = sCmd.SearchAscii( " " )) )
+ sCmd.Erase( nPos, 1 );
+ refLink->SetLinkSourceName( sCmd );
+}
+
+String SwDDEFieldType::GetCmd() const
+{
+ return refLink->GetLinkSourceName();
+}
+
+void SwDDEFieldType::SetDoc( SwDoc* pNewDoc )
+{
+ if( pNewDoc == pDoc )
+ return;
+
+ if( pDoc && refLink.Is() )
+ {
+ OSL_ENSURE( !nRefCnt, "wie kommen die Referenzen rueber?" );
+ pDoc->GetLinkManager().Remove( refLink );
+ }
+
+ pDoc = pNewDoc;
+ if( pDoc && nRefCnt )
+ {
+ refLink->SetVisible( pDoc->IsVisibleLinks() );
+ pDoc->GetLinkManager().InsertDDELink( refLink );
+ }
+}
+
+
+void SwDDEFieldType::_RefCntChgd()
+{
+ if( nRefCnt )
+ {
+ refLink->SetVisible( pDoc->IsVisibleLinks() );
+ pDoc->GetLinkManager().InsertDDELink( refLink );
+ if( pDoc->GetCurrentViewShell() ) //swmod 071108//swmod 071225
+ UpdateNow();
+ }
+ else
+ {
+ Disconnect();
+ pDoc->GetLinkManager().Remove( refLink );
+ }
+}
+
+bool SwDDEFieldType::QueryValue( uno::Any& rVal, sal_uInt16 nWhichId ) const
+{
+ sal_uInt8 nPart = 0;
+ switch( nWhichId )
+ {
+ case FIELD_PROP_PAR2: nPart = 3; break;
+ case FIELD_PROP_PAR4: nPart = 2; break;
+ case FIELD_PROP_SUBTYPE: nPart = 1; break;
+ case FIELD_PROP_BOOL1:
+ {
+ sal_Bool bSet = GetType() == sfx2::LINKUPDATE_ALWAYS ? sal_True : sal_False;
+ rVal.setValue(&bSet, ::getBooleanCppuType());
+ }
+ break;
+ case FIELD_PROP_PAR5:
+ rVal <<= ::rtl::OUString(aExpansion);
+ break;
+ default:
+ OSL_FAIL("illegal property");
+ }
+ if( nPart )
+ rVal <<= OUString(GetCmd().GetToken(nPart-1, sfx2::cTokenSeperator));
+ return true;
+}
+
+bool SwDDEFieldType::PutValue( const uno::Any& rVal, sal_uInt16 nWhichId )
+{
+ sal_uInt8 nPart = 0;
+ switch( nWhichId )
+ {
+ case FIELD_PROP_PAR2: nPart = 3; break;
+ case FIELD_PROP_PAR4: nPart = 2; break;
+ case FIELD_PROP_SUBTYPE: nPart = 1; break;
+ case FIELD_PROP_BOOL1:
+ SetType( static_cast<sal_uInt16>(*(sal_Bool*)rVal.getValue() ?
+ sfx2::LINKUPDATE_ALWAYS :
+ sfx2::LINKUPDATE_ONCALL ) );
+ break;
+ case FIELD_PROP_PAR5:
+ {
+ ::rtl::OUString sTemp;
+ rVal >>= sTemp;
+ aExpansion = sTemp;
+ }
+ break;
+ default:
+ OSL_FAIL("illegal property");
+ }
+ if( nPart )
+ {
+ String sTmp, sCmd( GetCmd() );
+ while(3 > sCmd.GetTokenCount(sfx2::cTokenSeperator))
+ sCmd += sfx2::cTokenSeperator;
+ sCmd.SetToken( nPart-1, sfx2::cTokenSeperator, ::GetString( rVal, sTmp ) );
+ SetCmd( sCmd );
+ }
+ return true;
+}
+
+SwDDEField::SwDDEField( SwDDEFieldType* pInitType )
+ : SwField(pInitType)
+{
+}
+
+SwDDEField::~SwDDEField()
+{
+ if( GetTyp()->IsLastDepend() )
+ ((SwDDEFieldType*)GetTyp())->Disconnect();
+}
+
+String SwDDEField::Expand() const
+{
+ xub_StrLen nPos;
+ String aStr( ((SwDDEFieldType*)GetTyp())->GetExpansion() );
+
+ aStr.EraseAllChars( '\r' );
+ while( (nPos = aStr.Search( '\t' )) != STRING_NOTFOUND )
+ aStr.SetChar( nPos, ' ' );
+ while( (nPos = aStr.Search( '\n' )) != STRING_NOTFOUND )
+ aStr.SetChar( nPos, '|' );
+ if( aStr.Len() && ( aStr.GetChar( aStr.Len()-1 ) == '|') )
+ aStr.Erase( aStr.Len()-1, 1 );
+ return aStr;
+}
+
+SwField* SwDDEField::Copy() const
+{
+ return new SwDDEField((SwDDEFieldType*)GetTyp());
+}
+
+/*--------------------------------------------------------------------
+ Beschreibung: Parameter des Typen erfragen
+ Name
+ --------------------------------------------------------------------*/
+const String& SwDDEField::GetPar1() const
+{
+ return ((SwDDEFieldType*)GetTyp())->GetName();
+}
+
+/*--------------------------------------------------------------------
+ Beschreibung: Parameter des Typen erfragen
+ Commando
+ --------------------------------------------------------------------*/
+String SwDDEField::GetPar2() const
+{
+ return ((SwDDEFieldType*)GetTyp())->GetCmd();
+}
+
+void SwDDEField::SetPar2(const String& rStr)
+{
+ ((SwDDEFieldType*)GetTyp())->SetCmd(rStr);
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/fields/ddetbl.cxx b/sw/source/core/fields/ddetbl.cxx
new file mode 100644
index 000000000000..e520cdbda4f2
--- /dev/null
+++ b/sw/source/core/fields/ddetbl.cxx
@@ -0,0 +1,199 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+
+#include <frmfmt.hxx>
+#include <doc.hxx>
+#include <index.hxx>
+#include <ndtxt.hxx>
+#include <swtable.hxx>
+#include <swddetbl.hxx>
+#include <ddefld.hxx> // fuer den FieldType
+#include <ndindex.hxx>
+#include <fldupde.hxx>
+#include <swtblfmt.hxx>
+#include <fieldhint.hxx>
+
+TYPEINIT1( SwDDETable, SwTable );
+
+ // Constructor movet alle Lines/Boxen aus der SwTable zu sich.
+ // Die SwTable ist danach Leer und muss geloescht werden.
+SwDDETable::SwDDETable( SwTable& rTable, SwDDEFieldType* pDDEType,
+ sal_Bool bUpdate )
+ : SwTable( rTable ), aDepend( this, pDDEType )
+{
+ // Kopiere/move die Daten der Tabelle
+ aSortCntBoxes.Insert( &rTable.GetTabSortBoxes(), 0,
+ rTable.GetTabSortBoxes().Count() ); // move die Inh. Boxen
+ rTable.GetTabSortBoxes().Remove( (sal_uInt16)0, rTable.GetTabSortBoxes().Count() );
+
+ aLines.Insert( &rTable.GetTabLines(),0 ); // move die Lines
+ rTable.GetTabLines().Remove( 0, rTable.GetTabLines().Count() );
+
+ if( aLines.Count() )
+ {
+ const SwNode& rNd = *GetTabSortBoxes()[0]->GetSttNd();
+ if( rNd.GetNodes().IsDocNodes() )
+ {
+ // mba: swclient refactoring - this code shouldn't have done anything!
+ // the ModifyLock Flag is evaluated in SwModify only, though it was accessible via SwClient
+ // This has been fixed now
+// aDepend.LockModify();
+ pDDEType->IncRefCnt();
+// aDepend.UnlockModify();
+
+ // Setzen der Werte in die einzelnen Boxen
+ // update box content only if update flag is set (false in import)
+ if (bUpdate)
+ ChangeContent();
+ }
+ }
+}
+
+SwDDETable::~SwDDETable()
+{
+ SwDDEFieldType* pFldTyp = (SwDDEFieldType*)aDepend.GetRegisteredIn();
+ SwDoc* pDoc = GetFrmFmt()->GetDoc();
+ if( !pDoc->IsInDtor() && aLines.Count() &&
+ GetTabSortBoxes()[0]->GetSttNd()->GetNodes().IsDocNodes() )
+ pFldTyp->DecRefCnt();
+
+ // sind wir der letzte Abhaengige vom "geloeschten Feld" dann loesche dieses
+ if( pFldTyp->IsDeleted() && pFldTyp->IsLastDepend() )
+ {
+ pFldTyp->Remove( &aDepend );
+ delete pFldTyp;
+ }
+}
+
+void SwDDETable::Modify( const SfxPoolItem* pOld, const SfxPoolItem* pNew )
+{
+ if( pNew && RES_UPDATEDDETBL == pNew->Which() )
+ ChangeContent();
+ else
+ SwTable::Modify( pOld, pNew );
+}
+
+void SwDDETable::SwClientNotify( const SwModify&, const SfxHint& rHint )
+{
+ const SwFieldHint* pHint = dynamic_cast<const SwFieldHint*>( &rHint );
+ if ( pHint )
+ // replace DDETable by real table
+ NoDDETable();
+}
+
+void SwDDETable::ChangeContent()
+{
+ OSL_ENSURE( GetFrmFmt(), "Kein FrameFormat" );
+
+ // Stehen wir im richtigen NodesArray (Wegen UNDO)
+ if( !aLines.Count() )
+ return;
+ OSL_ENSURE( GetTabSortBoxes().Count(), "Tabelle ohne Inhalt?" );
+ if( !GetTabSortBoxes()[0]->GetSttNd()->GetNodes().IsDocNodes() )
+ return;
+
+ // zugriff auf den DDEFldType
+ SwDDEFieldType* pDDEType = (SwDDEFieldType*)aDepend.GetRegisteredIn();
+
+ String aExpand = pDDEType->GetExpansion();
+ aExpand.EraseAllChars( '\r' );
+
+ for( sal_uInt16 n = 0; n < aLines.Count(); ++n )
+ {
+ String aLine = aExpand.GetToken( n, '\n' );
+ SwTableLine* pLine = aLines[ n ];
+ for( sal_uInt16 i = 0; i < pLine->GetTabBoxes().Count(); ++i )
+ {
+ SwTableBox* pBox = pLine->GetTabBoxes()[ i ];
+ OSL_ENSURE( pBox->GetSttIdx(), "keine InhaltsBox" );
+ SwNodeIndex aNdIdx( *pBox->GetSttNd(), 1 );
+ SwTxtNode* pTxtNode = aNdIdx.GetNode().GetTxtNode();
+ OSL_ENSURE( pTxtNode, "Kein Node" );
+ SwIndex aCntIdx( pTxtNode, 0 );
+ pTxtNode->EraseText( aCntIdx );
+ pTxtNode->InsertText( aLine.GetToken( i, '\t' ), aCntIdx );
+
+ SwTableBoxFmt* pBoxFmt = (SwTableBoxFmt*)pBox->GetFrmFmt();
+ pBoxFmt->LockModify();
+ pBoxFmt->ResetFmtAttr( RES_BOXATR_VALUE );
+ pBoxFmt->UnlockModify();
+ }
+ }
+
+ const IDocumentSettingAccess* pIDSA = GetFrmFmt()->getIDocumentSettingAccess();
+ SwDoc* pDoc = GetFrmFmt()->GetDoc();
+ if( AUTOUPD_FIELD_AND_CHARTS == pIDSA->getFieldUpdateFlags(true) )
+ pDoc->SetFieldsDirty( true, NULL, 0 );
+}
+
+SwDDEFieldType* SwDDETable::GetDDEFldType()
+{
+ return (SwDDEFieldType*)aDepend.GetRegisteredIn();
+}
+
+sal_Bool SwDDETable::NoDDETable()
+{
+ // suche den TabellenNode
+ OSL_ENSURE( GetFrmFmt(), "Kein FrameFormat" );
+ SwDoc* pDoc = GetFrmFmt()->GetDoc();
+
+ // Stehen wir im richtigen NodesArray (Wegen UNDO)
+ if( !aLines.Count() )
+ return sal_False;
+ OSL_ENSURE( GetTabSortBoxes().Count(), "Tabelle ohne Inhalt?" );
+ SwNode* pNd = (SwNode*)GetTabSortBoxes()[0]->GetSttNd();
+ if( !pNd->GetNodes().IsDocNodes() )
+ return sal_False;
+
+ SwTableNode* pTblNd = pNd->FindTableNode();
+ OSL_ENSURE( pTblNd, "wo steht denn die Tabelle ?");
+
+ SwTable* pNewTbl = new SwTable( *this );
+
+ // Kopiere/move die Daten der Tabelle
+ pNewTbl->GetTabSortBoxes().Insert( &GetTabSortBoxes(), 0,
+ GetTabSortBoxes().Count() ); // move die Inh. Boxen
+ GetTabSortBoxes().Remove( (sal_uInt16)0, GetTabSortBoxes().Count() );
+
+ pNewTbl->GetTabLines().Insert( &GetTabLines(),0 ); // move die Lines
+ GetTabLines().Remove( 0, GetTabLines().Count() );
+
+ if( pDoc->GetCurrentViewShell() ) //swmod 071108//swmod 071225
+ ((SwDDEFieldType*)aDepend.GetRegisteredIn())->DecRefCnt();
+
+ pTblNd->SetNewTable( pNewTbl ); // setze die Tabelle
+
+ return sal_True;
+}
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/fields/docufld.cxx b/sw/source/core/fields/docufld.cxx
new file mode 100644
index 000000000000..cf340a808417
--- /dev/null
+++ b/sw/source/core/fields/docufld.cxx
@@ -0,0 +1,2603 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+#include <textapi.hxx>
+
+#include <tools/pstm.hxx>
+#include <hintids.hxx>
+#include <com/sun/star/text/XText.hpp>
+#include <com/sun/star/script/XTypeConverter.hpp>
+#include <com/sun/star/text/SetVariableType.hpp>
+#include <com/sun/star/text/XTextFieldsSupplier.hpp>
+#include <com/sun/star/text/UserDataPart.hpp>
+#include <com/sun/star/text/ChapterFormat.hpp>
+#include <com/sun/star/text/XTextField.hpp>
+#include <com/sun/star/text/PlaceholderType.hpp>
+#include <com/sun/star/text/TemplateDisplayFormat.hpp>
+#include <com/sun/star/text/UserFieldFormat.hpp>
+#include <com/sun/star/text/PageNumberType.hpp>
+#include <com/sun/star/text/ReferenceFieldPart.hpp>
+#include <com/sun/star/text/FilenameDisplayFormat.hpp>
+#include <com/sun/star/text/XDependentTextField.hpp>
+#include <com/sun/star/text/DocumentStatistic.hpp>
+#include <com/sun/star/document/XDocumentPropertiesSupplier.hpp>
+#include <com/sun/star/document/XDocumentProperties.hpp>
+#include <com/sun/star/util/Date.hpp>
+#include <com/sun/star/util/Duration.hpp>
+#include <unotools/localedatawrapper.hxx>
+#include <editeng/unolingu.hxx>
+#include <comphelper/processfactory.hxx>
+#include <comphelper/types.hxx>
+#include <comphelper/string.hxx>
+#include <tools/urlobj.hxx>
+#include <vcl/svapp.hxx>
+#include <svl/urihelper.hxx>
+#include <unotools/useroptions.hxx>
+#include <unotools/syslocale.hxx>
+#include <svl/zforlist.hxx>
+
+#include <tools/time.hxx>
+#include <tools/datetime.hxx>
+
+#include <com/sun/star/beans/PropertyAttribute.hpp>
+#include <com/sun/star/util/DateTime.hpp>
+#include <com/sun/star/util/Time.hpp>
+
+#include <tools/shl.hxx>
+#include <swmodule.hxx>
+#include <sfx2/app.hxx>
+#include <sfx2/docfile.hxx>
+#include <sfx2/doctempl.hxx>
+#include <fmtfld.hxx>
+#include <txtfld.hxx>
+#include <charfmt.hxx>
+#include <docstat.hxx>
+#include <pagedesc.hxx>
+#include <fmtpdsc.hxx>
+#include <doc.hxx>
+#include <rootfrm.hxx> // AuthorField
+#include <pagefrm.hxx> //
+#include <cntfrm.hxx> //
+#include <pam.hxx>
+#include <viewsh.hxx>
+#include <dbmgr.hxx>
+#include <shellres.hxx>
+#include <docufld.hxx>
+#include <flddat.hxx>
+#include <docfld.hxx>
+#include <ndtxt.hxx>
+#include <expfld.hxx>
+#include <poolfmt.hxx>
+#include <docsh.hxx>
+#include <unofldmid.h>
+#include <swunohelper.hxx>
+#include <comcore.hrc>
+
+#include <editeng/outliner.hxx>
+#include <editeng/outlobj.hxx>
+#include <switerator.hxx>
+
+#define URL_DECODE INetURLObject::DECODE_UNAMBIGUOUS
+
+using ::rtl::OUString;
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::uno;
+using namespace nsSwDocInfoSubType;
+
+/*--------------------------------------------------------------------
+ Beschreibung: SwPageNumberFieldType
+ --------------------------------------------------------------------*/
+
+SwPageNumberFieldType::SwPageNumberFieldType()
+ : SwFieldType( RES_PAGENUMBERFLD ),
+ nNumberingType( SVX_NUM_ARABIC ),
+ nNum( 0 ),
+ nMax( USHRT_MAX ),
+ bVirtuell( sal_False )
+{
+}
+
+String& SwPageNumberFieldType::Expand( sal_uInt32 nFmt, short nOff,
+ const String& rUserStr, String& rRet ) const
+{
+ sal_uInt32 nTmpFmt = (SVX_NUM_PAGEDESC == nFmt) ? (sal_uInt32)nNumberingType : nFmt;
+ long nTmp = nNum + nOff;
+
+ if( 0 >= nTmp || SVX_NUM_NUMBER_NONE == nTmpFmt || (!bVirtuell && nTmp > nMax) )
+ rRet = aEmptyStr;
+ else if( SVX_NUM_CHAR_SPECIAL == nTmpFmt )
+ rRet = rUserStr;
+ else
+ rRet = FormatNumber( (sal_uInt16)nTmp, nTmpFmt );
+ return rRet;
+}
+
+SwFieldType* SwPageNumberFieldType::Copy() const
+{
+ SwPageNumberFieldType *pTmp = new SwPageNumberFieldType();
+
+ pTmp->nNum = nNum;
+ pTmp->nMax = nMax;
+ pTmp->nNumberingType = nNumberingType;
+ pTmp->bVirtuell = bVirtuell;
+
+ return pTmp;
+}
+
+/*--------------------------------------------------------------------
+ Beschreibung: Verschiedene Expandierung
+ --------------------------------------------------------------------*/
+
+void SwPageNumberFieldType::ChangeExpansion( SwDoc* pDoc, sal_uInt16 nPage,
+ sal_uInt16 nNumPages, sal_Bool bVirt,
+ const sal_Int16* pNumFmt )
+{
+ nNum = nPage;
+ nMax = nNumPages;
+ if( pNumFmt )
+ nNumberingType = *pNumFmt;
+
+ bVirtuell = sal_False;
+ if( bVirt )
+ {
+ // dann muss das Flag ueberprueft werden, denn das Layout setzt
+ // es NIE zurueck
+ const SfxItemPool &rPool = pDoc->GetAttrPool();
+ const SwFmtPageDesc *pDesc;
+ sal_uInt32 nMaxItems = rPool.GetItemCount2( RES_PAGEDESC );
+ for( sal_uInt32 n = 0; n < nMaxItems; ++n )
+ if( 0 != (pDesc = (SwFmtPageDesc*)rPool.GetItem2( RES_PAGEDESC, n ) )
+ && pDesc->GetNumOffset() && pDesc->GetDefinedIn() )
+ {
+ SwCntntNode* pNd = PTR_CAST( SwCntntNode, pDesc->GetDefinedIn() );
+ if( pNd )
+ {
+ if ( SwIterator<SwFrm,SwCntntNode>::FirstElement(*pNd) )
+ bVirtuell = sal_True;
+ }
+ else if( pDesc->GetDefinedIn()->ISA( SwFmt ))
+ {
+ SwAutoFmtGetDocNode aGetHt( &pDoc->GetNodes() );
+ bVirtuell = !pDesc->GetDefinedIn()->GetInfo( aGetHt );
+ break;
+ }
+ }
+ }
+}
+
+/*--------------------------------------------------------------------
+ Beschreibung: SwPageNumberField
+ --------------------------------------------------------------------*/
+
+SwPageNumberField::SwPageNumberField(SwPageNumberFieldType* pTyp,
+ sal_uInt16 nSub, sal_uInt32 nFmt, short nOff)
+ : SwField(pTyp, nFmt), nSubType(nSub), nOffset(nOff)
+{
+}
+
+String SwPageNumberField::Expand() const
+{
+ String sRet;
+ SwPageNumberFieldType* pFldType = (SwPageNumberFieldType*)GetTyp();
+
+ if( PG_NEXT == nSubType && 1 != nOffset )
+ {
+ if( pFldType->Expand( GetFormat(), 1, sUserStr, sRet ).Len() )
+ pFldType->Expand( GetFormat(), nOffset, sUserStr, sRet );
+ }
+ else if( PG_PREV == nSubType && -1 != nOffset )
+ {
+ if( pFldType->Expand( GetFormat(), -1, sUserStr, sRet ).Len() )
+ pFldType->Expand( GetFormat(), nOffset, sUserStr, sRet );
+ }
+ else
+ pFldType->Expand( GetFormat(), nOffset, sUserStr, sRet );
+ return sRet;
+}
+
+SwField* SwPageNumberField::Copy() const
+{
+ SwPageNumberField *pTmp =
+ new SwPageNumberField((SwPageNumberFieldType*)GetTyp(), nSubType, GetFormat(), nOffset);
+ pTmp->SetLanguage( GetLanguage() );
+ pTmp->SetUserString( sUserStr );
+ return pTmp;
+}
+
+String SwPageNumberField::GetPar2() const
+{
+ return String::CreateFromInt32(nOffset);
+}
+
+void SwPageNumberField::SetPar2(const String& rStr)
+{
+ nOffset = (short)rStr.ToInt32();
+}
+
+sal_uInt16 SwPageNumberField::GetSubType() const
+{
+ return nSubType;
+}
+
+bool SwPageNumberField::QueryValue( uno::Any& rAny, sal_uInt16 nWhichId ) const
+{
+ switch( nWhichId )
+ {
+ case FIELD_PROP_FORMAT:
+ rAny <<= (sal_Int16)GetFormat();
+ break;
+ case FIELD_PROP_USHORT1:
+ rAny <<= nOffset;
+ break;
+ case FIELD_PROP_SUBTYPE:
+ {
+ text::PageNumberType eType;
+ eType = text::PageNumberType_CURRENT;
+ if(nSubType == PG_PREV)
+ eType = text::PageNumberType_PREV;
+ else if(nSubType == PG_NEXT)
+ eType = text::PageNumberType_NEXT;
+ rAny.setValue(&eType, ::getCppuType((const text::PageNumberType*)0));
+ }
+ break;
+ case FIELD_PROP_PAR1:
+ rAny <<= OUString(sUserStr);
+ break;
+
+ default:
+ OSL_FAIL("illegal property");
+ }
+ return true;
+}
+
+bool SwPageNumberField::PutValue( const uno::Any& rAny, sal_uInt16 nWhichId )
+{
+ bool bRet = true;
+ sal_Int16 nSet = 0;
+ switch( nWhichId )
+ {
+ case FIELD_PROP_FORMAT:
+ rAny >>= nSet;
+
+ // TODO: woher kommen die defines?
+ if(nSet <= SVX_NUM_PAGEDESC )
+ SetFormat(nSet);
+ else {
+ }
+ break;
+ case FIELD_PROP_USHORT1:
+ rAny >>= nSet;
+ nOffset = nSet;
+ break;
+ case FIELD_PROP_SUBTYPE:
+ switch( SWUnoHelper::GetEnumAsInt32( rAny ) )
+ {
+ case text::PageNumberType_CURRENT:
+ nSubType = PG_RANDOM;
+ break;
+ case text::PageNumberType_PREV:
+ nSubType = PG_PREV;
+ break;
+ case text::PageNumberType_NEXT:
+ nSubType = PG_NEXT;
+ break;
+ default:
+ bRet = false;
+ }
+ break;
+ case FIELD_PROP_PAR1:
+ ::GetString( rAny, sUserStr );
+ break;
+
+ default:
+ OSL_FAIL("illegal property");
+ }
+ return bRet;
+}
+/*--------------------------------------------------------------------
+ Beschreibung: SwAuthorFieldType
+ --------------------------------------------------------------------*/
+
+SwAuthorFieldType::SwAuthorFieldType()
+ : SwFieldType( RES_AUTHORFLD )
+{
+}
+
+String SwAuthorFieldType::Expand(sal_uLong nFmt) const
+{
+ String sRet;
+ SvtUserOptions& rOpt = SW_MOD()->GetUserOptions();
+ if((nFmt & 0xff) == AF_NAME)
+ sRet = rOpt.GetFullName();
+ else
+ sRet = rOpt.GetID();
+ return sRet;
+}
+
+SwFieldType* SwAuthorFieldType::Copy() const
+{
+ return new SwAuthorFieldType;
+}
+
+/*--------------------------------------------------------------------
+ Beschreibung: SwAuthorField
+ --------------------------------------------------------------------*/
+
+SwAuthorField::SwAuthorField(SwAuthorFieldType* pTyp, sal_uInt32 nFmt)
+ : SwField(pTyp, nFmt)
+{
+ aContent = ((SwAuthorFieldType*)GetTyp())->Expand(GetFormat());
+}
+
+String SwAuthorField::Expand() const
+{
+ if (!IsFixed())
+ ((SwAuthorField*)this)->aContent =
+ ((SwAuthorFieldType*)GetTyp())->Expand(GetFormat());
+
+ return aContent;
+}
+
+SwField* SwAuthorField::Copy() const
+{
+ SwAuthorField *pTmp = new SwAuthorField( (SwAuthorFieldType*)GetTyp(),
+ GetFormat());
+ pTmp->SetExpansion(aContent);
+ return pTmp;
+}
+
+bool SwAuthorField::QueryValue( uno::Any& rAny, sal_uInt16 nWhichId ) const
+{
+ bool bVal;
+ switch( nWhichId )
+ {
+ case FIELD_PROP_BOOL1:
+ bVal = (GetFormat() & 0xff) == AF_NAME;
+ rAny.setValue(&bVal, ::getBooleanCppuType());
+ break;
+
+ case FIELD_PROP_BOOL2:
+ bVal = IsFixed();
+ rAny.setValue(&bVal, ::getBooleanCppuType());
+ break;
+
+ case FIELD_PROP_PAR1:
+ rAny <<= rtl::OUString(GetContent());
+ break;
+
+ default:
+ OSL_FAIL("illegal property");
+ }
+ return true;
+}
+
+bool SwAuthorField::PutValue( const uno::Any& rAny, sal_uInt16 nWhichId )
+{
+ switch( nWhichId )
+ {
+ case FIELD_PROP_BOOL1:
+ SetFormat( *(sal_Bool*)rAny.getValue() ? AF_NAME : AF_SHORTCUT );
+ break;
+
+ case FIELD_PROP_BOOL2:
+ if( *(sal_Bool*)rAny.getValue() )
+ SetFormat( GetFormat() | AF_FIXED);
+ else
+ SetFormat( GetFormat() & ~AF_FIXED);
+ break;
+
+ case FIELD_PROP_PAR1:
+ ::GetString( rAny, aContent );
+ break;
+
+ default:
+ OSL_FAIL("illegal property");
+ }
+ return true;
+}
+
+/*--------------------------------------------------------------------
+ Beschreibung: SwFileNameFieldType
+ --------------------------------------------------------------------*/
+
+SwFileNameFieldType::SwFileNameFieldType(SwDoc *pDocument)
+ : SwFieldType( RES_FILENAMEFLD )
+{
+ pDoc = pDocument;
+}
+
+String SwFileNameFieldType::Expand(sal_uLong nFmt) const
+{
+ String aRet;
+ const SwDocShell* pDShell = pDoc->GetDocShell();
+ if( pDShell && pDShell->HasName() )
+ {
+ const INetURLObject& rURLObj = pDShell->GetMedium()->GetURLObject();
+ switch( nFmt & ~FF_FIXED )
+ {
+ case FF_PATH:
+ {
+ if( INET_PROT_FILE == rURLObj.GetProtocol() )
+ {
+ INetURLObject aTemp(rURLObj);
+ aTemp.removeSegment();
+ // last slash should belong to the pathname
+ aRet = aTemp.PathToFileName();
+ }
+ else
+ {
+ aRet = URIHelper::removePassword(
+ rURLObj.GetMainURL( INetURLObject::NO_DECODE ),
+ INetURLObject::WAS_ENCODED, URL_DECODE );
+ aRet.Erase( aRet.Search( String(rURLObj.GetLastName(
+ URL_DECODE )) ) );
+ }
+ }
+ break;
+
+ case FF_NAME:
+ aRet = rURLObj.GetLastName( INetURLObject::DECODE_WITH_CHARSET );
+ break;
+
+ case FF_NAME_NOEXT:
+ aRet = rURLObj.GetBase();
+ break;
+
+ default:
+ if( INET_PROT_FILE == rURLObj.GetProtocol() )
+ aRet = rURLObj.GetFull();
+ else
+ aRet = URIHelper::removePassword(
+ rURLObj.GetMainURL( INetURLObject::NO_DECODE ),
+ INetURLObject::WAS_ENCODED, URL_DECODE );
+ }
+ }
+ return aRet;
+}
+
+SwFieldType* SwFileNameFieldType::Copy() const
+{
+ SwFieldType *pTmp = new SwFileNameFieldType(pDoc);
+ return pTmp;
+}
+/*--------------------------------------------------------------------
+ Beschreibung: SwFileNameField
+ --------------------------------------------------------------------*/
+
+SwFileNameField::SwFileNameField(SwFileNameFieldType* pTyp, sal_uInt32 nFmt)
+ : SwField(pTyp, nFmt)
+{
+ aContent = ((SwFileNameFieldType*)GetTyp())->Expand(GetFormat());
+}
+
+String SwFileNameField::Expand() const
+{
+ if (!IsFixed())
+ ((SwFileNameField*)this)->aContent = ((SwFileNameFieldType*)GetTyp())->Expand(GetFormat());
+
+ return aContent;
+}
+
+SwField* SwFileNameField::Copy() const
+{
+ SwFileNameField *pTmp =
+ new SwFileNameField((SwFileNameFieldType*)GetTyp(), GetFormat());
+ pTmp->SetExpansion(aContent);
+
+ return pTmp;
+}
+
+bool SwFileNameField::QueryValue( uno::Any& rAny, sal_uInt16 nWhichId ) const
+{
+ switch( nWhichId )
+ {
+ case FIELD_PROP_FORMAT:
+ {
+ sal_Int16 nRet;
+ switch( GetFormat() &(~FF_FIXED) )
+ {
+ case FF_PATH:
+ nRet = text::FilenameDisplayFormat::PATH;
+ break;
+ case FF_NAME_NOEXT:
+ nRet = text::FilenameDisplayFormat::NAME;
+ break;
+ case FF_NAME:
+ nRet = text::FilenameDisplayFormat::NAME_AND_EXT;
+ break;
+ default: nRet = text::FilenameDisplayFormat::FULL;
+ }
+ rAny <<= nRet;
+ }
+ break;
+
+ case FIELD_PROP_BOOL2:
+ {
+ sal_Bool bVal = IsFixed();
+ rAny.setValue(&bVal, ::getBooleanCppuType());
+ }
+ break;
+
+ case FIELD_PROP_PAR3:
+ rAny <<= OUString(GetContent());
+ break;
+ default:
+ OSL_FAIL("illegal property");
+ }
+ return true;
+}
+
+bool SwFileNameField::PutValue( const uno::Any& rAny, sal_uInt16 nWhichId )
+{
+ switch( nWhichId )
+ {
+ case FIELD_PROP_FORMAT:
+ {
+ //JP 24.10.2001: int32 because in UnoField.cxx a putvalue is
+ // called with a int32 value! But normally we need
+ // here only a int16
+ sal_Int32 nType = 0;
+ rAny >>= nType;
+ sal_Bool bFixed = IsFixed();
+ switch( nType )
+ {
+ case text::FilenameDisplayFormat::PATH:
+ nType = FF_PATH;
+ break;
+ case text::FilenameDisplayFormat::NAME:
+ nType = FF_NAME_NOEXT;
+ break;
+ case text::FilenameDisplayFormat::NAME_AND_EXT:
+ nType = FF_NAME;
+ break;
+ default: nType = FF_PATHNAME;
+ }
+ if(bFixed)
+ nType |= FF_FIXED;
+ SetFormat(nType);
+ }
+ break;
+
+ case FIELD_PROP_BOOL2:
+ if( *(sal_Bool*)rAny.getValue() )
+ SetFormat( GetFormat() | FF_FIXED);
+ else
+ SetFormat( GetFormat() & ~FF_FIXED);
+ break;
+
+ case FIELD_PROP_PAR3:
+ ::GetString( rAny, aContent );
+ break;
+
+ default:
+ OSL_FAIL("illegal property");
+ }
+ return true;
+}
+/*--------------------------------------------------------------------
+ Beschreibung: SwTemplNameFieldType
+ --------------------------------------------------------------------*/
+
+SwTemplNameFieldType::SwTemplNameFieldType(SwDoc *pDocument)
+ : SwFieldType( RES_TEMPLNAMEFLD )
+{
+ pDoc = pDocument;
+}
+
+String SwTemplNameFieldType::Expand(sal_uLong nFmt) const
+{
+ OSL_ENSURE( nFmt < FF_END, "Expand: kein guelt. Fmt!" );
+
+ String aRet;
+ SwDocShell *pDocShell(pDoc->GetDocShell());
+ DBG_ASSERT(pDocShell, "no SwDocShell");
+ if (pDocShell) {
+ uno::Reference<document::XDocumentPropertiesSupplier> xDPS(
+ pDocShell->GetModel(), uno::UNO_QUERY_THROW);
+ uno::Reference<document::XDocumentProperties> xDocProps(
+ xDPS->getDocumentProperties());
+ DBG_ASSERT(xDocProps.is(), "Doc has no DocumentProperties");
+
+ if( FF_UI_NAME == nFmt )
+ aRet = xDocProps->getTemplateName();
+ else if( xDocProps->getTemplateURL().getLength() )
+ {
+ if( FF_UI_RANGE == nFmt )
+ {
+ // fuers besorgen vom RegionNamen !!
+ SfxDocumentTemplates aFac;
+ aFac.Construct();
+ String sTmp;
+ aFac.GetLogicNames( xDocProps->getTemplateURL(), aRet, sTmp );
+ }
+ else
+ {
+ INetURLObject aPathName( xDocProps->getTemplateURL() );
+ if( FF_NAME == nFmt )
+ aRet = aPathName.GetName(URL_DECODE);
+ else if( FF_NAME_NOEXT == nFmt )
+ aRet = aPathName.GetBase();
+ else
+ {
+ if( FF_PATH == nFmt )
+ {
+ aPathName.removeSegment();
+ aRet = aPathName.GetFull();
+ }
+ else
+ aRet = aPathName.GetFull();
+ }
+ }
+ }
+ }
+ return aRet;
+}
+
+SwFieldType* SwTemplNameFieldType::Copy() const
+{
+ SwFieldType *pTmp = new SwTemplNameFieldType(pDoc);
+ return pTmp;
+}
+/*--------------------------------------------------------------------
+ Beschreibung: SwTemplNameField
+ --------------------------------------------------------------------*/
+
+SwTemplNameField::SwTemplNameField(SwTemplNameFieldType* pTyp, sal_uInt32 nFmt)
+ : SwField(pTyp, nFmt)
+{}
+
+String SwTemplNameField::Expand() const
+{
+ return((SwTemplNameFieldType*)GetTyp())->Expand(GetFormat());
+}
+
+SwField* SwTemplNameField::Copy() const
+{
+ SwTemplNameField *pTmp =
+ new SwTemplNameField((SwTemplNameFieldType*)GetTyp(), GetFormat());
+ return pTmp;
+}
+
+bool SwTemplNameField::QueryValue( uno::Any& rAny, sal_uInt16 nWhichId ) const
+{
+ switch ( nWhichId )
+ {
+ case FIELD_PROP_FORMAT:
+ {
+ sal_Int16 nRet;
+ switch( GetFormat() )
+ {
+ case FF_PATH: nRet = text::FilenameDisplayFormat::PATH; break;
+ case FF_NAME_NOEXT: nRet = text::FilenameDisplayFormat::NAME; break;
+ case FF_NAME: nRet = text::FilenameDisplayFormat::NAME_AND_EXT; break;
+ case FF_UI_RANGE: nRet = text::TemplateDisplayFormat::AREA; break;
+ case FF_UI_NAME: nRet = text::TemplateDisplayFormat::TITLE; break;
+ default: nRet = text::FilenameDisplayFormat::FULL;
+
+ }
+ rAny <<= nRet;
+ }
+ break;
+ default:
+ OSL_FAIL("illegal property");
+ }
+ return true;
+}
+
+bool SwTemplNameField::PutValue( const uno::Any& rAny, sal_uInt16 nWhichId )
+{
+ switch ( nWhichId )
+ {
+ case FIELD_PROP_FORMAT:
+ {
+ //JP 24.10.2001: int32 because in UnoField.cxx a putvalue is
+ // called with a int32 value! But normally we need
+ // here only a int16
+ sal_Int32 nType = 0;
+ rAny >>= nType;
+ switch( nType )
+ {
+ case text::FilenameDisplayFormat::PATH:
+ SetFormat(FF_PATH);
+ break;
+ case text::FilenameDisplayFormat::NAME:
+ SetFormat(FF_NAME_NOEXT);
+ break;
+ case text::FilenameDisplayFormat::NAME_AND_EXT:
+ SetFormat(FF_NAME);
+ break;
+ case text::TemplateDisplayFormat::AREA :
+ SetFormat(FF_UI_RANGE);
+ break;
+ case text::TemplateDisplayFormat::TITLE :
+ SetFormat(FF_UI_NAME);
+ break;
+ default: SetFormat(FF_PATHNAME);
+ }
+ }
+ break;
+ default:
+ OSL_FAIL("illegal property");
+ }
+ return true;
+}
+/*--------------------------------------------------------------------
+ Beschreibung: SwDocStatFieldType
+ --------------------------------------------------------------------*/
+
+SwDocStatFieldType::SwDocStatFieldType(SwDoc* pDocument)
+ : SwFieldType( RES_DOCSTATFLD ), nNumberingType( SVX_NUM_ARABIC )
+{
+ pDoc = pDocument;
+}
+
+String SwDocStatFieldType::Expand(sal_uInt16 nSubType, sal_uInt32 nFmt) const
+{
+ sal_uInt32 nVal = 0;
+ const SwDocStat& rDStat = pDoc->GetDocStat();
+ switch( nSubType )
+ {
+ case DS_TBL: nVal = rDStat.nTbl; break;
+ case DS_GRF: nVal = rDStat.nGrf; break;
+ case DS_OLE: nVal = rDStat.nOLE; break;
+ case DS_PARA: nVal = rDStat.nPara; break;
+ case DS_WORD: nVal = rDStat.nWord; break;
+ case DS_CHAR: nVal = rDStat.nChar; break;
+ case DS_PAGE:
+ if( pDoc->GetCurrentLayout() )//swmod 080218
+ ((SwDocStat &)rDStat).nPage = pDoc->GetCurrentLayout()->GetPageNum(); //swmod 080218
+ nVal = rDStat.nPage;
+ if( SVX_NUM_PAGEDESC == nFmt )
+ nFmt = (sal_uInt32)nNumberingType;
+ break;
+ default:
+ OSL_FAIL( "SwDocStatFieldType::Expand: unbekannter SubType" );
+ }
+
+ String sRet;
+ if( nVal <= SHRT_MAX )
+ sRet = FormatNumber( (sal_uInt16)nVal, nFmt );
+ else
+ sRet = String::CreateFromInt32( nVal );
+ return sRet;
+}
+
+SwFieldType* SwDocStatFieldType::Copy() const
+{
+ SwDocStatFieldType *pTmp = new SwDocStatFieldType(pDoc);
+ return pTmp;
+}
+
+/*--------------------------------------------------------------------
+ Beschreibung: SwDocStatFieldType
+ Aus historischen Gruenden steht in nFormat der
+ SubType
+ --------------------------------------------------------------------*/
+
+SwDocStatField::SwDocStatField(SwDocStatFieldType* pTyp, sal_uInt16 nSub, sal_uInt32 nFmt)
+ : SwField(pTyp, nFmt),
+ nSubType(nSub)
+{}
+
+String SwDocStatField::Expand() const
+{
+ return((SwDocStatFieldType*)GetTyp())->Expand(nSubType, GetFormat());
+}
+
+SwField* SwDocStatField::Copy() const
+{
+ SwDocStatField *pTmp = new SwDocStatField(
+ (SwDocStatFieldType*)GetTyp(), nSubType, GetFormat() );
+ return pTmp;
+}
+
+sal_uInt16 SwDocStatField::GetSubType() const
+{
+ return nSubType;
+}
+
+void SwDocStatField::SetSubType(sal_uInt16 nSub)
+{
+ nSubType = nSub;
+}
+
+void SwDocStatField::ChangeExpansion( const SwFrm* pFrm )
+{
+ if( DS_PAGE == nSubType && SVX_NUM_PAGEDESC == GetFormat() )
+ ((SwDocStatFieldType*)GetTyp())->SetNumFormat(
+ pFrm->FindPageFrm()->GetPageDesc()->GetNumType().GetNumberingType() );
+}
+
+bool SwDocStatField::QueryValue( uno::Any& rAny, sal_uInt16 nWhichId ) const
+{
+ switch ( nWhichId )
+ {
+ case FIELD_PROP_USHORT2:
+ rAny <<= (sal_Int16)GetFormat();
+ break;
+ default:
+ OSL_FAIL("illegal property");
+ }
+ return true;
+}
+
+bool SwDocStatField::PutValue( const uno::Any& rAny, sal_uInt16 nWhichId )
+{
+ bool bRet = false;
+ switch ( nWhichId )
+ {
+ case FIELD_PROP_USHORT2:
+ {
+ sal_Int16 nSet = 0;
+ rAny >>= nSet;
+ if(nSet <= SVX_NUM_CHARS_LOWER_LETTER_N &&
+ nSet != SVX_NUM_CHAR_SPECIAL &&
+ nSet != SVX_NUM_BITMAP)
+ {
+ SetFormat(nSet);
+ bRet = true;
+ }
+ }
+ break;
+
+ default:
+ OSL_FAIL("illegal property");
+ }
+ return bRet;
+}
+
+/*--------------------------------------------------------------------
+ Beschreibung: DokumentinfoFields
+ --------------------------------------------------------------------*/
+
+SwDocInfoFieldType::SwDocInfoFieldType(SwDoc* pDc)
+ : SwValueFieldType( pDc, RES_DOCINFOFLD )
+{
+}
+
+SwFieldType* SwDocInfoFieldType::Copy() const
+{
+ SwDocInfoFieldType* pTyp = new SwDocInfoFieldType(GetDoc());
+ return pTyp;
+}
+
+void lcl_GetLocalDataWrapper( sal_uLong nLang,
+ const LocaleDataWrapper **ppAppLocalData,
+ const LocaleDataWrapper **ppLocalData )
+{
+ SvtSysLocale aLocale;
+ *ppAppLocalData = &aLocale.GetLocaleData();
+ *ppLocalData = *ppAppLocalData;
+ if( nLang != SvxLocaleToLanguage( (*ppLocalData)->getLocale() ) )
+ *ppLocalData = new LocaleDataWrapper(
+ ::comphelper::getProcessServiceFactory(),
+ SvxCreateLocale( static_cast<LanguageType>(nLang) ) );
+}
+
+String SwDocInfoFieldType::Expand( sal_uInt16 nSub, sal_uInt32 nFormat,
+ sal_uInt16 nLang, const String& rName ) const
+{
+ String aStr;
+ const LocaleDataWrapper *pAppLocalData = 0, *pLocalData = 0;
+ SwDocShell *pDocShell(GetDoc()->GetDocShell());
+ DBG_ASSERT(pDocShell, "no SwDocShell");
+ if (!pDocShell) { return aStr; }
+
+ uno::Reference<document::XDocumentPropertiesSupplier> xDPS(
+ pDocShell->GetModel(), uno::UNO_QUERY_THROW);
+ uno::Reference<document::XDocumentProperties> xDocProps(
+ xDPS->getDocumentProperties());
+ DBG_ASSERT(xDocProps.is(), "Doc has no DocumentProperties");
+
+ sal_uInt16 nExtSub = nSub & 0xff00;
+ nSub &= 0xff; // ExtendedSubTypes nicht beachten
+
+ switch(nSub)
+ {
+ case DI_TITEL: aStr = xDocProps->getTitle(); break;
+ case DI_THEMA: aStr = xDocProps->getSubject(); break;
+ case DI_KEYS: aStr = ::comphelper::string::convertCommaSeparated(
+ xDocProps->getKeywords());
+ break;
+ case DI_COMMENT:aStr = xDocProps->getDescription(); break;
+ case DI_DOCNO: aStr = String::CreateFromInt32(
+ xDocProps->getEditingCycles() );
+ break;
+ case DI_EDIT:
+ if ( !nFormat )
+ {
+ lcl_GetLocalDataWrapper( nLang, &pAppLocalData, &pLocalData );
+ sal_Int32 dur = xDocProps->getEditingDuration();
+ aStr = pLocalData->getTime( Time(dur/3600, (dur%3600)/60, dur%60),
+ sal_False, sal_False);
+ }
+ else
+ {
+ sal_Int32 dur = xDocProps->getEditingDuration();
+ double fVal = Time(dur/3600, (dur%3600)/60, dur%60).GetTimeInDays();
+ aStr = ExpandValue(fVal, nFormat, nLang);
+ }
+ break;
+ case DI_CUSTOM:
+ {
+ ::rtl::OUString sVal;
+ try
+ {
+ uno::Any aAny;
+ uno::Reference < beans::XPropertySet > xSet(
+ xDocProps->getUserDefinedProperties(),
+ uno::UNO_QUERY_THROW);
+ aAny = xSet->getPropertyValue( rName );
+
+ uno::Reference < script::XTypeConverter > xConverter( comphelper::getProcessServiceFactory()
+ ->createInstance(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.script.Converter"))), uno::UNO_QUERY );
+ uno::Any aNew;
+ aNew = xConverter->convertToSimpleType( aAny, uno::TypeClass_STRING );
+ aNew >>= sVal;
+ }
+ catch (uno::Exception&) {}
+ return sVal;
+ }
+
+ default:
+ {
+ String aName( xDocProps->getAuthor() );
+ util::DateTime uDT( xDocProps->getCreationDate() );
+ Date aD(uDT.Day, uDT.Month, uDT.Year);
+ Time aT(uDT.Hours, uDT.Minutes, uDT.Seconds, uDT.HundredthSeconds);
+ DateTime aDate(aD,aT);
+ if( nSub == DI_CREATE )
+ ; // das wars schon!!
+ else if( nSub == DI_CHANGE )
+ {
+ aName = xDocProps->getModifiedBy();
+ uDT = xDocProps->getModificationDate();
+ Date bD(uDT.Day, uDT.Month, uDT.Year);
+ Time bT(uDT.Hours, uDT.Minutes, uDT.Seconds, uDT.HundredthSeconds);
+ DateTime bDate(bD,bT);
+ aDate = bDate;
+ }
+ else if( nSub == DI_PRINT )
+ {
+ aName = xDocProps->getPrintedBy();
+ uDT = xDocProps->getPrintDate();
+ Date bD(uDT.Day, uDT.Month, uDT.Year);
+ Time bT(uDT.Hours, uDT.Minutes, uDT.Seconds, uDT.HundredthSeconds);
+ DateTime bDate(bD,bT);
+ aDate = bDate;
+ }
+ else
+ break;
+
+ if (aDate.IsValid())
+ {
+ switch (nExtSub & ~DI_SUB_FIXED)
+ {
+ case DI_SUB_AUTHOR:
+ aStr = aName;
+ break;
+
+ case DI_SUB_TIME:
+ if (!nFormat)
+ {
+ lcl_GetLocalDataWrapper( nLang, &pAppLocalData,
+ &pLocalData );
+ aStr = pLocalData->getTime( aDate,
+ sal_False, sal_False);
+ }
+ else
+ {
+ // Numberformatter anwerfen!
+ double fVal = SwDateTimeField::GetDateTime( GetDoc(),
+ aDate);
+ aStr = ExpandValue(fVal, nFormat, nLang);
+ }
+ break;
+
+ case DI_SUB_DATE:
+ if (!nFormat)
+ {
+ lcl_GetLocalDataWrapper( nLang, &pAppLocalData,
+ &pLocalData );
+ aStr = pLocalData->getDate( aDate );
+ }
+ else
+ {
+ // Numberformatter anwerfen!
+ double fVal = SwDateTimeField::GetDateTime( GetDoc(),
+ aDate);
+ aStr = ExpandValue(fVal, nFormat, nLang);
+ }
+ break;
+ }
+ }
+ }
+ break;
+ }
+
+ if( pAppLocalData != pLocalData )
+ delete pLocalData;
+
+ return aStr;
+}
+
+SwDocInfoField::SwDocInfoField(SwDocInfoFieldType* pTyp, sal_uInt16 nSub, const String& rName, sal_uInt32 nFmt) :
+ SwValueField(pTyp, nFmt), nSubType(nSub)
+{
+ aName = rName;
+ aContent = ((SwDocInfoFieldType*)GetTyp())->Expand(nSubType, nFmt, GetLanguage(), aName);
+}
+
+SwDocInfoField::SwDocInfoField(SwDocInfoFieldType* pTyp, sal_uInt16 nSub, const String& rName, const String& rValue, sal_uInt32 nFmt) :
+ SwValueField(pTyp, nFmt), nSubType(nSub)
+{
+ aName = rName;
+ aContent = rValue;
+}
+
+
+template<class T>
+double lcl_TimeToDouble( const T& rTime )
+{
+ const double fMilliSecondsPerDay = 86400000.0;
+ return ((rTime.Hours*3600000)+(rTime.Minutes*60000)+(rTime.Seconds*1000)+(rTime.HundredthSeconds*10)) / fMilliSecondsPerDay;
+}
+
+template<class D>
+double lcl_DateToDouble( const D& rDate, const Date& rNullDate )
+{
+ long nDate = Date::DateToDays( rDate.Day, rDate.Month, rDate.Year );
+ long nNullDate = Date::DateToDays( rNullDate.GetDay(), rNullDate.GetMonth(), rNullDate.GetYear() );
+ return double( nDate - nNullDate );
+}
+
+String SwDocInfoField::Expand() const
+{
+ if ( ( nSubType & 0xFF ) == DI_CUSTOM )
+ {
+ // custom properties currently need special treatment
+ // we don't have a secure way to detect "real" custom properties in Word Import of text fields
+ // so we treat *every* unknown property as a custom property, even the "built-in" section in Word's document summary information stream
+ // as these properties have not been inserted when the document summary information was imported, we do it here
+ // this approach is still a lot better than the old one to import such fields as "user fields" and simple text
+ SwDocShell* pDocShell = GetDoc()->GetDocShell();
+ if( !pDocShell )
+ return aContent;
+ try
+ {
+ uno::Reference<document::XDocumentPropertiesSupplier> xDPS( pDocShell->GetModel(), uno::UNO_QUERY_THROW);
+ uno::Reference<document::XDocumentProperties> xDocProps( xDPS->getDocumentProperties());
+ uno::Reference < beans::XPropertySet > xSet( xDocProps->getUserDefinedProperties(), uno::UNO_QUERY_THROW);
+ uno::Reference < beans::XPropertySetInfo > xSetInfo = xSet->getPropertySetInfo();
+
+ uno::Any aAny;
+ if( xSetInfo->hasPropertyByName( aName ) )
+ aAny = xSet->getPropertyValue( aName );
+ if ( aAny.getValueType() != ::getVoidCppuType() )
+ {
+ // "void" type means that the property has not been inserted until now
+ if ( !IsFixed() )
+ {
+ // if the field is "fixed" we don't update it from the property
+ ::rtl::OUString sVal;
+ uno::Reference < script::XTypeConverter > xConverter( comphelper::getProcessServiceFactory()
+ ->createInstance(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.script.Converter"))), uno::UNO_QUERY );
+ util::Date aDate;
+ util::DateTime aDateTime;
+ util::Duration aDuration;
+ if( aAny >>= aDate)
+ {
+ SvNumberFormatter* pFormatter = pDocShell->GetDoc()->GetNumberFormatter();
+ Date* pNullDate = pFormatter->GetNullDate();
+ sVal = ExpandValue( lcl_DateToDouble<util::Date>( aDate, *pNullDate ), GetFormat(), GetLanguage());
+ }
+ else if( aAny >>= aDateTime )
+ {
+ double fDateTime = lcl_TimeToDouble<util::DateTime>( aDateTime );
+ SvNumberFormatter* pFormatter = pDocShell->GetDoc()->GetNumberFormatter();
+ Date* pNullDate = pFormatter->GetNullDate();
+ fDateTime += lcl_DateToDouble<util::DateTime>( aDateTime, *pNullDate );
+ sVal = ExpandValue( fDateTime, GetFormat(), GetLanguage());
+ }
+ else if( aAny >>= aDuration )
+ {
+ String sText(aDuration.Negative ? '-' : '+');
+ sText += ViewShell::GetShellRes()->sDurationFormat;
+ sText.SearchAndReplace(String::CreateFromAscii( "%1"), String::CreateFromInt32( aDuration.Years ) );
+ sText.SearchAndReplace(String::CreateFromAscii( "%2"), String::CreateFromInt32( aDuration.Months ) );
+ sText.SearchAndReplace(String::CreateFromAscii( "%3"), String::CreateFromInt32( aDuration.Days ) );
+ sText.SearchAndReplace(String::CreateFromAscii( "%4"), String::CreateFromInt32( aDuration.Hours ) );
+ sText.SearchAndReplace(String::CreateFromAscii( "%5"), String::CreateFromInt32( aDuration.Minutes) );
+ sText.SearchAndReplace(String::CreateFromAscii( "%6"), String::CreateFromInt32( aDuration.Seconds) );
+ sVal = sText;
+ }
+ else
+ {
+ uno::Any aNew = xConverter->convertToSimpleType( aAny, uno::TypeClass_STRING );
+ aNew >>= sVal;
+ }
+ ((SwDocInfoField*)this)->aContent = sVal;
+ }
+ }
+ }
+ catch (uno::Exception&) {}
+ }
+ else if ( !IsFixed() )
+ ((SwDocInfoField*)this)->aContent = ((SwDocInfoFieldType*)GetTyp())->Expand(nSubType, GetFormat(), GetLanguage(), aName);
+
+ return aContent;
+}
+
+String SwDocInfoField::GetFieldName() const
+{
+ String aStr(SwFieldType::GetTypeStr(GetTypeId()));
+ aStr += ':';
+
+ sal_uInt16 const nSub = nSubType & 0xff;
+
+ switch (nSub)
+ {
+ case DI_CUSTOM:
+ aStr += aName;
+ break;
+
+ default:
+ aStr += *ViewShell::GetShellRes()
+ ->aDocInfoLst[ nSub - DI_SUBTYPE_BEGIN ];
+ break;
+ }
+ if (IsFixed())
+ {
+ aStr += ' ';
+ aStr += ViewShell::GetShellRes()->aFixedStr;
+ }
+ return aStr;
+}
+
+SwField* SwDocInfoField::Copy() const
+{
+ SwDocInfoField* pFld = new SwDocInfoField((SwDocInfoFieldType*)GetTyp(), nSubType, aName, GetFormat());
+ pFld->SetAutomaticLanguage(IsAutomaticLanguage());
+ pFld->aContent = aContent;
+
+ return pFld;
+}
+
+sal_uInt16 SwDocInfoField::GetSubType() const
+{
+ return nSubType;
+}
+
+void SwDocInfoField::SetSubType(sal_uInt16 nSub)
+{
+ nSubType = nSub;
+}
+
+void SwDocInfoField::SetLanguage(sal_uInt16 nLng)
+{
+ if (!GetFormat())
+ SwField::SetLanguage(nLng);
+ else
+ SwValueField::SetLanguage(nLng);
+}
+
+bool SwDocInfoField::QueryValue( uno::Any& rAny, sal_uInt16 nWhichId ) const
+{
+ switch( nWhichId )
+ {
+ case FIELD_PROP_PAR1:
+ rAny <<= OUString(aContent);
+ break;
+
+ case FIELD_PROP_PAR4:
+ rAny <<= OUString(aName);
+ break;
+
+ case FIELD_PROP_USHORT1:
+ rAny <<= (sal_Int16)aContent.ToInt32();
+ break;
+
+ case FIELD_PROP_BOOL1:
+ {
+ sal_Bool bVal = 0 != (nSubType & DI_SUB_FIXED);
+ rAny.setValue(&bVal, ::getBooleanCppuType());
+ }
+ break;
+ case FIELD_PROP_FORMAT:
+ rAny <<= (sal_Int32)GetFormat();
+ break;
+
+ case FIELD_PROP_DOUBLE:
+ {
+ double fVal = GetValue();
+ rAny.setValue(&fVal, ::getCppuType(&fVal));
+ }
+ break;
+ case FIELD_PROP_PAR3:
+ rAny <<= rtl::OUString(Expand());
+ break;
+ case FIELD_PROP_BOOL2:
+ {
+ sal_uInt16 nExtSub = (nSubType & 0xff00) & ~DI_SUB_FIXED;
+ sal_Bool bVal = (nExtSub == DI_SUB_DATE);
+ rAny.setValue(&bVal, ::getBooleanCppuType());
+ }
+ break;
+ default:
+ return SwField::QueryValue(rAny, nWhichId);
+ }
+ return true;
+}
+
+bool SwDocInfoField::PutValue( const uno::Any& rAny, sal_uInt16 nWhichId )
+{
+ sal_Int32 nValue = 0;
+ switch( nWhichId )
+ {
+ case FIELD_PROP_PAR1:
+ if( nSubType & DI_SUB_FIXED )
+ ::GetString( rAny, aContent );
+ break;
+
+ case FIELD_PROP_USHORT1:
+ if( nSubType & DI_SUB_FIXED )
+ {
+ rAny >>= nValue;
+ aContent = String::CreateFromInt32(nValue);
+ }
+ break;
+
+ case FIELD_PROP_BOOL1:
+ if(*(sal_Bool*)rAny.getValue())
+ nSubType |= DI_SUB_FIXED;
+ else
+ nSubType &= ~DI_SUB_FIXED;
+ break;
+ case FIELD_PROP_FORMAT:
+ {
+ rAny >>= nValue;
+ if( nValue >= 0)
+ SetFormat(nValue);
+ }
+ break;
+
+ case FIELD_PROP_PAR3:
+ ::GetString( rAny, aContent );
+ break;
+ case FIELD_PROP_BOOL2:
+ nSubType &= 0xf0ff;
+ if(*(sal_Bool*)rAny.getValue())
+ nSubType |= DI_SUB_DATE;
+ else
+ nSubType |= DI_SUB_TIME;
+ break;
+ default:
+ return SwField::PutValue(rAny, nWhichId);
+ }
+ return true;
+}
+
+/*--------------------------------------------------------------------
+ Beschreibung: SwHiddenTxtFieldType by JP
+ --------------------------------------------------------------------*/
+
+SwHiddenTxtFieldType::SwHiddenTxtFieldType( sal_Bool bSetHidden )
+ : SwFieldType( RES_HIDDENTXTFLD ), bHidden( bSetHidden )
+{
+}
+
+SwFieldType* SwHiddenTxtFieldType::Copy() const
+{
+ return new SwHiddenTxtFieldType( bHidden );
+}
+
+void SwHiddenTxtFieldType::SetHiddenFlag( sal_Bool bSetHidden )
+{
+ if( bHidden != bSetHidden )
+ {
+ bHidden = bSetHidden;
+ UpdateFlds(); // alle HiddenText benachrichtigen
+ }
+}
+
+SwHiddenTxtField::SwHiddenTxtField( SwHiddenTxtFieldType* pFldType,
+ sal_Bool bConditional,
+ const String& rCond,
+ const String& rStr,
+ sal_Bool bHidden,
+ sal_uInt16 nSub) :
+ SwField( pFldType ), aCond(rCond), nSubType(nSub),
+ bCanToggle(bConditional), bIsHidden(bHidden), bValid(sal_False)
+{
+ if(nSubType == TYP_CONDTXTFLD)
+ {
+ sal_uInt16 nPos = 0;
+ aTRUETxt = rStr.GetToken(0, '|', nPos);
+
+ if(nPos != STRING_NOTFOUND)
+ {
+ aFALSETxt = rStr.GetToken(0, '|', nPos);
+ if(nPos != STRING_NOTFOUND)
+ {
+ aContent = rStr.GetToken(0, '|', nPos);
+ bValid = sal_True;
+ }
+ }
+ }
+ else
+ aTRUETxt = rStr;
+}
+
+SwHiddenTxtField::SwHiddenTxtField( SwHiddenTxtFieldType* pFldType,
+ const String& rCond,
+ const String& rTrue,
+ const String& rFalse,
+ sal_uInt16 nSub)
+ : SwField( pFldType ), aTRUETxt(rTrue), aFALSETxt(rFalse), aCond(rCond), nSubType(nSub),
+ bIsHidden(sal_True), bValid(sal_False)
+{
+ bCanToggle = aCond.Len() > 0;
+}
+
+String SwHiddenTxtField::Expand() const
+{
+ // Type: !Hidden -> immer anzeigen
+ // Hide -> Werte die Bedingung aus
+
+ if( TYP_CONDTXTFLD == nSubType )
+ {
+ if( bValid )
+ return aContent;
+
+ if( bCanToggle && !bIsHidden )
+ return aTRUETxt;
+ }
+ else if( !((SwHiddenTxtFieldType*)GetTyp())->GetHiddenFlag() ||
+ ( bCanToggle && bIsHidden ))
+ return aTRUETxt;
+
+ return aFALSETxt;
+}
+
+/*--------------------------------------------------------------------
+ Beschreibung: Aktuellen Field-Value holen und cachen
+ --------------------------------------------------------------------*/
+
+void SwHiddenTxtField::Evaluate(SwDoc* pDoc)
+{
+ OSL_ENSURE(pDoc, "Wo ist das Dokument Seniore");
+
+ if( TYP_CONDTXTFLD == nSubType )
+ {
+ SwNewDBMgr* pMgr = pDoc->GetNewDBMgr();
+
+ bValid = sal_False;
+ String sTmpName;
+
+ if (bCanToggle && !bIsHidden)
+ sTmpName = aTRUETxt;
+ else
+ sTmpName = aFALSETxt;
+
+// Datenbankausdruecke muessen sich von
+// einfachem Text unterscheiden. also wird der einfache Text
+// bevorzugt in Anfuehrungszeichen gesetzt.
+// Sind diese vorhanden werden umschliessende entfernt.
+// Wenn nicht, dann wird auf die Tauglichkeit als Datenbankname
+// geprueft. Nur wenn zwei oder mehr Punkte vorhanden sind und kein
+// Anfuehrungszeichen enthalten ist, gehen wir von einer DB aus.
+ if(sTmpName.Len() > 1 && sTmpName.GetChar(0) == '\"' &&
+ sTmpName.GetChar((sTmpName.Len() - 1))== '\"')
+ {
+ aContent = sTmpName.Copy(1, sTmpName.Len() - 2);
+ bValid = sal_True;
+ }
+ else if(sTmpName.Search('\"') == STRING_NOTFOUND &&
+ sTmpName.GetTokenCount('.') > 2)
+ {
+ ::ReplacePoint(sTmpName);
+ if(sTmpName.GetChar(0) == '[' && sTmpName.GetChar(sTmpName.Len()-1) == ']')
+ { // Eckige Klammern entfernen
+ sTmpName.Erase(0, 1);
+ sTmpName.Erase(sTmpName.Len()-1, 1);
+ }
+
+ if( pMgr)
+ {
+ String sDBName( GetDBName( sTmpName, pDoc ));
+ String sDataSource(sDBName.GetToken(0, DB_DELIM));
+ String sDataTableOrQuery(sDBName.GetToken(1, DB_DELIM));
+ if( pMgr->IsInMerge() && sDBName.Len() &&
+ pMgr->IsDataSourceOpen( sDataSource,
+ sDataTableOrQuery, sal_False))
+ {
+ double fNumber;
+ sal_uInt32 nTmpFormat;
+ pMgr->GetMergeColumnCnt(GetColumnName( sTmpName ),
+ GetLanguage(), aContent, &fNumber, &nTmpFormat );
+ bValid = sal_True;
+ }
+ else if( sDBName.Len() && sDataSource.Len() &&
+ sDataTableOrQuery.Len() )
+ bValid = sal_True;
+ }
+ }
+ }
+}
+
+String SwHiddenTxtField::GetFieldName() const
+{
+ String aStr(SwFieldType::GetTypeStr(nSubType));
+ aStr += ' ';
+ aStr += aCond;
+ aStr += ' ';
+ aStr += aTRUETxt;
+
+ if (nSubType == TYP_CONDTXTFLD)
+ {
+ aStr.AppendAscii(" : ");
+ aStr += aFALSETxt;
+ }
+ return aStr;
+}
+
+SwField* SwHiddenTxtField::Copy() const
+{
+ SwHiddenTxtField* pFld =
+ new SwHiddenTxtField((SwHiddenTxtFieldType*)GetTyp(), aCond,
+ aTRUETxt, aFALSETxt);
+ pFld->bIsHidden = bIsHidden;
+ pFld->bValid = bValid;
+ pFld->aContent = aContent;
+ pFld->SetFormat(GetFormat());
+ pFld->nSubType = nSubType;
+ return pFld;
+}
+
+
+/*--------------------------------------------------------------------
+ Beschreibung: Bedingung setzen
+ --------------------------------------------------------------------*/
+
+void SwHiddenTxtField::SetPar1(const String& rStr)
+{
+ aCond = rStr;
+ bCanToggle = aCond.Len() > 0;
+}
+
+const String& SwHiddenTxtField::GetPar1() const
+{
+ return aCond;
+}
+
+/*--------------------------------------------------------------------
+ Beschreibung: True/False Text
+ --------------------------------------------------------------------*/
+
+void SwHiddenTxtField::SetPar2(const String& rStr)
+{
+ if(nSubType == TYP_CONDTXTFLD)
+ {
+ sal_uInt16 nPos = rStr.Search('|');
+ aTRUETxt = rStr.Copy(0, nPos);
+
+ if(nPos != STRING_NOTFOUND)
+ aFALSETxt = rStr.Copy(nPos + 1);
+ }
+ else
+ aTRUETxt = rStr;
+}
+
+String SwHiddenTxtField::GetPar2() const
+{
+ String aRet(aTRUETxt);
+ if(nSubType == TYP_CONDTXTFLD)
+ {
+ aRet += '|';
+ aRet += aFALSETxt;
+ }
+ return aRet;
+}
+
+sal_uInt16 SwHiddenTxtField::GetSubType() const
+{
+ return nSubType;
+}
+
+bool SwHiddenTxtField::QueryValue( uno::Any& rAny, sal_uInt16 nWhichId ) const
+{
+ const String* pOut = 0;
+ switch( nWhichId )
+ {
+ case FIELD_PROP_PAR1:
+ pOut = &aCond;
+ break;
+ case FIELD_PROP_PAR2:
+ pOut = &aTRUETxt;
+ break;
+ case FIELD_PROP_PAR3:
+ pOut = &aFALSETxt;
+ break;
+ case FIELD_PROP_PAR4 :
+ pOut = &aContent;
+ break;
+ case FIELD_PROP_BOOL1:
+ {
+ sal_Bool bHidden = bIsHidden;
+ rAny.setValue(&bHidden, ::getBooleanCppuType());
+ }
+ break;
+ default:
+ OSL_FAIL("illegal property");
+ }
+ if( pOut )
+ rAny <<= OUString( *pOut );
+ return true;
+}
+
+bool SwHiddenTxtField::PutValue( const uno::Any& rAny, sal_uInt16 nWhichId )
+{
+ switch( nWhichId )
+ {
+ case FIELD_PROP_PAR1:
+ {
+ String sVal;
+ SetPar1(::GetString( rAny, sVal ));
+ }
+ break;
+ case FIELD_PROP_PAR2:
+ ::GetString( rAny, aTRUETxt );
+ break;
+ case FIELD_PROP_PAR3:
+ ::GetString( rAny, aFALSETxt );
+ break;
+ case FIELD_PROP_BOOL1:
+ bIsHidden = *(sal_Bool*)rAny.getValue();
+ break;
+ case FIELD_PROP_PAR4:
+ ::GetString( rAny, aContent);
+ bValid = sal_True;
+ break;
+ default:
+ OSL_FAIL("illegal property");
+ }
+ return true;
+}
+
+//------------------------------------------------------------------------------
+
+String SwHiddenTxtField::GetColumnName(const String& rName)
+{
+ sal_uInt16 nPos = rName.Search(DB_DELIM);
+ if( STRING_NOTFOUND != nPos )
+ {
+ nPos = rName.Search(DB_DELIM, nPos + 1);
+
+ if( STRING_NOTFOUND != nPos )
+ return rName.Copy(nPos + 1);
+ }
+ return rName;
+}
+
+//------------------------------------------------------------------------------
+
+String SwHiddenTxtField::GetDBName(const String& rName, SwDoc *pDoc)
+{
+ sal_uInt16 nPos = rName.Search(DB_DELIM);
+ if( STRING_NOTFOUND != nPos )
+ {
+ nPos = rName.Search(DB_DELIM, nPos + 1);
+
+ if( STRING_NOTFOUND != nPos )
+ return rName.Copy( 0, nPos );
+ }
+ SwDBData aData = pDoc->GetDBData();
+ String sRet = aData.sDataSource;
+ sRet += DB_DELIM;
+ sRet += String(aData.sCommand);
+ return sRet;
+}
+
+/*--------------------------------------------------------------------
+ Beschreibung: Der Feldtyp fuer Zeilenhoehe 0
+ --------------------------------------------------------------------*/
+
+SwHiddenParaFieldType::SwHiddenParaFieldType()
+ : SwFieldType( RES_HIDDENPARAFLD )
+{
+}
+
+SwFieldType* SwHiddenParaFieldType::Copy() const
+{
+ SwHiddenParaFieldType* pTyp = new SwHiddenParaFieldType();
+ return pTyp;
+}
+
+/*--------------------------------------------------------------------
+ Beschreibung: Das Feld Zeilenhoehe 0
+ --------------------------------------------------------------------*/
+
+SwHiddenParaField::SwHiddenParaField(SwHiddenParaFieldType* pTyp, const String& rStr)
+ : SwField(pTyp), aCond(rStr)
+{
+ bIsHidden = sal_False;
+}
+
+String SwHiddenParaField::Expand() const
+{
+ return aEmptyStr;
+}
+
+SwField* SwHiddenParaField::Copy() const
+{
+ SwHiddenParaField* pFld = new SwHiddenParaField((SwHiddenParaFieldType*)GetTyp(), aCond);
+ pFld->bIsHidden = bIsHidden;
+
+ return pFld;
+}
+
+bool SwHiddenParaField::QueryValue( uno::Any& rAny, sal_uInt16 nWhichId ) const
+{
+ switch ( nWhichId )
+ {
+ case FIELD_PROP_PAR1:
+ rAny <<= OUString(aCond);
+ break;
+ case FIELD_PROP_BOOL1:
+ {
+ sal_Bool bHidden = bIsHidden;
+ rAny.setValue(&bHidden, ::getBooleanCppuType());
+ }
+ break;
+
+ default:
+ OSL_FAIL("illegal property");
+ }
+ return true;
+}
+
+bool SwHiddenParaField::PutValue( const uno::Any& rAny, sal_uInt16 nWhichId )
+{
+ switch ( nWhichId )
+ {
+ case FIELD_PROP_PAR1:
+ ::GetString( rAny, aCond );
+ break;
+ case FIELD_PROP_BOOL1:
+ bIsHidden = *(sal_Bool*)rAny.getValue();
+ break;
+
+ default:
+ OSL_FAIL("illegal property");
+ }
+ return true;
+}
+
+/*--------------------------------------------------------------------
+ Beschreibung: Bedingung setzen
+ --------------------------------------------------------------------*/
+
+void SwHiddenParaField::SetPar1(const String& rStr)
+{
+ aCond = rStr;
+}
+
+const String& SwHiddenParaField::GetPar1() const
+{
+ return aCond;
+}
+
+/*--------------------------------------------------------------------
+ Beschreibung: PostIt
+ --------------------------------------------------------------------*/
+
+SwPostItFieldType::SwPostItFieldType(SwDoc *pDoc)
+ : SwFieldType( RES_POSTITFLD ),mpDoc(pDoc)
+{}
+
+SwFieldType* SwPostItFieldType::Copy() const
+{
+ return new SwPostItFieldType(mpDoc);
+}
+
+
+/*--------------------------------------------------------------------
+ Beschreibung: SwPostItFieldType
+ --------------------------------------------------------------------*/
+
+SwPostItField::SwPostItField( SwPostItFieldType* pT,
+ const String& rAuthor, const String& rTxt, const DateTime& rDateTime )
+ : SwField( pT ), sTxt( rTxt ), sAuthor( rAuthor ), aDateTime( rDateTime ), mpText(0), m_pTextObject(0)
+{
+}
+
+
+SwPostItField::~SwPostItField()
+{
+ if ( m_pTextObject )
+ {
+ m_pTextObject->DisposeEditSource();
+ m_pTextObject->release();
+ }
+}
+
+
+String SwPostItField::Expand() const
+{
+ return aEmptyStr;
+}
+
+
+String SwPostItField::GetDescription() const
+{
+ return SW_RES(STR_NOTE);
+}
+
+
+SwField* SwPostItField::Copy() const
+{
+ SwPostItField* pRet = new SwPostItField( (SwPostItFieldType*)GetTyp(), sAuthor,
+ sTxt, aDateTime);
+ if (mpText)
+ pRet->SetTextObject( new OutlinerParaObject(*mpText) );
+ return pRet;
+}
+/*--------------------------------------------------------------------
+ Beschreibung: Author setzen
+ --------------------------------------------------------------------*/
+
+void SwPostItField::SetPar1(const String& rStr)
+{
+ sAuthor = rStr;
+}
+
+const String& SwPostItField::GetPar1() const
+{
+ return sAuthor;
+}
+
+/*--------------------------------------------------------------------
+ Beschreibung: Text fuers PostIt setzen
+ --------------------------------------------------------------------*/
+
+void SwPostItField::SetPar2(const String& rStr)
+{
+ sTxt = rStr;
+}
+
+String SwPostItField::GetPar2() const
+{
+ return sTxt;
+}
+
+const OutlinerParaObject* SwPostItField::GetTextObject() const
+{
+ return mpText;
+}
+
+void SwPostItField::SetTextObject( OutlinerParaObject* pText )
+{
+ delete mpText;
+ mpText = pText;
+}
+
+sal_uInt32 SwPostItField::GetNumberOfParagraphs() const
+{
+ return (mpText) ? mpText->Count() : 1;
+}
+
+bool SwPostItField::QueryValue( uno::Any& rAny, sal_uInt16 nWhichId ) const
+{
+ switch( nWhichId )
+ {
+ case FIELD_PROP_PAR1:
+ rAny <<= OUString(sAuthor);
+ break;
+ case FIELD_PROP_PAR2:
+ {
+ rAny <<= OUString(sTxt);
+ break;
+ }
+ case FIELD_PROP_TEXT:
+ {
+ if ( !m_pTextObject )
+ {
+ SwPostItFieldType* pGetType = (SwPostItFieldType*)GetTyp();
+ SwDoc* pDoc = pGetType->GetDoc();
+ SwTextAPIEditSource* pObj = new SwTextAPIEditSource( pDoc );
+ const_cast <SwPostItField*> (this)->m_pTextObject = new SwTextAPIObject( pObj );
+ m_pTextObject->acquire();
+ }
+
+ if ( mpText )
+ m_pTextObject->SetText( *mpText );
+ else
+ m_pTextObject->SetString( sTxt );
+
+ uno::Reference < text::XText > xText( m_pTextObject );
+ rAny <<= xText;
+ break;
+ }
+ case FIELD_PROP_DATE:
+ {
+ util::Date aSetDate;
+ aSetDate.Day = aDateTime.GetDay();
+ aSetDate.Month = aDateTime.GetMonth();
+ aSetDate.Year = aDateTime.GetYear();
+ rAny.setValue(&aSetDate, ::getCppuType((util::Date*)0));
+ }
+ break;
+ case FIELD_PROP_DATE_TIME:
+ {
+ util::DateTime DateTimeValue;
+ DateTimeValue.HundredthSeconds = aDateTime.Get100Sec();
+ DateTimeValue.Seconds = aDateTime.GetSec();
+ DateTimeValue.Minutes = aDateTime.GetMin();
+ DateTimeValue.Hours = aDateTime.GetHour();
+ DateTimeValue.Day = aDateTime.GetDay();
+ DateTimeValue.Month = aDateTime.GetMonth();
+ DateTimeValue.Year = aDateTime.GetYear();
+ rAny <<= DateTimeValue;
+ }
+ break;
+ default:
+ OSL_FAIL("illegal property");
+ }
+ return true;
+}
+
+bool SwPostItField::PutValue( const uno::Any& rAny, sal_uInt16 nWhichId )
+{
+ switch( nWhichId )
+ {
+ case FIELD_PROP_PAR1:
+ ::GetString( rAny, sAuthor );
+ break;
+ case FIELD_PROP_PAR2:
+ ::GetString( rAny, sTxt );
+ //#i100374# new string via api, delete complex text object so SwPostItNote picks up the new string
+ if (mpText)
+ {
+ delete mpText;
+ mpText = 0;
+ }
+ break;
+ case FIELD_PROP_TEXT:
+ OSL_FAIL("Not implemented!");
+ break;
+ case FIELD_PROP_DATE:
+ if( rAny.getValueType() == ::getCppuType((util::Date*)0) )
+ {
+ util::Date aSetDate = *(util::Date*)rAny.getValue();
+ aDateTime = Date(aSetDate.Day, aSetDate.Month, aSetDate.Year);
+ }
+ break;
+ case FIELD_PROP_DATE_TIME:
+ {
+ util::DateTime aDateTimeValue;
+ if(!(rAny >>= aDateTimeValue))
+ return sal_False;
+ aDateTime.Set100Sec(aDateTimeValue.HundredthSeconds);
+ aDateTime.SetSec(aDateTimeValue.Seconds);
+ aDateTime.SetMin(aDateTimeValue.Minutes);
+ aDateTime.SetHour(aDateTimeValue.Hours);
+ aDateTime.SetDay(aDateTimeValue.Day);
+ aDateTime.SetMonth(aDateTimeValue.Month);
+ aDateTime.SetYear(aDateTimeValue.Year);
+ }
+ break;
+ default:
+ OSL_FAIL("illegal property");
+ }
+ return true;
+}
+/*--------------------------------------------------------------------
+ Beschreibung: DokumentinfoFields
+ --------------------------------------------------------------------*/
+
+SwExtUserFieldType::SwExtUserFieldType()
+ : SwFieldType( RES_EXTUSERFLD )
+{
+}
+
+SwFieldType* SwExtUserFieldType::Copy() const
+{
+ SwExtUserFieldType* pTyp = new SwExtUserFieldType;
+ return pTyp;
+}
+
+String SwExtUserFieldType::Expand(sal_uInt16 nSub, sal_uInt32 ) const
+{
+ String aRet;
+ sal_uInt16 nRet = USHRT_MAX;
+ switch(nSub)
+ {
+ case EU_FIRSTNAME: nRet = USER_OPT_FIRSTNAME; break;
+ case EU_NAME: nRet = USER_OPT_LASTNAME; break;
+ case EU_SHORTCUT: nRet = USER_OPT_ID; break;
+
+ case EU_COMPANY: nRet = USER_OPT_COMPANY; break;
+ case EU_STREET: nRet = USER_OPT_STREET; break;
+ case EU_TITLE: nRet = USER_OPT_TITLE; break;
+ case EU_POSITION: nRet = USER_OPT_POSITION; break;
+ case EU_PHONE_PRIVATE: nRet = USER_OPT_TELEPHONEHOME; break;
+ case EU_PHONE_COMPANY: nRet = USER_OPT_TELEPHONEWORK; break;
+ case EU_FAX: nRet = USER_OPT_FAX; break;
+ case EU_EMAIL: nRet = USER_OPT_EMAIL; break;
+ case EU_COUNTRY: nRet = USER_OPT_COUNTRY; break;
+ case EU_ZIP: nRet = USER_OPT_ZIP; break;
+ case EU_CITY: nRet = USER_OPT_CITY; break;
+ case EU_STATE: nRet = USER_OPT_STATE; break;
+ case EU_FATHERSNAME: nRet = USER_OPT_FATHERSNAME; break;
+ case EU_APARTMENT: nRet = USER_OPT_APARTMENT; break;
+ default: OSL_ENSURE( !this, "Field unknown");
+ }
+ if( USHRT_MAX != nRet )
+ {
+ SvtUserOptions& rUserOpt = SW_MOD()->GetUserOptions();
+ aRet = rUserOpt.GetToken( nRet );
+ }
+ return aRet;
+}
+
+SwExtUserField::SwExtUserField(SwExtUserFieldType* pTyp, sal_uInt16 nSubTyp, sal_uInt32 nFmt) :
+ SwField(pTyp, nFmt), nType(nSubTyp)
+{
+ aContent = ((SwExtUserFieldType*)GetTyp())->Expand(nType, GetFormat());
+}
+
+String SwExtUserField::Expand() const
+{
+ if (!IsFixed())
+ ((SwExtUserField*)this)->aContent = ((SwExtUserFieldType*)GetTyp())->Expand(nType, GetFormat());
+
+ return aContent;
+}
+
+SwField* SwExtUserField::Copy() const
+{
+ SwExtUserField* pFld = new SwExtUserField((SwExtUserFieldType*)GetTyp(), nType, GetFormat());
+ pFld->SetExpansion(aContent);
+
+ return pFld;
+}
+
+sal_uInt16 SwExtUserField::GetSubType() const
+{
+ return nType;
+}
+
+void SwExtUserField::SetSubType(sal_uInt16 nSub)
+{
+ nType = nSub;
+}
+
+bool SwExtUserField::QueryValue( uno::Any& rAny, sal_uInt16 nWhichId ) const
+{
+ switch( nWhichId )
+ {
+ case FIELD_PROP_PAR1:
+ rAny <<= OUString(aContent);
+ break;
+
+ case FIELD_PROP_USHORT1:
+ {
+ sal_Int16 nTmp = nType;
+ rAny <<= nTmp;
+ }
+ break;
+ case FIELD_PROP_BOOL1:
+ {
+ sal_Bool bTmp = IsFixed();
+ rAny.setValue(&bTmp, ::getBooleanCppuType());
+ }
+ break;
+ default:
+ OSL_FAIL("illegal property");
+ }
+ return true;
+}
+
+bool SwExtUserField::PutValue( const uno::Any& rAny, sal_uInt16 nWhichId )
+{
+ switch( nWhichId )
+ {
+ case FIELD_PROP_PAR1:
+ ::GetString( rAny, aContent );
+ break;
+
+ case FIELD_PROP_USHORT1:
+ {
+ sal_Int16 nTmp = 0;
+ rAny >>= nTmp;
+ nType = nTmp;
+ }
+ break;
+ case FIELD_PROP_BOOL1:
+ if( *(sal_Bool*)rAny.getValue() )
+ SetFormat(GetFormat() | AF_FIXED);
+ else
+ SetFormat(GetFormat() & ~AF_FIXED);
+ break;
+ default:
+ OSL_FAIL("illegal property");
+ }
+ return true;
+}
+//-------------------------------------------------------------------------
+
+/*--------------------------------------------------------------------
+ Beschreibung: Relatives Seitennummern - Feld
+ --------------------------------------------------------------------*/
+
+SwRefPageSetFieldType::SwRefPageSetFieldType()
+ : SwFieldType( RES_REFPAGESETFLD )
+{
+}
+
+SwFieldType* SwRefPageSetFieldType::Copy() const
+{
+ return new SwRefPageSetFieldType;
+}
+
+// ueberlagert, weil es nichts zum Updaten gibt!
+void SwRefPageSetFieldType::Modify( const SfxPoolItem*, const SfxPoolItem * )
+{
+}
+
+/*--------------------------------------------------------------------
+ Beschreibung: Relative Seitennummerierung
+ --------------------------------------------------------------------*/
+
+SwRefPageSetField::SwRefPageSetField( SwRefPageSetFieldType* pTyp,
+ short nOff, sal_Bool bFlag )
+ : SwField( pTyp ), nOffset( nOff ), bOn( bFlag )
+{
+}
+
+String SwRefPageSetField::Expand() const
+{
+ return aEmptyStr;
+}
+
+SwField* SwRefPageSetField::Copy() const
+{
+ return new SwRefPageSetField( (SwRefPageSetFieldType*)GetTyp(), nOffset, bOn );
+}
+
+String SwRefPageSetField::GetPar2() const
+{
+ return String::CreateFromInt32( GetOffset() );
+}
+
+void SwRefPageSetField::SetPar2(const String& rStr)
+{
+ SetOffset( (short) rStr.ToInt32() );
+}
+
+bool SwRefPageSetField::QueryValue( uno::Any& rAny, sal_uInt16 nWhichId ) const
+{
+ switch( nWhichId )
+ {
+ case FIELD_PROP_BOOL1:
+ rAny.setValue(&bOn, ::getBooleanCppuType());
+ break;
+ case FIELD_PROP_USHORT1:
+ rAny <<= (sal_Int16)nOffset;
+ break;
+ default:
+ OSL_FAIL("illegal property");
+ }
+ return true;
+}
+
+bool SwRefPageSetField::PutValue( const uno::Any& rAny, sal_uInt16 nWhichId )
+{
+ switch( nWhichId )
+ {
+ case FIELD_PROP_BOOL1:
+ bOn = *(sal_Bool*)rAny.getValue();
+ break;
+ case FIELD_PROP_USHORT1:
+ rAny >>=nOffset;
+ break;
+ default:
+ OSL_FAIL("illegal property");
+ }
+ return true;
+}
+/*--------------------------------------------------------------------
+ Beschreibung: relatives Seitennummern - Abfrage Feld
+ --------------------------------------------------------------------*/
+
+SwRefPageGetFieldType::SwRefPageGetFieldType( SwDoc* pDc )
+ : SwFieldType( RES_REFPAGEGETFLD ), pDoc( pDc ), nNumberingType( SVX_NUM_ARABIC )
+{
+}
+
+SwFieldType* SwRefPageGetFieldType::Copy() const
+{
+ SwRefPageGetFieldType* pNew = new SwRefPageGetFieldType( pDoc );
+ pNew->nNumberingType = nNumberingType;
+ return pNew;
+}
+
+void SwRefPageGetFieldType::Modify( const SfxPoolItem* pOld, const SfxPoolItem* pNew )
+{
+ // Update auf alle GetReferenz-Felder
+ if( !pNew && !pOld && GetDepends() )
+ {
+ // sammel erstmal alle SetPageRefFelder ein.
+ _SetGetExpFlds aTmpLst( 10, 5 );
+ if( MakeSetList( aTmpLst ) )
+ {
+ SwIterator<SwFmtFld,SwFieldType> aIter( *this );
+ for ( SwFmtFld* pFmtFld = aIter.First(); pFmtFld; pFmtFld = aIter.Next() )
+ // nur die GetRef-Felder Updaten
+ if( pFmtFld->GetTxtFld() )
+ UpdateField( pFmtFld->GetTxtFld(), aTmpLst );
+ }
+ }
+
+ // weiter an die Text-Felder, diese "Expandieren" den Text
+ NotifyClients( pOld, pNew );
+}
+
+sal_uInt16 SwRefPageGetFieldType::MakeSetList( _SetGetExpFlds& rTmpLst )
+{
+ SwIterator<SwFmtFld,SwFieldType> aIter(*pDoc->GetSysFldType( RES_REFPAGESETFLD));
+ for ( SwFmtFld* pFmtFld = aIter.First(); pFmtFld; pFmtFld = aIter.Next() )
+ {
+ // nur die GetRef-Felder Updaten
+ const SwTxtFld* pTFld = pFmtFld->GetTxtFld();
+ if( pTFld )
+ {
+ const SwTxtNode& rTxtNd = pTFld->GetTxtNode();
+
+ // immer den ersten !! (in Tab-Headline, Kopf-/Fuss )
+ Point aPt;
+ const SwCntntFrm* pFrm = rTxtNd.getLayoutFrm( rTxtNd.GetDoc()->GetCurrentLayout(), &aPt, 0, sal_False );
+
+ _SetGetExpFld* pNew;
+
+ if( !pFrm ||
+ pFrm->IsInDocBody() ||
+ // --> FME 2004-07-27 #i31868#
+ // Check if pFrm is not yet connected to the layout.
+ !pFrm->FindPageFrm() )
+ // <--
+ {
+ // einen sdbcx::Index fuers bestimmen vom TextNode anlegen
+ SwNodeIndex aIdx( rTxtNd );
+ pNew = new _SetGetExpFld( aIdx, pTFld );
+ }
+ else
+ {
+ // einen sdbcx::Index fuers bestimmen vom TextNode anlegen
+ SwPosition aPos( pDoc->GetNodes().GetEndOfPostIts() );
+#if OSL_DEBUG_LEVEL > 1
+ OSL_ENSURE( GetBodyTxtNode( *pDoc, aPos, *pFrm ),
+ "wo steht das Feld" );
+#else
+ GetBodyTxtNode( *pDoc, aPos, *pFrm );
+#endif
+ pNew = new _SetGetExpFld( aPos.nNode, pTFld,
+ &aPos.nContent );
+ }
+
+ if( !rTmpLst.Insert( pNew ))
+ delete pNew;
+ }
+ }
+
+ return rTmpLst.Count();
+}
+
+void SwRefPageGetFieldType::UpdateField( SwTxtFld* pTxtFld,
+ _SetGetExpFlds& rSetList )
+{
+ SwRefPageGetField* pGetFld = (SwRefPageGetField*)pTxtFld->GetFld().GetFld();
+ pGetFld->SetText( aEmptyStr );
+
+ // dann suche mal das richtige RefPageSet-Field
+ SwTxtNode* pTxtNode = (SwTxtNode*)&pTxtFld->GetTxtNode();
+ if( pTxtNode->StartOfSectionIndex() >
+ pDoc->GetNodes().GetEndOfExtras().GetIndex() )
+ {
+ SwNodeIndex aIdx( *pTxtNode );
+ _SetGetExpFld aEndFld( aIdx, pTxtFld );
+
+ sal_uInt16 nLast;
+ rSetList.Seek_Entry( &aEndFld, &nLast );
+
+ if( nLast-- )
+ {
+ const SwTxtFld* pRefTxtFld = rSetList[ nLast ]->GetFld();
+ const SwRefPageSetField* pSetFld =
+ (SwRefPageSetField*)pRefTxtFld->GetFld().GetFld();
+ if( pSetFld->IsOn() )
+ {
+ // dann bestimme mal den entsp. Offset
+ Point aPt;
+ const SwCntntFrm* pFrm = pTxtNode->getLayoutFrm( pTxtNode->GetDoc()->GetCurrentLayout(), &aPt, 0, sal_False );
+ const SwCntntFrm* pRefFrm = pRefTxtFld->GetTxtNode().getLayoutFrm( pRefTxtFld->GetTxtNode().GetDoc()->GetCurrentLayout(), &aPt, 0, sal_False );
+ const SwPageFrm* pPgFrm = 0;
+ sal_uInt16 nDiff = ( pFrm && pRefFrm )
+ ? (pPgFrm = pFrm->FindPageFrm())->GetPhyPageNum() -
+ pRefFrm->FindPageFrm()->GetPhyPageNum() + 1
+ : 1;
+
+ sal_uInt32 nTmpFmt = SVX_NUM_PAGEDESC == pGetFld->GetFormat()
+ ? ( !pPgFrm
+ ? (sal_uInt32)SVX_NUM_ARABIC
+ : pPgFrm->GetPageDesc()->GetNumType().GetNumberingType() )
+ : pGetFld->GetFormat();
+ short nPageNum = static_cast<short>(Max(0, pSetFld->GetOffset() + (short)nDiff));
+ pGetFld->SetText( FormatNumber( nPageNum, nTmpFmt ) );
+ }
+ }
+ }
+ // dann die Formatierung anstossen
+ ((SwFmtFld&)pTxtFld->GetFld()).ModifyNotification( 0, 0 );
+}
+
+/*--------------------------------------------------------------------
+ Beschreibung: Relative Seitennummerierung Abfragen
+ --------------------------------------------------------------------*/
+
+SwRefPageGetField::SwRefPageGetField( SwRefPageGetFieldType* pTyp,
+ sal_uInt32 nFmt )
+ : SwField( pTyp, nFmt )
+{
+}
+
+String SwRefPageGetField::Expand() const
+{
+ return sTxt;
+}
+
+SwField* SwRefPageGetField::Copy() const
+{
+ SwRefPageGetField* pCpy = new SwRefPageGetField(
+ (SwRefPageGetFieldType*)GetTyp(), GetFormat() );
+ pCpy->SetText( sTxt );
+ return pCpy;
+}
+
+void SwRefPageGetField::ChangeExpansion( const SwFrm* pFrm,
+ const SwTxtFld* pFld )
+{
+ // nur Felder in Footer, Header, FootNote, Flys
+ SwTxtNode* pTxtNode = (SwTxtNode*)&pFld->GetTxtNode();
+ SwRefPageGetFieldType* pGetType = (SwRefPageGetFieldType*)GetTyp();
+ SwDoc* pDoc = pGetType->GetDoc();
+ if( pFld->GetTxtNode().StartOfSectionIndex() >
+ pDoc->GetNodes().GetEndOfExtras().GetIndex() )
+ return;
+
+ sTxt.Erase();
+
+ OSL_ENSURE( !pFrm->IsInDocBody(), "Flag ist nicht richtig, Frame steht im DocBody" );
+
+ // sammel erstmal alle SetPageRefFelder ein.
+ _SetGetExpFlds aTmpLst( 10, 5 );
+ if( !pGetType->MakeSetList( aTmpLst ) )
+ return ;
+
+ // einen sdbcx::Index fuers bestimmen vom TextNode anlegen
+ SwPosition aPos( SwNodeIndex( pDoc->GetNodes() ) );
+ pTxtNode = (SwTxtNode*) GetBodyTxtNode( *pDoc, aPos, *pFrm );
+
+ // Wenn kein Layout vorhanden, kommt es in Kopf und Fusszeilen dazu
+ // das ChangeExpansion uebers Layout-Formatieren aufgerufen wird
+ // aber kein TxtNode vorhanden ist
+ //
+ if(!pTxtNode)
+ return;
+
+ _SetGetExpFld aEndFld( aPos.nNode, pFld, &aPos.nContent );
+
+ sal_uInt16 nLast;
+ aTmpLst.Seek_Entry( &aEndFld, &nLast );
+
+ if( !nLast-- )
+ return ; // es gibt kein entsprechendes Set - Feld vor mir
+
+ const SwTxtFld* pRefTxtFld = aTmpLst[ nLast ]->GetFld();
+ const SwRefPageSetField* pSetFld =
+ (SwRefPageSetField*)pRefTxtFld->GetFld().GetFld();
+ Point aPt;
+ const SwCntntFrm* pRefFrm = pRefTxtFld ? pRefTxtFld->GetTxtNode().getLayoutFrm( pFrm->getRootFrm(), &aPt, 0, sal_False ) : 0;
+ if( pSetFld->IsOn() && pRefFrm )
+ {
+ // dann bestimme mal den entsp. Offset
+ const SwPageFrm* pPgFrm = pFrm->FindPageFrm();
+ sal_uInt16 nDiff = pPgFrm->GetPhyPageNum() -
+ pRefFrm->FindPageFrm()->GetPhyPageNum() + 1;
+
+ SwRefPageGetField* pGetFld = (SwRefPageGetField*)pFld->GetFld().GetFld();
+ sal_uInt32 nTmpFmt = SVX_NUM_PAGEDESC == pGetFld->GetFormat()
+ ? pPgFrm->GetPageDesc()->GetNumType().GetNumberingType()
+ : pGetFld->GetFormat();
+ short nPageNum = static_cast<short>(Max(0, pSetFld->GetOffset() + (short)nDiff ));
+ pGetFld->SetText( FormatNumber( nPageNum, nTmpFmt ) );
+ }
+}
+
+bool SwRefPageGetField::QueryValue( uno::Any& rAny, sal_uInt16 nWhichId ) const
+{
+ switch( nWhichId )
+ {
+ case FIELD_PROP_USHORT1:
+ rAny <<= (sal_Int16)GetFormat();
+ break;
+ case FIELD_PROP_PAR1:
+ rAny <<= OUString(sTxt);
+ break;
+ default:
+ OSL_FAIL("illegal property");
+ }
+ return true;
+}
+
+bool SwRefPageGetField::PutValue( const uno::Any& rAny, sal_uInt16 nWhichId )
+{
+ switch( nWhichId )
+ {
+ case FIELD_PROP_USHORT1:
+ {
+ sal_Int16 nSet = 0;
+ rAny >>= nSet;
+ if(nSet <= SVX_NUM_PAGEDESC )
+ SetFormat(nSet);
+ else {
+ }
+ }
+ break;
+ case FIELD_PROP_PAR1:
+ {
+ OUString sTmp;
+ rAny >>= sTmp;
+ sTxt = sTmp;
+ }
+ break;
+ default:
+ OSL_FAIL("illegal property");
+ }
+ return true;
+}
+
+/*--------------------------------------------------------------------
+ Beschreibung: Feld zum Anspringen und Editieren
+ --------------------------------------------------------------------*/
+
+SwJumpEditFieldType::SwJumpEditFieldType( SwDoc* pD )
+ : SwFieldType( RES_JUMPEDITFLD ), pDoc( pD ), aDep( this, 0 )
+{
+}
+
+SwFieldType* SwJumpEditFieldType::Copy() const
+{
+ return new SwJumpEditFieldType( pDoc );
+}
+
+SwCharFmt* SwJumpEditFieldType::GetCharFmt()
+{
+ SwCharFmt* pFmt = pDoc->GetCharFmtFromPool( RES_POOLCHR_JUMPEDIT );
+
+ // noch nicht registriert ?
+ if( !aDep.GetRegisteredIn() )
+ pFmt->Add( &aDep ); // anmelden
+
+ return pFmt;
+}
+
+SwJumpEditField::SwJumpEditField( SwJumpEditFieldType* pTyp, sal_uInt32 nForm,
+ const String& rTxt, const String& rHelp )
+ : SwField( pTyp, nForm ), sTxt( rTxt ), sHelp( rHelp )
+{
+}
+
+String SwJumpEditField::Expand() const
+{
+ String sTmp( '<' );
+ sTmp += sTxt;
+ return sTmp += '>';
+}
+
+SwField* SwJumpEditField::Copy() const
+{
+ return new SwJumpEditField( (SwJumpEditFieldType*)GetTyp(), GetFormat(),
+ sTxt, sHelp );
+}
+
+// Platzhalter-Text
+
+const String& SwJumpEditField::GetPar1() const
+{
+ return sTxt;
+}
+
+void SwJumpEditField::SetPar1(const String& rStr)
+{
+ sTxt = rStr;
+}
+
+// HinweisText
+
+String SwJumpEditField::GetPar2() const
+{
+ return sHelp;
+}
+
+void SwJumpEditField::SetPar2(const String& rStr)
+{
+ sHelp = rStr;
+}
+
+bool SwJumpEditField::QueryValue( uno::Any& rAny, sal_uInt16 nWhichId ) const
+{
+ switch( nWhichId )
+ {
+ case FIELD_PROP_USHORT1:
+ {
+ sal_Int16 nRet;
+ switch( GetFormat() )
+ {
+ case JE_FMT_TABLE: nRet = text::PlaceholderType::TABLE; break;
+ case JE_FMT_FRAME: nRet = text::PlaceholderType::TEXTFRAME; break;
+ case JE_FMT_GRAPHIC:nRet = text::PlaceholderType::GRAPHIC; break;
+ case JE_FMT_OLE: nRet = text::PlaceholderType::OBJECT; break;
+ default:
+ nRet = text::PlaceholderType::TEXT; break;
+ }
+ rAny <<= nRet;
+ }
+ break;
+ case FIELD_PROP_PAR1 :
+ rAny <<= OUString(sHelp);
+ break;
+ case FIELD_PROP_PAR2 :
+ rAny <<= OUString(sTxt);
+ break;
+ default:
+ OSL_FAIL("illegal property");
+ }
+ return true;
+}
+
+bool SwJumpEditField::PutValue( const uno::Any& rAny, sal_uInt16 nWhichId )
+{
+ switch( nWhichId )
+ {
+ case FIELD_PROP_USHORT1:
+ {
+ //JP 24.10.2001: int32 because in UnoField.cxx a putvalue is
+ // called with a int32 value! But normally we need
+ // here only a int16
+ sal_Int32 nSet = 0;
+ rAny >>= nSet;
+ switch( nSet )
+ {
+ case text::PlaceholderType::TEXT : SetFormat(JE_FMT_TEXT); break;
+ case text::PlaceholderType::TABLE : SetFormat(JE_FMT_TABLE); break;
+ case text::PlaceholderType::TEXTFRAME: SetFormat(JE_FMT_FRAME); break;
+ case text::PlaceholderType::GRAPHIC : SetFormat(JE_FMT_GRAPHIC); break;
+ case text::PlaceholderType::OBJECT : SetFormat(JE_FMT_OLE); break;
+ }
+ }
+ break;
+ case FIELD_PROP_PAR1 :
+ ::GetString( rAny, sHelp );
+ break;
+ case FIELD_PROP_PAR2 :
+ ::GetString( rAny, sTxt);
+ break;
+ default:
+ OSL_FAIL("illegal property");
+ }
+ return true;
+}
+
+
+/*--------------------------------------------------------------------
+ Beschreibung: Combined Character Fieldtype / Field
+ --------------------------------------------------------------------*/
+
+SwCombinedCharFieldType::SwCombinedCharFieldType()
+ : SwFieldType( RES_COMBINED_CHARS )
+{
+}
+
+SwFieldType* SwCombinedCharFieldType::Copy() const
+{
+ return new SwCombinedCharFieldType;
+}
+
+/* --------------------------------------------------------------------*/
+
+SwCombinedCharField::SwCombinedCharField( SwCombinedCharFieldType* pFTyp,
+ const String& rChars )
+ : SwField( pFTyp, 0 ),
+ sCharacters( rChars.Copy( 0, MAX_COMBINED_CHARACTERS ))
+{
+}
+
+String SwCombinedCharField::Expand() const
+{
+ return sCharacters;
+}
+
+SwField* SwCombinedCharField::Copy() const
+{
+ return new SwCombinedCharField( (SwCombinedCharFieldType*)GetTyp(),
+ sCharacters );
+}
+
+const String& SwCombinedCharField::GetPar1() const
+{
+ return sCharacters;
+}
+
+void SwCombinedCharField::SetPar1(const String& rStr)
+{
+ sCharacters = rStr.Copy( 0, MAX_COMBINED_CHARACTERS );
+}
+
+bool SwCombinedCharField::QueryValue( uno::Any& rAny,
+ sal_uInt16 nWhichId ) const
+{
+ switch( nWhichId )
+ {
+ case FIELD_PROP_PAR1:
+ rAny <<= rtl::OUString( sCharacters );
+ break;
+ default:
+ OSL_FAIL("illegal property");
+ }
+ return true;
+}
+
+bool SwCombinedCharField::PutValue( const uno::Any& rAny,
+ sal_uInt16 nWhichId )
+{
+ switch( nWhichId )
+ {
+ case FIELD_PROP_PAR1:
+ ::GetString( rAny, sCharacters ).Erase( MAX_COMBINED_CHARACTERS );
+ break;
+ default:
+ OSL_FAIL("illegal property");
+ }
+ return true;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/fields/expfld.cxx b/sw/source/core/fields/expfld.cxx
new file mode 100644
index 000000000000..9027ee7bf412
--- /dev/null
+++ b/sw/source/core/fields/expfld.cxx
@@ -0,0 +1,1300 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+#include <hintids.hxx>
+#include <unotools/collatorwrapper.hxx>
+#include <unotools/charclass.hxx>
+#include <editeng/unolingu.hxx>
+#include <svx/pageitem.hxx>
+#include <editeng/langitem.hxx>
+#include <editeng/fontitem.hxx>
+#include <com/sun/star/text/SetVariableType.hpp>
+#include <unofield.hxx>
+#include <frmfmt.hxx>
+#include <fmtfld.hxx>
+#include <txtfld.hxx>
+#include <fmtanchr.hxx>
+#include <txtftn.hxx>
+#include <doc.hxx>
+#include <layfrm.hxx>
+#include <pagefrm.hxx>
+#include <cntfrm.hxx>
+#include <rootfrm.hxx>
+#include <tabfrm.hxx>
+#include <flyfrm.hxx>
+#include <ftnfrm.hxx>
+#include <rowfrm.hxx>
+#include <expfld.hxx>
+#include <usrfld.hxx>
+#include <ndtxt.hxx>
+#include <calc.hxx>
+#include <pam.hxx>
+#include <docfld.hxx>
+#include <swcache.hxx>
+#include <swtable.hxx>
+#include <breakit.hxx>
+#include <SwStyleNameMapper.hxx>
+#include <unofldmid.h>
+#include <numrule.hxx>
+#include <switerator.hxx>
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::text;
+using ::rtl::OUString;
+
+SV_IMPL_PTRARR( _SwSeqFldList, _SeqFldLstElem* )
+
+//-----------------------------------------------------------------------------
+sal_Int16 lcl_SubTypeToAPI(sal_uInt16 nSubType)
+{
+ sal_Int16 nRet = 0;
+ switch(nSubType)
+ {
+ case nsSwGetSetExpType::GSE_EXPR:
+ nRet = SetVariableType::VAR; // 0
+ break;
+ case nsSwGetSetExpType::GSE_SEQ:
+ nRet = SetVariableType::SEQUENCE; // 1
+ break;
+ case nsSwGetSetExpType::GSE_FORMULA:
+ nRet = SetVariableType::FORMULA; // 2
+ break;
+ case nsSwGetSetExpType::GSE_STRING:
+ nRet = SetVariableType::STRING; // 3
+ break;
+ }
+ return nRet;
+}
+//-----------------------------------------------------------------------------
+sal_Int32 lcl_APIToSubType(const uno::Any& rAny)
+{
+ sal_Int16 nVal = 0;
+ rAny >>= nVal;
+ sal_Int32 nSet = 0;
+ switch(nVal)
+ {
+ case SetVariableType::VAR: nSet = nsSwGetSetExpType::GSE_EXPR; break;
+ case SetVariableType::SEQUENCE: nSet = nsSwGetSetExpType::GSE_SEQ; break;
+ case SetVariableType::FORMULA: nSet = nsSwGetSetExpType::GSE_FORMULA; break;
+ case SetVariableType::STRING: nSet = nsSwGetSetExpType::GSE_STRING; break;
+ default:
+ OSL_FAIL("wrong value");
+ nSet = -1;
+ }
+ return nSet;
+}
+
+//-----------------------------------------------------------------------------
+
+void ReplacePoint( String& rTmpName, sal_Bool bWithCommandType )
+{
+ // replace first and last (if bWithCommandType: last two) dot Ersten und letzten Punkt ersetzen, da in Tabellennamen Punkte erlaubt sind
+ // since table names may contain dots
+
+ xub_StrLen nLen = rTmpName.Len();
+ sal_Unicode *pStr = rTmpName.GetBufferAccess(), *pBackStr = pStr + nLen;
+
+ long nBackCount = bWithCommandType ? 2 : 1;
+ xub_StrLen i;
+
+ for( i = nLen; i; --i, pBackStr-- )
+ if( '.' == *pBackStr )
+ {
+ *pBackStr = DB_DELIM;
+ if(!--nBackCount)
+ break;
+ }
+ for( i = 0; i < nLen; ++i, ++pStr )
+ if( '.' == *pStr )
+ {
+ *pStr = DB_DELIM;
+ break;
+ }
+}
+
+SwTxtNode* GetFirstTxtNode( const SwDoc& rDoc, SwPosition& rPos,
+ const SwCntntFrm *pCFrm, Point &rPt )
+{
+ SwTxtNode* pTxtNode = 0;
+ if ( !pCFrm )
+ {
+ const SwNodes& rNodes = rDoc.GetNodes();
+ rPos.nNode = *rNodes.GetEndOfContent().StartOfSectionNode();
+ SwCntntNode* pCNd;
+ while( 0 != (pCNd = rNodes.GoNext( &rPos.nNode ) ) &&
+ 0 == ( pTxtNode = pCNd->GetTxtNode() ) )
+ ;
+ OSL_ENSURE( pTxtNode, "wo ist der 1.TextNode" );
+ rPos.nContent.Assign( pTxtNode, 0 );
+ }
+ else if ( !pCFrm->IsValid() )
+ {
+ pTxtNode = (SwTxtNode*)pCFrm->GetNode();
+ rPos.nNode = *pTxtNode;
+ rPos.nContent.Assign( pTxtNode, 0 );
+ }
+ else
+ {
+ pCFrm->GetCrsrOfst( &rPos, rPt );
+ pTxtNode = rPos.nNode.GetNode().GetTxtNode();
+ }
+ return pTxtNode;
+}
+
+const SwTxtNode* GetBodyTxtNode( const SwDoc& rDoc, SwPosition& rPos,
+ const SwFrm& rFrm )
+{
+ const SwLayoutFrm* pLayout = (SwLayoutFrm*)rFrm.GetUpper();
+ const SwTxtNode* pTxtNode = 0;
+
+ while( pLayout )
+ {
+ if( pLayout->IsFlyFrm() )
+ {
+ // hole das FlyFormat
+ SwFrmFmt* pFlyFmt = ((SwFlyFrm*)pLayout)->GetFmt();
+ OSL_ENSURE( pFlyFmt, "kein FlyFormat gefunden, wo steht das Feld" );
+
+ const SwFmtAnchor &rAnchor = pFlyFmt->GetAnchor();
+
+ if( FLY_AT_FLY == rAnchor.GetAnchorId() )
+ {
+ // und der Fly muss irgendwo angehaengt sein, also
+ // den befragen
+ pLayout = (SwLayoutFrm*)((SwFlyFrm*)pLayout)->GetAnchorFrm();
+ continue;
+ }
+ else if ((FLY_AT_PARA == rAnchor.GetAnchorId()) ||
+ (FLY_AT_CHAR == rAnchor.GetAnchorId()) ||
+ (FLY_AS_CHAR == rAnchor.GetAnchorId()))
+ {
+ OSL_ENSURE( rAnchor.GetCntntAnchor(), "keine gueltige Position" );
+ rPos = *rAnchor.GetCntntAnchor();
+ pTxtNode = rPos.nNode.GetNode().GetTxtNode();
+ if ( FLY_AT_PARA == rAnchor.GetAnchorId() )
+ {
+ const_cast<SwTxtNode*>(pTxtNode)->MakeStartIndex(
+ &rPos.nContent );
+// oder doch besser das Ende vom (Anker-)TextNode nehmen ??
+// ((SwTxtNode*)pTxtNode)->MakeEndIndex( &rPos.nContent );
+ }
+
+ // noch nicht abbrechen, kann ja auch noch im
+ // Header/Footer/Footnote/Fly stehen !!
+ pLayout = ((SwFlyFrm*)pLayout)->GetAnchorFrm()
+ ? ((SwFlyFrm*)pLayout)->GetAnchorFrm()->GetUpper() : 0;
+ continue;
+ }
+ else
+ {
+ pLayout->FindPageFrm()->GetCntntPosition(
+ pLayout->Frm().Pos(), rPos );
+ pTxtNode = rPos.nNode.GetNode().GetTxtNode();
+ }
+ }
+ else if( pLayout->IsFtnFrm() )
+ {
+ // hole den Node vom Anker
+ const SwTxtFtn* pFtn = ((SwFtnFrm*)pLayout)->GetAttr();
+ pTxtNode = &pFtn->GetTxtNode();
+ rPos.nNode = *pTxtNode;
+ rPos.nContent = *pFtn->GetStart();
+ }
+ else if( pLayout->IsHeaderFrm() || pLayout->IsFooterFrm() )
+ {
+ const SwCntntFrm* pCntFrm;
+ const SwPageFrm* pPgFrm = pLayout->FindPageFrm();
+ if( pLayout->IsHeaderFrm() )
+ {
+ const SwTabFrm *pTab;
+ if( 0 != ( pCntFrm = pPgFrm->FindFirstBodyCntnt()) &&
+ 0 != (pTab = pCntFrm->FindTabFrm()) && pTab->IsFollow() &&
+ pTab->GetTable()->GetRowsToRepeat() > 0 &&
+ pTab->IsInHeadline( *pCntFrm ) )
+ {
+ // take the next line
+ const SwLayoutFrm* pRow = pTab->GetFirstNonHeadlineRow();
+ pCntFrm = pRow->ContainsCntnt();
+ }
+ }
+ else
+ pCntFrm = pPgFrm->FindLastBodyCntnt();
+
+ if( pCntFrm )
+ {
+ pTxtNode = pCntFrm->GetNode()->GetTxtNode();
+ rPos.nNode = *pTxtNode;
+ ((SwTxtNode*)pTxtNode)->MakeEndIndex( &rPos.nContent );
+ }
+ else
+ {
+ Point aPt( pLayout->Frm().Pos() );
+ aPt.Y()++; // aus dem Header raus
+ pCntFrm = pPgFrm->GetCntntPos( aPt, sal_False, sal_True, sal_False );
+ pTxtNode = GetFirstTxtNode( rDoc, rPos, pCntFrm, aPt );
+ }
+ }
+ else
+ {
+ pLayout = pLayout->GetUpper();
+ continue;
+ }
+ break; // gefunden und beende die Schleife
+ }
+ return pTxtNode;
+}
+
+/*--------------------------------------------------------------------
+ Beschreibung: SwSetExpFieldType by JP
+ --------------------------------------------------------------------*/
+
+SwGetExpFieldType::SwGetExpFieldType(SwDoc* pDc)
+ : SwValueFieldType( pDc, RES_GETEXPFLD )
+{
+}
+
+SwFieldType* SwGetExpFieldType::Copy() const
+{
+ return new SwGetExpFieldType(GetDoc());
+}
+
+void SwGetExpFieldType::Modify( const SfxPoolItem*, const SfxPoolItem* pNew )
+{
+ if( pNew && RES_DOCPOS_UPDATE == pNew->Which() )
+ NotifyClients( 0, pNew );
+ // sonst nichts weiter expandieren
+}
+
+/*--------------------------------------------------------------------
+ Beschreibung: SwGetExpField by JP
+ --------------------------------------------------------------------*/
+
+SwGetExpField::SwGetExpField(SwGetExpFieldType* pTyp, const String& rFormel,
+ sal_uInt16 nSub, sal_uLong nFmt)
+ : SwFormulaField( pTyp, nFmt, 0.0 ),
+ bIsInBodyTxt( sal_True ),
+ nSubType(nSub),
+ bLateInitialization( false )
+{
+ SetFormula( rFormel );
+}
+
+String SwGetExpField::Expand() const
+{
+ if(nSubType & nsSwExtendedSubType::SUB_CMD)
+ return GetFormula();
+ else
+ return sExpand;
+}
+
+String SwGetExpField::GetFieldName() const
+{
+ String aStr( SwFieldType::GetTypeStr(
+ static_cast<sal_uInt16>(((nsSwGetSetExpType::GSE_FORMULA & nSubType) != 0)
+ ? TYP_FORMELFLD
+ : TYP_GETFLD ) ));
+ aStr += ' ';
+ aStr += GetFormula();
+ return aStr;
+}
+
+SwField* SwGetExpField::Copy() const
+{
+ SwGetExpField *pTmp = new SwGetExpField((SwGetExpFieldType*)GetTyp(),
+ GetFormula(), nSubType, GetFormat());
+ pTmp->SetLanguage(GetLanguage());
+ pTmp->SwValueField::SetValue(GetValue());
+ pTmp->sExpand = sExpand;
+ pTmp->bIsInBodyTxt = bIsInBodyTxt;
+ pTmp->SetAutomaticLanguage(IsAutomaticLanguage());
+ if( bLateInitialization )
+ pTmp->SetLateInitialization();
+
+ return pTmp;
+}
+
+void SwGetExpField::ChangeExpansion( const SwFrm& rFrm, const SwTxtFld& rFld )
+{
+ if( bIsInBodyTxt ) // nur Felder in Footer, Header, FootNote, Flys
+ return;
+
+ OSL_ENSURE( !rFrm.IsInDocBody(), "Flag ist nicht richtig, Frame steht im DocBody" );
+
+ // bestimme mal das Dokument (oder geht es noch einfacher?)
+ const SwTxtNode* pTxtNode = &rFld.GetTxtNode();
+ SwDoc& rDoc = *(SwDoc*)pTxtNode->GetDoc();
+
+ // einen Index fuers bestimmen vom TextNode anlegen
+ SwPosition aPos( SwNodeIndex( rDoc.GetNodes() ) );
+ pTxtNode = GetBodyTxtNode( rDoc, aPos, rFrm );
+
+ // Wenn kein Layout vorhanden, kommt es in Kopf und Fusszeilen dazu
+ // das ChnageExpansion uebers Layout-Formatieren aufgerufen wird
+ // aber kein TxtNode vorhanden ist
+ //
+ if(!pTxtNode)
+ return;
+ // #i82544#
+ if( bLateInitialization )
+ {
+ SwFieldType* pSetExpFld = rDoc.GetFldType(RES_SETEXPFLD, GetFormula(), sal_False);
+ if( pSetExpFld )
+ {
+ bLateInitialization = false;
+ if( !(GetSubType() & nsSwGetSetExpType::GSE_STRING) &&
+ static_cast< SwSetExpFieldType* >(pSetExpFld)->GetType() == nsSwGetSetExpType::GSE_STRING )
+ SetSubType( nsSwGetSetExpType::GSE_STRING );
+ }
+ }
+
+ _SetGetExpFld aEndFld( aPos.nNode, &rFld, &aPos.nContent );
+ if(GetSubType() & nsSwGetSetExpType::GSE_STRING)
+ {
+ SwHash** ppHashTbl;
+ sal_uInt16 nSize;
+ rDoc.FldsToExpand( ppHashTbl, nSize, aEndFld );
+ LookString( ppHashTbl, nSize, GetFormula(), sExpand );
+ ::DeleteHashTable( ppHashTbl, nSize ); // HashTabelle loeschen
+ }
+ else
+ {
+ // fuelle den Calculator mit den Werten
+ SwCalc aCalc( rDoc );
+ rDoc.FldsToCalc(aCalc, aEndFld);
+
+ // Wert berechnen
+ SetValue(aCalc.Calculate(GetFormula()).GetDouble());
+
+ // Auswertung nach Format
+ sExpand = ((SwValueFieldType*)GetTyp())->ExpandValue(
+ GetValue(), GetFormat(), GetLanguage());
+ }
+}
+
+String SwGetExpField::GetPar2() const
+{
+ return GetFormula();
+}
+
+void SwGetExpField::SetPar2(const String& rStr)
+{
+ SetFormula(rStr);
+}
+
+sal_uInt16 SwGetExpField::GetSubType() const
+{
+ return nSubType;
+}
+
+void SwGetExpField::SetSubType(sal_uInt16 nType)
+{
+ nSubType = nType;
+}
+
+void SwGetExpField::SetLanguage(sal_uInt16 nLng)
+{
+ if (nSubType & nsSwExtendedSubType::SUB_CMD)
+ SwField::SetLanguage(nLng);
+ else
+ SwValueField::SetLanguage(nLng);
+}
+
+bool SwGetExpField::QueryValue( uno::Any& rAny, sal_uInt16 nWhichId ) const
+{
+ switch( nWhichId )
+ {
+ case FIELD_PROP_DOUBLE:
+ rAny <<= GetValue();
+ break;
+ case FIELD_PROP_FORMAT:
+ rAny <<= (sal_Int32)GetFormat();
+ break;
+ case FIELD_PROP_USHORT1:
+ rAny <<= (sal_Int16)nSubType;
+ break;
+ case FIELD_PROP_PAR1:
+ rAny <<= OUString( GetFormula() );
+ break;
+ case FIELD_PROP_SUBTYPE:
+ {
+ sal_Int16 nRet = lcl_SubTypeToAPI(GetSubType() & 0xff);
+ rAny <<= nRet;
+ }
+ break;
+ case FIELD_PROP_BOOL2:
+ {
+ sal_Bool bTmp = 0 != (nSubType & nsSwExtendedSubType::SUB_CMD);
+ rAny.setValue(&bTmp, ::getBooleanCppuType());
+ }
+ break;
+ case FIELD_PROP_PAR4:
+ rAny <<= rtl::OUString(GetExpStr());
+ break;
+ default:
+ return SwField::QueryValue(rAny, nWhichId);
+ }
+ return true;
+}
+
+bool SwGetExpField::PutValue( const uno::Any& rAny, sal_uInt16 nWhichId )
+{
+ sal_Int32 nTmp = 0;
+ String sTmp;
+ switch( nWhichId )
+ {
+ case FIELD_PROP_DOUBLE:
+ SwValueField::SetValue(*(double*) rAny.getValue());
+ break;
+ case FIELD_PROP_FORMAT:
+ rAny >>= nTmp;
+ SetFormat(nTmp);
+ break;
+ case FIELD_PROP_USHORT1:
+ rAny >>= nTmp;
+ nSubType = static_cast<sal_uInt16>(nTmp);
+ break;
+ case FIELD_PROP_PAR1:
+ SetFormula( ::GetString( rAny, sTmp ));
+ break;
+ case FIELD_PROP_SUBTYPE:
+ nTmp = lcl_APIToSubType(rAny);
+ if( nTmp >=0 )
+ SetSubType( static_cast<sal_uInt16>((GetSubType() & 0xff00) | nTmp));
+ break;
+ case FIELD_PROP_BOOL2:
+ if(*(sal_Bool*) rAny.getValue())
+ nSubType |= nsSwExtendedSubType::SUB_CMD;
+ else
+ nSubType &= (~nsSwExtendedSubType::SUB_CMD);
+ break;
+ case FIELD_PROP_PAR4:
+ ChgExpStr(::GetString( rAny, sTmp ));
+ break;
+ default:
+ return SwField::PutValue(rAny, nWhichId);
+ }
+ return true;
+}
+
+SwSetExpFieldType::SwSetExpFieldType( SwDoc* pDc, const String& rName, sal_uInt16 nTyp )
+ : SwValueFieldType( pDc, RES_SETEXPFLD ),
+ sName( rName ),
+ pOutlChgNd( 0 ),
+ sDelim( String::CreateFromAscii( "." ) ),
+ nType(nTyp), nLevel( UCHAR_MAX ),
+ bDeleted( sal_False )
+{
+ if( ( nsSwGetSetExpType::GSE_SEQ | nsSwGetSetExpType::GSE_STRING ) & nType )
+ EnableFormat(sal_False); // Numberformatter nicht einsetzen
+}
+
+SwFieldType* SwSetExpFieldType::Copy() const
+{
+ SwSetExpFieldType* pNew = new SwSetExpFieldType(GetDoc(), sName, nType);
+ pNew->bDeleted = bDeleted;
+ pNew->sDelim = sDelim;
+ pNew->nLevel = nLevel;
+
+ return pNew;
+}
+
+const String& SwSetExpFieldType::GetName() const
+{
+ return sName;
+}
+
+void SwSetExpFieldType::Modify( const SfxPoolItem*, const SfxPoolItem* )
+{
+ return; // nicht weiter expandieren
+}
+
+void SwSetExpFieldType::SetSeqFormat(sal_uLong nFmt)
+{
+ SwIterator<SwFmtFld,SwFieldType> aIter(*this);
+ for( SwFmtFld* pFld = aIter.First(); pFld; pFld = aIter.Next() )
+ pFld->GetFld()->ChangeFormat( nFmt );
+}
+
+sal_uLong SwSetExpFieldType::GetSeqFormat()
+{
+ if( !GetDepends() )
+ return SVX_NUM_ARABIC;
+
+ SwField *pFld = ((SwFmtFld*)GetDepends())->GetFld();
+ return pFld->GetFormat();
+}
+
+sal_uInt16 SwSetExpFieldType::SetSeqRefNo( SwSetExpField& rFld )
+{
+ if( !GetDepends() || !(nsSwGetSetExpType::GSE_SEQ & nType) )
+ return USHRT_MAX;
+
+extern void InsertSort( SvUShorts& rArr, sal_uInt16 nIdx, sal_uInt16* pInsPos = 0 );
+ SvUShorts aArr( 64 );
+
+ sal_uInt16 n;
+
+ // dann testmal, ob die Nummer schon vergeben ist oder ob eine neue
+ // bestimmt werden muss.
+ SwIterator<SwFmtFld,SwFieldType> aIter( *this );
+ const SwTxtNode* pNd;
+ for( SwFmtFld* pF = aIter.First(); pF; pF = aIter.Next() )
+ if( pF->GetFld() != &rFld && pF->GetTxtFld() &&
+ 0 != ( pNd = pF->GetTxtFld()->GetpTxtNode() ) &&
+ pNd->GetNodes().IsDocNodes() )
+ InsertSort( aArr, ((SwSetExpField*)pF->GetFld())->GetSeqNumber() );
+
+
+ // teste erstmal ob die Nummer schon vorhanden ist:
+ sal_uInt16 nNum = rFld.GetSeqNumber();
+ if( USHRT_MAX != nNum )
+ {
+ for( n = 0; n < aArr.Count(); ++n )
+ if( aArr[ n ] > nNum )
+ return nNum; // nicht vorhanden -> also benutzen
+ else if( aArr[ n ] == nNum )
+ break; // schon vorhanden -> neue erzeugen
+
+ if( n == aArr.Count() )
+ return nNum; // nicht vorhanden -> also benutzen
+ }
+
+ // alle Nummern entsprechend geflag, also bestimme die richtige Nummer
+ for( n = 0; n < aArr.Count(); ++n )
+ if( n != aArr[ n ] )
+ break;
+
+ rFld.SetSeqNumber( n );
+ return n;
+}
+
+sal_uInt16 SwSetExpFieldType::GetSeqFldList( SwSeqFldList& rList )
+{
+ if( rList.Count() )
+ rList.Remove( 0, rList.Count() );
+
+ SwIterator<SwFmtFld,SwFieldType> aIter( *this );
+ const SwTxtNode* pNd;
+ for( SwFmtFld* pF = aIter.First(); pF; pF = aIter.Next() )
+ if( pF->GetTxtFld() &&
+ 0 != ( pNd = pF->GetTxtFld()->GetpTxtNode() ) &&
+ pNd->GetNodes().IsDocNodes() )
+ {
+ _SeqFldLstElem* pNew = new _SeqFldLstElem(
+ pNd->GetExpandTxt( 0, (*pF->GetTxtFld()->GetStart()) + 1 ),
+ ((SwSetExpField*)pF->GetFld())->GetSeqNumber() );
+ rList.InsertSort( pNew );
+ }
+
+ return rList.Count();
+}
+
+
+void SwSetExpFieldType::SetChapter( SwSetExpField& rFld, const SwNode& rNd )
+{
+ const SwTxtNode* pTxtNd = rNd.FindOutlineNodeOfLevel( nLevel );
+ if( pTxtNd )
+ {
+ SwNumRule * pRule = pTxtNd->GetNumRule();
+
+ if (pRule)
+ {
+ // --> OD 2005-11-02 #i51089 - TUNING#
+ if ( pTxtNd->GetNum() )
+ {
+ const SwNodeNum & aNum = *(pTxtNd->GetNum());
+
+ // nur die Nummer besorgen, ohne Pre-/Post-fixstrings
+ String sNumber( pRule->MakeNumString(aNum, sal_False ));
+
+ if( sNumber.Len() )
+ rFld.ChgExpStr( ( sNumber += sDelim ) += rFld.GetExpStr() );
+ }
+ else
+ {
+ OSL_FAIL( "<SwSetExpFieldType::SetChapter(..)> - text node with numbering rule, but without number. This is a serious defect -> inform OD" );
+ }
+ }
+ }
+}
+
+bool SwSetExpFieldType::QueryValue( uno::Any& rAny, sal_uInt16 nWhichId ) const
+{
+ switch( nWhichId )
+ {
+ case FIELD_PROP_SUBTYPE:
+ {
+ sal_Int16 nRet = lcl_SubTypeToAPI(GetType());
+ rAny <<= nRet;
+ }
+ break;
+ case FIELD_PROP_PAR2:
+ rAny <<= OUString(GetDelimiter());
+ break;
+ case FIELD_PROP_SHORT1:
+ {
+ sal_Int8 nRet = nLevel < MAXLEVEL? nLevel : -1;
+ rAny <<= nRet;
+ }
+ break;
+ default:
+ OSL_FAIL("illegal property");
+ }
+ return true;
+}
+
+bool SwSetExpFieldType::PutValue( const uno::Any& rAny, sal_uInt16 nWhichId )
+{
+ switch( nWhichId )
+ {
+ case FIELD_PROP_SUBTYPE:
+ {
+ sal_Int32 nSet = lcl_APIToSubType(rAny);
+ if(nSet >=0)
+ SetType(static_cast<sal_uInt16>(nSet));
+ }
+ break;
+ case FIELD_PROP_PAR2:
+ {
+ String sTmp;
+ if( ::GetString( rAny, sTmp ).Len() )
+// SetDelimiter( sTmp.GetChar( 0 ));
+ SetDelimiter( sTmp );
+ else
+ SetDelimiter(String::CreateFromAscii( " "));
+ }
+ break;
+ case FIELD_PROP_SHORT1:
+ {
+ sal_Int8 nLvl = 0;
+ rAny >>= nLvl;
+ if(nLvl < 0 || nLvl >= MAXLEVEL)
+ SetOutlineLvl(UCHAR_MAX);
+ else
+ SetOutlineLvl(nLvl);
+ }
+ break;
+ default:
+ OSL_FAIL("illegal property");
+ }
+ return true;
+}
+
+sal_Bool SwSeqFldList::InsertSort( _SeqFldLstElem* pNew )
+{
+ sal_Unicode* p = pNew->sDlgEntry.GetBufferAccess();
+ while( *p )
+ {
+ if( *p < 0x20 )
+ *p = 0x20;
+ ++p;
+ }
+
+ sal_uInt16 nPos;
+ sal_Bool bRet = SeekEntry( *pNew, &nPos );
+ if( !bRet )
+ C40_INSERT( _SeqFldLstElem, pNew, nPos );
+ return bRet;
+}
+
+sal_Bool SwSeqFldList::SeekEntry( const _SeqFldLstElem& rNew, sal_uInt16* pP )
+{
+ sal_uInt16 nO = Count(), nM, nU = 0;
+ if( nO > 0 )
+ {
+ CollatorWrapper & rCaseColl = ::GetAppCaseCollator(),
+ & rColl = ::GetAppCollator();
+ const CharClass& rCC = GetAppCharClass();
+
+ //#59900# Die Sortierung soll die Nummer korrekt einordnen
+ //also "10" nach "9" und nicht "10" nach "1"
+ const String& rTmp2 = rNew.sDlgEntry;
+ xub_StrLen nFndPos2 = 0;
+ String sNum2( rTmp2.GetToken( 0, ' ', nFndPos2 ));
+ sal_Bool bIsNum2IsNumeric = rCC.isAsciiNumeric( sNum2 );
+ sal_Int32 nNum2 = bIsNum2IsNumeric ? sNum2.ToInt32() : 0;
+
+ nO--;
+ while( nU <= nO )
+ {
+ nM = nU + ( nO - nU ) / 2;
+
+ //#59900# Die Sortierung soll die Nummer korrekt einordnen
+ //also "10" nach "9" und nicht "10" nach "1"
+ const String& rTmp1 = (*((_SeqFldLstElem**)pData + nM))->sDlgEntry;
+ xub_StrLen nFndPos1 = 0;
+ String sNum1( rTmp1.GetToken( 0, ' ', nFndPos1 ));
+ sal_Int32 nCmp;
+
+ if( bIsNum2IsNumeric && rCC.isNumeric( sNum1 ) )
+ {
+ sal_Int32 nNum1 = sNum1.ToInt32();
+ nCmp = nNum2 - nNum1;
+ if( 0 == nCmp )
+ nCmp = rCaseColl.compareString( rTmp2.Copy( nFndPos2 ),
+ rTmp1.Copy( nFndPos1 ));
+ }
+ else
+ nCmp = rColl.compareString( rTmp2, rTmp1 );
+
+ if( 0 == nCmp )
+ {
+ if( pP ) *pP = nM;
+ return sal_True;
+ }
+ else if( 0 < nCmp )
+ nU = nM + 1;
+ else if( nM == 0 )
+ break;
+ else
+ nO = nM - 1;
+ }
+ }
+ if( pP ) *pP = nU;
+ return sal_False;
+}
+
+/*--------------------------------------------------------------------
+ Beschreibung: SwSetExpField by JP
+ --------------------------------------------------------------------*/
+
+SwSetExpField::SwSetExpField(SwSetExpFieldType* pTyp, const String& rFormel,
+ sal_uLong nFmt)
+ : SwFormulaField( pTyp, nFmt, 0.0 ), nSeqNo( USHRT_MAX ),
+ nSubType(0)
+{
+ SetFormula(rFormel);
+ // SubType ignorieren !!!
+ bInput = sal_False;
+ if( IsSequenceFld() )
+ {
+ SwValueField::SetValue(1.0);
+ if( !rFormel.Len() )
+ {
+ String sFormel(rFormel);
+ sFormel += pTyp->GetName();
+ sFormel += '+';
+ sFormel += '1';
+ SetFormula(sFormel);
+ }
+ }
+}
+
+String SwSetExpField::Expand() const
+{
+ String aStr;
+ if (nSubType & nsSwExtendedSubType::SUB_CMD)
+ { // Der CommandString ist gefragt
+ aStr = GetTyp()->GetName();
+ aStr.AppendAscii( RTL_CONSTASCII_STRINGPARAM( " = " ));
+ aStr += GetFormula();
+ }
+ else if(!(nSubType & nsSwExtendedSubType::SUB_INVISIBLE))
+ { // Der Wert ist sichtbar
+ aStr = sExpand;
+ }
+ return aStr;
+}
+
+/*--------------------------------------------------------------------
+ @return the field name
+ --------------------------------------------------------------------*/
+
+String SwSetExpField::GetFieldName() const
+{
+ SwFldTypesEnum const nStrType( (IsSequenceFld())
+ ? TYP_SEQFLD
+ : (bInput)
+ ? TYP_SETINPFLD
+ : TYP_SETFLD );
+
+ String aStr( SwFieldType::GetTypeStr( static_cast<sal_uInt16>(nStrType) ) );
+ aStr += ' ';
+ aStr += GetTyp()->GetName();
+
+ // Sequence: without formula
+ if (TYP_SEQFLD != nStrType)
+ {
+ aStr.AppendAscii( RTL_CONSTASCII_STRINGPARAM( " = " ) );
+ aStr += GetFormula();
+ }
+ return aStr;
+}
+
+SwField* SwSetExpField::Copy() const
+{
+ SwSetExpField *pTmp = new SwSetExpField((SwSetExpFieldType*)GetTyp(),
+ GetFormula(), GetFormat());
+ pTmp->SwValueField::SetValue(GetValue());
+ pTmp->sExpand = sExpand;
+ pTmp->SetAutomaticLanguage(IsAutomaticLanguage());
+ pTmp->SetLanguage(GetLanguage());
+ pTmp->aPText = aPText;
+ pTmp->bInput = bInput;
+ pTmp->nSeqNo = nSeqNo;
+ pTmp->SetSubType(GetSubType());
+
+ return pTmp;
+}
+
+void SwSetExpField::SetSubType(sal_uInt16 nSub)
+{
+ ((SwSetExpFieldType*)GetTyp())->SetType(nSub & 0xff);
+ nSubType = nSub & 0xff00;
+
+ DBG_ASSERT( (nSub & 0xff) != 3, "SubType ist illegal!" );
+}
+
+sal_uInt16 SwSetExpField::GetSubType() const
+{
+ return ((SwSetExpFieldType*)GetTyp())->GetType() | nSubType;
+}
+
+void SwSetExpField::SetValue( const double& rAny )
+{
+ SwValueField::SetValue(rAny);
+
+ if( IsSequenceFld() )
+ sExpand = FormatNumber( (sal_uInt16)GetValue(), GetFormat() );
+ else
+ sExpand = ((SwValueFieldType*)GetTyp())->ExpandValue( rAny,
+ GetFormat(), GetLanguage());
+}
+
+void SwGetExpField::SetValue( const double& rAny )
+{
+ SwValueField::SetValue(rAny);
+ sExpand = ((SwValueFieldType*)GetTyp())->ExpandValue( rAny, GetFormat(),
+ GetLanguage());
+}
+/* --------------------------------------------------
+ Description: Find the index of the reference text
+ following the current field
+ --------------------------------------------------*/
+xub_StrLen SwGetExpField::GetReferenceTextPos( const SwFmtFld& rFmt, SwDoc& rDoc)
+{
+ //
+ const SwTxtFld* pTxtFld = rFmt.GetTxtFld();
+ const SwTxtNode& rTxtNode = pTxtFld->GetTxtNode();
+ //
+ xub_StrLen nRet = *pTxtFld->GetStart() + 1;
+ String sNodeText = rTxtNode.GetTxt();
+ sNodeText.Erase(0, nRet);
+ if(sNodeText.Len())
+ {
+ //now check if sNodeText starts with a non-alphanumeric character plus a blank
+ sal_uInt16 nSrcpt = pBreakIt->GetRealScriptOfText( sNodeText, 0 );
+
+ static sal_uInt16 nIds[] =
+ {
+ RES_CHRATR_LANGUAGE, RES_CHRATR_LANGUAGE,
+ RES_CHRATR_FONT, RES_CHRATR_FONT,
+ RES_CHRATR_CJK_LANGUAGE, RES_CHRATR_CJK_LANGUAGE,
+ RES_CHRATR_CJK_FONT, RES_CHRATR_CJK_FONT,
+ RES_CHRATR_CTL_LANGUAGE, RES_CHRATR_CTL_LANGUAGE,
+ RES_CHRATR_CTL_FONT, RES_CHRATR_CTL_FONT,
+ 0, 0
+ };
+ SwAttrSet aSet(rDoc.GetAttrPool(), nIds);
+ rTxtNode.GetAttr(aSet, nRet, nRet+1);
+
+ if( RTL_TEXTENCODING_SYMBOL != ((SvxFontItem&)aSet.Get(
+ GetWhichOfScript( RES_CHRATR_FONT, nSrcpt )) ).GetCharSet() )
+ {
+ LanguageType eLang = ((SvxLanguageItem&)aSet.Get(
+ GetWhichOfScript( RES_CHRATR_LANGUAGE, nSrcpt )) ).GetLanguage();
+ CharClass aCC( SvxCreateLocale( eLang ));
+ sal_Unicode c0 = sNodeText.GetChar(0);
+ sal_Bool bIsAlphaNum = aCC.isAlphaNumeric( sNodeText, 0 );
+ if( !bIsAlphaNum ||
+ (c0 == ' ' || c0 == '\t'))
+ {
+ nRet++;
+ if( sNodeText.Len() > 1 &&
+ (sNodeText.GetChar(1) == ' ' ||
+ sNodeText.GetChar(1) == '\t'))
+ nRet++;
+ }
+ }
+ }
+ return nRet;
+}
+
+
+/*--------------------------------------------------------------------
+ Beschreibung: Parameter setzen
+ --------------------------------------------------------------------*/
+
+const String& SwSetExpField::GetPar1() const
+{
+ return ((SwSetExpFieldType*)GetTyp())->GetName();
+}
+
+String SwSetExpField::GetPar2() const
+{
+ sal_uInt16 nType = ((SwSetExpFieldType*)GetTyp())->GetType();
+
+ if (nType & nsSwGetSetExpType::GSE_STRING)
+ return GetFormula();
+ return GetExpandedFormula();
+}
+
+void SwSetExpField::SetPar2(const String& rStr)
+{
+ sal_uInt16 nType = ((SwSetExpFieldType*)GetTyp())->GetType();
+
+ if( !(nType & nsSwGetSetExpType::GSE_SEQ) || rStr.Len() )
+ {
+ if (nType & nsSwGetSetExpType::GSE_STRING)
+ SetFormula(rStr);
+ else
+ SetExpandedFormula(rStr);
+ }
+}
+
+/*--------------------------------------------------------------------
+ Beschreibung: Eingabefeld Type
+ ---------------------------------------------------------------------*/
+
+SwInputFieldType::SwInputFieldType( SwDoc* pD )
+ : SwFieldType( RES_INPUTFLD ), pDoc( pD )
+{
+}
+
+SwFieldType* SwInputFieldType::Copy() const
+{
+ SwInputFieldType* pType = new SwInputFieldType( pDoc );
+ return pType;
+}
+
+/*--------------------------------------------------------------------
+ Beschreibung: Eingabefeld
+ --------------------------------------------------------------------*/
+
+SwInputField::SwInputField(SwInputFieldType* pTyp, const String& rContent,
+ const String& rPrompt, sal_uInt16 nSub, sal_uLong nFmt) :
+ SwField(pTyp, nFmt), aContent(rContent), aPText(rPrompt), nSubType(nSub)
+{
+}
+
+String SwInputField::GetFieldName() const
+{
+ String aStr(SwField::GetFieldName());
+ if ((nSubType & 0x00ff) == INP_USR)
+ {
+ aStr += GetTyp()->GetName();
+ aStr += ' ';
+ aStr += aContent;
+ }
+ return aStr;
+}
+
+SwField* SwInputField::Copy() const
+{
+ SwInputField* pFld = new SwInputField((SwInputFieldType*)GetTyp(), aContent,
+ aPText, GetSubType(), GetFormat());
+
+ pFld->SetHelp(aHelp);
+ pFld->SetToolTip(aToolTip);
+
+ pFld->SetAutomaticLanguage(IsAutomaticLanguage());
+ return pFld;
+}
+
+String SwInputField::Expand() const
+{
+ String sRet;
+ if((nSubType & 0x00ff) == INP_TXT)
+ sRet = aContent;
+
+ else if( (nSubType & 0x00ff) == INP_USR )
+ {
+ SwUserFieldType* pUserTyp = (SwUserFieldType*)
+ ((SwInputFieldType*)GetTyp())->GetDoc()->
+ GetFldType( RES_USERFLD, aContent, false );
+ if( pUserTyp )
+ sRet = pUserTyp->GetContent();
+ }
+ return sRet;
+}
+
+bool SwInputField::QueryValue( uno::Any& rAny, sal_uInt16 nWhichId ) const
+{
+ switch( nWhichId )
+ {
+ case FIELD_PROP_PAR1:
+ rAny <<= OUString( aContent );
+ break;
+ case FIELD_PROP_PAR2:
+ rAny <<= OUString( aPText );
+ break;
+ case FIELD_PROP_PAR3:
+ rAny <<= OUString( aHelp );
+ break;
+ case FIELD_PROP_PAR4:
+ rAny <<= OUString( aToolTip );
+ break;
+ default:
+ OSL_FAIL("illegal property");
+ }
+ return true;
+}
+
+bool SwInputField::PutValue( const uno::Any& rAny, sal_uInt16 nWhichId )
+{
+ switch( nWhichId )
+ {
+ case FIELD_PROP_PAR1:
+ ::GetString( rAny, aContent );
+ break;
+ case FIELD_PROP_PAR2:
+ ::GetString( rAny, aPText );
+ break;
+ case FIELD_PROP_PAR3:
+ ::GetString( rAny, aHelp );
+ break;
+ case FIELD_PROP_PAR4:
+ ::GetString( rAny, aToolTip );
+ break;
+ default:
+ OSL_FAIL("illegal property");
+ }
+ return true;
+}
+/*--------------------------------------------------------------------
+ Beschreibung: Bedingung setzen
+ --------------------------------------------------------------------*/
+
+void SwInputField::SetPar1(const String& rStr)
+{
+ aContent = rStr;
+}
+
+const String& SwInputField::GetPar1() const
+{
+ return aContent;
+}
+
+/*--------------------------------------------------------------------
+ Beschreibung: True/False Text
+ --------------------------------------------------------------------*/
+
+void SwInputField::SetPar2(const String& rStr)
+{
+ aPText = rStr;
+}
+
+String SwInputField::GetPar2() const
+{
+ return aPText;
+}
+
+void SwInputField::SetHelp(const String & rStr)
+{
+ aHelp = rStr;
+}
+
+String SwInputField::GetHelp() const
+{
+ return aHelp;
+}
+
+void SwInputField::SetToolTip(const String & rStr)
+{
+ aToolTip = rStr;
+}
+
+String SwInputField::GetToolTip() const
+{
+ return aToolTip;
+}
+
+sal_Bool SwInputField::isFormField() const
+{
+ return aHelp.Len() > 0 || aToolTip.Len() > 0;
+}
+
+sal_uInt16 SwInputField::GetSubType() const
+{
+ return nSubType;
+}
+
+void SwInputField::SetSubType(sal_uInt16 nSub)
+{
+ nSubType = nSub;
+}
+
+bool SwSetExpField::QueryValue( uno::Any& rAny, sal_uInt16 nWhichId ) const
+{
+ switch( nWhichId )
+ {
+ case FIELD_PROP_BOOL2:
+ {
+ sal_Bool bVal = 0 == (nSubType & nsSwExtendedSubType::SUB_INVISIBLE);
+ rAny.setValue(&bVal, ::getBooleanCppuType());
+ }
+ break;
+ case FIELD_PROP_FORMAT:
+ rAny <<= (sal_Int32)GetFormat();
+ break;
+ case FIELD_PROP_USHORT2:
+ rAny <<= (sal_Int16)GetFormat();
+ break;
+ case FIELD_PROP_USHORT1:
+ rAny <<= (sal_Int16)nSeqNo;
+ break;
+ case FIELD_PROP_PAR1:
+ rAny <<= OUString ( SwStyleNameMapper::GetProgName(GetPar1(), nsSwGetPoolIdFromName::GET_POOLID_TXTCOLL ) );
+ break;
+ case FIELD_PROP_PAR2:
+ {
+ //I18N - if the formula contains only "TypeName+1"
+ //and it's one of the initially created sequence fields
+ //then the localized names has to be replaced by a programmatic name
+ OUString sMyFormula = SwXFieldMaster::LocalizeFormula(*this, GetFormula(), sal_True);
+ rAny <<= OUString( sMyFormula );
+ }
+ break;
+ case FIELD_PROP_DOUBLE:
+ rAny <<= (double)GetValue();
+ break;
+ case FIELD_PROP_SUBTYPE:
+ {
+ sal_Int16 nRet = 0;
+ nRet = lcl_SubTypeToAPI(GetSubType() & 0xff);
+ rAny <<= nRet;
+ }
+ break;
+ case FIELD_PROP_PAR3:
+ rAny <<= OUString( aPText );
+ break;
+ case FIELD_PROP_BOOL3:
+ {
+ sal_Bool bTmp = 0 != (nSubType & nsSwExtendedSubType::SUB_CMD);
+ rAny.setValue(&bTmp, ::getBooleanCppuType());
+ }
+ break;
+ case FIELD_PROP_BOOL1:
+ {
+ sal_Bool bTmp = GetInputFlag();
+ rAny.setValue(&bTmp, ::getBooleanCppuType());
+ }
+ break;
+ case FIELD_PROP_PAR4:
+ rAny <<= rtl::OUString(GetExpStr());
+ break;
+ default:
+ return SwField::QueryValue(rAny, nWhichId);
+ }
+ return true;
+}
+
+bool SwSetExpField::PutValue( const uno::Any& rAny, sal_uInt16 nWhichId )
+{
+ sal_Int32 nTmp32 = 0;
+ sal_Int16 nTmp16 = 0;
+ String sTmp;
+ switch( nWhichId )
+ {
+ case FIELD_PROP_BOOL2:
+ if(*(sal_Bool*)rAny.getValue())
+ nSubType &= ~nsSwExtendedSubType::SUB_INVISIBLE;
+ else
+ nSubType |= nsSwExtendedSubType::SUB_INVISIBLE;
+ break;
+ case FIELD_PROP_FORMAT:
+ rAny >>= nTmp32;
+ SetFormat(nTmp32);
+ break;
+ case FIELD_PROP_USHORT2:
+ {
+ rAny >>= nTmp16;
+ if(nTmp16 <= SVX_NUMBER_NONE )
+ SetFormat(nTmp16);
+ else {
+ }
+ }
+ break;
+ case FIELD_PROP_USHORT1:
+ rAny >>= nTmp16;
+ nSeqNo = nTmp16;
+ break;
+ case FIELD_PROP_PAR1:
+ SetPar1( SwStyleNameMapper::GetUIName(
+ ::GetString( rAny, sTmp ), nsSwGetPoolIdFromName::GET_POOLID_TXTCOLL ) );
+ break;
+ case FIELD_PROP_PAR2:
+ {
+ OUString uTmp;
+ rAny >>= uTmp;
+ //I18N - if the formula contains only "TypeName+1"
+ //and it's one of the initially created sequence fields
+ //then the localized names has to be replaced by a programmatic name
+ OUString sMyFormula = SwXFieldMaster::LocalizeFormula(*this, uTmp, sal_False);
+ SetFormula( sMyFormula );
+ }
+ break;
+ case FIELD_PROP_DOUBLE:
+ {
+ double fVal = 0.0;
+ rAny >>= fVal;
+ SetValue(fVal);
+ }
+ break;
+ case FIELD_PROP_SUBTYPE:
+ nTmp32 = lcl_APIToSubType(rAny);
+ if(nTmp32 >= 0)
+ SetSubType(static_cast<sal_uInt16>((GetSubType() & 0xff00) | nTmp32));
+ break;
+ case FIELD_PROP_PAR3:
+ ::GetString( rAny, aPText );
+ break;
+ case FIELD_PROP_BOOL3:
+ if(*(sal_Bool*) rAny.getValue())
+ nSubType |= nsSwExtendedSubType::SUB_CMD;
+ else
+ nSubType &= (~nsSwExtendedSubType::SUB_CMD);
+ break;
+ case FIELD_PROP_BOOL1:
+ SetInputFlag(*(sal_Bool*) rAny.getValue());
+ break;
+ case FIELD_PROP_PAR4:
+ ChgExpStr( ::GetString( rAny, sTmp ));
+ break;
+ default:
+ return SwField::PutValue(rAny, nWhichId);
+ }
+ return true;
+}
+
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/fields/fldbas.cxx b/sw/source/core/fields/fldbas.cxx
new file mode 100644
index 000000000000..b14864d52c98
--- /dev/null
+++ b/sw/source/core/fields/fldbas.cxx
@@ -0,0 +1,776 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+#include <float.h>
+#include <rtl/math.hxx>
+#include <svl/zforlist.hxx>
+#include <svl/zformat.hxx>
+#include <editeng/unolingu.hxx>
+#include <unofldmid.h>
+#include <doc.hxx>
+#include <editsh.hxx>
+#include <frame.hxx>
+#include <fldbas.hxx>
+#include <flddat.hxx>
+#include <ndtxt.hxx>
+#include <fmtfld.hxx>
+#include <txtfld.hxx>
+#include <pam.hxx>
+#include <docfld.hxx>
+#include <swtable.hxx>
+#include <docufld.hxx>
+#include <expfld.hxx>
+#include <shellres.hxx>
+#include <calc.hxx>
+#include <comcore.hrc>
+
+#include <math.h>
+
+using namespace ::com::sun::star;
+using namespace nsSwDocInfoSubType;
+
+sal_uInt16 lcl_GetLanguageOfFormat( sal_uInt16 nLng, sal_uLong nFmt,
+ const SvNumberFormatter& rFormatter )
+{
+ if( nLng == LANGUAGE_NONE ) // wegen Bug #60010
+ nLng = LANGUAGE_SYSTEM;
+ else if( nLng == ::GetAppLanguage() )
+ switch( rFormatter.GetIndexTableOffset( nFmt ))
+ {
+ case NF_NUMBER_SYSTEM:
+ case NF_DATE_SYSTEM_SHORT:
+ case NF_DATE_SYSTEM_LONG:
+ case NF_DATETIME_SYSTEM_SHORT_HHMM:
+ nLng = LANGUAGE_SYSTEM;
+ break;
+ default: break;
+ }
+ return nLng;
+}
+
+/*--------------------------------------------------------------------
+ Beschreibung: Globals
+ --------------------------------------------------------------------*/
+// Array der Feldname
+
+SvStringsDtor* SwFieldType::pFldNames = 0;
+
+DBG_NAME(SwFieldType)
+
+ sal_uInt16 aTypeTab[] = {
+ /* RES_DBFLD */ TYP_DBFLD,
+ /* RES_USERFLD */ TYP_USERFLD,
+ /* RES_FILENAMEFLD */ TYP_FILENAMEFLD,
+ /* RES_DBNAMEFLD */ TYP_DBNAMEFLD,
+ /* RES_DATEFLD */ TYP_DATEFLD,
+ /* RES_TIMEFLD */ TYP_TIMEFLD,
+ /* RES_PAGENUMBERFLD */ TYP_PAGENUMBERFLD, // dynamisch
+ /* RES_AUTHORFLD */ TYP_AUTHORFLD,
+ /* RES_CHAPTERFLD */ TYP_CHAPTERFLD,
+ /* RES_DOCSTATFLD */ TYP_DOCSTATFLD,
+ /* RES_GETEXPFLD */ TYP_GETFLD, // dynamisch
+ /* RES_SETEXPFLD */ TYP_SETFLD, // dynamisch
+ /* RES_GETREFFLD */ TYP_GETREFFLD,
+ /* RES_HIDDENTXTFLD */ TYP_HIDDENTXTFLD,
+ /* RES_POSTITFLD */ TYP_POSTITFLD,
+ /* RES_FIXDATEFLD */ TYP_FIXDATEFLD,
+ /* RES_FIXTIMEFLD */ TYP_FIXTIMEFLD,
+ /* RES_REGFLD */ 0, // alt
+ /* RES_VARREGFLD */ 0, // alt
+ /* RES_SETREFFLD */ TYP_SETREFFLD,
+ /* RES_INPUTFLD */ TYP_INPUTFLD,
+ /* RES_MACROFLD */ TYP_MACROFLD,
+ /* RES_DDEFLD */ TYP_DDEFLD,
+ /* RES_TABLEFLD */ TYP_FORMELFLD,
+ /* RES_HIDDENPARAFLD */ TYP_HIDDENPARAFLD,
+ /* RES_DOCINFOFLD */ TYP_DOCINFOFLD,
+ /* RES_TEMPLNAMEFLD */ TYP_TEMPLNAMEFLD,
+ /* RES_DBNEXTSETFLD */ TYP_DBNEXTSETFLD,
+ /* RES_DBNUMSETFLD */ TYP_DBNUMSETFLD,
+ /* RES_DBSETNUMBERFLD */ TYP_DBSETNUMBERFLD,
+ /* RES_EXTUSERFLD */ TYP_EXTUSERFLD,
+ /* RES_REFPAGESETFLD */ TYP_SETREFPAGEFLD,
+ /* RES_REFPAGEGETFLD */ TYP_GETREFPAGEFLD,
+ /* RES_INTERNETFLD */ TYP_INTERNETFLD,
+ /* RES_JUMPEDITFLD */ TYP_JUMPEDITFLD,
+ /* RES_SCRIPTFLD */ TYP_SCRIPTFLD,
+ /* RES_DATETIMEFLD */ 0, // dynamisch
+ /* RES_AUTHORITY */ TYP_AUTHORITY,
+ /* RES_COMBINED_CHARS */ TYP_COMBINED_CHARS,
+ /* RES_DROPDOWN */ TYP_DROPDOWN
+ };
+ // ????? TYP_USRINPFLD,
+
+
+
+const String& SwFieldType::GetTypeStr(sal_uInt16 nTypeId)
+{
+ if( !pFldNames )
+ _GetFldName();
+
+ if( nTypeId < SwFieldType::pFldNames->Count() )
+ return *SwFieldType::pFldNames->GetObject( nTypeId );
+ else
+ return aEmptyStr;
+}
+
+
+/*---------------------------------------------------
+ Jedes Feld referenziert einen Feldtypen, der fuer
+ jedes Dokument einmalig ist.
+ --------------------------------------------------*/
+
+SwFieldType::SwFieldType( sal_uInt16 nWhichId )
+ : SwModify(0),
+ nWhich( nWhichId )
+{
+ DBG_CTOR( SwFieldType, 0 );
+}
+
+#if OSL_DEBUG_LEVEL > 1
+
+SwFieldType::~SwFieldType()
+{
+ DBG_DTOR( SwFieldType, 0 );
+}
+
+#endif
+
+const String& SwFieldType::GetName() const
+{
+ return aEmptyStr;
+}
+
+bool SwFieldType::QueryValue( uno::Any&, sal_uInt16 ) const
+{
+ return false;
+}
+bool SwFieldType::PutValue( const uno::Any& , sal_uInt16 )
+{
+ return false;
+}
+
+/*--------------------------------------------------------------------
+ Beschreibung: Basisklasse aller Felder
+ Felder referenzieren einen Feldtyp
+ Felder sind n-mal vorhanden, Feldtypen nur einmal
+ --------------------------------------------------------------------*/
+
+SwField::SwField(SwFieldType* pTyp, sal_uInt32 nFmt, sal_uInt16 nLng) :
+ nLang(nLng),
+ bIsAutomaticLanguage(sal_True),
+ nFormat(nFmt)
+{
+ OSL_ENSURE( pTyp, "SwField: ungueltiger SwFieldType" );
+ pType = pTyp;
+}
+
+SwField::~SwField()
+{
+}
+
+/*--------------------------------------------------------------------
+ Beschreibung: Statt Umweg ueber den Typ
+ --------------------------------------------------------------------*/
+
+#if OSL_DEBUG_LEVEL > 1
+sal_uInt16 SwField::Which() const
+{
+ OSL_ENSURE(pType, "Kein Typ vorhanden");
+ return pType->Which();
+}
+#endif
+
+sal_uInt16 SwField::GetTypeId() const
+{
+
+ sal_uInt16 nRet;
+ switch( pType->Which() )
+ {
+ case RES_DATETIMEFLD:
+ if (GetSubType() & FIXEDFLD)
+ nRet = static_cast<sal_uInt16>(GetSubType() & DATEFLD ? TYP_FIXDATEFLD : TYP_FIXTIMEFLD);
+ else
+ nRet = static_cast<sal_uInt16>(GetSubType() & DATEFLD ? TYP_DATEFLD : TYP_TIMEFLD);
+ break;
+ case RES_GETEXPFLD:
+ nRet = static_cast<sal_uInt16>(nsSwGetSetExpType::GSE_FORMULA & GetSubType() ? TYP_FORMELFLD : TYP_GETFLD);
+ break;
+
+ case RES_HIDDENTXTFLD:
+ nRet = GetSubType();
+ break;
+
+ case RES_SETEXPFLD:
+ if( nsSwGetSetExpType::GSE_SEQ & GetSubType() )
+ nRet = TYP_SEQFLD;
+ else if( ((SwSetExpField*)this)->GetInputFlag() )
+ nRet = TYP_SETINPFLD;
+ else
+ nRet = TYP_SETFLD;
+ break;
+
+ case RES_PAGENUMBERFLD:
+ nRet = GetSubType();
+ if( PG_NEXT == nRet )
+ nRet = TYP_NEXTPAGEFLD;
+ else if( PG_PREV == nRet )
+ nRet = TYP_PREVPAGEFLD;
+ else
+ nRet = TYP_PAGENUMBERFLD;
+ break;
+
+ default:
+ nRet = aTypeTab[ pType->Which() ];
+ }
+ return nRet;
+}
+
+
+/*--------------------------------------------------------------------
+ Beschreibung: liefert den Namen oder den Inhalt
+ --------------------------------------------------------------------*/
+
+String SwField::GetFieldName() const
+{
+ sal_uInt16 nTypeId = GetTypeId();
+ if (RES_DATETIMEFLD == GetTyp()->Which())
+ {
+ nTypeId = static_cast<sal_uInt16>(
+ ((GetSubType() & DATEFLD) != 0) ? TYP_DATEFLD : TYP_TIMEFLD);
+ }
+ String sRet = SwFieldType::GetTypeStr( nTypeId );
+ if (IsFixed())
+ {
+ sRet += ' ';
+ sRet += ViewShell::GetShellRes()->aFixedStr;
+ }
+ return sRet;
+}
+
+/*--------------------------------------------------------------------
+ Beschreibung: Parameter setzen auslesen
+ --------------------------------------------------------------------*/
+
+const String& SwField::GetPar1() const
+{
+ return aEmptyStr;
+}
+
+String SwField::GetPar2() const
+{
+ return aEmptyStr;
+}
+
+String SwField::GetFormula() const
+{
+ return GetPar2();
+}
+
+void SwField::SetPar1(const String& )
+{}
+
+void SwField::SetPar2(const String& )
+{}
+
+sal_uInt16 SwField::GetSubType() const
+{
+ return 0;
+}
+
+void SwField::SetSubType(sal_uInt16 )
+{
+}
+
+bool SwField::QueryValue( uno::Any& rVal, sal_uInt16 nWhichId ) const
+{
+ switch( nWhichId )
+ {
+ case FIELD_PROP_BOOL4:
+ {
+ sal_Bool bFixed = !bIsAutomaticLanguage;
+ rVal.setValue(&bFixed, ::getCppuBooleanType());
+ }
+ break;
+ default:
+ OSL_FAIL("illegal property");
+ }
+ return true;
+}
+bool SwField::PutValue( const uno::Any& rVal, sal_uInt16 nWhichId )
+{
+ switch( nWhichId )
+ {
+ case FIELD_PROP_BOOL4:
+ {
+ sal_Bool bFixed = sal_False;
+ if(rVal >>= bFixed)
+ bIsAutomaticLanguage = !bFixed;
+ }
+ break;
+ default:
+ OSL_FAIL("illegal property");
+ }
+ return true;
+}
+
+
+/*--------------------------------------------------------------------
+ Beschreibung: neuen Typ setzen
+ (wird fuer das Kopieren zwischen Dokumenten benutzt)
+ muss immer vom gleichen Typ sein.
+ --------------------------------------------------------------------*/
+
+SwFieldType* SwField::ChgTyp( SwFieldType* pNewType )
+{
+ OSL_ENSURE( pNewType && pNewType->Which() == pType->Which(),
+ "kein Typ oder ungleiche Typen" );
+
+ SwFieldType* pOld = pType;
+ pType = pNewType;
+ return pOld;
+}
+
+ // hat das Feld eine Action auf dem ClickHandler ? (z.B. INetFelder,..)
+sal_Bool SwField::HasClickHdl() const
+{
+ sal_Bool bRet = sal_False;
+ switch( pType->Which() )
+ {
+ case RES_INTERNETFLD:
+ case RES_JUMPEDITFLD:
+ case RES_GETREFFLD:
+ case RES_MACROFLD:
+ case RES_INPUTFLD:
+ case RES_DROPDOWN :
+ bRet = sal_True;
+ break;
+
+ case RES_SETEXPFLD:
+ bRet = ((SwSetExpField*)this)->GetInputFlag();
+ break;
+ }
+ return bRet;
+}
+
+void SwField::SetLanguage(sal_uInt16 nLng)
+{
+ nLang = nLng;
+}
+
+void SwField::ChangeFormat(sal_uInt32 n)
+{
+ nFormat = n;
+}
+
+sal_Bool SwField::IsFixed() const
+{
+ sal_Bool bRet = sal_False;
+ switch( pType->Which() )
+ {
+ case RES_FIXDATEFLD:
+ case RES_FIXTIMEFLD:
+ bRet = sal_True;
+ break;
+
+ case RES_DATETIMEFLD:
+ bRet = 0 != (GetSubType() & FIXEDFLD);
+ break;
+
+ case RES_EXTUSERFLD:
+ case RES_AUTHORFLD:
+ bRet = 0 != (GetFormat() & AF_FIXED);
+ break;
+
+ case RES_FILENAMEFLD:
+ bRet = 0 != (GetFormat() & FF_FIXED);
+ break;
+
+ case RES_DOCINFOFLD:
+ bRet = 0 != (GetSubType() & DI_SUB_FIXED);
+ break;
+ }
+ return bRet;
+}
+
+String SwField::ExpandField(bool const bCached) const
+{
+ if (!bCached) // #i85766# do not expand fields in clipboard documents
+ {
+ m_Cache = Expand();
+ }
+ return m_Cache;
+}
+
+SwField * SwField::CopyField() const
+{
+ SwField *const pNew = Copy();
+ // #i85766# cache expansion of source (for clipboard)
+ // use this->cache, not this->Expand(): only text formatting calls Expand()
+ pNew->m_Cache = m_Cache;
+ return pNew;
+}
+
+/*--------------------------------------------------------------------
+ Beschreibung: Numerierung expandieren
+ --------------------------------------------------------------------*/
+
+String FormatNumber(sal_uInt16 nNum, sal_uInt32 nFormat)
+{
+ if(SVX_NUM_PAGEDESC == nFormat)
+ return String::CreateFromInt32( nNum );
+ SvxNumberType aNumber;
+
+ OSL_ENSURE(nFormat != SVX_NUM_NUMBER_NONE, "Falsches Nummern-Format" );
+
+ aNumber.SetNumberingType((sal_Int16)nFormat);
+ return aNumber.GetNumStr(nNum);
+}
+
+/*--------------------------------------------------------------------
+ Beschreibung: CTOR SwValueFieldType
+ --------------------------------------------------------------------*/
+
+SwValueFieldType::SwValueFieldType( SwDoc* pDocPtr, sal_uInt16 nWhichId )
+ : SwFieldType(nWhichId),
+ pDoc(pDocPtr),
+ bUseFormat(sal_True)
+{
+}
+
+SwValueFieldType::SwValueFieldType( const SwValueFieldType& rTyp )
+ : SwFieldType(rTyp.Which()),
+ pDoc(rTyp.GetDoc()),
+ bUseFormat(rTyp.UseFormat())
+{
+}
+
+/*--------------------------------------------------------------------
+ Beschreibung: Wert formatiert als String zurueckgeben
+ --------------------------------------------------------------------*/
+
+String SwValueFieldType::ExpandValue( const double& rVal,
+ sal_uInt32 nFmt, sal_uInt16 nLng) const
+{
+ if (rVal >= DBL_MAX) // FehlerString fuer Calculator
+ return ViewShell::GetShellRes()->aCalc_Error;
+
+ String sExpand;
+ SvNumberFormatter* pFormatter = pDoc->GetNumberFormatter();
+ Color* pCol = 0;
+
+ // wegen Bug #60010
+ sal_uInt16 nFmtLng = ::lcl_GetLanguageOfFormat( nLng, nFmt, *pFormatter );
+
+ if( nFmt < SV_COUNTRY_LANGUAGE_OFFSET && LANGUAGE_SYSTEM != nFmtLng )
+ {
+ short nType = NUMBERFORMAT_DEFINED;
+ xub_StrLen nDummy;
+
+ const SvNumberformat* pEntry = pFormatter->GetEntry(nFmt);
+
+ if (pEntry && nLng != pEntry->GetLanguage())
+ {
+ sal_uInt32 nNewFormat = pFormatter->GetFormatForLanguageIfBuiltIn(nFmt,
+ (LanguageType)nFmtLng);
+
+ if (nNewFormat == nFmt)
+ {
+ // Warscheinlich benutzerdefiniertes Format
+ String sFmt(pEntry->GetFormatstring());
+
+ pFormatter->PutandConvertEntry(sFmt, nDummy, nType, nFmt,
+ pEntry->GetLanguage(), nFmtLng );
+ }
+ else
+ nFmt = nNewFormat;
+ }
+ OSL_ENSURE(pEntry, "Unbekanntes Zahlenformat!");
+ }
+
+ if( pFormatter->IsTextFormat( nFmt ) )
+ {
+ String sValue;
+ DoubleToString(sValue, rVal, nFmtLng);
+ pFormatter->GetOutputString(sValue, nFmt, sExpand, &pCol);
+ }
+ else
+ pFormatter->GetOutputString(rVal, nFmt, sExpand, &pCol);
+
+ return sExpand;
+}
+
+void SwValueFieldType::DoubleToString( String &rValue, const double &rVal,
+ sal_uInt32 nFmt) const
+{
+ SvNumberFormatter* pFormatter = pDoc->GetNumberFormatter();
+ const SvNumberformat* pEntry = pFormatter->GetEntry(nFmt);
+
+ if (pEntry)
+ DoubleToString(rValue, rVal, pEntry->GetLanguage());
+}
+
+void SwValueFieldType::DoubleToString( String &rValue, const double &rVal,
+ sal_uInt16 nLng ) const
+{
+ SvNumberFormatter* pFormatter = pDoc->GetNumberFormatter();
+
+ // wegen Bug #60010
+ if( nLng == LANGUAGE_NONE ) // wegen Bug #60010
+ nLng = LANGUAGE_SYSTEM;
+
+ pFormatter->ChangeIntl( nLng ); // Separator in der richtigen Sprache besorgen
+ rValue = ::rtl::math::doubleToUString( rVal, rtl_math_StringFormat_F, 12,
+ pFormatter->GetDecSep(), true );
+}
+
+/*--------------------------------------------------------------------
+ Beschreibung: CTOR SwValueField
+ --------------------------------------------------------------------*/
+
+SwValueField::SwValueField( SwValueFieldType* pFldType, sal_uInt32 nFmt,
+ sal_uInt16 nLng, const double fVal )
+ : SwField(pFldType, nFmt, nLng),
+ fValue(fVal)
+{
+}
+
+SwValueField::SwValueField( const SwValueField& rFld )
+ : SwField(rFld),
+ fValue(rFld.GetValue())
+{
+}
+
+SwValueField::~SwValueField()
+{
+}
+/*--------------------------------------------------------------------
+ Beschreibung: neuen Typ setzen
+ (wird fuer das Kopieren zwischen Dokumenten benutzt)
+ muss immer vom gleichen Typ sein.
+ --------------------------------------------------------------------*/
+
+SwFieldType* SwValueField::ChgTyp( SwFieldType* pNewType )
+{
+ SwDoc* pNewDoc = ((SwValueFieldType *)pNewType)->GetDoc();
+ SwDoc* pDoc = GetDoc();
+
+ if( pNewDoc && pDoc && pDoc != pNewDoc)
+ {
+ SvNumberFormatter* pFormatter = pNewDoc->GetNumberFormatter();
+
+ if( pFormatter && pFormatter->HasMergeFmtTbl() &&
+ ((SwValueFieldType *)GetTyp())->UseFormat() )
+ SetFormat(pFormatter->GetMergeFmtIndex( GetFormat() ));
+ }
+
+ return SwField::ChgTyp(pNewType);
+}
+
+/*--------------------------------------------------------------------
+ Beschreibung: Format in Office-Sprache ermitteln
+ --------------------------------------------------------------------*/
+
+sal_uInt32 SwValueField::GetSystemFormat(SvNumberFormatter* pFormatter, sal_uInt32 nFmt)
+{
+ const SvNumberformat* pEntry = pFormatter->GetEntry(nFmt);
+ sal_uInt16 nLng = SvxLocaleToLanguage( SvtSysLocale().GetLocaleData().getLocale() );
+
+ if (pEntry && nLng != pEntry->GetLanguage())
+ {
+ sal_uInt32 nNewFormat = pFormatter->GetFormatForLanguageIfBuiltIn(nFmt,
+ (LanguageType)nLng);
+
+ if (nNewFormat == nFmt)
+ {
+ // Warscheinlich benutzerdefiniertes Format
+ short nType = NUMBERFORMAT_DEFINED;
+ xub_StrLen nDummy;
+
+ String sFmt(pEntry->GetFormatstring());
+
+ sal_uInt32 nFormat = nFmt;
+ pFormatter->PutandConvertEntry(sFmt, nDummy, nType,
+ nFormat, pEntry->GetLanguage(), nLng);
+ nFmt = nFormat;
+ }
+ else
+ nFmt = nNewFormat;
+ }
+
+ return nFmt;
+}
+
+/*--------------------------------------------------------------------
+ Beschreibung: Sprache im Format anpassen
+ --------------------------------------------------------------------*/
+
+void SwValueField::SetLanguage( sal_uInt16 nLng )
+{
+ if( IsAutomaticLanguage() &&
+ ((SwValueFieldType *)GetTyp())->UseFormat() &&
+ GetFormat() != SAL_MAX_UINT32 )
+ {
+ // wegen Bug #60010
+ SvNumberFormatter* pFormatter = GetDoc()->GetNumberFormatter();
+ sal_uInt16 nFmtLng = ::lcl_GetLanguageOfFormat( nLng, GetFormat(),
+ *pFormatter );
+
+ if( (GetFormat() >= SV_COUNTRY_LANGUAGE_OFFSET ||
+ LANGUAGE_SYSTEM != nFmtLng ) &&
+ !(Which() == RES_USERFLD && (GetSubType()&nsSwExtendedSubType::SUB_CMD) ) )
+ {
+ const SvNumberformat* pEntry = pFormatter->GetEntry(GetFormat());
+
+ if( pEntry && nFmtLng != pEntry->GetLanguage() )
+ {
+ sal_uInt32 nNewFormat = pFormatter->GetFormatForLanguageIfBuiltIn(
+ GetFormat(), (LanguageType)nFmtLng );
+
+ if( nNewFormat == GetFormat() )
+ {
+ // Warscheinlich benutzerdefiniertes Format
+ short nType = NUMBERFORMAT_DEFINED;
+ xub_StrLen nDummy;
+ String sFmt( pEntry->GetFormatstring() );
+ pFormatter->PutandConvertEntry( sFmt, nDummy, nType,
+ nNewFormat,
+ pEntry->GetLanguage(),
+ nFmtLng );
+ }
+ SetFormat( nNewFormat );
+ }
+ OSL_ENSURE(pEntry, "Unbekanntes Zahlenformat!");
+ }
+ }
+
+ SwField::SetLanguage(nLng);
+}
+
+double SwValueField::GetValue() const
+{
+ return fValue;
+}
+
+void SwValueField::SetValue( const double& rVal )
+{
+ fValue = rVal;
+}
+
+/*--------------------------------------------------------------------
+ Beschreibung: SwFormulaField
+ --------------------------------------------------------------------*/
+
+SwFormulaField::SwFormulaField( SwValueFieldType* pFldType, sal_uInt32 nFmt, const double fVal)
+ : SwValueField(pFldType, nFmt, LANGUAGE_SYSTEM, fVal)
+{
+}
+
+SwFormulaField::SwFormulaField( const SwFormulaField& rFld )
+ : SwValueField((SwValueFieldType *)rFld.GetTyp(), rFld.GetFormat(),
+ rFld.GetLanguage(), rFld.GetValue())
+{
+}
+
+String SwFormulaField::GetFormula() const
+{
+ return sFormula;
+}
+
+void SwFormulaField::SetFormula(const String& rStr)
+{
+ sFormula = rStr;
+
+ sal_uLong nFmt(GetFormat());
+
+ if( nFmt && SAL_MAX_UINT32 != nFmt )
+ {
+ xub_StrLen nPos = 0;
+ double fTmpValue;
+ if( SwCalc::Str2Double( rStr, nPos, fTmpValue, GetDoc() ) )
+ SwValueField::SetValue( fTmpValue );
+ }
+}
+
+void SwFormulaField::SetExpandedFormula( const String& rStr )
+{
+ sal_uInt32 nFmt(GetFormat());
+
+ if (nFmt && nFmt != SAL_MAX_UINT32 && ((SwValueFieldType *)GetTyp())->UseFormat())
+ {
+ double fTmpValue;
+
+ SvNumberFormatter* pFormatter = GetDoc()->GetNumberFormatter();
+
+ if (pFormatter->IsNumberFormat(rStr, nFmt, fTmpValue))
+ {
+ SwValueField::SetValue(fTmpValue);
+ sFormula.Erase();
+
+ ((SwValueFieldType *)GetTyp())->DoubleToString(sFormula, fTmpValue, nFmt);
+ return;
+ }
+ }
+ sFormula = rStr;
+}
+
+String SwFormulaField::GetExpandedFormula() const
+{
+ sal_uInt32 nFmt(GetFormat());
+
+ if (nFmt && nFmt != SAL_MAX_UINT32 && ((SwValueFieldType *)GetTyp())->UseFormat())
+ {
+ String sFormattedValue;
+ Color* pCol = 0;
+
+ SvNumberFormatter* pFormatter = GetDoc()->GetNumberFormatter();
+
+ if (pFormatter->IsTextFormat(nFmt))
+ {
+ String sValue;
+ ((SwValueFieldType *)GetTyp())->DoubleToString(sValue, GetValue(), nFmt);
+ pFormatter->GetOutputString(sValue, nFmt, sFormattedValue, &pCol);
+ }
+ else
+ pFormatter->GetOutputString(GetValue(), nFmt, sFormattedValue, &pCol);
+
+ return sFormattedValue;
+ }
+ else
+ return GetFormula();
+}
+
+String SwField::GetDescription() const
+{
+ return SW_RES(STR_FIELD);
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/fields/flddat.cxx b/sw/source/core/fields/flddat.cxx
new file mode 100644
index 000000000000..098d7a49ffb9
--- /dev/null
+++ b/sw/source/core/fields/flddat.cxx
@@ -0,0 +1,270 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+#include <tools/datetime.hxx>
+#include <svl/zforlist.hxx>
+#include <com/sun/star/util/DateTime.hpp>
+#include <doc.hxx>
+#include <fldbas.hxx>
+#include <flddat.hxx>
+#include <unofldmid.h>
+
+using namespace ::com::sun::star;
+/*--------------------------------------------------
+ Beschreibung: Datum/Zeit-Typ
+ ---------------------------------------------------*/
+
+SwDateTimeFieldType::SwDateTimeFieldType(SwDoc* pInitDoc)
+ : SwValueFieldType( pInitDoc, RES_DATETIMEFLD )
+{}
+
+SwFieldType* SwDateTimeFieldType::Copy() const
+{
+ SwDateTimeFieldType *pTmp = new SwDateTimeFieldType(GetDoc());
+ return pTmp;
+}
+
+/*--------------------------------------------------------------------
+ Beschreibung: Datum/Zeit-Feld
+ --------------------------------------------------------------------*/
+
+SwDateTimeField::SwDateTimeField(SwDateTimeFieldType* pInitType, sal_uInt16 nSub, sal_uLong nFmt, sal_uInt16 nLng)
+ : SwValueField(pInitType, nFmt, nLng, 0.0),
+ nSubType(nSub),
+ nOffset(0)
+{
+ if (!nFmt)
+ {
+ SvNumberFormatter* pFormatter = GetDoc()->GetNumberFormatter();
+ if (nSubType & DATEFLD)
+ ChangeFormat(pFormatter->GetFormatIndex(NF_DATE_SYSTEM_SHORT, GetLanguage()));
+ else
+ ChangeFormat(pFormatter->GetFormatIndex(NF_TIME_HHMMSS, GetLanguage()));
+ }
+ if (IsFixed())
+ {
+ DateTime aDateTime;
+ SetDateTime(aDateTime);
+ }
+}
+
+String SwDateTimeField::Expand() const
+{
+ double fVal;
+
+ if (!(IsFixed()))
+ {
+ DateTime aDateTime;
+ fVal = GetDateTime(GetDoc(), aDateTime);
+ }
+ else
+ fVal = GetValue();
+
+ if (nOffset)
+ fVal += (double)(nOffset * 60L) / 86400.0;
+
+ return ExpandValue(fVal, GetFormat(), GetLanguage());
+}
+
+SwField* SwDateTimeField::Copy() const
+{
+ SwDateTimeField *pTmp =
+ new SwDateTimeField((SwDateTimeFieldType*)GetTyp(), nSubType,
+ GetFormat(), GetLanguage());
+
+ pTmp->SetValue(GetValue());
+ pTmp->SetOffset(nOffset);
+ pTmp->SetAutomaticLanguage(IsAutomaticLanguage());
+
+ return pTmp;
+}
+
+sal_uInt16 SwDateTimeField::GetSubType() const
+{
+ return nSubType;
+}
+
+void SwDateTimeField::SetSubType(sal_uInt16 nType)
+{
+ nSubType = nType;
+}
+
+void SwDateTimeField::SetPar2(const String& rStr)
+{
+ nOffset = rStr.ToInt32();
+}
+
+String SwDateTimeField::GetPar2() const
+{
+ if (nOffset)
+ return String::CreateFromInt32(nOffset);
+ else
+ return aEmptyStr;
+}
+
+void SwDateTimeField::SetDateTime(const DateTime& rDT)
+{
+ SetValue(GetDateTime(GetDoc(), rDT));
+}
+
+double SwDateTimeField::GetDateTime(SwDoc* pDoc, const DateTime& rDT)
+{
+ SvNumberFormatter* pFormatter = pDoc->GetNumberFormatter();
+ Date* pNullDate = pFormatter->GetNullDate();
+
+ double fResult = rDT - DateTime(*pNullDate);
+
+ return fResult;
+}
+
+double SwDateTimeField::GetValue() const
+{
+ if (IsFixed())
+ return SwValueField::GetValue();
+ else
+ return GetDateTime(GetDoc(), DateTime());
+}
+
+Date SwDateTimeField::GetDate(sal_Bool bUseOffset) const
+{
+ SvNumberFormatter* pFormatter = GetDoc()->GetNumberFormatter();
+ Date* pNullDate = pFormatter->GetNullDate();
+
+ long nVal = static_cast<long>( GetValue() );
+
+ if (bUseOffset && nOffset)
+ nVal += nOffset / 60 / 24;
+
+ Date aDate = *pNullDate + nVal;
+
+ return aDate;
+}
+
+Time SwDateTimeField::GetTime(sal_Bool bUseOffset) const
+{
+ double fDummy;
+ double fFract = modf(GetValue(), &fDummy);
+ DateTime aDT((long)fDummy, 0);
+ aDT += fFract;
+ if (bUseOffset)
+ aDT += Time(0, nOffset);
+ return (Time)aDT;
+}
+
+bool SwDateTimeField::QueryValue( uno::Any& rVal, sal_uInt16 nWhichId ) const
+{
+ switch( nWhichId )
+ {
+ case FIELD_PROP_BOOL1:
+ {
+ sal_Bool bTmp = IsFixed();
+ rVal.setValue(&bTmp, ::getCppuBooleanType());
+ }
+ break;
+ case FIELD_PROP_BOOL2:
+ {
+ sal_Bool bTmp = IsDate();
+ rVal.setValue(&bTmp, ::getCppuBooleanType());
+ }
+ break;
+ case FIELD_PROP_FORMAT:
+ rVal <<= (sal_Int32)GetFormat();
+ break;
+ case FIELD_PROP_SUBTYPE:
+ rVal <<= (sal_Int32)nOffset;
+ break;
+ case FIELD_PROP_DATE_TIME:
+ {
+ DateTime aDateTime(GetDate(), GetTime());
+
+ util::DateTime DateTimeValue;
+ DateTimeValue.HundredthSeconds = aDateTime.Get100Sec();
+ DateTimeValue.Seconds = aDateTime.GetSec();
+ DateTimeValue.Minutes = aDateTime.GetMin();
+ DateTimeValue.Hours = aDateTime.GetHour();
+ DateTimeValue.Day = aDateTime.GetDay();
+ DateTimeValue.Month = aDateTime.GetMonth();
+ DateTimeValue.Year = aDateTime.GetYear();
+ rVal <<= DateTimeValue;
+ }
+ break;
+ default:
+ return SwField::QueryValue(rVal, nWhichId);
+ }
+ return true;
+}
+
+bool SwDateTimeField::PutValue( const uno::Any& rVal, sal_uInt16 nWhichId )
+{
+ sal_Int32 nTmp = 0;
+ switch( nWhichId )
+ {
+ case FIELD_PROP_BOOL1:
+ if(*(sal_Bool*)rVal.getValue())
+ nSubType |= FIXEDFLD;
+ else
+ nSubType &= ~FIXEDFLD;
+ break;
+ case FIELD_PROP_BOOL2:
+ nSubType &= ~(DATEFLD|TIMEFLD);
+ nSubType |= *(sal_Bool*)rVal.getValue() ? DATEFLD : TIMEFLD;
+ break;
+ case FIELD_PROP_FORMAT:
+ rVal >>= nTmp;
+ ChangeFormat(nTmp);
+ break;
+ case FIELD_PROP_SUBTYPE:
+ rVal >>= nTmp;
+ nOffset = nTmp;
+ break;
+ case FIELD_PROP_DATE_TIME:
+ {
+ util::DateTime aDateTimeValue;
+ if(!(rVal >>= aDateTimeValue))
+ return sal_False;
+ DateTime aDateTime;
+ aDateTime.Set100Sec(aDateTimeValue.HundredthSeconds);
+ aDateTime.SetSec(aDateTimeValue.Seconds);
+ aDateTime.SetMin(aDateTimeValue.Minutes);
+ aDateTime.SetHour(aDateTimeValue.Hours);
+ aDateTime.SetDay(aDateTimeValue.Day);
+ aDateTime.SetMonth(aDateTimeValue.Month);
+ aDateTime.SetYear(aDateTimeValue.Year);
+ SetDateTime(aDateTime);
+ }
+ break;
+ default:
+ return SwField::PutValue(rVal, nWhichId);
+ }
+ return true;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/fields/flddropdown.cxx b/sw/source/core/fields/flddropdown.cxx
new file mode 100644
index 000000000000..0e866b1e1c51
--- /dev/null
+++ b/sw/source/core/fields/flddropdown.cxx
@@ -0,0 +1,285 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+#include <flddropdown.hxx>
+
+#ifndef INCLUDED_ALGORITHM
+#include <algorithm>
+#define INCLUDED_ALGORITHM
+#endif
+#include <svl/poolitem.hxx>
+
+#include <unofldmid.h>
+#include <unoprnms.hxx>
+
+using namespace com::sun::star;
+
+using rtl::OUString;
+using std::vector;
+
+static String aEmptyString;
+
+SwDropDownFieldType::SwDropDownFieldType()
+ : SwFieldType(RES_DROPDOWN)
+{
+}
+
+SwDropDownFieldType::~SwDropDownFieldType()
+{
+}
+
+SwFieldType * SwDropDownFieldType::Copy() const
+{
+ return new SwDropDownFieldType;
+}
+
+SwDropDownField::SwDropDownField(SwFieldType * pTyp)
+ : SwField(pTyp, 0, LANGUAGE_SYSTEM)
+{
+}
+
+SwDropDownField::SwDropDownField(const SwDropDownField & rSrc)
+ : SwField(rSrc.GetTyp(), rSrc.GetFormat(), rSrc.GetLanguage()),
+ aValues(rSrc.aValues), aSelectedItem(rSrc.aSelectedItem),
+ aName(rSrc.aName), aHelp(rSrc.aHelp), aToolTip(rSrc.aToolTip)
+{
+}
+
+SwDropDownField::~SwDropDownField()
+{
+}
+
+String SwDropDownField::Expand() const
+{
+ String sSelect = GetSelectedItem();
+ if(!sSelect.Len())
+ {
+ vector<String>::const_iterator aIt = aValues.begin();
+ if ( aIt != aValues.end())
+ sSelect = *aIt;
+ }
+ //if still no list value is available a default text of 10 spaces is to be set
+ if(!sSelect.Len())
+ sSelect.AppendAscii ( RTL_CONSTASCII_STRINGPARAM (" "));
+ return sSelect;
+}
+
+SwField * SwDropDownField::Copy() const
+{
+ return new SwDropDownField(*this);
+}
+
+const String & SwDropDownField::GetPar1() const
+{
+ return GetSelectedItem();
+}
+
+String SwDropDownField::GetPar2() const
+{
+ return GetName();
+}
+
+void SwDropDownField::SetPar1(const String & rStr)
+{
+ SetSelectedItem(rStr);
+}
+
+void SwDropDownField::SetPar2(const String & rName)
+{
+ SetName(rName);
+}
+
+void SwDropDownField::SetItems(const vector<String> & rItems)
+{
+ aValues = rItems;
+ aSelectedItem = aEmptyString;
+}
+
+void SwDropDownField::SetItems(const uno::Sequence<OUString> & rItems)
+{
+ aValues.clear();
+
+ sal_Int32 aCount = rItems.getLength();
+ for (int i = 0; i < aCount; i++)
+ aValues.push_back(rItems[i]);
+
+ aSelectedItem = aEmptyString;
+}
+
+uno::Sequence<OUString> SwDropDownField::GetItemSequence() const
+{
+ uno::Sequence<OUString> aSeq( aValues.size() );
+ OUString* pSeq = aSeq.getArray();
+ int i = 0;
+ vector<String>::const_iterator aIt;
+
+ for (aIt = aValues.begin(); aIt != aValues.end(); ++aIt)
+ {
+ pSeq[i] = rtl::OUString(*aIt);
+
+ i++;
+ }
+
+ return aSeq;
+}
+
+const String & SwDropDownField::GetSelectedItem() const
+{
+ return aSelectedItem;
+}
+
+const String & SwDropDownField::GetName() const
+{
+ return aName;
+}
+
+const String & SwDropDownField::GetHelp() const
+{
+ return aHelp;
+}
+
+const String & SwDropDownField::GetToolTip() const
+{
+ return aToolTip;
+}
+
+sal_Bool SwDropDownField::SetSelectedItem(const String & rItem)
+{
+ vector<String>::const_iterator aIt =
+ std::find(aValues.begin(), aValues.end(), rItem);
+
+ if (aIt != aValues.end())
+ aSelectedItem = *aIt;
+ else
+ aSelectedItem = String();
+
+ return (aIt != aValues.end());
+}
+
+void SwDropDownField::SetName(const String & rName)
+{
+ aName = rName;
+}
+
+void SwDropDownField::SetHelp(const String & rHelp)
+{
+ aHelp = rHelp;
+}
+
+void SwDropDownField::SetToolTip(const String & rToolTip)
+{
+ aToolTip = rToolTip;
+}
+
+bool SwDropDownField::QueryValue(::uno::Any &rVal, sal_uInt16 nWhich) const
+{
+ nWhich &= ~CONVERT_TWIPS;
+ switch( nWhich )
+ {
+ case FIELD_PROP_PAR1:
+ rVal <<= rtl::OUString(GetSelectedItem());
+ break;
+ case FIELD_PROP_PAR2:
+ rVal <<= rtl::OUString(GetName());
+ break;
+ case FIELD_PROP_PAR3:
+ rVal <<= rtl::OUString(GetHelp());
+ break;
+ case FIELD_PROP_PAR4:
+ rVal <<= rtl::OUString(GetToolTip());
+ break;
+ case FIELD_PROP_STRINGS:
+ rVal <<= GetItemSequence();
+
+ break;
+
+ default:
+ OSL_FAIL("illegal property");
+ }
+ return true;
+}
+
+bool SwDropDownField::PutValue(const uno::Any &rVal,
+ sal_uInt16 nWhich)
+{
+ switch( nWhich )
+ {
+ case FIELD_PROP_PAR1:
+ {
+ String aTmpStr;
+ ::GetString( rVal, aTmpStr );
+
+ SetSelectedItem(aTmpStr);
+ }
+ break;
+
+ case FIELD_PROP_PAR2:
+ {
+ String aTmpStr;
+ ::GetString( rVal, aTmpStr );
+
+ SetName(aTmpStr);
+ }
+ break;
+
+ case FIELD_PROP_PAR3:
+ {
+ String aTmpStr;
+ ::GetString( rVal, aTmpStr );
+
+ SetHelp(aTmpStr);
+ }
+ break;
+
+ case FIELD_PROP_PAR4:
+ {
+ String aTmpStr;
+ ::GetString( rVal, aTmpStr );
+
+ SetToolTip(aTmpStr);
+ }
+ break;
+
+ case FIELD_PROP_STRINGS:
+ {
+ uno::Sequence<OUString> aSeq;
+ rVal >>= aSeq;
+ SetItems(aSeq);
+ }
+ break;
+
+ default:
+ OSL_FAIL("illegal property");
+ }
+ return true;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/fields/fldlst.cxx b/sw/source/core/fields/fldlst.cxx
new file mode 100644
index 000000000000..b3be2924760f
--- /dev/null
+++ b/sw/source/core/fields/fldlst.cxx
@@ -0,0 +1,232 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+#include "switerator.hxx"
+#include "editsh.hxx"
+#include "doc.hxx"
+#include <docary.hxx>
+#include <fmtfld.hxx>
+#include <txtfld.hxx>
+#include "edimp.hxx"
+#include "expfld.hxx"
+#include "pam.hxx"
+#include "docfld.hxx"
+#include "ndtxt.hxx"
+
+
+/*--------------------------------------------------------------------
+ Beschreibung: Sortieren der Input-Eintraege
+ --------------------------------------------------------------------*/
+
+SwInputFieldList::SwInputFieldList( SwEditShell* pShell, sal_Bool bBuildTmpLst )
+ : pSh(pShell)
+{
+ // Hier die Liste aller Eingabefelder sortiert erstellen
+ pSrtLst = new _SetGetExpFlds();
+
+ const SwFldTypes& rFldTypes = *pSh->GetDoc()->GetFldTypes();
+ const sal_uInt16 nSize = rFldTypes.Count();
+
+ // Alle Typen abklappern
+
+ for(sal_uInt16 i=0; i < nSize; ++i)
+ {
+ SwFieldType* pFldType = (SwFieldType*)rFldTypes[ i ];
+ sal_uInt16 nType = pFldType->Which();
+
+ if( RES_SETEXPFLD == nType || RES_INPUTFLD == nType || RES_DROPDOWN == nType )
+ {
+ SwIterator<SwFmtFld,SwFieldType> aIter( *pFldType );
+ for( SwFmtFld* pFld = aIter.First(); pFld; pFld = aIter.Next() )
+ {
+ const SwTxtFld* pTxtFld = pFld->GetTxtFld();
+
+ // nur InputFields und interaktive SetExpFlds bearbeiten
+ // and DropDown fields
+ if( !pTxtFld || ( RES_SETEXPFLD == nType &&
+ !((SwSetExpField*)pFld->GetFld())->GetInputFlag()))
+ continue;
+
+ const SwTxtNode& rTxtNode = pTxtFld->GetTxtNode();
+ if( rTxtNode.GetNodes().IsDocNodes() )
+ {
+ if( bBuildTmpLst )
+ {
+ VoidPtr pTmp = (VoidPtr)pTxtFld;
+ aTmpLst.Insert( pTmp, aTmpLst.Count() );
+ }
+ else
+ {
+ SwNodeIndex aIdx( rTxtNode );
+ _SetGetExpFld* pNew = new _SetGetExpFld(aIdx, pTxtFld );
+ pSrtLst->Insert( pNew );
+ }
+ }
+ }
+ }
+ }
+}
+
+SwInputFieldList::~SwInputFieldList()
+{
+ delete pSrtLst;
+}
+
+/*--------------------------------------------------------------------
+ Beschreibung: Felder aus der Liste in sortierter Reihenfolge
+ --------------------------------------------------------------------*/
+
+sal_uInt16 SwInputFieldList::Count() const
+{
+ return pSrtLst->Count();
+}
+
+
+SwField* SwInputFieldList::GetField(sal_uInt16 nId)
+{
+ const SwTxtFld* pTxtFld = (*pSrtLst)[ nId ]->GetFld();
+ OSL_ENSURE( pTxtFld, "kein TextFld" );
+ return (SwField*)pTxtFld->GetFld().GetFld();
+}
+
+/*--------------------------------------------------------------------
+ Beschreibung: Cursor sichern
+ --------------------------------------------------------------------*/
+
+void SwInputFieldList::PushCrsr()
+{
+ pSh->Push();
+ pSh->ClearMark();
+}
+
+void SwInputFieldList::PopCrsr()
+{
+ pSh->Pop(sal_False);
+}
+
+/*--------------------------------------------------------------------
+ Beschreibung: Position eines Feldes ansteuern
+ --------------------------------------------------------------------*/
+
+void SwInputFieldList::GotoFieldPos(sal_uInt16 nId)
+{
+ pSh->StartAllAction();
+ (*pSrtLst)[ nId ]->GetPosOfContent( *pSh->GetCrsr()->GetPoint() );
+ pSh->EndAllAction();
+}
+
+ // vergleiche TmpLst mit akt Feldern. Alle neue kommen in die SortLst
+ // damit sie geupdatet werden koennen. Returnt die Anzahl.
+ // (Fuer Textbausteine: nur seine Input-Felder aktualisieren)
+sal_uInt16 SwInputFieldList::BuildSortLst()
+{
+ const SwFldTypes& rFldTypes = *pSh->GetDoc()->GetFldTypes();
+ sal_uInt16 nSize = rFldTypes.Count();
+
+ // Alle Typen abklappern
+
+ for( sal_uInt16 i = 0; i < nSize; ++i )
+ {
+ SwFieldType* pFldType = (SwFieldType*)rFldTypes[ i ];
+ sal_uInt16 nType = pFldType->Which();
+
+ if( RES_SETEXPFLD == nType || RES_INPUTFLD == nType )
+ {
+ SwIterator<SwFmtFld,SwFieldType> aIter( *pFldType );
+ for( SwFmtFld* pFld = aIter.First(); pFld; pFld = aIter.Next() )
+ {
+ const SwTxtFld* pTxtFld = pFld->GetTxtFld();
+
+ // nur InputFields und interaktive SetExpFlds bearbeiten
+ if( !pTxtFld || ( RES_SETEXPFLD == nType &&
+ !((SwSetExpField*)pFld->GetFld())->GetInputFlag()))
+ continue;
+
+ const SwTxtNode& rTxtNode = pTxtFld->GetTxtNode();
+ if( rTxtNode.GetNodes().IsDocNodes() )
+ {
+ VoidPtr pTmp = (VoidPtr)pTxtFld;
+ // nicht in der TempListe vorhanden, also in die SortListe
+ // aufnehemen
+ sal_uInt16 nFndPos = aTmpLst.GetPos( pTmp );
+ if( USHRT_MAX == nFndPos )
+ {
+ SwNodeIndex aIdx( rTxtNode );
+ _SetGetExpFld* pNew = new _SetGetExpFld(aIdx, pTxtFld );
+ pSrtLst->Insert( pNew );
+ }
+ else
+ aTmpLst.Remove( nFndPos );
+ }
+ }
+ }
+ }
+
+ // die Pointer werden nicht mehr gebraucht
+ aTmpLst.Remove( 0, aTmpLst.Count() );
+ return pSrtLst->Count();
+}
+
+/*--------------------------------------------------------------------
+ Beschreibung: Alle Felder auáerhalb von Selektionen aus Liste entfernen
+ --------------------------------------------------------------------*/
+
+void SwInputFieldList::RemoveUnselectedFlds()
+{
+ _SetGetExpFlds* pNewLst = new _SetGetExpFlds();
+
+ FOREACHPAM_START(pSh)
+ {
+ for (sal_uInt16 i = 0; i < Count();)
+ {
+ _SetGetExpFld* pFld = (*pSrtLst)[i];
+ SwPosition aPos(*PCURCRSR->GetPoint());
+
+ pFld->GetPos( aPos );
+
+ if (aPos >= *PCURCRSR->Start() && aPos < *PCURCRSR->End())
+ {
+ // Feld innerhalb der Selektion
+ pNewLst->Insert( (*pSrtLst)[i] );
+ pSrtLst->Remove(i, 1);
+ }
+ else
+ i++;
+ }
+ }
+ FOREACHPAM_END()
+
+ delete pSrtLst;
+ pSrtLst = pNewLst;
+}
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/fields/macrofld.cxx b/sw/source/core/fields/macrofld.cxx
new file mode 100644
index 000000000000..023eb68f800c
--- /dev/null
+++ b/sw/source/core/fields/macrofld.cxx
@@ -0,0 +1,259 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+#include <hintids.hxx>
+#include <doc.hxx>
+#include <docufld.hxx>
+#include <unofldmid.h>
+#include <com/sun/star/lang/XMultiServiceFactory.hpp>
+#include <com/sun/star/uri/XUriReferenceFactory.hpp>
+#include <com/sun/star/uri/XVndSunStarScriptUrl.hpp>
+#include <comphelper/processfactory.hxx>
+
+
+using namespace ::com::sun::star;
+using ::rtl::OUString;
+
+/*--------------------------------------------------------------------
+ Beschreibung: MacroFeldtypen
+ --------------------------------------------------------------------*/
+
+SwMacroFieldType::SwMacroFieldType(SwDoc* pDocument)
+ : SwFieldType( RES_MACROFLD ),
+ pDoc(pDocument)
+{
+}
+
+SwFieldType* SwMacroFieldType::Copy() const
+{
+ SwMacroFieldType* pType = new SwMacroFieldType(pDoc);
+ return pType;
+}
+
+/*--------------------------------------------------------------------
+ Beschreibung: Das Macrofeld selbst
+ --------------------------------------------------------------------*/
+
+SwMacroField::SwMacroField(SwMacroFieldType* pInitType,
+ const String& rLibAndName, const String& rTxt) :
+ SwField(pInitType), aMacro(rLibAndName), aText(rTxt), bIsScriptURL(sal_False)
+{
+ bIsScriptURL = isScriptURL(aMacro);
+}
+
+String SwMacroField::Expand() const
+{ // Button malen anstatt von
+ return aText ;
+}
+
+SwField* SwMacroField::Copy() const
+{
+ return new SwMacroField((SwMacroFieldType*)GetTyp(), aMacro, aText);
+}
+
+String SwMacroField::GetFieldName() const
+{
+ String aStr(GetTyp()->GetName());
+ aStr += ' ';
+ aStr += aMacro;
+ return aStr;
+}
+
+String SwMacroField::GetLibName() const
+{
+ // if it is a Scripting Framework macro return an empty string
+ if (bIsScriptURL)
+ {
+ return String();
+ }
+
+ if (aMacro.Len())
+ {
+ sal_uInt16 nPos = aMacro.Len();
+
+ for (sal_uInt16 i = 0; i < 3 && nPos > 0; i++)
+ while (aMacro.GetChar(--nPos) != '.' && nPos > 0) ;
+
+ return aMacro.Copy(0, nPos );
+ }
+
+ DBG_ASSERT(0, "Kein Macroname vorhanden");
+ return aEmptyStr;
+}
+
+String SwMacroField::GetMacroName() const
+{
+ if (aMacro.Len())
+ {
+ if (bIsScriptURL)
+ {
+ return aMacro.Copy( 0 );
+ }
+ else
+ {
+ sal_uInt16 nPos = aMacro.Len();
+
+ for (sal_uInt16 i = 0; i < 3 && nPos > 0; i++)
+ while (aMacro.GetChar(--nPos) != '.' && nPos > 0) ;
+
+ return aMacro.Copy( ++nPos );
+ }
+ }
+
+ DBG_ASSERT(0, "Kein Macroname vorhanden");
+ return aEmptyStr;
+}
+
+SvxMacro SwMacroField::GetSvxMacro() const
+{
+ if (bIsScriptURL)
+ {
+ return SvxMacro(aMacro, String(), EXTENDED_STYPE);
+ }
+ else
+ {
+ return SvxMacro(GetMacroName(), GetLibName(), STARBASIC);
+ }
+}
+
+/*--------------------------------------------------------------------
+ Beschreibung: LibName und MacroName
+ --------------------------------------------------------------------*/
+
+void SwMacroField::SetPar1(const String& rStr)
+{
+ aMacro = rStr;
+ bIsScriptURL = isScriptURL(aMacro);
+}
+
+const String& SwMacroField::GetPar1() const
+{
+ return aMacro;
+}
+
+/*--------------------------------------------------------------------
+ Beschreibung: Macrotext
+ --------------------------------------------------------------------*/
+
+void SwMacroField::SetPar2(const String& rStr)
+{
+ aText = rStr;
+}
+
+String SwMacroField::GetPar2() const
+{
+ return aText;
+}
+
+bool SwMacroField::QueryValue( uno::Any& rAny, sal_uInt16 nWhichId ) const
+{
+ switch( nWhichId )
+ {
+ case FIELD_PROP_PAR1:
+ rAny <<= OUString(GetMacroName());
+ break;
+ case FIELD_PROP_PAR2:
+ rAny <<= OUString(aText);
+ break;
+ case FIELD_PROP_PAR3:
+ rAny <<= OUString(GetLibName());
+ break;
+ case FIELD_PROP_PAR4:
+ rAny <<= bIsScriptURL ? OUString(GetMacroName()): OUString();
+ break;
+ default:
+ OSL_FAIL("illegal property");
+ }
+ return true;
+}
+
+bool SwMacroField::PutValue( const uno::Any& rAny, sal_uInt16 nWhichId )
+{
+ String sTmp;
+ switch( nWhichId )
+ {
+ case FIELD_PROP_PAR1:
+ CreateMacroString( aMacro, ::GetString(rAny, sTmp), GetLibName());
+ break;
+ case FIELD_PROP_PAR2:
+ ::GetString( rAny, aText );
+ break;
+ case FIELD_PROP_PAR3:
+ CreateMacroString(aMacro, GetMacroName(), ::GetString(rAny, sTmp) );
+ break;
+ case FIELD_PROP_PAR4:
+ ::GetString(rAny, aMacro);
+ bIsScriptURL = isScriptURL(aMacro);
+ break;
+ default:
+ OSL_FAIL("illegal property");
+ }
+
+ return true;
+}
+
+// create an internally used macro name from the library and macro name parts
+void SwMacroField::CreateMacroString(
+ String& rMacro,
+ const String& rMacroName,
+ const String& rLibraryName )
+{
+ // concatenate library and name; use dot only if both strings have content
+ rMacro = rLibraryName;
+ if ( rLibraryName.Len() > 0 && rMacroName.Len() > 0 )
+ rMacro += '.';
+ rMacro += rMacroName;
+}
+
+sal_Bool SwMacroField::isScriptURL( const String& str )
+{
+ uno::Reference< lang::XMultiServiceFactory > xSMgr =
+ ::comphelper::getProcessServiceFactory();
+
+ uno::Reference< uri::XUriReferenceFactory >
+ xFactory( xSMgr->createInstance(
+ OUString(RTL_CONSTASCII_USTRINGPARAM(
+ "com.sun.star.uri.UriReferenceFactory")) ), uno::UNO_QUERY );
+
+ if ( xFactory.is() )
+ {
+ uno::Reference< uri::XVndSunStarScriptUrl >
+ xUrl( xFactory->parse( str ), uno::UNO_QUERY );
+
+ if ( xUrl.is() )
+ {
+ return sal_True;
+ }
+ }
+ return sal_False;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/fields/postithelper.cxx b/sw/source/core/fields/postithelper.cxx
new file mode 100644
index 000000000000..81cc0c294713
--- /dev/null
+++ b/sw/source/core/fields/postithelper.cxx
@@ -0,0 +1,208 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+#include <tools/gen.hxx>
+
+#include <postithelper.hxx>
+#include <PostItMgr.hxx>
+#include <AnnotationWin.hxx>
+
+#include <fmtfld.hxx>
+#include <txtfld.hxx>
+#include <docufld.hxx>
+#include <ndtxt.hxx>
+#include <cntfrm.hxx>
+#include <pagefrm.hxx>
+#include <rootfrm.hxx>
+#include <txtfrm.hxx>
+#include <tabfrm.hxx>
+#include <IDocumentRedlineAccess.hxx>
+#include <redline.hxx>
+#include <scriptinfo.hxx>
+#include <editeng/charhiddenitem.hxx>
+#include <switerator.hxx>
+
+namespace {
+
+struct LayoutInfoOrder
+{
+ bool operator()( const SwLayoutInfo& rLayoutInfo,
+ const SwLayoutInfo& rNewLayoutInfo )
+ {
+ if ( rLayoutInfo.mnPageNumber != rNewLayoutInfo.mnPageNumber )
+ {
+ // corresponding <SwFrm> instances are on different pages
+ return rLayoutInfo.mnPageNumber < rNewLayoutInfo.mnPageNumber;
+ }
+ else
+ {
+ // corresponding <SwFrm> instances are in different repeating table header rows
+ OSL_ENSURE( rLayoutInfo.mpAnchorFrm->FindTabFrm(),
+ "<LayoutInfoOrder::operator()> - table frame not found" );
+ OSL_ENSURE( rNewLayoutInfo.mpAnchorFrm->FindTabFrm(),
+ "<LayoutInfoOrder::operator()> - table frame not found" );
+ const SwTabFrm* pLayoutInfoTabFrm( rLayoutInfo.mpAnchorFrm->FindTabFrm() );
+ const SwTabFrm* pNewLayoutInfoTabFrm( rNewLayoutInfo.mpAnchorFrm->FindTabFrm() );
+ const SwTabFrm* pTmpTabFrm( pNewLayoutInfoTabFrm );
+ while ( pTmpTabFrm && pTmpTabFrm->GetFollow() )
+ {
+ pTmpTabFrm = static_cast<const SwTabFrm*>(pTmpTabFrm->GetFollow()->GetFrm());
+ if ( pTmpTabFrm == pLayoutInfoTabFrm )
+ {
+ return false;
+ }
+ }
+ return true;
+ }
+ }
+};
+
+} // eof anonymous namespace
+
+SwPostItHelper::SwLayoutStatus SwPostItHelper::getLayoutInfos( std::vector< SwLayoutInfo >& rInfo, SwPosition& rPos )
+{
+ SwLayoutStatus aRet = INVISIBLE;
+ const SwTxtNode* pTxtNode = rPos.nNode.GetNode().GetTxtNode();
+ SwCntntNode* pNode = rPos.nNode.GetNode().GetCntntNode(); // getfirstcontentnode // getnext...
+ if( !pNode )
+ return aRet;
+ SwIterator<SwTxtFrm,SwCntntNode> aIter( *pNode );
+ for( SwTxtFrm* pTxtFrm = aIter.First(); pTxtFrm; pTxtFrm = aIter.Next() )
+ {
+ if( !pTxtFrm->IsFollow() )
+ {
+ pTxtFrm = ((SwTxtFrm*)pTxtFrm)->GetFrmAtPos( rPos );
+ SwPageFrm *pPage = pTxtFrm ? pTxtFrm->FindPageFrm() : 0;
+ // #i103490#
+ if ( pPage && !pPage->IsInvalid() && !pPage->IsInvalidFly() )
+ {
+ SwLayoutInfo aInfo;
+ pTxtFrm->GetCharRect( aInfo.mPosition, rPos, 0 );
+ aInfo.mpAnchorFrm = pTxtFrm;
+ aInfo.mPageFrame = pPage->Frm();
+ aInfo.mPagePrtArea = pPage->Prt();
+ aInfo.mPagePrtArea.Pos() += aInfo.mPageFrame.Pos();
+ aInfo.mnPageNumber = pPage->GetPhyPageNum();
+ aInfo.meSidebarPosition = pPage->SidebarPosition();
+ aInfo.mRedlineAuthor = 0;
+
+ if( aRet == INVISIBLE )
+ {
+ aRet = VISIBLE;
+ const IDocumentRedlineAccess* pIDRA = pNode->getIDocumentRedlineAccess();
+ if( IDocumentRedlineAccess::IsShowChanges( pIDRA->GetRedlineMode() ) )
+ {
+ const SwRedline* pRedline = pIDRA->GetRedline( rPos, 0 );
+ if( pRedline )
+ {
+ if( nsRedlineType_t::REDLINE_INSERT == pRedline->GetType() )
+ aRet = INSERTED;
+ else if( nsRedlineType_t::REDLINE_DELETE == pRedline->GetType() )
+ aRet = DELETED;
+ aInfo.mRedlineAuthor = pRedline->GetAuthor();
+ }
+ }
+ }
+
+ {
+ std::vector< SwLayoutInfo >::iterator aInsPosIter =
+ std::lower_bound( rInfo.begin(), rInfo.end(),
+ aInfo, LayoutInfoOrder() );
+
+ rInfo.insert( aInsPosIter, aInfo );
+ }
+ }
+ }
+ }
+ return ((aRet==VISIBLE) && SwScriptInfo::IsInHiddenRange( *pTxtNode , rPos.nContent.GetIndex()) ) ? HIDDEN : aRet;
+}
+
+long SwPostItHelper::getLayoutHeight( const SwRootFrm* pRoot )
+{
+ long nRet = pRoot ? pRoot->Frm().Height() : 0;
+ return nRet;
+}
+
+void SwPostItHelper::setSidebarChanged( SwRootFrm* pRoot, bool bBrowseMode )
+{
+ if( pRoot )
+ {
+ pRoot->SetSidebarChanged();
+ if( bBrowseMode )
+ pRoot->InvalidateBrowseWidth();
+ }
+}
+
+unsigned long SwPostItHelper::getPageInfo( SwRect& rPageFrm, const SwRootFrm* pRoot, const Point& rPoint )
+{
+ unsigned long nRet = 0;
+ const SwFrm* pPage = pRoot->GetPageAtPos( rPoint, 0, true );
+ if( pPage )
+ {
+ nRet = pPage->GetPhyPageNum();
+ rPageFrm = pPage->Frm();
+ }
+ return nRet;
+}
+
+SwPosition SwAnnotationItem::GetAnchorPosition() const
+{
+ SwTxtFld* pFld = pFmtFld->GetTxtFld();
+ //if( pFld )
+ //{
+ SwTxtNode* pTNd = pFld->GetpTxtNode();
+ // if( pTNd )
+ // {
+ SwPosition aPos( *pTNd );
+ aPos.nContent.Assign( pTNd, *pFld->GetStart() );
+ return aPos;
+ // }
+ //}
+}
+
+bool SwAnnotationItem::UseElement()
+{
+ return pFmtFld->IsFldInDoc();
+}
+
+sw::sidebarwindows::SwSidebarWin* SwAnnotationItem::GetSidebarWindow(
+ SwEditWin& rEditWin,
+ WinBits nBits,
+ SwPostItMgr& aMgr,
+ SwPostItBits aBits)
+{
+ return new sw::annotation::SwAnnotationWin( rEditWin, nBits,
+ aMgr, aBits,
+ *this,
+ pFmtFld );
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/fields/reffld.cxx b/sw/source/core/fields/reffld.cxx
new file mode 100644
index 000000000000..2035ac97fc38
--- /dev/null
+++ b/sw/source/core/fields/reffld.cxx
@@ -0,0 +1,1074 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+
+#define _SVSTDARR_USHORTSSORT
+#define _SVSTDARR_USHORTS
+#include <svl/svstdarr.hxx>
+#include <com/sun/star/text/ReferenceFieldPart.hpp>
+#include <com/sun/star/text/ReferenceFieldSource.hpp>
+#include <unotools/localedatawrapper.hxx>
+#include <com/sun/star/lang/XMultiServiceFactory.hpp>
+#include <comphelper/processfactory.hxx>
+#include <editeng/unolingu.hxx>
+#include <doc.hxx>
+#include <pam.hxx>
+#include <cntfrm.hxx>
+#include <pagefrm.hxx>
+#include <docary.hxx>
+#include <fmtfld.hxx>
+#include <txtfld.hxx>
+#include <txtftn.hxx>
+#include <fmtrfmrk.hxx>
+#include <txtrfmrk.hxx>
+#include <fmtftn.hxx>
+#include <ndtxt.hxx>
+#include <chpfld.hxx>
+#include <reffld.hxx>
+#include <expfld.hxx>
+#include <txtfrm.hxx>
+#include <flyfrm.hxx>
+#include <pagedesc.hxx>
+#include <IMark.hxx>
+#include <crossrefbookmark.hxx>
+#include <ftnidx.hxx>
+#include <viewsh.hxx>
+#include <unofldmid.h>
+#include <SwStyleNameMapper.hxx>
+#include <shellres.hxx>
+#include <poolfmt.hxx>
+#include <poolfmt.hrc>
+#include <comcore.hrc>
+#include <numrule.hxx>
+#include <SwNodeNum.hxx>
+#include <switerator.hxx>
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::text;
+using namespace ::com::sun::star::lang;
+using ::rtl::OUString;
+
+extern void InsertSort( SvUShorts& rArr, sal_uInt16 nIdx, sal_uInt16* pInsPos = 0 );
+
+void lcl_GetLayTree( const SwFrm* pFrm, SvPtrarr& rArr )
+{
+ while( pFrm )
+ {
+ if( pFrm->IsBodyFrm() ) // soll uns nicht weiter interessieren
+ pFrm = pFrm->GetUpper();
+ else
+ {
+ void* p = (void*)pFrm;
+ rArr.Insert( p, rArr.Count() );
+
+ // bei der Seite ist schluss
+ if( pFrm->IsPageFrm() )
+ break;
+
+ if( pFrm->IsFlyFrm() )
+ pFrm = ((SwFlyFrm*)pFrm)->GetAnchorFrm();
+ else
+ pFrm = pFrm->GetUpper();
+ }
+ }
+}
+
+
+sal_Bool IsFrameBehind( const SwTxtNode& rMyNd, sal_uInt16 nMySttPos,
+ const SwTxtNode& rBehindNd, sal_uInt16 nSttPos )
+{
+ const SwTxtFrm *pMyFrm = (SwTxtFrm*)rMyNd.getLayoutFrm( rMyNd.GetDoc()->GetCurrentLayout(), 0,0,sal_False),
+ *pFrm = (SwTxtFrm*)rBehindNd.getLayoutFrm( rBehindNd.GetDoc()->GetCurrentLayout(), 0,0,sal_False);
+
+ while( pFrm && !pFrm->IsInside( nSttPos ) )
+ pFrm = (SwTxtFrm*)pFrm->GetFollow();
+ while( pMyFrm && !pMyFrm->IsInside( nMySttPos ) )
+ pMyFrm = (SwTxtFrm*)pMyFrm->GetFollow();
+
+ if( !pFrm || !pMyFrm || pFrm == pMyFrm )
+ return sal_False;
+
+ SvPtrarr aRefArr( 10, 10 ), aArr( 10, 10 );
+ ::lcl_GetLayTree( pFrm, aRefArr );
+ ::lcl_GetLayTree( pMyFrm, aArr );
+
+ sal_uInt16 nRefCnt = aRefArr.Count() - 1, nCnt = aArr.Count() - 1;
+ sal_Bool bVert = sal_False;
+ sal_Bool bR2L = sal_False;
+
+ // solange bis ein Frame ungleich ist ?
+ while( nRefCnt && nCnt && aRefArr[ nRefCnt ] == aArr[ nCnt ] )
+ {
+ const SwFrm* pTmpFrm = (const SwFrm*)aArr[ nCnt ];
+ bVert = pTmpFrm->IsVertical();
+ bR2L = pTmpFrm->IsRightToLeft();
+ --nCnt, --nRefCnt;
+ }
+
+ // sollte einer der Counter ueberlaeufen?
+ if( aRefArr[ nRefCnt ] == aArr[ nCnt ] )
+ {
+ if( nCnt )
+ --nCnt;
+ else
+ --nRefCnt;
+ }
+
+ const SwFrm* pRefFrm = (const SwFrm*)aRefArr[ nRefCnt ];
+ const SwFrm* pFldFrm = (const SwFrm*)aArr[ nCnt ];
+
+ // unterschiedliche Frames, dann ueberpruefe deren Y-/X-Position
+ sal_Bool bRefIsLower = sal_False;
+ if( ( FRM_COLUMN | FRM_CELL ) & pFldFrm->GetType() ||
+ ( FRM_COLUMN | FRM_CELL ) & pRefFrm->GetType() )
+ {
+ if( pFldFrm->GetType() == pRefFrm->GetType() )
+ {
+ // hier ist die X-Pos wichtiger!
+ if( bVert )
+ {
+ if( bR2L )
+ bRefIsLower = pRefFrm->Frm().Top() < pFldFrm->Frm().Top() ||
+ ( pRefFrm->Frm().Top() == pFldFrm->Frm().Top() &&
+ pRefFrm->Frm().Left() < pFldFrm->Frm().Left() );
+ else
+ bRefIsLower = pRefFrm->Frm().Top() < pFldFrm->Frm().Top() ||
+ ( pRefFrm->Frm().Top() == pFldFrm->Frm().Top() &&
+ pRefFrm->Frm().Left() > pFldFrm->Frm().Left() );
+ }
+ else if( bR2L )
+ bRefIsLower = pRefFrm->Frm().Left() > pFldFrm->Frm().Left() ||
+ ( pRefFrm->Frm().Left() == pFldFrm->Frm().Left() &&
+ pRefFrm->Frm().Top() < pFldFrm->Frm().Top() );
+ else
+ bRefIsLower = pRefFrm->Frm().Left() < pFldFrm->Frm().Left() ||
+ ( pRefFrm->Frm().Left() == pFldFrm->Frm().Left() &&
+ pRefFrm->Frm().Top() < pFldFrm->Frm().Top() );
+ pRefFrm = 0;
+ }
+ else if( ( FRM_COLUMN | FRM_CELL ) & pFldFrm->GetType() )
+ pFldFrm = (const SwFrm*)aArr[ nCnt - 1 ];
+ else
+ pRefFrm = (const SwFrm*)aRefArr[ nRefCnt - 1 ];
+ }
+
+ if( pRefFrm ) // als Flag missbrauchen
+ {
+ if( bVert )
+ {
+ if( bR2L )
+ bRefIsLower = pRefFrm->Frm().Left() < pFldFrm->Frm().Left() ||
+ ( pRefFrm->Frm().Left() == pFldFrm->Frm().Left() &&
+ pRefFrm->Frm().Top() < pFldFrm->Frm().Top() );
+ else
+ bRefIsLower = pRefFrm->Frm().Left() > pFldFrm->Frm().Left() ||
+ ( pRefFrm->Frm().Left() == pFldFrm->Frm().Left() &&
+ pRefFrm->Frm().Top() < pFldFrm->Frm().Top() );
+ }
+ else if( bR2L )
+ bRefIsLower = pRefFrm->Frm().Top() < pFldFrm->Frm().Top() ||
+ ( pRefFrm->Frm().Top() == pFldFrm->Frm().Top() &&
+ pRefFrm->Frm().Left() > pFldFrm->Frm().Left() );
+ else
+ bRefIsLower = pRefFrm->Frm().Top() < pFldFrm->Frm().Top() ||
+ ( pRefFrm->Frm().Top() == pFldFrm->Frm().Top() &&
+ pRefFrm->Frm().Left() < pFldFrm->Frm().Left() );
+ }
+ return bRefIsLower;
+}
+
+/*--------------------------------------------------------------------
+ Beschreibung: Referenzen holen
+ --------------------------------------------------------------------*/
+
+
+SwGetRefField::SwGetRefField( SwGetRefFieldType* pFldType,
+ const String& rSetRef, sal_uInt16 nSubTyp,
+ sal_uInt16 nSeqenceNo, sal_uLong nFmt )
+ : SwField( pFldType, nFmt ),
+ sSetRefName( rSetRef ),
+ nSubType( nSubTyp ),
+ nSeqNo( nSeqenceNo )
+{
+}
+
+SwGetRefField::~SwGetRefField()
+{
+}
+
+String SwGetRefField::GetDescription() const
+{
+ return SW_RES(STR_REFERENCE);
+}
+
+sal_uInt16 SwGetRefField::GetSubType() const
+{
+ return nSubType;
+}
+
+void SwGetRefField::SetSubType( sal_uInt16 n )
+{
+ nSubType = n;
+}
+
+// --> OD 2007-11-09 #i81002#
+bool SwGetRefField::IsRefToHeadingCrossRefBookmark() const
+{
+ return GetSubType() == REF_BOOKMARK &&
+ ::sw::mark::CrossRefHeadingBookmark::IsLegalName(sSetRefName);
+}
+
+bool SwGetRefField::IsRefToNumItemCrossRefBookmark() const
+{
+ return GetSubType() == REF_BOOKMARK &&
+ ::sw::mark::CrossRefNumItemBookmark::IsLegalName(sSetRefName);
+}
+
+const SwTxtNode* SwGetRefField::GetReferencedTxtNode() const
+{
+ SwDoc* pDoc = dynamic_cast<SwGetRefFieldType*>(GetTyp())->GetDoc();
+ sal_uInt16 nDummy = USHRT_MAX;
+ return SwGetRefFieldType::FindAnchor( pDoc, sSetRefName, nSubType, nSeqNo, &nDummy );
+}
+// <--
+// --> OD 2008-01-09 #i85090#
+String SwGetRefField::GetExpandedTxtOfReferencedTxtNode() const
+{
+ const SwTxtNode* pReferencedTxtNode( GetReferencedTxtNode() );
+ return pReferencedTxtNode
+ ? pReferencedTxtNode->GetExpandTxt( 0, STRING_LEN, true, true )
+ : aEmptyStr;
+}
+
+String SwGetRefField::Expand() const
+{
+ return sTxt;
+}
+
+
+String SwGetRefField::GetFieldName() const
+{
+ String aStr(GetTyp()->GetName());
+ aStr += ' ';
+ aStr += sSetRefName;
+ return aStr;
+}
+
+// --> OD 2007-09-07 #i81002# - parameter <pFldTxtAttr> added
+void SwGetRefField::UpdateField( const SwTxtFld* pFldTxtAttr )
+{
+ sTxt.Erase();
+
+ SwDoc* pDoc = ((SwGetRefFieldType*)GetTyp())->GetDoc();
+ sal_uInt16 nStt = USHRT_MAX;
+ sal_uInt16 nEnd = USHRT_MAX;
+ SwTxtNode* pTxtNd = SwGetRefFieldType::FindAnchor( pDoc, sSetRefName,
+ nSubType, nSeqNo, &nStt, &nEnd );
+ if ( !pTxtNd )
+ {
+ sTxt = ViewShell::GetShellRes()->aGetRefFld_RefItemNotFound;
+ return ;
+ }
+
+ switch( GetFormat() )
+ {
+ case REF_CONTENT:
+ case REF_ONLYNUMBER:
+ case REF_ONLYCAPTION:
+ case REF_ONLYSEQNO:
+ {
+ switch( nSubType )
+ {
+ case REF_SEQUENCEFLD:
+ nEnd = pTxtNd->GetTxt().Len();
+ switch( GetFormat() )
+ {
+ case REF_ONLYNUMBER:
+ if( nStt + 1 < nEnd )
+ nEnd = nStt + 1;
+ nStt = 0;
+ break;
+
+ case REF_ONLYCAPTION:
+ {
+ const SwTxtAttr* const pTxtAttr =
+ pTxtNd->GetTxtAttrForCharAt(nStt, RES_TXTATR_FIELD);
+ if( pTxtAttr )
+ nStt = SwGetExpField::GetReferenceTextPos(
+ pTxtAttr->GetFld(), *pDoc );
+ else if( nStt + 1 < nEnd )
+ ++nStt;
+ }
+ break;
+
+ case REF_ONLYSEQNO:
+ if( nStt + 1 < nEnd )
+ nEnd = nStt + 1;
+ break;
+
+ default:
+ nStt = 0;
+ break;
+ }
+ break;
+
+ case REF_BOOKMARK:
+ if( USHRT_MAX == nEnd )
+ {
+ // Text steht ueber verschiedene Nodes verteilt.
+ // Gesamten Text oder nur bis zum Ende vom Node?
+ nEnd = pTxtNd->GetTxt().Len();
+ }
+ break;
+
+ case REF_OUTLINE:
+ break;
+
+ case REF_FOOTNOTE:
+ case REF_ENDNOTE:
+ {
+ // die Nummer oder den NumString besorgen
+ sal_uInt16 n, nFtnCnt = pDoc->GetFtnIdxs().Count();
+ SwTxtFtn* pFtnIdx;
+ for( n = 0; n < nFtnCnt; ++n )
+ if( nSeqNo == (pFtnIdx = pDoc->GetFtnIdxs()[ n ])->GetSeqRefNo() )
+ {
+ sTxt = pFtnIdx->GetFtn().GetViewNumStr( *pDoc );
+ break;
+ }
+ nStt = nEnd; // kein Bereich, der String ist fertig
+ }
+ break;
+ }
+
+ if( nStt != nEnd ) // ein Bereich?
+ {
+ sTxt = pTxtNd->GetExpandTxt( nStt, nEnd - nStt );
+
+ // alle Sonderzeichen entfernen (durch Blanks ersetzen):
+ if( sTxt.Len() )
+ {
+ sTxt.EraseAllChars( 0xad );
+ for( sal_Unicode* p = sTxt.GetBufferAccess(); *p; ++p )
+ {
+ if( *p < 0x20 )
+ *p = 0x20;
+ else if(*p == 0x2011)
+ *p = '-';
+ }
+ }
+ }
+ }
+ break;
+
+ case REF_PAGE:
+ case REF_PAGE_PGDESC:
+ {
+ const SwTxtFrm* pFrm = (SwTxtFrm*)pTxtNd->getLayoutFrm( pDoc->GetCurrentLayout(), 0,0,sal_False),
+ *pSave = pFrm;
+ while( pFrm && !pFrm->IsInside( nStt ) )
+ pFrm = (SwTxtFrm*)pFrm->GetFollow();
+
+ if( pFrm || 0 != ( pFrm = pSave ))
+ {
+ sal_uInt16 nPageNo = pFrm->GetVirtPageNum();
+ const SwPageFrm *pPage;
+ if( REF_PAGE_PGDESC == GetFormat() &&
+ 0 != ( pPage = pFrm->FindPageFrm() ) &&
+ pPage->GetPageDesc() )
+ sTxt = pPage->GetPageDesc()->GetNumType().GetNumStr( nPageNo );
+ else
+ sTxt = String::CreateFromInt32(nPageNo);
+ }
+ }
+ break;
+
+ case REF_CHAPTER:
+ {
+ // ein bischen trickreich: suche irgend einen Frame
+ const SwFrm* pFrm = pTxtNd->getLayoutFrm( pDoc->GetCurrentLayout() );
+ if( pFrm )
+ {
+ SwChapterFieldType aFldTyp;
+ SwChapterField aFld( &aFldTyp, 0 );
+ aFld.SetLevel( MAXLEVEL - 1 );
+ aFld.ChangeExpansion( pFrm, pTxtNd, sal_True );
+ sTxt = aFld.GetNumber();
+ }
+ }
+ break;
+
+ case REF_UPDOWN:
+ {
+ // --> OD 2007-09-07 #i81002#
+ // simplified: use parameter <pFldTxtAttr>
+ if( !pFldTxtAttr || !pFldTxtAttr->GetpTxtNode() )
+ break;
+
+ LocaleDataWrapper aLocaleData(
+ ::comphelper::getProcessServiceFactory(),
+ SvxCreateLocale( GetLanguage() ) );
+
+ // erstmal ein "Kurz" - Test - falls beide im selben
+ // Node stehen!
+ if( pFldTxtAttr->GetpTxtNode() == pTxtNd )
+ {
+ sTxt = nStt < *pFldTxtAttr->GetStart()
+ ? aLocaleData.getAboveWord()
+ : aLocaleData.getBelowWord();
+ break;
+ }
+
+ sTxt = ::IsFrameBehind( *pFldTxtAttr->GetpTxtNode(), *pFldTxtAttr->GetStart(),
+ *pTxtNd, nStt )
+ ? aLocaleData.getAboveWord()
+ : aLocaleData.getBelowWord();
+ }
+ break;
+ // --> OD 2007-08-24 #i81002#
+ case REF_NUMBER:
+ case REF_NUMBER_NO_CONTEXT:
+ case REF_NUMBER_FULL_CONTEXT:
+ {
+ if ( pFldTxtAttr && pFldTxtAttr->GetpTxtNode() )
+ {
+ sTxt = MakeRefNumStr( pFldTxtAttr->GetTxtNode(), *pTxtNd, GetFormat() );
+ }
+ }
+ break;
+ // <--
+ default:
+ OSL_FAIL("<SwGetRefField::UpdateField(..)> - unknown format type");
+ }
+}
+
+// --> OD 2007-09-06 #i81002#
+String SwGetRefField::MakeRefNumStr( const SwTxtNode& rTxtNodeOfField,
+ const SwTxtNode& rTxtNodeOfReferencedItem,
+ const sal_uInt32 nRefNumFormat ) const
+{
+ if ( rTxtNodeOfReferencedItem.HasNumber() &&
+ rTxtNodeOfReferencedItem.IsCountedInList() )
+ {
+ OSL_ENSURE( rTxtNodeOfReferencedItem.GetNum(),
+ "<SwGetRefField::MakeRefNumStr(..)> - referenced paragraph has number, but no <SwNodeNum> instance --> please inform OD!" );
+
+ // Determine, up to which level the superior list labels have to be
+ // included - default is to include all superior list labels.
+ sal_uInt8 nRestrictInclToThisLevel( 0 );
+ // Determine for format REF_NUMBER the level, up to which the superior
+ // list labels have to be restricted, if the text node of the reference
+ // field and the text node of the referenced item are in the same
+ // document context.
+ if ( nRefNumFormat == REF_NUMBER &&
+ rTxtNodeOfField.FindFlyStartNode()
+ == rTxtNodeOfReferencedItem.FindFlyStartNode() &&
+ rTxtNodeOfField.FindFootnoteStartNode()
+ == rTxtNodeOfReferencedItem.FindFootnoteStartNode() &&
+ rTxtNodeOfField.FindHeaderStartNode()
+ == rTxtNodeOfReferencedItem.FindHeaderStartNode() &&
+ rTxtNodeOfField.FindFooterStartNode()
+ == rTxtNodeOfReferencedItem.FindFooterStartNode() )
+ {
+ const SwNodeNum* pNodeNumForTxtNodeOfField( 0 );
+ if ( rTxtNodeOfField.HasNumber() &&
+ rTxtNodeOfField.GetNumRule() == rTxtNodeOfReferencedItem.GetNumRule() )
+ {
+ pNodeNumForTxtNodeOfField = rTxtNodeOfField.GetNum();
+ }
+ else
+ {
+ pNodeNumForTxtNodeOfField =
+ rTxtNodeOfReferencedItem.GetNum()->GetPrecedingNodeNumOf( rTxtNodeOfField );
+ }
+ if ( pNodeNumForTxtNodeOfField )
+ {
+ const SwNumberTree::tNumberVector rFieldNumVec = pNodeNumForTxtNodeOfField->GetNumberVector();
+ const SwNumberTree::tNumberVector rRefItemNumVec = rTxtNodeOfReferencedItem.GetNum()->GetNumberVector();
+ sal_uInt8 nLevel( 0 );
+ while ( nLevel < rFieldNumVec.size() && nLevel < rRefItemNumVec.size() )
+ {
+ if ( rRefItemNumVec[nLevel] == rFieldNumVec[nLevel] )
+ {
+ nRestrictInclToThisLevel = nLevel + 1;
+ }
+ else
+ {
+ break;
+ }
+ ++nLevel;
+ }
+ }
+ }
+
+ // Determine, if superior list labels have to be included
+ const bool bInclSuperiorNumLabels(
+ ( nRestrictInclToThisLevel < rTxtNodeOfReferencedItem.GetActualListLevel() &&
+ ( nRefNumFormat == REF_NUMBER || nRefNumFormat == REF_NUMBER_FULL_CONTEXT ) ) );
+
+ OSL_ENSURE( rTxtNodeOfReferencedItem.GetNumRule(),
+ "<SwGetRefField::MakeRefNumStr(..)> - referenced numbered paragraph has no numbering rule set --> please inform OD!" );
+ return rTxtNodeOfReferencedItem.GetNumRule()->MakeRefNumString(
+ *(rTxtNodeOfReferencedItem.GetNum()),
+ bInclSuperiorNumLabels,
+ nRestrictInclToThisLevel );
+ }
+
+ return String();
+}
+// <--
+
+SwField* SwGetRefField::Copy() const
+{
+ SwGetRefField* pFld = new SwGetRefField( (SwGetRefFieldType*)GetTyp(),
+ sSetRefName, nSubType,
+ nSeqNo, GetFormat() );
+ pFld->sTxt = sTxt;
+ return pFld;
+}
+
+/*--------------------------------------------------------------------
+ Beschreibung: ReferenzName holen
+ --------------------------------------------------------------------*/
+
+
+const String& SwGetRefField::GetPar1() const
+{
+ return sSetRefName;
+}
+
+
+void SwGetRefField::SetPar1( const String& rName )
+{
+ sSetRefName = rName;
+}
+
+
+String SwGetRefField::GetPar2() const
+{
+ return Expand();
+}
+
+bool SwGetRefField::QueryValue( uno::Any& rAny, sal_uInt16 nWhichId ) const
+{
+ switch( nWhichId )
+ {
+ case FIELD_PROP_USHORT1:
+ {
+ sal_Int16 nPart = 0;
+ switch(GetFormat())
+ {
+ case REF_PAGE : nPart = ReferenceFieldPart::PAGE ; break;
+ case REF_CHAPTER : nPart = ReferenceFieldPart::CHAPTER ; break;
+ case REF_CONTENT : nPart = ReferenceFieldPart::TEXT ; break;
+ case REF_UPDOWN : nPart = ReferenceFieldPart::UP_DOWN ; break;
+ case REF_PAGE_PGDESC: nPart = ReferenceFieldPart::PAGE_DESC ; break;
+ case REF_ONLYNUMBER : nPart = ReferenceFieldPart::CATEGORY_AND_NUMBER ; break;
+ case REF_ONLYCAPTION: nPart = ReferenceFieldPart::ONLY_CAPTION ; break;
+ case REF_ONLYSEQNO : nPart = ReferenceFieldPart::ONLY_SEQUENCE_NUMBER; break;
+ // --> OD 2007-09-06 #i81002#
+ case REF_NUMBER: nPart = ReferenceFieldPart::NUMBER; break;
+ case REF_NUMBER_NO_CONTEXT: nPart = ReferenceFieldPart::NUMBER_NO_CONTEXT; break;
+ case REF_NUMBER_FULL_CONTEXT: nPart = ReferenceFieldPart::NUMBER_FULL_CONTEXT; break;
+ // <--
+ }
+ rAny <<= nPart;
+ }
+ break;
+ case FIELD_PROP_USHORT2:
+ {
+ sal_Int16 nSource = 0;
+ switch(nSubType)
+ {
+ case REF_SETREFATTR : nSource = ReferenceFieldSource::REFERENCE_MARK; break;
+ case REF_SEQUENCEFLD: nSource = ReferenceFieldSource::SEQUENCE_FIELD; break;
+ case REF_BOOKMARK : nSource = ReferenceFieldSource::BOOKMARK; break;
+ case REF_OUTLINE : OSL_FAIL("not implemented"); break;
+ case REF_FOOTNOTE : nSource = ReferenceFieldSource::FOOTNOTE; break;
+ case REF_ENDNOTE : nSource = ReferenceFieldSource::ENDNOTE; break;
+ }
+ rAny <<= nSource;
+ }
+ break;
+ case FIELD_PROP_PAR1:
+ {
+ String sTmp(GetPar1());
+ if(REF_SEQUENCEFLD == nSubType)
+ {
+ sal_uInt16 nPoolId = SwStyleNameMapper::GetPoolIdFromUIName( sTmp, nsSwGetPoolIdFromName::GET_POOLID_TXTCOLL );
+ switch( nPoolId )
+ {
+ case RES_POOLCOLL_LABEL_ABB:
+ case RES_POOLCOLL_LABEL_TABLE:
+ case RES_POOLCOLL_LABEL_FRAME:
+ case RES_POOLCOLL_LABEL_DRAWING:
+ SwStyleNameMapper::FillProgName(nPoolId, sTmp) ;
+ break;
+ }
+ }
+ rAny <<= rtl::OUString(sTmp);
+ }
+ break;
+ case FIELD_PROP_PAR3:
+ rAny <<= rtl::OUString(Expand());
+ break;
+ case FIELD_PROP_SHORT1:
+ rAny <<= (sal_Int16)nSeqNo;
+ break;
+ default:
+ OSL_FAIL("illegal property");
+ }
+ return true;
+}
+
+bool SwGetRefField::PutValue( const uno::Any& rAny, sal_uInt16 nWhichId )
+{
+ String sTmp;
+ switch( nWhichId )
+ {
+ case FIELD_PROP_USHORT1:
+ {
+ sal_Int16 nPart = 0;
+ rAny >>= nPart;
+ switch(nPart)
+ {
+ case ReferenceFieldPart::PAGE: nPart = REF_PAGE; break;
+ case ReferenceFieldPart::CHAPTER: nPart = REF_CHAPTER; break;
+ case ReferenceFieldPart::TEXT: nPart = REF_CONTENT; break;
+ case ReferenceFieldPart::UP_DOWN: nPart = REF_UPDOWN; break;
+ case ReferenceFieldPart::PAGE_DESC: nPart = REF_PAGE_PGDESC; break;
+ case ReferenceFieldPart::CATEGORY_AND_NUMBER: nPart = REF_ONLYNUMBER; break;
+ case ReferenceFieldPart::ONLY_CAPTION: nPart = REF_ONLYCAPTION; break;
+ case ReferenceFieldPart::ONLY_SEQUENCE_NUMBER : nPart = REF_ONLYSEQNO; break;
+ // --> OD 2007-09-06 #i81002#
+ case ReferenceFieldPart::NUMBER: nPart = REF_NUMBER; break;
+ case ReferenceFieldPart::NUMBER_NO_CONTEXT: nPart = REF_NUMBER_NO_CONTEXT; break;
+ case ReferenceFieldPart::NUMBER_FULL_CONTEXT: nPart = REF_NUMBER_FULL_CONTEXT; break;
+ // <--
+ default: return false;
+ }
+ SetFormat(nPart);
+ }
+ break;
+ case FIELD_PROP_USHORT2:
+ {
+ sal_Int16 nSource = 0;
+ rAny >>= nSource;
+ switch(nSource)
+ {
+ case ReferenceFieldSource::REFERENCE_MARK : nSubType = REF_SETREFATTR ; break;
+ case ReferenceFieldSource::SEQUENCE_FIELD :
+ {
+ if(REF_SEQUENCEFLD == nSubType)
+ break;
+ nSubType = REF_SEQUENCEFLD;
+ ConvertProgrammaticToUIName();
+ }
+ break;
+ case ReferenceFieldSource::BOOKMARK : nSubType = REF_BOOKMARK ; break;
+ case ReferenceFieldSource::FOOTNOTE : nSubType = REF_FOOTNOTE ; break;
+ case ReferenceFieldSource::ENDNOTE : nSubType = REF_ENDNOTE ; break;
+ }
+ }
+ break;
+ case FIELD_PROP_PAR1:
+ {
+ OUString sTmpStr;
+ rAny >>= sTmpStr;
+ SetPar1(sTmpStr);
+ ConvertProgrammaticToUIName();
+ }
+ break;
+ case FIELD_PROP_PAR3:
+ SetExpand( ::GetString( rAny, sTmp ));
+ break;
+ case FIELD_PROP_SHORT1:
+ {
+ sal_Int16 nSetSeq = 0;
+ rAny >>= nSetSeq;
+ if(nSetSeq >= 0)
+ nSeqNo = nSetSeq;
+ }
+ break;
+ default:
+ OSL_FAIL("illegal property");
+ }
+ return true;
+}
+
+void SwGetRefField::ConvertProgrammaticToUIName()
+{
+ if(GetTyp() && REF_SEQUENCEFLD == nSubType)
+ {
+ SwDoc* pDoc = ((SwGetRefFieldType*)GetTyp())->GetDoc();
+ const String& rPar1 = GetPar1();
+ //don't convert when the name points to an existing field type
+ if(!pDoc->GetFldType(RES_SETEXPFLD, rPar1, false))
+ {
+ sal_uInt16 nPoolId = SwStyleNameMapper::GetPoolIdFromProgName( rPar1, nsSwGetPoolIdFromName::GET_POOLID_TXTCOLL );
+ sal_uInt16 nResId = USHRT_MAX;
+ switch( nPoolId )
+ {
+ case RES_POOLCOLL_LABEL_ABB:
+ nResId = STR_POOLCOLL_LABEL_ABB;
+ break;
+ case RES_POOLCOLL_LABEL_TABLE:
+ nResId = STR_POOLCOLL_LABEL_TABLE;
+ break;
+ case RES_POOLCOLL_LABEL_FRAME:
+ nResId = STR_POOLCOLL_LABEL_FRAME;
+ break;
+ case RES_POOLCOLL_LABEL_DRAWING:
+ nResId = STR_POOLCOLL_LABEL_DRAWING;
+ break;
+ }
+ if( nResId != USHRT_MAX )
+ SetPar1(SW_RESSTR( nResId ));
+ }
+ }
+}
+
+SwGetRefFieldType::SwGetRefFieldType( SwDoc* pDc )
+ : SwFieldType( RES_GETREFFLD ), pDoc( pDc )
+{}
+
+
+SwFieldType* SwGetRefFieldType::Copy() const
+{
+ return new SwGetRefFieldType( pDoc );
+}
+
+
+void SwGetRefFieldType::Modify( const SfxPoolItem* pOld, const SfxPoolItem* pNew )
+{
+ // Update auf alle GetReferenz-Felder
+ if( !pNew && !pOld )
+ {
+ SwIterator<SwFmtFld,SwFieldType> aIter( *this );
+ for( SwFmtFld* pFld = aIter.First(); pFld; pFld = aIter.Next() )
+ {
+ // nur die GetRef-Felder Updaten
+ //JP 3.4.2001: Task 71231 - we need the correct language
+ SwGetRefField* pGRef = (SwGetRefField*)pFld->GetFld();
+ const SwTxtFld* pTFld;
+ if( !pGRef->GetLanguage() &&
+ 0 != ( pTFld = pFld->GetTxtFld()) &&
+ pTFld->GetpTxtNode() )
+ {
+ pGRef->SetLanguage( pTFld->GetpTxtNode()->GetLang(
+ *pTFld->GetStart() ) );
+ }
+
+ // --> OD 2007-09-06 #i81002#
+ pGRef->UpdateField( pFld->GetTxtFld() );
+ // <--
+ }
+ }
+ // weiter an die Text-Felder, diese "Expandieren" den Text
+ NotifyClients( pOld, pNew );
+}
+
+SwTxtNode* SwGetRefFieldType::FindAnchor( SwDoc* pDoc, const String& rRefMark,
+ sal_uInt16 nSubType, sal_uInt16 nSeqNo,
+ sal_uInt16* pStt, sal_uInt16* pEnd )
+{
+ OSL_ENSURE( pStt, "warum wird keine StartPos abgefragt?" );
+
+ SwTxtNode* pTxtNd = 0;
+ switch( nSubType )
+ {
+ case REF_SETREFATTR:
+ {
+ const SwFmtRefMark *pRef = pDoc->GetRefMark( rRefMark );
+ if( pRef && pRef->GetTxtRefMark() )
+ {
+ pTxtNd = (SwTxtNode*)&pRef->GetTxtRefMark()->GetTxtNode();
+ *pStt = *pRef->GetTxtRefMark()->GetStart();
+ if( pEnd )
+ *pEnd = *pRef->GetTxtRefMark()->GetAnyEnd();
+ }
+ }
+ break;
+
+ case REF_SEQUENCEFLD:
+ {
+ SwFieldType* pFldType = pDoc->GetFldType( RES_SETEXPFLD, rRefMark, false );
+ if( pFldType && pFldType->GetDepends() &&
+ nsSwGetSetExpType::GSE_SEQ & ((SwSetExpFieldType*)pFldType)->GetType() )
+ {
+ SwIterator<SwFmtFld,SwFieldType> aIter( *pFldType );
+ for( SwFmtFld* pFld = aIter.First(); pFld; pFld = aIter.Next() )
+ {
+ if( pFld->GetTxtFld() && nSeqNo ==
+ ((SwSetExpField*)pFld->GetFld())->GetSeqNumber() )
+ {
+ SwTxtFld* pTxtFld = pFld->GetTxtFld();
+ pTxtNd = (SwTxtNode*)pTxtFld->GetpTxtNode();
+ *pStt = *pTxtFld->GetStart();
+ if( pEnd )
+ *pEnd = (*pStt) + 1;
+ break;
+ }
+ }
+ }
+ }
+ break;
+
+ case REF_BOOKMARK:
+ {
+ IDocumentMarkAccess::const_iterator_t ppMark = pDoc->getIDocumentMarkAccess()->findMark(rRefMark);
+ if(ppMark != pDoc->getIDocumentMarkAccess()->getMarksEnd())
+ {
+ const ::sw::mark::IMark* pBkmk = ppMark->get();
+ const SwPosition* pPos = &pBkmk->GetMarkStart();
+
+ pTxtNd = pPos->nNode.GetNode().GetTxtNode();
+ *pStt = pPos->nContent.GetIndex();
+ if(pEnd)
+ {
+ if(!pBkmk->IsExpanded())
+ {
+ *pEnd = *pStt;
+ // --> OD 2007-10-18 #i81002#
+ if(dynamic_cast< ::sw::mark::CrossRefBookmark const *>(pBkmk))
+ {
+ OSL_ENSURE( pTxtNd,
+ "<SwGetRefFieldType::FindAnchor(..)> - node marked by cross-reference bookmark isn't a text node --> crash" );
+ *pEnd = pTxtNd->Len();
+ }
+ // <--
+ }
+ else if(pBkmk->GetOtherMarkPos().nNode == pBkmk->GetMarkPos().nNode)
+ *pEnd = pBkmk->GetMarkEnd().nContent.GetIndex();
+ else
+ *pEnd = USHRT_MAX;
+ }
+ }
+ }
+ break;
+
+ case REF_OUTLINE:
+ break;
+
+ case REF_FOOTNOTE:
+ case REF_ENDNOTE:
+ {
+ sal_uInt16 n, nFtnCnt = pDoc->GetFtnIdxs().Count();
+ SwTxtFtn* pFtnIdx;
+ for( n = 0; n < nFtnCnt; ++n )
+ if( nSeqNo == (pFtnIdx = pDoc->GetFtnIdxs()[ n ])->GetSeqRefNo() )
+ {
+ SwNodeIndex* pIdx = pFtnIdx->GetStartNode();
+ if( pIdx )
+ {
+ SwNodeIndex aIdx( *pIdx, 1 );
+ if( 0 == ( pTxtNd = aIdx.GetNode().GetTxtNode()))
+ pTxtNd = (SwTxtNode*)pDoc->GetNodes().GoNext( &aIdx );
+ }
+ *pStt = 0;
+ if( pEnd )
+ *pEnd = 0;
+ break;
+ }
+ }
+ break;
+ }
+
+ return pTxtNd;
+}
+
+
+struct _RefIdsMap
+{
+ String aName;
+ SvUShortsSort aIds, aDstIds, aIdsMap;
+ SvUShorts aMap;
+ sal_Bool bInit;
+
+ _RefIdsMap( const String& rName )
+ : aName( rName ), aIds( 16, 16 ), aIdsMap( 16, 16 ), aMap( 16, 16 ),
+ bInit( sal_False )
+ {}
+
+ void Check( SwDoc& rDoc, SwDoc& rDestDoc, SwGetRefField& rFld,
+ sal_Bool bField = sal_True );
+
+ sal_Bool IsInit() const { return bInit; }
+};
+
+SV_DECL_PTRARR_DEL( _RefIdsMaps, _RefIdsMap*, 5, 5 )
+SV_IMPL_PTRARR( _RefIdsMaps, _RefIdsMap* )
+
+void _RefIdsMap::Check( SwDoc& rDoc, SwDoc& rDestDoc, SwGetRefField& rFld,
+ sal_Bool bField )
+{
+
+ if( !bInit )
+ {
+ if( bField )
+ {
+ const SwTxtNode* pNd;
+ SwFieldType* pType;
+ if( 0 != ( pType = rDestDoc.GetFldType( RES_SETEXPFLD, aName, false ) ))
+ {
+ SwIterator<SwFmtFld,SwFieldType> aIter( *pType );
+ for( SwFmtFld* pF = aIter.First(); pF; pF = aIter.Next() )
+ if( pF->GetTxtFld() &&
+ 0 != ( pNd = pF->GetTxtFld()->GetpTxtNode() ) &&
+ pNd->GetNodes().IsDocNodes() )
+ aIds.Insert( ((SwSetExpField*)pF->GetFld())->GetSeqNumber() );
+ }
+ if( 0 != ( pType = rDoc.GetFldType( RES_SETEXPFLD, aName, false ) ))
+ {
+ SwIterator<SwFmtFld,SwFieldType> aIter( *pType );
+ for( SwFmtFld* pF = aIter.First(); pF; pF = aIter.Next() )
+ if( pF->GetTxtFld() &&
+ 0 != ( pNd = pF->GetTxtFld()->GetpTxtNode() ) &&
+ pNd->GetNodes().IsDocNodes() )
+ aDstIds.Insert( ((SwSetExpField*)pF->GetFld())->GetSeqNumber() );
+ }
+ }
+ else
+ {
+ sal_uInt16 n;
+
+ for( n = rDestDoc.GetFtnIdxs().Count(); n; )
+ aIds.Insert( rDestDoc.GetFtnIdxs()[ --n ]->GetSeqRefNo() );
+ for( n = rDoc.GetFtnIdxs().Count(); n; )
+ aDstIds.Insert( rDoc.GetFtnIdxs()[ --n ]->GetSeqRefNo() );
+ }
+ bInit = sal_True;
+ }
+
+ // dann teste mal, ob die Nummer schon vergeben ist
+ // oder ob eine neue bestimmt werden muss.
+ sal_uInt16 nPos, nSeqNo = rFld.GetSeqNo();
+ if( aIds.Seek_Entry( nSeqNo ) && aDstIds.Seek_Entry( nSeqNo ))
+ {
+ // ist schon vergeben, also muss eine neue
+ // erzeugt werden.
+ if( aIdsMap.Seek_Entry( nSeqNo, &nPos ))
+ rFld.SetSeqNo( aMap[ nPos ] );
+ else
+ {
+ sal_uInt16 n;
+
+ for( n = 0; n < aIds.Count(); ++n )
+ if( n != aIds[ n ] )
+ break;
+
+ // die neue SeqNo eintragen, damit die "belegt" ist
+ aIds.Insert( n );
+ aIdsMap.Insert( nSeqNo, nPos );
+ aMap.Insert( n, nPos );
+ rFld.SetSeqNo( n );
+
+ // und noch die Felder oder Fuss-/EndNote auf die neue
+ // Id umsetzen
+ if( bField )
+ {
+ SwFieldType* pType = rDoc.GetFldType( RES_SETEXPFLD, aName, false );
+ if( pType )
+ {
+ SwIterator<SwFmtFld,SwFieldType> aIter( *pType );
+ for( SwFmtFld* pF = aIter.First(); pF; pF = aIter.Next() )
+ if( pF->GetTxtFld() && nSeqNo ==
+ ((SwSetExpField*)pF->GetFld())->GetSeqNumber() )
+ ((SwSetExpField*)pF->GetFld())->SetSeqNumber( n );
+ }
+ }
+ else
+ {
+ SwTxtFtn* pFtnIdx;
+ for( sal_uInt16 i = 0, nCnt = rDoc.GetFtnIdxs().Count(); i < nCnt; ++i )
+ if( nSeqNo == (pFtnIdx = rDoc.GetFtnIdxs()[ i ])->GetSeqRefNo() )
+ {
+ pFtnIdx->SetSeqNo( n );
+ break;
+ }
+ }
+ }
+ }
+ else
+ {
+ aIds.Insert( nSeqNo );
+ aIdsMap.Insert( nSeqNo, nPos );
+ aMap.Insert( nSeqNo, nPos );
+ }
+}
+
+
+void SwGetRefFieldType::MergeWithOtherDoc( SwDoc& rDestDoc )
+{
+ if( &rDestDoc != pDoc &&
+ rDestDoc.GetSysFldType( RES_GETREFFLD )->GetDepends() )
+ {
+ // dann gibt es im DestDoc RefFelder, also muessen im SourceDoc
+ // alle RefFelder auf einduetige Ids in beiden Docs umgestellt
+ // werden.
+ _RefIdsMap aFntMap( aEmptyStr );
+ _RefIdsMaps aFldMap;
+
+ SwIterator<SwFmtFld,SwFieldType> aIter( *this );
+ for( SwFmtFld* pFld = aIter.First(); pFld; pFld = aIter.Next() )
+ {
+ SwGetRefField& rRefFld = *(SwGetRefField*)pFld->GetFld();
+ switch( rRefFld.GetSubType() )
+ {
+ case REF_SEQUENCEFLD:
+ {
+ _RefIdsMap* pMap = 0;
+ for( sal_uInt16 n = aFldMap.Count(); n; )
+ if( aFldMap[ --n ]->aName == rRefFld.GetSetRefName() )
+ {
+ pMap = aFldMap[ n ];
+ break;
+ }
+ if( !pMap )
+ {
+ pMap = new _RefIdsMap( rRefFld.GetSetRefName() );
+ aFldMap.C40_INSERT( _RefIdsMap, pMap, aFldMap.Count() );
+ }
+
+ pMap->Check( *pDoc, rDestDoc, rRefFld, sal_True );
+ }
+ break;
+
+ case REF_FOOTNOTE:
+ case REF_ENDNOTE:
+ aFntMap.Check( *pDoc, rDestDoc, rRefFld, sal_False );
+ break;
+ }
+ }
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/fields/scrptfld.cxx b/sw/source/core/fields/scrptfld.cxx
new file mode 100644
index 000000000000..3db79ca70afd
--- /dev/null
+++ b/sw/source/core/fields/scrptfld.cxx
@@ -0,0 +1,147 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+
+#include <docufld.hxx>
+#include <unofldmid.h>
+#include <comcore.hrc>
+#include <tools/resid.hxx>
+
+using namespace ::com::sun::star;
+using ::rtl::OUString;
+/*--------------------------------------------------------------------
+ Beschreibung: ScriptField
+ --------------------------------------------------------------------*/
+
+SwScriptFieldType::SwScriptFieldType( SwDoc* pD )
+ : SwFieldType( RES_SCRIPTFLD ), pDoc( pD )
+{}
+
+SwFieldType* SwScriptFieldType::Copy() const
+{
+ return new SwScriptFieldType( pDoc );
+}
+
+
+/*--------------------------------------------------------------------
+ Beschreibung: SwScriptField
+ --------------------------------------------------------------------*/
+
+SwScriptField::SwScriptField( SwScriptFieldType* pInitType,
+ const String& rType, const String& rCode,
+ sal_Bool bURL )
+ : SwField( pInitType ), sType( rType ), sCode( rCode ), bCodeURL( bURL )
+{
+}
+
+String SwScriptField::GetDescription() const
+{
+ return SW_RES(STR_SCRIPT);
+}
+
+String SwScriptField::Expand() const
+{
+ return aEmptyStr;
+}
+
+SwField* SwScriptField::Copy() const
+{
+ return new SwScriptField( (SwScriptFieldType*)GetTyp(), sType, sCode, bCodeURL );
+}
+
+/*--------------------------------------------------------------------
+ Beschreibung: Type setzen
+ --------------------------------------------------------------------*/
+
+void SwScriptField::SetPar1( const String& rStr )
+{
+ sType = rStr;
+}
+
+const String& SwScriptField::GetPar1() const
+{
+ return sType;
+}
+
+/*--------------------------------------------------------------------
+ Beschreibung: Code setzen
+ --------------------------------------------------------------------*/
+
+void SwScriptField::SetPar2( const String& rStr )
+{
+ sCode = rStr;
+}
+
+
+String SwScriptField::GetPar2() const
+{
+ return sCode;
+}
+
+bool SwScriptField::QueryValue( uno::Any& rAny, sal_uInt16 nWhichId ) const
+{
+ switch( nWhichId )
+ {
+ case FIELD_PROP_PAR1:
+ rAny <<= OUString( sType );
+ break;
+ case FIELD_PROP_PAR2:
+ rAny <<= OUString( sCode );
+ break;
+ case FIELD_PROP_BOOL1:
+ rAny.setValue(&bCodeURL, ::getBooleanCppuType());
+ break;
+ default:
+ OSL_FAIL("illegal property");
+ }
+ return true;
+}
+
+bool SwScriptField::PutValue( const uno::Any& rAny, sal_uInt16 nWhichId )
+{
+ switch( nWhichId )
+ {
+ case FIELD_PROP_PAR1:
+ ::GetString( rAny, sType );
+ break;
+ case FIELD_PROP_PAR2:
+ ::GetString( rAny, sCode );
+ break;
+ case FIELD_PROP_BOOL1:
+ bCodeURL = *(sal_Bool*)rAny.getValue();
+ break;
+ default:
+ OSL_FAIL("illegal property");
+ }
+ return true;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/fields/tblcalc.cxx b/sw/source/core/fields/tblcalc.cxx
new file mode 100644
index 000000000000..451c963f39ee
--- /dev/null
+++ b/sw/source/core/fields/tblcalc.cxx
@@ -0,0 +1,247 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+#include <switerator.hxx>
+#include <cntfrm.hxx>
+#include <doc.hxx>
+#include <pam.hxx> // fuer GetBodyTxtNode
+#include <ndtxt.hxx>
+#include <fmtfld.hxx>
+#include <txtfld.hxx>
+#include <expfld.hxx>
+#include <docfld.hxx> // fuer _SetGetExpFld
+#include <unofldmid.h>
+
+using namespace ::com::sun::star;
+using ::rtl::OUString;
+
+
+SwTblFieldType::SwTblFieldType(SwDoc* pDocPtr)
+ : SwValueFieldType( pDocPtr, RES_TABLEFLD )
+{}
+
+
+SwFieldType* SwTblFieldType::Copy() const
+{
+ return new SwTblFieldType(GetDoc());
+}
+
+
+
+void SwTblField::CalcField( SwTblCalcPara& rCalcPara )
+{
+ if( rCalcPara.rCalc.IsCalcError() ) // ist schon Fehler gesetzt ?
+ return;
+
+ // erzeuge aus den BoxNamen die Pointer
+ BoxNmToPtr( rCalcPara.pTbl );
+ String sFml( MakeFormel( rCalcPara ));
+ SetValue( rCalcPara.rCalc.Calculate( sFml ).GetDouble() );
+ ChgValid( !rCalcPara.IsStackOverFlow() ); // ist der Wert wieder gueltig?
+}
+
+
+
+SwTblField::SwTblField( SwTblFieldType* pInitType, const String& rFormel,
+ sal_uInt16 nType, sal_uLong nFmt )
+ : SwValueField( pInitType, nFmt ), SwTableFormula( rFormel ),
+ sExpand( '0' ), nSubType(nType)
+{
+}
+
+
+SwField* SwTblField::Copy() const
+{
+ SwTblField* pTmp = new SwTblField( (SwTblFieldType*)GetTyp(),
+ SwTableFormula::GetFormula(), nSubType, GetFormat() );
+ pTmp->sExpand = sExpand;
+ pTmp->SwValueField::SetValue(GetValue());
+ pTmp->SwTableFormula::operator=( *this );
+ pTmp->SetAutomaticLanguage(IsAutomaticLanguage());
+ return pTmp;
+}
+
+
+String SwTblField::GetFieldName() const
+{
+ String aStr(GetTyp()->GetName());
+ aStr += ' ';
+ aStr += const_cast<SwTblField *>(this)->GetCommand();
+ return aStr;
+}
+
+// suche den TextNode, in dem das Feld steht
+const SwNode* SwTblField::GetNodeOfFormula() const
+{
+ if( !GetTyp()->GetDepends() )
+ return 0;
+
+ SwIterator<SwFmtFld,SwFieldType> aIter( *GetTyp() );
+ for( SwFmtFld* pFmtFld = aIter.First(); pFmtFld; pFmtFld = aIter.Next() )
+ if( this == pFmtFld->GetFld() )
+ return (SwTxtNode*)&pFmtFld->GetTxtFld()->GetTxtNode();
+ return 0;
+}
+
+String SwTblField::GetCommand()
+{
+ if (EXTRNL_NAME != GetNameType())
+ {
+ SwNode const*const pNd = GetNodeOfFormula();
+ SwTableNode const*const pTblNd = (pNd) ? pNd->FindTableNode() : 0;
+ if (pTblNd)
+ {
+ PtrToBoxNm( &pTblNd->GetTable() );
+ }
+ }
+ return (EXTRNL_NAME == GetNameType())
+ ? SwTableFormula::GetFormula()
+ : String();
+}
+
+String SwTblField::Expand() const
+{
+ String aStr;
+ if (nSubType & nsSwExtendedSubType::SUB_CMD)
+ {
+ aStr = const_cast<SwTblField *>(this)->GetCommand();
+ }
+ else
+ {
+ aStr = sExpand;
+ if(nSubType & nsSwGetSetExpType::GSE_STRING)
+ {
+ // es ist ein String
+ aStr = sExpand;
+ aStr.Erase( 0,1 );
+ aStr.Erase( aStr.Len()-1, 1 );
+ }
+ }
+ return aStr;
+}
+
+sal_uInt16 SwTblField::GetSubType() const
+{
+ return nSubType;
+}
+
+void SwTblField::SetSubType(sal_uInt16 nType)
+{
+ nSubType = nType;
+}
+
+
+void SwTblField::SetValue( const double& rVal )
+{
+ SwValueField::SetValue(rVal);
+ sExpand = ((SwValueFieldType*)GetTyp())->ExpandValue(rVal, GetFormat(), GetLanguage());
+}
+
+/*--------------------------------------------------------------------
+ Beschreibung: Parameter setzen
+ --------------------------------------------------------------------*/
+
+
+String SwTblField::GetPar2() const
+{
+ return SwTableFormula::GetFormula();
+}
+
+
+void SwTblField::SetPar2(const String& rStr)
+{
+ SetFormula( rStr );
+}
+
+bool SwTblField::QueryValue( uno::Any& rAny, sal_uInt16 nWhichId ) const
+{
+ bool bRet = true;
+ switch ( nWhichId )
+ {
+ case FIELD_PROP_PAR2:
+ {
+ sal_uInt16 nOldSubType = nSubType;
+ SwTblField* pThis = (SwTblField*)this;
+ pThis->nSubType |= nsSwExtendedSubType::SUB_CMD;
+ rAny <<= rtl::OUString( Expand() );
+ pThis->nSubType = nOldSubType;
+ }
+ break;
+ case FIELD_PROP_BOOL1:
+ {
+ sal_Bool bFormula = 0 != (nsSwExtendedSubType::SUB_CMD & nSubType);
+ rAny.setValue(&bFormula, ::getBooleanCppuType());
+ }
+ break;
+ case FIELD_PROP_PAR1:
+ rAny <<= rtl::OUString(GetExpStr());
+ break;
+ case FIELD_PROP_FORMAT:
+ rAny <<= (sal_Int32)GetFormat();
+ break;
+ default:
+ bRet = false;
+ }
+ return bRet;
+}
+
+bool SwTblField::PutValue( const uno::Any& rAny, sal_uInt16 nWhichId )
+{
+ bool bRet = true;
+ String sTmp;
+ switch ( nWhichId )
+ {
+ case FIELD_PROP_PAR2:
+ SetFormula( ::GetString( rAny, sTmp ));
+ break;
+ case FIELD_PROP_BOOL1:
+ if(*(sal_Bool*)rAny.getValue())
+ nSubType = nsSwGetSetExpType::GSE_FORMULA|nsSwExtendedSubType::SUB_CMD;
+ else
+ nSubType = nsSwGetSetExpType::GSE_FORMULA;
+ break;
+ case FIELD_PROP_PAR1:
+ ChgExpStr( ::GetString( rAny, sTmp ));
+ break;
+ case FIELD_PROP_FORMAT:
+ {
+ sal_Int32 nTmp = 0;
+ rAny >>= nTmp;
+ SetFormat(nTmp);
+ }
+ break;
+ default:
+ bRet = false;
+ }
+ return bRet;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/fields/textapi.cxx b/sw/source/core/fields/textapi.cxx
new file mode 100644
index 000000000000..09d2ddc20fae
--- /dev/null
+++ b/sw/source/core/fields/textapi.cxx
@@ -0,0 +1,194 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+#include <textapi.hxx>
+#include <doc.hxx>
+#include <docsh.hxx>
+#include <editeng/eeitem.hxx>
+#include <editeng/editeng.hxx>
+
+#include <com/sun/star/text/XTextField.hpp>
+#include <com/sun/star/container/XNameContainer.hpp>
+#include <com/sun/star/beans/PropertyAttribute.hpp>
+
+using namespace com::sun::star;
+
+static const SvxItemPropertySet* ImplGetSvxTextPortionPropertySet()
+{
+ static const SfxItemPropertyMapEntry aSvxTextPortionPropertyMap[] =
+ {
+ SVX_UNOEDIT_CHAR_PROPERTIES,
+ SVX_UNOEDIT_FONT_PROPERTIES,
+ SVX_UNOEDIT_OUTLINER_PROPERTIES,
+ SVX_UNOEDIT_PARA_PROPERTIES,
+ {MAP_CHAR_LEN("TextField"), EE_FEATURE_FIELD, &::getCppuType((const uno::Reference< text::XTextField >*)0), beans::PropertyAttribute::READONLY, 0 },
+ {MAP_CHAR_LEN("TextPortionType"), WID_PORTIONTYPE, &::getCppuType((const ::rtl::OUString*)0), beans::PropertyAttribute::READONLY, 0 },
+ {MAP_CHAR_LEN("TextUserDefinedAttributes"), EE_CHAR_XMLATTRIBS, &::getCppuType((const ::com::sun::star::uno::Reference< ::com::sun::star::container::XNameContainer >*)0) , 0, 0},
+ {MAP_CHAR_LEN("ParaUserDefinedAttributes"), EE_PARA_XMLATTRIBS, &::getCppuType((const ::com::sun::star::uno::Reference< ::com::sun::star::container::XNameContainer >*)0) , 0, 0},
+ {0,0,0,0,0,0}
+ };
+ static SvxItemPropertySet aSvxTextPortionPropertySet( aSvxTextPortionPropertyMap, EditEngine::GetGlobalItemPool() );
+ return &aSvxTextPortionPropertySet;
+}
+
+SwTextAPIObject::SwTextAPIObject( SwTextAPIEditSource* p )
+: SvxUnoText( p, ImplGetSvxTextPortionPropertySet(), uno::Reference < text::XText >() )
+, pSource(p)
+{
+}
+
+SwTextAPIObject::~SwTextAPIObject() throw()
+{
+ pSource->Dispose();
+ delete pSource;
+}
+
+struct SwTextAPIEditSource_Impl
+{
+ // needed for "internal" refcounting
+ SfxItemPool* mpPool;
+ SwDoc* mpDoc;
+ Outliner* mpOutliner;
+ SvxOutlinerForwarder* mpTextForwarder;
+ sal_Int32 mnRef;
+};
+
+SwTextAPIEditSource::SwTextAPIEditSource( const SwTextAPIEditSource& rSource )
+: SvxEditSource( *this )
+{
+ // shallow copy; uses internal refcounting
+ pImpl = rSource.pImpl;
+ pImpl->mnRef++;
+}
+
+SvxEditSource* SwTextAPIEditSource::Clone() const
+{
+ return new SwTextAPIEditSource( *this );
+}
+
+void SwTextAPIEditSource::UpdateData()
+{
+ // data is kept in outliner all the time
+}
+
+SwTextAPIEditSource::SwTextAPIEditSource(SwDoc* pDoc)
+: pImpl(new SwTextAPIEditSource_Impl)
+{
+ pImpl->mpPool = &pDoc->GetDocShell()->GetPool();
+ pImpl->mpDoc = pDoc;
+ pImpl->mpOutliner = 0;
+ pImpl->mpTextForwarder = 0;
+ pImpl->mnRef = 1;
+}
+
+SwTextAPIEditSource::~SwTextAPIEditSource()
+{
+ if (!--pImpl->mnRef)
+ delete pImpl;
+}
+
+void SwTextAPIEditSource::Dispose()
+{
+ pImpl->mpPool=0;
+ pImpl->mpDoc=0;
+ DELETEZ(pImpl->mpTextForwarder);
+ DELETEZ(pImpl->mpOutliner);
+}
+
+SvxTextForwarder* SwTextAPIEditSource::GetTextForwarder()
+{
+ if( !pImpl->mpPool )
+ return 0; // mpPool == 0 can be used to flag this as disposed
+
+ if( !pImpl->mpOutliner )
+ {
+ //init draw model first
+ pImpl->mpDoc->GetOrCreateDrawModel();
+ pImpl->mpOutliner = new Outliner( pImpl->mpPool, OUTLINERMODE_TEXTOBJECT );
+ pImpl->mpDoc->SetCalcFieldValueHdl( pImpl->mpOutliner );
+ }
+
+ if( !pImpl->mpTextForwarder )
+ pImpl->mpTextForwarder = new SvxOutlinerForwarder( *pImpl->mpOutliner, 0 );
+
+ return pImpl->mpTextForwarder;
+}
+
+void SwTextAPIEditSource::SetText( OutlinerParaObject& rText )
+{
+ if ( pImpl->mpPool )
+ {
+ if( !pImpl->mpOutliner )
+ {
+ //init draw model first
+ pImpl->mpDoc->GetOrCreateDrawModel();
+ pImpl->mpOutliner = new Outliner( pImpl->mpPool, OUTLINERMODE_TEXTOBJECT );
+ pImpl->mpDoc->SetCalcFieldValueHdl( pImpl->mpOutliner );
+ }
+
+ pImpl->mpOutliner->SetText( rText );
+ }
+}
+
+void SwTextAPIEditSource::SetString( const String& rText )
+{
+ if ( pImpl->mpPool )
+ {
+ if( !pImpl->mpOutliner )
+ {
+ //init draw model first
+ pImpl->mpDoc->GetOrCreateDrawModel();
+ pImpl->mpOutliner = new Outliner( pImpl->mpPool, OUTLINERMODE_TEXTOBJECT );
+ pImpl->mpDoc->SetCalcFieldValueHdl( pImpl->mpOutliner );
+ }
+ else
+ pImpl->mpOutliner->Clear();
+ pImpl->mpOutliner->Insert( rText );
+ }
+}
+
+OutlinerParaObject* SwTextAPIEditSource::CreateText()
+{
+ if ( pImpl->mpPool && pImpl->mpOutliner )
+ return pImpl->mpOutliner->CreateParaObject();
+ else
+ return 0;
+}
+
+String SwTextAPIEditSource::GetText()
+{
+ if ( pImpl->mpPool && pImpl->mpOutliner )
+ return pImpl->mpOutliner->GetEditEngine().GetText();
+ else
+ return String();
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/fields/usrfld.cxx b/sw/source/core/fields/usrfld.cxx
new file mode 100644
index 000000000000..e5ba807f44fa
--- /dev/null
+++ b/sw/source/core/fields/usrfld.cxx
@@ -0,0 +1,369 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+#include <svl/zforlist.hxx>
+#include <svl/zformat.hxx>
+
+#include <svx/svdmodel.hxx>
+
+#include <calbck.hxx>
+#include <calc.hxx>
+#include <usrfld.hxx>
+#include <doc.hxx>
+#include <IDocumentUndoRedo.hxx>
+#include <editsh.hxx>
+#include <dpage.hxx>
+#include <unofldmid.h>
+
+
+using namespace ::com::sun::star;
+using ::rtl::OUString;
+
+/*--------------------------------------------------------------------
+ Beschreibung: Benutzerfelder
+ --------------------------------------------------------------------*/
+
+SwUserField::SwUserField(SwUserFieldType* pTyp, sal_uInt16 nSub, sal_uInt32 nFmt)
+ : SwValueField(pTyp, nFmt),
+ nSubType(nSub)
+{
+}
+
+String SwUserField::Expand() const
+{
+ String sStr;
+ if(!(nSubType & nsSwExtendedSubType::SUB_INVISIBLE))
+ sStr = ((SwUserFieldType*)GetTyp())->Expand(GetFormat(), nSubType, GetLanguage());
+
+ return sStr;
+}
+
+SwField* SwUserField::Copy() const
+{
+ SwField* pTmp = new SwUserField((SwUserFieldType*)GetTyp(), nSubType, GetFormat());
+ pTmp->SetAutomaticLanguage(IsAutomaticLanguage());
+ return pTmp;
+}
+
+String SwUserField::GetFieldName() const
+{
+ String aStr(SwFieldType::GetTypeStr(TYP_USERFLD));
+ aStr += ' ';
+ aStr += GetTyp()->GetName();
+ aStr.AppendAscii(" = ");
+ aStr += static_cast<SwUserFieldType*>(GetTyp())->GetContent();
+ return aStr;
+}
+
+double SwUserField::GetValue() const
+{
+ return ((SwUserFieldType*)GetTyp())->GetValue();
+}
+
+void SwUserField::SetValue( const double& rVal )
+{
+ ((SwUserFieldType*)GetTyp())->SetValue(rVal);
+}
+
+/*--------------------------------------------------------------------
+ Beschreibung: Name
+ --------------------------------------------------------------------*/
+
+const String& SwUserField::GetPar1() const
+{
+ return ((SwUserFieldType*)GetTyp())->GetName();
+}
+
+/*--------------------------------------------------------------------
+ Beschreibung: Content
+ --------------------------------------------------------------------*/
+
+String SwUserField::GetPar2() const
+{
+ return ((SwUserFieldType*)GetTyp())->GetContent(GetFormat());
+}
+
+void SwUserField::SetPar2(const String& rStr)
+{
+ ((SwUserFieldType*)GetTyp())->SetContent(rStr, GetFormat());
+}
+
+sal_uInt16 SwUserField::GetSubType() const
+{
+ return ((SwUserFieldType*)GetTyp())->GetType() | nSubType;
+}
+
+void SwUserField::SetSubType(sal_uInt16 nSub)
+{
+ ((SwUserFieldType*)GetTyp())->SetType(nSub & 0x00ff);
+ nSubType = nSub & 0xff00;
+}
+
+bool SwUserField::QueryValue( uno::Any& rAny, sal_uInt16 nWhichId ) const
+{
+ switch( nWhichId )
+ {
+ case FIELD_PROP_BOOL2:
+ {
+ sal_Bool bTmp = 0 != (nSubType & nsSwExtendedSubType::SUB_CMD);
+ rAny.setValue(&bTmp, ::getBooleanCppuType());
+ }
+ break;
+ case FIELD_PROP_BOOL1:
+ {
+ sal_Bool bTmp = 0 == (nSubType & nsSwExtendedSubType::SUB_INVISIBLE);
+ rAny.setValue(&bTmp, ::getBooleanCppuType());
+ }
+ break;
+ case FIELD_PROP_FORMAT:
+ rAny <<= (sal_Int32)GetFormat();
+ break;
+ default:
+ return SwField::QueryValue(rAny, nWhichId);
+ }
+ return true;
+}
+
+bool SwUserField::PutValue( const uno::Any& rAny, sal_uInt16 nWhichId )
+{
+ switch( nWhichId )
+ {
+ case FIELD_PROP_BOOL1:
+ if(*(sal_Bool*) rAny.getValue())
+ nSubType &= (~nsSwExtendedSubType::SUB_INVISIBLE);
+ else
+ nSubType |= nsSwExtendedSubType::SUB_INVISIBLE;
+ break;
+ case FIELD_PROP_BOOL2:
+ if(*(sal_Bool*) rAny.getValue())
+ nSubType |= nsSwExtendedSubType::SUB_CMD;
+ else
+ nSubType &= (~nsSwExtendedSubType::SUB_CMD);
+ break;
+ case FIELD_PROP_FORMAT:
+ {
+ sal_Int32 nTmp = 0;
+ rAny >>= nTmp;
+ SetFormat(nTmp);
+ }
+ break;
+ default:
+ return SwField::PutValue(rAny, nWhichId);
+ }
+ return true;
+}
+
+/*--------------------------------------------------------------------
+ Beschreibung: Benutzerfeldtypen
+ --------------------------------------------------------------------*/
+
+SwUserFieldType::SwUserFieldType( SwDoc* pDocPtr, const String& aNam )
+ : SwValueFieldType( pDocPtr, RES_USERFLD ),
+ nValue( 0 ),
+ nType(nsSwGetSetExpType::GSE_STRING)
+{
+ bValidValue = bDeleted = sal_False;
+ aName = aNam;
+
+ if (nType & nsSwGetSetExpType::GSE_STRING)
+ EnableFormat(sal_False); // Numberformatter nicht einsetzen
+}
+
+String SwUserFieldType::Expand(sal_uInt32 nFmt, sal_uInt16 nSubType, sal_uInt16 nLng)
+{
+ String aStr(aContent);
+ if((nType & nsSwGetSetExpType::GSE_EXPR) && !(nSubType & nsSwExtendedSubType::SUB_CMD))
+ {
+ EnableFormat(sal_True);
+ aStr = ExpandValue(nValue, nFmt, nLng);
+ }
+ else
+ EnableFormat(sal_False); // Numberformatter nicht einsetzen
+
+ return aStr;
+}
+
+SwFieldType* SwUserFieldType::Copy() const
+{
+ SwUserFieldType *pTmp = new SwUserFieldType( GetDoc(), aName );
+ pTmp->aContent = aContent;
+ pTmp->nType = nType;
+ pTmp->bValidValue = bValidValue;
+ pTmp->nValue = nValue;
+ pTmp->bDeleted = bDeleted;
+
+ return pTmp;
+}
+
+const String& SwUserFieldType::GetName() const
+{
+ return aName;
+}
+
+void SwUserFieldType::Modify( const SfxPoolItem* pOld, const SfxPoolItem* pNew )
+{
+ if( !pOld && !pNew )
+ ChgValid( sal_False );
+
+ NotifyClients( pOld, pNew );
+ // und ggfs. am UserFeld haengende InputFelder updaten!
+ GetDoc()->GetSysFldType( RES_INPUTFLD )->UpdateFlds();
+}
+
+double SwUserFieldType::GetValue( SwCalc& rCalc )
+{
+ if(bValidValue)
+ return nValue;
+
+ if(!rCalc.Push( this ))
+ {
+ rCalc.SetCalcError( CALC_SYNTAX );
+ return 0;
+ }
+ nValue = rCalc.Calculate( aContent ).GetDouble();
+ rCalc.Pop( this );
+
+ if( !rCalc.IsCalcError() )
+ bValidValue = sal_True;
+ else
+ nValue = 0;
+
+ return nValue;
+}
+
+String SwUserFieldType::GetContent( sal_uInt32 nFmt )
+{
+ if (nFmt && nFmt != SAL_MAX_UINT32)
+ {
+ String sFormattedValue;
+ Color* pCol = 0;
+
+ SvNumberFormatter* pFormatter = GetDoc()->GetNumberFormatter();
+
+ pFormatter->GetOutputString(GetValue(), nFmt, sFormattedValue, &pCol);
+ return sFormattedValue;
+ }
+ else
+ return aContent;
+}
+
+void SwUserFieldType::SetContent( const String& rStr, sal_uInt32 nFmt )
+{
+ if( aContent != rStr )
+ {
+ aContent = rStr;
+
+ if (nFmt && nFmt != SAL_MAX_UINT32)
+ {
+ double fValue;
+
+ SvNumberFormatter* pFormatter = GetDoc()->GetNumberFormatter();
+
+ if (pFormatter->IsNumberFormat(rStr, nFmt, fValue))
+ {
+ SetValue(fValue);
+ aContent.Erase();
+ DoubleToString(aContent, fValue, nFmt);
+ }
+ }
+
+ sal_Bool bModified = GetDoc()->IsModified();
+ GetDoc()->SetModified();
+ if( !bModified ) // Bug 57028
+ {
+ GetDoc()->GetIDocumentUndoRedo().SetUndoNoResetModified();
+ }
+ }
+}
+
+bool SwUserFieldType::QueryValue( uno::Any& rAny, sal_uInt16 nWhichId ) const
+{
+ switch( nWhichId )
+ {
+ case FIELD_PROP_DOUBLE:
+ rAny <<= (double) nValue;
+ break;
+ case FIELD_PROP_PAR2:
+ rAny <<= rtl::OUString(aContent);
+ break;
+ case FIELD_PROP_BOOL1:
+ {
+ sal_Bool bExpression = 0 != (nsSwGetSetExpType::GSE_EXPR&nType);
+ rAny.setValue(&bExpression, ::getBooleanCppuType());
+ }
+ break;
+ default:
+ OSL_FAIL("illegal property");
+ }
+ return true;
+}
+
+bool SwUserFieldType::PutValue( const uno::Any& rAny, sal_uInt16 nWhichId )
+{
+ switch( nWhichId )
+ {
+ case FIELD_PROP_DOUBLE:
+ {
+ double fVal = 0;
+ rAny >>= fVal;
+ nValue = fVal;
+
+ // Folgende Zeile ist eigentlich falsch, da die Sprache unbekannt ist
+ // (haengt am Feld) und aContent daher auch eigentlich ans Feld gehoeren
+ // muesste. Jedes Feld kann eine andere Sprache, aber den gleichen Inhalt
+ // haben, nur die Formatierung ist unterschiedlich.
+ DoubleToString(aContent, nValue, (sal_uInt16)LANGUAGE_SYSTEM);
+ }
+ break;
+ case FIELD_PROP_PAR2:
+ ::GetString( rAny, aContent );
+ break;
+ case FIELD_PROP_BOOL1:
+ if(*(sal_Bool*)rAny.getValue())
+ {
+ nType |= nsSwGetSetExpType::GSE_EXPR;
+ nType &= ~nsSwGetSetExpType::GSE_STRING;
+ }
+ else
+ {
+ nType &= ~nsSwGetSetExpType::GSE_EXPR;
+ nType |= nsSwGetSetExpType::GSE_STRING;
+ }
+ break;
+ default:
+ OSL_FAIL("illegal property");
+ }
+ return true;
+}
+
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/frmedt/fecopy.cxx b/sw/source/core/frmedt/fecopy.cxx
new file mode 100644
index 000000000000..8662286726de
--- /dev/null
+++ b/sw/source/core/frmedt/fecopy.cxx
@@ -0,0 +1,1539 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+
+#include <hintids.hxx>
+
+#include <vcl/graph.hxx>
+#include <sot/formats.hxx>
+#include <sot/storage.hxx>
+#include <unotools/pathoptions.hxx>
+#include <sfx2/dispatch.hxx>
+#include <sfx2/viewsh.hxx>
+#include <svx/xexch.hxx>
+#include <svx/xflasit.hxx>
+#include <svx/xfillit0.hxx>
+#include <svx/xflclit.hxx>
+#include <editeng/brshitem.hxx>
+#include <svx/svdocapt.hxx>
+#include <svx/svdouno.hxx>
+#include <svx/xfillit.hxx>
+#include <svx/svdpage.hxx>
+#include <svx/svdogrp.hxx>
+#include <svx/xoutbmp.hxx>
+#include <svx/svdoole2.hxx>
+#include <svx/fmmodel.hxx>
+#include <svx/unomodel.hxx>
+#include <svx/svditer.hxx> // #i50824#
+#include <svx/svdograf.hxx>
+#include <unotools/streamwrap.hxx>
+#include <fmtanchr.hxx>
+#include <fmtcntnt.hxx>
+#include <fmtornt.hxx>
+#include <fmtflcnt.hxx>
+#include <frmfmt.hxx>
+#include <docary.hxx>
+#include <txtfrm.hxx>
+#include <txtflcnt.hxx>
+#include <fesh.hxx>
+#include <doc.hxx>
+#include <IDocumentUndoRedo.hxx>
+#include <rootfrm.hxx>
+#include <ndtxt.hxx>
+#include <pam.hxx>
+#include <tblsel.hxx>
+#include <swtable.hxx>
+#include <flyfrm.hxx>
+#include <pagefrm.hxx>
+#include <fldbas.hxx>
+#include <edimp.hxx>
+#include <swundo.hxx>
+#include <viewimp.hxx>
+#include <dview.hxx>
+#include <dcontact.hxx>
+#include <dflyobj.hxx>
+#include <docsh.hxx>
+#include <pagedesc.hxx>
+#include <mvsave.hxx>
+#include <vcl/virdev.hxx>
+
+
+using namespace ::com::sun::star;
+
+/*************************************************************************
+|*
+|* SwFEShell::Copy() Copy fuer das Interne Clipboard.
+|* Kopiert alle Selektionen in das Clipboard.
+|*
+|*************************************************************************/
+
+sal_Bool SwFEShell::Copy( SwDoc* pClpDoc, const String* pNewClpTxt )
+{
+ OSL_ENSURE( pClpDoc, "kein Clipboard-Dokument" );
+
+ pClpDoc->GetIDocumentUndoRedo().DoUndo(false); // always false!
+
+ // steht noch Inhalt im ClpDocument, dann muss dieser geloescht werden
+ SwNodeIndex aSttIdx( pClpDoc->GetNodes().GetEndOfExtras(), 2 );
+ SwTxtNode* pTxtNd = aSttIdx.GetNode().GetTxtNode();
+ if( !pTxtNd || pTxtNd->GetTxt().Len() ||
+ aSttIdx.GetIndex()+1 != pClpDoc->GetNodes().GetEndOfContent().GetIndex() )
+ {
+ pClpDoc->GetNodes().Delete( aSttIdx,
+ pClpDoc->GetNodes().GetEndOfContent().GetIndex() - aSttIdx.GetIndex() );
+ pTxtNd = pClpDoc->GetNodes().MakeTxtNode( aSttIdx,
+ (SwTxtFmtColl*)pClpDoc->GetDfltTxtFmtColl() );
+ aSttIdx--;
+ }
+
+ // stehen noch FlyFrames rum, loesche auch diese
+ for( sal_uInt16 n = 0; n < pClpDoc->GetSpzFrmFmts()->Count(); ++n )
+ {
+ SwFlyFrmFmt* pFly = (SwFlyFrmFmt*)(*pClpDoc->GetSpzFrmFmts())[n];
+ pClpDoc->DelLayoutFmt( pFly );
+ }
+ pClpDoc->GCFieldTypes(); // loesche die FieldTypes
+
+ // wurde ein String uebergeben, so kopiere diesen in das Clipboard-
+ // Dokument. Somit kann auch der Calculator das interne Clipboard
+ // benutzen.
+ if( pNewClpTxt )
+ {
+ pTxtNd->InsertText( *pNewClpTxt, SwIndex( pTxtNd ) );
+ return sal_True; // das wars.
+ }
+
+ pClpDoc->LockExpFlds();
+ pClpDoc->SetRedlineMode_intern( nsRedlineMode_t::REDLINE_DELETE_REDLINES );
+ sal_Bool bRet;
+
+ // soll ein FlyFrame kopiert werden ?
+ if( IsFrmSelected() )
+ {
+ // hole das FlyFormat
+ SwFlyFrm* pFly = FindFlyFrm();
+ SwFrmFmt* pFlyFmt = pFly->GetFmt();
+ SwFmtAnchor aAnchor( pFlyFmt->GetAnchor() );
+
+ if ((FLY_AT_PARA == aAnchor.GetAnchorId()) ||
+ (FLY_AT_CHAR == aAnchor.GetAnchorId()) ||
+ (FLY_AT_FLY == aAnchor.GetAnchorId()) ||
+ (FLY_AS_CHAR == aAnchor.GetAnchorId()))
+ {
+ SwPosition aPos( aSttIdx );
+ if ( FLY_AS_CHAR == aAnchor.GetAnchorId() )
+ {
+ aPos.nContent.Assign( pTxtNd, 0 );
+ }
+ aAnchor.SetAnchor( &aPos );
+ }
+ pFlyFmt = pClpDoc->CopyLayoutFmt( *pFlyFmt, aAnchor, true, true );
+
+ // sorge dafuer das das "RootFmt" als erstes im SpzArray-steht
+ // (Es wurden ggf. Flys in Flys kopiert.
+ SwSpzFrmFmts& rSpzFrmFmts = *(SwSpzFrmFmts*)pClpDoc->GetSpzFrmFmts();
+ if( rSpzFrmFmts[ 0 ] != pFlyFmt )
+ {
+ sal_uInt16 nPos = rSpzFrmFmts.GetPos( pFlyFmt );
+ OSL_ENSURE( nPos != USHRT_MAX, "Fly steht nicht im Spz-Array" );
+
+ rSpzFrmFmts.Remove( nPos );
+ rSpzFrmFmts.Insert( pFlyFmt, 0 );
+ }
+
+ if ( FLY_AS_CHAR == aAnchor.GetAnchorId() )
+ {
+ // JP 13.02.99 Bug 61863: wenn eine Rahmenselektion ins Clipboard
+ // gestellt wird, so muss beim Pasten auch wieder
+ // eine solche vorgefunden werden. Also muss im Node
+ // das kopierte TextAttribut wieder entfernt werden,
+ // sonst wird es als TextSelektion erkannt
+ const SwIndex& rIdx = pFlyFmt->GetAnchor().GetCntntAnchor()->nContent;
+ SwTxtFlyCnt *const pTxtFly = static_cast<SwTxtFlyCnt *>(
+ pTxtNd->GetTxtAttrForCharAt(
+ rIdx.GetIndex(), RES_TXTATR_FLYCNT));
+ if( pTxtFly )
+ {
+ ((SwFmtFlyCnt&)pTxtFly->GetFlyCnt()).SetFlyFmt( 0 );
+ pTxtNd->EraseText( rIdx, 1 );
+ }
+ }
+ bRet = sal_True;
+ }
+ else if ( IsObjSelected() )
+ {
+ SwPosition aPos( aSttIdx, SwIndex( pTxtNd, 0 ));
+ const SdrMarkList &rMrkList = Imp()->GetDrawView()->GetMarkedObjectList();
+ for ( sal_uInt16 i = 0; i < rMrkList.GetMarkCount(); ++i )
+ {
+ SdrObject *pObj = rMrkList.GetMark( i )->GetMarkedSdrObj();
+
+ if( Imp()->GetDrawView()->IsGroupEntered() ||
+ ( !pObj->GetUserCall() && pObj->GetUpGroup()) )
+ {
+ SfxItemSet aSet( pClpDoc->GetAttrPool(), aFrmFmtSetRange );
+
+ SwFmtAnchor aAnchor( FLY_AT_PARA );
+ aAnchor.SetAnchor( &aPos );
+ aSet.Put( aAnchor );
+
+ SdrObject *const pNew =
+ pClpDoc->CloneSdrObj( *pObj, sal_False, sal_True );
+
+ SwPaM aTemp(aPos);
+ pClpDoc->Insert(aTemp, *pNew, &aSet, NULL);
+ }
+ else
+ {
+ SwDrawContact *pContact = (SwDrawContact*)GetUserCall( pObj );
+ SwFrmFmt *pFmt = pContact->GetFmt();
+ SwFmtAnchor aAnchor( pFmt->GetAnchor() );
+ if ((FLY_AT_PARA == aAnchor.GetAnchorId()) ||
+ (FLY_AT_CHAR == aAnchor.GetAnchorId()) ||
+ (FLY_AT_FLY == aAnchor.GetAnchorId()) ||
+ (FLY_AS_CHAR == aAnchor.GetAnchorId()))
+ {
+ aAnchor.SetAnchor( &aPos );
+ }
+
+ pClpDoc->CopyLayoutFmt( *pFmt, aAnchor, true, true );
+ }
+ }
+ bRet = sal_True;
+ }
+ else
+ bRet = _CopySelToDoc( pClpDoc, 0 ); // kopiere die Selectionen
+
+ pClpDoc->SetRedlineMode_intern((RedlineMode_t)0 );
+ pClpDoc->UnlockExpFlds();
+ if( !pClpDoc->IsExpFldsLocked() )
+ pClpDoc->UpdateExpFlds(NULL, true);
+
+ return bRet;
+}
+
+const Point &lcl_FindBasePos( const SwFrm *pFrm, const Point &rPt )
+{
+ const SwFrm *pF = pFrm;
+ while ( pF && !pF->Frm().IsInside( rPt ) )
+ {
+ if ( pF->IsCntntFrm() )
+ pF = ((SwCntntFrm*)pF)->GetFollow();
+ else
+ pF = 0;
+ }
+ if ( pF )
+ return pF->Frm().Pos();
+ else
+ return pFrm->Frm().Pos();
+}
+
+sal_Bool lcl_SetAnchor( const SwPosition& rPos, const SwNode& rNd, SwFlyFrm* pFly,
+ const Point& rInsPt, SwFEShell& rDestShell, SwFmtAnchor& rAnchor,
+ Point& rNewPos, sal_Bool bCheckFlyRecur )
+{
+ sal_Bool bRet = sal_True;
+ rAnchor.SetAnchor( &rPos );
+ SwCntntFrm* pTmpFrm = rNd.GetCntntNode()->getLayoutFrm( rDestShell.GetLayout(), &rInsPt, 0, sal_False );
+ SwFlyFrm *pTmpFly = pTmpFrm->FindFlyFrm();
+ if( pTmpFly && bCheckFlyRecur && pFly->IsUpperOf( *pTmpFly ) )
+ {
+ bRet = sal_False;
+ }
+ else if ( FLY_AT_FLY == rAnchor.GetAnchorId() )
+ {
+ if( pTmpFly )
+ {
+ const SwNodeIndex& rIdx = *pTmpFly->GetFmt()->GetCntnt().GetCntntIdx();
+ SwPosition aPos( rIdx );
+ rAnchor.SetAnchor( &aPos );
+ rNewPos = pTmpFly->Frm().Pos();
+ }
+ else
+ {
+ rAnchor.SetType( FLY_AT_PAGE );
+ rAnchor.SetPageNum( rDestShell.GetPageNumber( rInsPt ) );
+ const SwFrm *pPg = pTmpFrm->FindPageFrm();
+ rNewPos = pPg->Frm().Pos();
+ }
+ }
+ else
+ rNewPos = ::lcl_FindBasePos( pTmpFrm, rInsPt );
+ return bRet;
+}
+
+sal_Bool SwFEShell::CopyDrawSel( SwFEShell* pDestShell, const Point& rSttPt,
+ const Point& rInsPt, sal_Bool bIsMove, sal_Bool bSelectInsert )
+{
+ sal_Bool bRet = sal_True;
+
+ //Die Liste muss kopiert werden, weil unten die neuen Objekte
+ //selektiert werden.
+ const SdrMarkList aMrkList( Imp()->GetDrawView()->GetMarkedObjectList() );
+ sal_uLong nMarkCount = aMrkList.GetMarkCount();
+ if( !pDestShell->Imp()->GetDrawView() )
+ // sollte mal eine erzeugt werden
+ pDestShell->MakeDrawView();
+ else if( bSelectInsert )
+ pDestShell->Imp()->GetDrawView()->UnmarkAll();
+
+ SdrPageView *pDestPgView = pDestShell->Imp()->GetPageView(),
+ *pSrcPgView = Imp()->GetPageView();
+ SwDrawView *pDestDrwView = pDestShell->Imp()->GetDrawView(),
+ *pSrcDrwView = Imp()->GetDrawView();
+ SwDoc* pDestDoc = pDestShell->GetDoc();
+
+ Size aSiz( rInsPt.X() - rSttPt.X(), rInsPt.Y() - rSttPt.Y() );
+ for( sal_uInt16 i = 0; i < nMarkCount; ++i )
+ {
+ SdrObject *pObj = aMrkList.GetMark( i )->GetMarkedSdrObj();
+
+ SwDrawContact *pContact = (SwDrawContact*)GetUserCall( pObj );
+ SwFrmFmt *pFmt = pContact->GetFmt();
+ const SwFmtAnchor& rAnchor = pFmt->GetAnchor();
+
+ sal_Bool bInsWithFmt = sal_True;
+
+ if( pDestDrwView->IsGroupEntered() )
+ {
+ // in die Gruppe einfuegen, wenns aus einer betretenen Gruppe
+ // kommt oder das Object nicht zeichengebunden ist
+ if( pSrcDrwView->IsGroupEntered() ||
+ (FLY_AS_CHAR != rAnchor.GetAnchorId()) )
+
+ {
+ SdrObject* pNew = pDestDoc->CloneSdrObj( *pObj, bIsMove &&
+ GetDoc() == pDestDoc, sal_False );
+ pNew->NbcMove( aSiz );
+ pDestDrwView->InsertObjectAtView( pNew, *pDestPgView );
+ bInsWithFmt = sal_False;
+ }
+ }
+
+ if( bInsWithFmt )
+ {
+ SwFmtAnchor aAnchor( rAnchor );
+ Point aNewAnch;
+
+ if ((FLY_AT_PARA == aAnchor.GetAnchorId()) ||
+ (FLY_AT_CHAR == aAnchor.GetAnchorId()) ||
+ (FLY_AT_FLY == aAnchor.GetAnchorId()) ||
+ (FLY_AS_CHAR == aAnchor.GetAnchorId()))
+ {
+ if ( this == pDestShell )
+ {
+ //gleiche Shell? Dann erfrage die Position an der
+ //uebergebenen DokumentPosition
+ SwPosition aPos( *GetCrsr()->GetPoint() );
+ Point aPt( rInsPt );
+ aPt -= rSttPt - pObj->GetSnapRect().TopLeft();
+ SwCrsrMoveState aState( MV_SETONLYTEXT );
+ GetLayout()->GetCrsrOfst( &aPos, aPt, &aState );
+ const SwNode *pNd;
+ if( (pNd = &aPos.nNode.GetNode())->IsNoTxtNode() )
+ bRet = sal_False;
+ else
+ bRet = ::lcl_SetAnchor( aPos, *pNd, 0, rInsPt,
+ *pDestShell, aAnchor, aNewAnch, sal_False );
+ }
+ else
+ {
+ SwPaM *pCrsr = pDestShell->GetCrsr();
+ if( pCrsr->GetNode()->IsNoTxtNode() )
+ bRet = sal_False;
+ else
+ bRet = ::lcl_SetAnchor( *pCrsr->GetPoint(),
+ *pCrsr->GetNode(), 0, rInsPt,
+ *pDestShell, aAnchor,
+ aNewAnch, sal_False );
+ }
+ }
+ else if ( FLY_AT_PAGE == aAnchor.GetAnchorId() )
+ {
+ aAnchor.SetPageNum( pDestShell->GetPageNumber( rInsPt ) );
+ const SwRootFrm* pTmpRoot = pDestShell->GetLayout();
+ const SwFrm* pPg = pTmpRoot->GetPageAtPos( rInsPt, 0, true );
+ if ( pPg )
+ aNewAnch = pPg->Frm().Pos();
+ }
+
+ if( bRet )
+ {
+ if( pSrcDrwView->IsGroupEntered() ||
+ ( !pObj->GetUserCall() && pObj->GetUpGroup()) )
+ {
+ SfxItemSet aSet( pDestDoc->GetAttrPool(),aFrmFmtSetRange);
+ aSet.Put( aAnchor );
+ SdrObject* pNew = pDestDoc->CloneSdrObj( *pObj, bIsMove &&
+ GetDoc() == pDestDoc, sal_True );
+ pFmt = pDestDoc->Insert( *pDestShell->GetCrsr(),
+ *pNew, &aSet, NULL );
+ }
+ else
+ pFmt = pDestDoc->CopyLayoutFmt( *pFmt, aAnchor, true, true );
+
+ //Kann 0 sein, weil Draws in Kopf-/Fusszeilen nicht erlaubt sind.
+ if ( pFmt )
+ {
+ SdrObject* pNew = pFmt->FindSdrObject();
+ if ( FLY_AS_CHAR != aAnchor.GetAnchorId() )
+ {
+ Point aPos( rInsPt );
+ aPos -= aNewAnch;
+ aPos -= rSttPt - pObj->GetSnapRect().TopLeft();
+ // OD 2004-04-05 #i26791# - change attributes instead of
+ // direct positioning
+ pFmt->SetFmtAttr( SwFmtHoriOrient( aPos.X(), text::HoriOrientation::NONE, text::RelOrientation::FRAME ) );
+ pFmt->SetFmtAttr( SwFmtVertOrient( aPos.Y(), text::VertOrientation::NONE, text::RelOrientation::FRAME ) );
+ // --> OD 2005-04-15 #i47455# - notify draw frame format
+ // that position attributes are already set.
+ if ( pFmt->ISA(SwDrawFrmFmt) )
+ {
+ static_cast<SwDrawFrmFmt*>(pFmt)->PosAttrSet();
+ }
+ // <--
+ }
+ if( bSelectInsert )
+ pDestDrwView->MarkObj( pNew, pDestPgView );
+ }
+ }
+ }
+ }
+
+ if ( bIsMove && bRet )
+ {
+ if( pDestShell == this )
+ {
+ const SdrMarkList aList( pSrcDrwView->GetMarkedObjectList() );
+ pSrcDrwView->UnmarkAll();
+
+ sal_uLong nMrkCnt = aMrkList.GetMarkCount();
+ sal_uInt16 i;
+ for ( i = 0; i < nMrkCnt; ++i )
+ {
+ SdrObject *pObj = aMrkList.GetMark( i )->GetMarkedSdrObj();
+ pSrcDrwView->MarkObj( pObj, pSrcPgView );
+ }
+ DelSelectedObj();
+ nMrkCnt = aList.GetMarkCount();
+ for ( i = 0; i < nMrkCnt; ++i )
+ {
+ SdrObject *pObj = aList.GetMark( i )->GetMarkedSdrObj();
+ pSrcDrwView->MarkObj( pObj, pSrcPgView );
+ }
+ }
+ else
+ DelSelectedObj();
+ }
+
+ return bRet;
+}
+
+sal_Bool SwFEShell::Copy( SwFEShell* pDestShell, const Point& rSttPt,
+ const Point& rInsPt, sal_Bool bIsMove, sal_Bool bSelectInsert )
+{
+ sal_Bool bRet = sal_False;
+
+ OSL_ENSURE( pDestShell, "Copy ohne DestShell." );
+ OSL_ENSURE( this == pDestShell || !pDestShell->IsObjSelected(),
+ "Dest-Shell darf nie im Obj-Modus sein" );
+
+ SET_CURR_SHELL( pDestShell );
+
+ pDestShell->StartAllAction();
+ pDestShell->GetDoc()->LockExpFlds();
+
+ // Referenzen sollen verschoben werden.
+ sal_Bool bCopyIsMove = pDoc->IsCopyIsMove();
+ if( bIsMove )
+ // am Doc ein Flag setzen, damit in den TextNodes
+ pDoc->SetCopyIsMove( sal_True );
+
+ RedlineMode_t eOldRedlMode = pDestShell->GetDoc()->GetRedlineMode();
+ pDestShell->GetDoc()->SetRedlineMode_intern( (RedlineMode_t)(eOldRedlMode | nsRedlineMode_t::REDLINE_DELETE_REDLINES));
+
+ // sind Tabellen-Formeln im Bereich, dann muss erst die Tabelle
+ // angezeigt werden, damit die Tabellen-Formel den neuen Wert errechnen
+ // kann (bei Bereichen wird sich ueber das Layout die einzelnen Boxen
+ // besorgt)
+ SwFieldType* pTblFldTyp = pDestShell->GetDoc()->GetSysFldType( RES_TABLEFLD );
+
+ if( IsFrmSelected() )
+ {
+ SwFlyFrm* pFly = FindFlyFrm();
+ SwFrmFmt* pFlyFmt = pFly->GetFmt();
+ SwFmtAnchor aAnchor( pFlyFmt->GetAnchor() );
+ bRet = sal_True;
+ Point aNewAnch;
+
+ if ((FLY_AT_PARA == aAnchor.GetAnchorId()) ||
+ (FLY_AT_CHAR == aAnchor.GetAnchorId()) ||
+ (FLY_AT_FLY == aAnchor.GetAnchorId()) ||
+ (FLY_AS_CHAR == aAnchor.GetAnchorId()))
+ {
+ if ( this == pDestShell )
+ {
+ // gleiche Shell? Dann erfrage die Position an der
+ // uebergebenen DokumentPosition
+ SwPosition aPos( *GetCrsr()->GetPoint() );
+ Point aPt( rInsPt );
+ aPt -= rSttPt - pFly->Frm().Pos();
+ SwCrsrMoveState aState( MV_SETONLYTEXT );
+ GetLayout()->GetCrsrOfst( &aPos, aPt, &aState );
+ const SwNode *pNd;
+ if( (pNd = &aPos.nNode.GetNode())->IsNoTxtNode() )
+ bRet = sal_False;
+ else
+ { //Nicht in sich selbst kopieren
+ const SwNodeIndex *pTmp = pFlyFmt->GetCntnt().GetCntntIdx();
+ if ( aPos.nNode > *pTmp && aPos.nNode <
+ pTmp->GetNode().EndOfSectionIndex() )
+ {
+ bRet = sal_False;
+ }
+ else
+ bRet = ::lcl_SetAnchor( aPos, *pNd, pFly, rInsPt,
+ *pDestShell, aAnchor, aNewAnch, sal_True );
+ }
+ }
+ else
+ {
+ const SwPaM *pCrsr = pDestShell->GetCrsr();
+ if( pCrsr->GetNode()->IsNoTxtNode() )
+ bRet = sal_False;
+ else
+ bRet = ::lcl_SetAnchor( *pCrsr->GetPoint(), *pCrsr->GetNode(),
+ pFly, rInsPt, *pDestShell, aAnchor,
+ aNewAnch, GetDoc() == pDestShell->GetDoc());
+ }
+ }
+ else if ( FLY_AT_PAGE == aAnchor.GetAnchorId() )
+ {
+ aAnchor.SetPageNum( pDestShell->GetPageNumber( rInsPt ) );
+ const SwRootFrm* pTmpRoot = pDestShell->GetLayout();
+ const SwFrm* pPg = pTmpRoot->GetPageAtPos( rInsPt, 0, true );
+ if ( pPg )
+ aNewAnch = pPg->Frm().Pos();
+ }
+ else {
+ OSL_ENSURE( !this, "was fuer ein Anchor ist es denn?" );
+ }
+
+ if( bRet )
+ {
+ SwFrmFmt *pOldFmt = pFlyFmt;
+ pFlyFmt = pDestShell->GetDoc()->CopyLayoutFmt( *pFlyFmt, aAnchor, true, true );
+
+ if ( FLY_AS_CHAR != aAnchor.GetAnchorId() )
+ {
+ Point aPos( rInsPt );
+ aPos -= aNewAnch;
+ aPos -= rSttPt - pFly->Frm().Pos();
+ pFlyFmt->SetFmtAttr( SwFmtHoriOrient( aPos.X(),text::HoriOrientation::NONE, text::RelOrientation::FRAME ) );
+ pFlyFmt->SetFmtAttr( SwFmtVertOrient( aPos.Y(),text::VertOrientation::NONE, text::RelOrientation::FRAME ) );
+ }
+
+ const Point aPt( pDestShell->GetCrsrDocPos() );
+
+ if( bIsMove )
+ GetDoc()->DelLayoutFmt( pOldFmt );
+
+ // nur selektieren wenn es in der gleichen Shell verschoben/
+ // kopiert wird
+ if( bSelectInsert )
+ {
+ SwFlyFrm* pFlyFrm = ((SwFlyFrmFmt*)pFlyFmt)->GetFrm( &aPt, sal_False );
+ if( pFlyFrm )
+ {
+ //JP 12.05.98: sollte das nicht im SelectFlyFrm stehen???
+ pDestShell->Imp()->GetDrawView()->UnmarkAll();
+ pDestShell->SelectFlyFrm( *pFlyFrm, sal_True );
+ }
+ }
+
+ if( this != pDestShell && !pDestShell->HasShFcs() )
+ pDestShell->Imp()->GetDrawView()->hideMarkHandles();
+ }
+ }
+ else if ( IsObjSelected() )
+ bRet = CopyDrawSel( pDestShell, rSttPt, rInsPt, bIsMove, bSelectInsert );
+ else if( IsTableMode() )
+ {
+ // kopiere Teile aus einer Tabelle: lege eine Tabelle mit der Breite
+ // von der Originalen an und kopiere die selectierten Boxen.
+ // Die Groessen werden prozentual korrigiert.
+
+ // lasse ueber das Layout die Boxen suchen
+ const SwTableNode* pTblNd;
+ SwSelBoxes aBoxes;
+ GetTblSel( *this, aBoxes );
+ if( aBoxes.Count() &&
+ 0 != (pTblNd = aBoxes[0]->GetSttNd()->FindTableNode()) )
+ {
+ SwPosition* pDstPos = 0;
+ if( this == pDestShell )
+ {
+ // gleiche Shell? Dann erzeuge einen Crsr an der
+ // uebergebenen DokumentPosition
+ pDstPos = new SwPosition( *GetCrsr()->GetPoint() );
+ Point aPt( rInsPt );
+ GetLayout()->GetCrsrOfst( pDstPos, aPt );
+ if( !pDstPos->nNode.GetNode().IsNoTxtNode() )
+ bRet = sal_True;
+ }
+ else if( !pDestShell->GetCrsr()->GetNode()->IsNoTxtNode() )
+ {
+ pDstPos = new SwPosition( *pDestShell->GetCrsr()->GetPoint() );
+ bRet = sal_True;
+ }
+
+ if( bRet )
+ {
+ if( GetDoc() == pDestShell->GetDoc() )
+ ParkTblCrsr();
+
+ bRet = pDestShell->GetDoc()->InsCopyOfTbl( *pDstPos, aBoxes,0,
+ bIsMove && this == pDestShell &&
+ aBoxes.Count() == pTblNd->GetTable().
+ GetTabSortBoxes().Count(),
+ this != pDestShell );
+
+ if( this != pDestShell )
+ *pDestShell->GetCrsr()->GetPoint() = *pDstPos;
+
+ // wieder alle geparkten Crsr erzeugen?
+ if( GetDoc() == pDestShell->GetDoc() )
+ GetCrsr();
+
+ // JP 16.04.99: Bug 64908 - InsPos setzen, damit der geparkte
+ // Cursor auf die EinfuegePos. positioniert wird
+ if( this == pDestShell )
+ GetCrsrDocPos() = rInsPt;
+ }
+ delete pDstPos;
+ }
+ }
+ else
+ {
+ bRet = sal_True;
+ if( this == pDestShell )
+ {
+ // gleiche Shell? Dann erfrage die Position an der
+ // uebergebenen DokumentPosition
+ SwPosition aPos( *GetCrsr()->GetPoint() );
+ Point aPt( rInsPt );
+ GetLayout()->GetCrsrOfst( &aPos, aPt );
+ bRet = !aPos.nNode.GetNode().IsNoTxtNode();
+ }
+ else if( pDestShell->GetCrsr()->GetNode()->IsNoTxtNode() )
+ bRet = sal_False;
+
+ if( bRet )
+ bRet = 0 != SwEditShell::Copy( pDestShell );
+ }
+
+ pDestShell->GetDoc()->SetRedlineMode_intern( eOldRedlMode );
+ pDoc->SetCopyIsMove( bCopyIsMove );
+
+ // wurden neue Tabellenformeln eingefuegt ?
+ if( pTblFldTyp->GetDepends() )
+ {
+ // alte Actions beenden; die Tabellen-Frames werden angelegt und
+ // eine SSelection kann erzeugt werden
+ sal_uInt16 nActCnt;
+ for( nActCnt = 0; pDestShell->ActionPend(); ++nActCnt )
+ pDestShell->EndAllAction();
+
+ for( ; nActCnt; --nActCnt )
+ pDestShell->StartAllAction();
+ }
+ pDestShell->GetDoc()->UnlockExpFlds();
+ pDestShell->GetDoc()->UpdateFlds(NULL, false);
+
+ pDestShell->EndAllAction();
+ return bRet;
+}
+
+/*************************************************************************
+|*
+|* SwFEShell::Paste() Paste fuer das Interne Clipboard.
+|* Kopiert den Inhalt vom Clipboard in das Dokument.
+|*
+|*************************************************************************/
+
+namespace {
+ typedef boost::shared_ptr<SwPaM> PaMPtr;
+ typedef boost::shared_ptr<SwPosition> PositionPtr;
+ typedef std::pair< PaMPtr, PositionPtr > Insertion;
+}
+
+sal_Bool SwFEShell::Paste( SwDoc* pClpDoc, sal_Bool bIncludingPageFrames )
+{
+ SET_CURR_SHELL( this );
+ OSL_ENSURE( pClpDoc, "kein Clipboard-Dokument" );
+ const sal_uInt16 nStartPageNumber = GetPhyPageNum();
+ // dann bis zum Ende vom Nodes Array
+ SwNodeIndex aIdx( pClpDoc->GetNodes().GetEndOfExtras(), 2 );
+ SwPaM aCpyPam( aIdx ); //DocStart
+
+ // sind Tabellen-Formeln im Bereich, dann muss erst die Tabelle
+ // angezeigt werden, damit die Tabellen-Formel den neuen Wert errechnen
+ // kann (bei Bereichen wird sich ueber das Layout die einzelnen Boxen
+ // besorgt)
+ SwFieldType* pTblFldTyp = GetDoc()->GetSysFldType( RES_TABLEFLD );
+
+ SwTableNode *pDestNd, *pSrcNd = aCpyPam.GetNode()->GetTableNode();
+ if( !pSrcNd ) // TabellenNode ?
+ { // nicht ueberspringen!!
+ SwCntntNode* pCNd = aCpyPam.GetNode()->GetCntntNode();
+ if( pCNd )
+ aCpyPam.GetPoint()->nContent.Assign( pCNd, 0 );
+ else if( !aCpyPam.Move( fnMoveForward, fnGoNode ))
+ aCpyPam.Move( fnMoveBackward, fnGoNode );
+ }
+
+ aCpyPam.SetMark();
+ aCpyPam.Move( fnMoveForward, fnGoDoc );
+
+ sal_Bool bRet = sal_True, bDelTbl = sal_True;
+ StartAllAction();
+ GetDoc()->GetIDocumentUndoRedo().StartUndo( UNDO_INSGLOSSARY, NULL );
+ GetDoc()->LockExpFlds();
+
+ // When the clipboard content has been created by a rectangular selection
+ // the pasting is more sophisticated:
+ // every paragraph will be inserted into another position.
+ // The first positions are given by the actual cursor ring,
+ // if there are more text portions to insert than cursor in this ring,
+ // the additional insert positions will be created by moving the last
+ // cursor position into the next line (like pressing the cursor down key)
+ if( pClpDoc->IsColumnSelection() && !IsTableMode() )
+ {
+ // Creation of the list of insert positions
+ std::list< Insertion > aCopyList;
+ // The number of text portions of the rectangular selection
+ const sal_uInt32 nSelCount = aCpyPam.GetPoint()->nNode.GetIndex()
+ - aCpyPam.GetMark()->nNode.GetIndex();
+ sal_uInt32 nCount = nSelCount;
+ SwNodeIndex aClpIdx( aIdx );
+ SwPaM* pStartCursor = GetCrsr();
+ SwPaM* pCurrCrsr = pStartCursor;
+ sal_uInt32 nCursorCount = pStartCursor->numberOf();
+ // If the target selection is a multi-selection, often the last and first
+ // cursor of the ring points to identical document positions. Then
+ // we should avoid double insertion of text portions...
+ while( nCursorCount > 1 && *pCurrCrsr->GetPoint() ==
+ *(dynamic_cast<SwPaM*>(pCurrCrsr->GetPrev())->GetPoint()) )
+ {
+ --nCursorCount;
+ pCurrCrsr = dynamic_cast<SwPaM*>(pCurrCrsr->GetNext());
+ pStartCursor = pCurrCrsr;
+ }
+ SwPosition aStartPos( *pStartCursor->GetPoint() );
+ SwPosition aInsertPos( aStartPos ); // first insertion position
+ bool bCompletePara = false;
+ sal_uInt16 nMove = 0;
+ while( nCount )
+ {
+ --nCount;
+ OSL_ENSURE( aIdx.GetNode().GetCntntNode(), "Who filled the clipboard?!" );
+ if( aIdx.GetNode().GetCntntNode() ) // robust
+ {
+ Insertion aInsertion( PaMPtr( new SwPaM( aIdx ) ),
+ PositionPtr( new SwPosition( aInsertPos ) ) );
+ ++aIdx;
+ aInsertion.first->SetMark();
+ if( pStartCursor == pCurrCrsr->GetNext() )
+ { // Now we have to look for insertion positions...
+ if( !nMove ) // Annotate the last given insert position
+ aStartPos = aInsertPos;
+ SwCursor aCrsr( aStartPos, 0, false);
+ // Check if we find another insert position by moving
+ // down the last given position
+ if( aCrsr.UpDown( sal_False, ++nMove, 0, 0 ) )
+ aInsertPos = *aCrsr.GetPoint();
+ else // if there is no paragraph we have to create it
+ bCompletePara = nCount > 0;
+ nCursorCount = 0;
+ }
+ else // as long as we find more insert positions in the cursor ring
+ { // we'll take them
+ pCurrCrsr = dynamic_cast<SwPaM*>(pCurrCrsr->GetNext());
+ aInsertPos = *pCurrCrsr->GetPoint();
+ --nCursorCount;
+ }
+ // If there are no more paragraphs e.g. at the end of a document,
+ // we insert complete paragraphs instead of text portions
+ if( bCompletePara )
+ aInsertion.first->GetPoint()->nNode = aIdx;
+ else
+ aInsertion.first->GetPoint()->nContent =
+ aInsertion.first->GetCntntNode()->Len();
+ aCopyList.push_back( aInsertion );
+ }
+ // If there are no text portions left but there are some more
+ // cursor positions to fill we have to restart with the first
+ // text portion
+ if( !nCount && nCursorCount )
+ {
+ nCount = std::min( nSelCount, nCursorCount );
+ aIdx = aClpIdx; // Start of clipboard content
+ }
+ }
+ std::list< Insertion >::const_iterator pCurr = aCopyList.begin();
+ std::list< Insertion >::const_iterator pEnd = aCopyList.end();
+ while( pCurr != pEnd )
+ {
+ SwPosition& rInsPos = *pCurr->second;
+ SwPaM& rCopy = *pCurr->first;
+ const SwStartNode* pBoxNd = rInsPos.nNode.GetNode().FindTableBoxStartNode();
+ if( pBoxNd && 2 == pBoxNd->EndOfSectionIndex() - pBoxNd->GetIndex() &&
+ rCopy.GetPoint()->nNode != rCopy.GetMark()->nNode )
+ {
+ // if more than one node will be copied into a cell
+ // the box attributes have to be removed
+ GetDoc()->ClearBoxNumAttrs( rInsPos.nNode );
+ }
+ {
+ SwNodeIndex aIndexBefore(rInsPos.nNode);
+ aIndexBefore--;
+ pClpDoc->CopyRange( rCopy, rInsPos, false );
+ {
+ aIndexBefore++;
+ SwPaM aPaM(SwPosition(aIndexBefore),
+ SwPosition(rInsPos.nNode));
+ aPaM.GetDoc()->MakeUniqueNumRules(aPaM);
+ }
+ }
+ SaveTblBoxCntnt( &rInsPos );
+ ++pCurr;
+ }
+ }
+ else
+ {
+ FOREACHPAM_START(this)
+
+ if( pSrcNd &&
+ 0 != ( pDestNd = GetDoc()->IsIdxInTbl( PCURCRSR->GetPoint()->nNode )))
+ {
+ SwPosition aDestPos( *PCURCRSR->GetPoint() );
+
+ sal_Bool bParkTblCrsr = sal_False;
+ const SwStartNode* pSttNd = PCURCRSR->GetNode()->FindTableBoxStartNode();
+
+ // TABLE IN TABLE: Tabelle in Tabelle kopieren
+ // lasse ueber das Layout die Boxen suchen
+ SwSelBoxes aBoxes;
+ if( IsTableMode() ) // Tabellen-Selecktion ??
+ {
+ GetTblSel( *this, aBoxes );
+ ParkTblCrsr();
+ bParkTblCrsr = sal_True;
+ }
+ else if( !PCURCRSR->HasMark() && PCURCRSR->GetNext() == PCURCRSR &&
+ ( !pSrcNd->GetTable().IsTblComplex() ||
+ pDestNd->GetTable().IsNewModel() ) )
+ {
+ // dann die Tabelle "relativ" kopieren
+ SwTableBox* pBox = pDestNd->GetTable().GetTblBox(
+ pSttNd->GetIndex() );
+ OSL_ENSURE( pBox, "Box steht nicht in dieser Tabelle" );
+ aBoxes.Insert( pBox );
+ }
+
+ SwNodeIndex aNdIdx( *pDestNd->EndOfSectionNode());
+ if( !bParkTblCrsr )
+ {
+ // erstmal aus der gesamten Tabelle raus
+// ????? was ist mit Tabelle alleine im Rahmen ???????
+ SwCntntNode* pCNd = GetDoc()->GetNodes().GoNext( &aNdIdx );
+ SwPosition aPos( aNdIdx, SwIndex( pCNd, 0 ));
+ // #i59539: Don't remove all redline
+ SwPaM const tmpPaM(*pDestNd, *pDestNd->EndOfSectionNode());
+ ::PaMCorrAbs(tmpPaM, aPos);
+ }
+
+ bRet = GetDoc()->InsCopyOfTbl( aDestPos, aBoxes, &pSrcNd->GetTable(),
+ sal_False, sal_False );
+
+ if( bParkTblCrsr )
+ GetCrsr();
+ else
+ {
+ // und wieder in die Box zurueck
+ aNdIdx = *pSttNd;
+ SwCntntNode* pCNd = GetDoc()->GetNodes().GoNext( &aNdIdx );
+ SwPosition aPos( aNdIdx, SwIndex( pCNd, 0 ));
+ // #i59539: Don't remove all redline
+ SwNode & rNode(PCURCRSR->GetPoint()->nNode.GetNode());
+ SwCntntNode *const pCntntNode( rNode.GetCntntNode() );
+ SwPaM const tmpPam(rNode, 0,
+ rNode, (pCntntNode) ? pCntntNode->Len() : 0);
+ ::PaMCorrAbs(tmpPam, aPos);
+ }
+
+ break; // aus der "while"-Schleife heraus
+ }
+ else if( *aCpyPam.GetPoint() == *aCpyPam.GetMark() &&
+ pClpDoc->GetSpzFrmFmts()->Count() )
+ {
+ // so langsam sollte mal eine DrawView erzeugt werden
+ if( !Imp()->GetDrawView() )
+ MakeDrawView();
+
+ for ( sal_uInt16 i = 0; i < pClpDoc->GetSpzFrmFmts()->Count(); ++i )
+ {
+ sal_Bool bInsWithFmt = sal_True;
+ const SwFrmFmt& rCpyFmt = *(*pClpDoc->GetSpzFrmFmts())[i];
+
+ if( Imp()->GetDrawView()->IsGroupEntered() &&
+ RES_DRAWFRMFMT == rCpyFmt.Which() &&
+ (FLY_AS_CHAR != rCpyFmt.GetAnchor().GetAnchorId()) )
+ {
+ const SdrObject* pSdrObj = rCpyFmt.FindSdrObject();
+ if( pSdrObj )
+ {
+ SdrObject* pNew = GetDoc()->CloneSdrObj( *pSdrObj,
+ sal_False, sal_False );
+
+ // Insert object sets any anchor position to 0.
+ // Therefore we calculate the absolute position here
+ // and after the insert the anchor of the object
+ // is set to the anchor of the group object.
+ Rectangle aSnapRect = pNew->GetSnapRect();
+ if( pNew->GetAnchorPos().X() || pNew->GetAnchorPos().Y() )
+ {
+ const Point aPoint( 0, 0 );
+ // OD 2004-04-05 #i26791# - direct drawing object
+ // positioning for group members
+ pNew->NbcSetAnchorPos( aPoint );
+ pNew->NbcSetSnapRect( aSnapRect );
+ }
+
+ Imp()->GetDrawView()->InsertObjectAtView( pNew, *Imp()->GetPageView() );
+
+ Point aGrpAnchor( 0, 0 );
+ SdrObjList* pList = pNew->GetObjList();
+ if ( pList )
+ {
+ SdrObject* pOwner = pList->GetOwnerObj();
+ if ( pOwner )
+ {
+ SdrObjGroup* pThisGroup = PTR_CAST(SdrObjGroup, pOwner);
+ aGrpAnchor = pThisGroup->GetAnchorPos();
+ }
+ }
+
+ // OD 2004-04-05 #i26791# - direct drawing object
+ // positioning for group members
+ pNew->NbcSetAnchorPos( aGrpAnchor );
+ pNew->SetSnapRect( aSnapRect );
+
+ bInsWithFmt = sal_False;
+ }
+ }
+
+ if( bInsWithFmt )
+ {
+ SwFmtAnchor aAnchor( rCpyFmt.GetAnchor() );
+ if ((FLY_AT_PARA == aAnchor.GetAnchorId()) ||
+ (FLY_AT_CHAR == aAnchor.GetAnchorId()) ||
+ (FLY_AS_CHAR == aAnchor.GetAnchorId()))
+ {
+ SwPosition* pPos = PCURCRSR->GetPoint();
+ // allow shapes (no controls) in header/footer
+ if( RES_DRAWFRMFMT == rCpyFmt.Which() &&
+ GetDoc()->IsInHeaderFooter( pPos->nNode ) &&
+ CheckControlLayer( rCpyFmt.FindSdrObject() ) )
+ continue;
+
+ aAnchor.SetAnchor( pPos );
+ }
+ else if ( FLY_AT_PAGE == aAnchor.GetAnchorId() )
+ {
+ aAnchor.SetPageNum( GetPhyPageNum() );
+ }
+ else if( FLY_AT_FLY == aAnchor.GetAnchorId() )
+ {
+ Point aPt;
+ lcl_SetAnchor( *PCURCRSR->GetPoint(), *PCURCRSR->GetNode(),
+ 0, aPt, *this, aAnchor, aPt, sal_False );
+ }
+
+ SwFrmFmt * pNew = GetDoc()->CopyLayoutFmt( rCpyFmt, aAnchor, true, true );
+
+ if( pNew )
+ {
+ if( RES_FLYFRMFMT == pNew->Which() )
+ {
+ const Point aPt( GetCrsrDocPos() );
+ SwFlyFrm* pFlyFrm = ((SwFlyFrmFmt*)pNew)->
+ GetFrm( &aPt, sal_False );
+ if( pFlyFrm )
+ SelectFlyFrm( *pFlyFrm, sal_True );
+ // immer nur den ersten Fly-Frame nehmen; die anderen
+ // wurden ueber Fly in Fly ins ClipBoard kopiert !
+ break;
+ }
+ else
+ {
+ OSL_ENSURE( RES_DRAWFRMFMT == pNew->Which(), "Neues Format.");
+ // --> OD 2005-09-01 #i52780# - drawing object has
+ // to be made visible on paste.
+ {
+ SwDrawContact* pContact =
+ static_cast<SwDrawContact*>(pNew->FindContactObj());
+ pContact->MoveObjToVisibleLayer( pContact->GetMaster() );
+ }
+ // <--
+ SdrObject *pObj = pNew->FindSdrObject();
+ SwDrawView *pDV = Imp()->GetDrawView();
+ pDV->MarkObj( pObj, pDV->GetSdrPageView() );
+ // --> OD 2005-04-15 #i47455# - notify draw frame format
+ // that position attributes are already set.
+ if ( pNew->ISA(SwDrawFrmFmt) )
+ {
+ static_cast<SwDrawFrmFmt*>(pNew)->PosAttrSet();
+ }
+ // <--
+ }
+ }
+ }
+ }
+ }
+ else
+ {
+ if( bDelTbl && IsTableMode() )
+ {
+ SwEditShell::Delete();
+ bDelTbl = sal_False;
+ }
+
+ SwPosition& rInsPos = *PCURCRSR->GetPoint();
+ const SwStartNode* pBoxNd = rInsPos.nNode.GetNode().
+ FindTableBoxStartNode();
+ if( pBoxNd && 2 == pBoxNd->EndOfSectionIndex() -
+ pBoxNd->GetIndex() &&
+ aCpyPam.GetPoint()->nNode != aCpyPam.GetMark()->nNode )
+ {
+ // es wird mehr als 1 Node in die akt. Box kopiert. Dann
+ // muessen die BoxAttribute aber entfernt werden.
+ GetDoc()->ClearBoxNumAttrs( rInsPos.nNode );
+ }
+ //find out if the clipboard document starts with a table
+ bool bStartWithTable = 0 != aCpyPam.Start()->nNode.GetNode().FindTableNode();
+ SwPosition aInsertPosition( rInsPos );
+
+ {
+ SwNodeIndex aIndexBefore(rInsPos.nNode);
+
+ aIndexBefore--;
+
+ pClpDoc->CopyRange( aCpyPam, rInsPos, false );
+
+ {
+ aIndexBefore++;
+ SwPaM aPaM(SwPosition(aIndexBefore),
+ SwPosition(rInsPos.nNode));
+
+ aPaM.GetDoc()->MakeUniqueNumRules(aPaM);
+ }
+ }
+
+ SaveTblBoxCntnt( &rInsPos );
+ if(bIncludingPageFrames && bStartWithTable)
+ {
+ //remove the paragraph in front of the table
+ SwPaM aPara(aInsertPosition);
+ GetDoc()->DelFullPara(aPara);
+ }
+ //additionally copy page bound frames
+ if( bIncludingPageFrames && pClpDoc->GetSpzFrmFmts()->Count() )
+ {
+ // create a draw view if necessary
+ if( !Imp()->GetDrawView() )
+ MakeDrawView();
+
+ for ( sal_uInt16 i = 0; i < pClpDoc->GetSpzFrmFmts()->Count(); ++i )
+ {
+ sal_Bool bInsWithFmt = sal_True;
+ const SwFrmFmt& rCpyFmt = *(*pClpDoc->GetSpzFrmFmts())[i];
+ if( bInsWithFmt )
+ {
+ SwFmtAnchor aAnchor( rCpyFmt.GetAnchor() );
+ if ( FLY_AT_PAGE == aAnchor.GetAnchorId() )
+ {
+ aAnchor.SetPageNum( aAnchor.GetPageNum() + nStartPageNumber - 1 );
+ }
+ else
+ continue;
+ GetDoc()->CopyLayoutFmt( rCpyFmt, aAnchor, true, true );
+ }
+ }
+ }
+ }
+
+ FOREACHPAM_END()
+ }
+
+ GetDoc()->GetIDocumentUndoRedo().EndUndo( UNDO_INSGLOSSARY, NULL );
+
+ // wurden neue Tabellenformeln eingefuegt ?
+ if( pTblFldTyp->GetDepends() )
+ {
+ // alte Actions beenden; die Tabellen-Frames werden angelegt und
+ // eine Selection kann erzeugt werden
+ sal_uInt16 nActCnt;
+ for( nActCnt = 0; ActionPend(); ++nActCnt )
+ EndAllAction();
+
+ for( ; nActCnt; --nActCnt )
+ StartAllAction();
+ }
+ GetDoc()->UnlockExpFlds();
+ GetDoc()->UpdateFlds(NULL, false);
+ EndAllAction();
+
+ return bRet;
+}
+
+sal_Bool SwFEShell::PastePages( SwFEShell& rToFill, sal_uInt16 nStartPage, sal_uInt16 nEndPage)
+{
+ Push();
+ if(!GotoPage(nStartPage))
+ {
+ Pop(sal_False);
+ return sal_False;
+ }
+ MovePage( fnPageCurr, fnPageStart );
+ SwPaM aCpyPam( *GetCrsr()->GetPoint() );
+ String sStartingPageDesc = GetPageDesc( GetCurPageDesc()).GetName();
+ SwPageDesc* pDesc = rToFill.FindPageDescByName( sStartingPageDesc, sal_True );
+ if( pDesc )
+ rToFill.ChgCurPageDesc( *pDesc );
+
+ if(!GotoPage(nEndPage))
+ {
+ Pop(sal_False);
+ return sal_False;
+ }
+ //if the page starts with a table a paragraph has to be inserted before
+ SwNode* pTableNode = aCpyPam.GetNode()->FindTableNode();
+ if(pTableNode)
+ {
+ //insert a paragraph
+ StartUndo(UNDO_INSERT);
+ SwNodeIndex aTblIdx( *pTableNode, -1 );
+ SwPosition aBefore(aTblIdx);
+ if(GetDoc()->AppendTxtNode( aBefore ))
+ {
+ SwPaM aTmp(aBefore);
+ aCpyPam = aTmp;
+ }
+ EndUndo(UNDO_INSERT);
+ }
+
+ MovePage( fnPageCurr, fnPageEnd );
+ aCpyPam.SetMark();
+ *aCpyPam.GetMark() = *GetCrsr()->GetPoint();
+
+ SET_CURR_SHELL( this );
+
+ StartAllAction();
+ GetDoc()->LockExpFlds();
+ SetSelection(aCpyPam);
+ // copy the text of the selection
+ SwEditShell::Copy(&rToFill);
+
+ if(pTableNode)
+ {
+ //remove the inserted paragraph
+ Undo();
+ //remove the paragraph in the second doc, too
+ SwNodeIndex aIdx( rToFill.GetDoc()->GetNodes().GetEndOfExtras(), 2 );
+ SwPaM aPara( aIdx ); //DocStart
+ rToFill.GetDoc()->DelFullPara(aPara);
+ }
+ // now the page bound objects
+ //additionally copy page bound frames
+ if( GetDoc()->GetSpzFrmFmts()->Count() )
+ {
+ // create a draw view if necessary
+ if( !rToFill.Imp()->GetDrawView() )
+ rToFill.MakeDrawView();
+
+ for ( sal_uInt16 i = 0; i < GetDoc()->GetSpzFrmFmts()->Count(); ++i )
+ {
+ const SwFrmFmt& rCpyFmt = *(*GetDoc()->GetSpzFrmFmts())[i];
+ SwFmtAnchor aAnchor( rCpyFmt.GetAnchor() );
+ if ((FLY_AT_PAGE == aAnchor.GetAnchorId()) &&
+ aAnchor.GetPageNum() >= nStartPage && aAnchor.GetPageNum() <= nEndPage)
+ {
+ aAnchor.SetPageNum( aAnchor.GetPageNum() - nStartPage + 1);
+ }
+ else
+ continue;
+ rToFill.GetDoc()->CopyLayoutFmt( rCpyFmt, aAnchor, true, true );
+ }
+ }
+ GetDoc()->UnlockExpFlds();
+ GetDoc()->UpdateFlds(NULL, false);
+ Pop(sal_False);
+ EndAllAction();
+
+ return sal_True;
+}
+
+sal_Bool SwFEShell::GetDrawObjGraphic( sal_uLong nFmt, Graphic& rGrf ) const
+{
+ OSL_ENSURE( Imp()->HasDrawView(), "GetDrawObjGraphic without DrawView?" );
+ const SdrMarkList &rMrkList = Imp()->GetDrawView()->GetMarkedObjectList();
+ sal_Bool bConvert = sal_True;
+ if( rMrkList.GetMarkCount() )
+ {
+ if( rMrkList.GetMarkCount() == 1 &&
+ rMrkList.GetMark( 0 )->GetMarkedSdrObj()->ISA(SwVirtFlyDrawObj) )
+ {
+ // Rahmen selektiert
+ if( CNT_GRF == GetCntType() )
+ {
+ const Graphic* pGrf( GetGraphic() );
+ if ( pGrf )
+ {
+ Graphic aGrf( *pGrf );
+ if( SOT_FORMAT_GDIMETAFILE == nFmt )
+ {
+ if( GRAPHIC_BITMAP != aGrf.GetType() )
+ {
+ rGrf = aGrf;
+ bConvert = sal_False;
+ }
+ else if( GetWin() )
+ {
+ Size aSz;
+ Point aPt;
+ GetGrfSize( aSz );
+
+ VirtualDevice aVirtDev;
+ aVirtDev.EnableOutput( sal_False );
+
+ MapMode aTmp( GetWin()->GetMapMode() );
+ aTmp.SetOrigin( aPt );
+ aVirtDev.SetMapMode( aTmp );
+
+ GDIMetaFile aMtf;
+ aMtf.Record( &aVirtDev );
+ aGrf.Draw( &aVirtDev, aPt, aSz );
+ aMtf.Stop();
+ aMtf.SetPrefMapMode( aTmp );
+ aMtf.SetPrefSize( aSz );
+ rGrf = aMtf;
+ }
+ }
+ else if( GRAPHIC_BITMAP == aGrf.GetType() )
+ {
+ rGrf = aGrf;
+ bConvert = sal_False;
+ }
+ else
+ {
+ //fix(23806): Nicht die Originalgroesse, sondern die
+ //aktuelle. Anderfalls kann es passieren, dass z.B. bei
+ //Vektorgrafiken mal eben zig MB angefordert werden.
+ const Size aSz( FindFlyFrm()->Prt().SSize() );
+ VirtualDevice aVirtDev( *GetWin() );
+
+ MapMode aTmp( MAP_TWIP );
+ aVirtDev.SetMapMode( aTmp );
+ if( aVirtDev.SetOutputSize( aSz ) )
+ {
+ aGrf.Draw( &aVirtDev, Point(), aSz );
+ rGrf = aVirtDev.GetBitmap( Point(), aSz );
+ }
+ else
+ {
+ rGrf = aGrf;
+ bConvert = sal_False;
+ }
+ }
+ }
+ }
+ }
+ else if( SOT_FORMAT_GDIMETAFILE == nFmt )
+ rGrf = Imp()->GetDrawView()->GetAllMarkedMetaFile();
+ else if( SOT_FORMAT_BITMAP == nFmt )
+ rGrf = Imp()->GetDrawView()->GetAllMarkedBitmap();
+ }
+ return bConvert;
+}
+
+// --> OD 2005-08-03 #i50824#
+// replace method <lcl_RemoveOleObjsFromSdrModel> by <lcl_ConvertSdrOle2ObjsToSdrGrafObjs>
+void lcl_ConvertSdrOle2ObjsToSdrGrafObjs( SdrModel* _pModel )
+{
+ for ( sal_uInt16 nPgNum = 0; nPgNum < _pModel->GetPageCount(); ++nPgNum )
+ {
+ // setup object iterator in order to iterate through all objects
+ // including objects in group objects, but exclusive group objects.
+ SdrObjListIter aIter(*(_pModel->GetPage( nPgNum )));
+ while( aIter.IsMore() )
+ {
+ SdrOle2Obj* pOle2Obj = dynamic_cast< SdrOle2Obj* >( aIter.Next() );
+ if( pOle2Obj )
+ {
+ // found an ole2 shape
+ SdrObjList* pObjList = pOle2Obj->GetObjList();
+
+ // get its graphic
+ Graphic aGraphic;
+ pOle2Obj->Connect();
+ Graphic* pGraphic = pOle2Obj->GetGraphic();
+ if( pGraphic )
+ aGraphic = *pGraphic;
+ pOle2Obj->Disconnect();
+
+ // create new graphic shape with the ole graphic and shape size
+ SdrGrafObj* pGraphicObj = new SdrGrafObj( aGraphic, pOle2Obj->GetCurrentBoundRect() );
+ // apply layer of ole2 shape at graphic shape
+ pGraphicObj->SetLayer( pOle2Obj->GetLayer() );
+
+ // replace ole2 shape with the new graphic object and delete the ol2 shape
+ SdrObject* pRemovedObject = pObjList->ReplaceObject( pGraphicObj, pOle2Obj->GetOrdNum() );
+ SdrObject::Free( pRemovedObject );
+ }
+ }
+ }
+}
+
+void SwFEShell::Paste( SvStream& rStrm, sal_uInt16 nAction, const Point* pPt )
+{
+ SET_CURR_SHELL( this );
+ StartAllAction();
+ StartUndo();
+
+ SvtPathOptions aPathOpt;
+ FmFormModel* pModel = new FmFormModel( aPathOpt.GetPalettePath(),
+ 0, GetDoc()->GetDocShell() );
+ pModel->GetItemPool().FreezeIdRanges();
+
+ rStrm.Seek(0);
+
+ uno::Reference< io::XInputStream > xInputStream( new utl::OInputStreamWrapper( rStrm ) );
+ SvxDrawingLayerImport( pModel, xInputStream );
+
+ if ( !Imp()->HasDrawView() )
+ Imp()->MakeDrawView();
+
+ Point aPos( pPt ? *pPt : GetCharRect().Pos() );
+ SdrView *pView = Imp()->GetDrawView();
+
+ //Drop auf bestehendes Objekt: Objekt ersetzen oder neu Attributieren.
+ if( pModel->GetPageCount() > 0 &&
+ 1 == pModel->GetPage(0)->GetObjCount() &&
+ 1 == pView->GetMarkedObjectList().GetMarkCount() )
+ {
+ // replace a marked 'virtual' drawing object
+ // by its corresponding 'master' drawing object in the mark list.
+ SwDrawView::ReplaceMarkedDrawVirtObjs( *pView );
+
+ SdrObject* pClpObj = pModel->GetPage(0)->GetObj(0);
+ SdrObject* pOldObj = pView->GetMarkedObjectList().GetMark( 0 )->GetMarkedSdrObj();
+
+ if( SW_PASTESDR_SETATTR == nAction && pOldObj->ISA(SwVirtFlyDrawObj) )
+ nAction = SW_PASTESDR_REPLACE;
+
+ switch( nAction )
+ {
+ case SW_PASTESDR_REPLACE:
+ {
+ const SwFrmFmt* pFmt(0);
+ const SwFrm* pAnchor(0);
+ if( pOldObj->ISA(SwVirtFlyDrawObj) )
+ {
+ pFmt = FindFrmFmt( pOldObj );
+
+ Point aNullPt;
+ SwFlyFrm* pFlyFrm = ((SwFlyFrmFmt*)pFmt)->GetFrm( &aNullPt );
+ pAnchor = pFlyFrm->GetAnchorFrm();
+
+ if( pAnchor->FindFooterOrHeader() )
+ {
+ // wenn TextRahmen in der Kopf/Fusszeile steht, dann
+ // nicht ersetzen, sondern nur einfuegen
+ nAction = SW_PASTESDR_INSERT;
+ break;
+ }
+ }
+
+ SdrObject* pNewObj = pClpObj->Clone();
+ Rectangle aOldObjRect( pOldObj->GetCurrentBoundRect() );
+ Size aOldObjSize( aOldObjRect.GetSize() );
+ Rectangle aNewRect( pNewObj->GetCurrentBoundRect() );
+ Size aNewSize( aNewRect.GetSize() );
+
+ Fraction aScaleWidth( aOldObjSize.Width(), aNewSize.Width() );
+ Fraction aScaleHeight( aOldObjSize.Height(), aNewSize.Height());
+ pNewObj->NbcResize( aNewRect.TopLeft(), aScaleWidth, aScaleHeight);
+
+ Point aVec = aOldObjRect.TopLeft() - aNewRect.TopLeft();
+ pNewObj->NbcMove(Size(aVec.X(), aVec.Y()));
+
+ if( pNewObj->ISA( SdrUnoObj ) )
+ pNewObj->SetLayer( GetDoc()->GetControlsId() );
+ else if( pOldObj->ISA( SdrUnoObj ) )
+ pNewObj->SetLayer( GetDoc()->GetHeavenId() );
+ else
+ pNewObj->SetLayer( pOldObj->GetLayer() );
+
+ if( pOldObj->ISA(SwVirtFlyDrawObj) )
+ {
+ // Attribute sichern und dam SdrObject setzen
+ SfxItemSet aFrmSet( pDoc->GetAttrPool(),
+ RES_SURROUND, RES_ANCHOR );
+ aFrmSet.Set( pFmt->GetAttrSet() );
+
+ Point aNullPt;
+ if( pAnchor->IsTxtFrm() && ((SwTxtFrm*)pAnchor)->IsFollow() )
+ {
+ const SwTxtFrm* pTmp = (SwTxtFrm*)pAnchor;
+ do {
+ pTmp = pTmp->FindMaster();
+ OSL_ENSURE( pTmp, "Where's my Master?" );
+ } while( pTmp->IsFollow() );
+ pAnchor = pTmp;
+ }
+ if( pOldObj->ISA( SdrCaptionObj ))
+ aNullPt = ((SdrCaptionObj*)pOldObj)->GetTailPos();
+ else
+ aNullPt = aOldObjRect.TopLeft();
+
+ Point aNewAnchor = pAnchor->GetFrmAnchorPos( ::HasWrap( pOldObj ) );
+ // OD 2004-04-05 #i26791# - direct positioning of Writer
+ // fly frame object for <SwDoc::Insert(..)>
+ pNewObj->NbcSetRelativePos( aNullPt - aNewAnchor );
+ pNewObj->NbcSetAnchorPos( aNewAnchor );
+
+ pOldObj->GetOrdNum();
+
+ DelSelectedObj();
+
+ pFmt = GetDoc()->Insert( *GetCrsr(), *pNewObj, &aFrmSet, NULL );
+ }
+ else
+ pView->ReplaceObjectAtView( pOldObj, *Imp()->GetPageView(), pNewObj, sal_True );
+ }
+ break;
+
+ case SW_PASTESDR_SETATTR:
+ {
+ SfxItemSet aSet( GetAttrPool() );
+ aSet.Put(pClpObj->GetMergedItemSet());
+ pView->SetAttributes( aSet, sal_False );
+ }
+ break;
+
+ default:
+ nAction = SW_PASTESDR_INSERT;
+ break;
+ }
+ }
+ else
+ nAction = SW_PASTESDR_INSERT;
+
+ if( SW_PASTESDR_INSERT == nAction )
+ {
+ ::sw::DrawUndoGuard drawUndoGuard(GetDoc()->GetIDocumentUndoRedo());
+
+ sal_Bool bDesignMode = pView->IsDesignMode();
+ if( !bDesignMode )
+ pView->SetDesignMode( sal_True );
+
+ // --> OD 2005-08-03 #i50824#
+ // method <lcl_RemoveOleObjsFromSdrModel> replaced by <lcl_ConvertSdrOle2ObjsToSdrGrafObjs>
+ lcl_ConvertSdrOle2ObjsToSdrGrafObjs( pModel );
+ pView->Paste( *pModel, aPos );
+
+ sal_uLong nCnt = pView->GetMarkedObjectList().GetMarkCount();
+ if( nCnt )
+ {
+ const Point aNull( 0, 0 );
+ for( sal_uLong i=0; i < nCnt; ++i )
+ {
+ SdrObject *pObj = pView->GetMarkedObjectList().GetMark(i)->GetMarkedSdrObj();
+ pObj->ImpSetAnchorPos( aNull );
+ }
+
+ pView->SetCurrentObj( OBJ_GRUP, SdrInventor );
+ if ( nCnt > 1 )
+ pView->GroupMarked();
+ SdrObject *pObj = pView->GetMarkedObjectList().GetMark(0)->GetMarkedSdrObj();
+ if( pObj->ISA( SdrUnoObj ) )
+ {
+ pObj->SetLayer( GetDoc()->GetControlsId() );
+ bDesignMode = sal_True;
+ }
+ else
+ pObj->SetLayer( GetDoc()->GetHeavenId() );
+ const Rectangle &rSnap = pObj->GetSnapRect();
+ const Size aDiff( rSnap.GetWidth()/2, rSnap.GetHeight()/2 );
+ pView->MoveMarkedObj( aDiff );
+ ImpEndCreate();
+ if( !bDesignMode )
+ pView->SetDesignMode( sal_False );
+ }
+ }
+ EndUndo();
+ EndAllAction();
+ delete pModel;
+}
+
+sal_Bool SwFEShell::Paste( const Graphic &rGrf )
+{
+ SET_CURR_SHELL( this );
+ SdrObject* pObj;
+ SdrView *pView = Imp()->GetDrawView();
+
+ sal_Bool bRet = 1 == pView->GetMarkedObjectList().GetMarkCount() &&
+ (pObj = pView->GetMarkedObjectList().GetMark( 0 )->GetMarkedSdrObj())->IsClosedObj() &&
+ !pObj->ISA( SdrOle2Obj );
+
+ if( bRet )
+ {
+ XOBitmap aXOBitmap( rGrf.GetBitmap() );
+ SfxItemSet aSet( GetAttrPool(), XATTR_FILLSTYLE, XATTR_FILLBITMAP );
+ aSet.Put( XFillStyleItem( XFILL_BITMAP ));
+ aSet.Put( XFillBitmapItem( aEmptyStr, aXOBitmap ));
+ pView->SetAttributes( aSet, sal_False );
+ }
+ return bRet;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/frmedt/fedesc.cxx b/sw/source/core/frmedt/fedesc.cxx
new file mode 100644
index 000000000000..28becd7069d7
--- /dev/null
+++ b/sw/source/core/frmedt/fedesc.cxx
@@ -0,0 +1,283 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+#include <tools/ref.hxx>
+
+#include <hintids.hxx>
+#include <fesh.hxx>
+#include <doc.hxx>
+#include <IDocumentUndoRedo.hxx>
+#include <pagefrm.hxx>
+#include <rootfrm.hxx>
+#include <cntfrm.hxx>
+#include <pam.hxx>
+#include <fmtpdsc.hxx>
+#include <pagedesc.hxx>
+#include <tabfrm.hxx>
+#include <edimp.hxx>
+#include <SwStyleNameMapper.hxx>
+
+/*************************************************************************
+|*
+|* SwFEShell::GetPageDescCnt()
+|*
+|*************************************************************************/
+
+sal_uInt16 SwFEShell::GetPageDescCnt() const
+{
+ return GetDoc()->GetPageDescCnt();
+}
+
+/*************************************************************************
+|*
+|* SwFEShell::ChgCurPageDesc()
+|*
+|*************************************************************************/
+
+void SwFEShell::ChgCurPageDesc( const SwPageDesc& rDesc )
+{
+#if OSL_DEBUG_LEVEL > 1
+ //Die SS veraendert keinen PageDesc, sondern setzt nur das Attribut.
+ //Der Pagedesc muss im Dokument vorhanden sein!
+ sal_Bool bFound = sal_False;
+ for ( sal_uInt16 nTst = 0; nTst < GetPageDescCnt(); ++nTst )
+ if ( &rDesc == &GetPageDesc( nTst ) )
+ bFound = sal_True;
+ OSL_ENSURE( bFound, "ChgCurPageDesc mit ungueltigem Descriptor." );
+#endif
+
+ StartAllAction();
+
+ SwPageFrm *pPage = GetCurrFrm()->FindPageFrm();
+ const SwFrm *pFlow = 0;
+ sal_uInt16 nPageNmOffset = 0;
+
+ OSL_ENSURE( !GetCrsr()->HasMark(), "ChgCurPageDesc nur ohne Selektion!");
+
+ SET_CURR_SHELL( this );
+ while ( pPage )
+ {
+ pFlow = pPage->FindFirstBodyCntnt();
+ if ( pFlow )
+ {
+ if ( pFlow->IsInTab() )
+ pFlow = pFlow->FindTabFrm();
+ const SwFmtPageDesc& rPgDesc = pFlow->GetAttrSet()->GetPageDesc();
+ if( rPgDesc.GetPageDesc() )
+ {
+ // wir haben ihn den Schlingel
+ nPageNmOffset = rPgDesc.GetNumOffset();
+ break;
+ }
+ }
+ pPage = (SwPageFrm*) pPage->GetPrev();
+ }
+ if ( !pPage )
+ {
+ pPage = (SwPageFrm*) (GetLayout()->Lower());
+ pFlow = pPage->FindFirstBodyCntnt();
+ if ( !pFlow )
+ {
+ pPage = (SwPageFrm*)pPage->GetNext();
+ pFlow = pPage->FindFirstBodyCntnt();
+ OSL_ENSURE( pFlow, "Dokuemnt ohne Inhalt?!?" );
+ }
+ }
+
+ // Seitennummer mitnehmen
+ SwFmtPageDesc aNew( &rDesc );
+ aNew.SetNumOffset( nPageNmOffset );
+
+ if ( pFlow->IsInTab() )
+ GetDoc()->SetAttr( aNew, *(SwFmt*)pFlow->FindTabFrm()->GetFmt() );
+ else
+ {
+ SwPaM aPaM( *((SwCntntFrm*)pFlow)->GetNode() );
+ GetDoc()->InsertPoolItem( aPaM, aNew, 0 );
+ }
+ EndAllActionAndCall();
+}
+
+/*************************************************************************
+|*
+|* SwFEShell::ChgPageDesc()
+|*
+|*************************************************************************/
+
+void SwFEShell::ChgPageDesc( sal_uInt16 i, const SwPageDesc &rChged )
+{
+ StartAllAction();
+ SET_CURR_SHELL( this );
+ //Fix i64842: because Undo has a very special way to handle header/footer content
+ // we have to copy the page descriptor before calling ChgPageDesc.
+ SwPageDesc aDesc( rChged );
+ {
+ ::sw::UndoGuard const undoGuard(GetDoc()->GetIDocumentUndoRedo());
+ GetDoc()->CopyPageDesc(rChged, aDesc);
+ }
+ GetDoc()->ChgPageDesc( i, aDesc );
+ EndAllActionAndCall();
+}
+
+/*************************************************************************
+|*
+|* SwFEShell::GetPageDesc(), GetCurPageDesc()
+|*
+|*************************************************************************/
+
+const SwPageDesc& SwFEShell::GetPageDesc( sal_uInt16 i ) const
+{
+ return const_cast<const SwDoc *>(GetDoc())->GetPageDesc( i );
+}
+
+SwPageDesc* SwFEShell::FindPageDescByName( const String& rName,
+ sal_Bool bGetFromPool,
+ sal_uInt16* pPos )
+{
+ SwPageDesc* pDesc = GetDoc()->FindPageDescByName( rName, pPos );
+ if( !pDesc && bGetFromPool )
+ {
+ sal_uInt16 nPoolId = SwStyleNameMapper::GetPoolIdFromUIName( rName, nsSwGetPoolIdFromName::GET_POOLID_PAGEDESC );
+ if( USHRT_MAX != nPoolId &&
+ 0 != (pDesc = GetDoc()->GetPageDescFromPool( nPoolId ))
+ && pPos )
+ // werden immer hinten angehaengt
+ *pPos = GetDoc()->GetPageDescCnt() - 1 ;
+ }
+ return pDesc;
+}
+
+sal_uInt16 SwFEShell::GetMousePageDesc( const Point &rPt ) const
+{
+ if( GetLayout() )
+ {
+ const SwPageFrm* pPage =
+ static_cast<const SwPageFrm*>( GetLayout()->Lower() );
+ if( pPage )
+ {
+ while( pPage->GetNext() && rPt.Y() > pPage->Frm().Bottom() )
+ pPage = static_cast<const SwPageFrm*>( pPage->GetNext() );
+ SwDoc *pMyDoc = GetDoc();
+ for ( sal_uInt16 i = 0; i < GetDoc()->GetPageDescCnt(); ++i )
+ {
+ if ( pPage->GetPageDesc() == &const_cast<const SwDoc *>(pMyDoc)
+ ->GetPageDesc(i) )
+ return i;
+ }
+ }
+ }
+ return 0;
+}
+
+sal_uInt16 SwFEShell::GetCurPageDesc( const sal_Bool bCalcFrm ) const
+{
+ const SwFrm *pFrm = GetCurrFrm( bCalcFrm );
+ if ( pFrm )
+ {
+ const SwPageFrm *pPage = pFrm->FindPageFrm();
+ if ( pPage )
+ {
+ SwDoc *pMyDoc = GetDoc();
+ for ( sal_uInt16 i = 0; i < GetDoc()->GetPageDescCnt(); ++i )
+ {
+ if ( pPage->GetPageDesc() == &const_cast<const SwDoc *>(pMyDoc)
+ ->GetPageDesc(i) )
+ return i;
+ }
+ }
+ }
+ return 0;
+}
+
+// if inside all selection only one PageDesc, return this.
+// Otherwise return 0 pointer
+const SwPageDesc* SwFEShell::GetSelectedPageDescs() const
+{
+ const SwCntntNode* pCNd;
+ const SwFrm* pMkFrm, *pPtFrm;
+ const SwPageDesc* pFnd, *pRetDesc = (SwPageDesc*)0xffffffff;
+ const Point aNulPt;
+
+ FOREACHPAM_START(this)
+
+ if( 0 != (pCNd = PCURCRSR->GetCntntNode() ) &&
+ 0 != ( pPtFrm = pCNd->getLayoutFrm( GetLayout(), &aNulPt, 0, sal_False )) )
+ pPtFrm = pPtFrm->FindPageFrm();
+ else
+ pPtFrm = 0;
+
+ if( PCURCRSR->HasMark() &&
+ 0 != (pCNd = PCURCRSR->GetCntntNode( sal_False ) ) &&
+ 0 != ( pMkFrm = pCNd->getLayoutFrm( GetLayout(), &aNulPt, 0, sal_False )) )
+ pMkFrm = pMkFrm->FindPageFrm();
+ else
+ pMkFrm = pPtFrm;
+
+
+ if( !pMkFrm || !pPtFrm )
+ pFnd = 0;
+ else if( pMkFrm == pPtFrm )
+ pFnd = ((SwPageFrm*)pMkFrm)->GetPageDesc();
+ else
+ {
+ // swap pointer if PtFrm before MkFrm
+ if( ((SwPageFrm*)pMkFrm)->GetPhyPageNum() >
+ ((SwPageFrm*)pPtFrm)->GetPhyPageNum() )
+ {
+ const SwFrm* pTmp = pMkFrm; pMkFrm = pPtFrm; pPtFrm = pTmp;
+ }
+
+ // now check from MkFrm to PtFrm for equal PageDescs
+ pFnd = ((SwPageFrm*)pMkFrm)->GetPageDesc();
+ while( pFnd && pMkFrm != pPtFrm )
+ {
+ pMkFrm = pMkFrm->GetNext();
+ if( !pMkFrm || pFnd != ((SwPageFrm*)pMkFrm)->GetPageDesc() )
+ pFnd = 0;
+ }
+ }
+
+ if( (SwPageDesc*)0xffffffff == pRetDesc )
+ pRetDesc = pFnd;
+ else if( pFnd != pRetDesc )
+ {
+ pRetDesc = 0;
+ break;
+ }
+
+ FOREACHPAM_END()
+
+ return pRetDesc;
+}
+
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/frmedt/fefly1.cxx b/sw/source/core/frmedt/fefly1.cxx
new file mode 100644
index 000000000000..0661ae227dbc
--- /dev/null
+++ b/sw/source/core/frmedt/fefly1.cxx
@@ -0,0 +1,2207 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+#include <hintids.hxx>
+#include <svl/itemiter.hxx>
+#include <svtools/imapobj.hxx>
+#include <svtools/soerr.hxx>
+#include <editeng/protitem.hxx>
+#include <svx/svdogrp.hxx>
+#include <svx/svdouno.hxx>
+#include <svx/fmglob.hxx>
+#include <com/sun/star/form/FormButtonType.hpp>
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <fmtanchr.hxx>
+#include <txtflcnt.hxx>
+#include <fmtcntnt.hxx>
+#include <fmtornt.hxx>
+#include <fmtflcnt.hxx>
+#include <fmturl.hxx>
+#include <fmtclds.hxx>
+#include <fmtfsize.hxx>
+#include <docary.hxx>
+#include <fesh.hxx>
+#include <rootfrm.hxx>
+#include <pagefrm.hxx>
+#include <cntfrm.hxx>
+#include <txtfrm.hxx>
+#include <viewimp.hxx>
+#include <viscrs.hxx>
+#include <doc.hxx>
+#include <IDocumentUndoRedo.hxx>
+#include <dview.hxx>
+#include <dflyobj.hxx>
+#include <dcontact.hxx>
+#include <frmfmt.hxx>
+#include <flyfrm.hxx>
+#include <ndtxt.hxx>
+#include <edimp.hxx>
+#include <swtable.hxx>
+#include <mvsave.hxx> // Strukturen zum Sichern beim Move/Delete
+#include <ndgrf.hxx>
+#include <flyfrms.hxx>
+#include <flypos.hxx>
+#include <fldbas.hxx>
+#include <fmtfld.hxx>
+#include <swundo.hxx>
+#include <frame.hxx>
+#include <notxtfrm.hxx>
+#include <HandleAnchorNodeChg.hxx>
+#include <frmatr.hxx>
+#include <fmtsrnd.hxx> // #i89920#
+#include <ndole.hxx>
+#include <editeng/opaqitem.hxx>
+
+using ::rtl::OUString;
+using namespace ::com::sun::star;
+
+//Zum anmelden von Flys in Flys in ...
+//definiert in layout/frmtool.cxx
+void RegistFlys( SwPageFrm*, const SwLayoutFrm* );
+
+/***********************************************************************
+#* Class : SwDoc
+#* Methode : UseSpzLayoutFmt
+#* Beschreibung: Anhand des Request werden zu dem Format entsprechende
+#* Aenderungen an den Spezifischen Layouts vorgenommen.
+#***********************************************************************/
+
+sal_Bool lcl_SetNewFlyPos( const SwNode& rNode, SwFmtAnchor& rAnchor,
+ const Point& rPt )
+{
+ sal_Bool bRet = sal_False;
+ const SwStartNode* pStNode = rNode.FindFlyStartNode();
+ if( pStNode )
+ {
+ SwPosition aPos( *pStNode );
+ rAnchor.SetAnchor( &aPos );
+ bRet = sal_True;
+ }
+ else
+ {
+ const SwCntntNode *pCntNd = rNode.GetCntntNode();
+ const SwCntntFrm* pCFrm = pCntNd ? pCntNd->getLayoutFrm( pCntNd->GetDoc()->GetCurrentLayout(), &rPt, 0, sal_False ) : 0;
+ const SwPageFrm *pPg = pCFrm ? pCFrm->FindPageFrm() : 0;
+
+ rAnchor.SetPageNum( pPg ? pPg->GetPhyPageNum() : 1 );
+ rAnchor.SetType( FLY_AT_PAGE );
+ }
+ return bRet;
+}
+
+sal_Bool lcl_FindAnchorPos( SwDoc& rDoc, const Point& rPt, const SwFrm& rFrm,
+ SfxItemSet& rSet )
+{
+ sal_Bool bRet = sal_True;
+ SwFmtAnchor aNewAnch( (SwFmtAnchor&)rSet.Get( RES_ANCHOR ) );
+ RndStdIds nNew = aNewAnch.GetAnchorId();
+ const SwFrm *pNewAnch;
+
+ //Neuen Anker ermitteln
+ Point aTmpPnt( rPt );
+ switch( nNew )
+ {
+ case FLY_AS_CHAR: // sollte der nicht auch mit hinein?
+ case FLY_AT_PARA:
+ case FLY_AT_CHAR: // LAYER_IMPL
+ {
+ //Ausgehend von der linken oberen Ecke des Fly den
+ //dichtesten CntntFrm suchen.
+ const SwFrm* pFrm = rFrm.IsFlyFrm() ? ((SwFlyFrm&)rFrm).GetAnchorFrm()
+ : &rFrm;
+ pNewAnch = ::FindAnchor( pFrm, aTmpPnt );
+ if( pNewAnch->IsProtected() )
+ {
+ bRet = sal_False;
+ break;
+ }
+
+ SwPosition aPos( *((SwCntntFrm*)pNewAnch)->GetNode() );
+ if ((FLY_AT_CHAR == nNew) || (FLY_AS_CHAR == nNew))
+ {
+ // es muss ein TextNode gefunden werden, denn nur in diesen
+ // ist ein Inhaltsgebundene Frames zu verankern
+ SwCrsrMoveState aState( MV_SETONLYTEXT );
+ aTmpPnt.X() -= 1; //nicht im Fly landen!!
+ if( !pNewAnch->GetCrsrOfst( &aPos, aTmpPnt, &aState ) )
+ {
+ SwCntntNode* pCNd = ((SwCntntFrm*)pNewAnch)->GetNode();
+ if( pNewAnch->Frm().Bottom() < aTmpPnt.Y() )
+ pCNd->MakeStartIndex( &aPos.nContent );
+ else
+ pCNd->MakeEndIndex( &aPos.nContent );
+ }
+ }
+ aNewAnch.SetAnchor( &aPos );
+ }
+ break;
+
+ case FLY_AT_FLY: // LAYER_IMPL
+ {
+ //Ausgehend von der linken oberen Ecke des Fly den
+ //dichtesten SwFlyFrm suchen.
+ SwCrsrMoveState aState( MV_SETONLYTEXT );
+ SwPosition aPos( rDoc.GetNodes() );
+ aTmpPnt.X() -= 1; //nicht im Fly landen!!
+ rDoc.GetCurrentLayout()->GetCrsrOfst( &aPos, aTmpPnt, &aState ); //swmod 071108//swmod 071225
+ pNewAnch = ::FindAnchor(
+ aPos.nNode.GetNode().GetCntntNode()->getLayoutFrm( rFrm.getRootFrm(), 0, 0, sal_False ),
+ aTmpPnt )->FindFlyFrm();
+
+ if( pNewAnch && &rFrm != pNewAnch && !pNewAnch->IsProtected() )
+ {
+ aPos.nNode = *((SwFlyFrm*)pNewAnch)->GetFmt()->GetCntnt().
+ GetCntntIdx();
+ aNewAnch.SetAnchor( &aPos );
+ break;
+ }
+ }
+
+ aNewAnch.SetType( nNew = FLY_AT_PAGE );
+ // no break
+
+ case FLY_AT_PAGE:
+ pNewAnch = rFrm.FindPageFrm();
+ aNewAnch.SetPageNum( pNewAnch->GetPhyPageNum() );
+ break;
+
+ default:
+ OSL_ENSURE( !&rDoc, "Falsche ID fuer neuen Anker." );
+ }
+
+ rSet.Put( aNewAnch );
+ return bRet;
+}
+
+//
+//! also used in unoframe.cxx
+//
+sal_Bool lcl_ChkAndSetNewAnchor( const SwFlyFrm& rFly, SfxItemSet& rSet )
+{
+ const SwFrmFmt& rFmt = *rFly.GetFmt();
+ const SwFmtAnchor &rOldAnch = rFmt.GetAnchor();
+ const RndStdIds nOld = rOldAnch.GetAnchorId();
+
+ RndStdIds nNew = ((SwFmtAnchor&)rSet.Get( RES_ANCHOR )).GetAnchorId();
+
+ if( nOld == nNew )
+ return sal_False;
+
+ SwDoc* pDoc = (SwDoc*)rFmt.GetDoc();
+
+#if OSL_DEBUG_LEVEL > 1
+ OSL_ENSURE( !(nNew == FLY_AT_PAGE &&
+ (FLY_AT_PARA==nOld || FLY_AT_CHAR==nOld || FLY_AS_CHAR==nOld ) &&
+ pDoc->IsInHeaderFooter( rOldAnch.GetCntntAnchor()->nNode )),
+ "Unerlaubter Ankerwechsel in Head/Foot." );
+#endif
+
+ return ::lcl_FindAnchorPos( *pDoc, rFly.Frm().Pos(), rFly, rSet );
+}
+
+void SwFEShell::SelectFlyFrm( SwFlyFrm& rFrm, sal_Bool bNew )
+{
+ SET_CURR_SHELL( this );
+
+ // Wenn es ein neuer Rahmen ist, so soll er selektiert sein.
+ // !!Rahmen immer selektieren, wenn sie nicht selektiert sind.
+ // - Es kann ein neuer 'alter' sein weil der Anker gewechselt wurde.
+ // - 'alte' Rahmen sind vorher immer selektiert denn sonst wird nix
+ // an ihnen veraendert.
+ // Der Rahmen darf nicht per Dokumentposition selektiert werden, weil er
+ // auf jedenfall selektiert sein muss!
+ SwViewImp *pImpl = Imp();
+ if( GetWin() && (bNew || !pImpl->GetDrawView()->AreObjectsMarked()) )
+ {
+ OSL_ENSURE( rFrm.IsFlyFrm(), "SelectFlyFrm will einen Fly" );
+
+ //Wenn der Fly bereits selektiert ist gibt es hier ja wohl nichts
+ //zu tun.
+ if ( FindFlyFrm() == &rFrm )
+ return;
+
+ //Damit der Anker ueberhaupt noch gepaintet wird.
+ if( rFrm.IsFlyInCntFrm() && rFrm.GetAnchorFrm() )
+ rFrm.GetAnchorFrm()->SetCompletePaint();
+
+ if( pImpl->GetDrawView()->AreObjectsMarked() )
+ pImpl->GetDrawView()->UnmarkAll();
+
+ pImpl->GetDrawView()->MarkObj( rFrm.GetVirtDrawObj(),
+ pImpl->GetPageView(), sal_False, sal_False );
+ KillPams();
+ ClearMark();
+ SelFlyGrabCrsr();
+ }
+}
+
+/*************************************************************************
+|*
+|* SwFEShell::FindFlyFrm()
+|*
+|* Beschreibung Liefert den Fly wenn einer Selektiert ist.
+|*
+*************************************************************************/
+
+SwFlyFrm *SwFEShell::FindFlyFrm() const
+{
+ if ( Imp()->HasDrawView() )
+ {
+ // Ein Fly ist genau dann erreichbar, wenn er selektiert ist.
+ const SdrMarkList &rMrkList = Imp()->GetDrawView()->GetMarkedObjectList();
+ if( rMrkList.GetMarkCount() != 1 )
+ return 0;
+
+ SdrObject *pO = rMrkList.GetMark( 0 )->GetMarkedSdrObj();
+ return ( pO && pO->ISA(SwVirtFlyDrawObj) ) ? ((SwVirtFlyDrawObj*)pO)->GetFlyFrm() : 0;
+ }
+ return 0;
+}
+
+/*************************************************************************
+|*
+|* SwFEShell::IsFlyInFly()
+|*
+|* Beschreibung Liefert sal_True, wenn der aktuelle Fly an einem anderen
+|* verankert werden koennte (also innerhalb ist)
+|*
+*************************************************************************/
+
+const SwFrmFmt* SwFEShell::IsFlyInFly()
+{
+ SET_CURR_SHELL( this );
+
+ if ( !Imp()->HasDrawView() )
+ return NULL;
+
+ const SdrMarkList &rMrkList = Imp()->GetDrawView()->GetMarkedObjectList();
+ if ( !rMrkList.GetMarkCount() )
+ {
+ SwCntntFrm *pCntnt = GetCurrFrm( sal_False );
+ if( !pCntnt )
+ return NULL;
+ SwFlyFrm *pFly = pCntnt->FindFlyFrm();
+ if ( !pFly )
+ return NULL;
+ return pFly->GetFmt();
+ }
+ else if ( rMrkList.GetMarkCount() != 1 ||
+ !GetUserCall(rMrkList.GetMark( 0 )->GetMarkedSdrObj()) )
+ return NULL;
+
+ SdrObject *pObj = rMrkList.GetMark( 0 )->GetMarkedSdrObj();
+
+ SwFrmFmt *pFmt = FindFrmFmt( pObj );
+ if( pFmt && FLY_AT_FLY == pFmt->GetAnchor().GetAnchorId() )
+ {
+ const SwFrm* pFly = pObj->ISA(SwVirtFlyDrawObj) ?
+ ((SwVirtFlyDrawObj*)pObj)->GetFlyFrm()->GetAnchorFrm() :
+ ((SwDrawContact*)GetUserCall(pObj))->GetAnchorFrm( pObj );
+ OSL_ENSURE( pFly, "IsFlyInFly: Where's my anchor?" );
+ OSL_ENSURE( pFly->IsFlyFrm(), "IsFlyInFly: Funny anchor!" );
+ return ((SwFlyFrm*)pFly)->GetFmt();
+ }
+
+ Point aTmpPos = pObj->GetCurrentBoundRect().TopLeft();
+
+ SwFrm *pTxtFrm;
+ {
+ SwCrsrMoveState aState( MV_SETONLYTEXT );
+ SwNodeIndex aSwNodeIndex( GetDoc()->GetNodes() );
+ SwPosition aPos( aSwNodeIndex );
+ Point aPoint( aTmpPos );
+ aPoint.X() -= 1; //nicht im Fly landen!!
+ GetLayout()->GetCrsrOfst( &aPos, aPoint, &aState );
+ // determine text frame by left-top-corner of object
+ pTxtFrm = aPos.nNode.GetNode().GetCntntNode()->getLayoutFrm( GetLayout(), &aTmpPos, 0, sal_False );
+ }
+ const SwFrm *pTmp = ::FindAnchor( pTxtFrm, aTmpPos );
+ const SwFlyFrm *pFly = pTmp->FindFlyFrm();
+ if( pFly )
+ return pFly->GetFmt();
+ return NULL;
+}
+
+/*************************************************************************
+|*
+|* SwFEShell::SetFlyPos
+|*
+*************************************************************************/
+
+void SwFEShell::SetFlyPos( const Point& rAbsPos )
+{
+ SET_CURR_SHELL( this );
+
+ //Bezugspunkt in Dokumentkoordinaten bestimmen
+ SwCntntFrm *pCntnt = GetCurrFrm( sal_False );
+ if( !pCntnt )
+ return;
+ SwFlyFrm *pFly = pCntnt->FindFlyFrm();
+ if ( !pFly )
+ return;
+
+ //SwSaveHdl aSaveX( Imp() );
+
+ //Bei Absatzgebundenen Flys muss ausgehend von der absoluten
+ //Position ein neuer Anker gesetzt werden. Anker und neue RelPos werden
+ //vom Fly selbst berechnet und gesetzt.
+ if ( pFly->IsFlyAtCntFrm() )
+ ((SwFlyAtCntFrm*)pFly)->SetAbsPos( rAbsPos );
+ else
+ {
+ const SwFrm *pAnch = pFly->GetAnchorFrm();
+ Point aOrient( pAnch->Frm().Pos() );
+
+ if ( pFly->IsFlyInCntFrm() )
+ aOrient.X() = rAbsPos.X();
+
+ //RelPos errechnen.
+ aOrient.X() = rAbsPos.X() - aOrient.X();
+ aOrient.Y() = rAbsPos.Y() - aOrient.Y();
+ pFly->ChgRelPos( aOrient );
+ }
+ CallChgLnk(); // rufe das AttrChangeNotify auf der UI-Seite.
+}
+
+/*************************************************************************
+|*
+|* SwFEShell::FindAnchorPos
+|*
+*************************************************************************/
+
+Point SwFEShell::FindAnchorPos( const Point& rAbsPos, sal_Bool bMoveIt )
+{
+ Point aRet;
+
+ SET_CURR_SHELL( this );
+
+ if ( !Imp()->HasDrawView() )
+ return aRet;
+
+ const SdrMarkList &rMrkList = Imp()->GetDrawView()->GetMarkedObjectList();
+ if ( rMrkList.GetMarkCount() != 1 ||
+ !GetUserCall(rMrkList.GetMark( 0 )->GetMarkedSdrObj()) )
+ return aRet;
+
+ SdrObject* pObj = rMrkList.GetMark( 0 )->GetMarkedSdrObj();
+ // --> OD 2004-07-16 #i28701#
+ SwAnchoredObject* pAnchoredObj = ::GetUserCall( pObj )->GetAnchoredObj( pObj );
+ SwFrmFmt& rFmt = pAnchoredObj->GetFrmFmt();
+ RndStdIds nAnchorId = rFmt.GetAnchor().GetAnchorId();
+
+ if ( FLY_AS_CHAR == nAnchorId )
+ return aRet;
+
+ sal_Bool bFlyFrame = pObj->ISA(SwVirtFlyDrawObj);
+
+ SwFlyFrm* pFly = 0L;
+ const SwFrm* pOldAnch;
+ const SwFrm* pFooterOrHeader = NULL;
+
+ if( bFlyFrame )
+ {
+ //Bezugspunkt in Dokumentkoordinaten bestimmen
+ SwCntntFrm *pCntnt = GetCurrFrm( sal_False );
+ if( !pCntnt )
+ return aRet;
+ pFly = pCntnt->FindFlyFrm();
+ if ( !pFly )
+ return aRet;
+ pOldAnch = pFly->GetAnchorFrm();
+ if( !pOldAnch )
+ return aRet;
+ if ( FLY_AT_PAGE != nAnchorId )
+ {
+ pFooterOrHeader = pCntnt->FindFooterOrHeader();
+ }
+ }
+ // set <pFooterOrHeader> also for drawing
+ // objects, but not for control objects.
+ // Necessary for moving 'anchor symbol' at the user interface inside header/footer.
+ else if ( !::CheckControlLayer( pObj ) )
+ {
+ SwCntntFrm *pCntnt = GetCurrFrm( sal_False );
+ if( !pCntnt )
+ return aRet;
+ pFooterOrHeader = pCntnt->FindFooterOrHeader();
+ }
+
+ //Ausgehend von der linken oberen Ecke des Fly den
+ //dichtesten SwFlyFrm suchen.
+ SwCntntFrm *pTxtFrm;
+ {
+ SwCrsrMoveState aState( MV_SETONLYTEXT );
+ SwPosition aPos( GetDoc()->GetNodes().GetEndOfExtras() );
+ Point aTmpPnt( rAbsPos );
+ GetLayout()->GetCrsrOfst( &aPos, aTmpPnt, &aState );
+ pTxtFrm = aPos.nNode.GetNode().GetCntntNode()->getLayoutFrm( GetLayout(),0,&aPos,sal_False );
+ }
+ const SwFrm *pNewAnch;
+ if( pTxtFrm )
+ {
+ if ( FLY_AT_PAGE == nAnchorId )
+ {
+ pNewAnch = pTxtFrm->FindPageFrm();
+ }
+ else
+ {
+ pNewAnch = ::FindAnchor( pTxtFrm, rAbsPos );
+
+ if( FLY_AT_FLY == nAnchorId ) // LAYER_IMPL
+ {
+ pNewAnch = pNewAnch->FindFlyFrm();
+ }
+ }
+ }
+ else
+ pNewAnch = 0;
+
+ if( pNewAnch && !pNewAnch->IsProtected() )
+ {
+ const SwFlyFrm* pCheck = bFlyFrame ? pNewAnch->FindFlyFrm() : 0;
+ // Falls wir innerhalb eines Rahmens landen, muss sichergestellt werden,
+ // dass der Rahmen nicht in seinem eigenen Inhalt landet!
+ while( pCheck )
+ {
+ if( pCheck == pFly )
+ break;
+ const SwFrm *pTmp = pCheck->GetAnchorFrm();
+ pCheck = pTmp ? pTmp->FindFlyFrm() : NULL;
+ }
+ // Es darf nicht aus einer Kopf-/Fusszeile in einen anderen Bereich
+ // gewechselt werden, es darf nicht in eine Kopf-/Fusszeile hinein-
+ // gewechselt werden.
+ if( !pCheck &&
+ pFooterOrHeader == pNewAnch->FindFooterOrHeader() )
+ {
+ aRet = pNewAnch->GetFrmAnchorPos( ::HasWrap( pObj ) );
+
+ if ( bMoveIt || (nAnchorId == FLY_AT_CHAR) )
+ {
+ SwFmtAnchor aAnch( rFmt.GetAnchor() );
+ switch ( nAnchorId )
+ {
+ case FLY_AT_PARA:
+ {
+ SwPosition *pPos = (SwPosition*)aAnch.GetCntntAnchor();
+ pPos->nNode = *pTxtFrm->GetNode();
+ pPos->nContent.Assign(0,0);
+ break;
+ }
+ case FLY_AT_PAGE:
+ {
+ aAnch.SetPageNum( ((const SwPageFrm*)pNewAnch)->
+ GetPhyPageNum() );
+ break;
+ }
+ case FLY_AT_FLY:
+ {
+ SwPosition aPos( *((SwFlyFrm*)pNewAnch)->GetFmt()->
+ GetCntnt().GetCntntIdx() );
+ aAnch.SetAnchor( &aPos );
+ break;
+ }
+ case FLY_AT_CHAR:
+ {
+ SwPosition *pPos = (SwPosition*)aAnch.GetCntntAnchor();
+ Point aTmpPnt( rAbsPos );
+ if( pTxtFrm->GetCrsrOfst( pPos, aTmpPnt, NULL ) )
+ {
+ SwRect aTmpRect;
+ pTxtFrm->GetCharRect( aTmpRect, *pPos );
+ aRet = aTmpRect.Pos();
+ }
+ else
+ {
+ pPos->nNode = *pTxtFrm->GetNode();
+ pPos->nContent.Assign(0,0);
+ }
+ break;
+ }
+ default:
+ break;
+ }
+ if( bMoveIt )
+ {
+ StartAllAction();
+ // --> handle change of anchor node:
+ // if count of the anchor frame also change, the fly frames have to be
+ // re-created. Thus, delete all fly frames except the <this> before the
+ // anchor attribute is change and re-create them afterwards.
+ {
+ SwHandleAnchorNodeChg* pHandleAnchorNodeChg( 0L );
+ SwFlyFrmFmt* pFlyFrmFmt( dynamic_cast<SwFlyFrmFmt*>(&rFmt) );
+ if ( pFlyFrmFmt )
+ {
+ pHandleAnchorNodeChg =
+ new SwHandleAnchorNodeChg( *pFlyFrmFmt, aAnch );
+ }
+ rFmt.GetDoc()->SetAttr( aAnch, rFmt );
+ delete pHandleAnchorNodeChg;
+ }
+ // <--
+ // --> OD 2004-06-24 #i28701# - no call of method
+ // <CheckCharRectAndTopOfLine()> for to-character anchored
+ // Writer fly frame needed. This method call can cause a
+ // format of the anchor frame, which is no longer intended.
+ // Instead clear the anchor character rectangle and
+ // the top of line values for all to-character anchored objects.
+ pAnchoredObj->ClearCharRectAndTopOfLine();
+ // <--
+ EndAllAction();
+ }
+ }
+
+ SwRect aTmpRect( aRet, rAbsPos );
+ if( aTmpRect.HasArea() )
+ MakeVisible( aTmpRect );
+#if OSL_DEBUG_LEVEL > 1
+ //TODO: That doesn't seem to be intended
+ if( Color(COL_TRANSPARENT) != GetOut()->GetLineColor() )
+ {
+ OSL_FAIL( "Hey, Joe: Where's my Null Pen?" );
+ GetOut()->SetLineColor( Color(COL_TRANSPARENT) );
+ }
+#endif
+ }
+ }
+
+ return aRet;
+}
+
+/***********************************************************************
+#* Class : SwFEShell
+#* Methode : NewFlyFrm
+#* Beschreibung:
+#***********************************************************************/
+
+const SwFrmFmt *SwFEShell::NewFlyFrm( const SfxItemSet& rSet, sal_Bool bAnchValid,
+ SwFrmFmt *pParent )
+{
+ SET_CURR_SHELL( this );
+ StartAllAction();
+
+ SwPaM* pCrsr = GetCrsr();
+ const Point aPt( GetCrsrDocPos() );
+
+ SwSelBoxes aBoxes;
+ sal_Bool bMoveCntnt = sal_True;
+ if( IsTableMode() )
+ {
+ GetTblSel( *this, aBoxes );
+ if( aBoxes.Count() )
+ {
+ // die Crsr muessen noch aus dem Loeschbereich entfernt
+ // werden. Setze sie immer hinter/auf die Tabelle; ueber die
+ // Dokument-Position werden sie dann immer an die alte
+ // Position gesetzt.
+ ParkCrsr( SwNodeIndex( *aBoxes[0]->GetSttNd() ));
+
+ // --> FME 2005-12-01 #i127787# pCurCrsr will be deleted in ParkCrsr,
+ // we better get the current pCurCrsr instead of working with the
+ // deleted one:
+ pCrsr = GetCrsr();
+ }
+ else
+ bMoveCntnt = sal_False;
+ }
+ else if( !pCrsr->HasMark() && pCrsr->GetNext() == pCrsr )
+ bMoveCntnt = sal_False;
+
+ const SwPosition& rPos = *pCrsr->Start();
+
+ SwFmtAnchor& rAnch = (SwFmtAnchor&)rSet.Get( RES_ANCHOR );
+ RndStdIds eRndId = rAnch.GetAnchorId();
+ switch( eRndId )
+ {
+ case FLY_AT_PAGE:
+ if( !rAnch.GetPageNum() ) //HotFix: Bug in UpdateByExample
+ rAnch.SetPageNum( 1 );
+ break;
+
+ case FLY_AT_FLY:
+ case FLY_AT_PARA:
+ case FLY_AT_CHAR:
+ case FLY_AS_CHAR:
+ if( !bAnchValid )
+ {
+ if( FLY_AT_FLY != eRndId )
+ {
+ rAnch.SetAnchor( &rPos );
+ }
+ else if( lcl_SetNewFlyPos( rPos.nNode.GetNode(), rAnch, aPt ) )
+ {
+ eRndId = FLY_AT_PAGE;
+ }
+ }
+ break;
+
+ default:
+ OSL_ENSURE( !this, "Was sollte das fuer ein Fly werden?" );
+ break;
+ }
+
+ SwFlyFrmFmt *pRet;
+ if( bMoveCntnt )
+ {
+ GetDoc()->GetIDocumentUndoRedo().StartUndo( UNDO_INSLAYFMT, NULL );
+ SwFmtAnchor* pOldAnchor = 0;
+ sal_Bool bHOriChgd = sal_False, bVOriChgd = sal_False;
+ SwFmtVertOrient aOldV;
+ SwFmtHoriOrient aOldH;
+
+ if ( FLY_AT_PAGE != eRndId )
+ {
+ // erstmal als mit Seitenbindung, Absatz/Zeichenbindung erst wenn
+ // alles verschoben ist. Dann ist die Position gueltig!
+ // JP 13.05.98: ggfs. auch noch die Hori/Vert-Orientierung
+ // umsetzen, damit diese beim Umanker NICHT
+ // korrigiert wird
+ pOldAnchor = new SwFmtAnchor( rAnch );
+ const_cast<SfxItemSet&>(rSet).Put( SwFmtAnchor( FLY_AT_PAGE, 1 ) );
+
+ const SfxPoolItem* pItem;
+ if( SFX_ITEM_SET == rSet.GetItemState( RES_HORI_ORIENT, sal_False, &pItem )
+ && text::HoriOrientation::NONE == ((SwFmtHoriOrient*)pItem)->GetHoriOrient() )
+ {
+ bHOriChgd = sal_True;
+ aOldH = *((SwFmtHoriOrient*)pItem);
+ ((SfxItemSet&)rSet).Put( SwFmtHoriOrient( 0, text::HoriOrientation::LEFT ) );
+ }
+ if( SFX_ITEM_SET == rSet.GetItemState( RES_VERT_ORIENT, sal_False, &pItem )
+ && text::VertOrientation::NONE == ((SwFmtVertOrient*)pItem)->GetVertOrient() )
+ {
+ bVOriChgd = sal_True;
+ aOldV = *((SwFmtVertOrient*)pItem);
+ ((SfxItemSet&)rSet).Put( SwFmtVertOrient( 0, text::VertOrientation::TOP ) );
+ }
+ }
+
+ pRet = GetDoc()->MakeFlyAndMove( *pCrsr, rSet, &aBoxes, pParent );
+
+ KillPams();
+
+ if( pOldAnchor )
+ {
+ if( pRet )
+ {
+ // neue Position bestimmen
+ //JP 24.03.97: immer ueber die Seitenbindung gehen - der
+ // chaos::Anchor darf nie im verschobenen Bereich
+ // liegen
+ pRet->DelFrms();
+
+ const SwFrm* pAnch = ::FindAnchor( GetLayout(), aPt, sal_False );
+ SwPosition aPos( *((SwCntntFrm*)pAnch)->GetNode() );
+ if ( FLY_AS_CHAR == eRndId )
+ {
+ aPos.nContent.Assign( ((SwCntntFrm*)pAnch)->GetNode(), 0 );
+ }
+ pOldAnchor->SetAnchor( &aPos );
+
+ // das verschieben von TabelleSelektion ist noch nicht
+ // Undofaehig - also darf das UmAnkern auch nicht
+ // aufgezeichnet werden.
+ bool const bDoesUndo =
+ GetDoc()->GetIDocumentUndoRedo().DoesUndo();
+ SwUndoId nLastUndoId(UNDO_EMPTY);
+ if (bDoesUndo &&
+ GetDoc()->GetIDocumentUndoRedo().GetLastUndoInfo(0,
+ & nLastUndoId))
+ {
+ if (UNDO_INSLAYFMT == nLastUndoId)
+ {
+ GetDoc()->GetIDocumentUndoRedo().DoUndo(false);
+ }
+ }
+
+ ((SfxItemSet&)rSet).Put( *pOldAnchor );
+
+ if( bHOriChgd )
+ ((SfxItemSet&)rSet).Put( aOldH );
+ if( bVOriChgd )
+ ((SfxItemSet&)rSet).Put( aOldV );
+
+ GetDoc()->SetFlyFrmAttr( *pRet, (SfxItemSet&)rSet );
+ GetDoc()->GetIDocumentUndoRedo().DoUndo(bDoesUndo);
+ }
+ delete pOldAnchor;
+ }
+ GetDoc()->GetIDocumentUndoRedo().EndUndo( UNDO_INSLAYFMT, NULL );
+ }
+ else
+ /* If called from a shell try to propagate an
+ existing adjust item from rPos to the content node of the
+ new frame. */
+ pRet = GetDoc()->MakeFlySection( eRndId, &rPos, &rSet, pParent, sal_True );
+
+ if( pRet )
+ {
+ SwFlyFrm* pFrm = pRet->GetFrm( &aPt );
+ if( pFrm )
+ SelectFlyFrm( *pFrm, sal_True );
+ else
+ {
+ GetLayout()->SetAssertFlyPages();
+ pRet = 0;
+ }
+ }
+ EndAllActionAndCall();
+
+ return pRet;
+}
+
+/***********************************************************************
+#* Class : SwFEShell
+#* Methode : Insert
+#***********************************************************************/
+
+void SwFEShell::Insert( const String& rGrfName, const String& rFltName,
+ const Graphic* pGraphic,
+ const SfxItemSet* pFlyAttrSet,
+ const SfxItemSet* pGrfAttrSet,
+ SwFrmFmt* pFrmFmt )
+{
+ SwFlyFrmFmt* pFmt = 0;
+ SET_CURR_SHELL( this );
+ StartAllAction();
+ SwShellCrsr *pStartCursor = dynamic_cast<SwShellCrsr*>(this->GetSwCrsr());
+ SwShellCrsr *pCursor = pStartCursor;
+ do {
+
+ // Anker noch nicht oder unvollstaendig gesetzt ?
+ if( pFlyAttrSet )
+ {
+ const SfxPoolItem* pItem;
+ if( SFX_ITEM_SET == pFlyAttrSet->GetItemState( RES_ANCHOR, sal_False,
+ &pItem ) )
+ {
+ SwFmtAnchor* pAnchor = (SwFmtAnchor*)pItem;
+ switch( pAnchor->GetAnchorId())
+ {
+ case FLY_AT_PARA:
+ case FLY_AT_CHAR: // LAYER_IMPL
+ case FLY_AS_CHAR:
+ if( !pAnchor->GetCntntAnchor() )
+ {
+ pAnchor->SetAnchor( pCursor->GetPoint() );
+ }
+ break;
+ case FLY_AT_FLY:
+ if( !pAnchor->GetCntntAnchor() )
+ {
+ lcl_SetNewFlyPos( *pCursor->GetNode(),
+ *pAnchor, GetCrsrDocPos() );
+ }
+ break;
+ case FLY_AT_PAGE:
+ if( !pAnchor->GetPageNum() )
+ {
+ pAnchor->SetPageNum( pCursor->GetPageNum(
+ sal_True, &pCursor->GetPtPos() ) );
+ }
+ break;
+ default :
+ break;
+ }
+ }
+ }
+ pFmt = GetDoc()->Insert(*pCursor, rGrfName,
+ rFltName, pGraphic,
+ pFlyAttrSet,
+ pGrfAttrSet, pFrmFmt );
+ OSL_ENSURE( pFmt, "Doc->Insert(notxt) failed." );
+
+ } while( (pCursor = dynamic_cast<SwShellCrsr*>(pCursor->GetNext()))
+ != pStartCursor );
+
+ EndAllAction();
+
+ if( pFmt )
+ {
+ const Point aPt( GetCrsrDocPos() );
+ SwFlyFrm* pFrm = pFmt->GetFrm( &aPt );
+
+ if( pFrm )
+ SelectFlyFrm( *pFrm, sal_True );
+ else
+ GetLayout()->SetAssertFlyPages();
+ }
+}
+
+SwFlyFrmFmt* SwFEShell::InsertObject( const svt::EmbeddedObjectRef& xObj,
+ const SfxItemSet* pFlyAttrSet,
+ const SfxItemSet* pGrfAttrSet,
+ SwFrmFmt* pFrmFmt )
+{
+ SwFlyFrmFmt* pFmt = 0;
+ SET_CURR_SHELL( this );
+ StartAllAction();
+ FOREACHPAM_START( this )
+ pFmt = GetDoc()->Insert(*PCURCRSR, xObj,
+ pFlyAttrSet, pGrfAttrSet, pFrmFmt );
+ OSL_ENSURE( pFmt, "Doc->Insert(notxt) failed." );
+
+ FOREACHPAM_END()
+ EndAllAction();
+
+ if( pFmt )
+ {
+ const Point aPt( GetCrsrDocPos() );
+ SwFlyFrm* pFrm = pFmt->GetFrm( &aPt );
+
+ if( pFrm )
+ SelectFlyFrm( *pFrm, sal_True );
+ else
+ GetLayout()->SetAssertFlyPages();
+ }
+
+ return pFmt;
+}
+
+
+void SwFEShell::InsertDrawObj( SdrObject& rDrawObj,
+ const Point& rInsertPosition )
+{
+ SET_CURR_SHELL( this );
+
+ SfxItemSet rFlyAttrSet( GetDoc()->GetAttrPool(), aFrmFmtSetRange );
+ rFlyAttrSet.Put( SwFmtAnchor( FLY_AT_PARA ));
+ // --> OD 2009-12-29 #i89920#
+ rFlyAttrSet.Put( SwFmtSurround( SURROUND_THROUGHT ) );
+ rDrawObj.SetLayer( getIDocumentDrawModelAccess()->GetHeavenId() );
+ // <--
+
+ // find anchor position
+ SwPaM aPam( pDoc->GetNodes() );
+ {
+ SwCrsrMoveState aState( MV_SETONLYTEXT );
+ Point aTmpPt( rInsertPosition );
+ GetLayout()->GetCrsrOfst( aPam.GetPoint(), aTmpPt, &aState );
+ const SwFrm* pFrm = aPam.GetCntntNode()->getLayoutFrm( GetLayout(), 0, 0, sal_False );
+ const Point aRelPos( rInsertPosition.X() - pFrm->Frm().Left(),
+ rInsertPosition.Y() - pFrm->Frm().Top() );
+ rDrawObj.SetRelativePos( aRelPos );
+ ::lcl_FindAnchorPos( *GetDoc(), rInsertPosition, *pFrm, rFlyAttrSet );
+ }
+ // insert drawing object into the document creating a new <SwDrawFrmFmt> instance
+ SwDrawFrmFmt* pFmt = GetDoc()->Insert( aPam, rDrawObj, &rFlyAttrSet, 0 );
+
+ // move object to visible layer
+ SwContact* pContact = static_cast<SwContact*>(rDrawObj.GetUserCall());
+ if ( pContact )
+ {
+ pContact->MoveObjToVisibleLayer( &rDrawObj );
+ }
+
+ if ( pFmt )
+ {
+ // select drawing object
+ Imp()->GetDrawView()->MarkObj( &rDrawObj, Imp()->GetPageView(),
+ sal_False, sal_False );
+ }
+ else
+ {
+ GetLayout()->SetAssertFlyPages();
+ }
+}
+
+/***********************************************************************
+#* Class : SwFEShell
+#* Methode : GetPageObjs
+#***********************************************************************/
+
+void SwFEShell::GetPageObjs( SvPtrarr& rFillArr )
+{
+ if( rFillArr.Count() )
+ rFillArr.Remove( 0, rFillArr.Count() );
+
+ const SwFrmFmt* pFmt;
+ for( sal_uInt16 n = 0; n < pDoc->GetSpzFrmFmts()->Count(); ++n )
+ {
+ pFmt = (const SwFrmFmt*)(*pDoc->GetSpzFrmFmts())[n];
+ if (FLY_AT_PAGE == pFmt->GetAnchor().GetAnchorId())
+ {
+ rFillArr.Insert( (VoidPtr)pFmt, rFillArr.Count() );
+ }
+ }
+}
+
+/***********************************************************************
+#* Class : SwFEShell
+#* Methode : SetPageFlysNewPage
+#***********************************************************************/
+
+void SwFEShell::SetPageObjsNewPage( SvPtrarr& rFillArr, int nOffset )
+{
+ if( !rFillArr.Count() || !nOffset )
+ return;
+
+ StartAllAction();
+ StartUndo();
+
+ SwFrmFmt* pFmt;
+ long nNewPage;
+ SwRootFrm* pTmpRootFrm = GetLayout();//swmod 080317
+ sal_uInt16 nMaxPage = pTmpRootFrm->GetPageNum();
+ sal_Bool bTmpAssert = sal_False;
+ for( sal_uInt16 n = 0; n < rFillArr.Count(); ++n )
+ {
+ pFmt = (SwFrmFmt*)rFillArr[n];
+ if( USHRT_MAX != pDoc->GetSpzFrmFmts()->GetPos( pFmt ))
+ {
+ // FlyFmt ist noch gueltig, also behandeln
+ SwFmtAnchor aNewAnchor( pFmt->GetAnchor() );
+ if ((FLY_AT_PAGE != aNewAnchor.GetAnchorId()) ||
+ 0 >= ( nNewPage = aNewAnchor.GetPageNum() + nOffset ) )
+ // chaos::Anchor wurde veraendert oder ungueltige SeitenNummer,
+ // also nicht veraendern !!
+ continue;
+
+ if( sal_uInt16(nNewPage) > nMaxPage )
+ {
+ if ( RES_DRAWFRMFMT == pFmt->Which() )
+ {
+ SwContact *pCon = pFmt->FindContactObj();
+ if( pCon )
+ ((SwDrawContact*)pCon)->DisconnectFromLayout();
+ }
+ else
+ pFmt->DelFrms();
+ bTmpAssert = sal_True;
+ }
+ aNewAnchor.SetPageNum( sal_uInt16(nNewPage) );
+ pDoc->SetAttr( aNewAnchor, *pFmt );
+ }
+ }
+
+ if( bTmpAssert )
+ pTmpRootFrm->SetAssertFlyPages();
+
+ EndUndo();
+ EndAllAction();
+}
+
+/***********************************************************************
+#* Class : SwFEShell
+#* Methode : GetFlyFrmAttr
+#* Beschreibung: Alle Attribute in dem 'Koerbchen' werden mit den
+#* Attributen des aktuellen FlyFrms gefuellt.
+#* Sind Attribute nicht zu fuellen weil fehl am Platz oder
+#* uneindeutig (Mehrfachtselektionen) so werden sie entfernt.
+#***********************************************************************/
+
+sal_Bool SwFEShell::GetFlyFrmAttr( SfxItemSet &rSet ) const
+{
+ SwFlyFrm *pFly = FindFlyFrm();
+ if ( !pFly )
+ {
+ SwFrm* pCurrFrm( GetCurrFrm() );
+ if ( !pCurrFrm )
+ {
+ OSL_FAIL( "<SwFEShell::GetFlyFrmAttr(..)> - missing current frame. This is a serious defect, please inform OD." );
+ return sal_False;
+ }
+ pFly = GetCurrFrm()->FindFlyFrm();
+ if ( !pFly )
+ {
+ OSL_ENSURE( !this, "GetFlyFrmAttr, no Fly selected." );
+ return sal_False;
+ }
+ }
+
+ SET_CURR_SHELL( (ViewShell*)this );
+
+ if( !rSet.Set( pFly->GetFmt()->GetAttrSet(), sal_True ) )
+ return sal_False;
+
+ //Und die Attribute durchschaufeln. Unerlaubte Attribute entfernen, dann
+ //alle restlichen Attribute besorgen und eintragen.
+ const SfxPoolItem* pItem;
+ if( SFX_ITEM_SET == rSet.GetItemState( RES_ANCHOR, sal_False, &pItem ) )
+ {
+ SwFmtAnchor* pAnchor = (SwFmtAnchor*)pItem;
+ RndStdIds eType = pAnchor->GetAnchorId();
+
+ if ( FLY_AT_PAGE != eType )
+ {
+ // OD 12.11.2003 #i22341# - content anchor of anchor item is needed.
+ // Thus, don't overwrite anchor item by default contructed anchor item.
+ if ( FLY_AS_CHAR == eType )
+ {
+ rSet.ClearItem( RES_OPAQUE );
+ rSet.ClearItem( RES_SURROUND );
+ }
+ }
+ }
+ rSet.SetParent( pFly->GetFmt()->GetAttrSet().GetParent() );
+ // die Attribute MUESSEN entfern werden!
+ rSet.ClearItem( RES_FILL_ORDER );
+ rSet.ClearItem( RES_CNTNT );
+ //MA: Ersteinmal entfernen (Template by example usw.)
+ rSet.ClearItem( RES_CHAIN );
+ return sal_True;
+}
+/***********************************************************************
+#* Class : SwFEShell
+#* Methode : SetFlyFrmAttr
+#* Beschreibung: Die Attribute des aktuellen Flys aendern sich.
+#***********************************************************************/
+
+sal_Bool SwFEShell::SetFlyFrmAttr( SfxItemSet& rSet )
+{
+ SET_CURR_SHELL( this );
+ sal_Bool bRet = sal_False;
+
+ if( rSet.Count() )
+ {
+ SwFlyFrm *pFly = FindFlyFrm();
+ if( !pFly )
+ {
+ OSL_ENSURE( GetCurrFrm(), "Crsr in parking zone" );
+ pFly = GetCurrFrm()->FindFlyFrm();
+ OSL_ENSURE( pFly, "SetFlyFrmAttr, no Fly selected." );
+ }
+ if( pFly )
+ {
+ StartAllAction();
+ const Point aPt( pFly->Frm().Pos() );
+
+ if( SFX_ITEM_SET == rSet.GetItemState( RES_ANCHOR, sal_False ))
+ ::lcl_ChkAndSetNewAnchor( *pFly, rSet );
+ SwFlyFrmFmt* pFlyFmt = (SwFlyFrmFmt*)pFly->GetFmt();
+
+ if( GetDoc()->SetFlyFrmAttr( *pFlyFmt, rSet ))
+ {
+ bRet = sal_True;
+ SwFlyFrm* pFrm = pFlyFmt->GetFrm( &aPt );
+ if( pFrm )
+ SelectFlyFrm( *pFrm, sal_True );
+ else
+ GetLayout()->SetAssertFlyPages();
+ }
+
+ EndAllActionAndCall();
+ }
+ }
+ return bRet;
+}
+
+sal_Bool SwFEShell::SetDrawingAttr( SfxItemSet& rSet )
+{
+ sal_Bool bRet = sal_False;
+ SET_CURR_SHELL( this );
+ if ( !rSet.Count() ||
+ !Imp()->HasDrawView() )
+ return bRet;
+
+ const SdrMarkList &rMrkList = Imp()->GetDrawView()->GetMarkedObjectList();
+ if ( rMrkList.GetMarkCount() != 1 )
+ return bRet;
+
+ StartUndo();
+ SdrObject *pObj = rMrkList.GetMark( 0 )->GetMarkedSdrObj();
+ SwFrmFmt *pFmt = FindFrmFmt( pObj );
+ StartAllAction();
+ if( SFX_ITEM_SET == rSet.GetItemState( RES_ANCHOR, sal_False ))
+ {
+ RndStdIds nNew = ((SwFmtAnchor&)rSet.Get( RES_ANCHOR )).GetAnchorId();
+ if ( nNew != pFmt->GetAnchor().GetAnchorId() )
+ {
+ ChgAnchor( nNew );
+ // --> OD 2004-06-17 #i26791# - clear anchor attribute in item set,
+ // because method <ChgAnchor(..)> takes care of it.
+ rSet.ClearItem( RES_ANCHOR );
+ }
+ }
+
+ if( GetDoc()->SetFlyFrmAttr( *pFmt, rSet ))
+ {
+ bRet = sal_True;
+ Point aTmp;
+ SelectObj( aTmp, 0, pObj );
+ }
+ EndAllActionAndCall();
+ EndUndo();
+ return bRet;
+}
+
+
+/***********************************************************************
+#* Class : SwFEShell
+#* Methode : ResetFlyFrmAttr
+#* Beschreibung: Das gewuenschte Attribut oder die im Set befindlichen
+#* werden zurueckgesetzt.
+#***********************************************************************/
+
+sal_Bool SwFEShell::ResetFlyFrmAttr( sal_uInt16 nWhich, const SfxItemSet* pSet )
+{
+ sal_Bool bRet = sal_False;
+
+ if( RES_ANCHOR != nWhich && RES_CHAIN != nWhich && RES_CNTNT != nWhich )
+ {
+ SET_CURR_SHELL( this );
+
+ SwFlyFrm *pFly = FindFlyFrm();
+ if( !pFly )
+ {
+ OSL_ENSURE( GetCurrFrm(), "Crsr in parking zone" );
+ pFly = GetCurrFrm()->FindFlyFrm();
+ OSL_ENSURE( pFly, "SetFlyFrmAttr, no Fly selected." );
+ }
+
+ if( pFly )
+ {
+ StartAllAction();
+
+ if( pSet )
+ {
+ SfxItemIter aIter( *pSet );
+ const SfxPoolItem* pItem = aIter.FirstItem();
+ while( pItem )
+ {
+ if( !IsInvalidItem( pItem ) &&
+ RES_ANCHOR != ( nWhich = pItem->Which() ) &&
+ RES_CHAIN != nWhich && RES_CNTNT != nWhich )
+ pFly->GetFmt()->ResetFmtAttr( nWhich );
+ pItem = aIter.NextItem();
+ }
+ }
+ else
+ pFly->GetFmt()->ResetFmtAttr( nWhich );
+
+ bRet = sal_True;
+ EndAllActionAndCall();
+ GetDoc()->SetModified();
+ }
+ }
+ return bRet;
+}
+
+/***********************************************************************
+#* Class : SwFEShell
+#* Methode : GetCurFrmFmt
+#* Beschreibung: liefert wenn Rahmen, dann Rahmenvorlage, sonst 0
+#***********************************************************************/
+
+SwFrmFmt* SwFEShell::GetCurFrmFmt() const
+{
+ SwFrmFmt* pRet = 0;
+ SwLayoutFrm *pFly = FindFlyFrm();
+ if( pFly && ( pRet = (SwFrmFmt*)pFly->GetFmt()->DerivedFrom() ) ==
+ GetDoc()->GetDfltFrmFmt() )
+ pRet = 0;
+ return pRet;
+}
+
+/******************************************************************************
+ * Methode : void SwFEShell::SetFrmFmt(SwFrmFmt *pNewFmt)
+ * Beschreibung:
+ ******************************************************************************/
+
+void SwFEShell::SetFrmFmt( SwFrmFmt *pNewFmt, sal_Bool bKeepOrient, Point* pDocPos )
+{
+ SwFlyFrm *pFly = 0;
+ if(pDocPos)
+ {
+ const SwFrmFmt* pFmt = GetFmtFromObj( *pDocPos );
+
+ if(PTR_CAST(SwFlyFrmFmt, pFmt))
+ pFly = ((SwFlyFrmFmt*)pFmt)->GetFrm();
+ }
+ else
+ pFly = FindFlyFrm();
+ OSL_ENSURE( pFly, "SetFrmFmt: kein Frame" );
+ if( pFly )
+ {
+ StartAllAction();
+ SET_CURR_SHELL( this );
+
+ SwFlyFrmFmt* pFlyFmt = (SwFlyFrmFmt*)pFly->GetFmt();
+ const Point aPt( pFly->Frm().Pos() );
+
+ SfxItemSet* pSet = 0;
+ const SfxPoolItem* pItem;
+ if( SFX_ITEM_SET == pNewFmt->GetItemState( RES_ANCHOR, sal_False, &pItem ))
+ {
+ pSet = new SfxItemSet( GetDoc()->GetAttrPool(), aFrmFmtSetRange );
+ pSet->Put( *pItem );
+ if( !::lcl_ChkAndSetNewAnchor( *pFly, *pSet ))
+ delete pSet, pSet = 0;
+ }
+
+ if( GetDoc()->SetFrmFmtToFly( *pFlyFmt, *pNewFmt, pSet, bKeepOrient ))
+ {
+ SwFlyFrm* pFrm = pFlyFmt->GetFrm( &aPt );
+ if( pFrm )
+ SelectFlyFrm( *pFrm, sal_True );
+ else
+ GetLayout()->SetAssertFlyPages();
+ }
+ if( pSet )
+ delete pSet;
+
+ EndAllActionAndCall();
+ }
+}
+
+/*************************************************************************
+|*
+|* SwFEShell::GetFlyFrmFmt()
+|*
+*************************************************************************/
+
+const SwFrmFmt* SwFEShell::GetFlyFrmFmt() const
+{
+ const SwFlyFrm* pFly = FindFlyFrm();
+ if ( !pFly )
+ {
+ SwFrm* pCurrFrm = GetCurrFrm();
+ pFly = pCurrFrm ? pCurrFrm->FindFlyFrm() : 0;
+ }
+ if( pFly )
+ return pFly->GetFmt();
+ return 0;
+}
+
+SwFrmFmt* SwFEShell::GetFlyFrmFmt()
+{
+ SwFlyFrm* pFly = FindFlyFrm();
+ if ( !pFly )
+ {
+ SwFrm* pCurrFrm = GetCurrFrm();
+ pFly = pCurrFrm ? pCurrFrm->FindFlyFrm() : 0;
+ }
+ if( pFly )
+ return pFly->GetFmt();
+ return 0;
+}
+
+/*************************************************************************
+|*
+|* SwFEShell::GetFlyRect()
+|*
+*************************************************************************/
+
+SwRect SwFEShell::GetFlyRect() const
+{
+ SwCntntFrm *pCntnt = GetCurrFrm( sal_False );
+ SwFlyFrm *pFly = pCntnt ? pCntnt->FindFlyFrm() : 0;
+ if ( !pFly )
+ {
+ SwRect aRect;
+ return aRect;
+ }
+ else
+ return pFly->Frm();
+}
+
+/*************************************************************************
+|*
+|* SwFEShell::GetObjRect()
+|*
+*************************************************************************/
+
+SwRect SwFEShell::GetObjRect() const
+{
+ if( Imp()->HasDrawView() )
+ return Imp()->GetDrawView()->GetAllMarkedRect();
+ else
+ {
+ SwRect aRect;
+ return aRect;
+ }
+}
+
+void SwFEShell::SetObjRect( const SwRect& rRect )
+{
+ if ( Imp()->HasDrawView() )
+ {
+ Imp()->GetDrawView()->SetAllMarkedRect( rRect.SVRect() );
+ CallChgLnk(); // rufe das AttrChangeNotify auf der UI-Seite.
+ }
+}
+
+/***********************************************************************
+#* Class : SwFEShell
+#* Methode : RequestObjectResize()
+#***********************************************************************/
+
+Size SwFEShell::RequestObjectResize( const SwRect &rRect, const uno::Reference < embed::XEmbeddedObject >& xObj )
+{
+ Size aResult;
+
+ SwFlyFrm *pFly = FindFlyFrm( xObj );
+ if ( !pFly )
+ {
+ aResult = rRect.SSize();
+ return aResult;
+ }
+
+ aResult = pFly->Prt().SSize();
+
+ sal_Bool bPosProt = pFly->GetFmt()->GetProtect().IsPosProtected();
+ sal_Bool bSizeProt = pFly->GetFmt()->GetProtect().IsSizeProtected();
+
+ StartAllAction();
+
+ //MA wir lassen den Fly nicht Clippen, damit die Ole-Server mit
+ //beliebigen Wuenschen kommen koennen. Die Formatierung uebernimmt das
+ //Clippen. Die richtige Darstellung wird per Scalierung erledigt.
+ //Die Scalierung wird von SwNoTxtFrm::Format durch einen Aufruf von
+ //SwWrtShell::CalcAndSetScale() erledigt.
+ if ( rRect.SSize() != pFly->Prt().SSize() && !bSizeProt )
+ {
+ Size aSz( rRect.SSize() );
+
+ //JP 28.02.2001: Task 74707 - ask for fly in fly with automatic size
+ //
+ const SwFrm* pAnchor;
+ const SwTxtNode* pTNd;
+ const SwpHints* pHts;
+ const SwFmtFrmSize& rFrmSz = pFly->GetFmt()->GetFrmSize();
+ if( bCheckForOLEInCaption &&
+ 0 != rFrmSz.GetWidthPercent() &&
+ 0 != (pAnchor = pFly->GetAnchorFrm()) &&
+ pAnchor->IsTxtFrm() &&
+ !pAnchor->GetNext() && !pAnchor->GetPrev() &&
+ pAnchor->GetUpper()->IsFlyFrm() &&
+ 0 != ( pTNd = ((SwTxtFrm*)pAnchor)->GetNode()->GetTxtNode()) &&
+ 0 != ( pHts = pTNd->GetpSwpHints() ))
+ {
+ // search for a sequence field:
+ const SfxPoolItem* pItem;
+ for( sal_uInt16 n = 0, nEnd = pHts->Count(); n < nEnd; ++n )
+ if( RES_TXTATR_FIELD == ( pItem =
+ &(*pHts)[ n ]->GetAttr())->Which() &&
+ TYP_SEQFLD == ((SwFmtFld*)pItem)->GetFld()->GetTypeId() )
+ {
+ // sequence field found
+ SwFlyFrm* pChgFly = (SwFlyFrm*)pAnchor->GetUpper();
+ // calculate the changed size:
+ // width must change, height can change
+ Size aNewSz( aSz.Width() + pChgFly->Frm().Width() -
+ pFly->Prt().Width(), aSz.Height() );
+
+ SwFrmFmt *pFmt = pChgFly->GetFmt();
+ SwFmtFrmSize aFrmSz( pFmt->GetFrmSize() );
+ aFrmSz.SetWidth( aNewSz.Width() );
+ if( ATT_MIN_SIZE != aFrmSz.GetHeightSizeType() )
+ {
+ aNewSz.Height() += pChgFly->Frm().Height() -
+ pFly->Prt().Height();
+ if( Abs( aNewSz.Height() - pChgFly->Frm().Height()) > 1 )
+ aFrmSz.SetHeight( aNewSz.Height() );
+ }
+ // uebers Doc fuers Undo!
+ pFmt->GetDoc()->SetAttr( aFrmSz, *pFmt );
+ break;
+ }
+ }
+
+ // set the new Size at the fly themself
+ if ( pFly->Prt().Height() > 0 && pFly->Prt().Width() > 0 )
+ {
+ aSz.Width() += pFly->Frm().Width() - pFly->Prt().Width();
+ aSz.Height()+= pFly->Frm().Height()- pFly->Prt().Height();
+ }
+ aResult = pFly->ChgSize( aSz );
+
+ //Wenn sich das Objekt aendert ist die Kontur hoechstwahrscheinlich daneben.
+ OSL_ENSURE( pFly->Lower()->IsNoTxtFrm(), "Request ohne NoTxt" );
+ SwNoTxtNode *pNd = ((SwCntntFrm*)pFly->Lower())->GetNode()->GetNoTxtNode();
+ OSL_ENSURE( pNd, "Request ohne Node" );
+ pNd->SetContour( 0 );
+ ClrContourCache();
+ }
+
+ //Wenn nur die Size angepasst werden soll, so wird eine Pos mit
+ //ausgezeichneten Werten transportiert.
+ Point aPt( pFly->Prt().Pos() );
+ aPt += pFly->Frm().Pos();
+ if ( rRect.Top() != LONG_MIN && rRect.Pos() != aPt && !bPosProt )
+ {
+ aPt = rRect.Pos();
+ aPt.X() -= pFly->Prt().Left();
+ aPt.Y() -= pFly->Prt().Top();
+ //Bei Absatzgebundenen Flys muss ausgehend von der neuen Position ein
+ //neuer Anker gesetzt werden. Anker und neue RelPos werden vom Fly
+ //selbst berechnet und gesetzt.
+ if( pFly->IsFlyAtCntFrm() )
+ ((SwFlyAtCntFrm*)pFly)->SetAbsPos( aPt );
+ else
+ {
+ const SwFrmFmt *pFmt = pFly->GetFmt();
+ const SwFmtVertOrient &rVert = pFmt->GetVertOrient();
+ const SwFmtHoriOrient &rHori = pFmt->GetHoriOrient();
+ const long lXDiff = aPt.X() - pFly->Frm().Left();
+ const long lYDiff = aPt.Y() - pFly->Frm().Top();
+ const Point aTmp( rHori.GetPos() + lXDiff,
+ rVert.GetPos() + lYDiff );
+ pFly->ChgRelPos( aTmp );
+ }
+ }
+
+ SwFlyFrmFmt *pFlyFrmFmt = pFly->GetFmt();
+ OSL_ENSURE( pFlyFrmFmt, "fly frame format missing!" );
+ if ( pFlyFrmFmt )
+ pFlyFrmFmt->SetLastFlyFrmPrtRectPos( pFly->Prt().Pos() ); //stores the value of last Prt rect
+
+ EndAllAction();
+
+ return aResult;
+}
+
+
+/***********************************************************************
+#* Class : SwFEShell
+#* Methode : WizzardFindCurFrmFmt
+#***********************************************************************/
+
+SwFrmFmt* SwFEShell::WizzardGetFly()
+{
+ // mal nicht uebers Layout den Fly suchen. Dann kann auch ohne gueltiges
+ // Layout ein Rahmen geloescht werden. ( z.B.: fuer die Wizard's )
+ SwSpzFrmFmts& rSpzArr = *pDoc->GetSpzFrmFmts();
+ sal_uInt16 nCnt = rSpzArr.Count();
+ if( nCnt )
+ {
+ SwNodeIndex& rCrsrNd = GetCrsr()->GetPoint()->nNode;
+ if( rCrsrNd.GetIndex() > pDoc->GetNodes().GetEndOfExtras().GetIndex() )
+ // Cusor steht im Body-Bereich!
+ return 0;
+
+ for( sal_uInt16 n = 0; n < nCnt; ++n )
+ {
+ SwFrmFmt* pFmt = rSpzArr[ n ];
+ const SwNodeIndex* pIdx = pFmt->GetCntnt( sal_False ).GetCntntIdx();
+ SwStartNode* pSttNd;
+ if( pIdx &&
+ 0 != ( pSttNd = pIdx->GetNode().GetStartNode() ) &&
+ pSttNd->GetIndex() < rCrsrNd.GetIndex() &&
+ rCrsrNd.GetIndex() < pSttNd->EndOfSectionIndex() )
+ {
+ // gefunden: also raus damit
+ return pFmt;
+ }
+ }
+ }
+ return 0;
+}
+
+void SwFEShell::SetFlyName( const String& rName )
+{
+ SwLayoutFrm *pFly = FindFlyFrm();
+ if( pFly )
+ GetDoc()->SetFlyName( *(SwFlyFrmFmt*)pFly->GetFmt(), rName );
+ else {
+ OSL_ENSURE( !this, "kein FlyFrame selektiert" );
+ }
+}
+
+const String& SwFEShell::GetFlyName() const
+{
+ SwLayoutFrm *pFly = FindFlyFrm();
+ if( pFly )
+ return pFly->GetFmt()->GetName();
+
+ OSL_ENSURE( !this, "kein FlyFrame selektiert" );
+ return aEmptyStr;
+}
+
+
+const uno::Reference < embed::XEmbeddedObject > SwFEShell::GetOleRef() const
+{
+ uno::Reference < embed::XEmbeddedObject > xObj;
+ SwFlyFrm * pFly = FindFlyFrm();
+ if (pFly && pFly->Lower() && pFly->Lower()->IsNoTxtFrm())
+ {
+ SwOLENode *pNd = ((SwNoTxtFrm*)pFly->Lower())->GetNode()->GetOLENode();
+ if (pNd)
+ xObj = pNd->GetOLEObj().GetOleRef();
+ }
+ return xObj;
+}
+
+
+String SwFEShell::GetUniqueGrfName() const
+{
+ return GetDoc()->GetUniqueGrfName();
+}
+
+const SwFrmFmt* SwFEShell::IsURLGrfAtPos( const Point& rPt, String* pURL,
+ String *pTargetFrameName,
+ String *pDescription ) const
+{
+ if( !Imp()->HasDrawView() )
+ return 0;
+
+ SdrObject* pObj;
+ SdrPageView* pPV;
+ const SwFrmFmt* pRet = 0;
+ SwDrawView *pDView = (SwDrawView*)Imp()->GetDrawView();
+
+ sal_uInt16 nOld = pDView->GetHitTolerancePixel();
+ pDView->SetHitTolerancePixel( 2 );
+
+ if( pDView->PickObj( rPt, pDView->getHitTolLog(), pObj, pPV,SDRSEARCH_PICKMACRO ) &&
+ pObj->ISA(SwVirtFlyDrawObj) )
+ {
+ SwFlyFrm *pFly = ((SwVirtFlyDrawObj*)pObj)->GetFlyFrm();
+ const SwFmtURL &rURL = pFly->GetFmt()->GetURL();
+ if( rURL.GetURL().Len() || rURL.GetMap() )
+ {
+ sal_Bool bSetTargetFrameName = pTargetFrameName != 0;
+ sal_Bool bSetDescription = pDescription != 0;
+ if ( rURL.GetMap() )
+ {
+ IMapObject *pObject = pFly->GetFmt()->GetIMapObject( rPt, pFly );
+ if ( pObject && pObject->GetURL().Len() )
+ {
+ if( pURL )
+ *pURL = pObject->GetURL();
+ if ( bSetTargetFrameName && pObject->GetTarget().Len() )
+ {
+ bSetTargetFrameName = sal_False;
+ *pTargetFrameName = pObject->GetTarget();
+ }
+ if ( bSetDescription )
+ {
+ bSetDescription = sal_False;
+ *pDescription = pObject->GetAltText();
+ }
+ pRet = pFly->GetFmt();
+ }
+ }
+ else
+ {
+ if( pURL )
+ {
+ *pURL = rURL.GetURL();
+ if( rURL.IsServerMap() )
+ {
+ // dann die rel. Pixel Position anhaengen !!
+ Point aPt( rPt );
+ aPt -= pFly->Frm().Pos();
+ // ohne MapMode-Offset, ohne Offset, o ... !!!!!
+ aPt = GetOut()->LogicToPixel(
+ aPt, MapMode( MAP_TWIP ) );
+ ((( *pURL += '?' ) += String::CreateFromInt32( aPt.X() ))
+ += ',' ) += String::CreateFromInt32(aPt.Y() );
+ }
+ }
+ pRet = pFly->GetFmt();
+ }
+ if ( bSetTargetFrameName )
+ *pTargetFrameName = rURL.GetTargetFrameName();
+ if ( bSetDescription )
+ *pDescription = pFly->GetFmt()->GetName();
+ }
+ }
+ pDView->SetHitTolerancePixel( nOld );
+ return pRet;
+}
+
+const Graphic *SwFEShell::GetGrfAtPos( const Point &rPt,
+ String &rName, sal_Bool &rbLink ) const
+{
+ if( !Imp()->HasDrawView() )
+ return 0;
+
+ SdrObject* pObj;
+ SdrPageView* pPV;
+ SwDrawView *pDView = (SwDrawView*)Imp()->GetDrawView();
+
+ if( pDView->PickObj( rPt, pDView->getHitTolLog(), pObj, pPV ) && pObj->ISA(SwVirtFlyDrawObj) )
+ {
+ SwFlyFrm *pFly = ((SwVirtFlyDrawObj*)pObj)->GetFlyFrm();
+ if ( pFly->Lower() && pFly->Lower()->IsNoTxtFrm() )
+ {
+ SwGrfNode *pNd = ((SwCntntFrm*)pFly->Lower())->GetNode()->GetGrfNode();
+ if ( pNd )
+ {
+ if ( pNd->IsGrfLink() )
+ {
+ //Halbfertige Grafik?
+ ::sfx2::SvLinkSource* pLnkObj = pNd->GetLink()->GetObj();
+ if( pLnkObj && pLnkObj->IsPending() )
+ return 0;
+ rbLink = sal_True;
+ }
+
+ pNd->GetFileFilterNms( &rName, 0 );
+ if ( !rName.Len() )
+ rName = pFly->GetFmt()->GetName();
+ pNd->SwapIn( sal_True );
+ return &pNd->GetGrf();
+ }
+ }
+ }
+ return 0;
+}
+
+
+const SwFrmFmt* SwFEShell::GetFmtFromObj( const Point& rPt, SwRect** pRectToFill ) const
+{
+ SwFrmFmt* pRet = 0;
+
+ if( Imp()->HasDrawView() )
+ {
+ SdrObject* pObj;
+ SdrPageView* pPView;
+
+ SwDrawView *pDView = (SwDrawView*)Imp()->GetDrawView();
+
+ sal_uInt16 nOld = pDView->GetHitTolerancePixel();
+ // Tattergrenze fuer Drawing-SS
+ pDView->SetHitTolerancePixel( pDView->GetMarkHdlSizePixel()/2 );
+
+ if( pDView->PickObj( rPt, pDView->getHitTolLog(), pObj, pPView, SDRSEARCH_PICKMARKABLE ) )
+ {
+ // dann teste mal was es ist:
+ if ( pObj->ISA(SwVirtFlyDrawObj) )
+ pRet = ((SwVirtFlyDrawObj*)pObj)->GetFmt();
+ else if ( pObj->GetUserCall() ) //nicht fuer Gruppenobjekte
+ pRet = ((SwDrawContact*)pObj->GetUserCall())->GetFmt();
+ if(pRet && pRectToFill)
+ **pRectToFill = pObj->GetCurrentBoundRect();
+ }
+ pDView->SetHitTolerancePixel( nOld );
+ }
+ return pRet;
+}
+
+// returns a format too, if the point is over the text of any fly
+const SwFrmFmt* SwFEShell::GetFmtFromAnyObj( const Point& rPt ) const
+{
+ const SwFrmFmt* pRet = GetFmtFromObj( rPt );
+ if( !pRet || RES_FLYFRMFMT == pRet->Which() )
+ {
+ SwPosition aPos( *GetCrsr()->GetPoint() );
+ Point aPt( rPt );
+ GetLayout()->GetCrsrOfst( &aPos, aPt );
+ SwCntntNode *pNd = aPos.nNode.GetNode().GetCntntNode();
+ SwFrm* pFrm = pNd->getLayoutFrm( GetLayout(), &rPt, 0, sal_False )->FindFlyFrm();
+ pRet = pFrm ? ((SwLayoutFrm*)pFrm)->GetFmt() : 0;
+ }
+ return pRet;
+}
+
+ObjCntType SwFEShell::GetObjCntType( const SdrObject& rObj ) const
+{
+ ObjCntType eType = OBJCNT_NONE;
+
+ // investigate 'master' drawing object, if method
+ // is called for a 'virtual' drawing object.
+ const SdrObject* pInvestigatedObj;
+ if ( rObj.ISA(SwDrawVirtObj) )
+ {
+ const SwDrawVirtObj* pDrawVirtObj = static_cast<const SwDrawVirtObj*>(&rObj);
+ pInvestigatedObj = &(pDrawVirtObj->GetReferencedObj());
+ }
+ else
+ {
+ pInvestigatedObj = &rObj;
+ }
+
+ if( FmFormInventor == pInvestigatedObj->GetObjInventor() )
+ {
+ eType = OBJCNT_CONTROL;
+ uno::Reference< awt::XControlModel > xModel =
+ ((SdrUnoObj&)(*pInvestigatedObj)).GetUnoControlModel();
+ if( xModel.is() )
+ {
+ uno::Any aVal;
+ OUString sName(RTL_CONSTASCII_USTRINGPARAM("ButtonType"));
+ uno::Reference< beans::XPropertySet > xSet(xModel, uno::UNO_QUERY);
+
+ uno::Reference< beans::XPropertySetInfo > xInfo = xSet->getPropertySetInfo();
+ if(xInfo->hasPropertyByName( sName ))
+ {
+ beans::Property xProperty = xInfo->getPropertyByName( sName );
+ aVal = xSet->getPropertyValue( sName );
+ if( aVal.getValue() && form::FormButtonType_URL == *((form::FormButtonType*)aVal.getValue()) )
+ eType = OBJCNT_URLBUTTON;
+ }
+ }
+ }
+ else if( pInvestigatedObj->ISA(SwVirtFlyDrawObj) )
+ {
+ SwFlyFrm *pFly = ((SwVirtFlyDrawObj&)(*pInvestigatedObj)).GetFlyFrm();
+ if ( pFly->Lower() && pFly->Lower()->IsNoTxtFrm() )
+ {
+ if ( ((SwCntntFrm*)pFly->Lower())->GetNode()->GetGrfNode() )
+ eType = OBJCNT_GRF;
+ else
+ eType = OBJCNT_OLE;
+ }
+ else
+ eType = OBJCNT_FLY;
+ }
+ else if ( pInvestigatedObj->ISA( SdrObjGroup ) )
+ {
+ SwDrawContact* pDrawContact( dynamic_cast<SwDrawContact*>(GetUserCall( pInvestigatedObj ) ) );
+ if ( !pDrawContact )
+ {
+ OSL_FAIL( "<SwFEShell::GetObjCntType(..)> - missing draw contact object" );
+ eType = OBJCNT_NONE;
+ }
+ else
+ {
+ SwFrmFmt* pFrmFmt( pDrawContact->GetFmt() );
+ if ( !pFrmFmt )
+ {
+ OSL_FAIL( "<SwFEShell::GetObjCntType(..)> - missing frame format" );
+ eType = OBJCNT_NONE;
+ }
+ else if ( FLY_AS_CHAR != pFrmFmt->GetAnchor().GetAnchorId() )
+ {
+ eType = OBJCNT_GROUPOBJ;
+ }
+ }
+ }
+ else
+ eType = OBJCNT_SIMPLE;
+ return eType;
+}
+
+ObjCntType SwFEShell::GetObjCntType( const Point &rPt, SdrObject *&rpObj ) const
+{
+ ObjCntType eType = OBJCNT_NONE;
+
+ if( Imp()->HasDrawView() )
+ {
+ SdrObject* pObj;
+ SdrPageView* pPView;
+
+ SwDrawView *pDView = (SwDrawView*)Imp()->GetDrawView();
+
+ sal_uInt16 nOld = pDView->GetHitTolerancePixel();
+ // Tattergrenze fuer Drawing-SS
+ pDView->SetHitTolerancePixel( pDView->GetMarkHdlSizePixel()/2 );
+
+ if( pDView->PickObj( rPt, pDView->getHitTolLog(), pObj, pPView, SDRSEARCH_PICKMARKABLE ) )
+ eType = GetObjCntType( *(rpObj = pObj) );
+
+ pDView->SetHitTolerancePixel( nOld );
+ }
+ return eType;
+}
+
+ObjCntType SwFEShell::GetObjCntTypeOfSelection( SdrObject** ppObj ) const
+{
+ ObjCntType eType = OBJCNT_NONE;
+
+ if( Imp()->HasDrawView() )
+ {
+ const SdrMarkList &rMrkList = Imp()->GetDrawView()->GetMarkedObjectList();
+ for( sal_uInt32 i = 0, nE = rMrkList.GetMarkCount(); i < nE; ++i )
+ {
+ SdrObject* pObj = rMrkList.GetMark( i )->GetMarkedSdrObj();
+ if( !pObj )
+ continue;
+ ObjCntType eTmp = GetObjCntType( *pObj );
+ if( !i )
+ {
+ eType = eTmp;
+ if( ppObj ) *ppObj = pObj;
+ }
+ else if( eTmp != eType )
+ {
+ eType = OBJCNT_DONTCARE;
+ // einmal DontCare, immer DontCare!
+ break;
+ }
+ }
+ }
+ return eType;
+}
+
+
+sal_Bool SwFEShell::ReplaceSdrObj( const String& rGrfName, const String& rFltName,
+ const Graphic* pGrf )
+{
+ SET_CURR_SHELL( this );
+
+ sal_Bool bRet = sal_False;
+ const SdrMarkList *pMrkList;
+ if( Imp()->HasDrawView() && 1 ==
+ ( pMrkList = &Imp()->GetDrawView()->GetMarkedObjectList())->GetMarkCount() )
+ {
+ SdrObject* pObj = pMrkList->GetMark( 0 )->GetMarkedSdrObj();
+ SwFrmFmt *pFmt = FindFrmFmt( pObj );
+
+ // Attribute sichern und dann an der Grafik setzen
+ SfxItemSet aFrmSet( pDoc->GetAttrPool(),
+ pFmt->GetAttrSet().GetRanges() );
+ aFrmSet.Set( pFmt->GetAttrSet() );
+
+ // Groesse und Position setzen ??
+ if( !pObj->ISA(SwVirtFlyDrawObj) )
+ {
+ // dann mal los:
+ const Rectangle &rBound = pObj->GetSnapRect();
+ Point aRelPos( pObj->GetRelativePos() );
+
+ const long nWidth = rBound.Right() - rBound.Left();
+ const long nHeight= rBound.Bottom() - rBound.Top();
+ aFrmSet.Put( SwFmtFrmSize( ATT_MIN_SIZE,
+ Max( nWidth, long(MINFLY) ),
+ Max( nHeight, long(MINFLY) )));
+
+ if( SFX_ITEM_SET != aFrmSet.GetItemState( RES_HORI_ORIENT ))
+ aFrmSet.Put( SwFmtHoriOrient( aRelPos.X(), text::HoriOrientation::NONE, text::RelOrientation::FRAME ));
+
+ if( SFX_ITEM_SET != aFrmSet.GetItemState( RES_VERT_ORIENT ))
+ aFrmSet.Put( SwFmtVertOrient( aRelPos.Y(), text::VertOrientation::NONE, text::RelOrientation::FRAME ));
+
+ }
+
+ pObj->GetOrdNum();
+
+ StartAllAction();
+ StartUndo();
+
+ // das "Sdr-Object" loeschen und dafuer die Grafik einfuegen
+ DelSelectedObj();
+
+ pFmt = GetDoc()->Insert( *GetCrsr(), rGrfName, rFltName, pGrf, &aFrmSet, NULL, NULL );
+
+ EndUndo();
+ EndAllAction();
+ bRet = sal_True;
+ }
+ return bRet;
+}
+
+static sal_uInt16 SwFmtGetPageNum(const SwFlyFrmFmt * pFmt)
+{
+ OSL_ENSURE(pFmt != NULL, "invalid argument");
+
+ SwFlyFrm * pFrm = pFmt->GetFrm();
+
+ sal_uInt16 aResult;
+
+ if (pFrm != NULL)
+ aResult = pFrm->GetPhyPageNum();
+ else
+ aResult = pFmt->GetAnchor().GetPageNum();
+
+ return aResult;
+}
+
+#include <fmtcnct.hxx>
+
+void SwFEShell::GetConnectableFrmFmts(SwFrmFmt & rFmt,
+ const String & rReference,
+ sal_Bool bSuccessors,
+ ::std::vector< String > & aPrevPageVec,
+ ::std::vector< String > & aThisPageVec,
+ ::std::vector< String > & aNextPageVec,
+ ::std::vector< String > & aRestVec)
+{
+ StartAction();
+
+ SwFmtChain rChain = rFmt.GetChain();
+ SwFrmFmt * pOldChainNext = (SwFrmFmt *) rChain.GetNext();
+ SwFrmFmt * pOldChainPrev = (SwFrmFmt *) rChain.GetPrev();
+
+ if (pOldChainNext)
+ pDoc->Unchain(rFmt);
+
+ if (pOldChainPrev)
+ pDoc->Unchain(*pOldChainPrev);
+
+ sal_uInt16 nCnt = pDoc->GetFlyCount(FLYCNTTYPE_FRM);
+
+ /* potential successors resp. predecessors */
+ ::std::vector< const SwFrmFmt * > aTmpSpzArray;
+
+ (SwFrmFmt *) pDoc->FindFlyByName(rReference);
+
+ for (sal_uInt16 n = 0; n < nCnt; n++)
+ {
+ const SwFrmFmt & rFmt1 = *(pDoc->GetFlyNum(n, FLYCNTTYPE_FRM));
+
+ /*
+ pFmt is a potential successor of rFmt if it is chainable after
+ rFmt.
+
+ pFmt is a potential predecessor of rFmt if rFmt is chainable
+ after pFmt.
+ */
+
+ int nChainState;
+
+ if (bSuccessors)
+ nChainState = pDoc->Chainable(rFmt, rFmt1);
+ else
+ nChainState = pDoc->Chainable(rFmt1, rFmt);
+
+ if (nChainState == SW_CHAIN_OK)
+ {
+ aTmpSpzArray.push_back(&rFmt1);
+
+ }
+
+ }
+
+ if (aTmpSpzArray.size() > 0)
+ {
+ aPrevPageVec.clear();
+ aThisPageVec.clear();
+ aNextPageVec.clear();
+ aRestVec.clear();
+
+ /* number of page rFmt resides on */
+ sal_uInt16 nPageNum = SwFmtGetPageNum((SwFlyFrmFmt *) &rFmt);
+
+ ::std::vector< const SwFrmFmt * >::const_iterator aIt;
+
+ for (aIt = aTmpSpzArray.begin(); aIt != aTmpSpzArray.end(); aIt++)
+ {
+ String aString = (*aIt)->GetName();
+
+ /* rFmt is not a vaild successor or predecessor of
+ itself */
+ if (aString != rReference && aString != rFmt.GetName())
+ {
+ sal_uInt16 nNum1 =
+ SwFmtGetPageNum((SwFlyFrmFmt *) *aIt);
+
+ if (nNum1 == nPageNum -1)
+ aPrevPageVec.push_back(aString);
+ else if (nNum1 == nPageNum)
+ aThisPageVec.push_back(aString);
+ else if (nNum1 == nPageNum + 1)
+ aNextPageVec.push_back(aString);
+ else
+ aRestVec.push_back(aString);
+ }
+ }
+
+ }
+
+ if (pOldChainNext)
+ pDoc->Chain(rFmt, *pOldChainNext);
+
+ if (pOldChainPrev)
+ pDoc->Chain(*pOldChainPrev, rFmt);
+
+ EndAction();
+}
+
+// --> OD 2009-07-13 #i73249#
+const String SwFEShell::GetObjTitle() const
+{
+ String aTitle;
+
+ if ( Imp()->HasDrawView() )
+ {
+ const SdrMarkList *pMrkList = &Imp()->GetDrawView()->GetMarkedObjectList();
+ if ( pMrkList->GetMarkCount() == 1 )
+ {
+ const SdrObject* pObj = pMrkList->GetMark( 0 )->GetMarkedSdrObj();
+ const SwFrmFmt* pFmt = FindFrmFmt( pObj );
+ if ( pFmt->Which() == RES_FLYFRMFMT )
+ {
+ aTitle = dynamic_cast<const SwFlyFrmFmt*>(pFmt)->GetObjTitle();
+ }
+ else
+ {
+ aTitle = pObj->GetTitle();
+ }
+ }
+ }
+
+ return aTitle;
+}
+
+void SwFEShell::SetObjTitle( const String& rTitle )
+{
+ if ( Imp()->HasDrawView() )
+ {
+ const SdrMarkList *pMrkList = &Imp()->GetDrawView()->GetMarkedObjectList();
+ if ( pMrkList->GetMarkCount() == 1 )
+ {
+ SdrObject* pObj = pMrkList->GetMark( 0 )->GetMarkedSdrObj();
+ SwFrmFmt* pFmt = FindFrmFmt( pObj );
+ if ( pFmt->Which() == RES_FLYFRMFMT )
+ {
+ GetDoc()->SetFlyFrmTitle( *(dynamic_cast<SwFlyFrmFmt*>(pFmt)),
+ rTitle );
+ }
+ else
+ {
+ pObj->SetTitle( rTitle );
+ }
+ }
+ }
+}
+
+const String SwFEShell::GetObjDescription() const
+{
+ String aDescription;
+
+ if ( Imp()->HasDrawView() )
+ {
+ const SdrMarkList *pMrkList = &Imp()->GetDrawView()->GetMarkedObjectList();
+ if ( pMrkList->GetMarkCount() == 1 )
+ {
+ const SdrObject* pObj = pMrkList->GetMark( 0 )->GetMarkedSdrObj();
+ const SwFrmFmt* pFmt = FindFrmFmt( pObj );
+ if ( pFmt->Which() == RES_FLYFRMFMT )
+ {
+ aDescription = dynamic_cast<const SwFlyFrmFmt*>(pFmt)->GetObjDescription();
+ }
+ else
+ {
+ aDescription = pObj->GetDescription();
+ }
+ }
+ }
+
+ return aDescription;
+}
+
+void SwFEShell::SetObjDescription( const String& rDescription )
+{
+ if ( Imp()->HasDrawView() )
+ {
+ const SdrMarkList *pMrkList = &Imp()->GetDrawView()->GetMarkedObjectList();
+ if ( pMrkList->GetMarkCount() == 1 )
+ {
+ SdrObject* pObj = pMrkList->GetMark( 0 )->GetMarkedSdrObj();
+ SwFrmFmt* pFmt = FindFrmFmt( pObj );
+ if ( pFmt->Which() == RES_FLYFRMFMT )
+ {
+ GetDoc()->SetFlyFrmDescription( *(dynamic_cast<SwFlyFrmFmt*>(pFmt)),
+ rDescription );
+ }
+ else
+ {
+ pObj->SetDescription( rDescription );
+ }
+ }
+ }
+}
+
+
+void SwFEShell::AlignFormulaToBaseline( const uno::Reference < embed::XEmbeddedObject >& xObj, SwFlyFrm * pFly )
+{
+#if OSL_DEBUG_LEVEL > 1
+ SvGlobalName aCLSID( xObj->getClassID() );
+ const bool bStarMath = ( SotExchange::IsMath( aCLSID ) != 0 );
+ OSL_ENSURE( bStarMath, "AlignFormulaToBaseline should only be called for Math objects" );
+
+ if ( !bStarMath )
+ return;
+#endif
+
+ if (!pFly)
+ pFly = FindFlyFrm( xObj );
+ OSL_ENSURE( pFly , "No fly frame!" );
+ SwFrmFmt * pFrmFmt = pFly ? pFly->GetFmt() : 0;
+
+ // baseline to baseline alignment should only be applied to formulas anchored as char
+ if ( pFly && pFrmFmt && FLY_AS_CHAR == pFrmFmt->GetAnchor().GetAnchorId() )
+ {
+ // get baseline from Math object
+ uno::Any aBaseline;
+ if( svt::EmbeddedObjectRef::TryRunningState( xObj ) )
+ {
+ uno::Reference < beans::XPropertySet > xSet( xObj->getComponent(), uno::UNO_QUERY );
+ if ( xSet.is() )
+ {
+ try
+ {
+ aBaseline = xSet->getPropertyValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("BaseLine") ) );
+ }
+ catch ( uno::Exception& )
+ {
+ OSL_FAIL( "Baseline could not be retrieved from Starmath!" );
+ }
+ }
+ }
+
+ sal_Int32 nBaseline = ::comphelper::getINT32(aBaseline);
+ const MapMode aSourceMapMode( MAP_100TH_MM );
+ const MapMode aTargetMapMode( MAP_TWIP );
+ nBaseline = OutputDevice::LogicToLogic( nBaseline, aSourceMapMode.GetMapUnit(), aTargetMapMode.GetMapUnit() );
+
+ OSL_ENSURE( nBaseline > 0, "Wrong value of Baseline while retrieving from Starmath!" );
+ //nBaseline must be moved by aPrt position
+ const SwFlyFrmFmt *pFlyFrmFmt = pFly->GetFmt();
+ OSL_ENSURE( pFlyFrmFmt, "fly frame format missing!" );
+ if ( pFlyFrmFmt )
+ nBaseline += pFlyFrmFmt->GetLastFlyFrmPrtRectPos().Y();
+
+ const SwFmtVertOrient &rVert = pFrmFmt->GetVertOrient();
+ SwFmtVertOrient aVert( rVert );
+ aVert.SetPos( -nBaseline );
+ aVert.SetVertOrient( com::sun::star::text::VertOrientation::NONE );
+
+ pFrmFmt->LockModify();
+ pFrmFmt->SetFmtAttr( aVert );
+ pFrmFmt->UnlockModify();
+ pFly->InvalidatePos();
+ }
+}
+
+
+void SwFEShell::AlignAllFormulasToBaseline()
+{
+ StartAllAction();
+
+ SwStartNode *pStNd;
+ SwNodeIndex aIdx( *GetNodes().GetEndOfAutotext().StartOfSectionNode(), 1 );
+ while ( 0 != (pStNd = aIdx.GetNode().GetStartNode()) )
+ {
+ ++aIdx;
+ SwOLENode *pOleNode = dynamic_cast< SwOLENode * >( &aIdx.GetNode() );
+ if ( pOleNode )
+ {
+ const uno::Reference < embed::XEmbeddedObject > & xObj( pOleNode->GetOLEObj().GetOleRef() );
+ if (xObj.is())
+ {
+ SvGlobalName aCLSID( xObj->getClassID() );
+ if ( SotExchange::IsMath( aCLSID ) )
+ AlignFormulaToBaseline( xObj );
+ }
+ }
+
+ aIdx.Assign( *pStNd->EndOfSectionNode(), + 1 );
+ }
+
+ EndAllAction();
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/frmedt/feflyole.cxx b/sw/source/core/frmedt/feflyole.cxx
new file mode 100644
index 000000000000..2de80477cd85
--- /dev/null
+++ b/sw/source/core/frmedt/feflyole.cxx
@@ -0,0 +1,151 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+#include <com/sun/star/embed/EmbedStates.hpp>
+
+#include <sfx2/ipclient.hxx>
+#include <sfx2/viewsh.hxx>
+#include <sfx2/app.hxx>
+#include <unotools/moduleoptions.hxx>
+#include <sfx2/viewfrm.hxx>
+
+#include <sot/exchange.hxx>
+#include <fmtcntnt.hxx>
+#include <fmtanchr.hxx>
+#include <fesh.hxx>
+#include <cntfrm.hxx>
+#include <frmfmt.hxx>
+#include <flyfrm.hxx>
+#include <pam.hxx>
+#include <doc.hxx>
+#include <ndtxt.hxx>
+#include <notxtfrm.hxx>
+#include <ndole.hxx>
+#include <swcli.hxx>
+
+using namespace com::sun::star;
+
+SwFlyFrm *SwFEShell::FindFlyFrm( const uno::Reference < embed::XEmbeddedObject >& xObj ) const
+{
+ SwFlyFrm *pFly = FindFlyFrm();
+ if ( pFly && pFly->Lower() && pFly->Lower()->IsNoTxtFrm() )
+ {
+ SwOLENode *pNd = ((SwNoTxtFrm*)pFly->Lower())->GetNode()->GetOLENode();
+ if ( !pNd || pNd->GetOLEObj().GetOleRef() != xObj )
+ pFly = 0;
+ }
+ else
+ pFly = 0;
+
+ if ( !pFly )
+ {
+ //Kein Fly oder der falsche selektiert. Ergo muessen wir leider suchen.
+ sal_Bool bExist = sal_False;
+ SwStartNode *pStNd;
+ sal_uLong nSttIdx = GetNodes().GetEndOfAutotext().StartOfSectionIndex() + 1,
+ nEndIdx = GetNodes().GetEndOfAutotext().GetIndex();
+ while( nSttIdx < nEndIdx &&
+ 0 != (pStNd = GetNodes()[ nSttIdx ]->GetStartNode()) )
+ {
+ SwNode *pNd = GetNodes()[ nSttIdx+1 ];
+ if ( pNd->IsOLENode() &&
+ ((SwOLENode*)pNd)->GetOLEObj().GetOleRef() == xObj )
+ {
+ bExist = sal_True;
+ SwFrm *pFrm = ((SwOLENode*)pNd)->getLayoutFrm( GetLayout() );
+ if ( pFrm )
+ pFly = pFrm->FindFlyFrm();
+ break;
+ }
+ nSttIdx = pStNd->EndOfSectionIndex() + 1;
+ }
+
+ OSL_ENSURE( bExist, "OLE-Object unknown and FlyFrm not found." );
+ (void)bExist;
+ }
+ return pFly;
+}
+
+
+String SwFEShell::GetUniqueOLEName() const
+{
+ return GetDoc()->GetUniqueOLEName();
+}
+
+
+String SwFEShell::GetUniqueFrameName() const
+{
+ return GetDoc()->GetUniqueFrameName();
+}
+
+
+void SwFEShell::MakeObjVisible( const uno::Reference < embed::XEmbeddedObject >& xObj ) const
+{
+ SwFlyFrm *pFly = FindFlyFrm( xObj );
+ if ( pFly )
+ {
+ SwRect aTmp( pFly->Prt() );
+ aTmp += pFly->Frm().Pos();
+ if ( !aTmp.IsOver( VisArea() ) )
+ {
+ ((SwFEShell*)this)->StartAction();
+ ((SwFEShell*)this)->MakeVisible( aTmp );
+ ((SwFEShell*)this)->EndAction();
+ }
+ }
+}
+
+sal_Bool SwFEShell::FinishOLEObj() // Server wird beendet
+{
+ SfxInPlaceClient* pIPClient = GetSfxViewShell()->GetIPClient();
+ if ( !pIPClient )
+ return sal_False;
+
+ sal_Bool bRet = pIPClient->IsObjectInPlaceActive();
+ if( bRet )
+ {
+ uno::Reference < embed::XEmbeddedObject > xObj = pIPClient->GetObject();
+ if( CNT_OLE == GetCntType() )
+ ClearAutomaticContour();
+
+ if( ((SwOleClient*)pIPClient)->IsCheckForOLEInCaption() !=
+ IsCheckForOLEInCaption() )
+ SetCheckForOLEInCaption( !IsCheckForOLEInCaption() );
+
+ // leave UIActive state
+ pIPClient->DeactivateObject();
+ }
+ return bRet;
+}
+
+
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/frmedt/feshview.cxx b/sw/source/core/frmedt/feshview.cxx
new file mode 100644
index 000000000000..693fe638532a
--- /dev/null
+++ b/sw/source/core/frmedt/feshview.cxx
@@ -0,0 +1,3111 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+#include <com/sun/star/embed/EmbedMisc.hpp>
+
+#include "hintids.hxx"
+
+#include <svx/sdrobjectfilter.hxx>
+#include <svx/svditer.hxx>
+#include <svx/svdobj.hxx>
+#include <svx/svdouno.hxx>
+#include <svx/svdoole2.hxx>
+#include <svx/svdogrp.hxx>
+#include <svx/svdocirc.hxx>
+#include <svx/svdopath.hxx>
+#include <svx/sxciaitm.hxx>
+#include <svx/xfillit.hxx>
+#include <svx/svdocapt.hxx>
+#include <sfx2/app.hxx>
+#include <editeng/boxitem.hxx>
+#include <editeng/opaqitem.hxx>
+#include <editeng/protitem.hxx>
+#include <svx/svdpage.hxx>
+#include <svx/svdpagv.hxx>
+#include <IDocumentSettingAccess.hxx>
+#include <cmdid.h>
+#include <poolfmt.hrc> // fuer InitFldTypes
+#include <frmfmt.hxx>
+#include <frmatr.hxx>
+#include <fmtfsize.hxx>
+#include <fmtanchr.hxx>
+#include <fmtornt.hxx>
+#include <fmtsrnd.hxx>
+#include <fmtcntnt.hxx>
+#include <fmtflcnt.hxx>
+#include <fmtcnct.hxx>
+#include <docary.hxx>
+#include <tblsel.hxx>
+#include <swtable.hxx>
+#include <flyfrms.hxx>
+#include "fesh.hxx"
+#include "rootfrm.hxx"
+#include "pagefrm.hxx"
+#include "sectfrm.hxx"
+#include "doc.hxx"
+#include <IDocumentUndoRedo.hxx>
+#include "dview.hxx"
+#include "dflyobj.hxx"
+#include "dcontact.hxx"
+#include "viewimp.hxx"
+#include "flyfrm.hxx"
+#include "pam.hxx"
+#include "ndole.hxx"
+#include "ndgrf.hxx"
+#include "ndtxt.hxx"
+#include "viewopt.hxx" // fuer GetHTMLMode
+#include "swundo.hxx"
+#include "notxtfrm.hxx"
+#include "txtfrm.hxx"
+#include "txatbase.hxx"
+#include "mdiexp.hxx" // fuer Update der Statuszeile bei drag
+#include <sortedobjs.hxx>
+#include <HandleAnchorNodeChg.hxx>
+#include <basegfx/polygon/b2dpolygon.hxx>
+#include <switerator.hxx>
+
+#define SCROLLVAL 75
+
+using namespace com::sun::star;
+
+//Tattergrenze fuer Drawing-SS
+#define MINMOVE ((sal_uInt16)GetOut()->PixelToLogic(Size(Imp()->GetDrawView()->GetMarkHdlSizePixel()/2,0)).Width())
+
+SwFlyFrm *GetFlyFromMarked( const SdrMarkList *pLst, ViewShell *pSh )
+{
+ if ( !pLst )
+ pLst = pSh->HasDrawView() ? &pSh->Imp()->GetDrawView()->GetMarkedObjectList():0;
+
+ if ( pLst && pLst->GetMarkCount() == 1 )
+ {
+ SdrObject *pO = pLst->GetMark( 0 )->GetMarkedSdrObj();
+ if ( pO && pO->ISA(SwVirtFlyDrawObj) )
+ return ((SwVirtFlyDrawObj*)pO)->GetFlyFrm();
+ }
+ return 0;
+}
+
+void lcl_GrabCursor( SwFEShell* pSh, SwFlyFrm* pOldSelFly)
+{
+ const SwFrmFmt *pFlyFmt = pSh->SelFlyGrabCrsr();
+ if( pFlyFmt && !pSh->ActionPend() &&
+ (!pOldSelFly || pOldSelFly->GetFmt() != pFlyFmt) )
+ {
+ // dann das evt. gesetzte Macro rufen
+ pSh->GetFlyMacroLnk().Call( (void*)pFlyFmt );
+extern sal_Bool bNoInterrupt; // in swapp.cxx
+ // wir in dem Makro ein Dialog gestartet, dann kommt das
+ // MouseButtonUp zu diesem und nicht zu uns. Dadurch ist
+ // Flag bei uns immer gesetzt und schaltet nie die auf die
+ // entsp. Shell um !!!!!!!
+ bNoInterrupt = sal_False;
+ }
+ else if( !pFlyFmt || RES_DRAWFRMFMT == pFlyFmt->Which() )
+ {
+ // --> assure consistent cursor
+ pSh->KillPams();
+ pSh->ClearMark();
+ // <--
+ pSh->SetCrsr( pSh->Imp()->GetDrawView()->GetAllMarkedRect().TopLeft(), sal_True);
+ }
+}
+
+/*************************************************************************
+|*
+|* SwFEShell::SelectObj()
+*************************************************************************/
+
+sal_Bool SwFEShell::SelectObj( const Point& rPt, sal_uInt8 nFlag, SdrObject *pObj )
+{
+ SwDrawView *pDView = Imp()->GetDrawView();
+ if(!pDView)
+ return sal_False;
+ SET_CURR_SHELL( this );
+ StartAction(); //Aktion ist Notwendig, damit nicht mehrere
+ //AttrChgdNotify (etwa durch Unmark->MarkListHasChgd)
+ //durchkommen
+
+ const SdrMarkList &rMrkList = pDView->GetMarkedObjectList();
+ const sal_Bool bHadSelection = rMrkList.GetMarkCount() ? sal_True : sal_False;
+ const sal_Bool bAddSelect = 0 != (SW_ADD_SELECT & nFlag);
+ const sal_Bool bEnterGroup = 0 != (SW_ENTER_GROUP & nFlag);
+ SwFlyFrm* pOldSelFly = 0;
+ const Point aOldPos( pDView->GetAllMarkedRect().TopLeft() );
+
+ if( bHadSelection )
+ {
+ //Unmark rufen wenn !bAddSelect oder wenn ein Fly selektiert ist.
+ sal_Bool bUnmark = !bAddSelect;
+
+ if ( rMrkList.GetMarkCount() == 1 )
+ {
+ //Wenn ein Fly selektiert ist, so muss er erst deselektiert werden.
+ pOldSelFly = ::GetFlyFromMarked( &rMrkList, this );
+ if ( pOldSelFly )
+ {
+ const sal_uInt16 nType = GetCntType();
+ if( nType != CNT_TXT || (SW_LEAVE_FRAME & nFlag) ||
+ ( pOldSelFly->GetFmt()->GetProtect().IsCntntProtected()
+ && !IsReadOnlyAvailable() ))
+ {
+ //Wenn ein Fly deselektiert wird, der Grafik, Ole o.ae.
+ //enthaelt, so muss der Crsr aus diesem entfernt werden.
+ //Desgleichen wenn ein Fly mit geschuetztem Inhalt deselektiert
+ //wird. Der Einfachheit halber wire der Crsr 'grad so neben die
+ //linke obere Ecke gesetzt.
+ Point aPt( pOldSelFly->Frm().Pos() );
+ aPt.X() -= 1;
+ sal_Bool bUnLockView = !IsViewLocked();
+ LockView( sal_True );
+ SetCrsr( aPt, sal_True );
+ if( bUnLockView )
+ LockView( sal_False );
+ }
+ if ( nType & CNT_GRF &&
+ ((SwNoTxtFrm*)pOldSelFly->Lower())->HasAnimation() )
+ {
+ GetWin()->Invalidate( pOldSelFly->Frm().SVRect() );
+ }
+ bUnmark = sal_True;
+ }
+ }
+ if ( bUnmark )
+ pDView->UnmarkAll();
+ }
+ else
+ {
+ KillPams();
+ ClearMark();
+ }
+
+ if ( pObj )
+ {
+ OSL_ENSURE( !bEnterGroup, "SW_ENTER_GROUP is not supported" );
+ pDView->MarkObj( pObj, Imp()->GetPageView() );
+ }
+ else
+ {
+ pDView->MarkObj( rPt, MINMOVE, bAddSelect, bEnterGroup );
+ }
+
+ const sal_Bool bRet = 0 != rMrkList.GetMarkCount();
+
+ if ( rMrkList.GetMarkCount() > 1 )
+ {
+ //Ganz dumm ist es, wenn Zeichenobjekte Selektiert waren und
+ //nun ein Fly hinzuselektiert wird.
+ for ( sal_uInt16 i = 0; i < rMrkList.GetMarkCount(); ++i )
+ {
+ SdrObject *pTmpObj = rMrkList.GetMark( i )->GetMarkedSdrObj();
+ sal_Bool bForget = pTmpObj->ISA(SwVirtFlyDrawObj);
+ if( bForget )
+ {
+ pDView->UnmarkAll();
+ pDView->MarkObj( pTmpObj, Imp()->GetPageView(), bAddSelect, bEnterGroup );
+ break;
+ }
+ }
+ }
+
+ if ( bRet )
+ {
+ ::lcl_GrabCursor(this, pOldSelFly);
+ if ( GetCntType() & CNT_GRF )
+ {
+ const SwFlyFrm *pTmp = GetFlyFromMarked( &rMrkList, this );
+ OSL_ENSURE( pTmp, "Graphic without Fly" );
+ if ( ((SwNoTxtFrm*)pTmp->Lower())->HasAnimation() )
+ ((SwNoTxtFrm*)pTmp->Lower())->StopAnimation( GetOut() );
+ }
+ }
+ else if ( !pOldSelFly && bHadSelection )
+ SetCrsr( aOldPos, sal_True);
+
+ if( bRet || !bHadSelection )
+ CallChgLnk();
+
+ // update der Statuszeile
+ ::FrameNotify( this, bRet ? FLY_DRAG_START : FLY_DRAG_END );
+
+ EndAction();
+ return bRet;
+}
+
+/*************************************************************************
+|*
+|* sal_Bool SwFEShell::MoveAnchor( sal_uInt16 nDir )
+|*
+|* Description: MoveAnchor( nDir ) looked for an another Anchor for
+|* the selected drawing object (or fly frame) in the given direction.
+|* An object "as character" doesn't moves anyway.
+|* A page bounded object could move to the previous/next page with up/down,
+|* an object bounded "at paragraph" moves to the previous/next paragraph, too.
+|* An object bounded "at character" moves to the previous/next paragraph
+|* with up/down and to the previous/next character with left/right.
+|* If the anchor for at paragraph/character bounded objects has vertical or
+|* right_to_left text direction, the directions for up/down/left/right will
+|* interpreted accordingly.
+|* An object bounded "at fly" takes the center of the actual anchor and looks
+|* for the nearest fly frame in the given direction.
+|*
+*************************************************************************/
+
+#define LESS_X( aPt1, aPt2, bOld ) ( aPt1.X() < aPt2.X() || \
+ ( aPt1.X() == aPt2.X() && ( aPt1.Y() < aPt2.Y() || \
+ ( aPt1.Y() == aPt2.Y() && bOld ) ) ) )
+#define LESS_Y( aPt1, aPt2, bOld ) ( aPt1.Y() < aPt2.Y() || \
+ ( aPt1.Y() == aPt2.Y() && ( aPt1.X() < aPt2.X() || \
+ ( aPt1.X() == aPt2.X() && bOld ) ) ) )
+
+sal_Bool SwFEShell::MoveAnchor( sal_uInt16 nDir )
+{
+ const SdrMarkList* pMrkList;
+ if( !Imp()->GetDrawView() ||
+ 0 == (pMrkList = &Imp()->GetDrawView()->GetMarkedObjectList()) ||
+ 1 != pMrkList->GetMarkCount())
+ return sal_False;
+ SwFrm* pOld;
+ SwFlyFrm* pFly = NULL;
+ SdrObject *pObj = pMrkList->GetMark( 0 )->GetMarkedSdrObj();
+ if( pObj->ISA(SwVirtFlyDrawObj) )
+ {
+ pFly = ((SwVirtFlyDrawObj*)pObj)->GetFlyFrm();
+ pOld = pFly->AnchorFrm();
+ }
+ else
+ pOld = ((SwDrawContact*)GetUserCall(pObj))->GetAnchorFrm( pObj );
+ sal_Bool bRet = sal_False;
+ if( pOld )
+ {
+ SwFrm* pNew = pOld;
+ // --> OD 2004-07-16 #i28701#
+ SwAnchoredObject* pAnchoredObj = ::GetUserCall( pObj )->GetAnchoredObj( pObj );
+ SwFrmFmt& rFmt = pAnchoredObj->GetFrmFmt();
+ SwFmtAnchor aAnch( rFmt.GetAnchor() );
+ RndStdIds nAnchorId = aAnch.GetAnchorId();
+ if ( FLY_AS_CHAR == nAnchorId )
+ return sal_False;
+ if( pOld->IsVertical() )
+ {
+ if( pOld->IsTxtFrm() )
+ {
+ switch( nDir ) {
+ case SW_MOVE_UP: nDir = SW_MOVE_LEFT; break;
+ case SW_MOVE_DOWN: nDir = SW_MOVE_RIGHT; break;
+ case SW_MOVE_LEFT: nDir = SW_MOVE_DOWN; break;
+ case SW_MOVE_RIGHT: nDir = SW_MOVE_UP; break;
+ }
+ if( pOld->IsRightToLeft() )
+ {
+ if( nDir == SW_MOVE_LEFT )
+ nDir = SW_MOVE_RIGHT;
+ else if( nDir == SW_MOVE_RIGHT )
+ nDir = SW_MOVE_LEFT;
+ }
+ }
+ }
+ switch ( nAnchorId ) {
+ case FLY_AT_PAGE:
+ {
+ OSL_ENSURE( pOld->IsPageFrm(), "Wrong anchor, page exspected." );
+ if( SW_MOVE_UP == nDir )
+ pNew = pOld->GetPrev();
+ else if( SW_MOVE_DOWN == nDir )
+ pNew = pOld->GetNext();
+ if( pNew && pNew != pOld )
+ {
+ aAnch.SetPageNum( ((SwPageFrm*)pNew)->GetPhyPageNum() );
+ bRet = sal_True;
+ }
+ break;
+ }
+ case FLY_AT_CHAR:
+ {
+ OSL_ENSURE( pOld->IsCntntFrm(), "Wrong anchor, page exspected." );
+ if( SW_MOVE_LEFT == nDir || SW_MOVE_RIGHT == nDir )
+ {
+ SwPosition *pPos = (SwPosition*)aAnch.GetCntntAnchor();
+ SwTxtNode* pTxtNd = ((SwTxtFrm*)pOld)->GetTxtNode();
+ xub_StrLen nAct = pPos->nContent.GetIndex();
+ if( SW_MOVE_LEFT == nDir )
+ {
+ bRet = sal_True;
+ if( nAct )
+ {
+ --nAct;
+ pPos->nContent.Assign( pTxtNd, nAct );
+ }
+ else
+ nDir = SW_MOVE_UP;
+ }
+ else
+ {
+ xub_StrLen nMax =
+ ((SwTxtFrm*)pOld)->GetTxtNode()->GetTxt().Len();
+ if( nAct < nMax )
+ {
+ ++nAct;
+ bRet = sal_True;
+ pPos->nContent.Assign( pTxtNd, nAct );
+ }
+ else
+ nDir = SW_MOVE_DOWN;
+ }
+ }
+ } // no break!
+ case FLY_AT_PARA:
+ {
+ OSL_ENSURE( pOld->IsCntntFrm(), "Wrong anchor, page exspected." );
+ if( SW_MOVE_UP == nDir )
+ pNew = pOld->FindPrev();
+ else if( SW_MOVE_DOWN == nDir )
+ pNew = pOld->FindNext();
+ if( pNew && pNew != pOld && pNew->IsCntntFrm() )
+ {
+ SwPosition *pPos = (SwPosition*)aAnch.GetCntntAnchor();
+ SwTxtNode* pTxtNd = ((SwTxtFrm*)pNew)->GetTxtNode();
+ pPos->nNode = *pTxtNd;
+ xub_StrLen nTmp = 0;
+ if( bRet )
+ {
+ nTmp = ((SwTxtFrm*)pNew)->GetTxtNode()->GetTxt().Len();
+ if( nTmp )
+ --nTmp;
+ }
+ pPos->nContent.Assign( pTxtNd, nTmp );
+ bRet = sal_True;
+ }
+ else if( SW_MOVE_UP == nDir || SW_MOVE_DOWN == nDir )
+ bRet = sal_False;
+ break;
+ }
+ case FLY_AT_FLY:
+ {
+ OSL_ENSURE( pOld->IsFlyFrm(), "Wrong anchor, fly frame exspected.");
+ SwPageFrm* pPage = pOld->FindPageFrm();
+ OSL_ENSURE( pPage, "Where's my page?" );
+ SwFlyFrm* pNewFly = NULL;
+ if( pPage->GetSortedObjs() )
+ {
+ int i;
+ sal_Bool bOld = sal_False;
+ Point aCenter( pOld->Frm().Left() + pOld->Frm().Width()/2,
+ pOld->Frm().Top() + pOld->Frm().Height()/2 );
+ Point aBest;
+ for( i = 0; (sal_uInt16)i<pPage->GetSortedObjs()->Count(); ++i )
+ {
+ SwAnchoredObject* pAnchObj =
+ (*pPage->GetSortedObjs())[i];
+ if( pAnchObj->ISA(SwFlyFrm) )
+ {
+ SwFlyFrm* pTmp = static_cast<SwFlyFrm*>(pAnchObj);
+ if( pTmp == pOld )
+ bOld = sal_True;
+ else
+ {
+ const SwFlyFrm* pCheck = pFly ? pTmp : 0;
+ while( pCheck )
+ {
+ if( pCheck == pFly )
+ break;
+ const SwFrm *pNxt = pCheck->GetAnchorFrm();
+ pCheck = pNxt ? pNxt->FindFlyFrm() : NULL;
+ }
+ if( pCheck || pTmp->IsProtected() )
+ continue;
+ Point aNew( pTmp->Frm().Left() +
+ pTmp->Frm().Width()/2,
+ pTmp->Frm().Top() +
+ pTmp->Frm().Height()/2 );
+ sal_Bool bAccept = sal_False;
+ switch( nDir ) {
+ case SW_MOVE_RIGHT:
+ {
+ bAccept = LESS_X( aCenter, aNew, bOld )
+ && ( !pNewFly ||
+ LESS_X( aNew, aBest, sal_False ) );
+ break;
+ }
+ case SW_MOVE_LEFT:
+ {
+ bAccept = LESS_X( aNew, aCenter, !bOld )
+ && ( !pNewFly ||
+ LESS_X( aBest, aNew, sal_True ) );
+ break;
+ }
+ case SW_MOVE_UP:
+ {
+ bAccept = LESS_Y( aNew, aCenter, !bOld )
+ && ( !pNewFly ||
+ LESS_Y( aBest, aNew, sal_True ) );
+ break;
+ }
+ case SW_MOVE_DOWN:
+ {
+ bAccept = LESS_Y( aCenter, aNew, bOld )
+ && ( !pNewFly ||
+ LESS_Y( aNew, aBest, sal_False ) );
+ break;
+ }
+ }
+ if( bAccept )
+ {
+ pNewFly = pTmp;
+ aBest = aNew;
+ }
+ }
+ }
+ }
+ }
+
+ if( pNewFly )
+ {
+ SwPosition aPos( *pNewFly->GetFmt()->
+ GetCntnt().GetCntntIdx());
+ aAnch.SetAnchor( &aPos );
+ bRet = sal_True;
+ }
+ break;
+ }
+ default: break;
+ }
+ if( bRet )
+ {
+ StartAllAction();
+ // --> handle change of anchor node:
+ // if count of the anchor frame also change, the fly frames have to be
+ // re-created. Thus, delete all fly frames except the <this> before the
+ // anchor attribute is change and re-create them afterwards.
+ {
+ SwHandleAnchorNodeChg* pHandleAnchorNodeChg( 0L );
+ SwFlyFrmFmt* pFlyFrmFmt( dynamic_cast<SwFlyFrmFmt*>(&rFmt) );
+ if ( pFlyFrmFmt )
+ {
+ pHandleAnchorNodeChg =
+ new SwHandleAnchorNodeChg( *pFlyFrmFmt, aAnch );
+ }
+ rFmt.GetDoc()->SetAttr( aAnch, rFmt );
+ delete pHandleAnchorNodeChg;
+ }
+ // <--
+ // --> OD 2004-06-24 #i28701# - no call of method
+ // <CheckCharRectAndTopOfLine()> for to-character anchored
+ // Writer fly frame needed. This method call can cause a
+ // format of the anchor frame, which is no longer intended.
+ // Instead clear the anchor character rectangle and
+ // the top of line values for all to-character anchored objects.
+ pAnchoredObj->ClearCharRectAndTopOfLine();
+ EndAllAction();
+ }
+ }
+ return bRet;
+}
+
+/*************************************************************************
+|*
+|* SwFEShell::GetSelFrmType()
+|*
+*************************************************************************/
+
+const SdrMarkList* SwFEShell::_GetMarkList() const
+{
+ const SdrMarkList* pMarkList = NULL;
+ if( Imp()->GetDrawView() != NULL )
+ pMarkList = &Imp()->GetDrawView()->GetMarkedObjectList();
+ return pMarkList;
+}
+
+sal_uInt16 SwFEShell::GetSelFrmType() const
+{
+ sal_uInt16 eType;
+
+ // get marked frame list, and check if anything is selected
+ const SdrMarkList* pMarkList = _GetMarkList();
+ if( pMarkList == NULL || pMarkList->GetMarkCount() == 0 )
+ eType = FRMTYPE_NONE;
+ else
+ {
+ // obtain marked item as fly frame; if no fly frame, it must
+ // be a draw object
+ const SwFlyFrm* pFly = ::GetFlyFromMarked(pMarkList, (ViewShell*)this);
+ if ( pFly != NULL )
+ {
+ if( pFly->IsFlyLayFrm() )
+ eType = FRMTYPE_FLY_FREE;
+ else if( pFly->IsFlyAtCntFrm() )
+ eType = FRMTYPE_FLY_ATCNT;
+ else
+ {
+ OSL_ENSURE( pFly->IsFlyInCntFrm(), "Neuer Rahmentyp?" );
+ eType = FRMTYPE_FLY_INCNT;
+ }
+ }
+ else
+ eType = FRMTYPE_DRAWOBJ;
+ }
+
+ return eType;
+}
+
+// does the draw selection contain a control?
+bool SwFEShell::IsSelContainsControl() const
+{
+ bool bRet = false;
+
+ // basically, copy the mechanism from GetSelFrmType(), but call
+ // CheckControl... if you get a drawing object
+ const SdrMarkList* pMarkList = _GetMarkList();
+ if( pMarkList != NULL && pMarkList->GetMarkCount() == 1 )
+ {
+ // if we have one marked object, get the SdrObject and check
+ // whether it contains a control
+ const SdrObject* pSdrObject = pMarkList->GetMark( 0 )->GetMarkedSdrObj();
+ bRet = pSdrObject && ::CheckControlLayer( pSdrObject );
+ }
+ return bRet;
+}
+
+/*************************************************************************
+|*
+|* SwFEShell::Scroll()
+|*
+*************************************************************************/
+
+void SwFEShell::ScrollTo( const Point &rPt )
+{
+ const SwRect aRect( rPt, rPt );
+ if ( IsScrollMDI( this, aRect ) &&
+ (!Imp()->GetDrawView()->GetMarkedObjectList().GetMarkCount() ||
+ Imp()->IsDragPossible( rPt )) )
+ {
+ ScrollMDI( this, aRect, SCROLLVAL, SCROLLVAL );
+ }
+}
+
+/*************************************************************************
+|*
+|* SwFEShell::SetDragMode()
+|*
+*************************************************************************/
+
+void SwFEShell::SetDragMode( sal_uInt16 eDragMode )
+{
+ if ( Imp()->HasDrawView() )
+ Imp()->GetDrawView()->SetDragMode( (SdrDragMode)eDragMode );
+}
+
+/*************************************************************************
+|*
+|* SwFEShell::BeginDrag()
+|*
+*************************************************************************/
+
+long SwFEShell::BeginDrag( const Point* pPt, sal_Bool )
+{
+ SdrView *pView = Imp()->GetDrawView();
+ if ( pView && pView->AreObjectsMarked() )
+ {
+ delete pChainFrom; delete pChainTo; pChainFrom = pChainTo = 0;
+ SdrHdl* pHdl = pView->PickHandle( *pPt );
+ pView->BegDragObj( *pPt, 0, pHdl );
+ ::FrameNotify( this, FLY_DRAG );
+ return 1;
+ }
+ return 0;
+}
+/*************************************************************************
+|*
+|* SwFEShell::Drag()
+|*
+*************************************************************************/
+
+long SwFEShell::Drag( const Point *pPt, sal_Bool )
+{
+ OSL_ENSURE( Imp()->HasDrawView(), "Drag without DrawView?" );
+ if ( Imp()->GetDrawView()->IsDragObj() )
+ {
+ ScrollTo( *pPt );
+ Imp()->GetDrawView()->MovDragObj( *pPt );
+ Imp()->GetDrawView()->ShowDragAnchor();
+ ::FrameNotify( this, FLY_DRAG );
+ return 1;
+ }
+ return 0;
+}
+
+/*************************************************************************
+|*
+|* SwFEShell::EndDrag()
+|*
+*************************************************************************/
+
+long SwFEShell::EndDrag( const Point *, sal_Bool )
+{
+ OSL_ENSURE( Imp()->HasDrawView(), "EndDrag without DrawView?" );
+ SdrView *pView = Imp()->GetDrawView();
+ if ( pView->IsDragObj() )
+ {
+ //Start-/EndActions nur an der ViewShell aufsetzen
+ ViewShell *pSh = this;
+ do {
+ pSh->StartAction();
+ } while ( this != (pSh = (ViewShell*)pSh->GetNext()) );
+
+ StartUndo( UNDO_START );
+
+ //#50778# Bug im Draging: Im StartAction wird ein HideShowXor gerufen.
+ //Im EndDragObj() wird dies unsinniger und faelschlicherweise wieder
+ //Rueckgaengig gemacht. Um Konsistenz herzustellen muessen wir das
+ //Xor also wieder zur Anzeige bringen.
+
+ // Reanimation from the hack #50778 to fix bug #97057
+ // May be not the best solution, but the one with lowest risc at the moment.
+ //pView->ShowShownXor( GetOut() );
+
+ pView->EndDragObj();
+ // DrawUndo-Action auf FlyFrames werden nicht gespeichert
+ // Die Fly aendern das Flag
+ GetDoc()->GetIDocumentUndoRedo().DoDrawUndo(true);
+ ChgAnchor( 0, sal_True );
+
+ EndUndo( UNDO_END );
+
+ do {
+ pSh->EndAction();
+ if( pSh->IsA( TYPE( SwCrsrShell ) ) )
+ ((SwCrsrShell*)pSh)->CallChgLnk();
+ } while ( this != (pSh = (ViewShell*)pSh->GetNext()) );
+
+ GetDoc()->SetModified();
+ ::FrameNotify( this, FLY_DRAG );
+ return 1;
+ }
+ return 0;
+}
+
+/*************************************************************************
+|*
+|* SwFEShell::BreakDrag()
+|*
+*************************************************************************/
+
+void SwFEShell::BreakDrag()
+{
+ OSL_ENSURE( Imp()->HasDrawView(), "BreakDrag without DrawView?" );
+ if ( Imp()->GetDrawView()->IsDragObj() )
+ Imp()->GetDrawView()->BrkDragObj();
+ SetChainMarker();
+}
+
+/*************************************************************************
+|*
+|* SwFEShell::SelFlyGrabCrsr()
+|*
+|* Beschreibung Wenn ein Fly selektiert ist, zieht er den Crsr in
+|* den ersten CntntFrm
+*************************************************************************/
+
+const SwFrmFmt* SwFEShell::SelFlyGrabCrsr()
+{
+ if ( Imp()->HasDrawView() )
+ {
+ const SdrMarkList &rMrkList = Imp()->GetDrawView()->GetMarkedObjectList();
+ SwFlyFrm *pFly = ::GetFlyFromMarked( &rMrkList, this );
+
+ if( pFly )
+ {
+ SwCntntFrm *pCFrm = pFly->ContainsCntnt();
+ if ( pCFrm )
+ {
+ SwCntntNode *pCNode = pCFrm->GetNode();
+ // --> assure, that the cursor is consistent.
+ KillPams();
+ ClearMark();
+ // <--
+ SwPaM *pCrsr = GetCrsr();
+
+ pCrsr->GetPoint()->nNode = *pCNode;
+ pCrsr->GetPoint()->nContent.Assign( pCNode, 0 );
+
+ SwRect& rChrRect = (SwRect&)GetCharRect();
+ rChrRect = pFly->Prt();
+ rChrRect.Pos() += pFly->Frm().Pos();
+ GetCrsrDocPos() = rChrRect.Pos();
+ }
+ return pFly->GetFmt();
+ }
+ }
+ return 0;
+}
+
+
+/*************************************************************************
+|*
+|* SwFEShell::SelectionToTop(), SelectionToBottom()
+|*
+|* Beschreibung Selektion nach oben/unten (Z-Order)
+|*
+*************************************************************************/
+
+void lcl_NotifyNeighbours( const SdrMarkList *pLst )
+{
+ //Die Regeln fuer die Ausweichmanoever haben sich veraendert.
+ //1. Die Umgebung des Fly und aller innenliegenden muss benachrichtigt
+ // werden.
+ //2. Der Inhalt des Rahmen selbst muss benachrichtigt werden.
+ //3. Rahmen die dem Rahmen ausweichen bzw. wichen muessen benachrichtigt werden.
+ //4. Auch Zeichenobjekte koennen Rahmen verdraengen
+
+ for( sal_uInt16 j = 0; j < pLst->GetMarkCount(); ++j )
+ {
+ SwPageFrm *pPage;
+ sal_Bool bCheckNeighbours = sal_False;
+ sal_Int16 aHori = text::HoriOrientation::NONE;
+ SwRect aRect;
+ SdrObject *pO = pLst->GetMark( 0 )->GetMarkedSdrObj();
+ if ( pO->ISA(SwVirtFlyDrawObj) )
+ {
+ SwFlyFrm *pFly = ((SwVirtFlyDrawObj*)pO)->GetFlyFrm();
+
+ const SwFmtHoriOrient &rHori = pFly->GetFmt()->GetHoriOrient();
+ aHori = rHori.GetHoriOrient();
+ if( text::HoriOrientation::NONE != aHori && text::HoriOrientation::CENTER != aHori &&
+ pFly->IsFlyAtCntFrm() )
+ {
+ bCheckNeighbours = sal_True;
+ pFly->InvalidatePos();
+ pFly->Frm().Pos().Y() += 1;
+ }
+
+ pPage = pFly->FindPageFrm();
+ aRect = pFly->Frm();
+ }
+ else
+ {
+ SwFrm* pAnch = ( (SwDrawContact*)GetUserCall(pO) )->GetAnchorFrm( pO );
+ if( !pAnch )
+ continue;
+ pPage = pAnch->FindPageFrm();
+ // --> OD 2006-08-15 #i68520# - naming changed
+ aRect = GetBoundRectOfAnchoredObj( pO );
+ // <--
+ }
+
+ sal_uInt32 nCount = pPage->GetSortedObjs() ? pPage->GetSortedObjs()->Count() : 0;
+ for ( sal_uInt32 i = 0; i < nCount; ++i )
+ {
+ SwAnchoredObject* pAnchoredObj = (*pPage->GetSortedObjs())[i];
+ if ( !pAnchoredObj->ISA(SwFlyFrm) )
+ continue;
+
+ SwFlyFrm* pAct = static_cast<SwFlyFrm*>(pAnchoredObj);
+ SwRect aTmpCalcPnt( pAct->Prt() );
+ aTmpCalcPnt += pAct->Frm().Pos();
+ if ( aRect.IsOver( aTmpCalcPnt ) )
+ {
+ SwCntntFrm *pCnt = pAct->ContainsCntnt();
+ while ( pCnt )
+ {
+ aTmpCalcPnt = pCnt->Prt();
+ aTmpCalcPnt += pCnt->Frm().Pos();
+ if ( aRect.IsOver( aTmpCalcPnt ) )
+ ((SwFrm*)pCnt)->Prepare( PREP_FLY_ATTR_CHG );
+ pCnt = pCnt->GetNextCntntFrm();
+ }
+ }
+ if ( bCheckNeighbours && pAct->IsFlyAtCntFrm() )
+ {
+ const SwFmtHoriOrient &rH = pAct->GetFmt()->GetHoriOrient();
+ if ( rH.GetHoriOrient() == aHori &&
+ pAct->Frm().Top() <= aRect.Bottom() &&
+ pAct->Frm().Bottom() >= aRect.Top() )
+ {
+ pAct->InvalidatePos();
+ pAct->Frm().Pos().Y() += 1;
+ }
+ }
+ }
+ }
+}
+
+void SwFEShell::SelectionToTop( sal_Bool bTop )
+{
+ OSL_ENSURE( Imp()->HasDrawView(), "SelectionToTop without DrawView?" );
+ const SdrMarkList &rMrkList = Imp()->GetDrawView()->GetMarkedObjectList();
+ OSL_ENSURE( rMrkList.GetMarkCount(), "Kein Object Selektiert." );
+
+ SwFlyFrm *pFly = ::GetFlyFromMarked( &rMrkList, this );
+ if ( pFly && pFly->IsFlyInCntFrm() )
+ return;
+
+ StartAllAction();
+ if ( bTop )
+ Imp()->GetDrawView()->PutMarkedToTop();
+ else
+ Imp()->GetDrawView()->MovMarkedToTop();
+ ::lcl_NotifyNeighbours( &rMrkList );
+ GetDoc()->SetModified();
+ EndAllAction();
+}
+
+void SwFEShell::SelectionToBottom( sal_Bool bBottom )
+{
+ OSL_ENSURE( Imp()->HasDrawView(), "SelectionToBottom without DrawView?" );
+ const SdrMarkList &rMrkList = Imp()->GetDrawView()->GetMarkedObjectList();
+ OSL_ENSURE( rMrkList.GetMarkCount(), "Kein Object Selektiert." );
+
+ SwFlyFrm *pFly = ::GetFlyFromMarked( &rMrkList, this );
+ if ( pFly && pFly->IsFlyInCntFrm() )
+ return;
+
+ StartAllAction();
+ if ( bBottom )
+ Imp()->GetDrawView()->PutMarkedToBtm();
+ else
+ Imp()->GetDrawView()->MovMarkedToBtm();
+ ::lcl_NotifyNeighbours( &rMrkList );
+ GetDoc()->SetModified();
+ EndAllAction();
+}
+
+/*************************************************************************
+|*
+|* SwFEShell::GetLayerId()
+|*
+|* Beschreibung Objekt ueber/unter dem Dokument?
+|* 2 Controls, 1 Heaven, 0 Hell, -1 Uneindeutig
+*************************************************************************/
+
+short SwFEShell::GetLayerId() const
+{
+ short nRet = SHRT_MAX;
+ if ( Imp()->HasDrawView() )
+ {
+ const SdrMarkList &rMrkList = Imp()->GetDrawView()->GetMarkedObjectList();
+ for ( sal_uInt16 i = 0; i < rMrkList.GetMarkCount(); ++i )
+ {
+ const SdrObject *pObj = rMrkList.GetMark( i )->GetMarkedSdrObj();
+ if( !pObj )
+ continue;
+ if ( nRet == SHRT_MAX )
+ nRet = pObj->GetLayer();
+ else if ( nRet != pObj->GetLayer() )
+ {
+ nRet = -1;
+ break;
+ }
+ }
+ }
+ if ( nRet == SHRT_MAX )
+ nRet = -1;
+ return nRet;
+}
+
+/*************************************************************************
+|*
+|* SwFEShell::SelectionToHeaven(), SelectionToHell()
+|*
+|* Beschreibung Objekt ueber/unter dem Dokument
+|*
+*************************************************************************/
+// Note: only visible objects can be marked. Thus, objects with invisible
+// layer IDs have not to be considered.
+// If <SwFEShell> exists, layout exists!!
+void SwFEShell::ChangeOpaque( SdrLayerID nLayerId )
+{
+ if ( Imp()->HasDrawView() )
+ {
+ const SdrMarkList &rMrkList = Imp()->GetDrawView()->GetMarkedObjectList();
+ const IDocumentDrawModelAccess* pIDDMA = getIDocumentDrawModelAccess();
+ // correct type of <nControls>
+ for ( sal_uInt16 i = 0; i < rMrkList.GetMarkCount(); ++i )
+ {
+ SdrObject* pObj = rMrkList.GetMark( i )->GetMarkedSdrObj();
+ if( !pObj )
+ continue;
+ // or group objects containing controls.
+ // --> #i113730#
+ // consider that a member of a drawing group has been selected.
+ const SwContact* pContact = ::GetUserCall( pObj );
+ OSL_ENSURE( pContact && pContact->GetMaster(), "<SwFEShell::ChangeOpaque(..)> - missing contact or missing master object at contact!" );
+ const bool bControlObj = ( pContact && pContact->GetMaster() )
+ ? ::CheckControlLayer( pContact->GetMaster() )
+ : ::CheckControlLayer( pObj );
+ // <--
+ if ( !bControlObj && pObj->GetLayer() != nLayerId )
+ {
+ pObj->SetLayer( nLayerId );
+ InvalidateWindows( SwRect( pObj->GetCurrentBoundRect() ) );
+ if ( pObj->ISA(SwVirtFlyDrawObj) )
+ {
+ SwFmt *pFmt = ((SwVirtFlyDrawObj*)pObj)->GetFlyFrm()->GetFmt();
+ SvxOpaqueItem aOpa( pFmt->GetOpaque() );
+ aOpa.SetValue( nLayerId == pIDDMA->GetHellId() );
+ pFmt->SetFmtAttr( aOpa );
+ }
+ }
+ }
+ GetDoc()->SetModified();
+ }
+}
+
+void SwFEShell::SelectionToHeaven()
+{
+ ChangeOpaque( getIDocumentDrawModelAccess()->GetHeavenId() );
+}
+
+void SwFEShell::SelectionToHell()
+{
+ ChangeOpaque( getIDocumentDrawModelAccess()->GetHellId() );
+}
+
+/*************************************************************************
+|*
+|* SwFEShell::IsObjSelected(), IsFrmSelected()
+|*
+*************************************************************************/
+
+sal_uInt16 SwFEShell::IsObjSelected() const
+{
+ if ( IsFrmSelected() || !Imp()->HasDrawView() )
+ return 0;
+ else
+ return sal_uInt16( Imp()->GetDrawView()->GetMarkedObjectList().GetMarkCount() );
+}
+
+sal_Bool SwFEShell::IsFrmSelected() const
+{
+ if ( !Imp()->HasDrawView() )
+ return sal_False;
+ else
+ return 0 != ::GetFlyFromMarked( &Imp()->GetDrawView()->GetMarkedObjectList(),
+ (ViewShell*)this );
+}
+
+sal_Bool SwFEShell::IsObjSelected( const SdrObject& rObj ) const
+{
+ if ( IsFrmSelected() || !Imp()->HasDrawView() )
+ return sal_False;
+ else
+ return Imp()->GetDrawView()
+ ->IsObjMarked( const_cast< SdrObject * >( &rObj ) );
+}
+
+/*************************************************************************
+|*
+|* SwFEShell::EndTextEdit()
+|*
+*************************************************************************/
+
+void SwFEShell::EndTextEdit()
+{
+ //Beenden des TextEditModus. Wenn gewuenscht (default wenn das Objekt
+ //keinen Text mehr enthaelt und keine Attribute traegt) wird das
+ //Objekt gel�scht. Alle anderen markierten Objekte bleiben erhalten.
+
+ OSL_ENSURE( Imp()->HasDrawView() && Imp()->GetDrawView()->IsTextEdit(),
+ "EndTextEdit an no Object" );
+
+ StartAllAction();
+ SdrView *pView = Imp()->GetDrawView();
+ SdrObject *pObj = pView->GetTextEditObject();
+ SdrObjUserCall* pUserCall;
+ if( 0 != ( pUserCall = GetUserCall(pObj) ) )
+ {
+ SdrObject *pTmp = ((SwContact*)pUserCall)->GetMaster();
+ if( !pTmp )
+ pTmp = pObj;
+ pUserCall->Changed( *pTmp, SDRUSERCALL_RESIZE, pTmp->GetLastBoundRect() );
+ }
+ if ( !pObj->GetUpGroup() )
+ {
+ if ( SDRENDTEXTEDIT_SHOULDBEDELETED == pView->SdrEndTextEdit(sal_True) )
+ {
+ if ( pView->GetMarkedObjectList().GetMarkCount() > 1 )
+ {
+ {
+ SdrMarkList aSave( pView->GetMarkedObjectList() );
+ aSave.DeleteMark( aSave.FindObject( pObj ) );
+ if ( aSave.GetMarkCount() )
+ {
+ pView->UnmarkAll();
+ pView->MarkObj( pObj, Imp()->GetPageView() );
+ }
+ DelSelectedObj();
+ if ( aSave.GetMarkCount() )
+ {
+ for ( sal_uInt16 i = 0; i < aSave.GetMarkCount(); ++i )
+ pView->MarkObj( aSave.GetMark( i )->GetMarkedSdrObj(),
+ Imp()->GetPageView() );
+ }
+ }
+ }
+ else
+ DelSelectedObj();
+ }
+ }
+ else
+ pView->SdrEndTextEdit();
+ EndAllAction();
+}
+
+/*************************************************************************
+|*
+|* SwFEShell::IsInsideSelectedObj()
+|*
+*************************************************************************/
+
+int SwFEShell::IsInsideSelectedObj( const Point &rPt )
+{
+ if( Imp()->HasDrawView() )
+ {
+ SwDrawView *pDView = Imp()->GetDrawView();
+
+ if( pDView->GetMarkedObjectList().GetMarkCount() &&
+ pDView->IsMarkedObjHit( rPt ) )
+ {
+ return SDRHIT_OBJECT;
+ }
+ }
+ return SDRHIT_NONE;
+}
+
+/*************************************************************************
+|*
+|* SwFEShell::IsObjSelectable()
+|*
+*************************************************************************/
+
+bool SwFEShell::IsObjSelectable( const Point& rPt )
+{
+ SET_CURR_SHELL(this);
+ SwDrawView *pDView = Imp()->GetDrawView();
+ bool bRet = false;
+ if( pDView )
+ {
+ SdrObject* pObj;
+ SdrPageView* pPV;
+ sal_uInt16 nOld = pDView->GetHitTolerancePixel();
+ pDView->SetHitTolerancePixel( pDView->GetMarkHdlSizePixel()/2 );
+
+ bRet = 0 != pDView->PickObj( rPt, pDView->getHitTolLog(), pObj, pPV, SDRSEARCH_PICKMARKABLE );
+ pDView->SetHitTolerancePixel( nOld );
+ }
+ return bRet;
+}
+
+// Test if there is a object at that position and if it should be selected.
+sal_Bool SwFEShell::ShouldObjectBeSelected(const Point& rPt)
+{
+ SET_CURR_SHELL(this);
+ SwDrawView *pDrawView = Imp()->GetDrawView();
+ sal_Bool bRet(sal_False);
+
+ if(pDrawView)
+ {
+ SdrObject* pObj;
+ SdrPageView* pPV;
+ sal_uInt16 nOld(pDrawView->GetHitTolerancePixel());
+
+ pDrawView->SetHitTolerancePixel(pDrawView->GetMarkHdlSizePixel()/2);
+ bRet = pDrawView->PickObj(rPt, pDrawView->getHitTolLog(), pObj, pPV, SDRSEARCH_PICKMARKABLE);
+ pDrawView->SetHitTolerancePixel(nOld);
+
+ if ( bRet && pObj )
+ {
+ const IDocumentDrawModelAccess* pIDDMA = getIDocumentDrawModelAccess();
+ // --> OD 2009-12-30 #i89920#
+ // Do not select object in background which is overlapping this text
+ // at the given position.
+ bool bObjInBackground( false );
+ {
+ if ( pObj->GetLayer() == pIDDMA->GetHellId() )
+ {
+ const SwAnchoredObject* pAnchoredObj = ::GetUserCall( pObj )->GetAnchoredObj( pObj );
+ const SwFrmFmt& rFmt = pAnchoredObj->GetFrmFmt();
+ const SwFmtSurround& rSurround = rFmt.GetSurround();
+ if ( rSurround.GetSurround() == SURROUND_THROUGHT )
+ {
+ bObjInBackground = true;
+ }
+ }
+ }
+ if ( bObjInBackground )
+ {
+ const SwPageFrm* pPageFrm = GetLayout()->GetPageAtPos( rPt );
+ if( pPageFrm )
+ {
+ const SwCntntFrm* pCntntFrm( pPageFrm->ContainsCntnt() );
+ while ( pCntntFrm )
+ {
+ if ( pCntntFrm->UnionFrm().IsInside( rPt ) )
+ {
+ const SwTxtFrm* pTxtFrm =
+ dynamic_cast<const SwTxtFrm*>(pCntntFrm);
+ if ( pTxtFrm )
+ {
+ SwPosition* pPos =
+ new SwPosition( *(pTxtFrm->GetTxtNode()) );
+ Point aTmpPt( rPt );
+ if ( pTxtFrm->GetKeyCrsrOfst( pPos, aTmpPt ) )
+ {
+ SwRect aCursorCharRect;
+ if ( pTxtFrm->GetCharRect( aCursorCharRect, *pPos ) )
+ {
+ if ( aCursorCharRect.IsOver( SwRect( pObj->GetLastBoundRect() ) ) )
+ {
+ bRet = sal_False;
+ }
+ }
+ }
+ }
+ else
+ {
+ bRet = sal_False;
+ }
+ break;
+ }
+
+ pCntntFrm = pCntntFrm->GetNextCntntFrm();
+ }
+ }
+ }
+ // <--
+
+ if ( bRet )
+ {
+ const SdrPage* pPage = pIDDMA->GetDrawModel()->GetPage(0);
+ for(sal_uInt32 a(pObj->GetOrdNum() + 1); bRet && a < pPage->GetObjCount(); a++)
+ {
+ SdrObject *pCandidate = pPage->GetObj(a);
+
+ if (pCandidate->ISA(SwVirtFlyDrawObj) &&
+ ( (SwVirtFlyDrawObj*)pCandidate)->GetCurrentBoundRect().IsInside(rPt) )
+ {
+ bRet = sal_False;
+ }
+ }
+ }
+ }
+ }
+
+ return bRet;
+}
+
+/*************************************************************************
+|*
+|* SwFEShell::GotoObj()
+|*
+|* Beschreibung Wenn ein Obj selektiert ist, gehen wir von dessen
+|* TopLeft aus, andernfalls von der Mitte des aktuellen CharRects.
+|*
+*************************************************************************/
+/* --------------------------------------------------
+ * Beinhaltet das Objekt ein Control oder Gruppen,
+ * die nur aus Controls bestehen
+ * --------------------------------------------------*/
+sal_Bool lcl_IsControlGroup( const SdrObject *pObj )
+{
+ sal_Bool bRet = sal_False;
+ if(pObj->ISA(SdrUnoObj))
+ bRet = sal_True;
+ else if( pObj->ISA( SdrObjGroup ) )
+ {
+ bRet = sal_True;
+ const SdrObjList *pLst = ((SdrObjGroup*)pObj)->GetSubList();
+ for ( sal_uInt16 i = 0; i < pLst->GetObjCount(); ++i )
+ if( !::lcl_IsControlGroup( pLst->GetObj( i ) ) )
+ return sal_False;
+ }
+ return bRet;
+}
+
+namespace
+{
+ class MarkableObjectsOnly : public ::svx::ISdrObjectFilter
+ {
+ public:
+ MarkableObjectsOnly( SdrPageView* i_pPV )
+ :m_pPV( i_pPV )
+ {
+ }
+
+ virtual bool includeObject( const SdrObject& i_rObject ) const
+ {
+ return m_pPV && m_pPV->GetView().IsObjMarkable( const_cast< SdrObject* >( &i_rObject ), m_pPV );
+ }
+
+ private:
+ SdrPageView* m_pPV;
+ };
+}
+
+const SdrObject* SwFEShell::GetBestObject( sal_Bool bNext, sal_uInt16 /*GOTOOBJ_...*/ eType, sal_Bool bFlat, const ::svx::ISdrObjectFilter* pFilter )
+{
+ if( !Imp()->HasDrawView() )
+ return NULL;
+
+ const SdrObject *pBest = 0,
+ *pTop = 0;
+
+ const long nTmp = bNext ? LONG_MAX : 0;
+ Point aBestPos( nTmp, nTmp );
+ Point aTopPos( nTmp, nTmp );
+ Point aCurPos;
+ Point aPos;
+ sal_Bool bNoDraw = 0 == (GOTOOBJ_DRAW_ANY & eType);
+ sal_Bool bNoFly = 0 == (GOTOOBJ_FLY_ANY & eType);
+
+ if( !bNoFly && bNoDraw )
+ {
+ SwFlyFrm *pFly = GetCurrFrm( sal_False )->FindFlyFrm();
+ if( pFly )
+ pBest = pFly->GetVirtDrawObj();
+ }
+ const SdrMarkList &rMrkList = Imp()->GetDrawView()->GetMarkedObjectList();
+ SdrPageView* pPV = Imp()->GetDrawView()->GetSdrPageView();
+
+ MarkableObjectsOnly aDefaultFilter( pPV );
+ if ( !pFilter )
+ pFilter = &aDefaultFilter;
+
+ if( !pBest || rMrkList.GetMarkCount() == 1 )
+ {
+ // Ausgangspunkt bestimmen.
+ SdrObjList* pList = NULL;
+ if ( rMrkList.GetMarkCount() )
+ {
+ const SdrObject* pStartObj = rMrkList.GetMark(0)->GetMarkedSdrObj();
+ if( pStartObj->ISA(SwVirtFlyDrawObj) )
+ aPos = ((SwVirtFlyDrawObj*)pStartObj)->GetFlyFrm()->Frm().Pos();
+ else
+ aPos = pStartObj->GetSnapRect().TopLeft();
+
+ // If an object inside a group is selected, we want to
+ // iterate over the group members.
+ if ( ! pStartObj->GetUserCall() )
+ pList = pStartObj->GetObjList();
+ }
+ else
+ {
+ // If no object is selected, we check if we just entered a group.
+ // In this case we want to iterate over the group members.
+ aPos = GetCharRect().Center();
+ const SdrObject* pStartObj = pPV ? pPV->GetAktGroup() : 0;
+ if ( pStartObj && pStartObj->ISA( SdrObjGroup ) )
+ pList = pStartObj->GetSubList();
+ }
+
+ if ( ! pList )
+ {
+ // Here we are if
+ // A No object has been selected and no group has been entered or
+ // B An object has been selected and it is not inside a group
+ pList = getIDocumentDrawModelAccess()->GetDrawModel()->GetPage( 0 );
+ }
+
+
+ OSL_ENSURE( pList, "No object list to iterate" );
+
+ SdrObjListIter aObjIter( *pList, bFlat ? IM_FLAT : IM_DEEPNOGROUPS );
+ while ( aObjIter.IsMore() )
+ {
+ SdrObject* pObj = aObjIter.Next();
+ sal_Bool bFlyFrm = pObj->ISA(SwVirtFlyDrawObj);
+ if( ( bNoFly && bFlyFrm ) ||
+ ( bNoDraw && !bFlyFrm ) ||
+ ( eType == GOTOOBJ_DRAW_SIMPLE && lcl_IsControlGroup( pObj ) ) ||
+ ( eType == GOTOOBJ_DRAW_CONTROL && !lcl_IsControlGroup( pObj ) ) ||
+ ( pFilter && !pFilter->includeObject( *pObj ) ) )
+ continue;
+ if( bFlyFrm )
+ {
+ SwVirtFlyDrawObj *pO = (SwVirtFlyDrawObj*)pObj;
+ SwFlyFrm *pFly = pO->GetFlyFrm();
+ if( GOTOOBJ_FLY_ANY != ( GOTOOBJ_FLY_ANY & eType ) )
+ {
+ switch ( eType )
+ {
+ case GOTOOBJ_FLY_FRM:
+ if ( pFly->Lower() && pFly->Lower()->IsNoTxtFrm() )
+ continue;
+ break;
+ case GOTOOBJ_FLY_GRF:
+ if ( pFly->Lower() &&
+ (pFly->Lower()->IsLayoutFrm() ||
+ !((SwCntntFrm*)pFly->Lower())->GetNode()->GetGrfNode()))
+ continue;
+ break;
+ case GOTOOBJ_FLY_OLE:
+ if ( pFly->Lower() &&
+ (pFly->Lower()->IsLayoutFrm() ||
+ !((SwCntntFrm*)pFly->Lower())->GetNode()->GetOLENode()))
+ continue;
+ break;
+ }
+ }
+ aCurPos = pFly->Frm().Pos();
+ }
+ else
+ aCurPos = pObj->GetCurrentBoundRect().TopLeft();
+
+ // Sonderfall wenn ein anderes Obj auf selber Y steht.
+ if( aCurPos != aPos && // nur wenn ich es nicht selber bin
+ aCurPos.Y() == aPos.Y() && // ist die Y Position gleich
+ (bNext? (aCurPos.X() > aPos.X()) : // liegt neben mir
+ (aCurPos.X() < aPos.X())) ) // " reverse
+ {
+ aBestPos = Point( nTmp, nTmp );
+ SdrObjListIter aTmpIter( *pList, bFlat ? IM_FLAT : IM_DEEPNOGROUPS );
+ while ( aTmpIter.IsMore() )
+ {
+ SdrObject* pTmpObj = aTmpIter.Next();
+ bFlyFrm = pTmpObj->ISA(SwVirtFlyDrawObj);
+ if( ( bNoFly && bFlyFrm ) || ( bNoDraw && !bFlyFrm ) )
+ continue;
+ if( bFlyFrm )
+ {
+ SwVirtFlyDrawObj *pO = (SwVirtFlyDrawObj*)pTmpObj;
+ aCurPos = pO->GetFlyFrm()->Frm().Pos();
+ }
+ else
+ aCurPos = pTmpObj->GetCurrentBoundRect().TopLeft();
+
+ if( aCurPos != aPos && aCurPos.Y() == aPos.Y() &&
+ (bNext? (aCurPos.X() > aPos.X()) : // liegt neben mir
+ (aCurPos.X() < aPos.X())) && // " reverse
+ (bNext? (aCurPos.X() < aBestPos.X()) : // besser als Beste
+ (aCurPos.X() > aBestPos.X())) ) // " reverse
+ {
+ aBestPos = aCurPos;
+ pBest = pTmpObj;
+ }
+ }
+ break;
+ }
+
+ if( (
+ (bNext? (aPos.Y() < aCurPos.Y()) : // nur unter mir
+ (aPos.Y() > aCurPos.Y())) && // " reverse
+ (bNext? (aBestPos.Y() > aCurPos.Y()) : // naeher drunter
+ (aBestPos.Y() < aCurPos.Y()))
+ ) || // " reverse
+ (aBestPos.Y() == aCurPos.Y() &&
+ (bNext? (aBestPos.X() > aCurPos.X()) : // weiter links
+ (aBestPos.X() < aCurPos.X())))) // " reverse
+
+ {
+ aBestPos = aCurPos;
+ pBest = pObj;
+ }
+
+ if( (bNext? (aTopPos.Y() > aCurPos.Y()) : // hoeher als Beste
+ (aTopPos.Y() < aCurPos.Y())) || // " reverse
+ (aTopPos.Y() == aCurPos.Y() &&
+ (bNext? (aTopPos.X() > aCurPos.X()) : // weiter links
+ (aTopPos.X() < aCurPos.X())))) // " reverse
+ {
+ aTopPos = aCurPos;
+ pTop = pObj;
+ }
+ }
+ // leider nichts gefunden
+ if( (bNext? (aBestPos.X() == LONG_MAX) : (aBestPos.X() == 0)) )
+ pBest = pTop;
+ }
+
+ return pBest;
+}
+
+sal_Bool SwFEShell::GotoObj( sal_Bool bNext, sal_uInt16 /*GOTOOBJ_...*/ eType )
+{
+ const SdrObject* pBest = GetBestObject( bNext, eType );
+
+ if ( !pBest )
+ return sal_False;
+
+ sal_Bool bFlyFrm = pBest->ISA(SwVirtFlyDrawObj);
+ if( bFlyFrm )
+ {
+ SwVirtFlyDrawObj *pO = (SwVirtFlyDrawObj*)pBest;
+ const SwRect& rFrm = pO->GetFlyFrm()->Frm();
+ SelectObj( rFrm.Pos(), 0, (SdrObject*)pBest );
+ if( !ActionPend() )
+ MakeVisible( rFrm );
+ }
+ else
+ {
+ SelectObj( Point(), 0, (SdrObject*)pBest );
+ if( !ActionPend() )
+ MakeVisible( pBest->GetCurrentBoundRect() );
+ }
+ CallChgLnk();
+ return sal_True;
+}
+
+/*************************************************************************
+|*
+|* SwFEShell::BeginCreate()
+|*
+*************************************************************************/
+
+sal_Bool SwFEShell::BeginCreate( sal_uInt16 /*SdrObjKind ?*/ eSdrObjectKind, const Point &rPos )
+{
+ sal_Bool bRet = sal_False;
+
+ if ( !Imp()->HasDrawView() )
+ Imp()->MakeDrawView();
+
+ if ( GetPageNumber( rPos ) )
+ {
+ Imp()->GetDrawView()->SetCurrentObj( eSdrObjectKind );
+ if ( eSdrObjectKind == OBJ_CAPTION )
+ bRet = Imp()->GetDrawView()->BegCreateCaptionObj(
+ rPos, Size( lMinBorder - MINFLY, lMinBorder - MINFLY ),
+ GetOut() );
+ else
+ bRet = Imp()->GetDrawView()->BegCreateObj( rPos, GetOut() );
+ }
+ if ( bRet )
+ {
+ ::FrameNotify( this, FLY_DRAG_START );
+ }
+ return bRet;
+}
+
+sal_Bool SwFEShell::BeginCreate( sal_uInt16 /*SdrObjKind ?*/ eSdrObjectKind, sal_uInt32 eObjInventor,
+ const Point &rPos )
+{
+ sal_Bool bRet = sal_False;
+
+ if ( !Imp()->HasDrawView() )
+ Imp()->MakeDrawView();
+
+ if ( GetPageNumber( rPos ) )
+ {
+ Imp()->GetDrawView()->SetCurrentObj( eSdrObjectKind, eObjInventor );
+ bRet = Imp()->GetDrawView()->BegCreateObj( rPos, GetOut() );
+ }
+ if ( bRet )
+ ::FrameNotify( this, FLY_DRAG_START );
+ return bRet;
+}
+
+/*************************************************************************
+|*
+|* SwFEShell::MoveCreate()
+|*
+*************************************************************************/
+
+void SwFEShell::MoveCreate( const Point &rPos )
+{
+ OSL_ENSURE( Imp()->HasDrawView(), "MoveCreate without DrawView?" );
+ if ( GetPageNumber( rPos ) )
+ {
+ ScrollTo( rPos );
+ Imp()->GetDrawView()->MovCreateObj( rPos );
+ ::FrameNotify( this, FLY_DRAG );
+ }
+}
+
+/*************************************************************************
+|*
+|* SwFEShell::EndCreate(), ImpEndCreate()
+|*
+*************************************************************************/
+
+sal_Bool SwFEShell::EndCreate( sal_uInt16 eSdrCreateCmd )
+{
+ // Damit das Undo-Object aus der DrawEngine nicht bei uns
+ // gespeichert wird, (wir erzeugen ein eigenes Undo-Object!) hier kurz
+ // das Undo abschalten
+ OSL_ENSURE( Imp()->HasDrawView(), "EndCreate without DrawView?" );
+ if( !Imp()->GetDrawView()->IsGroupEntered() )
+ {
+ GetDoc()->GetIDocumentUndoRedo().DoDrawUndo(false);
+ }
+ sal_Bool bCreate = Imp()->GetDrawView()->EndCreateObj(
+ SdrCreateCmd( eSdrCreateCmd ) );
+ GetDoc()->GetIDocumentUndoRedo().DoDrawUndo(true);
+
+ if ( !bCreate )
+ {
+ ::FrameNotify( this, FLY_DRAG_END );
+ return sal_False;
+ }
+
+ if ( (SdrCreateCmd)eSdrCreateCmd == SDRCREATE_NEXTPOINT )
+ {
+ ::FrameNotify( this, FLY_DRAG );
+ return sal_True;
+ }
+ return ImpEndCreate();
+}
+
+
+sal_Bool SwFEShell::ImpEndCreate()
+{
+ OSL_ENSURE( Imp()->GetDrawView()->GetMarkedObjectList().GetMarkCount() == 1,
+ "Neues Object nicht selektiert." );
+
+ SdrObject& rSdrObj = *Imp()->GetDrawView()->GetMarkedObjectList().GetMark(0)->GetMarkedSdrObj();
+
+ if( rSdrObj.GetSnapRect().IsEmpty() )
+ {
+ // das Object vergessen wir lieber, fuerht nur
+ // zu Problemen
+ Imp()->GetDrawView()->DeleteMarked();
+ Imp()->GetDrawView()->UnmarkAll();
+ ::FrameNotify( this, FLY_DRAG_END );
+ return sal_False;
+ }
+
+ if( rSdrObj.GetUpGroup() )
+ {
+ Point aTmpPos( rSdrObj.GetSnapRect().TopLeft() );
+ Point aNewAnchor( rSdrObj.GetUpGroup()->GetAnchorPos() );
+ // OD 2004-04-05 #i26791# - direct object positioning for group members
+ rSdrObj.NbcSetRelativePos( aTmpPos - aNewAnchor );
+ rSdrObj.NbcSetAnchorPos( aNewAnchor );
+ ::FrameNotify( this, FLY_DRAG );
+ return sal_True;
+ }
+
+ LockPaint();
+ StartAllAction();
+
+ Imp()->GetDrawView()->UnmarkAll();
+
+ const Rectangle &rBound = rSdrObj.GetSnapRect();
+ Point aPt( rBound.TopRight() );
+
+ //Fremde Identifier sollen in den Default laufen.
+ //Ueberschneidungen sind moeglich!!
+ sal_uInt16 nIdent = SdrInventor == rSdrObj.GetObjInventor()
+ ? rSdrObj.GetObjIdentifier()
+ : 0xFFFF;
+
+ //Default fuer Controls ist Zeichengebunden, Absatzgebunden sonst.
+ SwFmtAnchor aAnch;
+ const SwFrm *pAnch = 0;
+ sal_Bool bCharBound = sal_False;
+ if( rSdrObj.ISA( SdrUnoObj ) )
+ {
+ SwPosition aPos( GetDoc()->GetNodes() );
+ SwCrsrMoveState aState( MV_SETONLYTEXT );
+ Point aPoint( aPt.X(), aPt.Y() + rBound.GetHeight()/2 );
+ GetLayout()->GetCrsrOfst( &aPos, aPoint, &aState ); //swmod 080317
+
+ //Zeichenbindung ist im ReadnOnly-Inhalt nicht erlaubt
+ if( !aPos.nNode.GetNode().IsProtect() )
+ {
+ pAnch = aPos.nNode.GetNode().GetCntntNode()->getLayoutFrm( GetLayout(), &aPoint, &aPos );
+ SwRect aTmp;
+ pAnch->GetCharRect( aTmp, aPos );
+
+ //Der Crsr darf nicht zu weit entfernt sein.
+ bCharBound = sal_True;
+ Rectangle aRect( aTmp.SVRect() );
+ aRect.Left() -= MM50*2;
+ aRect.Top() -= MM50*2;
+ aRect.Right() += MM50*2;
+ aRect.Bottom()+= MM50*2;
+
+ if( !aRect.IsOver( rBound ) && !::GetHtmlMode( GetDoc()->GetDocShell() ))
+ bCharBound = sal_False;
+
+ //Bindung in Kopf-/Fusszeilen ist ebenfalls nicht erlaubt.
+ if( bCharBound )
+ bCharBound = !GetDoc()->IsInHeaderFooter( aPos.nNode );
+
+ if( bCharBound )
+ {
+ aAnch.SetType( FLY_AS_CHAR );
+ aAnch.SetAnchor( &aPos );
+ }
+ }
+ }
+
+ if( !bCharBound )
+ {
+ // allow native drawing objects in header/footer.
+ // Thus, set <bBodyOnly> to <false> for these objects using value
+ // of <nIdent> - value <0xFFFF> indicates control objects, which aren't
+ // allowed in header/footer.
+ //bool bBodyOnly = OBJ_NONE != nIdent;
+ bool bBodyOnly = 0xFFFF == nIdent;
+ bool bAtPage = false;
+ const SwFrm* pPage = 0;
+ SwCrsrMoveState aState( MV_SETONLYTEXT );
+ Point aPoint( aPt );
+ SwPosition aPos( GetDoc()->GetNodes() );
+ GetLayout()->GetCrsrOfst( &aPos, aPoint, &aState );
+
+ //nicht in ReadnOnly-Inhalt setzen
+ if( aPos.nNode.GetNode().IsProtect() )
+ // dann darf er nur seitengebunden sein. Oder sollte man
+ // die naechste nicht READONLY Position suchen?
+ bAtPage = true;
+
+ pAnch = aPos.nNode.GetNode().GetCntntNode()->getLayoutFrm( GetLayout(), &aPoint, 0, sal_False );
+
+ if( !bAtPage )
+ {
+ const SwFlyFrm *pTmp = pAnch->FindFlyFrm();
+ if( pTmp )
+ {
+ const SwFrm* pTmpFrm = pAnch;
+ SwRect aBound( rBound );
+ while( pTmp )
+ {
+ if( pTmp->Frm().IsInside( aBound ) )
+ {
+ if( !bBodyOnly || !pTmp->FindFooterOrHeader() )
+ pPage = pTmpFrm;
+ break;
+ }
+ pTmp = pTmp->GetAnchorFrm()
+ ? pTmp->GetAnchorFrm()->FindFlyFrm()
+ : 0;
+ pTmpFrm = pTmp;
+ }
+ }
+
+ if( !pPage )
+ pPage = pAnch->FindPageFrm();
+
+ // immer ueber FindAnchor gehen, damit der Frame immer an den
+ // davorgehen gebunden wird. Beim GetCrsOfst kann man auch zum
+ // nachfolgenden kommen. DAS IST FALSCH
+ pAnch = ::FindAnchor( pPage, aPt, bBodyOnly );
+ aPos.nNode = *((SwCntntFrm*)pAnch)->GetNode();
+
+ //nicht in ReadnOnly-Inhalt setzen
+ if( aPos.nNode.GetNode().IsProtect() )
+ // dann darf er nur seitengebunden sein. Oder sollte man
+ // die naechste nicht READONLY Position suchen?
+ bAtPage = true;
+ else
+ {
+ aAnch.SetType( FLY_AT_PARA );
+ aAnch.SetAnchor( &aPos );
+ }
+ }
+
+ if( bAtPage )
+ {
+ pPage = pAnch->FindPageFrm();
+
+ aAnch.SetType( FLY_AT_PAGE );
+ aAnch.SetPageNum( pPage->GetPhyPageNum() );
+ pAnch = pPage; // die Page wird jetzt zum Anker
+ }
+ }
+
+ SfxItemSet aSet( GetDoc()->GetAttrPool(), RES_FRM_SIZE, RES_FRM_SIZE,
+ RES_SURROUND, RES_ANCHOR, 0 );
+ aSet.Put( aAnch );
+
+ // OD 2004-03-30 #i26791# - determine relative object position
+ SwTwips nXOffset;
+ SwTwips nYOffset = rBound.Top() - pAnch->Frm().Top();
+ {
+ if( pAnch->IsVertical() )
+ {
+ nXOffset = nYOffset;
+ nYOffset = pAnch->Frm().Left()+pAnch->Frm().Width()-rBound.Right();
+ }
+ else if( pAnch->IsRightToLeft() )
+ nXOffset = pAnch->Frm().Left()+pAnch->Frm().Width()-rBound.Right();
+ else
+ nXOffset = rBound.Left() - pAnch->Frm().Left();
+ if( pAnch->IsTxtFrm() && ((SwTxtFrm*)pAnch)->IsFollow() )
+ {
+ SwTxtFrm* pTmp = (SwTxtFrm*)pAnch;
+ do {
+ pTmp = pTmp->FindMaster();
+ OSL_ENSURE( pTmp, "Where's my Master?" );
+ // OD 2004-03-30 #i26791# - correction: add frame area height
+ // of master frames.
+ nYOffset += pTmp->IsVertical() ?
+ pTmp->Frm().Width() : pTmp->Frm().Height();
+ } while ( pTmp->IsFollow() );
+ }
+ }
+
+ if( OBJ_NONE == nIdent )
+ {
+ //Bei OBJ_NONE wird ein Fly eingefuegt.
+ const long nWidth = rBound.Right() - rBound.Left();
+ const long nHeight= rBound.Bottom() - rBound.Top();
+ aSet.Put( SwFmtFrmSize( ATT_MIN_SIZE, Max( nWidth, long(MINFLY) ),
+ Max( nHeight, long(MINFLY) )));
+
+ SwFmtHoriOrient aHori( nXOffset, text::HoriOrientation::NONE, text::RelOrientation::FRAME );
+ SwFmtVertOrient aVert( nYOffset, text::VertOrientation::NONE, text::RelOrientation::FRAME );
+ aSet.Put( SwFmtSurround( SURROUND_PARALLEL ) );
+ aSet.Put( aHori );
+ aSet.Put( aVert );
+
+ //Schnell noch das Rechteck merken
+ const SwRect aFlyRect( rBound );
+
+ //Erzeugtes Object wegwerfen, so kann der Fly am elegentesten
+ //ueber vorhandene SS erzeugt werden.
+ GetDoc()->GetIDocumentUndoRedo().DoDrawUndo(false); // see above
+ // --> OD 2005-08-08 #i52858# - method name changed
+ SdrPage *pPg = getIDocumentDrawModelAccess()->GetOrCreateDrawModel()->GetPage( 0 );
+ // <--
+ if( !pPg )
+ {
+ SdrModel* pTmpSdrModel = getIDocumentDrawModelAccess()->GetDrawModel();
+ pPg = pTmpSdrModel->AllocPage( sal_False );
+ pTmpSdrModel->InsertPage( pPg );
+ }
+ pPg->RecalcObjOrdNums();
+ SdrObject* pRemovedObject = pPg->RemoveObject( rSdrObj.GetOrdNumDirect() );
+ SdrObject::Free( pRemovedObject );
+ GetDoc()->GetIDocumentUndoRedo().DoDrawUndo(true);
+
+ SwFlyFrm* pFlyFrm;
+ if( NewFlyFrm( aSet, sal_True ) &&
+ ::GetHtmlMode( GetDoc()->GetDocShell() ) &&
+ 0 != ( pFlyFrm = FindFlyFrm() ))
+ {
+ SfxItemSet aHtmlSet( GetDoc()->GetAttrPool(), RES_VERT_ORIENT, RES_HORI_ORIENT );
+ //Horizontale Ausrichtung:
+ const sal_Bool bLeftFrm = aFlyRect.Left() <
+ pAnch->Frm().Left() + pAnch->Prt().Left(),
+ bLeftPrt = aFlyRect.Left() + aFlyRect.Width() <
+ pAnch->Frm().Left() + pAnch->Prt().Width()/2;
+ if( bLeftFrm || bLeftPrt )
+ {
+ aHori.SetHoriOrient( text::HoriOrientation::LEFT );
+ aHori.SetRelationOrient( bLeftFrm ? text::RelOrientation::FRAME : text::RelOrientation::PRINT_AREA );
+ }
+ else
+ {
+ const sal_Bool bRightFrm = aFlyRect.Left() >
+ pAnch->Frm().Left() + pAnch->Prt().Width();
+ aHori.SetHoriOrient( text::HoriOrientation::RIGHT );
+ aHori.SetRelationOrient( bRightFrm ? text::RelOrientation::FRAME : text::RelOrientation::PRINT_AREA );
+ }
+ aHtmlSet.Put( aHori );
+ aVert.SetVertOrient( text::VertOrientation::TOP );
+ aVert.SetRelationOrient( text::RelOrientation::PRINT_AREA );
+ aHtmlSet.Put( aVert );
+
+ GetDoc()->SetAttr( aHtmlSet, *pFlyFrm->GetFmt() );
+ }
+ }
+ else
+ {
+ Point aRelNullPt;
+ if( OBJ_CAPTION == nIdent )
+ aRelNullPt = ((SdrCaptionObj&)rSdrObj).GetTailPos();
+ else
+ aRelNullPt = rBound.TopLeft();
+
+ aSet.Put( aAnch );
+ aSet.Put( SwFmtSurround( SURROUND_THROUGHT ) );
+ // OD 2004-03-30 #i26791# - set horizontal position
+ SwFmtHoriOrient aHori( nXOffset, text::HoriOrientation::NONE, text::RelOrientation::FRAME );
+ aSet.Put( aHori );
+ // OD 2004-03-30 #i26791# - set vertical position
+ if( pAnch->IsTxtFrm() && ((SwTxtFrm*)pAnch)->IsFollow() )
+ {
+ SwTxtFrm* pTmp = (SwTxtFrm*)pAnch;
+ do {
+ pTmp = pTmp->FindMaster();
+ OSL_ENSURE( pTmp, "Where's my Master?" );
+ nYOffset += pTmp->IsVertical() ?
+ pTmp->Prt().Width() : pTmp->Prt().Height();
+ } while ( pTmp->IsFollow() );
+ }
+ SwFmtVertOrient aVert( nYOffset, text::VertOrientation::NONE, text::RelOrientation::FRAME );
+ aSet.Put( aVert );
+ SwDrawFrmFmt* pFmt = (SwDrawFrmFmt*)getIDocumentLayoutAccess()->MakeLayoutFmt( RND_DRAW_OBJECT, &aSet );
+ // --> OD 2004-10-25 #i36010# - set layout direction of the position
+ pFmt->SetPositionLayoutDir(
+ text::PositionLayoutDir::PositionInLayoutDirOfAnchor );
+ // <--
+ // --> OD 2005-03-11 #i44344#, #i44681# - positioning attributes already set
+ pFmt->PosAttrSet();
+ // <--
+
+ SwDrawContact *pContact = new SwDrawContact( pFmt, &rSdrObj );
+ // --> OD 2004-11-22 #i35635#
+ pContact->MoveObjToVisibleLayer( &rSdrObj );
+ // <--
+ if( bCharBound )
+ {
+ OSL_ENSURE( aAnch.GetAnchorId() == FLY_AS_CHAR, "wrong AnchorType" );
+ SwTxtNode *pNd = aAnch.GetCntntAnchor()->nNode.GetNode().GetTxtNode();
+ SwFmtFlyCnt aFmt( pFmt );
+ pNd->InsertItem(aFmt,
+ aAnch.GetCntntAnchor()->nContent.GetIndex(), 0 );
+ SwFmtVertOrient aVertical( pFmt->GetVertOrient() );
+ aVertical.SetVertOrient( text::VertOrientation::LINE_CENTER );
+ pFmt->SetFmtAttr( aVertical );
+ }
+ if( pAnch->IsTxtFrm() && ((SwTxtFrm*)pAnch)->IsFollow() )
+ {
+ SwTxtFrm* pTmp = (SwTxtFrm*)pAnch;
+ do {
+ pTmp = pTmp->FindMaster();
+ OSL_ENSURE( pTmp, "Where's my Master?" );
+ } while( pTmp->IsFollow() );
+ pAnch = pTmp;
+ }
+
+ pContact->ConnectToLayout();
+
+ // mark object at frame the object is inserted at.
+ {
+ SdrObject* pMarkObj = pContact->GetDrawObjectByAnchorFrm( *pAnch );
+ if ( pMarkObj )
+ {
+ Imp()->GetDrawView()->MarkObj( pMarkObj, Imp()->GetPageView(),
+ sal_False, sal_False );
+ }
+ else
+ {
+ Imp()->GetDrawView()->MarkObj( &rSdrObj, Imp()->GetPageView(),
+ sal_False, sal_False );
+ }
+ }
+ }
+
+ GetDoc()->SetModified();
+
+ KillPams();
+ EndAllActionAndCall();
+ UnlockPaint();
+ return sal_True;
+}
+
+
+/*************************************************************************
+|*
+|* SwFEShell::BreakCreate()
+|*
+*************************************************************************/
+
+void SwFEShell::BreakCreate()
+{
+ OSL_ENSURE( Imp()->HasDrawView(), "BreakCreate without DrawView?" );
+ Imp()->GetDrawView()->BrkCreateObj();
+ ::FrameNotify( this, FLY_DRAG_END );
+}
+
+/*************************************************************************
+|*
+|* SwFEShell::IsDrawCreate()
+|*
+*************************************************************************/
+
+sal_Bool SwFEShell::IsDrawCreate() const
+{
+ return Imp()->HasDrawView() ? Imp()->GetDrawView()->IsCreateObj() : sal_False;
+}
+
+/*************************************************************************
+|*
+|* SwFEShell::BeginMark()
+|*
+*************************************************************************/
+
+sal_Bool SwFEShell::BeginMark( const Point &rPos )
+{
+ if ( !Imp()->HasDrawView() )
+ Imp()->MakeDrawView();
+
+ if ( GetPageNumber( rPos ) )
+ {
+ SwDrawView* pDView = Imp()->GetDrawView();
+
+ if (pDView->HasMarkablePoints())
+ return pDView->BegMarkPoints( rPos );
+ else
+ return pDView->BegMarkObj( rPos );
+ }
+ else
+ return sal_False;
+}
+
+/*************************************************************************
+|*
+|* SwFEShell::MoveMark()
+|*
+*************************************************************************/
+
+void SwFEShell::MoveMark( const Point &rPos )
+{
+ OSL_ENSURE( Imp()->HasDrawView(), "MoveMark without DrawView?" );
+
+ if ( GetPageNumber( rPos ) )
+ {
+ ScrollTo( rPos );
+ SwDrawView* pDView = Imp()->GetDrawView();
+
+ if (pDView->IsInsObjPoint())
+ pDView->MovInsObjPoint( rPos );
+ else if (pDView->IsMarkPoints())
+ pDView->MovMarkPoints( rPos );
+ else
+ pDView->MovAction( rPos );
+ }
+}
+
+/*************************************************************************
+|*
+|* SwFEShell::EndMark()
+|*
+*************************************************************************/
+
+sal_Bool SwFEShell::EndMark()
+{
+ sal_Bool bRet = sal_False;
+ OSL_ENSURE( Imp()->HasDrawView(), "EndMark without DrawView?" );
+
+ if (Imp()->GetDrawView()->IsMarkObj())
+ {
+ bRet = Imp()->GetDrawView()->EndMarkObj();
+
+ if ( bRet )
+ {
+ sal_Bool bShowHdl = sal_False;
+ SwDrawView* pDView = Imp()->GetDrawView();
+ //Rahmen werden auf diese Art nicht Selektiert, es sein denn es
+ //ist nur ein Rahmen.
+ SdrMarkList &rMrkList = (SdrMarkList&)pDView->GetMarkedObjectList();
+ SwFlyFrm* pOldSelFly = ::GetFlyFromMarked( &rMrkList, this );
+
+ if ( rMrkList.GetMarkCount() > 1 )
+ for ( sal_uInt16 i = 0; i < rMrkList.GetMarkCount(); ++i )
+ {
+ SdrObject *pObj = rMrkList.GetMark( i )->GetMarkedSdrObj();
+ if( pObj->ISA(SwVirtFlyDrawObj) )
+ {
+ if ( !bShowHdl )
+ {
+ bShowHdl = sal_True;
+ }
+ rMrkList.DeleteMark( i );
+ --i; //keinen auslassen.
+ }
+ }
+
+ if( bShowHdl )
+ {
+ pDView->MarkListHasChanged();
+ pDView->AdjustMarkHdl();
+ }
+
+ if ( rMrkList.GetMarkCount() )
+ ::lcl_GrabCursor(this, pOldSelFly);
+ else
+ bRet = sal_False;
+ }
+ if ( bRet )
+ ::FrameNotify( this, FLY_DRAG_START );
+ }
+ else
+ {
+ if (Imp()->GetDrawView()->IsMarkPoints())
+ bRet = Imp()->GetDrawView()->EndMarkPoints();
+ }
+
+ SetChainMarker();
+ return bRet;
+}
+
+/*************************************************************************
+|*
+|* SwFEShell::BreakSelect()
+|*
+*************************************************************************/
+
+void SwFEShell::BreakMark()
+{
+ OSL_ENSURE( Imp()->HasDrawView(), "BreakMark without DrawView?" );
+ Imp()->GetDrawView()->BrkMarkObj();
+}
+
+/*************************************************************************
+|*
+|* SwFEShell::GetAnchorId()
+|*
+*************************************************************************/
+
+short SwFEShell::GetAnchorId() const
+{
+ short nRet = SHRT_MAX;
+ if ( Imp()->HasDrawView() )
+ {
+ const SdrMarkList &rMrkList = Imp()->GetDrawView()->GetMarkedObjectList();
+ for ( sal_uInt16 i = 0; i < rMrkList.GetMarkCount(); ++i )
+ {
+ SdrObject *pObj = rMrkList.GetMark( i )->GetMarkedSdrObj();
+ if ( pObj->ISA(SwVirtFlyDrawObj) )
+ {
+ nRet = -1;
+ break;
+ }
+ SwDrawContact *pContact = (SwDrawContact*)GetUserCall(pObj);
+ short nId = static_cast<short>(pContact->GetFmt()->GetAnchor().GetAnchorId());
+ if ( nRet == SHRT_MAX )
+ nRet = nId;
+ else if ( nRet != nId )
+ {
+ nRet = -1;
+ break;
+ }
+ }
+ }
+ if ( nRet == SHRT_MAX )
+ nRet = -1;
+ return nRet;
+}
+
+/*************************************************************************
+|*
+|* SwFEShell::ChgAnchor()
+|*
+*************************************************************************/
+
+void SwFEShell::ChgAnchor( int eAnchorId, sal_Bool bSameOnly, sal_Bool bPosCorr )
+{
+ OSL_ENSURE( Imp()->HasDrawView(), "ChgAnchor without DrawView?" );
+ const SdrMarkList &rMrkList = Imp()->GetDrawView()->GetMarkedObjectList();
+ if( rMrkList.GetMarkCount() &&
+ !rMrkList.GetMark( 0 )->GetMarkedSdrObj()->GetUpGroup() )
+ {
+ StartAllAction();
+
+ if( GetDoc()->ChgAnchor( rMrkList, (RndStdIds)eAnchorId, bSameOnly, bPosCorr ))
+ Imp()->GetDrawView()->UnmarkAll();
+
+ EndAllAction();
+
+ ::FrameNotify( this, FLY_DRAG );
+ }
+}
+
+/*************************************************************************
+|*
+|* SwFEShell::DelSelectedObj()
+|*
+*************************************************************************/
+
+void SwFEShell::DelSelectedObj()
+{
+ OSL_ENSURE( Imp()->HasDrawView(), "DelSelectedObj(), no DrawView available" );
+ if ( Imp()->HasDrawView() )
+ {
+ StartAllAction();
+ Imp()->GetDrawView()->DeleteMarked();
+ EndAllAction();
+ ::FrameNotify( this, FLY_DRAG_END );
+ }
+}
+
+/*************************************************************************
+|*
+|* SwFEShell::GetObjSize(), GetAnchorObjDiff()
+|*
+|* Beschreibung Fuer die Statuszeile zum Erfragen der aktuellen
+|* Verhaeltnisse
+|*
+*************************************************************************/
+
+Size SwFEShell::GetObjSize() const
+{
+ Rectangle aRect;
+ if ( Imp()->HasDrawView() )
+ {
+ if ( Imp()->GetDrawView()->IsAction() )
+ Imp()->GetDrawView()->TakeActionRect( aRect );
+ else
+ aRect = Imp()->GetDrawView()->GetAllMarkedRect();
+ }
+ return aRect.GetSize();
+}
+
+Point SwFEShell::GetAnchorObjDiff() const
+{
+ const SdrView *pView = Imp()->GetDrawView();
+ OSL_ENSURE( pView, "GetAnchorObjDiff without DrawView?" );
+
+ Rectangle aRect;
+ if ( Imp()->GetDrawView()->IsAction() )
+ Imp()->GetDrawView()->TakeActionRect( aRect );
+ else
+ aRect = Imp()->GetDrawView()->GetAllMarkedRect();
+
+ Point aRet( aRect.TopLeft() );
+
+ if ( IsFrmSelected() )
+ {
+ SwFlyFrm *pFly = FindFlyFrm();
+ aRet -= pFly->GetAnchorFrm()->Frm().Pos();
+ }
+ else
+ {
+ const SdrObject *pObj = pView->GetMarkedObjectList().GetMarkCount() == 1 ?
+ pView->GetMarkedObjectList().GetMark(0)->GetMarkedSdrObj() : 0;
+ if ( pObj )
+ aRet -= pObj->GetAnchorPos();
+ }
+
+ return aRet;
+}
+
+Point SwFEShell::GetObjAbsPos() const
+{
+ OSL_ENSURE( Imp()->GetDrawView(), "GetObjAbsPos() without DrawView?" );
+ return Imp()->GetDrawView()->GetDragStat().GetActionRect().TopLeft();
+}
+
+
+
+/*************************************************************************
+|*
+|* SwFEShell::IsGroupSelected()
+|*
+*************************************************************************/
+
+sal_Bool SwFEShell::IsGroupSelected()
+{
+ if ( IsObjSelected() )
+ {
+ const SdrMarkList &rMrkList = Imp()->GetDrawView()->GetMarkedObjectList();
+ for ( sal_uInt16 i = 0; i < rMrkList.GetMarkCount(); ++i )
+ {
+ SdrObject *pObj = rMrkList.GetMark( i )->GetMarkedSdrObj();
+ // consider 'virtual' drawing objects.
+ // Thus, use corresponding method instead of checking type.
+ if ( pObj->IsGroupObject() &&
+ // --> #i38505# No ungroup allowed for 3d objects
+ !pObj->Is3DObj() &&
+ // <--
+ FLY_AS_CHAR != ((SwDrawContact*)GetUserCall(pObj))->
+ GetFmt()->GetAnchor().GetAnchorId() )
+ {
+ return sal_True;
+ }
+ }
+ }
+ return sal_False;
+}
+
+// Change return type.
+// Adjustments for drawing objects in header/footer:
+// allow group, only if all selected objects are in the same header/footer
+// or not in header/footer.
+bool SwFEShell::IsGroupAllowed() const
+{
+ bool bIsGroupAllowed = false;
+ if ( IsObjSelected() > 1 )
+ {
+ bIsGroupAllowed = true;
+ const SdrObject* pUpGroup = 0L;
+ const SwFrm* pHeaderFooterFrm = 0L;
+ const SdrMarkList &rMrkList = Imp()->GetDrawView()->GetMarkedObjectList();
+ for ( sal_uInt16 i = 0; bIsGroupAllowed && i < rMrkList.GetMarkCount(); ++i )
+ {
+ const SdrObject* pObj = rMrkList.GetMark( i )->GetMarkedSdrObj();
+ if ( i )
+ bIsGroupAllowed = pObj->GetUpGroup() == pUpGroup;
+ else
+ pUpGroup = pObj->GetUpGroup();
+
+ if ( bIsGroupAllowed )
+ {
+ SwFrmFmt* pFrmFmt( ::FindFrmFmt( const_cast<SdrObject*>(pObj) ) );
+ if ( !pFrmFmt )
+ {
+ OSL_FAIL( "<SwFEShell::IsGroupAllowed()> - missing frame format" );
+ bIsGroupAllowed = false;
+ }
+ else if ( FLY_AS_CHAR == pFrmFmt->GetAnchor().GetAnchorId() )
+ {
+ bIsGroupAllowed = false;
+ }
+ }
+
+ // check, if all selected objects are in the
+ // same header/footer or not in header/footer.
+ if ( bIsGroupAllowed )
+ {
+ const SwFrm* pAnchorFrm = 0L;
+ if ( pObj->ISA(SwVirtFlyDrawObj) )
+ {
+ const SwFlyFrm* pFlyFrm =
+ static_cast<const SwVirtFlyDrawObj*>(pObj)->GetFlyFrm();
+ if ( pFlyFrm )
+ {
+ pAnchorFrm = pFlyFrm->GetAnchorFrm();
+ }
+ }
+ else
+ {
+ SwDrawContact* pDrawContact = static_cast<SwDrawContact*>(GetUserCall( pObj ));
+ if ( pDrawContact )
+ {
+ pAnchorFrm = pDrawContact->GetAnchorFrm( pObj );
+ }
+ }
+ if ( pAnchorFrm )
+ {
+ if ( i )
+ {
+ bIsGroupAllowed =
+ ( pAnchorFrm->FindFooterOrHeader() == pHeaderFooterFrm );
+ }
+ else
+ {
+ pHeaderFooterFrm = pAnchorFrm->FindFooterOrHeader();
+ }
+ }
+ }
+
+ }
+ }
+
+ return bIsGroupAllowed;
+}
+
+/*************************************************************************
+|*
+|* SwFEShell::GroupSelection()
+|*
+|* Beschreibung Die Gruppe bekommt den Anker und das Contactobjekt
+|* des ersten in der Selektion
+|*
+*************************************************************************/
+
+void SwFEShell::GroupSelection()
+{
+ if ( IsGroupAllowed() )
+ {
+ StartAllAction();
+ StartUndo( UNDO_START );
+
+ GetDoc()->GroupSelection( *Imp()->GetDrawView() );
+
+ EndUndo( UNDO_END );
+ EndAllAction();
+ }
+}
+
+/*************************************************************************
+|*
+|* SwFEShell::UnGroupSelection()
+|*
+|* Beschreibung Die Einzelobjekte bekommen eine Kopie vom Anker und
+|* Contactobjekt der Gruppe.
+|*
+*************************************************************************/
+
+void SwFEShell::UnGroupSelection()
+{
+ if ( IsGroupSelected() )
+ {
+ StartAllAction();
+ StartUndo( UNDO_START );
+
+ GetDoc()->UnGroupSelection( *Imp()->GetDrawView() );
+
+ EndUndo( UNDO_END );
+ EndAllAction();
+ }
+}
+
+/*************************************************************************
+|*
+|* SwFEShell::MirrorSelection()
+|*
+*************************************************************************/
+
+void SwFEShell::MirrorSelection( sal_Bool bHorizontal )
+{
+ SdrView *pView = Imp()->GetDrawView();
+ if ( IsObjSelected() && pView->IsMirrorAllowed() )
+ {
+ if ( bHorizontal )
+ pView->MirrorAllMarkedHorizontal();
+ else
+ pView->MirrorAllMarkedVertical();
+ }
+}
+
+// springe zum benannten Rahmen (Grafik/OLE)
+
+sal_Bool SwFEShell::GotoFly( const String& rName, FlyCntType eType, sal_Bool bSelFrm )
+{
+ sal_Bool bRet = sal_False;
+ static sal_uInt8 const aChkArr[ 4 ] = {
+ /* FLYCNTTYPE_ALL */ 0,
+ /* FLYCNTTYPE_FRM */ ND_TEXTNODE,
+ /* FLYCNTTYPE_GRF */ ND_GRFNODE,
+ /* FLYCNTTYPE_OLE */ ND_OLENODE
+ };
+
+ const SwFlyFrmFmt* pFlyFmt = pDoc->FindFlyByName( rName, aChkArr[ eType]);
+ if( pFlyFmt )
+ {
+ SET_CURR_SHELL( this );
+
+ SwFlyFrm* pFrm = SwIterator<SwFlyFrm,SwFmt>::FirstElement( *pFlyFmt );
+ if( pFrm )
+ {
+ if( bSelFrm )
+ {
+ SelectObj( pFrm->Frm().Pos(), 0, pFrm->GetVirtDrawObj() );
+ if( !ActionPend() )
+ MakeVisible( pFrm->Frm() );
+ }
+ else
+ {
+ SwCntntFrm *pCFrm = pFrm->ContainsCntnt();
+ if ( pCFrm )
+ {
+ SwCntntNode *pCNode = pCFrm->GetNode();
+ ClearMark();
+ SwPaM* pCrsr = GetCrsr();
+
+ pCrsr->GetPoint()->nNode = *pCNode;
+ pCrsr->GetPoint()->nContent.Assign( pCNode, 0 );
+
+ SwRect& rChrRect = (SwRect&)GetCharRect();
+ rChrRect = pFrm->Prt();
+ rChrRect.Pos() += pFrm->Frm().Pos();
+ GetCrsrDocPos() = rChrRect.Pos();
+ }
+ }
+ bRet = sal_True;
+ }
+ }
+ return bRet;
+}
+
+sal_uInt16 SwFEShell::GetFlyCount( FlyCntType eType ) const
+{
+ return GetDoc()->GetFlyCount(eType);
+}
+
+
+const SwFrmFmt* SwFEShell::GetFlyNum(sal_uInt16 nIdx, FlyCntType eType ) const
+{
+ return GetDoc()->GetFlyNum(nIdx, eType );
+}
+
+// zeige das akt. selektierte "Object" an
+void SwFEShell::MakeSelVisible()
+{
+ if( Imp()->HasDrawView() &&
+ Imp()->GetDrawView()->GetMarkedObjectList().GetMarkCount() )
+ {
+ MakeVisible( Imp()->GetDrawView()->GetAllMarkedRect() );
+ }
+ else
+ SwCrsrShell::MakeSelVisible();
+}
+
+
+//Welcher Schutz ist am selektierten Objekt gesetzt?
+sal_uInt8 SwFEShell::IsSelObjProtected( sal_uInt16 eType ) const
+{
+ int nChk = 0;
+ const bool bParent = (eType & FLYPROTECT_PARENT);
+ if( Imp()->HasDrawView() )
+ {
+ const SdrMarkList &rMrkList = Imp()->GetDrawView()->GetMarkedObjectList();
+ for( sal_uLong i = rMrkList.GetMarkCount(); i; )
+ {
+ SdrObject *pObj = rMrkList.GetMark( --i )->GetMarkedSdrObj();
+ if( !bParent )
+ {
+ nChk |= ( pObj->IsMoveProtect() ? FLYPROTECT_POS : 0 ) |
+ ( pObj->IsResizeProtect()? FLYPROTECT_SIZE : 0 );
+
+ if( pObj->ISA(SwVirtFlyDrawObj) )
+ {
+ SwFlyFrm *pFly = ((SwVirtFlyDrawObj*)pObj)->GetFlyFrm();
+ if ( (FLYPROTECT_CONTENT & eType) && pFly->GetFmt()->GetProtect().IsCntntProtected() )
+ nChk |= FLYPROTECT_CONTENT;
+
+ if ( pFly->Lower() && pFly->Lower()->IsNoTxtFrm() )
+ {
+ SwOLENode *pNd = ((SwCntntFrm*)pFly->Lower())->GetNode()->GetOLENode();
+ uno::Reference < embed::XEmbeddedObject > xObj( pNd ? pNd->GetOLEObj().GetOleRef() : 0 );
+ if ( xObj.is() )
+ {
+ // TODO/LATER: use correct aspect
+ const bool bNeverResize = (embed::EmbedMisc::EMBED_NEVERRESIZE & xObj->getStatus( embed::Aspects::MSOLE_CONTENT ));
+ if ( (FLYPROTECT_CONTENT & eType) && bNeverResize )
+ {
+ nChk |= FLYPROTECT_SIZE;
+ nChk |= FLYPROTECT_FIXED;
+ }
+
+ // set FLYPROTECT_POS if it is a Math object anchored 'as char' and baseline alignment is activated
+ const bool bProtectMathPos = SotExchange::IsMath( xObj->getClassID() )
+ && FLY_AS_CHAR == pFly->GetFmt()->GetAnchor().GetAnchorId()
+ && pDoc->get( IDocumentSettingAccess::MATH_BASELINE_ALIGNMENT );
+ if ((FLYPROTECT_POS & eType) && bProtectMathPos)
+ nChk |= FLYPROTECT_POS;
+ }
+ }
+ }
+ nChk &= eType;
+ if( nChk == eType )
+ return static_cast<sal_uInt8>(eType);
+ }
+ const SwFrm* pAnch;
+ if( pObj->ISA(SwVirtFlyDrawObj) )
+ pAnch = ( (SwVirtFlyDrawObj*)pObj )->GetFlyFrm()->GetAnchorFrm();
+ else
+ {
+ SwDrawContact* pTmp = (SwDrawContact*)GetUserCall(pObj);
+ pAnch = pTmp ? pTmp->GetAnchorFrm( pObj ) : NULL;
+ }
+ if( pAnch && pAnch->IsProtected() )
+ return static_cast<sal_uInt8>(eType);
+ }
+ }
+ return static_cast<sal_uInt8>(nChk);
+}
+
+sal_Bool SwFEShell::GetObjAttr( SfxItemSet &rSet ) const
+{
+ if ( !IsObjSelected() )
+ return sal_False;
+
+ const SdrMarkList &rMrkList = Imp()->GetDrawView()->GetMarkedObjectList();
+ for ( sal_uInt16 i = 0; i < rMrkList.GetMarkCount(); ++i )
+ {
+ SdrObject *pObj = rMrkList.GetMark( i )->GetMarkedSdrObj();
+ SwDrawContact *pContact = (SwDrawContact*)GetUserCall(pObj);
+ // --> make code robust
+ OSL_ENSURE( pContact, "<SwFEShell::GetObjAttr(..)> - missing <pContact> - please inform OD." );
+ if ( pContact )
+ {
+ if ( i )
+ rSet.MergeValues( pContact->GetFmt()->GetAttrSet() );
+ else
+ rSet.Put( pContact->GetFmt()->GetAttrSet() );
+ }
+ // <--
+ }
+ return sal_True;
+}
+
+sal_Bool SwFEShell::SetObjAttr( const SfxItemSet& rSet )
+{
+ SET_CURR_SHELL( this );
+
+ if ( !rSet.Count() )
+ { OSL_ENSURE( !this, "SetObjAttr, empty set." );
+ return sal_False;
+ }
+
+ StartAllAction();
+ StartUndo( UNDO_INSATTR );
+
+ const SdrMarkList &rMrkList = Imp()->GetDrawView()->GetMarkedObjectList();
+ for ( sal_uInt16 i = 0; i < rMrkList.GetMarkCount(); ++i )
+ {
+ SdrObject *pObj = rMrkList.GetMark( i )->GetMarkedSdrObj();
+ SwDrawContact *pContact = (SwDrawContact*)GetUserCall(pObj);
+ GetDoc()->SetAttr( rSet, *pContact->GetFmt() );
+ }
+
+ EndUndo( UNDO_INSATTR );
+ EndAllActionAndCall();
+ GetDoc()->SetModified();
+ return sal_True;
+}
+
+sal_Bool SwFEShell::IsAlignPossible() const
+{
+ sal_uInt16 nCnt;
+ if ( 0 < (nCnt = IsObjSelected()) )
+ {
+ sal_Bool bRet = sal_True;
+ if ( nCnt == 1 )
+ {
+ SdrObject *pO = Imp()->GetDrawView()->GetMarkedObjectList().GetMark(0)->GetMarkedSdrObj();
+ SwDrawContact *pC = (SwDrawContact*)GetUserCall(pO);
+ //only as character bound drawings can be aligned
+ bRet = (pC->GetFmt()->GetAnchor().GetAnchorId() == FLY_AS_CHAR);
+ }
+ if ( bRet )
+ return Imp()->GetDrawView()->IsAlignPossible();
+ }
+ return sal_False;
+}
+
+
+//Temporaerer Fix bis SS von JOE da ist
+void SwFEShell::CheckUnboundObjects()
+{
+ SET_CURR_SHELL( this );
+
+ const SdrMarkList &rMrkList = Imp()->GetDrawView()->GetMarkedObjectList();
+ for ( sal_uInt16 i = 0; i < rMrkList.GetMarkCount(); ++i )
+ {
+ SdrObject *pObj = rMrkList.GetMark( i )->GetMarkedSdrObj();
+ if ( !GetUserCall(pObj) )
+ {
+ const Rectangle &rBound = pObj->GetSnapRect();
+ const Point aPt( rBound.TopLeft() );
+ const SwFrm *pPage = GetLayout()->Lower();
+ const SwFrm *pLast = pPage;
+ while ( pPage && !pPage->Frm().IsInside( aPt ) )
+ {
+ if ( aPt.Y() > pPage->Frm().Bottom() )
+ pLast = pPage;
+ pPage = pPage->GetNext();
+ }
+ if ( !pPage )
+ pPage = pLast;
+ OSL_ENSURE( pPage, "Page not found." );
+
+ //Fremde Identifier sollen in den Default laufen.
+ //Ueberschneidungen sind moeglich!!
+ sal_uInt16 nIdent =
+ Imp()->GetDrawView()->GetCurrentObjInventor() == SdrInventor ?
+ Imp()->GetDrawView()->GetCurrentObjIdentifier() : 0xFFFF;
+
+ SwFmtAnchor aAnch;
+ const SwFrm *pAnch = 0;
+ {
+ pAnch = ::FindAnchor( pPage, aPt, sal_True );
+ SwPosition aPos( *((SwCntntFrm*)pAnch)->GetNode() );
+ aAnch.SetType( FLY_AT_PARA );
+ aAnch.SetAnchor( &aPos );
+ ((SwRect&)GetCharRect()).Pos() = aPt;
+ }
+
+ //Erst hier die Action, damit das GetCharRect aktuelle Werte liefert.
+ StartAllAction();
+
+ SfxItemSet aSet( GetAttrPool(), RES_FRM_SIZE, RES_FRM_SIZE,
+ RES_SURROUND, RES_ANCHOR, 0 );
+ aSet.Put( aAnch );
+
+ Point aRelNullPt;
+
+ if( OBJ_CAPTION == nIdent )
+ aRelNullPt = ((SdrCaptionObj*)pObj)->GetTailPos();
+ else
+ aRelNullPt = rBound.TopLeft();
+
+ aSet.Put( aAnch );
+ aSet.Put( SwFmtSurround( SURROUND_THROUGHT ) );
+ SwFrmFmt* pFmt = getIDocumentLayoutAccess()->MakeLayoutFmt( RND_DRAW_OBJECT, &aSet );
+
+ SwDrawContact *pContact = new SwDrawContact(
+ (SwDrawFrmFmt*)pFmt, pObj );
+
+ // --> OD 2004-11-22 #i35635#
+ pContact->MoveObjToVisibleLayer( pObj );
+ // <--
+ pContact->ConnectToLayout();
+
+ EndAllAction();
+ }
+ }
+}
+
+void SwFEShell::SetCalcFieldValueHdl(Outliner* pOutliner)
+{
+ GetDoc()->SetCalcFieldValueHdl(pOutliner);
+}
+
+
+
+int SwFEShell::Chainable( SwRect &rRect, const SwFrmFmt &rSource,
+ const Point &rPt ) const
+{
+ rRect.Clear();
+
+ //Die Source darf noch keinen Follow haben.
+ const SwFmtChain &rChain = rSource.GetChain();
+ if ( rChain.GetNext() )
+ return SW_CHAIN_SOURCE_CHAINED;
+
+ if( Imp()->HasDrawView() )
+ {
+ SdrObject* pObj;
+ SdrPageView* pPView;
+ SwDrawView *pDView = (SwDrawView*)Imp()->GetDrawView();
+ const sal_uInt16 nOld = pDView->GetHitTolerancePixel();
+ pDView->SetHitTolerancePixel( 0 );
+ if( pDView->PickObj( rPt, pDView->getHitTolLog(), pObj, pPView, SDRSEARCH_PICKMARKABLE ) &&
+ pObj->ISA(SwVirtFlyDrawObj) )
+ {
+ SwFlyFrm *pFly = ((SwVirtFlyDrawObj*)pObj)->GetFlyFrm();
+ rRect = pFly->Frm();
+
+ //Ziel darf natuerlich nicht gleich Source sein und es
+ //darf keine geschlossene Kette entstehen.
+ SwFrmFmt *pFmt = pFly->GetFmt();
+ return GetDoc()->Chainable(rSource, *pFmt);
+ }
+ pDView->SetHitTolerancePixel( nOld );
+ }
+ return SW_CHAIN_NOT_FOUND;
+}
+
+int SwFEShell::Chain( SwFrmFmt &rSource, const SwFrmFmt &rDest )
+{
+ return GetDoc()->Chain(rSource, rDest);
+}
+
+int SwFEShell::Chain( SwFrmFmt &rSource, const Point &rPt )
+{
+ SwRect aDummy;
+ int nErr = Chainable( aDummy, rSource, rPt );
+ if ( !nErr )
+ {
+ StartAllAction();
+ SdrObject* pObj;
+ SdrPageView* pPView;
+ SwDrawView *pDView = (SwDrawView*)Imp()->GetDrawView();
+ const sal_uInt16 nOld = pDView->GetHitTolerancePixel();
+ pDView->SetHitTolerancePixel( 0 );
+ pDView->PickObj( rPt, pDView->getHitTolLog(), pObj, pPView, SDRSEARCH_PICKMARKABLE );
+ pDView->SetHitTolerancePixel( nOld );
+ SwFlyFrm *pFly = ((SwVirtFlyDrawObj*)pObj)->GetFlyFrm();
+
+ SwFlyFrmFmt *pFmt = (SwFlyFrmFmt*)pFly->GetFmt();
+ GetDoc()->Chain(rSource, *pFmt);
+ EndAllAction();
+ SetChainMarker();
+ }
+ return nErr;
+}
+
+void SwFEShell::Unchain( SwFrmFmt &rFmt )
+{
+ StartAllAction();
+ GetDoc()->Unchain(rFmt);
+ EndAllAction();
+}
+
+
+void SwFEShell::HideChainMarker()
+{
+ if ( pChainFrom )
+ {
+ delete pChainFrom;
+ pChainFrom = 0L;
+ }
+ if ( pChainTo )
+ {
+ delete pChainTo;
+ pChainTo = 0L;
+ }
+}
+
+void SwFEShell::SetChainMarker()
+{
+ sal_Bool bDelFrom = sal_True,
+ bDelTo = sal_True;
+ if ( IsFrmSelected() )
+ {
+ SwFlyFrm *pFly = FindFlyFrm();
+
+ if ( pFly->GetPrevLink() )
+ {
+ bDelFrom = sal_False;
+ const SwFrm *pPre = pFly->GetPrevLink();
+
+ Point aStart( pPre->Frm().Right(), pPre->Frm().Bottom());
+ Point aEnd(pFly->Frm().Pos());
+
+ if ( !pChainFrom )
+ {
+ pChainFrom = new SdrDropMarkerOverlay( *GetDrawView(), aStart, aEnd );
+ }
+ }
+ if ( pFly->GetNextLink() )
+ {
+ bDelTo = sal_False;
+ const SwFlyFrm *pNxt = pFly->GetNextLink();
+
+ Point aStart( pFly->Frm().Right(), pFly->Frm().Bottom());
+ Point aEnd(pNxt->Frm().Pos());
+
+ if ( !pChainTo )
+ {
+ pChainTo = new SdrDropMarkerOverlay( *GetDrawView(), aStart, aEnd );
+ }
+ }
+ }
+
+ if ( bDelFrom )
+ {
+ delete pChainFrom, pChainFrom = 0;
+ }
+
+ if ( bDelTo )
+ {
+ delete pChainTo, pChainTo = 0;
+ }
+}
+
+long SwFEShell::GetSectionWidth( SwFmt& rFmt ) const
+{
+ SwFrm *pFrm = GetCurrFrm();
+ // Steht der Cursor z.Z. in einem SectionFrm?
+ if( pFrm && pFrm->IsInSct() )
+ {
+ SwSectionFrm* pSect = pFrm->FindSctFrm();
+ do
+ {
+ // Ist es der Gewuenschte?
+ if( pSect->KnowsFormat( rFmt ) )
+ return pSect->Frm().Width();
+ // fuer geschachtelte Bereiche
+ pSect = pSect->GetUpper()->FindSctFrm();
+ }
+ while( pSect );
+ }
+ SwIterator<SwSectionFrm,SwFmt> aIter( rFmt );
+ for ( SwSectionFrm* pSct = aIter.First(); pFrm; pFrm = aIter.Next() )
+ if( !pSct->IsFollow() )
+ return pSct->Frm().Width();
+ return 0;
+}
+
+ void SwFEShell::CreateDefaultShape( sal_uInt16 /*SdrObjKind ?*/ eSdrObjectKind, const Rectangle& rRect,
+ sal_uInt16 nSlotId)
+{
+ SdrView* pDrawView = GetDrawView();
+ SdrModel* pDrawModel = pDrawView->GetModel();
+ SdrObject* pObj = SdrObjFactory::MakeNewObject(
+ SdrInventor, eSdrObjectKind,
+ 0L, pDrawModel);
+
+ if(pObj)
+ {
+ Rectangle aRect(rRect);
+ if(OBJ_CARC == eSdrObjectKind || OBJ_CCUT == eSdrObjectKind)
+ {
+ // force quadratic
+ if(aRect.GetWidth() > aRect.GetHeight())
+ {
+ aRect = Rectangle(
+ Point(aRect.Left() + ((aRect.GetWidth() - aRect.GetHeight()) / 2), aRect.Top()),
+ Size(aRect.GetHeight(), aRect.GetHeight()));
+ }
+ else
+ {
+ aRect = Rectangle(
+ Point(aRect.Left(), aRect.Top() + ((aRect.GetHeight() - aRect.GetWidth()) / 2)),
+ Size(aRect.GetWidth(), aRect.GetWidth()));
+ }
+ }
+ pObj->SetLogicRect(aRect);
+
+ if(pObj->ISA(SdrCircObj))
+ {
+ SfxItemSet aAttr(pDrawModel->GetItemPool());
+ aAttr.Put(SdrCircStartAngleItem(9000));
+ aAttr.Put(SdrCircEndAngleItem(0));
+ pObj->SetMergedItemSet(aAttr);
+ }
+ else if(pObj->ISA(SdrPathObj))
+ {
+ basegfx::B2DPolyPolygon aPoly;
+
+ switch(eSdrObjectKind)
+ {
+ case OBJ_PATHLINE:
+ {
+ basegfx::B2DPolygon aInnerPoly;
+
+ aInnerPoly.append(basegfx::B2DPoint(aRect.Left(), aRect.Bottom()));
+
+ const basegfx::B2DPoint aCenterBottom(aRect.Center().X(), aRect.Bottom());
+ aInnerPoly.appendBezierSegment(
+ aCenterBottom,
+ aCenterBottom,
+ basegfx::B2DPoint(aRect.Center().X(), aRect.Center().Y()));
+
+ const basegfx::B2DPoint aCenterTop(aRect.Center().X(), aRect.Top());
+ aInnerPoly.appendBezierSegment(
+ aCenterTop,
+ aCenterTop,
+ basegfx::B2DPoint(aRect.Right(), aRect.Top()));
+
+ aInnerPoly.setClosed(true);
+ aPoly.append(aInnerPoly);
+ }
+ break;
+ case OBJ_FREELINE:
+ {
+ basegfx::B2DPolygon aInnerPoly;
+
+ aInnerPoly.append(basegfx::B2DPoint(aRect.Left(), aRect.Bottom()));
+
+ aInnerPoly.appendBezierSegment(
+ basegfx::B2DPoint(aRect.Left(), aRect.Top()),
+ basegfx::B2DPoint(aRect.Center().X(), aRect.Top()),
+ basegfx::B2DPoint(aRect.Center().X(), aRect.Center().Y()));
+
+ aInnerPoly.appendBezierSegment(
+ basegfx::B2DPoint(aRect.Center().X(), aRect.Bottom()),
+ basegfx::B2DPoint(aRect.Right(), aRect.Bottom()),
+ basegfx::B2DPoint(aRect.Right(), aRect.Top()));
+
+ aInnerPoly.append(basegfx::B2DPoint(aRect.Right(), aRect.Bottom()));
+ aInnerPoly.setClosed(true);
+ aPoly.append(aInnerPoly);
+ }
+ break;
+ case OBJ_POLY:
+ case OBJ_PLIN:
+ {
+ basegfx::B2DPolygon aInnerPoly;
+ sal_Int32 nWdt(aRect.GetWidth());
+ sal_Int32 nHgt(aRect.GetHeight());
+
+ aInnerPoly.append(basegfx::B2DPoint(aRect.Left(), aRect.Bottom()));
+ aInnerPoly.append(basegfx::B2DPoint(aRect.Left() + (nWdt * 30) / 100, aRect.Top() + (nHgt * 70) / 100));
+ aInnerPoly.append(basegfx::B2DPoint(aRect.Left(), aRect.Top() + (nHgt * 15) / 100));
+ aInnerPoly.append(basegfx::B2DPoint(aRect.Left() + (nWdt * 65) / 100, aRect.Top()));
+ aInnerPoly.append(basegfx::B2DPoint(aRect.Left() + nWdt, aRect.Top() + (nHgt * 30) / 100));
+ aInnerPoly.append(basegfx::B2DPoint(aRect.Left() + (nWdt * 80) / 100, aRect.Top() + (nHgt * 50) / 100));
+ aInnerPoly.append(basegfx::B2DPoint(aRect.Left() + (nWdt * 80) / 100, aRect.Top() + (nHgt * 75) / 100));
+ aInnerPoly.append(basegfx::B2DPoint(aRect.Bottom(), aRect.Right()));
+
+ if(OBJ_PLIN == eSdrObjectKind)
+ {
+ aInnerPoly.append(basegfx::B2DPoint(aRect.Center().X(), aRect.Bottom()));
+ }
+ else
+ {
+ aInnerPoly.setClosed(true);
+ }
+
+ aPoly.append(aInnerPoly);
+ }
+ break;
+ case OBJ_LINE :
+ {
+ sal_Int32 nYMiddle((aRect.Top() + aRect.Bottom()) / 2);
+ basegfx::B2DPolygon aTempPoly;
+ aTempPoly.append(basegfx::B2DPoint(aRect.TopLeft().X(), nYMiddle));
+ aTempPoly.append(basegfx::B2DPoint(aRect.BottomRight().X(), nYMiddle));
+ aPoly.append(aTempPoly);
+ }
+ break;
+ }
+
+ ((SdrPathObj*)pObj)->SetPathPoly(aPoly);
+ }
+ else if(pObj->ISA(SdrCaptionObj))
+ {
+ sal_Bool bVerticalText = ( SID_DRAW_TEXT_VERTICAL == nSlotId ||
+ SID_DRAW_CAPTION_VERTICAL == nSlotId );
+ ((SdrTextObj*)pObj)->SetVerticalWriting(bVerticalText);
+ if(bVerticalText)
+ {
+ SfxItemSet aSet(pObj->GetMergedItemSet());
+ aSet.Put(SdrTextVertAdjustItem(SDRTEXTVERTADJUST_CENTER));
+ aSet.Put(SdrTextHorzAdjustItem(SDRTEXTHORZADJUST_RIGHT));
+ pObj->SetMergedItemSet(aSet);
+ }
+
+ ((SdrCaptionObj*)pObj)->SetLogicRect(aRect);
+ ((SdrCaptionObj*)pObj)->SetTailPos(
+ aRect.TopLeft() - Point(aRect.GetWidth() / 2, aRect.GetHeight() / 2));
+ }
+ else if(pObj->ISA(SdrTextObj))
+ {
+ SdrTextObj* pText = (SdrTextObj*)pObj;
+ pText->SetLogicRect(aRect);
+
+ sal_Bool bVertical = (SID_DRAW_TEXT_VERTICAL == nSlotId);
+ sal_Bool bMarquee = (SID_DRAW_TEXT_MARQUEE == nSlotId);
+
+ pText->SetVerticalWriting(bVertical);
+
+ if(bVertical)
+ {
+ SfxItemSet aSet(pDrawModel->GetItemPool());
+ aSet.Put(SdrTextAutoGrowWidthItem(sal_True));
+ aSet.Put(SdrTextAutoGrowHeightItem(sal_False));
+ aSet.Put(SdrTextVertAdjustItem(SDRTEXTVERTADJUST_TOP));
+ aSet.Put(SdrTextHorzAdjustItem(SDRTEXTHORZADJUST_RIGHT));
+ pText->SetMergedItemSet(aSet);
+ }
+
+ if(bMarquee)
+ {
+ SfxItemSet aSet(pDrawModel->GetItemPool(), SDRATTR_MISC_FIRST, SDRATTR_MISC_LAST);
+ aSet.Put( SdrTextAutoGrowWidthItem( sal_False ) );
+ aSet.Put( SdrTextAutoGrowHeightItem( sal_False ) );
+ aSet.Put( SdrTextAniKindItem( SDRTEXTANI_SLIDE ) );
+ aSet.Put( SdrTextAniDirectionItem( SDRTEXTANI_LEFT ) );
+ aSet.Put( SdrTextAniCountItem( 1 ) );
+ aSet.Put( SdrTextAniAmountItem( (sal_Int16)GetWin()->PixelToLogic(Size(2,1)).Width()) );
+ pObj->SetMergedItemSetAndBroadcast(aSet);
+ }
+ }
+ SdrPageView* pPageView = pDrawView->GetSdrPageView();
+ pDrawView->InsertObjectAtView(pObj, *pPageView);
+ }
+ ImpEndCreate();
+}
+
+/** SwFEShell::GetShapeBackgrd
+ method determines background color of the page the selected drawing
+ object is on and returns this color.
+ If no color is found, because no drawing object is selected or ...,
+ color COL_BLACK (default color on constructing object of class Color)
+ is returned.
+
+ @author OD
+
+ @returns an object of class Color
+*/
+const Color SwFEShell::GetShapeBackgrd() const
+{
+ Color aRetColor;
+
+ // check, if a draw view exists
+ OSL_ENSURE( Imp()->GetDrawView(), "wrong usage of SwFEShell::GetShapeBackgrd - no draw view!");
+ if( Imp()->GetDrawView() )
+ {
+ // determine list of selected objects
+ const SdrMarkList* pMrkList = &Imp()->GetDrawView()->GetMarkedObjectList();
+ // check, if exactly one object is selected.
+ OSL_ENSURE( pMrkList->GetMarkCount() == 1, "wrong usage of SwFEShell::GetShapeBackgrd - no selected object!");
+ if ( pMrkList->GetMarkCount() == 1)
+ {
+ // get selected object
+ const SdrObject *pSdrObj = pMrkList->GetMark( 0 )->GetMarkedSdrObj();
+ // check, if selected object is a shape (drawing object)
+ OSL_ENSURE( !pSdrObj->ISA(SwVirtFlyDrawObj), "wrong usage of SwFEShell::GetShapeBackgrd - selected object is not a drawing object!");
+ if ( !pSdrObj->ISA(SwVirtFlyDrawObj) )
+ {
+ // determine page frame of the frame the shape is anchored.
+ const SwFrm* pAnchorFrm =
+ static_cast<SwDrawContact*>(GetUserCall(pSdrObj))->GetAnchorFrm( pSdrObj );
+ OSL_ENSURE( pAnchorFrm, "inconsistent modell - no anchor at shape!");
+ if ( pAnchorFrm )
+ {
+ const SwPageFrm* pPageFrm = pAnchorFrm->FindPageFrm();
+ OSL_ENSURE( pPageFrm, "inconsistent modell - no page!");
+ if ( pPageFrm )
+ {
+ aRetColor = pPageFrm->GetDrawBackgrdColor();
+ }
+ }
+ }
+ }
+ }
+
+ return aRetColor;
+}
+
+/** Is default horizontal text direction for selected drawing object right-to-left
+ Because drawing objects only painted for each page only, the default
+ horizontal text direction of a drawing object is given by the corresponding
+ page property.
+
+ @author OD
+
+ @returns boolean, indicating, if the horizontal text direction of the
+ page, the selected drawing object is on, is right-to-left.
+*/
+bool SwFEShell::IsShapeDefaultHoriTextDirR2L() const
+{
+ bool bRet = false;
+
+ // check, if a draw view exists
+ OSL_ENSURE( Imp()->GetDrawView(), "wrong usage of SwFEShell::GetShapeBackgrd - no draw view!");
+ if( Imp()->GetDrawView() )
+ {
+ // determine list of selected objects
+ const SdrMarkList* pMrkList = &Imp()->GetDrawView()->GetMarkedObjectList();
+ // check, if exactly one object is selected.
+ OSL_ENSURE( pMrkList->GetMarkCount() == 1, "wrong usage of SwFEShell::GetShapeBackgrd - no selected object!");
+ if ( pMrkList->GetMarkCount() == 1)
+ {
+ // get selected object
+ const SdrObject *pSdrObj = pMrkList->GetMark( 0 )->GetMarkedSdrObj();
+ // check, if selected object is a shape (drawing object)
+ OSL_ENSURE( !pSdrObj->ISA(SwVirtFlyDrawObj), "wrong usage of SwFEShell::GetShapeBackgrd - selected object is not a drawing object!");
+ if ( !pSdrObj->ISA(SwVirtFlyDrawObj) )
+ {
+ // determine page frame of the frame the shape is anchored.
+ const SwFrm* pAnchorFrm =
+ static_cast<SwDrawContact*>(GetUserCall(pSdrObj))->GetAnchorFrm( pSdrObj );
+ OSL_ENSURE( pAnchorFrm, "inconsistent modell - no anchor at shape!");
+ if ( pAnchorFrm )
+ {
+ const SwPageFrm* pPageFrm = pAnchorFrm->FindPageFrm();
+ OSL_ENSURE( pPageFrm, "inconsistent modell - no page!");
+ if ( pPageFrm )
+ {
+ bRet = pPageFrm->IsRightToLeft() ? true : false;
+ }
+ }
+ }
+ }
+ }
+
+ return bRet;
+}
+
+Point SwFEShell::GetRelativePagePosition(const Point& rDocPos)
+{
+ Point aRet(-1, -1);
+ const SwFrm *pPage = GetLayout()->Lower();
+ while ( pPage && !pPage->Frm().IsInside( rDocPos ) )
+ {
+ pPage = pPage->GetNext();
+ }
+ if(pPage)
+ {
+ aRet = rDocPos - pPage->Frm().TopLeft();
+ }
+ return aRet;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/frmedt/fetab.cxx b/sw/source/core/frmedt/fetab.cxx
new file mode 100644
index 000000000000..90d74a24a380
--- /dev/null
+++ b/sw/source/core/frmedt/fetab.cxx
@@ -0,0 +1,2509 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+ /*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+
+#include <hintids.hxx>
+
+#include <tools/errinf.hxx>
+#include <vcl/svapp.hxx>
+#include <basegfx/vector/b2dvector.hxx>
+#include <svx/svxids.hrc>
+#include <editeng/protitem.hxx>
+#include <editeng/brshitem.hxx>
+#include <editeng/frmdiritem.hxx>
+#include <svtools/ruler.hxx>
+#include <swwait.hxx>
+#include <fmtfsize.hxx>
+#include <fmtornt.hxx>
+#include <frmatr.hxx>
+#include <docary.hxx>
+#include <fesh.hxx>
+#include <doc.hxx>
+#include <cntfrm.hxx>
+#include <rootfrm.hxx>
+#include <pagefrm.hxx>
+#include <tabfrm.hxx>
+#include <rowfrm.hxx>
+#include <cellfrm.hxx>
+#include <flyfrm.hxx>
+#include <dflyobj.hxx>
+#include <swtable.hxx>
+#include <swddetbl.hxx>
+#include <ndtxt.hxx>
+#include <calc.hxx>
+#include <tabcol.hxx>
+#include <cellatr.hxx>
+#include <pam.hxx>
+#include <viscrs.hxx>
+#include <tblsel.hxx>
+#include <swtblfmt.hxx>
+#include <swerror.h>
+#include <swundo.hxx>
+#include <frmtool.hxx>
+
+#include <node.hxx> // #i23726#
+// OD 2004-05-24 #i28701#
+#include <sortedobjs.hxx>
+
+using namespace ::com::sun::star;
+
+
+//siehe auch swtable.cxx
+#define COLFUZZY 20L
+
+inline sal_Bool IsSame( long nA, long nB ) { return Abs(nA-nB) <= COLFUZZY; }
+inline sal_Bool IsNear( long nA, long nB, long nTolerance ) { return Abs( nA - nB ) <= nTolerance; }
+
+// table column cache
+SwTabCols *pLastCols = 0;
+const SwTable *pColumnCacheLastTable = 0;
+const SwTabFrm *pColumnCacheLastTabFrm = 0;
+const SwFrm *pColumnCacheLastCellFrm = 0;
+
+// table row cache
+SwTabCols *pLastRows = 0;
+const SwTable *pRowCacheLastTable = 0;
+const SwTabFrm *pRowCacheLastTabFrm = 0;
+const SwFrm *pRowCacheLastCellFrm = 0;
+
+
+class TblWait
+{
+ SwWait *pWait;
+public:
+ TblWait( sal_uInt16 nCnt, SwFrm *pFrm, SwDocShell &rDocShell, sal_uInt16 nCnt2 = 0);
+ ~TblWait() { delete pWait; }
+};
+
+TblWait::TblWait( sal_uInt16 nCnt, SwFrm *pFrm, SwDocShell &rDocShell, sal_uInt16 nCnt2):
+ pWait( 0 )
+{
+ sal_Bool bWait = 20 < nCnt || 20 < nCnt2 || (pFrm &&
+ 20 < pFrm->ImplFindTabFrm()->GetTable()->GetTabLines().Count());
+ if( bWait )
+ pWait = new SwWait( rDocShell, sal_True );
+}
+
+
+void SwFEShell::ParkCursorInTab()
+{
+ SwCursor * pSwCrsr = GetSwCrsr();
+
+ OSL_ENSURE(pSwCrsr, "no SwCursor");
+
+ SwPosition aStartPos = *pSwCrsr->GetPoint(), aEndPos = aStartPos;
+
+ SwCursor * pTmpCrsr = (SwCursor *) pSwCrsr;
+
+ /* Search least and greatest position in current cursor ring.
+ */
+ do
+ {
+ const SwPosition * pPt = pTmpCrsr->GetPoint(),
+ * pMk = pTmpCrsr->GetMark();
+
+ if (*pPt < aStartPos)
+ aStartPos = *pPt;
+
+ if (*pPt > aEndPos)
+ aEndPos = *pPt;
+
+ if (*pMk < aStartPos)
+ aStartPos = *pMk;
+
+ if (*pMk > aEndPos)
+ aEndPos = *pMk;
+
+ pTmpCrsr = (SwCursor *) pTmpCrsr->GetNext();
+ }
+ while (pTmpCrsr != pSwCrsr);
+
+ KillPams();
+
+ /* @@@ semantic: SwCursor::operator=() is not implemented @@@ */
+
+ /* Set cursor to end of selection to ensure IsLastCellInRow works
+ properly. */
+ {
+ SwCursor aTmpCrsr( aEndPos, 0, false );
+ *pSwCrsr = aTmpCrsr;
+ }
+
+ /* Move the cursor out of the columns to delete and stay in the
+ same row. If the table has only one column the cursor will
+ stay in the row and the shell will take care of it. */
+ if (IsLastCellInRow())
+ {
+ /* If the cursor is in the last row of the table, first
+ try to move it to the previous cell. If that fails move
+ it to the next cell. */
+
+ {
+ SwCursor aTmpCrsr( aStartPos, 0, false );
+ *pSwCrsr = aTmpCrsr;
+ }
+
+ if (! pSwCrsr->GoPrevCell())
+ {
+ SwCursor aTmpCrsr( aEndPos, 0, false );
+ *pSwCrsr = aTmpCrsr;
+ pSwCrsr->GoNextCell();
+ }
+ }
+ else
+ {
+ /* If the cursor is not in the last row of the table, first
+ try to move it to the next cell. If that fails move it
+ to the previous cell. */
+
+ {
+ SwCursor aTmpCrsr( aEndPos, 0, false );
+ *pSwCrsr = aTmpCrsr;
+ }
+
+ if (! pSwCrsr->GoNextCell())
+ {
+ SwCursor aTmpCrsr( aStartPos, 0, false );
+ *pSwCrsr = aTmpCrsr;
+ pSwCrsr->GoPrevCell();
+ }
+ }
+}
+
+/***********************************************************************
+#* Class : SwFEShell
+#* Methoden : InsertRow(), InsertCol
+#***********************************************************************/
+sal_Bool SwFEShell::InsertRow( sal_uInt16 nCnt, sal_Bool bBehind )
+{
+ // pruefe ob vom aktuellen Crsr der Point/Mark in einer Tabelle stehen
+ SwFrm *pFrm = GetCurrFrm();
+ if( !pFrm || !pFrm->IsInTab() )
+ return sal_False;
+
+ if( pFrm->ImplFindTabFrm()->GetTable()->ISA( SwDDETable ))
+ {
+ ErrorHandler::HandleError( ERR_TBLDDECHG_ERROR,
+ ERRCODE_MSG_INFO | ERRCODE_BUTTON_DEF_OK );
+ return sal_False;
+ }
+
+ SET_CURR_SHELL( this );
+ StartAllAction();
+
+ // lasse ueber das Layout die Boxen suchen
+ SwSelBoxes aBoxes;
+ GetTblSel( *this, aBoxes, nsSwTblSearchType::TBLSEARCH_ROW );
+
+ TblWait( nCnt, pFrm, *GetDoc()->GetDocShell(), aBoxes.Count() );
+
+ sal_Bool bRet = sal_False;
+ if ( aBoxes.Count() )
+ bRet = GetDoc()->InsertRow( aBoxes, nCnt, bBehind );
+
+ EndAllActionAndCall();
+ return bRet;
+}
+
+sal_Bool SwFEShell::InsertCol( sal_uInt16 nCnt, sal_Bool bBehind )
+{
+ // pruefe ob vom aktuellen Crsr der Point/Mark in einer Tabelle stehen
+ SwFrm *pFrm = GetCurrFrm();
+ if( !pFrm || !pFrm->IsInTab() )
+ return sal_False;
+
+ if( pFrm->ImplFindTabFrm()->GetTable()->ISA( SwDDETable ))
+ {
+ ErrorHandler::HandleError( ERR_TBLDDECHG_ERROR,
+ ERRCODE_MSG_INFO | ERRCODE_BUTTON_DEF_OK );
+ return sal_False;
+ }
+
+ SET_CURR_SHELL( this );
+
+ if( !CheckSplitCells( *this, nCnt + 1, nsSwTblSearchType::TBLSEARCH_COL ) )
+ {
+ ErrorHandler::HandleError( ERR_TBLINSCOL_ERROR,
+ ERRCODE_MSG_INFO | ERRCODE_BUTTON_DEF_OK );
+ return sal_False;
+ }
+
+ StartAllAction();
+ // lasse ueber das Layout die Boxen suchen
+ SwSelBoxes aBoxes;
+ GetTblSel( *this, aBoxes, nsSwTblSearchType::TBLSEARCH_COL );
+
+ TblWait( nCnt, pFrm, *GetDoc()->GetDocShell(), aBoxes.Count() );
+
+ sal_Bool bRet = sal_False;
+ if( aBoxes.Count() )
+ bRet = GetDoc()->InsertCol( aBoxes, nCnt, bBehind );
+
+ EndAllActionAndCall();
+ return bRet;
+}
+
+/***********************************************************************
+#* Class : SwFEShell
+#* Methoden : DeleteRow(), DeleteCol()
+#***********************************************************************/
+
+/**
+ Determines if the current cursor is in the last row of the table.
+*/
+sal_Bool SwFEShell::IsLastCellInRow() const
+{
+ SwTabCols aTabCols;
+ GetTabCols( aTabCols );
+ sal_Bool bResult = sal_False;
+
+ if (IsTableRightToLeft())
+ /* If the table is right-to-left the last row is the most left one. */
+ bResult = 0 == GetCurTabColNum();
+ else
+ /* If the table is left-to-right the last row is the most right one. */
+ bResult = aTabCols.Count() == GetCurTabColNum();
+
+ return bResult;
+}
+
+sal_Bool SwFEShell::DeleteCol()
+{
+ // pruefe ob vom aktuellen Crsr der SPoint/Mark in einer Tabelle stehen
+ SwFrm *pFrm = GetCurrFrm();
+ if( !pFrm || !pFrm->IsInTab() )
+ return sal_False;
+
+ if( pFrm->ImplFindTabFrm()->GetTable()->ISA( SwDDETable ))
+ {
+ ErrorHandler::HandleError( ERR_TBLDDECHG_ERROR,
+ ERRCODE_MSG_INFO | ERRCODE_BUTTON_DEF_OK );
+ return sal_False;
+ }
+
+ SET_CURR_SHELL( this );
+ StartAllAction();
+
+ // lasse ueber das Layout die Boxen suchen
+ sal_Bool bRet;
+ SwSelBoxes aBoxes;
+ GetTblSel( *this, aBoxes, nsSwTblSearchType::TBLSEARCH_COL );
+ if ( aBoxes.Count() )
+ {
+ TblWait( aBoxes.Count(), pFrm, *GetDoc()->GetDocShell() );
+
+ // die Crsr muessen noch aus dem Loesch Bereich entfernt
+ // werden. Setze sie immer hinter/auf die Tabelle; ueber die
+ // Dokument-Position werden sie dann immer an die alte Position gesetzt.
+ while( !pFrm->IsCellFrm() )
+ pFrm = pFrm->GetUpper();
+
+ ParkCursorInTab();
+
+ // dann loesche doch die Spalten
+ StartUndo(UNDO_COL_DELETE);
+ bRet = GetDoc()->DeleteRowCol( aBoxes, true );
+ EndUndo(UNDO_COL_DELETE);
+
+ }
+ else
+ bRet = sal_False;
+
+ EndAllActionAndCall();
+ return bRet;
+}
+
+sal_Bool SwFEShell::DeleteRow()
+{
+ // pruefe ob vom aktuellen Crsr der SPoint/Mark in einer Tabelle stehen
+ SwFrm *pFrm = GetCurrFrm();
+ if( !pFrm || !pFrm->IsInTab() )
+ return sal_False;
+
+ if( pFrm->ImplFindTabFrm()->GetTable()->ISA( SwDDETable ))
+ {
+ ErrorHandler::HandleError( ERR_TBLDDECHG_ERROR,
+ ERRCODE_MSG_INFO | ERRCODE_BUTTON_DEF_OK );
+ return sal_False;
+ }
+
+ SET_CURR_SHELL( this );
+ StartAllAction();
+
+ // lasse ueber das Layout die Boxen suchen
+ sal_Bool bRet;
+ SwSelBoxes aBoxes;
+ GetTblSel( *this, aBoxes, nsSwTblSearchType::TBLSEARCH_ROW );
+
+ if( aBoxes.Count() )
+ {
+ TblWait( aBoxes.Count(), pFrm, *GetDoc()->GetDocShell() );
+
+ // die Crsr aus dem Loeschbereich entfernen.
+ // Der Cursor steht danach:
+ // - es folgt noch eine Zeile, in dieser
+ // - vorher steht noch eine Zeile, in dieser
+ // - sonst immer dahinter
+ {
+ SwTableNode* pTblNd = ((SwCntntFrm*)pFrm)->GetNode()->FindTableNode();
+
+ // suche alle Boxen / Lines
+ _FndBox aFndBox( 0, 0 );
+ {
+ _FndPara aPara( aBoxes, &aFndBox );
+ pTblNd->GetTable().GetTabLines().ForEach( &_FndLineCopyCol, &aPara );
+ }
+
+ if( !aFndBox.GetLines().Count() )
+ {
+ EndAllActionAndCall();
+ return sal_False;
+ }
+
+ KillPams();
+
+ _FndBox* pFndBox = &aFndBox;
+ while( 1 == pFndBox->GetLines().Count() &&
+ 1 == pFndBox->GetLines()[0]->GetBoxes().Count() )
+ {
+ _FndBox* pTmp = pFndBox->GetLines()[0]->GetBoxes()[0];
+ if( pTmp->GetBox()->GetSttNd() )
+ break; // das ist sonst zu weit
+ pFndBox = pTmp;
+ }
+
+ SwTableLine* pDelLine = pFndBox->GetLines()[
+ pFndBox->GetLines().Count()-1 ]->GetLine();
+ SwTableBox* pDelBox = pDelLine->GetTabBoxes()[
+ pDelLine->GetTabBoxes().Count() - 1 ];
+ while( !pDelBox->GetSttNd() )
+ {
+ SwTableLine* pLn = pDelBox->GetTabLines()[
+ pDelBox->GetTabLines().Count()-1 ];
+ pDelBox = pLn->GetTabBoxes()[ pLn->GetTabBoxes().Count() - 1 ];
+ }
+ SwTableBox* pNextBox = pDelLine->FindNextBox( pTblNd->GetTable(),
+ pDelBox, sal_True );
+ while( pNextBox &&
+ pNextBox->GetFrmFmt()->GetProtect().IsCntntProtected() )
+ pNextBox = pNextBox->FindNextBox( pTblNd->GetTable(), pNextBox );
+
+ if( !pNextBox ) // keine nachfolgende? dann die vorhergehende
+ {
+ pDelLine = pFndBox->GetLines()[ 0 ]->GetLine();
+ pDelBox = pDelLine->GetTabBoxes()[ 0 ];
+ while( !pDelBox->GetSttNd() )
+ pDelBox = pDelBox->GetTabLines()[0]->GetTabBoxes()[0];
+ pNextBox = pDelLine->FindPreviousBox( pTblNd->GetTable(),
+ pDelBox, sal_True );
+ while( pNextBox &&
+ pNextBox->GetFrmFmt()->GetProtect().IsCntntProtected() )
+ pNextBox = pNextBox->FindPreviousBox( pTblNd->GetTable(), pNextBox );
+ }
+
+ sal_uLong nIdx;
+ if( pNextBox ) // dann den Cursor hier hinein
+ nIdx = pNextBox->GetSttIdx() + 1;
+ else // ansonsten hinter die Tabelle
+ nIdx = pTblNd->EndOfSectionIndex() + 1;
+
+ SwNodeIndex aIdx( GetDoc()->GetNodes(), nIdx );
+ SwCntntNode* pCNd = aIdx.GetNode().GetCntntNode();
+ if( !pCNd )
+ pCNd = GetDoc()->GetNodes().GoNext( &aIdx );
+
+ if( pCNd )
+ {
+ SwPaM* pPam = GetCrsr();
+ pPam->GetPoint()->nNode = aIdx;
+ pPam->GetPoint()->nContent.Assign( pCNd, 0 );
+ pPam->SetMark(); // beide wollen etwas davon haben
+ pPam->DeleteMark();
+ }
+ }
+
+ // dann loesche doch die Zeilen
+ StartUndo(UNDO_ROW_DELETE);
+ bRet = GetDoc()->DeleteRowCol( aBoxes );
+ EndUndo(UNDO_ROW_DELETE);
+ }
+ else
+ bRet = sal_False;
+
+ EndAllActionAndCall();
+ return bRet;
+}
+
+/***********************************************************************
+#* Class : SwFEShell
+#* Methoden : MergeTab(), SplitTab()
+#***********************************************************************/
+
+sal_uInt16 SwFEShell::MergeTab()
+{
+ // pruefe ob vom aktuellen Crsr der SPoint/Mark in einer Tabelle stehen
+ sal_uInt16 nRet = TBLMERGE_NOSELECTION;
+ if( IsTableMode() )
+ {
+ SwShellTableCrsr* pTableCrsr = GetTableCrsr();
+ const SwTableNode* pTblNd = pTableCrsr->GetNode()->FindTableNode();
+ if( pTblNd->GetTable().ISA( SwDDETable ))
+ {
+ ErrorHandler::HandleError( ERR_TBLDDECHG_ERROR,
+ ERRCODE_MSG_INFO | ERRCODE_BUTTON_DEF_OK );
+ }
+ else
+ {
+ SET_CURR_SHELL( this );
+ StartAllAction();
+
+ TblWait( pTableCrsr->GetBoxesCount(), 0, *GetDoc()->GetDocShell(),
+ pTblNd->GetTable().GetTabLines().Count() );
+
+ nRet = GetDoc()->MergeTbl( *pTableCrsr );
+
+ KillPams();
+
+ EndAllActionAndCall();
+ }
+ }
+ return nRet;
+}
+
+sal_Bool SwFEShell::SplitTab( sal_Bool bVert, sal_uInt16 nCnt, sal_Bool bSameHeight )
+{
+ // pruefe ob vom aktuellen Crsr der SPoint/Mark in einer Tabelle stehen
+ SwFrm *pFrm = GetCurrFrm();
+ if( !pFrm || !pFrm->IsInTab() )
+ return sal_False;
+
+ if( pFrm->ImplFindTabFrm()->GetTable()->ISA( SwDDETable ))
+ {
+ ErrorHandler::HandleError( ERR_TBLDDECHG_ERROR,
+ ERRCODE_MSG_INFO | ERRCODE_BUTTON_DEF_OK );
+ return sal_False;
+ }
+
+ SET_CURR_SHELL( this );
+
+ if( bVert && !CheckSplitCells( *this, nCnt + 1 ) )
+ {
+ ErrorHandler::HandleError( ERR_TBLSPLIT_ERROR,
+ ERRCODE_MSG_INFO | ERRCODE_BUTTON_DEF_OK );
+ return sal_False;
+ }
+ StartAllAction();
+ // lasse ueber das Layout die Boxen suchen
+ sal_Bool bRet;
+ SwSelBoxes aBoxes;
+ GetTblSel( *this, aBoxes );
+ if( aBoxes.Count() )
+ {
+ TblWait( nCnt, pFrm, *GetDoc()->GetDocShell(), aBoxes.Count() );
+
+ // dann loesche doch die Spalten
+ bRet = GetDoc()->SplitTbl( aBoxes, bVert, nCnt, bSameHeight );
+
+ DELETEZ( pLastCols );
+ DELETEZ( pLastRows );
+ }
+ else
+ bRet = sal_False;
+ EndAllActionAndCall();
+ return bRet;
+}
+
+
+/***********************************************************************
+#* Class : SwFEShell
+#* Methoden : _GetTabCols
+#***********************************************************************/
+void SwFEShell::_GetTabCols( SwTabCols &rToFill, const SwFrm *pBox ) const
+{
+ const SwTabFrm *pTab = pBox->FindTabFrm();
+ if ( pLastCols )
+ {
+ //Paar Kleinigkeiten muessen wir schon noch sicherstellen
+ sal_Bool bDel = sal_True;
+ if ( pColumnCacheLastTable == pTab->GetTable() )
+ {
+ bDel = sal_False;
+ SWRECTFN( pTab )
+
+ const SwPageFrm* pPage = pTab->FindPageFrm();
+ const sal_uLong nLeftMin = (pTab->Frm().*fnRect->fnGetLeft)() -
+ (pPage->Frm().*fnRect->fnGetLeft)();
+ const sal_uLong nRightMax = (pTab->Frm().*fnRect->fnGetRight)() -
+ (pPage->Frm().*fnRect->fnGetLeft)();
+
+ if ( pColumnCacheLastTabFrm != pTab )
+ {
+ //Wenn der TabFrm gewechselt hat, brauchen wir bei gleicher
+ //Breite nur ein wenig shiften.
+ SWRECTFNX( pColumnCacheLastTabFrm )
+ if( (pColumnCacheLastTabFrm->Frm().*fnRectX->fnGetWidth)() ==
+ (pTab->Frm().*fnRect->fnGetWidth)() )
+ {
+ pLastCols->SetLeftMin( nLeftMin );
+
+ pColumnCacheLastTabFrm = pTab;
+ }
+ else
+ bDel = sal_True;
+ }
+
+ if ( !bDel &&
+ pLastCols->GetLeftMin () == (sal_uInt16)nLeftMin &&
+ pLastCols->GetLeft () == (sal_uInt16)(pTab->Prt().*fnRect->fnGetLeft)() &&
+ pLastCols->GetRight () == (sal_uInt16)(pTab->Prt().*fnRect->fnGetRight)()&&
+ pLastCols->GetRightMax() == (sal_uInt16)nRightMax - pLastCols->GetLeftMin() )
+ {
+ if ( pColumnCacheLastCellFrm != pBox )
+ {
+ pTab->GetTable()->GetTabCols( *pLastCols,
+ ((SwCellFrm*)pBox)->GetTabBox(), sal_True);
+ pColumnCacheLastCellFrm = pBox;
+ }
+ rToFill = *pLastCols;
+ }
+ else
+ bDel = sal_True;
+ }
+ if ( bDel )
+ DELETEZ(pLastCols);
+ }
+ if ( !pLastCols )
+ {
+ GetDoc()->GetTabCols( rToFill, 0, (SwCellFrm*)pBox );
+
+ pLastCols = new SwTabCols( rToFill );
+ pColumnCacheLastTable = pTab->GetTable();
+ pColumnCacheLastTabFrm = pTab;
+ pColumnCacheLastCellFrm= pBox;
+ }
+
+#if OSL_DEBUG_LEVEL > 1
+ SwTabColsEntry aEntry;
+ for ( sal_uInt16 i = 0; i < rToFill.Count(); ++i )
+ {
+ aEntry = rToFill.GetEntry( i );
+ (void)aEntry;
+ }
+#endif
+}
+
+/***********************************************************************
+#* Class : SwFEShell
+#* Methoden : _GetTabRows
+#***********************************************************************/
+void SwFEShell::_GetTabRows( SwTabCols &rToFill, const SwFrm *pBox ) const
+{
+ const SwTabFrm *pTab = pBox->FindTabFrm();
+ if ( pLastRows )
+ {
+ //Paar Kleinigkeiten muessen wir schon noch sicherstellen
+ sal_Bool bDel = sal_True;
+ if ( pRowCacheLastTable == pTab->GetTable() )
+ {
+ bDel = sal_False;
+ SWRECTFN( pTab )
+ const SwPageFrm* pPage = pTab->FindPageFrm();
+ const long nLeftMin = ( bVert ?
+ pTab->GetPrtLeft() - pPage->Frm().Left() :
+ pTab->GetPrtTop() - pPage->Frm().Top() );
+ const long nLeft = bVert ? LONG_MAX : 0;
+ const long nRight = (pTab->Prt().*fnRect->fnGetHeight)();
+ const long nRightMax = bVert ? nRight : LONG_MAX;
+
+ if ( pRowCacheLastTabFrm != pTab ||
+ pRowCacheLastCellFrm != pBox )
+ bDel = sal_True;
+
+ if ( !bDel &&
+ pLastRows->GetLeftMin () == nLeftMin &&
+ pLastRows->GetLeft () == nLeft &&
+ pLastRows->GetRight () == nRight &&
+ pLastRows->GetRightMax() == nRightMax )
+ {
+ rToFill = *pLastRows;
+ }
+ else
+ bDel = sal_True;
+ }
+ if ( bDel )
+ DELETEZ(pLastRows);
+ }
+ if ( !pLastRows )
+ {
+ GetDoc()->GetTabRows( rToFill, 0, (SwCellFrm*)pBox );
+
+ pLastRows = new SwTabCols( rToFill );
+ pRowCacheLastTable = pTab->GetTable();
+ pRowCacheLastTabFrm = pTab;
+ pRowCacheLastCellFrm= pBox;
+ }
+}
+
+/***********************************************************************
+#* Class : SwFEShell
+#* Methoden : SetTabCols(), GetTabCols()
+#***********************************************************************/
+void SwFEShell::SetTabCols( const SwTabCols &rNew, sal_Bool bCurRowOnly )
+{
+ SwFrm *pBox = GetCurrFrm();
+ if( !pBox || !pBox->IsInTab() )
+ return;
+
+ SET_CURR_SHELL( this );
+ StartAllAction();
+
+ do {
+ pBox = pBox->GetUpper();
+ } while ( !pBox->IsCellFrm() );
+
+ GetDoc()->SetTabCols( rNew, bCurRowOnly, 0, (SwCellFrm*)pBox );
+ EndAllActionAndCall();
+}
+
+void SwFEShell::GetTabCols( SwTabCols &rToFill ) const
+{
+ const SwFrm *pFrm = GetCurrFrm();
+ if( !pFrm || !pFrm->IsInTab() )
+ return;
+ do
+ { pFrm = pFrm->GetUpper();
+ } while ( !pFrm->IsCellFrm() );
+
+ _GetTabCols( rToFill, pFrm );
+}
+
+void SwFEShell::GetTabRows( SwTabCols &rToFill ) const
+{
+ const SwFrm *pFrm = GetCurrFrm();
+ if( !pFrm || !pFrm->IsInTab() )
+ return;
+ do
+ { pFrm = pFrm->GetUpper();
+ } while ( !pFrm->IsCellFrm() );
+
+ _GetTabRows( rToFill, pFrm );
+}
+
+void SwFEShell::SetTabRows( const SwTabCols &rNew, sal_Bool bCurColOnly )
+{
+ SwFrm *pBox = GetCurrFrm();
+ if( !pBox || !pBox->IsInTab() )
+ return;
+
+ SET_CURR_SHELL( this );
+ StartAllAction();
+
+ do {
+ pBox = pBox->GetUpper();
+ } while ( !pBox->IsCellFrm() );
+
+ GetDoc()->SetTabRows( rNew, bCurColOnly, 0, (SwCellFrm*)pBox );
+ EndAllActionAndCall();
+}
+
+void SwFEShell::GetMouseTabRows( SwTabCols &rToFill, const Point &rPt ) const
+{
+ const SwFrm *pBox = GetBox( rPt );
+ if ( pBox )
+ _GetTabRows( rToFill, pBox );
+}
+
+void SwFEShell::SetMouseTabRows( const SwTabCols &rNew, sal_Bool bCurColOnly, const Point &rPt )
+{
+ const SwFrm *pBox = GetBox( rPt );
+ if( pBox )
+ {
+ SET_CURR_SHELL( this );
+ StartAllAction();
+ GetDoc()->SetTabRows( rNew, bCurColOnly, 0, (SwCellFrm*)pBox );
+ EndAllActionAndCall();
+ }
+}
+
+/***********************************************************************
+ * Class : SwFEShell
+ * Methoden : SetRowSplit(), GetRowSplit()
+ ***********************************************************************/
+
+void SwFEShell::SetRowSplit( const SwFmtRowSplit& rNew )
+{
+ SET_CURR_SHELL( this );
+ StartAllAction();
+ GetDoc()->SetRowSplit( *getShellCrsr( false ), rNew );
+ EndAllActionAndCall();
+}
+
+void SwFEShell::GetRowSplit( SwFmtRowSplit*& rpSz ) const
+{
+ GetDoc()->GetRowSplit( *getShellCrsr( false ), rpSz );
+}
+
+
+/***********************************************************************
+#* Class : SwFEShell
+#* Methoden : SetRowHeight(), GetRowHeight()
+#***********************************************************************/
+
+void SwFEShell::SetRowHeight( const SwFmtFrmSize &rNew )
+{
+ SET_CURR_SHELL( this );
+ StartAllAction();
+ GetDoc()->SetRowHeight( *getShellCrsr( false ), rNew );
+ EndAllActionAndCall();
+}
+
+/******************************************************************************
+ * SwTwips SwFEShell::GetRowHeight() const
+ ******************************************************************************/
+void SwFEShell::GetRowHeight( SwFmtFrmSize *& rpSz ) const
+{
+ GetDoc()->GetRowHeight( *getShellCrsr( false ), rpSz );
+}
+
+sal_Bool SwFEShell::BalanceRowHeight( sal_Bool bTstOnly )
+{
+ SET_CURR_SHELL( this );
+ if( !bTstOnly )
+ StartAllAction();
+ sal_Bool bRet = GetDoc()->BalanceRowHeight( *getShellCrsr( false ), bTstOnly );
+ if( !bTstOnly )
+ EndAllActionAndCall();
+ return bRet;
+}
+
+/******************************************************************************
+ * void SwFEShell::SetRowBackground()
+ ******************************************************************************/
+void SwFEShell::SetRowBackground( const SvxBrushItem &rNew )
+{
+ SET_CURR_SHELL( this );
+ StartAllAction();
+ GetDoc()->SetRowBackground( *getShellCrsr( false ), rNew );
+ EndAllActionAndCall();
+}
+
+/******************************************************************************
+ * SwTwips SwFEShell::GetRowBackground() const
+ ******************************************************************************/
+sal_Bool SwFEShell::GetRowBackground( SvxBrushItem &rToFill ) const
+{
+ return GetDoc()->GetRowBackground( *getShellCrsr( false ), rToFill );
+}
+
+/***********************************************************************
+#* Class : SwFEShell
+#* Methoden : SetTabBorders(), GetTabBorders()
+#***********************************************************************/
+
+void SwFEShell::SetTabBorders( const SfxItemSet& rSet )
+{
+ SET_CURR_SHELL( this );
+ StartAllAction();
+ GetDoc()->SetTabBorders( *getShellCrsr( false ), rSet );
+ EndAllActionAndCall();
+}
+
+void SwFEShell::SetTabLineStyle( const Color* pColor, sal_Bool bSetLine,
+ const editeng::SvxBorderLine* pBorderLine )
+{
+ SET_CURR_SHELL( this );
+ StartAllAction();
+ GetDoc()->SetTabLineStyle( *getShellCrsr( false ),
+ pColor, bSetLine, pBorderLine );
+ EndAllActionAndCall();
+}
+
+void SwFEShell::GetTabBorders( SfxItemSet& rSet ) const
+{
+ GetDoc()->GetTabBorders( *getShellCrsr( false ), rSet );
+}
+
+
+/***********************************************************************
+#* Class : SwFEShell
+#* Methoden : SetBoxBackground(), GetBoxBackground()
+#***********************************************************************/
+void SwFEShell::SetBoxBackground( const SvxBrushItem &rNew )
+{
+ SET_CURR_SHELL( this );
+ StartAllAction();
+ GetDoc()->SetBoxAttr( *getShellCrsr( false ), rNew );
+ EndAllActionAndCall();
+}
+
+sal_Bool SwFEShell::GetBoxBackground( SvxBrushItem &rToFill ) const
+{
+ return GetDoc()->GetBoxAttr( *getShellCrsr( false ), rToFill );
+}
+
+/***********************************************************************
+#* Class : SwFEShell
+#* Methoden : SetBoxDirection(), GetBoxDirection()
+#***********************************************************************/
+void SwFEShell::SetBoxDirection( const SvxFrameDirectionItem& rNew )
+{
+ SET_CURR_SHELL( this );
+ StartAllAction();
+ GetDoc()->SetBoxAttr( *getShellCrsr( false ), rNew );
+ EndAllActionAndCall();
+}
+
+sal_Bool SwFEShell::GetBoxDirection( SvxFrameDirectionItem& rToFill ) const
+{
+ return GetDoc()->GetBoxAttr( *getShellCrsr( false ), rToFill );
+}
+
+/***********************************************************************
+#* Class : SwFEShell
+#* Methoden : SetBoxAlign, SetBoxAlign
+#***********************************************************************/
+void SwFEShell::SetBoxAlign( sal_uInt16 nAlign )
+{
+ SET_CURR_SHELL( this );
+ StartAllAction();
+ GetDoc()->SetBoxAlign( *getShellCrsr( false ), nAlign );
+ EndAllActionAndCall();
+}
+
+sal_uInt16 SwFEShell::GetBoxAlign() const
+{
+ return GetDoc()->GetBoxAlign( *getShellCrsr( false ) );
+}
+
+/***********************************************************************
+#* Class : SwFEShell
+#* Methoden : SetTabBackground(), GetTabBackground()
+#***********************************************************************/
+void SwFEShell::SetTabBackground( const SvxBrushItem &rNew )
+{
+ SwFrm *pFrm = GetCurrFrm();
+ if( !pFrm || !pFrm->IsInTab() )
+ return;
+
+ SET_CURR_SHELL( this );
+ StartAllAction();
+ GetDoc()->SetAttr( rNew, *pFrm->ImplFindTabFrm()->GetFmt() );
+ EndAllAction(); //Kein Call, denn es veraendert sich nichts!
+ GetDoc()->SetModified();
+}
+
+void SwFEShell::GetTabBackground( SvxBrushItem &rToFill ) const
+{
+ SwFrm *pFrm = GetCurrFrm();
+ if( pFrm && pFrm->IsInTab() )
+ rToFill = pFrm->ImplFindTabFrm()->GetFmt()->GetBackground();
+}
+
+
+/***********************************************************************
+#* Class : SwFEShell
+#* Methoden : HasWholeTabSelection()
+#***********************************************************************/
+sal_Bool SwFEShell::HasWholeTabSelection() const
+{
+ //Ist die ganze Tabelle Selektiert?
+ if ( IsTableMode() )
+ {
+ SwSelBoxes aBoxes;
+ ::GetTblSelCrs( *this, aBoxes );
+ if( aBoxes.Count() )
+ {
+ const SwTableNode *pTblNd = IsCrsrInTbl();
+ return ( pTblNd && aBoxes[0]->GetSttIdx()-1 == pTblNd->
+ EndOfSectionNode()->StartOfSectionIndex() &&
+ aBoxes[aBoxes.Count()-1]->GetSttNd()->EndOfSectionIndex()+1
+ == pTblNd->EndOfSectionIndex() );
+ }
+ }
+ return sal_False;
+}
+
+sal_Bool SwFEShell::HasBoxSelection() const
+{
+ if(!IsCrsrInTbl())
+ return sal_False;
+ //Ist die ganze Tabelle Selektiert?
+ if( IsTableMode() )
+ return sal_True;
+ SwPaM* pPam = GetCrsr();
+ // empty boxes are also selected as the absence of selection
+ sal_Bool bChg = sal_False;
+ if( pPam->GetPoint() == pPam->End())
+ {
+ bChg = sal_True;
+ pPam->Exchange();
+ }
+ SwNode* pNd;
+ if( pPam->GetPoint()->nNode.GetIndex() -1 ==
+ ( pNd = pPam->GetNode())->StartOfSectionIndex() &&
+ !pPam->GetPoint()->nContent.GetIndex() &&
+ pPam->GetMark()->nNode.GetIndex() + 1 ==
+ pNd->EndOfSectionIndex())
+ {
+ SwNodeIndex aIdx( *pNd->EndOfSectionNode(), -1 );
+ SwCntntNode* pCNd = aIdx.GetNode().GetCntntNode();
+ if( !pCNd )
+ {
+ pCNd = GetDoc()->GetNodes().GoPrevious( &aIdx );
+ OSL_ENSURE( pCNd, "kein ContentNode in der Box ??" );
+ }
+ if( pPam->GetMark()->nContent == pCNd->Len() )
+ {
+ if( bChg )
+ pPam->Exchange();
+ return sal_True;
+ }
+ }
+ if( bChg )
+ pPam->Exchange();
+ return sal_False;
+}
+
+/***********************************************************************
+#* Class : SwFEShell
+#* Methoden : ProtectCells(), UnProtectCells()
+#***********************************************************************/
+void SwFEShell::ProtectCells()
+{
+ SvxProtectItem aProt( RES_PROTECT );
+ aProt.SetCntntProtect( sal_True );
+
+ SET_CURR_SHELL( this );
+ StartAllAction();
+
+ GetDoc()->SetBoxAttr( *getShellCrsr( false ), aProt );
+
+ if( !IsCrsrReadonly() )
+ {
+ if( IsTableMode() )
+ ClearMark();
+ ParkCursorInTab();
+ }
+ EndAllActionAndCall();
+}
+
+// die Tabellenselektion aufheben
+void SwFEShell::UnProtectCells()
+{
+ SET_CURR_SHELL( this );
+ StartAllAction();
+
+ SwSelBoxes aBoxes;
+ if( IsTableMode() )
+ ::GetTblSelCrs( *this, aBoxes );
+ else
+ {
+ SwFrm *pFrm = GetCurrFrm();
+ do {
+ pFrm = pFrm->GetUpper();
+ } while ( pFrm && !pFrm->IsCellFrm() );
+ if( pFrm )
+ {
+ SwTableBox *pBox = (SwTableBox*)((SwCellFrm*)pFrm)->GetTabBox();
+ aBoxes.Insert( pBox );
+ }
+ }
+
+ if( aBoxes.Count() )
+ GetDoc()->UnProtectCells( aBoxes );
+
+ EndAllActionAndCall();
+}
+
+void SwFEShell::UnProtectTbls()
+{
+ SET_CURR_SHELL( this );
+ StartAllAction();
+ GetDoc()->UnProtectTbls( *GetCrsr() );
+ EndAllActionAndCall();
+}
+
+sal_Bool SwFEShell::HasTblAnyProtection( const String* pTblName,
+ sal_Bool* pFullTblProtection )
+{
+ return GetDoc()->HasTblAnyProtection( GetCrsr()->GetPoint(), pTblName,
+ pFullTblProtection );
+}
+
+sal_Bool SwFEShell::CanUnProtectCells() const
+{
+ sal_Bool bUnProtectAvailable = sal_False;
+ const SwTableNode *pTblNd = IsCrsrInTbl();
+ if( pTblNd && !pTblNd->IsProtect() )
+ {
+ SwSelBoxes aBoxes;
+ if( IsTableMode() )
+ ::GetTblSelCrs( *this, aBoxes );
+ else
+ {
+ SwFrm *pFrm = GetCurrFrm();
+ do {
+ pFrm = pFrm->GetUpper();
+ } while ( pFrm && !pFrm->IsCellFrm() );
+ if( pFrm )
+ {
+ SwTableBox *pBox = (SwTableBox*)((SwCellFrm*)pFrm)->GetTabBox();
+ aBoxes.Insert( pBox );
+ }
+ }
+ if( aBoxes.Count() )
+ bUnProtectAvailable = ::HasProtectedCells( aBoxes );
+ }
+ return bUnProtectAvailable;
+}
+
+/***********************************************************************
+#* Class : SwFEShell
+#* Methoden : GetRowsToRepeat(), SetRowsToRepeat()
+#***********************************************************************/
+sal_uInt16 SwFEShell::GetRowsToRepeat() const
+{
+ const SwFrm *pFrm = GetCurrFrm();
+ const SwTabFrm *pTab = pFrm ? pFrm->FindTabFrm() : 0;
+ if( pTab )
+ return pTab->GetTable()->GetRowsToRepeat();
+ return 0;
+}
+
+void SwFEShell::SetRowsToRepeat( sal_uInt16 nSet )
+{
+ SwFrm *pFrm = GetCurrFrm();
+ SwTabFrm *pTab = pFrm ? pFrm->FindTabFrm() : 0;
+ if( pTab && pTab->GetTable()->GetRowsToRepeat() != nSet )
+ {
+ SwWait aWait( *GetDoc()->GetDocShell(), sal_True );
+ SET_CURR_SHELL( this );
+ StartAllAction();
+ GetDoc()->SetRowsToRepeat( *pTab->GetTable(), nSet );
+ EndAllActionAndCall();
+ }
+}
+/*-------------------------------------------------------------------------
+ returns the number of rows consecutively selected from top
+ -----------------------------------------------------------------------*/
+sal_uInt16 lcl_GetRowNumber( const SwPosition& rPos )
+{
+ sal_uInt16 nRet = USHRT_MAX;
+ Point aTmpPt;
+ const SwCntntNode *pNd;
+ const SwCntntFrm *pFrm;
+
+ if( 0 != ( pNd = rPos.nNode.GetNode().GetCntntNode() ))
+ pFrm = pNd->getLayoutFrm( pNd->GetDoc()->GetCurrentLayout(), &aTmpPt, &rPos, sal_False );
+ else
+ pFrm = 0;
+
+ if ( pFrm && pFrm->IsInTab() )
+ {
+ const SwFrm* pRow = pFrm->GetUpper();
+ while ( !pRow->GetUpper()->IsTabFrm() )
+ pRow = pRow->GetUpper();
+
+ const SwTabFrm* pTabFrm = (const SwTabFrm*)pRow->GetUpper();
+ const SwTableLine* pTabLine = static_cast<const SwRowFrm*>(pRow)->GetTabLine();
+
+ sal_uInt16 nI = 0;
+ while ( nI < pTabFrm->GetTable()->GetTabLines().Count() )
+ {
+ if ( pTabFrm->GetTable()->GetTabLines()[ nI ] == pTabLine )
+ {
+ nRet = nI;
+ break;
+ }
+ ++nI;
+ }
+ }
+
+ return nRet;
+}
+sal_uInt16 SwFEShell::GetRowSelectionFromTop() const
+{
+ sal_uInt16 nRet = 0;
+ const SwPaM* pPaM = IsTableMode() ? GetTableCrsr() : _GetCrsr();
+ const sal_uInt16 nPtLine = lcl_GetRowNumber( *pPaM->GetPoint() );
+
+ if ( !IsTableMode() )
+ {
+ nRet = 0 == nPtLine ? 1 : 0;
+ }
+ else
+ {
+ const sal_uInt16 nMkLine = lcl_GetRowNumber( *pPaM->GetMark() );
+
+ if ( ( nPtLine == 0 && nMkLine != USHRT_MAX ) ||
+ ( nMkLine == 0 && nPtLine != USHRT_MAX ) )
+ {
+ nRet = Max( nPtLine, nMkLine ) + 1;
+ }
+ }
+
+ return nRet;
+}
+
+/*
+ * 1. case: bRepeat = true
+ * returns true if the current frame is located inside a table headline in
+ * a follow frame
+ *
+ * 2. case: bRepeat = false
+ * returns true if the current frame is localed inside a table headline OR
+ * inside the first line of a table!!!
+ */
+sal_Bool SwFEShell::CheckHeadline( bool bRepeat ) const
+{
+ sal_Bool bRet = sal_False;
+ if ( !IsTableMode() )
+ {
+ SwFrm *pFrm = GetCurrFrm(); // DONE MULTIIHEADER
+ if ( pFrm && pFrm->IsInTab() )
+ {
+ SwTabFrm* pTab = pFrm->FindTabFrm();
+ if ( bRepeat )
+ {
+ bRet = pTab->IsFollow() && pTab->IsInHeadline( *pFrm );
+ }
+ else
+ {
+ bRet = ((SwLayoutFrm*)pTab->Lower())->IsAnLower( pFrm ) ||
+ pTab->IsInHeadline( *pFrm );
+ }
+ }
+ }
+ return bRet;
+}
+
+/***********************************************************************
+#* Class : SwFEShell
+#* Methoden : AdjustCellWidth()
+#***********************************************************************/
+
+void SwFEShell::AdjustCellWidth( sal_Bool bBalance )
+{
+ SET_CURR_SHELL( this );
+ StartAllAction();
+
+ //WarteCrsr immer einschalten, weil sich im vorraus nicht so recht
+ //ermitteln laesst wieviel Inhalt betroffen ist.
+ TblWait aWait( USHRT_MAX, 0, *GetDoc()->GetDocShell() );
+
+ GetDoc()->AdjustCellWidth( *getShellCrsr( false ), bBalance );
+ EndAllActionAndCall();
+}
+
+sal_Bool SwFEShell::IsAdjustCellWidthAllowed( sal_Bool bBalance ) const
+{
+ //Es muss mindestens eine Zelle mit Inhalt in der Selektion enthalten
+ //sein.
+
+ SwFrm *pFrm = GetCurrFrm();
+ if( !pFrm || !pFrm->IsInTab() )
+ return sal_False;
+
+ SwSelBoxes aBoxes;
+ ::GetTblSelCrs( *this, aBoxes );
+
+ if ( bBalance )
+ return aBoxes.Count() > 1;
+
+ if ( !aBoxes.Count() )
+ {
+ do
+ { pFrm = pFrm->GetUpper();
+ } while ( !pFrm->IsCellFrm() );
+ SwTableBox *pBox = (SwTableBox*)((SwCellFrm*)pFrm)->GetTabBox();
+ aBoxes.Insert( pBox );
+ }
+
+ for ( sal_uInt16 i = 0; i < aBoxes.Count(); ++i )
+ {
+ SwTableBox *pBox = aBoxes[i];
+ if ( pBox->GetSttNd() )
+ {
+ SwNodeIndex aIdx( *pBox->GetSttNd(), 1 );
+ SwTxtNode* pCNd = aIdx.GetNode().GetTxtNode();
+ if( !pCNd )
+ pCNd = (SwTxtNode*)GetDoc()->GetNodes().GoNext( &aIdx );
+
+ while ( pCNd )
+ {
+ if ( pCNd->GetTxt().Len() )
+ return sal_True;
+ ++aIdx;
+ pCNd = aIdx.GetNode().GetTxtNode();
+ }
+ }
+ }
+ return sal_False;
+}
+
+ // AutoFormat fuer die Tabelle/TabellenSelection
+sal_Bool SwFEShell::SetTableAutoFmt( const SwTableAutoFmt& rNew )
+{
+ SwTableNode *pTblNd = (SwTableNode*)IsCrsrInTbl();
+ if( !pTblNd || pTblNd->GetTable().IsTblComplex() )
+ return sal_False;
+
+ SwSelBoxes aBoxes;
+
+ if ( !IsTableMode() ) // falls Crsr noch nicht akt. sind
+ GetCrsr();
+
+ // gesamte Tabelle oder nur auf die akt. Selektion
+ if( IsTableMode() )
+ ::GetTblSelCrs( *this, aBoxes );
+ else
+ {
+ const SwTableSortBoxes& rTBoxes = pTblNd->GetTable().GetTabSortBoxes();
+ for( sal_uInt16 n = 0; n < rTBoxes.Count(); ++n )
+ {
+ SwTableBox* pBox = rTBoxes[ n ];
+ aBoxes.Insert( pBox );
+ }
+ }
+
+ sal_Bool bRet;
+ if( aBoxes.Count() )
+ {
+ SET_CURR_SHELL( this );
+ StartAllAction();
+ bRet = GetDoc()->SetTableAutoFmt( aBoxes, rNew );
+ DELETEZ( pLastCols );
+ DELETEZ( pLastRows );
+ EndAllActionAndCall();
+ }
+ else
+ bRet = sal_False;
+ return bRet;
+}
+
+sal_Bool SwFEShell::GetTableAutoFmt( SwTableAutoFmt& rGet )
+{
+ const SwTableNode *pTblNd = IsCrsrInTbl();
+ if( !pTblNd || pTblNd->GetTable().IsTblComplex() )
+ return sal_False;
+
+ SwSelBoxes aBoxes;
+
+ if ( !IsTableMode() ) // falls Crsr noch nicht akt. sind
+ GetCrsr();
+
+ // gesamte Tabelle oder nur auf die akt. Selektion
+ if( IsTableMode() )
+ ::GetTblSelCrs( *this, aBoxes );
+ else
+ {
+ const SwTableSortBoxes& rTBoxes = pTblNd->GetTable().GetTabSortBoxes();
+ for( sal_uInt16 n = 0; n < rTBoxes.Count(); ++n )
+ {
+ SwTableBox* pBox = rTBoxes[ n ];
+ aBoxes.Insert( pBox );
+ }
+ }
+
+ return GetDoc()->GetTableAutoFmt( aBoxes, rGet );
+}
+
+/***********************************************************************
+#* Class : SwFEShell
+#* Methoden : DeleteTblSel()
+#***********************************************************************/
+sal_Bool SwFEShell::DeleteTblSel()
+{
+ // pruefe ob vom aktuellen Crsr der SPoint/Mark in einer Tabelle stehen
+ SwFrm *pFrm = GetCurrFrm();
+ if( !pFrm || !pFrm->IsInTab() )
+ return sal_False;
+
+ if( pFrm->ImplFindTabFrm()->GetTable()->ISA( SwDDETable ))
+ {
+ ErrorHandler::HandleError( ERR_TBLDDECHG_ERROR,
+ ERRCODE_MSG_INFO | ERRCODE_BUTTON_DEF_OK );
+ return sal_False;
+ }
+
+ SET_CURR_SHELL( this );
+ StartAllAction();
+
+ // lasse ueber das Layout die Boxen suchen
+ sal_Bool bRet;
+ SwSelBoxes aBoxes;
+ GetTblSelCrs( *this, aBoxes );
+ if( aBoxes.Count() )
+ {
+ TblWait( aBoxes.Count(), pFrm, *GetDoc()->GetDocShell() );
+
+ // die Crsr muessen noch aus dem Loesch Bereich entfernt
+ // werden. Setze sie immer hinter/auf die Tabelle; ueber die
+ // Dokument-Position werden sie dann immer an die alte Position gesetzt.
+ while( !pFrm->IsCellFrm() )
+ pFrm = pFrm->GetUpper();
+ ParkCrsr( SwNodeIndex( *((SwCellFrm*)pFrm)->GetTabBox()->GetSttNd() ));
+
+ bRet = GetDoc()->DeleteRowCol( aBoxes );
+
+ DELETEZ( pLastCols );
+ DELETEZ( pLastRows );
+ }
+ else
+ bRet = sal_False;
+ EndAllActionAndCall();
+ return bRet;
+}
+
+/*************************************************************************
+|*
+|* SwFEShell::GetCurTabColNum()
+|*
+|*************************************************************************/
+sal_uInt16 SwFEShell::GetCurTabColNum() const
+{
+ //!!!GetCurMouseTabColNum() mitpflegen!!!!
+ sal_uInt16 nRet = 0;
+
+ SwFrm *pFrm = GetCurrFrm();
+ OSL_ENSURE( pFrm, "Crsr geparkt?" );
+
+ // pruefe ob vom aktuellen Crsr der SPoint/Mark in einer Tabelle stehen
+ if( pFrm && pFrm->IsInTab() )
+ {
+ do { // JP 26.09.95: warum mit dem CntntFrame und nicht mit
+ // dem CellFrame vergleichen????
+ pFrm = pFrm->GetUpper();
+ } while ( !pFrm->IsCellFrm() );
+ SWRECTFN( pFrm )
+
+ const SwPageFrm* pPage = pFrm->FindPageFrm();
+
+ //TabCols besorgen, den nur ueber diese erreichen wir die Position.
+ SwTabCols aTabCols;
+ GetTabCols( aTabCols );
+
+ if( pFrm->FindTabFrm()->IsRightToLeft() )
+ {
+ long nX = (pFrm->Frm().*fnRect->fnGetRight)() - (pPage->Frm().*fnRect->fnGetLeft)();
+
+ const long nRight = aTabCols.GetLeftMin() + aTabCols.GetRight();;
+
+ if ( !::IsSame( nX, nRight ) )
+ {
+ nX = nRight - nX + aTabCols.GetLeft();
+ for ( sal_uInt16 i = 0; i < aTabCols.Count(); ++i )
+ if ( ::IsSame( nX, aTabCols[i] ) )
+ {
+ nRet = i + 1;
+ break;
+ }
+ }
+ }
+ else
+ {
+ const long nX = (pFrm->Frm().*fnRect->fnGetLeft)() -
+ (pPage->Frm().*fnRect->fnGetLeft)();
+
+ const long nLeft = aTabCols.GetLeftMin();
+
+ if ( !::IsSame( nX, nLeft + aTabCols.GetLeft() ) )
+ {
+ for ( sal_uInt16 i = 0; i < aTabCols.Count(); ++i )
+ if ( ::IsSame( nX, nLeft + aTabCols[i] ) )
+ {
+ nRet = i + 1;
+ break;
+ }
+ }
+ }
+ }
+ return nRet;
+}
+
+/*************************************************************************
+|*
+|* SwFEShell::GetBox()
+|*
+|*************************************************************************/
+
+const SwFrm *lcl_FindFrmInTab( const SwLayoutFrm *pLay, const Point &rPt, SwTwips nFuzzy )
+{
+ const SwFrm *pFrm = pLay->Lower();
+
+ while( pFrm && pLay->IsAnLower( pFrm ) )
+ {
+ if ( pFrm->Frm().IsNear( rPt, nFuzzy ) )
+ {
+ if ( pFrm->IsLayoutFrm() )
+ {
+ const SwFrm *pTmp = ::lcl_FindFrmInTab( (SwLayoutFrm*)pFrm, rPt, nFuzzy );
+ if ( pTmp )
+ return pTmp;
+ }
+
+ return pFrm;
+ }
+
+ pFrm = pFrm->FindNext();
+ }
+
+ return 0;
+}
+
+const SwCellFrm *lcl_FindFrm( const SwLayoutFrm *pLay, const Point &rPt,
+ SwTwips nFuzzy, bool* pbRow, bool* pbCol )
+{
+ // bMouseMoveRowCols :
+ // Method is called for
+ // - Moving columns/rows with the mouse or
+ // - Enhanced table selection
+ const bool bMouseMoveRowCols = 0 == pbCol;
+
+ bool bCloseToRow = false;
+ bool bCloseToCol = false;
+
+ const SwFrm *pFrm = pLay->ContainsCntnt();
+ const SwFrm* pRet = 0;
+
+ if ( pFrm )
+ {
+ do
+ {
+ if ( pFrm->IsInTab() )
+ pFrm = ((SwFrm*)pFrm)->ImplFindTabFrm();
+
+ if ( pFrm->IsTabFrm() )
+ {
+ Point aPt( rPt );
+ bool bSearchForFrmInTab = true;
+ SwTwips nTmpFuzzy = nFuzzy;
+
+ if ( !bMouseMoveRowCols )
+ {
+ // We ignore nested tables for the enhanced table selection:
+ while ( pFrm->GetUpper()->IsInTab() )
+ pFrm = pFrm->GetUpper()->FindTabFrm();
+
+ // We first check if the given point is 'close' to the left or top
+ // border of the table frame:
+ OSL_ENSURE( pFrm, "Nested table frame without outer table" );
+ SWRECTFN( pFrm )
+ const bool bRTL = pFrm->IsRightToLeft();
+
+ SwRect aTabRect = pFrm->Prt();
+ aTabRect.Pos() += pFrm->Frm().Pos();
+
+ const SwTwips nLeft = bRTL ?
+ (aTabRect.*fnRect->fnGetRight)() :
+ (aTabRect.*fnRect->fnGetLeft)();
+ const SwTwips nTop = (aTabRect.*fnRect->fnGetTop)();
+
+ SwTwips& rPointX = bVert ? aPt.Y() : aPt.X();
+ SwTwips& rPointY = bVert ? aPt.X() : aPt.Y();
+
+ const SwTwips nXDiff = (*fnRect->fnXDiff)( nLeft, rPointX ) * ( bRTL ? (-1) : 1 );
+ const SwTwips nYDiff = (*fnRect->fnYDiff)( nTop, rPointY );
+
+ bCloseToRow = nXDiff >= 0 && nXDiff < nFuzzy;
+ bCloseToCol = nYDiff >= 0 && nYDiff < nFuzzy;
+
+ if ( bCloseToCol && 2 * nYDiff > nFuzzy )
+ {
+ const SwFrm* pPrev = pFrm->GetPrev();
+ if ( pPrev )
+ {
+ SwRect aPrevRect = pPrev->Prt();
+ aPrevRect.Pos() += pPrev->Frm().Pos();
+
+ if( aPrevRect.IsInside( rPt ) )
+ {
+ bCloseToCol = false;
+ }
+ }
+
+ }
+
+ // If we found the point to be 'close' to the left or top border
+ // of the table frame, we adjust the point to be on that border:
+ if ( bCloseToRow && bCloseToCol )
+ aPt = bRTL ? aTabRect.TopRight() : (aTabRect.*fnRect->fnGetPos)();
+ else if ( bCloseToRow )
+ rPointX = nLeft;
+ else if ( bCloseToCol )
+ rPointY = nTop;
+
+ if ( !bCloseToRow && !bCloseToCol )
+ bSearchForFrmInTab = false;
+
+ // Since the point has been adjusted, we call lcl_FindFrmInTab()
+ // with a fuzzy value of 1:
+ nTmpFuzzy = 1;
+ }
+
+ const SwFrm* pTmp = bSearchForFrmInTab ?
+ ::lcl_FindFrmInTab( (SwLayoutFrm*)pFrm, aPt, nTmpFuzzy ) :
+ 0;
+
+ if ( pTmp )
+ {
+ pFrm = pTmp;
+ break;
+ }
+ }
+ pFrm = pFrm->FindNextCnt();
+
+ } while ( pFrm && pLay->IsAnLower( pFrm ) );
+ }
+
+ if ( pFrm && pFrm->IsInTab() && pLay->IsAnLower( pFrm ) )
+ {
+ do
+ {
+ // We allow mouse drag of table borders within nested tables,
+ // but disallow hotspot selection of nested tables.
+ if ( bMouseMoveRowCols )
+ {
+ // find the next cell frame
+ while ( pFrm && !pFrm->IsCellFrm() )
+ pFrm = pFrm->GetUpper();
+ }
+ else
+ {
+ // find the most upper cell frame:
+ while ( pFrm &&
+ ( !pFrm->IsCellFrm() ||
+ !pFrm->GetUpper()->GetUpper()->IsTabFrm() ||
+ pFrm->GetUpper()->GetUpper()->GetUpper()->IsInTab() ) )
+ pFrm = pFrm->GetUpper();
+ }
+
+ if ( pFrm ) // Note: this condition should be the same like the while condition!!!
+ {
+ // --> FME 2004-07-30 #i32329# Enhanced table selection
+ // used for hotspot selection of tab/cols/rows
+ if ( !bMouseMoveRowCols )
+ {
+
+ OSL_ENSURE( pbCol && pbRow, "pbCol or pbRow missing" );
+
+ if ( bCloseToRow || bCloseToCol )
+ {
+ *pbRow = bCloseToRow;
+ *pbCol = bCloseToCol;
+ pRet = pFrm;
+ break;
+ }
+ }
+ // <--
+ else
+ {
+ // used for mouse move of columns/rows
+ const SwTabFrm* pTabFrm = pFrm->FindTabFrm();
+ SwRect aTabRect = pTabFrm->Prt();
+ aTabRect.Pos() += pTabFrm->Frm().Pos();
+
+ SWRECTFN( pTabFrm )
+
+ const SwTwips nTabTop = (aTabRect.*fnRect->fnGetTop)();
+ const SwTwips nMouseTop = bVert ? rPt.X() : rPt.Y();
+
+ // Do not allow to drag upper table border:
+ if ( !::IsSame( nTabTop, nMouseTop ) )
+ {
+ if ( ::IsSame( pFrm->Frm().Left(), rPt.X() ) ||
+ ::IsSame( pFrm->Frm().Right(),rPt.X() ) )
+ {
+ if ( pbRow ) *pbRow = false;
+ pRet = pFrm;
+ break;
+ }
+ if ( ::IsSame( pFrm->Frm().Top(), rPt.Y() ) ||
+ ::IsSame( pFrm->Frm().Bottom(),rPt.Y() ) )
+ {
+ if ( pbRow ) *pbRow = true;
+ pRet = pFrm;
+ break;
+ }
+ }
+ }
+
+ pFrm = pFrm->GetUpper();
+ }
+ } while ( pFrm );
+ }
+
+ // robust:
+ OSL_ENSURE( !pRet || pRet->IsCellFrm(), "lcl_FindFrm() is supposed to find a cell frame!" );
+ return pRet && pRet->IsCellFrm() ? static_cast<const SwCellFrm*>(pRet) : 0;
+}
+
+//
+// pbCol = 0 => Used for moving table rows/cols with mouse
+// pbCol != 0 => Used for selecting table/rows/cols
+//
+#define ENHANCED_TABLE_SELECTION_FUZZY 10
+
+const SwFrm* SwFEShell::GetBox( const Point &rPt, bool* pbRow, bool* pbCol ) const
+{
+ const SwPageFrm *pPage = (SwPageFrm*)GetLayout()->Lower();
+ Window* pOutWin = GetWin();
+ SwTwips nFuzzy = COLFUZZY;
+ if( pOutWin )
+ {
+ // --> FME 2004-07-30 #i32329# Enhanced table selection
+ SwTwips nSize = pbCol ? ENHANCED_TABLE_SELECTION_FUZZY : RULER_MOUSE_MARGINWIDTH;
+ // <--
+ Size aTmp( nSize, nSize );
+ aTmp = pOutWin->PixelToLogic( aTmp );
+ nFuzzy = aTmp.Width();
+ }
+
+ while ( pPage && !pPage->Frm().IsNear( rPt, nFuzzy ) )
+ pPage = (SwPageFrm*)pPage->GetNext();
+
+ const SwCellFrm *pFrm = 0;
+ if ( pPage )
+ {
+ //Per GetCrsrOfst oder GetCntntPos koennen wir hier die Box leider
+ //nicht suchen. Das wuerde zu einem Performance-Zusammenbruch bei
+ //Dokumenten mit vielen Absaetzen/Tabellen auf einer Seite fuehren
+ //(BrowseMode!)
+
+ //Erst die Flys checken.
+ if ( pPage->GetSortedObjs() )
+ {
+ for ( sal_uInt16 i = 0; !pFrm && i < pPage->GetSortedObjs()->Count(); ++i )
+ {
+ SwAnchoredObject* pObj = (*pPage->GetSortedObjs())[i];
+ if ( pObj->ISA(SwFlyFrm) )
+ {
+ pFrm = lcl_FindFrm( static_cast<SwFlyFrm*>(pObj),
+ rPt, nFuzzy, pbRow, pbCol );
+ }
+ }
+ }
+ const SwLayoutFrm *pLay = (SwLayoutFrm*)pPage->Lower();
+ while ( pLay && !pFrm )
+ {
+ pFrm = lcl_FindFrm( pLay, rPt, nFuzzy, pbRow, pbCol );
+ pLay = (SwLayoutFrm*)pLay->GetNext();
+ }
+ }
+ return pFrm;
+}
+
+/* Helper function*/
+/* calculated the distance between Point rC and Line Segment (rA, rB) */
+double lcl_DistancePoint2Segment( const Point& rA, const Point& rB, const Point& rC )
+{
+ double nRet = 0;
+
+ const basegfx::B2DVector aBC( rC.X() - rB.X(), rC.Y() - rB.Y() );
+ const basegfx::B2DVector aAB( rB.X() - rA.X(), rB.Y() - rA.Y() );
+ const double nDot1 = aBC.scalar( aAB );
+
+ if ( nDot1 > 0 ) // check outside case 1
+ nRet = aBC.getLength();
+ else
+ {
+ const basegfx::B2DVector aAC( rC.X() - rA.X(), rC.Y() - rA.Y() );
+ const basegfx::B2DVector aBA( rA.X() - rB.X(), rA.Y() - rB.Y() );
+ const double nDot2 = aAC.scalar( aBA );
+
+ if ( nDot2 > 0 ) // check outside case 2
+ nRet = aAC.getLength();
+ else
+ {
+ const double nDiv = aAB.getLength();
+ nRet = nDiv ? aAB.cross( aAC ) / nDiv : 0;
+ }
+ }
+
+ return Abs(nRet);
+}
+
+/* Helper function*/
+Point lcl_ProjectOntoClosestTableFrm( const SwTabFrm& rTab, const Point& rPoint, bool bRowDrag )
+{
+ Point aRet( rPoint );
+ const SwTabFrm* pCurrentTab = &rTab;
+ const bool bVert = pCurrentTab->IsVertical();
+ const bool bRTL = pCurrentTab->IsRightToLeft();
+
+ // Western Layout:
+ // bRowDrag = true => compare to left border of table
+ // bRowDrag = false => compare to top border of table
+
+ // Asian Layout:
+ // bRowDrag = true => compare to right border of table
+ // bRowDrag = false => compare to top border of table
+
+ // RTL Layout:
+ // bRowDrag = true => compare to right border of table
+ // bRowDrag = false => compare to top border of table
+ bool bLeft = false;
+ bool bRight = false;
+
+ if ( bRowDrag )
+ {
+ if ( bVert || bRTL )
+ bRight = true;
+ else
+ bLeft = true;
+ }
+
+ // used to find the minimal distance
+ double nMin = -1;
+ Point aMin1;
+ Point aMin2;
+
+ Point aS1;
+ Point aS2;
+
+ while ( pCurrentTab )
+ {
+ SwRect aTabRect( pCurrentTab->Prt() );
+ aTabRect += pCurrentTab->Frm().Pos();
+
+ if ( bLeft )
+ {
+ // distance to left table border
+ aS1 = aTabRect.TopLeft();
+ aS2 = aTabRect.BottomLeft();
+ }
+ else if ( bRight )
+ {
+ // distance to right table border
+ aS1 = aTabRect.TopRight();
+ aS2 = aTabRect.BottomRight();
+ }
+ else //if ( bTop )
+ {
+ // distance to top table border
+ aS1 = aTabRect.TopLeft();
+ aS2 = aTabRect.TopRight();
+ }
+
+ const double nDist = lcl_DistancePoint2Segment( aS1, aS2, rPoint );
+
+ if ( nDist < nMin || -1 == nMin )
+ {
+ aMin1 = aS1;
+ aMin2 = aS2;
+ nMin = nDist;
+ }
+
+ pCurrentTab = pCurrentTab->GetFollow();
+ }
+
+ // project onto closest line:
+ if ( bLeft || bRight )
+ {
+ aRet.X() = aMin1.X();
+ if ( aRet.Y() > aMin2.Y() )
+ aRet.Y() = aMin2.Y();
+ else if ( aRet.Y() < aMin1.Y() )
+ aRet.Y() = aMin1.Y();
+ }
+ else
+ {
+ aRet.Y() = aMin1.Y();
+ if ( aRet.X() > aMin2.X() )
+ aRet.X() = aMin2.X();
+ else if ( aRet.X() < aMin1.X() )
+ aRet.X() = aMin1.X();
+ }
+
+ return aRet;
+}
+
+// --> FME 2004-07-30 #i32329# Enhanced table selection
+bool SwFEShell::SelTblRowCol( const Point& rPt, const Point* pEnd, bool bRowDrag )
+{
+ bool bRet = false;
+ Point aEndPt;
+ if ( pEnd )
+ aEndPt = *pEnd;
+
+ SwPosition* ppPos[2] = { 0, 0 };
+ Point paPt [2] = { rPt, aEndPt };
+ bool pbRow[2] = { 0, 0 };
+ bool pbCol[2] = { 0, 0 };
+
+ // pEnd is set during dragging.
+ for ( sal_uInt16 i = 0; i < ( pEnd ? 2 : 1 ); ++i )
+ {
+ const SwCellFrm* pFrm =
+ static_cast<const SwCellFrm*>(GetBox( paPt[i], &pbRow[i], &pbCol[i] ) );
+
+ if( pFrm )
+ {
+ while( pFrm->Lower() && pFrm->Lower()->IsRowFrm() )
+ pFrm = static_cast<const SwCellFrm*>( static_cast<const SwLayoutFrm*>( pFrm->Lower() )->Lower() );
+ if( pFrm && pFrm->GetTabBox()->GetSttNd() &&
+ pFrm->GetTabBox()->GetSttNd()->IsInProtectSect() )
+ pFrm = 0;
+ }
+
+ if ( pFrm )
+ {
+ const SwCntntFrm* pCntnt = ::GetCellCntnt( *pFrm );
+
+ if ( pCntnt && pCntnt->IsTxtFrm() )
+ {
+ ppPos[i] = new SwPosition( *pCntnt->GetNode() );
+ ppPos[i]->nContent.Assign( const_cast<SwCntntNode*>(pCntnt->GetNode()), 0 );
+
+ // paPt[i] will not be used any longer, now we use it to store
+ // a position inside the content frame
+ paPt[i] = pCntnt->Frm().Center();
+ }
+ }
+
+ // no calculation of end frame if start frame has not been found.
+ if ( 1 == i || !ppPos[0] || !pEnd )
+ break;
+
+ // find 'closest' table frame to pEnd:
+ const SwTabFrm* pCurrentTab = pFrm->FindTabFrm();
+ if ( pCurrentTab->IsFollow() )
+ pCurrentTab = pCurrentTab->FindMaster( true );
+
+ const Point aProjection = lcl_ProjectOntoClosestTableFrm( *pCurrentTab, *pEnd, bRowDrag );
+ paPt[1] = aProjection;
+ }
+
+ if ( ppPos[0] )
+ {
+ SwShellCrsr* pCrsr = _GetCrsr();
+ SwCrsrSaveState aSaveState( *pCrsr );
+ SwPosition aOldPos( *pCrsr->GetPoint() );
+
+ pCrsr->DeleteMark();
+ *pCrsr->GetPoint() = *ppPos[0];
+ pCrsr->GetPtPos() = paPt[0];
+
+ if ( !pCrsr->IsInProtectTable( sal_False, sal_True ) )
+ {
+ bool bNewSelection = true;
+
+ if ( ppPos[1] )
+ {
+ if ( ppPos[1]->nNode.GetNode().StartOfSectionNode() !=
+ aOldPos.nNode.GetNode().StartOfSectionNode() )
+ {
+ pCrsr->SetMark();
+ SwCrsrSaveState aSaveState2( *pCrsr );
+ *pCrsr->GetPoint() = *ppPos[1];
+ pCrsr->GetPtPos() = paPt[1];
+
+ if ( pCrsr->IsInProtectTable( sal_False, sal_False ) )
+ {
+ pCrsr->RestoreSavePos();
+ bNewSelection = false;
+ }
+ }
+ else
+ {
+ pCrsr->RestoreSavePos();
+ bNewSelection = false;
+ }
+ }
+
+ if ( bNewSelection )
+ {
+ // --> FME 2004-10-20 #i35543# SelTblRowCol should remove any existing
+ // table cursor:
+ if ( IsTableMode() )
+ TblCrsrToCursor();
+ // <--
+
+ if ( pbRow[0] && pbCol[0] )
+ bRet = SwCrsrShell::SelTbl();
+ else if ( pbRow[0] )
+ bRet = SwCrsrShell::_SelTblRowOrCol( true, true );
+ else if ( pbCol[0] )
+ bRet = SwCrsrShell::_SelTblRowOrCol( false, true );
+ }
+ else
+ bRet = true;
+ }
+
+ delete ppPos[0];
+ delete ppPos[1];
+ }
+
+ return bRet;
+}
+// <--
+
+
+/*************************************************************************
+|*
+|* SwFEShell::WhichMouseTabCol()
+|*
+|*************************************************************************/
+sal_uInt8 SwFEShell::WhichMouseTabCol( const Point &rPt ) const
+{
+ sal_uInt8 nRet = SW_TABCOL_NONE;
+ bool bRow = false;
+ bool bCol = false;
+ bool bSelect = false;
+
+ // First try: Do we get the row/col move cursor?
+ SwCellFrm* pFrm = (SwCellFrm*)GetBox( rPt, &bRow, 0 );
+
+ if ( !pFrm )
+ {
+ // Second try: Do we get the row/col/tab selection cursor?
+ pFrm = (SwCellFrm*)GetBox( rPt, &bRow, &bCol );
+ bSelect = true;
+ }
+
+ if( pFrm )
+ {
+ while( pFrm->Lower() && pFrm->Lower()->IsRowFrm() )
+ pFrm = (SwCellFrm*)((SwLayoutFrm*)pFrm->Lower())->Lower();
+ if( pFrm && pFrm->GetTabBox()->GetSttNd() &&
+ pFrm->GetTabBox()->GetSttNd()->IsInProtectSect() )
+ pFrm = 0;
+ }
+
+ if( pFrm )
+ {
+ if ( !bSelect )
+ {
+ if ( pFrm->IsVertical() )
+ nRet = bRow ? SW_TABCOL_VERT : SW_TABROW_VERT;
+ else
+ nRet = bRow ? SW_TABROW_HORI : SW_TABCOL_HORI;
+ }
+ else
+ {
+ const SwTabFrm* pTabFrm = pFrm->FindTabFrm();
+ if ( pTabFrm->IsVertical() )
+ {
+ if ( bRow && bCol )
+ {
+ nRet = SW_TABSEL_VERT;
+ }
+ else if ( bRow )
+ {
+ nRet = SW_TABROWSEL_VERT;
+ }
+ else if ( bCol )
+ {
+ nRet = SW_TABCOLSEL_VERT;
+ }
+ }
+ else
+ {
+ if ( bRow && bCol )
+ {
+ nRet = pTabFrm->IsRightToLeft() ?
+ SW_TABSEL_HORI_RTL :
+ SW_TABSEL_HORI;
+ }
+ else if ( bRow )
+ {
+ nRet = pTabFrm->IsRightToLeft() ?
+ SW_TABROWSEL_HORI_RTL :
+ SW_TABROWSEL_HORI;
+ }
+ else if ( bCol )
+ {
+ nRet = SW_TABCOLSEL_HORI;
+ }
+ }
+ }
+ }
+
+ return nRet;
+}
+
+// -> #i23726#
+SwTxtNode * SwFEShell::GetNumRuleNodeAtPos( const Point &rPt)
+{
+ SwTxtNode * pResult = NULL;
+
+ SwContentAtPos aCntntAtPos
+ (SwContentAtPos::SW_NUMLABEL);
+
+ if( GetContentAtPos(rPt, aCntntAtPos) && aCntntAtPos.aFnd.pNode)
+ pResult = aCntntAtPos.aFnd.pNode->GetTxtNode();
+
+ return pResult;
+}
+
+sal_Bool SwFEShell::IsNumLabel( const Point &rPt, int nMaxOffset )
+{
+ sal_Bool bResult = sal_False;
+
+ SwContentAtPos aCntntAtPos
+ (SwContentAtPos::SW_NUMLABEL);
+
+ if( GetContentAtPos(rPt, aCntntAtPos))
+ {
+ if ((nMaxOffset >= 0 && aCntntAtPos.nDist <= nMaxOffset) ||
+ (nMaxOffset < 0))
+ bResult = sal_True;
+ }
+
+ return bResult;
+}
+// <- #i23726#
+
+// --> OD 2005-02-21 #i42921#
+bool SwFEShell::IsVerticalModeAtNdAndPos( const SwTxtNode& _rTxtNode,
+ const Point& _rDocPos ) const
+{
+ bool bRet( false );
+
+ const short nTextDir =
+ _rTxtNode.GetTextDirection( SwPosition(_rTxtNode), &_rDocPos );
+ switch ( nTextDir )
+ {
+ case -1:
+ case FRMDIR_HORI_RIGHT_TOP:
+ case FRMDIR_HORI_LEFT_TOP:
+ {
+ bRet = false;
+ }
+ break;
+ case FRMDIR_VERT_TOP_LEFT:
+ case FRMDIR_VERT_TOP_RIGHT:
+ {
+ bRet = true;
+ }
+ break;
+ }
+
+ return bRet;
+}
+// <--
+
+/*************************************************************************
+|*
+|* SwFEShell::GetMouseTabCols()
+|*
+|*************************************************************************/
+void SwFEShell::GetMouseTabCols( SwTabCols &rToFill, const Point &rPt ) const
+{
+ const SwFrm *pBox = GetBox( rPt );
+ if ( pBox )
+ _GetTabCols( rToFill, pBox );
+}
+
+void SwFEShell::SetMouseTabCols( const SwTabCols &rNew, sal_Bool bCurRowOnly,
+ const Point &rPt )
+{
+ const SwFrm *pBox = GetBox( rPt );
+ if( pBox )
+ {
+ SET_CURR_SHELL( this );
+ StartAllAction();
+ GetDoc()->SetTabCols( rNew, bCurRowOnly, 0, (SwCellFrm*)pBox );
+ EndAllActionAndCall();
+ }
+}
+
+/*************************************************************************
+|*
+|* SwFEShell::GetMouseColNum(), GetMouseTabColNum()
+|*
+|*************************************************************************/
+sal_uInt16 SwFEShell::GetCurMouseColNum( const Point &rPt,
+ SwGetCurColNumPara* pPara ) const
+{
+ return _GetCurColNum( GetBox( rPt ), pPara );
+}
+
+sal_uInt16 SwFEShell::GetCurMouseTabColNum( const Point &rPt ) const
+{
+ //!!!GetCurTabColNum() mitpflegen!!!!
+ sal_uInt16 nRet = 0;
+
+ const SwFrm *pFrm = GetBox( rPt );
+ OSL_ENSURE( pFrm, "Table not found" );
+ if( pFrm )
+ {
+ const long nX = pFrm->Frm().Left();
+
+ //TabCols besorgen, den nur ueber diese erreichen wir die Position.
+ SwTabCols aTabCols;
+ GetMouseTabCols( aTabCols, rPt );
+
+ const long nLeft = aTabCols.GetLeftMin();
+
+ if ( !::IsSame( nX, nLeft + aTabCols.GetLeft() ) )
+ {
+ for ( sal_uInt16 i = 0; i < aTabCols.Count(); ++i )
+ if ( ::IsSame( nX, nLeft + aTabCols[i] ) )
+ {
+ nRet = i + 1;
+ break;
+ }
+ }
+ }
+ return nRet;
+}
+
+void ClearFEShellTabCols()
+{
+ DELETEZ( pLastCols );
+ DELETEZ( pLastRows );
+}
+
+/*************************************************************************
+|*
+|* SwFEShell::GetTblAttr(), SetTblAttr()
+|*
+|*************************************************************************/
+void SwFEShell::GetTblAttr( SfxItemSet &rSet ) const
+{
+ SwFrm *pFrm = GetCurrFrm();
+ if( pFrm && pFrm->IsInTab() )
+ rSet.Put( pFrm->ImplFindTabFrm()->GetFmt()->GetAttrSet() );
+}
+
+void SwFEShell::SetTblAttr( const SfxItemSet &rNew )
+{
+ SwFrm *pFrm = GetCurrFrm();
+ if( pFrm && pFrm->IsInTab() )
+ {
+ SET_CURR_SHELL( this );
+ StartAllAction();
+ SwTabFrm *pTab = pFrm->FindTabFrm();
+ pTab->GetTable()->SetHTMLTableLayout( 0 );
+ GetDoc()->SetAttr( rNew, *pTab->GetFmt() );
+ GetDoc()->SetModified();
+ EndAllActionAndCall();
+ }
+}
+
+/** move cursor within a table into previous/next row (same column)
+ * @param pShell cursor shell whose cursor is to be moved
+ * @param bUp true: move up, false: move down
+ * @returns true if successful
+ */
+bool lcl_GoTableRow( SwCrsrShell* pShell, bool bUp )
+{
+ OSL_ENSURE( pShell != NULL, "need shell" );
+
+ bool bRet = false;
+
+ SwPaM* pPam = pShell->GetCrsr();
+ const SwStartNode* pTableBox = pPam->GetNode()->FindTableBoxStartNode();
+ OSL_ENSURE( pTableBox != NULL, "I'm living in a box... NOT!" );
+
+ // move cursor to start node of table box
+ pPam->GetPoint()->nNode = pTableBox->GetIndex();
+ pPam->GetPoint()->nContent.Assign( NULL, 0 );
+ GoInCntnt( *pPam, fnMoveForward );
+
+ // go to beginning end of table box
+ SwPosSection fnPosSect = bUp ? fnSectionStart : fnSectionEnd;
+ pShell->MoveSection( fnSectionCurr, fnPosSect );
+
+ // and go up/down into next content
+ bRet = bUp ? pShell->Up() : pShell->Down();
+
+ return bRet;
+}
+
+ // aender eine Zellenbreite/-Hoehe/Spaltenbreite/Zeilenhoehe
+sal_Bool SwFEShell::SetColRowWidthHeight( sal_uInt16 eType, sal_uInt16 nDiff )
+{
+ SwFrm *pFrm = GetCurrFrm();
+ if( !pFrm || !pFrm->IsInTab() )
+ return sal_False;
+
+ if( nsTblChgWidthHeightType::WH_FLAG_INSDEL & eType &&
+ pFrm->ImplFindTabFrm()->GetTable()->ISA( SwDDETable ))
+ {
+ ErrorHandler::HandleError( ERR_TBLDDECHG_ERROR,
+ ERRCODE_MSG_INFO | ERRCODE_BUTTON_DEF_OK );
+ return sal_False;
+ }
+
+ SET_CURR_SHELL( this );
+ StartAllAction();
+
+ do {
+ pFrm = pFrm->GetUpper();
+ } while( !pFrm->IsCellFrm() );
+
+ SwTabFrm *pTab = pFrm->ImplFindTabFrm();
+
+ // sollte die Tabelle noch auf relativen Werten (USHRT_MAX) stehen
+ // dann muss es jetzt auf absolute umgerechnet werden.
+ const SwFmtFrmSize& rTblFrmSz = pTab->GetFmt()->GetFrmSize();
+ SWRECTFN( pTab )
+ long nPrtWidth = (pTab->Prt().*fnRect->fnGetWidth)();
+ if( TBLVAR_CHGABS == pTab->GetTable()->GetTblChgMode() &&
+ ( eType & nsTblChgWidthHeightType::WH_COL_LEFT || eType & nsTblChgWidthHeightType::WH_COL_RIGHT ) &&
+ text::HoriOrientation::NONE == pTab->GetFmt()->GetHoriOrient().GetHoriOrient() &&
+ nPrtWidth != rTblFrmSz.GetWidth() )
+ {
+ SwFmtFrmSize aSz( rTblFrmSz );
+ aSz.SetWidth( pTab->Prt().Width() );
+ pTab->GetFmt()->SetFmtAttr( aSz );
+ }
+
+ if( (eType & (nsTblChgWidthHeightType::WH_FLAG_BIGGER | nsTblChgWidthHeightType::WH_FLAG_INSDEL)) ==
+ (nsTblChgWidthHeightType::WH_FLAG_BIGGER | nsTblChgWidthHeightType::WH_FLAG_INSDEL) )
+ {
+ nDiff = sal_uInt16((pFrm->Frm().*fnRect->fnGetWidth)());
+
+ // we must move the cursor outside the current cell before
+ // deleting the cells.
+ TblChgWidthHeightType eTmp =
+ static_cast<TblChgWidthHeightType>( eType & 0xfff );
+ switch( eTmp )
+ {
+ case nsTblChgWidthHeightType::WH_ROW_TOP:
+ lcl_GoTableRow( this, true );
+ break;
+ case nsTblChgWidthHeightType::WH_ROW_BOTTOM:
+ lcl_GoTableRow( this, false );
+ break;
+ case nsTblChgWidthHeightType::WH_COL_LEFT:
+ GoPrevCell();
+ break;
+ case nsTblChgWidthHeightType::WH_COL_RIGHT:
+ GoNextCell();
+ break;
+ default:
+ break;
+ }
+ }
+
+ SwTwips nLogDiff = nDiff;
+ nLogDiff *= pTab->GetFmt()->GetFrmSize().GetWidth();
+ nLogDiff /= nPrtWidth;
+
+ /** The cells are destroyed in here */
+ sal_Bool bRet = GetDoc()->SetColRowWidthHeight(
+ *(SwTableBox*)((SwCellFrm*)pFrm)->GetTabBox(),
+ eType, nDiff, nLogDiff );
+
+ delete pLastCols, pLastCols = 0;
+ EndAllActionAndCall();
+
+ if( bRet && (eType & (nsTblChgWidthHeightType::WH_FLAG_BIGGER | nsTblChgWidthHeightType::WH_FLAG_INSDEL)) == nsTblChgWidthHeightType::WH_FLAG_INSDEL )
+ {
+ switch(eType & ~(nsTblChgWidthHeightType::WH_FLAG_BIGGER | nsTblChgWidthHeightType::WH_FLAG_INSDEL))
+ {
+ case nsTblChgWidthHeightType::WH_CELL_LEFT:
+ case nsTblChgWidthHeightType::WH_COL_LEFT:
+ GoPrevCell();
+ break;
+
+ case nsTblChgWidthHeightType::WH_CELL_RIGHT:
+ case nsTblChgWidthHeightType::WH_COL_RIGHT:
+ GoNextCell();
+ break;
+
+ case nsTblChgWidthHeightType::WH_CELL_TOP:
+ case nsTblChgWidthHeightType::WH_ROW_TOP:
+ lcl_GoTableRow( this, true );
+ break;
+
+ case nsTblChgWidthHeightType::WH_CELL_BOTTOM:
+ case nsTblChgWidthHeightType::WH_ROW_BOTTOM:
+ lcl_GoTableRow( this, false );
+ break;
+ }
+ }
+
+ return bRet;
+}
+
+sal_Bool lcl_IsFormulaSelBoxes( const SwTable& rTbl, const SwTblBoxFormula& rFml,
+ SwCellFrms& rCells )
+{
+ SwTblBoxFormula aTmp( rFml );
+ SwSelBoxes aBoxes;
+ for( sal_uInt16 nSelBoxes = aTmp.GetBoxesOfFormula( rTbl,aBoxes ); nSelBoxes; )
+ {
+ SwTableBox* pBox = aBoxes[ --nSelBoxes ];
+ sal_uInt16 i;
+ for( i = 0; i < rCells.Count(); ++i )
+ if( rCells[ i ]->GetTabBox() == pBox )
+ break; // gefunden
+
+ if( i == rCells.Count() )
+ return sal_False;
+ }
+
+ return sal_True;
+}
+
+ // erfrage die Formel fuer die Autosumme
+sal_Bool SwFEShell::GetAutoSum( String& rFml ) const
+{
+ SwFrm *pFrm = GetCurrFrm();
+ SwTabFrm *pTab = pFrm ? pFrm->ImplFindTabFrm() : 0;
+ if( !pTab )
+ return sal_False;
+
+ rFml = String::CreateFromAscii( sCalc_Sum );
+
+ SwCellFrms aCells;
+ if( ::GetAutoSumSel( *this, aCells ))
+ {
+ sal_uInt16 nW = 0, nInsPos = 0;
+ for( sal_uInt16 n = aCells.Count(); n; )
+ {
+ SwCellFrm* pCFrm = aCells[ --n ];
+ sal_uInt16 nBoxW = pCFrm->GetTabBox()->IsFormulaOrValueBox();
+ if( !nBoxW )
+ break;
+
+ if( !nW )
+ {
+ if( USHRT_MAX == nBoxW )
+ continue; // leere am Anfang ueberspringen
+
+ rFml += '(';
+ nInsPos = rFml.Len();
+
+ // Formeln nur wenn diese Boxen enthalten
+ if( RES_BOXATR_FORMULA == nBoxW &&
+ !::lcl_IsFormulaSelBoxes( *pTab->GetTable(), pCFrm->
+ GetTabBox()->GetFrmFmt()->GetTblBoxFormula(), aCells))
+ {
+ nW = RES_BOXATR_VALUE;
+ // alle vorhierigen Leere wieder mit aufnehmen !
+ for( sal_uInt16 i = aCells.Count(); n+1 < i; )
+ {
+ String sTmp( String::CreateFromAscii(
+ RTL_CONSTASCII_STRINGPARAM( "|<" )) );
+ sTmp += aCells[ --i ]->GetTabBox()->GetName();
+ sTmp += '>';
+ rFml.Insert( sTmp, nInsPos );
+ }
+ }
+ else
+ nW = nBoxW;
+ }
+ else if( RES_BOXATR_VALUE == nW )
+ {
+ // values werden gesucht, Value/Formel/Text gefunden -> aufn.
+ if( RES_BOXATR_FORMULA == nBoxW &&
+ ::lcl_IsFormulaSelBoxes( *pTab->GetTable(), pCFrm->
+ GetTabBox()->GetFrmFmt()->GetTblBoxFormula(), aCells ))
+ break;
+ else if( USHRT_MAX != nBoxW )
+ rFml.Insert( cListDelim, nInsPos );
+ else
+ break;
+ }
+ else if( RES_BOXATR_FORMULA == nW )
+ {
+ // bei Formeln nur weiter suchen, wenn die akt. Formel auf
+ // alle Boxen verweist, die sich in der Selektion befinden
+ if( RES_BOXATR_FORMULA == nBoxW )
+ {
+ if( !::lcl_IsFormulaSelBoxes( *pTab->GetTable(), pCFrm->
+ GetTabBox()->GetFrmFmt()->GetTblBoxFormula(), aCells ))
+ {
+ // dann noch mal von vorne und nur die Values!
+
+ nW = RES_BOXATR_VALUE;
+ rFml.Erase( nInsPos );
+ // alle vorhierigen Leere wieder mit aufnehmen !
+ for( sal_uInt16 i = aCells.Count(); n+1 < i; )
+ {
+ String sTmp( String::CreateFromAscii(
+ RTL_CONSTASCII_STRINGPARAM( "|<" )) );
+ sTmp += aCells[ --i ]->GetTabBox()->GetName();
+ sTmp += '>';
+ rFml.Insert( sTmp, nInsPos );
+ }
+ }
+ else
+ rFml.Insert( cListDelim, nInsPos );
+ }
+ else if( USHRT_MAX == nBoxW )
+ break;
+ else
+ continue; // diese Boxen ignorieren
+ }
+ else
+ // alles andere beendet die Schleife
+// evt. Texte noch zu lassen??
+ break;
+
+ String sTmp( '<' );
+ sTmp += pCFrm->GetTabBox()->GetName();
+ sTmp += '>';
+ rFml.Insert( sTmp, nInsPos );
+ }
+ if( nW )
+ {
+ rFml += ')';
+ }
+ }
+
+ return sal_True;
+}
+
+sal_Bool SwFEShell::IsTableRightToLeft() const
+{
+ SwFrm *pFrm = GetCurrFrm();
+ if( !pFrm || !pFrm->IsInTab() )
+ return sal_False;
+
+ return pFrm->ImplFindTabFrm()->IsRightToLeft();
+}
+
+sal_Bool SwFEShell::IsMouseTableRightToLeft(const Point &rPt) const
+{
+ SwFrm *pFrm = (SwFrm *)GetBox( rPt );
+ const SwTabFrm* pTabFrm = pFrm ? pFrm->ImplFindTabFrm() : 0;
+ OSL_ENSURE( pTabFrm, "Table not found" );
+ return pTabFrm ? pTabFrm->IsRightToLeft() : sal_False;
+}
+
+sal_Bool SwFEShell::IsTableVertical() const
+{
+ SwFrm *pFrm = GetCurrFrm();
+ if( !pFrm || !pFrm->IsInTab() )
+ return sal_False;
+
+ return pFrm->ImplFindTabFrm()->IsVertical();
+}
+
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/frmedt/fews.cxx b/sw/source/core/frmedt/fews.cxx
new file mode 100644
index 000000000000..d88e6e1b89bd
--- /dev/null
+++ b/sw/source/core/frmedt/fews.cxx
@@ -0,0 +1,1355 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+#include <svx/svdobj.hxx>
+#include <init.hxx>
+#include <fesh.hxx>
+#include <pagefrm.hxx>
+#include <rootfrm.hxx>
+#include <cntfrm.hxx>
+#include <doc.hxx>
+#include <frmtool.hxx>
+#include <swtable.hxx>
+#include <viewimp.hxx>
+#include <dview.hxx>
+#include <flyfrm.hxx>
+#include <node.hxx>
+#include <pam.hxx>
+#include <sectfrm.hxx>
+#include <fmtpdsc.hxx>
+#include <fmtsrnd.hxx>
+#include <fmtcntnt.hxx>
+#include <tabfrm.hxx>
+#include <cellfrm.hxx>
+#include <flyfrms.hxx>
+#include <txtfrm.hxx> // SwTxtFrm
+#include <mdiexp.hxx>
+#include <edimp.hxx>
+#include <pagedesc.hxx>
+#include <fmtanchr.hxx>
+#include <environmentofanchoredobject.hxx>
+#include <ndtxt.hxx> // #i22341#
+#include <dflyobj.hxx>
+#include <dcontact.hxx> // #i26791#
+
+
+using namespace com::sun::star;
+
+
+TYPEINIT1(SwFEShell,SwEditShell)
+
+/***********************************************************************
+#* Class : SwFEShell
+#* Methode : EndAllActionAndCall()
+#***********************************************************************/
+
+void SwFEShell::EndAllActionAndCall()
+{
+ ViewShell *pTmp = this;
+ do {
+ if( pTmp->IsA( TYPE(SwCrsrShell) ) )
+ {
+ ((SwFEShell*)pTmp)->EndAction();
+ ((SwFEShell*)pTmp)->CallChgLnk();
+ }
+ else
+ pTmp->EndAction();
+ } while( this != ( pTmp = (ViewShell*)pTmp->GetNext() ));
+}
+
+
+/***********************************************************************
+#* Class : SwFEShell
+#* Methode : GetCntntPos
+#* Beschreibung: Ermitteln des Cntnt's der dem Punkt am naechsten liegt
+#***********************************************************************/
+
+Point SwFEShell::GetCntntPos( const Point& rPoint, sal_Bool bNext ) const
+{
+ SET_CURR_SHELL( (ViewShell*)this );
+ return GetLayout()->GetNextPrevCntntPos( rPoint, bNext );
+}
+
+
+const SwRect& SwFEShell::GetAnyCurRect( CurRectType eType, const Point* pPt,
+ const uno::Reference < embed::XEmbeddedObject >& xObj ) const
+{
+ const SwFrm *pFrm = Imp()->HasDrawView()
+ ? ::GetFlyFromMarked( &Imp()->GetDrawView()->GetMarkedObjectList(),
+ (ViewShell*)this)
+ : 0;
+
+ if( !pFrm )
+ {
+ if( pPt )
+ {
+ SwPosition aPos( *GetCrsr()->GetPoint() );
+ Point aPt( *pPt );
+ GetLayout()->GetCrsrOfst( &aPos, aPt );
+ SwCntntNode *pNd = aPos.nNode.GetNode().GetCntntNode();
+ pFrm = pNd->getLayoutFrm( GetLayout(), pPt );
+ }
+ else
+ {
+ const bool bOldCallbackActionEnabled = GetLayout()->IsCallbackActionEnabled();
+ if( bOldCallbackActionEnabled )
+ GetLayout()->SetCallbackActionEnabled( sal_False );
+ pFrm = GetCurrFrm();
+ if( bOldCallbackActionEnabled )
+ GetLayout()->SetCallbackActionEnabled( sal_True );
+ }
+ }
+
+ if( !pFrm )
+ return GetLayout()->Frm();
+
+ sal_Bool bFrm = sal_True;
+ switch ( eType )
+ {
+ case RECT_PAGE_PRT: bFrm = sal_False; /* no break */
+ case RECT_PAGE : pFrm = pFrm->FindPageFrm();
+ break;
+
+ case RECT_PAGE_CALC: pFrm->Calc();
+ pFrm = pFrm->FindPageFrm();
+ pFrm->Calc();
+ break;
+
+ case RECT_FLY_PRT_EMBEDDED: bFrm = sal_False; /* no break */
+ case RECT_FLY_EMBEDDED: pFrm = xObj.is() ? FindFlyFrm( xObj )
+ : pFrm->IsFlyFrm()
+ ? pFrm
+ : pFrm->FindFlyFrm();
+ break;
+
+ case RECT_OUTTABSECTION_PRT:
+ case RECT_OUTTABSECTION : if( pFrm->IsInTab() )
+ pFrm = pFrm->FindTabFrm();
+ else {
+ OSL_FAIL( "Missing Table" );
+ }
+ /* KEIN BREAK */
+ case RECT_SECTION_PRT:
+ case RECT_SECTION: if( pFrm->IsInSct() )
+ pFrm = pFrm->FindSctFrm();
+ else {
+ OSL_FAIL( "Missing section" );
+ }
+
+ if( RECT_OUTTABSECTION_PRT == eType ||
+ RECT_SECTION_PRT == eType )
+ bFrm = sal_False;
+ break;
+
+ case RECT_HEADERFOOTER_PRT: bFrm = sal_False; /* no break */
+ case RECT_HEADERFOOTER: if( 0 == (pFrm = pFrm->FindFooterOrHeader()) )
+ return GetLayout()->Frm();
+ break;
+
+ case RECT_PAGES_AREA: return GetLayout()->GetPagesArea();
+
+ default: break;
+ }
+ return bFrm ? pFrm->Frm() : pFrm->Prt();
+}
+
+
+sal_uInt16 SwFEShell::GetPageNumber( const Point &rPoint ) const
+{
+ const SwFrm *pPage = GetLayout()->Lower();
+ while ( pPage && !pPage->Frm().IsInside( rPoint ) )
+ pPage = pPage->GetNext();
+ if ( pPage )
+ return ((const SwPageFrm*)pPage)->GetPhyPageNum();
+ else
+ return 0;
+}
+
+
+sal_Bool SwFEShell::GetPageNumber( long nYPos, sal_Bool bAtCrsrPos, sal_uInt16& rPhyNum, sal_uInt16& rVirtNum, String &rDisplay) const
+{
+ const SwFrm *pPage;
+
+ if ( bAtCrsrPos ) //Seite vom Crsr besorgen
+ {
+ pPage = GetCurrFrm( sal_False );
+ if ( pPage )
+ pPage = pPage->FindPageFrm();
+ }
+ else if ( nYPos > -1 ) //Seite ueber die Positon ermitteln
+ {
+ pPage = GetLayout()->Lower();
+ while( pPage && (pPage->Frm().Bottom() < nYPos ||
+ nYPos < pPage->Frm().Top() ) )
+ pPage = pPage->GetNext();
+ }
+ else //Die erste sichtbare Seite
+ {
+ pPage = Imp()->GetFirstVisPage();
+ if ( pPage && ((SwPageFrm*)pPage)->IsEmptyPage() )
+ pPage = pPage->GetNext();
+ }
+
+ if( pPage )
+ {
+ rPhyNum = ((const SwPageFrm*)pPage)->GetPhyPageNum();
+ rVirtNum = ((const SwPageFrm*)pPage)->GetVirtPageNum();
+ const SvxNumberType& rNum = ((const SwPageFrm*)pPage)->GetPageDesc()->GetNumType();
+ rDisplay = rNum.GetNumStr( rVirtNum );
+ }
+
+ return 0 != pPage;
+}
+
+/*************************************************************************
+|*
+|* SwFEShell::IsDirectlyInSection()
+|*
+|* Hack for OS:
+|*
+*************************************************************************/
+
+bool SwFEShell::IsDirectlyInSection() const
+{
+ SwFrm* pFrm = GetCurrFrm( sal_False );
+ return pFrm && pFrm->GetUpper() && pFrm->GetUpper()->IsSctFrm();
+}
+
+/*************************************************************************
+|*
+|* SwFEShell::GetFrmType()
+|*
+*************************************************************************/
+
+sal_uInt16 SwFEShell::GetFrmType( const Point *pPt, sal_Bool bStopAtFly ) const
+{
+ sal_uInt16 nReturn = FRMTYPE_NONE;
+ const SwFrm *pFrm;
+ if ( pPt )
+ {
+ SwPosition aPos( *GetCrsr()->GetPoint() );
+ Point aPt( *pPt );
+ GetLayout()->GetCrsrOfst( &aPos, aPt );
+ SwCntntNode *pNd = aPos.nNode.GetNode().GetCntntNode();
+ pFrm = pNd->getLayoutFrm( GetLayout(), pPt );
+ }
+ else
+ pFrm = GetCurrFrm( sal_False );
+ while ( pFrm )
+ {
+ switch ( pFrm->GetType() )
+ {
+ case FRM_COLUMN: if( pFrm->GetUpper()->IsSctFrm() )
+ {
+ // Check, if isn't not only a single column
+ // from a section with footnotes at the end.
+ if( pFrm->GetNext() || pFrm->GetPrev() )
+ // Sectioncolumns
+ nReturn |= ( nReturn & FRMTYPE_TABLE ) ?
+ FRMTYPE_COLSECTOUTTAB : FRMTYPE_COLSECT;
+ }
+ else // nur Seiten und Rahmenspalten
+ nReturn |= FRMTYPE_COLUMN;
+ break;
+ case FRM_PAGE: nReturn |= FRMTYPE_PAGE;
+ if( ((SwPageFrm*)pFrm)->IsFtnPage() )
+ nReturn |= FRMTYPE_FTNPAGE;
+ break;
+ case FRM_HEADER: nReturn |= FRMTYPE_HEADER; break;
+ case FRM_FOOTER: nReturn |= FRMTYPE_FOOTER; break;
+ case FRM_BODY: if( pFrm->GetUpper()->IsPageFrm() ) // nicht bei ColumnFrms
+ nReturn |= FRMTYPE_BODY;
+ break;
+ case FRM_FTN: nReturn |= FRMTYPE_FOOTNOTE; break;
+ case FRM_FLY: if( ((SwFlyFrm*)pFrm)->IsFlyLayFrm() )
+ nReturn |= FRMTYPE_FLY_FREE;
+ else if ( ((SwFlyFrm*)pFrm)->IsFlyAtCntFrm() )
+ nReturn |= FRMTYPE_FLY_ATCNT;
+ else
+ {
+ OSL_ENSURE( ((SwFlyFrm*)pFrm)->IsFlyInCntFrm(),
+ "Neuer Rahmentyp?" );
+ nReturn |= FRMTYPE_FLY_INCNT;
+ }
+ nReturn |= FRMTYPE_FLY_ANY;
+ if( bStopAtFly )
+ return nReturn;
+ break;
+ case FRM_TAB:
+ case FRM_ROW:
+ case FRM_CELL: nReturn |= FRMTYPE_TABLE; break;
+ default: /* do nothing */ break;
+ }
+ if ( pFrm->IsFlyFrm() )
+ pFrm = ((SwFlyFrm*)pFrm)->GetAnchorFrm();
+ else
+ pFrm = pFrm->GetUpper();
+ }
+ return nReturn;
+}
+
+/*************************************************************************
+|*
+|* SwFEShell::ShLooseFcs(), ShGetFcs()
+|*
+*************************************************************************/
+
+void SwFEShell::ShGetFcs( sal_Bool bUpdate )
+{
+ ::SetShell( this );
+ SwCrsrShell::ShGetFcs( bUpdate );
+
+ if ( HasDrawView() )
+ {
+ Imp()->GetDrawView()->showMarkHandles();
+ if ( Imp()->GetDrawView()->AreObjectsMarked() )
+ FrameNotify( this, FLY_DRAG_START );
+ }
+}
+
+void SwFEShell::ShLooseFcs()
+{
+ SwCrsrShell::ShLooseFcs();
+
+ if ( HasDrawView() && Imp()->GetDrawView()->AreObjectsMarked() )
+ {
+ Imp()->GetDrawView()->hideMarkHandles();
+ FrameNotify( this, FLY_DRAG_END );
+ }
+}
+
+/*************************************************************************
+|*
+|* SwFEShell::GetPhyPageNum()
+|* SwFEShell::GetVirtPageNum()
+|*
+*************************************************************************/
+
+sal_uInt16 SwFEShell::GetPhyPageNum()
+{
+ SwFrm *pFrm = GetCurrFrm();
+ if ( pFrm )
+ return pFrm->GetPhyPageNum();
+ return 0;
+}
+
+sal_uInt16 SwFEShell::GetVirtPageNum( const sal_Bool bCalcFrm )
+{
+ SwFrm *pFrm = GetCurrFrm( bCalcFrm );
+ if ( pFrm )
+ return pFrm->GetVirtPageNum();
+ return 0;
+}
+
+/*************************************************************************
+|*
+|* void lcl_SetAPageOffset()
+|* void SwFEShell::SetNewPageOffset()
+|* void SwFEShell::SetPageOffset()
+|* sal_uInt16 SwFEShell::GetPageOffset() const
+|*
+*************************************************************************/
+
+void lcl_SetAPageOffset( sal_uInt16 nOffset, SwPageFrm* pPage, SwFEShell* pThis )
+{
+ pThis->StartAllAction();
+ OSL_ENSURE( pPage->FindFirstBodyCntnt(),
+ "SwFEShell _SetAPageOffset() ohne CntntFrm" );
+
+ SwFmtPageDesc aDesc( pPage->GetPageDesc() );
+ aDesc.SetNumOffset( nOffset );
+
+ SwFrm *pFrm = pThis->GetCurrFrm( sal_False );
+ if ( pFrm->IsInTab() )
+ pThis->GetDoc()->SetAttr( aDesc, *pFrm->FindTabFrm()->GetFmt() );
+ else
+ {
+ pThis->GetDoc()->InsertPoolItem( *pThis->GetCrsr(), aDesc, 0 );
+ }
+
+ pThis->EndAllAction();
+}
+
+void SwFEShell::SetNewPageOffset( sal_uInt16 nOffset )
+{
+ GetLayout()->SetVirtPageNum( sal_True );
+ const SwPageFrm *pPage = GetCurrFrm( sal_False )->FindPageFrm();
+ lcl_SetAPageOffset( nOffset, (SwPageFrm*)pPage, this );
+}
+
+void SwFEShell::SetPageOffset( sal_uInt16 nOffset )
+{
+ const SwPageFrm *pPage = GetCurrFrm( sal_False )->FindPageFrm();
+ const SwRootFrm* pDocLayout = GetLayout();
+ while ( pPage )
+ {
+ const SwFrm *pFlow = pPage->FindFirstBodyCntnt();
+ if ( pFlow )
+ {
+ if ( pFlow->IsInTab() )
+ pFlow = pFlow->FindTabFrm();
+ const SwFmtPageDesc& rPgDesc = pFlow->GetAttrSet()->GetPageDesc();
+ if ( rPgDesc.GetNumOffset() )
+ {
+ pDocLayout->SetVirtPageNum( sal_True );
+ lcl_SetAPageOffset( nOffset, (SwPageFrm*)pPage, this );
+ break;
+ }
+ }
+ pPage = (SwPageFrm*)pPage->GetPrev();
+ }
+}
+
+sal_uInt16 SwFEShell::GetPageOffset() const
+{
+ const SwPageFrm *pPage = GetCurrFrm()->FindPageFrm();
+ while ( pPage )
+ {
+ const SwFrm *pFlow = pPage->FindFirstBodyCntnt();
+ if ( pFlow )
+ {
+ if ( pFlow->IsInTab() )
+ pFlow = pFlow->FindTabFrm();
+ const sal_uInt16 nOffset = pFlow->GetAttrSet()->GetPageDesc().GetNumOffset();
+ if ( nOffset )
+ return nOffset;
+ }
+ pPage = (SwPageFrm*)pPage->GetPrev();
+ }
+ return 0;
+}
+
+/*************************************************************************
+|*
+|* SwFEShell::InsertLabel()
+|*
+*************************************************************************/
+
+void SwFEShell::InsertLabel( const SwLabelType eType, const String &rTxt, const String& rSeparator,
+ const String& rNumberSeparator,
+ const sal_Bool bBefore, const sal_uInt16 nId,
+ const String& rCharacterStyle,
+ const sal_Bool bCpyBrd )
+{
+ //NodeIndex der CrsrPosition besorgen, den Rest kann das Dokument
+ //selbst erledigen.
+ SwCntntFrm *pCnt = LTYPE_DRAW==eType ? 0 : GetCurrFrm( sal_False );
+ if( LTYPE_DRAW==eType || pCnt )
+ {
+ StartAllAction();
+
+ sal_uLong nIdx = 0;
+ SwFlyFrmFmt* pFlyFmt = 0;
+ switch( eType )
+ {
+ case LTYPE_OBJECT:
+ case LTYPE_FLY:
+ if( pCnt->IsInFly() )
+ {
+ //Bei Flys den Index auf den StartNode herunterreichen.
+ nIdx = pCnt->FindFlyFrm()->
+ GetFmt()->GetCntnt().GetCntntIdx()->GetIndex();
+ }
+ break;
+ case LTYPE_TABLE:
+ if( pCnt->IsInTab() )
+ {
+ //Bei Tabellen den Index auf den TblNode herunterreichen.
+ const SwTable& rTbl = *pCnt->FindTabFrm()->GetTable();
+ nIdx = rTbl.GetTabSortBoxes()[ 0 ]
+ ->GetSttNd()->FindTableNode()->GetIndex();
+ }
+ break;
+ case LTYPE_DRAW:
+ if( Imp()->GetDrawView() )
+ {
+ SwDrawView *pDView = Imp()->GetDrawView();
+ const SdrMarkList& rMrkList = pDView->GetMarkedObjectList();
+ StartUndo();
+
+ // copy marked drawing objects to
+ // local list to perform the corresponding action for each object
+ std::vector<SdrObject*> aDrawObjs;
+ {
+ for ( sal_uInt16 i = 0; i < rMrkList.GetMarkCount(); ++i )
+ {
+ SdrObject* pDrawObj = rMrkList.GetMark(i)->GetMarkedSdrObj();
+ if( pDrawObj )
+ aDrawObjs.push_back( pDrawObj );
+ }
+ }
+ // loop on marked drawing objects
+ while ( !aDrawObjs.empty() )
+ {
+ SdrObject* pDrawObj = aDrawObjs.back();
+ if ( !pDrawObj->ISA(SwVirtFlyDrawObj) &&
+ !pDrawObj->ISA(SwFlyDrawObj) )
+ {
+ SwFlyFrmFmt *pFmt =
+ GetDoc()->InsertDrawLabel( rTxt, rSeparator, rNumberSeparator, nId, rCharacterStyle, *pDrawObj );
+ if( !pFlyFmt )
+ pFlyFmt = pFmt;
+ }
+
+ aDrawObjs.pop_back();
+ }
+
+ EndUndo();
+ }
+ break;
+ default:
+ OSL_ENSURE( !this, "Crsr weder in Tabelle noch in Fly." );
+ }
+
+ if( nIdx )
+ pFlyFmt = GetDoc()->InsertLabel( eType, rTxt, rSeparator, rNumberSeparator, bBefore, nId,
+ nIdx, rCharacterStyle, bCpyBrd );
+
+ SwFlyFrm* pFrm;
+ const Point aPt( GetCrsrDocPos() );
+ if( pFlyFmt && 0 != ( pFrm = pFlyFmt->GetFrm( &aPt )))
+ SelectFlyFrm( *pFrm, sal_True );
+
+ EndAllActionAndCall();
+ }
+}
+
+
+/***********************************************************************
+#* Class : SwFEShell
+#* Methoden : Sort
+#***********************************************************************/
+
+sal_Bool SwFEShell::Sort(const SwSortOptions& rOpt)
+{
+ if( !HasSelection() )
+ return sal_False;
+
+ SET_CURR_SHELL( this );
+ sal_Bool bRet;
+ StartAllAction();
+ if(IsTableMode())
+ {
+ // Tabelle sortieren
+ // pruefe ob vom aktuellen Crsr der SPoint/Mark in einer Tabelle stehen
+ SwFrm *pFrm = GetCurrFrm( sal_False );
+ OSL_ENSURE( pFrm->FindTabFrm(), "Crsr nicht in Tabelle." );
+
+ // lasse ueber das Layout die Boxen suchen
+ SwSelBoxes aBoxes;
+ GetTblSel(*this, aBoxes);
+
+ // die Crsr muessen noch aus dem Loesch Bereich entfernt
+ // werden. Setze sie immer hinter/auf die Tabelle; ueber die
+ // Dokument-Position werden sie dann immer an die alte Position gesetzt.
+ while( !pFrm->IsCellFrm() )
+ pFrm = pFrm->GetUpper();
+ {
+ /* ParkCursor->ParkCursorTab */
+ ParkCursorInTab();
+ }
+
+ // Sorting am Dokument aufrufen
+ bRet = pDoc->SortTbl(aBoxes, rOpt);
+ }
+ else
+ {
+ // Text sortieren und nichts anderes
+ FOREACHPAM_START(this)
+
+ SwPaM* pPam = PCURCRSR;
+
+ SwPosition* pStart = pPam->Start();
+ SwPosition* pEnd = pPam->End();
+
+ SwNodeIndex aPrevIdx( pStart->nNode, -1 );
+ sal_uLong nOffset = pEnd->nNode.GetIndex() - pStart->nNode.GetIndex();
+ xub_StrLen nCntStt = pStart->nContent.GetIndex();
+
+ // Das Sortieren
+ bRet = pDoc->SortText(*pPam, rOpt);
+
+ // Selektion wieder setzen
+ pPam->DeleteMark();
+ pPam->GetPoint()->nNode.Assign( aPrevIdx.GetNode(), +1 );
+ SwCntntNode* pCNd = pPam->GetCntntNode();
+ xub_StrLen nLen = pCNd->Len();
+ if( nLen > nCntStt )
+ nLen = nCntStt;
+ pPam->GetPoint()->nContent.Assign(pCNd, nLen );
+ pPam->SetMark();
+
+ pPam->GetPoint()->nNode += nOffset;
+ pCNd = pPam->GetCntntNode();
+ pPam->GetPoint()->nContent.Assign( pCNd, pCNd->Len() );
+
+ FOREACHPAM_END()
+ }
+
+ EndAllAction();
+ return bRet;
+}
+
+/*************************************************************************
+|*
+|* SwFEShell::GetCurColNum(), _GetColNum()
+|*
+|*************************************************************************/
+
+sal_uInt16 SwFEShell::_GetCurColNum( const SwFrm *pFrm,
+ SwGetCurColNumPara* pPara ) const
+{
+ sal_uInt16 nRet = 0;
+ while ( pFrm )
+ {
+ pFrm = pFrm->GetUpper();
+ if( pFrm && pFrm->IsColumnFrm() )
+ {
+ const SwFrm *pCurFrm = pFrm;
+ do {
+ ++nRet;
+ pFrm = pFrm->GetPrev();
+ } while ( pFrm );
+
+ if( pPara )
+ {
+ // dann suche mal das Format, was diese Spaltigkeit bestimmt
+ pFrm = pCurFrm->GetUpper();
+ while( pFrm )
+ {
+ if( ( FRM_PAGE | FRM_FLY | FRM_SECTION ) & pFrm->GetType() )
+ {
+ pPara->pFrmFmt = ((SwLayoutFrm*)pFrm)->GetFmt();
+ pPara->pPrtRect = &pFrm->Prt();
+ pPara->pFrmRect = &pFrm->Frm();
+ break;
+ }
+ pFrm = pFrm->GetUpper();
+ }
+ if( !pFrm )
+ {
+ pPara->pFrmFmt = 0;
+ pPara->pPrtRect = 0;
+ pPara->pFrmRect = 0;
+ }
+ }
+ break;
+ }
+ }
+ return nRet;
+}
+
+sal_uInt16 SwFEShell::GetCurColNum( SwGetCurColNumPara* pPara ) const
+{
+ OSL_ENSURE( GetCurrFrm(), "Crsr geparkt?" );
+ return _GetCurColNum( GetCurrFrm(), pPara );
+}
+
+sal_uInt16 SwFEShell::GetCurOutColNum( SwGetCurColNumPara* pPara ) const
+{
+ sal_uInt16 nRet = 0;
+ SwFrm* pFrm = GetCurrFrm();
+ OSL_ENSURE( pFrm, "Crsr geparkt?" );
+ if( pFrm )
+ {
+ pFrm = pFrm->IsInTab() ? (SwFrm*)pFrm->FindTabFrm()
+ : (SwFrm*)pFrm->FindSctFrm();
+ OSL_ENSURE( pFrm, "No Tab, no Sect" );
+ if( pFrm )
+ nRet = _GetCurColNum( pFrm, pPara );
+ }
+ return nRet;
+}
+
+SwFEShell::SwFEShell( SwDoc& rDoc, Window *pWindow, const SwViewOption *pOptions )
+ : SwEditShell( rDoc, pWindow, pOptions ),
+ pChainFrom( 0 ), pChainTo( 0 ), bCheckForOLEInCaption( sal_False )
+{
+}
+
+SwFEShell::SwFEShell( SwEditShell& rShell, Window *pWindow )
+ : SwEditShell( rShell, pWindow ),
+ pChainFrom( 0 ), pChainTo( 0 ), bCheckForOLEInCaption( sal_False )
+{
+}
+
+SwFEShell::~SwFEShell()
+{
+ delete pChainFrom;
+ delete pChainTo;
+}
+
+// #i17567# - adjustments for allowing
+// negative vertical positions for fly frames anchored to paragraph/to character.
+// #i22305# - adjustments for option 'Follow text flow'
+// for to frame anchored objects.
+// #i22341# - adjustments for vertical alignment at top of line
+// for to character anchored objects.
+void SwFEShell::CalcBoundRect( SwRect& _orRect,
+ const RndStdIds _nAnchorId,
+ const sal_Int16 _eHoriRelOrient,
+ const sal_Int16 _eVertRelOrient,
+ const SwPosition* _pToCharCntntPos,
+ const bool _bFollowTextFlow,
+ bool _bMirror,
+ Point* _opRef,
+ Size* _opPercent ) const
+{
+ const SwFrm* pFrm;
+ const SwFlyFrm* pFly;
+ if( _opRef )
+ {
+ pFrm = GetCurrFrm();
+ if( 0 != ( pFly = pFrm->FindFlyFrm() ) )
+ pFrm = pFly->GetAnchorFrm();
+ }
+ else
+ {
+ pFly = FindFlyFrm();
+ pFrm = pFly ? pFly->GetAnchorFrm() : GetCurrFrm();
+ }
+
+ sal_Bool bWrapThrough = sal_False;
+ if ( pFly )
+ {
+ SwFlyFrmFmt* pFmt = (SwFlyFrmFmt*)pFly->GetFmt();
+ const SwFmtSurround& rSurround = pFmt->GetSurround();
+ bWrapThrough = rSurround.GetSurround() == SURROUND_THROUGHT;
+ }
+
+ const SwPageFrm* pPage = pFrm->FindPageFrm();
+ _bMirror = _bMirror && !pPage->OnRightPage();
+
+ Point aPos;
+ bool bVertic = false;
+ sal_Bool bRTL = sal_False;
+ // --> OD 2009-09-01 #mongolianlayout#
+ bool bVerticalL2R = false;
+ // <--
+
+ if ((FLY_AT_PAGE == _nAnchorId) || (FLY_AT_FLY == _nAnchorId)) // LAYER_IMPL
+ {
+ const SwFrm* pTmp = pFrm;
+ // OD 06.11.2003 #i22305#
+ if ((FLY_AT_PAGE == _nAnchorId) ||
+ ((FLY_AT_FLY == _nAnchorId) && !_bFollowTextFlow))
+ {
+ pFrm = pPage;
+ }
+ else
+ {
+ pFrm = pFrm->FindFlyFrm();
+ }
+ if ( !pFrm )
+ pFrm = pTmp;
+ _orRect = pFrm->Frm();
+ SWRECTFN( pFrm )
+ bRTL = pFrm->IsRightToLeft();
+ if ( bRTL )
+ aPos = pFrm->Frm().TopRight();
+ else
+ aPos = (pFrm->Frm().*fnRect->fnGetPos)();
+
+ // --> OD 2009-09-01 #mongolianlayout#
+ if( bVert || bVertL2R )
+ // <--
+ {
+ // --> OD 2009-09-01 #mongolianlayout#
+ bVertic = bVert ? true : false;
+ bVerticalL2R = bVertL2R ? true : false;
+ // <--
+ _bMirror = false; // no mirroring in vertical environment
+ switch ( _eHoriRelOrient )
+ {
+ case text::RelOrientation::PAGE_RIGHT:
+ case text::RelOrientation::FRAME_RIGHT: aPos.Y() += pFrm->Prt().Height();
+ // no break!
+ case text::RelOrientation::PRINT_AREA:
+ case text::RelOrientation::PAGE_PRINT_AREA: aPos.Y() += pFrm->Prt().Top(); break;
+ default: break;
+ }
+ }
+ else if ( _bMirror )
+ {
+ switch ( _eHoriRelOrient )
+ {
+ case text::RelOrientation::PRINT_AREA:
+ case text::RelOrientation::PAGE_PRINT_AREA: aPos.X() += pFrm->Prt().Width();
+ // kein break
+ case text::RelOrientation::PAGE_RIGHT:
+ case text::RelOrientation::FRAME_RIGHT: aPos.X() += pFrm->Prt().Left(); break;
+ default: aPos.X() += pFrm->Frm().Width();
+ }
+ }
+ else if ( bRTL )
+ {
+ switch ( _eHoriRelOrient )
+ {
+ case text::RelOrientation::PRINT_AREA:
+ case text::RelOrientation::PAGE_PRINT_AREA: aPos.X() += pFrm->Prt().Width();
+ // kein break!
+ case text::RelOrientation::PAGE_LEFT:
+ case text::RelOrientation::FRAME_LEFT: aPos.X() += pFrm->Prt().Left() -
+ pFrm->Frm().Width(); break;
+ default: break;
+ }
+ }
+ else
+ {
+ switch ( _eHoriRelOrient )
+ {
+ case text::RelOrientation::PAGE_RIGHT:
+ case text::RelOrientation::FRAME_RIGHT: aPos.X() += pFrm->Prt().Width();
+ // kein break!
+ case text::RelOrientation::PRINT_AREA:
+ case text::RelOrientation::PAGE_PRINT_AREA: aPos.X() += pFrm->Prt().Left(); break;
+ default:break;
+ }
+ }
+ // --> OD 2009-09-01 #mongolianlayout#
+ if ( bVert && !bVertL2R )
+ // <--
+ {
+ switch ( _eVertRelOrient )
+ {
+ case text::RelOrientation::PRINT_AREA:
+ case text::RelOrientation::PAGE_PRINT_AREA:
+ {
+ aPos.X() -= pFrm->GetRightMargin();
+ }
+ break;
+ }
+ }
+ // --> OD 2009-09-01 #mongolianlayout#
+ else if ( bVertL2R )
+ {
+ switch ( _eVertRelOrient )
+ {
+ case text::RelOrientation::PRINT_AREA:
+ case text::RelOrientation::PAGE_PRINT_AREA:
+ {
+ aPos.X() += pFrm->GetLeftMargin();
+ }
+ break;
+ }
+ }
+ // <--
+ else
+ {
+ switch ( _eVertRelOrient )
+ {
+ case text::RelOrientation::PRINT_AREA:
+ case text::RelOrientation::PAGE_PRINT_AREA:
+ {
+ if ( pFrm->IsPageFrm() )
+ {
+ aPos.Y() =
+ static_cast<const SwPageFrm*>(pFrm)->PrtWithoutHeaderAndFooter().Top();
+ }
+ else
+ {
+ aPos.Y() += pFrm->Prt().Top();
+ }
+ }
+ break;
+ }
+ }
+ // <--
+ if ( _opPercent )
+ *_opPercent = pFrm->Prt().SSize();
+ }
+ else
+ {
+ const SwFrm* pUpper = ( pFrm->IsPageFrm() || pFrm->IsFlyFrm() ) ?
+ pFrm : pFrm->GetUpper();
+ SWRECTFN( pUpper );
+ if ( _opPercent )
+ *_opPercent = pUpper->Prt().SSize();
+
+ bRTL = pFrm->IsRightToLeft();
+ if ( bRTL )
+ aPos = pFrm->Frm().TopRight();
+ else
+ aPos = (pFrm->Frm().*fnRect->fnGetPos)();
+ // #i17567# - allow negative positions
+ // for fly frames anchor to paragraph/to character.
+ if ((_nAnchorId == FLY_AT_PARA) || (_nAnchorId == FLY_AT_CHAR))
+ {
+ // The rectangle, the fly frame can be positioned in, is determined
+ // horizontally by the frame area of the horizontal environment
+ // and vertically by the printing area of the vertical environment,
+ // if the object follows the text flow, or by the frame area of the
+ // vertical environment, if the object doesn't follow the text flow.
+ // new class <SwEnvironmentOfAnchoredObject>
+ objectpositioning::SwEnvironmentOfAnchoredObject aEnvOfObj(
+ _bFollowTextFlow );
+ const SwLayoutFrm& rHoriEnvironLayFrm =
+ aEnvOfObj.GetHoriEnvironmentLayoutFrm( *pFrm );
+ const SwLayoutFrm& rVertEnvironLayFrm =
+ aEnvOfObj.GetVertEnvironmentLayoutFrm( *pFrm );
+ SwRect aHoriEnvironRect( rHoriEnvironLayFrm.Frm() );
+ SwRect aVertEnvironRect;
+ if ( _bFollowTextFlow )
+ {
+ aVertEnvironRect = rVertEnvironLayFrm.Prt();
+ aVertEnvironRect.Pos() += rVertEnvironLayFrm.Frm().Pos();
+ // #i18732# - adjust vertical 'virtual' anchor position
+ // (<aPos.Y()> respectively <aPos.X()>), if object is vertical aligned
+ // to page areas.
+ if ( _eVertRelOrient == text::RelOrientation::PAGE_FRAME || _eVertRelOrient == text::RelOrientation::PAGE_PRINT_AREA )
+ {
+ // --> OD 2009-09-01 #mongolianlayout#
+ if ( bVert && !bVertL2R )
+ // <--
+ {
+ aPos.X() = aVertEnvironRect.Right();
+ }
+ // --> OD 2009-09-01 #mongolianlayout#
+ else if ( bVertL2R )
+ {
+ aPos.X() = aVertEnvironRect.Left();
+ }
+ else
+ {
+ aPos.Y() = aVertEnvironRect.Top();
+ }
+ }
+ }
+ else
+ {
+ OSL_ENSURE( rVertEnvironLayFrm.IsPageFrm(),
+ "<SwFEShell::CalcBoundRect(..)> - not following text flow, but vertical environment *not* page!" );
+ aVertEnvironRect = rVertEnvironLayFrm.Frm();
+ // OD 19.09.2003 #i18732# - adjustment vertical 'virtual' anchor position
+ // (<aPos.Y()> respectively <aPos.X()>), if object is vertical aligned
+ // to page areas.
+ if ( _eVertRelOrient == text::RelOrientation::PAGE_FRAME || _eVertRelOrient == text::RelOrientation::PAGE_PRINT_AREA )
+ {
+ // --> OD 2009-09-01 #mongolianlayout#
+ if ( bVert && !bVertL2R )
+ // <--
+ {
+ aPos.X() = aVertEnvironRect.Right();
+ if ( _eVertRelOrient == text::RelOrientation::PAGE_PRINT_AREA )
+ {
+ aPos.X() -= rVertEnvironLayFrm.GetRightMargin();
+ }
+ }
+ // --> OD 2009-09-01 #mongolianlayout#
+ else if ( bVertL2R )
+ {
+ aPos.X() = aVertEnvironRect.Left();
+ if ( _eVertRelOrient == text::RelOrientation::PAGE_PRINT_AREA )
+ {
+ aPos.X() += rVertEnvironLayFrm.GetLeftMargin();
+ }
+ }
+ // <--
+ else
+ {
+ aPos.Y() = aVertEnvironRect.Top();
+ if ( _eVertRelOrient == text::RelOrientation::PAGE_PRINT_AREA )
+ {
+ aPos.Y() += rVertEnvironLayFrm.GetTopMargin();
+ // add height of page header
+ const SwFrm* pTmpFrm = rVertEnvironLayFrm.Lower();
+ if ( pTmpFrm->IsHeaderFrm() )
+ {
+ aPos.Y() += pTmpFrm->Frm().Height();
+ }
+ }
+ }
+ }
+ }
+
+ // #i22341# - adjust vertical 'virtual' anchor position
+ // (<aPos.Y()> respectively <aPos.X()>), if object is anchored to
+ // character and vertical aligned at character or top of line
+ // --> OD 2005-12-29 #125800#
+ // <pFrm>, which is the anchor frame or the proposed anchor frame,
+ // doesn't have to be a text frame (e.g. edit a to-page anchored
+ // fly frame). Thus, assure this.
+ const SwTxtFrm* pTxtFrm( dynamic_cast<const SwTxtFrm*>(pFrm) );
+ if ( pTxtFrm &&
+ (_nAnchorId == FLY_AT_CHAR) &&
+ ( _eVertRelOrient == text::RelOrientation::CHAR ||
+ _eVertRelOrient == text::RelOrientation::TEXT_LINE ) )
+ {
+ SwTwips nTop = 0L;
+ if ( _eVertRelOrient == text::RelOrientation::CHAR )
+ {
+ SwRect aChRect;
+ if ( _pToCharCntntPos )
+ {
+ pTxtFrm->GetAutoPos( aChRect, *_pToCharCntntPos );
+ }
+ else
+ {
+ // No content position provided. Thus, use a default one.
+ SwPosition aDefaultCntntPos( *(pTxtFrm->GetTxtNode()) );
+ pTxtFrm->GetAutoPos( aChRect, aDefaultCntntPos );
+ }
+ nTop = (aChRect.*fnRect->fnGetBottom)();
+ }
+ else
+ {
+ if ( _pToCharCntntPos )
+ {
+ pTxtFrm->GetTopOfLine( nTop, *_pToCharCntntPos );
+ }
+ else
+ {
+ // No content position provided. Thus, use a default one.
+ SwPosition aDefaultCntntPos( *(pTxtFrm->GetTxtNode()) );
+ pTxtFrm->GetTopOfLine( nTop, aDefaultCntntPos );
+ }
+ }
+ // --> OD 2009-09-01 #mongolianlayout#
+ if ( bVert || bVertL2R )
+ {
+ aPos.X() = nTop;
+ }
+ // <--
+ else
+ {
+ aPos.Y() = nTop;
+ }
+ }
+
+ // --> OD 2004-10-05 #i26945# - adjust horizontal 'virtual' anchor
+ // position (<aPos.X()> respectively <aPos.Y()>), if object is
+ // anchored to character and horizontal aligned at character.
+ if ( pTxtFrm &&
+ (_nAnchorId == FLY_AT_CHAR) &&
+ _eHoriRelOrient == text::RelOrientation::CHAR )
+ {
+ SwTwips nLeft = 0L;
+ SwRect aChRect;
+ if ( _pToCharCntntPos )
+ {
+ pTxtFrm->GetAutoPos( aChRect, *_pToCharCntntPos );
+ }
+ else
+ {
+ // No content position provided. Thus, use a default one.
+ SwPosition aDefaultCntntPos( *(pTxtFrm->GetTxtNode()) );
+ pTxtFrm->GetAutoPos( aChRect, aDefaultCntntPos );
+ }
+ nLeft = (aChRect.*fnRect->fnGetLeft)();
+ // --> OD 2009-09-01 #mongolianlayout#
+ if ( bVert || bVertL2R )
+ {
+ aPos.Y() = nLeft;
+ }
+ // <--
+ else
+ {
+ aPos.X() = nLeft;
+ }
+ }
+ // <--
+
+ // --> OD 2009-09-01 #mongolianlayout#
+ if ( bVert || bVertL2R )
+ // <--
+ {
+ _orRect = SwRect( aVertEnvironRect.Left(),
+ aHoriEnvironRect.Top(),
+ aVertEnvironRect.Width(),
+ aHoriEnvironRect.Height() );
+ }
+ else
+ {
+ _orRect = SwRect( aHoriEnvironRect.Left(),
+ aVertEnvironRect.Top(),
+ aHoriEnvironRect.Width(),
+ aVertEnvironRect.Height() );
+ }
+ }
+ else
+ {
+ if( _opRef && pFly && pFly->IsFlyInCntFrm() )
+ *_opRef = ( (SwFlyInCntFrm*)pFly )->GetRefPoint();
+
+ _orRect = pUpper->Frm();
+ if( !pUpper->IsBodyFrm() )
+ {
+ _orRect += pUpper->Prt().Pos();
+ _orRect.SSize( pUpper->Prt().SSize() );
+ if ( pUpper->IsCellFrm() )//MA_FLY_HEIGHT
+ {
+ const SwFrm* pTab = pUpper->FindTabFrm();
+ long nBottom = (pTab->GetUpper()->*fnRect->fnGetPrtBottom)();
+ (_orRect.*fnRect->fnSetBottom)( nBottom );
+ }
+ }
+ // bei zeichengebundenen lieber nur 90% der Hoehe ausnutzen
+ {
+ // --> OD 2009-09-01 #mongolianlayout#
+ if( bVert || bVertL2R )
+ // <--
+ _orRect.Width( (_orRect.Width()*9)/10 );
+ else
+ _orRect.Height( (_orRect.Height()*9)/10 );
+ }
+ }
+
+ const SwTwips nBaseOfstForFly = ( pFrm->IsTxtFrm() && pFly ) ?
+ ((SwTxtFrm*)pFrm)->GetBaseOfstForFly( !bWrapThrough ) :
+ 0;
+ // --> OD 2009-09-01 #mongolianlayout#
+ if( bVert || bVertL2R )
+ // <--
+ {
+ // --> OD 2009-09-01 #mongolianlayout#
+ bVertic = bVert ? true : false;
+ bVerticalL2R = bVertL2R ? true : false;
+ // <--
+ _bMirror = false;
+
+ switch ( _eHoriRelOrient )
+ {
+ case text::RelOrientation::FRAME_RIGHT:
+ {
+ aPos.Y() += pFrm->Prt().Height();
+ aPos += (pFrm->Prt().*fnRect->fnGetPos)();
+ break;
+ }
+ case text::RelOrientation::PRINT_AREA:
+ {
+ aPos += (pFrm->Prt().*fnRect->fnGetPos)();
+ aPos.Y() += nBaseOfstForFly;
+ break;
+ }
+ case text::RelOrientation::PAGE_RIGHT:
+ {
+ aPos.Y() = pPage->Frm().Top() + pPage->Prt().Bottom();
+ break;
+ }
+ case text::RelOrientation::PAGE_PRINT_AREA:
+ {
+ aPos.Y() = pPage->Frm().Top() + pPage->Prt().Top();
+ break;
+ }
+ case text::RelOrientation::PAGE_LEFT:
+ case text::RelOrientation::PAGE_FRAME:
+ {
+ aPos.Y() = pPage->Frm().Top();
+ break;
+ }
+ case text::RelOrientation::FRAME:
+ {
+ aPos.Y() += nBaseOfstForFly;
+ break;
+ }
+ default: break;
+ }
+ }
+ else if( _bMirror )
+ {
+ switch ( _eHoriRelOrient )
+ {
+ case text::RelOrientation::FRAME_RIGHT: aPos.X() += pFrm->Prt().Left(); break;
+ case text::RelOrientation::FRAME:
+ case text::RelOrientation::FRAME_LEFT: aPos.X() += pFrm->Frm().Width(); break;
+ case text::RelOrientation::PRINT_AREA: aPos.X() += pFrm->Prt().Right(); break;
+ case text::RelOrientation::PAGE_LEFT:
+ case text::RelOrientation::PAGE_FRAME: aPos.X() = pPage->Frm().Right(); break;
+ case text::RelOrientation::PAGE_PRINT_AREA: aPos.X() = pPage->Frm().Left()
+ + pPage->Prt().Left(); break;
+ default: break;
+ }
+ }
+ else if ( bRTL )
+ {
+ switch ( _eHoriRelOrient )
+ {
+ case text::RelOrientation::FRAME_LEFT:
+ aPos.X() = pFrm->Frm().Left() +
+ pFrm->Prt().Left();
+ break;
+
+ case text::RelOrientation::PRINT_AREA:
+ aPos.X() = pFrm->Frm().Left() + pFrm->Prt().Left() +
+ pFrm->Prt().Width();
+ aPos.X() += nBaseOfstForFly;
+ break;
+
+ case text::RelOrientation::PAGE_LEFT:
+ aPos.X() = pPage->Frm().Left() + pPage->Prt().Left();
+ break;
+
+ case text::RelOrientation::PAGE_PRINT_AREA:
+ aPos.X() = pPage->Frm().Left() + pPage->Prt().Left() +
+ pPage->Prt().Width() ;
+ break;
+
+ case text::RelOrientation::PAGE_RIGHT:
+ case text::RelOrientation::PAGE_FRAME:
+ aPos.X() = pPage->Frm().Right();
+ break;
+
+ case text::RelOrientation::FRAME:
+ aPos.X() += nBaseOfstForFly;
+ break;
+ default: break;
+ }
+ }
+ else
+ {
+ switch ( _eHoriRelOrient )
+ {
+ case text::RelOrientation::FRAME_RIGHT:
+ aPos.X() += pFrm->Prt().Width();
+ aPos += pFrm->Prt().Pos();
+ break;
+ case text::RelOrientation::PRINT_AREA:
+ aPos += pFrm->Prt().Pos();
+ aPos.X() += nBaseOfstForFly;
+ break;
+ case text::RelOrientation::PAGE_RIGHT:
+ aPos.X() = pPage->Frm().Left() + pPage->Prt().Right();
+ break;
+ case text::RelOrientation::PAGE_PRINT_AREA:
+ aPos.X() = pPage->Frm().Left() + pPage->Prt().Left();
+ break;
+ case text::RelOrientation::PAGE_LEFT:
+ case text::RelOrientation::PAGE_FRAME:
+ aPos.X() = pPage->Frm().Left();
+ break;
+ case text::RelOrientation::FRAME:
+ aPos.X() += nBaseOfstForFly;
+ break;
+ default: break;
+ }
+ }
+
+ }
+ if( !_opRef )
+ {
+ if( bVertic && !bVerticalL2R )
+ _orRect.Pos( aPos.X() - _orRect.Width() - _orRect.Left(), _orRect.Top() - aPos.Y() );
+ // --> OD 2009-09-01 #mongolianlayout#
+ else if( bVerticalL2R )
+ _orRect.Pos( _orRect.Left() - aPos.X(), _orRect.Top() - aPos.Y() );
+ // <--
+ else if ( bRTL )
+ _orRect.Pos( - ( _orRect.Right() - aPos.X() ), _orRect.Top() - aPos.Y() );
+ else
+ _orRect.Pos( _orRect.Left() - aPos.X(), _orRect.Top() - aPos.Y() );
+ if( _bMirror )
+ _orRect.Pos( -_orRect.Right(), _orRect.Top() );
+ }
+}
+
+Size SwFEShell::GetGraphicDefaultSize() const
+{
+ Size aRet;
+ SwFlyFrm *pFly = FindFlyFrm();
+ if ( pFly )
+ {
+ // --> OD 2004-09-24 #i32951# - due to issue #i28701# no format of a
+ // newly inserted Writer fly frame or its anchor frame is performed
+ // any more. Thus, it could be possible (e.g. on insert of a horizontal
+ // line) that the anchor frame isn't formatted and its printing area
+ // size is (0,0). If this is the case the printing area of the upper
+ // of the anchor frame is taken.
+ const SwFrm* pAnchorFrm = pFly->GetAnchorFrm();
+ aRet = pAnchorFrm->Prt().SSize();
+ if ( aRet.Width() == 0 && aRet.Height() == 0 &&
+ pAnchorFrm->GetUpper() )
+ {
+ aRet = pAnchorFrm->GetUpper()->Prt().SSize();
+ }
+ // <--
+
+ SwRect aBound;
+ CalcBoundRect( aBound, pFly->GetFmt()->GetAnchor().GetAnchorId());
+ if ( pFly->GetAnchorFrm()->IsVertical() )
+ aRet.Width() = aBound.Width();
+ else
+ aRet.Height() = aBound.Height();
+ }
+ return aRet;
+}
+
+// --> OD 2009-08-31 #mongolianlayou#
+// add output parameter <bVertL2R>
+sal_Bool SwFEShell::IsFrmVertical(const sal_Bool bEnvironment, sal_Bool& bRTL, sal_Bool& bVertL2R) const
+{
+ sal_Bool bVert = sal_False;
+ bRTL = sal_False;
+ bVertL2R = sal_False;
+
+ if ( Imp()->HasDrawView() )
+ {
+ const SdrMarkList &rMrkList = Imp()->GetDrawView()->GetMarkedObjectList();
+ if( rMrkList.GetMarkCount() != 1 )
+ return bVert;
+
+ SdrObject* pObj = rMrkList.GetMark( 0 )->GetMarkedSdrObj();
+ if ( !pObj )
+ {
+ OSL_FAIL( "<SwFEShell::IsFrmVertical(..)> - missing SdrObject instance in marked object list -> This is a serious situation, please inform OD" );
+ return bVert;
+ }
+ // #i26791#
+ SwContact* pContact = static_cast<SwContact*>(GetUserCall( pObj ));
+ if ( !pContact )
+ {
+ OSL_FAIL( "<SwFEShell::IsFrmVertical(..)> - missing SwContact instance at marked object -> This is a serious situation, please inform OD" );
+ return bVert;
+ }
+ const SwFrm* pRef = pContact->GetAnchoredObj( pObj )->GetAnchorFrm();
+ if ( !pRef )
+ {
+ OSL_FAIL( "<SwFEShell::IsFrmVertical(..)> - missing anchor frame at marked object -> This is a serious situation, please inform OD" );
+ return bVert;
+ }
+
+ if ( pObj->ISA(SwVirtFlyDrawObj) && !bEnvironment )
+ pRef = static_cast<const SwVirtFlyDrawObj*>(pObj)->GetFlyFrm();
+
+ bVert = pRef->IsVertical();
+ bRTL = pRef->IsRightToLeft();
+ bVertL2R = pRef->IsVertLR();
+ }
+
+ return bVert;
+}
+// <--
+
+void SwFEShell::MoveObjectIfActive( svt::EmbeddedObjectRef&, const Point& )
+{
+ // does not do anything, only avoids crash if the method is used for wrong shell
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/frmedt/tblsel.cxx b/sw/source/core/frmedt/tblsel.cxx
new file mode 100644
index 000000000000..7de8f0727ee1
--- /dev/null
+++ b/sw/source/core/frmedt/tblsel.cxx
@@ -0,0 +1,2703 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+#include <editeng/boxitem.hxx>
+#include <editeng/protitem.hxx>
+
+#include <hintids.hxx>
+#include <fmtanchr.hxx>
+#include <fmtfsize.hxx>
+#include <frmatr.hxx>
+#include <tblsel.hxx>
+#include <crsrsh.hxx>
+#include <doc.hxx>
+#include <IDocumentUndoRedo.hxx>
+#include <docary.hxx>
+#include <pam.hxx>
+#include <ndtxt.hxx>
+#include <ndole.hxx>
+#include <swtable.hxx>
+#include <cntfrm.hxx>
+#include <tabfrm.hxx>
+#include <rowfrm.hxx>
+#include <cellfrm.hxx>
+#include <pagefrm.hxx>
+#include <rootfrm.hxx>
+#include <viscrs.hxx>
+#include <swtblfmt.hxx>
+#include <UndoTable.hxx>
+#include <mvsave.hxx>
+#include <sectfrm.hxx>
+#include <frmtool.hxx>
+#include <switerator.hxx>
+#include <deque>
+
+//siehe auch swtable.cxx
+#define COLFUZZY 20L
+
+// defines, die bestimmen, wie Tabellen Boxen gemergt werden:
+// - 1. alle leeren Zeilen entfernen, alle Boxen werden mit Blank,
+// alle Lines mit ParaBreak getrennt
+// - 2. alle leeren Zeilen und alle leeren Boxen am Anfang und Ende
+// entfernen, alle Boxen werden mit Blank,
+// alle Lines mit ParaBreak getrennt
+// - 3. alle leeren Boxen entfernen, alle Boxen werden mit Blank,
+// alle Lines mit ParaBreak getrennt
+
+#undef DEL_ONLY_EMPTY_LINES
+#undef DEL_EMPTY_BOXES_AT_START_AND_END
+#define DEL_ALL_EMPTY_BOXES
+
+
+_SV_IMPL_SORTAR_ALG( SwSelBoxes, SwTableBoxPtr )
+sal_Bool SwSelBoxes::Seek_Entry( const SwTableBoxPtr rSrch, sal_uInt16* pFndPos ) const
+{
+ sal_uLong nIdx = rSrch->GetSttIdx();
+
+ sal_uInt16 nO = Count(), nM, nU = 0;
+ if( nO > 0 )
+ {
+ nO--;
+ while( nU <= nO )
+ {
+ nM = nU + ( nO - nU ) / 2;
+ if( (*this)[ nM ]->GetSttNd() == rSrch->GetSttNd() )
+ {
+ if( pFndPos )
+ *pFndPos = nM;
+ return sal_True;
+ }
+ else if( (*this)[ nM ]->GetSttIdx() < nIdx )
+ nU = nM + 1;
+ else if( nM == 0 )
+ {
+ if( pFndPos )
+ *pFndPos = nU;
+ return sal_False;
+ }
+ else
+ nO = nM - 1;
+ }
+ }
+ if( pFndPos )
+ *pFndPos = nU;
+ return sal_False;
+}
+
+
+SV_IMPL_PTRARR( SwCellFrms, SwCellFrm* )
+
+struct _CmpLPt
+{
+ Point aPos;
+ const SwTableBox* pSelBox;
+ sal_Bool bVert;
+
+ _CmpLPt( const Point& rPt, const SwTableBox* pBox, sal_Bool bVertical );
+
+ sal_Bool operator==( const _CmpLPt& rCmp ) const
+ { return X() == rCmp.X() && Y() == rCmp.Y() ? sal_True : sal_False; }
+
+ sal_Bool operator<( const _CmpLPt& rCmp ) const
+ {
+ if ( bVert )
+ return X() > rCmp.X() || ( X() == rCmp.X() && Y() < rCmp.Y() )
+ ? sal_True : sal_False;
+ else
+ return Y() < rCmp.Y() || ( Y() == rCmp.Y() && X() < rCmp.X() )
+ ? sal_True : sal_False;
+ }
+
+ long X() const { return aPos.X(); }
+ long Y() const { return aPos.Y(); }
+};
+
+
+SV_DECL_VARARR_SORT( _MergePos, _CmpLPt, 0, 40 )
+SV_IMPL_VARARR_SORT( _MergePos, _CmpLPt )
+
+SV_IMPL_PTRARR( _FndBoxes, _FndBox* )
+SV_IMPL_PTRARR( _FndLines, _FndLine* )
+
+
+struct _Sort_CellFrm
+{
+ const SwCellFrm* pFrm;
+
+ _Sort_CellFrm( const SwCellFrm& rCFrm )
+ : pFrm( &rCFrm ) {}
+};
+
+typedef std::deque< _Sort_CellFrm > _Sort_CellFrms;
+
+SV_IMPL_PTRARR( SwChartBoxes, SwTableBoxPtr );
+SV_IMPL_PTRARR( SwChartLines, SwChartBoxes* );
+
+const SwLayoutFrm *lcl_FindCellFrm( const SwLayoutFrm *pLay )
+{
+ while ( pLay && !pLay->IsCellFrm() )
+ pLay = pLay->GetUpper();
+ return pLay;
+}
+
+const SwLayoutFrm *lcl_FindNextCellFrm( const SwLayoutFrm *pLay )
+{
+ //Dafuer sorgen, dass die Zelle auch verlassen wird (Bereiche)
+ const SwLayoutFrm *pTmp = pLay;
+ do {
+ pTmp = pTmp->GetNextLayoutLeaf();
+ } while( pLay->IsAnLower( pTmp ) );
+
+ while( pTmp && !pTmp->IsCellFrm() )
+ pTmp = pTmp->GetUpper();
+ return pTmp;
+}
+
+void GetTblSelCrs( const SwCrsrShell &rShell, SwSelBoxes& rBoxes )
+{
+ if( rBoxes.Count() )
+ rBoxes.Remove( sal_uInt16(0), rBoxes.Count() );
+ if( rShell.IsTableMode() && ((SwCrsrShell&)rShell).UpdateTblSelBoxes())
+ rBoxes.Insert( &rShell.GetTableCrsr()->GetBoxes() );
+}
+
+void GetTblSelCrs( const SwTableCursor& rTblCrsr, SwSelBoxes& rBoxes )
+{
+ if( rBoxes.Count() )
+ rBoxes.Remove( sal_uInt16(0), rBoxes.Count() );
+
+ if( rTblCrsr.IsChgd() || !rTblCrsr.GetBoxesCount() )
+ {
+ SwTableCursor* pTCrsr = (SwTableCursor*)&rTblCrsr;
+ pTCrsr->GetDoc()->GetCurrentLayout()->MakeTblCrsrs( *pTCrsr ); //swmod 080218
+ }
+
+ if( rTblCrsr.GetBoxesCount() )
+ rBoxes.Insert( &rTblCrsr.GetBoxes() );
+}
+
+void GetTblSel( const SwCrsrShell& rShell, SwSelBoxes& rBoxes,
+ const SwTblSearchType eSearchType )
+{
+ //Start- und Endzelle besorgen und den naechsten fragen.
+ if ( !rShell.IsTableMode() )
+ rShell.GetCrsr();
+
+ GetTblSel( *rShell.getShellCrsr(false), rBoxes, eSearchType );
+}
+
+void GetTblSel( const SwCursor& rCrsr, SwSelBoxes& rBoxes,
+ const SwTblSearchType eSearchType )
+{
+ //Start- und Endzelle besorgen und den naechsten fragen.
+ OSL_ENSURE( rCrsr.GetCntntNode() && rCrsr.GetCntntNode( sal_False ),
+ "Tabselection nicht auf Cnt." );
+
+ // Zeilen-Selektion:
+ // teste ob Tabelle komplex ist. Wenn ja, dann immer uebers Layout
+ // die selektierten Boxen zusammen suchen. Andernfalls ueber die
+ // Tabellen-Struktur (fuer Makros !!)
+ const SwCntntNode* pContentNd = rCrsr.GetNode()->GetCntntNode();
+ const SwTableNode* pTblNd = pContentNd ? pContentNd->FindTableNode() : 0;
+ if( pTblNd && pTblNd->GetTable().IsNewModel() )
+ {
+ SwTable::SearchType eSearch;
+ switch( nsSwTblSearchType::TBLSEARCH_COL & eSearchType )
+ {
+ case nsSwTblSearchType::TBLSEARCH_ROW: eSearch = SwTable::SEARCH_ROW; break;
+ case nsSwTblSearchType::TBLSEARCH_COL: eSearch = SwTable::SEARCH_COL; break;
+ default: eSearch = SwTable::SEARCH_NONE; break;
+ }
+ const bool bChkP = 0 != ( nsSwTblSearchType::TBLSEARCH_PROTECT & eSearchType );
+ pTblNd->GetTable().CreateSelection( rCrsr, rBoxes, eSearch, bChkP );
+ return;
+ }
+ if( nsSwTblSearchType::TBLSEARCH_ROW == ((~nsSwTblSearchType::TBLSEARCH_PROTECT ) & eSearchType ) &&
+ pTblNd && !pTblNd->GetTable().IsTblComplex() )
+ {
+ const SwTable& rTbl = pTblNd->GetTable();
+ const SwTableLines& rLines = rTbl.GetTabLines();
+
+ const SwNode* pMarkNode = rCrsr.GetNode( sal_False );
+ const sal_uLong nMarkSectionStart = pMarkNode->StartOfSectionIndex();
+ const SwTableBox* pMarkBox = rTbl.GetTblBox( nMarkSectionStart );
+
+ OSL_ENSURE( pMarkBox, "Point in table, mark outside?" );
+
+ const SwTableLine* pLine = pMarkBox ? pMarkBox->GetUpper() : 0;
+ sal_uInt16 nSttPos = rLines.GetPos( pLine );
+ OSL_ENSURE( USHRT_MAX != nSttPos, "Wo ist meine Zeile in der Tabelle?" );
+ pLine = rTbl.GetTblBox( rCrsr.GetNode( sal_True )->StartOfSectionIndex() )->GetUpper();
+ sal_uInt16 nEndPos = rLines.GetPos( pLine );
+ OSL_ENSURE( USHRT_MAX != nEndPos, "Wo ist meine Zeile in der Tabelle?" );
+ // pb: #i20193# if tableintable then nSttPos == nEndPos == USHRT_MAX
+ if ( nSttPos != USHRT_MAX && nEndPos != USHRT_MAX )
+ {
+ if( nEndPos < nSttPos ) // vertauschen
+ {
+ sal_uInt16 nTmp = nSttPos; nSttPos = nEndPos; nEndPos = nTmp;
+ }
+
+ int bChkProtected = nsSwTblSearchType::TBLSEARCH_PROTECT & eSearchType;
+ for( ; nSttPos <= nEndPos; ++nSttPos )
+ {
+ pLine = rLines[ nSttPos ];
+ for( sal_uInt16 n = pLine->GetTabBoxes().Count(); n ; )
+ {
+ SwTableBox* pBox = pLine->GetTabBoxes()[ --n ];
+ // Zellenschutzt beachten ??
+ if( !bChkProtected ||
+ !pBox->GetFrmFmt()->GetProtect().IsCntntProtected() )
+ rBoxes.Insert( pBox );
+ }
+ }
+ }
+ }
+ else
+ {
+ Point aPtPos, aMkPos;
+ const SwShellCrsr* pShCrsr = dynamic_cast<const SwShellCrsr*>(&rCrsr);
+ if( pShCrsr )
+ {
+ aPtPos = pShCrsr->GetPtPos();
+ aMkPos = pShCrsr->GetMkPos();
+ }
+ const SwCntntNode *pCntNd = rCrsr.GetCntntNode();
+ const SwLayoutFrm *pStart = pCntNd ?
+ pCntNd->getLayoutFrm( pCntNd->GetDoc()->GetCurrentLayout(), &aPtPos )->GetUpper() : 0;
+ pCntNd = rCrsr.GetCntntNode(sal_False);
+ const SwLayoutFrm *pEnd = pCntNd ?
+ pCntNd->getLayoutFrm( pCntNd->GetDoc()->GetCurrentLayout(), &aMkPos )->GetUpper() : 0;
+ if( pStart && pEnd )
+ GetTblSel( pStart, pEnd, rBoxes, 0, eSearchType );
+ }
+}
+
+void GetTblSel( const SwLayoutFrm* pStart, const SwLayoutFrm* pEnd,
+ SwSelBoxes& rBoxes, SwCellFrms* pCells,
+ const SwTblSearchType eSearchType )
+{
+ const SwTabFrm* pStartTab = pStart->FindTabFrm();
+ if ( !pStartTab )
+ {
+ OSL_FAIL( "GetTblSel without start table" );
+ return;
+ }
+
+ int bChkProtected = nsSwTblSearchType::TBLSEARCH_PROTECT & eSearchType;
+
+ sal_Bool bTblIsValid;
+ // #i55421# Reduced value 10
+ int nLoopMax = 10;
+ sal_uInt16 i;
+
+ do {
+ bTblIsValid = sal_True;
+
+ //Zuerst lassen wir uns die Tabellen und die Rechtecke heraussuchen.
+ SwSelUnions aUnions;
+ ::MakeSelUnions( aUnions, pStart, pEnd, eSearchType );
+
+ Point aCurrentTopLeft( LONG_MAX, LONG_MAX );
+ Point aCurrentTopRight( 0, LONG_MAX );
+ Point aCurrentBottomLeft( LONG_MAX, 0 );
+ Point aCurrentBottomRight( 0, 0 );
+ const SwCellFrm* pCurrentTopLeftFrm = 0;
+ const SwCellFrm* pCurrentTopRightFrm = 0;
+ const SwCellFrm* pCurrentBottomLeftFrm = 0;
+ const SwCellFrm* pCurrentBottomRightFrm = 0;
+
+ //Jetzt zu jedem Eintrag die Boxen herausfischen und uebertragen.
+ for( i = 0; i < aUnions.Count() && bTblIsValid; ++i )
+ {
+ SwSelUnion *pUnion = aUnions[i];
+ const SwTabFrm *pTable = pUnion->GetTable();
+ if( !pTable->IsValid() && nLoopMax )
+ {
+ bTblIsValid = sal_False;
+ break;
+ }
+
+ // Skip any repeated headlines in the follow:
+ const SwLayoutFrm* pRow = pTable->IsFollow() ?
+ pTable->GetFirstNonHeadlineRow() :
+ (const SwLayoutFrm*)pTable->Lower();
+
+ while( pRow && bTblIsValid )
+ {
+ if( !pRow->IsValid() && nLoopMax )
+ {
+ bTblIsValid = sal_False;
+ break;
+ }
+
+ if ( pRow->Frm().IsOver( pUnion->GetUnion() ) )
+ {
+ const SwLayoutFrm *pCell = pRow->FirstCell();
+
+ while( bTblIsValid && pCell && pRow->IsAnLower( pCell ) )
+ {
+ if( !pCell->IsValid() && nLoopMax )
+ {
+ bTblIsValid = sal_False;
+ break;
+ }
+
+ OSL_ENSURE( pCell->IsCellFrm(), "Frame ohne Celle" );
+ if( ::IsFrmInTblSel( pUnion->GetUnion(), pCell ) )
+ {
+ SwTableBox* pBox = (SwTableBox*)
+ ((SwCellFrm*)pCell)->GetTabBox();
+ // Zellenschutzt beachten ??
+ if( !bChkProtected ||
+ !pBox->GetFrmFmt()->GetProtect().IsCntntProtected() )
+ rBoxes.Insert( pBox );
+
+ if ( pCells )
+ {
+ const Point aTopLeft( pCell->Frm().TopLeft() );
+ const Point aTopRight( pCell->Frm().TopRight() );
+ const Point aBottomLeft( pCell->Frm().BottomLeft() );
+ const Point aBottomRight( pCell->Frm().BottomRight() );
+
+ if ( aTopLeft.Y() < aCurrentTopLeft.Y() ||
+ ( aTopLeft.Y() == aCurrentTopLeft.Y() &&
+ aTopLeft.X() < aCurrentTopLeft.X() ) )
+ {
+ aCurrentTopLeft = aTopLeft;
+ pCurrentTopLeftFrm = static_cast<const SwCellFrm*>( pCell );
+ }
+
+ if ( aTopRight.Y() < aCurrentTopRight.Y() ||
+ ( aTopRight.Y() == aCurrentTopRight.Y() &&
+ aTopRight.X() > aCurrentTopRight.X() ) )
+ {
+ aCurrentTopRight = aTopRight;
+ pCurrentTopRightFrm = static_cast<const SwCellFrm*>( pCell );
+ }
+
+ if ( aBottomLeft.Y() > aCurrentBottomLeft.Y() ||
+ ( aBottomLeft.Y() == aCurrentBottomLeft.Y() &&
+ aBottomLeft.X() < aCurrentBottomLeft.X() ) )
+ {
+ aCurrentBottomLeft = aBottomLeft;
+ pCurrentBottomLeftFrm = static_cast<const SwCellFrm*>( pCell );
+ }
+
+ if ( aBottomRight.Y() > aCurrentBottomRight.Y() ||
+ ( aBottomRight.Y() == aCurrentBottomRight.Y() &&
+ aBottomRight.X() > aCurrentBottomRight.X() ) )
+ {
+ aCurrentBottomRight = aBottomRight;
+ pCurrentBottomRightFrm = static_cast<const SwCellFrm*>( pCell );
+ }
+
+ }
+ }
+ if ( pCell->GetNext() )
+ {
+ pCell = (const SwLayoutFrm*)pCell->GetNext();
+ if ( pCell->Lower() && pCell->Lower()->IsRowFrm() )
+ pCell = pCell->FirstCell();
+ }
+ else
+ pCell = ::lcl_FindNextCellFrm( pCell );
+ }
+ }
+ pRow = (const SwLayoutFrm*)pRow->GetNext();
+ }
+ }
+
+ if ( pCells )
+ {
+ pCells->Remove( 0, pCells->Count() );
+ pCells->Insert( pCurrentTopLeftFrm, 0 );
+ pCells->Insert( pCurrentTopRightFrm, 1 );
+ pCells->Insert( pCurrentBottomLeftFrm, 2 );
+ pCells->Insert( pCurrentBottomRightFrm, 3 );
+ }
+
+ if( bTblIsValid )
+ break;
+
+ SwDeletionChecker aDelCheck( pStart );
+
+ // ansonsten das Layout der Tabelle kurz "kalkulieren" lassen
+ // und nochmals neu aufsetzen
+ SwTabFrm *pTable = aUnions[0]->GetTable();
+ while( pTable )
+ {
+ if( pTable->IsValid() )
+ pTable->InvalidatePos();
+ pTable->SetONECalcLowers();
+ pTable->Calc();
+ pTable->SetCompletePaint();
+ if( 0 == (pTable = pTable->GetFollow()) )
+ break;
+ }
+
+ // --> Make code robust, check if pStart has
+ // been deleted due to the formatting of the table:
+ if ( aDelCheck.HasBeenDeleted() )
+ {
+ OSL_FAIL( "Current box has been deleted during GetTblSel()" );
+ break;
+ }
+ // <--
+
+ i = 0;
+ rBoxes.Remove( i, rBoxes.Count() );
+ --nLoopMax;
+
+ } while( sal_True );
+ OSL_ENSURE( nLoopMax, "das Layout der Tabelle wurde nicht valide!" );
+}
+
+
+
+sal_Bool ChkChartSel( const SwNode& rSttNd, const SwNode& rEndNd,
+ SwChartLines* pGetCLines )
+{
+ const SwTableNode* pTNd = rSttNd.FindTableNode();
+ if( !pTNd )
+ return sal_False;
+
+ Point aNullPos;
+ SwNodeIndex aIdx( rSttNd );
+ const SwCntntNode* pCNd = aIdx.GetNode().GetCntntNode();
+ if( !pCNd )
+ pCNd = aIdx.GetNodes().GoNextSection( &aIdx, sal_False, sal_False );
+
+ // if table is invisible, return
+ // (layout needed for forming table selection further down, so we can't
+ // continue with invisible tables)
+ // #i22135# - Also the content of the table could be
+ // invisible - e.g. in a hidden section
+ // Robust: check, if content was found (e.g. empty table cells)
+ if ( !pCNd || pCNd->getLayoutFrm( pCNd->GetDoc()->GetCurrentLayout() ) == NULL )
+ return sal_False;
+
+ const SwLayoutFrm *pStart = pCNd ? pCNd->getLayoutFrm( pCNd->GetDoc()->GetCurrentLayout(), &aNullPos )->GetUpper() : 0;
+ OSL_ENSURE( pStart, "ohne Frame geht gar nichts" );
+
+ aIdx = rEndNd;
+ pCNd = aIdx.GetNode().GetCntntNode();
+ if( !pCNd )
+ pCNd = aIdx.GetNodes().GoNextSection( &aIdx, sal_False, sal_False );
+
+ // #i22135# - Robust: check, if content was found and if it's visible
+ if ( !pCNd || pCNd->getLayoutFrm( pCNd->GetDoc()->GetCurrentLayout() ) == NULL )
+ {
+ return sal_False;
+ }
+
+ const SwLayoutFrm *pEnd = pCNd ? pCNd->getLayoutFrm( pCNd->GetDoc()->GetCurrentLayout(), &aNullPos )->GetUpper() : 0;
+ OSL_ENSURE( pEnd, "ohne Frame geht gar nichts" );
+
+
+ sal_Bool bTblIsValid, bValidChartSel;
+ // --> FME 2006-01-25 #i55421# Reduced value 10
+ int nLoopMax = 10; //JP 28.06.99: max 100 loops - Bug 67292
+ // <--
+ sal_uInt16 i = 0;
+
+ do {
+ bTblIsValid = sal_True;
+ bValidChartSel = sal_True;
+
+ sal_uInt16 nRowCells = USHRT_MAX;
+
+ //Zuerst lassen wir uns die Tabellen und die Rechtecke heraussuchen.
+ SwSelUnions aUnions;
+ ::MakeSelUnions( aUnions, pStart, pEnd, nsSwTblSearchType::TBLSEARCH_NO_UNION_CORRECT );
+
+ //Jetzt zu jedem Eintrag die Boxen herausfischen und uebertragen.
+ for( i = 0; i < aUnions.Count() && bTblIsValid &&
+ bValidChartSel; ++i )
+ {
+ SwSelUnion *pUnion = aUnions[i];
+ const SwTabFrm *pTable = pUnion->GetTable();
+
+ SWRECTFN( pTable )
+ sal_Bool bRTL = pTable->IsRightToLeft();
+
+ if( !pTable->IsValid() && nLoopMax )
+ {
+ bTblIsValid = sal_False;
+ break;
+ }
+
+ _Sort_CellFrms aCellFrms;
+
+ // Skip any repeated headlines in the follow:
+ const SwLayoutFrm* pRow = pTable->IsFollow() ?
+ pTable->GetFirstNonHeadlineRow() :
+ (const SwLayoutFrm*)pTable->Lower();
+
+ while( pRow && bTblIsValid && bValidChartSel )
+ {
+ if( !pRow->IsValid() && nLoopMax )
+ {
+ bTblIsValid = sal_False;
+ break;
+ }
+
+ if( pRow->Frm().IsOver( pUnion->GetUnion() ) )
+ {
+ const SwLayoutFrm *pCell = pRow->FirstCell();
+
+ while( bValidChartSel && bTblIsValid && pCell &&
+ pRow->IsAnLower( pCell ) )
+ {
+ if( !pCell->IsValid() && nLoopMax )
+ {
+ bTblIsValid = sal_False;
+ break;
+ }
+
+ OSL_ENSURE( pCell->IsCellFrm(), "Frame ohne Celle" );
+ const SwRect& rUnion = pUnion->GetUnion(),
+ & rFrmRect = pCell->Frm();
+
+ const long nUnionRight = rUnion.Right();
+ const long nUnionBottom = rUnion.Bottom();
+ const long nFrmRight = rFrmRect.Right();
+ const long nFrmBottom = rFrmRect.Bottom();
+
+ // liegt das FrmRect ausserhalb der Union, kann es
+ // ignoriert werden.
+
+ const long nXFuzzy = bVert ? 0 : 20;
+ const long nYFuzzy = bVert ? 20 : 0;
+
+ if( !( rUnion.Top() + nYFuzzy > nFrmBottom ||
+ nUnionBottom < rFrmRect.Top() + nYFuzzy ||
+ rUnion.Left() + nXFuzzy > nFrmRight ||
+ nUnionRight < rFrmRect.Left() + nXFuzzy ))
+ {
+ // ok, rUnion is _not_ completely outside of rFrmRect
+
+ // wenn es aber nicht komplett in der Union liegt,
+ // dann ist es fuers Chart eine ungueltige
+ // Selektion.
+ if( rUnion.Left() <= rFrmRect.Left() + nXFuzzy &&
+ rFrmRect.Left() <= nUnionRight &&
+ rUnion.Left() <= nFrmRight &&
+ nFrmRight <= nUnionRight + nXFuzzy &&
+ rUnion.Top() <= rFrmRect.Top() + nYFuzzy &&
+ rFrmRect.Top() <= nUnionBottom &&
+ rUnion.Top() <= nFrmBottom &&
+ nFrmBottom <= nUnionBottom+ nYFuzzy )
+
+ aCellFrms.push_back(
+ _Sort_CellFrm( *(SwCellFrm*)pCell) );
+ else
+ {
+ bValidChartSel = sal_False;
+ break;
+ }
+ }
+ if ( pCell->GetNext() )
+ {
+ pCell = (const SwLayoutFrm*)pCell->GetNext();
+ if ( pCell->Lower() && pCell->Lower()->IsRowFrm() )
+ pCell = pCell->FirstCell();
+ }
+ else
+ pCell = ::lcl_FindNextCellFrm( pCell );
+ }
+ }
+ pRow = (const SwLayoutFrm*)pRow->GetNext();
+ }
+
+ if( !bValidChartSel )
+ break;
+
+ // alle Zellen der (Teil-)Tabelle zusammen. Dann teste mal ob
+ // all huebsch nebeneinander liegen.
+ size_t n, nCellCnt = 0;
+ long nYPos = LONG_MAX;
+ long nXPos = 0;
+ long nHeight = 0;
+
+ for( n = 0 ; n < aCellFrms.size(); ++n )
+ {
+ const _Sort_CellFrm& rCF = aCellFrms[ n ];
+ if( (rCF.pFrm->Frm().*fnRect->fnGetTop)() != nYPos )
+ {
+ // neue Zeile
+ if( n )
+ {
+ if( USHRT_MAX == nRowCells ) // 1. Zeilenwechsel
+ nRowCells = nCellCnt;
+ else if( nRowCells != nCellCnt )
+ {
+ bValidChartSel = sal_False;
+ break;
+ }
+ }
+ nCellCnt = 1;
+ nYPos = (rCF.pFrm->Frm().*fnRect->fnGetTop)();
+ nHeight = (rCF.pFrm->Frm().*fnRect->fnGetHeight)();
+
+ nXPos = bRTL ?
+ (rCF.pFrm->Frm().*fnRect->fnGetLeft)() :
+ (rCF.pFrm->Frm().*fnRect->fnGetRight)();
+ }
+ else if( nXPos == ( bRTL ?
+ (rCF.pFrm->Frm().*fnRect->fnGetRight)() :
+ (rCF.pFrm->Frm().*fnRect->fnGetLeft)() ) &&
+ nHeight == (rCF.pFrm->Frm().*fnRect->fnGetHeight)() )
+ {
+ nXPos += ( bRTL ? (-1) : 1 ) *
+ (rCF.pFrm->Frm().*fnRect->fnGetWidth)();
+ ++nCellCnt;
+ }
+ else
+ {
+ bValidChartSel = sal_False;
+ break;
+ }
+ }
+ if( bValidChartSel )
+ {
+ if( USHRT_MAX == nRowCells )
+ nRowCells = nCellCnt;
+ else if( nRowCells != nCellCnt )
+ bValidChartSel = sal_False;
+ }
+
+ if( bValidChartSel && pGetCLines )
+ {
+ nYPos = LONG_MAX;
+ SwChartBoxes* pBoxes = 0;
+ for( n = 0; n < aCellFrms.size(); ++n )
+ {
+ const _Sort_CellFrm& rCF = aCellFrms[ n ];
+ if( (rCF.pFrm->Frm().*fnRect->fnGetTop)() != nYPos )
+ {
+ pBoxes = new SwChartBoxes( 255 < nRowCells
+ ? 255 : (sal_uInt8)nRowCells);
+ pGetCLines->C40_INSERT( SwChartBoxes, pBoxes, pGetCLines->Count() );
+ nYPos = (rCF.pFrm->Frm().*fnRect->fnGetTop)();
+ }
+ SwTableBoxPtr pBox = (SwTableBox*)rCF.pFrm->GetTabBox();
+ pBoxes->Insert( pBox, pBoxes->Count() );
+ }
+ }
+ }
+
+ if( bTblIsValid )
+ break;
+
+ // ansonsten das Layout der Tabelle kurz "kalkulieren" lassen
+ // und nochmals neu aufsetzen
+ SwTabFrm *pTable = aUnions[0]->GetTable();
+ for( i = 0; i < aUnions.Count(); ++i )
+ {
+ if( pTable->IsValid() )
+ pTable->InvalidatePos();
+ pTable->SetONECalcLowers();
+ pTable->Calc();
+ pTable->SetCompletePaint();
+ if( 0 == (pTable = pTable->GetFollow()) )
+ break;
+ }
+ --nLoopMax;
+ if( pGetCLines )
+ pGetCLines->DeleteAndDestroy( 0, pGetCLines->Count() );
+ } while( sal_True );
+
+ OSL_ENSURE( nLoopMax, "das Layout der Tabelle wurde nicht valide!" );
+
+ if( !bValidChartSel && pGetCLines )
+ pGetCLines->DeleteAndDestroy( 0, pGetCLines->Count() );
+
+ return bValidChartSel;
+}
+
+
+sal_Bool IsFrmInTblSel( const SwRect& rUnion, const SwFrm* pCell )
+{
+ OSL_ENSURE( pCell->IsCellFrm(), "Frame ohne Gazelle" );
+
+ if( pCell->FindTabFrm()->IsVertical() )
+ return ( rUnion.Right() >= pCell->Frm().Right() &&
+ rUnion.Left() <= pCell->Frm().Left() &&
+ (( rUnion.Top() <= pCell->Frm().Top()+20 &&
+ rUnion.Bottom() > pCell->Frm().Top() ) ||
+ ( rUnion.Top() >= pCell->Frm().Top() &&
+ rUnion.Bottom() < pCell->Frm().Bottom() )) ? sal_True : sal_False );
+
+ return (
+ rUnion.Top() <= pCell->Frm().Top() &&
+ rUnion.Bottom() >= pCell->Frm().Bottom() &&
+
+ (( rUnion.Left() <= pCell->Frm().Left()+20 &&
+ rUnion.Right() > pCell->Frm().Left() ) ||
+
+ ( rUnion.Left() >= pCell->Frm().Left() &&
+ rUnion.Right() < pCell->Frm().Right() )) ? sal_True : sal_False );
+}
+
+sal_Bool GetAutoSumSel( const SwCrsrShell& rShell, SwCellFrms& rBoxes )
+{
+ SwShellCrsr* pCrsr = rShell.pCurCrsr;
+ if ( rShell.IsTableMode() )
+ pCrsr = rShell.pTblCrsr;
+
+ const SwLayoutFrm *pStart = pCrsr->GetCntntNode()->getLayoutFrm( rShell.GetLayout(),
+ &pCrsr->GetPtPos() )->GetUpper(),
+ *pEnd = pCrsr->GetCntntNode(sal_False)->getLayoutFrm( rShell.GetLayout(),
+ &pCrsr->GetMkPos() )->GetUpper();
+
+ const SwLayoutFrm* pSttCell = pStart;
+ while( pSttCell && !pSttCell->IsCellFrm() )
+ pSttCell = pSttCell->GetUpper();
+
+ //Zuerst lassen wir uns die Tabellen und die Rechtecke heraussuchen.
+ SwSelUnions aUnions;
+
+ // default erstmal nach oben testen, dann nach links
+ ::MakeSelUnions( aUnions, pStart, pEnd, nsSwTblSearchType::TBLSEARCH_COL );
+
+ sal_Bool bTstRow = sal_True, bFound = sal_False;
+ sal_uInt16 i;
+
+ // 1. teste ob die darueber liegende Box Value/Formel enhaelt:
+ for( i = 0; i < aUnions.Count(); ++i )
+ {
+ SwSelUnion *pUnion = aUnions[i];
+ const SwTabFrm *pTable = pUnion->GetTable();
+
+ // Skip any repeated headlines in the follow:
+ const SwLayoutFrm* pRow = pTable->IsFollow() ?
+ pTable->GetFirstNonHeadlineRow() :
+ (const SwLayoutFrm*)pTable->Lower();
+
+ while( pRow )
+ {
+ if( pRow->Frm().IsOver( pUnion->GetUnion() ) )
+ {
+ const SwCellFrm* pUpperCell = 0;
+ const SwLayoutFrm *pCell = pRow->FirstCell();
+
+ while( pCell && pRow->IsAnLower( pCell ) )
+ {
+ if( pCell == pSttCell )
+ {
+ sal_uInt16 nWhichId = 0;
+ for( sal_uInt16 n = rBoxes.Count(); n; )
+ if( USHRT_MAX != ( nWhichId = rBoxes[ --n ]
+ ->GetTabBox()->IsFormulaOrValueBox() ))
+ break;
+
+ // alle Boxen zusammen, nicht mehr die Zeile
+ // pruefen, wenn eine Formel oder Value gefunden wurde
+ bTstRow = 0 == nWhichId || USHRT_MAX == nWhichId;
+ bFound = sal_True;
+ break;
+ }
+
+ OSL_ENSURE( pCell->IsCellFrm(), "Frame ohne Celle" );
+ if( ::IsFrmInTblSel( pUnion->GetUnion(), pCell ) )
+ pUpperCell = (SwCellFrm*)pCell;
+
+ if( pCell->GetNext() )
+ {
+ pCell = (const SwLayoutFrm*)pCell->GetNext();
+ if ( pCell->Lower() && pCell->Lower()->IsRowFrm() )
+ pCell = pCell->FirstCell();
+ }
+ else
+ pCell = ::lcl_FindNextCellFrm( pCell );
+ }
+
+ if( pUpperCell )
+ rBoxes.Insert( pUpperCell, rBoxes.Count() );
+ }
+ if( bFound )
+ {
+ i = aUnions.Count();
+ break;
+ }
+ pRow = (const SwLayoutFrm*)pRow->GetNext();
+ }
+ }
+
+
+ // 2. teste ob die links liegende Box Value/Formel enhaelt:
+ if( bTstRow )
+ {
+ bFound = sal_False;
+
+ rBoxes.Remove( 0, rBoxes.Count() );
+ aUnions.DeleteAndDestroy( 0, aUnions.Count() );
+ ::MakeSelUnions( aUnions, pStart, pEnd, nsSwTblSearchType::TBLSEARCH_ROW );
+
+ for( i = 0; i < aUnions.Count(); ++i )
+ {
+ SwSelUnion *pUnion = aUnions[i];
+ const SwTabFrm *pTable = pUnion->GetTable();
+
+ // Skip any repeated headlines in the follow:
+ const SwLayoutFrm* pRow = pTable->IsFollow() ?
+ pTable->GetFirstNonHeadlineRow() :
+ (const SwLayoutFrm*)pTable->Lower();
+
+ while( pRow )
+ {
+ if( pRow->Frm().IsOver( pUnion->GetUnion() ) )
+ {
+ const SwLayoutFrm *pCell = pRow->FirstCell();
+
+ while( pCell && pRow->IsAnLower( pCell ) )
+ {
+ if( pCell == pSttCell )
+ {
+ sal_uInt16 nWhichId = 0;
+ for( sal_uInt16 n = rBoxes.Count(); n; )
+ if( USHRT_MAX != ( nWhichId = rBoxes[ --n ]
+ ->GetTabBox()->IsFormulaOrValueBox() ))
+ break;
+
+ // alle Boxen zusammen, nicht mehr die Zeile
+ // pruefen, wenn eine Formel oder Value gefunden wurde
+ bFound = 0 != nWhichId && USHRT_MAX != nWhichId;
+ bTstRow = sal_False;
+ break;
+ }
+
+ OSL_ENSURE( pCell->IsCellFrm(), "Frame ohne Celle" );
+ if( ::IsFrmInTblSel( pUnion->GetUnion(), pCell ) )
+ {
+ const SwCellFrm* pC = (SwCellFrm*)pCell;
+ rBoxes.Insert( pC, rBoxes.Count() );
+ }
+ if( pCell->GetNext() )
+ {
+ pCell = (const SwLayoutFrm*)pCell->GetNext();
+ if ( pCell->Lower() && pCell->Lower()->IsRowFrm() )
+ pCell = pCell->FirstCell();
+ }
+ else
+ pCell = ::lcl_FindNextCellFrm( pCell );
+ }
+ }
+ if( !bTstRow )
+ {
+ i = aUnions.Count();
+ break;
+ }
+
+ pRow = (const SwLayoutFrm*)pRow->GetNext();
+ }
+ }
+ }
+
+ return bFound;
+}
+
+sal_Bool HasProtectedCells( const SwSelBoxes& rBoxes )
+{
+ sal_Bool bRet = sal_False;
+ for( sal_uInt16 n = 0, nCnt = rBoxes.Count(); n < nCnt; ++n )
+ if( rBoxes[ n ]->GetFrmFmt()->GetProtect().IsCntntProtected() )
+ {
+ bRet = sal_True;
+ break;
+ }
+ return bRet;
+}
+
+
+_CmpLPt::_CmpLPt( const Point& rPt, const SwTableBox* pBox, sal_Bool bVertical )
+ : aPos( rPt ), pSelBox( pBox ), bVert( bVertical )
+{}
+
+void lcl_InsTblBox( SwTableNode* pTblNd, SwDoc* pDoc, SwTableBox* pBox,
+ sal_uInt16 nInsPos, sal_uInt16 nCnt = 1 )
+{
+ OSL_ENSURE( pBox->GetSttNd(), "Box ohne Start-Node" );
+ SwCntntNode* pCNd = pDoc->GetNodes()[ pBox->GetSttIdx() + 1 ]
+ ->GetCntntNode();
+ if( pCNd && pCNd->IsTxtNode() )
+ pDoc->GetNodes().InsBoxen( pTblNd, pBox->GetUpper(),
+ (SwTableBoxFmt*)pBox->GetFrmFmt(),
+ ((SwTxtNode*)pCNd)->GetTxtColl(),
+ pCNd->GetpSwAttrSet(),
+ nInsPos, nCnt );
+ else
+ pDoc->GetNodes().InsBoxen( pTblNd, pBox->GetUpper(),
+ (SwTableBoxFmt*)pBox->GetFrmFmt(),
+ (SwTxtFmtColl*)pDoc->GetDfltTxtFmtColl(), 0,
+ nInsPos, nCnt );
+}
+
+sal_Bool IsEmptyBox( const SwTableBox& rBox, SwPaM& rPam )
+{
+ rPam.GetPoint()->nNode = *rBox.GetSttNd()->EndOfSectionNode();
+ rPam.Move( fnMoveBackward, fnGoCntnt );
+ rPam.SetMark();
+ rPam.GetPoint()->nNode = *rBox.GetSttNd();
+ rPam.Move( fnMoveForward, fnGoCntnt );
+ sal_Bool bRet = *rPam.GetMark() == *rPam.GetPoint()
+ && ( rBox.GetSttNd()->GetIndex() + 1 == rPam.GetPoint()->nNode.GetIndex() );
+
+ if( bRet )
+ {
+ // dann teste mal auf absatzgebundenen Flys
+ const SwSpzFrmFmts& rFmts = *rPam.GetDoc()->GetSpzFrmFmts();
+ sal_uLong nSttIdx = rPam.GetPoint()->nNode.GetIndex(),
+ nEndIdx = rBox.GetSttNd()->EndOfSectionIndex(),
+ nIdx;
+
+ for( sal_uInt16 n = 0; n < rFmts.Count(); ++n )
+ {
+ const SwFmtAnchor& rAnchor = rFmts[n]->GetAnchor();
+ const SwPosition* pAPos = rAnchor.GetCntntAnchor();
+ if (pAPos &&
+ ((FLY_AT_PARA == rAnchor.GetAnchorId()) ||
+ (FLY_AT_CHAR == rAnchor.GetAnchorId())) &&
+ nSttIdx <= ( nIdx = pAPos->nNode.GetIndex() ) &&
+ nIdx < nEndIdx )
+ {
+ bRet = sal_False;
+ break;
+ }
+ }
+ }
+ return bRet;
+}
+
+
+void GetMergeSel( const SwPaM& rPam, SwSelBoxes& rBoxes,
+ SwTableBox** ppMergeBox, SwUndoTblMerge* pUndo )
+{
+ if( rBoxes.Count() )
+ rBoxes.Remove( sal_uInt16(0), rBoxes.Count() );
+
+ //Zuerst lassen wir uns die Tabellen und die Rechtecke heraussuchen.
+ OSL_ENSURE( rPam.GetCntntNode() && rPam.GetCntntNode( sal_False ),
+ "Tabselection nicht auf Cnt." );
+
+//JP 24.09.96: Merge mit wiederholenden TabellenHeadline funktioniert nicht
+// richtig. Warum nicht Point 0,0 benutzen? Dann ist garantiert,
+// das die 1. Headline mit drin ist.
+ Point aPt( 0, 0 );
+
+ const SwCntntNode* pCntNd = rPam.GetCntntNode();
+ const SwLayoutFrm *pStart = pCntNd->getLayoutFrm( pCntNd->GetDoc()->GetCurrentLayout(),
+ &aPt )->GetUpper();
+ pCntNd = rPam.GetCntntNode(sal_False);
+ const SwLayoutFrm *pEnd = pCntNd->getLayoutFrm( pCntNd->GetDoc()->GetCurrentLayout(),
+ &aPt )->GetUpper();
+
+ SwSelUnions aUnions;
+ ::MakeSelUnions( aUnions, pStart, pEnd );
+ if( !aUnions.Count() )
+ return;
+
+ const SwTable *pTable = aUnions[0]->GetTable()->GetTable();
+ SwDoc* pDoc = (SwDoc*)pStart->GetFmt()->GetDoc();
+ SwTableNode* pTblNd = (SwTableNode*)pTable->GetTabSortBoxes()[ 0 ]->
+ GetSttNd()->FindTableNode();
+
+ _MergePos aPosArr; // Sort-Array mit den Positionen der Frames
+ long nWidth;
+ SwTableBox* pLastBox = 0;
+
+ SWRECTFN( pStart->GetUpper() )
+
+ for ( sal_uInt16 i = 0; i < aUnions.Count(); ++i )
+ {
+ const SwTabFrm *pTabFrm = aUnions[i]->GetTable();
+
+ SwRect &rUnion = aUnions[i]->GetUnion();
+
+ // Skip any repeated headlines in the follow:
+ const SwLayoutFrm* pRow = pTabFrm->IsFollow() ?
+ pTabFrm->GetFirstNonHeadlineRow() :
+ (const SwLayoutFrm*)pTabFrm->Lower();
+
+ while ( pRow )
+ {
+ if ( pRow->Frm().IsOver( rUnion ) )
+ {
+ const SwLayoutFrm *pCell = pRow->FirstCell();
+
+ while ( pCell && pRow->IsAnLower( pCell ) )
+ {
+ OSL_ENSURE( pCell->IsCellFrm(), "Frame ohne Celle" );
+ // in der vollen Breite ueberlappend ?
+ if( rUnion.Top() <= pCell->Frm().Top() &&
+ rUnion.Bottom() >= pCell->Frm().Bottom() )
+ {
+ SwTableBox* pBox =(SwTableBox*)((SwCellFrm*)pCell)->GetTabBox();
+
+ // nur nach rechts ueberlappend
+ if( ( rUnion.Left() - COLFUZZY ) <= pCell->Frm().Left() &&
+ ( rUnion.Right() - COLFUZZY ) > pCell->Frm().Left() )
+ {
+ if( ( rUnion.Right() + COLFUZZY ) < pCell->Frm().Right() )
+ {
+ sal_uInt16 nInsPos = pBox->GetUpper()->
+ GetTabBoxes().C40_GETPOS( SwTableBox, pBox )+1;
+ lcl_InsTblBox( pTblNd, pDoc, pBox, nInsPos );
+ pBox->ClaimFrmFmt();
+ SwFmtFrmSize aNew(
+ pBox->GetFrmFmt()->GetFrmSize() );
+ nWidth = rUnion.Right() - pCell->Frm().Left();
+ nWidth = nWidth * aNew.GetWidth() /
+ pCell->Frm().Width();
+ long nTmpWidth = aNew.GetWidth() - nWidth;
+ aNew.SetWidth( nWidth );
+ pBox->GetFrmFmt()->SetFmtAttr( aNew );
+ // diese Box ist selektiert
+ pLastBox = pBox;
+ rBoxes.Insert( pBox );
+ aPosArr.Insert(
+ _CmpLPt( (pCell->Frm().*fnRect->fnGetPos)(),
+ pBox, bVert ) );
+
+ pBox = pBox->GetUpper()->GetTabBoxes()[ nInsPos ];
+ aNew.SetWidth( nTmpWidth );
+ pBox->ClaimFrmFmt();
+ pBox->GetFrmFmt()->SetFmtAttr( aNew );
+
+ if( pUndo )
+ pUndo->AddNewBox( pBox->GetSttIdx() );
+ }
+ else
+ {
+ // diese Box ist selektiert
+ pLastBox = pBox;
+ rBoxes.Insert( pBox );
+#if OSL_DEBUG_LEVEL > 1
+ Point aInsPoint( (pCell->Frm().*fnRect->fnGetPos)() );
+#endif
+ aPosArr.Insert(
+ _CmpLPt( (pCell->Frm().*fnRect->fnGetPos)(),
+ pBox, bVert ) );
+ }
+ }
+ // oder rechts und links ueberlappend
+ else if( ( rUnion.Left() - COLFUZZY ) >= pCell->Frm().Left() &&
+ ( rUnion.Right() + COLFUZZY ) < pCell->Frm().Right() )
+ {
+ sal_uInt16 nInsPos = pBox->GetUpper()->GetTabBoxes().
+ C40_GETPOS( SwTableBox, pBox )+1;
+ lcl_InsTblBox( pTblNd, pDoc, pBox, nInsPos, 2 );
+ pBox->ClaimFrmFmt();
+ SwFmtFrmSize aNew(
+ pBox->GetFrmFmt()->GetFrmSize() );
+ long nLeft = rUnion.Left() - pCell->Frm().Left();
+ nLeft = nLeft * aNew.GetWidth() /
+ pCell->Frm().Width();
+ long nRight = pCell->Frm().Right() - rUnion.Right();
+ nRight = nRight * aNew.GetWidth() /
+ pCell->Frm().Width();
+ nWidth = aNew.GetWidth() - nLeft - nRight;
+
+ aNew.SetWidth( nLeft );
+ pBox->GetFrmFmt()->SetFmtAttr( aNew );
+
+ {
+ const SfxPoolItem* pItem;
+ if( SFX_ITEM_SET == pBox->GetFrmFmt()->GetAttrSet()
+ .GetItemState( RES_BOX, sal_False, &pItem ))
+ {
+ SvxBoxItem aBox( *(SvxBoxItem*)pItem );
+ aBox.SetLine( 0, BOX_LINE_RIGHT );
+ pBox->GetFrmFmt()->SetFmtAttr( aBox );
+ }
+ }
+
+ pBox = pBox->GetUpper()->GetTabBoxes()[ nInsPos ];
+ aNew.SetWidth( nWidth );
+ pBox->ClaimFrmFmt();
+ pBox->GetFrmFmt()->SetFmtAttr( aNew );
+
+ if( pUndo )
+ pUndo->AddNewBox( pBox->GetSttIdx() );
+
+ // diese Box ist selektiert
+ pLastBox = pBox;
+ rBoxes.Insert( pBox );
+ aPosArr.Insert(
+ _CmpLPt( (pCell->Frm().*fnRect->fnGetPos)(),
+ pBox, bVert ) );
+
+ pBox = pBox->GetUpper()->GetTabBoxes()[ nInsPos+1 ];
+ aNew.SetWidth( nRight );
+ pBox->ClaimFrmFmt();
+ pBox->GetFrmFmt()->SetFmtAttr( aNew );
+
+ if( pUndo )
+ pUndo->AddNewBox( pBox->GetSttIdx() );
+ }
+ // oder reicht die rechte Kante der Box in den
+ // selektierten Bereich?
+ else if( ( pCell->Frm().Right() - COLFUZZY ) < rUnion.Right() &&
+ ( pCell->Frm().Right() - COLFUZZY ) > rUnion.Left() &&
+ ( pCell->Frm().Left() + COLFUZZY ) < rUnion.Left() )
+ {
+ // dann muss eine neue Box einfuegt und die
+ // Breiten angepasst werden
+ sal_uInt16 nInsPos = pBox->GetUpper()->GetTabBoxes().
+ C40_GETPOS( SwTableBox, pBox )+1;
+ lcl_InsTblBox( pTblNd, pDoc, pBox, nInsPos, 1 );
+
+ SwFmtFrmSize aNew(pBox->GetFrmFmt()->GetFrmSize() );
+ long nLeft = rUnion.Left() - pCell->Frm().Left(),
+ nRight = pCell->Frm().Right() - rUnion.Left();
+
+ nLeft = nLeft * aNew.GetWidth() /
+ pCell->Frm().Width();
+ nRight = nRight * aNew.GetWidth() /
+ pCell->Frm().Width();
+
+ aNew.SetWidth( nLeft );
+ pBox->ClaimFrmFmt()->SetFmtAttr( aNew );
+
+ // diese Box ist selektiert
+ pBox = pBox->GetUpper()->GetTabBoxes()[ nInsPos ];
+ aNew.SetWidth( nRight );
+ pBox->ClaimFrmFmt();
+ pBox->GetFrmFmt()->SetFmtAttr( aNew );
+
+ pLastBox = pBox;
+ rBoxes.Insert( pBox );
+ aPosArr.Insert( _CmpLPt( Point( rUnion.Left(),
+ pCell->Frm().Top()), pBox, bVert ));
+
+ if( pUndo )
+ pUndo->AddNewBox( pBox->GetSttIdx() );
+ }
+ }
+ if ( pCell->GetNext() )
+ {
+ pCell = (const SwLayoutFrm*)pCell->GetNext();
+ // --> Check if table cell is not empty
+ if ( pCell->Lower() && pCell->Lower()->IsRowFrm() )
+ pCell = pCell->FirstCell();
+ }
+ else
+ pCell = ::lcl_FindNextCellFrm( pCell );
+ }
+ }
+ pRow = (const SwLayoutFrm*)pRow->GetNext();
+ }
+ }
+
+ // keine SSelection / keine gefundenen Boxen
+ if( 1 >= rBoxes.Count() )
+ return;
+
+ // dann suche mal alle Boxen, die nebeneinander liegen, und verbinde
+ // deren Inhalte mit Blanks. Alle untereinander liegende werden als
+ // Absaetze zusammengefasst
+
+ // 1. Loesung: gehe ueber das Array und
+ // alle auf der gleichen Y-Ebene werden mit Blanks getrennt
+ // alle anderen werden als Absaetze getrennt.
+ sal_Bool bCalcWidth = sal_True;
+ const SwTableBox* pFirstBox = aPosArr[ 0 ].pSelBox;
+
+ // JP 27.03.98: Optimierung - falls die Boxen einer Line leer sind,
+ // dann werden jetzt dafuer keine Blanks und
+ // kein Umbruch mehr eingefuegt.
+ //Block damit SwPaM, SwPosition vom Stack geloescht werden
+ {
+ SwPaM aPam( pDoc->GetNodes() );
+
+#if defined( DEL_ONLY_EMPTY_LINES )
+ nWidth = pFirstBox->GetFrmFmt()->GetFrmSize().GetWidth();
+ sal_Bool bEmptyLine = sal_True;
+ sal_uInt16 n, nSttPos = 0;
+
+ for( n = 0; n < aPosArr.Count(); ++n )
+ {
+ const _CmpLPt& rPt = aPosArr[ n ];
+ if( n && aPosArr[ n - 1 ].Y() == rPt.Y() ) // gleiche Ebene ?
+ {
+ if( bEmptyLine && !IsEmptyBox( *rPt.pSelBox, aPam ))
+ bEmptyLine = sal_False;
+ if( bCalcWidth )
+ nWidth += rPt.pSelBox->GetFrmFmt()->GetFrmSize().GetWidth();
+ }
+ else
+ {
+ if( bCalcWidth && n )
+ bCalcWidth = sal_False; // eine Zeile fertig
+
+ if( bEmptyLine && nSttPos < n )
+ {
+ // dann ist die gesamte Line leer und braucht
+ // nicht mit Blanks aufgefuellt und als Absatz
+ // eingefuegt werden.
+ if( pUndo )
+ for( sal_uInt16 i = nSttPos; i < n; ++i )
+ pUndo->SaveCollection( *aPosArr[ i ].pSelBox );
+
+ aPosArr.Remove( nSttPos, n - nSttPos );
+ n = nSttPos;
+ }
+ else
+ nSttPos = n;
+
+ bEmptyLine = IsEmptyBox( *aPosArr[n].pSelBox, aPam );
+ }
+ }
+ if( bEmptyLine && nSttPos < n )
+ {
+ if( pUndo )
+ for( sal_uInt16 i = nSttPos; i < n; ++i )
+ pUndo->SaveCollection( *aPosArr[ i ].pSelBox );
+ aPosArr.Remove( nSttPos, n - nSttPos );
+ }
+#elsif defined( DEL_EMPTY_BOXES_AT_START_AND_END )
+
+ nWidth = pFirstBox->GetFrmFmt()->GetFrmSize().GetWidth();
+ sal_uInt16 n, nSttPos = 0, nSEndPos = 0, nESttPos = 0;
+
+ for( n = 0; n < aPosArr.Count(); ++n )
+ {
+ const _CmpLPt& rPt = aPosArr[ n ];
+ if( n && aPosArr[ n - 1 ].Y() == rPt.Y() ) // gleiche Ebene ?
+ {
+ sal_Bool bEmptyBox = IsEmptyBox( *rPt.pSelBox, aPam );
+ if( bEmptyBox )
+ {
+ if( nSEndPos == n ) // der Anfang ist leer
+ nESttPos = ++nSEndPos;
+ }
+ else // das Ende kann leer sein
+ nESttPos = n+1;
+
+ if( bCalcWidth )
+ nWidth += rPt.pSelBox->GetFrmFmt()->GetFrmSize().GetWidth();
+ }
+ else
+ {
+ if( bCalcWidth && n )
+ bCalcWidth = sal_False; // eine Zeile fertig
+
+ // zuerst die vom Anfang
+ if( nSttPos < nSEndPos )
+ {
+ // dann ist der vorder Teil der Line leer und braucht
+ // nicht mit Blanks aufgefuellt werden.
+ if( pUndo )
+ for( sal_uInt16 i = nSttPos; i < nSEndPos; ++i )
+ pUndo->SaveCollection( *aPosArr[ i ].pSelBox );
+
+ sal_uInt16 nCnt = nSEndPos - nSttPos;
+ aPosArr.Remove( nSttPos, nCnt );
+ nESttPos -= nCnt;
+ n -= nCnt;
+ }
+
+ if( nESttPos < n )
+ {
+ // dann ist der vorder Teil der Line leer und braucht
+ // nicht mit Blanks aufgefuellt werden.
+ if( pUndo )
+ for( sal_uInt16 i = nESttPos; i < n; ++i )
+ pUndo->SaveCollection( *aPosArr[ i ].pSelBox );
+
+ sal_uInt16 nCnt = n - nESttPos;
+ aPosArr.Remove( nESttPos, nCnt );
+ n -= nCnt;
+ }
+
+ nSttPos = nSEndPos = nESttPos = n;
+ if( IsEmptyBox( *aPosArr[n].pSelBox, aPam ))
+ ++nSEndPos;
+ else
+ ++nESttPos;
+ }
+ }
+
+ // zuerst die vom Anfang
+ if( nSttPos < nSEndPos )
+ {
+ // dann ist der vorder Teil der Line leer und braucht
+ // nicht mit Blanks aufgefuellt werden.
+ if( pUndo )
+ for( sal_uInt16 i = nSttPos; i < nSEndPos; ++i )
+ pUndo->SaveCollection( *aPosArr[ i ].pSelBox );
+
+ sal_uInt16 nCnt = nSEndPos - nSttPos;
+ aPosArr.Remove( nSttPos, nCnt );
+ nESttPos -= nCnt;
+ n -= nCnt;
+ }
+ if( nESttPos < n )
+ {
+ // dann ist der vorder Teil der Line leer und braucht
+ // nicht mit Blanks aufgefuellt werden.
+ if( pUndo )
+ for( sal_uInt16 i = nESttPos; i < n; ++i )
+ pUndo->SaveCollection( *aPosArr[ i ].pSelBox );
+
+ sal_uInt16 nCnt = n - nESttPos;
+ aPosArr.Remove( nESttPos, nCnt );
+ }
+#else
+// DEL_ALL_EMPTY_BOXES
+
+ nWidth = 0;
+ long nY = aPosArr.Count() ?
+ ( bVert ?
+ aPosArr[ 0 ].X() :
+ aPosArr[ 0 ].Y() ) :
+ 0;
+
+ for( sal_uInt16 n = 0; n < aPosArr.Count(); ++n )
+ {
+ const _CmpLPt& rPt = aPosArr[ n ];
+ if( bCalcWidth )
+ {
+ if( nY == ( bVert ? rPt.X() : rPt.Y() ) ) // gleiche Ebene ?
+ nWidth += rPt.pSelBox->GetFrmFmt()->GetFrmSize().GetWidth();
+ else
+ bCalcWidth = sal_False; // eine Zeile fertig
+ }
+
+ if( IsEmptyBox( *rPt.pSelBox, aPam ) )
+ {
+ if( pUndo )
+ pUndo->SaveCollection( *rPt.pSelBox );
+
+ aPosArr.Remove( n, 1 );
+ --n;
+ }
+ }
+#endif
+ }
+
+ // lege schon mal die neue Box an
+ {
+ SwTableBox* pTmpBox = rBoxes[0];
+ SwTableLine* pInsLine = pTmpBox->GetUpper();
+ sal_uInt16 nInsPos = pInsLine->GetTabBoxes().C40_GETPOS( SwTableBox, pTmpBox );
+
+ lcl_InsTblBox( pTblNd, pDoc, pTmpBox, nInsPos );
+ (*ppMergeBox) = pInsLine->GetTabBoxes()[ nInsPos ];
+ pInsLine->GetTabBoxes().Remove( nInsPos ); // wieder austragen
+ (*ppMergeBox)->SetUpper( 0 );
+ (*ppMergeBox)->ClaimFrmFmt();
+
+ // setze die Umrandung: von der 1. Box die linke/obere von der
+ // letzten Box die rechte/untere Kante:
+ if( pLastBox && pFirstBox )
+ {
+ SvxBoxItem aBox( pFirstBox->GetFrmFmt()->GetBox() );
+ const SvxBoxItem& rBox = pLastBox->GetFrmFmt()->GetBox();
+ aBox.SetLine( rBox.GetRight(), BOX_LINE_RIGHT );
+ aBox.SetLine( rBox.GetBottom(), BOX_LINE_BOTTOM );
+ if( aBox.GetLeft() || aBox.GetTop() ||
+ aBox.GetRight() || aBox.GetBottom() )
+ (*ppMergeBox)->GetFrmFmt()->SetFmtAttr( aBox );
+ }
+ }
+
+ //Block damit SwPaM, SwPosition vom Stack geloescht werden
+ if( aPosArr.Count() )
+ {
+ SwTxtNode* pTxtNd = 0;
+ SwPosition aInsPos( *(*ppMergeBox)->GetSttNd() );
+ SwNodeIndex& rInsPosNd = aInsPos.nNode;
+
+ SwPaM aPam( aInsPos );
+
+ for( sal_uInt16 n = 0; n < aPosArr.Count(); ++n )
+ {
+ const _CmpLPt& rPt = aPosArr[ n ];
+ aPam.GetPoint()->nNode.Assign( *rPt.pSelBox->GetSttNd()->
+ EndOfSectionNode(), -1 );
+ SwCntntNode* pCNd = aPam.GetCntntNode();
+ sal_uInt16 nL = pCNd ? pCNd->Len() : 0;
+ aPam.GetPoint()->nContent.Assign( pCNd, nL );
+
+ SwNodeIndex aSttNdIdx( *rPt.pSelBox->GetSttNd(), 1 );
+ // ein Node muss in der Box erhalten bleiben (sonst wird beim
+ // Move die gesamte Section geloescht)
+ bool const bUndo(pDoc->GetIDocumentUndoRedo().DoesUndo());
+ if( pUndo )
+ {
+ pDoc->GetIDocumentUndoRedo().DoUndo(false);
+ }
+ pDoc->AppendTxtNode( *aPam.GetPoint() );
+ if( pUndo )
+ {
+ pDoc->GetIDocumentUndoRedo().DoUndo(bUndo);
+ }
+ SwNodeRange aRg( aSttNdIdx, aPam.GetPoint()->nNode );
+ rInsPosNd++;
+ if( pUndo )
+ pUndo->MoveBoxCntnt( pDoc, aRg, rInsPosNd );
+ else
+ {
+ pDoc->MoveNodeRange( aRg, rInsPosNd,
+ IDocumentContentOperations::DOC_MOVEDEFAULT );
+ }
+ // wo steht jetzt aInsPos ??
+
+ if( bCalcWidth )
+ bCalcWidth = sal_False; // eine Zeile fertig
+
+ // den initialen TextNode ueberspringen
+ rInsPosNd.Assign( pDoc->GetNodes(),
+ rInsPosNd.GetNode().EndOfSectionIndex() - 2 );
+ pTxtNd = rInsPosNd.GetNode().GetTxtNode();
+ if( pTxtNd )
+ aInsPos.nContent.Assign( pTxtNd, pTxtNd->GetTxt().Len() );
+ }
+
+ // in der MergeBox sollte jetzt der gesamte Text stehen
+ // loesche jetzt noch den initialen TextNode
+ OSL_ENSURE( (*ppMergeBox)->GetSttIdx()+2 <
+ (*ppMergeBox)->GetSttNd()->EndOfSectionIndex(),
+ "leere Box" );
+ SwNodeIndex aIdx( *(*ppMergeBox)->GetSttNd()->EndOfSectionNode(), -1 );
+ pDoc->GetNodes().Delete( aIdx, 1 );
+ }
+
+ // setze die Breite der Box
+ (*ppMergeBox)->GetFrmFmt()->SetFmtAttr( SwFmtFrmSize( ATT_VAR_SIZE, nWidth, 0 ));
+ if( pUndo )
+ pUndo->AddNewBox( (*ppMergeBox)->GetSttIdx() );
+}
+
+
+static sal_Bool lcl_CheckCol( const _FndBox*& rpFndBox, void* pPara );
+
+static sal_Bool lcl_CheckRow( const _FndLine*& rpFndLine, void* pPara )
+{
+ ((_FndLine*)rpFndLine)->GetBoxes().ForEach( &lcl_CheckCol, pPara );
+ return *(sal_Bool*)pPara;
+}
+
+static sal_Bool lcl_CheckCol( const _FndBox*& rpFndBox, void* pPara )
+{
+ if( !rpFndBox->GetBox()->GetSttNd() )
+ {
+ if( rpFndBox->GetLines().Count() !=
+ rpFndBox->GetBox()->GetTabLines().Count() )
+ *((sal_Bool*)pPara) = sal_False;
+ else
+ ((_FndBox*)rpFndBox)->GetLines().ForEach( &lcl_CheckRow, pPara );
+ }
+ // Box geschuetzt ??
+ else if( rpFndBox->GetBox()->GetFrmFmt()->GetProtect().IsCntntProtected() )
+ *((sal_Bool*)pPara) = sal_False;
+ return *(sal_Bool*)pPara;
+}
+
+
+sal_uInt16 CheckMergeSel( const SwPaM& rPam )
+{
+ SwSelBoxes aBoxes;
+//JP 24.09.96: Merge mit wiederholenden TabellenHeadline funktioniert nicht
+// richtig. Warum nicht Point 0,0 benutzen? Dann ist garantiert,
+// das die 1. Headline mit drin ist.
+ Point aPt;
+ const SwCntntNode* pCntNd = rPam.GetCntntNode();
+ const SwLayoutFrm *pStart = pCntNd->getLayoutFrm( pCntNd->GetDoc()->GetCurrentLayout(),
+ &aPt )->GetUpper();
+ pCntNd = rPam.GetCntntNode(sal_False);
+ const SwLayoutFrm *pEnd = pCntNd->getLayoutFrm( pCntNd->GetDoc()->GetCurrentLayout(),
+ &aPt )->GetUpper();
+ GetTblSel( pStart, pEnd, aBoxes, 0 );
+ return CheckMergeSel( aBoxes );
+}
+
+sal_uInt16 CheckMergeSel( const SwSelBoxes& rBoxes )
+{
+ sal_uInt16 eRet = TBLMERGE_NOSELECTION;
+ if( rBoxes.Count() )
+ {
+ eRet = TBLMERGE_OK;
+
+ _FndBox aFndBox( 0, 0 );
+ _FndPara aPara( rBoxes, &aFndBox );
+ const SwTableNode* pTblNd = aPara.rBoxes[0]->GetSttNd()->FindTableNode();
+ ((SwTable&)pTblNd->GetTable()).GetTabLines().ForEach(
+ &_FndLineCopyCol, &aPara );
+ if( aFndBox.GetLines().Count() )
+ {
+ sal_Bool bMergeSelOk = sal_True;
+ _FndBox* pFndBox = &aFndBox;
+ _FndLine* pFndLine = 0;
+ while( pFndBox && 1 == pFndBox->GetLines().Count() )
+ {
+ pFndLine = pFndBox->GetLines()[0];
+ if( 1 == pFndLine->GetBoxes().Count() )
+ pFndBox = pFndLine->GetBoxes()[0];
+ else
+ pFndBox = 0;
+ }
+ if( pFndBox )
+ pFndBox->GetLines().ForEach( &lcl_CheckRow, &bMergeSelOk );
+ else if( pFndLine )
+ pFndLine->GetBoxes().ForEach( &lcl_CheckCol, &bMergeSelOk );
+ if( !bMergeSelOk )
+ eRet = TBLMERGE_TOOCOMPLEX;
+ }
+ else
+ eRet = TBLMERGE_NOSELECTION;
+ }
+ return eRet;
+}
+
+//Ermittelt die von einer Tabellenselektion betroffenen Tabellen und die
+//Union-Rechteckte der Selektionen - auch fuer aufgespaltene Tabellen.
+SV_IMPL_PTRARR( SwSelUnions, SwSelUnion* );
+
+SwTwips lcl_CalcWish( const SwLayoutFrm *pCell, long nWish,
+ const long nAct )
+{
+ const SwLayoutFrm *pTmp = pCell;
+ if ( !nWish )
+ nWish = 1;
+
+ const sal_Bool bRTL = pCell->IsRightToLeft();
+ SwTwips nRet = bRTL ?
+ nAct - pCell->Frm().Width() :
+ 0;
+
+ while ( pTmp )
+ {
+ while ( pTmp->GetPrev() )
+ {
+ pTmp = (SwLayoutFrm*)pTmp->GetPrev();
+ long nTmp = pTmp->GetFmt()->GetFrmSize().GetWidth();
+ nRet += ( bRTL ? ( -1 ) : 1 ) * nTmp * nAct / nWish;
+ }
+ pTmp = pTmp->GetUpper()->GetUpper();
+ if ( pTmp && !pTmp->IsCellFrm() )
+ pTmp = 0;
+ }
+ return nRet;
+}
+
+void lcl_FindStartEndRow( const SwLayoutFrm *&rpStart,
+ const SwLayoutFrm *&rpEnd,
+ const int bChkProtected )
+{
+ //Start an den Anfang seiner Zeile setzen.
+ //End an das Ende seiner Zeile setzen.
+ rpStart = (SwLayoutFrm*)rpStart->GetUpper()->Lower();
+ while ( rpEnd->GetNext() )
+ rpEnd = (SwLayoutFrm*)rpEnd->GetNext();
+
+ SvPtrarr aSttArr( 8, 8 ), aEndArr( 8, 8 );
+ const SwLayoutFrm *pTmp;
+ for( pTmp = rpStart; (FRM_CELL|FRM_ROW) & pTmp->GetType();
+ pTmp = pTmp->GetUpper() )
+ {
+ void* p = (void*)pTmp;
+ aSttArr.Insert( p, 0 );
+ }
+ for( pTmp = rpEnd; (FRM_CELL|FRM_ROW) & pTmp->GetType();
+ pTmp = pTmp->GetUpper() )
+ {
+ void* p = (void*)pTmp;
+ aEndArr.Insert( p, 0 );
+ }
+
+ for( sal_uInt16 n = 0; n < aEndArr.Count() && n < aSttArr.Count(); ++n )
+ if( aSttArr[ n ] != aEndArr[ n ] )
+ {
+ // first unequal line or box - all odds are
+ if( n & 1 ) // 1, 3, 5, ... are boxes
+ {
+ rpStart = (SwLayoutFrm*)aSttArr[ n ];
+ rpEnd = (SwLayoutFrm*)aEndArr[ n ];
+ }
+ else // 0, 2, 4, ... are lines
+ {
+ // check if start & end line are the first & last Line of the
+ // box. If not return these cells.
+ // Else the hole line with all Boxes has to be deleted.
+ rpStart = (SwLayoutFrm*)aSttArr[ n+1 ];
+ rpEnd = (SwLayoutFrm*)aEndArr[ n+1 ];
+ if( n )
+ {
+ const SwCellFrm* pCellFrm = (SwCellFrm*)aSttArr[ n-1 ];
+ const SwTableLines& rLns = pCellFrm->
+ GetTabBox()->GetTabLines();
+ if( rLns[ 0 ] == ((SwRowFrm*)aSttArr[ n ])->GetTabLine() &&
+ rLns[ rLns.Count() - 1 ] ==
+ ((SwRowFrm*)aEndArr[ n ])->GetTabLine() )
+ {
+ rpStart = rpEnd = pCellFrm;
+ while ( rpStart->GetPrev() )
+ rpStart = (SwLayoutFrm*)rpStart->GetPrev();
+ while ( rpEnd->GetNext() )
+ rpEnd = (SwLayoutFrm*)rpEnd->GetNext();
+ }
+ }
+ }
+ break;
+ }
+
+ if( !bChkProtected ) // geschuetzte Zellen beachten ?
+ return;
+
+
+ //Anfang und Ende duerfen nicht auf geschuetzten Zellen liegen.
+ while ( rpStart->GetFmt()->GetProtect().IsCntntProtected() )
+ rpStart = (SwLayoutFrm*)rpStart->GetNext();
+ while ( rpEnd->GetFmt()->GetProtect().IsCntntProtected() )
+ rpEnd = (SwLayoutFrm*)rpEnd->GetPrev();
+}
+
+
+void lcl_FindStartEndCol( const SwLayoutFrm *&rpStart,
+ const SwLayoutFrm *&rpEnd,
+ const int bChkProtected )
+{
+ //Start und End senkrecht bis an den Rand der Tabelle denken; es muss
+ //die Gesamttabelle betrachtet werden, also inklusive Masters und
+ //Follows.
+ //Fuer den Start brauchen wir den Mutter-TabellenFrm.
+ if( !rpStart )
+ return;
+ const SwTabFrm *pOrg = rpStart->FindTabFrm();
+ const SwTabFrm *pTab = pOrg;
+
+ SWRECTFN( pTab )
+
+ sal_Bool bRTL = pTab->IsRightToLeft();
+ const long nTmpWish = pOrg->GetFmt()->GetFrmSize().GetWidth();
+ const long nWish = ( nTmpWish > 0 ) ? nTmpWish : 1;
+
+ while ( pTab->IsFollow() )
+ {
+ const SwFrm *pTmp = pTab->FindPrev();
+ OSL_ENSURE( pTmp->IsTabFrm(), "Vorgaenger vom Follow nicht der Master." );
+ pTab = (const SwTabFrm*)pTmp;
+ }
+
+ SwTwips nSX = 0;
+ SwTwips nSX2 = 0;
+
+ if ( pTab->GetTable()->IsNewModel() )
+ {
+ nSX = (rpStart->Frm().*fnRect->fnGetLeft )();
+ nSX2 = (rpStart->Frm().*fnRect->fnGetRight)();
+ }
+ else
+ {
+ const SwTwips nPrtWidth = (pTab->Prt().*fnRect->fnGetWidth)();
+ nSX = ::lcl_CalcWish( rpStart, nWish, nPrtWidth ) + (pTab->*fnRect->fnGetPrtLeft)();
+ nSX2 = nSX + (rpStart->GetFmt()->GetFrmSize().GetWidth() * nPrtWidth / nWish);
+ }
+
+ const SwLayoutFrm *pTmp = pTab->FirstCell();
+
+ while ( pTmp &&
+ (!pTmp->IsCellFrm() ||
+ ( ( ! bRTL && (pTmp->Frm().*fnRect->fnGetLeft)() < nSX &&
+ (pTmp->Frm().*fnRect->fnGetRight)()< nSX2 ) ||
+ ( bRTL && (pTmp->Frm().*fnRect->fnGetLeft)() > nSX &&
+ (pTmp->Frm().*fnRect->fnGetRight)()> nSX2 ) ) ) )
+ pTmp = pTmp->GetNextLayoutLeaf();
+
+ if ( pTmp )
+ rpStart = pTmp;
+
+ pTab = pOrg;
+
+ const SwTabFrm* pLastValidTab = pTab;
+ while ( pTab->GetFollow() )
+ {
+ //
+ // Check if pTab->GetFollow() is a valid follow table:
+ // Only follow tables with at least on non-FollowFlowLine
+ // should be considered.
+ //
+ if ( pTab->HasFollowFlowLine() )
+ {
+ pTab = pTab->GetFollow();
+ const SwFrm* pTmpRow = pTab->GetFirstNonHeadlineRow();
+ if ( pTmpRow && pTmpRow->GetNext() )
+ pLastValidTab = pTab;
+ }
+ else
+ pLastValidTab = pTab = pTab->GetFollow();
+ }
+ pTab = pLastValidTab;
+
+ SwTwips nEX = 0;
+
+ if ( pTab->GetTable()->IsNewModel() )
+ {
+ nEX = (rpEnd->Frm().*fnRect->fnGetLeft )();
+ }
+ else
+ {
+ const SwTwips nPrtWidth = (pTab->Prt().*fnRect->fnGetWidth)();
+ nEX = ::lcl_CalcWish( rpEnd, nWish, nPrtWidth ) + (pTab->*fnRect->fnGetPrtLeft)();
+ }
+
+ const SwCntntFrm* pLastCntnt = pTab->FindLastCntnt();
+ rpEnd = pLastCntnt ? pLastCntnt->GetUpper() : 0;
+ // --> Made code robust. If pTab does not have a lower,
+ // we would crash here.
+ if ( !pLastCntnt ) return;
+ // <--
+
+ while( !rpEnd->IsCellFrm() )
+ rpEnd = rpEnd->GetUpper();
+
+ while ( ( bRTL && (rpEnd->Frm().*fnRect->fnGetLeft)() < nEX ) ||
+ ( ! bRTL && (rpEnd->Frm().*fnRect->fnGetLeft)() > nEX ) )
+ {
+ const SwLayoutFrm* pTmpLeaf = rpEnd->GetPrevLayoutLeaf();
+ if( !pTmpLeaf || !pTab->IsAnLower( pTmpLeaf ) )
+ break;
+ rpEnd = pTmpLeaf;
+ }
+
+ if( !bChkProtected ) // geschuetzte Zellen beachten ?
+ return;
+
+ //Anfang und Ende duerfen nicht auf geschuetzten Zellen liegen.
+ //Also muss ggf. nocheinmal rueckwaerts gesucht werden.
+ while ( rpStart->GetFmt()->GetProtect().IsCntntProtected() )
+ {
+ const SwLayoutFrm *pTmpLeaf = rpStart;
+ pTmpLeaf = pTmpLeaf->GetNextLayoutLeaf();
+ while ( pTmpLeaf && (pTmpLeaf->Frm().*fnRect->fnGetLeft)() > nEX )//erstmal die Zeile ueberspr.
+ pTmpLeaf = pTmpLeaf->GetNextLayoutLeaf();
+ while ( pTmpLeaf && (pTmpLeaf->Frm().*fnRect->fnGetLeft)() < nSX &&
+ (pTmpLeaf->Frm().*fnRect->fnGetRight)()< nSX2 )
+ pTmpLeaf = pTmpLeaf->GetNextLayoutLeaf();
+ const SwTabFrm *pTmpTab = rpStart->FindTabFrm();
+ if ( !pTmpTab->IsAnLower( pTmpLeaf ) )
+ {
+ pTmpTab = pTmpTab->GetFollow();
+ rpStart = pTmpTab->FirstCell();
+ while ( (rpStart->Frm().*fnRect->fnGetLeft)() < nSX &&
+ (rpStart->Frm().*fnRect->fnGetRight)()< nSX2 )
+ rpStart = rpStart->GetNextLayoutLeaf();
+ }
+ else
+ rpStart = pTmpLeaf;
+ }
+ while ( rpEnd->GetFmt()->GetProtect().IsCntntProtected() )
+ {
+ const SwLayoutFrm *pTmpLeaf = rpEnd;
+ pTmpLeaf = pTmpLeaf->GetPrevLayoutLeaf();
+ while ( pTmpLeaf && (pTmpLeaf->Frm().*fnRect->fnGetLeft)() < nEX )//erstmal die Zeile ueberspr.
+ pTmpLeaf = pTmpLeaf->GetPrevLayoutLeaf();
+ while ( pTmpLeaf && (pTmpLeaf->Frm().*fnRect->fnGetLeft)() > nEX )
+ pTmpLeaf = pTmpLeaf->GetPrevLayoutLeaf();
+ const SwTabFrm *pTmpTab = rpEnd->FindTabFrm();
+ if ( !pTmpLeaf || !pTmpTab->IsAnLower( pTmpLeaf ) )
+ {
+ pTmpTab = (const SwTabFrm*)pTmpTab->FindPrev();
+ OSL_ENSURE( pTmpTab->IsTabFrm(), "Vorgaenger vom Follow nicht der Master.");
+ rpEnd = pTmpTab->FindLastCntnt()->GetUpper();
+ while( !rpEnd->IsCellFrm() )
+ rpEnd = rpEnd->GetUpper();
+ while ( (rpEnd->Frm().*fnRect->fnGetLeft)() > nEX )
+ rpEnd = rpEnd->GetPrevLayoutLeaf();
+ }
+ else
+ rpEnd = pTmpLeaf;
+ }
+}
+
+
+void MakeSelUnions( SwSelUnions& rUnions, const SwLayoutFrm *pStart,
+ const SwLayoutFrm *pEnd, const SwTblSearchType eSearchType )
+{
+ while ( pStart && !pStart->IsCellFrm() )
+ pStart = pStart->GetUpper();
+ while ( pEnd && !pEnd->IsCellFrm() )
+ pEnd = pEnd->GetUpper();
+
+ if ( !pStart || !pEnd )
+ {
+ OSL_FAIL( "MakeSelUnions with pStart or pEnd not in CellFrm" );
+ return;
+ }
+
+ const SwTabFrm *pTable = pStart->FindTabFrm();
+ const SwTabFrm *pEndTable = pEnd->FindTabFrm();
+ if( !pTable || !pEndTable )
+ return;
+ sal_Bool bExchange = sal_False;
+
+ if ( pTable != pEndTable )
+ {
+ if ( !pTable->IsAnFollow( pEndTable ) )
+ {
+ OSL_ENSURE( pEndTable->IsAnFollow( pTable ), "Tabkette verknotet." );
+ bExchange = sal_True;
+ }
+ }
+ else
+ {
+ SWRECTFN( pTable )
+ long nSttTop = (pStart->Frm().*fnRect->fnGetTop)();
+ long nEndTop = (pEnd->Frm().*fnRect->fnGetTop)();
+ if( nSttTop == nEndTop )
+ {
+ if( (pStart->Frm().*fnRect->fnGetLeft)() >
+ (pEnd->Frm().*fnRect->fnGetLeft)() )
+ bExchange = sal_True;
+ }
+ else if( bVert == ( nSttTop < nEndTop ) )
+ bExchange = sal_True;
+ }
+ if ( bExchange )
+ {
+ const SwLayoutFrm *pTmp = pStart;
+ pStart = pEnd;
+ pEnd = pTmp;
+ //pTable und pEndTable nicht umsortieren, werden unten neu gesetzt.
+ //MA: 28. Dec. 93 Bug: 5190
+ }
+
+ //Start und End sind jetzt huebsch sortiert, jetzt muessen sie falls
+ //erwuenscht noch versetzt werden.
+ if( nsSwTblSearchType::TBLSEARCH_ROW == ((~nsSwTblSearchType::TBLSEARCH_PROTECT ) & eSearchType ) )
+ ::lcl_FindStartEndRow( pStart, pEnd, nsSwTblSearchType::TBLSEARCH_PROTECT & eSearchType );
+ else if( nsSwTblSearchType::TBLSEARCH_COL == ((~nsSwTblSearchType::TBLSEARCH_PROTECT ) & eSearchType ) )
+ ::lcl_FindStartEndCol( pStart, pEnd, nsSwTblSearchType::TBLSEARCH_PROTECT & eSearchType );
+
+ if ( !pEnd ) return; // Made code robust.
+
+ //neu besorgen, da sie jetzt verschoben sind.
+ pTable = pStart->FindTabFrm();
+ pEndTable = pEnd->FindTabFrm();
+
+ const long nStSz = pStart->GetFmt()->GetFrmSize().GetWidth();
+ const long nEdSz = pEnd->GetFmt()->GetFrmSize().GetWidth();
+ const long nWish = Max( 1L, pTable->GetFmt()->GetFrmSize().GetWidth() );
+ while ( pTable )
+ {
+ SWRECTFN( pTable )
+ const long nOfst = (pTable->*fnRect->fnGetPrtLeft)();
+ const long nPrtWidth = (pTable->Prt().*fnRect->fnGetWidth)();
+ long nSt1 = ::lcl_CalcWish( pStart, nWish, nPrtWidth ) + nOfst;
+ long nEd1 = ::lcl_CalcWish( pEnd, nWish, nPrtWidth ) + nOfst;
+
+ if ( nSt1 <= nEd1 )
+ nEd1 += (long)((nEdSz * nPrtWidth) / nWish) - 1;
+ else
+ nSt1 += (long)((nStSz * nPrtWidth) / nWish) - 1;
+
+ long nSt2;
+ long nEd2;
+ if( pTable->IsAnLower( pStart ) )
+ nSt2 = (pStart->Frm().*fnRect->fnGetTop)();
+ else
+ nSt2 = (pTable->Frm().*fnRect->fnGetTop)();
+ if( pTable->IsAnLower( pEnd ) )
+ nEd2 = (pEnd->Frm().*fnRect->fnGetBottom)();
+ else
+ nEd2 = (pTable->Frm().*fnRect->fnGetBottom)();
+ Point aSt, aEd;
+ if( nSt1 > nEd1 )
+ {
+ long nTmp = nSt1;
+ nSt1 = nEd1;
+ nEd1 = nTmp;
+ }
+ if( nSt2 > nEd2 )
+ {
+ long nTmp = nSt2;
+ nSt2 = nEd2;
+ nEd2 = nTmp;
+ }
+ if( bVert )
+ {
+ aSt = Point( nSt2, nSt1 );
+ aEd = Point( nEd2, nEd1 );
+ }
+ else
+ {
+ aSt = Point( nSt1, nSt2 );
+ aEd = Point( nEd1, nEd2 );
+ }
+
+ const Point aDiff( aEd - aSt );
+ SwRect aUnion( aSt, Size( aDiff.X(), aDiff.Y() ) );
+ aUnion.Justify();
+
+ // fuers
+ if( !(nsSwTblSearchType::TBLSEARCH_NO_UNION_CORRECT & eSearchType ))
+ {
+ //Leider ist die Union jetzt mit Rundungsfehlern behaftet und dadurch
+ //wuerden beim Split/Merge fehlertraechtige Umstaende entstehen.
+ //Um dies zu vermeiden werden jetzt fuer die Table die erste und
+ //letzte Zelle innerhalb der Union ermittelt und aus genau deren
+ //Werten wird die Union neu gebildet.
+ const SwLayoutFrm* pRow = pTable->IsFollow() ?
+ pTable->GetFirstNonHeadlineRow() :
+ (const SwLayoutFrm*)pTable->Lower();
+
+ while ( pRow && !pRow->Frm().IsOver( aUnion ) )
+ pRow = (SwLayoutFrm*)pRow->GetNext();
+
+ // --> FME 2004-07-26 #i31976#
+ // A follow flow row may contain emtpy cells. These are not
+ // considered by FirstCell(). Therefore we have to find
+ // the first cell manually:
+ const SwFrm* pTmpCell = 0;
+ if ( pTable->IsFollow() && pRow && pRow->IsInFollowFlowRow() )
+ {
+ const SwFrm* pTmpRow = pRow;
+ while ( pTmpRow && pTmpRow->IsRowFrm() )
+ {
+ pTmpCell = static_cast<const SwRowFrm*>(pTmpRow)->Lower();
+ pTmpRow = static_cast<const SwCellFrm*>(pTmpCell)->Lower();
+ }
+ OSL_ENSURE( !pTmpCell || pTmpCell->IsCellFrm(), "Lower of rowframe != cellframe?!" );
+ }
+ // <--
+
+ const SwLayoutFrm* pFirst = pTmpCell ?
+ static_cast<const SwLayoutFrm*>(pTmpCell) :
+ pRow ?
+ pRow->FirstCell() :
+ 0;
+
+ while ( pFirst && !::IsFrmInTblSel( aUnion, pFirst ) )
+ {
+ if ( pFirst->GetNext() )
+ {
+ pFirst = (const SwLayoutFrm*)pFirst->GetNext();
+ if ( pFirst->Lower() && pFirst->Lower()->IsRowFrm() )
+ pFirst = pFirst->FirstCell();
+ }
+ else
+ pFirst = ::lcl_FindNextCellFrm( pFirst );
+ }
+ const SwLayoutFrm* pLast = 0;
+ const SwFrm* pLastCntnt = pTable->FindLastCntnt();
+ if ( pLastCntnt )
+ pLast = ::lcl_FindCellFrm( pLastCntnt->GetUpper() );
+
+ while ( pLast && !::IsFrmInTblSel( aUnion, pLast ) )
+ pLast = ::lcl_FindCellFrm( pLast->GetPrevLayoutLeaf() );
+
+ if ( pFirst && pLast ) //Robust
+ {
+ aUnion = pFirst->Frm();
+ aUnion.Union( pLast->Frm() );
+ }
+ else
+ aUnion.Width( 0 );
+ }
+
+ if( (aUnion.*fnRect->fnGetWidth)() )
+ {
+ SwSelUnion *pTmp = new SwSelUnion( aUnion, (SwTabFrm*)pTable );
+ rUnions.C40_INSERT( SwSelUnion, pTmp, rUnions.Count() );
+ }
+
+ pTable = pTable->GetFollow();
+ if ( pTable != pEndTable && pEndTable->IsAnFollow( pTable ) )
+ pTable = 0;
+ }
+}
+
+sal_Bool CheckSplitCells( const SwCrsrShell& rShell, sal_uInt16 nDiv,
+ const SwTblSearchType eSearchType )
+{
+ if( !rShell.IsTableMode() )
+ rShell.GetCrsr();
+
+ return CheckSplitCells( *rShell.getShellCrsr(false), nDiv, eSearchType );
+}
+
+sal_Bool CheckSplitCells( const SwCursor& rCrsr, sal_uInt16 nDiv,
+ const SwTblSearchType eSearchType )
+{
+ if( 1 >= nDiv )
+ return sal_False;
+
+ sal_uInt16 nMinValue = nDiv * MINLAY;
+
+ //Start- und Endzelle besorgen und den naechsten fragen.
+ Point aPtPos, aMkPos;
+ const SwShellCrsr* pShCrsr = dynamic_cast<const SwShellCrsr*>(&rCrsr);
+ if( pShCrsr )
+ {
+ aPtPos = pShCrsr->GetPtPos();
+ aMkPos = pShCrsr->GetMkPos();
+ }
+
+ const SwCntntNode* pCntNd = rCrsr.GetCntntNode();
+ const SwLayoutFrm *pStart = pCntNd->getLayoutFrm( pCntNd->GetDoc()->GetCurrentLayout(),
+ &aPtPos )->GetUpper();
+ pCntNd = rCrsr.GetCntntNode(sal_False);
+ const SwLayoutFrm *pEnd = pCntNd->getLayoutFrm( pCntNd->GetDoc()->GetCurrentLayout(),
+ &aMkPos )->GetUpper();
+
+ SWRECTFN( pStart->GetUpper() )
+
+ //Zuerst lassen wir uns die Tabellen und die Rechtecke heraussuchen.
+ SwSelUnions aUnions;
+
+ ::MakeSelUnions( aUnions, pStart, pEnd, eSearchType );
+
+ //Jetzt zu jedem Eintrag die Boxen herausfischen und uebertragen.
+ for ( sal_uInt16 i = 0; i < aUnions.Count(); ++i )
+ {
+ SwSelUnion *pUnion = aUnions[i];
+ const SwTabFrm *pTable = pUnion->GetTable();
+
+ // Skip any repeated headlines in the follow:
+ const SwLayoutFrm* pRow = pTable->IsFollow() ?
+ pTable->GetFirstNonHeadlineRow() :
+ (const SwLayoutFrm*)pTable->Lower();
+
+ while ( pRow )
+ {
+ if ( pRow->Frm().IsOver( pUnion->GetUnion() ) )
+ {
+ const SwLayoutFrm *pCell = pRow->FirstCell();
+
+ while ( pCell && pRow->IsAnLower( pCell ) )
+ {
+ OSL_ENSURE( pCell->IsCellFrm(), "Frame ohne Celle" );
+ if( ::IsFrmInTblSel( pUnion->GetUnion(), pCell ) )
+ {
+ if( (pCell->Frm().*fnRect->fnGetWidth)() < nMinValue )
+ return sal_False;
+ }
+
+ if ( pCell->GetNext() )
+ {
+ pCell = (const SwLayoutFrm*)pCell->GetNext();
+ if ( pCell->Lower() && pCell->Lower()->IsRowFrm() )
+ pCell = pCell->FirstCell();
+ }
+ else
+ pCell = ::lcl_FindNextCellFrm( pCell );
+ }
+ }
+ pRow = (const SwLayoutFrm*)pRow->GetNext();
+ }
+ }
+ return sal_True;
+}
+
+// -------------------------------------------------------------------
+// Diese Klassen kopieren die aktuelle Tabellen-Selektion (rBoxes)
+// unter Beibehaltung der Tabellen-Struktur in eine eigene Struktur
+// neu: SS zum gezielten Loeschen/Retaurieren des Layouts.
+
+void lcl_InsertRow( SwTableLine &rLine, SwLayoutFrm *pUpper, SwFrm *pSibling )
+{
+ SwRowFrm *pRow = new SwRowFrm( rLine, pUpper );
+ if ( pUpper->IsTabFrm() && ((SwTabFrm*)pUpper)->IsFollow() )
+ {
+ SwTabFrm* pTabFrm = (SwTabFrm*)pUpper;
+ pTabFrm->FindMaster()->InvalidatePos(); //kann die Zeile vielleicht aufnehmen
+
+ if ( pSibling && pTabFrm->IsInHeadline( *pSibling ) )
+ {
+ // Skip any repeated headlines in the follow:
+ pSibling = pTabFrm->GetFirstNonHeadlineRow();
+ }
+ }
+ pRow->Paste( pUpper, pSibling );
+ pRow->RegistFlys();
+}
+
+
+sal_Bool _FndBoxCopyCol( const SwTableBox*& rpBox, void* pPara )
+{
+ _FndPara* pFndPara = (_FndPara*)pPara;
+ _FndBox* pFndBox = new _FndBox( (SwTableBox*)rpBox, pFndPara->pFndLine );
+ if( rpBox->GetTabLines().Count() )
+ {
+ _FndPara aPara( *pFndPara, pFndBox );
+ pFndBox->GetBox()->GetTabLines().ForEach( &_FndLineCopyCol, &aPara );
+ if( !pFndBox->GetLines().Count() )
+ {
+ delete pFndBox;
+ return sal_True;
+ }
+ }
+ else
+ {
+ SwTableBoxPtr pSrch = (SwTableBoxPtr)rpBox;
+ sal_uInt16 nFndPos;
+ if( !pFndPara->rBoxes.Seek_Entry( pSrch, &nFndPos ))
+ {
+ delete pFndBox;
+ return sal_True;
+ }
+ }
+ pFndPara->pFndLine->GetBoxes().C40_INSERT( _FndBox, pFndBox,
+ pFndPara->pFndLine->GetBoxes().Count() );
+ return sal_True;
+}
+
+sal_Bool _FndLineCopyCol( const SwTableLine*& rpLine, void* pPara )
+{
+ _FndPara* pFndPara = (_FndPara*)pPara;
+ _FndLine* pFndLine = new _FndLine( (SwTableLine*)rpLine, pFndPara->pFndBox );
+ _FndPara aPara( *pFndPara, pFndLine );
+ pFndLine->GetLine()->GetTabBoxes().ForEach( &_FndBoxCopyCol, &aPara );
+ if( pFndLine->GetBoxes().Count() )
+ {
+ pFndPara->pFndBox->GetLines().C40_INSERT( _FndLine, pFndLine,
+ pFndPara->pFndBox->GetLines().Count() );
+ }
+ else
+ delete pFndLine;
+ return sal_True;
+}
+
+void _FndBox::SetTableLines( const SwSelBoxes &rBoxes, const SwTable &rTable )
+{
+ //Pointer auf die Lines vor und hinter den zu verarbeitenden Bereich
+ //setzen. Wenn die erste/letzte Zeile in den Bereich eingeschlossen
+ //sind, so bleiben die Pointer eben einfach 0.
+ //Gesucht werden zunachst die Positionen der ersten/letzten betroffenen
+ //Line im Array der SwTable. Damit die 0 fuer 'keine Line' verwand werden
+ //kann werden die Positionen um 1 nach oben versetzt!
+
+ sal_uInt16 nStPos = USHRT_MAX;
+ sal_uInt16 nEndPos= 0;
+
+ for ( sal_uInt16 i = 0; i < rBoxes.Count(); ++i )
+ {
+ SwTableLine *pLine = rBoxes[i]->GetUpper();
+ while ( pLine->GetUpper() )
+ pLine = pLine->GetUpper()->GetUpper();
+ const sal_uInt16 nPos = rTable.GetTabLines().GetPos(
+ (const SwTableLine*&)pLine ) + 1;
+
+ OSL_ENSURE( nPos != USHRT_MAX, "TableLine not found." );
+
+ if( nStPos > nPos )
+ nStPos = nPos;
+
+ if( nEndPos < nPos )
+ nEndPos = nPos;
+ }
+ if ( nStPos > 1 )
+ pLineBefore = rTable.GetTabLines()[nStPos - 2];
+ if ( nEndPos < rTable.GetTabLines().Count() )
+ pLineBehind = rTable.GetTabLines()[nEndPos];
+}
+
+void _FndBox::SetTableLines( const SwTable &rTable )
+{
+ // Pointer auf die Lines vor und hinter den zu verarbeitenden Bereich
+ // setzen. Wenn die erste/letzte Zeile in den Bereich eingeschlossen
+ // sind, so bleiben die Pointer eben einfach 0.
+ // Die Positionen der ersten/letzten betroffenen Line im Array der
+ // SwTable steht in der FndBox. Damit die 0 fuer 'keine Line' verwand
+ // werdenkann werden die Positionen um 1 nach oben versetzt!
+
+ if( !GetLines().Count() )
+ return;
+
+ SwTableLine* pTmpLine = GetLines()[0]->GetLine();
+ sal_uInt16 nPos = rTable.GetTabLines().C40_GETPOS( SwTableLine, pTmpLine );
+ OSL_ENSURE( USHRT_MAX != nPos, "Line steht nicht in der Tabelle" );
+ if( nPos )
+ pLineBefore = rTable.GetTabLines()[ nPos - 1 ];
+
+ pTmpLine = GetLines()[GetLines().Count()-1]->GetLine();
+ nPos = rTable.GetTabLines().C40_GETPOS( SwTableLine, pTmpLine );
+ OSL_ENSURE( USHRT_MAX != nPos, "Line steht nicht in der Tabelle" );
+ if( ++nPos < rTable.GetTabLines().Count() )
+ pLineBehind = rTable.GetTabLines()[nPos];
+}
+
+inline void UnsetFollow( SwFlowFrm *pTab )
+{
+ pTab->bIsFollow = sal_False;
+}
+
+void _FndBox::DelFrms( SwTable &rTable )
+{
+ //Alle Lines zwischen pLineBefore und pLineBehind muessen aus dem
+ //Layout ausgeschnitten und geloescht werden.
+ //Entstehen dabei leere Follows so muessen diese vernichtet werden.
+ //Wird ein Master vernichtet, so muss der Follow Master werden.
+ //Ein TabFrm muss immer uebrigbleiben.
+
+ sal_uInt16 nStPos = 0;
+ sal_uInt16 nEndPos= rTable.GetTabLines().Count() - 1;
+ if( rTable.IsNewModel() && pLineBefore )
+ rTable.CheckRowSpan( pLineBefore, true );
+ if ( pLineBefore )
+ {
+ nStPos = rTable.GetTabLines().GetPos(
+ (const SwTableLine*&)pLineBefore );
+ OSL_ENSURE( nStPos != USHRT_MAX, "Fuchs Du hast die Line gestohlen!" );
+ ++nStPos;
+ }
+ if( rTable.IsNewModel() && pLineBehind )
+ rTable.CheckRowSpan( pLineBehind, false );
+ if ( pLineBehind )
+ {
+ nEndPos = rTable.GetTabLines().GetPos(
+ (const SwTableLine*&)pLineBehind );
+ OSL_ENSURE( nEndPos != USHRT_MAX, "Fuchs Du hast die Line gestohlen!" );
+ --nEndPos;
+ }
+
+ for ( sal_uInt16 i = nStPos; i <= nEndPos; ++i)
+ {
+ SwFrmFmt *pFmt = rTable.GetTabLines()[i]->GetFrmFmt();
+ SwIterator<SwRowFrm,SwFmt> aIter( *pFmt );
+ for ( SwRowFrm* pFrm = aIter.First(); pFrm; pFrm = aIter.Next() )
+ {
+ if ( pFrm->GetTabLine() == rTable.GetTabLines()[i] )
+ {
+ sal_Bool bDel = sal_True;
+ SwTabFrm *pUp = !pFrm->GetPrev() && !pFrm->GetNext() ?
+ (SwTabFrm*)pFrm->GetUpper() : 0;
+ if ( !pUp )
+ {
+ const sal_uInt16 nRepeat =
+ ((SwTabFrm*)pFrm->GetUpper())->GetTable()->GetRowsToRepeat();
+ if ( nRepeat > 0 &&
+ ((SwTabFrm*)pFrm->GetUpper())->IsFollow() )
+ {
+ if ( !pFrm->GetNext() )
+ {
+ SwRowFrm* pFirstNonHeadline =
+ ((SwTabFrm*)pFrm->GetUpper())->GetFirstNonHeadlineRow();
+ if ( pFirstNonHeadline == pFrm )
+ {
+ pUp = (SwTabFrm*)pFrm->GetUpper();
+ }
+ }
+ }
+ }
+ if ( pUp )
+ {
+ SwTabFrm *pFollow = pUp->GetFollow();
+ SwTabFrm *pPrev = pUp->IsFollow() ? pUp : 0;
+ if ( pPrev )
+ {
+ SwFrm *pTmp = pPrev->FindPrev();
+ OSL_ENSURE( pTmp->IsTabFrm(),
+ "Vorgaenger vom Follow kein Master.");
+ pPrev = (SwTabFrm*)pTmp;
+ }
+ if ( pPrev )
+ {
+ pPrev->SetFollow( pFollow );
+ // --> FME 2006-01-31 #i60340# Do not transfer the
+ // flag from pUp to pPrev. pUp may still have the
+ // flag set although there is not more follow flow
+ // line associated with pUp.
+ pPrev->SetFollowFlowLine( sal_False );
+ // <--
+ }
+ else if ( pFollow )
+ ::UnsetFollow( pFollow );
+
+ //Ein TabellenFrm muss immer stehenbleiben!
+ if ( pPrev || pFollow )
+ {
+ // OD 26.08.2003 #i18103# - if table is in a section,
+ // lock the section, to avoid its delete.
+ {
+ SwSectionFrm* pSctFrm = pUp->FindSctFrm();
+ bool bOldSectLock = false;
+ if ( pSctFrm )
+ {
+ bOldSectLock = pSctFrm->IsColLocked();
+ pSctFrm->ColLock();
+ }
+ pUp->Cut();
+ if ( pSctFrm && !bOldSectLock )
+ {
+ pSctFrm->ColUnlock();
+ }
+ }
+ delete pUp;
+ bDel = sal_False;//Die Row wird mit in den Abgrund
+ //gerissen.
+ }
+ }
+ if ( bDel )
+ {
+ SwFrm* pTabFrm = pFrm->GetUpper();
+ if ( pTabFrm->IsTabFrm() &&
+ !pFrm->GetNext() &&
+ ((SwTabFrm*)pTabFrm)->GetFollow() )
+ {
+ // We do not delete the follow flow line,
+ // this will be done automatically in the
+ // next turn.
+ ((SwTabFrm*)pTabFrm)->SetFollowFlowLine( sal_False );
+ }
+
+ pFrm->Cut();
+ delete pFrm;
+ }
+ }
+ }
+ }
+}
+
+sal_Bool lcl_IsLineOfTblFrm( const SwTabFrm& rTable, const SwFrm& rChk )
+{
+ const SwTabFrm* pTblFrm = rChk.FindTabFrm();
+ if( pTblFrm->IsFollow() )
+ pTblFrm = pTblFrm->FindMaster( true );
+ return &rTable == pTblFrm;
+}
+
+/*
+ * lcl_UpdateRepeatedHeadlines
+ */
+void lcl_UpdateRepeatedHeadlines( SwTabFrm& rTabFrm, bool bCalcLowers )
+{
+ OSL_ENSURE( rTabFrm.IsFollow(), "lcl_UpdateRepeatedHeadlines called for non-follow tab" );
+
+ // Delete remaining headlines:
+ SwRowFrm* pLower = 0;
+ while ( 0 != ( pLower = (SwRowFrm*)rTabFrm.Lower() ) && pLower->IsRepeatedHeadline() )
+ {
+ pLower->Cut();
+ delete pLower;
+ }
+
+ // Insert fresh set of headlines:
+ pLower = (SwRowFrm*)rTabFrm.Lower();
+ SwTable& rTable = *rTabFrm.GetTable();
+ const sal_uInt16 nRepeat = rTable.GetRowsToRepeat();
+ for ( sal_uInt16 nIdx = 0; nIdx < nRepeat; ++nIdx )
+ {
+ SwRowFrm* pHeadline = new SwRowFrm( *rTable.GetTabLines()[ nIdx ], &rTabFrm );
+ pHeadline->SetRepeatedHeadline( true );
+ pHeadline->Paste( &rTabFrm, pLower );
+ pHeadline->RegistFlys();
+ }
+
+ if ( bCalcLowers )
+ rTabFrm.SetCalcLowers();
+}
+
+void _FndBox::MakeFrms( SwTable &rTable )
+{
+ //Alle Lines zwischen pLineBefore und pLineBehind muessen im Layout
+ //wieder neu erzeugt werden.
+ //Und Zwar fuer alle Auspraegungen der Tabelle (mehrere z.B. im Kopf/Fuss).
+
+ sal_uInt16 nStPos = 0;
+ sal_uInt16 nEndPos= rTable.GetTabLines().Count() - 1;
+ if ( pLineBefore )
+ {
+ nStPos = rTable.GetTabLines().GetPos(
+ (const SwTableLine*&)pLineBefore );
+ OSL_ENSURE( nStPos != USHRT_MAX, "Fuchs Du hast die Line gestohlen!" );
+ ++nStPos;
+
+ }
+ if ( pLineBehind )
+ {
+ nEndPos = rTable.GetTabLines().GetPos(
+ (const SwTableLine*&)pLineBehind );
+ OSL_ENSURE( nEndPos != USHRT_MAX, "Fuchs Du hast die Line gestohlen!" );
+ --nEndPos;
+ }
+ //Jetzt die grosse Einfuegeoperation fuer alle Tabllen.
+ SwIterator<SwTabFrm,SwFmt> aTabIter( *rTable.GetFrmFmt() );
+ for ( SwTabFrm *pTable = aTabIter.First(); pTable; pTable = aTabIter.Next() )
+ {
+ if ( !pTable->IsFollow() )
+ {
+ SwRowFrm *pSibling = 0;
+ SwFrm *pUpperFrm = 0;
+ int i;
+ for ( i = rTable.GetTabLines().Count()-1;
+ i >= 0 && !pSibling; --i )
+ {
+ SwTableLine *pLine = pLineBehind ? pLineBehind :
+ rTable.GetTabLines()[static_cast<sal_uInt16>(i)];
+ SwIterator<SwRowFrm,SwFmt> aIter( *pLine->GetFrmFmt() );
+ pSibling = aIter.First();
+ while ( pSibling && (
+ pSibling->GetTabLine() != pLine ||
+ !lcl_IsLineOfTblFrm( *pTable, *pSibling ) ||
+ pSibling->IsRepeatedHeadline() ||
+ // --> FME 2005-08-24 #i53647# If !pLineBehind,
+ // IsInSplitTableRow() should be checked.
+ ( pLineBehind && pSibling->IsInFollowFlowRow() ) ||
+ (!pLineBehind && pSibling->IsInSplitTableRow() ) ) )
+ // <--
+ {
+ pSibling = aIter.Next();
+ }
+ }
+ if ( pSibling )
+ {
+ pUpperFrm = pSibling->GetUpper();
+ if ( !pLineBehind )
+ pSibling = 0;
+ }
+ else
+// ???? oder das der Letzte Follow der Tabelle ????
+ pUpperFrm = pTable;
+
+ for ( i = nStPos; (sal_uInt16)i <= nEndPos; ++i )
+ ::lcl_InsertRow( *rTable.GetTabLines()[static_cast<sal_uInt16>(i)],
+ (SwLayoutFrm*)pUpperFrm, pSibling );
+ if ( pUpperFrm->IsTabFrm() )
+ ((SwTabFrm*)pUpperFrm)->SetCalcLowers();
+ }
+ else if ( rTable.GetRowsToRepeat() > 0 )
+ {
+ // Insert new headlines:
+ lcl_UpdateRepeatedHeadlines( *pTable, true );
+ }
+ }
+}
+
+void _FndBox::MakeNewFrms( SwTable &rTable, const sal_uInt16 nNumber,
+ const sal_Bool bBehind )
+{
+ //Frms fuer neu eingefuege Zeilen erzeugen.
+ //bBehind == sal_True: vor pLineBehind
+ // == sal_False: hinter pLineBefore
+ const sal_uInt16 nBfPos = pLineBefore ?
+ rTable.GetTabLines().GetPos( (const SwTableLine*&)pLineBefore ) :
+ USHRT_MAX;
+ const sal_uInt16 nBhPos = pLineBehind ?
+ rTable.GetTabLines().GetPos( (const SwTableLine*&)pLineBehind ) :
+ USHRT_MAX;
+
+ //nNumber: wie oft ist eingefuegt worden.
+ //nCnt: wieviele sind nNumber mal eingefuegt worden.
+
+ const sal_uInt16 nCnt =
+ ((nBhPos != USHRT_MAX ? nBhPos : rTable.GetTabLines().Count()) -
+ (nBfPos != USHRT_MAX ? nBfPos + 1 : 0)) / (nNumber + 1);
+
+ //Den Master-TabFrm suchen
+ SwIterator<SwTabFrm,SwFmt> aTabIter( *rTable.GetFrmFmt() );
+ SwTabFrm *pTable;
+ for ( pTable = aTabIter.First(); pTable; pTable = aTabIter.Next() )
+ {
+ if( !pTable->IsFollow() )
+ {
+ SwRowFrm* pSibling = 0;
+ SwLayoutFrm *pUpperFrm = 0;
+ if ( bBehind )
+ {
+ if ( pLineBehind )
+ {
+ SwIterator<SwRowFrm,SwFmt> aIter( *pLineBehind->GetFrmFmt() );
+ pSibling = aIter.First();
+ while ( pSibling && (
+ // only consider row frames associated with pLineBehind:
+ pSibling->GetTabLine() != pLineBehind ||
+ // only consider row frames that are in pTables Master-Follow chain:
+ !lcl_IsLineOfTblFrm( *pTable, *pSibling ) ||
+ // only consider row frames that are not repeated headlines:
+ pSibling->IsRepeatedHeadline() ||
+ // only consider row frames that are not follow flow rows
+ pSibling->IsInFollowFlowRow() ) )
+ {
+ pSibling = aIter.Next();
+ }
+ }
+ if ( pSibling )
+ pUpperFrm = pSibling->GetUpper();
+ else
+ {
+ while( pTable->GetFollow() )
+ pTable = pTable->GetFollow();
+ pUpperFrm = pTable;
+ }
+ const sal_uInt16 nMax = nBhPos != USHRT_MAX ?
+ nBhPos : rTable.GetTabLines().Count();
+
+ sal_uInt16 i = nBfPos != USHRT_MAX ? nBfPos + 1 + nCnt : nCnt;
+
+ for ( ; i < nMax; ++i )
+ ::lcl_InsertRow( *rTable.GetTabLines()[i], pUpperFrm, pSibling );
+ if ( pUpperFrm->IsTabFrm() )
+ ((SwTabFrm*)pUpperFrm)->SetCalcLowers();
+ }
+ else //davor einfuegen
+ {
+ sal_uInt16 i;
+
+ // We are looking for the frame that is behind the row frame
+ // that should be inserted.
+ for ( i = 0; !pSibling; ++i )
+ {
+ SwTableLine* pLine = pLineBefore ? pLineBefore : rTable.GetTabLines()[i];
+
+ SwIterator<SwRowFrm,SwFmt> aIter( *pLine->GetFrmFmt() );
+ pSibling = aIter.First();
+
+ while ( pSibling && (
+ // only consider row frames associated with pLineBefore:
+ pSibling->GetTabLine() != pLine ||
+ // only consider row frames that are in pTables Master-Follow chain:
+ !lcl_IsLineOfTblFrm( *pTable, *pSibling ) ||
+ // only consider row frames that are not repeated headlines:
+ pSibling->IsRepeatedHeadline() ||
+ // 1. case: pLineBefore == 0:
+ // only consider row frames that are not follow flow rows
+ // 2. case: pLineBefore != 0:
+ // only consider row frames that are not split table rows
+ // --> FME 2004-11-23 #i37476# If !pLineBefore,
+ // check IsInFollowFlowRow instead of IsInSplitTableRow.
+ ( ( !pLineBefore && pSibling->IsInFollowFlowRow() ) ||
+ ( pLineBefore && pSibling->IsInSplitTableRow() ) ) ) )
+ // <--
+ {
+ pSibling = aIter.Next();
+ }
+ }
+
+ pUpperFrm = pSibling->GetUpper();
+ if ( pLineBefore )
+ pSibling = (SwRowFrm*) pSibling->GetNext();
+
+ sal_uInt16 nMax = nBhPos != USHRT_MAX ?
+ nBhPos - nCnt :
+ rTable.GetTabLines().Count() - nCnt;
+
+ i = nBfPos != USHRT_MAX ? nBfPos + 1 : 0;
+ for ( ; i < nMax; ++i )
+ ::lcl_InsertRow( *rTable.GetTabLines()[i],
+ pUpperFrm, pSibling );
+ if ( pUpperFrm->IsTabFrm() )
+ ((SwTabFrm*)pUpperFrm)->SetCalcLowers();
+ }
+ }
+ }
+
+ //Die Headlines mussen ggf. auch verarbeitet werden. Um gut arbeitenden
+ //Code nicht zu zerfasern wird hier nochmals iteriert.
+ const sal_uInt16 nRowsToRepeat = rTable.GetRowsToRepeat();
+ if ( nRowsToRepeat > 0 &&
+ ( ( !bBehind && ( nBfPos == USHRT_MAX || nBfPos + 1 < nRowsToRepeat ) ) ||
+ ( bBehind && ( ( nBfPos == USHRT_MAX && nRowsToRepeat > 1 ) || nBfPos + 2 < nRowsToRepeat ) ) ) )
+ {
+ for ( pTable = aTabIter.First(); pTable; pTable = aTabIter.Next() )
+ {
+ if ( pTable->Lower() )
+ {
+ if ( pTable->IsFollow() )
+ {
+ lcl_UpdateRepeatedHeadlines( *pTable, true );
+ }
+
+ OSL_ENSURE( ((SwRowFrm*)pTable->Lower())->GetTabLine() ==
+ rTable.GetTabLines()[0], "MakeNewFrms: Table corruption!" );
+ }
+ }
+ }
+}
+
+sal_Bool _FndBox::AreLinesToRestore( const SwTable &rTable ) const
+{
+ //Lohnt es sich MakeFrms zu rufen?
+
+ if ( !pLineBefore && !pLineBehind && rTable.GetTabLines().Count() )
+ return sal_True;
+
+ sal_uInt16 nBfPos;
+ if(pLineBefore)
+ {
+ const SwTableLine* rLBefore = (const SwTableLine*)pLineBefore;
+ nBfPos = rTable.GetTabLines().GetPos( rLBefore );
+ }
+ else
+ nBfPos = USHRT_MAX;
+
+ sal_uInt16 nBhPos;
+ if(pLineBehind)
+ {
+ const SwTableLine* rLBehind = (const SwTableLine*)pLineBehind;
+ nBhPos = rTable.GetTabLines().GetPos( rLBehind );
+ }
+ else
+ nBhPos = USHRT_MAX;
+
+ if ( nBfPos == nBhPos ) //Duerfte eigentlich nie vorkommen.
+ {
+ OSL_FAIL( "Table, Loeschen auf keinem Bereich !?!" );
+ return sal_False;
+ }
+
+ if ( rTable.GetRowsToRepeat() > 0 )
+ {
+ // ups. sollte unsere zu wiederholende Kopfzeile geloescht worden
+ // sein??
+ SwIterator<SwTabFrm,SwFmt> aIter( *rTable.GetFrmFmt() );
+ for( SwTabFrm* pTable = aIter.First(); pTable; pTable = aIter.Next() )
+ {
+ if( pTable->IsFollow() )
+ {
+ // Insert new headlines:
+ lcl_UpdateRepeatedHeadlines( *pTable, false );
+ }
+ }
+ }
+
+ // Some adjacent lines at the beginning of the table have been deleted:
+ if ( nBfPos == USHRT_MAX && nBhPos == 0 )
+ return sal_False;
+
+ // Some adjacent lines at the end of the table have been deleted:
+ if ( nBhPos == USHRT_MAX && nBfPos == (rTable.GetTabLines().Count() - 1) )
+ return sal_False;
+
+ // Some adjacent lines in the middle of the table have been deleted:
+ if ( nBfPos != USHRT_MAX && nBhPos != USHRT_MAX && (nBfPos + 1) == nBhPos )
+ return sal_False;
+
+ // The structure of the deleted lines is more complex due to split lines.
+ // A call of MakeFrms() is necessary.
+ return sal_True;
+}
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/graphic/grfatr.cxx b/sw/source/core/graphic/grfatr.cxx
new file mode 100644
index 000000000000..e652a0a12c2b
--- /dev/null
+++ b/sw/source/core/graphic/grfatr.cxx
@@ -0,0 +1,359 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+
+#include <com/sun/star/text/RelOrientation.hpp>
+#include <com/sun/star/text/VertOrientation.hpp>
+#include <com/sun/star/text/HorizontalAdjust.hpp>
+#include <com/sun/star/text/DocumentStatistic.hpp>
+#include <com/sun/star/text/HoriOrientation.hpp>
+#include <com/sun/star/text/HoriOrientationFormat.hpp>
+#include <com/sun/star/text/NotePrintMode.hpp>
+#include <com/sun/star/text/SizeType.hpp>
+#include <com/sun/star/text/VertOrientationFormat.hpp>
+#include <com/sun/star/text/WrapTextMode.hpp>
+#include <com/sun/star/text/GraphicCrop.hpp>
+#include <com/sun/star/text/XTextGraphicObjectsSupplier.hpp>
+#include <com/sun/star/drawing/ColorMode.hpp>
+#include <svtools/grfmgr.hxx>
+#include <swtypes.hxx>
+#include <grfatr.hxx>
+#include <swunohelper.hxx>
+
+#include <cmdid.h>
+#include <unomid.h>
+
+using namespace ::com::sun::star;
+
+TYPEINIT1_AUTOFACTORY(SwCropGrf, SfxPoolItem)
+TYPEINIT1_AUTOFACTORY(SwGammaGrf, SfxPoolItem)
+
+/******************************************************************************
+ * Implementierung class SwMirrorGrf
+ ******************************************************************************/
+
+SfxPoolItem* SwMirrorGrf::Clone( SfxItemPool* ) const
+{
+ return new SwMirrorGrf( *this );
+}
+
+sal_uInt16 SwMirrorGrf::GetValueCount() const
+{
+ return RES_MIRROR_GRAPH_END - RES_MIRROR_GRAPH_BEGIN;
+}
+
+int SwMirrorGrf::operator==( const SfxPoolItem& rItem) const
+{
+ return SfxEnumItem::operator==(rItem) &&
+ ((SwMirrorGrf&)rItem).IsGrfToggle() == IsGrfToggle();
+}
+
+sal_Bool lcl_IsHoriOnEvenPages(int nEnum, sal_Bool bToggle)
+{
+ sal_Bool bEnum = nEnum == RES_MIRROR_GRAPH_VERT ||
+ nEnum == RES_MIRROR_GRAPH_BOTH;
+ return bEnum != bToggle;
+}
+sal_Bool lcl_IsHoriOnOddPages(int nEnum)
+{
+ sal_Bool bEnum = nEnum == RES_MIRROR_GRAPH_VERT ||
+ nEnum == RES_MIRROR_GRAPH_BOTH;
+ return bEnum;
+}
+bool SwMirrorGrf::QueryValue( uno::Any& rVal, sal_uInt8 nMemberId ) const
+{
+ bool bRet = true;
+ sal_Bool bVal;
+ // Vertikal und Horizontal sind mal getauscht worden!
+ nMemberId &= ~CONVERT_TWIPS;
+ switch ( nMemberId )
+ {
+ case MID_MIRROR_HORZ_EVEN_PAGES:
+ bVal = lcl_IsHoriOnEvenPages(GetValue(), IsGrfToggle());
+ break;
+ case MID_MIRROR_HORZ_ODD_PAGES:
+ bVal = lcl_IsHoriOnOddPages(GetValue());
+ break;
+ case MID_MIRROR_VERT:
+ bVal = GetValue() == RES_MIRROR_GRAPH_HOR ||
+ GetValue() == RES_MIRROR_GRAPH_BOTH;
+ break;
+ default:
+ OSL_ENSURE( !this, "unknown MemberId" );
+ bRet = false;
+ }
+ rVal.setValue( &bVal, ::getBooleanCppuType() );
+ return bRet;
+}
+
+bool SwMirrorGrf::PutValue( const uno::Any& rVal, sal_uInt8 nMemberId )
+{
+ bool bRet = true;
+ sal_Bool bVal = *(sal_Bool*)rVal.getValue();
+ // Vertikal und Horizontal sind mal getauscht worden!
+ nMemberId &= ~CONVERT_TWIPS;
+ switch ( nMemberId )
+ {
+ case MID_MIRROR_HORZ_EVEN_PAGES:
+ case MID_MIRROR_HORZ_ODD_PAGES:
+ {
+ sal_Bool bIsVert = GetValue() == RES_MIRROR_GRAPH_HOR ||
+ GetValue() == RES_MIRROR_GRAPH_BOTH;
+ sal_Bool bOnOddPages = nMemberId == MID_MIRROR_HORZ_EVEN_PAGES ?
+ lcl_IsHoriOnOddPages(GetValue()) : bVal;
+ sal_Bool bOnEvenPages = nMemberId == MID_MIRROR_HORZ_ODD_PAGES ?
+ lcl_IsHoriOnEvenPages(GetValue(), IsGrfToggle()) : bVal;
+ MirrorGraph nEnum = bOnOddPages ?
+ bIsVert ? RES_MIRROR_GRAPH_BOTH : RES_MIRROR_GRAPH_VERT :
+ bIsVert ? RES_MIRROR_GRAPH_HOR : RES_MIRROR_GRAPH_DONT;
+ sal_Bool bToggle = bOnOddPages != bOnEvenPages;
+ SetValue(static_cast<sal_uInt16>(nEnum));
+ SetGrfToggle( bToggle );
+ }
+ break;
+ case MID_MIRROR_VERT:
+ if ( bVal )
+ {
+ if ( GetValue() == RES_MIRROR_GRAPH_VERT )
+ SetValue( RES_MIRROR_GRAPH_BOTH );
+ else if ( GetValue() != RES_MIRROR_GRAPH_BOTH )
+ SetValue( RES_MIRROR_GRAPH_HOR );
+ }
+ else
+ {
+ if ( GetValue() == RES_MIRROR_GRAPH_BOTH )
+ SetValue( RES_MIRROR_GRAPH_VERT );
+ else if ( GetValue() == RES_MIRROR_GRAPH_HOR )
+ SetValue( RES_MIRROR_GRAPH_DONT );
+ }
+ break;
+ default:
+ OSL_ENSURE( !this, "unknown MemberId" );
+ bRet = false;
+ }
+ return bRet;
+}
+
+
+/******************************************************************************
+ * Implementierung class SwCropGrf
+ ******************************************************************************/
+
+SwCropGrf::SwCropGrf()
+ : SvxGrfCrop( RES_GRFATR_CROPGRF )
+{}
+
+SwCropGrf::SwCropGrf(sal_Int32 nL, sal_Int32 nR, sal_Int32 nT, sal_Int32 nB )
+ : SvxGrfCrop( nL, nR, nT, nB, RES_GRFATR_CROPGRF )
+{}
+
+SfxPoolItem* SwCropGrf::Clone( SfxItemPool* ) const
+{
+ return new SwCropGrf( *this );
+}
+
+// ------------------------------------------------------------------
+
+SfxPoolItem* SwRotationGrf::Clone( SfxItemPool * ) const
+{
+ return new SwRotationGrf( GetValue(), aUnrotatedSize );
+}
+
+
+int SwRotationGrf::operator==( const SfxPoolItem& rCmp ) const
+{
+ return SfxUInt16Item::operator==( rCmp ) &&
+ GetUnrotatedSize() == ((SwRotationGrf&)rCmp).GetUnrotatedSize();
+}
+
+
+bool SwRotationGrf::QueryValue( uno::Any& rVal, sal_uInt8 ) const
+{
+ // SfxUInt16Item::QueryValue returns sal_Int32 in Any now... (srx642w)
+ // where we still want this to be a sal_Int16
+ rVal <<= (sal_Int16)GetValue();
+ return true;
+}
+
+bool SwRotationGrf::PutValue( const uno::Any& rVal, sal_uInt8 )
+{
+ // SfxUInt16Item::QueryValue returns sal_Int32 in Any now... (srx642w)
+ // where we still want this to be a sal_Int16
+ sal_Int16 nValue = 0;
+ if (rVal >>= nValue)
+ {
+ // sal_uInt16 argument needed
+ SetValue( (sal_uInt16) nValue );
+ return true;
+ }
+
+ OSL_FAIL( "SwRotationGrf::PutValue - Wrong type!" );
+ return false;
+}
+
+// ------------------------------------------------------------------
+
+SfxPoolItem* SwLuminanceGrf::Clone( SfxItemPool * ) const
+{
+ return new SwLuminanceGrf( *this );
+}
+
+// ------------------------------------------------------------------
+
+SfxPoolItem* SwContrastGrf::Clone( SfxItemPool * ) const
+{
+ return new SwContrastGrf( *this );
+}
+
+// ------------------------------------------------------------------
+
+SfxPoolItem* SwChannelRGrf::Clone( SfxItemPool * ) const
+{
+ return new SwChannelRGrf( *this );
+}
+
+// ------------------------------------------------------------------
+
+SfxPoolItem* SwChannelGGrf::Clone( SfxItemPool * ) const
+{
+ return new SwChannelGGrf( *this );
+}
+
+// ------------------------------------------------------------------
+
+SfxPoolItem* SwChannelBGrf::Clone( SfxItemPool * ) const
+{
+ return new SwChannelBGrf( *this );
+}
+
+// ------------------------------------------------------------------
+
+SfxPoolItem* SwGammaGrf::Clone( SfxItemPool * ) const
+{
+ return new SwGammaGrf( *this );
+}
+
+int SwGammaGrf::operator==( const SfxPoolItem& rCmp ) const
+{
+ return SfxPoolItem::operator==( rCmp ) &&
+ nValue == ((SwGammaGrf&)rCmp).GetValue();
+}
+
+bool SwGammaGrf::QueryValue( uno::Any& rVal, sal_uInt8 ) const
+{
+ rVal <<= nValue;
+ return true;
+}
+
+bool SwGammaGrf::PutValue( const uno::Any& rVal, sal_uInt8 )
+{
+ return rVal >>= nValue;
+}
+
+// ------------------------------------------------------------------
+
+SfxPoolItem* SwInvertGrf::Clone( SfxItemPool * ) const
+{
+ return new SwInvertGrf( *this );
+}
+
+// ------------------------------------------------------------------
+
+SfxPoolItem* SwTransparencyGrf::Clone( SfxItemPool * ) const
+{
+ return new SwTransparencyGrf( *this );
+}
+// ------------------------------------------------------------------
+bool SwTransparencyGrf::QueryValue( uno::Any& rVal,
+ sal_uInt8 ) const
+{
+ DBG_ASSERT(ISA(SfxByteItem),"Put/QueryValue should be removed!");
+ sal_Int16 nRet = GetValue();
+ DBG_ASSERT( 0 <= nRet && nRet <= 100, "value out of range" );
+ rVal <<= nRet;
+ return true;
+}
+// ------------------------------------------------------------------
+bool SwTransparencyGrf::PutValue( const uno::Any& rVal,
+ sal_uInt8 )
+{
+ //temporary conversion until this is a SfxInt16Item!
+ DBG_ASSERT(ISA(SfxByteItem),"Put/QueryValue should be removed!");
+ sal_Int16 nVal = 0;
+ if(!(rVal >>= nVal) || nVal < -100 || nVal > 100)
+ return false;
+ if(nVal < 0)
+ {
+ // for compatibility with old documents
+ // introduce rounding as for SO 6.0 PP2
+ nVal = ( ( nVal * 128 ) - (99/2) ) / 100;
+ nVal += 128;
+ }
+ DBG_ASSERT( 0 <= nVal && nVal <= 100, "value out of range" );
+ SetValue(static_cast<sal_uInt8>(nVal));
+ return true;
+}
+
+// ------------------------------------------------------------------
+
+SfxPoolItem* SwDrawModeGrf::Clone( SfxItemPool * ) const
+{
+ return new SwDrawModeGrf( *this );
+}
+
+sal_uInt16 SwDrawModeGrf::GetValueCount() const
+{
+ return GRAPHICDRAWMODE_WATERMARK + 1;
+}
+
+bool SwDrawModeGrf::QueryValue( uno::Any& rVal,
+ sal_uInt8 ) const
+{
+ drawing::ColorMode eRet = (drawing::ColorMode)GetEnumValue();
+ rVal <<= eRet;
+ return true;
+}
+
+bool SwDrawModeGrf::PutValue( const uno::Any& rVal,
+ sal_uInt8 )
+{
+ sal_Int32 eVal = SWUnoHelper::GetEnumAsInt32( rVal );
+ if(eVal >= 0 && eVal <= GRAPHICDRAWMODE_WATERMARK)
+ {
+ SetEnumValue((sal_uInt16)eVal);
+ return true;
+ }
+ return false;
+}
+
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/graphic/ndgrf.cxx b/sw/source/core/graphic/ndgrf.cxx
new file mode 100644
index 000000000000..b1d1c75b54a7
--- /dev/null
+++ b/sw/source/core/graphic/ndgrf.cxx
@@ -0,0 +1,1205 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+#include <hintids.hxx>
+#include <vcl/salbtype.hxx> // FRound
+#include <tools/urlobj.hxx>
+#include <svl/undo.hxx>
+#include <svl/fstathelper.hxx>
+#include <svtools/imap.hxx>
+#include <svtools/filter.hxx>
+#include <sot/storage.hxx>
+#include <sfx2/linkmgr.hxx>
+#include <editeng/boxitem.hxx>
+#include <sot/formats.hxx>
+#include <fmtfsize.hxx>
+#include <fmturl.hxx>
+#include <frmfmt.hxx>
+#include <doc.hxx>
+#include <frmatr.hxx>
+#include <grfatr.hxx>
+#include <swtypes.hxx>
+#include <ndgrf.hxx>
+#include <fmtcol.hxx>
+#include <hints.hxx>
+#include <swbaslnk.hxx>
+#include <pagefrm.hxx>
+#include <editsh.hxx>
+#include <pam.hxx>
+
+#include <unotools/ucbstreamhelper.hxx>
+#include <com/sun/star/embed/ElementModes.hpp>
+#include <com/sun/star/embed/XTransactedObject.hpp>
+#include <tools/link.hxx>
+#include <vcl/svapp.hxx>
+#include <com/sun/star/io/XSeekable.hpp>
+// --> OD 2007-03-28 #i73788#
+#include <retrieveinputstreamconsumer.hxx>
+// <--
+
+using namespace com::sun::star;
+
+// --------------------
+// SwGrfNode
+// --------------------
+SwGrfNode::SwGrfNode(
+ const SwNodeIndex & rWhere,
+ const String& rGrfName, const String& rFltName,
+ const Graphic* pGraphic,
+ SwGrfFmtColl *pGrfColl,
+ SwAttrSet* pAutoAttr ) :
+ SwNoTxtNode( rWhere, ND_GRFNODE, pGrfColl, pAutoAttr ),
+ // --> OD 2007-01-23 #i73788#
+ mbLinkedInputStreamReady( false ),
+ mbIsStreamReadOnly( sal_False )
+ // <--
+{
+ aGrfObj.SetSwapStreamHdl( LINK( this, SwGrfNode, SwapGraphic ) );
+ bInSwapIn = bChgTwipSize = bChgTwipSizeFromPixel = bLoadLowResGrf =
+ bFrameInPaint = bScaleImageMap = sal_False;
+
+ bGrafikArrived = sal_True;
+ ReRead(rGrfName,rFltName, pGraphic, 0, sal_False);
+}
+
+SwGrfNode::SwGrfNode( const SwNodeIndex & rWhere,
+ const GraphicObject& rGrfObj,
+ SwGrfFmtColl *pGrfColl, SwAttrSet* pAutoAttr ) :
+ SwNoTxtNode( rWhere, ND_GRFNODE, pGrfColl, pAutoAttr ),
+ // --> OD 2007-01-23 #i73788#
+ mbLinkedInputStreamReady( false ),
+ mbIsStreamReadOnly( sal_False )
+ // <--
+{
+ aGrfObj = rGrfObj;
+ aGrfObj.SetSwapStreamHdl( LINK( this, SwGrfNode, SwapGraphic ) );
+ if( rGrfObj.HasUserData() && rGrfObj.IsSwappedOut() )
+ aGrfObj.SetSwapState();
+ bInSwapIn = bChgTwipSize = bChgTwipSizeFromPixel= bLoadLowResGrf =
+ bFrameInPaint = bScaleImageMap = sal_False;
+ bGrafikArrived = sal_True;
+}
+
+// Konstruktor fuer den SW/G-Reader. Dieser ctor wird verwendet,
+// wenn eine gelinkte Grafik gelesen wird. Sie liest diese NICHT ein.
+
+
+SwGrfNode::SwGrfNode( const SwNodeIndex & rWhere,
+ const String& rGrfName, const String& rFltName,
+ SwGrfFmtColl *pGrfColl,
+ SwAttrSet* pAutoAttr ) :
+ SwNoTxtNode( rWhere, ND_GRFNODE, pGrfColl, pAutoAttr ),
+ // --> OD 2007-01-23 #i73788#
+ mbLinkedInputStreamReady( false ),
+ mbIsStreamReadOnly( sal_False )
+ // <--
+{
+ aGrfObj.SetSwapStreamHdl( LINK( this, SwGrfNode, SwapGraphic ) );
+
+ Graphic aGrf; aGrf.SetDefaultType();
+ aGrfObj.SetGraphic( aGrf, rGrfName );
+
+ bInSwapIn = bChgTwipSize = bChgTwipSizeFromPixel = bLoadLowResGrf =
+ bFrameInPaint = bScaleImageMap = sal_False;
+ bGrafikArrived = sal_True;
+
+ InsertLink( rGrfName, rFltName );
+ if( IsLinkedFile() )
+ {
+ INetURLObject aUrl( rGrfName );
+ if( INET_PROT_FILE == aUrl.GetProtocol() &&
+ FStatHelper::IsDocument( aUrl.GetMainURL( INetURLObject::NO_DECODE ) ))
+ {
+ // File vorhanden, Verbindung herstellen ohne ein Update
+ ((SwBaseLink*)&refLink)->Connect();
+ }
+ }
+}
+
+sal_Bool SwGrfNode::ReRead(
+ const String& rGrfName, const String& rFltName,
+ const Graphic* pGraphic, const GraphicObject* pGrfObj,
+ sal_Bool bNewGrf )
+{
+ sal_Bool bReadGrf = sal_False, bSetTwipSize = sal_True;
+
+ OSL_ENSURE( pGraphic || pGrfObj || rGrfName.Len(),
+ "GraphicNode without a name, Graphic or GraphicObject" );
+
+ // ReadRead mit Namen
+ if( refLink.Is() )
+ {
+ OSL_ENSURE( !bInSwapIn, "ReRead: stehe noch im SwapIn" );
+
+ if( rGrfName.Len() )
+ {
+ // Besonderheit: steht im FltNamen DDE, handelt es sich um eine
+ // DDE-gelinkte Grafik
+ String sCmd( rGrfName );
+ if( rFltName.Len() )
+ {
+ sal_uInt16 nNewType;
+ if( rFltName.EqualsAscii( "DDE" ))
+ nNewType = OBJECT_CLIENT_DDE;
+ else
+ {
+ sfx2::MakeLnkName( sCmd, 0, rGrfName, aEmptyStr, &rFltName );
+ nNewType = OBJECT_CLIENT_GRF;
+ }
+
+ if( nNewType != refLink->GetObjType() )
+ {
+ refLink->Disconnect();
+ ((SwBaseLink*)&refLink)->SetObjType( nNewType );
+ }
+ }
+
+ refLink->SetLinkSourceName( sCmd );
+ }
+ else // kein Name mehr, Link aufheben
+ {
+ GetDoc()->GetLinkManager().Remove( refLink );
+ refLink.Clear();
+ }
+
+ if( pGraphic )
+ {
+ aGrfObj.SetGraphic( *pGraphic, rGrfName );
+ bReadGrf = sal_True;
+ }
+ else if( pGrfObj )
+ {
+ aGrfObj = *pGrfObj;
+ if( pGrfObj->HasUserData() && pGrfObj->IsSwappedOut() )
+ aGrfObj.SetSwapState();
+ aGrfObj.SetLink( rGrfName );
+ bReadGrf = sal_True;
+ }
+ else
+ {
+ // MIB 25.02.97: Daten der alten Grafik zuruecksetzen, damit
+ // die korrekte Ersatz-Darstellung erscheint, wenn die
+ // der neue Link nicht geladen werden konnte.
+ Graphic aGrf; aGrf.SetDefaultType();
+ aGrfObj.SetGraphic( aGrf, rGrfName );
+
+ if( refLink.Is() )
+ {
+ if( getLayoutFrm( GetDoc()->GetCurrentLayout() ) )
+ {
+ SwMsgPoolItem aMsgHint( RES_GRF_REREAD_AND_INCACHE );
+ ModifyNotification( &aMsgHint, &aMsgHint );
+ }
+ // --> OD 2006-11-03 #i59688#
+ // do not load linked graphic, if it isn't a new linked graphic.
+// else {
+ else if ( bNewGrf )
+ // <--
+ {
+ //TODO refLink->setInputStream(getInputStream());
+ ((SwBaseLink*)&refLink)->SwapIn();
+ }
+ }
+ bSetTwipSize = sal_False;
+ }
+ }
+ else if( pGraphic && !rGrfName.Len() )
+ {
+ // MIB 27.02.2001: Old stream must be deleted before the new one is set.
+ if( HasStreamName() )
+ DelStreamName();
+
+ aGrfObj.SetGraphic( *pGraphic );
+ bReadGrf = sal_True;
+ }
+ else if( pGrfObj && !rGrfName.Len() )
+ {
+ // MIB 27.02.2001: Old stream must be deleted before the new one is set.
+ if( HasStreamName() )
+ DelStreamName();
+
+ aGrfObj = *pGrfObj;
+ if( pGrfObj->HasUserData() && pGrfObj->IsSwappedOut() )
+ aGrfObj.SetSwapState();
+ bReadGrf = sal_True;
+ }
+ // Import einer Grafik:
+ // Ist die Grafik bereits geladen?
+ else if( !bNewGrf && GRAPHIC_NONE != aGrfObj.GetType() )
+ return sal_True;
+
+ else
+ {
+ if( HasStreamName() )
+ DelStreamName();
+
+ // einen neuen Grafik-Link anlegen
+ InsertLink( rGrfName, rFltName );
+
+ if( GetNodes().IsDocNodes() )
+ {
+ if( pGraphic )
+ {
+ aGrfObj.SetGraphic( *pGraphic, rGrfName );
+ bReadGrf = sal_True;
+ // Verbindung herstellen ohne ein Update; Grafik haben wir!
+ ((SwBaseLink*)&refLink)->Connect();
+ }
+ else if( pGrfObj )
+ {
+ aGrfObj = *pGrfObj;
+ aGrfObj.SetLink( rGrfName );
+ bReadGrf = sal_True;
+ // Verbindung herstellen ohne ein Update; Grafik haben wir!
+ ((SwBaseLink*)&refLink)->Connect();
+ }
+ else
+ {
+ // MIB 25.02.97: Daten der alten Grafik zuruecksetzen, damit
+ // die korrekte Ersatz-Darstellung erscheint, wenn die
+ // der neue Kink nicht geladen werden konnte.
+ Graphic aGrf; aGrf.SetDefaultType();
+ aGrfObj.SetGraphic( aGrf, rGrfName );
+ // #i59688# - do not load linked graphic, if it isn't a new linked graphic.
+ if ( bNewGrf )
+ {
+ ((SwBaseLink*)&refLink)->SwapIn();
+ }
+ // <--
+ }
+ }
+ }
+
+ // Bug 39281: Size nicht sofort loeschen - Events auf ImageMaps
+ // sollten nicht beim Austauschen nicht ins "leere greifen"
+ if( bSetTwipSize )
+ SetTwipSize( ::GetGraphicSizeTwip( aGrfObj.GetGraphic(), 0 ) );
+
+ // erzeuge noch einen Update auf die Frames
+ if( bReadGrf && bNewGrf )
+ {
+ SwMsgPoolItem aMsgHint( RES_UPDATE_ATTR );
+ ModifyNotification( &aMsgHint, &aMsgHint );
+ }
+
+ return bReadGrf;
+}
+
+
+SwGrfNode::~SwGrfNode()
+{
+ // --> OD 2007-03-30 #i73788#
+ mpThreadConsumer.reset();
+ // <--
+
+ SwDoc* pDoc = GetDoc();
+ if( refLink.Is() )
+ {
+ OSL_ENSURE( !bInSwapIn, "DTOR: stehe noch im SwapIn" );
+ pDoc->GetLinkManager().Remove( refLink );
+ refLink->Disconnect();
+ }
+ else
+ {
+ // --> OD 2005-01-19 #i40014# - A graphic node, which are in linked
+ // section, whose link is another section is the document, doesn't
+ // have to remove the stream from the storage.
+ // Because it's hard to detect this case here and it would only fix
+ // one problem with shared graphic files - there are also problems,
+ // a certain graphic file is referenced by two independent graphic nodes,
+ // brush item or drawing objects, the stream isn't no longer removed here.
+ // To do this stuff correct, a reference counting on shared streams
+ // inside one document have to be implemented.
+// if( !pDoc->IsInDtor() && HasStreamName() )
+// DelStreamName();
+ // <--
+ }
+ //#39289# Die Frames muessen hier bereits geloescht weil der DTor der
+ //Frms die Grafik noch fuer StopAnimation braucht.
+ if( GetDepends() )
+ DelFrms();
+}
+
+
+SwCntntNode *SwGrfNode::SplitCntntNode( const SwPosition & )
+{
+ return this;
+}
+
+
+SwGrfNode * SwNodes::MakeGrfNode( const SwNodeIndex & rWhere,
+ const String& rGrfName,
+ const String& rFltName,
+ const Graphic* pGraphic,
+ SwGrfFmtColl* pGrfColl,
+ SwAttrSet* pAutoAttr,
+ sal_Bool bDelayed )
+{
+ OSL_ENSURE( pGrfColl, "MakeGrfNode: Formatpointer ist 0." );
+ SwGrfNode *pNode;
+ // Delayed erzeugen nur aus dem SW/G-Reader
+ if( bDelayed )
+ pNode = new SwGrfNode( rWhere, rGrfName,
+ rFltName, pGrfColl, pAutoAttr );
+ else
+ pNode = new SwGrfNode( rWhere, rGrfName,
+ rFltName, pGraphic, pGrfColl, pAutoAttr );
+ return pNode;
+}
+
+SwGrfNode * SwNodes::MakeGrfNode( const SwNodeIndex & rWhere,
+ const GraphicObject& rGrfObj,
+ SwGrfFmtColl* pGrfColl,
+ SwAttrSet* pAutoAttr )
+{
+ OSL_ENSURE( pGrfColl, "MakeGrfNode: Formatpointer ist 0." );
+ return new SwGrfNode( rWhere, rGrfObj, pGrfColl, pAutoAttr );
+}
+
+
+Size SwGrfNode::GetTwipSize() const
+{
+ return nGrfSize;
+}
+
+
+
+sal_Bool SwGrfNode::ImportGraphic( SvStream& rStrm )
+{
+ Graphic aGraphic;
+ if( !GraphicFilter::GetGraphicFilter()->ImportGraphic( aGraphic, String(), rStrm ) )
+ {
+ const String aUserData( aGrfObj.GetUserData() );
+
+ aGrfObj.SetGraphic( aGraphic );
+ aGrfObj.SetUserData( aUserData );
+ return sal_True;
+ }
+
+ return sal_False;
+}
+
+// Returnwert:
+// -1 : ReRead erfolgreich
+// 0 : nicht geladen
+// 1 : Einlesen erfolgreich
+
+short SwGrfNode::SwapIn( sal_Bool bWaitForData )
+{
+ if( bInSwapIn ) // nicht rekuriv!!
+ return !aGrfObj.IsSwappedOut();
+
+ short nRet = 0;
+ bInSwapIn = sal_True;
+ SwBaseLink* pLink = (SwBaseLink*)(::sfx2::SvBaseLink*) refLink;
+
+ if( pLink )
+ {
+ if( GRAPHIC_NONE == aGrfObj.GetType() ||
+ GRAPHIC_DEFAULT == aGrfObj.GetType() )
+ {
+ // noch nicht geladener Link
+ //TODO pLink->setInputStream(getInputStream());
+ if( pLink->SwapIn( bWaitForData ) )
+ nRet = -1;
+ else if( GRAPHIC_DEFAULT == aGrfObj.GetType() )
+ {
+ // keine default Bitmap mehr, also neu Painten!
+ aGrfObj.SetGraphic( Graphic() );
+ SwMsgPoolItem aMsgHint( RES_GRAPHIC_PIECE_ARRIVED );
+ ModifyNotification( &aMsgHint, &aMsgHint );
+ }
+ }
+ else if( aGrfObj.IsSwappedOut() ) {
+ // nachzuladender Link
+ //TODO pLink->setInputStream(getInputStream());
+ nRet = pLink->SwapIn( bWaitForData ) ? 1 : 0;
+ }
+ else
+ nRet = 1;
+ }
+ else if( aGrfObj.IsSwappedOut() )
+ {
+ // Die Grafik ist im Storage oder im TempFile drin
+ if( !HasStreamName() )
+ nRet = (short)aGrfObj.SwapIn();
+ else
+ {
+
+ // --> OD 2005-05-04 #i48434# - usage of new method <_GetStreamForEmbedGrf(..)>
+ try
+ {
+ // #i53025# - needed correction of new method <_GetStreamForEmbedGrf(..)>
+ String aStrmName, aPicStgName;
+ _GetStreamStorageNames( aStrmName, aPicStgName );
+ uno::Reference < embed::XStorage > refPics = _GetDocSubstorageOrRoot( aPicStgName );
+ SvStream* pStrm = _GetStreamForEmbedGrf( refPics, aStrmName );
+ if ( pStrm )
+ {
+ if ( ImportGraphic( *pStrm ) )
+ nRet = 1;
+ delete pStrm;
+ }
+ // <--
+ }
+ catch ( uno::Exception& )
+ {
+ // --> OD 2005-04-25 #i48434#
+ OSL_FAIL( "<SwGrfNode::SwapIn(..)> - unhandled exception!" );
+ // <--
+ }
+ // <--
+ }
+
+ if( 1 == nRet )
+ {
+ SwMsgPoolItem aMsg( RES_GRAPHIC_SWAPIN );
+ ModifyNotification( &aMsg, &aMsg );
+ }
+ }
+ else
+ nRet = 1;
+ DBG_ASSERTWARNING( nRet, "Grafik kann nicht eingeswapt werden" );
+
+ if( nRet )
+ {
+ if( !nGrfSize.Width() && !nGrfSize.Height() )
+ SetTwipSize( ::GetGraphicSizeTwip( aGrfObj.GetGraphic(), 0 ) );
+ }
+ bInSwapIn = sal_False;
+ return nRet;
+}
+
+
+short SwGrfNode::SwapOut()
+{
+ if( aGrfObj.GetType() != GRAPHIC_DEFAULT &&
+ aGrfObj.GetType() != GRAPHIC_NONE &&
+ !aGrfObj.IsSwappedOut() && !bInSwapIn )
+ {
+ if( !refLink.Is() )
+ {
+ // Das Swapping brauchen wir nur fuer Embedded Pictures
+ // Die Grafik wird in eine TempFile geschrieben, wenn
+ // sie frisch eingefuegt war, d.h. wenn es noch keinen
+ // Streamnamen im Storage gibt.
+ if( !HasStreamName() )
+ if( !aGrfObj.SwapOut() )
+ return 0;
+ }
+ // Geschriebene Grafiken oder Links werden jetzt weggeschmissen
+ return (short) aGrfObj.SwapOut( NULL );
+ }
+ return 1;
+}
+
+
+sal_Bool SwGrfNode::GetFileFilterNms( String* pFileNm, String* pFilterNm ) const
+{
+ sal_Bool bRet = sal_False;
+ if( refLink.Is() && refLink->GetLinkManager() )
+ {
+ sal_uInt16 nType = refLink->GetObjType();
+ if( OBJECT_CLIENT_GRF == nType )
+ bRet = refLink->GetLinkManager()->GetDisplayNames(
+ refLink, 0, pFileNm, 0, pFilterNm );
+ else if( OBJECT_CLIENT_DDE == nType && pFileNm && pFilterNm )
+ {
+ String sApp, sTopic, sItem;
+ if( refLink->GetLinkManager()->GetDisplayNames(
+ refLink, &sApp, &sTopic, &sItem ) )
+ {
+ ( *pFileNm = sApp ) += sfx2::cTokenSeperator;
+ ( *pFileNm += sTopic ) += sfx2::cTokenSeperator;
+ *pFileNm += sItem;
+ pFilterNm->AssignAscii( RTL_CONSTASCII_STRINGPARAM( "DDE" ));
+ bRet = sal_True;
+ }
+ }
+ }
+ return bRet;
+}
+
+
+// Eine Grafik Undo-faehig machen. Falls sie sich bereits in
+// einem Storage befindet, muss sie geladen werden.
+
+sal_Bool SwGrfNode::SavePersistentData()
+{
+ if( refLink.Is() )
+ {
+ OSL_ENSURE( !bInSwapIn, "SavePersistentData: stehe noch im SwapIn" );
+ GetDoc()->GetLinkManager().Remove( refLink );
+ return sal_True;
+ }
+
+ // Erst mal reinswappen, falls sie im Storage ist
+ if( HasStreamName() && !SwapIn() )
+ return sal_False;
+
+ // --> OD 2005-04-19 #i44367#
+ // Do not delete graphic file in storage, because the graphic file could
+ // be referenced by other graphic nodes.
+ // Because it's hard to detect this case here and it would only fix
+ // one problem with shared graphic files - there are also problems,
+ // a certain graphic file is referenced by two independent graphic nodes,
+ // brush item or drawing objects, the stream isn't no longer removed here.
+ // To do this stuff correct, a reference counting on shared streams
+ // inside one document have to be implemented.
+ // Important note: see also fix for #i40014#
+// if( HasStreamName() )
+// DelStreamName();
+ // <--
+
+ // Und in TempFile rausswappen
+ return (sal_Bool) SwapOut();
+}
+
+
+sal_Bool SwGrfNode::RestorePersistentData()
+{
+ if( refLink.Is() )
+ {
+ IDocumentLinksAdministration* pIDLA = getIDocumentLinksAdministration();
+ refLink->SetVisible( pIDLA->IsVisibleLinks() );
+ pIDLA->GetLinkManager().InsertDDELink( refLink );
+ if( getIDocumentLayoutAccess()->GetCurrentLayout() ) //swmod 080218
+ refLink->Update();
+ }
+ return sal_True;
+}
+
+
+void SwGrfNode::InsertLink( const String& rGrfName, const String& rFltName )
+{
+ refLink = new SwBaseLink( sfx2::LINKUPDATE_ONCALL, FORMAT_GDIMETAFILE, this );
+
+ IDocumentLinksAdministration* pIDLA = getIDocumentLinksAdministration();
+ if( GetNodes().IsDocNodes() )
+ {
+ refLink->SetVisible( pIDLA->IsVisibleLinks() );
+ if( rFltName.EqualsAscii( "DDE" ))
+ {
+ sal_uInt16 nTmp = 0;
+ String sApp, sTopic, sItem;
+ sApp = rGrfName.GetToken( 0, sfx2::cTokenSeperator, nTmp );
+ sTopic = rGrfName.GetToken( 0, sfx2::cTokenSeperator, nTmp );
+ sItem = rGrfName.Copy( nTmp );
+ pIDLA->GetLinkManager().InsertDDELink( refLink,
+ sApp, sTopic, sItem );
+ }
+ else
+ {
+ sal_Bool bSync = rFltName.EqualsAscii( "SYNCHRON" );
+ refLink->SetSynchron( bSync );
+ refLink->SetContentType( SOT_FORMATSTR_ID_SVXB );
+
+ pIDLA->GetLinkManager().InsertFileLink( *refLink,
+ OBJECT_CLIENT_GRF, rGrfName,
+ (!bSync && rFltName.Len() ? &rFltName : 0) );
+ }
+ }
+ aGrfObj.SetLink( rGrfName );
+}
+
+
+void SwGrfNode::ReleaseLink()
+{
+ if( refLink.Is() )
+ {
+ {
+ bInSwapIn = sal_True;
+ SwBaseLink* pLink = (SwBaseLink*)(::sfx2::SvBaseLink*) refLink;
+ //TODO pLink->setInputStream(getInputStream());
+ pLink->SwapIn( sal_True, sal_True );
+ bInSwapIn = sal_False;
+ }
+ getIDocumentLinksAdministration()->GetLinkManager().Remove( refLink );
+ refLink.Clear();
+ aGrfObj.SetLink();
+ }
+}
+
+
+void SwGrfNode::SetTwipSize( const Size& rSz )
+{
+ nGrfSize = rSz;
+ if( IsScaleImageMap() && nGrfSize.Width() && nGrfSize.Height() )
+ {
+ // Image-Map an Grafik-Groesse anpassen
+ ScaleImageMap();
+
+ // Image-Map nicht noch einmal skalieren
+ SetScaleImageMap( sal_False );
+ }
+}
+
+void SwGrfNode::ScaleImageMap()
+{
+ if( !nGrfSize.Width() || !nGrfSize.Height() )
+ return;
+
+ // dann die Image-Map skalieren
+ SwFrmFmt* pFmt = GetFlyFmt();
+
+ if( !pFmt )
+ return;
+
+ SwFmtURL aURL( pFmt->GetURL() );
+ if ( !aURL.GetMap() )
+ return;
+
+ sal_Bool bScale = sal_False;
+ Fraction aScaleX( 1, 1 );
+ Fraction aScaleY( 1, 1 );
+
+ const SwFmtFrmSize& rFrmSize = pFmt->GetFrmSize();
+ const SvxBoxItem& rBox = pFmt->GetBox();
+
+ if( !rFrmSize.GetWidthPercent() )
+ {
+ SwTwips nWidth = rFrmSize.GetWidth();
+
+ nWidth -= rBox.CalcLineSpace(BOX_LINE_LEFT) +
+ rBox.CalcLineSpace(BOX_LINE_RIGHT);
+
+ OSL_ENSURE( nWidth>0, "Gibt es 0 twip breite Grafiken!?" );
+
+ if( nGrfSize.Width() != nWidth )
+ {
+ aScaleX = Fraction( nGrfSize.Width(), nWidth );
+ bScale = sal_True;
+ }
+ }
+ if( !rFrmSize.GetHeightPercent() )
+ {
+ SwTwips nHeight = rFrmSize.GetHeight();
+
+ nHeight -= rBox.CalcLineSpace(BOX_LINE_TOP) +
+ rBox.CalcLineSpace(BOX_LINE_BOTTOM);
+
+ OSL_ENSURE( nHeight>0, "Gibt es 0 twip hohe Grafiken!?" );
+
+ if( nGrfSize.Height() != nHeight )
+ {
+ aScaleY = Fraction( nGrfSize.Height(), nHeight );
+ bScale = sal_True;
+ }
+ }
+
+ if( bScale )
+ {
+ aURL.GetMap()->Scale( aScaleX, aScaleY );
+ pFmt->SetFmtAttr( aURL );
+ }
+}
+
+
+void SwGrfNode::DelStreamName()
+{
+ if( HasStreamName() )
+ {
+ // Dann die Grafik im Storage loeschen
+ uno::Reference < embed::XStorage > xDocStg = GetDoc()->GetDocStorage();
+ if( xDocStg.is() )
+ {
+ try
+ {
+ String aPicStgName, aStrmName;
+ _GetStreamStorageNames( aStrmName, aPicStgName );
+ uno::Reference < embed::XStorage > refPics = xDocStg;
+ if ( aPicStgName.Len() )
+ refPics = xDocStg->openStorageElement( aPicStgName, embed::ElementModes::READWRITE );
+ refPics->removeElement( aStrmName );
+ uno::Reference < embed::XTransactedObject > xTrans( refPics, uno::UNO_QUERY );
+ if ( xTrans.is() )
+ xTrans->commit();
+ }
+ catch ( uno::Exception& )
+ {
+ // --> OD 2005-04-25 #i48434#
+ OSL_FAIL( "<SwGrfNode::DelStreamName()> - unhandled exception!" );
+ // <--
+ }
+ }
+
+ aGrfObj.SetUserData();
+ }
+}
+
+/** helper method to get a substorage of the document storage for readonly access.
+
+ OD, MAV 2005-08-17 #i53025#
+ A substorage with the specified name will be opened readonly. If the provided
+ name is empty the root storage will be returned.
+*/
+uno::Reference< embed::XStorage > SwGrfNode::_GetDocSubstorageOrRoot( const String& aStgName ) const
+{
+ uno::Reference < embed::XStorage > refStor =
+ const_cast<SwGrfNode*>(this)->GetDoc()->GetDocStorage();
+ OSL_ENSURE( refStor.is(), "Kein Storage am Doc" );
+
+ if ( aStgName.Len() )
+ {
+ if( refStor.is() )
+ return refStor->openStorageElement( aStgName, embed::ElementModes::READ );
+ }
+
+ return refStor;
+}
+
+/** helper method to determine stream for the embedded graphic.
+
+ OD 2005-05-04 #i48434#
+ Important note: caller of this method has to handle the thrown exceptions
+ OD, MAV 2005-08-17 #i53025#
+ Storage, which should contain the stream of the embedded graphic, is
+ provided via parameter. Otherwise the returned stream will be closed
+ after the the method returns, because its parent stream is closed and deleted.
+ Proposed name of embedded graphic stream is also provided by parameter.
+
+ @author OD
+*/
+SvStream* SwGrfNode::_GetStreamForEmbedGrf(
+ const uno::Reference< embed::XStorage >& _refPics,
+ String& _aStrmName ) const
+{
+ SvStream* pStrm( 0L );
+
+ if( _refPics.is() && _aStrmName.Len() )
+ {
+ // If stream doesn't exist in the storage, try access the graphic file by
+ // re-generating its name.
+ // A save action can have changed the filename of the embedded graphic,
+ // because a changed unique ID of the graphic is calculated.
+ // --> recursive calls of <GetUniqueID()> have to be avoided.
+ // Thus, use local static boolean to assure this.
+ if ( !_refPics->hasByName( _aStrmName ) ||
+ !_refPics->isStreamElement( _aStrmName ) )
+ {
+ xub_StrLen nExtPos = _aStrmName.Search( '.' );
+ String aExtStr = _aStrmName.Copy( nExtPos );
+ Graphic aGraphic( GetGrfObj().GetGraphic() );
+ if ( aGraphic.GetType() != GRAPHIC_NONE )
+ {
+ _aStrmName = String( GetGrfObj().GetUniqueID(), RTL_TEXTENCODING_ASCII_US );
+ _aStrmName += aExtStr;
+ }
+ }
+ // <--
+
+ // assure that graphic file exist in the storage.
+ if ( _refPics->hasByName( _aStrmName ) &&
+ _refPics->isStreamElement( _aStrmName ) )
+ {
+ uno::Reference < io::XStream > refStrm = _refPics->openStreamElement( _aStrmName, embed::ElementModes::READ );
+ pStrm = utl::UcbStreamHelper::CreateStream( refStrm );
+ }
+ else
+ {
+ OSL_FAIL( "<SwGrfNode::_GetStreamForEmbedGrf(..)> - embedded graphic file not found!" );
+ }
+ }
+
+ return pStrm;
+}
+
+
+// --> OD 2005-08-17 #i53025# - stream couldn't be in a 3.1 - 5.2 storage any more.
+// Thus, removing corresponding code.
+void SwGrfNode::_GetStreamStorageNames( String& rStrmName,
+ String& rStorName ) const
+{
+ rStorName.Erase();
+ rStrmName.Erase();
+
+ String aUserData( aGrfObj.GetUserData() );
+ if( !aUserData.Len() )
+ return;
+
+ if (aNewStrmName.Len()>0) {
+ aUserData=aNewStrmName;
+ }
+
+ String aProt( RTL_CONSTASCII_USTRINGPARAM( "vnd.sun.star.Package:" ) );
+ if( 0 == aUserData.CompareTo( aProt, aProt.Len() ) )
+ {
+ // 6.0 (XML) Package
+ xub_StrLen nPos = aUserData.Search( '/' );
+ if( STRING_NOTFOUND == nPos )
+ {
+ rStrmName = aUserData.Copy( aProt.Len() );
+ }
+ else
+ {
+ xub_StrLen nPathStart = aProt.Len();
+ if( 0 == aUserData.CompareToAscii( "./", 2 ) )
+ nPathStart += 2;
+ rStorName = aUserData.Copy( nPathStart, nPos-nPathStart );
+ rStrmName = aUserData.Copy( nPos+1 );
+ }
+ }
+ else
+ {
+ OSL_FAIL( "<SwGrfNode::_GetStreamStorageNames(..)> - unknown graphic URL type. Code for handling 3.1 - 5.2 storages has been deleted by issue i53025." );
+ }
+ OSL_ENSURE( STRING_NOTFOUND == rStrmName.Search( '/' ),
+ "invalid graphic stream name" );
+}
+// <--
+
+SwCntntNode* SwGrfNode::MakeCopy( SwDoc* pDoc, const SwNodeIndex& rIdx ) const
+{
+ // kopiere die Formate in das andere Dokument:
+ SwGrfFmtColl* pColl = pDoc->CopyGrfColl( *GetGrfColl() );
+
+ Graphic aTmpGrf;
+ SwBaseLink* pLink = (SwBaseLink*)(::sfx2::SvBaseLink*) refLink;
+ if( !pLink && HasStreamName() )
+ {
+ // --> OD 2005-05-04 #i48434# - usage of new method <_GetStreamForEmbedGrf(..)>
+ try
+ {
+ // #i53025# - needed correction of new method <_GetStreamForEmbedGrf(..)>
+ String aStrmName, aPicStgName;
+ _GetStreamStorageNames( aStrmName, aPicStgName );
+ uno::Reference < embed::XStorage > refPics = _GetDocSubstorageOrRoot( aPicStgName );
+ SvStream* pStrm = _GetStreamForEmbedGrf( refPics, aStrmName );
+ if ( pStrm )
+ {
+ GraphicFilter::GetGraphicFilter()->ImportGraphic( aTmpGrf, String(), *pStrm );
+ delete pStrm;
+ }
+ // <--
+ }
+ catch ( uno::Exception& )
+ {
+ // --> OD 2005-04-25 #i48434#
+ OSL_FAIL( "<SwGrfNode::MakeCopy(..)> - unhandled exception!" );
+ // <--
+ }
+ // <--
+ }
+ else
+ {
+ if( aGrfObj.IsSwappedOut() )
+ const_cast<SwGrfNode*>(this)->SwapIn();
+ aTmpGrf = aGrfObj.GetGraphic();
+ }
+
+ const sfx2::LinkManager& rMgr = getIDocumentLinksAdministration()->GetLinkManager();
+ String sFile, sFilter;
+ if( IsLinkedFile() )
+ rMgr.GetDisplayNames( refLink, 0, &sFile, 0, &sFilter );
+ else if( IsLinkedDDE() )
+ {
+ String sTmp1, sTmp2;
+ rMgr.GetDisplayNames( refLink, &sTmp1, &sTmp2, &sFilter );
+ sfx2::MakeLnkName( sFile, &sTmp1, sTmp2, sFilter );
+ sFilter.AssignAscii( RTL_CONSTASCII_STRINGPARAM( "DDE" ));
+ }
+
+ SwGrfNode* pGrfNd = pDoc->GetNodes().MakeGrfNode( rIdx, sFile, sFilter,
+ &aTmpGrf, pColl,
+ (SwAttrSet*)GetpSwAttrSet() );
+ pGrfNd->SetTitle( GetTitle() );
+ pGrfNd->SetDescription( GetDescription() );
+ pGrfNd->SetContour( HasContour(), HasAutomaticContour() );
+ return pGrfNd;
+}
+
+IMPL_LINK( SwGrfNode, SwapGraphic, GraphicObject*, pGrfObj )
+{
+ SvStream* pRet;
+
+ // Keep graphic while in swap in. That's at least important
+ // when breaking links, because in this situation a reschedule call and
+ // a DataChanged call lead to a paint of the graphic.
+ if( pGrfObj->IsInSwapOut() && (IsSelected() || bInSwapIn) )
+ pRet = GRFMGR_AUTOSWAPSTREAM_NONE;
+ else if( refLink.Is() )
+ {
+ if( pGrfObj->IsInSwapIn() )
+ {
+ // then make it by your self
+ if( !bInSwapIn )
+ {
+ sal_Bool bIsModifyLocked = IsModifyLocked();
+ LockModify();
+ SwapIn( sal_False );
+ if( !bIsModifyLocked )
+ UnlockModify();
+ }
+ pRet = GRFMGR_AUTOSWAPSTREAM_NONE;
+ }
+ else
+ pRet = GRFMGR_AUTOSWAPSTREAM_LINK;
+ }
+ else
+ {
+ pRet = GRFMGR_AUTOSWAPSTREAM_TEMP;
+
+ if( HasStreamName() )
+ {
+ // --> OD 2005-05-04 #i48434# - usage of new method <_GetStreamForEmbedGrf(..)>
+ try
+ {
+ // #i53025# - needed correction of new method <_GetStreamForEmbedGrf(..)>
+ String aStrmName, aPicStgName;
+ _GetStreamStorageNames( aStrmName, aPicStgName );
+ uno::Reference < embed::XStorage > refPics = _GetDocSubstorageOrRoot( aPicStgName );
+ SvStream* pStrm = _GetStreamForEmbedGrf( refPics, aStrmName );
+ if ( pStrm )
+ {
+ if( pGrfObj->IsInSwapOut() )
+ {
+ pRet = GRFMGR_AUTOSWAPSTREAM_LINK;
+ }
+ else
+ {
+ ImportGraphic( *pStrm );
+ pRet = GRFMGR_AUTOSWAPSTREAM_LOADED;
+ }
+ delete pStrm;
+ }
+ // <--
+ }
+ catch ( uno::Exception& )
+ {
+ // --> OD 2005-04-25 #i48434#
+ OSL_FAIL( "<SwapGraphic> - unhandled exception!" );
+ // <--
+ }
+ // <--
+ }
+ }
+
+ return (long)pRet;
+}
+
+
+// alle QuickDraw-Bitmaps eines speziellen Docs loeschen
+void DelAllGrfCacheEntries( SwDoc* pDoc )
+{
+ if( pDoc )
+ {
+ // alle Graphic-Links mit dem Namen aus dem Cache loeschen
+ const sfx2::LinkManager& rLnkMgr = pDoc->GetLinkManager();
+ const ::sfx2::SvBaseLinks& rLnks = rLnkMgr.GetLinks();
+ SwGrfNode* pGrfNd;
+ String sFileNm;
+ for( sal_uInt16 n = rLnks.Count(); n; )
+ {
+ ::sfx2::SvBaseLink* pLnk = &(*rLnks[ --n ]);
+ if( pLnk && OBJECT_CLIENT_GRF == pLnk->GetObjType() &&
+ rLnkMgr.GetDisplayNames( pLnk, 0, &sFileNm ) &&
+ pLnk->ISA( SwBaseLink ) && 0 != ( pGrfNd =
+ ((SwBaseLink*)pLnk)->GetCntntNode()->GetGrfNode()) )
+ {
+ pGrfNd->GetGrfObj().ReleaseFromCache();
+ }
+ }
+ }
+}
+
+// returns the with our graphic attributes filled Graphic-Attr-Structure
+GraphicAttr& SwGrfNode::GetGraphicAttr( GraphicAttr& rGA,
+ const SwFrm* pFrm ) const
+{
+ const SwAttrSet& rSet = GetSwAttrSet();
+
+ rGA.SetDrawMode( (GraphicDrawMode)rSet.GetDrawModeGrf().GetValue() );
+
+ const SwMirrorGrf & rMirror = rSet.GetMirrorGrf();
+ sal_uLong nMirror = BMP_MIRROR_NONE;
+ if( rMirror.IsGrfToggle() && pFrm && !pFrm->FindPageFrm()->OnRightPage() )
+ {
+ switch( rMirror.GetValue() )
+ {
+ case RES_MIRROR_GRAPH_DONT: nMirror = BMP_MIRROR_HORZ; break;
+ case RES_MIRROR_GRAPH_VERT: nMirror = BMP_MIRROR_NONE; break;
+ case RES_MIRROR_GRAPH_HOR: nMirror = BMP_MIRROR_HORZ|BMP_MIRROR_VERT;
+ break;
+ default: nMirror = BMP_MIRROR_VERT; break;
+ }
+ }
+ else
+ switch( rMirror.GetValue() )
+ {
+ case RES_MIRROR_GRAPH_BOTH: nMirror = BMP_MIRROR_HORZ|BMP_MIRROR_VERT;
+ break;
+ case RES_MIRROR_GRAPH_VERT: nMirror = BMP_MIRROR_HORZ; break;
+ case RES_MIRROR_GRAPH_HOR: nMirror = BMP_MIRROR_VERT; break;
+ }
+
+ rGA.SetMirrorFlags( nMirror );
+
+ const SwCropGrf& rCrop = rSet.GetCropGrf();
+ rGA.SetCrop( TWIP_TO_MM100( rCrop.GetLeft() ),
+ TWIP_TO_MM100( rCrop.GetTop() ),
+ TWIP_TO_MM100( rCrop.GetRight() ),
+ TWIP_TO_MM100( rCrop.GetBottom() ));
+
+ const SwRotationGrf& rRotation = rSet.GetRotationGrf();
+ rGA.SetRotation( rRotation.GetValue() );
+
+ rGA.SetLuminance( rSet.GetLuminanceGrf().GetValue() );
+ rGA.SetContrast( rSet.GetContrastGrf().GetValue() );
+ rGA.SetChannelR( rSet.GetChannelRGrf().GetValue() );
+ rGA.SetChannelG( rSet.GetChannelGGrf().GetValue() );
+ rGA.SetChannelB( rSet.GetChannelBGrf().GetValue() );
+ rGA.SetGamma( rSet.GetGammaGrf().GetValue() );
+ rGA.SetInvert( rSet.GetInvertGrf().GetValue() );
+
+ const sal_uInt16 nTrans = rSet.GetTransparencyGrf().GetValue();
+ rGA.SetTransparency( (sal_uInt8) FRound(
+ Min( nTrans, (sal_uInt16) 100 ) * 2.55 ) );
+
+ return rGA;
+}
+
+sal_Bool SwGrfNode::IsTransparent() const
+{
+ sal_Bool bRet = aGrfObj.IsTransparent();
+ if( !bRet ) // ask the attribut
+ bRet = 0 != GetSwAttrSet().GetTransparencyGrf().GetValue();
+
+ return bRet;
+}
+
+
+sal_Bool SwGrfNode::IsSelected() const
+{
+ sal_Bool bRet = sal_False;
+ const SwEditShell* pESh = GetDoc()->GetEditShell();
+ if( pESh )
+ {
+ const SwNode* pN = this;
+ const ViewShell* pV = pESh;
+ do {
+ if( pV->ISA( SwEditShell ) && pN == &((SwCrsrShell*)pV)
+ ->GetCrsr()->GetPoint()->nNode.GetNode() )
+ {
+ bRet = sal_True;
+ break;
+ }
+ }
+ while( pESh != ( pV = (ViewShell*)pV->GetNext() ));
+ }
+ return bRet;
+}
+
+// --> OD 2006-12-22 #i73788#
+boost::weak_ptr< SwAsyncRetrieveInputStreamThreadConsumer > SwGrfNode::GetThreadConsumer()
+{
+ return mpThreadConsumer;
+}
+
+void SwGrfNode::TriggerAsyncRetrieveInputStream()
+{
+ if ( !IsLinkedFile() )
+ {
+ OSL_FAIL( "<SwGrfNode::TriggerAsyncLoad()> - Method is misused. Method call is only valid for graphic nodes, which refer a linked graphic file" );
+ return;
+ }
+
+ if ( mpThreadConsumer.get() == 0 )
+ {
+ mpThreadConsumer.reset( new SwAsyncRetrieveInputStreamThreadConsumer( *this ) );
+
+ String sGrfNm;
+ refLink->GetLinkManager()->GetDisplayNames( refLink, 0, &sGrfNm, 0, 0 );
+
+ mpThreadConsumer->CreateThread( sGrfNm );
+ }
+}
+
+bool SwGrfNode::IsLinkedInputStreamReady() const
+{
+ return mbLinkedInputStreamReady;
+}
+
+void SwGrfNode::ApplyInputStream(
+ com::sun::star::uno::Reference<com::sun::star::io::XInputStream> xInputStream,
+ const sal_Bool bIsStreamReadOnly )
+{
+ if ( IsLinkedFile() )
+ {
+ if ( xInputStream.is() )
+ {
+ mxInputStream = xInputStream;
+ mbIsStreamReadOnly = bIsStreamReadOnly;
+ mbLinkedInputStreamReady = true;
+ SwMsgPoolItem aMsgHint( RES_LINKED_GRAPHIC_STREAM_ARRIVED );
+ ModifyNotification( &aMsgHint, &aMsgHint );
+ }
+ }
+}
+
+void SwGrfNode::UpdateLinkWithInputStream()
+{
+ if ( IsLinkedFile() )
+ {
+ GetLink()->setStreamToLoadFrom( mxInputStream, mbIsStreamReadOnly );
+ GetLink()->Update();
+ SwMsgPoolItem aMsgHint( RES_GRAPHIC_ARRIVED );
+ ModifyNotification( &aMsgHint, &aMsgHint );
+
+ // --> OD 2008-06-18 #i88291#
+ mxInputStream.clear();
+ GetLink()->clearStreamToLoadFrom();
+ // <--
+ mbLinkedInputStreamReady = false;
+ mpThreadConsumer.reset();
+ }
+}
+// <--
+
+// --> OD 2008-07-21 #i90395#
+bool SwGrfNode::IsAsyncRetrieveInputStreamPossible() const
+{
+ bool bRet = false;
+
+ if ( IsLinkedFile() )
+ {
+ String sGrfNm;
+ refLink->GetLinkManager()->GetDisplayNames( refLink, 0, &sGrfNm, 0, 0 );
+ String sProtocol( RTL_CONSTASCII_USTRINGPARAM( "vnd.sun.star.pkg:" ) );
+ if ( sGrfNm.CompareTo( sProtocol, sProtocol.Len() ) != 0 )
+ {
+ bRet = true;
+ }
+ }
+
+ return bRet;
+}
+// <--
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/inc/GetMetricVal.hxx b/sw/source/core/inc/GetMetricVal.hxx
new file mode 100644
index 000000000000..a752aa53b0d1
--- /dev/null
+++ b/sw/source/core/inc/GetMetricVal.hxx
@@ -0,0 +1,57 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+#ifndef _GETMETRICVAL_HXX
+#define _GETMETRICVAL_HXX
+
+#include <tools/solar.h>
+
+#define CM_1 0 // 1 centimeter or 1/2 inch
+#define CM_05 1 // 0.5 centimeter or 1/4 inch
+#define CM_01 2 // 0.1 centimeter or 1/20 inch
+
+inline sal_uInt16 GetMetricVal( int n )
+{
+#ifdef USE_MEASUREMENT
+ sal_uInt16 nVal = MEASURE_METRIC == SvtSysLocale().GetLocaleData().getMeasurementSystemEnum()
+ ? 567 // 1 cm
+ : 770; // 1/2 Inch
+#else
+ sal_uInt16 nVal = 567; // 1 cm
+#endif
+
+ if( CM_01 == n )
+ nVal /= 10;
+ else if( CM_05 == n )
+ nVal /= 2;
+ return nVal;
+}
+
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/inc/MarkManager.hxx b/sw/source/core/inc/MarkManager.hxx
new file mode 100644
index 000000000000..415b8e7b6a68
--- /dev/null
+++ b/sw/source/core/inc/MarkManager.hxx
@@ -0,0 +1,100 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef _SW_BOOKMARK_MARKMANAGER_HXX
+#define _SW_BOOKMARK_MARKMANAGER_HXX
+
+#include <IMark.hxx>
+#include <IDocumentMarkAccess.hxx>
+
+namespace sw { namespace mark
+{
+ class MarkManager
+ : private ::boost::noncopyable
+ , virtual public IDocumentMarkAccess
+ {
+ public:
+ MarkManager(/*[in/out]*/ SwDoc& rDoc);
+#if OSL_DEBUG_LEVEL > 1
+ void dumpFieldmarks( ) const;
+#endif
+ // IDocumentMarkAccess
+ virtual ::sw::mark::IMark* makeMark(const SwPaM& rPaM, const ::rtl::OUString& rName, IDocumentMarkAccess::MarkType eMark);
+
+ virtual sw::mark::IFieldmark* makeFieldBookmark( const SwPaM& rPaM,
+ const rtl::OUString& rName,
+ const rtl::OUString& rType);
+ virtual sw::mark::IFieldmark* makeNoTextFieldBookmark( const SwPaM& rPaM,
+ const rtl::OUString& rName,
+ const rtl::OUString& rType);
+
+ virtual ::sw::mark::IMark* getMarkForTxtNode(const SwTxtNode& rTxtNode, IDocumentMarkAccess::MarkType eMark);
+
+ virtual void repositionMark(::sw::mark::IMark* io_pMark, const SwPaM& rPaM);
+ virtual bool renameMark(::sw::mark::IMark* io_pMark, const ::rtl::OUString& rNewName);
+ virtual void correctMarksAbsolute(const SwNodeIndex& rOldNode, const SwPosition& rNewPos, const xub_StrLen nOffset);
+ virtual void correctMarksRelative(const SwNodeIndex& rOldNode, const SwPosition& rNewPos, const xub_StrLen nOffset);
+
+ virtual void deleteMarks(const SwNodeIndex& rStt, const SwNodeIndex& rEnd, ::std::vector< ::sw::mark::SaveBookmark>* pSaveBkmk, const SwIndex* pSttIdx, const SwIndex* pEndIdx);
+
+ // deleters
+ virtual void deleteMark(const const_iterator_t ppMark);
+ virtual void deleteMark(const ::sw::mark::IMark* const pMark);
+ virtual void clearAllMarks();
+
+ // marks
+ virtual const_iterator_t getMarksBegin() const;
+ virtual const_iterator_t getMarksEnd() const;
+ virtual sal_Int32 getMarksCount() const;
+ virtual const_iterator_t findMark(const ::rtl::OUString& rName) const;
+
+ // bookmarks
+ virtual const_iterator_t getBookmarksBegin() const;
+ virtual const_iterator_t getBookmarksEnd() const;
+ virtual sal_Int32 getBookmarksCount() const;
+ virtual const_iterator_t findBookmark(const ::rtl::OUString& rName) const;
+
+ // Fieldmarks
+ virtual ::sw::mark::IFieldmark* getFieldmarkFor(const SwPosition& rPos) const;
+ virtual ::sw::mark::IFieldmark* getFieldmarkBefore(const SwPosition& rPos) const;
+ virtual ::sw::mark::IFieldmark* getFieldmarkAfter(const SwPosition& rPos) const;
+
+ private:
+ // make names
+ ::rtl::OUString getUniqueMarkName(const ::rtl::OUString& rName) const;
+ void sortMarks();
+
+ container_t m_vMarks;
+ container_t m_vBookmarks;
+ container_t m_vFieldmarks;
+ SwDoc * const m_pDoc;
+ };
+}}
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/inc/SwGrammarMarkUp.hxx b/sw/source/core/inc/SwGrammarMarkUp.hxx
new file mode 100644
index 000000000000..0d831d3f0b2a
--- /dev/null
+++ b/sw/source/core/inc/SwGrammarMarkUp.hxx
@@ -0,0 +1,77 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef _SWGRAMMARMARKUP_HXX
+#define _SWGRAMMARMARKUP_HXX
+
+#include <wrong.hxx>
+#include <vector>
+
+/* SwGrammarMarkUp extends the functionality of a "normal" SwWrongList by memorizing
+ the start positions of sentences in the paragraph
+
+ The whole class is only a temporary solution without usage of virtual functions.
+ At the end the whole SwWrongList stuff should be reworked and replaced by interfaces
+ to deal with all the different wronglists like
+ spell, grammar, smarttag, sentence...
+ "MarkUpList" would be a better name than WrongList.
+*/
+
+class SwGrammarMarkUp : public SwWrongList
+{
+ std::vector< xub_StrLen > maSentence;
+public:
+ SwGrammarMarkUp() : SwWrongList( WRONGLIST_GRAMMAR ) {}
+ SwGrammarMarkUp( const SwGrammarMarkUp* );
+
+ virtual ~SwGrammarMarkUp();
+ virtual SwWrongList* Clone();
+ virtual void CopyFrom( const SwWrongList& rCopy );
+
+ /* SwWrongList::Move() + handling of maSentence */
+ void MoveGrammar( xub_StrLen nPos, long nDiff );
+ /* SwWrongList::SplitList() + handling of maSentence */
+ SwGrammarMarkUp* SplitGrammarList( xub_StrLen nSplitPos );
+ /* SwWrongList::JoinList() + handling of maSentence */
+ void JoinGrammarList( SwGrammarMarkUp* pNext, xub_StrLen nInsertPos );
+ /* SwWrongList::ClearList() + handling of maSentence */
+ void ClearGrammarList( xub_StrLen nSentenceEnd = STRING_LEN );
+ /* setSentence to define the start positionof a sentence,
+ at the moment the end position is given by the next start position */
+ void setSentence( xub_StrLen nStart );
+ /* getSentenceStart returns the last start position of a sentence
+ which is lower or equal to the given parameter */
+ xub_StrLen getSentenceStart( xub_StrLen nPos );
+ /* getSentenceEnd returns the first start position of a sentence
+ which is greater than the given parameter */
+ xub_StrLen getSentenceEnd( xub_StrLen nPos );
+};
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/inc/SwPortionHandler.hxx b/sw/source/core/inc/SwPortionHandler.hxx
new file mode 100644
index 000000000000..a78e00bbc753
--- /dev/null
+++ b/sw/source/core/inc/SwPortionHandler.hxx
@@ -0,0 +1,104 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+#ifndef _SW_PORTIONHANDLER_HXX
+#define _SW_PORTIONHANDLER_HXX
+
+#include <tools/solar.h>
+class String;
+
+/** The SwPortionHandler interface implements a visitor for the layout
+ * engine's text portions. This can be used to gather information of
+ * the on-screen representation of a single paragraph.
+ *
+ * For each text portion, one of the methods text(...) or special(...)
+ * is called, depending on whether it is a 'normal' run of text, or
+ * any other portion. Additionally, the linebreak() method is called
+ * once at the end of every on-screen line.
+ *
+ * All parameters relate to the 'model string', which is the text string
+ * held by the corresponding SwTxtNode.
+ *
+ * The SwPortionHandler can be used with the
+ * SwTextFrame::VisitPortions(...) method.
+ */
+class SwPortionHandler
+{
+public:
+
+ SwPortionHandler() {} /// (emtpy) constructor
+
+ virtual ~SwPortionHandler() {} /// (empty) destructor
+
+ /** text portion. A run of nLength characters from the model
+ * string, that contains no special characters like embedded
+ * fields, etc. Thus, the on-screen text of this portion
+ * corresponds exactly to the corresponding characters in the
+ * model string.
+ */
+ virtual void Text(
+ sal_uInt16 nLength, /// length of this portion in the model string
+ sal_uInt16 nType /// type of this portion
+ ) = 0;
+
+ /** special portion. This method is called for every non-text
+ * portion. The parameters describe the length of the
+ * corresponding characters in the model string (often 0 or 1),
+ * the text which is displayed, and the type of the portion.
+ */
+ virtual void Special(
+ sal_uInt16 nLength, /// length of this portion in the model string
+ const String& rText, /// text which is painted on-screen
+ sal_uInt16 nType /// type of this portion
+ ) = 0;
+
+ /** line break. This method is called whenever a line break in the
+ * layout occurs.
+ */
+ virtual void LineBreak() = 0;
+
+ /** skip characters. The SwTxtFrame may only display partially
+ * display a certain paragraph (e.g. when the paragaph is split
+ * across multiple pages). In this case, the Skip() method must be
+ * called to inform the portion handler to ignore a certain run of
+ * characters in the 'model string'. Skip(), if used at all, must
+ * be called before any of the other methods is called. Calling
+ * Skip() between portions is not allowed.
+ */
+ virtual void Skip(
+ sal_uInt16 nLength /// number of 'model string' characters to be skipped
+ ) = 0;
+
+ /** end of paragraph. This method is to be called when all the
+ * paragraph's portions have been processed.
+ */
+ virtual void Finish() = 0;
+};
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/inc/SwUndoFmt.hxx b/sw/source/core/inc/SwUndoFmt.hxx
new file mode 100644
index 000000000000..0eeb4df3f802
--- /dev/null
+++ b/sw/source/core/inc/SwUndoFmt.hxx
@@ -0,0 +1,255 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+#ifndef SW_UNDO_TXT_FMT_COLL_HXX
+#define SW_UNDO_TXT_FMT_COLL_HXX
+
+#include <undobj.hxx>
+#include <swundo.hxx>
+#include <numrule.hxx>
+
+
+class SwDoc;
+class SwTxtFmtColl;
+class String;
+class SwRewriter;
+class SfxItemSet;
+
+class SwUndoFmtCreate : public SwUndo
+{
+protected:
+ SwFmt * pNew;
+ String sDerivedFrom;
+ SwDoc * pDoc;
+ mutable String sNewName;
+ SfxItemSet * pNewSet;
+ sal_uInt16 nId; // FmtId related
+ sal_Bool bAuto;
+
+public:
+
+ SwUndoFmtCreate(SwUndoId nUndoId, SwFmt * pNew, SwFmt * pDerivedFrom,
+ SwDoc * pDoc);
+ virtual ~SwUndoFmtCreate();
+
+ virtual void UndoImpl( ::sw::UndoRedoContext & );
+ virtual void RedoImpl( ::sw::UndoRedoContext & );
+
+ virtual SwRewriter GetRewriter() const;
+
+ virtual SwFmt * Create(SwFmt * pDerivedFrom) = 0;
+ virtual void Delete() = 0;
+ virtual SwFmt * Find(const String & rName) const = 0;
+};
+
+class SwUndoFmtDelete : public SwUndo
+{
+protected:
+ String sDerivedFrom;
+ SwDoc * pDoc;
+ String sOldName;
+ SfxItemSet aOldSet;
+ sal_uInt16 nId; // FmtId related
+ sal_Bool bAuto;
+
+public:
+ SwUndoFmtDelete(SwUndoId nUndoId, SwFmt * pOld, SwDoc * pDoc);
+ ~SwUndoFmtDelete();
+
+ virtual void UndoImpl( ::sw::UndoRedoContext & );
+ virtual void RedoImpl( ::sw::UndoRedoContext & );
+
+ virtual SwRewriter GetRewriter() const;
+
+ virtual SwFmt * Create(SwFmt * pDerivedFrom) = 0;
+ virtual void Delete(SwFmt * pFmt) = 0;
+ virtual SwFmt * Find(const String & rName) const = 0;
+};
+
+class SwUndoRenameFmt : public SwUndo
+{
+protected:
+ String sOldName, sNewName;
+ SwDoc * pDoc;
+
+public:
+ SwUndoRenameFmt(SwUndoId nUndoId, const String & sOldName,
+ const String & sNewName,
+ SwDoc * pDoc);
+ ~SwUndoRenameFmt();
+
+ virtual void UndoImpl( ::sw::UndoRedoContext & );
+ virtual void RedoImpl( ::sw::UndoRedoContext & );
+
+ SwRewriter GetRewriter() const;
+
+ virtual SwFmt * Find(const String & rName) const = 0;
+};
+
+class SwUndoTxtFmtCollCreate : public SwUndoFmtCreate
+{
+public:
+ SwUndoTxtFmtCollCreate(SwTxtFmtColl * pNew, SwTxtFmtColl * pDerivedFrom,
+ SwDoc * pDoc);
+
+ virtual SwFmt * Create(SwFmt * pDerivedFrom);
+ virtual void Delete();
+ virtual SwFmt * Find(const String & rName) const;
+};
+
+class SwUndoTxtFmtCollDelete : public SwUndoFmtDelete
+{
+public:
+ SwUndoTxtFmtCollDelete(SwTxtFmtColl * pOld, SwDoc * pDoc);
+
+ virtual SwFmt * Create(SwFmt * pDerivedFrom);
+ virtual void Delete(SwFmt * pFmt);
+ virtual SwFmt * Find(const String & rName) const;
+};
+
+class SwUndoRenameFmtColl : public SwUndoRenameFmt
+{
+public:
+ SwUndoRenameFmtColl(const String & sOldName,
+ const String & sNewName,
+ SwDoc * pDoc);
+
+ virtual SwFmt * Find(const String & rName) const;
+};
+
+class SwUndoCharFmtCreate : public SwUndoFmtCreate
+{
+public:
+ SwUndoCharFmtCreate(SwCharFmt * pNew, SwCharFmt * pDerivedFrom,
+ SwDoc * pDoc);
+
+ virtual SwFmt * Create(SwFmt * pDerivedFrom);
+ virtual void Delete();
+ virtual SwFmt * Find(const String & rName) const;
+};
+
+class SwUndoCharFmtDelete : public SwUndoFmtDelete
+{
+public:
+ SwUndoCharFmtDelete(SwCharFmt * pOld, SwDoc * pDoc);
+
+ virtual SwFmt * Create(SwFmt * pDerivedFrom);
+ virtual void Delete(SwFmt * pFmt);
+ virtual SwFmt * Find(const String & rName) const;
+};
+
+class SwUndoRenameCharFmt : public SwUndoRenameFmt
+{
+public:
+ SwUndoRenameCharFmt(const String & sOldName,
+ const String & sNewName,
+ SwDoc * pDoc);
+
+ virtual SwFmt * Find(const String & rName) const;
+};
+
+class SwUndoFrmFmtCreate : public SwUndoFmtCreate
+{
+ sal_Bool bAuto;
+
+public:
+ SwUndoFrmFmtCreate(SwFrmFmt * pNew, SwFrmFmt * pDerivedFrom,
+ SwDoc * pDoc);
+
+ virtual SwFmt * Create(SwFmt * pDerivedFrom);
+ virtual void Delete();
+ virtual SwFmt * Find(const String & rName) const;
+};
+
+class SwUndoFrmFmtDelete : public SwUndoFmtDelete
+{
+public:
+ SwUndoFrmFmtDelete(SwFrmFmt * pOld, SwDoc * pDoc);
+
+ virtual SwFmt * Create(SwFmt * pDerivedFrom);
+ virtual void Delete(SwFmt * pFmt);
+ virtual SwFmt * Find(const String & rName) const;
+};
+
+class SwUndoRenameFrmFmt : public SwUndoRenameFmt
+{
+public:
+ SwUndoRenameFrmFmt(const String & sOldName,
+ const String & sNewName,
+ SwDoc * pDoc);
+
+ virtual SwFmt * Find(const String & rName) const;
+};
+
+class SwUndoNumruleCreate : public SwUndo
+{
+ const SwNumRule * pNew;
+ mutable SwNumRule aNew;
+ SwDoc * pDoc;
+ mutable bool bInitialized;
+
+public:
+ SwUndoNumruleCreate(const SwNumRule * pNew, SwDoc * pDoc);
+
+ virtual void UndoImpl( ::sw::UndoRedoContext & );
+ virtual void RedoImpl( ::sw::UndoRedoContext & );
+
+ SwRewriter GetRewriter() const;
+};
+
+class SwUndoNumruleDelete : public SwUndo
+{
+ SwNumRule aOld;
+ SwDoc * pDoc;
+
+public:
+ SwUndoNumruleDelete(const SwNumRule & aRule, SwDoc * pDoc);
+
+ virtual void UndoImpl( ::sw::UndoRedoContext & );
+ virtual void RedoImpl( ::sw::UndoRedoContext & );
+
+ SwRewriter GetRewriter() const;
+};
+
+class SwUndoNumruleRename : public SwUndo
+{
+ String aOldName, aNewName;
+ SwDoc * pDoc;
+
+ public:
+ SwUndoNumruleRename(const String & aOldName, const String & aNewName,
+ SwDoc * pDoc);
+
+ virtual void UndoImpl( ::sw::UndoRedoContext & );
+ virtual void RedoImpl( ::sw::UndoRedoContext & );
+
+ SwRewriter GetRewriter() const;
+};
+
+#endif // SW_UNDO_TXT_FMT_COLL_HXX
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/inc/SwUndoPageDesc.hxx b/sw/source/core/inc/SwUndoPageDesc.hxx
new file mode 100644
index 000000000000..7acb98053e52
--- /dev/null
+++ b/sw/source/core/inc/SwUndoPageDesc.hxx
@@ -0,0 +1,96 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+#ifndef SW_UNDO_PAGE_DESC_HXX
+#define SW_UNDO_PAGE_DESC_HXX
+
+#include <undobj.hxx>
+#include <pagedesc.hxx>
+
+class SwDoc;
+class SwPageDesc;
+
+
+class SwUndoPageDesc : public SwUndo
+{
+ SwPageDescExt aOld, aNew;
+ SwDoc * pDoc;
+ bool bExchange;
+
+ // To avoid duplication of (header/footer)content nodes for simple page desc changes
+ void ExchangeContentNodes( SwPageDesc& rSource, SwPageDesc &rDest );
+
+public:
+ SwUndoPageDesc(const SwPageDesc & aOld, const SwPageDesc & aNew,
+ SwDoc * pDoc);
+ virtual ~SwUndoPageDesc();
+
+ virtual void UndoImpl( ::sw::UndoRedoContext & );
+ virtual void RedoImpl( ::sw::UndoRedoContext & );
+
+ virtual SwRewriter GetRewriter() const;
+};
+
+class SwUndoPageDescCreate : public SwUndo
+{
+ const SwPageDesc * pDesc;
+ SwPageDescExt aNew;
+ SwDoc * pDoc;
+
+ void DoImpl();
+
+public:
+ SwUndoPageDescCreate(const SwPageDesc * pNew, SwDoc * pDoc);
+ virtual ~SwUndoPageDescCreate();
+
+ virtual void UndoImpl( ::sw::UndoRedoContext & );
+ virtual void RedoImpl( ::sw::UndoRedoContext & );
+ virtual void RepeatImpl( ::sw::RepeatContext & );
+
+ virtual SwRewriter GetRewriter() const;
+};
+
+class SwUndoPageDescDelete : public SwUndo
+{
+ SwPageDescExt aOld;
+ SwDoc * pDoc;
+
+ void DoImpl();
+
+public:
+ SwUndoPageDescDelete(const SwPageDesc & aOld, SwDoc * pDoc);
+ virtual ~SwUndoPageDescDelete();
+
+ virtual void UndoImpl( ::sw::UndoRedoContext & );
+ virtual void RedoImpl( ::sw::UndoRedoContext & );
+ virtual void RepeatImpl( ::sw::RepeatContext & );
+
+ virtual SwRewriter GetRewriter() const;
+};
+#endif // _SW_UNDO_PAGE_DESC_CHANGE_HXX
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/inc/SwUndoTOXChange.hxx b/sw/source/core/inc/SwUndoTOXChange.hxx
new file mode 100644
index 000000000000..a661ab5de571
--- /dev/null
+++ b/sw/source/core/inc/SwUndoTOXChange.hxx
@@ -0,0 +1,52 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+#ifndef SW_UNDO_TOX_CHANGE_HXX
+#define SW_UNDO_TOX_CHANGE_HXX
+
+#include <undobj.hxx>
+#include <tox.hxx>
+
+class SwUndoTOXChange : public SwUndo
+{
+ SwTOXBase * pTOX, aOld, aNew;
+
+ void UpdateTOXBaseSection();
+ void DoImpl();
+
+public:
+ SwUndoTOXChange(SwTOXBase * pTOX, const SwTOXBase & rNew);
+ virtual ~SwUndoTOXChange();
+
+ virtual void UndoImpl( ::sw::UndoRedoContext & );
+ virtual void RedoImpl( ::sw::UndoRedoContext & );
+ virtual void RepeatImpl( ::sw::RepeatContext & );
+};
+
+#endif // SW_UNDO_TOX_CHANGE_HXX
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/inc/SwXMLBlockExport.hxx b/sw/source/core/inc/SwXMLBlockExport.hxx
new file mode 100644
index 000000000000..8d02e47a4e8f
--- /dev/null
+++ b/sw/source/core/inc/SwXMLBlockExport.hxx
@@ -0,0 +1,76 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+#ifndef _SW_XMLBLOCKEXPORT_HXX
+#define _SW_XMLBLOCKEXPORT_HXX
+
+#include <xmloff/xmlexp.hxx>
+
+class String;
+class SwXMLTextBlocks;
+
+class SwXMLBlockListExport : public SvXMLExport
+{
+private:
+ SwXMLTextBlocks &rBlockList;
+public:
+ // #110680#
+ SwXMLBlockListExport(
+ const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory > xServiceFactory,
+ SwXMLTextBlocks & rBlocks,
+ const rtl::OUString &rFileName,
+ com::sun::star::uno::Reference< com::sun::star::xml::sax::XDocumentHandler> &rHandler);
+
+ virtual ~SwXMLBlockListExport ( void ) {}
+ sal_uInt32 exportDoc( enum ::xmloff::token::XMLTokenEnum eClass);
+ void _ExportAutoStyles() {}
+ void _ExportMasterStyles () {}
+ void _ExportContent() {}
+};
+
+class SwXMLTextBlockExport : public SvXMLExport
+{
+private:
+ SwXMLTextBlocks &rBlockList;
+public:
+ // #110680#
+ SwXMLTextBlockExport(
+ const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory > xServiceFactory,
+ SwXMLTextBlocks & rBlocks,
+ const rtl::OUString &rFileName,
+ com::sun::star::uno::Reference< com::sun::star::xml::sax::XDocumentHandler> &rHandler);
+
+ virtual ~SwXMLTextBlockExport ( void ) {}
+ sal_uInt32 exportDoc(enum ::xmloff::token::XMLTokenEnum /*eClass*/) {return 0;}
+ sal_uInt32 exportDoc(const String & rText);
+ void _ExportAutoStyles() {}
+ void _ExportMasterStyles () {}
+ void _ExportContent() {}
+};
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/inc/SwXMLBlockImport.hxx b/sw/source/core/inc/SwXMLBlockImport.hxx
new file mode 100644
index 000000000000..4d37e9b417ee
--- /dev/null
+++ b/sw/source/core/inc/SwXMLBlockImport.hxx
@@ -0,0 +1,92 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+#ifndef _SW_XMLBLOCKIMPORT_HXX
+#define _SW_XMLBLOCKIMPORT_HXX
+
+#include <xmloff/xmlimp.hxx>
+
+class SwXMLTextBlocks;
+class SwXMLBlockListImport : public SvXMLImport
+{
+private:
+ SwXMLTextBlocks &rBlockList;
+protected:
+
+ // This method is called after the namespace map has been updated, but
+ // before a context for the current element has been pushed.
+ virtual SvXMLImportContext *CreateContext( sal_uInt16 nPrefix,
+ const ::rtl::OUString& rLocalName,
+ const ::com::sun::star::uno::Reference<
+ ::com::sun::star::xml::sax::XAttributeList > & xAttrList );
+public:
+ // #110680#
+ SwXMLBlockListImport(
+ const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory > xServiceFactory,
+ SwXMLTextBlocks &rBlocks );
+
+ SwXMLTextBlocks& getBlockList ( void )
+ {
+ return rBlockList;
+ }
+ virtual ~SwXMLBlockListImport ( void )
+ throw();
+};
+
+class SwXMLTextBlockImport : public SvXMLImport
+{
+private:
+ SwXMLTextBlocks &rBlockList;
+protected:
+
+ // This method is called after the namespace map has been updated, but
+ // before a context for the current element has been pushed.
+ virtual SvXMLImportContext *CreateContext( sal_uInt16 nPrefix,
+ const ::rtl::OUString& rLocalName,
+ const ::com::sun::star::uno::Reference<
+ ::com::sun::star::xml::sax::XAttributeList > & xAttrList );
+public:
+ sal_Bool bTextOnly;
+ String &m_rText;
+
+ // #110680#
+ SwXMLTextBlockImport(
+ const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory > xServiceFactory,
+ SwXMLTextBlocks &rBlocks, String &rNewText, sal_Bool bNewTextOnly );
+
+ SwXMLTextBlocks& getBlockList ( void )
+ {
+ return rBlockList;
+ }
+ virtual ~SwXMLTextBlockImport ( void )
+ throw();
+ virtual void SAL_CALL endDocument(void)
+ throw( ::com::sun::star::xml::sax::SAXException, ::com::sun::star::uno::RuntimeException );
+};
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/inc/SwXMLBlockListContext.hxx b/sw/source/core/inc/SwXMLBlockListContext.hxx
new file mode 100644
index 000000000000..64c9dbb8c0e9
--- /dev/null
+++ b/sw/source/core/inc/SwXMLBlockListContext.hxx
@@ -0,0 +1,129 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+#ifndef _SW_XMLBLOCKLISTCONTEXT_HXX
+#define _SW_XMLBLOCKLISTCONTEXT_HXX
+
+#include <xmloff/xmlictxt.hxx>
+
+class SwXMLBlockListImport;
+class SwXMLTextBlockImport;
+
+class SwXMLBlockListContext : public SvXMLImportContext
+{
+private:
+ SwXMLBlockListImport & rLocalRef;
+public:
+ SwXMLBlockListContext( SwXMLBlockListImport& rImport,
+ sal_uInt16 nPrefix,
+ const rtl::OUString& rLocalName,
+ const ::com::sun::star::uno::Reference<
+ ::com::sun::star::xml::sax::XAttributeList > & xAttrList );
+ ~SwXMLBlockListContext ( void );
+ virtual SvXMLImportContext *CreateChildContext( sal_uInt16 nPrefix,
+ const rtl::OUString& rLocalName,
+ const ::com::sun::star::uno::Reference<
+ ::com::sun::star::xml::sax::XAttributeList > & xAttrList );
+
+};
+class SwXMLBlockContext : public SvXMLImportContext
+{
+private:
+ SwXMLBlockListImport & rLocalRef;
+public:
+ SwXMLBlockContext( SwXMLBlockListImport& rImport,
+ sal_uInt16 nPrefix,
+ const rtl::OUString& rLocalName,
+ const ::com::sun::star::uno::Reference<
+ ::com::sun::star::xml::sax::XAttributeList > & xAttrList );
+ ~SwXMLBlockContext ( void );
+};
+
+class SwXMLTextBlockDocumentContext : public SvXMLImportContext
+{
+private:
+ SwXMLTextBlockImport & rLocalRef;
+public:
+ SwXMLTextBlockDocumentContext( SwXMLTextBlockImport& rImport,
+ sal_uInt16 nPrefix,
+ const rtl::OUString& rLocalName,
+ const ::com::sun::star::uno::Reference<
+ ::com::sun::star::xml::sax::XAttributeList > & xAttrList );
+ virtual SvXMLImportContext *CreateChildContext( sal_uInt16 nPrefix,
+ const rtl::OUString& rLocalName,
+ const ::com::sun::star::uno::Reference<
+ ::com::sun::star::xml::sax::XAttributeList > & xAttrList );
+ ~SwXMLTextBlockDocumentContext ( void );
+};
+class SwXMLTextBlockBodyContext : public SvXMLImportContext
+{
+private:
+ SwXMLTextBlockImport & rLocalRef;
+public:
+ SwXMLTextBlockBodyContext( SwXMLTextBlockImport& rImport,
+ sal_uInt16 nPrefix,
+ const rtl::OUString& rLocalName,
+ const ::com::sun::star::uno::Reference<
+ ::com::sun::star::xml::sax::XAttributeList > & xAttrList );
+ virtual SvXMLImportContext *CreateChildContext( sal_uInt16 nPrefix,
+ const rtl::OUString& rLocalName,
+ const ::com::sun::star::uno::Reference<
+ ::com::sun::star::xml::sax::XAttributeList > & xAttrList );
+ ~SwXMLTextBlockBodyContext ( void );
+};
+class SwXMLTextBlockTextContext : public SvXMLImportContext
+{
+private:
+ SwXMLTextBlockImport & rLocalRef;
+public:
+ SwXMLTextBlockTextContext( SwXMLTextBlockImport& rImport,
+ sal_uInt16 nPrefix,
+ const rtl::OUString& rLocalName,
+ const ::com::sun::star::uno::Reference<
+ ::com::sun::star::xml::sax::XAttributeList > & xAttrList );
+ virtual SvXMLImportContext *CreateChildContext( sal_uInt16 nPrefix,
+ const rtl::OUString& rLocalName,
+ const ::com::sun::star::uno::Reference<
+ ::com::sun::star::xml::sax::XAttributeList > & xAttrList );
+ ~SwXMLTextBlockTextContext ( void );
+};
+class SwXMLTextBlockParContext : public SvXMLImportContext
+{
+private:
+ SwXMLTextBlockImport & rLocalRef;
+public:
+ SwXMLTextBlockParContext( SwXMLTextBlockImport& rImport,
+ sal_uInt16 nPrefix,
+ const rtl::OUString& rLocalName,
+ const ::com::sun::star::uno::Reference<
+ ::com::sun::star::xml::sax::XAttributeList > & xAttrList );
+ virtual void Characters( const ::rtl::OUString& rChars );
+ ~SwXMLTextBlockParContext ( void );
+};
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/inc/SwXMLTextBlocks.hxx b/sw/source/core/inc/SwXMLTextBlocks.hxx
new file mode 100644
index 000000000000..c87b08d77360
--- /dev/null
+++ b/sw/source/core/inc/SwXMLTextBlocks.hxx
@@ -0,0 +1,114 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+#ifndef _SW_XMLTEXTBLOCKS_HXX
+#define _SW_XMLTEXTBLOCKS_HXX
+#include <sfx2/objsh.hxx>
+#include <sfx2/docfile.hxx>
+#include <swblocks.hxx>
+
+class SfxMedium;
+class SwPaM;
+class SwDoc;
+class SvxMacroTableDtor;
+class SwImpBlocks;
+
+#define SWXML_CONVBLOCK 0x0001
+#define SWXML_NOROOTCOMMIT 0x0002
+
+class SwXMLTextBlocks : public SwImpBlocks
+{
+protected:
+ sal_Bool bAutocorrBlock;
+ sal_Bool bBlock;
+ SfxObjectShellRef xDocShellRef;
+ sal_uInt16 nFlags;
+ String aPackageName;
+ SfxMediumRef xMedium;
+
+ void ReadInfo();
+ void WriteInfo();
+ void InitBlockMode ( const com::sun::star::uno::Reference < com::sun::star::embed::XStorage >& rStorage );
+ void ResetBlockMode();
+
+public:
+ com::sun::star::uno::Reference < com::sun::star::embed::XStorage > xBlkRoot;
+ com::sun::star::uno::Reference < com::sun::star::embed::XStorage > xRoot;
+ short nCurBlk;
+ SwXMLTextBlocks( const String& rFile );
+ SwXMLTextBlocks( const com::sun::star::uno::Reference < com::sun::star::embed::XStorage >&, const String& rFile );
+ void AddName( const String&, const String&, const String&, sal_Bool bOnlyTxt = sal_False );
+ virtual void AddName( const String&, const String&, sal_Bool bOnlyTxt = sal_False );
+ void GeneratePackageName ( const String& rShort, String& rPackageName );
+ virtual ~SwXMLTextBlocks();
+ //virtual sal_Bool IsOld() const;
+ virtual sal_uLong Delete( sal_uInt16 );
+ virtual sal_uLong Rename( sal_uInt16, const String&, const String& );
+ virtual sal_uLong CopyBlock( SwImpBlocks& rImp, String& rShort, const String& rLong);
+ virtual void ClearDoc();
+ virtual sal_uLong GetDoc( sal_uInt16 );
+ virtual sal_uLong BeginPutDoc( const String&, const String& );
+ virtual sal_uLong PutDoc();
+ virtual sal_uLong GetText( sal_uInt16, String& );
+ virtual sal_uLong PutText( const String&, const String&, const String& );
+ virtual sal_uLong MakeBlockList();
+
+ virtual short GetFileType ( void ) const;
+ virtual sal_uLong OpenFile( sal_Bool bReadOnly = sal_True );
+ virtual void CloseFile();
+
+ static sal_Bool IsFileUCBStorage( const String & rFileName);
+
+ // Methods for the new Autocorrecter
+ sal_uLong GetText( const String& rShort, String& );
+
+ virtual sal_Bool IsOnlyTextBlock( const String& rShort ) const;
+ virtual sal_Bool IsOnlyTextBlock( sal_uInt16 nIdx ) const;
+ virtual void SetIsTextOnly( const String& rShort, sal_Bool bNewValue );
+ virtual void SetIsTextOnly( sal_uInt16 nIdx, sal_Bool bNewValue );
+
+ virtual sal_uLong GetMacroTable( sal_uInt16, SvxMacroTableDtor& rMacroTbl,
+ sal_Bool bFileAlreadyOpen = sal_False );
+ virtual sal_uLong SetMacroTable( sal_uInt16 nIdx,
+ const SvxMacroTableDtor& rMacroTable,
+ sal_Bool bFileAlreadyOpen = sal_False );
+ virtual sal_Bool PutMuchEntries( sal_Bool bOn );
+
+public:
+ SwDoc* GetDoc() const { return pDoc; }
+ //void SetDoc( SwDoc * pNewDoc);
+ sal_uLong StartPutBlock( const String& rShort, const String& rPackageName );
+ sal_uLong PutBlock( SwPaM& rPaM, const String& rLong );
+ sal_uLong GetBlockText( const String& rShort, String& rText );
+ sal_uLong PutBlockText( const String& rShort, const String& rName, const String& rText, const String& rPackageName );
+ void MakeBlockText( const String& rText );
+
+};
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/inc/SwXTextDefaults.hxx b/sw/source/core/inc/SwXTextDefaults.hxx
new file mode 100644
index 000000000000..931ed54006bf
--- /dev/null
+++ b/sw/source/core/inc/SwXTextDefaults.hxx
@@ -0,0 +1,85 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+#ifndef _SW_XTEXT_DEFAULTS_HXX
+#define _SW_XTEXT_DEFAULTS_HXX
+#include <cppuhelper/implbase3.hxx>
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/beans/XPropertyState.hpp>
+
+#include <com/sun/star/lang/XServiceInfo.hpp>
+#include <svl/itemprop.hxx>
+
+class SwDoc;
+
+class SwXTextDefaults : public cppu::WeakImplHelper3
+ <
+ com::sun::star::beans::XPropertyState,
+ com::sun::star::beans::XPropertySet,
+ com::sun::star::lang::XServiceInfo
+ >
+{
+ const SfxItemPropertySet* m_pPropSet;
+ SwDoc * m_pDoc;
+public:
+ SwXTextDefaults ( SwDoc * pNewDoc );
+ ~SwXTextDefaults ();
+
+ // XPropertySet
+ virtual ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySetInfo > SAL_CALL getPropertySetInfo( )
+ throw(::com::sun::star::uno::RuntimeException);
+ virtual void SAL_CALL setPropertyValue( const ::rtl::OUString& rPropertyName, const ::com::sun::star::uno::Any& aValue )
+ throw(::com::sun::star::beans::UnknownPropertyException, ::com::sun::star::beans::PropertyVetoException, ::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::lang::WrappedTargetException, ::com::sun::star::uno::RuntimeException);
+ virtual ::com::sun::star::uno::Any SAL_CALL getPropertyValue( const ::rtl::OUString& rPropertyName )
+ throw(::com::sun::star::beans::UnknownPropertyException, ::com::sun::star::lang::WrappedTargetException, ::com::sun::star::uno::RuntimeException);
+ virtual void SAL_CALL addPropertyChangeListener( const ::rtl::OUString& rPropertyName, const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertyChangeListener >& xListener )
+ throw(::com::sun::star::beans::UnknownPropertyException, ::com::sun::star::lang::WrappedTargetException, ::com::sun::star::uno::RuntimeException);
+ virtual void SAL_CALL removePropertyChangeListener( const ::rtl::OUString& rPropertyName, const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertyChangeListener >& aListener )
+ throw(::com::sun::star::beans::UnknownPropertyException, ::com::sun::star::lang::WrappedTargetException, ::com::sun::star::uno::RuntimeException);
+ virtual void SAL_CALL addVetoableChangeListener( const ::rtl::OUString& rPropertyName, const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XVetoableChangeListener >& aListener )
+ throw(::com::sun::star::beans::UnknownPropertyException, ::com::sun::star::lang::WrappedTargetException, ::com::sun::star::uno::RuntimeException);
+ virtual void SAL_CALL removeVetoableChangeListener( const ::rtl::OUString& rPropertyName, const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XVetoableChangeListener >& aListener )
+ throw(::com::sun::star::beans::UnknownPropertyException, ::com::sun::star::lang::WrappedTargetException, ::com::sun::star::uno::RuntimeException);
+
+ // XPropertyState
+ virtual ::com::sun::star::beans::PropertyState SAL_CALL getPropertyState( const ::rtl::OUString& rPropertyName )
+ throw(::com::sun::star::beans::UnknownPropertyException, ::com::sun::star::uno::RuntimeException);
+ virtual ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyState > SAL_CALL getPropertyStates( const ::com::sun::star::uno::Sequence< ::rtl::OUString >& rPropertyNames )
+ throw(::com::sun::star::beans::UnknownPropertyException, ::com::sun::star::uno::RuntimeException);
+ virtual void SAL_CALL setPropertyToDefault( const ::rtl::OUString& rPropertyName )
+ throw(::com::sun::star::beans::UnknownPropertyException, ::com::sun::star::uno::RuntimeException);
+ virtual ::com::sun::star::uno::Any SAL_CALL getPropertyDefault( const ::rtl::OUString& rPropertyName )
+ throw(::com::sun::star::beans::UnknownPropertyException, ::com::sun::star::lang::WrappedTargetException, ::com::sun::star::uno::RuntimeException);
+
+ // XServiceInfo
+ virtual ::rtl::OUString SAL_CALL getImplementationName( ) throw (::com::sun::star::uno::RuntimeException);
+ virtual sal_Bool SAL_CALL supportsService( const ::rtl::OUString& ServiceName ) throw (::com::sun::star::uno::RuntimeException);
+ virtual ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL getSupportedServiceNames( ) throw (::com::sun::star::uno::RuntimeException);
+};
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/inc/UndoAttribute.hxx b/sw/source/core/inc/UndoAttribute.hxx
new file mode 100644
index 000000000000..849603e2b534
--- /dev/null
+++ b/sw/source/core/inc/UndoAttribute.hxx
@@ -0,0 +1,288 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef SW_UNDO_ATTRIBUTE_HXX
+#define SW_UNDO_ATTRIBUTE_HXX
+
+#include <undobj.hxx>
+
+#include <memory>
+
+#ifndef _SVSTDARR_HXX
+#define _SVSTDARR_USHORTS
+#define _SVSTDARR_ULONGS
+#define _SVSTDARR_BOOLS
+#define _SVSTDARR_BYTES
+#define _SVSTDARR_USHORTSSORT
+#include <svl/svstdarr.hxx>
+#endif
+#include <svl/itemset.hxx>
+
+#include <swtypes.hxx>
+#include <calbck.hxx>
+
+
+class SvxTabStopItem;
+class SwFmt;
+class SwFtnInfo;
+class SwEndNoteInfo;
+
+
+class SwUndoAttr : public SwUndo, private SwUndRng
+{
+ SfxItemSet m_AttrSet; // attributes for Redo
+ const ::std::auto_ptr<SwHistory> m_pHistory; // History for Undo
+ ::std::auto_ptr<SwRedlineData> m_pRedlineData; // Redlining
+ ::std::auto_ptr<SwRedlineSaveDatas> m_pRedlineSaveData;
+ sal_uLong m_nNodeIndex; // Offset: for Redlining
+ const SetAttrMode m_nInsertFlags; // insert flags
+
+ void RemoveIdx( SwDoc& rDoc );
+
+public:
+ SwUndoAttr( const SwPaM&, const SfxItemSet &, const SetAttrMode nFlags );
+ SwUndoAttr( const SwPaM&, const SfxPoolItem&, const SetAttrMode nFlags );
+
+ virtual ~SwUndoAttr();
+
+ virtual void UndoImpl( ::sw::UndoRedoContext & );
+ virtual void RedoImpl( ::sw::UndoRedoContext & );
+ virtual void RepeatImpl( ::sw::RepeatContext & );
+
+ void SaveRedlineData( const SwPaM& rPam, sal_Bool bInsCntnt );
+
+ SwHistory& GetHistory() { return *m_pHistory; }
+
+};
+
+class SwUndoResetAttr : public SwUndo, private SwUndRng
+{
+ const ::std::auto_ptr<SwHistory> m_pHistory;
+ SvUShortsSort m_Ids;
+ const sal_uInt16 m_nFormatId; // Format-Id for Redo
+
+public:
+ SwUndoResetAttr( const SwPaM&, sal_uInt16 nFmtId );
+ SwUndoResetAttr( const SwPosition&, sal_uInt16 nFmtId );
+
+ virtual ~SwUndoResetAttr();
+
+ virtual void UndoImpl( ::sw::UndoRedoContext & );
+ virtual void RedoImpl( ::sw::UndoRedoContext & );
+ virtual void RepeatImpl( ::sw::RepeatContext & );
+
+ void SetAttrs( const SvUShortsSort& rArr );
+
+ SwHistory& GetHistory() { return *m_pHistory; }
+
+};
+
+class SwUndoFmtAttr : public SwUndo
+{
+ friend class SwUndoDefaultAttr;
+ SwFmt * m_pFmt;
+ ::std::auto_ptr<SfxItemSet> m_pOldSet; // old attributes
+ sal_uLong m_nNodeIndex;
+ const sal_uInt16 m_nFmtWhich;
+ const bool m_bSaveDrawPt;
+
+ bool IsFmtInDoc( SwDoc* ); //is the attribute format still in the Doc?
+ void SaveFlyAnchor( bool bSaveDrawPt = false );
+ // --> OD 2004-10-26 #i35443# - Add return value, type <bool>.
+ // Return value indicates, if anchor attribute is restored.
+ // Notes: - If anchor attribute is restored, all other existing attributes
+ // are also restored.
+ // - Anchor attribute isn't restored successfully, if it contains
+ // an invalid anchor position and all other existing attributes
+ // aren't restored.
+ // This situation occurs for undo of styles.
+ bool RestoreFlyAnchor(::sw::UndoRedoContext & rContext);
+ // <--
+ // --> OD 2008-02-27 #refactorlists# - removed <rAffectedItemSet>
+ void Init();
+ // <--
+
+public:
+ // register at the Format and save old attributes
+ // --> OD 2008-02-27 #refactorlists# - removed <rNewSet>
+ SwUndoFmtAttr( const SfxItemSet& rOldSet,
+ SwFmt& rFmt,
+ bool bSaveDrawPt = true );
+ // <--
+ SwUndoFmtAttr( const SfxPoolItem& rItem,
+ SwFmt& rFmt,
+ bool bSaveDrawPt = true );
+
+ virtual ~SwUndoFmtAttr();
+
+ virtual void UndoImpl( ::sw::UndoRedoContext & );
+ virtual void RedoImpl( ::sw::UndoRedoContext & );
+ virtual void RepeatImpl( ::sw::RepeatContext & );
+
+ virtual SwRewriter GetRewriter() const;
+
+ void PutAttr( const SfxPoolItem& rItem );
+ SwFmt* GetFmt( SwDoc& rDoc ); // checks if it is still in the Doc!
+};
+
+// --> OD 2008-02-12 #newlistlevelattrs#
+class SwUndoFmtResetAttr : public SwUndo
+{
+ public:
+ SwUndoFmtResetAttr( SwFmt& rChangedFormat,
+ const sal_uInt16 nWhichId );
+ ~SwUndoFmtResetAttr();
+
+ virtual void UndoImpl( ::sw::UndoRedoContext & );
+ virtual void RedoImpl( ::sw::UndoRedoContext & );
+
+ private:
+ // format at which a certain attribute is reset.
+ SwFmt * const m_pChangedFormat;
+ // which ID of the reset attribute
+ const sal_uInt16 m_nWhichId;
+ // old attribute which has been reset - needed for undo.
+ ::std::auto_ptr<SfxPoolItem> m_pOldItem;
+};
+// <--
+
+class SwUndoDontExpandFmt : public SwUndo
+{
+ const sal_uLong m_nNodeIndex;
+ const xub_StrLen m_nContentIndex;
+
+public:
+ SwUndoDontExpandFmt( const SwPosition& rPos );
+
+ virtual void UndoImpl( ::sw::UndoRedoContext & );
+ virtual void RedoImpl( ::sw::UndoRedoContext & );
+ virtual void RepeatImpl( ::sw::RepeatContext & );
+};
+
+// helper class to receive changed attribute sets
+class SwUndoFmtAttrHelper : public SwClient
+{
+ ::std::auto_ptr<SwUndoFmtAttr> m_pUndo;
+ const bool m_bSaveDrawPt;
+
+public:
+ SwUndoFmtAttrHelper( SwFmt& rFmt, bool bSaveDrawPt = true );
+
+ virtual void Modify( const SfxPoolItem*, const SfxPoolItem* );
+
+ SwUndoFmtAttr* GetUndo() const { return m_pUndo.get(); }
+ // release the undo object (so it is not deleted here), and return it
+ SwUndoFmtAttr* ReleaseUndo() { return m_pUndo.release(); }
+};
+
+
+class SwUndoMoveLeftMargin : public SwUndo, private SwUndRng
+{
+ const ::std::auto_ptr<SwHistory> m_pHistory;
+ const bool m_bModulus;
+
+public:
+ SwUndoMoveLeftMargin( const SwPaM&, sal_Bool bRight, sal_Bool bModulus );
+
+ virtual ~SwUndoMoveLeftMargin();
+
+ virtual void UndoImpl( ::sw::UndoRedoContext & );
+ virtual void RedoImpl( ::sw::UndoRedoContext & );
+ virtual void RepeatImpl( ::sw::RepeatContext & );
+
+ SwHistory& GetHistory() { return *m_pHistory; }
+
+};
+
+
+//--------------------------------------------------------------------
+
+class SwUndoDefaultAttr : public SwUndo
+{
+ ::std::auto_ptr<SfxItemSet> m_pOldSet; // the old attributes
+ ::std::auto_ptr<SvxTabStopItem> m_pTabStop;
+
+public:
+ // registers at the format and saves old attributes
+ SwUndoDefaultAttr( const SfxItemSet& rOldSet );
+
+ virtual ~SwUndoDefaultAttr();
+
+ virtual void UndoImpl( ::sw::UndoRedoContext & );
+ virtual void RedoImpl( ::sw::UndoRedoContext & );
+};
+
+
+//--------------------------------------------------------------------
+
+class SwUndoChangeFootNote : public SwUndo, private SwUndRng
+{
+ const ::std::auto_ptr<SwHistory> m_pHistory;
+ const String m_Text;
+ const sal_uInt16 m_nNumber;
+ const bool m_bEndNote;
+
+public:
+ SwUndoChangeFootNote( const SwPaM& rRange, const String& rTxt,
+ sal_uInt16 nNum, bool bIsEndNote );
+ virtual ~SwUndoChangeFootNote();
+
+ virtual void UndoImpl( ::sw::UndoRedoContext & );
+ virtual void RedoImpl( ::sw::UndoRedoContext & );
+ virtual void RepeatImpl( ::sw::RepeatContext & );
+
+ SwHistory& GetHistory() { return *m_pHistory; }
+};
+
+class SwUndoFootNoteInfo : public SwUndo
+{
+ ::std::auto_ptr<SwFtnInfo> m_pFootNoteInfo;
+
+public:
+ SwUndoFootNoteInfo( const SwFtnInfo &rInfo );
+
+ virtual ~SwUndoFootNoteInfo();
+
+ virtual void UndoImpl( ::sw::UndoRedoContext & );
+ virtual void RedoImpl( ::sw::UndoRedoContext & );
+};
+
+class SwUndoEndNoteInfo : public SwUndo
+{
+ ::std::auto_ptr<SwEndNoteInfo> m_pEndNoteInfo;
+
+public:
+ SwUndoEndNoteInfo( const SwEndNoteInfo &rInfo );
+
+ virtual ~SwUndoEndNoteInfo();
+
+ virtual void UndoImpl( ::sw::UndoRedoContext & );
+ virtual void RedoImpl( ::sw::UndoRedoContext & );
+};
+
+#endif // SW_UNDO_ATTRIBUTE_HXX
+
diff --git a/sw/source/core/inc/UndoBookmark.hxx b/sw/source/core/inc/UndoBookmark.hxx
new file mode 100644
index 000000000000..87d774d0c43e
--- /dev/null
+++ b/sw/source/core/inc/UndoBookmark.hxx
@@ -0,0 +1,83 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef SW_UNDO_BOOKMARK_HXX
+#define SW_UNDO_BOOKMARK_HXX
+
+#include <undobj.hxx>
+
+
+class SwHistoryBookmark;
+
+namespace sw {
+ namespace mark {
+ class IMark;
+ }
+}
+
+
+class SwUndoBookmark : public SwUndo
+{
+ const ::std::auto_ptr<SwHistoryBookmark> m_pHistoryBookmark;
+
+protected:
+ SwUndoBookmark( SwUndoId nUndoId, const ::sw::mark::IMark& );
+
+ void SetInDoc( SwDoc* );
+ void ResetInDoc( SwDoc* );
+
+public:
+ virtual ~SwUndoBookmark();
+
+ // #111827#
+ /**
+ Returns the rewriter for this undo object.
+
+ The rewriter contains the following rule:
+
+ $1 -> <name of bookmark>
+
+ <name of bookmark> is the name of the bookmark whose
+ insertion/deletion is recorded by this undo object.
+
+ @return the rewriter for this undo object
+ */
+ virtual SwRewriter GetRewriter() const;
+};
+
+
+class SwUndoInsBookmark : public SwUndoBookmark
+{
+public:
+ SwUndoInsBookmark( const ::sw::mark::IMark& );
+
+ virtual void UndoImpl( ::sw::UndoRedoContext & );
+ virtual void RedoImpl( ::sw::UndoRedoContext & );
+};
+
+#endif // SW_UNDO_BOOKMARK_HXX
+
diff --git a/sw/source/core/inc/UndoCore.hxx b/sw/source/core/inc/UndoCore.hxx
new file mode 100644
index 000000000000..35abb46f7cf7
--- /dev/null
+++ b/sw/source/core/inc/UndoCore.hxx
@@ -0,0 +1,266 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef SW_UNDOCORE_HXX
+#define SW_UNDOCORE_HXX
+
+#include <undobj.hxx>
+
+#include <calbck.hxx>
+
+
+class SfxItemSet;
+class SwFmtColl;
+class SwFmtAnchor;
+class SdrMarkList;
+class SwUndoDelete;
+class SwRedlineSaveData;
+class SwFrm;
+class SwFmt;
+
+namespace sw {
+ class UndoManager;
+ class IShellCursorSupplier;
+}
+
+
+typedef SwRedlineSaveData* SwRedlineSaveDataPtr;
+SV_DECL_PTRARR_DEL( SwRedlineSaveDatas, SwRedlineSaveDataPtr, 8, 8 )
+
+
+namespace sw {
+
+class SW_DLLPRIVATE UndoRedoContext
+ : public SfxUndoContext
+{
+public:
+ UndoRedoContext(SwDoc & rDoc, IShellCursorSupplier & rCursorSupplier)
+ : m_rDoc(rDoc)
+ , m_rCursorSupplier(rCursorSupplier)
+ , m_pSelFmt(0)
+ , m_pMarkList(0)
+ { }
+
+ SwDoc & GetDoc() const { return m_rDoc; }
+
+ IShellCursorSupplier & GetCursorSupplier() { return m_rCursorSupplier; }
+
+ void SetSelections(SwFrmFmt *const pSelFmt, SdrMarkList *const pMarkList)
+ {
+ m_pSelFmt = pSelFmt;
+ m_pMarkList = pMarkList;
+ }
+ void GetSelections(SwFrmFmt *& o_rpSelFmt, SdrMarkList *& o_rpMarkList)
+ {
+ o_rpSelFmt = m_pSelFmt;
+ o_rpMarkList = m_pMarkList;
+ }
+
+private:
+ SwDoc & m_rDoc;
+ IShellCursorSupplier & m_rCursorSupplier;
+ SwFrmFmt * m_pSelFmt;
+ SdrMarkList * m_pMarkList;
+};
+
+class SW_DLLPRIVATE RepeatContext
+ : public SfxRepeatTarget
+{
+public:
+ RepeatContext(SwDoc & rDoc, SwPaM & rPaM)
+ : m_rDoc(rDoc)
+ , m_pCurrentPaM(& rPaM)
+ , m_bDeleteRepeated(false)
+ { }
+
+ SwDoc & GetDoc() const { return m_rDoc; }
+
+ SwPaM & GetRepeatPaM()
+ {
+ return *m_pCurrentPaM;
+ }
+
+private:
+ friend class ::sw::UndoManager;
+ friend class ::SwUndoDelete;
+
+ SwDoc & m_rDoc;
+ SwPaM * m_pCurrentPaM;
+ bool m_bDeleteRepeated; /// has a delete action been repeated?
+};
+
+} // namespace sw
+
+
+
+class SwUndoFmtColl : public SwUndo, private SwUndRng
+{
+ String aFmtName;
+ SwHistory* pHistory;
+ SwFmtColl* pFmtColl;
+ // --> OD 2008-04-15 #refactorlists# - for correct <ReDo(..)> and <Repeat(..)>
+ // boolean, which indicates that the attributes are reseted at the nodes
+ // before the format has been applied.
+ const bool mbReset;
+ // boolean, which indicates that the list attributes had been reseted at
+ // the nodes before the format has been applied.
+ const bool mbResetListAttrs;
+ // <--
+
+ void DoSetFmtColl(SwDoc & rDoc, SwPaM & rPaM);
+
+public:
+ // --> OD 2008-04-15 #refactorlists#
+// SwUndoFmtColl( const SwPaM&, SwFmtColl* );
+ SwUndoFmtColl( const SwPaM&, SwFmtColl*,
+ const bool bReset,
+ const bool bResetListAttrs );
+ // <--
+ virtual ~SwUndoFmtColl();
+
+ virtual void UndoImpl( ::sw::UndoRedoContext & );
+ virtual void RedoImpl( ::sw::UndoRedoContext & );
+ virtual void RepeatImpl( ::sw::RepeatContext & );
+
+ // #111827#
+ /**
+ Returns the rewriter for this undo object.
+
+ The rewriter contains one rule:
+
+ $1 -> <name of format collection>
+
+ <name of format collection> is the name of the format
+ collection that is applied by the action recorded by this undo
+ object.
+
+ @return the rewriter for this undo object
+ */
+ virtual SwRewriter GetRewriter() const;
+
+ SwHistory* GetHistory() { return pHistory; }
+
+};
+
+
+class SwUndoSetFlyFmt : public SwUndo, public SwClient
+{
+ SwFrmFmt* pFrmFmt; // das gespeicherte FlyFormat
+ SwFrmFmt* pOldFmt; // die alte Fly Vorlage
+ SwFrmFmt* pNewFmt; // die neue Fly Vorlage
+ SfxItemSet* pItemSet; // die zurueck-/ gesetzten Attribute
+ sal_uLong nOldNode, nNewNode;
+ xub_StrLen nOldCntnt, nNewCntnt;
+ sal_uInt16 nOldAnchorTyp, nNewAnchorTyp;
+ sal_Bool bAnchorChgd;
+
+ void PutAttr( sal_uInt16 nWhich, const SfxPoolItem* pItem );
+ void Modify( const SfxPoolItem*, const SfxPoolItem* );
+ void GetAnchor( SwFmtAnchor& rAnhor, sal_uLong nNode, xub_StrLen nCntnt );
+
+public:
+ SwUndoSetFlyFmt( SwFrmFmt& rFlyFmt, SwFrmFmt& rNewFrmFmt );
+ virtual ~SwUndoSetFlyFmt();
+
+ virtual void UndoImpl( ::sw::UndoRedoContext & );
+ virtual void RedoImpl( ::sw::UndoRedoContext & );
+
+ virtual SwRewriter GetRewriter() const;
+ void DeRegisterFromFormat( SwFmt& );
+};
+
+
+//------------ Undo von verschieben/stufen von Gliederung ----------------
+
+class SwUndoOutlineLeftRight : public SwUndo, private SwUndRng
+{
+ short nOffset;
+public:
+ SwUndoOutlineLeftRight( const SwPaM& rPam, short nOffset );
+
+ virtual void UndoImpl( ::sw::UndoRedoContext & );
+ virtual void RedoImpl( ::sw::UndoRedoContext & );
+ virtual void RepeatImpl( ::sw::RepeatContext & );
+};
+
+
+//--------------------------------------------------------------------
+
+// -> #111827#
+const int nUndoStringLength = 20;
+
+/**
+ Shortens a string to a maximum length.
+
+ @param rStr the string to be shortened
+ @param nLength the maximum length for rStr
+ @param rFillStr string to replace cut out characters with
+
+ If rStr has less than nLength characters it will be returned unaltered.
+
+ If rStr has more than nLength characters the following algorithm
+ generates the shortened string:
+
+ frontLength = (nLength - length(rFillStr)) / 2
+ rearLength = nLength - length(rFillStr) - frontLength
+ shortenedString = concat(<first frontLength characters of rStr,
+ rFillStr,
+ <last rearLength characters of rStr>)
+
+ Preconditions:
+ - nLength - length(rFillStr) >= 2
+
+ @return the shortened string
+ */
+String
+ShortenString(const String & rStr, xub_StrLen nLength, const String & rFillStr);
+// <- #111827#
+
+// #16487#
+/**
+ Denotes special characters in a string.
+
+ The rStr is split into parts containing special characters and
+ parts not containing special characters. In a part containing
+ special characters all characters are equal. These parts are
+ maximal.
+
+ @param rStr the string to denote in
+
+ The resulting string is generated by concatenating the found
+ parts. The parts without special characters are surrounded by
+ "'". The parts containing special characters are denoted as "n x",
+ where n is the length of the part and x is the representation of
+ the special character (i. e. "tab(s)").
+
+ @return the denoted string
+*/
+String DenoteSpecialCharacters(const String & rStr);
+
+
+#endif // SW_UNDOCORE_HXX
+
diff --git a/sw/source/core/inc/UndoDelete.hxx b/sw/source/core/inc/UndoDelete.hxx
new file mode 100644
index 000000000000..7bdfb79c633d
--- /dev/null
+++ b/sw/source/core/inc/UndoDelete.hxx
@@ -0,0 +1,115 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef SW_UNDO_DELETE_HXX
+#define SW_UNDO_DELETE_HXX
+
+#include <undobj.hxx>
+
+#include <tools/mempool.hxx>
+
+
+class SwRedlineSaveDatas;
+class SwTxtNode;
+
+namespace sfx2 {
+ class MetadatableUndo;
+}
+
+
+class SwUndoDelete
+ : public SwUndo
+ , private SwUndRng
+ , private SwUndoSaveCntnt
+{
+ SwNodeIndex* pMvStt; // Position of Nodes in UndoNodes-Array
+ String *pSttStr, *pEndStr;
+ SwRedlineData* pRedlData;
+ SwRedlineSaveDatas* pRedlSaveData;
+ ::boost::shared_ptr< ::sfx2::MetadatableUndo > m_pMetadataUndoStart;
+ ::boost::shared_ptr< ::sfx2::MetadatableUndo > m_pMetadataUndoEnd;
+
+ String sTableName;
+
+ sal_uLong nNode;
+ sal_uLong nNdDiff; // difference of Nodes before/after Delete
+ sal_uLong nSectDiff; // diff. of Nodes before/after Move w/ SectionNodes
+ sal_uLong nReplaceDummy; // diff. to a temporary dummy object
+ sal_uInt16 nSetPos;
+
+ sal_Bool bGroup : 1; // TRUE: is already Grouped; see CanGrouping()
+ sal_Bool bBackSp : 1; // TRUE: if Grouped and preceding content deleted
+ sal_Bool bJoinNext: 1; // TRUE: if range is selected forwards
+ sal_Bool bTblDelLastNd : 1; // TRUE: TextNode following Table inserted/deleted
+ sal_Bool bDelFullPara : 1; // TRUE: entire Nodes were deleted
+ sal_Bool bResetPgDesc : 1; // TRUE: reset PgDsc on following node
+ sal_Bool bResetPgBrk : 1; // TRUE: reset PgBreak on following node
+ sal_Bool bFromTableCopy : 1; // TRUE: called by SwUndoTblCpyTbl
+
+ sal_Bool SaveCntnt( const SwPosition* pStt, const SwPosition* pEnd,
+ SwTxtNode* pSttTxtNd, SwTxtNode* pEndTxtNd );
+public:
+ SwUndoDelete( SwPaM&,
+ sal_Bool bFullPara = sal_False, sal_Bool bCalledByTblCpy = sal_False );
+ virtual ~SwUndoDelete();
+
+ virtual void UndoImpl( ::sw::UndoRedoContext & );
+ virtual void RedoImpl( ::sw::UndoRedoContext & );
+ virtual void RepeatImpl( ::sw::RepeatContext & );
+
+ // #111827#
+ /**
+ Returns rewriter for this undo object.
+
+ The rewriter consists of the following rule:
+
+ $1 -> '<deleted text>'
+
+ <deleted text> is shortened to nUndoStringLength characters.
+
+ @return rewriter for this undo object
+ */
+ virtual SwRewriter GetRewriter() const;
+
+ sal_Bool CanGrouping( SwDoc*, const SwPaM& );
+
+ void SetTblDelLastNd() { bTblDelLastNd = sal_True; }
+
+ // for PageDesc/PageBreak Attributes of a table
+ void SetPgBrkFlags( sal_Bool bPageBreak, sal_Bool bPageDesc )
+ { bResetPgDesc = bPageDesc; bResetPgBrk = bPageBreak; }
+
+ void SetTableName(const String & rName);
+
+ // SwUndoTblCpyTbl needs this information:
+ sal_Bool IsDelFullPara() const { return bDelFullPara; }
+
+ DECL_FIXEDMEMPOOL_NEWDEL(SwUndoDelete)
+};
+
+#endif // SW_UNDO_DELETE_HXX
+
diff --git a/sw/source/core/inc/UndoDraw.hxx b/sw/source/core/inc/UndoDraw.hxx
new file mode 100644
index 000000000000..9d490901c02b
--- /dev/null
+++ b/sw/source/core/inc/UndoDraw.hxx
@@ -0,0 +1,150 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef SW_UNDO_DRAW_HXX
+#define SW_UNDO_DRAW_HXX
+
+#include <undobj.hxx>
+
+#include <svx/svdundo.hxx>
+
+
+struct SwUndoGroupObjImpl;
+class SdrMark;
+class SdrMarkList;
+class SdrObject;
+class SdrObjGroup;
+class SdrUndoAction;
+class SwDrawFrmFmt;
+
+
+
+//--------------------------------------------------------------------
+// ----------- Undo for Draw Objects ---------------------------------
+
+class SwSdrUndo : public SwUndo
+{
+ SdrUndoAction* pSdrUndo;
+ SdrMarkList* pMarkList; // MarkList for all selected SdrObjects
+public:
+ SwSdrUndo( SdrUndoAction* , const SdrMarkList* pMarkList );
+
+ virtual ~SwSdrUndo();
+
+ virtual void UndoImpl( ::sw::UndoRedoContext & );
+ virtual void RedoImpl( ::sw::UndoRedoContext & );
+
+ String GetComment() const;
+};
+
+class SwUndoDrawGroup : public SwUndo
+{
+ SwUndoGroupObjImpl* pObjArr;
+ sal_uInt16 nSize;
+ sal_Bool bDelFmt;
+
+public:
+ SwUndoDrawGroup( sal_uInt16 nCnt );
+
+ virtual ~SwUndoDrawGroup();
+
+ virtual void UndoImpl( ::sw::UndoRedoContext & );
+ virtual void RedoImpl( ::sw::UndoRedoContext & );
+
+ void AddObj( sal_uInt16 nPos, SwDrawFrmFmt*, SdrObject* );
+ void SetGroupFmt( SwDrawFrmFmt* );
+};
+
+// --> OD 2006-11-01 #130889#
+// Action "ungroup drawing object" is now splitted into three parts - see
+// method <SwDoc::UnGroupSelection(..)>:
+// - creation for <SwDrawFrmFmt> instances for the group members of the
+// selected group objects
+// - intrinsic ungroup of the selected group objects
+// - creation of <SwDrawContact> instances for the former group members and
+// connection to the Writer layout.
+// Thus, two undo actions (instances of <SwUndo>) are needed:
+// - Existing class <SwUndoDrawUnGroup> takes over the part for the formats.
+// - New class <SwUndoDrawUnGroupConnectToLayout> takes over the part for
+// contact object.
+class SwUndoDrawUnGroup : public SwUndo
+{
+ SwUndoGroupObjImpl* pObjArr;
+ sal_uInt16 nSize;
+ sal_Bool bDelFmt;
+
+public:
+ SwUndoDrawUnGroup( SdrObjGroup* );
+
+ virtual ~SwUndoDrawUnGroup();
+
+ virtual void UndoImpl( ::sw::UndoRedoContext & );
+ virtual void RedoImpl( ::sw::UndoRedoContext & );
+
+ void AddObj( sal_uInt16 nPos, SwDrawFrmFmt* );
+};
+
+// --> OD 2006-11-01 #130889#
+class SwUndoDrawUnGroupConnectToLayout : public SwUndo
+{
+ private:
+ std::vector< std::pair< SwDrawFrmFmt*, SdrObject* > > aDrawFmtsAndObjs;
+
+ public:
+ SwUndoDrawUnGroupConnectToLayout();
+
+ virtual ~SwUndoDrawUnGroupConnectToLayout();
+
+ virtual void UndoImpl( ::sw::UndoRedoContext & );
+ virtual void RedoImpl( ::sw::UndoRedoContext & );
+
+ void AddFmtAndObj( SwDrawFrmFmt* pDrawFrmFmt,
+ SdrObject* pDrawObject );
+};
+// <--
+
+
+class SwUndoDrawDelete : public SwUndo
+{
+ SwUndoGroupObjImpl* pObjArr;
+ SdrMarkList* pMarkLst; // MarkList for all selected SdrObjects
+ sal_uInt16 nSize;
+ sal_Bool bDelFmt;
+
+public:
+ SwUndoDrawDelete( sal_uInt16 nCnt );
+
+ virtual ~SwUndoDrawDelete();
+
+ virtual void UndoImpl( ::sw::UndoRedoContext & );
+ virtual void RedoImpl( ::sw::UndoRedoContext & );
+
+ void AddObj( sal_uInt16 nPos, SwDrawFrmFmt*, const SdrMark& );
+};
+
+#endif // SW_UNDO_DRAW_HXX
+
diff --git a/sw/source/core/inc/UndoInsert.hxx b/sw/source/core/inc/UndoInsert.hxx
new file mode 100644
index 000000000000..a39ba329fdc1
--- /dev/null
+++ b/sw/source/core/inc/UndoInsert.hxx
@@ -0,0 +1,235 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef SW_UNDO_INSERT_HXX
+#define SW_UNDO_INSERT_HXX
+
+#include <undobj.hxx>
+
+#include <tools/mempool.hxx>
+
+#include <swtypes.hxx>
+#include <IDocumentContentOperations.hxx>
+
+
+class Graphic;
+class SwGrfNode;
+class SwUndoDelete;
+class SwUndoFmtAttr;
+
+
+class SwUndoInsert: public SwUndo, private SwUndoSaveCntnt
+{
+ SwPosition *pPos; // Inhalt fuers Redo
+ String *pTxt, *pUndoTxt;
+ SwRedlineData* pRedlData;
+ sal_uLong nNode;
+ xub_StrLen nCntnt, nLen;
+ sal_Bool bIsWordDelim : 1;
+ sal_Bool bIsAppend : 1;
+
+ const IDocumentContentOperations::InsertFlags m_nInsertFlags;
+
+ friend class SwDoc; // eigentlich nur SwDoc::Insert( String )
+ sal_Bool CanGrouping( sal_Unicode cIns );
+ sal_Bool CanGrouping( const SwPosition& rPos );
+
+ SwDoc * pDoc;
+
+ void Init(const SwNodeIndex & rNode);
+ String * GetTxtFromDoc() const;
+
+public:
+ SwUndoInsert( const SwNodeIndex& rNode, xub_StrLen nCntnt, xub_StrLen nLen,
+ const IDocumentContentOperations::InsertFlags nInsertFlags,
+ sal_Bool bWDelim = sal_True );
+ SwUndoInsert( const SwNodeIndex& rNode );
+ virtual ~SwUndoInsert();
+
+ virtual void UndoImpl( ::sw::UndoRedoContext & );
+ virtual void RedoImpl( ::sw::UndoRedoContext & );
+ virtual void RepeatImpl( ::sw::RepeatContext & );
+
+ // #111827#
+ /**
+ Returns rewriter for this undo object.
+
+ The returned rewriter has the following rule:
+
+ $1 -> '<inserted text>'
+
+ <inserted text> is shortened to a length of nUndoStringLength.
+
+ @return rewriter for this undo object
+ */
+ virtual SwRewriter GetRewriter() const;
+
+
+ DECL_FIXEDMEMPOOL_NEWDEL(SwUndoInsert)
+};
+
+
+//--------------------------------------------------------------------
+
+SwRewriter SW_DLLPRIVATE
+MakeUndoReplaceRewriter(sal_uLong const ocurrences,
+ ::rtl::OUString const& sOld, ::rtl::OUString const& sNew);
+
+class SwUndoReplace
+ : public SwUndo
+{
+public:
+ SwUndoReplace(SwPaM const& rPam,
+ ::rtl::OUString const& rInsert, bool const bRegExp);
+
+ virtual ~SwUndoReplace();
+
+ virtual void UndoImpl( ::sw::UndoRedoContext & );
+ virtual void RedoImpl( ::sw::UndoRedoContext & );
+
+ // #111827#
+ /**
+ Returns the rewriter of this undo object.
+
+ If this undo object represents several replacements the
+ rewriter contains the following rules:
+
+ $1 -> <number of replacements>
+ $2 -> occurrences of
+ $3 -> <replaced text>
+
+ If this undo object represents one replacement the rewriter
+ contains these rules:
+
+ $1 -> <replaced text>
+ $2 -> "->" (STR_YIELDS)
+ $3 -> <replacing text>
+
+ @return the rewriter of this undo object
+ */
+ virtual SwRewriter GetRewriter() const;
+
+ void SetEnd( const SwPaM& rPam );
+
+private:
+ class Impl;
+ ::std::auto_ptr<Impl> m_pImpl;
+};
+
+
+//--------------------------------------------------------------------
+
+class SwUndoReRead : public SwUndo
+{
+ Graphic *pGrf;
+ String *pNm, *pFltr;
+ sal_uLong nPos;
+ sal_uInt16 nMirr;
+
+ void SaveGraphicData( const SwGrfNode& );
+ void SetAndSave( ::sw::UndoRedoContext & );
+
+public:
+ SwUndoReRead( const SwPaM& rPam, const SwGrfNode& pGrfNd );
+
+ virtual ~SwUndoReRead();
+
+ virtual void UndoImpl( ::sw::UndoRedoContext & );
+ virtual void RedoImpl( ::sw::UndoRedoContext & );
+};
+
+//--------------------------------------------------------------------
+
+class SwUndoInsertLabel : public SwUndo
+{
+ union {
+ struct {
+ // fuer NoTxtFrms
+ SwUndoInsLayFmt* pUndoFly;
+ SwUndoFmtAttr* pUndoAttr;
+ } OBJECT;
+ struct {
+ // fuer Tabelle/TextRahmen
+ SwUndoDelete* pUndoInsNd;
+ sal_uLong nNode;
+ } NODE;
+ };
+
+ String sText;
+ // --> PB 2005-01-06 #i39983# the separator is drawn with a character style
+ String sSeparator;
+ // <--
+ String sNumberSeparator;
+ String sCharacterStyle;
+ // OD 2004-04-15 #i26791# - re-store of drawing object position no longer needed
+ sal_uInt16 nFldId;
+ SwLabelType eType;
+ sal_uInt8 nLayerId; // fuer Zeichen-Objekte
+ sal_Bool bBefore :1;
+ sal_Bool bUndoKeep :1;
+ sal_Bool bCpyBrd :1;
+
+public:
+ SwUndoInsertLabel( const SwLabelType eTyp, const String &rText,
+ // --> PB 2005-01-06 #i39983# the separator is drawn with a character style
+ const String& rSeparator,
+ // <--
+ const String& rNumberSeparator, //#i61007# order of captions
+ const sal_Bool bBefore, const sal_uInt16 nId,
+ const String& rCharacterStyle,
+ const sal_Bool bCpyBrd );
+ virtual ~SwUndoInsertLabel();
+
+ virtual void UndoImpl( ::sw::UndoRedoContext & );
+ virtual void RedoImpl( ::sw::UndoRedoContext & );
+ virtual void RepeatImpl( ::sw::RepeatContext & );
+
+ // #111827#
+ /**
+ Returns the rewriter of this undo object.
+
+ The rewriter contains this rule:
+
+ $1 -> '<text of inserted label>'
+
+ <text of inserted label> is shortened to nUndoStringLength
+ characters.
+
+ @return the rewriter of this undo object
+ */
+ virtual SwRewriter GetRewriter() const;
+
+ void SetNodePos( sal_uLong nNd )
+ { if( LTYPE_OBJECT != eType ) NODE.nNode = nNd; }
+
+ void SetUndoKeep() { bUndoKeep = sal_True; }
+ void SetFlys( SwFrmFmt& rOldFly, SfxItemSet& rChgSet, SwFrmFmt& rNewFly );
+ void SetDrawObj( sal_uInt8 nLayerId );
+};
+
+#endif // SW_UNDO_INSERT_HXX
+
diff --git a/sw/source/core/inc/UndoManager.hxx b/sw/source/core/inc/UndoManager.hxx
new file mode 100644
index 000000000000..0f734d17abfa
--- /dev/null
+++ b/sw/source/core/inc/UndoManager.hxx
@@ -0,0 +1,124 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef SW_UNDO_MANAGER_HXX
+#define SW_UNDO_MANAGER_HXX
+
+#include <IDocumentUndoRedo.hxx>
+
+#include <memory>
+
+#include <svl/undo.hxx>
+
+
+class IDocumentDrawModelAccess;
+class IDocumentRedlineAccess;
+class IDocumentState;
+
+
+namespace sw {
+
+class UndoManager
+ : public IDocumentUndoRedo
+ , public SfxUndoManager
+{
+public:
+
+ UndoManager(::std::auto_ptr<SwNodes> pUndoNodes,
+ IDocumentDrawModelAccess & rDrawModelAccess,
+ IDocumentRedlineAccess & rRedlineAccess,
+ IDocumentState & rState);
+
+ /** IDocumentUndoRedo */
+ virtual void DoUndo(bool const bDoUndo);
+ virtual bool DoesUndo() const;
+ virtual void DoGroupUndo(bool const bDoUndo);
+ virtual bool DoesGroupUndo() const;
+ virtual void DoDrawUndo(bool const bDoUndo);
+ virtual bool DoesDrawUndo() const;
+ virtual void SetUndoNoModifiedPosition();
+ virtual void LockUndoNoModifiedPosition();
+ virtual void UnLockUndoNoModifiedPosition();
+ virtual void SetUndoNoResetModified();
+ virtual bool IsUndoNoResetModified() const;
+// virtual bool Undo();
+ virtual SwUndoId StartUndo(SwUndoId const eUndoId,
+ SwRewriter const*const pRewriter);
+ virtual SwUndoId EndUndo(SwUndoId const eUndoId,
+ SwRewriter const*const pRewriter);
+ virtual void DelAllUndoObj();
+ virtual bool GetLastUndoInfo(::rtl::OUString *const o_pStr,
+ SwUndoId *const o_pId) const;
+ virtual SwUndoComments_t GetUndoComments() const;
+// virtual bool Redo();
+ virtual bool GetFirstRedoInfo(::rtl::OUString *const o_pStr) const;
+ virtual SwUndoComments_t GetRedoComments() const;
+ virtual bool Repeat(::sw::RepeatContext & rContext,
+ sal_uInt16 const nRepeatCnt);
+ virtual SwUndoId GetRepeatInfo(::rtl::OUString *const o_pStr) const;
+ virtual void AppendUndo(SwUndo *const pUndo);
+ virtual void ClearRedo();
+ virtual bool IsUndoNodes(SwNodes const& rNodes) const;
+
+ // ::svl::IUndoManager
+ virtual void AddUndoAction(SfxUndoAction *pAction,
+ sal_Bool bTryMerg = sal_False);
+ virtual sal_Bool Undo();
+ virtual sal_Bool Redo();
+ virtual void EnableUndo(bool bEnable);
+
+ SwUndo * RemoveLastUndo();
+ SwUndo * GetLastUndo();
+
+ SwNodes const& GetUndoNodes() const;
+ SwNodes & GetUndoNodes();
+
+private:
+ IDocumentDrawModelAccess & m_rDrawModelAccess;
+ IDocumentRedlineAccess & m_rRedlineAccess;
+ IDocumentState & m_rState;
+
+ /// Undo nodes array: content not currently in document
+ ::std::auto_ptr<SwNodes> m_pUndoNodes;
+
+ bool m_bGroupUndo : 1; // TRUE: Undo grouping enabled
+ bool m_bDrawUndo : 1; // TRUE: Draw Undo enabled
+ bool m_bLockUndoNoModifiedPosition : 1;
+ /// position in Undo-Array at which Doc was saved (and is not modified)
+ UndoStackMark m_UndoSaveMark;
+
+ typedef enum { UNDO = true, REDO = false } UndoOrRedo_t;
+ bool impl_DoUndoRedo(UndoOrRedo_t const undoOrRedo);
+
+ // UGLY: should not be called
+ using SfxUndoManager::Repeat;
+};
+
+} // namespace sw
+
+#endif // SW_UNDO_MANAGER_HXX
+
diff --git a/sw/source/core/inc/UndoNumbering.hxx b/sw/source/core/inc/UndoNumbering.hxx
new file mode 100644
index 000000000000..3d92ff7ce1c7
--- /dev/null
+++ b/sw/source/core/inc/UndoNumbering.hxx
@@ -0,0 +1,150 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef SW_UNDO_NUMBERING_HXX
+#define SW_UNDO_NUMBERING_HXX
+
+#include <vector>
+#include <undobj.hxx>
+#include <boost/shared_ptr.hpp>
+#include <numrule.hxx>
+
+
+//--------------------------------------------------------------------
+//----------- Undo for Numbering -------------------------------------
+
+class SwUndoInsNum : public SwUndo, private SwUndRng
+{
+ SwNumRule aNumRule;
+ SwHistory* pHistory;
+ sal_uLong nSttSet;
+ SwNumRule* pOldNumRule;
+ String sReplaceRule;
+ sal_uInt16 nLRSavePos;
+public:
+ SwUndoInsNum( const SwPaM& rPam, const SwNumRule& rRule );
+ SwUndoInsNum( const SwNumRule& rOldRule, const SwNumRule& rNewRule,
+ SwUndoId nUndoId = UNDO_INSFMTATTR );
+ SwUndoInsNum( const SwPosition& rPos, const SwNumRule& rRule,
+ const String& rReplaceRule );
+
+ virtual ~SwUndoInsNum();
+
+ virtual void UndoImpl( ::sw::UndoRedoContext & );
+ virtual void RedoImpl( ::sw::UndoRedoContext & );
+ virtual void RepeatImpl( ::sw::RepeatContext & );
+
+ virtual SwRewriter GetRewriter() const;
+
+ SwHistory* GetHistory(); // will be created if necessary
+ void SetSttNum( sal_uLong nNdIdx ) { nSttSet = nNdIdx; }
+ void SaveOldNumRule( const SwNumRule& rOld );
+
+ void SetLRSpaceEndPos();
+
+};
+
+class SwUndoDelNum : public SwUndo, private SwUndRng
+{
+ struct NodeLevel
+ {
+ sal_uLong index;
+ int level;
+ inline NodeLevel(sal_uLong idx, int lvl) : index(idx), level(lvl) {};
+ };
+ std::vector<NodeLevel> aNodes;
+ SwHistory* pHistory;
+public:
+ SwUndoDelNum( const SwPaM& rPam );
+
+ virtual ~SwUndoDelNum();
+
+ virtual void UndoImpl( ::sw::UndoRedoContext & );
+ virtual void RedoImpl( ::sw::UndoRedoContext & );
+ virtual void RepeatImpl( ::sw::RepeatContext & );
+
+ void AddNode( const SwTxtNode& rNd, sal_Bool bResetLRSpace );
+ SwHistory* GetHistory() { return pHistory; }
+
+};
+
+class SwUndoMoveNum : public SwUndo, private SwUndRng
+{
+ sal_uLong nNewStt;
+ long nOffset;
+public:
+ SwUndoMoveNum( const SwPaM& rPam, long nOffset, sal_Bool bIsOutlMv = sal_False );
+
+ virtual void UndoImpl( ::sw::UndoRedoContext & );
+ virtual void RedoImpl( ::sw::UndoRedoContext & );
+ virtual void RepeatImpl( ::sw::RepeatContext & );
+
+ void SetStartNode( sal_uLong nValue ) { nNewStt = nValue; }
+};
+
+class SwUndoNumUpDown : public SwUndo, private SwUndRng
+{
+ short nOffset;
+public:
+ SwUndoNumUpDown( const SwPaM& rPam, short nOffset );
+
+ virtual void UndoImpl( ::sw::UndoRedoContext & );
+ virtual void RedoImpl( ::sw::UndoRedoContext & );
+ virtual void RepeatImpl( ::sw::RepeatContext & );
+};
+
+class SwUndoNumOrNoNum : public SwUndo
+{
+ sal_uLong nIdx;
+ sal_Bool mbNewNum, mbOldNum;
+
+public:
+ SwUndoNumOrNoNum( const SwNodeIndex& rIdx, sal_Bool mbOldNum,
+ sal_Bool mbNewNum );
+
+ virtual void UndoImpl( ::sw::UndoRedoContext & );
+ virtual void RedoImpl( ::sw::UndoRedoContext & );
+ virtual void RepeatImpl( ::sw::RepeatContext & );
+};
+
+class SwUndoNumRuleStart : public SwUndo
+{
+ sal_uLong nIdx;
+ sal_uInt16 nOldStt, nNewStt;
+ sal_Bool bSetSttValue : 1;
+ sal_Bool bFlag : 1;
+public:
+ SwUndoNumRuleStart( const SwPosition& rPos, sal_Bool bDelete );
+ SwUndoNumRuleStart( const SwPosition& rPos, sal_uInt16 nStt );
+
+ virtual void UndoImpl( ::sw::UndoRedoContext & );
+ virtual void RedoImpl( ::sw::UndoRedoContext & );
+ virtual void RepeatImpl( ::sw::RepeatContext & );
+};
+
+#endif // SW_UNDO_NUMBERING_HXX
+
diff --git a/sw/source/core/inc/UndoOverwrite.hxx b/sw/source/core/inc/UndoOverwrite.hxx
new file mode 100644
index 000000000000..151de9b344c1
--- /dev/null
+++ b/sw/source/core/inc/UndoOverwrite.hxx
@@ -0,0 +1,105 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef SW_UNDO_OVERWRITE_HXX
+#define SW_UNDO_OVERWRITE_HXX
+
+#include <undobj.hxx>
+
+#include <com/sun/star/uno/Sequence.h>
+
+
+class SwRedlineSaveDatas;
+class SwTxtNode;
+
+namespace utl {
+ class TransliterationWrapper;
+}
+
+
+class SwUndoOverwrite: public SwUndo, private SwUndoSaveCntnt
+{
+ String aDelStr, aInsStr;
+ SwRedlineSaveDatas* pRedlSaveData;
+ sal_uLong nSttNode;
+ xub_StrLen nSttCntnt;
+ sal_Bool bInsChar : 1; // no Overwrite, but Insert
+ sal_Bool bGroup : 1; // TRUE: is already grouped; evaluated in CanGrouping()
+
+public:
+ SwUndoOverwrite( SwDoc*, SwPosition&, sal_Unicode cIns );
+
+ virtual ~SwUndoOverwrite();
+
+ virtual void UndoImpl( ::sw::UndoRedoContext & );
+ virtual void RedoImpl( ::sw::UndoRedoContext & );
+ virtual void RepeatImpl( ::sw::RepeatContext & );
+
+ // #111827#
+ /**
+ Returns the rewriter of this undo object.
+
+ The rewriter contains the following rule:
+
+ $1 -> '<overwritten text>'
+
+ <overwritten text> is shortened to nUndoStringLength characters.
+
+ @return the rewriter of this undo object
+ */
+ virtual SwRewriter GetRewriter() const;
+
+ sal_Bool CanGrouping( SwDoc*, SwPosition&, sal_Unicode cIns );
+};
+
+//--------------------------------------------------------------------
+
+struct _UndoTransliterate_Data;
+class SwUndoTransliterate : public SwUndo, public SwUndRng
+{
+ std::vector< _UndoTransliterate_Data * > aChanges;
+ sal_uInt32 nType;
+
+ void DoTransliterate(SwDoc & rDoc, SwPaM & rPam);
+
+public:
+ SwUndoTransliterate( const SwPaM& rPam,
+ const utl::TransliterationWrapper& rTrans );
+
+ virtual ~SwUndoTransliterate();
+
+ virtual void UndoImpl( ::sw::UndoRedoContext & );
+ virtual void RedoImpl( ::sw::UndoRedoContext & );
+ virtual void RepeatImpl( ::sw::RepeatContext & );
+
+ void AddChanges( SwTxtNode& rTNd, xub_StrLen nStart, xub_StrLen nLen,
+ ::com::sun::star::uno::Sequence <sal_Int32>& rOffsets );
+ sal_Bool HasData() const { return aChanges.size() > 0; }
+};
+
+#endif // SW_UNDO_OVERWRITE_HXX
+
diff --git a/sw/source/core/inc/UndoRedline.hxx b/sw/source/core/inc/UndoRedline.hxx
new file mode 100644
index 000000000000..57b0df0867b9
--- /dev/null
+++ b/sw/source/core/inc/UndoRedline.hxx
@@ -0,0 +1,145 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef SW_UNDO_REDLINE_HXX
+#define SW_UNDO_REDLINE_HXX
+
+#include <undobj.hxx>
+
+
+struct SwSortOptions;
+class SwRedline;
+class SwRedlineSaveDatas;
+class SwUndoDelete;
+
+
+//--------------------------------------------------------------------
+
+class SwUndoRedline : public SwUndo, public SwUndRng
+{
+protected:
+ SwRedlineData* pRedlData;
+ SwRedlineSaveDatas* pRedlSaveData;
+ SwUndoId nUserId;
+ sal_Bool bHiddenRedlines;
+
+ virtual void UndoRedlineImpl(SwDoc & rDoc, SwPaM & rPam);
+ virtual void RedoRedlineImpl(SwDoc & rDoc, SwPaM & rPam);
+
+public:
+ SwUndoRedline( SwUndoId nUserId, const SwPaM& rRange );
+
+ virtual ~SwUndoRedline();
+
+ virtual void UndoImpl( ::sw::UndoRedoContext & );
+ virtual void RedoImpl( ::sw::UndoRedoContext & );
+
+ SwUndoId GetUserId() const { return nUserId; }
+ sal_uInt16 GetRedlSaveCount() const;
+};
+
+class SwUndoRedlineDelete : public SwUndoRedline
+{
+ sal_Bool bCanGroup : 1;
+ sal_Bool bIsDelim : 1;
+ sal_Bool bIsBackspace : 1;
+
+ virtual void UndoRedlineImpl(SwDoc & rDoc, SwPaM & rPam);
+ virtual void RedoRedlineImpl(SwDoc & rDoc, SwPaM & rPam);
+
+public:
+ SwUndoRedlineDelete( const SwPaM& rRange, SwUndoId nUserId = UNDO_EMPTY );
+
+ sal_Bool CanGrouping( const SwUndoRedlineDelete& rPrev );
+
+ // SwUndoTblCpyTbl needs this information:
+ long NodeDiff() const { return nSttNode - nEndNode; }
+ xub_StrLen ContentStart() const { return nSttCntnt; }
+};
+
+class SwUndoRedlineSort : public SwUndoRedline
+{
+ SwSortOptions* pOpt;
+ sal_uLong nSaveEndNode, nOffset;
+ xub_StrLen nSaveEndCntnt;
+
+ virtual void UndoRedlineImpl(SwDoc & rDoc, SwPaM & rPam);
+ virtual void RedoRedlineImpl(SwDoc & rDoc, SwPaM & rPam);
+
+public:
+ SwUndoRedlineSort( const SwPaM& rRange, const SwSortOptions& rOpt );
+
+ virtual ~SwUndoRedlineSort();
+
+ virtual void RepeatImpl( ::sw::RepeatContext & );
+
+ void SetSaveRange( const SwPaM& rRange );
+ void SetOffset( const SwNodeIndex& rIdx );
+};
+
+class SwUndoAcceptRedline : public SwUndoRedline
+{
+private:
+ virtual void RedoRedlineImpl(SwDoc & rDoc, SwPaM & rPam);
+
+public:
+ SwUndoAcceptRedline( const SwPaM& rRange );
+
+ virtual void RepeatImpl( ::sw::RepeatContext & );
+};
+
+class SwUndoRejectRedline : public SwUndoRedline
+{
+private:
+ virtual void RedoRedlineImpl(SwDoc & rDoc, SwPaM & rPam);
+
+public:
+ SwUndoRejectRedline( const SwPaM& rRange );
+
+ virtual void RepeatImpl( ::sw::RepeatContext & );
+};
+
+//--------------------------------------------------------------------
+
+class SwUndoCompDoc : public SwUndo, public SwUndRng
+{
+ SwRedlineData* pRedlData;
+ SwUndoDelete* pUnDel, *pUnDel2;
+ SwRedlineSaveDatas* pRedlSaveData;
+ sal_Bool bInsert;
+public:
+ SwUndoCompDoc( const SwPaM& rRg, sal_Bool bIns );
+ SwUndoCompDoc( const SwRedline& rRedl );
+
+ virtual ~SwUndoCompDoc();
+
+ virtual void UndoImpl( ::sw::UndoRedoContext & );
+ virtual void RedoImpl( ::sw::UndoRedoContext & );
+};
+
+#endif // SW_UNDO_REDLINE_HXX
+
diff --git a/sw/source/core/inc/UndoSection.hxx b/sw/source/core/inc/UndoSection.hxx
new file mode 100644
index 000000000000..bc6c8dd9fbfc
--- /dev/null
+++ b/sw/source/core/inc/UndoSection.hxx
@@ -0,0 +1,82 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef SW_UNDO_SECTION_HXX
+#define SW_UNDO_SECTION_HXX
+
+#include <undobj.hxx>
+
+#include <memory>
+
+#include <swdllapi.h>
+
+
+class SfxItemSet;
+class SwTxtNode;
+class SwSectionData;
+class SwSectionFmt;
+class SwTOXBase;
+
+
+//------------ Undo of Insert-/Delete-Section ----------------------
+
+class SwUndoInsSection : public SwUndo, private SwUndRng
+{
+private:
+ const ::std::auto_ptr<SwSectionData> m_pSectionData;
+ const ::std::auto_ptr<SwTOXBase> m_pTOXBase; /// set iff section is TOX
+ const ::std::auto_ptr<SfxItemSet> m_pAttrSet;
+ ::std::auto_ptr<SwHistory> m_pHistory;
+ ::std::auto_ptr<SwRedlineData> m_pRedlData;
+ sal_uLong m_nSectionNodePos;
+ bool m_bSplitAtStart : 1;
+ bool m_bSplitAtEnd : 1;
+ bool m_bUpdateFtn : 1;
+
+ void Join( SwDoc& rDoc, sal_uLong nNode );
+
+public:
+ SwUndoInsSection(SwPaM const&, SwSectionData const&,
+ SfxItemSet const*const pSet, SwTOXBase const*const pTOXBase);
+
+ virtual ~SwUndoInsSection();
+
+ virtual void UndoImpl( ::sw::UndoRedoContext & );
+ virtual void RedoImpl( ::sw::UndoRedoContext & );
+ virtual void RepeatImpl( ::sw::RepeatContext & );
+
+ void SetSectNdPos(sal_uLong const nPos) { m_nSectionNodePos = nPos; }
+ void SaveSplitNode(SwTxtNode *const pTxtNd, bool const bAtStart);
+ void SetUpdtFtnFlag(bool const bFlag) { m_bUpdateFtn = bFlag; }
+};
+
+SW_DLLPRIVATE SwUndo * MakeUndoDelSection(SwSectionFmt const&);
+
+SW_DLLPRIVATE SwUndo * MakeUndoUpdateSection(SwSectionFmt const&, bool const);
+
+#endif // SW_UNDO_SECTION_HXX
+
diff --git a/sw/source/core/inc/UndoSort.hxx b/sw/source/core/inc/UndoSort.hxx
new file mode 100644
index 000000000000..b1cab7246aad
--- /dev/null
+++ b/sw/source/core/inc/UndoSort.hxx
@@ -0,0 +1,97 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef SW_UNDO_SORT_HXX
+#define SW_UNDO_SORT_HXX
+
+#include <undobj.hxx>
+
+
+struct SwSortOptions;
+class SwTableNode;
+class SwUndoAttrTbl;
+
+
+/*--------------------------------------------------------------------
+ Undo for Sorting
+ --------------------------------------------------------------------*/
+
+struct SwSortUndoElement
+{
+ union {
+ struct {
+ sal_uLong nKenn;
+ sal_uLong nSource, nTarget;
+ } TXT;
+ struct {
+ String *pSource, *pTarget;
+ } TBL;
+ } SORT_TXT_TBL;
+
+ SwSortUndoElement( const String& aS, const String& aT )
+ {
+ SORT_TXT_TBL.TBL.pSource = new String( aS );
+ SORT_TXT_TBL.TBL.pTarget = new String( aT );
+ }
+ SwSortUndoElement( sal_uLong nS, sal_uLong nT )
+ {
+ SORT_TXT_TBL.TXT.nSource = nS;
+ SORT_TXT_TBL.TXT.nTarget = nT;
+ SORT_TXT_TBL.TXT.nKenn = 0xffffffff;
+ }
+ ~SwSortUndoElement();
+};
+
+SV_DECL_PTRARR_DEL(SwSortList, SwSortUndoElement*, 10,30)
+SV_DECL_PTRARR(SwUndoSortList, SwNodeIndex*, 10,30)
+
+class SwUndoSort : public SwUndo, private SwUndRng
+{
+ SwSortOptions* pSortOpt;
+ SwSortList aSortList;
+ SwUndoAttrTbl* pUndoTblAttr;
+ SwRedlineData* pRedlData;
+ sal_uLong nTblNd;
+
+public:
+ SwUndoSort( const SwPaM&, const SwSortOptions& );
+ SwUndoSort( sal_uLong nStt, sal_uLong nEnd, const SwTableNode&,
+ const SwSortOptions&, sal_Bool bSaveTable );
+
+ virtual ~SwUndoSort();
+
+ virtual void UndoImpl( ::sw::UndoRedoContext & );
+ virtual void RedoImpl( ::sw::UndoRedoContext & );
+ virtual void RepeatImpl( ::sw::RepeatContext & );
+
+ void Insert( const String& rOrgPos, const String& rNewPos );
+ void Insert( sal_uLong nOrgPos, sal_uLong nNewPos );
+
+};
+
+#endif // SW_UNDO_SORT_HXX
+
diff --git a/sw/source/core/inc/UndoSplitMove.hxx b/sw/source/core/inc/UndoSplitMove.hxx
new file mode 100644
index 000000000000..f58e71517f78
--- /dev/null
+++ b/sw/source/core/inc/UndoSplitMove.hxx
@@ -0,0 +1,96 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef SW_UNDO_MOVE_HXX
+#define SW_UNDO_MOVE_HXX
+
+#include <undobj.hxx>
+
+
+class SwUndoSplitNode: public SwUndo
+{
+ SwHistory* pHistory;
+ SwRedlineData* pRedlData;
+ sal_uLong nNode;
+ xub_StrLen nCntnt;
+ sal_Bool bTblFlag : 1;
+ sal_Bool bChkTblStt : 1;
+
+public:
+ SwUndoSplitNode( SwDoc* pDoc, const SwPosition& rPos, sal_Bool bChkTbl );
+
+ virtual ~SwUndoSplitNode();
+
+ virtual void UndoImpl( ::sw::UndoRedoContext & );
+ virtual void RedoImpl( ::sw::UndoRedoContext & );
+ virtual void RepeatImpl( ::sw::RepeatContext & );
+
+ void SetTblFlag() { bTblFlag = sal_True; }
+};
+
+
+class SwUndoMove : public SwUndo, private SwUndRng, private SwUndoSaveCntnt
+{
+ // nDest.. - destination range of move (after move!)
+ // nIns.. - source Position of move (after move!)
+ // nMv.. - destination position of move (before move!); for REDO
+ sal_uLong nDestSttNode, nDestEndNode, nInsPosNode, nMvDestNode;
+ xub_StrLen nDestSttCntnt, nDestEndCntnt, nInsPosCntnt, nMvDestCntnt;
+
+ sal_uInt16 nFtnStt; // StartPos of Footnotes in History
+
+ sal_Bool bJoinNext : 1,
+ bJoinPrev : 1,
+ bMoveRange : 1;
+
+ bool bMoveRedlines; // use DOC_MOVEREDLINES when calling SwDoc::Move
+
+ void DelFtn( const SwPaM& );
+
+public:
+ SwUndoMove( const SwPaM&, const SwPosition& );
+ SwUndoMove( SwDoc* pDoc, const SwNodeRange&, const SwNodeIndex& );
+
+ virtual void UndoImpl( ::sw::UndoRedoContext & );
+ virtual void RedoImpl( ::sw::UndoRedoContext & );
+
+ /// set the destination range after the move
+ void SetDestRange( const SwPaM&, const SwPosition&, sal_Bool, sal_Bool );
+ void SetDestRange( const SwNodeIndex& rStt, const SwNodeIndex& rEnd,
+ const SwNodeIndex& rInsPos );
+
+ sal_Bool IsMoveRange() const { return bMoveRange; }
+ sal_uLong GetEndNode() const { return nEndNode; }
+ sal_uLong GetDestSttNode() const { return nDestSttNode; }
+ xub_StrLen GetDestSttCntnt() const { return nDestSttCntnt; }
+
+ void SetMoveRedlines( bool b ) { bMoveRedlines = b; }
+
+};
+
+#endif // SW_UNDO_MOVE_HXX
+
diff --git a/sw/source/core/inc/UndoTable.hxx b/sw/source/core/inc/UndoTable.hxx
new file mode 100644
index 000000000000..d7705a398ee2
--- /dev/null
+++ b/sw/source/core/inc/UndoTable.hxx
@@ -0,0 +1,391 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef SW_UNDO_TABLE_HXX
+#define SW_UNDO_TABLE_HXX
+
+#include <undobj.hxx>
+
+#ifndef _SVSTDARR_HXX
+#define _SVSTDARR_USHORTS
+#define _SVSTDARR_ULONGS
+#define _SVSTDARR_BOOLS
+#define _SVSTDARR_BYTES
+#define _SVSTDARR_USHORTSSORT
+#include <svl/svstdarr.hxx>
+#endif
+
+#include <vector>
+#include <swtypes.hxx>
+#include <itabenum.hxx>
+
+class SfxItemSet;
+
+struct SwSaveRowSpan;
+class _SaveTable;
+class SwDDEFieldType;
+class SwUndoSaveSections;
+class SwUndoMoves;
+class SwUndoDelete;
+class SwSelBoxes;
+class SwTblToTxtSaves;
+class SwTable;
+class SwTableBox;
+class SwStartNode;
+class SwTableNode;
+class SwTableAutoFmt;
+class SwTableSortBoxes;
+
+
+class SwUndoInsTbl : public SwUndo
+{
+ String sTblNm;
+ SwInsertTableOptions aInsTblOpts;
+ SwDDEFieldType* pDDEFldType;
+ SvUShorts* pColWidth;
+ SwRedlineData* pRedlData;
+ SwTableAutoFmt* pAutoFmt;
+ sal_uLong nSttNode;
+ sal_uInt16 nRows, nCols;
+ sal_uInt16 nAdjust;
+
+public:
+ SwUndoInsTbl( const SwPosition&, sal_uInt16 nCols, sal_uInt16 nRows,
+ sal_uInt16 eAdjust, const SwInsertTableOptions& rInsTblOpts,
+ const SwTableAutoFmt* pTAFmt, const SvUShorts* pColArr,
+ const String & rName);
+
+ virtual ~SwUndoInsTbl();
+
+ virtual void UndoImpl( ::sw::UndoRedoContext & );
+ virtual void RedoImpl( ::sw::UndoRedoContext & );
+ virtual void RepeatImpl( ::sw::RepeatContext & );
+
+ virtual SwRewriter GetRewriter() const;
+
+};
+
+class SwUndoTxtToTbl : public SwUndo, public SwUndRng
+{
+ String sTblNm;
+ SwInsertTableOptions aInsTblOpts;
+ SvULongs* pDelBoxes;
+ SwTableAutoFmt* pAutoFmt;
+ SwHistory* pHistory;
+ sal_Unicode cTrenner;
+ sal_uInt16 nAdjust;
+ sal_Bool bSplitEnd : 1;
+
+public:
+ SwUndoTxtToTbl( const SwPaM&, const SwInsertTableOptions&, sal_Unicode,
+ sal_uInt16,
+ const SwTableAutoFmt* pAFmt );
+
+ virtual ~SwUndoTxtToTbl();
+
+
+ virtual void UndoImpl( ::sw::UndoRedoContext & );
+ virtual void RedoImpl( ::sw::UndoRedoContext & );
+ virtual void RepeatImpl( ::sw::RepeatContext & );
+
+ SwHistory& GetHistory(); // will be created if necessary
+ void AddFillBox( const SwTableBox& rBox );
+};
+
+class SwUndoTblToTxt : public SwUndo
+{
+ String sTblNm;
+ SwDDEFieldType* pDDEFldType;
+ _SaveTable* pTblSave;
+ SwTblToTxtSaves* pBoxSaves;
+ SwHistory* pHistory;
+ sal_uLong nSttNd, nEndNd;
+ sal_uInt16 nAdjust;
+ sal_Unicode cTrenner;
+ sal_uInt16 nHdlnRpt;
+ sal_Bool bCheckNumFmt : 1;
+
+public:
+ SwUndoTblToTxt( const SwTable& rTbl, sal_Unicode cCh );
+
+ virtual ~SwUndoTblToTxt();
+
+ virtual void UndoImpl( ::sw::UndoRedoContext & );
+ virtual void RedoImpl( ::sw::UndoRedoContext & );
+ virtual void RepeatImpl( ::sw::RepeatContext & );
+
+ void SetRange( const SwNodeRange& );
+ void AddBoxPos( SwDoc& rDoc, sal_uLong nNdIdx, sal_uLong nEndIdx,
+ xub_StrLen nCntntIdx = STRING_MAXLEN);
+};
+
+class SwUndoAttrTbl : public SwUndo
+{
+ sal_uLong nSttNode;
+ _SaveTable* pSaveTbl;
+ sal_Bool bClearTabCol : 1;
+public:
+ SwUndoAttrTbl( const SwTableNode& rTblNd, sal_Bool bClearTabCols = sal_False );
+
+ virtual ~SwUndoAttrTbl();
+
+ virtual void UndoImpl( ::sw::UndoRedoContext & );
+ virtual void RedoImpl( ::sw::UndoRedoContext & );
+};
+
+class SwUndoTblNumFmt;
+
+class SwUndoTblAutoFmt : public SwUndo
+{
+ sal_uLong nSttNode;
+ _SaveTable* pSaveTbl;
+ ::std::vector< ::boost::shared_ptr<SwUndoTblNumFmt> > m_Undos;
+ sal_Bool bSaveCntntAttr;
+
+ void UndoRedo(bool const bUndo, ::sw::UndoRedoContext & rContext);
+
+public:
+ SwUndoTblAutoFmt( const SwTableNode& rTblNd, const SwTableAutoFmt& );
+
+ virtual ~SwUndoTblAutoFmt();
+
+ virtual void UndoImpl( ::sw::UndoRedoContext & );
+ virtual void RedoImpl( ::sw::UndoRedoContext & );
+
+ void SaveBoxCntnt( const SwTableBox& rBox );
+};
+
+class SwUndoTblNdsChg : public SwUndo
+{
+ _SaveTable* pSaveTbl;
+ SvULongs aBoxes;
+
+ union {
+ SvULongs* pNewSttNds;
+ SwUndoSaveSections* pDelSects;
+ } Ptrs;
+ std::vector<bool> aMvBoxes; // for SplitRow (split Nodes of Box)
+ long nMin, nMax; // for redo of delete column
+ sal_uLong nSttNode, nCurrBox;
+ sal_uInt16 nCount, nRelDiff, nAbsDiff, nSetColType;
+ sal_Bool bFlag;
+ sal_Bool bSameHeight; // only used for SplitRow
+public:
+ SwUndoTblNdsChg( SwUndoId UndoId,
+ const SwSelBoxes& rBoxes,
+ const SwTableNode& rTblNd,
+ long nMn, long nMx,
+ sal_uInt16 nCnt, sal_Bool bFlg, sal_Bool bSameHeight );
+
+ // for SetColWidth
+ SwUndoTblNdsChg( SwUndoId UndoId, const SwSelBoxes& rBoxes,
+ const SwTableNode& rTblNd );
+
+ virtual ~SwUndoTblNdsChg();
+
+ virtual void UndoImpl( ::sw::UndoRedoContext & );
+ virtual void RedoImpl( ::sw::UndoRedoContext & );
+
+ void SaveNewBoxes( const SwTableNode& rTblNd, const SwTableSortBoxes& rOld );
+ void SaveNewBoxes( const SwTableNode& rTblNd, const SwTableSortBoxes& rOld,
+ const SwSelBoxes& rBoxes, const SvULongs& rNodeCnts );
+ void SaveSection( SwStartNode* pSttNd );
+ void ReNewBoxes( const SwSelBoxes& rBoxes );
+
+
+ void SetColWidthParam( sal_uLong nBoxIdx, sal_uInt16 nMode, sal_uInt16 nType,
+ SwTwips nAbsDif, SwTwips nRelDif )
+ {
+ nCurrBox = nBoxIdx;
+ nCount = nMode;
+ nSetColType = nType;
+ nAbsDiff = (sal_uInt16)nAbsDif;
+ nRelDiff = (sal_uInt16)nRelDif;
+ }
+
+};
+
+class SwUndoTblMerge : public SwUndo, private SwUndRng
+{
+ sal_uLong nTblNode;
+ _SaveTable* pSaveTbl;
+ SvULongs aBoxes, aNewSttNds;
+ SwUndoMoves* pMoves;
+ SwHistory* pHistory;
+
+public:
+ SwUndoTblMerge( const SwPaM& rTblSel );
+
+ virtual ~SwUndoTblMerge();
+
+ virtual void UndoImpl( ::sw::UndoRedoContext & );
+ virtual void RedoImpl( ::sw::UndoRedoContext & );
+
+ void MoveBoxCntnt( SwDoc* pDoc, SwNodeRange& rRg, SwNodeIndex& rPos );
+
+ void SetSelBoxes( const SwSelBoxes& rBoxes );
+
+ void AddNewBox( sal_uLong nSttNdIdx )
+ { aNewSttNds.Insert( nSttNdIdx, aNewSttNds.Count() ); }
+
+ void SaveCollection( const SwTableBox& rBox );
+
+};
+
+
+class SwUndoTblNumFmt : public SwUndo
+{
+ SfxItemSet *pBoxSet;
+ SwHistory* pHistory;
+ String aStr, aNewFml;
+
+ sal_uLong nFmtIdx, nNewFmtIdx;
+ double fNum, fNewNum;
+ sal_uLong nNode;
+ sal_uLong nNdPos;
+
+ sal_Bool bNewFmt : 1;
+ sal_Bool bNewFml : 1;
+ sal_Bool bNewValue : 1;
+
+public:
+ SwUndoTblNumFmt( const SwTableBox& rBox, const SfxItemSet* pNewSet = 0 );
+
+ virtual ~SwUndoTblNumFmt();
+
+ virtual void UndoImpl( ::sw::UndoRedoContext & );
+ virtual void RedoImpl( ::sw::UndoRedoContext & );
+
+ void SetNumFmt( sal_uLong nNewNumFmtIdx, const double& rNewNumber )
+ { nFmtIdx = nNewNumFmtIdx; fNum = rNewNumber; }
+ void SetBox( const SwTableBox& rBox );
+};
+
+class _UndoTblCpyTbl_Entries;
+
+class SwUndoTblCpyTbl : public SwUndo
+{
+ _UndoTblCpyTbl_Entries* pArr;
+ SwUndoTblNdsChg* pInsRowUndo;
+
+ //b6341295: When redlining is active, PrepareRedline has to create the
+ //redlining attributes for the new and the old table cell content
+ SwUndo* PrepareRedline( SwDoc* pDoc, const SwTableBox& rBox,
+ const SwPosition& rPos, bool& rJoin, bool bRedo );
+public:
+ SwUndoTblCpyTbl();
+
+ virtual ~SwUndoTblCpyTbl();
+
+ virtual void UndoImpl( ::sw::UndoRedoContext & );
+ virtual void RedoImpl( ::sw::UndoRedoContext & );
+
+ void AddBoxBefore( const SwTableBox& rBox, sal_Bool bDelCntnt );
+ void AddBoxAfter( const SwTableBox& rBox, const SwNodeIndex& rIdx,
+ sal_Bool bDelCntnt );
+
+ sal_Bool IsEmpty() const;
+ sal_Bool InsertRow( SwTable& rTbl, const SwSelBoxes& rBoxes, sal_uInt16 nCnt );
+};
+
+class SwUndoCpyTbl : public SwUndo
+{
+ SwUndoDelete* pDel;
+ sal_uLong nTblNode;
+public:
+ SwUndoCpyTbl();
+
+ virtual ~SwUndoCpyTbl();
+
+ virtual void UndoImpl( ::sw::UndoRedoContext & );
+ virtual void RedoImpl( ::sw::UndoRedoContext & );
+
+ void SetTableSttIdx( sal_uLong nIdx ) { nTblNode = nIdx; }
+};
+
+class SwUndoSplitTbl : public SwUndo
+{
+ sal_uLong nTblNode, nOffset;
+ SwSaveRowSpan* mpSaveRowSpan; // stores row span values at the splitting row
+ _SaveTable* pSavTbl;
+ SwHistory* pHistory;
+ sal_uInt16 nMode, nFmlEnd;
+ sal_Bool bCalcNewSize;
+public:
+ SwUndoSplitTbl( const SwTableNode& rTblNd, SwSaveRowSpan* pRowSp,
+ sal_uInt16 nMode, sal_Bool bCalcNewSize );
+
+ virtual ~SwUndoSplitTbl();
+
+ virtual void UndoImpl( ::sw::UndoRedoContext & );
+ virtual void RedoImpl( ::sw::UndoRedoContext & );
+ virtual void RepeatImpl( ::sw::RepeatContext & );
+
+ void SetTblNodeOffset( sal_uLong nIdx ) { nOffset = nIdx - nTblNode; }
+ SwHistory* GetHistory() { return pHistory; }
+ void SaveFormula( SwHistory& rHistory );
+};
+
+class SwUndoMergeTbl : public SwUndo
+{
+ String aName;
+ sal_uLong nTblNode;
+ _SaveTable* pSavTbl, *pSavHdl;
+ SwHistory* pHistory;
+ sal_uInt16 nMode;
+ sal_Bool bWithPrev;
+public:
+ SwUndoMergeTbl( const SwTableNode& rTblNd, const SwTableNode& rDelTblNd,
+ sal_Bool bWithPrev, sal_uInt16 nMode );
+
+ virtual ~SwUndoMergeTbl();
+
+ virtual void UndoImpl( ::sw::UndoRedoContext & );
+ virtual void RedoImpl( ::sw::UndoRedoContext & );
+ virtual void RepeatImpl( ::sw::RepeatContext & );
+
+ void SaveFormula( SwHistory& rHistory );
+};
+
+
+//--------------------------------------------------------------------
+
+class SwUndoTblHeadline : public SwUndo
+{
+ sal_uLong nTblNd;
+ sal_uInt16 nOldHeadline;
+ sal_uInt16 nNewHeadline;
+public:
+ SwUndoTblHeadline( const SwTable&, sal_uInt16 nOldHdl, sal_uInt16 nNewHdl );
+
+ virtual void UndoImpl( ::sw::UndoRedoContext & );
+ virtual void RedoImpl( ::sw::UndoRedoContext & );
+ virtual void RepeatImpl( ::sw::RepeatContext & );
+};
+
+#endif // SW_UNDO_TABLE_HXX
+
diff --git a/sw/source/core/inc/acorrect.hxx b/sw/source/core/inc/acorrect.hxx
new file mode 100644
index 000000000000..d8b4f3ae0ffa
--- /dev/null
+++ b/sw/source/core/inc/acorrect.hxx
@@ -0,0 +1,126 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+#ifndef _ACORRECT_HXX
+#define _ACORRECT_HXX
+
+#include <editeng/svxacorr.hxx>
+
+#include <swundo.hxx>
+
+
+class SwEditShell;
+class SwPaM;
+class SwNodeIndex;
+struct SwPosition;
+class SfxItemSet;
+
+class SwDontExpandItem
+{
+ SfxItemSet* pDontExpItems;
+public:
+ SwDontExpandItem() :
+ pDontExpItems(0){}
+ ~SwDontExpandItem();
+
+ void SaveDontExpandItems( const SwPosition& rPos );
+ void RestoreDontExpandItems( const SwPosition& rPos );
+
+};
+
+class SwAutoCorrDoc : public SvxAutoCorrDoc
+{
+ SwEditShell& rEditSh;
+ SwPaM& rCrsr;
+ SwNodeIndex* pIdx;
+ int m_nEndUndoCounter;
+ bool bUndoIdInitialized;
+
+ void DeleteSel( SwPaM& rDelPam );
+
+public:
+ SwAutoCorrDoc( SwEditShell& rEditShell, SwPaM& rPam, sal_Unicode cIns = 0 );
+ ~SwAutoCorrDoc();
+
+ virtual sal_Bool Delete( xub_StrLen nStt, xub_StrLen nEnd );
+ virtual sal_Bool Insert( xub_StrLen nPos, const String& rTxt );
+ virtual sal_Bool Replace( xub_StrLen nPos, const String& rTxt );
+ virtual sal_Bool ReplaceRange( xub_StrLen nPos, xub_StrLen nLen, const String& rTxt );
+
+ virtual sal_Bool SetAttr( xub_StrLen nStt, xub_StrLen nEnd, sal_uInt16 nSlotId,
+ SfxPoolItem& );
+
+ virtual sal_Bool SetINetAttr( xub_StrLen nStt, xub_StrLen nEnd, const String& rURL );
+
+ // returne den Text eines vorherigen Absatzes.
+ // Dieser darf nicht leer sein!
+ // Gibt es diesen nicht oder gibt es davor nur Leere, dann returne 0
+ // Das Flag gibt an:
+ // sal_True: den, vor der normalen Einfuegeposition (sal_True)
+ // sal_False: den, in den das korrigierte Wort eingfuegt wurde.
+ // (Muss nicht der gleiche Absatz sein!!!!)
+ virtual const String* GetPrevPara( sal_Bool bAtNormalPos );
+
+ virtual sal_Bool ChgAutoCorrWord( xub_StrLen& rSttPos, xub_StrLen nEndPos,
+ SvxAutoCorrect& rACorrect,
+ const String** ppPara );
+
+ // wird nach dem austauschen der Zeichen von den Funktionen
+ // - FnCptlSttWrd
+ // - FnCptlSttSntnc
+ // gerufen. Dann koennen die Worte ggfs. in die Ausnahmelisten
+ // aufgenommen werden.
+ virtual void SaveCpltSttWord( sal_uLong nFlag, xub_StrLen nPos,
+ const String& rExceptWord, sal_Unicode cChar );
+ virtual LanguageType GetLanguage( xub_StrLen nPos, sal_Bool bPrevPara ) const;
+};
+
+class SwAutoCorrExceptWord
+{
+ String sWord;
+ sal_uLong nFlags, nNode;
+ xub_StrLen nCntnt;
+ sal_Unicode cChar;
+ LanguageType eLanguage;
+ sal_Bool bDeleted;
+public:
+ SwAutoCorrExceptWord( sal_uLong nAFlags, sal_uLong nNd, xub_StrLen nContent,
+ const String& rWord, sal_Unicode cChr,
+ LanguageType eLang )
+ : sWord(rWord), nFlags(nAFlags), nNode(nNd), nCntnt(nContent),
+ cChar(cChr), eLanguage(eLang), bDeleted(sal_False)
+ {}
+
+ sal_Bool IsDeleted() const { return bDeleted; }
+ void CheckChar( const SwPosition& rPos, sal_Unicode cChar );
+ sal_Bool CheckDelChar( const SwPosition& rPos );
+};
+
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/inc/anchoredobjectposition.hxx b/sw/source/core/inc/anchoredobjectposition.hxx
new file mode 100644
index 000000000000..88affdb989b2
--- /dev/null
+++ b/sw/source/core/inc/anchoredobjectposition.hxx
@@ -0,0 +1,474 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+ /*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+#ifndef _ANCHOREDOBJECTPOSITION_HXX
+#define _ANCHOREDOBJECTPOSITION_HXX
+
+#include <swtypes.hxx>
+// #i11860#
+#include <frame.hxx>
+
+class SdrObject;
+class SwFrm;
+class SwFlyFrm;
+class SwContact;
+class SwFrmFmt;
+class SwRect;
+class SvxLRSpaceItem;
+class SvxULSpaceItem;
+class SwFmtHoriOrient;
+// #i26701#
+class SwAnchoredObject;
+
+namespace objectpositioning
+{
+ class SwEnvironmentOfAnchoredObject;
+
+ class SwAnchoredObjectPosition
+ {
+ private:
+ // object to be positioned
+ SdrObject& mrDrawObj;
+
+ // information about object
+ // does the object represents a Writer fly frame
+ bool mbIsObjFly;
+ // #i26791# - anchored object the object belongs to;
+ SwAnchoredObject* mpAnchoredObj;
+ // frame the object is anchored at
+ SwFrm* mpAnchorFrm;
+ // contact object
+ SwContact* mpContact;
+ // frame format
+ const SwFrmFmt* mpFrmFmt;
+ // #i62875#
+ bool mbFollowTextFlow;
+ // #i62875#
+ // for compatibility option <DoNotCaptureDrawObjsOnPage>
+ bool mbDoNotCaptureAnchoredObj;
+
+ /** determine information about object
+
+ member <mbIsObjFly>, <mpAnchoredObj>, <mpAnchorFrm>, <mpContact>
+ and <mpFrmFmt> are set
+ */
+ void _GetInfoAboutObj();
+
+ // #i62875#
+ // --> OD 2009-09-01 #mongolianlayout# - add parameter <bVertL2R>
+ SwTwips _ImplAdjustVertRelPos( const SwTwips nTopOfAnch,
+ const bool bVert,
+ const bool bVertL2R,
+ const SwFrm& rPageAlignLayFrm,
+ const SwTwips nProposedRelPosY,
+ const bool bFollowTextFlow,
+ const bool bCheckBottom = true ) const;
+ SwTwips _ImplAdjustHoriRelPos( const SwFrm& _rPageAlignLayFrm,
+ const SwTwips _nProposedRelPosX ) const;
+
+ protected:
+ SwAnchoredObjectPosition( SdrObject& _rDrawObj );
+ virtual ~SwAnchoredObjectPosition();
+
+ // accessors for object and its corresponding data/information
+ inline SdrObject& GetObject() const
+ {
+ return mrDrawObj;
+ }
+ inline bool IsObjFly() const
+ {
+ return mbIsObjFly;
+ }
+ inline SwAnchoredObject& GetAnchoredObj() const
+ {
+ return *mpAnchoredObj;
+ }
+ inline SwFrm& GetAnchorFrm() const
+ {
+ return *mpAnchorFrm;
+ }
+ inline SwContact& GetContact() const
+ {
+ return *mpContact;
+ }
+ inline const SwFrmFmt& GetFrmFmt() const
+ {
+ return *mpFrmFmt;
+ }
+ // #i62875#
+ inline bool DoesObjFollowsTextFlow() const
+ {
+ return mbFollowTextFlow;
+ }
+
+ // virtual methods providing data for to character anchored objects.
+ virtual bool IsAnchoredToChar() const;
+ virtual const SwFrm* ToCharOrientFrm() const;
+ virtual const SwRect* ToCharRect() const;
+ // #i22341#
+ virtual SwTwips ToCharTopOfLine() const;
+
+ // *********************************************************************
+ /** helper method to determine top of a frame for the vertical
+ object positioning
+
+ #i11860#
+ */
+ SwTwips _GetTopForObjPos( const SwFrm& _rFrm,
+ const SwRectFn& _fnRect,
+ const bool _bVert ) const;
+
+ // *********************************************************************
+ void _GetVertAlignmentValues( const SwFrm& _rVertOrientFrm,
+ const SwFrm& _rPageAlignLayFrm,
+ const sal_Int16 _eRelOrient,
+ SwTwips& _orAlignAreaHeight,
+ SwTwips& _orAlignAreaOffset ) const;
+
+ // *********************************************************************
+ // #i26791# - add output parameter <_roVertOffsetToFrmAnchorPos>
+ SwTwips _GetVertRelPos( const SwFrm& _rVertOrientFrm,
+ const SwFrm& _rPageAlignLayFrm,
+ const sal_Int16 _eVertOrient,
+ const sal_Int16 _eRelOrient,
+ const SwTwips _nVertPos,
+ const SvxLRSpaceItem& _rLRSpacing,
+ const SvxULSpaceItem& _rULSpacing,
+ SwTwips& _roVertOffsetToFrmAnchorPos ) const;
+
+ // *********************************************************************
+ /** adjust calculated vertical in order to keep object inside
+ 'page' alignment layout frame.
+
+ #i31805# - add parameter <_bCheckBottom>
+ #i26945# - add parameter <_bFollowTextFlow>
+ #i62875# - made inline, intrinsic actions moved
+ to private method <_ImplAdjustVertRelPos>, which is only
+ called, if <mbDoNotCaptureAnchoredObj> not set.
+ OD 2009-09-01 #mongolianlayout# - add parameter <bVertL2R>
+
+ @param nTopOfAnch
+ input parameter - 'vertical' position, at which the relative
+ position of the object is calculated from.
+
+ @param bVert
+ input parameter - boolean, indicating, if object is in vertical
+ layout.
+
+ @param bVertL2R
+ input parameter - boolean, indicating, if object is in mongolian
+ layout (vertical left-to-right layout).
+
+ @param rPageAlignLayFrm
+ input parameter - layout frame, which determines the 'page area'
+ the object has to be vertical positioned in.
+
+ @param nProposedRelPosY
+ input parameter - proposed relative vertical position, which
+ will be adjusted.
+
+ @param bFollowTextFlow
+ input parameter - value of attribute 'Follow text flow' of the
+ anchored object.
+
+ @param bCheckBottom
+ input parameter - boolean indicating, if bottom of anchored
+ object has to be checked and thus, (if needed) the proposed
+ relative position has to be adjusted. default value <true>
+ */
+ inline SwTwips _AdjustVertRelPos( const SwTwips nTopOfAnch,
+ const bool bVert,
+ const bool bVertL2R,
+ const SwFrm& rPageAlignLayFrm,
+ const SwTwips nProposedRelPosY,
+ const bool bFollowTextFlow,
+ const bool bCheckBottom = true ) const
+ {
+ return !mbDoNotCaptureAnchoredObj
+ ? _ImplAdjustVertRelPos( nTopOfAnch, bVert, bVertL2R,
+ rPageAlignLayFrm,
+ nProposedRelPosY,
+ bFollowTextFlow,
+ bCheckBottom )
+ : nProposedRelPosY;
+ }
+
+ // *********************************************************************
+ /** calculate relative horizontal position
+
+ #i26791# - add output parameter
+ <_roHoriOffsetToFrmAnchorPos>
+
+ @param _rHoriOrientFrm
+ input parameter - frame the horizontal position of the object
+ is oriented at.
+
+ @param _rEnvOfObj
+ input parameter - object instance to retrieve environment
+ information about the object
+
+ @param _rHoriOrient
+ input parameter - horizontal positioning and alignment, for which
+ the relative position is calculated.
+
+ @param _rLRSpacing
+ input parameter - left and right spacing of the object to the text
+
+ @param _rULSpacing
+ input parameter - upper and lower spacing of the object to the text
+
+ @param _bObjWrapThrough
+ input parameter - boolean indicating, if object has wrap mode
+ 'wrap through'.
+
+ @param _nRelPosY
+ input parameter - relative vertical position
+
+ @param _roHoriOffsetToFrmAnchorPos
+ output parameter - 'horizontal' offset to frame anchor position
+ according to the alignment
+
+ @return relative horizontal position in SwTwips
+ */
+ SwTwips _CalcRelPosX( const SwFrm& _rHoriOrientFrm,
+ const SwEnvironmentOfAnchoredObject& _rEnvOfObj,
+ const SwFmtHoriOrient& _rHoriOrient,
+ const SvxLRSpaceItem& _rLRSpacing,
+ const SvxULSpaceItem& _rULSpacing,
+ const bool _bObjWrapThrough,
+ const SwTwips _nRelPosY,
+ SwTwips& _roHoriOffsetToFrmAnchorPos
+ ) const;
+
+ // *********************************************************************
+ /** adjust calculated horizontal in order to keep object inside
+ 'page' alignment layout frame for object type position TO_CNTNT
+
+ #i62875# - made inline, intrinsic actions moved
+ to private method <_ImplAdjustHoriRelPos>, which is only
+ called, if <mbDoNotCaptureAnchoredObj> not set.
+
+ @param _rPageAlignLayFrm
+ input paramter - layout frame, which determines the 'page area'
+ the object has to be horizontal positioned in.
+
+ @param _nProposedRelPosX
+ input parameter - proposed relative horizontal position, which
+ will be adjusted.
+
+ @return adjusted relative horizontal position in SwTwips.
+ */
+ inline SwTwips _AdjustHoriRelPos( const SwFrm& _rPageAlignLayFrm,
+ const SwTwips _nProposedRelPosX ) const
+ {
+ return !mbDoNotCaptureAnchoredObj
+ ? _ImplAdjustHoriRelPos( _rPageAlignLayFrm, _nProposedRelPosX )
+ : _nProposedRelPosX;
+ }
+
+ // *********************************************************************
+ /** toggle given horizontal orientation and relative alignment
+
+ @param _bToggleLeftRight
+ input parameter - boolean indicating, if horizontal orientation
+ and relative alignment has to be toggled.
+
+ @param _ioeHoriOrient
+ input/output parameter - horizontal orientation, that is toggled,
+ if needed.
+
+ @param _iopeRelOrient
+ optional input/output parameter (default value NULL)
+ - if set, relative alignment, that is toggled, if needed.
+ */
+ void _ToggleHoriOrientAndAlign( const bool _bToggleLeftRight,
+ sal_Int16& _ioeHoriOrient,
+ sal_Int16& _iopeRelOrient
+ ) const;
+
+ // *********************************************************************
+ /** determine alignment values for horizontal position of object
+
+ @param _rHoriOrientFrm
+ input parameter - frame the horizontal position of the object
+ is oriented at.
+
+ @param _rPageAlignLayFrm
+ input paramter - layout frame, which determines the 'page area'
+ the object has to be horizontal positioned in.
+
+ @param _eRelOrient
+ input parameter - horizontal relative alignment, for which
+ the relative position is calculated.
+
+ @param _bToggleLeftRight
+ input parameter - boolean indicating, if left/right alignments
+ have to be toggled.
+
+ @param _bObjWrapThrough
+ input parameter - boolean indicating, if object has wrap mode
+ 'wrap through'.
+ important note: value is only relevant, if _rHoriOrientFrm is
+ a text frame.
+
+ @param _orAlignAreaWidth
+ output parameter - width in SwTwips of the area the horizontal
+ position is aligned to.
+
+ @param _orAlignAreaOffset
+ output parameter - offset in SwTwips of the area the horizontal
+ position is aligned to. offset is given to the 'left' of the
+ anchor position.
+
+ @param _obAlignedRelToPage
+ output parameter - boolean indicating, that object is aligned
+ to 'page area'.
+ */
+ void _GetHoriAlignmentValues( const SwFrm& _rHoriOrientFrm,
+ const SwFrm& _rPageAlignLayFrm,
+ const sal_Int16 _eRelOrient,
+ const bool _bObjWrapThrough,
+ SwTwips& _orAlignAreaWidth,
+ SwTwips& _orAlignAreaOffset,
+ bool& _obAlignedRelToPage ) const;
+
+ // *********************************************************************
+ /** adjust calculated horizontal position in order to draw object
+ aside other objects with same positioning
+
+ @param _rHoriOrientFrm
+ input parameter - frame the horizontal position of the object
+ is oriented at.
+
+ @param _nProposedRelPosX
+ input parameter - proposed relative horizontal position, which
+ will be adjusted.
+
+ @param _nRelPosY
+ input parameter - relative vertical position
+
+ @param _eHoriOrient
+ input parameter - horizontal position of object
+
+ @param _eRelOrient
+ inpt parameter - alignment of object
+
+ @param _rLRSpacing
+ input parameter - left and right spacing of the object to the text
+
+ @param _rULSpacing
+ input parameter - upper and lower spacing of the object to the text
+
+ @param _bEvenPage
+ input parameter - boolean indicating, if object is on an even page.
+
+ @return adjusted relative horizontal position in SwTwips
+ */
+ SwTwips _AdjustHoriRelPosForDrawAside( const SwFrm& _rHoriOrientFrm,
+ const SwTwips _nProposedRelPosX,
+ const SwTwips _nRelPosY,
+ const sal_Int16 _eHoriOrient,
+ const sal_Int16 _eRelOrient,
+ const SvxLRSpaceItem& _rLRSpacing,
+ const SvxULSpaceItem& _rULSpacing,
+ const bool _bEvenPage
+ ) const;
+
+ // *********************************************************************
+ /** detemine, if object has to draw aside given fly frame
+
+ method used by <_AdjustHoriRelPosForDrawAside(..)>
+
+ @param _pFly
+ input parameter - fly frame the draw aside check is done for.
+
+ @param _rObjRect
+ input parameter - proposed object rectangle
+
+ @param _pObjContext
+ input parameter - context of the object
+
+ @param _nObjIndex
+ input parameter - index of the anchor frame of the object
+
+ @param _bEvenPage
+ input parameter - boolean indicating, if object is on an even page.
+
+ @param _eHoriOrient
+ input parameter - horizontal position of object
+
+ @param _eRelOrient
+ inpt parameter - alignment of object
+
+ @return boolean indicating, if object has to be drawn aside
+ given fly frame.
+ */
+ bool _DrawAsideFly( const SwFlyFrm* _pFly,
+ const SwRect& _rObjRect,
+ const SwFrm* _pObjContext,
+ const sal_uLong _nObjIndex,
+ const bool _bEvenPage,
+ const sal_Int16 _eHoriOrient,
+ const sal_Int16 _eRelOrient
+ ) const;
+
+ // *********************************************************************
+ /** determine, if object has to draw aside another object
+
+ the different alignments of the objects determines, if one has
+ to draw aside another one. Thus, the given alignment are checked
+ against each other, which one has to be drawn aside the other one.
+ depending on parameter _bLeft check is done for left or right
+ positioning.
+ method used by <_DrawAsideFly(..)>
+
+ @param _eRelOrient1
+ input parameter - alignment 1
+
+ @param _eRelOrient2
+ input parameter - alignment 2
+
+ @param _bLeft
+ input parameter - boolean indicating, if check is done for left
+ or for right positioning.
+
+ @return boolean indicating, if an object with an alignment
+ <_eRelOrient1> has to be drawn aside an object with an
+ alignment <_eRelOrient2>
+ */
+ bool _Minor( sal_Int16 _eRelOrient1,
+ sal_Int16 _eRelOrient2,
+ bool _bLeft ) const;
+
+ public:
+ virtual void CalcPosition() = 0;
+ };
+} // namespace objectpositioning
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/inc/ascharanchoredobjectposition.hxx b/sw/source/core/inc/ascharanchoredobjectposition.hxx
new file mode 100644
index 000000000000..f83cdf6259c7
--- /dev/null
+++ b/sw/source/core/inc/ascharanchoredobjectposition.hxx
@@ -0,0 +1,174 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+ /*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+#ifndef _ASCHARANCHOREDOBJECTPOSITION_HXX
+#define _ASCHARANCHOREDOBJECTPOSITION_HXX
+#include <anchoredobjectposition.hxx>
+#include <sal/types.h>
+#include <swtypes.hxx>
+#include <swrect.hxx>
+
+class SwTxtFrm;
+class SwFmtVertOrient;
+
+namespace objectpositioning
+{
+ // flags for positioning algorithm of as-character-anchored objects
+ typedef sal_uInt8 AsCharFlags;
+ #define AS_CHAR_NOFLAG 0
+ #define AS_CHAR_QUICK 1
+ #define AS_CHAR_ULSPACE 2
+ #define AS_CHAR_INIT 4
+ #define AS_CHAR_ROTATE 8
+ #define AS_CHAR_REVERSE 16
+ #define AS_CHAR_BIDI 32
+
+ class SwAsCharAnchoredObjectPosition : public SwAnchoredObjectPosition
+ {
+ private:
+ // data to calculate object position
+ // proposed anchor position, starting point for the calculation
+ // of the object position
+ const Point& mrProposedAnchorPos;
+ // flags that influences the calculation of the anchor position
+ // AS_CHAR_QUICK : quick formatting - calculated position not set at object
+ // AS_CHAR_ULSPACE : consider upper/lower spacing - adjustment of anchor position
+ // AS_CHAR_INIT : initial calculation
+ // AS_CHAR_ROTATE : object is rotated by 90 degrees
+ // AS_CHAR_REVERSE : object is reversed (rotated by 270 degrees)
+ // AS_CHAR_BIDI : object belongs to a BIDI-multi-portion
+ const AsCharFlags mnFlags;
+ // needed line values for the different alignments.
+ const SwTwips mnLineAscent;
+ const SwTwips mnLineDescent;
+ const SwTwips mnLineAscentInclObjs;
+ const SwTwips mnLineDescentInclObjs;
+
+ // calculated data for object position
+ Point maAnchorPos;
+ SwTwips mnRelPos;
+ SwRect maObjBoundRect;
+ // line alignment relative to line height; gives feedback for line formatting
+ // 0 - no line alignment, 1 - at top, 2 - at center, 3 - at bottom
+ sal_uInt8 mnLineAlignment;
+
+ // method to cast <SwAnchoredObjectPosition::GetAnchorFrm()>
+ const SwTxtFrm& GetAnchorTxtFrm() const;
+
+ /** determine the relative position to base line for object position
+
+ @author OD
+
+ @param _ObjBoundHeight
+ height including corresponding spacing of the object, for which
+ the Y-position has to be calculated.
+
+ @param _rVert
+ given vertical positioning and alignment
+
+ @return relative position to the base line
+ */
+ SwTwips _GetRelPosToBase( const SwTwips _nObjBoundHeight,
+ const SwFmtVertOrient& _rVert );
+
+ // *********************************************************************
+ public:
+ /** construtor; provided object to be positioned and needed data
+ for calculation of the object position
+
+ OD 28.10.2003 #110978#
+
+ @param _rDrawObj
+ input parameter - object, that is be positioned.
+
+ @param _rProposedAnchorPos
+ proposed anchor position; starting point for the calculation
+ of the anchor position
+
+ @param _nFlags
+ flags that influences the calculation of the anchor position
+ AS_CHAR_QUICK : quick formatting - calculated position not set at object
+ AS_CHAR_ULSPACE : consider upper/lower spacing - adjustment of anchor position
+ AS_CHAR_INIT : initial calculation
+ AS_CHAR_ROTATE : object is rotated by 90 degrees
+ AS_CHAR_REVERSE : object is reversed (rotated by 270 degrees)
+ AS_CHAR_BIDI : object belongs to a BIDI-multi-portion
+
+ @param _nLineAscent, _nLineDescent, _nLineAscentInclObjs,
+ _nLineDescentInclObjs - needed line values for the different
+ alignments.
+
+ @author OD
+ */
+ SwAsCharAnchoredObjectPosition( SdrObject& _rDrawObj,
+ const Point& _rProposedAnchorPos,
+ const AsCharFlags _nFlags,
+ const SwTwips _nLineAscent,
+ const SwTwips _nLineDescent,
+ const SwTwips _nLineAscentInclObjs,
+ const SwTwips _nLineDescentInclObjs );
+ virtual ~SwAsCharAnchoredObjectPosition();
+
+ /** calculate position for object position
+
+ members <maAnchorPos>, <mnRelPos>, <maObjBoundRect> and
+ <mnLineAlignment> are calculated.
+ calculated position is set at the given object.
+
+ @author OD
+ */
+ virtual void CalcPosition();
+
+ /** calculated anchored position for object position type AS_CHAR
+
+ @author OD
+ */
+ Point GetAnchorPos() const;
+
+ /** calculated relative position to base line for object position type AS_CHAR
+
+ @author OD
+ */
+ SwTwips GetRelPosY() const;
+
+ /** determined object rectangle including spacing for object position type AS_CHAR
+
+ @author OD
+ */
+ SwRect GetObjBoundRectInclSpacing() const;
+
+ /** determined line alignment relative to line height
+
+ @author OD
+ */
+ sal_uInt8 GetLineAlignment() const;
+ };
+} // namespace objectpositioning
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/inc/attrhint.hxx b/sw/source/core/inc/attrhint.hxx
new file mode 100644
index 000000000000..da2ed160b9c4
--- /dev/null
+++ b/sw/source/core/inc/attrhint.hxx
@@ -0,0 +1,44 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef _ATTRHINT_HXX
+#define _ATTRHINT_HXX
+
+#include <svl/hint.hxx>
+
+class SwAttrHint : public SfxHint
+{
+ sal_Int32 nId;
+public:
+ SwAttrHint( sal_Int32 n )
+ : nId(n)
+ {}
+
+ sal_Int32 GetId() const { return nId; }
+};
+
+#endif
diff --git a/sw/source/core/inc/blink.hxx b/sw/source/core/inc/blink.hxx
new file mode 100644
index 000000000000..1a4b0a9252c0
--- /dev/null
+++ b/sw/source/core/inc/blink.hxx
@@ -0,0 +1,91 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+#ifndef _BLINK_HXX
+#define _BLINK_HXX
+
+class SwLinePortion;
+class SwRootFrm;
+class SwTxtFrm;
+
+#include <vcl/timer.hxx>
+#include <tools/gen.hxx>
+
+#include <svl/svarray.hxx>
+
+class SwBlinkPortion
+{
+ Point aPos;
+ const SwLinePortion *pPor;
+ const SwRootFrm *pFrm;
+ sal_uInt16 nDir;
+public:
+ SwBlinkPortion( const SwLinePortion* pPortion, sal_uInt16 nDirection )
+ { pPor = pPortion; nDir = nDirection; }
+ SwBlinkPortion( const SwBlinkPortion* pBlink, const SwLinePortion* pPort )
+ { pPor = pPort; pFrm = pBlink->pFrm; aPos = pBlink->aPos; nDir = pBlink->nDir; }
+ void SetPos( const Point& aNew ){ aPos = aNew; }
+ const Point& GetPos() const{ return aPos; }
+ void SetRootFrm( const SwRootFrm* pNew ){ pFrm = pNew; }
+ const SwRootFrm* GetRootFrm() const{ return pFrm; }
+ const SwLinePortion *GetPortion() const{ return pPor; }
+ sal_uInt16 GetDirection() const { return nDir; }
+ sal_Bool operator<( const SwBlinkPortion& rBlinkPortion ) const
+ { return (long)pPor < (long)rBlinkPortion.pPor; }
+ sal_Bool operator==( const SwBlinkPortion& rBlinkPortion ) const
+ { return (long)pPor == (long)rBlinkPortion.pPor; }
+};
+
+typedef SwBlinkPortion* SwBlinkPortionPtr;
+SV_DECL_PTRARR_SORT_DEL(SwBlinkList, SwBlinkPortionPtr, 0, 10)
+
+class SwBlink
+{
+ SwBlinkList aList;
+ AutoTimer aTimer;
+ sal_Bool bVisible;
+public:
+ SwBlink();
+ ~SwBlink();
+
+ DECL_LINK( Blinker, Timer * );
+
+ void Insert( const Point& rPoint, const SwLinePortion* pPor,
+ const SwTxtFrm *pTxtFrm, sal_uInt16 nDir );
+ void Replace( const SwLinePortion* pOld, const SwLinePortion* pNew );
+ void Delete( const SwLinePortion* pPor );
+ void FrmDelete( const SwRootFrm* pRoot );
+ inline sal_Bool IsVisible() const { return bVisible ; }
+};
+
+// Blink-Manager, globale Variable, in Blink.Cxx angelegt
+extern SwBlink *pBlink;
+
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/inc/bodyfrm.hxx b/sw/source/core/inc/bodyfrm.hxx
new file mode 100644
index 000000000000..42b77f36cec8
--- /dev/null
+++ b/sw/source/core/inc/bodyfrm.hxx
@@ -0,0 +1,54 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+#ifndef _BODYFRM_HXX
+#define _BODYFRM_HXX
+
+#include <tools/mempool.hxx>
+#include "layfrm.hxx"
+
+class SwBorderAttrs;
+
+class SwBodyFrm: public SwLayoutFrm
+{
+protected:
+ virtual void Format( const SwBorderAttrs *pAttrs = 0 );
+
+#if defined ( GCC) && defined ( C272 )
+ ~SwBodyFrm();
+#endif
+public:
+ SwBodyFrm( SwFrmFmt*, SwFrm* );
+
+ virtual void Paint( const SwRect&, const SwPrintData *pPrintData = NULL ) const;
+
+ DECL_FIXEDMEMPOOL_NEWDEL(SwBodyFrm)
+};
+
+#endif //_BODYFRM_HXX
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/inc/bookmrk.hxx b/sw/source/core/inc/bookmrk.hxx
new file mode 100644
index 000000000000..06933e804888
--- /dev/null
+++ b/sw/source/core/inc/bookmrk.hxx
@@ -0,0 +1,266 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef _BOOKMRK_HXX
+#define _BOOKMRK_HXX
+
+#include <cppuhelper/weakref.hxx>
+
+#include <sfx2/Metadatable.hxx>
+
+#include <boost/scoped_ptr.hpp>
+#include <boost/noncopyable.hpp>
+#include <map>
+#include <rtl/ustring.hxx>
+
+#include <IMark.hxx>
+
+
+namespace com { namespace sun { namespace star {
+ namespace text { class XTextContent; }
+} } }
+
+struct SwPosition; // fwd Decl. wg. UI
+class SwDoc;
+
+namespace sw { namespace mark
+{
+ class MarkBase
+ : virtual public IMark
+ {
+ public:
+ //getters
+ virtual SwPosition& GetMarkPos() const
+ { return *m_pPos1; }
+ virtual const ::rtl::OUString& GetName() const
+ { return m_aName; }
+ virtual bool IsCoveringPosition(const SwPosition& rPos) const;
+ virtual SwPosition& GetOtherMarkPos() const
+ {
+ OSL_PRECOND(IsExpanded(), "<SwPosition::GetOtherMarkPos(..)> - I have no other Pos set." );
+ return *m_pPos2;
+ }
+ virtual SwPosition& GetMarkStart() const
+ {
+ if( !IsExpanded() ) return GetMarkPos( );
+ if ( GetMarkPos( ) < GetOtherMarkPos( ) )
+ return GetMarkPos();
+ else
+ return GetOtherMarkPos( );
+ }
+ virtual SwPosition& GetMarkEnd() const
+ {
+ if( !IsExpanded() ) return GetMarkPos();
+ if ( GetMarkPos( ) >= GetOtherMarkPos( ) )
+ return GetMarkPos( );
+ else
+ return GetOtherMarkPos( );
+ }
+ virtual bool IsExpanded() const
+ { return m_pPos2; }
+
+ //setters
+ virtual void SetName(const ::rtl::OUString& rName)
+ { m_aName = rName; }
+ virtual void SetMarkPos(const SwPosition& rNewPos);
+ virtual void SetOtherMarkPos(const SwPosition& rNewPos);
+ virtual void ClearOtherMarkPos()
+ { m_pPos2.reset(); }
+
+ virtual rtl::OUString ToString( ) const;
+
+ virtual void Swap()
+ {
+ if(m_pPos2)
+ m_pPos1.swap(m_pPos2);
+ }
+
+ virtual void InitDoc(SwDoc* const)
+ {}
+
+ virtual ~MarkBase();
+
+ const ::com::sun::star::uno::WeakReference<
+ ::com::sun::star::text::XTextContent> & GetXBookmark() const
+ { return m_wXBookmark; }
+ void SetXBookmark(::com::sun::star::uno::Reference<
+ ::com::sun::star::text::XTextContent> const& xBkmk)
+ { m_wXBookmark = xBkmk; }
+
+ protected:
+ // SwClient
+ virtual void Modify( const SfxPoolItem* pOld, const SfxPoolItem *pNew );
+
+ MarkBase(const SwPaM& rPaM,
+ const ::rtl::OUString& rName);
+ ::boost::scoped_ptr<SwPosition> m_pPos1;
+ ::boost::scoped_ptr<SwPosition> m_pPos2;
+ ::rtl::OUString m_aName;
+ static ::rtl::OUString GenerateNewName(const ::rtl::OUString& rPrefix);
+
+ ::com::sun::star::uno::WeakReference<
+ ::com::sun::star::text::XTextContent> m_wXBookmark;
+ };
+
+ class NavigatorReminder
+ : public MarkBase
+ {
+ public:
+ NavigatorReminder(const SwPaM& rPaM);
+ private:
+ static const ::rtl::OUString our_sNamePrefix;
+ };
+
+ class UnoMark
+ : public MarkBase
+ {
+ public:
+ UnoMark(const SwPaM& rPaM);
+ private:
+ static const ::rtl::OUString our_sNamePrefix;
+ };
+
+ class DdeBookmark
+ : public MarkBase
+ {
+ public:
+ DdeBookmark(const SwPaM& rPaM);
+
+ //getters
+ const SwServerObject* GetRefObject() const
+ { return &m_aRefObj; }
+ SwServerObject* GetRefObject()
+ { return &m_aRefObj; }
+
+ bool IsServer() const
+ { return m_aRefObj.Is(); }
+
+ //setters
+ void SetRefObject( SwServerObject* pObj );
+
+ void DeregisterFromDoc(SwDoc* const pDoc);
+ virtual ~DdeBookmark();
+ private:
+ SwServerObjectRef m_aRefObj;
+ static const ::rtl::OUString our_sNamePrefix;
+ };
+
+ class Bookmark
+ : virtual public IBookmark
+ , public DdeBookmark
+ , public ::sfx2::Metadatable
+ {
+ public:
+ Bookmark(const SwPaM& rPaM,
+ const KeyCode& rCode,
+ const ::rtl::OUString& rName,
+ const ::rtl::OUString& rShortName);
+ virtual void InitDoc(SwDoc* const io_Doc);
+
+ virtual const ::rtl::OUString& GetShortName() const
+ { return m_sShortName; }
+ virtual const KeyCode& GetKeyCode() const
+ { return m_aCode; }
+ virtual void SetShortName(const ::rtl::OUString& rShortName)
+ { m_sShortName = rShortName; }
+ virtual void SetKeyCode(const KeyCode& rCode)
+ { m_aCode = rCode; }
+
+ // ::sfx2::Metadatable
+ virtual ::sfx2::IXmlIdRegistry& GetRegistry();
+ virtual bool IsInClipboard() const;
+ virtual bool IsInUndo() const;
+ virtual bool IsInContent() const;
+ virtual ::com::sun::star::uno::Reference<
+ ::com::sun::star::rdf::XMetadatable > MakeUnoObject();
+
+ private:
+ KeyCode m_aCode;
+ ::rtl::OUString m_sShortName;
+ };
+
+ class Fieldmark
+ : virtual public IFieldmark
+ , public MarkBase
+ {
+ public:
+ Fieldmark(const SwPaM& rPaM);
+
+ // getters
+ virtual ::rtl::OUString GetFieldname() const
+ { return m_aFieldname; }
+ virtual ::rtl::OUString GetFieldHelptext() const
+ { return m_aFieldHelptext; }
+
+ virtual IFieldmark::parameter_map_t* GetParameters()
+ { return &m_vParams; }
+
+ virtual const IFieldmark::parameter_map_t* GetParameters() const
+ { return &m_vParams; }
+
+ // setters
+ virtual void SetFieldname(const ::rtl::OUString& aFieldname)
+ { m_aFieldname = aFieldname; }
+ virtual void SetFieldHelptext(const ::rtl::OUString& aFieldHelptext)
+ { m_aFieldHelptext = aFieldHelptext; }
+
+ virtual void Invalidate();
+ virtual rtl::OUString ToString() const;
+ private:
+ ::rtl::OUString m_aFieldname;
+ ::rtl::OUString m_aFieldHelptext;
+ IFieldmark::parameter_map_t m_vParams;
+
+ static const ::rtl::OUString our_sNamePrefix;
+ };
+
+ class TextFieldmark
+ : public Fieldmark
+ {
+ public:
+ TextFieldmark(const SwPaM& rPaM);
+ virtual void InitDoc(SwDoc* const io_pDoc);
+ };
+
+ class CheckboxFieldmark
+ : virtual public ICheckboxFieldmark
+ , public Fieldmark
+ {
+ public:
+ CheckboxFieldmark(const SwPaM& rPaM);
+ virtual void InitDoc(SwDoc* const io_pDoc);
+ bool IsChecked() const;
+ void SetChecked(bool checked);
+
+ virtual rtl::OUString toString( ) const;
+ };
+
+}}
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/inc/cellfrm.hxx b/sw/source/core/inc/cellfrm.hxx
new file mode 100644
index 000000000000..66a2f6d36662
--- /dev/null
+++ b/sw/source/core/inc/cellfrm.hxx
@@ -0,0 +1,75 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+#ifndef SW_CELLFRM_HXX
+#define SW_CELLFRM_HXX
+
+#include <tools/mempool.hxx>
+
+#include "layfrm.hxx"
+
+class SwTableBox;
+struct SwCrsrMoveState;
+class SwBorderAttrs;
+
+class SwCellFrm: public SwLayoutFrm
+{
+ const SwTableBox* pTabBox;
+
+protected:
+ virtual void Format( const SwBorderAttrs *pAttrs = 0 );
+ virtual void Modify( const SfxPoolItem*, const SfxPoolItem* );
+
+public:
+ SwCellFrm( const SwTableBox &, SwFrm*, bool bInsertContent = true );
+ ~SwCellFrm();
+
+ virtual sal_Bool GetCrsrOfst( SwPosition *, Point&, SwCrsrMoveState* = 0 ) const;
+ virtual void Paint( SwRect const&,
+ SwPrintData const*const pPrintData = NULL ) const;
+ virtual void CheckDirection( sal_Bool bVert );
+
+ // --> OD 2010-02-17 #i103961#
+ virtual void Cut();
+ // <--
+
+ const SwTableBox *GetTabBox() const { return pTabBox; }
+
+ // used for breaking table rows:
+ SwCellFrm* GetFollowCell() const;
+ SwCellFrm* GetPreviousCell() const;
+
+ // used for rowspan stuff:
+ const SwCellFrm& FindStartEndOfRowSpanCell( bool bStart, bool bCurrentTab ) const;
+ long GetLayoutRowSpan() const;
+
+ DECL_FIXEDMEMPOOL_NEWDEL(SwCellFrm)
+};
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/inc/cntfrm.hxx b/sw/source/core/inc/cntfrm.hxx
new file mode 100644
index 000000000000..5f7c69f71cf4
--- /dev/null
+++ b/sw/source/core/inc/cntfrm.hxx
@@ -0,0 +1,153 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+#ifndef _CNTFRM_HXX
+#define _CNTFRM_HXX
+#include "frame.hxx"
+#include "flowfrm.hxx"
+#include "cshtyp.hxx"
+
+class SwLayoutFrm;
+class SwCntntNode;
+class SwBorderAttrs;
+class SwAttrSetChg;
+class SwTxtFrm;
+
+//Implementiert in cntfrm.cxx, wird von cntfrm.cxx und crsrsh.cxx angezogen
+extern sal_Bool GetFrmInPage( const SwCntntFrm*, SwWhichPage, SwPosPage, SwPaM* );
+
+class SwCntntFrm: public SwFrm, public SwFlowFrm
+{
+ friend void MakeNxt( SwFrm *pFrm, SwFrm *pNxt ); //ruft MakePrtArea
+
+ // --> OD 2007-11-26 #b6614158#
+ // parameter <bObjsInNewUpper>, indicating that objects are existing in
+ // remaining area of new upper
+ sal_Bool _WouldFit( SwTwips nSpace,
+ SwLayoutFrm *pNewUpper,
+ sal_Bool bTstMove,
+ const bool bObjsInNewUpper );
+ // <--
+ virtual void MakeAll();
+
+ void _UpdateAttr( const SfxPoolItem*, const SfxPoolItem*, sal_uInt8 &,
+ SwAttrSetChg *pa = 0, SwAttrSetChg *pb = 0 );
+
+ virtual sal_Bool ShouldBwdMoved( SwLayoutFrm *pNewUpper, sal_Bool, sal_Bool& );
+
+ const SwCntntFrm* ImplGetNextCntntFrm( bool bFwd ) const;
+
+protected:
+
+ sal_Bool MakePrtArea( const SwBorderAttrs & );
+
+ virtual void Modify( const SfxPoolItem*, const SfxPoolItem* );
+ virtual SwTwips ShrinkFrm( SwTwips, sal_Bool bTst = sal_False, sal_Bool bInfo = sal_False );
+ virtual SwTwips GrowFrm ( SwTwips, sal_Bool bTst = sal_False, sal_Bool bInfo = sal_False );
+
+ SwCntntFrm( SwCntntNode * const, SwFrm* );
+
+public:
+ virtual ~SwCntntFrm();
+ TYPEINFO(); //bereits in Basisklassen drin
+
+ virtual void Cut();
+ virtual void Paste( SwFrm* pParent, SwFrm* pSibling = 0 );
+
+ inline SwCntntNode *GetNode();
+ inline const SwCntntNode *GetNode() const;
+ sal_uInt16 GetSectionLevel();
+
+ inline const SwCntntFrm *GetFollow() const;
+ inline SwCntntFrm *GetFollow();
+ SwTxtFrm* FindMaster() const;
+
+ //Layoutabhaengiges Cursortravelling
+ virtual sal_Bool LeftMargin( SwPaM * ) const;
+ virtual sal_Bool RightMargin( SwPaM *, sal_Bool bAPI = sal_False ) const;
+ virtual sal_Bool UnitUp( SwPaM *, const SwTwips nOffset = 0,
+ sal_Bool bSetInReadOnly = sal_False ) const;
+ virtual sal_Bool UnitDown( SwPaM *, const SwTwips nOffset = 0,
+ sal_Bool bSetInReadOnly = sal_False ) const;
+ inline sal_Bool StartNextPage( SwPaM * ) const;
+ inline sal_Bool StartPrevPage( SwPaM * ) const;
+ inline sal_Bool StartCurrPage( SwPaM * ) const;
+ inline sal_Bool EndCurrPage( SwPaM * ) const;
+ inline sal_Bool EndNextPage( SwPaM * ) const;
+ inline sal_Bool EndPrevPage( SwPaM * ) const;
+
+ // nMaxHeight is the required height
+ // bSplit indicates, that the paragraph has to be split
+ // bTst indicates, that we are currently doing a test formatting
+ virtual sal_Bool WouldFit( SwTwips &nMaxHeight, sal_Bool &bSplit, sal_Bool bTst );
+
+ sal_Bool MoveFtnCntFwd( sal_Bool, SwFtnBossFrm* );//von MoveFwd gerufen bei Ftn-Inhalt
+
+ inline SwCntntFrm* GetNextCntntFrm() const;
+ inline SwCntntFrm* GetPrevCntntFrm() const;
+ static bool CalcLowers( SwLayoutFrm* pLay, const SwLayoutFrm* pDontLeave, long nBottom, bool bSkipRowSpanCells );
+ void RegisterToNode( SwCntntNode& );
+ static void DelFrms( const SwCntntNode& );
+};
+
+inline SwCntntFrm* SwCntntFrm::GetNextCntntFrm() const
+{
+ if ( GetNext() && GetNext()->IsCntntFrm() )
+ return (SwCntntFrm*)GetNext();
+ else
+ return (SwCntntFrm*)ImplGetNextCntntFrm( true );
+}
+
+inline SwCntntFrm* SwCntntFrm::GetPrevCntntFrm() const
+{
+ if ( GetPrev() && GetPrev()->IsCntntFrm() )
+ return (SwCntntFrm*)GetPrev();
+ else
+ return (SwCntntFrm*)ImplGetNextCntntFrm( false );
+}
+
+inline SwCntntNode *SwCntntFrm::GetNode()
+{
+ return (SwCntntNode*)GetDep();
+}
+inline const SwCntntNode *SwCntntFrm::GetNode() const
+{
+ return (SwCntntNode*)GetDep();
+}
+
+inline const SwCntntFrm *SwCntntFrm::GetFollow() const
+{
+ return (const SwCntntFrm*)SwFlowFrm::GetFollow();
+}
+inline SwCntntFrm *SwCntntFrm::GetFollow()
+{
+ return (SwCntntFrm*)SwFlowFrm::GetFollow();
+}
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/inc/colfrm.hxx b/sw/source/core/inc/colfrm.hxx
new file mode 100644
index 000000000000..0485cdf064d7
--- /dev/null
+++ b/sw/source/core/inc/colfrm.hxx
@@ -0,0 +1,45 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+#ifndef _COLFRM_HXX
+#define _COLFRM_HXX
+
+#include <tools/mempool.hxx>
+#include "ftnboss.hxx"
+
+class SwColumnFrm: public SwFtnBossFrm
+{
+public:
+ SwColumnFrm( SwFrmFmt*, SwFrm* );
+ ~SwColumnFrm();
+
+ DECL_FIXEDMEMPOOL_NEWDEL(SwColumnFrm)
+};
+
+#endif //_COLFRM_HXX
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/inc/crossrefbookmark.hxx b/sw/source/core/inc/crossrefbookmark.hxx
new file mode 100644
index 000000000000..ef5f8933a81a
--- /dev/null
+++ b/sw/source/core/inc/crossrefbookmark.hxx
@@ -0,0 +1,102 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+#ifndef _CROSSREFBOOKMRK_HXX
+#define _CROSSREFBOOKMRK_HXX
+
+#include <IMark.hxx>
+#include <bookmrk.hxx>
+#include <rtl/ustring.hxx>
+
+
+namespace sw { namespace mark
+{
+ class CrossRefBookmark
+ : public Bookmark
+ {
+ public:
+ CrossRefBookmark(const SwPaM& rPaM,
+ const KeyCode& rCode,
+ const ::rtl::OUString& rName,
+ const ::rtl::OUString& rShortName,
+ const ::rtl::OUString& rPrefix);
+
+ // getters
+ virtual SwPosition& GetOtherMarkPos() const;
+ virtual SwPosition& GetMarkStart() const
+ { return *m_pPos1; }
+ virtual SwPosition& GetMarkEnd() const
+ { return *m_pPos1; }
+ virtual bool IsExpanded() const
+ { return false; }
+
+ // setters
+ virtual void SetMarkPos(const SwPosition& rNewPos);
+ virtual void SetOtherMarkPos(const SwPosition&)
+ {
+ OSL_PRECOND(false,
+ "<CrossRefBookmark::SetOtherMarkPos(..)>"
+ " - misusage of CrossRefBookmark: other bookmark position isn't allowed to be set." );
+ }
+ virtual void ClearOtherMarkPos()
+ {
+ OSL_PRECOND(false,
+ "<SwCrossRefBookmark::ClearOtherMarkPos(..)>"
+ " - misusage of CrossRefBookmark: other bookmark position isn't allowed to be set or cleared." );
+ }
+ };
+
+ class CrossRefHeadingBookmark
+ : public CrossRefBookmark
+ {
+ public:
+ CrossRefHeadingBookmark(const SwPaM& rPaM,
+ const KeyCode& rCode,
+ const ::rtl::OUString& rName,
+ const ::rtl::OUString& rShortName);
+ static ::rtl::OUString GenerateNewName();
+ static bool IsLegalName(const ::rtl::OUString& rName);
+ static const ::rtl::OUString our_sNamePrefix;
+ };
+
+ class CrossRefNumItemBookmark
+ : public CrossRefBookmark
+ {
+ public:
+ CrossRefNumItemBookmark(const SwPaM& rPaM,
+ const KeyCode& rCode,
+ const ::rtl::OUString& rName,
+ const ::rtl::OUString& rShortName);
+ static ::rtl::OUString GenerateNewName();
+ static bool IsLegalName(const ::rtl::OUString& rName);
+ static const ::rtl::OUString our_sNamePrefix;
+ };
+
+}}
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/inc/dbg_lay.hxx b/sw/source/core/inc/dbg_lay.hxx
new file mode 100644
index 000000000000..d290e9c8c178
--- /dev/null
+++ b/sw/source/core/inc/dbg_lay.hxx
@@ -0,0 +1,123 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef _DBG_LAY_HXX
+#define _DBG_LAY_HXX
+
+#define PROT_FILE_INIT 0x00000000
+#define PROT_INIT 0x00000001
+#define PROT_MAKEALL 0x00000002
+#define PROT_MOVE_FWD 0x00000004
+#define PROT_MOVE_BWD 0x00000008
+#define PROT_GROW 0x00000010
+#define PROT_SHRINK 0x00000020
+#define PROT_GROW_TST 0x00000040
+#define PROT_SHRINK_TST 0x00000080
+#define PROT_SIZE 0x00000100
+#define PROT_PRTAREA 0x00000200
+#define PROT_POS 0x00000400
+#define PROT_ADJUSTN 0x00000800
+#define PROT_SECTION 0x00001000
+#define PROT_CUT 0x00002000
+#define PROT_PASTE 0x00004000
+#define PROT_LEAF 0x00008000
+#define PROT_TESTFORMAT 0x00010000
+#define PROT_FRMCHANGES 0x00020000
+#define PROT_SNAPSHOT 0x00040000
+
+#define ACT_START 1
+#define ACT_END 2
+#define ACT_CREATE_MASTER 3
+#define ACT_CREATE_FOLLOW 4
+#define ACT_DEL_MASTER 5
+#define ACT_DEL_FOLLOW 6
+#define ACT_MERGE 7
+#define ACT_NEXT_SECT 8
+#define ACT_PREV_SECT 9
+
+#define SNAP_LOWER 0x00000001
+#define SNAP_FLYFRAMES 0x00000002
+#define SNAP_TABLECONT 0x00000004
+
+#if OSL_DEBUG_LEVEL > 1
+
+#include "swtypes.hxx"
+
+class SwImplProtocol;
+class SwFrm;
+class SwImplEnterLeave;
+
+class SwProtocol
+{
+ static sal_uLong nRecord;
+ static SwImplProtocol* pImpl;
+ static sal_Bool Start() { return 0 != ( PROT_INIT & nRecord ); }
+public:
+ static sal_uLong Record() { return nRecord; }
+ static void SetRecord( sal_uLong nNew ) { nRecord = nNew; }
+ static sal_Bool Record( sal_uLong nFunc ) { return 0 != (( nFunc | PROT_INIT ) & nRecord); }
+ static void Record( const SwFrm* pFrm, sal_uLong nFunction, sal_uLong nAction, void* pParam );
+ static void Init();
+ static void Stop();
+ static void SnapShot( const SwFrm* pFrm, sal_uLong nFlags );
+ static void GetVar( const sal_uInt16 nNo, long& rVar );
+};
+
+class SwEnterLeave
+{
+ SwImplEnterLeave* pImpl;
+ void Ctor( const SwFrm* pFrm, sal_uLong nFunc, sal_uLong nAct, void* pPar );
+ void Dtor();
+public:
+ SwEnterLeave( const SwFrm* pFrm, sal_uLong nFunc, sal_uLong nAct, void* pPar )
+ { if( SwProtocol::Record( nFunc ) ) Ctor( pFrm, nFunc, nAct, pPar ); else pImpl = NULL; }
+ ~SwEnterLeave() { if( pImpl ) Dtor(); }
+};
+
+#define PROTOCOL( pFrm, nFunc, nAct, pPar ) { if( SwProtocol::Record( nFunc ) )\
+ SwProtocol::Record( pFrm, nFunc, nAct, pPar ); }
+#define PROTOCOL_INIT SwProtocol::Init();
+#define PROTOCOL_STOP SwProtocol::Stop();
+#define PROTOCOL_ENTER( pFrm, nFunc, nAct, pPar ) SwEnterLeave aEnter( pFrm, nFunc, nAct, pPar );
+#define PROTOCOL_SNAPSHOT( pFrm, nFlags ) SwProtocol::SnapShot( pFrm, nFlags );
+#define GET_VARIABLE( nNo, nVar ) SwProtocol::GetVar( nNo, nVar );
+
+#else
+
+#define PROTOCOL( pFrm, nFunc, nAct, pPar )
+#define PROTOCOL_INIT
+#define PROTOCOL_STOP
+#define PROTOCOL_ENTER( pFrm, nFunc, nAct, pPar )
+#define PROTOCOL_SNAPSHOT( pFrm, nFlags )
+#define GET_VARIABLE( nNo, nVar )
+
+#endif
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/inc/dbgloop.hxx b/sw/source/core/inc/dbgloop.hxx
new file mode 100644
index 000000000000..bfa17b466828
--- /dev/null
+++ b/sw/source/core/inc/dbgloop.hxx
@@ -0,0 +1,77 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef _DBGLOOP_HXX
+#define _DBGLOOP_HXX
+
+#ifdef DBG_UTIL
+
+#include <tools/solar.h>
+
+class SvStream;
+
+#define DBG_MAX_STACK 20 // Verschachtelungstiefe
+#define DBG_MAX_LOOP 1000 // das Abbruchkriterium
+
+class DbgLoopStack
+{
+ sal_uInt16 aCount[DBG_MAX_STACK];
+ sal_uInt16 nPtr;
+ const void *pDbg;
+ void Reset();
+public:
+ DbgLoopStack();
+ void Push( const void *pThis );
+ void Pop();
+ void Print( SvStream &rOS ) const; //$ ostream
+};
+
+class DbgLoop
+{
+ friend inline void PrintLoopStack( SvStream &rOS ); //$ ostream
+ static DbgLoopStack aDbgLoopStack;
+public:
+ inline DbgLoop( const void *pThis ) { aDbgLoopStack.Push( pThis ); }
+ inline ~DbgLoop() { aDbgLoopStack.Pop(); }
+};
+
+inline void PrintLoopStack( SvStream &rOS ) //$ ostream
+{
+ DbgLoop::aDbgLoopStack.Print( rOS );
+}
+
+#define DBG_LOOP DbgLoop aDbgLoop( (const void*)this );
+#define DBG_LOOP_RESET DbgLoop aDbgLoop( 0 );
+
+#else
+
+#define DBG_LOOP
+#define DBG_LOOP_RESET
+
+#endif
+
+#endif
diff --git a/sw/source/core/inc/dflyobj.hxx b/sw/source/core/inc/dflyobj.hxx
new file mode 100644
index 000000000000..9e3cf0dff55e
--- /dev/null
+++ b/sw/source/core/inc/dflyobj.hxx
@@ -0,0 +1,143 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+#ifndef _DFLYOBJ_HXX
+#define _DFLYOBJ_HXX
+#include <svx/svdovirt.hxx>
+
+class SwFlyFrm;
+class SwFrmFmt;
+class SdrObjMacroHitRec;
+
+const sal_uInt32 SWGInventor = sal_uInt32('S')*0x00000001+
+ sal_uInt32('W')*0x00000100+
+ sal_uInt32('G')*0x00010000;
+
+const sal_uInt16 SwFlyDrawObjIdentifier = 0x0001;
+const sal_uInt16 SwDrawFirst = 0x0001;
+
+//---------------------------------------
+//SwFlyDrawObj, Die DrawObjekte fuer Flys.
+
+class SwFlyDrawObj : public SdrObject
+{
+private:
+ virtual sdr::properties::BaseProperties* CreateObjectSpecificProperties();
+
+protected:
+ // #i95264# SwFlyDrawObj needs an own VC since createViewIndependentPrimitive2DSequence()
+ // is called when RecalcBoundRect() is used
+ virtual sdr::contact::ViewContact* CreateObjectSpecificViewContact();
+
+public:
+ TYPEINFO();
+
+ SwFlyDrawObj();
+ ~SwFlyDrawObj();
+
+ //Damit eine Instanz dieser Klasse beim laden erzeugt werden kann
+ //(per Factory).
+ virtual sal_uInt32 GetObjInventor() const;
+ virtual sal_uInt16 GetObjIdentifier() const;
+ virtual sal_uInt16 GetObjVersion() const;
+};
+
+//---------------------------------------
+//SwVirtFlyDrawObj, die virtuellen Objekte fuer Flys.
+//Flys werden immer mit virtuellen Objekten angezeigt. Nur so koennen sie
+//ggf. mehrfach angezeigt werden (Kopf-/Fusszeilen).
+
+class SwVirtFlyDrawObj : public SdrVirtObj
+{
+private:
+ SwFlyFrm *pFlyFrm;
+
+protected:
+ // AW: Need own sdr::contact::ViewContact since AnchorPos from parent is
+ // not used but something own (top left of new SnapRect minus top left
+ // of original SnapRect)
+ virtual sdr::contact::ViewContact* CreateObjectSpecificViewContact();
+
+public:
+ // for paints triggered form ExecutePrimitive
+ void wrap_DoPaintObject() const;
+
+ // for simple access to inner and outer bounds
+ basegfx::B2DRange getOuterBound() const;
+ basegfx::B2DRange getInnerBound() const;
+
+public:
+ TYPEINFO();
+
+ SwVirtFlyDrawObj(SdrObject& rNew, SwFlyFrm* pFly);
+ ~SwVirtFlyDrawObj();
+
+ //Ueberladene Methoden der Basisklasse SdrVirtObj
+ virtual void TakeObjInfo( SdrObjTransformInfoRec& rInfo ) const;
+
+ //Wir nehemen die Groessenbehandlung vollstaendig selbst in die Hand.
+ virtual const Rectangle& GetCurrentBoundRect() const;
+ virtual const Rectangle& GetLastBoundRect() const;
+ virtual void RecalcBoundRect();
+ virtual void RecalcSnapRect();
+ virtual const Rectangle& GetSnapRect() const;
+ virtual void SetSnapRect(const Rectangle& rRect);
+ virtual void NbcSetSnapRect(const Rectangle& rRect);
+ virtual const Rectangle& GetLogicRect() const;
+ virtual void SetLogicRect(const Rectangle& rRect);
+ virtual void NbcSetLogicRect(const Rectangle& rRect);
+ virtual ::basegfx::B2DPolyPolygon TakeXorPoly() const;
+ virtual void NbcMove (const Size& rSiz);
+ virtual void NbcResize(const Point& rRef, const Fraction& xFact,
+ const Fraction& yFact);
+ virtual void Move (const Size& rSiz);
+ virtual void Resize(const Point& rRef, const Fraction& xFact,
+ const Fraction& yFact);
+
+ const SwFrmFmt *GetFmt() const;
+ SwFrmFmt *GetFmt();
+
+ // Get Methoden fuer die Fly Verpointerung
+ SwFlyFrm* GetFlyFrm() { return pFlyFrm; }
+ const SwFlyFrm* GetFlyFrm() const { return pFlyFrm; }
+
+ void SetRect() const;
+
+ // ist eine URL an einer Grafik gesetzt, dann ist das ein Makro-Object
+ virtual bool HasMacro() const;
+ virtual SdrObject* CheckMacroHit (const SdrObjMacroHitRec& rRec) const;
+ virtual Pointer GetMacroPointer (const SdrObjMacroHitRec& rRec) const;
+
+ // FullDrag support
+ virtual bool supportsFullDrag() const;
+ virtual SdrObject* getFullDragClone() const;
+};
+
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/inc/docfld.hxx b/sw/source/core/inc/docfld.hxx
new file mode 100644
index 000000000000..26d19dc4d859
--- /dev/null
+++ b/sw/source/core/inc/docfld.hxx
@@ -0,0 +1,195 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+#ifndef _DOCFLD_HXX
+#define _DOCFLD_HXX
+
+#include <calc.hxx> // fuer SwHash
+
+class SwTxtFld;
+class SwIndex;
+class SwNodeIndex;
+class SwCntntNode;
+class SwCntntFrm;
+class SwSectionNode;
+class SwSection;
+class SwTxtTOXMark;
+class SwTableBox;
+class SwTxtINetFmt;
+class SwFlyFrmFmt;
+class SwDoc;
+class SwNode;
+struct SwPosition;
+
+// Update an den Expression Feldern
+class _SetGetExpFld
+{
+ sal_uLong nNode;
+ xub_StrLen nCntnt;
+ union {
+ const SwTxtFld* pTxtFld;
+ const SwSection* pSection;
+ const SwPosition* pPos;
+ const SwTxtTOXMark* pTxtTOX;
+ const SwTableBox* pTBox;
+ const SwTxtINetFmt* pTxtINet;
+ const SwFlyFrmFmt* pFlyFmt;
+ } CNTNT;
+ enum _SetGetExpFldType
+ {
+ TEXTFIELD, TEXTTOXMARK, SECTIONNODE, CRSRPOS, TABLEBOX,
+ TEXTINET, FLYFRAME
+ } eSetGetExpFldType;
+
+public:
+ _SetGetExpFld( const SwNodeIndex& rNdIdx, const SwTxtFld* pFld = 0,
+ const SwIndex* pIdx = 0 );
+
+ _SetGetExpFld( const SwNodeIndex& rNdIdx, const SwTxtINetFmt& rINet,
+ const SwIndex* pIdx = 0 );
+
+ _SetGetExpFld( const SwSectionNode& rSectNode,
+ const SwPosition* pPos = 0 );
+
+ _SetGetExpFld( const SwTableBox& rTableBox,
+ const SwPosition* pPos = 0 );
+
+ _SetGetExpFld( const SwNodeIndex& rNdIdx, const SwTxtTOXMark& rTOX,
+ const SwIndex* pIdx );
+
+ _SetGetExpFld( const SwPosition& rPos );
+
+ _SetGetExpFld( const SwFlyFrmFmt& rFlyFmt, const SwPosition* pPos = 0 );
+
+ sal_Bool operator==( const _SetGetExpFld& rFld ) const
+ { return nNode == rFld.nNode && nCntnt == rFld.nCntnt &&
+ ( !CNTNT.pTxtFld || !rFld.CNTNT.pTxtFld ||
+ CNTNT.pTxtFld == rFld.CNTNT.pTxtFld ); }
+ sal_Bool operator<( const _SetGetExpFld& rFld ) const;
+
+ const SwTxtFld* GetFld() const
+ { return TEXTFIELD == eSetGetExpFldType ? CNTNT.pTxtFld : 0; }
+ const SwTxtTOXMark* GetTOX() const
+ { return TEXTTOXMARK == eSetGetExpFldType ? CNTNT.pTxtTOX : 0; }
+ const SwSection* GetSection() const
+ { return SECTIONNODE == eSetGetExpFldType ? CNTNT.pSection : 0; }
+ const SwTableBox* GetTableBox() const
+ { return TABLEBOX == eSetGetExpFldType ? CNTNT.pTBox : 0; }
+ const SwTxtINetFmt* GetINetFmt() const
+ { return TEXTINET == eSetGetExpFldType ? CNTNT.pTxtINet : 0; }
+ const SwFlyFrmFmt* GetFlyFmt() const
+ { return FLYFRAME == eSetGetExpFldType ? CNTNT.pFlyFmt : 0; }
+
+ sal_uLong GetNode() const { return nNode; }
+ xub_StrLen GetCntnt() const { return nCntnt; }
+ const void* GetPointer() const { return CNTNT.pTxtFld; }
+
+ void GetPos( SwPosition& rPos ) const;
+ void GetPosOfContent( SwPosition& rPos ) const;
+
+ const SwNode* GetNodeFromCntnt() const;
+ xub_StrLen GetCntPosFromCntnt() const;
+
+ void SetBodyPos( const SwCntntFrm& rFrm );
+};
+
+typedef _SetGetExpFld* _SetGetExpFldPtr;
+SV_DECL_PTRARR_SORT_DEL( _SetGetExpFlds, _SetGetExpFldPtr, 0, 10 )
+
+
+// Struktur zum Speichern der Strings aus SetExp-String-Feldern
+struct _HashStr : public SwHash
+{
+ String aSetStr;
+ _HashStr( const String& rName, const String& rText, _HashStr* = 0 );
+};
+
+struct SwCalcFldType : public SwHash
+{
+ const SwFieldType* pFldType;
+
+ SwCalcFldType( const String& rStr, const SwFieldType* pFldTyp )
+ : SwHash( rStr ), pFldType( pFldTyp )
+ {}
+};
+
+// Suche nach dem String, der unter dem Namen in der HashTabelle abgelegt
+// wurde
+void LookString( SwHash** ppTbl, sal_uInt16 nSize, const String& rName,
+ String& rRet, sal_uInt16* pPos = 0 );
+
+
+// --------
+
+const int GETFLD_ALL = 3; // veroderte Flags !!
+const int GETFLD_CALC = 1;
+const int GETFLD_EXPAND = 2;
+
+class SwDocUpdtFld
+{
+ _SetGetExpFlds* pFldSortLst; // akt. Field-Liste zum Calculieren
+ SwCalcFldType* aFldTypeTable[ TBLSZ ];
+
+// noch eine weitere Optimierung - wird z.Z. nicht angesprochen!
+ long nFldUpdtPos; // ab dieser Position mit Update starten
+ SwCntntNode* pCNode; // der TxtNode zur UpdatePos.
+
+ sal_uLong nNodes; // sollte die NodesAnzahl unterschiedlich sein
+ sal_uInt8 nFldLstGetMode;
+
+ sal_Bool bInUpdateFlds : 1; // zur Zeit laeuft ein UpdateFlds,
+ sal_Bool bFldsDirty : 1; // irgendwelche Felder sind ungueltig
+
+ void _MakeFldList( SwDoc& pDoc, int eGetMode );
+ void GetBodyNode( const SwTxtFld& , sal_uInt16 nFldWhich );
+ void GetBodyNode( const SwSectionNode&);
+public:
+ SwDocUpdtFld();
+ ~SwDocUpdtFld();
+
+ const _SetGetExpFlds* GetSortLst() const { return pFldSortLst; }
+
+ void MakeFldList( SwDoc& rDoc, int bAll, int eGetMode );
+
+ void InsDelFldInFldLst( sal_Bool bIns, const SwTxtFld& rFld );
+
+ void InsertFldType( const SwFieldType& rType );
+ void RemoveFldType( const SwFieldType& rType );
+
+ sal_Bool IsInUpdateFlds() const { return bInUpdateFlds; }
+ void SetInUpdateFlds( sal_Bool b ) { bInUpdateFlds = b; }
+
+ sal_Bool IsFieldsDirty() const { return bFldsDirty; }
+ void SetFieldsDirty( sal_Bool b ) { bFldsDirty = b; }
+
+ SwHash** GetFldTypeTable() const { return (SwHash**)aFldTypeTable; }
+};
+
+
+#endif // _DOCFLD_HXX
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/inc/docsort.hxx b/sw/source/core/inc/docsort.hxx
new file mode 100644
index 000000000000..aa2d096f3cb8
--- /dev/null
+++ b/sw/source/core/inc/docsort.hxx
@@ -0,0 +1,180 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef _SORT_HXX
+#define _SORT_HXX
+
+#include <svl/svarray.hxx>
+#include <ndindex.hxx>
+
+
+class SwDoc;
+class SwTableBox;
+class SwUndoSort;
+class FlatFndBox;
+struct SwSortOptions;
+struct SwSortElement;
+class _FndBox;
+class _FndLine;
+class CollatorWrapper;
+class LocaleDataWrapper;
+
+
+namespace com { namespace sun { namespace star { namespace lang {
+ struct Locale;
+}}}}
+
+/*--------------------------------------------------------------------
+ Beschreibung: Liste aller sortierten Elemente
+ --------------------------------------------------------------------*/
+typedef const _FndBox* _FndBoxPtr;
+typedef SwSortElement* SwSortElementPtr;
+typedef const SwTableBox* SwMovedBoxPtr;
+
+SV_DECL_PTRARR_SORT(SwSortElements, SwSortElementPtr, 0, 1 )
+SV_DECL_PTRARR(SwMovedBoxes, SwMovedBoxPtr, 10, 10 )
+
+/*--------------------------------------------------------------------
+ Beschreibung: Funktionen zum Moven von Boxen
+ --------------------------------------------------------------------*/
+
+void MoveCol(SwDoc* pDoc, const FlatFndBox& rBox,
+ sal_uInt16 nS, sal_uInt16 nT, SwMovedBoxes& rMovedList, SwUndoSort* pUD=0);
+void MoveRow(SwDoc* pDoc, const FlatFndBox& rBox,
+ sal_uInt16 nS, sal_uInt16 nT, SwMovedBoxes& rMovedList, SwUndoSort* pUD=0);
+void MoveCell(SwDoc* pDoc, const SwTableBox* pSource,
+ const SwTableBox* pTar, sal_Bool bMovedBefore, SwUndoSort* pUD=0);
+
+/*-------------------------------------------------------------------
+ Beschreibung: Elemente zum Sortieren von Text und Tabellen-Inhalt
+ --------------------------------------------------------------------*/
+
+struct SwSortElement
+{
+ static SwSortOptions* pOptions;
+ static SwDoc* pDoc;
+ static const FlatFndBox* pBox;
+ static CollatorWrapper* pSortCollator;
+ static ::com::sun::star::lang::Locale* pLocale;
+ static String* pLastAlgorithm;
+ static LocaleDataWrapper* pLclData;
+
+ static void Init( SwDoc*, const SwSortOptions& rOpt, FlatFndBox* = 0 );
+ static void Finit();
+
+ virtual ~SwSortElement();
+
+ virtual String GetKey(sal_uInt16 nKey ) const = 0;
+ virtual double GetValue(sal_uInt16 nKey ) const;
+
+ sal_Bool operator==(const SwSortElement& );
+ sal_Bool operator<(const SwSortElement& );
+
+ double StrToDouble(const String& rStr) const;
+};
+
+/*--------------------------------------------------------------------
+ Beschreibung: Sortieren Text
+ --------------------------------------------------------------------*/
+
+struct SwSortTxtElement : public SwSortElement
+{
+ // fuer Text
+ sal_uLong nOrg;
+ SwNodeIndex aPos;
+
+ SwSortTxtElement( const SwNodeIndex& rPos );
+ virtual ~SwSortTxtElement();
+
+ virtual String GetKey( sal_uInt16 nKey ) const;
+};
+
+/*--------------------------------------------------------------------
+ Beschreibung: Sortieren Tabelle
+ --------------------------------------------------------------------*/
+
+struct SwSortBoxElement : public SwSortElement
+{
+ sal_uInt16 nRow;
+
+ SwSortBoxElement( sal_uInt16 nRC );
+ virtual ~SwSortBoxElement();
+
+ virtual String GetKey( sal_uInt16 nKey ) const;
+ virtual double GetValue( sal_uInt16 nKey ) const;
+};
+
+
+/*--------------------------------------------------------------------
+ Beschreibung: SymFndBoxes stellt ein zweidimensionales
+ Array von FndBoxes dar
+ --------------------------------------------------------------------*/
+
+class FlatFndBox
+{
+public:
+ FlatFndBox(SwDoc* pDocPtr, const _FndBox& rBox);
+ ~FlatFndBox();
+
+ sal_Bool IsSymmetric() const { return bSym; }
+ sal_uInt16 GetRows() const { return nRows; }
+ sal_uInt16 GetCols() const { return nCols; }
+
+ const _FndBox* GetBox(sal_uInt16 nCol, sal_uInt16 nRow) const;
+
+ inline sal_Bool HasItemSets() const;
+ const SfxItemSet* GetItemSet(sal_uInt16 nCol, sal_uInt16 nRow) const;
+
+private:
+
+ sal_Bool CheckLineSymmetry(const _FndBox& rBox);
+ sal_Bool CheckBoxSymmetry(const _FndLine& rLn);
+ sal_uInt16 GetColCount(const _FndBox& rBox);
+ sal_uInt16 GetRowCount(const _FndBox& rBox);
+ void FillFlat(const _FndBox&, sal_Bool bLastBox=sal_False);
+
+ SwDoc* pDoc;
+ const _FndBox& rBoxRef;
+ _FndBoxPtr* pArr;
+ SfxItemSet** ppItemSets;
+
+ sal_uInt16 nRows;
+ sal_uInt16 nCols;
+
+ sal_uInt16 nRow;
+ sal_uInt16 nCol;
+
+ sal_Bool bSym;
+};
+
+
+inline sal_Bool FlatFndBox::HasItemSets() const { return 0 != ppItemSets; }
+
+#endif // _NDSORT_HXX
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/inc/doctxm.hxx b/sw/source/core/inc/doctxm.hxx
new file mode 100644
index 000000000000..842b6a319726
--- /dev/null
+++ b/sw/source/core/inc/doctxm.hxx
@@ -0,0 +1,148 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+#ifndef _DOCTXM_HXX
+#define _DOCTXM_HXX
+
+
+#include <svl/svarray.hxx>
+#include <tools/gen.hxx>
+#include <tox.hxx>
+#include <section.hxx>
+
+class SwTOXInternational;
+class SvUShorts;
+class SvStringsDtor;
+class SvPtrarr;
+class SwPageDesc;
+class SwTxtNode;
+class SwTxtFmtColl;
+struct SwPosition;
+struct SwTOXSortTabBase;
+
+typedef SwTOXSortTabBase* SwTOXSortTabBasePtr;
+
+SV_DECL_PTRARR(SwTOXSortTabBases, SwTOXSortTabBasePtr, 0, 5 )
+
+/*--------------------------------------------------------------------
+ Beschreibung: Ring der speziellen Verzeichnisse
+ --------------------------------------------------------------------*/
+
+class SwTOXBaseSection : public SwTOXBase, public SwSection
+{
+ SwTOXSortTabBases aSortArr;
+
+ void UpdateMarks( const SwTOXInternational& rIntl,
+ const SwTxtNode* pOwnChapterNode );
+ void UpdateOutline( const SwTxtNode* pOwnChapterNode );
+ void UpdateTemplate( const SwTxtNode* pOwnChapterNode );
+ void UpdateCntnt( SwTOXElement eType,
+ const SwTxtNode* pOwnChapterNode );
+ void UpdateTable( const SwTxtNode* pOwnChapterNode );
+ void UpdateSequence( const SwTxtNode* pOwnChapterNode );
+ void UpdateAuthorities( const SwTOXInternational& rIntl );
+ void UpdateAll();
+
+ // Sortiert einfuegen ins Array fuer die Generierung
+ void InsertSorted(SwTOXSortTabBase* pBase);
+
+ // Alpha-Trennzeichen bei der Generierung einfuegen
+ void InsertAlphaDelimitter( const SwTOXInternational& rIntl );
+
+ // Textrumpf generieren
+ // OD 18.03.2003 #106329# - add parameter <_TOXSectNdIdx> and <_pDefaultPageDesc>
+ void GenerateText( sal_uInt16 nArrayIdx,
+ sal_uInt16 nCount,
+ SvStringsDtor&,
+ const sal_uInt32 _nTOXSectNdIdx,
+ const SwPageDesc* _pDefaultPageDesc );
+
+ // Seitennummerplatzhalter gegen aktuelle Nummern austauschen
+ void _UpdatePageNum( SwTxtNode* pNd,
+ const SvUShorts& rNums,
+ const SvPtrarr &rDescs,
+ const SvUShorts* pMainEntryNums,
+ const SwTOXInternational& rIntl );
+
+ // Bereich fuer Stichwort einfuegen suchen
+ Range GetKeyRange( const String& rStr, const String& rStrReading,
+ const SwTOXSortTabBase& rNew, sal_uInt16 nLevel,
+ const Range& rRange );
+
+ // returne die TextCollection ueber den Namen / aus Format-Pool
+ SwTxtFmtColl* GetTxtFmtColl( sal_uInt16 nLevel );
+
+public:
+ SwTOXBaseSection(SwTOXBase const& rBase, SwSectionFmt & rFmt);
+ virtual ~SwTOXBaseSection();
+
+ // OD 19.03.2003 #106329# - add parameter <_bNewTOX> in order to distinguish
+ // between the creation of a new table-of-content or an update of
+ // a table-of-content. Default value: false
+ void Update( const SfxItemSet* pAttr = 0,
+ const bool _bNewTOX = false ); // Formatieren
+ void UpdatePageNum(); // Seitennummern einfuegen
+ TYPEINFO(); // fuers rtti
+
+ sal_Bool SetPosAtStartEnd( SwPosition& rPos, sal_Bool bAtStart = sal_True ) const;
+};
+
+struct SwDefTOXBase_Impl
+{
+ SwTOXBase* pContBase;
+ SwTOXBase* pIdxBase;
+ SwTOXBase* pUserBase;
+ SwTOXBase* pTblBase;
+ SwTOXBase* pObjBase;
+ SwTOXBase* pIllBase;
+ SwTOXBase* pAuthBase;
+
+ SwDefTOXBase_Impl() :
+ pContBase(0),
+ pIdxBase(0),
+ pUserBase(0),
+ pTblBase(0),
+ pObjBase(0),
+ pIllBase(0),
+ pAuthBase(0)
+ {}
+ ~SwDefTOXBase_Impl()
+ {
+ delete pContBase;
+ delete pIdxBase;
+ delete pUserBase;
+ delete pTblBase;
+ delete pObjBase;
+ delete pIllBase;
+ delete pAuthBase;
+ }
+
+};
+
+#endif // _DOCTXM_HXX
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/inc/drawdev.hxx b/sw/source/core/inc/drawdev.hxx
new file mode 100644
index 000000000000..31d630a741e4
--- /dev/null
+++ b/sw/source/core/inc/drawdev.hxx
@@ -0,0 +1,141 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef _DRAWDEV_HXX
+#define _DRAWDEV_HXX
+
+#include "swrect.hxx"
+
+#include <vcl/outdev.hxx>
+
+/*************************************************************************
+ * class SwDrawDev
+ *
+ * Alle Draw-Methoden werden um den Offset *pPos verschoben.
+ *************************************************************************/
+
+class SwDrawDev
+{
+ OutputDevice *pOut;
+ const Point *pPos;
+
+public:
+ inline SwDrawDev( OutputDevice *pOutDev, const Point *pPosition )
+ :pOut(pOutDev), pPos(pPosition) { }
+
+ inline OutputDevice *GetOut() { return pOut; }
+
+ // Ausgabemethoden
+ inline void DrawText( const Point& rStart, const String& rTxt,
+ const sal_uInt16 nIdx = 0,
+ const sal_uInt16 nLen = STRING_LEN );
+ inline void DrawStretchText( const Point& rStart, sal_uInt16 nWidth,
+ const String& rTxt,
+ const sal_uInt16 nIdx = 0,
+ const sal_uInt16 nLen = STRING_LEN );
+ inline void DrawTextArray( const Point& rStart,
+ const String& rTxt,
+ long *pKernArray = 0,
+ const sal_uInt16 nIdx = 0,
+ const sal_uInt16 nLen = STRING_LEN);
+ inline void DrawLine( const Point& rStart, const Point& rEnd );
+ inline void DrawRect( const SwRect& rRect,
+ const sal_uInt16 nHorzRount = 0,
+ const sal_uInt16 nVertRound = 0 );
+
+ inline const Point *GetOrigin() const {return pPos; }
+};
+
+/*************************************************************************
+ * SwDrawDev::DrawText
+ *************************************************************************/
+
+inline void SwDrawDev::DrawText( const Point& rStart, const String& rTxt,
+ const sal_uInt16 nIdx, const sal_uInt16 nLen )
+{
+ if( !pPos )
+ pOut->DrawText( rStart, rTxt, nIdx, nLen );
+ else
+ pOut->DrawText( rStart - *pPos, rTxt, nIdx, nLen );
+}
+
+/*************************************************************************
+ * SwDrawDev::DrawStretchText
+ *************************************************************************/
+
+inline void SwDrawDev::DrawStretchText( const Point& rStart, sal_uInt16 nWidth,
+ const String& rTxt, const sal_uInt16 nIdx, const sal_uInt16 nLen )
+{
+ if( !pPos )
+ pOut->DrawStretchText( rStart, nWidth, rTxt, nIdx, nLen );
+ else
+ pOut->DrawStretchText( rStart - *pPos, nWidth, rTxt, nIdx, nLen );
+}
+
+/*************************************************************************
+ * SwDrawDev::DrawTextArray
+ *************************************************************************/
+
+inline void SwDrawDev::DrawTextArray( const Point& rStart, const String& rTxt,
+ long *pKernArray, const sal_uInt16 nIdx, const sal_uInt16 nLen )
+{
+ if( !pPos )
+ pOut->DrawTextArray( rStart, rTxt, pKernArray, nIdx, nLen );
+ else
+ pOut->DrawTextArray( rStart - *pPos, rTxt, pKernArray, nIdx, nLen );
+}
+
+/*************************************************************************
+ * SwDrawDev::DrawLine
+ *************************************************************************/
+
+inline void SwDrawDev::DrawLine( const Point& rStart, const Point& rEnd )
+{
+ if( !pPos )
+ pOut->DrawLine( rStart, rEnd );
+ else
+ pOut->DrawLine( rStart - *pPos, rEnd - *pPos );
+}
+
+/*************************************************************************
+ * SwDrawDev::DrawRect
+ *************************************************************************/
+
+inline void SwDrawDev::DrawRect( const SwRect& rRect,
+ const sal_uInt16 nHorzRound, const sal_uInt16 nVertRound )
+{
+ SwRect aRect( rRect );
+ if( pPos )
+ aRect.Pos() -= *pPos;
+ pOut->DrawRect( aRect.SVRect(), nHorzRound, nVertRound );
+}
+
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/inc/drawfont.hxx b/sw/source/core/inc/drawfont.hxx
new file mode 100644
index 000000000000..aad3c9f00787
--- /dev/null
+++ b/sw/source/core/inc/drawfont.hxx
@@ -0,0 +1,628 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+#ifndef _DRAWFONT_HXX
+#define _DRAWFONT_HXX
+
+#include <tools/solar.h>
+#include <tools/string.hxx>
+
+class SwTxtFrm;
+class OutputDevice;
+class ViewShell;
+class SwScriptInfo;
+class Point;
+class SwWrongList;
+class Size;
+class SwFont;
+class Font;
+class SwUnderlineFont;
+
+/*************************************************************************
+ * class SwDrawTextInfo
+ *
+ * encapsulates information for drawing text
+ *************************************************************************/
+
+class SwDrawTextInfo
+{
+ const SwTxtFrm* pFrm;
+ OutputDevice* pOut;
+ ViewShell* pSh;
+ const SwScriptInfo* pScriptInfo;
+ const Point* pPos;
+ const XubString* pText;
+ const SwWrongList* pWrong;
+ const SwWrongList* pGrammarCheck;
+ const SwWrongList* pSmartTags; // SMARTTAGS
+ const Size* pSize;
+ SwFont *pFnt;
+ SwUnderlineFont* pUnderFnt;
+ xub_StrLen* pHyphPos;
+ long nLeft;
+ long nRight;
+ long nKanaDiff;
+ xub_StrLen nIdx;
+ xub_StrLen nLen;
+ xub_StrLen nOfst;
+ sal_uInt16 nWidth;
+ sal_uInt16 nAscent;
+ sal_uInt16 nCompress;
+ long nSperren;
+ long nSpace;
+ long nKern;
+ xub_StrLen nNumberOfBlanks;
+ sal_uInt8 nCursorBidiLevel;
+ sal_Bool bBullet : 1;
+ sal_Bool bUpper : 1; // Fuer Kapitaelchen: Grossbuchstaben-Flag
+ sal_Bool bDrawSpace : 1; // Fuer Kapitaelchen: Unter/Durchstreichung
+ sal_Bool bGreyWave : 1; // Graue Wellenlinie beim extended TextInput
+ sal_Bool bSpaceStop : 1; // For underlining we need to know, if a portion
+ // is right in front of a hole portion or a
+ // fix margin portion.
+ sal_Bool bSnapToGrid : 1; // Does paragraph snap to grid?
+ sal_Bool bIgnoreFrmRTL : 1; // Paint text as if text has LTR direction, used for
+ // line numbering
+ sal_Bool bPosMatchesBounds :1; // GetCrsrOfst should not return the next
+ // position if screen position is inside second
+ // half of bound rect, used for Accessibility
+
+ SwDrawTextInfo(); // nicht zulaessig
+public:
+
+#if OSL_DEBUG_LEVEL > 1
+ sal_Bool bPos : 1; // These flags should control, that the appropriate
+ sal_Bool bWrong : 1; // Set-function has been called before calling
+ sal_Bool bGrammarCheck : 1; // the Get-function of a member
+ sal_Bool bSize : 1;
+ sal_Bool bFnt : 1;
+ sal_Bool bHyph : 1;
+ sal_Bool bLeft : 1;
+ sal_Bool bRight : 1;
+ sal_Bool bKana : 1;
+ sal_Bool bOfst : 1;
+ sal_Bool bAscent: 1;
+ sal_Bool bSperr : 1;
+ sal_Bool bSpace : 1;
+ sal_Bool bNumberOfBlanks : 1;
+ sal_Bool bUppr : 1;
+ sal_Bool bDrawSp: 1;
+#endif
+
+ SwDrawTextInfo( ViewShell *pS, OutputDevice &rO, const SwScriptInfo* pSI,
+ const XubString &rSt, xub_StrLen nI, xub_StrLen nL,
+ sal_uInt16 nW = 0, sal_Bool bB = sal_False )
+ {
+ pFrm = NULL;
+ pSh = pS;
+ pOut = &rO;
+ pScriptInfo = pSI;
+ pText = &rSt;
+ nIdx = nI;
+ nLen = nL;
+ nKern = 0;
+ nCompress = 0;
+ nWidth = nW;
+ nNumberOfBlanks = 0;
+ nCursorBidiLevel = 0;
+ bBullet = bB;
+ pUnderFnt = 0;
+ bGreyWave = sal_False;
+ bSpaceStop = sal_False;
+ bSnapToGrid = sal_False;
+ bIgnoreFrmRTL = sal_False;
+ bPosMatchesBounds = sal_False;
+
+ // These values are initialized but, they have to be
+ // set explicitly via their Set-function before they may
+ // be accessed by their Get-function:
+ pPos = 0;
+ pWrong = 0;
+ pGrammarCheck = 0;
+ pSmartTags = 0;
+ pSize = 0;
+ pFnt = 0;
+ pHyphPos = 0;
+ nLeft = 0;
+ nRight = 0;
+ nKanaDiff = 0;
+ nOfst = 0;
+ nAscent = 0;
+ nSperren = 0;
+ nSpace = 0;
+ bUpper = sal_False;
+ bDrawSpace = sal_False;
+
+#if OSL_DEBUG_LEVEL > 1
+ // these flags control, whether the matching member variables have
+ // been set by using the Set-function before they may be accessed
+ // by their Get-function:
+ bPos = bWrong = bGrammarCheck = bSize = bFnt = bAscent = bSpace = bNumberOfBlanks = bUppr =
+ bDrawSp = bLeft = bRight = bKana = bOfst = bHyph = bSperr = sal_False;
+#endif
+ }
+
+ const SwTxtFrm* GetFrm() const
+ {
+ return pFrm;
+ }
+
+ void SetFrm( const SwTxtFrm* pNewFrm )
+ {
+ pFrm = pNewFrm;
+ }
+
+ ViewShell *GetShell() const
+ {
+ return pSh;
+ }
+
+ OutputDevice& GetOut() const
+ {
+ return *pOut;
+ }
+
+ OutputDevice *GetpOut() const
+ {
+ return pOut;
+ }
+
+ const SwScriptInfo* GetScriptInfo() const
+ {
+ return pScriptInfo;
+ }
+
+ const Point &GetPos() const
+ {
+#if OSL_DEBUG_LEVEL > 1
+ OSL_ENSURE( bPos, "DrawTextInfo: Undefined Position" );
+#endif
+ return *pPos;
+ }
+
+ xub_StrLen *GetHyphPos() const
+ {
+#if OSL_DEBUG_LEVEL > 1
+ OSL_ENSURE( bHyph, "DrawTextInfo: Undefined Hyph Position" );
+#endif
+ return pHyphPos;
+ }
+
+ const XubString &GetText() const
+ {
+ return *pText;
+ }
+
+ const SwWrongList* GetWrong() const
+ {
+#if OSL_DEBUG_LEVEL > 1
+ OSL_ENSURE( bWrong, "DrawTextInfo: Undefined WrongList" );
+#endif
+ return pWrong;
+ }
+
+ const SwWrongList* GetGrammarCheck() const
+ {
+#if OSL_DEBUG_LEVEL > 1
+ OSL_ENSURE( bGrammarCheck, "DrawTextInfo: Undefined GrammarCheck List" );
+#endif
+ return pGrammarCheck;
+ }
+
+ const SwWrongList* GetSmartTags() const
+ {
+ return pSmartTags;
+ }
+
+ const Size &GetSize() const
+ {
+#if OSL_DEBUG_LEVEL > 1
+ OSL_ENSURE( bSize, "DrawTextInfo: Undefined Size" );
+#endif
+ return *pSize;
+ }
+
+ SwFont* GetFont() const
+ {
+#if OSL_DEBUG_LEVEL > 1
+ OSL_ENSURE( bFnt, "DrawTextInfo: Undefined Font" );
+#endif
+ return pFnt;
+ }
+
+ SwUnderlineFont* GetUnderFnt() const
+ {
+ return pUnderFnt;
+ }
+
+ xub_StrLen GetIdx() const
+ {
+ return nIdx;
+ }
+
+ xub_StrLen GetLen() const
+ {
+ return nLen;
+ }
+
+ xub_StrLen GetOfst() const
+ {
+#if OSL_DEBUG_LEVEL > 1
+ OSL_ENSURE( bOfst, "DrawTextInfo: Undefined Offset" );
+#endif
+ return nOfst;
+ }
+
+ xub_StrLen GetEnd() const
+ {
+ return nIdx + nLen;
+ }
+
+ long GetLeft() const
+ {
+#if OSL_DEBUG_LEVEL > 1
+ OSL_ENSURE( bLeft, "DrawTextInfo: Undefined left range" );
+#endif
+ return nLeft;
+ }
+
+ long GetRight() const
+ {
+#if OSL_DEBUG_LEVEL > 1
+ OSL_ENSURE( bRight, "DrawTextInfo: Undefined right range" );
+#endif
+ return nRight;
+ }
+
+ long GetKanaDiff() const
+ {
+#if OSL_DEBUG_LEVEL > 1
+ OSL_ENSURE( bKana, "DrawTextInfo: Undefined kana difference" );
+#endif
+ return nKanaDiff;
+ }
+
+ sal_uInt16 GetWidth() const
+ {
+ return nWidth;
+ }
+
+ sal_uInt16 GetAscent() const
+ {
+#if OSL_DEBUG_LEVEL > 1
+ OSL_ENSURE( bAscent, "DrawTextInfo: Undefined Ascent" );
+#endif
+ return nAscent;
+ }
+
+ sal_uInt16 GetKanaComp() const
+ {
+ return nCompress;
+ }
+
+ long GetSperren() const
+ {
+#if OSL_DEBUG_LEVEL > 1
+ OSL_ENSURE( bSperr, "DrawTextInfo: Undefined >Sperren<" );
+#endif
+ return nSperren;
+ }
+
+ long GetKern() const
+ {
+ return nKern;
+ }
+
+ long GetSpace() const
+ {
+#if OSL_DEBUG_LEVEL > 1
+ OSL_ENSURE( bSpace, "DrawTextInfo: Undefined Spacing" );
+#endif
+ return nSpace;
+ }
+
+ xub_StrLen GetNumberOfBlanks() const
+ {
+#if OSL_DEBUG_LEVEL > 1
+ OSL_ENSURE( bNumberOfBlanks, "DrawTextInfo::Undefined NumberOfBlanks" );
+#endif
+ return nNumberOfBlanks;
+ }
+
+ sal_uInt8 GetCursorBidiLevel() const
+ {
+ return nCursorBidiLevel;
+ }
+
+ sal_Bool GetBullet() const
+ {
+ return bBullet;
+ }
+
+ sal_Bool GetUpper() const
+ {
+#if OSL_DEBUG_LEVEL > 1
+ OSL_ENSURE( bUppr, "DrawTextInfo: Undefined Upperflag" );
+#endif
+ return bUpper;
+ }
+
+ sal_Bool GetDrawSpace() const
+ {
+#if OSL_DEBUG_LEVEL > 1
+ OSL_ENSURE( bDrawSp, "DrawTextInfo: Undefined DrawSpaceflag" );
+#endif
+ return bDrawSpace;
+ }
+
+ sal_Bool GetGreyWave() const
+ {
+ return bGreyWave;
+ }
+
+ sal_Bool IsSpaceStop() const
+ {
+ return bSpaceStop;
+ }
+
+ sal_Bool SnapToGrid() const
+ {
+ return bSnapToGrid;
+ }
+
+ sal_Bool IsIgnoreFrmRTL() const
+ {
+ return bIgnoreFrmRTL;
+ }
+
+ sal_Bool IsPosMatchesBounds() const
+ {
+ return bPosMatchesBounds;
+ }
+
+ void SetOut( OutputDevice &rNew )
+ {
+ pOut = &rNew;
+ }
+
+ void SetPos( const Point &rNew )
+ {
+ pPos = &rNew;
+#if OSL_DEBUG_LEVEL > 1
+ bPos = sal_True;
+#endif
+ }
+
+ void SetHyphPos( xub_StrLen *pNew )
+ {
+ pHyphPos = pNew;
+#if OSL_DEBUG_LEVEL > 1
+ bHyph = sal_True;
+#endif
+ }
+
+ void SetText( const XubString &rNew )
+ {
+ pText = &rNew;
+ }
+
+ void SetWrong( const SwWrongList* pNew )
+ {
+ pWrong = pNew;
+#if OSL_DEBUG_LEVEL > 1
+ bWrong = sal_True;
+#endif
+ }
+
+ void SetGrammarCheck( const SwWrongList* pNew )
+ {
+ pGrammarCheck = pNew;
+#if OSL_DEBUG_LEVEL > 1
+ bGrammarCheck = sal_True;
+#endif
+ }
+
+ void SetSmartTags( const SwWrongList* pNew )
+ {
+ pSmartTags = pNew;
+ }
+
+ void SetSize( const Size &rNew )
+ {
+ pSize = &rNew;
+#if OSL_DEBUG_LEVEL > 1
+ bSize = sal_True;
+#endif
+ }
+
+ void SetFont( SwFont* pNew )
+ {
+ pFnt = pNew;
+#if OSL_DEBUG_LEVEL > 1
+ bFnt = sal_True;
+#endif
+ }
+
+ void SetIdx( xub_StrLen nNew )
+ {
+ nIdx = nNew;
+ }
+
+ void SetLen( xub_StrLen nNew )
+ {
+ nLen = nNew;
+ }
+
+ void SetOfst( xub_StrLen nNew )
+ {
+ nOfst = nNew;
+#if OSL_DEBUG_LEVEL > 1
+ bOfst = sal_True;
+#endif
+ }
+
+ void SetLeft( long nNew )
+ {
+ nLeft = nNew;
+#if OSL_DEBUG_LEVEL > 1
+ bLeft = sal_True;
+#endif
+ }
+
+ void SetRight( long nNew )
+ {
+ nRight = nNew;
+#if OSL_DEBUG_LEVEL > 1
+ bRight = sal_True;
+#endif
+ }
+
+ void SetKanaDiff( long nNew )
+ {
+ nKanaDiff = nNew;
+#if OSL_DEBUG_LEVEL > 1
+ bKana = sal_True;
+#endif
+ }
+
+ void SetWidth( sal_uInt16 nNew )
+ {
+ nWidth = nNew;
+ }
+
+ void SetAscent( sal_uInt16 nNew )
+ {
+ nAscent = nNew;
+#if OSL_DEBUG_LEVEL > 1
+ bAscent = sal_True;
+#endif
+ }
+
+ void SetKern( long nNew )
+ {
+ nKern = nNew;
+ }
+
+ void SetSpace( long nNew )
+ {
+ if( nNew < 0 )
+ {
+ nSperren = -nNew;
+ nSpace = 0;
+ }
+ else
+ {
+ nSpace = nNew;
+ nSperren = 0;
+ }
+#if OSL_DEBUG_LEVEL > 1
+ bSpace = sal_True;
+ bSperr = sal_True;
+#endif
+ }
+
+ void SetNumberOfBlanks( xub_StrLen nNew )
+ {
+#if OSL_DEBUG_LEVEL > 1
+ bNumberOfBlanks = sal_True;
+#endif
+ nNumberOfBlanks = nNew;
+ }
+
+ void SetCursorBidiLevel( sal_uInt8 nNew )
+ {
+ nCursorBidiLevel = nNew;
+ }
+
+ void SetKanaComp( short nNew )
+ {
+ nCompress = nNew;
+ }
+
+ void SetBullet( sal_Bool bNew )
+ {
+ bBullet = bNew;
+ }
+
+ void SetUnderFnt( SwUnderlineFont* pULFnt )
+ {
+ pUnderFnt = pULFnt;
+ }
+
+ void SetUpper( sal_Bool bNew )
+ {
+ bUpper = bNew;
+#if OSL_DEBUG_LEVEL > 1
+ bUppr = sal_True;
+#endif
+ }
+
+ void SetDrawSpace( sal_Bool bNew )
+ {
+ bDrawSpace = bNew;
+#if OSL_DEBUG_LEVEL > 1
+ bDrawSp = sal_True;
+#endif
+ }
+
+ void SetGreyWave( sal_Bool bNew )
+ {
+ bGreyWave = bNew;
+ }
+
+ void SetSpaceStop( sal_Bool bNew )
+ {
+ bSpaceStop = bNew;
+ }
+
+ void SetSnapToGrid( sal_Bool bNew )
+ {
+ bSnapToGrid = bNew;
+ }
+
+ void SetIgnoreFrmRTL( sal_Bool bNew )
+ {
+ bIgnoreFrmRTL = bNew;
+ }
+
+ void SetPosMatchesBounds( sal_Bool bNew )
+ {
+ bPosMatchesBounds = bNew;
+ }
+
+ void Shift( sal_uInt16 nDir );
+
+ // sets a new color at the output device if necessary
+ // if a font is passed as argument, the change if made to the font
+ // otherwise the font at the output device is changed
+ // returns if the font has been changed
+ sal_Bool ApplyAutoColor( Font* pFnt = 0 );
+};
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/inc/dview.hxx b/sw/source/core/inc/dview.hxx
new file mode 100644
index 000000000000..b51f555ea384
--- /dev/null
+++ b/sw/source/core/inc/dview.hxx
@@ -0,0 +1,136 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+#ifndef _DVIEW_HXX
+#define _DVIEW_HXX
+
+
+#include <svx/fmview.hxx>
+
+class OutputDevice;
+class SwViewImp;
+class SwFrm;
+class SwFlyFrm;
+class SwAnchoredObject;
+
+class SwDrawView : public FmFormView
+{
+ //Fuer den Anker
+ Point aAnchorPoint; //Ankerposition
+ SwViewImp &rImp; //Die View gehoert immer zu einer Shell
+
+ const SwFrm *CalcAnchor();
+
+ /** determine maximal order number for a 'child' object of given 'parent' object
+
+ OD 2004-08-20 #110810#
+ The maximal order number will be determined on the current object
+ order hierarchy. It's the order number of the 'child' object with the
+ highest order number. The calculation can be influenced by parameter
+ <_pExclChildObj> - this 'child' object won't be considered.
+
+ @param <_rParentObj>
+ input parameter - 'parent' object, for which the maximal order number
+ for its 'childs' will be determined.
+
+ @param <_pExclChildObj>
+ optional input parameter - 'child' object, which will not be considered
+ on the calculation of the maximal order number
+
+ @author OD
+ */
+ sal_uInt32 _GetMaxChildOrdNum( const SwFlyFrm& _rParentObj,
+ const SdrObject* _pExclChildObj = 0L ) const;
+
+ /** method to move 'repeated' objects of the given moved object to the
+ according level
+
+ OD 2004-08-23 #110810#
+
+ @param <_rMovedAnchoredObj>
+ input parameter - moved object, for which the 'repeated' ones have also
+ to be moved.
+
+ @param <_rMovedChildsObjs>
+ input parameter - data collection of moved 'child' objects - the 'repeated'
+ ones of these 'childs' will also been moved.
+
+ @author OD
+ */
+ void _MoveRepeatedObjs( const SwAnchoredObject& _rMovedAnchoredObj,
+ const std::vector<SdrObject*>& _rMovedChildObjs ) const;
+
+protected:
+ // add custom handles (used by other apps, e.g. AnchorPos)
+ virtual void AddCustomHdl();
+
+ // overloaded to allow extra handling when picking SwVirtFlyDrawObj's
+ using FmFormView::CheckSingleSdrObjectHit;
+ virtual SdrObject* CheckSingleSdrObjectHit(const Point& rPnt, sal_uInt16 nTol, SdrObject* pObj, SdrPageView* pPV, sal_uLong nOptions, const SetOfByte* pMVisLay) const;
+
+public:
+ SwDrawView( SwViewImp &rI, SdrModel *pMd, OutputDevice* pOutDev=NULL );
+
+ //aus der Basisklasse
+ virtual SdrObject* GetMaxToTopObj(SdrObject* pObj) const;
+ virtual SdrObject* GetMaxToBtmObj(SdrObject* pObj) const;
+ virtual void MarkListHasChanged();
+
+ // #i7672#
+ // Overload to resue edit background color in active text edit view (OutlinerView)
+ virtual void ModelHasChanged();
+
+ virtual void ObjOrderChanged( SdrObject* pObj, sal_uLong nOldPos,
+ sal_uLong nNewPos );
+ virtual sal_Bool TakeDragLimit(SdrDragMode eMode, Rectangle& rRect) const;
+ virtual void MakeVisible( const Rectangle&, Window &rWin );
+ virtual void CheckPossibilities();
+
+ const SwViewImp &Imp() const { return rImp; }
+ SwViewImp &Imp() { return rImp; }
+
+ //Anker und Xor fuer das Draggen.
+ void ShowDragAnchor();
+
+ virtual void DeleteMarked();
+
+ //JP 06.10.98: 2. Versuch
+ inline void ValidateMarkList() { FlushComeBackTimer(); }
+
+ // --> OD 2009-03-05 #i99665#
+ sal_Bool IsAntiAliasing() const;
+ // <--
+
+ // OD 18.06.2003 #108784# - method to replace marked/selected <SwDrawVirtObj>
+ // by its reference object for delete of selection and group selection
+ static void ReplaceMarkedDrawVirtObjs( SdrMarkView& _rMarkView );
+};
+
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/inc/environmentofanchoredobject.hxx b/sw/source/core/inc/environmentofanchoredobject.hxx
new file mode 100644
index 000000000000..0700256555f2
--- /dev/null
+++ b/sw/source/core/inc/environmentofanchoredobject.hxx
@@ -0,0 +1,106 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+ /*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+#ifndef _ENVIRONMENTOFANCHOREDOBJECT_HXX
+#define _ENVIRONMENTOFANCHOREDOBJECT_HXX
+
+class SwFrm;
+class SwLayoutFrm;
+
+namespace objectpositioning
+{
+ class SwEnvironmentOfAnchoredObject
+ {
+ private:
+ const bool mbFollowTextFlow;
+
+ public:
+ /** construtor
+
+ @param _bFollowTextFlow
+ input parameter - indicates, if the anchored object, for which
+ this environment is instantiated, follow the text flow or not
+ */
+ SwEnvironmentOfAnchoredObject( const bool _bFollowTextFlow );
+
+ /** destructor
+ */
+ ~SwEnvironmentOfAnchoredObject();
+
+ /** determine environment layout frame for possible horizontal object
+ positions respectively for alignment to 'page areas'
+
+ this is, if object has to follow the text flow:
+ - cell frame, if anchored inside a cell
+ - fly frame, if anchored inside a fly frame
+ otherwise it's the page frame
+
+ this is, if object hasn't to follow the text flow:
+ - page frame.
+ - no exception any more. Thus remove
+ parameter <_bForPageAlignment>
+
+ @param _rHoriOrientFrm
+ input parameter - frame, at which the horizontal position is
+ oriented at (typically it's the anchor frame).
+ starting point for the search of the layout frame.
+
+ @return reference to the layout frame, which determines the
+ the horizontal environment the object has to be positioned in.
+ */
+ const SwLayoutFrm& GetHoriEnvironmentLayoutFrm( const SwFrm& _rHoriOrientFrm ) const;
+
+ /** determine environment layout frame for possible vertical object
+ positions respectively for alignments to 'page areas'
+
+ this is, if object has to follow the text flow:
+ - cell frame, if anchored inside a cell
+ - fly frame, if anchored inside a fly frame
+ - header/footer frame, if anchored inside page header/footer
+ - footnote frame, if anchored inside footnote
+ otherwise it's the document body frame
+
+ this is, if object hasn't to follow the text flow:
+ - page frame.
+ - no exception any more. Thus remove
+ parameter <_bForPageAlignment>
+
+ @param _rVertOrientFrm
+ input parameter - frame, at which the vertical position is
+ oriented at (typically it's the anchor frame).
+ starting point for the search of the layout frame.
+
+ @return reference to the layout frame, which determines the
+ the vertical environment the object has to be positioned in.
+ */
+ const SwLayoutFrm& GetVertEnvironmentLayoutFrm( const SwFrm& _rVertOrientFrm ) const;
+ };
+} // namespace objectpositioning
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/inc/fieldhint.hxx b/sw/source/core/inc/fieldhint.hxx
new file mode 100644
index 000000000000..82955be53bc8
--- /dev/null
+++ b/sw/source/core/inc/fieldhint.hxx
@@ -0,0 +1,44 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef _FIELDHINT_HXX
+#define _FIELDHINT_HXX
+
+#include <svl/hint.hxx>
+
+class SwFieldHint : public SfxHint
+{
+ SwPaM* pPaM;
+public:
+ SwFieldHint( SwPaM* p )
+ : pPaM(p)
+ {}
+
+ SwPaM* GetPaM() const { return pPaM; }
+};
+
+#endif
diff --git a/sw/source/core/inc/finalthreadmanager.hxx b/sw/source/core/inc/finalthreadmanager.hxx
new file mode 100644
index 000000000000..19e902c53a37
--- /dev/null
+++ b/sw/source/core/inc/finalthreadmanager.hxx
@@ -0,0 +1,108 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+#ifndef _FINALTHREADMANAGER_HXX
+#define _FINALTHREADMANAGER_HXX
+
+#include "sal/config.h"
+#include "cppuhelper/factory.hxx"
+#include "cppuhelper/implementationentry.hxx"
+#include "cppuhelper/implbase3.hxx"
+#include "com/sun/star/lang/XServiceInfo.hpp"
+#include "com/sun/star/util/XJobManager.hpp"
+#include "com/sun/star/frame/XTerminateListener2.hpp"
+
+
+#include <osl/mutex.hxx>
+
+#include <list>
+
+class CancelJobsThread;
+class TerminateOfficeThread;
+class SwPauseThreadStarting;
+
+// service helper namespace
+namespace comp_FinalThreadManager {
+
+// component and service helper functions:
+::rtl::OUString SAL_CALL _getImplementationName();
+com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL _getSupportedServiceNames();
+com::sun::star::uno::Reference< com::sun::star::uno::XInterface > SAL_CALL _create(
+ com::sun::star::uno::Reference< com::sun::star::uno::XComponentContext > const & context );
+
+} // closing service helper namespace
+
+
+class FinalThreadManager : public ::cppu::WeakImplHelper3< com::sun::star::lang::XServiceInfo,
+ com::sun::star::util::XJobManager,
+ com::sun::star::frame::XTerminateListener2 >
+{
+public:
+ explicit FinalThreadManager(com::sun::star::uno::Reference< com::sun::star::uno::XComponentContext > const & context);
+
+ // ::com::sun::star::lang::XServiceInfo:
+ virtual ::rtl::OUString SAL_CALL getImplementationName() throw (com::sun::star::uno::RuntimeException);
+ virtual ::sal_Bool SAL_CALL supportsService(const ::rtl::OUString & ServiceName) throw (com::sun::star::uno::RuntimeException);
+ virtual com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL getSupportedServiceNames() throw (com::sun::star::uno::RuntimeException);
+
+ // ::com::sun::star::util::XJobManager:
+ virtual void SAL_CALL registerJob(const com::sun::star::uno::Reference< com::sun::star::util::XCancellable > & Job) throw (com::sun::star::uno::RuntimeException);
+ virtual void SAL_CALL releaseJob(const com::sun::star::uno::Reference< com::sun::star::util::XCancellable > & Job) throw (com::sun::star::uno::RuntimeException);
+ virtual void SAL_CALL cancelAllJobs() throw (com::sun::star::uno::RuntimeException);
+
+ // ::com::sun::star::frame::XTerminateListener2
+ virtual void SAL_CALL cancelTermination( const ::com::sun::star::lang::EventObject& Event ) throw (::com::sun::star::uno::RuntimeException);
+
+ // ::com::sun::star::frame::XTerminateListener (inherited via com::sun::star::frame::XTerminateListener2)
+ virtual void SAL_CALL queryTermination( const ::com::sun::star::lang::EventObject& Event ) throw (::com::sun::star::frame::TerminationVetoException, ::com::sun::star::uno::RuntimeException);
+ virtual void SAL_CALL notifyTermination( const ::com::sun::star::lang::EventObject& Event ) throw (::com::sun::star::uno::RuntimeException);
+
+ // ::com::sun:star::lang::XEventListener (inherited via com::sun::star::frame::XTerminateListener)
+ virtual void SAL_CALL disposing( const ::com::sun::star::lang::EventObject& Source ) throw (::com::sun::star::uno::RuntimeException);
+
+private:
+ FinalThreadManager(FinalThreadManager &); // not defined
+ void operator =(FinalThreadManager &); // not defined
+
+ virtual ~FinalThreadManager();
+
+ void registerAsListenerAtDesktop();
+
+ com::sun::star::uno::Reference< com::sun::star::uno::XComponentContext > m_xContext;
+
+ osl::Mutex maMutex;
+
+ std::list< com::sun::star::uno::Reference< com::sun::star::util::XCancellable > > maThreads;
+ CancelJobsThread* mpCancelJobsThread;
+ TerminateOfficeThread* mpTerminateOfficeThread;
+ SwPauseThreadStarting* mpPauseThreadStarting;
+
+ bool mbRegisteredAtDesktop;
+};
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/inc/flowfrm.hxx b/sw/source/core/inc/flowfrm.hxx
new file mode 100644
index 000000000000..1403718101d8
--- /dev/null
+++ b/sw/source/core/inc/flowfrm.hxx
@@ -0,0 +1,255 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+#ifndef _FLOWFRM_HXX
+#define _FLOWFRM_HXX
+
+//Der FlowFrm gibt die Funktionalitaet fuer alle Frms vor, die fliessen und
+//die sich aufspalten koennen (wie CntntFrm oder TabFrm).
+//Teile der Funktionalitaet sind im FlowFrm implementiert, andere Teile werden
+//von den spezifischen Frms implementiert.
+//Der FlowFrm ist kein eigenstaender Frm, es kann also auch niemals eine
+//eigenstaendige Instanz vom FlowFrm existieren.
+//Der FlowFrm ist nicht einmal ein echter Frm. Die naheliegende Implementierung
+//waere ein FlowFrm der virtual vom SwFrm abgeleitet ist und direkt auf den
+//eigenen Instanzdaten arbeitet. Abgeleitete Klassen muessten sich
+//vom FlowFrm und (ueber mehrere Basisklassen weil der Klassenbaum sich direkt
+//vom SwFrm zu SwCntntFrm und zum SwLayoutFrm spaltet) virtual vom SwFrm
+//ableiten.
+//Leider entstehen dadurch - neben Problemen mit Compilern und Debuggern -
+//erhebliche zusaetzliche Kosten, die wir uns heutzutage IMHO nicht erlauben
+//koennen.
+//Ich greife deshalb auf eine andere Technik zurueck: Der FlowFrm hat eine
+//Referenz auf den SwFrm - der er genau betrachtet selbst ist - und ist mit
+//diesem befreundet. So kann der FlowFrm anstelle des this-Pointer mit der
+//Referenz auf den SwFrm arbeiten.
+
+class SwPageFrm;
+class SwRect;
+class SwBorderAttrs;
+class SwDoc;
+class SwNodeIndex;
+// #i44049#
+class SwObjectFormatterTxtFrm;
+
+void MakeFrms( SwDoc *, const SwNodeIndex &, const SwNodeIndex & );
+
+class SwFlowFrm
+{
+ //PrepareMake darf Locken/Unlocken (Robustheit)
+ friend inline void PrepareLock ( SwFlowFrm * );
+ friend inline void PrepareUnlock( SwFlowFrm * );
+ friend inline void TableSplitRecalcLock( SwFlowFrm * );
+ friend inline void TableSplitRecalcUnlock( SwFlowFrm * );
+ // #i44049#
+ friend class SwObjectFormatterTxtFrm;
+
+ //TblSel darf das Follow-Bit zuruecksetzen.
+ friend inline void UnsetFollow( SwFlowFrm *pFlow );
+
+ friend void MakeFrms( SwDoc *, const SwNodeIndex &, const SwNodeIndex & );
+
+ friend class SwNode2LayImpl;
+
+ SwFrm &rThis;
+
+ //Hilfsfunktionen fuer MoveSubTree()
+ static SwLayoutFrm *CutTree( SwFrm* );
+ static sal_Bool PasteTree( SwFrm *, SwLayoutFrm *, SwFrm *, SwFrm* );
+
+ //Wird fuer das Zusammenspiel von _GetPrevxxx und MoveBwd gebraucht, damit
+ //mehrere Blaetter gleichzeitig uebersprungen werden koennen.
+ //Wird auch vom MoveBwd des TabFrm ausgewertet!
+ static sal_Bool bMoveBwdJump;
+
+ /** helper method to determine previous frame for calculation of the
+ upper space
+
+ #i11860#
+
+ @param _pProposedPrevFrm
+ optional input parameter - pointer to frame, which should be used
+ instead of the direct previous frame.
+ */
+ const SwFrm* _GetPrevFrmForUpperSpaceCalc( const SwFrm* _pProposedPrevFrm = 0L ) const;
+
+ /** method to detemine the upper space amount, which is considered for
+ the previous frame
+
+ #i11860#
+ */
+ SwTwips _GetUpperSpaceAmountConsideredForPrevFrm() const;
+
+ /** method to detemine the upper space amount, which is considered for
+ the page grid
+
+ #i11860#
+ */
+ SwTwips _GetUpperSpaceAmountConsideredForPageGrid(
+ const SwTwips _nUpperSpaceWithoutGrid ) const;
+
+protected:
+
+ SwFlowFrm *pFollow;
+
+ sal_Bool bIsFollow :1; //Ist's ein Follow
+ sal_Bool bLockJoin :1; //Join (und damit deleten) verboten wenn sal_True!
+ sal_Bool bUndersized:1; // wir sind kleiner als gewuenscht
+ sal_Bool bFtnAtEnd :1; // For sectionfrms only: footnotes at the end of section
+ sal_Bool bEndnAtEnd :1; // " " " : endnotes at the end of section
+ sal_Bool bCntntLock :1; // " " " : content locked
+ sal_Bool bOwnFtnNum :1; // " " " : special numbering of footnotes
+ sal_Bool bFtnLock :1; // " " " : ftn, don't leave this section bwd
+ sal_Bool bFlyLock :1; // Stop positioning of at-character flyframes
+
+ //Prueft ob Vorwaertsfluss noch Sinn macht Endloswanderschaften (unterbinden)
+ inline sal_Bool IsFwdMoveAllowed();
+ // #i44049# - method <CalcCntnt(..)> has to check this property.
+ friend void CalcCntnt( SwLayoutFrm *pLay, bool bNoColl, bool bNoCalcFollow );
+ sal_Bool IsKeepFwdMoveAllowed(); //Wie oben, Move fuer Keep.
+
+ //Prueft ob ein Obj das Umlauf wuenscht ueberlappt.
+ //eine Null bedeutet, kein Objekt ueberlappt,
+ // 1 heisst, Objekte, die am FlowFrm selbst verankert sind, ueberlappen
+ // 2 heisst, Objekte, die woanders verankert sind, ueberlappen
+ // 3 heistt, beiderlei verankerte Objekte ueberlappen
+ sal_uInt8 BwdMoveNecessary( const SwPageFrm *pPage, const SwRect &rRect );
+
+ void LockJoin() { bLockJoin = sal_True; }
+ void UnlockJoin() { bLockJoin = sal_False; }
+
+ sal_Bool CheckMoveFwd( sal_Bool &rbMakePage, sal_Bool bKeep, sal_Bool bMovedBwd );
+ sal_Bool MoveFwd( sal_Bool bMakePage, sal_Bool bPageBreak, sal_Bool bMoveAlways = sal_False );
+ virtual sal_Bool ShouldBwdMoved( SwLayoutFrm *pNewUpper, sal_Bool bHead, sal_Bool &rReformat )=0;
+ sal_Bool MoveBwd( sal_Bool &rbReformat );
+
+public:
+ SwFlowFrm( SwFrm &rFrm );
+
+ const SwFrm *GetFrm() const { return &rThis; }
+ SwFrm *GetFrm() { return &rThis; }
+
+ static sal_Bool IsMoveBwdJump() { return bMoveBwdJump; }
+ static void SetMoveBwdJump( sal_Bool bNew ){ bMoveBwdJump = bNew; }
+
+ inline void SetUndersized( const sal_Bool bNew ) { bUndersized = bNew; }
+ inline sal_Bool IsUndersized() const { return bUndersized; }
+
+ sal_Bool IsPrevObjMove() const;
+
+ //Die Kette mit minimalen Operationen und Benachrichtigungen unter den
+ //neuen Parent Moven.
+ void MoveSubTree( SwLayoutFrm* pParent, SwFrm* pSibling = 0 );
+
+ sal_Bool HasFollow() const { return pFollow ? sal_True : sal_False; }
+ sal_Bool IsFollow() const { return bIsFollow; }
+ inline void _SetIsFollow( sal_Bool bSet ) { bIsFollow = bSet; }
+ const SwFlowFrm *GetFollow() const { return pFollow; }
+ SwFlowFrm *GetFollow() { return pFollow; }
+ sal_Bool IsAnFollow( const SwFlowFrm *pFlow ) const;
+ inline void SetFollow( SwFlowFrm *pNew ) { pFollow = pNew; }
+
+ sal_Bool IsJoinLocked() const { return bLockJoin; }
+ sal_Bool IsAnyJoinLocked() const { return bLockJoin || HasLockedFollow(); }
+ sal_Bool IsFtnAtEnd() const { return bFtnAtEnd; }
+ sal_Bool IsEndnAtEnd() const { return bEndnAtEnd; }
+ sal_Bool IsAnyNoteAtEnd() const { return bFtnAtEnd || bEndnAtEnd; }
+ sal_Bool AreNotesAtEnd() const { return bFtnAtEnd && bEndnAtEnd; }
+
+ sal_Bool IsPageBreak( sal_Bool bAct ) const;
+ sal_Bool IsColBreak( sal_Bool bAct ) const;
+
+ //Ist ein Keep zu beruecksichtigen (Breaks!)
+ sal_Bool IsKeep( const SwAttrSet& rAttrs, bool bBreakCheck = false ) const;
+
+ sal_Bool HasLockedFollow() const;
+
+ sal_Bool HasParaSpaceAtPages( sal_Bool bSct ) const;
+
+ /** method to determine the upper space hold by the frame
+
+ #i11860# - add 3rd parameter <_bConsiderGrid> to get
+ the upper space with and without considering the page grid
+ (default value: <sal_True>)
+ */
+ SwTwips CalcUpperSpace( const SwBorderAttrs *pAttrs = NULL,
+ const SwFrm* pPr = NULL,
+ const bool _bConsiderGrid = true ) const;
+
+ /** method to determine the upper space amount, which is considered for
+ the previous frame and the page grid, if option 'Use former object
+ positioning' is OFF
+
+ #i11860#
+ */
+ SwTwips GetUpperSpaceAmountConsideredForPrevFrmAndPageGrid() const;
+
+ /** calculation of lower space
+ */
+ SwTwips CalcLowerSpace( const SwBorderAttrs* _pAttrs = 0L ) const;
+
+ /** calculation of the additional space to be considered, if flow frame
+ is the last inside a table cell
+
+ #i26250
+
+ @param _pAttrs
+ optional input parameter - border attributes of the flow frame.
+ Used for optimization, if caller has already determined the border
+ attributes.
+
+ @return SwTwips
+ */
+ SwTwips CalcAddLowerSpaceAsLastInTableCell(
+ const SwBorderAttrs* _pAttrs = 0L ) const;
+
+ void CheckKeep();
+
+ void SetFtnLock( sal_Bool bNew ){ bFtnLock = bNew; }
+ sal_Bool IsFtnLock() const { return bFtnLock; }
+ void SetFlyLock( sal_Bool bNew ){ bFlyLock = bNew; }
+ sal_Bool IsFlyLock() const { return bFlyLock; }
+ void SetOwnFtnNum( sal_Bool bNew ){ bOwnFtnNum = bNew; }
+ sal_Bool IsOwnFtnNum() const { return bOwnFtnNum; }
+ void SetCntntLock( sal_Bool bNew ){ bCntntLock = bNew; }
+ sal_Bool IsCntntLocked() const { return bCntntLock; }
+
+ //casten einen Frm auf einen FlowFrm - wenns denn einer ist, sonst 0
+ //Diese Methoden muessen fuer neue Ableitungen geaendert werden!
+ static SwFlowFrm *CastFlowFrm( SwFrm *pFrm );
+ static const SwFlowFrm *CastFlowFrm( const SwFrm *pFrm );
+};
+
+inline sal_Bool SwFlowFrm::IsFwdMoveAllowed()
+{
+ return rThis.GetIndPrev() != 0;
+}
+
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/inc/flyfrm.hxx b/sw/source/core/inc/flyfrm.hxx
new file mode 100644
index 000000000000..04525e1c0fd5
--- /dev/null
+++ b/sw/source/core/inc/flyfrm.hxx
@@ -0,0 +1,288 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+#ifndef SW_FLYFRM_HXX
+#define SW_FLYFRM_HXX
+
+#include "layfrm.hxx"
+#include <list>
+#include "frmfmt.hxx"
+
+class SwPageFrm;
+class SwFmtFrmSize;
+struct SwCrsrMoveState;
+class SwBorderAttrs;
+class SwVirtFlyDrawObj;
+class SwSpzFrmFmts;
+class SwAttrSetChg;
+class PolyPolygon;
+class SwFlyDrawContact;
+class SwDrawContact;
+class SwFmt;
+
+#include <anchoredobject.hxx>
+
+//Sucht ausgehend von pOldAnch einen Anker fuer Absatzgebundene Rahmen.
+//Wird beim Draggen von Absatzgebundenen Objekten zur Ankeranzeige sowie
+//fuer Ankerwechsel benoetigt.
+//implementiert in layout/flycnt.cxx
+const SwCntntFrm *FindAnchor( const SwFrm *pOldAnch, const Point &rNew,
+ const sal_Bool bBody = sal_False );
+
+// berechnet das Rechteck, in dem das Objekt bewegt bzw. resized werden darf
+sal_Bool CalcClipRect( const SdrObject *pSdrObj, SwRect &rRect, sal_Bool bMove = sal_True );
+
+//allg. Basisklasse fuer alle Freifliegenden Rahmen
+// #i26791# - inherit also from <SwAnchoredFlyFrm>
+class SwFlyFrm : public SwLayoutFrm, public SwAnchoredObject
+{
+ //darf Locken. Definiert in frmtool.cxx
+ friend void AppendObjs ( const SwSpzFrmFmts *, sal_uLong, SwFrm *, SwPageFrm * );
+ friend void Notify( SwFlyFrm *, SwPageFrm *pOld, const SwRect &rOld,
+ const SwRect* pOldPrt );
+
+ void InitDrawObj( sal_Bool bNotify ); //Wird von den CToren gerufen.
+ void FinitDrawObj(); //Wird vom CTor gerufen.
+
+ void _UpdateAttr( const SfxPoolItem*, const SfxPoolItem*, sal_uInt8 &,
+ SwAttrSetChg *pa = 0, SwAttrSetChg *pb = 0 );
+
+ using SwLayoutFrm::CalcRel;
+
+ sal_uInt32 _GetOrdNumForNewRef( const SwFlyDrawContact* );
+ SwVirtFlyDrawObj* CreateNewRef( SwFlyDrawContact* );
+
+protected:
+
+ SwFlyFrm *pPrevLink, // Vorgaenger/Nachfolger fuer Verkettung mit
+ *pNextLink; // Textfluss
+
+ // #i26791# - moved to <SwAnchoredObject>
+// Point aRelPos; //Die Relative Position zum Master
+
+private:
+ sal_Bool bLocked :1; //Cntnt-gebundene Flys muessen derart blockiert werden
+ //koennen, dass sie nicht Formatiert werden; :MakeAll
+ //returnt dann sofort. Dies ist bei Seitenwechseln
+ //waehrend der Formatierung notwendig.
+ //Auch wahrend des RootCTors ist dies notwendig da
+ //sonst der Anker formatiert wird obwohl die Root noch
+ //nicht korrekt an der Shell haengt und weil sonst
+ //initial zuviel Formatiert wuerde.
+ sal_Bool bNotifyBack:1; //sal_True wenn am Ende eines MakeAll() der Background
+ //vom NotifyDTor benachrichtigt werden muss.
+protected:
+
+ sal_Bool bInvalid :1; //Pos, PrtArea od. SSize wurden Invalidiert, sie werden
+ //gleich wieder Validiert, denn sie muessen _immer_
+ //gueltig sein. Damit in LayAction korrekt gearbeitet
+ //werden kann muss hier festgehalten werden, dass sie
+ //invalidiert wurden. Ausnahmen bestaetigen die Regelt!
+ sal_Bool bMinHeight:1; //sal_True wenn die vom Attribut vorgegebene Hoehe eine
+ //eine Minimalhoehe ist (der Frm also bei Bedarf
+ //darueberhinaus wachsen kann).
+ sal_Bool bHeightClipped :1; //sal_True wenn der Fly nicht die Pos/Size anhand der Attrs
+ sal_Bool bWidthClipped :1; //formatieren konnte, weil z.B. nicht genug Raum vorh.
+ //war.
+ sal_Bool bFormatHeightOnly :1; //Damit nach einer Anpassung der Breite
+ //(CheckClip) nur das Format aufgerufen wird;
+ //nicht aber die Breite anhand der Attribute
+ //wieder bestimmt wird.
+ sal_Bool bInCnt :1; // FLY_AS_CHAR, anchored as character
+ sal_Bool bAtCnt :1; // FLY_AT_PARA, anchored at paragraph
+ sal_Bool bLayout :1; // FLY_AT_PAGE, FLY_AT_FLY, at page or at frame
+ sal_Bool bAutoPosition :1; // FLY_AT_CHAR, anchored at character
+ sal_Bool bNoShrink :1; // temporary forbud of shrinking to avoid loops
+ sal_Bool bLockDeleteContent :1; // If the flag is set, the content of the
+ // fly frame is not deleted if moved to
+ // invisible layer.
+
+ friend class SwNoTxtFrm; // Darf NotifyBackground rufen
+
+ virtual void Format( const SwBorderAttrs *pAttrs = 0 );
+ void MakePrtArea( const SwBorderAttrs &rAttrs );
+
+ void Lock() { bLocked = sal_True; }
+ void Unlock() { bLocked = sal_False; }
+
+ void SetMinHeight() { bMinHeight = sal_True; }
+ void ResetMinHeight(){ bMinHeight = sal_False; }
+
+ Size CalcRel( const SwFmtFrmSize &rSz ) const;
+ SwTwips CalcAutoWidth() const;
+
+ SwFlyFrm( SwFlyFrmFmt*, SwFrm*, SwFrm *pAnchor );
+
+ /** method to assure that anchored object is registered at the correct
+ page frame
+
+ #i28701#
+ */
+ virtual void RegisterAtCorrectPage();
+
+ virtual bool _SetObjTop( const SwTwips _nTop );
+ virtual bool _SetObjLeft( const SwTwips _nLeft );
+
+ virtual const SwRect GetObjBoundRect() const;
+ virtual void Modify( const SfxPoolItem*, const SfxPoolItem* );
+
+ virtual const IDocumentDrawModelAccess* getIDocumentDrawModelAccess( );
+
+public:
+ // #i26791#
+ TYPEINFO();
+
+ virtual ~SwFlyFrm();
+ // erfrage vom Client Informationen
+ virtual sal_Bool GetInfo( SfxPoolItem& ) const;
+ virtual void Paint( SwRect const&,
+ SwPrintData const*const pPrintData = NULL ) const;
+ virtual Size ChgSize( const Size& aNewSize );
+ virtual sal_Bool GetCrsrOfst( SwPosition *, Point&,
+ SwCrsrMoveState* = 0 ) const;
+
+ virtual void CheckDirection( sal_Bool bVert );
+ virtual void Cut();
+#if OSL_DEBUG_LEVEL > 1
+ virtual void Paste( SwFrm* pParent, SwFrm* pSibling = 0 );
+#endif
+
+ SwTwips _Shrink( SwTwips, sal_Bool bTst );
+ SwTwips _Grow ( SwTwips, sal_Bool bTst );
+ void _Invalidate( SwPageFrm *pPage = 0 );
+
+ sal_Bool FrmSizeChg( const SwFmtFrmSize & );
+
+ SwFlyFrm *GetPrevLink() const { return pPrevLink; }
+ SwFlyFrm *GetNextLink() const { return pNextLink; }
+
+ static void ChainFrames( SwFlyFrm *pMaster, SwFlyFrm *pFollow );
+ static void UnchainFrames( SwFlyFrm *pMaster, SwFlyFrm *pFollow );
+
+ SwFlyFrm *FindChainNeighbour( SwFrmFmt &rFmt, SwFrm *pAnch = 0 );
+
+ // #i26791#
+ const SwVirtFlyDrawObj* GetVirtDrawObj() const;
+ SwVirtFlyDrawObj *GetVirtDrawObj();
+ void NotifyDrawObj();
+
+ void ChgRelPos( const Point &rAbsPos );
+ sal_Bool IsInvalid() const { return bInvalid; }
+ void Invalidate() const { ((SwFlyFrm*)this)->bInvalid = sal_True; }
+ void Validate() const { ((SwFlyFrm*)this)->bInvalid = sal_False; }
+
+ sal_Bool IsMinHeight() const { return bMinHeight; }
+ sal_Bool IsLocked() const { return bLocked; }
+ sal_Bool IsAutoPos() const { return bAutoPosition; }
+ sal_Bool IsFlyInCntFrm() const { return bInCnt; }
+ sal_Bool IsFlyFreeFrm() const { return bAtCnt || bLayout; }
+ sal_Bool IsFlyLayFrm() const { return bLayout; }
+ sal_Bool IsFlyAtCntFrm() const { return bAtCnt; }
+
+ sal_Bool IsNotifyBack() const { return bNotifyBack; }
+ void SetNotifyBack() { bNotifyBack = sal_True; }
+ void ResetNotifyBack() { bNotifyBack = sal_False; }
+ sal_Bool IsNoShrink() const { return bNoShrink; }
+ void SetNoShrink( sal_Bool bNew ) { bNoShrink = bNew; }
+ sal_Bool IsLockDeleteContent() const { return bLockDeleteContent; }
+ void SetLockDeleteContent( sal_Bool bNew ) { bLockDeleteContent = bNew; }
+
+
+ sal_Bool IsClipped() const { return bHeightClipped || bWidthClipped; }
+ sal_Bool IsHeightClipped() const { return bHeightClipped; }
+ sal_Bool IsWidthClipped() const { return bWidthClipped; }
+
+ sal_Bool IsLowerOf( const SwLayoutFrm* pUpper ) const;
+ inline sal_Bool IsUpperOf( const SwFlyFrm& _rLower ) const
+ {
+ return _rLower.IsLowerOf( this );
+ }
+
+ SwFrm *FindLastLower();
+
+ // #i13147# - add parameter <_bForPaint> to avoid load of
+ // the graphic during paint. Default value: sal_False
+ sal_Bool GetContour( PolyPolygon& rContour,
+ const sal_Bool _bForPaint = sal_False ) const;
+
+
+ //Auf dieser Shell painten (PreView, Print-Flag usw. rekursiv beachten)?.
+ static sal_Bool IsPaint( SdrObject *pObj, const ViewShell *pSh );
+
+ /** SwFlyFrm::IsBackgroundTransparent
+
+ determines, if background of fly frame has to be drawn transparent
+ definition found in /core/layout/paintfrm.cxx
+
+ @return true, if background color is transparent or a existing background
+ graphic is transparent.
+ */
+ sal_Bool IsBackgroundTransparent() const;
+
+ /** SwFlyFrm::IsShadowTransparent
+
+ determine, if shadow color of fly frame has to be drawn transparent
+ definition found in /core/layout/paintfrm.cxx
+
+ @return true, if shadow color is transparent.
+ */
+ sal_Bool IsShadowTransparent() const;
+
+ void Chain( SwFrm* _pAnchor );
+ void Unchain();
+ void InsertCnt();
+ void DeleteCnt();
+ void InsertColumns();
+
+ // #i26791# - pure virtual methods of base class <SwAnchoredObject>
+ virtual void MakeObjPos();
+ virtual void InvalidateObjPos();
+
+ virtual SwFrmFmt& GetFrmFmt();
+ virtual const SwFrmFmt& GetFrmFmt() const;
+
+ virtual const SwRect GetObjRect() const;
+
+ /** method to determine, if a format on the Writer fly frame is possible
+
+ #i28701#
+ refine 'IsFormatPossible'-conditions of method
+ <SwAnchoredObject::IsFormatPossible()> by:
+ format isn't possible, if Writer fly frame is locked resp. col-locked.
+ */
+ virtual bool IsFormatPossible() const;
+ static void GetAnchoredObjects( std::list<SwAnchoredObject*>&, const SwFmt& rFmt );
+
+ // overwriting "SwFrmFmt *SwLayoutFrm::GetFmt" to provide the correct derived return type.
+ // (This is in order to skip on the otherwise necessary casting of the result to
+ // 'SwFlyFrmFmt *' after calls to this function. The casting is now done in this function.)
+ virtual const SwFlyFrmFmt *GetFmt() const;
+ virtual SwFlyFrmFmt *GetFmt();
+};
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/inc/flyfrms.hxx b/sw/source/core/inc/flyfrms.hxx
new file mode 100644
index 000000000000..8b89e869f21f
--- /dev/null
+++ b/sw/source/core/inc/flyfrms.hxx
@@ -0,0 +1,260 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+#ifndef _FLYFRMS_HXX
+#define _FLYFRMS_HXX
+#include "flyfrm.hxx"
+// --> #i28701#
+class SwFlyAtCntFrm;
+
+//Basisklasse fuer diejenigen Flys, die sich relativ frei Bewegen koennen -
+//also die nicht _im_ Inhalt gebundenen Flys.
+class SwFlyFreeFrm : public SwFlyFrm
+{
+ SwPageFrm *pPage; //Bei dieser Seite ist der Fly angemeldet.
+
+ // --> #i34753# - flag for at-page anchored Writer fly frames
+ // to prevent a positioning - call of method <MakeObjPos()> -, if Writer
+ // fly frame is already clipped during its format by the object formatter.
+ bool mbNoMakePos;
+ // <--
+ // --> #i37068# - flag to prevent move in method
+ // <CheckClip(..)>
+ bool mbNoMoveOnCheckClip;
+ // <--
+ void CheckClip( const SwFmtFrmSize &rSz ); //'Emergency' Clipping.
+
+ /** determines, if direct environment of fly frame has 'auto' size
+
+ #i17297#
+ start with anchor frame and search for a header, footer, row or fly frame
+ stopping at page frame.
+ return <true>, if such a frame is found and it has 'auto' size.
+ otherwise <false> is returned.
+
+ @author OD
+
+ @return boolean indicating, that direct environment has 'auto' size
+ */
+ bool HasEnvironmentAutoSize() const;
+
+protected:
+ // #i28701# - new friend class <SwFlyNotify> for access to
+ // method <NotifyBackground>
+ friend class SwFlyNotify;
+ virtual void NotifyBackground( SwPageFrm *pPage,
+ const SwRect& rRect, PrepareHint eHint);
+
+ SwFlyFreeFrm( SwFlyFrmFmt*, SwFrm*, SwFrm *pAnchor );
+
+public:
+ // --> #i28701#
+ TYPEINFO();
+
+ virtual ~SwFlyFreeFrm();
+
+ virtual void MakeAll();
+
+ // --> #i37068# - accessors for member <mbNoMoveOnCheckClip>
+ inline void SetNoMoveOnCheckClip( const bool _bNewNoMoveOnCheckClip )
+ {
+ mbNoMoveOnCheckClip = _bNewNoMoveOnCheckClip;
+ }
+ inline bool IsNoMoveOnCheckClip() const
+ {
+ return mbNoMoveOnCheckClip;
+ }
+ // <--
+ // --> #i34753# - accessors for member <mbNoMakePos>
+ inline void SetNoMakePos( const bool _bNoMakePos )
+ {
+ if ( IsFlyLayFrm() )
+ {
+ mbNoMakePos = _bNoMakePos;
+ }
+ }
+ inline bool IsNoMakePos() const
+ {
+ if ( IsFlyLayFrm() )
+ {
+ return mbNoMakePos;
+ }
+ else
+ {
+ return false;
+ }
+ }
+ // <--
+
+ /** method to determine, if a format on the Writer fly frame is possible
+
+ #i28701#
+ refine 'IsFormatPossible'-conditions of method
+ <SwFlyFrm::IsFormatPossible()> by:
+ format isn't possible, if Writer fly frame isn't registered at a page frame
+ and its anchor frame isn't inside another Writer fly frame.
+
+ @author OD
+ */
+ virtual bool IsFormatPossible() const;
+};
+
+
+//Die Fly's, die an einem Layoutfrm haengen und nicht inhaltsgebunden sind
+class SwFlyLayFrm : public SwFlyFreeFrm
+{
+public:
+ // --> #i28701#
+ TYPEINFO();
+
+ SwFlyLayFrm( SwFlyFrmFmt*, SwFrm*, SwFrm *pAnchor );
+ SwFlyLayFrm( SwFlyLayFrm& );
+protected:
+ virtual void Modify( const SfxPoolItem*, const SfxPoolItem* );
+};
+
+//Die Flys, die an einem Cntnt haengen nicht aber im Inhalt
+class SwFlyAtCntFrm : public SwFlyFreeFrm
+{
+protected:
+ virtual void MakeAll();
+
+ // #i28701#
+ virtual bool _InvalidationAllowed( const InvalidationType _nInvalid ) const;
+
+ /** method to assure that anchored object is registered at the correct
+ page frame
+
+ #i28701#
+
+ @author OD
+ */
+ virtual void RegisterAtCorrectPage();
+ virtual void Modify( const SfxPoolItem*, const SfxPoolItem* );
+
+public:
+ // --> #i28701#
+ TYPEINFO();
+
+ SwFlyAtCntFrm( SwFlyFrmFmt*, SwFrm*, SwFrm *pAnchor );
+
+ void SetAbsPos( const Point &rNew );
+
+ // #i26791#
+ virtual void MakeObjPos();
+
+ /** method to determine, if a format on the Writer fly frame is possible
+
+ #i28701#
+ refine 'IsFormatPossible'-conditions of method
+ <SwFlyFreeFrm::IsFormatPossible()> by:
+ format isn't possible, if method <MakeAll()> is already in progress.
+
+ @author OD
+ */
+ virtual bool IsFormatPossible() const;
+};
+
+//Die Flys, die an einem Zeichen in einem Cntnt haengen.
+class SwFlyInCntFrm : public SwFlyFrm
+{
+ Point aRef; //Relativ zu diesem Point wird die AbsPos berechnet.
+ long nLine; //Zeilenhoehe, Ref.Y() - nLine == Zeilenanfang.
+
+ sal_Bool bInvalidLayout :1;
+ sal_Bool bInvalidCntnt :1;
+
+protected:
+ virtual void NotifyBackground( SwPageFrm *pPage,
+ const SwRect& rRect, PrepareHint eHint);
+ virtual void MakeAll();
+ virtual void Modify( const SfxPoolItem*, const SfxPoolItem* );
+
+public:
+ // --> #i28701#
+ TYPEINFO();
+
+ SwFlyInCntFrm( SwFlyFrmFmt*, SwFrm*, SwFrm *pAnchor );
+
+ virtual ~SwFlyInCntFrm();
+ virtual void Format( const SwBorderAttrs *pAttrs = 0 );
+
+ void SetRefPoint( const Point& rPoint, const Point &rRelAttr,
+ const Point &rRelPos );
+ const Point &GetRefPoint() const { return aRef; }
+ const Point GetRelPos() const;
+ long GetLineHeight() const { return nLine; }
+
+ inline void InvalidateLayout() const;
+ inline void InvalidateCntnt() const;
+ inline void ValidateLayout() const;
+ inline void ValidateCntnt() const;
+ sal_Bool IsInvalid() const { return (bInvalidLayout || bInvalidCntnt); }
+ sal_Bool IsInvalidLayout() const { return bInvalidLayout; }
+ sal_Bool IsInvalidCntnt() const { return bInvalidCntnt; }
+
+
+ //BP 26.11.93: vgl. tabfrm.hxx, gilt bestimmt aber fuer andere auch...
+ //Zum Anmelden der Flys nachdem ein FlyCnt erzeugt _und_ eingefuegt wurde.
+ //Muss vom Erzeuger gerufen werden, denn erst nach dem Konstruieren wird
+ //Das Teil gepastet; mithin ist auch erst dann die Seite zum Anmelden der
+ //Flys erreichbar.
+ void RegistFlys();
+
+ //siehe layact.cxx
+ void AddRefOfst( long nOfst ) { aRef.Y() += nOfst; }
+
+ // #i26791#
+ virtual void MakeObjPos();
+
+ // --> #115759# - invalidate anchor frame on invalidation
+ // of the position, because the position is calculated during the
+ // format of the anchor frame
+ virtual void _ActionOnInvalidation( const InvalidationType _nInvalid );
+ // <--
+};
+
+inline void SwFlyInCntFrm::InvalidateLayout() const
+{
+ ((SwFlyInCntFrm*)this)->bInvalidLayout = sal_True;
+}
+inline void SwFlyInCntFrm::InvalidateCntnt() const
+{
+ ((SwFlyInCntFrm*)this)->bInvalidCntnt = sal_True;
+}
+inline void SwFlyInCntFrm::ValidateLayout() const
+{
+ ((SwFlyInCntFrm*)this)->bInvalidLayout = sal_False;
+}
+inline void SwFlyInCntFrm::ValidateCntnt() const
+{
+ ((SwFlyInCntFrm*)this)->bInvalidCntnt = sal_False;
+}
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/inc/fntcache.hxx b/sw/source/core/inc/fntcache.hxx
new file mode 100644
index 000000000000..39a739ab41e2
--- /dev/null
+++ b/sw/source/core/inc/fntcache.hxx
@@ -0,0 +1,163 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+#ifndef _FNTCACHE_HXX
+#define _FNTCACHE_HXX
+
+#include <vcl/font.hxx>
+#include <tools/mempool.hxx>
+
+#include "swtypes.hxx"
+#include "swcache.hxx"
+
+class Printer;
+class OutputDevice;
+class FontMetric;
+class SwFntObj;
+class SwDrawTextInfo; // DrawText
+class ViewShell;
+class SwSubFont;
+class MapMode;
+
+/*************************************************************************
+ * class SwFntCache
+ *************************************************************************/
+
+class SwFntCache : public SwCache
+{
+public:
+
+ inline SwFntCache() : SwCache(50,50
+#if OSL_DEBUG_LEVEL > 1
+ , ByteString( RTL_CONSTASCII_STRINGPARAM(
+ "Globaler Font-Cache pFntCache" ))
+#endif
+ ) {}
+
+ inline SwFntObj *First( ) { return (SwFntObj *)SwCache::First(); }
+ inline SwFntObj *Next( SwFntObj *pFntObj)
+ { return (SwFntObj *)SwCache::Next( (SwCacheObj *)pFntObj ); }
+ void Flush();
+};
+
+// Font-Cache, globale Variable, in txtinit.Cxx angelegt/zerstoert
+extern SwFntCache *pFntCache;
+extern SwFntObj *pLastFont;
+extern sal_uInt8 *pMagicNo;
+extern Color *pWaveCol;
+
+/*************************************************************************
+ * class SwFntObj
+ *************************************************************************/
+
+class SwFntObj : public SwCacheObj
+{
+ friend class SwFntAccess;
+ friend void _InitCore();
+ friend void _FinitCore();
+
+ Font aFont;
+ Font *pScrFont;
+ Font *pPrtFont;
+ OutputDevice* pPrinter;
+ sal_uInt16 nGuessedLeading;
+ sal_uInt16 nExtLeading;
+ sal_uInt16 nScrAscent;
+ sal_uInt16 nPrtAscent;
+ sal_uInt16 nScrHeight;
+ sal_uInt16 nPrtHeight;
+ sal_uInt16 nPropWidth;
+ sal_uInt16 nZoom;
+ sal_Bool bSymbol : 1;
+ sal_Bool bPaintBlank : 1;
+
+ static long nPixWidth;
+ static MapMode *pPixMap;
+ static OutputDevice *pPixOut;
+
+ // SMARTTAGS
+ void calcLinePos(SwDrawTextInfo& rInf, Point& aStart, Point& aEnd, xub_StrLen nStart,
+ xub_StrLen nWrLen, xub_StrLen nCnt, const sal_Bool bSwitchH2V, const sal_Bool bSwitchL2R,
+ long nHalfSpace, long* pKernArray, const sal_Bool bBidiPor);
+
+public:
+ DECL_FIXEDMEMPOOL_NEWDEL(SwFntObj)
+
+ SwFntObj( const SwSubFont &rFont, const void* pOwner,
+ ViewShell *pSh );
+
+ virtual ~SwFntObj();
+
+ inline Font *GetScrFont() { return pScrFont; }
+ inline Font *GetFont() { return &aFont; }
+ inline const Font *GetFont() const { return &aFont; }
+
+ inline sal_uInt16 GetGuessedLeading() const { return nGuessedLeading; }
+ inline sal_uInt16 GetExtLeading() const { return nExtLeading; }
+
+ sal_uInt16 GetFontAscent( const ViewShell *pSh, const OutputDevice& rOut );
+ sal_uInt16 GetFontHeight( const ViewShell *pSh, const OutputDevice& rOut );
+ sal_uInt16 GetFontLeading( const ViewShell *pSh, const OutputDevice& rOut );
+
+ void GuessLeading( const ViewShell& rSh, const FontMetric& rMet );
+
+ void SetDevFont( const ViewShell *pSh, OutputDevice& rOut );
+ inline OutputDevice* GetPrt() const { return pPrinter; }
+ inline sal_uInt16 GetZoom() const { return nZoom; }
+ inline sal_uInt16 GetPropWidth() const { return nPropWidth; }
+ inline sal_Bool IsSymbol() const { return bSymbol; }
+
+ void DrawText( SwDrawTextInfo &rInf );
+ Size GetTextSize( SwDrawTextInfo &rInf );
+ xub_StrLen GetCrsrOfst( SwDrawTextInfo &rInf );
+
+ void CreateScrFont( const ViewShell& rSh, const OutputDevice& rOut );
+ void CreatePrtFont( const OutputDevice& rOut );
+};
+
+/*************************************************************************
+ * class SwFntAccess
+ *************************************************************************/
+
+
+class SwFntAccess : public SwCacheAccess
+{
+ ViewShell *pShell;
+protected:
+ virtual SwCacheObj *NewObj( );
+
+public:
+ SwFntAccess( const void * &rMagic, sal_uInt16 &rIndex, const void *pOwner,
+ ViewShell *pShell,
+ sal_Bool bCheck = sal_False );
+ inline SwFntObj* Get() { return (SwFntObj*) SwCacheAccess::Get(); };
+};
+
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/inc/frame.hxx b/sw/source/core/inc/frame.hxx
new file mode 100644
index 000000000000..789bc7985b0e
--- /dev/null
+++ b/sw/source/core/inc/frame.hxx
@@ -0,0 +1,1324 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+#ifndef SW_FRAME_HXX
+#define SW_FRAME_HXX
+
+#include <vector>
+#include <drawinglayer/primitive2d/baseprimitive2d.hxx>
+#include <svl/svarray.hxx>
+#include <editeng/borderline.hxx>
+#include "swtypes.hxx" // fuer SwTwips
+#include "swrect.hxx"
+#include "calbck.hxx" // fuer SwClient
+#include <svl/brdcst.hxx>
+#include "IDocumentDrawModelAccess.hxx"
+
+#if OSL_DEBUG_LEVEL > 1
+#include <libxml/encoding.h>
+#include <libxml/xmlwriter.h>
+#endif
+
+class SwLayoutFrm;
+class SwRootFrm;
+class SwPageFrm;
+class SwFlyFrm;
+class SwSectionFrm;
+class SdrObject;
+class SwFtnFrm;
+class SwFtnBossFrm;
+class SwTabFrm;
+class SwRowFrm;
+class SwFlowFrm;
+class SwCntntFrm;
+class SfxPoolItem;
+class SwAttrSet;
+class ViewShell;
+class Color;
+class SwBorderAttrs;
+class SwCache;
+class SvxBrushItem;
+class SwSelectionList;
+struct SwPosition;
+struct SwCrsrMoveState;
+class SwFmt;
+class SwPrintData;
+class SwSortedObjs;
+class SwAnchoredObject;
+
+//Jeder FrmTyp findet sich hier in einem Bit wieder.
+//Die Bits muessen so gesetzt werden, dass mit einer Maskierung festgestellt
+//werden kann was fuer ein FrmTyp eine Instanz ist _und_ von welchen Klassen
+//sie abgeleitet ist.
+//Der Frm hat in der Basisklasse einen Member der von den CToren der
+//einzelnen Frms entsprechend gesetzt werden muss.
+#define FRM_ROOT 0x0001
+#define FRM_PAGE 0x0002
+#define FRM_COLUMN 0x0004
+#define FRM_HEADER 0x0008
+#define FRM_FOOTER 0x0010
+#define FRM_FTNCONT 0x0020
+#define FRM_FTN 0x0040
+#define FRM_BODY 0x0080
+#define FRM_FLY 0x0100
+#define FRM_SECTION 0x0200
+#define FRM_UNUSED 0x0400
+#define FRM_TAB 0x0800
+#define FRM_ROW 0x1000
+#define FRM_CELL 0x2000
+#define FRM_TXT 0x4000
+#define FRM_NOTXT 0x8000
+
+//Fuer den internen Gebrauch ein paar gebraeuchliche Verknuepfungen.
+#define FRM_LAYOUT 0x3FFF
+#define FRM_CNTNT 0xC000
+#define FRM_FTNBOSS 0x0006
+#define FRM_ACCESSIBLE (FRM_HEADER|FRM_FOOTER|FRM_FTN|FRM_TXT|FRM_ROOT|FRM_FLY|FRM_TAB|FRM_CELL|FRM_PAGE)
+
+ //Weils so schon ist das ganze als Bitfeld....
+//0000 0000 0000 0001 ROOT
+//0000 0000 0000 0010 PAGE
+//0000 0000 0000 0100 COLUMN
+//0000 0000 0000 1000 HEADER
+//0000 0000 0001 0000 FOOTER
+//0000 0000 0010 0000 FTNCONT
+//0000 0000 0100 0000 FTN
+//0000 0000 1000 0000 BODY
+//0000 0001 0000 0000 FLY
+//0000 0010 0000 0000 SECTION
+//0000 0100 0000 0000 UNUSED
+//0000 1000 0000 0000 TAB
+//0001 0000 0000 0000 ROW
+//0010 0000 0000 0000 CELL
+//0100 0000 0000 0000 TXT
+//1000 0000 0000 0000 NOTXT
+
+// The type of the frame is internal represented by the 4-bit value nType,
+// which can expanded to the types above by shifting a bit (0x1 << nType)
+// Here are the corresponding defines for the compressed representation:
+
+#define FRMC_ROOT 0
+#define FRMC_PAGE 1
+#define FRMC_COLUMN 2
+#define FRMC_HEADER 3
+#define FRMC_FOOTER 4
+#define FRMC_FTNCONT 5
+#define FRMC_FTN 6
+#define FRMC_BODY 7
+#define FRMC_FLY 8
+#define FRMC_SECTION 9
+#define FRMC_UNUSED 10
+#define FRMC_TAB 11
+#define FRMC_ROW 12
+#define FRMC_CELL 13
+#define FRMC_TXT 14
+#define FRMC_NOTXT 15
+
+#define FRM_NEIGHBOUR 0x2004
+#define FRM_NOTE_VERT 0x7a60
+#define FRM_HEADFOOT 0x0018
+#define FRM_BODYFTNC 0x00a0
+
+class SwFrm;
+typedef long (SwFrm:: *SwFrmGet)() const;
+typedef sal_Bool (SwFrm:: *SwFrmMax)( long );
+typedef void (SwFrm:: *SwFrmMakePos)( const SwFrm*, const SwFrm*, sal_Bool );
+typedef long (*SwOperator)( long, long );
+typedef void (SwFrm:: *SwFrmSet)( long, long );
+
+struct SwRectFnCollection
+{
+ SwRectGet fnGetTop;
+ SwRectGet fnGetBottom;
+ SwRectGet fnGetLeft;
+ SwRectGet fnGetRight;
+ SwRectGet fnGetWidth;
+ SwRectGet fnGetHeight;
+ SwRectPoint fnGetPos;
+ SwRectSize fnGetSize;
+
+ SwRectSet fnSetTop;
+ SwRectSet fnSetBottom;
+ SwRectSet fnSetLeft;
+ SwRectSet fnSetRight;
+ SwRectSet fnSetWidth;
+ SwRectSet fnSetHeight;
+
+ SwRectSet fnSubTop;
+ SwRectSet fnAddBottom;
+ SwRectSet fnSubLeft;
+ SwRectSet fnAddRight;
+ SwRectSet fnAddWidth;
+ SwRectSet fnAddHeight;
+
+ SwRectSet fnSetPosX;
+ SwRectSet fnSetPosY;
+
+ SwFrmGet fnGetTopMargin;
+ SwFrmGet fnGetBottomMargin;
+ SwFrmGet fnGetLeftMargin;
+ SwFrmGet fnGetRightMargin;
+ SwFrmSet fnSetXMargins;
+ SwFrmSet fnSetYMargins;
+ SwFrmGet fnGetPrtTop;
+ SwFrmGet fnGetPrtBottom;
+ SwFrmGet fnGetPrtLeft;
+ SwFrmGet fnGetPrtRight;
+ SwRectDist fnTopDist;
+ SwRectDist fnBottomDist;
+ SwRectDist fnLeftDist;
+ SwRectDist fnRightDist;
+ SwFrmMax fnSetLimit;
+ SwRectMax fnOverStep;
+
+ SwRectSetPos fnSetPos;
+ SwFrmMakePos fnMakePos;
+ SwOperator fnXDiff;
+ SwOperator fnYDiff;
+ SwOperator fnXInc;
+ SwOperator fnYInc;
+
+ SwRectSetTwice fnSetLeftAndWidth;
+ SwRectSetTwice fnSetTopAndHeight;
+};
+
+typedef SwRectFnCollection* SwRectFn;
+/*
+extern SwRectFn fnRectHori, fnRectVert, fnRectB2T, fnRectVL2R;
+#define SWRECTFN( pFrm ) sal_Bool bVert = pFrm->IsVertical(); \
+ sal_Bool bRev = pFrm->IsReverse(); \
+ SwRectFn fnRect = bVert ? \
+ ( bRev ? fnRectVL2R : fnRectVert ): \
+ ( bRev ? fnRectB2T : fnRectHori );
+#define SWRECTFNX( pFrm ) sal_Bool bVertX = pFrm->IsVertical(); \
+ sal_Bool bRevX = pFrm->IsReverse(); \
+ SwRectFn fnRectX = bVertX ? \
+ ( bRevX ? fnRectVL2R : fnRectVert ): \
+ ( bRevX ? fnRectB2T : fnRectHori );
+#define SWREFRESHFN( pFrm ) { if( bVert != pFrm->IsVertical() || \
+ bRev != pFrm->IsReverse() ) \
+ bVert = pFrm->IsVertical(); \
+ bRev = pFrm->IsReverse(); \
+ fnRect = bVert ? \
+ ( bRev ? fnRectVL2R : fnRectVert ): \
+ ( bRev ? fnRectB2T : fnRectHori ); }
+#define SWRECTFN2( pFrm ) sal_Bool bVert = pFrm->IsVertical(); \
+ sal_Bool bNeighb = pFrm->IsNeighbourFrm(); \
+ SwRectFn fnRect = bVert == bNeighb ? \
+ fnRectHori : fnRectVert;
+*/
+
+//Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin
+extern SwRectFn fnRectHori, fnRectVert, fnRectB2T, fnRectVL2R, fnRectVertL2R;
+#define SWRECTFN( pFrm ) sal_Bool bVert = pFrm->IsVertical(); \
+ sal_Bool bRev = pFrm->IsReverse(); \
+ sal_Bool bVertL2R = pFrm->IsVertLR(); \
+ SwRectFn fnRect = bVert ? \
+ ( bRev ? fnRectVL2R : ( bVertL2R ? fnRectVertL2R : fnRectVert ) ): \
+ ( bRev ? fnRectB2T : fnRectHori );
+#define SWRECTFNX( pFrm ) sal_Bool bVertX = pFrm->IsVertical(); \
+ sal_Bool bRevX = pFrm->IsReverse(); \
+ sal_Bool bVertL2RX = pFrm->IsVertLR(); \
+ SwRectFn fnRectX = bVertX ? \
+ ( bRevX ? fnRectVL2R : ( bVertL2RX ? fnRectVertL2R : fnRectVert ) ): \
+ ( bRevX ? fnRectB2T : fnRectHori );
+#define SWREFRESHFN( pFrm ) { if( bVert != pFrm->IsVertical() || \
+ bRev != pFrm->IsReverse() ) \
+ bVert = pFrm->IsVertical(); \
+ bRev = pFrm->IsReverse(); \
+ bVertL2R = pFrm->IsVertLR(); \
+ fnRect = bVert ? \
+ ( bRev ? fnRectVL2R : ( bVertL2R ? fnRectVertL2R : fnRectVert ) ): \
+ ( bRev ? fnRectB2T : fnRectHori ); }
+#define SWRECTFN2( pFrm ) sal_Bool bVert = pFrm->IsVertical(); \
+ sal_Bool bVertL2R = pFrm->IsVertLR(); \
+ sal_Bool bNeighb = pFrm->IsNeighbourFrm(); \
+ SwRectFn fnRect = bVert == bNeighb ? \
+ fnRectHori : ( bVertL2R ? fnRectVertL2R : fnRectVert );
+//End of SCMS
+#define POS_DIFF( aFrm1, aFrm2 ) \
+ ( (aFrm1.*fnRect->fnGetTop)() != (aFrm2.*fnRect->fnGetTop)() || \
+ (aFrm1.*fnRect->fnGetLeft)() != (aFrm2.*fnRect->fnGetLeft)() )
+
+//Fuer GetNextLeaf/GetPrevLeaf.
+enum MakePageType
+{
+ MAKEPAGE_NONE, //Keine Seite bzw. Fussnote anlegen
+ MAKEPAGE_APPEND, //Nur ggf. Seite anhaengen
+ MAKEPAGE_INSERT, //Seite ggf. anhaengen oder einfuegen.
+ MAKEPAGE_FTN, //Fussnote ggf. einfuegen.
+ MAKEPAGE_NOSECTION // Don't create section frames
+};
+
+// OD 2004-05-06 #i28701# - replaced by new class <SwSortedObjs>
+//typedef SdrObject* SdrObjectPtr;
+//SV_DECL_PTRARR(SwDrawObjs,SdrObjectPtr,1,1);
+
+class SwFrm: public SwClient, public SfxBroadcaster
+{
+ //Der verkappte Frm
+ friend class SwFlowFrm;
+ friend class SwLayoutFrm; // Sw3FrameIo: fuer pNext, pPrev
+ friend class SwLooping; // LoopControlling (layouter.cxx)
+
+ //Hebt die Lower waehrend eines Spaltenumbaus auf.
+ friend SwFrm *SaveCntnt( SwLayoutFrm *, SwFrm* pStart = NULL );
+ friend void RestoreCntnt( SwFrm *, SwLayoutFrm *, SwFrm *pSibling, bool bGrow );
+
+#if OSL_DEBUG_LEVEL > 1
+ //entfernt leere SwSectionFrms aus einer Kette
+ friend SwFrm* SwClearDummies( SwFrm* pFrm );
+#endif
+
+ //Zum validieren eines unsinnig invalidierten in SwCntntFrm::MakeAll
+ friend void ValidateSz( SwFrm *pFrm );
+ // Implementiert in text/txtftn.cxx, verhindert Ftn-Oszillation
+ friend void ValidateTxt( SwFrm *pFrm );
+
+// friend void CalcAnchorAndKeep( SwFlyFrm * );
+
+ friend void MakeNxt( SwFrm *pFrm, SwFrm *pNxt );
+
+ //Cache fuer (Umrandungs-)Attribute.
+ static SwCache *pCache;
+
+ // --> OD 2006-05-10 #i65250#
+ // frame ID is now in general available - used for layout loop control
+ static sal_uInt32 mnLastFrmId;
+ const sal_uInt32 mnFrmId;
+ // <--
+
+ SwRootFrm *mpRoot;
+ SwLayoutFrm *pUpper;
+ SwFrm *pNext;
+ SwFrm *pPrev;
+
+ SwFrm *_FindNext();
+ SwFrm *_FindPrev();
+
+ /** method to determine next content frame in the same environment
+ for a flow frame (content frame, table frame, section frame)
+
+ OD 2005-11-30 #i27138# - adding documentation:
+ Travelling downwards through the layout to determine the next content
+ frame in the same environment. There are several environments in a
+ document, which form a closed context regarding this function. These
+ environments are:
+ - Each page header
+ - Each page footer
+ - Each unlinked fly frame
+ - Each group of linked fly frames
+ - All footnotes
+ - All document body frames
+ OD 2005-11-30 #i27138# - adding parameter <_bInSameFtn>
+ Its default value is <false>. If its value is <true>, the environment
+ 'All footnotes' is no longer treated. Instead each footnote is treated
+ as an own environment.
+
+ @author OD
+
+ @param _bInSameFtn
+ input parameter - boolean indicating, that the found next content
+ frame has to be in the same footnote frame. This parameter is only
+ relevant for flow frames in footnotes.
+
+ @return SwCntntFrm*
+ pointer to the found next content frame. It's NULL, if none exists.
+ */
+ SwCntntFrm* _FindNextCnt( const bool _bInSameFtn = false );
+
+ /** method to determine previous content frame in the same environment
+ for a flow frame (content frame, table frame, section frame)
+
+ OD 2005-11-30 #i27138#
+ Travelling upwards through the layout to determine the previous content
+ frame in the same environment. There are several environments in a
+ document, which form a closed context regarding this function. These
+ environments are:
+ - Each page header
+ - Each page footer
+ - Each unlinked fly frame
+ - Each group of linked fly frames
+ - All footnotes
+ - All document body frames
+ OD 2005-11-30 #i27138# - adding parameter <_bInSameFtn>
+ Its default value is <false>. If its value is <true>, the environment
+ 'All footnotes' is no longer treated. Instead each footnote is treated
+ as an own environment.
+
+ @author OD
+
+ @param _bInSameFtn
+ input parameter - boolean indicating, that the found previous content
+ frame has to be in the same footnote frame. This parameter is only
+ relevant for flow frames in footnotes.
+
+ @return SwCntntFrm*
+ pointer to the found previous content frame. It's NULL, if none exists.
+ */
+ SwCntntFrm* _FindPrevCnt( const bool _bInSameFtn = false );
+
+
+ void _UpdateAttrFrm( const SfxPoolItem*, const SfxPoolItem*, sal_uInt8 & );
+ SwFrm* _GetIndNext();
+ void SetDirFlags( sal_Bool bVert );
+
+ SwFrm( SwFrm & ); //Kopieren ist nicht erlaubt.
+
+ const SwLayoutFrm* ImplGetNextLayoutLeaf( bool bFwd ) const;
+
+protected:
+ SwSortedObjs* pDrawObjs; //Hier haengen die DrawObjs, kann 0 sein
+
+ SwRect aFrm; //Absolute Dokumentposition und groesse des Frm
+ SwRect aPrt; //Position der PrtArea rel zum Frm und groesse der PrtArea
+
+ sal_uInt16 bFlag01: 1;
+ sal_uInt16 bFlag02: 1;
+ sal_uInt16 bFlag03: 1;
+ sal_uInt16 bFlag04: 1;
+ sal_uInt16 bFlag05: 1;
+ sal_uInt16 bReverse: 1; // Next line above/at the right side instead
+ // under/at the left side of the previous line.
+ sal_uInt16 bInvalidR2L: 1;
+ sal_uInt16 bDerivedR2L: 1;
+ sal_uInt16 bRightToLeft: 1;
+ sal_uInt16 bInvalidVert: 1;
+ sal_uInt16 bDerivedVert: 1;
+ sal_uInt16 bVertical: 1;
+ //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin
+ sal_uInt16 bVertLR: 1;
+ //End of SCMS
+ sal_uInt16 nType: 4; //Who am I?
+
+ sal_Bool bValidPos: 1;
+ sal_Bool bValidPrtArea: 1;
+ sal_Bool bValidSize: 1;
+ sal_Bool bValidLineNum: 1;
+ sal_Bool bFixSize: 1;
+ sal_Bool bUnUsed1: 1;
+ sal_Bool bCompletePaint: 1; //Frame wird ganz gepaintet wenn sal_True, auch
+ //wenn der Inhalt nur teilw. veraendert ist;
+ //Bei CntntFrms wird ausschliesslich wenn sal_True
+ //der Border (von Action) gemalt.
+ sal_Bool bRetouche: 1; //Der Frame ist fuer Retusche verantwortlich
+ //wenn sal_True.
+public:
+ sal_Bool bUnUsed2: 1;
+protected:
+ sal_Bool bInfInvalid: 1; //InfoFlags sind Invalid.
+ sal_Bool bInfBody: 1; //Frm steht im DokumentBody.
+ sal_Bool bInfTab: 1; //Frm steht in einer Tabelle.
+ sal_Bool bInfFly: 1; //Frm steht in einem Fly.
+ sal_Bool bInfFtn: 1; //Frm steht in einer Fussnote.
+ sal_Bool bInfSct: 1; //Frm steht in einem Bereich.
+ sal_Bool bColLocked: 1; //Grow/Shrink sperren bei spaltigen Section-
+ //oder Fly-Frames, wird im Format gesetzt
+
+ void ColLock() { bColLocked = sal_True; }
+ void ColUnlock() { bColLocked = sal_False; }
+
+ // Only used by SwRootFrm Ctor to get 'this' into mpRoot...
+ void setRootFrm( SwRootFrm* pRoot ) { mpRoot = pRoot; }
+
+ SwPageFrm *InsertPage( SwPageFrm *pSibling, sal_Bool bFtn );
+ void PrepareMake();
+ void OptPrepareMake();
+ void MakePos();
+ // --> OD 2005-09-28 #b6329202#
+ // method formats next frame of table frame to assure keep attribute.
+ // in case of nested tables method <SwFrm::MakeAll()> is called to
+ // avoid format of superior table frame.
+ friend SwFrm* lcl_FormatNextCntntForKeep( SwTabFrm* pTabFrm );
+ // <--
+ virtual void MakeAll() = 0;
+ //Adjustierung der Frames einer Seite
+ SwTwips AdjustNeighbourhood( SwTwips nDiff, sal_Bool bTst = sal_False );
+
+ //Aendern nur die Framesize, nicht die PrtArea-SSize
+ virtual SwTwips ShrinkFrm( SwTwips, sal_Bool bTst = sal_False, sal_Bool bInfo = sal_False ) = 0;
+ virtual SwTwips GrowFrm ( SwTwips, sal_Bool bTst = sal_False, sal_Bool bInfo = sal_False ) = 0;
+
+ SwModify *GetDep() { return GetRegisteredInNonConst(); }
+ const SwModify *GetDep() const { return GetRegisteredIn(); }
+
+ SwFrm( SwModify*, SwFrm* );
+
+ void CheckDir( sal_uInt16 nDir, sal_Bool bVert, sal_Bool bOnlyBiDi, sal_Bool bBrowse );
+
+ /** enumeration for the different invalidations
+
+ OD 2004-05-19 #i28701#
+
+ @author OD
+ */
+ enum InvalidationType
+ {
+ INVALID_SIZE, INVALID_PRTAREA, INVALID_POS, INVALID_LINENUM, INVALID_ALL
+ };
+
+ /** method to determine, if an invalidation is allowed.
+
+ OD 2004-05-19 #i28701
+
+ @author OD
+ */
+ virtual bool _InvalidationAllowed( const InvalidationType _nInvalid ) const;
+
+ /** method to perform additional actions on an invalidation
+
+ OD 2004-05-19 #i28701#
+ Method has *only* to contain actions, which has to be performed on
+ *every* assignment of the corresponding flag to <sal_False>.
+
+ @author OD
+ */
+ virtual void _ActionOnInvalidation( const InvalidationType _nInvalid );
+
+ //Schatten und Umrandung painten
+ void PaintShadow( const SwRect&, SwRect&, const SwBorderAttrs& ) const;
+ virtual void Modify( const SfxPoolItem*, const SfxPoolItem* );
+
+ virtual const IDocumentDrawModelAccess* getIDocumentDrawModelAccess( );
+
+public:
+ TYPEINFO(); //Bereits in Basisklasse Client drin.
+
+ sal_uInt16 GetType() const { return 0x1 << nType; }
+
+ static SwCache &GetCache() { return *pCache; }
+ static SwCache *GetCachePtr() { return pCache; }
+ static void SetCache( SwCache *pNew ) { pCache = pNew; }
+
+ //Aendern die PrtArea-SSize und die FrmSize.
+ SwTwips Shrink( SwTwips, sal_Bool bTst = sal_False, sal_Bool bInfo = sal_False );
+ SwTwips Grow ( SwTwips, sal_Bool bTst = sal_False, sal_Bool bInfo = sal_False );
+
+ //Wir brauchen unterschiedliche Methoden (wg. Performance) fuer das
+ //Einfuegenin den Layout Baum:
+
+ //Einfuegen vor pBehind oder am Ende der Kette unter pUpper
+ void InsertBefore( SwLayoutFrm* pParent, SwFrm* pBehind );
+ //Einfuegen hinter pBefore oder am Anfang der Kette unter pUpper
+ void InsertBehind( SwLayoutFrm *pParent, SwFrm *pBefore );
+ //Einfuegen vor pBehind oder am Ende der Kette, unter Beruecksichtigung
+ //der Geschwister von pSct
+ void InsertGroupBefore( SwFrm* pParent, SwFrm* pWhere, SwFrm* pSct );
+ void Remove();
+
+ //For internal use only; wer es anders macht wird
+ //in einen Sack gesteckt und muss zwei Tage drin hocken bleiben.
+ //Fuert Spezialbehandlung fuer _Get[Next|Prev]Leaf() durch (Tabellen).
+ SwLayoutFrm *GetLeaf( MakePageType eMakePage, sal_Bool bFwd );
+ SwLayoutFrm *GetNextLeaf ( MakePageType eMakePage );
+ SwLayoutFrm *GetNextFtnLeaf( MakePageType eMakePage );
+ SwLayoutFrm *GetNextSctLeaf( MakePageType eMakePage );
+ SwLayoutFrm *GetNextCellLeaf( MakePageType eMakePage );
+ SwLayoutFrm *GetPrevLeaf ( MakePageType eMakeFtn = MAKEPAGE_FTN );
+ SwLayoutFrm *GetPrevFtnLeaf( MakePageType eMakeFtn = MAKEPAGE_FTN );
+ SwLayoutFrm *GetPrevSctLeaf( MakePageType eMakeFtn = MAKEPAGE_FTN );
+ SwLayoutFrm *GetPrevCellLeaf( MakePageType eMakeFtn = MAKEPAGE_FTN );
+ const SwLayoutFrm *GetLeaf ( MakePageType eMakePage, sal_Bool bFwd,
+ const SwFrm *pAnch ) const;
+
+ sal_Bool WrongPageDesc( SwPageFrm* pNew );
+
+ // --> OD 2004-07-02 #i28701# - new methods to append/remove drawing objects
+ void AppendDrawObj( SwAnchoredObject& _rNewObj );
+ void RemoveDrawObj( SwAnchoredObject& _rToRemoveObj );
+ // <--
+
+ //Arbeiten mit der Kette der FlyFrms
+ void AppendFly( SwFlyFrm *pNew );
+ void RemoveFly( SwFlyFrm *pToRemove );
+ const SwSortedObjs *GetDrawObjs() const { return pDrawObjs; }
+ SwSortedObjs *GetDrawObjs() { return pDrawObjs; }
+ // --> OD 2004-07-01 #i28701# - change purpose of method and adjust its name
+ void InvalidateObjs( const bool _bInvaPosOnly,
+ const bool _bNoInvaOfAsCharAnchoredObjs = true );
+
+ virtual void PaintBorder( const SwRect&, const SwPageFrm *pPage,
+ const SwBorderAttrs & ) const;
+ void PaintBaBo( const SwRect&, const SwPageFrm *pPage = 0,
+ const sal_Bool bLowerBorder = sal_False ) const;
+ void PaintBackground( const SwRect&, const SwPageFrm *pPage,
+ const SwBorderAttrs &,
+ const sal_Bool bLowerMode = sal_False,
+ const sal_Bool bLowerBorder = sal_False ) const;
+ void PaintBorderLine( const SwRect&, const SwRect&, const SwPageFrm*,
+ const Color *pColor, const editeng::SvxBorderStyle = editeng::SOLID ) const;
+
+ void ProcessPrimitives( const drawinglayer::primitive2d::Primitive2DSequence& rSequence ) const;
+
+ //Retouche, nicht im Bereich des uebergebenen Rect!
+ void Retouche( const SwPageFrm *pPage, const SwRect &rRect ) const;
+
+ sal_Bool GetBackgroundBrush( const SvxBrushItem*& rpBrush,
+ const Color*& rpColor,
+ SwRect &rOrigRect,
+ sal_Bool bLowerMode ) const;
+
+ inline void SetCompletePaint() const;
+ inline void ResetCompletePaint() const;
+ inline sal_Bool IsCompletePaint() const { return bCompletePaint; }
+
+ inline void SetRetouche() const;
+ inline void ResetRetouche() const;
+ inline sal_Bool IsRetouche() const { return bRetouche; }
+
+ void SetInfFlags(); //Setzen der InfoFlags
+ inline void InvalidateInfFlags() { bInfInvalid = sal_True; }
+ inline sal_Bool IsInDocBody() const; //Benutzen die InfoFlags.
+ inline sal_Bool IsInFtn() const; //ggf. werden die Flags ermittelt.
+ inline sal_Bool IsInTab() const;
+ inline sal_Bool IsInFly() const;
+ inline sal_Bool IsInSct() const;
+
+ // If frame is inside a split table row, this function returns
+ // the corresponding row frame in the follow table.
+ const SwRowFrm* IsInSplitTableRow() const;
+
+ // If frame is inside a follow flow row, this function returns
+ // the corresponding row frame master table
+ const SwRowFrm* IsInFollowFlowRow() const;
+
+ bool IsInBalancedSection() const;
+
+ inline sal_Bool IsReverse() const { return bReverse; }
+ inline void SetReverse( sal_Bool bNew ){ bReverse = bNew ? 1 : 0; }
+ inline sal_Bool IsVertical() const;
+ //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin
+ inline sal_Bool IsVertLR() const;
+ //End of SCMS
+ inline sal_Bool GetVerticalFlag() const;
+ inline void SetVertical( sal_Bool bNew ){ bVertical = bNew ? 1 : 0; }
+ //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin
+ inline void SetbVertLR( sal_Bool bNew ) { bVertLR = bNew ? 1 : 0; }
+ //End of SCMS
+ inline void SetDerivedVert( sal_Bool bNew ){ bDerivedVert = bNew ? 1 : 0; }
+ inline void SetInvalidVert( sal_Bool bNew) { bInvalidVert = bNew ? 1 : 0; }
+ inline sal_Bool IsRightToLeft() const;
+ inline sal_Bool GetRightToLeftFlag() const;
+ inline void SetRightToLeft( sal_Bool bNew ){ bRightToLeft = bNew ? 1 : 0; }
+ inline void SetDerivedR2L( sal_Bool bNew ) { bDerivedR2L = bNew ? 1 : 0; }
+ inline void SetInvalidR2L( sal_Bool bNew ) { bInvalidR2L = bNew ? 1 : 0; }
+
+ void CheckDirChange();
+ // returns upper left frame position for LTR and
+ // upper right frame position for Asian / RTL frames
+ Point GetFrmAnchorPos( sal_Bool bIgnoreFlysAnchoredAtThisFrame ) const;
+
+ /** determine, if frame is moveable in given environment
+
+ OD 08.08.2003 #110978#
+ method replaced 'old' method <sal_Bool IsMoveable() const>.
+ Determines, if frame is moveable in given environment. if no environment
+ is given (parameter _pLayoutFrm == 0L), the movability in the actual
+ environment (<this->GetUpper()) is checked.
+
+ @author OD
+
+ @param _pLayoutFrm
+ input parameter - given environment (layout frame), in which the movability
+ will be checked. If not set ( == 0L ), actual environment is taken.
+
+ @return boolean, indicating, if frame is moveable in given environment
+ */
+// sal_Bool IsMoveable() const;
+ bool IsMoveable( const SwLayoutFrm* _pLayoutFrm = 0L ) const;
+
+ //Ist es fuer den (Txt)Frm in der aktuellen Umgebung erlaubt eine
+ //Fussnote einzufuegen (nicht z.B. in wiederholten TabellenHeadlines).
+ sal_Bool IsFtnAllowed() const;
+
+ virtual void Format( const SwBorderAttrs *pAttrs = 0 );
+
+ virtual void CheckDirection( sal_Bool bVert );
+
+ void ReinitializeFrmSizeAttrFlags();
+
+ const SwAttrSet *GetAttrSet() const;
+
+ inline sal_Bool HasFixSize() const { return bFixSize; }
+ inline void SetFixSize( sal_Bool bNew ) { bFixSize = bNew; }
+
+ //Prueft alle Seiten ab der Uebergebenen und korrigiert ggf.
+ static void CheckPageDescs( SwPageFrm *pStart, sal_Bool bNotifyFields = sal_True );
+
+ //Koennen 0 liefern, einmal const einmal nicht
+ SwFrm *GetNext() { return pNext; }
+ SwFrm *GetPrev() { return pPrev; }
+ SwLayoutFrm *GetUpper() { return pUpper; }
+ SwRootFrm *getRootFrm(){ return mpRoot; }
+ SwPageFrm *FindPageFrm();
+ SwFrm *FindColFrm();
+ SwRowFrm *FindRowFrm();
+ SwFtnBossFrm *FindFtnBossFrm( sal_Bool bFootnotes = sal_False );
+ SwTabFrm *ImplFindTabFrm();
+ SwFtnFrm *ImplFindFtnFrm();
+ SwFlyFrm *ImplFindFlyFrm();
+ SwSectionFrm *ImplFindSctFrm();
+ SwFrm *FindFooterOrHeader();
+ SwFrm *GetLower();
+ const SwFrm *GetNext() const { return pNext; }
+ const SwFrm *GetPrev() const { return pPrev; }
+ const SwLayoutFrm *GetUpper() const { return pUpper; }
+ const SwRootFrm *getRootFrm() const { return mpRoot; }
+ inline SwTabFrm *FindTabFrm();
+ inline SwFtnFrm *FindFtnFrm();
+ inline SwFlyFrm *FindFlyFrm();
+ inline SwSectionFrm *FindSctFrm();
+ inline SwFrm *FindNext();
+ // --> OD 2005-12-01 #i27138# - add parameter <_bInSameFtn>
+ inline SwCntntFrm* FindNextCnt( const bool _bInSameFtn = false );
+ // <--
+ inline SwFrm *FindPrev();
+ inline const SwPageFrm *FindPageFrm() const;
+ inline const SwFtnBossFrm *FindFtnBossFrm( sal_Bool bFtn = sal_False ) const;
+ inline const SwFrm *FindColFrm() const;
+ inline const SwFrm *FindFooterOrHeader() const;
+ inline const SwTabFrm *FindTabFrm() const;
+ inline const SwFtnFrm *FindFtnFrm() const;
+ inline const SwFlyFrm *FindFlyFrm() const;
+ inline const SwSectionFrm *FindSctFrm() const;
+ inline const SwFrm *FindNext() const;
+ // --> OD 2005-12-01 #i27138# - add parameter <_bInSameFtn>
+ inline const SwCntntFrm* FindNextCnt( const bool _bInSameFtn = false ) const;
+ // <--
+ inline const SwFrm *FindPrev() const;
+ const SwFrm *GetLower() const;
+
+ /** inline wrapper method for <_FindPrevCnt(..)>
+
+ OD 2005-11-30 #i27138#
+
+ @author OD
+ */
+ inline SwCntntFrm* FindPrevCnt( const bool _bInSameFtn = false )
+ {
+ if ( GetPrev() && GetPrev()->IsCntntFrm() )
+ return (SwCntntFrm*)(GetPrev());
+ else
+ return _FindPrevCnt( _bInSameFtn );
+ }
+
+ /** inline const wrapper method for <_FindPrevCnt(..)>
+
+ OD 2005-11-30 #i27138#
+
+ @author OD
+ */
+ inline const SwCntntFrm* FindPrevCnt( const bool _bInSameFtn = false ) const
+ {
+ if ( GetPrev() && GetPrev()->IsCntntFrm() )
+ return (const SwCntntFrm*)(GetPrev());
+ else
+ return const_cast<SwFrm*>(this)->_FindPrevCnt( _bInSameFtn );
+ }
+
+ // --> OD 2007-09-04 #i79774#, #b6596954#
+ SwFrm* _GetIndPrev() const;
+ SwFrm* GetIndPrev() const
+ { return ( pPrev || !IsInSct() ) ? pPrev : _GetIndPrev(); }
+// const SwFrm* GetIndPrev() const { return ((SwFrm*)this)->GetIndPrev(); }
+ // <--
+ SwFrm* GetIndNext()
+ { return ( pNext || !IsInSct() ) ? pNext : _GetIndNext(); }
+ const SwFrm* GetIndNext() const { return ((SwFrm*)this)->GetIndNext(); }
+
+ sal_uInt16 GetPhyPageNum() const; //Seitennummer ohne Offset
+ sal_uInt16 GetVirtPageNum() const; //Seitenummer mit Offset
+ sal_Bool OnRightPage() const { return 0 != GetPhyPageNum() % 2; };
+ sal_Bool WannaRightPage() const;
+
+ inline const SwLayoutFrm *GetPrevLayoutLeaf() const;
+ inline const SwLayoutFrm *GetNextLayoutLeaf() const;
+ inline SwLayoutFrm *GetPrevLayoutLeaf();
+ inline SwLayoutFrm *GetNextLayoutLeaf();
+
+ inline void Calc() const; //Hier wird ggf. 'Formatiert'
+ inline void OptCalc() const; //Hier wird zur Optimierung davon ausgegangen,
+ //das die Vorgaenger bereits formatiert sind.
+
+ inline Point GetRelPos() const;
+ const SwRect &Frm() const { return aFrm; }
+ const SwRect &Prt() const { return aPrt; }
+
+ // The PaintArea is the area, where content may be displayed.
+ // The margin of the page or the space between columns belongs to her.
+ const SwRect PaintArea() const;
+ // The UnionFrm is the union of frm- and prt-area, normally identical
+ // to the frm-area except the case of negative prt-margins.
+ const SwRect UnionFrm( sal_Bool bBorder = sal_False ) const;
+
+ //Der Zugriff auf die Member wird hier ausnahmsweiste gestattet,
+ //dies soll aber nicht dazu dienen die Werte wahllos zu veraendern;
+ //es ist nur die einzige Moeglichkeit die Compilerprobleme zu umgehen
+ //(gleiche Methode mal public mal protected).
+ SwRect &Frm() { return aFrm; }
+ SwRect &Prt() { return aPrt; }
+
+ virtual Size ChgSize( const Size& aNewSize );
+
+ virtual void Cut() = 0;
+ virtual void Paste( SwFrm* pParent, SwFrm* pSibling = 0 ) = 0;
+
+ void ValidateLineNum() { bValidLineNum = sal_True; }
+
+ sal_Bool GetValidPosFlag() const { return bValidPos; }
+ sal_Bool GetValidPrtAreaFlag()const { return bValidPrtArea; }
+ sal_Bool GetValidSizeFlag() const { return bValidSize; }
+ sal_Bool GetValidLineNumFlag()const { return bValidLineNum; }
+ sal_Bool IsValid() const { return bValidPos && bValidSize && bValidPrtArea; }
+
+ //Invalideren nur den Frm
+ // OD 2004-05-19 #i28701# - add call to method <_ActionOnInvalidation(..)>
+ // for all invalidation methods.
+ // OD 2004-05-19 #i28701# - use method <_InvalidationAllowed(..)> to
+ // decide, if invalidation will to be performed or not.
+ // --> OD 2004-10-08 #i26945# - no additional invalidation, if it's already
+ // invalidate.
+ void _InvalidateSize()
+ {
+ if ( bValidSize && _InvalidationAllowed( INVALID_SIZE ) )
+ {
+ bValidSize = sal_False;
+ _ActionOnInvalidation( INVALID_SIZE );
+ }
+ }
+ void _InvalidatePrt()
+ {
+ if ( bValidPrtArea && _InvalidationAllowed( INVALID_PRTAREA ) )
+ {
+ bValidPrtArea = sal_False;
+ _ActionOnInvalidation( INVALID_PRTAREA );
+ }
+ }
+ void _InvalidatePos()
+ {
+ if ( bValidPos && _InvalidationAllowed( INVALID_POS ) )
+ {
+ bValidPos = sal_False;
+ _ActionOnInvalidation( INVALID_POS );
+ }
+ }
+ void _InvalidateLineNum()
+ {
+ if ( bValidLineNum && _InvalidationAllowed( INVALID_LINENUM ) )
+ {
+ bValidLineNum = sal_False;
+ _ActionOnInvalidation( INVALID_LINENUM );
+ }
+ }
+ void _InvalidateAll()
+ {
+ if ( ( bValidSize || bValidPrtArea || bValidPos ) &&
+ _InvalidationAllowed( INVALID_ALL ) )
+ {
+ bValidSize = bValidPrtArea = bValidPos = sal_False;
+ _ActionOnInvalidation( INVALID_ALL );
+ }
+ }
+ // <--
+ //Benachrichtigen gleich die Seite mit.
+ inline void InvalidateSize();
+ inline void InvalidatePrt();
+ inline void InvalidatePos();
+ inline void InvalidateLineNum();
+ inline void InvalidateAll();
+ void ImplInvalidateSize();
+ void ImplInvalidatePrt();
+ void ImplInvalidatePos();
+ void ImplInvalidateLineNum();
+
+ inline void InvalidateNextPos( sal_Bool bNoFtn = sal_False );
+ void ImplInvalidateNextPos( sal_Bool bNoFtn = sal_False );
+
+ /** method to invalidate printing area of next frame
+
+ OD 09.01.2004 #i11859#
+
+ @author OD
+ */
+ void InvalidateNextPrtArea();
+
+ void InvalidatePage( const SwPageFrm *pPage = 0 ) const;
+
+ virtual bool FillSelection( SwSelectionList& rList, const SwRect& rRect ) const;
+
+ virtual sal_Bool GetCrsrOfst( SwPosition *, Point&,
+ SwCrsrMoveState* = 0 ) const;
+ virtual sal_Bool GetCharRect( SwRect &, const SwPosition&,
+ SwCrsrMoveState* = 0 ) const;
+ virtual void Paint( SwRect const&,
+ SwPrintData const*const pPrintData = NULL ) const;
+
+ // der "kurze Dienstweg" zwischen den Frames und der Formatierung.
+ // Wer den void* falsch Casted ist selbst schuld!
+ // Auf jedenfall muss der void* auf 0 geprueft werden.
+ virtual void Prepare( const PrepareHint ePrep = PREP_CLEAR,
+ const void *pVoid = 0, sal_Bool bNotify = sal_True );
+
+ //sal_True wenn's die richtige Klasse ist, sal_False sonst
+ inline sal_Bool IsLayoutFrm() const;
+ inline sal_Bool IsRootFrm() const;
+ inline sal_Bool IsPageFrm() const;
+ inline sal_Bool IsColumnFrm() const;
+ inline sal_Bool IsFtnBossFrm() const; // Fussnotenbosse sind PageFrms und ColumnFrms
+ inline sal_Bool IsHeaderFrm() const;
+ inline sal_Bool IsFooterFrm() const;
+ inline sal_Bool IsFtnContFrm() const;
+ inline sal_Bool IsFtnFrm() const;
+ inline sal_Bool IsBodyFrm() const;
+ inline sal_Bool IsColBodyFrm() const; // in layfrm.hxx implementiert, BodyFrm unterhalb ColumnFrm
+ inline sal_Bool IsPageBodyFrm() const; // in layfrm.hxx implementiert, BodyFrm unterhalb PageFrm
+ inline sal_Bool IsFlyFrm() const;
+ inline sal_Bool IsSctFrm() const;
+ inline sal_Bool IsTabFrm() const;
+ inline sal_Bool IsRowFrm() const;
+ inline sal_Bool IsCellFrm() const;
+ inline sal_Bool IsCntntFrm() const;
+ inline sal_Bool IsTxtFrm() const;
+ inline sal_Bool IsNoTxtFrm() const;
+ inline sal_Bool IsFlowFrm() const; //Frms deren PrtArea von den Nachbarn
+ //abhaengen und die halt im Inhaltsfluss
+ //stehen.
+ inline sal_Bool IsRetoucheFrm() const; //Frms die Retouchefaehig sind bzw. die
+ //u.U. hinter sich Retouchieren muessen.
+ inline sal_Bool IsAccessibleFrm() const;
+
+ void PrepareCrsr(); //Die CrsrShell darf.
+
+ //Ist der Frm (bzw. die Section in der er steht) geschuetzt?
+ //Auch Fly in Fly in ... und Fussnoten
+ sal_Bool IsProtected() const;
+
+ sal_Bool IsColLocked() const { return bColLocked; }
+
+ virtual ~SwFrm();
+
+ // No inline cause we need the function pointers
+ long GetTopMargin() const;
+ long GetBottomMargin() const;
+ long GetLeftMargin() const;
+ long GetRightMargin() const;
+ void SetTopBottomMargins( long, long );
+ void SetBottomTopMargins( long, long );
+ void SetLeftRightMargins( long, long );
+ void SetRightLeftMargins( long, long );
+ void SetLeftAndWidth( long nLeft, long nWidth );
+ void SetTopAndHeight( long nTop, long nHeight );
+ void SetRightAndWidth( long nRight, long nWidth );
+ void SetBottomAndHeight( long nBottom, long nHeight );
+ long GetPrtLeft() const;
+ long GetPrtBottom() const;
+ long GetPrtRight() const;
+ long GetPrtTop() const;
+ sal_Bool SetMinLeft( long );
+ sal_Bool SetMaxBottom( long );
+ sal_Bool SetMaxRight( long );
+ sal_Bool SetMinTop( long );
+ void MakeBelowPos( const SwFrm*, const SwFrm*, sal_Bool );
+ void MakeUpperPos( const SwFrm*, const SwFrm*, sal_Bool );
+ void MakeLeftPos( const SwFrm*, const SwFrm*, sal_Bool );
+ void MakeRightPos( const SwFrm*, const SwFrm*, sal_Bool );
+ inline sal_Bool IsNeighbourFrm() const
+ { return GetType() & FRM_NEIGHBOUR ? sal_True : sal_False; }
+
+ // --> OD 2006-05-10 #i65250#
+ inline sal_uInt32 GetFrmId() const { return mnFrmId; }
+ inline sal_uInt32 GetLastFrmId() const { return mnLastFrmId; }
+ // <--
+
+ // NEW TABELS
+ // Some functions for covered/covering table cells. This way unnessessary
+ // includes can be avoided
+ bool IsLeaveUpperAllowed() const;
+ bool IsCoveredCell() const;
+ bool IsInCoveredCell() const;
+
+ // FME 2007-08-30 #i81146# new loop control
+ bool KnowsFormat( const SwFmt& rFmt ) const;
+ void RegisterToFormat( SwFmt& rFmt );
+ void ValidateThisAndAllLowers( const sal_uInt16 nStage );
+
+public:
+#if OSL_DEBUG_LEVEL > 1
+ virtual void dumpAsXml(xmlTextWriterPtr writer);
+ virtual void dumpAsXmlAttributes(xmlTextWriterPtr writer);
+ void dumpChildrenAsXml(xmlTextWriterPtr writer);
+#endif
+ bool IsCollapse() const;
+};
+
+inline sal_Bool SwFrm::IsInDocBody() const
+{
+ if ( bInfInvalid )
+ ((SwFrm*)this)->SetInfFlags();
+ return bInfBody;
+}
+inline sal_Bool SwFrm::IsInFtn() const
+{
+ if ( bInfInvalid )
+ ((SwFrm*)this)->SetInfFlags();
+ return bInfFtn;
+}
+inline sal_Bool SwFrm::IsInTab() const
+{
+ if ( bInfInvalid )
+ ((SwFrm*)this)->SetInfFlags();
+ return bInfTab;
+}
+inline sal_Bool SwFrm::IsInFly() const
+{
+ if ( bInfInvalid )
+ ((SwFrm*)this)->SetInfFlags();
+ return bInfFly;
+}
+inline sal_Bool SwFrm::IsInSct() const
+{
+ if ( bInfInvalid )
+ ((SwFrm*)this)->SetInfFlags();
+ return bInfSct;
+}
+sal_Bool SwFrm::IsVertical() const
+{
+ if( bInvalidVert )
+ ((SwFrm*)this)->SetDirFlags( sal_True );
+ return bVertical != 0;
+}
+//Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin
+inline sal_Bool SwFrm::IsVertLR() const
+{
+ return bVertLR != 0;
+}
+//End of SCMS
+sal_Bool SwFrm::GetVerticalFlag() const
+{
+ return bVertical != 0;
+}
+inline sal_Bool SwFrm::IsRightToLeft() const
+{
+ if( bInvalidR2L )
+ ((SwFrm*)this)->SetDirFlags( sal_False );
+ return bRightToLeft != 0;
+}
+sal_Bool SwFrm::GetRightToLeftFlag() const
+{
+ return bRightToLeft != 0;
+}
+
+inline void SwFrm::SetCompletePaint() const
+{
+ ((SwFrm*)this)->bCompletePaint = sal_True;
+}
+inline void SwFrm::ResetCompletePaint() const
+{
+ ((SwFrm*)this)->bCompletePaint = sal_False;
+}
+
+inline void SwFrm::SetRetouche() const
+{
+ ((SwFrm*)this)->bRetouche = sal_True;
+}
+inline void SwFrm::ResetRetouche() const
+{
+ ((SwFrm*)this)->bRetouche = sal_False;
+}
+
+inline SwLayoutFrm *SwFrm::GetNextLayoutLeaf()
+{
+ return (SwLayoutFrm*)((const SwFrm*)this)->GetNextLayoutLeaf();
+}
+
+inline SwLayoutFrm *SwFrm::GetPrevLayoutLeaf()
+{
+ return (SwLayoutFrm*)((const SwFrm*)this)->GetPrevLayoutLeaf();
+}
+
+inline const SwLayoutFrm *SwFrm::GetNextLayoutLeaf() const
+{
+ return ImplGetNextLayoutLeaf( true );
+}
+
+inline const SwLayoutFrm *SwFrm::GetPrevLayoutLeaf() const
+{
+ return ImplGetNextLayoutLeaf( false );
+}
+
+inline void SwFrm::InvalidateSize()
+{
+ if ( bValidSize )
+ ImplInvalidateSize();
+}
+inline void SwFrm::InvalidatePrt()
+{
+ if ( bValidPrtArea )
+ ImplInvalidatePrt();
+}
+inline void SwFrm::InvalidatePos()
+{
+ if ( bValidPos )
+ ImplInvalidatePos();
+}
+inline void SwFrm::InvalidateLineNum()
+{
+ if ( bValidLineNum )
+ ImplInvalidateLineNum();
+}
+
+inline void SwFrm::InvalidateAll()
+{
+ if ( _InvalidationAllowed( INVALID_ALL ) )
+ {
+ if ( bValidPrtArea && bValidSize && bValidPos )
+ ImplInvalidatePos();
+ bValidPrtArea = bValidSize = bValidPos = sal_False;
+
+ // OD 2004-05-19 #i28701#
+ _ActionOnInvalidation( INVALID_ALL );
+ }
+}
+
+inline void SwFrm::InvalidateNextPos( sal_Bool bNoFtn )
+{
+ if ( pNext && !pNext->IsSctFrm() )
+ pNext->InvalidatePos();
+#ifndef C30 // vielleicht geht es ja bei C40 ?
+ else
+ ImplInvalidateNextPos( bNoFtn );
+#else
+ if ( !pNext )
+ ImplInvalidateNextPos( bNoFtn );
+#endif
+}
+
+inline void SwFrm::Calc() const
+{
+ if ( !bValidPos || !bValidPrtArea || !bValidSize )
+ ((SwFrm*)this)->PrepareMake();
+}
+inline void SwFrm::OptCalc() const
+{
+ if ( !bValidPos || !bValidPrtArea || !bValidSize )
+ ((SwFrm*)this)->OptPrepareMake();
+}
+
+inline Point SwFrm::GetRelPos() const
+{
+ Point aRet( aFrm.Pos() );
+ //hier wird gecasted, weil die Klasse SwLayoutFrm nur vorward-
+ //declariert ist.
+ aRet -= ((SwFrm*)GetUpper())->Prt().Pos();
+ aRet -= ((SwFrm*)GetUpper())->Frm().Pos();
+ return aRet;
+}
+
+inline const SwPageFrm *SwFrm::FindPageFrm() const
+{
+ return ((SwFrm*)this)->FindPageFrm();
+}
+inline const SwFrm *SwFrm::FindColFrm() const
+{
+ return ((SwFrm*)this)->FindColFrm();
+}
+inline const SwFrm *SwFrm::FindFooterOrHeader() const
+{
+ return ((SwFrm*)this)->FindFooterOrHeader();
+}
+inline SwTabFrm *SwFrm::FindTabFrm()
+{
+ return IsInTab() ? ImplFindTabFrm() : 0;
+}
+inline const SwFtnBossFrm *SwFrm::FindFtnBossFrm( sal_Bool bFtn ) const
+{
+ return ((SwFrm*)this)->FindFtnBossFrm( bFtn );
+}
+inline SwFtnFrm *SwFrm::FindFtnFrm()
+{
+ return IsInFtn() ? ImplFindFtnFrm() : 0;
+}
+inline SwFlyFrm *SwFrm::FindFlyFrm()
+{
+ return IsInFly() ? ImplFindFlyFrm() : 0;
+}
+inline SwSectionFrm *SwFrm::FindSctFrm()
+{
+ return IsInSct() ? ImplFindSctFrm() : 0;
+}
+
+inline const SwTabFrm *SwFrm::FindTabFrm() const
+{
+ return IsInTab() ? ((SwFrm*)this)->ImplFindTabFrm() : 0;
+}
+inline const SwFtnFrm *SwFrm::FindFtnFrm() const
+{
+ return IsInFtn() ? ((SwFrm*)this)->ImplFindFtnFrm() : 0;
+}
+inline const SwFlyFrm *SwFrm::FindFlyFrm() const
+{
+ return IsInFly() ? ((SwFrm*)this)->ImplFindFlyFrm() : 0;
+}
+inline const SwSectionFrm *SwFrm::FindSctFrm() const
+{
+ return IsInSct() ? ((SwFrm*)this)->ImplFindSctFrm() : 0;
+}
+inline SwFrm *SwFrm::FindNext()
+{
+ if ( pNext )
+ return pNext;
+ else
+ return _FindNext();
+}
+inline const SwFrm *SwFrm::FindNext() const
+{
+ if ( pNext )
+ return pNext;
+ else
+ return ((SwFrm*)this)->_FindNext();
+}
+// --> OD 2005-12-01 #i27138# - add parameter <_bInSameFtn>
+inline SwCntntFrm *SwFrm::FindNextCnt( const bool _bInSameFtn )
+{
+ if ( pNext && pNext->IsCntntFrm() )
+ return (SwCntntFrm*)pNext;
+ else
+ return _FindNextCnt( _bInSameFtn );
+}
+// <--
+// --> OD 2005-12-01 #i27138# - add parameter <_bInSameFtn>
+inline const SwCntntFrm *SwFrm::FindNextCnt( const bool _bInSameFtn ) const
+{
+ if ( pNext && pNext->IsCntntFrm() )
+ return (SwCntntFrm*)pNext;
+ else
+ return ((SwFrm*)this)->_FindNextCnt( _bInSameFtn );
+}
+// <--
+inline SwFrm *SwFrm::FindPrev()
+{
+ if ( pPrev && !pPrev->IsSctFrm() )
+ return pPrev;
+ else
+ return _FindPrev();
+}
+inline const SwFrm *SwFrm::FindPrev() const
+{
+ if ( pPrev && !pPrev->IsSctFrm() )
+ return pPrev;
+ else
+ return ((SwFrm*)this)->_FindPrev();
+}
+
+
+inline sal_Bool SwFrm::IsLayoutFrm() const
+{
+ return GetType() & FRM_LAYOUT ? sal_True : sal_False;
+}
+inline sal_Bool SwFrm::IsRootFrm() const
+{
+ return nType == FRMC_ROOT;
+}
+inline sal_Bool SwFrm::IsPageFrm() const
+{
+ return nType == FRMC_PAGE;
+}
+inline sal_Bool SwFrm::IsColumnFrm() const
+{
+ return nType == FRMC_COLUMN;
+}
+inline sal_Bool SwFrm::IsFtnBossFrm() const
+{
+ return GetType() & FRM_FTNBOSS ? sal_True : sal_False;
+}
+inline sal_Bool SwFrm::IsHeaderFrm() const
+{
+ return nType == FRMC_HEADER;
+}
+inline sal_Bool SwFrm::IsFooterFrm() const
+{
+ return nType == FRMC_FOOTER;
+}
+inline sal_Bool SwFrm::IsFtnContFrm() const
+{
+ return nType == FRMC_FTNCONT;
+}
+inline sal_Bool SwFrm::IsFtnFrm() const
+{
+ return nType == FRMC_FTN;
+}
+inline sal_Bool SwFrm::IsBodyFrm() const
+{
+ return nType == FRMC_BODY;
+}
+inline sal_Bool SwFrm::IsFlyFrm() const
+{
+ return nType == FRMC_FLY;
+}
+inline sal_Bool SwFrm::IsSctFrm() const
+{
+ return nType == FRMC_SECTION;
+}
+inline sal_Bool SwFrm::IsTabFrm() const
+{
+ return nType == FRMC_TAB;
+}
+inline sal_Bool SwFrm::IsRowFrm() const
+{
+ return nType == FRMC_ROW;
+}
+inline sal_Bool SwFrm::IsCellFrm() const
+{
+ return nType == FRMC_CELL;
+}
+inline sal_Bool SwFrm::IsCntntFrm() const
+{
+ return GetType() & FRM_CNTNT ? sal_True : sal_False;
+}
+inline sal_Bool SwFrm::IsTxtFrm() const
+{
+ return nType == FRMC_TXT;
+}
+inline sal_Bool SwFrm::IsNoTxtFrm() const
+{
+ return nType == FRMC_NOTXT;
+}
+inline sal_Bool SwFrm::IsFlowFrm() const
+{
+ return GetType() & 0xCA00 ? sal_True : sal_False; //TabFrm, CntntFrm, SectionFrm
+}
+inline sal_Bool SwFrm::IsRetoucheFrm() const
+{
+ return GetType() & 0xCA40 ? sal_True : sal_False; //TabFrm, CntntFrm, SectionFrm, Ftnfrm
+}
+inline sal_Bool SwFrm::IsAccessibleFrm() const
+{
+ return GetType() & FRM_ACCESSIBLE ? sal_True : sal_False;
+}
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/inc/frminf.hxx b/sw/source/core/inc/frminf.hxx
new file mode 100644
index 000000000000..f05658c8ced7
--- /dev/null
+++ b/sw/source/core/inc/frminf.hxx
@@ -0,0 +1,87 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+#ifndef _FRMINF_HXX
+#define _FRMINF_HXX
+
+#include "swtypes.hxx"
+
+class SwTxtFrm; // SwTxtFrmInfo
+class SwPaM; // SwTxtFrmInfo
+class SwTxtCursor; // SwTxtFrmInfo
+
+
+/*************************************************************************
+ * class SwTxtFrmInfo
+ *************************************************************************/
+
+class SwTxtFrmInfo
+{
+ const SwTxtFrm *pFrm;
+
+ // Wo beginnt der Text (ohne whitespaces)? (Dokument global !!)
+ SwTwips GetLineStart( const SwTxtCursor &rLine ) const;
+
+public:
+ inline SwTxtFrmInfo( const SwTxtFrm *pTxtFrm ) : pFrm(pTxtFrm) { }
+
+ // Passt der Absatz in eine Zeile?
+ sal_Bool IsOneLine() const;
+
+ // Ist die Zeile zu X% gefuellt?
+ sal_Bool IsFilled( const sal_uInt8 nPercent ) const;
+
+ // Wo beginnt der Text (ohne whitespaces)? (rel. im Frame !!)
+ SwTwips GetLineStart() const;
+
+ //returne die mittel Position des n. Charakters
+ SwTwips GetCharPos( xub_StrLen nChar, sal_Bool bCenter = sal_True ) const;
+
+ // Sammelt die whitespaces am Zeilenbeginn und -ende im Pam
+ void GetSpaces( SwPaM &rPam, sal_Bool bWithLineBreak ) const;
+
+ // Ist an der ersten Textposition ein Bullet/Symbol etc?
+ sal_Bool IsBullet( xub_StrLen nTxtPos ) const;
+
+ // Ermittelt Erstzeileneinzug
+ SwTwips GetFirstIndent() const;
+
+ // setze und erfrage den Frame;
+ const SwTxtFrm* GetFrm() const { return pFrm; }
+ SwTxtFrmInfo& SetFrm( const SwTxtFrm* pNew )
+ { pFrm = pNew; return *this; }
+
+ // liegt eine Gegenueberstellung vor? (returnt Pos im Frame)
+ sal_uInt16 GetBigIndent( xub_StrLen& rFndPos,
+ const SwTxtFrm *pNextFrm = 0 ) const;
+};
+
+
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/inc/frmtool.hxx b/sw/source/core/inc/frmtool.hxx
new file mode 100644
index 000000000000..ba1b0f43d539
--- /dev/null
+++ b/sw/source/core/inc/frmtool.hxx
@@ -0,0 +1,579 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+#ifndef _FRMTOOL_HXX
+#define _FRMTOOL_HXX
+#include "swtypes.hxx"
+#include "layfrm.hxx"
+#include "frmatr.hxx"
+#include "swcache.hxx"
+// #i96772#
+#include <editeng/lrspitem.hxx>
+
+class SwPageFrm;
+class SwFlyFrm;
+class SwCntntFrm;
+class SwRootFrm;
+class SwDoc;
+class SwAttrSet;
+class SdrObject;
+class BigInt;
+class SvxBrushItem;
+class SdrMarkList;
+class SwNodeIndex;
+class OutputDevice;
+class SwPageDesc;
+class SwTableBox;
+struct SwFindRowSpanCacheObj;
+
+#if defined(MSC)
+#define MA_FASTCALL __fastcall
+#else
+#define MA_FASTCALL
+#endif
+
+#define WEIT_WECH LONG_MAX - 20000 //Initale Position der Flys.
+#define BROWSE_HEIGHT 56700L * 10L //10 Meter
+
+#define GRFNUM_NO 0
+#define GRFNUM_YES 1
+#define GRFNUM_REPLACE 2
+
+//Painten des Hintergrunds. Mit Brush oder Graphic.
+// - add 6th parameter to indicate that method should
+// consider background transparency, saved in the color of the brush item
+void MA_FASTCALL DrawGraphic( const SvxBrushItem *, OutputDevice *,
+ const SwRect &rOrg, const SwRect &rOut, const sal_uInt8 nGrfNum = GRFNUM_NO,
+ const sal_Bool bConsiderBackgroundTransparency = sal_False );
+
+// - method to align rectangle
+// Created declaration here to avoid <extern> declarations
+void MA_FASTCALL SwAlignRect( SwRect &rRect, const ViewShell *pSh );
+
+// - method to align graphic rectangle
+// Created declaration here to avoid <extern> declarations
+void SwAlignGrfRect( SwRect *pGrfRect, const OutputDevice &rOut );
+
+//Fly besorgen, wenn keine List hineingereicht wird, wir die der aktuellen
+//Shell benutzt.
+//Implementierung in feshview.cxx
+SwFlyFrm *GetFlyFromMarked( const SdrMarkList *pLst, ViewShell *pSh );
+
+//Nicht gleich die math.lib anziehen.
+sal_uLong MA_FASTCALL SqRt( BigInt nX );
+
+SwFrm *SaveCntnt( SwLayoutFrm *pLay, SwFrm *pStart );
+void RestoreCntnt( SwFrm *pSav, SwLayoutFrm *pParent, SwFrm *pSibling, bool bGrow );
+
+//CntntNodes besorgen, CntntFrms erzeugen und in den LayFrm haengen.
+void MA_FASTCALL _InsertCnt( SwLayoutFrm *pLay, SwDoc *pDoc, sal_uLong nIndex,
+ sal_Bool bPages = sal_False, sal_uLong nEndIndex = 0,
+ SwFrm *pPrv = 0 );
+
+//Erzeugen der Frames fuer einen bestimmten Bereich, verwendet _InsertCnt
+void MakeFrms( SwDoc *pDoc, const SwNodeIndex &rSttIdx,
+ const SwNodeIndex &rEndIdx );
+
+//Um z.B. fuer Tabelleheadlines das Erzeugen der Flys in _InsertCnt zu unterbinden.
+extern sal_Bool bDontCreateObjects;
+
+//Fuer FlyCnts, siehe SwFlyAtCntFrm::MakeAll()
+extern sal_Bool bSetCompletePaintOnInvalidate;
+
+//Fuer Tabelleneinstellung per Tastatur.
+long MA_FASTCALL CalcRowRstHeight( SwLayoutFrm *pRow );
+long MA_FASTCALL CalcHeightWidthFlys( const SwFrm *pFrm ); //MA_FLY_HEIGHT
+
+//Neue Seite einsetzen
+SwPageFrm * MA_FASTCALL InsertNewPage( SwPageDesc &rDesc, SwFrm *pUpper,
+ sal_Bool bOdd, sal_Bool bInsertEmpty, sal_Bool bFtn,
+ SwFrm *pSibling );
+
+//Flys bei der Seite anmelden.
+void RegistFlys( SwPageFrm*, const SwLayoutFrm* );
+
+//Benachrichtung des Fly Hintergrundes wenn Notwendig.
+void Notify( SwFlyFrm *pFly, SwPageFrm *pOld, const SwRect &rOld,
+ const SwRect* pOldRect = 0 );
+
+void Notify_Background( const SdrObject* pObj,
+ SwPageFrm* pPage,
+ const SwRect& rRect,
+ const PrepareHint eHint,
+ const sal_Bool bInva );
+
+const SwFrm* GetVirtualUpper( const SwFrm* pFrm, const Point& rPos );
+
+sal_Bool Is_Lower_Of( const SwFrm *pCurrFrm, const SdrObject* pObj );
+
+const SwFrm *FindKontext( const SwFrm *pFrm, sal_uInt16 nAdditionalKontextTyp );
+
+sal_Bool IsFrmInSameKontext( const SwFrm *pInnerFrm, const SwFrm *pFrm );
+
+const SwFrm * MA_FASTCALL FindPage( const SwRect &rRect, const SwFrm *pPage );
+
+// wird von SwCntntNode::GetFrm und von SwFlyFrm::GetFrm
+// gerufen
+SwFrm* GetFrmOfModify( const SwRootFrm* pLayout, SwModify const&, sal_uInt16 const nFrmType, const Point* = 0,
+ const SwPosition *pPos = 0,
+ const sal_Bool bCalcFrm = sal_False );
+
+//Sollen ExtraDaten (Reline-Strich, Zeilennummern) gepaintet werden?
+sal_Bool IsExtraData( const SwDoc *pDoc );
+
+// #i11760# - method declaration <CalcCntnt(..)>
+void CalcCntnt( SwLayoutFrm *pLay,
+ bool bNoColl = false,
+ bool bNoCalcFollow = false );
+
+
+//Die Notify-Klassen merken sich im CTor die aktuellen Groessen und fuehren
+//im DTor ggf. die notwendigen Benachrichtigungen durch.
+
+class SwFrmNotify
+{
+protected:
+ SwFrm *pFrm;
+ const SwRect aFrm;
+ const SwRect aPrt;
+ SwTwips mnFlyAnchorOfst;
+ SwTwips mnFlyAnchorOfstNoWrap;
+ sal_Bool bHadFollow;
+ sal_Bool bInvaKeep;
+ sal_Bool bValidSize;
+protected:
+ // #i49383#
+ bool mbFrmDeleted;
+
+public:
+ SwFrmNotify( SwFrm *pFrm );
+ ~SwFrmNotify();
+
+ const SwRect &Frm() const { return aFrm; }
+ const SwRect &Prt() const { return aPrt; }
+ void SetInvaKeep() { bInvaKeep = sal_True; }
+ // #i49383#
+ void FrmDeleted()
+ {
+ mbFrmDeleted = true;
+ }
+};
+
+class SwLayNotify : public SwFrmNotify
+{
+ sal_Bool bLowersComplete;
+
+ SwLayoutFrm *GetLay() { return (SwLayoutFrm*)pFrm; }
+public:
+ SwLayNotify( SwLayoutFrm *pLayFrm );
+ ~SwLayNotify();
+
+ void SetLowersComplete( sal_Bool b ) { bLowersComplete = b; }
+ sal_Bool IsLowersComplete() { return bLowersComplete; }
+};
+
+class SwFlyNotify : public SwLayNotify
+{
+ SwPageFrm *pOldPage;
+ const SwRect aFrmAndSpace;
+ SwFlyFrm *GetFly() { return (SwFlyFrm*)pFrm; }
+public:
+ SwFlyNotify( SwFlyFrm *pFlyFrm );
+ ~SwFlyNotify();
+
+ SwPageFrm *GetOldPage() const { return pOldPage; }
+};
+
+class SwCntntNotify : public SwFrmNotify
+{
+private:
+ // #i11859#
+ bool mbChkHeightOfLastLine;
+ SwTwips mnHeightOfLastLine;
+
+ // #i25029#
+ bool mbInvalidatePrevPrtArea;
+ bool mbBordersJoinedWithPrev;
+
+ SwCntntFrm *GetCnt() { return (SwCntntFrm*)pFrm; }
+
+public:
+ SwCntntNotify( SwCntntFrm *pCntFrm );
+ ~SwCntntNotify();
+
+ // #i25029#
+ void SetInvalidatePrevPrtArea()
+ {
+ mbInvalidatePrevPrtArea = true;
+ }
+
+ void SetBordersJoinedWithPrev()
+ {
+ mbBordersJoinedWithPrev = true;
+ }
+};
+
+//SwBorderAttrs kapselt die Berechnung fuer die Randattribute inclusive
+//Umrandung. Die Attribute und die errechneten Werte werden gecached.
+//Neu: Die gesammte Klasse wird gecached.
+
+//!!!Achtung: Wenn weitere Attribute gecached werden muss unbedingt die
+//Methode Modify::Modify mitgepflegt werden!!!
+
+// - delete old method <SwBorderAttrs::CalcRight()> and
+// the stuff that belongs to it.
+class SwBorderAttrs : public SwCacheObj
+{
+ const SwAttrSet &rAttrSet;
+ const SvxULSpaceItem &rUL;
+ // #i96772#
+ SvxLRSpaceItem rLR;
+ const SvxBoxItem &rBox;
+ const SvxShadowItem &rShadow;
+ const Size aFrmSize; //Die FrmSize
+
+ sal_Bool bBorderDist :1; //Ist's ein Frm der auch ohne Linie
+ //einen Abstand haben kann?
+
+ //Mit den Folgenden Bools werden die gecache'ten Werte fuer UNgueltig
+ //erklaert - bis sie einmal berechnet wurden.
+ sal_Bool bTopLine :1;
+ sal_Bool bBottomLine :1;
+ sal_Bool bLeftLine :1;
+ sal_Bool bRightLine :1;
+ sal_Bool bTop :1;
+ sal_Bool bBottom :1;
+ sal_Bool bLine :1;
+
+ sal_Bool bIsLine :1; //Umrandung an mind. einer Kante?
+
+ sal_Bool bCacheGetLine :1; //GetTopLine(), GetBottomLine() cachen?
+ sal_Bool bCachedGetTopLine :1; //GetTopLine() gecached?
+ sal_Bool bCachedGetBottomLine :1; //GetBottomLine() gecached?
+ // - booleans indicating, if values <bJoinedWithPrev>
+ // and <bJoinedWithNext> are cached and valid.
+ // Caching depends on value of <bCacheGetLine>.
+ mutable sal_Bool bCachedJoinedWithPrev :1;
+ mutable sal_Bool bCachedJoinedWithNext :1;
+ // - booleans indicating, if borders are joined
+ // with previous/next frame.
+ sal_Bool bJoinedWithPrev :1;
+ sal_Bool bJoinedWithNext :1;
+
+ //Die gecache'ten Werte, undefiniert bis sie einmal berechnet wurden.
+ sal_uInt16 nTopLine,
+ nBottomLine,
+ nLeftLine,
+ nRightLine,
+ nTop,
+ nBottom,
+ nGetTopLine,
+ nGetBottomLine;
+
+ //Nur die Lines + Shadow errechnen.
+ void _CalcTopLine();
+ void _CalcBottomLine();
+ void _CalcLeftLine();
+ void _CalcRightLine();
+
+ //Lines + Shadow + Abstaende
+ void _CalcTop();
+ void _CalcBottom();
+
+ void _IsLine();
+
+ // #i25029# - add optional 2nd parameter <_pPrevFrm>
+ // If set, its value is taken for testing, if borders/shadow have to joined
+ // with previous frame.
+ void _GetTopLine ( const SwFrm& _rFrm,
+ const SwFrm* _pPrevFrm = 0L );
+ void _GetBottomLine( const SwFrm& _rFrm );
+
+ // - private methods to calculate cached values
+ // <bJoinedWithPrev> and <bJoinedWithNext>.
+ // #i25029# - add optional 2nd parameter <_pPrevFrm>
+ // If set, its value is taken for testing, if borders/shadow have to joined
+ // with previous frame.
+ void _CalcJoinedWithPrev( const SwFrm& _rFrm,
+ const SwFrm* _pPrevFrm = 0L );
+ void _CalcJoinedWithNext( const SwFrm& _rFrm );
+
+ // - internal helper method for methods
+ // <_CalcJoinedWithPrev> and <_CalcJoinedWithNext>.
+ sal_Bool _JoinWithCmp( const SwFrm& _rCallerFrm,
+ const SwFrm& _rCmpFrm ) const;
+
+ //Rechte und linke Linie sowie LRSpace gleich?
+ // - change name of 1st parameter - "rAttrs" -> "rCmpAttrs".
+ sal_Bool CmpLeftRight( const SwBorderAttrs &rCmpAttrs,
+ const SwFrm *pCaller,
+ const SwFrm *pCmp ) const;
+
+public:
+ DECL_FIXEDMEMPOOL_NEWDEL(SwBorderAttrs)
+
+ SwBorderAttrs( const SwModify *pOwner, const SwFrm *pConstructor );
+ ~SwBorderAttrs();
+
+ inline const SwAttrSet &GetAttrSet() const { return rAttrSet; }
+ inline const SvxULSpaceItem &GetULSpace() const { return rUL; }
+ inline const SvxLRSpaceItem &GetLRSpace() const { return rLR; }
+ inline const SvxBoxItem &GetBox() const { return rBox; }
+ inline const SvxShadowItem &GetShadow() const { return rShadow; }
+
+ inline sal_uInt16 CalcTopLine() const;
+ inline sal_uInt16 CalcBottomLine() const;
+ inline sal_uInt16 CalcLeftLine() const;
+ inline sal_uInt16 CalcRightLine() const;
+ inline sal_uInt16 CalcTop() const;
+ inline sal_uInt16 CalcBottom() const;
+ long CalcLeft( const SwFrm *pCaller ) const;
+ long CalcRight( const SwFrm *pCaller ) const;
+
+ inline sal_Bool IsLine() const;
+
+ inline const Size &GetSize() const { return aFrmSize; }
+
+ inline sal_Bool IsBorderDist() const { return bBorderDist; }
+
+ //Sollen obere bzw. untere Umrandung fuer den Frm ausgewertet werden?
+ // #i25029# - add optional 2nd parameter <_pPrevFrm>
+ // If set, its value is taken for testing, if borders/shadow have to joined
+ // with previous frame.
+ inline sal_uInt16 GetTopLine ( const SwFrm& _rFrm,
+ const SwFrm* _pPrevFrm = 0L ) const;
+ inline sal_uInt16 GetBottomLine( const SwFrm& _rFrm ) const;
+ inline void SetGetCacheLine( sal_Bool bNew ) const;
+ // - accessors for cached values <bJoinedWithPrev>
+ // and <bJoinedWithPrev>
+ // #i25029# - add optional 2nd parameter <_pPrevFrm>
+ // If set, its value is taken for testing, if borders/shadow have to joined
+ // with previous frame.
+ sal_Bool JoinedWithPrev( const SwFrm& _rFrm,
+ const SwFrm* _pPrevFrm = 0L ) const;
+ sal_Bool JoinedWithNext( const SwFrm& _rFrm ) const;
+};
+
+class SwBorderAttrAccess : public SwCacheAccess
+{
+ const SwFrm *pConstructor; //opt: Zur weitergabe an SwBorderAttrs
+protected:
+ virtual SwCacheObj *NewObj();
+
+public:
+ SwBorderAttrAccess( SwCache &rCache, const SwFrm *pOwner );
+
+ SwBorderAttrs *Get();
+};
+
+//---------------------------------------------------------------------
+//Iterator fuer die DrawObjecte einer Seite. Die Objecte werden Nach ihrer
+//Z-Order iteriert.
+//Das iterieren ist nicht eben billig, denn fuer alle Operationen muss jeweils
+//ueber das gesamte SortArray iteriert werden.
+class SwOrderIter
+{
+ const SwPageFrm *pPage;
+ const SdrObject *pCurrent;
+ const sal_Bool bFlysOnly;
+public:
+ SwOrderIter( const SwPageFrm *pPage, sal_Bool bFlysOnly = sal_True );
+
+ void Current( const SdrObject *pNew ) { pCurrent = pNew; }
+ const SdrObject *Current() const { return pCurrent; }
+ const SdrObject *operator()() const { return pCurrent; }
+ const SdrObject *Top();
+ const SdrObject *Bottom();
+ const SdrObject *Next();
+ const SdrObject *Prev();
+};
+
+
+class StackHack
+{
+ static sal_uInt8 nCnt;
+ static sal_Bool bLocked;
+public:
+ StackHack()
+ {
+ if ( ++StackHack::nCnt > 50 )
+ StackHack::bLocked = sal_True;
+ }
+ ~StackHack()
+ {
+ if ( --StackHack::nCnt < 5 )
+ StackHack::bLocked = sal_False;
+ }
+
+ static sal_Bool IsLocked() { return StackHack::bLocked; }
+ static sal_uInt8 Count() { return StackHack::nCnt; }
+};
+
+
+//Sollen obere bzw. untere Umrandung fuer den Frm ausgewertet werden?
+// #i25029# - add optional 2nd parameter <_pPrevFrm>
+// If set, its value is taken for testing, if borders/shadow have to joined
+// with previous frame.
+inline sal_uInt16 SwBorderAttrs::GetTopLine ( const SwFrm& _rFrm,
+ const SwFrm* _pPrevFrm ) const
+{
+ if ( !bCachedGetTopLine || _pPrevFrm )
+ {
+ const_cast<SwBorderAttrs*>(this)->_GetTopLine( _rFrm, _pPrevFrm );
+ }
+ return nGetTopLine;
+}
+inline sal_uInt16 SwBorderAttrs::GetBottomLine( const SwFrm& _rFrm ) const
+{
+ if ( !bCachedGetBottomLine )
+ const_cast<SwBorderAttrs*>(this)->_GetBottomLine( _rFrm );
+ return nGetBottomLine;
+}
+inline void SwBorderAttrs::SetGetCacheLine( sal_Bool bNew ) const
+{
+ ((SwBorderAttrs*)this)->bCacheGetLine = bNew;
+ ((SwBorderAttrs*)this)->bCachedGetBottomLine =
+ ((SwBorderAttrs*)this)->bCachedGetTopLine = sal_False;
+ // - invalidate cache for values <bJoinedWithPrev>
+ // and <bJoinedWithNext>.
+ bCachedJoinedWithPrev = sal_False;
+ bCachedJoinedWithNext = sal_False;
+}
+
+inline sal_uInt16 SwBorderAttrs::CalcTopLine() const
+{
+ if ( bTopLine )
+ ((SwBorderAttrs*)this)->_CalcTopLine();
+ return nTopLine;
+}
+inline sal_uInt16 SwBorderAttrs::CalcBottomLine() const
+{
+ if ( bBottomLine )
+ ((SwBorderAttrs*)this)->_CalcBottomLine();
+ return nBottomLine;
+}
+inline sal_uInt16 SwBorderAttrs::CalcLeftLine() const
+{
+ if ( bLeftLine )
+ ((SwBorderAttrs*)this)->_CalcLeftLine();
+ return nLeftLine;
+}
+inline sal_uInt16 SwBorderAttrs::CalcRightLine() const
+{
+ if ( bRightLine )
+ ((SwBorderAttrs*)this)->_CalcRightLine();
+ return nRightLine;
+}
+inline sal_uInt16 SwBorderAttrs::CalcTop() const
+{
+ if ( bTop )
+ ((SwBorderAttrs*)this)->_CalcTop();
+ return nTop;
+}
+inline sal_uInt16 SwBorderAttrs::CalcBottom() const
+{
+ if ( bBottom )
+ ((SwBorderAttrs*)this)->_CalcBottom();
+ return nBottom;
+}
+inline sal_Bool SwBorderAttrs::IsLine() const
+{
+ if ( bLine )
+ ((SwBorderAttrs*)this)->_IsLine();
+ return bIsLine;
+}
+
+/** method to determine the spacing values of a frame
+
+ #i28701#
+ Values only provided for flow frames (table, section or text frames)
+ Note: line spacing value is only determined for text frames
+ #i102458#
+ Add output parameter <obIsLineSpacingProportional>
+
+ @param rFrm
+ input parameter - frame, for which the spacing values are determined.
+
+ @param onPrevLowerSpacing
+ output parameter - lower spacing of the frame in SwTwips
+
+ @param onPrevLineSpacing
+ output parameter - line spacing of the frame in SwTwips
+
+ @param obIsLineSpacingProportional
+*/
+void GetSpacingValuesOfFrm( const SwFrm& rFrm,
+ SwTwips& onLowerSpacing,
+ SwTwips& onLineSpacing,
+ bool& obIsLineSpacingProportional );
+
+/** method to get the content of the table cell
+
+ Content from any nested tables will be omitted.
+ Note: line spacing value is only determined for text frames
+
+ @param rCell_
+ input parameter - the cell which should be searched for content.
+
+ return
+ pointer to the found content frame or 0
+*/
+
+const SwCntntFrm* GetCellCntnt( const SwLayoutFrm& rCell_ );
+
+
+/** helper class to check if a frame has been deleted during an operation
+ * !!!WARNING!!! This should only be used as a last and desperate means
+ * to make the code robust.
+ */
+
+class SwDeletionChecker
+{
+ private:
+
+ const SwFrm* mpFrm;
+ const SwModify* mpRegIn;
+
+ public:
+
+ SwDeletionChecker( const SwFrm* pFrm )
+ : mpFrm( pFrm ),
+ mpRegIn( pFrm ? const_cast<SwFrm*>(pFrm)->GetRegisteredIn() : 0 )
+ {
+ }
+
+ /**
+ * return
+ * true if mpFrm != 0 and mpFrm is not client of pRegIn
+ * false otherwise
+ */
+ bool HasBeenDeleted();
+};
+
+#endif //_FRMTOOL_HXX
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/inc/ftnboss.hxx b/sw/source/core/inc/ftnboss.hxx
new file mode 100644
index 000000000000..21aab8886a39
--- /dev/null
+++ b/sw/source/core/inc/ftnboss.hxx
@@ -0,0 +1,140 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+#ifndef _FTNBOSS_HXX
+#define _FTNBOSS_HXX
+
+#include "layfrm.hxx"
+
+class SwFtnBossFrm;
+class SwFtnContFrm;
+class SwFtnFrm;
+class SwTxtFtn;
+
+
+//Setzen des maximalen Fussnotenbereiches. Restaurieren des alten Wertes im DTor.
+//Implementierung im ftnfrm.cxx
+class SwSaveFtnHeight
+{
+ SwFtnBossFrm *pBoss;
+ const SwTwips nOldHeight;
+ SwTwips nNewHeight;
+public:
+ SwSaveFtnHeight( SwFtnBossFrm *pBs, const SwTwips nDeadLine );
+ ~SwSaveFtnHeight();
+};
+
+#define NA_ONLY_ADJUST 0
+#define NA_GROW_SHRINK 1
+#define NA_GROW_ADJUST 2
+#define NA_ADJUST_GROW 3
+
+class SwFtnBossFrm: public SwLayoutFrm
+{
+ //Fuer die privaten Fussnotenoperationen
+ friend class SwFrm;
+ friend class SwSaveFtnHeight;
+ friend class SwPageFrm; // fuer das Setzen der MaxFtnHeight
+
+ //Maximale Hoehe des Fussnotencontainers fuer diese Seite.
+ SwTwips nMaxFtnHeight;
+
+ SwFtnContFrm *MakeFtnCont();
+ SwFtnFrm *FindFirstFtn();
+ sal_uInt8 _NeighbourhoodAdjustment( const SwFrm* pFrm ) const;
+protected:
+
+ void InsertFtn( SwFtnFrm * );
+ static void ResetFtn( const SwFtnFrm *pAssumed );
+public:
+ inline SwFtnBossFrm( SwFrmFmt* pFmt, SwFrm* pSib ) : SwLayoutFrm( pFmt, pSib ) {}
+
+ SwLayoutFrm *FindBodyCont();
+ inline const SwLayoutFrm *FindBodyCont() const;
+ inline void SetMaxFtnHeight( const SwTwips nNewMax ) { nMaxFtnHeight = nNewMax; }
+
+ //Fussnotenschnittstelle
+ void AppendFtn( SwCntntFrm *, SwTxtFtn * );
+ void RemoveFtn( const SwCntntFrm *, const SwTxtFtn *, sal_Bool bPrep = sal_True );
+ static SwFtnFrm *FindFtn( const SwCntntFrm *, const SwTxtFtn * );
+ SwFtnContFrm *FindFtnCont();
+ inline const SwFtnContFrm *FindFtnCont() const;
+ const SwFtnFrm *FindFirstFtn( SwCntntFrm* ) const;
+ SwFtnContFrm *FindNearestFtnCont( sal_Bool bDontLeave = sal_False );
+
+ void ChangeFtnRef( const SwCntntFrm *pOld, const SwTxtFtn *,
+ SwCntntFrm *pNew );
+ void RearrangeFtns( const SwTwips nDeadLine, const sal_Bool bLock = sal_False,
+ const SwTxtFtn *pAttr = 0 );
+
+ //SS damit der Textformatierer Temporaer die Fussnotenhoehe begrenzen
+ //kann. DeadLine in Dokumentkoordinaten.
+ void SetFtnDeadLine( const SwTwips nDeadLine );
+ SwTwips GetMaxFtnHeight() const { return nMaxFtnHeight; }
+
+ //Liefert den Wert, der noch uebrig ist, bis der Body seine minimale
+ //Hoehe erreicht hat.
+ SwTwips GetVarSpace() const;
+
+ //Layoutseitig benoetigte Methoden
+ /// OD 03.04.2003 #108446# - add parameters <_bCollectOnlyPreviousFtns> and
+ /// <_pRefFtnBossFrm> in order to control, if only footnotes, which are positioned
+ /// before the given reference footnote boss frame have to be collected.
+ /// Note: if parameter <_bCollectOnlyPreviousFtns> is true, then parameter
+ /// <_pRefFtnBossFrm> have to be referenced to an object.
+ static void _CollectFtns( const SwCntntFrm* _pRef,
+ SwFtnFrm* _pFtn,
+ SvPtrarr& _rFtnArr,
+ const sal_Bool _bCollectOnlyPreviousFtns = sal_False,
+ const SwFtnBossFrm* _pRefFtnBossFrm = NULL);
+ /// OD 03.04.2003 #108446# - add parameter <_bCollectOnlyPreviousFtns> in
+ /// order to control, if only footnotes, which are positioned before the
+ /// footnote boss frame <this> have to be collected.
+ void CollectFtns( const SwCntntFrm* _pRef,
+ SwFtnBossFrm* _pOld,
+ SvPtrarr& _rFtnArr,
+ const sal_Bool _bCollectOnlyPreviousFtns = sal_False );
+ void _MoveFtns( SvPtrarr &rFtnArr, sal_Bool bCalc = sal_False );
+ void MoveFtns( const SwCntntFrm *pSrc, SwCntntFrm *pDest,
+ SwTxtFtn *pAttr );
+ // Sollte AdjustNeighbourhood gerufen werden (oder Grow/Shrink)?
+ sal_uInt8 NeighbourhoodAdjustment( const SwFrm* pFrm ) const
+ { return IsPageFrm() ? NA_ONLY_ADJUST : _NeighbourhoodAdjustment( pFrm ); }
+};
+
+inline const SwLayoutFrm *SwFtnBossFrm::FindBodyCont() const
+{
+ return ((SwFtnBossFrm*)this)->FindBodyCont();
+}
+inline const SwFtnContFrm *SwFtnBossFrm::FindFtnCont() const
+{
+ return ((SwFtnBossFrm*)this)->FindFtnCont();
+}
+
+#endif //_FTNBOSS_HXX
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/inc/ftnfrm.hxx b/sw/source/core/inc/ftnfrm.hxx
new file mode 100644
index 000000000000..773c4eca68b7
--- /dev/null
+++ b/sw/source/core/inc/ftnfrm.hxx
@@ -0,0 +1,153 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+#ifndef _FTNFRM_HXX
+#define _FTNFRM_HXX
+
+#include "layfrm.hxx"
+
+class SwCntntFrm;
+class SwTxtFtn;
+class SwBorderAttrs;
+class SwFtnFrm;
+
+//Fuer Fussnoten gibt es einen Speziellen Bereich auf der Seite. Dieser
+//Bereich ist ein SwFtnContFrm.
+//Jede Fussnote ist durch einen SwFtnFrm abgegrenzt, dieser nimmt die
+//Fussnotenabsaetze auf. SwFtnFrm koennen aufgespalten werden, sie gehen
+//dann auf einer anderen Seite weiter.
+
+class SwFtnContFrm: public SwLayoutFrm
+{
+public:
+ SwFtnContFrm( SwFrmFmt*, SwFrm* );
+
+ const SwFtnFrm* FindFootNote() const;
+
+ virtual SwTwips ShrinkFrm( SwTwips, sal_Bool bTst = sal_False, sal_Bool bInfo = sal_False );
+ virtual SwTwips GrowFrm ( SwTwips, sal_Bool bTst = sal_False, sal_Bool bInfo = sal_False );
+ virtual void Format( const SwBorderAttrs *pAttrs = 0 );
+ virtual void PaintBorder( const SwRect &, const SwPageFrm *pPage,
+ const SwBorderAttrs & ) const;
+ void PaintLine( const SwRect &, const SwPageFrm * ) const;
+};
+
+class SwFtnFrm: public SwLayoutFrm
+{
+ //Zeiger auf den FtnFrm in dem die Fussnote weitergefuehrt wird:
+ // 0 wenn kein Follow vorhanden,
+ // this beim letzten
+ // der Follow sonst.
+ SwFtnFrm *pFollow;
+ SwFtnFrm *pMaster; //Der FtnFrm dessen Follow ich bin.
+ SwCntntFrm *pRef; //In diesem CntntFrm steht die Fussnotenref.
+ SwTxtFtn *pAttr; //Fussnotenattribut (zum wiedererkennen)
+
+ sal_Bool bBackMoveLocked : 1; //Absaetze in dieser Fussnote duerfen derzeit
+ //nicht rueckwaerts fliessen.
+ // --> OD 2005-05-18 #i49383# - control unlock of position of lower anchored objects.
+ bool mbUnlockPosOfLowerObjs : 1;
+ // <--
+#if OSL_DEBUG_LEVEL > 1
+protected:
+ virtual SwTwips ShrinkFrm( SwTwips, sal_Bool bTst = sal_False, sal_Bool bInfo = sal_False );
+ virtual SwTwips GrowFrm ( SwTwips, sal_Bool bTst = sal_False, sal_Bool bInfo = sal_False );
+#endif
+
+
+public:
+ SwFtnFrm( SwFrmFmt*, SwFrm*, SwCntntFrm*, SwTxtFtn* );
+
+ virtual void Cut();
+ virtual void Paste( SwFrm* pParent, SwFrm* pSibling = 0 );
+
+ sal_Bool operator<( const SwTxtFtn* pTxtFtn ) const;
+
+#if OSL_DEBUG_LEVEL > 1
+ // in a non pro version test if the attribute has the same
+ // meaning which his reference is
+ const SwCntntFrm *GetRef() const;
+ SwCntntFrm *GetRef();
+#else
+ const SwCntntFrm *GetRef() const { return pRef; }
+ SwCntntFrm *GetRef() { return pRef; }
+#endif
+ const SwCntntFrm *GetRefFromAttr() const;
+ SwCntntFrm *GetRefFromAttr();
+
+ const SwFtnFrm *GetFollow() const { return pFollow; }
+ SwFtnFrm *GetFollow() { return pFollow; }
+
+ const SwFtnFrm *GetMaster() const { return pMaster; }
+ SwFtnFrm *GetMaster() { return pMaster; }
+
+ const SwTxtFtn *GetAttr() const { return pAttr; }
+ SwTxtFtn *GetAttr() { return pAttr; }
+
+ void SetFollow( SwFtnFrm *pNew ) { pFollow = pNew; }
+ void SetMaster( SwFtnFrm *pNew ) { pMaster = pNew; }
+ void SetRef ( SwCntntFrm *pNew ) { pRef = pNew; }
+
+ void InvalidateNxtFtnCnts( SwPageFrm* pPage );
+
+ void LockBackMove() { bBackMoveLocked = sal_True; }
+ void UnlockBackMove() { bBackMoveLocked = sal_False;}
+ sal_Bool IsBackMoveLocked() { return bBackMoveLocked; }
+
+ // Verhindert, dass der letzte Inhalt den SwFtnFrm mitloescht (Cut())
+ inline void ColLock() { bColLocked = sal_True; }
+ inline void ColUnlock() { bColLocked = sal_False; }
+
+ // --> OD 2005-05-18 #i49383#
+ inline void UnlockPosOfLowerObjs()
+ {
+ mbUnlockPosOfLowerObjs = true;
+ }
+ inline void KeepLockPosOfLowerObjs()
+ {
+ mbUnlockPosOfLowerObjs = false;
+ }
+ inline bool IsUnlockPosOfLowerObjs()
+ {
+ return mbUnlockPosOfLowerObjs;
+ }
+ // <--
+ /** search for last content in the current footnote frame
+
+ OD 2005-12-02 #i27138#
+
+ @author OD
+
+ @return SwCntntFrm*
+ pointer to found last content frame. NULL, if none is found.
+ */
+ SwCntntFrm* FindLastCntnt();
+};
+
+#endif //_FTNFRM_HXX
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/inc/hffrm.hxx b/sw/source/core/inc/hffrm.hxx
new file mode 100644
index 000000000000..39f09e9bd45a
--- /dev/null
+++ b/sw/source/core/inc/hffrm.hxx
@@ -0,0 +1,69 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+#ifndef _HFFRM_HXX
+#define _HFFRM_HXX
+
+#include <tools/mempool.hxx>
+
+#include "layfrm.hxx"
+
+
+class SwHeadFootFrm : public SwLayoutFrm
+{
+protected:
+ void FormatSize(SwTwips nUL, const SwBorderAttrs * pAttrs);
+ void FormatPrt(SwTwips & nUL, const SwBorderAttrs * pAttrs);
+ inline sal_Bool GetEatSpacing() const; // in hffrm.cxx
+public:
+ SwHeadFootFrm(SwFrmFmt * pFrm, SwFrm*, sal_uInt16 aType);
+ virtual void Format( const SwBorderAttrs *pAttrs = 0 );
+ virtual SwTwips GrowFrm( SwTwips,
+ sal_Bool bTst = sal_False, sal_Bool bInfo = sal_False );
+ virtual SwTwips ShrinkFrm( SwTwips,
+ sal_Bool bTst = sal_False, sal_Bool bInfo = sal_False );
+};
+
+class SwHeaderFrm: public SwHeadFootFrm
+{
+public:
+ SwHeaderFrm( SwFrmFmt* pFrm, SwFrm* pSib ) : SwHeadFootFrm(pFrm, pSib, FRMC_HEADER) {};
+
+ DECL_FIXEDMEMPOOL_NEWDEL(SwHeaderFrm)
+};
+
+class SwFooterFrm: public SwHeadFootFrm
+{
+public:
+ SwFooterFrm( SwFrmFmt* pFrm, SwFrm* pSib ) : SwHeadFootFrm(pFrm, pSib, FRMC_FOOTER) {};
+
+ DECL_FIXEDMEMPOOL_NEWDEL(SwFooterFrm)
+};
+
+#endif //_HFFRM_HXX
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/inc/ifinishedthreadlistener.hxx b/sw/source/core/inc/ifinishedthreadlistener.hxx
new file mode 100644
index 000000000000..fbf6099f8456
--- /dev/null
+++ b/sw/source/core/inc/ifinishedthreadlistener.hxx
@@ -0,0 +1,58 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+#ifndef _IFINISHEDTHREADLISTENER_HXX
+#define _IFINISHEDTHREADLISTENER_HXX
+
+#include <osl/interlck.h>
+
+/** interface class to listen on the finish of a thread
+
+ OD 2007-03-30 #i73788#
+ Note: The thread provides its ThreadID on the finish notification
+
+ @author OD
+*/
+class IFinishedThreadListener
+{
+ public:
+
+ inline virtual ~IFinishedThreadListener()
+ {
+ };
+
+ virtual void NotifyAboutFinishedThread( const oslInterlockedCount nThreadID ) = 0;
+
+ protected:
+
+ inline IFinishedThreadListener()
+ {
+ };
+};
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/inc/ithreadlistenerowner.hxx b/sw/source/core/inc/ithreadlistenerowner.hxx
new file mode 100644
index 000000000000..8ba165774ee7
--- /dev/null
+++ b/sw/source/core/inc/ithreadlistenerowner.hxx
@@ -0,0 +1,61 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+#ifndef _ITHREADLISTENEROWNER_HXX
+#define _ITHREADLISTENEROWNER_HXX
+
+#include <ifinishedthreadlistener.hxx>
+
+#include <boost/weak_ptr.hpp>
+
+/** interface class of the owner of a thread listener
+
+ OD 2007-01-30 #i73788#
+
+ @author OD
+*/
+class IThreadListenerOwner
+{
+ public:
+
+ inline virtual ~IThreadListenerOwner()
+ {
+ };
+
+ virtual boost::weak_ptr< IFinishedThreadListener > GetThreadListenerWeakRef() = 0;
+
+ virtual void NotifyAboutFinishedThread( const oslInterlockedCount nThreadID ) = 0;
+
+ protected:
+
+ inline IThreadListenerOwner()
+ {
+ };
+};
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/inc/layact.hxx b/sw/source/core/inc/layact.hxx
new file mode 100644
index 000000000000..e0ff55d151e4
--- /dev/null
+++ b/sw/source/core/inc/layact.hxx
@@ -0,0 +1,242 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+#ifndef _LAYACT_HXX
+#define _LAYACT_HXX
+#include "swtypes.hxx"
+#include "swrect.hxx"
+
+class SwRootFrm;
+class SwLayoutFrm;
+class SwPageFrm;
+class SwFlyFrm;
+class SwCntntFrm;
+class SwTabFrm;
+class SwViewImp;
+class SwCntntNode;
+class SwWait;
+// --> OD 2004-06-28 #i28701#
+class SfxProgress;
+
+//Die Verwendung der LayAction laeuft immer gleich ab:
+//
+// 1. Erzeugen des LayAction-Objektes.
+// 2. Einstellen des gewuenschten Verhaltens mittels der Set-Methoden
+// 3. Aufruf von Action()
+// 4. Baldiges Zerstoeren des Objektes.
+//
+// Das Objekt meldet sich im CTor beim SwViewImp an und erst im DTor
+// wieder ab! Es handelt sich mithin um ein typisches Stackobjekt.
+
+
+class SwLayAction
+{
+ SwRootFrm *pRoot;
+ SwViewImp *pImp; //Hier Meldet sich die Action an und ab.
+
+ //Zur Optimierung, damit die Tabellen etwas besser am Crsr kleben beim
+ //Return/Backspace davor.
+ //Wenn der erste TabFrm, der sich Paintet (pro Seite) traegt sich im
+ //Pointer ein. Die CntntFrms unterhalb der Seite brauchen sich
+ //dann nicht mehr bei der Shell zum Painten anmelden.
+ const SwTabFrm *pOptTab;
+
+ SwWait *pWait;
+
+ SfxProgress * pProgress;
+
+ //Wenn ein Absatz - oder was auch immer - bei der Formatierung mehr
+ //als eine Seite rueckwaerts floss traegt er seine neue Seitennummer
+ //hier ein. Die Steuerung der InternalAction kann dann geeignet reagieren.
+ sal_uInt16 nPreInvaPage;
+
+ sal_uLong nStartTicks; //Startzeitpunkt der Aktion, vergeht zu viel Zeit kann
+ //der WaitCrsr per CheckWaitCrsr() eingeschaltet werden.
+
+ sal_uInt16 nInputType; //Bei welchem Input soll die Verarbeitung abgebrochen
+ //werden?
+ sal_uInt16 nEndPage; //StatBar Steuerung.
+ sal_uInt16 nCheckPageNum; //CheckPageDesc() wurde verzoegert wenn != USHRT_MAX
+ //ab dieser Seite Checken.
+
+ sal_Bool bPaint; //Painten oder nur Formatieren?
+ sal_Bool bComplete; //Alles bis zum sichtbaren Bereich Formatieren oder
+ //oder nur den sichtbaren Bereich?
+ sal_Bool bCalcLayout; //Vollstaendige Reformatierung?
+ sal_Bool bAgain; //Zur automatisch wiederholten Action wenn Seiten
+ //geloscht werden.
+ sal_Bool bNextCycle; //Wiederaufsetzen bei der ersten Ungueltigen Seite.
+ sal_Bool bInput; //Zum Abbrechen der Verarbeitung wenn ein Input anliegt.
+ sal_Bool bIdle; //True wenn die Layaction vom Idler ausgeloest wurde.
+ sal_Bool bReschedule; //Soll das Reschedule - abhaengig vom Progress -
+ //gerufen werden?
+ sal_Bool bCheckPages; //CheckPageDescs() ausfuehren oder verzoegern.
+ sal_Bool bUpdateExpFlds;//Wird gesetzt wenn nach dem Formatierien noch eine
+ //Runde fuer den ExpFld laufen muss.
+ sal_Bool bBrowseActionStop; //Action fruehzeitig beenden (per bInput) und den
+ //Rest dem Idler ueberlassen.
+ sal_Bool bWaitAllowed; //Wartecursor erlaubt?
+ sal_Bool bPaintExtraData; //Anzeige von Zeilennumerierung o. ae. eingeschaltet?
+ sal_Bool bActionInProgress; // wird in Action() anfangs gesetzt und zum Schluss geloescht
+
+ // OD 14.04.2003 #106346# - new flag for content formatting on interrupt.
+ sal_Bool mbFormatCntntOnInterrupt;
+
+#ifdef _LAYACT_CXX
+
+ void PaintCntnt( const SwCntntFrm *, const SwPageFrm *,
+ const SwRect &rOldRect, long nOldBottom );
+ sal_Bool PaintWithoutFlys( const SwRect &, const SwCntntFrm *,
+ const SwPageFrm * );
+ inline sal_Bool _PaintCntnt( const SwCntntFrm *, const SwPageFrm *,
+ const SwRect & );
+
+ sal_Bool FormatLayout( SwLayoutFrm *, sal_Bool bAddRect = sal_True );
+ sal_Bool FormatLayoutTab( SwTabFrm *, sal_Bool bAddRect = sal_True );
+ sal_Bool FormatCntnt( const SwPageFrm* pPage );
+ void _FormatCntnt( const SwCntntFrm* pCntnt,
+ const SwPageFrm* pPage );
+ sal_Bool IsShortCut( SwPageFrm *& );
+
+ sal_Bool TurboAction();
+ sal_Bool _TurboAction( const SwCntntFrm * );
+ void InternalAction();
+
+ SwPageFrm *CheckFirstVisPage( SwPageFrm *pPage );
+
+ sal_Bool RemoveEmptyBrowserPages();
+
+ inline void CheckIdleEnd();
+ inline sal_uLong GetStartTicks() { return nStartTicks; }
+
+#endif
+
+public:
+ SwLayAction( SwRootFrm *pRt, SwViewImp *pImp );
+ ~SwLayAction();
+
+#ifdef _LAYACT_CXX
+ void SetIdle ( sal_Bool bNew ) { bIdle = bNew; }
+ void SetCheckPages ( sal_Bool bNew ) { bCheckPages = bNew; }
+ void SetBrowseActionStop(sal_Bool bNew ) { bBrowseActionStop = bNew; }
+ void SetNextCycle ( sal_Bool bNew ) { bNextCycle = bNew; }
+
+ sal_Bool IsWaitAllowed() const { return bWaitAllowed; }
+ sal_Bool IsNextCycle() const { return bNextCycle; }
+ sal_Bool IsInput() const { return bInput; }
+ sal_Bool IsWait() const { return 0 != pWait; }
+ sal_Bool IsPaint() const { return bPaint; }
+ sal_Bool IsIdle() const { return bIdle; }
+ sal_Bool IsReschedule() const { return bReschedule; }
+ sal_Bool IsPaintExtraData() const { return bPaintExtraData;}
+ sal_Bool IsStopPrt() const;
+ sal_Bool IsInterrupt() const { return IsInput() || IsStopPrt(); }
+
+ sal_uInt16 GetInputType() const { return nInputType; }
+#endif
+
+ //Einstellen der Action auf das gewuenschte Verhalten.
+ void SetPaint ( sal_Bool bNew ) { bPaint = bNew; }
+ void SetComplete ( sal_Bool bNew ) { bComplete = bNew; }
+ void SetStatBar ( sal_Bool bNew );
+ void SetInputType ( sal_uInt16 nNew ) { nInputType = nNew; }
+ void SetCalcLayout ( sal_Bool bNew ) { bCalcLayout = bNew; }
+ void SetReschedule ( sal_Bool bNew ) { bReschedule = bNew; }
+ void SetWaitAllowed ( sal_Bool bNew ) { bWaitAllowed = bNew; }
+
+ void SetAgain() { bAgain = sal_True; }
+ void SetUpdateExpFlds() {bUpdateExpFlds = sal_True; }
+ void SetProgress(SfxProgress * _pProgress = NULL)
+ { pProgress = _pProgress; }
+
+ inline void SetCheckPageNum( sal_uInt16 nNew );
+ inline void SetCheckPageNumDirect( sal_uInt16 nNew ) { nCheckPageNum = nNew; }
+
+ void Action(); //Jetzt gehts loos...
+ void Reset(); //Zurueck auf CTor-Defaults.
+
+ sal_Bool IsAgain() const { return bAgain; }
+ sal_Bool IsComplete() const { return bComplete; }
+ sal_Bool IsExpFlds() const { return bUpdateExpFlds; }
+ sal_Bool IsCalcLayout() const { return bCalcLayout; }
+ sal_Bool IsCheckPages() const { return bCheckPages; }
+ sal_Bool IsBrowseActionStop() const { return bBrowseActionStop; }
+ sal_Bool IsActionInProgress() const { return bActionInProgress; }
+
+ sal_uInt16 GetCheckPageNum() const { return nCheckPageNum; }
+
+ //Auch andere sollen den Wartecrsr einschalten koennen.
+ void CheckWaitCrsr();
+
+ // --> OD 2004-06-09 #i28701# - method is now public;
+ // delete 2nd parameter, because its not used;
+ sal_Bool FormatLayoutFly( SwFlyFrm * );
+ // --> OD 2004-06-09 #i28701# - method is now public
+ sal_Bool _FormatFlyCntnt( const SwFlyFrm * );
+
+};
+
+class SwLayIdle
+{
+
+ SwRootFrm *pRoot;
+ SwViewImp *pImp; // Hier Meldet sich der Idler an und ab.
+ SwCntntNode *pCntntNode; // Hier wird die aktuelle Cursorposition
+ xub_StrLen nTxtPos; // zwischengespeichert.
+ sal_Bool bPageValid; // Konnte die Seite alles validiert werden?
+ sal_Bool bAllValid; // Konnte alles validiert werden?
+
+#if OSL_DEBUG_LEVEL > 1
+ sal_Bool bIndicator;
+#endif
+
+#ifdef _LAYACT_CXX
+
+#if OSL_DEBUG_LEVEL > 1
+ void ShowIdle( ColorData eName );
+#endif
+
+ enum IdleJobType{ ONLINE_SPELLING, AUTOCOMPLETE_WORDS, WORD_COUNT, SMART_TAGS }; // SMARTTAGS
+ sal_Bool _DoIdleJob( const SwCntntFrm*, IdleJobType );
+ sal_Bool DoIdleJob( IdleJobType, sal_Bool bVisAreaOnly );
+
+#endif
+
+public:
+ SwLayIdle( SwRootFrm *pRt, SwViewImp *pImp );
+ ~SwLayIdle();
+};
+
+inline void SwLayAction::SetCheckPageNum( sal_uInt16 nNew )
+{
+ if ( nNew < nCheckPageNum )
+ nCheckPageNum = nNew;
+}
+
+#endif //_LAYACT_HXX
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/inc/laycache.hxx b/sw/source/core/inc/laycache.hxx
new file mode 100644
index 000000000000..768a1611010b
--- /dev/null
+++ b/sw/source/core/inc/laycache.hxx
@@ -0,0 +1,80 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+#ifndef _LAYCACHE_HXX
+#define _LAYCACHE_HXX
+
+#include <tools/solar.h>
+
+class SwDoc;
+class SwLayCacheImpl;
+class SvStream;
+
+/*************************************************************************
+ * class SwLayoutCache
+ *
+ * This class allows to save layout information in the file and it contains
+ * this information after loading of a file.
+ * Call Write(..) with a stream and the document to save and the page break
+ * information of the document will be written.
+ * Call Read(..) with a stream and the member pLayCacheImpl will
+ * read the information from the stream and store it in an internal structur.
+ * There's a simple locking mechanism at these classes,
+ * if somebody reads the information, he increments the lock count by 1,
+ * during the Read(..) function the lock count will set to $8000.
+ *
+ **************************************************************************/
+
+class SwLayoutCache
+{
+ SwLayCacheImpl *pImpl;
+ sal_uInt16 nLockCount;
+public:
+ SwLayoutCache() : pImpl( NULL ), nLockCount( 0 ) {}
+ ~SwLayoutCache();
+
+ void Read( SvStream &rStream );
+ void Write( SvStream &rStream, const SwDoc& rDoc );
+
+ void ClearImpl();
+ sal_Bool IsLocked() const { return nLockCount > 0; }
+ sal_uInt16& GetLockCount() { return nLockCount; }
+ SwLayCacheImpl *LockImpl()
+ { if( nLockCount & 0x8000 ) return NULL;
+ if ( pImpl )
+ ++nLockCount;
+ return pImpl; }
+ void UnlockImpl() { --nLockCount; }
+
+#if OSL_DEBUG_LEVEL > 1
+ sal_Bool CompareLayout( const SwDoc& rDoc ) const;
+#endif
+};
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/inc/layfrm.hxx b/sw/source/core/inc/layfrm.hxx
new file mode 100644
index 000000000000..828e45fe8b27
--- /dev/null
+++ b/sw/source/core/inc/layfrm.hxx
@@ -0,0 +1,209 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+#ifndef SW_LAYFRM_HXX
+#define SW_LAYFRM_HXX
+
+#include "frame.hxx"
+
+class SwCntntFrm;
+class SwFlowFrm;
+class SwFmtCol;
+struct SwCrsrMoveState;
+class SwFrmFmt;
+class SwBorderAttrs;
+class SwFmtFrmSize;
+class SwCellFrm;
+
+class SwLayoutFrm: public SwFrm
+{
+ //Der verkappte SwFrm
+ friend class SwFlowFrm;
+ friend class SwFrm;
+
+ //Hebt die Lower waehrend eines Spaltenumbaus auf.
+ friend SwFrm* SaveCntnt( SwLayoutFrm *, SwFrm * );
+ friend void RestoreCntnt( SwFrm *, SwLayoutFrm *, SwFrm *pSibling, bool bGrow );
+
+#if OSL_DEBUG_LEVEL > 1
+ //entfernt leere SwSectionFrms aus einer Kette
+ friend SwFrm* SwClearDummies( SwFrm* pFrm );
+#endif
+
+ void CopySubtree( const SwLayoutFrm *pDest );
+protected:
+ virtual void Format( const SwBorderAttrs *pAttrs = 0 );
+ virtual void MakeAll();
+
+ SwFrm *pLower;
+
+ virtual SwTwips ShrinkFrm( SwTwips, sal_Bool bTst = sal_False, sal_Bool bInfo = sal_False );
+ virtual SwTwips GrowFrm ( SwTwips, sal_Bool bTst = sal_False, sal_Bool bInfo = sal_False );
+
+ long CalcRel( const SwFmtFrmSize &rSz, sal_Bool bWidth ) const;
+
+public:
+ // --> #i28701#
+ TYPEINFO();
+
+ void PaintSubsidiaryLines( const SwPageFrm*, const SwRect& ) const;
+ void RefreshLaySubsidiary( const SwPageFrm*, const SwRect& ) const;
+ void RefreshExtraData( const SwRect & ) const;
+
+ //Proportionale Groessenanpassung der untergeordneten.
+ void ChgLowersProp( const Size& rOldSize );
+
+ void AdjustColumns( const SwFmtCol *pCol, sal_Bool bAdjustAttributes );
+
+ void ChgColumns( const SwFmtCol &rOld, const SwFmtCol &rNew,
+ const sal_Bool bChgFtn = sal_False );
+
+
+ //Painted die Column-Trennlinien fuer die innenliegenden Columns.
+ void PaintColLines( const SwRect &, const SwFmtCol &,
+ const SwPageFrm * ) const;
+
+ virtual bool FillSelection( SwSelectionList& rList, const SwRect& rRect ) const;
+
+ virtual sal_Bool GetCrsrOfst( SwPosition *, Point&,
+ SwCrsrMoveState* = 0 ) const;
+
+ virtual void Cut();
+ virtual void Paste( SwFrm* pParent, SwFrm* pSibling = 0 );
+
+ //sucht den dichtesten Cntnt zum SPoint, wird bei Seiten, Flys und Cells
+ //benutzt wenn GetCrsrOfst versagt hat.
+ const SwCntntFrm* GetCntntPos( Point &rPoint, const sal_Bool bDontLeave,
+ const sal_Bool bBodyOnly = sal_False,
+ const sal_Bool bCalc = sal_False,
+ const SwCrsrMoveState *pCMS = 0,
+ const sal_Bool bDefaultExpand = sal_True ) const;
+
+ SwLayoutFrm( SwFrmFmt*, SwFrm* );
+ ~SwLayoutFrm();
+
+ virtual void Paint( SwRect const&,
+ SwPrintData const*const pPrintData = NULL ) const;
+ const SwFrm *Lower() const { return pLower; }
+ SwFrm *Lower() { return pLower; }
+ const SwCntntFrm *ContainsCntnt() const;
+ inline SwCntntFrm *ContainsCntnt();
+ const SwCellFrm *FirstCell() const;
+ inline SwCellFrm *FirstCell();
+ // Method <ContainsAny()> doesn't investigate content of footnotes by default.
+ // But under certain circumstances this investigation is intended.
+ // Thus, introduce new optional parameter <_bInvestigateFtnForSections>.
+ // It's default is <false>, still indicating that content of footnotes isn't
+ // investigated for sections.
+ const SwFrm *ContainsAny( const bool _bInvestigateFtnForSections = false ) const;
+ inline SwFrm *ContainsAny( const bool _bInvestigateFtnForSections = false );
+ sal_Bool IsAnLower( const SwFrm * ) const;
+
+ virtual const SwFrmFmt *GetFmt() const;
+ virtual SwFrmFmt *GetFmt();
+ void SetFrmFmt( SwFrmFmt* );
+
+ //Verschieben der Ftns aller Lower - ab dem StartCntnt.
+ //sal_True wenn mindestens eine Ftn verschoben wurde.
+ //Ruft das Update der Seitennummer wenn bFtnNums gesetzt ist.
+ sal_Bool MoveLowerFtns( SwCntntFrm *pStart, SwFtnBossFrm *pOldBoss,
+ SwFtnBossFrm *pNewBoss, const sal_Bool bFtnNums );
+
+ // --> #i28701# - change purpose of method and its name
+ // --> #i44016# - add parameter <_bUnlockPosOfObjs> to
+ // force an unlockposition call for the lower objects.
+ void NotifyLowerObjs( const bool _bUnlockPosOfObjs = false );
+ // <--
+
+ //Invalidiert diejenigen innenliegenden Frames, deren Breite und/oder
+ //Hoehe Prozentual berechnet werden. Auch Rahmen, die an this oder an
+ //innenliegenden verankert sind werden ggf. invalidiert.
+ void InvaPercentLowers( SwTwips nDiff = 0 );
+
+ //Gerufen von Format fuer Rahmen und Bereichen mit Spalten.
+ void FormatWidthCols( const SwBorderAttrs &, const SwTwips nBorder,
+ const SwTwips nMinHeight );
+
+ // InnerHeight returns the height of the content and may be bigger or
+ // less than the PrtArea-Height of the layoutframe himself
+ SwTwips InnerHeight() const;
+
+ /** method to check relative position of layout frame to
+ a given layout frame.
+
+ refactoring of pseudo-local method <lcl_Apres(..)> in
+ <txtftn.cxx> for #104840#.
+
+ @param _aCheckRefLayFrm
+ constant reference of an instance of class <SwLayoutFrm> which
+ is used as the reference for the relative position check.
+
+ @author OD
+
+ @return true, if <this> is positioned before the layout frame <p>
+ */
+ bool IsBefore( const SwLayoutFrm* _pCheckRefLayFrm ) const;
+
+ const SwFrm* GetLastLower() const;
+ inline SwFrm* GetLastLower();
+};
+
+//Um doppelte Implementierung zu sparen wird hier ein bischen gecasted
+inline SwCntntFrm* SwLayoutFrm::ContainsCntnt()
+{
+ return (SwCntntFrm*)(((const SwLayoutFrm*)this)->ContainsCntnt());
+}
+
+inline SwCellFrm* SwLayoutFrm::FirstCell()
+{
+ return (SwCellFrm*)(((const SwLayoutFrm*)this)->FirstCell());
+}
+
+inline SwFrm* SwLayoutFrm::ContainsAny( const bool _bInvestigateFtnForSections )
+{
+ return (SwFrm*)(((const SwLayoutFrm*)this)->ContainsAny( _bInvestigateFtnForSections ));
+}
+
+// Diese SwFrm-inlines sind hier, damit frame.hxx nicht layfrm.hxx includen muss
+inline sal_Bool SwFrm::IsColBodyFrm() const
+{
+ return nType == FRMC_BODY && GetUpper()->IsColumnFrm();
+}
+
+inline sal_Bool SwFrm::IsPageBodyFrm() const
+{
+ return nType == FRMC_BODY && GetUpper()->IsPageFrm();
+}
+
+inline SwFrm* SwLayoutFrm::GetLastLower()
+{
+ return const_cast<SwFrm*>(static_cast<const SwLayoutFrm*>(this)->GetLastLower());
+}
+
+#endif // SW_LAYFRM_HXX
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/inc/layouter.hxx b/sw/source/core/inc/layouter.hxx
new file mode 100644
index 000000000000..7ffa885038dd
--- /dev/null
+++ b/sw/source/core/inc/layouter.hxx
@@ -0,0 +1,185 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+#ifndef _LAYOUTER_HXX
+#define _LAYOUTER_HXX
+
+#include "swtypes.hxx"
+
+class SwEndnoter;
+class SwDoc;
+class SwSectionFrm;
+class SwFtnFrm;
+class SwPageFrm;
+class SwLooping;
+class IDocumentLayoutAccess;
+
+// --> #i28701#
+class SwMovedFwdFrmsByObjPos;
+class SwTxtFrm;
+// <--
+// --> #i26945#
+class SwRowFrm;
+// <--
+// --> #i35911#
+class SwObjsMarkedAsTmpConsiderWrapInfluence;
+class SwAnchoredObject;
+// <--
+// --> #i40155#
+#include <vector>
+class SwFrm;
+// <--
+// --> #i65250#
+#include <swtypes.hxx>
+#include <boost/unordered_map.hpp>
+class SwFlowFrm;
+class SwLayoutFrm;
+// <--
+
+#define LOOP_PAGE 1
+
+class SwLayouter
+{
+ SwEndnoter* pEndnoter;
+ SwLooping* pLooping;
+ void _CollectEndnotes( SwSectionFrm* pSect );
+ sal_Bool StartLooping( SwPageFrm* pPage );
+
+ // --> #i28701#
+ SwMovedFwdFrmsByObjPos* mpMovedFwdFrms;
+ // <--
+ // --> #i35911#
+ SwObjsMarkedAsTmpConsiderWrapInfluence* mpObjsTmpConsiderWrapInfl;
+ // <--
+ // --> #i40155# - data structure to collect frames, which are
+ // marked not to wrap around objects.
+ std::vector< const SwFrm* > maFrmsNotToWrap;
+ // <--
+
+public:
+ // --> #i65250#
+ // - data structure to collect moving backward layout information
+ struct tMoveBwdLayoutInfoKey
+ {
+ // frame ID of flow frame
+ sal_uInt32 mnFrmId;
+ // position of new upper frame
+ SwTwips mnNewUpperPosX;
+ SwTwips mnNewUpperPosY;
+ // size of new upper frame
+ SwTwips mnNewUpperWidth;
+ SwTwips mnNewUpperHeight;
+ // free space in new upper frame
+ SwTwips mnFreeSpaceInNewUpper;
+
+ };
+private:
+ struct fMoveBwdLayoutInfoKeyHash
+ {
+ size_t operator()( const tMoveBwdLayoutInfoKey& p_key ) const
+ {
+ return p_key.mnFrmId;
+ }
+ };
+ struct fMoveBwdLayoutInfoKeyEq
+ {
+ bool operator()( const tMoveBwdLayoutInfoKey& p_key1,
+ const tMoveBwdLayoutInfoKey& p_key2 ) const
+ {
+ return p_key1.mnFrmId == p_key2.mnFrmId &&
+ p_key1.mnNewUpperPosX == p_key2.mnNewUpperPosX &&
+ p_key1.mnNewUpperPosY == p_key2.mnNewUpperPosY &&
+ p_key1.mnNewUpperWidth == p_key2.mnNewUpperWidth &&
+ p_key1.mnNewUpperHeight == p_key2.mnNewUpperHeight &&
+ p_key1.mnFreeSpaceInNewUpper == p_key2.mnFreeSpaceInNewUpper;
+ }
+ };
+ boost::unordered_map< const tMoveBwdLayoutInfoKey, sal_uInt16,
+ fMoveBwdLayoutInfoKeyHash,
+ fMoveBwdLayoutInfoKeyEq > maMoveBwdLayoutInfo;
+ // <--
+public:
+ SwLayouter();
+ ~SwLayouter();
+ void InsertEndnotes( SwSectionFrm* pSect );
+ void CollectEndnote( SwFtnFrm* pFtn );
+ sal_Bool HasEndnotes() const;
+
+ void LoopControl( SwPageFrm* pPage, sal_uInt8 nLoop );
+ void EndLoopControl();
+ void LoopingLouieLight( const SwDoc& rDoc, const SwTxtFrm& rFrm );
+
+ static void CollectEndnotes( SwDoc* pDoc, SwSectionFrm* pSect );
+ static sal_Bool Collecting( SwDoc* pDoc, SwSectionFrm* pSect, SwFtnFrm* pFtn );
+ static sal_Bool StartLoopControl( SwDoc* pDoc, SwPageFrm *pPage );
+
+ // --> #i28701#
+ static void ClearMovedFwdFrms( const SwDoc& _rDoc );
+ static void InsertMovedFwdFrm( const SwDoc& _rDoc,
+ const SwTxtFrm& _rMovedFwdFrmByObjPos,
+ const sal_uInt32 _nToPageNum );
+ static bool FrmMovedFwdByObjPos( const SwDoc& _rDoc,
+ const SwTxtFrm& _rTxtFrm,
+ sal_uInt32& _ornToPageNum );
+ // <--
+ // --> #i40155# - ummark given frame as to be moved forward.
+ static void RemoveMovedFwdFrm( const SwDoc& _rDoc,
+ const SwTxtFrm& _rTxtFrm );
+ // <--
+ // --> #i26945#
+ static bool DoesRowContainMovedFwdFrm( const SwDoc& _rDoc,
+ const SwRowFrm& _rRowFrm );
+ // <--
+
+ // --> #i35911#
+ static void ClearObjsTmpConsiderWrapInfluence( const SwDoc& _rDoc );
+ static void InsertObjForTmpConsiderWrapInfluence(
+ const SwDoc& _rDoc,
+ SwAnchoredObject& _rAnchoredObj );
+ // <--
+ // --> #i40155#
+ static void ClearFrmsNotToWrap( const SwDoc& _rDoc );
+ static void InsertFrmNotToWrap( const SwDoc& _rDoc,
+ const SwFrm& _rFrm );
+ static bool FrmNotToWrap( const IDocumentLayoutAccess& _rIDLA,
+ const SwFrm& _rFrm );
+ // <--
+ // --> #i65250#
+ static bool MoveBwdSuppressed( const SwDoc& p_rDoc,
+ const SwFlowFrm& p_rFlowFrm,
+ const SwLayoutFrm& p_rNewUpperFrm );
+ static void ClearMoveBwdLayoutInfo( const SwDoc& p_rDoc );
+ // <--
+};
+
+
+extern void LOOPING_LOUIE_LIGHT( bool bCondition, const SwTxtFrm& rTxtFrm );
+
+#endif //_LAYOUTER_HXX
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/inc/movedfwdfrmsbyobjpos.hxx b/sw/source/core/inc/movedfwdfrmsbyobjpos.hxx
new file mode 100644
index 000000000000..21120f6e5e7a
--- /dev/null
+++ b/sw/source/core/inc/movedfwdfrmsbyobjpos.hxx
@@ -0,0 +1,73 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+#ifndef _MOVEDFWDFRMSBYOBJPOS_HXX
+#define _MOVEDFWDFRMSBYOBJPOS_HXX
+
+#include <map>
+#include <sal/types.h>
+
+class SwTxtNode;
+class SwTxtFrm;
+// --> #i26945#
+class SwRowFrm;
+// <--
+
+typedef std::map< const SwTxtNode*, const sal_uInt32 > NodeMap;
+typedef std::map< const SwTxtNode*, const sal_uInt32 >::const_iterator NodeMapIter;
+typedef NodeMap::value_type NodeMapEntry;
+
+
+class SwMovedFwdFrmsByObjPos
+{
+ private:
+ NodeMap maMovedFwdFrms;
+
+ public:
+ SwMovedFwdFrmsByObjPos();
+ ~SwMovedFwdFrmsByObjPos();
+
+ void Insert( const SwTxtFrm& _rMovedFwdFrmByObjPos,
+ const sal_uInt32 _nToPageNum );
+
+ // --> #i40155#
+ void Remove( const SwTxtFrm& _rTxtFrm );
+ // <--
+
+ bool FrmMovedFwdByObjPos( const SwTxtFrm& _rTxtFrm,
+ sal_uInt32& _ornToPageNum ) const;
+
+ // --> #i26945#
+ bool DoesRowContainMovedFwdFrm( const SwRowFrm& _rRowFrm ) const;
+ // <--
+
+ void Clear() { maMovedFwdFrms.clear(); };
+};
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/inc/mvsave.hxx b/sw/source/core/inc/mvsave.hxx
new file mode 100644
index 000000000000..ed4a856de65a
--- /dev/null
+++ b/sw/source/core/inc/mvsave.hxx
@@ -0,0 +1,215 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+#ifndef SW_MVSAVE_HXX
+#define SW_MVSAVE_HXX
+
+#include <tools/string.hxx>
+#include <vcl/keycod.hxx>
+#include <svl/svarray.hxx>
+#include <IDocumentMarkAccess.hxx>
+#include <vector>
+
+namespace sfx2 {
+ class MetadatableUndo;
+}
+
+class SvNumberFormatter;
+class SvULongs;
+class SwDoc;
+class SwFmtAnchor;
+class SwFrmFmt;
+class SwIndex;
+class SwNodeIndex;
+class SwNodeRange;
+class SwPaM;
+class SwNode;
+struct SwPosition;
+
+namespace sw { namespace mark
+{
+ class IMark;
+
+ class SaveBookmark
+ {
+ public:
+ SaveBookmark(bool bSavePos,
+ bool bSaveOtherPos,
+ const ::sw::mark::IMark& rBkmk,
+ const SwNodeIndex& rMvPos,
+ const SwIndex* pIdx =0);
+ void SetInDoc(SwDoc* pDoc,
+ const SwNodeIndex&,
+ const SwIndex* pIdx =0);
+ IDocumentMarkAccess::MarkType GetOriginalBkmType() const
+ { return m_eOrigBkmType; }
+
+ private:
+ ::rtl::OUString m_aName;
+ ::rtl::OUString m_aShortName;
+ KeyCode m_aCode;
+ bool m_bSavePos;
+ bool m_bSaveOtherPos;
+ IDocumentMarkAccess::MarkType m_eOrigBkmType;
+ sal_uLong m_nNode1;
+ sal_uLong m_nNode2;
+ xub_StrLen m_nCntnt1;
+ xub_StrLen m_nCntnt2;
+ ::boost::shared_ptr< ::sfx2::MetadatableUndo > m_pMetadataUndo;
+ };
+}}
+
+#define SAVEFLY 1
+#define SAVEFLY_SPLIT 2
+
+void _DelBookmarks(const SwNodeIndex& rStt,
+ const SwNodeIndex& rEnd,
+ ::std::vector< ::sw::mark::SaveBookmark> * SaveBkmk =0,
+ const SwIndex* pSttIdx =0,
+ const SwIndex* pEndIdx =0);
+void _SaveCntntIdx( SwDoc* pDoc, sal_uLong nNode, xub_StrLen nCntnt,
+ SvULongs& rSaveArr, sal_uInt8 nSaveFly = 0 );
+void _RestoreCntntIdx( SwDoc* pDoc, SvULongs& rSaveArr,
+ sal_uLong nNode, xub_StrLen nOffset = 0,
+ sal_Bool bAuto = sal_False );
+void _RestoreCntntIdx( SvULongs& rSaveArr, const SwNode& rNd,
+ xub_StrLen nLen, xub_StrLen nCorrLen );
+
+
+/** data structure to temporarily hold fly anchor positions relative to some
+ * location. */
+struct _SaveFly
+{
+ sal_uLong nNdDiff; /// relative node difference
+ SwFrmFmt* pFrmFmt; /// the fly's frame format
+ sal_Bool bInsertPosition; /// if true, anchor _at_ insert position
+
+ _SaveFly( sal_uLong nNodeDiff, SwFrmFmt* pFmt, sal_Bool bInsert )
+ : nNdDiff( nNodeDiff ), pFrmFmt( pFmt ), bInsertPosition( bInsert )
+ { }
+};
+
+SV_DECL_VARARR( _SaveFlyArr, _SaveFly, 0, 10 )
+
+void _RestFlyInRange( _SaveFlyArr& rArr, const SwNodeIndex& rSttIdx,
+ const SwNodeIndex* pInsPos );
+void _SaveFlyInRange( const SwNodeRange& rRg, _SaveFlyArr& rArr );
+void _SaveFlyInRange( const SwPaM& rPam, const SwNodeIndex& rInsPos,
+ _SaveFlyArr& rArr, sal_Bool bMoveAllFlys );
+
+void DelFlyInRange( const SwNodeIndex& rMkNdIdx,
+ const SwNodeIndex& rPtNdIdx );
+
+
+class SwDataChanged
+{
+ const SwPaM* pPam;
+ const SwPosition* pPos;
+ SwDoc* pDoc;
+ sal_uLong nNode;
+ xub_StrLen nCntnt;
+ sal_uInt16 nType; // Insert/Move/Delete/... (UndoIds)
+
+public:
+ SwDataChanged( const SwPaM& rPam, sal_uInt16 nType );
+ SwDataChanged( SwDoc* pDoc, const SwPosition& rPos, sal_uInt16 nType );
+ ~SwDataChanged();
+
+ sal_uLong GetNode() const { return nNode; }
+ xub_StrLen GetCntnt() const { return nCntnt; }
+};
+
+
+// Funktions-Deklaration damit auch alles unter der CrsrShell mal die
+// Crsr verschieben kann
+// die Funktionen rufen nicht die SwDoc::Corr - Methoden!
+
+ // Setzt alle PaMs im Bereich vom Range nach NewPos
+void PaMCorrAbs( const SwPaM& rRange,
+ const SwPosition& rNewPos );
+
+ // Setzt alle PaMs in OldNode auf relative Pos
+void PaMCorrRel( const SwNodeIndex &rOldNode,
+ const SwPosition &rNewPos,
+ const xub_StrLen nOffset = 0 );
+
+
+// Hilfsklasse zum kopieren von absatzgebundenen Flys. Durch die Sortierung
+// nach der Ordnungsnummer wird versucht die layout seitige Anordnung
+// bei zu behalten
+class _ZSortFly
+{
+ const SwFrmFmt* pFmt;
+ const SwFmtAnchor* pAnchor;
+ sal_uInt32 nOrdNum;
+
+public:
+ _ZSortFly( const SwFrmFmt* pFrmFmt, const SwFmtAnchor* pFlyAnchor,
+ sal_uInt32 nArrOrdNum );
+ _ZSortFly& operator=( const _ZSortFly& rCpy )
+ {
+ pFmt = rCpy.pFmt, pAnchor = rCpy.pAnchor, nOrdNum = rCpy.nOrdNum;
+ return *this;
+ }
+
+ int operator==( const _ZSortFly& ) const { return sal_False; }
+ int operator<( const _ZSortFly& rCmp ) const
+ { return nOrdNum < rCmp.nOrdNum; }
+
+ const SwFrmFmt* GetFmt() const { return pFmt; }
+ const SwFmtAnchor* GetAnchor() const { return pAnchor; }
+};
+
+SV_DECL_VARARR_SORT( _ZSortFlys, _ZSortFly, 0, 10 )
+
+
+class SwTblNumFmtMerge
+{
+ SvNumberFormatter* pNFmt;
+public:
+ SwTblNumFmtMerge( const SwDoc& rSrc, SwDoc& rDest );
+ ~SwTblNumFmtMerge();
+};
+
+
+class _SaveRedlEndPosForRestore
+{
+ SvPtrarr* pSavArr;
+ SwNodeIndex* pSavIdx;
+ xub_StrLen nSavCntnt;
+
+ void _Restore();
+public:
+ _SaveRedlEndPosForRestore( const SwNodeIndex& rInsIdx, xub_StrLen nCntnt );
+ ~_SaveRedlEndPosForRestore();
+ void Restore() { if( pSavArr ) _Restore(); }
+};
+
+
+#endif // SW_MVSAVE_HXX
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/inc/node2lay.hxx b/sw/source/core/inc/node2lay.hxx
new file mode 100644
index 000000000000..ac83381f8c16
--- /dev/null
+++ b/sw/source/core/inc/node2lay.hxx
@@ -0,0 +1,84 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+#ifndef _NODE2LAY_HXX
+#define _NODE2LAY_HXX
+
+#include <tools/solar.h>
+
+/* --------------------------------------------------
+ * Die Klasse SwNode2Layout stellt die Verbindung von Nodes zum Layout her.
+ * Sie liefert einen intelligenten Iterator ueber die zum Node oder Nodebereich
+ * gehoerenden Frames. Je nach Zweck der Iteration, z.B. um vor oder hinter
+ * den Frames andere Frames einzufuegen, werden Master/Follows erkannt und nur
+ * die relevanten zurueckgegeben. Auch wiederholte Tabellenueberschriften werden
+ * beachtet.
+ * Es ist auch moeglich, ueber SectionNodes zu iterieren, die durch Schachtelung
+ * manchmal gar keinem SectionFrm direkt zugeordnet sind, manchmal aber sogar
+ * mehreren.
+ * SwNode2Layout ist ein Schnittstelle zwischen der aufrufenden Methode und
+ * einem SwClientIter, sie waehlt je nach Aufgabenstellung das richtige
+ * SwModify aus, erzeugt einen SwClientIter und filtert dessen Iterationen
+ * je nach Aufgabenstellung.
+ * Die Aufgabenstellung wird durch die Wahl des Ctors bestimmt.
+ * 1. Das Einsammeln der UpperFrms, damit spaeter RestoreUpperFrms wird,
+ * wird von MakeFrms gerufen, wenn es keinen PrevNext gibt, vor/hinter den
+ * die Frames gehaengt werden koennen.
+ * 2. Die Lieferung der Frames hinter/vor die die neuen Frames eines Nodes
+ * gehaengt werden muessen, ebenfalls von MakeFrms gerufen.
+ * --------------------------------------------------*/
+
+class SwNode2LayImpl;
+class SwFrm;
+class SwLayoutFrm;
+class SwNode;
+class SwNodes;
+class Point;
+struct SwPosition;
+
+class SwNode2Layout
+{
+ SwNode2LayImpl *pImpl;
+public:
+ // Dieser Ctor ist zum Einsammeln der UpperFrms gedacht.
+ SwNode2Layout( const SwNode& rNd );
+ // Dieser Ctor ist fuer das Einfuegen vor oder hinter rNd gedacht,
+ // nIdx ist der Index des einzufuegenden Nodes
+ SwNode2Layout( const SwNode& rNd, sal_uLong nIdx );
+ ~SwNode2Layout();
+ SwFrm* NextFrm();
+ SwLayoutFrm* UpperFrm( SwFrm* &rpFrm, const SwNode& rNode );
+ void RestoreUpperFrms( SwNodes& rNds, sal_uLong nStt, sal_uLong nEnd );
+
+ SwFrm *GetFrm( const Point* pDocPos = 0,
+ const SwPosition *pPos = 0,
+ const sal_Bool bCalcFrm = sal_True ) const;
+};
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/inc/noteurl.hxx b/sw/source/core/inc/noteurl.hxx
new file mode 100644
index 000000000000..42db71134c45
--- /dev/null
+++ b/sw/source/core/inc/noteurl.hxx
@@ -0,0 +1,78 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef _NOTEURL_HXX
+#define _NOTEURL_HXX
+
+
+#include <svl/svarray.hxx>
+#include <tools/string.hxx>
+#include "swrect.hxx"
+
+class ImageMap;
+class MapMode;
+
+class SwURLNote
+{
+ String aURL;
+ String aTarget;
+ SwRect aRect;
+public:
+ SwURLNote( const String& rURL, const String& rTarget, const SwRect& rRect )
+ : aURL( rURL ), aTarget( rTarget ), aRect( rRect )
+ {}
+ const String& GetURL() const { return aURL; }
+ const String& GetTarget() const { return aTarget; }
+ const SwRect& GetRect() const { return aRect; }
+ sal_Bool operator==( const SwURLNote& rSwURLNote ) const
+ { return aRect == rSwURLNote.aRect; }
+};
+
+typedef SwURLNote* SwURLNotePtr;
+SV_DECL_PTRARR_DEL(SwURLNoteList, SwURLNotePtr, 0, 5)
+
+class SwNoteURL
+{
+ SwURLNoteList aList;
+public:
+ SwNoteURL() {}
+ sal_uInt16 Count() const { return aList.Count(); }
+ void InsertURLNote( const String& rURL, const String& rTarget,
+ const SwRect& rRect );
+ const SwURLNote& GetURLNote( sal_uInt16 nPos ) const
+ { return *aList.GetObject( nPos ); }
+ void FillImageMap( ImageMap* pMap, const Point& rPos, const MapMode& rMap );
+};
+
+// globale Variable, in NoteURL.Cxx angelegt
+extern SwNoteURL *pNoteURL;
+
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/inc/notxtfrm.hxx b/sw/source/core/inc/notxtfrm.hxx
new file mode 100644
index 000000000000..17494b01a7ea
--- /dev/null
+++ b/sw/source/core/inc/notxtfrm.hxx
@@ -0,0 +1,80 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+#ifndef SW_NOTXTFRM_HXX
+#define SW_NOTXTFRM_HXX
+
+#include <cntfrm.hxx>
+
+class SwNoTxtNode;
+class OutputDevice;
+class SwBorderAttrs;
+class Bitmap;
+struct SwCrsrMoveState;
+
+class SwNoTxtFrm: public SwCntntFrm
+{
+ friend void _FrmFinit();
+
+ short nWeight; // importance of the graphic
+
+ const Size& GetSize() const;
+
+ void InitCtor();
+
+ void Format ( const SwBorderAttrs *pAttrs = 0 );
+ void PaintCntnt ( OutputDevice*, const SwRect&, const SwRect& ) const;
+ void PaintPicture( OutputDevice*, const SwRect& ) const;
+protected:
+ virtual void MakeAll();
+ virtual void Modify( const SfxPoolItem*, const SfxPoolItem* );
+public:
+ SwNoTxtFrm( SwNoTxtNode * const, SwFrm* );
+ ~SwNoTxtFrm();
+
+ virtual void Paint( SwRect const&,
+ SwPrintData const*const pPrintData = NULL ) const;
+ virtual sal_Bool GetCharRect( SwRect &, const SwPosition&,
+ SwCrsrMoveState* = 0) const;
+ sal_Bool GetCrsrOfst(SwPosition* pPos, Point& aPoint,
+ SwCrsrMoveState* = 0) const;
+
+ const Size &GetGrfSize() const { return GetSize(); }
+ void GetGrfArea( SwRect &rRect, SwRect * = 0, sal_Bool bMirror = sal_True ) const;
+
+ sal_Bool IsTransparent() const;
+
+ void StopAnimation( OutputDevice* = 0 ) const;
+ sal_Bool HasAnimation() const;
+
+ // Routine for the graphics cache
+ sal_uInt16 GetWeight() { return nWeight; }
+};
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/inc/objectformatter.hxx b/sw/source/core/inc/objectformatter.hxx
new file mode 100644
index 000000000000..c78c6f7775c5
--- /dev/null
+++ b/sw/source/core/inc/objectformatter.hxx
@@ -0,0 +1,212 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+#ifndef _OBJECTFORMATTER_HXX
+#define _OBJECTFORMATTER_HXX
+
+#include <sal/types.h>
+
+class SwFrm;
+// #i26945#
+class SwTxtFrm;
+class SwLayoutFrm;
+class SwPageFrm;
+class SwAnchoredObject;
+class SwLayAction;
+// OD 2004-10-04 #i26945#
+class SwPageNumAndTypeOfAnchors;
+
+// -----------------------------------------------------------------------------
+// #i28701#
+// Format floating screen objects, which are anchored at the given anchor frame
+// and registered at the given page frame.
+// -----------------------------------------------------------------------------
+class SwObjectFormatter
+{
+ private:
+ // page frame, at which the floating screen objects are registered.
+ const SwPageFrm& mrPageFrm;
+
+ // boolean, indicating that only as-character anchored objects have to
+ // be formatted.
+ bool mbFormatOnlyAsCharAnchored;
+
+ // value of document compatibility option 'Consider wrapping style on
+ // object positioning'
+ const bool mbConsiderWrapOnObjPos;
+
+ // layout action calling the format of the floating screen objects
+ SwLayAction* mpLayAction;
+
+ // data structure to collect page number of object's 'anchor'
+ // #i26945#
+ SwPageNumAndTypeOfAnchors* mpPgNumAndTypeOfAnchors;
+
+ /** helper method for method <_FormatObj(..)> - performs the intrinsic
+ format of the layout of the given layout frame and all its lower
+ layout frames.
+
+ #i28701#
+ IMPORTANT NOTE:
+ Method corresponds to methods <SwLayAction::FormatLayoutFly(..)> and
+ <SwLayAction::FormatLayout(..)>. Thus, its code for the formatting have
+ to be synchronised.
+ */
+ void _FormatLayout( SwLayoutFrm& _rLayoutFrm );
+
+ /** helper method for method <_FormatObj(..)> - performs the intrinsic
+ format of the content of the given floating screen object.
+
+ #i28701#
+ */
+ void _FormatObjCntnt( SwAnchoredObject& _rAnchoredObj );
+
+ protected:
+ SwObjectFormatter( const SwPageFrm& _rPageFrm,
+ SwLayAction* _pLayAction = 0L,
+ const bool _bCollectPgNumOfAnchors = false );
+
+ static SwObjectFormatter* CreateObjFormatter( SwFrm& _rAnchorFrm,
+ const SwPageFrm& _rPageFrm,
+ SwLayAction* _pLayAction );
+
+ virtual SwFrm& GetAnchorFrm() = 0;
+
+ inline const SwPageFrm& GetPageFrm() const
+ {
+ return mrPageFrm;
+ }
+
+ inline bool ConsiderWrapOnObjPos() const
+ {
+ return mbConsiderWrapOnObjPos;
+ }
+
+ inline SwLayAction* GetLayAction()
+ {
+ return mpLayAction;
+ }
+
+ /** method to restrict the format of floating screen objects to
+ as-character anchored ones
+ */
+ inline void SetFormatOnlyAsCharAnchored()
+ {
+ mbFormatOnlyAsCharAnchored = true;
+ }
+
+ inline bool FormatOnlyAsCharAnchored() const
+ {
+ return mbFormatOnlyAsCharAnchored;
+ }
+
+ /** performs the intrinsic format of a given floating screen object and its content.
+
+ #i28701#
+ */
+ void _FormatObj( SwAnchoredObject& _rAnchoredObj );
+
+ /** invokes the intrinsic format method for all floating screen objects,
+ anchored at anchor frame on the given page frame
+
+ #i28701#
+ #i26945# - for format of floating screen objects for
+ follow text frames, the 'master' text frame is passed to the method.
+ Thus, the objects, whose anchor character is inside the follow text
+ frame can be formatted.
+
+ @param _pMasterTxtFrm
+ input parameter - pointer to 'master' text frame. default value: NULL
+ */
+ bool _FormatObjsAtFrm( SwTxtFrm* _pMasterTxtFrm = 0L );
+
+ /** accessor to collected anchored object
+
+ #i28701#
+ */
+ SwAnchoredObject* GetCollectedObj( const sal_uInt32 _nIndex );
+
+ /** accessor to 'anchor' page number of collected anchored object
+
+ #i28701#
+ */
+ sal_uInt32 GetPgNumOfCollected( const sal_uInt32 _nIndex );
+
+ /** accessor to 'anchor' type of collected anchored object
+
+ #i26945#
+ */
+ bool IsCollectedAnchoredAtMaster( const sal_uInt32 _nIndex );
+
+ /** accessor to total number of collected anchored objects
+
+ #i28701#
+ */
+ sal_uInt32 CountOfCollected();
+
+ public:
+ virtual ~SwObjectFormatter();
+
+ /** intrinsic method to format a certain floating screen object
+
+ #i40147# - add parameter <_bCheckForMovedFwd>
+
+ @param _rAnchoredObj
+ input parameter - anchored object, which have to be formatted.
+
+ @param _bCheckForMovedFwd
+ input parameter - boolean indicating, that after a successful
+ format of the anchored object the anchor frame has to be checked,
+ if it would moved forward due to the positioning of the anchored object.
+ default value: false
+ value only considered, if wrapping style influence has to be
+ considered for the positioning of the anchored object.
+ */
+ virtual bool DoFormatObj( SwAnchoredObject& _rAnchoredObj,
+ const bool _bCheckForMovedFwd = false ) = 0;
+
+ /** intrinsic method to format all floating screen objects
+ */
+ virtual bool DoFormatObjs() = 0;
+
+ /** method to format all floating screen objects at the given anchor frame
+ */
+ static bool FormatObjsAtFrm( SwFrm& _rAnchorFrm,
+ const SwPageFrm& _rPageFrm,
+ SwLayAction* _pLayAction = 0L );
+
+ /** method to format a given floating screen object
+ */
+ static bool FormatObj( SwAnchoredObject& _rAnchoredObj,
+ SwFrm* _pAnchorFrm = 0L,
+ const SwPageFrm* _pPageFrm = 0L,
+ SwLayAction* _pLayAction = 0L );
+};
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/inc/observablethread.hxx b/sw/source/core/inc/observablethread.hxx
new file mode 100644
index 000000000000..e51a06e76420
--- /dev/null
+++ b/sw/source/core/inc/observablethread.hxx
@@ -0,0 +1,106 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+#ifndef _OBSERVABLETHREAD_HXX
+#define _OBSERVABLETHREAD_HXX
+
+#include <osl/thread.hxx>
+#include <rtl/ref.hxx>
+#include <osl/interlck.h>
+
+#include <boost/weak_ptr.hpp>
+#include <ithreadlistenerowner.hxx>
+
+/** class for an observable thread
+
+ OD 2007-01-29 #i73788#
+ Note: A thread is ref-counted. Thus, an instance of a derived class has to
+ to be hold via a reference. The thread itself assures during its execution,
+ that the ref-count is increased. Its execution starts with its <run()> method
+ and ends with its <onTerminated()> method.
+ Note: A thread can be only observed by one or none thread observer in order
+ to notify, that the thread has finished its work.
+
+ @author OD
+*/
+class ObservableThread : public osl::Thread,
+ public rtl::IReference
+{
+ public:
+
+ virtual ~ObservableThread();
+
+ void SetListener( boost::weak_ptr< IFinishedThreadListener > pThreadListener,
+ const oslInterlockedCount nThreadID );
+
+ // IReference
+ virtual oslInterlockedCount SAL_CALL acquire();
+ virtual oslInterlockedCount SAL_CALL release();
+
+ protected:
+
+ ObservableThread();
+
+ /** intrinsic function of the thread
+
+ Important note:
+ Do not override this method again. Instead override <threadFunction()>.
+ Otherwise, it's not guaranteed, that its ref-count is increased
+ during the execution of the thread.
+
+ @author OD
+ */
+ virtual void SAL_CALL run();
+
+ virtual void threadFunction() = 0;
+
+ /** method called, when thread has finished its work
+
+ Important note:
+ Do not override this method again. Instead override <threadFinished()>.
+ Otherwise, it's not guaranteed, that the ref-count is decreased at
+ the end of its execution and that the observer is notified, that
+ the thread has finished its work.
+
+ @author OD
+ */
+ virtual void SAL_CALL onTerminated();
+
+ virtual void threadFinished();
+
+ private:
+
+ oslInterlockedCount mnRefCount;
+
+ oslInterlockedCount mnThreadID;
+
+ boost::weak_ptr< IFinishedThreadListener > mpThreadListener;
+
+};
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/inc/pagedeschint.hxx b/sw/source/core/inc/pagedeschint.hxx
new file mode 100644
index 000000000000..b18ed39e3315
--- /dev/null
+++ b/sw/source/core/inc/pagedeschint.hxx
@@ -0,0 +1,46 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef _PAGEDESCHINT_HXX
+#define _PAGEDESCHINT_HXX
+
+#include <svl/hint.hxx>
+
+class SwPageDesc;
+
+class SwPageDescHint : public SfxHint
+{
+ SwPageDesc* pPageDesc;
+public:
+ SwPageDescHint( SwPageDesc* p )
+ : pPageDesc(p)
+ {}
+
+ SwPageDesc* GetPageDesc() const { return const_cast<SwPageDesc*>(pPageDesc); }
+};
+
+#endif
diff --git a/sw/source/core/inc/pagefrm.hrc b/sw/source/core/inc/pagefrm.hrc
new file mode 100644
index 000000000000..b8f89e091c15
--- /dev/null
+++ b/sw/source/core/inc/pagefrm.hrc
@@ -0,0 +1,45 @@
+/*
+ * Version: MPL 1.1 / GPLv3+ / LGPLv3+
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License or as specified alternatively below. You may obtain a copy of
+ * the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Initial Developer of the Original Code is
+ * Sébastien Le Ray <sebastien-libreoffice@orniz.org>
+ * Portions created by the Initial Developer are Copyright (C) 2010 the
+ * Initial Developer. All Rights Reserved.
+ *
+ * For minor contributions see the git repository.
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 3 or later (the "GPLv3+"), or
+ * the GNU Lesser General Public License Version 3 or later (the "LGPLv3+"),
+ * in which case the provisions of the GPLv3+ or the LGPLv3+ are applicable
+ * instead of those above.
+ */
+
+#ifndef _PAGEFRM_HRC
+#define _PAGEFRM_HRC
+
+#include "rcid.hrc"
+
+// Bitmaps for page shadow
+#define BMP_PAGE_SHADOW_MASK RC_PAGEFRM_BEGIN + 0
+
+
+// If you add resources, don't forget to update this
+#define PAGEFRM_ACT_END BMP_PAGE_SHADOW_MASK
+
+// Sanity check
+#if PAGEFRM_ACT_END > RC_PAGEFRM_END
+#error Not enough room for pagefrm resource in #file:#line
+#endif
+
+#endif
diff --git a/sw/source/core/inc/pagefrm.hxx b/sw/source/core/inc/pagefrm.hxx
new file mode 100644
index 000000000000..1fb456dea39d
--- /dev/null
+++ b/sw/source/core/inc/pagefrm.hxx
@@ -0,0 +1,490 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+#ifndef _PAGEFRM_HXX
+#define _PAGEFRM_HXX
+
+
+#include <svl/svarray.hxx>
+
+#include "ftnboss.hxx"
+#include <tools/mempool.hxx>
+
+#include <SidebarWindowsTypes.hxx>
+
+class SwFlyFrm;
+class SwFlyFrmFmt;
+class SwPageDesc;
+class SwCntntFrm;
+struct SwPosition;
+struct SwCrsrMoveState;
+class SdrObject;
+class SwAttrSetChg;
+class Font;
+
+// #i28701# - replaced by class <SwSortedObjs>
+class SwSortedObjs;
+// #i28701#
+class SwAnchoredObject;
+
+enum SwPageChg
+{
+ CHG_NEWPAGE,
+ CHG_CUTPAGE,
+ CHG_CHGPAGE
+};
+
+class SwPageFrm: public SwFtnBossFrm
+{
+ friend class SwFrm;
+
+ // #i28701# - use <SwSortedObjs>
+ SwSortedObjs *pSortedObjs;
+
+ SwPageDesc *pDesc; //PageDesc der die Seite beschreibt.
+
+ sal_uInt16 nPhyPageNum; //Physikalische Seitennummer.
+
+ sal_Bool bInvalidCntnt :1;
+ sal_Bool bInvalidLayout :1;
+ sal_Bool bInvalidFlyCntnt :1;
+ sal_Bool bInvalidFlyLayout :1;
+ sal_Bool bInvalidFlyInCnt :1;
+ sal_Bool bFtnPage :1; //Diese Seite ist fuer Dokumentende-Fussnoten.
+ sal_Bool bEmptyPage :1; //Dies ist eine explizite Leerseite
+ sal_Bool bEndNotePage :1; //'Fussnotenseite' fuer Endnoten
+ sal_Bool bInvalidSpelling :1; //Das Online-Spelling ist gefordert
+ sal_Bool bInvalidSmartTags :1; //checking for smarttags is needed // SMARTTAGS
+ sal_Bool bInvalidAutoCmplWrds :1; //Auto-Complete Wordliste aktualisieren
+ sal_Bool bInvalidWordCount :1;
+ sal_Bool bHasGrid :1; // Grid for Asian layout
+
+ // #i28701# - boolean, indicating that layout of page frame
+ // is in progress.
+ bool mbLayoutInProgress;
+
+ static const sal_Int8 mnShadowPxWidth;
+
+ void _UpdateAttr( const SfxPoolItem*, const SfxPoolItem*, sal_uInt8 &,
+ SwAttrSetChg *pa = 0, SwAttrSetChg *pb = 0 );
+
+ // Anpassen der max. Fussnotenhoehen in den einzelnen Spalten
+ void SetColMaxFtnHeight();
+
+ /** determine rectangle for horizontal page shadow
+
+ #i9719#
+
+ @param _rPageRect
+ input parameter - constant instance reference of the page rectangle.
+ Generally, it's the frame area of the page, but for empty pages in print
+ preview, this parameter is useful.
+
+ @param _pViewShell
+ input parameter - instance of the view shell, for which the rectangle
+ has to be generated.
+
+ @param _orBottomShadowRect
+ output parameter - instance reference of the bottom shadow rectangle for
+ the given page rectangle
+ */
+
+ static void GetHorizontalShadowRect( const SwRect& _rPageRect,
+ const ViewShell* _pViewShell,
+ SwRect& _orBottomShadowRect,
+ bool bPaintLeftShadow,
+ bool bPaintRightShadow,
+ bool bRightSidebar );
+
+ /** adds the sidebar used for notes to right and left border
+ #i6193#
+
+ @param aRect
+ input parameter - current rect, we change borders if we want a sidebar
+
+ @param _pViewShell
+ input parameter - instance of the view shell, for which the rectangle
+ has to be generated.
+
+ @param bPx
+ input parameter - if set to true, we add in pixel
+ */
+ static void AddSidebarBorders( Rectangle& aRect, ViewShell* _pViewShell, bool bRight, bool bPx = false);
+ static void AddSidebarBorders( SwRect& aRect, ViewShell* _pViewShell, bool bRight, bool bPx = false);
+
+protected:
+ virtual void MakeAll();
+ virtual void Modify( const SfxPoolItem*, const SfxPoolItem* );
+
+public:
+ DECL_FIXEDMEMPOOL_NEWDEL(SwPageFrm)
+
+ SwPageFrm( SwFrmFmt*, SwFrm*, SwPageDesc* );
+ ~SwPageFrm();
+
+ //public, damit die ViewShell beim Umschalten vom BrowseMode darauf
+ //zugreifen kann.
+ void PrepareHeader(); //Kopf-/Fusszeilen anlegen/entfernen.
+ void PrepareFooter();
+
+ const SwSortedObjs *GetSortedObjs() const { return pSortedObjs; }
+ SwSortedObjs *GetSortedObjs() { return pSortedObjs; }
+
+ // #i28701# - new methods to append/remove drawing objects
+ void AppendDrawObjToPage( SwAnchoredObject& _rNewObj );
+ void RemoveDrawObjFromPage( SwAnchoredObject& _rToRemoveObj );
+
+ void AppendFlyToPage( SwFlyFrm *pNew );
+ void RemoveFlyFromPage( SwFlyFrm *pToRemove );
+ void MoveFly( SwFlyFrm *pToMove, SwPageFrm *pDest );//optimiertes Remove/Append
+
+ void SetPageDesc( SwPageDesc *, SwFrmFmt * );
+ SwPageDesc *GetPageDesc() { return pDesc; }
+ const SwPageDesc *GetPageDesc() const { return pDesc; }
+ SwPageDesc *FindPageDesc();
+
+ SwCntntFrm *FindLastBodyCntnt();
+ inline SwCntntFrm *FindFirstBodyCntnt();
+ inline const SwCntntFrm *FindFirstBodyCntnt() const;
+ inline const SwCntntFrm *FindLastBodyCntnt() const;
+
+ SwRect GetBoundRect() const;
+
+ //Spezialisiertes GetCntntPos() fuer Felder in Rahmen.
+ void GetCntntPosition( const Point &rPt, SwPosition &rPos ) const;
+
+ sal_Bool IsEmptyPage() const { return bEmptyPage; } //explizite Leerseite.
+
+ void UpdateFtnNum();
+
+ //Immer nach dem Paste rufen. Erzeugt die Seitengeb. Rahmen und Formatiert
+ //generischen Inhalt.
+ void PreparePage( sal_Bool bFtn );
+
+ //Schickt an alle ContentFrames ein Prepare wg. geaenderter Registervorlage
+ void PrepareRegisterChg();
+
+ // #i50432# - adjust method description and synopsis.
+ // Appends a fly frame - the given one or a new one - at the page frame.
+ // Needed for <Modify> and <MakeFrms>
+ // - return value not needed any more
+ // - second parameter is of type <SwFlyFrmFmt*>
+ // - third parameter only needed for assertion, but calling method assures
+ // this assertion. Thus, delete it.
+ void PlaceFly( SwFlyFrm* pFly, SwFlyFrmFmt* pFmt );
+
+ virtual sal_Bool GetCrsrOfst( SwPosition *, Point&,
+ SwCrsrMoveState* = 0 ) const;
+ // erfrage vom Client Informationen
+ virtual sal_Bool GetInfo( SfxPoolItem& ) const;
+
+ virtual void Cut();
+ virtual void Paste( SwFrm* pParent, SwFrm* pSibling = 0 );
+ virtual void CheckDirection( sal_Bool bVert );
+ void CheckGrid( sal_Bool bInvalidate );
+ void PaintGrid( OutputDevice* pOut, SwRect &rRect ) const;
+ sal_Bool HasGrid() const { return bHasGrid; }
+
+ //Zeilennummern usw malen
+ void RefreshExtraData( const SwRect & ) const;
+
+ //Hilfslinien malen.
+ void RefreshSubsidiary( const SwRect& ) const;
+
+ //Fussnotenschnittstelle
+ sal_Bool IsFtnPage() const { return bFtnPage; }
+ sal_Bool IsEndNotePage() const { return bEndNotePage; }
+ void SetFtnPage( sal_Bool b ) { bFtnPage = b; }
+ void SetEndNotePage( sal_Bool b ) { bEndNotePage = b; }
+
+ inline sal_uInt16 GetPhyPageNum() const { return nPhyPageNum;}
+ inline void SetPhyPageNum( sal_uInt16 nNum ) { nPhyPageNum = nNum;}
+ inline void DecrPhyPageNum() { --nPhyPageNum; }
+ inline void IncrPhyPageNum() { ++nPhyPageNum; }
+
+ //Validieren, invalidieren und abfragen des Status der Seite.
+ //Layout/Cntnt und jeweils Fly/nicht Fly werden getrennt betrachtet.
+ inline void InvalidateFlyLayout() const;
+ inline void InvalidateFlyCntnt() const;
+ inline void InvalidateFlyInCnt() const;
+ inline void InvalidateLayout() const;
+ inline void InvalidateCntnt() const;
+ inline void InvalidateSpelling() const;
+ inline void InvalidateSmartTags() const;
+ inline void InvalidateAutoCompleteWords() const;
+ inline void InvalidateWordCount() const;
+ inline void ValidateFlyLayout() const;
+ inline void ValidateFlyCntnt() const;
+ inline void ValidateFlyInCnt() const;
+ inline void ValidateLayout() const;
+ inline void ValidateCntnt() const;
+ inline void ValidateSpelling() const;
+ inline void ValidateSmartTags() const; // SMARTTAGS
+ inline void ValidateAutoCompleteWords() const;
+ inline void ValidateWordCount() const;
+ inline sal_Bool IsInvalid() const;
+ inline sal_Bool IsInvalidFly() const;
+ sal_Bool IsRightShadowNeeded() const;
+ sal_Bool IsLeftShadowNeeded() const;
+ sal_Bool IsInvalidFlyLayout() const { return bInvalidFlyLayout; }
+ sal_Bool IsInvalidFlyCntnt() const { return bInvalidFlyCntnt; }
+ sal_Bool IsInvalidFlyInCnt() const { return bInvalidFlyInCnt; }
+ sal_Bool IsInvalidLayout() const { return bInvalidLayout; }
+ sal_Bool IsInvalidCntnt() const { return (bInvalidCntnt || bInvalidFlyInCnt); }
+ sal_Bool IsInvalidSpelling() const { return bInvalidSpelling; }
+ sal_Bool IsInvalidSmartTags() const { return bInvalidSmartTags; } // SMARTTAGS
+ sal_Bool IsInvalidAutoCompleteWords() const { return bInvalidAutoCmplWrds; }
+ sal_Bool IsInvalidWordCount() const { return bInvalidWordCount; }
+
+ /** SwPageFrm::GetDrawBackgrdColor
+
+ determine the color, that is respectively will be drawn as background
+ for the page frame.
+
+ @return reference to an instance of class Color
+ */
+ const Color& GetDrawBackgrdColor() const;
+
+ /** paint margin area of a page
+
+ implement paint of margin area; margin area will be painted for a
+ view shell with a window and if the document is not in online layout.
+
+ @param _rOutputRect
+ input parameter - constant instance reference of the rectangle, for
+ which an output has to be generated.
+
+ @param _pViewShell
+ input parameter - instance of the view shell, on which the output
+ has to be generated.
+ */
+ void PaintMarginArea( const SwRect& _rOutputRect,
+ ViewShell* _pViewShell ) const;
+
+ /** paint page border and shadow
+
+ #i9719#
+ implement paint of page border and shadow
+
+ @param _rPageRect
+ input parameter - constant instance reference of the page rectangle.
+ Generally, it's the frame area of the page, but for empty pages in print
+ preview, this parameter is useful.
+
+ @param _pViewShell
+ input parameter - instance of the view shell, on which the output
+ has to be generated.
+
+ @param bPaintRightShadow
+ Should we paint shadow on the right or not (used in book mode)
+
+ @param bFullBottomShadow
+ Should we have a bottom shadow of the same size as the pages or
+ not (for right pages in book mode in a LTR environment).
+
+ @param bRightSidebar
+ Is the note sidebar on the right or not (used to adjust the
+ shadow with & position).
+ */
+ static void PaintBorderAndShadow( const SwRect& _rPageRect,
+ const ViewShell* _pViewShell,
+ bool bPaintLeftShadow,
+ bool bPaintRightShadow,
+ bool bRightSidebar );
+
+ /** get bound rectangle of border and shadow for repaints
+
+ #i9719#
+
+ @param _rPageRect
+ input parameter - constant instance reference of the page rectangle.
+ Generally, it's the frame area of the page, but for empty pages in print
+ preview, this parameter is useful.
+
+ @param _pViewShell
+ input parameter - instance of the view shell, for which the rectangle
+ has to be generated.
+
+ @param _orBorderAndShadowBoundRect
+ output parameter - instance reference of the bounded border and shadow
+ rectangle for the given page rectangle
+ */
+ static void GetBorderAndShadowBoundRect( const SwRect& _rPageRect,
+ const ViewShell* _pViewShell,
+ SwRect& _orBorderAndShadowBoundRect,
+ const bool bLeftShadow,
+ const bool bRightShadow,
+ const bool bRightSidebar
+ );
+
+ static void PaintNotesSidebar(const SwRect& _rPageRect, ViewShell* _pViewShell, sal_uInt16 nPageNum, bool bRight);
+ static void PaintNotesSidebarArrows(const Point &aMiddleFirst, const Point &aMiddleSecond, ViewShell* _pViewShell, const Color aColorUp, const Color aColorDown);
+ /**
+ asks the page on which side a margin should be shown, e.g for notes
+ returns true for left side, false for right side
+ */
+ sw::sidebarwindows::SidebarPosition SidebarPosition() const;
+
+ virtual bool FillSelection( SwSelectionList& rList, const SwRect& rRect ) const;
+
+ inline sal_Int8 ShadowPxWidth() const
+ {
+ return mnShadowPxWidth;
+ }
+
+ const SwRect PrtWithoutHeaderAndFooter() const;
+
+ // #i28701#
+ inline bool IsLayoutInProgress() const
+ {
+ return mbLayoutInProgress;
+ }
+ inline void SetLayoutInProgress( const bool _bLayoutInProgress )
+ {
+ mbLayoutInProgress = _bLayoutInProgress;
+ }
+
+ // in case this is am empty page, this function returns the 'reference' page
+ const SwPageFrm& GetFormatPage() const;
+
+ // return font used to paint the "empty page" string
+ static const Font& GetEmptyPageFont();
+
+ static SwTwips GetSidebarBorderWidth( const ViewShell* );
+};
+
+inline SwCntntFrm *SwPageFrm::FindFirstBodyCntnt()
+{
+ SwLayoutFrm *pBody = FindBodyCont();
+ return pBody ? pBody->ContainsCntnt() : 0;
+}
+inline const SwCntntFrm *SwPageFrm::FindFirstBodyCntnt() const
+{
+ const SwLayoutFrm *pBody = FindBodyCont();
+ return pBody ? pBody->ContainsCntnt() : 0;
+}
+inline const SwCntntFrm *SwPageFrm::FindLastBodyCntnt() const
+{
+ return ((SwPageFrm*)this)->FindLastBodyCntnt();
+}
+inline void SwPageFrm::InvalidateFlyLayout() const
+{
+ ((SwPageFrm*)this)->bInvalidFlyLayout = sal_True;
+}
+inline void SwPageFrm::InvalidateFlyCntnt() const
+{
+ ((SwPageFrm*)this)->bInvalidFlyCntnt = sal_True;
+}
+inline void SwPageFrm::InvalidateFlyInCnt() const
+{
+ ((SwPageFrm*)this)->bInvalidFlyInCnt = sal_True;
+}
+inline void SwPageFrm::InvalidateLayout() const
+{
+ ((SwPageFrm*)this)->bInvalidLayout = sal_True;
+}
+inline void SwPageFrm::InvalidateCntnt() const
+{
+ ((SwPageFrm*)this)->bInvalidCntnt = sal_True;
+}
+inline void SwPageFrm::InvalidateSpelling() const
+{
+ ((SwPageFrm*)this)->bInvalidSpelling = sal_True;
+}
+// SMARTTAGS
+inline void SwPageFrm::InvalidateSmartTags() const
+{
+ ((SwPageFrm*)this)->bInvalidSmartTags = sal_True;
+}
+inline void SwPageFrm::InvalidateAutoCompleteWords() const
+{
+ ((SwPageFrm*)this)->bInvalidAutoCmplWrds = sal_True;
+}
+inline void SwPageFrm::InvalidateWordCount() const
+{
+ ((SwPageFrm*)this)->bInvalidWordCount = sal_True;
+}
+inline void SwPageFrm::ValidateFlyLayout() const
+{
+ ((SwPageFrm*)this)->bInvalidFlyLayout = sal_False;
+}
+inline void SwPageFrm::ValidateFlyCntnt() const
+{
+ ((SwPageFrm*)this)->bInvalidFlyCntnt = sal_False;
+}
+inline void SwPageFrm::ValidateFlyInCnt() const
+{
+ ((SwPageFrm*)this)->bInvalidFlyInCnt = sal_False;
+}
+inline void SwPageFrm::ValidateLayout() const
+{
+ ((SwPageFrm*)this)->bInvalidLayout = sal_False;
+}
+inline void SwPageFrm::ValidateCntnt() const
+{
+ ((SwPageFrm*)this)->bInvalidCntnt = sal_False;
+}
+inline void SwPageFrm::ValidateSpelling() const
+{
+ ((SwPageFrm*)this)->bInvalidSpelling = sal_False;
+}
+// SMARTTAGS
+inline void SwPageFrm::ValidateSmartTags() const
+{
+ ((SwPageFrm*)this)->bInvalidSmartTags = sal_False;
+}
+inline void SwPageFrm::ValidateAutoCompleteWords() const
+{
+ ((SwPageFrm*)this)->bInvalidAutoCmplWrds = sal_False;
+}
+inline void SwPageFrm::ValidateWordCount() const
+{
+ ((SwPageFrm*)this)->bInvalidWordCount = sal_False;
+}
+
+inline sal_Bool SwPageFrm::IsInvalid() const
+{
+ return (bInvalidCntnt || bInvalidLayout || bInvalidFlyInCnt);
+}
+inline sal_Bool SwPageFrm::IsInvalidFly() const
+{
+ return bInvalidFlyLayout || bInvalidFlyCntnt;
+}
+
+#define GETGRID( pPage ) const SwTextGridItem *pGrid = NULL; \
+ {if( pPage && pPage->HasGrid() && GRID_NONE==(pGrid=(SwTextGridItem*)&pPage->\
+ GetPageDesc()->GetMaster().GetFmtAttr(RES_TEXTGRID))->GetGridType() ) \
+ pGrid = NULL;}
+
+#define GETGRIDWIDTH( pGrid , pDoc ) pDoc->IsSquaredPageMode() ? \
+ pGrid->GetBaseHeight(): pGrid->GetBaseWidth()
+
+
+
+#endif //_PAGEFRM_HXX
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/inc/pamtyp.hxx b/sw/source/core/inc/pamtyp.hxx
new file mode 100644
index 000000000000..f124abaccf27
--- /dev/null
+++ b/sw/source/core/inc/pamtyp.hxx
@@ -0,0 +1,105 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef _PAMTYP_HXX
+#define _PAMTYP_HXX
+
+#include <svtools/txtcmp.hxx>
+#include <pam.hxx>
+#include <node.hxx>
+#include <tools/string.hxx>
+
+class SwpHints;
+struct SwPosition;
+class SwPaM;
+class SwTxtAttr;
+
+// Funktions-Deklarationen fuer die Move/Find-Methoden vom SwPaM
+
+void GoStartDoc( SwPosition*);
+void GoEndDoc( SwPosition*);
+void GoStartSection( SwPosition*);
+void GoEndSection( SwPosition*);
+sal_Bool GoInDoc( SwPaM&, SwMoveFn);
+sal_Bool GoInSection( SwPaM&, SwMoveFn);
+sal_Bool GoInNode( SwPaM&, SwMoveFn);
+sal_Bool GoInCntnt( SwPaM&, SwMoveFn);
+sal_Bool GoInCntntCells( SwPaM&, SwMoveFn);
+sal_Bool GoInCntntSkipHidden( SwPaM&, SwMoveFn);
+sal_Bool GoInCntntCellsSkipHidden( SwPaM&, SwMoveFn);
+const SwTxtAttr* GetFrwrdTxtHint( const SwpHints&, sal_uInt16&, xub_StrLen );
+const SwTxtAttr* GetBkwrdTxtHint( const SwpHints&, sal_uInt16&, xub_StrLen );
+
+sal_Bool GoNext(SwNode* pNd, SwIndex * pIdx, sal_uInt16 nMode );
+sal_Bool GoPrevious(SwNode* pNd, SwIndex * pIdx, sal_uInt16 nMode );
+SW_DLLPUBLIC SwCntntNode* GoNextNds( SwNodeIndex * pIdx, sal_Bool );
+SwCntntNode* GoPreviousNds( SwNodeIndex * pIdx, sal_Bool );
+
+// --------- Funktionsdefinitionen fuer die SwCrsrShell --------------
+
+sal_Bool GoPrevPara( SwPaM&, SwPosPara);
+sal_Bool GoCurrPara( SwPaM&, SwPosPara);
+sal_Bool GoNextPara( SwPaM&, SwPosPara);
+sal_Bool GoPrevSection( SwPaM&, SwPosSection);
+sal_Bool GoCurrSection( SwPaM&, SwPosSection);
+sal_Bool GoNextSection( SwPaM&, SwPosSection);
+
+
+// ------------ Typedefiniton fuer Funktionen ----------------------
+
+typedef sal_Bool (*GoNd)( SwNode*, SwIndex*, sal_uInt16 );
+typedef SwCntntNode* (*GoNds)( SwNodeIndex*, sal_Bool );
+typedef void (*GoDoc)( SwPosition* );
+typedef void (*GoSection)( SwPosition* );
+typedef sal_Bool (SwPosition:: *CmpOp)( const SwPosition& ) const;
+typedef const SwTxtAttr* (*GetHint)( const SwpHints&, sal_uInt16&, xub_StrLen );
+typedef int (utl::TextSearch:: *SearchTxt)( const String&, xub_StrLen*,
+ xub_StrLen*, ::com::sun::star::util::SearchResult* );
+typedef void (SwNodes:: *MvSection)( SwNodeIndex * ) const;
+
+
+struct SwMoveFnCollection
+{
+ GoNd fnNd;
+ GoNds fnNds;
+ GoDoc fnDoc;
+ GoSection fnSections;
+ CmpOp fnCmpOp;
+ GetHint fnGetHint;
+ SearchTxt fnSearch;
+ MvSection fnSection;
+};
+
+// --------- Funktionsdefinitionen fuers Suchen --------------
+SwCntntNode* GetNode( SwPaM&, sal_Bool&, SwMoveFn, sal_Bool bInReadOnly = sal_False );
+
+
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/inc/prevwpage.hxx b/sw/source/core/inc/prevwpage.hxx
new file mode 100644
index 000000000000..dd35bb65d96e
--- /dev/null
+++ b/sw/source/core/inc/prevwpage.hxx
@@ -0,0 +1,62 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef _PREVIEWPAGES_HXX
+#define _PREVIEWPAGES_HXX
+
+// classes <Point>, <Size> and <Rectangle>
+#include <tools/gen.hxx>
+
+class SwPageFrm;
+
+/** data structure for a preview page in the current preview layout
+*/
+struct PrevwPage
+{
+ const SwPageFrm* pPage;
+ bool bVisible;
+ Size aPageSize;
+ Point aPrevwWinPos;
+ Point aLogicPos;
+ Point aMapOffset;
+
+ inline PrevwPage();
+};
+
+inline PrevwPage::PrevwPage()
+ : pPage( 0 ),
+ bVisible( false ),
+ aPageSize( Size(0,0) ),
+ aPrevwWinPos( Point(0,0) ),
+ aLogicPos( Point(0,0) ),
+ aMapOffset( Point(0,0) )
+{};
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/inc/ptqueue.hxx b/sw/source/core/inc/ptqueue.hxx
new file mode 100644
index 000000000000..9ef7c2017822
--- /dev/null
+++ b/sw/source/core/inc/ptqueue.hxx
@@ -0,0 +1,65 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+#ifndef _PTQUEUE_HXX
+#define _PTQUEUE_HXX
+
+//Leider vertragen wir es nicht so gut, wenn wir mehr als ein Paint
+//gleichzeitig verarbeiten sollen. Insbesondere beim Drucken kommt dies
+//leider haeufig vor.
+//SwRootFrm::Paint() stellt fest, dass es zum zweitenmal gerufen wird, und
+//traegt das Rechteck sowie die dazugehoerige Shell in den PaintCollector ein.
+//Diejenigen stellen, die moeglicherweise das doppelte Paint "Verursachen"
+//brauchen nur noch zum richtigen Zeitpunkt die gesammelten Paints verarbeiten.
+//Derzeit bietet sich der Druckvorgang an, und zwar nach dem Druck von jeweils
+//einer Seite.
+
+//Das Invalidieren der Windows direkt aus dem RootFrm::Paint hat sich als nicht
+//erfolgreich erwiesen, weil die Paints dann in den allermeisten Faellen
+//wiederum zu einem sehr unguenstigen Zeitpunkt ankommen.
+//Nach dem Druck jeder Seite ein Update auf alle Fenster auszuloesen scheint
+//auch nicht angeraten, weil einerseits die edit-Windows nicht im direkten
+//Zugriff sind und anderseits das notwendige Update je nach Plattform extrem
+//teuer werden kann.
+
+class SwQueuedPaint;
+class ViewShell;
+class SwRect;
+
+class SwPaintQueue
+{
+public:
+ static SwQueuedPaint *pQueue;
+
+ static void Add( ViewShell *pSh, const SwRect &rNew );
+ static void Remove( ViewShell *pSh );
+ static void Repaint();
+};
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/inc/retrievedinputstreamdata.hxx b/sw/source/core/inc/retrievedinputstreamdata.hxx
new file mode 100644
index 000000000000..652e14633061
--- /dev/null
+++ b/sw/source/core/inc/retrievedinputstreamdata.hxx
@@ -0,0 +1,110 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+#ifndef _RETRIEVEDINPUTSTREAMDATA_HXX
+#define _RETRIEVEDINPUTSTREAMDATA_HXX
+
+#include <tools/link.hxx>
+#include <sal/types.h>
+#include <osl/mutex.hxx>
+#include <com/sun/star/uno/Reference.hxx>
+#include <com/sun/star/io/XInputStream.hpp>
+
+#include <map>
+
+#include <boost/weak_ptr.hpp>
+
+class SwAsyncRetrieveInputStreamThreadConsumer;
+
+/** Singleton class to manage retrieved input stream data in Writer
+
+ OD 2007-01-29 #i73788#
+ The instance of this class provides data container for retrieved input
+ stream data. The data container is accessed via a key, which the data
+ manager provides on creation of the data container.
+ When a certain data container is filled with data, an user event is submitted
+ to trigger the processing of with data.
+
+ @author OD
+*/
+class SwRetrievedInputStreamDataManager
+{
+ public:
+
+ typedef sal_uInt64 tDataKey;
+
+ struct tData
+ {
+ boost::weak_ptr< SwAsyncRetrieveInputStreamThreadConsumer > mpThreadConsumer;
+ com::sun::star::uno::Reference<com::sun::star::io::XInputStream> mxInputStream;
+ sal_Bool mbIsStreamReadOnly;
+
+ tData()
+ : mpThreadConsumer(),
+ mbIsStreamReadOnly( sal_False )
+ {};
+
+ tData( boost::weak_ptr< SwAsyncRetrieveInputStreamThreadConsumer > pThreadConsumer )
+ : mpThreadConsumer( pThreadConsumer ),
+ mbIsStreamReadOnly( sal_False )
+ {};
+ };
+
+ static SwRetrievedInputStreamDataManager& GetManager();
+
+ ~SwRetrievedInputStreamDataManager()
+ {
+ };
+
+ tDataKey ReserveData( boost::weak_ptr< SwAsyncRetrieveInputStreamThreadConsumer > pThreadConsumer );
+
+ void PushData( const tDataKey nDataKey,
+ com::sun::star::uno::Reference<com::sun::star::io::XInputStream> xInputStream,
+ const sal_Bool bIsStreamReadOnly );
+
+ bool PopData( const tDataKey nDataKey,
+ tData& rData );
+
+ DECL_LINK( LinkedInputStreamReady, SwRetrievedInputStreamDataManager::tDataKey* );
+
+ private:
+
+ static SwRetrievedInputStreamDataManager* mpManager;
+ static tDataKey mnNextKeyValue;
+ static osl::Mutex maGetManagerMutex;
+
+ osl::Mutex maMutex;
+
+ std::map< tDataKey, tData > maInputStreamData;
+
+ SwRetrievedInputStreamDataManager()
+ {
+ };
+};
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/inc/retrieveinputstream.hxx b/sw/source/core/inc/retrieveinputstream.hxx
new file mode 100644
index 000000000000..29e0fb532bca
--- /dev/null
+++ b/sw/source/core/inc/retrieveinputstream.hxx
@@ -0,0 +1,66 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+#ifndef _RETRIEVEINPUTSTREAM_HXX
+#define _RETRIEVEINPUTSTREAM_HXX
+
+#include <observablethread.hxx>
+#include <tools/string.hxx>
+#include <com/sun/star/io/XInputStream.hpp>
+#include <retrievedinputstreamdata.hxx>
+
+/** class for a thread to retrieve an input stream given by an URL
+
+ OD 2007-01-29 #i73788#
+
+ @author OD
+*/
+class SwAsyncRetrieveInputStreamThread : public ObservableThread
+{
+ public:
+
+ static ::rtl::Reference< ObservableThread > createThread(
+ const SwRetrievedInputStreamDataManager::tDataKey nDataKey,
+ const String& rLinkedURL );
+
+ virtual ~SwAsyncRetrieveInputStreamThread();
+
+ protected:
+
+ virtual void threadFunction();
+
+ private:
+
+ SwAsyncRetrieveInputStreamThread( const SwRetrievedInputStreamDataManager::tDataKey nDataKey,
+ const String& rLinkedURL );
+
+ const SwRetrievedInputStreamDataManager::tDataKey mnDataKey;
+ const String mrLinkedURL;
+};
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/inc/retrieveinputstreamconsumer.hxx b/sw/source/core/inc/retrieveinputstreamconsumer.hxx
new file mode 100644
index 000000000000..26284034d425
--- /dev/null
+++ b/sw/source/core/inc/retrieveinputstreamconsumer.hxx
@@ -0,0 +1,69 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+#ifndef _RETRIEVEINPUTSTREAMCONSUMER_HXX
+#define _RETRIEVEINPUTSTREAMCONSUMER_HXX
+
+#include <com/sun/star/uno/Reference.hxx>
+#include <com/sun/star/io/XInputStream.hpp>
+#include <osl/interlck.h>
+#include <retrievedinputstreamdata.hxx>
+
+class SwGrfNode;
+class String;
+class SwAsyncRetrieveInputStreamThread;
+
+/** class to provide creation of a thread to retrieve an input stream given by
+ an URL and to consume the retrieved input stream.
+
+ #i73788#
+*/
+class SwAsyncRetrieveInputStreamThreadConsumer
+{
+ public:
+
+ SwAsyncRetrieveInputStreamThreadConsumer( SwGrfNode& rGrfNode );
+ ~SwAsyncRetrieveInputStreamThreadConsumer();
+
+ /** method to create thread
+ */
+ void CreateThread( const String& rURL );
+
+ /** method called to provide the retrieved input stream to the thread Consumer
+ */
+ void ApplyInputStream(
+ com::sun::star::uno::Reference<com::sun::star::io::XInputStream> xInputStream,
+ const sal_Bool bIsStreamReadOnly );
+
+ private:
+
+ SwGrfNode& mrGrfNode;
+ oslInterlockedCount mnThreadID;
+};
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/inc/rolbck.hxx b/sw/source/core/inc/rolbck.hxx
new file mode 100644
index 000000000000..df9da4bfb9b4
--- /dev/null
+++ b/sw/source/core/inc/rolbck.hxx
@@ -0,0 +1,439 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+#ifndef _ROLBCK_HXX
+#define _ROLBCK_HXX
+
+#include <tools/solar.h>
+#ifndef _SVSTDARR_HXX
+#define _SVSTDARR_USHORTS
+#define _SVSTDARR_USHORTSSORT
+#include <svl/svstdarr.hxx>
+#endif
+#include <svl/itemset.hxx>
+
+//Nur die History anziehen, um das docnew.cxx gegen die CLOOK's zu behaupten.
+
+namespace sfx2 {
+ class MetadatableUndo;
+}
+
+class SwDoc;
+class SwFmt;
+class SwFmtColl;
+class SwHistoryHint;
+class SwTxtAttr;
+class SfxPoolItem;
+class SwTxtNode;
+class SwUndoSaveSection;
+class SwTxtFtn;
+class SwTxtFlyCnt;
+class SwUndoDelLayFmt;
+class SwFlyFrmFmt;
+class SwFmtFld;
+class SwTxtFld;
+class SwFieldType;
+class SwTxtTOXMark;
+class SwTxtRefMark;
+class SwFrmFmt;
+class SwpHints;
+class SwFmtChain;
+class SwNode;
+class SwCharFmt;
+
+#ifndef ROLBCK_HISTORY_ONLY
+
+#include <tox.hxx>
+
+#include <SwNumberTreeTypes.hxx>
+#include <IDocumentMarkAccess.hxx>
+
+#include <memory>
+
+enum HISTORY_HINT {
+ HSTRY_SETFMTHNT,
+ HSTRY_RESETFMTHNT,
+ HSTRY_SETTXTHNT,
+ HSTRY_SETTXTFLDHNT,
+ HSTRY_SETREFMARKHNT,
+ HSTRY_SETTOXMARKHNT,
+ HSTRY_RESETTXTHNT,
+ HSTRY_SETFTNHNT,
+ HSTRY_CHGFMTCOLL,
+ HSTRY_FLYCNT,
+ HSTRY_BOOKMARK,
+ HSTRY_SETATTRSET,
+ HSTRY_RESETATTRSET,
+ HSTRY_CHGFLYANCHOR,
+ HSTRY_CHGFLYCHAIN,
+ HSTRY_CHGCHARFMT,
+ HSTRY_END
+};
+
+class SwHistoryHint
+{
+ const HISTORY_HINT m_eWhichId;
+
+public:
+ SwHistoryHint( HISTORY_HINT eWhich ) : m_eWhichId( eWhich ) {}
+ virtual ~SwHistoryHint() {}
+ virtual void SetInDoc( SwDoc* pDoc, bool bTmpSet ) = 0;
+ HISTORY_HINT Which() const { return m_eWhichId; }
+ virtual String GetDescription() const;
+};
+
+class SwHistorySetFmt : public SwHistoryHint
+{
+ ::std::auto_ptr<SfxPoolItem> m_pAttr;
+ const sal_uLong m_nNodeIndex;
+
+public:
+ SwHistorySetFmt( const SfxPoolItem* pFmtHt, sal_uLong nNode );
+ virtual ~SwHistorySetFmt();
+ virtual void SetInDoc( SwDoc* pDoc, bool bTmpSet );
+ virtual String GetDescription() const;
+
+};
+
+class SwHistoryResetFmt : public SwHistoryHint
+{
+ const sal_uLong m_nNodeIndex;
+ const sal_uInt16 m_nWhich;
+
+public:
+ SwHistoryResetFmt( const SfxPoolItem* pFmtHt, sal_uLong nNodeIdx );
+ virtual void SetInDoc( SwDoc* pDoc, bool bTmpSet );
+
+};
+
+class SwHistorySetTxt : public SwHistoryHint
+{
+ ::std::auto_ptr<SfxPoolItem> m_pAttr;
+ const sal_uLong m_nNodeIndex;
+ const xub_StrLen m_nStart;
+ const xub_StrLen m_nEnd;
+
+public:
+ SwHistorySetTxt( SwTxtAttr* pTxtHt, sal_uLong nNode );
+ virtual ~SwHistorySetTxt();
+ virtual void SetInDoc( SwDoc* pDoc, bool bTmpSet );
+
+};
+
+class SwHistorySetTxtFld : public SwHistoryHint
+{
+ //!! beware of the order for the declation of the auto_ptrs.
+ //!! If they get destroyed in the wrong order sw may crash (namely mail-merge as well)
+ ::std::auto_ptr<SwFieldType> m_pFldType;
+ const ::std::auto_ptr<SwFmtFld> m_pFld;
+
+ sal_uLong m_nNodeIndex;
+ xub_StrLen m_nPos;
+ sal_uInt16 m_nFldWhich;
+
+public:
+ SwHistorySetTxtFld( SwTxtFld* pTxtFld, sal_uLong nNode );
+ virtual ~SwHistorySetTxtFld();
+ virtual void SetInDoc( SwDoc* pDoc, bool bTmpSet );
+
+ virtual String GetDescription() const;
+
+};
+
+class SwHistorySetRefMark : public SwHistoryHint
+{
+ const String m_RefName;
+ const sal_uLong m_nNodeIndex;
+ const xub_StrLen m_nStart;
+ const xub_StrLen m_nEnd;
+
+public:
+ SwHistorySetRefMark( SwTxtRefMark* pTxtHt, sal_uLong nNode );
+ virtual void SetInDoc( SwDoc* pDoc, bool bTmpSet );
+
+};
+
+class SwHistorySetTOXMark : public SwHistoryHint
+{
+ SwTOXMark m_TOXMark;
+ const String m_TOXName;
+ const TOXTypes m_eTOXTypes;
+ const sal_uLong m_nNodeIndex;
+ const xub_StrLen m_nStart;
+ const xub_StrLen m_nEnd;
+
+public:
+ SwHistorySetTOXMark( SwTxtTOXMark* pTxtHt, sal_uLong nNode );
+ virtual void SetInDoc( SwDoc* pDoc, bool bTmpSet );
+ int IsEqual( const SwTOXMark& rCmp ) const;
+
+};
+
+class SwHistoryResetTxt : public SwHistoryHint
+{
+ const sal_uLong m_nNodeIndex;
+ const xub_StrLen m_nStart;
+ const xub_StrLen m_nEnd;
+ const sal_uInt16 m_nAttr;
+
+public:
+ SwHistoryResetTxt( sal_uInt16 nWhich, xub_StrLen nStt, xub_StrLen nEnd,
+ sal_uLong nNode );
+ virtual void SetInDoc( SwDoc* pDoc, bool bTmpSet );
+
+ sal_uInt16 GetWhich() const { return m_nAttr; }
+ sal_uLong GetNode() const { return m_nNodeIndex; }
+ xub_StrLen GetCntnt() const { return m_nStart; }
+
+};
+
+class SwHistorySetFootnote : public SwHistoryHint
+{
+ const ::std::auto_ptr<SwUndoSaveSection> m_pUndo;
+ const String m_FootnoteNumber;
+ sal_uLong m_nNodeIndex;
+ const xub_StrLen m_nStart;
+ const bool m_bEndNote;
+
+public:
+ SwHistorySetFootnote( SwTxtFtn* pTxtFtn, sal_uLong nNode );
+ SwHistorySetFootnote( const SwTxtFtn& );
+ virtual ~SwHistorySetFootnote();
+ virtual void SetInDoc( SwDoc* pDoc, bool bTmpSet );
+
+ virtual String GetDescription() const;
+
+};
+
+class SwHistoryChangeFmtColl : public SwHistoryHint
+{
+ SwFmtColl * const m_pColl;
+ const sal_uLong m_nNodeIndex;
+ const sal_uInt8 m_nNodeType;
+
+public:
+ SwHistoryChangeFmtColl( SwFmtColl* pColl, sal_uLong nNode, sal_uInt8 nNodeWhich );
+ virtual void SetInDoc( SwDoc* pDoc, bool bTmpSet );
+
+};
+
+class SwHistoryTxtFlyCnt : public SwHistoryHint
+{
+ ::std::auto_ptr<SwUndoDelLayFmt> m_pUndo;
+
+public:
+ SwHistoryTxtFlyCnt( SwFrmFmt* const pFlyFmt );
+ virtual ~SwHistoryTxtFlyCnt();
+ virtual void SetInDoc( SwDoc* pDoc, bool bTmpSet );
+ SwUndoDelLayFmt* GetUDelLFmt() { return m_pUndo.get(); }
+
+};
+
+class SwHistoryBookmark : public SwHistoryHint
+{
+ public:
+ SwHistoryBookmark(const ::sw::mark::IMark& rBkmk,
+ bool bSavePos, bool bSaveOtherPos);
+ virtual void SetInDoc(SwDoc * pDoc, bool);
+
+ bool IsEqualBookmark(const ::sw::mark::IMark& rBkmk);
+ const ::rtl::OUString& GetName() const;
+
+ private:
+ const ::rtl::OUString m_aName;
+ ::rtl::OUString m_aShortName;
+ KeyCode m_aKeycode;
+ const sal_uLong m_nNode;
+ const sal_uLong m_nOtherNode;
+ const xub_StrLen m_nCntnt;
+ const xub_StrLen m_nOtherCntnt;
+ const bool m_bSavePos;
+ const bool m_bSaveOtherPos;
+ const bool m_bHadOtherPos;
+ const IDocumentMarkAccess::MarkType m_eBkmkType;
+ ::boost::shared_ptr< ::sfx2::MetadatableUndo > m_pMetadataUndo;
+};
+
+class SwHistorySetAttrSet : public SwHistoryHint
+{
+ SfxItemSet m_OldSet;
+ SvUShorts m_ResetArray;
+ const sal_uLong m_nNodeIndex;
+
+public:
+ SwHistorySetAttrSet( const SfxItemSet& rSet, sal_uLong nNode,
+ const SvUShortsSort& rSetArr );
+ virtual void SetInDoc( SwDoc* pDoc, bool bTmpSet );
+
+};
+
+class SwHistoryResetAttrSet : public SwHistoryHint
+{
+ const sal_uLong m_nNodeIndex;
+ const xub_StrLen m_nStart;
+ const xub_StrLen m_nEnd;
+ SvUShorts m_Array;
+
+public:
+ SwHistoryResetAttrSet( const SfxItemSet& rSet, sal_uLong nNode,
+ xub_StrLen nStt = STRING_MAXLEN,
+ xub_StrLen nEnd = STRING_MAXLEN );
+ virtual void SetInDoc( SwDoc* pDoc, bool bTmpSet );
+
+ const SvUShorts& GetArr() const { return m_Array; }
+ sal_uLong GetNode() const { return m_nNodeIndex; }
+ xub_StrLen GetCntnt() const { return m_nStart; }
+
+};
+
+class SwHistoryChangeFlyAnchor : public SwHistoryHint
+{
+ SwFrmFmt & m_rFmt;
+ const sal_uLong m_nOldNodeIndex;
+ const xub_StrLen m_nOldContentIndex;
+
+public:
+ SwHistoryChangeFlyAnchor( SwFrmFmt& rFmt );
+ virtual void SetInDoc( SwDoc* pDoc, bool bTmpSet );
+};
+
+class SwHistoryChangeFlyChain : public SwHistoryHint
+{
+ SwFlyFrmFmt * const m_pPrevFmt;
+ SwFlyFrmFmt * const m_pNextFmt;
+ SwFlyFrmFmt * const m_pFlyFmt;
+
+public:
+ SwHistoryChangeFlyChain( SwFlyFrmFmt& rFmt, const SwFmtChain& rAttr );
+ virtual void SetInDoc( SwDoc* pDoc, bool bTmpSet );
+};
+
+class SwHistoryChangeCharFmt : public SwHistoryHint
+{
+ const SfxItemSet m_OldSet;
+ const String m_Fmt;
+
+public:
+ SwHistoryChangeCharFmt( const SfxItemSet& rSet, const String & sFmt);
+ virtual void SetInDoc( SwDoc* pDoc, bool bTmpSet );
+
+};
+
+#endif
+
+typedef SwHistoryHint* SwHistoryHintPtr;
+SV_DECL_PTRARR_DEL( SwpHstry, SwHistoryHintPtr, 0, 2 )
+
+class SwHistory
+{
+ friend class SwDoc; // actually only SwDoc::DelUndoObj may access
+ friend class SwUndoWriter; // for Undo/Redo Writer
+ friend class SwRegHistory; // for inserting History attributes
+
+ SwpHstry m_SwpHstry;
+ sal_uInt16 m_nEndDiff;
+
+public:
+ SwHistory( sal_uInt16 nInitSz = 0, sal_uInt16 nGrowSz = 2 );
+ ~SwHistory();
+
+ // delete History from nStart to array end
+ void Delete( sal_uInt16 nStart = 0 );
+ // call and delete all objects between nStart and array end
+ bool Rollback( SwDoc* pDoc, sal_uInt16 nStart = 0 );
+ // call all objects between nStart and TmpEnd; store nStart as TmpEnd
+ bool TmpRollback( SwDoc* pDoc, sal_uInt16 nStart, bool ToFirst = true );
+
+ void Add( const SfxPoolItem* pOldValue, const SfxPoolItem* pNewValue,
+ sal_uLong nNodeIdx );
+ void Add( SwTxtAttr* pTxtHt, sal_uLong nNodeIdx, bool bNewAttr = true );
+ void Add( SwFmtColl*, sal_uLong nNodeIdx, sal_uInt8 nWhichNd );
+ void Add( const ::sw::mark::IMark&, bool bSavePos, bool bSaveOtherPos );
+ void Add( SwFrmFmt& rFmt );
+ void Add( SwFlyFrmFmt&, sal_uInt16& rSetPos );
+ void Add( const SwTxtFtn& );
+ void Add( const SfxItemSet & rSet, const SwCharFmt & rCharFmt);
+
+ sal_uInt16 Count() const { return m_SwpHstry.Count(); }
+ sal_uInt16 GetTmpEnd() const { return m_SwpHstry.Count() - m_nEndDiff; }
+ sal_uInt16 SetTmpEnd( sal_uInt16 nTmpEnd ); // return previous value
+ SwHistoryHint * operator[]( sal_uInt16 nPos ) { return m_SwpHstry[nPos]; }
+ SwHistoryHint const* operator[]( sal_uInt16 nPos ) const
+ { return m_SwpHstry[nPos]; }
+
+ // for SwUndoDelete::Undo/Redo
+ void Move( sal_uInt16 nPos, SwHistory *pIns,
+ sal_uInt16 nStart = 0, sal_uInt16 nEnd = USHRT_MAX )
+ {
+ m_SwpHstry.Insert( &pIns->m_SwpHstry, nPos, nStart, nEnd );
+ pIns->m_SwpHstry.Remove( nStart, (nEnd == USHRT_MAX)
+ ? pIns->Count() - nStart
+ : nEnd );
+ }
+
+ // helper methods for recording attribute in History
+ // used by Undo classes (Delete/Overwrite/Inserts)
+ void CopyAttr( SwpHints* pHts, sal_uLong nNodeIdx, xub_StrLen nStart,
+ xub_StrLen nEnd, bool bFields );
+ void CopyFmtAttr( const SfxItemSet& rSet, sal_uLong nNodeIdx );
+};
+
+#ifndef ROLBCK_HISTORY_ONLY
+
+class SwRegHistory : public SwClient
+{
+private:
+ SvUShortsSort m_WhichIdSet;
+ SwHistory * const m_pHistory;
+ sal_uLong m_nNodeIndex;
+
+ void _MakeSetWhichIds();
+
+protected:
+ virtual void Modify( const SfxPoolItem* pOld, const SfxPoolItem* pNew );
+
+public:
+ SwRegHistory( SwHistory* pHst );
+ SwRegHistory( const SwNode& rNd, SwHistory* pHst );
+ SwRegHistory( SwModify* pRegIn, const SwNode& rNd, SwHistory* pHst );
+
+ /// @return true if at least 1 item was inserted
+ bool InsertItems( const SfxItemSet& rSet,
+ xub_StrLen const nStart, xub_StrLen const nEnd,
+ SetAttrMode const nFlags );
+
+ void AddHint( SwTxtAttr* pHt, const bool bNew = false );
+
+ void RegisterInModify( SwModify* pRegIn, const SwNode& rNd );
+ void ChangeNodeIndex( sal_uLong nNew ) { m_nNodeIndex = nNew; }
+};
+
+#endif
+
+#endif // _ROLBCK_HXX
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/inc/rootfrm.hxx b/sw/source/core/inc/rootfrm.hxx
new file mode 100644
index 000000000000..64ad72101420
--- /dev/null
+++ b/sw/source/core/inc/rootfrm.hxx
@@ -0,0 +1,375 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+#ifndef SW_ROOTFRM_HXX
+#define SW_ROOTFRM_HXX
+
+#include "layfrm.hxx"
+
+class SwCntntFrm;
+class ViewShell;
+class SdrPage;
+class SwFrmFmt;
+class SwPaM;
+class SwCursor;
+class SwShellCrsr;
+class SwTableCursor;
+class SwLayVout;
+class SwDestroyList;
+class SwCurrShells;
+class SwViewOption;
+class SwSelectionList;
+struct SwPosition;
+struct SwCrsrMoveState;
+
+#define HACK_TABLEMODE_INIT 0
+#define HACK_TABLEMODE_LOCKLINES 1
+#define HACK_TABLEMODE_PAINTLINES 2
+#define HACK_TABLEMODE_UNLOCKLINES 3
+#define HACK_TABLEMODE_EXIT 4
+
+#define INV_SIZE 1
+#define INV_PRTAREA 2
+#define INV_POS 4
+#define INV_TABLE 8
+#define INV_SECTION 16
+#define INV_LINENUM 32
+#define INV_DIRECTION 64
+
+#include <vector>
+
+class SwRootFrm: public SwLayoutFrm
+{
+ //Muss das Superfluous temporaer abschalten.
+ friend void AdjustSizeChgNotify( SwRootFrm *pRoot );
+
+ //Pflegt pLastPage (Cut() und Paste() vom SwPageFrm
+ friend inline void SetLastPage( SwPageFrm* );
+
+ // Fuer das Anlegen und Zerstoeren des virtuellen Outputdevice-Managers
+ friend void _FrmInit(); //erzeugt pVout
+ friend void _FrmFinit(); //loescht pVout
+
+ // PAGES01
+ std::vector<SwRect> maPageRects;// returns the current rectangle for each page frame
+ // the rectangle is extended to the top/bottom/left/right
+ // for pages located at the outer borders
+ SwRect maPagesArea; // the area covered by the pages
+ long mnViewWidth; // the current page layout bases on this view width
+ sal_uInt16 mnColumns; // the current page layout bases on this number of columns
+ bool mbBookMode; // the current page layout is in book view
+ bool mbSidebarChanged; // the notes sidebar state has changed
+ // <--
+
+ bool mbNeedGrammarCheck; // true when sth needs to be checked (not necessarily started yet!)
+
+ static SwLayVout *pVout;
+ static sal_Bool bInPaint; //Schutz gegen doppelte Paints.
+ static sal_Bool bNoVirDev; //Bei SystemPaints kein virt. Device
+
+ sal_Bool bCheckSuperfluous :1; //Leere Seiten suchen?
+ sal_Bool bIdleFormat :1; //Idle-Formatierer anwerfen?
+ sal_Bool bBrowseWidthValid :1; //Ist nBrowseWidth gueltig?
+ sal_Bool bDummy2 :1; //Unbenutzt
+ sal_Bool bTurboAllowed :1;
+ sal_Bool bAssertFlyPages :1; //Ggf. weitere Seiten fuer Flys einfuegen?
+ sal_Bool bDummy :1; //Unbenutzt
+ sal_Bool bIsVirtPageNum :1; //gibt es eine virtuelle Seitennummer ?
+ sal_Bool bIsNewLayout :1; //Layout geladen oder neu erzeugt.
+ sal_Bool bCallbackActionEnabled:1; //Keine Action in Benachrichtung erwuenscht
+ //siehe dcontact.cxx, ::Changed()
+
+ //Fuer den BrowseMode. nBrowseWidth ist die Aeussere Kante des am weitesten
+ //rechts stehenden Objectes. Die rechte Kante der Seiten soll im BrowseMode
+ //nicht kleiner werden als dieser Wert.
+ long nBrowseWidth;
+
+ //Wenn nur _ein: CntntFrm zu formatieren ist, so steht dieser in pTurbo.
+ const SwCntntFrm *pTurbo;
+
+ //Die letzte Seite wollen wir uns nicht immer muehsam zusammensuchen.
+ SwPageFrm *pLastPage;
+
+ //Die Root kuemmert sich nun auch um den Shell-Zugriff. Ueber das Dokument
+ //sollte man auch immer an die Root herankommen und somit auch immer
+ //einen Zugriff auf die Shell haben.
+ //Der Pointer pCurrShell ist der Pointer auf irgendeine der Shells fuer
+ //das Dokument
+ //Da es durchaus nicht immer egal ist, auf welcher Shell gearbeitet wird,
+ //ist es notwendig die aktive Shell zu kennen. Das wird dadurch angenaehert,
+ //dass der Pointer pCurrShell immer dann umgesetzt wird, wenn eine
+ //Shell den Fokus erhaelt (FEShell). Zusaetzlich wird der Pointer
+ //Temporaer von SwCurrShell umgesetzt, dieses wird typischerweise
+ //ueber das Macro SET_CURR_SHELL erledigt. Makro + Klasse sind in der
+ //ViewShell zu finden. Diese Objekte koennen auch verschachtelt (auch fuer
+ //unterschiedliche Shells) erzeugt werden. Sie werden im Array pCurrShells
+ //gesammelt.
+ //Weiterhin kann es noch vorkommen, dass eine Shell aktiviert wird,
+ //waehrend noch ein CurrShell-Objekt "aktiv" ist. Dieses wird dann in
+ //pWaitingCurrShell eingetragen und vom letzten DTor der CurrShell
+ //"aktiviert".
+ //Ein weiteres Problem ist dass Zerstoeren einer Shell waehrend sie aktiv
+ //ist. Der Pointer pCurrShell wird dann auf eine beliebige andere Shell
+ //umgesetzt.
+ //Wenn zum Zeitpunkt der zerstoerung einer Shell diese noch in irgendwelchen
+ //CurrShell-Objekten referenziert wird, so wird auch dies aufgeklart.
+ friend class CurrShell;
+ friend void SetShell( ViewShell *pSh );
+ friend void InitCurrShells( SwRootFrm *pRoot );
+ ViewShell *pCurrShell;
+ ViewShell *pWaitingCurrShell;
+ SwCurrShells *pCurrShells;
+
+ //Eine Page im DrawModel pro Dokument, hat immer die Groesse der Root.
+ SdrPage *pDrawPage;
+
+ SwDestroyList* pDestroy;
+
+ sal_uInt16 nPhyPageNums; //Anzahl der Seiten.
+ sal_uInt16 nAccessibleShells; // Number of accessible shells
+
+ void ImplCalcBrowseWidth();
+ void ImplInvalidateBrowseWidth();
+
+ void _DeleteEmptySct(); // zerstoert ggf. die angemeldeten SectionFrms
+ void _RemoveFromList( SwSectionFrm* pSct ); // entfernt SectionFrms aus der Delete-Liste
+
+protected:
+
+ virtual void MakeAll();
+
+public:
+
+ //MasterObjekte aus der Page entfernen (von den Ctoren gerufen).
+ static void RemoveMasterObjs( SdrPage *pPg );
+
+ void AllCheckPageDescs() const;//swmod 080226
+ void AllInvalidateAutoCompleteWords() const;//swmod 080305
+ void AllAddPaintRect() const;
+ void AllRemoveFtns() ;//swmod 080305
+ void AllInvalidateSmartTagsOrSpelling(sal_Bool bSmartTags) const;//swmod 080307
+ //Virtuelles Device ausgeben (z.B. wenn Animationen ins Spiel kommen)
+ static sal_Bool FlushVout();
+ //Clipping sparen, wenn im Vout eh genau das Cliprechteck ausgegeben wird
+ static sal_Bool HasSameRect( const SwRect& rRect );
+
+ SwRootFrm( SwFrmFmt*, ViewShell* );
+ ~SwRootFrm();
+ void Init(SwFrmFmt*);
+
+ ViewShell *GetCurrShell() const { return pCurrShell; }
+ void DeRegisterShell( ViewShell *pSh );
+
+ //Start-/EndAction fuer alle Shells auf moeglichst hoeher
+ //(Shell-Ableitungs-)Ebene aufsetzen. Fuer die StarONE Anbindung, die
+ //die Shells nicht dirkt kennt.
+ //Der ChangeLinkd der CrsrShell (UI-Benachrichtigung) wird im EndAllAction
+ //automatisch gecallt.
+ void StartAllAction();
+ void EndAllAction( sal_Bool bVirDev = sal_False );
+
+ // fuer bestimmte UNO-Aktionen (Tabellencursor) ist es notwendig, dass alle Actions
+ // kurzfristig zurueckgesetzt werden. Dazu muss sich jede ViewShell ihren alten Action-zaehler
+ // merken
+ void UnoRemoveAllActions();
+ void UnoRestoreAllActions();
+
+ const SdrPage* GetDrawPage() const { return pDrawPage; }
+ SdrPage* GetDrawPage() { return pDrawPage; }
+ void SetDrawPage( SdrPage* pNew ){ pDrawPage = pNew; }
+
+ virtual sal_Bool GetCrsrOfst( SwPosition *, Point&,
+ SwCrsrMoveState* = 0 ) const;
+
+ virtual void Paint( SwRect const&,
+ SwPrintData const*const pPrintData = NULL ) const;
+ virtual SwTwips ShrinkFrm( SwTwips, sal_Bool bTst = sal_False, sal_Bool bInfo = sal_False );
+ virtual SwTwips GrowFrm ( SwTwips, sal_Bool bTst = sal_False, sal_Bool bInfo = sal_False );
+#if OSL_DEBUG_LEVEL > 1
+ virtual void Cut();
+ virtual void Paste( SwFrm* pParent, SwFrm* pSibling = 0 );
+#endif
+
+ virtual bool FillSelection( SwSelectionList& rList, const SwRect& rRect ) const;
+
+ Point GetNextPrevCntntPos( const Point &rPoint, sal_Bool bNext ) const;
+
+ virtual Size ChgSize( const Size& aNewSize );
+
+ void SetIdleFlags() { bIdleFormat = sal_True; }
+ sal_Bool IsIdleFormat() const { return bIdleFormat; }
+ void ResetIdleFormat() { bIdleFormat = sal_False; }
+
+ bool IsNeedGrammarCheck() const { return mbNeedGrammarCheck; }
+ void SetNeedGrammarCheck( bool bVal ) { mbNeedGrammarCheck = bVal; }
+
+ //Sorgt dafuer, dass alle gewuenschten Seitengebunden Flys eine Seite finden
+ void SetAssertFlyPages() { bAssertFlyPages = sal_True; }
+ void AssertFlyPages();
+ sal_Bool IsAssertFlyPages() { return bAssertFlyPages; }
+
+ //Stellt sicher, dass ab der uebergebenen Seite auf allen Seiten die
+ //Seitengebundenen Rahmen auf der richtigen Seite (Seitennummer) stehen.
+ void AssertPageFlys( SwPageFrm * );
+
+ //Saemtlichen Inhalt invalidieren, Size oder PrtArea
+ void InvalidateAllCntnt( sal_uInt8 nInvalidate = INV_SIZE );
+
+ /** method to invalidate/re-calculate the position of all floating
+ screen objects (Writer fly frames and drawing objects), which are
+ anchored to paragraph or to character.
+
+ OD 2004-03-16 #i11860#
+
+ @author OD
+ */
+ void InvalidateAllObjPos();
+
+ //Ueberfluessige Seiten entfernen.
+ void SetSuperfluous() { bCheckSuperfluous = sal_True; }
+ sal_Bool IsSuperfluous() const { return bCheckSuperfluous; }
+ void RemoveSuperfluous();
+
+ //abfragen/setzen der aktuellen Seite und der Gesamtzahl der Seiten.
+ //Es wird soweit wie notwendig Formatiert.
+ sal_uInt16 GetCurrPage( const SwPaM* ) const;
+ sal_uInt16 SetCurrPage( SwCursor*, sal_uInt16 nPageNum );
+ Point GetPagePos( sal_uInt16 nPageNum ) const;
+ sal_uInt16 GetPageNum() const { return nPhyPageNums; }
+ void DecrPhyPageNums() { --nPhyPageNums; }
+ void IncrPhyPageNums() { ++nPhyPageNums; }
+ sal_Bool IsVirtPageNum() const { return bIsVirtPageNum; }
+ inline void SetVirtPageNum( const sal_Bool bOf ) const;
+ sal_Bool IsDummyPage( sal_uInt16 nPageNum ) const;
+
+ // Point rPt: The point that should be used to find the page
+ // Size pSize: If given, we return the (first) page that overlaps with the
+ // rectangle defined by rPt and pSize
+ // bool bExtend: Extend each page to the left/right/top/botton up to the
+ // next page border
+ const SwPageFrm* GetPageAtPos( const Point& rPt, const Size* pSize = 0, bool bExtend = false ) const;
+
+ //Der Crsr moechte die zu selektierenden Bereiche wissen.
+ void CalcFrmRects( SwShellCrsr&, sal_Bool bIsTblSel );
+
+ // Calculates the cells included from the current selection
+ // false: There was no result because of an invalid layout
+ // true: Everything worked fine.
+ bool MakeTblCrsrs( SwTableCursor& );
+
+ void DisallowTurbo() const { ((SwRootFrm*)this)->bTurboAllowed = sal_False; }
+ void ResetTurboFlag() const { ((SwRootFrm*)this)->bTurboAllowed = sal_True; }
+ sal_Bool IsTurboAllowed() const { return bTurboAllowed; }
+ void SetTurbo( const SwCntntFrm *pCntnt ) { pTurbo = pCntnt; }
+ void ResetTurbo() { pTurbo = 0; }
+ const SwCntntFrm *GetTurbo() { return pTurbo; }
+
+ //Fussnotennummern aller Seiten auf den neuesten Stand bringen.
+ void UpdateFtnNums(); //nur bei Seitenweiser Nummerierung!
+
+ //Alle Fussnoten (nicht etwa die Referenzen) entfernen.
+ void RemoveFtns( SwPageFrm *pPage = 0, sal_Bool bPageOnly = sal_False,
+ sal_Bool bEndNotes = sal_False );
+ void CheckFtnPageDescs( sal_Bool bEndNote );
+
+ const SwPageFrm *GetLastPage() const { return pLastPage; }
+ SwPageFrm *GetLastPage() { return pLastPage; }
+
+ static sal_Bool IsInPaint() { return bInPaint; }
+
+ static void SetNoVirDev( const sal_Bool bNew ) { bNoVirDev = bNew; }
+
+ inline long GetBrowseWidth() const;
+ void SetBrowseWidth( long n ) { bBrowseWidthValid = sal_True; nBrowseWidth = n;}
+ inline void InvalidateBrowseWidth();
+
+ sal_Bool IsNewLayout() const { return bIsNewLayout; }
+ void ResetNewLayout() { bIsNewLayout = sal_False;}
+
+ // Hier werden leere SwSectionFrms zur Zerstoerung angemeldet
+ // und spaeter zerstoert oder wieder abgemeldet
+ void InsertEmptySct( SwSectionFrm* pDel );
+ void DeleteEmptySct() { if( pDestroy ) _DeleteEmptySct(); }
+ void RemoveFromList( SwSectionFrm* pSct ) { if( pDestroy ) _RemoveFromList( pSct ); }
+#if OSL_DEBUG_LEVEL > 1
+ // Wird zur Zeit nur fuer OSL_ENSURE( benutzt:
+ sal_Bool IsInDelList( SwSectionFrm* pSct ) const; // Ist der SectionFrm in der Liste enthalten?
+#endif
+
+
+ void SetCallbackActionEnabled( sal_Bool b ) { bCallbackActionEnabled = b; }
+ sal_Bool IsCallbackActionEnabled() const { return bCallbackActionEnabled; }
+
+ sal_Bool IsAnyShellAccessible() const { return nAccessibleShells > 0; }
+ void AddAccessibleShell() { ++nAccessibleShells; }
+ void RemoveAccessibleShell() { --nAccessibleShells; }
+
+ /** get page frame by phyiscal page number
+
+ OD 14.01.2003 #103492#
+ looping through the lowers, which are page frame, in order to find the
+ page frame with the given physical page number.
+ if no page frame is found, 0 is returned.
+ Note: Empty page frames are also returned.
+
+ @param _nPageNum
+ input parameter - physical page number of page frame to be searched and
+ returned.
+
+ @return pointer to the page frame with the given physical page number
+ */
+ SwPageFrm* GetPageByPageNum( sal_uInt16 _nPageNum ) const;
+
+ // --> PAGES01
+ void CheckViewLayout( const SwViewOption* pViewOpt, const SwRect* pVisArea );
+ bool IsLeftToRightViewLayout() const;
+ const SwRect& GetPagesArea() const { return maPagesArea; }
+ void SetSidebarChanged() { mbSidebarChanged = true; }
+ // <--
+};
+
+inline long SwRootFrm::GetBrowseWidth() const
+{
+ if ( !bBrowseWidthValid )
+ ((SwRootFrm*)this)->ImplCalcBrowseWidth();
+ return nBrowseWidth;
+}
+
+inline void SwRootFrm::InvalidateBrowseWidth()
+{
+ if ( bBrowseWidthValid )
+ ImplInvalidateBrowseWidth();
+}
+
+inline void SwRootFrm::SetVirtPageNum( const sal_Bool bOf) const
+{
+ ((SwRootFrm*)this)->bIsVirtPageNum = bOf;
+}
+
+#endif // SW_ROOTFRM_HXX
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/inc/rowfrm.hxx b/sw/source/core/inc/rowfrm.hxx
new file mode 100644
index 000000000000..d8c3abb0346d
--- /dev/null
+++ b/sw/source/core/inc/rowfrm.hxx
@@ -0,0 +1,114 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+#ifndef _ROWFRM_HXX
+#define _ROWFRM_HXX
+
+#include <tools/mempool.hxx>
+
+#include "layfrm.hxx"
+
+class SwTableLine;
+class SwBorderAttrs;
+
+class SwRowFrm: public SwLayoutFrm
+{
+ virtual void Format( const SwBorderAttrs *pAttrs = 0 );
+ //Aendern nur die Framesize, nicht die PrtArea-SSize
+ virtual SwTwips ShrinkFrm( SwTwips, sal_Bool bTst = sal_False, sal_Bool bInfo = sal_False );
+ virtual SwTwips GrowFrm ( SwTwips, sal_Bool bTst = sal_False, sal_Bool bInfo = sal_False );
+
+ const SwTableLine *pTabLine;
+ SwRowFrm* pFollowRow;
+ // --> collapsing borders FME 2005-05-27 #i29550#
+ sal_uInt16 mnTopMarginForLowers;
+ sal_uInt16 mnBottomMarginForLowers;
+ sal_uInt16 mnBottomLineSize;
+ // <-- collapsing
+ bool bIsFollowFlowRow;
+ bool bIsRepeatedHeadline;
+ bool mbIsRowSpanLine;
+
+protected:
+ virtual void MakeAll();
+ virtual void Modify( const SfxPoolItem*, const SfxPoolItem* );
+
+public:
+ SwRowFrm( const SwTableLine &, SwFrm*, bool bInsertContent = true );
+ ~SwRowFrm();
+
+ virtual void Cut();
+
+ //Zum Anmelden der Flys nachdem eine Zeile erzeugt _und_ eingefuegt wurde.
+ //Muss vom Erzeuger gerufen werden, denn erst nach dem Konstruieren wird
+ //Das Teil gepastet; mithin ist auch erst dann die Seite zum Anmelden der
+ //Flys erreichbar.
+ void RegistFlys( SwPageFrm *pPage = 0 );
+
+ const SwTableLine *GetTabLine() const { return pTabLine; }
+
+ //Passt die Zellen auf die aktuelle Hoehe an, invalidiert die Zellen
+ //wenn die Direction nicht der Hoehe entspricht.
+ void AdjustCells( const SwTwips nHeight, const sal_Bool bHeight );
+
+ //
+ //
+ SwRowFrm* GetFollowRow() const { return pFollowRow; }
+ void SetFollowRow( SwRowFrm* pNew ) { pFollowRow = pNew; }
+
+ // --> collapsing borders FME 2005-05-27 #i29550#
+ sal_uInt16 GetTopMarginForLowers() const { return mnTopMarginForLowers; }
+ void SetTopMarginForLowers( sal_uInt16 nNew ) { mnTopMarginForLowers = nNew; }
+ sal_uInt16 GetBottomMarginForLowers() const { return mnBottomMarginForLowers; }
+ void SetBottomMarginForLowers( sal_uInt16 nNew ) { mnBottomMarginForLowers = nNew; }
+ sal_uInt16 GetBottomLineSize() const { return mnBottomLineSize; }
+ void SetBottomLineSize( sal_uInt16 nNew ) { mnBottomLineSize = nNew; }
+ // <-- collapsing
+
+ bool IsRepeatedHeadline() const { return bIsRepeatedHeadline; }
+ void SetRepeatedHeadline( bool bNew ) { bIsRepeatedHeadline = bNew; }
+
+ // --> split table rows
+ bool IsRowSplitAllowed() const;
+ bool IsFollowFlowRow() const { return bIsFollowFlowRow; }
+ void SetFollowFlowRow( bool bNew ) { bIsFollowFlowRow = bNew; }
+ // <-- split table rows
+
+ // --> FME 2006-02-10 #131283# Table row keep feature
+ bool ShouldRowKeepWithNext() const;
+ // <--
+
+ // --> FME 2006-10-30 #i4032# NEW TABLES
+ bool IsRowSpanLine() const { return mbIsRowSpanLine; }
+ void SetRowSpanLine( bool bNew ) { mbIsRowSpanLine = bNew; }
+
+ DECL_FIXEDMEMPOOL_NEWDEL(SwRowFrm)
+};
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/inc/scriptinfo.hxx b/sw/source/core/inc/scriptinfo.hxx
new file mode 100644
index 000000000000..d814bc089666
--- /dev/null
+++ b/sw/source/core/inc/scriptinfo.hxx
@@ -0,0 +1,436 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+#ifndef _SCRIPTINFO_HXX
+#define _SCRIPTINFO_HXX
+#ifndef _SVSTDARR_HXX
+#define _SVSTDARR_USHORTS
+#define _SVSTDARR_XUB_STRLEN
+#include <svl/svstdarr.hxx>
+#endif
+#include <i18npool/lang.h>
+#include <list>
+#include <modeltoviewhelper.hxx>
+
+
+class SwTxtNode;
+class Point;
+class MultiSelection;
+class String;
+typedef std::list< xub_StrLen > PositionList;
+
+#define SPACING_PRECISION_FACTOR 100
+
+/*************************************************************************
+ * class SwScanner
+ * Hilfsklasse, die beim Spellen die Worte im gewuenschten Bereich
+ * nacheinander zur Verfuegung stellt.
+ *************************************************************************/
+
+class SwScanner
+{
+ XubString aWord;
+ const SwTxtNode& rNode;
+ const String& rText;
+ const LanguageType* pLanguage;
+ const ModelToViewHelper::ConversionMap* pConversionMap;
+ xub_StrLen nStartPos;
+ xub_StrLen nEndPos;
+ xub_StrLen nBegin;
+ xub_StrLen nLen;
+ LanguageType aCurrLang;
+ sal_uInt16 nWordType;
+ sal_Bool bClip;
+
+public:
+ SwScanner( const SwTxtNode& rNd, const String& rTxt, const LanguageType* pLang,
+ const ModelToViewHelper::ConversionMap* pConvMap,
+ sal_uInt16 nWordType,
+ xub_StrLen nStart, xub_StrLen nEnde, sal_Bool bClip = sal_False );
+
+
+ // This next word function tries to find the language for the next word
+ // It should currently _not_ be used for spell checking, and works only for
+ // ! bReverse
+ sal_Bool NextWord();
+
+ const XubString& GetWord() const { return aWord; }
+
+ xub_StrLen GetBegin() const { return nBegin; }
+ xub_StrLen GetEnd() const { return nBegin + nLen; }
+ xub_StrLen GetLen() const { return nLen; }
+
+ LanguageType GetCurrentLanguage() const {return aCurrLang;}
+};
+
+/*************************************************************************
+ * class SwScriptInfo
+ *
+ * encapsultes information about script changes
+ *************************************************************************/
+
+class SwScriptInfo
+{
+private:
+ //! Records a single change in script type.
+ struct ScriptChangeInfo
+ {
+ xub_StrLen position; //!< Character position at which we change script
+ sal_uInt8 type; //!< Script type (Latin/Asian/Complex) that we change to.
+ inline ScriptChangeInfo(xub_StrLen pos, sal_uInt8 typ) : position(pos), type(typ) {};
+ };
+ //TODO - This is sorted, so should probably be a std::set rather than vector.
+ // But we also use random access (probably unnecessarily).
+ std::vector<ScriptChangeInfo> aScriptChanges;
+ //! Records a single change in direction.
+ struct DirectionChangeInfo
+ {
+ xub_StrLen position; //!< Character position at which we change direction.
+ sal_uInt8 type; //!< Direction that we change to.
+ inline DirectionChangeInfo(xub_StrLen pos, sal_uInt8 typ) : position(pos), type(typ) {};
+ };
+ std::vector<DirectionChangeInfo> aDirectionChanges;
+ SvXub_StrLens aKashida;
+ SvXub_StrLens aKashidaInvalid;
+ SvXub_StrLens aNoKashidaLine;
+ SvXub_StrLens aNoKashidaLineEnd;
+ SvXub_StrLens aHiddenChg;
+ //! Records a single change in compression.
+ struct CompressionChangeInfo
+ {
+ xub_StrLen position; //!< Character position where the change occurs.
+ xub_StrLen length; //!< Length of the segment.
+ sal_uInt8 type; //!< Type of compression that we change to.
+ inline CompressionChangeInfo(xub_StrLen pos, xub_StrLen len, sal_uInt8 typ) : position(pos), length(len), type(typ) {};
+ };
+ std::vector<CompressionChangeInfo> aCompressionChanges;
+ xub_StrLen nInvalidityPos;
+ sal_uInt8 nDefaultDir;
+
+ void UpdateBidiInfo( const String& rTxt );
+
+ sal_Bool IsKashidaValid ( xub_StrLen nKashPos ) const;
+ void MarkKashidaInvalid ( xub_StrLen nKashPos );
+ void ClearKashidaInvalid ( xub_StrLen nKashPos );
+ bool MarkOrClearKashidaInvalid( xub_StrLen nStt, xub_StrLen nLen, bool bMark, xub_StrLen nMarkCount );
+ bool IsKashidaLine ( xub_StrLen nCharIdx ) const;
+
+public:
+ enum CompType { KANA, SPECIAL_LEFT, SPECIAL_RIGHT, NONE };
+
+ SwScriptInfo();
+ ~SwScriptInfo();
+
+ // determines script changes
+ void InitScriptInfo( const SwTxtNode& rNode, sal_Bool bRTL );
+ void InitScriptInfo( const SwTxtNode& rNode );
+
+ // set/get position from which data is invalid
+ inline void SetInvalidity( const xub_StrLen nPos );
+ inline xub_StrLen GetInvalidity() const { return nInvalidityPos; };
+
+ // get default direction for paragraph
+ inline sal_uInt8 GetDefaultDir() const { return nDefaultDir; };
+
+ // array operations, nCnt refers to array position
+ inline size_t CountScriptChg() const;
+ inline xub_StrLen GetScriptChg( const size_t nCnt ) const;
+ inline sal_uInt8 GetScriptType( const sal_uInt16 nCnt ) const;
+
+ inline size_t CountDirChg() const;
+ inline xub_StrLen GetDirChg( const size_t nCnt ) const;
+ inline sal_uInt8 GetDirType( const size_t nCnt ) const;
+
+ inline size_t CountKashida() const;
+ inline xub_StrLen GetKashida( const size_t nCnt ) const;
+
+ inline size_t CountCompChg() const;
+ inline xub_StrLen GetCompStart( const size_t nCnt ) const;
+ inline xub_StrLen GetCompLen( const size_t nCnt ) const;
+ inline sal_uInt8 GetCompType( const size_t nCnt ) const;
+
+ inline size_t CountHiddenChg() const;
+ inline xub_StrLen GetHiddenChg( const size_t nCnt ) const;
+ static void CalcHiddenRanges( const SwTxtNode& rNode,
+ MultiSelection& rHiddenMulti );
+
+ // "high" level operations, nPos refers to string position
+ xub_StrLen NextScriptChg( const xub_StrLen nPos ) const;
+ sal_uInt8 ScriptType( const xub_StrLen nPos ) const;
+
+ // Returns the position of the next direction level change.
+ // If bLevel is set, the position of the next level which is smaller
+ // than the level at position nPos is returned. This is required to
+ // obtain the end of a SwBidiPortion
+ xub_StrLen NextDirChg( const xub_StrLen nPos,
+ const sal_uInt8* pLevel = 0 ) const;
+ sal_uInt8 DirType( const xub_StrLen nPos ) const;
+
+#if OSL_DEBUG_LEVEL > 1
+ sal_uInt8 CompType( const xub_StrLen nPos ) const;
+#endif
+
+ //
+ // HIDDEN TEXT STUFF START
+ //
+
+/** Hidden text range information - static and non-version
+
+ @descr Determines if a given position is inside a hidden text range. The
+ static version tries to obtain a valid SwScriptInfo object
+ via the SwTxtNode, otherwise it calculates the values from scratch.
+ The non-static version uses the internally cached informatio
+ for the calculation.
+
+ @param rNode
+ The text node.
+ @param nPos
+ The given position that should be checked.
+ @param rnStartPos
+ Return parameter for the start position of the hidden range.
+ STRING_LEN if nPos is not inside a hidden range.
+ @param rnEndPos
+ Return parameter for the end position of the hidden range.
+ 0 if nPos is not inside a hidden range.
+ @param rnEndPos
+ Return parameter that contains all the hidden text ranges. Optional.
+ @return
+ returns true if there are any hidden characters in this paragraph.
+
+*/
+ static bool GetBoundsOfHiddenRange( const SwTxtNode& rNode, xub_StrLen nPos,
+ xub_StrLen& rnStartPos, xub_StrLen& rnEndPos,
+ PositionList* pList = 0 );
+ bool GetBoundsOfHiddenRange( xub_StrLen nPos, xub_StrLen& rnStartPos,
+ xub_StrLen& rnEndPos, PositionList* pList = 0 ) const;
+
+ static bool IsInHiddenRange( const SwTxtNode& rNode, xub_StrLen nPos );
+
+/** Hidden text attribute handling
+
+ @descr Takes a string and either deletes the hidden ranges or sets
+ a given character in place of the hidden characters.
+
+ @param rNode
+ The text node.
+ @param nPos
+ The string to modify.
+ @param cChar
+ The character that should replace the hidden characters.
+ @param bDel
+ If set, the hidden ranges will be deleted from the text node.
+ */
+ static sal_uInt16 MaskHiddenRanges( const SwTxtNode& rNode, XubString& rText,
+ const xub_StrLen nStt, const xub_StrLen nEnd,
+ const xub_Unicode cChar );
+
+/** Hidden text attribute handling
+
+ @descr Takes a SwTxtNode and deletes the hidden ranges from the node.
+
+ @param rNode
+ The text node.
+ */
+ static void DeleteHiddenRanges( SwTxtNode& rNode );
+
+ //
+ // HIDDEN TEXT STUFF END
+ //
+
+ // examines the range [ nStart, nStart + nEnd ] if there are kanas
+ // returns start index of kana entry in array, otherwise USHRT_MAX
+ sal_uInt16 HasKana( xub_StrLen nStart, const xub_StrLen nEnd ) const;
+
+ // modifies the kerning array according to a given compress value
+ long Compress( sal_Int32* pKernArray, xub_StrLen nIdx, xub_StrLen nLen,
+ const sal_uInt16 nCompress, const sal_uInt16 nFontHeight,
+ Point* pPoint = NULL ) const;
+
+/** Performes a kashida justification on the kerning array
+
+ @descr Add some extra space for kashida justification to the
+ positions in the kerning array.
+ @param pKernArray
+ The printers kerning array. Optional.
+ @param pScrArray
+ The screen kerning array. Optional.
+ @param nStt
+ Start referring to the paragraph.
+ @param nLen
+ The number of characters to be considered.
+ @param nSpaceAdd
+ The value which has to be added to a kashida opportunity.
+ @return The number of kashida opportunities in the given range
+*/
+ sal_uInt16 KashidaJustify( sal_Int32* pKernArray, sal_Int32* pScrArray,
+ xub_StrLen nStt, xub_StrLen nLen,
+ long nSpaceAdd = 0) const;
+
+/** Clears array of kashidas marked as invalid
+ */
+ inline void ClearKashidaInvalid ( xub_StrLen nStt, xub_StrLen nLen ) { MarkOrClearKashidaInvalid( nStt, nLen, false, 0 ); }
+
+/** Marks nCnt kashida positions as invalid
+ pKashidaPositions: array of char indices relative to the paragraph
+*/
+ bool MarkKashidasInvalid ( xub_StrLen nCnt, xub_StrLen* pKashidaPositions );
+
+/** Marks nCnt kashida positions as invalid
+ in the given text range
+ */
+ inline bool MarkKashidasInvalid ( xub_StrLen nCnt, xub_StrLen nStt, xub_StrLen nLen )
+ { return MarkOrClearKashidaInvalid( nStt, nLen, true, nCnt ); }
+
+/** retrieves kashida opportunities for a given text range.
+ returns the number of kashida positions in the given text range
+
+ pKashidaPositions: buffer to reveive the char indices of the
+ kashida opportunties relative to the paragraph
+*/
+ sal_uInt16 GetKashidaPositions ( xub_StrLen nStt, xub_StrLen nLen,
+ xub_StrLen* pKashidaPosition );
+
+
+
+
+/** Use regular blank justification instead of kashdida justification for the given line of text.
+ nStt Start char index of the line referring to the paragraph.
+ nLen Number of characters in the line
+*/
+ void SetNoKashidaLine ( xub_StrLen nStt, xub_StrLen nLen );
+
+/** Clear forced blank justification for a given line.
+ nStt Start char index of the line referring to the paragraph.
+ nLen Number of characters in the line
+*/
+ void ClearNoKashidaLine ( xub_StrLen nStt, xub_StrLen nLen );
+
+/** Checks if text is Arabic text.
+
+ @descr Checks if text is Arabic text.
+ @param rTxt
+ The text to check
+ @param nStt
+ Start index of the text
+ @return Returns if the language is an Arabic language
+ */
+ static sal_Bool IsArabicText( const XubString& rTxt, xub_StrLen nStt, xub_StrLen nLen );
+
+/** Performes a thai justification on the kerning array
+
+ @descr Add some extra space for thai justification to the
+ positions in the kerning array.
+ @param rTxt
+ The String
+ @param pKernArray
+ The printers kerning array. Optional.
+ @param pScrArray
+ The screen kerning array. Optional.
+ @param nIdx
+ Start referring to the paragraph.
+ @param nLen
+ The number of characters to be considered.
+ @param nSpaceAdd
+ The value which has to be added to the cells.
+ @return The number of extra spaces in the given range
+*/
+ static sal_uInt16 ThaiJustify( const XubString& rTxt, sal_Int32* pKernArray,
+ sal_Int32* pScrArray, xub_StrLen nIdx,
+ xub_StrLen nLen, xub_StrLen nNumberOfBlanks = 0,
+ long nSpaceAdd = 0 );
+
+ static SwScriptInfo* GetScriptInfo( const SwTxtNode& rNode,
+ sal_Bool bAllowInvalid = sal_False );
+
+ static sal_uInt8 WhichFont( xub_StrLen nIdx, const String* pTxt, const SwScriptInfo* pSI );
+};
+
+inline void SwScriptInfo::SetInvalidity( const xub_StrLen nPos )
+{
+ if ( nPos < nInvalidityPos )
+ nInvalidityPos = nPos;
+};
+inline size_t SwScriptInfo::CountScriptChg() const { return aScriptChanges.size(); }
+inline xub_StrLen SwScriptInfo::GetScriptChg( const size_t nCnt ) const
+{
+ OSL_ENSURE( nCnt < aScriptChanges.size(),"No ScriptChange today!");
+ return aScriptChanges[nCnt].position;
+}
+inline sal_uInt8 SwScriptInfo::GetScriptType( const xub_StrLen nCnt ) const
+{
+ OSL_ENSURE( nCnt < aScriptChanges.size(),"No ScriptType today!");
+ return aScriptChanges[nCnt].type;
+}
+
+inline size_t SwScriptInfo::CountDirChg() const { return aDirectionChanges.size(); }
+inline xub_StrLen SwScriptInfo::GetDirChg( const size_t nCnt ) const
+{
+ OSL_ENSURE( nCnt < aDirectionChanges.size(),"No DirChange today!");
+ return aDirectionChanges[ nCnt ].position;
+}
+inline sal_uInt8 SwScriptInfo::GetDirType( const size_t nCnt ) const
+{
+ OSL_ENSURE( nCnt < aDirectionChanges.size(),"No DirType today!");
+ return aDirectionChanges[ nCnt ].type;
+}
+
+inline size_t SwScriptInfo::CountKashida() const { return aKashida.size(); }
+inline xub_StrLen SwScriptInfo::GetKashida( const size_t nCnt ) const
+{
+ OSL_ENSURE( nCnt < aKashida.size(),"No Kashidas today!");
+ return aKashida[ nCnt ];
+}
+
+inline size_t SwScriptInfo::CountCompChg() const { return aCompressionChanges.size(); };
+inline xub_StrLen SwScriptInfo::GetCompStart( const size_t nCnt ) const
+{
+ OSL_ENSURE( nCnt < aCompressionChanges.size(),"No CompressionStart today!");
+ return aCompressionChanges[ nCnt ].position;
+}
+inline xub_StrLen SwScriptInfo::GetCompLen( const size_t nCnt ) const
+{
+ OSL_ENSURE( nCnt < aCompressionChanges.size(),"No CompressionLen today!");
+ return aCompressionChanges[ nCnt ].length;
+}
+
+inline sal_uInt8 SwScriptInfo::GetCompType( const size_t nCnt ) const
+{
+ OSL_ENSURE( nCnt < aCompressionChanges.size(),"No CompressionType today!");
+ return aCompressionChanges[ nCnt ].type;
+}
+
+inline size_t SwScriptInfo::CountHiddenChg() const { return aHiddenChg.size(); };
+inline xub_StrLen SwScriptInfo::GetHiddenChg( const size_t nCnt ) const
+{
+ OSL_ENSURE( nCnt < aHiddenChg.size(),"No HiddenChg today!");
+ return aHiddenChg[ nCnt ];
+}
+
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/inc/sectfrm.hxx b/sw/source/core/inc/sectfrm.hxx
new file mode 100644
index 000000000000..8c1b84bbd5b8
--- /dev/null
+++ b/sw/source/core/inc/sectfrm.hxx
@@ -0,0 +1,153 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+#ifndef _SECTFRM_HXX
+#define _SECTFRM_HXX
+#include <tools/mempool.hxx>
+
+#include "layfrm.hxx"
+#include "flowfrm.hxx"
+
+class SwSection;
+class SwSectionFmt;
+class SwAttrSetChg;
+class SwFtnContFrm;
+class SwLayouter;
+
+#define FINDMODE_ENDNOTE 1
+#define FINDMODE_LASTCNT 2
+#define FINDMODE_MYLAST 4
+
+class SwSectionFrm: public SwLayoutFrm, public SwFlowFrm
+{
+ SwSection* pSection;
+
+ void _UpdateAttr( const SfxPoolItem*, const SfxPoolItem*, sal_uInt8 &,
+ SwAttrSetChg *pa = 0, SwAttrSetChg *pb = 0 );
+ void _Cut( sal_Bool bRemove );
+ // Is there a FtnContainer?
+ // An empty sectionfrm without FtnCont is superfluous
+ sal_Bool IsSuperfluous() const { return !ContainsAny() && !ContainsFtnCont(); }
+ void CalcFtnAtEndFlag();
+ void CalcEndAtEndFlag();
+ const SwSectionFmt* _GetEndSectFmt() const;
+ sal_Bool IsEndnoteAtMyEnd() const;
+protected:
+ virtual void MakeAll();
+ virtual sal_Bool ShouldBwdMoved( SwLayoutFrm *pNewUpper, sal_Bool bHead, sal_Bool &rReformat );
+ virtual void Format( const SwBorderAttrs *pAttrs = 0 );
+ virtual void Modify( const SfxPoolItem*, const SfxPoolItem* );
+ virtual void SwClientNotify( const SwModify&, const SfxHint& );
+
+public:
+ SwSectionFrm( SwSection &, SwFrm* ); //Inhalt wird nicht erzeugt!
+ SwSectionFrm( SwSectionFrm &, sal_Bool bMaster );//_Nur_ zum Erzeugen von Master/Follows
+ ~SwSectionFrm();
+
+ void Init();
+ virtual void CheckDirection( sal_Bool bVert );
+
+ virtual void Cut();
+ virtual void Paste( SwFrm* pParent, SwFrm* pSibling = 0 );
+
+ inline const SwSectionFrm *GetFollow() const;
+ inline SwSectionFrm *GetFollow();
+ SwSectionFrm* FindMaster() const;
+
+ SwCntntFrm *FindLastCntnt( sal_uInt8 nMode = 0 );
+ inline const SwCntntFrm *FindLastCntnt( sal_uInt8 nMode = 0 ) const;
+ inline SwSection* GetSection() { return pSection; }
+ inline const SwSection* GetSection() const { return pSection; }
+ inline void ColLock() { bColLocked = sal_True; }
+ inline void ColUnlock() { bColLocked = sal_False; }
+
+ void CalcFtnCntnt();
+ void SimpleFormat();
+ sal_Bool IsDescendantFrom( const SwSectionFmt* pSect ) const;
+ sal_Bool HasToBreak( const SwFrm* pFrm ) const;
+ void MergeNext( SwSectionFrm* pNxt );
+ //Zerlegt den pFrm umgebenden SectionFrm in zwei Teile,
+ //pFrm an den Anfang des 2. Teils
+ sal_Bool SplitSect( SwFrm* pFrm, sal_Bool bApres );
+ void DelEmpty( sal_Bool bRemove ); // wie Cut(), Follow-Verkettung wird aber mitgepflegt
+ sal_Bool IsToIgnore() const // Keine Groesse, kein Inhalt, muss ignoriert werden
+ { return !Frm().Height() && !ContainsCntnt(); }
+ SwFtnContFrm* ContainsFtnCont( const SwFtnContFrm* pCont = NULL ) const;
+ sal_Bool Growable() const;
+ SwTwips _Shrink( SwTwips, sal_Bool bTst );
+ SwTwips _Grow ( SwTwips, sal_Bool bTst );
+
+ // A sectionfrm has to maximize, if he has a follow or a ftncontainer at
+ // the end of the page. A superfluous follow will be ignored,
+ // if bCheckFollow is set.
+ sal_Bool ToMaximize( sal_Bool bCheckFollow ) const;
+ inline sal_Bool _ToMaximize() const
+ { if( !pSection ) return sal_False; return ToMaximize( sal_False ); }
+ sal_Bool MoveAllowed( const SwFrm* ) const;
+ sal_Bool CalcMinDiff( SwTwips& rMinDiff ) const;
+ // Uebergibt man kein bOverSize bzw. sal_False, so ist der Returnwert
+ // >0 fuer Undersized-Frames, ==0 sonst.
+ // Uebergibt man sal_True, so kann es auch einen negativen Returnwert geben,
+ // wenn der SectionFrm nicht vollstaendig ausgefuellt ist, was z.B. bei
+ // SectionFrm mit Follow meist vorkommt. Benoetigt wird dies im
+ // FormatWidthCols, um "Luft" aus den Spalten zu lassen.
+ long Undersize( sal_Bool bOverSize = sal_False );
+ // Groesse an die Umgebung anpassen
+ void _CheckClipping( sal_Bool bGrow, sal_Bool bMaximize );
+
+ void InvalidateFtnPos();
+ void CollectEndnotes( SwLayouter* pLayouter );
+ const SwSectionFmt* GetEndSectFmt() const
+ { if( IsEndnAtEnd() ) return _GetEndSectFmt(); return NULL; }
+
+ static void MoveCntntAndDelete( SwSectionFrm* pDel, sal_Bool bSave );
+
+ bool IsBalancedSection() const;
+
+ DECL_FIXEDMEMPOOL_NEWDEL(SwSectionFrm)
+};
+
+typedef SwSectionFrm* SwSectionFrmPtr;
+SV_DECL_PTRARR_SORT( SwDestroyList, SwSectionFrmPtr, 1, 5)
+
+inline const SwSectionFrm *SwSectionFrm::GetFollow() const
+{
+ return (const SwSectionFrm*)SwFlowFrm::GetFollow();
+}
+inline SwSectionFrm *SwSectionFrm::GetFollow()
+{
+ return (SwSectionFrm*)SwFlowFrm::GetFollow();
+}
+inline const SwCntntFrm *SwSectionFrm::FindLastCntnt( sal_uInt8 nMode ) const
+{
+ return ((SwSectionFrm*)this)->FindLastCntnt( nMode );
+}
+
+
+#endif //_SECTFRM_HXX
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/inc/setmapvirtdev.hxx b/sw/source/core/inc/setmapvirtdev.hxx
new file mode 100644
index 000000000000..c3b6cdf7fea7
--- /dev/null
+++ b/sw/source/core/inc/setmapvirtdev.hxx
@@ -0,0 +1,73 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+#ifndef _SETMAPVIRTDEV_HXX
+#define _SETMAPVIRTDEV_HXX
+
+class OutputDevice;
+class VirtualDevice;
+class MapMode;
+class Point;
+
+/** method to set mapping/pixel offset for virtual output device
+
+ OD 12.11.2002 #96272# - method implements two solutions for the mapping of
+ the virtual output device:
+ The old solution set the origin of the mapping mode, which will be used in
+ the virtual output device. This causes several paint errors, because of the
+ different roundings in the virtual output device and the original output device.
+ The new solution avoids the rounding differences between virtual and original
+ output device by setting a pixel offset at the virtual output device.
+ A local boolean controls, which solution is used, in order to switch in
+ escalation back to old solution.
+
+ @author OD
+
+ @param _pOrgOutDev
+ input parameter - constant instance of the original output device, for which
+ the virtual output device is created.
+
+ @param _pVirDev
+ input/output parameter - instance of the virtual output device.
+
+ @param _pMapMode
+ input/output parameter - instance of the mapping mode, which will be set
+ at the virtual output device.
+
+ @param _rNewOrigin
+ input parameter - constant instance of the origin, which will be used in
+ the virtual output device
+*/
+void SetMappingForVirtDev( const Point& _rNewOrigin,
+ MapMode* _pMapMode,
+ const OutputDevice* _pOrgOutDev,
+ VirtualDevice* _pVirDev );
+
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/inc/sortedobjs.hxx b/sw/source/core/inc/sortedobjs.hxx
new file mode 100644
index 000000000000..720ff087c936
--- /dev/null
+++ b/sw/source/core/inc/sortedobjs.hxx
@@ -0,0 +1,100 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+#ifndef _SORTEDOBJS_HXX
+#define _SORTEDOBJS_HXX
+class SwSortedObjsImpl;
+class SwAnchoredObject;
+
+#include <sal/types.h>
+
+/** class for collecting anchored objects
+
+ for #i28701#
+ Anchored objects can be inserted and deleted. The entries can be directly
+ accessed via index.
+ An anchored object is inserted sorted. The sort criteria are:
+ - anchor type
+ - order 1: to-page, 2: to-fly, 3: to-paragraph|to-character|as-character
+ - anchor node
+ - wrapping style (inclusive layer)
+ - order 1: wrapping style != SURROUND_THROUGHT and not in hell layer,
+ 2: wrapping style = SURROUND_THROUGHT or in hell layer
+ - wrapping style influence
+ - order 1: NONE_SUCCESSIVE_POSITIONED, 2: NONE_CONCURRENT_POSITIONED
+ - again anchor type
+ - order 1: to-paragraph, 2: to-character, 3: as-character
+ - anchor node position
+ - internal anchor order number
+ If one of the sort criteria attributes of an anchored object changes,
+ the sorting has to be updated - use method <Update(..)>
+*/
+class SwSortedObjs
+{
+ private:
+ SwSortedObjsImpl* mpImpl;
+
+ public:
+ SwSortedObjs();
+ ~SwSortedObjs();
+
+ sal_uInt32 Count() const;
+
+ /** direct access to the entries
+
+ @param _nIndex
+ input parameter - index of entry, valid value range [0..Count()-1]
+ */
+ SwAnchoredObject* operator[]( sal_uInt32 _nIndex ) const;
+
+ bool Insert( SwAnchoredObject& _rAnchoredObj );
+
+ bool Remove( SwAnchoredObject& _rAnchoredObj );
+
+ bool Contains( const SwAnchoredObject& _rAnchoredObj ) const;
+
+ /** method to update the position of the given anchored object in the
+ sorted list
+
+ @return boolean, indicating success of the update.
+ */
+ bool Update( SwAnchoredObject& _rAnchoredObj );
+
+ /** Position of object <_rAnchoredObj> in sorted list
+
+ Returns the number of the list position of object <_rAnchoredObj>.
+ Returns <Count()>, if object isn't contained in list.
+
+ @return sal_uInt32
+ Number of the list position of object <_rAnchoredObj>
+ */
+ sal_uInt32 ListPosOf( const SwAnchoredObject& _rAnchoredObj ) const;
+};
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/inc/sortedobjsimpl.hxx b/sw/source/core/inc/sortedobjsimpl.hxx
new file mode 100644
index 000000000000..1b23cd194ac9
--- /dev/null
+++ b/sw/source/core/inc/sortedobjsimpl.hxx
@@ -0,0 +1,64 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+#ifndef _SORTEDOBJSIMPL_HXX
+#define _SORTEDOBJSIMPL_HXX
+
+#include <vector>
+#include <sal/types.h>
+#include <fmtanchr.hxx>
+
+class SwAnchoredObject;
+class SwTxtFrm;
+
+class SwSortedObjsImpl
+{
+ private:
+ std::vector< SwAnchoredObject* > maSortedObjLst;
+
+ public:
+ SwSortedObjsImpl();
+ ~SwSortedObjsImpl();
+
+ sal_uInt32 Count() const;
+
+ SwAnchoredObject* operator[]( sal_uInt32 _nIndex );
+
+ bool Insert( SwAnchoredObject& _rAnchoredObj );
+
+ bool Remove( SwAnchoredObject& _rAnchoredObj );
+
+ bool Contains( const SwAnchoredObject& _rAnchoredObj ) const;
+
+ bool Update( SwAnchoredObject& _rAnchoredObj );
+
+ sal_uInt32 ListPosOf( const SwAnchoredObject& _rAnchoredObj ) const;
+};
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/inc/swblocks.hxx b/sw/source/core/inc/swblocks.hxx
new file mode 100644
index 000000000000..1ac9455abff7
--- /dev/null
+++ b/sw/source/core/inc/swblocks.hxx
@@ -0,0 +1,148 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+#ifndef _SWBLOCKS_HXX
+#define _SWBLOCKS_HXX
+
+#include <tools/string.hxx>
+
+#include <tools/datetime.hxx>
+#include <svl/svarray.hxx>
+
+
+class SfxMedium;
+class SwPaM;
+class SwDoc;
+class SvxMacroTableDtor;
+
+// Name eines Textblocks:
+
+class SwBlockName
+{
+ friend class SwImpBlocks;
+ friend class Sw2TextBlocks;
+ sal_uInt16 nHashS, nHashL; // Hash-Codes zum Checken
+ long nPos; // Dateiposition (SW2-Format)
+public:
+ String aShort; // Short name
+ String aLong; // Long name
+ String aPackageName; // Package name
+ sal_Bool bIsOnlyTxtFlagInit : 1; // ist das Flag gueltig?
+ sal_Bool bIsOnlyTxt : 1; // unformatted text
+ sal_Bool bInPutMuchBlocks : 1; // put serveral block entries
+
+ SwBlockName( const String& rShort, const String& rLong, long n );
+ SwBlockName( const String& rShort, const String& rLong, const String& rPackageName );
+
+ // fuer das Einsortieren in das Array
+ int operator==( const SwBlockName& r ) { return aShort == r.aShort; }
+ int operator< ( const SwBlockName& r ) { return aShort < r.aShort; }
+};
+
+SV_DECL_PTRARR_SORT( SwBlockNames, SwBlockName*, 10, 10 )
+
+
+class SwImpBlocks
+{
+ friend class SwTextBlocks;
+protected:
+ String aFile; // physikalischer Dateiname
+ String aName; // logischer Name der Datei
+ String aCur; // aktueller Text
+ String aShort, aLong; // Kurz- und Langname (PutDoc)
+ String sBaseURL; // base URL - has to be set at the Readers and Writers
+ SwBlockNames aNames; // Liste aller Bausteine
+ Date aDateModified; // fuers abgleichen bei den Aktionen
+ Time aTimeModified;
+ SwDoc* pDoc; // Austauschdokument
+ sal_uInt16 nCur; // aktueller Index
+ sal_Bool bReadOnly : 1;
+ sal_Bool bInPutMuchBlocks : 1; // put serveral block entries
+ sal_Bool bInfoChanged : 1; // any Info of TextBlock is changed
+
+ SwImpBlocks( const String&, sal_Bool = sal_False );
+ virtual ~SwImpBlocks();
+
+ static short GetFileType( const String& );
+ virtual short GetFileType() const = 0;
+#define SWBLK_NO_FILE 0 // nicht da
+#define SWBLK_NONE 1 // keine TB-Datei
+#define SWBLK_SW2 2 // SW2-Datei
+#define SWBLK_SW3 3 // SW3-Datei
+#define SWBLK_XML 4 // XML Block List
+
+ virtual void ClearDoc(); // Doc-Inhalt loeschen
+ SwPaM* MakePaM(); // PaM ueber Doc aufspannen
+ virtual void AddName( const String&, const String&, sal_Bool bOnlyTxt = sal_False );
+ sal_Bool IsFileChanged() const;
+ void Touch();
+
+public:
+ static sal_uInt16 Hash( const String& ); // Hashcode fuer Blocknamen
+ sal_uInt16 GetCount() const; // Anzahl Textbausteine ermitteln
+ sal_uInt16 GetIndex( const String& ) const; // Index fuer Kurznamen ermitteln
+ sal_uInt16 GetLongIndex( const String& ) const; //Index fuer Langnamen ermitteln
+ const String& GetShortName( sal_uInt16 ) const; // Kurzname fuer Index zurueck
+ const String& GetLongName( sal_uInt16 ) const; // Langname fuer Index zurueck
+ const String& GetPackageName( sal_uInt16 ) const; // Langname fuer Index zurueck
+
+ const String& GetFileName() const {return aFile;} // phys. Dateinamen liefern
+ void SetName( const String& rName ) // logic name
+ { aName = rName; bInfoChanged = sal_True; }
+ const String & GetName( void )
+ { return aName; }
+
+ const String& GetBaseURL() const { return sBaseURL;}
+ void SetBaseURL( const String& rURL ) { sBaseURL = rURL; }
+
+ virtual sal_uLong Delete( sal_uInt16 ) = 0;
+ virtual sal_uLong Rename( sal_uInt16, const String&, const String& ) = 0;
+ virtual sal_uLong CopyBlock( SwImpBlocks& rImp, String& rShort, const String& rLong) = 0;
+ virtual sal_uLong GetDoc( sal_uInt16 ) = 0;
+ virtual sal_uLong GetDocForConversion( sal_uInt16 );
+ virtual sal_uLong BeginPutDoc( const String&, const String& ) = 0;
+ virtual sal_uLong PutDoc() = 0;
+ virtual sal_uLong GetText( sal_uInt16, String& ) = 0;
+ virtual sal_uLong PutText( const String&, const String&, const String& ) = 0;
+ virtual sal_uLong MakeBlockList() = 0;
+
+ virtual sal_uLong OpenFile( sal_Bool bReadOnly = sal_True ) = 0;
+ virtual void CloseFile() = 0;
+
+ virtual sal_Bool IsOnlyTextBlock( const String& rShort ) const;
+
+ virtual sal_uLong GetMacroTable( sal_uInt16 nIdx, SvxMacroTableDtor& rMacroTbl,
+ sal_Bool bFileAlreadyOpen = sal_False );
+ virtual sal_uLong SetMacroTable( sal_uInt16 nIdx,
+ const SvxMacroTableDtor& rMacroTbl,
+ sal_Bool bFileAlreadyOpen = sal_False );
+ virtual sal_Bool PutMuchEntries( sal_Bool bOn );
+};
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/inc/swcache.hxx b/sw/source/core/inc/swcache.hxx
new file mode 100644
index 000000000000..cfb585345566
--- /dev/null
+++ b/sw/source/core/inc/swcache.hxx
@@ -0,0 +1,303 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+#ifndef _SWCACHE_HXX
+#define _SWCACHE_HXX
+
+
+
+/*
+ * Es werden Pointer auf Objekte verwaltet. Diese werden in einem einfachen
+ * PtrArray verwaltet.
+ * Angelegt (new) werden die Objekte von Cache-Zugriffsklassen, zuerstoert
+ * werden die Objekte vom Cache.
+ *
+ * Auf die Objekte kann wahlweise per Index in das Array oder per Suche
+ * zugegriffen werden. Soll per Index zugegriffen werden, so obliegt die
+ * Verwaltung des Index dem Anwender des Cache.
+ *
+ * Fuer die verwalteten Cache-Objekte gibt es eine Basisklasse, von dieser
+ * sind spezifische Klassen abzuleiten.
+ * In der Basisklasse werden die Cache-Objekte eines Cache doppelt verkettet,
+ * das ermoeglich die Implementierung eines LRU-Algorithmus.
+ *
+ * Der LRU kann in der Cache-Basisklasse manipuliert werden, indem ein
+ * virtueller First-Pointer gesetzt wird. Dieser kann auf den echten ersten
+ * plus einem Ofst gesetzt werden. Dadurch kann man den Anfangsbereich des
+ * Cache sichern und so dafuer sorgen, dass man waehrend bestimmter
+ * Operationen nicht den Cache versaut. Beispiel: Der Idle-Handler sollte nicht
+ * den Cache fuer den sichtbaren Bereich vernichten.
+ *
+ * Der Cache kann in der Groesse erweitert und wieder verkleinert werden.
+ * Beispiel: Fuer jede neue Shell wird der Cache fuer FormatInfo vergrossert
+ * und beim Destruieren der Shell wieder verkleinert.
+ *
+ */
+
+#if OSL_DEBUG_LEVEL > 1
+#include <tools/string.hxx>
+#endif
+
+#ifndef _SVSTDARR_HXX
+#define _SVSTDARR_USHORTS
+#include <svl/svstdarr.hxx>
+#endif
+
+class SwCacheObj;
+
+SV_DECL_PTRARR_DEL(SwCacheObjArr,SwCacheObj*,1,1)
+
+class SwCache : public SwCacheObjArr
+{
+ SvUShorts aFreePositions; //Freie Positionen fuer das Insert wenn
+ //die Maximalgrenze nicht erreicht ist.
+ //Immer wenn ein Objekt ausgetragen wird,
+ //so wird seine Position hier eingetragen.
+
+ SwCacheObj *pRealFirst; //_immer_ der echte LRU-erste
+ SwCacheObj *pFirst; //der virtuelle erste.
+ SwCacheObj *pLast;
+
+ const sal_uInt16 nMax; //Mehr sollen nicht aufgenommen werden,
+ //der Cache kann aber dynamisch um jeweils
+ //nMax vergroessert werden.
+ sal_uInt16 nCurMax; //Mehr werden nicht aufgenommen.
+
+
+ void DeleteObj( SwCacheObj *pObj );
+
+#if OSL_DEBUG_LEVEL > 1
+ ByteString aName;
+ long nAppend; //Anzahl der Eintragungen durch Erweiterung.
+ long nInsertFree; //Anzahl der Eintragungen auf freie Plaetze.
+ long nReplace; //Anzahl der Ersetzungen durch ein neues Objekt
+ long nGetSuccess; //Anzahl der Erfolgreichen Get's
+ long nGetFail; //Anzahl der nicht Erfolgreichen Get's
+ long nToTop; //Anzahl der Umsortierungen (LRU)
+ long nDelete; //Anzahl der Loeschungen (von Aussen)
+ long nGetSeek; //Anzahl der Get's ohne Index
+ long nAverageSeekCnt; //Anzahl der Seek's fuer alle Get's ohne Index
+ long nFlushCnt; //Anzahl von Flush-Aufrufen.
+ long nFlushedObjects; //Anzahl der wg. Flush vernichteten Objekte
+ long nIncreaseMax; //Anzahl Cache-Erweiterungen
+ long nDecreaseMax; //Anzahl Cache-Verkleinerungen
+
+ void Check(); //Wird bei swcache.cxx mit DEBUG aktiv!
+#endif
+
+public:
+
+ //nur sal_uInt8 hineinstecken!!!
+#if OSL_DEBUG_LEVEL > 1
+ SwCache( const sal_uInt16 nInitSize, const sal_uInt16 nGrowSize,
+ const ByteString &rNm );
+ ~SwCache();
+#else
+ SwCache( const sal_uInt16 nInitSize, const sal_uInt16 nGrowSize );
+#endif
+
+ void Flush( const sal_uInt8 nPercent = 100 );
+
+ //bToTop == sal_False -> Keine LRU-Umsortierung!
+ SwCacheObj *Get( const void *pOwner, const sal_Bool bToTop = sal_True );
+ SwCacheObj *Get( const void *pOwner, const sal_uInt16 nIndex,
+ const sal_Bool bToTop = sal_True );
+ void ToTop( SwCacheObj *pObj );
+
+ sal_Bool Insert( SwCacheObj *pNew );
+ void Delete( const void *pOwner );
+// void Delete( const void *pOwner, const sal_uInt16 nIndex );
+
+ void SetLRUOfst( const sal_uInt16 nOfst ); //nOfst sagt wieviele unangetastet
+ //bleiben sollen.
+ void ResetLRUOfst() { pFirst = pRealFirst; }
+
+ inline void IncreaseMax( const sal_uInt16 nAdd );
+ inline void DecreaseMax( const sal_uInt16 nSub );
+ sal_uInt16 GetCurMax() const { return nCurMax; }
+ inline SwCacheObj *First() { return pRealFirst; }
+ inline SwCacheObj *Last() { return pLast; }
+ inline SwCacheObj *Next( SwCacheObj *pCacheObj);
+};
+
+//Cache-Manipulation auf die sichere Art.
+class SwSaveSetLRUOfst
+{
+ SwCache &rCache;
+public:
+ SwSaveSetLRUOfst( SwCache &rC, const sal_uInt16 nOfst )
+ : rCache( rC ) { rCache.SetLRUOfst( nOfst ); }
+
+ ~SwSaveSetLRUOfst() { rCache.ResetLRUOfst(); }
+};
+
+//Das allgemeine CacheObjekt. Anwender des Cache muessen eine Klasse vom
+//CacheObjekt ableiten und dort die Nutzdaten unterbringen.
+
+class SwCacheObj
+{
+ friend class SwCache; //Der darf alles
+
+ SwCacheObj *pNext; //Fuer die LRU-Verkettung.
+ SwCacheObj *pPrev;
+
+ sal_uInt16 nCachePos; //Position im Cache-Array.
+
+ sal_uInt8 nLock;
+
+ inline SwCacheObj *GetNext() { return pNext; }
+ inline SwCacheObj *GetPrev() { return pPrev; }
+ inline void SetNext( SwCacheObj *pNew ) { pNext = pNew; }
+ inline void SetPrev( SwCacheObj *pNew ) { pPrev = pNew; }
+
+ inline void SetCachePos( const sal_uInt16 nNew ) { nCachePos = nNew; }
+
+protected:
+ const void *pOwner;
+ inline void SetOwner( const void *pNew ) { pOwner = pNew; }
+
+public:
+
+ SwCacheObj( const void *pOwner );
+ virtual ~SwCacheObj();
+
+ inline const void *GetOwner() const { return pOwner; }
+ inline sal_Bool IsOwner( const void *pNew ) const;
+
+ inline sal_uInt16 GetCachePos() const { return nCachePos; }
+ inline void Invalidate() { pOwner = 0; }
+
+ inline sal_Bool IsLocked() const { return 0 != nLock; }
+
+#if OSL_DEBUG_LEVEL > 1
+ void Lock();
+ void Unlock();
+#else
+ inline void Lock() { ++nLock; }
+ inline void Unlock() { --nLock; }
+#endif
+
+ SwCacheObj *Next() { return pNext; }
+ SwCacheObj *Prev() { return pPrev; }
+
+};
+
+//Zugriffsklasse fuer den Cache. Im CTor wird das CacheObjekt erzeugt.
+//Wenn der Cache keines herausrueckt wird der Member zunaechst auf 0 gesetzt.
+//Beim Get wird dann eines erzeugt und, falls moeglich, in den Cache
+//eingetragen.
+//Anwender der des Cache muessen eine Klasse vom Access ableiten um
+//fuer Typsicherheit zu sorgen, die Basisklasse sollte fuer das Get aber immer
+//gerufen werden, ein Abgeleitetes Get sollte nur der Typsicherheit dienen.
+//Cache-Objekte werden stets gelockt solange die Instanz lebt.
+
+class SwCacheAccess
+{
+ SwCache &rCache;
+
+ void _Get();
+
+protected:
+ SwCacheObj *pObj;
+ const void *pOwner; //Kann ggf. in NewObj benutzt werden.
+
+ virtual SwCacheObj *NewObj() = 0;
+
+ inline SwCacheObj *Get();
+
+ inline SwCacheAccess( SwCache &rCache, const void *pOwner, sal_Bool bSeek = sal_True );
+ inline SwCacheAccess( SwCache &rCache, const void *pOwner, const sal_uInt16 nIndex );
+
+public:
+ virtual ~SwCacheAccess();
+
+ virtual sal_Bool IsAvailable() const;
+
+ //Abkuerzung fuer diejenigen, die wissen, das die Ableitung das IsAvailable
+ //nicht ueberladen haben.
+ sal_Bool IsAvail() const { return pObj != 0; }
+};
+
+inline void SwCache::IncreaseMax( const sal_uInt16 nAdd )
+{
+ nCurMax = nCurMax + sal::static_int_cast< sal_uInt16 >(nAdd);
+#if OSL_DEBUG_LEVEL > 1
+ ++nIncreaseMax;
+#endif
+}
+inline void SwCache::DecreaseMax( const sal_uInt16 nSub )
+{
+ if ( nCurMax > nSub )
+ nCurMax = nCurMax - sal::static_int_cast< sal_uInt16 >(nSub);
+#if OSL_DEBUG_LEVEL > 1
+ ++nDecreaseMax;
+#endif
+}
+
+inline sal_Bool SwCacheObj::IsOwner( const void *pNew ) const
+{
+ return pOwner && pOwner == pNew;
+}
+
+inline SwCacheObj *SwCache::Next( SwCacheObj *pCacheObj)
+{
+ if ( pCacheObj )
+ return pCacheObj->GetNext();
+ else
+ return NULL;
+}
+
+inline SwCacheAccess::SwCacheAccess( SwCache &rC, const void *pOwn, sal_Bool bSeek ) :
+ rCache( rC ),
+ pObj( 0 ),
+ pOwner( pOwn )
+{
+ if ( bSeek && pOwner && 0 != (pObj = rCache.Get( pOwner )) )
+ pObj->Lock();
+}
+
+inline SwCacheAccess::SwCacheAccess( SwCache &rC, const void *pOwn,
+ const sal_uInt16 nIndex ) :
+ rCache( rC ),
+ pObj( 0 ),
+ pOwner( pOwn )
+{
+ if ( pOwner && 0 != (pObj = rCache.Get( pOwner, nIndex )) )
+ pObj->Lock();
+}
+
+inline SwCacheObj *SwCacheAccess::Get()
+{
+ if ( !pObj )
+ _Get();
+ return pObj;
+}
+
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/inc/swfntcch.hxx b/sw/source/core/inc/swfntcch.hxx
new file mode 100644
index 000000000000..e57b6f7b1a41
--- /dev/null
+++ b/sw/source/core/inc/swfntcch.hxx
@@ -0,0 +1,102 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+#ifndef _SWFNTCCH_HXX
+#define _SWFNTCCH_HXX
+
+#include <tools/mempool.hxx>
+
+#define NUM_DEFAULT_VALUES 36
+
+#include "swcache.hxx"
+#include "swfont.hxx"
+
+class ViewShell;
+class SfxPoolItem;
+
+/*************************************************************************
+ * class SwFontCache
+ *************************************************************************/
+
+class SwFontCache : public SwCache
+{
+public:
+
+ inline SwFontCache() : SwCache(50,50
+#if OSL_DEBUG_LEVEL > 1
+ , "Globaler AttributSet/Font-Cache pSwFontCache"
+#endif
+ ) {}
+
+};
+
+// AttributSet/Font-Cache, globale Variable, in FontCache.Cxx angelegt
+extern SwFontCache *pSwFontCache;
+
+/*************************************************************************
+ * class SwFontObj
+ *************************************************************************/
+
+class SwFontObj : public SwCacheObj
+{
+ friend class SwFontAccess;
+
+private:
+ SwFont aSwFont;
+ const SfxPoolItem* pDefaultArray[ NUM_DEFAULT_VALUES ];
+
+public:
+ DECL_FIXEDMEMPOOL_NEWDEL(SwFontObj)
+
+ SwFontObj( const void* pOwner, ViewShell *pSh );
+
+ virtual ~SwFontObj();
+
+ inline SwFont *GetFont() { return &aSwFont; }
+ inline const SwFont *GetFont() const { return &aSwFont; }
+ inline const SfxPoolItem** GetDefault() { return pDefaultArray; }
+};
+
+/*************************************************************************
+ * class SwFontAccess
+ *************************************************************************/
+
+
+class SwFontAccess : public SwCacheAccess
+{
+ ViewShell *pShell;
+protected:
+ virtual SwCacheObj *NewObj( );
+
+public:
+ SwFontAccess( const void *pOwner, ViewShell *pSh );
+ SwFontObj *Get();
+};
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/inc/swfont.hxx b/sw/source/core/inc/swfont.hxx
new file mode 100644
index 000000000000..f0cf7bab6a32
--- /dev/null
+++ b/sw/source/core/inc/swfont.hxx
@@ -0,0 +1,899 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+#ifndef _SWFONT_HXX
+#define _SWFONT_HXX
+
+#include <i18npool/lang.h>
+#include <tools/color.hxx>
+#include <tools/stream.hxx>
+#include <editeng/svxfont.hxx>
+#include <swtypes.hxx>
+#include <drawfont.hxx> // SwDrawTextInfo
+
+class SfxItemSet;
+class SwAttrSet;
+class SwDoCapitals; // DoCapitals
+class SwDrawTextInfo; // _DrawText
+class SwScriptInfo; // _GetTxtSize
+class ViewShell;
+class IDocumentSettingAccess;
+
+const xub_Unicode CH_BLANK = ' '; // ' ' Leerzeichen
+const xub_Unicode CH_BREAK = 0x0A; //
+const xub_Unicode CH_TAB = '\t'; // \t
+const xub_Unicode CH_PAR = 0xB6; // Paragraph
+const xub_Unicode CH_BULLET = 0xB7; // mittiger Punkt
+
+class SwSubFont : public SvxFont
+{
+ friend class SwFont;
+ const void *pMagic; // "MagicNumber" innerhalb des Fontcaches
+ Size aSize; // Fremde kriegen nur diese Size zu sehen
+ sal_uInt16 nFntIndex; // Index im Fontcache
+ sal_uInt16 nOrgHeight; // Hoehe inkl. Escapement/Proportion
+ sal_uInt16 nOrgAscent; // Ascent inkl. Escapement/Proportion
+ sal_uInt16 nPropWidth; // proportional width
+ inline SwSubFont() : aSize(0,0)
+ { pMagic = NULL; nFntIndex = nOrgHeight = nOrgAscent = 0; nPropWidth =100; }
+
+ sal_uInt16 CalcEscAscent( const sal_uInt16 nOldAscent ) const;
+ sal_uInt16 CalcEscHeight( const sal_uInt16 nOldHeight,
+ const sal_uInt16 nOldAscent ) const;
+ void CalcEsc( SwDrawTextInfo& rInf, Point& rPos );
+
+ inline void CopyMagic( const SwSubFont& rFnt )
+ { pMagic = rFnt.pMagic; nFntIndex = rFnt.nFntIndex; }
+
+ sal_Bool operator==( const SwFont &rFnt ) const;
+ SwSubFont& operator=( const SwSubFont &rFont );
+
+ short _CheckKerning( );
+
+ sal_Bool ChgFnt( ViewShell *pSh, OutputDevice& rOut );
+ sal_Bool IsSymbol( ViewShell *pSh );
+ sal_uInt16 GetAscent( ViewShell *pSh, const OutputDevice& rOut );
+ sal_uInt16 GetHeight( ViewShell *pSh, const OutputDevice& rOut );
+ Size _GetTxtSize( SwDrawTextInfo& rInf );
+ Size GetCapitalSize( SwDrawTextInfo& rInf );
+ void _DrawText( SwDrawTextInfo &rInf, const sal_Bool bGrey );
+ void DrawCapital( SwDrawTextInfo &rInf );
+ void DrawStretchCapital( SwDrawTextInfo &rInf );
+ void DoOnCapitals( SwDoCapitals &rDo );
+ void _DrawStretchText( SwDrawTextInfo &rInf );
+ xub_StrLen _GetCrsrOfst( SwDrawTextInfo& rInf );
+ xub_StrLen GetCapitalCrsrOfst( SwDrawTextInfo& rInf );
+
+ inline void SetColor( const Color& rColor );
+ inline void SetFillColor( const Color& rColor );
+ inline void SetCharSet( const CharSet eCharSet );
+ inline void SetPitch( const FontPitch ePitch );
+ inline void SetAlign( const FontAlign eAlign );
+ inline void SetUnderline( const FontUnderline eUnderline );
+ inline void SetOverline( const FontUnderline eOverline );
+ inline void SetStrikeout( const FontStrikeout eStrikeout );
+ inline void SetItalic( const FontItalic eItalic );
+ inline void SetOutline( const sal_Bool bOutline );
+ inline void SetVertical( const sal_uInt16 nDir, const sal_Bool bVertFormat );
+ inline void SetShadow( const sal_Bool bShadow );
+ inline void SetAutoKern( const sal_uInt8 nAutoKern );
+ inline void SetWordLineMode( const sal_Bool bWordLineMode );
+ inline void SetEmphasisMark( const FontEmphasisMark eValue );
+ inline void SetRelief( const FontRelief eNew );
+
+ // Methoden fuer die Hoch-/Tiefstellung
+ inline void SetEscapement( const short nNewEsc );
+ inline void SetProportion( const sal_uInt8 nNewPropr );
+
+ inline void SetFamily( const FontFamily eFamily );
+ inline void SetName( const XubString& rName );
+ inline void SetStyleName( const XubString& rStyleName );
+ inline void SetSize( const Size& rSize );
+ inline void SetWeight( const FontWeight eWeight );
+ inline void SetLanguage( LanguageType eNewLang );
+ inline short CheckKerning()
+ { return GetFixKerning() >= 0 ? GetFixKerning() : _CheckKerning( ); }
+ inline void SetPropWidth( const sal_uInt16 nNew )
+ { pMagic = 0; nPropWidth = nNew; }
+public:
+ sal_uInt16 GetPropWidth() const { return nPropWidth; }
+};
+
+#define SW_LATIN 0
+#define SW_CJK 1
+#define SW_CTL 2
+#define SW_SCRIPTS 3
+
+class SwFont
+{ // CJK == Chinese, Japanese, Korean
+ // CTL == Complex text layout ( Hebrew, Arabic )
+ SwSubFont aSub[SW_SCRIPTS]; // Latin-, CJK- and CTL-font
+ Color* pBackColor; // background color (i.e. at character styles)
+ Color aUnderColor; // color of the underlining
+ Color aOverColor; // color of the overlining
+ sal_uInt8 nToxCnt; // Zaehlt die Schachtelungstiefe der Tox
+ sal_uInt8 nRefCnt; // Zaehlt die Schachtelungstiefe der Refs
+ sal_uInt8 m_nMetaCount; // count META/METAFIELD
+ sal_uInt8 nActual; // actual font (Latin, CJK or CTL)
+
+ // Schalter fuer die Font-Extensions
+ sal_Bool bNoHyph :1; // SwTxtNoHyphenHere: keine Trennstelle
+ sal_Bool bBlink :1; // blinkender Font
+ sal_Bool bPaintBlank :1; // Blanks nicht mit DrawRect
+ sal_Bool bFntChg :1;
+ sal_Bool bOrgChg :1; // nOrgHeight/Ascent sind invalid
+ sal_Bool bURL :1;
+ sal_Bool bPaintWrong :1; // Flag fuer Rechtschreibfehler
+ sal_Bool bGreyWave :1; // Fuers extended TextInput: Graue Wellenlinie
+ sal_Bool bNoColReplace :1; // Replacement without colormanipulation
+
+ sal_Bool operator==( const SwFont &rFnt ) const;
+
+protected:
+ inline SwFont() { pBackColor = NULL; nActual = SW_LATIN; }
+
+public:
+ SwFont( const SwAttrSet* pSet, const IDocumentSettingAccess* pIDocumentSettingAccess );
+ SwFont( const SwFont& rFont );
+
+ inline void ChgFnt( ViewShell *pSh, OutputDevice& rOut )
+ { bPaintBlank = aSub[nActual].ChgFnt( pSh, rOut ); }
+
+ ~SwFont(){ delete pBackColor; }
+
+ SwFont& operator=( const SwFont &rFont );
+
+ inline sal_uInt8 GetActual() const { return nActual; }
+ inline void SetActual( sal_uInt8 nNew );
+ inline const SvxFont& GetActualFont() const { return aSub[nActual]; }
+
+ // holt sich eine MagicNumber ueber SwFntAccess
+ void GoMagic( ViewShell *pSh, sal_uInt8 nWhich );
+ // set background color
+ void SetBackColor( Color* pNewColor );
+ inline const Color* GetBackColor() const{ return pBackColor; }
+
+ inline void ChkMagic( ViewShell *pSh, sal_uInt8 nWhich )
+ { if( !aSub[ nWhich ].pMagic ) GoMagic( pSh, nWhich ); }
+ // uebernimmt die MagicNumber eines (hoffentlich ident.) Kollegen
+ inline void CopyMagic( const SwFont* pFnt, sal_uInt8 nWhich )
+ { aSub[nWhich].CopyMagic( pFnt->aSub[nWhich] ); }
+ inline void GetMagic( const void* &rMagic, sal_uInt16 &rIdx, sal_uInt8 nWhich )
+ { rMagic = aSub[nWhich].pMagic; rIdx = aSub[nWhich].nFntIndex; }
+ inline void SetMagic( const void* pNew, const sal_uInt16 nIdx, sal_uInt8 nWhich )
+ { aSub[nWhich].pMagic = pNew; aSub[nWhich].nFntIndex = nIdx; }
+ inline sal_Bool DifferentMagic( const SwFont* pFnt, sal_uInt8 nWhich )
+ { return aSub[nWhich].pMagic != pFnt->aSub[nWhich].pMagic ||
+ !aSub[nWhich].pMagic || !pFnt->aSub[nWhich].pMagic; }
+
+ inline const Size &GetSize( sal_uInt8 nWhich ) const
+ { return aSub[nWhich].aSize; }
+ inline sal_Bool IsFntChg() const { return bFntChg; }
+ inline void SetFntChg( const sal_Bool bNew ) { bFntChg = bNew; }
+
+ // die gekapselten SV-Font-Methoden (setzen bFntChg auf sal_True)
+ inline void SetColor( const Color& rColor );
+ inline void SetFillColor( const Color& rColor );
+ inline void SetAlign( const FontAlign eAlign );
+ inline void SetUnderline( const FontUnderline eUnderline );
+ inline void SetUnderColor( const Color &rColor ) { aUnderColor = rColor; }
+ inline void SetOverline( const FontUnderline eOverline );
+ inline void SetOverColor( const Color &rColor ) { aOverColor = rColor; }
+ inline void SetStrikeout( const FontStrikeout eStrikeout );
+ inline void SetOutline( const sal_Bool bOutline );
+ void SetVertical( sal_uInt16 nDir, const sal_Bool nVertLayout = sal_False );
+ inline void SetShadow( const sal_Bool bShadow );
+ inline void SetAutoKern( sal_uInt8 nAutoKern );
+ inline void SetTransparent( const sal_Bool bTrans );
+ inline void SetWordLineMode( const sal_Bool bWordLineMode );
+ inline void SetFixKerning( const short nNewKern );
+ inline void SetCaseMap( const SvxCaseMap eNew );
+ inline void SetEmphasisMark( const FontEmphasisMark eValue );
+
+ // Methoden fuer die Hoch-/Tiefstellung
+ inline void SetEscapement( const short nNewEsc );
+ inline void SetProportion( const sal_uInt8 nNewPropr );
+
+ inline void SetPropWidth( const sal_uInt16 nNew );
+
+ inline void SetFamily( const FontFamily eFamily, const sal_uInt8 nWhich );
+ inline void SetName( const XubString& rName, const sal_uInt8 nWhich );
+ inline void SetStyleName( const XubString& rStyleName, const sal_uInt8 nWhich );
+ inline void SetSize( const Size& rSize, const sal_uInt8 nWhich );
+ inline void SetWeight( const FontWeight eWeight, const sal_uInt8 nWhich );
+ inline void SetItalic( const FontItalic eItalic, const sal_uInt8 nWhich );
+ inline void SetLanguage( LanguageType eNewLang, const sal_uInt8 nWhich );
+ inline void SetCharSet( const CharSet eCharSet, const sal_uInt8 nWhich );
+ inline void SetPitch( const FontPitch ePitch, const sal_uInt8 nWhich );
+ inline void SetRelief( const FontRelief eNew );
+
+ // Get/Set-Methoden fuer die aktuelle Einstellung
+ inline void SetNoHyph( const sal_Bool bNew );
+ inline sal_Bool IsNoHyph() const { return bNoHyph; }
+ inline void SetBlink( const sal_Bool bBlink );
+ inline sal_Bool IsBlink() const { return bBlink; }
+ inline sal_uInt8 &GetTox() { return nToxCnt; }
+ inline sal_uInt8 GetTox() const { return nToxCnt; }
+ inline sal_Bool IsTox() const { return ( 0 != nToxCnt ); }
+ inline sal_uInt8 &GetRef() { return nRefCnt; }
+ inline sal_uInt8 GetRef() const { return nRefCnt; }
+ inline sal_Bool IsRef() const { return ( 0 != nRefCnt ); }
+ inline sal_uInt8 &GetMeta() { return m_nMetaCount; }
+ inline sal_uInt8 GetMeta() const { return m_nMetaCount; }
+ inline bool IsMeta() const { return (0 != m_nMetaCount); }
+ inline void SetURL( const sal_Bool bURL );
+ inline sal_Bool IsURL() const { return bURL; }
+ inline void SetGreyWave( const sal_Bool bNew );
+ inline sal_Bool IsGreyWave() const { return bGreyWave; }
+ inline void SetNoCol( const sal_Bool bNew );
+ inline sal_Bool IsNoCol() const { return bNoColReplace; }
+
+ inline void SetPaintBlank( const sal_Bool bNew );
+ inline sal_Bool IsPaintBlank() const { return bPaintBlank; }
+ inline void SetPaintWrong( const sal_Bool bNew );
+ inline sal_Bool IsPaintWrong() const { return bPaintWrong; }
+
+ // Setzen der Basisklasse Font fuer SwTxtCharFmt
+ void SetDiffFnt( const SfxItemSet* pSet,
+ const IDocumentSettingAccess* pIDocumentSettingAccess );
+
+ inline const SvxFont &GetFnt( const sal_uInt8 nWhich ) const
+ { return aSub[nWhich]; };
+
+ sal_Bool IsSymbol( ViewShell *pSh )
+ { return aSub[nActual].IsSymbol( pSh ); }
+ FontUnderline GetUnderline() const { return aSub[nActual].GetUnderline(); }
+ const Color& GetUnderColor() const { return aUnderColor; }
+ FontUnderline GetOverline() const { return aSub[nActual].GetOverline(); }
+ const Color& GetOverColor() const { return aOverColor; }
+ short GetFixKerning() const { return aSub[nActual].GetFixKerning(); }
+ FontStrikeout GetStrikeout() const { return aSub[nActual].GetStrikeout(); }
+ const Color& GetColor() const { return aSub[nActual].GetColor(); }
+ sal_Bool IsShadow() const { return aSub[nActual].IsShadow(); }
+ sal_Bool IsWordLineMode() const { return aSub[nActual].IsWordLineMode(); }
+ sal_Bool IsOutline() const { return aSub[nActual].IsOutline(); }
+ sal_Bool IsKerning() const { return aSub[nActual].IsKerning(); }
+ short GetEscapement() const { return aSub[nActual].GetEscapement(); }
+ SvxCaseMap GetCaseMap() const { return aSub[nActual].GetCaseMap(); }
+ sal_uInt8 GetPropr() const { return aSub[nActual].GetPropr(); }
+ FontItalic GetItalic() const { return aSub[nActual].GetItalic(); }
+ LanguageType GetLanguage() const { return aSub[nActual].GetLanguage(); }
+ FontAlign GetAlign() const { return aSub[nActual].GetAlign(); }
+ const XubString& GetName() const { return aSub[nActual].GetName(); }
+ const XubString& GetStyleName() const {return aSub[nActual].GetStyleName();}
+ FontFamily GetFamily() const { return aSub[nActual].GetFamily(); }
+ FontPitch GetPitch() const { return aSub[nActual].GetPitch(); }
+ rtl_TextEncoding GetCharSet() const { return aSub[nActual].GetCharSet(); }
+ long GetHeight() const { return aSub[nActual].GetSize().Height(); }
+ FontWeight GetWeight() const { return aSub[nActual].GetWeight(); }
+ FontEmphasisMark GetEmphasisMark() const
+ { return aSub[nActual].GetEmphasisMark(); }
+ sal_uInt16 GetPropWidth() const { return aSub[nActual].GetPropWidth(); }
+ sal_uInt16 GetOrientation( const sal_Bool nVertLayout = sal_False ) const;
+
+ inline const XubString& GetName( const sal_uInt8 nWhich ) const
+ { return aSub[nWhich].GetName(); }
+ inline LanguageType GetLanguage( const sal_uInt8 nWhich ) const
+ { return aSub[nWhich].GetLanguage(); }
+ inline const XubString& GetStyleName( const sal_uInt8 nWhich ) const
+ { return aSub[nWhich].GetStyleName(); }
+ inline FontFamily GetFamily( const sal_uInt8 nWhich ) const
+ { return aSub[nWhich].GetFamily(); }
+ inline FontItalic GetItalic( const sal_uInt8 nWhich ) const
+ { return aSub[nWhich].GetItalic(); }
+ inline FontPitch GetPitch( const sal_uInt8 nWhich ) const
+ { return aSub[nWhich].GetPitch(); }
+ inline rtl_TextEncoding GetCharSet( const sal_uInt8 nWhich ) const
+ { return aSub[nWhich].GetCharSet(); }
+ inline long GetHeight( const sal_uInt8 nWhich ) const
+ { return aSub[nWhich].GetSize().Height(); }
+ inline FontWeight GetWeight( const sal_uInt8 nWhich ) const
+ { return aSub[nWhich].GetWeight(); }
+ inline FontEmphasisMark GetEmphasisMark( const sal_uInt8 nWhich ) const
+ { return aSub[nWhich].GetEmphasisMark(); }
+
+ // Macht den logischen Font im OutputDevice wirksam.
+ void ChgPhysFnt( ViewShell *pSh, OutputDevice& rOut );
+
+ Size GetCapitalSize( SwDrawTextInfo& rInf )
+ { return aSub[nActual].GetCapitalSize( rInf ); }
+
+ xub_StrLen GetCapitalBreak( ViewShell* pSh, const OutputDevice* pOut,
+ const SwScriptInfo* pScript, const XubString& rTxt,
+ long nTextWidth, xub_StrLen* pExtra, const xub_StrLen nIdx,
+ const xub_StrLen nLen );
+
+ xub_StrLen GetCapitalCrsrOfst( SwDrawTextInfo& rInf )
+ { return aSub[nActual].GetCapitalCrsrOfst( rInf ); }
+
+ void DrawCapital( SwDrawTextInfo &rInf )
+ { aSub[nActual].DrawCapital( rInf ); }
+
+ void DrawStretchCapital( SwDrawTextInfo &rInf )
+ { aSub[nActual].DrawStretchCapital( rInf ); }
+
+ void DoOnCapitals( SwDoCapitals &rDo )
+ { aSub[nActual].DoOnCapitals( rDo ); }
+
+ Size _GetTxtSize( SwDrawTextInfo& rInf )
+ { rInf.SetFont( this ); return aSub[nActual]._GetTxtSize( rInf ); }
+
+ xub_StrLen GetTxtBreak( SwDrawTextInfo& rInf, long nTextWidth );
+
+ xub_StrLen _GetCrsrOfst( SwDrawTextInfo& rInf )
+ { return aSub[nActual]._GetCrsrOfst( rInf ); }
+
+ inline void _DrawText( SwDrawTextInfo &rInf )
+ { aSub[nActual]._DrawText( rInf, IsGreyWave() ); }
+
+ inline void _DrawStretchText( SwDrawTextInfo &rInf )
+ { aSub[nActual]._DrawStretchText( rInf ); }
+
+ inline short CheckKerning()
+ { return aSub[nActual].CheckKerning(); }
+
+ inline sal_uInt16 GetAscent( ViewShell *pSh, const OutputDevice& rOut )
+ { return aSub[nActual].GetAscent( pSh, rOut ); }
+ inline sal_uInt16 GetHeight( ViewShell *pSh, const OutputDevice& rOut )
+ { return aSub[nActual].GetHeight( pSh, rOut ); }
+
+ inline void Invalidate()
+ { bFntChg = bOrgChg = sal_True; }
+};
+
+inline void SwFont::SetColor( const Color& rColor )
+{
+ bFntChg = sal_True;
+ aSub[0].SetColor( rColor );
+ aSub[1].SetColor( rColor );
+ aSub[2].SetColor( rColor );
+}
+
+// gekapselte SV-Font-Methode
+inline void SwSubFont::SetColor( const Color& rColor )
+{
+ pMagic = 0;
+ Font::SetColor( rColor );
+}
+
+
+// gekapselte SV-Font-Methode
+inline void SwSubFont::SetFillColor( const Color& rColor )
+{
+ pMagic = 0;
+ Font::SetFillColor( rColor );
+}
+
+inline void SwFont::SetFillColor( const Color& rColor )
+{
+ bFntChg = sal_True;
+ aSub[0].SetFillColor( rColor );
+ aSub[1].SetFillColor( rColor );
+ aSub[2].SetFillColor( rColor );
+}
+
+// gekapselte SV-Font-Methode
+inline void SwSubFont::SetFamily( const FontFamily eFamily )
+{
+ pMagic = 0;
+ Font::SetFamily( eFamily );
+}
+
+inline void SwFont::SetFamily( const FontFamily eFamily, const sal_uInt8 nWhich )
+{
+ bFntChg = sal_True;
+ aSub[nWhich].SetFamily( eFamily );
+}
+
+// gekapselte SV-Font-Methode
+inline void SwSubFont::SetName( const XubString& rName )
+{
+ pMagic = 0;
+ Font::SetName( rName );
+}
+
+inline void SwFont::SetName( const XubString& rName, const sal_uInt8 nWhich )
+{
+ bFntChg = sal_True;
+ aSub[nWhich].SetName( rName );
+}
+
+// gekapselte SV-Font-Methode
+inline void SwSubFont::SetStyleName( const XubString& rStyleName )
+{
+ pMagic = 0;
+ Font::SetStyleName( rStyleName );
+}
+
+inline void SwFont::SetStyleName( const XubString& rStyle, const sal_uInt8 nWhich )
+{
+ bFntChg = sal_True;
+ aSub[nWhich].SetStyleName( rStyle );
+}
+
+// gekapselte SV-Font-Methode
+inline void SwSubFont::SetCharSet( const CharSet eCharSet )
+{
+ pMagic = 0;
+ Font::SetCharSet( eCharSet );
+}
+
+inline void SwFont::SetCharSet( const CharSet eCharSet, const sal_uInt8 nWhich )
+{
+ bFntChg = sal_True;
+ aSub[nWhich].SetCharSet( eCharSet );
+}
+
+// gekapselte SV-Font-Methode
+inline void SwSubFont::SetPitch( const FontPitch ePitch )
+{
+ pMagic = 0;
+ Font::SetPitch( ePitch );
+}
+
+// gekapselte SV-Font-Methode
+inline void SwFont::SetPitch( const FontPitch ePitch, const sal_uInt8 nWhich )
+{
+ bFntChg = sal_True;
+ aSub[nWhich].SetPitch( ePitch );
+}
+
+// gekapselte SV-Font-Methode
+inline void SwSubFont::SetAlign( const FontAlign eAlign )
+{
+ pMagic = 0;
+ Font::SetAlign( eAlign );
+}
+
+inline void SwFont::SetAlign( const FontAlign eAlign )
+{
+ bFntChg = sal_True;
+ aSub[0].SetAlign( eAlign );
+ aSub[1].SetAlign( eAlign );
+ aSub[2].SetAlign( eAlign );
+}
+
+// gekapselte SV-Font-Methode
+inline void SwSubFont::SetWeight( const FontWeight eWeight )
+{
+ pMagic = 0;
+ Font::SetWeight( eWeight );
+}
+
+inline void SwFont::SetWeight( const FontWeight eWeight, const sal_uInt8 nWhich )
+{
+ bFntChg = sal_True;
+ aSub[nWhich].SetWeight( eWeight );
+}
+
+// gekapselte SV-Font-Methode
+inline void SwSubFont::SetUnderline( const FontUnderline eUnderline )
+{
+ pMagic = 0;
+ Font::SetUnderline( eUnderline );
+}
+
+inline void SwFont::SetUnderline( const FontUnderline eUnderline )
+{
+ bFntChg = sal_True;
+ aSub[0].SetUnderline( eUnderline );
+ aSub[1].SetUnderline( eUnderline );
+ aSub[2].SetUnderline( eUnderline );
+}
+
+// gekapselte SV-Font-Methode
+inline void SwSubFont::SetOverline( const FontUnderline eOverline )
+{
+ pMagic = 0;
+ Font::SetOverline( eOverline );
+}
+
+inline void SwFont::SetOverline( const FontUnderline eOverline )
+{
+ bFntChg = sal_True;
+ aSub[0].SetOverline( eOverline );
+ aSub[1].SetOverline( eOverline );
+ aSub[2].SetOverline( eOverline );
+}
+
+// gekapselte SV-Font-Methode
+inline void SwSubFont::SetStrikeout( const FontStrikeout eStrikeout )
+{
+ pMagic = 0;
+ Font::SetStrikeout( eStrikeout );
+}
+
+inline void SwFont::SetStrikeout( const FontStrikeout eStrikeout )
+{
+ bFntChg = sal_True;
+ aSub[0].SetStrikeout( eStrikeout );
+ aSub[1].SetStrikeout( eStrikeout );
+ aSub[2].SetStrikeout( eStrikeout );
+}
+
+// gekapselte SV-Font-Methode
+inline void SwSubFont::SetItalic( const FontItalic eItalic )
+{
+ pMagic = 0;
+ Font::SetItalic( eItalic );
+}
+
+inline void SwFont::SetItalic( const FontItalic eItalic, const sal_uInt8 nWhich )
+{
+ bFntChg = sal_True;
+ aSub[nWhich].SetItalic( eItalic );
+}
+
+// gekapselte SV-Font-Methode
+inline void SwSubFont::SetOutline( const sal_Bool bOutline )
+{
+ pMagic = 0;
+ Font::SetOutline( bOutline );
+}
+
+inline void SwFont::SetOutline( const sal_Bool bOutline )
+{
+ bFntChg = sal_True;
+ aSub[0].SetOutline( bOutline );
+ aSub[1].SetOutline( bOutline );
+ aSub[2].SetOutline( bOutline );
+}
+
+// gekapselte SV-Font-Methode
+inline void SwSubFont::SetShadow( const sal_Bool bShadow )
+{
+ pMagic = 0;
+ Font::SetShadow( bShadow );
+}
+
+inline void SwFont::SetShadow( const sal_Bool bShadow )
+{
+ bFntChg = sal_True;
+ aSub[0].SetShadow( bShadow );
+ aSub[1].SetShadow( bShadow );
+ aSub[2].SetShadow( bShadow );
+}
+
+// gekapselte SV-Font-Methode
+inline void SwSubFont::SetAutoKern( const sal_uInt8 nAutoKern )
+{
+ pMagic = 0;
+ Font::SetKerning( nAutoKern );
+}
+
+inline void SwFont::SetAutoKern( sal_uInt8 nAutoKern )
+{
+ bFntChg = sal_True;
+ aSub[1].SetAutoKern( nAutoKern );
+ if( nAutoKern )
+ nAutoKern = KERNING_FONTSPECIFIC;
+ aSub[0].SetAutoKern( nAutoKern );
+ aSub[2].SetAutoKern( nAutoKern );
+}
+
+inline void SwFont::SetTransparent( const sal_Bool bTrans )
+{
+ aSub[0].SetTransparent( bTrans );
+ aSub[1].SetTransparent( bTrans );
+ aSub[2].SetTransparent( bTrans );
+}
+
+inline void SwFont::SetFixKerning( const short nNewKern )
+{
+ aSub[SW_LATIN].SetFixKerning( nNewKern );
+ aSub[SW_CJK].SetFixKerning( nNewKern );
+ aSub[SW_CTL].SetFixKerning( nNewKern );
+}
+
+inline void SwFont::SetCaseMap( const SvxCaseMap eNew )
+{
+ aSub[SW_LATIN].SetCaseMap( eNew );
+ aSub[SW_CJK].SetCaseMap( eNew );
+ aSub[SW_CTL].SetCaseMap( eNew );
+}
+
+// gekapselte SV-Font-Methode
+inline void SwSubFont::SetWordLineMode( const sal_Bool bWordLineMode )
+{
+ pMagic = 0;
+ Font::SetWordLineMode( bWordLineMode );
+}
+
+inline void SwFont::SetWordLineMode( const sal_Bool bWordLineMode )
+{
+ bFntChg = sal_True;
+ aSub[0].SetWordLineMode( bWordLineMode );
+ aSub[1].SetWordLineMode( bWordLineMode );
+ aSub[2].SetWordLineMode( bWordLineMode );
+}
+// gekapselte SV-Font-Methode
+inline void SwSubFont::SetEmphasisMark( const FontEmphasisMark eValue )
+{
+ pMagic = 0;
+ Font::SetEmphasisMark( eValue );
+}
+
+inline void SwFont::SetEmphasisMark( const FontEmphasisMark eValue )
+{
+ bFntChg = sal_True;
+ aSub[0].SetEmphasisMark( eValue );
+ aSub[1].SetEmphasisMark( eValue );
+ aSub[2].SetEmphasisMark( eValue );
+}
+
+inline void SwFont::SetPropWidth( const sal_uInt16 nNew )
+{
+ if( nNew != aSub[0].GetPropWidth() )
+ {
+ bFntChg = sal_True;
+ aSub[0].SetPropWidth( nNew );
+ aSub[1].SetPropWidth( nNew );
+ aSub[2].SetPropWidth( nNew );
+ }
+}
+
+// gekapselte SV-Font-Methode
+inline void SwSubFont::SetRelief( const FontRelief eNew )
+{
+ pMagic = 0;
+ Font::SetRelief( eNew );
+}
+
+inline void SwFont::SetRelief( const FontRelief eNew )
+{
+ if( eNew != aSub[0].GetRelief() )
+ {
+ bFntChg = sal_True;
+ aSub[0].SetRelief( eNew );
+ aSub[1].SetRelief( eNew );
+ aSub[2].SetRelief( eNew );
+ }
+}
+
+// ueberladene Font-Methode
+inline void SwSubFont::SetSize( const Size& rSize )
+{
+ aSize = rSize;
+ if ( GetPropr() == 100 )
+ Font::SetSize( aSize );
+ else
+ {
+ Font::SetSize( Size(
+ (long) aSize.Width() * GetPropr() / 100L,
+ (long) aSize.Height() * GetPropr() / 100L ) );
+ }
+ pMagic = 0;
+}
+
+inline void SwFont::SetSize( const Size& rSize, const sal_uInt8 nWhich )
+{
+ if( aSub[nWhich].aSize != rSize )
+ {
+ aSub[nWhich].SetSize( rSize );
+ bFntChg = sal_True;
+ bOrgChg = sal_True;
+ }
+}
+
+inline void SwFont::SetActual( sal_uInt8 nNew )
+{
+ if ( nActual != nNew )
+ {
+ bFntChg = sal_True;
+ bOrgChg = sal_True;
+ nActual = nNew;
+ }
+}
+
+inline void SwSubFont::SetProportion( const sal_uInt8 nNewPropr )
+{
+ pMagic = 0;
+ Font::SetSize( Size( (long) aSize.Width() * nNewPropr / 100L,
+ (long) aSize.Height() * nNewPropr / 100L ) );
+ SvxFont::SetPropr( nNewPropr );
+}
+
+inline void SwFont::SetProportion( const sal_uInt8 nNewPropr )
+{
+ if( nNewPropr != aSub[0].GetPropr() )
+ {
+ bFntChg = sal_True;
+ bOrgChg = sal_True;
+
+ aSub[0].SetProportion( nNewPropr );
+ aSub[1].SetProportion( nNewPropr );
+ aSub[2].SetProportion( nNewPropr );
+ }
+}
+
+inline void SwSubFont::SetEscapement( const short nNewEsc )
+{
+ pMagic = 0;
+ SvxFont::SetEscapement( nNewEsc );
+}
+
+inline void SwFont::SetEscapement( const short nNewEsc )
+{
+ if( nNewEsc != aSub[0].GetEscapement() )
+ {
+ // these have to be set, otherwise nOrgHeight and nOrgAscent will not
+ // be calculated
+ bFntChg = sal_True;
+ bOrgChg = sal_True;
+
+ aSub[0].SetEscapement( nNewEsc );
+ aSub[1].SetEscapement( nNewEsc );
+ aSub[2].SetEscapement( nNewEsc );
+ }
+}
+
+inline void SwSubFont::SetLanguage( LanguageType eNewLang )
+{
+ if( eNewLang == LANGUAGE_SYSTEM )
+ eNewLang = (LanguageType)GetAppLanguage();
+ SvxFont::SetLanguage( eNewLang );
+}
+
+inline void SwFont::SetLanguage( const LanguageType eNewLang, const sal_uInt8 nWhich )
+{
+ aSub[nWhich].SetLanguage( eNewLang );
+ if( SW_CJK == nWhich )
+ {
+ aSub[SW_LATIN].SetCJKContextLanguage( eNewLang );
+ aSub[SW_CJK].SetCJKContextLanguage( eNewLang );
+ aSub[SW_CTL].SetCJKContextLanguage( eNewLang );
+ }
+}
+
+inline void SwFont::SetPaintBlank( const sal_Bool bNew )
+{
+ bPaintBlank = bNew;
+}
+
+inline void SwFont::SetPaintWrong( const sal_Bool bNew )
+{
+ bPaintWrong = bNew;
+}
+
+inline void SwFont::SetNoHyph( const sal_Bool bNew )
+{
+ bNoHyph = bNew;
+}
+
+inline void SwFont::SetBlink( const sal_Bool bNew )
+{
+ bBlink = bNew;
+}
+
+inline void SwFont::SetURL( const sal_Bool bNew )
+{
+ bURL = bNew;
+}
+
+inline void SwFont::SetGreyWave( const sal_Bool bNew )
+{
+ bGreyWave = bNew;
+}
+
+inline void SwFont::SetNoCol( const sal_Bool bNew )
+{
+ bNoColReplace = bNew;
+}
+
+inline void SwSubFont::SetVertical( const sal_uInt16 nDir, const sal_Bool bVertFormat )
+{
+ pMagic = 0;
+ Font::SetVertical( bVertFormat );
+ Font::SetOrientation( nDir );
+}
+
+
+/*************************************************************************
+ * class SwUnderlineFont
+ *
+ * Used for the "continuous underline" feature.
+ *************************************************************************/
+
+class SwUnderlineFont
+{
+ Point aPos;
+ SwFont* pFnt;
+
+public:
+ // sets the font which should paint the common baseline
+ // and the starting point of the common baseline
+ SwUnderlineFont( SwFont& rFnt, const Point& rPoint );
+ ~SwUnderlineFont();
+
+ SwFont& GetFont()
+ {
+ OSL_ENSURE( pFnt, "No underline font" );
+ return *pFnt;
+ }
+ const Point& GetPos() const { return aPos; }
+ // the x coordinate of the starting point has to be set for each portion
+ void SetPos( const Point& rPoint ) { aPos = rPoint; }
+};
+
+
+/*************************************************************************
+ * class SvStatistics
+ *************************************************************************/
+
+#if OSL_DEBUG_LEVEL > 1
+
+class SvStatistics
+{
+public:
+ sal_uInt16 nGetTextSize;
+ sal_uInt16 nDrawText;
+ sal_uInt16 nGetStretchTextSize;
+ sal_uInt16 nDrawStretchText;
+ sal_uInt16 nChangeFont;
+ sal_uInt16 nGetFontMetric;
+
+ inline void Reset()
+ {
+ nGetTextSize = nDrawText = nGetStretchTextSize =
+ nDrawStretchText = nChangeFont = nGetFontMetric = 0;
+ }
+
+ inline SvStatistics() { Reset(); }
+
+ inline void PrintOn( SvStream &rOS ) const; //$ ostream
+ inline sal_Bool IsEmpty() const
+ {
+ return !( nGetTextSize || nDrawText ||
+ nDrawStretchText || nChangeFont || nGetFontMetric );
+ }
+};
+
+// globale Variable, implementiert in swfont.cxx
+extern SvStatistics aSvStat;
+
+#define SV_STAT(nWhich) ++(aSvStat.nWhich);
+
+inline void SvStatistics::PrintOn( SvStream &rOS ) const //$ ostream
+{
+ if( IsEmpty() )
+ return;
+
+ rOS << "{ SV called:" << '\n';
+ if( nGetTextSize )
+ rOS << "\tnGetTextSize: " << nGetTextSize << '\n'; if( nDrawText )
+ rOS << "\tnDrawText: " << nDrawText << '\n'; if( nGetStretchTextSize )
+ rOS << "\tnGetStretchTextSize: " << nGetStretchTextSize << '\n'; if( nDrawStretchText )
+ rOS << "\tnDrawStretchText: " << nDrawStretchText << '\n'; if( nChangeFont )
+ rOS << "\tnChangeFont: " << nChangeFont << '\n'; if( nGetFontMetric )
+ rOS << "\tnGetFontMetric: " << nGetFontMetric << '\n'; rOS << "}" << '\n'; }
+#else
+#define SV_STAT(nWhich)
+#endif /* DEBUG */
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/inc/swselectionlist.hxx b/sw/source/core/inc/swselectionlist.hxx
new file mode 100644
index 000000000000..a3deb52ce66f
--- /dev/null
+++ b/sw/source/core/inc/swselectionlist.hxx
@@ -0,0 +1,100 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+#ifndef _SWSELECTIONLIST_HXX
+#define _SWSELECTIONLIST_HXX
+
+#include <list>
+
+class SwPaM;
+class SwFrm;
+
+/** This class is used as parameter for creation of a block cursor selection
+
+ This class will be created by a block cursor. Its responsibility is
+ to collect a group of selected text portions which are part of a common
+ context.
+ Definition of context:
+ A page header is a context.
+ A page footer is a context.
+ A footnote is a context.
+ Every fly frame builds a context together with its linked colleagues.
+ The content of the page bodies builds a context.
+*/
+
+class SwSelectionList
+{
+ std::list< SwPaM* > aList; // container for the selected text portions
+ const SwFrm* pContext; // the context of these text portions
+public:
+ /** Ctor to create an empty list for a given context
+
+ @param pInitCxt
+ The frame (normally a SwTxtFrm) where the block cursor selection starts,
+ it will be used to get the allowed context for the text selections.
+ */
+ explicit SwSelectionList( const SwFrm* pInitCxt );
+
+ /** Start of the container for the selected text portions
+ */
+ std::list<SwPaM*>::iterator getStart() { return aList.begin(); }
+
+ /** End of the container for the selected text portions
+ */
+ std::list<SwPaM*>::iterator getEnd() { return aList.end(); }
+
+ /** Adds a text portion to the selection list
+
+ @param pPam
+ represents a text portion to select
+ */
+ void insertPaM( SwPaM* pPam ) { aList.push_front( pPam ); }
+
+ /** Reports if the list does not contain any text portion
+
+ @return true, if list is empty
+ */
+ bool isEmpty() const { return aList.empty(); }
+
+ /** Checks if the context of the list is equal to the context of the frame
+
+ If the list does not have already a context, the context of the frame
+ will define the list's context.
+ If the list has already a context, it will be compared to the context of
+ the given frame.
+
+ @param pCheck
+ The frame to check
+
+ @return true, if the context of the frame is equal to the one of the list
+ */
+ bool checkContext( const SwFrm* pCheck );
+};
+
+#endif //_SWSELECTIONLIST_HXX
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/inc/swthreadjoiner.hxx b/sw/source/core/inc/swthreadjoiner.hxx
new file mode 100644
index 000000000000..e997e6dadc26
--- /dev/null
+++ b/sw/source/core/inc/swthreadjoiner.hxx
@@ -0,0 +1,54 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+#ifndef _SWTHREADJOINER_HXX
+#define _SWTHREADJOINER_HXX
+
+#include "com/sun/star/util/XJobManager.hpp"
+#include <osl/mutex.hxx>
+
+/** Testing
+
+ @author OD
+*/
+class SwThreadJoiner
+{
+ public:
+
+ static ::com::sun::star::uno::Reference< ::com::sun::star::util::XJobManager >& GetThreadJoiner();
+
+ static void ReleaseThreadJoiner();
+
+ private:
+ static ::com::sun::star::uno::Reference< ::com::sun::star::util::XJobManager > mpThreadJoiner;
+ static osl::Mutex* mpGetJoinerMutex;
+
+ SwThreadJoiner();
+};
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/inc/swthreadmanager.hxx b/sw/source/core/inc/swthreadmanager.hxx
new file mode 100644
index 000000000000..c44fe5109b62
--- /dev/null
+++ b/sw/source/core/inc/swthreadmanager.hxx
@@ -0,0 +1,86 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+#ifndef _SWTHREADMANAGER_HXX
+#define _SWTHREADMANAGER_HXX
+
+#include <osl/interlck.h>
+#include <osl/mutex.hxx>
+#include <rtl/ref.hxx>
+
+#include <boost/utility.hpp>
+#include <memory>
+
+
+class ObservableThread;
+class ThreadManager;
+
+/** class to manage threads in Writer using a <ThreadManager> instance
+
+ #i73788#
+ Conforms the singleton pattern
+*/
+class SwThreadManager
+ : private ::boost::noncopyable
+{
+ public:
+
+ static SwThreadManager& GetThreadManager();
+
+ static bool ExistsThreadManager();
+
+ // private: don't call!
+ SwThreadManager();
+ // private: don't call!
+ ~SwThreadManager();
+
+ oslInterlockedCount AddThread( const rtl::Reference< ObservableThread >& rThread );
+
+ void RemoveThread( const oslInterlockedCount nThreadID );
+
+ /** suspend the starting of threads
+
+ Suspending the starting of further threads is sensible during the
+ destruction of a Writer document.
+ */
+ void SuspendStartingOfThreads();
+
+ /** continues the starting of threads after it has been suspended
+ */
+ void ResumeStartingOfThreads();
+
+ bool StartingOfThreadsSuspended();
+
+ private:
+ static bool mbThreadManagerInstantiated;
+
+ ::std::auto_ptr<ThreadManager> mpThreadManagerImpl;
+
+};
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/inc/tabfrm.hxx b/sw/source/core/inc/tabfrm.hxx
new file mode 100644
index 000000000000..3527e2f6deff
--- /dev/null
+++ b/sw/source/core/inc/tabfrm.hxx
@@ -0,0 +1,238 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+#ifndef SW_TABFRM_HXX
+#define SW_TABFRM_HXX
+
+#include <tools/mempool.hxx>
+#include "layfrm.hxx"
+#include "flowfrm.hxx"
+
+class SwTable;
+class SwBorderAttrs;
+class SwAttrSetChg;
+
+class SwTabFrm: public SwLayoutFrm, public SwFlowFrm
+{
+ // OD 14.03.2003 #i11760# - adjustment, because of method signature change
+ //darf mit den Flags spielen.
+ friend void CalcCntnt( SwLayoutFrm *pLay, bool bNoColl, bool bNoCalcFollow );
+
+ //Fuert Spezialbehandlung fuer _Get[Next|Prev]Leaf() durch.
+ using SwFrm::GetLeaf;
+ SwLayoutFrm *GetLeaf( MakePageType eMakePage, sal_Bool bFwd );
+
+ SwTable* pTable;
+
+ sal_Bool bComplete :1; //Eintrage als Repaint ohne das CompletePaint
+ //der Basisklasse gesetzt werden muss. Damit
+ //sollen unertraegliche Tabellen-Repaints
+ //vermieden werden.
+ sal_Bool bCalcLowers :1; //Im MakeAll auf jedenfall auch fuer Stabilitaet
+ //des Inhaltes sorgen.
+ sal_Bool bLowersFormatted :1;//Kommunikation zwischen MakeAll und Layact
+ sal_Bool bLockBackMove :1; //BackMove-Test hat der Master erledigt.
+ sal_Bool bResizeHTMLTable :1; //Resize des HTMLTableLayout rufen im MakeAll
+ //Zur Optimierung, damit dies nicht im
+ //CntntFrm::Grow gerufen werden muss, denn dann
+ //wird es ggf. fuer jede Zelle gerufen #47483#
+ sal_Bool bONECalcLowers :1; //Primaer fuer die StarONE-SS. Beim MakeAll werden
+ //die Cntnts auf jedenfall per Calc() formatiert.
+ //es finden keine zusaetzlichen Invalidierungen
+ //statt und dieser Weg kann auch kaum garantien
+ //geben.
+
+ sal_Bool bHasFollowFlowLine :1; // Means that the first line in the follow
+ // is indented to contain content from a broken
+ // cell
+ sal_Bool bIsRebuildLastLine :1; // Means that currently the last line of the
+ // TabFrame is rebuilded. In this case we
+ // do not want any notification to the master
+ // table
+ sal_Bool bRestrictTableGrowth :1; // Usually, the table may grow infinite,
+ // because the table can be split in
+ // SwTabFrm::MakeAll. In MakeAll, this
+ // flag is set to indicate that the table
+ // may only grow inside its upper. This
+ // is necessary, in order to let the text
+ // flow into the FollowFlowLine
+ sal_Bool bRemoveFollowFlowLinePending :1;
+ // --> OD 2004-10-04 #i26945#
+ sal_Bool bConsiderObjsForMinCellHeight :1; // Usually, the floating screen objects
+ // are considered on the calculation
+ // for the minimal cell height.
+ // For splitting table rows algorithm
+ // it's needed not to consider floating
+ // screen object for the preparation
+ // of the re-calculation of the
+ // last table row.
+ // <--
+ // --> OD 2004-10-15 #i26945#
+ sal_Bool bObjsDoesFit :1; // For splitting table rows algorithm, this boolean
+ // indicates, if the floating screen objects fits
+ // <--
+ sal_Bool bDummy4 :1;
+
+ //Split() spaltet den Frm an der angegebenen Stelle, es wird ein
+ //Follow erzeugt und aufgebaut und direkt hinter this gepastet.
+ //Join() Holt sich den Inhalt aus dem Follow und vernichtet diesen.
+ bool Split( const SwTwips nCutPos, bool bTryToSplit, bool bTableRowKeep );
+ bool Join();
+
+ void _UpdateAttr( const SfxPoolItem*, const SfxPoolItem*, sal_uInt8 &,
+ SwAttrSetChg *pa = 0, SwAttrSetChg *pb = 0 );
+
+ virtual sal_Bool ShouldBwdMoved( SwLayoutFrm *pNewUpper, sal_Bool bHead, sal_Bool &rReformat );
+
+protected:
+ virtual void MakeAll();
+ virtual void Format( const SwBorderAttrs *pAttrs = 0 );
+ virtual void Modify( const SfxPoolItem*, const SfxPoolItem* );
+ //Aendert nur die Framesize, nicht die PrtArea-SSize
+ virtual SwTwips GrowFrm ( SwTwips, sal_Bool bTst = sal_False, sal_Bool bInfo = sal_False );
+
+public:
+ SwTabFrm( SwTable &, SwFrm* ); //Immer nach dem erzeugen _und_ pasten das
+ //Regist Flys rufen!
+ SwTabFrm( SwTabFrm & ); //_Nur_ zum erzeugen von Follows
+ ~SwTabFrm();
+
+ void JoinAndDelFollows(); //Fuer DelFrms des TableNodes!
+
+ //Ruft das RegistFlys der Zeilen.
+ void RegistFlys();
+
+ inline const SwTabFrm *GetFollow() const;
+ inline SwTabFrm *GetFollow();
+ SwTabFrm* FindMaster( bool bFirstMaster = false ) const;
+
+ virtual sal_Bool GetInfo( SfxPoolItem &rHnt ) const;
+ virtual void Paint( SwRect const&,
+ SwPrintData const*const pPrintData = NULL ) const;
+ virtual void CheckDirection( sal_Bool bVert );
+
+ virtual void Cut();
+ virtual void Paste( SwFrm* pParent, SwFrm* pSibling = 0 );
+
+ virtual void Prepare( const PrepareHint ePrep = PREP_CLEAR,
+ const void *pVoid = 0, sal_Bool bNotify = sal_True );
+
+ SwCntntFrm *FindLastCntnt();
+ inline const SwCntntFrm *FindLastCntnt() const;
+
+ const SwTable *GetTable() const { return pTable; }
+ SwTable *GetTable() { return pTable; }
+
+ sal_Bool IsComplete() { return bComplete; }
+ void SetComplete() { bComplete = sal_True; }
+ void ResetComplete() { bComplete = sal_False; }
+
+ sal_Bool IsLowersFormatted() const { return bLowersFormatted; }
+ void SetLowersFormatted( sal_Bool b ) { bLowersFormatted = b; }
+
+ void SetCalcLowers() { bCalcLowers = sal_True; } //Sparsam einsetzen!
+ void SetResizeHTMLTable() { bResizeHTMLTable = sal_True; } //dito
+ void SetONECalcLowers() { bONECalcLowers = sal_True; }
+
+ //
+ // Start: New stuff for breaking table rows
+ //
+ sal_Bool HasFollowFlowLine() const { return bHasFollowFlowLine; }
+ void SetFollowFlowLine( sal_Bool bNew ) { bHasFollowFlowLine = bNew; }
+
+ sal_Bool IsRebuildLastLine() const { return bIsRebuildLastLine; }
+ void SetRebuildLastLine( sal_Bool bNew ) { bIsRebuildLastLine = bNew; }
+
+ sal_Bool IsRestrictTableGrowth() const { return bRestrictTableGrowth; }
+ void SetRestrictTableGrowth( sal_Bool bNew ) { bRestrictTableGrowth = bNew; }
+
+ sal_Bool IsRemoveFollowFlowLinePending() const { return bRemoveFollowFlowLinePending; }
+ void SetRemoveFollowFlowLinePending( sal_Bool bNew ) { bRemoveFollowFlowLinePending = bNew; }
+
+ // --> OD 2004-10-04 #i26945#
+ sal_Bool IsConsiderObjsForMinCellHeight() const
+ {
+ return bConsiderObjsForMinCellHeight;
+ }
+ void SetConsiderObjsForMinCellHeight( sal_Bool _bNewConsiderObjsForMinCellHeight )
+ {
+ bConsiderObjsForMinCellHeight = _bNewConsiderObjsForMinCellHeight;
+ }
+ // <--
+ // --> OD 2004-10-04 #i26945#
+ sal_Bool DoesObjsFit() const
+ {
+ return bObjsDoesFit;
+ }
+ void SetDoesObjsFit( sal_Bool _bNewObjsDoesFit )
+ {
+ bObjsDoesFit = _bNewObjsDoesFit;
+ }
+ // <--
+
+ bool RemoveFollowFlowLine();
+ //
+ // End: New stuff for breaking table rows
+ //
+
+ sal_Bool CalcFlyOffsets( SwTwips& rUpper, long& rLeftOffset,
+ long& rRightOffset ) const;
+
+ SwTwips CalcHeightOfFirstContentLine() const;
+
+ bool IsInHeadline( const SwFrm& rFrm ) const;
+ SwRowFrm* GetFirstNonHeadlineRow() const;
+
+ bool IsLayoutSplitAllowed() const;
+
+ // --> collapsing borders FME 2005-05-27 #i29550#
+ bool IsCollapsingBorders() const;
+
+ // used for collapsing border lines:
+ sal_uInt16 GetBottomLineSize() const;
+ // <-- collapsing
+
+ DECL_FIXEDMEMPOOL_NEWDEL(SwTabFrm)
+};
+
+inline const SwCntntFrm *SwTabFrm::FindLastCntnt() const
+{
+ return ((SwTabFrm*)this)->FindLastCntnt();
+}
+
+inline const SwTabFrm *SwTabFrm::GetFollow() const
+{
+ return (const SwTabFrm*)SwFlowFrm::GetFollow();
+}
+inline SwTabFrm *SwTabFrm::GetFollow()
+{
+ return (SwTabFrm*)SwFlowFrm::GetFollow();
+}
+
+#endif // SW_TABFRM_HXX
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/inc/tblrwcl.hxx b/sw/source/core/inc/tblrwcl.hxx
new file mode 100644
index 000000000000..23866a3c47e4
--- /dev/null
+++ b/sw/source/core/inc/tblrwcl.hxx
@@ -0,0 +1,232 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+#ifndef _TBLRWCL_HXX
+#define _TBLRWCL_HXX
+#ifndef _SVSTDARR_HXX
+#define _SVSTDARR_USHORTS
+#include <svl/svstdarr.hxx>
+#endif
+#include <vector>
+#include <swtypes.hxx>
+#include <tblsel.hxx>
+#include <swtable.hxx>
+
+namespace editeng { class SvxBorderLine; }
+
+class SwDoc;
+class SwTableNode;
+class _FndLine;
+class _FndBox;
+class SwTableLine;
+class SwTableBox;
+class SwTableBoxFmt;
+class SwHistory;
+class SwCntntNode;
+class SfxPoolItem;
+class SwShareBoxFmts;
+class SwFmtFrmSize;
+
+// Funktions Deklarationen:
+sal_Bool lcl_CopyRow( const _FndLine*& rpFndLine, void* pPara );
+sal_Bool lcl_CopyCol( const _FndBox*& rpFndBox, void* pPara );
+
+sal_Bool lcl_MergeGCBox( const SwTableBox*& rpBox, void* pPara );
+sal_Bool lcl_MergeGCLine( const SwTableLine*& rpLine, void* pPara );
+
+sal_Bool lcl_Merge_MoveBox( const _FndBox*& rpFndBox, void* pPara );
+sal_Bool lcl_Merge_MoveLine( const _FndLine*& rpFndLine, void* pPara );
+
+sal_Bool lcl_CopyBoxToDoc( const _FndBox*& rpFndBox, void* pPara );
+sal_Bool lcl_CopyLineToDoc( const _FndLine*& rpFndLn, void* pPara );
+
+sal_Bool lcl_BoxSetHeadCondColl( const SwTableBox*& rpBox, void* pPara );
+sal_Bool lcl_LineSetHeadCondColl( const SwTableLine*& rpLine, void* pPara );
+
+
+#if OSL_DEBUG_LEVEL > 1
+void _CheckBoxWidth( const SwTableLine& rLine, SwTwips nSize );
+#endif
+
+void _InsTblBox( SwDoc* pDoc, SwTableNode* pTblNd,
+ SwTableLine* pLine, SwTableBoxFmt* pBoxFrmFmt,
+ SwTableBox* pBox, sal_uInt16 nInsPos, sal_uInt16 nCnt = 1 );
+
+SW_DLLPUBLIC void _DeleteBox( SwTable& rTbl, SwTableBox* pBox, SwUndo* pUndo = 0,
+ sal_Bool bCalcNewSize = sal_True, const sal_Bool bCorrBorder = sal_True,
+ SwShareBoxFmts* pShareFmts = 0 );
+
+// Klasse fuers SplitTable
+// sammelt von einer Line die Boxen aller obersten oder untersten Lines
+// in einem Array. Zusaetzlich werden die Positionen vermerkt.
+// ( die Implementierung steht im ndtbl.cxx)
+
+class SwCollectTblLineBoxes
+{
+ SvUShorts aPosArr;
+ SwSelBoxes_SAR aBoxes;
+ SwHistory* pHst;
+ sal_uInt16 nMode, nWidth;
+ sal_Bool bGetFromTop : 1;
+ sal_Bool bGetValues : 1;
+
+public:
+ SwCollectTblLineBoxes( sal_Bool bTop, sal_uInt16 nMd = 0, SwHistory* pHist=0 )
+ : aPosArr( 16, 16 ), aBoxes( 16, 16 ),
+ pHst( pHist ), nMode( nMd ), nWidth( 0 ),
+ bGetFromTop( bTop ), bGetValues( sal_True )
+
+ {}
+
+ void AddBox( const SwTableBox& rBox );
+ const SwTableBox* GetBoxOfPos( const SwTableBox& rBox );
+ void AddToUndoHistory( const SwCntntNode& rNd );
+
+ sal_uInt16 Count() const { return aBoxes.Count(); }
+ const SwTableBox& GetBox( sal_uInt16 nPos, sal_uInt16* pWidth = 0 ) const
+ {
+ // hier wird die EndPos der Spalte benoetigt!
+ if( pWidth )
+ *pWidth = nPos+1 == aPosArr.Count() ? nWidth
+ : aPosArr[ nPos+1 ];
+ return *aBoxes[ nPos ];
+ }
+
+ sal_Bool IsGetFromTop() const { return bGetFromTop; }
+ sal_Bool IsGetValues() const { return bGetValues; }
+
+ sal_uInt16 GetMode() const { return nMode; }
+ void SetValues( sal_Bool bFlag ) { bGetValues = sal_False; nWidth = 0;
+ bGetFromTop = bFlag; }
+ sal_Bool Resize( sal_uInt16 nOffset, sal_uInt16 nWidth );
+};
+
+sal_Bool lcl_Box_CollectBox( const SwTableBox*& rpBox, void* pPara );
+sal_Bool lcl_Line_CollectBox( const SwTableLine*& rpLine, void* pPara );
+
+sal_Bool lcl_BoxSetSplitBoxFmts( const SwTableBox*& rpBox, void* pPara );
+
+// This structure is needed by Undo to restore row span attributes
+// when a table has been splitted into two tables
+struct SwSaveRowSpan
+{
+ sal_uInt16 mnSplitLine; // the line number where the table has been splitted
+ std::vector< long > mnRowSpans; // the row span attributes in this line
+ SwSaveRowSpan( SwTableBoxes& rBoxes, sal_uInt16 nSplitLn );
+};
+
+struct _SwGCLineBorder
+{
+ const SwTableLines* pLines;
+ SwShareBoxFmts* pShareFmts;
+ sal_uInt16 nLinePos;
+
+ _SwGCLineBorder( const SwTable& rTable )
+ : pLines( &rTable.GetTabLines() ), pShareFmts(0), nLinePos( 0 ) {}
+
+ _SwGCLineBorder( const SwTableBox& rBox )
+ : pLines( &rBox.GetTabLines() ), pShareFmts(0), nLinePos( 0 ) {}
+ sal_Bool IsLastLine() const { return nLinePos + 1 >= pLines->Count(); }
+};
+
+class _SwGCBorder_BoxBrd
+{
+ const editeng::SvxBorderLine* pBrdLn;
+ sal_Bool bAnyBorderFnd;
+public:
+ _SwGCBorder_BoxBrd() : pBrdLn( 0 ), bAnyBorderFnd( sal_False ) {}
+
+ void SetBorder( const editeng::SvxBorderLine& rBorderLine )
+ { pBrdLn = &rBorderLine; bAnyBorderFnd = sal_False; }
+
+ // checke, ob die linke Border dieselbe wie die gesetzte ist
+ // returnt sal_False falls gar keine Border gesetzt ist
+ sal_Bool CheckLeftBorderOfFormat( const SwFrmFmt& rFmt );
+
+ sal_Bool IsAnyBorderFound() const { return bAnyBorderFnd; }
+};
+
+sal_Bool lcl_GC_Line_Border( const SwTableLine*& , void* pPara );
+sal_Bool lcl_GC_Box_Border( const SwTableBox*& , void* pPara );
+
+sal_Bool lcl_GCBorder_ChkBoxBrd_L( const SwTableLine*& , void* pPara );
+sal_Bool lcl_GCBorder_ChkBoxBrd_B( const SwTableBox*& , void* pPara );
+
+sal_Bool lcl_GCBorder_GetLastBox_L( const SwTableLine*& , void* pPara );
+sal_Bool lcl_GCBorder_GetLastBox_B( const SwTableBox*& , void* pPara );
+
+
+class SwShareBoxFmt
+{
+ const SwFrmFmt* pOldFmt;
+ SvPtrarr aNewFmts;
+
+public:
+ SwShareBoxFmt( const SwFrmFmt& rFmt )
+ : pOldFmt( &rFmt ), aNewFmts( 1, 4 )
+ {}
+
+ const SwFrmFmt& GetOldFormat() const { return *pOldFmt; }
+
+ SwFrmFmt* GetFormat( long nWidth ) const;
+ SwFrmFmt* GetFormat( const SfxPoolItem& rItem ) const;
+ void AddFormat( const SwFrmFmt& rFmt );
+ // returnt sal_True, wenn geloescht werden kann
+ sal_Bool RemoveFormat( const SwFrmFmt& rFmt );
+};
+
+
+SV_DECL_PTRARR_DEL( _SwShareBoxFmts, SwShareBoxFmt*, 8, 8 )
+
+class SwShareBoxFmts
+{
+ _SwShareBoxFmts aShareArr;
+ sal_Bool Seek_Entry( const SwFrmFmt& rFmt, sal_uInt16* pPos ) const;
+
+ void ChangeFrmFmt( SwTableBox* pBox, SwTableLine* pLn, SwFrmFmt& rFmt );
+
+public:
+ SwShareBoxFmts() {}
+ ~SwShareBoxFmts();
+
+ SwFrmFmt* GetFormat( const SwFrmFmt& rFmt, long nWidth ) const;
+ SwFrmFmt* GetFormat( const SwFrmFmt& rFmt, const SfxPoolItem& ) const;
+
+ void AddFormat( const SwFrmFmt& rOld, const SwFrmFmt& rNew );
+
+ void SetSize( SwTableBox& rBox, const SwFmtFrmSize& rSz );
+ void SetAttr( SwTableBox& rBox, const SfxPoolItem& rItem );
+ void SetAttr( SwTableLine& rLine, const SfxPoolItem& rItem );
+
+ void RemoveFormat( const SwFrmFmt& rFmt );
+};
+
+
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/inc/textapi.hxx b/sw/source/core/inc/textapi.hxx
new file mode 100644
index 000000000000..5692c7ae3c7f
--- /dev/null
+++ b/sw/source/core/inc/textapi.hxx
@@ -0,0 +1,73 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#include <editeng/unoedsrc.hxx>
+#include <editeng/unotext.hxx>
+#include <editeng/eeitem.hxx>
+#include <editeng/outliner.hxx>
+#include <editeng/unoipset.hxx>
+#include <editeng/unoprnms.hxx>
+#include <editeng/unoforou.hxx>
+
+class SwDoc;
+
+struct SwTextAPIEditSource_Impl;
+class SwTextAPIEditSource : public SvxEditSource
+{
+ SwTextAPIEditSource_Impl* pImpl;
+
+ virtual SvxEditSource* Clone() const;
+ virtual SvxTextForwarder* GetTextForwarder();
+ virtual void UpdateData();
+ explicit SwTextAPIEditSource( const SwTextAPIEditSource& rSource );
+
+public:
+ SwTextAPIEditSource(SwDoc* pDoc);
+ virtual ~SwTextAPIEditSource();
+
+ void Dispose();
+ void SetText( OutlinerParaObject& rText );
+ void SetString( const String& rText );
+ OutlinerParaObject* CreateText();
+ String GetText();
+};
+
+class SwTextAPIObject : public SvxUnoText
+{
+ SwTextAPIEditSource* pSource;
+public:
+ SwTextAPIObject( SwTextAPIEditSource* p);
+ virtual ~SwTextAPIObject() throw();
+ void DisposeEditSource() { pSource->Dispose(); }
+ OutlinerParaObject* CreateText() { return pSource->CreateText(); }
+ void SetString( const String& rText ) { pSource->SetString( rText ); }
+ void SetText( OutlinerParaObject& rText ) { pSource->SetText( rText ); }
+ String GetText() { return pSource->GetText(); }
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/inc/threadlistener.hxx b/sw/source/core/inc/threadlistener.hxx
new file mode 100644
index 000000000000..f6bc5edf8895
--- /dev/null
+++ b/sw/source/core/inc/threadlistener.hxx
@@ -0,0 +1,65 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+#ifndef _THREADLISTENER_HXX
+#define _THREADLISTENER_HXX
+
+#include <ifinishedthreadlistener.hxx>
+#include <ithreadlistenerowner.hxx>
+#include <observablethread.hxx>
+
+/** helper class to observe threads
+
+ OD 2007-03-30 #i73788#
+ An instance of this class can be used to observe a thread in order to
+ be notified, if the thread has finished its work. The notification is
+ directly forward to its owner - an instance of IThreadListenerOwner
+ Note:
+ - A thread can only have one or none listener.
+ - The notification is performed via the ThreadID
+
+ @author OD
+*/
+class ThreadListener : public IFinishedThreadListener
+{
+ public:
+
+ ThreadListener( IThreadListenerOwner& rThreadListenerOwner );
+ virtual ~ThreadListener();
+
+ void ListenToThread( const oslInterlockedCount nThreadID,
+ ObservableThread& rThread );
+
+ virtual void NotifyAboutFinishedThread( const oslInterlockedCount nThreadID );
+
+ private:
+
+ IThreadListenerOwner& mrThreadListenerOwner;
+};
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/inc/threadmanager.hxx b/sw/source/core/inc/threadmanager.hxx
new file mode 100644
index 000000000000..53ea5f7c689f
--- /dev/null
+++ b/sw/source/core/inc/threadmanager.hxx
@@ -0,0 +1,175 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+#ifndef _THREADMANAGER_HXX
+#define _THREADMANAGER_HXX
+
+#include <ithreadlistenerowner.hxx>
+#include <vcl/timer.hxx>
+#include <osl/mutex.hxx>
+#include <osl/interlck.h>
+#include <rtl/ref.hxx>
+
+#include <deque>
+#include <list>
+#include <cppuhelper/weak.hxx>
+#include "com/sun/star/util/XJobManager.hpp"
+#include <observablethread.hxx>
+#include <cancellablejob.hxx>
+#include <threadlistener.hxx>
+
+#include <boost/shared_ptr.hpp>
+#include <boost/weak_ptr.hpp>
+
+/** class to manage threads
+
+ OD 2007-01-29 #i73788#
+ An instance of this class takes care of the starting of threads.
+ It assures that not more than <mnStartedSize> threads
+ are started.
+
+ @author OD
+*/
+class ThreadManager : public IThreadListenerOwner
+{
+ public:
+
+ explicit ThreadManager( ::com::sun::star::uno::Reference< ::com::sun::star::util::XJobManager >& rThreadJoiner );
+ ~ThreadManager();
+
+ // --> IThreadListenerOwner
+ virtual boost::weak_ptr< IFinishedThreadListener > GetThreadListenerWeakRef();
+ virtual void NotifyAboutFinishedThread( const oslInterlockedCount nThreadID );
+ // <--
+
+ /** initialization
+
+ IMPORTANT NOTE: Needs to be called directly after construction
+
+ @author OD
+ */
+ void Init();
+
+ /** add thread to the thread manager and taking ownership for the thread
+
+ @author OD
+
+ @return unique ID for added thread
+ */
+ oslInterlockedCount AddThread(
+ const ::rtl::Reference< ObservableThread >& rThread );
+
+ void RemoveThread( const oslInterlockedCount nThreadID,
+ const bool bThreadFinished = false );
+
+ DECL_LINK( TryToStartNewThread, Timer* );
+
+ /** suspend the starting of threads
+
+ Suspending the starting of further threads is sensible during the
+ destruction of a Writer document.
+
+ @author OD
+ */
+ inline void SuspendStartingOfThreads()
+ {
+ osl::MutexGuard aGuard(maMutex);
+
+ mbStartingOfThreadsSuspended = true;
+ }
+
+ /** continues the starting of threads after it has been suspended
+
+ @author OD
+ */
+ void ResumeStartingOfThreads();
+
+ inline bool StartingOfThreadsSuspended()
+ {
+ osl::MutexGuard aGuard(maMutex);
+
+ return mbStartingOfThreadsSuspended;
+ }
+
+ struct tThreadData
+ {
+ oslInterlockedCount nThreadID;
+ ::rtl::Reference< ObservableThread > pThread;
+ com::sun::star::uno::Reference< com::sun::star::util::XCancellable > aJob;
+
+ tThreadData()
+ : nThreadID( 0 ),
+ pThread( 0 ),
+ aJob()
+ {}
+ };
+
+ private:
+
+ static const std::deque< tThreadData >::size_type mnStartedSize;
+
+ osl::Mutex maMutex;
+
+ ::com::sun::star::uno::WeakReference< ::com::sun::star::util::XJobManager > mrThreadJoiner;
+
+ boost::shared_ptr< ThreadListener > mpThreadListener;
+
+ oslInterlockedCount mnThreadIDCounter;
+
+ std::deque< tThreadData > maWaitingForStartThreads;
+ std::deque< tThreadData > maStartedThreads;
+
+ Timer maStartNewThreadTimer;
+
+ bool mbStartingOfThreadsSuspended;
+
+ struct ThreadPred
+ {
+ oslInterlockedCount mnThreadID;
+ explicit ThreadPred( oslInterlockedCount nThreadID )
+ : mnThreadID( nThreadID )
+ {}
+
+ bool operator() ( const tThreadData& rThreadData ) const
+ {
+ return rThreadData.nThreadID == mnThreadID;
+ }
+ };
+
+
+ inline oslInterlockedCount RetrieveNewThreadID()
+ {
+ return osl_incrementInterlockedCount( &mnThreadIDCounter );
+ }
+
+ bool StartWaitingThread();
+
+ bool StartThread( const tThreadData& aThreadData );
+};
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/inc/tocntntanchoredobjectposition.hxx b/sw/source/core/inc/tocntntanchoredobjectposition.hxx
new file mode 100644
index 000000000000..ac5c8ac5424c
--- /dev/null
+++ b/sw/source/core/inc/tocntntanchoredobjectposition.hxx
@@ -0,0 +1,99 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+ /*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+#ifndef _TOCNTNTANCHOREDOBJECTPOSITION_HXX
+#define _TOCNTNTANCHOREDOBJECTPOSITION_HXX
+#include <anchoredobjectposition.hxx>
+
+class SwFrm;
+class SwTxtFrm;
+class SwLayoutFrm;
+class SwRect;
+
+namespace objectpositioning
+{
+ class SwToCntntAnchoredObjectPosition : public SwAnchoredObjectPosition
+ {
+ private:
+ // calculated data for object position
+ const SwLayoutFrm* mpVertPosOrientFrm;
+ // #i26791#
+ // determine offset to frame anchor position according to the
+ // positioning alignments
+ Point maOffsetToFrmAnchorPos;
+
+ // data for calculation of position
+ bool mbAnchorToChar;
+ const SwFrm* mpToCharOrientFrm;
+ const SwRect* mpToCharRect;
+ SwTwips mnToCharTopOfLine;
+
+ virtual bool IsAnchoredToChar() const;
+ virtual const SwFrm* ToCharOrientFrm() const;
+ virtual const SwRect* ToCharRect() const;
+ // #i22341#
+ virtual SwTwips ToCharTopOfLine() const;
+
+ // method to cast <SwAnchoredObjectPosition::GetAnchorFrm()> to
+ // the needed type
+ SwTxtFrm& GetAnchorTxtFrm() const;
+
+ // *********************************************************************
+ /** determine frame for horizontal position
+
+ if the given proposed frame is a content frame, the proposed
+ frame is returned.
+ otherwise (given proposed frame is a layout frame),
+ the lower content frames of the proposed frame are checked
+ for the first, that the anchor or a follow of the anchor.
+ If none is found, the proposed frame is returned.
+
+ @param _pProposedFrm
+ input parameter - proposed frame for horizontal position
+
+ @return constant reference to <SwFrm> object, at which the
+ horizontal position is determined.
+ */
+ const SwFrm& _GetHoriVirtualAnchor( const SwLayoutFrm& _pProposedFrm ) const;
+
+ public:
+ SwToCntntAnchoredObjectPosition( SdrObject& _rDrawObj );
+ virtual ~SwToCntntAnchoredObjectPosition();
+
+ /** calculate position of object
+ */
+ virtual void CalcPosition();
+
+ /** frame, at which the vertical position is oriented at
+ */
+ const SwLayoutFrm& GetVertPosOrientFrm() const;
+ };
+} // namespace objectpositioning
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/inc/tolayoutanchoredobjectposition.hxx b/sw/source/core/inc/tolayoutanchoredobjectposition.hxx
new file mode 100644
index 000000000000..6387b8e7ced4
--- /dev/null
+++ b/sw/source/core/inc/tolayoutanchoredobjectposition.hxx
@@ -0,0 +1,63 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+ /*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+#ifndef _TOLAYOUTANCHOREDOBJECTPOSITION_HXX
+#define _TOLAYOUTANCHOREDOBJECTPOSITION_HXX
+#include <anchoredobjectposition.hxx>
+#include <swtypes.hxx>
+#include <swrect.hxx>
+
+namespace objectpositioning
+{
+ class SwToLayoutAnchoredObjectPosition : public SwAnchoredObjectPosition
+ {
+ private:
+ // calculated data for object position type TO_LAYOUT
+ Point maRelPos;
+
+ // #i26791#
+ // determine offset to frame anchor position according to the
+ // positioning alignments
+ Point maOffsetToFrmAnchorPos;
+
+ public:
+ SwToLayoutAnchoredObjectPosition( SdrObject& _rDrawObj );
+ virtual ~SwToLayoutAnchoredObjectPosition();
+
+ /** calculate position for object
+ */
+ virtual void CalcPosition();
+
+ /** calculated relative position for object
+ */
+ Point GetRelPos() const;
+ };
+} // namespace objectpositioning
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/inc/toxhlp.hxx b/sw/source/core/inc/toxhlp.hxx
new file mode 100644
index 000000000000..b254874009bf
--- /dev/null
+++ b/sw/source/core/inc/toxhlp.hxx
@@ -0,0 +1,79 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef _TOXHLP_HXX
+#define _TOXHLP_HXX
+
+#include <tools/solar.h>
+#include <com/sun/star/lang/Locale.hpp>
+#include <com/sun/star/uno/Reference.hxx>
+#include <swunodef.hxx>
+
+namespace com { namespace sun { namespace star {
+namespace i18n {
+ class XExtendedIndexEntrySupplier;
+}
+namespace lang {
+ class XMultiServiceFactory;
+}
+}}}
+
+
+class String;
+
+class IndexEntrySupplierWrapper
+{
+ STAR_NMSPC::lang::Locale aLcl;
+ STAR_NMSPC::uno::Reference < com::sun::star::i18n::XExtendedIndexEntrySupplier > xIES;
+
+public:
+ IndexEntrySupplierWrapper(
+ const STAR_NMSPC::lang::Locale& rLcl,
+ STAR_REFERENCE( lang::XMultiServiceFactory )& rxMSF );
+ ~IndexEntrySupplierWrapper();
+
+ String GetIndexKey( const String& rTxt, const String& rTxtReading,
+ const STAR_NMSPC::lang::Locale& rLocale ) const;
+
+ String GetFollowingText( sal_Bool bMorePages ) const;
+
+ STAR_NMSPC::uno::Sequence< ::rtl::OUString >
+ GetAlgorithmList( const STAR_NMSPC::lang::Locale& rLcl ) const;
+
+ sal_Bool LoadAlgorithm( const STAR_NMSPC::lang::Locale& rLcl,
+ const String& sSortAlgorithm, long nOptions ) const;
+
+ sal_Int16 CompareIndexEntry( const String& rTxt1, const String& rTxtReading1,
+ const STAR_NMSPC::lang::Locale& rLcl1,
+ const String& rTxt2, const String& rTxtReading2,
+ const STAR_NMSPC::lang::Locale& rLcl2 ) const;
+};
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/inc/txmsrt.hxx b/sw/source/core/inc/txmsrt.hxx
new file mode 100644
index 000000000000..75ad22213c79
--- /dev/null
+++ b/sw/source/core/inc/txmsrt.hxx
@@ -0,0 +1,297 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+#ifndef SW_TXMSRT_HXX
+#define SW_TXMSRT_HXX
+
+#include <i18npool/lang.h>
+#include <tox.hxx>
+
+#include <com/sun/star/lang/Locale.hpp>
+
+
+class CharClass;
+class SwCntntNode;
+class SwTxtNode;
+class SwTxtTOXMark;
+class SwIndex;
+class SwFmtFld;
+class IndexEntrySupplierWrapper;
+
+enum TOXSortType
+{
+ TOX_SORT_INDEX,
+ TOX_SORT_CUSTOM,
+ TOX_SORT_CONTENT,
+ TOX_SORT_PARA,
+ TOX_SORT_TABLE,
+ TOX_SORT_AUTHORITY
+};
+
+struct SwTOXSource
+{
+ const SwCntntNode* pNd;
+ xub_StrLen nPos;
+ sal_Bool bMainEntry;
+
+ SwTOXSource() : pNd(0), nPos(0), bMainEntry(sal_False) {}
+ SwTOXSource( const SwCntntNode* pNode, xub_StrLen n, sal_Bool bMain )
+ : pNd(pNode), nPos(n), bMainEntry(bMain)
+ {}
+};
+
+SV_DECL_VARARR( SwTOXSources, SwTOXSource, 0, 10 )
+
+class SwTOXInternational
+{
+ IndexEntrySupplierWrapper* pIndexWrapper;
+ CharClass* pCharClass;
+ LanguageType eLang;
+ String sSortAlgorithm;
+ sal_uInt16 nOptions;
+
+ void Init();
+
+public:
+ SwTOXInternational( LanguageType nLang, sal_uInt16 nOptions,
+ const String& rSortAlgorithm );
+ SwTOXInternational( const SwTOXInternational& );
+ ~SwTOXInternational();
+
+ sal_Int32 Compare( const String& rTxt1, const String& rTxtReading1,
+ const ::com::sun::star::lang::Locale& rLocale1,
+ const String& rTxt2, const String& rTxtReading2,
+ const ::com::sun::star::lang::Locale& rLocale2 ) const;
+
+ inline sal_Bool IsEqual( const String& rTxt1, const String& rTxtReading1,
+ const ::com::sun::star::lang::Locale& rLocale1,
+ const String& rTxt2, const String& rTxtReading2,
+ const ::com::sun::star::lang::Locale& rLocale2 ) const
+ {
+ return 0 == Compare( rTxt1, rTxtReading1, rLocale1,
+ rTxt2, rTxtReading2, rLocale2 );
+ }
+
+ inline sal_Bool IsLess( const String& rTxt1, const String& rTxtReading1,
+ const ::com::sun::star::lang::Locale& rLocale1,
+ const String& rTxt2, const String& rTxtReading2,
+ const ::com::sun::star::lang::Locale& rLocale2 ) const
+ {
+ return -1 == Compare( rTxt1, rTxtReading1, rLocale1,
+ rTxt2, rTxtReading2, rLocale2 );
+ }
+
+ String GetIndexKey( const String& rTxt, const String& rTxtReading,
+ const ::com::sun::star::lang::Locale& rLcl ) const;
+
+ String GetFollowingText( sal_Bool bMorePages ) const;
+
+ String ToUpper( const String& rStr, xub_StrLen nPos ) const;
+ inline sal_Bool IsNumeric( const String& rStr ) const;
+};
+
+/*--------------------------------------------------------------------
+ Beschreibung: Klassen fuer die Sortierung der Verzeichnisse
+ --------------------------------------------------------------------*/
+
+struct SwTOXSortTabBase
+{
+ SwTOXSources aTOXSources;
+ ::com::sun::star::lang::Locale aLocale;
+ const SwTxtNode* pTOXNd;
+ const SwTxtTOXMark* pTxtMark;
+ const SwTOXInternational* pTOXIntl;
+ sal_uLong nPos;
+ xub_StrLen nCntPos;
+ sal_uInt16 nType;
+ static sal_uInt16 nOpt;
+
+ SwTOXSortTabBase( TOXSortType nType,
+ const SwCntntNode* pTOXSrc,
+ const SwTxtTOXMark* pTxtMark,
+ const SwTOXInternational* pIntl,
+ const ::com::sun::star::lang::Locale* pLocale = NULL );
+ virtual ~SwTOXSortTabBase() {}
+
+ sal_uInt16 GetType() const { return nType; }
+ sal_uInt16 GetOptions() const { return nOpt; }
+
+ virtual void FillText( SwTxtNode& rNd, const SwIndex& rInsPos, sal_uInt16 nAuthField = 0) const;
+ virtual sal_uInt16 GetLevel() const = 0;
+ virtual sal_Bool operator==( const SwTOXSortTabBase& );
+ virtual sal_Bool operator<( const SwTOXSortTabBase& );
+
+ virtual String GetURL() const;
+
+ inline void GetTxt( String&, String& ) const;
+ inline const ::com::sun::star::lang::Locale& GetLocale() const;
+
+private:
+ sal_Bool bValidTxt;
+ String sSortTxt;
+ String sSortTxtReading;
+
+ virtual void GetText_Impl( String&, String& ) const = 0;
+};
+
+inline void SwTOXSortTabBase::GetTxt( String& rSortTxt,
+ String& rSortTxtReading ) const
+{
+ if( !bValidTxt )
+ {
+ SwTOXSortTabBase* pThis = (SwTOXSortTabBase*)this;
+ pThis->GetText_Impl( pThis->sSortTxt, pThis->sSortTxtReading );
+ pThis->bValidTxt = sal_True;
+ }
+
+ rSortTxt = sSortTxt;
+ rSortTxtReading = sSortTxtReading;
+}
+
+inline const ::com::sun::star::lang::Locale& SwTOXSortTabBase::GetLocale() const
+{
+ return aLocale;
+}
+
+/*--------------------------------------------------------------------
+ Beschreibung: fuer Sortierung nach Text
+ --------------------------------------------------------------------*/
+
+struct SwTOXIndex : public SwTOXSortTabBase
+{
+ SwTOXIndex( const SwTxtNode&, const SwTxtTOXMark*, sal_uInt16 nOptions, sal_uInt8 nKeyLevel,
+ const SwTOXInternational& rIntl,
+ const ::com::sun::star::lang::Locale& rLocale );
+ virtual ~SwTOXIndex() {}
+
+
+ virtual void FillText( SwTxtNode& rNd, const SwIndex& rInsPos, sal_uInt16 nAuthField = 0 ) const;
+ virtual sal_uInt16 GetLevel() const;
+ virtual sal_Bool operator==( const SwTOXSortTabBase& );
+ virtual sal_Bool operator<( const SwTOXSortTabBase& );
+
+private:
+ virtual void GetText_Impl( String&, String& ) const;
+
+ sal_uInt8 nKeyLevel;
+};
+
+struct SwTOXCustom : public SwTOXSortTabBase
+{
+ SwTOXCustom( const String& rKey, const String& rReading, sal_uInt16 nLevel,
+ const SwTOXInternational& rIntl,
+ const ::com::sun::star::lang::Locale& rLocale );
+ virtual ~SwTOXCustom() {}
+
+ virtual sal_uInt16 GetLevel() const;
+ virtual sal_Bool operator==( const SwTOXSortTabBase& );
+ virtual sal_Bool operator<( const SwTOXSortTabBase& );
+
+private:
+ virtual void GetText_Impl( String&, String& ) const;
+
+ String aKey;
+ String sReading;
+ sal_uInt16 nLev;
+};
+
+/*--------------------------------------------------------------------
+ Beschreibung: fuer Sortierung nach Position
+ --------------------------------------------------------------------*/
+
+struct SwTOXContent : public SwTOXSortTabBase
+{
+ SwTOXContent( const SwTxtNode&, const SwTxtTOXMark*,
+ const SwTOXInternational& rIntl );
+ virtual ~SwTOXContent() {}
+
+ virtual void FillText( SwTxtNode& rNd, const SwIndex& rInsPos, sal_uInt16 nAuthField = 0 ) const;
+ virtual sal_uInt16 GetLevel() const;
+private:
+ virtual void GetText_Impl( String&, String& ) const;
+
+};
+
+struct SwTOXPara : public SwTOXSortTabBase
+{
+ SwTOXPara( const SwCntntNode&, SwTOXElement, sal_uInt16 nLevel = FORM_ALPHA_DELIMITTER );
+ virtual ~SwTOXPara() {}
+
+ void SetStartIndex( xub_StrLen nSet) { nStartIndex = nSet;}
+ void SetEndIndex( xub_StrLen nSet ) { nEndIndex = nSet;}
+
+ virtual void FillText( SwTxtNode& rNd, const SwIndex& rInsPos, sal_uInt16 nAuthField = 0 ) const;
+ virtual sal_uInt16 GetLevel() const;
+
+ virtual String GetURL() const;
+private:
+ virtual void GetText_Impl( String&, String& ) const;
+
+ SwTOXElement eType;
+ sal_uInt16 m_nLevel;
+ xub_StrLen nStartIndex;
+ xub_StrLen nEndIndex;
+};
+
+struct SwTOXTable : public SwTOXSortTabBase
+{
+ SwTOXTable( const SwCntntNode& rNd );
+ virtual ~SwTOXTable() {}
+
+ void SetLevel(sal_uInt16 nSet){nLevel = nSet;}
+
+ virtual sal_uInt16 GetLevel() const;
+
+ virtual String GetURL() const;
+private:
+ virtual void GetText_Impl( String&, String& ) const;
+
+ sal_uInt16 nLevel;
+};
+
+struct SwTOXAuthority : public SwTOXSortTabBase
+{
+private:
+ SwFmtFld& m_rField;
+ virtual void FillText( SwTxtNode& rNd, const SwIndex& rInsPos, sal_uInt16 nAuthField = 0 ) const;
+ virtual void GetText_Impl( String&, String& ) const;
+
+public:
+ SwTOXAuthority( const SwCntntNode& rNd, SwFmtFld& rField, const SwTOXInternational& rIntl );
+ virtual ~SwTOXAuthority() {}
+
+ SwFmtFld& GetFldFmt() {return m_rField;}
+
+ virtual sal_Bool operator==( const SwTOXSortTabBase& );
+ virtual sal_Bool operator<( const SwTOXSortTabBase& );
+ virtual sal_uInt16 GetLevel() const;
+};
+
+
+#endif // SW_TXMSRT_HXX
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/inc/txtfrm.hxx b/sw/source/core/inc/txtfrm.hxx
new file mode 100644
index 000000000000..07deaf40678c
--- /dev/null
+++ b/sw/source/core/inc/txtfrm.hxx
@@ -0,0 +1,795 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+#ifndef SW_TXTFRM_HXX
+#define SW_TXTFRM_HXX
+
+#include <tools/mempool.hxx>
+#include <tools/string.hxx>
+#include "cntfrm.hxx"
+
+#define STRSIZE(x) (sizeof(x)-1)
+
+class SwCharRange;
+class SwTxtNode;
+class SwTxtFormatter;
+class SwTxtFormatInfo;
+class SwParaPortion;
+class WidowsAndOrphans;
+class SwBodyFrm;
+class SwTxtFtn;
+class SwInterHyphInfo; // Hyphenate()
+class SwCache;
+class SwBorderAttrs;
+class SwFrmFmt;
+class OutputDevice;
+class SwTestFormat;
+struct SwCrsrMoveState;
+struct SwFillData;
+class SwPortionHandler;
+class SwScriptInfo;
+class SwViewOption;
+class SwWrongList;
+
+#define GRID_ON 0
+#define GRID_HEIGHT 1
+#define RUBY_HEIGHT 2
+#define RUBY_TOP 3
+#define GRID_CELLS 4
+
+class SwTxtFrm: public SwCntntFrm
+{
+ friend class SwTxtIter;
+ friend class SwTestFormat;
+ friend class WidowsAndOrphans;
+ friend class SwTxtFrmLocker; // duerfen Lock()/Unlock()
+ friend sal_Bool lcl_ChangeOffset( SwTxtFrm* pFrm, sal_uInt16 nNew );
+
+ static SwCache *pTxtCache; //Pointer auf den Line-Cache
+ static long nMinPrtLine; //Diese Linie darf beim Drucken nicht
+ //unterschritten werden, Hack fuer Tabellenzellen ueber mehrere Seiten
+
+ sal_uLong nAllLines :24;//Anzahl der Zeilen fuer das Paint (inkl. nThisLines)
+ sal_uLong nThisLines :8; //Anzahl der Zeilen dieses Frames
+
+ // The x position for flys anchored at this paragraph.
+ // These values are calculated in SwTxtFrm::CalcBaseOfstForFly()
+ SwTwips mnFlyAnchorOfst;
+ // The x position for wrap-through flys anchored at this paragraph.
+ SwTwips mnFlyAnchorOfstNoWrap;
+ SwTwips mnFtnLine;
+ // OD 2004-03-17 #i11860# - re-factoring of #i11859#
+ // member for height of last line (value needed for proportional line spacing)
+ SwTwips mnHeightOfLastLine;
+ // member for the additional first line offset, which is caused by the list
+ // label alignment for list level position and space mode LABEL_ALIGNMENT.
+ // This additional first line offset is used for the text formatting.
+ // It is NOT used for the determination of printing area.
+ SwTwips mnAdditionalFirstLineOffset;
+
+
+ xub_StrLen nOfst; //nOfst gibt den Offset im Cntnt (Anzahl Zeichen) an.
+
+ sal_uInt16 nCacheIdx; //Index in den Cache, USHRT_MAX wenn definitiv
+ //kein passendes Objekt im Cache steht.
+
+ //Teilt den Master ab und erzeugt einen Follow oder passt die
+ //Daten im Follow an.
+ void _AdjustFollow( SwTxtFormatter &rLine, const xub_StrLen nOffset,
+ const xub_StrLen nStrEnd, const sal_uInt8 nMode );
+ inline void AdjustFollow( SwTxtFormatter &rLine, const xub_StrLen nOffset,
+ const xub_StrLen nStrEnd, const sal_uInt8 nMode );
+
+ //Iteriert ueber alle Zeilen und stellt das Linespacing
+ //entsprechend dem Attribut ein.
+ void CalcLineSpace();
+
+ void InitCtor(); // Wird in beiden Ctoren gerufen
+
+ // Wird nur in Format gerufen:
+ void AdjustFrm( const SwTwips nChgHeight, sal_Bool bHasToFit = sal_False );
+
+ // wertet in Format() die Preps aus.
+ sal_Bool CalcPreps();
+ void PrepWidows( const sal_uInt16 nNeed, sal_Bool bNotify = sal_True );
+ void _InvalidateRange( const SwCharRange &, const long = 0);
+ inline void InvalidateRange( const SwCharRange &, const long = 0);
+
+ // WidowsAndOrphans, AdjustFrm, AdjustFollow
+ void FormatAdjust( SwTxtFormatter &rLine, WidowsAndOrphans &rFrmBreak,
+ const xub_StrLen nStrLen, const sal_Bool bDummy );
+
+ sal_Bool bLocked : 1; // im Format?
+ sal_Bool bFormatted : 1; // nach Format auf sal_True
+ sal_Bool bWidow : 1; // sind wir ein Widow
+ sal_Bool bJustWidow : 1; // haben wir soeben Widow angefordert
+ sal_Bool bEmpty : 1; // sind wir ein leerer Absatz
+ sal_Bool bInFtnConnect : 1; // Steht gerade im Connect
+ sal_Bool bFtn : 1; // Hat mindestens eine Fussnote
+ sal_Bool bRepaint : 1; // TxtFrm: Repaint steht zur Abholung bereit
+ sal_Bool bBlinkPor : 1; // enthaelt Blink-Portions
+ sal_Bool bFieldFollow : 1; // beginne mit Feldrest des Masters
+ sal_Bool bHasAnimation : 1; // enthaelt animierte SwGrfNumPortion
+ sal_Bool bIsSwapped : 1; // during text formatting we swap the
+ // width and height for vertical formatting
+ // OD 14.03.2003 #i11760# - flag to control, if follow is formatted in
+ // method <CalcFollow(..)>.
+ // E.g., avoid formatting of follow, if method <SwLayoutFrm::FormatWidthCols(..)>
+ // is running.
+ sal_Bool mbFollowFormatAllowed : 1;
+
+ void ResetPreps();
+ inline void Lock() { bLocked = sal_True; }
+ inline void Unlock() { bLocked = sal_False; }
+ inline void SetFormatted( const sal_Bool bNew ) { bFormatted = bNew; }
+ inline void SetWidow( const sal_Bool bNew ) { bWidow = bNew; }
+ inline void SetJustWidow( const sal_Bool bNew ) { bJustWidow = bNew; }
+ inline void SetEmpty( const sal_Bool bNew ) { bEmpty = bNew; }
+ inline void SetFieldFollow( const sal_Bool bNew ) { bFieldFollow = bNew; }
+
+ sal_Bool IsIdxInside( const xub_StrLen nPos, const xub_StrLen nLen ) const;
+
+ // Wechselt den Frame oder auch nicht (vgl. FlyCnt)
+ sal_Bool _GetCrsrOfst(SwPosition *pPos, const Point &rPoint,
+ const sal_Bool bChgFrm, SwCrsrMoveState* = 0 ) const;
+ void FillCrsrPos( SwFillData &rFill ) const;
+
+ // formatiert genau eine Zeile ...
+ sal_Bool FormatLine( SwTxtFormatter &rLine, const sal_Bool bPrev );
+
+ // Um Stack einzusparen aufgeteilt ...
+ // _Format ruft _Format mit Parametern
+ void _Format( SwParaPortion *pPara );
+ void _Format( SwTxtFormatter &rLine, SwTxtFormatInfo &rInf,
+ const sal_Bool bAdjust = sal_False );
+ void FormatOnceMore( SwTxtFormatter &rLine, SwTxtFormatInfo &rInf );
+
+ // formatiert den Follow und sorgt fuer die Entsorgung bei Orphans
+ sal_Bool CalcFollow( const xub_StrLen nTxtOfst );
+
+ // korrigiert die Stelle ab der formatiert werden muss.
+ xub_StrLen FindBrk(const String &rTxt, const xub_StrLen nStart,
+ const xub_StrLen nEnd) const;
+
+ // inline-Weiche
+ SwTwips _GetFtnFrmHeight() const;
+
+ // Aus CalcPreps ausgelagert.
+ sal_Bool CalcPrepFtnAdjust();
+
+ // Fuer Ftn und WidOrp: Zwangsvalidierung
+ void ValidateFrm();
+ void ValidateBodyFrm();
+
+ sal_Bool _GetDropRect( SwRect &rRect ) const;
+
+ void SetPara( SwParaPortion *pNew, sal_Bool bDelete = sal_True );
+
+ sal_Bool _IsFtnNumFrm() const;
+
+ // 6995: Formatinformationen auffrischen
+ sal_Bool FormatQuick( bool bForceQuickFormat );
+
+ // Opt: Leere Absaetze formatieren
+ sal_Bool FormatEmpty();
+ SwTwips EmptyHeight() const;
+ // Opt: Leere Absaetze painten
+ sal_Bool PaintEmpty( const SwRect &, sal_Bool bCheck ) const;
+
+ void ChgThisLines();//Muss immer gerufen werden, wenn sich die Zeilenazahl
+ //veraendert haben kann.
+
+ // required for 'new' relative anchor position
+ void CalcBaseOfstForFly();
+
+ /** method to determine height of last line, needed for proportional line spacing
+
+ OD 2004-03-17 #i11860#
+ OD 2005-05-20 #i47162# - introduce new optional parameter <_bUseFont>
+ in order to force the usage of the former algorithm to determine the
+ height of the last line, which uses the font.
+
+ @param _bUseFont
+ optional input parameter - boolean indicating, if the font has to be
+ used to determine the height of the last line. default value: false
+
+ @author OD
+ */
+ void _CalcHeightOfLastLine( const bool _bUseFont = false );
+
+ // ST2
+ SwWrongList* _SmartTagScan ( ::rtl::OUString aTxtToScan, SwWrongList *pSmartTagList,
+ xub_StrLen nBegin,xub_StrLen nEnd,
+ xub_StrLen nInsertPos, xub_StrLen nActPos,
+ xub_StrLen &nChgStart, xub_StrLen &nChgEnd,
+ xub_StrLen &nInvStart, xub_StrLen &nInvEnd);
+protected:
+ virtual void Modify( const SfxPoolItem*, const SfxPoolItem* );
+
+public:
+
+ //public, weil der eine oder andere die Methode rufen darf um das
+ //Prepare zu sparen - mit Vorsicht zu geniessen!
+ void Init();
+
+ // Wird von FormatSpelling( ) gerufen
+ SwRect _AutoSpell( const SwCntntNode*, const SwViewOption&, sal_uInt16 );
+ // is called from the FormatSpelling( ) method
+ SwRect SmartTagScan( SwCntntNode* , sal_uInt16 );
+ // Wird vom CollectAutoCmplWords gerufen
+ void CollectAutoCmplWrds( SwCntntNode* , sal_uInt16 );
+
+ // Returns the screen position of rPos. The values are relative to the upper
+ // left position of the page frame.
+ // Additional information can be obtained by passing an SwCrsrMoveState object.
+ // Returns sal_False if rPos > number of character is string
+ virtual sal_Bool GetCharRect( SwRect& rRect, const SwPosition& rPos,
+ SwCrsrMoveState* pCMS = 0 ) const;
+ // Eine etwas abgespeckte GetCharRect-Version fuer autopositionierte Rahmen
+ sal_Bool GetAutoPos( SwRect &, const SwPosition& ) const;
+
+ /** determine top of line for given position in the text frame
+
+ OD 11.11.2003 #i22341#
+ Assumption: given position exists in the text frame or in a follow of it
+ OD 2004-02-02 - adjustment
+ Top of first paragraph line is the top of the paragraph.
+ OD 2004-03-18 #i11860# - Consider upper space amount considered for
+ previous frame and the page grid.
+
+ @author OD
+
+ @param _onTopOfLine
+ output parameter - top of line, if the given position is found in the
+ text frame.
+
+ @param _rPos
+ input parameter - reference to the position in the text frame
+
+ @return boolean indicating, if the top of line for the given position
+ has been determined or not.
+ */
+ bool GetTopOfLine( SwTwips& _onTopOfLine,
+ const SwPosition& _rPos ) const;
+
+ virtual bool FillSelection( SwSelectionList& rList, const SwRect& rRect ) const;
+
+
+ //Liefert in nOffset den Offset des Characters innerhalb des
+ //gesetzten Textbuffers zurueck, welcher der durch aPoint
+ //gegebenen Position innerhalb der SSize des Layout am
+ //naechsten ist. Wenn der SPoint ausserhalb der SSize liegt,
+ //liefert die Funktion sal_False, sal_True sonst.
+ virtual sal_Bool GetCrsrOfst( SwPosition *, Point&,
+ SwCrsrMoveState* = 0) const;
+
+ // GetKeyCrsrOfst sorgt dafuer, dass der Frame nicht gewechselt wird
+ // (z.B. Wechsel in den zeichengebundenen Frame).
+ inline sal_Bool GetKeyCrsrOfst(SwPosition *pPos, const Point &rPoint ) const
+ { return _GetCrsrOfst( pPos, rPoint, sal_False ); }
+
+ void PaintExtraData( const SwRect & rRect ) const; //Seitennummer usw.
+ SwRect Paint();
+ virtual void Paint( SwRect const&,
+ SwPrintData const*const pPrintData = NULL ) const;
+ virtual sal_Bool GetInfo( SfxPoolItem & ) const;
+
+ //Layoutorientiertes Cursortravelling: Linker, rechter Rand,
+ //vorhergehende/naechste Zeile, gleiche horizontale Position.
+ virtual sal_Bool LeftMargin(SwPaM *) const;
+ virtual sal_Bool RightMargin(SwPaM *, sal_Bool bAPI = sal_False) const;
+
+ virtual sal_Bool UnitUp(SwPaM *, const SwTwips nOffset = 0,
+ sal_Bool bSetInReadOnly = sal_False ) const;
+ virtual sal_Bool UnitDown(SwPaM *, const SwTwips nOffset = 0,
+ sal_Bool bSetInReadOnly = sal_False ) const;
+ sal_Bool _UnitUp(SwPaM *, const SwTwips nOffset = 0,
+ sal_Bool bSetInReadOnly = sal_False ) const;
+ sal_Bool _UnitDown(SwPaM *, const SwTwips nOffset = 0,
+ sal_Bool bSetInReadOnly = sal_False ) const;
+
+ // Prepares the cursor position for a visual cursor move (BiDi).
+ // The behaviour is different for insert and overwrite cursors
+ void PrepareVisualMove( xub_StrLen& nPos, sal_uInt8& nCrsrLevel,
+ sal_Bool& bRight, sal_Bool bInsertCrsr );
+
+ // Methoden zur Verwaltung von FolgeFrames
+ SwCntntFrm *SplitFrm( const xub_StrLen nTxtPos );
+ SwCntntFrm *JoinFrm();
+ inline sal_uInt16 GetOfst() const { return nOfst; }
+ void _SetOfst( const sal_uInt16 nNewOfst );
+ inline void SetOfst ( const sal_uInt16 nNewOfst );
+ inline void ManipOfst ( const sal_uInt16 nNewOfst ){ nOfst = nNewOfst; }
+ SwTxtFrm *GetFrmAtPos ( const SwPosition &rPos);
+ inline const SwTxtFrm *GetFrmAtPos ( const SwPosition &rPos) const;
+ // OD 07.10.2003 #110978# - return <reference> instead of <pointer>
+ SwTxtFrm& GetFrmAtOfst( const xub_StrLen nOfst );
+ // Wenn es einen Follow gibt und wir selbst keinen Text enthalten:
+ inline sal_Bool IsEmptyMaster() const
+ { return GetFollow() && !GetFollow()->GetOfst(); }
+
+ // Liefert den zu bearbeitenden Textausschnitt zurueck (inline, s.u.)
+ const String& GetTxt() const;
+ inline SwTxtNode *GetTxtNode()
+ { return (SwTxtNode*)SwCntntFrm::GetNode(); }
+ inline const SwTxtNode *GetTxtNode() const
+ { return (SwTxtNode*)SwCntntFrm::GetNode(); }
+
+ SwTxtFrm(SwTxtNode * const, SwFrm* );
+ virtual ~SwTxtFrm();
+
+ // SwCntntFrm: der "kurze Dienstweg" fuer die Frames.
+ // Wer den void* falsch casted ist selbst Schuld!
+ // Auf jedenfall muss der void* auf 0 geprueft werden.
+ virtual void Prepare( const PrepareHint ePrep = PREP_CLEAR,
+ const void *pVoid = 0, sal_Bool bNotify = sal_True );
+
+ // nMaxHeight is the required height
+ // bSplit indicates, that the paragraph has to be split
+ // bTst indicates, that we are currently doing a test formatting
+ virtual sal_Bool WouldFit( SwTwips &nMaxHeight, sal_Bool &bSplit, sal_Bool bTst );
+
+ // Hier das WouldFit-Aequivalent fuer mal kurz probeweise
+ // umgehaengte TextFrames, auch hier liefert
+ // nMaxHeight die benoetigte Hoehe,
+ // und bSplit sagt, obj der Absatz gesplittet werden muss.
+ // Uebergeben wird der potentielle Vorgaenger fuer die Abstandsberechnung
+ sal_Bool TestFormat( const SwFrm* pPrv, SwTwips &nMaxHeight, sal_Bool &bSplit );
+
+ // Wir formatieren eine Zeile fuer die interaktive Trennung
+ // Return: found
+ sal_Bool Hyphenate( SwInterHyphInfo &rInf );
+
+ // Probegrow
+ inline SwTwips GrowTst( const SwTwips nGrow );
+
+ SwParaPortion *GetPara();
+ inline const SwParaPortion *GetPara() const;
+ inline sal_Bool HasPara() const;
+ sal_Bool _HasPara() const;
+ // If there are any hanging punctuation portions in the margin
+ // the offset will be returned.
+ SwTwips HangingMargin() const;
+
+ // RTTI
+ TYPEINFO();
+ DECL_FIXEDMEMPOOL_NEWDEL(SwTxtFrm)
+
+ // Locking
+ inline sal_Bool IsLocked() const { return bLocked; }
+ inline sal_Bool IsFormatted() const { return bFormatted; }
+
+ inline sal_Bool IsWidow() const { return bWidow; }
+ inline sal_Bool IsJustWidow() const { return bJustWidow; }
+ inline sal_Bool IsEmpty() const { return bEmpty; }
+ inline sal_Bool HasFtn() const { return bFtn; }
+ inline sal_Bool IsInFtnConnect()const { return bInFtnConnect;}
+ inline sal_Bool IsFieldFollow() const { return bFieldFollow;}
+
+ inline void SetRepaint() const;
+ inline void ResetRepaint() const;
+ inline sal_Bool HasRepaint() const { return bRepaint; }
+ inline void SetBlinkPor() const;
+ inline void ResetBlinkPor() const;
+ inline sal_Bool HasBlinkPor() const { return bBlinkPor; }
+ inline void SetAnimation() const
+ { ( (SwTxtFrm*)this )->bHasAnimation = sal_True; }
+ inline sal_Bool HasAnimation() const { return bHasAnimation; }
+
+ inline sal_Bool IsSwapped() const { return bIsSwapped; }
+
+ // Hat der Frm eine lokale Fussnote (in diesem Frm bzw. Follow)?
+#if OSL_DEBUG_LEVEL > 1
+ void CalcFtnFlag( xub_StrLen nStop = STRING_LEN );//For testing SplitFrm
+#else
+ void CalcFtnFlag();
+#endif
+
+ // Hidden
+ sal_Bool IsHiddenNow() const; // bHidden && pOut == pPrt
+ void HideHidden(); // Anhaengsel entfernen wenn Hidden
+ void HideFootnotes( xub_StrLen nStart, xub_StrLen nEnd );
+
+ /** method to hide/show objects
+
+ OD 2004-01-15 #110582#
+ method hides respectively shows objects, which are anchored at paragraph,
+ at/as a character of the paragraph, corresponding to the paragraph and
+ paragraph portion visibility.
+
+ @author OD
+ */
+ void HideAndShowObjects();
+
+ // Ftn
+ void RemoveFtn( const xub_StrLen nStart = 0,
+ const xub_StrLen nLen = STRING_LEN );
+ inline SwTwips GetFtnFrmHeight() const;
+ SwTxtFrm *FindFtnRef( const SwTxtFtn *pFtn );
+ inline const SwTxtFrm *FindFtnRef( const SwTxtFtn *pFtn ) const
+ { return FindFtnRef( pFtn ); }
+ void ConnectFtn( SwTxtFtn *pFtn, const SwTwips nDeadLine );
+
+ // Wenn wir eine Ftn sind, die auf ihre Referenz zu waechst...
+ // public weil von SwCntntFrm::MakeAll benoetigt.
+ SwTwips GetFtnLine( const SwTxtFtn *pFtn ) const;
+
+ // Liefern den linken und den rechten Rand in
+ // Dokumentkoordinaten (unter Beachtung der Absatzattribute).
+ inline SwTwips GetLeftMargin() const;
+ inline SwTwips GetRightMargin() const;
+
+ virtual void Format( const SwBorderAttrs *pAttrs = 0 );
+ virtual void CheckDirection( sal_Bool bVert );
+
+ // Liefert die Summe der Zeilenhoehen in pLine zurueck.
+ sal_uInt16 GetParHeight() const;
+
+ // Liefert die Resthoehe zurueck
+ inline SwTwips GetRstHeight() const;
+
+ inline SwTxtFrm *GetFollow();
+ inline const SwTxtFrm *GetFollow() const;
+
+ // Suche die Seitennummer von ErgoSum und QuoVadis
+ SwTxtFrm *FindQuoVadisFrm();
+
+ // holt die Formatierug nach, wenn der Idle-Handler zugeschlagen hat.
+ // --> FME 2004-10-29 #i29062# GetFormatted() can trigger a full formatting
+ // of the paragraph, causing other layout frames to become invalid. This
+ // has to be avoided during painting. Therefore we need to pass the
+ // information that we are currently in the paint process.
+ SwTxtFrm* GetFormatted( bool bForceQuickFormat = false );
+ // <--
+
+ // wird demnaechst uebertragen
+ inline void SetFtn( const sal_Bool bNew ) { bFtn = bNew; }
+
+ // Beruecksichtigung der Follows
+ inline sal_Bool IsInside( const xub_StrLen nPos ) const;
+
+ const SwBodyFrm *FindBodyFrm() const;
+
+ // DropCaps und Selektionen
+ inline sal_Bool GetDropRect( SwRect &rRect ) const
+ { return HasPara() ? _GetDropRect( rRect ) : sal_False; }
+
+ static SwCache *GetTxtCache() { return pTxtCache; }
+ static void SetTxtCache( SwCache *pNew ) { pTxtCache = pNew; }
+
+ static long GetMinPrtLine() { return nMinPrtLine; }
+ static void SetMinPrtLine( long nNew ) { nMinPrtLine = nNew; }
+
+ inline sal_uInt16 GetCacheIdx() const { return nCacheIdx; }
+ inline void SetCacheIdx( const sal_uInt16 nNew ) { nCacheIdx = nNew; }
+
+ //Entfert die Line-Informationen aus dem Cache.
+ void ClearPara();
+
+ // Bin ich ein FtnFrm, der eine Nummer am Absatzanfang hat?
+ inline sal_Bool IsFtnNumFrm() const
+ { return IsInFtn() && !GetIndPrev() && _IsFtnNumFrm(); }
+
+ // simuliert eine Formatierung, als wenn es keinen rechten Rand und
+ // keine Flys oder andere Hindernisse gaebe und liefert die Breite.
+ SwTwips CalcFitToContent();
+
+ /** simulate format for a list item paragraph, whose list level attributes
+ are in LABEL_ALIGNMENT mode, in order to determine additional first
+ line offset for the real text formatting due to the value of label
+ adjustment attribute of the list level.
+
+ @author OD
+ */
+ void CalcAdditionalFirstLineOffset();
+
+ inline SwTwips GetAdditionalFirstLineOffset() const
+ {
+ return mnAdditionalFirstLineOffset;
+ }
+
+ // liefert den zusaetzlichen Zeilenabstand fuer den naechsten Absatz
+ // OD 07.01.2004 #i11859# - change return data type;
+ // add default parameter <_bNoPropLineSpacing> to control, if the
+ // value of a proportional line spacing is returned or not
+ long GetLineSpace( const bool _bNoPropLineSpacing = false ) const;
+
+ // liefert die erste Zeilenhoehe zurueck
+ sal_uInt16 FirstLineHeight() const;
+
+ // Haengt FlyInCntFrm um, wenn nEnd > Index >= nStart ist.
+ void MoveFlyInCnt( SwTxtFrm *pNew, sal_uInt16 nStart, sal_uInt16 nEnd );
+
+ // Berechnet die Position von FlyInCntFrms
+ sal_uInt16 CalcFlyPos( SwFrmFmt* pSearch );
+
+ // Ermittelt die Startposition und Schrittweite des Registers
+ sal_Bool FillRegister( SwTwips& rRegStart, sal_uInt16& rRegDiff );
+
+
+ sal_uInt16 GetLineCount( sal_uInt16 nPos ); //Ermittelt die Zeilenanzahl
+
+ //Fuer die Anzeige der Zeilennummern.
+ sal_uLong GetAllLines() const { return nAllLines; }
+ sal_uLong GetThisLines() const { return nThisLines;}
+ void RecalcAllLines();
+
+ // Stoppt Animationen innerhalb von Numerierungen
+ void StopAnimation( OutputDevice *pOut );
+
+ // visit all portions for Accessibility
+ void VisitPortions( SwPortionHandler& rPH ) const;
+
+ // returns the script info stored at the paraportion
+ const SwScriptInfo* GetScriptInfo() const;
+
+ // Swaps width and height of the text frame
+ void SwapWidthAndHeight();
+ // Calculates the coordinates of a rectangle when switching from
+ // horizontal to vertical layout.
+ void SwitchHorizontalToVertical( SwRect& rRect ) const;
+ // Calculates the coordinates of a point when switching from
+ // horizontal to vertical layout.
+ void SwitchHorizontalToVertical( Point& rPoint ) const;
+ // Calculates the a limit value when switching from
+ // horizontal to vertical layout.
+ long SwitchHorizontalToVertical( long nLimit ) const;
+ // Calculates the coordinates of a rectangle when switching from
+ // vertical to horizontal layout.
+ void SwitchVerticalToHorizontal( SwRect& rRect ) const;
+ // Calculates the coordinates of a point when switching from
+ // vertical to horizontal layout.
+ void SwitchVerticalToHorizontal( Point& rPoint ) const;
+ // Calculates the a limit value when switching from
+ // vertical to horizontal layout.
+ long SwitchVerticalToHorizontal( long nLimit ) const;
+
+ // Calculates the coordinates of a rectangle when switching from
+ // LTR to RTL layout
+ void SwitchLTRtoRTL( SwRect& rRect ) const;
+ // Calculates the coordinates of a point when switching from
+ // LTR to RTL layout.
+ void SwitchLTRtoRTL( Point& rPoint ) const;
+ // Calculates the coordinates of a rectangle when switching from
+ // RTL to LTR layout
+ inline void SwitchRTLtoLTR( SwRect& rRect ) const { SwitchLTRtoRTL( rRect ); }
+ // Calculates the coordinates of a point when switching from
+ // RTL to LTR layout.
+ inline void SwitchRTLtoLTR( Point& rPoint ) const { SwitchLTRtoRTL( rPoint ); };
+
+ // OD 14.03.2003 #i11760# - access to new member <mbNoFollowFormat>
+ inline bool FollowFormatAllowed() const
+ {
+ return mbFollowFormatAllowed;
+ }
+ inline void AllowFollowFormat()
+ {
+ mbFollowFormatAllowed = true;
+ }
+ inline void ForbidFollowFormat()
+ {
+ mbFollowFormatAllowed = false;
+ }
+
+ SwTwips GetBaseOfstForFly( sal_Bool bIgnoreFlysAnchoredAtThisFrame ) const
+ {
+ return ( bIgnoreFlysAnchoredAtThisFrame ?
+ mnFlyAnchorOfst :
+ mnFlyAnchorOfstNoWrap );
+ }
+
+ // OD 2004-03-17 #i11860#
+ inline SwTwips GetHeightOfLastLine() const
+ {
+ return mnHeightOfLastLine;
+ }
+
+ static void repaintTextFrames( const SwTxtNode& rNode );
+
+#if OSL_DEBUG_LEVEL > 1
+ virtual void dumpAsXmlAttributes(xmlTextWriterPtr writer);
+#endif
+};
+
+/*************************************************************************
+ * class SwTxtFrmLocker
+ *************************************************************************/
+
+class SwTxtFrmLocker
+{
+private:
+ SwTxtFrm * const pFrm;
+public:
+ inline SwTxtFrmLocker( SwTxtFrm *pTxtFrm )
+ : pFrm( pTxtFrm->IsLocked() ? 0 : pTxtFrm )
+ { if( pFrm ) pFrm->Lock(); }
+ inline ~SwTxtFrmLocker() { if( pFrm ) pFrm->Unlock(); }
+};
+
+/*************************************************************************
+ * Inline-Implementierung
+ *************************************************************************/
+
+inline const SwParaPortion *SwTxtFrm::GetPara() const
+{
+ return ((SwTxtFrm*)this)->GetPara();
+}
+
+inline sal_Bool SwTxtFrm::HasPara() const
+{
+ return nCacheIdx != USHRT_MAX ? _HasPara() : sal_False;
+}
+
+// 9104: Frm().Height() - Prt().Height(), siehe widorp.cxx und 7455, 6114, 7908
+inline SwTwips SwTxtFrm::GetRstHeight() const
+{
+ return !GetUpper() ? 0 : ((const SwFrm*)GetUpper())->Frm().Top()
+ + ((const SwFrm*)GetUpper())->Prt().Top()
+ + ((const SwFrm*)GetUpper())->Prt().Height()
+ - Frm().Top() - (Frm().Height() - Prt().Height());
+}
+
+inline SwTwips SwTxtFrm::GetLeftMargin() const
+{
+ return Frm().Left() + Prt().Left();
+}
+inline SwTwips SwTxtFrm::GetRightMargin() const
+{
+ return Frm().Left() + Prt().Left() + Prt().Width();
+}
+inline SwTwips SwTxtFrm::GrowTst( const SwTwips nGrow )
+{
+ return Grow( nGrow, sal_True );
+}
+
+#if OSL_DEBUG_LEVEL > 1
+// fragt auf WYSIWYG DBG ab
+extern sal_Bool IsDbg( const SwTxtFrm *pFrm );
+#define DBTXTFRM aDbstream << "SwTxtFrm[" << GetFrmId() << "]"
+#endif
+
+inline sal_Bool SwTxtFrm::IsInside( const xub_StrLen nPos ) const
+{
+ sal_Bool bRet = sal_True;
+ if( nPos < GetOfst() )
+ bRet = sal_False;
+ else
+ {
+ const SwTxtFrm *pFoll = GetFollow();
+ if( pFoll && nPos >= pFoll->GetOfst() )
+ bRet = sal_False;
+ }
+ return bRet;
+}
+
+inline SwTwips SwTxtFrm::GetFtnFrmHeight() const
+{
+ if( !IsFollow() && IsInFtn() && HasPara() )
+ return _GetFtnFrmHeight();
+ else
+ return 0;
+}
+
+inline const SwTxtFrm *SwTxtFrm::GetFollow() const
+{
+ return (const SwTxtFrm*)SwCntntFrm::GetFollow();
+}
+inline SwTxtFrm *SwTxtFrm::GetFollow()
+{
+ return (SwTxtFrm*)SwCntntFrm::GetFollow();
+}
+
+inline const SwTxtFrm *SwTxtFrm::GetFrmAtPos( const SwPosition &rPos) const
+{
+ return ((SwTxtFrm*)this)->GetFrmAtPos( rPos );
+}
+
+inline void SwTxtFrm::AdjustFollow( SwTxtFormatter &rLine,
+ const xub_StrLen nOffset, const xub_StrLen nStrEnd, const sal_uInt8 nMode )
+{
+ if ( HasFollow() )
+ _AdjustFollow( rLine, nOffset, nStrEnd, nMode );
+}
+
+inline void SwTxtFrm::SetOfst( const xub_StrLen nNewOfst )
+{
+ if ( nOfst != nNewOfst )
+ _SetOfst( nNewOfst );
+}
+
+inline void SwTxtFrm::SetRepaint() const
+{
+ ((SwTxtFrm*)this)->bRepaint = sal_True;
+}
+inline void SwTxtFrm::ResetRepaint() const
+{
+ ((SwTxtFrm*)this)->bRepaint = sal_False;
+}
+
+inline void SwTxtFrm::SetBlinkPor() const
+{
+ ((SwTxtFrm*)this)->bBlinkPor = sal_True;
+}
+inline void SwTxtFrm::ResetBlinkPor() const
+{
+ ((SwTxtFrm*)this)->bBlinkPor = sal_False;
+}
+
+#define SWAP_IF_SWAPPED( pFrm )\
+ sal_Bool bUndoSwap = sal_False; \
+ if ( pFrm->IsVertical() && pFrm->IsSwapped() )\
+ { \
+ bUndoSwap = sal_True; \
+ ((SwTxtFrm*)pFrm)->SwapWidthAndHeight(); \
+ }
+
+#define SWAP_IF_NOT_SWAPPED( pFrm )\
+ sal_Bool bUndoSwap = sal_False; \
+ if ( pFrm->IsVertical() && ! pFrm->IsSwapped() )\
+ { \
+ bUndoSwap = sal_True; \
+ ((SwTxtFrm*)pFrm)->SwapWidthAndHeight(); \
+ }
+
+#define UNDO_SWAP( pFrm )\
+ if ( bUndoSwap )\
+ ((SwTxtFrm*)pFrm)->SwapWidthAndHeight();
+
+// Helper class which can be used instead of the macros if a function
+// has too many returns
+class SwFrmSwapper
+{
+ const SwTxtFrm* pFrm;
+ sal_Bool bUndo;
+public:
+ SwFrmSwapper( const SwTxtFrm* pFrm, sal_Bool bSwapIfNotSwapped );
+ ~SwFrmSwapper();
+};
+
+class SwLayoutModeModifier
+{
+ const OutputDevice& rOut;
+ long nOldLayoutMode;
+public:
+ SwLayoutModeModifier( const OutputDevice& rOutp );
+ ~SwLayoutModeModifier();
+ void Modify( sal_Bool bChgToRTL );
+ void SetAuto();
+};
+
+class SwDigitModeModifier
+{
+ const OutputDevice& rOut;
+ LanguageType nOldLanguageType;
+public:
+ SwDigitModeModifier( const OutputDevice& rOutp, LanguageType eCurLang );
+ ~SwDigitModeModifier();
+};
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/inc/txttypes.hxx b/sw/source/core/inc/txttypes.hxx
new file mode 100644
index 000000000000..86d9e5cd07a6
--- /dev/null
+++ b/sw/source/core/inc/txttypes.hxx
@@ -0,0 +1,106 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+#ifndef _TXTTYPES_HXX
+#define _TXTTYPES_HXX
+
+#include "swtypes.hxx"
+
+// Ueberpruefte USHORTs, z.B. Indizes auf Arrays oder garantiert kleine
+// Integerwerte, auch von aussen vorgegebene
+#define MSHORT sal_uInt16
+#define MSHRT_MAX USHRT_MAX
+// Koordinaten: Breite, Hoehe und Offsets in X-/Y-Richtung sowie Ascent etc.
+#define KSHORT sal_uInt16
+#define KSHRT_MAX USHRT_MAX
+
+// Portiontypen
+#define POR_LIN 0x0000
+#define POR_FLYCNT 0x0001
+
+#define POR_HOLE 0x0080
+#define POR_TMPEND 0x0081
+#define POR_BRK 0x0082
+#define POR_KERN 0x0083
+#define POR_ARROW 0x0084
+#define POR_MULTI 0x0085
+#define POR_HIDDEN_TXT 0x0086
+#define POR_CONTROLCHAR 0x0087
+
+#define POR_TXT 0x8000
+#define POR_LAY 0x8001
+#define POR_PARA 0x8002
+#define POR_URL 0x8003
+#define POR_HNG 0x8004
+
+#define POR_DROP 0x8080
+#define POR_TOX 0x8089
+#define POR_ISOTOX 0x808a
+#define POR_REF 0x808b
+#define POR_ISOREF 0x808c
+#define POR_META 0x808d
+
+#define POR_EXP 0xc080
+#define POR_BLANK 0xc081
+#define POR_POSTITS 0xc082
+
+#define POR_HYPH 0xd080
+#define POR_HYPHSTR 0xd081
+#define POR_SOFTHYPH 0xd082
+#define POR_SOFTHYPHSTR 0xd083
+#define POR_SOFTHYPH_COMP 0xd084
+
+#define POR_FLD 0xe080
+#define POR_HIDDEN 0xe081
+#define POR_QUOVADIS 0xe082
+#define POR_ERGOSUM 0xe083
+#define POR_COMBINED 0xe084
+#define POR_FTN 0xe085
+
+#define POR_FTNNUM 0xe880
+#define POR_NUMBER 0xe881
+#define POR_BULLET 0xe882
+#define POR_GRFNUM 0xe883
+
+#define POR_GLUE 0x0480
+
+#define POR_MARGIN 0x04c0
+
+#define POR_FIX 0x06c0
+#define POR_FLY 0x06c1
+
+#define POR_TAB 0x0750
+
+#define POR_TABRIGHT 0x07d0
+#define POR_TABCENTER 0x07d1
+#define POR_TABDECIMAL 0x07d2
+
+#define POR_TABLEFT 0x0740
+
+#endif //_TXTTYPES_HXX
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/inc/undoflystrattr.hxx b/sw/source/core/inc/undoflystrattr.hxx
new file mode 100644
index 000000000000..9a44ae2310c3
--- /dev/null
+++ b/sw/source/core/inc/undoflystrattr.hxx
@@ -0,0 +1,59 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+#ifndef SW_UNDO_FLY_STR_ATTR_HXX
+#define SW_UNDO_FLY_STR_ATTR_HXX
+
+#include <undobj.hxx>
+#include <swundo.hxx>
+
+class SwFlyFrmFmt;
+class String;
+
+class SwUndoFlyStrAttr : public SwUndo
+{
+ public:
+ SwUndoFlyStrAttr( SwFlyFrmFmt& rFlyFrmFmt,
+ const SwUndoId eUndoId,
+ const String& sOldStr,
+ const String& sNewStr );
+ virtual ~SwUndoFlyStrAttr();
+
+ virtual void UndoImpl( ::sw::UndoRedoContext & );
+ virtual void RedoImpl( ::sw::UndoRedoContext & );
+
+ virtual SwRewriter GetRewriter() const;
+
+ private:
+ SwFlyFrmFmt& mrFlyFrmFmt;
+ const String msOldStr;
+ const String msNewStr;
+};
+
+#endif // SW_UNDO_FLY_STR_ATTR_HXX
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/inc/unofldmid.h b/sw/source/core/inc/unofldmid.h
new file mode 100644
index 000000000000..09c91e4021b4
--- /dev/null
+++ b/sw/source/core/inc/unofldmid.h
@@ -0,0 +1,74 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+#ifndef SW_UNOFLDMID_H
+#define SW_UNOFLDMID_H
+
+#include <tools/solar.h>
+
+class String;
+namespace com { namespace sun { namespace star { namespace uno {
+ class Any;
+} } } }
+
+/******************************************************************************
+ *
+ ******************************************************************************/
+//Abbildung der Properties auf den Descriptor
+#define FIELD_PROP_PAR1 10
+#define FIELD_PROP_PAR2 11
+#define FIELD_PROP_PAR3 12
+#define FIELD_PROP_FORMAT 13
+#define FIELD_PROP_SUBTYPE 14
+#define FIELD_PROP_BOOL1 15
+#define FIELD_PROP_BOOL2 16
+#define FIELD_PROP_DATE 17
+#define FIELD_PROP_USHORT1 18
+#define FIELD_PROP_USHORT2 19
+#define FIELD_PROP_BYTE1 20
+#define FIELD_PROP_DOUBLE 21
+#define FIELD_PROP_BOOL3 22
+#define FIELD_PROP_PAR4 23
+#define FIELD_PROP_SHORT1 24
+#define FIELD_PROP_DATE_TIME 25
+#define FIELD_PROP_PROP_SEQ 26
+#define FIELD_PROP_LOCALE 27
+#define FIELD_PROP_BOOL4 28
+#define FIELD_PROP_STRINGS 29
+#define FIELD_PROP_PAR5 30
+#define FIELD_PROP_PAR6 31
+
+#define FIELD_PROP_IS_FIELD_USED 32
+#define FIELD_PROP_IS_FIELD_DISPLAYED 33
+
+#define FIELD_PROP_TEXT 34
+
+String& GetString( const com::sun::star::uno::Any&, String& rStr );
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/inc/unometa.hxx b/sw/source/core/inc/unometa.hxx
new file mode 100644
index 000000000000..92333a46ca8a
--- /dev/null
+++ b/sw/source/core/inc/unometa.hxx
@@ -0,0 +1,370 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef SW_UNOMETA_HXX
+#define SW_UNOMETA_HXX
+
+#include <deque>
+
+#include <com/sun/star/lang/XServiceInfo.hpp>
+#include <com/sun/star/lang/XUnoTunnel.hpp>
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/container/XChild.hpp>
+#include <com/sun/star/container/XEnumerationAccess.hpp>
+#include <com/sun/star/text/XTextContent.hpp>
+#include <com/sun/star/text/XTextField.hpp>
+
+#include <cppuhelper/implbase2.hxx>
+#include <cppuhelper/implbase6.hxx>
+
+#include <sfx2/Metadatable.hxx>
+
+#include <unobaseclass.hxx>
+
+
+typedef ::std::deque<
+ ::com::sun::star::uno::Reference< ::com::sun::star::text::XTextRange > >
+ TextRangeList_t;
+
+class SwPaM;
+class SwTxtNode;
+
+namespace sw {
+ class Meta;
+ class MetaField;
+}
+
+typedef ::cppu::ImplInheritanceHelper6
+< ::sfx2::MetadatableMixin
+, ::com::sun::star::lang::XUnoTunnel
+, ::com::sun::star::lang::XServiceInfo
+, ::com::sun::star::container::XChild
+, ::com::sun::star::container::XEnumerationAccess
+, ::com::sun::star::text::XTextContent
+, ::com::sun::star::text::XText
+> SwXMeta_Base;
+
+class SwXMeta
+ : public SwXMeta_Base
+ , private ::boost::noncopyable
+{
+
+public:
+
+ class Impl;
+
+protected:
+
+ ::sw::UnoImplPtr<Impl> m_pImpl;
+
+ virtual void SAL_CALL AttachImpl(
+ const ::com::sun::star::uno::Reference<
+ ::com::sun::star::text::XTextRange > & xTextRange,
+ const sal_uInt16 nWhich)
+ throw (::com::sun::star::lang::IllegalArgumentException,
+ ::com::sun::star::uno::RuntimeException);
+
+ virtual ~SwXMeta();
+
+ /// @param pDoc and pMeta != 0, but not & because of ImplInheritanceHelper
+ SwXMeta(SwDoc *const pDoc, ::sw::Meta *const pMeta,
+ ::com::sun::star::uno::Reference< ::com::sun::star::text::XText> const&
+ xParentText,
+ TextRangeList_t const*const pPortions);
+
+public:
+
+ SwXMeta(SwDoc *const pDoc);
+
+ static ::com::sun::star::uno::Reference<
+ ::com::sun::star::rdf::XMetadatable >
+ CreateXMeta(
+ ::sw::Meta & rMeta,
+ ::com::sun::star::uno::Reference< ::com::sun::star::text::XText>
+ const& xParentText = 0,
+ ::std::auto_ptr<TextRangeList_t const> pPortions =
+ ::std::auto_ptr<TextRangeList_t const>(0));
+
+ /// init params with position of the attribute content (w/out CH_TXTATR)
+ bool SetContentRange(
+ SwTxtNode *& rpNode, xub_StrLen & rStart, xub_StrLen & rEnd) const;
+ ::com::sun::star::uno::Reference< ::com::sun::star::text::XText >
+ GetParentText() const;
+
+ bool CheckForOwnMemberMeta(const SwPaM & rPam, const bool bAbsorb)
+ throw (::com::sun::star::lang::IllegalArgumentException,
+ ::com::sun::star::uno::RuntimeException);
+
+ // MetadatableMixin
+ virtual ::sfx2::Metadatable * GetCoreObject();
+ virtual ::com::sun::star::uno::Reference< ::com::sun::star::frame::XModel >
+ GetModel();
+
+ static const ::com::sun::star::uno::Sequence< sal_Int8 > & getUnoTunnelId();
+
+ // XUnoTunnel
+ virtual sal_Int64 SAL_CALL getSomething(
+ const ::com::sun::star::uno::Sequence< sal_Int8 >& Identifier )
+ throw (::com::sun::star::uno::RuntimeException);
+
+ // XServiceInfo
+ virtual ::rtl::OUString SAL_CALL getImplementationName()
+ throw (::com::sun::star::uno::RuntimeException);
+ virtual sal_Bool SAL_CALL supportsService(
+ const ::rtl::OUString& rServiceName)
+ throw (::com::sun::star::uno::RuntimeException);
+ virtual ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL
+ getSupportedServiceNames()
+ throw (::com::sun::star::uno::RuntimeException);
+
+ // XComponent
+ virtual void SAL_CALL dispose()
+ throw (::com::sun::star::uno::RuntimeException);
+ virtual void SAL_CALL addEventListener(
+ const ::com::sun::star::uno::Reference<
+ ::com::sun::star::lang::XEventListener > & xListener)
+ throw (::com::sun::star::uno::RuntimeException);
+ virtual void SAL_CALL removeEventListener(
+ const ::com::sun::star::uno::Reference<
+ ::com::sun::star::lang::XEventListener > & xListener)
+ throw (::com::sun::star::uno::RuntimeException);
+
+ // XChild
+ virtual ::com::sun::star::uno::Reference<
+ ::com::sun::star::uno::XInterface > SAL_CALL
+ getParent()
+ throw (::com::sun::star::uno::RuntimeException);
+ virtual void SAL_CALL setParent(
+ ::com::sun::star::uno::Reference<
+ ::com::sun::star::uno::XInterface> const& xParent)
+ throw (::com::sun::star::uno::RuntimeException,
+ ::com::sun::star::lang::NoSupportException);
+
+ // XElementAccess
+ virtual ::com::sun::star::uno::Type SAL_CALL getElementType()
+ throw (::com::sun::star::uno::RuntimeException);
+ virtual sal_Bool SAL_CALL hasElements()
+ throw (::com::sun::star::uno::RuntimeException);
+
+ // XEnumerationAccess
+ virtual ::com::sun::star::uno::Reference<
+ ::com::sun::star::container::XEnumeration > SAL_CALL
+ createEnumeration()
+ throw (::com::sun::star::uno::RuntimeException);
+
+ // XTextContent
+ virtual void SAL_CALL attach(
+ const ::com::sun::star::uno::Reference<
+ ::com::sun::star::text::XTextRange > & xTextRange)
+ throw (::com::sun::star::lang::IllegalArgumentException,
+ ::com::sun::star::uno::RuntimeException);
+ virtual ::com::sun::star::uno::Reference<
+ ::com::sun::star::text::XTextRange > SAL_CALL getAnchor()
+ throw (::com::sun::star::uno::RuntimeException);
+
+ // XTextRange
+ virtual ::com::sun::star::uno::Reference< ::com::sun::star::text::XText >
+ SAL_CALL getText() throw (::com::sun::star::uno::RuntimeException);
+ virtual ::com::sun::star::uno::Reference<
+ ::com::sun::star::text::XTextRange > SAL_CALL getStart()
+ throw (::com::sun::star::uno::RuntimeException);
+ virtual ::com::sun::star::uno::Reference<
+ ::com::sun::star::text::XTextRange > SAL_CALL getEnd()
+ throw (::com::sun::star::uno::RuntimeException);
+ virtual rtl::OUString SAL_CALL getString()
+ throw (::com::sun::star::uno::RuntimeException);
+ virtual void SAL_CALL setString(const rtl::OUString& rString)
+ throw (::com::sun::star::uno::RuntimeException);
+
+ // XSimpleText
+ virtual ::com::sun::star::uno::Reference<
+ ::com::sun::star::text::XTextCursor > SAL_CALL
+ createTextCursor()
+ throw (::com::sun::star::uno::RuntimeException);
+ virtual ::com::sun::star::uno::Reference<
+ ::com::sun::star::text::XTextCursor > SAL_CALL
+ createTextCursorByRange(
+ const ::com::sun::star::uno::Reference<
+ ::com::sun::star::text::XTextRange > & xTextPosition)
+ throw (::com::sun::star::uno::RuntimeException);
+ virtual void SAL_CALL insertString(
+ const ::com::sun::star::uno::Reference<
+ ::com::sun::star::text::XTextRange > & xRange,
+ const rtl::OUString& aString, sal_Bool bAbsorb)
+ throw (::com::sun::star::uno::RuntimeException);
+ virtual void SAL_CALL insertControlCharacter(
+ const ::com::sun::star::uno::Reference<
+ ::com::sun::star::text::XTextRange > & xRange,
+ sal_Int16 nControlCharacter, sal_Bool bAbsorb)
+ throw (::com::sun::star::lang::IllegalArgumentException,
+ ::com::sun::star::uno::RuntimeException);
+
+ // XText
+ virtual void SAL_CALL insertTextContent(
+ const ::com::sun::star::uno::Reference<
+ ::com::sun::star::text::XTextRange > & xRange,
+ const ::com::sun::star::uno::Reference<
+ ::com::sun::star::text::XTextContent > & xContent,
+ sal_Bool bAbsorb)
+ throw (::com::sun::star::lang::IllegalArgumentException,
+ ::com::sun::star::uno::RuntimeException);
+ virtual void SAL_CALL removeTextContent(
+ const ::com::sun::star::uno::Reference<
+ ::com::sun::star::text::XTextContent > & xContent)
+ throw (::com::sun::star::container::NoSuchElementException,
+ ::com::sun::star::uno::RuntimeException);
+
+};
+
+
+typedef ::cppu::ImplInheritanceHelper2
+< SwXMeta
+, ::com::sun::star::beans::XPropertySet
+, ::com::sun::star::text::XTextField
+> SwXMetaField_Base;
+
+class SwXMetaField
+ : public SwXMetaField_Base
+{
+
+private:
+
+ virtual ~SwXMetaField();
+
+ friend ::com::sun::star::uno::Reference<
+ ::com::sun::star::rdf::XMetadatable >
+ SwXMeta::CreateXMeta(::sw::Meta &,
+ ::com::sun::star::uno::Reference< ::com::sun::star::text::XText>
+ const&,
+ ::std::auto_ptr<TextRangeList_t const> pPortions);
+
+ SwXMetaField(SwDoc *const pDoc, ::sw::Meta *const pMeta,
+ ::com::sun::star::uno::Reference< ::com::sun::star::text::XText> const&
+ xParentText,
+ TextRangeList_t const*const pPortions);
+
+public:
+
+ SwXMetaField(SwDoc *const pDoc);
+
+ // XServiceInfo
+ virtual ::rtl::OUString SAL_CALL getImplementationName()
+ throw (::com::sun::star::uno::RuntimeException);
+ virtual sal_Bool SAL_CALL supportsService(
+ const ::rtl::OUString& ServiceName)
+ throw (::com::sun::star::uno::RuntimeException);
+ virtual ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL
+ getSupportedServiceNames( )
+ throw (::com::sun::star::uno::RuntimeException);
+
+ // XComponent
+ virtual void SAL_CALL dispose()
+ throw (::com::sun::star::uno::RuntimeException);
+ virtual void SAL_CALL addEventListener(
+ const ::com::sun::star::uno::Reference<
+ ::com::sun::star::lang::XEventListener > & xListener)
+ throw (::com::sun::star::uno::RuntimeException);
+ virtual void SAL_CALL removeEventListener(
+ const ::com::sun::star::uno::Reference<
+ ::com::sun::star::lang::XEventListener > & xListener)
+ throw (::com::sun::star::uno::RuntimeException);
+
+ // XPropertySet
+ virtual ::com::sun::star::uno::Reference<
+ ::com::sun::star::beans::XPropertySetInfo > SAL_CALL
+ getPropertySetInfo()
+ throw (::com::sun::star::uno::RuntimeException);
+ virtual void SAL_CALL setPropertyValue(
+ const ::rtl::OUString& rPropertyName,
+ const ::com::sun::star::uno::Any& rValue)
+ throw (::com::sun::star::beans::UnknownPropertyException,
+ ::com::sun::star::beans::PropertyVetoException,
+ ::com::sun::star::lang::IllegalArgumentException,
+ ::com::sun::star::lang::WrappedTargetException,
+ ::com::sun::star::uno::RuntimeException);
+ virtual ::com::sun::star::uno::Any SAL_CALL
+ getPropertyValue(const ::rtl::OUString& rPropertyName)
+ throw (::com::sun::star::beans::UnknownPropertyException,
+ ::com::sun::star::lang::WrappedTargetException,
+ ::com::sun::star::uno::RuntimeException);
+ virtual void SAL_CALL addPropertyChangeListener(
+ const ::rtl::OUString& rPropertyName,
+ const ::com::sun::star::uno::Reference<
+ ::com::sun::star::beans::XPropertyChangeListener >& xListener)
+ throw (::com::sun::star::beans::UnknownPropertyException,
+ ::com::sun::star::lang::WrappedTargetException,
+ ::com::sun::star::uno::RuntimeException);
+ virtual void SAL_CALL removePropertyChangeListener(
+ const ::rtl::OUString& rPropertyName,
+ const ::com::sun::star::uno::Reference<
+ ::com::sun::star::beans::XPropertyChangeListener >& xListener)
+ throw (::com::sun::star::beans::UnknownPropertyException,
+ ::com::sun::star::lang::WrappedTargetException,
+ ::com::sun::star::uno::RuntimeException);
+ virtual void SAL_CALL addVetoableChangeListener(
+ const ::rtl::OUString& rPropertyName,
+ const ::com::sun::star::uno::Reference<
+ ::com::sun::star::beans::XVetoableChangeListener >& xListener)
+ throw (::com::sun::star::beans::UnknownPropertyException,
+ ::com::sun::star::lang::WrappedTargetException,
+ ::com::sun::star::uno::RuntimeException);
+ virtual void SAL_CALL removeVetoableChangeListener(
+ const ::rtl::OUString& rPropertyName,
+ const ::com::sun::star::uno::Reference<
+ ::com::sun::star::beans::XVetoableChangeListener >& xListener)
+ throw (::com::sun::star::beans::UnknownPropertyException,
+ ::com::sun::star::lang::WrappedTargetException,
+ ::com::sun::star::uno::RuntimeException);
+
+ // XTextContent
+ virtual void SAL_CALL attach(
+ const ::com::sun::star::uno::Reference<
+ ::com::sun::star::text::XTextRange > & xTextRange)
+ throw ( ::com::sun::star::lang::IllegalArgumentException,
+ ::com::sun::star::uno::RuntimeException );
+ virtual ::com::sun::star::uno::Reference<
+ ::com::sun::star::text::XTextRange > SAL_CALL getAnchor()
+ throw (::com::sun::star::uno::RuntimeException);
+
+ // XTextField
+ virtual rtl::OUString SAL_CALL getPresentation(sal_Bool bShowCommand)
+ throw (::com::sun::star::uno::RuntimeException);
+
+};
+
+/// get prefix/suffix from the RDF repository. @throws RuntimeException
+void getPrefixAndSuffix(
+ const ::com::sun::star::uno::Reference<
+ ::com::sun::star::frame::XModel>& xModel,
+ const ::com::sun::star::uno::Reference<
+ ::com::sun::star::rdf::XMetadatable>& xMetaField,
+ ::rtl::OUString *const o_pPrefix, ::rtl::OUString *const o_pSuffix);
+
+#endif // SW_UNOMETA_HXX
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/inc/viewimp.hxx b/sw/source/core/inc/viewimp.hxx
new file mode 100644
index 000000000000..84a840f43bc3
--- /dev/null
+++ b/sw/source/core/inc/viewimp.hxx
@@ -0,0 +1,353 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+#ifndef SW_VIEWIMP_HXX
+#define SW_VIEWIMP_HXX
+
+#include <vector>
+
+#include <vcl/timer.hxx>
+#include <tools/color.hxx>
+
+#include <svx/svdtypes.hxx>
+
+#include <tools/string.hxx>
+
+#include <swtypes.hxx>
+#include <swrect.hxx>
+
+class ViewShell;
+class SwFlyFrm;
+class SwViewOption;
+class SwRegionRects;
+class SwFrm;
+class SwLayAction;
+class SwLayIdle;
+class SwDrawView;
+class SdrPageView;
+class SwPageFrm;
+class SwRegionRects;
+struct SdrPaintProcRec;
+class SwAccessibleMap;
+class SdrObject;
+class Fraction;
+class SwPrintData;
+class SwPagePreviewLayout;
+struct PrevwPage;
+class SwTxtFrm;
+
+class SwViewImp
+{
+ friend class ViewShell;
+
+ friend class SwLayAction; //Lay- und IdleAction tragen sich ein und aus.
+ friend class SwLayIdle;
+
+ // for paint of page preview
+ friend class SwPagePreviewLayout;
+
+ ViewShell *pSh; //Falls jemand einen Imp durchreicht und doch
+ //mal eine ViewShell braucht hier die
+ //Rueckwaertsverkettung.
+
+ SwDrawView *pDrawView; //Unsere DrawView
+ SdrPageView *pSdrPageView; //Genau eine Seite fuer unsere DrawView
+
+ SwPageFrm *pFirstVisPage;//Zeigt immer auf die erste sichtbare Seite.
+ SwRegionRects *pRegion; //Sammler fuer Paintrects aus der LayAction.
+
+ SwLayAction *pLayAct; //Ist gesetzt wenn ein Action-Objekt existiert
+ //Wird vom SwLayAction-CTor ein- und vom DTor
+ //ausgetragen.
+ SwLayIdle *pIdleAct; //Analog zur SwLayAction fuer SwLayIdle.
+
+ SwAccessibleMap *pAccMap; // Accessible Wrappers
+
+ mutable const SdrObject * pSdrObjCached;
+ mutable String sSdrObjCachedComment;
+
+ sal_Bool bFirstPageInvalid :1; //Pointer auf erste Seite ungueltig?
+
+ sal_Bool bResetHdlHiddenPaint:1;// -- "" --
+
+ sal_Bool bSmoothUpdate :1; //Meber fuer SmoothScroll
+ sal_Bool bStopSmooth :1;
+ sal_Bool bStopPrt :1; // Stop Printing
+
+ sal_uInt16 nRestoreActions ; //Die Anzahl der zu restaurierenden Actions (UNO)
+ SwRect aSmoothRect;
+
+ SwPagePreviewLayout* mpPgPrevwLayout;
+
+ /**
+ Signal whether to stop printing.
+
+ @param _useless just to fit macro
+ */
+ DECL_LINK(SetStopPrt, void * _useless = NULL);
+
+ /**
+ Returns if printer shall be stopped.
+
+ @retval sal_True The printer shall be stopped.
+ @retval sal_False else
+ */
+ sal_Bool IsStopPrt() { return bStopPrt; }
+
+ /**
+ Resets signal for stopping printing.
+
+ */
+ void ResetStopPrt() { bStopPrt = sal_False; }
+
+ void SetFirstVisPage(); //Neue Ermittlung der ersten sichtbaren Seite
+
+ void StartAction(); //Henkel Anzeigen und verstecken.
+ void EndAction(); //gerufen von ViewShell::ImplXXXAction
+ void LockPaint(); //dito, gerufen von ViewShell::ImplLockPaint
+ void UnlockPaint();
+
+private:
+
+ SwAccessibleMap *CreateAccessibleMap();
+
+ /** invalidate CONTENT_FLOWS_FROM/_TO relation for paragraphs
+
+ #i27138#
+ implementation for wrapper method
+ <ViewShell::InvalidateAccessibleParaFlowRelation(..)>
+
+ @param _pFromTxtFrm
+ input parameter - paragraph frame, for which the relation CONTENT_FLOWS_FROM
+ has to be invalidated.
+ If NULL, no CONTENT_FLOWS_FROM relation has to be invalidated
+
+ @param _pToTxtFrm
+ input parameter - paragraph frame, for which the relation CONTENT_FLOWS_TO
+ has to be invalidated.
+ If NULL, no CONTENT_FLOWS_TO relation has to be invalidated
+ */
+ void _InvalidateAccessibleParaFlowRelation( const SwTxtFrm* _pFromTxtFrm,
+ const SwTxtFrm* _pToTxtFrm );
+
+ /** invalidate text selection for paragraphs
+
+ #i27301#
+ implementation for wrapper method
+ <ViewShell::InvalidateAccessibleParaTextSelection(..)>
+ */
+ void _InvalidateAccessibleParaTextSelection();
+
+ /** invalidate attributes for paragraphs and paragraph's characters
+
+ #i88069#
+ implementation for wrapper method
+ <ViewShell::InvalidateAccessibleParaAttrs(..)>
+ */
+ void _InvalidateAccessibleParaAttrs( const SwTxtFrm& rTxtFrm );
+
+public:
+ SwViewImp( ViewShell * );
+ ~SwViewImp();
+ void Init( const SwViewOption * ); //nur fuer ViewShell::Init()
+
+ const ViewShell *GetShell() const { return pSh; }
+ ViewShell *GetShell() { return pSh; }
+
+ Color GetRetoucheColor() const;
+
+ //Verwaltung zur ersten sichtbaren Seite
+ inline const SwPageFrm *GetFirstVisPage() const;
+ inline SwPageFrm *GetFirstVisPage();
+ void SetFirstVisPageInvalid() { bFirstPageInvalid = sal_True; }
+
+ sal_Bool AddPaintRect( const SwRect &rRect );
+ SwRegionRects *GetRegion() { return pRegion; }
+ void DelRegion();
+
+ // neues Interface fuer StarView Drawing
+ inline sal_Bool HasDrawView() const { return 0 != pDrawView; }
+ SwDrawView* GetDrawView() { return pDrawView; }
+ const SwDrawView* GetDrawView() const { return pDrawView; }
+ SdrPageView*GetPageView() { return pSdrPageView; }
+ const SdrPageView*GetPageView() const { return pSdrPageView; }
+ void MakeDrawView();
+
+ // add 3rd parameter <const Color* pPageBackgrdColor> for setting this
+ // color as the background color at the outliner of the draw view
+ // for painting layers <hell> and <heaven>
+
+ // add 4th parameter for the horizontal text
+ // direction of the page in order to set the default horizontal text
+ // direction at the outliner of the draw view for painting layers <hell>
+ // and <heaven>.
+
+ // correct type of 1st parameter
+ void PaintLayer( const SdrLayerID _nLayerID,
+ SwPrintData const*const pPrintData,
+ const SwRect& _rRect,
+ const Color* _pPageBackgrdColor = 0,
+ const bool _bIsPageRightToLeft = false ) const;
+
+ //wird als Link an die DrawEngine uebergeben, entscheidet was wie
+ //gepaintet wird oder nicht.
+
+ // Interface Drawing
+ sal_Bool IsDragPossible( const Point &rPoint );
+ void NotifySizeChg( const Size &rNewSz );
+
+ //SS Fuer die Lay- bzw. IdleAction und verwandtes
+ sal_Bool IsAction() const { return pLayAct != 0; }
+ sal_Bool IsIdleAction() const { return pIdleAct != 0; }
+ SwLayAction &GetLayAction() { return *pLayAct; }
+ const SwLayAction &GetLayAction() const { return *pLayAct; }
+ SwLayIdle &GetIdleAction() { return *pIdleAct;}
+ const SwLayIdle &GetIdleAction() const { return *pIdleAct;}
+
+ //Wenn eine Aktion laueft wird diese gebeten zu pruefen ob es
+ //an der zeit ist den WaitCrsr einzuschalten.
+ void CheckWaitCrsr();
+ sal_Bool IsCalcLayoutProgress() const; //Fragt die LayAction wenn vorhanden.
+ //sal_True wenn eine LayAction laeuft, dort wird dann auch das Flag fuer
+ //ExpressionFields gesetzt.
+ sal_Bool IsUpdateExpFlds();
+
+ void SetRestoreActions(sal_uInt16 nSet){nRestoreActions = nSet;}
+ sal_uInt16 GetRestoreActions() const{return nRestoreActions;}
+
+ void InitPagePreviewLayout();
+
+ inline SwPagePreviewLayout* PagePreviewLayout()
+ {
+ return mpPgPrevwLayout;
+ }
+
+ // Is this view accessible?
+ sal_Bool IsAccessible() const { return pAccMap != 0; }
+
+ inline SwAccessibleMap& GetAccessibleMap();
+
+ // Update (this) accessible view
+ void UpdateAccessible();
+
+ // Remove a frame from the accessible view
+ void DisposeAccessible( const SwFrm *pFrm, const SdrObject *pObj,
+ sal_Bool bRecursive );
+ inline void DisposeAccessibleFrm( const SwFrm *pFrm,
+ sal_Bool bRecursive=sal_False );
+ inline void DisposeAccessibleObj( const SdrObject *pObj );
+
+ // Move a frame's position in the accessible view
+ void MoveAccessible( const SwFrm *pFrm, const SdrObject *pObj,
+ const SwRect& rOldFrm );
+ inline void MoveAccessibleFrm( const SwFrm *pFrm, const SwRect& rOldFrm );
+
+ // Add a frame in the accessible view
+ inline void AddAccessibleFrm( const SwFrm *pFrm );
+
+ inline void AddAccessibleObj( const SdrObject *pObj );
+
+ // Invalidate accessible frame's frame's content
+ void InvalidateAccessibleFrmContent( const SwFrm *pFrm );
+
+ // Invalidate accessible frame's cursor position
+ void InvalidateAccessibleCursorPosition( const SwFrm *pFrm );
+
+ // Invalidate editable state for all accessible frames
+ void InvalidateAccessibleEditableState( sal_Bool bAllShells=sal_True,
+ const SwFrm *pFrm=0 );
+
+ // Invalidate frame's relation set (for chained frames)
+ void InvalidateAccessibleRelationSet( const SwFlyFrm *pMaster,
+ const SwFlyFrm *pFollow );
+
+ // update data for accessible preview
+ // change method signature due to new page preview functionality
+ void UpdateAccessiblePreview( const std::vector<PrevwPage*>& _rPrevwPages,
+ const Fraction& _rScale,
+ const SwPageFrm* _pSelectedPageFrm,
+ const Size& _rPrevwWinSize );
+
+ void InvalidateAccessiblePreViewSelection( sal_uInt16 nSelPage );
+
+ // Fire all accessible events that have been collected so far
+ void FireAccessibleEvents();
+};
+
+inline SwPageFrm *SwViewImp::GetFirstVisPage()
+{
+ if ( bFirstPageInvalid )
+ SetFirstVisPage();
+ return pFirstVisPage;
+}
+
+inline const SwPageFrm *SwViewImp::GetFirstVisPage() const
+{
+ if ( bFirstPageInvalid )
+ ((SwViewImp*)this)->SetFirstVisPage();
+ return pFirstVisPage;
+}
+
+inline SwAccessibleMap& SwViewImp::GetAccessibleMap()
+{
+ if( !pAccMap )
+ CreateAccessibleMap();
+
+ return *pAccMap;
+}
+
+inline void SwViewImp::DisposeAccessibleFrm( const SwFrm *pFrm,
+ sal_Bool bRecursive )
+{
+ DisposeAccessible( pFrm, 0, bRecursive );
+}
+
+inline void SwViewImp::DisposeAccessibleObj( const SdrObject *pObj )
+{
+ DisposeAccessible( 0, pObj, sal_False );
+}
+
+inline void SwViewImp::MoveAccessibleFrm( const SwFrm *pFrm,
+ const SwRect& rOldFrm )
+{
+ MoveAccessible( pFrm, 0, rOldFrm );
+}
+
+inline void SwViewImp::AddAccessibleFrm( const SwFrm *pFrm )
+{
+ SwRect aEmptyRect;
+ MoveAccessible( pFrm, 0, aEmptyRect );
+}
+
+inline void SwViewImp::AddAccessibleObj( const SdrObject *pObj )
+{
+ SwRect aEmptyRect;
+ MoveAccessible( 0, pObj, aEmptyRect );
+}
+#endif // SW_VIEWIMP_HXX
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/inc/visiturl.hxx b/sw/source/core/inc/visiturl.hxx
new file mode 100644
index 000000000000..b0d63c2baa9c
--- /dev/null
+++ b/sw/source/core/inc/visiturl.hxx
@@ -0,0 +1,48 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef _VISITURL_HXX
+#define _VISITURL_HXX
+
+#include <svl/lstner.hxx>
+
+class SwDoc;
+
+class SwURLStateChanged : public SfxListener
+{
+ const SwDoc* pDoc;
+public:
+ SwURLStateChanged( const SwDoc* pD );
+ virtual ~SwURLStateChanged();
+
+ virtual void Notify( SfxBroadcaster& rBC, const SfxHint& rHint );
+};
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/inc/wrong.hxx b/sw/source/core/inc/wrong.hxx
new file mode 100644
index 000000000000..71e00c1c9e46
--- /dev/null
+++ b/sw/source/core/inc/wrong.hxx
@@ -0,0 +1,167 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef _WRONG_HXX
+#define _WRONG_HXX
+
+#include <com/sun/star/container/XStringKeyMap.hpp>
+
+#include <vector>
+
+#include <tools/string.hxx>
+
+class SwWrongList;
+
+// ST2
+class SwWrongArea
+{
+public:
+ rtl::OUString maType;
+ com::sun::star::uno::Reference< com::sun::star::container::XStringKeyMap > mxPropertyBag;
+ xub_StrLen mnPos;
+ xub_StrLen mnLen;
+ SwWrongList* mpSubList;
+
+ SwWrongArea() : mnPos(0), mnLen(0), mpSubList(NULL) {}
+ SwWrongArea( const rtl::OUString& rType,
+ com::sun::star::uno::Reference< com::sun::star::container::XStringKeyMap > xPropertyBag,
+ xub_StrLen nPos,
+ xub_StrLen nLen,
+ SwWrongList* pSubList )
+ : maType(rType), mxPropertyBag(xPropertyBag), mnPos(nPos), mnLen(nLen), mpSubList(pSubList) {}
+};
+
+enum WrongListType
+{
+ WRONGLIST_SPELL,
+ WRONGLIST_GRAMMAR,
+ WRONGLIST_SMARTTAG,
+ WRONGLIST_CHANGETRACKING
+};
+
+class SwWrongList
+{
+ std::vector<SwWrongArea> maList;
+ WrongListType meType;
+
+ xub_StrLen nBeginInvalid; // Start of the invalid range
+ xub_StrLen nEndInvalid; // End of the invalid range
+
+ void ShiftLeft( xub_StrLen &rPos, xub_StrLen nStart, xub_StrLen nEnd )
+ { if( rPos > nStart ) rPos = rPos > nEnd ? rPos - nEnd + nStart : nStart; }
+ void ShiftRight( xub_StrLen &rPos, xub_StrLen nStart, xub_StrLen nEnd )
+ { if( rPos >= nStart ) rPos += nStart - nEnd; }
+ void _Invalidate( xub_StrLen nBegin, xub_StrLen nEnd );
+
+ void Insert(sal_uInt16 nWhere, std::vector<SwWrongArea>::iterator startPos, std::vector<SwWrongArea>::iterator endPos);
+ void Remove( sal_uInt16 nIdx, sal_uInt16 nLen );
+
+ // forbidden and not implemented
+ SwWrongList& operator= (const SwWrongList &);
+ SwWrongList( const SwWrongList& rCpy );
+
+public:
+ SwWrongList( WrongListType eType );
+
+ virtual ~SwWrongList();
+ virtual SwWrongList* Clone();
+ virtual void CopyFrom( const SwWrongList& rCopy );
+
+ inline WrongListType GetWrongListType() const { return meType; }
+ inline xub_StrLen GetBeginInv() const { return nBeginInvalid; }
+ inline xub_StrLen GetEndInv() const { return nEndInvalid; }
+ inline sal_Bool InsideInvalid( xub_StrLen nChk ) const
+ { return nChk >= nBeginInvalid && nChk <= nEndInvalid; }
+ void SetInvalid( xub_StrLen nBegin, xub_StrLen nEnd );
+ inline void Validate(){ nBeginInvalid = STRING_LEN; }
+ void Invalidate( xub_StrLen nBegin, xub_StrLen nEnd );
+ sal_Bool InvalidateWrong();
+ sal_Bool Fresh( xub_StrLen &rStart, xub_StrLen &rEnd, xub_StrLen nPos,
+ xub_StrLen nLen, sal_uInt16 nIndex, xub_StrLen nCursorPos );
+ sal_uInt16 GetWrongPos( xub_StrLen nValue ) const;
+
+ sal_Bool Check( xub_StrLen &rChk, xub_StrLen &rLn ) const;
+ sal_Bool InWrongWord( xub_StrLen &rChk, xub_StrLen &rLn ) const;
+ xub_StrLen NextWrong( xub_StrLen nChk ) const;
+
+ void Move( xub_StrLen nPos, long nDiff );
+ void ClearList();
+
+ // Divide the list into two part, the wrong words until nSplitPos will be
+ // removed and transferred to a new SwWrongList.
+ SwWrongList* SplitList( xub_StrLen nSplitPos );
+ // Join the next SwWrongList, nInsertPos is my own text length, where
+ // the other wrong list has to be inserted.
+ void JoinList( SwWrongList* pNext, xub_StrLen nInsertPos );
+
+ inline xub_StrLen Len( sal_uInt16 nIdx ) const
+ {
+ return nIdx < maList.size() ? maList[nIdx].mnLen : 0;
+ }
+
+ inline xub_StrLen Pos( sal_uInt16 nIdx ) const
+ {
+ return nIdx < maList.size() ? maList[nIdx].mnPos : 0;
+ }
+
+ inline sal_uInt16 Count() const { return (sal_uInt16)maList.size(); }
+
+ inline void Insert( const rtl::OUString& rType,
+ com::sun::star::uno::Reference< com::sun::star::container::XStringKeyMap > xPropertyBag,
+ xub_StrLen nNewPos, xub_StrLen nNewLen, sal_uInt16 nWhere )
+ {
+ std::vector<SwWrongArea>::iterator i = maList.begin();
+ if ( nWhere >= maList.size() )
+ i = maList.end(); // robust
+ else
+ i += nWhere;
+ maList.insert(i, SwWrongArea( rType, xPropertyBag, nNewPos, nNewLen, 0 ) );
+ }
+
+ void Insert( const rtl::OUString& rType,
+ com::sun::star::uno::Reference< com::sun::star::container::XStringKeyMap > xPropertyBag,
+ xub_StrLen nNewPos, xub_StrLen nNewLen );
+
+ inline SwWrongList* SubList( sal_uInt16 nIdx ) const
+ {
+ return nIdx < maList.size() ? maList[nIdx].mpSubList : 0;
+ }
+
+ void InsertSubList( xub_StrLen nNewPos, xub_StrLen nNewLen, sal_uInt16 nWhere, SwWrongList* pSubList );
+
+ inline const SwWrongArea* GetElement( sal_uInt16 nIdx ) const
+ {
+ return nIdx < maList.size() ? &maList[nIdx] : 0;
+ }
+ void RemoveEntry( xub_StrLen nBegin, xub_StrLen nEnd );
+ bool LookForEntry( xub_StrLen nBegin, xub_StrLen nEnd );
+};
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/layout/anchoreddrawobject.cxx b/sw/source/core/layout/anchoreddrawobject.cxx
new file mode 100644
index 000000000000..c00f394c9a83
--- /dev/null
+++ b/sw/source/core/layout/anchoreddrawobject.cxx
@@ -0,0 +1,900 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+#include <anchoreddrawobject.hxx>
+#include <svx/svdobj.hxx>
+#include <dcontact.hxx>
+#include <rootfrm.hxx>
+#include <pagefrm.hxx>
+#include <cntfrm.hxx>
+#include <doc.hxx>
+#include <tocntntanchoredobjectposition.hxx>
+#include <tolayoutanchoredobjectposition.hxx>
+#include <frmtool.hxx>
+#include <fmtornt.hxx>
+// --> #i32795#
+#include <txtfrm.hxx>
+// <--
+// --> #i32795#
+// template class <std::vector>
+#include <vector>
+// <--
+
+// --> #i28749#
+#include <com/sun/star/text/PositionLayoutDir.hpp>
+// <--
+// --> #i44559#
+#include <ndtxt.hxx>
+// <--
+
+using namespace ::com::sun::star;
+
+// ============================================================================
+// helper class for correct notification due to the positioning of
+// the anchored drawing object
+// ============================================================================
+class SwPosNotify
+{
+ private:
+ SwAnchoredDrawObject* mpAnchoredDrawObj;
+ SwRect maOldObjRect;
+ SwPageFrm* mpOldPageFrm;
+
+ public:
+ SwPosNotify( SwAnchoredDrawObject* _pAnchoredDrawObj );
+ ~SwPosNotify();
+ // --> OD 2004-08-12 #i32795#
+ Point LastObjPos() const;
+ // <--
+};
+
+SwPosNotify::SwPosNotify( SwAnchoredDrawObject* _pAnchoredDrawObj ) :
+ mpAnchoredDrawObj( _pAnchoredDrawObj )
+{
+ maOldObjRect = mpAnchoredDrawObj->GetObjRect();
+ // --> #i35640# - determine correct page frame
+ mpOldPageFrm = mpAnchoredDrawObj->GetPageFrm();
+ // <--
+}
+
+SwPosNotify::~SwPosNotify()
+{
+ if ( maOldObjRect != mpAnchoredDrawObj->GetObjRect() )
+ {
+ if( maOldObjRect.HasArea() && mpOldPageFrm )
+ {
+ mpAnchoredDrawObj->NotifyBackground( mpOldPageFrm, maOldObjRect,
+ PREP_FLY_LEAVE );
+ }
+ SwRect aNewObjRect( mpAnchoredDrawObj->GetObjRect() );
+ if( aNewObjRect.HasArea() )
+ {
+ // --> #i35640# - determine correct page frame
+ SwPageFrm* pNewPageFrm = mpAnchoredDrawObj->GetPageFrm();
+ // <--
+ if( pNewPageFrm )
+ mpAnchoredDrawObj->NotifyBackground( pNewPageFrm, aNewObjRect,
+ PREP_FLY_ARRIVE );
+ }
+
+ ::ClrContourCache( mpAnchoredDrawObj->GetDrawObj() );
+
+ // --> #i35640# - additional notify anchor text frame
+ // Needed for negative positioned drawing objects
+ // --> #i43255# - refine condition to avoid unneeded
+ // invalidations: anchored object had to be on the page of its anchor
+ // text frame.
+ if ( mpAnchoredDrawObj->GetAnchorFrm()->IsTxtFrm() &&
+ mpOldPageFrm == mpAnchoredDrawObj->GetAnchorFrm()->FindPageFrm() )
+ {
+ mpAnchoredDrawObj->AnchorFrm()->Prepare( PREP_FLY_LEAVE );
+ }
+ // <--
+
+ // indicate a restart of the layout process
+ mpAnchoredDrawObj->SetRestartLayoutProcess( true );
+ }
+ else
+ {
+ // lock position
+ mpAnchoredDrawObj->LockPosition();
+
+ if ( !mpAnchoredDrawObj->ConsiderForTextWrap() )
+ {
+ // indicate that object has to be considered for text wrap
+ mpAnchoredDrawObj->SetConsiderForTextWrap( true );
+ // invalidate 'background' in order to allow its 'background'
+ // to wrap around it.
+ mpAnchoredDrawObj->NotifyBackground( mpAnchoredDrawObj->GetPageFrm(),
+ mpAnchoredDrawObj->GetObjRectWithSpaces(),
+ PREP_FLY_ARRIVE );
+ // invalidate position of anchor frame in order to force
+ // a re-format of the anchor frame, which also causes a
+ // re-format of the invalid previous frames of the anchor frame.
+ mpAnchoredDrawObj->AnchorFrm()->InvalidatePos();
+ }
+ }
+}
+
+// --> #i32795#
+Point SwPosNotify::LastObjPos() const
+{
+ return maOldObjRect.Pos();
+}
+//<--
+
+// ============================================================================
+// #i32795#
+// helper class for oscillation control on object positioning
+// ============================================================================
+class SwObjPosOscillationControl
+{
+ private:
+ sal_uInt8 mnPosStackSize;
+
+ const SwAnchoredDrawObject* mpAnchoredDrawObj;
+
+ std::vector<Point*> maObjPositions;
+
+ public:
+ SwObjPosOscillationControl( const SwAnchoredDrawObject& _rAnchoredDrawObj );
+ ~SwObjPosOscillationControl();
+
+ bool OscillationDetected();
+};
+
+SwObjPosOscillationControl::SwObjPosOscillationControl(
+ const SwAnchoredDrawObject& _rAnchoredDrawObj )
+ : mnPosStackSize( 20 ),
+ mpAnchoredDrawObj( &_rAnchoredDrawObj )
+{
+}
+
+SwObjPosOscillationControl::~SwObjPosOscillationControl()
+{
+ while ( !maObjPositions.empty() )
+ {
+ Point* pPos = maObjPositions.back();
+ delete pPos;
+
+ maObjPositions.pop_back();
+ }
+}
+
+bool SwObjPosOscillationControl::OscillationDetected()
+{
+ bool bOscillationDetected = false;
+
+ if ( maObjPositions.size() == mnPosStackSize )
+ {
+ // position stack is full -> oscillation
+ bOscillationDetected = true;
+ }
+ else
+ {
+ Point* pNewObjPos = new Point( mpAnchoredDrawObj->GetObjRect().Pos() );
+ for ( std::vector<Point*>::iterator aObjPosIter = maObjPositions.begin();
+ aObjPosIter != maObjPositions.end();
+ ++aObjPosIter )
+ {
+ if ( *(pNewObjPos) == *(*aObjPosIter) )
+ {
+ // position already occurred -> oscillation
+ bOscillationDetected = true;
+ delete pNewObjPos;
+ break;
+ }
+ }
+ if ( !bOscillationDetected )
+ {
+ maObjPositions.push_back( pNewObjPos );
+ }
+ }
+
+ return bOscillationDetected;
+}
+
+// ============================================================================
+// implementation of class <SwAnchoredDrawObject>
+// ============================================================================
+TYPEINIT1(SwAnchoredDrawObject,SwAnchoredObject);
+
+SwAnchoredDrawObject::SwAnchoredDrawObject() :
+ SwAnchoredObject(),
+ mbValidPos( false ),
+ // --> #i34748#
+ mpLastObjRect( 0L ),
+ // <--
+ mbNotYetAttachedToAnchorFrame( true ),
+ // --> #i28749#
+ mbNotYetPositioned( true ),
+ // <--
+ // --> #i62875#
+ mbCaptureAfterLayoutDirChange( false )
+ // <--
+{
+}
+
+SwAnchoredDrawObject::~SwAnchoredDrawObject()
+{
+ // --> follow-up of #i34748#
+ delete mpLastObjRect;
+ // <--
+}
+
+// --> #i62875#
+void SwAnchoredDrawObject::UpdateLayoutDir()
+{
+ SwFrmFmt::tLayoutDir nOldLayoutDir( GetFrmFmt().GetLayoutDir() );
+
+ SwAnchoredObject::UpdateLayoutDir();
+
+ if ( !NotYetPositioned() &&
+ GetFrmFmt().GetLayoutDir() != nOldLayoutDir &&
+ GetFrmFmt().GetDoc()->get(IDocumentSettingAccess::DO_NOT_CAPTURE_DRAW_OBJS_ON_PAGE) &&
+ !IsOutsidePage() )
+ {
+ mbCaptureAfterLayoutDirChange = true;
+ }
+}
+// <--
+
+// --> #i62875#
+bool SwAnchoredDrawObject::IsOutsidePage() const
+{
+ bool bOutsidePage( false );
+
+ if ( !NotYetPositioned() && GetPageFrm() )
+ {
+ SwRect aTmpRect( GetObjRect() );
+ bOutsidePage =
+ ( aTmpRect.Intersection( GetPageFrm()->Frm() ) != GetObjRect() );
+ }
+
+ return bOutsidePage;
+}
+// <--
+
+// =============================================================================
+// #i26791# - implementation of pure virtual method declared in
+// base class <SwAnchoredObject>
+// =============================================================================
+void SwAnchoredDrawObject::MakeObjPos()
+{
+ if ( IsPositioningInProgress() )
+ {
+ // nothind to do - positioning already in progress
+ return;
+ }
+
+ if ( mbValidPos )
+ {
+ // nothing to do - position is valid
+ return;
+ }
+
+ // --> #i28749# - anchored drawing object has to be attached
+ // to anchor frame
+ if ( mbNotYetAttachedToAnchorFrame )
+ {
+ OSL_FAIL( "<SwAnchoredDrawObject::MakeObjPos() - drawing object not yet attached to anchor frame -> no positioning" );
+ return;
+ }
+
+ SwDrawContact* pDrawContact =
+ static_cast<SwDrawContact*>(::GetUserCall( GetDrawObj() ));
+
+ // --> #i28749# - if anchored drawing object hasn't been yet
+ // positioned, convert its positioning attributes, if its positioning
+ // attributes are given in horizontal left-to-right layout.
+ // --> #i36010# - Note: horizontal left-to-right layout is made
+ // the default layout direction for <SwDrawFrmFmt> instances. Thus, it has
+ // to be adjusted manually, if no adjustment of the positioning attributes
+ // have to be performed here.
+ // --> #i35635# - additionally move drawing object to the visible layer.
+ if ( mbNotYetPositioned )
+ {
+ // --> #i35635#
+ pDrawContact->MoveObjToVisibleLayer( DrawObj() );
+ // <--
+ // --> perform conversion of positioning
+ // attributes only for 'master' drawing objects
+ // --> #i44334#, #i44681# - check, if positioning
+ // attributes already have been set.
+ if ( !GetDrawObj()->ISA(SwDrawVirtObj) &&
+ !static_cast<SwDrawFrmFmt&>(GetFrmFmt()).IsPosAttrSet() )
+ {
+ _SetPositioningAttr();
+ }
+ // <--
+ // -->
+ // - reset internal flag after all needed actions are performed to
+ // avoid callbacks from drawing layer
+ mbNotYetPositioned = false;
+ // <--
+ }
+ // <--
+
+ // indicate that positioning is in progress
+ {
+ SwObjPositioningInProgress aObjPosInProgress( *this );
+
+ // determine relative position of drawing object and set it
+ switch ( pDrawContact->GetAnchorId() )
+ {
+ case FLY_AS_CHAR:
+ {
+ // indicate that position will be valid after positioning is performed
+ mbValidPos = true;
+ // nothing to do, because as-character anchored objects are positioned
+ // during the format of its anchor frame - see <SwFlyCntPortion::SetBase(..)>
+ }
+ break;
+ case FLY_AT_PARA:
+ case FLY_AT_CHAR:
+ {
+ // --> #i32795# - move intrinsic positioning to
+ // helper method <_MakeObjPosAnchoredAtPara()>
+ _MakeObjPosAnchoredAtPara();
+ }
+ break;
+ case FLY_AT_PAGE:
+ case FLY_AT_FLY:
+ {
+ // --> #i32795# - move intrinsic positioning to
+ // helper method <_MakeObjPosAnchoredAtLayout()>
+ _MakeObjPosAnchoredAtLayout();
+ }
+ break;
+ default:
+ {
+ OSL_FAIL( "<SwAnchoredDrawObject::MakeObjPos()> - unknown anchor type - please inform OD." );
+ }
+ }
+
+ // keep, current object rectangle
+ // --> #i34748# - use new method <SetLastObjRect(..)>
+ SetLastObjRect( GetObjRect().SVRect() );
+ // <--
+
+ // Assure for 'master' drawing object, that it's registered at the correct page.
+ // Perform check not for as-character anchored drawing objects and only if
+ // the anchor frame is valid.
+ if ( !GetDrawObj()->ISA(SwDrawVirtObj) &&
+ !pDrawContact->ObjAnchoredAsChar() &&
+ GetAnchorFrm()->IsValid() )
+ {
+ pDrawContact->ChkPage();
+ }
+ }
+
+ // --> #i62875#
+ if ( mbCaptureAfterLayoutDirChange &&
+ GetPageFrm() )
+ {
+ SwRect aPageRect( GetPageFrm()->Frm() );
+ SwRect aObjRect( GetObjRect() );
+ if ( aObjRect.Right() >= aPageRect.Right() + 10 )
+ {
+ Size aSize( aPageRect.Right() - aObjRect.Right(), 0 );
+ DrawObj()->Move( aSize );
+ aObjRect = GetObjRect();
+ }
+
+ if ( aObjRect.Left() + 10 <= aPageRect.Left() )
+ {
+ Size aSize( aPageRect.Left() - aObjRect.Left(), 0 );
+ DrawObj()->Move( aSize );
+ }
+
+ mbCaptureAfterLayoutDirChange = false;
+ }
+ // <--
+}
+
+/** method for the intrinsic positioning of a at-paragraph|at-character
+ anchored drawing object
+
+ #i32795# - helper method for method <MakeObjPos>
+
+ @author OD
+*/
+void SwAnchoredDrawObject::_MakeObjPosAnchoredAtPara()
+{
+ // --> #i32795# - adopt positioning algorithm from Writer
+ // fly frames, which are anchored at paragraph|at character
+
+ // Determine, if anchor frame can/has to be formatted.
+ // If yes, after each object positioning the anchor frame is formatted.
+ // If after the anchor frame format the object position isn't valid, the
+ // object is positioned again.
+ // --> #i43255# - refine condition: anchor frame format not
+ // allowed, if another anchored object, has to be consider its wrap influence
+ // --> #i50356# - format anchor frame containing the anchor
+ // position. E.g., for at-character anchored object this can be the follow
+ // frame of the anchor frame, which contains the anchor character.
+ const bool bFormatAnchor =
+ !static_cast<const SwTxtFrm*>( GetAnchorFrmContainingAnchPos() )->IsAnyJoinLocked() &&
+ !ConsiderObjWrapInfluenceOnObjPos() &&
+ !ConsiderObjWrapInfluenceOfOtherObjs();
+ // <--
+
+ if ( bFormatAnchor )
+ {
+ // --> #i50356#
+ GetAnchorFrmContainingAnchPos()->Calc();
+ // <--
+ }
+
+ bool bOscillationDetected = false;
+ SwObjPosOscillationControl aObjPosOscCtrl( *this );
+ // --> #i3317# - boolean, to apply temporarly the
+ // 'straightforward positioning process' for the frame due to its
+ // overlapping with a previous column.
+ bool bConsiderWrapInfluenceDueToOverlapPrevCol( false );
+ // <--
+ do {
+ // indicate that position will be valid after positioning is performed
+ mbValidPos = true;
+
+ // --> #i35640# - correct scope for <SwPosNotify> instance
+ {
+ // create instance of <SwPosNotify> for correct notification
+ SwPosNotify aPosNotify( this );
+
+ // determine and set position
+ objectpositioning::SwToCntntAnchoredObjectPosition
+ aObjPositioning( *DrawObj() );
+ aObjPositioning.CalcPosition();
+
+ // get further needed results of the positioning algorithm
+ SetVertPosOrientFrm ( aObjPositioning.GetVertPosOrientFrm() );
+ _SetDrawObjAnchor();
+
+ // check for object position oscillation, if position has changed.
+ if ( GetObjRect().Pos() != aPosNotify.LastObjPos() )
+ {
+ bOscillationDetected = aObjPosOscCtrl.OscillationDetected();
+ }
+ }
+ // <--
+ // format anchor frame, if requested.
+ // Note: the format of the anchor frame can cause the object position
+ // to be invalid.
+ if ( bFormatAnchor )
+ {
+ // --> #i50356#
+ GetAnchorFrmContainingAnchPos()->Calc();
+ // <--
+ }
+
+ // --> #i3317#
+ if ( !ConsiderObjWrapInfluenceOnObjPos() &&
+ OverlapsPrevColumn() )
+ {
+ bConsiderWrapInfluenceDueToOverlapPrevCol = true;
+ }
+ // <--
+ } while ( !mbValidPos && !bOscillationDetected &&
+ !bConsiderWrapInfluenceDueToOverlapPrevCol );
+
+ // --> #i3317# - consider a detected oscillation and overlapping
+ // with previous column.
+ // temporarly consider the anchored objects wrapping style influence
+ if ( bOscillationDetected || bConsiderWrapInfluenceDueToOverlapPrevCol )
+ {
+ SetTmpConsiderWrapInfluence( true );
+ SetRestartLayoutProcess( true );
+ }
+ // <--
+}
+
+/** method for the intrinsic positioning of a at-page|at-frame anchored
+ drawing object
+
+ #i32795# - helper method for method <MakeObjPos>
+
+ @author OD
+*/
+void SwAnchoredDrawObject::_MakeObjPosAnchoredAtLayout()
+{
+ // indicate that position will be valid after positioning is performed
+ mbValidPos = true;
+
+ // create instance of <SwPosNotify> for correct notification
+ SwPosNotify aPosNotify( this );
+
+ // determine position
+ objectpositioning::SwToLayoutAnchoredObjectPosition
+ aObjPositioning( *DrawObj() );
+ aObjPositioning.CalcPosition();
+
+ // set position
+
+ // --> #i31698#
+ // --> #i34995# - setting anchor position needed for filters,
+ // especially for the xml-filter to the OpenOffice.org file format
+ {
+ const Point aNewAnchorPos =
+ GetAnchorFrm()->GetFrmAnchorPos( ::HasWrap( GetDrawObj() ) );
+ DrawObj()->SetAnchorPos( aNewAnchorPos );
+ // --> #i70122# - missing invalidation
+ InvalidateObjRectWithSpaces();
+ // <--
+ }
+ // <--
+ SetCurrRelPos( aObjPositioning.GetRelPos() );
+ const SwFrm* pAnchorFrm = GetAnchorFrm();
+ SWRECTFN( pAnchorFrm );
+ const Point aAnchPos( (pAnchorFrm->Frm().*fnRect->fnGetPos)() );
+ SetObjLeft( aAnchPos.X() + GetCurrRelPos().X() );
+ SetObjTop( aAnchPos.Y() + GetCurrRelPos().Y() );
+ // <--
+}
+
+void SwAnchoredDrawObject::_SetDrawObjAnchor()
+{
+ // new anchor position
+ // --> #i31698# -
+ Point aNewAnchorPos =
+ GetAnchorFrm()->GetFrmAnchorPos( ::HasWrap( GetDrawObj() ) );
+ Point aCurrAnchorPos = GetDrawObj()->GetAnchorPos();
+ if ( aNewAnchorPos != aCurrAnchorPos )
+ {
+ // determine movement to be applied after setting the new anchor position
+ Size aMove( aCurrAnchorPos.X() - aNewAnchorPos.X(),
+ aCurrAnchorPos.Y() - aNewAnchorPos.Y() );
+ // set new anchor position
+ DrawObj()->SetAnchorPos( aNewAnchorPos );
+ // correct object position, caused by setting new anchor position
+ DrawObj()->Move( aMove );
+ // --> #i70122# - missing invalidation
+ InvalidateObjRectWithSpaces();
+ // <--
+ }
+}
+
+/** method to invalidate the given page frame
+
+ #i28701#
+
+ @author OD
+*/
+void SwAnchoredDrawObject::_InvalidatePage( SwPageFrm* _pPageFrm )
+{
+ if ( _pPageFrm && !_pPageFrm->GetFmt()->GetDoc()->IsInDtor() )
+ {
+ if ( _pPageFrm->GetUpper() )
+ {
+ // --> #i35007# - correct invalidation for as-character
+ // anchored objects.
+ if ( GetFrmFmt().GetAnchor().GetAnchorId() == FLY_AS_CHAR )
+ {
+ _pPageFrm->InvalidateFlyInCnt();
+ }
+ else
+ {
+ _pPageFrm->InvalidateFlyLayout();
+ }
+ // <--
+
+ SwRootFrm* pRootFrm = static_cast<SwRootFrm*>(_pPageFrm->GetUpper());
+ pRootFrm->DisallowTurbo();
+ if ( pRootFrm->GetTurbo() )
+ {
+ const SwCntntFrm* pTmpFrm = pRootFrm->GetTurbo();
+ pRootFrm->ResetTurbo();
+ pTmpFrm->InvalidatePage();
+ }
+ pRootFrm->SetIdleFlags();
+ }
+ }
+}
+
+void SwAnchoredDrawObject::InvalidateObjPos()
+{
+ // --> #i28701# - check, if invalidation is allowed
+ if ( mbValidPos &&
+ InvalidationOfPosAllowed() )
+ {
+ mbValidPos = false;
+ // --> #i68520#
+ InvalidateObjRectWithSpaces();
+ // <--
+
+ // --> #i44339# - check, if anchor frame exists.
+ if ( GetAnchorFrm() )
+ {
+ // --> #118547# - notify anchor frame of as-character
+ // anchored object, because its positioned by the format of its anchor frame.
+ // --> #i44559# - assure, that text hint is already
+ // existing in the text frame
+ if ( GetAnchorFrm()->ISA(SwTxtFrm) &&
+ (GetFrmFmt().GetAnchor().GetAnchorId() == FLY_AS_CHAR) )
+ {
+ SwTxtFrm* pAnchorTxtFrm( static_cast<SwTxtFrm*>(AnchorFrm()) );
+ if ( pAnchorTxtFrm->GetTxtNode()->GetpSwpHints() &&
+ pAnchorTxtFrm->CalcFlyPos( &GetFrmFmt() ) != STRING_LEN )
+ {
+ AnchorFrm()->Prepare( PREP_FLY_ATTR_CHG, &GetFrmFmt() );
+ }
+ }
+ // <--
+
+ SwPageFrm* pPageFrm = AnchorFrm()->FindPageFrm();
+ _InvalidatePage( pPageFrm );
+
+ // --> #i32270# - also invalidate page frame, at which the
+ // drawing object is registered at.
+ SwPageFrm* pPageFrmRegisteredAt = GetPageFrm();
+ if ( pPageFrmRegisteredAt &&
+ pPageFrmRegisteredAt != pPageFrm )
+ {
+ _InvalidatePage( pPageFrmRegisteredAt );
+ }
+ // <--
+ // --> #i33751#, #i34060# - method <GetPageFrmOfAnchor()>
+ // is replaced by method <FindPageFrmOfAnchor()>. It's return value
+ // have to be checked.
+ SwPageFrm* pPageFrmOfAnchor = FindPageFrmOfAnchor();
+ if ( pPageFrmOfAnchor &&
+ pPageFrmOfAnchor != pPageFrm &&
+ pPageFrmOfAnchor != pPageFrmRegisteredAt )
+ // <--
+ {
+ _InvalidatePage( pPageFrmOfAnchor );
+ }
+ }
+ // <--
+ }
+}
+
+SwFrmFmt& SwAnchoredDrawObject::GetFrmFmt()
+{
+ OSL_ENSURE( static_cast<SwDrawContact*>(GetUserCall(GetDrawObj()))->GetFmt(),
+ "<SwAnchoredDrawObject::GetFrmFmt()> - missing frame format -> crash." );
+ return *(static_cast<SwDrawContact*>(GetUserCall(GetDrawObj()))->GetFmt());
+}
+const SwFrmFmt& SwAnchoredDrawObject::GetFrmFmt() const
+{
+ OSL_ENSURE( static_cast<SwDrawContact*>(GetUserCall(GetDrawObj()))->GetFmt(),
+ "<SwAnchoredDrawObject::GetFrmFmt()> - missing frame format -> crash." );
+ return *(static_cast<SwDrawContact*>(GetUserCall(GetDrawObj()))->GetFmt());
+}
+
+const SwRect SwAnchoredDrawObject::GetObjRect() const
+{
+ // use geometry of drawing object
+ //return GetDrawObj()->GetCurrentBoundRect();
+ return GetDrawObj()->GetSnapRect();
+}
+
+// --> #i70122#
+const SwRect SwAnchoredDrawObject::GetObjBoundRect() const
+{
+ return GetDrawObj()->GetCurrentBoundRect();
+}
+// <--
+
+// --> #i68520#
+bool SwAnchoredDrawObject::_SetObjTop( const SwTwips _nTop )
+{
+ SwTwips nDiff = _nTop - GetObjRect().Top();
+ DrawObj()->Move( Size( 0, nDiff ) );
+
+ return nDiff != 0;
+}
+bool SwAnchoredDrawObject::_SetObjLeft( const SwTwips _nLeft )
+{
+ SwTwips nDiff = _nLeft - GetObjRect().Left();
+ DrawObj()->Move( Size( nDiff, 0 ) );
+
+ return nDiff != 0;
+}
+// <--
+
+/** adjust positioning and alignment attributes for new anchor frame
+
+ #i33313# - add second optional parameter <_pNewObjRect>
+
+ @author OD
+*/
+void SwAnchoredDrawObject::AdjustPositioningAttr( const SwFrm* _pNewAnchorFrm,
+ const SwRect* _pNewObjRect )
+{
+ SwTwips nHoriRelPos = 0;
+ SwTwips nVertRelPos = 0;
+ const Point aAnchorPos = _pNewAnchorFrm->GetFrmAnchorPos( ::HasWrap( GetDrawObj() ) );
+ // --> #i33313#
+ const SwRect aObjRect( _pNewObjRect ? *_pNewObjRect : GetObjRect() );
+ // <--
+ const bool bVert = _pNewAnchorFrm->IsVertical();
+ const bool bR2L = _pNewAnchorFrm->IsRightToLeft();
+ if ( bVert )
+ {
+ nHoriRelPos = aObjRect.Top() - aAnchorPos.Y();
+ nVertRelPos = aAnchorPos.X() - aObjRect.Right();
+ }
+ else if ( bR2L )
+ {
+ nHoriRelPos = aAnchorPos.X() - aObjRect.Right();
+ nVertRelPos = aObjRect.Top() - aAnchorPos.Y();
+ }
+ else
+ {
+ nHoriRelPos = aObjRect.Left() - aAnchorPos.X();
+ nVertRelPos = aObjRect.Top() - aAnchorPos.Y();
+ }
+
+ GetFrmFmt().SetFmtAttr( SwFmtHoriOrient( nHoriRelPos, text::HoriOrientation::NONE, text::RelOrientation::FRAME ) );
+ GetFrmFmt().SetFmtAttr( SwFmtVertOrient( nVertRelPos, text::VertOrientation::NONE, text::RelOrientation::FRAME ) );
+}
+
+// --> #i34748# - change return type
+const Rectangle* SwAnchoredDrawObject::GetLastObjRect() const
+{
+ return mpLastObjRect;
+}
+// <--
+
+// --> #i34748# - change return type.
+// If member <mpLastObjRect> is NULL, create one.
+void SwAnchoredDrawObject::SetLastObjRect( const Rectangle& _rNewLastRect )
+{
+ if ( !mpLastObjRect )
+ {
+ mpLastObjRect = new Rectangle;
+ }
+ *(mpLastObjRect) = _rNewLastRect;
+}
+// <--
+
+void SwAnchoredDrawObject::ObjectAttachedToAnchorFrame()
+{
+ // --> #i31698#
+ SwAnchoredObject::ObjectAttachedToAnchorFrame();
+ // <--
+
+ if ( mbNotYetAttachedToAnchorFrame )
+ {
+ mbNotYetAttachedToAnchorFrame = false;
+ }
+}
+
+/** method to set positioning attributes
+
+ #i35798#
+ During load the positioning attributes aren't set.
+ Thus, the positioning attributes are set by the current object geometry.
+ This method is also used for the conversion for drawing objects
+ (not anchored as-character) imported from OpenOffice.org file format
+ once and directly before the first positioning.
+
+ @author OD
+*/
+void SwAnchoredDrawObject::_SetPositioningAttr()
+{
+ SwDrawContact* pDrawContact =
+ static_cast<SwDrawContact*>(GetUserCall( GetDrawObj() ));
+
+ if ( !pDrawContact->ObjAnchoredAsChar() )
+ {
+ SwRect aObjRect( GetObjRect() );
+
+ SwTwips nHoriPos = aObjRect.Left();
+ SwTwips nVertPos = aObjRect.Top();
+ // --> #i44334#, #i44681#
+ // perform conversion only if position is in horizontal-left-to-right-layout.
+ if ( GetFrmFmt().GetPositionLayoutDir() ==
+ text::PositionLayoutDir::PositionInHoriL2R )
+ {
+ SwFrmFmt::tLayoutDir eLayoutDir = GetFrmFmt().GetLayoutDir();
+ switch ( eLayoutDir )
+ {
+ case SwFrmFmt::HORI_L2R:
+ {
+ // nothing to do
+ }
+ break;
+ case SwFrmFmt::HORI_R2L:
+ {
+ nHoriPos = -aObjRect.Left() - aObjRect.Width();
+ }
+ break;
+ case SwFrmFmt::VERT_R2L:
+ {
+ nHoriPos = aObjRect.Top();
+ nVertPos = -aObjRect.Left() - aObjRect.Width();
+ }
+ break;
+ default:
+ {
+ OSL_FAIL( "<SwAnchoredDrawObject::_SetPositioningAttr()> - unsupported layout direction" );
+ }
+ }
+ }
+ // <--
+
+ // --> #i71182#
+ // only change position - do not lose other attributes
+ SwFmtHoriOrient aHori( GetFrmFmt().GetHoriOrient() );
+ aHori.SetPos( nHoriPos );
+ GetFrmFmt().SetFmtAttr( aHori );
+
+ SwFmtVertOrient aVert( GetFrmFmt().GetVertOrient() );
+
+ aVert.SetPos( nVertPos );
+ GetFrmFmt().SetFmtAttr( aVert );
+ // <--
+
+ // --> #i36010# - set layout direction of the position
+ GetFrmFmt().SetPositionLayoutDir(
+ text::PositionLayoutDir::PositionInLayoutDirOfAnchor );
+ // <--
+ }
+ // --> #i65798# - also for as-character anchored objects
+ // --> #i45952# - indicate that position
+ // attributes are set now.
+ static_cast<SwDrawFrmFmt&>(GetFrmFmt()).PosAttrSet();
+ // <--
+}
+
+void SwAnchoredDrawObject::NotifyBackground( SwPageFrm* _pPageFrm,
+ const SwRect& _rRect,
+ PrepareHint _eHint )
+{
+ ::Notify_Background( GetDrawObj(), _pPageFrm, _rRect, _eHint, sal_True );
+}
+
+/** method to assure that anchored object is registered at the correct
+ page frame
+
+ #i28701#
+
+ @author OD
+*/
+void SwAnchoredDrawObject::RegisterAtCorrectPage()
+{
+ SwPageFrm* pPageFrm( 0L );
+ if ( GetVertPosOrientFrm() )
+ {
+ pPageFrm = const_cast<SwPageFrm*>(GetVertPosOrientFrm()->FindPageFrm());
+ }
+ if ( pPageFrm && GetPageFrm() != pPageFrm )
+ {
+ if ( GetPageFrm() )
+ GetPageFrm()->RemoveDrawObjFromPage( *this );
+ pPageFrm->AppendDrawObjToPage( *this );
+ }
+}
+
+// =============================================================================
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/layout/anchoredobject.cxx b/sw/source/core/layout/anchoredobject.cxx
new file mode 100644
index 000000000000..d33b6e009753
--- /dev/null
+++ b/sw/source/core/layout/anchoredobject.cxx
@@ -0,0 +1,1062 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+#include <anchoredobject.hxx>
+#include <pam.hxx>
+#include <frame.hxx>
+#include <txtfrm.hxx>
+#include <frmfmt.hxx>
+#include <fmtanchr.hxx>
+#include <fmtornt.hxx>
+// --> #i28701#
+#include <doc.hxx>
+#include <fmtsrnd.hxx>
+#include <svx/svdobj.hxx>
+#include <dcontact.hxx>
+#include <editeng/ulspitem.hxx>
+#include <editeng/lrspitem.hxx>
+#include <sortedobjs.hxx>
+#include <pagefrm.hxx>
+// <--
+#include <frmatr.hxx>
+// --> #i3317#
+#include <colfrm.hxx>
+// <--
+// --> #i35911#
+#include <layouter.hxx>
+
+
+using namespace ::com::sun::star;
+
+
+// <--
+// ============================================================================
+// --> #i28701# -
+// implementation of helper class <SwObjPositioningInProgress>
+// ============================================================================
+SwObjPositioningInProgress::SwObjPositioningInProgress( SdrObject& _rSdrObj ) :
+ mpAnchoredObj( 0L ),
+ // --> #i52904#
+ mbOldObjPositioningInProgress( false )
+ // <--
+{
+ mpAnchoredObj = ::GetUserCall( &_rSdrObj )->GetAnchoredObj( &_rSdrObj );
+ // --> #i52904#
+ mbOldObjPositioningInProgress = mpAnchoredObj->IsPositioningInProgress();
+ // <--
+ mpAnchoredObj->SetPositioningInProgress( true );
+}
+SwObjPositioningInProgress::SwObjPositioningInProgress( SwAnchoredObject& _rAnchoredObj ) :
+ mpAnchoredObj( &_rAnchoredObj ),
+ // --> #i52904#
+ mbOldObjPositioningInProgress( false )
+ // <--
+{
+ // --> #i52904#
+ mbOldObjPositioningInProgress = mpAnchoredObj->IsPositioningInProgress();
+ // <--
+ mpAnchoredObj->SetPositioningInProgress( true );
+}
+
+SwObjPositioningInProgress::~SwObjPositioningInProgress()
+{
+ if ( mpAnchoredObj )
+ {
+ // --> #i52904#
+ mpAnchoredObj->SetPositioningInProgress( mbOldObjPositioningInProgress );
+ // <--
+ }
+}
+
+// ============================================================================
+
+TYPEINIT0(SwAnchoredObject);
+
+SwAnchoredObject::SwAnchoredObject() :
+ mpDrawObj( 0L ),
+ mpAnchorFrm( 0L ),
+ // --> #i28701#
+ mpPageFrm( 0L ),
+ // <--
+ maRelPos(),
+ maLastCharRect(),
+ mnLastTopOfLine( 0L ),
+ mpVertPosOrientFrm( 0L ),
+ // --> #i28701#
+ mbPositioningInProgress( false ),
+ mbConsiderForTextWrap( false ),
+ mbPositionLocked( false ),
+ // --> #i40147#
+ mbKeepPositionLockedForSection( false ),
+ // <--
+ mbRestartLayoutProcess( false ),
+ // <--
+ // --> #i35911#
+ mbClearedEnvironment( false ),
+ // <--
+ // --> #i3317#
+ mbTmpConsiderWrapInfluence( false ),
+ // <--
+ // --> #i68520#
+ maObjRectWithSpaces(),
+ mbObjRectWithSpacesValid( false ),
+ maLastObjRect()
+ // <--
+{
+}
+
+SwAnchoredObject::~SwAnchoredObject()
+{
+}
+
+// =============================================================================
+// accessors for member <mpDrawObj>
+// =============================================================================
+void SwAnchoredObject::SetDrawObj( SdrObject& _rDrawObj )
+{
+ mpDrawObj = &_rDrawObj;
+}
+
+const SdrObject* SwAnchoredObject::GetDrawObj() const
+{
+ return mpDrawObj;
+}
+
+SdrObject* SwAnchoredObject::DrawObj()
+{
+ return mpDrawObj;
+}
+
+// =============================================================================
+// accessors for member <mpAnchorFrm>
+// =============================================================================
+const SwFrm* SwAnchoredObject::GetAnchorFrm() const
+{
+ return mpAnchorFrm;
+}
+
+SwFrm* SwAnchoredObject::AnchorFrm()
+{
+ return mpAnchorFrm;
+}
+
+void SwAnchoredObject::ChgAnchorFrm( SwFrm* _pNewAnchorFrm )
+{
+ mpAnchorFrm = _pNewAnchorFrm;
+
+ if ( mpAnchorFrm )
+ {
+ ObjectAttachedToAnchorFrame();
+ }
+}
+
+/** determine anchor frame containing the anchor position
+
+ #i26945#
+ the anchor frame, which is determined, is <mpAnchorFrm>
+ for an at-page, at-frame or at-paragraph anchored object
+ and the anchor character frame for an at-character and as-character
+ anchored object.
+
+ @author OD
+*/
+SwFrm* SwAnchoredObject::GetAnchorFrmContainingAnchPos()
+{
+ SwFrm* pAnchorFrmContainingAnchPos = FindAnchorCharFrm();
+ if ( !pAnchorFrmContainingAnchPos )
+ {
+ pAnchorFrmContainingAnchPos = AnchorFrm();
+ }
+
+ return pAnchorFrmContainingAnchPos;
+}
+
+// =============================================================================
+// #i28701# accessors for member <mpPageFrm>
+// =============================================================================
+SwPageFrm* SwAnchoredObject::GetPageFrm()
+{
+ return mpPageFrm;
+}
+
+const SwPageFrm* SwAnchoredObject::GetPageFrm() const
+{
+ return mpPageFrm;
+}
+
+void SwAnchoredObject::SetPageFrm( SwPageFrm* _pNewPageFrm )
+{
+ if ( mpPageFrm != _pNewPageFrm )
+ {
+ // clear member, which denotes the layout frame at which the vertical
+ // position is oriented at, if it doesn't fit to the new page frame.
+ if ( GetVertPosOrientFrm() &&
+ ( !_pNewPageFrm ||
+ _pNewPageFrm != GetVertPosOrientFrm()->FindPageFrm() ) )
+ {
+ ClearVertPosOrientFrm();
+ }
+
+ // assign new page frame
+ mpPageFrm = _pNewPageFrm;
+ }
+}
+
+// =============================================================================
+// accessors for member <maLastCharRect>
+// =============================================================================
+const SwRect& SwAnchoredObject::GetLastCharRect() const
+{
+ return maLastCharRect;
+}
+
+SwTwips SwAnchoredObject::GetRelCharX( const SwFrm* pFrm ) const
+{
+ return maLastCharRect.Left() - pFrm->Frm().Left();
+}
+
+SwTwips SwAnchoredObject::GetRelCharY( const SwFrm* pFrm ) const
+{
+ return maLastCharRect.Bottom() - pFrm->Frm().Top();
+}
+
+void SwAnchoredObject::AddLastCharY( long nDiff )
+{
+ maLastCharRect.Pos().Y() += nDiff;
+}
+
+void SwAnchoredObject::ResetLastCharRectHeight()
+{
+ maLastCharRect.Height( 0 );
+}
+// =============================================================================
+// accessors for member <mpVertPosOrientFrm>
+// =============================================================================
+void SwAnchoredObject::SetVertPosOrientFrm( const SwLayoutFrm& _rVertPosOrientFrm )
+{
+ mpVertPosOrientFrm = &_rVertPosOrientFrm;
+
+ // --> OD 2004-07-02 #i28701# - take over functionality of deleted method
+ // <SwFlyAtCntFrm::AssertPage()>: assure for at-paragraph and at-character
+ // an anchored object, that it is registered at the correct page frame
+ RegisterAtCorrectPage();
+}
+
+// =============================================================================
+// accessors for member <mnLastTopOfLine>
+// =============================================================================
+SwTwips SwAnchoredObject::GetLastTopOfLine() const
+{
+ return mnLastTopOfLine;
+}
+
+// #i28701# - follow-up of #i22341#
+void SwAnchoredObject::AddLastTopOfLineY( SwTwips _nDiff )
+{
+ mnLastTopOfLine += _nDiff;
+}
+
+/** check anchor character rectangle and top of line
+
+ #i26791
+ For to-character anchored Writer fly frames the members <maLastCharRect>
+ and <maLastTopOfLine> are updated. These are checked for change and
+ depending on the applied positioning, it's decided, if the Writer fly
+ frame has to be invalidated.
+
+ add parameter <_bCheckForParaPorInf>, default value <true>
+
+ @author OD
+*/
+void SwAnchoredObject::CheckCharRectAndTopOfLine(
+ const bool _bCheckForParaPorInf )
+{
+ if ( GetAnchorFrm() &&
+ GetAnchorFrm()->IsTxtFrm() )
+ {
+ const SwFmtAnchor& rAnch = GetFrmFmt().GetAnchor();
+ if ( (rAnch.GetAnchorId() == FLY_AT_CHAR) &&
+ rAnch.GetCntntAnchor() )
+ {
+ // --> if requested, assure that anchor frame,
+ // which contains the anchor character, has a paragraph portion information.
+ // The paragraph portion information is needed to determine the
+ // anchor character rectangle respectively the top of the line.
+ // Thus, a format of this frame is avoided to determine the
+ // paragraph portion information.
+ // --> #i26945# - use new method <FindAnchorCharFrm()>
+ const SwTxtFrm& aAnchorCharFrm = *(FindAnchorCharFrm());
+ // <--
+ if ( !_bCheckForParaPorInf || aAnchorCharFrm.HasPara() )
+ {
+ _CheckCharRect( rAnch, aAnchorCharFrm );
+ _CheckTopOfLine( rAnch, aAnchorCharFrm );
+ }
+ // <--
+ }
+ }
+}
+
+/** check anchor character rectangle
+
+ #i22341#
+ helper method for method <CheckCharRectAndTopOfLine()>
+ For to-character anchored Writer fly frames the member <maLastCharRect>
+ is updated. This is checked for change and depending on the applied
+ positioning, it's decided, if the Writer fly frame has to be invalidated.
+
+ improvement - add second parameter <_rAnchorCharFrm>
+
+ @author OD
+*/
+void SwAnchoredObject::_CheckCharRect( const SwFmtAnchor& _rAnch,
+ const SwTxtFrm& _rAnchorCharFrm )
+{
+ // determine rectangle of anchor character. If not exist, abort operation
+ SwRect aCharRect;
+ if ( !_rAnchorCharFrm.GetAutoPos( aCharRect, *_rAnch.GetCntntAnchor() ) )
+ {
+ return;
+ }
+ // check, if anchor character rectangle has changed
+ if ( aCharRect != maLastCharRect )
+ {
+ // check positioning and alignment for invalidation of position
+ {
+ SWRECTFN( (&_rAnchorCharFrm) );
+ // determine positioning and alignment
+ SwFmtVertOrient aVert( GetFrmFmt().GetVertOrient() );
+ SwFmtHoriOrient aHori( GetFrmFmt().GetHoriOrient() );
+ // check for anchor character rectangle changes for certain
+ // positionings and alignments
+ // add condition to invalidate position,
+ // if vertical aligned at frame/page area and vertical position
+ // of anchor character has changed.
+ const sal_Int16 eVertRelOrient = aVert.GetRelationOrient();
+ if ( ( aHori.GetRelationOrient() == text::RelOrientation::CHAR &&
+ (aCharRect.*fnRect->fnGetLeft)() !=
+ (maLastCharRect.*fnRect->fnGetLeft)() ) ||
+ ( eVertRelOrient == text::RelOrientation::CHAR &&
+ ( (aCharRect.*fnRect->fnGetTop)() !=
+ (maLastCharRect.*fnRect->fnGetTop)() ||
+ (aCharRect.*fnRect->fnGetHeight)() !=
+ (maLastCharRect.*fnRect->fnGetHeight)() ) ) ||
+ ( ( ( eVertRelOrient == text::RelOrientation::FRAME ) ||
+ ( eVertRelOrient == text::RelOrientation::PRINT_AREA ) ||
+ ( eVertRelOrient == text::RelOrientation::PAGE_FRAME ) ||
+ ( eVertRelOrient == text::RelOrientation::PAGE_PRINT_AREA ) ) &&
+ ( (aCharRect.*fnRect->fnGetTop)() !=
+ (maLastCharRect.*fnRect->fnGetTop)() ) ) )
+ {
+ // --> #i26945#, #i35911# - unlock position of
+ // anchored object, if it isn't registered at the page,
+ // where its anchor character frame is on.
+ if ( GetPageFrm() != _rAnchorCharFrm.FindPageFrm() )
+ {
+ UnlockPosition();
+ }
+ // <--
+ InvalidateObjPos();
+ }
+ }
+ // keep new anchor character rectangle
+ maLastCharRect = aCharRect;
+ }
+}
+
+/** check top of line
+
+ #i22341#
+ helper method for method <CheckCharRectAndTopOfLine()>
+ For to-character anchored Writer fly frames the member <mnLastTopOfLine>
+ is updated. This is checked for change and depending on the applied
+ positioning, it's decided, if the Writer fly frame has to be invalidated.
+
+ improvement - add second parameter <_rAnchorCharFrm>
+
+ @author OD
+*/
+void SwAnchoredObject::_CheckTopOfLine( const SwFmtAnchor& _rAnch,
+ const SwTxtFrm& _rAnchorCharFrm )
+{
+ SwTwips nTopOfLine = 0L;
+ if ( _rAnchorCharFrm.GetTopOfLine( nTopOfLine, *_rAnch.GetCntntAnchor() ) )
+ {
+ if ( nTopOfLine != mnLastTopOfLine )
+ {
+ // check alignment for invalidation of position
+ if ( GetFrmFmt().GetVertOrient().GetRelationOrient() == text::RelOrientation::TEXT_LINE )
+ {
+ // --> #i26945#, #i35911# - unlock position of
+ // anchored object, if it isn't registered at the page,
+ // where its anchor character frame is on.
+ if ( GetPageFrm() != _rAnchorCharFrm.FindPageFrm() )
+ {
+ UnlockPosition();
+ }
+ // <--
+ InvalidateObjPos();
+ }
+ // keep new top of line value
+ mnLastTopOfLine = nTopOfLine;
+ }
+ }
+}
+
+void SwAnchoredObject::ClearCharRectAndTopOfLine()
+{
+ maLastCharRect.Clear();
+ mnLastTopOfLine = 0;
+}
+
+const Point SwAnchoredObject::GetCurrRelPos() const
+{
+ return maRelPos;
+}
+void SwAnchoredObject::SetCurrRelPos( Point _aRelPos )
+{
+ maRelPos = _aRelPos;
+}
+
+void SwAnchoredObject::ObjectAttachedToAnchorFrame()
+{
+ // default behaviour:
+ // update layout direction, the anchored object is assigned to
+ UpdateLayoutDir();
+}
+
+/** method update layout direction the layout direction, the anchored
+ object is in
+
+ #i31698#
+ method has typically to be called, if the anchored object gets its
+ anchor frame assigned.
+
+ @author OD
+*/
+void SwAnchoredObject::UpdateLayoutDir()
+{
+ SwFrmFmt::tLayoutDir nLayoutDir = SwFrmFmt::HORI_L2R;
+ const SwFrm* pAnchorFrm = GetAnchorFrm();
+ if ( pAnchorFrm )
+ {
+ const bool bVert = pAnchorFrm->IsVertical();
+ const bool bR2L = pAnchorFrm->IsRightToLeft();
+ if ( bVert )
+ {
+ nLayoutDir = SwFrmFmt::VERT_R2L;
+ }
+ else if ( bR2L )
+ {
+ nLayoutDir = SwFrmFmt::HORI_R2L;
+ }
+ }
+ GetFrmFmt().SetLayoutDir( nLayoutDir );
+}
+
+/** method to perform necessary invalidations for the positioning of
+ objects, for whose the wrapping style influence has to be considered
+ on the object positioning.
+
+ #i28701#
+
+ @author OD
+*/
+void SwAnchoredObject::InvalidateObjPosForConsiderWrapInfluence(
+ const bool _bNotifyBackgrd )
+{
+ if ( ConsiderObjWrapInfluenceOnObjPos() )
+ {
+ // indicate that object has not to be considered for text wrap
+ SetConsiderForTextWrap( false );
+ // unlock position
+ UnlockPosition();
+ // invalidate position
+ InvalidateObjPos();
+ // invalidate 'background', if requested
+ if ( _bNotifyBackgrd )
+ {
+ NotifyBackground( GetPageFrm(), GetObjRectWithSpaces(), PREP_FLY_LEAVE );
+ }
+ }
+}
+
+/** method to determine, if wrapping style influence of the anchored
+ object has to be considered on the object positioning
+
+ #i28701#
+ Note: result of this method also decides, if the booleans for the
+ layout process are of relevance.
+
+ @author OD
+*/
+bool SwAnchoredObject::ConsiderObjWrapInfluenceOnObjPos() const
+{
+ bool bRet( false );
+
+ const SwFrmFmt& rObjFmt = GetFrmFmt();
+
+ // --> #i3317# - add condition <IsTmpConsiderWrapInfluence()>
+ // --> #i55204#
+ // - correction: wrapping style influence has been considered, if condition
+ // <IsTmpConsiderWrapInfluence()> is hold, regardless of its anchor type
+ // or its wrapping style.
+ if ( IsTmpConsiderWrapInfluence() )
+ {
+ bRet = true;
+ }
+ else if ( rObjFmt.getIDocumentSettingAccess()->get(IDocumentSettingAccess::CONSIDER_WRAP_ON_OBJECT_POSITION) )
+ // <--
+ {
+ const SwFmtAnchor& rAnchor = rObjFmt.GetAnchor();
+ if ( ((rAnchor.GetAnchorId() == FLY_AT_CHAR) ||
+ (rAnchor.GetAnchorId() == FLY_AT_PARA)) &&
+ rObjFmt.GetSurround().GetSurround() != SURROUND_THROUGHT )
+ {
+ // --> #i34520# - text also wraps around anchored
+ // objects in the layer Hell - see the text formatting.
+ // Thus, it hasn't to be checked here.
+ bRet = true;
+ // <--
+ }
+ }
+
+ return bRet;
+}
+
+/** method to determine, if other anchored objects, also attached at
+ to the anchor frame, have to consider its wrap influence.
+
+ // --> #i43255#
+
+ @author OD
+*/
+bool SwAnchoredObject::ConsiderObjWrapInfluenceOfOtherObjs() const
+{
+ bool bRet( false );
+
+ const SwSortedObjs* pObjs = GetAnchorFrm()->GetDrawObjs();
+ if ( pObjs->Count() > 1 )
+ {
+ sal_uInt32 i = 0;
+ for ( ; i < pObjs->Count(); ++i )
+ {
+ SwAnchoredObject* pAnchoredObj = (*pObjs)[i];
+ if ( pAnchoredObj != this &&
+ pAnchoredObj->ConsiderObjWrapInfluenceOnObjPos() )
+ {
+ bRet = true;
+ break;
+ }
+ }
+ }
+
+ return bRet;
+}
+
+// =============================================================================
+// --> #i28701# - accessors to booleans for layout process
+// =============================================================================
+bool SwAnchoredObject::ConsiderForTextWrap() const
+{
+ if ( ConsiderObjWrapInfluenceOnObjPos() )
+ return mbConsiderForTextWrap;
+ else
+ return true;
+}
+
+void SwAnchoredObject::SetConsiderForTextWrap( const bool _bConsiderForTextWrap )
+{
+ mbConsiderForTextWrap = _bConsiderForTextWrap;
+}
+
+bool SwAnchoredObject::PositionLocked() const
+{
+ if ( ConsiderObjWrapInfluenceOnObjPos() )
+ return mbPositionLocked;
+ else
+ return false;
+}
+
+bool SwAnchoredObject::RestartLayoutProcess() const
+{
+ if ( ConsiderObjWrapInfluenceOnObjPos() )
+ return mbRestartLayoutProcess;
+ else
+ return false;
+}
+
+void SwAnchoredObject::SetRestartLayoutProcess( const bool _bRestartLayoutProcess )
+{
+ mbRestartLayoutProcess = _bRestartLayoutProcess;
+}
+
+// --> #i35911#
+bool SwAnchoredObject::ClearedEnvironment() const
+{
+ if ( ConsiderObjWrapInfluenceOnObjPos() )
+ return mbClearedEnvironment;
+ else
+ return false;
+}
+void SwAnchoredObject::SetClearedEnvironment( const bool _bClearedEnvironment )
+{
+ mbClearedEnvironment = _bClearedEnvironment;
+}
+// <--
+
+/** method to determine, if due to anchored object size and wrapping
+ style, its layout environment is cleared.
+
+ #i35911#
+
+ @author OD
+*/
+bool SwAnchoredObject::HasClearedEnvironment() const
+{
+ bool bHasClearedEnvironment( false );
+
+ // --> #i43913# - layout frame, vertical position is orient at, has to be set.
+ OSL_ENSURE( GetVertPosOrientFrm(),
+ "<SwAnchoredObject::HasClearedEnvironment()> - layout frame missing, at which the vertical position is oriented at." );
+ if ( GetVertPosOrientFrm() &&
+ GetAnchorFrm()->IsTxtFrm() &&
+ !static_cast<const SwTxtFrm*>(GetAnchorFrm())->IsFollow() &&
+ static_cast<const SwTxtFrm*>(GetAnchorFrm())->FindPageFrm()->GetPhyPageNum() >=
+ GetPageFrm()->GetPhyPageNum() )
+ // <--
+ {
+ const SwFrm* pTmpFrm = GetVertPosOrientFrm()->Lower();
+ while ( pTmpFrm && pTmpFrm->IsLayoutFrm() && !pTmpFrm->IsTabFrm() )
+ {
+ pTmpFrm = static_cast<const SwLayoutFrm*>(pTmpFrm)->Lower();
+ }
+ if ( !pTmpFrm )
+ {
+ bHasClearedEnvironment = true;
+ }
+ else if ( pTmpFrm->IsTxtFrm() && !pTmpFrm->GetNext() )
+ {
+ const SwTxtFrm* pTmpTxtFrm = static_cast<const SwTxtFrm*>(pTmpFrm);
+ if ( pTmpTxtFrm->IsUndersized() ||
+ ( pTmpTxtFrm->GetFollow() &&
+ pTmpTxtFrm->GetFollow()->GetOfst() == 0 ) )
+ {
+ bHasClearedEnvironment = true;
+ }
+ }
+ }
+
+ return bHasClearedEnvironment;
+}
+
+/** method to add spacing to object area
+
+ #i28701#
+ #i68520# - return constant reference and use cache
+
+ @author OD
+*/
+const SwRect& SwAnchoredObject::GetObjRectWithSpaces() const
+{
+ if ( mbObjRectWithSpacesValid &&
+ maLastObjRect != GetObjRect() )
+ {
+ OSL_FAIL( "<SwAnchoredObject::GetObjRectWithSpaces> - cache for object rectangle inclusive spaces marked as valid, but it couldn't be. Missing invalidation of cache. Please inform OD." );
+ InvalidateObjRectWithSpaces();
+ }
+ if ( !mbObjRectWithSpacesValid )
+ {
+ // --> #i70122# - correction:
+ // use bounding rectangle of anchored objects.
+// maObjRectWithSpaces = GetObjRect();
+ maObjRectWithSpaces = GetObjBoundRect();
+ // <--
+ const SwFrmFmt& rFmt = GetFrmFmt();
+ const SvxULSpaceItem& rUL = rFmt.GetULSpace();
+ const SvxLRSpaceItem& rLR = rFmt.GetLRSpace();
+ {
+ maObjRectWithSpaces.Top ( Max( maObjRectWithSpaces.Top() - long(rUL.GetUpper()), 0L ));
+ maObjRectWithSpaces.Left( Max( maObjRectWithSpaces.Left()- long(rLR.GetLeft()), 0L ));
+ maObjRectWithSpaces.SSize().Height() += rUL.GetLower();
+ maObjRectWithSpaces.SSize().Width() += rLR.GetRight();
+ }
+
+ mbObjRectWithSpacesValid = true;
+ maLastObjRect = GetObjRect();
+ }
+
+ return maObjRectWithSpaces;
+}
+
+// --> #i68520#
+void SwAnchoredObject::SetObjTop( const SwTwips _nTop)
+{
+ const bool bTopChanged( _SetObjTop( _nTop ) );
+ if ( bTopChanged )
+ {
+ mbObjRectWithSpacesValid = false;
+ }
+}
+
+void SwAnchoredObject::SetObjLeft( const SwTwips _nLeft)
+{
+ const bool bLeftChanged( _SetObjLeft( _nLeft ) );
+ if ( bLeftChanged )
+ {
+ mbObjRectWithSpacesValid = false;
+ }
+}
+// <--
+
+/** method to update anchored object in the <SwSortedObjs> lists
+
+ #i28701#
+ If document compatibility option 'Consider wrapping style influence
+ on object positioning' is ON, additionally all anchored objects
+ at the anchor frame and all following anchored objects on the page
+ frame are invalidated.
+
+ @author OD
+*/
+void SwAnchoredObject::UpdateObjInSortedList()
+{
+ if ( GetAnchorFrm() )
+ {
+ if ( GetFrmFmt().getIDocumentSettingAccess()->get(IDocumentSettingAccess::CONSIDER_WRAP_ON_OBJECT_POSITION) )
+ {
+ // invalidate position of all anchored objects at anchor frame
+ if ( GetAnchorFrm()->GetDrawObjs() )
+ {
+ const SwSortedObjs* pObjs = GetAnchorFrm()->GetDrawObjs();
+ // determine start index
+ sal_uInt32 i = 0;
+ for ( ; i < pObjs->Count(); ++i )
+ {
+ SwAnchoredObject* pAnchoredObj = (*pObjs)[i];
+ if ( pAnchoredObj->ConsiderObjWrapInfluenceOnObjPos() )
+ pAnchoredObj->InvalidateObjPosForConsiderWrapInfluence( true );
+ else
+ pAnchoredObj->InvalidateObjPos();
+ }
+ }
+ // invalidate all following anchored objects on the page frame
+ if ( GetPageFrm() && GetPageFrm()->GetSortedObjs() )
+ {
+ const SwSortedObjs* pObjs = GetPageFrm()->GetSortedObjs();
+ // determine start index
+ sal_uInt32 i = pObjs->ListPosOf( *this ) + 1;
+ for ( ; i < pObjs->Count(); ++i )
+ {
+ SwAnchoredObject* pAnchoredObj = (*pObjs)[i];
+ if ( pAnchoredObj->ConsiderObjWrapInfluenceOnObjPos() )
+ pAnchoredObj->InvalidateObjPosForConsiderWrapInfluence( true );
+ else
+ pAnchoredObj->InvalidateObjPos();
+ }
+ }
+ }
+ // update its position in the sorted object list of its anchor frame
+ AnchorFrm()->GetDrawObjs()->Update( *this );
+ // update its position in the sorted object list of its page frame
+ // note: as-character anchored object aren't registered at a page frame
+ if ( GetFrmFmt().GetAnchor().GetAnchorId() != FLY_AS_CHAR )
+ {
+ GetPageFrm()->GetSortedObjs()->Update( *this );
+ }
+ }
+}
+
+/** method to determine, if invalidation of position is allowed
+
+ #i28701#
+
+ @author OD
+*/
+bool SwAnchoredObject::InvalidationOfPosAllowed() const
+{
+ // --> Check, if page frame layout is in progress,
+ // isn't needed, because of anchored object, whose are moved forward.
+ return !PositionLocked();
+ // <--
+}
+
+/** method to determine the page frame, on which the 'anchor' of
+ the given anchored object is.
+
+ #i28701#
+ #i33751#, #i34060#
+ Adjust meaning of method and thus its name: If the anchored object
+ or its anchor isn't correctly inserted in the layout, no page frame
+ can be found. Thus, the return type changed to be a pointer and can
+ be NULL.
+
+ @author OD
+*/
+SwPageFrm* SwAnchoredObject::FindPageFrmOfAnchor()
+{
+ SwPageFrm* pRetPageFrm = 0L;
+
+ // --> #i44339# - check, if anchor frame exists.
+ if ( mpAnchorFrm )
+ {
+ // --> #i26945# - use new method <GetAnchorFrmContainingAnchPos()>
+ pRetPageFrm = GetAnchorFrmContainingAnchPos()->FindPageFrm();
+ // <--
+ }
+
+ return pRetPageFrm;
+}
+
+/** get frame, which contains the anchor character, if the object
+ is anchored at-character or as-character.
+
+ #i26945#
+
+ @author OD
+
+ @return SwTxtFrm*
+ text frame containing the anchor character. It's NULL, if the object
+ isn't anchored at-character resp. as-character.
+*/
+SwTxtFrm* SwAnchoredObject::FindAnchorCharFrm()
+{
+ SwTxtFrm* pAnchorCharFrm( 0L );
+
+ // --> #i44339# - check, if anchor frame exists.
+ if ( mpAnchorFrm )
+ {
+ const SwFmtAnchor& rAnch = GetFrmFmt().GetAnchor();
+ if ((rAnch.GetAnchorId() == FLY_AT_CHAR) ||
+ (rAnch.GetAnchorId() == FLY_AS_CHAR))
+ {
+ pAnchorCharFrm = &(static_cast<SwTxtFrm*>(AnchorFrm())->
+ GetFrmAtOfst( rAnch.GetCntntAnchor()->nContent.GetIndex() ));
+ }
+ }
+ // <--
+
+ return pAnchorCharFrm;
+}
+
+/** method to determine, if a format on the anchored object is possible
+
+ #i28701#
+ A format is possible, if anchored object is in an invisible layer.
+ Note: method is virtual to refine the conditions for the sub-classes.
+
+ @author OD
+*/
+bool SwAnchoredObject::IsFormatPossible() const
+{
+ return GetFrmFmt().GetDoc()->IsVisibleLayerId( GetDrawObj()->GetLayer() );
+}
+
+// --> #i3317#
+void SwAnchoredObject::SetTmpConsiderWrapInfluence( const bool _bTmpConsiderWrapInfluence )
+{
+ mbTmpConsiderWrapInfluence = _bTmpConsiderWrapInfluence;
+ // --> #i35911#
+ if ( mbTmpConsiderWrapInfluence )
+ {
+ SwLayouter::InsertObjForTmpConsiderWrapInfluence( *(GetFrmFmt().GetDoc()),
+ *this );
+ }
+ // <--
+}
+
+bool SwAnchoredObject::IsTmpConsiderWrapInfluence() const
+{
+ return mbTmpConsiderWrapInfluence;
+}
+// <--
+
+void SwAnchoredObject::SetTmpConsiderWrapInfluenceOfOtherObjs( const bool bTmpConsiderWrapInfluence )
+{
+ const SwSortedObjs* pObjs = GetAnchorFrm()->GetDrawObjs();
+ if ( pObjs->Count() > 1 )
+ {
+ sal_uInt32 i = 0;
+ for ( ; i < pObjs->Count(); ++i )
+ {
+ SwAnchoredObject* pAnchoredObj = (*pObjs)[i];
+ if ( pAnchoredObj != this )
+ {
+ pAnchoredObj->SetTmpConsiderWrapInfluence( bTmpConsiderWrapInfluence );
+ }
+ }
+ }
+}
+
+/** method to determine, if the anchored object is overlapping with a
+ previous column
+
+ #i3317#
+ overlapping with a previous column means, that the object overlaps
+ with a column, which is a previous one of the column its anchor
+ frame is in.
+ Only applied for at-paragraph and at-character anchored objects.
+
+ @author OD
+*/
+bool SwAnchoredObject::OverlapsPrevColumn() const
+{
+ bool bOverlapsPrevColumn( false );
+
+ if ( mpAnchorFrm && mpAnchorFrm->IsTxtFrm() )
+ {
+ const SwFrm* pColFrm = mpAnchorFrm->FindColFrm();
+ if ( pColFrm && pColFrm->GetPrev() )
+ {
+ const SwFrm* pTmpColFrm = pColFrm->GetPrev();
+ SwRect aChkRect;
+ while ( pTmpColFrm )
+ {
+ aChkRect.Union( pTmpColFrm->Frm() );
+ pTmpColFrm = pTmpColFrm->GetPrev();
+ }
+ bOverlapsPrevColumn = GetObjRect().IsOver( aChkRect );
+ }
+ }
+
+ return bOverlapsPrevColumn;
+}
+
+/** method to determine position of anchored object relative to
+ anchor frame
+
+ #i30669#
+ Usage: Needed layout information for WW8 export
+
+ @author OD
+*/
+Point SwAnchoredObject::GetRelPosToAnchorFrm() const
+{
+ Point aRelPos;
+
+ OSL_ENSURE( GetAnchorFrm(),
+ "<SwAnchoredObject::GetRelPosToAnchorFrm()> - missing anchor frame." );
+ aRelPos = GetObjRect().Pos();
+ aRelPos -= GetAnchorFrm()->Frm().Pos();
+
+ return aRelPos;
+}
+
+/** method to determine position of anchored object relative to
+ page frame
+
+ #i30669#
+ Usage: Needed layout information for WW8 export
+ #i33818# - add parameters <_bFollowTextFlow> and
+ <_obRelToTableCell>
+ If <_bFollowTextFlow> is set and object is anchored inside table,
+ the position relative to the table cell is determined. Output
+ parameter <_obRelToTableCell> reflects this situation
+
+ @author OD
+*/
+Point SwAnchoredObject::GetRelPosToPageFrm( const bool _bFollowTextFlow,
+ bool& _obRelToTableCell ) const
+{
+ Point aRelPos;
+ _obRelToTableCell = false;
+
+ OSL_ENSURE( GetAnchorFrm(),
+ "<SwAnchoredObject::GetRelPosToPageFrm()> - missing anchor frame." );
+ OSL_ENSURE( GetAnchorFrm()->FindPageFrm(),
+ "<SwAnchoredObject::GetRelPosToPageFrm()> - missing page frame." );
+
+ aRelPos = GetObjRect().Pos();
+ // --> #i33818# - search for cell frame, if object has to
+ // follow the text flow.
+ const SwFrm* pFrm( 0L );
+ if ( _bFollowTextFlow && !GetAnchorFrm()->IsPageFrm() )
+ {
+ pFrm = GetAnchorFrm()->GetUpper();
+ while ( !pFrm->IsCellFrm() && !pFrm->IsPageFrm() )
+ {
+ pFrm = pFrm->GetUpper();
+ }
+ }
+ else
+ {
+ pFrm = GetAnchorFrm()->FindPageFrm();
+ }
+ if ( pFrm->IsCellFrm() )
+ {
+ aRelPos -= ( pFrm->Frm().Pos() + pFrm->Prt().Pos() );
+ _obRelToTableCell = true;
+ }
+ else
+ {
+ aRelPos -= pFrm->Frm().Pos();
+ }
+ // <--
+
+ return aRelPos;
+}
+
+/** method to determine position of anchored object relative to
+ anchor character
+
+ #i30669#
+ Usage: Needed layout information for WW8 export
+
+ @author OD
+*/
+Point SwAnchoredObject::GetRelPosToChar() const
+{
+ Point aRelPos;
+
+ aRelPos = GetObjRect().Pos();
+ aRelPos -= GetLastCharRect().Pos();
+
+ return aRelPos;
+}
+
+/** method to determine position of anchored object relative to
+ top of line
+
+ #i30669#
+ Usage: Needed layout information for WW8 export
+
+ @author OD
+*/
+Point SwAnchoredObject::GetRelPosToLine() const
+{
+ Point aRelPos;
+
+ aRelPos = GetObjRect().Pos();
+ aRelPos.Y() -= GetLastTopOfLine();
+
+ return aRelPos;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/layout/atrfrm.cxx b/sw/source/core/layout/atrfrm.cxx
new file mode 100644
index 000000000000..5d3c7924531e
--- /dev/null
+++ b/sw/source/core/layout/atrfrm.cxx
@@ -0,0 +1,3299 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+
+#include <hintids.hxx>
+#include <com/sun/star/text/RelOrientation.hpp>
+#include <com/sun/star/text/VertOrientation.hpp>
+#include <com/sun/star/text/HorizontalAdjust.hpp>
+#include <com/sun/star/text/DocumentStatistic.hpp>
+#include <com/sun/star/text/HoriOrientation.hpp>
+#include <com/sun/star/text/HoriOrientationFormat.hpp>
+#include <com/sun/star/text/NotePrintMode.hpp>
+#include <com/sun/star/text/SizeType.hpp>
+#include <com/sun/star/text/VertOrientationFormat.hpp>
+#include <com/sun/star/text/WrapTextMode.hpp>
+#include <com/sun/star/text/XTextFrame.hpp>
+#include <com/sun/star/text/TextContentAnchorType.hpp>
+#include <com/sun/star/text/InvalidTextContentException.hpp>
+#include <com/sun/star/container/XIndexContainer.hpp>
+#include <com/sun/star/text/TextGridMode.hpp>
+#include <com/sun/star/awt/Size.hpp>
+#include <svtools/unoimap.hxx>
+#include <svtools/unoevent.hxx>
+#include <basic/sbxvar.hxx>
+#include <svtools/imap.hxx>
+#include <svtools/imapobj.hxx>
+#include <editeng/ulspitem.hxx>
+#include <editeng/lrspitem.hxx>
+#include <svx/svdmodel.hxx>
+#include <svx/svdpage.hxx>
+#include <unosett.hxx>
+#include <unostyle.hxx>
+#include <fmtclds.hxx>
+#include <fmtornt.hxx>
+#include <fmthdft.hxx>
+#include <fmtpdsc.hxx>
+#include <fmtcntnt.hxx>
+#include <fmtfsize.hxx>
+#include <fmtfordr.hxx>
+#include <fmtsrnd.hxx>
+#include <fmtanchr.hxx>
+#include <fmtlsplt.hxx>
+#include <fmtrowsplt.hxx>
+#include <fmtftntx.hxx>
+#include <fmteiro.hxx>
+#include <fmturl.hxx>
+#include <fmtcnct.hxx>
+#include <node.hxx>
+#include <section.hxx>
+#include <fmtline.hxx>
+#include <tgrditem.hxx>
+#include <hfspacingitem.hxx>
+#include <doc.hxx>
+#include <IDocumentUndoRedo.hxx>
+#include <pagefrm.hxx>
+#include <rootfrm.hxx>
+#include <cntfrm.hxx>
+#include <crsrsh.hxx>
+#include <pam.hxx>
+#include <dflyobj.hxx>
+#include <dcontact.hxx>
+#include <flyfrm.hxx>
+#include <frmtool.hxx>
+#include <flyfrms.hxx>
+#include <pagedesc.hxx>
+#include <grfatr.hxx>
+#include <ndnotxt.hxx>
+#include <docary.hxx>
+#include <node2lay.hxx>
+#include <fmtclbl.hxx>
+#include <swunohelper.hxx>
+#include <unoframe.hxx>
+#include <unotextbodyhf.hxx>
+#include <SwStyleNameMapper.hxx>
+#include <editeng/brshitem.hxx>
+#include <svtools/grfmgr.hxx>
+#include <cmdid.h>
+#include <unomid.h>
+#include <comcore.hrc>
+#include <svx/svdundo.hxx> // #111827#
+#include <sortedobjs.hxx>
+#include <HandleAnchorNodeChg.hxx>
+#include <svl/cjkoptions.hxx>
+#include <switerator.hxx>
+#include <pagedeschint.hxx>
+
+using namespace ::com::sun::star;
+using ::rtl::OUString;
+
+SV_IMPL_PTRARR(SwColumns,SwColumn*)
+
+TYPEINIT1(SwFmtVertOrient, SfxPoolItem);
+TYPEINIT1(SwFmtHoriOrient, SfxPoolItem);
+TYPEINIT2(SwFmtHeader, SfxPoolItem, SwClient );
+TYPEINIT2(SwFmtFooter, SfxPoolItem, SwClient );
+TYPEINIT2(SwFmtPageDesc, SfxPoolItem, SwClient );
+TYPEINIT1_AUTOFACTORY(SwFmtLineNumber, SfxPoolItem);
+
+/* --------------------------------------------------
+ * Umwandlung fuer QueryValue
+ * --------------------------------------------------*/
+sal_Int16 lcl_RelToINT(sal_Int16 eRelation)
+{
+ sal_Int16 nRet = text::RelOrientation::FRAME;
+ switch(eRelation)
+ {
+ case text::RelOrientation::PRINT_AREA: nRet = text::RelOrientation::PRINT_AREA; break;
+ case text::RelOrientation::CHAR: nRet = text::RelOrientation::CHAR; break;
+ case text::RelOrientation::PAGE_LEFT: nRet = text::RelOrientation::PAGE_LEFT; break;
+ case text::RelOrientation::PAGE_RIGHT: nRet = text::RelOrientation::PAGE_RIGHT; break;
+ case text::RelOrientation::FRAME_LEFT: nRet = text::RelOrientation::FRAME_LEFT; break;
+ case text::RelOrientation::FRAME_RIGHT: nRet = text::RelOrientation::FRAME_RIGHT; break;
+ case text::RelOrientation::PAGE_FRAME: nRet = text::RelOrientation::PAGE_FRAME; break;
+ case text::RelOrientation::PAGE_PRINT_AREA: nRet = text::RelOrientation::PAGE_PRINT_AREA; break;
+ // OD 13.11.2003 #i22341#
+ case text::RelOrientation::TEXT_LINE: nRet = text::RelOrientation::TEXT_LINE; break;
+ default: break;
+ }
+ return nRet;
+}
+
+sal_Int16 lcl_IntToRelation(const uno::Any& rVal)
+{
+ sal_Int16 eRet = text::RelOrientation::FRAME;
+ sal_Int16 nVal = 0;
+ rVal >>= nVal;
+ switch(nVal)
+ {
+ case text::RelOrientation::PRINT_AREA: eRet = text::RelOrientation::PRINT_AREA ; break;
+ case text::RelOrientation::CHAR: eRet = text::RelOrientation::CHAR ; break;
+ case text::RelOrientation::PAGE_LEFT: eRet = text::RelOrientation::PAGE_LEFT ; break;
+ case text::RelOrientation::PAGE_RIGHT: eRet = text::RelOrientation::PAGE_RIGHT ; break;
+ case text::RelOrientation::FRAME_LEFT: eRet = text::RelOrientation::FRAME_LEFT ; break;
+ case text::RelOrientation::FRAME_RIGHT: eRet = text::RelOrientation::FRAME_RIGHT ; break;
+ case text::RelOrientation::PAGE_FRAME: eRet = text::RelOrientation::PAGE_FRAME ; break;
+ case text::RelOrientation::PAGE_PRINT_AREA: eRet = text::RelOrientation::PAGE_PRINT_AREA ; break;
+ // OD 13.11.2003 #i22341#
+ case text::RelOrientation::TEXT_LINE: eRet = text::RelOrientation::TEXT_LINE; break;
+ }
+ return eRet;
+}
+
+void DelHFFormat( SwClient *pToRemove, SwFrmFmt *pFmt )
+{
+ //Wenn der Client der letzte ist der das Format benutzt, so muss dieses
+ //vernichtet werden. Zuvor muss jedoch ggf. die Inhaltssection vernichtet
+ //werden.
+ SwDoc* pDoc = pFmt->GetDoc();
+ pFmt->Remove( pToRemove );
+ if( pDoc->IsInDtor() )
+ {
+ delete pFmt;
+ return;
+ }
+
+ //Nur noch Frms angemeldet?
+ sal_Bool bDel = sal_True;
+ {
+ // Klammer, weil im DTOR SwClientIter das Flag bTreeChg zurueck
+ // gesetzt wird. Unguenstig, wenn das Format vorher zerstoert wird.
+ SwClientIter aIter( *pFmt ); // TODO
+ SwClient *pLast = aIter.GoStart();
+ if( pLast )
+ do {
+ bDel = pLast->IsA( TYPE(SwFrm) )
+ || SwXHeadFootText::IsXHeadFootText(pLast);
+ } while( bDel && 0 != ( pLast = aIter++ ));
+ }
+
+ if ( bDel )
+ {
+ //Wenn in einem der Nodes noch ein Crsr angemeldet ist, muss das
+ //ParkCrsr einer (beliebigen) Shell gerufen werden.
+ SwFmtCntnt& rCnt = (SwFmtCntnt&)pFmt->GetCntnt();
+ if ( rCnt.GetCntntIdx() )
+ {
+ SwNode *pNode = 0;
+ {
+ // --> OD 2008-10-07 #i92993#
+ // Begin with start node of page header/footer to assure that
+ // complete content is checked for cursors and the complete content
+ // is deleted on below made method call <pDoc->DeleteSection(pNode)>
+// SwNodeIndex aIdx( *rCnt.GetCntntIdx(), 1 );
+ SwNodeIndex aIdx( *rCnt.GetCntntIdx(), 0 );
+ // <--
+ //Wenn in einem der Nodes noch ein Crsr angemeldet ist, muss das
+ //ParkCrsr einer (beliebigen) Shell gerufen werden.
+ pNode = & aIdx.GetNode();
+ sal_uInt32 nEnd = pNode->EndOfSectionIndex();
+ while ( aIdx < nEnd )
+ {
+ if ( pNode->IsCntntNode() &&
+ ((SwCntntNode*)pNode)->GetDepends() )
+ {
+ SwCrsrShell *pShell = SwIterator<SwCrsrShell,SwCntntNode>::FirstElement( *(SwCntntNode*)pNode );
+ if( pShell )
+ {
+ pShell->ParkCrsr( aIdx );
+ aIdx = nEnd-1;
+ }
+ }
+ aIdx++;
+ pNode = & aIdx.GetNode();
+ }
+ }
+ rCnt.SetNewCntntIdx( (const SwNodeIndex*)0 );
+
+ // beim Loeschen von Header/Footer-Formaten IMMER das Undo
+ // abschalten! (Bug 31069)
+ ::sw::UndoGuard const undoGuard(pDoc->GetIDocumentUndoRedo());
+
+ OSL_ENSURE( pNode, "Ein grosses Problem." );
+ pDoc->DeleteSection( pNode );
+ }
+ delete pFmt;
+ }
+}
+
+// class SwFmtFrmSize
+// Implementierung teilweise inline im hxx
+
+SwFmtFrmSize::SwFmtFrmSize( SwFrmSize eSize, SwTwips nWidth, SwTwips nHeight )
+ : SfxPoolItem( RES_FRM_SIZE ),
+ aSize( nWidth, nHeight ),
+ eFrmHeightType( eSize ),
+ eFrmWidthType( ATT_FIX_SIZE )
+{
+ nWidthPercent = nHeightPercent = 0;
+}
+
+SwFmtFrmSize& SwFmtFrmSize::operator=( const SwFmtFrmSize& rCpy )
+{
+ aSize = rCpy.GetSize();
+ eFrmHeightType = rCpy.GetHeightSizeType();
+ eFrmWidthType = rCpy.GetWidthSizeType();
+ nHeightPercent = rCpy.GetHeightPercent();
+ nWidthPercent = rCpy.GetWidthPercent();
+ return *this;
+}
+
+int SwFmtFrmSize::operator==( const SfxPoolItem& rAttr ) const
+{
+ OSL_ENSURE( SfxPoolItem::operator==( rAttr ), "keine gleichen Attribute" );
+ return( eFrmHeightType == ((SwFmtFrmSize&)rAttr).eFrmHeightType &&
+ eFrmWidthType == ((SwFmtFrmSize&)rAttr).eFrmWidthType &&
+ aSize == ((SwFmtFrmSize&)rAttr).GetSize()&&
+ nWidthPercent == ((SwFmtFrmSize&)rAttr).GetWidthPercent() &&
+ nHeightPercent == ((SwFmtFrmSize&)rAttr).GetHeightPercent() );
+}
+
+SfxPoolItem* SwFmtFrmSize::Clone( SfxItemPool* ) const
+{
+ return new SwFmtFrmSize( *this );
+}
+
+bool SwFmtFrmSize::QueryValue( uno::Any& rVal, sal_uInt8 nMemberId ) const
+{
+ // hier wird immer konvertiert!
+ nMemberId &= ~CONVERT_TWIPS;
+ switch ( nMemberId )
+ {
+ case MID_FRMSIZE_SIZE:
+ {
+ awt::Size aTmp;
+ aTmp.Height = TWIP_TO_MM100(aSize.Height());
+ aTmp.Width = TWIP_TO_MM100(aSize.Width());
+ rVal.setValue(&aTmp, ::getCppuType((const awt::Size*)0));
+ }
+ break;
+ case MID_FRMSIZE_REL_HEIGHT:
+ rVal <<= (sal_Int16)(GetHeightPercent() != 0xFF ? GetHeightPercent() : 0);
+ break;
+ case MID_FRMSIZE_REL_WIDTH:
+ rVal <<= (sal_Int16)(GetWidthPercent() != 0xFF ? GetWidthPercent() : 0);
+ break;
+ case MID_FRMSIZE_IS_SYNC_HEIGHT_TO_WIDTH:
+ {
+ sal_Bool bTmp = 0xFF == GetHeightPercent();
+ rVal.setValue(&bTmp, ::getBooleanCppuType());
+ }
+ break;
+ case MID_FRMSIZE_IS_SYNC_WIDTH_TO_HEIGHT:
+ {
+ sal_Bool bTmp = 0xFF == GetWidthPercent();
+ rVal.setValue(&bTmp, ::getBooleanCppuType());
+ }
+ break;
+ case MID_FRMSIZE_WIDTH :
+ rVal <<= (sal_Int32)TWIP_TO_MM100(aSize.Width());
+ break;
+ case MID_FRMSIZE_HEIGHT:
+ // #95848# returned size should never be zero.
+ // (there was a bug that allowed for setting height to 0.
+ // Thus there some documents existing with that not allowed
+ // attribut value which may cause problems on import.)
+ rVal <<= (sal_Int32)TWIP_TO_MM100(aSize.Height() < MINLAY ? MINLAY : aSize.Height() );
+ break;
+ case MID_FRMSIZE_SIZE_TYPE:
+ rVal <<= (sal_Int16)GetHeightSizeType();
+ break;
+ case MID_FRMSIZE_IS_AUTO_HEIGHT:
+ {
+ sal_Bool bTmp = ATT_FIX_SIZE != GetHeightSizeType();
+ rVal.setValue(&bTmp, ::getBooleanCppuType());
+ }
+ break;
+ case MID_FRMSIZE_WIDTH_TYPE:
+ rVal <<= (sal_Int16)GetWidthSizeType();
+ break;
+ }
+ return true;
+}
+
+bool SwFmtFrmSize::PutValue( const uno::Any& rVal, sal_uInt8 nMemberId )
+{
+ sal_Bool bConvert = 0 != (nMemberId&CONVERT_TWIPS);
+ nMemberId &= ~CONVERT_TWIPS;
+ bool bRet = true;
+ switch ( nMemberId )
+ {
+ case MID_FRMSIZE_SIZE:
+ {
+ awt::Size aVal;
+ if(!(rVal >>= aVal))
+ bRet = false;
+ else
+ {
+ Size aTmp(aVal.Width, aVal.Height);
+ if(bConvert)
+ {
+ aTmp.Height() = MM100_TO_TWIP(aTmp.Height());
+ aTmp.Width() = MM100_TO_TWIP(aTmp.Width());
+ }
+ if(aTmp.Height() && aTmp.Width())
+ aSize = aTmp;
+ else
+ bRet = false;
+ }
+ }
+ break;
+ case MID_FRMSIZE_REL_HEIGHT:
+ {
+ sal_Int16 nSet = 0;
+ rVal >>= nSet;
+ if(nSet >= 0 && nSet <= 0xfe)
+ SetHeightPercent((sal_uInt8)nSet);
+ else
+ bRet = false;
+ }
+ break;
+ case MID_FRMSIZE_REL_WIDTH:
+ {
+ sal_Int16 nSet = 0;
+ rVal >>= nSet;
+ if(nSet >= 0 && nSet <= 0xfe)
+ SetWidthPercent((sal_uInt8)nSet);
+ else
+ bRet = false;
+ }
+ break;
+ case MID_FRMSIZE_IS_SYNC_HEIGHT_TO_WIDTH:
+ {
+ sal_Bool bSet = *(sal_Bool*)rVal.getValue();
+ if(bSet)
+ SetHeightPercent(0xff);
+ else if( 0xff == GetHeightPercent() )
+ SetHeightPercent( 0 );
+ }
+ break;
+ case MID_FRMSIZE_IS_SYNC_WIDTH_TO_HEIGHT:
+ {
+ sal_Bool bSet = *(sal_Bool*)rVal.getValue();
+ if(bSet)
+ SetWidthPercent(0xff);
+ else if( 0xff == GetWidthPercent() )
+ SetWidthPercent(0);
+ }
+ break;
+ case MID_FRMSIZE_WIDTH :
+ {
+ sal_Int32 nWd = 0;
+ if(rVal >>= nWd)
+ {
+ if(bConvert)
+ nWd = MM100_TO_TWIP(nWd);
+ if(nWd < MINLAY)
+ nWd = MINLAY;
+ aSize.Width() = nWd;
+ }
+ else
+ bRet = sal_False;
+ }
+ break;
+ case MID_FRMSIZE_HEIGHT:
+ {
+ sal_Int32 nHg = 0;
+ if(rVal >>= nHg)
+ {
+ if(bConvert)
+ nHg = MM100_TO_TWIP(nHg);
+ if(nHg < MINLAY)
+ nHg = MINLAY;
+ aSize.Height() = nHg;
+ }
+ else
+ bRet = false;
+ }
+ break;
+ case MID_FRMSIZE_SIZE_TYPE:
+ {
+ sal_Int16 nType = 0;
+ if((rVal >>= nType) && nType >= 0 && nType <= ATT_MIN_SIZE )
+ {
+ SetHeightSizeType((SwFrmSize)nType);
+ }
+ else
+ bRet = false;
+ }
+ break;
+ case MID_FRMSIZE_IS_AUTO_HEIGHT:
+ {
+ sal_Bool bSet = *(sal_Bool*)rVal.getValue();
+ SetHeightSizeType(bSet ? ATT_VAR_SIZE : ATT_FIX_SIZE);
+ }
+ break;
+ case MID_FRMSIZE_WIDTH_TYPE:
+ {
+ sal_Int16 nType = 0;
+ if((rVal >>= nType) && nType >= 0 && nType <= ATT_MIN_SIZE )
+ {
+ SetWidthSizeType((SwFrmSize)nType);
+ }
+ else
+ bRet = false;
+ }
+ break;
+ default:
+ bRet = false;
+ }
+ return bRet;
+}
+
+// class SwFmtFillOrder
+// Implementierung teilweise inline im hxx
+
+SwFmtFillOrder::SwFmtFillOrder( SwFillOrder nFO )
+ : SfxEnumItem( RES_FILL_ORDER, sal_uInt16(nFO) )
+{}
+
+SfxPoolItem* SwFmtFillOrder::Clone( SfxItemPool* ) const
+{
+ return new SwFmtFillOrder( GetFillOrder() );
+}
+
+sal_uInt16 SwFmtFillOrder::GetValueCount() const
+{
+ return SW_FILL_ORDER_END - SW_FILL_ORDER_BEGIN;
+}
+
+// class SwFmtHeader
+// Implementierung teilweise inline im hxx
+
+SwFmtHeader::SwFmtHeader( SwFrmFmt *pHeaderFmt )
+ : SfxPoolItem( RES_HEADER ),
+ SwClient( pHeaderFmt ),
+ bActive( pHeaderFmt ? sal_True : sal_False )
+{
+}
+
+SwFmtHeader::SwFmtHeader( const SwFmtHeader &rCpy )
+ : SfxPoolItem( RES_HEADER ),
+ SwClient( (SwModify*)rCpy.GetRegisteredIn() ),
+ bActive( rCpy.IsActive() )
+{
+}
+
+SwFmtHeader::SwFmtHeader( sal_Bool bOn )
+ : SfxPoolItem( RES_HEADER ),
+ SwClient( 0 ),
+ bActive( bOn )
+{
+}
+
+ SwFmtHeader::~SwFmtHeader()
+{
+ if ( GetHeaderFmt() )
+ DelHFFormat( this, GetHeaderFmt() );
+}
+
+int SwFmtHeader::operator==( const SfxPoolItem& rAttr ) const
+{
+ OSL_ENSURE( SfxPoolItem::operator==( rAttr ), "keine gleichen Attribute" );
+ return ( GetRegisteredIn() == ((SwFmtHeader&)rAttr).GetRegisteredIn() &&
+ bActive == ((SwFmtHeader&)rAttr).IsActive() );
+}
+
+SfxPoolItem* SwFmtHeader::Clone( SfxItemPool* ) const
+{
+ return new SwFmtHeader( *this );
+}
+
+void SwFmtHeader::RegisterToFormat( SwFmt& rFmt )
+{
+ rFmt.Add(this);
+}
+
+// class SwFmtFooter
+// Implementierung teilweise inline im hxx
+
+SwFmtFooter::SwFmtFooter( SwFrmFmt *pFooterFmt )
+ : SfxPoolItem( RES_FOOTER ),
+ SwClient( pFooterFmt ),
+ bActive( pFooterFmt ? sal_True : sal_False )
+{
+}
+
+SwFmtFooter::SwFmtFooter( const SwFmtFooter &rCpy )
+ : SfxPoolItem( RES_FOOTER ),
+ SwClient( (SwModify*)rCpy.GetRegisteredIn() ),
+ bActive( rCpy.IsActive() )
+{
+}
+
+SwFmtFooter::SwFmtFooter( sal_Bool bOn )
+ : SfxPoolItem( RES_FOOTER ),
+ SwClient( 0 ),
+ bActive( bOn )
+{
+}
+
+ SwFmtFooter::~SwFmtFooter()
+{
+ if ( GetFooterFmt() )
+ DelHFFormat( this, GetFooterFmt() );
+}
+
+void SwFmtFooter::RegisterToFormat( SwFmt& rFmt )
+{
+ rFmt.Add(this);
+}
+
+int SwFmtFooter::operator==( const SfxPoolItem& rAttr ) const
+{
+ OSL_ENSURE( SfxPoolItem::operator==( rAttr ), "keine gleichen Attribute" );
+ return ( GetRegisteredIn() == ((SwFmtFooter&)rAttr).GetRegisteredIn() &&
+ bActive == ((SwFmtFooter&)rAttr).IsActive() );
+}
+
+SfxPoolItem* SwFmtFooter::Clone( SfxItemPool* ) const
+{
+ return new SwFmtFooter( *this );
+}
+
+// class SwFmtCntnt
+// Implementierung teilweise inline im hxx
+
+SwFmtCntnt::SwFmtCntnt( const SwFmtCntnt &rCpy )
+ : SfxPoolItem( RES_CNTNT )
+{
+ pStartNode = rCpy.GetCntntIdx() ?
+ new SwNodeIndex( *rCpy.GetCntntIdx() ) : 0;
+}
+
+SwFmtCntnt::SwFmtCntnt( const SwStartNode *pStartNd )
+ : SfxPoolItem( RES_CNTNT )
+{
+ pStartNode = pStartNd ? new SwNodeIndex( *pStartNd ) : 0;
+}
+
+ SwFmtCntnt::~SwFmtCntnt()
+{
+ delete pStartNode;
+}
+
+void SwFmtCntnt::SetNewCntntIdx( const SwNodeIndex *pIdx )
+{
+ delete pStartNode;
+ pStartNode = pIdx ? new SwNodeIndex( *pIdx ) : 0;
+}
+
+int SwFmtCntnt::operator==( const SfxPoolItem& rAttr ) const
+{
+ OSL_ENSURE( SfxPoolItem::operator==( rAttr ), "keine gleichen Attribute" );
+ if( (long)pStartNode ^ (long)((SwFmtCntnt&)rAttr).pStartNode )
+ return 0;
+ if( pStartNode )
+ return ( *pStartNode == *((SwFmtCntnt&)rAttr).GetCntntIdx() );
+ return 1;
+}
+
+SfxPoolItem* SwFmtCntnt::Clone( SfxItemPool* ) const
+{
+ return new SwFmtCntnt( *this );
+}
+
+// class SwFmtPageDesc
+// Implementierung teilweise inline im hxx
+
+SwFmtPageDesc::SwFmtPageDesc( const SwFmtPageDesc &rCpy )
+ : SfxPoolItem( RES_PAGEDESC ),
+ SwClient( (SwPageDesc*)rCpy.GetPageDesc() ),
+ nNumOffset( rCpy.nNumOffset ),
+ nDescNameIdx( rCpy.nDescNameIdx ),
+ pDefinedIn( 0 )
+{
+}
+
+SwFmtPageDesc::SwFmtPageDesc( const SwPageDesc *pDesc )
+ : SfxPoolItem( RES_PAGEDESC ),
+ SwClient( (SwPageDesc*)pDesc ),
+ nNumOffset( 0 ),
+ nDescNameIdx( 0xFFFF ), // IDX_NO_VALUE
+ pDefinedIn( 0 )
+{
+}
+
+ SwFmtPageDesc::~SwFmtPageDesc() {}
+
+bool SwFmtPageDesc::KnowsPageDesc() const
+{
+ return (GetRegisteredIn() != 0);
+}
+
+int SwFmtPageDesc::operator==( const SfxPoolItem& rAttr ) const
+{
+ OSL_ENSURE( SfxPoolItem::operator==( rAttr ), "keine gleichen Attribute" );
+ return ( pDefinedIn == ((SwFmtPageDesc&)rAttr).pDefinedIn ) &&
+ ( nNumOffset == ((SwFmtPageDesc&)rAttr).nNumOffset ) &&
+ ( GetPageDesc() == ((SwFmtPageDesc&)rAttr).GetPageDesc() );
+}
+
+SfxPoolItem* SwFmtPageDesc::Clone( SfxItemPool* ) const
+{
+ return new SwFmtPageDesc( *this );
+}
+
+void SwFmtPageDesc::SwClientNotify( const SwModify&, const SfxHint& rHint )
+{
+ const SwPageDescHint* pHint = dynamic_cast<const SwPageDescHint*>(&rHint);
+ if ( pHint )
+ {
+ // mba: shouldn't that be broadcasted also?
+ SwFmtPageDesc aDfltDesc( pHint->GetPageDesc() );
+ SwPageDesc* pDesc = pHint->GetPageDesc();
+ const SwModify* pMod = GetDefinedIn();
+ if ( pMod )
+ {
+ if( pMod->ISA( SwCntntNode ) )
+ ((SwCntntNode*)pMod)->SetAttr( aDfltDesc );
+ else if( pMod->ISA( SwFmt ))
+ ((SwFmt*)pMod)->SetFmtAttr( aDfltDesc );
+ else
+ {
+ OSL_FAIL( "What kind of SwModify is this?" );
+ RegisterToPageDesc( *pDesc );
+ }
+ }
+ else
+ // there could be an Undo-copy
+ RegisterToPageDesc( *pDesc );
+ }
+}
+
+void SwFmtPageDesc::RegisterToPageDesc( SwPageDesc& rDesc )
+{
+ rDesc.Add( this );
+}
+
+void SwFmtPageDesc::Modify( const SfxPoolItem* pOld, const SfxPoolItem* pNew )
+{
+ if( !pDefinedIn )
+ return;
+
+ const sal_uInt16 nWhichId = pOld ? pOld->Which() : pNew ? pNew->Which() : 0;
+ switch( nWhichId )
+ {
+ case RES_OBJECTDYING:
+ //Der Pagedesc, bei dem ich angemeldet bin stirbt, ich trage
+ //mich also bei meinem Format aus.
+ //Dabei werden ich Deletet!!!
+ if( IS_TYPE( SwFmt, pDefinedIn ))
+#if OSL_DEBUG_LEVEL > 1
+ {
+ sal_Bool bDel = ((SwFmt*)pDefinedIn)->ResetFmtAttr( RES_PAGEDESC );
+ OSL_ENSURE( bDel, ";-) FmtPageDesc nicht zerstoert." );
+ }
+#else
+ ((SwFmt*)pDefinedIn)->ResetFmtAttr( RES_PAGEDESC );
+#endif
+ else if( IS_TYPE( SwCntntNode, pDefinedIn ))
+#if OSL_DEBUG_LEVEL > 1
+ {
+ sal_Bool bDel = ((SwCntntNode*)pDefinedIn)->ResetAttr( RES_PAGEDESC );
+ OSL_ENSURE( bDel, ";-) FmtPageDesc nicht zerstoert." );
+ }
+#else
+ ((SwCntntNode*)pDefinedIn)->ResetAttr( RES_PAGEDESC );
+#endif
+ break;
+
+ default:
+ /* do nothing */;
+ }
+}
+
+bool SwFmtPageDesc::QueryValue( uno::Any& rVal, sal_uInt8 nMemberId ) const
+{
+ // hier wird immer konvertiert!
+ nMemberId &= ~CONVERT_TWIPS;
+ bool bRet = true;
+ switch ( nMemberId )
+ {
+ case MID_PAGEDESC_PAGENUMOFFSET:
+ rVal <<= (sal_Int16)GetNumOffset();
+ break;
+
+ case MID_PAGEDESC_PAGEDESCNAME:
+ {
+ const SwPageDesc* pDesc = GetPageDesc();
+ if( pDesc )
+ {
+ String aString;
+ SwStyleNameMapper::FillProgName(pDesc->GetName(), aString, nsSwGetPoolIdFromName::GET_POOLID_PAGEDESC, sal_True );
+ rVal <<= OUString( aString );
+ }
+ else
+ rVal.clear();
+ }
+ break;
+ default:
+ OSL_ENSURE( !this, "unknown MemberId" );
+ bRet = false;
+ }
+ return bRet;
+}
+
+bool SwFmtPageDesc::PutValue( const uno::Any& rVal, sal_uInt8 nMemberId )
+{
+ // hier wird immer konvertiert!
+ nMemberId &= ~CONVERT_TWIPS;
+ sal_Bool bRet = sal_True;
+ switch ( nMemberId )
+ {
+ case MID_PAGEDESC_PAGENUMOFFSET:
+ {
+ sal_Int16 nOffset = 0;
+ if(rVal >>= nOffset)
+ SetNumOffset( nOffset );
+ else
+ bRet = false;
+ }
+ break;
+
+ case MID_PAGEDESC_PAGEDESCNAME:
+ /* geht nicht, weil das Attribut eigentlich nicht den Namen
+ * sondern einen Pointer auf den PageDesc braucht (ist Client davon).
+ * Der Pointer waere aber ueber den Namen nur vom Dokument zu erfragen.
+ */
+ default:
+ OSL_ENSURE( !this, "unknown MemberId" );
+ bRet = false;
+ }
+ return bRet;
+}
+
+
+// class SwFmtCol
+// Implementierung teilweise inline im hxx
+
+SwColumn::SwColumn() :
+ nWish ( 0 ),
+ nUpper( 0 ),
+ nLower( 0 ),
+ nLeft ( 0 ),
+ nRight( 0 )
+{
+}
+
+sal_Bool SwColumn::operator==( const SwColumn &rCmp )
+{
+ return (nWish == rCmp.GetWishWidth() &&
+ GetLeft() == rCmp.GetLeft() &&
+ GetRight() == rCmp.GetRight() &&
+ GetUpper() == rCmp.GetUpper() &&
+ GetLower() == rCmp.GetLower()) ? sal_True : sal_False;
+}
+
+SwFmtCol::SwFmtCol( const SwFmtCol& rCpy )
+ : SfxPoolItem( RES_COL ),
+ eLineStyle( rCpy.eLineStyle ),
+ nLineWidth( rCpy.nLineWidth),
+ aLineColor( rCpy.aLineColor),
+ nLineHeight( rCpy.GetLineHeight() ),
+ eAdj( rCpy.GetLineAdj() ),
+ aColumns( (sal_Int8)rCpy.GetNumCols(), 1 ),
+ nWidth( rCpy.GetWishWidth() ),
+ bOrtho( rCpy.IsOrtho() )
+{
+ for ( sal_uInt16 i = 0; i < rCpy.GetNumCols(); ++i )
+ {
+ SwColumn *pCol = new SwColumn( *rCpy.GetColumns()[i] );
+ aColumns.Insert( pCol, aColumns.Count() );
+ }
+}
+
+SwFmtCol::~SwFmtCol() {}
+
+SwFmtCol& SwFmtCol::operator=( const SwFmtCol& rCpy )
+{
+ eLineStyle = rCpy.eLineStyle;
+ nLineWidth = rCpy.nLineWidth;
+ aLineColor = rCpy.aLineColor;
+ nLineHeight = rCpy.GetLineHeight();
+ eAdj = rCpy.GetLineAdj();
+ nWidth = rCpy.GetWishWidth();
+ bOrtho = rCpy.IsOrtho();
+
+ if ( aColumns.Count() )
+ aColumns.DeleteAndDestroy( 0, aColumns.Count() );
+ for ( sal_uInt16 i = 0; i < rCpy.GetNumCols(); ++i )
+ {
+ SwColumn *pCol = new SwColumn( *rCpy.GetColumns()[i] );
+ aColumns.Insert( pCol, aColumns.Count() );
+ }
+ return *this;
+}
+
+SwFmtCol::SwFmtCol()
+ : SfxPoolItem( RES_COL ),
+ eLineStyle( editeng::NO_STYLE ),
+ nLineWidth(0),
+ nLineHeight( 100 ),
+ eAdj( COLADJ_NONE ),
+ nWidth( USHRT_MAX ),
+ bOrtho( sal_True )
+{
+}
+
+int SwFmtCol::operator==( const SfxPoolItem& rAttr ) const
+{
+ OSL_ENSURE( SfxPoolItem::operator==( rAttr ), "keine gleichen Attribute" );
+ const SwFmtCol &rCmp = (const SwFmtCol&)rAttr;
+ if( !(eLineStyle == rCmp.eLineStyle &&
+ nLineWidth == rCmp.nLineWidth &&
+ aLineColor == rCmp.aLineColor &&
+ nLineHeight == rCmp.GetLineHeight() &&
+ eAdj == rCmp.GetLineAdj() &&
+ nWidth == rCmp.GetWishWidth() &&
+ bOrtho == rCmp.IsOrtho() &&
+ aColumns.Count() == rCmp.GetNumCols()) )
+ return 0;
+
+ for ( sal_uInt16 i = 0; i < aColumns.Count(); ++i )
+ if ( !(*aColumns[i] == *rCmp.GetColumns()[i]) )
+ return 0;
+
+ return 1;
+}
+
+SfxPoolItem* SwFmtCol::Clone( SfxItemPool* ) const
+{
+ return new SwFmtCol( *this );
+}
+
+sal_uInt16 SwFmtCol::GetGutterWidth( sal_Bool bMin ) const
+{
+ sal_uInt16 nRet = 0;
+ if ( aColumns.Count() == 2 )
+ nRet = aColumns[0]->GetRight() + aColumns[1]->GetLeft();
+ else if ( aColumns.Count() > 2 )
+ {
+ sal_Bool bSet = sal_False;
+ for ( sal_uInt16 i = 1; i < aColumns.Count()-1; ++i )
+ {
+ const sal_uInt16 nTmp = aColumns[i]->GetRight() + aColumns[i+1]->GetLeft();
+ if ( bSet )
+ {
+ if ( nTmp != nRet )
+ {
+ if ( !bMin )
+ return USHRT_MAX;
+ if ( nRet > nTmp )
+ nRet = nTmp;
+ }
+ }
+ else
+ { bSet = sal_True;
+ nRet = nTmp;
+ }
+ }
+ }
+ return nRet;
+}
+
+void SwFmtCol::SetGutterWidth( sal_uInt16 nNew, sal_uInt16 nAct )
+{
+ if ( bOrtho )
+ Calc( nNew, nAct );
+ else
+ {
+ sal_uInt16 nHalf = nNew / 2;
+ for ( sal_uInt16 i = 0; i < aColumns.Count(); ++i )
+ { SwColumn *pCol = aColumns[i];
+ pCol->SetLeft ( nHalf );
+ pCol->SetRight( nHalf );
+ if ( i == 0 )
+ pCol->SetLeft( 0 );
+ else if ( i == (aColumns.Count() - 1) )
+ pCol->SetRight( 0 );
+ }
+ }
+}
+
+void SwFmtCol::Init( sal_uInt16 nNumCols, sal_uInt16 nGutterWidth, sal_uInt16 nAct )
+{
+ //Loeschen scheint hier auf den erste Blick vielleicht etwas zu heftig;
+ //anderfalls muessten allerdings alle Werte der verbleibenden SwColumn's
+ //initialisiert werden.
+ if ( aColumns.Count() )
+ aColumns.DeleteAndDestroy( 0, aColumns.Count() );
+ for ( sal_uInt16 i = 0; i < nNumCols; ++i )
+ { SwColumn *pCol = new SwColumn;
+ aColumns.Insert( pCol, i );
+ }
+ bOrtho = sal_True;
+ nWidth = USHRT_MAX;
+ if( nNumCols )
+ Calc( nGutterWidth, nAct );
+}
+
+void SwFmtCol::SetOrtho( sal_Bool bNew, sal_uInt16 nGutterWidth, sal_uInt16 nAct )
+{
+ bOrtho = bNew;
+ if ( bNew && aColumns.Count() )
+ Calc( nGutterWidth, nAct );
+}
+
+sal_uInt16 SwFmtCol::CalcColWidth( sal_uInt16 nCol, sal_uInt16 nAct ) const
+{
+ OSL_ENSURE( nCol < aColumns.Count(), ":-( ColumnsArr ueberindiziert." );
+ if ( nWidth != nAct )
+ {
+ long nW = aColumns[nCol]->GetWishWidth();
+ nW *= nAct;
+ nW /= nWidth;
+ return sal_uInt16(nW);
+ }
+ else
+ return aColumns[nCol]->GetWishWidth();
+}
+
+sal_uInt16 SwFmtCol::CalcPrtColWidth( sal_uInt16 nCol, sal_uInt16 nAct ) const
+{
+ OSL_ENSURE( nCol < aColumns.Count(), ":-( ColumnsArr ueberindiziert." );
+ sal_uInt16 nRet = CalcColWidth( nCol, nAct );
+ SwColumn *pCol = aColumns[nCol];
+ nRet = nRet - pCol->GetLeft();
+ nRet = nRet - pCol->GetRight();
+ return nRet;
+}
+
+void SwFmtCol::Calc( sal_uInt16 nGutterWidth, sal_uInt16 nAct )
+{
+ if(!GetNumCols())
+ return;
+ //Erstmal die Spalten mit der Aktuellen Breite einstellen, dann die
+ //Wunschbreite der Spalten anhand der Gesamtwunschbreite hochrechnen.
+
+ const sal_uInt16 nGutterHalf = nGutterWidth ? nGutterWidth / 2 : 0;
+
+ //Breite der PrtAreas ist Gesamtbreite - Zwischenraeume / Anzahl
+ const sal_uInt16 nPrtWidth =
+ (nAct - ((GetNumCols()-1) * nGutterWidth)) / GetNumCols();
+ sal_uInt16 nAvail = nAct;
+
+ //Die erste Spalte ist PrtBreite + (Zwischenraumbreite/2)
+ const sal_uInt16 nLeftWidth = nPrtWidth + nGutterHalf;
+ SwColumn *pCol = aColumns[0];
+ pCol->SetWishWidth( nLeftWidth );
+ pCol->SetRight( nGutterHalf );
+ pCol->SetLeft ( 0 );
+ nAvail = nAvail - nLeftWidth;
+
+ //Spalte 2 bis n-1 ist PrtBreite + Zwischenraumbreite
+ const sal_uInt16 nMidWidth = nPrtWidth + nGutterWidth;
+ sal_uInt16 i;
+
+ for ( i = 1; i < GetNumCols()-1; ++i )
+ {
+ pCol = aColumns[i];
+ pCol->SetWishWidth( nMidWidth );
+ pCol->SetLeft ( nGutterHalf );
+ pCol->SetRight( nGutterHalf );
+ nAvail = nAvail - nMidWidth;
+ }
+
+ //Die Letzte Spalte entspricht wieder der ersten, um Rundungsfehler
+ //auszugleichen wird der letzten Spalte alles zugeschlagen was die
+ //anderen nicht verbraucht haben.
+ pCol = aColumns[aColumns.Count()-1];
+ pCol->SetWishWidth( nAvail );
+ pCol->SetLeft ( nGutterHalf );
+ pCol->SetRight( 0 );
+
+ //Umrechnen der aktuellen Breiten in Wunschbreiten.
+ for ( i = 0; i < aColumns.Count(); ++i )
+ {
+ pCol = aColumns[i];
+ long nTmp = pCol->GetWishWidth();
+ nTmp *= GetWishWidth();
+ nTmp /= nAct;
+ pCol->SetWishWidth( sal_uInt16(nTmp) );
+ }
+}
+
+bool SwFmtCol::QueryValue( uno::Any& rVal, sal_uInt8 nMemberId ) const
+{
+ // hier wird immer konvertiert!
+ nMemberId &= ~CONVERT_TWIPS;
+ if(MID_COLUMN_SEPARATOR_LINE == nMemberId)
+ {
+ OSL_FAIL("not implemented");
+ }
+ else
+ {
+ uno::Reference< text::XTextColumns > xCols = new SwXTextColumns(*this);
+ rVal.setValue(&xCols, ::getCppuType((uno::Reference< text::XTextColumns>*)0));
+ }
+ return true;
+}
+
+bool SwFmtCol::PutValue( const uno::Any& rVal, sal_uInt8 nMemberId )
+{
+ // hier wird immer konvertiert!
+ nMemberId &= ~CONVERT_TWIPS;
+ bool bRet = false;
+ if(MID_COLUMN_SEPARATOR_LINE == nMemberId)
+ {
+ OSL_FAIL("not implemented");
+ }
+ else
+ {
+ uno::Reference< text::XTextColumns > xCols;
+ rVal >>= xCols;
+ if(xCols.is())
+ {
+ uno::Sequence<text::TextColumn> aSetColumns = xCols->getColumns();
+ const text::TextColumn* pArray = aSetColumns.getConstArray();
+ aColumns.DeleteAndDestroy(0, aColumns.Count());
+ //max. Count ist hier 64K - das kann das Array aber nicht
+ sal_uInt16 nCount = Min( (sal_uInt16)aSetColumns.getLength(),
+ (sal_uInt16) 0x3fff );
+ sal_uInt16 nWidthSum = 0;
+ // #101224# one column is no column
+ //
+ if(nCount > 1)
+ for(sal_uInt16 i = 0; i < nCount; i++)
+ {
+ SwColumn* pCol = new SwColumn;
+ pCol->SetWishWidth( static_cast<sal_uInt16>(pArray[i].Width) );
+ nWidthSum = static_cast<sal_uInt16>(nWidthSum + pArray[i].Width);
+ pCol->SetLeft ( static_cast<sal_uInt16>(MM100_TO_TWIP(pArray[i].LeftMargin)) );
+ pCol->SetRight( static_cast<sal_uInt16>(MM100_TO_TWIP(pArray[i].RightMargin)) );
+ aColumns.Insert(pCol, i);
+ }
+ bRet = true;
+ nWidth = nWidthSum;
+ bOrtho = sal_False;
+
+ uno::Reference<lang::XUnoTunnel> xNumTunnel(xCols, uno::UNO_QUERY);
+ SwXTextColumns* pSwColums = 0;
+ if(xNumTunnel.is())
+ {
+ pSwColums = reinterpret_cast< SwXTextColumns * >(
+ sal::static_int_cast< sal_IntPtr >(
+ xNumTunnel->getSomething( SwXTextColumns::getUnoTunnelId() )));
+ }
+ if(pSwColums)
+ {
+ bOrtho = pSwColums->IsAutomaticWidth();
+ nLineWidth = pSwColums->GetSepLineWidth();
+ aLineColor.SetColor(pSwColums->GetSepLineColor());
+ nLineHeight = pSwColums->GetSepLineHeightRelative();
+ switch ( pSwColums->GetSepLineStyle() )
+ {
+ default:
+ case 0: eLineStyle = editeng::NO_STYLE; break;
+ case 1: eLineStyle = editeng::SOLID; break;
+ case 2: eLineStyle = editeng::DOTTED; break;
+ case 3: eLineStyle = editeng::DASHED; break;
+ }
+ if(!pSwColums->GetSepLineIsOn())
+ eAdj = COLADJ_NONE;
+ else switch(pSwColums->GetSepLineVertAlign())
+ {
+ case 0: eAdj = COLADJ_TOP; break; //VerticalAlignment_TOP
+ case 1: eAdj = COLADJ_CENTER;break; //VerticalAlignment_MIDDLE
+ case 2: eAdj = COLADJ_BOTTOM;break; //VerticalAlignment_BOTTOM
+ default: OSL_ENSURE( !this, "unknown alignment" ); break;
+ }
+ }
+ }
+ }
+ return bRet;
+}
+
+
+// class SwFmtSurround
+// Implementierung teilweise inline im hxx
+
+SwFmtSurround::SwFmtSurround( SwSurround eFly ) :
+ SfxEnumItem( RES_SURROUND, sal_uInt16( eFly ) )
+{
+ bAnchorOnly = bContour = bOutside = sal_False;
+}
+
+SwFmtSurround::SwFmtSurround( const SwFmtSurround &rCpy ) :
+ SfxEnumItem( RES_SURROUND, rCpy.GetValue() )
+{
+ bAnchorOnly = rCpy.bAnchorOnly;
+ bContour = rCpy.bContour;
+ bOutside = rCpy.bOutside;
+}
+
+int SwFmtSurround::operator==( const SfxPoolItem& rAttr ) const
+{
+ OSL_ENSURE( SfxPoolItem::operator==( rAttr ), "keine gleichen Attribute" );
+ return ( GetValue() == ((SwFmtSurround&)rAttr).GetValue() &&
+ bAnchorOnly== ((SwFmtSurround&)rAttr).bAnchorOnly &&
+ bContour== ((SwFmtSurround&)rAttr).bContour &&
+ bOutside== ((SwFmtSurround&)rAttr).bOutside );
+}
+
+SfxPoolItem* SwFmtSurround::Clone( SfxItemPool* ) const
+{
+ return new SwFmtSurround( *this );
+}
+
+sal_uInt16 SwFmtSurround::GetValueCount() const
+{
+ return SURROUND_END - SURROUND_BEGIN;
+}
+
+
+bool SwFmtSurround::QueryValue( uno::Any& rVal, sal_uInt8 nMemberId ) const
+{
+ // hier wird immer konvertiert!
+ nMemberId &= ~CONVERT_TWIPS;
+ bool bRet = true;
+ switch ( nMemberId )
+ {
+ case MID_SURROUND_SURROUNDTYPE:
+ rVal <<= (text::WrapTextMode)GetSurround();
+ break;
+ case MID_SURROUND_ANCHORONLY:
+ {
+ sal_Bool bTmp = IsAnchorOnly();
+ rVal.setValue(&bTmp, ::getBooleanCppuType());
+ }
+ break;
+ case MID_SURROUND_CONTOUR:
+ {
+ sal_Bool bTmp = IsContour();
+ rVal.setValue(&bTmp, ::getBooleanCppuType());
+ }
+ break;
+ case MID_SURROUND_CONTOUROUTSIDE:
+ {
+ sal_Bool bTmp = IsOutside();
+ rVal.setValue(&bTmp, ::getBooleanCppuType());
+ }
+ break;
+ default:
+ OSL_ENSURE( !this, "unknown MemberId" );
+ bRet = false;
+ }
+ return bRet;
+}
+
+bool SwFmtSurround::PutValue( const uno::Any& rVal, sal_uInt8 nMemberId )
+{
+ // hier wird immer konvertiert!
+ nMemberId &= ~CONVERT_TWIPS;
+ bool bRet = true;
+ switch ( nMemberId )
+ {
+ case MID_SURROUND_SURROUNDTYPE:
+ {
+ sal_Int32 eVal = SWUnoHelper::GetEnumAsInt32( rVal );
+ if( eVal >= 0 && eVal < (sal_Int16)SURROUND_END )
+ SetValue( static_cast<sal_uInt16>(eVal) );
+ else {
+ //exception
+ ;
+ }
+ }
+ break;
+
+ case MID_SURROUND_ANCHORONLY:
+ SetAnchorOnly( *(sal_Bool*)rVal.getValue() );
+ break;
+ case MID_SURROUND_CONTOUR:
+ SetContour( *(sal_Bool*)rVal.getValue() );
+ break;
+ case MID_SURROUND_CONTOUROUTSIDE:
+ SetOutside( *(sal_Bool*)rVal.getValue() );
+ break;
+ default:
+ OSL_ENSURE( !this, "unknown MemberId" );
+ bRet = false;
+ }
+ return bRet;
+}
+
+// class SwFmtVertOrient
+// Implementierung teilweise inline im hxx
+
+SwFmtVertOrient::SwFmtVertOrient( SwTwips nY, sal_Int16 eVert,
+ sal_Int16 eRel )
+ : SfxPoolItem( RES_VERT_ORIENT ),
+ nYPos( nY ),
+ eOrient( eVert ),
+ eRelation( eRel )
+{}
+
+int SwFmtVertOrient::operator==( const SfxPoolItem& rAttr ) const
+{
+ OSL_ENSURE( SfxPoolItem::operator==( rAttr ), "keine gleichen Attribute" );
+ return ( nYPos == ((SwFmtVertOrient&)rAttr).nYPos &&
+ eOrient == ((SwFmtVertOrient&)rAttr).eOrient &&
+ eRelation == ((SwFmtVertOrient&)rAttr).eRelation );
+}
+
+SfxPoolItem* SwFmtVertOrient::Clone( SfxItemPool* ) const
+{
+ return new SwFmtVertOrient( nYPos, eOrient, eRelation );
+}
+
+bool SwFmtVertOrient::QueryValue( uno::Any& rVal, sal_uInt8 nMemberId ) const
+{
+ // hier wird immer konvertiert!
+ nMemberId &= ~CONVERT_TWIPS;
+ bool bRet = true;
+ switch ( nMemberId )
+ {
+ case MID_VERTORIENT_ORIENT:
+ {
+ sal_Int16 nRet = text::VertOrientation::NONE;
+ switch( eOrient )
+ {
+ case text::VertOrientation::TOP : nRet = text::VertOrientation::TOP ;break;
+ case text::VertOrientation::CENTER : nRet = text::VertOrientation::CENTER ;break;
+ case text::VertOrientation::BOTTOM : nRet = text::VertOrientation::BOTTOM ;break;
+ case text::VertOrientation::CHAR_TOP : nRet = text::VertOrientation::CHAR_TOP ;break;
+ case text::VertOrientation::CHAR_CENTER: nRet = text::VertOrientation::CHAR_CENTER;break;
+ case text::VertOrientation::CHAR_BOTTOM: nRet = text::VertOrientation::CHAR_BOTTOM;break;
+ case text::VertOrientation::LINE_TOP : nRet = text::VertOrientation::LINE_TOP ;break;
+ case text::VertOrientation::LINE_CENTER: nRet = text::VertOrientation::LINE_CENTER;break;
+ case text::VertOrientation::LINE_BOTTOM: nRet = text::VertOrientation::LINE_BOTTOM;break;
+ default: break;
+ }
+ rVal <<= nRet;
+ }
+ break;
+ case MID_VERTORIENT_RELATION:
+ rVal <<= lcl_RelToINT(eRelation);
+ break;
+ case MID_VERTORIENT_POSITION:
+ rVal <<= (sal_Int32)TWIP_TO_MM100(GetPos());
+ break;
+ default:
+ OSL_ENSURE( !this, "unknown MemberId" );
+ bRet = false;
+ }
+ return bRet;
+}
+
+bool SwFmtVertOrient::PutValue( const uno::Any& rVal, sal_uInt8 nMemberId )
+{
+ sal_Bool bConvert = 0 != (nMemberId&CONVERT_TWIPS);
+ nMemberId &= ~CONVERT_TWIPS;
+ bool bRet = true;
+ switch ( nMemberId )
+ {
+ case MID_VERTORIENT_ORIENT:
+ {
+ sal_uInt16 nVal = 0;
+ rVal >>= nVal;
+ switch( nVal )
+ {
+ case text::VertOrientation::NONE: eOrient = text::VertOrientation::NONE; break;
+ case text::VertOrientation::TOP : eOrient = text::VertOrientation::TOP; break;
+ case text::VertOrientation::CENTER : eOrient = text::VertOrientation::CENTER; break;
+ case text::VertOrientation::BOTTOM : eOrient = text::VertOrientation::BOTTOM; break;
+ case text::VertOrientation::CHAR_TOP : eOrient = text::VertOrientation::CHAR_TOP; break;
+ case text::VertOrientation::CHAR_CENTER: eOrient = text::VertOrientation::CHAR_CENTER;break;
+ case text::VertOrientation::CHAR_BOTTOM: eOrient = text::VertOrientation::CHAR_BOTTOM;break;
+ case text::VertOrientation::LINE_TOP : eOrient = text::VertOrientation::LINE_TOP; break;
+ case text::VertOrientation::LINE_CENTER: eOrient = text::VertOrientation::LINE_CENTER;break;
+ case text::VertOrientation::LINE_BOTTOM: eOrient = text::VertOrientation::LINE_BOTTOM;break;
+ }
+ }
+ break;
+ case MID_VERTORIENT_RELATION:
+ {
+ eRelation = lcl_IntToRelation(rVal);
+ }
+ break;
+ case MID_VERTORIENT_POSITION:
+ {
+ sal_Int32 nVal = 0;
+ rVal >>= nVal;
+ if(bConvert)
+ nVal = MM100_TO_TWIP(nVal);
+ SetPos( nVal );
+ }
+ break;
+ default:
+ OSL_ENSURE( !this, "unknown MemberId" );
+ bRet = false;
+ }
+ return bRet;
+}
+
+
+
+// class SwFmtHoriOrient
+// Implementierung teilweise inline im hxx
+
+SwFmtHoriOrient::SwFmtHoriOrient( SwTwips nX, sal_Int16 eHori,
+ sal_Int16 eRel, sal_Bool bPos )
+ : SfxPoolItem( RES_HORI_ORIENT ),
+ nXPos( nX ),
+ eOrient( eHori ),
+ eRelation( eRel ),
+ bPosToggle( bPos )
+{}
+
+int SwFmtHoriOrient::operator==( const SfxPoolItem& rAttr ) const
+{
+ OSL_ENSURE( SfxPoolItem::operator==( rAttr ), "keine gleichen Attribute" );
+ return ( nXPos == ((SwFmtHoriOrient&)rAttr).nXPos &&
+ eOrient == ((SwFmtHoriOrient&)rAttr).eOrient &&
+ eRelation == ((SwFmtHoriOrient&)rAttr).eRelation &&
+ bPosToggle == ((SwFmtHoriOrient&)rAttr).bPosToggle );
+}
+
+SfxPoolItem* SwFmtHoriOrient::Clone( SfxItemPool* ) const
+{
+ return new SwFmtHoriOrient( nXPos, eOrient, eRelation, bPosToggle );
+}
+
+bool SwFmtHoriOrient::QueryValue( uno::Any& rVal, sal_uInt8 nMemberId ) const
+{
+ // hier wird immer konvertiert!
+ nMemberId &= ~CONVERT_TWIPS;
+ bool bRet = true;
+ switch ( nMemberId )
+ {
+ case MID_HORIORIENT_ORIENT:
+ {
+ sal_Int16 nRet = text::HoriOrientation::NONE;
+ switch( eOrient )
+ {
+ case text::HoriOrientation::RIGHT: nRet = text::HoriOrientation::RIGHT; break;
+ case text::HoriOrientation::CENTER : nRet = text::HoriOrientation::CENTER; break;
+ case text::HoriOrientation::LEFT : nRet = text::HoriOrientation::LEFT; break;
+ case text::HoriOrientation::INSIDE : nRet = text::HoriOrientation::INSIDE; break;
+ case text::HoriOrientation::OUTSIDE: nRet = text::HoriOrientation::OUTSIDE; break;
+ case text::HoriOrientation::FULL: nRet = text::HoriOrientation::FULL; break;
+ case text::HoriOrientation::LEFT_AND_WIDTH :
+ nRet = text::HoriOrientation::LEFT_AND_WIDTH;
+ break;
+ default:
+ break;
+
+ }
+ rVal <<= nRet;
+ }
+ break;
+ case MID_HORIORIENT_RELATION:
+ rVal <<= lcl_RelToINT(eRelation);
+ break;
+ case MID_HORIORIENT_POSITION:
+ rVal <<= (sal_Int32)TWIP_TO_MM100(GetPos());
+ break;
+ case MID_HORIORIENT_PAGETOGGLE:
+ {
+ sal_Bool bTmp = IsPosToggle();
+ rVal.setValue(&bTmp, ::getBooleanCppuType());
+ }
+ break;
+ default:
+ OSL_ENSURE( !this, "unknown MemberId" );
+ bRet = false;
+ }
+ return bRet;
+}
+
+bool SwFmtHoriOrient::PutValue( const uno::Any& rVal, sal_uInt8 nMemberId )
+{
+ sal_Bool bConvert = 0 != (nMemberId&CONVERT_TWIPS);
+ nMemberId &= ~CONVERT_TWIPS;
+ bool bRet = true;
+ switch ( nMemberId )
+ {
+ case MID_HORIORIENT_ORIENT:
+ {
+ sal_Int16 nVal = 0;
+ rVal >>= nVal;
+ switch( nVal )
+ {
+ case text::HoriOrientation::NONE: eOrient = text::HoriOrientation::NONE ; break;
+ case text::HoriOrientation::RIGHT: eOrient = text::HoriOrientation::RIGHT; break;
+ case text::HoriOrientation::CENTER : eOrient = text::HoriOrientation::CENTER; break;
+ case text::HoriOrientation::LEFT : eOrient = text::HoriOrientation::LEFT; break;
+ case text::HoriOrientation::INSIDE : eOrient = text::HoriOrientation::INSIDE; break;
+ case text::HoriOrientation::OUTSIDE: eOrient = text::HoriOrientation::OUTSIDE; break;
+ case text::HoriOrientation::FULL: eOrient = text::HoriOrientation::FULL; break;
+ case text::HoriOrientation::LEFT_AND_WIDTH:
+ eOrient = text::HoriOrientation::LEFT_AND_WIDTH;
+ break;
+ }
+ }
+ break;
+ case MID_HORIORIENT_RELATION:
+ {
+ eRelation = lcl_IntToRelation(rVal);
+ }
+ break;
+ case MID_HORIORIENT_POSITION:
+ {
+ sal_Int32 nVal = 0;
+ if(!(rVal >>= nVal))
+ bRet = false;
+ if(bConvert)
+ nVal = MM100_TO_TWIP(nVal);
+ SetPos( nVal );
+ }
+ break;
+ case MID_HORIORIENT_PAGETOGGLE:
+ SetPosToggle( *(sal_Bool*)rVal.getValue());
+ break;
+ default:
+ OSL_ENSURE( !this, "unknown MemberId" );
+ bRet = false;
+ }
+ return bRet;
+}
+
+
+
+// class SwFmtAnchor
+// Implementierung teilweise inline im hxx
+
+SwFmtAnchor::SwFmtAnchor( RndStdIds nRnd, sal_uInt16 nPage )
+ : SfxPoolItem( RES_ANCHOR ),
+ pCntntAnchor( 0 ),
+ nAnchorId( nRnd ),
+ nPageNum( nPage ),
+ // OD 2004-05-05 #i28701# - get always new increased order number
+ mnOrder( ++mnOrderCounter )
+{}
+
+SwFmtAnchor::SwFmtAnchor( const SwFmtAnchor &rCpy )
+ : SfxPoolItem( RES_ANCHOR ),
+ nAnchorId( rCpy.GetAnchorId() ),
+ nPageNum( rCpy.GetPageNum() ),
+ // OD 2004-05-05 #i28701# - get always new increased order number
+ mnOrder( ++mnOrderCounter )
+{
+ pCntntAnchor = rCpy.GetCntntAnchor() ?
+ new SwPosition( *rCpy.GetCntntAnchor() ) : 0;
+}
+
+ SwFmtAnchor::~SwFmtAnchor()
+{
+ delete pCntntAnchor;
+}
+
+void SwFmtAnchor::SetAnchor( const SwPosition *pPos )
+{
+ if ( pCntntAnchor )
+ delete pCntntAnchor;
+ pCntntAnchor = pPos ? new SwPosition( *pPos ) : 0;
+ //AM Absatz gebundene Flys sollten nie in den Absatz hineinzeigen.
+ if (pCntntAnchor &&
+ ((FLY_AT_PARA == nAnchorId) || (FLY_AT_FLY == nAnchorId)))
+ {
+ pCntntAnchor->nContent.Assign( 0, 0 );
+ }
+}
+
+SwFmtAnchor& SwFmtAnchor::operator=(const SwFmtAnchor& rAnchor)
+{
+ nAnchorId = rAnchor.GetAnchorId();
+ nPageNum = rAnchor.GetPageNum();
+ // OD 2004-05-05 #i28701# - get always new increased order number
+ mnOrder = ++mnOrderCounter;
+
+ delete pCntntAnchor;
+ pCntntAnchor = rAnchor.pCntntAnchor ?
+ new SwPosition(*(rAnchor.pCntntAnchor)) : 0;
+ return *this;
+}
+
+int SwFmtAnchor::operator==( const SfxPoolItem& rAttr ) const
+{
+ OSL_ENSURE( SfxPoolItem::operator==( rAttr ), "keine gleichen Attribute" );
+ // OD 2004-05-05 #i28701# - Note: <mnOrder> hasn't to be considered.
+ return ( nAnchorId == ((SwFmtAnchor&)rAttr).GetAnchorId() &&
+ nPageNum == ((SwFmtAnchor&)rAttr).GetPageNum() &&
+ //Anker vergleichen. Entweder zeigen beide auf das gleiche
+ //Attribut bzw. sind 0 oder die SwPosition* sind beide
+ //gueltig und die SwPositions sind gleich.
+ (pCntntAnchor == ((SwFmtAnchor&)rAttr).GetCntntAnchor() ||
+ (pCntntAnchor && ((SwFmtAnchor&)rAttr).GetCntntAnchor() &&
+ *pCntntAnchor == *((SwFmtAnchor&)rAttr).GetCntntAnchor())));
+}
+
+SfxPoolItem* SwFmtAnchor::Clone( SfxItemPool* ) const
+{
+ return new SwFmtAnchor( *this );
+}
+
+// OD 2004-05-05 #i28701#
+sal_uInt32 SwFmtAnchor::mnOrderCounter = 0;
+
+// OD 2004-05-05 #i28701#
+sal_uInt32 SwFmtAnchor::GetOrder() const
+{
+ return mnOrder;
+}
+
+bool SwFmtAnchor::QueryValue( uno::Any& rVal, sal_uInt8 nMemberId ) const
+{
+ // hier wird immer konvertiert!
+ nMemberId &= ~CONVERT_TWIPS;
+ bool bRet = true;
+ switch ( nMemberId )
+ {
+ case MID_ANCHOR_ANCHORTYPE:
+
+ text::TextContentAnchorType eRet;
+ switch (GetAnchorId())
+ {
+ case FLY_AT_CHAR:
+ eRet = text::TextContentAnchorType_AT_CHARACTER;
+ break;
+ case FLY_AT_PAGE:
+ eRet = text::TextContentAnchorType_AT_PAGE;
+ break;
+ case FLY_AT_FLY:
+ eRet = text::TextContentAnchorType_AT_FRAME;
+ break;
+ case FLY_AS_CHAR:
+ eRet = text::TextContentAnchorType_AS_CHARACTER;
+ break;
+ //case FLY_AT_PARA:
+ default:
+ eRet = text::TextContentAnchorType_AT_PARAGRAPH;
+ }
+ rVal <<= eRet;
+ break;
+ case MID_ANCHOR_PAGENUM:
+ rVal <<= (sal_Int16)GetPageNum();
+ break;
+ case MID_ANCHOR_ANCHORFRAME:
+ {
+ if(pCntntAnchor && FLY_AT_FLY == nAnchorId)
+ {
+ SwFrmFmt* pFmt = pCntntAnchor->nNode.GetNode().GetFlyFmt();
+ if(pFmt)
+ {
+ uno::Reference<container::XNamed> xNamed = SwXFrames::GetObject( *pFmt, FLYCNTTYPE_FRM );
+ uno::Reference<text::XTextFrame> xRet(xNamed, uno::UNO_QUERY);
+ rVal <<= xRet;
+ }
+ }
+ }
+ break;
+ default:
+ OSL_ENSURE( !this, "unknown MemberId" );
+ bRet = false;
+ }
+ return bRet;
+}
+
+bool SwFmtAnchor::PutValue( const uno::Any& rVal, sal_uInt8 nMemberId )
+{
+ // hier wird immer konvertiert!
+ nMemberId &= ~CONVERT_TWIPS;
+ bool bRet = true;
+ switch ( nMemberId )
+ {
+ case MID_ANCHOR_ANCHORTYPE:
+ {
+ RndStdIds eAnchor;
+ switch( SWUnoHelper::GetEnumAsInt32( rVal ) )
+ {
+ case text::TextContentAnchorType_AS_CHARACTER:
+ eAnchor = FLY_AS_CHAR;
+ break;
+ case text::TextContentAnchorType_AT_PAGE:
+ eAnchor = FLY_AT_PAGE;
+ if( GetPageNum() > 0 && pCntntAnchor )
+ {
+ // If the anchor type is page and a valid page number
+ // has been set, the content position isn't required
+ // any longer.
+ delete pCntntAnchor;
+ pCntntAnchor = 0;
+ }
+ break;
+ case text::TextContentAnchorType_AT_FRAME:
+ eAnchor = FLY_AT_FLY;
+ break;
+ case text::TextContentAnchorType_AT_CHARACTER:
+ eAnchor = FLY_AT_CHAR;
+ break;
+ //case text::TextContentAnchorType_AT_PARAGRAPH:
+ default:
+ eAnchor = FLY_AT_PARA;
+ break;
+ }
+ SetType( eAnchor );
+ }
+ break;
+ case MID_ANCHOR_PAGENUM:
+ {
+ sal_Int16 nVal = 0;
+ if((rVal >>= nVal) && nVal > 0)
+ {
+ SetPageNum( nVal );
+ if ((FLY_AT_PAGE == GetAnchorId()) && pCntntAnchor)
+ {
+ // If the anchor type is page and a valid page number
+ // is set, the content paoition has to be deleted to not
+ // confuse the layout (frmtool.cxx). However, if the
+ // anchor type is not page, any content position will
+ // be kept.
+ delete pCntntAnchor;
+ pCntntAnchor = 0;
+ }
+ }
+ else
+ bRet = false;
+ }
+ break;
+ case MID_ANCHOR_ANCHORFRAME:
+ //no break here!;
+ default:
+ OSL_ENSURE( !this, "unknown MemberId" );
+ bRet = false;
+ }
+ return bRet;
+}
+
+// class SwFmtURL
+// Implementierung teilweise inline im hxx
+
+SwFmtURL::SwFmtURL() :
+ SfxPoolItem( RES_URL ),
+ pMap( 0 ),
+ bIsServerMap( sal_False )
+{
+}
+
+SwFmtURL::SwFmtURL( const SwFmtURL &rURL) :
+ SfxPoolItem( RES_URL ),
+ sTargetFrameName( rURL.GetTargetFrameName() ),
+ sURL( rURL.GetURL() ),
+ sName( rURL.GetName() ),
+ bIsServerMap( rURL.IsServerMap() )
+{
+ pMap = rURL.GetMap() ? new ImageMap( *rURL.GetMap() ) : 0;
+}
+
+SwFmtURL::~SwFmtURL()
+{
+ if ( pMap )
+ delete pMap;
+}
+
+int SwFmtURL::operator==( const SfxPoolItem &rAttr ) const
+{
+ OSL_ENSURE( SfxPoolItem::operator==( rAttr ), "keine gleichen Attribute" );
+ const SwFmtURL &rCmp = (SwFmtURL&)rAttr;
+ sal_Bool bRet = bIsServerMap == rCmp.IsServerMap() &&
+ sURL == rCmp.GetURL() &&
+ sTargetFrameName == rCmp.GetTargetFrameName() &&
+ sName == rCmp.GetName();
+ if ( bRet )
+ {
+ if ( pMap && rCmp.GetMap() )
+ bRet = *pMap == *rCmp.GetMap();
+ else
+ bRet = pMap == rCmp.GetMap();
+ }
+ return bRet;
+}
+
+SfxPoolItem* SwFmtURL::Clone( SfxItemPool* ) const
+{
+ return new SwFmtURL( *this );
+}
+
+void SwFmtURL::SetURL( const XubString &rURL, sal_Bool bServerMap )
+{
+ sURL = rURL;
+ bIsServerMap = bServerMap;
+}
+
+void SwFmtURL::SetMap( const ImageMap *pM )
+{
+ if ( pMap )
+ delete pMap;
+ pMap = pM ? new ImageMap( *pM ) : 0;
+}
+extern const SvEventDescription* lcl_GetSupportedMacroItems();
+
+bool SwFmtURL::QueryValue( uno::Any& rVal, sal_uInt8 nMemberId ) const
+{
+ // hier wird immer konvertiert!
+ nMemberId &= ~CONVERT_TWIPS;
+ bool bRet = true;
+ switch ( nMemberId )
+ {
+ case MID_URL_URL:
+ {
+ OUString sRet = GetURL();
+ rVal <<= sRet;
+ }
+ break;
+ case MID_URL_TARGET:
+ {
+ OUString sRet = GetTargetFrameName();
+ rVal <<= sRet;
+ }
+ break;
+ case MID_URL_HYPERLINKNAME:
+ rVal <<= OUString( GetName() );
+ break;
+ case MID_URL_CLIENTMAP:
+ {
+ uno::Reference< uno::XInterface > xInt;
+ if(pMap)
+ {
+ xInt = SvUnoImageMap_createInstance( *pMap, lcl_GetSupportedMacroItems() );
+ }
+ else
+ {
+ ImageMap aEmptyMap;
+ xInt = SvUnoImageMap_createInstance( aEmptyMap, lcl_GetSupportedMacroItems() );
+ }
+ uno::Reference< container::XIndexContainer > xCont(xInt, uno::UNO_QUERY);
+ rVal <<= xCont;
+ }
+ break;
+ case MID_URL_SERVERMAP:
+ {
+ sal_Bool bTmp = IsServerMap();
+ rVal.setValue(&bTmp, ::getBooleanCppuType());
+ }
+ break;
+ default:
+ OSL_ENSURE( !this, "unknown MemberId" );
+ bRet = false;
+ }
+ return bRet;
+}
+
+bool SwFmtURL::PutValue( const uno::Any& rVal, sal_uInt8 nMemberId )
+{
+ // hier wird immer konvertiert!
+ nMemberId &= ~CONVERT_TWIPS;
+ bool bRet = true;
+ switch ( nMemberId )
+ {
+ case MID_URL_URL:
+ {
+ OUString sTmp;
+ rVal >>= sTmp;
+ SetURL( sTmp, bIsServerMap );
+ }
+ break;
+ case MID_URL_TARGET:
+ {
+ OUString sTmp;
+ rVal >>= sTmp;
+ SetTargetFrameName( sTmp );
+ }
+ break;
+ case MID_URL_HYPERLINKNAME:
+ {
+ OUString sTmp;
+ rVal >>= sTmp;
+ SetName( sTmp );
+ }
+ break;
+ case MID_URL_CLIENTMAP:
+ {
+ uno::Reference<container::XIndexContainer> xCont;
+ if(!rVal.hasValue())
+ DELETEZ(pMap);
+ else if(rVal >>= xCont)
+ {
+ if(!pMap)
+ pMap = new ImageMap;
+ bRet = SvUnoImageMap_fillImageMap( xCont, *pMap );
+ }
+ else
+ bRet = false;
+ }
+ break;
+ case MID_URL_SERVERMAP:
+ bIsServerMap = *(sal_Bool*)rVal.getValue();
+ break;
+ default:
+ OSL_ENSURE( !this, "unknown MemberId" );
+ bRet = false;
+ }
+ return bRet;
+}
+
+
+// class SwNoReadOnly
+
+SfxPoolItem* SwFmtEditInReadonly::Clone( SfxItemPool* ) const
+{
+ return new SwFmtEditInReadonly( Which(), GetValue() );
+}
+
+// class SwFmtLayoutSplit
+
+SfxPoolItem* SwFmtLayoutSplit::Clone( SfxItemPool* ) const
+{
+ return new SwFmtLayoutSplit( GetValue() );
+}
+
+// class SwFmtRowSplit
+
+SfxPoolItem* SwFmtRowSplit::Clone( SfxItemPool* ) const
+{
+ return new SwFmtRowSplit( GetValue() );
+}
+
+
+// class SwFmtNoBalancedColumns
+
+SfxPoolItem* SwFmtNoBalancedColumns::Clone( SfxItemPool* ) const
+{
+ return new SwFmtNoBalancedColumns( GetValue() );
+}
+
+// class SwFmtFtnEndAtTxtEnd
+
+sal_uInt16 SwFmtFtnEndAtTxtEnd::GetValueCount() const
+{
+ return sal_uInt16( FTNEND_ATTXTEND_END );
+}
+
+SwFmtFtnEndAtTxtEnd& SwFmtFtnEndAtTxtEnd::operator=(
+ const SwFmtFtnEndAtTxtEnd& rAttr )
+{
+ SfxEnumItem::SetValue( rAttr.GetValue() );
+ aFmt = rAttr.aFmt;
+ nOffset = rAttr.nOffset;
+ sPrefix = rAttr.sPrefix;
+ sSuffix = rAttr.sSuffix;
+ return *this;
+}
+
+int SwFmtFtnEndAtTxtEnd::operator==( const SfxPoolItem& rItem ) const
+{
+ const SwFmtFtnEndAtTxtEnd& rAttr = (SwFmtFtnEndAtTxtEnd&)rItem;
+ return SfxEnumItem::operator==( rAttr ) &&
+ aFmt.GetNumberingType() == rAttr.aFmt.GetNumberingType() &&
+ nOffset == rAttr.nOffset &&
+ sPrefix == rAttr.sPrefix &&
+ sSuffix == rAttr.sSuffix;
+}
+
+bool SwFmtFtnEndAtTxtEnd::QueryValue( uno::Any& rVal, sal_uInt8 nMemberId ) const
+{
+ nMemberId &= ~CONVERT_TWIPS;
+ switch(nMemberId)
+ {
+ case MID_COLLECT :
+ {
+ sal_Bool bVal = GetValue() >= FTNEND_ATTXTEND;
+ rVal.setValue(&bVal, ::getBooleanCppuType());
+ }
+ break;
+ case MID_RESTART_NUM :
+ {
+ sal_Bool bVal = GetValue() >= FTNEND_ATTXTEND_OWNNUMSEQ;
+ rVal.setValue(&bVal, ::getBooleanCppuType());
+ }
+ break;
+ case MID_NUM_START_AT: rVal <<= (sal_Int16) nOffset; break;
+ case MID_OWN_NUM :
+ {
+ sal_Bool bVal = GetValue() >= FTNEND_ATTXTEND_OWNNUMANDFMT;
+ rVal.setValue(&bVal, ::getBooleanCppuType());
+ }
+ break;
+ case MID_NUM_TYPE : rVal <<= aFmt.GetNumberingType(); break;
+ case MID_PREFIX : rVal <<= OUString(sPrefix); break;
+ case MID_SUFFIX : rVal <<= OUString(sSuffix); break;
+ default: return sal_False;
+ }
+ return true;
+}
+
+bool SwFmtFtnEndAtTxtEnd::PutValue( const uno::Any& rVal, sal_uInt8 nMemberId )
+{
+ bool bRet = true;
+ nMemberId &= ~CONVERT_TWIPS;
+ switch(nMemberId)
+ {
+ case MID_COLLECT :
+ {
+ sal_Bool bVal = *(sal_Bool*)rVal.getValue();
+ if(!bVal && GetValue() >= FTNEND_ATTXTEND)
+ SetValue(FTNEND_ATPGORDOCEND);
+ else if(bVal && GetValue() < FTNEND_ATTXTEND)
+ SetValue(FTNEND_ATTXTEND);
+ }
+ break;
+ case MID_RESTART_NUM :
+ {
+ sal_Bool bVal = *(sal_Bool*)rVal.getValue();
+ if(!bVal && GetValue() >= FTNEND_ATTXTEND_OWNNUMSEQ)
+ SetValue(FTNEND_ATTXTEND);
+ else if(bVal && GetValue() < FTNEND_ATTXTEND_OWNNUMSEQ)
+ SetValue(FTNEND_ATTXTEND_OWNNUMSEQ);
+ }
+ break;
+ case MID_NUM_START_AT:
+ {
+ sal_Int16 nVal = 0;
+ rVal >>= nVal;
+ if(nVal >= 0)
+ nOffset = nVal;
+ else
+ bRet = false;
+ }
+ break;
+ case MID_OWN_NUM :
+ {
+ sal_Bool bVal = *(sal_Bool*)rVal.getValue();
+ if(!bVal && GetValue() >= FTNEND_ATTXTEND_OWNNUMANDFMT)
+ SetValue(FTNEND_ATTXTEND_OWNNUMSEQ);
+ else if(bVal && GetValue() < FTNEND_ATTXTEND_OWNNUMANDFMT)
+ SetValue(FTNEND_ATTXTEND_OWNNUMANDFMT);
+ }
+ break;
+ case MID_NUM_TYPE :
+ {
+ sal_Int16 nVal = 0;
+ rVal >>= nVal;
+ if(nVal >= 0 &&
+ (nVal <= SVX_NUM_ARABIC ||
+ SVX_NUM_CHARS_UPPER_LETTER_N == nVal ||
+ SVX_NUM_CHARS_LOWER_LETTER_N == nVal ))
+ aFmt.SetNumberingType(nVal);
+ else
+ bRet = false;
+ }
+ break;
+ case MID_PREFIX :
+ {
+ OUString sVal; rVal >>= sVal;
+ sPrefix = sVal;
+ }
+ break;
+ case MID_SUFFIX :
+ {
+ OUString sVal; rVal >>= sVal;
+ sSuffix = sVal;
+ }
+ break;
+ default: bRet = false;
+ }
+ return bRet;
+}
+
+
+// class SwFmtFtnAtTxtEnd
+
+SfxPoolItem* SwFmtFtnAtTxtEnd::Clone( SfxItemPool* ) const
+{
+ SwFmtFtnAtTxtEnd* pNew = new SwFmtFtnAtTxtEnd;
+ *pNew = *this;
+ return pNew;
+}
+
+// class SwFmtEndAtTxtEnd
+
+SfxPoolItem* SwFmtEndAtTxtEnd::Clone( SfxItemPool* ) const
+{
+ SwFmtEndAtTxtEnd* pNew = new SwFmtEndAtTxtEnd;
+ *pNew = *this;
+ return pNew;
+}
+
+//class SwFmtChain
+
+
+int SwFmtChain::operator==( const SfxPoolItem &rAttr ) const
+{
+ OSL_ENSURE( SfxPoolItem::operator==( rAttr ), "keine gleichen Attribute" );
+
+ return GetPrev() == ((SwFmtChain&)rAttr).GetPrev() &&
+ GetNext() == ((SwFmtChain&)rAttr).GetNext();
+}
+
+SwFmtChain::SwFmtChain( const SwFmtChain &rCpy ) :
+ SfxPoolItem( RES_CHAIN )
+{
+ SetPrev( rCpy.GetPrev() );
+ SetNext( rCpy.GetNext() );
+}
+
+SfxPoolItem* SwFmtChain::Clone( SfxItemPool* ) const
+{
+ SwFmtChain *pRet = new SwFmtChain;
+ pRet->SetPrev( GetPrev() );
+ pRet->SetNext( GetNext() );
+ return pRet;
+}
+
+void SwFmtChain::SetPrev( SwFlyFrmFmt *pFmt )
+{
+ if ( pFmt )
+ pFmt->Add( &aPrev );
+ else if ( aPrev.GetRegisteredIn() )
+ ((SwModify*)aPrev.GetRegisteredIn())->Remove( &aPrev );
+}
+
+void SwFmtChain::SetNext( SwFlyFrmFmt *pFmt )
+{
+ if ( pFmt )
+ pFmt->Add( &aNext );
+ else if ( aNext.GetRegisteredIn() )
+ ((SwModify*)aNext.GetRegisteredIn())->Remove( &aNext );
+}
+
+bool SwFmtChain::QueryValue( uno::Any& rVal, sal_uInt8 nMemberId ) const
+{
+ // hier wird immer konvertiert!
+ nMemberId &= ~CONVERT_TWIPS;
+ bool bRet = true;
+ XubString aRet;
+ switch ( nMemberId )
+ {
+ case MID_CHAIN_PREVNAME:
+ if ( GetPrev() )
+ aRet = GetPrev()->GetName();
+ break;
+ case MID_CHAIN_NEXTNAME:
+ if ( GetNext() )
+ aRet = GetNext()->GetName();
+ break;
+ default:
+ OSL_ENSURE( !this, "unknown MemberId" );
+ bRet = false;
+ }
+ rVal <<= OUString(aRet);
+ return bRet;
+}
+
+
+
+
+//class SwFmtLineNumber
+
+SwFmtLineNumber::SwFmtLineNumber() :
+ SfxPoolItem( RES_LINENUMBER )
+{
+ nStartValue = 0;
+ bCountLines = sal_True;
+}
+
+SwFmtLineNumber::~SwFmtLineNumber()
+{
+}
+
+int SwFmtLineNumber::operator==( const SfxPoolItem &rAttr ) const
+{
+ OSL_ENSURE( SfxPoolItem::operator==( rAttr ), "keine gleichen Attribute" );
+
+ return nStartValue == ((SwFmtLineNumber&)rAttr).GetStartValue() &&
+ bCountLines == ((SwFmtLineNumber&)rAttr).IsCount();
+}
+
+SfxPoolItem* SwFmtLineNumber::Clone( SfxItemPool* ) const
+{
+ return new SwFmtLineNumber( *this );
+}
+
+bool SwFmtLineNumber::QueryValue( uno::Any& rVal, sal_uInt8 nMemberId ) const
+{
+ // hier wird immer konvertiert!
+ nMemberId &= ~CONVERT_TWIPS;
+ bool bRet = true;
+ switch ( nMemberId )
+ {
+ case MID_LINENUMBER_COUNT:
+ {
+ sal_Bool bTmp = IsCount();
+ rVal.setValue(&bTmp, ::getBooleanCppuType());
+ }
+ break;
+ case MID_LINENUMBER_STARTVALUE:
+ rVal <<= (sal_Int32)GetStartValue();
+ break;
+ default:
+ OSL_ENSURE( !this, "unknown MemberId" );
+ bRet = false;
+ }
+ return bRet;
+}
+
+bool SwFmtLineNumber::PutValue( const uno::Any& rVal, sal_uInt8 nMemberId )
+{
+ // hier wird immer konvertiert!
+ nMemberId &= ~CONVERT_TWIPS;
+ bool bRet = true;
+ switch ( nMemberId )
+ {
+ case MID_LINENUMBER_COUNT:
+ SetCountLines( *(sal_Bool*)rVal.getValue() );
+ break;
+ case MID_LINENUMBER_STARTVALUE:
+ {
+ sal_Int32 nVal = 0;
+ if(rVal >>= nVal)
+ SetStartValue( nVal );
+ else
+ bRet = false;
+ }
+ break;
+ default:
+ OSL_ENSURE( !this, "unknown MemberId" );
+ bRet = false;
+ }
+ return bRet;
+}
+
+/*************************************************************************
+ * class SwTextGridItem
+ *************************************************************************/
+
+SwTextGridItem::SwTextGridItem()
+ : SfxPoolItem( RES_TEXTGRID ), aColor( COL_LIGHTGRAY ), nLines( 20 ),
+ nBaseHeight( 400 ), nRubyHeight( 200 ), eGridType( GRID_NONE ),
+ bRubyTextBelow( 0 ), bPrintGrid( 1 ), bDisplayGrid( 1 ),
+ nBaseWidth(400), bSnapToChars( 1 ), bSquaredMode(1)
+{
+}
+
+SwTextGridItem::~SwTextGridItem()
+{
+}
+
+int SwTextGridItem::operator==( const SfxPoolItem& rAttr ) const
+{
+ OSL_ENSURE( SfxPoolItem::operator==( rAttr ), "keine gleichen Attribute" );
+ return eGridType == ((SwTextGridItem&)rAttr).GetGridType() &&
+ nLines == ((SwTextGridItem&)rAttr).GetLines() &&
+ nBaseHeight == ((SwTextGridItem&)rAttr).GetBaseHeight() &&
+ nRubyHeight == ((SwTextGridItem&)rAttr).GetRubyHeight() &&
+ bRubyTextBelow == ((SwTextGridItem&)rAttr).GetRubyTextBelow() &&
+ bDisplayGrid == ((SwTextGridItem&)rAttr).GetDisplayGrid() &&
+ bPrintGrid == ((SwTextGridItem&)rAttr).GetPrintGrid() &&
+ aColor == ((SwTextGridItem&)rAttr).GetColor() &&
+ nBaseWidth == ((SwTextGridItem&)rAttr).GetBaseWidth() &&
+ bSnapToChars == ((SwTextGridItem&)rAttr).GetSnapToChars() &&
+ bSquaredMode == ((SwTextGridItem&)rAttr).GetSquaredMode();
+}
+
+SfxPoolItem* SwTextGridItem::Clone( SfxItemPool* ) const
+{
+ return new SwTextGridItem( *this );
+}
+
+SwTextGridItem& SwTextGridItem::operator=( const SwTextGridItem& rCpy )
+{
+ aColor = rCpy.GetColor();
+ nLines = rCpy.GetLines();
+ nBaseHeight = rCpy.GetBaseHeight();
+ nRubyHeight = rCpy.GetRubyHeight();
+ eGridType = rCpy.GetGridType();
+ bRubyTextBelow = rCpy.GetRubyTextBelow();
+ bPrintGrid = rCpy.GetPrintGrid();
+ bDisplayGrid = rCpy.GetDisplayGrid();
+ nBaseWidth = rCpy.GetBaseWidth();
+ bSnapToChars = rCpy.GetSnapToChars();
+ bSquaredMode = rCpy.GetSquaredMode();
+
+ return *this;
+}
+
+bool SwTextGridItem::QueryValue( uno::Any& rVal, sal_uInt8 nMemberId ) const
+{
+ bool bRet = true;
+
+ switch( nMemberId & ~CONVERT_TWIPS )
+ {
+ case MID_GRID_COLOR:
+ rVal <<= GetColor().GetColor();
+ break;
+ case MID_GRID_LINES:
+ rVal <<= GetLines();
+ break;
+ case MID_GRID_RUBY_BELOW:
+ rVal.setValue( &bRubyTextBelow, ::getBooleanCppuType() );
+ break;
+ case MID_GRID_PRINT:
+ rVal.setValue( &bPrintGrid, ::getBooleanCppuType() );
+ break;
+ case MID_GRID_DISPLAY:
+ rVal.setValue( &bDisplayGrid, ::getBooleanCppuType() );
+ break;
+ case MID_GRID_BASEHEIGHT:
+ DBG_ASSERT( (nMemberId & CONVERT_TWIPS) != 0,
+ "This value needs TWIPS-MM100 conversion" );
+ rVal <<= (sal_Int32) TWIP_TO_MM100_UNSIGNED(nBaseHeight);
+ break;
+ case MID_GRID_BASEWIDTH:
+ DBG_ASSERT( (nMemberId & CONVERT_TWIPS) != 0,
+ "This value needs TWIPS-MM100 conversion" );
+ rVal <<= (sal_Int32) TWIP_TO_MM100_UNSIGNED(nBaseWidth);
+ break;
+ case MID_GRID_RUBYHEIGHT:
+ DBG_ASSERT( (nMemberId & CONVERT_TWIPS) != 0,
+ "This value needs TWIPS-MM100 conversion" );
+ rVal <<= (sal_Int32)TWIP_TO_MM100_UNSIGNED(nRubyHeight);
+ break;
+ case MID_GRID_TYPE:
+ switch( GetGridType() )
+ {
+ case GRID_NONE:
+ rVal <<= text::TextGridMode::NONE;
+ break;
+ case GRID_LINES_ONLY:
+ rVal <<= text::TextGridMode::LINES;
+ break;
+ case GRID_LINES_CHARS:
+ rVal <<= text::TextGridMode::LINES_AND_CHARS;
+ break;
+ default:
+ OSL_FAIL("unknown SwTextGrid value");
+ bRet = false;
+ break;
+ }
+ break;
+ case MID_GRID_SNAPTOCHARS:
+ rVal.setValue( &bSnapToChars, ::getBooleanCppuType() );
+ break;
+ case MID_GRID_STANDARD_MODE:
+ {
+ sal_Bool bStandardMode = !bSquaredMode;
+ rVal.setValue( &bStandardMode, ::getBooleanCppuType() );
+ }
+ break;
+ default:
+ OSL_FAIL("Unknown SwTextGridItem member");
+ bRet = false;
+ break;
+ }
+
+ return bRet;
+}
+
+bool SwTextGridItem::PutValue( const uno::Any& rVal, sal_uInt8 nMemberId )
+{
+ bool bRet = true;
+ switch( nMemberId & ~CONVERT_TWIPS )
+ {
+ case MID_GRID_COLOR:
+ {
+ sal_Int32 nTmp = 0;
+ bRet = (rVal >>= nTmp);
+ if( bRet )
+ SetColor( Color(nTmp) );
+ }
+ break;
+ case MID_GRID_LINES:
+ {
+ sal_Int16 nTmp = 0;
+ bRet = (rVal >>= nTmp);
+ if( bRet && (nTmp >= 0) )
+ SetLines( (sal_uInt16)nTmp );
+ else
+ bRet = false;
+ }
+ break;
+ case MID_GRID_RUBY_BELOW:
+ SetRubyTextBelow( *(sal_Bool*)rVal.getValue() );
+ break;
+ case MID_GRID_PRINT:
+ SetPrintGrid( *(sal_Bool*)rVal.getValue() );
+ break;
+ case MID_GRID_DISPLAY:
+ SetDisplayGrid( *(sal_Bool*)rVal.getValue() );
+ break;
+ case MID_GRID_BASEHEIGHT:
+ case MID_GRID_BASEWIDTH:
+ case MID_GRID_RUBYHEIGHT:
+ {
+ DBG_ASSERT( (nMemberId & CONVERT_TWIPS) != 0,
+ "This value needs TWIPS-MM100 conversion" );
+ sal_Int32 nTmp = 0;
+ bRet = (rVal >>= nTmp);
+ nTmp = MM100_TO_TWIP( nTmp );
+ if( bRet && (nTmp >= 0) && ( nTmp <= USHRT_MAX) )
+ if( (nMemberId & ~CONVERT_TWIPS) == MID_GRID_BASEHEIGHT )
+ SetBaseHeight( (sal_uInt16)nTmp );
+ else if( (nMemberId & ~CONVERT_TWIPS) == MID_GRID_BASEWIDTH )
+ SetBaseWidth( (sal_uInt16)nTmp );
+ else
+ SetRubyHeight( (sal_uInt16)nTmp );
+ else
+ bRet = false;
+ }
+ break;
+ case MID_GRID_TYPE:
+ {
+ sal_Int16 nTmp = 0;
+ bRet = (rVal >>= nTmp);
+ if( bRet )
+ {
+ switch( nTmp )
+ {
+ case text::TextGridMode::NONE:
+ SetGridType( GRID_NONE );
+ break;
+ case text::TextGridMode::LINES:
+ SetGridType( GRID_LINES_ONLY );
+ break;
+ case text::TextGridMode::LINES_AND_CHARS:
+ SetGridType( GRID_LINES_CHARS );
+ break;
+ default:
+ bRet = false;
+ break;
+ }
+ }
+ break;
+ }
+ case MID_GRID_SNAPTOCHARS:
+ SetSnapToChars( *(sal_Bool*)rVal.getValue() );
+ break;
+ case MID_GRID_STANDARD_MODE:
+ {
+ sal_Bool bStandard = *(sal_Bool*)rVal.getValue();
+ SetSquaredMode( !bStandard );
+ break;
+ }
+ default:
+ OSL_FAIL("Unknown SwTextGridItem member");
+ bRet = false;
+ }
+
+ return bRet;
+}
+
+void SwTextGridItem::SwitchPaperMode(sal_Bool bNew)
+{
+ if( bNew == bSquaredMode )
+ {
+ //same paper mode, not switch
+ return;
+ }
+
+ // use default value when grid is disable
+ if( eGridType == GRID_NONE )
+ {
+ bSquaredMode = bNew;
+ Init();
+ return;
+ }
+
+ if( bSquaredMode )
+ {
+ //switch from "squared mode" to "standard mode"
+ nBaseWidth = nBaseHeight;
+ nBaseHeight = nBaseHeight + nRubyHeight;
+ nRubyHeight = 0;
+ }
+ else
+ {
+ //switch from "standard mode" to "squared mode"
+ nRubyHeight = nBaseHeight/3;
+ nBaseHeight = nBaseHeight - nRubyHeight;
+ nBaseWidth = nBaseHeight;
+ }
+ bSquaredMode = !bSquaredMode;
+}
+
+void SwTextGridItem::Init()
+{
+ if( bSquaredMode )
+ {
+ nLines = 20;
+ nBaseHeight = 400;
+ nRubyHeight = 200;
+ eGridType = GRID_NONE;
+ bRubyTextBelow = 0;
+ bPrintGrid = 1;
+ bDisplayGrid = 1;
+ bSnapToChars = 1;
+ nBaseWidth = 400;
+ }
+ else
+ {
+ nLines = 44;
+ nBaseHeight = 312;
+ nRubyHeight = 0;
+ eGridType = GRID_NONE;
+ bRubyTextBelow = 0;
+ bPrintGrid = 1;
+ bDisplayGrid = 1;
+ nBaseWidth = 210;
+ bSnapToChars = 1;
+
+ //default grid type is line only in CJK env
+ //disable this function due to type area change
+ //if grid type change.
+ //if(SvtCJKOptions().IsAsianTypographyEnabled())
+ //{
+ // bDisplayGrid = 0;
+ // eGridType = GRID_LINES_ONLY;
+ //}
+ }
+}
+// class SwHeaderAndFooterEatSpacingItem
+
+SfxPoolItem* SwHeaderAndFooterEatSpacingItem::Clone( SfxItemPool* ) const
+{
+ return new SwHeaderAndFooterEatSpacingItem( Which(), GetValue() );
+}
+
+
+// class SwFrmFmt
+// Implementierung teilweise inline im hxx
+
+TYPEINIT1( SwFrmFmt, SwFmt );
+IMPL_FIXEDMEMPOOL_NEWDEL_DLL( SwFrmFmt, 20, 20 )
+
+void SwFrmFmt::Modify( const SfxPoolItem* pOld, const SfxPoolItem* pNew )
+{
+ SwFmtHeader *pH = 0;
+ SwFmtFooter *pF = 0;
+
+ sal_uInt16 nWhich = pNew ? pNew->Which() : 0;
+
+ if( RES_ATTRSET_CHG == nWhich )
+ {
+ ((SwAttrSetChg*)pNew)->GetChgSet()->GetItemState(
+ RES_HEADER, sal_False, (const SfxPoolItem**)&pH );
+ ((SwAttrSetChg*)pNew)->GetChgSet()->GetItemState(
+ RES_FOOTER, sal_False, (const SfxPoolItem**)&pF );
+ }
+ else if( RES_HEADER == nWhich )
+ pH = (SwFmtHeader*)pNew;
+ else if( RES_FOOTER == nWhich )
+ pF = (SwFmtFooter*)pNew;
+
+ if( pH && pH->IsActive() && !pH->GetHeaderFmt() )
+ { //Hat er keinen, mach ich ihm einen
+ SwFrmFmt *pFmt = GetDoc()->MakeLayoutFmt( RND_STD_HEADER, 0 );
+ pH->RegisterToFormat( *pFmt );
+ }
+
+ if( pF && pF->IsActive() && !pF->GetFooterFmt() )
+ { //Hat er keinen, mach ich ihm einen
+ SwFrmFmt *pFmt = GetDoc()->MakeLayoutFmt( RND_STD_FOOTER, 0 );
+ pF->RegisterToFormat( *pFmt );
+ }
+
+ // MIB 24.3.98: Modify der Basisklasse muss immer gerufen werden, z.B.
+ // wegen RESET_FMTWRITTEN.
+// if ( GetDepends() )
+ SwFmt::Modify( pOld, pNew );
+
+ if (pOld && (RES_REMOVE_UNO_OBJECT == pOld->Which()))
+ { // invalidate cached uno object
+ SetXObject(uno::Reference<uno::XInterface>(0));
+ }
+}
+
+void SwFrmFmt::RegisterToFormat( SwFmt& rFmt )
+{
+ rFmt.Add( this );
+}
+
+//Vernichtet alle Frms, die in aDepend angemeldet sind.
+
+void SwFrmFmt::DelFrms()
+{
+ SwIterator<SwFrm,SwFmt> aIter( *this );
+ SwFrm * pLast = aIter.First();
+ if( pLast )
+ do {
+ pLast->Cut();
+ delete pLast;
+ } while( 0 != ( pLast = aIter.Next() ));
+}
+
+void SwFrmFmt::MakeFrms()
+{
+ OSL_ENSURE( !this, "Sorry not implemented." );
+}
+
+
+
+SwRect SwFrmFmt::FindLayoutRect( const sal_Bool bPrtArea, const Point* pPoint,
+ const sal_Bool bCalcFrm ) const
+{
+ SwRect aRet;
+ SwFrm *pFrm = 0;
+ if( ISA( SwSectionFmt ) )
+ {
+ // dann den frame::Frame per Node2Layout besorgen
+ SwSectionNode* pSectNd = ((SwSectionFmt*)this)->GetSectionNode();
+ if( pSectNd )
+ {
+ SwNode2Layout aTmp( *pSectNd, pSectNd->GetIndex() - 1 );
+ pFrm = aTmp.NextFrm();
+
+ if( pFrm && !pFrm->KnowsFormat(*this) )
+ {
+ // die Section hat keinen eigenen frame::Frame, also falls
+ // jemand die tatsaechliche Groe?e braucht, so muss das
+ // noch implementier werden, in dem sich vom Ende noch
+ // der entsprechende frame::Frame besorgt wird.
+ // PROBLEM: was passiert bei SectionFrames, die auf unter-
+ // schiedlichen Seiten stehen??
+ if( bPrtArea )
+ aRet = pFrm->Prt();
+ else
+ {
+ aRet = pFrm->Frm();
+ --aRet.Pos().Y();
+ }
+ pFrm = 0; // das Rect ist ja jetzt fertig
+ }
+ }
+ }
+ else
+ {
+ sal_uInt16 nFrmType = RES_FLYFRMFMT == Which() ? FRM_FLY : USHRT_MAX;
+ pFrm = ::GetFrmOfModify( 0, *(SwModify*)this, nFrmType, pPoint,
+ 0, bCalcFrm );
+ }
+
+ if( pFrm )
+ {
+ if( bPrtArea )
+ aRet = pFrm->Prt();
+ else
+ aRet = pFrm->Frm();
+ }
+ return aRet;
+}
+
+SwContact* SwFrmFmt::FindContactObj()
+{
+ return SwIterator<SwContact,SwFmt>::FirstElement( *this );
+}
+
+SdrObject* SwFrmFmt::FindSdrObject()
+{
+ // --> OD 2005-01-06 #i30669# - use method <FindContactObj()> instead of
+ // duplicated code.
+ SwContact* pFoundContact = FindContactObj();
+ return pFoundContact ? pFoundContact->GetMaster() : 0;
+ // <--
+}
+
+SdrObject* SwFrmFmt::FindRealSdrObject()
+{
+ if( RES_FLYFRMFMT == Which() )
+ {
+ Point aNullPt;
+ SwFlyFrm* pFly = (SwFlyFrm*)::GetFrmOfModify( 0, *this, FRM_FLY,
+ &aNullPt, 0, sal_False );
+ return pFly ? pFly->GetVirtDrawObj() : 0;
+ }
+ return FindSdrObject();
+}
+
+
+sal_Bool SwFrmFmt::IsLowerOf( const SwFrmFmt& rFmt ) const
+{
+ //Auch eine Verkettung von Innen nach aussen oder von aussen
+ //nach innen ist nicht zulaessig.
+ SwFlyFrm *pSFly = SwIterator<SwFlyFrm,SwFmt>::FirstElement(*this);
+ if( pSFly )
+ {
+ SwFlyFrm *pAskFly = SwIterator<SwFlyFrm,SwFmt>::FirstElement(rFmt);
+ if( pAskFly )
+ return pSFly->IsLowerOf( pAskFly );
+ }
+
+ // dann mal ueber die Node-Positionen versuchen
+ const SwFmtAnchor* pAnchor = &rFmt.GetAnchor();
+ if ((FLY_AT_PAGE != pAnchor->GetAnchorId()) && pAnchor->GetCntntAnchor())
+ {
+ const SwSpzFrmFmts& rFmts = *GetDoc()->GetSpzFrmFmts();
+ const SwNode* pFlyNd = pAnchor->GetCntntAnchor()->nNode.GetNode().
+ FindFlyStartNode();
+ while( pFlyNd )
+ {
+ // dann ueber den Anker nach oben "hangeln"
+ sal_uInt16 n;
+ for( n = 0; n < rFmts.Count(); ++n )
+ {
+ const SwFrmFmt* pFmt = rFmts[ n ];
+ const SwNodeIndex* pIdx = pFmt->GetCntnt().GetCntntIdx();
+ if( pIdx && pFlyNd == &pIdx->GetNode() )
+ {
+ if( pFmt == this )
+ return sal_True;
+
+ pAnchor = &pFmt->GetAnchor();
+ if ((FLY_AT_PAGE == pAnchor->GetAnchorId()) ||
+ !pAnchor->GetCntntAnchor() )
+ {
+ return sal_False;
+ }
+
+ pFlyNd = pAnchor->GetCntntAnchor()->nNode.GetNode().
+ FindFlyStartNode();
+ break;
+ }
+ }
+ if( n >= rFmts.Count() )
+ {
+ OSL_ENSURE( !this, "Fly-Section aber kein Format gefunden" );
+ return sal_False;
+ }
+ }
+ }
+ return sal_False;
+}
+
+// --> OD 2004-07-27 #i31698#
+SwFrmFmt::tLayoutDir SwFrmFmt::GetLayoutDir() const
+{
+ return SwFrmFmt::HORI_L2R;
+}
+
+void SwFrmFmt::SetLayoutDir( const SwFrmFmt::tLayoutDir )
+{
+ // empty body, because default implementation does nothing
+}
+// <--
+
+// --> OD 2004-08-06 #i28749#
+sal_Int16 SwFrmFmt::GetPositionLayoutDir() const
+{
+ return text::PositionLayoutDir::PositionInLayoutDirOfAnchor;
+}
+void SwFrmFmt::SetPositionLayoutDir( const sal_Int16 )
+{
+ // empty body, because default implementation does nothing
+}
+// <--
+String SwFrmFmt::GetDescription() const
+{
+ return SW_RES(STR_FRAME);
+}
+
+// class SwFlyFrmFmt
+// Implementierung teilweise inline im hxx
+
+TYPEINIT1( SwFlyFrmFmt, SwFrmFmt );
+IMPL_FIXEDMEMPOOL_NEWDEL( SwFlyFrmFmt, 10, 10 )
+
+SwFlyFrmFmt::~SwFlyFrmFmt()
+{
+ SwIterator<SwFlyFrm,SwFmt> aIter( *this );
+ SwFlyFrm * pLast = aIter.First();
+ if( pLast )
+ do {
+ delete pLast;
+ } while( 0 != ( pLast = aIter.Next() ));
+
+ SwIterator<SwFlyDrawContact,SwFmt> a2ndIter( *this );
+ SwFlyDrawContact* pC = a2ndIter.First();
+ if( pC )
+ do {
+ delete pC;
+
+ } while( 0 != ( pC = a2ndIter.Next() ));
+}
+
+//Erzeugen der Frms wenn das Format einen Absatzgebundenen Rahmen beschreibt.
+//MA: 14. Feb. 94, Erzeugen der Frms auch fuer Seitengebundene Rahmen.
+
+void SwFlyFrmFmt::MakeFrms()
+{
+ // gibts ueberhaupt ein Layout ??
+ if( !GetDoc()->GetCurrentViewShell() )
+ return; //swmod 071108//swmod 071225
+
+ SwModify *pModify = 0;
+ // OD 24.07.2003 #111032# - create local copy of anchor attribute for possible changes.
+ SwFmtAnchor aAnchorAttr( GetAnchor() );
+ switch( aAnchorAttr.GetAnchorId() )
+ {
+ case FLY_AS_CHAR:
+ case FLY_AT_PARA:
+ case FLY_AT_CHAR:
+ if( aAnchorAttr.GetCntntAnchor() )
+ {
+ pModify = aAnchorAttr.GetCntntAnchor()->nNode.GetNode().GetCntntNode();
+ }
+ break;
+
+ case FLY_AT_FLY:
+ if( aAnchorAttr.GetCntntAnchor() )
+ {
+ //Erst einmal ueber den Inhalt suchen, weil konstant schnell. Kann
+ //Bei verketteten Rahmen aber auch schief gehen, weil dann evtl.
+ //niemals ein frame::Frame zu dem Inhalt existiert. Dann muss leider noch
+ //die Suche vom StartNode zum FrameFormat sein.
+ SwNodeIndex aIdx( aAnchorAttr.GetCntntAnchor()->nNode );
+ SwCntntNode *pCNd = GetDoc()->GetNodes().GoNext( &aIdx );
+ // --> OD 2009-12-28 #i105535#
+ if ( pCNd == 0 )
+ {
+ pCNd = aAnchorAttr.GetCntntAnchor()->nNode.GetNode().GetCntntNode();
+ }
+ if ( pCNd )
+ // <--
+ {
+ if( SwIterator<SwFrm,SwCntntNode>::FirstElement( *pCNd ) )
+ {
+ pModify = pCNd;
+ }
+ }
+ // --> OD 2009-12-28 #i105535#
+ if ( pModify == 0 )
+ // <--
+ {
+ const SwNodeIndex &rIdx = aAnchorAttr.GetCntntAnchor()->nNode;
+ SwSpzFrmFmts& rFmts = *GetDoc()->GetSpzFrmFmts();
+ for( sal_uInt16 i = 0; i < rFmts.Count(); ++i )
+ {
+ SwFrmFmt* pFlyFmt = rFmts[i];
+ if( pFlyFmt->GetCntnt().GetCntntIdx() &&
+ rIdx == *pFlyFmt->GetCntnt().GetCntntIdx() )
+ {
+ pModify = pFlyFmt;
+ break;
+ }
+ }
+ }
+ }
+ break;
+
+ case FLY_AT_PAGE:
+ {
+ sal_uInt16 nPgNum = aAnchorAttr.GetPageNum();
+ SwPageFrm *pPage = (SwPageFrm*)GetDoc()->GetCurrentLayout()->Lower(); //swmod 080218
+ if( !nPgNum && aAnchorAttr.GetCntntAnchor() )
+ {
+ SwCntntNode *pCNd =
+ aAnchorAttr.GetCntntAnchor()->nNode.GetNode().GetCntntNode();
+ SwIterator<SwFrm,SwCntntNode> aIter( *pCNd );
+ for (SwFrm* pFrm = aIter.First(); pFrm; pFrm = aIter.Next() )
+ {
+ pPage = pFrm->FindPageFrm();
+ if( pPage )
+ {
+ nPgNum = pPage->GetPhyPageNum();
+ // OD 24.07.2003 #111032# - update anchor attribute
+ aAnchorAttr.SetPageNum( nPgNum );
+ aAnchorAttr.SetAnchor( 0 );
+ SetFmtAttr( aAnchorAttr );
+ }
+ break;
+ }
+ }
+ while ( pPage )
+ {
+ if ( pPage->GetPhyPageNum() == nPgNum )
+ {
+ // --> OD 2005-06-09 #i50432# - adjust synopsis of <PlaceFly(..)>
+ pPage->PlaceFly( 0, this );
+ // <--
+ break;
+ }
+ pPage = (SwPageFrm*)pPage->GetNext();
+ }
+ }
+ break;
+ default:
+ break;
+ }
+
+ if( pModify )
+ {
+ SwIterator<SwFrm,SwModify> aIter( *pModify );
+ for( SwFrm *pFrm = aIter.First(); pFrm; pFrm = aIter.Next() )
+ {
+ sal_Bool bAdd = !pFrm->IsCntntFrm() ||
+ !((SwCntntFrm*)pFrm)->IsFollow();
+
+ if ( FLY_AT_FLY == aAnchorAttr.GetAnchorId() && !pFrm->IsFlyFrm() )
+ {
+ // --> OD 2009-12-28 #i105535#
+ // fallback to anchor type at-paragraph, if no fly frame is found.
+// pFrm = pFrm->FindFlyFrm();
+ SwFrm* pFlyFrm = pFrm->FindFlyFrm();
+ if ( pFlyFrm )
+ {
+ pFrm = pFlyFrm;
+ }
+ else
+ {
+ aAnchorAttr.SetType( FLY_AT_PARA );
+ SetFmtAttr( aAnchorAttr );
+ MakeFrms();
+ return;
+ }
+ // <--
+ }
+
+ if( pFrm->GetDrawObjs() )
+ {
+ // --> OD 2004-07-01 #i28701# - new type <SwSortedObjs>
+ SwSortedObjs &rObjs = *pFrm->GetDrawObjs();
+ for( sal_uInt16 i = 0; i < rObjs.Count(); ++i)
+ {
+ // --> OD 2004-07-01 #i28701# - consider changed type of
+ // <SwSortedObjs> entries.
+ SwAnchoredObject* pObj = rObjs[i];
+ if( pObj->ISA(SwFlyFrm) &&
+ (&pObj->GetFrmFmt()) == this )
+ {
+ bAdd = sal_False;
+ break;
+ }
+ }
+ }
+
+ if( bAdd )
+ {
+ SwFlyFrm *pFly = 0;
+ switch( aAnchorAttr.GetAnchorId() )
+ {
+ case FLY_AT_FLY:
+ pFly = new SwFlyLayFrm( this, pFrm, pFrm );
+ break;
+
+ case FLY_AT_PARA:
+ case FLY_AT_CHAR:
+ pFly = new SwFlyAtCntFrm( this, pFrm, pFrm );
+ break;
+
+ case FLY_AS_CHAR:
+ pFly = new SwFlyInCntFrm( this, pFrm, pFrm );
+ break;
+ default:
+ OSL_ENSURE( !this, "Neuer Ankertyp" );
+ break;
+ }
+ pFrm->AppendFly( pFly );
+ SwPageFrm *pPage = pFly->FindPageFrm();
+ if( pPage )
+ ::RegistFlys( pPage, pFly );
+ }
+ }
+ }
+}
+
+SwFlyFrm* SwFlyFrmFmt::GetFrm( const Point* pPoint, const sal_Bool bCalcFrm ) const
+{
+ return (SwFlyFrm*)::GetFrmOfModify( 0, *(SwModify*)this, FRM_FLY,
+ pPoint, 0, bCalcFrm );
+}
+
+SwAnchoredObject* SwFlyFrmFmt::GetAnchoredObj( const Point* pPoint, const sal_Bool bCalcFrm ) const
+{
+ SwFlyFrm* pFlyFrm( GetFrm( pPoint, bCalcFrm ) );
+ if ( pFlyFrm )
+ {
+ return dynamic_cast<SwAnchoredObject*>(pFlyFrm);
+ }
+ else
+ {
+ return 0L;
+ }
+}
+
+
+sal_Bool SwFlyFrmFmt::GetInfo( SfxPoolItem& rInfo ) const
+{
+ switch( rInfo.Which() )
+ {
+ case RES_CONTENT_VISIBLE:
+ {
+ ((SwPtrMsgPoolItem&)rInfo).pObject = SwIterator<SwFrm,SwFmt>::FirstElement( *this );
+ }
+ return sal_False;
+
+ default:
+ return SwFrmFmt::GetInfo( rInfo );
+ }
+ return sal_True;
+}
+
+// --> OD 2009-07-14 #i73249#
+void SwFlyFrmFmt::SetObjTitle( const String& rTitle, bool bBroadcast )
+{
+ SdrObject* pMasterObject = FindSdrObject();
+ OSL_ENSURE( pMasterObject,
+ "<SwNoTxtNode::SetObjTitle(..)> - missing <SdrObject> instance" );
+ if ( !pMasterObject )
+ {
+ return;
+ }
+
+ if( bBroadcast )
+ {
+ SwStringMsgPoolItem aOld( RES_TITLE_CHANGED, pMasterObject->GetTitle() );
+ SwStringMsgPoolItem aNew( RES_TITLE_CHANGED, rTitle );
+ pMasterObject->SetTitle( rTitle );
+ ModifyNotification( &aOld, &aNew );
+ }
+ else
+ {
+ pMasterObject->SetTitle( rTitle );
+ }
+}
+
+const String SwFlyFrmFmt::GetObjTitle() const
+{
+ const SdrObject* pMasterObject = FindSdrObject();
+ OSL_ENSURE( pMasterObject,
+ "<SwFlyFrmFmt::GetObjTitle(..)> - missing <SdrObject> instance" );
+ if ( !pMasterObject )
+ {
+ return aEmptyStr;
+ }
+
+ return pMasterObject->GetTitle();
+}
+
+void SwFlyFrmFmt::SetObjDescription( const String& rDescription, bool bBroadcast )
+{
+ SdrObject* pMasterObject = FindSdrObject();
+ OSL_ENSURE( pMasterObject,
+ "<SwFlyFrmFmt::SetDescription(..)> - missing <SdrObject> instance" );
+ if ( !pMasterObject )
+ {
+ return;
+ }
+
+ if( bBroadcast )
+ {
+ SwStringMsgPoolItem aOld( RES_DESCRIPTION_CHANGED, pMasterObject->GetDescription() );
+ SwStringMsgPoolItem aNew( RES_DESCRIPTION_CHANGED, rDescription );
+ pMasterObject->SetDescription( rDescription );
+ ModifyNotification( &aOld, &aNew );
+ }
+ else
+ {
+ pMasterObject->SetDescription( rDescription );
+ }
+}
+
+const String SwFlyFrmFmt::GetObjDescription() const
+{
+ const SdrObject* pMasterObject = FindSdrObject();
+ OSL_ENSURE( pMasterObject,
+ "<SwNoTxtNode::GetDescription(..)> - missing <SdrObject> instance" );
+ if ( !pMasterObject )
+ {
+ return aEmptyStr;
+ }
+
+ return pMasterObject->GetDescription();
+}
+// <--
+
+/** SwFlyFrmFmt::IsBackgroundTransparent - for #99657#
+
+ OD 22.08.2002 - overloading virtual method and its default implementation,
+ because format of fly frame provides transparent backgrounds.
+ Method determines, if background of fly frame is transparent.
+
+ @author OD
+
+ @return true, if background color is transparent, but not "no fill"
+ or the transparency of a existing background graphic is set.
+*/
+sal_Bool SwFlyFrmFmt::IsBackgroundTransparent() const
+{
+ sal_Bool bReturn = sal_False;
+
+ /// NOTE: If background color is "no fill"/"auto fill" (COL_TRANSPARENT)
+ /// and there is no background graphic, it "inherites" the background
+ /// from its anchor.
+ if ( (GetBackground().GetColor().GetTransparency() != 0) &&
+ (GetBackground().GetColor() != COL_TRANSPARENT)
+ )
+ {
+ bReturn = sal_True;
+ }
+ else
+ {
+ const GraphicObject *pTmpGrf =
+ static_cast<const GraphicObject*>(GetBackground().GetGraphicObject());
+ if ( (pTmpGrf) &&
+ (pTmpGrf->GetAttr().GetTransparency() != 0)
+ )
+ {
+ bReturn = sal_True;
+ }
+ }
+
+ return bReturn;
+}
+
+/** SwFlyFrmFmt::IsBackgroundBrushInherited - for #103898#
+
+ OD 08.10.2002 - method to determine, if the brush for drawing the
+ background is "inherited" from its parent/grandparent.
+ This is the case, if no background graphic is set and the background
+ color is "no fill"/"auto fill"
+ NOTE: condition is "copied" from method <SwFrm::GetBackgroundBrush(..).
+
+ @author OD
+
+ @return true, if background brush is "inherited" from parent/grandparent
+*/
+sal_Bool SwFlyFrmFmt::IsBackgroundBrushInherited() const
+{
+ sal_Bool bReturn = sal_False;
+
+ if ( (GetBackground().GetColor() == COL_TRANSPARENT) &&
+ !(GetBackground().GetGraphicObject()) )
+ {
+ bReturn = sal_True;
+ }
+
+ return bReturn;
+}
+
+// --> OD 2006-02-28 #125892#
+SwHandleAnchorNodeChg::SwHandleAnchorNodeChg( SwFlyFrmFmt& _rFlyFrmFmt,
+ const SwFmtAnchor& _rNewAnchorFmt,
+ SwFlyFrm* _pKeepThisFlyFrm )
+ : mrFlyFrmFmt( _rFlyFrmFmt ),
+ mbAnchorNodeChanged( false )
+{
+ const RndStdIds nNewAnchorType( _rNewAnchorFmt.GetAnchorId() );
+ if ( ((nNewAnchorType == FLY_AT_PARA) ||
+ (nNewAnchorType == FLY_AT_CHAR)) &&
+ _rNewAnchorFmt.GetCntntAnchor() &&
+ _rNewAnchorFmt.GetCntntAnchor()->nNode.GetNode().GetCntntNode() )
+ {
+ const SwFmtAnchor& aOldAnchorFmt( _rFlyFrmFmt.GetAnchor() );
+ if ( aOldAnchorFmt.GetAnchorId() == nNewAnchorType &&
+ aOldAnchorFmt.GetCntntAnchor() &&
+ aOldAnchorFmt.GetCntntAnchor()->nNode.GetNode().GetCntntNode() &&
+ aOldAnchorFmt.GetCntntAnchor()->nNode !=
+ _rNewAnchorFmt.GetCntntAnchor()->nNode )
+ {
+ // determine 'old' number of anchor frames
+ sal_uInt32 nOldNumOfAnchFrm( 0L );
+ SwIterator<SwFrm,SwCntntNode> aOldIter( *(aOldAnchorFmt.GetCntntAnchor()->nNode.GetNode().GetCntntNode()) );
+ for( SwFrm* pOld = aOldIter.First(); pOld; pOld = aOldIter.Next() )
+ {
+ ++nOldNumOfAnchFrm;
+ }
+ // determine 'new' number of anchor frames
+ sal_uInt32 nNewNumOfAnchFrm( 0L );
+ SwIterator<SwFrm,SwCntntNode> aNewIter( *(_rNewAnchorFmt.GetCntntAnchor()->nNode.GetNode().GetCntntNode()) );
+ for( SwFrm* pNew = aNewIter.First(); pNew; pNew = aNewIter.Next() )
+ {
+ ++nNewNumOfAnchFrm;
+ }
+ if ( nOldNumOfAnchFrm != nNewNumOfAnchFrm )
+ {
+ // delete existing fly frames except <_pKeepThisFlyFrm>
+ SwIterator<SwFrm,SwFmt> aIter( mrFlyFrmFmt );
+ SwFrm* pFrm = aIter.First();
+ if ( pFrm )
+ {
+ do {
+ if ( pFrm != _pKeepThisFlyFrm )
+ {
+ pFrm->Cut();
+ delete pFrm;
+ }
+ } while( 0 != ( pFrm = aIter.Next() ));
+ }
+ // indicate, that re-creation of fly frames necessary
+ mbAnchorNodeChanged = true;
+ }
+ }
+ }
+}
+
+SwHandleAnchorNodeChg::~SwHandleAnchorNodeChg()
+{
+ if ( mbAnchorNodeChanged )
+ {
+ mrFlyFrmFmt.MakeFrms();
+ }
+}
+// <--
+// class SwDrawFrmFmt
+// Implementierung teilweise inline im hxx
+
+TYPEINIT1( SwDrawFrmFmt, SwFrmFmt );
+IMPL_FIXEDMEMPOOL_NEWDEL( SwDrawFrmFmt, 10, 10 )
+
+SwDrawFrmFmt::~SwDrawFrmFmt()
+{
+ SwContact *pContact = FindContactObj();
+ delete pContact;
+}
+
+void SwDrawFrmFmt::MakeFrms()
+{
+ SwDrawContact *pContact = (SwDrawContact*)FindContactObj();
+ if ( pContact )
+ pContact->ConnectToLayout();
+}
+
+void SwDrawFrmFmt::DelFrms()
+{
+ SwDrawContact *pContact = (SwDrawContact *)FindContactObj();
+ if ( pContact ) //fuer den Reader und andere Unabwaegbarkeiten.
+ pContact->DisconnectFromLayout();
+}
+
+// --> OD 2004-07-27 #i31698#
+SwFrmFmt::tLayoutDir SwDrawFrmFmt::GetLayoutDir() const
+{
+ return meLayoutDir;
+}
+
+void SwDrawFrmFmt::SetLayoutDir( const SwFrmFmt::tLayoutDir _eLayoutDir )
+{
+ meLayoutDir = _eLayoutDir;
+}
+// <--
+
+// --> OD 2004-08-06 #i28749#
+sal_Int16 SwDrawFrmFmt::GetPositionLayoutDir() const
+{
+ return mnPositionLayoutDir;
+}
+void SwDrawFrmFmt::SetPositionLayoutDir( const sal_Int16 _nPositionLayoutDir )
+{
+ switch ( _nPositionLayoutDir )
+ {
+ case text::PositionLayoutDir::PositionInHoriL2R:
+ case text::PositionLayoutDir::PositionInLayoutDirOfAnchor:
+ {
+ mnPositionLayoutDir = _nPositionLayoutDir;
+ }
+ break;
+ default:
+ {
+ OSL_FAIL( "<SwDrawFrmFmt::SetPositionLayoutDir(..)> - invalid attribute value." );
+ }
+ }
+}
+// <--
+
+String SwDrawFrmFmt::GetDescription() const
+{
+ String aResult;
+ const SdrObject * pSdrObj = FindSdrObject();
+
+ if (pSdrObj)
+ {
+ if (pSdrObj != pSdrObjCached)
+ {
+ SdrObject * pSdrObjCopy = pSdrObj->Clone();
+ SdrUndoNewObj * pSdrUndo = new SdrUndoNewObj(*pSdrObjCopy);
+ sSdrObjCachedComment = pSdrUndo->GetComment();
+
+ delete pSdrUndo;
+
+ pSdrObjCached = pSdrObj;
+ }
+
+ aResult = sSdrObjCachedComment;
+ }
+ else
+ aResult = SW_RES(STR_GRAPHIC);
+
+ return aResult;
+}
+
+IMapObject* SwFrmFmt::GetIMapObject( const Point& rPoint,
+ const SwFlyFrm *pFly ) const
+{
+ const SwFmtURL &rURL = GetURL();
+ if( !rURL.GetMap() )
+ return 0;
+
+ if( !pFly )
+ {
+ pFly = SwIterator<SwFlyFrm,SwFmt>::FirstElement( *this );
+ if( !pFly )
+ return 0;
+ }
+
+ //Orignialgroesse fuer OLE und Grafik ist die TwipSize,
+ //ansonsten die Groesse vom FrmFmt des Fly.
+ const SwFrm *pRef;
+ SwNoTxtNode *pNd = 0;
+ Size aOrigSz;
+ if( pFly->Lower() && pFly->Lower()->IsNoTxtFrm() )
+ {
+ pRef = pFly->Lower();
+ pNd = ((SwCntntFrm*)pRef)->GetNode()->GetNoTxtNode();
+ aOrigSz = pNd->GetTwipSize();
+ }
+ else
+ {
+ pRef = pFly;
+ aOrigSz = pFly->GetFmt()->GetFrmSize().GetSize();
+ }
+
+ if( aOrigSz.Width() != 0 && aOrigSz.Height() != 0 )
+ {
+ Point aPos( rPoint );
+ Size aActSz ( pRef == pFly ? pFly->Frm().SSize() : pRef->Prt().SSize() );
+ const MapMode aSrc ( MAP_TWIP );
+ const MapMode aDest( MAP_100TH_MM );
+ aOrigSz = OutputDevice::LogicToLogic( aOrigSz, aSrc, aDest );
+ aActSz = OutputDevice::LogicToLogic( aActSz, aSrc, aDest );
+ aPos -= pRef->Frm().Pos();
+ aPos -= pRef->Prt().Pos();
+ aPos = OutputDevice::LogicToLogic( aPos, aSrc, aDest );
+ sal_uInt32 nFlags = 0;
+ if ( pFly != pRef && pNd->IsGrfNode() )
+ {
+ const sal_uInt16 nMirror = pNd->GetSwAttrSet().
+ GetMirrorGrf().GetValue();
+ if ( RES_MIRROR_GRAPH_BOTH == nMirror )
+ nFlags = IMAP_MIRROR_HORZ | IMAP_MIRROR_VERT;
+ else if ( RES_MIRROR_GRAPH_VERT == nMirror )
+ nFlags = IMAP_MIRROR_VERT;
+ else if ( RES_MIRROR_GRAPH_HOR == nMirror )
+ nFlags = IMAP_MIRROR_HORZ;
+
+ }
+ return ((ImageMap*)rURL.GetMap())->GetHitIMapObject( aOrigSz,
+ aActSz, aPos, nFlags );
+ }
+
+ return 0;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/layout/calcmove.cxx b/sw/source/core/layout/calcmove.cxx
new file mode 100644
index 000000000000..e3bcf56ee9c4
--- /dev/null
+++ b/sw/source/core/layout/calcmove.cxx
@@ -0,0 +1,2116 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+#include "rootfrm.hxx"
+#include "pagefrm.hxx"
+#include "cntfrm.hxx"
+#include "viewsh.hxx"
+#include "doc.hxx"
+#include "viewimp.hxx"
+#include "viewopt.hxx"
+#include "swtypes.hxx"
+#include "dflyobj.hxx"
+#include "dcontact.hxx"
+#include "flyfrm.hxx"
+#include "frmtool.hxx"
+#include "txtftn.hxx"
+#include "fmtftn.hxx"
+#include <editeng/ulspitem.hxx>
+#include <editeng/keepitem.hxx>
+
+#include <vcl/outdev.hxx>
+#include <fmtfsize.hxx>
+#include <fmtanchr.hxx>
+#include <fmtclbl.hxx>
+
+#include "tabfrm.hxx"
+#include "ftnfrm.hxx"
+#include "txtfrm.hxx"
+#include "pagedesc.hxx"
+#include "ftninfo.hxx"
+#include "sectfrm.hxx"
+#include "dbg_lay.hxx"
+
+// --> OD 2004-06-23 #i28701#
+#include <sortedobjs.hxx>
+#include <layouter.hxx>
+// --> OD 2004-11-01 #i36347#
+#include <flyfrms.hxx>
+// <--
+
+#include <ndtxt.hxx>
+
+//------------------------------------------------------------------------
+// Move-Methoden
+//------------------------------------------------------------------------
+
+/*************************************************************************
+|*
+|* SwCntntFrm::ShouldBwdMoved()
+|*
+|* Beschreibung Returnwert sagt, ob der Frm verschoben werden sollte.
+|*
+|*************************************************************************/
+
+
+sal_Bool SwCntntFrm::ShouldBwdMoved( SwLayoutFrm *pNewUpper, sal_Bool, sal_Bool & )
+{
+ if ( (SwFlowFrm::IsMoveBwdJump() || !IsPrevObjMove()))
+ {
+ //Das zurueckfliessen von Frm's ist leider etwas Zeitintensiv.
+ //Der haufigste Fall ist der, dass dort wo der Frm hinfliessen
+ //moechte die FixSize die gleiche ist, die der Frm selbst hat.
+ //In diesem Fall kann einfach geprueft werden, ob der Frm genug
+ //Platz fuer seine VarSize findet, ist dies nicht der Fall kann
+ //gleich auf das Verschieben verzichtet werden.
+ //Die Pruefung, ob der Frm genug Platz findet fuehrt er selbst
+ //durch, dabei wird beruecksichtigt, dass er sich moeglicherweise
+ //aufspalten kann.
+ //Wenn jedoch die FixSize eine andere ist oder Flys im Spiel sind
+ //(an der alten oder neuen Position) hat alle Prueferei keinen Sinn
+ //der Frm muss dann halt Probehalber verschoben werden (Wenn ueberhaupt
+ //etwas Platz zur Verfuegung steht).
+
+ //Die FixSize der Umgebungen in denen Cntnts herumlungern ist immer
+ //Die Breite.
+
+ //Wenn mehr als ein Blatt zurueckgegangen wurde (z.B. ueberspringen
+ //von Leerseiten), so muss in jedemfall gemoved werden - sonst wuerde,
+ //falls der Frm nicht in das Blatt passt, nicht mehr auf die
+ //dazwischenliegenden Blaetter geachtet werden.
+ sal_uInt8 nMoveAnyway = 0;
+ SwPageFrm * const pNewPage = pNewUpper->FindPageFrm();
+ SwPageFrm *pOldPage = FindPageFrm();
+
+ if ( SwFlowFrm::IsMoveBwdJump() )
+ return sal_True;
+
+ if( IsInFtn() && IsInSct() )
+ {
+ SwFtnFrm* pFtn = FindFtnFrm();
+ SwSectionFrm* pMySect = pFtn->FindSctFrm();
+ if( pMySect && pMySect->IsFtnLock() )
+ {
+ SwSectionFrm *pSect = pNewUpper->FindSctFrm();
+ while( pSect && pSect->IsInFtn() )
+ pSect = pSect->GetUpper()->FindSctFrm();
+ OSL_ENSURE( pSect, "Escaping footnote" );
+ if( pSect != pMySect )
+ return sal_False;
+ }
+ }
+ SWRECTFN( this )
+ SWRECTFNX( pNewUpper )
+ if( Abs( (pNewUpper->Prt().*fnRectX->fnGetWidth)() -
+ (GetUpper()->Prt().*fnRect->fnGetWidth)() ) > 1 )
+ nMoveAnyway = 2; // Damit kommt nur noch ein _WouldFit mit Umhaengen in Frage
+
+ // OD 2004-05-26 #i25904# - do *not* move backward,
+ // if <nMoveAnyway> equals 3 and no space is left in new upper.
+ nMoveAnyway |= BwdMoveNecessary( pOldPage, Frm() );
+ {
+ const IDocumentSettingAccess* pIDSA = pNewPage->GetFmt()->getIDocumentSettingAccess();
+ SwTwips nSpace = 0;
+ SwRect aRect( pNewUpper->Prt() );
+ aRect.Pos() += pNewUpper->Frm().Pos();
+ const SwFrm *pPrevFrm = pNewUpper->Lower();
+ while ( pPrevFrm )
+ {
+ SwTwips nNewTop = (pPrevFrm->Frm().*fnRectX->fnGetBottom)();
+ // OD 2004-03-01 #106629#:
+ // consider lower spacing of last frame in a table cell
+ {
+ // check, if last frame is inside table and if it includes
+ // its lower spacing.
+ if ( !pPrevFrm->GetNext() && pPrevFrm->IsInTab() &&
+ pIDSA->get(IDocumentSettingAccess::ADD_PARA_SPACING_TO_TABLE_CELLS) )
+ {
+ const SwFrm* pLastFrm = pPrevFrm;
+ // if last frame is a section, take its last content
+ if ( pPrevFrm->IsSctFrm() )
+ {
+ pLastFrm = static_cast<const SwSectionFrm*>(pPrevFrm)->FindLastCntnt();
+ if ( pLastFrm &&
+ pLastFrm->FindTabFrm() != pPrevFrm->FindTabFrm() )
+ {
+ pLastFrm = pLastFrm->FindTabFrm();
+ }
+ }
+
+ if ( pLastFrm )
+ {
+ SwBorderAttrAccess aAccess( SwFrm::GetCache(), pLastFrm );
+ const SwBorderAttrs& rAttrs = *aAccess.Get();
+ nNewTop -= rAttrs.GetULSpace().GetLower();
+ }
+ }
+ }
+ (aRect.*fnRectX->fnSetTop)( nNewTop );
+
+ pPrevFrm = pPrevFrm->GetNext();
+ }
+
+ nMoveAnyway |= BwdMoveNecessary( pNewPage, aRect);
+
+ //determine space left in new upper frame
+ nSpace = (aRect.*fnRectX->fnGetHeight)();
+ const ViewShell *pSh = pNewUpper->getRootFrm()->GetCurrShell();
+ if ( IsInFtn() ||
+ (pSh && pSh->GetViewOptions()->getBrowseMode()) ||
+ pNewUpper->IsCellFrm() ||
+ ( pNewUpper->IsInSct() && ( pNewUpper->IsSctFrm() ||
+ ( pNewUpper->IsColBodyFrm() &&
+ !pNewUpper->GetUpper()->GetPrev() &&
+ !pNewUpper->GetUpper()->GetNext() ) ) ) )
+ nSpace += pNewUpper->Grow( LONG_MAX, sal_True );
+
+ if ( nMoveAnyway < 3 )
+ {
+ if ( nSpace )
+ {
+ //Keine Beruecksichtigung der Fussnoten die an dem Absatz
+ //kleben, denn dies wuerde extrem unuebersichtlichen Code
+ //beduerfen (wg. Beruecksichtung der Breiten und vor allem
+ //der Flys, die ja wieder Einfluss auf die Fussnoten nehmen...).
+
+ // _WouldFit kann bei gleicher Breite und _nur_ selbst verankerten Flys
+ // befragt werden.
+ // _WouldFit kann auch gefragt werden, wenn _nur_ fremdverankerte Flys vorliegen,
+ // dabei ist sogar die Breite egal, da ein TestFormat in der neuen Umgebung
+ // vorgenommen wird.
+ // --> OD 2007-11-26 #b6614158#
+ const sal_uInt8 nBwdMoveNecessaryResult =
+ BwdMoveNecessary( pNewPage, aRect);
+ const bool bObjsInNewUpper( nBwdMoveNecessaryResult == 2 ||
+ nBwdMoveNecessaryResult == 3 );
+
+ return _WouldFit( nSpace, pNewUpper, nMoveAnyway == 2,
+ bObjsInNewUpper );
+ // <--
+ }
+ //Bei einem spaltigen Bereichsfrischling kann _WouldFit kein
+ //brauchbares Ergebnis liefern, also muessen wir wirklich
+ //zurueckfliessen
+ else if( pNewUpper->IsInSct() && pNewUpper->IsColBodyFrm() &&
+ !(pNewUpper->Prt().*fnRectX->fnGetWidth)() &&
+ ( pNewUpper->GetUpper()->GetPrev() ||
+ pNewUpper->GetUpper()->GetNext() ) )
+ return sal_True;
+ else
+ return sal_False; // Kein Platz, dann ist es sinnlos, zurueckzufliessen
+ }
+ else
+ {
+ // OD 2004-05-26 #i25904# - check for space left in new upper
+ if ( nSpace )
+ return sal_True;
+ else
+ return sal_False;
+ }
+ }
+ }
+ return sal_False;
+}
+
+//------------------------------------------------------------------------
+// Calc-Methoden
+//------------------------------------------------------------------------
+
+/*************************************************************************
+|*
+|* SwFrm::Prepare()
+|*
+|* Beschreibung Bereitet den Frm auf die 'Formatierung' (MakeAll())
+|* vor. Diese Methode dient dazu auf dem Stack Platz einzusparen,
+|* denn zur Positionsberechnung des Frm muss sichergestellt sein, dass
+|* die Position von Upper und Prev gueltig sind, mithin also ein
+|* rekursiver Aufruf (Schleife waere relativ teuer, da selten notwendig).
+|* Jeder Aufruf von MakeAll verbraucht aber ca. 500Byte Stack -
+|* das Ende ist leicht abzusehen. _Prepare benoetigt nur wenig Stack,
+|* deshalb solle der Rekursive Aufruf hier kein Problem sein.
+|* Ein weiterer Vorteil ist, das eines schoenen Tages das _Prepare und
+|* damit die Formatierung von Vorgaengern umgangen werden kann.
+|* So kann evtl. mal 'schnell' an's Dokumentende gesprungen werden.
+|*
+|*************************************************************************/
+//Zwei kleine Freundschaften werden hier zu einem Geheimbund.
+inline void PrepareLock( SwFlowFrm *pTab )
+{
+ pTab->LockJoin();
+}
+inline void PrepareUnlock( SwFlowFrm *pTab )
+{
+ pTab->UnlockJoin();
+
+}
+
+// hopefully, one day this function simply will return 'false'
+bool lcl_IsCalcUpperAllowed( const SwFrm& rFrm )
+{
+ return !rFrm.GetUpper()->IsSctFrm() &&
+ !rFrm.GetUpper()->IsFooterFrm() &&
+ // --> OD 2004-11-02 #i23129#, #i36347# - no format of upper Writer fly frame
+ !rFrm.GetUpper()->IsFlyFrm() &&
+ // <--
+ !( rFrm.GetUpper()->IsTabFrm() && rFrm.GetUpper()->GetUpper()->IsInTab() ) &&
+ !( rFrm.IsTabFrm() && rFrm.GetUpper()->IsInTab() );
+}
+
+void SwFrm::PrepareMake()
+{
+ StackHack aHack;
+ if ( GetUpper() )
+ {
+ if ( lcl_IsCalcUpperAllowed( *this ) )
+ GetUpper()->Calc();
+ OSL_ENSURE( GetUpper(), ":-( Layoutgeruest wackelig (Upper wech)." );
+ if ( !GetUpper() )
+ return;
+
+ const sal_Bool bCnt = IsCntntFrm();
+ const sal_Bool bTab = IsTabFrm();
+ sal_Bool bNoSect = IsInSct();
+ sal_Bool bOldTabLock = sal_False, bFoll = sal_False;
+ SwFlowFrm* pThis = bCnt ? (SwCntntFrm*)this : NULL;
+
+ if ( bTab )
+ {
+ pThis = (SwTabFrm*)this;
+ bOldTabLock = ((SwTabFrm*)this)->IsJoinLocked();
+ ::PrepareLock( (SwTabFrm*)this );
+ bFoll = pThis->IsFollow();
+ }
+ else if( IsSctFrm() )
+ {
+ pThis = (SwSectionFrm*)this;
+ bFoll = pThis->IsFollow();
+ bNoSect = sal_False;
+ }
+ else if ( bCnt && sal_True == (bFoll = pThis->IsFollow()) &&
+ GetPrev() )
+ {
+ //Wenn der Master gereade ein CalcFollow ruft braucht die Kette
+ //nicht durchlaufen werden. Das spart Zeit und vermeidet Probleme.
+ if ( ((SwTxtFrm*)((SwTxtFrm*)this)->FindMaster())->IsLocked() )
+ {
+ MakeAll();
+ return;
+ }
+ }
+
+ // --> OD 2005-03-04 #i44049# - no format of previous frame, if current
+ // frame is a table frame and its previous frame wants to keep with it.
+ const bool bFormatPrev = !bTab ||
+ !GetPrev() ||
+ !GetPrev()->GetAttrSet()->GetKeep().GetValue();
+ if ( bFormatPrev )
+ {
+ SwFrm *pFrm = GetUpper()->Lower();
+ while ( pFrm != this )
+ {
+ OSL_ENSURE( pFrm, ":-( Layoutgeruest wackelig (this not found)." );
+ if ( !pFrm )
+ return; //Oioioioi ...
+
+ if ( !pFrm->IsValid() )
+ {
+ //Ein kleiner Eingriff der hoffentlich etwas zur Verbesserung
+ //der Stabilitaet beitraegt:
+ //Wenn ich Follow _und_ Nachbar eines Frms vor mir bin,
+ //so wuerde dieser mich beim Formatieren deleten; wie jeder
+ //leicht sehen kann waere dies eine etwas unuebersichtliche
+ //Situation die es zu vermeiden gilt.
+ if ( bFoll && pFrm->IsFlowFrm() &&
+ (SwFlowFrm::CastFlowFrm(pFrm))->IsAnFollow( pThis ) )
+ break;
+
+ //MA: 24. Mar. 94, Calc wuerde doch nur wieder in ein _Prepare laufen und so
+ //die ganze Kette nocheinmal abhuenern.
+ // pFrm->Calc();
+ pFrm->MakeAll();
+ if( IsSctFrm() && !((SwSectionFrm*)this)->GetSection() )
+ break;
+ }
+ //Die Kette kann bei CntntFrms waehrend des durchlaufens
+ //aufgebrochen werden, deshalb muss der Nachfolger etwas
+ //umstaendlich ermittelt werden. However, irgendwann _muss_
+ //ich wieder bei mir selbst ankommen.
+ pFrm = pFrm->FindNext();
+
+ //Wenn wir in einem SectionFrm gestartet sind, koennen wir durch die
+ //MakeAll-Aufrufe in einen Section-Follow gewandert sein.
+ //FindNext liefert allerdings den SectionFrm, nicht seinen Inhalt.
+ // => wir finden uns selbst nicht mehr!
+ if( bNoSect && pFrm && pFrm->IsSctFrm() )
+ {
+ SwFrm* pCnt = ((SwSectionFrm*)pFrm)->ContainsAny();
+ if( pCnt )
+ pFrm = pCnt;
+ }
+ }
+ OSL_ENSURE( GetUpper(), "Layoutgeruest wackelig (Upper wech II)." );
+ if ( !GetUpper() )
+ return;
+
+ if ( lcl_IsCalcUpperAllowed( *this ) )
+ GetUpper()->Calc();
+
+ OSL_ENSURE( GetUpper(), "Layoutgeruest wackelig (Upper wech III)." );
+ }
+
+ if ( bTab && !bOldTabLock )
+ ::PrepareUnlock( (SwTabFrm*)this );
+ }
+ MakeAll();
+}
+
+void SwFrm::OptPrepareMake()
+{
+ // --> OD 2004-11-02 #i23129#, #i36347# - no format of upper Writer fly frame
+ if ( GetUpper() && !GetUpper()->IsFooterFrm() &&
+ !GetUpper()->IsFlyFrm() )
+ // <--
+ {
+ GetUpper()->Calc();
+ OSL_ENSURE( GetUpper(), ":-( Layoutgeruest wackelig (Upper wech)." );
+ if ( !GetUpper() )
+ return;
+ }
+ if ( GetPrev() && !GetPrev()->IsValid() )
+ PrepareMake();
+ else
+ {
+ StackHack aHack;
+ MakeAll();
+ }
+}
+
+
+
+void SwFrm::PrepareCrsr()
+{
+ StackHack aHack;
+ if( GetUpper() && !GetUpper()->IsSctFrm() )
+ {
+ GetUpper()->PrepareCrsr();
+ GetUpper()->Calc();
+
+ OSL_ENSURE( GetUpper(), ":-( Layoutgeruest wackelig (Upper wech)." );
+ if ( !GetUpper() )
+ return;
+
+ const sal_Bool bCnt = IsCntntFrm();
+ const sal_Bool bTab = IsTabFrm();
+ sal_Bool bNoSect = IsInSct();
+
+ sal_Bool bOldTabLock = sal_False, bFoll;
+ SwFlowFrm* pThis = bCnt ? (SwCntntFrm*)this : NULL;
+
+ if ( bTab )
+ {
+ bOldTabLock = ((SwTabFrm*)this)->IsJoinLocked();
+ ::PrepareLock( (SwTabFrm*)this );
+ pThis = (SwTabFrm*)this;
+ }
+ else if( IsSctFrm() )
+ {
+ pThis = (SwSectionFrm*)this;
+ bNoSect = sal_False;
+ }
+ bFoll = pThis && pThis->IsFollow();
+
+ SwFrm *pFrm = GetUpper()->Lower();
+ while ( pFrm != this )
+ {
+ OSL_ENSURE( pFrm, ":-( Layoutgeruest wackelig (this not found)." );
+ if ( !pFrm )
+ return; //Oioioioi ...
+
+ if ( !pFrm->IsValid() )
+ {
+ //Ein kleiner Eingriff der hoffentlich etwas zur Verbesserung
+ //der Stabilitaet beitraegt:
+ //Wenn ich Follow _und_ Nachbar eines Frms vor mir bin,
+ //so wuerde dieser mich beim Formatieren deleten; wie jeder
+ //leicht sehen kann waere dies eine etwas unuebersichtliche
+ //Situation die es zu vermeiden gilt.
+ if ( bFoll && pFrm->IsFlowFrm() &&
+ (SwFlowFrm::CastFlowFrm(pFrm))->IsAnFollow( pThis ) )
+ break;
+
+ pFrm->MakeAll();
+ }
+ //Die Kette kann bei CntntFrms waehrend des durchlaufens
+ //aufgebrochen werden, deshalb muss der Nachfolger etwas
+ //umstaendlich ermittelt werden. However, irgendwann _muss_
+ //ich wieder bei mir selbst ankommen.
+ pFrm = pFrm->FindNext();
+ if( bNoSect && pFrm && pFrm->IsSctFrm() )
+ {
+ SwFrm* pCnt = ((SwSectionFrm*)pFrm)->ContainsAny();
+ if( pCnt )
+ pFrm = pCnt;
+ }
+ }
+ OSL_ENSURE( GetUpper(), "Layoutgeruest wackelig (Upper wech II)." );
+ if ( !GetUpper() )
+ return;
+
+ GetUpper()->Calc();
+
+ OSL_ENSURE( GetUpper(), "Layoutgeruest wackelig (Upper wech III)." );
+
+ if ( bTab && !bOldTabLock )
+ ::PrepareUnlock( (SwTabFrm*)this );
+ }
+ Calc();
+}
+
+/*************************************************************************
+|*
+|* SwFrm::MakePos()
+|*
+|*************************************************************************/
+
+// Hier wird GetPrev() zurueckgegeben, allerdings werden
+// dabei leere SectionFrms ueberlesen
+SwFrm* lcl_Prev( SwFrm* pFrm, sal_Bool bSectPrv = sal_True )
+{
+ SwFrm* pRet = pFrm->GetPrev();
+ if( !pRet && pFrm->GetUpper() && pFrm->GetUpper()->IsSctFrm() &&
+ bSectPrv && !pFrm->IsColumnFrm() )
+ pRet = pFrm->GetUpper()->GetPrev();
+ while( pRet && pRet->IsSctFrm() &&
+ !((SwSectionFrm*)pRet)->GetSection() )
+ pRet = pRet->GetPrev();
+ return pRet;
+}
+
+SwFrm* lcl_NotHiddenPrev( SwFrm* pFrm )
+{
+ SwFrm *pRet = pFrm;
+ do
+ {
+ pRet = lcl_Prev( pRet );
+ } while ( pRet && pRet->IsTxtFrm() && ((SwTxtFrm*)pRet)->IsHiddenNow() );
+ return pRet;
+}
+
+void SwFrm::MakePos()
+{
+ if ( !bValidPos )
+ {
+ bValidPos = sal_True;
+ sal_Bool bUseUpper = sal_False;
+ SwFrm* pPrv = lcl_Prev( this );
+ if ( pPrv &&
+ ( !pPrv->IsCntntFrm() ||
+ ( ((SwCntntFrm*)pPrv)->GetFollow() != this ) )
+ )
+ {
+ if ( !StackHack::IsLocked() &&
+ ( !IsInSct() || IsSctFrm() ) &&
+ !pPrv->IsSctFrm() &&
+ !pPrv->GetAttrSet()->GetKeep().GetValue()
+ )
+ {
+ pPrv->Calc(); //hierbei kann der Prev verschwinden!
+ }
+ else if ( pPrv->Frm().Top() == 0 )
+ {
+ bUseUpper = sal_True;
+ }
+ }
+
+ pPrv = lcl_Prev( this, sal_False );
+ sal_uInt16 nMyType = GetType();
+ SWRECTFN( ( IsCellFrm() && GetUpper() ? GetUpper() : this ) )
+ if ( !bUseUpper && pPrv )
+ {
+ aFrm.Pos( pPrv->Frm().Pos() );
+ if( FRM_NEIGHBOUR & nMyType )
+ {
+ sal_Bool bR2L = IsRightToLeft();
+ if( bR2L )
+ (aFrm.*fnRect->fnSetPosX)( (aFrm.*fnRect->fnGetLeft)() -
+ (aFrm.*fnRect->fnGetWidth)() );
+ else
+ (aFrm.*fnRect->fnSetPosX)( (aFrm.*fnRect->fnGetLeft)() +
+ (pPrv->Frm().*fnRect->fnGetWidth)() );
+
+ // cells may now leave their uppers
+ if( bVert && FRM_CELL & nMyType && !bReverse )
+ aFrm.Pos().X() -= aFrm.Width() -pPrv->Frm().Width();
+ }
+ else if( bVert && FRM_NOTE_VERT & nMyType )
+ {
+ if( bReverse )
+ aFrm.Pos().X() += pPrv->Frm().Width();
+ else
+ //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin
+ {
+ if ( bVertL2R )
+ aFrm.Pos().X() += pPrv->Frm().Width();
+ else
+ aFrm.Pos().X() -= aFrm.Width();
+ }
+ }
+ else
+ aFrm.Pos().Y() += pPrv->Frm().Height();
+ }
+ else if ( GetUpper() )
+ {
+ // OD 15.10.2002 #103517# - add safeguard for <SwFooterFrm::Calc()>
+ // If parent frame is a footer frame and its <ColLocked()>, then
+ // do *not* calculate it.
+ // NOTE: Footer frame is <ColLocked()> during its
+ // <FormatSize(..)>, which is called from <Format(..)>, which
+ // is called from <MakeAll()>, which is called from <Calc()>.
+ // --> OD 2005-11-17 #i56850#
+ // - no format of upper Writer fly frame, which is anchored
+ // at-paragraph or at-character.
+ if ( !GetUpper()->IsTabFrm() &&
+ !( IsTabFrm() && GetUpper()->IsInTab() ) &&
+ !GetUpper()->IsSctFrm() &&
+ !dynamic_cast<SwFlyAtCntFrm*>(GetUpper()) &&
+ !( GetUpper()->IsFooterFrm() &&
+ GetUpper()->IsColLocked() )
+ )
+ {
+ GetUpper()->Calc();
+ }
+ // <--
+ pPrv = lcl_Prev( this, sal_False );
+ if ( !bUseUpper && pPrv )
+ {
+ aFrm.Pos( pPrv->Frm().Pos() );
+ if( FRM_NEIGHBOUR & nMyType )
+ {
+ sal_Bool bR2L = IsRightToLeft();
+ if( bR2L )
+ (aFrm.*fnRect->fnSetPosX)( (aFrm.*fnRect->fnGetLeft)() -
+ (aFrm.*fnRect->fnGetWidth)() );
+ else
+ (aFrm.*fnRect->fnSetPosX)( (aFrm.*fnRect->fnGetLeft)() +
+ (pPrv->Frm().*fnRect->fnGetWidth)() );
+
+ // cells may now leave their uppers
+ if( bVert && FRM_CELL & nMyType && !bReverse )
+ aFrm.Pos().X() -= aFrm.Width() -pPrv->Frm().Width();
+ }
+ else if( bVert && FRM_NOTE_VERT & nMyType )
+ {
+ if( bReverse )
+ aFrm.Pos().X() += pPrv->Frm().Width();
+ else
+ aFrm.Pos().X() -= aFrm.Width();
+ }
+ else
+ aFrm.Pos().Y() += pPrv->Frm().Height();
+ }
+ else
+ {
+ aFrm.Pos( GetUpper()->Frm().Pos() );
+ aFrm.Pos() += GetUpper()->Prt().Pos();
+ if( FRM_NEIGHBOUR & nMyType && IsRightToLeft() )
+ {
+ if( bVert )
+ aFrm.Pos().Y() += GetUpper()->Prt().Height()
+ - aFrm.Height();
+ else
+ aFrm.Pos().X() += GetUpper()->Prt().Width()
+ - aFrm.Width();
+ }
+ //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin
+ else if( bVert && !bVertL2R && FRM_NOTE_VERT & nMyType && !bReverse )
+ aFrm.Pos().X() -= aFrm.Width() - GetUpper()->Prt().Width();
+ }
+ }
+ else
+ aFrm.Pos().X() = aFrm.Pos().Y() = 0;
+ //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin
+ if( IsBodyFrm() && bVert && !bVertL2R && !bReverse && GetUpper() )
+ aFrm.Pos().X() += GetUpper()->Prt().Width() - aFrm.Width();
+ bValidPos = sal_True;
+ }
+}
+
+/*************************************************************************
+|*
+|* SwPageFrm::MakeAll()
+|*
+|*************************************************************************/
+// --> OD 2004-07-01 #i28701# - new type <SwSortedObjs>
+void lcl_CheckObjects( SwSortedObjs* pSortedObjs, SwFrm* pFrm, long& rBot )
+{
+ //Und dann kann es natuerlich noch Absatzgebundene
+ //Rahmen geben, die unterhalb ihres Absatzes stehen.
+ long nMax = 0;
+ for ( sal_uInt16 i = 0; i < pSortedObjs->Count(); ++i )
+ {
+ // --> OD 2004-07-01 #i28701# - consider changed type of <SwSortedObjs>
+ // entries.
+ SwAnchoredObject* pObj = (*pSortedObjs)[i];
+ long nTmp = 0;
+ if ( pObj->ISA(SwFlyFrm) )
+ {
+ SwFlyFrm *pFly = static_cast<SwFlyFrm*>(pObj);
+ if( pFly->Frm().Top() != WEIT_WECH &&
+ ( pFrm->IsPageFrm() ? pFly->IsFlyLayFrm() :
+ ( pFly->IsFlyAtCntFrm() &&
+ ( pFrm->IsBodyFrm() ? pFly->GetAnchorFrm()->IsInDocBody() :
+ pFly->GetAnchorFrm()->IsInFtn() ) ) ) )
+ {
+ nTmp = pFly->Frm().Bottom();
+ }
+ }
+ else
+ nTmp = pObj->GetObjRect().Bottom();
+ nMax = Max( nTmp, nMax );
+ // <--
+ }
+ ++nMax; //Unterkante vs. Hoehe!
+ rBot = Max( rBot, nMax );
+}
+
+void SwPageFrm::MakeAll()
+{
+ PROTOCOL_ENTER( this, PROT_MAKEALL, 0, 0 )
+
+ const SwRect aOldRect( Frm() ); //Anpassung der Root-Groesse
+ const SwLayNotify aNotify( this ); //uebernimmt im DTor die Benachrichtigung
+ SwBorderAttrAccess *pAccess = 0;
+ const SwBorderAttrs*pAttrs = 0;
+
+ while ( !bValidPos || !bValidSize || !bValidPrtArea )
+ {
+ if ( !bValidPos )
+ {
+ // PAGES01
+ bValidPos = sal_True; // positioning of the pages is taken care of by the root frame
+ }
+
+ if ( !bValidSize || !bValidPrtArea )
+ {
+ if ( IsEmptyPage() )
+ {
+ Frm().Width( 0 ); Prt().Width( 0 );
+ Frm().Height( 0 ); Prt().Height( 0 );
+ Prt().Left( 0 ); Prt().Top( 0 );
+ bValidSize = bValidPrtArea = sal_True;
+ }
+ else
+ {
+ if ( !pAccess )
+ {
+ pAccess = new SwBorderAttrAccess( SwFrm::GetCache(), this );
+ pAttrs = pAccess->Get();
+ }
+ //Bei der BrowseView gelten feste Einstellungen.
+ ViewShell *pSh = getRootFrm()->GetCurrShell();
+ if ( pSh && pSh->GetViewOptions()->getBrowseMode() )
+ {
+ const Size aBorder = pSh->GetOut()->PixelToLogic( pSh->GetBrowseBorder() );
+ const long nTop = pAttrs->CalcTopLine() + aBorder.Height();
+ const long nBottom = pAttrs->CalcBottomLine()+ aBorder.Height();
+
+ long nWidth = GetUpper() ? ((SwRootFrm*)GetUpper())->GetBrowseWidth() : 0;
+ if ( nWidth < pSh->GetBrowseWidth() )
+ nWidth = pSh->GetBrowseWidth();
+ nWidth += + 2 * aBorder.Width();
+/*
+ long nWidth = GetUpper() ? ((SwRootFrm*)GetUpper())->GetBrowseWidth() + 2 * aBorder.Width() : 0;
+ if ( nWidth < pSh->VisArea().Width() )
+ nWidth = pSh->VisArea().Width(); */
+
+ nWidth = Max( nWidth, 2L * aBorder.Width() + 4L*MM50 );
+ Frm().Width( nWidth );
+
+ SwLayoutFrm *pBody = FindBodyCont();
+ if ( pBody && pBody->Lower() && pBody->Lower()->IsColumnFrm() )
+ {
+ //Fuer Spalten gilt eine feste Hoehe
+ Frm().Height( pAttrs->GetSize().Height() );
+ }
+ else
+ {
+ //Fuer Seiten ohne Spalten bestimmt der Inhalt die
+ //Groesse.
+ long nBot = Frm().Top() + nTop;
+ SwFrm *pFrm = Lower();
+ while ( pFrm )
+ {
+ long nTmp = 0;
+ SwFrm *pCnt = ((SwLayoutFrm*)pFrm)->ContainsAny();
+ while ( pCnt && (pCnt->GetUpper() == pFrm ||
+ ((SwLayoutFrm*)pFrm)->IsAnLower( pCnt )))
+ {
+ nTmp += pCnt->Frm().Height();
+ if( pCnt->IsTxtFrm() &&
+ ((SwTxtFrm*)pCnt)->IsUndersized() )
+ nTmp += ((SwTxtFrm*)pCnt)->GetParHeight()
+ - pCnt->Prt().Height();
+ else if( pCnt->IsSctFrm() &&
+ ((SwSectionFrm*)pCnt)->IsUndersized() )
+ nTmp += ((SwSectionFrm*)pCnt)->Undersize();
+ pCnt = pCnt->FindNext();
+ }
+ // OD 29.10.2002 #97265# - consider invalid body frame properties
+ if ( pFrm->IsBodyFrm() &&
+ ( !pFrm->GetValidSizeFlag() ||
+ !pFrm->GetValidPrtAreaFlag() ) &&
+ ( pFrm->Frm().Height() < pFrm->Prt().Height() )
+ )
+ {
+ nTmp = Min( nTmp, pFrm->Frm().Height() );
+ }
+ else
+ {
+ // OD 30.10.2002 #97265# - assert invalid lower property
+ OSL_ENSURE( !(pFrm->Frm().Height() < pFrm->Prt().Height()),
+ "SwPageFrm::MakeAll(): Lower with frame height < printing height" );
+ nTmp += pFrm->Frm().Height() - pFrm->Prt().Height();
+ }
+ if ( !pFrm->IsBodyFrm() )
+ nTmp = Min( nTmp, pFrm->Frm().Height() );
+ nBot += nTmp;
+ // Hier werden die absatzgebundenen Objekte ueberprueft,
+ // ob sie ueber den Body/FtnCont hinausragen.
+ if( pSortedObjs && !pFrm->IsHeaderFrm() &&
+ !pFrm->IsFooterFrm() )
+ lcl_CheckObjects( pSortedObjs, pFrm, nBot );
+ pFrm = pFrm->GetNext();
+ }
+ nBot += nBottom;
+ //Und die Seitengebundenen
+ if ( pSortedObjs )
+ lcl_CheckObjects( pSortedObjs, this, nBot );
+ nBot -= Frm().Top();
+ // --> OD 2004-11-10 #i35143# - If second page frame
+ // exists, the first page doesn't have to fulfill the
+ // visible area.
+ if ( !GetPrev() && !GetNext() )
+ // <--
+ {
+ nBot = Max( nBot, pSh->VisArea().Height() );
+ }
+ // --> OD 2004-11-10 #i35143# - Assure, that the page
+ // doesn't exceed the defined browse height.
+ Frm().Height( Min( nBot, BROWSE_HEIGHT ) );
+ // <--
+ }
+ Prt().Left ( pAttrs->CalcLeftLine() + aBorder.Width() );
+ Prt().Top ( nTop );
+ Prt().Width( Frm().Width() - ( Prt().Left()
+ + pAttrs->CalcRightLine() + aBorder.Width() ) );
+ Prt().Height( Frm().Height() - (nTop + nBottom) );
+ bValidSize = bValidPrtArea = sal_True;
+ }
+ else
+ { //FixSize einstellen, bei Seiten nicht vom Upper sondern vom
+ //Attribut vorgegeben.
+ Frm().SSize( pAttrs->GetSize() );
+ Format( pAttrs );
+ }
+ }
+ }
+ } //while ( !bValidPos || !bValidSize || !bValidPrtArea )
+ delete pAccess;
+
+ // PAGES01
+ if ( Frm() != aOldRect && GetUpper() )
+ static_cast<SwRootFrm*>(GetUpper())->CheckViewLayout( 0, 0 );
+
+#if OSL_DEBUG_LEVEL > 1
+ //Der Upper (Root) muss mindestens so breit
+ //sein, dass er die breiteste Seite aufnehmen kann.
+ if ( GetUpper() )
+ {
+ OSL_ENSURE( GetUpper()->Prt().Width() >= aFrm.Width(), "Rootsize" );
+ }
+#endif
+}
+
+/*************************************************************************
+|*
+|* SwLayoutFrm::MakeAll()
+|*
+|*************************************************************************/
+
+
+void SwLayoutFrm::MakeAll()
+{
+ PROTOCOL_ENTER( this, PROT_MAKEALL, 0, 0 )
+
+ //uebernimmt im DTor die Benachrichtigung
+ const SwLayNotify aNotify( this );
+ sal_Bool bVert = IsVertical();
+ //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin
+ SwRectFn fnRect = ( IsNeighbourFrm() == bVert )? fnRectHori : ( IsVertLR() ? fnRectVertL2R : fnRectVert );
+
+ SwBorderAttrAccess *pAccess = 0;
+ const SwBorderAttrs*pAttrs = 0;
+
+ while ( !bValidPos || !bValidSize || !bValidPrtArea )
+ {
+ if ( !bValidPos )
+ MakePos();
+
+ if ( GetUpper() )
+ {
+ // NEW TABLES
+ if ( IsLeaveUpperAllowed() )
+ {
+ if ( !bValidSize )
+ bValidPrtArea = sal_False;
+ }
+ else
+ {
+ if ( !bValidSize )
+ {
+ //FixSize einstellen, die VarSize wird von Format() nach
+ //Berechnung der PrtArea eingestellt.
+ bValidPrtArea = sal_False;
+
+ SwTwips nPrtWidth = (GetUpper()->Prt().*fnRect->fnGetWidth)();
+ if( bVert && ( IsBodyFrm() || IsFtnContFrm() ) )
+ {
+ SwFrm* pNxt = GetPrev();
+ while( pNxt && !pNxt->IsHeaderFrm() )
+ pNxt = pNxt->GetPrev();
+ if( pNxt )
+ nPrtWidth -= pNxt->Frm().Height();
+ pNxt = GetNext();
+ while( pNxt && !pNxt->IsFooterFrm() )
+ pNxt = pNxt->GetNext();
+ if( pNxt )
+ nPrtWidth -= pNxt->Frm().Height();
+ }
+
+ const long nDiff = nPrtWidth - (Frm().*fnRect->fnGetWidth)();
+
+ if( IsNeighbourFrm() && IsRightToLeft() )
+ (Frm().*fnRect->fnSubLeft)( nDiff );
+ else
+ (Frm().*fnRect->fnAddRight)( nDiff );
+ }
+ else
+ {
+ // Don't leave your upper
+ const SwTwips nDeadLine = (GetUpper()->*fnRect->fnGetPrtBottom)();
+ if( (Frm().*fnRect->fnOverStep)( nDeadLine ) )
+ bValidSize = sal_False;
+ }
+ }
+ }
+ if ( !bValidSize || !bValidPrtArea )
+ {
+ if ( !pAccess )
+ {
+ pAccess = new SwBorderAttrAccess( SwFrm::GetCache(), this );
+ pAttrs = pAccess->Get();
+ }
+ Format( pAttrs );
+ }
+ } //while ( !bValidPos || !bValidSize || !bValidPrtArea )
+ if ( pAccess )
+ delete pAccess;
+}
+
+/*************************************************************************
+|*
+|* SwCntntFrm::MakePrtArea()
+|*
+|*************************************************************************/
+bool SwTxtNode::IsCollapse() const
+{
+ if ( GetDoc()->get( IDocumentSettingAccess::COLLAPSE_EMPTY_CELL_PARA ) && GetTxt().Len()==0 ) {
+ sal_uLong nIdx=GetIndex();
+ const SwEndNode *pNdBefore=GetNodes()[nIdx-1]->GetEndNode();
+ const SwEndNode *pNdAfter=GetNodes()[nIdx+1]->GetEndNode();
+
+ // The paragraph is collapsed only if the NdAfter is the end of a cell
+ bool bInTable = this->FindTableNode( ) != NULL;
+
+ SwSortedObjs* pObjs = this->getLayoutFrm( GetDoc()->GetCurrentLayout() )->GetDrawObjs( );
+ sal_uInt32 nObjs = ( pObjs != NULL ) ? pObjs->Count( ) : 0;
+
+ if ( pNdBefore!=NULL && pNdAfter!=NULL && nObjs == 0 && bInTable ) {
+ return true;
+ } else {
+ return false;
+ }
+ } else
+ return false;
+}
+
+bool SwFrm::IsCollapse() const
+{
+ if (IsTxtFrm()) {
+ const SwTxtFrm *pTxtFrm=(SwTxtFrm*)this;
+ const SwTxtNode *pTxtNode=pTxtFrm->GetTxtNode();
+ if (pTxtNode && pTxtNode->IsCollapse()) {
+ return true;
+ } else {
+ return false;
+ }
+ } else {
+ return false;
+ }
+}
+
+sal_Bool SwCntntFrm::MakePrtArea( const SwBorderAttrs &rAttrs )
+{
+ sal_Bool bSizeChgd = sal_False;
+
+ if ( !bValidPrtArea )
+ {
+ bValidPrtArea = sal_True;
+
+ SWRECTFN( this )
+ const sal_Bool bTxtFrm = IsTxtFrm();
+ SwTwips nUpper = 0;
+ if ( bTxtFrm && ((SwTxtFrm*)this)->IsHiddenNow() )
+ {
+ if ( ((SwTxtFrm*)this)->HasFollow() )
+ ((SwTxtFrm*)this)->JoinFrm();
+
+ if( (Prt().*fnRect->fnGetHeight)() )
+ ((SwTxtFrm*)this)->HideHidden();
+ Prt().Pos().X() = Prt().Pos().Y() = 0;
+ (Prt().*fnRect->fnSetWidth)( (Frm().*fnRect->fnGetWidth)() );
+ (Prt().*fnRect->fnSetHeight)( 0 );
+ nUpper = -( (Frm().*fnRect->fnGetHeight)() );
+ }
+ else
+ {
+ //Vereinfachung: CntntFrms sind immer in der Hoehe Variabel!
+
+ //An der FixSize gibt der umgebende Frame die Groesse vor, die
+ //Raender werden einfach abgezogen.
+ const long nLeft = rAttrs.CalcLeft( this );
+ const long nRight = ((SwBorderAttrs&)rAttrs).CalcRight( this );
+ (this->*fnRect->fnSetXMargins)( nLeft, nRight );
+
+ ViewShell *pSh = getRootFrm()->GetCurrShell();
+ SwTwips nWidthArea;
+ if( pSh && 0!=(nWidthArea=(pSh->VisArea().*fnRect->fnGetWidth)()) &&
+ GetUpper()->IsPageBodyFrm() && // nicht dagegen bei BodyFrms in Columns
+ pSh->GetViewOptions()->getBrowseMode() )
+ {
+ //Nicht ueber die Kante des sichbaren Bereiches hinausragen.
+ //Die Seite kann breiter sein, weil es Objekte mit "ueberbreite"
+ //geben kann (RootFrm::ImplCalcBrowseWidth())
+ long nMinWidth = 0;
+
+ for (sal_uInt16 i = 0; GetDrawObjs() && i < GetDrawObjs()->Count();++i)
+ {
+ // --> OD 2004-07-01 #i28701# - consider changed type of
+ // <SwSortedObjs> entries
+ SwAnchoredObject* pObj = (*GetDrawObjs())[i];
+ const SwFrmFmt& rFmt = pObj->GetFrmFmt();
+ const sal_Bool bFly = pObj->ISA(SwFlyFrm);
+ if ((bFly && (WEIT_WECH == pObj->GetObjRect().Width()))
+ || rFmt.GetFrmSize().GetWidthPercent())
+ {
+ continue;
+ }
+
+ if ( FLY_AS_CHAR == rFmt.GetAnchor().GetAnchorId() )
+ {
+ nMinWidth = Max( nMinWidth,
+ bFly ? rFmt.GetFrmSize().GetWidth()
+ : pObj->GetObjRect().Width() );
+ }
+ // <--
+ }
+
+ const Size aBorder = pSh->GetOut()->PixelToLogic( pSh->GetBrowseBorder() );
+ long nWidth = nWidthArea - 2 * ( IsVertical() ? aBorder.Height() : aBorder.Width() );
+ nWidth -= (Prt().*fnRect->fnGetLeft)();
+ nWidth -= rAttrs.CalcRightLine();
+ nWidth = Max( nMinWidth, nWidth );
+ (Prt().*fnRect->fnSetWidth)( Min( nWidth,
+ (Prt().*fnRect->fnGetWidth)() ) );
+ }
+
+ if ( (Prt().*fnRect->fnGetWidth)() <= MINLAY )
+ {
+ //Die PrtArea sollte schon wenigstens MINLAY breit sein, passend
+ //zu den Minimalwerten des UI
+ (Prt().*fnRect->fnSetWidth)( Min( long(MINLAY),
+ (Frm().*fnRect->fnGetWidth)() ) );
+ SwTwips nTmp = (Frm().*fnRect->fnGetWidth)() -
+ (Prt().*fnRect->fnGetWidth)();
+ if( (Prt().*fnRect->fnGetLeft)() > nTmp )
+ (Prt().*fnRect->fnSetLeft)( nTmp );
+ }
+
+ //Fuer die VarSize gelten folgende Regeln:
+ //1. Der erste einer Kette hat keinen Rand nach oben
+ //2. Nach unten gibt es nie einen Rand
+ //3. Der Rand nach oben ist das Maximum aus dem Abstand des
+ // Prev nach unten und dem eigenen Abstand nach oben.
+ //Die drei Regeln werden auf die Berechnung der Freiraeume, die von
+ //UL- bzw. LRSpace vorgegeben werden, angewand. Es gibt in alle
+ //Richtungen jedoch ggf. trotzdem einen Abstand; dieser wird durch
+ //Umrandung und/oder Schatten vorgegeben.
+ //4. Der Abstand fuer TextFrms entspricht mindestens dem Durchschuss
+
+ nUpper = CalcUpperSpace( &rAttrs, NULL );
+
+ SwTwips nLower = CalcLowerSpace( &rAttrs );
+ if (IsCollapse()) {
+ nUpper=0;
+ nLower=0;
+ }
+// // in balanced columned section frames we do not want the
+// // common border
+// sal_Bool bCommonBorder = sal_True;
+// if ( IsInSct() && GetUpper()->IsColBodyFrm() )
+// {
+// const SwSectionFrm* pSct = FindSctFrm();
+// bCommonBorder = pSct->GetFmt()->GetBalancedColumns().GetValue();
+// }
+// SwTwips nLower = bCommonBorder ?
+// rAttrs.GetBottomLine( this ) :
+// rAttrs.CalcBottomLine();
+
+ (Prt().*fnRect->fnSetPosY)( (!bVert || bReverse) ? nUpper : nLower);
+ nUpper += nLower;
+ nUpper -= (Frm().*fnRect->fnGetHeight)() -
+ (Prt().*fnRect->fnGetHeight)();
+ }
+ //Wenn Unterschiede zwischen Alter und neuer Groesse,
+ //Grow() oder Shrink() rufen
+ if ( nUpper )
+ {
+ if ( nUpper > 0 )
+ GrowFrm( nUpper );
+ else
+ ShrinkFrm( -nUpper );
+ bSizeChgd = sal_True;
+ }
+ }
+ return bSizeChgd;
+}
+
+/*************************************************************************
+|*
+|* SwCntntFrm::MakeAll()
+|*
+|*************************************************************************/
+
+#define STOP_FLY_FORMAT 10
+// --> OD 2006-09-25 #b6448963# - loop prevention
+const int cnStopFormat = 15;
+// <--
+
+inline void ValidateSz( SwFrm *pFrm )
+{
+ if ( pFrm )
+ {
+ pFrm->bValidSize = sal_True;
+ pFrm->bValidPrtArea = sal_True;
+ }
+}
+
+void SwCntntFrm::MakeAll()
+{
+ OSL_ENSURE( GetUpper(), "keinen Upper?" );
+ OSL_ENSURE( IsTxtFrm(), "MakeAll(), NoTxt" );
+
+ if ( !IsFollow() && StackHack::IsLocked() )
+ return;
+
+ if ( IsJoinLocked() )
+ return;
+
+ OSL_ENSURE( !((SwTxtFrm*)this)->IsSwapped(), "Calculation of a swapped frame" );
+
+ StackHack aHack;
+
+ if ( ((SwTxtFrm*)this)->IsLocked() )
+ {
+ OSL_FAIL( "Format fuer gelockten TxtFrm." );
+ return;
+ }
+
+ LockJoin();
+ long nFormatCount = 0;
+ // --> OD 2006-09-25 #b6448963# - loop prevention
+ int nConsequetiveFormatsWithoutChange = 0;
+ // <--
+ PROTOCOL_ENTER( this, PROT_MAKEALL, 0, 0 )
+
+#if OSL_DEBUG_LEVEL > 1
+ const SwDoc *pDoc = GetAttrSet()->GetDoc();
+ if( pDoc )
+ {
+ static sal_Bool bWarn = sal_False;
+ if( pDoc->InXMLExport() )
+ {
+ OSL_ENSURE( bWarn, "Formatting during XML-export!" );
+ bWarn = sal_True;
+ }
+ else
+ bWarn = sal_False;
+ }
+#endif
+
+ //uebernimmt im DTor die Benachrichtigung
+ SwCntntNotify *pNotify = new SwCntntNotify( this );
+
+ sal_Bool bMakePage = sal_True; //solange sal_True kann eine neue Seite
+ //angelegt werden (genau einmal)
+ sal_Bool bMovedBwd = sal_False; //Wird sal_True wenn der Frame zurueckfliesst
+ sal_Bool bMovedFwd = sal_False; //solange sal_False kann der Frm zurueck-
+ //fliessen (solange, bis er einmal
+ //vorwaerts ge'moved wurde).
+ sal_Bool bFormatted = sal_False; //Fuer die Witwen und Waisen Regelung
+ //wird der letzte CntntFrm einer Kette
+ //u.U. zum Formatieren angeregt, dies
+ //braucht nur einmal zu passieren.
+ //Immer wenn der Frm gemoved wird muss
+ //das Flag zurueckgesetzt werden.
+ sal_Bool bMustFit = sal_False; //Wenn einmal die Notbremse gezogen wurde,
+ //werden keine anderen Prepares mehr
+ //abgesetzt.
+ sal_Bool bFitPromise = sal_False; //Wenn ein Absatz nicht passte, mit WouldFit
+ //aber verspricht, dass er sich passend
+ //einstellt wird dieses Flag gesetzt.
+ //Wenn er dann sein Versprechen nicht haelt,
+ //kann kontrolliert verfahren werden.
+ sal_Bool bMoveable;
+ const sal_Bool bFly = IsInFly();
+ const sal_Bool bTab = IsInTab();
+ const sal_Bool bFtn = IsInFtn();
+ const sal_Bool bSct = IsInSct();
+ Point aOldFrmPos; //Damit bei Turnarounds jew. mit der
+ Point aOldPrtPos; //letzten Pos verglichen und geprueft
+ //werden kann, ob ein Prepare sinnvoll ist.
+
+ SwBorderAttrAccess aAccess( SwFrm::GetCache(), this );
+ const SwBorderAttrs &rAttrs = *aAccess.Get();
+
+ // OD 2004-02-26 #i25029#
+ if ( !IsFollow() && rAttrs.JoinedWithPrev( *(this) ) )
+ {
+ pNotify->SetBordersJoinedWithPrev();
+ }
+
+ const sal_Bool bKeep = IsKeep( rAttrs.GetAttrSet() );
+
+ SwSaveFtnHeight *pSaveFtn = 0;
+ if ( bFtn )
+ {
+ SwFtnFrm *pFtn = FindFtnFrm();
+ SwSectionFrm* pSct = pFtn->FindSctFrm();
+ if ( !((SwTxtFrm*)pFtn->GetRef())->IsLocked() )
+ {
+ SwFtnBossFrm* pBoss = pFtn->GetRef()->FindFtnBossFrm(
+ pFtn->GetAttr()->GetFtn().IsEndNote() );
+ if( !pSct || pSct->IsColLocked() || !pSct->Growable() )
+ pSaveFtn = new SwSaveFtnHeight( pBoss,
+ ((SwTxtFrm*)pFtn->GetRef())->GetFtnLine( pFtn->GetAttr() ) );
+ }
+ }
+
+ // --> OD 2008-08-12 #b6732519#
+ if ( GetUpper()->IsSctFrm() &&
+ HasFollow() &&
+ GetFollow()->GetFrm() == GetNext() )
+ {
+ dynamic_cast<SwTxtFrm*>(this)->JoinFrm();
+ }
+ // <--
+
+ // --> OD 2004-06-23 #i28701# - move master forward, if it has to move,
+ // because of its object positioning.
+ if ( !static_cast<SwTxtFrm*>(this)->IsFollow() )
+ {
+ sal_uInt32 nToPageNum = 0L;
+ const bool bMoveFwdByObjPos = SwLayouter::FrmMovedFwdByObjPos(
+ *(GetAttrSet()->GetDoc()),
+ *(static_cast<SwTxtFrm*>(this)),
+ nToPageNum );
+ // --> OD 2006-01-27 #i58182#
+ // Also move a paragraph forward, which is the first one inside a table cell.
+ if ( bMoveFwdByObjPos &&
+ FindPageFrm()->GetPhyPageNum() < nToPageNum &&
+ ( lcl_Prev( this ) ||
+ GetUpper()->IsCellFrm() ||
+ ( GetUpper()->IsSctFrm() &&
+ GetUpper()->GetUpper()->IsCellFrm() ) ) &&
+ IsMoveable() )
+ {
+ bMovedFwd = sal_True;
+ MoveFwd( bMakePage, sal_False );
+ }
+ // <--
+ }
+ // <--
+
+ //Wenn ein Follow neben seinem Master steht und nicht passt, kann er
+ //gleich verschoben werden.
+ if ( lcl_Prev( this ) && ((SwTxtFrm*)this)->IsFollow() && IsMoveable() )
+ {
+ bMovedFwd = sal_True;
+ // OD 2004-03-02 #106629# - If follow frame is in table, it's master
+ // will be the last in the current table cell. Thus, invalidate the
+ // printing area of the master,
+ if ( IsInTab() )
+ {
+ lcl_Prev( this )->InvalidatePrt();
+ }
+ MoveFwd( bMakePage, sal_False );
+ }
+
+ // OD 08.11.2002 #104840# - check footnote content for forward move.
+ // If a content of a footnote is on a prior page/column as its invalid
+ // reference, it can be moved forward.
+ if ( bFtn && !bValidPos )
+ {
+ SwFtnFrm* pFtn = FindFtnFrm();
+ SwCntntFrm* pRefCnt = pFtn ? pFtn->GetRef() : 0;
+ if ( pRefCnt && !pRefCnt->IsValid() )
+ {
+ SwFtnBossFrm* pFtnBossOfFtn = pFtn->FindFtnBossFrm();
+ SwFtnBossFrm* pFtnBossOfRef = pRefCnt->FindFtnBossFrm();
+ //<loop of movefwd until condition held or no move>
+ if ( pFtnBossOfFtn && pFtnBossOfRef &&
+ pFtnBossOfFtn != pFtnBossOfRef &&
+ pFtnBossOfFtn->IsBefore( pFtnBossOfRef ) )
+ {
+ bMovedFwd = sal_True;
+ MoveFwd( bMakePage, sal_False );
+ }
+ }
+ }
+
+ SWRECTFN( this )
+
+ while ( !bValidPos || !bValidSize || !bValidPrtArea )
+ {
+ // --> OD 2006-09-25 #b6448963# - loop prevention
+ SwRect aOldFrm_StopFormat( Frm() );
+ SwRect aOldPrt_StopFormat( Prt() );
+ // <--
+ if ( sal_True == (bMoveable = IsMoveable()) )
+ {
+ SwFrm *pPre = GetIndPrev();
+ if ( CheckMoveFwd( bMakePage, bKeep, bMovedBwd ) )
+ {
+ SWREFRESHFN( this )
+ bMovedFwd = sal_True;
+ if ( bMovedBwd )
+ {
+ //Beim zurueckfliessen wurde der Upper angeregt sich
+ //vollstaendig zu Painten, dass koennen wir uns jetzt
+ //nach dem hin und her fliessen sparen.
+ GetUpper()->ResetCompletePaint();
+ //Der Vorgaenger wurde Invalidiert, das ist jetzt auch obsolete.
+ OSL_ENSURE( pPre, "missing old Prev" );
+ if( !pPre->IsSctFrm() )
+ ::ValidateSz( pPre );
+ }
+ bMoveable = IsMoveable();
+ }
+ }
+
+ aOldFrmPos = (Frm().*fnRect->fnGetPos)();
+ aOldPrtPos = (Prt().*fnRect->fnGetPos)();
+
+ if ( !bValidPos )
+ MakePos();
+
+ //FixSize einstellen, die VarSize wird von Format() justiert.
+ if ( !bValidSize )
+ {
+ // --> OD 2006-01-03 #125452#
+ // invalidate printing area flag, if the following conditions are hold:
+ // - current frame width is 0.
+ // - current printing area width is 0.
+ // - frame width is adjusted to a value greater than 0.
+ // - printing area flag is sal_True.
+ // Thus, it's assured that the printing area is adjusted, if the
+ // frame area width changes its width from 0 to something greater
+ // than 0.
+ // Note: A text frame can be in such a situation, if the format is
+ // triggered by method call <SwCrsrShell::SetCrsr()> after
+ // loading the document.
+ const SwTwips nNewFrmWidth = (GetUpper()->Prt().*fnRect->fnGetWidth)();
+ if ( bValidPrtArea && nNewFrmWidth > 0 &&
+ (Frm().*fnRect->fnGetWidth)() == 0 &&
+ (Prt().*fnRect->fnGetWidth)() == 0 )
+ {
+ bValidPrtArea = sal_False;
+ }
+
+ (Frm().*fnRect->fnSetWidth)( nNewFrmWidth );
+ // <--
+ }
+ if ( !bValidPrtArea )
+ {
+ const long nOldW = (Prt().*fnRect->fnGetWidth)();
+ // --> OD 2004-09-28 #i34730# - keep current frame height
+ const SwTwips nOldH = (Frm().*fnRect->fnGetHeight)();
+ // <--
+ MakePrtArea( rAttrs );
+ if ( nOldW != (Prt().*fnRect->fnGetWidth)() )
+ Prepare( PREP_FIXSIZE_CHG );
+ // --> OD 2004-09-28 #i34730# - check, if frame height has changed.
+ // If yes, send a PREP_ADJUST_FRM and invalidate the size flag to
+ // force a format. The format will check in its method
+ // <SwTxtFrm::CalcPreps()>, if the already formatted lines still
+ // fit and if not, performs necessary actions.
+ // --> OD 2005-01-10 #i40150# - no check, if frame is undersized.
+ if ( bValidSize && !IsUndersized() &&
+ nOldH != (Frm().*fnRect->fnGetHeight)() )
+ {
+ // --> OD 2004-11-25 #115759# - no PREP_ADJUST_FRM and size
+ // invalidation, if height decreases only by the additional
+ // lower space as last content of a table cell and an existing
+ // follow containing one line exists.
+ const SwTwips nHDiff = nOldH - (Frm().*fnRect->fnGetHeight)();
+ const bool bNoPrepAdjustFrm =
+ nHDiff > 0 && IsInTab() && GetFollow() &&
+ ( 1 == static_cast<SwTxtFrm*>(GetFollow())->GetLineCount( STRING_LEN ) || (static_cast<SwTxtFrm*>(GetFollow())->Frm().*fnRect->fnGetWidth)() < 0 ) &&
+ GetFollow()->CalcAddLowerSpaceAsLastInTableCell() == nHDiff;
+ if ( !bNoPrepAdjustFrm )
+ {
+ Prepare( PREP_ADJUST_FRM );
+ bValidSize = sal_False;
+ }
+ // <--
+ }
+ // <--
+ }
+
+ //Damit die Witwen- und Waisen-Regelung eine Change bekommt muss der
+ //CntntFrm benachrichtigt werden.
+ //Kriterium:
+ //- Er muss Moveable sein (sonst mach das Spalten keinen Sinn.)
+ //- Er muss mit der Unterkante der PrtArea des Upper ueberlappen.
+ if ( !bMustFit )
+ {
+ sal_Bool bWidow = sal_True;
+ const SwTwips nDeadLine = (GetUpper()->*fnRect->fnGetPrtBottom)();
+ if ( bMoveable && !bFormatted && ( GetFollow() ||
+ ( (Frm().*fnRect->fnOverStep)( nDeadLine ) ) ) )
+ {
+ Prepare( PREP_WIDOWS_ORPHANS, 0, sal_False );
+ bValidSize = bWidow = sal_False;
+ }
+ if( (Frm().*fnRect->fnGetPos)() != aOldFrmPos ||
+ (Prt().*fnRect->fnGetPos)() != aOldPrtPos )
+ {
+ // In diesem Prepare erfolgt ggf. ein _InvalidateSize().
+ // bValidSize wird sal_False und das Format() wird gerufen.
+ Prepare( PREP_POS_CHGD, (const void*)&bFormatted, sal_False );
+ if ( bWidow && GetFollow() )
+ { Prepare( PREP_WIDOWS_ORPHANS, 0, sal_False );
+ bValidSize = sal_False;
+ }
+ }
+ }
+ if ( !bValidSize )
+ {
+ bValidSize = bFormatted = sal_True;
+ ++nFormatCount;
+ if( nFormatCount > STOP_FLY_FORMAT )
+ SetFlyLock( sal_True );
+ // --> OD 2006-09-25 #b6448963# - loop prevention
+ // No format any longer, if <cnStopFormat> consequetive formats
+ // without change occur.
+ if ( nConsequetiveFormatsWithoutChange <= cnStopFormat )
+ {
+ Format();
+ }
+#if OSL_DEBUG_LEVEL > 1
+ else
+ {
+ OSL_FAIL( "debug assertion: <SwCntntFrm::MakeAll()> - format of text frame suppressed by fix b6448963" );
+ }
+#endif
+ // <--
+ }
+
+ //Wenn ich der erste einer Kette bin koennte ich mal sehen ob
+ //ich zurueckfliessen kann (wenn ich mich ueberhaupt bewegen soll).
+ //Damit es keine Oszillation gibt, darf ich nicht gerade vorwaerts
+ //geflossen sein.
+ sal_Bool bDummy;
+ if ( !lcl_Prev( this ) &&
+ !bMovedFwd &&
+ ( bMoveable || ( bFly && !bTab ) ) &&
+ ( !bFtn || !GetUpper()->FindFtnFrm()->GetPrev() )
+ && MoveBwd( bDummy ) )
+ {
+ SWREFRESHFN( this )
+ bMovedBwd = sal_True;
+ bFormatted = sal_False;
+ if ( bKeep && bMoveable )
+ {
+ if( CheckMoveFwd( bMakePage, sal_False, bMovedBwd ) )
+ {
+ bMovedFwd = sal_True;
+ bMoveable = IsMoveable();
+ SWREFRESHFN( this )
+ }
+ Point aOldPos = (Frm().*fnRect->fnGetPos)();
+ MakePos();
+ if( aOldPos != (Frm().*fnRect->fnGetPos)() )
+ {
+ Prepare( PREP_POS_CHGD, (const void*)&bFormatted, sal_False );
+ if ( !bValidSize )
+ {
+ (Frm().*fnRect->fnSetWidth)( (GetUpper()->
+ Prt().*fnRect->fnGetWidth)() );
+ if ( !bValidPrtArea )
+ {
+ const long nOldW = (Prt().*fnRect->fnGetWidth)();
+ MakePrtArea( rAttrs );
+ if( nOldW != (Prt().*fnRect->fnGetWidth)() )
+ Prepare( PREP_FIXSIZE_CHG, 0, sal_False );
+ }
+ if( GetFollow() )
+ Prepare( PREP_WIDOWS_ORPHANS, 0, sal_False );
+ bValidSize = bFormatted = sal_True;
+ Format();
+ }
+ }
+ SwFrm *pNxt = HasFollow() ? NULL : FindNext();
+ while( pNxt && pNxt->IsSctFrm() )
+ { // Leere Bereiche auslassen, in die anderen hinein
+ if( ((SwSectionFrm*)pNxt)->GetSection() )
+ {
+ SwFrm* pTmp = ((SwSectionFrm*)pNxt)->ContainsAny();
+ if( pTmp )
+ {
+ pNxt = pTmp;
+ break;
+ }
+ }
+ pNxt = pNxt->FindNext();
+ }
+ if ( pNxt )
+ {
+ pNxt->Calc();
+ if( bValidPos && !GetIndNext() )
+ {
+ SwSectionFrm *pSct = FindSctFrm();
+ if( pSct && !pSct->GetValidSizeFlag() )
+ {
+ SwSectionFrm* pNxtSct = pNxt->FindSctFrm();
+ if( pNxtSct && pSct->IsAnFollow( pNxtSct ) )
+ bValidPos = sal_False;
+ }
+ else
+ bValidPos = sal_False;
+ }
+ }
+ }
+ }
+
+ //Der TxtFrm Validiert sich bei Fussnoten ggf. selbst, dass kann leicht
+ //dazu fuehren, dass seine Position obwohl unrichtig valide ist.
+ if ( bValidPos )
+ {
+ // --> OD 2006-01-23 #i59341#
+ // Workaround for inadequate layout algorithm:
+ // suppress invalidation and calculation of position, if paragraph
+ // has formatted itself at least STOP_FLY_FORMAT times and
+ // has anchored objects.
+ // Thus, the anchored objects get the possibility to format itself
+ // and this probably solve the layout loop.
+ if ( bFtn &&
+ nFormatCount <= STOP_FLY_FORMAT &&
+ !GetDrawObjs() )
+ // <--
+ {
+ bValidPos = sal_False;
+ MakePos();
+ aOldFrmPos = (Frm().*fnRect->fnGetPos)();
+ aOldPrtPos = (Prt().*fnRect->fnGetPos)();
+ }
+ }
+
+ // --> OD 2006-09-25 #b6448963# - loop prevention
+ {
+ if ( aOldFrm_StopFormat == Frm() &&
+ aOldPrt_StopFormat == Prt() )
+ {
+ ++nConsequetiveFormatsWithoutChange;
+ }
+ else
+ {
+ nConsequetiveFormatsWithoutChange = 0;
+ }
+ }
+ // <--
+
+ //Wieder ein Wert ungueltig? - dann nochmal das ganze...
+ if ( !bValidPos || !bValidSize || !bValidPrtArea )
+ continue;
+
+ //Fertig?
+ // Achtung, wg. Hoehe==0, ist es besser statt Bottom() Top()+Height() zu nehmen
+ // (kommt bei Undersized TxtFrms an der Unterkante eines spaltigen Bereichs vor)
+ const long nPrtBottom = (GetUpper()->*fnRect->fnGetPrtBottom)();
+ const long nBottomDist = (Frm().*fnRect->fnBottomDist)( nPrtBottom );
+ if( nBottomDist >= 0 )
+ {
+ if ( bKeep && bMoveable )
+ {
+ //Wir sorgen dafuer, dass der Nachfolger gleich mit formatiert
+ //wird. Dadurch halten wir das Heft in der Hand, bis wirklich
+ //(fast) alles stabil ist. So vermeiden wir Endlosschleifen,
+ //die durch staendig wiederholte Versuche entstehen.
+ //Das bMoveFwdInvalid ist fuer #38407# notwendig. War urspruenglich
+ //in flowfrm.cxx rev 1.38 behoben, das unterbrach aber obiges
+ //Schema und spielte lieber Tuerme von Hanoi (#43669#).
+ SwFrm *pNxt = HasFollow() ? NULL : FindNext();
+ // Bei Bereichen nehmen wir lieber den Inhalt, denn nur
+ // dieser kann ggf. die Seite wechseln
+ while( pNxt && pNxt->IsSctFrm() )
+ {
+ if( ((SwSectionFrm*)pNxt)->GetSection() )
+ {
+ pNxt = ((SwSectionFrm*)pNxt)->ContainsAny();
+ break;
+ }
+ pNxt = pNxt->FindNext();
+ }
+ if ( pNxt )
+ {
+ const sal_Bool bMoveFwdInvalid = 0 != GetIndNext();
+ const sal_Bool bNxtNew =
+ ( 0 == (pNxt->Prt().*fnRect->fnGetHeight)() ) &&
+ (!pNxt->IsTxtFrm() ||!((SwTxtFrm*)pNxt)->IsHiddenNow());
+
+ pNxt->Calc();
+
+ if ( !bMovedBwd &&
+ ((bMoveFwdInvalid && !GetIndNext()) ||
+ bNxtNew) )
+ {
+ if( bMovedFwd )
+ pNotify->SetInvaKeep();
+ bMovedFwd = sal_False;
+ }
+ }
+ }
+ continue;
+ }
+
+ //Ich passe nicht mehr in meinen Uebergeordneten, also ist es jetzt
+ //an der Zeit moeglichst konstruktive Veranderungen vorzunehmen
+
+ //Wenn ich den uebergeordneten Frm nicht verlassen darf, habe
+ //ich ein Problem; Frei nach Artur Dent tun wir das einzige das man
+ //mit einen nicht loesbaren Problem tun kann: wir ignorieren es - und
+ //zwar mit aller Kraft.
+ if ( !bMoveable || IsUndersized() )
+ {
+ if( !bMoveable && IsInTab() )
+ {
+ long nDiff = -(Frm().*fnRect->fnBottomDist)(
+ (GetUpper()->*fnRect->fnGetPrtBottom)() );
+ long nReal = GetUpper()->Grow( nDiff );
+ if( nReal )
+ continue;
+ }
+ break;
+ }
+
+ //Wenn ich nun ueberhaupt ganz und garnicht in meinen Upper passe
+ //so kann die Situation vielleicht doch noch durch Aufbrechen
+ //aufgeklart werden. Diese Situation tritt bei einem frisch
+ //erzeugten Follow auf, der zwar auf die Folgeseite geschoben wurde
+ //aber selbst noch zu gross fuer diese ist; also wiederum
+ //aufgespalten werden muss.
+ //Wenn ich nicht passe und nicht Spaltbar (WouldFit()) bin, so schicke
+ //ich meinem TxtFrmanteil die Nachricht, dass eben falls moeglich
+ //trotz des Attributes 'nicht aufspalten' aufgespalten werden muss.
+ sal_Bool bMoveOrFit = sal_False;
+ sal_Bool bDontMoveMe = !GetIndPrev();
+ if( bDontMoveMe && IsInSct() )
+ {
+ SwFtnBossFrm* pBoss = FindFtnBossFrm();
+ bDontMoveMe = !pBoss->IsInSct() ||
+ ( !pBoss->Lower()->GetNext() && !pBoss->GetPrev() );
+ }
+
+ // Finally, we are able to split table rows. Therefore, bDontMoveMe
+ // can be set to sal_False:
+ if( bDontMoveMe && IsInTab() &&
+ 0 != const_cast<SwCntntFrm*>(this)->GetNextCellLeaf( MAKEPAGE_NONE ) )
+ bDontMoveMe = sal_False;
+
+ if ( bDontMoveMe && (Frm().*fnRect->fnGetHeight)() >
+ (GetUpper()->Prt().*fnRect->fnGetHeight)() )
+ {
+ if ( !bFitPromise )
+ {
+ SwTwips nTmp = (GetUpper()->Prt().*fnRect->fnGetHeight)() -
+ (Prt().*fnRect->fnGetTop)();
+ sal_Bool bSplit = !IsFwdMoveAllowed();
+ if ( nTmp > 0 && WouldFit( nTmp, bSplit, sal_False ) )
+ {
+ Prepare( PREP_WIDOWS_ORPHANS, 0, sal_False );
+ bValidSize = sal_False;
+ bFitPromise = sal_True;
+ continue;
+ }
+ /* --------------------------------------------------
+ * Frueher wurde in Rahmen und Bereichen niemals versucht,
+ * durch bMoveOrFit den TxtFrm unter Verzicht auf seine
+ * Attribute (Widows,Keep) doch noch passend zu bekommen.
+ * Dies haette zumindest bei spaltigen Rahmen versucht
+ * werden muessen, spaetestens bei verketteten Rahmen und
+ * in Bereichen muss es versucht werden.
+ * Ausnahme: Wenn wir im FormatWidthCols stehen, duerfen die
+ * Attribute nicht ausser Acht gelassen werden.
+ * --------------------------------------------------*/
+ else if ( !bFtn && bMoveable &&
+ ( !bFly || !FindFlyFrm()->IsColLocked() ) &&
+ ( !bSct || !FindSctFrm()->IsColLocked() ) )
+ bMoveOrFit = sal_True;
+ }
+#if OSL_DEBUG_LEVEL > 1
+ else
+ {
+ OSL_FAIL( "+TxtFrm hat WouldFit-Versprechen nicht eingehalten." );
+ }
+#endif
+ }
+
+ //Mal sehen ob ich irgenwo Platz finde...
+ //Benachbarte Fussnoten werden in _MoveFtnCntFwd 'vorgeschoben'
+ SwFrm *pPre = GetIndPrev();
+ SwFrm *pOldUp = GetUpper();
+
+/* MA 13. Oct. 98: Was soll das denn sein!?
+ * AMA 14. Dec 98: Wenn ein spaltiger Bereich keinen Platz mehr fuer seinen ersten ContentFrm
+ * bietet, so soll dieser nicht nur in die naechste Spalte, sondern ggf. bis zur naechsten
+ * Seite wandern und dort einen Section-Follow erzeugen.
+ */
+ if( IsInSct() && bMovedFwd && bMakePage && pOldUp->IsColBodyFrm() &&
+ pOldUp->GetUpper()->GetUpper()->IsSctFrm() &&
+ ( pPre || pOldUp->GetUpper()->GetPrev() ) &&
+ ((SwSectionFrm*)pOldUp->GetUpper()->GetUpper())->MoveAllowed(this) )
+ bMovedFwd = sal_False;
+
+ const sal_Bool bCheckForGrownBody = pOldUp->IsBodyFrm();
+ const long nOldBodyHeight = (pOldUp->Frm().*fnRect->fnGetHeight)();
+
+ if ( !bMovedFwd && !MoveFwd( bMakePage, sal_False ) )
+ bMakePage = sal_False;
+ SWREFRESHFN( this )
+
+ // If MoveFwd moves the paragraph to the next page, a following
+ // paragraph, which contains footnotes can can cause the old upper
+ // frame to grow. In this case we explicitely allow a new check
+ // for MoveBwd. Robust: We also check the bMovedBwd flag again.
+ // If pOldUp was a footnote frame, it has been deleted inside MoveFwd.
+ // Therefore we only check for growing body frames.
+ if ( bCheckForGrownBody && ! bMovedBwd && pOldUp != GetUpper() &&
+ (pOldUp->Frm().*fnRect->fnGetHeight)() > nOldBodyHeight )
+ bMovedFwd = sal_False;
+ else
+ bMovedFwd = sal_True;
+
+ bFormatted = sal_False;
+ if ( bMoveOrFit && GetUpper() == pOldUp )
+ {
+ // FME 2007-08-30 #i81146# new loop control
+ if ( nConsequetiveFormatsWithoutChange <= cnStopFormat )
+ {
+ Prepare( PREP_MUST_FIT, 0, sal_False );
+ bValidSize = sal_False;
+ bMustFit = sal_True;
+ continue;
+ }
+
+#if OSL_DEBUG_LEVEL > 1
+ OSL_FAIL( "LoopControl in SwCntntFrm::MakeAll" );
+#endif
+ }
+ if ( bMovedBwd && GetUpper() )
+ { //Unuetz gewordene Invalidierungen zuruecknehmen.
+ GetUpper()->ResetCompletePaint();
+ if( pPre && !pPre->IsSctFrm() )
+ ::ValidateSz( pPre );
+ }
+
+ } //while ( !bValidPos || !bValidSize || !bValidPrtArea )
+
+
+ // NEW: Looping Louie (Light). Should not be applied in balanced sections.
+ // Should only be applied if there is no better solution!
+ LOOPING_LOUIE_LIGHT( bMovedFwd && bMovedBwd && !IsInBalancedSection() &&
+ (
+
+ // --> FME 2005-01-26 #118572#
+ ( bFtn && !FindFtnFrm()->GetRef()->IsInSct() ) ||
+ // <--
+
+ // --> FME 2005-01-27 #i33887#
+ ( IsInSct() && bKeep )
+ // <--
+
+ // ... add your conditions here ...
+
+ ),
+ static_cast<SwTxtFrm&>(*this) );
+
+
+ if ( pSaveFtn )
+ delete pSaveFtn;
+
+ UnlockJoin();
+ if ( bMovedFwd || bMovedBwd )
+ pNotify->SetInvaKeep();
+ // OD 2004-02-26 #i25029#
+ if ( bMovedFwd )
+ {
+ pNotify->SetInvalidatePrevPrtArea();
+ }
+ delete pNotify;
+ SetFlyLock( sal_False );
+}
+
+/*************************************************************************
+|*
+|* SwCntntFrm::_WouldFit()
+|*
+|*************************************************************************/
+
+
+
+
+void MakeNxt( SwFrm *pFrm, SwFrm *pNxt )
+{
+ //fix(25455): Validieren, sonst kommt es zu einer Rekursion.
+ //Der erste Versuch, der Abbruch mit pFrm = 0 wenn !Valid,
+ //fuehrt leider zu dem Problem, dass das Keep dann u.U. nicht mehr
+ //korrekt beachtet wird (27417)
+ const sal_Bool bOldPos = pFrm->GetValidPosFlag();
+ const sal_Bool bOldSz = pFrm->GetValidSizeFlag();
+ const sal_Bool bOldPrt = pFrm->GetValidPrtAreaFlag();
+ pFrm->bValidPos = pFrm->bValidPrtArea = pFrm->bValidSize = sal_True;
+
+ //fix(29272): Nicht MakeAll rufen, dort wird evtl. pFrm wieder invalidert
+ //und kommt rekursiv wieder herein.
+ if ( pNxt->IsCntntFrm() )
+ {
+ SwCntntNotify aNotify( (SwCntntFrm*)pNxt );
+ SwBorderAttrAccess aAccess( SwFrm::GetCache(), pNxt );
+ const SwBorderAttrs &rAttrs = *aAccess.Get();
+ if ( !pNxt->GetValidSizeFlag() )
+ {
+ if( pNxt->IsVertical() )
+ pNxt->Frm().Height( pNxt->GetUpper()->Prt().Height() );
+ else
+ pNxt->Frm().Width( pNxt->GetUpper()->Prt().Width() );
+ }
+ ((SwCntntFrm*)pNxt)->MakePrtArea( rAttrs );
+ pNxt->Format( &rAttrs );
+ }
+ else
+ {
+ SwLayNotify aNotify( (SwLayoutFrm*)pNxt );
+ SwBorderAttrAccess aAccess( SwFrm::GetCache(), pNxt );
+ const SwBorderAttrs &rAttrs = *aAccess.Get();
+ if ( !pNxt->GetValidSizeFlag() )
+ {
+ if( pNxt->IsVertical() )
+ pNxt->Frm().Height( pNxt->GetUpper()->Prt().Height() );
+ else
+ pNxt->Frm().Width( pNxt->GetUpper()->Prt().Width() );
+ }
+ pNxt->Format( &rAttrs );
+ }
+
+ pFrm->bValidPos = bOldPos;
+ pFrm->bValidSize = bOldSz;
+ pFrm->bValidPrtArea = bOldPrt;
+}
+
+// Diese Routine ueberprueft, ob zwischen dem FtnBoss von pFrm und dem
+// von pNxt keine anderen FtnBosse liegen
+
+sal_Bool lcl_IsNextFtnBoss( const SwFrm *pFrm, const SwFrm* pNxt )
+{
+ OSL_ENSURE( pFrm && pNxt, "lcl_IsNextFtnBoss: No Frames?" );
+ pFrm = pFrm->FindFtnBossFrm();
+ pNxt = pNxt->FindFtnBossFrm();
+ // Falls pFrm eine letzte Spalte ist, wird stattdessen die Seite genommen
+ while( pFrm && pFrm->IsColumnFrm() && !pFrm->GetNext() )
+ pFrm = pFrm->GetUpper()->FindFtnBossFrm();
+ // Falls pNxt eine erste Spalte ist, wird stattdessen die Seite genommen
+ while( pNxt && pNxt->IsColumnFrm() && !pNxt->GetPrev() )
+ pNxt = pNxt->GetUpper()->FindFtnBossFrm();
+ // So, jetzt muessen pFrm und pNxt entweder zwei benachbarte Seiten oder Spalten sein.
+ return ( pFrm && pNxt && pFrm->GetNext() == pNxt );
+}
+
+// --> OD 2007-11-26 #b6614158#
+sal_Bool SwCntntFrm::_WouldFit( SwTwips nSpace,
+ SwLayoutFrm *pNewUpper,
+ sal_Bool bTstMove,
+ const bool bObjsInNewUpper )
+// <--
+{
+ //Damit die Fussnote sich ihren Platz sorgsam waehlt, muss
+ //sie in jedem Fall gemoved werden, wenn zwischen dem
+ //neuen Upper und ihrer aktuellen Seite/Spalte mindestens eine
+ //Seite/Spalte liegt.
+ SwFtnFrm* pFtnFrm = 0;
+ if ( IsInFtn() )
+ {
+ if( !lcl_IsNextFtnBoss( pNewUpper, this ) )
+ return sal_True;
+ pFtnFrm = FindFtnFrm();
+ }
+
+ sal_Bool bRet;
+ sal_Bool bSplit = !pNewUpper->Lower();
+ SwCntntFrm *pFrm = this;
+ const SwFrm *pTmpPrev = pNewUpper->Lower();
+ if( pTmpPrev && pTmpPrev->IsFtnFrm() )
+ pTmpPrev = ((SwFtnFrm*)pTmpPrev)->Lower();
+ while ( pTmpPrev && pTmpPrev->GetNext() )
+ pTmpPrev = pTmpPrev->GetNext();
+ do
+ {
+ // --> FME 2005-03-31 #b6236853# #i46181#
+ SwTwips nSecondCheck = 0;
+ SwTwips nOldSpace = nSpace;
+ sal_Bool bOldSplit = bSplit;
+ // <--
+
+ if ( bTstMove || IsInFly() || ( IsInSct() &&
+ ( pFrm->GetUpper()->IsColBodyFrm() || ( pFtnFrm &&
+ pFtnFrm->GetUpper()->GetUpper()->IsColumnFrm() ) ) ) )
+ {
+ //Jetzt wirds ein bischen hinterlistig; empfindliche Gemueter sollten
+ //lieber wegsehen. Wenn ein Flys Spalten enthaelt so sind die Cntnts
+ //moveable, mit Ausnahme der in der letzten Spalte (siehe
+ //SwFrm::IsMoveable()). Zurueckfliessen duerfen sie aber natuerlich.
+ //Das WouldFit() liefert leider nur dann einen vernueftigen Wert, wenn
+ //der Frm moveable ist. Um dem WouldFit() einen Moveable Frm
+ //vorzugaukeln haenge ich ihn einfach solange um.
+ // Auch bei spaltigen Bereichen muss umgehaengt werden, damit
+ // SwSectionFrm::Growable() den richtigen Wert liefert.
+ // Innerhalb von Fussnoten muss ggf. sogar der SwFtnFrm umgehaengt werden,
+ // falls es dort keinen SwFtnFrm gibt.
+ SwFrm* pTmpFrm = pFrm->IsInFtn() && !pNewUpper->FindFtnFrm() ?
+ (SwFrm*)pFrm->FindFtnFrm() : pFrm;
+ SwLayoutFrm *pUp = pTmpFrm->GetUpper();
+ SwFrm *pOldNext = pTmpFrm->GetNext();
+ pTmpFrm->Remove();
+ pTmpFrm->InsertBefore( pNewUpper, 0 );
+ if ( pFrm->IsTxtFrm() &&
+ ( bTstMove ||
+ ((SwTxtFrm*)pFrm)->HasFollow() ||
+ ( !((SwTxtFrm*)pFrm)->HasPara() &&
+ !((SwTxtFrm*)pFrm)->IsEmpty()
+ )
+ )
+ )
+ {
+ bTstMove = sal_True;
+ bRet = ((SwTxtFrm*)pFrm)->TestFormat( pTmpPrev, nSpace, bSplit );
+ }
+ else
+ bRet = pFrm->WouldFit( nSpace, bSplit, sal_False );
+
+ pTmpFrm->Remove();
+ pTmpFrm->InsertBefore( pUp, pOldNext );
+ }
+ else
+ {
+ bRet = pFrm->WouldFit( nSpace, bSplit, sal_False );
+ nSecondCheck = !bSplit ? 1 : 0;
+ }
+
+ SwBorderAttrAccess aAccess( SwFrm::GetCache(), pFrm );
+ const SwBorderAttrs &rAttrs = *aAccess.Get();
+
+ //Bitter aber wahr: Der Abstand muss auch noch mit einkalkuliert werden.
+ //Bei TestFormatierung ist dies bereits geschehen.
+ if ( bRet && !bTstMove )
+ {
+ SwTwips nUpper;
+
+ if ( pTmpPrev )
+ {
+ nUpper = CalcUpperSpace( NULL, pTmpPrev );
+
+ // in balanced columned section frames we do not want the
+ // common border
+ sal_Bool bCommonBorder = sal_True;
+ if ( pFrm->IsInSct() && pFrm->GetUpper()->IsColBodyFrm() )
+ {
+ const SwSectionFrm* pSct = pFrm->FindSctFrm();
+ bCommonBorder = pSct->GetFmt()->GetBalancedColumns().GetValue();
+ }
+
+ // --> FME 2005-03-31 #b6236853# #i46181#
+ nSecondCheck = ( 1 == nSecondCheck &&
+ pFrm == this &&
+ IsTxtFrm() &&
+ bCommonBorder &&
+ !static_cast<const SwTxtFrm*>(this)->IsEmpty() ) ?
+ nUpper :
+ 0;
+ // <--
+
+ nUpper += bCommonBorder ?
+ rAttrs.GetBottomLine( *(pFrm) ) :
+ rAttrs.CalcBottomLine();
+
+ }
+ else
+ {
+ // --> FME 2005-03-31 #b6236853# #i46181#
+ nSecondCheck = 0;
+ // <--
+
+ if( pFrm->IsVertical() )
+ nUpper = pFrm->Frm().Width() - pFrm->Prt().Width();
+ else
+ nUpper = pFrm->Frm().Height() - pFrm->Prt().Height();
+ }
+
+ nSpace -= nUpper;
+
+ if ( nSpace < 0 )
+ {
+ bRet = sal_False;
+
+ // --> FME 2005-03-31 #b6236853# #i46181#
+ if ( nSecondCheck > 0 )
+ {
+ // The following code is indented to solve a (rare) problem
+ // causing some frames not to move backward:
+ // SwTxtFrm::WouldFit() claims that the whole paragraph
+ // fits into the given space and subtracts the height of
+ // all lines from nSpace. nSpace - nUpper is not a valid
+ // indicator if the frame should be allowed to move backward.
+ // We do a second check with the original remaining space
+ // reduced by the required upper space:
+ nOldSpace -= nSecondCheck;
+ const bool bSecondRet = nOldSpace >= 0 && pFrm->WouldFit( nOldSpace, bOldSplit, sal_False );
+ if ( bSecondRet && bOldSplit && nOldSpace >= 0 )
+ {
+ bRet = sal_True;
+ bSplit = sal_True;
+ }
+ }
+ // <--
+ }
+ }
+
+ // OD 2004-03-01 #106629# - also consider lower spacing in table cells
+ if ( bRet && IsInTab() &&
+ pNewUpper->GetFmt()->getIDocumentSettingAccess()->get(IDocumentSettingAccess::ADD_PARA_SPACING_TO_TABLE_CELLS) )
+ {
+ nSpace -= rAttrs.GetULSpace().GetLower();
+ if ( nSpace < 0 )
+ {
+ bRet = sal_False;
+ }
+ }
+
+ if ( bRet && !bSplit && pFrm->IsKeep( rAttrs.GetAttrSet() ) )
+ {
+ if( bTstMove )
+ {
+ while( pFrm->IsTxtFrm() && ((SwTxtFrm*)pFrm)->HasFollow() )
+ {
+ pFrm = ((SwTxtFrm*)pFrm)->GetFollow();
+ }
+ // OD 11.04.2003 #108824# - If last follow frame of <this> text
+ // frame isn't valid, a formatting of the next content frame
+ // doesn't makes sense. Thus, return sal_True.
+ if ( IsAnFollow( pFrm ) && !pFrm->IsValid() )
+ {
+ OSL_FAIL( "Only a warning for task 108824:/n<SwCntntFrm::_WouldFit(..) - follow not valid!" );
+ return sal_True;
+ }
+ }
+ SwFrm *pNxt;
+ if( 0 != (pNxt = pFrm->FindNext()) && pNxt->IsCntntFrm() &&
+ ( !pFtnFrm || ( pNxt->IsInFtn() &&
+ pNxt->FindFtnFrm()->GetAttr() == pFtnFrm->GetAttr() ) ) )
+ {
+ // ProbeFormatierung vertraegt keine absatz- oder gar zeichengebundene Objekte
+ // --> OD 2007-11-26 #b6614158#
+ // current solution for the test formatting doesn't work, if
+ // objects are present in the remaining area of the new upper
+ if ( bTstMove &&
+ ( pNxt->GetDrawObjs() || bObjsInNewUpper ) )
+ {
+ return sal_True;
+ }
+ // <--
+
+ if ( !pNxt->IsValid() )
+ MakeNxt( pFrm, pNxt );
+
+ //Kleiner Trick: Wenn der naechste einen Vorgaenger hat, so hat
+ //er den Absatzabstand bereits berechnet. Er braucht dann nicht
+ //teuer kalkuliert werden.
+ if( lcl_NotHiddenPrev( pNxt ) )
+ pTmpPrev = 0;
+ else
+ {
+ if( pFrm->IsTxtFrm() && ((SwTxtFrm*)pFrm)->IsHiddenNow() )
+ pTmpPrev = lcl_NotHiddenPrev( pFrm );
+ else
+ pTmpPrev = pFrm;
+ }
+ pFrm = (SwCntntFrm*)pNxt;
+ }
+ else
+ pFrm = 0;
+ }
+ else
+ pFrm = 0;
+
+ } while ( bRet && pFrm );
+
+ return bRet;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/layout/colfrm.cxx b/sw/source/core/layout/colfrm.cxx
new file mode 100644
index 000000000000..5e9aa78fdb59
--- /dev/null
+++ b/sw/source/core/layout/colfrm.cxx
@@ -0,0 +1,478 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+#include <hintids.hxx>
+#include "cntfrm.hxx"
+#include "doc.hxx"
+
+#include "hintids.hxx"
+#include <editeng/ulspitem.hxx>
+#include <editeng/lrspitem.hxx>
+#include <fmtclds.hxx>
+#include <fmtfordr.hxx>
+#include <frmfmt.hxx>
+#include <node.hxx>
+#include "frmtool.hxx"
+#include "colfrm.hxx"
+#include "pagefrm.hxx"
+#include "bodyfrm.hxx" // ColumnFrms jetzt mit BodyFrm
+#include "rootfrm.hxx" // wg. RemoveFtns
+#include "sectfrm.hxx" // wg. FtnAtEnd-Flag
+#include "switerator.hxx"
+
+// ftnfrm.cxx:
+void lcl_RemoveFtns( SwFtnBossFrm* pBoss, sal_Bool bPageOnly, sal_Bool bEndNotes );
+
+
+/*************************************************************************
+|*
+|* SwColumnFrm::SwColumnFrm()
+|*
+|*************************************************************************/
+SwColumnFrm::SwColumnFrm( SwFrmFmt *pFmt, SwFrm* pSib ):
+ SwFtnBossFrm( pFmt, pSib )
+{
+ nType = FRMC_COLUMN;
+ SwBodyFrm* pColBody = new SwBodyFrm( pFmt->GetDoc()->GetDfltFrmFmt(), pSib );
+ pColBody->InsertBehind( this, 0 ); // ColumnFrms jetzt mit BodyFrm
+ SetMaxFtnHeight( LONG_MAX );
+}
+
+SwColumnFrm::~SwColumnFrm()
+{
+ SwFrmFmt *pFmt = GetFmt();
+ SwDoc *pDoc;
+ if ( !(pDoc = pFmt->GetDoc())->IsInDtor() && pFmt->IsLastDepend() )
+ {
+ //Ich bin der einzige, weg mit dem Format.
+ //Vorher ummelden, damit die Basisklasse noch klarkommt.
+ pDoc->GetDfltFrmFmt()->Add( this );
+ pDoc->DelFrmFmt( pFmt );
+ }
+}
+
+/*************************************************************************
+|*
+|* SwLayoutFrm::ChgColumns()
+|*
+|*************************************************************************/
+
+void MA_FASTCALL lcl_RemoveColumns( SwLayoutFrm *pCont, sal_uInt16 nCnt )
+{
+ OSL_ENSURE( pCont && pCont->Lower() && pCont->Lower()->IsColumnFrm(),
+ "Keine Spalten zu entfernen." );
+
+ SwColumnFrm *pColumn = (SwColumnFrm*)pCont->Lower();
+ ::lcl_RemoveFtns( pColumn, sal_True, sal_True );
+ while ( pColumn->GetNext() )
+ {
+ OSL_ENSURE( pColumn->GetNext()->IsColumnFrm(),
+ "Nachbar von ColFrm kein ColFrm." );
+ pColumn = (SwColumnFrm*)pColumn->GetNext();
+ }
+ for ( sal_uInt16 i = 0; i < nCnt; ++i )
+ {
+ SwColumnFrm *pTmp = (SwColumnFrm*)pColumn->GetPrev();
+ pColumn->Cut();
+ delete pColumn; //Format wird ggf. im DTor mit vernichtet.
+ pColumn = pTmp;
+ }
+}
+
+SwLayoutFrm * MA_FASTCALL lcl_FindColumns( SwLayoutFrm *pLay, sal_uInt16 nCount )
+{
+ SwFrm *pCol = pLay->Lower();
+ if ( pLay->IsPageFrm() )
+ pCol = ((SwPageFrm*)pLay)->FindBodyCont()->Lower();
+
+ if ( pCol && pCol->IsColumnFrm() )
+ {
+ SwFrm *pTmp = pCol;
+ sal_uInt16 i;
+ for ( i = 0; pTmp; pTmp = pTmp->GetNext(), ++i )
+ /* do nothing */;
+ return i == nCount ? (SwLayoutFrm*)pCol : 0;
+ }
+ return 0;
+}
+
+
+static sal_Bool lcl_AddColumns( SwLayoutFrm *pCont, sal_uInt16 nCount )
+{
+ SwDoc *pDoc = pCont->GetFmt()->GetDoc();
+ const sal_Bool bMod = pDoc->IsModified();
+
+ //Format sollen soweit moeglich geshared werden. Wenn es also schon einen
+ //Nachbarn mit den selben Spalteneinstellungen gibt, so koennen die
+ //Spalten an die selben Formate gehaengt werden.
+ //Der Nachbar kann ueber das Format gesucht werden, wer der Owner des Attributes
+ //ist, ist allerdings vom Frametyp abhaengig.
+ SwLayoutFrm *pAttrOwner = pCont;
+ if ( pCont->IsBodyFrm() )
+ pAttrOwner = pCont->FindPageFrm();
+ SwLayoutFrm *pNeighbourCol = 0;
+ SwIterator<SwLayoutFrm,SwFmt> aIter( *pAttrOwner->GetFmt() );
+ SwLayoutFrm *pNeighbour = aIter.First();
+
+ sal_uInt16 nAdd = 0;
+ SwFrm *pCol = pCont->Lower();
+ if ( pCol && pCol->IsColumnFrm() )
+ for ( nAdd = 1; pCol; pCol = pCol->GetNext(), ++nAdd )
+ /* do nothing */;
+ while ( pNeighbour )
+ {
+ if ( 0 != (pNeighbourCol = lcl_FindColumns( pNeighbour, nCount+nAdd )) &&
+ pNeighbourCol != pCont )
+ break;
+ pNeighbourCol = 0;
+ pNeighbour = aIter.Next();
+ }
+
+ sal_Bool bRet;
+ SwTwips nMax = pCont->IsPageBodyFrm() ?
+ pCont->FindPageFrm()->GetMaxFtnHeight() : LONG_MAX;
+ if ( pNeighbourCol )
+ {
+ bRet = sal_False;
+ SwFrm *pTmp = pCont->Lower();
+ while ( pTmp )
+ {
+ pTmp = pTmp->GetNext();
+ pNeighbourCol = (SwLayoutFrm*)pNeighbourCol->GetNext();
+ }
+ for ( sal_uInt16 i = 0; i < nCount; ++i )
+ {
+ SwColumnFrm *pTmpCol = new SwColumnFrm( pNeighbourCol->GetFmt(), pCont );
+ pTmpCol->SetMaxFtnHeight( nMax );
+ pTmpCol->InsertBefore( pCont, NULL );
+ pNeighbourCol = (SwLayoutFrm*)pNeighbourCol->GetNext();
+ }
+ }
+ else
+ {
+ bRet = sal_True;
+ for ( sal_uInt16 i = 0; i < nCount; ++i )
+ {
+ SwFrmFmt *pFmt = pDoc->MakeFrmFmt( aEmptyStr, pDoc->GetDfltFrmFmt());
+ SwColumnFrm *pTmp = new SwColumnFrm( pFmt, pCont );
+ pTmp->SetMaxFtnHeight( nMax );
+ pTmp->Paste( pCont );
+ }
+ }
+
+ if ( !bMod )
+ pDoc->ResetModified();
+ return bRet;
+}
+
+/*--------------------------------------------------
+ * ChgColumns() adds or removes columns from a layoutframe.
+ * Normally, a layoutframe with a column attribut of 1 or 0 columns contains
+ * no columnframe. However, a sectionframe with "footnotes at the end" needs
+ * a columnframe. If the bChgFtn-flag is set, the columnframe will be inserted
+ * or remove, if necessary.
+ * --------------------------------------------------*/
+
+void SwLayoutFrm::ChgColumns( const SwFmtCol &rOld, const SwFmtCol &rNew,
+ const sal_Bool bChgFtn )
+{
+ if ( rOld.GetNumCols() <= 1 && rNew.GetNumCols() <= 1 && !bChgFtn )
+ return;
+ // --> OD 2009-08-12 #i97379#
+ // If current lower is a no text frame, then columns are not allowed
+ if ( Lower() && Lower()->IsNoTxtFrm() &&
+ rNew.GetNumCols() > 1 )
+ {
+ return;
+ }
+ // <--
+
+ sal_uInt16 nNewNum, nOldNum = 1;
+ if( Lower() && Lower()->IsColumnFrm() )
+ {
+ SwFrm* pCol = Lower();
+ while( 0 != (pCol=pCol->GetNext()) )
+ ++nOldNum;
+ }
+ nNewNum = rNew.GetNumCols();
+ if( !nNewNum )
+ ++nNewNum;
+ sal_Bool bAtEnd;
+ if( IsSctFrm() )
+ bAtEnd = ((SwSectionFrm*)this)->IsAnyNoteAtEnd();
+ else
+ bAtEnd = sal_False;
+
+ //Einstellung der Spaltenbreiten ist nur bei neuen Formaten notwendig.
+ sal_Bool bAdjustAttributes = nOldNum != rOld.GetNumCols();
+
+ //Wenn die Spaltenanzahl unterschiedlich ist, wird der Inhalt
+ //gesichert und restored.
+ SwFrm *pSave = 0;
+ if( nOldNum != nNewNum || bChgFtn )
+ {
+ SwDoc *pDoc = GetFmt()->GetDoc();
+ OSL_ENSURE( pDoc, "FrmFmt gibt kein Dokument her." );
+ // SaveCntnt wuerde auch den Inhalt der Fussnotencontainer aufsaugen
+ // und im normalen Textfluss unterbringen.
+ if( IsPageBodyFrm() )
+ pDoc->GetCurrentLayout()->RemoveFtns( (SwPageFrm*)GetUpper(), sal_True, sal_False ); //swmod 080218
+ pSave = ::SaveCntnt( this );
+
+ //Wenn Spalten existieren, jetzt aber eine Spaltenanzahl von
+ //0 oder eins gewuenscht ist, so werden die Spalten einfach vernichtet.
+ if ( nNewNum == 1 && !bAtEnd )
+ {
+ ::lcl_RemoveColumns( this, nOldNum );
+ if ( IsBodyFrm() )
+ SetFrmFmt( pDoc->GetDfltFrmFmt() );
+ else
+ GetFmt()->SetFmtAttr( SwFmtFillOrder() );
+ if ( pSave )
+ ::RestoreCntnt( pSave, this, 0, true );
+ return;
+ }
+ if ( nOldNum == 1 )
+ {
+ if ( IsBodyFrm() )
+ SetFrmFmt( pDoc->GetColumnContFmt() );
+ else
+ GetFmt()->SetFmtAttr( SwFmtFillOrder( ATT_LEFT_TO_RIGHT ) );
+ if( !Lower() || !Lower()->IsColumnFrm() )
+ --nOldNum;
+ }
+ if ( nOldNum > nNewNum )
+ {
+ ::lcl_RemoveColumns( this, nOldNum - nNewNum );
+ bAdjustAttributes = sal_True;
+ }
+ else if( nOldNum < nNewNum )
+ {
+ sal_uInt16 nAdd = nNewNum - nOldNum;
+ bAdjustAttributes = lcl_AddColumns( this, nAdd );
+ }
+ }
+
+ if ( !bAdjustAttributes )
+ {
+ if ( rOld.GetLineWidth() != rNew.GetLineWidth() ||
+ rOld.GetWishWidth() != rNew.GetWishWidth() ||
+ rOld.IsOrtho() != rNew.IsOrtho() )
+ bAdjustAttributes = sal_True;
+ else
+ {
+ sal_uInt16 nCount = Min( rNew.GetColumns().Count(), rOld.GetColumns().Count() );
+ for ( sal_uInt16 i = 0; i < nCount; ++i )
+ if ( !(*rOld.GetColumns()[i] == *rNew.GetColumns()[i]) )
+ {
+ bAdjustAttributes = sal_True;
+ break;
+ }
+ }
+ }
+
+ //Sodele, jetzt koennen die Spalten bequem eingestellt werden.
+ AdjustColumns( &rNew, bAdjustAttributes );
+
+ //Erst jetzt den Inhalt restaurieren. Ein frueheres Restaurieren wuerde
+ //unnuetzte Aktionen beim Einstellen zur Folge haben.
+ if ( pSave )
+ {
+ OSL_ENSURE( Lower() && Lower()->IsLayoutFrm() &&
+ ((SwLayoutFrm*)Lower())->Lower() &&
+ ((SwLayoutFrm*)Lower())->Lower()->IsLayoutFrm(),
+ "Gesucht: Spaltenbody (Tod oder Lebend)." ); // ColumnFrms jetzt mit BodyFrm
+ ::RestoreCntnt( pSave, (SwLayoutFrm*)((SwLayoutFrm*)Lower())->Lower(), 0, true );
+ }
+}
+
+/*************************************************************************
+|*
+|* SwLayoutFrm::AdjustColumns()
+|*
+|*************************************************************************/
+
+void SwLayoutFrm::AdjustColumns( const SwFmtCol *pAttr, sal_Bool bAdjustAttributes )
+{
+ if( !Lower()->GetNext() )
+ {
+ Lower()->ChgSize( Prt().SSize() );
+ return;
+ }
+
+ const sal_Bool bVert = IsVertical();
+ //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin
+ SwRectFn fnRect = bVert ? ( IsVertLR() ? fnRectVertL2R : fnRectVert ) : fnRectHori;
+
+ //Ist ein Pointer da, oder sollen wir die Attribute einstellen,
+ //so stellen wir auf jeden Fall die Spaltenbreiten ein. Andernfalls
+ //checken wir, ob eine Einstellung notwendig ist.
+ if ( !pAttr )
+ {
+ pAttr = &GetFmt()->GetCol();
+ if ( !bAdjustAttributes )
+ {
+ long nAvail = (Prt().*fnRect->fnGetWidth)();
+ for ( SwLayoutFrm *pCol = (SwLayoutFrm*)Lower();
+ pCol;
+ pCol = (SwLayoutFrm*)pCol->GetNext() )
+ nAvail -= (pCol->Frm().*fnRect->fnGetWidth)();
+ if ( !nAvail )
+ return;
+ }
+ }
+
+ //Sodele, jetzt koennen die Spalten bequem eingestellt werden.
+ //Die Breiten werden mitgezaehlt, damit wir dem letzten den Rest geben
+ //koennen.
+ SwTwips nAvail = (Prt().*fnRect->fnGetWidth)();
+ const sal_Bool bLine = pAttr->GetLineAdj() != COLADJ_NONE;
+ const sal_uInt16 nMin = bLine ? sal_uInt16( 20 + ( pAttr->GetLineWidth() / 2) ) : 0;
+
+ const sal_Bool bR2L = IsRightToLeft();
+ SwFrm *pCol = bR2L ? GetLastLower() : Lower();
+
+ // --> FME 2004-07-16 #i27399#
+ // bOrtho means we have to adjust the column frames manually. Otherwise
+ // we may use the values returned by CalcColWidth:
+ const sal_Bool bOrtho = pAttr->IsOrtho() && pAttr->GetNumCols() > 0;
+ long nGutter = 0;
+ // <--
+
+ for ( sal_uInt16 i = 0; i < pAttr->GetNumCols(); ++i )
+ {
+ if( !bOrtho )
+ {
+ const SwTwips nWidth = i == (pAttr->GetNumCols() - 1) ?
+ nAvail :
+ pAttr->CalcColWidth( i, sal_uInt16( (Prt().*fnRect->fnGetWidth)() ) );
+
+ const Size aColSz = bVert ?
+ Size( Prt().Width(), nWidth ) :
+ Size( nWidth, Prt().Height() );
+
+ pCol->ChgSize( aColSz );
+
+ // Hierdurch werden die ColumnBodyFrms von Seitenspalten angepasst und
+ // ihr bFixHeight-Flag wird gesetzt, damit sie nicht schrumpfen/wachsen.
+ // Bei Rahmenspalten hingegen soll das Flag _nicht_ gesetzt werden,
+ // da BodyFrms in Rahmenspalten durchaus wachsen/schrumpfen duerfen.
+ if( IsBodyFrm() )
+ ((SwLayoutFrm*)pCol)->Lower()->ChgSize( aColSz );
+
+ nAvail -= nWidth;
+ }
+
+ if ( bOrtho || bAdjustAttributes )
+ {
+ const SwColumn *pC = pAttr->GetColumns()[i];
+ const SwAttrSet* pSet = pCol->GetAttrSet();
+ SvxLRSpaceItem aLR( pSet->GetLRSpace() );
+
+ //Damit die Trennlinien Platz finden, muessen sie hier
+ //Beruecksichtigung finden. Ueberall wo zwei Spalten aufeinanderstossen
+ //wird jeweils rechts bzw. links ein Sicherheitsabstand von 20 plus
+ //der halben Penbreite einkalkuliert.
+ const sal_uInt16 nLeft = pC->GetLeft();
+ const sal_uInt16 nRight = pC->GetRight();
+
+ aLR.SetLeft ( nLeft );
+ aLR.SetRight( nRight );
+
+ if ( bLine )
+ {
+ if ( i == 0 )
+ {
+ aLR.SetRight( Max( nRight, nMin ) );
+ }
+ else if ( i == pAttr->GetNumCols() - 1 )
+ {
+ aLR.SetLeft ( Max( nLeft, nMin ) );
+ }
+ else
+ {
+ aLR.SetLeft ( Max( nLeft, nMin ) );
+ aLR.SetRight( Max( nRight, nMin ) );
+ }
+ }
+
+ if ( bAdjustAttributes )
+ {
+ SvxULSpaceItem aUL( pSet->GetULSpace() );
+ aUL.SetUpper( pC->GetUpper());
+ aUL.SetLower( pC->GetLower());
+
+ ((SwLayoutFrm*)pCol)->GetFmt()->SetFmtAttr( aLR );
+ ((SwLayoutFrm*)pCol)->GetFmt()->SetFmtAttr( aUL );
+ }
+
+ nGutter += aLR.GetLeft() + aLR.GetRight();
+ }
+
+ pCol = bR2L ? pCol->GetPrev() : pCol->GetNext();
+ }
+
+ if( bOrtho )
+ {
+ long nInnerWidth = ( nAvail - nGutter ) / pAttr->GetNumCols();
+ pCol = Lower();
+ for( sal_uInt16 i = 0; i < pAttr->GetNumCols(); pCol = pCol->GetNext(), ++i )
+ {
+ SwTwips nWidth;
+ if ( i == pAttr->GetNumCols() - 1 )
+ nWidth = nAvail;
+ else
+ {
+ SvxLRSpaceItem aLR( pCol->GetAttrSet()->GetLRSpace() );
+ nWidth = nInnerWidth + aLR.GetLeft() + aLR.GetRight();
+ }
+ if( nWidth < 0 )
+ nWidth = 0;
+
+ const Size aColSz = bVert ?
+ Size( Prt().Width(), nWidth ) :
+ Size( nWidth, Prt().Height() );
+
+ pCol->ChgSize( aColSz );
+
+ if( IsBodyFrm() )
+ ((SwLayoutFrm*)pCol)->Lower()->ChgSize( aColSz );
+
+ nAvail -= nWidth;
+ }
+ }
+}
+
+
+
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/layout/dbg_lay.cxx b/sw/source/core/layout/dbg_lay.cxx
new file mode 100644
index 000000000000..8f70b6925a0a
--- /dev/null
+++ b/sw/source/core/layout/dbg_lay.cxx
@@ -0,0 +1,868 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+#if OSL_DEBUG_LEVEL > 1
+
+/*
+ * Und hier die Beschreibung:
+ *
+ * Durch die PROTOCOL-Makros wird es ermoeglicht, Ereignisse im Frame-Methoden zu protokollieren.
+ * In protokollwuerdigen Stellen in Frame-Methoden muss entweder ein PROTOCOL(...) oder bei Methoden,
+ * bei denen auch das Verlassen der Methode mitprotokolliert werden soll, ein PROTOCOL_ENTER(...)-Makro
+ * stehen.
+ * Die Parameter der PROTOCOL-Makros sind
+ * 1. Ein Pointer auf einen SwFrm, also meist "this" oder "rThis"
+ * 2. Die Funktionsgruppe z.B. PROT_MAKEALL, hierueber wird (inline) entschieden, ob dies
+ * zur Zeit protokolliert werden soll oder nicht.
+ * 3. Die Aktion, im Normalfall 0, aber z.B. ein ACT_START bewirkt eine Einrueckung in der
+ * Ausgabedatei, ein ACT_END nimmt dies wieder zurueck. Auf diese Art wird z.B. durch
+ * PROTOCOL_ENTER am Anfang einer Methode eingerueckt und beim Verlassen wieder zurueck.
+ * 4. Der vierte Parameter ist ein void-Pointer, damit man irgendetwas uebergeben kann,
+ * was in das Protokoll einfliessen kann, typesches Beispiel bei PROT_GROW muss man
+ * einen Pointer auf den Wert, um den gegrowt werden soll, uebergeben.
+ *
+ *
+ * Das Protokoll ist die Datei "dbg_lay.out" im aktuellen (BIN-)Verzeichnis.
+ * Es enthaelt Zeilen mit FrmId, Funktionsgruppe sowie weiteren Infos.
+ *
+ * Was genau protokolliert wird, kann auf folgende Arten eingestellt werden:
+ * 1. Die statische Variable SwProtokoll::nRecord enthaelt die Funktionsgruppen,
+ * die aufgezeichnet werden sollen.
+ * Ein Wert von z.B. PROT_GROW bewirkt, das Aufrufe von SwFrm::Grow dokumentiert werden,
+ * PROT_MAKEALL protokolliert Aufrufe von xxx::MakeAll.
+ * Die PROT_XY-Werte koennen oderiert werden.
+ * Default ist Null, es wird keine Methode aufgezeichnet.
+ * 2. In der SwImplProtocol-Klasse gibt es einen Filter fuer Frame-Typen,
+ * nur die Methodenaufrufe von Frame-Typen, die dort gesetzt sind, werden protokolliert.
+ * Der Member nTypes kann auf Werte wie FRM_PAGE, FRM_SECTION gesetzt und oderiert werden.
+ * Default ist 0xFFFF, d.h. alle Frame-Typen.
+ * 3. In der SwImplProtocol-Klasse gibt es einen ArrayPointer auf FrmIds, die zu ueberwachen sind.
+ * Ist der Pointer Null, so werden alle Frames protokolliert, ansonsten nur Frames,
+ * die in dem Array vermerkt sind.
+ *
+ * Eine Aufzeichnung in Gang zu setzen, erfordert entweder Codemanipulation, z.B. in
+ * SwProtocol::Init() einen anderen Default fuer nRecord setzen oder Debuggermanipulation.
+ * Im Debugger gibt verschiedene, sich anbietende Stellen:
+ * 1. In SwProtocol::Init() einen Breakpoint setzen und dort nRecord manipulieren, ggf.
+ * FrmIds eintragen, dann beginnt die Aufzeichnung bereits beim Programmstart.
+ * 2. Waehrend des Programmlaufs einen Breakpoint vor irgendein PROTOCOL oder PROTOCOL_ENTER-
+ * Makro setzen, dann am SwProtocol::nRecord das unterste Bit setzen (PROT_INIT). Dies
+ * bewirkt, dass die Funktionsgruppe des folgenden Makros aktiviert und in Zukunft
+ * protokolliert wird.
+ * 3. Spezialfall von 2.: Wenn man 2. in der Methode SwRootFrm::Paint(..) anwendet, werden
+ * die Aufzeichnungseinstellung aus der Datei "dbg_lay.ini" ausgelesen!
+ * In dieser INI-Datei kann es Kommentarzeilen geben, diese beginnen mit '#', dann
+ * sind die Sektionen "[frmid]", "[frmtype]" und "[record]" relevant.
+ * Nach [frmid] koennen die FrameIds der zu protokollierenden Frames folgen. Gibt es
+ * dort keine Eintraege, werden alle Frames aufgezeichnet.
+ * Nach [frmtype] koennen FrameTypen folgen, die aufgezeichnet werden sollen, da der
+ * Default hier allerdings USHRT_MAX ist, werden sowieso alle aufgezeichnet. Man kann
+ * allerdings auch Typen entfernen, in dem man ein '!' vor den Wert setzt, z.B.
+ * !0xC000 nimmt die SwCntntFrms aus der Aufzeichnung heraus.
+ * Nach [record] folgen die Funktionsgruppen, die aufgezeichnet werden sollen, Default
+ * ist hier 0, also keine. Auch hier kann man mit einem vorgestellten '!' Funktionen
+ * wieder entfernen.
+ * Hier mal ein Beispiel fuer eine INI-Datei:
+ * ------------------------------------------
+ * #Funktionen: Alle, ausser PRTAREA
+ * [record] 0xFFFFFFE !0x200
+ * [frmid]
+ * #folgende FrmIds:
+ * 1 2 12 13 14 15
+ * #keine Layoutframes ausser ColumnFrms
+ * [frmtype] !0x3FFF 0x4
+ * ------------------------------------------
+ *
+ * Wenn die Aufzeichnung erstmal laeuft, kann man in SwImplProtocol::_Record(...) mittels
+ * Debugger vielfaeltige Manipulationen vornehmen, z.B. bezueglich FrameTypen oder FrmIds.
+ *
+ * --------------------------------------------------*/
+
+#if !defined(OSL_DEBUG_LEVEL) || OSL_DEBUG_LEVEL <= 1
+#error Who broken the makefiles?
+#endif
+
+
+
+#include "dbg_lay.hxx"
+#include <tools/stream.hxx>
+
+#ifndef _SVSTDARR_HXX
+#define _SVSTDARR_USHORTS
+#define _SVSTDARR_USHORTSSORT
+#include <svl/svstdarr.hxx>
+#endif
+
+#include <stdio.h>
+
+#include "frame.hxx"
+#include "layfrm.hxx"
+#include "flyfrm.hxx"
+#include "txtfrm.hxx"
+#include "ndtxt.hxx"
+#include "dflyobj.hxx"
+#include <fntcache.hxx>
+// OD 2004-05-24 #i28701#
+#include <sortedobjs.hxx>
+
+sal_uLong SwProtocol::nRecord = 0;
+SwImplProtocol* SwProtocol::pImpl = NULL;
+
+sal_uLong lcl_GetFrameId( const SwFrm* pFrm )
+{
+#if OSL_DEBUG_LEVEL > 1
+ static sal_Bool bFrameId = sal_False;
+ if( bFrameId )
+ return pFrm->GetFrmId();
+#endif
+ if( pFrm && pFrm->IsTxtFrm() )
+ return ((SwTxtFrm*)pFrm)->GetTxtNode()->GetIndex();
+ return 0;
+}
+
+class SwImplProtocol
+{
+ SvFileStream *pStream; // Ausgabestream
+ SvUShortsSort *pFrmIds; // welche FrmIds sollen aufgezeichnet werden ( NULL == alle )
+ std::vector<long> aVars; // Variables
+ ByteString aLayer; // Einrueckung der Ausgabe (" " pro Start/End)
+ sal_uInt16 nTypes; // welche Typen sollen aufgezeichnet werden
+ sal_uInt16 nLineCount; // Ausgegebene Zeilen
+ sal_uInt16 nMaxLines; // Maximal auszugebende Zeilen
+ sal_uInt8 nInitFile; // Bereich (FrmId,FrmType,Record) beim Einlesen der INI-Datei
+ sal_uInt8 nTestMode; // Special fuer Testformatierung, es wird ggf. nur
+ // innerhalb einer Testformatierung aufgezeichnet.
+ void _Record( const SwFrm* pFrm, sal_uLong nFunction, sal_uLong nAct, void* pParam );
+ sal_Bool NewStream();
+ void CheckLine( ByteString& rLine );
+ void SectFunc( ByteString &rOut, const SwFrm* pFrm, sal_uLong nAct, void* pParam );
+public:
+ SwImplProtocol();
+ ~SwImplProtocol();
+ // Aufzeichnen
+ void Record( const SwFrm* pFrm, sal_uLong nFunction, sal_uLong nAct, void* pParam )
+ { if( pStream ) _Record( pFrm, nFunction, nAct, pParam ); }
+ sal_Bool InsertFrm( sal_uInt16 nFrmId ); // FrmId aufnehmen zum Aufzeichnen
+ sal_Bool DeleteFrm( sal_uInt16 nFrmId ); // FrmId entfernen, diesen nicht mehr Aufzeichnen
+ void FileInit(); // Auslesen der INI-Datei
+ void ChkStream() { if( !pStream ) NewStream(); }
+ void SnapShot( const SwFrm* pFrm, sal_uLong nFlags );
+ void GetVar( const sal_uInt16 nNo, long& rVar )
+ { if( nNo < aVars.size() ) rVar = aVars[ nNo ]; }
+};
+
+/* --------------------------------------------------
+ * Durch das PROTOCOL_ENTER-Makro wird ein SwEnterLeave-Objekt erzeugt,
+ * wenn die aktuelle Funktion aufgezeichnet werden soll, wird ein
+ * SwImplEnterLeave-Objekt angelegt. Der Witz dabei ist, das der Ctor
+ * des Impl-Objekt am Anfang der Funktion und automatisch der Dtor beim
+ * Verlassen der Funktion gerufen wird. In der Basis-Implementierung ruft
+ * der Ctor lediglich ein PROTOCOL(..) mit ACT_START und im Dtor ein
+ * PROTOCOL(..) mit ACT_END.
+ * Es lassen sich Ableitungen der Klasse bilden, um z.B. beim Verlassen
+ * einer Funktion Groessenaenderungen des Frames zu dokumentieren u.v.a.m.
+ * Dazu braucht dann nur noch in SwEnterLeave::Ctor(...) die gewuenschte
+ * SwImplEnterLeave-Klasse angelegt zu werden.
+ *
+ * --------------------------------------------------*/
+
+class SwImplEnterLeave
+{
+protected:
+ const SwFrm* pFrm; // Der Frame,
+ sal_uLong nFunction, nAction; // die Funktion, ggf. die Aktion
+ void* pParam; // und weitere Parameter
+public:
+ SwImplEnterLeave( const SwFrm* pF, sal_uLong nFunct, sal_uLong nAct, void* pPar )
+ : pFrm( pF ), nFunction( nFunct ), nAction( nAct ), pParam( pPar ) {}
+ virtual void Enter(); // Ausgabe beim Eintritt
+ virtual void Leave(); // Ausgabe beim Verlassen
+};
+
+class SwSizeEnterLeave : public SwImplEnterLeave
+{
+ long nFrmHeight;
+public:
+ SwSizeEnterLeave( const SwFrm* pF, sal_uLong nFunct, sal_uLong nAct, void* pPar )
+ : SwImplEnterLeave( pF, nFunct, nAct, pPar ), nFrmHeight( pF->Frm().Height() ) {}
+ virtual void Leave(); // Ausgabe der Groessenaenderung
+};
+
+class SwUpperEnterLeave : public SwImplEnterLeave
+{
+ sal_uInt16 nFrmId;
+public:
+ SwUpperEnterLeave( const SwFrm* pF, sal_uLong nFunct, sal_uLong nAct, void* pPar )
+ : SwImplEnterLeave( pF, nFunct, nAct, pPar ), nFrmId( 0 ) {}
+ virtual void Enter(); // Ausgabe
+ virtual void Leave(); // Ausgabe der FrmId des Uppers
+};
+
+class SwFrmChangesLeave : public SwImplEnterLeave
+{
+ SwRect aFrm;
+public:
+ SwFrmChangesLeave( const SwFrm* pF, sal_uLong nFunct, sal_uLong nAct, void* pPar )
+ : SwImplEnterLeave( pF, nFunct, nAct, pPar ), aFrm( pF->Frm() ) {}
+ virtual void Enter(); // keine Ausgabe
+ virtual void Leave(); // Ausgabe bei Aenderung der Frm-Area
+};
+
+void SwProtocol::Record( const SwFrm* pFrm, sal_uLong nFunction, sal_uLong nAct, void* pParam )
+{
+ if( Start() )
+ { // Hier landen wir, wenn im Debugger SwProtocol::nRecord mit PROT_INIT(0x1) oderiert wurde
+ sal_Bool bFinit = sal_False; // Dies bietet im Debugger die Moeglichkeit,
+ if( bFinit ) // die Aufzeichnung dieser Action zu beenden
+ {
+ nRecord &= ~nFunction; // Diese Funktion nicht mehr aufzeichnen
+ nRecord &= ~PROT_INIT; // PROT_INIT stets zuruecksetzen
+ return;
+ }
+ nRecord |= nFunction; // Aufzeichnung dieser Funktion freischalten
+ nRecord &= ~PROT_INIT; // PROT_INIT stets zuruecksetzen
+ if( pImpl )
+ pImpl->ChkStream();
+ }
+ if( !pImpl ) // Impl-Object anlegen, wenn noetig
+ pImpl = new SwImplProtocol();
+ pImpl->Record( pFrm, nFunction, nAct, pParam ); // ...und Aufzeichnen
+}
+
+// Die folgende Funktion wird beim Anziehen der Writer-DLL durch TxtInit(..) aufgerufen
+// und ermoeglicht dem Debuggenden Funktionen und/oder FrmIds freizuschalten
+
+void SwProtocol::Init()
+{
+ nRecord = 0;
+ XubString aName( "dbg_lay.go", RTL_TEXTENCODING_MS_1252 );
+ SvFileStream aStream( aName, STREAM_READ );
+ if( aStream.IsOpen() )
+ {
+ pImpl = new SwImplProtocol();
+ pImpl->FileInit();
+ }
+ aStream.Close();
+}
+
+// Ende der Aufzeichnung
+
+void SwProtocol::Stop()
+{
+ if( pImpl )
+ {
+ delete pImpl;
+ pImpl = NULL;
+ if( pFntCache )
+ pFntCache->Flush();
+ }
+ nRecord = 0;
+}
+
+// Creates a more or less detailed snapshot of the layout structur
+
+void SwProtocol::SnapShot( const SwFrm* pFrm, sal_uLong nFlags )
+{
+ if( pImpl )
+ pImpl->SnapShot( pFrm, nFlags );
+}
+
+void SwProtocol::GetVar( const sal_uInt16 nNo, long& rVar )
+{
+ if( pImpl )
+ pImpl->GetVar( nNo, rVar );
+}
+
+SwImplProtocol::SwImplProtocol()
+ : pStream( NULL ), pFrmIds( NULL ), nTypes( 0xffff ),
+ nLineCount( 0 ), nMaxLines( USHRT_MAX ), nTestMode( 0 )
+{
+ NewStream();
+}
+
+sal_Bool SwImplProtocol::NewStream()
+{
+ XubString aName( "dbg_lay.out", RTL_TEXTENCODING_MS_1252 );
+ nLineCount = 0;
+ pStream = new SvFileStream( aName, STREAM_WRITE | STREAM_TRUNC );
+ if( pStream->GetError() )
+ {
+ delete pStream;
+ pStream = NULL;
+ }
+ return 0 != pStream;
+}
+
+SwImplProtocol::~SwImplProtocol()
+{
+ if( pStream )
+ {
+ pStream->Close();
+ delete pStream;
+ }
+ delete pFrmIds;
+ aVars.clear();
+}
+
+/* --------------------------------------------------
+ * SwImplProtocol::CheckLine analysiert eine Zeile der INI-Datei
+ * --------------------------------------------------*/
+
+void SwImplProtocol::CheckLine( ByteString& rLine )
+{
+ rLine = rLine.ToLowerAscii(); // Gross/Kleinschreibung ist einerlei
+ while( STRING_LEN > rLine.SearchAndReplace( '\t', ' ' ) )
+ ; //nothing // Tabs werden durch Blanks ersetzt
+ if( '#' == rLine.GetChar(0) ) // Kommentarzeilen beginnen mit '#'
+ return;
+ if( '[' == rLine.GetChar(0) ) // Bereiche: FrmIds, Typen oder Funktionen
+ {
+ ByteString aTmp = rLine.GetToken( 0, ']' );
+ if( "[frmid" == aTmp ) // Bereich FrmIds
+ {
+ nInitFile = 1;
+ delete pFrmIds;
+ pFrmIds = NULL; // Default: Alle Frames aufzeichnen
+ }
+ else if( "[frmtype" == aTmp )// Bereich Typen
+ {
+ nInitFile = 2;
+ nTypes = USHRT_MAX; // Default: Alle FrmaeTypen aufzeichnen
+ }
+ else if( "[record" == aTmp )// Bereich Funktionen
+ {
+ nInitFile = 3;
+ SwProtocol::SetRecord( 0 );// Default: Keine Funktion wird aufgezeichnet
+ }
+ else if( "[test" == aTmp )// Bereich Funktionen
+ {
+ nInitFile = 4; // Default:
+ nTestMode = 0; // Ausserhalb der Testformatierung wird aufgezeichnet
+ }
+ else if( "[max" == aTmp )// maximale Zeilenzahl
+ {
+ nInitFile = 5; // Default:
+ nMaxLines = USHRT_MAX;
+ }
+ else if( "[var" == aTmp )// variables
+ {
+ nInitFile = 6;
+ }
+ else
+ nInitFile = 0; // Nanu: Unbekannter Bereich?
+ rLine.Erase( 0, aTmp.Len() + 1 );
+ }
+ sal_uInt16 nToks = rLine.GetTokenCount( ' ' ); // Blanks (oder Tabs) sind die Trenner
+ for( sal_uInt16 i=0; i < nToks; ++i )
+ {
+ ByteString aTok = rLine.GetToken( i, ' ' );
+ sal_Bool bNo = sal_False;
+ if( '!' == aTok.GetChar(0) )
+ {
+ bNo = sal_True; // Diese(n) Funktion/Typ entfernen
+ aTok.Erase( 0, 1 );
+ }
+ if( aTok.Len() )
+ {
+ sal_uLong nVal;
+ sscanf( aTok.GetBuffer(), "%li", &nVal );
+ switch ( nInitFile )
+ {
+ case 1: InsertFrm( sal_uInt16( nVal ) ); // FrmId aufnehmen
+ break;
+ case 2: {
+ sal_uInt16 nNew = (sal_uInt16)nVal;
+ if( bNo )
+ nTypes &= ~nNew; // Typ entfernen
+ else
+ nTypes |= nNew; // Typ aufnehmen
+ }
+ break;
+ case 3: {
+ sal_uLong nOld = SwProtocol::Record();
+ if( bNo )
+ nOld &= ~nVal; // Funktion entfernen
+ else
+ nOld |= nVal; // Funktion aufnehmen
+ SwProtocol::SetRecord( nOld );
+ }
+ break;
+ case 4: {
+ sal_uInt8 nNew = (sal_uInt8)nVal;
+ if( bNo )
+ nTestMode &= ~nNew; // TestMode zuruecksetzen
+ else
+ nTestMode |= nNew; // TestMode setzen
+ }
+ break;
+ case 5: nMaxLines = (sal_uInt16)nVal;
+ break;
+ case 6: aVars.push_back( (long)nVal );
+ break;
+ }
+ }
+ }
+}
+
+/* --------------------------------------------------
+ * SwImplProtocol::FileInit() liest die Datei "dbg_lay.ini"
+ * im aktuellen Verzeichnis und wertet sie aus.
+ * --------------------------------------------------*/
+void SwImplProtocol::FileInit()
+{
+ XubString aName( "dbg_lay.ini", RTL_TEXTENCODING_MS_1252 );
+ SvFileStream aStream( aName, STREAM_READ );
+ if( aStream.IsOpen() )
+ {
+ ByteString aLine;
+ nInitFile = 0;
+ while( !aStream.IsEof() )
+ {
+ sal_Char c;
+ aStream >> c;
+ if( '\n' == c || '\r' == c ) // Zeilenende
+ {
+ aLine.EraseLeadingChars();
+ aLine.EraseTrailingChars();
+ if( aLine.Len() )
+ CheckLine( aLine ); // Zeile auswerten
+ aLine.Erase();
+ }
+ else
+ aLine += c;
+ }
+ if( aLine.Len() )
+ CheckLine( aLine ); // letzte Zeile auswerten
+ }
+ aStream.Close();
+}
+
+/* --------------------------------------------------
+ * lcl_Start sorgt fuer Einrueckung um zwei Blanks bei ACT_START
+ * und nimmt diese bei ACT_END wieder zurueck.
+ * --------------------------------------------------*/
+void lcl_Start( ByteString& rOut, ByteString& rLay, sal_uLong nAction )
+{
+ if( nAction == ACT_START )
+ {
+ rLay += " ";
+ rOut += " On";
+ }
+ else if( nAction == ACT_END )
+ {
+ if( rLay.Len() > 1 )
+ {
+ rLay.Erase( rLay.Len() - 2 );
+ rOut.Erase( 0, 2 );
+ }
+ rOut += " Off";
+ }
+}
+
+/* --------------------------------------------------
+ * lcl_Flags gibt das ValidSize-, ValidPos- und ValidPrtArea-Flag ("Sz","Ps","PA")
+ * des Frames aus, "+" fuer valid, "-" fuer invalid.
+ * --------------------------------------------------*/
+
+void lcl_Flags( ByteString& rOut, const SwFrm* pFrm )
+{
+ rOut += " Sz";
+ rOut += pFrm->GetValidSizeFlag() ? '+' : '-';
+ rOut += " Ps";
+ rOut += pFrm->GetValidPosFlag() ? '+' : '-';
+ rOut += " PA";
+ rOut += pFrm->GetValidPrtAreaFlag() ? '+' : '-';
+}
+
+/* --------------------------------------------------
+ * lcl_FrameType gibt den Typ des Frames in Klartext aus.
+ * --------------------------------------------------*/
+
+void lcl_FrameType( ByteString& rOut, const SwFrm* pFrm )
+{
+ if( pFrm->IsTxtFrm() )
+ rOut += "Txt ";
+ else if( pFrm->IsLayoutFrm() )
+ {
+ if( pFrm->IsPageFrm() )
+ rOut += "Page ";
+ else if( pFrm->IsColumnFrm() )
+ rOut += "Col ";
+ else if( pFrm->IsBodyFrm() )
+ {
+ if( pFrm->GetUpper() && pFrm->IsColBodyFrm() )
+ rOut += "(Col)";
+ rOut += "Body ";
+ }
+ else if( pFrm->IsRootFrm() )
+ rOut += "Root ";
+ else if( pFrm->IsCellFrm() )
+ rOut += "Cell ";
+ else if( pFrm->IsTabFrm() )
+ rOut += "Tab ";
+ else if( pFrm->IsRowFrm() )
+ rOut += "Row ";
+ else if( pFrm->IsSctFrm() )
+ rOut += "Sect ";
+ else if( pFrm->IsHeaderFrm() )
+ rOut += "Header ";
+ else if( pFrm->IsFooterFrm() )
+ rOut += "Footer ";
+ else if( pFrm->IsFtnFrm() )
+ rOut += "Ftn ";
+ else if( pFrm->IsFtnContFrm() )
+ rOut += "FtnCont ";
+ else if( pFrm->IsFlyFrm() )
+ rOut += "Fly ";
+ else
+ rOut += "Layout ";
+ }
+ else if( pFrm->IsNoTxtFrm() )
+ rOut += "NoTxt ";
+ else
+ rOut += "Not impl. ";
+}
+
+/* --------------------------------------------------
+ * SwImplProtocol::Record(..) wird nur gerufen, wenn das PROTOCOL-Makro
+ * feststellt, dass die Funktion aufgezeichnet werden soll ( SwProtocol::nRecord ).
+ * In dieser Methode werden noch die beiden weiteren Einschraenkungen ueberprueft,
+ * ob die FrmId und der FrameType zu den aufzuzeichnenden gehoeren.
+ * --------------------------------------------------*/
+
+void SwImplProtocol::_Record( const SwFrm* pFrm, sal_uLong nFunction, sal_uLong nAct, void* pParam )
+{
+ sal_uInt16 nSpecial = 0;
+ if( nSpecial ) // Debugger-Manipulationsmoeglichkeit
+ {
+ sal_uInt16 nId = sal_uInt16(lcl_GetFrameId( pFrm ));
+ switch ( nSpecial )
+ {
+ case 1: InsertFrm( nId ); break;
+ case 2: DeleteFrm( nId ); break;
+ case 3: delete pFrmIds; pFrmIds = NULL; break;
+ case 4: delete pStream; pStream = NULL; break;
+ }
+ return;
+ }
+ if( !pStream && !NewStream() )
+ return; // Immer noch kein Stream
+
+ if( pFrmIds && !pFrmIds->Seek_Entry( sal_uInt16(lcl_GetFrameId( pFrm )) ) )
+ return; // gehoert nicht zu den gewuenschten FrmIds
+
+ if( !(pFrm->GetType() & nTypes) )
+ return; // Der Typ ist unerwuenscht
+
+ if( 1 == nTestMode && nFunction != PROT_TESTFORMAT )
+ return; // Wir sollen nur innerhalb einer Testformatierung aufzeichnen
+ sal_Bool bTmp = sal_False;
+ ByteString aOut = aLayer;
+ aOut += ByteString::CreateFromInt64( lcl_GetFrameId( pFrm ) );
+ aOut += ' ';
+ lcl_FrameType( aOut, pFrm ); // dann den FrameType
+ switch ( nFunction ) // und die Funktion
+ {
+ case PROT_SNAPSHOT: lcl_Flags( aOut, pFrm );
+ break;
+ case PROT_MAKEALL: aOut += "MakeAll";
+ lcl_Start( aOut, aLayer, nAct );
+ if( nAct == ACT_START )
+ lcl_Flags( aOut, pFrm );
+ break;
+ case PROT_MOVE_FWD: bTmp = sal_True; // NoBreak
+ case PROT_MOVE_BWD: aOut += ( nFunction == bTmp ) ? "Fwd" : "Bwd";
+ lcl_Start( aOut, aLayer, nAct );
+ if( pParam )
+ {
+ aOut += ' ';
+ aOut += ByteString::CreateFromInt32( *((sal_uInt16*)pParam) );
+ }
+ break;
+ case PROT_GROW_TST: if( ACT_START != nAct )
+ return;
+ aOut += "TestGrow";
+ break;
+ case PROT_SHRINK_TST: if( ACT_START != nAct )
+ return;
+ aOut += "TestShrink";
+ break;
+ case PROT_ADJUSTN :
+ case PROT_SHRINK: bTmp = sal_True; // NoBreak
+ case PROT_GROW: aOut += !bTmp ? "Grow" :
+ ( nFunction == PROT_SHRINK ? "Shrink" : "AdjustNgbhd" );
+ lcl_Start( aOut, aLayer, nAct );
+ if( pParam )
+ {
+ aOut += ' ';
+ aOut += ByteString::CreateFromInt64( *((long*)pParam) );
+ }
+ break;
+ case PROT_POS: break;
+ case PROT_PRTAREA: aOut += "PrtArea";
+ lcl_Start( aOut, aLayer, nAct );
+ break;
+ case PROT_SIZE: aOut += "Size";
+ lcl_Start( aOut, aLayer, nAct );
+ aOut += ' ';
+ aOut += ByteString::CreateFromInt64( pFrm->Frm().Height() );
+ break;
+ case PROT_LEAF: aOut += "Prev/NextLeaf";
+ lcl_Start( aOut, aLayer, nAct );
+ aOut += ' ';
+ if( pParam )
+ {
+ aOut += ' ';
+ aOut += ByteString::CreateFromInt64( lcl_GetFrameId( (SwFrm*)pParam ) );
+ }
+ break;
+ case PROT_FILE_INIT: FileInit();
+ aOut = "Initialize";
+ break;
+ case PROT_SECTION: SectFunc( aOut, pFrm, nAct, pParam );
+ break;
+ case PROT_CUT: bTmp = sal_True; // NoBreak
+ case PROT_PASTE: aOut += bTmp ? "Cut from " : "Paste to ";
+ aOut += ByteString::CreateFromInt64( lcl_GetFrameId( (SwFrm*)pParam ) );
+ break;
+ case PROT_TESTFORMAT: aOut += "Test";
+ lcl_Start( aOut, aLayer, nAct );
+ if( ACT_START == nAct )
+ nTestMode |= 2;
+ else
+ nTestMode &= ~2;
+ break;
+ case PROT_FRMCHANGES:
+ {
+ SwRect& rFrm = *((SwRect*)pParam);
+ if( pFrm->Frm().Pos() != rFrm.Pos() )
+ {
+ aOut += "PosChg: (";
+ aOut += ByteString::CreateFromInt64(rFrm.Left());
+ aOut += ", ";
+ aOut += ByteString::CreateFromInt64(rFrm.Top());
+ aOut += ") (";
+ aOut += ByteString::CreateFromInt64(pFrm->Frm().Left());
+ aOut += ", ";
+ aOut += ByteString::CreateFromInt64(pFrm->Frm().Top());
+ aOut += ") ";
+ }
+ if( pFrm->Frm().Height() != rFrm.Height() )
+ {
+ aOut += "Height: ";
+ aOut += ByteString::CreateFromInt64(rFrm.Height());
+ aOut += " -> ";
+ aOut += ByteString::CreateFromInt64(pFrm->Frm().Height());
+ aOut += " ";
+ }
+ if( pFrm->Frm().Width() != rFrm.Width() )
+ {
+ aOut += "Width: ";
+ aOut += ByteString::CreateFromInt64(rFrm.Width());
+ aOut += " -> ";
+ aOut += ByteString::CreateFromInt64(pFrm->Frm().Width());
+ aOut += " ";
+ }
+ break;
+ }
+ }
+ *pStream << aOut.GetBuffer() << endl; // Ausgabe
+ pStream->Flush(); // Gleich auf die Platte, damit man mitlesen kann
+ if( ++nLineCount >= nMaxLines ) // Maximale Ausgabe erreicht?
+ SwProtocol::SetRecord( 0 ); // => Ende der Aufzeichnung
+}
+
+/* --------------------------------------------------
+ * SwImplProtocol::SectFunc(...) wird von SwImplProtocol::_Record(..) gerufen,
+ * hier werden die Ausgaben rund um SectionFrms abgehandelt.
+ * --------------------------------------------------*/
+
+void SwImplProtocol::SectFunc( ByteString &rOut, const SwFrm* , sal_uLong nAct, void* pParam )
+{
+ sal_Bool bTmp = sal_False;
+ switch( nAct )
+ {
+ case ACT_MERGE: rOut += "Merge Section ";
+ rOut += ByteString::CreateFromInt64( lcl_GetFrameId( (SwFrm*)pParam ) );
+ break;
+ case ACT_CREATE_MASTER: bTmp = sal_True; // NoBreak
+ case ACT_CREATE_FOLLOW: rOut += "Create Section ";
+ rOut += bTmp ? "Master to " : "Follow from ";
+ rOut += ByteString::CreateFromInt64( lcl_GetFrameId( (SwFrm*)pParam ) );
+ break;
+ case ACT_DEL_MASTER: bTmp = sal_True; // NoBreak
+ case ACT_DEL_FOLLOW: rOut += "Delete Section ";
+ rOut += bTmp ? "Master to " : "Follow from ";
+ rOut += ByteString::CreateFromInt64( lcl_GetFrameId( (SwFrm*)pParam ) );
+ break;
+ }
+}
+
+/* --------------------------------------------------
+ * SwImplProtocol::InsertFrm(..) nimmt eine neue FrmId zum Aufzeichnen auf,
+ * wenn pFrmIds==NULL, werden alle aufgezeichnet, sobald durch InsertFrm(..)
+ * pFrmIds angelegt wird, werden nur noch die enthaltenen FrmIds aufgezeichnet.
+ * --------------------------------------------------*/
+
+sal_Bool SwImplProtocol::InsertFrm( sal_uInt16 nId )
+{
+ if( !pFrmIds )
+ pFrmIds = new SvUShortsSort(5,5);
+ if( pFrmIds->Seek_Entry( nId ) )
+ return sal_False;
+ pFrmIds->Insert( nId );
+ return sal_True;
+}
+
+/* --------------------------------------------------
+ * SwImplProtocol::DeleteFrm(..) entfernt eine FrmId aus dem pFrmIds-Array,
+ * so dass diese Frame nicht mehr aufgezeichnet wird.
+ * --------------------------------------------------*/
+sal_Bool SwImplProtocol::DeleteFrm( sal_uInt16 nId )
+{
+ sal_uInt16 nPos;
+ if( !pFrmIds || !pFrmIds->Seek_Entry( nId, &nPos ) )
+ return sal_False;
+ pFrmIds->Remove( nPos );
+ return sal_True;
+}
+
+/*--------------------------------------------------
+ * SwProtocol::SnapShot(..)
+ * creates a snapshot of the given frame and its content.
+ * --------------------------------------------------*/
+void SwImplProtocol::SnapShot( const SwFrm* pFrm, sal_uLong nFlags )
+{
+ while( pFrm )
+ {
+ _Record( pFrm, PROT_SNAPSHOT, 0, 0);
+ if( pFrm->GetDrawObjs() && nFlags & SNAP_FLYFRAMES )
+ {
+ aLayer += "[ ";
+ const SwSortedObjs &rObjs = *pFrm->GetDrawObjs();
+ for ( sal_uInt16 i = 0; i < rObjs.Count(); ++i )
+ {
+ SwAnchoredObject* pObj = rObjs[i];
+ if ( pObj->ISA(SwFlyFrm) )
+ SnapShot( static_cast<SwFlyFrm*>(pObj), nFlags );
+ }
+ if( aLayer.Len() > 1 )
+ aLayer.Erase( aLayer.Len() - 2 );
+ }
+ if( pFrm->IsLayoutFrm() && nFlags & SNAP_LOWER &&
+ ( !pFrm->IsTabFrm() || nFlags & SNAP_TABLECONT ) )
+ {
+ aLayer += " ";
+ SnapShot( ((SwLayoutFrm*)pFrm)->Lower(), nFlags );
+ if( aLayer.Len() > 1 )
+ aLayer.Erase( aLayer.Len() - 2 );
+ }
+ pFrm = pFrm->GetNext();
+ }
+}
+
+/* --------------------------------------------------
+ * SwEnterLeave::Ctor(..) wird vom eigentlichen (inline-)Kontruktor gerufen,
+ * wenn die Funktion aufgezeichnet werden soll.
+ * Die Aufgabe ist es abhaengig von der Funktion das richtige SwImplEnterLeave-Objekt
+ * zu erzeugen, alles weitere geschieht dann in dessen Ctor/Dtor.
+ * --------------------------------------------------*/
+void SwEnterLeave::Ctor( const SwFrm* pFrm, sal_uLong nFunc, sal_uLong nAct, void* pPar )
+{
+ switch( nFunc )
+ {
+ case PROT_ADJUSTN :
+ case PROT_GROW:
+ case PROT_SHRINK : pImpl = new SwSizeEnterLeave( pFrm, nFunc, nAct, pPar ); break;
+ case PROT_MOVE_FWD:
+ case PROT_MOVE_BWD : pImpl = new SwUpperEnterLeave( pFrm, nFunc, nAct, pPar ); break;
+ case PROT_FRMCHANGES : pImpl = new SwFrmChangesLeave( pFrm, nFunc, nAct, pPar ); break;
+ default: pImpl = new SwImplEnterLeave( pFrm, nFunc, nAct, pPar ); break;
+ }
+ pImpl->Enter();
+}
+
+/* --------------------------------------------------
+ * SwEnterLeave::Dtor() ruft lediglich den Destruktor des SwImplEnterLeave-Objekts,
+ * ist nur deshalb nicht inline, damit die SwImplEnterLeave-Definition nicht
+ * im dbg_lay.hxx zu stehen braucht.
+ * --------------------------------------------------*/
+
+void SwEnterLeave::Dtor()
+{
+ if( pImpl )
+ {
+ pImpl->Leave();
+ delete pImpl;
+ }
+}
+
+void SwImplEnterLeave::Enter()
+{
+ SwProtocol::Record( pFrm, nFunction, ACT_START, pParam );
+}
+
+void SwImplEnterLeave::Leave()
+{
+ SwProtocol::Record( pFrm, nFunction, ACT_END, pParam );
+}
+
+void SwSizeEnterLeave::Leave()
+{
+ nFrmHeight = pFrm->Frm().Height() - nFrmHeight;
+ SwProtocol::Record( pFrm, nFunction, ACT_END, &nFrmHeight );
+}
+
+void SwUpperEnterLeave::Enter()
+{
+ nFrmId = pFrm->GetUpper() ? sal_uInt16(lcl_GetFrameId( pFrm->GetUpper() )) : 0;
+ SwProtocol::Record( pFrm, nFunction, ACT_START, &nFrmId );
+}
+
+void SwUpperEnterLeave::Leave()
+{
+ nFrmId = pFrm->GetUpper() ? sal_uInt16(lcl_GetFrameId( pFrm->GetUpper() )) : 0;
+ SwProtocol::Record( pFrm, nFunction, ACT_END, &nFrmId );
+}
+
+void SwFrmChangesLeave::Enter()
+{
+}
+
+void SwFrmChangesLeave::Leave()
+{
+ if( pFrm->Frm() != aFrm )
+ SwProtocol::Record( pFrm, PROT_FRMCHANGES, 0, &aFrm );
+}
+
+#endif // DBG_UTIL
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/layout/findfrm.cxx b/sw/source/core/layout/findfrm.cxx
new file mode 100644
index 000000000000..16bc348b6a42
--- /dev/null
+++ b/sw/source/core/layout/findfrm.cxx
@@ -0,0 +1,1793 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+
+#include "pagefrm.hxx"
+#include "rootfrm.hxx"
+#include "cntfrm.hxx"
+#include "node.hxx"
+#include "doc.hxx"
+#include "frmtool.hxx"
+#include "flyfrm.hxx"
+#include <frmfmt.hxx>
+#include <cellfrm.hxx>
+#include <rowfrm.hxx>
+#include <swtable.hxx>
+
+#include "tabfrm.hxx"
+#include "sectfrm.hxx"
+#include "flyfrms.hxx"
+#include "ftnfrm.hxx"
+#include "txtftn.hxx"
+#include "fmtftn.hxx"
+#include <txtfrm.hxx> // SwTxtFrm
+#include <switerator.hxx>
+
+/*************************************************************************
+|*
+|* FindBodyCont, FindLastBodyCntnt()
+|*
+|* Beschreibung Sucht den ersten/letzten CntntFrm im BodyText unterhalb
+|* der Seite.
+|*
+|*************************************************************************/
+SwLayoutFrm *SwFtnBossFrm::FindBodyCont()
+{
+ SwFrm *pLay = Lower();
+ while ( pLay && !pLay->IsBodyFrm() )
+ pLay = pLay->GetNext();
+ return (SwLayoutFrm*)pLay;
+}
+
+SwCntntFrm *SwPageFrm::FindLastBodyCntnt()
+{
+ SwCntntFrm *pRet = FindFirstBodyCntnt();
+ SwCntntFrm *pNxt = pRet;
+ while ( pNxt && pNxt->IsInDocBody() && IsAnLower( pNxt ) )
+ { pRet = pNxt;
+ pNxt = pNxt->FindNextCnt();
+ }
+ return pRet;
+}
+
+/*************************************************************************
+|*
+|* SwLayoutFrm::ContainsCntnt
+|*
+|* Beschreibung Prueft, ob der Frame irgendwo in seiner
+|* untergeordneten Struktur einen oder mehrere CntntFrm's enthaelt;
+|* Falls ja wird der erste gefundene CntntFrm zurueckgegeben.
+|*
+|*************************************************************************/
+
+const SwCntntFrm *SwLayoutFrm::ContainsCntnt() const
+{
+ //LayoutBlatt nach unten hin suchen und wenn dieses keinen Inhalt hat
+ //solange die weiteren Blatter abklappern bis Inhalt gefunden oder der
+ //this verlassen wird.
+ //Sections: Cntnt neben Sections wuerde so nicht gefunden (leere Section
+ //direct neben CntntFrm), deshalb muss fuer diese Aufwendiger rekursiv gesucht
+ //werden.
+
+ const SwLayoutFrm *pLayLeaf = this;
+ do
+ {
+ while ( (!pLayLeaf->IsSctFrm() || pLayLeaf == this ) &&
+ pLayLeaf->Lower() && pLayLeaf->Lower()->IsLayoutFrm() )
+ pLayLeaf = (SwLayoutFrm*)pLayLeaf->Lower();
+
+ if( pLayLeaf->IsSctFrm() && pLayLeaf != this )
+ {
+ const SwCntntFrm *pCnt = pLayLeaf->ContainsCntnt();
+ if( pCnt )
+ return pCnt;
+ if( pLayLeaf->GetNext() )
+ {
+ if( pLayLeaf->GetNext()->IsLayoutFrm() )
+ {
+ pLayLeaf = (SwLayoutFrm*)pLayLeaf->GetNext();
+ continue;
+ }
+ else
+ return (SwCntntFrm*)pLayLeaf->GetNext();
+ }
+ }
+ else if ( pLayLeaf->Lower() )
+ return (SwCntntFrm*)pLayLeaf->Lower();
+
+ pLayLeaf = pLayLeaf->GetNextLayoutLeaf();
+ if( !IsAnLower( pLayLeaf) )
+ return 0;
+ } while( pLayLeaf );
+ return 0;
+}
+
+/*************************************************************************
+|*
+|* SwLayoutFrm::FirstCell
+|*
+|* Beschreibung ruft zunaechst ContainsAny auf, um in die innerste Zelle
+|* hineinzukommen. Dort hangelt es sich wieder hoch zum
+|* ersten SwCellFrm, seit es SectionFrms gibt, reicht kein
+|* ContainsCntnt()->GetUpper() mehr...
+|*
+|*************************************************************************/
+
+const SwCellFrm *SwLayoutFrm::FirstCell() const
+{
+ const SwFrm* pCnt = ContainsAny();
+ while( pCnt && !pCnt->IsCellFrm() )
+ pCnt = pCnt->GetUpper();
+ return (const SwCellFrm*)pCnt;
+}
+
+/*************************************************************************
+|*
+|* SwLayoutFrm::ContainsAny
+|*
+|* Beschreibung wie ContainsCntnt, nur dass nicht nur CntntFrms, sondern auch
+|* Bereiche und Tabellen zurueckgegeben werden.
+|*
+|*************************************************************************/
+
+// --> OD 2006-02-01 #130797#
+// New parameter <_bInvestigateFtnForSections> controls investigation of
+// content of footnotes for sections.
+const SwFrm *SwLayoutFrm::ContainsAny( const bool _bInvestigateFtnForSections ) const
+{
+ //LayoutBlatt nach unten hin suchen und wenn dieses keinen Inhalt hat
+ //solange die weiteren Blatter abklappern bis Inhalt gefunden oder der
+ //this verlassen wird.
+ // Oder bis wir einen SectionFrm oder TabFrm gefunden haben
+
+ const SwLayoutFrm *pLayLeaf = this;
+ // --> OD 2006-02-01 #130797#
+ const bool bNoFtn = IsSctFrm() && !_bInvestigateFtnForSections;
+ // <--
+ do
+ {
+ while ( ( (!pLayLeaf->IsSctFrm() && !pLayLeaf->IsTabFrm())
+ || pLayLeaf == this ) &&
+ pLayLeaf->Lower() && pLayLeaf->Lower()->IsLayoutFrm() )
+ pLayLeaf = (SwLayoutFrm*)pLayLeaf->Lower();
+
+ if( ( pLayLeaf->IsTabFrm() || pLayLeaf->IsSctFrm() )
+ && pLayLeaf != this )
+ {
+ // Wir liefern jetzt auch "geloeschte" SectionFrms zurueck,
+ // damit diese beim SaveCntnt und RestoreCntnt mitgepflegt werden.
+ return pLayLeaf;
+ }
+ else if ( pLayLeaf->Lower() )
+ return (SwCntntFrm*)pLayLeaf->Lower();
+
+ pLayLeaf = pLayLeaf->GetNextLayoutLeaf();
+ if( bNoFtn && pLayLeaf && pLayLeaf->IsInFtn() )
+ {
+ do
+ {
+ pLayLeaf = pLayLeaf->GetNextLayoutLeaf();
+ } while( pLayLeaf && pLayLeaf->IsInFtn() );
+ }
+ if( !IsAnLower( pLayLeaf) )
+ return 0;
+ } while( pLayLeaf );
+ return 0;
+}
+
+
+/*************************************************************************
+|*
+|* SwFrm::GetLower()
+|*
+|*************************************************************************/
+const SwFrm* SwFrm::GetLower() const
+{
+ return IsLayoutFrm() ? ((SwLayoutFrm*)this)->Lower() : 0;
+}
+
+SwFrm* SwFrm::GetLower()
+{
+ return IsLayoutFrm() ? ((SwLayoutFrm*)this)->Lower() : 0;
+}
+
+/*************************************************************************
+|*
+|* SwLayoutFrm::IsAnLower()
+|*
+|*************************************************************************/
+sal_Bool SwLayoutFrm::IsAnLower( const SwFrm *pAssumed ) const
+{
+ const SwFrm *pUp = pAssumed;
+ while ( pUp )
+ {
+ if ( pUp == this )
+ return sal_True;
+ if ( pUp->IsFlyFrm() )
+ pUp = ((SwFlyFrm*)pUp)->GetAnchorFrm();
+ else
+ pUp = pUp->GetUpper();
+ }
+ return sal_False;
+}
+
+/** method to check relative position of layout frame to
+ a given layout frame.
+
+ OD 08.11.2002 - refactoring of pseudo-local method <lcl_Apres(..)> in
+ <txtftn.cxx> for #104840#.
+
+ @param _aCheckRefLayFrm
+ constant reference of an instance of class <SwLayoutFrm> which
+ is used as the reference for the relative position check.
+
+ @author OD
+
+ @return true, if <this> is positioned before the layout frame <p>
+*/
+bool SwLayoutFrm::IsBefore( const SwLayoutFrm* _pCheckRefLayFrm ) const
+{
+ OSL_ENSURE( !IsRootFrm() , "<IsBefore> called at a <SwRootFrm>.");
+ OSL_ENSURE( !_pCheckRefLayFrm->IsRootFrm() , "<IsBefore> called with a <SwRootFrm>.");
+
+ bool bReturn;
+
+ // check, if on different pages
+ const SwPageFrm *pMyPage = FindPageFrm();
+ const SwPageFrm *pCheckRefPage = _pCheckRefLayFrm->FindPageFrm();
+ if( pMyPage != pCheckRefPage )
+ {
+ // being on different page as check reference
+ bReturn = pMyPage->GetPhyPageNum() < pCheckRefPage->GetPhyPageNum();
+ }
+ else
+ {
+ // being on same page as check reference
+ // --> search my supreme parent <pUp>, which doesn't contain check reference.
+ const SwLayoutFrm* pUp = this;
+ while ( pUp->GetUpper() &&
+ !pUp->GetUpper()->IsAnLower( _pCheckRefLayFrm )
+ )
+ pUp = pUp->GetUpper();
+ if( !pUp->GetUpper() )
+ {
+ // can occur, if <this> is a fly frm
+ bReturn = false;
+ }
+ else
+ {
+ // travel through the next's of <pUp> and check if one of these
+ // contain the check reference.
+ SwLayoutFrm* pUpNext = (SwLayoutFrm*)pUp->GetNext();
+ while ( pUpNext &&
+ !pUpNext->IsAnLower( _pCheckRefLayFrm ) )
+ {
+ pUpNext = (SwLayoutFrm*)pUpNext->GetNext();
+ }
+ bReturn = pUpNext != 0;
+ }
+ }
+
+ return bReturn;
+}
+
+//
+// Local helper functions for GetNextLayoutLeaf
+//
+
+const SwFrm* lcl_FindLayoutFrame( const SwFrm* pFrm, bool bNext )
+{
+ const SwFrm* pRet = 0;
+ if ( pFrm->IsFlyFrm() )
+ pRet = bNext ? ((SwFlyFrm*)pFrm)->GetNextLink() : ((SwFlyFrm*)pFrm)->GetPrevLink();
+ else
+ pRet = bNext ? pFrm->GetNext() : pFrm->GetPrev();
+
+ return pRet;
+}
+
+const SwFrm* lcl_GetLower( const SwFrm* pFrm, bool bFwd )
+{
+ if ( !pFrm->IsLayoutFrm() )
+ return 0;
+
+ return bFwd ?
+ static_cast<const SwLayoutFrm*>(pFrm)->Lower() :
+ static_cast<const SwLayoutFrm*>(pFrm)->GetLastLower();
+}
+
+/*************************************************************************
+|*
+|* SwFrm::ImplGetNextLayoutLeaf
+|*
+|* Finds the next layout leaf. This is a layout frame, which does not
+ * have a lower which is a LayoutFrame. That means, pLower can be 0 or a
+ * content frame.
+ *
+ * However, pLower may be a TabFrm
+ *
+|*************************************************************************/
+
+const SwLayoutFrm *SwFrm::ImplGetNextLayoutLeaf( bool bFwd ) const
+{
+ const SwFrm *pFrm = this;
+ const SwLayoutFrm *pLayoutFrm = 0;
+ const SwFrm *p = 0;
+ bool bGoingUp = !bFwd; // false for forward, true for backward
+ do {
+
+ bool bGoingFwdOrBwd = false, bGoingDown = false;
+
+ bGoingDown = ( !bGoingUp && ( 0 != (p = lcl_GetLower( pFrm, bFwd ) ) ) );
+ if ( !bGoingDown )
+ {
+ // I cannot go down, because either I'm currently going up or
+ // because the is no lower.
+ // I'll try to go forward:
+ bGoingFwdOrBwd = (0 != (p = lcl_FindLayoutFrame( pFrm, bFwd ) ) );
+ if ( !bGoingFwdOrBwd )
+ {
+ // I cannot go forward, because there is no next frame.
+ // I'll try to go up:
+ bGoingUp = (0 != (p = pFrm->GetUpper() ) );
+ if ( !bGoingUp )
+ {
+ // I cannot go up, because there is no upper frame.
+ return 0;
+ }
+ }
+ }
+
+ // If I could not go down or forward, I'll have to go up
+ bGoingUp = !bGoingFwdOrBwd && !bGoingDown;
+
+ pFrm = p;
+ p = lcl_GetLower( pFrm, true );
+
+ } while( ( p && !p->IsFlowFrm() ) ||
+ pFrm == this ||
+ 0 == ( pLayoutFrm = pFrm->IsLayoutFrm() ? (SwLayoutFrm*)pFrm : 0 ) ||
+ pLayoutFrm->IsAnLower( this ) );
+
+ return pLayoutFrm;
+}
+
+
+
+/*************************************************************************
+|*
+|* SwFrm::ImplGetNextCntntFrm( bool )
+|*
+|* Rueckwaertswandern im Baum: Den untergeordneten Frm greifen,
+|* wenn es einen gibt und nicht gerade zuvor um eine Ebene
+|* aufgestiegen wurde (das wuerde zu einem endlosen Auf und Ab
+|* fuehren!). Damit wird sichergestellt, dass beim
+|* Rueckwaertswandern alle Unterbaeume durchsucht werden. Wenn
+|* abgestiegen wurde, wird zuerst an das Ende der Kette gegangen,
+|* weil im weiteren ja vom letzten Frm innerhalb eines anderen
+|* Frms rueckwaerts gegangen wird.
+|* Vorwaetzwander funktioniert analog.
+|*
+|*************************************************************************/
+
+// Achtung: Fixes in ImplGetNextCntntFrm() muessen moeglicherweise auch in
+// die weiter oben stehende Methode lcl_NextFrm(..) eingepflegt werden
+const SwCntntFrm* SwCntntFrm::ImplGetNextCntntFrm( bool bFwd ) const
+{
+ const SwFrm *pFrm = this;
+ // #100926#
+ SwCntntFrm *pCntntFrm = 0;
+ sal_Bool bGoingUp = sal_False;
+ do {
+ const SwFrm *p = 0;
+ sal_Bool bGoingFwdOrBwd = sal_False, bGoingDown = sal_False;
+
+ bGoingDown = ( !bGoingUp && ( 0 != ( p = lcl_GetLower( pFrm, true ) ) ) );
+ if ( !bGoingDown )
+ {
+ bGoingFwdOrBwd = ( 0 != ( p = lcl_FindLayoutFrame( pFrm, bFwd ) ) );
+ if ( !bGoingFwdOrBwd )
+ {
+ bGoingUp = ( 0 != ( p = pFrm->GetUpper() ) );
+ if ( !bGoingUp )
+ {
+ return 0;
+ }
+ }
+ }
+
+ bGoingUp = !(bGoingFwdOrBwd || bGoingDown);
+
+ if ( !bFwd )
+ {
+ if( bGoingDown && p )
+ while ( p->GetNext() )
+ p = p->GetNext();
+ }
+
+ pFrm = p;
+ } while ( 0 == (pCntntFrm = (pFrm->IsCntntFrm() ? (SwCntntFrm*)pFrm:0) ));
+
+ return pCntntFrm;
+}
+
+
+
+
+/*************************************************************************
+|*
+|* SwFrm::FindRootFrm(), FindTabFrm(), FindFtnFrm(), FindFlyFrm(),
+|* FindPageFrm(), FindColFrm()
+|*
+|*************************************************************************/
+SwPageFrm* SwFrm::FindPageFrm()
+{
+ SwFrm *pRet = this;
+ while ( pRet && !pRet->IsPageFrm() )
+ {
+ if ( pRet->GetUpper() )
+ pRet = pRet->GetUpper();
+ else if ( pRet->IsFlyFrm() )
+ {
+ // --> OD 2004-06-30 #i28701# - use new method <GetPageFrm()>
+ if ( static_cast<SwFlyFrm*>(pRet)->GetPageFrm() )
+ pRet = static_cast<SwFlyFrm*>(pRet)->GetPageFrm();
+ else
+ pRet = static_cast<SwFlyFrm*>(pRet)->AnchorFrm();
+ }
+ else
+ return 0;
+ }
+ return (SwPageFrm*)pRet;
+}
+
+SwFtnBossFrm* SwFrm::FindFtnBossFrm( sal_Bool bFootnotes )
+{
+ SwFrm *pRet = this;
+ // Innerhalb einer Tabelle gibt es keine Fussnotenbosse, auch spaltige
+ // Bereiche enthalten dort keine Fussnotentexte
+ if( pRet->IsInTab() )
+ pRet = pRet->FindTabFrm();
+ while ( pRet && !pRet->IsFtnBossFrm() )
+ {
+ if ( pRet->GetUpper() )
+ pRet = pRet->GetUpper();
+ else if ( pRet->IsFlyFrm() )
+ {
+ // --> OD 2004-06-30 #i28701# - use new method <GetPageFrm()>
+ if ( static_cast<SwFlyFrm*>(pRet)->GetPageFrm() )
+ pRet = static_cast<SwFlyFrm*>(pRet)->GetPageFrm();
+ else
+ pRet = static_cast<SwFlyFrm*>(pRet)->AnchorFrm();
+ }
+ else
+ return 0;
+ }
+ if( bFootnotes && pRet && pRet->IsColumnFrm() &&
+ !pRet->GetNext() && !pRet->GetPrev() )
+ {
+ SwSectionFrm* pSct = pRet->FindSctFrm();
+ OSL_ENSURE( pSct, "FindFtnBossFrm: Single column outside section?" );
+ if( !pSct->IsFtnAtEnd() )
+ return pSct->FindFtnBossFrm( sal_True );
+ }
+ return (SwFtnBossFrm*)pRet;
+}
+
+SwTabFrm* SwFrm::ImplFindTabFrm()
+{
+ SwFrm *pRet = this;
+ while ( !pRet->IsTabFrm() )
+ {
+ pRet = pRet->GetUpper();
+ if ( !pRet )
+ return 0;
+ }
+ return (SwTabFrm*)pRet;
+}
+
+SwSectionFrm* SwFrm::ImplFindSctFrm()
+{
+ SwFrm *pRet = this;
+ while ( !pRet->IsSctFrm() )
+ {
+ pRet = pRet->GetUpper();
+ if ( !pRet )
+ return 0;
+ }
+ return (SwSectionFrm*)pRet;
+}
+
+SwFtnFrm *SwFrm::ImplFindFtnFrm()
+{
+ SwFrm *pRet = this;
+ while ( !pRet->IsFtnFrm() )
+ {
+ pRet = pRet->GetUpper();
+ if ( !pRet )
+ return 0;
+ }
+ return (SwFtnFrm*)pRet;
+}
+
+SwFlyFrm *SwFrm::ImplFindFlyFrm()
+{
+ const SwFrm *pRet = this;
+ do
+ {
+ if ( pRet->IsFlyFrm() )
+ return (SwFlyFrm*)pRet;
+ else
+ pRet = pRet->GetUpper();
+ } while ( pRet );
+ return 0;
+}
+
+SwFrm *SwFrm::FindColFrm()
+{
+ SwFrm *pFrm = this;
+ do
+ { pFrm = pFrm->GetUpper();
+ } while ( pFrm && !pFrm->IsColumnFrm() );
+ return pFrm;
+}
+
+SwRowFrm *SwFrm::FindRowFrm()
+{
+ SwFrm *pFrm = this;
+ do
+ { pFrm = pFrm->GetUpper();
+ } while ( pFrm && !pFrm->IsRowFrm() );
+ return dynamic_cast< SwRowFrm* >( pFrm );
+}
+
+SwFrm* SwFrm::FindFooterOrHeader()
+{
+ SwFrm* pRet = this;
+ do
+ { if ( pRet->GetType() & 0x0018 ) //Header und Footer
+ return pRet;
+ else if ( pRet->GetUpper() )
+ pRet = pRet->GetUpper();
+ else if ( pRet->IsFlyFrm() )
+ pRet = ((SwFlyFrm*)pRet)->AnchorFrm();
+ else
+ return 0;
+ } while ( pRet );
+ return pRet;
+}
+
+const SwFtnFrm* SwFtnContFrm::FindFootNote() const
+{
+ const SwFtnFrm* pRet = (SwFtnFrm*)Lower();
+ if( pRet && !pRet->GetAttr()->GetFtn().IsEndNote() )
+ return pRet;
+ return NULL;
+}
+
+const SwPageFrm* SwRootFrm::GetPageAtPos( const Point& rPt, const Size* pSize, bool bExtend ) const
+{
+ const SwPageFrm* pRet = 0;
+
+ SwRect aRect;
+ if ( pSize )
+ {
+ aRect.Pos() = rPt;
+ aRect.SSize() = *pSize;
+ }
+
+ const SwFrm* pPage = Lower();
+
+ if ( !bExtend )
+ {
+ if( !Frm().IsInside( rPt ) )
+ return 0;
+
+ // skip pages above point:
+ while( pPage && rPt.Y() > pPage->Frm().Bottom() )
+ pPage = pPage->GetNext();
+ }
+
+ OSL_ENSURE( GetPageNum() <= maPageRects.size(), "number of pages differes from page rect array size" );
+ sal_uInt16 nPageIdx = 0;
+
+ while ( pPage && !pRet )
+ {
+ const SwRect& rBoundRect = bExtend ? maPageRects[ nPageIdx++ ] : pPage->Frm();
+
+ if ( (!pSize && rBoundRect.IsInside(rPt)) ||
+ (pSize && rBoundRect.IsOver(aRect)) )
+ {
+ pRet = static_cast<const SwPageFrm*>(pPage);
+ }
+
+ pPage = pPage->GetNext();
+ }
+
+ return pRet;
+}
+
+/*************************************************************************
+|*
+|* SwFrmFrm::GetAttrSet()
+|*
+|*************************************************************************/
+const SwAttrSet* SwFrm::GetAttrSet() const
+{
+ if ( IsCntntFrm() )
+ return &((const SwCntntFrm*)this)->GetNode()->GetSwAttrSet();
+ else
+ return &((const SwLayoutFrm*)this)->GetFmt()->GetAttrSet();
+}
+
+/*************************************************************************
+|*
+|* SwFrm::_FindNext(), _FindPrev(), InvalidateNextPos()
+|* _FindNextCnt() geht in Tabellen und Bereiche hineinund liefert
+|* nur SwCntntFrms.
+|*
+|* Beschreibung Invalidiert die Position des Naechsten Frames.
+|* Dies ist der direkte Nachfolger, oder bei CntntFrm's der naechste
+|* CntntFrm der im gleichen Fluss liegt wie ich:
+|* - Body,
+|* - Fussnoten,
+|* - Bei Kopf-/Fussbereichen ist die Benachrichtigung nur innerhalb des
+|* Bereiches weiterzuleiten.
+|* - dito fuer Flys.
+|* - Cntnts in Tabs halten sich ausschliesslich innerhalb ihrer Zelle
+|* auf.
+|* - Tabellen verhalten sich prinzipiell analog zu den Cntnts
+|* - Bereiche ebenfalls
+|*
+|*************************************************************************/
+
+// Diese Hilfsfunktion ist ein Aequivalent zur ImplGetNextCntntFrm()-Methode,
+// sie liefert allerdings neben ContentFrames auch TabFrms und SectionFrms.
+SwFrm* lcl_NextFrm( SwFrm* pFrm )
+{
+ SwFrm *pRet = 0;
+ sal_Bool bGoingUp = sal_False;
+ do {
+ SwFrm *p = 0;
+
+ sal_Bool bGoingFwd = sal_False;
+ sal_Bool bGoingDown = (!bGoingUp && ( 0 != (p = pFrm->IsLayoutFrm() ? ((SwLayoutFrm*)pFrm)->Lower() : 0)));
+
+ if( !bGoingDown )
+ {
+ bGoingFwd = (0 != (p = ( pFrm->IsFlyFrm() ? ((SwFlyFrm*)pFrm)->GetNextLink() : pFrm->GetNext())));
+ if ( !bGoingFwd )
+ {
+ bGoingUp = (0 != (p = pFrm->GetUpper()));
+ if ( !bGoingUp )
+ {
+ return 0;
+ }
+ }
+ }
+ bGoingUp = !(bGoingFwd || bGoingDown);
+ pFrm = p;
+ } while ( 0 == (pRet = ( ( pFrm->IsCntntFrm() || ( !bGoingUp &&
+ ( pFrm->IsTabFrm() || pFrm->IsSctFrm() ) ) )? pFrm : 0 ) ) );
+ return pRet;
+}
+
+SwFrm *SwFrm::_FindNext()
+{
+ sal_Bool bIgnoreTab = sal_False;
+ SwFrm *pThis = this;
+
+ if ( IsTabFrm() )
+ {
+ //Der letzte Cntnt der Tabelle wird
+ //gegriffen und dessen Nachfolger geliefert. Um die Spezialbeh.
+ //Fuer Tabellen (s.u.) auszuschalten wird bIgnoreTab gesetzt.
+ if ( ((SwTabFrm*)this)->GetFollow() )
+ return ((SwTabFrm*)this)->GetFollow();
+
+ pThis = ((SwTabFrm*)this)->FindLastCntnt();
+ if ( !pThis )
+ pThis = this;
+ bIgnoreTab = sal_True;
+ }
+ else if ( IsSctFrm() )
+ {
+ //Der letzte Cntnt des Bereichs wird gegriffen und dessen Nachfolger
+ // geliefert.
+ if ( ((SwSectionFrm*)this)->GetFollow() )
+ return ((SwSectionFrm*)this)->GetFollow();
+
+ pThis = ((SwSectionFrm*)this)->FindLastCntnt();
+ if ( !pThis )
+ pThis = this;
+ }
+ else if ( IsCntntFrm() )
+ {
+ if( ((SwCntntFrm*)this)->GetFollow() )
+ return ((SwCntntFrm*)this)->GetFollow();
+ }
+ else if ( IsRowFrm() )
+ {
+ SwFrm* pMyUpper = GetUpper();
+ if ( pMyUpper->IsTabFrm() && ((SwTabFrm*)pMyUpper)->GetFollow() )
+ return ((SwTabFrm*)pMyUpper)->GetFollow()->GetLower();
+ else return NULL;
+ }
+ else
+ return NULL;
+
+ SwFrm* pRet = NULL;
+ const sal_Bool bFtn = pThis->IsInFtn();
+ if ( !bIgnoreTab && pThis->IsInTab() )
+ {
+ SwLayoutFrm *pUp = pThis->GetUpper();
+ while ( !pUp->IsCellFrm() )
+ pUp = pUp->GetUpper();
+ OSL_ENSURE( pUp, "Cntnt in Tabelle aber nicht in Zelle." );
+ SwFrm* pNxt = ((SwCellFrm*)pUp)->GetFollowCell();
+ if ( pNxt )
+ pNxt = ((SwCellFrm*)pNxt)->ContainsCntnt();
+ if ( !pNxt )
+ {
+ pNxt = lcl_NextFrm( pThis );
+ if ( pUp->IsAnLower( pNxt ) )
+ pRet = pNxt;
+ }
+ else
+ pRet = pNxt;
+ }
+ else
+ {
+ const sal_Bool bBody = pThis->IsInDocBody();
+ SwFrm *pNxtCnt = lcl_NextFrm( pThis );
+ if ( pNxtCnt )
+ {
+ if ( bBody || bFtn )
+ {
+ while ( pNxtCnt )
+ {
+ // OD 02.04.2003 #108446# - check for endnote, only if found
+ // next content isn't contained in a section, that collect its
+ // endnotes at its end.
+ bool bEndn = IsInSct() && !IsSctFrm() &&
+ ( !pNxtCnt->IsInSct() ||
+ !pNxtCnt->FindSctFrm()->IsEndnAtEnd()
+ );
+ if ( ( bBody && pNxtCnt->IsInDocBody() ) ||
+ ( pNxtCnt->IsInFtn() &&
+ ( bFtn ||
+ ( bEndn && pNxtCnt->FindFtnFrm()->GetAttr()->GetFtn().IsEndNote() )
+ )
+ )
+ )
+ {
+ pRet = pNxtCnt->IsInTab() ? pNxtCnt->FindTabFrm()
+ : (SwFrm*)pNxtCnt;
+ break;
+ }
+ pNxtCnt = lcl_NextFrm( pNxtCnt );
+ }
+ }
+ else if ( pThis->IsInFly() )
+ {
+ pRet = pNxtCnt->IsInTab() ? pNxtCnt->FindTabFrm()
+ : (SwFrm*)pNxtCnt;
+ }
+ else //Fuss-/oder Kopfbereich
+ {
+ const SwFrm *pUp = pThis->GetUpper();
+ const SwFrm *pCntUp = pNxtCnt->GetUpper();
+ while ( pUp && pUp->GetUpper() &&
+ !pUp->IsHeaderFrm() && !pUp->IsFooterFrm() )
+ pUp = pUp->GetUpper();
+ while ( pCntUp && pCntUp->GetUpper() &&
+ !pCntUp->IsHeaderFrm() && !pCntUp->IsFooterFrm() )
+ pCntUp = pCntUp->GetUpper();
+ if ( pCntUp == pUp )
+ {
+ pRet = pNxtCnt->IsInTab() ? pNxtCnt->FindTabFrm()
+ : (SwFrm*)pNxtCnt;
+ }
+ }
+ }
+ }
+ if( pRet && pRet->IsInSct() )
+ {
+ SwSectionFrm* pSct = pRet->FindSctFrm();
+ //Fussnoten in spaltigen Rahmen duerfen nicht den Bereich
+ //liefern, der die Fussnoten umfasst
+ if( !pSct->IsAnLower( this ) &&
+ (!bFtn || pSct->IsInFtn() ) )
+ return pSct;
+ }
+ return pRet;
+}
+
+// --> OD 2005-12-01 #i27138# - add parameter <_bInSameFtn>
+SwCntntFrm *SwFrm::_FindNextCnt( const bool _bInSameFtn )
+{
+ SwFrm *pThis = this;
+
+ if ( IsTabFrm() )
+ {
+ if ( ((SwTabFrm*)this)->GetFollow() )
+ {
+ pThis = ((SwTabFrm*)this)->GetFollow()->ContainsCntnt();
+ if( pThis )
+ return (SwCntntFrm*)pThis;
+ }
+ pThis = ((SwTabFrm*)this)->FindLastCntnt();
+ if ( !pThis )
+ return 0;
+ }
+ else if ( IsSctFrm() )
+ {
+ if ( ((SwSectionFrm*)this)->GetFollow() )
+ {
+ pThis = ((SwSectionFrm*)this)->GetFollow()->ContainsCntnt();
+ if( pThis )
+ return (SwCntntFrm*)pThis;
+ }
+ pThis = ((SwSectionFrm*)this)->FindLastCntnt();
+ if ( !pThis )
+ return 0;
+ }
+ else if ( IsCntntFrm() && ((SwCntntFrm*)this)->GetFollow() )
+ return ((SwCntntFrm*)this)->GetFollow();
+
+ if ( pThis->IsCntntFrm() )
+ {
+ const sal_Bool bBody = pThis->IsInDocBody();
+ const sal_Bool bFtn = pThis->IsInFtn();
+ SwCntntFrm *pNxtCnt = ((SwCntntFrm*)pThis)->GetNextCntntFrm();
+ if ( pNxtCnt )
+ {
+ // --> OD 2005-12-01 #i27138#
+ if ( bBody || ( bFtn && !_bInSameFtn ) )
+ // <--
+ {
+ // handling for environments 'footnotes' and 'document body frames':
+ while ( pNxtCnt )
+ {
+ if ( (bBody && pNxtCnt->IsInDocBody()) ||
+ (bFtn && pNxtCnt->IsInFtn()) )
+ return pNxtCnt;
+ pNxtCnt = pNxtCnt->GetNextCntntFrm();
+ }
+ }
+ // --> OD 2005-12-01 #i27138#
+ else if ( bFtn && _bInSameFtn )
+ {
+ // handling for environments 'each footnote':
+ // Assure that found next content frame belongs to the same footnotes
+ const SwFtnFrm* pFtnFrmOfNext( pNxtCnt->FindFtnFrm() );
+ const SwFtnFrm* pFtnFrmOfCurr( pThis->FindFtnFrm() );
+ OSL_ENSURE( pFtnFrmOfCurr,
+ "<SwFrm::_FindNextCnt() - unknown layout situation: current frame has to have an upper footnote frame." );
+ if ( pFtnFrmOfNext == pFtnFrmOfCurr )
+ {
+ return pNxtCnt;
+ }
+ else if ( pFtnFrmOfCurr->GetFollow() )
+ {
+ // next content frame has to be the first content frame
+ // in the follow footnote, which contains a content frame.
+ SwFtnFrm* pFollowFtnFrmOfCurr(
+ const_cast<SwFtnFrm*>(pFtnFrmOfCurr) );
+ pNxtCnt = 0L;
+ do {
+ pFollowFtnFrmOfCurr = pFollowFtnFrmOfCurr->GetFollow();
+ pNxtCnt = pFollowFtnFrmOfCurr->ContainsCntnt();
+ } while ( !pNxtCnt && pFollowFtnFrmOfCurr->GetFollow() );
+ return pNxtCnt;
+ }
+ else
+ {
+ // current content frame is the last content frame in the
+ // footnote - no next content frame exists.
+ return 0L;
+ }
+ }
+ // <--
+ else if ( pThis->IsInFly() )
+ // handling for environments 'unlinked fly frame' and
+ // 'group of linked fly frames':
+ return pNxtCnt;
+ else
+ {
+ // handling for environments 'page header' and 'page footer':
+ const SwFrm *pUp = pThis->GetUpper();
+ const SwFrm *pCntUp = pNxtCnt->GetUpper();
+ while ( pUp && pUp->GetUpper() &&
+ !pUp->IsHeaderFrm() && !pUp->IsFooterFrm() )
+ pUp = pUp->GetUpper();
+ while ( pCntUp && pCntUp->GetUpper() &&
+ !pCntUp->IsHeaderFrm() && !pCntUp->IsFooterFrm() )
+ pCntUp = pCntUp->GetUpper();
+ if ( pCntUp == pUp )
+ return pNxtCnt;
+ }
+ }
+ }
+ return 0;
+}
+
+/** method to determine previous content frame in the same environment
+ for a flow frame (content frame, table frame, section frame)
+
+ OD 2005-11-30 #i27138#
+
+ @author OD
+*/
+SwCntntFrm* SwFrm::_FindPrevCnt( const bool _bInSameFtn )
+{
+ if ( !IsFlowFrm() )
+ {
+ // nothing to do, if current frame isn't a flow frame.
+ return 0L;
+ }
+
+ SwCntntFrm* pPrevCntntFrm( 0L );
+
+ // Because method <SwCntntFrm::GetPrevCntntFrm()> is used to travel
+ // through the layout, a content frame, at which the travel starts, is needed.
+ SwCntntFrm* pCurrCntntFrm = dynamic_cast<SwCntntFrm*>(this);
+
+ // perform shortcut, if current frame is a follow, and
+ // determine <pCurrCntntFrm>, if current frame is a table or section frame
+ if ( pCurrCntntFrm && pCurrCntntFrm->IsFollow() )
+ {
+ // previous content frame is its master content frame
+ pPrevCntntFrm = pCurrCntntFrm->FindMaster();
+ }
+ else if ( IsTabFrm() )
+ {
+ SwTabFrm* pTabFrm( static_cast<SwTabFrm*>(this) );
+ if ( pTabFrm->IsFollow() )
+ {
+ // previous content frame is the last content of its master table frame
+ pPrevCntntFrm = pTabFrm->FindMaster()->FindLastCntnt();
+ }
+ else
+ {
+ // start content frame for the search is the first content frame of
+ // the table frame.
+ pCurrCntntFrm = pTabFrm->ContainsCntnt();
+ }
+ }
+ else if ( IsSctFrm() )
+ {
+ SwSectionFrm* pSectFrm( static_cast<SwSectionFrm*>(this) );
+ if ( pSectFrm->IsFollow() )
+ {
+ // previous content frame is the last content of its master section frame
+ pPrevCntntFrm = pSectFrm->FindMaster()->FindLastCntnt();
+ }
+ else
+ {
+ // start content frame for the search is the first content frame of
+ // the section frame.
+ pCurrCntntFrm = pSectFrm->ContainsCntnt();
+ }
+ }
+
+ // search for next content frame, depending on the environment, in which
+ // the current frame is in.
+ if ( !pPrevCntntFrm && pCurrCntntFrm )
+ {
+ pPrevCntntFrm = pCurrCntntFrm->GetPrevCntntFrm();
+ if ( pPrevCntntFrm )
+ {
+ if ( pCurrCntntFrm->IsInFly() )
+ {
+ // handling for environments 'unlinked fly frame' and
+ // 'group of linked fly frames':
+ // Nothing to do, <pPrevCntntFrm> is the one
+ }
+ else
+ {
+ const bool bInDocBody = pCurrCntntFrm->IsInDocBody();
+ const bool bInFtn = pCurrCntntFrm->IsInFtn();
+ if ( bInDocBody || ( bInFtn && !_bInSameFtn ) )
+ {
+ // handling for environments 'footnotes' and 'document body frames':
+ // Assure that found previous frame is also in one of these
+ // environments. Otherwise, travel further
+ while ( pPrevCntntFrm )
+ {
+ if ( ( bInDocBody && pPrevCntntFrm->IsInDocBody() ) ||
+ ( bInFtn && pPrevCntntFrm->IsInFtn() ) )
+ {
+ break;
+ }
+ pPrevCntntFrm = pPrevCntntFrm->GetPrevCntntFrm();
+ }
+ }
+ else if ( bInFtn && _bInSameFtn )
+ {
+ // handling for environments 'each footnote':
+ // Assure that found next content frame belongs to the same footnotes
+ const SwFtnFrm* pFtnFrmOfPrev( pPrevCntntFrm->FindFtnFrm() );
+ const SwFtnFrm* pFtnFrmOfCurr( pCurrCntntFrm->FindFtnFrm() );
+ if ( pFtnFrmOfPrev != pFtnFrmOfCurr )
+ {
+ if ( pFtnFrmOfCurr->GetMaster() )
+ {
+ SwFtnFrm* pMasterFtnFrmOfCurr(
+ const_cast<SwFtnFrm*>(pFtnFrmOfCurr) );
+ pPrevCntntFrm = 0L;
+ // --> OD 2007-07-05 #146872#
+ // correct wrong loop-condition
+ do {
+ pMasterFtnFrmOfCurr = pMasterFtnFrmOfCurr->GetMaster();
+ pPrevCntntFrm = pMasterFtnFrmOfCurr->FindLastCntnt();
+ } while ( !pPrevCntntFrm &&
+ pMasterFtnFrmOfCurr->GetMaster() );
+ // <--
+ }
+ else
+ {
+ // current content frame is the first content in the
+ // footnote - no previous content exists.
+ pPrevCntntFrm = 0L;;
+ }
+ }
+ }
+ else
+ {
+ // handling for environments 'page header' and 'page footer':
+ // Assure that found previous frame is also in the same
+ // page header respectively page footer as <pCurrCntntFrm>
+ // Note: At this point its clear, that <pCurrCntntFrm> has
+ // to be inside a page header or page footer and that
+ // neither <pCurrCntntFrm> nor <pPrevCntntFrm> are
+ // inside a fly frame.
+ // Thus, method <FindFooterOrHeader()> can be used.
+ OSL_ENSURE( pCurrCntntFrm->FindFooterOrHeader(),
+ "<SwFrm::_FindPrevCnt()> - unknown layout situation: current frame should be in page header or page footer" );
+ OSL_ENSURE( !pPrevCntntFrm->IsInFly(),
+ "<SwFrm::_FindPrevCnt()> - unknown layout situation: found previous frame should *not* be inside a fly frame." );
+ if ( pPrevCntntFrm->FindFooterOrHeader() !=
+ pCurrCntntFrm->FindFooterOrHeader() )
+ {
+ pPrevCntntFrm = 0L;
+ }
+ }
+ }
+ }
+ }
+
+ return pPrevCntntFrm;
+}
+
+SwFrm *SwFrm::_FindPrev()
+{
+ sal_Bool bIgnoreTab = sal_False;
+ SwFrm *pThis = this;
+
+ if ( IsTabFrm() )
+ {
+ //Der erste Cntnt der Tabelle wird
+ //gegriffen und dessen Vorgaenger geliefert. Um die Spezialbeh.
+ //Fuer Tabellen (s.u.) auszuschalten wird bIgnoreTab gesetzt.
+ if ( ((SwTabFrm*)this)->IsFollow() )
+ return ((SwTabFrm*)this)->FindMaster();
+ else
+ pThis = ((SwTabFrm*)this)->ContainsCntnt();
+ bIgnoreTab = sal_True;
+ }
+
+ if ( pThis && pThis->IsCntntFrm() )
+ {
+ SwCntntFrm *pPrvCnt = ((SwCntntFrm*)pThis)->GetPrevCntntFrm();
+ if( !pPrvCnt )
+ return 0;
+ if ( !bIgnoreTab && pThis->IsInTab() )
+ {
+ SwLayoutFrm *pUp = pThis->GetUpper();
+ while ( !pUp->IsCellFrm() )
+ pUp = pUp->GetUpper();
+ OSL_ENSURE( pUp, "Cntnt in Tabelle aber nicht in Zelle." );
+ if ( pUp->IsAnLower( pPrvCnt ) )
+ return pPrvCnt;
+ }
+ else
+ {
+ SwFrm* pRet;
+ const sal_Bool bBody = pThis->IsInDocBody();
+ const sal_Bool bFtn = bBody ? sal_False : pThis->IsInFtn();
+ if ( bBody || bFtn )
+ {
+ while ( pPrvCnt )
+ {
+ if ( (bBody && pPrvCnt->IsInDocBody()) ||
+ (bFtn && pPrvCnt->IsInFtn()) )
+ {
+ pRet = pPrvCnt->IsInTab() ? pPrvCnt->FindTabFrm()
+ : (SwFrm*)pPrvCnt;
+ return pRet;
+ }
+ pPrvCnt = pPrvCnt->GetPrevCntntFrm();
+ }
+ }
+ else if ( pThis->IsInFly() )
+ {
+ pRet = pPrvCnt->IsInTab() ? pPrvCnt->FindTabFrm()
+ : (SwFrm*)pPrvCnt;
+ return pRet;
+ }
+ else //Fuss-/oder Kopfbereich oder Fly
+ {
+ const SwFrm *pUp = pThis->GetUpper();
+ const SwFrm *pCntUp = pPrvCnt->GetUpper();
+ while ( pUp && pUp->GetUpper() &&
+ !pUp->IsHeaderFrm() && !pUp->IsFooterFrm() )
+ pUp = pUp->GetUpper();
+ while ( pCntUp && pCntUp->GetUpper() )
+ pCntUp = pCntUp->GetUpper();
+ if ( pCntUp == pUp )
+ {
+ pRet = pPrvCnt->IsInTab() ? pPrvCnt->FindTabFrm()
+ : (SwFrm*)pPrvCnt;
+ return pRet;
+ }
+ }
+ }
+ }
+ return 0;
+}
+
+void SwFrm::ImplInvalidateNextPos( sal_Bool bNoFtn )
+{
+ SwFrm *pFrm;
+ if ( 0 != (pFrm = _FindNext()) )
+ {
+ if( pFrm->IsSctFrm() )
+ {
+ while( pFrm && pFrm->IsSctFrm() )
+ {
+ if( ((SwSectionFrm*)pFrm)->GetSection() )
+ {
+ SwFrm* pTmp = ((SwSectionFrm*)pFrm)->ContainsAny();
+ if( pTmp )
+ pTmp->InvalidatePos();
+ else if( !bNoFtn )
+ ((SwSectionFrm*)pFrm)->InvalidateFtnPos();
+ if( !IsInSct() || FindSctFrm()->GetFollow() != pFrm )
+ pFrm->InvalidatePos();
+ return;
+ }
+ pFrm = pFrm->FindNext();
+ }
+ if( pFrm )
+ {
+ if ( pFrm->IsSctFrm())
+ { // Damit der Inhalt eines Bereichs die Chance erhaelt,
+ // die Seite zu wechseln, muss er ebenfalls invalidiert werden.
+ SwFrm* pTmp = ((SwSectionFrm*)pFrm)->ContainsAny();
+ if( pTmp )
+ pTmp->InvalidatePos();
+ if( !IsInSct() || FindSctFrm()->GetFollow() != pFrm )
+ pFrm->InvalidatePos();
+ }
+ else
+ pFrm->InvalidatePos();
+ }
+ }
+ else
+ pFrm->InvalidatePos();
+ }
+}
+
+/** method to invalidate printing area of next frame
+
+ OD 09.01.2004 #i11859#
+
+ @author OD
+
+ FME 2004-04-19 #i27145# Moved function from SwTxtFrm to SwFrm
+*/
+void SwFrm::InvalidateNextPrtArea()
+{
+ // determine next frame
+ SwFrm* pNextFrm = FindNext();
+ // skip empty section frames and hidden text frames
+ {
+ while ( pNextFrm &&
+ ( ( pNextFrm->IsSctFrm() &&
+ !static_cast<SwSectionFrm*>(pNextFrm)->GetSection() ) ||
+ ( pNextFrm->IsTxtFrm() &&
+ static_cast<SwTxtFrm*>(pNextFrm)->IsHiddenNow() ) ) )
+ {
+ pNextFrm = pNextFrm->FindNext();
+ }
+ }
+
+ // Invalidate printing area of found next frame
+ if ( pNextFrm )
+ {
+ if ( pNextFrm->IsSctFrm() )
+ {
+ // Invalidate printing area of found section frame, if
+ // (1) this text frame isn't in a section OR
+ // (2) found section frame isn't a follow of the section frame this
+ // text frame is in.
+ if ( !IsInSct() || FindSctFrm()->GetFollow() != pNextFrm )
+ {
+ pNextFrm->InvalidatePrt();
+ }
+
+ // Invalidate printing area of first content in found section.
+ SwFrm* pFstCntntOfSctFrm =
+ static_cast<SwSectionFrm*>(pNextFrm)->ContainsAny();
+ if ( pFstCntntOfSctFrm )
+ {
+ pFstCntntOfSctFrm->InvalidatePrt();
+ }
+ }
+ else
+ {
+ pNextFrm->InvalidatePrt();
+ }
+ }
+}
+
+/*************************************************************************
+|*
+|* lcl_IsInColSect()
+|* liefert nur sal_True, wenn der Frame _direkt_ in einem spaltigen Bereich steht,
+|* nicht etwa, wenn er in einer Tabelle steht, die in einem spaltigen Bereich ist.
+|*
+|*************************************************************************/
+
+sal_Bool lcl_IsInColSct( const SwFrm *pUp )
+{
+ sal_Bool bRet = sal_False;
+ while( pUp )
+ {
+ if( pUp->IsColumnFrm() )
+ bRet = sal_True;
+ else if( pUp->IsSctFrm() )
+ return bRet;
+ else if( pUp->IsTabFrm() )
+ return sal_False;
+ pUp = pUp->GetUpper();
+ }
+ return sal_False;
+}
+
+/*************************************************************************
+|*
+|* SwFrm::IsMoveable();
+|*
+|*************************************************************************/
+/** determine, if frame is moveable in given environment
+
+ OD 08.08.2003 #110978#
+ method replaced 'old' method <sal_Bool IsMoveable() const>.
+ Determines, if frame is moveable in given environment. if no environment
+ is given (parameter _pLayoutFrm == 0L), the movability in the actual
+ environment (<this->GetUpper()) is checked.
+
+ @author OD
+*/
+
+bool SwFrm::IsMoveable( const SwLayoutFrm* _pLayoutFrm ) const
+{
+ bool bRetVal = false;
+
+ if ( !_pLayoutFrm )
+ {
+ _pLayoutFrm = GetUpper();
+ }
+
+ if ( _pLayoutFrm && IsFlowFrm() )
+ {
+ if ( _pLayoutFrm->IsInSct() && lcl_IsInColSct( _pLayoutFrm ) )
+ {
+ bRetVal = true;
+ }
+ else if ( _pLayoutFrm->IsInFly() ||
+ _pLayoutFrm->IsInDocBody() ||
+ _pLayoutFrm->IsInFtn() )
+ {
+ if ( _pLayoutFrm->IsInTab() && !IsTabFrm() &&
+ ( !IsCntntFrm() || !const_cast<SwFrm*>(this)->GetNextCellLeaf( MAKEPAGE_NONE ) ) )
+ {
+ bRetVal = false;
+ }
+ else
+ {
+ if ( _pLayoutFrm->IsInFly() )
+ {
+ // if fly frame has a follow (next linked fly frame),
+ // frame is moveable.
+ if ( const_cast<SwLayoutFrm*>(_pLayoutFrm)->FindFlyFrm()->GetNextLink() )
+ {
+ bRetVal = true;
+ }
+ else
+ {
+ // if environment is columned, frame is moveable, if
+ // it isn't in last column.
+ // search for column frame
+ const SwFrm* pCol = _pLayoutFrm;
+ while ( pCol && !pCol->IsColumnFrm() )
+ {
+ pCol = pCol->GetUpper();
+ }
+ // frame is moveable, if found column frame isn't last one.
+ if ( pCol && pCol->GetNext() )
+ {
+ bRetVal = true;
+ }
+ }
+ }
+ else
+ {
+ bRetVal = true;
+ }
+ }
+ }
+ }
+
+ return bRetVal;
+}
+
+/*************************************************************************
+|*
+|* SwFrm::SetInfFlags();
+|*
+|*************************************************************************/
+void SwFrm::SetInfFlags()
+{
+ if ( !IsFlyFrm() && !GetUpper() ) //noch nicht gepastet, keine Informationen
+ return; //lieferbar
+
+ bInfInvalid = bInfBody = bInfTab = bInfFly = bInfFtn = bInfSct = sal_False;
+
+ SwFrm *pFrm = this;
+ if( IsFtnContFrm() )
+ bInfFtn = sal_True;
+ do
+ { // bInfBody wird nur am Seitenbody, nicht im ColumnBody gesetzt
+ if ( pFrm->IsBodyFrm() && !bInfFtn && pFrm->GetUpper()
+ && pFrm->GetUpper()->IsPageFrm() )
+ bInfBody = sal_True;
+ else if ( pFrm->IsTabFrm() || pFrm->IsCellFrm() )
+ {
+ bInfTab = sal_True;
+ }
+ else if ( pFrm->IsFlyFrm() )
+ bInfFly = sal_True;
+ else if ( pFrm->IsSctFrm() )
+ bInfSct = sal_True;
+ else if ( pFrm->IsFtnFrm() )
+ bInfFtn = sal_True;
+
+ pFrm = pFrm->GetUpper();
+
+ } while ( pFrm && !pFrm->IsPageFrm() ); //Oberhalb der Seite kommt nix
+}
+
+/*-----------------22.8.2001 14:30------------------
+ * SwFrm::SetDirFlags( sal_Bool )
+ * actualizes the vertical or the righttoleft-flags.
+ * If the property is derived, it's from the upper or (for fly frames) from
+ * the anchor. Otherwise we've to call a virtual method to check the property.
+ * --------------------------------------------------*/
+
+void SwFrm::SetDirFlags( sal_Bool bVert )
+{
+ if( bVert )
+ {
+ // OD 2004-01-21 #114969# - if derived, valid vertical flag only if
+ // vertical flag of upper/anchor is valid.
+ if( bDerivedVert )
+ {
+ const SwFrm* pAsk = IsFlyFrm() ?
+ ((SwFlyFrm*)this)->GetAnchorFrm() : GetUpper();
+
+ OSL_ENSURE( pAsk != this, "Autsch! Stack overflow is about to happen" );
+
+ if( pAsk )
+ {
+ bVertical = pAsk->IsVertical() ? 1 : 0;
+ bReverse = pAsk->IsReverse() ? 1 : 0;
+
+ bVertLR = pAsk->IsVertLR() ? 1 : 0;
+ //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin
+ if ( !pAsk->bInvalidVert )
+ bInvalidVert = sal_False;
+ }
+ }
+ else
+ CheckDirection( bVert );
+ }
+ else
+ {
+ sal_Bool bInv = 0;
+ if( !bDerivedR2L ) // CheckDirection is able to set bDerivedR2L!
+ CheckDirection( bVert );
+ if( bDerivedR2L )
+ {
+ const SwFrm* pAsk = IsFlyFrm() ?
+ ((SwFlyFrm*)this)->GetAnchorFrm() : GetUpper();
+
+ OSL_ENSURE( pAsk != this, "Autsch! Stack overflow is about to happen" );
+
+ if( pAsk )
+ bRightToLeft = pAsk->IsRightToLeft() ? 1 : 0;
+ if( !pAsk || pAsk->bInvalidR2L )
+ bInv = bInvalidR2L;
+ }
+ bInvalidR2L = bInv;
+ }
+}
+
+SwLayoutFrm* SwFrm::GetNextCellLeaf( MakePageType )
+{
+ SwFrm* pTmpFrm = this;
+ while ( !pTmpFrm->IsCellFrm() )
+ pTmpFrm = pTmpFrm->GetUpper();
+
+ OSL_ENSURE( pTmpFrm, "SwFrm::GetNextCellLeaf() without cell" );
+ return ((SwCellFrm*)pTmpFrm)->GetFollowCell();
+}
+
+SwLayoutFrm* SwFrm::GetPrevCellLeaf( MakePageType )
+{
+ SwFrm* pTmpFrm = this;
+ while ( !pTmpFrm->IsCellFrm() )
+ pTmpFrm = pTmpFrm->GetUpper();
+
+ OSL_ENSURE( pTmpFrm, "SwFrm::GetNextPreviousLeaf() without cell" );
+ return ((SwCellFrm*)pTmpFrm)->GetPreviousCell();
+}
+
+SwCellFrm* lcl_FindCorrespondingCellFrm( const SwRowFrm& rOrigRow,
+ const SwCellFrm& rOrigCell,
+ const SwRowFrm& rCorrRow,
+ bool bInFollow )
+{
+ SwCellFrm* pRet = NULL;
+ SwCellFrm* pCell = (SwCellFrm*)rOrigRow.Lower();
+ SwCellFrm* pCorrCell = (SwCellFrm*)rCorrRow.Lower();
+
+ while ( pCell != &rOrigCell && !pCell->IsAnLower( &rOrigCell ) )
+ {
+ pCell = (SwCellFrm*)pCell->GetNext();
+ pCorrCell = (SwCellFrm*)pCorrCell->GetNext();
+ }
+
+ OSL_ENSURE( pCell && pCorrCell, "lcl_FindCorrespondingCellFrm does not work" );
+
+ if ( pCell != &rOrigCell )
+ {
+ // rOrigCell must be a lower of pCell. We need to recurse into the rows:
+ OSL_ENSURE( pCell->Lower() && pCell->Lower()->IsRowFrm(),
+ "lcl_FindCorrespondingCellFrm does not work" );
+
+ SwRowFrm* pRow = (SwRowFrm*)pCell->Lower();
+ while ( !pRow->IsAnLower( &rOrigCell ) )
+ pRow = (SwRowFrm*)pRow->GetNext();
+
+ SwRowFrm* pCorrRow = 0;
+ if ( bInFollow )
+ pCorrRow = pRow->GetFollowRow();
+ else
+ {
+ SwRowFrm* pTmpRow = static_cast<SwRowFrm*>(pCorrCell->GetLastLower());
+
+ if ( pTmpRow && pTmpRow->GetFollowRow() == pRow )
+ pCorrRow = pTmpRow;
+ }
+
+ if ( pCorrRow )
+ pRet = lcl_FindCorrespondingCellFrm( *pRow, rOrigCell, *pCorrRow, bInFollow );
+ }
+ else
+ pRet = pCorrCell;
+
+ return pRet;
+}
+
+// VERSION OF GetFollowCell() that assumes that we always have a follow flow line:
+SwCellFrm* SwCellFrm::GetFollowCell() const
+{
+ SwCellFrm* pRet = NULL;
+
+ // NEW TABLES
+ // Covered cells do not have follow cells!
+ const long nRowSpan = GetLayoutRowSpan();
+ if ( nRowSpan < 1 )
+ return NULL;
+
+ // find most upper row frame
+ const SwFrm* pRow = GetUpper();
+ while( !pRow->IsRowFrm() || !pRow->GetUpper()->IsTabFrm() )
+ pRow = pRow->GetUpper();
+
+ if ( !pRow )
+ return NULL;
+
+ const SwTabFrm* pTabFrm = static_cast<const SwTabFrm*>( pRow->GetUpper() );
+ if ( !pRow || !pTabFrm->GetFollow() || !pTabFrm->HasFollowFlowLine() )
+ return NULL;
+
+ const SwCellFrm* pThisCell = this;
+
+ // Get last cell of the current table frame that belongs to the rowspan:
+ if ( nRowSpan > 1 )
+ {
+ // optimization: Will end of row span be in last row or exceed row?
+ long nMax = 0;
+ while ( pRow->GetNext() && ++nMax < nRowSpan )
+ pRow = pRow->GetNext();
+
+ if ( !pRow->GetNext() )
+ {
+ pThisCell = &pThisCell->FindStartEndOfRowSpanCell( false, true );
+ pRow = pThisCell->GetUpper();
+ }
+ }
+
+ const SwRowFrm* pFollowRow = NULL;
+ if ( !pRow->GetNext() &&
+ NULL != ( pFollowRow = pRow->IsInSplitTableRow() ) &&
+ ( !pFollowRow->IsRowSpanLine() || nRowSpan > 1 ) )
+ pRet = lcl_FindCorrespondingCellFrm( *((SwRowFrm*)pRow), *pThisCell, *pFollowRow, true );
+
+ return pRet;
+}
+
+// VERSION OF GetPreviousCell() THAT ASSUMES THAT WE ALWAYS HAVE A FFL
+SwCellFrm* SwCellFrm::GetPreviousCell() const
+{
+ SwCellFrm* pRet = NULL;
+
+ // NEW TABLES
+ // Covered cells do not have previous cells!
+ if ( GetLayoutRowSpan() < 1 )
+ return NULL;
+
+ // find most upper row frame
+ const SwFrm* pRow = GetUpper();
+ while( !pRow->IsRowFrm() || !pRow->GetUpper()->IsTabFrm() )
+ pRow = pRow->GetUpper();
+
+ OSL_ENSURE( pRow->GetUpper() && pRow->GetUpper()->IsTabFrm(), "GetPreviousCell without Table" );
+
+ SwTabFrm* pTab = (SwTabFrm*)pRow->GetUpper();
+
+ if ( pTab->IsFollow() )
+ {
+ const SwFrm* pTmp = pTab->GetFirstNonHeadlineRow();
+ const bool bIsInFirstLine = ( pTmp == pRow );
+
+ if ( bIsInFirstLine )
+ {
+ SwTabFrm *pMaster = (SwTabFrm*)pTab->FindMaster();
+ if ( pMaster && pMaster->HasFollowFlowLine() )
+ {
+ SwRowFrm* pMasterRow = static_cast<SwRowFrm*>(pMaster->GetLastLower());
+ if ( pMasterRow )
+ pRet = lcl_FindCorrespondingCellFrm( *((SwRowFrm*)pRow), *this, *pMasterRow, false );
+ if ( pRet && pRet->GetTabBox()->getRowSpan() < 1 )
+ pRet = &const_cast<SwCellFrm&>(pRet->FindStartEndOfRowSpanCell( true, true ));
+ }
+ }
+ }
+
+ return pRet;
+}
+
+// --> NEW TABLES
+const SwCellFrm& SwCellFrm::FindStartEndOfRowSpanCell( bool bStart, bool bCurrentTableOnly ) const
+{
+ const SwCellFrm* pRet = 0;
+
+ const SwTabFrm* pTableFrm = dynamic_cast<const SwTabFrm*>(GetUpper()->GetUpper());
+
+ if ( !bStart && pTableFrm->IsFollow() && pTableFrm->IsInHeadline( *this ) )
+ return *this;
+
+ OSL_ENSURE( pTableFrm &&
+ ( (bStart && GetTabBox()->getRowSpan() < 1) ||
+ (!bStart && GetLayoutRowSpan() > 1) ),
+ "SwCellFrm::FindStartRowSpanCell: No rowspan, no table, no cookies" );
+
+ if ( pTableFrm )
+ {
+ const SwTable* pTable = pTableFrm->GetTable();
+
+ sal_uInt16 nMax = USHRT_MAX;
+ if ( bCurrentTableOnly )
+ {
+ const SwFrm* pCurrentRow = GetUpper();
+ const bool bDoNotEnterHeadline = bStart && pTableFrm->IsFollow() &&
+ !pTableFrm->IsInHeadline( *pCurrentRow );
+
+ // check how many rows we are allowed to go up or down until we reach the end of
+ // the current table frame:
+ nMax = 0;
+ while ( bStart ? pCurrentRow->GetPrev() : pCurrentRow->GetNext() )
+ {
+ if ( bStart )
+ {
+ // do not enter a repeated headline:
+ if ( bDoNotEnterHeadline && pTableFrm->IsFollow() &&
+ pTableFrm->IsInHeadline( *pCurrentRow->GetPrev() ) )
+ break;
+
+ pCurrentRow = pCurrentRow->GetPrev();
+ }
+ else
+ pCurrentRow = pCurrentRow->GetNext();
+
+ ++nMax;
+ }
+ }
+
+ // By passing the nMax value for Find*OfRowSpan (in case of bCurrentTableOnly
+ // is set) we assure that we find a rMasterBox that has a SwCellFrm in
+ // the current table frame:
+ const SwTableBox& rMasterBox = bStart ?
+ GetTabBox()->FindStartOfRowSpan( *pTable, nMax ) :
+ GetTabBox()->FindEndOfRowSpan( *pTable, nMax );
+
+ SwIterator<SwCellFrm,SwFmt> aIter( *rMasterBox.GetFrmFmt() );
+
+ for ( SwCellFrm* pMasterCell = aIter.First(); pMasterCell; pMasterCell = aIter.Next() )
+ {
+ if ( pMasterCell->GetTabBox() == &rMasterBox )
+ {
+ const SwTabFrm* pMasterTable = static_cast<const SwTabFrm*>(pMasterCell->GetUpper()->GetUpper());
+
+ if ( bCurrentTableOnly )
+ {
+ if ( pMasterTable == pTableFrm )
+ {
+ pRet = pMasterCell;
+ break;
+ }
+ }
+ else
+ {
+ if ( pMasterTable == pTableFrm ||
+ ( (bStart && pMasterTable->IsAnFollow(pTableFrm)) ||
+ (!bStart && pTableFrm->IsAnFollow(pMasterTable)) ) )
+ {
+ pRet = pMasterCell;
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ OSL_ENSURE( pRet, "SwCellFrm::FindStartRowSpanCell: No result" );
+
+ return *pRet;
+}
+// <-- NEW TABLES
+
+const SwRowFrm* SwFrm::IsInSplitTableRow() const
+{
+ OSL_ENSURE( IsInTab(), "IsInSplitTableRow should only be called for frames in tables" );
+
+ const SwFrm* pRow = this;
+
+ // find most upper row frame
+ while( pRow && ( !pRow->IsRowFrm() || !pRow->GetUpper()->IsTabFrm() ) )
+ pRow = pRow->GetUpper();
+
+ if ( !pRow ) return NULL;
+
+ OSL_ENSURE( pRow->GetUpper()->IsTabFrm(), "Confusion in table layout" );
+
+ const SwTabFrm* pTab = (SwTabFrm*)pRow->GetUpper();
+ // --> OD 2006-06-28 #b6443897#
+ // If most upper row frame is a headline row, the current frame
+ // can't be in a splitted table row. Thus, add corresponding condition.
+ if ( pRow->GetNext() ||
+ pTab->GetTable()->IsHeadline(
+ *(static_cast<const SwRowFrm*>(pRow)->GetTabLine()) ) ||
+ !pTab->HasFollowFlowLine() ||
+ !pTab->GetFollow() )
+ return NULL;
+ // <--
+
+ // skip headline
+ const SwRowFrm* pFollowRow = pTab->GetFollow()->GetFirstNonHeadlineRow();
+
+ OSL_ENSURE( pFollowRow, "SwFrm::IsInSplitTableRow() does not work" );
+
+ return pFollowRow;
+}
+
+const SwRowFrm* SwFrm::IsInFollowFlowRow() const
+{
+ OSL_ENSURE( IsInTab(), "IsInSplitTableRow should only be called for frames in tables" );
+
+ // find most upper row frame
+ const SwFrm* pRow = this;
+ while( pRow && ( !pRow->IsRowFrm() || !pRow->GetUpper()->IsTabFrm() ) )
+ pRow = pRow->GetUpper();
+
+ if ( !pRow ) return NULL;
+
+ OSL_ENSURE( pRow->GetUpper()->IsTabFrm(), "Confusion in table layout" );
+
+ const SwTabFrm* pTab = (SwTabFrm*)pRow->GetUpper();
+
+ const SwTabFrm* pMaster = pTab->IsFollow() ? pTab->FindMaster() : 0;
+
+ if ( !pMaster || !pMaster->HasFollowFlowLine() )
+ return NULL;
+
+ const SwFrm* pTmp = pTab->GetFirstNonHeadlineRow();
+ const bool bIsInFirstLine = ( pTmp == pRow );
+
+ if ( !bIsInFirstLine )
+ return NULL;
+
+ const SwRowFrm* pMasterRow = static_cast<const SwRowFrm*>(pMaster->GetLastLower());
+ return pMasterRow;
+}
+
+bool SwFrm::IsInBalancedSection() const
+{
+ bool bRet = false;
+
+ if ( IsInSct() )
+ {
+ const SwSectionFrm* pSectionFrm = FindSctFrm();
+ if ( pSectionFrm )
+ bRet = pSectionFrm->IsBalancedSection();
+ }
+ return bRet;
+}
+
+/*
+ * SwLayoutFrm::GetLastLower()
+ */
+const SwFrm* SwLayoutFrm::GetLastLower() const
+{
+ const SwFrm* pRet = Lower();
+ if ( !pRet )
+ return 0;
+ while ( pRet->GetNext() )
+ pRet = pRet->GetNext();
+ return pRet;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/layout/flowfrm.cxx b/sw/source/core/layout/flowfrm.cxx
new file mode 100644
index 000000000000..59fac2138f1d
--- /dev/null
+++ b/sw/source/core/layout/flowfrm.cxx
@@ -0,0 +1,2672 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+#include "pam.hxx"
+#include "swtable.hxx"
+#include "frame.hxx"
+#include "rootfrm.hxx"
+#include "pagefrm.hxx"
+#include "flyfrm.hxx"
+#include "viewsh.hxx"
+#include "doc.hxx"
+#include "viewimp.hxx"
+#include "viewopt.hxx"
+#include "dflyobj.hxx"
+#include "frmtool.hxx"
+#include "dcontact.hxx"
+#include <editeng/brkitem.hxx>
+#include <editeng/keepitem.hxx>
+#include <fmtsrnd.hxx>
+#include <fmtanchr.hxx>
+#include <fmtpdsc.hxx>
+#include <editeng/ulspitem.hxx>
+#include <tgrditem.hxx>
+#include <txtftn.hxx>
+#include <fmtftn.hxx>
+#include <editeng/pgrditem.hxx>
+#include <paratr.hxx>
+#include "ftnfrm.hxx"
+#include "txtfrm.hxx"
+#include "tabfrm.hxx"
+#include "pagedesc.hxx"
+#include "layact.hxx"
+#include "fmtornt.hxx"
+#include "flyfrms.hxx"
+#include "sectfrm.hxx"
+#include "section.hxx"
+#include "dbg_lay.hxx"
+#include "lineinfo.hxx"
+#include <fmtclbl.hxx>
+#include <sortedobjs.hxx>
+#include <layouter.hxx>
+#include <fmtfollowtextflow.hxx>
+#include <switerator.hxx>
+
+sal_Bool SwFlowFrm::bMoveBwdJump = sal_False;
+
+
+/*************************************************************************
+|*
+|* SwFlowFrm::SwFlowFrm()
+|*
+|*************************************************************************/
+
+
+SwFlowFrm::SwFlowFrm( SwFrm &rFrm ) :
+ rThis( rFrm ),
+ pFollow( 0 )
+{
+ bLockJoin = bIsFollow = bCntntLock = bOwnFtnNum =
+ bFtnLock = bFlyLock = sal_False;
+}
+
+
+/*************************************************************************
+|*
+|* SwFlowFrm::IsFollowLocked()
+|* return sal_True if any follow has the JoinLocked flag
+|*
+|*************************************************************************/
+
+sal_Bool SwFlowFrm::HasLockedFollow() const
+{
+ const SwFlowFrm* pFrm = GetFollow();
+ while( pFrm )
+ {
+ if( pFrm->IsJoinLocked() )
+ return sal_True;
+ pFrm = pFrm->GetFollow();
+ }
+ return sal_False;
+}
+
+/*************************************************************************
+|*
+|* SwFlowFrm::IsKeepFwdMoveAllowed()
+|*
+|*************************************************************************/
+
+
+sal_Bool SwFlowFrm::IsKeepFwdMoveAllowed()
+{
+ //Wenn der Vorgaenger das KeepAttribut traegt und auch dessen
+ //Vorgaenger usw. bis zum ersten der Kette und fuer diesen das
+ //IsFwdMoveAllowed ein sal_False liefert, so ist das Moven eben nicht erlaubt.
+ SwFrm *pFrm = &rThis;
+ if ( !pFrm->IsInFtn() )
+ do
+ { if ( pFrm->GetAttrSet()->GetKeep().GetValue() )
+ pFrm = pFrm->GetIndPrev();
+ else
+ return sal_True;
+ } while ( pFrm );
+
+ //Siehe IsFwdMoveAllowed()
+ sal_Bool bRet = sal_False;
+ if ( pFrm && pFrm->GetIndPrev() )
+ bRet = sal_True;
+ return bRet;
+}
+
+/*************************************************************************
+|*
+|* SwFlowFrm::CheckKeep()
+|*
+|*************************************************************************/
+
+
+void SwFlowFrm::CheckKeep()
+{
+ //Den 'letzten' Vorgaenger mit KeepAttribut anstossen, denn
+ //die ganze Truppe koennte zuruckrutschen.
+ SwFrm *pPre = rThis.GetIndPrev();
+ if( pPre->IsSctFrm() )
+ {
+ SwFrm *pLast = ((SwSectionFrm*)pPre)->FindLastCntnt();
+ if( pLast && pLast->FindSctFrm() == pPre )
+ pPre = pLast;
+ else
+ return;
+ }
+ SwFrm* pTmp;
+ sal_Bool bKeep;
+ while ( sal_True == (bKeep = pPre->GetAttrSet()->GetKeep().GetValue()) &&
+ 0 != ( pTmp = pPre->GetIndPrev() ) )
+ {
+ if( pTmp->IsSctFrm() )
+ {
+ SwFrm *pLast = ((SwSectionFrm*)pTmp)->FindLastCntnt();
+ if( pLast && pLast->FindSctFrm() == pTmp )
+ pTmp = pLast;
+ else
+ break;
+ }
+ pPre = pTmp;
+ }
+ if ( bKeep )
+ pPre->InvalidatePos();
+}
+
+/*************************************************************************
+|*
+|* SwFlowFrm::IsKeep()
+|*
+|*************************************************************************/
+
+sal_Bool SwFlowFrm::IsKeep( const SwAttrSet& rAttrs, bool bCheckIfLastRowShouldKeep ) const
+{
+ // 1. The keep attribute is ignored inside footnotes
+ // 2. For compatibility reasons, the keep attribute is
+ // ignored for frames inside table cells
+ // 3. If bBreakCheck is set to true, this function only checks
+ // if there are any break after attributes set at rAttrs
+ // or break before attributes set for the next content (or next table)
+ sal_Bool bKeep = bCheckIfLastRowShouldKeep ||
+ ( !rThis.IsInFtn() &&
+ ( !rThis.IsInTab() || rThis.IsTabFrm() ) &&
+ rAttrs.GetKeep().GetValue() );
+
+ OSL_ENSURE( !bCheckIfLastRowShouldKeep || rThis.IsTabFrm(),
+ "IsKeep with bCheckIfLastRowShouldKeep should only be used for tabfrms" );
+
+ // Ignore keep attribute if there are break situations:
+ if ( bKeep )
+ {
+ switch ( rAttrs.GetBreak().GetBreak() )
+ {
+ case SVX_BREAK_COLUMN_AFTER:
+ case SVX_BREAK_COLUMN_BOTH:
+ case SVX_BREAK_PAGE_AFTER:
+ case SVX_BREAK_PAGE_BOTH:
+ {
+ bKeep = sal_False;
+ }
+ default: break;
+ }
+ if ( bKeep )
+ {
+ SwFrm *pNxt;
+ if( 0 != (pNxt = rThis.FindNextCnt()) &&
+ (!pFollow || pNxt != pFollow->GetFrm()))
+ {
+ // --> FME 2006-05-15 #135914#
+ // The last row of a table only keeps with the next content
+ // it they are in the same section:
+ if ( bCheckIfLastRowShouldKeep )
+ {
+ const SwSection* pThisSection = 0;
+ const SwSection* pNextSection = 0;
+ const SwSectionFrm* pThisSectionFrm = rThis.FindSctFrm();
+ const SwSectionFrm* pNextSectionFrm = pNxt->FindSctFrm();
+
+ if ( pThisSectionFrm )
+ pThisSection = pThisSectionFrm->GetSection();
+
+ if ( pNextSectionFrm )
+ pNextSection = pNextSectionFrm->GetSection();
+
+ if ( pThisSection != pNextSection )
+ bKeep = sal_False;
+ }
+ // <--
+
+ if ( bKeep )
+ {
+ const SwAttrSet* pSet = NULL;
+
+ if ( pNxt->IsInTab() )
+ {
+ SwTabFrm* pTab = pNxt->FindTabFrm();
+ if ( ! rThis.IsInTab() || rThis.FindTabFrm() != pTab )
+ pSet = &pTab->GetFmt()->GetAttrSet();
+ }
+
+ if ( ! pSet )
+ pSet = pNxt->GetAttrSet();
+
+ OSL_ENSURE( pSet, "No AttrSet to check keep attribute" );
+
+ if ( pSet->GetPageDesc().GetPageDesc() )
+ bKeep = sal_False;
+ else switch ( pSet->GetBreak().GetBreak() )
+ {
+ case SVX_BREAK_COLUMN_BEFORE:
+ case SVX_BREAK_COLUMN_BOTH:
+ case SVX_BREAK_PAGE_BEFORE:
+ case SVX_BREAK_PAGE_BOTH:
+ bKeep = sal_False;
+ default: break;
+ }
+ }
+ }
+ }
+ }
+ return bKeep;
+}
+
+/*************************************************************************
+|*
+|* SwFlowFrm::BwdMoveNecessary()
+|*
+|*************************************************************************/
+
+
+sal_uInt8 SwFlowFrm::BwdMoveNecessary( const SwPageFrm *pPage, const SwRect &rRect )
+{
+ // Der return-Wert entscheidet mit,
+ // ob auf Zurueckgeflossen werden muss, (3)
+ // ob das gute alte WouldFit gerufen werden kann (0, 1)
+ // oder ob ein Umhaengen und eine Probeformatierung sinnvoll ist (2)
+ // dabei bedeutet Bit 1, dass Objekte an mir selbst verankert sind
+ // und Bit 2, dass ich anderen Objekten ausweichen muss.
+
+ //Wenn ein SurroundObj, dass einen Umfluss wuenscht mit dem Rect ueberlappt
+ //ist der Fluss notwendig (weil die Verhaeltnisse nicht geschaetzt werden
+ //koennen), es kann allerdings ggf. eine TestFormatierung stattfinden.
+ //Wenn das SurroundObj ein Fly ist und ich selbst ein Lower bin oder der Fly
+ //Lower von mir ist, so spielt er keine Rolle.
+ //Wenn das SurroundObj in einem zeichengebunden Fly verankert ist, und ich
+ //selbst nicht Lower dieses Zeichengebundenen Flys bin, so spielt der Fly
+ //keine Rolle.
+ //#32639# Wenn das Objekt bei mir verankert ist kann ich es
+ //vernachlaessigen, weil es hoechstwahrscheinlich (!?) mitfliesst,
+ //eine TestFormatierung ist dann allerdings nicht erlaubt!
+ sal_uInt8 nRet = 0;
+ SwFlowFrm *pTmp = this;
+ do
+ { // Wenn an uns oder einem Follow Objekte haengen, so
+ // kann keine ProbeFormatierung stattfinden, da absatzgebundene
+ // nicht richtig beruecksichtigt wuerden und zeichengebundene sollten
+ // gar nicht zur Probe formatiert werden.
+ if( pTmp->GetFrm()->GetDrawObjs() )
+ nRet = 1;
+ pTmp = pTmp->GetFollow();
+ } while ( !nRet && pTmp );
+ if ( pPage->GetSortedObjs() )
+ {
+ // --> OD 2004-07-01 #i28701# - new type <SwSortedObjs>
+ const SwSortedObjs &rObjs = *pPage->GetSortedObjs();
+ sal_uLong nIndex = ULONG_MAX;
+ for ( sal_uInt16 i = 0; nRet < 3 && i < rObjs.Count(); ++i )
+ {
+ // --> OD 2004-07-01 #i28701# - consider changed type of
+ // <SwSortedObjs> entries.
+ SwAnchoredObject* pObj = rObjs[i];
+ const SwFrmFmt& rFmt = pObj->GetFrmFmt();
+ const SwRect aRect( pObj->GetObjRect() );
+ if ( aRect.IsOver( rRect ) &&
+ rFmt.GetSurround().GetSurround() != SURROUND_THROUGHT )
+ {
+ if( rThis.IsLayoutFrm() && //Fly Lower von This?
+ Is_Lower_Of( &rThis, pObj->GetDrawObj() ) )
+ continue;
+ if( pObj->ISA(SwFlyFrm) )
+ {
+ const SwFlyFrm *pFly = static_cast<const SwFlyFrm*>(pObj);
+ if ( pFly->IsAnLower( &rThis ) )//This Lower vom Fly?
+ continue;
+ }
+
+ const SwFrm* pAnchor = pObj->GetAnchorFrm();
+ if ( pAnchor == &rThis )
+ {
+ nRet |= 1;
+ continue;
+ }
+
+ //Nicht wenn das Objekt im Textfluss hinter mir verankert ist,
+ //denn dann weiche ich ihm nicht aus.
+ if ( ::IsFrmInSameKontext( pAnchor, &rThis ) )
+ {
+ if ( rFmt.GetAnchor().GetAnchorId() == FLY_AT_PARA )
+ {
+ // Den Index des anderen erhalten wir immer ueber das Ankerattr.
+ sal_uLong nTmpIndex = rFmt.GetAnchor().GetCntntAnchor()->nNode.GetIndex();
+ // Jetzt wird noch ueberprueft, ob der aktuelle Absatz vor dem
+ // Anker des verdraengenden Objekts im Text steht, dann wird
+ // nicht ausgewichen.
+ // Der Index wird moeglichst ueber einen SwFmtAnchor ermittelt,
+ // da sonst recht teuer.
+ if( ULONG_MAX == nIndex )
+ {
+ const SwNode *pNode;
+ if ( rThis.IsCntntFrm() )
+ pNode = ((SwCntntFrm&)rThis).GetNode();
+ else if( rThis.IsSctFrm() )
+ pNode = ((SwSectionFmt*)((SwSectionFrm&)rThis).
+ GetFmt())->GetSectionNode();
+ else
+ {
+ OSL_ENSURE( rThis.IsTabFrm(), "new FowFrm?" );
+ pNode = ((SwTabFrm&)rThis).GetTable()->
+ GetTabSortBoxes()[0]->GetSttNd()->FindTableNode();
+ }
+ nIndex = pNode->GetIndex();
+ }
+ if( nIndex < nTmpIndex )
+ continue;
+ }
+ }
+ else
+ continue;
+
+ nRet |= 2;
+ }
+ }
+ }
+ return nRet;
+}
+
+/*************************************************************************
+|*
+|* SwFlowFrm::CutTree(), PasteTree(), MoveSubTree()
+|*
+|* Beschreibung Eine Spezialisierte Form des Cut() und Paste(), die
+|* eine ganze Kette umhaengt (naehmlich this und folgende). Dabei werden
+|* nur minimale Operationen und Benachrichtigungen ausgefuehrt.
+|*
+|*************************************************************************/
+
+
+SwLayoutFrm *SwFlowFrm::CutTree( SwFrm *pStart )
+{
+ //Der Start und alle Nachbarn werden ausgeschnitten, sie werden aneinander-
+ //gereiht und ein Henkel auf den ersten wird zurueckgeliefert.
+ //Zurueckbleibende werden geeignet invalidiert.
+
+ SwLayoutFrm *pLay = pStart->GetUpper();
+ if ( pLay->IsInFtn() )
+ pLay = pLay->FindFtnFrm();
+
+ // --> OD 2006-05-08 #i58846#
+ // <pPrepare( PREP_QUOVADIS )> only for frames in footnotes
+ if( pStart->IsInFtn() )
+ {
+ SwFrm* pTmp = pStart->GetIndPrev();
+ if( pTmp )
+ pTmp->Prepare( PREP_QUOVADIS );
+ }
+ // <--
+
+ //Nur fix auschneiden und zwar so, dass klare Verhaeltnisse bei den
+ //Verlassenen herrschen. Die Pointer der ausgeschnittenen Kette zeigen
+ //noch wer weiss wo hin.
+ if ( pStart == pStart->GetUpper()->Lower() )
+ pStart->GetUpper()->pLower = 0;
+ if ( pStart->GetPrev() )
+ {
+ pStart->GetPrev()->pNext = 0;
+ pStart->pPrev = 0;
+ }
+
+ if ( pLay->IsFtnFrm() )
+ {
+ if ( !pLay->Lower() && !pLay->IsColLocked() &&
+ !((SwFtnFrm*)pLay)->IsBackMoveLocked() )
+ {
+ pLay->Cut();
+ delete pLay;
+ }
+ else
+ {
+ sal_Bool bUnlock = !((SwFtnFrm*)pLay)->IsBackMoveLocked();
+ ((SwFtnFrm*)pLay)->LockBackMove();
+ pLay->InvalidateSize();
+ pLay->Calc();
+ SwCntntFrm *pCnt = pLay->ContainsCntnt();
+ while ( pCnt && pLay->IsAnLower( pCnt ) )
+ {
+ //Kann sein, dass der CntFrm gelockt ist, wir wollen hier nicht
+ //in eine endlose Seitenwanderung hineinlaufen und rufen das
+ //Calc garnicht erst!
+ OSL_ENSURE( pCnt->IsTxtFrm(), "Die Graphic ist gelandet." );
+ if ( ((SwTxtFrm*)pCnt)->IsLocked() ||
+ ((SwTxtFrm*)pCnt)->GetFollow() == pStart )
+ break;
+ pCnt->Calc();
+ pCnt = pCnt->GetNextCntntFrm();
+ }
+ if( bUnlock )
+ ((SwFtnFrm*)pLay)->UnlockBackMove();
+ }
+ pLay = 0;
+ }
+ return pLay;
+}
+
+
+
+sal_Bool SwFlowFrm::PasteTree( SwFrm *pStart, SwLayoutFrm *pParent, SwFrm *pSibling,
+ SwFrm *pOldParent )
+{
+ //returnt sal_True wenn in der Kette ein LayoutFrm steht.
+ sal_Bool bRet = sal_False;
+
+ //Die mit pStart beginnende Kette wird vor den Sibling unter den Parent
+ //gehaengt. Fuer geeignete Invalidierung wird ebenfalls gesorgt.
+
+ //Ich bekomme eine fertige Kette. Der Anfang der Kette muss verpointert
+ //werden, dann alle Upper fuer die Kette und schliesslich dass Ende.
+ //Unterwegs werden alle geeignet invalidiert.
+ if ( pSibling )
+ {
+ if ( 0 != (pStart->pPrev = pSibling->GetPrev()) )
+ pStart->GetPrev()->pNext = pStart;
+ else
+ pParent->pLower = pStart;
+ pSibling->_InvalidatePos();
+ pSibling->_InvalidatePrt();
+ }
+ else
+ {
+ if ( 0 == (pStart->pPrev = pParent->Lower()) )
+ pParent->pLower = pStart;
+ else
+ //Modified for #i100782#,04/03/2009
+ //If the pParent has more than 1 child nodes, former design will
+ //ignore them directly without any collection work. It will make some
+ //dangling pointers. This lead the crash...
+ //The new design will find the last child of pParent in loop way, and
+ //add the pStart after the last child.
+ // pParent->Lower()->pNext = pStart;
+ {
+ SwFrm* pTemp = pParent->pLower;
+ while (pTemp)
+ {
+ if (pTemp->pNext)
+ pTemp = pTemp->pNext;
+ else
+ {
+ pStart->pPrev = pTemp;
+ pTemp->pNext = pStart;
+ break;
+ }
+ }
+ }
+ //End modification for #i100782#,04/03/2009
+
+ // #i27145#
+ if ( pParent->IsSctFrm() )
+ {
+ // We have no sibling because pParent is a section frame and
+ // has just been created to contain some content. The printing
+ // area of the frame behind pParent has to be invalidated, so
+ // that the correct distance between pParent and the next frame
+ // can be calculated.
+ pParent->InvalidateNextPrtArea();
+ }
+ }
+ SwFrm *pFloat = pStart;
+ SwFrm *pLst = 0;
+ SWRECTFN( pParent )
+ SwTwips nGrowVal = 0;
+ do
+ { pFloat->pUpper = pParent;
+ pFloat->_InvalidateAll();
+ pFloat->CheckDirChange();
+
+ //Ich bin Freund des TxtFrm und darf deshalb so einiges. Das mit
+ //dem CacheIdx scheint etwas riskant!
+ if ( pFloat->IsTxtFrm() )
+ {
+ if ( ((SwTxtFrm*)pFloat)->GetCacheIdx() != USHRT_MAX )
+ ((SwTxtFrm*)pFloat)->Init(); //Ich bin sein Freund.
+ }
+ else
+ bRet = sal_True;
+
+ nGrowVal += (pFloat->Frm().*fnRect->fnGetHeight)();
+ if ( pFloat->GetNext() )
+ pFloat = pFloat->GetNext();
+ else
+ {
+ pLst = pFloat;
+ pFloat = 0;
+ }
+ } while ( pFloat );
+
+ if ( pSibling )
+ {
+ pLst->pNext = pSibling;
+ pSibling->pPrev = pLst;
+ if( pSibling->IsInFtn() )
+ {
+ if( pSibling->IsSctFrm() )
+ pSibling = ((SwSectionFrm*)pSibling)->ContainsAny();
+ if( pSibling )
+ pSibling->Prepare( PREP_ERGOSUM );
+ }
+ }
+ if ( nGrowVal )
+ {
+ if ( pOldParent && pOldParent->IsBodyFrm() ) //Fuer variable Seitenhoehe beim Browsen
+ pOldParent->Shrink( nGrowVal );
+ pParent->Grow( nGrowVal );
+ }
+
+ if ( pParent->IsFtnFrm() )
+ ((SwFtnFrm*)pParent)->InvalidateNxtFtnCnts( pParent->FindPageFrm() );
+ return bRet;
+}
+
+
+
+void SwFlowFrm::MoveSubTree( SwLayoutFrm* pParent, SwFrm* pSibling )
+{
+ OSL_ENSURE( pParent, "Kein Parent uebergeben." );
+ OSL_ENSURE( rThis.GetUpper(), "Wo kommen wir denn her?" );
+
+ //Sparsamer benachrichtigen wenn eine Action laeuft.
+ ViewShell *pSh = rThis.getRootFrm()->GetCurrShell();
+ const SwViewImp *pImp = pSh ? pSh->Imp() : 0;
+ const sal_Bool bComplete = pImp && pImp->IsAction() && pImp->GetLayAction().IsComplete();
+
+ if ( !bComplete )
+ {
+ SwFrm *pPre = rThis.GetIndPrev();
+ if ( pPre )
+ {
+ pPre->SetRetouche();
+ // --> OD 2004-11-23 #115759# - follow-up of #i26250#
+ // invalidate printing area of previous frame, if it's in a table
+ if ( pPre->GetUpper()->IsInTab() )
+ {
+ pPre->_InvalidatePrt();
+ }
+ // <--
+ pPre->InvalidatePage();
+ }
+ else
+ { rThis.GetUpper()->SetCompletePaint();
+ rThis.GetUpper()->InvalidatePage();
+ }
+ }
+
+ SwPageFrm *pOldPage = rThis.FindPageFrm();
+
+ SwLayoutFrm *pOldParent = CutTree( &rThis );
+ const sal_Bool bInvaLay = PasteTree( &rThis, pParent, pSibling, pOldParent );
+
+ // Wenn durch das Cut&Paste ein leerer SectionFrm entstanden ist, sollte
+ // dieser automatisch verschwinden.
+ SwSectionFrm *pSct;
+ // --> OD 2006-01-04 #126020# - adjust check for empty section
+ // --> OD 2006-02-01 #130797# - correct fix #126020#
+ if ( pOldParent && !pOldParent->Lower() &&
+ ( pOldParent->IsInSct() &&
+ !(pSct = pOldParent->FindSctFrm())->ContainsCntnt() &&
+ !pSct->ContainsAny( true ) ) )
+ // <--
+ {
+ pSct->DelEmpty( sal_False );
+ }
+
+ // In einem spaltigen Bereich rufen wir lieber kein Calc "von unten"
+ if( !rThis.IsInSct() &&
+ ( !rThis.IsInTab() || ( rThis.IsTabFrm() && !rThis.GetUpper()->IsInTab() ) ) )
+ rThis.GetUpper()->Calc();
+ else if( rThis.GetUpper()->IsSctFrm() )
+ {
+ SwSectionFrm* pTmpSct = (SwSectionFrm*)rThis.GetUpper();
+ sal_Bool bOld = pTmpSct->IsCntntLocked();
+ pTmpSct->SetCntntLock( sal_True );
+ pTmpSct->Calc();
+ if( !bOld )
+ pTmpSct->SetCntntLock( sal_False );
+ }
+ SwPageFrm *pPage = rThis.FindPageFrm();
+
+ if ( pOldPage != pPage )
+ {
+ rThis.InvalidatePage( pPage );
+ if ( rThis.IsLayoutFrm() )
+ {
+ SwCntntFrm *pCnt = ((SwLayoutFrm*)&rThis)->ContainsCntnt();
+ if ( pCnt )
+ pCnt->InvalidatePage( pPage );
+ }
+ else if ( pSh && pSh->GetDoc()->GetLineNumberInfo().IsRestartEachPage()
+ && pPage->FindFirstBodyCntnt() == &rThis )
+ {
+ rThis._InvalidateLineNum();
+ }
+ }
+ if ( bInvaLay || (pSibling && pSibling->IsLayoutFrm()) )
+ rThis.GetUpper()->InvalidatePage( pPage );
+}
+
+/*************************************************************************
+|*
+|* SwFlowFrm::IsAnFollow()
+|*
+|*************************************************************************/
+
+
+sal_Bool SwFlowFrm::IsAnFollow( const SwFlowFrm *pAssumed ) const
+{
+ const SwFlowFrm *pFoll = this;
+ do
+ { if ( pAssumed == pFoll )
+ return sal_True;
+ pFoll = pFoll->GetFollow();
+ } while ( pFoll );
+ return sal_False;
+}
+
+
+/*************************************************************************
+|*
+|* SwFlowFrm::FindMaster()
+|*
+|*************************************************************************/
+
+SwTxtFrm* SwCntntFrm::FindMaster() const
+{
+ OSL_ENSURE( IsFollow(), "SwCntntFrm::FindMaster(): !IsFollow" );
+
+ const SwCntntFrm* pCnt = GetPrevCntntFrm();
+
+ while ( pCnt )
+ {
+ if ( pCnt->HasFollow() && pCnt->GetFollow() == this )
+ {
+ OSL_ENSURE( pCnt->IsTxtFrm(), "NoTxtFrm with follow found" );
+ return (SwTxtFrm*)pCnt;
+ }
+ pCnt = pCnt->GetPrevCntntFrm();
+ }
+
+ OSL_FAIL( "Follow ist lost in Space." );
+ return 0;
+}
+
+SwSectionFrm* SwSectionFrm::FindMaster() const
+{
+ OSL_ENSURE( IsFollow(), "SwSectionFrm::FindMaster(): !IsFollow" );
+
+ SwIterator<SwSectionFrm,SwFmt> aIter( *pSection->GetFmt() );
+ SwSectionFrm* pSect = aIter.First();
+ while ( pSect )
+ {
+ if( pSect->GetFollow() == this )
+ return pSect;
+ pSect = aIter.Next();
+ }
+
+ OSL_FAIL( "Follow ist lost in Space." );
+ return 0;
+}
+
+SwTabFrm* SwTabFrm::FindMaster( bool bFirstMaster ) const
+{
+ OSL_ENSURE( IsFollow(), "SwTabFrm::FindMaster(): !IsFollow" );
+
+ SwIterator<SwTabFrm,SwFmt> aIter( *GetTable()->GetFrmFmt() );
+ SwTabFrm* pTab = aIter.First();
+ while ( pTab )
+ {
+ if ( bFirstMaster )
+ {
+ //
+ // Optimization. This makes code like this obsolete:
+ // while ( pTab->IsFollow() )
+ // pTab = pTab->FindMaster();
+ //
+ if ( !pTab->IsFollow() )
+ {
+ SwTabFrm* pNxt = pTab;
+ while ( pNxt )
+ {
+ if ( pNxt->GetFollow() == this )
+ return pTab;
+ pNxt = pNxt->GetFollow();
+ }
+ }
+ }
+ else
+ {
+ if ( pTab->GetFollow() == this )
+ return pTab;
+ }
+
+ pTab = aIter.Next();
+ }
+
+ OSL_FAIL( "Follow ist lost in Space." );
+ return 0;
+}
+
+/*************************************************************************
+|*
+|* SwFrm::GetLeaf()
+|*
+|* Beschreibung Liefert das naechste/vorhergehende LayoutBlatt,
+|* das _nicht_ unterhalb von this liegt (oder gar this selbst ist).
+|* Ausserdem muss dieses LayoutBlatt im gleichen Textfluss wie
+|* pAnch Ausgangsfrm liegen (Body, Ftn)
+|*
+|*************************************************************************/
+
+
+const SwLayoutFrm *SwFrm::GetLeaf( MakePageType eMakePage, sal_Bool bFwd,
+ const SwFrm *pAnch ) const
+{
+ //Ohne Fluss kein genuss...
+ if ( !(IsInDocBody() || IsInFtn() || IsInFly()) )
+ return 0;
+
+ const SwFrm *pLeaf = this;
+ sal_Bool bFound = sal_False;
+
+ do
+ { pLeaf = ((SwFrm*)pLeaf)->GetLeaf( eMakePage, bFwd );
+
+ if ( pLeaf &&
+ (!IsLayoutFrm() || !((SwLayoutFrm*)this)->IsAnLower( pLeaf )))
+ {
+ if ( pAnch->IsInDocBody() == pLeaf->IsInDocBody() &&
+ pAnch->IsInFtn() == pLeaf->IsInFtn() )
+ {
+ bFound = sal_True;
+ }
+ }
+ } while ( !bFound && pLeaf );
+
+ return (const SwLayoutFrm*)pLeaf;
+}
+
+/*************************************************************************
+|*
+|* SwFrm::GetLeaf()
+|*
+|* Beschreibung Ruft Get[Next|Prev]Leaf
+|*
+|*************************************************************************/
+
+
+SwLayoutFrm *SwFrm::GetLeaf( MakePageType eMakePage, sal_Bool bFwd )
+{
+ if ( IsInFtn() )
+ return bFwd ? GetNextFtnLeaf( eMakePage ) : GetPrevFtnLeaf( eMakePage );
+
+ // --> OD 2005-08-16 #i53323#
+ // A frame could be inside a table AND inside a section.
+ // Thus, it has to be determined, which is the first parent.
+ bool bInTab( IsInTab() );
+ bool bInSct( IsInSct() );
+ if ( bInTab && bInSct )
+ {
+ const SwFrm* pUpperFrm( GetUpper() );
+ while ( pUpperFrm )
+ {
+ if ( pUpperFrm->IsTabFrm() )
+ {
+ // the table is the first.
+ bInSct = false;
+ break;
+ }
+ else if ( pUpperFrm->IsSctFrm() )
+ {
+ // the section is the first.
+ bInTab = false;
+ break;
+ }
+
+ pUpperFrm = pUpperFrm->GetUpper();
+ }
+ }
+
+ if ( bInTab && ( !IsTabFrm() || GetUpper()->IsCellFrm() ) ) // TABLE IN TABLE
+ return bFwd ? GetNextCellLeaf( eMakePage ) : GetPrevCellLeaf( eMakePage );
+
+ if ( bInSct )
+ return bFwd ? GetNextSctLeaf( eMakePage ) : GetPrevSctLeaf( eMakePage );
+ // <--
+
+ return bFwd ? GetNextLeaf( eMakePage ) : GetPrevLeaf( eMakePage );
+}
+
+
+
+sal_Bool SwFrm::WrongPageDesc( SwPageFrm* pNew )
+{
+ //Jetzt wirds leider etwas kompliziert:
+ //Ich bringe ich evtl. selbst
+ //einen Pagedesc mit; der der Folgeseite muss dann damit
+ //uebereinstimmen.
+ //Anderfalls muss ich mir etwas genauer ansehen wo der
+ //Folgepagedesc herkam.
+ //Wenn die Folgeseite selbst schon sagt, dass ihr
+ //Pagedesc nicht stimmt so kann ich das Teil bedenkenlos
+ //auswechseln.
+ //Wenn die Seite meint, dass ihr Pagedesc stimmt, so heisst
+ //das leider noch immer nicht, dass ich damit etwas anfangen
+ //kann: Wenn der erste BodyCntnt einen PageDesc oder einen
+ //PageBreak wuenscht, so muss ich ebenfalls eine neue
+ //Seite einfuegen; es sein denn die gewuenschte Seite ist
+ //die richtige.
+ //Wenn ich einen neue Seite eingefuegt habe, so fangen die
+ //Probleme leider erst an, denn wahrscheinlich wird die dann
+ //folgende Seite verkehrt gewesen und ausgewechselt worden
+ //sein. Das hat zur Folge, dass ich zwar eine neue (und
+ //jetzt richtige) Seite habe, die Bedingungen zum auswechseln
+ //aber leider noch immer stimmen.
+ //Ausweg: Vorlaeufiger Versuch, nur einmal eine neue Seite
+ //einsetzen (Leerseiten werden noetigenfalls bereits von
+ //InsertPage() eingefuegt.
+ const SwFmtPageDesc &rFmtDesc = GetAttrSet()->GetPageDesc();
+
+ //Mein Pagedesc zaehlt nicht, wenn ich ein Follow bin!
+ SwPageDesc *pDesc = 0;
+ sal_uInt16 nTmp = 0;
+ SwFlowFrm *pFlow = SwFlowFrm::CastFlowFrm( this );
+ if ( !pFlow || !pFlow->IsFollow() )
+ {
+ pDesc = (SwPageDesc*)rFmtDesc.GetPageDesc();
+ if( pDesc )
+ {
+ if( !pDesc->GetRightFmt() )
+ nTmp = 2;
+ else if( !pDesc->GetLeftFmt() )
+ nTmp = 1;
+ else if( rFmtDesc.GetNumOffset() )
+ nTmp = rFmtDesc.GetNumOffset();
+ }
+ }
+
+ //Bringt der Cntnt einen Pagedesc mit oder muss zaehlt die
+ //virtuelle Seitennummer des neuen Layoutleafs?
+ // Bei Follows zaehlt der PageDesc nicht
+ const sal_Bool bOdd = nTmp ? ( nTmp % 2 ? sal_True : sal_False )
+ : pNew->OnRightPage();
+ if ( !pDesc )
+ pDesc = pNew->FindPageDesc();
+ const SwFlowFrm *pNewFlow = pNew->FindFirstBodyCntnt();
+ // Haben wir uns selbst gefunden?
+ if( pNewFlow == pFlow )
+ pNewFlow = NULL;
+ if ( pNewFlow && pNewFlow->GetFrm()->IsInTab() )
+ pNewFlow = pNewFlow->GetFrm()->FindTabFrm();
+ const SwPageDesc *pNewDesc= ( pNewFlow && !pNewFlow->IsFollow() )
+ ? pNewFlow->GetFrm()->GetAttrSet()->GetPageDesc().GetPageDesc():0;
+
+ return ( pNew->GetPageDesc() != pDesc || // own desc ?
+ pNew->GetFmt() != (bOdd ? pDesc->GetRightFmt() : pDesc->GetLeftFmt()) ||
+ ( pNewDesc && pNewDesc == pDesc ) );
+}
+
+
+/*************************************************************************
+|*
+|* SwFrm::GetNextLeaf()
+|*
+|* Beschreibung Liefert das naechste LayoutBlatt in den das
+|* Frame gemoved werden kann.
+|*
+|*************************************************************************/
+
+SwLayoutFrm *SwFrm::GetNextLeaf( MakePageType eMakePage )
+{
+ OSL_ENSURE( !IsInFtn(), "GetNextLeaf(), don't call me for Ftn." );
+ OSL_ENSURE( !IsInSct(), "GetNextLeaf(), don't call me for Sections." );
+
+ const sal_Bool bBody = IsInDocBody(); //Wenn ich aus dem DocBody komme
+ //Will ich auch im Body landen.
+
+ // Bei Flys macht es keinen Sinn, Seiten einzufuegen, wir wollen lediglich
+ // die Verkettung absuchen.
+ if( IsInFly() )
+ eMakePage = MAKEPAGE_NONE;
+
+ //Bei Tabellen gleich den grossen Sprung wagen, ein einfaches GetNext...
+ //wuerde die erste Zellen und in der Folge alle weiteren Zellen nacheinander
+ //abklappern....
+ SwLayoutFrm *pLayLeaf = 0;
+ if ( IsTabFrm() )
+ {
+ SwCntntFrm* pTmp = ((SwTabFrm*)this)->FindLastCntnt();
+ if ( pTmp )
+ pLayLeaf = pTmp->GetUpper();
+ }
+ if ( !pLayLeaf )
+ pLayLeaf = GetNextLayoutLeaf();
+
+ SwLayoutFrm *pOldLayLeaf = 0; //Damit bei neu erzeugten Seiten
+ //nicht wieder vom Anfang gesucht
+ //wird.
+ sal_Bool bNewPg = sal_False; //nur einmal eine neue Seite einfuegen.
+
+ while ( sal_True )
+ {
+ if ( pLayLeaf )
+ {
+ //Es gibt noch einen weiteren LayoutFrm, mal sehen,
+ //ob er bereit ist mich aufzunehmen.
+ //Dazu braucht er nur von der gleichen Art wie mein Ausgangspunkt
+ //sein (DocBody bzw. Footnote.)
+ if ( pLayLeaf->FindPageFrm()->IsFtnPage() )
+ { //Wenn ich bei den Endnotenseiten angelangt bin hat sichs.
+ pLayLeaf = 0;
+ continue;
+ }
+ if ( (bBody && !pLayLeaf->IsInDocBody()) || pLayLeaf->IsInTab()
+ || pLayLeaf->IsInSct() )
+ {
+ //Er will mich nicht; neuer Versuch, neues Glueck
+ pOldLayLeaf = pLayLeaf;
+ pLayLeaf = pLayLeaf->GetNextLayoutLeaf();
+ continue;
+ }
+ //Er will mich, also ist er der gesuchte und ich bin fertig.
+ //Bei einem Seitenwechsel kann es allerdings noch sein, dass
+ //Der Seitentyp nicht der gewuenschte ist, in diesem Fall muessen
+ //wir eine Seite des richtigen Typs einfuegen.
+
+ if( !IsFlowFrm() && ( eMakePage == MAKEPAGE_NONE ||
+ eMakePage==MAKEPAGE_APPEND || eMakePage==MAKEPAGE_NOSECTION ) )
+ return pLayLeaf;
+
+ SwPageFrm *pNew = pLayLeaf->FindPageFrm();
+ const ViewShell *pSh = getRootFrm()->GetCurrShell();
+ // #111704# The pagedesc check does not make sense for frames in fly frames
+ if ( pNew != FindPageFrm() && !bNewPg && !IsInFly() &&
+ // --> FME 2005-05-10 #i46683#
+ // Do not consider page descriptions in browse mode (since
+ // MoveBwd ignored them)
+ !(pSh && pSh->GetViewOptions()->getBrowseMode() ) )
+ // <--
+ {
+ if( WrongPageDesc( pNew ) )
+ {
+ SwFtnContFrm *pCont = pNew->FindFtnCont();
+ if( pCont )
+ {
+ // Falls die Referenz der ersten Fussnote dieser Seite
+ // vor der Seite liegt, fuegen wir lieber keine neue Seite
+ // ein (Bug #55620#)
+ SwFtnFrm *pFtn = (SwFtnFrm*)pCont->Lower();
+ if( pFtn && pFtn->GetRef() )
+ {
+ const sal_uInt16 nRefNum = pNew->GetPhyPageNum();
+ if( pFtn->GetRef()->GetPhyPageNum() < nRefNum )
+ break;
+ }
+ }
+ //Erwischt, die folgende Seite ist verkehrt, also
+ //muss eine neue eingefuegt werden.
+ if ( eMakePage == MAKEPAGE_INSERT )
+ {
+ bNewPg = sal_True;
+
+ SwPageFrm *pPg = pOldLayLeaf ?
+ pOldLayLeaf->FindPageFrm() : 0;
+ if ( pPg && pPg->IsEmptyPage() )
+ //Nicht hinter, sondern vor der EmptyPage einfuegen.
+ pPg = (SwPageFrm*)pPg->GetPrev();
+
+ if ( !pPg || pPg == pNew )
+ pPg = FindPageFrm();
+
+ InsertPage( pPg, sal_False );
+ pLayLeaf = GetNextLayoutLeaf();
+ pOldLayLeaf = 0;
+ continue;
+ }
+ else
+ pLayLeaf = 0;
+ }
+ }
+ break;
+ }
+ else
+ {
+ //Es gibt keinen passenden weiteren LayoutFrm, also muss eine
+ //neue Seite her.
+ if ( eMakePage == MAKEPAGE_APPEND || eMakePage == MAKEPAGE_INSERT )
+ {
+ InsertPage(
+ pOldLayLeaf ? pOldLayLeaf->FindPageFrm() : FindPageFrm(),
+ sal_False );
+
+ //und nochmal das ganze
+ pLayLeaf = pOldLayLeaf ? pOldLayLeaf : GetNextLayoutLeaf();
+ }
+ else
+ break;
+ }
+ }
+ return pLayLeaf;
+}
+
+/*************************************************************************
+|*
+|* SwFrm::GetPrevLeaf()
+|*
+|* Beschreibung Liefert das vorhergehende LayoutBlatt in das der
+|* Frame gemoved werden kann.
+|*
+|*************************************************************************/
+
+
+SwLayoutFrm *SwFrm::GetPrevLeaf( MakePageType )
+{
+ OSL_ENSURE( !IsInFtn(), "GetPrevLeaf(), don't call me for Ftn." );
+
+ const sal_Bool bBody = IsInDocBody(); //Wenn ich aus dem DocBody komme
+ //will ich auch im Body landen.
+ const sal_Bool bFly = IsInFly();
+
+ SwLayoutFrm *pLayLeaf = GetPrevLayoutLeaf();
+ SwLayoutFrm *pPrevLeaf = 0;
+
+ while ( pLayLeaf )
+ {
+ if ( pLayLeaf->IsInTab() || //In Tabellen geht's niemals hinein.
+ pLayLeaf->IsInSct() ) //In Bereiche natuerlich auch nicht!
+ pLayLeaf = pLayLeaf->GetPrevLayoutLeaf();
+ else if ( bBody && pLayLeaf->IsInDocBody() )
+ {
+ if ( pLayLeaf->Lower() )
+ break;
+ pPrevLeaf = pLayLeaf;
+ pLayLeaf = pLayLeaf->GetPrevLayoutLeaf();
+ if ( pLayLeaf )
+ SwFlowFrm::SetMoveBwdJump( sal_True );
+ }
+ else if ( bFly )
+ break; //Cntnts in Flys sollte jedes Layout-Blatt recht sein.
+ else
+ pLayLeaf = pLayLeaf->GetPrevLayoutLeaf();
+ }
+ return pLayLeaf ? pLayLeaf : pPrevLeaf;
+}
+
+/*************************************************************************
+|*
+|* SwFlowFrm::IsPrevObjMove()
+|*
+|*************************************************************************/
+
+
+sal_Bool SwFlowFrm::IsPrevObjMove() const
+{
+ //sal_True der FlowFrm soll auf einen Rahmen des Vorgaengers Ruecksicht nehmen
+ // und fuer diesen ggf. Umbrechen.
+
+ //!!!!!!!!!!!Hack!!!!!!!!!!!
+ const ViewShell *pSh = rThis.getRootFrm()->GetCurrShell();
+ if( pSh && pSh->GetViewOptions()->getBrowseMode() )
+ return sal_False;
+
+ SwFrm *pPre = rThis.FindPrev();
+
+ if ( pPre && pPre->GetDrawObjs() )
+ {
+ OSL_ENSURE( SwFlowFrm::CastFlowFrm( pPre ), "new flowfrm?" );
+ if( SwFlowFrm::CastFlowFrm( pPre )->IsAnFollow( this ) )
+ return sal_False;
+ SwLayoutFrm* pPreUp = pPre->GetUpper();
+ // Wenn der Upper ein SectionFrm oder die Spalte eines SectionFrms ist,
+ // duerfen wir aus diesem durchaus heraushaengen,
+ // es muss stattdessen der Upper des SectionFrms beruecksichtigt werden.
+ if( pPreUp->IsInSct() )
+ {
+ if( pPreUp->IsSctFrm() )
+ pPreUp = pPreUp->GetUpper();
+ else if( pPreUp->IsColBodyFrm() &&
+ pPreUp->GetUpper()->GetUpper()->IsSctFrm() )
+ pPreUp = pPreUp->GetUpper()->GetUpper()->GetUpper();
+ }
+ // --> OD 2004-10-15 #i26945# - re-factoring:
+ // use <GetVertPosOrientFrm()> to determine, if object has followed the
+ // text flow to the next layout frame
+ for ( sal_uInt16 i = 0; i < pPre->GetDrawObjs()->Count(); ++i )
+ {
+ // --> OD 2004-07-01 #i28701# - consider changed type of
+ // <SwSortedObjs> entries.
+ const SwAnchoredObject* pObj = (*pPre->GetDrawObjs())[i];
+ // OD 2004-01-20 #110582# - do not consider hidden objects
+ // --> OD 2004-10-15 #i26945# - do not consider object, which
+ // doesn't follow the text flow.
+ if ( pObj->GetFrmFmt().GetDoc()->IsVisibleLayerId(
+ pObj->GetDrawObj()->GetLayer() ) &&
+ pObj->GetFrmFmt().GetFollowTextFlow().GetValue() )
+ // <--
+ {
+ const SwLayoutFrm* pVertPosOrientFrm = pObj->GetVertPosOrientFrm();
+ if ( pVertPosOrientFrm &&
+ pPreUp != pVertPosOrientFrm &&
+ !pPreUp->IsAnLower( pVertPosOrientFrm ) )
+ {
+ return sal_True;
+ }
+ }
+ }
+ // <--
+ }
+ return sal_False;
+}
+
+/*************************************************************************
+|*
+|* sal_Bool SwFlowFrm::IsPageBreak()
+|*
+|* Beschreibung Wenn vor dem Frm ein harter Seitenumbruch steht UND
+|* es einen Vorgaenger auf der gleichen Seite gibt, wird sal_True
+|* zurueckgeliefert (es muss ein PageBreak erzeugt werden) sal_False sonst.
+|* Wenn in bAct sal_True uebergeben wird, gibt die Funktion dann sal_True
+|* zurueck, wenn ein PageBreak besteht.
+|* Fuer Follows wird der harte Seitenumbruch natuerlich nicht
+|* ausgewertet.
+|* Der Seitenumbruch steht im eigenen FrmFmt (BEFORE) oder im FrmFmt
+|* des Vorgaengers (AFTER). Wenn es keinen Vorgaenger auf der Seite
+|* gibt ist jede weitere Ueberlegung ueberfluessig.
+|* Ein Seitenumbruch (oder der Bedarf) liegt auch dann vor, wenn
+|* im FrmFmt ein PageDesc angegeben wird.
+|* Die Implementierung arbeitet zuaechst nur auf CntntFrms!
+|* -->Fuer LayoutFrms ist die Definition des Vorgaengers unklar.
+|*
+|*************************************************************************/
+
+
+sal_Bool SwFlowFrm::IsPageBreak( sal_Bool bAct ) const
+{
+ if ( !IsFollow() && rThis.IsInDocBody() &&
+ ( !rThis.IsInTab() || ( rThis.IsTabFrm() && !rThis.GetUpper()->IsInTab() ) ) ) // i66968
+ {
+ const ViewShell *pSh = rThis.getRootFrm()->GetCurrShell();
+ if( pSh && pSh->GetViewOptions()->getBrowseMode() )
+ return sal_False;
+ const SwAttrSet *pSet = rThis.GetAttrSet();
+
+ //Vorgaenger ermitteln
+ const SwFrm *pPrev = rThis.FindPrev();
+ while ( pPrev && ( !pPrev->IsInDocBody() ||
+ ( pPrev->IsTxtFrm() && ((SwTxtFrm*)pPrev)->IsHiddenNow() ) ) )
+ pPrev = pPrev->FindPrev();
+
+ if ( pPrev )
+ {
+ OSL_ENSURE( pPrev->IsInDocBody(), "IsPageBreak: Not in DocBody?" );
+ if ( bAct )
+ { if ( rThis.FindPageFrm() == pPrev->FindPageFrm() )
+ return sal_False;
+ }
+ else
+ { if ( rThis.FindPageFrm() != pPrev->FindPageFrm() )
+ return sal_False;
+ }
+
+ const SvxBreak eBreak = pSet->GetBreak().GetBreak();
+ if ( eBreak == SVX_BREAK_PAGE_BEFORE || eBreak == SVX_BREAK_PAGE_BOTH )
+ return sal_True;
+ else
+ {
+ const SvxBreak &ePrB = pPrev->GetAttrSet()->GetBreak().GetBreak();
+ if ( ePrB == SVX_BREAK_PAGE_AFTER ||
+ ePrB == SVX_BREAK_PAGE_BOTH ||
+ pSet->GetPageDesc().GetPageDesc() )
+ return sal_True;
+ }
+ }
+ }
+ return sal_False;
+}
+
+/*************************************************************************
+|*
+|* sal_Bool SwFlowFrm::IsColBreak()
+|*
+|* Beschreibung Wenn vor dem Frm ein harter Spaltenumbruch steht UND
+|* es einen Vorgaenger in der gleichen Spalte gibt, wird sal_True
+|* zurueckgeliefert (es muss ein PageBreak erzeugt werden) sal_False sonst.
+|* Wenn in bAct sal_True uebergeben wird, gibt die Funktion dann sal_True
+|* zurueck, wenn ein ColBreak besteht.
+|* Fuer Follows wird der harte Spaltenumbruch natuerlich nicht
+|* ausgewertet.
+|* Der Spaltenumbruch steht im eigenen FrmFmt (BEFORE) oder im FrmFmt
+|* des Vorgaengers (AFTER). Wenn es keinen Vorgaenger in der Spalte
+|* gibt ist jede weitere Ueberlegung ueberfluessig.
+|* Die Implementierung arbeitet zuaechst nur auf CntntFrms!
+|* -->Fuer LayoutFrms ist die Definition des Vorgaengers unklar.
+|*
+|*************************************************************************/
+
+sal_Bool SwFlowFrm::IsColBreak( sal_Bool bAct ) const
+{
+ if ( !IsFollow() && (rThis.IsMoveable() || bAct) )
+ {
+ const SwFrm *pCol = rThis.FindColFrm();
+ if ( pCol )
+ {
+ //Vorgaenger ermitteln
+ const SwFrm *pPrev = rThis.FindPrev();
+ while( pPrev && ( ( !pPrev->IsInDocBody() && !rThis.IsInFly() ) ||
+ ( pPrev->IsTxtFrm() && ((SwTxtFrm*)pPrev)->IsHiddenNow() ) ) )
+ pPrev = pPrev->FindPrev();
+
+ if ( pPrev )
+ {
+ if ( bAct )
+ { if ( pCol == pPrev->FindColFrm() )
+ return sal_False;
+ }
+ else
+ { if ( pCol != pPrev->FindColFrm() )
+ return sal_False;
+ }
+
+ const SvxBreak eBreak = rThis.GetAttrSet()->GetBreak().GetBreak();
+ if ( eBreak == SVX_BREAK_COLUMN_BEFORE ||
+ eBreak == SVX_BREAK_COLUMN_BOTH )
+ return sal_True;
+ else
+ {
+ const SvxBreak &ePrB = pPrev->GetAttrSet()->GetBreak().GetBreak();
+ if ( ePrB == SVX_BREAK_COLUMN_AFTER ||
+ ePrB == SVX_BREAK_COLUMN_BOTH )
+ return sal_True;
+ }
+ }
+ }
+ }
+ return sal_False;
+}
+
+sal_Bool SwFlowFrm::HasParaSpaceAtPages( sal_Bool bSct ) const
+{
+ if( rThis.IsInSct() )
+ {
+ const SwFrm* pTmp = rThis.GetUpper();
+ while( pTmp )
+ {
+ if( pTmp->IsCellFrm() || pTmp->IsFlyFrm() ||
+ pTmp->IsFooterFrm() || pTmp->IsHeaderFrm() ||
+ ( pTmp->IsFtnFrm() && !((SwFtnFrm*)pTmp)->GetMaster() ) )
+ return sal_True;
+ if( pTmp->IsPageFrm() )
+ return ( pTmp->GetPrev() && !IsPageBreak(sal_True) ) ? sal_False : sal_True;
+ if( pTmp->IsColumnFrm() && pTmp->GetPrev() )
+ return IsColBreak( sal_True );
+ if( pTmp->IsSctFrm() && ( !bSct || pTmp->GetPrev() ) )
+ return sal_False;
+ pTmp = pTmp->GetUpper();
+ }
+ OSL_FAIL( "HasParaSpaceAtPages: Where's my page?" );
+ return sal_False;
+ }
+ if( !rThis.IsInDocBody() || ( rThis.IsInTab() && !rThis.IsTabFrm()) ||
+ IsPageBreak( sal_True ) || ( rThis.FindColFrm() && IsColBreak( sal_True ) ) )
+ return sal_True;
+ const SwFrm* pTmp = rThis.FindColFrm();
+ if( pTmp )
+ {
+ if( pTmp->GetPrev() )
+ return sal_False;
+ }
+ else
+ pTmp = &rThis;
+ pTmp = pTmp->FindPageFrm();
+ return pTmp && !pTmp->GetPrev();
+}
+
+/** helper method to determine previous frame for calculation of the
+ upper space
+
+ OD 2004-03-10 #i11860#
+
+ @author OD
+*/
+const SwFrm* SwFlowFrm::_GetPrevFrmForUpperSpaceCalc( const SwFrm* _pProposedPrevFrm ) const
+{
+ const SwFrm* pPrevFrm = _pProposedPrevFrm
+ ? _pProposedPrevFrm
+ : rThis.GetPrev();
+
+ // Skip hidden paragraphs and empty sections
+ while ( pPrevFrm &&
+ ( ( pPrevFrm->IsTxtFrm() &&
+ static_cast<const SwTxtFrm*>(pPrevFrm)->IsHiddenNow() ) ||
+ ( pPrevFrm->IsSctFrm() &&
+ !static_cast<const SwSectionFrm*>(pPrevFrm)->GetSection() ) ) )
+ {
+ pPrevFrm = pPrevFrm->GetPrev();
+ }
+
+ // Special case: no direct previous frame is found but frame is in footnote
+ // Search for a previous frame in previous footnote,
+ // if frame isn't in a section, which is also in the footnote
+ if ( !pPrevFrm && rThis.IsInFtn() &&
+ ( rThis.IsSctFrm() ||
+ !rThis.IsInSct() || !rThis.FindSctFrm()->IsInFtn() ) )
+ {
+ const SwFtnFrm* pPrevFtnFrm =
+ static_cast<const SwFtnFrm*>(rThis.FindFtnFrm()->GetPrev());
+ if ( pPrevFtnFrm )
+ {
+ pPrevFrm = pPrevFtnFrm->GetLastLower();
+
+ // Skip hidden paragraphs and empty sections
+ while ( pPrevFrm &&
+ ( ( pPrevFrm->IsTxtFrm() &&
+ static_cast<const SwTxtFrm*>(pPrevFrm)->IsHiddenNow() ) ||
+ ( pPrevFrm->IsSctFrm() &&
+ !static_cast<const SwSectionFrm*>(pPrevFrm)->GetSection() ) ) )
+ {
+ pPrevFrm = pPrevFrm->GetPrev();
+ }
+ }
+ }
+ // Special case: found previous frame is a section
+ // Search for the last content in the section
+ if( pPrevFrm && pPrevFrm->IsSctFrm() )
+ {
+ const SwSectionFrm* pPrevSectFrm =
+ static_cast<const SwSectionFrm*>(pPrevFrm);
+ pPrevFrm = pPrevSectFrm->FindLastCntnt();
+ // If the last content is in a table _inside_ the section,
+ // take the table herself.
+ // OD 2004-02-18 #106629# - correction:
+ // Check directly, if table is inside table, instead of indirectly
+ // by checking, if section isn't inside a table
+ if ( pPrevFrm && pPrevFrm->IsInTab() )
+ {
+ const SwTabFrm* pTableFrm = pPrevFrm->FindTabFrm();
+ if ( pPrevSectFrm->IsAnLower( pTableFrm ) )
+ {
+ pPrevFrm = pTableFrm;
+ }
+ }
+ // OD 2004-02-18 #106629# correction: skip hidden text frames
+ while ( pPrevFrm &&
+ pPrevFrm->IsTxtFrm() &&
+ static_cast<const SwTxtFrm*>(pPrevFrm)->IsHiddenNow() )
+ {
+ pPrevFrm = pPrevFrm->GetPrev();
+ }
+ }
+
+ return pPrevFrm;
+}
+
+// OD 2004-03-12 #i11860# - add 3rd parameter <_bConsiderGrid>
+SwTwips SwFlowFrm::CalcUpperSpace( const SwBorderAttrs *pAttrs,
+ const SwFrm* pPr,
+ const bool _bConsiderGrid ) const
+{
+ // OD 2004-03-10 #i11860# - use new method <GetPrevFrmForUpperSpaceCalc(..)>
+ const SwFrm* pPrevFrm = _GetPrevFrmForUpperSpaceCalc( pPr );
+
+ SwBorderAttrAccess *pAccess;
+ SwFrm* pOwn;
+ if( !pAttrs )
+ {
+ if( rThis.IsSctFrm() )
+ {
+ SwSectionFrm* pFoll = &((SwSectionFrm&)rThis);
+ do
+ pOwn = pFoll->ContainsAny();
+ while( !pOwn && 0 != ( pFoll = pFoll->GetFollow() ) );
+ if( !pOwn )
+ return 0;
+ }
+ else
+ pOwn = &rThis;
+ pAccess= new SwBorderAttrAccess( SwFrm::GetCache(), pOwn );
+ pAttrs = pAccess->Get();
+ }
+ else
+ {
+ pAccess = NULL;
+ pOwn = &rThis;
+ }
+ SwTwips nUpper = 0;
+ // OD 06.01.2004 #i11859#
+ {
+ const IDocumentSettingAccess* pIDSA = rThis.GetUpper()->GetFmt()->getIDocumentSettingAccess();
+ const bool bUseFormerLineSpacing = pIDSA->get(IDocumentSettingAccess::OLD_LINE_SPACING);
+ if( pPrevFrm )
+ {
+ // OD 2004-03-10 #i11860# - use new method to determine needed spacing
+ // values of found previous frame and use these values.
+ SwTwips nPrevLowerSpace = 0;
+ SwTwips nPrevLineSpacing = 0;
+ // --> OD 2009-08-28 #i102458#
+ bool bPrevLineSpacingPorportional = false;
+ GetSpacingValuesOfFrm( (*pPrevFrm),
+ nPrevLowerSpace, nPrevLineSpacing,
+ bPrevLineSpacingPorportional );
+ // <--
+ if( pIDSA->get(IDocumentSettingAccess::PARA_SPACE_MAX) )
+ {
+ nUpper = nPrevLowerSpace + pAttrs->GetULSpace().GetUpper();
+ SwTwips nAdd = nPrevLineSpacing;
+ // OD 07.01.2004 #i11859# - consideration of the line spacing
+ // for the upper spacing of a text frame
+ if ( bUseFormerLineSpacing )
+ {
+ // former consideration
+ if ( pOwn->IsTxtFrm() )
+ {
+ nAdd = Max( nAdd, static_cast<SwTxtFrm&>(rThis).GetLineSpace() );
+ }
+ nUpper += nAdd;
+ }
+ else
+ {
+ // new consideration:
+ // Only the proportional line spacing of the previous
+ // text frame is considered for the upper spacing and
+ // the line spacing values are add up instead of
+ // building its maximum.
+ if ( pOwn->IsTxtFrm() )
+ {
+ // --> OD 2009-08-28 #i102458#
+ // Correction:
+ // A proportional line spacing of the previous text frame
+ // is added up to a own leading line spacing.
+ // Otherwise, the maximum of the leading line spacing
+ // of the previous text frame and the own leading line
+ // spacing is built.
+ if ( bPrevLineSpacingPorportional )
+ {
+ nAdd += static_cast<SwTxtFrm&>(rThis).GetLineSpace( true );
+ }
+ else
+ {
+ nAdd = Max( nAdd, static_cast<SwTxtFrm&>(rThis).GetLineSpace( true ) );
+ }
+ // <--
+ }
+ nUpper += nAdd;
+ }
+ }
+ else
+ {
+ nUpper = Max( static_cast<long>(nPrevLowerSpace),
+ static_cast<long>(pAttrs->GetULSpace().GetUpper()) );
+ // OD 07.01.2004 #i11859# - consideration of the line spacing
+ // for the upper spacing of a text frame
+ if ( bUseFormerLineSpacing )
+ {
+ // former consideration
+ if ( pOwn->IsTxtFrm() )
+ nUpper = Max( nUpper, ((SwTxtFrm*)pOwn)->GetLineSpace() );
+ if ( nPrevLineSpacing != 0 )
+ {
+ nUpper = Max( nUpper, nPrevLineSpacing );
+ }
+ }
+ else
+ {
+ // new consideration:
+ // Only the proportional line spacing of the previous
+ // text frame is considered for the upper spacing and
+ // the line spacing values are add up and added to
+ // the paragraph spacing instead of building the
+ // maximum of the line spacings and the paragraph spacing.
+ SwTwips nAdd = nPrevLineSpacing;
+ if ( pOwn->IsTxtFrm() )
+ {
+ // --> OD 2009-08-28 #i102458#
+ // Correction:
+ // A proportional line spacing of the previous text frame
+ // is added up to a own leading line spacing.
+ // Otherwise, the maximum of the leading line spacing
+ // of the previous text frame and the own leading line
+ // spacing is built.
+ if ( bPrevLineSpacingPorportional )
+ {
+ nAdd += static_cast<SwTxtFrm&>(rThis).GetLineSpace( true );
+ }
+ else
+ {
+ nAdd = Max( nAdd, static_cast<SwTxtFrm&>(rThis).GetLineSpace( true ) );
+ }
+ // <--
+ }
+ nUpper += nAdd;
+ }
+ }
+ }
+ else if ( pIDSA->get(IDocumentSettingAccess::PARA_SPACE_MAX_AT_PAGES) &&
+ CastFlowFrm( pOwn )->HasParaSpaceAtPages( rThis.IsSctFrm() ) )
+ {
+ nUpper = pAttrs->GetULSpace().GetUpper();
+ }
+ }
+
+ // OD 2004-02-26 #i25029# - pass previous frame <pPrevFrm>
+ // to method <GetTopLine(..)>, if parameter <pPr> is set.
+ // Note: parameter <pPr> is set, if method is called from <SwTxtFrm::WouldFit(..)>
+ nUpper += pAttrs->GetTopLine( rThis, (pPr ? pPrevFrm : 0L) );
+
+ // OD 2004-03-12 #i11860# - consider value of new parameter <_bConsiderGrid>
+ // and use new method <GetUpperSpaceAmountConsideredForPageGrid(..)>
+
+ //consider grid in square page mode
+ if ( _bConsiderGrid && rThis.GetUpper()->GetFmt()->GetDoc()->IsSquaredPageMode() )
+ {
+ nUpper += _GetUpperSpaceAmountConsideredForPageGrid( nUpper );
+ }
+
+ delete pAccess;
+ return nUpper;
+}
+
+/** method to detemine the upper space amount, which is considered for
+ the page grid
+
+ OD 2004-03-12 #i11860#
+ Precondition: Position of frame is valid.
+
+ @author OD
+*/
+SwTwips SwFlowFrm::_GetUpperSpaceAmountConsideredForPageGrid(
+ const SwTwips _nUpperSpaceWithoutGrid ) const
+{
+ SwTwips nUpperSpaceAmountConsideredForPageGrid = 0;
+
+ if ( rThis.IsInDocBody() && rThis.GetAttrSet()->GetParaGrid().GetValue() )
+ {
+ const SwPageFrm* pPageFrm = rThis.FindPageFrm();
+ GETGRID( pPageFrm )
+ if( pGrid )
+ {
+ const SwFrm* pBodyFrm = pPageFrm->FindBodyCont();
+ if ( pBodyFrm )
+ {
+ const long nGridLineHeight =
+ pGrid->GetBaseHeight() + pGrid->GetRubyHeight();
+
+ SWRECTFN( (&rThis) )
+ const SwTwips nBodyPrtTop = (pBodyFrm->*fnRect->fnGetPrtTop)();
+ const SwTwips nProposedPrtTop =
+ (*fnRect->fnYInc)( (rThis.Frm().*fnRect->fnGetTop)(),
+ _nUpperSpaceWithoutGrid );
+
+ const SwTwips nSpaceAbovePrtTop =
+ (*fnRect->fnYDiff)( nProposedPrtTop, nBodyPrtTop );
+ const SwTwips nSpaceOfCompleteLinesAbove =
+ nGridLineHeight * ( nSpaceAbovePrtTop / nGridLineHeight );
+ SwTwips nNewPrtTop =
+ (*fnRect->fnYInc)( nBodyPrtTop, nSpaceOfCompleteLinesAbove );
+ if ( (*fnRect->fnYDiff)( nProposedPrtTop, nNewPrtTop ) > 0 )
+ {
+ nNewPrtTop = (*fnRect->fnYInc)( nNewPrtTop, nGridLineHeight );
+ }
+
+ const SwTwips nNewUpperSpace =
+ (*fnRect->fnYDiff)( nNewPrtTop,
+ (rThis.Frm().*fnRect->fnGetTop)() );
+
+ nUpperSpaceAmountConsideredForPageGrid =
+ nNewUpperSpace - _nUpperSpaceWithoutGrid;
+
+ OSL_ENSURE( nUpperSpaceAmountConsideredForPageGrid >= 0,
+ "<SwFlowFrm::GetUpperSpaceAmountConsideredForPageGrid(..)> - negative space considered for page grid!" );
+ }
+ }
+ }
+ return nUpperSpaceAmountConsideredForPageGrid;
+}
+
+/** method to determent the upper space amount, which is considered for
+ the previous frame
+
+ OD 2004-03-11 #i11860#
+
+ @author OD
+*/
+SwTwips SwFlowFrm::_GetUpperSpaceAmountConsideredForPrevFrm() const
+{
+ SwTwips nUpperSpaceAmountOfPrevFrm = 0;
+
+ const SwFrm* pPrevFrm = _GetPrevFrmForUpperSpaceCalc();
+ if ( pPrevFrm )
+ {
+ SwTwips nPrevLowerSpace = 0;
+ SwTwips nPrevLineSpacing = 0;
+ // --> OD 2009-08-28 #i102458#
+ bool bDummy = false;
+ GetSpacingValuesOfFrm( (*pPrevFrm), nPrevLowerSpace, nPrevLineSpacing, bDummy );
+ // <--
+ if ( nPrevLowerSpace > 0 || nPrevLineSpacing > 0 )
+ {
+ const IDocumentSettingAccess* pIDSA = rThis.GetUpper()->GetFmt()->getIDocumentSettingAccess();
+ if ( pIDSA->get(IDocumentSettingAccess::PARA_SPACE_MAX) ||
+ !pIDSA->get(IDocumentSettingAccess::OLD_LINE_SPACING) )
+ {
+ nUpperSpaceAmountOfPrevFrm = nPrevLowerSpace + nPrevLineSpacing;
+ }
+ else
+ {
+ nUpperSpaceAmountOfPrevFrm = Max( nPrevLowerSpace, nPrevLineSpacing );
+ }
+ }
+ }
+
+ return nUpperSpaceAmountOfPrevFrm;
+}
+
+/** method to determine the upper space amount, which is considered for
+ the previous frame and the page grid, if option 'Use former object
+ positioning' is OFF
+
+ OD 2004-03-18 #i11860#
+
+ @author OD
+*/
+SwTwips SwFlowFrm::GetUpperSpaceAmountConsideredForPrevFrmAndPageGrid() const
+{
+ SwTwips nUpperSpaceAmountConsideredForPrevFrmAndPageGrid = 0;
+
+ if ( !rThis.GetUpper()->GetFmt()->getIDocumentSettingAccess()->get(IDocumentSettingAccess::USE_FORMER_OBJECT_POS) )
+ {
+ nUpperSpaceAmountConsideredForPrevFrmAndPageGrid =
+ _GetUpperSpaceAmountConsideredForPrevFrm() +
+ _GetUpperSpaceAmountConsideredForPageGrid( CalcUpperSpace( 0L, 0L, false ) );
+ }
+
+ return nUpperSpaceAmountConsideredForPrevFrmAndPageGrid;
+}
+
+/** calculation of lower space
+
+ OD 2004-03-02 #106629#
+
+ @author OD
+*/
+SwTwips SwFlowFrm::CalcLowerSpace( const SwBorderAttrs* _pAttrs ) const
+{
+ SwTwips nLowerSpace = 0;
+
+ SwBorderAttrAccess* pAttrAccess = 0L;
+ if ( !_pAttrs )
+ {
+ pAttrAccess = new SwBorderAttrAccess( SwFrm::GetCache(), &rThis );
+ _pAttrs = pAttrAccess->Get();
+ }
+
+ sal_Bool bCommonBorder = sal_True;
+ if ( rThis.IsInSct() && rThis.GetUpper()->IsColBodyFrm() )
+ {
+ const SwSectionFrm* pSectFrm = rThis.FindSctFrm();
+ bCommonBorder = pSectFrm->GetFmt()->GetBalancedColumns().GetValue();
+ }
+ nLowerSpace = bCommonBorder ?
+ _pAttrs->GetBottomLine( rThis ) :
+ _pAttrs->CalcBottomLine();
+
+ // --> OD 2004-07-16 #i26250#
+ // - correct consideration of table frames
+ // - use new method <CalcAddLowerSpaceAsLastInTableCell(..)>
+ if ( ( ( rThis.IsTabFrm() && rThis.GetUpper()->IsInTab() ) ||
+ // --> OD 2004-11-16 #115759# - no lower spacing, if frame has a follow
+ ( rThis.IsInTab() && !GetFollow() ) ) &&
+ // <--
+ !rThis.GetIndNext() )
+ {
+ nLowerSpace += CalcAddLowerSpaceAsLastInTableCell( _pAttrs );
+ }
+ // <--
+
+ delete pAttrAccess;
+
+ return nLowerSpace;
+}
+
+/** calculation of the additional space to be considered, if flow frame
+ is the last inside a table cell
+
+ OD 2004-07-16 #i26250#
+
+ @author OD
+*/
+SwTwips SwFlowFrm::CalcAddLowerSpaceAsLastInTableCell(
+ const SwBorderAttrs* _pAttrs ) const
+{
+ SwTwips nAdditionalLowerSpace = 0;
+
+ if ( rThis.GetUpper()->GetFmt()->getIDocumentSettingAccess()->get(IDocumentSettingAccess::ADD_PARA_SPACING_TO_TABLE_CELLS) )
+ {
+ const SwFrm* pFrm = &rThis;
+ if ( pFrm->IsSctFrm() )
+ {
+ const SwSectionFrm* pSectFrm = static_cast<const SwSectionFrm*>(pFrm);
+ pFrm = pSectFrm->FindLastCntnt();
+ if ( pFrm && pFrm->IsInTab() )
+ {
+ const SwTabFrm* pTableFrm = pFrm->FindTabFrm();
+ if ( pSectFrm->IsAnLower( pTableFrm ) )
+ {
+ pFrm = pTableFrm;
+ }
+ }
+ }
+
+ SwBorderAttrAccess* pAttrAccess = 0L;
+ if ( !_pAttrs || pFrm != &rThis )
+ {
+ pAttrAccess = new SwBorderAttrAccess( SwFrm::GetCache(), pFrm );
+ _pAttrs = pAttrAccess->Get();
+ }
+
+ nAdditionalLowerSpace += _pAttrs->GetULSpace().GetLower();
+
+ delete pAttrAccess;
+ }
+
+ return nAdditionalLowerSpace;
+}
+
+/*************************************************************************
+|*
+|* sal_Bool SwFlowFrm::CheckMoveFwd()
+|*
+|* Beschreibung Moved den Frm vorwaerts wenn es durch die aktuellen
+|* Bedingungen und Attribute notwendig erscheint.
+|*
+|*************************************************************************/
+
+
+sal_Bool SwFlowFrm::CheckMoveFwd( sal_Bool &rbMakePage, sal_Bool bKeep, sal_Bool )
+{
+ const SwFrm* pNxt = rThis.GetIndNext();
+
+ if ( bKeep && //!bMovedBwd &&
+ ( !pNxt || ( pNxt->IsTxtFrm() && ((SwTxtFrm*)pNxt)->IsEmptyMaster() ) ) &&
+ ( 0 != (pNxt = rThis.FindNext()) ) && IsKeepFwdMoveAllowed() )
+ {
+ if( pNxt->IsSctFrm() )
+ { // Nicht auf leere SectionFrms hereinfallen
+ const SwFrm* pTmp = NULL;
+ while( pNxt && pNxt->IsSctFrm() &&
+ ( !((SwSectionFrm*)pNxt)->GetSection() ||
+ 0 == ( pTmp = ((SwSectionFrm*)pNxt)->ContainsAny() ) ) )
+ {
+ pNxt = pNxt->FindNext();
+ pTmp = NULL;
+ }
+ if( pTmp )
+ pNxt = pTmp; // the content of the next notempty sectionfrm
+ }
+ if( pNxt && pNxt->GetValidPosFlag() )
+ {
+ sal_Bool bMove = sal_False;
+ const SwSectionFrm *pSct = rThis.FindSctFrm();
+ if( pSct && !pSct->GetValidSizeFlag() )
+ {
+ const SwSectionFrm* pNxtSct = pNxt->FindSctFrm();
+ if( pNxtSct && pSct->IsAnFollow( pNxtSct ) )
+ bMove = sal_True;
+ }
+ else
+ bMove = sal_True;
+ if( bMove )
+ {
+ //Keep together with the following frame
+ MoveFwd( rbMakePage, sal_False );
+ return sal_True;
+ }
+ }
+ }
+
+ sal_Bool bMovedFwd = sal_False;
+
+ if ( rThis.GetIndPrev() )
+ {
+ if ( IsPrevObjMove() ) //Auf Objekte des Prev Ruecksicht nehmen?
+ {
+ bMovedFwd = sal_True;
+ if ( !MoveFwd( rbMakePage, sal_False ) )
+ rbMakePage = sal_False;
+ }
+ else
+ {
+ if ( IsPageBreak( sal_False ) )
+ {
+ while ( MoveFwd( rbMakePage, sal_True ) )
+ /* do nothing */;
+ rbMakePage = sal_False;
+ bMovedFwd = sal_True;
+ }
+ else if ( IsColBreak ( sal_False ) )
+ {
+ const SwPageFrm *pPage = rThis.FindPageFrm();
+ SwFrm *pCol = rThis.FindColFrm();
+ do
+ { MoveFwd( rbMakePage, sal_False );
+ SwFrm *pTmp = rThis.FindColFrm();
+ if( pTmp != pCol )
+ {
+ bMovedFwd = sal_True;
+ pCol = pTmp;
+ }
+ else
+ break;
+ } while ( IsColBreak( sal_False ) );
+ if ( pPage != rThis.FindPageFrm() )
+ rbMakePage = sal_False;
+ }
+ }
+ }
+ return bMovedFwd;
+}
+
+/*************************************************************************
+|*
+|* sal_Bool SwFlowFrm::MoveFwd()
+|*
+|* Beschreibung Returnwert sagt, ob der Frm die Seite gewechselt hat.
+|*
+|*************************************************************************/
+
+
+sal_Bool SwFlowFrm::MoveFwd( sal_Bool bMakePage, sal_Bool bPageBreak, sal_Bool bMoveAlways )
+{
+//!!!!MoveFtnCntFwd muss ggf. mitgepflegt werden.
+ SwFtnBossFrm *pOldBoss = rThis.FindFtnBossFrm();
+ if ( rThis.IsInFtn() )
+ return ((SwCntntFrm&)rThis).MoveFtnCntFwd( bMakePage, pOldBoss );
+
+ if( !IsFwdMoveAllowed() && !bMoveAlways )
+ {
+ sal_Bool bNoFwd = sal_True;
+ if( rThis.IsInSct() )
+ {
+ SwFtnBossFrm* pBoss = rThis.FindFtnBossFrm();
+ bNoFwd = !pBoss->IsInSct() || ( !pBoss->Lower()->GetNext() &&
+ !pBoss->GetPrev() );
+ }
+
+ // Allow the MoveFwd even if we do not have an IndPrev in these cases:
+ if ( rThis.IsInTab() &&
+ ( !rThis.IsTabFrm() ||
+ ( rThis.GetUpper()->IsInTab() &&
+ rThis.GetUpper()->FindTabFrm()->IsFwdMoveAllowed() ) ) &&
+ 0 != const_cast<SwFrm&>(rThis).GetNextCellLeaf( MAKEPAGE_NONE ) )
+ {
+ bNoFwd = sal_False;
+ }
+
+ if( bNoFwd )
+ {
+ //Fuer PageBreak ist das Moven erlaubt, wenn der Frm nicht
+ //bereits der erste der Seite ist.
+ if ( !bPageBreak )
+ return sal_False;
+
+ const SwFrm *pCol = rThis.FindColFrm();
+ if ( !pCol || !pCol->GetPrev() )
+ return sal_False;
+ }
+ }
+
+ sal_Bool bSamePage = sal_True;
+ SwLayoutFrm *pNewUpper =
+ rThis.GetLeaf( bMakePage ? MAKEPAGE_INSERT : MAKEPAGE_NONE, sal_True );
+
+ if ( pNewUpper )
+ {
+ PROTOCOL_ENTER( &rThis, PROT_MOVE_FWD, 0, 0 );
+ SwPageFrm *pOldPage = pOldBoss->FindPageFrm();
+ //Wir moven uns und alle direkten Nachfolger vor den ersten
+ //CntntFrm unterhalb des neuen Uppers.
+
+ // Wenn unser NewUpper in einem SectionFrm liegt, muessen wir
+ // verhindern, dass sich dieser im Calc selbst zerstoert
+ SwSectionFrm* pSect = pNewUpper->FindSctFrm();
+ sal_Bool bUnlock = sal_False;
+ if( pSect )
+ {
+ // Wenn wir nur innerhalb unseres SectionFrms die Spalte wechseln,
+ // rufen wir lieber kein Calc, sonst wird noch der SectionFrm
+ // formatiert, der wiederum uns ruft etc.
+ if( pSect != rThis.FindSctFrm() )
+ {
+ bUnlock = !pSect->IsColLocked();
+ pSect->ColLock();
+ pNewUpper->Calc();
+ if( bUnlock )
+ pSect->ColUnlock();
+ }
+ }
+ // Do not calculate split cell frames.
+ else if ( !pNewUpper->IsCellFrm() || ((SwLayoutFrm*)pNewUpper)->Lower() )
+ pNewUpper->Calc();
+
+ SwFtnBossFrm *pNewBoss = pNewUpper->FindFtnBossFrm();
+ sal_Bool bBossChg = pNewBoss != pOldBoss;
+ pNewBoss = pNewBoss->FindFtnBossFrm( sal_True );
+ pOldBoss = pOldBoss->FindFtnBossFrm( sal_True );
+ SwPageFrm* pNewPage = pOldPage;
+
+ // First, we move the footnotes.
+ sal_Bool bFtnMoved = sal_False;
+
+ // --> FME 2004-07-15 #i26831#
+ // If pSect has just been created, the printing area of pSect has
+ // been calculated based on the first content of its follow.
+ // In this case we prefer to call a SimpleFormat for this new
+ // section after we inserted the contents. Otherwise the section
+ // frame will invalidate its lowers, if its printing area changes
+ // in SwSectionFrm::Format, which can cause loops.
+ const bool bForceSimpleFormat = pSect && pSect->HasFollow() &&
+ !pSect->ContainsAny();
+ // <--
+
+ if ( pNewBoss != pOldBoss )
+ {
+ pNewPage = pNewBoss->FindPageFrm();
+ bSamePage = pNewPage == pOldPage;
+ //Damit die Fussnoten nicht auf dumme Gedanken kommen
+ //setzen wir hier die Deadline.
+ SWRECTFN( pOldBoss )
+ SwSaveFtnHeight aHeight( pOldBoss,
+ (pOldBoss->Frm().*fnRect->fnGetBottom)() );
+ SwCntntFrm* pStart = rThis.IsCntntFrm() ?
+ (SwCntntFrm*)&rThis : ((SwLayoutFrm&)rThis).ContainsCntnt();
+ OSL_ENSURE( pStart || ( rThis.IsTabFrm() && !((SwTabFrm&)rThis).Lower() ),
+ "MoveFwd: Missing Content" );
+ SwLayoutFrm* pBody = pStart ? ( pStart->IsTxtFrm() ?
+ (SwLayoutFrm*)((SwTxtFrm*)pStart)->FindBodyFrm() : 0 ) : 0;
+ if( pBody )
+ bFtnMoved = pBody->MoveLowerFtns( pStart, pOldBoss, pNewBoss,
+ sal_False);
+ }
+ // Bei SectionFrms ist es moeglich, dass wir selbst durch pNewUpper->Calc()
+ // bewegt wurden, z. B. in den pNewUpper.
+ // MoveSubTree bzw. PasteTree ist auf so etwas nicht vorbereitet.
+ if( pNewUpper != rThis.GetUpper() )
+ {
+ // --> FME 2004-04-19 #i27145#
+ SwSectionFrm* pOldSct = 0;
+ if ( rThis.GetUpper()->IsSctFrm() )
+ {
+ pOldSct = static_cast<SwSectionFrm*>(rThis.GetUpper());
+ }
+ // <--
+
+ MoveSubTree( pNewUpper, pNewUpper->Lower() );
+
+ // --> FME 2004-04-19 #i27145#
+ if ( pOldSct && pOldSct->GetSection() )
+ {
+ // Prevent loops by setting the new height at
+ // the section frame if footnotes have been moved.
+ // Otherwise the call of SwLayNotify::~SwLayNotify() for
+ // the (invalid) section frame will invalidate the first
+ // lower of its follow, because it grows due to the removed
+ // footnotes.
+ // Note: If pOldSct has become empty during MoveSubTree, it
+ // has already been scheduled for removal. No SimpleFormat
+ // for these.
+ pOldSct->SimpleFormat();
+ }
+ // <--
+
+ // --> FME 2004-07-15 #i26831#
+ if ( bForceSimpleFormat )
+ {
+ pSect->SimpleFormat();
+ }
+ // <--
+
+ if ( bFtnMoved && !bSamePage )
+ {
+ pOldPage->UpdateFtnNum();
+ pNewPage->UpdateFtnNum();
+ }
+
+ if( bBossChg )
+ {
+ rThis.Prepare( PREP_BOSS_CHGD, 0, sal_False );
+ if( !bSamePage )
+ {
+ ViewShell *pSh = rThis.getRootFrm()->GetCurrShell();
+ if ( pSh && !pSh->Imp()->IsUpdateExpFlds() )
+ pSh->GetDoc()->SetNewFldLst(true); //Wird von CalcLayout() hinterher erledigt!
+
+ pNewPage->InvalidateSpelling();
+ pNewPage->InvalidateSmartTags(); // SMARTTAGS
+ pNewPage->InvalidateAutoCompleteWords();
+ pNewPage->InvalidateWordCount();
+ }
+ }
+ }
+ // OD 30.10.2002 #97265# - no <CheckPageDesc(..)> in online layout
+ const ViewShell *pSh = rThis.getRootFrm()->GetCurrShell();
+
+ if ( !( pSh && pSh->GetViewOptions()->getBrowseMode() ) )
+ {
+ // --> OD 2009-12-31 #i106452#
+ // check page description not only in situation with sections.
+ if ( !bSamePage &&
+ ( rThis.GetAttrSet()->GetPageDesc().GetPageDesc() ||
+ pOldPage->GetPageDesc()->GetFollow() != pNewPage->GetPageDesc() ) )
+ {
+ SwFrm::CheckPageDescs( pNewPage, sal_False );
+ }
+ // <--
+ }
+ }
+ return bSamePage;
+}
+
+
+/*************************************************************************
+|*
+|* sal_Bool SwFlowFrm::MoveBwd()
+|*
+|* Beschreibung Returnwert sagt, ob der Frm die Seite wechseln soll.
+|* Sollte von abgeleiteten Klassen gerufen werden.
+|* Das moven selbst muessen die abgeleiteten uebernehmen.
+|*
+|*************************************************************************/
+
+sal_Bool SwFlowFrm::MoveBwd( sal_Bool &rbReformat )
+{
+ SwFlowFrm::SetMoveBwdJump( sal_False );
+
+ SwFtnFrm* pFtn = rThis.FindFtnFrm();
+ if ( pFtn && pFtn->IsBackMoveLocked() )
+ return sal_False;
+
+ // --> OD 2004-11-29 #115759# - text frames, which are directly inside
+ // tables aren't allowed to move backward.
+ if ( rThis.IsTxtFrm() && rThis.IsInTab() )
+ {
+ const SwLayoutFrm* pUpperFrm = rThis.GetUpper();
+ while ( pUpperFrm )
+ {
+ if ( pUpperFrm->IsTabFrm() )
+ {
+ return sal_False;
+ }
+ else if ( pUpperFrm->IsColumnFrm() && pUpperFrm->IsInSct() )
+ {
+ break;
+ }
+ pUpperFrm = pUpperFrm->GetUpper();
+ }
+ }
+ // <--
+
+ SwFtnBossFrm * pOldBoss = rThis.FindFtnBossFrm();
+ SwPageFrm * const pOldPage = pOldBoss->FindPageFrm();
+ SwLayoutFrm *pNewUpper = 0;
+ sal_Bool bCheckPageDescs = sal_False;
+ bool bCheckPageDescOfNextPage = false;
+
+ if ( pFtn )
+ {
+ //Wenn die Fussnote bereits auf der gleichen Seite/Spalte wie die Referenz
+ //steht, ist nix mit zurueckfliessen. Die breaks brauche fuer die
+ //Fussnoten nicht geprueft zu werden.
+
+ // --> FME 2004-11-15 #i37084# FindLastCntnt does not necessarily
+ // have to have a result != 0
+ SwFrm* pRef = 0;
+ const bool bEndnote = pFtn->GetAttr()->GetFtn().IsEndNote();
+ if( bEndnote && pFtn->IsInSct() )
+ {
+ SwSectionFrm* pSect = pFtn->FindSctFrm();
+ if( pSect->IsEndnAtEnd() )
+ pRef = pSect->FindLastCntnt( FINDMODE_LASTCNT );
+ }
+ if( !pRef )
+ pRef = pFtn->GetRef();
+ // <--
+
+ OSL_ENSURE( pRef, "MoveBwd: Endnote for an empty section?" );
+
+ if( !bEndnote )
+ pOldBoss = pOldBoss->FindFtnBossFrm( sal_True );
+ SwFtnBossFrm *pRefBoss = pRef->FindFtnBossFrm( !bEndnote );
+ if ( pOldBoss != pRefBoss &&
+ // OD 08.11.2002 #104840# - use <SwLayoutFrm::IsBefore(..)>
+ ( !bEndnote ||
+ pRefBoss->IsBefore( pOldBoss ) )
+ )
+ pNewUpper = rThis.GetLeaf( MAKEPAGE_FTN, sal_False );
+ }
+ else if ( IsPageBreak( sal_True ) ) //PageBreak zu beachten?
+ {
+ //Wenn auf der vorhergehenden Seite kein Frm im Body steht,
+ //so ist das Zurueckfliessen trotz Pagebreak sinnvoll
+ //(sonst: leere Seite).
+ //Natuerlich muessen Leereseiten geflissentlich uebersehen werden!
+ const SwFrm *pFlow = &rThis;
+ do
+ {
+ pFlow = pFlow->FindPrev();
+ } while ( pFlow &&
+ ( pFlow->FindPageFrm() == pOldPage ||
+ !pFlow->IsInDocBody() ) );
+ if ( pFlow )
+ {
+ long nDiff = pOldPage->GetPhyPageNum() - pFlow->GetPhyPageNum();
+ if ( nDiff > 1 )
+ {
+ if ( ((SwPageFrm*)pOldPage->GetPrev())->IsEmptyPage() )
+ nDiff -= 1;
+ if ( nDiff > 1 )
+ {
+ pNewUpper = rThis.GetLeaf( MAKEPAGE_NONE, sal_False );
+ // --> OD 2006-05-08 #i53139#
+ // Now <pNewUpper> is a previous layout frame, which contains
+ // content. But the new upper layout frame has to be the next one.
+ // Thus, hack for issue i14206 no longer needed, but fix for issue 114442
+ // --> OD 2006-05-17 #136024# - correct fix for i53139:
+ // Check for wrong page description before using next new upper.
+ // --> OD 2006-06-06 #i66051# - further correction of fix for i53139
+ // Check for correct type of new next upper layout frame
+ // --> OD 2006-06-08 #136538# - another correction of fix for i53139
+ // Assumption, that in all cases <pNewUpper> is a previous
+ // layout frame, which contains content, is wrong.
+ // --> OD 2006-07-05 #136538# - another correction of fix for i53139
+ // Beside type check, check also, if proposed new next upper
+ // frame is inside the same frame types.
+ // --> OD 2007-01-10 #i73194# - and yet another correction
+ // of fix for i53139:
+ // Assure that the new next upper layout frame doesn't
+ // equal the current one.
+ // E.g.: content is on page 3, on page 2 is only a 'ghost'
+ // section and on page 1 is normal content. Method <FindPrev(..)>
+ // will find the last content of page 1, but <GetLeaf(..)>
+ // returns new upper on page 2.
+ if ( pNewUpper->Lower() )
+ {
+ SwLayoutFrm* pNewNextUpper = pNewUpper->GetLeaf( MAKEPAGE_NONE, sal_True );
+ if ( pNewNextUpper &&
+ pNewNextUpper != rThis.GetUpper() &&
+ pNewNextUpper->GetType() == pNewUpper->GetType() &&
+ pNewNextUpper->IsInDocBody() == pNewUpper->IsInDocBody() &&
+ pNewNextUpper->IsInFtn() == pNewUpper->IsInFtn() &&
+ pNewNextUpper->IsInTab() == pNewUpper->IsInTab() &&
+ pNewNextUpper->IsInSct() == pNewUpper->IsInSct() &&
+ !rThis.WrongPageDesc( pNewNextUpper->FindPageFrm() ) )
+ {
+ pNewUpper = pNewNextUpper;
+ bCheckPageDescOfNextPage = true;
+ }
+ }
+ // <--
+
+ bCheckPageDescs = sal_True;
+ }
+ }
+ }
+ }
+ else if ( IsColBreak( sal_True ) )
+ {
+ //Wenn in der vorhergehenden Spalte kein CntntFrm steht, so ist
+ //das Zurueckfliessen trotz ColumnBreak sinnvoll
+ //(sonst: leere Spalte).
+ if( rThis.IsInSct() )
+ {
+ pNewUpper = rThis.GetLeaf( MAKEPAGE_NONE, sal_False );
+ if( pNewUpper && !SwFlowFrm::IsMoveBwdJump() &&
+ ( pNewUpper->ContainsCntnt() ||
+ ( ( !pNewUpper->IsColBodyFrm() ||
+ !pNewUpper->GetUpper()->GetPrev() ) &&
+ !pNewUpper->FindSctFrm()->GetPrev() ) ) )
+ {
+ pNewUpper = 0;
+ }
+ // --> OD 2006-05-08 #i53139#
+ // --> OD 2006-09-11 #i69409# - check <pNewUpper>
+ // --> OD 2006-11-02 #i71065# - check <SwFlowFrm::IsMoveBwdJump()>
+ else if ( pNewUpper && !SwFlowFrm::IsMoveBwdJump() )
+ // <--
+ {
+ // Now <pNewUpper> is a previous layout frame, which
+ // contains content. But the new upper layout frame
+ // has to be the next one.
+ // --> OD 2006-05-17 #136024# - correct fix for i53139
+ // Check for wrong page description before using next new upper.
+ // --> OD 2006-06-06 #i66051# - further correction of fix for i53139
+ // Check for correct type of new next upper layout frame
+ // --> OD 2006-07-05 #136538# - another correction of fix for i53139
+ // Beside type check, check also, if proposed new next upper
+ // frame is inside the same frame types.
+ SwLayoutFrm* pNewNextUpper = pNewUpper->GetLeaf( MAKEPAGE_NOSECTION, sal_True );
+ if ( pNewNextUpper &&
+ pNewNextUpper->GetType() == pNewUpper->GetType() &&
+ pNewNextUpper->IsInDocBody() == pNewUpper->IsInDocBody() &&
+ pNewNextUpper->IsInFtn() == pNewUpper->IsInFtn() &&
+ pNewNextUpper->IsInTab() == pNewUpper->IsInTab() &&
+ pNewNextUpper->IsInSct() == pNewUpper->IsInSct() &&
+ !rThis.WrongPageDesc( pNewNextUpper->FindPageFrm() ) )
+ {
+ pNewUpper = pNewNextUpper;
+ }
+ }
+ // <--
+ }
+ else
+ {
+ const SwFrm *pCol = rThis.FindColFrm();
+ sal_Bool bGoOn = sal_True;
+ sal_Bool bJump = sal_False;
+ do
+ {
+ if ( pCol->GetPrev() )
+ pCol = pCol->GetPrev();
+ else
+ {
+ bGoOn = sal_False;
+ pCol = rThis.GetLeaf( MAKEPAGE_NONE, sal_False );
+ }
+ if ( pCol )
+ {
+ // ColumnFrms jetzt mit BodyFrm
+ SwLayoutFrm* pColBody = pCol->IsColumnFrm() ?
+ (SwLayoutFrm*)((SwLayoutFrm*)pCol)->Lower() :
+ (SwLayoutFrm*)pCol;
+ if ( pColBody->ContainsCntnt() )
+ {
+ bGoOn = sal_False; // Hier gibt's Inhalt, wir akzeptieren diese
+ // nur, wenn GetLeaf() das MoveBwdJump-Flag gesetzt hat.
+ if( SwFlowFrm::IsMoveBwdJump() )
+ {
+ pNewUpper = pColBody;
+ // --> OD 2006-05-08 #i53139#
+ // Now <pNewUpper> is a previous layout frame, which
+ // contains content. But the new upper layout frame
+ // has to be the next one.
+ // --> OD 2006-05-17 #136024# - correct fix for i53139
+ // Check for wrong page description before using next new upper.
+ // --> OD 2006-06-06 #i66051# - further correction of fix for i53139
+ // Check for correct type of new next upper layout frame
+ // --> OD 2006-07-05 #136538# - another correction of fix for i53139
+ // Beside type check, check also, if proposed new next upper
+ // frame is inside the same frame types.
+ // --> OD 2006-11-02 #i71065#
+ // Check that the proposed new next upper layout
+ // frame isn't the current one.
+ SwLayoutFrm* pNewNextUpper = pNewUpper->GetLeaf( MAKEPAGE_NONE, sal_True );
+ if ( pNewNextUpper &&
+ pNewNextUpper != rThis.GetUpper() &&
+ pNewNextUpper->GetType() == pNewUpper->GetType() &&
+ pNewNextUpper->IsInDocBody() == pNewUpper->IsInDocBody() &&
+ pNewNextUpper->IsInFtn() == pNewUpper->IsInFtn() &&
+ pNewNextUpper->IsInTab() == pNewUpper->IsInTab() &&
+ pNewNextUpper->IsInSct() == pNewUpper->IsInSct() &&
+ !rThis.WrongPageDesc( pNewNextUpper->FindPageFrm() ) )
+ {
+ pNewUpper = pNewNextUpper;
+ }
+ // <--
+ }
+ }
+ else
+ {
+ if( pNewUpper ) // Wir hatten schon eine leere Spalte, haben
+ bJump = sal_True; // also eine uebersprungen
+ pNewUpper = pColBody; // Diese leere Spalte kommt in Frage,
+ // trotzdem weitersuchen
+ }
+ }
+ } while( bGoOn );
+ if( bJump )
+ SwFlowFrm::SetMoveBwdJump( sal_True );
+ }
+ }
+ else //Keine Breaks also kann ich zurueckfliessen
+ pNewUpper = rThis.GetLeaf( MAKEPAGE_NONE, sal_False );
+
+ // --> OD 2004-06-23 #i27801# - no move backward of 'master' text frame,
+ // if - due to its object positioning - it isn't allowed to be on the new page frame
+ // --> OD 2005-03-07 #i44049# - add another condition for not moving backward:
+ // If one of its objects has restarted the layout process, moving backward
+ // isn't sensible either.
+ // --> OD 2005-04-19 #i47697# - refine condition made for issue i44049:
+ // - allow move backward as long as the anchored object is only temporarily
+ // positions considering its wrapping style.
+ if ( pNewUpper &&
+ rThis.IsTxtFrm() && !IsFollow() )
+ {
+ sal_uInt32 nToPageNum( 0L );
+ const bool bMoveFwdByObjPos = SwLayouter::FrmMovedFwdByObjPos(
+ *(pOldPage->GetFmt()->GetDoc()),
+ static_cast<SwTxtFrm&>(rThis),
+ nToPageNum );
+ if ( bMoveFwdByObjPos &&
+ pNewUpper->FindPageFrm()->GetPhyPageNum() < nToPageNum )
+ {
+ pNewUpper = 0;
+ }
+ // --> OD 2005-03-07 #i44049# - check, if one of its anchored objects
+ // has restarted the layout process.
+ else if ( rThis.GetDrawObjs() )
+ {
+ sal_uInt32 i = 0;
+ for ( ; i < rThis.GetDrawObjs()->Count(); ++i )
+ {
+ SwAnchoredObject* pAnchoredObj = (*rThis.GetDrawObjs())[i];
+ // --> OD 2005-04-19 #i47697# - refine condition - see above
+ if ( pAnchoredObj->RestartLayoutProcess() &&
+ !pAnchoredObj->IsTmpConsiderWrapInfluence() )
+ // <--
+ {
+ pNewUpper = 0;
+ break;
+ }
+ }
+ }
+ // <--
+ }
+ // <--
+
+ //Fuer Follows ist das zurueckfliessen nur dann erlaubt wenn in der
+ //neuen Umgebung kein Nachbar existiert (denn dieses waere der Master).
+ //(6677)Wenn allerdings leere Blaetter uebersprungen wurden wird doch gemoved.
+ if ( pNewUpper && IsFollow() && pNewUpper->Lower() )
+ {
+ // --> OD 2007-09-05 #i79774#, #b6596954#
+ // neglect empty sections in proposed new upper frame
+ bool bProposedNewUpperContainsOnlyEmptySections( true );
+ {
+ const SwFrm* pLower( pNewUpper->Lower() );
+ while ( pLower )
+ {
+ if ( pLower->IsSctFrm() &&
+ !dynamic_cast<const SwSectionFrm*>(pLower)->GetSection() )
+ {
+ pLower = pLower->GetNext();
+ continue;
+ }
+ else
+ {
+ bProposedNewUpperContainsOnlyEmptySections = false;
+ break;
+ }
+ }
+ }
+ if ( !bProposedNewUpperContainsOnlyEmptySections )
+ {
+ if ( SwFlowFrm::IsMoveBwdJump() )
+ {
+ //Nicht hinter den Master sondern in das naechstfolgende leere
+ //Blatt moven.
+ SwFrm *pFrm = pNewUpper->Lower();
+ while ( pFrm->GetNext() )
+ pFrm = pFrm->GetNext();
+ pNewUpper = pFrm->GetLeaf( MAKEPAGE_INSERT, sal_True );
+ if( pNewUpper == rThis.GetUpper() ) //Landen wir wieder an der gleichen Stelle?
+ pNewUpper = NULL; //dann eruebrigt sich das Moven
+ }
+ else
+ pNewUpper = 0;
+ }
+ // <--
+ }
+ if ( pNewUpper && !ShouldBwdMoved( pNewUpper, sal_True, rbReformat ) )
+ {
+ if( !pNewUpper->Lower() )
+ {
+ if( pNewUpper->IsFtnContFrm() )
+ {
+ pNewUpper->Cut();
+ delete pNewUpper;
+ }
+ else
+ {
+ SwSectionFrm* pSectFrm = pNewUpper->FindSctFrm();
+ // --> OD 2006-01-04 #126020# - adjust check for empty section
+ // --> OD 2006-02-01 #130797# - correct fix #126020#
+ if ( pSectFrm && !pSectFrm->IsColLocked() &&
+ !pSectFrm->ContainsCntnt() && !pSectFrm->ContainsAny( true ) )
+ // <--
+ {
+ pSectFrm->DelEmpty( sal_True );
+ delete pSectFrm;
+ rThis.bValidPos = sal_True;
+ }
+ }
+ }
+ pNewUpper = 0;
+ }
+
+ // OD 2004-05-26 #i21478# - don't move backward, if flow frame wants to
+ // keep with next frame and next frame is locked.
+ // --> OD 2004-12-08 #i38232# - If next frame is a table, do *not* check,
+ // if it's locked.
+ if ( pNewUpper && !IsFollow() &&
+ rThis.GetAttrSet()->GetKeep().GetValue() && rThis.GetIndNext() )
+ {
+ SwFrm* pIndNext = rThis.GetIndNext();
+ // --> OD 2004-12-08 #i38232#
+ if ( !pIndNext->IsTabFrm() )
+ {
+ // get first content of section, while empty sections are skipped
+ while ( pIndNext && pIndNext->IsSctFrm() )
+ {
+ if( static_cast<SwSectionFrm*>(pIndNext)->GetSection() )
+ {
+ SwFrm* pTmp = static_cast<SwSectionFrm*>(pIndNext)->ContainsAny();
+ if ( pTmp )
+ {
+ pIndNext = pTmp;
+ break;
+ }
+ }
+ pIndNext = pIndNext->GetIndNext();
+ }
+ OSL_ENSURE( !pIndNext || pIndNext->ISA(SwTxtFrm),
+ "<SwFlowFrm::MovedBwd(..)> - incorrect next found." );
+ if ( pIndNext && pIndNext->IsFlowFrm() &&
+ SwFlowFrm::CastFlowFrm(pIndNext)->IsJoinLocked() )
+ {
+ pNewUpper = 0L;
+ }
+ }
+ // <--
+ }
+
+ // --> OD 2006-05-10 #i65250#
+ // layout loop control for flowing content again and again moving
+ // backward under the same layout condition.
+ if ( pNewUpper && !IsFollow() &&
+ pNewUpper != rThis.GetUpper() &&
+ SwLayouter::MoveBwdSuppressed( *(pOldPage->GetFmt()->GetDoc()),
+ *this, *pNewUpper ) )
+ {
+ SwLayoutFrm* pNextNewUpper = pNewUpper->GetLeaf(
+ ( !rThis.IsSctFrm() && rThis.IsInSct() )
+ ? MAKEPAGE_NOSECTION
+ : MAKEPAGE_NONE,
+ sal_True );
+ // --> OD 2007-01-10 #i73194# - make code robust
+ OSL_ENSURE( pNextNewUpper, "<SwFlowFrm::MoveBwd(..)> - missing next new upper" );
+ if ( pNextNewUpper &&
+ ( pNextNewUpper == rThis.GetUpper() ||
+ pNextNewUpper->GetType() != rThis.GetUpper()->GetType() ) )
+ // <--
+ {
+ pNewUpper = 0L;
+#if OSL_DEBUG_LEVEL > 1
+ OSL_FAIL( "<SwFlowFrm::MoveBwd(..)> - layout loop control for layout action <Move Backward> applied!" );
+#endif
+ }
+ }
+ // <--
+
+ OSL_ENSURE( pNewUpper != rThis.GetUpper(),
+ "<SwFlowFrm::MoveBwd(..)> - moving backward to the current upper frame!? -> Please inform OD." );
+ if ( pNewUpper )
+ {
+ PROTOCOL_ENTER( &rThis, PROT_MOVE_BWD, 0, 0 );
+ if ( pNewUpper->IsFtnContFrm() )
+ {
+ //Kann sein, dass ich einen Container bekam.
+ SwFtnFrm *pOld = rThis.FindFtnFrm();
+ SwFtnFrm *pNew = new SwFtnFrm( pOld->GetFmt(), pOld,
+ pOld->GetRef(), pOld->GetAttr() );
+ if ( pOld->GetMaster() )
+ {
+ pNew->SetMaster( pOld->GetMaster() );
+ pOld->GetMaster()->SetFollow( pNew );
+ }
+ pNew->SetFollow( pOld );
+ pOld->SetMaster( pNew );
+ pNew->Paste( pNewUpper );
+ pNewUpper = pNew;
+ }
+ if( pNewUpper->IsFtnFrm() && rThis.IsInSct() )
+ {
+ SwSectionFrm* pSct = rThis.FindSctFrm();
+ //Wenn wir in einem Bereich in einer Fussnote stecken, muss im
+ //neuen Upper ggf. ein SwSectionFrm angelegt werden
+ if( pSct->IsInFtn() )
+ {
+ SwFrm* pTmp = pNewUpper->Lower();
+ if( pTmp )
+ {
+ while( pTmp->GetNext() )
+ pTmp = pTmp->GetNext();
+ if( !pTmp->IsSctFrm() ||
+ ((SwSectionFrm*)pTmp)->GetFollow() != pSct )
+ pTmp = NULL;
+ }
+ if( pTmp )
+ pNewUpper = (SwSectionFrm*)pTmp;
+ else
+ {
+ pSct = new SwSectionFrm( *pSct, sal_True );
+ pSct->Paste( pNewUpper );
+ pSct->Init();
+ pNewUpper = pSct;
+ pSct->SimpleFormat();
+ }
+ }
+ }
+ sal_Bool bUnlock = sal_False;
+ sal_Bool bFollow = sal_False;
+ //Section locken, sonst kann sie bei Fluss des einzigen Cntnt etwa
+ //von zweiter in die erste Spalte zerstoert werden.
+ SwSectionFrm* pSect = pNewUpper->FindSctFrm();
+ if( pSect )
+ {
+ bUnlock = !pSect->IsColLocked();
+ pSect->ColLock();
+ bFollow = pSect->HasFollow();
+ }
+ pNewUpper->Calc();
+ rThis.Cut();
+ // --> OD 2005-02-23 #b6229852#
+ // optimization: format section, if its size is invalidated and if it's
+ // the new parent of moved backward frame.
+ bool bFormatSect( false );
+ // <--
+ if( bUnlock )
+ {
+ pSect->ColUnlock();
+ if( pSect->HasFollow() != bFollow )
+ {
+ pSect->InvalidateSize();
+ // --> OD 2005-02-23 #b6229852# - optimization
+ if ( pSect == pNewUpper )
+ bFormatSect = true;
+ // <--
+ }
+ }
+
+ rThis.Paste( pNewUpper );
+ // --> OD 2005-02-23 #b6229852# - optimization
+ if ( bFormatSect )
+ pSect->Calc();
+ // <--
+
+ SwPageFrm *pNewPage = rThis.FindPageFrm();
+ if( pNewPage != pOldPage )
+ {
+ rThis.Prepare( PREP_BOSS_CHGD, (const void*)pOldPage, sal_False );
+ ViewShell *pSh = rThis.getRootFrm()->GetCurrShell();
+ if ( pSh && !pSh->Imp()->IsUpdateExpFlds() )
+ pSh->GetDoc()->SetNewFldLst(true); //Wird von CalcLayout() hinterher eledigt!
+
+ pNewPage->InvalidateSpelling();
+ pNewPage->InvalidateSmartTags(); // SMARTTAGS
+ pNewPage->InvalidateAutoCompleteWords();
+ pNewPage->InvalidateWordCount();
+
+ // OD 30.10.2002 #97265# - no <CheckPageDesc(..)> in online layout
+ if ( !( pSh && pSh->GetViewOptions()->getBrowseMode() ) )
+ {
+ if ( bCheckPageDescs && pNewPage->GetNext() )
+ {
+ SwPageFrm* pStartPage = bCheckPageDescOfNextPage ?
+ pNewPage :
+ (SwPageFrm*)pNewPage->GetNext();
+ SwFrm::CheckPageDescs( pStartPage, sal_False);
+ }
+ else if ( rThis.GetAttrSet()->GetPageDesc().GetPageDesc() )
+ {
+ //Erste Seite wird etwa durch Ausblenden eines Bereiches leer
+ SwFrm::CheckPageDescs( (SwPageFrm*)pNewPage, sal_False);
+ }
+ }
+ }
+ }
+ return pNewUpper != 0;
+}
+
+/*************************************************************************
+|*
+|* SwFlowFrm::CastFlowFrm
+|*
+|*************************************************************************/
+
+SwFlowFrm *SwFlowFrm::CastFlowFrm( SwFrm *pFrm )
+{
+ if ( pFrm->IsCntntFrm() )
+ return (SwCntntFrm*)pFrm;
+ if ( pFrm->IsTabFrm() )
+ return (SwTabFrm*)pFrm;
+ if ( pFrm->IsSctFrm() )
+ return (SwSectionFrm*)pFrm;
+ return 0;
+}
+
+const SwFlowFrm *SwFlowFrm::CastFlowFrm( const SwFrm *pFrm )
+{
+ if ( pFrm->IsCntntFrm() )
+ return (SwCntntFrm*)pFrm;
+ if ( pFrm->IsTabFrm() )
+ return (SwTabFrm*)pFrm;
+ if ( pFrm->IsSctFrm() )
+ return (SwSectionFrm*)pFrm;
+ return 0;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/layout/fly.cxx b/sw/source/core/layout/fly.cxx
new file mode 100644
index 000000000000..5b265942d561
--- /dev/null
+++ b/sw/source/core/layout/fly.cxx
@@ -0,0 +1,2882 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+#include "hintids.hxx"
+#include <svl/itemiter.hxx>
+#include <svtools/imap.hxx>
+#include <vcl/graph.hxx>
+#include <tools/poly.hxx>
+#include <svx/contdlg.hxx>
+#include <editeng/protitem.hxx>
+#include <editeng/opaqitem.hxx>
+#include <editeng/ulspitem.hxx>
+#include <editeng/lrspitem.hxx>
+#include <editeng/frmdiritem.hxx>
+#include <editeng/keepitem.hxx>
+#include <fmtanchr.hxx>
+#include <fmtfsize.hxx>
+#include <fmtclds.hxx>
+#include <fmtcntnt.hxx>
+#include <fmturl.hxx>
+#include <fmtsrnd.hxx>
+#include <fmtornt.hxx>
+#include <fmtpdsc.hxx>
+#include <fmtcnct.hxx>
+#include <layhelp.hxx>
+#include <ndtxt.hxx>
+#include <svx/svdogrp.hxx>
+#include <ndgrf.hxx>
+#include <tolayoutanchoredobjectposition.hxx>
+#include <fmtfollowtextflow.hxx>
+#include <sortedobjs.hxx>
+#include <objectformatter.hxx>
+#include <anchoredobject.hxx>
+#include <ndole.hxx>
+#include <swtable.hxx>
+#include <svx/svdpage.hxx>
+#include "doc.hxx"
+#include "viewsh.hxx"
+#include "layouter.hxx"
+#include "pagefrm.hxx"
+#include "rootfrm.hxx"
+#include "cntfrm.hxx"
+#include "pam.hxx"
+#include "frmatr.hxx"
+#include "viewimp.hxx"
+#include "viewopt.hxx"
+#include "dcontact.hxx"
+#include "dflyobj.hxx"
+#include "dview.hxx"
+#include "flyfrm.hxx"
+#include "frmtool.hxx"
+#include "frmfmt.hxx"
+#include "hints.hxx"
+#include "swregion.hxx"
+#include "tabfrm.hxx"
+#include "txtfrm.hxx"
+#include "ndnotxt.hxx"
+#include "notxtfrm.hxx" // GetGrfArea
+#include "flyfrms.hxx"
+#include "ndindex.hxx" // GetGrfArea
+#include "sectfrm.hxx"
+#include <vcl/svapp.hxx>
+#include <vcl/salbtype.hxx> // FRound
+#include "switerator.hxx"
+
+using namespace ::com::sun::star;
+
+
+// OD 2004-03-23 #i26791
+TYPEINIT2(SwFlyFrm,SwLayoutFrm,SwAnchoredObject);
+
+/*************************************************************************
+|*
+|* SwFlyFrm::SwFlyFrm()
+|*
+|*************************************************************************/
+
+SwFlyFrm::SwFlyFrm( SwFlyFrmFmt *pFmt, SwFrm* pSib, SwFrm *pAnch ) :
+ SwLayoutFrm( pFmt, pSib ),
+ // OD 2004-03-22 #i26791#
+ SwAnchoredObject(),
+ // OD 2004-05-27 #i26791# - moved to <SwAnchoredObject>
+// aRelPos(),
+ pPrevLink( 0 ),
+ pNextLink( 0 ),
+ bInCnt( sal_False ),
+ bAtCnt( sal_False ),
+ bLayout( sal_False ),
+ bAutoPosition( sal_False ),
+ bNoShrink( sal_False ),
+ bLockDeleteContent( sal_False )
+{
+ nType = FRMC_FLY;
+
+ bInvalid = bNotifyBack = sal_True;
+ bLocked = bMinHeight =
+ bHeightClipped = bWidthClipped = bFormatHeightOnly = sal_False;
+
+ //Grosseneinstellung, Fixe groesse ist immer die Breite
+ const SwFmtFrmSize &rFrmSize = pFmt->GetFrmSize();
+ sal_Bool bVert = sal_False;
+ sal_uInt16 nDir =
+ ((SvxFrameDirectionItem&)pFmt->GetFmtAttr( RES_FRAMEDIR )).GetValue();
+ if( FRMDIR_ENVIRONMENT == nDir )
+ {
+ bDerivedVert = 1;
+ bDerivedR2L = 1;
+ if( pAnch && pAnch->IsVertical() )
+ bVert = sal_True;
+ }
+ else
+ {
+ bInvalidVert = 0;
+ bDerivedVert = 0;
+ bDerivedR2L = 0;
+ if( FRMDIR_HORI_LEFT_TOP == nDir || FRMDIR_HORI_RIGHT_TOP == nDir )
+ {
+ //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin
+ bVertLR = 0;
+ bVertical = 0;
+ }
+ else
+ {
+ const ViewShell *pSh = getRootFrm() ? getRootFrm()->GetCurrShell() : 0;
+ if( pSh && pSh->GetViewOptions()->getBrowseMode() )
+ {
+ //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin
+ bVertLR = 0;
+ bVertical = 0;
+ }
+ else
+ {
+ bVertical = 1;
+ //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin
+ if ( FRMDIR_VERT_TOP_LEFT == nDir )
+ bVertLR = 1;
+ else
+ bVertLR = 0;
+ }
+ }
+
+ bVert = bVertical;
+ bInvalidR2L = 0;
+ if( FRMDIR_HORI_RIGHT_TOP == nDir )
+ bRightToLeft = 1;
+ else
+ bRightToLeft = 0;
+ }
+
+ Frm().Width( rFrmSize.GetWidth() );
+ Frm().Height( rFrmSize.GetHeightSizeType() == ATT_VAR_SIZE ? MINFLY : rFrmSize.GetHeight() );
+
+ //Hoehe Fix oder Variabel oder was?
+ if ( rFrmSize.GetHeightSizeType() == ATT_MIN_SIZE )
+ bMinHeight = sal_True;
+ else if ( rFrmSize.GetHeightSizeType() == ATT_FIX_SIZE )
+ bFixSize = sal_True;
+
+ // OD 2004-02-12 #110582#-2 - insert columns, if necessary
+ InsertColumns();
+
+ //Erst das Init, dann den Inhalt, denn zum Inhalt koennen widerum
+ //Objekte/Rahmen gehoeren die dann angemeldet werden.
+ InitDrawObj( sal_False );
+
+ // OD 2004-01-19 #110582#
+ Chain( pAnch );
+
+ // OD 2004-01-19 #110582#
+ InsertCnt();
+
+ //Und erstmal in den Wald stellen die Kiste, damit bei neuen Dokument nicht
+ //unnoetig viel formatiert wird.
+ Frm().Pos().X() = Frm().Pos().Y() = WEIT_WECH;
+}
+
+// OD 2004-01-19 #110582#
+void SwFlyFrm::Chain( SwFrm* _pAnch )
+{
+ // Connect to chain neighboors.
+ // No problem, if a neighboor doesn't exist - the construction of the
+ // neighboor will make the connection
+ const SwFmtChain& rChain = GetFmt()->GetChain();
+ if ( rChain.GetPrev() || rChain.GetNext() )
+ {
+ if ( rChain.GetNext() )
+ {
+ SwFlyFrm* pFollow = FindChainNeighbour( *rChain.GetNext(), _pAnch );
+ if ( pFollow )
+ {
+ OSL_ENSURE( !pFollow->GetPrevLink(), "wrong chain detected" );
+ if ( !pFollow->GetPrevLink() )
+ SwFlyFrm::ChainFrames( this, pFollow );
+ }
+ }
+ if ( rChain.GetPrev() )
+ {
+ SwFlyFrm *pMaster = FindChainNeighbour( *rChain.GetPrev(), _pAnch );
+ if ( pMaster )
+ {
+ OSL_ENSURE( !pMaster->GetNextLink(), "wrong chain detected" );
+ if ( !pMaster->GetNextLink() )
+ SwFlyFrm::ChainFrames( pMaster, this );
+ }
+ }
+ }
+}
+
+// OD 2004-01-19 #110582#
+void SwFlyFrm::InsertCnt()
+{
+ if ( !GetPrevLink() )
+ {
+ const SwFmtCntnt& rCntnt = GetFmt()->GetCntnt();
+ OSL_ENSURE( rCntnt.GetCntntIdx(), ":-( no content prepared." );
+ sal_uLong nIndex = rCntnt.GetCntntIdx()->GetIndex();
+ // Lower() bedeutet SwColumnFrm, eingefuegt werden muss der Inhalt dann in den (Column)BodyFrm
+ ::_InsertCnt( Lower() ? (SwLayoutFrm*)((SwLayoutFrm*)Lower())->Lower() : (SwLayoutFrm*)this,
+ GetFmt()->GetDoc(), nIndex );
+
+ //NoTxt haben immer eine FixHeight.
+ if ( Lower() && Lower()->IsNoTxtFrm() )
+ {
+ bFixSize = sal_True;
+ bMinHeight = sal_False;
+ }
+ }
+}
+
+ // OD 2004-02-12 #110582#-2
+ void SwFlyFrm::InsertColumns()
+ {
+ // --> OD 2009-08-12 #i97379#
+ // Check, if column are allowed.
+ // Columns are not allowed for fly frames, which represent graphics or embedded objects.
+ const SwFmtCntnt& rCntnt = GetFmt()->GetCntnt();
+ OSL_ENSURE( rCntnt.GetCntntIdx(), "<SwFlyFrm::InsertColumns()> - no content prepared." );
+ SwNodeIndex aFirstCntnt( *(rCntnt.GetCntntIdx()), 1 );
+ if ( aFirstCntnt.GetNode().IsNoTxtNode() )
+ {
+ return;
+ }
+ // <--
+
+ const SwFmtCol &rCol = GetFmt()->GetCol();
+ if ( rCol.GetNumCols() > 1 )
+ {
+ //PrtArea ersteinmal so gross wie der Frm, damit die Spalten
+ //vernuenftig eingesetzt werden koennen; das schaukelt sich dann
+ //schon zurecht.
+ Prt().Width( Frm().Width() );
+ Prt().Height( Frm().Height() );
+ const SwFmtCol aOld; //ChgColumns() verlaesst sich darauf, dass auch ein
+ //Old-Wert hereingereicht wird.
+ ChgColumns( aOld, rCol );
+ }
+ }
+
+/*************************************************************************
+|*
+|* SwFlyFrm::~SwFlyFrm()
+|*
+|*************************************************************************/
+
+SwFlyFrm::~SwFlyFrm()
+{
+ // Accessible objects for fly frames will be destroyed in this destructor.
+ // For frames bound as char or frames that don't have an anchor we have
+ // to do that ourselves. For any other frame the call RemoveFly at the
+ // anchor will do that.
+ if( IsAccessibleFrm() && GetFmt() && (IsFlyInCntFrm() || !GetAnchorFrm()) )
+ {
+ SwRootFrm *pRootFrm = getRootFrm();
+ if( pRootFrm && pRootFrm->IsAnyShellAccessible() )
+ {
+ ViewShell *pVSh = pRootFrm->GetCurrShell();
+ if( pVSh && pVSh->Imp() )
+ {
+ // Lowers aren't disposed already, so we have to do a recursive
+ // dispose
+ pVSh->Imp()->DisposeAccessibleFrm( this, sal_True );
+ }
+ }
+ }
+
+ if( GetFmt() && !GetFmt()->GetDoc()->IsInDtor() )
+ {
+ // OD 2004-01-19 #110582#
+ Unchain();
+
+ // OD 2004-01-19 #110582#
+ DeleteCnt();
+
+ //Tschuess sagen.
+ if ( GetAnchorFrm() )
+ AnchorFrm()->RemoveFly( this );
+ }
+
+ FinitDrawObj();
+}
+
+const IDocumentDrawModelAccess* SwFlyFrm::getIDocumentDrawModelAccess()
+{
+ return GetFmt()->getIDocumentDrawModelAccess();
+}
+
+// OD 2004-01-19 #110582#
+void SwFlyFrm::Unchain()
+{
+ if ( GetPrevLink() )
+ UnchainFrames( GetPrevLink(), this );
+ if ( GetNextLink() )
+ UnchainFrames( this, GetNextLink() );
+}
+
+// OD 2004-01-19 #110582#
+void SwFlyFrm::DeleteCnt()
+{
+ // #110582#-2
+ if ( IsLockDeleteContent() )
+ return;
+
+ SwFrm* pFrm = pLower;
+ while ( pFrm )
+ {
+ while ( pFrm->GetDrawObjs() && pFrm->GetDrawObjs()->Count() )
+ {
+ SwAnchoredObject *pAnchoredObj = (*pFrm->GetDrawObjs())[0];
+ if ( pAnchoredObj->ISA(SwFlyFrm) )
+ delete pAnchoredObj;
+ else if ( pAnchoredObj->ISA(SwAnchoredDrawObject) )
+ {
+ // OD 23.06.2003 #108784# - consider 'virtual' drawing objects
+ SdrObject* pObj = pAnchoredObj->DrawObj();
+ if ( pObj->ISA(SwDrawVirtObj) )
+ {
+ SwDrawVirtObj* pDrawVirtObj = static_cast<SwDrawVirtObj*>(pObj);
+ pDrawVirtObj->RemoveFromWriterLayout();
+ pDrawVirtObj->RemoveFromDrawingPage();
+ }
+ else
+ {
+ SwDrawContact* pContact =
+ static_cast<SwDrawContact*>(::GetUserCall( pObj ));
+ if ( pContact )
+ {
+ pContact->DisconnectFromLayout();
+ }
+ }
+ }
+ }
+
+ pFrm->Remove();
+ delete pFrm;
+ pFrm = pLower;
+ }
+
+ InvalidatePage();
+}
+
+/*************************************************************************
+|*
+|* SwFlyFrm::InitDrawObj()
+|*
+|*************************************************************************/
+
+sal_uInt32 SwFlyFrm::_GetOrdNumForNewRef( const SwFlyDrawContact* pContact )
+{
+ sal_uInt32 nOrdNum( 0L );
+
+ // search for another Writer fly frame registered at same frame format
+ SwIterator<SwFlyFrm,SwFmt> aIter( *pContact->GetFmt() );
+ const SwFlyFrm* pFlyFrm( 0L );
+ for ( pFlyFrm = aIter.First(); pFlyFrm; pFlyFrm = aIter.Next() )
+ {
+ if ( pFlyFrm != this )
+ {
+ break;
+ }
+ }
+
+ if ( pFlyFrm )
+ {
+ // another Writer fly frame found. Take its order number
+ nOrdNum = pFlyFrm->GetVirtDrawObj()->GetOrdNum();
+ }
+ else
+ {
+ // no other Writer fly frame found. Take order number of 'master' object
+ // --> OD 2004-11-11 #i35748# - use method <GetOrdNumDirect()> instead
+ // of method <GetOrdNum()> to avoid a recalculation of the order number,
+ // which isn't intended.
+ nOrdNum = pContact->GetMaster()->GetOrdNumDirect();
+ // <--
+ }
+
+ return nOrdNum;
+}
+
+SwVirtFlyDrawObj* SwFlyFrm::CreateNewRef( SwFlyDrawContact *pContact )
+{
+ SwVirtFlyDrawObj *pDrawObj = new SwVirtFlyDrawObj( *pContact->GetMaster(), this );
+ pDrawObj->SetModel( pContact->GetMaster()->GetModel() );
+ pDrawObj->SetUserCall( pContact );
+
+ //Der Reader erzeugt die Master und setzt diese, um die Z-Order zu
+ //transportieren, in die Page ein. Beim erzeugen der ersten Referenz werden
+ //die Master aus der Liste entfernt und fuehren von da an ein
+ //Schattendasein.
+ SdrPage* pPg( 0L );
+ if ( 0 != ( pPg = pContact->GetMaster()->GetPage() ) )
+ {
+ const sal_uInt32 nOrdNum = pContact->GetMaster()->GetOrdNum();
+ pPg->ReplaceObject( pDrawObj, nOrdNum );
+ }
+ // --> OD 2004-08-16 #i27030# - insert new <SwVirtFlyDrawObj> instance
+ // into drawing page with correct order number
+ else
+ {
+ pContact->GetFmt()->getIDocumentDrawModelAccess()->GetDrawModel()->GetPage( 0 )->
+ InsertObject( pDrawObj, _GetOrdNumForNewRef( pContact ) );
+ }
+ // <--
+ // --> OD 2004-12-13 #i38889# - assure, that new <SwVirtFlyDrawObj> instance
+ // is in a visible layer.
+ pContact->MoveObjToVisibleLayer( pDrawObj );
+ // <--
+ return pDrawObj;
+}
+
+
+
+void SwFlyFrm::InitDrawObj( sal_Bool bNotify )
+{
+ //ContactObject aus dem Format suchen. Wenn bereits eines existiert, so
+ //braucht nur eine neue Ref erzeugt werden, anderfalls ist es jetzt an
+ //der Zeit das Contact zu erzeugen.
+
+ IDocumentDrawModelAccess* pIDDMA = GetFmt()->getIDocumentDrawModelAccess();
+ SwFlyDrawContact *pContact = SwIterator<SwFlyDrawContact,SwFmt>::FirstElement( *GetFmt() );
+ if ( !pContact )
+ {
+ // --> OD 2005-08-08 #i52858# - method name changed
+ pContact = new SwFlyDrawContact( (SwFlyFrmFmt*)GetFmt(),
+ pIDDMA->GetOrCreateDrawModel() );
+ // <--
+ }
+ OSL_ENSURE( pContact, "InitDrawObj failed" );
+ // OD 2004-03-22 #i26791#
+ SetDrawObj( *(CreateNewRef( pContact )) );
+
+ //Den richtigen Layer setzen.
+ // OD 2004-01-19 #110582#
+ SdrLayerID nHeavenId = pIDDMA->GetHeavenId();
+ SdrLayerID nHellId = pIDDMA->GetHellId();
+ // OD 2004-03-22 #i26791#
+ GetVirtDrawObj()->SetLayer( GetFmt()->GetOpaque().GetValue()
+ ? nHeavenId
+ : nHellId );
+ if ( bNotify )
+ NotifyDrawObj();
+}
+
+/*************************************************************************
+|*
+|* SwFlyFrm::FinitDrawObj()
+|*
+|*************************************************************************/
+
+void SwFlyFrm::FinitDrawObj()
+{
+ if ( !GetVirtDrawObj() )
+ return;
+
+ //Bei den SdrPageViews abmelden falls das Objekt dort noch selektiert ist.
+ if ( !GetFmt()->GetDoc()->IsInDtor() )
+ {
+ ViewShell *p1St = getRootFrm()->GetCurrShell();
+ if ( p1St )
+ {
+ ViewShell *pSh = p1St;
+ do
+ { //z.Zt. kann das Drawing nur ein Unmark auf alles, weil das
+ //Objekt bereits Removed wurde.
+ if( pSh->HasDrawView() )
+ pSh->Imp()->GetDrawView()->UnmarkAll();
+ pSh = (ViewShell*)pSh->GetNext();
+
+ } while ( pSh != p1St );
+ }
+ }
+
+ //VirtObject mit in das Grab nehmen. Wenn das letzte VirObject
+ //zerstoert wird, mussen das DrawObject und DrawContact ebenfalls
+ //zerstoert werden.
+ SwFlyDrawContact *pMyContact = 0;
+ if ( GetFmt() )
+ {
+ bool bContinue = true;
+ SwIterator<SwFrm,SwFmt> aFrmIter( *GetFmt() );
+ for ( SwFrm* pFrm = aFrmIter.First(); pFrm; pFrm = aFrmIter.Next() )
+ if ( pFrm != this )
+ {
+ // don't delete Contact if there is still a Frm
+ bContinue = false;
+ break;
+ }
+
+ if ( bContinue )
+ // no Frm left, find Contact object to destroy
+ pMyContact = SwIterator<SwFlyDrawContact,SwFmt>::FirstElement( *GetFmt() );
+ }
+
+ // OD, OS 2004-03-31 #116203# - clear user call of Writer fly frame 'master'
+ // <SdrObject> to assure, that a <SwXFrame::dispose()> doesn't delete the
+ // Writer fly frame again.
+ if ( pMyContact )
+ {
+ pMyContact->GetMaster()->SetUserCall( 0 );
+ }
+ GetVirtDrawObj()->SetUserCall( 0 ); //Ruft sonst Delete des ContactObj
+ delete GetVirtDrawObj(); //Meldet sich selbst beim Master ab.
+ if ( pMyContact )
+ delete pMyContact; //zerstoert den Master selbst.
+}
+
+/*************************************************************************
+|*
+|* SwFlyFrm::ChainFrames()
+|*
+|*************************************************************************/
+
+void SwFlyFrm::ChainFrames( SwFlyFrm *pMaster, SwFlyFrm *pFollow )
+{
+ OSL_ENSURE( pMaster && pFollow, "uncomplete chain" );
+ OSL_ENSURE( !pMaster->GetNextLink(), "link can not be changed" );
+ OSL_ENSURE( !pFollow->GetPrevLink(), "link can not be changed" );
+
+ pMaster->pNextLink = pFollow;
+ pFollow->pPrevLink = pMaster;
+
+ if ( pMaster->ContainsCntnt() )
+ {
+ //Damit ggf. ein Textfluss zustande kommt muss invalidiert werden.
+ SwFrm *pInva = pMaster->FindLastLower();
+ SWRECTFN( pMaster )
+ const long nBottom = (pMaster->*fnRect->fnGetPrtBottom)();
+ while ( pInva )
+ {
+ if( (pInva->Frm().*fnRect->fnBottomDist)( nBottom ) <= 0 )
+ {
+ pInva->InvalidateSize();
+ pInva->Prepare( PREP_CLEAR );
+ pInva = pInva->FindPrev();
+ }
+ else
+ pInva = 0;
+ }
+ }
+
+ if ( pFollow->ContainsCntnt() )
+ {
+ //Es gibt nur noch den Inhalt des Masters, der Inhalt vom Follow
+ //hat keine Frames mehr (sollte immer nur genau ein leerer TxtNode sein).
+ SwFrm *pFrm = pFollow->ContainsCntnt();
+ OSL_ENSURE( !pFrm->IsTabFrm() && !pFrm->FindNext(), "follow in chain contains content" );
+ pFrm->Cut();
+ delete pFrm;
+ }
+
+ // invalidate accessible relation set (accessibility wrapper)
+ ViewShell* pSh = pMaster->getRootFrm()->GetCurrShell();
+ if( pSh )
+ {
+ SwRootFrm* pLayout = pMaster->getRootFrm();
+ if( pLayout && pLayout->IsAnyShellAccessible() )
+ pSh->Imp()->InvalidateAccessibleRelationSet( pMaster, pFollow );
+ }
+}
+
+void SwFlyFrm::UnchainFrames( SwFlyFrm *pMaster, SwFlyFrm *pFollow )
+{
+ pMaster->pNextLink = 0;
+ pFollow->pPrevLink = 0;
+
+ if ( pFollow->ContainsCntnt() )
+ {
+ //Der Master saugt den Inhalt vom Follow auf
+ SwLayoutFrm *pUpper = pMaster;
+ if ( pUpper->Lower()->IsColumnFrm() )
+ {
+ pUpper = static_cast<SwLayoutFrm*>(pUpper->GetLastLower());
+ pUpper = static_cast<SwLayoutFrm*>(pUpper->Lower()); // der (Column)BodyFrm
+ OSL_ENSURE( pUpper && pUpper->IsColBodyFrm(), "Missing ColumnBody" );
+ }
+ SwFlyFrm *pFoll = pFollow;
+ while ( pFoll )
+ {
+ SwFrm *pTmp = ::SaveCntnt( pFoll );
+ if ( pTmp )
+ ::RestoreCntnt( pTmp, pUpper, pMaster->FindLastLower(), true );
+ pFoll->SetCompletePaint();
+ pFoll->InvalidateSize();
+ pFoll = pFoll->GetNextLink();
+ }
+ }
+
+ //Der Follow muss mit seinem eigenen Inhalt versorgt werden.
+ const SwFmtCntnt &rCntnt = pFollow->GetFmt()->GetCntnt();
+ OSL_ENSURE( rCntnt.GetCntntIdx(), ":-( Kein Inhalt vorbereitet." );
+ sal_uLong nIndex = rCntnt.GetCntntIdx()->GetIndex();
+ // Lower() bedeutet SwColumnFrm, dieser beinhaltet wieder einen SwBodyFrm
+ ::_InsertCnt( pFollow->Lower() ? (SwLayoutFrm*)((SwLayoutFrm*)pFollow->Lower())->Lower()
+ : (SwLayoutFrm*)pFollow,
+ pFollow->GetFmt()->GetDoc(), ++nIndex );
+
+ // invalidate accessible relation set (accessibility wrapper)
+ ViewShell* pSh = pMaster->getRootFrm()->GetCurrShell();
+ if( pSh )
+ {
+ SwRootFrm* pLayout = pMaster->getRootFrm();
+ if( pLayout && pLayout->IsAnyShellAccessible() )
+ pSh->Imp()->InvalidateAccessibleRelationSet( pMaster, pFollow );
+}
+}
+
+/*************************************************************************
+|*
+|* SwFlyFrm::FindChainNeighbour()
+|*
+|*************************************************************************/
+
+SwFlyFrm *SwFlyFrm::FindChainNeighbour( SwFrmFmt &rChain, SwFrm *pAnch )
+{
+ //Wir suchen denjenigen Fly, der in dem selben Bereich steht.
+ //Bereiche koennen zunaechst nur Kopf-/Fusszeilen oder Flys sein.
+
+ if ( !pAnch ) //Wenn ein Anchor uebergeben Wurde zaehlt dieser: Ctor!
+ pAnch = AnchorFrm();
+
+ SwLayoutFrm *pLay;
+ if ( pAnch->IsInFly() )
+ pLay = pAnch->FindFlyFrm();
+ else
+ {
+ //FindFooterOrHeader taugt hier nicht, weil evtl. noch keine Verbindung
+ //zum Anker besteht.
+ pLay = pAnch->GetUpper();
+ while ( pLay && !(pLay->GetType() & (FRM_HEADER|FRM_FOOTER)) )
+ pLay = pLay->GetUpper();
+ }
+
+ SwIterator<SwFlyFrm,SwFmt> aIter( rChain );
+ SwFlyFrm *pFly = aIter.First();
+ if ( pLay )
+ {
+ while ( pFly )
+ {
+ if ( pFly->GetAnchorFrm() )
+ {
+ if ( pFly->GetAnchorFrm()->IsInFly() )
+ {
+ if ( pFly->AnchorFrm()->FindFlyFrm() == pLay )
+ break;
+ }
+ else if ( pLay == pFly->FindFooterOrHeader() )
+ break;
+ }
+ pFly = aIter.Next();
+ }
+ }
+ else if ( pFly )
+ {
+ OSL_ENSURE( !aIter.Next(), "chain with more than one inkarnation" );
+ }
+ return pFly;
+}
+
+
+/*************************************************************************
+|*
+|* SwFlyFrm::FindLastLower()
+|*
+|*************************************************************************/
+
+SwFrm *SwFlyFrm::FindLastLower()
+{
+ SwFrm *pRet = ContainsAny();
+ if ( pRet && pRet->IsInTab() )
+ pRet = pRet->FindTabFrm();
+ SwFrm *pNxt = pRet;
+ while ( pNxt && IsAnLower( pNxt ) )
+ { pRet = pNxt;
+ pNxt = pNxt->FindNext();
+ }
+ return pRet;
+}
+
+
+/*************************************************************************
+|*
+|* SwFlyFrm::FrmSizeChg()
+|*
+|*************************************************************************/
+
+sal_Bool SwFlyFrm::FrmSizeChg( const SwFmtFrmSize &rFrmSize )
+{
+ sal_Bool bRet = sal_False;
+ SwTwips nDiffHeight = Frm().Height();
+ if ( rFrmSize.GetHeightSizeType() == ATT_VAR_SIZE )
+ bFixSize = bMinHeight = sal_False;
+ else
+ {
+ if ( rFrmSize.GetHeightSizeType() == ATT_FIX_SIZE )
+ {
+ bFixSize = sal_True;
+ bMinHeight = sal_False;
+ }
+ else if ( rFrmSize.GetHeightSizeType() == ATT_MIN_SIZE )
+ {
+ bFixSize = sal_False;
+ bMinHeight = sal_True;
+ }
+ nDiffHeight -= rFrmSize.GetHeight();
+ }
+ //Wenn der Fly Spalten enthaehlt muessen der Fly und
+ //die Spalten schon einmal auf die Wunschwerte gebracht
+ //werden, sonst haben wir ein kleines Problem.
+ if ( Lower() )
+ {
+ if ( Lower()->IsColumnFrm() )
+ {
+ const SwRect aOld( GetObjRectWithSpaces() );
+ const Size aOldSz( Prt().SSize() );
+ const SwTwips nDiffWidth = Frm().Width() - rFrmSize.GetWidth();
+ aFrm.Height( aFrm.Height() - nDiffHeight );
+ aFrm.Width ( aFrm.Width() - nDiffWidth );
+ // --> OD 2006-08-16 #i68520#
+ InvalidateObjRectWithSpaces();
+ // <--
+ aPrt.Height( aPrt.Height() - nDiffHeight );
+ aPrt.Width ( aPrt.Width() - nDiffWidth );
+ ChgLowersProp( aOldSz );
+ ::Notify( this, FindPageFrm(), aOld );
+ bValidPos = sal_False;
+ bRet = sal_True;
+ }
+ else if ( Lower()->IsNoTxtFrm() )
+ {
+ bFixSize = sal_True;
+ bMinHeight = sal_False;
+ }
+ }
+ return bRet;
+}
+
+/*************************************************************************
+|*
+|* SwFlyFrm::Modify()
+|*
+|*************************************************************************/
+
+void SwFlyFrm::Modify( const SfxPoolItem* pOld, const SfxPoolItem * pNew )
+{
+ sal_uInt8 nInvFlags = 0;
+
+ if( pNew && RES_ATTRSET_CHG == pNew->Which() )
+ {
+ SfxItemIter aNIter( *((SwAttrSetChg*)pNew)->GetChgSet() );
+ SfxItemIter aOIter( *((SwAttrSetChg*)pOld)->GetChgSet() );
+ SwAttrSetChg aOldSet( *(SwAttrSetChg*)pOld );
+ SwAttrSetChg aNewSet( *(SwAttrSetChg*)pNew );
+ while( sal_True )
+ {
+ _UpdateAttr( (SfxPoolItem*)aOIter.GetCurItem(),
+ (SfxPoolItem*)aNIter.GetCurItem(), nInvFlags,
+ &aOldSet, &aNewSet );
+ if( aNIter.IsAtEnd() )
+ break;
+ aNIter.NextItem();
+ aOIter.NextItem();
+ }
+ if ( aOldSet.Count() || aNewSet.Count() )
+ SwLayoutFrm::Modify( &aOldSet, &aNewSet );
+ }
+ else
+ _UpdateAttr( pOld, pNew, nInvFlags );
+
+ if ( nInvFlags != 0 )
+ {
+ _Invalidate();
+ if ( nInvFlags & 0x01 )
+ {
+ _InvalidatePos();
+ // --> OD 2006-08-16 #i68520#
+ InvalidateObjRectWithSpaces();
+ // <--
+ }
+ if ( nInvFlags & 0x02 )
+ {
+ _InvalidateSize();
+ // --> OD 2006-08-16 #i68520#
+ InvalidateObjRectWithSpaces();
+ // <--
+ }
+ if ( nInvFlags & 0x04 )
+ _InvalidatePrt();
+ if ( nInvFlags & 0x08 )
+ SetNotifyBack();
+ if ( nInvFlags & 0x10 )
+ SetCompletePaint();
+ if ( ( nInvFlags & 0x40 ) && Lower() && Lower()->IsNoTxtFrm() )
+ ClrContourCache( GetVirtDrawObj() );
+ SwRootFrm *pRoot;
+ if ( nInvFlags & 0x20 && 0 != (pRoot = getRootFrm()) )
+ pRoot->InvalidateBrowseWidth();
+ // --> OD 2004-06-28 #i28701#
+ if ( nInvFlags & 0x80 )
+ {
+ // update sorted object lists, the Writer fly frame is registered at.
+ UpdateObjInSortedList();
+ }
+ // <--
+ }
+
+ // --> OD 2005-07-18 #i51474# - reset flags for the layout process
+ ResetLayoutProcessBools();
+ // <--
+}
+
+void SwFlyFrm::_UpdateAttr( const SfxPoolItem *pOld, const SfxPoolItem *pNew,
+ sal_uInt8 &rInvFlags,
+ SwAttrSetChg *pOldSet, SwAttrSetChg *pNewSet )
+{
+ sal_Bool bClear = sal_True;
+ const sal_uInt16 nWhich = pOld ? pOld->Which() : pNew ? pNew->Which() : 0;
+ ViewShell *pSh = getRootFrm()->GetCurrShell();
+ switch( nWhich )
+ {
+ case RES_VERT_ORIENT:
+ case RES_HORI_ORIENT:
+ // OD 22.09.2003 #i18732# - consider new option 'follow text flow'
+ case RES_FOLLOW_TEXT_FLOW:
+ {
+ //Achtung! _immer_ Aktion in ChgRePos() mitpflegen.
+ rInvFlags |= 0x09;
+ }
+ break;
+ // OD 2004-07-01 #i28701# - consider new option 'wrap influence on position'
+ case RES_WRAP_INFLUENCE_ON_OBJPOS:
+ {
+ rInvFlags |= 0x89;
+ }
+ break;
+ case RES_SURROUND:
+ {
+ // OD 2004-05-13 #i28701# - invalidate position on change of
+ // wrapping style.
+ //rInvFlags |= 0x40;
+ rInvFlags |= 0x41;
+ //Der Hintergrund muss benachrichtigt und Invalidiert werden.
+ const SwRect aTmp( GetObjRectWithSpaces() );
+ NotifyBackground( FindPageFrm(), aTmp, PREP_FLY_ATTR_CHG );
+
+ // Durch eine Umlaufaenderung von rahmengebundenen Rahmen kann eine
+ // vertikale Ausrichtung aktiviert/deaktiviert werden => MakeFlyPos
+ if( FLY_AT_FLY == GetFmt()->GetAnchor().GetAnchorId() )
+ rInvFlags |= 0x09;
+
+ //Ggf. die Kontur am Node loeschen.
+ if ( Lower() && Lower()->IsNoTxtFrm() &&
+ !GetFmt()->GetSurround().IsContour() )
+ {
+ SwNoTxtNode *pNd = (SwNoTxtNode*)((SwCntntFrm*)Lower())->GetNode();
+ if ( pNd->HasContour() )
+ pNd->SetContour( 0 );
+ }
+ // --> OD 2004-06-28 #i28701# - perform reorder of object lists
+ // at anchor frame and at page frame.
+ rInvFlags |= 0x80;
+ }
+ break;
+
+ case RES_PROTECT:
+ {
+ const SvxProtectItem *pP = (SvxProtectItem*)pNew;
+ GetVirtDrawObj()->SetMoveProtect( pP->IsPosProtected() );
+ GetVirtDrawObj()->SetResizeProtect( pP->IsSizeProtected() );
+ if( pSh )
+ {
+ SwRootFrm* pLayout = getRootFrm();
+ if( pLayout && pLayout->IsAnyShellAccessible() )
+ pSh->Imp()->InvalidateAccessibleEditableState( sal_True, this );
+ }
+ break;
+ }
+
+ case RES_COL:
+ {
+ ChgColumns( *(const SwFmtCol*)pOld, *(const SwFmtCol*)pNew );
+ const SwFmtFrmSize &rNew = GetFmt()->GetFrmSize();
+ if ( FrmSizeChg( rNew ) )
+ NotifyDrawObj();
+ rInvFlags |= 0x1A;
+ break;
+ }
+
+ case RES_FRM_SIZE:
+ case RES_FMT_CHG:
+ {
+ const SwFmtFrmSize &rNew = GetFmt()->GetFrmSize();
+ if ( FrmSizeChg( rNew ) )
+ NotifyDrawObj();
+ rInvFlags |= 0x7F;
+ if ( RES_FMT_CHG == nWhich )
+ {
+ SwRect aNew( GetObjRectWithSpaces() );
+ SwRect aOld( aFrm );
+ const SvxULSpaceItem &rUL = ((SwFmtChg*)pOld)->pChangedFmt->GetULSpace();
+ aOld.Top( Max( aOld.Top() - long(rUL.GetUpper()), 0L ) );
+ aOld.SSize().Height()+= rUL.GetLower();
+ const SvxLRSpaceItem &rLR = ((SwFmtChg*)pOld)->pChangedFmt->GetLRSpace();
+ aOld.Left ( Max( aOld.Left() - long(rLR.GetLeft()), 0L ) );
+ aOld.SSize().Width() += rLR.GetRight();
+ aNew.Union( aOld );
+ NotifyBackground( FindPageFrm(), aNew, PREP_CLEAR );
+
+ //Dummer Fall. Bei der Zusweisung einer Vorlage k?nnen wir uns
+ //nicht auf das alte Spaltenattribut verlassen. Da diese
+ //wenigstens anzahlgemass fuer ChgColumns vorliegen muessen,
+ //bleibt uns nur einen temporaeres Attribut zu basteln.
+ SwFmtCol aCol;
+ if ( Lower() && Lower()->IsColumnFrm() )
+ {
+ sal_uInt16 nCol = 0;
+ SwFrm *pTmp = Lower();
+ do
+ { ++nCol;
+ pTmp = pTmp->GetNext();
+ } while ( pTmp );
+ aCol.Init( nCol, 0, 1000 );
+ }
+ ChgColumns( aCol, GetFmt()->GetCol() );
+ }
+
+ SwFmtURL aURL( GetFmt()->GetURL() );
+ if ( aURL.GetMap() )
+ {
+ const SwFmtFrmSize &rOld = nWhich == RES_FRM_SIZE ?
+ *(SwFmtFrmSize*)pNew :
+ ((SwFmtChg*)pOld)->pChangedFmt->GetFrmSize();
+ //#35091# Kann beim Laden von Vorlagen mal 0 sein
+ if ( rOld.GetWidth() && rOld.GetHeight() )
+ {
+
+ Fraction aScaleX( rOld.GetWidth(), rNew.GetWidth() );
+ Fraction aScaleY( rOld.GetHeight(), rOld.GetHeight() );
+ aURL.GetMap()->Scale( aScaleX, aScaleY );
+ SwFrmFmt *pFmt = GetFmt();
+ pFmt->LockModify();
+ pFmt->SetFmtAttr( aURL );
+ pFmt->UnlockModify();
+ }
+ }
+ const SvxProtectItem &rP = GetFmt()->GetProtect();
+ GetVirtDrawObj()->SetMoveProtect( rP.IsPosProtected() );
+ GetVirtDrawObj()->SetResizeProtect( rP.IsSizeProtected() );
+
+ if ( pSh )
+ pSh->InvalidateWindows( Frm() );
+ const IDocumentDrawModelAccess* pIDDMA = GetFmt()->getIDocumentDrawModelAccess();
+ const sal_uInt8 nId = GetFmt()->GetOpaque().GetValue() ?
+ pIDDMA->GetHeavenId() :
+ pIDDMA->GetHellId();
+ GetVirtDrawObj()->SetLayer( nId );
+
+ if ( Lower() )
+ {
+ //Ggf. die Kontur am Node loeschen.
+ if( Lower()->IsNoTxtFrm() &&
+ !GetFmt()->GetSurround().IsContour() )
+ {
+ SwNoTxtNode *pNd = (SwNoTxtNode*)((SwCntntFrm*)Lower())->GetNode();
+ if ( pNd->HasContour() )
+ pNd->SetContour( 0 );
+ }
+ else if( !Lower()->IsColumnFrm() )
+ {
+ SwFrm* pFrm = GetLastLower();
+ if( pFrm->IsTxtFrm() && ((SwTxtFrm*)pFrm)->IsUndersized() )
+ pFrm->Prepare( PREP_ADJUST_FRM );
+ }
+ }
+
+ // --> OD 2004-06-28 #i28701# - perform reorder of object lists
+ // at anchor frame and at page frame.
+ rInvFlags |= 0x80;
+
+ break;
+ }
+ case RES_UL_SPACE:
+ case RES_LR_SPACE:
+ {
+ rInvFlags |= 0x41;
+ if( pSh && pSh->GetViewOptions()->getBrowseMode() )
+ getRootFrm()->InvalidateBrowseWidth();
+ SwRect aNew( GetObjRectWithSpaces() );
+ SwRect aOld( aFrm );
+ if ( RES_UL_SPACE == nWhich )
+ {
+ const SvxULSpaceItem &rUL = *(SvxULSpaceItem*)pNew;
+ aOld.Top( Max( aOld.Top() - long(rUL.GetUpper()), 0L ) );
+ aOld.SSize().Height()+= rUL.GetLower();
+ }
+ else
+ {
+ const SvxLRSpaceItem &rLR = *(SvxLRSpaceItem*)pNew;
+ aOld.Left ( Max( aOld.Left() - long(rLR.GetLeft()), 0L ) );
+ aOld.SSize().Width() += rLR.GetRight();
+ }
+ aNew.Union( aOld );
+ NotifyBackground( FindPageFrm(), aNew, PREP_CLEAR );
+ }
+ break;
+
+ case RES_BOX:
+ case RES_SHADOW:
+ rInvFlags |= 0x17;
+ break;
+
+ case RES_FRAMEDIR :
+ SetDerivedVert( sal_False );
+ SetDerivedR2L( sal_False );
+ CheckDirChange();
+ break;
+
+ case RES_OPAQUE:
+ {
+ if ( pSh )
+ pSh->InvalidateWindows( Frm() );
+
+ const IDocumentDrawModelAccess* pIDDMA = GetFmt()->getIDocumentDrawModelAccess();
+ const sal_uInt8 nId = ((SvxOpaqueItem*)pNew)->GetValue() ?
+ pIDDMA->GetHeavenId() :
+ pIDDMA->GetHellId();
+ GetVirtDrawObj()->SetLayer( nId );
+ if( pSh )
+ {
+ SwRootFrm* pLayout = getRootFrm();
+ if( pLayout && pLayout->IsAnyShellAccessible() )
+ {
+ pSh->Imp()->DisposeAccessibleFrm( this );
+ pSh->Imp()->AddAccessibleFrm( this );
+ }
+ }
+ // --> OD 2004-06-28 #i28701# - perform reorder of object lists
+ // at anchor frame and at page frame.
+ rInvFlags |= 0x80;
+ }
+ break;
+
+ case RES_URL:
+ //Das Interface arbeitet bei Textrahmen auf der Rahmengroesse,
+ //die Map muss sich aber auf die FrmSize beziehen
+ if ( (!Lower() || !Lower()->IsNoTxtFrm()) &&
+ ((SwFmtURL*)pNew)->GetMap() && ((SwFmtURL*)pOld)->GetMap() )
+ {
+ const SwFmtFrmSize &rSz = GetFmt()->GetFrmSize();
+ if ( rSz.GetHeight() != Frm().Height() ||
+ rSz.GetWidth() != Frm().Width() )
+ {
+ SwFmtURL aURL( GetFmt()->GetURL() );
+ Fraction aScaleX( Frm().Width(), rSz.GetWidth() );
+ Fraction aScaleY( Frm().Height(), rSz.GetHeight() );
+ aURL.GetMap()->Scale( aScaleX, aScaleY );
+ SwFrmFmt *pFmt = GetFmt();
+ pFmt->LockModify();
+ pFmt->SetFmtAttr( aURL );
+ pFmt->UnlockModify();
+ }
+ }
+ /* Keine Invalidierung notwendig */
+ break;
+
+ case RES_CHAIN:
+ {
+ SwFmtChain *pChain = (SwFmtChain*)pNew;
+ if ( pChain->GetNext() )
+ {
+ SwFlyFrm *pFollow = FindChainNeighbour( *pChain->GetNext() );
+ if ( GetNextLink() && pFollow != GetNextLink() )
+ SwFlyFrm::UnchainFrames( this, GetNextLink());
+ if ( pFollow )
+ {
+ if ( pFollow->GetPrevLink() &&
+ pFollow->GetPrevLink() != this )
+ SwFlyFrm::UnchainFrames( pFollow->GetPrevLink(),
+ pFollow );
+ if ( !GetNextLink() )
+ SwFlyFrm::ChainFrames( this, pFollow );
+ }
+ }
+ else if ( GetNextLink() )
+ SwFlyFrm::UnchainFrames( this, GetNextLink() );
+ if ( pChain->GetPrev() )
+ {
+ SwFlyFrm *pMaster = FindChainNeighbour( *pChain->GetPrev() );
+ if ( GetPrevLink() && pMaster != GetPrevLink() )
+ SwFlyFrm::UnchainFrames( GetPrevLink(), this );
+ if ( pMaster )
+ {
+ if ( pMaster->GetNextLink() &&
+ pMaster->GetNextLink() != this )
+ SwFlyFrm::UnchainFrames( pMaster,
+ pMaster->GetNextLink() );
+ if ( !GetPrevLink() )
+ SwFlyFrm::ChainFrames( pMaster, this );
+ }
+ }
+ else if ( GetPrevLink() )
+ SwFlyFrm::UnchainFrames( GetPrevLink(), this );
+ }
+
+ default:
+ bClear = sal_False;
+ }
+ if ( bClear )
+ {
+ if ( pOldSet || pNewSet )
+ {
+ if ( pOldSet )
+ pOldSet->ClearItem( nWhich );
+ if ( pNewSet )
+ pNewSet->ClearItem( nWhich );
+ }
+ else
+ SwLayoutFrm::Modify( pOld, pNew );
+ }
+}
+
+/*************************************************************************
+|*
+|* SwFlyFrm::GetInfo()
+|*
+|* Beschreibung erfragt Informationen
+|*
+*************************************************************************/
+
+ // erfrage vom Modify Informationen
+sal_Bool SwFlyFrm::GetInfo( SfxPoolItem & rInfo ) const
+{
+ if( RES_AUTOFMT_DOCNODE == rInfo.Which() )
+ return sal_False; // es gibt einen FlyFrm also wird er benutzt
+ return sal_True; // weiter suchen
+}
+
+/*************************************************************************
+|*
+|* SwFlyFrm::_Invalidate()
+|*
+|*************************************************************************/
+
+void SwFlyFrm::_Invalidate( SwPageFrm *pPage )
+{
+ InvalidatePage( pPage );
+ bNotifyBack = bInvalid = sal_True;
+
+ SwFlyFrm *pFrm;
+ if ( GetAnchorFrm() && 0 != (pFrm = AnchorFrm()->FindFlyFrm()) )
+ {
+ //Gaanz dumm: Wenn der Fly innerhalb eines Fly gebunden ist, der
+ //Spalten enthaehlt, sollte das Format von diesem ausgehen.
+ if ( !pFrm->IsLocked() && !pFrm->IsColLocked() &&
+ pFrm->Lower() && pFrm->Lower()->IsColumnFrm() )
+ pFrm->InvalidateSize();
+ }
+
+ // --> OD 2008-01-21 #i85216#
+ // if vertical position is oriented at a layout frame inside a ghost section,
+ // assure that the position is invalidated and that the information about
+ // the vertical position oriented frame is cleared
+ if ( GetVertPosOrientFrm() && GetVertPosOrientFrm()->IsLayoutFrm() )
+ {
+ const SwSectionFrm* pSectFrm( GetVertPosOrientFrm()->FindSctFrm() );
+ if ( pSectFrm && pSectFrm->GetSection() == 0 )
+ {
+ InvalidatePos();
+ ClearVertPosOrientFrm();
+ }
+ }
+ // <--
+}
+
+/*************************************************************************
+|*
+|* SwFlyFrm::ChgRelPos()
+|*
+|* Beschreibung Aenderung der relativen Position, die Position wird
+|* damit automatisch Fix, das Attribut wird entprechend angepasst.
+|*
+|*************************************************************************/
+
+void SwFlyFrm::ChgRelPos( const Point &rNewPos )
+{
+ if ( GetCurrRelPos() != rNewPos )
+ {
+ SwFrmFmt *pFmt = GetFmt();
+ const bool bVert = GetAnchorFrm()->IsVertical();
+ const SwTwips nNewY = bVert ? rNewPos.X() : rNewPos.Y();
+ SwTwips nTmpY = nNewY == LONG_MAX ? 0 : nNewY;
+ if( bVert )
+ nTmpY = -nTmpY;
+ SfxItemSet aSet( pFmt->GetDoc()->GetAttrPool(),
+ RES_VERT_ORIENT, RES_HORI_ORIENT);
+
+ SwFmtVertOrient aVert( pFmt->GetVertOrient() );
+ SwTxtFrm *pAutoFrm = NULL;
+ // --> OD 2004-11-12 #i34948# - handle also at-page and at-fly anchored
+ // Writer fly frames
+ const RndStdIds eAnchorType = GetFrmFmt().GetAnchor().GetAnchorId();
+ if ( eAnchorType == FLY_AT_PAGE )
+ {
+ aVert.SetVertOrient( text::VertOrientation::NONE );
+ aVert.SetRelationOrient( text::RelOrientation::PAGE_FRAME );
+ }
+ else if ( eAnchorType == FLY_AT_FLY )
+ {
+ aVert.SetVertOrient( text::VertOrientation::NONE );
+ aVert.SetRelationOrient( text::RelOrientation::FRAME );
+ }
+ // <--
+ else if ( IsFlyAtCntFrm() || text::VertOrientation::NONE != aVert.GetVertOrient() )
+ {
+ if( text::RelOrientation::CHAR == aVert.GetRelationOrient() && IsAutoPos() )
+ {
+ if( LONG_MAX != nNewY )
+ {
+ aVert.SetVertOrient( text::VertOrientation::NONE );
+ xub_StrLen nOfs =
+ pFmt->GetAnchor().GetCntntAnchor()->nContent.GetIndex();
+ OSL_ENSURE( GetAnchorFrm()->IsTxtFrm(), "TxtFrm expected" );
+ pAutoFrm = (SwTxtFrm*)GetAnchorFrm();
+ while( pAutoFrm->GetFollow() &&
+ pAutoFrm->GetFollow()->GetOfst() <= nOfs )
+ {
+ if( pAutoFrm == GetAnchorFrm() )
+ nTmpY += pAutoFrm->GetRelPos().Y();
+ nTmpY -= pAutoFrm->GetUpper()->Prt().Height();
+ pAutoFrm = pAutoFrm->GetFollow();
+ }
+ nTmpY = ((SwFlyAtCntFrm*)this)->GetRelCharY(pAutoFrm)-nTmpY;
+ }
+ else
+ aVert.SetVertOrient( text::VertOrientation::CHAR_BOTTOM );
+ }
+ else
+ {
+ aVert.SetVertOrient( text::VertOrientation::NONE );
+ aVert.SetRelationOrient( text::RelOrientation::FRAME );
+ }
+ }
+ aVert.SetPos( nTmpY );
+ aSet.Put( aVert );
+
+ //Fuer Flys im Cnt ist die horizontale Ausrichtung uninteressant,
+ //den sie ist stets 0.
+ if ( !IsFlyInCntFrm() )
+ {
+ const SwTwips nNewX = bVert ? rNewPos.Y() : rNewPos.X();
+ SwTwips nTmpX = nNewX == LONG_MAX ? 0 : nNewX;
+ SwFmtHoriOrient aHori( pFmt->GetHoriOrient() );
+ // --> OD 2004-11-12 #i34948# - handle also at-page and at-fly anchored
+ // Writer fly frames
+ if ( eAnchorType == FLY_AT_PAGE )
+ {
+ aHori.SetHoriOrient( text::HoriOrientation::NONE );
+ aHori.SetRelationOrient( text::RelOrientation::PAGE_FRAME );
+ aHori.SetPosToggle( sal_False );
+ }
+ else if ( eAnchorType == FLY_AT_FLY )
+ {
+ aHori.SetHoriOrient( text::HoriOrientation::NONE );
+ aHori.SetRelationOrient( text::RelOrientation::FRAME );
+ aHori.SetPosToggle( sal_False );
+ }
+ // <--
+ else if ( IsFlyAtCntFrm() || text::HoriOrientation::NONE != aHori.GetHoriOrient() )
+ {
+ aHori.SetHoriOrient( text::HoriOrientation::NONE );
+ if( text::RelOrientation::CHAR == aHori.GetRelationOrient() && IsAutoPos() )
+ {
+ if( LONG_MAX != nNewX )
+ {
+ if( !pAutoFrm )
+ {
+ xub_StrLen nOfs = pFmt->GetAnchor().GetCntntAnchor()
+ ->nContent.GetIndex();
+ OSL_ENSURE( GetAnchorFrm()->IsTxtFrm(), "TxtFrm expected");
+ pAutoFrm = (SwTxtFrm*)GetAnchorFrm();
+ while( pAutoFrm->GetFollow() &&
+ pAutoFrm->GetFollow()->GetOfst() <= nOfs )
+ pAutoFrm = pAutoFrm->GetFollow();
+ }
+ nTmpX -= ((SwFlyAtCntFrm*)this)->GetRelCharX(pAutoFrm);
+ }
+ }
+ else
+ aHori.SetRelationOrient( text::RelOrientation::FRAME );
+ aHori.SetPosToggle( sal_False );
+ }
+ aHori.SetPos( nTmpX );
+ aSet.Put( aHori );
+ }
+ SetCurrRelPos( rNewPos );
+ pFmt->GetDoc()->SetAttr( aSet, *pFmt );
+ }
+}
+/*************************************************************************
+|*
+|* SwFlyFrm::Format()
+|*
+|* Beschreibung: "Formatiert" den Frame; Frm und PrtArea.
+|* Die Fixsize wird hier nicht eingestellt.
+|*
+|*************************************************************************/
+
+void SwFlyFrm::Format( const SwBorderAttrs *pAttrs )
+{
+ OSL_ENSURE( pAttrs, "FlyFrm::Format, pAttrs ist 0." );
+
+ ColLock();
+
+ if ( !bValidSize )
+ {
+ if ( Frm().Top() == WEIT_WECH && Frm().Left() == WEIT_WECH )
+ {
+ //Sicherheitsschaltung wegnehmen (siehe SwFrm::CTor)
+ Frm().Pos().X() = Frm().Pos().Y() = 0;
+ // --> OD 2006-08-16 #i68520#
+ InvalidateObjRectWithSpaces();
+ // <--
+ }
+
+ //Breite der Spalten pruefen und ggf. einstellen.
+ if ( Lower() && Lower()->IsColumnFrm() )
+ AdjustColumns( 0, sal_False );
+
+ bValidSize = sal_True;
+
+ const SwTwips nUL = pAttrs->CalcTopLine() + pAttrs->CalcBottomLine();
+ const SwTwips nLR = pAttrs->CalcLeftLine() + pAttrs->CalcRightLine();
+ const SwFmtFrmSize &rFrmSz = GetFmt()->GetFrmSize();
+ Size aRelSize( CalcRel( rFrmSz ) );
+
+ OSL_ENSURE( pAttrs->GetSize().Height() != 0 || rFrmSz.GetHeightPercent(), "Hoehe des RahmenAttr ist 0." );
+ OSL_ENSURE( pAttrs->GetSize().Width() != 0 || rFrmSz.GetWidthPercent(), "Breite des RahmenAttr ist 0." );
+
+ SWRECTFN( this )
+ if( !HasFixSize() )
+ {
+ SwTwips nRemaining = 0;
+
+ long nMinHeight = 0;
+ if( IsMinHeight() )
+ nMinHeight = bVert ? aRelSize.Width() : aRelSize.Height();
+
+ if ( Lower() )
+ {
+ if ( Lower()->IsColumnFrm() )
+ {
+ FormatWidthCols( *pAttrs, nUL, nMinHeight );
+ nRemaining = (Lower()->Frm().*fnRect->fnGetHeight)();
+ }
+ else
+ {
+ SwFrm *pFrm = Lower();
+ while ( pFrm )
+ {
+ nRemaining += (pFrm->Frm().*fnRect->fnGetHeight)();
+ if( pFrm->IsTxtFrm() && ((SwTxtFrm*)pFrm)->IsUndersized() )
+ // Dieser TxtFrm waere gern ein bisschen groesser
+ nRemaining += ((SwTxtFrm*)pFrm)->GetParHeight()
+ - (pFrm->Prt().*fnRect->fnGetHeight)();
+ else if( pFrm->IsSctFrm() && ((SwSectionFrm*)pFrm)->IsUndersized() )
+ nRemaining += ((SwSectionFrm*)pFrm)->Undersize();
+ pFrm = pFrm->GetNext();
+ }
+ // --> OD 2006-02-09 #130878#
+ // Do not keep old height, if content has no height.
+ // The old height could be wrong due to wrong layout cache
+ // and isn't corrected in the further formatting, because
+ // the fly frame doesn't become invalid anymore.
+// if( !nRemaining )
+// nRemaining = nOldHeight - nUL;
+ // <--
+ }
+ if ( GetDrawObjs() )
+ {
+ sal_uInt32 nCnt = GetDrawObjs()->Count();
+ SwTwips nTop = (Frm().*fnRect->fnGetTop)();
+ SwTwips nBorder = (Frm().*fnRect->fnGetHeight)() -
+ (Prt().*fnRect->fnGetHeight)();
+ for ( sal_uInt16 i = 0; i < nCnt; ++i )
+ {
+ SwAnchoredObject* pAnchoredObj = (*GetDrawObjs())[i];
+ if ( pAnchoredObj->ISA(SwFlyFrm) )
+ {
+ SwFlyFrm* pFly = static_cast<SwFlyFrm*>(pAnchoredObj);
+ // OD 06.11.2003 #i22305# - consider
+ // only Writer fly frames, which follow the text flow.
+ if ( pFly->IsFlyLayFrm() &&
+ pFly->Frm().Top() != WEIT_WECH &&
+ pFly->GetFmt()->GetFollowTextFlow().GetValue() )
+ {
+ SwTwips nDist = -(pFly->Frm().*fnRect->
+ fnBottomDist)( nTop );
+ if( nDist > nBorder + nRemaining )
+ nRemaining = nDist - nBorder;
+ }
+ }
+ }
+ }
+ }
+
+ if( IsMinHeight() && (nRemaining + nUL) < nMinHeight )
+ nRemaining = nMinHeight - nUL;
+ //Weil das Grow/Shrink der Flys die Groessen nicht direkt
+ //einstellt, sondern indirekt per Invalidate ein Format
+ //ausloesst, muessen die Groessen hier direkt eingestellt
+ //werden. Benachrichtung laeuft bereits mit.
+ //Weil bereits haeufiger 0en per Attribut hereinkamen wehre
+ //ich mich ab sofort dagegen.
+ if ( nRemaining < MINFLY )
+ nRemaining = MINFLY;
+ (Prt().*fnRect->fnSetHeight)( nRemaining );
+ nRemaining -= (Frm().*fnRect->fnGetHeight)();
+ (Frm().*fnRect->fnAddBottom)( nRemaining + nUL );
+ // --> OD 2006-08-16 #i68520#
+ if ( nRemaining + nUL != 0 )
+ {
+ InvalidateObjRectWithSpaces();
+ }
+ // <--
+ bValidSize = sal_True;
+ }
+ else
+ {
+ bValidSize = sal_True; //Fixe Frms formatieren sich nicht.
+ //Flys stellen ihre Groesse anhand des Attr ein.
+ SwTwips nNewSize = bVert ? aRelSize.Width() : aRelSize.Height();
+ nNewSize -= nUL;
+ if( nNewSize < MINFLY )
+ nNewSize = MINFLY;
+ (Prt().*fnRect->fnSetHeight)( nNewSize );
+ nNewSize += nUL - (Frm().*fnRect->fnGetHeight)();
+ (Frm().*fnRect->fnAddBottom)( nNewSize );
+ // --> OD 2006-08-16 #i68520#
+ if ( nNewSize != 0 )
+ {
+ InvalidateObjRectWithSpaces();
+ }
+ // <--
+ }
+
+ if ( !bFormatHeightOnly )
+ {
+ OSL_ENSURE( aRelSize == CalcRel( rFrmSz ), "SwFlyFrm::Format CalcRel problem" );
+ SwTwips nNewSize = bVert ? aRelSize.Height() : aRelSize.Width();
+
+ if ( rFrmSz.GetWidthSizeType() != ATT_FIX_SIZE )
+ {
+ // #i9046# Autowidth for fly frames
+ const SwTwips nAutoWidth = CalcAutoWidth();
+ if ( nAutoWidth )
+ {
+ if( ATT_MIN_SIZE == rFrmSz.GetWidthSizeType() )
+ nNewSize = Max( nNewSize - nLR, nAutoWidth );
+ else
+ nNewSize = nAutoWidth;
+ }
+ }
+ else
+ nNewSize -= nLR;
+
+ if( nNewSize < MINFLY )
+ nNewSize = MINFLY;
+ (Prt().*fnRect->fnSetWidth)( nNewSize );
+ nNewSize += nLR - (Frm().*fnRect->fnGetWidth)();
+ (Frm().*fnRect->fnAddRight)( nNewSize );
+ // --> OD 2006-08-16 #i68520#
+ if ( nNewSize != 0 )
+ {
+ InvalidateObjRectWithSpaces();
+ }
+ // <--
+ }
+ }
+ ColUnlock();
+}
+
+// OD 14.03.2003 #i11760# - change parameter <bNoColl>: type <bool>;
+// default value = false.
+// OD 14.03.2003 #i11760# - add new parameter <bNoCalcFollow> with
+// default value = false.
+// OD 11.04.2003 #108824# - new parameter <bNoCalcFollow> was used by method
+// <FormatWidthCols(..)> to avoid follow formatting
+// for text frames. But, unformatted follows causes
+// problems in method <SwCntntFrm::_WouldFit(..)>,
+// which assumes that the follows are formatted.
+// Thus, <bNoCalcFollow> no longer used by <FormatWidthCols(..)>.
+//void CalcCntnt( SwLayoutFrm *pLay, sal_Bool bNoColl )
+void CalcCntnt( SwLayoutFrm *pLay,
+ bool bNoColl,
+ bool bNoCalcFollow )
+{
+ SwSectionFrm* pSect;
+ sal_Bool bCollect = sal_False;
+ if( pLay->IsSctFrm() )
+ {
+ pSect = (SwSectionFrm*)pLay;
+ if( pSect->IsEndnAtEnd() && !bNoColl )
+ {
+ bCollect = sal_True;
+ SwLayouter::CollectEndnotes( pLay->GetFmt()->GetDoc(), pSect );
+ }
+ pSect->CalcFtnCntnt();
+ }
+ else
+ pSect = NULL;
+ SwFrm *pFrm = pLay->ContainsAny();
+ if ( !pFrm )
+ {
+ if( pSect )
+ {
+ if( pSect->HasFollow() )
+ pFrm = pSect->GetFollow()->ContainsAny();
+ if( !pFrm )
+ {
+ if( pSect->IsEndnAtEnd() )
+ {
+ if( bCollect )
+ pLay->GetFmt()->GetDoc()->GetLayouter()->
+ InsertEndnotes( pSect );
+ sal_Bool bLock = pSect->IsFtnLock();
+ pSect->SetFtnLock( sal_True );
+ pSect->CalcFtnCntnt();
+ pSect->CalcFtnCntnt();
+ pSect->SetFtnLock( bLock );
+ }
+ return;
+ }
+ pFrm->_InvalidatePos();
+ }
+ else
+ return;
+ }
+ pFrm->InvalidatePage();
+
+ do
+ {
+ // local variables to avoid loops caused by anchored object positioning
+ SwAnchoredObject* pAgainObj1 = 0;
+ SwAnchoredObject* pAgainObj2 = 0;
+
+ // FME 2007-08-30 #i81146# new loop control
+ sal_uInt16 nLoopControlRuns = 0;
+ const sal_uInt16 nLoopControlMax = 20;
+ const SwFrm* pLoopControlCond = 0;
+
+ SwFrm* pLast;
+ do
+ {
+ pLast = pFrm;
+ if( pFrm->IsVertical() ?
+ ( pFrm->GetUpper()->Prt().Height() != pFrm->Frm().Height() )
+ : ( pFrm->GetUpper()->Prt().Width() != pFrm->Frm().Width() ) )
+ {
+ pFrm->Prepare( PREP_FIXSIZE_CHG );
+ pFrm->_InvalidateSize();
+ }
+
+ if ( pFrm->IsTabFrm() )
+ {
+ ((SwTabFrm*)pFrm)->bCalcLowers = sal_True;
+ // OD 26.08.2003 #i18103# - lock move backward of follow table,
+ // if no section content is formatted or follow table belongs
+ // to the section, which content is formatted.
+ if ( ((SwTabFrm*)pFrm)->IsFollow() &&
+ ( !pSect || pSect == pFrm->FindSctFrm() ) )
+ {
+ ((SwTabFrm*)pFrm)->bLockBackMove = sal_True;
+ }
+ }
+
+ // OD 14.03.2003 #i11760# - forbid format of follow, if requested.
+ if ( bNoCalcFollow && pFrm->IsTxtFrm() )
+ static_cast<SwTxtFrm*>(pFrm)->ForbidFollowFormat();
+
+ pFrm->Calc();
+
+ // OD 14.03.2003 #i11760# - reset control flag for follow format.
+ if ( pFrm->IsTxtFrm() )
+ {
+ static_cast<SwTxtFrm*>(pFrm)->AllowFollowFormat();
+ }
+
+ // #111937# The keep-attribute can cause the position
+ // of the prev to be invalid:
+ // OD 2004-03-15 #116560# - Do not consider invalid previous frame
+ // due to its keep-attribute, if current frame is a follow or is locked.
+ // --> OD 2005-03-08 #i44049# - do not consider invalid previous
+ // frame due to its keep-attribute, if it can't move forward.
+ // --> OD 2006-01-27 #i57765# - do not consider invalid previous
+ // frame, if current frame has a column/page break before attribute.
+ SwFrm* pTmpPrev = pFrm->FindPrev();
+ SwFlowFrm* pTmpPrevFlowFrm = pTmpPrev && pTmpPrev->IsFlowFrm() ? SwFlowFrm::CastFlowFrm(pTmpPrev) : 0;
+ SwFlowFrm* pTmpFlowFrm = pFrm->IsFlowFrm() ? SwFlowFrm::CastFlowFrm(pFrm) : 0;
+
+ bool bPrevInvalid = pTmpPrevFlowFrm && pTmpFlowFrm &&
+ !pTmpFlowFrm->IsFollow() &&
+ !StackHack::IsLocked() && // #i76382#
+ !pTmpFlowFrm->IsJoinLocked() &&
+ !pTmpPrev->GetValidPosFlag() &&
+ pLay->IsAnLower( pTmpPrev ) &&
+ pTmpPrevFlowFrm->IsKeep( *pTmpPrev->GetAttrSet() ) &&
+ pTmpPrevFlowFrm->IsKeepFwdMoveAllowed();
+ // <--
+
+ // format floating screen objects anchored to the frame.
+ bool bRestartLayoutProcess = false;
+ if ( !bPrevInvalid && pFrm->GetDrawObjs() && pLay->IsAnLower( pFrm ) )
+ {
+ bool bAgain = false;
+ SwPageFrm* pPageFrm = pFrm->FindPageFrm();
+ sal_uInt32 nCnt = pFrm->GetDrawObjs()->Count();
+ for ( sal_uInt16 i = 0; i < nCnt; ++i )
+ {
+ // --> OD 2004-07-01 #i28701#
+ SwAnchoredObject* pAnchoredObj = (*pFrm->GetDrawObjs())[i];
+ // determine, if anchored object has to be formatted.
+ if ( pAnchoredObj->PositionLocked() )
+ {
+ continue;
+ }
+
+ // format anchored object
+ if ( pAnchoredObj->IsFormatPossible() )
+ {
+ // --> OD 2005-05-17 #i43737# - no invalidation of
+ // anchored object needed - causes loops for as-character
+ // anchored objects.
+ //pAnchoredObj->InvalidateObjPos();
+ // <--
+ SwRect aRect( pAnchoredObj->GetObjRect() );
+ if ( !SwObjectFormatter::FormatObj( *pAnchoredObj, pFrm, pPageFrm ) )
+ {
+ bRestartLayoutProcess = true;
+ break;
+ }
+ // --> OD 2004-08-25 #i3317# - restart layout process,
+ // if the position of the anchored object is locked now.
+ if ( pAnchoredObj->PositionLocked() )
+ {
+ bRestartLayoutProcess = true;
+ break;
+ }
+ // <--
+
+ if ( aRect != pAnchoredObj->GetObjRect() )
+ {
+ bAgain = true;
+ if ( pAgainObj2 == pAnchoredObj )
+ {
+ OSL_FAIL( "::CalcCntnt(..) - loop detected, perform attribute changes to avoid the loop" );
+ //Oszillation unterbinden.
+ SwFrmFmt& rFmt = pAnchoredObj->GetFrmFmt();
+ SwFmtSurround aAttr( rFmt.GetSurround() );
+ if( SURROUND_THROUGHT != aAttr.GetSurround() )
+ {
+ // Bei autopositionierten hilft manchmal nur
+ // noch, auf Durchlauf zu schalten
+ if ((rFmt.GetAnchor().GetAnchorId() ==
+ FLY_AT_CHAR) &&
+ (SURROUND_PARALLEL ==
+ aAttr.GetSurround()))
+ {
+ aAttr.SetSurround( SURROUND_THROUGHT );
+ }
+ else
+ {
+ aAttr.SetSurround( SURROUND_PARALLEL );
+ }
+ rFmt.LockModify();
+ rFmt.SetFmtAttr( aAttr );
+ rFmt.UnlockModify();
+ }
+ }
+ else
+ {
+ if ( pAgainObj1 == pAnchoredObj )
+ pAgainObj2 = pAnchoredObj;
+ pAgainObj1 = pAnchoredObj;
+ }
+ }
+
+ if ( !pFrm->GetDrawObjs() )
+ break;
+ if ( pFrm->GetDrawObjs()->Count() < nCnt )
+ {
+ --i;
+ --nCnt;
+ }
+ }
+ }
+
+ // --> OD 2004-06-11 #i28701# - restart layout process, if
+ // requested by floating screen object formatting
+ if ( bRestartLayoutProcess )
+ {
+ pFrm = pLay->ContainsAny();
+ pAgainObj1 = 0L;
+ pAgainObj2 = 0L;
+ continue;
+ }
+
+ // OD 2004-05-17 #i28701# - format anchor frame after its objects
+ // are formatted, if the wrapping style influence has to be considered.
+ if ( pLay->GetFmt()->getIDocumentSettingAccess()->get(IDocumentSettingAccess::CONSIDER_WRAP_ON_OBJECT_POSITION) )
+ {
+ pFrm->Calc();
+ }
+ // <--
+
+ if ( bAgain )
+ {
+ pFrm = pLay->ContainsCntnt();
+ if ( pFrm && pFrm->IsInTab() )
+ pFrm = pFrm->FindTabFrm();
+ if( pFrm && pFrm->IsInSct() )
+ {
+ SwSectionFrm* pTmp = pFrm->FindSctFrm();
+ if( pTmp != pLay && pLay->IsAnLower( pTmp ) )
+ pFrm = pTmp;
+ }
+
+ if ( pFrm == pLoopControlCond )
+ ++nLoopControlRuns;
+ else
+ {
+ nLoopControlRuns = 0;
+ pLoopControlCond = pFrm;
+ }
+
+ if ( nLoopControlRuns < nLoopControlMax )
+ continue;
+
+#if OSL_DEBUG_LEVEL > 1
+ OSL_FAIL( "LoopControl in CalcCntnt" );
+#endif
+ }
+ }
+ if ( pFrm->IsTabFrm() )
+ {
+ if ( ((SwTabFrm*)pFrm)->IsFollow() )
+ ((SwTabFrm*)pFrm)->bLockBackMove = sal_False;
+ }
+
+ pFrm = bPrevInvalid ? pTmpPrev : pFrm->FindNext();
+ if( !bPrevInvalid && pFrm && pFrm->IsSctFrm() && pSect )
+ {
+ // Es koennen hier leere SectionFrms herumspuken
+ while( pFrm && pFrm->IsSctFrm() && !((SwSectionFrm*)pFrm)->GetSection() )
+ pFrm = pFrm->FindNext();
+ // Wenn FindNext den Follow des urspruenglichen Bereichs liefert,
+ // wollen wir mit dessen Inhalt weitermachen, solange dieser
+ // zurueckfliesst.
+ if( pFrm && pFrm->IsSctFrm() && ( pFrm == pSect->GetFollow() ||
+ ((SwSectionFrm*)pFrm)->IsAnFollow( pSect ) ) )
+ {
+ pFrm = ((SwSectionFrm*)pFrm)->ContainsAny();
+ if( pFrm )
+ pFrm->_InvalidatePos();
+ }
+ }
+ // Im pLay bleiben, Ausnahme, bei SectionFrms mit Follow wird der erste
+ // CntntFrm des Follows anformatiert, damit er die Chance erhaelt, in
+ // pLay zu landen. Solange diese Frames in pLay landen, geht's weiter.
+ } while ( pFrm &&
+ ( pLay->IsAnLower( pFrm ) ||
+ ( pSect &&
+ ( ( pSect->HasFollow() &&
+ ( pLay->IsAnLower( pLast ) ||
+ ( pLast->IsInSct() &&
+ pLast->FindSctFrm()->IsAnFollow(pSect) ) ) &&
+ pSect->GetFollow()->IsAnLower( pFrm ) ) ||
+ ( pFrm->IsInSct() &&
+ pFrm->FindSctFrm()->IsAnFollow( pSect ) ) ) ) ) );
+ if( pSect )
+ {
+ if( bCollect )
+ {
+ pLay->GetFmt()->GetDoc()->GetLayouter()->InsertEndnotes(pSect);
+ pSect->CalcFtnCntnt();
+ }
+ if( pSect->HasFollow() )
+ {
+ SwSectionFrm* pNxt = pSect->GetFollow();
+ while( pNxt && !pNxt->ContainsCntnt() )
+ pNxt = pNxt->GetFollow();
+ if( pNxt )
+ pNxt->CalcFtnCntnt();
+ }
+ if( bCollect )
+ {
+ pFrm = pLay->ContainsAny();
+ bCollect = sal_False;
+ if( pFrm )
+ continue;
+ }
+ }
+ break;
+ }
+ while( sal_True );
+}
+
+/*************************************************************************
+|*
+|* SwFlyFrm::MakeFlyPos()
+|*
+|*************************************************************************/
+// OD 2004-03-23 #i26791#
+//void SwFlyFrm::MakeFlyPos()
+void SwFlyFrm::MakeObjPos()
+{
+ if ( !bValidPos )
+ {
+ bValidPos = sal_True;
+
+ // OD 29.10.2003 #113049# - use new class to position object
+ GetAnchorFrm()->Calc();
+ objectpositioning::SwToLayoutAnchoredObjectPosition
+ aObjPositioning( *GetVirtDrawObj() );
+ aObjPositioning.CalcPosition();
+
+ // --> OD 2006-10-05 #i58280#
+ // update relative position
+ SetCurrRelPos( aObjPositioning.GetRelPos() );
+ // <--
+
+ SWRECTFN( GetAnchorFrm() );
+ aFrm.Pos( aObjPositioning.GetRelPos() );
+ aFrm.Pos() += (GetAnchorFrm()->Frm().*fnRect->fnGetPos)();
+ // --> OD 2006-09-11 #i69335#
+ InvalidateObjRectWithSpaces();
+ // <--
+ }
+}
+
+/*************************************************************************
+|*
+|* SwFlyFrm::MakePrtArea()
+|*
+|*************************************************************************/
+void SwFlyFrm::MakePrtArea( const SwBorderAttrs &rAttrs )
+{
+
+ if ( !bValidPrtArea )
+ {
+ bValidPrtArea = sal_True;
+
+ // OD 31.07.2003 #110978# - consider vertical layout
+ SWRECTFN( this )
+ (this->*fnRect->fnSetXMargins)( rAttrs.CalcLeftLine(),
+ rAttrs.CalcRightLine() );
+ (this->*fnRect->fnSetYMargins)( rAttrs.CalcTopLine(),
+ rAttrs.CalcBottomLine() );
+ }
+}
+
+/*************************************************************************
+|*
+|* SwFlyFrm::_Grow(), _Shrink()
+|*
+|*************************************************************************/
+
+SwTwips SwFlyFrm::_Grow( SwTwips nDist, sal_Bool bTst )
+{
+ SWRECTFN( this )
+ if ( Lower() && !IsColLocked() && !HasFixSize() )
+ {
+ SwTwips nSize = (Frm().*fnRect->fnGetHeight)();
+ if( nSize > 0 && nDist > ( LONG_MAX - nSize ) )
+ nDist = LONG_MAX - nSize;
+
+ if ( nDist <= 0L )
+ return 0L;
+
+ if ( Lower()->IsColumnFrm() )
+ { //Bei Spaltigkeit ubernimmt das Format die Kontrolle ueber
+ //das Wachstum (wg. des Ausgleichs).
+ if ( !bTst )
+ {
+ // --> OD 2004-06-09 #i28701# - unlock position of Writer fly frame
+ UnlockPosition();
+ _InvalidatePos();
+ InvalidateSize();
+ }
+ return 0L;
+ }
+
+ if ( !bTst )
+ {
+ const SwRect aOld( GetObjRectWithSpaces() );
+ _InvalidateSize();
+ const sal_Bool bOldLock = bLocked;
+ Unlock();
+ if ( IsFlyFreeFrm() )
+ {
+ // --> OD 2004-11-12 #i37068# - no format of position here
+ // and prevent move in method <CheckClip(..)>.
+ // This is needed to prevent layout loop caused by nested
+ // Writer fly frames - inner Writer fly frames format its
+ // anchor, which grows/shrinks the outer Writer fly frame.
+ // Note: position will be invalidated below.
+ bValidPos = sal_True;
+ // --> OD 2005-10-10 #i55416#
+ // Suppress format of width for autowidth frame, because the
+ // format of the width would call <SwTxtFrm::CalcFitToContent()>
+ // for the lower frame, which initiated this grow.
+ const sal_Bool bOldFormatHeightOnly = bFormatHeightOnly;
+ const SwFmtFrmSize& rFrmSz = GetFmt()->GetFrmSize();
+ if ( rFrmSz.GetWidthSizeType() != ATT_FIX_SIZE )
+ {
+ bFormatHeightOnly = sal_True;
+ }
+ // <--
+ static_cast<SwFlyFreeFrm*>(this)->SetNoMoveOnCheckClip( true );
+ ((SwFlyFreeFrm*)this)->SwFlyFreeFrm::MakeAll();
+ static_cast<SwFlyFreeFrm*>(this)->SetNoMoveOnCheckClip( false );
+ // --> OD 2005-10-10 #i55416#
+ if ( rFrmSz.GetWidthSizeType() != ATT_FIX_SIZE )
+ {
+ bFormatHeightOnly = bOldFormatHeightOnly;
+ }
+ // <--
+ // <--
+ }
+ else
+ MakeAll();
+ _InvalidateSize();
+ InvalidatePos();
+ if ( bOldLock )
+ Lock();
+ const SwRect aNew( GetObjRectWithSpaces() );
+ if ( aOld != aNew )
+ ::Notify( this, FindPageFrm(), aOld );
+ return (aNew.*fnRect->fnGetHeight)()-(aOld.*fnRect->fnGetHeight)();
+ }
+ return nDist;
+ }
+ return 0L;
+}
+
+SwTwips SwFlyFrm::_Shrink( SwTwips nDist, sal_Bool bTst )
+{
+ if( Lower() && !IsColLocked() && !HasFixSize() && !IsNoShrink() )
+ {
+ SWRECTFN( this )
+ SwTwips nHeight = (Frm().*fnRect->fnGetHeight)();
+ if ( nDist > nHeight )
+ nDist = nHeight;
+
+ SwTwips nVal = nDist;
+ if ( IsMinHeight() )
+ {
+ const SwFmtFrmSize& rFmtSize = GetFmt()->GetFrmSize();
+ SwTwips nFmtHeight = bVert ? rFmtSize.GetWidth() : rFmtSize.GetHeight();
+
+ nVal = Min( nDist, nHeight - nFmtHeight );
+ }
+
+ if ( nVal <= 0L )
+ return 0L;
+
+ if ( Lower()->IsColumnFrm() )
+ { //Bei Spaltigkeit ubernimmt das Format die Kontrolle ueber
+ //das Wachstum (wg. des Ausgleichs).
+ if ( !bTst )
+ {
+ SwRect aOld( GetObjRectWithSpaces() );
+ (Frm().*fnRect->fnSetHeight)( nHeight - nVal );
+ // --> OD 2006-08-16 #i68520#
+ if ( nHeight - nVal != 0 )
+ {
+ InvalidateObjRectWithSpaces();
+ }
+ // <--
+ nHeight = (Prt().*fnRect->fnGetHeight)();
+ (Prt().*fnRect->fnSetHeight)( nHeight - nVal );
+ _InvalidatePos();
+ InvalidateSize();
+ ::Notify( this, FindPageFrm(), aOld );
+ NotifyDrawObj();
+ if ( GetAnchorFrm()->IsInFly() )
+ AnchorFrm()->FindFlyFrm()->Shrink( nDist, bTst );
+ }
+ return 0L;
+ }
+
+ if ( !bTst )
+ {
+ const SwRect aOld( GetObjRectWithSpaces() );
+ _InvalidateSize();
+ const sal_Bool bOldLocked = bLocked;
+ Unlock();
+ if ( IsFlyFreeFrm() )
+ {
+ // --> OD 2004-11-12 #i37068# - no format of position here
+ // and prevent move in method <CheckClip(..)>.
+ // This is needed to prevent layout loop caused by nested
+ // Writer fly frames - inner Writer fly frames format its
+ // anchor, which grows/shrinks the outer Writer fly frame.
+ // Note: position will be invalidated below.
+ bValidPos = sal_True;
+ // --> OD 2005-10-10 #i55416#
+ // Suppress format of width for autowidth frame, because the
+ // format of the width would call <SwTxtFrm::CalcFitToContent()>
+ // for the lower frame, which initiated this shrink.
+ const sal_Bool bOldFormatHeightOnly = bFormatHeightOnly;
+ const SwFmtFrmSize& rFrmSz = GetFmt()->GetFrmSize();
+ if ( rFrmSz.GetWidthSizeType() != ATT_FIX_SIZE )
+ {
+ bFormatHeightOnly = sal_True;
+ }
+ // <--
+ static_cast<SwFlyFreeFrm*>(this)->SetNoMoveOnCheckClip( true );
+ ((SwFlyFreeFrm*)this)->SwFlyFreeFrm::MakeAll();
+ static_cast<SwFlyFreeFrm*>(this)->SetNoMoveOnCheckClip( false );
+ // --> OD 2005-10-10 #i55416#
+ if ( rFrmSz.GetWidthSizeType() != ATT_FIX_SIZE )
+ {
+ bFormatHeightOnly = bOldFormatHeightOnly;
+ }
+ // <--
+ // <--
+ }
+ else
+ MakeAll();
+ _InvalidateSize();
+ InvalidatePos();
+ if ( bOldLocked )
+ Lock();
+ const SwRect aNew( GetObjRectWithSpaces() );
+ if ( aOld != aNew )
+ {
+ ::Notify( this, FindPageFrm(), aOld );
+ if ( GetAnchorFrm()->IsInFly() )
+ AnchorFrm()->FindFlyFrm()->Shrink( nDist, bTst );
+ }
+ return (aOld.*fnRect->fnGetHeight)() -
+ (aNew.*fnRect->fnGetHeight)();
+ }
+ return nVal;
+ }
+ return 0L;
+}
+
+/*************************************************************************
+|*
+|* SwFlyFrm::ChgSize()
+|*
+|*************************************************************************/
+
+Size SwFlyFrm::ChgSize( const Size& aNewSize )
+{
+ // --> OD 2006-01-19 #i53298#
+ // If the fly frame anchored at-paragraph or at-character contains an OLE
+ // object, assure that the new size fits into the current clipping area
+ // of the fly frame
+ Size aAdjustedNewSize( aNewSize );
+ {
+ if ( dynamic_cast<SwFlyAtCntFrm*>(this) &&
+ Lower() && dynamic_cast<SwNoTxtFrm*>(Lower()) &&
+ static_cast<SwNoTxtFrm*>(Lower())->GetNode()->GetOLENode() )
+ {
+ SwRect aClipRect;
+ ::CalcClipRect( GetVirtDrawObj(), aClipRect, sal_False );
+ if ( aAdjustedNewSize.Width() > aClipRect.Width() )
+ {
+ aAdjustedNewSize.setWidth( aClipRect.Width() );
+ }
+ if ( aAdjustedNewSize.Height() > aClipRect.Height() )
+ {
+ aAdjustedNewSize.setWidth( aClipRect.Height() );
+ }
+ }
+ }
+ // <--
+ if ( aAdjustedNewSize != Frm().SSize() )
+ {
+ SwFrmFmt *pFmt = GetFmt();
+ SwFmtFrmSize aSz( pFmt->GetFrmSize() );
+ aSz.SetWidth( aAdjustedNewSize.Width() );
+ // --> OD 2006-01-19 #i53298# - no tolerance any more.
+ // If it reveals that the tolerance is still needed, then suppress a
+ // <SetAttr> call, if <aSz> equals the current <SwFmtFrmSize> attribute.
+// if ( Abs(aAdjustedNewSize.Height() - aSz.GetHeight()) > 1 )
+ aSz.SetHeight( aAdjustedNewSize.Height() );
+ // <--
+ // uebers Doc fuers Undo!
+ pFmt->GetDoc()->SetAttr( aSz, *pFmt );
+ return aSz.GetSize();
+ }
+ else
+ return Frm().SSize();
+}
+
+/*************************************************************************
+|*
+|* SwFlyFrm::IsLowerOf()
+|*
+|*************************************************************************/
+
+sal_Bool SwFlyFrm::IsLowerOf( const SwLayoutFrm* pUpperFrm ) const
+{
+ OSL_ENSURE( GetAnchorFrm(), "8-( Fly is lost in Space." );
+ const SwFrm* pFrm = GetAnchorFrm();
+ do
+ {
+ if ( pFrm == pUpperFrm )
+ return sal_True;
+ pFrm = pFrm->IsFlyFrm()
+ ? ((const SwFlyFrm*)pFrm)->GetAnchorFrm()
+ : pFrm->GetUpper();
+ } while ( pFrm );
+ return sal_False;
+}
+
+/*************************************************************************
+|*
+|* SwFlyFrm::Cut()
+|*
+|*************************************************************************/
+
+void SwFlyFrm::Cut()
+{
+}
+
+/*************************************************************************
+|*
+|* SwFrm::AppendFly(), RemoveFly()
+|*
+|*************************************************************************/
+
+void SwFrm::AppendFly( SwFlyFrm *pNew )
+{
+ if ( !pDrawObjs )
+ pDrawObjs = new SwSortedObjs();
+ pDrawObjs->Insert( *pNew );
+ pNew->ChgAnchorFrm( this );
+
+ //Bei der Seite anmelden; kann sein, dass noch keine da ist - die
+ //Anmeldung wird dann in SwPageFrm::PreparePage durch gefuehrt.
+ SwPageFrm *pPage = FindPageFrm();
+ if ( pPage )
+ {
+ if ( pNew->IsFlyAtCntFrm() && pNew->Frm().Top() == WEIT_WECH )
+ {
+ //Versuch die Seitenformatierung von neuen Dokumenten etwas
+ //guenstiger zu gestalten.
+ //Wir haengen die Flys erstenmal nach hinten damit sie bei heftigem
+ //Fluss der Anker nicht unoetig oft formatiert werden.
+ //Damit man noch brauchbar an das Ende des Dokumentes springen
+ //kann werden die Flys nicht ganz an das Ende gehaengt.
+ SwRootFrm *pRoot = (SwRootFrm*)pPage->GetUpper();
+ if( !SwLayHelper::CheckPageFlyCache( pPage, pNew ) )
+ {
+ SwPageFrm *pTmp = pRoot->GetLastPage();
+ if ( pTmp->GetPhyPageNum() > 30 )
+ {
+ for ( sal_uInt16 i = 0; i < 10; ++i )
+ {
+ pTmp = (SwPageFrm*)pTmp->GetPrev();
+ if( pTmp->GetPhyPageNum() <= pPage->GetPhyPageNum() )
+ break; // damit wir nicht vor unserem Anker landen
+ }
+ if ( pTmp->IsEmptyPage() )
+ pTmp = (SwPageFrm*)pTmp->GetPrev();
+ pPage = pTmp;
+ }
+ }
+ pPage->AppendFlyToPage( pNew );
+ }
+ else
+ pPage->AppendFlyToPage( pNew );
+ }
+}
+
+void SwFrm::RemoveFly( SwFlyFrm *pToRemove )
+{
+ //Bei der Seite Abmelden - kann schon passiert sein weil die Seite
+ //bereits destruiert wurde.
+ SwPageFrm *pPage = pToRemove->FindPageFrm();
+ if ( pPage && pPage->GetSortedObjs() )
+ {
+ pPage->RemoveFlyFromPage( pToRemove );
+ }
+ // --> OD 2008-05-19 #i73201#
+ else
+ {
+ if ( pToRemove->IsAccessibleFrm() &&
+ pToRemove->GetFmt() &&
+ !pToRemove->IsFlyInCntFrm() )
+ {
+ SwRootFrm *pRootFrm = getRootFrm();
+ if( pRootFrm && pRootFrm->IsAnyShellAccessible() )
+ {
+ ViewShell *pVSh = pRootFrm->GetCurrShell();
+ if( pVSh && pVSh->Imp() )
+ {
+ pVSh->Imp()->DisposeAccessibleFrm( pToRemove );
+ }
+ }
+ }
+ }
+ // <--
+
+ pDrawObjs->Remove( *pToRemove );
+ if ( !pDrawObjs->Count() )
+ DELETEZ( pDrawObjs );
+
+ pToRemove->ChgAnchorFrm( 0 );
+
+ if ( !pToRemove->IsFlyInCntFrm() && GetUpper() && IsInTab() )//MA_FLY_HEIGHT
+ GetUpper()->InvalidateSize();
+}
+
+/*************************************************************************
+|*
+|* SwFrm::AppendDrawObj(), RemoveDrawObj()
+|*
+|* --> OD 2004-07-06 #i28701# - new methods
+|*
+|*************************************************************************/
+void SwFrm::AppendDrawObj( SwAnchoredObject& _rNewObj )
+{
+ if ( !_rNewObj.ISA(SwAnchoredDrawObject) )
+ {
+ OSL_FAIL( "SwFrm::AppendDrawObj(..) - anchored object of unexcepted type -> object not appended" );
+ return;
+ }
+
+ if ( !_rNewObj.GetDrawObj()->ISA(SwDrawVirtObj) &&
+ _rNewObj.GetAnchorFrm() && _rNewObj.GetAnchorFrm() != this )
+ {
+ // perform disconnect from layout, if 'master' drawing object is appended
+ // to a new frame.
+ static_cast<SwDrawContact*>(::GetUserCall( _rNewObj.GetDrawObj() ))->
+ DisconnectFromLayout( false );
+ }
+
+ if ( _rNewObj.GetAnchorFrm() != this )
+ {
+ if ( !pDrawObjs )
+ pDrawObjs = new SwSortedObjs();
+ pDrawObjs->Insert( _rNewObj );
+ _rNewObj.ChgAnchorFrm( this );
+ }
+
+ // --> OD 2010-09-14 #i113730#
+ // Assure the control objects and group objects containing controls are on the control layer
+ if ( ::CheckControlLayer( _rNewObj.DrawObj() ) )
+ {
+ const IDocumentDrawModelAccess* pIDDMA = getIDocumentDrawModelAccess();
+ const SdrLayerID aCurrentLayer(_rNewObj.DrawObj()->GetLayer());
+ const SdrLayerID aControlLayerID(pIDDMA->GetControlsId());
+ const SdrLayerID aInvisibleControlLayerID(pIDDMA->GetInvisibleControlsId());
+
+ if(aCurrentLayer != aControlLayerID && aCurrentLayer != aInvisibleControlLayerID)
+ {
+ if ( aCurrentLayer == pIDDMA->GetInvisibleHellId() ||
+ aCurrentLayer == pIDDMA->GetInvisibleHeavenId() )
+ {
+ _rNewObj.DrawObj()->SetLayer(aInvisibleControlLayerID);
+ }
+ else
+ {
+ _rNewObj.DrawObj()->SetLayer(aControlLayerID);
+ }
+ }
+ }
+ // <--
+
+ // no direct positioning needed, but invalidate the drawing object position
+ _rNewObj.InvalidateObjPos();
+
+ // register at page frame
+ SwPageFrm* pPage = FindPageFrm();
+ if ( pPage )
+ {
+ pPage->AppendDrawObjToPage( _rNewObj );
+ }
+
+ // Notify accessible layout.
+ ViewShell* pSh = getRootFrm()->GetCurrShell();
+ if( pSh )
+ {
+ SwRootFrm* pLayout = getRootFrm();
+ if( pLayout && pLayout->IsAnyShellAccessible() )
+ pSh->Imp()->AddAccessibleObj( _rNewObj.GetDrawObj() );
+ }
+}
+
+void SwFrm::RemoveDrawObj( SwAnchoredObject& _rToRemoveObj )
+{
+ // Notify accessible layout.
+ ViewShell* pSh = getRootFrm()->GetCurrShell();
+ if( pSh )
+ {
+ SwRootFrm* pLayout = getRootFrm();
+ if( pLayout && pLayout->IsAnyShellAccessible() )
+ pSh->Imp()->DisposeAccessibleObj( _rToRemoveObj.GetDrawObj() );
+ }
+
+ // deregister from page frame
+ SwPageFrm* pPage = _rToRemoveObj.GetPageFrm();
+ if ( pPage && pPage->GetSortedObjs() )
+ pPage->RemoveDrawObjFromPage( _rToRemoveObj );
+
+ pDrawObjs->Remove( _rToRemoveObj );
+ if ( !pDrawObjs->Count() )
+ DELETEZ( pDrawObjs );
+
+ _rToRemoveObj.ChgAnchorFrm( 0 );
+}
+
+/*************************************************************************
+|*
+|* SwFrm::InvalidateObjs()
+|*
+|*************************************************************************/
+// --> OD 2004-07-01 #i28701# - change purpose of method and adjust its name
+void SwFrm::InvalidateObjs( const bool _bInvaPosOnly,
+ const bool _bNoInvaOfAsCharAnchoredObjs )
+{
+ if ( GetDrawObjs() )
+ {
+ // --> OD 2004-10-08 #i26945# - determine page the frame is on,
+ // in order to check, if anchored object is registered at the same
+ // page.
+ const SwPageFrm* pPageFrm = FindPageFrm();
+ // <--
+ // --> OD 2004-07-01 #i28701# - re-factoring
+ sal_uInt32 i = 0;
+ for ( ; i < GetDrawObjs()->Count(); ++i )
+ {
+ SwAnchoredObject* pAnchoredObj = (*GetDrawObjs())[i];
+ if ( _bNoInvaOfAsCharAnchoredObjs &&
+ (pAnchoredObj->GetFrmFmt().GetAnchor().GetAnchorId()
+ == FLY_AS_CHAR) )
+ {
+ continue;
+ }
+ // --> OD 2004-10-08 #i26945# - no invalidation, if anchored object
+ // isn't registered at the same page and instead is registered at
+ // the page, where its anchor character text frame is on.
+ if ( pAnchoredObj->GetPageFrm() &&
+ pAnchoredObj->GetPageFrm() != pPageFrm )
+ {
+ SwTxtFrm* pAnchorCharFrm = pAnchoredObj->FindAnchorCharFrm();
+ if ( pAnchorCharFrm &&
+ pAnchoredObj->GetPageFrm() == pAnchorCharFrm->FindPageFrm() )
+ {
+ continue;
+ }
+ // --> OD 2004-11-24 #115759# - unlock its position, if anchored
+ // object isn't registered at the page, where its anchor
+ // character text frame is on, respectively if it has no
+ // anchor character text frame.
+ else
+ {
+ pAnchoredObj->UnlockPosition();
+ }
+ // <--
+ }
+ // <--
+ // --> OD 2005-07-18 #i51474# - reset flag, that anchored object
+ // has cleared environment, and unlock its position, if the anchored
+ // object is registered at the same page as the anchor frame is on.
+ if ( pAnchoredObj->ClearedEnvironment() &&
+ pAnchoredObj->GetPageFrm() &&
+ pAnchoredObj->GetPageFrm() == pPageFrm )
+ {
+ pAnchoredObj->UnlockPosition();
+ pAnchoredObj->SetClearedEnvironment( false );
+ }
+ // <--
+ // distinguish between writer fly frames and drawing objects
+ if ( pAnchoredObj->ISA(SwFlyFrm) )
+ {
+ SwFlyFrm* pFly = static_cast<SwFlyFrm*>(pAnchoredObj);
+ pFly->_Invalidate();
+ pFly->_InvalidatePos();
+ if ( !_bInvaPosOnly )
+ pFly->_InvalidateSize();
+ }
+ else
+ {
+ pAnchoredObj->InvalidateObjPos();
+ } // end of distinction between writer fly frames and drawing objects
+
+ } // end of loop on objects, which are connected to the frame
+ }
+}
+
+/*************************************************************************
+|*
+|* SwLayoutFrm::NotifyLowerObjs()
+|*
+|*************************************************************************/
+// --> OD 2004-07-01 #i28701# - change purpose of method and its name
+// --> OD 2004-10-08 #i26945# - correct check, if anchored object is a lower
+// of the layout frame. E.g., anchor character text frame can be a follow text
+// frame.
+// --> OD 2005-03-11 #i44016# - add parameter <_bUnlockPosOfObjs> to
+// force an unlockposition call for the lower objects.
+void SwLayoutFrm::NotifyLowerObjs( const bool _bUnlockPosOfObjs )
+{
+ // invalidate lower floating screen objects
+ SwPageFrm* pPageFrm = FindPageFrm();
+ if ( pPageFrm && pPageFrm->GetSortedObjs() )
+ {
+ SwSortedObjs& rObjs = *(pPageFrm->GetSortedObjs());
+ for ( sal_uInt32 i = 0; i < rObjs.Count(); ++i )
+ {
+ SwAnchoredObject* pObj = rObjs[i];
+ // --> OD 2004-10-08 #i26945# - check, if anchored object is a lower
+ // of the layout frame is changed to check, if its anchor frame
+ // is a lower of the layout frame.
+ // determine the anchor frame - usually it's the anchor frame,
+ // for at-character/as-character anchored objects the anchor character
+ // text frame is taken.
+ const SwFrm* pAnchorFrm = pObj->GetAnchorFrmContainingAnchPos();
+ // <--
+ if ( pObj->ISA(SwFlyFrm) )
+ {
+ SwFlyFrm* pFly = static_cast<SwFlyFrm*>(pObj);
+
+ if ( pFly->Frm().Left() == WEIT_WECH )
+ continue;
+
+ if ( pFly->IsAnLower( this ) )
+ continue;
+
+ // --> OD 2004-10-08 #i26945# - use <pAnchorFrm> to check, if
+ // fly frame is lower of layout frame resp. if fly frame is
+ // at a different page registered as its anchor frame is on.
+ const bool bLow = IsAnLower( pAnchorFrm );
+ if ( bLow || pAnchorFrm->FindPageFrm() != pPageFrm )
+ // <--
+ {
+ pFly->_Invalidate( pPageFrm );
+ if ( !bLow || pFly->IsFlyAtCntFrm() )
+ {
+ // --> OD 2005-03-11 #i44016#
+ if ( _bUnlockPosOfObjs )
+ {
+ pFly->UnlockPosition();
+ }
+ // <--
+ pFly->_InvalidatePos();
+ }
+ else
+ pFly->_InvalidatePrt();
+ }
+ }
+ else
+ {
+ OSL_ENSURE( pObj->ISA(SwAnchoredDrawObject),
+ "<SwLayoutFrm::NotifyFlys() - anchored object of unexcepted type" );
+ // --> OD 2004-10-08 #i26945# - use <pAnchorFrm> to check, if
+ // fly frame is lower of layout frame resp. if fly frame is
+ // at a different page registered as its anchor frame is on.
+ if ( IsAnLower( pAnchorFrm ) ||
+ pAnchorFrm->FindPageFrm() != pPageFrm )
+ // <--
+ {
+ // --> OD 2005-03-11 #i44016#
+ if ( _bUnlockPosOfObjs )
+ {
+ pObj->UnlockPosition();
+ }
+ // <--
+ pObj->InvalidateObjPos();
+ }
+ }
+ }
+ }
+}
+
+/*************************************************************************
+|*
+|* SwFlyFrm::NotifyDrawObj()
+|*
+|*************************************************************************/
+
+void SwFlyFrm::NotifyDrawObj()
+{
+ SwVirtFlyDrawObj* pObj = GetVirtDrawObj();
+ pObj->SetRect();
+ pObj->SetRectsDirty();
+ pObj->SetChanged();
+ pObj->BroadcastObjectChange();
+ if ( GetFmt()->GetSurround().IsContour() )
+ ClrContourCache( pObj );
+}
+
+/*************************************************************************
+|*
+|* SwFlyFrm::CalcRel()
+|*
+|*************************************************************************/
+
+Size SwFlyFrm::CalcRel( const SwFmtFrmSize &rSz ) const
+{
+ Size aRet( rSz.GetSize() );
+
+ const SwFrm *pRel = IsFlyLayFrm() ? GetAnchorFrm() : GetAnchorFrm()->GetUpper();
+ if( pRel ) // LAYER_IMPL
+ {
+ long nRelWidth = LONG_MAX, nRelHeight = LONG_MAX;
+ const ViewShell *pSh = getRootFrm()->GetCurrShell();
+ if ( ( pRel->IsBodyFrm() || pRel->IsPageFrm() ) &&
+ pSh && pSh->GetViewOptions()->getBrowseMode() &&
+ pSh->VisArea().HasArea() )
+ {
+ nRelWidth = pSh->GetBrowseWidth();
+ nRelHeight = pSh->VisArea().Height();
+ Size aBorder = pSh->GetOut()->PixelToLogic( pSh->GetBrowseBorder() );
+ long nDiff = nRelWidth - pRel->Prt().Width();
+ if ( nDiff > 0 )
+ nRelWidth -= nDiff;
+ nRelHeight -= 2*aBorder.Height();
+ nDiff = nRelHeight - pRel->Prt().Height();
+ if ( nDiff > 0 )
+ nRelHeight -= nDiff;
+ }
+ nRelWidth = Min( nRelWidth, pRel->Prt().Width() );
+ nRelHeight = Min( nRelHeight, pRel->Prt().Height() );
+ if( !pRel->IsPageFrm() )
+ {
+ const SwPageFrm* pPage = FindPageFrm();
+ if( pPage )
+ {
+ nRelWidth = Min( nRelWidth, pPage->Prt().Width() );
+ nRelHeight = Min( nRelHeight, pPage->Prt().Height() );
+ }
+ }
+
+ if ( rSz.GetWidthPercent() && rSz.GetWidthPercent() != 0xFF )
+ aRet.Width() = nRelWidth * rSz.GetWidthPercent() / 100;
+ if ( rSz.GetHeightPercent() && rSz.GetHeightPercent() != 0xFF )
+ aRet.Height() = nRelHeight * rSz.GetHeightPercent() / 100;
+
+ if ( rSz.GetWidthPercent() == 0xFF )
+ {
+ aRet.Width() *= aRet.Height();
+ aRet.Width() /= rSz.GetHeight();
+ }
+ else if ( rSz.GetHeightPercent() == 0xFF )
+ {
+ aRet.Height() *= aRet.Width();
+ aRet.Height() /= rSz.GetWidth();
+ }
+ }
+ return aRet;
+}
+
+/*************************************************************************
+|*
+|* SwFlyFrm::CalcAutoWidth()
+|*
+|*************************************************************************/
+
+SwTwips lcl_CalcAutoWidth( const SwLayoutFrm& rFrm )
+{
+ SwTwips nRet = 0;
+ SwTwips nMin = 0;
+ const SwFrm* pFrm = rFrm.Lower();
+
+ // No autowidth defined for columned frames
+ if ( !pFrm || pFrm->IsColumnFrm() )
+ return nRet;
+
+ while ( pFrm )
+ {
+ if ( pFrm->IsSctFrm() )
+ {
+ nMin = lcl_CalcAutoWidth( *(SwSectionFrm*)pFrm );
+ }
+ if ( pFrm->IsTxtFrm() )
+ {
+ nMin = ((SwTxtFrm*)pFrm)->CalcFitToContent();
+ const SvxLRSpaceItem &rSpace =
+ ((SwTxtFrm*)pFrm)->GetTxtNode()->GetSwAttrSet().GetLRSpace();
+ nMin += rSpace.GetRight() + rSpace.GetTxtLeft() + rSpace.GetTxtFirstLineOfst();
+ }
+ else if ( pFrm->IsTabFrm() )
+ {
+ const SwFmtFrmSize& rTblFmtSz = ((SwTabFrm*)pFrm)->GetTable()->GetFrmFmt()->GetFrmSize();
+ if ( USHRT_MAX == rTblFmtSz.GetSize().Width() ||
+ text::HoriOrientation::NONE == ((SwTabFrm*)pFrm)->GetFmt()->GetHoriOrient().GetHoriOrient() )
+ {
+ const SwPageFrm* pPage = rFrm.FindPageFrm();
+ // auto width table
+ nMin = pFrm->GetUpper()->IsVertical() ?
+ pPage->Prt().Height() :
+ pPage->Prt().Width();
+ }
+ else
+ {
+ nMin = rTblFmtSz.GetSize().Width();
+ }
+ }
+
+ if ( nMin > nRet )
+ nRet = nMin;
+
+ pFrm = pFrm->GetNext();
+ }
+
+ return nRet;
+}
+
+SwTwips SwFlyFrm::CalcAutoWidth() const
+{
+ return lcl_CalcAutoWidth( *this );
+}
+
+/*************************************************************************
+|*
+|* SwFlyFrm::GetContour()
+|*
+|*************************************************************************/
+/// OD 16.04.2003 #i13147# - If called for paint and the <SwNoTxtFrm> contains
+/// a graphic, load of intrinsic graphic has to be avoided.
+sal_Bool SwFlyFrm::GetContour( PolyPolygon& rContour,
+ const sal_Bool _bForPaint ) const
+{
+ sal_Bool bRet = sal_False;
+ if( GetFmt()->GetSurround().IsContour() && Lower() &&
+ Lower()->IsNoTxtFrm() )
+ {
+ SwNoTxtNode *pNd = (SwNoTxtNode*)((SwCntntFrm*)Lower())->GetNode();
+ // OD 16.04.2003 #i13147# - determine <GraphicObject> instead of <Graphic>
+ // in order to avoid load of graphic, if <SwNoTxtNode> contains a graphic
+ // node and method is called for paint.
+ const GraphicObject* pGrfObj = NULL;
+ sal_Bool bGrfObjCreated = sal_False;
+ const SwGrfNode* pGrfNd = pNd->GetGrfNode();
+ if ( pGrfNd && _bForPaint )
+ {
+ pGrfObj = &(pGrfNd->GetGrfObj());
+ }
+ else
+ {
+ pGrfObj = new GraphicObject( pNd->GetGraphic() );
+ bGrfObjCreated = sal_True;
+ }
+ OSL_ENSURE( pGrfObj, "SwFlyFrm::GetContour() - No Graphic/GraphicObject found at <SwNoTxtNode>." );
+ if ( pGrfObj && pGrfObj->GetType() != GRAPHIC_NONE )
+ {
+ if( !pNd->HasContour() )
+ {
+ // OD 16.04.2003 #i13147# - no <CreateContour> for a graphic
+ // during paint. Thus, return (value of <bRet> should be <sal_False>).
+ if ( pGrfNd && _bForPaint )
+ {
+ OSL_FAIL( "SwFlyFrm::GetContour() - No Contour found at <SwNoTxtNode> during paint." );
+ return bRet;
+ }
+ pNd->CreateContour();
+ }
+ pNd->GetContour( rContour );
+ //Der Node haelt das Polygon passend zur Originalgroesse der Grafik
+ //hier muss die Skalierung einkalkuliert werden.
+ SwRect aClip;
+ SwRect aOrig;
+ Lower()->Calc();
+ ((SwNoTxtFrm*)Lower())->GetGrfArea( aClip, &aOrig, sal_False );
+ // OD 16.04.2003 #i13147# - copy method code <SvxContourDlg::ScaleContour(..)>
+ // in order to avoid that graphic has to be loaded for contour scale.
+ //SvxContourDlg::ScaleContour( rContour, aGrf, MAP_TWIP, aOrig.SSize() );
+ {
+ OutputDevice* pOutDev = Application::GetDefaultDevice();
+ const MapMode aDispMap( MAP_TWIP );
+ const MapMode aGrfMap( pGrfObj->GetPrefMapMode() );
+ const Size aGrfSize( pGrfObj->GetPrefSize() );
+ Size aOrgSize;
+ Point aNewPoint;
+ sal_Bool bPixelMap = aGrfMap.GetMapUnit() == MAP_PIXEL;
+
+ if ( bPixelMap )
+ aOrgSize = pOutDev->PixelToLogic( aGrfSize, aDispMap );
+ else
+ aOrgSize = pOutDev->LogicToLogic( aGrfSize, aGrfMap, aDispMap );
+
+ if ( aOrgSize.Width() && aOrgSize.Height() )
+ {
+ double fScaleX = (double) aOrig.Width() / aOrgSize.Width();
+ double fScaleY = (double) aOrig.Height() / aOrgSize.Height();
+
+ for ( sal_uInt16 j = 0, nPolyCount = rContour.Count(); j < nPolyCount; j++ )
+ {
+ Polygon& rPoly = rContour[ j ];
+
+ for ( sal_uInt16 i = 0, nCount = rPoly.GetSize(); i < nCount; i++ )
+ {
+ if ( bPixelMap )
+ aNewPoint = pOutDev->PixelToLogic( rPoly[ i ], aDispMap );
+ else
+ aNewPoint = pOutDev->LogicToLogic( rPoly[ i ], aGrfMap, aDispMap );
+
+ rPoly[ i ] = Point( FRound( aNewPoint.X() * fScaleX ), FRound( aNewPoint.Y() * fScaleY ) );
+ }
+ }
+ }
+ }
+ // OD 17.04.2003 #i13147# - destroy created <GraphicObject>.
+ if ( bGrfObjCreated )
+ {
+ delete pGrfObj;
+ }
+ rContour.Move( aOrig.Left(), aOrig.Top() );
+ if( !aClip.Width() )
+ aClip.Width( 1 );
+ if( !aClip.Height() )
+ aClip.Height( 1 );
+ rContour.Clip( aClip.SVRect() );
+ rContour.Optimize(POLY_OPTIMIZE_CLOSE);
+ bRet = sal_True;
+ }
+ }
+ return bRet;
+}
+
+// OD 2004-03-25 #i26791#
+const SwVirtFlyDrawObj* SwFlyFrm::GetVirtDrawObj() const
+{
+ return static_cast<const SwVirtFlyDrawObj*>(GetDrawObj());
+}
+SwVirtFlyDrawObj* SwFlyFrm::GetVirtDrawObj()
+{
+ return static_cast<SwVirtFlyDrawObj*>(DrawObj());
+}
+
+// =============================================================================
+// OD 2004-03-24 #i26791# - implementation of pure virtual method declared in
+// base class <SwAnchoredObject>
+// =============================================================================
+void SwFlyFrm::InvalidateObjPos()
+{
+ InvalidatePos();
+ // --> OD 2006-08-10 #i68520#
+ InvalidateObjRectWithSpaces();
+ // <--
+}
+
+SwFrmFmt& SwFlyFrm::GetFrmFmt()
+{
+ OSL_ENSURE( GetFmt(),
+ "<SwFlyFrm::GetFrmFmt()> - missing frame format -> crash." );
+ return *GetFmt();
+}
+const SwFrmFmt& SwFlyFrm::GetFrmFmt() const
+{
+ OSL_ENSURE( GetFmt(),
+ "<SwFlyFrm::GetFrmFmt()> - missing frame format -> crash." );
+ return *GetFmt();
+}
+
+const SwRect SwFlyFrm::GetObjRect() const
+{
+ return Frm();
+}
+
+// --> OD 2006-10-05 #i70122#
+// for Writer fly frames the bounding rectangle equals the object rectangles
+const SwRect SwFlyFrm::GetObjBoundRect() const
+{
+ return GetObjRect();
+}
+// <--
+
+// --> OD 2006-08-10 #i68520#
+bool SwFlyFrm::_SetObjTop( const SwTwips _nTop )
+{
+ const bool bChanged( Frm().Pos().Y() != _nTop );
+
+ Frm().Pos().Y() = _nTop;
+
+ return bChanged;
+}
+bool SwFlyFrm::_SetObjLeft( const SwTwips _nLeft )
+{
+ const bool bChanged( Frm().Pos().X() != _nLeft );
+
+ Frm().Pos().X() = _nLeft;
+
+ return bChanged;
+}
+// <--
+
+/** method to assure that anchored object is registered at the correct
+ page frame
+
+ OD 2004-07-02 #i28701#
+
+ @author OD
+*/
+void SwFlyFrm::RegisterAtCorrectPage()
+{
+ // default behaviour is to do nothing.
+}
+
+/** method to determine, if a <MakeAll()> on the Writer fly frame is possible
+
+ OD 2004-05-11 #i28701#
+
+ @author OD
+*/
+bool SwFlyFrm::IsFormatPossible() const
+{
+ return SwAnchoredObject::IsFormatPossible() &&
+ !IsLocked() && !IsColLocked();
+}
+
+void SwFlyFrm::GetAnchoredObjects( std::list<SwAnchoredObject*>& aList, const SwFmt& rFmt )
+{
+ SwIterator<SwFlyFrm,SwFmt> aIter( rFmt );
+ for( SwFlyFrm* pFlyFrm = aIter.First(); pFlyFrm; pFlyFrm = aIter.Next() )
+ aList.push_back( pFlyFrm );
+}
+
+const SwFlyFrmFmt * SwFlyFrm::GetFmt() const
+{
+ return static_cast< const SwFlyFrmFmt * >( GetDep() );
+}
+
+SwFlyFrmFmt * SwFlyFrm::GetFmt()
+{
+ return static_cast< SwFlyFrmFmt * >( GetDep() );
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/layout/flycnt.cxx b/sw/source/core/layout/flycnt.cxx
new file mode 100644
index 000000000000..7db5677f7403
--- /dev/null
+++ b/sw/source/core/layout/flycnt.cxx
@@ -0,0 +1,1541 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+#include <tools/bigint.hxx>
+#include "pagefrm.hxx"
+#include "cntfrm.hxx"
+#include "flyfrm.hxx"
+#include "txtfrm.hxx"
+#include <doc.hxx>
+#include <IDocumentUndoRedo.hxx>
+#include "viewsh.hxx"
+#include "viewimp.hxx"
+#include "pam.hxx"
+#include "frmfmt.hxx"
+#include "frmtool.hxx"
+#include "dflyobj.hxx"
+#include "hints.hxx"
+#include "ndtxt.hxx"
+#include "swundo.hxx"
+#include <editeng/ulspitem.hxx>
+#include <editeng/lrspitem.hxx>
+#include <fmtanchr.hxx>
+#include <fmtornt.hxx>
+#include <fmtfsize.hxx>
+#include <fmtsrnd.hxx>
+
+#include "tabfrm.hxx"
+#include "flyfrms.hxx"
+#include "crstate.hxx"
+#include "sectfrm.hxx"
+
+#include <tocntntanchoredobjectposition.hxx>
+#include <dcontact.hxx>
+#include <sortedobjs.hxx>
+#include <layouter.hxx>
+#include <objectformattertxtfrm.hxx>
+#include <HandleAnchorNodeChg.hxx>
+
+using namespace ::com::sun::star;
+
+
+/*************************************************************************
+|*
+|* SwFlyAtCntFrm::SwFlyAtCntFrm()
+|*
+|*************************************************************************/
+
+SwFlyAtCntFrm::SwFlyAtCntFrm( SwFlyFrmFmt *pFmt, SwFrm* pSib, SwFrm *pAnch ) :
+ SwFlyFreeFrm( pFmt, pSib, pAnch )
+{
+ bAtCnt = sal_True;
+ bAutoPosition = (FLY_AT_CHAR == pFmt->GetAnchor().GetAnchorId());
+}
+
+// #i28701#
+TYPEINIT1(SwFlyAtCntFrm,SwFlyFreeFrm);
+/*************************************************************************
+|*
+|* SwFlyAtCntFrm::Modify()
+|*
+|*************************************************************************/
+
+void SwFlyAtCntFrm::Modify( const SfxPoolItem* pOld, const SfxPoolItem *pNew )
+{
+ sal_uInt16 nWhich = pNew ? pNew->Which() : 0;
+ const SwFmtAnchor *pAnch = 0;
+
+ if( RES_ATTRSET_CHG == nWhich && SFX_ITEM_SET ==
+ ((SwAttrSetChg*)pNew)->GetChgSet()->GetItemState( RES_ANCHOR, sal_False,
+ (const SfxPoolItem**)&pAnch ))
+ ; // Beim GetItemState wird der AnkerPointer gesetzt !
+
+ else if( RES_ANCHOR == nWhich )
+ {
+ //Ankerwechsel, ich haenge mich selbst um.
+ //Es darf sich nicht um einen Wechsel des Ankertyps handeln,
+ //dies ist nur ueber die SwFEShell moeglich.
+ pAnch = (const SwFmtAnchor*)pNew;
+ }
+
+ if( pAnch )
+ {
+ OSL_ENSURE( pAnch->GetAnchorId() == GetFmt()->GetAnchor().GetAnchorId(),
+ "Unzulaessiger Wechsel des Ankertyps." );
+
+ //Abmelden, neuen Anker besorgen und 'dranhaengen.
+ SwRect aOld( GetObjRectWithSpaces() );
+ SwPageFrm *pOldPage = FindPageFrm();
+ const SwFrm *pOldAnchor = GetAnchorFrm();
+ SwCntntFrm *pCntnt = (SwCntntFrm*)GetAnchorFrm();
+ AnchorFrm()->RemoveFly( this );
+
+ const sal_Bool bBodyFtn = (pCntnt->IsInDocBody() || pCntnt->IsInFtn());
+
+ //Den neuen Anker anhand des NodeIdx suchen, am alten und
+ //neuen NodeIdx kann auch erkannt werden, in welche Richtung
+ //gesucht werden muss.
+ const SwNodeIndex aNewIdx( pAnch->GetCntntAnchor()->nNode );
+ SwNodeIndex aOldIdx( *pCntnt->GetNode() );
+
+ //fix: Umstellung, ehemals wurde in der do-while-Schleife nach vorn bzw.
+ //nach hinten gesucht; je nachdem wie welcher Index kleiner war.
+ //Das kann aber u.U. zu einer Endlosschleife fuehren. Damit
+ //wenigstens die Schleife unterbunden wird suchen wir nur in eine
+ //Richtung. Wenn der neue Anker nicht gefunden wird koennen wir uns
+ //immer noch vom Node einen Frame besorgen. Die Change, dass dies dann
+ //der richtige ist, ist gut.
+ const bool bNext = aOldIdx < aNewIdx;
+ // consider the case that at found anchor frame candidate already a
+ // fly frame of the given fly format is registered.
+ // consider, that <pCntnt> is the already
+ // the new anchor frame.
+ bool bFound( aOldIdx == aNewIdx );
+ while ( pCntnt && !bFound )
+ {
+ do
+ {
+ if ( bNext )
+ pCntnt = pCntnt->GetNextCntntFrm();
+ else
+ pCntnt = pCntnt->GetPrevCntntFrm();
+ } while ( pCntnt &&
+ !( bBodyFtn == ( pCntnt->IsInDocBody() ||
+ pCntnt->IsInFtn() ) ) );
+ if ( pCntnt )
+ aOldIdx = *pCntnt->GetNode();
+
+ // check, if at found anchor frame candidate already a fly frame
+ // of the given fly frame format is registered.
+ bFound = aOldIdx == aNewIdx;
+ if ( bFound && pCntnt->GetDrawObjs() )
+ {
+ SwFrmFmt* pMyFlyFrmFmt( &GetFrmFmt() );
+ SwSortedObjs &rObjs = *pCntnt->GetDrawObjs();
+ for( sal_uInt16 i = 0; i < rObjs.Count(); ++i)
+ {
+ SwFlyFrm* pFlyFrm = dynamic_cast<SwFlyFrm*>(rObjs[i]);
+ if ( pFlyFrm &&
+ &(pFlyFrm->GetFrmFmt()) == pMyFlyFrmFmt )
+ {
+ bFound = false;
+ break;
+ }
+ }
+ }
+ }
+ if ( !pCntnt )
+ {
+ SwCntntNode *pNode = aNewIdx.GetNode().GetCntntNode();
+ pCntnt = pNode->getLayoutFrm( getRootFrm(), &pOldAnchor->Frm().Pos(), 0, sal_False );
+ OSL_ENSURE( pCntnt, "Neuen Anker nicht gefunden" );
+ }
+ //Flys haengen niemals an einem Follow sondern immer am
+ //Master, den suchen wir uns jetzt.
+ SwCntntFrm* pFlow = pCntnt;
+ while ( pFlow->IsFollow() )
+ pFlow = pFlow->FindMaster();
+ pCntnt = pFlow;
+
+ //und schwupp angehaengt das teil...
+ pCntnt->AppendFly( this );
+ if ( pOldPage && pOldPage != FindPageFrm() )
+ NotifyBackground( pOldPage, aOld, PREP_FLY_LEAVE );
+
+ //Fix(3495)
+ _InvalidatePos();
+ InvalidatePage();
+ SetNotifyBack();
+ // #i28701# - reset member <maLastCharRect> and
+ // <mnLastTopOfLine> for to-character anchored objects.
+ ClearCharRectAndTopOfLine();
+ }
+ else
+ SwFlyFrm::Modify( pOld, pNew );
+}
+
+/*************************************************************************
+|*
+|* SwFlyAtCntFrm::MakeAll()
+|*
+|* Beschreibung Bei einem Absatzgebunden Fly kann es durchaus sein,
+|* das der Anker auf die Veraenderung des Flys reagiert. Auf diese
+|* Reaktion hat der Fly natuerlich auch wieder zu reagieren.
+|* Leider kann dies zu Oszillationen fuehren z.b. Der Fly will nach
+|* unten, dadurch kann der Inhalt nach oben, der TxtFrm wird kleiner,
+|* der Fly muss wieder hoeher woduch der Text wieder nach unten
+|* verdraengt wird...
+|* Um derartige Oszillationen zu vermeiden, wird ein kleiner Positions-
+|* stack aufgebaut. Wenn der Fly ein Position erreicht, die er bereits
+|* einmal einnahm, so brechen wir den Vorgang ab. Um keine Risiken
+|* einzugehen, wird der Positionsstack so aufgebaut, dass er fuenf
+|* Positionen zurueckblickt.
+|* Wenn der Stack ueberlaeuft, wird ebenfalls abgebrochen.
+|* Der Abbruch fuer dazu, dass der Fly am Ende eine unguenste Position
+|* einnimmt. Damit es nicht durch einen wiederholten Aufruf von
+|* Aussen zu einer 'grossen Oszillation' kommen kann wird im Abbruch-
+|* fall das Attribut des Rahmens auf automatische Ausrichtung oben
+|* eingestellt.
+|*
+|*************************************************************************/
+//Wir brauchen ein Paar Hilfsklassen zur Kontrolle der Ozillation und ein paar
+//Funktionen um die Uebersicht zu gewaehrleisten.
+// #i3317# - re-factoring of the position stack
+class SwOszControl
+{
+ static const SwFlyFrm *pStk1;
+ static const SwFlyFrm *pStk2;
+ static const SwFlyFrm *pStk3;
+ static const SwFlyFrm *pStk4;
+ static const SwFlyFrm *pStk5;
+
+ const SwFlyFrm *pFly;
+ // #i3317#
+ sal_uInt8 mnPosStackSize;
+ std::vector<Point*> maObjPositions;
+
+public:
+ SwOszControl( const SwFlyFrm *pFrm );
+ ~SwOszControl();
+ bool ChkOsz();
+ static sal_Bool IsInProgress( const SwFlyFrm *pFly );
+};
+const SwFlyFrm *SwOszControl::pStk1 = 0;
+const SwFlyFrm *SwOszControl::pStk2 = 0;
+const SwFlyFrm *SwOszControl::pStk3 = 0;
+const SwFlyFrm *SwOszControl::pStk4 = 0;
+const SwFlyFrm *SwOszControl::pStk5 = 0;
+
+SwOszControl::SwOszControl( const SwFlyFrm *pFrm )
+ : pFly( pFrm ),
+ // #i3317#
+ mnPosStackSize( 20 )
+{
+ if ( !SwOszControl::pStk1 )
+ SwOszControl::pStk1 = pFly;
+ else if ( !SwOszControl::pStk2 )
+ SwOszControl::pStk2 = pFly;
+ else if ( !SwOszControl::pStk3 )
+ SwOszControl::pStk3 = pFly;
+ else if ( !SwOszControl::pStk4 )
+ SwOszControl::pStk4 = pFly;
+ else if ( !SwOszControl::pStk5 )
+ SwOszControl::pStk5 = pFly;
+}
+
+SwOszControl::~SwOszControl()
+{
+ if ( SwOszControl::pStk1 == pFly )
+ SwOszControl::pStk1 = 0;
+ else if ( SwOszControl::pStk2 == pFly )
+ SwOszControl::pStk2 = 0;
+ else if ( SwOszControl::pStk3 == pFly )
+ SwOszControl::pStk3 = 0;
+ else if ( SwOszControl::pStk4 == pFly )
+ SwOszControl::pStk4 = 0;
+ else if ( SwOszControl::pStk5 == pFly )
+ SwOszControl::pStk5 = 0;
+ // #i3317#
+ while ( !maObjPositions.empty() )
+ {
+ Point* pPos = maObjPositions.back();
+ delete pPos;
+
+ maObjPositions.pop_back();
+ }
+}
+
+sal_Bool SwOszControl::IsInProgress( const SwFlyFrm *pFly )
+{
+ if ( SwOszControl::pStk1 && !pFly->IsLowerOf( SwOszControl::pStk1 ) )
+ return sal_True;
+ if ( SwOszControl::pStk2 && !pFly->IsLowerOf( SwOszControl::pStk2 ) )
+ return sal_True;
+ if ( SwOszControl::pStk3 && !pFly->IsLowerOf( SwOszControl::pStk3 ) )
+ return sal_True;
+ if ( SwOszControl::pStk4 && !pFly->IsLowerOf( SwOszControl::pStk4 ) )
+ return sal_True;
+ if ( SwOszControl::pStk5 && !pFly->IsLowerOf( SwOszControl::pStk5 ) )
+ return sal_True;
+ return sal_False;
+}
+
+bool SwOszControl::ChkOsz()
+{
+ bool bOscillationDetected = false;
+
+ if ( maObjPositions.size() == mnPosStackSize )
+ {
+ // position stack is full -> oscillation
+ bOscillationDetected = true;
+ }
+ else
+ {
+ Point* pNewObjPos = new Point( pFly->GetObjRect().Pos() );
+ for ( std::vector<Point*>::iterator aObjPosIter = maObjPositions.begin();
+ aObjPosIter != maObjPositions.end();
+ ++aObjPosIter )
+ {
+ if ( *(pNewObjPos) == *(*aObjPosIter) )
+ {
+ // position already occurred -> oscillation
+ bOscillationDetected = true;
+ delete pNewObjPos;
+ break;
+ }
+ }
+ if ( !bOscillationDetected )
+ {
+ maObjPositions.push_back( pNewObjPos );
+ }
+ }
+
+ return bOscillationDetected;
+}
+
+void SwFlyAtCntFrm::MakeAll()
+{
+ if ( !GetFmt()->GetDoc()->IsVisibleLayerId( GetVirtDrawObj()->GetLayer() ) )
+ {
+ return;
+ }
+
+ if ( !SwOszControl::IsInProgress( this ) && !IsLocked() && !IsColLocked() )
+ {
+ // #i28701# - use new method <GetPageFrm()>
+ if( !GetPageFrm() && GetAnchorFrm() && GetAnchorFrm()->IsInFly() )
+ {
+ SwFlyFrm* pFly = AnchorFrm()->FindFlyFrm();
+ SwPageFrm *pTmpPage = pFly ? pFly->FindPageFrm() : NULL;
+ if( pTmpPage )
+ pTmpPage->AppendFlyToPage( this );
+ }
+ // #i28701# - use new method <GetPageFrm()>
+ if( GetPageFrm() )
+ {
+ bSetCompletePaintOnInvalidate = sal_True;
+ {
+ SwFlyFrmFmt *pFmt = (SwFlyFrmFmt*)GetFmt();
+ const SwFmtFrmSize &rFrmSz = GetFmt()->GetFrmSize();
+ if( rFrmSz.GetHeightPercent() != 0xFF &&
+ rFrmSz.GetHeightPercent() >= 100 )
+ {
+ pFmt->LockModify();
+ SwFmtSurround aMain( pFmt->GetSurround() );
+ if ( aMain.GetSurround() == SURROUND_NONE )
+ {
+ aMain.SetSurround( SURROUND_THROUGHT );
+ pFmt->SetFmtAttr( aMain );
+ }
+ pFmt->UnlockModify();
+ }
+ }
+
+ SwOszControl aOszCntrl( this );
+
+ // #i43255#
+ // #i50356# - format the anchor frame, which
+ // contains the anchor position. E.g., for at-character anchored
+ // object this can be the follow frame of the anchor frame.
+ const bool bFormatAnchor =
+ !static_cast<const SwTxtFrm*>( GetAnchorFrmContainingAnchPos() )->IsAnyJoinLocked() &&
+ !ConsiderObjWrapInfluenceOnObjPos() &&
+ !ConsiderObjWrapInfluenceOfOtherObjs();
+
+ const SwFrm* pFooter = GetAnchorFrm()->FindFooterOrHeader();
+ if( pFooter && !pFooter->IsFooterFrm() )
+ pFooter = NULL;
+ bool bOsz = false;
+ sal_Bool bExtra = Lower() && Lower()->IsColumnFrm();
+ // #i3317# - boolean, to apply temporarly the
+ // 'straightforward positioning process' for the frame due to its
+ // overlapping with a previous column.
+ bool bConsiderWrapInfluenceDueToOverlapPrevCol( false );
+ // #i35911# - boolean, to apply temporarly the
+ // 'straightforward positioning process' for the frame due to fact
+ // that it causes the complete content of its layout environment
+ // to move forward.
+ // #i40444# - extend usage of this boolean:
+ // apply temporarly the 'straightforward positioning process' for
+ // the frame due to the fact that the frame clears the area for
+ // the anchor frame, thus it has to move forward.
+ bool bConsiderWrapInfluenceDueToMovedFwdAnchor( false );
+ do {
+ SWRECTFN( this )
+ Point aOldPos( (Frm().*fnRect->fnGetPos)() );
+ SwFlyFreeFrm::MakeAll();
+ const bool bPosChgDueToOwnFormat =
+ aOldPos != (Frm().*fnRect->fnGetPos)();
+ // #i3317#
+ if ( !ConsiderObjWrapInfluenceOnObjPos() &&
+ OverlapsPrevColumn() )
+ {
+ bConsiderWrapInfluenceDueToOverlapPrevCol = true;
+ }
+ // #i28701# - no format of anchor frame, if
+ // wrapping style influence is considered on object positioning
+ if ( bFormatAnchor )
+ {
+ SwTxtFrm* pAnchPosAnchorFrm =
+ dynamic_cast<SwTxtFrm*>(GetAnchorFrmContainingAnchPos());
+ OSL_ENSURE( pAnchPosAnchorFrm,
+ "<SwFlyAtCntFrm::MakeAll()> - anchor frame of wrong type -> crash" );
+ // #i58182# - For the usage of new method
+ // <SwObjectFormatterTxtFrm::CheckMovedFwdCondition(..)>
+ // to check move forward of anchor frame due to the object
+ // positioning it's needed to know, if the object is anchored
+ // at the master frame before the anchor frame is formatted.
+ const bool bAnchoredAtMaster( !pAnchPosAnchorFrm->IsFollow() );
+
+ // #i56300#
+ // perform complete format of anchor text frame and its
+ // previous frames, which have become invalid due to the
+ // fly frame format.
+ SwObjectFormatterTxtFrm::FormatAnchorFrmAndItsPrevs( *pAnchPosAnchorFrm );
+ // #i35911#
+ // #i40444#
+ // #i58182# - usage of new method
+ // <SwObjectFormatterTxtFrm::CheckMovedFwdCondition(..)>
+ sal_uInt32 nToPageNum( 0L );
+ bool bDummy( false );
+ if ( SwObjectFormatterTxtFrm::CheckMovedFwdCondition(
+ *this, GetPageFrm()->GetPhyPageNum(),
+ bAnchoredAtMaster, nToPageNum, bDummy ) )
+ {
+ bConsiderWrapInfluenceDueToMovedFwdAnchor = true;
+ // mark anchor text frame
+ // directly, that it is moved forward by object positioning.
+ SwTxtFrm* pAnchorTxtFrm( static_cast<SwTxtFrm*>(AnchorFrm()) );
+ bool bInsert( true );
+ sal_uInt32 nAnchorFrmToPageNum( 0L );
+ const SwDoc& rDoc = *(GetFrmFmt().GetDoc());
+ if ( SwLayouter::FrmMovedFwdByObjPos(
+ rDoc, *pAnchorTxtFrm, nAnchorFrmToPageNum ) )
+ {
+ if ( nAnchorFrmToPageNum < nToPageNum )
+ SwLayouter::RemoveMovedFwdFrm( rDoc, *pAnchorTxtFrm );
+ else
+ bInsert = false;
+ }
+ if ( bInsert )
+ {
+ SwLayouter::InsertMovedFwdFrm( rDoc, *pAnchorTxtFrm,
+ nToPageNum );
+ }
+ }
+ }
+
+ if ( aOldPos != (Frm().*fnRect->fnGetPos)() ||
+ ( !GetValidPosFlag() &&
+ ( pFooter || bPosChgDueToOwnFormat ) ) )
+ {
+ bOsz = aOszCntrl.ChkOsz();
+
+ // special loop prevention for dedicated document:
+ if ( bOsz &&
+ HasFixSize() && IsClipped() &&
+ GetAnchorFrm()->GetUpper()->IsCellFrm() )
+ {
+ SwFrmFmt* pFmt = GetFmt();
+ const SwFmtFrmSize& rFrmSz = pFmt->GetFrmSize();
+ if ( rFrmSz.GetWidthPercent() &&
+ rFrmSz.GetHeightPercent() == 0xFF )
+ {
+ SwFmtSurround aSurround( pFmt->GetSurround() );
+ if ( aSurround.GetSurround() == SURROUND_NONE )
+ {
+ pFmt->LockModify();
+ aSurround.SetSurround( SURROUND_THROUGHT );
+ pFmt->SetFmtAttr( aSurround );
+ pFmt->UnlockModify();
+ bOsz = false;
+#if OSL_DEBUG_LEVEL > 1
+ OSL_FAIL( "<SwFlyAtCntFrm::MakeAll()> - special loop prevention for dedicated document of b6403541 applied" );
+#endif
+ }
+ }
+ }
+ }
+
+ if ( bExtra && Lower() && !Lower()->GetValidPosFlag() )
+ {
+ // Wenn ein mehrspaltiger Rahmen wg. Positionswechsel ungueltige
+ // Spalten hinterlaesst, so drehen wir lieber hier eine weitere
+ // Runde und formatieren unseren Inhalt via FormatWidthCols nochmal.
+ _InvalidateSize();
+ bExtra = sal_False; // Sicherhaltshalber gibt es nur eine Ehrenrunde.
+ }
+ } while ( !IsValid() && !bOsz &&
+ // #i3317#
+ !bConsiderWrapInfluenceDueToOverlapPrevCol &&
+ // #i40444#
+ !bConsiderWrapInfluenceDueToMovedFwdAnchor &&
+ GetFmt()->GetDoc()->IsVisibleLayerId( GetVirtDrawObj()->GetLayer() ) );
+
+ // #i3317# - instead of attribute change apply
+ // temporarly the 'straightforward positioning process'.
+ // #i80924#
+ // handle special case during splitting of table rows
+ if ( bConsiderWrapInfluenceDueToMovedFwdAnchor &&
+ GetAnchorFrm()->IsInTab() &&
+ GetAnchorFrm()->IsInFollowFlowRow() )
+ {
+ const SwFrm* pCellFrm = GetAnchorFrm();
+ while ( pCellFrm && !pCellFrm->IsCellFrm() )
+ {
+ pCellFrm = pCellFrm->GetUpper();
+ }
+ if ( pCellFrm )
+ {
+ SWRECTFN( pCellFrm )
+ if ( (pCellFrm->Frm().*fnRect->fnGetTop)() == 0 &&
+ (pCellFrm->Frm().*fnRect->fnGetHeight)() == 0 )
+ {
+ bConsiderWrapInfluenceDueToMovedFwdAnchor = false;
+ }
+ }
+ }
+ if ( bOsz || bConsiderWrapInfluenceDueToOverlapPrevCol ||
+ // #i40444#
+ bConsiderWrapInfluenceDueToMovedFwdAnchor )
+ {
+ SetTmpConsiderWrapInfluence( true );
+ SetRestartLayoutProcess( true );
+ SetTmpConsiderWrapInfluenceOfOtherObjs( true );
+ }
+ bSetCompletePaintOnInvalidate = sal_False;
+ }
+ }
+}
+
+/** method to determine, if a <MakeAll()> on the Writer fly frame is possible
+
+ #i28701#
+*/
+bool SwFlyAtCntFrm::IsFormatPossible() const
+{
+ return SwFlyFreeFrm::IsFormatPossible() &&
+ !SwOszControl::IsInProgress( this );
+}
+
+/*************************************************************************
+|*
+|* FindAnchor() und Hilfsfunktionen.
+|*
+|* Beschreibung: Sucht ausgehend von pOldAnch einen Anker fuer
+|* Absatzgebundene Objekte.
+|* Wird beim Draggen von Absatzgebundenen Objekten zur Ankeranzeige sowie
+|* fuer Ankerwechsel benoetigt.
+|*
+|*************************************************************************/
+
+class SwDistance
+{
+public:
+ SwTwips nMain, nSub;
+ SwDistance() { nMain = nSub = 0; }
+ SwDistance& operator=( const SwDistance &rTwo )
+ { nMain = rTwo.nMain; nSub = rTwo.nSub; return *this; }
+ sal_Bool operator<( const SwDistance& rTwo )
+ { return nMain < rTwo.nMain || ( nMain == rTwo.nMain && nSub &&
+ rTwo.nSub && nSub < rTwo.nSub ); }
+ sal_Bool operator<=( const SwDistance& rTwo )
+ { return nMain < rTwo.nMain || ( nMain == rTwo.nMain && ( !nSub ||
+ !rTwo.nSub || nSub <= rTwo.nSub ) ); }
+};
+
+const SwFrm * MA_FASTCALL lcl_CalcDownDist( SwDistance &rRet,
+ const Point &rPt,
+ const SwCntntFrm *pCnt )
+{
+ rRet.nSub = 0;
+ //Wenn der Point direkt innerhalb des Cnt steht ist die Sache klar und
+ //der Cntnt hat automatisch eine Entfernung von 0
+ if ( pCnt->Frm().IsInside( rPt ) )
+ {
+ rRet.nMain = 0;
+ return pCnt;
+ }
+ else
+ {
+ const SwLayoutFrm *pUp = pCnt->IsInTab() ? pCnt->FindTabFrm()->GetUpper() : pCnt->GetUpper();
+ // einspaltige Bereiche muessen zu ihrem Upper durchschalten
+ while( pUp->IsSctFrm() )
+ pUp = pUp->GetUpper();
+ const bool bVert = pUp->IsVertical();
+ //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin
+ const bool bVertL2R = pUp->IsVertLR();
+
+ //Dem Textflus folgen.
+ // #i70582#
+ // --> OD 2009-03-05 - adopted for Support for Classical Mongolian Script
+ const SwTwips nTopForObjPos =
+ bVert
+ ? ( bVertL2R
+ ? ( pCnt->Frm().Left() +
+ pCnt->GetUpperSpaceAmountConsideredForPrevFrmAndPageGrid() )
+ : ( pCnt->Frm().Left() +
+ pCnt->Frm().Width() -
+ pCnt->GetUpperSpaceAmountConsideredForPrevFrmAndPageGrid() ) )
+ : ( pCnt->Frm().Top() +
+ pCnt->GetUpperSpaceAmountConsideredForPrevFrmAndPageGrid() );
+ if ( pUp->Frm().IsInside( rPt ) )
+ {
+ // <rPt> point is inside environment of given content frame
+ // #i70582#
+ if( bVert )
+ //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin
+ {
+ if ( bVertL2R )
+ rRet.nMain = rPt.X() - nTopForObjPos;
+ else
+ rRet.nMain = nTopForObjPos - rPt.X();
+ }
+ else
+ rRet.nMain = rPt.Y() - nTopForObjPos;
+ return pCnt;
+ }
+ else if ( rPt.Y() <= pUp->Frm().Top() )
+ {
+ // <rPt> point is above environment of given content frame
+ // correct for vertical layout?
+ rRet.nMain = LONG_MAX;
+ }
+ else if( rPt.X() < pUp->Frm().Left() &&
+ rPt.Y() <= ( bVert ? pUp->Frm().Top() : pUp->Frm().Bottom() ) )
+ {
+ // <rPt> point is left of environment of given content frame
+ // seems not to be correct for vertical layout!?
+ const SwFrm *pLay = pUp->GetLeaf( MAKEPAGE_NONE, sal_False, pCnt );
+ if( !pLay ||
+ (bVert && (pLay->Frm().Top() + pLay->Prt().Bottom()) <rPt.Y())||
+ (!bVert && (pLay->Frm().Left() + pLay->Prt().Right())<rPt.X()) )
+ {
+ // <rPt> point is in left border of environment
+ // #i70582#
+ if( bVert )
+ //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin
+ {
+ if ( bVertL2R )
+ rRet.nMain = rPt.X() - nTopForObjPos;
+ else
+ rRet.nMain = nTopForObjPos - rPt.X();
+ }
+ else
+ rRet.nMain = rPt.Y() - nTopForObjPos;
+ return pCnt;
+ }
+ else
+ rRet.nMain = LONG_MAX;
+ }
+ else
+ {
+ // Support for Classical Mongolian Script (SCMS) joint with Jiayanmin
+ rRet.nMain = bVert
+ ? ( bVertL2R
+ ? ( (pUp->Frm().Left() + pUp->Prt().Right()) - nTopForObjPos )
+ : ( nTopForObjPos - (pUp->Frm().Left() + pUp->Prt().Left() ) ) )
+ : ( (pUp->Frm().Top() + pUp->Prt().Bottom()) - nTopForObjPos );
+
+ const SwFrm *pPre = pCnt;
+ const SwFrm *pLay = pUp->GetLeaf( MAKEPAGE_NONE, sal_True, pCnt );
+ SwTwips nFrmTop = 0;
+ SwTwips nPrtHeight = 0;
+ sal_Bool bSct = sal_False;
+ const SwSectionFrm *pSect = pUp->FindSctFrm();
+ if( pSect )
+ {
+ rRet.nSub = rRet.nMain;
+ rRet.nMain = 0;
+ }
+ if( pSect && !pSect->IsAnLower( pLay ) )
+ {
+ bSct = sal_False;
+ const SwSectionFrm* pNxtSect = pLay ? pLay->FindSctFrm() : 0;
+ if( pSect->IsAnFollow( pNxtSect ) )
+ {
+ if( pLay->IsVertical() )
+ {
+ //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin
+ if ( pLay->IsVertLR() )
+ nFrmTop = pLay->Frm().Left();
+ else
+ nFrmTop = pLay->Frm().Left() + pLay->Frm().Width();
+ nPrtHeight = pLay->Prt().Width();
+ }
+ else
+ {
+ nFrmTop = pLay->Frm().Top();
+ nPrtHeight = pLay->Prt().Height();
+ }
+ pSect = pNxtSect;
+ }
+ else
+ {
+ pLay = pSect->GetUpper();
+ if( pLay->IsVertical() )
+ {
+ //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin
+ if ( pLay->IsVertLR() )
+ {
+ nFrmTop = pSect->Frm().Right();
+ nPrtHeight = pLay->Frm().Left() + pLay->Prt().Left()
+ + pLay->Prt().Width() - pSect->Frm().Left()
+ - pSect->Frm().Width();
+ }
+ else
+ {
+ nFrmTop = pSect->Frm().Left();
+ nPrtHeight = pSect->Frm().Left() - pLay->Frm().Left()
+ - pLay->Prt().Left();
+ }
+ }
+ else
+ {
+ nFrmTop = pSect->Frm().Bottom();
+ nPrtHeight = pLay->Frm().Top() + pLay->Prt().Top()
+ + pLay->Prt().Height() - pSect->Frm().Top()
+ - pSect->Frm().Height();
+ }
+ pSect = 0;
+ }
+ }
+ else if( pLay )
+ {
+ if( pLay->IsVertical() )
+ {
+ //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin
+ if ( pLay->IsVertLR() )
+ {
+ nFrmTop = pLay->Frm().Left();
+ nPrtHeight = pLay->Prt().Width();
+ }
+ else
+ {
+ nFrmTop = pLay->Frm().Left() + pLay->Frm().Width();
+ nPrtHeight = pLay->Prt().Width();
+ }
+ }
+ else
+ {
+ nFrmTop = pLay->Frm().Top();
+ nPrtHeight = pLay->Prt().Height();
+ }
+ bSct = 0 != pSect;
+ }
+ while ( pLay && !pLay->Frm().IsInside( rPt ) &&
+ ( pLay->Frm().Top() <= rPt.Y() || pLay->IsInFly() ||
+ ( pLay->IsInSct() &&
+ pLay->FindSctFrm()->GetUpper()->Frm().Top() <= rPt.Y())) )
+ {
+ if ( pLay->IsFtnContFrm() )
+ {
+ if ( !((SwLayoutFrm*)pLay)->Lower() )
+ {
+ SwFrm *pDel = (SwFrm*)pLay;
+ pDel->Cut();
+ delete pDel;
+ return pPre;
+ }
+ return 0;
+ }
+ else
+ {
+ if( bSct || pSect )
+ rRet.nSub += nPrtHeight;
+ else
+ rRet.nMain += nPrtHeight;
+ pPre = pLay;
+ pLay = pLay->GetLeaf( MAKEPAGE_NONE, sal_True, pCnt );
+ if( pSect && !pSect->IsAnLower( pLay ) )
+ { // If we're leaving a SwSectionFrm, the next Leaf-Frm
+ // is the part of the upper below the SectionFrm.
+ const SwSectionFrm* pNxtSect = pLay ?
+ pLay->FindSctFrm() : NULL;
+ bSct = sal_False;
+ if( pSect->IsAnFollow( pNxtSect ) )
+ {
+ pSect = pNxtSect;
+ if( pLay->IsVertical() )
+ {
+ //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin
+ if ( pLay->IsVertLR() )
+ {
+ nFrmTop = pLay->Frm().Left();
+ nPrtHeight = pLay->Prt().Width();
+ }
+ else
+ {
+ nFrmTop = pLay->Frm().Left() + pLay->Frm().Width();
+ nPrtHeight = pLay->Prt().Width();
+ }
+ }
+ else
+ {
+ nFrmTop = pLay->Frm().Top();
+ nPrtHeight = pLay->Prt().Height();
+ }
+ }
+ else
+ {
+ pLay = pSect->GetUpper();
+ if( pLay->IsVertical() )
+ {
+ //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin
+ if ( pLay->IsVertLR() )
+ {
+ nFrmTop = pSect->Frm().Right();
+ nPrtHeight = pLay->Frm().Left()+pLay->Prt().Left()
+ + pLay->Prt().Width() - pSect->Frm().Left()
+ - pSect->Frm().Width();
+ }
+ else
+ {
+ nFrmTop = pSect->Frm().Left();
+ nPrtHeight = pSect->Frm().Left() -
+ pLay->Frm().Left() - pLay->Prt().Left();
+ }
+ }
+ else
+ {
+ nFrmTop = pSect->Frm().Bottom();
+ nPrtHeight = pLay->Frm().Top()+pLay->Prt().Top()
+ + pLay->Prt().Height() - pSect->Frm().Top()
+ - pSect->Frm().Height();
+ }
+ pSect = 0;
+ }
+ }
+ else if( pLay )
+ {
+ if( pLay->IsVertical() )
+ {
+ //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin
+ if ( pLay->IsVertLR() )
+ {
+ nFrmTop = pLay->Frm().Left();
+ nPrtHeight = pLay->Prt().Width();
+ }
+ else
+ {
+ nFrmTop = pLay->Frm().Left() + pLay->Frm().Width();
+ nPrtHeight = pLay->Prt().Width();
+ }
+ }
+ else
+ {
+ nFrmTop = pLay->Frm().Top();
+ nPrtHeight = pLay->Prt().Height();
+ }
+ bSct = 0 != pSect;
+ }
+ }
+ }
+ if ( pLay )
+ {
+ if ( pLay->Frm().IsInside( rPt ) )
+ {
+ //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin
+ SwTwips nDiff = pLay->IsVertical() ? ( pLay->IsVertLR() ? ( rPt.X() - nFrmTop ) : ( nFrmTop - rPt.X() ) )
+ : ( rPt.Y() - nFrmTop );
+ if( bSct || pSect )
+ rRet.nSub += nDiff;
+ else
+ rRet.nMain += nDiff;
+ }
+ if ( pLay->IsFtnContFrm() && !((SwLayoutFrm*)pLay)->Lower() )
+ {
+ SwFrm *pDel = (SwFrm*)pLay;
+ pDel->Cut();
+ delete pDel;
+ return 0;
+ }
+ return pLay;
+ }
+ else
+ rRet.nMain = LONG_MAX;
+ }
+ }
+ return 0;
+}
+
+sal_uLong MA_FASTCALL lcl_FindCntDiff( const Point &rPt, const SwLayoutFrm *pLay,
+ const SwCntntFrm *& rpCnt,
+ const sal_Bool bBody, const sal_Bool bFtn )
+{
+ //Sucht unterhalb von pLay den dichtesten Cnt zum Point. Der Bezugspunkt
+ //der Cntnts ist immer die linke obere Ecke.
+ //Der Cnt soll moeglichst ueber dem Point liegen.
+
+#if OSL_DEBUG_LEVEL > 1
+ Point arPoint( rPt );
+#endif
+
+ rpCnt = 0;
+ sal_uLong nDistance = ULONG_MAX;
+ sal_uLong nNearest = ULONG_MAX;
+ const SwCntntFrm *pCnt = pLay->ContainsCntnt();
+
+ while ( pCnt && (bBody != pCnt->IsInDocBody() || bFtn != pCnt->IsInFtn()))
+ {
+ pCnt = pCnt->GetNextCntntFrm();
+ if ( !pLay->IsAnLower( pCnt ) )
+ pCnt = 0;
+ }
+ const SwCntntFrm *pNearest = pCnt;
+ if ( pCnt )
+ {
+ do
+ {
+ //Jetzt die Entfernung zwischen den beiden Punkten berechnen.
+ //'Delta' X^2 + 'Delta'Y^2 = 'Entfernung'^2
+ sal_uInt32 dX = Max( pCnt->Frm().Left(), rPt.X() ) -
+ Min( pCnt->Frm().Left(), rPt.X() ),
+ dY = Max( pCnt->Frm().Top(), rPt.Y() ) -
+ Min( pCnt->Frm().Top(), rPt.Y() );
+ BigInt dX1( dX ), dY1( dY );
+ dX1 *= dX1; dY1 *= dY1;
+ const sal_uLong nDiff = ::SqRt( dX1 + dY1 );
+ if ( pCnt->Frm().Top() <= rPt.Y() )
+ {
+ if ( nDiff < nDistance )
+ { //Der ist dichter dran
+ nDistance = nNearest = nDiff;
+ rpCnt = pNearest = pCnt;
+ }
+ }
+ else if ( nDiff < nNearest )
+ {
+ nNearest = nDiff;
+ pNearest = pCnt;
+ }
+ pCnt = pCnt->GetNextCntntFrm();
+ while ( pCnt &&
+ (bBody != pCnt->IsInDocBody() || bFtn != pCnt->IsInFtn()))
+ pCnt = pCnt->GetNextCntntFrm();
+
+ } while ( pCnt && pLay->IsAnLower( pCnt ) );
+ }
+ if ( nDistance == ULONG_MAX )
+ { rpCnt = pNearest;
+ return nNearest;
+ }
+ return nDistance;
+}
+
+const SwCntntFrm * MA_FASTCALL lcl_FindCnt( const Point &rPt, const SwCntntFrm *pCnt,
+ const sal_Bool bBody, const sal_Bool bFtn )
+{
+ //Sucht ausgehen von pCnt denjenigen CntntFrm, dessen linke obere
+ //Ecke am dichtesten am Point liegt.
+ //Liefert _immer_ einen CntntFrm zurueck.
+
+ //Zunaechst wird versucht den dichtesten Cntnt innerhalt derjenigen
+ //Seite zu suchen innerhalb derer der Cntnt steht.
+ //Ausgehend von der Seite muessen die Seiten in beide
+ //Richtungen beruecksichtigt werden.
+ //Falls moeglich wird ein Cntnt geliefert, dessen Y-Position ueber der
+ //des Point sitzt.
+ const SwCntntFrm *pRet, *pNew;
+ const SwLayoutFrm *pLay = pCnt->FindPageFrm();
+ sal_uLong nDist;
+
+ nDist = ::lcl_FindCntDiff( rPt, pLay, pNew, bBody, bFtn );
+ if ( pNew )
+ pRet = pNew;
+ else
+ { pRet = pCnt;
+ nDist = ULONG_MAX;
+ }
+ const SwCntntFrm *pNearest = pRet;
+ sal_uLong nNearest = nDist;
+
+ if ( pLay )
+ {
+ const SwLayoutFrm *pPge = pLay;
+ sal_uLong nOldNew = ULONG_MAX;
+ for ( sal_uInt16 i = 0; pPge->GetPrev() && (i < 3); ++i )
+ {
+ pPge = (SwLayoutFrm*)pPge->GetPrev();
+ const sal_uLong nNew = ::lcl_FindCntDiff( rPt, pPge, pNew, bBody, bFtn );
+ if ( nNew < nDist )
+ {
+ if ( pNew->Frm().Top() <= rPt.Y() )
+ {
+ pRet = pNearest = pNew;
+ nDist = nNearest = nNew;
+ }
+ else if ( nNew < nNearest )
+ {
+ pNearest = pNew;
+ nNearest = nNew;
+ }
+ }
+ else if ( nOldNew != ULONG_MAX && nNew > nOldNew )
+ break;
+ else
+ nOldNew = nNew;
+
+ }
+ pPge = pLay;
+ nOldNew = ULONG_MAX;
+ for ( sal_uInt16 j = 0; pPge->GetNext() && (j < 3); ++j )
+ {
+ pPge = (SwLayoutFrm*)pPge->GetNext();
+ const sal_uLong nNew = ::lcl_FindCntDiff( rPt, pPge, pNew, bBody, bFtn );
+ if ( nNew < nDist )
+ {
+ if ( pNew->Frm().Top() <= rPt.Y() )
+ {
+ pRet = pNearest = pNew;
+ nDist = nNearest = nNew;
+ }
+ else if ( nNew < nNearest )
+ {
+ pNearest = pNew;
+ nNearest = nNew;
+ }
+ }
+ else if ( nOldNew != ULONG_MAX && nNew > nOldNew )
+ break;
+ else
+ nOldNew = nNew;
+ }
+ }
+ if ( (pRet->Frm().Top() > rPt.Y()) )
+ return pNearest;
+ else
+ return pRet;
+}
+
+void lcl_PointToPrt( Point &rPoint, const SwFrm *pFrm )
+{
+ SwRect aTmp( pFrm->Prt() );
+ aTmp += pFrm->Frm().Pos();
+ if ( rPoint.X() < aTmp.Left() )
+ rPoint.X() = aTmp.Left();
+ else if ( rPoint.X() > aTmp.Right() )
+ rPoint.X() = aTmp.Right();
+ if ( rPoint.Y() < aTmp.Top() )
+ rPoint.Y() = aTmp.Top();
+ else if ( rPoint.Y() > aTmp.Bottom() )
+ rPoint.Y() = aTmp.Bottom();
+
+}
+
+const SwCntntFrm *FindAnchor( const SwFrm *pOldAnch, const Point &rNew,
+ const sal_Bool bBodyOnly )
+{
+ //Zu der angegebenen DokumentPosition wird der dichteste Cnt im
+ //Textfluss gesucht. AusgangsFrm ist der uebergebene Anker.
+ const SwCntntFrm* pCnt;
+ if ( pOldAnch->IsCntntFrm() )
+ {
+ pCnt = (const SwCntntFrm*)pOldAnch;
+ }
+ else
+ {
+ Point aTmp( rNew );
+ SwLayoutFrm *pTmpLay = (SwLayoutFrm*)pOldAnch;
+ if( pTmpLay->IsRootFrm() )
+ {
+ SwRect aTmpRect( aTmp, Size(0,0) );
+ pTmpLay = (SwLayoutFrm*)::FindPage( aTmpRect, pTmpLay->Lower() );
+ }
+ pCnt = pTmpLay->GetCntntPos( aTmp, sal_False, bBodyOnly );
+ }
+
+ //Beim Suchen darauf achten, dass die Bereiche sinnvoll erhalten
+ //bleiben. D.h. in diesem Fall nicht in Header/Footer hinein und
+ //nicht aus Header/Footer hinaus.
+ const sal_Bool bBody = pCnt->IsInDocBody() || bBodyOnly;
+ const sal_Bool bFtn = !bBodyOnly && pCnt->IsInFtn();
+
+ Point aNew( rNew );
+ if ( bBody )
+ {
+ //#38848 Vom Seitenrand in den Body ziehen.
+ const SwFrm *pPage = pCnt->FindPageFrm();
+ ::lcl_PointToPrt( aNew, pPage->GetUpper() );
+ SwRect aTmp( aNew, Size( 0, 0 ) );
+ pPage = ::FindPage( aTmp, pPage );
+ ::lcl_PointToPrt( aNew, pPage );
+ }
+
+ if ( pCnt->IsInDocBody() == bBody && pCnt->Frm().IsInside( aNew ) )
+ return pCnt;
+ else if ( pOldAnch->IsInDocBody() || pOldAnch->IsPageFrm() )
+ {
+ //Vielleicht befindet sich der gewuenschte Anker ja auf derselben
+ //Seite wie der aktuelle Anker.
+ //So gibt es kein Problem mit Spalten.
+ Point aTmp( aNew );
+ const SwCntntFrm *pTmp = pCnt->FindPageFrm()->
+ GetCntntPos( aTmp, sal_False, sal_True, sal_False );
+ if ( pTmp && pTmp->Frm().IsInside( aNew ) )
+ return pTmp;
+ }
+
+ //Ausgehend vom Anker suche ich jetzt in beide Richtungen bis ich
+ //den jeweils dichtesten gefunden habe.
+ //Nicht die direkte Entfernung ist relevant sondern die Strecke die
+ //im Textfluss zurueckgelegt werden muss.
+ const SwCntntFrm *pUpLst;
+ const SwCntntFrm *pUpFrm = pCnt;
+ SwDistance nUp, nUpLst;
+ ::lcl_CalcDownDist( nUp, aNew, pUpFrm );
+ SwDistance nDown = nUp;
+ sal_Bool bNegAllowed = sal_True;//Einmal aus dem negativen Bereich heraus lassen.
+ do
+ {
+ pUpLst = pUpFrm; nUpLst = nUp;
+ pUpFrm = pUpLst->GetPrevCntntFrm();
+ while ( pUpFrm &&
+ (bBody != pUpFrm->IsInDocBody() || bFtn != pUpFrm->IsInFtn()))
+ pUpFrm = pUpFrm->GetPrevCntntFrm();
+ if ( pUpFrm )
+ {
+ ::lcl_CalcDownDist( nUp, aNew, pUpFrm );
+ //Wenn die Distanz innnerhalb einer Tabelle waechst, so lohnt es
+ //sich weiter zu suchen.
+ if ( pUpLst->IsInTab() && pUpFrm->IsInTab() )
+ {
+ while ( pUpFrm && ((nUpLst < nUp && pUpFrm->IsInTab()) ||
+ bBody != pUpFrm->IsInDocBody()) )
+ {
+ pUpFrm = pUpFrm->GetPrevCntntFrm();
+ if ( pUpFrm )
+ ::lcl_CalcDownDist( nUp, aNew, pUpFrm );
+ }
+ }
+ }
+ if ( !pUpFrm )
+ nUp.nMain = LONG_MAX;
+ if ( nUp.nMain >= 0 && LONG_MAX != nUp.nMain )
+ {
+ bNegAllowed = sal_False;
+ if ( nUpLst.nMain < 0 ) //nicht den falschen erwischen, wenn der Wert
+ //gerade von negativ auf positiv gekippt ist.
+ { pUpLst = pUpFrm;
+ nUpLst = nUp;
+ }
+ }
+ } while ( pUpFrm && ( ( bNegAllowed && nUp.nMain < 0 ) || ( nUp <= nUpLst ) ) );
+
+ const SwCntntFrm *pDownLst;
+ const SwCntntFrm *pDownFrm = pCnt;
+ SwDistance nDownLst;
+ if ( nDown.nMain < 0 )
+ nDown.nMain = LONG_MAX;
+ do
+ {
+ pDownLst = pDownFrm; nDownLst = nDown;
+ pDownFrm = pDownLst->GetNextCntntFrm();
+ while ( pDownFrm &&
+ (bBody != pDownFrm->IsInDocBody() || bFtn != pDownFrm->IsInFtn()))
+ pDownFrm = pDownFrm->GetNextCntntFrm();
+ if ( pDownFrm )
+ {
+ ::lcl_CalcDownDist( nDown, aNew, pDownFrm );
+ if ( nDown.nMain < 0 )
+ nDown.nMain = LONG_MAX;
+ //Wenn die Distanz innnerhalb einer Tabelle waechst, so lohnt es
+ //sich weiter zu suchen.
+ if ( pDownLst->IsInTab() && pDownFrm->IsInTab() )
+ {
+ while ( pDownFrm && ( ( nDown.nMain != LONG_MAX && nDownLst < nDownLst
+ && pDownFrm->IsInTab()) || bBody != pDownFrm->IsInDocBody() ) )
+ {
+ pDownFrm = pDownFrm->GetNextCntntFrm();
+ if ( pDownFrm )
+ ::lcl_CalcDownDist( nDown, aNew, pDownFrm );
+ if ( nDown.nMain < 0 )
+ nDown.nMain = LONG_MAX;
+ }
+ }
+ }
+ if ( !pDownFrm )
+ nDown.nMain = LONG_MAX;
+
+ } while ( pDownFrm && nDown <= nDownLst &&
+ nDown.nMain != LONG_MAX && nDownLst.nMain != LONG_MAX );
+
+ //Wenn ich in beide Richtungen keinen gefunden habe, so suche ich mir
+ //denjenigen Cntnt dessen linke obere Ecke dem Point am naechsten liegt.
+ //Eine derartige Situation tritt z.b. auf, wenn der Point nicht im Text-
+ //fluss sondern in irgendwelchen Raendern steht.
+ if ( nDownLst.nMain == LONG_MAX && nUpLst.nMain == LONG_MAX )
+ {
+ // If an OLE objects, which is contained in a fly frame
+ // is resized in inplace mode and the new Position is outside the
+ // fly frame, we do not want to leave our fly frame.
+ if ( pCnt->IsInFly() )
+ return pCnt;
+
+ return ::lcl_FindCnt( aNew, pCnt, bBody, bFtn );
+ }
+ else
+ return nDownLst < nUpLst ? pDownLst : pUpLst;
+}
+
+/*************************************************************************
+|*
+|* SwFlyAtCntFrm::SetAbsPos()
+|*
+|*************************************************************************/
+
+void SwFlyAtCntFrm::SetAbsPos( const Point &rNew )
+{
+ SwPageFrm *pOldPage = FindPageFrm();
+ const SwRect aOld( GetObjRectWithSpaces() );
+ Point aNew( rNew );
+ //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin
+ if( ( GetAnchorFrm()->IsVertical() && !GetAnchorFrm()->IsVertLR() ) || GetAnchorFrm()->IsRightToLeft() )
+ aNew.X() += Frm().Width();
+ SwCntntFrm *pCnt = (SwCntntFrm*)::FindAnchor( GetAnchorFrm(), aNew );
+ if( pCnt->IsProtected() )
+ pCnt = (SwCntntFrm*)GetAnchorFrm();
+
+ SwPageFrm *pTmpPage = 0;
+ const bool bVert = pCnt->IsVertical();
+ //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin
+ const bool bVertL2R = pCnt->IsVertLR();
+ const sal_Bool bRTL = pCnt->IsRightToLeft();
+
+ if( ( !bVert != !GetAnchorFrm()->IsVertical() ) ||
+ ( !bRTL != !GetAnchorFrm()->IsRightToLeft() ) )
+ {
+ if( bVert || bRTL )
+ aNew.X() += Frm().Width();
+ else
+ aNew.X() -= Frm().Width();
+ }
+
+ if ( pCnt->IsInDocBody() )
+ {
+ //#38848 Vom Seitenrand in den Body ziehen.
+ pTmpPage = pCnt->FindPageFrm();
+ ::lcl_PointToPrt( aNew, pTmpPage->GetUpper() );
+ SwRect aTmp( aNew, Size( 0, 0 ) );
+ pTmpPage = (SwPageFrm*)::FindPage( aTmp, pTmpPage );
+ ::lcl_PointToPrt( aNew, pTmpPage );
+ }
+
+ //RelPos einstellen, nur auf Wunsch invalidieren.
+ //rNew ist eine Absolute Position. Um die RelPos korrekt einzustellen
+ //muessen wir uns die Entfernung von rNew zum Anker im Textfluss besorgen.
+//!!!!!Hier kann Optimiert werden: FindAnchor koennte die RelPos mitliefern!
+ const SwFrm *pFrm = 0;
+ SwTwips nY;
+ if ( pCnt->Frm().IsInside( aNew ) )
+ {
+ // #i70582#
+ const SwTwips nTopForObjPos =
+ bVert
+ ? ( bVertL2R
+ ? ( pCnt->Frm().Left() +
+ pCnt->GetUpperSpaceAmountConsideredForPrevFrmAndPageGrid() )
+ : ( pCnt->Frm().Left() +
+ pCnt->Frm().Width() -
+ pCnt->GetUpperSpaceAmountConsideredForPrevFrmAndPageGrid() ) )
+ : ( pCnt->Frm().Top() +
+ pCnt->GetUpperSpaceAmountConsideredForPrevFrmAndPageGrid() );
+ if( bVert )
+ //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin
+ {
+ if ( bVertL2R )
+ nY = rNew.X() - nTopForObjPos;
+ else
+ nY = nTopForObjPos - rNew.X() - Frm().Width();
+ }
+ else
+ {
+ nY = rNew.Y() - nTopForObjPos;
+ }
+ }
+ else
+ {
+ SwDistance aDist;
+ pFrm = ::lcl_CalcDownDist( aDist, aNew, pCnt );
+ nY = aDist.nMain + aDist.nSub;
+ }
+
+ SwTwips nX = 0;
+
+ if ( pCnt->IsFollow() )
+ {
+ //Flys haengen niemals an einem Follow sondern immer am
+ //Master, den suchen wir uns jetzt.
+ const SwCntntFrm *pOriginal = pCnt;
+ const SwCntntFrm *pFollow = pCnt;
+ while ( pCnt->IsFollow() )
+ {
+ do
+ { pCnt = pCnt->GetPrevCntntFrm();
+ } while ( pCnt->GetFollow() != pFollow );
+ pFollow = pCnt;
+ }
+ SwTwips nDiff = 0;
+ do
+ { const SwFrm *pUp = pFollow->GetUpper();
+ if( pUp->IsVertical() )
+ //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin
+ {
+ if ( pUp->IsVertLR() )
+ nDiff += pUp->Prt().Width() - pFollow->GetRelPos().X();
+ else
+ nDiff += pFollow->Frm().Left() + pFollow->Frm().Width()
+ - pUp->Frm().Left() - pUp->Prt().Left();
+ }
+ else
+ nDiff += pUp->Prt().Height() - pFollow->GetRelPos().Y();
+ pFollow = pFollow->GetFollow();
+ } while ( pFollow != pOriginal );
+ nY += nDiff;
+ if( bVert )
+ nX = pCnt->Frm().Top() - pOriginal->Frm().Top();
+ else
+ nX = pCnt->Frm().Left() - pOriginal->Frm().Left();
+ }
+
+ if ( nY == LONG_MAX )
+ {
+ // #i70582#
+ const SwTwips nTopForObjPos =
+ bVert
+ ? ( bVertL2R
+ ? ( pCnt->Frm().Left() +
+ pCnt->GetUpperSpaceAmountConsideredForPrevFrmAndPageGrid() )
+ : ( pCnt->Frm().Left() +
+ pCnt->Frm().Width() -
+ pCnt->GetUpperSpaceAmountConsideredForPrevFrmAndPageGrid() ) )
+ : ( pCnt->Frm().Top() +
+ pCnt->GetUpperSpaceAmountConsideredForPrevFrmAndPageGrid() );
+ if( bVert )
+ //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin
+ {
+ if ( bVertL2R )
+ nY = rNew.X() - nTopForObjPos;
+ else
+ nY = nTopForObjPos - rNew.X();
+ }
+ else
+ {
+ nY = rNew.Y() - nTopForObjPos;
+ }
+ }
+
+ SwFlyFrmFmt *pFmt = (SwFlyFrmFmt*)GetFmt();
+ const SwFmtSurround& rSurround = pFmt->GetSurround();
+ const sal_Bool bWrapThrough =
+ rSurround.GetSurround() == SURROUND_THROUGHT;
+ SwTwips nBaseOfstForFly = 0;
+ const SwFrm* pTmpFrm = pFrm ? pFrm : pCnt;
+ if ( pTmpFrm->IsTxtFrm() )
+ nBaseOfstForFly =
+ ((SwTxtFrm*)pTmpFrm)->GetBaseOfstForFly( !bWrapThrough );
+
+ if( bVert )
+ {
+ if( !pFrm )
+ nX += rNew.Y() - pCnt->Frm().Top() - nBaseOfstForFly;
+ else
+ nX = rNew.Y() - pFrm->Frm().Top() - nBaseOfstForFly;
+ }
+ else
+ {
+ if( !pFrm )
+ {
+ if ( pCnt->IsRightToLeft() )
+ nX += pCnt->Frm().Right() - rNew.X() - Frm().Width() +
+ nBaseOfstForFly;
+ else
+ nX += rNew.X() - pCnt->Frm().Left() - nBaseOfstForFly;
+ }
+ else
+ {
+ if ( pFrm->IsRightToLeft() )
+ nX += pFrm->Frm().Right() - rNew.X() - Frm().Width() +
+ nBaseOfstForFly;
+ else
+ nX = rNew.X() - pFrm->Frm().Left() - nBaseOfstForFly;
+ }
+ }
+ GetFmt()->GetDoc()->GetIDocumentUndoRedo().StartUndo( UNDO_START, NULL );
+
+ if( pCnt != GetAnchorFrm() || ( IsAutoPos() && pCnt->IsTxtFrm() &&
+ GetFmt()->getIDocumentSettingAccess()->get(IDocumentSettingAccess::HTML_MODE)) )
+ {
+ //Das Ankerattribut auf den neuen Cnt setzen.
+ SwFmtAnchor aAnch( pFmt->GetAnchor() );
+ SwPosition *pPos = (SwPosition*)aAnch.GetCntntAnchor();
+ if( IsAutoPos() && pCnt->IsTxtFrm() )
+ {
+ SwCrsrMoveState eTmpState( MV_SETONLYTEXT );
+ Point aPt( rNew );
+ if( pCnt->GetCrsrOfst( pPos, aPt, &eTmpState )
+ && pPos->nNode == *pCnt->GetNode() )
+ {
+ ResetLastCharRectHeight();
+ if( text::RelOrientation::CHAR == pFmt->GetVertOrient().GetRelationOrient() )
+ nY = LONG_MAX;
+ if( text::RelOrientation::CHAR == pFmt->GetHoriOrient().GetRelationOrient() )
+ nX = LONG_MAX;
+ }
+ else
+ {
+ pPos->nNode = *pCnt->GetNode();
+ pPos->nContent.Assign( pCnt->GetNode(), 0 );
+ }
+ }
+ else
+ {
+ pPos->nNode = *pCnt->GetNode();
+ pPos->nContent.Assign( pCnt->GetNode(), 0 );
+ }
+
+ // handle change of anchor node:
+ // if count of the anchor frame also change, the fly frames have to be
+ // re-created. Thus, delete all fly frames except the <this> before the
+ // anchor attribute is change and re-create them afterwards.
+ {
+ SwHandleAnchorNodeChg aHandleAnchorNodeChg( *pFmt, aAnch, this );
+ pFmt->GetDoc()->SetAttr( aAnch, *pFmt );
+ }
+ }
+ // #i28701# - use new method <GetPageFrm()>
+ else if ( pTmpPage && pTmpPage != GetPageFrm() )
+ GetPageFrm()->MoveFly( this, pTmpPage );
+
+ const Point aRelPos = bVert ? Point( -nY, nX ) : Point( nX, nY );
+
+ ChgRelPos( aRelPos );
+
+ GetFmt()->GetDoc()->GetIDocumentUndoRedo().EndUndo( UNDO_END, NULL );
+
+ if ( pOldPage != FindPageFrm() )
+ ::Notify_Background( GetVirtDrawObj(), pOldPage, aOld, PREP_FLY_LEAVE,
+ sal_False );
+}
+
+/** method to assure that anchored object is registered at the correct
+ page frame
+
+ #i28701#
+ takes over functionality of deleted method <SwFlyAtCntFrm::AssertPage()>
+*/
+void SwFlyAtCntFrm::RegisterAtCorrectPage()
+{
+ SwPageFrm* pPageFrm( 0L );
+ if ( GetVertPosOrientFrm() )
+ {
+ pPageFrm = const_cast<SwPageFrm*>(GetVertPosOrientFrm()->FindPageFrm());
+ }
+ if ( pPageFrm && GetPageFrm() != pPageFrm )
+ {
+ if ( GetPageFrm() )
+ GetPageFrm()->MoveFly( this, pPageFrm );
+ else
+ pPageFrm->AppendFlyToPage( this );
+ }
+}
+
+// #i26791#
+//void SwFlyAtCntFrm::MakeFlyPos()
+void SwFlyAtCntFrm::MakeObjPos()
+{
+ // if fly frame position is valid, nothing is to do. Thus, return
+ if ( bValidPos )
+ {
+ return;
+ }
+
+ // #i26791# - validate position flag here.
+ bValidPos = sal_True;
+
+ // #i35911# - no calculation of new position, if
+ // anchored object is marked that it clears its environment and its
+ // environment is already cleared.
+ // before checking for cleared environment
+ // check, if member <mpVertPosOrientFrm> is set.
+ if ( GetVertPosOrientFrm() &&
+ ClearedEnvironment() && HasClearedEnvironment() )
+ {
+ return;
+ }
+
+ // use new class to position object
+ objectpositioning::SwToCntntAnchoredObjectPosition
+ aObjPositioning( *GetVirtDrawObj() );
+ aObjPositioning.CalcPosition();
+
+ SetVertPosOrientFrm ( aObjPositioning.GetVertPosOrientFrm() );
+}
+
+// #i28701#
+bool SwFlyAtCntFrm::_InvalidationAllowed( const InvalidationType _nInvalid ) const
+{
+ bool bAllowed( SwFlyFreeFrm::_InvalidationAllowed( _nInvalid ) );
+
+ // forbiddance of base instance can't be over ruled.
+ if ( bAllowed )
+ {
+ if ( _nInvalid == INVALID_POS ||
+ _nInvalid == INVALID_ALL )
+ {
+ bAllowed = InvalidationOfPosAllowed();
+ }
+ }
+
+ return bAllowed;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/layout/flyincnt.cxx b/sw/source/core/layout/flyincnt.cxx
new file mode 100644
index 000000000000..3a84f4948758
--- /dev/null
+++ b/sw/source/core/layout/flyincnt.cxx
@@ -0,0 +1,338 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+#include "cntfrm.hxx"
+#include "doc.hxx"
+#include "flyfrm.hxx"
+#include "frmtool.hxx"
+#include "frmfmt.hxx"
+#include "hints.hxx"
+#include <fmtornt.hxx>
+#include <fmtfsize.hxx>
+#include "txtfrm.hxx" //fuer IsLocked()
+#include "flyfrms.hxx"
+// OD 2004-01-19 #110582#
+#include <dflyobj.hxx>
+
+//aus FlyCnt.cxx
+void DeepCalc( const SwFrm *pFrm );
+
+/*************************************************************************
+|*
+|* SwFlyInCntFrm::SwFlyInCntFrm(), ~SwFlyInCntFrm()
+|*
+|*************************************************************************/
+SwFlyInCntFrm::SwFlyInCntFrm( SwFlyFrmFmt *pFmt, SwFrm* pSib, SwFrm *pAnch ) :
+ SwFlyFrm( pFmt, pSib, pAnch )
+{
+ bInCnt = bInvalidLayout = bInvalidCntnt = sal_True;
+ SwTwips nRel = pFmt->GetVertOrient().GetPos();
+ // OD 2004-05-27 #i26791# - member <aRelPos> moved to <SwAnchoredObject>
+ Point aRelPos;
+ if( pAnch && pAnch->IsVertical() )
+ aRelPos.X() = pAnch->IsReverse() ? nRel : -nRel;
+ else
+ aRelPos.Y() = nRel;
+ SetCurrRelPos( aRelPos );
+}
+
+SwFlyInCntFrm::~SwFlyInCntFrm()
+{
+ //und Tschuess.
+ if ( !GetFmt()->GetDoc()->IsInDtor() && GetAnchorFrm() )
+ {
+ SwRect aTmp( GetObjRectWithSpaces() );
+ SwFlyInCntFrm::NotifyBackground( FindPageFrm(), aTmp, PREP_FLY_LEAVE );
+ }
+}
+
+// --> OD 2004-06-29 #i28701#
+TYPEINIT1(SwFlyInCntFrm,SwFlyFrm);
+// <--
+/*************************************************************************
+|*
+|* SwFlyInCntFrm::SetRefPoint(),
+|*
+|*************************************************************************/
+void SwFlyInCntFrm::SetRefPoint( const Point& rPoint,
+ const Point& rRelAttr,
+ const Point& rRelPos )
+{
+ // OD 2004-05-27 #i26791# - member <aRelPos> moved to <SwAnchoredObject>
+ OSL_ENSURE( rPoint != aRef || rRelAttr != GetCurrRelPos(), "SetRefPoint: no change" );
+ SwFlyNotify *pNotify = NULL;
+ // No notify at a locked fly frame, if a fly frame is locked, there's
+ // already a SwFlyNotify object on the stack (MakeAll).
+ if( !IsLocked() )
+ pNotify = new SwFlyNotify( this );
+ aRef = rPoint;
+ SetCurrRelPos( rRelAttr );
+ SWRECTFN( GetAnchorFrm() )
+ (Frm().*fnRect->fnSetPos)( rPoint + rRelPos );
+ // --> OD 2006-08-25 #i68520#
+ InvalidateObjRectWithSpaces();
+ // <--
+ if( pNotify )
+ {
+ InvalidatePage();
+ bValidPos = sal_False;
+ bInvalid = sal_True;
+ Calc();
+ delete pNotify;
+ }
+}
+
+/*************************************************************************
+|*
+|* SwFlyInCntFrm::Modify()
+|*
+|*************************************************************************/
+void SwFlyInCntFrm::Modify( const SfxPoolItem* pOld, const SfxPoolItem *pNew )
+{
+ sal_Bool bCallPrepare = sal_False;
+ sal_uInt16 nWhich = pOld ? pOld->Which() : pNew ? pNew->Which() : 0;
+ if( RES_ATTRSET_CHG == nWhich )
+ {
+ if( SFX_ITEM_SET == ((SwAttrSetChg*)pNew)->GetChgSet()->
+ GetItemState( RES_SURROUND, sal_False ) ||
+ SFX_ITEM_SET == ((SwAttrSetChg*)pNew)->GetChgSet()->
+ GetItemState( RES_FRMMACRO, sal_False ) )
+ {
+ SwAttrSetChg aOld( *(SwAttrSetChg*)pOld );
+ SwAttrSetChg aNew( *(SwAttrSetChg*)pNew );
+
+ aOld.ClearItem( RES_SURROUND );
+ aNew.ClearItem( RES_SURROUND );
+ aOld.ClearItem( RES_FRMMACRO );
+ aNew.ClearItem( RES_FRMMACRO );
+ if( aNew.Count() )
+ {
+ SwFlyFrm::Modify( &aOld, &aNew );
+ bCallPrepare = sal_True;
+ }
+ }
+ else if( ((SwAttrSetChg*)pNew)->GetChgSet()->Count())
+ {
+ SwFlyFrm::Modify( pOld, pNew );
+ bCallPrepare = sal_True;
+ }
+ }
+ else if( nWhich != RES_SURROUND && RES_FRMMACRO != nWhich )
+ {
+ SwFlyFrm::Modify( pOld, pNew );
+ bCallPrepare = sal_True;
+ }
+
+ if ( bCallPrepare && GetAnchorFrm() )
+ AnchorFrm()->Prepare( PREP_FLY_ATTR_CHG, GetFmt() );
+}
+/*************************************************************************
+|*
+|* SwFlyInCntFrm::Format()
+|*
+|* Beschreibung: Hier wird der Inhalt initial mit Formatiert.
+|*
+|*************************************************************************/
+void SwFlyInCntFrm::Format( const SwBorderAttrs *pAttrs )
+{
+ if ( !Frm().Height() )
+ {
+ Lock(); //nicht hintenherum den Anker formatieren.
+ SwCntntFrm *pCntnt = ContainsCntnt();
+ while ( pCntnt )
+ { pCntnt->Calc();
+ pCntnt = pCntnt->GetNextCntntFrm();
+ }
+ Unlock();
+ }
+ SwFlyFrm::Format( pAttrs );
+}
+/*************************************************************************
+|*
+|* SwFlyInCntFrm::MakeFlyPos()
+|*
+|* Beschreibung Im Unterschied zu anderen Frms wird hier nur die
+|* die RelPos berechnet. Die absolute Position wird ausschliesslich
+|* per SetAbsPos errechnet.
+|*
+|*************************************************************************/
+// OD 2004-03-23 #i26791#
+//void SwFlyInCntFrm::MakeFlyPos()
+void SwFlyInCntFrm::MakeObjPos()
+{
+ if ( !bValidPos )
+ {
+ bValidPos = sal_True;
+ SwFlyFrmFmt *pFmt = (SwFlyFrmFmt*)GetFmt();
+ const SwFmtVertOrient &rVert = pFmt->GetVertOrient();
+ //Und ggf. noch die aktuellen Werte im Format updaten, dabei darf
+ //zu diesem Zeitpunkt natuerlich kein Modify verschickt werden.
+ const bool bVert = GetAnchorFrm()->IsVertical();
+ const bool bRev = GetAnchorFrm()->IsReverse();
+ SwTwips nOld = rVert.GetPos();
+ SwTwips nAct = bVert ? -GetCurrRelPos().X() : GetCurrRelPos().Y();
+ if( bRev )
+ nAct = -nAct;
+ if( nAct != nOld )
+ {
+ SwFmtVertOrient aVert( rVert );
+ aVert.SetPos( nAct );
+ pFmt->LockModify();
+ pFmt->SetFmtAttr( aVert );
+ pFmt->UnlockModify();
+ }
+ }
+}
+
+// --> OD 2004-12-02 #115759#
+void SwFlyInCntFrm::_ActionOnInvalidation( const InvalidationType _nInvalid )
+{
+ if ( INVALID_POS == _nInvalid || INVALID_ALL == _nInvalid )
+ AnchorFrm()->Prepare( PREP_FLY_ATTR_CHG, &GetFrmFmt() );
+}
+// <--
+/*************************************************************************
+|*
+|* SwFlyInCntFrm::NotifyBackground()
+|*
+|*************************************************************************/
+void SwFlyInCntFrm::NotifyBackground( SwPageFrm *, const SwRect& rRect,
+ PrepareHint eHint)
+{
+ if ( eHint == PREP_FLY_ATTR_CHG )
+ AnchorFrm()->Prepare( PREP_FLY_ATTR_CHG );
+ else
+ AnchorFrm()->Prepare( eHint, (void*)&rRect );
+}
+
+/*************************************************************************
+|*
+|* SwFlyInCntFrm::GetRelPos()
+|*
+|*************************************************************************/
+const Point SwFlyInCntFrm::GetRelPos() const
+{
+ Calc();
+ return GetCurrRelPos();
+}
+
+/*************************************************************************
+|*
+|* SwFlyInCntFrm::RegistFlys()
+|*
+|*************************************************************************/
+void SwFlyInCntFrm::RegistFlys()
+{
+ // vgl. SwRowFrm::RegistFlys()
+ SwPageFrm *pPage = FindPageFrm();
+ OSL_ENSURE( pPage, "Flys ohne Seite anmelden?" );
+ ::RegistFlys( pPage, this );
+}
+
+/*************************************************************************
+|*
+|* SwFlyInCntFrm::MakeAll()
+|*
+|*************************************************************************/
+void SwFlyInCntFrm::MakeAll()
+{
+ // OD 2004-01-19 #110582#
+ if ( !GetFmt()->GetDoc()->IsVisibleLayerId( GetVirtDrawObj()->GetLayer() ) )
+ {
+ return;
+ }
+
+ if ( !GetAnchorFrm() || IsLocked() || IsColLocked() || !FindPageFrm() )
+ return;
+
+ Lock(); //Der Vorhang faellt
+
+ //uebernimmt im DTor die Benachrichtigung
+ const SwFlyNotify aNotify( this );
+ SwBorderAttrAccess aAccess( SwFrm::GetCache(), this );
+ const SwBorderAttrs &rAttrs = *aAccess.Get();
+
+ if ( IsClipped() )
+ bValidSize = bHeightClipped = bWidthClipped = sal_False;
+
+ while ( !bValidPos || !bValidSize || !bValidPrtArea )
+ {
+ //Nur einstellen wenn das Flag gesetzt ist!!
+ if ( !bValidSize )
+ {
+ bValidPrtArea = sal_False;
+/*
+ // This is also done in the Format function, so I think
+ // this code is not necessary anymore:
+ long nOldWidth = aFrm.Width();
+ const Size aRelSize( CalcRel( rFrmSz ) );
+ aFrm.Width( aRelSize.Width() );
+
+ if ( aFrm.Width() > nOldWidth )
+ //Damit sich der Inhalt anpasst
+ aFrm.Height( aRelSize.Height() );
+*/
+ }
+
+ if ( !bValidPrtArea )
+ MakePrtArea( rAttrs );
+
+ if ( !bValidSize )
+ Format( &rAttrs );
+
+ if ( !bValidPos )
+ {
+ // OD 2004-03-23 #i26791#
+ //MakeFlyPos();
+ MakeObjPos();
+ }
+
+ // --> OD 2006-04-13 #b6402800#
+ // re-activate clipping of as-character anchored Writer fly frames
+ // depending on compatibility option <ClipAsCharacterAnchoredWriterFlyFrames>
+ if ( bValidPos && bValidSize &&
+ GetFmt()->getIDocumentSettingAccess()->get( IDocumentSettingAccess::CLIP_AS_CHARACTER_ANCHORED_WRITER_FLY_FRAME ) )
+ {
+ SwFrm* pFrm = AnchorFrm();
+ if ( Frm().Left() == (pFrm->Frm().Left()+pFrm->Prt().Left()) &&
+ Frm().Width() > pFrm->Prt().Width() )
+ {
+ Frm().Width( pFrm->Prt().Width() );
+ bValidPrtArea = sal_False;
+ bWidthClipped = sal_True;
+ }
+ }
+ // <--
+ }
+ Unlock();
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/layout/flylay.cxx b/sw/source/core/layout/flylay.cxx
new file mode 100644
index 000000000000..170779683097
--- /dev/null
+++ b/sw/source/core/layout/flylay.cxx
@@ -0,0 +1,1319 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+#include "doc.hxx"
+#include "pagefrm.hxx"
+#include "rootfrm.hxx"
+#include "cntfrm.hxx"
+#include "dview.hxx"
+#include "dflyobj.hxx"
+#include "dcontact.hxx"
+#include "flyfrm.hxx"
+#include "ftnfrm.hxx"
+#include "frmtool.hxx"
+#include "frmfmt.hxx"
+#include "hints.hxx"
+#include "pam.hxx"
+#include "sectfrm.hxx"
+
+
+#include <svx/svdpage.hxx>
+#include <editeng/ulspitem.hxx>
+#include <fmtanchr.hxx>
+#include <fmtornt.hxx>
+#include <fmtfsize.hxx>
+#include "ndole.hxx"
+#include "tabfrm.hxx"
+#include "flyfrms.hxx"
+// #i18732#
+#include <fmtfollowtextflow.hxx>
+#include <environmentofanchoredobject.hxx>
+// #i28701#
+#include <sortedobjs.hxx>
+#include <viewsh.hxx>
+#include <viewimp.hxx>
+
+
+using namespace ::com::sun::star;
+
+
+/*************************************************************************
+|*
+|* SwFlyFreeFrm::SwFlyFreeFrm(), ~SwFlyFreeFrm()
+|*
+|*************************************************************************/
+
+SwFlyFreeFrm::SwFlyFreeFrm( SwFlyFrmFmt *pFmt, SwFrm* pSib, SwFrm *pAnch ) :
+ SwFlyFrm( pFmt, pSib, pAnch ),
+ pPage( 0 ),
+ // #i34753#
+ mbNoMakePos( false ),
+ // #i37068#
+ mbNoMoveOnCheckClip( false )
+{
+}
+
+SwFlyFreeFrm::~SwFlyFreeFrm()
+{
+ //und Tschuess.
+ // #i28701# - use new method <GetPageFrm()>
+ if( GetPageFrm() )
+ {
+ if( GetFmt()->GetDoc()->IsInDtor() )
+ {
+ // #i29879# - remove also to-frame anchored Writer
+ // fly frame from page.
+ const bool bRemoveFromPage =
+ GetPageFrm()->GetSortedObjs() &&
+ ( IsFlyAtCntFrm() ||
+ ( GetAnchorFrm() && GetAnchorFrm()->IsFlyFrm() ) );
+ if ( bRemoveFromPage )
+ {
+ GetPageFrm()->GetSortedObjs()->Remove( *this );
+ }
+ }
+ else
+ {
+ SwRect aTmp( GetObjRectWithSpaces() );
+ SwFlyFreeFrm::NotifyBackground( GetPageFrm(), aTmp, PREP_FLY_LEAVE );
+ }
+ }
+}
+
+// #i28701#
+TYPEINIT1(SwFlyFreeFrm,SwFlyFrm);
+/*************************************************************************
+|*
+|* SwFlyFreeFrm::NotifyBackground()
+|*
+|* Beschreibung Benachrichtigt den Hintergrund (alle CntntFrms die
+|* gerade ueberlappt werden. Ausserdem wird das Window in einigen
+|* Faellen direkt invalidiert (vor allem dort, wo keine CntntFrms
+|* ueberlappt werden.
+|* Es werden auch die CntntFrms innerhalb von anderen Flys
+|* beruecksichtigt.
+|*
+|*************************************************************************/
+
+void SwFlyFreeFrm::NotifyBackground( SwPageFrm *pPageFrm,
+ const SwRect& rRect, PrepareHint eHint )
+{
+ ::Notify_Background( GetVirtDrawObj(), pPageFrm, rRect, eHint, sal_True );
+}
+
+/*************************************************************************
+|*
+|* SwFlyFreeFrm::MakeAll()
+|*
+|*************************************************************************/
+
+void SwFlyFreeFrm::MakeAll()
+{
+ if ( !GetFmt()->GetDoc()->IsVisibleLayerId( GetVirtDrawObj()->GetLayer() ) )
+ {
+ return;
+ }
+
+ if ( !GetAnchorFrm() || IsLocked() || IsColLocked() )
+ return;
+ // #i28701# - use new method <GetPageFrm()>
+ if( !GetPageFrm() && GetAnchorFrm() && GetAnchorFrm()->IsInFly() )
+ {
+ SwFlyFrm* pFly = AnchorFrm()->FindFlyFrm();
+ SwPageFrm *pPageFrm = pFly ? pFly->FindPageFrm() : NULL;
+ if( pPageFrm )
+ pPageFrm->AppendFlyToPage( this );
+ }
+ if( !GetPageFrm() )
+ return;
+
+ Lock(); //Der Vorhang faellt
+
+ //uebernimmt im DTor die Benachrichtigung
+ const SwFlyNotify aNotify( this );
+
+ if ( IsClipped() )
+ {
+ bValidSize = bHeightClipped = bWidthClipped = sal_False;
+ // no invalidation of position,
+ // if anchored object is anchored inside a Writer fly frame,
+ // its position is already locked, and it follows the text flow.
+ // #i34753# - add condition:
+ // no invalidation of position, if no direct move is requested in <CheckClip(..)>
+ if ( !IsNoMoveOnCheckClip() &&
+ !( PositionLocked() &&
+ GetAnchorFrm()->IsInFly() &&
+ GetFrmFmt().GetFollowTextFlow().GetValue() ) )
+ {
+ bValidPos = sal_False;
+ }
+ }
+
+ // #i81146# new loop control
+ sal_uInt16 nLoopControlRuns = 0;
+ const sal_uInt16 nLoopControlMax = 10;
+
+ while ( !bValidPos || !bValidSize || !bValidPrtArea || bFormatHeightOnly )
+ {
+ SWRECTFN( this )
+ const SwFmtFrmSize *pSz;
+ { //Zusaetzlicher Scope, damit aAccess vor dem Check zerstoert wird!
+
+ SwBorderAttrAccess aAccess( SwFrm::GetCache(), this );
+ const SwBorderAttrs &rAttrs = *aAccess.Get();
+ pSz = &rAttrs.GetAttrSet().GetFrmSize();
+
+ //Nur einstellen wenn das Flag gesetzt ist!!
+ if ( !bValidSize )
+ {
+ bValidPrtArea = sal_False;
+ }
+
+ if ( !bValidPrtArea )
+ MakePrtArea( rAttrs );
+
+ if ( !bValidSize || bFormatHeightOnly )
+ {
+ bValidSize = sal_False;
+ Format( &rAttrs );
+ bFormatHeightOnly = sal_False;
+ }
+
+ if ( !bValidPos )
+ {
+ const Point aOldPos( (Frm().*fnRect->fnGetPos)() );
+ // #i26791# - use new method <MakeObjPos()>
+ // #i34753# - no positioning, if requested.
+ if ( IsNoMakePos() )
+ bValidPos = sal_True;
+ else
+ // #i26791# - use new method <MakeObjPos()>
+ MakeObjPos();
+ if( aOldPos == (Frm().*fnRect->fnGetPos)() )
+ {
+ if( !bValidPos && GetAnchorFrm()->IsInSct() &&
+ !GetAnchorFrm()->FindSctFrm()->IsValid() )
+ bValidPos = sal_True;
+ }
+ else
+ bValidSize = sal_False;
+ }
+ }
+
+ if ( bValidPos && bValidSize )
+ {
+ ++nLoopControlRuns;
+
+#if OSL_DEBUG_LEVEL > 1
+ OSL_ENSURE( nLoopControlRuns < nLoopControlMax, "LoopControl in SwFlyFreeFrm::MakeAll" );
+#endif
+
+ if ( nLoopControlRuns < nLoopControlMax )
+ CheckClip( *pSz );
+ }
+ else
+ nLoopControlRuns = 0;
+ }
+ Unlock();
+
+#if OSL_DEBUG_LEVEL > 1
+ SWRECTFN( this )
+ OSL_ENSURE( bHeightClipped || ( (Frm().*fnRect->fnGetHeight)() > 0 &&
+ (Prt().*fnRect->fnGetHeight)() > 0),
+ "SwFlyFreeFrm::Format(), flipping Fly." );
+
+#endif
+}
+
+/** determines, if direct environment of fly frame has 'auto' size
+
+ #i17297#
+ start with anchor frame and search via <GetUpper()> for a header, footer,
+ row or fly frame stopping at page frame.
+ return <true>, if such a frame is found and it has 'auto' size.
+ otherwise <false> is returned.
+
+ @return boolean indicating, that direct environment has 'auto' size
+*/
+bool SwFlyFreeFrm::HasEnvironmentAutoSize() const
+{
+ bool bRetVal = false;
+
+ const SwFrm* pToBeCheckedFrm = GetAnchorFrm();
+ while ( pToBeCheckedFrm &&
+ !pToBeCheckedFrm->IsPageFrm() )
+ {
+ if ( pToBeCheckedFrm->IsHeaderFrm() ||
+ pToBeCheckedFrm->IsFooterFrm() ||
+ pToBeCheckedFrm->IsRowFrm() ||
+ pToBeCheckedFrm->IsFlyFrm() )
+ {
+ bRetVal = ATT_FIX_SIZE !=
+ pToBeCheckedFrm->GetAttrSet()->GetFrmSize().GetHeightSizeType();
+ break;
+ }
+ else
+ {
+ pToBeCheckedFrm = pToBeCheckedFrm->GetUpper();
+ }
+ }
+
+ return bRetVal;
+}
+
+/*************************************************************************
+|*
+|* SwFlyFreeFrm::CheckClip()
+|*
+|*************************************************************************/
+
+void SwFlyFreeFrm::CheckClip( const SwFmtFrmSize &rSz )
+{
+ //Jetzt ist es ggf. an der Zeit geignete Massnahmen zu ergreifen wenn
+ //der Fly nicht in seine Umgebung passt.
+ //Zuerst gibt der Fly seine Position auf. Danach wird er zunaechst
+ //formatiert. Erst wenn er auch durch die Aufgabe der Position nicht
+ //passt wird die Breite oder Hoehe aufgegeben - der Rahmen wird soweit
+ //wie notwendig zusammengequetscht.
+
+ const SwVirtFlyDrawObj *pObj = GetVirtDrawObj();
+ SwRect aClip, aTmpStretch;
+ ::CalcClipRect( pObj, aClip, sal_True );
+ ::CalcClipRect( pObj, aTmpStretch, sal_False );
+ aClip._Intersection( aTmpStretch );
+
+ const long nBot = Frm().Top() + Frm().Height();
+ const long nRig = Frm().Left() + Frm().Width();
+ const long nClipBot = aClip.Top() + aClip.Height();
+ const long nClipRig = aClip.Left() + aClip.Width();
+
+ const sal_Bool bBot = nBot > nClipBot;
+ const sal_Bool bRig = nRig > nClipRig;
+ if ( bBot || bRig )
+ {
+ sal_Bool bAgain = sal_False;
+ // #i37068# - no move, if it's requested
+ if ( bBot && !IsNoMoveOnCheckClip() &&
+ !GetDrawObjs() && !GetAnchorFrm()->IsInTab() )
+ {
+ SwFrm* pHeader = FindFooterOrHeader();
+ // In a header, correction of the position is no good idea.
+ // If the fly moves, some paragraphs has to be formatted, this
+ // could cause a change of the height of the headerframe,
+ // now the flyframe can change its position and so on ...
+ if ( !pHeader || !pHeader->IsHeaderFrm() )
+ {
+ const long nOld = Frm().Top();
+ Frm().Pos().Y() = Max( aClip.Top(), nClipBot - Frm().Height() );
+ if ( Frm().Top() != nOld )
+ bAgain = sal_True;
+ bHeightClipped = sal_True;
+ }
+ }
+ if ( bRig )
+ {
+ const long nOld = Frm().Left();
+ Frm().Pos().X() = Max( aClip.Left(), nClipRig - Frm().Width() );
+ if ( Frm().Left() != nOld )
+ {
+ const SwFmtHoriOrient &rH = GetFmt()->GetHoriOrient();
+ // Links ausgerichtete duerfen nicht nach links verschoben werden,
+ // wenn sie einem anderen ausweichen.
+ if( rH.GetHoriOrient() == text::HoriOrientation::LEFT )
+ Frm().Pos().X() = nOld;
+ else
+ bAgain = sal_True;
+ }
+ bWidthClipped = sal_True;
+ }
+ if ( bAgain )
+ bValidSize = sal_False;
+ else
+ {
+ //Wenn wir hier ankommen ragt der Frm in unerlaubte Bereiche
+ //hinein, und eine Positionskorrektur ist nicht erlaubt bzw.
+ //moeglich oder noetig.
+
+ //Fuer Flys mit OLE-Objekten als Lower sorgen wir dafuer, dass
+ //immer proportional Resized wird.
+ Size aOldSize( Frm().SSize() );
+
+ //Zuerst wird das FrmRect eingestellt, und dann auf den Frm
+ //uebertragen.
+ SwRect aFrmRect( Frm() );
+
+ if ( bBot )
+ {
+ long nDiff = nClipBot;
+ nDiff -= aFrmRect.Top(); //nDiff ist die verfuegbare Strecke.
+ nDiff = aFrmRect.Height() - nDiff;
+ aFrmRect.Height( aFrmRect.Height() - nDiff );
+ bHeightClipped = sal_True;
+ }
+ if ( bRig )
+ {
+ long nDiff = nClipRig;
+ nDiff -= aFrmRect.Left();//nDiff ist die verfuegbare Strecke.
+ nDiff = aFrmRect.Width() - nDiff;
+ aFrmRect.Width( aFrmRect.Width() - nDiff );
+ bWidthClipped = sal_True;
+ }
+
+ // #i17297# - no proportional
+ // scaling of graphics in environments, which determines its size
+ // by its content ('auto' size). Otherwise layout loops can occur and
+ // layout sizes of the environment can be incorrect.
+ // Such environment are:
+ // (1) header and footer frames with 'auto' size
+ // (2) table row frames with 'auto' size
+ // (3) fly frames with 'auto' size
+ // Note: section frames seems to be not critical - didn't found
+ // any critical layout situation so far.
+ if ( Lower() && Lower()->IsNoTxtFrm() &&
+ ( static_cast<SwCntntFrm*>(Lower())->GetNode()->GetOLENode() ||
+ !HasEnvironmentAutoSize() ) )
+ {
+ //Wenn Breite und Hoehe angepasst wurden, so ist die
+ //groessere Veraenderung massgeblich.
+ if ( aFrmRect.Width() != aOldSize.Width() &&
+ aFrmRect.Height()!= aOldSize.Height() )
+ {
+ if ( (aOldSize.Width() - aFrmRect.Width()) >
+ (aOldSize.Height()- aFrmRect.Height()) )
+ aFrmRect.Height( aOldSize.Height() );
+ else
+ aFrmRect.Width( aOldSize.Width() );
+ }
+
+ //Breite angepasst? - Hoehe dann proportional verkleinern
+ if( aFrmRect.Width() != aOldSize.Width() )
+ {
+ aFrmRect.Height( aFrmRect.Width() * aOldSize.Height() /
+ aOldSize.Width() );
+ bHeightClipped = sal_True;
+ }
+ //Hoehe angepasst? - Breite dann proportional verkleinern
+ else if( aFrmRect.Height() != aOldSize.Height() )
+ {
+ aFrmRect.Width( aFrmRect.Height() * aOldSize.Width() /
+ aOldSize.Height() );
+ bWidthClipped = sal_True;
+ }
+
+ // #i17297# - reactivate change
+ // of size attribute for fly frames containing an ole object.
+
+ // Added the aFrmRect.HasArea() hack, because
+ // the environment of the ole object does not have to be valid
+ // at this moment, or even worse, it does not have to have a
+ // resonable size. In this case we do not want to change to
+ // attributes permanentely. Maybe one day somebody dares to remove
+ // this code.
+ if ( aFrmRect.HasArea() &&
+ static_cast<SwCntntFrm*>(Lower())->GetNode()->GetOLENode() &&
+ ( bWidthClipped || bHeightClipped ) )
+ {
+ SwFlyFrmFmt *pFmt = (SwFlyFrmFmt*)GetFmt();
+ pFmt->LockModify();
+ SwFmtFrmSize aFrmSize( rSz );
+ aFrmSize.SetWidth( aFrmRect.Width() );
+ aFrmSize.SetHeight( aFrmRect.Height() );
+ pFmt->SetFmtAttr( aFrmSize );
+ pFmt->UnlockModify();
+ }
+ }
+
+ //Jetzt die Einstellungen am Frm vornehmen, bei Spalten werden
+ //die neuen Werte in die Attribute eingetragen, weil es sonst
+ //ziemlich fiese Oszillationen gibt.
+ const long nPrtHeightDiff = Frm().Height() - Prt().Height();
+ const long nPrtWidthDiff = Frm().Width() - Prt().Width();
+ Frm().Height( aFrmRect.Height() );
+ Frm().Width ( Max( long(MINLAY), aFrmRect.Width() ) );
+ if ( Lower() && Lower()->IsColumnFrm() )
+ {
+ ColLock(); //Grow/Shrink locken.
+ const Size aTmpOldSize( Prt().SSize() );
+ Prt().Height( Frm().Height() - nPrtHeightDiff );
+ Prt().Width ( Frm().Width() - nPrtWidthDiff );
+ ChgLowersProp( aTmpOldSize );
+ SwFrm *pLow = Lower();
+ do
+ { pLow->Calc();
+ // auch den (Column)BodyFrm mitkalkulieren
+ ((SwLayoutFrm*)pLow)->Lower()->Calc();
+ pLow = pLow->GetNext();
+ } while ( pLow );
+ ::CalcCntnt( this );
+ ColUnlock();
+ if ( !bValidSize && !bWidthClipped )
+ bFormatHeightOnly = bValidSize = sal_True;
+ }
+ else
+ {
+ Prt().Height( Frm().Height() - nPrtHeightDiff );
+ Prt().Width ( Frm().Width() - nPrtWidthDiff );
+ }
+ }
+ }
+
+ // #i26945#
+ OSL_ENSURE( Frm().Height() >= 0,
+ "<SwFlyFreeFrm::CheckClip(..)> - fly frame has negative height now." );
+}
+
+/** method to determine, if a <MakeAll()> on the Writer fly frame is possible
+ #i43771#
+*/
+bool SwFlyFreeFrm::IsFormatPossible() const
+{
+ return SwFlyFrm::IsFormatPossible() &&
+ ( GetPageFrm() ||
+ ( GetAnchorFrm() && GetAnchorFrm()->IsInFly() ) );
+}
+
+/*************************************************************************
+|*
+|* SwFlyLayFrm::SwFlyLayFrm()
+|*
+|*************************************************************************/
+
+SwFlyLayFrm::SwFlyLayFrm( SwFlyFrmFmt *pFmt, SwFrm* pSib, SwFrm *pAnch ) :
+ SwFlyFreeFrm( pFmt, pSib, pAnch )
+{
+ bLayout = sal_True;
+}
+
+// #i28701#
+TYPEINIT1(SwFlyLayFrm,SwFlyFreeFrm);
+/*************************************************************************
+|*
+|* SwFlyLayFrm::Modify()
+|*
+|*************************************************************************/
+
+void SwFlyLayFrm::Modify( const SfxPoolItem* pOld, const SfxPoolItem *pNew )
+{
+ sal_uInt16 nWhich = pNew ? pNew->Which() : 0;
+
+ SwFmtAnchor *pAnch = 0;
+ if( RES_ATTRSET_CHG == nWhich && SFX_ITEM_SET ==
+ ((SwAttrSetChg*)pNew)->GetChgSet()->GetItemState( RES_ANCHOR, sal_False,
+ (const SfxPoolItem**)&pAnch ))
+ ; // Beim GetItemState wird der AnkerPointer gesetzt !
+
+ else if( RES_ANCHOR == nWhich )
+ {
+ //Ankerwechsel, ich haenge mich selbst um.
+ //Es darf sich nicht um einen Wechsel des Ankertyps handeln,
+ //dies ist nur ueber die SwFEShell moeglich.
+ pAnch = (SwFmtAnchor*)pNew;
+ }
+
+ if( pAnch )
+ {
+ OSL_ENSURE( pAnch->GetAnchorId() ==
+ GetFmt()->GetAnchor().GetAnchorId(),
+ "8-) Unzulaessiger Wechsel des Ankertyps." );
+
+ //Abmelden, Seite besorgen, an den entsprechenden LayoutFrm
+ //haengen.
+ SwRect aOld( GetObjRectWithSpaces() );
+ // #i28701# - use new method <GetPageFrm()>
+ SwPageFrm *pOldPage = GetPageFrm();
+ AnchorFrm()->RemoveFly( this );
+
+ if ( FLY_AT_PAGE == pAnch->GetAnchorId() )
+ {
+ sal_uInt16 nPgNum = pAnch->GetPageNum();
+ SwRootFrm *pRoot = getRootFrm();
+ SwPageFrm *pTmpPage = (SwPageFrm*)pRoot->Lower();
+ for ( sal_uInt16 i = 1; (i <= nPgNum) && pTmpPage; ++i,
+ pTmpPage = (SwPageFrm*)pTmpPage->GetNext() )
+ {
+ if ( i == nPgNum )
+ {
+ // #i50432# - adjust synopsis of <PlaceFly(..)>
+ pTmpPage->PlaceFly( this, 0 );
+ }
+ }
+ if( !pTmpPage )
+ {
+ pRoot->SetAssertFlyPages();
+ pRoot->AssertFlyPages();
+ }
+ }
+ else
+ {
+ SwNodeIndex aIdx( pAnch->GetCntntAnchor()->nNode );
+ SwCntntFrm *pCntnt = GetFmt()->GetDoc()->GetNodes().GoNext( &aIdx )->
+ GetCntntNode()->getLayoutFrm( getRootFrm(), 0, 0, sal_False );
+ if( pCntnt )
+ {
+ SwFlyFrm *pTmp = pCntnt->FindFlyFrm();
+ if( pTmp )
+ pTmp->AppendFly( this );
+ }
+ }
+ // #i28701# - use new method <GetPageFrm()>
+ if ( pOldPage && pOldPage != GetPageFrm() )
+ NotifyBackground( pOldPage, aOld, PREP_FLY_LEAVE );
+ SetCompletePaint();
+ InvalidateAll();
+ SetNotifyBack();
+ }
+ else
+ SwFlyFrm::Modify( pOld, pNew );
+}
+
+/*************************************************************************
+|*
+|* SwPageFrm::AppendFly()
+|*
+|*************************************************************************/
+
+void SwPageFrm::AppendFlyToPage( SwFlyFrm *pNew )
+{
+ if ( !pNew->GetVirtDrawObj()->IsInserted() )
+ getRootFrm()->GetDrawPage()->InsertObject(
+ (SdrObject*)pNew->GetVirtDrawObj(),
+ pNew->GetVirtDrawObj()->GetReferencedObj().GetOrdNumDirect() );
+
+ InvalidateSpelling();
+ InvalidateSmartTags(); // SMARTTAGS
+ InvalidateAutoCompleteWords();
+ InvalidateWordCount();
+
+ if ( GetUpper() )
+ {
+ ((SwRootFrm*)GetUpper())->SetIdleFlags();
+ ((SwRootFrm*)GetUpper())->InvalidateBrowseWidth();
+ }
+
+ SdrObject* pObj = pNew->GetVirtDrawObj();
+ OSL_ENSURE( pNew->GetAnchorFrm(), "Fly without Anchor" );
+ const SwFlyFrm* pFly = pNew->GetAnchorFrm()->FindFlyFrm();
+ if ( pFly && pObj->GetOrdNum() < pFly->GetVirtDrawObj()->GetOrdNum() )
+ {
+ sal_uInt32 nNewNum = pFly->GetVirtDrawObj()->GetOrdNumDirect();
+ if ( pObj->GetPage() )
+ pObj->GetPage()->SetObjectOrdNum( pObj->GetOrdNumDirect(), nNewNum);
+ else
+ pObj->SetOrdNum( nNewNum );
+ }
+
+ //Flys die im Cntnt sitzen beachten wir nicht weiter.
+ if ( pNew->IsFlyInCntFrm() )
+ InvalidateFlyInCnt();
+ else
+ {
+ InvalidateFlyCntnt();
+
+ if ( !pSortedObjs )
+ pSortedObjs = new SwSortedObjs();
+
+#if OSL_DEBUG_LEVEL > 1
+ const bool bSucessInserted =
+#endif
+ pSortedObjs->Insert( *pNew );
+#if OSL_DEBUG_LEVEL > 1
+ OSL_ENSURE( bSucessInserted, "Fly nicht in Sorted eingetragen." );
+ (void) bSucessInserted;
+#endif
+
+ // #i87493#
+ OSL_ENSURE( pNew->GetPageFrm() == 0 || pNew->GetPageFrm() == this,
+ "<SwPageFrm::AppendFlyToPage(..)> - anchored fly frame seems to be registered at another page frame. Serious defect -> please inform OD." );
+ // #i28701# - use new method <SetPageFrm(..)>
+ pNew->SetPageFrm( this );
+ pNew->InvalidatePage( this );
+ // #i28701#
+ pNew->UnlockPosition();
+
+ // Notify accessible layout. That's required at this place for
+ // frames only where the anchor is moved. Creation of new frames
+ // is additionally handled by the SwFrmNotify class.
+ if( GetUpper() &&
+ static_cast< SwRootFrm * >( GetUpper() )->IsAnyShellAccessible() &&
+ static_cast< SwRootFrm * >( GetUpper() )->GetCurrShell() )
+ {
+ static_cast< SwRootFrm * >( GetUpper() )->GetCurrShell()->Imp()
+ ->AddAccessibleFrm( pNew );
+ }
+ }
+
+ // #i28701# - correction: consider also drawing objects
+ if ( pNew->GetDrawObjs() )
+ {
+ SwSortedObjs &rObjs = *pNew->GetDrawObjs();
+ for ( sal_uInt16 i = 0; i < rObjs.Count(); ++i )
+ {
+ SwAnchoredObject* pTmpObj = rObjs[i];
+ if ( pTmpObj->ISA(SwFlyFrm) )
+ {
+ SwFlyFrm* pTmpFly = static_cast<SwFlyFrm*>(pTmpObj);
+ // #i28701# - use new method <GetPageFrm()>
+ if ( pTmpFly->IsFlyFreeFrm() && !pTmpFly->GetPageFrm() )
+ AppendFlyToPage( pTmpFly );
+ }
+ else if ( pTmpObj->ISA(SwAnchoredDrawObject) )
+ {
+ // #i87493#
+ if ( pTmpObj->GetPageFrm() != this )
+ {
+ if ( pTmpObj->GetPageFrm() != 0 )
+ {
+ pTmpObj->GetPageFrm()->RemoveDrawObjFromPage( *pTmpObj );
+ }
+ AppendDrawObjToPage( *pTmpObj );
+ }
+ }
+ }
+ }
+}
+
+/*************************************************************************
+|*
+|* SwPageFrm::RemoveFly()
+|*
+|*************************************************************************/
+
+void SwPageFrm::RemoveFlyFromPage( SwFlyFrm *pToRemove )
+{
+ const sal_uInt32 nOrdNum = pToRemove->GetVirtDrawObj()->GetOrdNum();
+ getRootFrm()->GetDrawPage()->RemoveObject( nOrdNum );
+ pToRemove->GetVirtDrawObj()->ReferencedObj().SetOrdNum( nOrdNum );
+
+ if ( GetUpper() )
+ {
+ if ( !pToRemove->IsFlyInCntFrm() )
+ ((SwRootFrm*)GetUpper())->SetSuperfluous();
+ ((SwRootFrm*)GetUpper())->InvalidateBrowseWidth();
+ }
+
+ //Flys die im Cntnt sitzen beachten wir nicht weiter.
+ if ( pToRemove->IsFlyInCntFrm() )
+ return;
+
+ // Notify accessible layout. That's required at this place for
+ // frames only where the anchor is moved. Creation of new frames
+ // is additionally handled by the SwFrmNotify class.
+ if( GetUpper() &&
+ static_cast< SwRootFrm * >( GetUpper() )->IsAnyShellAccessible() &&
+ static_cast< SwRootFrm * >( GetUpper() )->GetCurrShell() )
+ {
+ static_cast< SwRootFrm * >( GetUpper() )->GetCurrShell()->Imp()
+ ->DisposeAccessibleFrm( pToRemove, sal_True );
+ }
+
+ //Collections noch nicht loeschen. Das passiert am Ende
+ //der Action im RemoveSuperfluous der Seite - angestossen von gleich-
+ //namiger Methode der Root.
+ //Die FlyColl kann bereits weg sein, weil der DTor der Seite
+ //gerade 'laeuft'
+ if ( pSortedObjs )
+ {
+ pSortedObjs->Remove( *pToRemove );
+ if ( !pSortedObjs->Count() )
+ { DELETEZ( pSortedObjs );
+ }
+ }
+ // #i28701# - use new method <SetPageFrm(..)>
+ pToRemove->SetPageFrm( 0L );
+}
+
+/*************************************************************************
+|*
+|* SwPageFrm::MoveFly
+|*
+|*************************************************************************/
+
+void SwPageFrm::MoveFly( SwFlyFrm *pToMove, SwPageFrm *pDest )
+{
+ //Invalidierungen
+ if ( GetUpper() )
+ {
+ ((SwRootFrm*)GetUpper())->SetIdleFlags();
+ if ( !pToMove->IsFlyInCntFrm() && pDest->GetPhyPageNum() < GetPhyPageNum() )
+ ((SwRootFrm*)GetUpper())->SetSuperfluous();
+ }
+
+ pDest->InvalidateSpelling();
+ pDest->InvalidateSmartTags(); // SMARTTAGS
+ pDest->InvalidateAutoCompleteWords();
+ pDest->InvalidateWordCount();
+
+ if ( pToMove->IsFlyInCntFrm() )
+ {
+ pDest->InvalidateFlyInCnt();
+ return;
+ }
+
+ // Notify accessible layout. That's required at this place for
+ // frames only where the anchor is moved. Creation of new frames
+ // is additionally handled by the SwFrmNotify class.
+ if( GetUpper() &&
+ static_cast< SwRootFrm * >( GetUpper() )->IsAnyShellAccessible() &&
+ static_cast< SwRootFrm * >( GetUpper() )->GetCurrShell() )
+ {
+ static_cast< SwRootFrm * >( GetUpper() )->GetCurrShell()->Imp()
+ ->DisposeAccessibleFrm( pToMove, sal_True );
+ }
+
+ //Die FlyColl kann bereits weg sein, weil der DTor der Seite
+ //gerade 'laeuft'
+ if ( pSortedObjs )
+ {
+ pSortedObjs->Remove( *pToMove );
+ if ( !pSortedObjs->Count() )
+ { DELETEZ( pSortedObjs );
+ }
+ }
+
+ //Anmelden
+ if ( !pDest->GetSortedObjs() )
+ pDest->pSortedObjs = new SwSortedObjs();
+
+#if OSL_DEBUG_LEVEL > 1
+ const bool bSucessInserted =
+#endif
+ pDest->GetSortedObjs()->Insert( *pToMove );
+#if OSL_DEBUG_LEVEL > 1
+ OSL_ENSURE( bSucessInserted, "Fly nicht in Sorted eingetragen." );
+ (void) bSucessInserted;
+#endif
+
+ // #i28701# - use new method <SetPageFrm(..)>
+ pToMove->SetPageFrm( pDest );
+ pToMove->InvalidatePage( pDest );
+ pToMove->SetNotifyBack();
+ pDest->InvalidateFlyCntnt();
+ // #i28701#
+ pToMove->UnlockPosition();
+
+ // Notify accessible layout. That's required at this place for
+ // frames only where the anchor is moved. Creation of new frames
+ // is additionally handled by the SwFrmNotify class.
+ if( GetUpper() &&
+ static_cast< SwRootFrm * >( GetUpper() )->IsAnyShellAccessible() &&
+ static_cast< SwRootFrm * >( GetUpper() )->GetCurrShell() )
+ {
+ static_cast< SwRootFrm * >( GetUpper() )->GetCurrShell()->Imp()
+ ->AddAccessibleFrm( pToMove );
+ }
+
+ // #i28701# - correction: move lowers of Writer fly frame
+ if ( pToMove->GetDrawObjs() )
+ {
+ SwSortedObjs &rObjs = *pToMove->GetDrawObjs();
+ for ( sal_uInt32 i = 0; i < rObjs.Count(); ++i )
+ {
+ SwAnchoredObject* pObj = rObjs[i];
+ if ( pObj->ISA(SwFlyFrm) )
+ {
+ SwFlyFrm* pFly = static_cast<SwFlyFrm*>(pObj);
+ if ( pFly->IsFlyFreeFrm() )
+ {
+ // #i28701# - use new method <GetPageFrm()>
+ SwPageFrm* pPageFrm = pFly->GetPageFrm();
+ if ( pPageFrm )
+ pPageFrm->MoveFly( pFly, pDest );
+ else
+ pDest->AppendFlyToPage( pFly );
+ }
+ }
+ else if ( pObj->ISA(SwAnchoredDrawObject) )
+ {
+ RemoveDrawObjFromPage( *pObj );
+ pDest->AppendDrawObjToPage( *pObj );
+ }
+ }
+ }
+}
+
+/*************************************************************************
+|*
+|* SwPageFrm::AppendDrawObjToPage(), RemoveDrawObjFromPage()
+|*
+|* #i28701# - new methods
+|*
+|*************************************************************************/
+void SwPageFrm::AppendDrawObjToPage( SwAnchoredObject& _rNewObj )
+{
+ if ( !_rNewObj.ISA(SwAnchoredDrawObject) )
+ {
+ OSL_FAIL( "SwPageFrm::AppendDrawObjToPage(..) - anchored object of unexcepted type -> object not appended" );
+ return;
+ }
+
+ if ( GetUpper() )
+ {
+ ((SwRootFrm*)GetUpper())->InvalidateBrowseWidth();
+ }
+
+ OSL_ENSURE( _rNewObj.GetAnchorFrm(), "anchored draw object without anchor" );
+ const SwFlyFrm* pFlyFrm = _rNewObj.GetAnchorFrm()->FindFlyFrm();
+ if ( pFlyFrm &&
+ _rNewObj.GetDrawObj()->GetOrdNum() < pFlyFrm->GetVirtDrawObj()->GetOrdNum() )
+ {
+ sal_uInt32 nNewNum = pFlyFrm->GetVirtDrawObj()->GetOrdNumDirect();
+ if ( _rNewObj.GetDrawObj()->GetPage() )
+ _rNewObj.DrawObj()->GetPage()->SetObjectOrdNum(
+ _rNewObj.GetDrawObj()->GetOrdNumDirect(), nNewNum);
+ else
+ _rNewObj.DrawObj()->SetOrdNum( nNewNum );
+ }
+
+ if ( FLY_AS_CHAR == _rNewObj.GetFrmFmt().GetAnchor().GetAnchorId() )
+ {
+ return;
+ }
+
+ if ( !pSortedObjs )
+ {
+ pSortedObjs = new SwSortedObjs();
+ }
+ if ( !pSortedObjs->Insert( _rNewObj ) )
+ {
+#if OSL_DEBUG_LEVEL > 1
+ OSL_ENSURE( pSortedObjs->Contains( _rNewObj ),
+ "Drawing object not appended into list <pSortedObjs>." );
+#endif
+ }
+ // #i87493#
+ OSL_ENSURE( _rNewObj.GetPageFrm() == 0 || _rNewObj.GetPageFrm() == this,
+ "<SwPageFrm::AppendDrawObjToPage(..)> - anchored draw object seems to be registered at another page frame. Serious defect -> please inform OD." );
+ _rNewObj.SetPageFrm( this );
+
+ // invalidate page in order to force a reformat of object layout of the page.
+ InvalidateFlyLayout();
+}
+
+void SwPageFrm::RemoveDrawObjFromPage( SwAnchoredObject& _rToRemoveObj )
+{
+ if ( !_rToRemoveObj.ISA(SwAnchoredDrawObject) )
+ {
+ OSL_FAIL( "SwPageFrm::RemoveDrawObjFromPage(..) - anchored object of unexcepted type -> object not removed" );
+ return;
+ }
+
+ if ( pSortedObjs )
+ {
+ pSortedObjs->Remove( _rToRemoveObj );
+ if ( !pSortedObjs->Count() )
+ {
+ DELETEZ( pSortedObjs );
+ }
+ if ( GetUpper() )
+ {
+ if (FLY_AS_CHAR !=
+ _rToRemoveObj.GetFrmFmt().GetAnchor().GetAnchorId())
+ {
+ ((SwRootFrm*)GetUpper())->SetSuperfluous();
+ InvalidatePage();
+ }
+ ((SwRootFrm*)GetUpper())->InvalidateBrowseWidth();
+ }
+ }
+ _rToRemoveObj.SetPageFrm( 0 );
+}
+
+/*************************************************************************
+|*
+|* SwPageFrm::PlaceFly
+|*
+|*************************************************************************/
+
+// #i50432# - adjust method description and synopsis.
+void SwPageFrm::PlaceFly( SwFlyFrm* pFly, SwFlyFrmFmt* pFmt )
+{
+ // #i50432# - consider the case that page is an empty page:
+ // In this case append the fly frame at the next page
+ OSL_ENSURE( !IsEmptyPage() || GetNext(),
+ "<SwPageFrm::PlaceFly(..)> - empty page with no next page! -> fly frame appended at empty page" );
+ if ( IsEmptyPage() && GetNext() )
+ {
+ static_cast<SwPageFrm*>(GetNext())->PlaceFly( pFly, pFmt );
+ }
+ else
+ {
+ //Wenn ein Fly uebergeben wurde, so benutzen wir diesen, ansonsten wird
+ //mit dem Format einer erzeugt.
+ if ( pFly )
+ AppendFly( pFly );
+ else
+ { OSL_ENSURE( pFmt, ":-( kein Format fuer Fly uebergeben." );
+ pFly = new SwFlyLayFrm( (SwFlyFrmFmt*)pFmt, this, this );
+ AppendFly( pFly );
+ ::RegistFlys( this, pFly );
+ }
+ }
+}
+
+/*************************************************************************
+|*
+|* ::CalcClipRect
+|*
+|*************************************************************************/
+// #i18732# - adjustments for following text flow or not
+// AND alignment at 'page areas' for to paragraph/to character anchored objects
+// #i22305# - adjustment for following text flow
+// for to frame anchored objects
+// #i29778# - Because the calculation of the position of the
+// floating screen object (Writer fly frame or drawing object) doesn't perform
+// a calculation on its upper frames and its anchor frame, a calculation of
+// the upper frames in this method no longer sensible.
+// #i28701# - if document compatibility option 'Consider
+// wrapping style influence on object positioning' is ON, the clip area
+// corresponds to the one as the object doesn't follows the text flow.
+sal_Bool CalcClipRect( const SdrObject *pSdrObj, SwRect &rRect, sal_Bool bMove )
+{
+ sal_Bool bRet = sal_True;
+ if ( pSdrObj->ISA(SwVirtFlyDrawObj) )
+ {
+ const SwFlyFrm* pFly = ((const SwVirtFlyDrawObj*)pSdrObj)->GetFlyFrm();
+ const bool bFollowTextFlow = pFly->GetFmt()->GetFollowTextFlow().GetValue();
+ // #i28701#
+ const bool bConsiderWrapOnObjPos =
+ pFly->GetFmt()->getIDocumentSettingAccess()->get(IDocumentSettingAccess::CONSIDER_WRAP_ON_OBJECT_POSITION);
+ const SwFmtVertOrient &rV = pFly->GetFmt()->GetVertOrient();
+ if( pFly->IsFlyLayFrm() )
+ {
+ const SwFrm* pClip;
+ // #i22305#
+ // #i28701#
+ if ( !bFollowTextFlow || bConsiderWrapOnObjPos )
+ {
+ pClip = pFly->GetAnchorFrm()->FindPageFrm();
+ }
+ else
+ {
+ pClip = pFly->GetAnchorFrm();
+ }
+
+ rRect = pClip->Frm();
+ SWRECTFN( pClip )
+
+ //Vertikales clipping: Top und Bottom, ggf. an PrtArea
+ if( rV.GetVertOrient() != text::VertOrientation::NONE &&
+ rV.GetRelationOrient() == text::RelOrientation::PRINT_AREA )
+ {
+ (rRect.*fnRect->fnSetTop)( (pClip->*fnRect->fnGetPrtTop)() );
+ (rRect.*fnRect->fnSetBottom)( (pClip->*fnRect->fnGetPrtBottom)() );
+ }
+ //Horizontales clipping: Left und Right, ggf. an PrtArea
+ const SwFmtHoriOrient &rH = pFly->GetFmt()->GetHoriOrient();
+ if( rH.GetHoriOrient() != text::HoriOrientation::NONE &&
+ rH.GetRelationOrient() == text::RelOrientation::PRINT_AREA )
+ {
+ (rRect.*fnRect->fnSetLeft)( (pClip->*fnRect->fnGetPrtLeft)() );
+ (rRect.*fnRect->fnSetRight)((pClip->*fnRect->fnGetPrtRight)());
+ }
+ }
+ else if( pFly->IsFlyAtCntFrm() )
+ {
+ // #i18732# - consider following text flow or not
+ // AND alignment at 'page areas'
+ const SwFrm* pVertPosOrientFrm = pFly->GetVertPosOrientFrm();
+ if ( !pVertPosOrientFrm )
+ {
+ OSL_FAIL( "::CalcClipRect(..) - frame, vertical position is oriented at, is missing .");
+ pVertPosOrientFrm = pFly->GetAnchorFrm();
+ }
+
+ if ( !bFollowTextFlow || bConsiderWrapOnObjPos )
+ {
+ const SwLayoutFrm* pClipFrm = pVertPosOrientFrm->FindPageFrm();
+ rRect = bMove ? pClipFrm->GetUpper()->Frm()
+ : pClipFrm->Frm();
+ // #i26945# - consider that a table, during
+ // its format, can exceed its upper printing area bottom.
+ // Thus, enlarge the clip rectangle, if such a case occurred
+ if ( pFly->GetAnchorFrm()->IsInTab() )
+ {
+ const SwTabFrm* pTabFrm = const_cast<SwFlyFrm*>(pFly)
+ ->GetAnchorFrmContainingAnchPos()->FindTabFrm();
+ SwRect aTmp( pTabFrm->Prt() );
+ aTmp += pTabFrm->Frm().Pos();
+ rRect.Union( aTmp );
+ // #i43913# - consider also the cell frame
+ const SwFrm* pCellFrm = const_cast<SwFlyFrm*>(pFly)
+ ->GetAnchorFrmContainingAnchPos()->GetUpper();
+ while ( pCellFrm && !pCellFrm->IsCellFrm() )
+ {
+ pCellFrm = pCellFrm->GetUpper();
+ }
+ if ( pCellFrm )
+ {
+ aTmp = pCellFrm->Prt();
+ aTmp += pCellFrm->Frm().Pos();
+ rRect.Union( aTmp );
+ }
+ }
+ }
+ else if ( rV.GetRelationOrient() == text::RelOrientation::PAGE_FRAME ||
+ rV.GetRelationOrient() == text::RelOrientation::PAGE_PRINT_AREA )
+ {
+ // new class <SwEnvironmentOfAnchoredObject>
+ objectpositioning::SwEnvironmentOfAnchoredObject
+ aEnvOfObj( bFollowTextFlow );
+ const SwLayoutFrm& rVertClipFrm =
+ aEnvOfObj.GetVertEnvironmentLayoutFrm( *pVertPosOrientFrm );
+ if ( rV.GetRelationOrient() == text::RelOrientation::PAGE_FRAME )
+ {
+ rRect = rVertClipFrm.Frm();
+ }
+ else if ( rV.GetRelationOrient() == text::RelOrientation::PAGE_PRINT_AREA )
+ {
+ if ( rVertClipFrm.IsPageFrm() )
+ {
+ rRect = static_cast<const SwPageFrm&>(rVertClipFrm).PrtWithoutHeaderAndFooter();
+ }
+ else
+ {
+ rRect = rVertClipFrm.Frm();
+ }
+ }
+ const SwLayoutFrm* pHoriClipFrm =
+ pFly->GetAnchorFrm()->FindPageFrm()->GetUpper();
+ SWRECTFN( pFly->GetAnchorFrm() )
+ (rRect.*fnRect->fnSetLeft)( (pHoriClipFrm->Frm().*fnRect->fnGetLeft)() );
+ (rRect.*fnRect->fnSetRight)((pHoriClipFrm->Frm().*fnRect->fnGetRight)());
+ }
+ else
+ {
+ // #i26945#
+ const SwFrm *pClip =
+ const_cast<SwFlyFrm*>(pFly)->GetAnchorFrmContainingAnchPos();
+ SWRECTFN( pClip )
+ const SwLayoutFrm *pUp = pClip->GetUpper();
+ const SwFrm *pCell = pUp->IsCellFrm() ? pUp : 0;
+ sal_uInt16 nType = bMove ? FRM_ROOT | FRM_FLY | FRM_HEADER |
+ FRM_FOOTER | FRM_FTN
+ : FRM_BODY | FRM_FLY | FRM_HEADER |
+ FRM_FOOTER | FRM_CELL| FRM_FTN;
+
+ while ( !(pUp->GetType() & nType) || pUp->IsColBodyFrm() )
+ {
+ pUp = pUp->GetUpper();
+ if ( !pCell && pUp->IsCellFrm() )
+ pCell = pUp;
+ }
+ if ( bMove )
+ {
+ if ( pUp->IsRootFrm() )
+ {
+ rRect = pUp->Prt();
+ rRect += pUp->Frm().Pos();
+ pUp = 0;
+ }
+ }
+ if ( pUp )
+ {
+ if ( pUp->GetType() & FRM_BODY )
+ {
+ const SwPageFrm *pPg;
+ if ( pUp->GetUpper() != (pPg = pFly->FindPageFrm()) )
+ pUp = pPg->FindBodyCont();
+ rRect = pUp->GetUpper()->Frm();
+ (rRect.*fnRect->fnSetTop)( (pUp->*fnRect->fnGetPrtTop)() );
+ (rRect.*fnRect->fnSetBottom)((pUp->*fnRect->fnGetPrtBottom)());
+ }
+ else
+ {
+ if( ( pUp->GetType() & (FRM_FLY | FRM_FTN ) ) &&
+ !pUp->Frm().IsInside( pFly->Frm().Pos() ) )
+ {
+ if( pUp->IsFlyFrm() )
+ {
+ SwFlyFrm *pTmpFly = (SwFlyFrm*)pUp;
+ while( pTmpFly->GetNextLink() )
+ {
+ pTmpFly = pTmpFly->GetNextLink();
+ if( pTmpFly->Frm().IsInside( pFly->Frm().Pos() ) )
+ break;
+ }
+ pUp = pTmpFly;
+ }
+ else if( pUp->IsInFtn() )
+ {
+ const SwFtnFrm *pTmp = pUp->FindFtnFrm();
+ while( pTmp->GetFollow() )
+ {
+ pTmp = pTmp->GetFollow();
+ if( pTmp->Frm().IsInside( pFly->Frm().Pos() ) )
+ break;
+ }
+ pUp = pTmp;
+ }
+ }
+ rRect = pUp->Prt();
+ rRect.Pos() += pUp->Frm().Pos();
+ if ( pUp->GetType() & (FRM_HEADER | FRM_FOOTER) )
+ {
+ rRect.Left ( pUp->GetUpper()->Frm().Left() );
+ rRect.Width( pUp->GetUpper()->Frm().Width());
+ }
+ else if ( pUp->IsCellFrm() ) //MA_FLY_HEIGHT
+ {
+ const SwFrm *pTab = pUp->FindTabFrm();
+ (rRect.*fnRect->fnSetBottom)(
+ (pTab->GetUpper()->*fnRect->fnGetPrtBottom)() );
+ // expand to left and right cell border
+ rRect.Left ( pUp->Frm().Left() );
+ rRect.Width( pUp->Frm().Width() );
+ }
+ }
+ }
+ if ( pCell )
+ {
+ //CellFrms koennen auch in 'unerlaubten' Bereichen stehen, dann
+ //darf der Fly das auch.
+ SwRect aTmp( pCell->Prt() );
+ aTmp += pCell->Frm().Pos();
+ rRect.Union( aTmp );
+ }
+ }
+ }
+ else
+ {
+ const SwFrm *pUp = pFly->GetAnchorFrm()->GetUpper();
+ SWRECTFN( pFly->GetAnchorFrm() )
+ while( pUp->IsColumnFrm() || pUp->IsSctFrm() || pUp->IsColBodyFrm())
+ pUp = pUp->GetUpper();
+ rRect = pUp->Frm();
+ if( !pUp->IsBodyFrm() )
+ {
+ rRect += pUp->Prt().Pos();
+ rRect.SSize( pUp->Prt().SSize() );
+ if ( pUp->IsCellFrm() )
+ {
+ const SwFrm *pTab = pUp->FindTabFrm();
+ (rRect.*fnRect->fnSetBottom)(
+ (pTab->GetUpper()->*fnRect->fnGetPrtBottom)() );
+ }
+ }
+ else if ( pUp->GetUpper()->IsPageFrm() )
+ {
+ // Objects anchored as character may exceed right margin
+ // of body frame:
+ (rRect.*fnRect->fnSetRight)( (pUp->GetUpper()->Frm().*fnRect->fnGetRight)() );
+ }
+ long nHeight = (9*(rRect.*fnRect->fnGetHeight)())/10;
+ long nTop;
+ const SwFmt *pFmt = ((SwContact*)GetUserCall(pSdrObj))->GetFmt();
+ const SvxULSpaceItem &rUL = pFmt->GetULSpace();
+ if( bMove )
+ {
+ nTop = bVert ? ((SwFlyInCntFrm*)pFly)->GetRefPoint().X() :
+ ((SwFlyInCntFrm*)pFly)->GetRefPoint().Y();
+ nTop = (*fnRect->fnYInc)( nTop, -nHeight );
+ long nWidth = (pFly->Frm().*fnRect->fnGetWidth)();
+ (rRect.*fnRect->fnSetLeftAndWidth)( bVert ?
+ ((SwFlyInCntFrm*)pFly)->GetRefPoint().Y() :
+ ((SwFlyInCntFrm*)pFly)->GetRefPoint().X(), nWidth );
+ nHeight = 2*nHeight - rUL.GetLower() - rUL.GetUpper();
+ }
+ else
+ {
+ nTop = (*fnRect->fnYInc)( (pFly->Frm().*fnRect->fnGetBottom)(),
+ rUL.GetLower() - nHeight );
+ nHeight = 2*nHeight - (pFly->Frm().*fnRect->fnGetHeight)()
+ - rUL.GetLower() - rUL.GetUpper();
+ }
+ (rRect.*fnRect->fnSetTopAndHeight)( nTop, nHeight );
+ }
+ }
+ else
+ {
+ const SwDrawContact *pC = (const SwDrawContact*)GetUserCall(pSdrObj);
+ const SwFrmFmt *pFmt = (const SwFrmFmt*)pC->GetFmt();
+ const SwFmtAnchor &rAnch = pFmt->GetAnchor();
+ if ( FLY_AS_CHAR == rAnch.GetAnchorId() )
+ {
+ const SwFrm* pAnchorFrm = pC->GetAnchorFrm( pSdrObj );
+ if( !pAnchorFrm )
+ {
+ OSL_FAIL( "<::CalcClipRect(..)> - missing anchor frame." );
+ ((SwDrawContact*)pC)->ConnectToLayout();
+ pAnchorFrm = pC->GetAnchorFrm();
+ }
+ const SwFrm* pUp = pAnchorFrm->GetUpper();
+ rRect = pUp->Prt();
+ rRect += pUp->Frm().Pos();
+ SWRECTFN( pAnchorFrm )
+ long nHeight = (9*(rRect.*fnRect->fnGetHeight)())/10;
+ long nTop;
+ const SvxULSpaceItem &rUL = pFmt->GetULSpace();
+ SwRect aSnapRect( pSdrObj->GetSnapRect() );
+ long nTmpH = 0;
+ if( bMove )
+ {
+ nTop = (*fnRect->fnYInc)( bVert ? pSdrObj->GetAnchorPos().X() :
+ pSdrObj->GetAnchorPos().Y(), -nHeight );
+ long nWidth = (aSnapRect.*fnRect->fnGetWidth)();
+ (rRect.*fnRect->fnSetLeftAndWidth)( bVert ?
+ pSdrObj->GetAnchorPos().Y() :
+ pSdrObj->GetAnchorPos().X(), nWidth );
+ }
+ else
+ {
+ // #i26791# - value of <nTmpH> is needed to
+ // calculate value of <nTop>.
+ nTmpH = bVert ? pSdrObj->GetCurrentBoundRect().GetWidth() :
+ pSdrObj->GetCurrentBoundRect().GetHeight();
+ nTop = (*fnRect->fnYInc)( (aSnapRect.*fnRect->fnGetTop)(),
+ rUL.GetLower() + nTmpH - nHeight );
+ }
+ nHeight = 2*nHeight - nTmpH - rUL.GetLower() - rUL.GetUpper();
+ (rRect.*fnRect->fnSetTopAndHeight)( nTop, nHeight );
+ }
+ else
+ {
+ // restrict clip rectangle for drawing
+ // objects in header/footer to the page frame.
+ // #i26791#
+ const SwFrm* pAnchorFrm = pC->GetAnchorFrm( pSdrObj );
+ if ( pAnchorFrm && pAnchorFrm->FindFooterOrHeader() )
+ {
+ // clip frame is the page frame the header/footer is on.
+ const SwFrm* pClipFrm = pAnchorFrm->FindPageFrm();
+ rRect = pClipFrm->Frm();
+ }
+ else
+ {
+ bRet = sal_False;
+ }
+ }
+ }
+ return bRet;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/layout/flypos.cxx b/sw/source/core/layout/flypos.cxx
new file mode 100644
index 000000000000..2c9c4e1b20f4
--- /dev/null
+++ b/sw/source/core/layout/flypos.cxx
@@ -0,0 +1,114 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+#include "doc.hxx"
+#include "node.hxx"
+#include <docary.hxx>
+#include <fmtanchr.hxx>
+#include "flypos.hxx"
+#include "frmfmt.hxx"
+#include "dcontact.hxx"
+#include "dview.hxx"
+#include "flyfrm.hxx"
+#include "dflyobj.hxx"
+#include "ndindex.hxx"
+#include "switerator.hxx"
+
+SV_IMPL_OP_PTRARR_SORT( SwPosFlyFrms, SwPosFlyFrmPtr )
+
+SwPosFlyFrm::SwPosFlyFrm( const SwNodeIndex& rIdx, const SwFrmFmt* pFmt,
+ sal_uInt16 nArrPos )
+ : pFrmFmt( pFmt ), pNdIdx( (SwNodeIndex*) &rIdx )
+{
+ bool bFnd = false;
+ const SwFmtAnchor& rAnchor = pFmt->GetAnchor();
+ if (FLY_AT_PAGE == rAnchor.GetAnchorId())
+ {
+ pNdIdx = new SwNodeIndex( rIdx );
+ }
+ else if( pFmt->GetDoc()->GetCurrentViewShell() ) //swmod 071108//swmod 071225
+ {
+ if( RES_FLYFRMFMT == pFmt->Which() )
+ {
+ // Schauen, ob es ein SdrObject dafuer gibt
+ SwFlyFrm* pFly = SwIterator<SwFlyFrm,SwFmt>::FirstElement(*pFmt);
+ if( pFly )
+ {
+ nOrdNum = pFly->GetVirtDrawObj()->GetOrdNum();
+ bFnd = true;
+ }
+ }
+ else if( RES_DRAWFRMFMT == pFmt->Which() )
+ {
+ // Schauen, ob es ein SdrObject dafuer gibt
+ SwDrawContact* pContact = SwIterator<SwDrawContact,SwFmt>::FirstElement(*pFmt);
+ if( pContact )
+ {
+ nOrdNum = pContact->GetMaster()->GetOrdNum();
+ bFnd = true;
+ }
+ }
+ }
+
+ if( !bFnd )
+ {
+ nOrdNum = pFmt->GetDoc()->GetSpzFrmFmts()->Count();
+ nOrdNum += nArrPos;
+ }
+}
+
+SwPosFlyFrm::~SwPosFlyFrm()
+{
+ const SwFmtAnchor& rAnchor = pFrmFmt->GetAnchor();
+ if (FLY_AT_PAGE == rAnchor.GetAnchorId())
+ {
+ delete pNdIdx;
+ }
+}
+
+sal_Bool SwPosFlyFrm::operator==( const SwPosFlyFrm& )
+{
+ return sal_False; // FlyFrames koennen auf der gleichen Position stehen
+}
+
+sal_Bool SwPosFlyFrm::operator<( const SwPosFlyFrm& rPosFly )
+{
+ if( pNdIdx->GetIndex() == rPosFly.pNdIdx->GetIndex() )
+ {
+ // dann entscheidet die Ordnungsnummer!
+ return nOrdNum < rPosFly.nOrdNum;
+ }
+ return pNdIdx->GetIndex() < rPosFly.pNdIdx->GetIndex();
+}
+
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/layout/frmtool.cxx b/sw/source/core/layout/frmtool.cxx
new file mode 100644
index 000000000000..56059a4aaf26
--- /dev/null
+++ b/sw/source/core/layout/frmtool.cxx
@@ -0,0 +1,3604 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+#include <hintids.hxx>
+#include <tools/bigint.hxx>
+#include <svx/svdmodel.hxx>
+#include <svx/svdpage.hxx>
+#include <editeng/brshitem.hxx>
+#include <editeng/keepitem.hxx>
+#include <editeng/shaditem.hxx>
+#include <editeng/ulspitem.hxx>
+#include <editeng/lrspitem.hxx>
+#include <editeng/boxitem.hxx>
+#include <sfx2/printer.hxx>
+#include <editeng/lspcitem.hxx>
+
+#include <fmtornt.hxx>
+#include <fmtanchr.hxx>
+#include <fmthdft.hxx>
+#include <fmtcntnt.hxx>
+#include <fmtfsize.hxx>
+#include <fmtsrnd.hxx>
+#include <docary.hxx>
+#include <lineinfo.hxx>
+#include <swmodule.hxx>
+#include "pagefrm.hxx"
+#include "colfrm.hxx"
+#include "doc.hxx"
+#include "fesh.hxx"
+#include "viewimp.hxx"
+#include "viewopt.hxx"
+#include "pam.hxx"
+#include "dflyobj.hxx"
+#include "dcontact.hxx"
+#include "frmtool.hxx"
+#include "docsh.hxx"
+#include "tabfrm.hxx"
+#include "rowfrm.hxx"
+#include "ftnfrm.hxx"
+#include "txtfrm.hxx"
+#include "notxtfrm.hxx"
+#include "flyfrms.hxx"
+#include "layact.hxx"
+#include "pagedesc.hxx"
+#include "section.hxx"
+#include "sectfrm.hxx"
+#include "node2lay.hxx"
+#include "ndole.hxx"
+#include "ndtxt.hxx"
+#include "swtable.hxx"
+#include "hints.hxx"
+#include <layhelp.hxx>
+#include <laycache.hxx>
+#include <rootfrm.hxx>
+#include "mdiexp.hxx"
+#include "statstr.hrc"
+#include <paratr.hxx>
+#include <sortedobjs.hxx>
+#include <objectformatter.hxx>
+#include <switerator.hxx>
+
+// ftnfrm.cxx:
+void lcl_RemoveFtns( SwFtnBossFrm* pBoss, sal_Bool bPageOnly, sal_Bool bEndNotes );
+
+using namespace ::com::sun::star;
+
+
+sal_Bool bObjsDirect = sal_True;
+sal_Bool bDontCreateObjects = sal_False;
+sal_Bool bSetCompletePaintOnInvalidate = sal_False;
+
+sal_uInt8 StackHack::nCnt = 0;
+sal_Bool StackHack::bLocked = sal_False;
+
+
+
+/*************************************************************************/
+
+SwFrmNotify::SwFrmNotify( SwFrm *pF ) :
+ pFrm( pF ),
+ aFrm( pF->Frm() ),
+ aPrt( pF->Prt() ),
+ bInvaKeep( sal_False ),
+ bValidSize( pF->GetValidSizeFlag() ),
+ mbFrmDeleted( false ) // #i49383#
+{
+ if ( pF->IsTxtFrm() )
+ {
+ mnFlyAnchorOfst = ((SwTxtFrm*)pF)->GetBaseOfstForFly( sal_True );
+ mnFlyAnchorOfstNoWrap = ((SwTxtFrm*)pF)->GetBaseOfstForFly( sal_False );
+ }
+ else
+ {
+ mnFlyAnchorOfst = 0;
+ mnFlyAnchorOfstNoWrap = 0;
+ }
+
+ bHadFollow = pF->IsCntntFrm() ?
+ (((SwCntntFrm*)pF)->GetFollow() ? sal_True : sal_False) :
+ sal_False;
+}
+
+/*************************************************************************/
+
+SwFrmNotify::~SwFrmNotify()
+{
+ // #i49383#
+ if ( mbFrmDeleted )
+ {
+ return;
+ }
+
+ SWRECTFN( pFrm )
+ const sal_Bool bAbsP = POS_DIFF( aFrm, pFrm->Frm() );
+ const sal_Bool bChgWidth =
+ (aFrm.*fnRect->fnGetWidth)() != (pFrm->Frm().*fnRect->fnGetWidth)();
+ const sal_Bool bChgHeight =
+ (aFrm.*fnRect->fnGetHeight)()!=(pFrm->Frm().*fnRect->fnGetHeight)();
+ const sal_Bool bChgFlyBasePos = pFrm->IsTxtFrm() &&
+ ( ( mnFlyAnchorOfst != ((SwTxtFrm*)pFrm)->GetBaseOfstForFly( sal_True ) ) ||
+ ( mnFlyAnchorOfstNoWrap != ((SwTxtFrm*)pFrm)->GetBaseOfstForFly( sal_False ) ) );
+
+ if ( pFrm->IsFlowFrm() && !pFrm->IsInFtn() )
+ {
+ SwFlowFrm *pFlow = SwFlowFrm::CastFlowFrm( pFrm );
+
+ if ( !pFlow->IsFollow() )
+ {
+ if ( !pFrm->GetIndPrev() )
+ {
+ if ( bInvaKeep )
+ {
+ SwFrm *pPre = pFrm->FindPrev();
+ if ( pPre && pPre->IsFlowFrm() )
+ {
+ // 1. pPre wants to keep with me:
+ bool bInvalidPrePos = SwFlowFrm::CastFlowFrm( pPre )->IsKeep( *pPre->GetAttrSet() ) && pPre->GetIndPrev();
+
+ // 2. pPre is a table and the last row wants to keep with me:
+ if ( !bInvalidPrePos && pPre->IsTabFrm() )
+ {
+ SwTabFrm* pPreTab = static_cast<SwTabFrm*>(pPre);
+ if ( pPreTab->GetFmt()->GetDoc()->get(IDocumentSettingAccess::TABLE_ROW_KEEP) )
+ {
+ SwRowFrm* pLastRow = static_cast<SwRowFrm*>(pPreTab->GetLastLower());
+ if ( pLastRow && pLastRow->ShouldRowKeepWithNext() )
+ bInvalidPrePos = true;
+ }
+ }
+
+ if ( bInvalidPrePos )
+ pPre->InvalidatePos();
+ }
+ }
+ }
+ else if ( !pFlow->HasFollow() )
+ {
+ long nOldHeight = (aFrm.*fnRect->fnGetHeight)();
+ long nNewHeight = (pFrm->Frm().*fnRect->fnGetHeight)();
+ if( (nOldHeight > nNewHeight) || (!nOldHeight && nNewHeight) )
+ pFlow->CheckKeep();
+ }
+ }
+ }
+
+ if ( bAbsP )
+ {
+ pFrm->SetCompletePaint();
+
+ SwFrm* pNxt = pFrm->GetIndNext();
+ // #121888# - skip empty section frames
+ while ( pNxt &&
+ pNxt->IsSctFrm() && !static_cast<SwSectionFrm*>(pNxt)->GetSection() )
+ {
+ pNxt = pNxt->GetIndNext();
+ }
+
+ if ( pNxt )
+ pNxt->InvalidatePos();
+ else
+ {
+ // #104100# - correct condition for setting retouche
+ // flag for vertical layout.
+ if( pFrm->IsRetoucheFrm() &&
+ (aFrm.*fnRect->fnTopDist)( (pFrm->Frm().*fnRect->fnGetTop)() ) > 0 )
+ {
+ pFrm->SetRetouche();
+ }
+
+ // A fresh follow frame does not have to be invalidated, because
+ // it is already formatted:
+ if ( bHadFollow || !pFrm->IsCntntFrm() || !((SwCntntFrm*)pFrm)->GetFollow() )
+ {
+ if ( !pFrm->IsTabFrm() || !((SwTabFrm*)pFrm)->GetFollow() )
+ pFrm->InvalidateNextPos();
+ }
+ }
+ }
+
+ //Fuer Hintergrundgrafiken muss bei Groessenaenderungen ein Repaint her.
+ const sal_Bool bPrtWidth =
+ (aPrt.*fnRect->fnGetWidth)() != (pFrm->Prt().*fnRect->fnGetWidth)();
+ const sal_Bool bPrtHeight =
+ (aPrt.*fnRect->fnGetHeight)()!=(pFrm->Prt().*fnRect->fnGetHeight)();
+ if ( bPrtWidth || bPrtHeight )
+ {
+ const SvxGraphicPosition ePos = pFrm->GetAttrSet()->GetBackground().GetGraphicPos();
+ if ( GPOS_NONE != ePos && GPOS_TILED != ePos )
+ pFrm->SetCompletePaint();
+ }
+ else
+ {
+ // #97597# - consider case that *only* margins between
+ // frame and printing area has changed. Then, frame has to be repainted,
+ // in order to force paint of the margin areas.
+ if ( !bAbsP && (bChgWidth || bChgHeight) )
+ {
+ pFrm->SetCompletePaint();
+ }
+ }
+
+ const sal_Bool bPrtP = POS_DIFF( aPrt, pFrm->Prt() );
+ if ( bAbsP || bPrtP || bChgWidth || bChgHeight ||
+ bPrtWidth || bPrtHeight || bChgFlyBasePos )
+ {
+ if( pFrm->IsAccessibleFrm() )
+ {
+ SwRootFrm *pRootFrm = pFrm->getRootFrm();
+ if( pRootFrm && pRootFrm->IsAnyShellAccessible() &&
+ pRootFrm->GetCurrShell() )
+ {
+ pRootFrm->GetCurrShell()->Imp()->MoveAccessibleFrm( pFrm, aFrm );
+ }
+ }
+
+ // Notification of anchored objects
+ if ( pFrm->GetDrawObjs() )
+ {
+ const SwSortedObjs &rObjs = *pFrm->GetDrawObjs();
+ SwPageFrm* pPageFrm = 0;
+ for ( sal_uInt32 i = 0; i < rObjs.Count(); ++i )
+ {
+ // OD 2004-03-31 #i26791# - no general distinction between
+ // Writer fly frames and drawing objects
+ bool bNotify = false;
+ bool bNotifySize = false;
+ SwAnchoredObject* pObj = rObjs[i];
+ SwContact* pContact = ::GetUserCall( pObj->GetDrawObj() );
+ // --> OD 2004-12-08 #115759#
+ const bool bAnchoredAsChar = pContact->ObjAnchoredAsChar();
+ if ( !bAnchoredAsChar )
+ // <--
+ {
+ // Notify object, which aren't anchored as-character:
+
+ // always notify objects, if frame position has changed
+ // or if the object is to-page|to-fly anchored.
+ if ( bAbsP ||
+ pContact->ObjAnchoredAtPage() ||
+ pContact->ObjAnchoredAtFly() )
+ {
+ bNotify = true;
+
+ // assure that to-fly anchored Writer fly frames are
+ // registered at the correct page frame, if frame
+ // position has changed.
+ if ( bAbsP && pContact->ObjAnchoredAtFly() &&
+ pObj->ISA(SwFlyFrm) )
+ {
+ // determine to-fly anchored Writer fly frame
+ SwFlyFrm* pFlyFrm = static_cast<SwFlyFrm*>(pObj);
+ // determine page frame of to-fly anchored
+ // Writer fly frame
+ SwPageFrm* pFlyPageFrm = pFlyFrm->FindPageFrm();
+ // determine page frame, if needed.
+ if ( !pPageFrm )
+ {
+ pPageFrm = pFrm->FindPageFrm();
+ }
+ if ( pPageFrm != pFlyPageFrm )
+ {
+ OSL_ENSURE( pFlyPageFrm, "~SwFrmNotify: Fly from Nowhere" );
+ if( pFlyPageFrm )
+ pFlyPageFrm->MoveFly( pFlyFrm, pPageFrm );
+ else
+ pPageFrm->AppendFlyToPage( pFlyFrm );
+ }
+ }
+ }
+ // otherwise the objects are notified in dependence to
+ // its positioning and alignment
+ else
+ {
+ const SwFmtVertOrient& rVert =
+ pContact->GetFmt()->GetVertOrient();
+ if ( ( rVert.GetVertOrient() == text::VertOrientation::CENTER ||
+ rVert.GetVertOrient() == text::VertOrientation::BOTTOM ||
+ rVert.GetRelationOrient() == text::RelOrientation::PRINT_AREA ) &&
+ ( bChgHeight || bPrtHeight ) )
+ {
+ bNotify = true;
+ }
+ if ( !bNotify )
+ {
+ const SwFmtHoriOrient& rHori =
+ pContact->GetFmt()->GetHoriOrient();
+ if ( ( rHori.GetHoriOrient() != text::HoriOrientation::NONE ||
+ rHori.GetRelationOrient()== text::RelOrientation::PRINT_AREA ||
+ rHori.GetRelationOrient()== text::RelOrientation::FRAME ) &&
+ ( bChgWidth || bPrtWidth || bChgFlyBasePos ) )
+ {
+ bNotify = true;
+ }
+ }
+ }
+ }
+ else if ( bPrtWidth )
+ {
+ // Notify as-character anchored objects, if printing area
+ // width has changed.
+ bNotify = true;
+ bNotifySize = true;
+ }
+
+ // perform notification via the corresponding invalidations
+ if ( bNotify )
+ {
+ if ( pObj->ISA(SwFlyFrm) )
+ {
+ SwFlyFrm* pFlyFrm = static_cast<SwFlyFrm*>(pObj);
+ if ( bNotifySize )
+ pFlyFrm->_InvalidateSize();
+ // --> OD 2004-12-08 #115759# - no invalidation of
+ // position for as-character anchored objects.
+ if ( !bAnchoredAsChar )
+ {
+ pFlyFrm->_InvalidatePos();
+ }
+ // <--
+ pFlyFrm->_Invalidate();
+ }
+ else if ( pObj->ISA(SwAnchoredDrawObject) )
+ {
+ // --> OD 2004-12-08 #115759# - no invalidation of
+ // position for as-character anchored objects.
+ if ( !bAnchoredAsChar )
+ {
+ pObj->InvalidateObjPos();
+ }
+ // <--
+ }
+ else
+ {
+ OSL_FAIL( "<SwCntntNotify::~SwCntntNotify()> - unknown anchored object type. Please inform OD." );
+ }
+ }
+ }
+ }
+ }
+ else if( pFrm->IsTxtFrm() && bValidSize != pFrm->GetValidSizeFlag() )
+ {
+ SwRootFrm *pRootFrm = pFrm->getRootFrm();
+ if( pRootFrm && pRootFrm->IsAnyShellAccessible() &&
+ pRootFrm->GetCurrShell() )
+ {
+ pRootFrm->GetCurrShell()->Imp()->InvalidateAccessibleFrmContent( pFrm );
+ }
+ }
+
+ // #i9046# Automatic frame width
+ SwFlyFrm* pFly = 0;
+ // --> FME 2004-10-21 #i35879# Do not trust the inf flags. pFrm does not
+ // necessarily have to have an upper!
+ if ( !pFrm->IsFlyFrm() && 0 != ( pFly = pFrm->ImplFindFlyFrm() ) )
+ // <--
+ {
+ // --> OD 2006-05-08 #i61999#
+ // no invalidation of columned Writer fly frames, because automatic
+ // width doesn't make sense for such Writer fly frames.
+ if ( pFly->Lower() && !pFly->Lower()->IsColumnFrm() )
+ {
+ const SwFmtFrmSize &rFrmSz = pFly->GetFmt()->GetFrmSize();
+
+ // This could be optimized. Basically the fly frame only has to
+ // be invalidated, if the first line of pFrm (if pFrm is a content
+ // frame, for other frame types its the print area) has changed its
+ // size and pFrm was responsible for the current width of pFly. On
+ // the other hand, this is only rarely used and re-calculation of
+ // the fly frame does not cause too much trouble. So we keep it this
+ // way:
+ if ( ATT_FIX_SIZE != rFrmSz.GetWidthSizeType() )
+ {
+ // --> OD 2005-07-29 #i50668#, #i50998# - invalidation of position
+ // of as-character anchored fly frames not needed and can cause
+ // layout loops
+ if ( !pFly->ISA(SwFlyInCntFrm) )
+ {
+ pFly->InvalidatePos();
+ }
+ // <--
+ pFly->InvalidateSize();
+ }
+ }
+ // <--
+ }
+}
+
+/*************************************************************************/
+
+SwLayNotify::SwLayNotify( SwLayoutFrm *pLayFrm ) :
+ SwFrmNotify( pLayFrm ),
+ bLowersComplete( sal_False )
+{
+}
+
+/*************************************************************************/
+
+// OD 2004-05-11 #i28701# - local method to invalidate the position of all
+// frames inclusive its floating screen objects, which are lowers of the given
+// layout frame
+void lcl_InvalidatePosOfLowers( SwLayoutFrm& _rLayoutFrm )
+{
+ if( _rLayoutFrm.IsFlyFrm() && _rLayoutFrm.GetDrawObjs() )
+ {
+ _rLayoutFrm.InvalidateObjs( true, false );
+ }
+
+ SwFrm* pLowerFrm = _rLayoutFrm.Lower();
+ while ( pLowerFrm )
+ {
+ pLowerFrm->InvalidatePos();
+ if ( pLowerFrm->IsTxtFrm() )
+ {
+ static_cast<SwTxtFrm*>(pLowerFrm)->Prepare( PREP_POS_CHGD );
+ }
+ else if ( pLowerFrm->IsTabFrm() )
+ {
+ pLowerFrm->InvalidatePrt();
+ }
+
+ pLowerFrm->InvalidateObjs( true, false );
+
+ pLowerFrm = pLowerFrm->GetNext();
+ };
+}
+
+SwLayNotify::~SwLayNotify()
+{
+ // --> OD 2005-07-29 #i49383#
+ if ( mbFrmDeleted )
+ {
+ return;
+ }
+ // <--
+
+ SwLayoutFrm *pLay = GetLay();
+ SWRECTFN( pLay )
+ sal_Bool bNotify = sal_False;
+ if ( pLay->Prt().SSize() != aPrt.SSize() )
+ {
+ if ( !IsLowersComplete() )
+ {
+ sal_Bool bInvaPercent;
+
+ if ( pLay->IsRowFrm() )
+ {
+ bInvaPercent = sal_True;
+ long nNew = (pLay->Prt().*fnRect->fnGetHeight)();
+ if( nNew != (aPrt.*fnRect->fnGetHeight)() )
+ ((SwRowFrm*)pLay)->AdjustCells( nNew, sal_True);
+ if( (pLay->Prt().*fnRect->fnGetWidth)()
+ != (aPrt.*fnRect->fnGetWidth)() )
+ ((SwRowFrm*)pLay)->AdjustCells( 0, sal_False );
+ }
+ else
+ {
+ //Proportionale Anpassung der innenliegenden.
+ //1. Wenn der Formatierte kein Fly ist
+ //2. Wenn er keine Spalten enthaelt
+ //3. Wenn der Fly eine feste Hoehe hat und die Spalten in der
+ // Hoehe danebenliegen.
+ //4. niemals bei SectionFrms.
+ sal_Bool bLow;
+ if( pLay->IsFlyFrm() )
+ {
+ if ( pLay->Lower() )
+ {
+ bLow = !pLay->Lower()->IsColumnFrm() ||
+ (pLay->Lower()->Frm().*fnRect->fnGetHeight)()
+ != (pLay->Prt().*fnRect->fnGetHeight)();
+ }
+ else
+ bLow = sal_False;
+ }
+ else if( pLay->IsSctFrm() )
+ {
+ if ( pLay->Lower() )
+ {
+ if( pLay->Lower()->IsColumnFrm() && pLay->Lower()->GetNext() )
+ bLow = pLay->Lower()->Frm().Height() != pLay->Prt().Height();
+ else
+ bLow = pLay->Prt().Width() != aPrt.Width();
+ }
+ else
+ bLow = sal_False;
+ }
+ else if( pLay->IsFooterFrm() && !pLay->HasFixSize() )
+ bLow = pLay->Prt().Width() != aPrt.Width();
+ else
+ bLow = sal_True;
+ bInvaPercent = bLow;
+ if ( bLow )
+ {
+ pLay->ChgLowersProp( aPrt.SSize() );
+ }
+ //Wenn die PrtArea gewachsen ist, so ist es moeglich, dass die
+ //Kette der Untergeordneten einen weiteren Frm aufnehmen kann,
+ //mithin muss also der 'moeglicherweise passende' Invalidiert werden.
+ //Das invalidieren lohnt nur, wenn es sich beim mir bzw. meinen
+ //Uppers um eine Moveable-Section handelt.
+ //Die PrtArea ist gewachsen, wenn die Breite oder die Hoehe groesser
+ //geworden ist.
+ if ( (pLay->Prt().Height() > aPrt.Height() ||
+ pLay->Prt().Width() > aPrt.Width()) &&
+ (pLay->IsMoveable() || pLay->IsFlyFrm()) )
+ {
+ SwFrm *pTmpFrm = pLay->Lower();
+ if ( pTmpFrm && pTmpFrm->IsFlowFrm() )
+ {
+ while ( pTmpFrm->GetNext() )
+ pTmpFrm = pTmpFrm->GetNext();
+ pTmpFrm->InvalidateNextPos();
+ }
+ }
+ }
+ bNotify = sal_True;
+ //TEUER!! aber wie macht man es geschickter?
+ if( bInvaPercent )
+ pLay->InvaPercentLowers( pLay->Prt().Height() - aPrt.Height() );
+ }
+ if ( pLay->IsTabFrm() )
+ //Damit _nur_ der Shatten bei Groessenaenderungen gemalt wird.
+ ((SwTabFrm*)pLay)->SetComplete();
+ else
+ {
+ const ViewShell *pSh = pLay->getRootFrm()->GetCurrShell();
+ if( !( pSh && pSh->GetViewOptions()->getBrowseMode() ) ||
+ !(pLay->GetType() & (FRM_BODY | FRM_PAGE)) )
+ //Damit die untergeordneten sauber retouchiert werden.
+ //Problembsp: Flys an den Henkeln packen und verkleinern.
+ //Nicht fuer Body und Page, sonst flackerts beim HTML-Laden.
+ pLay->SetCompletePaint();
+ }
+ }
+ //Lower benachrichtigen wenn sich die Position veraendert hat.
+ const sal_Bool bPrtPos = POS_DIFF( aPrt, pLay->Prt() );
+ const sal_Bool bPos = bPrtPos || POS_DIFF( aFrm, pLay->Frm() );
+ const sal_Bool bSize = pLay->Frm().SSize() != aFrm.SSize();
+
+ if ( bPos && pLay->Lower() && !IsLowersComplete() )
+ pLay->Lower()->InvalidatePos();
+
+ if ( bPrtPos )
+ pLay->SetCompletePaint();
+
+ //Nachfolger benachrichtigen wenn sich die SSize geaendert hat.
+ if ( bSize )
+ {
+ if( pLay->GetNext() )
+ {
+ if ( pLay->GetNext()->IsLayoutFrm() )
+ pLay->GetNext()->_InvalidatePos();
+ else
+ pLay->GetNext()->InvalidatePos();
+ }
+ else if( pLay->IsSctFrm() )
+ pLay->InvalidateNextPos();
+ }
+ if ( !IsLowersComplete() &&
+ !(pLay->GetType()&(FRM_FLY|FRM_SECTION) &&
+ pLay->Lower() && pLay->Lower()->IsColumnFrm()) &&
+ (bPos || bNotify) && !(pLay->GetType() & 0x1823) ) //Tab, Row, FtnCont, Root, Page
+ {
+ // --> OD 2005-03-11 #i44016# - force unlock of position of lower objects.
+ // --> OD 2005-03-30 #i43913# - no unlock of position of objects,
+ // if <pLay> is a cell frame, and its table frame resp. its parent table
+ // frame is locked.
+ // --> OD 2005-04-15 #i47458# - force unlock of position of lower objects,
+ // only if position of layout frame has changed.
+ bool bUnlockPosOfObjs( bPos );
+ if ( bUnlockPosOfObjs && pLay->IsCellFrm() )
+ {
+ SwTabFrm* pTabFrm( pLay->FindTabFrm() );
+ if ( pTabFrm &&
+ ( pTabFrm->IsJoinLocked() ||
+ ( pTabFrm->IsFollow() &&
+ pTabFrm->FindMaster()->IsJoinLocked() ) ) )
+ {
+ bUnlockPosOfObjs = false;
+ }
+ }
+ // --> OD 2005-05-18 #i49383# - check for footnote frame, if unlock
+ // of position of lower objects is allowed.
+ else if ( bUnlockPosOfObjs && pLay->IsFtnFrm() )
+ {
+ bUnlockPosOfObjs = static_cast<SwFtnFrm*>(pLay)->IsUnlockPosOfLowerObjs();
+ }
+ // <--
+ // --> OD 2005-07-29 #i51303# - no unlock of object positions for sections
+ else if ( bUnlockPosOfObjs && pLay->IsSctFrm() )
+ {
+ bUnlockPosOfObjs = false;
+ }
+ // <--
+ pLay->NotifyLowerObjs( bUnlockPosOfObjs );
+ // <--
+ }
+ if ( bPos && pLay->IsFtnFrm() && pLay->Lower() )
+ {
+ // OD 2004-05-11 #i28701#
+ ::lcl_InvalidatePosOfLowers( *pLay );
+ }
+ if( ( bPos || bSize ) && pLay->IsFlyFrm() && ((SwFlyFrm*)pLay)->GetAnchorFrm()
+ && ((SwFlyFrm*)pLay)->GetAnchorFrm()->IsFlyFrm() )
+ ((SwFlyFrm*)pLay)->AnchorFrm()->InvalidateSize();
+}
+
+/*************************************************************************/
+
+SwFlyNotify::SwFlyNotify( SwFlyFrm *pFlyFrm ) :
+ SwLayNotify( pFlyFrm ),
+ // --> OD 2004-11-24 #115759# - keep correct page frame - the page frame
+ // the Writer fly frame is currently registered at.
+ pOldPage( pFlyFrm->GetPageFrm() ),
+ // <--
+ aFrmAndSpace( pFlyFrm->GetObjRectWithSpaces() )
+{
+}
+
+/*************************************************************************/
+
+SwFlyNotify::~SwFlyNotify()
+{
+ // --> OD 2005-07-29 #i49383#
+ if ( mbFrmDeleted )
+ {
+ return;
+ }
+ // <--
+
+ SwFlyFrm *pFly = GetFly();
+ if ( pFly->IsNotifyBack() )
+ {
+ ViewShell *pSh = pFly->getRootFrm()->GetCurrShell();
+ SwViewImp *pImp = pSh ? pSh->Imp() : 0;
+ if ( !pImp || !pImp->IsAction() || !pImp->GetLayAction().IsAgain() )
+ {
+ //Wenn in der LayAction das IsAgain gesetzt ist kann es sein,
+ //dass die alte Seite inzwischen vernichtet wurde!
+ ::Notify( pFly, pOldPage, aFrmAndSpace, &aPrt );
+ // --> OD 2004-10-20 #i35640# - additional notify anchor text frame,
+ // if Writer fly frame has changed its page
+ if ( pFly->GetAnchorFrm()->IsTxtFrm() &&
+ pFly->GetPageFrm() != pOldPage )
+ {
+ pFly->AnchorFrm()->Prepare( PREP_FLY_LEAVE );
+ }
+ // <--
+ }
+ pFly->ResetNotifyBack();
+ }
+
+ //Haben sich Groesse oder Position geaendert, so sollte die View
+ //das wissen.
+ SWRECTFN( pFly )
+ const bool bPosChgd = POS_DIFF( aFrm, pFly->Frm() );
+ const bool bFrmChgd = pFly->Frm().SSize() != aFrm.SSize();
+ const bool bPrtChgd = aPrt != pFly->Prt();
+ if ( bPosChgd || bFrmChgd || bPrtChgd )
+ {
+ pFly->NotifyDrawObj();
+ }
+ if ( bPosChgd && aFrm.Pos().X() != WEIT_WECH )
+ {
+ // OD 2004-05-10 #i28701# - no direct move of lower Writer fly frames.
+ // reason: New positioning and alignment (e.g. to-paragraph anchored,
+ // but aligned at page) are introduced.
+ // <SwLayNotify::~SwLayNotify()> takes care of invalidation of lower
+ // floating screen objects by calling method <SwLayoutFrm::NotifyLowerObjs()>.
+
+ if ( pFly->IsFlyAtCntFrm() )
+ {
+ SwFrm *pNxt = pFly->AnchorFrm()->FindNext();
+ if ( pNxt )
+ {
+ pNxt->InvalidatePos();
+ }
+ }
+
+ // --> OD 2004-11-05 #i26945# - notify anchor.
+ // Needed for negative positioned Writer fly frames
+ if ( pFly->GetAnchorFrm()->IsTxtFrm() )
+ {
+ pFly->AnchorFrm()->Prepare( PREP_FLY_LEAVE );
+ }
+ // <--
+ }
+
+ // OD 2004-05-13 #i28701#
+ // --> OD 2005-03-21 #i45180# - no adjustment of layout process flags and
+ // further notifications/invalidations, if format is called by grow/shrink
+ if ( pFly->ConsiderObjWrapInfluenceOnObjPos() &&
+ ( !pFly->ISA(SwFlyFreeFrm) ||
+ !static_cast<SwFlyFreeFrm*>(pFly)->IsNoMoveOnCheckClip() ) )
+ // <--
+ {
+ // --> OD 2005-09-05 #i54138# - suppress restart of the layout process
+ // on changed frame height.
+ // Note: It doesn't seem to be necessary and can cause layout loops.
+ if ( bPosChgd )
+ // <--
+ {
+ // indicate a restart of the layout process
+ pFly->SetRestartLayoutProcess( true );
+ }
+ else
+ {
+ // lock position
+ pFly->LockPosition();
+
+ if ( !pFly->ConsiderForTextWrap() )
+ {
+ // indicate that object has to be considered for text wrap
+ pFly->SetConsiderForTextWrap( true );
+ // invalidate 'background' in order to allow its 'background'
+ // to wrap around it.
+ pFly->NotifyBackground( pFly->GetPageFrm(),
+ pFly->GetObjRectWithSpaces(),
+ PREP_FLY_ARRIVE );
+ // invalidate position of anchor frame in order to force
+ // a re-format of the anchor frame, which also causes a
+ // re-format of the invalid previous frames of the anchor frame.
+ pFly->AnchorFrm()->InvalidatePos();
+ }
+ }
+ }
+}
+
+/*************************************************************************/
+
+SwCntntNotify::SwCntntNotify( SwCntntFrm *pCntntFrm ) :
+ SwFrmNotify( pCntntFrm ),
+ // OD 08.01.2004 #i11859#
+ mbChkHeightOfLastLine( false ),
+ mnHeightOfLastLine( 0L ),
+ // OD 2004-02-26 #i25029#
+ mbInvalidatePrevPrtArea( false ),
+ mbBordersJoinedWithPrev( false )
+{
+ // OD 08.01.2004 #i11859#
+ if ( pCntntFrm->IsTxtFrm() )
+ {
+ SwTxtFrm* pTxtFrm = static_cast<SwTxtFrm*>(pCntntFrm);
+ if ( !pTxtFrm->GetTxtNode()->getIDocumentSettingAccess()->get(IDocumentSettingAccess::OLD_LINE_SPACING) )
+ {
+ const SwAttrSet* pSet = pTxtFrm->GetAttrSet();
+ const SvxLineSpacingItem &rSpace = pSet->GetLineSpacing();
+ if ( rSpace.GetInterLineSpaceRule() == SVX_INTER_LINE_SPACE_PROP )
+ {
+ mbChkHeightOfLastLine = true;
+ mnHeightOfLastLine = pTxtFrm->GetHeightOfLastLine();
+ }
+ }
+ }
+}
+
+/*************************************************************************/
+
+SwCntntNotify::~SwCntntNotify()
+{
+ // --> OD 2005-07-29 #i49383#
+ if ( mbFrmDeleted )
+ {
+ return;
+ }
+ // <--
+
+ SwCntntFrm *pCnt = GetCnt();
+ if ( bSetCompletePaintOnInvalidate )
+ pCnt->SetCompletePaint();
+
+ SWRECTFN( pCnt )
+ if ( pCnt->IsInTab() && ( POS_DIFF( pCnt->Frm(), aFrm ) ||
+ pCnt->Frm().SSize() != aFrm.SSize()))
+ {
+ SwLayoutFrm* pCell = pCnt->GetUpper();
+ while( !pCell->IsCellFrm() && pCell->GetUpper() )
+ pCell = pCell->GetUpper();
+ OSL_ENSURE( pCell->IsCellFrm(), "Where's my cell?" );
+ if ( text::VertOrientation::NONE != pCell->GetFmt()->GetVertOrient().GetVertOrient() )
+ pCell->InvalidatePrt(); //fuer vertikale Ausrichtung.
+ }
+
+ // OD 2004-02-26 #i25029#
+ if ( mbInvalidatePrevPrtArea && mbBordersJoinedWithPrev &&
+ pCnt->IsTxtFrm() &&
+ !pCnt->IsFollow() && !pCnt->GetIndPrev() )
+ {
+ // determine previous frame
+ SwFrm* pPrevFrm = pCnt->FindPrev();
+ // skip empty section frames and hidden text frames
+ {
+ while ( pPrevFrm &&
+ ( ( pPrevFrm->IsSctFrm() &&
+ !static_cast<SwSectionFrm*>(pPrevFrm)->GetSection() ) ||
+ ( pPrevFrm->IsTxtFrm() &&
+ static_cast<SwTxtFrm*>(pPrevFrm)->IsHiddenNow() ) ) )
+ {
+ pPrevFrm = pPrevFrm->FindPrev();
+ }
+ }
+
+ // Invalidate printing area of found previous frame
+ if ( pPrevFrm )
+ {
+ if ( pPrevFrm->IsSctFrm() )
+ {
+ if ( pCnt->IsInSct() )
+ {
+ // Note: found previous frame is a section frame and
+ // <pCnt> is also inside a section.
+ // Thus due to <mbBordersJoinedWithPrev>,
+ // <pCnt> had joined its borders/shadow with the
+ // last content of the found section.
+ // Invalidate printing area of last content in found section.
+ SwFrm* pLstCntntOfSctFrm =
+ static_cast<SwSectionFrm*>(pPrevFrm)->FindLastCntnt();
+ if ( pLstCntntOfSctFrm )
+ {
+ pLstCntntOfSctFrm->InvalidatePrt();
+ }
+ }
+ }
+ else
+ {
+ pPrevFrm->InvalidatePrt();
+ }
+ }
+ }
+
+ sal_Bool bFirst = (aFrm.*fnRect->fnGetWidth)() == 0;
+
+ if ( pCnt->IsNoTxtFrm() )
+ {
+ //Aktive PlugIn's oder OLE-Objekte sollten etwas von der Veraenderung
+ //mitbekommen, damit sie Ihr Window entsprechend verschieben.
+ ViewShell *pSh = pCnt->getRootFrm()->GetCurrShell();
+ if ( pSh )
+ {
+ SwOLENode *pNd;
+ if ( 0 != (pNd = pCnt->GetNode()->GetOLENode()) &&
+ (pNd->GetOLEObj().IsOleRef() ||
+ pNd->IsOLESizeInvalid()) )
+ {
+ OSL_ENSURE( pCnt->IsInFly(), "OLE not in FlyFrm" );
+ SwFlyFrm *pFly = pCnt->FindFlyFrm();
+ svt::EmbeddedObjectRef& xObj = pNd->GetOLEObj().GetObject();
+ SwFEShell *pFESh = 0;
+ ViewShell *pTmp = pSh;
+ do
+ { if ( pTmp->ISA( SwCrsrShell ) )
+ {
+ pFESh = (SwFEShell*)pTmp;
+ // #108369#: Here used to be the condition if (!bFirst).
+ // I think this should mean "do not call CalcAndSetScale"
+ // if the frame is formatted for the first time.
+ // Unfortunately this is not valid anymore since the
+ // SwNoTxtFrm already gets a width during CalcLowerPreps.
+ // Nevertheless, the indention of !bFirst seemed to be
+ // to assure that the OLE objects have already been notified
+ // if necessary before calling CalcAndSetScale.
+ // So I replaced !bFirst by !IsOLESizeInvalid. There is
+ // one additional problem specific to the word import:
+ // The layout is calculated _before_ calling PrtOLENotify,
+ // and the OLE objects are not invalidated during import.
+ // Therefore I added the condition !IsUpdateExpFld,
+ // have a look at the occurrence of CalcLayout in
+ // uiview/view.cxx.
+ if ( !pNd->IsOLESizeInvalid() &&
+ !pSh->GetDoc()->IsUpdateExpFld() )
+ pFESh->CalcAndSetScale( xObj, &pFly->Prt(), &pFly->Frm());
+ }
+ pTmp = (ViewShell*)pTmp->GetNext();
+ } while ( pTmp != pSh );
+
+ if ( pFESh && pNd->IsOLESizeInvalid() )
+ {
+ pNd->SetOLESizeInvalid( sal_False );
+ //TODO/LATER: needs OnDocumentPrinterChanged
+ //xObj->OnDocumentPrinterChanged( pNd->GetDoc()->getPrinter( false ) );
+ pFESh->CalcAndSetScale( xObj );//Client erzeugen lassen.
+ }
+ }
+ //dito Animierte Grafiken
+ if ( Frm().HasArea() && ((SwNoTxtFrm*)pCnt)->HasAnimation() )
+ {
+ ((SwNoTxtFrm*)pCnt)->StopAnimation();
+ pSh->InvalidateWindows( Frm() );
+ }
+ }
+ }
+
+ if ( bFirst )
+ {
+ pCnt->SetRetouche(); //fix(13870)
+
+ SwDoc *pDoc = pCnt->GetNode()->GetDoc();
+ if ( pDoc->GetSpzFrmFmts()->Count() &&
+ !pDoc->IsLoaded() && !pDoc->IsNewDoc() )
+ {
+ //Der Frm wurde wahrscheinlich zum ersten mal formatiert.
+ //Wenn ein Filter Flys oder Zeichenobjekte einliest und diese
+ //Seitengebunden sind, hat er ein Problem, weil er i.d.R. die
+ //Seitennummer nicht kennt. Er weiss lediglich welches der Inhalt
+ //(CntntNode) an dieser Stelle ist.
+ //Die Filter stellen dazu das Ankerattribut der Objekte so ein, dass
+ //sie vom Typ zwar Seitengebunden sind, aber der Index des Ankers
+ //auf diesen CntntNode zeigt.
+ //Hier werden diese vorlauefigen Verbindungen aufgeloest.
+
+ const SwPageFrm *pPage = 0;
+ SwNodeIndex *pIdx = 0;
+ SwSpzFrmFmts *pTbl = pDoc->GetSpzFrmFmts();
+
+ for ( sal_uInt16 i = 0; i < pTbl->Count(); ++i )
+ {
+ if ( !pPage )
+ pPage = pCnt->FindPageFrm();
+ SwFrmFmt *pFmt = (*pTbl)[i];
+ const SwFmtAnchor &rAnch = pFmt->GetAnchor();
+
+ if ((FLY_AT_PAGE != rAnch.GetAnchorId()) &&
+ (FLY_AT_PARA != rAnch.GetAnchorId()))
+ {
+ continue; //#60878# nicht etwa zeichengebundene.
+ }
+
+ if ( rAnch.GetCntntAnchor() )
+ {
+ if ( !pIdx )
+ {
+ pIdx = new SwNodeIndex( *pCnt->GetNode() );
+ }
+ if ( rAnch.GetCntntAnchor()->nNode == *pIdx )
+ {
+ if (FLY_AT_PAGE == rAnch.GetAnchorId())
+ {
+ OSL_FAIL( "<SwCntntNotify::~SwCntntNotify()> - to page anchored object with content position. Please inform OD." );
+ SwFmtAnchor aAnch( rAnch );
+ aAnch.SetAnchor( 0 );
+ aAnch.SetPageNum( pPage->GetPhyPageNum() );
+ pFmt->SetFmtAttr( aAnch );
+ if ( RES_DRAWFRMFMT != pFmt->Which() )
+ pFmt->MakeFrms();
+ }
+ }
+ }
+ }
+ delete pIdx;
+ }
+ }
+
+ // OD 12.01.2004 #i11859# - invalidate printing area of following frame,
+ // if height of last line has changed.
+ if ( pCnt->IsTxtFrm() && mbChkHeightOfLastLine )
+ {
+ if ( mnHeightOfLastLine != static_cast<SwTxtFrm*>(pCnt)->GetHeightOfLastLine() )
+ {
+ pCnt->InvalidateNextPrtArea();
+ }
+ }
+
+ // --> OD 2005-03-07 #i44049#
+ if ( pCnt->IsTxtFrm() && POS_DIFF( aFrm, pCnt->Frm() ) )
+ {
+ pCnt->InvalidateObjs( true );
+ }
+ // <--
+
+ // --> OD 2005-04-12 #i43255# - move code to invalidate at-character
+ // anchored objects due to a change of its anchor character from
+ // method <SwTxtFrm::Format(..)>.
+ if ( pCnt->IsTxtFrm() )
+ {
+ SwTxtFrm* pMasterFrm = pCnt->IsFollow()
+ ? static_cast<SwTxtFrm*>(pCnt)->FindMaster()
+ : static_cast<SwTxtFrm*>(pCnt);
+ if ( pMasterFrm && !pMasterFrm->IsFlyLock() &&
+ pMasterFrm->GetDrawObjs() )
+ {
+ SwSortedObjs* pObjs = pMasterFrm->GetDrawObjs();
+ for ( sal_uInt32 i = 0; i < pObjs->Count(); ++i )
+ {
+ SwAnchoredObject* pAnchoredObj = (*pObjs)[i];
+ if ( pAnchoredObj->GetFrmFmt().GetAnchor().GetAnchorId()
+ == FLY_AT_CHAR )
+ {
+ pAnchoredObj->CheckCharRectAndTopOfLine( !pMasterFrm->IsEmpty() );
+ }
+ }
+ }
+ }
+ // <--
+}
+
+/*************************************************************************/
+
+void AppendObjs( const SwSpzFrmFmts *pTbl, sal_uLong nIndex,
+ SwFrm *pFrm, SwPageFrm *pPage )
+{
+ for ( sal_uInt16 i = 0; i < pTbl->Count(); ++i )
+ {
+ SwFrmFmt *pFmt = (SwFrmFmt*)(*pTbl)[i];
+ const SwFmtAnchor &rAnch = pFmt->GetAnchor();
+ if ( rAnch.GetCntntAnchor() &&
+ (rAnch.GetCntntAnchor()->nNode.GetIndex() == nIndex) )
+ {
+ const bool bFlyAtFly = rAnch.GetAnchorId() == FLY_AT_FLY; // LAYER_IMPL
+ //Wird ein Rahmen oder ein SdrObject beschrieben?
+ const bool bSdrObj = RES_DRAWFRMFMT == pFmt->Which();
+ // OD 23.06.2003 #108784# - append also drawing objects anchored
+ // as character.
+ const bool bDrawObjInCntnt = bSdrObj &&
+ (rAnch.GetAnchorId() == FLY_AS_CHAR);
+
+ if( bFlyAtFly ||
+ (rAnch.GetAnchorId() == FLY_AT_PARA) ||
+ (rAnch.GetAnchorId() == FLY_AT_CHAR) ||
+ bDrawObjInCntnt )
+ {
+ SdrObject* pSdrObj = 0;
+ if ( bSdrObj && 0 == (pSdrObj = pFmt->FindSdrObject()) )
+ {
+ OSL_ENSURE( !bSdrObj, "DrawObject not found." );
+ pFmt->GetDoc()->DelFrmFmt( pFmt );
+ --i;
+ continue;
+ }
+ if ( pSdrObj )
+ {
+ if ( !pSdrObj->GetPage() )
+ {
+ pFmt->getIDocumentDrawModelAccess()->GetDrawModel()->GetPage(0)->
+ InsertObject(pSdrObj, pSdrObj->GetOrdNumDirect());
+ }
+
+ SwDrawContact* pNew =
+ static_cast<SwDrawContact*>(GetUserCall( pSdrObj ));
+ if ( !pNew->GetAnchorFrm() )
+ {
+ pFrm->AppendDrawObj( *(pNew->GetAnchoredObj( 0L )) );
+ }
+ // OD 19.06.2003 #108784# - add 'virtual' drawing object,
+ // if necessary. But control objects have to be excluded.
+ else if ( !::CheckControlLayer( pSdrObj ) &&
+ pNew->GetAnchorFrm() != pFrm &&
+ !pNew->GetDrawObjectByAnchorFrm( *pFrm ) )
+ {
+ SwDrawVirtObj* pDrawVirtObj = pNew->AddVirtObj();
+ pFrm->AppendDrawObj( *(pNew->GetAnchoredObj( pDrawVirtObj )) );
+
+ // for repaint, use new ActionChanged()
+ // pDrawVirtObj->SendRepaintBroadcast();
+ pDrawVirtObj->ActionChanged();
+ }
+
+ }
+ else
+ {
+ SwFlyFrm *pFly;
+ if( bFlyAtFly )
+ pFly = new SwFlyLayFrm( (SwFlyFrmFmt*)pFmt, pFrm, pFrm );
+ else
+ pFly = new SwFlyAtCntFrm( (SwFlyFrmFmt*)pFmt, pFrm, pFrm );
+ pFly->Lock();
+ pFrm->AppendFly( pFly );
+ pFly->Unlock();
+ if ( pPage )
+ ::RegistFlys( pPage, pFly );
+ }
+ }
+ }
+ }
+}
+
+bool lcl_ObjConnected( SwFrmFmt *pFmt, const SwFrm* pSib )
+{
+ SwIterator<SwFlyFrm,SwFmt> aIter( *pFmt );
+ if ( RES_FLYFRMFMT == pFmt->Which() )
+ {
+ const SwRootFrm* pRoot = pSib ? pSib->getRootFrm() : 0;
+ const SwFlyFrm* pTmpFrm;
+ for( pTmpFrm = aIter.First(); pTmpFrm; pTmpFrm = aIter.Next() )
+ {
+ if(! pRoot || pRoot == pTmpFrm->getRootFrm() )
+ return true;
+ }
+ }
+ else
+ {
+ SwDrawContact *pContact = SwIterator<SwDrawContact,SwFmt>::FirstElement(*pFmt);
+ if ( pContact )
+ return pContact->GetAnchorFrm() != 0;
+ }
+ return false;
+}
+
+/** helper method to determine, if a <SwFrmFmt>, which has an object connected,
+ is located in header or footer.
+
+ OD 23.06.2003 #108784#
+
+ @author OD
+*/
+bool lcl_InHeaderOrFooter( SwFrmFmt& _rFmt )
+{
+ bool bRetVal = false;
+
+ const SwFmtAnchor& rAnch = _rFmt.GetAnchor();
+
+ if (rAnch.GetAnchorId() != FLY_AT_PAGE)
+ {
+ bRetVal = _rFmt.GetDoc()->IsInHeaderFooter( rAnch.GetCntntAnchor()->nNode );
+ }
+
+ return bRetVal;
+}
+
+void AppendAllObjs( const SwSpzFrmFmts *pTbl, const SwFrm* pSib )
+{
+ //Verbinden aller Objekte, die in der SpzTbl beschrieben sind mit dem
+ //Layout.
+ //Wenn sich nix mehr tut hoeren wir auf. Dann koennen noch Formate
+ //uebrigbleiben, weil wir weder zeichengebunde Rahmen verbinden noch
+ //Objecte die in zeichengebundenen verankert sind.
+
+ SwSpzFrmFmts aCpy( 255, 255 );
+ aCpy.Insert( pTbl, 0 );
+
+ sal_uInt16 nOldCnt = USHRT_MAX;
+
+ while ( aCpy.Count() && aCpy.Count() != nOldCnt )
+ {
+ nOldCnt = aCpy.Count();
+ for ( int i = 0; i < int(aCpy.Count()); ++i )
+ {
+ SwFrmFmt *pFmt = (SwFrmFmt*)aCpy[ sal_uInt16(i) ];
+ const SwFmtAnchor &rAnch = pFmt->GetAnchor();
+ sal_Bool bRemove = sal_False;
+ if ((rAnch.GetAnchorId() == FLY_AT_PAGE) ||
+ (rAnch.GetAnchorId() == FLY_AS_CHAR))
+ {
+ //Seitengebunde sind bereits verankert, zeichengebundene
+ //will ich hier nicht.
+ bRemove = sal_True;
+ }
+ else if ( sal_False == (bRemove = ::lcl_ObjConnected( pFmt, pSib )) ||
+ ::lcl_InHeaderOrFooter( *pFmt ) )
+ {
+ // OD 23.06.2003 #108784# - correction: for objects in header
+ // or footer create frames, in spite of the fact that an connected
+ // objects already exists.
+ //Fuer Flys und DrawObjs nur dann ein MakeFrms rufen wenn noch
+ //keine abhaengigen Existieren, andernfalls, oder wenn das
+ //MakeFrms keine abhaengigen erzeugt, entfernen.
+ pFmt->MakeFrms();
+ bRemove = ::lcl_ObjConnected( pFmt, pSib );
+ }
+ if ( bRemove )
+ {
+ aCpy.Remove( sal_uInt16(i) );
+ --i;
+ }
+ }
+ }
+ aCpy.Remove( 0, aCpy.Count() );
+}
+
+/** local method to set 'working' position for newly inserted frames
+
+ OD 12.08.2003 #i17969#
+
+ @author OD
+*/
+void lcl_SetPos( SwFrm& _rNewFrm,
+ const SwLayoutFrm& _rLayFrm )
+{
+ SWRECTFN( (&_rLayFrm) )
+ (_rNewFrm.Frm().*fnRect->fnSetPos)( (_rLayFrm.Frm().*fnRect->fnGetPos)() );
+ // move position by one SwTwip in text flow direction in order to get
+ // notifications for a new calculated position after its formatting.
+ if ( bVert )
+ _rNewFrm.Frm().Pos().X() -= 1;
+ else
+ _rNewFrm.Frm().Pos().Y() += 1;
+}
+
+void MA_FASTCALL _InsertCnt( SwLayoutFrm *pLay, SwDoc *pDoc,
+ sal_uLong nIndex, sal_Bool bPages, sal_uLong nEndIndex,
+ SwFrm *pPrv )
+{
+ pDoc->BlockIdling();
+ SwRootFrm* pLayout = pLay->getRootFrm();
+ const sal_Bool bOldCallbackActionEnabled = pLayout ? pLayout->IsCallbackActionEnabled() : sal_False;
+ if( bOldCallbackActionEnabled )
+ pLayout->SetCallbackActionEnabled( sal_False );
+
+ //Bei der Erzeugung des Layouts wird bPages mit sal_True uebergeben. Dann
+ //werden schon mal alle x Absaetze neue Seiten angelegt. Bei umbruechen
+ //und/oder Pagedescriptorwechseln werden gleich die entsprechenden Seiten
+ //angelegt.
+ //Vorteil ist, das einerseits schon eine annaehernd realistische Zahl von
+ //Seiten angelegt wird, vor allem aber gibt es nicht mehr eine schier
+ //lange Kette von Absaetzen teuer verschoben werden muss, bis sie sich auf
+ //ertraegliches mass reduziert hat.
+ //Wir gehen mal davon aus, da? 20 Absaetze auf eine Seite passen
+ //Damit es in extremen Faellen nicht gar so heftig rechenen wir je nach
+ //Node noch etwas drauf.
+ //Wenn in der DocStatistik eine brauchebare Seitenzahl angegeben ist
+ //(wird beim Schreiben gepflegt), so wird von dieser Seitenanzahl
+ //ausgegengen.
+ const sal_Bool bStartPercent = bPages && !nEndIndex;
+
+ SwPageFrm *pPage = pLay->FindPageFrm();
+ const SwSpzFrmFmts *pTbl = pDoc->GetSpzFrmFmts();
+ SwFrm *pFrm = 0;
+ sal_Bool bBreakAfter = sal_False;
+
+ SwActualSection *pActualSection = 0;
+ SwLayHelper *pPageMaker;
+
+ //Wenn das Layout erzeugt wird (bPages == sal_True) steuern wir den Progress
+ //an. Flys und DrawObjekte werden dann nicht gleich verbunden, dies
+ //passiert erst am Ende der Funktion.
+ if ( bPages )
+ {
+ // Attention: the SwLayHelper class uses references to the content-,
+ // page-, layout-frame etc. and may change them!
+ pPageMaker = new SwLayHelper( pDoc, pFrm, pPrv, pPage, pLay,
+ pActualSection, bBreakAfter, nIndex, 0 == nEndIndex );
+ if( bStartPercent )
+ {
+ const sal_uLong nPageCount = pPageMaker->CalcPageCount();
+ if( nPageCount )
+ bObjsDirect = sal_False;
+ }
+ }
+ else
+ pPageMaker = NULL;
+
+ if( pLay->IsInSct() &&
+ ( pLay->IsSctFrm() || pLay->GetUpper() ) ) // Hierdurch werden Frischlinge
+ // abgefangen, deren Flags noch nicht ermittelt werden koennen,
+ // so z.B. beim Einfuegen einer Tabelle
+ {
+ SwSectionFrm* pSct = pLay->FindSctFrm();
+ // Wenn Inhalt in eine Fussnote eingefuegt wird, die in einem spaltigen
+ // Bereich liegt, so darf der spaltige Bereich nicht aufgebrochen werden.
+ // Nur wenn im Innern der Fussnote ein Bereich liegt, ist dies ein
+ // Kandidat fuer pActualSection.
+ // Gleiches gilt fuer Bereiche in Tabellen, wenn innerhalb einer Tabelle
+ // eingefuegt wird, duerfen nur Bereiche, die ebenfalls im Innern liegen,
+ // aufgebrochen werden.
+ if( ( !pLay->IsInFtn() || pSct->IsInFtn() ) &&
+ ( !pLay->IsInTab() || pSct->IsInTab() ) )
+ {
+ pActualSection = new SwActualSection( 0, pSct, 0 );
+ OSL_ENSURE( !pLay->Lower() || !pLay->Lower()->IsColumnFrm(),
+ "_InsertCnt: Wrong Call" );
+ }
+ }
+
+ //If a section is "open", the pActualSection points to an SwActualSection.
+ //If the page breaks, for "open" sections a follow will created.
+ //For nested sections (which have, however, not a nested layout),
+ //the SwActualSection class has a member, which points to an upper(section).
+ //When the "inner" section finishs, the upper will used instead.
+
+ while( sal_True )
+ {
+ SwNode *pNd = pDoc->GetNodes()[nIndex];
+ if ( pNd->IsCntntNode() )
+ {
+ SwCntntNode* pNode = (SwCntntNode*)pNd;
+ pFrm = pNode->IsTxtNode() ? new SwTxtFrm( (SwTxtNode*)pNode, pLay ) :
+ pNode->MakeFrm( pLay );
+ if( pPageMaker )
+ pPageMaker->CheckInsert( nIndex );
+
+ pFrm->InsertBehind( pLay, pPrv );
+ // --> OD 2005-12-01 #i27138#
+ // notify accessibility paragraphs objects about changed
+ // CONTENT_FLOWS_FROM/_TO relation.
+ // Relation CONTENT_FLOWS_FROM for next paragraph will change
+ // and relation CONTENT_FLOWS_TO for previous paragraph will change.
+ if ( pFrm->IsTxtFrm() )
+ {
+ ViewShell* pViewShell( pFrm->getRootFrm()->GetCurrShell() );
+ // no notification, if <ViewShell> is in construction
+ if ( pViewShell && !pViewShell->IsInConstructor() &&
+ pViewShell->GetLayout() &&
+ pViewShell->GetLayout()->IsAnyShellAccessible() )
+ {
+ pViewShell->InvalidateAccessibleParaFlowRelation(
+ dynamic_cast<SwTxtFrm*>(pFrm->FindNextCnt( true )),
+ dynamic_cast<SwTxtFrm*>(pFrm->FindPrevCnt( true )) );
+ // --> OD 2006-08-28 #i68958#
+ // The information flags of the text frame are validated
+ // in methods <FindNextCnt(..)> and <FindPrevCnt(..)>.
+ // The information flags have to be invalidated, because
+ // it is possible, that the one of its upper frames
+ // isn't inserted into the layout.
+ pFrm->InvalidateInfFlags();
+ // <--
+ }
+ }
+ // <--
+ // OD 12.08.2003 #i17969# - consider horizontal/vertical layout
+ // for setting position at newly inserted frame
+ lcl_SetPos( *pFrm, *pLay );
+ pPrv = pFrm;
+
+ if ( pTbl->Count() && bObjsDirect && !bDontCreateObjects )
+ AppendObjs( pTbl, nIndex, pFrm, pPage );
+ }
+ else if ( pNd->IsTableNode() )
+ { //Sollten wir auf eine Tabelle gestossen sein?
+ SwTableNode *pTblNode = (SwTableNode*)pNd;
+
+ // #108116# loading may produce table structures that GCLines
+ // needs to clean up. To keep table formulas correct, change
+ // all table formulas to internal (BOXPTR) representation.
+ SwTableFmlUpdate aMsgHnt( &pTblNode->GetTable() );
+ aMsgHnt.eFlags = TBL_BOXPTR;
+ pDoc->UpdateTblFlds( &aMsgHnt );
+ pTblNode->GetTable().GCLines();
+
+ pFrm = pTblNode->MakeFrm( pLay );
+
+ if( pPageMaker )
+ pPageMaker->CheckInsert( nIndex );
+
+ pFrm->InsertBehind( pLay, pPrv );
+ // --> OD 2005-12-01 #i27138#
+ // notify accessibility paragraphs objects about changed
+ // CONTENT_FLOWS_FROM/_TO relation.
+ // Relation CONTENT_FLOWS_FROM for next paragraph will change
+ // and relation CONTENT_FLOWS_TO for previous paragraph will change.
+ {
+ ViewShell* pViewShell( pFrm->getRootFrm()->GetCurrShell() );
+ // no notification, if <ViewShell> is in construction
+ if ( pViewShell && !pViewShell->IsInConstructor() &&
+ pViewShell->GetLayout() &&
+ pViewShell->GetLayout()->IsAnyShellAccessible() )
+ {
+ pViewShell->InvalidateAccessibleParaFlowRelation(
+ dynamic_cast<SwTxtFrm*>(pFrm->FindNextCnt( true )),
+ dynamic_cast<SwTxtFrm*>(pFrm->FindPrevCnt( true )) );
+ }
+ }
+ // <--
+ if ( bObjsDirect && pTbl->Count() )
+ ((SwTabFrm*)pFrm)->RegistFlys();
+ // OD 12.08.2003 #i17969# - consider horizontal/vertical layout
+ // for setting position at newly inserted frame
+ lcl_SetPos( *pFrm, *pLay );
+
+ pPrv = pFrm;
+ //Index auf den Endnode der Tabellensection setzen.
+ nIndex = pTblNode->EndOfSectionIndex();
+
+ SwTabFrm* pTmpFrm = (SwTabFrm*)pFrm;
+ while ( pTmpFrm )
+ {
+ pTmpFrm->CheckDirChange();
+ pTmpFrm = pTmpFrm->IsFollow() ? pTmpFrm->FindMaster() : NULL;
+ }
+
+ }
+ else if ( pNd->IsSectionNode() )
+ {
+ SwSectionNode *pNode = (SwSectionNode*)pNd;
+ if( pNode->GetSection().CalcHiddenFlag() )
+ // ist versteckt, ueberspringe den Bereich
+ nIndex = pNode->EndOfSectionIndex();
+ else
+ {
+ pFrm = pNode->MakeFrm( pLay );
+ pActualSection = new SwActualSection( pActualSection,
+ (SwSectionFrm*)pFrm, pNode );
+ if ( pActualSection->GetUpper() )
+ {
+ //Hinter den Upper einsetzen, beim EndNode wird der "Follow"
+ //des Uppers erzeugt.
+ SwSectionFrm *pTmp = pActualSection->GetUpper()->GetSectionFrm();
+ pFrm->InsertBehind( pTmp->GetUpper(), pTmp );
+ // OD 25.03.2003 #108339# - direct initialization of section
+ // after insertion in the layout
+ static_cast<SwSectionFrm*>(pFrm)->Init();
+ }
+ else
+ {
+ pFrm->InsertBehind( pLay, pPrv );
+ // OD 25.03.2003 #108339# - direct initialization of section
+ // after insertion in the layout
+ static_cast<SwSectionFrm*>(pFrm)->Init();
+
+ // --> FME 2004-09-08 #i33963#
+ // Do not trust the IsInFtn flag. If we are currently
+ // building up a table, the upper of pPrv may be a cell
+ // frame, but the cell frame does not have an upper yet.
+ if( pPrv && 0 != pPrv->ImplFindFtnFrm() )
+ // <--
+ {
+ if( pPrv->IsSctFrm() )
+ pPrv = ((SwSectionFrm*)pPrv)->ContainsCntnt();
+ if( pPrv && pPrv->IsTxtFrm() )
+ ((SwTxtFrm*)pPrv)->Prepare( PREP_QUOVADIS, 0, sal_False );
+ }
+ }
+ // --> OD 2005-12-01 #i27138#
+ // notify accessibility paragraphs objects about changed
+ // CONTENT_FLOWS_FROM/_TO relation.
+ // Relation CONTENT_FLOWS_FROM for next paragraph will change
+ // and relation CONTENT_FLOWS_TO for previous paragraph will change.
+ {
+ ViewShell* pViewShell( pFrm->getRootFrm()->GetCurrShell() );
+ // no notification, if <ViewShell> is in construction
+ if ( pViewShell && !pViewShell->IsInConstructor() &&
+ pViewShell->GetLayout() &&
+ pViewShell->GetLayout()->IsAnyShellAccessible() )
+ {
+ pViewShell->InvalidateAccessibleParaFlowRelation(
+ dynamic_cast<SwTxtFrm*>(pFrm->FindNextCnt( true )),
+ dynamic_cast<SwTxtFrm*>(pFrm->FindPrevCnt( true )) );
+ }
+ }
+ // <--
+ pFrm->CheckDirChange();
+
+ // OD 12.08.2003 #i17969# - consider horizontal/vertical layout
+ // for setting position at newly inserted frame
+ lcl_SetPos( *pFrm, *pLay );
+
+ // OD 20.11.2002 #105405# - no page, no invalidate.
+ if ( pPage )
+ {
+ // OD 18.09.2002 #100522#
+ // invalidate page in order to force format and paint of
+ // inserted section frame
+ pFrm->InvalidatePage( pPage );
+
+ // FME 10.11.2003 #112243#
+ // Invalidate fly content flag:
+ if ( pFrm->IsInFly() )
+ pPage->InvalidateFlyCntnt();
+
+ // OD 14.11.2002 #104684# - invalidate page content in order to
+ // force format and paint of section content.
+ pPage->InvalidateCntnt();
+ }
+
+ pLay = (SwLayoutFrm*)pFrm;
+ if ( pLay->Lower() && pLay->Lower()->IsLayoutFrm() )
+ pLay = pLay->GetNextLayoutLeaf();
+ pPrv = 0;
+ }
+ }
+ else if ( pNd->IsEndNode() && pNd->StartOfSectionNode()->IsSectionNode() )
+ {
+ OSL_ENSURE( pActualSection, "Sectionende ohne Anfang?" );
+ OSL_ENSURE( pActualSection->GetSectionNode() == pNd->StartOfSectionNode(),
+ "Sectionende mit falschen Start Node?" );
+
+ //Section schliessen, ggf. die umgebende Section wieder
+ //aktivieren.
+ SwActualSection *pTmp = pActualSection->GetUpper();
+ delete pActualSection;
+ pLay = pLay->FindSctFrm();
+ if ( 0 != (pActualSection = pTmp) )
+ {
+ //Koennte noch sein, das der letzte SectionFrm leer geblieben
+ //ist. Dann ist es jetzt an der Zeit ihn zu entfernen.
+ if ( !pLay->ContainsCntnt() )
+ {
+ SwFrm *pTmpFrm = pLay;
+ pLay = pTmpFrm->GetUpper();
+ pPrv = pTmpFrm->GetPrev();
+ pTmpFrm->Remove();
+ delete pTmpFrm;
+ }
+ else
+ {
+ pPrv = pLay;
+ pLay = pLay->GetUpper();
+ }
+
+ // new section frame
+ pFrm = pActualSection->GetSectionNode()->MakeFrm( pLay );
+ pFrm->InsertBehind( pLay, pPrv );
+ static_cast<SwSectionFrm*>(pFrm)->Init();
+
+ // OD 12.08.2003 #i17969# - consider horizontal/vertical layout
+ // for setting position at newly inserted frame
+ lcl_SetPos( *pFrm, *pLay );
+
+ SwSectionFrm* pOuterSectionFrm = pActualSection->GetSectionFrm();
+
+ // a follow has to be appended to the new section frame
+ SwSectionFrm* pFollow = pOuterSectionFrm->GetFollow();
+ if ( pFollow )
+ {
+ pOuterSectionFrm->SetFollow( NULL );
+ pOuterSectionFrm->InvalidateSize();
+ ((SwSectionFrm*)pFrm)->SetFollow( pFollow );
+ }
+
+ // Wir wollen keine leeren Teile zuruecklassen
+ if( ! pOuterSectionFrm->IsColLocked() &&
+ ! pOuterSectionFrm->ContainsCntnt() )
+ {
+ pOuterSectionFrm->DelEmpty( sal_True );
+ delete pOuterSectionFrm;
+ }
+ pActualSection->SetSectionFrm( (SwSectionFrm*)pFrm );
+
+ pLay = (SwLayoutFrm*)pFrm;
+ if ( pLay->Lower() && pLay->Lower()->IsLayoutFrm() )
+ pLay = pLay->GetNextLayoutLeaf();
+ pPrv = 0;
+ }
+ else
+ {
+ //Nix mehr mit Sections, es geht direkt hinter dem SectionFrame
+ //weiter.
+ pPrv = pLay;
+ pLay = pLay->GetUpper();
+ }
+ }
+ else if( pNd->IsStartNode() &&
+ SwFlyStartNode == ((SwStartNode*)pNd)->GetStartNodeType() )
+ {
+ if ( pTbl->Count() && bObjsDirect && !bDontCreateObjects )
+ {
+ SwFlyFrm* pFly = pLay->FindFlyFrm();
+ if( pFly )
+ AppendObjs( pTbl, nIndex, pFly, pPage );
+ }
+ }
+ else
+ // Weder Cntnt noch Tabelle noch Section,
+ // also muessen wir fertig sein.
+ break;
+
+ ++nIndex;
+ // Der Endnode wird nicht mehr mitgenommen, es muss vom
+ // Aufrufenden (Section/MakeFrms()) sichergestellt sein, dass das Ende
+ // des Bereichs vor dem EndIndex liegt!
+ if ( nEndIndex && nIndex >= nEndIndex )
+ break;
+ }
+
+ if ( pActualSection )
+ {
+ //Kann passieren, dass noch eine leere (Follow-)Section uebrig geblieben ist.
+ if ( !(pLay = pActualSection->GetSectionFrm())->ContainsCntnt() )
+ {
+ pLay->Remove();
+ delete pLay;
+ }
+ delete pActualSection;
+ }
+
+ if ( bPages ) //Jetzt noch die Flys verbinden lassen.
+ {
+ if ( !bDontCreateObjects )
+ AppendAllObjs( pTbl, pLayout );
+ bObjsDirect = sal_True;
+ }
+
+ if( pPageMaker )
+ {
+ pPageMaker->CheckFlyCache( pPage );
+ delete pPageMaker;
+ if( pDoc->GetLayoutCache() )
+ {
+#if OSL_DEBUG_LEVEL > 1
+ pDoc->GetLayoutCache()->CompareLayout( *pDoc );
+#endif
+ pDoc->GetLayoutCache()->ClearImpl();
+ }
+ }
+
+ pDoc->UnblockIdling();
+ if( bOldCallbackActionEnabled )
+ pLayout->SetCallbackActionEnabled( bOldCallbackActionEnabled );
+}
+
+
+void MakeFrms( SwDoc *pDoc, const SwNodeIndex &rSttIdx,
+ const SwNodeIndex &rEndIdx )
+{
+ bObjsDirect = sal_False;
+
+ SwNodeIndex aTmp( rSttIdx );
+ sal_uLong nEndIdx = rEndIdx.GetIndex();
+ SwNode* pNd = pDoc->GetNodes().FindPrvNxtFrmNode( aTmp,
+ pDoc->GetNodes()[ nEndIdx-1 ]);
+ if ( pNd )
+ {
+ sal_Bool bApres = aTmp < rSttIdx;
+ SwNode2Layout aNode2Layout( *pNd, rSttIdx.GetIndex() );
+ SwFrm* pFrm;
+ while( 0 != (pFrm = aNode2Layout.NextFrm()) )
+ {
+ SwLayoutFrm *pUpper = pFrm->GetUpper();
+ SwFtnFrm* pFtnFrm = pUpper->FindFtnFrm();
+ sal_Bool bOldLock, bOldFtn;
+ if( pFtnFrm )
+ {
+ bOldFtn = pFtnFrm->IsColLocked();
+ pFtnFrm->ColLock();
+ }
+ else
+ bOldFtn = sal_True;
+ SwSectionFrm* pSct = pUpper->FindSctFrm();
+ // Es sind innerhalb von Fussnoten nur die Bereiche interessant,
+ // die in den Fussnoten liegen, nicht etwa die (spaltigen) Bereiche,
+ // in denen die Fussnoten(Container) liegen.
+ // #109767# Table frame is in section, insert section in cell frame.
+ if( pSct && ((pFtnFrm && !pSct->IsInFtn()) || pUpper->IsCellFrm()) )
+ pSct = NULL;
+ if( pSct )
+ { // damit der SectionFrm nicht zerstoert wird durch pTmp->MoveFwd()
+ bOldLock = pSct->IsColLocked();
+ pSct->ColLock();
+ }
+ else
+ bOldLock = sal_True;
+
+ // Wenn pFrm sich nicht bewegen kann, koennen wir auch niemanden
+ // auf die naechste Seite schieben. Innerhalb eines Rahmens auch
+ // nicht ( in der 1. Spalte eines Rahmens waere pFrm Moveable()! )
+ // Auch in spaltigen Bereichen in Tabellen waere pFrm Moveable.
+ sal_Bool bMoveNext = nEndIdx - rSttIdx.GetIndex() > 120;
+ sal_Bool bAllowMove = !pFrm->IsInFly() && pFrm->IsMoveable() &&
+ (!pFrm->IsInTab() || pFrm->IsTabFrm() );
+ if ( bMoveNext && bAllowMove )
+ {
+ SwFrm *pMove = pFrm;
+ SwFrm *pPrev = pFrm->GetPrev();
+ SwFlowFrm *pTmp = SwFlowFrm::CastFlowFrm( pMove );
+ OSL_ENSURE( pTmp, "Missing FlowFrm" );
+
+ if ( bApres )
+ {
+ // Wir wollen, dass der Rest der Seite leer ist, d.h.
+ // der naechste muss auf die naechste Seite wandern.
+ // Dieser kann auch in der naechsten Spalte stehen!
+ OSL_ENSURE( !pTmp->HasFollow(), "Follows forbidden" );
+ pPrev = pFrm;
+ // Wenn unser umgebender SectionFrm einen Next besitzt,
+ // so soll dieser ebenfalls gemoved werden!
+ pMove = pFrm->GetIndNext();
+ SwColumnFrm* pCol = (SwColumnFrm*)pFrm->FindColFrm();
+ if( pCol )
+ pCol = (SwColumnFrm*)pCol->GetNext();
+ do
+ {
+ if( pCol && !pMove )
+ { // Bisher haben wir keinen Nachfolger gefunden
+ // jetzt gucken wir in die naechste Spalte
+ pMove = pCol->ContainsAny();
+ if( pCol->GetNext() )
+ pCol = (SwColumnFrm*)pCol->GetNext();
+ else if( pCol->IsInSct() )
+ { // Wenn es keine naechste Spalte gibt, wir aber
+ // innerhalb eines spaltigen Bereichs sind,
+ // koennte es noch ausserhalb des Bereich
+ // (Seiten-)Spalten geben
+ pCol = (SwColumnFrm*)pCol->FindSctFrm()->FindColFrm();
+ if( pCol )
+ pCol = (SwColumnFrm*)pCol->GetNext();
+ }
+ else
+ pCol = NULL;
+ }
+ // Falls hier verschrottete SectionFrms herumgammeln,
+ // muessen diese uebersprungen werden.
+ while( pMove && pMove->IsSctFrm() &&
+ !((SwSectionFrm*)pMove)->GetSection() )
+ pMove = pMove->GetNext();
+ } while( !pMove && pCol );
+
+ if( pMove )
+ {
+ if ( pMove->IsCntntFrm() )
+ pTmp = (SwCntntFrm*)pMove;
+ else if ( pMove->IsTabFrm() )
+ pTmp = (SwTabFrm*)pMove;
+ else if ( pMove->IsSctFrm() )
+ {
+ pMove = ((SwSectionFrm*)pMove)->ContainsAny();
+ if( pMove )
+ pTmp = SwFlowFrm::CastFlowFrm( pMove );
+ else
+ pTmp = NULL;
+ }
+ }
+ else
+ pTmp = 0;
+ }
+ else
+ {
+ OSL_ENSURE( !pTmp->IsFollow(), "Follows really forbidden" );
+ // Bei Bereichen muss natuerlich der Inhalt auf die Reise
+ // geschickt werden.
+ if( pMove->IsSctFrm() )
+ {
+ while( pMove && pMove->IsSctFrm() &&
+ !((SwSectionFrm*)pMove)->GetSection() )
+ pMove = pMove->GetNext();
+ if( pMove && pMove->IsSctFrm() )
+ pMove = ((SwSectionFrm*)pMove)->ContainsAny();
+ if( pMove )
+ pTmp = SwFlowFrm::CastFlowFrm( pMove );
+ else
+ pTmp = NULL;
+ }
+ }
+
+ if( pTmp )
+ {
+ SwFrm* pOldUp = pTmp->GetFrm()->GetUpper();
+ // MoveFwd==sal_True bedeutet, dass wir auf der gleichen
+ // Seite geblieben sind, wir wollen aber die Seite wechseln,
+ // sofern dies moeglich ist
+ sal_Bool bTmpOldLock = pTmp->IsJoinLocked();
+ pTmp->LockJoin();
+ while( pTmp->MoveFwd( sal_True, sal_False, sal_True ) )
+ {
+ if( pOldUp == pTmp->GetFrm()->GetUpper() )
+ break;
+ pOldUp = pTmp->GetFrm()->GetUpper();
+ }
+ if( !bTmpOldLock )
+ pTmp->UnlockJoin();
+ }
+ ::_InsertCnt( pUpper, pDoc, rSttIdx.GetIndex(),
+ pFrm->IsInDocBody(), nEndIdx, pPrev );
+ }
+ else
+ {
+ sal_Bool bSplit;
+ SwFrm* pPrv = bApres ? pFrm : pFrm->GetPrev();
+ // Wenn in einen SectionFrm ein anderer eingefuegt wird,
+ // muss dieser aufgebrochen werden
+ if( pSct && rSttIdx.GetNode().IsSectionNode() )
+ {
+ bSplit = pSct->SplitSect( pFrm, bApres );
+ // Wenn pSct nicht aufgespalten werden konnte
+ if( !bSplit && !bApres )
+ {
+ pUpper = pSct->GetUpper();
+ pPrv = pSct->GetPrev();
+ }
+ }
+ else
+ bSplit = sal_False;
+ ::_InsertCnt( pUpper, pDoc, rSttIdx.GetIndex(), sal_False,
+ nEndIdx, pPrv );
+ // OD 23.06.2003 #108784# - correction: append objects doesn't
+ // depend on value of <bAllowMove>
+ if( !bDontCreateObjects )
+ {
+ const SwSpzFrmFmts *pTbl = pDoc->GetSpzFrmFmts();
+ if( pTbl->Count() )
+ AppendAllObjs( pTbl, pUpper );
+ }
+
+ // Wenn nichts eingefuegt wurde, z.B. ein ausgeblendeter Bereich,
+ // muss das Splitten rueckgaengig gemacht werden
+ if( bSplit && pSct && pSct->GetNext()
+ && pSct->GetNext()->IsSctFrm() )
+ pSct->MergeNext( (SwSectionFrm*)pSct->GetNext() );
+ if( pFrm->IsInFly() )
+ pFrm->FindFlyFrm()->_Invalidate();
+ if( pFrm->IsInTab() )
+ pFrm->InvalidateSize();
+ }
+
+ SwPageFrm *pPage = pUpper->FindPageFrm();
+ SwFrm::CheckPageDescs( pPage, sal_False );
+ if( !bOldFtn )
+ pFtnFrm->ColUnlock();
+ if( !bOldLock )
+ {
+ pSct->ColUnlock();
+ // Zum Beispiel beim Einfuegen von gelinkten Bereichen,
+ // die wiederum Bereiche enthalten, kann pSct jetzt leer sein
+ // und damit ruhig zerstoert werden.
+ if( !pSct->ContainsCntnt() )
+ {
+ pSct->DelEmpty( sal_True );
+ pUpper->getRootFrm()->RemoveFromList( pSct );
+ delete pSct;
+ }
+ }
+ }
+ }
+
+ bObjsDirect = sal_True;
+}
+
+
+/*************************************************************************/
+
+SwBorderAttrs::SwBorderAttrs( const SwModify *pMod, const SwFrm *pConstructor ) :
+ SwCacheObj( pMod ),
+ rAttrSet( pConstructor->IsCntntFrm()
+ ? ((SwCntntFrm*)pConstructor)->GetNode()->GetSwAttrSet()
+ : ((SwLayoutFrm*)pConstructor)->GetFmt()->GetAttrSet() ),
+ rUL ( rAttrSet.GetULSpace() ),
+ // --> OD 2008-12-04 #i96772#
+ // LRSpaceItem is copied due to the possibility that it is adjusted - see below
+ rLR ( rAttrSet.GetLRSpace() ),
+ // <--
+ rBox ( rAttrSet.GetBox() ),
+ rShadow ( rAttrSet.GetShadow() ),
+ aFrmSize( rAttrSet.GetFrmSize().GetSize() )
+{
+ // --> OD 2008-12-02 #i96772#
+ const SwTxtFrm* pTxtFrm = dynamic_cast<const SwTxtFrm*>(pConstructor);
+ if ( pTxtFrm )
+ {
+ pTxtFrm->GetTxtNode()->ClearLRSpaceItemDueToListLevelIndents( rLR );
+ }
+
+ //Achtung: Die USHORTs fuer die gecache'ten Werte werden absichtlich
+ //nicht initialisiert!
+
+ //Muessen alle einmal berechnet werden:
+ bTopLine = bBottomLine = bLeftLine = bRightLine =
+ bTop = bBottom = bLine = sal_True;
+
+ bCacheGetLine = bCachedGetTopLine = bCachedGetBottomLine = sal_False;
+ // OD 21.05.2003 #108789# - init cache status for values <bJoinedWithPrev>
+ // and <bJoinedWithNext>, which aren't initialized by default.
+ bCachedJoinedWithPrev = sal_False;
+ bCachedJoinedWithNext = sal_False;
+
+ bBorderDist = 0 != (pConstructor->GetType() & (FRM_CELL));
+}
+
+SwBorderAttrs::~SwBorderAttrs()
+{
+ ((SwModify*)pOwner)->SetInCache( sal_False );
+}
+
+/*************************************************************************
+|*
+|* SwBorderAttrs::CalcTop(), CalcBottom(), CalcLeft(), CalcRight()
+|*
+|* Beschreibung Die Calc-Methoden errechnen zusaetzlich zu den
+|* von den Attributen vorgegebenen Groessen einen Sicherheitsabstand.
+|* der Sicherheitsabstand wird nur einkalkuliert, wenn Umrandung und/oder
+|* Schatten im Spiel sind; er soll vermeiden, dass aufgrund der
+|* groben physikalischen Gegebenheiten Raender usw. uebermalt werden.
+|*
+|*************************************************************************/
+
+void SwBorderAttrs::_CalcTop()
+{
+ nTop = CalcTopLine() + rUL.GetUpper();
+ bTop = sal_False;
+}
+
+void SwBorderAttrs::_CalcBottom()
+{
+ nBottom = CalcBottomLine() + rUL.GetLower();
+ bBottom = sal_False;
+}
+
+long SwBorderAttrs::CalcRight( const SwFrm* pCaller ) const
+{
+ long nRight=0;
+
+ if (!pCaller->IsTxtFrm() || !((SwTxtFrm*)pCaller)->GetTxtNode()->GetDoc()->get(IDocumentSettingAccess::INVERT_BORDER_SPACING)) {
+ // OD 23.01.2003 #106895# - for cell frame in R2L text direction the left
+ // and right border are painted on the right respectively left.
+ if ( pCaller->IsCellFrm() && pCaller->IsRightToLeft() )
+ nRight = CalcLeftLine();
+ else
+ nRight = CalcRightLine();
+
+ }
+ // for paragraphs, "left" is "before text" and "right" is "after text"
+ if ( pCaller->IsTxtFrm() && pCaller->IsRightToLeft() )
+ nRight += rLR.GetLeft();
+ else
+ nRight += rLR.GetRight();
+
+ // correction: retrieve left margin for numbering in R2L-layout
+ if ( pCaller->IsTxtFrm() && pCaller->IsRightToLeft() )
+ {
+ nRight += ((SwTxtFrm*)pCaller)->GetTxtNode()->GetLeftMarginWithNum();
+ }
+
+ return nRight;
+}
+
+long SwBorderAttrs::CalcLeft( const SwFrm *pCaller ) const
+{
+ long nLeft=0;
+
+ if (!pCaller->IsTxtFrm() || !((SwTxtFrm*)pCaller)->GetTxtNode()->GetDoc()->get(IDocumentSettingAccess::INVERT_BORDER_SPACING)) {
+ // OD 23.01.2003 #106895# - for cell frame in R2L text direction the left
+ // and right border are painted on the right respectively left.
+ if ( pCaller->IsCellFrm() && pCaller->IsRightToLeft() )
+ nLeft = CalcRightLine();
+ else
+ nLeft = CalcLeftLine();
+ }
+
+ // for paragraphs, "left" is "before text" and "right" is "after text"
+ if ( pCaller->IsTxtFrm() && pCaller->IsRightToLeft() )
+ nLeft += rLR.GetRight();
+ else
+ nLeft += rLR.GetLeft();
+
+
+ // correction: do not retrieve left margin for numbering in R2L-layout
+// if ( pCaller->IsTxtFrm() )
+ if ( pCaller->IsTxtFrm() && !pCaller->IsRightToLeft() )
+ {
+ nLeft += ((SwTxtFrm*)pCaller)->GetTxtNode()->GetLeftMarginWithNum();
+ }
+
+ return nLeft;
+}
+
+/*************************************************************************
+|*
+|* SwBorderAttrs::CalcTopLine(), CalcBottomLine(),
+|* CalcLeftLine(), CalcRightLine()
+|*
+|* Beschreibung Berechnung der Groessen fuer Umrandung und Schatten.
+|* Es kann auch ohne Linien ein Abstand erwuenscht sein,
+|* dieser wird dann nicht vom Attribut sondern hier
+|* beruecksichtigt (bBorderDist, z.B. fuer Zellen).
+|*
+|*************************************************************************/
+
+void SwBorderAttrs::_CalcTopLine()
+{
+ nTopLine = (bBorderDist && !rBox.GetTop())
+ ? rBox.GetDistance (BOX_LINE_TOP)
+ : rBox.CalcLineSpace(BOX_LINE_TOP);
+ nTopLine = nTopLine + rShadow.CalcShadowSpace(SHADOW_TOP);
+ bTopLine = sal_False;
+}
+
+void SwBorderAttrs::_CalcBottomLine()
+{
+ nBottomLine = (bBorderDist && !rBox.GetBottom())
+ ? rBox.GetDistance (BOX_LINE_BOTTOM)
+ : rBox.CalcLineSpace(BOX_LINE_BOTTOM);
+ nBottomLine = nBottomLine + rShadow.CalcShadowSpace(SHADOW_BOTTOM);
+ bBottomLine = sal_False;
+}
+
+void SwBorderAttrs::_CalcLeftLine()
+{
+ nLeftLine = (bBorderDist && !rBox.GetLeft())
+ ? rBox.GetDistance (BOX_LINE_LEFT)
+ : rBox.CalcLineSpace(BOX_LINE_LEFT);
+ nLeftLine = nLeftLine + rShadow.CalcShadowSpace(SHADOW_LEFT);
+ bLeftLine = sal_False;
+}
+
+void SwBorderAttrs::_CalcRightLine()
+{
+ nRightLine = (bBorderDist && !rBox.GetRight())
+ ? rBox.GetDistance (BOX_LINE_RIGHT)
+ : rBox.CalcLineSpace(BOX_LINE_RIGHT);
+ nRightLine = nRightLine + rShadow.CalcShadowSpace(SHADOW_RIGHT);
+ bRightLine = sal_False;
+}
+
+/*************************************************************************/
+
+void SwBorderAttrs::_IsLine()
+{
+ bIsLine = rBox.GetTop() || rBox.GetBottom() ||
+ rBox.GetLeft()|| rBox.GetRight();
+ bLine = sal_False;
+}
+
+/*************************************************************************
+|*
+|* SwBorderAttrs::CmpLeftRightLine(), IsTopLine(), IsBottomLine()
+|*
+|* Die Umrandungen benachbarter Absaetze werden nach folgendem
+|* Algorithmus zusammengefasst:
+|*
+|* 1. Die Umrandung oben faellt weg, wenn der Vorgaenger dieselbe
+|* Umrandung oben aufweist und 3. Zutrifft.
+|* Zusaetzlich muss der Absatz mindestens rechts oder links oder
+|* unten eine Umrandung haben.
+|* 2. Die Umrandung unten faellt weg, wenn der Nachfolger dieselbe
+|* Umrandung untern aufweist und 3. Zustrifft.
+|* Zusaetzlich muss der Absatz mindestens rechts oder links oder
+|* oben eine Umrandung haben.
+|* 3. Die Umrandungen links und rechts vor Vorgaenger bzw. Nachfolger
+|* sind identisch.
+|*
+|*************************************************************************/
+inline int CmpLines( const editeng::SvxBorderLine *pL1, const editeng::SvxBorderLine *pL2 )
+{
+ return ( ((pL1 && pL2) && (*pL1 == *pL2)) || (!pL1 && !pL2) );
+}
+
+// OD 21.05.2003 #108789# - change name of 1st parameter - "rAttrs" -> "rCmpAttrs"
+// OD 21.05.2003 #108789# - compare <CalcRight()> and <rCmpAttrs.CalcRight()>
+// instead of only the right LR-spacing, because R2L-layout has to be
+// considered.
+sal_Bool SwBorderAttrs::CmpLeftRight( const SwBorderAttrs &rCmpAttrs,
+ const SwFrm *pCaller,
+ const SwFrm *pCmp ) const
+{
+ return ( CmpLines( rCmpAttrs.GetBox().GetLeft(), GetBox().GetLeft() ) &&
+ CmpLines( rCmpAttrs.GetBox().GetRight(),GetBox().GetRight() ) &&
+ CalcLeft( pCaller ) == rCmpAttrs.CalcLeft( pCmp ) &&
+ // OD 21.05.2003 #108789# - compare <CalcRight> with <rCmpAttrs.CalcRight>.
+ CalcRight( pCaller ) == rCmpAttrs.CalcRight( pCmp ) );
+}
+
+sal_Bool SwBorderAttrs::_JoinWithCmp( const SwFrm& _rCallerFrm,
+ const SwFrm& _rCmpFrm ) const
+{
+ sal_Bool bReturnVal = sal_False;
+
+ SwBorderAttrAccess aCmpAccess( SwFrm::GetCache(), &_rCmpFrm );
+ const SwBorderAttrs &rCmpAttrs = *aCmpAccess.Get();
+ if ( rShadow == rCmpAttrs.GetShadow() &&
+ CmpLines( rBox.GetTop(), rCmpAttrs.GetBox().GetTop() ) &&
+ CmpLines( rBox.GetBottom(), rCmpAttrs.GetBox().GetBottom() ) &&
+ CmpLeftRight( rCmpAttrs, &_rCallerFrm, &_rCmpFrm )
+ )
+ {
+ bReturnVal = sal_True;
+ }
+
+ return bReturnVal;
+}
+
+// OD 21.05.2003 #108789# - method to determine, if borders are joined with
+// previous frame. Calculated value saved in cached value <bJoinedWithPrev>
+// OD 2004-02-26 #i25029# - add 2nd parameter <_pPrevFrm>
+void SwBorderAttrs::_CalcJoinedWithPrev( const SwFrm& _rFrm,
+ const SwFrm* _pPrevFrm )
+{
+ // set default
+ bJoinedWithPrev = sal_False;
+
+ if ( _rFrm.IsTxtFrm() )
+ {
+ // text frame can potentially join with previous text frame, if
+ // corresponding attribute set is set at previous text frame.
+ // OD 2004-02-26 #i25029# - If parameter <_pPrevFrm> is set, take this
+ // one as previous frame.
+ const SwFrm* pPrevFrm = _pPrevFrm ? _pPrevFrm : _rFrm.GetPrev();
+ // OD 2004-02-13 #i25029# - skip hidden text frames.
+ while ( pPrevFrm && pPrevFrm->IsTxtFrm() &&
+ static_cast<const SwTxtFrm*>(pPrevFrm)->IsHiddenNow() )
+ {
+ pPrevFrm = pPrevFrm->GetPrev();
+ }
+ if ( pPrevFrm && pPrevFrm->IsTxtFrm() &&
+ pPrevFrm->GetAttrSet()->GetParaConnectBorder().GetValue()
+ )
+ {
+ bJoinedWithPrev = _JoinWithCmp( _rFrm, *(pPrevFrm) );
+ }
+ }
+
+ // valid cache status, if demanded
+ // OD 2004-02-26 #i25029# - Do not validate cache, if parameter <_pPrevFrm>
+ // is set.
+ bCachedJoinedWithPrev = bCacheGetLine && !_pPrevFrm;
+}
+
+// OD 21.05.2003 #108789# - method to determine, if borders are joined with
+// next frame. Calculated value saved in cached value <bJoinedWithNext>
+void SwBorderAttrs::_CalcJoinedWithNext( const SwFrm& _rFrm )
+{
+ // set default
+ bJoinedWithNext = sal_False;
+
+ if ( _rFrm.IsTxtFrm() )
+ {
+ // text frame can potentially join with next text frame, if
+ // corresponding attribute set is set at current text frame.
+ // OD 2004-02-13 #i25029# - get next frame, but skip hidden text frames.
+ const SwFrm* pNextFrm = _rFrm.GetNext();
+ while ( pNextFrm && pNextFrm->IsTxtFrm() &&
+ static_cast<const SwTxtFrm*>(pNextFrm)->IsHiddenNow() )
+ {
+ pNextFrm = pNextFrm->GetNext();
+ }
+ if ( pNextFrm && pNextFrm->IsTxtFrm() &&
+ _rFrm.GetAttrSet()->GetParaConnectBorder().GetValue()
+ )
+ {
+ bJoinedWithNext = _JoinWithCmp( _rFrm, *(pNextFrm) );
+ }
+ }
+
+ // valid cache status, if demanded
+ bCachedJoinedWithNext = bCacheGetLine;
+}
+
+// OD 21.05.2003 #108789# - accessor for cached values <bJoinedWithPrev>
+// OD 2004-02-26 #i25029# - add 2nd parameter <_pPrevFrm>, which is passed to
+// method <_CalcJoindWithPrev(..)>.
+sal_Bool SwBorderAttrs::JoinedWithPrev( const SwFrm& _rFrm,
+ const SwFrm* _pPrevFrm ) const
+{
+ if ( !bCachedJoinedWithPrev || _pPrevFrm )
+ {
+ // OD 2004-02-26 #i25029# - pass <_pPrevFrm> as 2nd parameter
+ const_cast<SwBorderAttrs*>(this)->_CalcJoinedWithPrev( _rFrm, _pPrevFrm );
+ }
+
+ return bJoinedWithPrev;
+}
+
+sal_Bool SwBorderAttrs::JoinedWithNext( const SwFrm& _rFrm ) const
+{
+ if ( !bCachedJoinedWithNext )
+ {
+ const_cast<SwBorderAttrs*>(this)->_CalcJoinedWithNext( _rFrm );
+ }
+
+ return bJoinedWithNext;
+}
+
+// OD 2004-02-26 #i25029# - added 2nd parameter <_pPrevFrm>, which is passed to
+// method <JoinedWithPrev>
+void SwBorderAttrs::_GetTopLine( const SwFrm& _rFrm,
+ const SwFrm* _pPrevFrm )
+{
+ sal_uInt16 nRet = CalcTopLine();
+
+ // OD 21.05.2003 #108789# - use new method <JoinWithPrev()>
+ // OD 2004-02-26 #i25029# - add 2nd parameter
+ if ( JoinedWithPrev( _rFrm, _pPrevFrm ) )
+ {
+ nRet = 0;
+ }
+
+ bCachedGetTopLine = bCacheGetLine;
+
+ nGetTopLine = nRet;
+}
+
+void SwBorderAttrs::_GetBottomLine( const SwFrm& _rFrm )
+{
+ sal_uInt16 nRet = CalcBottomLine();
+
+ // OD 21.05.2003 #108789# - use new method <JoinWithPrev()>
+ if ( JoinedWithNext( _rFrm ) )
+ {
+ nRet = 0;
+ }
+
+ bCachedGetBottomLine = bCacheGetLine;
+
+ nGetBottomLine = nRet;
+}
+
+/*************************************************************************/
+
+SwBorderAttrAccess::SwBorderAttrAccess( SwCache &rCach, const SwFrm *pFrm ) :
+ SwCacheAccess( rCach, (pFrm->IsCntntFrm() ?
+ (void*)((SwCntntFrm*)pFrm)->GetNode() :
+ (void*)((SwLayoutFrm*)pFrm)->GetFmt()),
+ (sal_Bool)(pFrm->IsCntntFrm() ?
+ ((SwModify*)((SwCntntFrm*)pFrm)->GetNode())->IsInCache() :
+ ((SwModify*)((SwLayoutFrm*)pFrm)->GetFmt())->IsInCache()) ),
+ pConstructor( pFrm )
+{
+}
+
+/*************************************************************************/
+
+SwCacheObj *SwBorderAttrAccess::NewObj()
+{
+ ((SwModify*)pOwner)->SetInCache( sal_True );
+ return new SwBorderAttrs( (SwModify*)pOwner, pConstructor );
+}
+
+SwBorderAttrs *SwBorderAttrAccess::Get()
+{
+ return (SwBorderAttrs*)SwCacheAccess::Get();
+}
+
+/*************************************************************************/
+
+SwOrderIter::SwOrderIter( const SwPageFrm *pPg, sal_Bool bFlys ) :
+ pPage( pPg ),
+ pCurrent( 0 ),
+ bFlysOnly( bFlys )
+{
+}
+
+/*************************************************************************/
+
+const SdrObject *SwOrderIter::Top()
+{
+ pCurrent = 0;
+ if ( pPage->GetSortedObjs() )
+ {
+ const SwSortedObjs *pObjs = pPage->GetSortedObjs();
+ if ( pObjs->Count() )
+ {
+ sal_uInt32 nTopOrd = 0;
+ (*pObjs)[0]->GetDrawObj()->GetOrdNum(); //Aktualisieren erzwingen!
+ for ( sal_uInt16 i = 0; i < pObjs->Count(); ++i )
+ {
+ const SdrObject* pObj = (*pObjs)[i]->GetDrawObj();
+ if ( bFlysOnly && !pObj->ISA(SwVirtFlyDrawObj) )
+ continue;
+ sal_uInt32 nTmp = pObj->GetOrdNumDirect();
+ if ( nTmp >= nTopOrd )
+ {
+ nTopOrd = nTmp;
+ pCurrent = pObj;
+ }
+ }
+ }
+ }
+ return pCurrent;
+}
+
+/*************************************************************************/
+
+const SdrObject *SwOrderIter::Bottom()
+{
+ pCurrent = 0;
+ if ( pPage->GetSortedObjs() )
+ {
+ sal_uInt32 nBotOrd = USHRT_MAX;
+ const SwSortedObjs *pObjs = pPage->GetSortedObjs();
+ if ( pObjs->Count() )
+ {
+ (*pObjs)[0]->GetDrawObj()->GetOrdNum(); //Aktualisieren erzwingen!
+ for ( sal_uInt16 i = 0; i < pObjs->Count(); ++i )
+ {
+ const SdrObject* pObj = (*pObjs)[i]->GetDrawObj();
+ if ( bFlysOnly && !pObj->ISA(SwVirtFlyDrawObj) )
+ continue;
+ sal_uInt32 nTmp = pObj->GetOrdNumDirect();
+ if ( nTmp < nBotOrd )
+ {
+ nBotOrd = nTmp;
+ pCurrent = pObj;
+ }
+ }
+ }
+ }
+ return pCurrent;
+}
+
+/*************************************************************************/
+
+const SdrObject *SwOrderIter::Next()
+{
+ const sal_uInt32 nCurOrd = pCurrent ? pCurrent->GetOrdNumDirect() : 0;
+ pCurrent = 0;
+ if ( pPage->GetSortedObjs() )
+ {
+ sal_uInt32 nOrd = USHRT_MAX;
+ const SwSortedObjs *pObjs = pPage->GetSortedObjs();
+ if ( pObjs->Count() )
+ {
+ (*pObjs)[0]->GetDrawObj()->GetOrdNum(); //Aktualisieren erzwingen!
+ for ( sal_uInt16 i = 0; i < pObjs->Count(); ++i )
+ {
+ const SdrObject* pObj = (*pObjs)[i]->GetDrawObj();
+ if ( bFlysOnly && !pObj->ISA(SwVirtFlyDrawObj) )
+ continue;
+ sal_uInt32 nTmp = pObj->GetOrdNumDirect();
+ if ( nTmp > nCurOrd && nTmp < nOrd )
+ {
+ nOrd = nTmp;
+ pCurrent = pObj;
+ }
+ }
+ }
+ }
+ return pCurrent;
+}
+
+/*************************************************************************/
+
+const SdrObject *SwOrderIter::Prev()
+{
+ const sal_uInt32 nCurOrd = pCurrent ? pCurrent->GetOrdNumDirect() : 0;
+ pCurrent = 0;
+ if ( pPage->GetSortedObjs() )
+ {
+ const SwSortedObjs *pObjs = pPage->GetSortedObjs();
+ if ( pObjs->Count() )
+ {
+ sal_uInt32 nOrd = 0;
+ (*pObjs)[0]->GetDrawObj()->GetOrdNum(); //Aktualisieren erzwingen!
+ for ( sal_uInt16 i = 0; i < pObjs->Count(); ++i )
+ {
+ const SdrObject* pObj = (*pObjs)[i]->GetDrawObj();
+ if ( bFlysOnly && !pObj->ISA(SwVirtFlyDrawObj) )
+ continue;
+ sal_uInt32 nTmp = pObj->GetOrdNumDirect();
+ if ( nTmp < nCurOrd && nTmp >= nOrd )
+ {
+ nOrd = nTmp;
+ pCurrent = pObj;
+ }
+ }
+ }
+ }
+ return pCurrent;
+}
+
+/*************************************************************************/
+
+//Unterstruktur eines LayoutFrms fuer eine Aktion aufheben und wieder
+//restaurieren.
+//Neuer Algorithmus: Es ist unuetz jeden Nachbarn einzeln zu betrachten und
+//die Pointer sauber zu setzen (Upper, Nachbarn, usw.)
+//Es reicht vollkommen jeweils eine Einzelkette zu loesen, und mit dem
+//Letzen der Einzelkette nachzuschauen ob noch eine weitere Kette
+//angeheangt werden muss. Es brauchen nur die Pointer korrigiert werden,
+//die zur Verkettung notwendig sind. So koennen Beipspielsweise die Pointer
+//auf die Upper auf den alten Uppern stehenbleiben. Korrigiert werden die
+//Pointer dann im RestoreCntnt. Zwischenzeitlich ist sowieso jeder Zugriff
+//verboten.
+//Unterwegs werden die Flys bei der Seite abgemeldet.
+
+// --> OD 2004-11-29 #115759# - 'remove' also drawing object from page and
+// at-fly anchored objects from page
+void MA_FASTCALL lcl_RemoveObjsFromPage( SwFrm* _pFrm )
+{
+ OSL_ENSURE( _pFrm->GetDrawObjs(), "Keine DrawObjs fuer lcl_RemoveFlysFromPage." );
+ SwSortedObjs &rObjs = *_pFrm->GetDrawObjs();
+ for ( sal_uInt16 i = 0; i < rObjs.Count(); ++i )
+ {
+ SwAnchoredObject* pObj = rObjs[i];
+ // --> OD 2004-11-29 #115759# - reset member, at which the anchored
+ // object orients its vertical position
+ pObj->ClearVertPosOrientFrm();
+ // <--
+ // --> OD 2005-03-03 #i43913#
+ pObj->ResetLayoutProcessBools();
+ // <--
+ // --> OD 2004-11-29 #115759# - remove also lower objects of as-character
+ // anchored Writer fly frames from page
+ if ( pObj->ISA(SwFlyFrm) )
+ {
+ SwFlyFrm* pFlyFrm = static_cast<SwFlyFrm*>(pObj);
+
+ // --> OD 2004-11-29 #115759# - remove also direct lowers of Writer
+ // fly frame from page
+ if ( pFlyFrm->GetDrawObjs() )
+ {
+ ::lcl_RemoveObjsFromPage( pFlyFrm );
+ }
+ // <--
+
+ SwCntntFrm* pCnt = pFlyFrm->ContainsCntnt();
+ while ( pCnt )
+ {
+ if ( pCnt->GetDrawObjs() )
+ ::lcl_RemoveObjsFromPage( pCnt );
+ pCnt = pCnt->GetNextCntntFrm();
+ }
+ if ( pFlyFrm->IsFlyFreeFrm() )
+ {
+ // --> OD 2004-06-30 #i28701# - use new method <GetPageFrm()>
+ pFlyFrm->GetPageFrm()->RemoveFlyFromPage( pFlyFrm );
+ }
+ }
+ // <--
+ // --> OD 2004-11-29 #115759# - remove also drawing objects from page
+ else if ( pObj->ISA(SwAnchoredDrawObject) )
+ {
+ if (pObj->GetFrmFmt().GetAnchor().GetAnchorId() != FLY_AS_CHAR)
+ {
+ pObj->GetPageFrm()->RemoveDrawObjFromPage(
+ *(static_cast<SwAnchoredDrawObject*>(pObj)) );
+ }
+ }
+ // <--
+ }
+}
+
+SwFrm *SaveCntnt( SwLayoutFrm *pLay, SwFrm *pStart )
+{
+ if( pLay->IsSctFrm() && pLay->Lower() && pLay->Lower()->IsColumnFrm() )
+ lcl_RemoveFtns( (SwColumnFrm*)pLay->Lower(), sal_True, sal_True );
+
+ SwFrm *pSav;
+ if ( 0 == (pSav = pLay->ContainsAny()) )
+ return 0;
+
+ if( pSav->IsInFtn() && !pLay->IsInFtn() )
+ {
+ do
+ pSav = pSav->FindNext();
+ while( pSav && pSav->IsInFtn() );
+ if( !pSav || !pLay->IsAnLower( pSav ) )
+ return NULL;
+ }
+
+ // Tables should be saved as a whole, expection:
+ // The contents of a section or a cell inside a table should be saved
+ if ( pSav->IsInTab() && !( ( pLay->IsSctFrm() || pLay->IsCellFrm() ) && pLay->IsInTab() ) )
+ while ( !pSav->IsTabFrm() )
+ pSav = pSav->GetUpper();
+
+ if( pSav->IsInSct() )
+ { // Jetzt wird der oberste Bereich gesucht, der innerhalb von pLay ist.
+ SwFrm* pSect = pLay->FindSctFrm();
+ SwFrm *pTmp = pSav;
+ do
+ {
+ pSav = pTmp;
+ pTmp = pSav->GetUpper() ? pSav->GetUpper()->FindSctFrm() : NULL;
+ } while ( pTmp != pSect );
+ }
+
+ SwFrm *pFloat = pSav;
+ if( !pStart )
+ pStart = pSav;
+ sal_Bool bGo = pStart == pSav;
+ do
+ {
+ if( bGo )
+ pFloat->GetUpper()->pLower = 0; //Die Teilkette ausklinken.
+
+ //Das Ende der Teilkette suchen, unterwegs die Flys abmelden.
+ do
+ {
+ if( bGo )
+ {
+ if ( pFloat->IsCntntFrm() )
+ {
+ if ( pFloat->GetDrawObjs() )
+ ::lcl_RemoveObjsFromPage( (SwCntntFrm*)pFloat );
+ }
+ else if ( pFloat->IsTabFrm() || pFloat->IsSctFrm() )
+ {
+ SwCntntFrm *pCnt = ((SwLayoutFrm*)pFloat)->ContainsCntnt();
+ if( pCnt )
+ {
+ do
+ { if ( pCnt->GetDrawObjs() )
+ ::lcl_RemoveObjsFromPage( pCnt );
+ pCnt = pCnt->GetNextCntntFrm();
+ } while ( pCnt && ((SwLayoutFrm*)pFloat)->IsAnLower( pCnt ) );
+ }
+ }
+ else {
+ OSL_ENSURE( !pFloat, "Neuer Float-Frame?" );
+ }
+ }
+ if ( pFloat->GetNext() )
+ {
+ if( bGo )
+ pFloat->pUpper = NULL;
+ pFloat = pFloat->GetNext();
+ if( !bGo && pFloat == pStart )
+ {
+ bGo = sal_True;
+ pFloat->pPrev->pNext = NULL;
+ pFloat->pPrev = NULL;
+ }
+ }
+ else
+ break;
+
+ } while ( pFloat );
+
+ //Die naechste Teilkette suchen und die Ketten miteinander verbinden.
+ SwFrm *pTmp = pFloat->FindNext();
+ if( bGo )
+ pFloat->pUpper = NULL;
+
+ if( !pLay->IsInFtn() )
+ while( pTmp && pTmp->IsInFtn() )
+ pTmp = pTmp->FindNext();
+
+ if ( !pLay->IsAnLower( pTmp ) )
+ pTmp = 0;
+
+ if ( pTmp && bGo )
+ {
+ pFloat->pNext = pTmp; //Die beiden Ketten verbinden.
+ pFloat->pNext->pPrev = pFloat;
+ }
+ pFloat = pTmp;
+ bGo = bGo || ( pStart == pFloat );
+ } while ( pFloat );
+
+ return bGo ? pStart : NULL;
+}
+
+// --> OD 2004-11-29 #115759# - add also drawing objects to page and at-fly
+// anchored objects to page
+void MA_FASTCALL lcl_AddObjsToPage( SwFrm* _pFrm, SwPageFrm* _pPage )
+{
+ OSL_ENSURE( _pFrm->GetDrawObjs(), "Keine DrawObjs fuer lcl_AddFlysToPage." );
+ SwSortedObjs &rObjs = *_pFrm->GetDrawObjs();
+ for ( sal_uInt16 i = 0; i < rObjs.Count(); ++i )
+ {
+ SwAnchoredObject* pObj = rObjs[i];
+
+ // --> OD 2004-11-29 #115759# - unlock position of anchored object
+ // in order to get the object's position calculated.
+ pObj->UnlockPosition();
+ // <--
+ // --> OD 2004-11-29 #115759# - add also lower objects of as-character
+ // anchored Writer fly frames from page
+ if ( pObj->ISA(SwFlyFrm) )
+ {
+ SwFlyFrm* pFlyFrm = static_cast<SwFlyFrm*>(pObj);
+ if ( pObj->ISA(SwFlyFreeFrm) )
+ {
+ _pPage->AppendFlyToPage( pFlyFrm );
+ }
+ pFlyFrm->_InvalidatePos();
+ pFlyFrm->_InvalidateSize();
+ pFlyFrm->InvalidatePage( _pPage );
+
+ // --> OD 2004-11-29 #115759# - add also at-fly anchored objects
+ // to page
+ if ( pFlyFrm->GetDrawObjs() )
+ {
+ ::lcl_AddObjsToPage( pFlyFrm, _pPage );
+ }
+ // <--
+
+ SwCntntFrm *pCnt = pFlyFrm->ContainsCntnt();
+ while ( pCnt )
+ {
+ if ( pCnt->GetDrawObjs() )
+ ::lcl_AddObjsToPage( pCnt, _pPage );
+ pCnt = pCnt->GetNextCntntFrm();
+ }
+ }
+ // <--
+ // --> OD 2004-11-29 #115759# - remove also drawing objects from page
+ else if ( pObj->ISA(SwAnchoredDrawObject) )
+ {
+ if (pObj->GetFrmFmt().GetAnchor().GetAnchorId() != FLY_AS_CHAR)
+ {
+ pObj->InvalidateObjPos();
+ _pPage->AppendDrawObjToPage(
+ *(static_cast<SwAnchoredDrawObject*>(pObj)) );
+ }
+ }
+ // <--
+ }
+}
+
+void RestoreCntnt( SwFrm *pSav, SwLayoutFrm *pParent, SwFrm *pSibling, bool bGrow )
+{
+ OSL_ENSURE( pSav && pParent, "Kein Save oder Parent fuer Restore." );
+ SWRECTFN( pParent )
+
+ //Wenn es bereits FlowFrms unterhalb des neuen Parent gibt, so wird die
+ //Kette, beginnend mit pSav, hinter dem letzten angehaengt.
+ //Die Teile werden kurzerhand insertet und geeignet invalidiert.
+ //Unterwegs werden die Flys der CntntFrms bei der Seite angemeldet.
+
+ SwPageFrm *pPage = pParent->FindPageFrm();
+
+ if ( pPage )
+ pPage->InvalidatePage( pPage ); //Invalides Layout anmelden.
+
+ //Vorgaenger festellen und die Verbindung herstellen bzw. initialisieren.
+ pSav->pPrev = pSibling;
+ SwFrm* pNxt;
+ if ( pSibling )
+ {
+ pNxt = pSibling->pNext;
+ pSibling->pNext = pSav;
+ pSibling->_InvalidatePrt();
+ ((SwCntntFrm*)pSibling)->InvalidatePage( pPage );//Invaliden Cntnt anmelden.
+ if ( ((SwCntntFrm*)pSibling)->GetFollow() )
+ pSibling->Prepare( PREP_CLEAR, 0, sal_False );
+ }
+ else
+ { pNxt = pParent->pLower;
+ pParent->pLower = pSav;
+ pSav->pUpper = pParent; //Schon mal setzen, sonst ist fuer das
+ //invalidate der Parent (z.B. ein Fly) nicht klar.
+ //Invaliden Cntnt anmelden.
+ if ( pSav->IsCntntFrm() )
+ ((SwCntntFrm*)pSav)->InvalidatePage( pPage );
+ else
+ { // pSav koennte auch ein leerer SectFrm sein
+ SwCntntFrm* pCnt = pParent->ContainsCntnt();
+ if( pCnt )
+ pCnt->InvalidatePage( pPage );
+ }
+ }
+
+ //Der Parent muss entsprechend gegrow'ed werden.
+ SwTwips nGrowVal = 0;
+ SwFrm* pLast;
+ do
+ { pSav->pUpper = pParent;
+ nGrowVal += (pSav->Frm().*fnRect->fnGetHeight)();
+ pSav->_InvalidateAll();
+
+ //Jetzt die Flys anmelden, fuer TxtFrms gleich geeignet invalidieren.
+ if ( pSav->IsCntntFrm() )
+ {
+ if ( pSav->IsTxtFrm() &&
+ ((SwTxtFrm*)pSav)->GetCacheIdx() != USHRT_MAX )
+ ((SwTxtFrm*)pSav)->Init(); //Ich bin sein Freund.
+
+ if ( pPage && pSav->GetDrawObjs() )
+ ::lcl_AddObjsToPage( (SwCntntFrm*)pSav, pPage );
+ }
+ else
+ { SwCntntFrm *pBlub = ((SwLayoutFrm*)pSav)->ContainsCntnt();
+ if( pBlub )
+ {
+ do
+ { if ( pPage && pBlub->GetDrawObjs() )
+ ::lcl_AddObjsToPage( pBlub, pPage );
+ if( pBlub->IsTxtFrm() && ((SwTxtFrm*)pBlub)->HasFtn() &&
+ ((SwTxtFrm*)pBlub)->GetCacheIdx() != USHRT_MAX )
+ ((SwTxtFrm*)pBlub)->Init(); //Ich bin sein Freund.
+ pBlub = pBlub->GetNextCntntFrm();
+ } while ( pBlub && ((SwLayoutFrm*)pSav)->IsAnLower( pBlub ));
+ }
+ }
+ pLast = pSav;
+ pSav = pSav->GetNext();
+
+ } while ( pSav );
+
+ if( pNxt )
+ {
+ pLast->pNext = pNxt;
+ pNxt->pPrev = pLast;
+ }
+
+ if ( bGrow )
+ pParent->Grow( nGrowVal );
+}
+
+/*************************************************************************
+|*
+|* SqRt() Berechnung der Quadratwurzel, damit die math.lib
+|* nicht auch noch dazugelinkt werden muss.
+|*
+|*************************************************************************/
+
+sal_uLong MA_FASTCALL SqRt( BigInt nX )
+{
+ BigInt nErg = 1;
+
+ if ( !nX.IsNeg() )
+ {
+ BigInt nOldErg = 1;
+ for ( int i = 0; i <= 5; i++ )
+ {
+ nErg = (nOldErg + (nX / nOldErg)) / BigInt(2);
+ nOldErg = nErg;
+ }
+ }
+ return nErg >= BigInt(SAL_MAX_UINT32) ? ULONG_MAX : (sal_uLong)nErg;
+}
+
+/*************************************************************************/
+
+SwPageFrm * MA_FASTCALL InsertNewPage( SwPageDesc &rDesc, SwFrm *pUpper,
+ sal_Bool bOdd, sal_Bool bInsertEmpty, sal_Bool bFtn,
+ SwFrm *pSibling )
+{
+ SwPageFrm *pRet;
+ SwDoc *pDoc = ((SwLayoutFrm*)pUpper)->GetFmt()->GetDoc();
+ SwFrmFmt *pFmt = bOdd ? rDesc.GetRightFmt() : rDesc.GetLeftFmt();
+ //Wenn ich kein FrmFmt fuer die Seite gefunden habe, muss ich eben
+ //eine Leerseite einfuegen.
+ if ( !pFmt )
+ {
+ pFmt = bOdd ? rDesc.GetLeftFmt() : rDesc.GetRightFmt();
+ OSL_ENSURE( pFmt, "Descriptor without any format?!" );
+ bInsertEmpty = !bInsertEmpty;
+ }
+ if( bInsertEmpty )
+ {
+ SwPageDesc *pTmpDesc = pSibling && pSibling->GetPrev() ?
+ ((SwPageFrm*)pSibling->GetPrev())->GetPageDesc() : &rDesc;
+ pRet = new SwPageFrm( pDoc->GetEmptyPageFmt(), pUpper, pTmpDesc );
+ pRet->Paste( pUpper, pSibling );
+ pRet->PreparePage( bFtn );
+ }
+ pRet = new SwPageFrm( pFmt, pUpper, &rDesc );
+ pRet->Paste( pUpper, pSibling );
+ pRet->PreparePage( bFtn );
+ if ( pRet->GetNext() )
+ ((SwRootFrm*)pRet->GetUpper())->AssertPageFlys( pRet );
+ return pRet;
+}
+
+
+/*************************************************************************
+|*
+|* RegistFlys(), Regist() Die beiden folgenden Methoden durchsuchen rekursiv
+|* eine Layoutstruktur und melden alle FlyFrms, die einen beliebigen Frm
+|* innerhalb der Struktur als Anker haben bei der Seite an.
+|*
+|*************************************************************************/
+
+void MA_FASTCALL lcl_Regist( SwPageFrm *pPage, const SwFrm *pAnch )
+{
+ SwSortedObjs *pObjs = (SwSortedObjs*)pAnch->GetDrawObjs();
+ for ( sal_uInt16 i = 0; i < pObjs->Count(); ++i )
+ {
+ SwAnchoredObject* pObj = (*pObjs)[i];
+ if ( pObj->ISA(SwFlyFrm) )
+ {
+ SwFlyFrm *pFly = static_cast<SwFlyFrm*>(pObj);
+ //Ggf. ummelden, nicht anmelden wenn bereits bekannt.
+ // --> OD 2004-06-30 #i28701# - use new method <GetPageFrm()>
+ SwPageFrm *pPg = pFly->IsFlyFreeFrm()
+ ? pFly->GetPageFrm() : pFly->FindPageFrm();
+ if ( pPg != pPage )
+ {
+ if ( pPg )
+ pPg->RemoveFlyFromPage( pFly );
+ pPage->AppendFlyToPage( pFly );
+ }
+ ::RegistFlys( pPage, pFly );
+ }
+ else
+ {
+ // --> OD 2008-04-22 #i87493#
+ if ( pPage != pObj->GetPageFrm() )
+ {
+ // --> OD 2004-07-02 #i28701#
+ if ( pObj->GetPageFrm() )
+ pObj->GetPageFrm()->RemoveDrawObjFromPage( *pObj );
+ pPage->AppendDrawObjToPage( *pObj );
+ // <--
+ }
+ // <--
+ }
+
+ const SwFlyFrm* pFly = pAnch->FindFlyFrm();
+ if ( pFly &&
+ pObj->GetDrawObj()->GetOrdNum() < pFly->GetVirtDrawObj()->GetOrdNum() &&
+ pObj->GetDrawObj()->GetPage() )
+ {
+ pObj->DrawObj()->GetPage()->SetObjectOrdNum(
+ pObj->GetDrawObj()->GetOrdNumDirect(),
+ pFly->GetVirtDrawObj()->GetOrdNumDirect() + 1 );
+ }
+ }
+}
+
+void RegistFlys( SwPageFrm *pPage, const SwLayoutFrm *pLay )
+{
+ if ( pLay->GetDrawObjs() )
+ ::lcl_Regist( pPage, pLay );
+ const SwFrm *pFrm = pLay->Lower();
+ while ( pFrm )
+ {
+ if ( pFrm->IsLayoutFrm() )
+ ::RegistFlys( pPage, (const SwLayoutFrm*)pFrm );
+ else if ( pFrm->GetDrawObjs() )
+ ::lcl_Regist( pPage, pFrm );
+ pFrm = pFrm->GetNext();
+ }
+}
+
+/*************************************************************************
+|*
+|* void Notify()
+|*
+|* Beschreibung Benachrichtigt den Hintergrund je nach der
+|* Veraenderung zwischen altem und neuem Rechteckt.
+|*
+|*************************************************************************/
+
+void Notify( SwFlyFrm *pFly, SwPageFrm *pOld, const SwRect &rOld,
+ const SwRect* pOldPrt )
+{
+ const SwRect aFrm( pFly->GetObjRectWithSpaces() );
+ if ( rOld.Pos() != aFrm.Pos() )
+ { //Positionsaenderung, alten und neuen Bereich invalidieren
+ if ( rOld.HasArea() &&
+ rOld.Left()+pFly->GetFmt()->GetLRSpace().GetLeft() < WEIT_WECH )
+ {
+ pFly->NotifyBackground( pOld, rOld, PREP_FLY_LEAVE );
+ }
+ pFly->NotifyBackground( pFly->FindPageFrm(), aFrm, PREP_FLY_ARRIVE );
+ }
+ else if ( rOld.SSize() != aFrm.SSize() )
+ { //Groessenaenderung, den Bereich der Verlassen wurde bzw. jetzt
+ //ueberdeckt wird invalidieren.
+ //Der Einfachheit halber wird hier bewusst jeweils ein Twip
+ //unnoetig invalidiert.
+
+ ViewShell *pSh = pFly->getRootFrm()->GetCurrShell();
+ if( pSh && rOld.HasArea() )
+ pSh->InvalidateWindows( rOld );
+
+ // --> OD 2005-08-19 #i51941# - consider case that fly frame isn't
+ // registered at the old page <pOld>
+ SwPageFrm* pPageFrm = pFly->FindPageFrm();
+ if ( pOld != pPageFrm )
+ {
+ pFly->NotifyBackground( pPageFrm, aFrm, PREP_FLY_ARRIVE );
+ }
+ // <--
+
+ if ( rOld.Left() != aFrm.Left() )
+ {
+ SwRect aTmp( rOld );
+ aTmp.Union( aFrm );
+ aTmp.Left( Min(aFrm.Left(), rOld.Left()) );
+ aTmp.Right( Max(aFrm.Left(), rOld.Left()) );
+ pFly->NotifyBackground( pOld, aTmp, PREP_FLY_CHGD );
+ }
+ SwTwips nOld = rOld.Right();
+ SwTwips nNew = aFrm.Right();
+ if ( nOld != nNew )
+ {
+ SwRect aTmp( rOld );
+ aTmp.Union( aFrm );
+ aTmp.Left( Min(nNew, nOld) );
+ aTmp.Right( Max(nNew, nOld) );
+ pFly->NotifyBackground( pOld, aTmp, PREP_FLY_CHGD );
+ }
+ if ( rOld.Top() != aFrm.Top() )
+ {
+ SwRect aTmp( rOld );
+ aTmp.Union( aFrm );
+ aTmp.Top( Min(aFrm.Top(), rOld.Top()) );
+ aTmp.Bottom( Max(aFrm.Top(), rOld.Top()) );
+ pFly->NotifyBackground( pOld, aTmp, PREP_FLY_CHGD );
+ }
+ nOld = rOld.Bottom();
+ nNew = aFrm.Bottom();
+ if ( nOld != nNew )
+ {
+ SwRect aTmp( rOld );
+ aTmp.Union( aFrm );
+ aTmp.Top( Min(nNew, nOld) );
+ aTmp.Bottom( Max(nNew, nOld) );
+ pFly->NotifyBackground( pOld, aTmp, PREP_FLY_CHGD );
+ }
+ }
+ else if ( pOldPrt && *pOldPrt != pFly->Prt() &&
+ pFly->GetFmt()->GetSurround().IsContour() )
+ {
+ // #i24097#
+ pFly->NotifyBackground( pFly->FindPageFrm(), aFrm, PREP_FLY_ARRIVE );
+ }
+}
+
+/*************************************************************************/
+
+void lcl_CheckFlowBack( SwFrm* pFrm, const SwRect &rRect )
+{
+ SwTwips nBottom = rRect.Bottom();
+ while( pFrm )
+ {
+ if( pFrm->IsLayoutFrm() )
+ {
+ if( rRect.IsOver( pFrm->Frm() ) )
+ lcl_CheckFlowBack( ((SwLayoutFrm*)pFrm)->Lower(), rRect );
+ }
+ else if( !pFrm->GetNext() && nBottom > pFrm->Frm().Bottom() )
+ {
+ if( pFrm->IsCntntFrm() && ((SwCntntFrm*)pFrm)->HasFollow() )
+ pFrm->InvalidateSize();
+ else
+ pFrm->InvalidateNextPos();
+ }
+ pFrm = pFrm->GetNext();
+ }
+}
+
+void MA_FASTCALL lcl_NotifyCntnt( const SdrObject *pThis, SwCntntFrm *pCnt,
+ const SwRect &rRect, const PrepareHint eHint )
+{
+ if ( pCnt->IsTxtFrm() )
+ {
+ SwRect aCntPrt( pCnt->Prt() );
+ aCntPrt.Pos() += pCnt->Frm().Pos();
+ if ( eHint == PREP_FLY_ATTR_CHG )
+ {
+ // --> OD 2004-10-20 #i35640# - use given rectangle <rRect> instead
+ // of current bound rectangle
+ if ( aCntPrt.IsOver( rRect ) )
+ // <--
+ pCnt->Prepare( PREP_FLY_ATTR_CHG );
+ }
+ // --> OD 2004-11-01 #i23129# - only invalidate, if the text frame
+ // printing area overlaps with the given rectangle.
+ else if ( aCntPrt.IsOver( rRect ) )
+ // <--
+ pCnt->Prepare( eHint, (void*)&aCntPrt._Intersection( rRect ) );
+ if ( pCnt->GetDrawObjs() )
+ {
+ const SwSortedObjs &rObjs = *pCnt->GetDrawObjs();
+ for ( sal_uInt16 i = 0; i < rObjs.Count(); ++i )
+ {
+ SwAnchoredObject* pObj = rObjs[i];
+ if ( pObj->ISA(SwFlyFrm) )
+ {
+ SwFlyFrm *pFly = static_cast<SwFlyFrm*>(pObj);
+ if ( pFly->IsFlyInCntFrm() )
+ {
+ SwCntntFrm *pCntnt = pFly->ContainsCntnt();
+ while ( pCntnt )
+ {
+ ::lcl_NotifyCntnt( pThis, pCntnt, rRect, eHint );
+ pCntnt = pCntnt->GetNextCntntFrm();
+ }
+ }
+ }
+ }
+ }
+ }
+}
+
+void Notify_Background( const SdrObject* pObj,
+ SwPageFrm* pPage,
+ const SwRect& rRect,
+ const PrepareHint eHint,
+ const sal_Bool bInva )
+{
+
+ //Wenn der Frm gerade erstmalig sinnvoll positioniert wurde, braucht der
+ //alte Bereich nicht benachrichtigt werden.
+ if ( eHint == PREP_FLY_LEAVE && rRect.Top() == WEIT_WECH )
+ return;
+
+ SwLayoutFrm* pArea;
+ SwFlyFrm *pFlyFrm = 0;
+ SwFrm* pAnchor;
+ if( pObj->ISA(SwVirtFlyDrawObj) )
+ {
+ pFlyFrm = ((SwVirtFlyDrawObj*)pObj)->GetFlyFrm();
+ pAnchor = pFlyFrm->AnchorFrm();
+ }
+ else
+ {
+ pFlyFrm = NULL;
+ pAnchor = const_cast<SwFrm*>(
+ GetUserCall(pObj)->GetAnchoredObj( pObj )->GetAnchorFrm() );
+ }
+ if( PREP_FLY_LEAVE != eHint && pAnchor->IsInFly() )
+ pArea = pAnchor->FindFlyFrm();
+ else
+ pArea = pPage;
+ SwCntntFrm *pCnt = 0;
+ if ( pArea )
+ {
+ if( PREP_FLY_ARRIVE != eHint )
+ lcl_CheckFlowBack( pArea, rRect );
+
+ //Es reagieren sowieso nur die auf den Anker folgenden auf den Fly, also
+ //brauchen diese nicht abgeklappert werden.
+ //Ausnahme sind ist natuerlich das LEAVE, denn der Fly koennte ja von
+ //"oben" kommen.
+ // Wenn der Anker auf der vorhergehenden Seite liegt, muss ebenfalls
+ // die gesamte Seite abgearbeitet werden. (47722)
+ // OD 2004-05-13 #i28701# - If the wrapping style has to be considered
+ // on the object positioning, the complete area has to be processed,
+ // because content frames before the anchor frame also have to consider
+ // the object for the text wrapping.
+ // --> OD 2004-08-25 #i3317# - The complete area has always been
+ // processed.
+ {
+ pCnt = pArea->ContainsCntnt();
+ }
+ // <--
+ }
+ SwFrm *pLastTab = 0;
+
+ while ( pCnt && pArea && pArea->IsAnLower( pCnt ) )
+ {
+ ::lcl_NotifyCntnt( pObj, pCnt, rRect, eHint );
+ if ( pCnt->IsInTab() )
+ {
+ SwLayoutFrm* pCell = pCnt->GetUpper();
+ // --> OD 2005-01-14 #i40606# - use <GetLastBoundRect()>
+ // instead of <GetCurrentBoundRect()>, because a recalculation
+ // of the bounding rectangle isn't intended here.
+ if ( pCell->IsCellFrm() &&
+ ( pCell->Frm().IsOver( pObj->GetLastBoundRect() ) ||
+ pCell->Frm().IsOver( rRect ) ) )
+ // <--
+ {
+ const SwFmtVertOrient &rOri = pCell->GetFmt()->GetVertOrient();
+ if ( text::VertOrientation::NONE != rOri.GetVertOrient() )
+ pCell->InvalidatePrt();
+ }
+ SwTabFrm *pTab = pCnt->FindTabFrm();
+ if ( pTab != pLastTab )
+ {
+ pLastTab = pTab;
+ // --> OD 2005-01-14 #i40606# - use <GetLastBoundRect()>
+ // instead of <GetCurrentBoundRect()>, because a recalculation
+ // of the bounding rectangle isn't intended here.
+ if ( pTab->Frm().IsOver( pObj->GetLastBoundRect() ) ||
+ pTab->Frm().IsOver( rRect ) )
+ // <--
+ {
+ if ( !pFlyFrm || !pFlyFrm->IsLowerOf( pTab ) )
+ pTab->InvalidatePrt();
+ }
+ }
+ }
+ pCnt = pCnt->GetNextCntntFrm();
+ }
+// #108745# Sorry, but this causes nothing but trouble. I remove these lines
+// taking the risk that the footer frame will have a wrong height
+// if( pPage->Lower() )
+// {
+// SwFrm* pFrm = pPage->Lower();
+// while( pFrm->GetNext() )
+// pFrm = pFrm->GetNext();
+// if( pFrm->IsFooterFrm() &&
+// ( ( pFrm->Frm().IsOver( pObj->GetBoundRect() ) ||
+// pFrm->Frm().IsOver( rRect ) ) ) )
+// pFrm->InvalidateSize();
+// }
+ // --> OD 2007-07-24 #128702# - make code robust
+ if ( pPage && pPage->GetSortedObjs() )
+ // <--
+ {
+ pObj->GetOrdNum();
+ const SwSortedObjs &rObjs = *pPage->GetSortedObjs();
+ for ( sal_uInt16 i = 0; i < rObjs.Count(); ++i )
+ {
+ SwAnchoredObject* pAnchoredObj = rObjs[i];
+ if ( pAnchoredObj->ISA(SwFlyFrm) )
+ {
+ if( pAnchoredObj->GetDrawObj() == pObj )
+ continue;
+ SwFlyFrm *pFly = static_cast<SwFlyFrm*>(pAnchoredObj);
+ if ( pFly->Frm().Top() == WEIT_WECH )
+ continue;
+
+ if ( !pFlyFrm ||
+ (!pFly->IsLowerOf( pFlyFrm ) &&
+ pFly->GetVirtDrawObj()->GetOrdNumDirect() < pObj->GetOrdNumDirect()))
+ {
+ pCnt = pFly->ContainsCntnt();
+ while ( pCnt )
+ {
+ ::lcl_NotifyCntnt( pObj, pCnt, rRect, eHint );
+ pCnt = pCnt->GetNextCntntFrm();
+ }
+ }
+ if( pFly->IsFlyLayFrm() )
+ {
+ if( pFly->Lower() && pFly->Lower()->IsColumnFrm() &&
+ pFly->Frm().Bottom() >= rRect.Top() &&
+ pFly->Frm().Top() <= rRect.Bottom() &&
+ pFly->Frm().Right() >= rRect.Left() &&
+ pFly->Frm().Left() <= rRect.Right() )
+ {
+ pFly->InvalidateSize();
+ }
+ }
+ //Flys, die ueber mir liegen muessen/mussten evtl.
+ //ausweichen, wenn sie eine automatische Ausrichtung haben.
+ //das ist unabhaengig von meinem Attribut, weil dies sich
+ //gerade geaendert haben kann und eben deshalb
+ //umformatiert wurde.
+ else if ( pFly->IsFlyAtCntFrm() &&
+ pObj->GetOrdNumDirect() <
+ pFly->GetVirtDrawObj()->GetOrdNumDirect() &&
+ pFlyFrm && !pFly->IsLowerOf( pFlyFrm ) )
+ {
+ const SwFmtHoriOrient &rH = pFly->GetFmt()->GetHoriOrient();
+ if ( text::HoriOrientation::NONE != rH.GetHoriOrient() &&
+ text::HoriOrientation::CENTER != rH.GetHoriOrient() &&
+ ( !pFly->IsAutoPos() || text::RelOrientation::CHAR != rH.GetRelationOrient() ) &&
+ (pFly->Frm().Bottom() >= rRect.Top() &&
+ pFly->Frm().Top() <= rRect.Bottom()) )
+ pFly->InvalidatePos();
+ }
+ }
+ }
+ }
+ if ( pFlyFrm && pAnchor->GetUpper() && pAnchor->IsInTab() )//MA_FLY_HEIGHT
+ pAnchor->GetUpper()->InvalidateSize();
+
+ // --> OD 2008-01-30 #i82258# - make code robust
+ ViewShell* pSh = 0;
+ if ( bInva && pPage &&
+ 0 != (pSh = pPage->getRootFrm()->GetCurrShell()) )
+ {
+ pSh->InvalidateWindows( rRect );
+ }
+ // <--
+}
+
+/*************************************************************************
+|*
+|* GetVirtualUpper() liefert bei absatzgebundenen Objekten den Upper
+|* des Ankers. Falls es sich dabei um verkettete Rahmen oder
+|* Fussnoten handelt, wird ggf. der "virtuelle" Upper ermittelt.
+|*
+|*************************************************************************/
+
+const SwFrm* GetVirtualUpper( const SwFrm* pFrm, const Point& rPos )
+{
+ if( pFrm->IsTxtFrm() )
+ {
+ pFrm = pFrm->GetUpper();
+ if( !pFrm->Frm().IsInside( rPos ) )
+ {
+ if( pFrm->IsFtnFrm() )
+ {
+ const SwFtnFrm* pTmp = ((SwFtnFrm*)pFrm)->GetFollow();
+ while( pTmp )
+ {
+ if( pTmp->Frm().IsInside( rPos ) )
+ return pTmp;
+ pTmp = pTmp->GetFollow();
+ }
+ }
+ else
+ {
+ SwFlyFrm* pTmp = (SwFlyFrm*)pFrm->FindFlyFrm();
+ while( pTmp )
+ {
+ if( pTmp->Frm().IsInside( rPos ) )
+ return pTmp;
+ pTmp = pTmp->GetNextLink();
+ }
+ }
+ }
+ }
+ return pFrm;
+}
+
+/*************************************************************************/
+
+sal_Bool Is_Lower_Of( const SwFrm *pCurrFrm, const SdrObject* pObj )
+{
+ Point aPos;
+ const SwFrm* pFrm;
+ if( pObj->ISA(SwVirtFlyDrawObj) )
+ {
+ const SwFlyFrm* pFly = ( (SwVirtFlyDrawObj*)pObj )->GetFlyFrm();
+ pFrm = pFly->GetAnchorFrm();
+ aPos = pFly->Frm().Pos();
+ }
+ else
+ {
+ pFrm = ( (SwDrawContact*)GetUserCall(pObj) )->GetAnchorFrm(pObj);
+ aPos = pObj->GetCurrentBoundRect().TopLeft();
+ }
+ OSL_ENSURE( pFrm, "8-( Fly is lost in Space." );
+ pFrm = GetVirtualUpper( pFrm, aPos );
+ do
+ { if ( pFrm == pCurrFrm )
+ return sal_True;
+ if( pFrm->IsFlyFrm() )
+ {
+ aPos = pFrm->Frm().Pos();
+ pFrm = GetVirtualUpper( ((const SwFlyFrm*)pFrm)->GetAnchorFrm(), aPos );
+ }
+ else
+ pFrm = pFrm->GetUpper();
+ } while ( pFrm );
+ return sal_False;
+}
+
+const SwFrm *FindKontext( const SwFrm *pFrm, sal_uInt16 nAdditionalKontextTyp )
+{
+ //Liefert die Umgebung des Frm in die kein Fly aus einer anderen
+ //Umgebung hineinragen kann.
+ const sal_uInt16 nTyp = FRM_ROOT | FRM_HEADER | FRM_FOOTER | FRM_FTNCONT |
+ FRM_FTN | FRM_FLY |
+ FRM_TAB | FRM_ROW | FRM_CELL |
+ nAdditionalKontextTyp;
+ do
+ { if ( pFrm->GetType() & nTyp )
+ break;
+ pFrm = pFrm->GetUpper();
+ } while( pFrm );
+ return pFrm;
+}
+
+sal_Bool IsFrmInSameKontext( const SwFrm *pInnerFrm, const SwFrm *pFrm )
+{
+ const SwFrm *pKontext = FindKontext( pInnerFrm, 0 );
+
+ const sal_uInt16 nTyp = FRM_ROOT | FRM_HEADER | FRM_FOOTER | FRM_FTNCONT |
+ FRM_FTN | FRM_FLY |
+ FRM_TAB | FRM_ROW | FRM_CELL;
+ do
+ { if ( pFrm->GetType() & nTyp )
+ {
+ if( pFrm == pKontext )
+ return sal_True;
+ if( pFrm->IsCellFrm() )
+ return sal_False;
+ }
+ if( pFrm->IsFlyFrm() )
+ {
+ Point aPos( pFrm->Frm().Pos() );
+ pFrm = GetVirtualUpper( ((const SwFlyFrm*)pFrm)->GetAnchorFrm(), aPos );
+ }
+ else
+ pFrm = pFrm->GetUpper();
+ } while( pFrm );
+
+ return sal_False;
+}
+
+
+//---------------------------------
+
+SwTwips MA_FASTCALL lcl_CalcCellRstHeight( SwLayoutFrm *pCell )
+{
+ if ( pCell->Lower()->IsCntntFrm() || pCell->Lower()->IsSctFrm() )
+ {
+ SwFrm *pLow = pCell->Lower();
+ long nHeight = 0, nFlyAdd = 0;
+ do
+ {
+ long nLow = pLow->Frm().Height();
+ if( pLow->IsTxtFrm() && ((SwTxtFrm*)pLow)->IsUndersized() )
+ nLow += ((SwTxtFrm*)pLow)->GetParHeight()-pLow->Prt().Height();
+ else if( pLow->IsSctFrm() && ((SwSectionFrm*)pLow)->IsUndersized() )
+ nLow += ((SwSectionFrm*)pLow)->Undersize();
+ nFlyAdd = Max( 0L, nFlyAdd - nLow );
+ nFlyAdd = Max( nFlyAdd, ::CalcHeightWidthFlys( pLow ) );
+ nHeight += nLow;
+ pLow = pLow->GetNext();
+ } while ( pLow );
+ if ( nFlyAdd )
+ nHeight += nFlyAdd;
+
+ //Der Border will natuerlich auch mitspielen, er kann leider nicht
+ //aus PrtArea und Frm errechnet werden, da diese in beliebiger
+ //Kombination ungueltig sein koennen.
+ SwBorderAttrAccess aAccess( SwFrm::GetCache(), pCell );
+ const SwBorderAttrs &rAttrs = *aAccess.Get();
+ nHeight += rAttrs.CalcTop() + rAttrs.CalcBottom();
+
+ return pCell->Frm().Height() - nHeight;
+ }
+ else
+ {
+ long nRstHeight = 0;
+ SwFrm *pLow = pCell->Lower();
+ do
+ { nRstHeight += ::CalcRowRstHeight( (SwLayoutFrm*)pLow );
+ pLow = pLow->GetNext();
+
+ } while ( pLow );
+
+ return nRstHeight;
+ }
+}
+
+SwTwips MA_FASTCALL CalcRowRstHeight( SwLayoutFrm *pRow )
+{
+ SwTwips nRstHeight = LONG_MAX;
+ SwLayoutFrm *pLow = (SwLayoutFrm*)pRow->Lower();
+ while ( pLow )
+ {
+ nRstHeight = Min( nRstHeight, ::lcl_CalcCellRstHeight( pLow ) );
+ pLow = (SwLayoutFrm*)pLow->GetNext();
+ }
+ return nRstHeight;
+}
+
+const SwFrm* MA_FASTCALL FindPage( const SwRect &rRect, const SwFrm *pPage )
+{
+ if ( !rRect.IsOver( pPage->Frm() ) )
+ {
+ const SwRootFrm* pRootFrm = static_cast<const SwRootFrm*>(pPage->GetUpper());
+ const SwFrm* pTmpPage = pRootFrm ? pRootFrm->GetPageAtPos( rRect.TopLeft(), &rRect.SSize(), true ) : 0;
+ if ( pTmpPage )
+ pPage = pTmpPage;
+ }
+
+ return pPage;
+}
+
+#include <svl/smplhint.hxx>
+class SwFrmHolder : private SfxListener
+{
+ SwFrm* pFrm;
+ bool bSet;
+ virtual void Notify( SfxBroadcaster& rBC, const SfxHint& rHint );
+public:
+ SwFrmHolder() : pFrm(0), bSet(false) {}
+ void SetFrm( SwFrm* pHold );
+ SwFrm* GetFrm() { return pFrm; }
+ void Reset();
+ bool IsSet() { return bSet; }
+};
+
+void SwFrmHolder::SetFrm( SwFrm* pHold )
+{
+ bSet = true;
+ pFrm = pHold;
+ StartListening(*pHold);
+}
+
+void SwFrmHolder::Reset()
+{
+ if (pFrm)
+ EndListening(*pFrm);
+ bSet = false;
+ pFrm = 0;
+}
+
+void SwFrmHolder::Notify( SfxBroadcaster& rBC, const SfxHint& rHint )
+{
+ if ( rHint.IsA(TYPE(SfxSimpleHint)) )
+ {
+ if ( ( (SfxSimpleHint&) rHint ).GetId() == SFX_HINT_DYING && &rBC == pFrm )
+ pFrm = 0;
+ }
+}
+
+SwFrm* GetFrmOfModify( const SwRootFrm* pLayout, SwModify const& rMod, sal_uInt16 const nFrmType,
+ const Point* pPoint, const SwPosition *pPos, const sal_Bool bCalcFrm )
+{
+ SwFrm *pMinFrm = 0, *pTmpFrm;
+ SwFrmHolder aHolder;
+ SwRect aCalcRect;
+ bool bClientIterChanged = false;
+
+ SwIterator<SwFrm,SwModify> aIter( rMod );
+ do {
+ pMinFrm = 0;
+ aHolder.Reset();
+ sal_uInt64 nMinDist = 0;
+ bClientIterChanged = false;
+
+ for( pTmpFrm = aIter.First(); pTmpFrm; pTmpFrm = aIter.Next() )
+ {
+ if( pTmpFrm->GetType() & nFrmType &&
+ ( !pLayout || pLayout == pTmpFrm->getRootFrm() ) &&
+ (!pTmpFrm->IsFlowFrm() ||
+ !SwFlowFrm::CastFlowFrm( pTmpFrm )->IsFollow() ))
+ {
+ if( pPoint )
+ {
+ // watch for Frm being deleted
+ if ( pMinFrm )
+ aHolder.SetFrm( pMinFrm );
+ else
+ aHolder.Reset();
+
+ if( bCalcFrm )
+ {
+ // --> OD 2005-03-04 #b6234250# - format parent Writer
+ // fly frame, if it isn't been formatted yet.
+ // Note: The Writer fly frame could be the frame itself.
+ SwFlyFrm* pFlyFrm( pTmpFrm->FindFlyFrm() );
+ if ( pFlyFrm &&
+ pFlyFrm->Frm().Pos().X() == WEIT_WECH &&
+ pFlyFrm->Frm().Pos().Y() == WEIT_WECH )
+ {
+ SwObjectFormatter::FormatObj( *pFlyFrm );
+ }
+ // <--
+ pTmpFrm->Calc();
+ }
+
+ // #127369#
+ // aIter.IsChanged checks if the current pTmpFrm has been deleted while
+ // it is the current iterator
+ // FrmHolder watches for deletion of the current pMinFrm
+ if( aIter.IsChanged() || ( aHolder.IsSet() && !aHolder.GetFrm() ) )
+ {
+ // restart iteration
+ bClientIterChanged = true;
+ break;
+ }
+
+ // bei Flys ggfs. ueber den Parent gehen wenn sie selbst
+ // nocht nicht "formatiert" sind
+ if( !bCalcFrm && nFrmType & FRM_FLY &&
+ ((SwFlyFrm*)pTmpFrm)->GetAnchorFrm() &&
+ WEIT_WECH == pTmpFrm->Frm().Pos().X() &&
+ WEIT_WECH == pTmpFrm->Frm().Pos().Y() )
+ aCalcRect = ((SwFlyFrm*)pTmpFrm)->GetAnchorFrm()->Frm();
+ else
+ aCalcRect = pTmpFrm->Frm();
+
+ if ( aCalcRect.IsInside( *pPoint ) )
+ {
+ pMinFrm = pTmpFrm;
+ break;
+ }
+
+ // Point not in rectangle. Compare distances:
+ const Point aCalcRectCenter = aCalcRect.Center();
+ const Point aDiff = aCalcRectCenter - *pPoint;
+ const sal_uInt64 nCurrentDist = aDiff.X() * aDiff.X() + aDiff.Y() * aDiff.Y(); // opt: no sqrt
+ if ( !pMinFrm || nCurrentDist < nMinDist )
+ {
+ pMinFrm = pTmpFrm;
+ nMinDist = nCurrentDist;
+ }
+ }
+ else
+ {
+ // Wenn kein pPoint angegeben ist, dann reichen
+ // wir irgendeinen raus: den ersten!
+ pMinFrm = pTmpFrm;
+ break;
+ }
+ }
+ }
+ } while( bClientIterChanged );
+
+ if( pPos && pMinFrm && pMinFrm->IsTxtFrm() )
+ return ((SwTxtFrm*)pMinFrm)->GetFrmAtPos( *pPos );
+
+ return pMinFrm;
+}
+
+sal_Bool IsExtraData( const SwDoc *pDoc )
+{
+ const SwLineNumberInfo &rInf = pDoc->GetLineNumberInfo();
+ return rInf.IsPaintLineNumbers() ||
+ rInf.IsCountInFlys() ||
+ ((sal_Int16)SW_MOD()->GetRedlineMarkPos() != text::HoriOrientation::NONE &&
+ pDoc->GetRedlineTbl().Count());
+}
+
+// OD 22.09.2003 #110978#
+const SwRect SwPageFrm::PrtWithoutHeaderAndFooter() const
+{
+ SwRect aPrtWithoutHeaderFooter( Prt() );
+ aPrtWithoutHeaderFooter.Pos() += Frm().Pos();
+
+ const SwFrm* pLowerFrm = Lower();
+ while ( pLowerFrm )
+ {
+ // Note: independent on text direction page header and page footer are
+ // always at top respectively at bottom of the page frame.
+ if ( pLowerFrm->IsHeaderFrm() )
+ {
+ aPrtWithoutHeaderFooter.Top( aPrtWithoutHeaderFooter.Top() +
+ pLowerFrm->Frm().Height() );
+ }
+ if ( pLowerFrm->IsFooterFrm() )
+ {
+ aPrtWithoutHeaderFooter.Bottom( aPrtWithoutHeaderFooter.Bottom() -
+ pLowerFrm->Frm().Height() );
+ }
+
+ pLowerFrm = pLowerFrm->GetNext();
+ }
+
+ return aPrtWithoutHeaderFooter;
+}
+
+/** method to determine the spacing values of a frame
+
+ OD 2004-03-10 #i28701#
+ OD 2009-08-28 #i102458#
+ Add output parameter <obIsLineSpacingProportional>
+
+ @author OD
+*/
+void GetSpacingValuesOfFrm( const SwFrm& rFrm,
+ SwTwips& onLowerSpacing,
+ SwTwips& onLineSpacing,
+ bool& obIsLineSpacingProportional )
+{
+ if ( !rFrm.IsFlowFrm() )
+ {
+ onLowerSpacing = 0;
+ onLineSpacing = 0;
+ }
+ else
+ {
+ const SvxULSpaceItem& rULSpace = rFrm.GetAttrSet()->GetULSpace();
+ onLowerSpacing = rULSpace.GetLower();
+
+ onLineSpacing = 0;
+ obIsLineSpacingProportional = false;
+ if ( rFrm.IsTxtFrm() )
+ {
+ onLineSpacing = static_cast<const SwTxtFrm&>(rFrm).GetLineSpace();
+ obIsLineSpacingProportional =
+ onLineSpacing != 0 &&
+ static_cast<const SwTxtFrm&>(rFrm).GetLineSpace( true ) == 0;
+ }
+
+ OSL_ENSURE( onLowerSpacing >= 0 && onLineSpacing >= 0,
+ "<GetSpacingValuesOfFrm(..)> - spacing values aren't positive!" );
+ }
+}
+
+/** method to get the content of the table cell, skipping content from nested tables
+*/
+const SwCntntFrm* GetCellCntnt( const SwLayoutFrm& rCell )
+{
+ const SwCntntFrm* pCntnt = rCell.ContainsCntnt();
+ const SwTabFrm* pTab = rCell.FindTabFrm();
+
+ while ( pCntnt && rCell.IsAnLower( pCntnt ) )
+ {
+ const SwTabFrm* pTmpTab = pCntnt->FindTabFrm();
+ if ( pTmpTab != pTab )
+ {
+ pCntnt = pTmpTab->FindLastCntnt();
+ if ( pCntnt )
+
+ pCntnt = pCntnt->FindNextCnt();
+
+ }
+ else
+ break;
+ }
+ return pCntnt;
+}
+
+/** Can be used to check if a frame has been deleted
+ */
+bool SwDeletionChecker::HasBeenDeleted()
+{
+ if ( !mpFrm || !mpRegIn )
+ return false;
+
+ SwIterator<SwFrm,SwModify> aIter(*mpRegIn);
+ SwFrm* pLast = aIter.First();
+ while ( pLast )
+ {
+ if ( pLast == mpFrm )
+ return false;
+ pLast = aIter.Next();
+ }
+
+ return true;
+}
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/layout/ftnfrm.cxx b/sw/source/core/layout/ftnfrm.cxx
new file mode 100644
index 000000000000..608ecb57ddd5
--- /dev/null
+++ b/sw/source/core/layout/ftnfrm.cxx
@@ -0,0 +1,3241 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+#include <txtftn.hxx>
+#include <fmtftn.hxx>
+#include <ftnidx.hxx>
+#include <pagefrm.hxx>
+#include <colfrm.hxx>
+#include <rootfrm.hxx>
+#include <cntfrm.hxx>
+#include <doc.hxx>
+#include <ndtxt.hxx>
+#include <frmtool.hxx>
+#include <swtable.hxx>
+#include <ftnfrm.hxx>
+#include <txtfrm.hxx>
+#include <tabfrm.hxx>
+#include <pagedesc.hxx>
+#include <ftninfo.hxx>
+#include <ndindex.hxx>
+#include <sectfrm.hxx>
+#include <pam.hxx>
+#include <objectformatter.hxx>
+#include "viewopt.hxx"
+#include "viewsh.hxx"
+#include <switerator.hxx>
+
+/*************************************************************************
+|*
+|* lcl_FindFtnPos() Sucht die Position des Attributes im FtnArray am
+|* Dokument, dort stehen die Fussnoten gluecklicherweise nach ihrem
+|* Index sortiert.
+|*
+|*************************************************************************/
+
+#define ENDNOTE 0x80000000
+
+sal_uLong MA_FASTCALL lcl_FindFtnPos( const SwDoc *pDoc, const SwTxtFtn *pAttr )
+{
+ const SwFtnIdxs &rFtnIdxs = pDoc->GetFtnIdxs();
+
+ sal_uInt16 nRet;
+ SwTxtFtnPtr pBla = (SwTxtFtn*)pAttr;
+ if ( rFtnIdxs.Seek_Entry( pBla, &nRet ) )
+ {
+ if( pAttr->GetFtn().IsEndNote() )
+ return sal_uLong(nRet) + ENDNOTE;
+ return nRet;
+ }
+ OSL_ENSURE( !pDoc, "FtnPos not found." );
+ return 0;
+}
+
+sal_Bool SwFtnFrm::operator<( const SwTxtFtn* pTxtFtn ) const
+{
+ const SwDoc* pDoc = GetFmt()->GetDoc();
+ OSL_ENSURE( pDoc, "SwFtnFrm: Missing doc!" );
+ return lcl_FindFtnPos( pDoc, GetAttr() ) <
+ lcl_FindFtnPos( pDoc, pTxtFtn );
+}
+
+/*************************************************************************
+|*
+|* sal_Bool lcl_NextFtnBoss( SwFtnBossFrm* pBoss, SwPageFrm* pPage)
+|* setzt pBoss auf den naechsten SwFtnBossFrm, das kann entweder eine Spalte
+|* oder eine Seite (ohne Spalten) sein. Wenn die Seite dabei gewechselt wird
+|* enthaelt pPage die neue Seite und die Funktion liefert sal_True.
+|*
+|*************************************************************************/
+
+sal_Bool lcl_NextFtnBoss( SwFtnBossFrm* &rpBoss, SwPageFrm* &rpPage,
+ sal_Bool bDontLeave )
+{
+ if( rpBoss->IsColumnFrm() )
+ {
+ if( rpBoss->GetNext() )
+ {
+ rpBoss = (SwFtnBossFrm*)rpBoss->GetNext(); //naechste Spalte
+ return sal_False;
+ }
+ if( rpBoss->IsInSct() )
+ {
+ SwSectionFrm* pSct = rpBoss->FindSctFrm()->GetFollow();
+ if( pSct )
+ {
+ OSL_ENSURE( pSct->Lower() && pSct->Lower()->IsColumnFrm(),
+ "Where's the column?" );
+ rpBoss = (SwColumnFrm*)pSct->Lower();
+ SwPageFrm* pOld = rpPage;
+ rpPage = pSct->FindPageFrm();
+ return pOld != rpPage;
+ }
+ else if( bDontLeave )
+ {
+ rpPage = NULL;
+ rpBoss = NULL;
+ return sal_False;
+ }
+ }
+ }
+ rpPage = (SwPageFrm*)rpPage->GetNext(); // naechste Seite
+ rpBoss = rpPage;
+ if( rpPage )
+ {
+ SwLayoutFrm* pBody = rpPage->FindBodyCont();
+ if( pBody && pBody->Lower() && pBody->Lower()->IsColumnFrm() )
+ rpBoss = (SwFtnBossFrm*)pBody->Lower(); // erste Spalte
+ }
+ return sal_True;
+}
+
+/*************************************************************************
+|*
+|* sal_uInt16 lcl_ColumnNum( SwFrm* pBoss )
+|* liefert die Spaltennummer, wenn pBoss eine Spalte ist,
+|* sonst eine Null (bei Seiten).
+|*
+|*************************************************************************/
+
+sal_uInt16 lcl_ColumnNum( const SwFrm* pBoss )
+{
+ sal_uInt16 nRet = 0;
+ if( !pBoss->IsColumnFrm() )
+ return 0;
+ const SwFrm* pCol;
+ if( pBoss->IsInSct() )
+ {
+ pCol = pBoss->GetUpper()->FindColFrm();
+ if( pBoss->GetNext() || pBoss->GetPrev() )
+ {
+ while( pBoss )
+ {
+ ++nRet; // Section columns
+ pBoss = pBoss->GetPrev();
+ }
+ }
+ }
+ else
+ pCol = pBoss;
+ while( pCol )
+ {
+ nRet += 256; // Page columns
+ pCol = pCol->GetPrev();
+ }
+ return nRet;
+}
+
+/*************************************************************************
+|*
+|* SwFtnContFrm::SwFtnContFrm()
+|*
+|*************************************************************************/
+
+
+SwFtnContFrm::SwFtnContFrm( SwFrmFmt *pFmt, SwFrm* pSib ):
+ SwLayoutFrm( pFmt, pSib )
+{
+ nType = FRMC_FTNCONT;
+}
+
+
+// lcl_Undersize(..) klappert einen SwFrm und dessen Inneres ab
+// und liefert die Summe aller TxtFrm-Vergroesserungswuensche
+
+long lcl_Undersize( const SwFrm* pFrm )
+{
+ long nRet = 0;
+ SWRECTFN( pFrm )
+ if( pFrm->IsTxtFrm() )
+ {
+ if( ((SwTxtFrm*)pFrm)->IsUndersized() )
+ {
+ // Dieser TxtFrm waere gern ein bisschen groesser
+ nRet = ((SwTxtFrm*)pFrm)->GetParHeight() -
+ (pFrm->Prt().*fnRect->fnGetHeight)();
+ if( nRet < 0 )
+ nRet = 0;
+ }
+ }
+ else if( pFrm->IsLayoutFrm() )
+ {
+ const SwFrm* pNxt = ((SwLayoutFrm*)pFrm)->Lower();
+ while( pNxt )
+ {
+ nRet += lcl_Undersize( pNxt );
+ pNxt = pNxt->GetNext();
+ }
+ }
+ return nRet;
+}
+
+/*************************************************************************
+|*
+|* SwFtnContFrm::Format()
+|*
+|* Beschreibung: "Formatiert" den Frame;
+|* Die Fixsize wird hier nicht eingestellt.
+|*
+|*************************************************************************/
+
+
+void SwFtnContFrm::Format( const SwBorderAttrs * )
+{
+ //GesamtBorder ermitteln, es gibt nur einen Abstand nach oben.
+ const SwPageFrm* pPage = FindPageFrm();
+ const SwPageFtnInfo &rInf = pPage->GetPageDesc()->GetFtnInfo();
+ const SwTwips nBorder = rInf.GetTopDist() + rInf.GetBottomDist() +
+ rInf.GetLineWidth();
+ SWRECTFN( this )
+ if ( !bValidPrtArea )
+ {
+ bValidPrtArea = sal_True;
+ (Prt().*fnRect->fnSetTop)( nBorder );
+ (Prt().*fnRect->fnSetWidth)( (Frm().*fnRect->fnGetWidth)() );
+ (Prt().*fnRect->fnSetHeight)((Frm().*fnRect->fnGetHeight)() - nBorder );
+ if( (Prt().*fnRect->fnGetHeight)() < 0 && !pPage->IsFtnPage() )
+ bValidSize = sal_False;
+ }
+
+ if ( !bValidSize )
+ {
+ bool bGrow = pPage->IsFtnPage();
+ if( bGrow )
+ {
+ const ViewShell *pSh = getRootFrm() ? getRootFrm()->GetCurrShell() : 0;
+ if( pSh && pSh->GetViewOptions()->getBrowseMode() )
+ bGrow = false;
+ }
+ if( bGrow )
+ Grow( LONG_MAX, sal_False );
+ else
+ {
+ //Die Groesse in der VarSize wird durch den Inhalt plus den
+ //Raendern bestimmt.
+ SwTwips nRemaining = 0;
+ SwFrm *pFrm = pLower;
+ while ( pFrm )
+ { // lcl_Undersize(..) beruecksichtigt (rekursiv) TxtFrms, die gerne
+ // groesser waeren. Diese entstehen insbesondere in spaltigen Rahmen,
+ // wenn diese noch nicht ihre maximale Groesse haben.
+ nRemaining += (pFrm->Frm().*fnRect->fnGetHeight)()
+ + lcl_Undersize( pFrm );
+ pFrm = pFrm->GetNext();
+ }
+ //Jetzt noch den Rand addieren
+ nRemaining += nBorder;
+
+ SwTwips nDiff;
+ if( IsInSct() )
+ {
+ nDiff = -(Frm().*fnRect->fnBottomDist)(
+ (GetUpper()->*fnRect->fnGetPrtBottom)() );
+ if( nDiff > 0 )
+ {
+ if( nDiff > (Frm().*fnRect->fnGetHeight)() )
+ nDiff = (Frm().*fnRect->fnGetHeight)();
+ (Frm().*fnRect->fnAddBottom)( -nDiff );
+ (Prt().*fnRect->fnAddHeight)( -nDiff );
+ }
+ }
+ nDiff = (Frm().*fnRect->fnGetHeight)() - nRemaining;
+ if ( nDiff > 0 )
+ Shrink( nDiff );
+ else if ( nDiff < 0 )
+ {
+ Grow( -nDiff );
+ //Es kann passieren, dass weniger Platz zur Verfuegung steht,
+ //als der bereits der Border benoetigt - die Groesse der
+ //PrtArea wird dann negativ.
+ SwTwips nPrtHeight = (Prt().*fnRect->fnGetHeight)();
+ if( nPrtHeight < 0 )
+ {
+ const SwTwips nTmpDiff = Max( (Prt().*fnRect->fnGetTop)(),
+ -nPrtHeight );
+ (Prt().*fnRect->fnSubTop)( nTmpDiff );
+ }
+ }
+ }
+ bValidSize = sal_True;
+ }
+}
+/*************************************************************************
+|*
+|* SwFtnContFrm::GrowFrm(), ShrinkFrm()
+|*
+|*************************************************************************/
+
+SwTwips SwFtnContFrm::GrowFrm( SwTwips nDist, sal_Bool bTst, sal_Bool )
+{
+ //Keine Pruefung ob FixSize oder nicht, die FtnContainer sind immer bis
+ //zur Maximalhoehe variabel.
+ //Wenn die Maximalhoehe LONG_MAX ist, so nehmen wir uns soviel Platz wie eben
+ //moeglich.
+ //Wenn die Seite eine spezielle Fussnotenseite ist, so nehmen wir uns auch
+ //soviel Platz wie eben moeglich.
+#if OSL_DEBUG_LEVEL > 1
+ if ( !GetUpper() || !GetUpper()->IsFtnBossFrm() )
+ { OSL_ENSURE( !this, "Keine FtnBoss." );
+ return 0;
+ }
+#endif
+
+ SWRECTFN( this )
+ if( (Frm().*fnRect->fnGetHeight)() > 0 &&
+ nDist > ( LONG_MAX - (Frm().*fnRect->fnGetHeight)() ) )
+ nDist = LONG_MAX - (Frm().*fnRect->fnGetHeight)();
+
+ SwFtnBossFrm *pBoss = (SwFtnBossFrm*)GetUpper();
+ if( IsInSct() )
+ {
+ SwSectionFrm* pSect = FindSctFrm();
+ OSL_ENSURE( pSect, "GrowFrm: Missing SectFrm" );
+ // In a section, which has to maximize, a footnotecontainer is allowed
+ // to grow, when the section can't grow anymore.
+ if( !bTst && !pSect->IsColLocked() &&
+ pSect->ToMaximize( sal_False ) && pSect->Growable() )
+ {
+ pSect->InvalidateSize();
+ return 0;
+ }
+ }
+ const ViewShell *pSh = getRootFrm() ? getRootFrm()->GetCurrShell() : 0;
+ const sal_Bool bBrowseMode = pSh && pSh->GetViewOptions()->getBrowseMode();
+ SwPageFrm *pPage = pBoss->FindPageFrm();
+ if ( bBrowseMode || !pPage->IsFtnPage() )
+ {
+ if ( pBoss->GetMaxFtnHeight() != LONG_MAX )
+ {
+ nDist = Min( nDist, pBoss->GetMaxFtnHeight()
+ - (Frm().*fnRect->fnGetHeight)() );
+ if ( nDist <= 0 )
+ return 0L;
+ }
+ //Der FtnBoss will bezueglich des MaxWerts auch noch mitreden.
+ if( !IsInSct() )
+ {
+ const SwTwips nMax = pBoss->GetVarSpace();
+ if ( nDist > nMax )
+ nDist = nMax;
+ if ( nDist <= 0 )
+ return 0L;
+ }
+ }
+ else if( nDist > (GetPrev()->Frm().*fnRect->fnGetHeight)() )
+ //aber mehr als der Body kann koennen und wollen wir nun auch wieder
+ //nicht herausruecken.
+ nDist = (GetPrev()->Frm().*fnRect->fnGetHeight)();
+
+ long nAvail = 0;
+ if ( bBrowseMode )
+ {
+ nAvail = GetUpper()->Prt().Height();
+ const SwFrm *pAvail = GetUpper()->Lower();
+ do
+ { nAvail -= pAvail->Frm().Height();
+ pAvail = pAvail->GetNext();
+ } while ( pAvail );
+ if ( nAvail > nDist )
+ nAvail = nDist;
+ }
+
+ if ( !bTst )
+ {
+ (Frm().*fnRect->fnSetHeight)( (Frm().*fnRect->fnGetHeight)() + nDist );
+ //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin
+ if( IsVertical() && !IsVertLR() && !IsReverse() )
+ Frm().Pos().X() -= nDist;
+ }
+ long nGrow = nDist - nAvail,
+ nReal = 0;
+ if ( nGrow > 0 )
+ {
+ sal_uInt8 nAdjust = pBoss->NeighbourhoodAdjustment( this );
+ if( NA_ONLY_ADJUST == nAdjust )
+ nReal = AdjustNeighbourhood( nGrow, bTst );
+ else
+ {
+ if( NA_GROW_ADJUST == nAdjust )
+ {
+ SwFrm* pFtn = Lower();
+ if( pFtn )
+ {
+ while( pFtn->GetNext() )
+ pFtn = pFtn->GetNext();
+ if( ((SwFtnFrm*)pFtn)->GetAttr()->GetFtn().IsEndNote() )
+ {
+ nReal = AdjustNeighbourhood( nGrow, bTst );
+ nAdjust = NA_GROW_SHRINK; // no more AdjustNeighbourhood
+ }
+ }
+ }
+ nReal += pBoss->Grow( nGrow - nReal, bTst );
+ if( ( NA_GROW_ADJUST == nAdjust || NA_ADJUST_GROW == nAdjust )
+ && nReal < nGrow )
+ nReal += AdjustNeighbourhood( nGrow - nReal, bTst );
+ }
+ }
+
+ nReal += nAvail;
+
+ if ( !bTst )
+ {
+ if ( nReal != nDist )
+ {
+ nDist -= nReal;
+ //Den masslosen Wunsch koennen wir leider nur in Grenzen erfuellen.
+ Frm().SSize().Height() -= nDist;
+ //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin
+ if( IsVertical() && !IsVertLR() && !IsReverse() )
+ Frm().Pos().X() += nDist;
+ }
+
+ //Nachfolger braucht nicht invalidiert werden, denn wir wachsen
+ //immer nach oben.
+ if( nReal )
+ {
+ _InvalidateSize();
+ _InvalidatePos();
+ InvalidatePage( pPage );
+ }
+ }
+ return nReal;
+}
+
+
+SwTwips SwFtnContFrm::ShrinkFrm( SwTwips nDiff, sal_Bool bTst, sal_Bool bInfo )
+{
+ SwPageFrm *pPage = FindPageFrm();
+ bool bShrink = false;
+ if ( pPage )
+ {
+ if( !pPage->IsFtnPage() )
+ bShrink = true;
+ else
+ {
+ const ViewShell *pSh = getRootFrm()->GetCurrShell();
+ if( pSh && pSh->GetViewOptions()->getBrowseMode() )
+ bShrink = true;
+ }
+ }
+ if( bShrink )
+ {
+ SwTwips nRet = SwLayoutFrm::ShrinkFrm( nDiff, bTst, bInfo );
+ if( IsInSct() && !bTst )
+ FindSctFrm()->InvalidateNextPos();
+ if ( !bTst && nRet )
+ {
+ _InvalidatePos();
+ InvalidatePage( pPage );
+ }
+ return nRet;
+ }
+ return 0;
+}
+
+
+/*************************************************************************
+|*
+|* SwFtnFrm::SwFtnFrm()
+|*
+|*************************************************************************/
+
+
+SwFtnFrm::SwFtnFrm( SwFrmFmt *pFmt, SwFrm* pSib, SwCntntFrm *pCnt, SwTxtFtn *pAt ):
+ SwLayoutFrm( pFmt, pSib ),
+ pFollow( 0 ),
+ pMaster( 0 ),
+ pRef( pCnt ),
+ pAttr( pAt ),
+ bBackMoveLocked( sal_False ),
+ // --> OD 2005-08-11 #i49383#
+ mbUnlockPosOfLowerObjs( true )
+ // <--
+{
+ nType = FRMC_FTN;
+}
+
+/*************************************************************************
+|*
+|* SwFtnFrm::InvalidateNxtFtnCnts()
+|*
+|*************************************************************************/
+
+
+void SwFtnFrm::InvalidateNxtFtnCnts( SwPageFrm *pPage )
+{
+ if ( GetNext() )
+ {
+ SwFrm *pCnt = ((SwLayoutFrm*)GetNext())->ContainsAny();
+ if( pCnt )
+ {
+ pCnt->InvalidatePage( pPage );
+ pCnt->_InvalidatePrt();
+ do
+ { pCnt->_InvalidatePos();
+ if( pCnt->IsSctFrm() )
+ {
+ SwFrm* pTmp = ((SwSectionFrm*)pCnt)->ContainsAny();
+ if( pTmp )
+ pTmp->_InvalidatePos();
+ }
+ pCnt->GetUpper()->_InvalidateSize();
+ pCnt = pCnt->FindNext();
+ } while ( pCnt && GetUpper()->IsAnLower( pCnt ) );
+ }
+ }
+}
+
+#if OSL_DEBUG_LEVEL > 1
+
+SwTwips SwFtnFrm::GrowFrm( SwTwips nDist, sal_Bool bTst, sal_Bool bInfo )
+{
+ static sal_uInt16 nNum = USHRT_MAX;
+ SwTxtFtn* pTxtFtn = GetAttr();
+ if ( pTxtFtn->GetFtn().GetNumber() == nNum )
+ {
+ int bla = 5;
+ (void)bla;
+
+ }
+ return SwLayoutFrm::GrowFrm( nDist, bTst, bInfo );
+}
+
+
+SwTwips SwFtnFrm::ShrinkFrm( SwTwips nDist, sal_Bool bTst, sal_Bool bInfo )
+{
+ static sal_uInt16 nNum = USHRT_MAX;
+ if( nNum != USHRT_MAX )
+ {
+ SwTxtFtn* pTxtFtn = GetAttr();
+ if( &pTxtFtn->GetAttr() && pTxtFtn->GetFtn().GetNumber() == nNum )
+ {
+ int bla = 5;
+ (void)bla;
+ }
+ }
+ return SwLayoutFrm::ShrinkFrm( nDist, bTst, bInfo );
+}
+#endif
+
+/*************************************************************************
+|*
+|* SwFtnFrm::Cut()
+|*
+|*************************************************************************/
+
+
+void SwFtnFrm::Cut()
+{
+ if ( GetNext() )
+ GetNext()->InvalidatePos();
+ else if ( GetPrev() )
+ GetPrev()->SetRetouche();
+
+ //Erst removen, dann Upper Shrinken.
+ SwLayoutFrm *pUp = GetUpper();
+
+ //Verkettung korrigieren.
+ SwFtnFrm *pFtn = (SwFtnFrm*)this;
+ if ( pFtn->GetFollow() )
+ pFtn->GetFollow()->SetMaster( pFtn->GetMaster() );
+ if ( pFtn->GetMaster() )
+ pFtn->GetMaster()->SetFollow( pFtn->GetFollow() );
+ pFtn->SetFollow( 0 );
+ pFtn->SetMaster( 0 );
+
+ // Alle Verbindungen kappen.
+ Remove();
+
+ if ( pUp )
+ {
+ //Die letzte Fussnote nimmt ihren Container mit.
+ if ( !pUp->Lower() )
+ {
+ SwPageFrm *pPage = pUp->FindPageFrm();
+ if ( pPage )
+ {
+ SwLayoutFrm *pBody = pPage->FindBodyCont();
+ if( pBody && !pBody->ContainsCntnt() )
+ pPage->getRootFrm()->SetSuperfluous();
+ }
+ SwSectionFrm* pSect = pUp->FindSctFrm();
+ pUp->Cut();
+ delete pUp;
+ // Wenn der letzte Fussnotencontainer aus einem spaltigen Bereich verschwindet,
+ // so kann dieser, falls er keinen Follow besitzt, zusammenschrumpfen.
+ if( pSect && !pSect->ToMaximize( sal_False ) && !pSect->IsColLocked() )
+ pSect->_InvalidateSize();
+ }
+ else
+ { if ( Frm().Height() )
+ pUp->Shrink( Frm().Height() );
+ pUp->SetCompletePaint();
+ pUp->InvalidatePage();
+ }
+ }
+}
+
+/*************************************************************************
+|*
+|* SwFtnFrm::Paste()
+|*
+|*************************************************************************/
+
+
+void SwFtnFrm::Paste( SwFrm* pParent, SwFrm* pSibling )
+{
+ OSL_ENSURE( pParent, "Kein Parent fuer Paste." );
+ OSL_ENSURE( pParent->IsLayoutFrm(), "Parent ist CntntFrm." );
+ OSL_ENSURE( pParent != this, "Bin selbst der Parent." );
+ OSL_ENSURE( pSibling != this, "Bin mein eigener Nachbar." );
+ OSL_ENSURE( !GetPrev() && !GetNext() && !GetUpper(),
+ "Bin noch irgendwo angemeldet." );
+
+ //In den Baum einhaengen.
+ InsertBefore( (SwLayoutFrm*)pParent, pSibling );
+
+ SWRECTFN( this )
+ if( (Frm().*fnRect->fnGetWidth)()!=(pParent->Prt().*fnRect->fnGetWidth)() )
+ _InvalidateSize();
+ _InvalidatePos();
+ SwPageFrm *pPage = FindPageFrm();
+ InvalidatePage( pPage );
+ if ( GetNext() )
+ GetNext()->_InvalidatePos();
+ if( (Frm().*fnRect->fnGetHeight)() )
+ pParent->Grow( (Frm().*fnRect->fnGetHeight)() );
+
+ //Wenn mein Vorgaenger mein Master ist und/oder wenn mein Nachfolger mein
+ //Follow ist so kann ich deren Inhalt uebernehmen und sie vernichten.
+ if ( GetPrev() && GetPrev() == GetMaster() )
+ { OSL_ENSURE( SwFlowFrm::CastFlowFrm( GetPrev()->GetLower() ),
+ "Fussnote ohne Inhalt?" );
+ (SwFlowFrm::CastFlowFrm( GetPrev()->GetLower()))->
+ MoveSubTree( this, GetLower() );
+ SwFrm *pDel = GetPrev();
+ pDel->Cut();
+ delete pDel;
+ }
+ if ( GetNext() && GetNext() == GetFollow() )
+ { OSL_ENSURE( SwFlowFrm::CastFlowFrm( GetNext()->GetLower() ),
+ "Fussnote ohne Inhalt?" );
+ (SwFlowFrm::CastFlowFrm( GetNext()->GetLower()))->MoveSubTree( this );
+ SwFrm *pDel = GetNext();
+ pDel->Cut();
+ delete pDel;
+ }
+#if OSL_DEBUG_LEVEL > 1
+ SwDoc *pDoc = GetFmt()->GetDoc();
+ if ( GetPrev() )
+ {
+ OSL_ENSURE( lcl_FindFtnPos( pDoc, ((SwFtnFrm*)GetPrev())->GetAttr() ) <=
+ lcl_FindFtnPos( pDoc, GetAttr() ), "Prev ist not FtnPrev" );
+ }
+ if ( GetNext() )
+ {
+ OSL_ENSURE( lcl_FindFtnPos( pDoc, GetAttr() ) <=
+ lcl_FindFtnPos( pDoc, ((SwFtnFrm*)GetNext())->GetAttr() ),
+ "Next is not FtnNext" );
+ }
+#endif
+ InvalidateNxtFtnCnts( pPage );
+}
+
+/*************************************************************************
+|*
+|* SwFrm::GetNextFtnLeaf()
+|*
+|* Beschreibung Liefert das naechste LayoutBlatt in den das
+|* Frame gemoved werden kann.
+|* Neue Seiten werden nur dann erzeugt, wenn der Parameter sal_True ist.
+|*
+|*************************************************************************/
+
+
+SwLayoutFrm *SwFrm::GetNextFtnLeaf( MakePageType eMakePage )
+{
+ SwFtnBossFrm *pOldBoss = FindFtnBossFrm();
+ SwPageFrm* pOldPage = pOldBoss->FindPageFrm();
+ SwPageFrm* pPage;
+ SwFtnBossFrm *pBoss = pOldBoss->IsColumnFrm() ?
+ (SwFtnBossFrm*)pOldBoss->GetNext() : 0; // naechste Spalte, wenn vorhanden
+ if( pBoss )
+ pPage = NULL;
+ else
+ {
+ if( pOldBoss->GetUpper()->IsSctFrm() )
+ { // Das kann nur in einem spaltigen Bereich sein
+ SwLayoutFrm* pNxt = pOldBoss->GetNextSctLeaf( eMakePage );
+ if( pNxt )
+ {
+ OSL_ENSURE( pNxt->IsColBodyFrm(), "GetNextFtnLeaf: Funny Leaf" );
+ pBoss = (SwFtnBossFrm*)pNxt->GetUpper();
+ pPage = pBoss->FindPageFrm();
+ }
+ else
+ return 0;
+ }
+ else
+ {
+ // naechste Seite
+ pPage = (SwPageFrm*)pOldPage->GetNext();
+ // Leerseiten ueberspringen
+ if( pPage && pPage->IsEmptyPage() )
+ pPage = (SwPageFrm*)pPage->GetNext();
+ pBoss = pPage;
+ }
+ }
+ // Was haben wir jetzt?
+ // pBoss != NULL, pPage==NULL => pBoss ist die auf der gleichen Seite folgende Spalte
+ // pBoss != NULL, pPage!=NULL => pBoss und pPage sind die folgende Seite (Empty uebersprungen)
+ // pBoss == NULL => pPage == NULL, es gibt keine folgende Seite
+
+ //Wenn die Fussnote bereits einen Follow hat brauchen wir nicht zu suchen.
+ //Wenn allerdings zwischen Ftn und Follow unerwuenschte Leerseiten/spalten
+ //herumlungern, so legen wir auf der naechstbesten Seite/Spalte einen weiteren
+ //Follow an, der Rest wird sich schon finden.
+ SwFtnFrm *pFtn = FindFtnFrm();
+ if ( pFtn && pFtn->GetFollow() )
+ {
+ SwFtnBossFrm* pTmpBoss = pFtn->GetFollow()->FindFtnBossFrm();
+ // Folgende Faelle werden hier erkannt und akzeptiert
+ // 1. Die FtnBosse sind benachbarte Seiten oder benachbarte Spalten
+ // 2. Der neue ist die erste Spalte der benachbarten Seite
+ // 3. Der neue ist die erste Spalte in einem Bereich in der naechsten Spalte/Seite
+ while( pTmpBoss != pBoss && pTmpBoss && !pTmpBoss->GetPrev() )
+ pTmpBoss = pTmpBoss->GetUpper()->FindFtnBossFrm();
+ if( pTmpBoss == pBoss )
+ return pFtn->GetFollow();
+ }
+
+ // Wenn wir keinen pBoss gefunden haben oder es sich um eine "falsche" Seite handelt,
+ // muss eine neue Seite her
+ if ( !pBoss || ( pPage && pPage->IsEndNotePage() && !pOldPage->IsEndNotePage() ) )
+ {
+ if ( eMakePage == MAKEPAGE_APPEND || eMakePage == MAKEPAGE_INSERT )
+ {
+ pBoss = InsertPage( pOldPage, pOldPage->IsFtnPage() );
+ ((SwPageFrm*)pBoss)->SetEndNotePage( pOldPage->IsEndNotePage() );
+ }
+ else
+ return 0;
+ }
+ if( pBoss->IsPageFrm() )
+ { // Wenn wir auf einer spaltigen Seite gelandet sind,
+ // gehen wir in die erste Spalte
+ SwLayoutFrm* pLay = pBoss->FindBodyCont();
+ if( pLay && pLay->Lower() && pLay->Lower()->IsColumnFrm() )
+ pBoss = (SwFtnBossFrm*)pLay->Lower();
+ }
+ //Seite/Spalte gefunden, da schummeln wir uns doch gleich mal 'rein
+ SwFtnContFrm *pCont = pBoss->FindFtnCont();
+ if ( !pCont && pBoss->GetMaxFtnHeight() &&
+ ( eMakePage == MAKEPAGE_APPEND || eMakePage == MAKEPAGE_INSERT ) )
+ pCont = pBoss->MakeFtnCont();
+ return pCont;
+}
+
+/*************************************************************************
+|*
+|* SwFrm::GetPrevFtnLeaf()
+|*
+|* Beschreibung Liefert das vorhergehende LayoutBlatt in das der
+|* Frame gemoved werden kann.
+|*
+|*************************************************************************/
+
+
+SwLayoutFrm *SwFrm::GetPrevFtnLeaf( MakePageType eMakeFtn )
+{
+ //Der Vorgaenger fuer eine Fussnote ist falls moeglich der Master
+ //in der Fussnoteneigenen Verkettung.
+ SwLayoutFrm *pRet = 0;
+ SwFtnFrm *pFtn = FindFtnFrm();
+ pRet = pFtn->GetMaster();
+
+ SwFtnBossFrm* pOldBoss = FindFtnBossFrm();
+ SwPageFrm *pOldPage = pOldBoss->FindPageFrm();
+
+ if ( !pOldBoss->GetPrev() && !pOldPage->GetPrev() )
+ return pRet; // es gibt weder eine Spalte noch eine Seite vor uns
+
+ if ( !pRet )
+ {
+ bool bEndn = pFtn->GetAttr()->GetFtn().IsEndNote();
+ SwFrm* pTmpRef = NULL;
+ if( bEndn && pFtn->IsInSct() )
+ {
+ SwSectionFrm* pSect = pFtn->FindSctFrm();
+ if( pSect->IsEndnAtEnd() )
+ pTmpRef = pSect->FindLastCntnt( FINDMODE_LASTCNT );
+ }
+ if( !pTmpRef )
+ pTmpRef = pFtn->GetRef();
+ SwFtnBossFrm* pStop = pTmpRef->FindFtnBossFrm( !bEndn );
+
+ const sal_uInt16 nNum = pStop->GetPhyPageNum();
+
+ //Wenn die Fussnoten am Dokumentende angezeigt werden, so verlassen wir
+ //die Entsprechenden Seiten nicht.
+ //Selbiges gilt analog fuer die Endnotenseiten.
+ const sal_Bool bEndNote = pOldPage->IsEndNotePage();
+ const sal_Bool bFtnEndDoc = pOldPage->IsFtnPage();
+ SwFtnBossFrm* pNxtBoss = pOldBoss;
+ SwSectionFrm *pSect = pNxtBoss->GetUpper()->IsSctFrm() ?
+ (SwSectionFrm*)pNxtBoss->GetUpper() : 0;
+
+ do
+ {
+ if( pNxtBoss->IsColumnFrm() && pNxtBoss->GetPrev() )
+ pNxtBoss = (SwFtnBossFrm*)pNxtBoss->GetPrev(); // eine Spalte zurueck
+ else // oder eine Seite zurueck
+ {
+ SwLayoutFrm* pBody = 0;
+ if( pSect )
+ {
+ if( pSect->IsFtnLock() )
+ {
+ if( pNxtBoss == pOldBoss )
+ return 0;
+ pStop = pNxtBoss;
+ }
+ else
+ {
+ pSect = (SwSectionFrm*)pSect->FindMaster();
+ if( !pSect || !pSect->Lower() )
+ return 0;
+ OSL_ENSURE( pSect->Lower()->IsColumnFrm(),
+ "GetPrevFtnLeaf: Where's the column?" );
+ pNxtBoss = (SwFtnBossFrm*)pSect->Lower();
+ pBody = pSect;
+ }
+ }
+ else
+ {
+ SwPageFrm* pPage = (SwPageFrm*)pNxtBoss->FindPageFrm()->GetPrev();
+ if( !pPage || pPage->GetPhyPageNum() < nNum ||
+ bEndNote != pPage->IsEndNotePage() || bFtnEndDoc != pPage->IsFtnPage() )
+ return NULL; // Keine in Frage kommende Seite mehr gefunden
+ pNxtBoss = pPage;
+ pBody = pPage->FindBodyCont();
+ }
+ // Die vorherige Seite haben wir nun, ggf. sollten wir in die letzte Spalte
+ // der Seite wechseln
+ if( pBody )
+ {
+ if ( pBody->Lower() && pBody->Lower()->IsColumnFrm() )
+ {
+ pNxtBoss = static_cast<SwFtnBossFrm*>(pBody->GetLastLower());
+ }
+ }
+ }
+ SwFtnContFrm *pCont = pNxtBoss->FindFtnCont();
+ if ( pCont )
+ {
+ pRet = pCont;
+ break;
+ }
+ if ( pStop == pNxtBoss )
+ { //Die Seite/Spalte auf der sich auch die Referenz tummelt, ist erreicht.
+ //Wir koennen jetzt probehalber mal einen Container erzeugen und
+ //uns hineinpasten.
+ if ( eMakeFtn == MAKEPAGE_FTN && pNxtBoss->GetMaxFtnHeight() )
+ pRet = pNxtBoss->MakeFtnCont();
+ break;
+ }
+ } while( !pRet );
+ }
+ if ( pRet )
+ {
+ const SwFtnBossFrm* pNewBoss = pRet->FindFtnBossFrm();
+ sal_Bool bJump = sal_False;
+ if( pOldBoss->IsColumnFrm() && pOldBoss->GetPrev() ) // es gibt eine vorherige Spalte
+ bJump = pOldBoss->GetPrev() != (SwFrm*)pNewBoss; // sind wir darin gelandet?
+ else if( pNewBoss->IsColumnFrm() && pNewBoss->GetNext() )
+ bJump = sal_True; // es gibt hinter dem neuen Boss noch eine Spalte, die aber nicht
+ // der alte Boss sein kann, das haben wir ja bereits geprueft.
+ else // hier landen wir nur, wenn neuer und alter Boss entweder Seiten oder letzte (neu)
+ { // bzw. erste (alt) Spalten einer Seite sind. In diesem Fall muss noch geprueft
+ // werden, ob Seiten ueberspringen wurden.
+ sal_uInt16 nDiff = pOldPage->GetPhyPageNum() - pRet->FindPageFrm()->GetPhyPageNum();
+ if ( nDiff > 2 ||
+ (nDiff > 1 && !((SwPageFrm*)pOldPage->GetPrev())->IsEmptyPage()) )
+ bJump = sal_True;
+ }
+ if( bJump )
+ SwFlowFrm::SetMoveBwdJump( sal_True );
+ }
+ return pRet;
+}
+
+/*************************************************************************
+|*
+|* SwFrm::IsFtnAllowed()
+|*
+|*************************************************************************/
+
+
+sal_Bool SwFrm::IsFtnAllowed() const
+{
+ if ( !IsInDocBody() )
+ return sal_False;
+
+ if ( IsInTab() )
+ {
+ //Keine Ftns in wiederholten Headlines.
+ const SwTabFrm *pTab = ((SwFrm*)this)->ImplFindTabFrm();
+ if ( pTab->IsFollow() )
+ return !pTab->IsInHeadline( *this );
+ }
+ return sal_True;
+}
+
+/*************************************************************************
+|*
+|* SwRootFrm::UpdateFtnNums()
+|*
+|*************************************************************************/
+
+
+void SwRootFrm::UpdateFtnNums()
+{
+ //Seitenweise Numerierung nur wenn es am Dokument so eingestellt ist.
+ if ( GetFmt()->GetDoc()->GetFtnInfo().eNum == FTNNUM_PAGE )
+ {
+ SwPageFrm *pPage = (SwPageFrm*)Lower();
+ while ( pPage && !pPage->IsFtnPage() )
+ {
+ pPage->UpdateFtnNum();
+ pPage = (SwPageFrm*)pPage->GetNext();
+ }
+ }
+}
+
+/*************************************************************************
+|*
+|* RemoveFtns() Entfernen aller Fussnoten (nicht etwa die Referenzen)
+|* und Entfernen aller Fussnotenseiten.
+|*
+|*************************************************************************/
+
+void lcl_RemoveFtns( SwFtnBossFrm* pBoss, sal_Bool bPageOnly, sal_Bool bEndNotes )
+{
+ do
+ {
+ SwFtnContFrm *pCont = pBoss->FindFtnCont();
+ if ( pCont )
+ {
+ SwFtnFrm *pFtn = (SwFtnFrm*)pCont->Lower();
+ OSL_ENSURE( pFtn, "FtnCont ohne Ftn." );
+ if ( bPageOnly )
+ while ( pFtn->GetMaster() )
+ pFtn = pFtn->GetMaster();
+ do
+ {
+ SwFtnFrm *pNxt = (SwFtnFrm*)pFtn->GetNext();
+ if ( !pFtn->GetAttr()->GetFtn().IsEndNote() ||
+ bEndNotes )
+ {
+ pFtn->GetRef()->Prepare( PREP_FTN, (void*)pFtn->GetAttr() );
+ if ( bPageOnly && !pNxt )
+ pNxt = pFtn->GetFollow();
+ pFtn->Cut();
+ delete pFtn;
+ }
+ pFtn = pNxt;
+
+ } while ( pFtn );
+ }
+ if( !pBoss->IsInSct() )
+ {
+ // A sectionframe with the Ftn/EndnAtEnd-flags may contain
+ // foot/endnotes. If the last lower frame of the bodyframe is
+ // a multicolumned sectionframe, it may contain footnotes, too.
+ SwLayoutFrm* pBody = pBoss->FindBodyCont();
+ if( pBody && pBody->Lower() )
+ {
+ SwFrm* pLow = pBody->Lower();
+ while( pLow->GetNext() )
+ {
+ if( pLow->IsSctFrm() && ( !pLow->GetNext() ||
+ ((SwSectionFrm*)pLow)->IsAnyNoteAtEnd() ) &&
+ ((SwSectionFrm*)pLow)->Lower() &&
+ ((SwSectionFrm*)pLow)->Lower()->IsColumnFrm() )
+ lcl_RemoveFtns( (SwColumnFrm*)((SwSectionFrm*)pLow)->Lower(),
+ bPageOnly, bEndNotes );
+ pLow = pLow->GetNext();
+ }
+ }
+ }
+ // noch 'ne Spalte?
+ pBoss = pBoss->IsColumnFrm() ? (SwColumnFrm*)pBoss->GetNext() : NULL;
+ } while( pBoss );
+}
+
+void SwRootFrm::RemoveFtns( SwPageFrm *pPage, sal_Bool bPageOnly, sal_Bool bEndNotes )
+{
+ if ( !pPage )
+ pPage = (SwPageFrm*)Lower();
+
+ do
+ { // Bei spaltigen Seiten muessen wir in allen Spalten aufraeumen
+ SwFtnBossFrm* pBoss;
+ SwLayoutFrm* pBody = pPage->FindBodyCont();
+ if( pBody && pBody->Lower() && pBody->Lower()->IsColumnFrm() )
+ pBoss = (SwFtnBossFrm*)pBody->Lower(); // die erste Spalte
+ else
+ pBoss = pPage; // keine Spalten
+ lcl_RemoveFtns( pBoss, bPageOnly, bEndNotes );
+ if ( !bPageOnly )
+ {
+ if ( pPage->IsFtnPage() &&
+ (!pPage->IsEndNotePage() || bEndNotes) )
+ {
+ SwFrm *pDel = pPage;
+ pPage = (SwPageFrm*)pPage->GetNext();
+ pDel->Cut();
+ delete pDel;
+ }
+ else
+ pPage = (SwPageFrm*)pPage->GetNext();
+ }
+ else
+ break;
+
+ } while ( pPage );
+}
+
+/*************************************************************************
+|*
+|* SetFtnPageDescs() Seitenvorlagen der Fussnotenseiten aendern
+|*
+|*************************************************************************/
+
+void SwRootFrm::CheckFtnPageDescs( sal_Bool bEndNote )
+{
+ SwPageFrm *pPage = (SwPageFrm*)Lower();
+ while ( pPage && !pPage->IsFtnPage() )
+ pPage = (SwPageFrm*)pPage->GetNext();
+ while ( pPage && pPage->IsEndNotePage() != bEndNote )
+ pPage = (SwPageFrm*)pPage->GetNext();
+ if ( pPage )
+ SwFrm::CheckPageDescs( pPage, sal_False );
+}
+
+
+/*************************************************************************
+|*
+|* SwFtnBossFrm::MakeFtnCont()
+|*
+|*************************************************************************/
+
+
+SwFtnContFrm *SwFtnBossFrm::MakeFtnCont()
+{
+ //Einfuegen eines Fussnotencontainers. Der Fussnotencontainer sitzt
+ //immer direkt hinter dem Bodytext.
+ //Sein FrmFmt ist immer das DefaultFrmFmt.
+
+#if OSL_DEBUG_LEVEL > 1
+ if ( FindFtnCont() )
+ { OSL_ENSURE( !this, "Fussnotencontainer bereits vorhanden." );
+ return 0;
+ }
+#endif
+
+ SwFtnContFrm *pNew = new SwFtnContFrm( GetFmt()->GetDoc()->GetDfltFrmFmt(), this );
+ SwLayoutFrm *pLay = FindBodyCont();
+ pNew->Paste( this, pLay->GetNext() );
+ return pNew;
+}
+
+/*************************************************************************
+|*
+|* SwFtnBossFrm::FindFtnCont()
+|*
+|*************************************************************************/
+
+
+SwFtnContFrm *SwFtnBossFrm::FindFtnCont()
+{
+ SwFrm *pFrm = Lower();
+ while( pFrm && !pFrm->IsFtnContFrm() )
+ pFrm = pFrm->GetNext();
+
+#if OSL_DEBUG_LEVEL > 1
+ if ( pFrm )
+ {
+ SwFrm *pFtn = pFrm->GetLower();
+ OSL_ENSURE( pFtn, "Cont ohne Fussnote." );
+ while ( pFtn )
+ {
+ OSL_ENSURE( pFtn->IsFtnFrm(), "Nachbar von Fussnote keine Fussnote." );
+ pFtn = pFtn->GetNext();
+ }
+ }
+#endif
+
+ return (SwFtnContFrm*)pFrm;
+}
+
+/*************************************************************************
+|*
+|* SwFtnBossFrm::FindNearestFtnCont() Sucht den naechst greifbaren Fussnotencontainer.
+|*
+|*************************************************************************/
+
+SwFtnContFrm *SwFtnBossFrm::FindNearestFtnCont( sal_Bool bDontLeave )
+{
+ SwFtnContFrm *pCont = 0;
+ if ( GetFmt()->GetDoc()->GetFtnIdxs().Count() )
+ {
+ pCont = FindFtnCont();
+ if ( !pCont )
+ {
+ SwPageFrm *pPage = FindPageFrm();
+ SwFtnBossFrm* pBoss = this;
+ sal_Bool bEndNote = pPage->IsEndNotePage();
+ do
+ {
+ sal_Bool bChgPage = lcl_NextFtnBoss( pBoss, pPage, bDontLeave );
+ // Haben wir noch einen Boss gefunden? Bei einem Seitenwechsel muss
+ // zudem noch das EndNotenFlag uebereinstimmen
+ if( pBoss && ( !bChgPage || pPage->IsEndNotePage() == bEndNote ) )
+ pCont = pBoss->FindFtnCont();
+ } while ( !pCont && pPage );
+ }
+ }
+ return pCont;
+}
+
+
+/*************************************************************************
+|*
+|* SwFtnBossFrm::FindFirstFtn()
+|*
+|* Beschreibung Erste Fussnote des Fussnotenbosses suchen.
+|*
+|*************************************************************************/
+
+
+SwFtnFrm *SwFtnBossFrm::FindFirstFtn()
+{
+ //Erstmal den naechsten FussnotenContainer suchen.
+ SwFtnContFrm *pCont = FindNearestFtnCont();
+ if ( !pCont )
+ return 0;
+
+ //Ab der ersten Fussnote im Container die erste suchen, die
+ //von der aktuellen Spalte (bzw. einspaltigen Seite) referenziert wird.
+
+ SwFtnFrm *pRet = (SwFtnFrm*)pCont->Lower();
+ const sal_uInt16 nRefNum = FindPageFrm()->GetPhyPageNum();
+ const sal_uInt16 nRefCol = lcl_ColumnNum( this );
+ sal_uInt16 nPgNum, nColNum; //Seitennummer, Spaltennummer
+ SwFtnBossFrm* pBoss;
+ SwPageFrm* pPage;
+ if( pRet )
+ {
+ pBoss = pRet->GetRef()->FindFtnBossFrm();
+ OSL_ENSURE( pBoss, "FindFirstFtn: No boss found" );
+ if( !pBoss )
+ return sal_False; // ?There must be a bug, but no GPF
+ pPage = pBoss->FindPageFrm();
+ nPgNum = pPage->GetPhyPageNum();
+ if ( nPgNum == nRefNum )
+ {
+ nColNum = lcl_ColumnNum( pBoss );
+ if( nColNum == nRefCol )
+ return pRet; //hat ihn.
+ else if( nColNum > nRefCol )
+ return NULL; //mind. eine Spalte zu weit.
+ }
+ else if ( nPgNum > nRefNum )
+ return NULL; //mind. eine Seite zu weit.
+ }
+ else
+ return NULL;
+ // Ende, wenn Ref auf einer spaeteren Seite oder auf der gleichen Seite in einer
+ // spaeteren Spalte liegt
+
+ do
+ {
+ while ( pRet->GetFollow() )
+ pRet = pRet->GetFollow();
+
+ SwFtnFrm *pNxt = (SwFtnFrm*)pRet->GetNext();
+ if ( !pNxt )
+ {
+ pBoss = pRet->FindFtnBossFrm();
+ pPage = pBoss->FindPageFrm();
+ lcl_NextFtnBoss( pBoss, pPage, sal_False ); // naechster FtnBoss
+ pCont = pBoss ? pBoss->FindNearestFtnCont() : 0;
+ if ( pCont )
+ pNxt = (SwFtnFrm*)pCont->Lower();
+ }
+ if ( pNxt )
+ {
+ pRet = pNxt;
+ pBoss = pRet->GetRef()->FindFtnBossFrm();
+ pPage = pBoss->FindPageFrm();
+ nPgNum = pPage->GetPhyPageNum();
+ if ( nPgNum == nRefNum )
+ {
+ nColNum = lcl_ColumnNum( pBoss );
+ if( nColNum == nRefCol )
+ break; //hat ihn.
+ else if( nColNum > nRefCol )
+ pRet = 0; //mind. eine Spalte zu weit.
+ }
+ else if ( nPgNum > nRefNum )
+ pRet = 0; //mind. eine Seite zu weit.
+ }
+ else
+ pRet = 0; //Gibt eben keinen.
+ } while( pRet );
+ return pRet;
+}
+
+/*************************************************************************
+|*
+|* SwFtnBossFrm::FindFirstFtn()
+|*
+|* Beschreibunt Erste Fussnote zum Cnt suchen.
+|*
+|*************************************************************************/
+
+
+const SwFtnFrm *SwFtnBossFrm::FindFirstFtn( SwCntntFrm *pCnt ) const
+{
+ const SwFtnFrm *pRet = ((SwFtnBossFrm*)this)->FindFirstFtn();
+ if ( pRet )
+ {
+ const sal_uInt16 nColNum = lcl_ColumnNum( this ); //Spaltennummer
+ const sal_uInt16 nPageNum = GetPhyPageNum();
+ while ( pRet && (pRet->GetRef() != pCnt) )
+ {
+ while ( pRet->GetFollow() )
+ pRet = pRet->GetFollow();
+
+ if ( pRet->GetNext() )
+ pRet = (const SwFtnFrm*)pRet->GetNext();
+ else
+ { SwFtnBossFrm *pBoss = (SwFtnBossFrm*)pRet->FindFtnBossFrm();
+ SwPageFrm *pPage = pBoss->FindPageFrm();
+ lcl_NextFtnBoss( pBoss, pPage, sal_False ); // naechster FtnBoss
+ SwFtnContFrm *pCont = pBoss ? pBoss->FindNearestFtnCont() : 0;
+ pRet = pCont ? (SwFtnFrm*)pCont->Lower() : 0;
+ }
+ if ( pRet )
+ {
+ const SwFtnBossFrm* pBoss = pRet->GetRef()->FindFtnBossFrm();
+ if( pBoss->GetPhyPageNum() != nPageNum ||
+ nColNum != lcl_ColumnNum( pBoss ) )
+ pRet = 0;
+ }
+ }
+ }
+ return pRet;
+}
+
+/*************************************************************************
+|*
+|* SwFtnBossFrm::ResetFtn()
+|*
+|*************************************************************************/
+
+
+void SwFtnBossFrm::ResetFtn( const SwFtnFrm *pCheck )
+{
+ //Vernichten der Inkarnationen von Fussnoten zum Attribut, wenn sie nicht
+ //zu pAssumed gehoeren.
+ OSL_ENSURE( !pCheck->GetMaster(), "Master not an Master." );
+
+ SwNodeIndex aIdx( *pCheck->GetAttr()->GetStartNode(), 1 );
+ SwCntntNode *pNd = aIdx.GetNode().GetCntntNode();
+ if ( !pNd )
+ pNd = pCheck->GetFmt()->GetDoc()->
+ GetNodes().GoNextSection( &aIdx, sal_True, sal_False );
+ SwIterator<SwFrm,SwCntntNode> aIter( *pNd );
+ SwFrm* pFrm = aIter.First();
+ while( pFrm )
+ {
+ if( pFrm->getRootFrm() == pCheck->getRootFrm() )
+ {
+ SwFrm *pTmp = pFrm->GetUpper();
+ while ( pTmp && !pTmp->IsFtnFrm() )
+ pTmp = pTmp->GetUpper();
+
+ SwFtnFrm *pFtn = (SwFtnFrm*)pTmp;
+ while ( pFtn && pFtn->GetMaster() )
+ pFtn = pFtn->GetMaster();
+ if ( pFtn != pCheck )
+ {
+ while ( pFtn )
+ {
+ SwFtnFrm *pNxt = pFtn->GetFollow();
+ pFtn->Cut();
+ delete pFtn;
+ pFtn = pNxt;
+ }
+ }
+ }
+
+ pFrm = aIter.Next();
+ }
+}
+
+/*************************************************************************
+|*
+|* SwFtnBossFrm::InsertFtn()
+|*
+|*************************************************************************/
+
+
+void SwFtnBossFrm::InsertFtn( SwFtnFrm* pNew )
+{
+ //Die Fussnote haben wir, sie muss jetzt nur noch irgendwo
+ //hin und zwar vor die Fussnote, deren Attribut vor das
+ //der neuen zeigt (Position wird ueber das Doc ermittelt)
+ //Gibt es in diesem Fussnotenboss noch keine Fussnoten, so muss eben ein
+ //Container erzeugt werden.
+ //Gibt es bereits einen Container aber noch keine Fussnote zu diesem
+ //Fussnotenboss, so muss die Fussnote hinter die letzte Fussnote der dichtesten
+ //Vorseite/spalte.
+
+ ResetFtn( pNew );
+ SwFtnFrm *pSibling = FindFirstFtn();
+ sal_Bool bDontLeave = sal_False;
+
+ // Ok, a sibling has been found, but is the sibling in an acceptable
+ // environment?
+ if( IsInSct() )
+ {
+ SwSectionFrm* pMySect = ImplFindSctFrm();
+ bool bEndnt = pNew->GetAttr()->GetFtn().IsEndNote();
+ if( bEndnt )
+ {
+ const SwSectionFmt* pEndFmt = pMySect->GetEndSectFmt();
+ bDontLeave = 0 != pEndFmt;
+ if( pSibling )
+ {
+ if( pEndFmt )
+ {
+ if( !pSibling->IsInSct() ||
+ !pSibling->ImplFindSctFrm()->IsDescendantFrom( pEndFmt ) )
+ pSibling = NULL;
+ }
+ else if( pSibling->IsInSct() )
+ pSibling = NULL;
+ }
+ }
+ else
+ {
+ bDontLeave = pMySect->IsFtnAtEnd();
+ if( pSibling )
+ {
+ if( pMySect->IsFtnAtEnd() )
+ {
+ if( !pSibling->IsInSct() ||
+ !pMySect->IsAnFollow( pSibling->ImplFindSctFrm() ) )
+ pSibling = NULL;
+ }
+ else if( pSibling->IsInSct() )
+ pSibling = NULL;
+ }
+ }
+ }
+
+ if( pSibling && pSibling->FindPageFrm()->IsEndNotePage() !=
+ FindPageFrm()->IsEndNotePage() )
+ pSibling = NULL;
+
+ //Damit die Position herausgefunden werden kann.
+ SwDoc *pDoc = GetFmt()->GetDoc();
+ const sal_uLong nStPos = ::lcl_FindFtnPos( pDoc, pNew->GetAttr() );
+
+ sal_uLong nCmpPos = 0;
+ sal_uLong nLastPos = 0;
+ SwFtnContFrm *pParent = 0;
+ if( pSibling )
+ {
+ nCmpPos = ::lcl_FindFtnPos( pDoc, pSibling->GetAttr() );
+ if( nCmpPos > nStPos )
+ pSibling = NULL;
+ }
+
+ if ( !pSibling )
+ { pParent = FindFtnCont();
+ if ( !pParent )
+ {
+ //Es gibt noch keinen FussnotenContainer, also machen wir einen.
+ //HAAAAAAAALT! So einfach ist das leider mal wieder nicht: Es kann
+ //sein, dass irgendeine naechste Fussnote existiert die vor der
+ //einzufuegenden zu stehen hat, weil z.B. eine Fussnote ueber zig
+ //Seiten aufgespalten ist usw.
+ pParent = FindNearestFtnCont( bDontLeave );
+ if ( pParent )
+ {
+ SwFtnFrm *pFtn = (SwFtnFrm*)pParent->Lower();
+ if ( pFtn )
+ {
+
+ nCmpPos = ::lcl_FindFtnPos( pDoc, pFtn->GetAttr() );
+ if ( nCmpPos > nStPos )
+ pParent = 0;
+ }
+ else
+ pParent = 0;
+ }
+ }
+ if ( !pParent )
+ //Jetzt kann aber ein Fussnotencontainer gebaut werden.
+ pParent = MakeFtnCont();
+ else
+ {
+ //Ausgehend von der ersten Fussnote unterhalb des Parents wird die
+ //erste Fussnote gesucht deren Index hinter dem Index der
+ //einzufuegenden liegt; vor dieser kann der neue dann gepastet
+ //werden.
+ pSibling = (SwFtnFrm*)pParent->Lower();
+ if ( !pSibling )
+ { OSL_ENSURE( !this, "Keinen Platz fuer Fussnote gefunden.");
+ return;
+ }
+ nCmpPos = ::lcl_FindFtnPos( pDoc, pSibling->GetAttr() );
+
+ SwFtnBossFrm *pNxtB = this; //Immer den letzten merken, damit wir nicht
+ SwFtnFrm *pLastSib = 0; //ueber das Ziel hinausschiessen.
+
+ while ( pSibling && nCmpPos <= nStPos )
+ {
+ pLastSib = pSibling; // der kommt schon mal in Frage
+ nLastPos = nCmpPos;
+
+ while ( pSibling->GetFollow() )
+ pSibling = pSibling->GetFollow();
+
+ if ( pSibling->GetNext() )
+ {
+ pSibling = (SwFtnFrm*)pSibling->GetNext();
+ OSL_ENSURE( !pSibling->GetMaster() || ( ENDNOTE > nStPos &&
+ pSibling->GetAttr()->GetFtn().IsEndNote() ),
+ "InsertFtn: Master expected I" );
+ }
+ else
+ {
+ pNxtB = pSibling->FindFtnBossFrm();
+ SwPageFrm *pSibPage = pNxtB->FindPageFrm();
+ sal_Bool bEndNote = pSibPage->IsEndNotePage();
+ sal_Bool bChgPage = lcl_NextFtnBoss( pNxtB, pSibPage, bDontLeave );
+ // Bei Seitenwechsel muss das EndNoteFlag ueberprueft werden.
+ SwFtnContFrm *pCont = pNxtB && ( !bChgPage ||
+ pSibPage->IsEndNotePage() == bEndNote )
+ ? pNxtB->FindNearestFtnCont( bDontLeave ) : 0;
+ if( pCont )
+ pSibling = (SwFtnFrm*)pCont->Lower();
+ else // kein weiterer FtnContainer, dann werden wir uns wohl hinter
+ break; // pSibling haengen
+ }
+ if ( pSibling )
+ {
+ nCmpPos = ::lcl_FindFtnPos( pDoc, pSibling->GetAttr() );
+ OSL_ENSURE( nCmpPos > nLastPos, "InsertFtn: Order of FtnFrm's buggy" );
+ }
+ }
+ // pLastSib ist jetzt die letzte Fussnote vor uns,
+ // pSibling leer oder die erste nach uns.
+ if ( pSibling && pLastSib && (pSibling != pLastSib) )
+ { //Sind wir vielleicht bereits ueber das Ziel hinausgeschossen?
+ if ( nCmpPos > nStPos )
+ pSibling = pLastSib;
+ }
+ else if ( !pSibling )
+ { //Eine Chance haben wir noch: wir nehmen einfach die letzte
+ //Fussnote im Parent. Ein Sonderfall, der z.B. beim
+ //zurueckfliessen von Absaetzen mit mehreren Fussnoten
+ //vorkommt.
+ //Damit wir nicht die Reihenfolge verwuerfeln muessen wir den
+ //Parent der letzten Fussnote, die wir an der Hand hatten benutzen.
+ pSibling = pLastSib;
+ while( pSibling->GetFollow() )
+ pSibling = pSibling->GetFollow();
+ OSL_ENSURE( !pSibling->GetNext(), "InsertFtn: Who's that guy?" );
+ }
+ }
+ }
+ else
+ { //Die erste Fussnote der Spalte/Seite haben wir an der Hand, jetzt ausgehend
+ //von dieser die erste zur selben Spalte/Seite suchen deren Index hinter
+ //den uebergebenen zeigt, die letzte, die wir an der Hand hatten, ist
+ //dann der Vorgaenger.
+ SwFtnBossFrm* pBoss = pNew->GetRef()->FindFtnBossFrm(
+ !pNew->GetAttr()->GetFtn().IsEndNote() );
+ sal_uInt16 nRefNum = pBoss->GetPhyPageNum(); // Die Seiten- und
+ sal_uInt16 nRefCol = lcl_ColumnNum( pBoss ); // Spaltennummer der neuen Fussnote
+ sal_Bool bEnd = sal_False;
+ SwFtnFrm *pLastSib = 0;
+ while ( pSibling && !bEnd && (nCmpPos <= nStPos) )
+ {
+ pLastSib = pSibling;
+ nLastPos = nCmpPos;
+
+ while ( pSibling->GetFollow() )
+ pSibling = pSibling->GetFollow();
+
+ SwFtnFrm *pFoll = (SwFtnFrm*)pSibling->GetNext();
+ if ( pFoll )
+ {
+ pBoss = pSibling->GetRef()->FindFtnBossFrm( !pSibling->
+ GetAttr()->GetFtn().IsEndNote() );
+ sal_uInt16 nTmpRef;
+ if( nStPos >= ENDNOTE ||
+ (nTmpRef = pBoss->GetPhyPageNum()) < nRefNum ||
+ ( nTmpRef == nRefNum && lcl_ColumnNum( pBoss ) <= nRefCol ))
+ pSibling = pFoll;
+ else
+ bEnd = sal_True;
+ }
+ else
+ {
+ SwFtnBossFrm* pNxtB = pSibling->FindFtnBossFrm();
+ SwPageFrm *pSibPage = pNxtB->FindPageFrm();
+ sal_Bool bEndNote = pSibPage->IsEndNotePage();
+ sal_Bool bChgPage = lcl_NextFtnBoss( pNxtB, pSibPage, bDontLeave );
+ // Bei Seitenwechsel muss das EndNoteFlag ueberprueft werden.
+ SwFtnContFrm *pCont = pNxtB && ( !bChgPage ||
+ pSibPage->IsEndNotePage() == bEndNote )
+ ? pNxtB->FindNearestFtnCont( bDontLeave ) : 0;
+ if ( pCont )
+ pSibling = (SwFtnFrm*)pCont->Lower();
+ else
+ bEnd = sal_True;
+ }
+ if ( !bEnd && pSibling )
+ nCmpPos = ::lcl_FindFtnPos( pDoc, pSibling->GetAttr() );
+ if ( pSibling && pLastSib && (pSibling != pLastSib) )
+ { //Sind wir vielleicht bereits ueber das Ziel hinausgeschossen?
+ if ( (nLastPos < nCmpPos) && (nCmpPos > nStPos) )
+ {
+ pSibling = pLastSib;
+ bEnd = sal_True;
+ }
+ }
+ }
+ }
+ if ( pSibling )
+ {
+ nCmpPos = ::lcl_FindFtnPos( pDoc, pSibling->GetAttr() );
+ if ( nCmpPos < nStPos )
+ {
+ while ( pSibling->GetFollow() )
+ pSibling = pSibling->GetFollow();
+ pParent = (SwFtnContFrm*)pSibling->GetUpper();
+ pSibling = (SwFtnFrm*)pSibling->GetNext();
+ }
+ else
+ {
+ if( pSibling->GetMaster() )
+ {
+ if( ENDNOTE > nCmpPos || nStPos >= ENDNOTE )
+ {
+ OSL_FAIL( "InsertFtn: Master expected II" );
+ do
+ pSibling = pSibling->GetMaster();
+ while ( pSibling->GetMaster() );
+ }
+ }
+ pParent = (SwFtnContFrm*)pSibling->GetUpper();
+ }
+ }
+ OSL_ENSURE( pParent, "paste in space?" );
+ pNew->Paste( pParent, pSibling );
+}
+
+/*************************************************************************
+|*
+|* SwFtnBossFrm::AppendFtn()
+|*
+|*************************************************************************/
+
+
+void SwFtnBossFrm::AppendFtn( SwCntntFrm *pRef, SwTxtFtn *pAttr )
+{
+ //Wenn es die Fussnote schon gibt tun wir nix.
+ if ( FindFtn( pRef, pAttr ) )
+ return;
+
+ //Wenn Fussnoten am Dokumentende eingestellt sind, so brauchen wir 'eh erst
+ //ab der entsprechenden Seite zu suchen.
+ //Wenn es noch keine gibt, muss eben eine erzeugt werden.
+ //Wenn es sich um eine Endnote handelt, muss eine Endnotenseite gesucht
+ //bzw. erzeugt werden.
+ SwDoc *pDoc = GetFmt()->GetDoc();
+ SwFtnBossFrm *pBoss = this;
+ SwPageFrm *pPage = FindPageFrm();
+ SwPageFrm *pMyPage = pPage;
+ sal_Bool bChgPage = sal_False;
+ sal_Bool bEnd = sal_False;
+ if ( pAttr->GetFtn().IsEndNote() )
+ {
+ bEnd = sal_True;
+ if( GetUpper()->IsSctFrm() &&
+ ((SwSectionFrm*)GetUpper())->IsEndnAtEnd() )
+ {
+ SwFrm* pLast =
+ ((SwSectionFrm*)GetUpper())->FindLastCntnt( FINDMODE_ENDNOTE );
+ if( pLast )
+ {
+ pBoss = pLast->FindFtnBossFrm();
+ pPage = pBoss->FindPageFrm();
+ }
+ }
+ else
+ {
+ while ( pPage->GetNext() && !pPage->IsEndNotePage() )
+ {
+ pPage = (SwPageFrm*)pPage->GetNext();
+ bChgPage = sal_True;
+ }
+ if ( !pPage->IsEndNotePage() )
+ {
+ SwPageDesc *pDesc = pDoc->GetEndNoteInfo().GetPageDesc( *pDoc );
+ pPage = ::InsertNewPage( *pDesc, pPage->GetUpper(),
+ !pPage->OnRightPage(), sal_False, sal_True, 0 );
+ pPage->SetEndNotePage( sal_True );
+ bChgPage = sal_True;
+ }
+ else
+ {
+ //Wir koennen wenigstens schon mal ungefaehr die richtige Seite
+ //suchen. Damit stellen wir sicher das wir auch bei hunderten
+ //Fussnoten noch in endlicher Zeit fertig werden.
+ SwPageFrm *pNxt = (SwPageFrm*)pPage->GetNext();
+ const sal_uLong nStPos = ::lcl_FindFtnPos( pDoc, pAttr );
+ while ( pNxt && pNxt->IsEndNotePage() )
+ {
+ SwFtnContFrm *pCont = pNxt->FindFtnCont();
+ if ( pCont && pCont->Lower() )
+ {
+ OSL_ENSURE( pCont->Lower()->IsFtnFrm(), "Keine Ftn im Container" );
+ if ( nStPos > ::lcl_FindFtnPos( pDoc,
+ ((SwFtnFrm*)pCont->Lower())->GetAttr()))
+ {
+ pPage = pNxt;
+ pNxt = (SwPageFrm*)pPage->GetNext();
+ continue;
+ }
+ }
+ break;
+ }
+ }
+ }
+ }
+ else if( FTNPOS_CHAPTER == pDoc->GetFtnInfo().ePos && ( !GetUpper()->
+ IsSctFrm() || !((SwSectionFrm*)GetUpper())->IsFtnAtEnd() ) )
+ {
+ while ( pPage->GetNext() && !pPage->IsFtnPage() &&
+ !((SwPageFrm*)pPage->GetNext())->IsEndNotePage() )
+ {
+ pPage = (SwPageFrm*)pPage->GetNext();
+ bChgPage = sal_True;
+ }
+
+ if ( !pPage->IsFtnPage() )
+ {
+ SwPageDesc *pDesc = pDoc->GetFtnInfo().GetPageDesc( *pDoc );
+ pPage = ::InsertNewPage( *pDesc, pPage->GetUpper(),
+ !pPage->OnRightPage(), sal_False, sal_True, pPage->GetNext() );
+ bChgPage = sal_True;
+ }
+ else
+ {
+ //Wir koennen wenigstens schon mal ungefaehr die richtige Seite
+ //suchen. Damit stellen wir sicher das wir auch bei hunderten
+ //Fussnoten noch in endlicher Zeit fertig werden.
+ SwPageFrm *pNxt = (SwPageFrm*)pPage->GetNext();
+ const sal_uLong nStPos = ::lcl_FindFtnPos( pDoc, pAttr );
+ while ( pNxt && pNxt->IsFtnPage() && !pNxt->IsEndNotePage() )
+ {
+ SwFtnContFrm *pCont = pNxt->FindFtnCont();
+ if ( pCont && pCont->Lower() )
+ {
+ OSL_ENSURE( pCont->Lower()->IsFtnFrm(), "Keine Ftn im Container" );
+ if ( nStPos > ::lcl_FindFtnPos( pDoc,
+ ((SwFtnFrm*)pCont->Lower())->GetAttr()))
+ {
+ pPage = pNxt;
+ pNxt = (SwPageFrm*)pPage->GetNext();
+ continue;
+ }
+ }
+ break;
+ }
+ }
+ }
+
+ //Erstmal eine Fussnote und die benoetigten CntntFrms anlegen.
+ if ( !pAttr->GetStartNode() )
+ { OSL_ENSURE( !this, "Kein Fussnoteninhalt." );
+ return;
+ }
+
+ // Wenn es auf der Seite/Spalte bereits einen FtnCont gibt,
+ // kann in einen spaltigen Bereich keiner erzeugt werden.
+ if( pBoss->IsInSct() && pBoss->IsColumnFrm() && !pPage->IsFtnPage() )
+ {
+ SwSectionFrm* pSct = pBoss->FindSctFrm();
+ if( bEnd ? !pSct->IsEndnAtEnd() : !pSct->IsFtnAtEnd() )
+ {
+ SwFtnContFrm* pFtnCont = pSct->FindFtnBossFrm(!bEnd)->FindFtnCont();
+ if( pFtnCont )
+ {
+ SwFtnFrm* pTmp = (SwFtnFrm*)pFtnCont->Lower();
+ if( bEnd )
+ while( pTmp && !pTmp->GetAttr()->GetFtn().IsEndNote() )
+ pTmp = (SwFtnFrm*)pTmp->GetNext();
+ if( pTmp && *pTmp < pAttr )
+ return;
+ }
+ }
+ }
+
+ SwFtnFrm *pNew = new SwFtnFrm( pDoc->GetDfltFrmFmt(), this, pRef, pAttr );
+ {
+ SwNodeIndex aIdx( *pAttr->GetStartNode(), 1 );
+ ::_InsertCnt( pNew, pDoc, aIdx.GetIndex() );
+ }
+ // Wenn die Seite gewechselt (oder gar neu angelegt) wurde,
+ // muessen wir uns dort in die erste Spalte setzen
+ if( bChgPage )
+ {
+ SwLayoutFrm* pBody = pPage->FindBodyCont();
+ OSL_ENSURE( pBody, "AppendFtn: NoPageBody?" );
+ if( pBody->Lower() && pBody->Lower()->IsColumnFrm() )
+ pBoss = (SwFtnBossFrm*)pBody->Lower();
+ else
+ pBoss = pPage; // bei nichtspaltigen Seiten auf die Seite selbst
+ }
+ pBoss->InsertFtn( pNew );
+ if ( pNew->GetUpper() ) //Eingesetzt oder nicht?
+ {
+ ::RegistFlys( pNew->FindPageFrm(), pNew );
+ SwSectionFrm* pSect = FindSctFrm();
+ // Der Inhalt des FtnContainers in einem (spaltigen) Bereich
+ // braucht nur kalkuliert zu werden,
+ // wenn der Bereich bereits bis zur Unterkante seines Uppers geht.
+ if( pSect && !pSect->IsJoinLocked() && ( bEnd ? !pSect->IsEndnAtEnd() :
+ !pSect->IsFtnAtEnd() ) && pSect->Growable() )
+ pSect->InvalidateSize();
+ else
+ {
+ // --> OD 2005-05-18 #i49383# - disable unlock of position of
+ // lower objects during format of footnote content.
+ const bool bOldFtnFrmLocked( pNew->IsColLocked() );
+ pNew->ColLock();
+ pNew->KeepLockPosOfLowerObjs();
+ // --> OD 2006-02-02 #i57914# - adjust fix #i49383#
+ // no extra notify for footnote frame
+// SwLayNotify* pFtnFrmNotitfy = new SwLayNotify( pNew );
+ // <--
+ SwCntntFrm *pCnt = pNew->ContainsCntnt();
+ while ( pCnt && pCnt->FindFtnFrm()->GetAttr() == pAttr )
+ {
+ pCnt->Calc();
+ // --> OD 2005-05-17 #i49383# - format anchored objects
+ if ( pCnt->IsTxtFrm() && pCnt->IsValid() )
+ {
+ if ( !SwObjectFormatter::FormatObjsAtFrm( *pCnt,
+ *(pCnt->FindPageFrm()) ) )
+ {
+ // restart format with first content
+ pCnt = pNew->ContainsCntnt();
+ continue;
+ }
+ }
+ // <--
+ pCnt = (SwCntntFrm*)pCnt->FindNextCnt();
+ }
+ // --> OD 2005-05-18 #i49383#
+ if ( !bOldFtnFrmLocked )
+ {
+ pNew->ColUnlock();
+ }
+ // --> OD 2006-02-02 #i57914# - adjust fix #i49383#
+ // enable lock of lower object position before format of footnote frame.
+ pNew->UnlockPosOfLowerObjs();
+ // <--
+ pNew->Calc();
+ // --> OD 2006-02-02 #i57914# - adjust fix #i49383#
+ // no extra notify for footnote frame
+// pNew->UnlockPosOfLowerObjs();
+// delete pFtnFrmNotitfy;
+ // <--
+ if ( !bOldFtnFrmLocked && !pNew->GetLower() &&
+ !pNew->IsColLocked() && !pNew->IsBackMoveLocked() )
+ {
+ pNew->Cut();
+ delete pNew;
+ }
+ // <--
+ }
+ pMyPage->UpdateFtnNum();
+ }
+ else
+ delete pNew;
+}
+/*************************************************************************
+|*
+|* SwFtnBossFrm::FindFtn()
+|*
+|*************************************************************************/
+
+
+SwFtnFrm *SwFtnBossFrm::FindFtn( const SwCntntFrm *pRef, const SwTxtFtn *pAttr )
+{
+ //Der einfachste und sicherste Weg geht ueber das Attribut.
+ OSL_ENSURE( pAttr->GetStartNode(), "FtnAtr ohne StartNode." );
+ SwNodeIndex aIdx( *pAttr->GetStartNode(), 1 );
+ SwCntntNode *pNd = aIdx.GetNode().GetCntntNode();
+ if ( !pNd )
+ pNd = pRef->GetAttrSet()->GetDoc()->
+ GetNodes().GoNextSection( &aIdx, sal_True, sal_False );
+ if ( !pNd )
+ return 0;
+ SwIterator<SwFrm,SwCntntNode> aIter( *pNd );
+ SwFrm* pFrm = aIter.First();
+ if( pFrm )
+ do
+ {
+ pFrm = pFrm->GetUpper();
+ // #i28500#, #i27243# Due to the endnode collector, there are
+ // SwFtnFrms, which are not in the layout. Therefore the
+ // bInfFtn flags are not set correctly, and a cell of FindFtnFrm
+ // would return 0. Therefore we better call ImplFindFtnFrm().
+ SwFtnFrm *pFtn = pFrm->ImplFindFtnFrm();
+ if ( pFtn && pFtn->GetRef() == pRef )
+ {
+ // The following condition becomes true, if the whole
+ // footnotecontent is a section. While no frames exist,
+ // the HiddenFlag of the section is set, this causes
+ // the GoNextSection-function leaves the footnote.
+ if( pFtn->GetAttr() != pAttr )
+ return 0;
+ while ( pFtn && pFtn->GetMaster() )
+ pFtn = pFtn->GetMaster();
+ return pFtn;
+ }
+
+ } while ( 0 != (pFrm = aIter.Next()) );
+
+ return 0;
+}
+/*************************************************************************
+|*
+|* SwFtnBossFrm::RemoveFtn()
+|*
+|*************************************************************************/
+
+
+void SwFtnBossFrm::RemoveFtn( const SwCntntFrm *pRef, const SwTxtFtn *pAttr,
+ sal_Bool bPrep )
+{
+ SwFtnFrm *pFtn = FindFtn( pRef, pAttr );
+ if( pFtn )
+ {
+ do
+ {
+ SwFtnFrm *pFoll = pFtn->GetFollow();
+ pFtn->Cut();
+ delete pFtn;
+ pFtn = pFoll;
+ } while ( pFtn );
+ if( bPrep && pRef->IsFollow() )
+ {
+ OSL_ENSURE( pRef->IsTxtFrm(), "NoTxtFrm has Footnote?" );
+ SwTxtFrm* pMaster = (SwTxtFrm*)pRef->FindMaster();
+ if( !pMaster->IsLocked() )
+ pMaster->Prepare( PREP_FTN_GONE );
+ }
+ }
+ FindPageFrm()->UpdateFtnNum();
+}
+
+/*************************************************************************
+|*
+|* SwFtnBossFrm::ChangeFtnRef()
+|*
+|*************************************************************************/
+
+
+void SwFtnBossFrm::ChangeFtnRef( const SwCntntFrm *pOld, const SwTxtFtn *pAttr,
+ SwCntntFrm *pNew )
+{
+ SwFtnFrm *pFtn = FindFtn( pOld, pAttr );
+ while ( pFtn )
+ {
+ pFtn->SetRef( pNew );
+ pFtn = pFtn->GetFollow();
+ }
+}
+
+/*************************************************************************
+|*
+|* SwFtnBossFrm::CollectFtns()
+|*
+|*************************************************************************/
+
+
+/// OD 03.04.2003 #108446# - add parameter <_bCollectOnlyPreviousFtns> in
+/// order to control, if only footnotes, which are positioned before the
+/// footnote boss frame <this> have to be collected.
+void SwFtnBossFrm::CollectFtns( const SwCntntFrm* _pRef,
+ SwFtnBossFrm* _pOld,
+ SvPtrarr& _rFtnArr,
+ const sal_Bool _bCollectOnlyPreviousFtns )
+{
+ SwFtnFrm *pFtn = _pOld->FindFirstFtn();
+ while( !pFtn )
+ {
+ if( _pOld->IsColumnFrm() )
+ { // Spalten abklappern
+ while ( !pFtn && _pOld->GetPrev() )
+ {
+ //Wenn wir keine Fussnote gefunden haben, ist noch nicht alles zu
+ //spaet. Die Schleife wird beim Aufnehmen von Follow-Zeilen durch
+ //Tabellen benoetigt. Fuer alle anderen Faelle ist sie in der Lage
+ //'krumme' Verhaeltnisse zu korrigieren.
+ _pOld = (SwFtnBossFrm*)_pOld->GetPrev();
+ pFtn = _pOld->FindFirstFtn();
+ }
+ }
+ if( !pFtn )
+ {
+ // vorherige Seite
+ SwPageFrm* pPg;
+ for ( SwFrm* pTmp = _pOld;
+ 0 != ( pPg = (SwPageFrm*)pTmp->FindPageFrm()->GetPrev())
+ && pPg->IsEmptyPage() ;
+ )
+ {
+ pTmp = pPg;
+ }
+ if( !pPg )
+ return;
+
+ SwLayoutFrm* pBody = pPg->FindBodyCont();
+ if( pBody->Lower() && pBody->Lower()->IsColumnFrm() )
+ {
+ // mehrspaltige Seite => letzte Spalte suchen
+ _pOld = static_cast<SwFtnBossFrm*>(pBody->GetLastLower());
+ }
+ else
+ _pOld = pPg; // einspaltige Seite
+ pFtn = _pOld->FindFirstFtn();
+ }
+ }
+ // OD 03.04.2003 #108446# - consider new parameter <_bCollectOnlyPreviousFtns>
+ SwFtnBossFrm* pRefBossFrm = NULL;
+ if ( _bCollectOnlyPreviousFtns )
+ {
+ pRefBossFrm = this;
+ }
+ _CollectFtns( _pRef, pFtn, _rFtnArr, _bCollectOnlyPreviousFtns, pRefBossFrm );
+}
+
+
+/*************************************************************************
+|*
+|* SwFtnBossFrm::_CollectFtns()
+|*
+|*************************************************************************/
+inline void FtnInArr( SvPtrarr& rFtnArr, SwFtnFrm* pFtn )
+{
+ if ( USHRT_MAX == rFtnArr.GetPos( (VoidPtr)pFtn ) )
+ rFtnArr.Insert( (VoidPtr)pFtn, rFtnArr.Count() );
+}
+
+/// OD 03.04.2003 #108446# - add parameters <_bCollectOnlyPreviousFtns> and
+/// <_pRefFtnBossFrm> in order to control, if only footnotes, which are positioned
+/// before the given reference footnote boss frame have to be collected.
+/// Note: if parameter <_bCollectOnlyPreviousFtns> is true, then parameter
+/// <_pRefFtnBossFrm> have to be referenced to an object.
+/// Adjust parameter names.
+void SwFtnBossFrm::_CollectFtns( const SwCntntFrm* _pRef,
+ SwFtnFrm* _pFtn,
+ SvPtrarr& _rFtnArr,
+ sal_Bool _bCollectOnlyPreviousFtns,
+ const SwFtnBossFrm* _pRefFtnBossFrm)
+{
+ // OD 03.04.2003 #108446# - assert, that no reference footnote boss frame
+ // is set, in spite of the order, that only previous footnotes has to be
+ // collected.
+ OSL_ENSURE( !_bCollectOnlyPreviousFtns || _pRefFtnBossFrm,
+ "<SwFtnBossFrm::_CollectFtns(..)> - No reference footnote boss frame for collecting only previous footnotes set.\nCrash will be caused!" );
+
+ //Alle Fussnoten die von pRef referenziert werden nacheinander
+ //einsammeln (Attribut fuer Attribut), zusammengefuegen
+ //(der Inhalt zu einem Attribut kann ueber mehrere Seiten verteilt sein)
+ //und ausschneiden.
+
+ SvPtrarr aNotFtnArr( 20, 20 ); //Zur Robustheit werden hier die nicht
+ //dazugehoerigen Fussnoten eingetragen.
+ //Wenn eine Fussnote zweimal angefasst wird
+ //ists vorbei! So kommt die Funktion auch
+ //noch mit einem kaputten Layout
+ //einigermassen (ohne Schleife und Absturz)
+ //"klar".
+
+ //Hier sollte keiner mit einer Follow-Ftn ankommen, es sei denn er hat
+ //ernste Absichten (:-)); spricht er kommt mit einer Ftn an die vor der
+ //ersten der Referenz liegt.
+ OSL_ENSURE( !_pFtn->GetMaster() || _pFtn->GetRef() != _pRef, "FollowFtn moven?" );
+ while ( _pFtn->GetMaster() )
+ _pFtn = _pFtn->GetMaster();
+
+ sal_Bool bFound = sal_False;
+
+ while ( _pFtn )
+ {
+ //Erstmal die naechste Fussnote der Spalte/Seite suchen, damit wir nicht
+ //nach dem Cut jeder Fussnote von vorn anfangen muessen.
+ SwFtnFrm *pNxtFtn = _pFtn;
+ while ( pNxtFtn->GetFollow() )
+ pNxtFtn = pNxtFtn->GetFollow();
+ pNxtFtn = (SwFtnFrm*)pNxtFtn->GetNext();
+
+ if ( !pNxtFtn )
+ {
+ SwFtnBossFrm* pBoss = _pFtn->FindFtnBossFrm();
+ SwPageFrm* pPage = pBoss->FindPageFrm();
+ do
+ {
+ lcl_NextFtnBoss( pBoss, pPage, sal_False );
+ if( pBoss )
+ {
+ SwLayoutFrm* pCont = pBoss->FindFtnCont();
+ if( pCont )
+ {
+ pNxtFtn = (SwFtnFrm*)pCont->Lower();
+ if( pNxtFtn )
+ {
+ while( pNxtFtn->GetMaster() )
+ pNxtFtn = pNxtFtn->GetMaster();
+ if( pNxtFtn == _pFtn )
+ pNxtFtn = NULL;
+ }
+ }
+ }
+ } while( !pNxtFtn && pBoss );
+ }
+ else if( !pNxtFtn->GetAttr()->GetFtn().IsEndNote() )
+ { OSL_ENSURE( !pNxtFtn->GetMaster(), "_CollectFtn: Master exspected" );
+ while ( pNxtFtn->GetMaster() )
+ pNxtFtn = pNxtFtn->GetMaster();
+ }
+ if ( pNxtFtn == _pFtn )
+ {
+ OSL_FAIL( "_CollectFtn: Devil's circle" );
+ pNxtFtn = 0;
+ }
+
+ // OD 03.04.2003 #108446# - determine, if found footnote has to be collected.
+ sal_Bool bCollectFoundFtn = sal_False;
+ if ( _pFtn->GetRef() == _pRef && !_pFtn->GetAttr()->GetFtn().IsEndNote() )
+ {
+ if ( _bCollectOnlyPreviousFtns )
+ {
+ SwFtnBossFrm* pBossOfFoundFtn = _pFtn->FindFtnBossFrm( sal_True );
+ OSL_ENSURE( pBossOfFoundFtn,
+ "<SwFtnBossFrm::_CollectFtns(..)> - footnote boss frame of found footnote frame missing.\nWrong layout!" );
+ if ( !pBossOfFoundFtn || // don't crash, if no footnote boss is found.
+ pBossOfFoundFtn->IsBefore( _pRefFtnBossFrm )
+ )
+ {
+ bCollectFoundFtn = sal_True;
+ }
+ }
+ else
+ {
+ bCollectFoundFtn = sal_True;
+ }
+ }
+
+ if ( bCollectFoundFtn )
+ {
+ OSL_ENSURE( !_pFtn->GetMaster(), "FollowFtn moven?" );
+ SwFtnFrm *pNxt = _pFtn->GetFollow();
+ while ( pNxt )
+ {
+ SwFrm *pCnt = pNxt->ContainsAny();
+ if ( pCnt )
+ { //Unterwegs wird der Follow zerstoert weil er leer wird!
+ do
+ { SwFrm *pNxtCnt = pCnt->GetNext();
+ pCnt->Cut();
+ pCnt->Paste( _pFtn );
+ pCnt = pNxtCnt;
+ } while ( pCnt );
+ }
+ else
+ { OSL_ENSURE( !pNxt, "Fussnote ohne Inhalt?" );
+ pNxt->Cut();
+ delete pNxt;
+ }
+ pNxt = _pFtn->GetFollow();
+ }
+ _pFtn->Cut();
+ FtnInArr( _rFtnArr, _pFtn );
+ bFound = sal_True;
+ }
+ else
+ {
+ FtnInArr( aNotFtnArr, _pFtn );
+ if( bFound )
+ break;
+ }
+ if ( pNxtFtn &&
+ USHRT_MAX == _rFtnArr.GetPos( (VoidPtr)pNxtFtn ) &&
+ USHRT_MAX == aNotFtnArr.GetPos( (VoidPtr)pNxtFtn ) )
+ _pFtn = pNxtFtn;
+ else
+ break;
+ }
+}
+
+/*************************************************************************
+|*
+|* SwFtnBossFrm::_MoveFtns()
+|*
+|*************************************************************************/
+
+
+void SwFtnBossFrm::_MoveFtns( SvPtrarr &rFtnArr, sal_Bool bCalc )
+{
+ //Alle Fussnoten die von pRef referenziert werden muessen von der
+ //aktuellen Position, die sich durch die alte Spalte/Seite ergab, auf eine
+ //neue Position, bestimmt durch die neue Spalte/Seite, gemoved werden.
+ const sal_uInt16 nMyNum = FindPageFrm()->GetPhyPageNum();
+ const sal_uInt16 nMyCol = lcl_ColumnNum( this );
+ SWRECTFN( this )
+
+ // --> OD 2004-06-11 #i21478# - keep last inserted footnote in order to
+ // format the content of the following one.
+ SwFtnFrm* pLastInsertedFtn = 0L;
+ for ( sal_uInt16 i = 0; i < rFtnArr.Count(); ++i )
+ {
+ SwFtnFrm *pFtn = (SwFtnFrm*)rFtnArr[i];
+
+ SwFtnBossFrm* pRefBoss = pFtn->GetRef()->FindFtnBossFrm( sal_True );
+ if( pRefBoss != this )
+ {
+ const sal_uInt16 nRefNum = pRefBoss->FindPageFrm()->GetPhyPageNum();
+ const sal_uInt16 nRefCol = lcl_ColumnNum( this );
+ if( nRefNum < nMyNum || ( nRefNum == nMyNum && nRefCol <= nMyCol ) )
+ pRefBoss = this;
+ }
+ pRefBoss->InsertFtn( pFtn );
+
+ if ( pFtn->GetUpper() ) //Robust, z.B. bei doppelten
+ {
+ // Damit FtnFrms, die nicht auf die Seite passen, nicht fuer zuviel
+ // Unruhe sorgen (Loop 66312), wird ihr Inhalt zunaechst zusammengestaucht.
+ // Damit wird der FtnCont erst gegrowt, wenn der Inhalt formatiert wird
+ // und feststellt, dass er auf die Seite passt.
+ SwFrm *pCnt = pFtn->ContainsAny();
+ while( pCnt )
+ {
+ if( pCnt->IsLayoutFrm() )
+ {
+ SwFrm* pTmp = ((SwLayoutFrm*)pCnt)->ContainsAny();
+ while( pTmp && ((SwLayoutFrm*)pCnt)->IsAnLower( pTmp ) )
+ {
+ pTmp->Prepare( PREP_MOVEFTN );
+ (pTmp->Frm().*fnRect->fnSetHeight)(0);
+ (pTmp->Prt().*fnRect->fnSetHeight)(0);
+ pTmp = pTmp->FindNext();
+ }
+ }
+ else
+ pCnt->Prepare( PREP_MOVEFTN );
+ (pCnt->Frm().*fnRect->fnSetHeight)(0);
+ (pCnt->Prt().*fnRect->fnSetHeight)(0);
+ pCnt = pCnt->GetNext();
+ }
+ (pFtn->Frm().*fnRect->fnSetHeight)(0);
+ (pFtn->Prt().*fnRect->fnSetHeight)(0);
+ pFtn->Calc();
+ pFtn->GetUpper()->Calc();
+
+ if( bCalc )
+ {
+ SwTxtFtn *pAttr = pFtn->GetAttr();
+ pCnt = pFtn->ContainsAny();
+ sal_Bool bUnlock = !pFtn->IsBackMoveLocked();
+ pFtn->LockBackMove();
+
+ // --> OD 2005-05-18 #i49383# - disable unlock of position of
+ // lower objects during format of footnote content.
+ pFtn->KeepLockPosOfLowerObjs();
+ // --> OD 2006-02-02 #i57914# - adjust fix #i49383#
+ // no extra notify for footnote frame
+// SwLayNotify aFtnFrmNotitfy( pFtn );
+ // <--
+
+ while ( pCnt && pCnt->FindFtnFrm()->GetAttr() == pAttr )
+ {
+ pCnt->_InvalidatePos();
+ pCnt->Calc();
+ // --> OD 2005-05-17 #i49383# - format anchored objects
+ if ( pCnt->IsTxtFrm() && pCnt->IsValid() )
+ {
+ if ( !SwObjectFormatter::FormatObjsAtFrm( *pCnt,
+ *(pCnt->FindPageFrm()) ) )
+ {
+ // restart format with first content
+ pCnt = pFtn->ContainsAny();
+ continue;
+ }
+ }
+ // <--
+ if( pCnt->IsSctFrm() )
+ { // Wenn es sich um einen nichtleeren Bereich handelt,
+ // iterieren wir auch ueber seinen Inhalt
+ SwFrm* pTmp = ((SwSectionFrm*)pCnt)->ContainsAny();
+ if( pTmp )
+ pCnt = pTmp;
+ else
+ pCnt = pCnt->FindNext();
+ }
+ else
+ pCnt = pCnt->FindNext();
+ }
+ if( bUnlock )
+ {
+ pFtn->UnlockBackMove();
+ if( !pFtn->ContainsAny() && !pFtn->IsColLocked() )
+ {
+ pFtn->Cut();
+ delete pFtn;
+ // --> OD 2004-06-10 #i21478#
+ pFtn = 0L;
+ }
+ }
+ // --> OD 2005-05-18 #i49383#
+ if ( pFtn )
+ {
+ // --> OD 2006-02-02 #i57914# - adjust fix #i49383#
+ // enable lock of lower object position before format of footnote frame.
+ pFtn->UnlockPosOfLowerObjs();
+ pFtn->Calc();
+// pFtn->UnlockPosOfLowerObjs();
+ // <--
+ }
+ // --> OD 2006-02-02 #i57914# - adjust fix #i49383#
+ // no extra notify for footnote frame
+// else
+// {
+// aFtnFrmNotitfy.FrmDeleted();
+// }
+ // <--
+ }
+ }
+ else
+ { OSL_ENSURE( !pFtn->GetMaster() && !pFtn->GetFollow(),
+ "DelFtn und Master/Follow?" );
+ delete pFtn;
+ // --> OD 2004-06-10 #i21478#
+ pFtn = 0L;
+ }
+
+ // --> OD 2004-06-10 #i21478#
+ if ( pFtn )
+ {
+ pLastInsertedFtn = pFtn;
+ }
+ }
+
+ // --> OD 2004-06-10 #i21478# - format content of footnote following
+ // the new inserted ones.
+ if ( bCalc && pLastInsertedFtn )
+ {
+ if ( pLastInsertedFtn->GetNext() )
+ {
+ SwFtnFrm* pNextFtn = static_cast<SwFtnFrm*>(pLastInsertedFtn->GetNext());
+ SwTxtFtn* pAttr = pNextFtn->GetAttr();
+ SwFrm* pCnt = pNextFtn->ContainsAny();
+
+ sal_Bool bUnlock = !pNextFtn->IsBackMoveLocked();
+ pNextFtn->LockBackMove();
+ // --> OD 2005-05-18 #i49383# - disable unlock of position of
+ // lower objects during format of footnote content.
+ pNextFtn->KeepLockPosOfLowerObjs();
+ // --> OD 2006-02-02 #i57914# - adjust fix #i49383#
+ // no extra notify for footnote frame
+// SwLayNotify aFtnFrmNotitfy( pNextFtn );
+ // <--
+
+ while ( pCnt && pCnt->FindFtnFrm()->GetAttr() == pAttr )
+ {
+ pCnt->_InvalidatePos();
+ pCnt->Calc();
+ // --> OD 2005-05-17 #i49383# - format anchored objects
+ if ( pCnt->IsTxtFrm() && pCnt->IsValid() )
+ {
+ if ( !SwObjectFormatter::FormatObjsAtFrm( *pCnt,
+ *(pCnt->FindPageFrm()) ) )
+ {
+ // restart format with first content
+ pCnt = pNextFtn->ContainsAny();
+ continue;
+ }
+ }
+ // <--
+ if( pCnt->IsSctFrm() )
+ { // Wenn es sich um einen nichtleeren Bereich handelt,
+ // iterieren wir auch ueber seinen Inhalt
+ SwFrm* pTmp = ((SwSectionFrm*)pCnt)->ContainsAny();
+ if( pTmp )
+ pCnt = pTmp;
+ else
+ pCnt = pCnt->FindNext();
+ }
+ else
+ pCnt = pCnt->FindNext();
+ }
+ if( bUnlock )
+ {
+ pNextFtn->UnlockBackMove();
+ }
+ // --> OD 2005-05-18 #i49383#
+ // --> OD 2006-02-02 #i57914# - adjust fix #i49383#
+ // enable lock of lower object position before format of footnote frame.
+ pNextFtn->UnlockPosOfLowerObjs();
+ pNextFtn->Calc();
+// pNextFtn->UnlockPosOfLowerObjs();
+ // <--
+ }
+ }
+}
+
+/*************************************************************************
+|*
+|* SwFtnBossFrm::MoveFtns()
+|*
+|*************************************************************************/
+
+
+void SwFtnBossFrm::MoveFtns( const SwCntntFrm *pSrc, SwCntntFrm *pDest,
+ SwTxtFtn *pAttr )
+{
+ if( ( GetFmt()->GetDoc()->GetFtnInfo().ePos == FTNPOS_CHAPTER &&
+ (!GetUpper()->IsSctFrm() || !((SwSectionFrm*)GetUpper())->IsFtnAtEnd()))
+ || pAttr->GetFtn().IsEndNote() )
+ return;
+
+ OSL_ENSURE( this == pSrc->FindFtnBossFrm( sal_True ),
+ "SwPageFrm::MoveFtns: source frame isn't on that FtnBoss" );
+
+ SwFtnFrm *pFtn = FindFirstFtn();
+ if( pFtn )
+ {
+ ChangeFtnRef( pSrc, pAttr, pDest );
+ SwFtnBossFrm *pDestBoss = pDest->FindFtnBossFrm( sal_True );
+ OSL_ENSURE( pDestBoss, "+SwPageFrm::MoveFtns: no destination boss" );
+ if( pDestBoss ) // robust
+ {
+ SvPtrarr aFtnArr( 5, 5 );
+ pDestBoss->_CollectFtns( pDest, pFtn, aFtnArr );
+ if ( aFtnArr.Count() )
+ {
+ pDestBoss->_MoveFtns( aFtnArr, sal_True );
+ SwPageFrm* pSrcPage = FindPageFrm();
+ SwPageFrm* pDestPage = pDestBoss->FindPageFrm();
+ // Nur beim Seitenwechsel FtnNum Updaten
+ if( pSrcPage != pDestPage )
+ {
+ if( pSrcPage->GetPhyPageNum() > pDestPage->GetPhyPageNum() )
+ pSrcPage->UpdateFtnNum();
+ pDestPage->UpdateFtnNum();
+ }
+ }
+ }
+ }
+}
+
+/*************************************************************************
+|*
+|* SwFtnBossFrm::RearrangeFtns()
+|*
+|*************************************************************************/
+
+
+void SwFtnBossFrm::RearrangeFtns( const SwTwips nDeadLine, const sal_Bool bLock,
+ const SwTxtFtn *pAttr )
+{
+ //Alle Fussnoten der Spalte/Seite dergestalt anformatieren,
+ //dass sie ggf. die Spalte/Seite wechseln.
+
+ SwSaveFtnHeight aSave( this, nDeadLine );
+ SwFtnFrm *pFtn = FindFirstFtn();
+ if( pFtn && pFtn->GetPrev() && bLock )
+ {
+ SwFtnFrm* pFirst = (SwFtnFrm*)pFtn->GetUpper()->Lower();
+ SwFrm* pCntnt = pFirst->ContainsAny();
+ if( pCntnt )
+ {
+ sal_Bool bUnlock = !pFirst->IsBackMoveLocked();
+ pFirst->LockBackMove();
+ pFirst->Calc();
+ pCntnt->Calc();
+ // --> OD 2005-05-17 #i49383# - format anchored objects
+ if ( pCntnt->IsTxtFrm() && pCntnt->IsValid() )
+ {
+ SwObjectFormatter::FormatObjsAtFrm( *pCntnt,
+ *(pCntnt->FindPageFrm()) );
+ }
+ // <--
+ if( bUnlock )
+ pFirst->UnlockBackMove();
+ }
+ pFtn = FindFirstFtn();
+ }
+ SwDoc *pDoc = GetFmt()->GetDoc();
+ const sal_uLong nFtnPos = pAttr ? ::lcl_FindFtnPos( pDoc, pAttr ) : 0;
+ SwFrm *pCnt = pFtn ? pFtn->ContainsAny() : 0;
+ if ( pCnt )
+ {
+ sal_Bool bMore = sal_True;
+ sal_Bool bStart = pAttr == 0; // wenn kein Attribut uebergeben wird, alle bearbeiten
+ // --> OD 2005-05-18 #i49383# - disable unlock of position of
+ // lower objects during format of footnote and footnote content.
+ SwFtnFrm* pLastFtnFrm( 0L );
+ // --> OD 2006-02-02 #i57914# - adjust fix #i49383#
+ // no extra notify for footnote frame
+// SwLayNotify* pFtnFrmNotify( 0L );
+ // footnote frame needs to be locked, if <bLock> isn't set.
+ bool bUnlockLastFtnFrm( false );
+ // <--
+ do
+ {
+ if( !bStart )
+ bStart = ::lcl_FindFtnPos( pDoc, pCnt->FindFtnFrm()->GetAttr() )
+ == nFtnPos;
+ if( bStart )
+ {
+ pCnt->_InvalidatePos();
+ pCnt->_InvalidateSize();
+ pCnt->Prepare( PREP_ADJUST_FRM );
+ SwFtnFrm* pFtnFrm = pCnt->FindFtnFrm();
+ // --> OD 2005-05-18 #i49383#
+ if ( pFtnFrm != pLastFtnFrm )
+ {
+ if ( pLastFtnFrm )
+ {
+ if ( !bLock && bUnlockLastFtnFrm )
+ {
+ pLastFtnFrm->ColUnlock();
+ }
+ // --> OD 2006-02-02 #i57914# - adjust fix #i49383#
+ // enable lock of lower object position before format of footnote frame.
+ pLastFtnFrm->UnlockPosOfLowerObjs();
+ pLastFtnFrm->Calc();
+// pLastFtnFrm->UnlockPosOfLowerObjs();
+ // no extra notify for footnote frame
+// delete pFtnFrmNotify;
+ // <--
+ if ( !bLock && bUnlockLastFtnFrm &&
+ !pLastFtnFrm->GetLower() &&
+ !pLastFtnFrm->IsColLocked() &&
+ !pLastFtnFrm->IsBackMoveLocked() )
+ {
+ pLastFtnFrm->Cut();
+ delete pLastFtnFrm;
+ pLastFtnFrm = 0L;
+ }
+ }
+ if ( !bLock )
+ {
+ bUnlockLastFtnFrm = !pFtnFrm->IsColLocked();
+ pFtnFrm->ColLock();
+ }
+ pFtnFrm->KeepLockPosOfLowerObjs();
+ pLastFtnFrm = pFtnFrm;
+ // --> OD 2006-02-02 #i57914# - adjust fix #i49383#
+ // no extra notify for footnote frame
+// pFtnFrmNotify = new SwLayNotify( pLastFtnFrm );
+ // <--
+ }
+ // <--
+ // OD 30.10.2002 #97265# - invalidate position of footnote
+ // frame, if it's below its footnote container, in order to
+ // assure its correct position, probably calculating its previous
+ // footnote frames.
+ {
+ SWRECTFN( this );
+ SwFrm* aFtnContFrm = pFtnFrm->GetUpper();
+ if ( (pFtnFrm->Frm().*fnRect->fnTopDist)((aFtnContFrm->*fnRect->fnGetPrtBottom)()) > 0 )
+ {
+ pFtnFrm->_InvalidatePos();
+ }
+ }
+ if ( bLock )
+ {
+ sal_Bool bUnlock = !pFtnFrm->IsBackMoveLocked();
+ pFtnFrm->LockBackMove();
+ pFtnFrm->Calc();
+ pCnt->Calc();
+ // --> OD 2005-05-17 #i49383# - format anchored objects
+ if ( pCnt->IsTxtFrm() && pCnt->IsValid() )
+ {
+ if ( !SwObjectFormatter::FormatObjsAtFrm( *pCnt,
+ *(pCnt->FindPageFrm()) ) )
+ {
+ // restart format with first content
+ pCnt = pFtn->ContainsAny();
+ continue;
+ }
+ }
+ // <--
+ if( bUnlock )
+ {
+ pFtnFrm->UnlockBackMove();
+ if( !pFtnFrm->Lower() &&
+ !pFtnFrm->IsColLocked() )
+ {
+ // --> OD 2005-08-10 #i49383#
+ OSL_ENSURE( pLastFtnFrm == pFtnFrm,
+ "<SwFtnBossFrm::RearrangeFtns(..)> - <pLastFtnFrm> != <pFtnFrm>" );
+ pLastFtnFrm = 0L;
+ // --> OD 2006-02-02 #i57914# - adjust fix #i49383#
+ // no extra notify for footnote frame
+// pFtnFrmNotify->FrmDeleted();
+// delete pFtnFrmNotify;
+ // <--
+ pFtnFrm->Cut();
+ delete pFtnFrm;
+ }
+ }
+ }
+ else
+ {
+ pFtnFrm->Calc();
+ pCnt->Calc();
+ // --> OD 2005-05-17 #i49383# - format anchored objects
+ if ( pCnt->IsTxtFrm() && pCnt->IsValid() )
+ {
+ if ( !SwObjectFormatter::FormatObjsAtFrm( *pCnt,
+ *(pCnt->FindPageFrm()) ) )
+ {
+ // restart format with first content
+ pCnt = pFtn->ContainsAny();
+ continue;
+ }
+ }
+ // <--
+ }
+ }
+ SwSectionFrm *pDel = NULL;
+ if( pCnt->IsSctFrm() )
+ {
+ SwFrm* pTmp = ((SwSectionFrm*)pCnt)->ContainsAny();
+ if( pTmp )
+ {
+ pCnt = pTmp;
+ continue;
+ }
+ pDel = (SwSectionFrm*)pCnt;
+ }
+ if ( pCnt->GetNext() )
+ pCnt = pCnt->GetNext();
+ else
+ {
+ pCnt = pCnt->FindNext();
+ if ( pCnt )
+ {
+ SwFtnFrm* pFtnFrm = pCnt->FindFtnFrm();
+ if( pFtnFrm->GetRef()->FindFtnBossFrm(
+ pFtnFrm->GetAttr()->GetFtn().IsEndNote() ) != this )
+ bMore = sal_False;
+ }
+ else
+ bMore = sal_False;
+ }
+ if( pDel )
+ {
+ pDel->Cut();
+ delete pDel;
+ }
+ if ( bMore )
+ {
+ //Nicht weiter als bis zur angegebenen Fussnote, falls eine
+ //angegeben wurde.
+ if ( pAttr &&
+ (::lcl_FindFtnPos( pDoc,
+ pCnt->FindFtnFrm()->GetAttr()) > nFtnPos ) )
+ bMore = sal_False;
+ }
+ } while ( bMore );
+ // --> OD 2005-05-18 #i49383#
+ if ( pLastFtnFrm )
+ {
+ if ( !bLock && bUnlockLastFtnFrm )
+ {
+ pLastFtnFrm->ColUnlock();
+ }
+ // --> OD 2006-02-02 #i57914# - adjust fix #i49383#
+ // enable lock of lower object position before format of footnote frame.
+ pLastFtnFrm->UnlockPosOfLowerObjs();
+ pLastFtnFrm->Calc();
+// pLastFtnFrm->UnlockPosOfLowerObjs();
+ // no extra notify for footnote frame
+// delete pFtnFrmNotify;
+ // <--
+ if ( !bLock && bUnlockLastFtnFrm &&
+ !pLastFtnFrm->GetLower() &&
+ !pLastFtnFrm->IsColLocked() &&
+ !pLastFtnFrm->IsBackMoveLocked() )
+ {
+ pLastFtnFrm->Cut();
+ delete pLastFtnFrm;
+ }
+ }
+ // <--
+ }
+}
+
+/*************************************************************************
+|*
+|* SwPageFrm::UpdateFtnNum()
+|*
+|*************************************************************************/
+
+void SwPageFrm::UpdateFtnNum()
+{
+ //Seitenweise Numerierung nur wenn es am Dokument so eingestellt ist.
+ if ( GetFmt()->GetDoc()->GetFtnInfo().eNum != FTNNUM_PAGE )
+ return;
+
+ SwLayoutFrm* pBody = FindBodyCont();
+ if( !pBody || !pBody->Lower() )
+ return;
+
+ SwCntntFrm* pCntnt = pBody->ContainsCntnt();
+ sal_uInt16 nNum = 0;
+
+ while( pCntnt && pCntnt->FindPageFrm() == this )
+ {
+ if( ((SwTxtFrm*)pCntnt)->HasFtn() )
+ {
+ SwFtnBossFrm* pBoss = pCntnt->FindFtnBossFrm( sal_True );
+ if( pBoss->GetUpper()->IsSctFrm() &&
+ ((SwSectionFrm*)pBoss->GetUpper())->IsOwnFtnNum() )
+ pCntnt = ((SwSectionFrm*)pBoss->GetUpper())->FindLastCntnt();
+ else
+ {
+ SwFtnFrm* pFtn = (SwFtnFrm*)pBoss->FindFirstFtn( pCntnt );
+ while( pFtn )
+ {
+ SwTxtFtn* pTxtFtn = pFtn->GetAttr();
+ if( !pTxtFtn->GetFtn().IsEndNote() &&
+ !pTxtFtn->GetFtn().GetNumStr().Len() &&
+ !pFtn->GetMaster() &&
+ (pTxtFtn->GetFtn().GetNumber() != ++nNum) )
+ pTxtFtn->SetNumber( nNum );
+ if ( pFtn->GetNext() )
+ pFtn = (SwFtnFrm*)pFtn->GetNext();
+ else
+ {
+ SwFtnBossFrm* pTmpBoss = pFtn->FindFtnBossFrm( sal_True );
+ if( pTmpBoss )
+ {
+ SwPageFrm* pPage = pTmpBoss->FindPageFrm();
+ pFtn = NULL;
+ lcl_NextFtnBoss( pTmpBoss, pPage, sal_False );
+ SwFtnContFrm *pCont = pTmpBoss->FindNearestFtnCont();
+ if ( pCont )
+ pFtn = (SwFtnFrm*)pCont->Lower();
+ }
+ }
+ if( pFtn && pFtn->GetRef() != pCntnt )
+ pFtn = NULL;
+ }
+ }
+ }
+ pCntnt = pCntnt->FindNextCnt();
+ }
+}
+
+/*************************************************************************
+|*
+|* SwFtnBossFrm::SetFtnDeadLine()
+|*
+|*************************************************************************/
+
+void SwFtnBossFrm::SetFtnDeadLine( const SwTwips nDeadLine )
+{
+ SwFrm *pBody = FindBodyCont();
+ pBody->Calc();
+
+ SwFrm *pCont = FindFtnCont();
+ const SwTwips nMax = nMaxFtnHeight;//Aktuelle MaxHeight nicht ueberschreiten.
+ SWRECTFN( this )
+ if ( pCont )
+ {
+ pCont->Calc();
+ nMaxFtnHeight = -(pCont->Frm().*fnRect->fnBottomDist)( nDeadLine );
+ }
+ else
+ nMaxFtnHeight = -(pBody->Frm().*fnRect->fnBottomDist)( nDeadLine );
+
+ const ViewShell *pSh = getRootFrm() ? getRootFrm()->GetCurrShell() : 0;
+ if( pSh && pSh->GetViewOptions()->getBrowseMode() )
+ nMaxFtnHeight += pBody->Grow( LONG_MAX, sal_True );
+ if ( IsInSct() )
+ nMaxFtnHeight += FindSctFrm()->Grow( LONG_MAX, sal_True );
+
+ if ( nMaxFtnHeight < 0 )
+ nMaxFtnHeight = 0;
+ if ( nMax != LONG_MAX && nMaxFtnHeight > nMax )
+ nMaxFtnHeight = nMax;
+}
+
+/*************************************************************************
+|*
+|* SwFtnBossFrm::GetVarSpace()
+|*
+|*************************************************************************/
+SwTwips SwFtnBossFrm::GetVarSpace() const
+{
+ //Fuer Seiten soll ein Wert von 20% der Seitenhoehe nicht unterschritten
+ //werden (->AMA: was macht MS da?)
+ //->AMA: Was ist da fuer Bereiche sinnvoll (und kompatibel zu MS ;-)?
+ //AMA: MS kennt scheinbar kein Begrenzung, die Fussnoten nehmen durchaus
+ // die ganze Seite/Spalte ein.
+
+ const SwPageFrm* pPg = FindPageFrm();
+ OSL_ENSURE( pPg || IsInSct(), "Footnote lost page" );
+
+ const SwFrm *pBody = FindBodyCont();
+ SwTwips nRet;
+ if( pBody )
+ {
+ SWRECTFN( this )
+ if( IsInSct() )
+ {
+ nRet = 0;
+ SwTwips nTmp = (*fnRect->fnYDiff)( (pBody->*fnRect->fnGetPrtTop)(),
+ (Frm().*fnRect->fnGetTop)() );
+ const SwSectionFrm* pSect = FindSctFrm();
+ // Endnotes in a ftncontainer causes a deadline:
+ // the bottom of the last contentfrm
+ if( pSect->IsEndnAtEnd() ) // endnotes allowed?
+ {
+ OSL_ENSURE( !Lower() || !Lower()->GetNext() || Lower()->GetNext()->
+ IsFtnContFrm(), "FtnContainer exspected" );
+ const SwFtnContFrm* pCont = Lower() ?
+ (SwFtnContFrm*)Lower()->GetNext() : 0;
+ if( pCont )
+ {
+ SwFtnFrm* pFtn = (SwFtnFrm*)pCont->Lower();
+ while( pFtn)
+ {
+ if( pFtn->GetAttr()->GetFtn().IsEndNote() )
+ { // endnote found
+ SwFrm* pFrm = ((SwLayoutFrm*)Lower())->Lower();
+ if( pFrm )
+ {
+ while( pFrm->GetNext() )
+ pFrm = pFrm->GetNext(); // last cntntfrm
+ nTmp += (*fnRect->fnYDiff)(
+ (Frm().*fnRect->fnGetTop)(),
+ (pFrm->Frm().*fnRect->fnGetBottom)() );
+ }
+ break;
+ }
+ pFtn = (SwFtnFrm*)pFtn->GetNext();
+ }
+ }
+ }
+ if( nTmp < nRet )
+ nRet = nTmp;
+ }
+ else
+ nRet = - (pPg->Prt().*fnRect->fnGetHeight)()/5;
+ nRet += (pBody->Frm().*fnRect->fnGetHeight)();
+ if( nRet < 0 )
+ nRet = 0;
+ }
+ else
+ nRet = 0;
+ if ( IsPageFrm() )
+ {
+ const ViewShell *pSh = getRootFrm() ? getRootFrm()->GetCurrShell() : 0;
+ if( pSh && pSh->GetViewOptions()->getBrowseMode() )
+ nRet += BROWSE_HEIGHT - Frm().Height();
+ }
+ return nRet;
+}
+
+/*************************************************************************
+|*
+|* SwFtnBossFrm::NeighbourhoodAdjustment(SwFrm*)
+|*
+|* gibt Auskunft, ob die Groessenveraenderung von pFrm von AdjustNeighbourhood(...)
+|* oder von Grow/Shrink(..) verarbeitet werden sollte.
+|* Bei einem PageFrm oder in Spalten direkt unterhalb der Seite muss AdjustNei..
+|* gerufen werden, in Rahmenspalten Grow/Shrink.
+|* Spannend sind die spaltigen Bereiche: Wenn es in der Spalte einen Fussnotencontainer
+|* gibt und die Fussnoten nicht vom Bereich eingesammelt werden, ist ein Adjust..,
+|* ansonsten ein Grow/Shrink notwendig.
+|*
+|*************************************************************************/
+
+sal_uInt8 SwFtnBossFrm::_NeighbourhoodAdjustment( const SwFrm* ) const
+{
+ sal_uInt8 nRet = NA_ONLY_ADJUST;
+ if( GetUpper() && !GetUpper()->IsPageBodyFrm() )
+ {
+ // Spaltige Rahmen erfordern Grow/Shrink
+ if( GetUpper()->IsFlyFrm() )
+ nRet = NA_GROW_SHRINK;
+ else
+ {
+ OSL_ENSURE( GetUpper()->IsSctFrm(), "NeighbourhoodAdjustment: Unexspected Upper" );
+ if( !GetNext() && !GetPrev() )
+ nRet = NA_GROW_ADJUST; // section with a single column (FtnAtEnd)
+ else
+ {
+ const SwFrm* pTmp = Lower();
+ OSL_ENSURE( pTmp, "NeighbourhoodAdjustment: Missing Lower()" );
+ if( !pTmp->GetNext() )
+ nRet = NA_GROW_SHRINK;
+ else if( !GetUpper()->IsColLocked() )
+ nRet = NA_ADJUST_GROW;
+ OSL_ENSURE( !pTmp->GetNext() || pTmp->GetNext()->IsFtnContFrm(),
+ "NeighbourhoodAdjustment: Who's that guy?" );
+ }
+ }
+ }
+ return nRet;
+}
+
+/*************************************************************************
+|*
+|* SwPageFrm::SetColMaxFtnHeight()
+|*
+|*************************************************************************/
+void SwPageFrm::SetColMaxFtnHeight()
+{
+ SwLayoutFrm *pBody = FindBodyCont();
+ if( pBody && pBody->Lower() && pBody->Lower()->IsColumnFrm() )
+ {
+ SwColumnFrm* pCol = (SwColumnFrm*)pBody->Lower();
+ do
+ {
+ pCol->SetMaxFtnHeight( GetMaxFtnHeight() );
+ pCol = (SwColumnFrm*)pCol->GetNext();
+ } while ( pCol );
+ }
+}
+
+/*************************************************************************
+|*
+|* SwLayoutFrm::MoveLowerFtns
+|*
+|*************************************************************************/
+
+
+sal_Bool SwLayoutFrm::MoveLowerFtns( SwCntntFrm *pStart, SwFtnBossFrm *pOldBoss,
+ SwFtnBossFrm *pNewBoss, const sal_Bool bFtnNums )
+{
+ SwDoc *pDoc = GetFmt()->GetDoc();
+ if ( !pDoc->GetFtnIdxs().Count() )
+ return sal_False;
+ if( pDoc->GetFtnInfo().ePos == FTNPOS_CHAPTER &&
+ ( !IsInSct() || !FindSctFrm()->IsFtnAtEnd() ) )
+ return sal_True;
+
+ if ( !pNewBoss )
+ pNewBoss = FindFtnBossFrm( sal_True );
+ if ( pNewBoss == pOldBoss )
+ return sal_False;
+
+ sal_Bool bMoved = sal_False;
+ if( !pStart )
+ pStart = ContainsCntnt();
+
+ SvPtrarr aFtnArr( 5, 5 );
+
+ while ( IsAnLower( pStart ) )
+ {
+ if ( ((SwTxtFrm*)pStart)->HasFtn() )
+ {
+ // OD 03.04.2003 #108446# - To avoid unnecessary moves of footnotes
+ // use new parameter <_bCollectOnlyPreviousFtn> (4th parameter of
+ // method <SwFtnBossFrm::CollectFtn(..)>) to control, that only
+ // footnotes have to be collected, that are positioned before the
+ // new dedicated footnote boss frame.
+ pNewBoss->CollectFtns( pStart, pOldBoss, aFtnArr, sal_True );
+ }
+ pStart = pStart->GetNextCntntFrm();
+ }
+
+ OSL_ENSURE( pOldBoss->IsInSct() == pNewBoss->IsInSct(),
+ "MoveLowerFtns: Section confusion" );
+ SvPtrarr *pFtnArr;
+ SwLayoutFrm* pNewChief = 0;
+ SwLayoutFrm* pOldChief = 0;
+ if( pStart && pOldBoss->IsInSct() && ( pOldChief = pOldBoss->FindSctFrm() )
+ != ( pNewChief = pNewBoss->FindSctFrm() ) )
+ {
+ pFtnArr = new SvPtrarr( 5, 5 );
+ pOldChief = pOldBoss->FindFtnBossFrm( sal_True );
+ pNewChief = pNewBoss->FindFtnBossFrm( sal_True );
+ while( pOldChief->IsAnLower( pStart ) )
+ {
+ if ( ((SwTxtFrm*)pStart)->HasFtn() )
+ ((SwFtnBossFrm*)pNewChief)->CollectFtns( pStart,
+ (SwFtnBossFrm*)pOldBoss, *pFtnArr );
+ pStart = pStart->GetNextCntntFrm();
+ }
+ if( !pFtnArr->Count() )
+ {
+ delete pFtnArr;
+ pFtnArr = NULL;
+ }
+ }
+ else
+ pFtnArr = NULL;
+
+ if ( aFtnArr.Count() || pFtnArr )
+ {
+ if( aFtnArr.Count() )
+ pNewBoss->_MoveFtns( aFtnArr, sal_True );
+ if( pFtnArr )
+ {
+ ((SwFtnBossFrm*)pNewChief)->_MoveFtns( *pFtnArr, sal_True );
+ delete pFtnArr;
+ }
+ bMoved = sal_True;
+
+ // Nur bei einem Seitenwechsel muss die FtnNum neu berechnet werden
+ if ( bFtnNums )
+ {
+ SwPageFrm* pOldPage = pOldBoss->FindPageFrm();
+ SwPageFrm* pNewPage =pNewBoss->FindPageFrm();
+ if( pOldPage != pNewPage )
+ {
+ pOldPage->UpdateFtnNum();
+ pNewPage->UpdateFtnNum();
+ }
+ }
+ }
+ return bMoved;
+}
+
+/*************************************************************************
+|*
+|* SwLayoutFrm::MoveFtnCntFwd()
+|*
+|*************************************************************************/
+
+
+sal_Bool SwCntntFrm::MoveFtnCntFwd( sal_Bool bMakePage, SwFtnBossFrm *pOldBoss )
+{
+ OSL_ENSURE( IsInFtn(), "Keine Ftn." );
+ SwLayoutFrm *pFtn = FindFtnFrm();
+
+ // The first paragraph in the first footnote in the first column in the
+ // sectionfrm at the top of the page has not to move forward, if the
+ // columnbody is empty.
+ if( pOldBoss->IsInSct() && !pOldBoss->GetIndPrev() && !GetIndPrev() &&
+ !pFtn->GetPrev() )
+ {
+ SwLayoutFrm* pBody = pOldBoss->FindBodyCont();
+ if( !pBody || !pBody->Lower() )
+ return sal_True;
+ }
+
+ //fix(9538): Wenn die Ftn noch Nachbarn hinter sich hat, so muessen
+ //diese ersteinmal verschwinden.
+ SwLayoutFrm *pNxt = (SwLayoutFrm*)pFtn->GetNext();
+ SwLayoutFrm *pLst = 0;
+ while ( pNxt )
+ {
+ while ( pNxt->GetNext() )
+ pNxt = (SwLayoutFrm*)pNxt->GetNext();
+ if ( pNxt == pLst )
+ pNxt = 0;
+ else
+ { pLst = pNxt;
+ SwCntntFrm *pCnt = pNxt->ContainsCntnt();
+ if( pCnt )
+ pCnt->MoveFtnCntFwd( sal_True, pOldBoss );
+ pNxt = (SwLayoutFrm*)pFtn->GetNext();
+ }
+ }
+
+ sal_Bool bSamePage = sal_True;
+ SwLayoutFrm *pNewUpper =
+ GetLeaf( bMakePage ? MAKEPAGE_INSERT : MAKEPAGE_NONE, sal_True );
+
+ if ( pNewUpper )
+ {
+ sal_Bool bSameBoss = sal_True;
+ SwFtnBossFrm * const pNewBoss = pNewUpper->FindFtnBossFrm();
+ //Wechseln wir die Spalte/Seite?
+ if ( sal_False == ( bSameBoss = pNewBoss == pOldBoss ) )
+ {
+ bSamePage = pOldBoss->FindPageFrm() == pNewBoss->FindPageFrm(); // Seitenwechsel?
+ pNewUpper->Calc();
+ }
+
+ //Das Layoutblatt, dass wir fuer Fussnoten bekommen ist entweder
+ //ein Fussnotencontainer oder eine Fussnote
+ //Wenn es eine Fussnote ist, und sie die gleiche Fussnotenreferez
+ //wie der alte Upper hat, so moven wir uns direkt hinein.
+ //Ist die Referenz einen andere oder ist es ein Container, so wird
+ //eine neue Fussnote erzeugt und in den Container gestellt.
+ // Wenn wir in einem Bereich innerhalb der Fussnote sind, muss
+ // SectionFrame noch angelegt werden.
+ SwFtnFrm* pTmpFtn = pNewUpper->IsFtnFrm() ? ((SwFtnFrm*)pNewUpper) : 0;
+ if( !pTmpFtn )
+ {
+ OSL_ENSURE( pNewUpper->IsFtnContFrm(), "Neuer Upper kein FtnCont.");
+ SwFtnContFrm *pCont = (SwFtnContFrm*)pNewUpper;
+
+ //Fussnote erzeugen.
+ SwFtnFrm *pOld = FindFtnFrm();
+ pTmpFtn = new SwFtnFrm( pOld->GetFmt()->GetDoc()->GetDfltFrmFmt(),
+ pOld, pOld->GetRef(), pOld->GetAttr() );
+ //Verkettung der Fussnoten.
+ if ( pOld->GetFollow() )
+ {
+ pTmpFtn->SetFollow( pOld->GetFollow() );
+ pOld->GetFollow()->SetMaster( pTmpFtn );
+ }
+ pOld->SetFollow( pTmpFtn );
+ pTmpFtn->SetMaster( pOld );
+ SwFrm* pNx = pCont->Lower();
+ if( pNx && pTmpFtn->GetAttr()->GetFtn().IsEndNote() )
+ while(pNx && !((SwFtnFrm*)pNx)->GetAttr()->GetFtn().IsEndNote())
+ pNx = pNx->GetNext();
+ pTmpFtn->Paste( pCont, pNx );
+ pTmpFtn->Calc();
+ }
+ OSL_ENSURE( pTmpFtn->GetAttr() == FindFtnFrm()->GetAttr(), "Wrong Footnote!" );
+ // Bereiche in Fussnoten beduerfen besonderer Behandlung
+ SwLayoutFrm *pNewUp = pTmpFtn;
+ if( IsInSct() )
+ {
+ SwSectionFrm* pSect = FindSctFrm();
+ // Bereich in Fussnote (oder nur Fussnote in Bereich)?
+ if( pSect->IsInFtn() )
+ {
+ if( pTmpFtn->Lower() && pTmpFtn->Lower()->IsSctFrm() &&
+ pSect->GetFollow() == (SwSectionFrm*)pTmpFtn->Lower() )
+ pNewUp = (SwSectionFrm*)pTmpFtn->Lower();
+ else
+ {
+ pNewUp = new SwSectionFrm( *pSect, sal_False );
+ pNewUp->InsertBefore( pTmpFtn, pTmpFtn->Lower() );
+ static_cast<SwSectionFrm*>(pNewUp)->Init();
+ pNewUp->Frm().Pos() = pTmpFtn->Frm().Pos();
+ pNewUp->Frm().Pos().Y() += 1; //wg. Benachrichtigungen.
+
+ // Wenn unser Bereichsframe einen Nachfolger hat, so muss dieser
+ // umgehaengt werden hinter den neuen Follow der Bereichsframes.
+ SwFrm* pTmp = pSect->GetNext();
+ if( pTmp )
+ {
+ SwFlowFrm* pTmpNxt;
+ if( pTmp->IsCntntFrm() )
+ pTmpNxt = (SwCntntFrm*)pTmp;
+ else if( pTmp->IsSctFrm() )
+ pTmpNxt = (SwSectionFrm*)pTmp;
+ else
+ {
+ OSL_ENSURE( pTmp->IsTabFrm(), "GetNextSctLeaf: Wrong Type" );
+ pTmpNxt = (SwTabFrm*)pTmp;
+ }
+ pTmpNxt->MoveSubTree( pTmpFtn, pNewUp->GetNext() );
+ }
+ }
+ }
+ }
+
+ MoveSubTree( pNewUp, pNewUp->Lower() );
+
+ if( !bSameBoss )
+ Prepare( PREP_BOSS_CHGD );
+ }
+ return bSamePage;
+}
+
+/*************************************************************************
+|*
+|* class SwSaveFtnHeight
+|*
+|*************************************************************************/
+
+
+SwSaveFtnHeight::SwSaveFtnHeight( SwFtnBossFrm *pBs, const SwTwips nDeadLine ) :
+ pBoss( pBs ),
+ nOldHeight( pBs->GetMaxFtnHeight() )
+{
+ pBoss->SetFtnDeadLine( nDeadLine );
+ nNewHeight = pBoss->GetMaxFtnHeight();
+}
+
+
+
+SwSaveFtnHeight::~SwSaveFtnHeight()
+{
+ //Wenn zwischendurch jemand an der DeadLine gedreht hat, so lassen wir
+ //ihm seinen Spass!
+ if ( nNewHeight == pBoss->GetMaxFtnHeight() )
+ pBoss->nMaxFtnHeight = nOldHeight;
+}
+
+
+#if OSL_DEBUG_LEVEL > 1
+//JP 15.10.2001: in a non pro version test if the attribute has the same
+// meaning which his reference is
+
+// Normally, the pRef member and the GetRefFromAttr() result has to be
+// identically. Sometimes footnote will be moved from a master to its follow,
+// but the GetRef() is called first, so we have to ignore a master/follow
+// mismatch.
+
+const SwCntntFrm* SwFtnFrm::GetRef() const
+{
+ const SwCntntFrm* pRefAttr = GetRefFromAttr();
+ OSL_ENSURE( pRef == pRefAttr || pRef->IsAnFollow( pRefAttr )
+ || pRefAttr->IsAnFollow( pRef ),
+ "access to deleted Frame? pRef != pAttr->GetRef()" );
+ return pRef;
+}
+
+SwCntntFrm* SwFtnFrm::GetRef()
+{
+ const SwCntntFrm* pRefAttr = GetRefFromAttr();
+ OSL_ENSURE( pRef == pRefAttr || pRef->IsAnFollow( pRefAttr )
+ || pRefAttr->IsAnFollow( pRef ),
+ "access to deleted Frame? pRef != pAttr->GetRef()" );
+ return pRef;
+}
+
+#endif
+
+const SwCntntFrm* SwFtnFrm::GetRefFromAttr() const
+{
+ SwFtnFrm* pThis = (SwFtnFrm*)this;
+ return pThis->GetRefFromAttr();
+}
+
+SwCntntFrm* SwFtnFrm::GetRefFromAttr()
+{
+ OSL_ENSURE( pAttr, "invalid Attribute" );
+ SwTxtNode& rTNd = (SwTxtNode&)pAttr->GetTxtNode();
+ SwPosition aPos( rTNd, SwIndex( &rTNd, *pAttr->GetStart() ));
+ SwCntntFrm* pCFrm = rTNd.getLayoutFrm( getRootFrm(), 0, &aPos, sal_False );
+ return pCFrm;
+}
+
+/** search for last content in the current footnote frame
+
+ OD 2005-12-02 #i27138#
+
+ @author OD
+*/
+SwCntntFrm* SwFtnFrm::FindLastCntnt()
+{
+ SwCntntFrm* pLastCntntFrm( 0L );
+
+ // find last lower, which is a content frame or contains content.
+ // hidden text frames, empty sections and empty tables have to be skipped.
+ SwFrm* pLastLowerOfFtn( GetLower() );
+ SwFrm* pTmpLastLower( pLastLowerOfFtn );
+ while ( pTmpLastLower && pTmpLastLower->GetNext() )
+ {
+ pTmpLastLower = pTmpLastLower->GetNext();
+ if ( ( pTmpLastLower->IsTxtFrm() &&
+ !static_cast<SwTxtFrm*>(pTmpLastLower)->IsHiddenNow() ) ||
+ ( pTmpLastLower->IsSctFrm() &&
+ static_cast<SwSectionFrm*>(pTmpLastLower)->GetSection() &&
+ static_cast<SwSectionFrm*>(pTmpLastLower)->ContainsCntnt() ) ||
+ ( pTmpLastLower->IsTabFrm() &&
+ static_cast<SwTabFrm*>(pTmpLastLower)->ContainsCntnt() ) )
+ {
+ pLastLowerOfFtn = pTmpLastLower;
+ }
+ }
+
+ // determine last content frame depending on type of found last lower.
+ if ( pLastLowerOfFtn && pLastLowerOfFtn->IsTabFrm() )
+ {
+ pLastCntntFrm = static_cast<SwTabFrm*>(pLastLowerOfFtn)->FindLastCntnt();
+ }
+ else if ( pLastLowerOfFtn && pLastLowerOfFtn->IsSctFrm() )
+ {
+ pLastCntntFrm = static_cast<SwSectionFrm*>(pLastLowerOfFtn)->FindLastCntnt();
+ }
+ else
+ {
+ pLastCntntFrm = dynamic_cast<SwCntntFrm*>(pLastLowerOfFtn);
+ }
+
+ return pLastCntntFrm;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/layout/hffrm.cxx b/sw/source/core/layout/hffrm.cxx
new file mode 100644
index 000000000000..b8168dca941a
--- /dev/null
+++ b/sw/source/core/layout/hffrm.cxx
@@ -0,0 +1,796 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+#include "pagefrm.hxx"
+#include "viewsh.hxx"
+#include "doc.hxx"
+#include <fmtcntnt.hxx>
+#include <fmthdft.hxx>
+#include <fmtfsize.hxx>
+#include "viewopt.hxx"
+#include "hffrm.hxx"
+#include "rootfrm.hxx"
+#include "txtfrm.hxx"
+#include "sectfrm.hxx"
+#include "flyfrm.hxx"
+#include "frmtool.hxx"
+#include "dflyobj.hxx"
+#include "frmfmt.hxx"
+#include "ndindex.hxx"
+#include "hfspacingitem.hxx"
+// OD 2004-05-24 #i28701#
+#include <sortedobjs.hxx>
+// --> OD 2005-03-03 #i43771#
+#include <objectformatter.hxx>
+// <--
+
+extern sal_Bool bObjsDirect; //frmtool.cxx
+
+static SwTwips lcl_GetFrmMinHeight(const SwLayoutFrm & rFrm)
+{
+ const SwFmtFrmSize &rSz = rFrm.GetFmt()->GetFrmSize();
+ SwTwips nMinHeight;
+
+ switch (rSz.GetHeightSizeType())
+ {
+ case ATT_MIN_SIZE:
+ nMinHeight = rSz.GetHeight();
+
+ break;
+
+ default:
+ nMinHeight = 0;
+ }
+
+
+ return nMinHeight;
+}
+
+
+static SwTwips lcl_CalcContentHeight(SwLayoutFrm & frm)
+{
+ SwFrm* pFrm = frm.Lower();
+
+ SwTwips nRemaining = 0;
+ sal_uInt16 nNum = 0;
+ pFrm = frm.Lower();
+ while ( pFrm )
+ {
+ SwTwips nTmp;
+
+ nTmp = pFrm->Frm().Height();
+ nRemaining += nTmp;
+ if( pFrm->IsTxtFrm() && ((SwTxtFrm*)pFrm)->IsUndersized() )
+ {
+ nTmp = ((SwTxtFrm*)pFrm)->GetParHeight()
+ - pFrm->Prt().Height();
+ // Dieser TxtFrm waere gern ein bisschen groesser
+ nRemaining += nTmp;
+ }
+ else if( pFrm->IsSctFrm() && ((SwSectionFrm*)pFrm)->IsUndersized() )
+ {
+ nTmp = ((SwSectionFrm*)pFrm)->Undersize();
+ nRemaining += nTmp;
+ }
+ pFrm = pFrm->GetNext();
+
+ nNum++;
+ }
+
+ return nRemaining;
+}
+
+static void lcl_LayoutFrmEnsureMinHeight(SwLayoutFrm & rFrm,
+ const SwBorderAttrs * )
+{
+ SwTwips nMinHeight = lcl_GetFrmMinHeight(rFrm);
+
+ if (rFrm.Frm().Height() < nMinHeight)
+ {
+ rFrm.Grow(nMinHeight - rFrm.Frm().Height());
+ }
+}
+
+SwHeadFootFrm::SwHeadFootFrm( SwFrmFmt * pFmt, SwFrm* pSib, sal_uInt16 nTypeIn)
+ : SwLayoutFrm( pFmt, pSib )
+{
+ nType = nTypeIn;
+ SetDerivedVert( sal_False );
+
+ const SwFmtCntnt &rCnt = pFmt->GetCntnt();
+
+ OSL_ENSURE( rCnt.GetCntntIdx(), "Kein Inhalt fuer Header." );
+
+ //Fuer Header Footer die Objekte gleich erzeugen lassen.
+ sal_Bool bOld = bObjsDirect;
+ bObjsDirect = sal_True;
+ sal_uLong nIndex = rCnt.GetCntntIdx()->GetIndex();
+ ::_InsertCnt( this, pFmt->GetDoc(), ++nIndex );
+ bObjsDirect = bOld;
+}
+
+void SwHeadFootFrm::FormatPrt(SwTwips & nUL, const SwBorderAttrs * pAttrs)
+{
+ if (GetEatSpacing())
+ {
+ /* The minimal height of the print area is the minimal height of the
+ frame without the height needed for borders and shadow. */
+ SwTwips nMinHeight = lcl_GetFrmMinHeight(*this);
+
+ nMinHeight -= pAttrs->CalcTop();
+ nMinHeight -= pAttrs->CalcBottom();
+
+ /* If the minimal height of the print area is negative, try to
+ compensate by overlapping */
+ SwTwips nOverlap = 0;
+ if (nMinHeight < 0)
+ {
+ nOverlap = -nMinHeight;
+ nMinHeight = 0;
+ }
+
+ /* Calculate desired height of content. The minimal height has to be
+ adhered. */
+ SwTwips nHeight;
+
+ if ( ! HasFixSize() )
+ nHeight = lcl_CalcContentHeight(*this);
+ else
+ nHeight = nMinHeight;
+
+ if (nHeight < nMinHeight)
+ nHeight = nMinHeight;
+
+ /* calculate initial spacing/line space */
+ SwTwips nSpace, nLine;
+
+ if (IsHeaderFrm())
+ {
+ nSpace = pAttrs->CalcBottom();
+ nLine = pAttrs->CalcBottomLine();
+ }
+ else
+ {
+ nSpace = pAttrs->CalcTop();
+ nLine = pAttrs->CalcTopLine();
+ }
+
+ /* calculate overlap and correct spacing */
+ nOverlap += nHeight - nMinHeight;
+ if (nOverlap < nSpace - nLine)
+ nSpace -= nOverlap;
+ else
+ nSpace = nLine;
+
+ /* calculate real vertical space between frame and print area */
+ if (IsHeaderFrm())
+ nUL = pAttrs->CalcTop() + nSpace;
+ else
+ nUL = pAttrs->CalcBottom() + nSpace;
+
+ /* set print area */
+ // OD 23.01.2003 #106895# - add first parameter to <SwBorderAttrs::CalcRight(..)>
+ SwTwips nLR = pAttrs->CalcLeft( this ) + pAttrs->CalcRight( this );
+
+ aPrt.Left(pAttrs->CalcLeft(this));
+
+ if (IsHeaderFrm())
+ aPrt.Top(pAttrs->CalcTop());
+ else
+ aPrt.Top(nSpace);
+
+ aPrt.Width(aFrm.Width() - nLR);
+
+ SwTwips nNewHeight;
+
+ if (nUL < aFrm.Height())
+ nNewHeight = aFrm.Height() - nUL;
+ else
+ nNewHeight = 0;
+
+ aPrt.Height(nNewHeight);
+
+ }
+ else
+ {
+ //Position einstellen.
+ aPrt.Left( pAttrs->CalcLeft( this ) );
+ aPrt.Top ( pAttrs->CalcTop() );
+
+ //Sizes einstellen; die Groesse gibt der umgebende Frm vor, die
+ //die Raender werden einfach abgezogen.
+ // OD 23.01.2003 #106895# - add first parameter to <SwBorderAttrs::CalcRight(..)>
+ SwTwips nLR = pAttrs->CalcLeft( this ) + pAttrs->CalcRight( this );
+ aPrt.Width ( aFrm.Width() - nLR );
+ aPrt.Height( aFrm.Height()- nUL );
+
+ }
+
+ bValidPrtArea = sal_True;
+}
+
+void SwHeadFootFrm::FormatSize(SwTwips nUL, const SwBorderAttrs * pAttrs)
+{
+ if ( !HasFixSize() )
+ {
+ if( !IsColLocked() )
+ {
+ bValidSize = bValidPrtArea = sal_True;
+
+ const SwTwips nBorder = nUL;
+ SwTwips nMinHeight = lcl_GetFrmMinHeight(*this);
+ nMinHeight -= pAttrs->CalcTop();
+ nMinHeight -= pAttrs->CalcBottom();
+
+ if (nMinHeight < 0)
+ nMinHeight = 0;
+
+ ColLock();
+
+ SwTwips nMaxHeight = LONG_MAX;
+ SwTwips nRemaining, nOldHeight;
+ // --> OD 2006-05-24 #i64301#
+ // use the position of the footer printing area to control invalidation
+ // of the first footer content.
+ Point aOldFooterPrtPos;
+ // <--
+
+ do
+ {
+ nOldHeight = Prt().Height();
+ SwFrm* pFrm = Lower();
+ // --> OD 2006-05-24 #i64301#
+ if ( pFrm &&
+ aOldFooterPrtPos != ( Frm().Pos() + Prt().Pos() ) )
+ {
+ pFrm->_InvalidatePos();
+ aOldFooterPrtPos = Frm().Pos() + Prt().Pos();
+ }
+ // <--
+ while( pFrm )
+ {
+ pFrm->Calc();
+ // --> OD 2005-03-03 #i43771# - format also object anchored
+ // at the frame
+ // --> OD 2005-05-03 #i46941# - frame has to be valid.
+ // Note: frame could be invalid after calling its format,
+ // if it's locked
+ OSL_ENSURE( StackHack::IsLocked() || !pFrm->IsTxtFrm() ||
+ pFrm->IsValid() ||
+ static_cast<SwTxtFrm*>(pFrm)->IsJoinLocked(),
+ "<SwHeadFootFrm::FormatSize(..)> - text frame invalid and not locked." );
+ if ( pFrm->IsTxtFrm() && pFrm->IsValid() )
+ {
+ if ( !SwObjectFormatter::FormatObjsAtFrm( *pFrm,
+ *(pFrm->FindPageFrm()) ) )
+ {
+ // restart format with first content
+ pFrm = Lower();
+ continue;
+ }
+ }
+ // <--
+ pFrm = pFrm->GetNext();
+ }
+ nRemaining = 0;
+ pFrm = Lower();
+
+ while ( pFrm )
+ {
+ nRemaining += pFrm->Frm().Height();
+
+ if( pFrm->IsTxtFrm() &&
+ ((SwTxtFrm*)pFrm)->IsUndersized() )
+ // Dieser TxtFrm waere gern ein bisschen groesser
+ nRemaining += ((SwTxtFrm*)pFrm)->GetParHeight()
+ - pFrm->Prt().Height();
+ else if( pFrm->IsSctFrm() &&
+ ((SwSectionFrm*)pFrm)->IsUndersized() )
+ nRemaining += ((SwSectionFrm*)pFrm)->Undersize();
+ pFrm = pFrm->GetNext();
+ }
+ if ( nRemaining < nMinHeight )
+ nRemaining = nMinHeight;
+
+ SwTwips nDiff = nRemaining - nOldHeight;
+
+ if( !nDiff )
+ break;
+ if( nDiff < 0 )
+ {
+ nMaxHeight = nOldHeight;
+
+ if( nRemaining <= nMinHeight )
+ nRemaining = ( nMaxHeight + nMinHeight + 1 ) / 2;
+ }
+ else
+ {
+ if (nOldHeight > nMinHeight)
+ nMinHeight = nOldHeight;
+
+ if( nRemaining >= nMaxHeight )
+ nRemaining = ( nMaxHeight + nMinHeight + 1 ) / 2;
+ }
+
+ nDiff = nRemaining - nOldHeight;
+
+ if ( nDiff )
+ {
+ ColUnlock();
+ if ( nDiff > 0 )
+ {
+ if ( Grow( nDiff ) )
+ {
+ pFrm = Lower();
+
+ while ( pFrm )
+ {
+ if( pFrm->IsTxtFrm())
+ {
+ SwTxtFrm * pTmpFrm = (SwTxtFrm*) pFrm;
+ if (pTmpFrm->IsUndersized() )
+ {
+ pTmpFrm->InvalidateSize();
+ pTmpFrm->Prepare(PREP_ADJUST_FRM);
+ }
+ }
+ /* #i3568# Undersized sections need to be
+ invalidated too. */
+ else if (pFrm->IsSctFrm())
+ {
+ SwSectionFrm * pTmpFrm =
+ (SwSectionFrm*) pFrm;
+ if (pTmpFrm->IsUndersized() )
+ {
+ pTmpFrm->InvalidateSize();
+ pTmpFrm->Prepare(PREP_ADJUST_FRM);
+ }
+ }
+ pFrm = pFrm->GetNext();
+ }
+ }
+ }
+ else
+ Shrink( -nDiff );
+ //Schnell auf dem kurzen Dienstweg die Position updaten.
+
+ MakePos();
+ ColLock();
+ }
+ else
+ break;
+ //Unterkante des Uppers nicht ueberschreiten.
+ if ( GetUpper() && Frm().Height() )
+ {
+ const SwTwips nDeadLine = GetUpper()->Frm().Top() +
+ GetUpper()->Prt().Bottom();
+ const SwTwips nBot = Frm().Bottom();
+ if ( nBot > nDeadLine )
+ {
+ Frm().Bottom( nDeadLine );
+ Prt().SSize().Height() = Frm().Height() - nBorder;
+ }
+ }
+ bValidSize = bValidPrtArea = sal_True;
+ } while( nRemaining<=nMaxHeight && nOldHeight!=Prt().Height() );
+ ColUnlock();
+ }
+ bValidSize = bValidPrtArea = sal_True;
+ }
+ else //if ( GetType() & 0x0018 )
+ {
+ do
+ {
+ if ( Frm().Height() != pAttrs->GetSize().Height() )
+ ChgSize( Size( Frm().Width(), pAttrs->GetSize().Height()));
+ bValidSize = sal_True;
+ MakePos();
+ } while ( !bValidSize );
+ }
+}
+
+void SwHeadFootFrm::Format(const SwBorderAttrs * pAttrs)
+{
+ OSL_ENSURE( pAttrs, "SwFooterFrm::Format, pAttrs ist 0." );
+
+ if ( bValidPrtArea && bValidSize )
+ return;
+
+ if ( ! GetEatSpacing() && IsHeaderFrm())
+ {
+ SwLayoutFrm::Format(pAttrs);
+ }
+ else
+ {
+ lcl_LayoutFrmEnsureMinHeight(*this, pAttrs);
+
+ long nUL = pAttrs->CalcTop() + pAttrs->CalcBottom();
+
+ if ( !bValidPrtArea )
+ FormatPrt(nUL, pAttrs);
+
+ if ( !bValidSize )
+ FormatSize(nUL, pAttrs);
+ }
+}
+
+SwTwips SwHeadFootFrm::GrowFrm( SwTwips nDist, sal_Bool bTst, sal_Bool bInfo )
+{
+ SwTwips nResult;
+
+ if ( IsColLocked() )
+ {
+ nResult = 0;
+ }
+ else if (!GetEatSpacing())
+ {
+ nResult = SwLayoutFrm::GrowFrm(nDist, bTst, bInfo);
+ }
+ else
+ {
+ nResult = 0;
+
+ SwBorderAttrAccess * pAccess =
+ new SwBorderAttrAccess( SwFrm::GetCache(), this );
+ OSL_ENSURE(pAccess, "no border attributes");
+
+ SwBorderAttrs * pAttrs = pAccess->Get();
+
+ /* First assume the whole amount to grow can be provided by eating
+ spacing. */
+ SwTwips nEat = nDist;
+ SwTwips nMaxEat;
+
+ /* calculate maximum eatable spacing */
+ if (IsHeaderFrm())
+ nMaxEat = aFrm.Height() - aPrt.Top() - aPrt.Height() - pAttrs->CalcBottomLine();
+ else
+ nMaxEat = aPrt.Top() - pAttrs->CalcTopLine();
+
+ delete pAccess;
+
+ if (nMaxEat < 0)
+ nMaxEat = 0;
+
+ /* If the frame is too small, eat less spacing thus letting the frame
+ grow more. */
+ SwTwips nMinHeight = lcl_GetFrmMinHeight(*this);
+ SwTwips nFrameTooSmall = nMinHeight - Frm().Height();
+
+ if (nFrameTooSmall > 0)
+ nEat -= nFrameTooSmall;
+
+ /* No negative eating, not eating more than allowed. */
+ if (nEat < 0)
+ nEat = 0;
+ else if (nEat > nMaxEat)
+ nEat = nMaxEat;
+
+ // OD 10.04.2003 #108719# - Notify fly frame, if header frame
+ // grows. Consider, that 'normal' grow of layout frame already notifys
+ // the fly frames.
+ sal_Bool bNotifyFlys = sal_False;
+ if (nEat > 0)
+ {
+ if ( ! bTst)
+ {
+ if (! IsHeaderFrm())
+ {
+ aPrt.Top(aPrt.Top() - nEat);
+ aPrt.Height(aPrt.Height() - nEat);
+ }
+
+ InvalidateAll();
+ }
+
+ nResult += nEat;
+ // OD 14.04.2003 #108719# - trigger fly frame notify.
+ if ( IsHeaderFrm() )
+ {
+ bNotifyFlys = sal_True;
+ }
+ }
+
+ if (nDist - nEat > 0)
+ {
+ SwTwips nFrmGrow =
+ SwLayoutFrm::GrowFrm( nDist - nEat, bTst, bInfo );
+
+ nResult += nFrmGrow;
+ if ( nFrmGrow > 0 )
+ {
+ bNotifyFlys = sal_False;
+ }
+ }
+
+ // OD 10.04.2003 #108719# - notify fly frames, if necessary and triggered.
+ if ( ( nResult > 0 ) && bNotifyFlys )
+ {
+ NotifyLowerObjs();
+ }
+ }
+
+ if ( nResult && !bTst )
+ SetCompletePaint();
+
+ return nResult;
+}
+
+SwTwips SwHeadFootFrm::ShrinkFrm( SwTwips nDist, sal_Bool bTst, sal_Bool bInfo )
+{
+ SwTwips nResult;
+
+ if ( IsColLocked() )
+ {
+ nResult = 0;
+ }
+ else if (! GetEatSpacing())
+ {
+ nResult = SwLayoutFrm::ShrinkFrm(nDist, bTst, bInfo);
+ }
+ else
+ {
+ nResult = 0;
+
+ SwTwips nMinHeight = lcl_GetFrmMinHeight(*this);
+ SwTwips nOldHeight = Frm().Height();
+ SwTwips nRest = 0; // Amount to shrink by spitting out spacing
+
+ if ( nOldHeight >= nMinHeight )
+ {
+ /* If the frame's height is bigger than its minimum height, shrink
+ the frame towards its minimum height. If this is not sufficient
+ to provide the shrinking requested provide the rest by spitting
+ out spacing. */
+
+ SwTwips nBiggerThanMin = nOldHeight - nMinHeight;
+
+ if (nBiggerThanMin < nDist)
+ {
+ nRest = nDist - nBiggerThanMin;
+ }
+ /* info: declaration of nRest -> else nRest = 0 */
+ }
+ else
+ /* The frame cannot shrink. Provide shrinking by spitting out
+ spacing. */
+ nRest = nDist;
+
+ // OD 10.04.2003 #108719# - Notify fly frame, if header/footer frame
+ // shrinks. Consider, that 'normal' shrink of layout frame already notifys
+ // the fly frames.
+ sal_Bool bNotifyFlys = sal_False;
+ if (nRest > 0)
+ {
+
+ SwBorderAttrAccess * pAccess =
+ new SwBorderAttrAccess( SwFrm::GetCache(), this );
+ OSL_ENSURE(pAccess, "no border attributes");
+
+ SwBorderAttrs * pAttrs = pAccess->Get();
+
+ /* minimal height of print area */
+ SwTwips nMinPrtHeight = nMinHeight
+ - pAttrs->CalcTop()
+ - pAttrs->CalcBottom();
+
+ if (nMinPrtHeight < 0)
+ nMinPrtHeight = 0;
+
+ delete pAccess;
+
+ /* assume all shrinking can be provided */
+ SwTwips nShrink = nRest;
+
+ /* calculate maximum shrinking */
+ SwTwips nMaxShrink = aPrt.Height() - nMinPrtHeight;
+
+ /* shrink no more than maximum shrinking */
+ if (nShrink > nMaxShrink)
+ {
+ //nRest -= nShrink - nMaxShrink;
+ nShrink = nMaxShrink;
+ }
+
+ if (!bTst)
+ {
+ if (! IsHeaderFrm() )
+ {
+ aPrt.Top(aPrt.Top() + nShrink);
+ aPrt.Height(aPrt.Height() - nShrink);
+ }
+
+ InvalidateAll();
+ }
+ nResult += nShrink;
+ // OD 14.04.2003 #108719# - trigger fly frame notify.
+ if ( IsHeaderFrm() )
+ {
+ bNotifyFlys = sal_True;
+ }
+ }
+
+ /* The shrinking not providable by spitting out spacing has to be done
+ by the frame. */
+ if (nDist - nRest > 0)
+ {
+ SwTwips nShrinkAmount = SwLayoutFrm::ShrinkFrm( nDist - nRest, bTst, bInfo );
+ nResult += nShrinkAmount;
+ if ( nShrinkAmount > 0 )
+ {
+ bNotifyFlys = sal_False;
+ }
+ }
+
+ // OD 10.04.2003 #108719# - notify fly frames, if necessary.
+ if ( ( nResult > 0 ) && bNotifyFlys )
+ {
+ NotifyLowerObjs();
+ }
+ }
+
+ return nResult;
+}
+
+sal_Bool SwHeadFootFrm::GetEatSpacing() const
+{
+ const SwFrmFmt * pFmt = GetFmt();
+ OSL_ENSURE(pFmt, "SwHeadFootFrm: no format?");
+
+ if (pFmt->GetHeaderAndFooterEatSpacing().GetValue())
+ return sal_True;
+
+ return sal_False;
+}
+
+
+/*************************************************************************
+|*
+|* SwPageFrm::PrepareHeader()
+|*
+|* Beschreibung Erzeugt oder Entfernt Header
+|*
+|*************************************************************************/
+
+
+void DelFlys( SwLayoutFrm *pFrm, SwPageFrm *pPage )
+{
+ for ( int i = 0; pPage->GetSortedObjs() &&
+ pPage->GetSortedObjs()->Count() &&
+ i < (int)pPage->GetSortedObjs()->Count(); ++i )
+ {
+ SwAnchoredObject* pObj = (*pPage->GetSortedObjs())[i];
+ if ( pObj->ISA(SwFlyFrm) )
+ {
+ SwFlyFrm* pFlyFrm = static_cast<SwFlyFrm*>(pObj);
+ if ( pFrm->IsAnLower( pFlyFrm ) )
+ {
+ delete pFlyFrm;
+ --i;
+ }
+ }
+ }
+}
+
+
+
+void SwPageFrm::PrepareHeader()
+{
+ SwLayoutFrm *pLay = (SwLayoutFrm*)Lower();
+ if ( !pLay )
+ return;
+
+ const SwFmtHeader &rH = ((SwFrmFmt*)GetRegisteredIn())->GetHeader();
+
+ const ViewShell *pSh = getRootFrm()->GetCurrShell();
+ const sal_Bool bOn = !(pSh && pSh->GetViewOptions()->getBrowseMode());
+
+ if ( bOn && rH.IsActive() )
+ { //Header einsetzen, vorher entfernen falls vorhanden.
+ OSL_ENSURE( rH.GetHeaderFmt(), "FrmFmt fuer Header nicht gefunden." );
+
+ if ( pLay->GetFmt() == (SwFrmFmt*)rH.GetHeaderFmt() )
+ return; //Der Footer ist bereits der richtige
+
+ if ( pLay->IsHeaderFrm() )
+ { SwLayoutFrm *pDel = pLay;
+ pLay = (SwLayoutFrm*)pLay->GetNext();
+ ::DelFlys( pDel, this );
+ pDel->Cut();
+ delete pDel;
+ }
+ OSL_ENSURE( pLay, "Wohin mit dem Header?" );
+ SwHeaderFrm *pH = new SwHeaderFrm( (SwFrmFmt*)rH.GetHeaderFmt(), this );
+ pH->Paste( this, pLay );
+ if ( GetUpper() )
+ ::RegistFlys( this, pH );
+ }
+ else if ( pLay && pLay->IsHeaderFrm() )
+ { //Header entfernen falls vorhanden.
+ ::DelFlys( pLay, this );
+ pLay->Cut();
+ delete pLay;
+ }
+}
+/*************************************************************************
+|*
+|* SwPageFrm::PrepareFooter()
+|*
+|* Beschreibung Erzeugt oder Entfernt Footer
+|*
+|*************************************************************************/
+
+
+void SwPageFrm::PrepareFooter()
+{
+ SwLayoutFrm *pLay = (SwLayoutFrm*)Lower();
+ if ( !pLay )
+ return;
+
+ const SwFmtFooter &rF = ((SwFrmFmt*)GetRegisteredIn())->GetFooter();
+ while ( pLay->GetNext() )
+ pLay = (SwLayoutFrm*)pLay->GetNext();
+
+ const ViewShell *pSh = getRootFrm()->GetCurrShell();
+ const sal_Bool bOn = !(pSh && pSh->GetViewOptions()->getBrowseMode());
+
+ if ( bOn && rF.IsActive() )
+ { //Footer einsetzen, vorher entfernen falls vorhanden.
+ OSL_ENSURE( rF.GetFooterFmt(), "FrmFmt fuer Footer nicht gefunden." );
+
+ if ( pLay->GetFmt() == (SwFrmFmt*)rF.GetFooterFmt() )
+ return; //Der Footer ist bereits der richtige.
+
+ if ( pLay->IsFooterFrm() )
+ { ::DelFlys( pLay, this );
+ pLay->Cut();
+ delete pLay;
+ }
+ SwFooterFrm *pF = new SwFooterFrm( (SwFrmFmt*)rF.GetFooterFmt(), this );
+ pF->Paste( this );
+ if ( GetUpper() )
+ ::RegistFlys( this, pF );
+ }
+ else if ( pLay && pLay->IsFooterFrm() )
+ { //Footer entfernen falls vorhanden.
+ ::DelFlys( pLay, this );
+ ViewShell *pShell;
+ if ( pLay->GetPrev() && 0 != (pShell = getRootFrm()->GetCurrShell()) &&
+ pShell->VisArea().HasArea() )
+ pShell->InvalidateWindows( pShell->VisArea() );
+ pLay->Cut();
+ delete pLay;
+ }
+}
+
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/layout/layact.cxx b/sw/source/core/layout/layact.cxx
new file mode 100644
index 000000000000..e0b4cd7432dc
--- /dev/null
+++ b/sw/source/core/layout/layact.cxx
@@ -0,0 +1,2546 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+#include <time.h>
+#include "rootfrm.hxx"
+#include "pagefrm.hxx"
+#include "cntfrm.hxx"
+#include "doc.hxx"
+#include "IDocumentDrawModelAccess.hxx"
+#include "IDocumentSettingAccess.hxx"
+#include "IDocumentLayoutAccess.hxx"
+#include "IDocumentStatistics.hxx"
+#include "IDocumentTimerAccess.hxx"
+#include "viewimp.hxx"
+#include "crsrsh.hxx"
+#include "dflyobj.hxx"
+#include "flyfrm.hxx"
+#include "frmtool.hxx"
+#include "dcontact.hxx"
+#include "ndtxt.hxx" // OnlineSpelling
+#include "frmfmt.hxx"
+#include "swregion.hxx"
+#include "viewopt.hxx" // OnlineSpelling ueber Internal-TabPage testen.
+#include "pam.hxx" // OnlineSpelling wg. der aktuellen Cursorposition
+#include "dbg_lay.hxx"
+#include "layouter.hxx" // LoopControlling
+#include "docstat.hxx"
+#include "swevent.hxx"
+
+#include <sfx2/event.hxx>
+
+#include <ftnidx.hxx>
+#include <vcl/window.hxx>
+#include <vcl/svapp.hxx>
+#include <editeng/opaqitem.hxx>
+#include <editeng/brshitem.hxx>
+#include <SwSmartTagMgr.hxx>
+
+#define _LAYACT_CXX
+#include "layact.hxx"
+#include <swwait.hxx>
+#include <fmtsrnd.hxx>
+#include <fmtanchr.hxx>
+#include <tools/shl.hxx>
+#include <sfx2/progress.hxx>
+#include <docsh.hxx>
+
+#include "swmodule.hxx"
+#include "fmtline.hxx"
+#include "tabfrm.hxx"
+#include "ftnfrm.hxx"
+#include "txtfrm.hxx"
+#include "notxtfrm.hxx"
+#include "flyfrms.hxx"
+#include "mdiexp.hxx"
+#include "fmtornt.hxx"
+#include "sectfrm.hxx"
+#include "lineinfo.hxx"
+#include <acmplwrd.hxx>
+// --> OD 2004-06-28 #i28701#
+#include <sortedobjs.hxx>
+#include <objectformatter.hxx>
+#include <PostItMgr.hxx>
+#include <vector>
+
+// <--
+//#pragma optimize("ity",on)
+
+/*************************************************************************
+|*
+|* SwLayAction Statisches Geraffel
+|*
+|*************************************************************************/
+
+#define IS_FLYS (pPage->GetSortedObjs())
+#define IS_INVAFLY (pPage->IsInvalidFly())
+
+
+//Sparen von Schreibarbeit um den Zugriff auf zerstoerte Seiten zu vermeiden.
+#if OSL_DEBUG_LEVEL > 1
+
+static void BreakPoint()
+{
+ return;
+}
+
+#define CHECKPAGE \
+ { if ( IsAgain() ) \
+ { BreakPoint(); \
+ return; \
+ } \
+ }
+
+#define XCHECKPAGE \
+ { if ( IsAgain() ) \
+ { BreakPoint(); \
+ if( bNoLoop ) \
+ pLayoutAccess->GetLayouter()->EndLoopControl(); \
+ return; \
+ } \
+ }
+#else
+#define CHECKPAGE \
+ { if ( IsAgain() ) \
+ return; \
+ }
+
+#define XCHECKPAGE \
+ { if ( IsAgain() ) \
+ { \
+ if( bNoLoop ) \
+ pLayoutAccess->GetLayouter()->EndLoopControl(); \
+ return; \
+ } \
+ }
+#endif
+
+#define RESCHEDULE \
+ { \
+ if ( IsReschedule() ) \
+ { \
+ if (pProgress) pProgress->Reschedule(); \
+ ::RescheduleProgress( pImp->GetShell()->GetDoc()->GetDocShell() ); \
+ } \
+ }
+
+inline sal_uLong Ticks()
+{
+ return 1000 * clock() / CLOCKS_PER_SEC;
+}
+
+void SwLayAction::CheckWaitCrsr()
+{
+ RESCHEDULE
+ if ( !IsWait() && IsWaitAllowed() && IsPaint() &&
+ ((Ticks() - GetStartTicks()) >= CLOCKS_PER_SEC/2) )
+ {
+ pWait = new SwWait( *pRoot->GetFmt()->GetDoc()->GetDocShell(), sal_True );
+ }
+}
+
+/*************************************************************************
+|*
+|* SwLayAction::CheckIdleEnd()
+|*
+|*************************************************************************/
+//Ist es wirklich schon soweit...
+inline void SwLayAction::CheckIdleEnd()
+{
+ if ( !IsInput() )
+ bInput = GetInputType() && Application::AnyInput( GetInputType() );
+}
+
+/*************************************************************************
+|*
+|* SwLayAction::SetStatBar()
+|*
+|*************************************************************************/
+void SwLayAction::SetStatBar( sal_Bool bNew )
+{
+ if ( bNew )
+ {
+ nEndPage = pRoot->GetPageNum();
+ nEndPage += nEndPage * 10 / 100;
+ }
+ else
+ nEndPage = USHRT_MAX;
+}
+
+/*************************************************************************
+|*
+|* SwLayAction::PaintCntnt()
+|*
+|* Beschreibung Je nach Typ wird der Cntnt entsprechend seinen
+|* Veraenderungen ausgegeben bzw. wird die auszugebende Flaeche in der
+|* Region eingetragen.
+|* PaintCntnt: fuellt die Region,
+|*
+|*************************************************************************/
+sal_Bool SwLayAction::PaintWithoutFlys( const SwRect &rRect, const SwCntntFrm *pCnt,
+ const SwPageFrm *pPage )
+{
+ SwRegionRects aTmp( rRect );
+ const SwSortedObjs &rObjs = *pPage->GetSortedObjs();
+ const SwFlyFrm *pSelfFly = pCnt->FindFlyFrm();
+ sal_uInt16 i;
+
+ for ( i = 0; i < rObjs.Count() && aTmp.Count(); ++i )
+ {
+ SdrObject *pO = rObjs[i]->DrawObj();
+ if ( !pO->ISA(SwVirtFlyDrawObj) )
+ continue;
+
+ // OD 2004-01-15 #110582# - do not consider invisible objects
+ const IDocumentDrawModelAccess* pIDDMA = pPage->GetFmt()->getIDocumentDrawModelAccess();
+ if ( !pIDDMA->IsVisibleLayerId( pO->GetLayer() ) )
+ {
+ continue;
+ }
+
+ SwFlyFrm *pFly = ((SwVirtFlyDrawObj*)pO)->GetFlyFrm();
+
+ if ( pFly == pSelfFly || !rRect.IsOver( pFly->Frm() ) )
+ continue;
+
+ if ( pSelfFly && pSelfFly->IsLowerOf( pFly ) )
+ continue;
+
+ if ( pFly->GetVirtDrawObj()->GetLayer() == pIDDMA->GetHellId() )
+ continue;
+
+ if ( pSelfFly )
+ {
+ const SdrObject *pTmp = pSelfFly->GetVirtDrawObj();
+ if ( pO->GetLayer() == pTmp->GetLayer() )
+ {
+ if ( pO->GetOrdNumDirect() < pTmp->GetOrdNumDirect() )
+ //Im gleichen Layer werden nur obenliegende beachtet.
+ continue;
+ }
+ else
+ {
+ const sal_Bool bLowerOfSelf = pFly->IsLowerOf( pSelfFly );
+ if ( !bLowerOfSelf && !pFly->GetFmt()->GetOpaque().GetValue() )
+ //Aus anderem Layer interessieren uns nur nicht transparente
+ //oder innenliegende
+ continue;
+ }
+ }
+
+ /// OD 19.08.2002 #99657#
+ /// Fly frame without a lower have to be subtracted from paint region.
+ /// For checking, if fly frame contains transparent graphic or
+ /// has surrounded contour, assure that fly frame has a lower
+ if ( pFly->Lower() &&
+ pFly->Lower()->IsNoTxtFrm() &&
+ ( ((SwNoTxtFrm*)pFly->Lower())->IsTransparent() ||
+ pFly->GetFmt()->GetSurround().IsContour() )
+ )
+ {
+ continue;
+ }
+
+ /// OD 19.08.2002 #99657#
+ /// Region of a fly frame with transparent background or a transparent
+ /// shadow have not to be subtracted from paint region
+ if ( pFly->IsBackgroundTransparent() ||
+ pFly->IsShadowTransparent() )
+ {
+ continue;
+ }
+
+ aTmp -= pFly->Frm();
+ }
+
+ sal_Bool bRetPaint = sal_False;
+ const SwRect *pData = aTmp.GetData();
+ for ( i = 0; i < aTmp.Count(); ++pData, ++i )
+ bRetPaint |= pImp->GetShell()->AddPaintRect( *pData );
+ return bRetPaint;
+}
+
+inline sal_Bool SwLayAction::_PaintCntnt( const SwCntntFrm *pCntnt,
+ const SwPageFrm *pPage,
+ const SwRect &rRect )
+{
+ if ( rRect.HasArea() )
+ {
+ if ( pPage->GetSortedObjs() )
+ return PaintWithoutFlys( rRect, pCntnt, pPage );
+ else
+ return pImp->GetShell()->AddPaintRect( rRect );
+ }
+ return sal_False;
+}
+
+void SwLayAction::PaintCntnt( const SwCntntFrm *pCnt,
+ const SwPageFrm *pPage,
+ const SwRect &rOldRect,
+ long nOldBottom )
+{
+ SWRECTFN( pCnt )
+
+ if ( pCnt->IsCompletePaint() || !pCnt->IsTxtFrm() )
+ {
+ SwRect aPaint( pCnt->PaintArea() );
+ if ( !_PaintCntnt( pCnt, pPage, aPaint ) )
+ pCnt->ResetCompletePaint();
+ }
+ else
+ {
+ // paint the area between printing bottom and frame bottom and
+ // the area left and right beside the frame, if its height changed.
+ long nOldHeight = (rOldRect.*fnRect->fnGetHeight)();
+ long nNewHeight = (pCnt->Frm().*fnRect->fnGetHeight)();
+ const bool bHeightDiff = nOldHeight != nNewHeight;
+ if( bHeightDiff )
+ {
+ // OD 05.11.2002 #94454# - consider whole potential paint area.
+ //SwRect aDrawRect( pCnt->UnionFrm( sal_True ) );
+ SwRect aDrawRect( pCnt->PaintArea() );
+ if( nOldHeight > nNewHeight )
+ nOldBottom = (pCnt->*fnRect->fnGetPrtBottom)();
+ (aDrawRect.*fnRect->fnSetTop)( nOldBottom );
+ _PaintCntnt( pCnt, pPage, aDrawRect );
+ }
+ // paint content area
+ SwRect aPaintRect = static_cast<SwTxtFrm*>(const_cast<SwCntntFrm*>(pCnt))->Paint();
+ _PaintCntnt( pCnt, pPage, aPaintRect );
+ }
+
+ if ( pCnt->IsRetouche() && !pCnt->GetNext() )
+ {
+ const SwFrm *pTmp = pCnt;
+ if( pCnt->IsInSct() )
+ {
+ const SwSectionFrm* pSct = pCnt->FindSctFrm();
+ if( pSct->IsRetouche() && !pSct->GetNext() )
+ pTmp = pSct;
+ }
+ SwRect aRect( pTmp->GetUpper()->PaintArea() );
+ (aRect.*fnRect->fnSetTop)( (pTmp->*fnRect->fnGetPrtBottom)() );
+ if ( !_PaintCntnt( pCnt, pPage, aRect ) )
+ pCnt->ResetRetouche();
+ }
+}
+
+/*************************************************************************
+|*
+|* SwLayAction::SwLayAction()
+|*
+|*************************************************************************/
+SwLayAction::SwLayAction( SwRootFrm *pRt, SwViewImp *pI ) :
+ pRoot( pRt ),
+ pImp( pI ),
+ pOptTab( 0 ),
+ pWait( 0 ),
+ pProgress(NULL),
+ nPreInvaPage( USHRT_MAX ),
+ nStartTicks( Ticks() ),
+ nInputType( 0 ),
+ nEndPage( USHRT_MAX ),
+ nCheckPageNum( USHRT_MAX )
+{
+ bPaintExtraData = ::IsExtraData( pImp->GetShell()->GetDoc() );
+ bPaint = bComplete = bWaitAllowed = bCheckPages = sal_True;
+ bInput = bAgain = bNextCycle = bCalcLayout = bIdle = bReschedule =
+ bUpdateExpFlds = bBrowseActionStop = bActionInProgress = sal_False;
+ // OD 14.04.2003 #106346# - init new flag <mbFormatCntntOnInterrupt>.
+ mbFormatCntntOnInterrupt = sal_False;
+
+ pImp->pLayAct = this; //Anmelden
+}
+
+SwLayAction::~SwLayAction()
+{
+ OSL_ENSURE( !pWait, "Wait object not destroyed" );
+ pImp->pLayAct = 0; //Abmelden
+}
+
+/*************************************************************************
+|*
+|* SwLayAction::Reset()
+|*
+|*************************************************************************/
+void SwLayAction::Reset()
+{
+ pOptTab = 0;
+ nStartTicks = Ticks();
+ nInputType = 0;
+ nEndPage = nPreInvaPage = nCheckPageNum = USHRT_MAX;
+ bPaint = bComplete = bWaitAllowed = bCheckPages = sal_True;
+ bInput = bAgain = bNextCycle = bCalcLayout = bIdle = bReschedule =
+ bUpdateExpFlds = bBrowseActionStop = sal_False;
+}
+
+/*************************************************************************
+|*
+|* SwLayAction::RemoveEmptyBrowserPages()
+|*
+|*************************************************************************/
+
+sal_Bool SwLayAction::RemoveEmptyBrowserPages()
+{
+ //Beim umschalten vom normalen in den Browsermodus bleiben u.U. einige
+ //unangenehm lange stehen. Diese beseiten wir mal schnell.
+ sal_Bool bRet = sal_False;
+ const ViewShell *pSh = pRoot->GetCurrShell();
+ if( pSh && pSh->GetViewOptions()->getBrowseMode() )
+ {
+ SwPageFrm *pPage = (SwPageFrm*)pRoot->Lower();
+ do
+ {
+ if ( (pPage->GetSortedObjs() && pPage->GetSortedObjs()->Count()) ||
+ pPage->ContainsCntnt() )
+ pPage = (SwPageFrm*)pPage->GetNext();
+ else
+ {
+ bRet = sal_True;
+ SwPageFrm *pDel = pPage;
+ pPage = (SwPageFrm*)pPage->GetNext();
+ pDel->Cut();
+ delete pDel;
+ }
+ } while ( pPage );
+ }
+ return bRet;
+}
+
+
+/*************************************************************************
+|*
+|* SwLayAction::Action()
+|*
+|*************************************************************************/
+void SwLayAction::Action()
+{
+ bActionInProgress = sal_True;
+
+ //TurboMode? Disqualifiziert fuer Idle-Format.
+ if ( IsPaint() && !IsIdle() && TurboAction() )
+ {
+ delete pWait, pWait = 0;
+ pRoot->ResetTurboFlag();
+ bActionInProgress = sal_False;
+ pRoot->DeleteEmptySct();
+ return;
+ }
+ else if ( pRoot->GetTurbo() )
+ {
+ pRoot->DisallowTurbo();
+ const SwFrm *pFrm = pRoot->GetTurbo();
+ pRoot->ResetTurbo();
+ pFrm->InvalidatePage();
+ }
+ pRoot->DisallowTurbo();
+
+ if ( IsCalcLayout() )
+ SetCheckPages( sal_False );
+
+ InternalAction();
+ bAgain |= RemoveEmptyBrowserPages();
+ while ( IsAgain() )
+ {
+ bAgain = bNextCycle = sal_False;
+ InternalAction();
+ bAgain |= RemoveEmptyBrowserPages();
+ }
+ pRoot->DeleteEmptySct();
+
+ delete pWait, pWait = 0;
+
+ //Turbo-Action ist auf jedenfall wieder erlaubt.
+ pRoot->ResetTurboFlag();
+ pRoot->ResetTurbo();
+
+ SetCheckPages( sal_True );
+
+ bActionInProgress = sal_False;
+}
+
+SwPageFrm* SwLayAction::CheckFirstVisPage( SwPageFrm *pPage )
+{
+ SwCntntFrm *pCnt = pPage->FindFirstBodyCntnt();
+ SwCntntFrm *pChk = pCnt;
+ sal_Bool bPageChgd = sal_False;
+ while ( pCnt && pCnt->IsFollow() )
+ pCnt = static_cast<SwCntntFrm*>(pCnt)->FindMaster();
+ if ( pCnt && pChk != pCnt )
+ { bPageChgd = sal_True;
+ pPage = pCnt->FindPageFrm();
+ }
+
+ if ( pPage->GetFmt()->GetDoc()->GetFtnIdxs().Count() )
+ {
+ SwFtnContFrm *pCont = pPage->FindFtnCont();
+ if ( pCont )
+ {
+ pCnt = pCont->ContainsCntnt();
+ pChk = pCnt;
+ while ( pCnt && pCnt->IsFollow() )
+ pCnt = (SwCntntFrm*)pCnt->FindPrev();
+ if ( pCnt && pCnt != pChk )
+ {
+ if ( bPageChgd )
+ {
+ //Die 'oberste' Seite benutzten.
+ SwPageFrm *pTmp = pCnt->FindPageFrm();
+ if ( pPage->GetPhyPageNum() > pTmp->GetPhyPageNum() )
+ pPage = pTmp;
+ }
+ else
+ pPage = pCnt->FindPageFrm();
+ }
+ }
+ }
+ return pPage;
+}
+
+// OD 2004-05-12 #i28701#
+// --> OD 2004-11-03 #i114798# - unlock position on start and end of page
+// layout process.
+class NotifyLayoutOfPageInProgress
+{
+ private:
+ SwPageFrm& mrPageFrm;
+
+ void _UnlockPositionOfObjs()
+ {
+ SwSortedObjs* pObjs = mrPageFrm.GetSortedObjs();
+ if ( pObjs )
+ {
+ sal_uInt32 i = 0;
+ for ( ; i < pObjs->Count(); ++i )
+ {
+ SwAnchoredObject* pObj = (*pObjs)[i];
+ pObj->UnlockPosition();
+ }
+ }
+ }
+ public:
+ NotifyLayoutOfPageInProgress( SwPageFrm& _rPageFrm )
+ : mrPageFrm( _rPageFrm )
+ {
+ _UnlockPositionOfObjs();
+ _rPageFrm.SetLayoutInProgress( true );
+ }
+ ~NotifyLayoutOfPageInProgress()
+ {
+ mrPageFrm.SetLayoutInProgress( false );
+ _UnlockPositionOfObjs();
+ }
+};
+// <--
+
+void SwLayAction::InternalAction()
+{
+ OSL_ENSURE( pRoot->Lower()->IsPageFrm(), ":-( Keine Seite unterhalb der Root.");
+
+ pRoot->Calc();
+
+ //Die erste ungueltige bzw. zu formatierende Seite ermitteln.
+ //Bei einer Complete-Action ist es die erste ungueltige; mithin ist die
+ //erste zu formatierende Seite diejenige Seite mit der Numemr eins.
+ //Bei einer Luegen-Formatierung ist die Nummer der erste Seite die Nummer
+ //der ersten Sichtbaren Seite.
+ SwPageFrm *pPage = IsComplete() ? (SwPageFrm*)pRoot->Lower() :
+ pImp->GetFirstVisPage();
+ if ( !pPage )
+ pPage = (SwPageFrm*)pRoot->Lower();
+
+ //Wenn ein "Erster-Fliess-Cntnt" innerhalb der der ersten sichtbaren Seite
+ //ein Follow ist, so schalten wir die Seite zurueck auf den Ur-Master dieses
+ //Cntnt's
+ if ( !IsComplete() )
+ pPage = CheckFirstVisPage( pPage );
+ sal_uInt16 nFirstPageNum = pPage->GetPhyPageNum();
+
+ while ( pPage && !pPage->IsInvalid() && !pPage->IsInvalidFly() )
+ pPage = (SwPageFrm*)pPage->GetNext();
+
+ IDocumentLayoutAccess *pLayoutAccess = pRoot->GetFmt()->getIDocumentLayoutAccess();
+ sal_Bool bNoLoop = pPage ? SwLayouter::StartLoopControl( pRoot->GetFmt()->GetDoc(), pPage ) : sal_False;
+ sal_uInt16 nPercentPageNum = 0;
+ while ( (pPage && !IsInterrupt()) || nCheckPageNum != USHRT_MAX )
+ {
+ if ( !pPage && nCheckPageNum != USHRT_MAX &&
+ (!pPage || pPage->GetPhyPageNum() >= nCheckPageNum) )
+ {
+ if ( !pPage || pPage->GetPhyPageNum() > nCheckPageNum )
+ {
+ SwPageFrm *pPg = (SwPageFrm*)pRoot->Lower();
+ while ( pPg && pPg->GetPhyPageNum() < nCheckPageNum )
+ pPg = (SwPageFrm*)pPg->GetNext();
+ if ( pPg )
+ pPage = pPg;
+ if ( !pPage )
+ break;
+ }
+ SwPageFrm *pTmp = pPage->GetPrev() ?
+ (SwPageFrm*)pPage->GetPrev() : pPage;
+ SetCheckPages( sal_True );
+ SwFrm::CheckPageDescs( pPage );
+ SetCheckPages( sal_False );
+ nCheckPageNum = USHRT_MAX;
+ pPage = pTmp;
+ continue;
+ }
+
+ if ( nEndPage != USHRT_MAX && pPage->GetPhyPageNum() > nPercentPageNum )
+ {
+ nPercentPageNum = pPage->GetPhyPageNum();
+ ::SetProgressState( nPercentPageNum, pImp->GetShell()->GetDoc()->GetDocShell());
+ }
+ pOptTab = 0;
+ //Kein ShortCut fuer Idle oder CalcLayout
+ if ( !IsIdle() && !IsComplete() && IsShortCut( pPage ) )
+ {
+ pRoot->DeleteEmptySct();
+ XCHECKPAGE;
+ if ( !IsInterrupt() &&
+ (pRoot->IsSuperfluous() || pRoot->IsAssertFlyPages()) )
+ {
+ if ( pRoot->IsAssertFlyPages() )
+ pRoot->AssertFlyPages();
+ if ( pRoot->IsSuperfluous() )
+ {
+ sal_Bool bOld = IsAgain();
+ pRoot->RemoveSuperfluous();
+ bAgain = bOld;
+ }
+ if ( IsAgain() )
+ {
+ if( bNoLoop )
+ pLayoutAccess->GetLayouter()->EndLoopControl();
+ return;
+ }
+ pPage = (SwPageFrm*)pRoot->Lower();
+ while ( pPage && !pPage->IsInvalid() && !pPage->IsInvalidFly() )
+ pPage = (SwPageFrm*)pPage->GetNext();
+ while ( pPage && pPage->GetNext() &&
+ pPage->GetPhyPageNum() < nFirstPageNum )
+ pPage = (SwPageFrm*)pPage->GetNext();
+ continue;
+ }
+ break;
+ }
+ else
+ {
+ pRoot->DeleteEmptySct();
+ XCHECKPAGE;
+
+ // OD 2004-05-12 #i28701# - scope for instance of class
+ // <NotifyLayoutOfPageInProgress>
+ {
+ NotifyLayoutOfPageInProgress aLayoutOfPageInProgress( *pPage );
+
+ while ( !IsInterrupt() && !IsNextCycle() &&
+ ((IS_FLYS && IS_INVAFLY) || pPage->IsInvalid()) )
+ {
+ // OD 2004-05-10 #i28701#
+ SwObjectFormatter::FormatObjsAtFrm( *pPage, *pPage, this );
+ if ( !IS_FLYS )
+ {
+ //Wenn keine Flys (mehr) da sind, sind die Flags
+ //mehr als fluessig.
+ pPage->ValidateFlyLayout();
+ pPage->ValidateFlyCntnt();
+ }
+ // OD 2004-05-10 #i28701# - change condition
+ while ( !IsInterrupt() && !IsNextCycle() &&
+ ( pPage->IsInvalid() ||
+ (IS_FLYS && IS_INVAFLY) ) )
+ {
+ PROTOCOL( pPage, PROT_FILE_INIT, 0, 0)
+ XCHECKPAGE;
+
+ // FME 2007-08-30 #i81146# new loop control
+ sal_uInt16 nLoopControlRuns_1 = 0;
+ const sal_uInt16 nLoopControlMax = 20;
+
+ while ( !IsNextCycle() && pPage->IsInvalidLayout() )
+ {
+ pPage->ValidateLayout();
+
+ if ( ++nLoopControlRuns_1 > nLoopControlMax )
+ {
+#if OSL_DEBUG_LEVEL > 1
+ OSL_FAIL( "LoopControl_1 in SwLayAction::InternalAction" );
+
+#endif
+ break;
+ }
+
+ FormatLayout( pPage );
+ XCHECKPAGE;
+ }
+ // OD 2004-05-10 #i28701# - change condition
+ if ( !IsNextCycle() &&
+ ( pPage->IsInvalidCntnt() ||
+ (IS_FLYS && IS_INVAFLY) ) )
+ {
+ pPage->ValidateFlyInCnt();
+ pPage->ValidateCntnt();
+ // --> OD 2004-05-10 #i28701#
+ pPage->ValidateFlyLayout();
+ pPage->ValidateFlyCntnt();
+ // <--
+ if ( !FormatCntnt( pPage ) )
+ {
+ XCHECKPAGE;
+ pPage->InvalidateCntnt();
+ pPage->InvalidateFlyInCnt();
+ // --> OD 2004-05-10 #i28701#
+ pPage->InvalidateFlyLayout();
+ pPage->InvalidateFlyCntnt();
+ // <--
+ if ( IsBrowseActionStop() )
+ bInput = sal_True;
+ }
+ }
+ if( bNoLoop )
+ pLayoutAccess->GetLayouter()->LoopControl( pPage, LOOP_PAGE );
+ }
+ }
+ } // end of scope for instance of class <NotifyLayoutOfPageInProgress>
+
+
+ //Eine vorige Seite kann wieder invalid sein.
+ XCHECKPAGE;
+ if ( !IS_FLYS )
+ {
+ //Wenn keine Flys (mehr) da sind, sind die Flags
+ //mehr als fluessig.
+ pPage->ValidateFlyLayout();
+ pPage->ValidateFlyCntnt();
+ }
+ if ( !IsInterrupt() )
+ {
+ SetNextCycle( sal_False );
+
+ if ( nPreInvaPage != USHRT_MAX )
+ {
+ if( !IsComplete() && nPreInvaPage + 2 < nFirstPageNum )
+ {
+ pImp->SetFirstVisPageInvalid();
+ SwPageFrm *pTmpPage = pImp->GetFirstVisPage();
+ nFirstPageNum = pTmpPage->GetPhyPageNum();
+ if( nPreInvaPage < nFirstPageNum )
+ {
+ nPreInvaPage = nFirstPageNum;
+ pPage = pTmpPage;
+ }
+ }
+ while ( pPage->GetPrev() && pPage->GetPhyPageNum() > nPreInvaPage )
+ pPage = (SwPageFrm*)pPage->GetPrev();
+ nPreInvaPage = USHRT_MAX;
+ }
+
+ while ( pPage->GetPrev() &&
+ ( ((SwPageFrm*)pPage->GetPrev())->IsInvalid() ||
+ ( ((SwPageFrm*)pPage->GetPrev())->GetSortedObjs() &&
+ ((SwPageFrm*)pPage->GetPrev())->IsInvalidFly())) &&
+ (((SwPageFrm*)pPage->GetPrev())->GetPhyPageNum() >=
+ nFirstPageNum) )
+ {
+ pPage = (SwPageFrm*)pPage->GetPrev();
+ }
+
+ //Weiter bis zur naechsten invaliden Seite.
+ while ( pPage && !pPage->IsInvalid() &&
+ (!IS_FLYS || !IS_INVAFLY) )
+ {
+ pPage = (SwPageFrm*)pPage->GetNext();
+ }
+ if( bNoLoop )
+ pLayoutAccess->GetLayouter()->LoopControl( pPage, LOOP_PAGE );
+ }
+ CheckIdleEnd();
+ }
+ if ( !pPage && !IsInterrupt() &&
+ (pRoot->IsSuperfluous() || pRoot->IsAssertFlyPages()) )
+ {
+ if ( pRoot->IsAssertFlyPages() )
+ pRoot->AssertFlyPages();
+ if ( pRoot->IsSuperfluous() )
+ {
+ sal_Bool bOld = IsAgain();
+ pRoot->RemoveSuperfluous();
+ bAgain = bOld;
+ }
+ if ( IsAgain() )
+ {
+ if( bNoLoop )
+ pLayoutAccess->GetLayouter()->EndLoopControl();
+ return;
+ }
+ pPage = (SwPageFrm*)pRoot->Lower();
+ while ( pPage && !pPage->IsInvalid() && !pPage->IsInvalidFly() )
+ pPage = (SwPageFrm*)pPage->GetNext();
+ while ( pPage && pPage->GetNext() &&
+ pPage->GetPhyPageNum() < nFirstPageNum )
+ pPage = (SwPageFrm*)pPage->GetNext();
+ }
+ }
+ if ( IsInterrupt() && pPage )
+ {
+ //Wenn ein Input anliegt wollen wir keinen Inhalt mehr Formatieren,
+ //Das Layout muessen wir aber schon in Ordnung bringen.
+ //Andernfalls kann folgende Situation auftreten (Bug: 3244):
+ //Am Ende des Absatz der letzten Seite wird Text eingegeben, so das
+ //der Absatz einen Follow fuer die nachste Seite erzeugt, ausserdem
+ //wird gleich schnell weitergetippt - Es liegt waehrend der
+ //Verarbeitung ein Input an. Der Absatz auf der neuen Seite wurde
+ //bereits anformatiert, die neue Seite ist Formatiert und steht
+ //auf CompletePaint, hat sich aber noch nicht im Auszugebenden Bereich
+ //eingetragen. Es wird gepaintet, das CompletePaint der Seite wird
+ //zurueckgesetzt weil der neue Absatz sich bereits eingetragen hatte,
+ //aber die Raender der Seite werden nicht gepaintet. Naja, bei der
+ //zwangslaeufig auftretenden naechsten LayAction traegt sich die Seite
+ //nicht mehr ein, weil ihre (LayoutFrm-)Flags bereits zurueckgesetzt
+ //wurden -- Der Rand der Seite wird nie gepaintet.
+ SwPageFrm *pPg = pPage;
+ XCHECKPAGE;
+ const SwRect &rVis = pImp->GetShell()->VisArea();
+
+ while( pPg && pPg->Frm().Bottom() < rVis.Top() )
+ pPg = (SwPageFrm*)pPg->GetNext();
+ if( pPg != pPage )
+ pPg = pPg ? (SwPageFrm*)pPg->GetPrev() : pPage;
+
+ // OD 14.04.2003 #106346# - set flag for interrupt content formatting
+ mbFormatCntntOnInterrupt = IsInput() && !IsStopPrt();
+ long nBottom = rVis.Bottom();
+ // --> OD 2005-02-15 #i42586# - format current page, if idle action is active
+ // This is an optimization for the case that the interrupt is created by
+ // the move of a form control object, which is represented by a window.
+ while ( pPg && ( pPg->Frm().Top() < nBottom ||
+ ( IsIdle() && pPg == pPage ) ) )
+ // <--
+ {
+ // --> OD 2004-10-11 #i26945# - follow-up of #i28701#
+ NotifyLayoutOfPageInProgress aLayoutOfPageInProgress( *pPg );
+
+ XCHECKPAGE;
+
+ // FME 2007-08-30 #i81146# new loop control
+ sal_uInt16 nLoopControlRuns_2 = 0;
+ const sal_uInt16 nLoopControlMax = 20;
+
+ // OD 14.04.2003 #106346# - special case: interrupt content formatting
+ // --> OD 2004-07-08 #i28701# - conditions, introduced by #106346#,
+ // are incorrect (marcos IS_FLYS and IS_INVAFLY only works for <pPage>)
+ // and are too strict.
+ // --> OD 2005-06-09 #i50432# - adjust interrupt formatting to
+ // normal page formatting - see above.
+ while ( ( mbFormatCntntOnInterrupt &&
+ ( pPg->IsInvalid() ||
+ ( pPg->GetSortedObjs() && pPg->IsInvalidFly() ) ) ) ||
+ ( !mbFormatCntntOnInterrupt && pPg->IsInvalidLayout() ) )
+ {
+ XCHECKPAGE;
+ // --> OD 2005-06-09 #i50432# - format also at-page anchored objects
+ SwObjectFormatter::FormatObjsAtFrm( *pPg, *pPg, this );
+ // <--
+ // --> OD 2005-06-09 #i50432#
+ if ( !pPg->GetSortedObjs() )
+ {
+ pPg->ValidateFlyLayout();
+ pPg->ValidateFlyCntnt();
+ }
+ // <--
+
+ // FME 2007-08-30 #i81146# new loop control
+ sal_uInt16 nLoopControlRuns_3 = 0;
+
+ while ( pPg->IsInvalidLayout() )
+ {
+ pPg->ValidateLayout();
+
+ if ( ++nLoopControlRuns_3 > nLoopControlMax )
+ {
+#if OSL_DEBUG_LEVEL > 1
+ OSL_FAIL( "LoopControl_3 in Interrupt formatting in SwLayAction::InternalAction" );
+#endif
+ break;
+ }
+
+ FormatLayout( pPg );
+ XCHECKPAGE;
+ }
+
+ // --> OD 2005-06-09 #i50432#
+ if ( mbFormatCntntOnInterrupt &&
+ ( pPg->IsInvalidCntnt() ||
+ ( pPg->GetSortedObjs() && pPg->IsInvalidFly() ) ) )
+ // <--
+ {
+ pPg->ValidateFlyInCnt();
+ pPg->ValidateCntnt();
+ // --> OD 2004-05-10 #i26945# - follow-up of fix #117736#
+ pPg->ValidateFlyLayout();
+ pPg->ValidateFlyCntnt();
+ // <--
+
+ if ( ++nLoopControlRuns_2 > nLoopControlMax )
+ {
+#if OSL_DEBUG_LEVEL > 1
+ OSL_FAIL( "LoopControl_2 in Interrupt formatting in SwLayAction::InternalAction" );
+#endif
+ break;
+ }
+
+ if ( !FormatCntnt( pPg ) )
+ {
+ XCHECKPAGE;
+ pPg->InvalidateCntnt();
+ pPg->InvalidateFlyInCnt();
+ // --> OD 2004-05-10 #i26945# - follow-up of fix #117736#
+ pPg->InvalidateFlyLayout();
+ pPg->InvalidateFlyCntnt();
+ // <--
+ }
+ // --> OD 2005-04-06 #i46807# - we are statisfied, if the
+ // content is formatted once complete.
+ else
+ {
+ break;
+ }
+ // <--
+ }
+ }
+ // <--
+ pPg = (SwPageFrm*)pPg->GetNext();
+ }
+ // OD 14.04.2003 #106346# - reset flag for special interrupt content formatting.
+ mbFormatCntntOnInterrupt = sal_False;
+ }
+ pOptTab = 0;
+ if( bNoLoop )
+ pLayoutAccess->GetLayouter()->EndLoopControl();
+}
+/*************************************************************************
+|*
+|* SwLayAction::TurboAction(), _TurboAction()
+|*
+|*************************************************************************/
+sal_Bool SwLayAction::_TurboAction( const SwCntntFrm *pCnt )
+{
+
+ const SwPageFrm *pPage = 0;
+ if ( !pCnt->IsValid() || pCnt->IsCompletePaint() || pCnt->IsRetouche() )
+ {
+ const SwRect aOldRect( pCnt->UnionFrm( sal_True ) );
+ const long nOldBottom = pCnt->Frm().Top() + pCnt->Prt().Bottom();
+ pCnt->Calc();
+ if ( pCnt->Frm().Bottom() < aOldRect.Bottom() )
+ pCnt->SetRetouche();
+
+ pPage = pCnt->FindPageFrm();
+ PaintCntnt( pCnt, pPage, aOldRect, nOldBottom );
+
+ if ( !pCnt->GetValidLineNumFlag() && pCnt->IsTxtFrm() )
+ {
+ const sal_uLong nAllLines = ((SwTxtFrm*)pCnt)->GetAllLines();
+ ((SwTxtFrm*)pCnt)->RecalcAllLines();
+ if ( nAllLines != ((SwTxtFrm*)pCnt)->GetAllLines() )
+ {
+ if ( IsPaintExtraData() )
+ pImp->GetShell()->AddPaintRect( pCnt->Frm() );
+ //Damit die restlichen LineNums auf der Seite bereichnet werden
+ //und nicht hier abgebrochen wird.
+ //Das im RecalcAllLines zu erledigen waere teuer, weil dort
+ //auch in unnoetigen Faellen (normale Action) auch immer die
+ //Seite benachrichtigt werden muesste.
+ const SwCntntFrm *pNxt = pCnt->GetNextCntntFrm();
+ while ( pNxt &&
+ (pNxt->IsInTab() || pNxt->IsInDocBody() != pCnt->IsInDocBody()) )
+ pNxt = pNxt->GetNextCntntFrm();
+ if ( pNxt )
+ pNxt->InvalidatePage();
+ }
+ return sal_False;
+ }
+
+ if ( pPage->IsInvalidLayout() || (IS_FLYS && IS_INVAFLY) )
+ return sal_False;
+ }
+ if ( !pPage )
+ pPage = pCnt->FindPageFrm();
+
+ // OD 2004-05-10 #i28701# - format floating screen objects at content frame.
+ if ( pCnt->IsTxtFrm() &&
+ !SwObjectFormatter::FormatObjsAtFrm( *(const_cast<SwCntntFrm*>(pCnt)),
+ *pPage, this ) )
+ {
+ return sal_False;
+ }
+
+ if ( pPage->IsInvalidCntnt() )
+ return sal_False;
+ return sal_True;
+}
+
+sal_Bool SwLayAction::TurboAction()
+{
+ sal_Bool bRet = sal_True;
+
+ if ( pRoot->GetTurbo() )
+ {
+ if ( !_TurboAction( pRoot->GetTurbo() ) )
+ {
+ CheckIdleEnd();
+ bRet = sal_False;
+ }
+ pRoot->ResetTurbo();
+ }
+ else
+ bRet = sal_False;
+ return bRet;
+}
+/*************************************************************************
+|*
+|* SwLayAction::IsShortCut()
+|*
+|* Beschreibung: Liefert ein True, wenn die Seite vollstaendig unter
+|* oder rechts neben dem sichbaren Bereich liegt.
+|* Es kann passieren, dass sich die Verhaeltnisse derart aendern, dass
+|* die Verarbeitung (des Aufrufers!) mit der Vorgaengerseite der
+|* uebergebenen Seite weitergefuehrt werden muss. Der Paramter wird also
+|* ggf. veraendert!
+|* Fuer den BrowseMode kann auch dann der ShortCut aktiviert werden,
+|* wenn der ungueltige Inhalt der Seite unterhalb des sichbaren
+|* bereiches liegt.
+|*
+|*************************************************************************/
+static bool lcl_IsInvaLay( const SwFrm *pFrm, long nBottom )
+{
+ if (
+ !pFrm->IsValid() ||
+ (pFrm->IsCompletePaint() && ( pFrm->Frm().Top() < nBottom ) )
+ )
+ {
+ return true;
+ }
+ return false;
+}
+
+static const SwFrm *lcl_FindFirstInvaLay( const SwFrm *pFrm, long nBottom )
+{
+ OSL_ENSURE( pFrm->IsLayoutFrm(), "FindFirstInvaLay, no LayFrm" );
+
+ if (lcl_IsInvaLay(pFrm, nBottom))
+ return pFrm;
+ pFrm = ((SwLayoutFrm*)pFrm)->Lower();
+ while ( pFrm )
+ {
+ if ( pFrm->IsLayoutFrm() )
+ {
+ if (lcl_IsInvaLay(pFrm, nBottom))
+ return pFrm;
+ const SwFrm *pTmp;
+ if ( 0 != (pTmp = lcl_FindFirstInvaLay( pFrm, nBottom )) )
+ return pTmp;
+ }
+ pFrm = pFrm->GetNext();
+ }
+ return 0;
+}
+
+static const SwFrm *lcl_FindFirstInvaCntnt( const SwLayoutFrm *pLay, long nBottom,
+ const SwCntntFrm *pFirst )
+{
+ const SwCntntFrm *pCnt = pFirst ? pFirst->GetNextCntntFrm() :
+ pLay->ContainsCntnt();
+ while ( pCnt )
+ {
+ if ( !pCnt->IsValid() || pCnt->IsCompletePaint() )
+ {
+ if ( pCnt->Frm().Top() <= nBottom )
+ return pCnt;
+ }
+
+ if ( pCnt->GetDrawObjs() )
+ {
+ const SwSortedObjs &rObjs = *pCnt->GetDrawObjs();
+ for ( sal_uInt16 i = 0; i < rObjs.Count(); ++i )
+ {
+ const SwAnchoredObject* pObj = rObjs[i];
+ if ( pObj->ISA(SwFlyFrm) )
+ {
+ const SwFlyFrm* pFly = static_cast<const SwFlyFrm*>(pObj);
+ if ( pFly->IsFlyInCntFrm() )
+ {
+ if ( ((SwFlyInCntFrm*)pFly)->IsInvalid() ||
+ pFly->IsCompletePaint() )
+ {
+ if ( pFly->Frm().Top() <= nBottom )
+ return pFly;
+ }
+ const SwFrm *pFrm = lcl_FindFirstInvaCntnt( pFly, nBottom, 0 );
+ if ( pFrm && pFrm->Frm().Bottom() <= nBottom )
+ return pFrm;
+ }
+ }
+ }
+ }
+ if ( pCnt->Frm().Top() > nBottom && !pCnt->IsInTab() )
+ return 0;
+ pCnt = pCnt->GetNextCntntFrm();
+ if ( !pLay->IsAnLower( pCnt ) )
+ break;
+ }
+ return 0;
+}
+
+// --> OD 2005-02-21 #i37877# - consider drawing objects
+static const SwAnchoredObject* lcl_FindFirstInvaObj( const SwPageFrm* _pPage,
+ long _nBottom )
+{
+ OSL_ENSURE( _pPage->GetSortedObjs(), "FindFirstInvaObj, no Objs" );
+
+ for ( sal_uInt16 i = 0; i < _pPage->GetSortedObjs()->Count(); ++i )
+ {
+ const SwAnchoredObject* pObj = (*_pPage->GetSortedObjs())[i];
+ if ( pObj->ISA(SwFlyFrm) )
+ {
+ const SwFlyFrm* pFly = static_cast<const SwFlyFrm*>(pObj);
+ if ( pFly->Frm().Top() <= _nBottom )
+ {
+ if ( pFly->IsInvalid() || pFly->IsCompletePaint() )
+ return pFly;
+
+ const SwFrm* pTmp;
+ if ( 0 != (pTmp = lcl_FindFirstInvaCntnt( pFly, _nBottom, 0 )) &&
+ pTmp->Frm().Top() <= _nBottom )
+ return pFly;
+ }
+ }
+ else if ( pObj->ISA(SwAnchoredDrawObject) )
+ {
+ if ( !static_cast<const SwAnchoredDrawObject*>(pObj)->IsValidPos() )
+ {
+ return pObj;
+ }
+ }
+ }
+ return 0;
+}
+// <--
+
+sal_Bool SwLayAction::IsShortCut( SwPageFrm *&prPage )
+{
+ sal_Bool bRet = sal_False;
+ const ViewShell *pSh = pRoot->GetCurrShell();
+ const sal_Bool bBrowse = pSh && pSh->GetViewOptions()->getBrowseMode();
+
+ //Wenn die Seite nicht Gueltig ist wird sie schnell formatiert, sonst
+ //gibts nix als Aerger.
+ if ( !prPage->IsValid() )
+ {
+ if ( bBrowse )
+ {
+ /// OD 15.10.2002 #103517# - format complete page
+ /// Thus, loop on all lowers of the page <prPage>, instead of only
+ /// format its first lower.
+ /// NOTE: In online layout (bBrowse == sal_True) a page can contain
+ /// a header frame and/or a footer frame beside the body frame.
+ prPage->Calc();
+ SwFrm* pPageLowerFrm = prPage->Lower();
+ while ( pPageLowerFrm )
+ {
+ pPageLowerFrm->Calc();
+ pPageLowerFrm = pPageLowerFrm->GetNext();
+ }
+ }
+ else
+ FormatLayout( prPage );
+ if ( IsAgain() )
+ return sal_False;
+ }
+
+
+ const SwRect &rVis = pImp->GetShell()->VisArea();
+ if ( (prPage->Frm().Top() >= rVis.Bottom()) ||
+ (prPage->Frm().Left()>= rVis.Right()) )
+ {
+ bRet = sal_True;
+
+ //Jetzt wird es ein bischen unangenehm: Der erste CntntFrm dieser Seite
+ //im Bodytext muss Formatiert werden, wenn er dabei die Seite
+ //wechselt, muss ich nochmal eine Seite zuvor anfangen, denn
+ //es wurde ein PageBreak verarbeitet.
+//Noch unangenehmer: Der naechste CntntFrm ueberhaupt muss
+ //Formatiert werden, denn es kann passieren, dass kurzfristig
+ //leere Seiten existieren (Bsp. Absatz ueber mehrere Seiten
+ //wird geloescht oder verkleinert).
+
+ //Ist fuer den Browser uninteressant, wenn der letzte Cnt davor bereits
+ //nicht mehr sichbar ist.
+
+ const SwPageFrm *p2ndPage = prPage;
+ const SwCntntFrm *pCntnt;
+ const SwLayoutFrm* pBody = p2ndPage->FindBodyCont();
+ if( p2ndPage->IsFtnPage() && pBody )
+ pBody = (SwLayoutFrm*)pBody->GetNext();
+ pCntnt = pBody ? pBody->ContainsCntnt() : 0;
+ while ( p2ndPage && !pCntnt )
+ {
+ p2ndPage = (SwPageFrm*)p2ndPage->GetNext();
+ if( p2ndPage )
+ {
+ pBody = p2ndPage->FindBodyCont();
+ if( p2ndPage->IsFtnPage() && pBody )
+ pBody = (SwLayoutFrm*)pBody->GetNext();
+ pCntnt = pBody ? pBody->ContainsCntnt() : 0;
+ }
+ }
+ if ( pCntnt )
+ {
+ sal_Bool bTstCnt = sal_True;
+ if ( bBrowse )
+ {
+ //Der Cnt davor schon nicht mehr sichtbar?
+ const SwFrm *pLst = pCntnt;
+ if ( pLst->IsInTab() )
+ pLst = pCntnt->FindTabFrm();
+ if ( pLst->IsInSct() )
+ pLst = pCntnt->FindSctFrm();
+ pLst = pLst->FindPrev();
+ if ( pLst &&
+ (pLst->Frm().Top() >= rVis.Bottom() ||
+ pLst->Frm().Left()>= rVis.Right()) )
+ {
+ bTstCnt = sal_False;
+ }
+ }
+
+ if ( bTstCnt )
+ {
+ // --> OD 2004-06-04 #i27756# - check after each frame calculation,
+ // if the content frame has changed the page. If yes, no other
+ // frame calculation is performed
+ bool bPageChg = false;
+
+ if ( pCntnt->IsInSct() )
+ {
+ const SwSectionFrm *pSct = ((SwFrm*)pCntnt)->ImplFindSctFrm();
+ if ( !pSct->IsValid() )
+ {
+ pSct->Calc();
+ pSct->SetCompletePaint();
+ if ( IsAgain() )
+ return sal_False;
+ // --> OD 2004-06-04 #i27756#
+ bPageChg = pCntnt->FindPageFrm() != p2ndPage &&
+ prPage->GetPrev();
+ }
+ }
+
+ if ( !bPageChg && !pCntnt->IsValid() )
+ {
+ pCntnt->Calc();
+ pCntnt->SetCompletePaint();
+ if ( IsAgain() )
+ return sal_False;
+ // --> OD 2004-06-04 #i27756#
+ bPageChg = pCntnt->FindPageFrm() != p2ndPage &&
+ prPage->GetPrev();
+ }
+
+ if ( !bPageChg && pCntnt->IsInTab() )
+ {
+ const SwTabFrm *pTab = ((SwFrm*)pCntnt)->ImplFindTabFrm();
+ if ( !pTab->IsValid() )
+ {
+ pTab->Calc();
+ pTab->SetCompletePaint();
+ if ( IsAgain() )
+ return sal_False;
+ // --> OD 2004-06-04 #i27756#
+ bPageChg = pCntnt->FindPageFrm() != p2ndPage &&
+ prPage->GetPrev();
+ }
+ }
+
+ if ( !bPageChg && pCntnt->IsInSct() )
+ {
+ const SwSectionFrm *pSct = ((SwFrm*)pCntnt)->ImplFindSctFrm();
+ if ( !pSct->IsValid() )
+ {
+ pSct->Calc();
+ pSct->SetCompletePaint();
+ if ( IsAgain() )
+ return sal_False;
+ // --> OD 2004-06-04 #i27756#
+ bPageChg = pCntnt->FindPageFrm() != p2ndPage &&
+ prPage->GetPrev();
+ }
+ }
+
+ // --> OD 2004-06-04 #i27756#
+ if ( bPageChg )
+ {
+ bRet = sal_False;
+ const SwPageFrm* pTmp = pCntnt->FindPageFrm();
+ if ( pTmp->GetPhyPageNum() < prPage->GetPhyPageNum() &&
+ pTmp->IsInvalid() )
+ {
+ prPage = (SwPageFrm*)pTmp;
+ }
+ else
+ {
+ prPage = (SwPageFrm*)prPage->GetPrev();
+ }
+ }
+ // --> OD 2005-04-25 #121980# - no shortcut, if at previous page
+ // an anchored object is registered, whose anchor is <pCntnt>.
+ else if ( prPage->GetPrev() &&
+ static_cast<SwPageFrm*>(prPage->GetPrev())->GetSortedObjs() )
+ {
+ SwSortedObjs* pObjs =
+ static_cast<SwPageFrm*>(prPage->GetPrev())->GetSortedObjs();
+ if ( pObjs )
+ {
+ sal_uInt32 i = 0;
+ for ( ; i < pObjs->Count(); ++i )
+ {
+ SwAnchoredObject* pObj = (*pObjs)[i];
+ if ( pObj->GetAnchorFrmContainingAnchPos() == pCntnt )
+ {
+ bRet = sal_False;
+ break;
+ }
+ }
+ }
+ }
+ // <--
+ }
+ }
+ }
+
+ if ( !bRet && bBrowse )
+ {
+ const long nBottom = rVis.Bottom();
+ const SwAnchoredObject* pObj( 0L );
+ if ( prPage->GetSortedObjs() &&
+ (prPage->IsInvalidFlyLayout() || prPage->IsInvalidFlyCntnt()) &&
+ 0 != (pObj = lcl_FindFirstInvaObj( prPage, nBottom )) &&
+ pObj->GetObjRect().Top() <= nBottom )
+ {
+ return sal_False;
+ }
+ const SwFrm* pFrm( 0L );
+ if ( prPage->IsInvalidLayout() &&
+ 0 != (pFrm = lcl_FindFirstInvaLay( prPage, nBottom )) &&
+ pFrm->Frm().Top() <= nBottom )
+ {
+ return sal_False;
+ }
+ if ( (prPage->IsInvalidCntnt() || prPage->IsInvalidFlyInCnt()) &&
+ 0 != (pFrm = lcl_FindFirstInvaCntnt( prPage, nBottom, 0 )) &&
+ pFrm->Frm().Top() <= nBottom )
+ {
+ return sal_False;
+ }
+ bRet = sal_True;
+ }
+ return bRet;
+}
+
+/*************************************************************************
+|*
+|* SwLayAction::FormatLayout(), FormatLayoutFly, FormatLayoutTab()
+|*
+|*************************************************************************/
+// OD 15.11.2002 #105155# - introduce support for vertical layout
+sal_Bool SwLayAction::FormatLayout( SwLayoutFrm *pLay, sal_Bool bAddRect )
+{
+ OSL_ENSURE( !IsAgain(), "Ungueltige Seite beachten." );
+ if ( IsAgain() )
+ return sal_False;
+
+ sal_Bool bChanged = sal_False;
+ sal_Bool bAlreadyPainted = sal_False;
+ // OD 11.11.2002 #104414# - remember frame at complete paint
+ SwRect aFrmAtCompletePaint;
+
+ if ( !pLay->IsValid() || pLay->IsCompletePaint() )
+ {
+ if ( pLay->GetPrev() && !pLay->GetPrev()->IsValid() )
+ pLay->GetPrev()->SetCompletePaint();
+
+ SwRect aOldFrame( pLay->Frm() );
+ SwRect aOldRect( aOldFrame );
+ if( pLay->IsPageFrm() )
+ {
+ aOldRect = static_cast<SwPageFrm*>(pLay)->GetBoundRect();
+ }
+
+ pLay->Calc();
+ if ( aOldFrame != pLay->Frm() )
+ bChanged = sal_True;
+
+ sal_Bool bNoPaint = sal_False;
+ if ( pLay->IsPageBodyFrm() &&
+ pLay->Frm().Pos() == aOldRect.Pos() &&
+ pLay->Lower() )
+ {
+ const ViewShell *pSh = pLay->getRootFrm()->GetCurrShell();
+ //Einschraenkungen wegen Kopf-/Fusszeilen
+ if( pSh && pSh->GetViewOptions()->getBrowseMode() &&
+ !( pLay->IsCompletePaint() && pLay->FindPageFrm()->FindFtnCont() ) )
+ bNoPaint = sal_True;
+ }
+
+ if ( !bNoPaint && IsPaint() && bAddRect && (pLay->IsCompletePaint() || bChanged) )
+ {
+ SwRect aPaint( pLay->Frm() );
+ // OD 13.02.2003 #i9719#, #105645# - consider border and shadow for
+ // page frames -> enlarge paint rectangle correspondingly.
+ if ( pLay->IsPageFrm() )
+ {
+ SwPageFrm* pPageFrm = static_cast<SwPageFrm*>(pLay);
+ aPaint = pPageFrm->GetBoundRect();
+ }
+
+ sal_Bool bPageInBrowseMode = pLay->IsPageFrm();
+ if( bPageInBrowseMode )
+ {
+ const ViewShell *pSh = pLay->getRootFrm()->GetCurrShell();
+ if( !pSh || !pSh->GetViewOptions()->getBrowseMode() )
+ bPageInBrowseMode = sal_False;
+ }
+ if( bPageInBrowseMode )
+ {
+ // NOTE: no vertical layout in online layout
+ //Ist die Aenderung ueberhaupt sichtbar?
+ if ( pLay->IsCompletePaint() )
+ {
+ pImp->GetShell()->AddPaintRect( aPaint );
+ bAddRect = sal_False;
+ }
+ else
+ {
+ sal_uInt16 i;
+
+ SwRegionRects aRegion( aOldRect );
+ aRegion -= aPaint;
+ for ( i = 0; i < aRegion.Count(); ++i )
+ pImp->GetShell()->AddPaintRect( aRegion[i] );
+ aRegion.ChangeOrigin( aPaint );
+ aRegion.Remove( 0, aRegion.Count() );
+ aRegion.Insert( aPaint, 0 );
+ aRegion -= aOldRect;
+ for ( i = 0; i < aRegion.Count(); ++i )
+ pImp->GetShell()->AddPaintRect( aRegion[i] );
+ }
+
+ }
+ else
+ {
+ pImp->GetShell()->AddPaintRect( aPaint );
+ bAlreadyPainted = sal_True;
+ // OD 11.11.2002 #104414# - remember frame at complete paint
+ aFrmAtCompletePaint = pLay->Frm();
+ }
+
+ // OD 13.02.2003 #i9719#, #105645# - provide paint of spacing
+ // between pages (not only for in online mode).
+ if ( pLay->IsPageFrm() )
+ {
+ const SwTwips nHalfDocBorder = GAPBETWEENPAGES;
+ const bool bLeftToRightViewLayout = pRoot->IsLeftToRightViewLayout();
+ const bool bPrev = bLeftToRightViewLayout ? pLay->GetPrev() : pLay->GetNext();
+ const bool bNext = bLeftToRightViewLayout ? pLay->GetNext() : pLay->GetPrev();
+ SwPageFrm* pPageFrm = static_cast<SwPageFrm*>(pLay);
+ const ViewShell *pSh = pLay->getRootFrm()->GetCurrShell();
+ SwRect aPageRect( pLay->Frm() );
+
+ if(pSh)
+ {
+ SwPageFrm::GetBorderAndShadowBoundRect(aPageRect, pSh,
+ aPageRect, pPageFrm->IsLeftShadowNeeded(), pPageFrm->IsRightShadowNeeded(),
+ pPageFrm->SidebarPosition() == sw::sidebarwindows::SIDEBAR_RIGHT);
+ }
+
+ if ( bPrev )
+ {
+ // top
+ SwRect aSpaceToPrevPage( aPageRect );
+ aSpaceToPrevPage.Top( aSpaceToPrevPage.Top() - nHalfDocBorder );
+ aSpaceToPrevPage.Bottom( pLay->Frm().Top() );
+ if(aSpaceToPrevPage.Height() > 0 && aSpaceToPrevPage.Width() > 0)
+ pImp->GetShell()->AddPaintRect( aSpaceToPrevPage );
+
+ pSh->GetOut()->DrawRect( aSpaceToPrevPage.SVRect() );
+
+ // left
+ aSpaceToPrevPage = aPageRect;
+ aSpaceToPrevPage.Left( aSpaceToPrevPage.Left() - nHalfDocBorder );
+ aSpaceToPrevPage.Right( pLay->Frm().Left() );
+ if(aSpaceToPrevPage.Height() > 0 && aSpaceToPrevPage.Width() > 0)
+ pImp->GetShell()->AddPaintRect( aSpaceToPrevPage );
+ }
+ if ( bNext )
+ {
+ // bottom
+ SwRect aSpaceToNextPage( aPageRect );
+ aSpaceToNextPage.Bottom( aSpaceToNextPage.Bottom() + nHalfDocBorder );
+ aSpaceToNextPage.Top( pLay->Frm().Bottom() );
+ if(aSpaceToNextPage.Height() > 0 && aSpaceToNextPage.Width() > 0)
+ pImp->GetShell()->AddPaintRect( aSpaceToNextPage );
+
+ // right
+ aSpaceToNextPage = aPageRect;
+ aSpaceToNextPage.Right( aSpaceToNextPage.Right() + nHalfDocBorder );
+ aSpaceToNextPage.Left( pLay->Frm().Right() );
+ if(aSpaceToNextPage.Height() > 0 && aSpaceToNextPage.Width() > 0)
+ pImp->GetShell()->AddPaintRect( aSpaceToNextPage );
+ }
+ }
+ }
+ pLay->ResetCompletePaint();
+ }
+
+ if ( IsPaint() && bAddRect &&
+ !pLay->GetNext() && pLay->IsRetoucheFrm() && pLay->IsRetouche() )
+ {
+ // OD 15.11.2002 #105155# - vertical layout support
+ SWRECTFN( pLay );
+ SwRect aRect( pLay->GetUpper()->PaintArea() );
+ (aRect.*fnRect->fnSetTop)( (pLay->*fnRect->fnGetPrtBottom)() );
+ if ( !pImp->GetShell()->AddPaintRect( aRect ) )
+ pLay->ResetRetouche();
+ }
+
+ if( bAlreadyPainted )
+ bAddRect = sal_False;
+
+ CheckWaitCrsr();
+
+ if ( IsAgain() )
+ return sal_False;
+
+ //Jetzt noch diejenigen Lowers versorgen die LayoutFrm's sind
+
+ if ( pLay->IsFtnFrm() ) //Hat keine LayFrms als Lower.
+ return bChanged;
+
+ SwFrm *pLow = pLay->Lower();
+ sal_Bool bTabChanged = sal_False;
+ while ( pLow && pLow->GetUpper() == pLay )
+ {
+ if ( pLow->IsLayoutFrm() )
+ {
+ if ( pLow->IsTabFrm() )
+ bTabChanged |= FormatLayoutTab( (SwTabFrm*)pLow, bAddRect );
+ // bereits zum Loeschen angemeldete Ueberspringen
+ else if( !pLow->IsSctFrm() || ((SwSectionFrm*)pLow)->GetSection() )
+ bChanged |= FormatLayout( (SwLayoutFrm*)pLow, bAddRect );
+ }
+ else if ( pImp->GetShell()->IsPaintLocked() )
+ //Abkuerzung im die Zyklen zu minimieren, bei Lock kommt das
+ //Paint sowieso (Primaer fuer Browse)
+ pLow->OptCalc();
+
+ if ( IsAgain() )
+ return sal_False;
+ pLow = pLow->GetNext();
+ }
+ // OD 11.11.2002 #104414# - add complete frame area as paint area, if frame
+ // area has been already added and after formating its lowers the frame area
+ // is enlarged.
+ SwRect aBoundRect(pLay->IsPageFrm() ? static_cast<SwPageFrm*>(pLay)->GetBoundRect() : pLay->Frm() );
+
+ if ( bAlreadyPainted &&
+ ( aBoundRect.Width() > aFrmAtCompletePaint.Width() ||
+ aBoundRect.Height() > aFrmAtCompletePaint.Height() )
+ )
+ {
+ pImp->GetShell()->AddPaintRect( aBoundRect );
+ }
+ return bChanged || bTabChanged;
+}
+
+sal_Bool SwLayAction::FormatLayoutFly( SwFlyFrm* pFly )
+{
+ OSL_ENSURE( !IsAgain(), "Ungueltige Seite beachten." );
+ if ( IsAgain() )
+ return sal_False;
+
+ sal_Bool bChanged = false;
+ sal_Bool bAddRect = true;
+
+ if ( !pFly->IsValid() || pFly->IsCompletePaint() || pFly->IsInvalid() )
+ {
+ //Der Frame hat sich veraendert, er wird jetzt Formatiert
+ const SwRect aOldRect( pFly->Frm() );
+ pFly->Calc();
+ bChanged = aOldRect != pFly->Frm();
+
+ if ( IsPaint() && (pFly->IsCompletePaint() || bChanged) &&
+ pFly->Frm().Top() > 0 && pFly->Frm().Left() > 0 )
+ pImp->GetShell()->AddPaintRect( pFly->Frm() );
+
+ if ( bChanged )
+ pFly->Invalidate();
+ else
+ pFly->Validate();
+/*
+ //mba: it's unclear why we should invalidate always, so I remove it
+ //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin
+ if ( IsPaint() && bAddRect && pFly->Frm().Top() > 0 && pFly->Frm().Left() > 0 )
+ pImp->GetShell()->AddPaintRect( pFly->Frm() );
+
+ pFly->Invalidate();
+*/
+ bAddRect = false;
+ pFly->ResetCompletePaint();
+ }
+
+ if ( IsAgain() )
+ return sal_False;
+
+ //Jetzt noch diejenigen Lowers versorgen die LayoutFrm's sind
+ sal_Bool bTabChanged = false;
+ SwFrm *pLow = pFly->Lower();
+ while ( pLow )
+ {
+ if ( pLow->IsLayoutFrm() )
+ {
+ if ( pLow->IsTabFrm() )
+ bTabChanged |= FormatLayoutTab( (SwTabFrm*)pLow, bAddRect );
+ else
+ bChanged |= FormatLayout( (SwLayoutFrm*)pLow, bAddRect );
+ }
+ pLow = pLow->GetNext();
+ }
+ return bChanged || bTabChanged;
+}
+
+// OD 31.10.2002 #104100#
+// Implement vertical layout support
+sal_Bool SwLayAction::FormatLayoutTab( SwTabFrm *pTab, sal_Bool bAddRect )
+{
+ OSL_ENSURE( !IsAgain(), "8-) Ungueltige Seite beachten." );
+ if ( IsAgain() || !pTab->Lower() )
+ return sal_False;
+
+ IDocumentTimerAccess *pTimerAccess = pRoot->GetFmt()->getIDocumentTimerAccess();
+ pTimerAccess->BlockIdling();
+
+ sal_Bool bChanged = sal_False;
+ sal_Bool bPainted = sal_False;
+
+ const SwPageFrm *pOldPage = pTab->FindPageFrm();
+
+ // OD 31.10.2002 #104100# - vertical layout support
+ // use macro to declare and init <sal_Bool bVert>, <sal_Bool bRev> and
+ // <SwRectFn fnRect> for table frame <pTab>.
+ SWRECTFN( pTab );
+
+ if ( !pTab->IsValid() || pTab->IsCompletePaint() || pTab->IsComplete() )
+ {
+ if ( pTab->GetPrev() && !pTab->GetPrev()->IsValid() )
+ {
+ pTab->GetPrev()->SetCompletePaint();
+ }
+
+ const SwRect aOldRect( pTab->Frm() );
+ pTab->SetLowersFormatted( sal_False );
+ pTab->Calc();
+ if ( aOldRect != pTab->Frm() )
+ {
+ bChanged = sal_True;
+ }
+ const SwRect aPaintFrm = pTab->PaintArea();
+
+ if ( IsPaint() && bAddRect )
+ {
+ // OD 01.11.2002 #104100# - add condition <pTab->Frm().HasArea()>
+ if ( !pTab->IsCompletePaint() &&
+ pTab->IsComplete() &&
+ ( pTab->Frm().SSize() != pTab->Prt().SSize() ||
+ // OD 31.10.2002 #104100# - vertical layout support
+ (pTab->*fnRect->fnGetLeftMargin)() ) &&
+ pTab->Frm().HasArea()
+ )
+ {
+ // OD 01.11.2002 #104100# - re-implement calculation of margin rectangles.
+ SwRect aMarginRect;
+
+ SwTwips nLeftMargin = (pTab->*fnRect->fnGetLeftMargin)();
+ if ( nLeftMargin > 0)
+ {
+ aMarginRect = pTab->Frm();
+ (aMarginRect.*fnRect->fnSetWidth)( nLeftMargin );
+ pImp->GetShell()->AddPaintRect( aMarginRect );
+ }
+
+ if ( (pTab->*fnRect->fnGetRightMargin)() > 0)
+ {
+ aMarginRect = pTab->Frm();
+ (aMarginRect.*fnRect->fnSetLeft)( (pTab->*fnRect->fnGetPrtRight)() );
+ pImp->GetShell()->AddPaintRect( aMarginRect );
+ }
+
+ SwTwips nTopMargin = (pTab->*fnRect->fnGetTopMargin)();
+ if ( nTopMargin > 0)
+ {
+ aMarginRect = pTab->Frm();
+ (aMarginRect.*fnRect->fnSetHeight)( nTopMargin );
+ pImp->GetShell()->AddPaintRect( aMarginRect );
+ }
+
+ if ( (pTab->*fnRect->fnGetBottomMargin)() > 0)
+ {
+ aMarginRect = pTab->Frm();
+ (aMarginRect.*fnRect->fnSetTop)( (pTab->*fnRect->fnGetPrtBottom)() );
+ pImp->GetShell()->AddPaintRect( aMarginRect );
+ }
+ }
+ else if ( pTab->IsCompletePaint() )
+ {
+ pImp->GetShell()->AddPaintRect( aPaintFrm );
+ bAddRect = sal_False;
+ bPainted = sal_True;
+ }
+
+ if ( pTab->IsRetouche() && !pTab->GetNext() )
+ {
+ SwRect aRect( pTab->GetUpper()->PaintArea() );
+ // OD 04.11.2002 #104100# - vertical layout support
+ (aRect.*fnRect->fnSetTop)( (pTab->*fnRect->fnGetPrtBottom)() );
+ if ( !pImp->GetShell()->AddPaintRect( aRect ) )
+ pTab->ResetRetouche();
+ }
+ }
+ else
+ bAddRect = sal_False;
+
+ if ( pTab->IsCompletePaint() && !pOptTab )
+ pOptTab = pTab;
+ pTab->ResetCompletePaint();
+ }
+ if ( IsPaint() && bAddRect && pTab->IsRetouche() && !pTab->GetNext() )
+ {
+ // OD 04.10.2002 #102779#
+ // set correct rectangle for retouche: area between bottom of table frame
+ // and bottom of paint area of the upper frame.
+ SwRect aRect( pTab->GetUpper()->PaintArea() );
+ // OD 04.11.2002 #104100# - vertical layout support
+ (aRect.*fnRect->fnSetTop)( (pTab->*fnRect->fnGetPrtBottom)() );
+ if ( !pImp->GetShell()->AddPaintRect( aRect ) )
+ pTab->ResetRetouche();
+ }
+
+ CheckWaitCrsr();
+
+ pTimerAccess->UnblockIdling();
+
+ //Heftige Abkuerzung!
+ if ( pTab->IsLowersFormatted() &&
+ (bPainted || !pImp->GetShell()->VisArea().IsOver( pTab->Frm())) )
+ return sal_False;
+
+ //Jetzt noch die Lowers versorgen
+ if ( IsAgain() )
+ return sal_False;
+
+ // OD 20.10.2003 #112464# - for savety reasons:
+ // check page number before formatting lowers.
+ if ( pOldPage->GetPhyPageNum() > (pTab->FindPageFrm()->GetPhyPageNum() + 1) )
+ SetNextCycle( sal_True );
+
+ // OD 20.10.2003 #112464# - format lowers, only if table frame is valid
+ if ( pTab->IsValid() )
+ {
+ SwLayoutFrm *pLow = (SwLayoutFrm*)pTab->Lower();
+ while ( pLow )
+ {
+ bChanged |= FormatLayout( (SwLayoutFrm*)pLow, bAddRect );
+ if ( IsAgain() )
+ return sal_False;
+ pLow = (SwLayoutFrm*)pLow->GetNext();
+ }
+ }
+
+ return bChanged;
+}
+
+/*************************************************************************
+|*
+|* SwLayAction::FormatCntnt()
+|*
+|*************************************************************************/
+sal_Bool SwLayAction::FormatCntnt( const SwPageFrm *pPage )
+{
+ const SwCntntFrm *pCntnt = pPage->ContainsCntnt();
+ const ViewShell *pSh = pRoot->GetCurrShell();
+ const sal_Bool bBrowse = pSh && pSh->GetViewOptions()->getBrowseMode();
+
+ while ( pCntnt && pPage->IsAnLower( pCntnt ) )
+ {
+ //Wenn der Cntnt sich eh nicht veraendert koennen wir ein paar
+ //Abkuerzungen nutzen.
+ const sal_Bool bFull = !pCntnt->IsValid() || pCntnt->IsCompletePaint() ||
+ pCntnt->IsRetouche() || pCntnt->GetDrawObjs();
+ if ( bFull )
+ {
+ //Damit wir nacher nicht suchen muessen.
+ const sal_Bool bNxtCnt = IsCalcLayout() && !pCntnt->GetFollow();
+ const SwCntntFrm *pCntntNext = bNxtCnt ? pCntnt->GetNextCntntFrm() : 0;
+ const SwCntntFrm *pCntntPrev = pCntnt->GetPrev() ? pCntnt->GetPrevCntntFrm() : 0;
+
+ const SwLayoutFrm*pOldUpper = pCntnt->GetUpper();
+ const SwTabFrm *pTab = pCntnt->FindTabFrm();
+ const sal_Bool bInValid = !pCntnt->IsValid() || pCntnt->IsCompletePaint();
+ const sal_Bool bOldPaint = IsPaint();
+ bPaint = bOldPaint && !(pTab && pTab == pOptTab);
+ _FormatCntnt( pCntnt, pPage );
+ // --> OD 2004-11-05 #i26945# - reset <bPaint> before format objects
+ bPaint = bOldPaint;
+ // <--
+
+ // OD 2004-05-10 #i28701# - format floating screen object at content frame.
+ // No format, if action flag <bAgain> is set or action is interrupted.
+ // OD 2004-08-30 #117736# - allow format on interruption of action, if
+ // it's the format for this interrupt
+ // --> OD 2004-11-01 #i23129#, #i36347# - pass correct page frame
+ // to the object formatter.
+ if ( !IsAgain() &&
+ ( !IsInterrupt() || mbFormatCntntOnInterrupt ) &&
+ pCntnt->IsTxtFrm() &&
+ !SwObjectFormatter::FormatObjsAtFrm( *(const_cast<SwCntntFrm*>(pCntnt)),
+ *(pCntnt->FindPageFrm()), this ) )
+ // <--
+ {
+ return sal_False;
+ }
+
+ if ( !pCntnt->GetValidLineNumFlag() && pCntnt->IsTxtFrm() )
+ {
+ const sal_uLong nAllLines = ((SwTxtFrm*)pCntnt)->GetAllLines();
+ ((SwTxtFrm*)pCntnt)->RecalcAllLines();
+ if ( IsPaintExtraData() && IsPaint() &&
+ nAllLines != ((SwTxtFrm*)pCntnt)->GetAllLines() )
+ pImp->GetShell()->AddPaintRect( pCntnt->Frm() );
+ }
+
+ if ( IsAgain() )
+ return sal_False;
+
+ //Wenn Layout oder Flys wieder Invalid sind breche ich die Verarbeitung
+ //vorlaeufig ab - allerdings nicht fuer die BrowseView, denn dort wird
+ //das Layout staendig ungueltig, weil die Seitenhoehe angepasst wird.
+ //Desgleichen wenn der Benutzer weiterarbeiten will und mindestens ein
+ //Absatz verarbeitet wurde.
+ if ( (!pTab || (pTab && !bInValid)) )
+ {
+ CheckIdleEnd();
+ // OD 14.04.2003 #106346# - consider interrupt formatting.
+ if ( ( IsInterrupt() && !mbFormatCntntOnInterrupt ) ||
+ ( !bBrowse && pPage->IsInvalidLayout() ) ||
+ // OD 07.05.2003 #109435# - consider interrupt formatting
+ ( IS_FLYS && IS_INVAFLY && !mbFormatCntntOnInterrupt )
+ )
+ return sal_False;
+ }
+ if ( pOldUpper != pCntnt->GetUpper() )
+ {
+ const sal_uInt16 nCurNum = pCntnt->FindPageFrm()->GetPhyPageNum();
+ if ( nCurNum < pPage->GetPhyPageNum() )
+ nPreInvaPage = nCurNum;
+
+ //Wenn der Frm mehr als eine Seite rueckwaerts geflossen ist, so
+ //fangen wir nocheinmal von vorn an damit wir nichts auslassen.
+ if ( !IsCalcLayout() && pPage->GetPhyPageNum() > nCurNum+1 )
+ {
+ SetNextCycle( sal_True );
+ // OD 07.05.2003 #109435# - consider interrupt formatting
+ if ( !mbFormatCntntOnInterrupt )
+ {
+ return sal_False;
+ }
+ }
+ }
+ //Wenn der Frame die Seite vorwaerts gewechselt hat, so lassen wir
+ //den Vorgaenger nocheinmal durchlaufen.
+ //So werden einerseits Vorgaenger erwischt, die jetzt f?r Retouche
+ //verantwortlich sind, andererseits werden die Fusszeilen
+ //auch angefasst.
+ sal_Bool bSetCntnt = sal_True;
+ if ( pCntntPrev )
+ {
+ if ( !pCntntPrev->IsValid() && pPage->IsAnLower( pCntntPrev ) )
+ pPage->InvalidateCntnt();
+ if ( pOldUpper != pCntnt->GetUpper() &&
+ pPage->GetPhyPageNum() < pCntnt->FindPageFrm()->GetPhyPageNum() )
+ {
+ pCntnt = pCntntPrev;
+ bSetCntnt = sal_False;
+ }
+ }
+ if ( bSetCntnt )
+ {
+ if ( bBrowse && !IsIdle() && !IsCalcLayout() && !IsComplete() &&
+ pCntnt->Frm().Top() > pImp->GetShell()->VisArea().Bottom())
+ {
+ const long nBottom = pImp->GetShell()->VisArea().Bottom();
+ const SwFrm *pTmp = lcl_FindFirstInvaCntnt( pPage,
+ nBottom, pCntnt );
+ if ( !pTmp )
+ {
+ if ( (!(IS_FLYS && IS_INVAFLY) ||
+ !lcl_FindFirstInvaObj( pPage, nBottom )) &&
+ (!pPage->IsInvalidLayout() ||
+ !lcl_FindFirstInvaLay( pPage, nBottom )))
+ SetBrowseActionStop( sal_True );
+ // OD 14.04.2003 #106346# - consider interrupt formatting.
+ if ( !mbFormatCntntOnInterrupt )
+ {
+ return sal_False;
+ }
+ }
+ }
+ pCntnt = bNxtCnt ? pCntntNext : pCntnt->GetNextCntntFrm();
+ }
+
+ RESCHEDULE;
+ }
+ else
+ {
+ if ( !pCntnt->GetValidLineNumFlag() && pCntnt->IsTxtFrm() )
+ {
+ const sal_uLong nAllLines = ((SwTxtFrm*)pCntnt)->GetAllLines();
+ ((SwTxtFrm*)pCntnt)->RecalcAllLines();
+ if ( IsPaintExtraData() && IsPaint() &&
+ nAllLines != ((SwTxtFrm*)pCntnt)->GetAllLines() )
+ pImp->GetShell()->AddPaintRect( pCntnt->Frm() );
+ }
+
+ //Falls der Frm schon vor der Abarbeitung hier formatiert wurde.
+ if ( pCntnt->IsTxtFrm() && ((SwTxtFrm*)pCntnt)->HasRepaint() &&
+ IsPaint() )
+ PaintCntnt( pCntnt, pPage, pCntnt->Frm(), pCntnt->Frm().Bottom());
+ if ( IsIdle() )
+ {
+ CheckIdleEnd();
+ // OD 14.04.2003 #106346# - consider interrupt formatting.
+ if ( IsInterrupt() && !mbFormatCntntOnInterrupt )
+ return sal_False;
+ }
+ if ( bBrowse && !IsIdle() && !IsCalcLayout() && !IsComplete() &&
+ pCntnt->Frm().Top() > pImp->GetShell()->VisArea().Bottom())
+ {
+ const long nBottom = pImp->GetShell()->VisArea().Bottom();
+ const SwFrm *pTmp = lcl_FindFirstInvaCntnt( pPage,
+ nBottom, pCntnt );
+ if ( !pTmp )
+ {
+ if ( (!(IS_FLYS && IS_INVAFLY) ||
+ !lcl_FindFirstInvaObj( pPage, nBottom )) &&
+ (!pPage->IsInvalidLayout() ||
+ !lcl_FindFirstInvaLay( pPage, nBottom )))
+ SetBrowseActionStop( sal_True );
+ // OD 14.04.2003 #106346# - consider interrupt formatting.
+ if ( !mbFormatCntntOnInterrupt )
+ {
+ return sal_False;
+ }
+ }
+ }
+ pCntnt = pCntnt->GetNextCntntFrm();
+ }
+ }
+ CheckWaitCrsr();
+ // OD 14.04.2003 #106346# - consider interrupt formatting.
+ return !IsInterrupt() || mbFormatCntntOnInterrupt;
+}
+/*************************************************************************
+|*
+|* SwLayAction::_FormatCntnt()
+|*
+|* Beschreibung Returnt sal_True wenn der Absatz verarbeitet wurde,
+|* sal_False wenn es nichts zu verarbeiten gab.
+|*
+|*************************************************************************/
+void SwLayAction::_FormatCntnt( const SwCntntFrm *pCntnt,
+ const SwPageFrm *pPage )
+{
+ //wird sind hier evtl. nur angekommen, weil der Cntnt DrawObjekte haelt.
+ const bool bDrawObjsOnly = pCntnt->IsValid() && !pCntnt->IsCompletePaint() &&
+ !pCntnt->IsRetouche();
+ SWRECTFN( pCntnt )
+ if ( !bDrawObjsOnly && IsPaint() )
+ {
+ const SwRect aOldRect( pCntnt->UnionFrm() );
+ const long nOldBottom = (pCntnt->*fnRect->fnGetPrtBottom)();
+ pCntnt->OptCalc();
+ if( IsAgain() )
+ return;
+ if( (*fnRect->fnYDiff)( (pCntnt->Frm().*fnRect->fnGetBottom)(),
+ (aOldRect.*fnRect->fnGetBottom)() ) < 0 )
+ {
+ pCntnt->SetRetouche();
+ }
+ PaintCntnt( pCntnt, pCntnt->FindPageFrm(), aOldRect, nOldBottom);
+ }
+ else
+ {
+ if ( IsPaint() && pCntnt->IsTxtFrm() && ((SwTxtFrm*)pCntnt)->HasRepaint() )
+ PaintCntnt( pCntnt, pPage, pCntnt->Frm(),
+ (pCntnt->Frm().*fnRect->fnGetBottom)() );
+ pCntnt->OptCalc();
+ }
+}
+
+/*************************************************************************
+|*
+|* SwLayAction::_FormatFlyCntnt()
+|*
+|* Beschreibung:
+|* - Returnt sal_True wenn alle Cntnts des Flys vollstaendig verarbeitet
+|* wurden. sal_False wenn vorzeitig unterbrochen wurde.
+|*
+|*************************************************************************/
+sal_Bool SwLayAction::_FormatFlyCntnt( const SwFlyFrm *pFly )
+{
+ const SwCntntFrm *pCntnt = pFly->ContainsCntnt();
+
+ while ( pCntnt )
+ {
+ // OD 2004-05-10 #i28701#
+ _FormatCntnt( pCntnt, pCntnt->FindPageFrm() );
+
+ // --> OD 2004-07-23 #i28701# - format floating screen objects
+ // at content text frame
+ // --> OD 2004-11-02 #i23129#, #i36347# - pass correct page frame
+ // to the object formatter.
+ if ( pCntnt->IsTxtFrm() &&
+ !SwObjectFormatter::FormatObjsAtFrm(
+ *(const_cast<SwCntntFrm*>(pCntnt)),
+ *(pCntnt->FindPageFrm()), this ) )
+ // <--
+ {
+ // restart format with first content
+ pCntnt = pFly->ContainsCntnt();
+ continue;
+ }
+ // <--
+
+ if ( !pCntnt->GetValidLineNumFlag() && pCntnt->IsTxtFrm() )
+ {
+ const sal_uLong nAllLines = ((SwTxtFrm*)pCntnt)->GetAllLines();
+ ((SwTxtFrm*)pCntnt)->RecalcAllLines();
+ if ( IsPaintExtraData() && IsPaint() &&
+ nAllLines != ((SwTxtFrm*)pCntnt)->GetAllLines() )
+ pImp->GetShell()->AddPaintRect( pCntnt->Frm() );
+ }
+
+ if ( IsAgain() )
+ return sal_False;
+
+ //wenn eine Eingabe anliegt breche ich die Verarbeitung ab.
+ if ( !pFly->IsFlyInCntFrm() )
+ {
+ CheckIdleEnd();
+ // OD 14.04.2003 #106346# - consider interrupt formatting.
+ if ( IsInterrupt() && !mbFormatCntntOnInterrupt )
+ return sal_False;
+ }
+ pCntnt = pCntnt->GetNextCntntFrm();
+ }
+ CheckWaitCrsr();
+ // OD 14.04.2003 #106346# - consider interrupt formatting.
+ return !(IsInterrupt() && !mbFormatCntntOnInterrupt);
+}
+
+sal_Bool SwLayAction::IsStopPrt() const
+{
+ sal_Bool bResult = sal_False;
+
+ if (pImp != NULL && pProgress != NULL)
+ bResult = pImp->IsStopPrt();
+
+ return bResult;
+}
+
+/*************************************************************************
+|*
+|* SwLayAction::FormatSpelling(), _FormatSpelling()
+|*
+|*************************************************************************/
+sal_Bool SwLayIdle::_DoIdleJob( const SwCntntFrm *pCnt, IdleJobType eJob )
+{
+ OSL_ENSURE( pCnt->IsTxtFrm(), "NoTxt neighbour of Txt" );
+ // robust against misuse by e.g. #i52542#
+ if( !pCnt->IsTxtFrm() )
+ return sal_False;
+
+ const SwTxtNode* pTxtNode = pCnt->GetNode()->GetTxtNode();
+
+ bool bProcess = false;
+ switch ( eJob )
+ {
+ case ONLINE_SPELLING :
+ bProcess = pTxtNode->IsWrongDirty(); break;
+ case AUTOCOMPLETE_WORDS :
+ bProcess = pTxtNode->IsAutoCompleteWordDirty(); break;
+ case WORD_COUNT :
+ bProcess = pTxtNode->IsWordCountDirty(); break;
+ case SMART_TAGS : // SMARTTAGS
+ bProcess = pTxtNode->IsSmartTagDirty(); break;
+ }
+
+ if( bProcess )
+ {
+ ViewShell *pSh = pImp->GetShell();
+ if( STRING_LEN == nTxtPos )
+ {
+ --nTxtPos;
+ if( pSh->ISA(SwCrsrShell) && !((SwCrsrShell*)pSh)->IsTableMode() )
+ {
+ SwPaM *pCrsr = ((SwCrsrShell*)pSh)->GetCrsr();
+ if( !pCrsr->HasMark() && pCrsr == pCrsr->GetNext() )
+ {
+ pCntntNode = pCrsr->GetCntntNode();
+ nTxtPos = pCrsr->GetPoint()->nContent.GetIndex();
+ }
+ }
+ }
+
+ switch ( eJob )
+ {
+ case ONLINE_SPELLING :
+ {
+ SwRect aRepaint( ((SwTxtFrm*)pCnt)->_AutoSpell( pCntntNode, *pSh->GetViewOptions(), nTxtPos ) );
+ bPageValid = bPageValid && !pTxtNode->IsWrongDirty();
+ if( !bPageValid )
+ bAllValid = sal_False;
+ if ( aRepaint.HasArea() )
+ pImp->GetShell()->InvalidateWindows( aRepaint );
+ if ( Application::AnyInput( INPUT_MOUSEANDKEYBOARD|INPUT_OTHER|INPUT_PAINT ) )
+ return sal_True;
+ break;
+ }
+ case AUTOCOMPLETE_WORDS :
+ ((SwTxtFrm*)pCnt)->CollectAutoCmplWrds( pCntntNode, nTxtPos );
+ if ( Application::AnyInput( INPUT_ANY ) )
+ return sal_True;
+ break;
+ case WORD_COUNT :
+ {
+ const xub_StrLen nEnd = pTxtNode->GetTxt().Len();
+ SwDocStat aStat;
+ pTxtNode->CountWords( aStat, 0, nEnd );
+ if ( Application::AnyInput( INPUT_ANY ) )
+ return sal_True;
+ break;
+ }
+ case SMART_TAGS : // SMARTTAGS
+ {
+ const SwRect aRepaint( ((SwTxtFrm*)pCnt)->SmartTagScan( pCntntNode, nTxtPos ) );
+ bPageValid = bPageValid && !pTxtNode->IsSmartTagDirty();
+ if( !bPageValid )
+ bAllValid = sal_False;
+ if ( aRepaint.HasArea() )
+ pImp->GetShell()->InvalidateWindows( aRepaint );
+ if ( Application::AnyInput( INPUT_MOUSEANDKEYBOARD|INPUT_OTHER|INPUT_PAINT ) )
+ return sal_True;
+ break;
+ }
+ }
+ }
+
+ //Die im Absatz verankerten Flys wollen auch mitspielen.
+ if ( pCnt->GetDrawObjs() )
+ {
+ const SwSortedObjs &rObjs = *pCnt->GetDrawObjs();
+ for ( sal_uInt16 i = 0; i < rObjs.Count(); ++i )
+ {
+ SwAnchoredObject* pObj = rObjs[i];
+ if ( pObj->ISA(SwFlyFrm) )
+ {
+ SwFlyFrm* pFly = static_cast<SwFlyFrm*>(pObj);
+ if ( pFly->IsFlyInCntFrm() )
+ {
+ const SwCntntFrm *pC = pFly->ContainsCntnt();
+ while( pC )
+ {
+ if ( pC->IsTxtFrm() )
+ {
+ if ( _DoIdleJob( pC, eJob ) )
+ return sal_True;
+ }
+ pC = pC->GetNextCntntFrm();
+ }
+ }
+ }
+ }
+ }
+ return sal_False;
+}
+
+sal_Bool SwLayIdle::DoIdleJob( IdleJobType eJob, sal_Bool bVisAreaOnly )
+{
+ //Spellchecken aller Inhalte der Seiten. Entweder nur der sichtbaren
+ //Seiten oder eben aller.
+ const ViewShell* pViewShell = pImp->GetShell();
+ const SwViewOption* pViewOptions = pViewShell->GetViewOptions();
+ const SwDoc* pDoc = pViewShell->GetDoc();
+
+ switch ( eJob )
+ {
+ case ONLINE_SPELLING :
+ if( !pViewOptions->IsOnlineSpell() )
+ return sal_False;
+ break;
+ case AUTOCOMPLETE_WORDS :
+ if( !pViewOptions->IsAutoCompleteWords() ||
+ pDoc->GetAutoCompleteWords().IsLockWordLstLocked())
+ return sal_False;
+ break;
+ case WORD_COUNT :
+ if ( !pViewShell->getIDocumentStatistics()->GetDocStat().bModified )
+ return sal_False;
+ break;
+ case SMART_TAGS :
+ if ( pDoc->GetDocShell()->IsHelpDocument() ||
+ pDoc->isXForms() ||
+ !SwSmartTagMgr::Get().IsSmartTagsEnabled() )
+ return sal_False;
+ break;
+ default: OSL_FAIL( "Unknown idle job type" );
+ }
+
+ SwPageFrm *pPage;
+ if ( bVisAreaOnly )
+ pPage = pImp->GetFirstVisPage();
+ else
+ pPage = (SwPageFrm*)pRoot->Lower();
+
+ pCntntNode = NULL;
+ nTxtPos = STRING_LEN;
+
+ while ( pPage )
+ {
+ bPageValid = sal_True;
+ const SwCntntFrm *pCnt = pPage->ContainsCntnt();
+ while( pCnt && pPage->IsAnLower( pCnt ) )
+ {
+ if ( _DoIdleJob( pCnt, eJob ) )
+ return sal_True;
+ pCnt = pCnt->GetNextCntntFrm();
+ }
+ if ( pPage->GetSortedObjs() )
+ {
+ for ( sal_uInt16 i = 0; pPage->GetSortedObjs() &&
+ i < pPage->GetSortedObjs()->Count(); ++i )
+ {
+ const SwAnchoredObject* pObj = (*pPage->GetSortedObjs())[i];
+ if ( pObj->ISA(SwFlyFrm) )
+ {
+ const SwFlyFrm *pFly = static_cast<const SwFlyFrm*>(pObj);
+ const SwCntntFrm *pC = pFly->ContainsCntnt();
+ while( pC )
+ {
+ if ( pC->IsTxtFrm() )
+ {
+ if ( _DoIdleJob( pC, eJob ) )
+ return sal_True;
+ }
+ pC = pC->GetNextCntntFrm();
+ }
+ }
+ }
+ }
+
+ if( bPageValid )
+ {
+ switch ( eJob )
+ {
+ case ONLINE_SPELLING : pPage->ValidateSpelling(); break;
+ case AUTOCOMPLETE_WORDS : pPage->ValidateAutoCompleteWords(); break;
+ case WORD_COUNT : pPage->ValidateWordCount(); break;
+ case SMART_TAGS : pPage->ValidateSmartTags(); break; // SMARTTAGS
+ }
+ }
+
+ pPage = (SwPageFrm*)pPage->GetNext();
+ if ( pPage && bVisAreaOnly &&
+ !pPage->Frm().IsOver( pImp->GetShell()->VisArea()))
+ break;
+ }
+ return sal_False;
+}
+
+
+#if OSL_DEBUG_LEVEL > 1
+
+/*************************************************************************
+|*
+|* void SwLayIdle::SwLayIdle()
+|*
+|*************************************************************************/
+void SwLayIdle::ShowIdle( ColorData eColorData )
+{
+ if ( !bIndicator )
+ {
+ bIndicator = sal_True;
+ Window *pWin = pImp->GetShell()->GetWin();
+ if ( pWin )
+ {
+ Rectangle aRect( 0, 0, 5, 5 );
+ aRect = pWin->PixelToLogic( aRect );
+ // OD 2004-04-23 #116347#
+ pWin->Push( PUSH_FILLCOLOR|PUSH_LINECOLOR );
+ pWin->SetFillColor( eColorData );
+ pWin->SetLineColor();
+ pWin->DrawRect( aRect );
+ pWin->Pop();
+ }
+ }
+}
+#define SHOW_IDLE( ColorData ) ShowIdle( ColorData )
+#else
+#define SHOW_IDLE( ColorData )
+#endif
+
+/*************************************************************************
+|*
+|* void SwLayIdle::SwLayIdle()
+|*
+|*************************************************************************/
+SwLayIdle::SwLayIdle( SwRootFrm *pRt, SwViewImp *pI ) :
+ pRoot( pRt ),
+ pImp( pI )
+#if OSL_DEBUG_LEVEL > 1
+ , bIndicator( sal_False )
+#endif
+{
+ pImp->pIdleAct = this;
+
+ SHOW_IDLE( COL_LIGHTRED );
+
+ pImp->GetShell()->EnableSmooth( sal_False );
+
+ //Zuerst den Sichtbaren Bereich Spellchecken, nur wenn dort nichts
+ //zu tun war wird das IdleFormat angestossen.
+ if ( !DoIdleJob( SMART_TAGS, sal_True ) &&
+ !DoIdleJob( ONLINE_SPELLING, sal_True ) &&
+ !DoIdleJob( AUTOCOMPLETE_WORDS, sal_True ) ) // SMARTTAGS
+ {
+ //Formatieren und ggf. Repaint-Rechtecke an der ViewShell vormerken.
+ //Dabei muessen kuenstliche Actions laufen, damit es z.B. bei
+ //Veraenderungen der Seitenzahl nicht zu unerwuenschten Effekten kommt.
+ //Wir merken uns bei welchen Shells der Cursor sichtbar ist, damit
+ //wir ihn bei Dokumentaenderung ggf. wieder sichbar machen koennen.
+ std::vector<bool> aBools;
+ ViewShell *pSh = pImp->GetShell();
+ do
+ { ++pSh->nStartAction;
+ sal_Bool bVis = sal_False;
+ if ( pSh->ISA(SwCrsrShell) )
+ {
+#ifdef SW_CRSR_TIMER
+ ((SwCrsrShell*)pSh)->ChgCrsrTimerFlag( sal_False );
+#endif
+ bVis = ((SwCrsrShell*)pSh)->GetCharRect().IsOver(pSh->VisArea());
+ }
+ aBools.push_back( bVis );
+ pSh = (ViewShell*)pSh->GetNext();
+ } while ( pSh != pImp->GetShell() );
+
+ SwLayAction aAction( pRoot, pImp );
+ aAction.SetInputType( INPUT_ANY );
+ aAction.SetIdle( sal_True );
+ aAction.SetWaitAllowed( sal_False );
+ aAction.Action();
+
+ //Weitere Start-/EndActions nur auf wenn irgendwo Paints aufgelaufen
+ //sind oder wenn sich die Sichtbarkeit des CharRects veraendert hat.
+ sal_Bool bActions = sal_False;
+ sal_uInt16 nBoolIdx = 0;
+ do
+ {
+ --pSh->nStartAction;
+
+ if ( pSh->Imp()->GetRegion() )
+ bActions = sal_True;
+ else
+ {
+ SwRect aTmp( pSh->VisArea() );
+ pSh->UISizeNotify();
+
+ // --> FME 2006-08-03 #137134#
+ // Are we supposed to crash if pSh isn't a cursor shell?!
+ // bActions |= aTmp != pSh->VisArea() ||
+ // aBools[nBoolIdx] != ((SwCrsrShell*)pSh)->GetCharRect().IsOver( pSh->VisArea() );
+
+ // aBools[ i ] is true, if the i-th shell is a cursor shell (!!!)
+ // and the cursor is visible.
+ bActions |= aTmp != pSh->VisArea();
+ if ( aTmp == pSh->VisArea() && pSh->ISA(SwCrsrShell) )
+ {
+ bActions |= aBools[nBoolIdx] !=
+ static_cast<SwCrsrShell*>(pSh)->GetCharRect().IsOver( pSh->VisArea() );
+ }
+ }
+
+ pSh = (ViewShell*)pSh->GetNext();
+ ++nBoolIdx;
+ } while ( pSh != pImp->GetShell() );
+
+ if ( bActions )
+ {
+ //Start- EndActions aufsetzen. ueber die CrsrShell, damit der
+ //Cursor/Selektion und die VisArea korrekt gesetzt werden.
+ nBoolIdx = 0;
+ do
+ {
+ sal_Bool bCrsrShell = pSh->IsA( TYPE(SwCrsrShell) );
+
+ if ( bCrsrShell )
+ ((SwCrsrShell*)pSh)->SttCrsrMove();
+// else
+// pSh->StartAction();
+
+ //Wenn Paints aufgelaufen sind, ist es am sinnvollsten schlicht das
+ //gesamte Window zu invalidieren. Anderfalls gibt es Paintprobleme
+ //deren Loesung unverhaeltnissmaessig aufwendig waere.
+ //fix(18176):
+ SwViewImp *pViewImp = pSh->Imp();
+ sal_Bool bUnlock = sal_False;
+ if ( pViewImp->GetRegion() )
+ {
+ pViewImp->DelRegion();
+
+ //Fuer Repaint mit virtuellem Device sorgen.
+ pSh->LockPaint();
+ bUnlock = sal_True;
+ }
+
+ if ( bCrsrShell )
+ //Wenn der Crsr sichbar war wieder sichbar machen, sonst
+ //EndCrsrMove mit sal_True fuer IdleEnd.
+ ((SwCrsrShell*)pSh)->EndCrsrMove( sal_True^aBools[nBoolIdx] );
+// else
+// pSh->EndAction();
+ if( bUnlock )
+ {
+ if( bCrsrShell )
+ {
+ // UnlockPaint overwrite the selection from the
+ // CrsrShell and calls the virtual method paint
+ // to fill the virtual device. This fill dont have
+ // paint the selection! -> Set the focus flag at
+ // CrsrShell and it dont paint the selection.
+ ((SwCrsrShell*)pSh)->ShLooseFcs();
+ pSh->UnlockPaint( sal_True );
+ ((SwCrsrShell*)pSh)->ShGetFcs( sal_False );
+ }
+ else
+ pSh->UnlockPaint( sal_True );
+ }
+
+ pSh = (ViewShell*)pSh->GetNext();
+ ++nBoolIdx;
+
+ } while ( pSh != pImp->GetShell() );
+ }
+
+ if ( !aAction.IsInterrupt() )
+ {
+ if ( !DoIdleJob( WORD_COUNT, sal_False ) )
+ if ( !DoIdleJob( SMART_TAGS, sal_False ) )
+ if ( !DoIdleJob( ONLINE_SPELLING, sal_False ) )
+ DoIdleJob( AUTOCOMPLETE_WORDS, sal_False ); // SMARTTAGS
+ }
+
+ bool bInValid = false;
+ const SwViewOption& rVOpt = *pImp->GetShell()->GetViewOptions();
+ const ViewShell* pViewShell = pImp->GetShell();
+ // See conditions in DoIdleJob()
+ const sal_Bool bSpell = rVOpt.IsOnlineSpell();
+ const sal_Bool bACmplWrd = rVOpt.IsAutoCompleteWords();
+ const sal_Bool bWordCount = pViewShell->getIDocumentStatistics()->GetDocStat().bModified;
+ const sal_Bool bSmartTags = !pViewShell->GetDoc()->GetDocShell()->IsHelpDocument() &&
+ !pViewShell->GetDoc()->isXForms() &&
+ SwSmartTagMgr::Get().IsSmartTagsEnabled(); // SMARTTAGS
+
+ SwPageFrm *pPg = (SwPageFrm*)pRoot->Lower();
+ do
+ {
+ bInValid = pPg->IsInvalidCntnt() || pPg->IsInvalidLayout() ||
+ pPg->IsInvalidFlyCntnt() || pPg->IsInvalidFlyLayout() ||
+ pPg->IsInvalidFlyInCnt() ||
+ (bSpell && pPg->IsInvalidSpelling()) ||
+ (bACmplWrd && pPg->IsInvalidAutoCompleteWords()) ||
+ (bWordCount && pPg->IsInvalidWordCount()) ||
+ (bSmartTags && pPg->IsInvalidSmartTags()); // SMARTTAGS
+
+ pPg = (SwPageFrm*)pPg->GetNext();
+
+ } while ( pPg && !bInValid );
+
+ if ( !bInValid )
+ {
+ pRoot->ResetIdleFormat();
+ SfxObjectShell* pDocShell = pImp->GetShell()->GetDoc()->GetDocShell();
+ pDocShell->Broadcast( SfxEventHint( SW_EVENT_LAYOUT_FINISHED, SwDocShell::GetEventName(STR_SW_EVENT_LAYOUT_FINISHED), pDocShell ) );
+ }
+ }
+
+ pImp->GetShell()->EnableSmooth( sal_True );
+
+ if( pImp->IsAccessible() )
+ pImp->FireAccessibleEvents();
+
+#if OSL_DEBUG_LEVEL > 1
+ if ( bIndicator && pImp->GetShell()->GetWin() )
+ {
+ // #i75172# Do not invalidate indicator, this may cause a endless loop. Instead, just repaint it
+ // This should be replaced by an overlay object in the future, anyways. Since it's only for debug
+ // purposes, it is not urgent.
+ bIndicator = false; SHOW_IDLE( COL_LIGHTGREEN );
+ }
+#endif
+}
+
+SwLayIdle::~SwLayIdle()
+{
+ pImp->pIdleAct = 0;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/layout/laycache.cxx b/sw/source/core/layout/laycache.cxx
new file mode 100644
index 000000000000..60ac1238c19c
--- /dev/null
+++ b/sw/source/core/layout/laycache.cxx
@@ -0,0 +1,1338 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+
+#include <hintids.hxx>
+#include <editeng/brkitem.hxx>
+#include <tools/stream.hxx>
+#include <doc.hxx>
+#include <docstat.hxx>
+#include <docary.hxx>
+#include <fmtpdsc.hxx>
+#include <laycache.hxx>
+#include <layhelp.hxx>
+#include <pagefrm.hxx>
+#include <rootfrm.hxx>
+#include <txtfrm.hxx>
+#include <ndtxt.hxx>
+#include <swtable.hxx>
+#include <tabfrm.hxx>
+#include <rowfrm.hxx>
+#include <colfrm.hxx>
+#include <bodyfrm.hxx>
+#include <ndindex.hxx>
+#include <sectfrm.hxx>
+#include <frmfmt.hxx>
+#include <fmtcntnt.hxx>
+#include <pagedesc.hxx>
+#include <frmtool.hxx>
+#include <dflyobj.hxx>
+#include <dcontact.hxx>
+#include "viewopt.hxx"
+#include "viewsh.hxx"
+#include <flyfrm.hxx>
+// OD 2004-05-24 #i28701#
+#include <sortedobjs.hxx>
+// --> OD 2006-03-22 #b6375613#
+#include <pam.hxx>
+#include <docsh.hxx>
+#include <com/sun/star/document/XDocumentInfoSupplier.hpp>
+#include <com/sun/star/beans/XPropertySet.hpp>
+
+#include <set>
+
+
+using namespace ::com::sun::star;
+// <--
+
+SV_IMPL_PTRARR( SwPageFlyCache, SwFlyCachePtr )
+
+/*-----------------28.5.2001 10:06------------------
+ * Reading and writing of the layout cache.
+ * The layout cache is not necessary, but it improves
+ * the performance and reduces the text flow during
+ * the formatting.
+ * The layout cache contains the index of the paragraphs/tables
+ * at the top of every page, so it's possible to create
+ * the right count of pages and to distribute the document content
+ * to this pages before the formatting starts.
+ *--------------------------------------------------*/
+
+void SwLayoutCache::Read( SvStream &rStream )
+{
+ if( !pImpl )
+ {
+ pImpl = new SwLayCacheImpl;
+ if( !pImpl->Read( rStream ) )
+ {
+ delete pImpl;
+ pImpl = 0;
+ }
+ }
+}
+
+//-----------------------------------------------------------------------------
+
+void SwLayCacheImpl::Insert( sal_uInt16 nType, sal_uLong nIndex, xub_StrLen nOffset )
+{
+ aType.Insert( nType, aType.Count() );
+ SvULongs::Insert( nIndex, SvULongs::Count() );
+ aOffset.push_back( nOffset );
+}
+
+sal_Bool SwLayCacheImpl::Read( SvStream& rStream )
+{
+ SwLayCacheIoImpl aIo( rStream, sal_False );
+ if( aIo.GetMajorVersion() > SW_LAYCACHE_IO_VERSION_MAJOR )
+ return sal_False;
+
+ // Due to an evil bug in the layout cache (#102759#), we cannot trust the
+ // sizes of fly frames which have been written using the "old" layout cache.
+ // This flag should indicate that we do not want to trust the width and
+ // height of fly frames
+ bUseFlyCache = aIo.GetMinorVersion() >= 1;
+
+ sal_uInt8 cFlags;
+ sal_uInt32 nIndex, nOffset;
+
+ aIo.OpenRec( SW_LAYCACHE_IO_REC_PAGES );
+ aIo.OpenFlagRec();
+ aIo.CloseFlagRec();
+ while( aIo.BytesLeft() && !aIo.HasError() )
+ {
+ switch( aIo.Peek() )
+ {
+ case SW_LAYCACHE_IO_REC_PARA:
+ aIo.OpenRec( SW_LAYCACHE_IO_REC_PARA );
+ cFlags = aIo.OpenFlagRec();
+ aIo.GetStream() >> nIndex;
+ if( (cFlags & 0x01) != 0 )
+ aIo.GetStream() >> nOffset;
+ else
+ nOffset = STRING_LEN;
+ aIo.CloseFlagRec();
+ Insert( SW_LAYCACHE_IO_REC_PARA, nIndex, (xub_StrLen)nOffset );
+ aIo.CloseRec( SW_LAYCACHE_IO_REC_PARA );
+ break;
+ case SW_LAYCACHE_IO_REC_TABLE:
+ aIo.OpenRec( SW_LAYCACHE_IO_REC_TABLE );
+ aIo.OpenFlagRec();
+ aIo.GetStream() >> nIndex
+ >> nOffset;
+ Insert( SW_LAYCACHE_IO_REC_TABLE, nIndex, (xub_StrLen)nOffset );
+ aIo.CloseFlagRec();
+ aIo.CloseRec( SW_LAYCACHE_IO_REC_TABLE );
+ break;
+ case SW_LAYCACHE_IO_REC_FLY:
+ {
+ aIo.OpenRec( SW_LAYCACHE_IO_REC_FLY );
+ aIo.OpenFlagRec();
+ aIo.CloseFlagRec();
+ long nX, nY, nW, nH;
+ sal_uInt16 nPgNum;
+ aIo.GetStream() >> nPgNum >> nIndex
+ >> nX >> nY >> nW >> nH;
+ SwFlyCache* pFly = new SwFlyCache( nPgNum, nIndex, nX, nY, nW, nH );
+ aFlyCache.Insert( pFly, aFlyCache.Count() );
+ aIo.CloseRec( SW_LAYCACHE_IO_REC_FLY );
+ break;
+ }
+ default:
+ aIo.SkipRec();
+ break;
+ }
+ }
+ aIo.CloseRec( SW_LAYCACHE_IO_REC_PAGES );
+
+ return !aIo.HasError();
+}
+
+/*-----------------28.5.2001 10:19------------------
+ * SwLayoutCache::Write(..)
+ * writes the index (more precise: the difference between
+ * the index and the first index of the document content)
+ * of the first paragraph/table at the top of every page.
+ * If at the top of a page is the rest of a paragraph/table
+ * from the bottom of the previous page, the character/row
+ * number is stored, too.
+ * The position, size and page number of the text frames
+ * are stored, too
+ * --------------------------------------------------*/
+
+void SwLayoutCache::Write( SvStream &rStream, const SwDoc& rDoc )
+{
+ if( rDoc.GetCurrentLayout() ) // the layout itself .. //swmod 080218
+ {
+ SwLayCacheIoImpl aIo( rStream, sal_True );
+ // We want to save the relative index, so we need the index
+ // of the first content
+ sal_uLong nStartOfContent = rDoc.GetNodes().GetEndOfContent().
+ StartOfSectionNode()->GetIndex();
+ // The first page..
+ SwPageFrm* pPage = (SwPageFrm*)rDoc.GetCurrentLayout()->Lower(); //swmod 080218
+
+ aIo.OpenRec( SW_LAYCACHE_IO_REC_PAGES );
+ aIo.OpenFlagRec( 0, 0 );
+ aIo.CloseFlagRec();
+ while( pPage )
+ {
+ if( pPage->GetPrev() )
+ {
+ SwLayoutFrm* pLay = pPage->FindBodyCont();
+ SwFrm* pTmp = pLay ? pLay->ContainsAny() : NULL;
+ // We are only interested in paragraph or table frames,
+ // a section frames contains paragraphs/tables.
+ if( pTmp && pTmp->IsSctFrm() )
+ pTmp = ((SwSectionFrm*)pTmp)->ContainsAny();
+
+ if( pTmp ) // any content
+ {
+ if( pTmp->IsTxtFrm() )
+ {
+ sal_uLong nNdIdx = ((SwTxtFrm*)pTmp)->GetNode()->GetIndex();
+ if( nNdIdx > nStartOfContent )
+ {
+ /* Open Paragraph Record */
+ aIo.OpenRec( SW_LAYCACHE_IO_REC_PARA );
+ sal_Bool bFollow = ((SwTxtFrm*)pTmp)->IsFollow();
+ aIo.OpenFlagRec( bFollow ? 0x01 : 0x00,
+ bFollow ? 8 : 4 );
+ nNdIdx -= nStartOfContent;
+ aIo.GetStream() << static_cast<sal_uInt32>(nNdIdx);
+ if( bFollow )
+ aIo.GetStream() << static_cast<sal_uInt32>(((SwTxtFrm*)pTmp)->GetOfst());
+ aIo.CloseFlagRec();
+ /* Close Paragraph Record */
+ aIo.CloseRec( SW_LAYCACHE_IO_REC_PARA );
+ }
+ }
+ else if( pTmp->IsTabFrm() )
+ {
+ SwTabFrm* pTab = (SwTabFrm*)pTmp;
+ sal_uLong nOfst = STRING_LEN;
+ if( pTab->IsFollow() )
+ {
+ // If the table is a follow, we have to look for the
+ // master and to count all rows to get the row number
+ nOfst = 0;
+ if( pTab->IsFollow() )
+ pTab = pTab->FindMaster( true );
+ while( pTab != pTmp )
+ {
+ SwFrm* pSub = pTab->Lower();
+ while( pSub )
+ {
+ ++nOfst;
+ pSub = pSub->GetNext();
+ }
+ pTab = pTab->GetFollow();
+ OSL_ENSURE( pTab, "Table follow without master" );
+ }
+ }
+ do
+ {
+ sal_uLong nNdIdx =
+ pTab->GetTable()->GetTableNode()->GetIndex();
+ if( nNdIdx > nStartOfContent )
+ {
+ /* Open Table Record */
+ aIo.OpenRec( SW_LAYCACHE_IO_REC_TABLE );
+ aIo.OpenFlagRec( 0, 8 );
+ nNdIdx -= nStartOfContent;
+ aIo.GetStream() << static_cast<sal_uInt32>(nNdIdx)
+ << static_cast<sal_uInt32>(nOfst);
+ aIo.CloseFlagRec();
+ /* Close Table Record */
+ aIo.CloseRec( SW_LAYCACHE_IO_REC_TABLE );
+ }
+ // If the table has a follow on the next page,
+ // we know already the row number and store this
+ // immediately.
+ if( pTab->GetFollow() )
+ {
+ if( nOfst == STRING_LEN )
+ nOfst = 0;
+ do
+ {
+ SwFrm* pSub = pTab->Lower();
+ while( pSub )
+ {
+ ++nOfst;
+ pSub = pSub->GetNext();
+ }
+ pTab = pTab->GetFollow();
+ SwPageFrm *pTabPage = pTab->FindPageFrm();
+ if( pTabPage != pPage )
+ {
+ OSL_ENSURE( pPage->GetPhyPageNum() <
+ pTabPage->GetPhyPageNum(),
+ "Looping Tableframes" );
+ pPage = pTabPage;
+ break;
+ }
+ } while ( pTab->GetFollow() );
+ }
+ else
+ break;
+ } while( pTab );
+ }
+ }
+ }
+ if( pPage->GetSortedObjs() )
+ {
+ SwSortedObjs &rObjs = *pPage->GetSortedObjs();
+ for ( sal_uInt16 i = 0; i < rObjs.Count(); ++i )
+ {
+ SwAnchoredObject* pAnchoredObj = rObjs[i];
+ if ( pAnchoredObj->ISA(SwFlyFrm) )
+ {
+ SwFlyFrm *pFly = static_cast<SwFlyFrm*>(pAnchoredObj);
+ if( pFly->Frm().Left() != WEIT_WECH &&
+ !pFly->GetAnchorFrm()->FindFooterOrHeader() )
+ {
+ const SwContact *pC =
+ ::GetUserCall(pAnchoredObj->GetDrawObj());
+ if( pC )
+ {
+ sal_uInt32 nOrdNum = pAnchoredObj->GetDrawObj()->GetOrdNum();
+ sal_uInt16 nPageNum = pPage->GetPhyPageNum();
+ /* Open Fly Record */
+ aIo.OpenRec( SW_LAYCACHE_IO_REC_FLY );
+ aIo.OpenFlagRec( 0, 0 );
+ aIo.CloseFlagRec();
+ SwRect &rRct = pFly->Frm();
+ sal_Int32 nX = rRct.Left() - pPage->Frm().Left();
+ sal_Int32 nY = rRct.Top() - pPage->Frm().Top();
+ aIo.GetStream() << nPageNum << nOrdNum
+ << nX << nY << rRct.Width()
+ << rRct.Height();
+ /* Close Fly Record */
+ aIo.CloseRec( SW_LAYCACHE_IO_REC_FLY );
+ }
+ }
+ }
+ }
+ }
+ pPage = (SwPageFrm*)pPage->GetNext();
+ }
+ aIo.CloseRec( SW_LAYCACHE_IO_REC_PAGES );
+ }
+}
+
+#if OSL_DEBUG_LEVEL > 1
+sal_Bool SwLayoutCache::CompareLayout( const SwDoc& rDoc ) const
+{
+ if( !pImpl )
+ return sal_True;
+ const SwRootFrm *pRootFrm = rDoc.GetCurrentLayout();
+ sal_Bool bRet = sal_True;
+ if( pRootFrm )
+ {
+ sal_uInt16 nIndex = 0;
+ sal_uLong nStartOfContent = rDoc.GetNodes().GetEndOfContent().
+ StartOfSectionNode()->GetIndex();
+ SwPageFrm* pPage = (SwPageFrm*)pRootFrm->Lower();
+ if( pPage )
+ pPage = (SwPageFrm*)pPage->GetNext();
+ while( pPage )
+ {
+ if( nIndex >= pImpl->Count() )
+ {
+ if( bRet )
+ bRet = sal_False;
+ break;
+ }
+ SwLayoutFrm* pLay = pPage->FindBodyCont();
+ SwFrm* pTmp = pLay ? pLay->ContainsAny() : NULL;
+ if( pTmp && pTmp->IsSctFrm() )
+ pTmp = ((SwSectionFrm*)pTmp)->ContainsAny();
+ if( pTmp )
+ {
+ if( pTmp->IsTxtFrm() )
+ {
+ sal_uLong nNdIdx = ((SwTxtFrm*)pTmp)->GetNode()->GetIndex();
+ if( nNdIdx > nStartOfContent )
+ {
+ sal_Bool bFollow = ((SwTxtFrm*)pTmp)->IsFollow();
+ nNdIdx -= nStartOfContent;
+ if( pImpl->GetBreakIndex( nIndex ) != nNdIdx ||
+ SW_LAYCACHE_IO_REC_PARA !=
+ pImpl->GetBreakType( nIndex ) ||
+ ( bFollow ? ((SwTxtFrm*)pTmp)->GetOfst()
+ : STRING_LEN ) != pImpl->GetBreakOfst( nIndex ) )
+ {
+ if( bRet )
+ bRet = sal_False;
+ }
+ ++nIndex;
+ }
+ }
+ else if( pTmp->IsTabFrm() )
+ {
+ SwTabFrm* pTab = (SwTabFrm*)pTmp;
+ sal_uLong nOfst = STRING_LEN;
+ if( pTab->IsFollow() )
+ {
+ nOfst = 0;
+ if( pTab->IsFollow() )
+ pTab = pTab->FindMaster( true );
+ while( pTab != pTmp )
+ {
+ SwFrm* pSub = pTab->Lower();
+ while( pSub )
+ {
+ ++nOfst;
+ pSub = pSub->GetNext();
+ }
+ pTab = pTab->GetFollow();
+ }
+ }
+ do
+ {
+ sal_uLong nNdIdx =
+ pTab->GetTable()->GetTableNode()->GetIndex();
+ if( nNdIdx > nStartOfContent )
+ {
+ nNdIdx -= nStartOfContent;
+ if( pImpl->GetBreakIndex( nIndex ) != nNdIdx ||
+ SW_LAYCACHE_IO_REC_TABLE !=
+ pImpl->GetBreakType( nIndex ) ||
+ nOfst != pImpl->GetBreakOfst( nIndex ) )
+ {
+ if( bRet )
+ bRet = sal_False;
+ }
+ ++nIndex;
+ }
+ if( pTab->GetFollow() )
+ {
+ if( nOfst == STRING_LEN )
+ nOfst = 0;
+ do
+ {
+ SwFrm* pSub = pTab->Lower();
+ while( pSub )
+ {
+ ++nOfst;
+ pSub = pSub->GetNext();
+ }
+ pTab = pTab->GetFollow();
+ SwPageFrm *pTabPage = pTab->FindPageFrm();
+ if( pTabPage != pPage )
+ {
+ pPage = pTabPage;
+ break;
+ }
+ } while ( pTab->GetFollow() );
+ }
+ else
+ break;
+ } while( pTab );
+ }
+ }
+ pPage = (SwPageFrm*)pPage->GetNext();
+ }
+ }
+ return bRet;
+}
+#endif
+
+void SwLayoutCache::ClearImpl()
+{
+ if( !IsLocked() )
+ {
+ delete pImpl;
+ pImpl = 0;
+ }
+}
+
+
+SwLayoutCache::~SwLayoutCache()
+{
+ OSL_ENSURE( !nLockCount, "Deleting a locked SwLayoutCache!?" );
+ delete pImpl;
+}
+
+/*-----------------28.5.2001 10:47------------------
+ * SwActualSection,
+ * a help class to create not nested section frames
+ * for nested sections.
+ * --------------------------------------------------*/
+
+SwActualSection::SwActualSection( SwActualSection *pUp,
+ SwSectionFrm *pSect,
+ SwSectionNode *pNd ) :
+ pUpper( pUp ),
+ pSectFrm( pSect ),
+ pSectNode( pNd )
+{
+ if ( !pSectNode )
+ {
+ const SwNodeIndex *pIndex = pSect->GetFmt()->GetCntnt().GetCntntIdx();
+ pSectNode = pIndex->GetNode().FindSectionNode();
+ }
+}
+
+/*-----------------28.5.2001 11:09------------------
+ * SwLayHelper
+ * is the helper class, which utilizes the layout cache information
+ * to distribute the document content to the rigth pages.
+ * It's used by the _InsertCnt(..)-function.
+ * If there's no layout cache, the distibution to the pages is more
+ * a guess, but a guess with statistical background.
+ * --------------------------------------------------*/
+
+SwLayHelper::SwLayHelper( SwDoc *pD, SwFrm* &rpF, SwFrm* &rpP, SwPageFrm* &rpPg,
+ SwLayoutFrm* &rpL, SwActualSection* &rpA, sal_Bool &rB,
+ sal_uLong nNodeIndex, sal_Bool bCache )
+ : rpFrm( rpF ), rpPrv( rpP ), rpPage( rpPg ), rpLay( rpL ),
+ rpActualSection( rpA ), rbBreakAfter(rB), pDoc(pD), nMaxParaPerPage( 25 ),
+ nParagraphCnt( bCache ? 0 : USHRT_MAX ), bFirst( bCache )
+{
+ pImpl = pDoc->GetLayoutCache() ? pDoc->GetLayoutCache()->LockImpl() : NULL;
+ if( pImpl )
+ {
+ nMaxParaPerPage = 1000;
+ nStartOfContent = pDoc->GetNodes().GetEndOfContent().StartOfSectionNode()
+ ->GetIndex();
+ nNodeIndex -= nStartOfContent;
+ nIndex = 0;
+ nFlyIdx = 0;
+ while( nIndex < pImpl->Count() && (*pImpl)[ nIndex ] < nNodeIndex )
+ ++nIndex;
+ if( nIndex >= pImpl->Count() )
+ {
+ pDoc->GetLayoutCache()->UnlockImpl();
+ pImpl = NULL;
+ }
+ }
+ else
+ {
+ nIndex = USHRT_MAX;
+ nStartOfContent = ULONG_MAX;
+ }
+}
+
+SwLayHelper::~SwLayHelper()
+{
+ if( pImpl )
+ {
+ OSL_ENSURE( pDoc && pDoc->GetLayoutCache(), "Missing layoutcache" );
+ pDoc->GetLayoutCache()->UnlockImpl();
+ }
+}
+
+/*-----------------23.5.2001 16:40------------------
+ * SwLayHelper::CalcPageCount() does not really calculate the page count,
+ * it returns the page count value from the layout cache, if available,
+ * otherwise it estimates the page count.
+ * --------------------------------------------------*/
+
+sal_uLong SwLayHelper::CalcPageCount()
+{
+ sal_uLong nPgCount;
+ SwLayCacheImpl *pCache = pDoc->GetLayoutCache() ?
+ pDoc->GetLayoutCache()->LockImpl() : NULL;
+ if( pCache )
+ {
+ nPgCount = pCache->Count() + 1;
+ pDoc->GetLayoutCache()->UnlockImpl();
+ }
+ else
+ {
+ nPgCount = pDoc->GetDocStat().nPage;
+ if ( nPgCount <= 10 ) // no page insertion for less than 10 pages
+ nPgCount = 0;
+ sal_uLong nNdCount = pDoc->GetDocStat().nPara;
+ if ( nNdCount <= 1 )
+ {
+ //Estimates the number of paragraphs.
+ sal_uLong nTmp = pDoc->GetNodes().GetEndOfContent().GetIndex() -
+ pDoc->GetNodes().GetEndOfExtras().GetIndex();
+ //Tables have a little overhead..
+ nTmp -= pDoc->GetTblFrmFmts()->Count() * 25;
+ //Fly frames, too ..
+ nTmp -= (pDoc->GetNodes().GetEndOfAutotext().GetIndex() -
+ pDoc->GetNodes().GetEndOfInserts().GetIndex()) / 3 * 5;
+ if ( nTmp > 0 )
+ nNdCount = nTmp;
+ }
+ if ( nNdCount > 100 ) // no estimation below this value
+ {
+ if ( nPgCount > 0 )
+ nMaxParaPerPage = nNdCount / nPgCount;
+ else
+ {
+ nMaxParaPerPage = Max( sal_uLong(20),
+ sal_uLong(20 + nNdCount / 1000 * 3) );
+#ifdef PM2
+ const sal_uLong nMax = 49;
+#else
+ const sal_uLong nMax = 53;
+#endif
+ nMaxParaPerPage = Min( nMaxParaPerPage, nMax );
+ nPgCount = nNdCount / nMaxParaPerPage;
+ }
+ if ( nNdCount < 1000 )
+ nPgCount = 0;// no progress bar for small documents
+ ViewShell *pSh = 0;
+ if( rpLay && rpLay->getRootFrm() )
+ pSh = rpLay->getRootFrm()->GetCurrShell();
+ if( pSh && pSh->GetViewOptions()->getBrowseMode() )
+ nMaxParaPerPage *= 6;
+ }
+ }
+ return nPgCount;
+}
+
+/*-----------------23.5.2001 16:44------------------
+ * SwLayHelper::CheckInsertPage()
+ * inserts a page and return sal_True, if
+ * - the break after flag is set
+ * - the actual content wants a break before
+ * - the maximum count of paragraph/rows is reached
+ *
+ * The break after flag is set, if the actual content
+ * wants a break after.
+ * --------------------------------------------------*/
+
+sal_Bool SwLayHelper::CheckInsertPage()
+{
+ sal_Bool bEnd = 0 == rpPage->GetNext();
+ const SwAttrSet* pAttr = rpFrm->GetAttrSet();
+ const SvxFmtBreakItem& rBrk = pAttr->GetBreak();
+ const SwFmtPageDesc& rDesc = pAttr->GetPageDesc();
+ // --> FME 2004-10-26 #118195# Do not evaluate page description if frame
+ // is a follow frame!
+ const SwPageDesc* pDesc = rpFrm->IsFlowFrm() &&
+ SwFlowFrm::CastFlowFrm( rpFrm )->IsFollow() ?
+ 0 :
+ rDesc.GetPageDesc();
+ // <--
+
+ sal_Bool bBrk = nParagraphCnt > nMaxParaPerPage || rbBreakAfter;
+ rbBreakAfter = rBrk.GetBreak() == SVX_BREAK_PAGE_AFTER ||
+ rBrk.GetBreak() == SVX_BREAK_PAGE_BOTH;
+ if ( !bBrk )
+ bBrk = rBrk.GetBreak() == SVX_BREAK_PAGE_BEFORE ||
+ rBrk.GetBreak() == SVX_BREAK_PAGE_BOTH;
+
+ if ( bBrk || pDesc )
+ {
+ sal_uInt16 nPgNum = 0;
+ if ( !pDesc )
+ pDesc = rpPage->GetPageDesc()->GetFollow();
+ else
+ {
+ if ( 0 != (nPgNum = rDesc.GetNumOffset()) )
+ ((SwRootFrm*)rpPage->GetUpper())->SetVirtPageNum(sal_True);
+ }
+ sal_Bool bNextPageOdd = !rpPage->OnRightPage();
+ sal_Bool bInsertEmpty = sal_False;
+ if( nPgNum && bNextPageOdd != ( ( nPgNum % 2 ) != 0 ) )
+ {
+ bNextPageOdd = !bNextPageOdd;
+ bInsertEmpty = sal_True;
+ }
+ ::InsertNewPage( (SwPageDesc&)*pDesc, rpPage->GetUpper(),
+ bNextPageOdd, bInsertEmpty, sal_False, rpPage->GetNext() );
+ if ( bEnd )
+ {
+ OSL_ENSURE( rpPage->GetNext(), "Keine neue Seite?" );
+ do
+ { rpPage = (SwPageFrm*)rpPage->GetNext();
+ } while ( rpPage->GetNext() );
+ }
+ else
+ {
+ OSL_ENSURE( rpPage->GetNext(), "Keine neue Seite?" );
+ rpPage = (SwPageFrm*)rpPage->GetNext();
+ if ( rpPage->IsEmptyPage() )
+ {
+ OSL_ENSURE( rpPage->GetNext(), "Keine neue Seite?" );
+ rpPage = (SwPageFrm*)rpPage->GetNext();
+ }
+ }
+ rpLay = rpPage->FindBodyCont();
+ while( rpLay->Lower() )
+ rpLay = (SwLayoutFrm*)rpLay->Lower();
+ return sal_True;
+ }
+ return sal_False;
+}
+
+// --> OD 2006-03-22 #b6375613#
+bool lcl_HasTextFrmAnchoredObjs( SwTxtFrm* p_pTxtFrm )
+{
+ bool bHasTextFrmAnchoredObjs( false );
+
+ const SwSpzFrmFmts* pSpzFrmFmts = p_pTxtFrm->GetTxtNode()->GetDoc()->GetSpzFrmFmts();
+ for ( sal_uInt16 i = 0; i < pSpzFrmFmts->Count(); ++i )
+ {
+ SwFrmFmt *pFmt = (SwFrmFmt*)(*pSpzFrmFmts)[i];
+ const SwFmtAnchor &rAnch = pFmt->GetAnchor();
+ if ( rAnch.GetCntntAnchor() &&
+ ((rAnch.GetAnchorId() == FLY_AT_PARA) ||
+ (rAnch.GetAnchorId() == FLY_AT_CHAR)) &&
+ rAnch.GetCntntAnchor()->nNode.GetIndex() ==
+ p_pTxtFrm->GetTxtNode()->GetIndex() )
+ {
+ bHasTextFrmAnchoredObjs = true;
+ break;
+ }
+ }
+
+ return bHasTextFrmAnchoredObjs;
+}
+
+void lcl_ApplyWorkaroundForB6375613( SwFrm* p_pFirstFrmOnNewPage )
+{
+ SwTxtFrm* pFirstTextFrmOnNewPage = dynamic_cast<SwTxtFrm*>(p_pFirstFrmOnNewPage);
+ //
+ if ( pFirstTextFrmOnNewPage &&
+ !pFirstTextFrmOnNewPage->IsFollow() &&
+ pFirstTextFrmOnNewPage->GetTxt().Len() == 0 &&
+ lcl_HasTextFrmAnchoredObjs( pFirstTextFrmOnNewPage ) )
+ {
+ // apply page break before at this text frame to assure, that it doesn't flow backward.
+ const SvxBreak eBreak =
+ pFirstTextFrmOnNewPage->GetAttrSet()->GetBreak().GetBreak();
+ if ( eBreak == SVX_BREAK_NONE )
+ {
+ pFirstTextFrmOnNewPage->GetTxtNode()->LockModify();
+ SwDoc* pDoc( pFirstTextFrmOnNewPage->GetTxtNode()->GetDoc() );
+ IDocumentContentOperations* pIDCO = pFirstTextFrmOnNewPage->GetTxtNode()->getIDocumentContentOperations();
+ const SwPaM aTmpPaM( *(pFirstTextFrmOnNewPage->GetTxtNode()) );
+ pIDCO->InsertPoolItem( aTmpPaM,
+ SvxFmtBreakItem( SVX_BREAK_PAGE_BEFORE, RES_BREAK ), 0 );
+ pFirstTextFrmOnNewPage->GetTxtNode()->UnlockModify();
+
+ uno::Reference< document::XDocumentInfoSupplier > xDoc(
+ pDoc->GetDocShell()->GetBaseModel(),
+ uno::UNO_QUERY);
+ uno::Reference< beans::XPropertySet > xDocInfo(
+ xDoc->getDocumentInfo(),
+ uno::UNO_QUERY );
+ try
+ {
+ xDocInfo->setPropertyValue( rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("WorkaroundForB6375613Applied")), uno::makeAny( true ) );
+ }
+ catch( uno::Exception& )
+ {
+ }
+ }
+ }
+}
+// <--
+
+/*-----------------28.5.2001 11:31------------------
+ * SwLayHelper::CheckInsert
+ * is the entry point for the _InsertCnt-function.
+ * The document content index is checked either it is
+ * in the layout cache either it's time to insert a page
+ * cause the maximal estimation of content per page is reached.
+ * A really big table or long paragraph may contains more than
+ * one page, in this case the needed count of pages will inserted.
+ * --------------------------------------------------*/
+
+sal_Bool SwLayHelper::CheckInsert( sal_uLong nNodeIndex )
+{
+ sal_Bool bRet = sal_False;
+ sal_Bool bLongTab = sal_False;
+ sal_uLong nMaxRowPerPage( 0 );
+ nNodeIndex -= nStartOfContent;
+ sal_uInt16 nRows( 0 );
+ if( rpFrm->IsTabFrm() )
+ {
+ //Inside a table counts every row as a paragraph
+ SwFrm *pLow = ((SwTabFrm*)rpFrm)->Lower();
+ nRows = 0;
+ do
+ {
+ ++nRows;
+ pLow = pLow->GetNext();
+ } while ( pLow );
+ nParagraphCnt += nRows;
+ if( !pImpl && nParagraphCnt > nMaxParaPerPage + 10 )
+ {
+ // OD 09.04.2003 #108698# - improve heuristics:
+ // Assume that a table, which has more than three times the quantity
+ // of maximal paragraphs per page rows, consists of rows, which have
+ // the height of a normal paragraph. Thus, allow as much rows per page
+ // as much paragraphs are allowed.
+ if ( nRows > ( 3*nMaxParaPerPage ) )
+ {
+ nMaxRowPerPage = nMaxParaPerPage;
+ }
+ else
+ {
+ SwFrm *pTmp = ((SwTabFrm*)rpFrm)->Lower();
+ if( pTmp->GetNext() )
+ pTmp = pTmp->GetNext();
+ pTmp = ((SwRowFrm*)pTmp)->Lower();
+ sal_uInt16 nCnt = 0;
+ do
+ {
+ ++nCnt;
+ pTmp = pTmp->GetNext();
+ } while( pTmp );
+ nMaxRowPerPage = Max( sal_uLong(2), nMaxParaPerPage / nCnt );
+ }
+ bLongTab = sal_True;
+ }
+ }
+ else
+ ++nParagraphCnt;
+ if( bFirst && pImpl && nIndex < pImpl->Count() &&
+ pImpl->GetBreakIndex( nIndex ) == nNodeIndex &&
+ ( pImpl->GetBreakOfst( nIndex ) < STRING_LEN ||
+ ( ++nIndex < pImpl->Count() &&
+ pImpl->GetBreakIndex( nIndex ) == nNodeIndex ) ) )
+ bFirst = sal_False;
+#if OSL_DEBUG_LEVEL > 1
+ sal_uLong nBreakIndex = ( pImpl && nIndex < pImpl->Count() ) ?
+ pImpl->GetBreakIndex(nIndex) : 0xffff;
+ (void)nBreakIndex;
+#endif
+ // OD 09.04.2003 #108698# - always split a big tables.
+ if ( !bFirst ||
+ ( rpFrm->IsTabFrm() && bLongTab )
+ )
+ {
+ sal_uLong nRowCount = 0;
+ do
+ {
+ if( pImpl || bLongTab )
+ {
+#if OSL_DEBUG_LEVEL > 1
+ sal_uLong nBrkIndex = ( pImpl && nIndex < pImpl->Count() ) ?
+ pImpl->GetBreakIndex(nIndex) : 0xffff;
+ (void)nBrkIndex;
+#endif
+ xub_StrLen nOfst = STRING_LEN;
+ sal_uInt16 nType = SW_LAYCACHE_IO_REC_PAGES;
+ if( bLongTab )
+ {
+ rbBreakAfter = sal_True;
+ nOfst = static_cast<xub_StrLen>(nRowCount + nMaxRowPerPage);
+ }
+ else
+ {
+ while( nIndex < pImpl->Count() &&
+ pImpl->GetBreakIndex(nIndex) < nNodeIndex)
+ ++nIndex;
+ if( nIndex < pImpl->Count() &&
+ pImpl->GetBreakIndex(nIndex) == nNodeIndex )
+ {
+ nType = pImpl->GetBreakType( nIndex );
+ nOfst = pImpl->GetBreakOfst( nIndex++ );
+ rbBreakAfter = sal_True;
+ }
+ }
+
+ if( nOfst < STRING_LEN )
+ {
+ sal_Bool bSplit = sal_False;
+ sal_uInt16 nRepeat( 0 );
+ if( !bLongTab && rpFrm->IsTxtFrm() &&
+ SW_LAYCACHE_IO_REC_PARA == nType &&
+ nOfst<((SwTxtFrm*)rpFrm)->GetTxtNode()->GetTxt().Len() )
+ bSplit = sal_True;
+ else if( rpFrm->IsTabFrm() && nRowCount < nOfst &&
+ ( bLongTab || SW_LAYCACHE_IO_REC_TABLE == nType ) )
+ {
+ nRepeat = ((SwTabFrm*)rpFrm)->
+ GetTable()->GetRowsToRepeat();
+ bSplit = nOfst < nRows && nRowCount + nRepeat < nOfst;
+ bLongTab = bLongTab && bSplit;
+ }
+ if( bSplit )
+ {
+ rpFrm->InsertBehind( rpLay, rpPrv );
+ rpFrm->Frm().Pos() = rpLay->Frm().Pos();
+ rpFrm->Frm().Pos().Y() += 1;
+ rpPrv = rpFrm;
+ if( rpFrm->IsTabFrm() )
+ {
+ SwTabFrm* pTab = (SwTabFrm*)rpFrm;
+ // --> OD 2004-09-23 #i33629#, #i29955#
+ ::RegistFlys( pTab->FindPageFrm(), pTab );
+ // <--
+ SwFrm *pRow = pTab->Lower();
+ SwTabFrm *pFoll = new SwTabFrm( *pTab );
+
+ SwFrm *pPrv;
+ if( nRepeat > 0 )
+ {
+ bDontCreateObjects = sal_True; //frmtool
+
+ // Insert new headlines:
+ sal_uInt16 nRowIdx = 0;
+ SwRowFrm* pHeadline = 0;
+ while( nRowIdx < nRepeat )
+ {
+ OSL_ENSURE( pTab->GetTable()->GetTabLines()[ nRowIdx ], "Table ohne Zeilen?" );
+ pHeadline =
+ new SwRowFrm( *pTab->GetTable()->GetTabLines()[ nRowIdx ], pTab );
+ pHeadline->SetRepeatedHeadline( true );
+ pHeadline->InsertBefore( pFoll, 0 );
+ pHeadline->RegistFlys();
+
+ ++nRowIdx;
+ }
+
+ bDontCreateObjects = sal_False;
+ pPrv = pHeadline;
+ nRows = nRows + nRepeat;
+ }
+ else
+ pPrv = 0;
+ while( pRow && nRowCount < nOfst )
+ {
+ pRow = pRow->GetNext();
+ ++nRowCount;
+ }
+ while ( pRow )
+ {
+ SwFrm* pNxt = pRow->GetNext();
+ pRow->Remove();
+ pRow->InsertBehind( pFoll, pPrv );
+ pPrv = pRow;
+ pRow = pNxt;
+ }
+ rpFrm = pFoll;
+ }
+ else
+ {
+ SwTxtFrm *pNew = new SwTxtFrm( ((SwTxtFrm*)rpFrm)->
+ GetTxtNode(), rpFrm );
+ pNew->_SetIsFollow( sal_True );
+ pNew->ManipOfst( nOfst );
+ pNew->SetFollow( ((SwTxtFrm*)rpFrm)->GetFollow() );
+ ((SwTxtFrm*)rpFrm)->SetFollow( pNew );
+ rpFrm = pNew;
+ }
+ }
+ }
+ }
+
+ SwPageFrm* pLastPage = rpPage;
+ if( CheckInsertPage() )
+ {
+ // --> OD 2006-03-21 #b6375613#
+ if ( pDoc->ApplyWorkaroundForB6375613() )
+ {
+ lcl_ApplyWorkaroundForB6375613( rpFrm );
+ }
+ // <--
+ _CheckFlyCache( pLastPage );
+ if( rpPrv && rpPrv->IsTxtFrm() && !rpPrv->GetValidSizeFlag() )
+ rpPrv->Frm().Height( rpPrv->GetUpper()->Prt().Height() );
+
+ bRet = sal_True;
+ rpPrv = 0;
+ nParagraphCnt = 0;
+
+ if ( rpActualSection )
+ {
+ //Hatte der SectionFrm ueberhaupt Inhalt? Wenn
+ //nicht kann er gleich umgehaengt werden.
+ SwSectionFrm *pSct;
+ bool bInit = false;
+ if ( !rpActualSection->GetSectionFrm()->ContainsCntnt())
+ {
+ pSct = rpActualSection->GetSectionFrm();
+ pSct->Remove();
+ }
+ else
+ {
+ pSct = new SwSectionFrm(
+ *rpActualSection->GetSectionFrm(), sal_False );
+ rpActualSection->GetSectionFrm()->SimpleFormat();
+ bInit = true;
+ }
+ rpActualSection->SetSectionFrm( pSct );
+ pSct->InsertBehind( rpLay, 0 );
+ if( bInit )
+ pSct->Init();
+ pSct->Frm().Pos() = rpLay->Frm().Pos();
+ pSct->Frm().Pos().Y() += 1; //wg. Benachrichtigungen.
+
+ rpLay = pSct;
+ if ( rpLay->Lower() && rpLay->Lower()->IsLayoutFrm() )
+ rpLay = rpLay->GetNextLayoutLeaf();
+ }
+ }
+ } while( bLongTab || ( pImpl && nIndex < pImpl->Count() &&
+ (*pImpl)[ nIndex ] == nNodeIndex ) );
+ }
+ bFirst = sal_False;
+ return bRet;
+}
+
+struct SdrObjectCompare
+{
+ bool operator()( const SdrObject* pF1, const SdrObject* pF2 ) const
+ {
+ return pF1->GetOrdNum() < pF2->GetOrdNum();
+ }
+};
+
+struct FlyCacheCompare
+{
+ bool operator()( const SwFlyCache* pC1, const SwFlyCache* pC2 ) const
+ {
+ return pC1->nOrdNum < pC2->nOrdNum;
+ }
+};
+
+ /*-----------------28.6.2001 14:40------------------
+ * SwLayHelper::_CheckFlyCache(..)
+ * If a new page is inserted, the last page is analysed.
+ * If there are text frames with default position, the fly cache
+ * is checked, if these frames are stored in the cache.
+ * --------------------------------------------------*/
+
+void SwLayHelper::_CheckFlyCache( SwPageFrm* pPage )
+{
+ if( !pImpl || !pPage )
+ return;
+ sal_uInt16 nFlyCount = pImpl->GetFlyCount();
+ // Any text frames at the page, fly cache avaiable?
+ if( pPage->GetSortedObjs() && nFlyIdx < nFlyCount )
+ {
+ SwSortedObjs &rObjs = *pPage->GetSortedObjs();
+ sal_uInt16 nPgNum = pPage->GetPhyPageNum();
+
+ //
+ // NOTE: Here we do not use the absolute ordnums but
+ // relative ordnums for the objects on this page.
+
+ // skip fly frames from pages before the current page
+ SwFlyCache* pFlyC;
+ while( nFlyIdx < nFlyCount && ( pFlyC = pImpl->
+ GetFlyCache(nFlyIdx) )->nPageNum < nPgNum)
+ ++nFlyIdx;
+
+ // sort cached objects on this page by ordnum
+ std::set< const SwFlyCache*, FlyCacheCompare > aFlyCacheSet;
+ sal_uInt16 nIdx = nFlyIdx;
+
+ while( nIdx < nFlyCount && ( pFlyC = pImpl->
+ GetFlyCache( nIdx ) )->nPageNum == nPgNum )
+ {
+ aFlyCacheSet.insert( pFlyC );
+ ++nIdx;
+ }
+
+ // sort objects on this page by ordnum
+ std::set< const SdrObject*, SdrObjectCompare > aFlySet;
+ for ( sal_uInt16 i = 0; i < rObjs.Count(); ++i )
+ {
+ SwAnchoredObject* pAnchoredObj = rObjs[i];
+ if ( pAnchoredObj->ISA(SwFlyFrm) ) // a text frame?
+ {
+ SwFlyFrm *pFly = static_cast<SwFlyFrm*>(pAnchoredObj);
+ if( pFly->GetAnchorFrm() &&
+ !pFly->GetAnchorFrm()->FindFooterOrHeader() )
+ {
+ const SwContact *pC = ::GetUserCall( pAnchoredObj->GetDrawObj() );
+ if( pC )
+ {
+ aFlySet.insert( pAnchoredObj->GetDrawObj() );
+ }
+ }
+ }
+ }
+
+ if ( aFlyCacheSet.size() == aFlySet.size() )
+ {
+ std::set< const SwFlyCache*, FlyCacheCompare >::iterator aFlyCacheSetIt =
+ aFlyCacheSet.begin();
+ std::set< const SdrObject*, SdrObjectCompare >::iterator aFlySetIt =
+ aFlySet.begin();
+
+ while ( aFlyCacheSetIt != aFlyCacheSet.end() )
+ {
+ const SwFlyCache* pFlyCache = *aFlyCacheSetIt;
+ SwFlyFrm* pFly = ((SwVirtFlyDrawObj*)*aFlySetIt)->GetFlyFrm();
+
+ if ( pFly->Frm().Left() == WEIT_WECH )
+ {
+ // we get the stored information
+ pFly->Frm().Pos().X() = pFlyCache->Left() +
+ pPage->Frm().Left();
+ pFly->Frm().Pos().Y() = pFlyCache->Top() +
+ pPage->Frm().Top();
+ if ( pImpl->IsUseFlyCache() )
+ {
+ pFly->Frm().Width( pFlyCache->Width() );
+ pFly->Frm().Height( pFlyCache->Height() );
+ }
+ }
+
+ ++aFlyCacheSetIt;
+ ++aFlySetIt;
+ }
+ }
+ }
+}
+
+/*-----------------28.6.2001 14:48------------------
+ * SwLayHelper::CheckPageFlyCache(..)
+ * looks for the given text frame in the fly cache and sets
+ * the position and size, if possible.
+ * The fly cache is sorted by pages and we start searching with the given page.
+ * If we found the page number in the fly cache, we set
+ * the rpPage parameter to the right page, if possible.
+ * --------------------------------------------------*/
+
+sal_Bool SwLayHelper::CheckPageFlyCache( SwPageFrm* &rpPage, SwFlyFrm* pFly )
+{
+ if( !pFly->GetAnchorFrm() || !pFly->GetVirtDrawObj() ||
+ pFly->GetAnchorFrm()->FindFooterOrHeader() )
+ return sal_False;
+ sal_Bool bRet = sal_False;
+ SwDoc* pDoc = rpPage->GetFmt()->GetDoc();
+ SwLayCacheImpl *pCache = pDoc->GetLayoutCache() ?
+ pDoc->GetLayoutCache()->LockImpl() : NULL;
+ if( pCache )
+ {
+ sal_uInt16 nPgNum = rpPage->GetPhyPageNum();
+ sal_uInt16 nIdx = 0;
+ sal_uInt16 nCnt = pCache->GetFlyCount();
+ sal_uLong nOrdNum = pFly->GetVirtDrawObj()->GetOrdNum();
+ SwFlyCache* pFlyC = 0;
+
+ // skip fly frames from pages before the current page
+ while( nIdx < nCnt &&
+ nPgNum > (pFlyC = pCache->GetFlyCache( nIdx ))->nPageNum )
+ ++nIdx;
+
+ while( nIdx < nCnt &&
+ nOrdNum != (pFlyC = pCache->GetFlyCache( nIdx ))->nOrdNum )
+ ++nIdx;
+ if( nIdx < nCnt )
+ {
+ SwPageFrm *pPage = rpPage;
+ while( pPage && pPage->GetPhyPageNum() < pFlyC->nPageNum )
+ pPage = (SwPageFrm*)pPage->GetNext();
+ // --> OD 2005-02-22 #i43266# - if the found page is an empty page,
+ // take the previous one (take next one, if previous one doesn't exists)
+ if ( pPage && pPage->IsEmptyPage() )
+ {
+ pPage = static_cast<SwPageFrm*>( pPage->GetPrev()
+ ? pPage->GetPrev()
+ : pPage->GetNext() );
+ }
+ // <--
+ if( pPage )
+ {
+ rpPage = pPage;
+ pFly->Frm().Pos().X() = pFlyC->Left() + pPage->Frm().Left();
+ pFly->Frm().Pos().Y() = pFlyC->Top() + pPage->Frm().Top();
+ if ( pCache->IsUseFlyCache() )
+ {
+ pFly->Frm().Width( pFlyC->Width() );
+ pFly->Frm().Height( pFlyC->Height() );
+ }
+ bRet = sal_True;
+ }
+ }
+ pDoc->GetLayoutCache()->UnlockImpl();
+ }
+ return bRet;
+}
+
+// -----------------------------------------------------------------------------
+
+SwLayCacheIoImpl::SwLayCacheIoImpl( SvStream& rStrm, sal_Bool bWrtMd ) :
+ pStream( &rStrm ),
+ nMajorVersion(SW_LAYCACHE_IO_VERSION_MAJOR),
+ nMinorVersion(SW_LAYCACHE_IO_VERSION_MINOR),
+ bWriteMode( bWrtMd ),
+ bError( sal_False )
+{
+ if( bWriteMode )
+ *pStream << nMajorVersion
+ << nMinorVersion;
+
+ else
+ *pStream >> nMajorVersion
+ >> nMinorVersion;
+}
+
+sal_Bool SwLayCacheIoImpl::OpenRec( sal_uInt8 cType )
+{
+ sal_Bool bRes = sal_True;
+ sal_uInt32 nPos = pStream->Tell();
+ if( bWriteMode )
+ {
+ aRecords.push_back( RecTypeSize(cType, nPos) );
+ *pStream << (sal_uInt32) 0;
+ }
+ else
+ {
+ sal_uInt32 nVal;
+ *pStream >> nVal;
+ sal_uInt8 cRecTyp = (sal_uInt8)nVal;
+ if( !nVal || cRecTyp != cType ||
+ pStream->GetErrorCode() != SVSTREAM_OK || pStream->IsEof() )
+ {
+ OSL_ENSURE( nVal, "OpenRec: Record-Header is 0" );
+ OSL_ENSURE( cRecTyp == cType, "OpenRec: Wrong Record Type" );
+ aRecords.push_back( RecTypeSize(0, pStream->Tell()) );
+ bRes = sal_False;
+ bError = sal_True;
+ }
+ else
+ {
+ sal_uInt32 nSize = nVal >> 8;
+ aRecords.push_back( RecTypeSize(cRecTyp, nPos+nSize) );
+ }
+ }
+ return bRes;
+}
+
+// Close record
+
+sal_Bool SwLayCacheIoImpl::CloseRec( sal_uInt8 )
+{
+ sal_Bool bRes = sal_True;
+ OSL_ENSURE( !aRecords.empty(), "CloseRec: no levels" );
+ if( !aRecords.empty() )
+ {
+ sal_uInt32 nPos = pStream->Tell();
+ if( bWriteMode )
+ {
+ sal_uInt32 nBgn = aRecords.back().size;
+ pStream->Seek( nBgn );
+ sal_uInt32 nSize = nPos - nBgn;
+ sal_uInt32 nVal = ( nSize << 8 ) | aRecords.back().type;
+ *pStream << nVal;
+ pStream->Seek( nPos );
+ if( pStream->GetError() != SVSTREAM_OK )
+ bRes = sal_False;
+ }
+ else
+ {
+ sal_uInt32 n = aRecords.back().size;
+ OSL_ENSURE( n >= nPos, "CloseRec: to much data read" );
+ if( n != nPos )
+ {
+ pStream->Seek( n );
+ if( n < nPos )
+ bRes = sal_False;
+ }
+ if( pStream->GetErrorCode() != SVSTREAM_OK )
+ bRes = sal_False;
+ }
+ aRecords.pop_back();
+ }
+
+ if( !bRes )
+ bError = sal_True;
+
+ return bRes;
+}
+
+sal_uInt32 SwLayCacheIoImpl::BytesLeft()
+{
+ sal_uInt32 n = 0;
+ if( !bError && !aRecords.empty() )
+ {
+ sal_uInt32 nEndPos = aRecords.back().size;
+ sal_uInt32 nPos = pStream->Tell();
+ if( nEndPos > nPos )
+ n = nEndPos - nPos;
+ }
+ return n;
+}
+
+sal_uInt8 SwLayCacheIoImpl::Peek()
+{
+ sal_uInt8 c = 0;
+ if( !bError )
+ {
+ sal_uInt32 nPos = pStream->Tell();
+ *pStream >> c;
+ pStream->Seek( nPos );
+ if( pStream->GetErrorCode() != SVSTREAM_OK )
+ {
+ c = 0;
+ bError = sal_True;
+ }
+ }
+ return c;
+}
+
+void SwLayCacheIoImpl::SkipRec()
+{
+ sal_uInt8 c = Peek();
+ OpenRec( c );
+ pStream->Seek( aRecords.back().size );
+ CloseRec( c );
+}
+
+sal_uInt8 SwLayCacheIoImpl::OpenFlagRec()
+{
+ OSL_ENSURE( !bWriteMode, "OpenFlagRec illegal in write mode" );
+ sal_uInt8 cFlags;
+ *pStream >> cFlags;
+ nFlagRecEnd = pStream->Tell() + ( cFlags & 0x0F );
+ return (cFlags >> 4);
+}
+
+void SwLayCacheIoImpl::OpenFlagRec( sal_uInt8 nFlags, sal_uInt8 nLen )
+{
+ OSL_ENSURE( bWriteMode, "OpenFlagRec illegal in read mode" );
+ OSL_ENSURE( (nFlags & 0xF0) == 0, "illegal flags set" );
+ OSL_ENSURE( nLen < 16, "wrong flag record length" );
+ sal_uInt8 cFlags = (nFlags << 4) + nLen;
+ *pStream << cFlags;
+ nFlagRecEnd = pStream->Tell() + nLen;
+}
+
+void SwLayCacheIoImpl::CloseFlagRec()
+{
+ if( bWriteMode )
+ {
+ OSL_ENSURE( pStream->Tell() == nFlagRecEnd, "Wrong amount of data written" );
+ }
+ else
+ {
+ OSL_ENSURE( pStream->Tell() <= nFlagRecEnd, "To many data read" );
+ if( pStream->Tell() != nFlagRecEnd )
+ pStream->Seek( nFlagRecEnd );
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/layout/layhelp.hxx b/sw/source/core/layout/layhelp.hxx
new file mode 100644
index 000000000000..d690940320d7
--- /dev/null
+++ b/sw/source/core/layout/layhelp.hxx
@@ -0,0 +1,240 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+#ifndef _LAYHELP_HXX
+#define _LAYHELP_HXX
+#ifndef _SVSTDARR_HXX
+#define _SVSTDARR_USHORTS
+#define _SVSTDARR_ULONGS
+#define _SVSTDARR_XUB_STRLEN
+#include <svl/svstdarr.hxx>
+#endif
+#include <swrect.hxx>
+#include <vector>
+
+class SwDoc;
+class SwFrm;
+class SwLayoutFrm;
+class SwPageFrm;
+class SwFlyFrm;
+class SwSectionFrm;
+class SwSectionNode;
+class SvStream;
+
+/*************************************************************************
+ * class SwLayCacheImpl
+ * contains the page break information and the text frame positions
+ * of the document (after loading)
+ * and is used inside the constructor of the layout rootframe to
+ * insert content and text frames at the right pages.
+ * For every page of the main text (body content, no footnotes, text frames etc.)
+ * we have the nodeindex of the first content at the page,
+ * the type of content ( table or paragraph )
+ * and if it's not the first part of the table/paragraph,
+ * the row/character-offset inside the table/paragraph.
+ * The text frame positions are stored in the SwPageFlyCache array.
+ *************************************************************************/
+
+class SwFlyCache;
+typedef SwFlyCache* SwFlyCachePtr;
+SV_DECL_PTRARR_DEL( SwPageFlyCache, SwFlyCachePtr, 0, 4 )
+
+class SwLayCacheImpl : public SvULongs
+{
+ SvXub_StrLens aOffset;
+ SvUShorts aType;
+ SwPageFlyCache aFlyCache;
+ sal_Bool bUseFlyCache;
+ void Insert( sal_uInt16 nType, sal_uLong nIndex, xub_StrLen nOffset );
+
+public:
+ SwLayCacheImpl() : SvULongs( 20, 10 ), aType( 20, 10 ) {}
+ sal_Bool Read( SvStream& rStream );
+
+ sal_uLong GetBreakIndex( sal_uInt16 nIdx ) const { return GetObject( nIdx ); }
+ xub_StrLen GetBreakOfst( size_t nIdx ) const { return aOffset[ nIdx ]; }
+ sal_uInt16 GetBreakType( sal_uInt16 nIdx ) const { return aType[ nIdx ]; }
+
+ sal_uInt16 GetFlyCount() const { return aFlyCache.Count(); }
+ SwFlyCache *GetFlyCache( sal_uInt16 nIdx ) const { return aFlyCache[ nIdx ]; }
+
+ sal_Bool IsUseFlyCache() const { return bUseFlyCache; }
+};
+
+/*************************************************************************
+ * class SwActualSection
+ * helps to create the sectionframes during the _InsertCnt-function
+ * by controlling nested sections.
+ *************************************************************************/
+
+class SwActualSection
+{
+ SwActualSection *pUpper;
+ SwSectionFrm *pSectFrm;
+ SwSectionNode *pSectNode;
+public:
+ SwActualSection( SwActualSection *pUpper,
+ SwSectionFrm *pSect,
+ SwSectionNode *pNd );
+
+ SwSectionFrm *GetSectionFrm() { return pSectFrm; }
+ void SetSectionFrm( SwSectionFrm *p ) { pSectFrm = p; }
+ SwSectionNode *GetSectionNode() { return pSectNode;}
+ SwActualSection *GetUpper() { return pUpper; }
+};
+
+/*************************************************************************
+ * class SwLayHelper
+ * helps during the _InsertCnt-function to create new pages.
+ * If there's a layoutcache available, this information is used.
+ *************************************************************************/
+
+class SwLayHelper
+{
+ SwFrm* &rpFrm;
+ SwFrm* &rpPrv;
+ SwPageFrm* &rpPage;
+ SwLayoutFrm* &rpLay;
+ SwActualSection* &rpActualSection;
+ sal_Bool &rbBreakAfter;
+ SwDoc* pDoc;
+ SwLayCacheImpl* pImpl;
+ sal_uLong nMaxParaPerPage;
+ sal_uLong nParagraphCnt;
+ sal_uLong nStartOfContent;
+ sal_uInt16 nIndex; // the index in the page break array
+ sal_uInt16 nFlyIdx; // the index in the fly cache array
+ sal_Bool bFirst : 1;
+ void _CheckFlyCache( SwPageFrm* pPage );
+public:
+ SwLayHelper( SwDoc *pD, SwFrm* &rpF, SwFrm* &rpP, SwPageFrm* &rpPg,
+ SwLayoutFrm* &rpL, SwActualSection* &rpA, sal_Bool &rBrk,
+ sal_uLong nNodeIndex, sal_Bool bCache );
+ ~SwLayHelper();
+ sal_uLong CalcPageCount();
+ sal_Bool CheckInsert( sal_uLong nNodeIndex );
+
+ sal_Bool BreakPage( xub_StrLen& rOffs, sal_uLong nNodeIndex );
+ sal_Bool CheckInsertPage();
+
+ // Look for fresh text frames at this (new) page and set them to the right
+ // position, if they are in the fly cache.
+ void CheckFlyCache( SwPageFrm* pPage )
+ { if( pImpl && nFlyIdx < pImpl->GetFlyCount() ) _CheckFlyCache( pPage ); }
+
+ // Look for this text frame and set it to the right position,
+ // if it's in the fly cache.
+ static sal_Bool CheckPageFlyCache( SwPageFrm* &rpPage, SwFlyFrm* pFly );
+};
+
+/*************************************************************************
+ * class SwLayCacheIoImpl
+ * contains the data structures that are required to read and write a
+ * layout cache.
+ *************************************************************************/
+
+#define SW_LAYCACHE_IO_REC_PAGES 'p'
+#define SW_LAYCACHE_IO_REC_PARA 'P'
+#define SW_LAYCACHE_IO_REC_TABLE 'T'
+#define SW_LAYCACHE_IO_REC_FLY 'F'
+
+#define SW_LAYCACHE_IO_VERSION_MAJOR 1
+#define SW_LAYCACHE_IO_VERSION_MINOR 1
+
+class SwLayCacheIoImpl
+{
+private:
+ struct RecTypeSize {
+ sal_uInt8 type;
+ sal_uLong size;
+ RecTypeSize(sal_uInt8 typ, sal_uLong siz) : type(typ), size(siz) {}
+ };
+ std::vector<RecTypeSize> aRecords;
+
+ SvStream *pStream;
+
+ sal_uLong nFlagRecEnd;
+
+ sal_uInt16 nMajorVersion;
+ sal_uInt16 nMinorVersion;
+
+ sal_Bool bWriteMode : 1;
+ sal_Bool bError : 1;
+
+public:
+ SwLayCacheIoImpl( SvStream& rStrm, sal_Bool bWrtMd );
+
+ // Get input or output stream
+ SvStream& GetStream() const { return *pStream; }
+
+ // Open a record of type "nType"
+ sal_Bool OpenRec( sal_uInt8 nType );
+
+ // Close a record of type "nType". This skips any unread data that
+ // remains in the record.
+ sal_Bool CloseRec( sal_uInt8 nType );
+
+ // Return the number of bytes contained in the current record that
+ // haven't been read by now.
+ sal_uInt32 BytesLeft();
+
+ // Return the current record's type
+ sal_uInt8 Peek();
+
+ // Skip the current record
+ void SkipRec();
+
+ // Open a flag record for reading. The uppermost four bits are flags,
+ // while the lowermost are the flag record's size. Flag records cannot
+ // be nested.
+ sal_uInt8 OpenFlagRec();
+
+ // Open flag record for writing;
+ void OpenFlagRec( sal_uInt8 nFlags, sal_uInt8 nLen );
+
+ // Close a flag record. Any bytes left are skipped.
+ void CloseFlagRec();
+
+ sal_Bool HasError() const { return bError; }
+
+ sal_uInt16 GetMajorVersion() const { return nMajorVersion; }
+ sal_uInt16 GetMinorVersion() const { return nMinorVersion; }
+};
+
+// Stored information about text frames:
+class SwFlyCache : public SwRect // position and size
+{
+public:
+ sal_uLong nOrdNum; // Id to recognize text frames
+ sal_uInt16 nPageNum; // page number
+ SwFlyCache( sal_uInt16 nP, sal_uLong nO, long nXL, long nYL, long nWL, long nHL ) :
+ SwRect( nXL, nYL, nWL, nHL ), nOrdNum( nO ), nPageNum( nP ){}
+};
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/layout/layouter.cxx b/sw/source/core/layout/layouter.cxx
new file mode 100644
index 000000000000..a02b17401c01
--- /dev/null
+++ b/sw/source/core/layout/layouter.cxx
@@ -0,0 +1,565 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+#include "layouter.hxx"
+#include "doc.hxx"
+#include "sectfrm.hxx"
+#include "ftnboss.hxx"
+#include "cntfrm.hxx"
+#include "pagefrm.hxx"
+#include "ftnfrm.hxx"
+#include "txtfrm.hxx"
+
+// --> OD 2004-06-23 #i28701#
+#include <movedfwdfrmsbyobjpos.hxx>
+// <--
+// --> OD 2004-10-22 #i35911#
+#include <objstmpconsiderwrapinfl.hxx>
+// <--
+
+#define LOOP_DETECT 250
+
+class SwLooping
+{
+ sal_uInt16 nMinPage;
+ sal_uInt16 nMaxPage;
+ sal_uInt16 nCount;
+ sal_uInt16 mnLoopControlStage;
+public:
+ SwLooping( SwPageFrm* pPage );
+ void Control( SwPageFrm* pPage );
+ void Drastic( SwFrm* pFrm );
+ bool IsLoopingLouieLight() const { return nCount > LOOP_DETECT - 30; };
+};
+
+class SwEndnoter
+{
+ SwLayouter* pMaster;
+ SwSectionFrm* pSect;
+ SvPtrarr* pEndArr;
+public:
+ SwEndnoter( SwLayouter* pLay )
+ : pMaster( pLay ), pSect( NULL ), pEndArr( NULL ) {}
+ ~SwEndnoter() { delete pEndArr; }
+ void CollectEndnotes( SwSectionFrm* pSct );
+ void CollectEndnote( SwFtnFrm* pFtn );
+ const SwSectionFrm* GetSect() const { return pSect; }
+ void InsertEndnotes();
+ sal_Bool HasEndnotes() const { return pEndArr && pEndArr->Count(); }
+};
+
+void SwEndnoter::CollectEndnotes( SwSectionFrm* pSct )
+{
+ OSL_ENSURE( pSct, "CollectEndnotes: Which section?" );
+ if( !pSect )
+ pSect = pSct;
+ else if( pSct != pSect )
+ return;
+ pSect->CollectEndnotes( pMaster );
+}
+
+void SwEndnoter::CollectEndnote( SwFtnFrm* pFtn )
+{
+ if( pEndArr && USHRT_MAX != pEndArr->GetPos( (VoidPtr)pFtn ) )
+ return;
+
+ if( pFtn->GetUpper() )
+ {
+ // pFtn is the master, he incorporates its follows
+ SwFtnFrm *pNxt = pFtn->GetFollow();
+ while ( pNxt )
+ {
+ SwFrm *pCnt = pNxt->ContainsAny();
+ if ( pCnt )
+ {
+ do
+ { SwFrm *pNxtCnt = pCnt->GetNext();
+ pCnt->Cut();
+ pCnt->Paste( pFtn );
+ pCnt = pNxtCnt;
+ } while ( pCnt );
+ }
+ else
+ { OSL_ENSURE( pNxt->Lower() && pNxt->Lower()->IsSctFrm(),
+ "Endnote without content?" );
+ pNxt->Cut();
+ delete pNxt;
+ }
+ pNxt = pFtn->GetFollow();
+ }
+ if( pFtn->GetMaster() )
+ return;
+ pFtn->Cut();
+ }
+ else if( pEndArr )
+ {
+ for ( sal_uInt16 i = 0; i < pEndArr->Count(); ++i )
+ {
+ SwFtnFrm *pEndFtn = (SwFtnFrm*)((*pEndArr)[i]);
+ if( pEndFtn->GetAttr() == pFtn->GetAttr() )
+ {
+ delete pFtn;
+ return;
+ }
+ }
+ }
+ if( !pEndArr )
+ pEndArr = new SvPtrarr( 5, 5 ); // deleted from the SwLayouter
+ pEndArr->Insert( (VoidPtr)pFtn, pEndArr->Count() );
+}
+
+void SwEndnoter::InsertEndnotes()
+{
+ if( !pSect )
+ return;
+ if( !pEndArr || !pEndArr->Count() )
+ {
+ pSect = NULL;
+ return;
+ }
+ OSL_ENSURE( pSect->Lower() && pSect->Lower()->IsFtnBossFrm(),
+ "InsertEndnotes: Where's my column?" );
+ SwFrm* pRef = pSect->FindLastCntnt( FINDMODE_MYLAST );
+ SwFtnBossFrm *pBoss = pRef ? pRef->FindFtnBossFrm()
+ : (SwFtnBossFrm*)pSect->Lower();
+ pBoss->_MoveFtns( *pEndArr );
+ delete pEndArr;
+ pEndArr = NULL;
+ pSect = NULL;
+}
+
+SwLooping::SwLooping( SwPageFrm* pPage )
+{
+ OSL_ENSURE( pPage, "Where's my page?" );
+ nMinPage = pPage->GetPhyPageNum();
+ nMaxPage = nMinPage;
+ nCount = 0;
+ mnLoopControlStage = 0;
+}
+
+void SwLooping::Drastic( SwFrm* pFrm )
+{
+ while( pFrm )
+ {
+ pFrm->ValidateThisAndAllLowers( mnLoopControlStage );
+ pFrm = pFrm->GetNext();
+ }
+}
+
+void SwLooping::Control( SwPageFrm* pPage )
+{
+ if( !pPage )
+ return;
+ sal_uInt16 nNew = pPage->GetPhyPageNum();
+ if( nNew > nMaxPage )
+ nMaxPage = nNew;
+ if( nNew < nMinPage )
+ {
+ nMinPage = nNew;
+ nMaxPage = nNew;
+ nCount = 0;
+ mnLoopControlStage = 0;
+ }
+ else if( nNew > nMinPage + 2 )
+ {
+ nMinPage = nNew - 2;
+ nMaxPage = nNew;
+ nCount = 0;
+ mnLoopControlStage = 0;
+ }
+ else if( ++nCount > LOOP_DETECT )
+ {
+#if OSL_DEBUG_LEVEL > 1
+ static sal_Bool bNoLouie = sal_False;
+ if( bNoLouie )
+ return;
+
+ // FME 2007-08-30 #i81146# new loop control
+ OSL_ENSURE( 0 != mnLoopControlStage, "Looping Louie: Stage 1!" );
+ OSL_ENSURE( 1 != mnLoopControlStage, "Looping Louie: Stage 2!!" );
+ OSL_ENSURE( 2 > mnLoopControlStage, "Looping Louie: Stage 3!!!" );
+#endif
+
+ Drastic( pPage->Lower() );
+ if( nNew > nMinPage && pPage->GetPrev() )
+ Drastic( ((SwPageFrm*)pPage->GetPrev())->Lower() );
+ if( nNew < nMaxPage && pPage->GetNext() )
+ Drastic( ((SwPageFrm*)pPage->GetNext())->Lower() );
+
+ ++mnLoopControlStage;
+ nCount = 0;
+ }
+}
+
+/*************************************************************************
+|*
+|* SwLayouter::SwLayouter()
+|*
+|*************************************************************************/
+
+SwLayouter::SwLayouter()
+ : pEndnoter( NULL ),
+ pLooping( NULL ),
+ // --> OD 2004-06-23 #i28701#
+ mpMovedFwdFrms( 0L ),
+ // <--
+ // --> OD 2004-10-22 #i35911#
+ mpObjsTmpConsiderWrapInfl( 0L )
+ // <--
+{
+}
+
+SwLayouter::~SwLayouter()
+{
+ delete pEndnoter;
+ delete pLooping;
+ // --> OD 2004-06-23 #i28701#
+ delete mpMovedFwdFrms;
+ mpMovedFwdFrms = 0L;
+ // <--
+ // --> OD 2004-10-22 #i35911#
+ delete mpObjsTmpConsiderWrapInfl;
+ mpObjsTmpConsiderWrapInfl = 0L;
+ // <--
+}
+
+void SwLayouter::_CollectEndnotes( SwSectionFrm* pSect )
+{
+ if( !pEndnoter )
+ pEndnoter = new SwEndnoter( this );
+ pEndnoter->CollectEndnotes( pSect );
+}
+
+sal_Bool SwLayouter::HasEndnotes() const
+{
+ return pEndnoter->HasEndnotes();
+}
+
+void SwLayouter::CollectEndnote( SwFtnFrm* pFtn )
+{
+ pEndnoter->CollectEndnote( pFtn );
+}
+
+void SwLayouter::InsertEndnotes( SwSectionFrm* pSect )
+{
+ if( !pEndnoter || pEndnoter->GetSect() != pSect )
+ return;
+ pEndnoter->InsertEndnotes();
+}
+
+void SwLayouter::LoopControl( SwPageFrm* pPage, sal_uInt8 )
+{
+ OSL_ENSURE( pLooping, "Looping: Lost control" );
+ pLooping->Control( pPage );
+}
+
+void SwLayouter::LoopingLouieLight( const SwDoc& rDoc, const SwTxtFrm& rFrm )
+{
+ if ( pLooping && pLooping->IsLoopingLouieLight() )
+ {
+#if OSL_DEBUG_LEVEL > 1
+ OSL_FAIL( "Looping Louie (Light): Fixating fractious frame" );
+#endif
+ SwLayouter::InsertMovedFwdFrm( rDoc, rFrm, rFrm.FindPageFrm()->GetPhyPageNum() );
+ }
+}
+
+sal_Bool SwLayouter::StartLooping( SwPageFrm* pPage )
+{
+ if( pLooping )
+ return sal_False;
+ pLooping = new SwLooping( pPage );
+ return sal_True;
+}
+
+void SwLayouter::EndLoopControl()
+{
+ delete pLooping;
+ pLooping = NULL;
+}
+
+void SwLayouter::CollectEndnotes( SwDoc* pDoc, SwSectionFrm* pSect )
+{
+ OSL_ENSURE( pDoc, "No doc, no fun" );
+ if( !pDoc->GetLayouter() )
+ pDoc->SetLayouter( new SwLayouter() );
+ pDoc->GetLayouter()->_CollectEndnotes( pSect );
+}
+
+sal_Bool SwLayouter::Collecting( SwDoc* pDoc, SwSectionFrm* pSect, SwFtnFrm* pFtn )
+{
+ if( !pDoc->GetLayouter() )
+ return sal_False;
+ SwLayouter *pLayouter = pDoc->GetLayouter();
+ if( pLayouter->pEndnoter && pLayouter->pEndnoter->GetSect() && pSect &&
+ ( pLayouter->pEndnoter->GetSect()->IsAnFollow( pSect ) ||
+ pSect->IsAnFollow( pLayouter->pEndnoter->GetSect() ) ) )
+ {
+ if( pFtn )
+ pLayouter->CollectEndnote( pFtn );
+ return sal_True;
+ }
+ return sal_False;
+}
+
+sal_Bool SwLayouter::StartLoopControl( SwDoc* pDoc, SwPageFrm *pPage )
+{
+ OSL_ENSURE( pDoc, "No doc, no fun" );
+ if( !pDoc->GetLayouter() )
+ pDoc->SetLayouter( new SwLayouter() );
+ return !pDoc->GetLayouter()->pLooping &&
+ pDoc->GetLayouter()->StartLooping( pPage );
+}
+
+// --> OD 2004-06-23 #i28701#
+// -----------------------------------------------------------------------------
+// methods to manage text frames, which are moved forward by the positioning
+// of its anchored objects
+// -----------------------------------------------------------------------------
+void SwLayouter::ClearMovedFwdFrms( const SwDoc& _rDoc )
+{
+ if ( _rDoc.GetLayouter() &&
+ _rDoc.GetLayouter()->mpMovedFwdFrms )
+ {
+ _rDoc.GetLayouter()->mpMovedFwdFrms->Clear();
+ }
+}
+
+void SwLayouter::InsertMovedFwdFrm( const SwDoc& _rDoc,
+ const SwTxtFrm& _rMovedFwdFrmByObjPos,
+ const sal_uInt32 _nToPageNum )
+{
+ if ( !_rDoc.GetLayouter() )
+ {
+ const_cast<SwDoc&>(_rDoc).SetLayouter( new SwLayouter() );
+ }
+
+ if ( !_rDoc.GetLayouter()->mpMovedFwdFrms )
+ {
+ const_cast<SwDoc&>(_rDoc).GetLayouter()->mpMovedFwdFrms =
+ new SwMovedFwdFrmsByObjPos();
+ }
+
+ _rDoc.GetLayouter()->mpMovedFwdFrms->Insert( _rMovedFwdFrmByObjPos,
+ _nToPageNum );
+}
+
+// --> OD 2005-01-12 #i40155#
+void SwLayouter::RemoveMovedFwdFrm( const SwDoc& _rDoc,
+ const SwTxtFrm& _rTxtFrm )
+{
+ sal_uInt32 nDummy;
+ if ( SwLayouter::FrmMovedFwdByObjPos( _rDoc, _rTxtFrm, nDummy ) )
+ {
+ _rDoc.GetLayouter()->mpMovedFwdFrms->Remove( _rTxtFrm );
+ }
+}
+// <--
+
+bool SwLayouter::FrmMovedFwdByObjPos( const SwDoc& _rDoc,
+ const SwTxtFrm& _rTxtFrm,
+ sal_uInt32& _ornToPageNum )
+{
+ if ( !_rDoc.GetLayouter() )
+ {
+ _ornToPageNum = 0;
+ return false;
+ }
+ else if ( !_rDoc.GetLayouter()->mpMovedFwdFrms )
+ {
+ _ornToPageNum = 0;
+ return false;
+ }
+ else
+ {
+ return _rDoc.GetLayouter()->mpMovedFwdFrms->
+ FrmMovedFwdByObjPos( _rTxtFrm, _ornToPageNum );
+ }
+}
+// <--
+// --> OD 2004-10-05 #i26945#
+bool SwLayouter::DoesRowContainMovedFwdFrm( const SwDoc& _rDoc,
+ const SwRowFrm& _rRowFrm )
+{
+ if ( !_rDoc.GetLayouter() )
+ {
+ return false;
+ }
+ else if ( !_rDoc.GetLayouter()->mpMovedFwdFrms )
+ {
+ return false;
+ }
+ else
+ {
+ return _rDoc.GetLayouter()->
+ mpMovedFwdFrms->DoesRowContainMovedFwdFrm( _rRowFrm );
+ }
+}
+// <--
+
+// --> OD 2004-10-22 #i35911#
+void SwLayouter::ClearObjsTmpConsiderWrapInfluence( const SwDoc& _rDoc )
+{
+ if ( _rDoc.GetLayouter() &&
+ _rDoc.GetLayouter()->mpObjsTmpConsiderWrapInfl )
+ {
+ _rDoc.GetLayouter()->mpObjsTmpConsiderWrapInfl->Clear();
+ }
+}
+void SwLayouter::InsertObjForTmpConsiderWrapInfluence(
+ const SwDoc& _rDoc,
+ SwAnchoredObject& _rAnchoredObj )
+{
+ if ( !_rDoc.GetLayouter() )
+ {
+ const_cast<SwDoc&>(_rDoc).SetLayouter( new SwLayouter() );
+ }
+
+ if ( !_rDoc.GetLayouter()->mpObjsTmpConsiderWrapInfl )
+ {
+ const_cast<SwDoc&>(_rDoc).GetLayouter()->mpObjsTmpConsiderWrapInfl =
+ new SwObjsMarkedAsTmpConsiderWrapInfluence();
+ }
+
+ _rDoc.GetLayouter()->mpObjsTmpConsiderWrapInfl->Insert( _rAnchoredObj );
+}
+// <--
+// --> OD 2005-01-12 #i40155#
+void SwLayouter::ClearFrmsNotToWrap( const SwDoc& _rDoc )
+{
+ if ( _rDoc.GetLayouter() )
+ {
+ const_cast<SwDoc&>(_rDoc).GetLayouter()->maFrmsNotToWrap.clear();
+ }
+}
+
+void SwLayouter::InsertFrmNotToWrap( const SwDoc& _rDoc,
+ const SwFrm& _rFrm )
+{
+ if ( !_rDoc.GetLayouter() )
+ {
+ const_cast<SwDoc&>(_rDoc).SetLayouter( new SwLayouter() );
+ }
+
+ if ( !SwLayouter::FrmNotToWrap( _rDoc, _rFrm ) )
+ {
+ const_cast<SwDoc&>(_rDoc).GetLayouter()->maFrmsNotToWrap.push_back( &_rFrm );
+ }
+}
+
+bool SwLayouter::FrmNotToWrap( const IDocumentLayoutAccess& _rDLA,
+ const SwFrm& _rFrm )
+{
+ const SwLayouter* pLayouter = _rDLA.GetLayouter();
+ if ( !pLayouter )
+ {
+ return false;
+ }
+ else
+ {
+ bool bFrmNotToWrap( false );
+ std::vector< const SwFrm* >::const_iterator aIter =
+ pLayouter->maFrmsNotToWrap.begin();
+ for ( ; aIter != pLayouter->maFrmsNotToWrap.end(); ++aIter )
+ {
+ const SwFrm* pFrm = *(aIter);
+ if ( pFrm == &_rFrm )
+ {
+ bFrmNotToWrap = true;
+ break;
+ }
+ }
+ return bFrmNotToWrap;
+ }
+}
+// <--
+
+void LOOPING_LOUIE_LIGHT( bool bCondition, const SwTxtFrm& rTxtFrm )
+{
+ if ( bCondition )
+ {
+ const SwDoc& rDoc = *rTxtFrm.GetAttrSet()->GetDoc();
+ if ( rDoc.GetLayouter() )
+ {
+ const_cast<SwDoc&>(rDoc).GetLayouter()->LoopingLouieLight( rDoc, rTxtFrm );
+ }
+ }
+}
+
+// --> OD 2006-05-10 #i65250#
+bool SwLayouter::MoveBwdSuppressed( const SwDoc& p_rDoc,
+ const SwFlowFrm& p_rFlowFrm,
+ const SwLayoutFrm& p_rNewUpperFrm )
+{
+ bool bMoveBwdSuppressed( false );
+
+ if ( !p_rDoc.GetLayouter() )
+ {
+ const_cast<SwDoc&>(p_rDoc).SetLayouter( new SwLayouter() );
+ }
+
+ // create hash map key
+ tMoveBwdLayoutInfoKey aMoveBwdLayoutInfo;
+ aMoveBwdLayoutInfo.mnFrmId = p_rFlowFrm.GetFrm()->GetFrmId();
+ aMoveBwdLayoutInfo.mnNewUpperPosX = p_rNewUpperFrm.Frm().Pos().X();
+ aMoveBwdLayoutInfo.mnNewUpperPosY = p_rNewUpperFrm.Frm().Pos().Y();
+ aMoveBwdLayoutInfo.mnNewUpperWidth = p_rNewUpperFrm.Frm().Width();
+ aMoveBwdLayoutInfo.mnNewUpperHeight = p_rNewUpperFrm.Frm().Height();
+ SWRECTFN( (&p_rNewUpperFrm) )
+ const SwFrm* pLastLower( p_rNewUpperFrm.Lower() );
+ while ( pLastLower && pLastLower->GetNext() )
+ {
+ pLastLower = pLastLower->GetNext();
+ }
+ aMoveBwdLayoutInfo.mnFreeSpaceInNewUpper =
+ pLastLower
+ ? (pLastLower->Frm().*fnRect->fnBottomDist)( (p_rNewUpperFrm.*fnRect->fnGetPrtBottom)() )
+ : (p_rNewUpperFrm.Frm().*fnRect->fnGetHeight)();
+
+ // check for moving backward suppress threshold
+ const sal_uInt16 cMoveBwdCountSuppressThreshold = 20;
+ if ( ++const_cast<SwDoc&>(p_rDoc).GetLayouter()->maMoveBwdLayoutInfo[ aMoveBwdLayoutInfo ] >
+ cMoveBwdCountSuppressThreshold )
+ {
+ bMoveBwdSuppressed = true;
+ }
+
+ return bMoveBwdSuppressed;
+}
+
+void SwLayouter::ClearMoveBwdLayoutInfo( const SwDoc& _rDoc )
+{
+ if ( _rDoc.GetLayouter() )
+ const_cast<SwDoc&>(_rDoc).GetLayouter()->maMoveBwdLayoutInfo.clear();
+}
+// <--
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/layout/movedfwdfrmsbyobjpos.cxx b/sw/source/core/layout/movedfwdfrmsbyobjpos.cxx
new file mode 100644
index 000000000000..7ce3bf320579
--- /dev/null
+++ b/sw/source/core/layout/movedfwdfrmsbyobjpos.cxx
@@ -0,0 +1,108 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+#include <movedfwdfrmsbyobjpos.hxx>
+#include <txtfrm.hxx>
+#include <rowfrm.hxx>
+#include <pagefrm.hxx>
+#include <ndtxt.hxx>
+#include <switerator.hxx>
+
+SwMovedFwdFrmsByObjPos::SwMovedFwdFrmsByObjPos()
+{
+}
+
+SwMovedFwdFrmsByObjPos::~SwMovedFwdFrmsByObjPos()
+{
+ Clear();
+}
+
+void SwMovedFwdFrmsByObjPos::Insert( const SwTxtFrm& _rMovedFwdFrmByObjPos,
+ const sal_uInt32 _nToPageNum )
+{
+ if ( maMovedFwdFrms.end() ==
+ maMovedFwdFrms.find( _rMovedFwdFrmByObjPos.GetTxtNode() ) )
+ {
+ const NodeMapEntry aEntry( _rMovedFwdFrmByObjPos.GetTxtNode(), _nToPageNum );
+ maMovedFwdFrms.insert( aEntry );
+ }
+}
+
+void SwMovedFwdFrmsByObjPos::Remove( const SwTxtFrm& _rTxtFrm )
+{
+ maMovedFwdFrms.erase( _rTxtFrm.GetTxtNode() );
+};
+
+bool SwMovedFwdFrmsByObjPos::FrmMovedFwdByObjPos( const SwTxtFrm& _rTxtFrm,
+ sal_uInt32& _ornToPageNum ) const
+{
+ NodeMapIter aIter = maMovedFwdFrms.find( _rTxtFrm.GetTxtNode() );
+ if ( maMovedFwdFrms.end() != aIter )
+ {
+ _ornToPageNum = (*aIter).second;
+ return true;
+ }
+
+ return false;
+}
+
+// --> OD 2004-10-05 #i26945#
+bool SwMovedFwdFrmsByObjPos::DoesRowContainMovedFwdFrm( const SwRowFrm& _rRowFrm ) const
+{
+ bool bDoesRowContainMovedFwdFrm( false );
+
+ const sal_uInt32 nPageNumOfRow = _rRowFrm.FindPageFrm()->GetPhyPageNum();
+
+ NodeMapIter aIter = maMovedFwdFrms.begin();
+ for ( ; aIter != maMovedFwdFrms.end(); ++aIter )
+ {
+ const NodeMapEntry& rEntry = *(aIter);
+ if ( rEntry.second >= nPageNumOfRow )
+ {
+ SwIterator<SwTxtFrm,SwTxtNode> aFrmIter( *rEntry.first );
+ for( SwTxtFrm* pTxtFrm = aFrmIter.First(); pTxtFrm; pTxtFrm = (SwTxtFrm*)aFrmIter.Next() )
+ {
+ // --> OD 2004-12-03 #115759# - assure that found text frame
+ // is the first one.
+ if ( _rRowFrm.IsAnLower( pTxtFrm ) && !pTxtFrm->GetIndPrev() )
+ // <--
+ {
+ bDoesRowContainMovedFwdFrm = true;
+ break;
+ }
+ }
+ }
+ }
+
+ return bDoesRowContainMovedFwdFrm;
+}
+// <--
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/layout/newfrm.cxx b/sw/source/core/layout/newfrm.cxx
new file mode 100644
index 000000000000..faefa9c3e8b0
--- /dev/null
+++ b/sw/source/core/layout/newfrm.cxx
@@ -0,0 +1,679 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+#include <svx/svdmodel.hxx>
+#include <svx/svdpage.hxx>
+#include <fmtfordr.hxx>
+#include <fmtpdsc.hxx>
+#include <frmfmt.hxx>
+#include <swtable.hxx>
+#include <rootfrm.hxx>
+#include <pagefrm.hxx>
+#include <cntfrm.hxx>
+#include <viewsh.hxx>
+#include <doc.hxx>
+#include <node.hxx>
+#include <dflyobj.hxx>
+#include <frmtool.hxx>
+#include <virtoutp.hxx>
+#include <blink.hxx>
+#include <ndindex.hxx>
+#include <sectfrm.hxx>
+#include <notxtfrm.hxx>
+#include <pagedesc.hxx>
+#include "viewimp.hxx"
+#include "IDocumentTimerAccess.hxx"
+#include "IDocumentLayoutAccess.hxx"
+#include "IDocumentFieldsAccess.hxx"
+#include "IDocumentSettingAccess.hxx"
+#include "IDocumentDrawModelAccess.hxx"
+#include <hints.hxx>
+#include <viewopt.hxx>
+
+SwLayVout *SwRootFrm::pVout = 0;
+sal_Bool SwRootFrm::bInPaint = sal_False;
+sal_Bool SwRootFrm::bNoVirDev = sal_False;
+
+SwCache *SwFrm::pCache = 0;
+
+long FirstMinusSecond( long nFirst, long nSecond )
+ { return nFirst - nSecond; }
+long SecondMinusFirst( long nFirst, long nSecond )
+ { return nSecond - nFirst; }
+long SwIncrement( long nA, long nAdd )
+ { return nA + nAdd; }
+long SwDecrement( long nA, long nSub )
+ { return nA - nSub; }
+
+static SwRectFnCollection aHorizontal = {
+ /* fnRectGet */
+ &SwRect::_Top,
+ &SwRect::_Bottom,
+ &SwRect::_Left,
+ &SwRect::_Right,
+ &SwRect::_Width,
+ &SwRect::_Height,
+ &SwRect::TopLeft,
+ &SwRect::_Size,
+ /* fnRectSet */
+ &SwRect::_Top,
+ &SwRect::_Bottom,
+ &SwRect::_Left,
+ &SwRect::_Right,
+ &SwRect::_Width,
+ &SwRect::_Height,
+
+ &SwRect::SubTop,
+ &SwRect::AddBottom,
+ &SwRect::SubLeft,
+ &SwRect::AddRight,
+ &SwRect::AddWidth,
+ &SwRect::AddHeight,
+
+ &SwRect::SetPosX,
+ &SwRect::SetPosY,
+
+ &SwFrm::GetTopMargin,
+ &SwFrm::GetBottomMargin,
+ &SwFrm::GetLeftMargin,
+ &SwFrm::GetRightMargin,
+ &SwFrm::SetLeftRightMargins,
+ &SwFrm::SetTopBottomMargins,
+ &SwFrm::GetPrtTop,
+ &SwFrm::GetPrtBottom,
+ &SwFrm::GetPrtLeft,
+ &SwFrm::GetPrtRight,
+ &SwRect::GetTopDistance,
+ &SwRect::GetBottomDistance,
+ &SwRect::GetLeftDistance,
+ &SwRect::GetRightDistance,
+ &SwFrm::SetMaxBottom,
+ &SwRect::OverStepBottom,
+
+ &SwRect::SetUpperLeftCorner,
+ &SwFrm::MakeBelowPos,
+ &FirstMinusSecond,
+ &FirstMinusSecond,
+ &SwIncrement,
+ &SwIncrement,
+ &SwRect::SetLeftAndWidth,
+ &SwRect::SetTopAndHeight
+};
+
+static SwRectFnCollection aVertical = {
+ /* fnRectGet */
+ &SwRect::_Right,
+ &SwRect::_Left,
+ &SwRect::_Top,
+ &SwRect::_Bottom,
+ &SwRect::_Height,
+ &SwRect::_Width,
+ &SwRect::TopRight,
+ &SwRect::SwappedSize,
+ /* fnRectSet */
+ &SwRect::_Right,
+ &SwRect::_Left,
+ &SwRect::_Top,
+ &SwRect::_Bottom,
+ &SwRect::_Height,
+ &SwRect::_Width,
+
+ &SwRect::AddRight,
+ &SwRect::SubLeft,
+ &SwRect::SubTop,
+ &SwRect::AddBottom,
+ &SwRect::AddHeight,
+ &SwRect::AddWidth,
+
+ &SwRect::SetPosY,
+ &SwRect::SetPosX,
+
+ &SwFrm::GetRightMargin,
+ &SwFrm::GetLeftMargin,
+ &SwFrm::GetTopMargin,
+ &SwFrm::GetBottomMargin,
+ &SwFrm::SetTopBottomMargins,
+ &SwFrm::SetRightLeftMargins,
+ &SwFrm::GetPrtRight,
+ &SwFrm::GetPrtLeft,
+ &SwFrm::GetPrtTop,
+ &SwFrm::GetPrtBottom,
+ &SwRect::GetRightDistance,
+ &SwRect::GetLeftDistance,
+ &SwRect::GetTopDistance,
+ &SwRect::GetBottomDistance,
+ &SwFrm::SetMinLeft,
+ &SwRect::OverStepLeft,
+
+ &SwRect::SetUpperRightCorner,
+ &SwFrm::MakeLeftPos,
+ &FirstMinusSecond,
+ &SecondMinusFirst,
+ &SwIncrement,
+ &SwDecrement,
+ &SwRect::SetTopAndHeight,
+ &SwRect::SetRightAndWidth
+};
+
+static SwRectFnCollection aBottomToTop = {
+ /* fnRectGet */
+ &SwRect::_Bottom,
+ &SwRect::_Top,
+ &SwRect::_Left,
+ &SwRect::_Right,
+ &SwRect::_Width,
+ &SwRect::_Height,
+ &SwRect::BottomLeft,
+ &SwRect::_Size,
+ /* fnRectSet */
+ &SwRect::_Bottom,
+ &SwRect::_Top,
+ &SwRect::_Left,
+ &SwRect::_Right,
+ &SwRect::_Width,
+ &SwRect::_Height,
+
+ &SwRect::AddBottom,
+ &SwRect::SubTop,
+ &SwRect::SubLeft,
+ &SwRect::AddRight,
+ &SwRect::AddWidth,
+ &SwRect::AddHeight,
+
+ &SwRect::SetPosX,
+ &SwRect::SetPosY,
+
+ &SwFrm::GetBottomMargin,
+ &SwFrm::GetTopMargin,
+ &SwFrm::GetLeftMargin,
+ &SwFrm::GetRightMargin,
+ &SwFrm::SetLeftRightMargins,
+ &SwFrm::SetBottomTopMargins,
+ &SwFrm::GetPrtBottom,
+ &SwFrm::GetPrtTop,
+ &SwFrm::GetPrtLeft,
+ &SwFrm::GetPrtRight,
+ &SwRect::GetBottomDistance,
+ &SwRect::GetTopDistance,
+ &SwRect::GetLeftDistance,
+ &SwRect::GetRightDistance,
+ &SwFrm::SetMinTop,
+ &SwRect::OverStepTop,
+
+ &SwRect::SetLowerLeftCorner,
+ &SwFrm::MakeUpperPos,
+ &FirstMinusSecond,
+ &SecondMinusFirst,
+ &SwIncrement,
+ &SwDecrement,
+ &SwRect::SetLeftAndWidth,
+ &SwRect::SetBottomAndHeight
+};
+
+static SwRectFnCollection aVerticalRightToLeft = {
+ /* fnRectGet */
+ &SwRect::_Left,
+ &SwRect::_Right,
+ &SwRect::_Top,
+ &SwRect::_Bottom,
+ &SwRect::_Height,
+ &SwRect::_Width,
+ &SwRect::BottomRight,
+ &SwRect::SwappedSize,
+ /* fnRectSet */
+ &SwRect::_Left,
+ &SwRect::_Right,
+ &SwRect::_Top,
+ &SwRect::_Bottom,
+ &SwRect::_Height,
+ &SwRect::_Width,
+
+ &SwRect::SubLeft,
+ &SwRect::AddRight,
+ &SwRect::SubTop,
+ &SwRect::AddBottom,
+ &SwRect::AddHeight,
+ &SwRect::AddWidth,
+
+ &SwRect::SetPosY,
+ &SwRect::SetPosX,
+
+ &SwFrm::GetLeftMargin,
+ &SwFrm::GetRightMargin,
+ &SwFrm::GetTopMargin,
+ &SwFrm::GetBottomMargin,
+ &SwFrm::SetTopBottomMargins,
+ &SwFrm::SetLeftRightMargins,
+ &SwFrm::GetPrtLeft,
+ &SwFrm::GetPrtRight,
+ &SwFrm::GetPrtBottom,
+ &SwFrm::GetPrtTop,
+ &SwRect::GetLeftDistance,
+ &SwRect::GetRightDistance,
+ &SwRect::GetBottomDistance,
+ &SwRect::GetTopDistance,
+ &SwFrm::SetMaxRight,
+ &SwRect::OverStepRight,
+
+ &SwRect::SetLowerLeftCorner,
+ &SwFrm::MakeRightPos,
+ &FirstMinusSecond,
+ &FirstMinusSecond,
+ &SwDecrement,
+ &SwIncrement,
+ &SwRect::SetBottomAndHeight,
+ &SwRect::SetLeftAndWidth
+};
+//Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin
+static SwRectFnCollection aVerticalLeftToRight = {
+ /* fnRectGet */
+ &SwRect::_Left,
+ &SwRect::_Right,
+ &SwRect::_Top,
+ &SwRect::_Bottom,
+ &SwRect::_Height,
+ &SwRect::_Width,
+ &SwRect::TopLeft,
+ &SwRect::SwappedSize,
+ /* fnRectSet */
+ &SwRect::_Left,
+ &SwRect::_Right,
+ &SwRect::_Top,
+ &SwRect::_Bottom,
+ &SwRect::_Height,
+ &SwRect::_Width,
+
+ &SwRect::SubLeft,
+ &SwRect::AddRight,
+ &SwRect::SubTop,
+ &SwRect::AddBottom,
+ &SwRect::AddHeight,
+ &SwRect::AddWidth,
+
+ &SwRect::SetPosY,
+ &SwRect::SetPosX,
+
+ &SwFrm::GetLeftMargin,
+ &SwFrm::GetRightMargin,
+ &SwFrm::GetTopMargin,
+ &SwFrm::GetBottomMargin,
+ &SwFrm::SetTopBottomMargins,
+ &SwFrm::SetLeftRightMargins,
+ &SwFrm::GetPrtLeft,
+ &SwFrm::GetPrtRight,
+ &SwFrm::GetPrtTop,
+ &SwFrm::GetPrtBottom,
+ &SwRect::GetLeftDistance,
+ &SwRect::GetRightDistance,
+ &SwRect::GetTopDistance,
+ &SwRect::GetBottomDistance,
+ &SwFrm::SetMaxRight,
+ &SwRect::OverStepRight,
+
+ &SwRect::SetUpperLeftCorner,
+ &SwFrm::MakeRightPos,
+ &FirstMinusSecond,
+ &FirstMinusSecond,
+ &SwIncrement,
+ &SwIncrement,
+ &SwRect::SetTopAndHeight,
+ &SwRect::SetLeftAndWidth
+};
+//End of SCMS
+SwRectFn fnRectHori = &aHorizontal;
+SwRectFn fnRectVert = &aVertical;
+//Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin
+SwRectFn fnRectVertL2R = &aVerticalLeftToRight;
+//End of SCMS
+SwRectFn fnRectB2T = &aBottomToTop;
+SwRectFn fnRectVL2R = &aVerticalRightToLeft;
+
+// --> OD 2006-05-10 #i65250#
+sal_uInt32 SwFrm::mnLastFrmId=0;
+// <--
+
+TYPEINIT1(SwFrm,SwClient); //rtti fuer SwFrm
+TYPEINIT1(SwCntntFrm,SwFrm); //rtti fuer SwCntntFrm
+
+
+void _FrmInit()
+{
+ SwRootFrm::pVout = new SwLayVout();
+ SwCache *pNew = new SwCache( 100, 100
+#if OSL_DEBUG_LEVEL > 1
+ , "static SwBorderAttrs::pCache"
+#endif
+ );
+ SwFrm::SetCache( pNew );
+}
+
+
+
+void _FrmFinit()
+{
+#if OSL_DEBUG_LEVEL > 1
+ // im Chache duerfen nur noch 0-Pointer stehen
+ for( sal_uInt16 n = SwFrm::GetCachePtr()->Count(); n; )
+ if( (*SwFrm::GetCachePtr())[ --n ] )
+ {
+ SwCacheObj* pObj = (*SwFrm::GetCachePtr())[ n ];
+ OSL_ENSURE( !pObj, "Wer hat sich nicht ausgetragen?");
+ }
+#endif
+ delete SwRootFrm::pVout;
+ delete SwFrm::GetCachePtr();
+}
+
+/*************************************************************************
+|*
+|* RootFrm::Alles was so zur CurrShell gehoert
+|*
+|*************************************************************************/
+
+typedef CurrShell* CurrShellPtr;
+SV_DECL_PTRARR_SORT(SwCurrShells,CurrShellPtr,4,4)
+SV_IMPL_PTRARR_SORT(SwCurrShells,CurrShellPtr)
+
+CurrShell::CurrShell( ViewShell *pNew )
+{
+ OSL_ENSURE( pNew, "0-Shell einsetzen?" );
+ pRoot = pNew->GetLayout();
+ if ( pRoot )
+ {
+ pPrev = pRoot->pCurrShell;
+ pRoot->pCurrShell = pNew;
+ pRoot->pCurrShells->Insert( this );
+ }
+ else
+ pPrev = 0;
+}
+
+CurrShell::~CurrShell()
+{
+ if ( pRoot )
+ {
+ pRoot->pCurrShells->Remove( this );
+ if ( pPrev )
+ pRoot->pCurrShell = pPrev;
+ if ( !pRoot->pCurrShells->Count() && pRoot->pWaitingCurrShell )
+ {
+ pRoot->pCurrShell = pRoot->pWaitingCurrShell;
+ pRoot->pWaitingCurrShell = 0;
+ }
+ }
+}
+
+void SetShell( ViewShell *pSh )
+{
+ SwRootFrm *pRoot = pSh->GetLayout();
+ if ( !pRoot->pCurrShells->Count() )
+ pRoot->pCurrShell = pSh;
+ else
+ pRoot->pWaitingCurrShell = pSh;
+}
+
+void SwRootFrm::DeRegisterShell( ViewShell *pSh )
+{
+ //Wenn moeglich irgendeine Shell aktivieren
+ if ( pCurrShell == pSh )
+ pCurrShell = pSh->GetNext() != pSh ? (ViewShell*)pSh->GetNext() : 0;
+
+ //Das hat sich eruebrigt
+ if ( pWaitingCurrShell == pSh )
+ pWaitingCurrShell = 0;
+
+ //Referenzen entfernen.
+ for ( sal_uInt16 i = 0; i < pCurrShells->Count(); ++i )
+ {
+ CurrShell *pC = (*pCurrShells)[i];
+ if (pC->pPrev == pSh)
+ pC->pPrev = 0;
+ }
+}
+
+void InitCurrShells( SwRootFrm *pRoot )
+{
+ pRoot->pCurrShells = new SwCurrShells;
+}
+
+
+/*************************************************************************
+|*
+|* SwRootFrm::SwRootFrm()
+|*
+|* Beschreibung:
+|* Der RootFrm laesst sich grundsaetzlich vom Dokument ein eigenes
+|* FrmFmt geben. Dieses loescht er dann selbst im DTor.
+|* Das eigene FrmFmt wird vom uebergebenen Format abgeleitet.
+|*
+|*************************************************************************/
+
+
+SwRootFrm::SwRootFrm( SwFrmFmt *pFmt, ViewShell * pSh ) :
+ SwLayoutFrm( pFmt->GetDoc()->MakeFrmFmt(
+ XubString( "Root", RTL_TEXTENCODING_MS_1252 ), pFmt ), 0 ),
+ // --> PAGES01
+ maPagesArea(),
+ mnViewWidth( -1 ),
+ mnColumns( 0 ),
+ mbBookMode( false ),
+ mbSidebarChanged( false ),
+ mbNeedGrammarCheck( false ),
+ // <--
+ nBrowseWidth( MM50*4 ), //2cm Minimum
+ pTurbo( 0 ),
+ pLastPage( 0 ),
+ pCurrShell( pSh ),
+ pWaitingCurrShell( 0 ),
+ pDrawPage( 0 ),
+ pDestroy( 0 ),
+ nPhyPageNums( 0 ),
+ nAccessibleShells( 0 )
+{
+ nType = FRMC_ROOT;
+ bIdleFormat = bTurboAllowed = bAssertFlyPages = bIsNewLayout = sal_True;
+ bCheckSuperfluous = bBrowseWidthValid = sal_False;
+ setRootFrm( this );
+}
+
+void SwRootFrm::Init( SwFrmFmt* pFmt )
+{
+ InitCurrShells( this );
+
+ IDocumentTimerAccess *pTimerAccess = pFmt->getIDocumentTimerAccess();
+ IDocumentLayoutAccess *pLayoutAccess = pFmt->getIDocumentLayoutAccess();
+ IDocumentFieldsAccess *pFieldsAccess = pFmt->getIDocumentFieldsAccess();
+ const IDocumentSettingAccess *pSettingAccess = pFmt->getIDocumentSettingAccess();
+ pTimerAccess->StopIdling();
+ pLayoutAccess->SetCurrentViewShell( this->GetCurrShell() ); //Fuer das Erzeugen der Flys durch MakeFrms() //swmod 071108//swmod 071225
+ bCallbackActionEnabled = sal_False; //vor Verlassen auf sal_True setzen!
+
+ SdrModel *pMd = pFmt->getIDocumentDrawModelAccess()->GetDrawModel();
+ if ( pMd )
+ {
+ // Disable "multiple layout"
+ pDrawPage = pMd->GetPage(0); //pMd->AllocPage( FALSE );
+ //pMd->InsertPage( pDrawPage );
+ // end of disabling
+
+ pDrawPage->SetSize( Frm().SSize() );
+ }
+
+ //Initialisierung des Layouts: Seiten erzeugen. Inhalt mit cntnt verbinden
+ //usw.
+ //Zuerst einiges initialiseren und den ersten Node besorgen (der wird
+ //fuer den PageDesc benoetigt).
+
+ SwDoc* pDoc = pFmt->GetDoc();
+ SwNodeIndex aIndex( *pDoc->GetNodes().GetEndOfContent().StartOfSectionNode() );
+ SwCntntNode *pNode = pDoc->GetNodes().GoNextSection( &aIndex, sal_True, sal_False );
+ // --> FME 2005-05-25 #123067# pNode = 0 can really happen:
+ SwTableNode *pTblNd= pNode ? pNode->FindTableNode() : 0;
+ // <--
+
+ //PageDesc besorgen (entweder vom FrmFmt des ersten Node oder den
+ //initialen.)
+ SwPageDesc *pDesc = 0;
+ sal_uInt16 nPgNum = 1;
+
+ if ( pTblNd )
+ {
+ const SwFmtPageDesc &rDesc = pTblNd->GetTable().GetFrmFmt()->GetPageDesc();
+ pDesc = (SwPageDesc*)rDesc.GetPageDesc();
+ //#19104# Seitennummeroffset beruecksictigen!!
+ bIsVirtPageNum = 0 != ( nPgNum = rDesc.GetNumOffset() );
+ }
+ else if ( pNode )
+ {
+ const SwFmtPageDesc &rDesc = pNode->GetSwAttrSet().GetPageDesc();
+ pDesc = (SwPageDesc*)rDesc.GetPageDesc();
+ //#19104# Seitennummeroffset beruecksictigen!!
+ bIsVirtPageNum = 0 != ( nPgNum = rDesc.GetNumOffset() );
+ }
+ else
+ bIsVirtPageNum = sal_False;
+ if ( !pDesc )
+ pDesc = (SwPageDesc*)
+ &const_cast<const SwDoc *>(pDoc)->GetPageDesc( 0 );
+ const sal_Bool bOdd = !nPgNum || 0 != ( nPgNum % 2 );
+
+ //Eine Seite erzeugen und in das Layout stellen
+ SwPageFrm *pPage = ::InsertNewPage( *pDesc, this, bOdd, sal_False, sal_False, 0 );
+
+ //Erstes Blatt im Bodytext-Bereich suchen.
+ SwLayoutFrm *pLay = pPage->FindBodyCont();
+ while( pLay->Lower() )
+ pLay = (SwLayoutFrm*)pLay->Lower();
+
+ SwNodeIndex aTmp( *pDoc->GetNodes().GetEndOfContent().StartOfSectionNode(), 1 );
+ ::_InsertCnt( pLay, pDoc, aTmp.GetIndex(), sal_True );
+ //Noch nicht ersetzte Master aus der Liste entfernen.
+ RemoveMasterObjs( pDrawPage );
+ if( pSettingAccess->get(IDocumentSettingAccess::GLOBAL_DOCUMENT) )
+ pFieldsAccess->UpdateRefFlds( NULL );
+ //b6433357: Update page fields after loading
+ // --->
+ if ( !pCurrShell || !pCurrShell->Imp()->IsUpdateExpFlds() )
+ {
+ SwDocPosUpdate aMsgHnt( pPage->Frm().Top() );
+ pFieldsAccess->UpdatePageFlds( &aMsgHnt );
+ }
+ // <---
+
+ pTimerAccess->StartIdling();
+ bCallbackActionEnabled = sal_True;
+
+ ViewShell *pViewSh = GetCurrShell();
+ if (pViewSh)
+ mbNeedGrammarCheck = pViewSh->GetViewOptions()->IsOnlineSpell();
+}
+
+/*************************************************************************
+|*
+|* SwRootFrm::~SwRootFrm()
+|*
+|*************************************************************************/
+
+
+
+SwRootFrm::~SwRootFrm()
+{
+ bTurboAllowed = sal_False;
+ pTurbo = 0;
+ if(pBlink)
+ pBlink->FrmDelete( this );
+ static_cast<SwFrmFmt*>(GetRegisteredInNonConst())->GetDoc()->DelFrmFmt( static_cast<SwFrmFmt*>(GetRegisteredInNonConst()) );
+ delete pDestroy;
+ pDestroy = 0;
+
+ //Referenzen entfernen.
+ for ( sal_uInt16 i = 0; i < pCurrShells->Count(); ++i )
+ (*pCurrShells)[i]->pRoot = 0;
+
+ delete pCurrShells;
+
+ OSL_ENSURE( 0==nAccessibleShells, "Some accessible shells are left" );
+}
+
+/*************************************************************************
+|*
+|* SwRootFrm::RemoveMasterObjs()
+|*
+|*************************************************************************/
+
+
+void SwRootFrm::RemoveMasterObjs( SdrPage *pPg )
+{
+ //Alle Masterobjekte aus der Page entfernen. Nicht loeschen!!
+ for( sal_uLong i = pPg ? pPg->GetObjCount() : 0; i; )
+ {
+ SdrObject* pObj = pPg->GetObj( --i );
+ if( pObj->ISA(SwFlyDrawObj ) )
+ pPg->RemoveObject( i );
+ }
+}
+
+
+void SwRootFrm::AllCheckPageDescs() const
+{
+ CheckPageDescs( (SwPageFrm*)this->Lower() );
+}
+//swmod 080226
+void SwRootFrm::AllInvalidateAutoCompleteWords() const
+{
+ SwPageFrm *pPage = (SwPageFrm*)this->Lower();
+ while ( pPage )
+ {
+ pPage->InvalidateAutoCompleteWords();
+ pPage = (SwPageFrm*)pPage->GetNext();
+ }
+}//swmod 080305
+void SwRootFrm::AllAddPaintRect() const
+{
+ GetCurrShell()->AddPaintRect( this->Frm() );
+}//swmod 080305
+void SwRootFrm::AllRemoveFtns()
+{
+ RemoveFtns();
+}
+void SwRootFrm::AllInvalidateSmartTagsOrSpelling(sal_Bool bSmartTags) const
+{
+ SwPageFrm *pPage = (SwPageFrm*)this->Lower();
+ while ( pPage )
+ {
+ if ( bSmartTags )
+ pPage->InvalidateSmartTags();
+
+ pPage->InvalidateSpelling();
+ pPage = (SwPageFrm*)pPage->GetNext();
+ } //swmod 080218
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/layout/objectformatter.cxx b/sw/source/core/layout/objectformatter.cxx
new file mode 100644
index 000000000000..c9cebfd93ce6
--- /dev/null
+++ b/sw/source/core/layout/objectformatter.cxx
@@ -0,0 +1,580 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+#include <objectformatter.hxx>
+#include <objectformattertxtfrm.hxx>
+#include <objectformatterlayfrm.hxx>
+#include <anchoredobject.hxx>
+#include <anchoreddrawobject.hxx>
+#include <sortedobjs.hxx>
+#include <pagefrm.hxx>
+#include <flyfrms.hxx>
+#include <txtfrm.hxx>
+#include <layact.hxx>
+#include <frmfmt.hxx>
+#include <fmtanchr.hxx>
+#include <doc.hxx>
+
+#include <vector>
+
+// =============================================================================
+// helper class <SwPageNumAndTypeOfAnchors>
+// --> #i26945# - Additionally the type of the anchor text frame
+// is collected - by type is meant 'master' or 'follow'.
+// =============================================================================
+class SwPageNumAndTypeOfAnchors
+{
+ private:
+ struct tEntry
+ {
+ SwAnchoredObject* mpAnchoredObj;
+ sal_uInt32 mnPageNumOfAnchor;
+ bool mbAnchoredAtMaster;
+ };
+
+ std::vector< tEntry* > maObjList;
+
+ public:
+ inline SwPageNumAndTypeOfAnchors()
+ {
+ }
+ inline ~SwPageNumAndTypeOfAnchors()
+ {
+ for ( std::vector< tEntry* >::iterator aIter = maObjList.begin();
+ aIter != maObjList.end(); ++aIter )
+ {
+ delete (*aIter);
+ }
+ maObjList.clear();
+ }
+
+ inline void Collect( SwAnchoredObject& _rAnchoredObj )
+ {
+ tEntry* pNewEntry = new tEntry();
+ pNewEntry->mpAnchoredObj = &_rAnchoredObj;
+ // --> #i33751#, #i34060# - method <GetPageFrmOfAnchor()>
+ // is replaced by method <FindPageFrmOfAnchor()>. It's return value
+ // have to be checked.
+ SwPageFrm* pPageFrmOfAnchor = _rAnchoredObj.FindPageFrmOfAnchor();
+ if ( pPageFrmOfAnchor )
+ {
+ pNewEntry->mnPageNumOfAnchor = pPageFrmOfAnchor->GetPhyPageNum();
+ }
+ else
+ {
+ pNewEntry->mnPageNumOfAnchor = 0;
+ }
+ // <--
+ // --> #i26945# - collect type of anchor
+ SwTxtFrm* pAnchorCharFrm = _rAnchoredObj.FindAnchorCharFrm();
+ if ( pAnchorCharFrm )
+ {
+ pNewEntry->mbAnchoredAtMaster = !pAnchorCharFrm->IsFollow();
+ }
+ else
+ {
+ pNewEntry->mbAnchoredAtMaster = true;
+ }
+ // <--
+ maObjList.push_back( pNewEntry );
+ }
+
+ inline SwAnchoredObject* operator[]( sal_uInt32 _nIndex )
+ {
+ SwAnchoredObject* bRetObj = 0L;
+
+ if ( _nIndex < Count())
+ {
+ bRetObj = maObjList[_nIndex]->mpAnchoredObj;
+ }
+
+ return bRetObj;
+ }
+
+ inline sal_uInt32 GetPageNum( sal_uInt32 _nIndex ) const
+ {
+ sal_uInt32 nRetPgNum = 0L;
+
+ if ( _nIndex < Count())
+ {
+ nRetPgNum = maObjList[_nIndex]->mnPageNumOfAnchor;
+ }
+
+ return nRetPgNum;
+ }
+
+ // --> #i26945#
+ inline bool AnchoredAtMaster( sal_uInt32 _nIndex )
+ {
+ bool bAnchoredAtMaster( true );
+
+ if ( _nIndex < Count())
+ {
+ bAnchoredAtMaster = maObjList[_nIndex]->mbAnchoredAtMaster;
+ }
+
+ return bAnchoredAtMaster;
+ }
+ // <--
+
+ inline sal_uInt32 Count() const
+ {
+ return maObjList.size();
+ }
+};
+
+// =============================================================================
+// implementation of class <SwObjectFormatter>
+// =============================================================================
+SwObjectFormatter::SwObjectFormatter( const SwPageFrm& _rPageFrm,
+ SwLayAction* _pLayAction,
+ const bool _bCollectPgNumOfAnchors )
+ : mrPageFrm( _rPageFrm ),
+ mbFormatOnlyAsCharAnchored( false ),
+ mbConsiderWrapOnObjPos( _rPageFrm.GetFmt()->getIDocumentSettingAccess()->get(IDocumentSettingAccess::CONSIDER_WRAP_ON_OBJECT_POSITION) ),
+ mpLayAction( _pLayAction ),
+ // --> #i26945#
+ mpPgNumAndTypeOfAnchors( _bCollectPgNumOfAnchors ? new SwPageNumAndTypeOfAnchors() : 0L )
+ // <--
+{
+}
+
+SwObjectFormatter::~SwObjectFormatter()
+{
+ delete mpPgNumAndTypeOfAnchors;
+}
+
+SwObjectFormatter* SwObjectFormatter::CreateObjFormatter(
+ SwFrm& _rAnchorFrm,
+ const SwPageFrm& _rPageFrm,
+ SwLayAction* _pLayAction )
+{
+ SwObjectFormatter* pObjFormatter = 0L;
+ if ( _rAnchorFrm.IsTxtFrm() )
+ {
+ pObjFormatter = SwObjectFormatterTxtFrm::CreateObjFormatter(
+ static_cast<SwTxtFrm&>(_rAnchorFrm),
+ _rPageFrm, _pLayAction );
+ }
+ else if ( _rAnchorFrm.IsLayoutFrm() )
+ {
+ pObjFormatter = SwObjectFormatterLayFrm::CreateObjFormatter(
+ static_cast<SwLayoutFrm&>(_rAnchorFrm),
+ _rPageFrm, _pLayAction );
+ }
+ else
+ {
+ OSL_FAIL( "<SwObjectFormatter::CreateObjFormatter(..)> - unexcepted type of anchor frame" );
+ }
+
+ return pObjFormatter;
+}
+
+/** method to format all floating screen objects at the given anchor frame
+
+ @author OD
+*/
+bool SwObjectFormatter::FormatObjsAtFrm( SwFrm& _rAnchorFrm,
+ const SwPageFrm& _rPageFrm,
+ SwLayAction* _pLayAction )
+{
+ bool bSuccess( true );
+
+ // create corresponding object formatter
+ SwObjectFormatter* pObjFormatter =
+ SwObjectFormatter::CreateObjFormatter( _rAnchorFrm, _rPageFrm, _pLayAction );
+
+ if ( pObjFormatter )
+ {
+ // format anchored floating screen objects
+ bSuccess = pObjFormatter->DoFormatObjs();
+ }
+ delete pObjFormatter;
+
+ return bSuccess;
+}
+
+/** method to format a given floating screen object
+
+ @author OD
+*/
+bool SwObjectFormatter::FormatObj( SwAnchoredObject& _rAnchoredObj,
+ SwFrm* _pAnchorFrm,
+ const SwPageFrm* _pPageFrm,
+ SwLayAction* _pLayAction )
+{
+ bool bSuccess( true );
+
+ OSL_ENSURE( _pAnchorFrm || _rAnchoredObj.GetAnchorFrm(),
+ "<SwObjectFormatter::FormatObj(..)> - missing anchor frame" );
+ SwFrm& rAnchorFrm = _pAnchorFrm ? *(_pAnchorFrm) : *(_rAnchoredObj.AnchorFrm());
+
+ OSL_ENSURE( _pPageFrm || rAnchorFrm.FindPageFrm(),
+ "<SwObjectFormatter::FormatObj(..)> - missing page frame" );
+ const SwPageFrm& rPageFrm = _pPageFrm ? *(_pPageFrm) : *(rAnchorFrm.FindPageFrm());
+
+ // create corresponding object formatter
+ SwObjectFormatter* pObjFormatter =
+ SwObjectFormatter::CreateObjFormatter( rAnchorFrm, rPageFrm, _pLayAction );
+
+ if ( pObjFormatter )
+ {
+ // format given floating screen object
+ // --> #i40147# - check for moved forward anchor frame
+ bSuccess = pObjFormatter->DoFormatObj( _rAnchoredObj, true );
+ // <--
+ }
+ delete pObjFormatter;
+
+ return bSuccess;
+}
+
+/** helper method for method <_FormatObj(..)> - performs the intrinsic format
+ of the layout of the given layout frame and all its lower layout frames.
+
+ #i28701#
+ IMPORTANT NOTE:
+ Method corresponds to methods <SwLayAction::FormatLayoutFly(..)> and
+ <SwLayAction::FormatLayout(..)>. Thus, its code for the formatting have
+ to be synchronised.
+
+ @author OD
+*/
+void SwObjectFormatter::_FormatLayout( SwLayoutFrm& _rLayoutFrm )
+{
+ _rLayoutFrm.Calc();
+
+ SwFrm* pLowerFrm = _rLayoutFrm.Lower();
+ while ( pLowerFrm )
+ {
+ if ( pLowerFrm->IsLayoutFrm() )
+ {
+ _FormatLayout( *(static_cast<SwLayoutFrm*>(pLowerFrm)) );
+ }
+ pLowerFrm = pLowerFrm->GetNext();
+ }
+}
+
+/** helper method for method <_FormatObj(..)> - performs the intrinsic
+ format of the content of the given floating screen object.
+
+ #i28701#
+
+ @author OD
+*/
+void SwObjectFormatter::_FormatObjCntnt( SwAnchoredObject& _rAnchoredObj )
+{
+ if ( !_rAnchoredObj.ISA(SwFlyFrm) )
+ {
+ // only Writer fly frames have content
+ return;
+ }
+
+ SwFlyFrm& rFlyFrm = static_cast<SwFlyFrm&>(_rAnchoredObj);
+ SwCntntFrm* pCntnt = rFlyFrm.ContainsCntnt();
+
+ while ( pCntnt )
+ {
+ // format content
+ pCntnt->OptCalc();
+
+ // format floating screen objects at content text frame
+ // --> #i23129#, #i36347# - pass correct page frame to
+ // the object formatter
+ if ( pCntnt->IsTxtFrm() &&
+ !SwObjectFormatter::FormatObjsAtFrm( *pCntnt,
+ *(pCntnt->FindPageFrm()),
+ GetLayAction() ) )
+ // <--
+ {
+ // restart format with first content
+ pCntnt = rFlyFrm.ContainsCntnt();
+ continue;
+ }
+
+ // continue with next content
+ pCntnt = pCntnt->GetNextCntntFrm();
+ }
+}
+
+/** performs the intrinsic format of a given floating screen object and its content.
+
+ #i28701#
+
+ @author OD
+*/
+void SwObjectFormatter::_FormatObj( SwAnchoredObject& _rAnchoredObj )
+{
+ // check, if only as-character anchored object have to be formatted, and
+ // check the anchor type
+ if ( FormatOnlyAsCharAnchored() &&
+ !(_rAnchoredObj.GetFrmFmt().GetAnchor().GetAnchorId() == FLY_AS_CHAR) )
+ {
+ return;
+ }
+
+ // collect anchor object and its 'anchor' page number, if requested
+ if ( mpPgNumAndTypeOfAnchors )
+ {
+ mpPgNumAndTypeOfAnchors->Collect( _rAnchoredObj );
+ }
+
+ if ( _rAnchoredObj.ISA(SwFlyFrm) )
+ {
+ SwFlyFrm& rFlyFrm = static_cast<SwFlyFrm&>(_rAnchoredObj);
+ // --> #i34753# - reset flag, which prevents a positioning
+ if ( rFlyFrm.IsFlyLayFrm() )
+ {
+ static_cast<SwFlyLayFrm&>(rFlyFrm).SetNoMakePos( false );
+ }
+ // <--
+
+ // #i81146# new loop control
+ sal_uInt16 nLoopControlRuns = 0;
+ const sal_uInt16 nLoopControlMax = 15;
+
+ do {
+ if ( mpLayAction )
+ {
+ mpLayAction->FormatLayoutFly( &rFlyFrm );
+ // --> consider, if the layout action
+ // has to be restarted due to a delete of a page frame.
+ if ( mpLayAction->IsAgain() )
+ {
+ break;
+ }
+ // <--
+ }
+ else
+ {
+ _FormatLayout( rFlyFrm );
+ }
+ // --> #i34753# - prevent further positioning, if
+ // to-page|to-fly anchored Writer fly frame is already clipped.
+ if ( rFlyFrm.IsFlyLayFrm() && rFlyFrm.IsClipped() )
+ {
+ static_cast<SwFlyLayFrm&>(rFlyFrm).SetNoMakePos( true );
+ }
+ // <--
+ // --> #i23129#, #i36347# - pass correct page frame
+ // to the object formatter
+ SwObjectFormatter::FormatObjsAtFrm( rFlyFrm,
+ *(rFlyFrm.FindPageFrm()),
+ mpLayAction );
+ // <--
+ if ( mpLayAction )
+ {
+ mpLayAction->_FormatFlyCntnt( &rFlyFrm );
+ // --> consider, if the layout action
+ // has to be restarted due to a delete of a page frame.
+ if ( mpLayAction->IsAgain() )
+ {
+ break;
+ }
+ // <--
+ }
+ else
+ {
+ _FormatObjCntnt( rFlyFrm );
+ }
+
+ if ( ++nLoopControlRuns >= nLoopControlMax )
+ {
+#if OSL_DEBUG_LEVEL > 1
+ OSL_FAIL( "LoopControl in SwObjectFormatter::_FormatObj: Stage 3!!!" );
+#endif
+ rFlyFrm.ValidateThisAndAllLowers( 2 );
+ nLoopControlRuns = 0;
+ }
+
+ // --> #i57917#
+ // stop formatting of anchored object, if restart of layout process is requested.
+ } while ( !rFlyFrm.IsValid() &&
+ !_rAnchoredObj.RestartLayoutProcess() &&
+ rFlyFrm.GetAnchorFrm() == &GetAnchorFrm() );
+ // <--
+ }
+ else if ( _rAnchoredObj.ISA(SwAnchoredDrawObject) )
+ {
+ _rAnchoredObj.MakeObjPos();
+ }
+}
+
+/** invokes the intrinsic format method for all floating screen objects,
+ anchored at anchor frame on the given page frame
+
+ #i28701#
+ #i26945# - for format of floating screen objects for
+ follow text frames, the 'master' text frame is passed to the method.
+ Thus, the objects, whose anchor character is inside the follow text
+ frame can be formatted.
+
+ @author OD
+*/
+bool SwObjectFormatter::_FormatObjsAtFrm( SwTxtFrm* _pMasterTxtFrm )
+{
+ // --> #i26945#
+ SwFrm* pAnchorFrm( 0L );
+ if ( GetAnchorFrm().IsTxtFrm() &&
+ static_cast<SwTxtFrm&>(GetAnchorFrm()).IsFollow() &&
+ _pMasterTxtFrm )
+ {
+ pAnchorFrm = _pMasterTxtFrm;
+ }
+ else
+ {
+ pAnchorFrm = &GetAnchorFrm();
+ }
+ // <--
+ if ( !pAnchorFrm->GetDrawObjs() )
+ {
+ // nothing to do, if no floating screen object is registered at the anchor frame.
+ return true;
+ }
+
+ bool bSuccess( true );
+
+ sal_uInt32 i = 0;
+ for ( ; i < pAnchorFrm->GetDrawObjs()->Count(); ++i )
+ {
+ SwAnchoredObject* pAnchoredObj = (*pAnchorFrm->GetDrawObjs())[i];
+
+ // check, if object's anchor is on the given page frame or
+ // object is registered at the given page frame.
+ // --> #i26945# - check, if the anchor character of the
+ // anchored object is located in a follow text frame. If this anchor
+ // follow text frame differs from the given anchor frame, the given
+ // anchor frame is a 'master' text frame of the anchor follow text frame.
+ // If the anchor follow text frame is in the same body as its 'master'
+ // text frame, do not format the anchored object.
+ // E.g., this situation can occur during the table row splitting algorithm.
+ SwTxtFrm* pAnchorCharFrm = pAnchoredObj->FindAnchorCharFrm();
+ const bool bAnchoredAtFollowInSameBodyAsMaster =
+ pAnchorCharFrm && pAnchorCharFrm->IsFollow() &&
+ pAnchorCharFrm != pAnchoredObj->GetAnchorFrm() &&
+ pAnchorCharFrm->FindBodyFrm() ==
+ static_cast<SwTxtFrm*>(pAnchoredObj->AnchorFrm())->FindBodyFrm();
+ if ( bAnchoredAtFollowInSameBodyAsMaster )
+ {
+ continue;
+ }
+ // <--
+ // --> #i33751#, #i34060# - method <GetPageFrmOfAnchor()>
+ // is replaced by method <FindPageFrmOfAnchor()>. It's return value
+ // have to be checked.
+ SwPageFrm* pPageFrmOfAnchor = pAnchoredObj->FindPageFrmOfAnchor();
+ OSL_ENSURE( pPageFrmOfAnchor,
+ "<SwObjectFormatter::_FormatObjsAtFrm()> - missing page frame." );
+ // --> #i26945#
+ if ( pPageFrmOfAnchor && pPageFrmOfAnchor == &mrPageFrm )
+ // <--
+ {
+ // if format of object fails, stop formatting and pass fail to
+ // calling method via the return value.
+ if ( !DoFormatObj( *pAnchoredObj ) )
+ {
+ bSuccess = false;
+ break;
+ }
+
+ // considering changes at <pAnchorFrm->GetDrawObjs()> during
+ // format of the object.
+ if ( !pAnchorFrm->GetDrawObjs() ||
+ i > pAnchorFrm->GetDrawObjs()->Count() )
+ {
+ break;
+ }
+ else
+ {
+ sal_uInt32 nActPosOfObj =
+ pAnchorFrm->GetDrawObjs()->ListPosOf( *pAnchoredObj );
+ if ( nActPosOfObj == pAnchorFrm->GetDrawObjs()->Count() ||
+ nActPosOfObj > i )
+ {
+ --i;
+ }
+ else if ( nActPosOfObj < i )
+ {
+ i = nActPosOfObj;
+ }
+ }
+ }
+ } // end of loop on <pAnchorFrm->.GetDrawObjs()>
+
+ return bSuccess;
+}
+
+/** accessor to collected anchored object
+
+ #i28701#
+
+ @author OD
+*/
+SwAnchoredObject* SwObjectFormatter::GetCollectedObj( const sal_uInt32 _nIndex )
+{
+ return mpPgNumAndTypeOfAnchors ? (*mpPgNumAndTypeOfAnchors)[_nIndex] : 0L;
+}
+
+/** accessor to 'anchor' page number of collected anchored object
+
+ #i28701#
+
+ @author OD
+*/
+sal_uInt32 SwObjectFormatter::GetPgNumOfCollected( const sal_uInt32 _nIndex )
+{
+ return mpPgNumAndTypeOfAnchors ? mpPgNumAndTypeOfAnchors->GetPageNum(_nIndex) : 0L;
+}
+
+/** accessor to 'anchor' type of collected anchored object
+
+ #i26945#
+
+ @author OD
+*/
+bool SwObjectFormatter::IsCollectedAnchoredAtMaster( const sal_uInt32 _nIndex )
+{
+ return mpPgNumAndTypeOfAnchors
+ ? mpPgNumAndTypeOfAnchors->AnchoredAtMaster(_nIndex)
+ : true;
+}
+
+/** accessor to total number of collected anchored objects
+
+ #i28701#
+
+ @author OD
+*/
+sal_uInt32 SwObjectFormatter::CountOfCollected()
+{
+ return mpPgNumAndTypeOfAnchors ? mpPgNumAndTypeOfAnchors->Count() : 0L;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/layout/objectformatterlayfrm.cxx b/sw/source/core/layout/objectformatterlayfrm.cxx
new file mode 100644
index 000000000000..80fc372eb2f6
--- /dev/null
+++ b/sw/source/core/layout/objectformatterlayfrm.cxx
@@ -0,0 +1,216 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+#include <objectformatterlayfrm.hxx>
+#include <anchoredobject.hxx>
+#include <sortedobjs.hxx>
+#include <layfrm.hxx>
+#include <pagefrm.hxx>
+
+// --> OD 2005-07-13 #124218#
+#include <layact.hxx>
+// <--
+
+// =============================================================================
+// implementation of class <SwObjectFormatterLayFrm>
+// =============================================================================
+SwObjectFormatterLayFrm::SwObjectFormatterLayFrm( SwLayoutFrm& _rAnchorLayFrm,
+ const SwPageFrm& _rPageFrm,
+ SwLayAction* _pLayAction )
+ : SwObjectFormatter( _rPageFrm, _pLayAction ),
+ mrAnchorLayFrm( _rAnchorLayFrm )
+{
+}
+
+SwObjectFormatterLayFrm::~SwObjectFormatterLayFrm()
+{
+}
+
+SwObjectFormatterLayFrm* SwObjectFormatterLayFrm::CreateObjFormatter(
+ SwLayoutFrm& _rAnchorLayFrm,
+ const SwPageFrm& _rPageFrm,
+ SwLayAction* _pLayAction )
+{
+ if ( !_rAnchorLayFrm.IsPageFrm() &&
+ !_rAnchorLayFrm.IsFlyFrm() )
+ {
+ OSL_FAIL( "<SwObjectFormatterLayFrm::CreateObjFormatter(..)> - unexcepted type of anchor frame " );
+ return 0L;
+ }
+
+ SwObjectFormatterLayFrm* pObjFormatter = 0L;
+
+ // create object formatter, if floating screen objects are registered at
+ // given anchor layout frame.
+ if ( _rAnchorLayFrm.GetDrawObjs() ||
+ ( _rAnchorLayFrm.IsPageFrm() &&
+ static_cast<SwPageFrm&>(_rAnchorLayFrm).GetSortedObjs() ) )
+ {
+ pObjFormatter =
+ new SwObjectFormatterLayFrm( _rAnchorLayFrm, _rPageFrm, _pLayAction );
+ }
+
+ return pObjFormatter;
+}
+
+SwFrm& SwObjectFormatterLayFrm::GetAnchorFrm()
+{
+ return mrAnchorLayFrm;
+}
+
+// --> OD 2005-01-10 #i40147# - add parameter <_bCheckForMovedFwd>.
+// Not relevant for objects anchored at layout frame.
+bool SwObjectFormatterLayFrm::DoFormatObj( SwAnchoredObject& _rAnchoredObj,
+ const bool )
+// <--
+{
+ _FormatObj( _rAnchoredObj );
+
+ // --> OD 2005-07-13 #124218# - consider that the layout action has to be
+ // restarted due to a deleted page frame.
+ return GetLayAction() ? !GetLayAction()->IsAgain() : true;
+ // <--
+}
+
+bool SwObjectFormatterLayFrm::DoFormatObjs()
+{
+ bool bSuccess( true );
+
+ bSuccess = _FormatObjsAtFrm();
+
+ if ( bSuccess && GetAnchorFrm().IsPageFrm() )
+ {
+ // anchor layout frame is a page frame.
+ // Thus, format also all anchored objects, which are registered at
+ // this page frame, whose 'anchor' isn't on this page frame and whose
+ // anchor frame is valid.
+ bSuccess = _AdditionalFormatObjsOnPage();
+ }
+
+ return bSuccess;
+}
+
+/** method to format all anchored objects, which are registered at
+ the page frame, whose 'anchor' isn't on this page frame and whose
+ anchor frame is valid.
+
+ OD 2004-07-02 #i28701#
+
+ @author
+*/
+bool SwObjectFormatterLayFrm::_AdditionalFormatObjsOnPage()
+{
+ if ( !GetAnchorFrm().IsPageFrm() )
+ {
+ OSL_FAIL( "<SwObjectFormatterLayFrm::_AdditionalFormatObjsOnPage()> - mis-usage of method, call only for anchor frames of type page frame" );
+ return true;
+ }
+
+ // --> OD 2005-07-13 #124218# - consider, if the layout action
+ // has to be restarted due to a delete of a page frame.
+ if ( GetLayAction() && GetLayAction()->IsAgain() )
+ {
+ return false;
+ }
+ // <--
+
+
+ SwPageFrm& rPageFrm = static_cast<SwPageFrm&>(GetAnchorFrm());
+
+ if ( !rPageFrm.GetSortedObjs() )
+ {
+ // nothing to do, if no floating screen object is registered at the anchor frame.
+ return true;
+ }
+
+ bool bSuccess( true );
+
+ sal_uInt32 i = 0;
+ for ( ; i < rPageFrm.GetSortedObjs()->Count(); ++i )
+ {
+ SwAnchoredObject* pAnchoredObj = (*rPageFrm.GetSortedObjs())[i];
+
+ // --> OD 2005-08-18 #i51941# - do not format object, which are anchored
+ // inside or at fly frame.
+ if ( pAnchoredObj->GetAnchorFrm()->FindFlyFrm() )
+ {
+ continue;
+ }
+ // <--
+ // --> OD 2004-09-23 #i33751#, #i34060# - method <GetPageFrmOfAnchor()>
+ // is replaced by method <FindPageFrmOfAnchor()>. It's return value
+ // have to be checked.
+ SwPageFrm* pPageFrmOfAnchor = pAnchoredObj->FindPageFrmOfAnchor();
+ // --> OD 2004-10-08 #i26945# - check, if the page frame of the
+ // object's anchor frame isn't the given page frame
+ OSL_ENSURE( pPageFrmOfAnchor,
+ "<SwObjectFormatterLayFrm::_AdditionalFormatObjsOnPage()> - missing page frame" );
+ if ( pPageFrmOfAnchor &&
+ // --> OD 2004-10-22 #i35911#
+ pPageFrmOfAnchor->GetPhyPageNum() < rPageFrm.GetPhyPageNum() )
+ // <--
+ // <--
+ {
+ // if format of object fails, stop formatting and pass fail to
+ // calling method via the return value.
+ if ( !DoFormatObj( *pAnchoredObj ) )
+ {
+ bSuccess = false;
+ break;
+ }
+
+ // considering changes at <GetAnchorFrm().GetDrawObjs()> during
+ // format of the object.
+ if ( !rPageFrm.GetSortedObjs() ||
+ i > rPageFrm.GetSortedObjs()->Count() )
+ {
+ break;
+ }
+ else
+ {
+ sal_uInt32 nActPosOfObj =
+ rPageFrm.GetSortedObjs()->ListPosOf( *pAnchoredObj );
+ if ( nActPosOfObj == rPageFrm.GetSortedObjs()->Count() ||
+ nActPosOfObj > i )
+ {
+ --i;
+ }
+ else if ( nActPosOfObj < i )
+ {
+ i = nActPosOfObj;
+ }
+ }
+ }
+ } // end of loop on <rPageFrm.GetSortedObjs()>
+
+ return bSuccess;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/layout/objectformatterlayfrm.hxx b/sw/source/core/layout/objectformatterlayfrm.hxx
new file mode 100644
index 000000000000..a2199030a61c
--- /dev/null
+++ b/sw/source/core/layout/objectformatterlayfrm.hxx
@@ -0,0 +1,84 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+#ifndef _OBJECTFORMATTERLAYFRM_HXX
+#define _OBJECTFORMATTERLAYFRM_HXX
+
+#include <objectformatter.hxx>
+
+class SwLayoutFrm;
+
+// -----------------------------------------------------------------------------
+// Format floating screen objects, which are anchored at a given anchor text frame
+// and registered at the given page frame.
+// -----------------------------------------------------------------------------
+class SwObjectFormatterLayFrm : public SwObjectFormatter
+{
+ private:
+ // anchor layout frame
+ SwLayoutFrm& mrAnchorLayFrm;
+
+ SwObjectFormatterLayFrm( SwLayoutFrm& _rAnchorLayFrm,
+ const SwPageFrm& _rPageFrm,
+ SwLayAction* _pLayAction );
+
+ /** method to format all anchored objects, which are registered at
+ the page frame, whose 'anchor' isn't on this page frame and whose
+ anchor frame is valid.
+
+ OD 2004-07-02 #i28701#
+
+ @author OD
+
+ @return boolean
+ indicates, if format was successfull
+ */
+ bool _AdditionalFormatObjsOnPage();
+
+ protected:
+
+ virtual SwFrm& GetAnchorFrm();
+
+ public:
+ virtual ~SwObjectFormatterLayFrm();
+
+ // --> OD 2005-01-10 #i40147# - add parameter <_bCheckForMovedFwd>.
+ // Not relevant for objects anchored at layout frame.
+ virtual bool DoFormatObj( SwAnchoredObject& _rAnchoredObj,
+ const bool _bCheckForMovedFwd = false );
+ // <--
+ virtual bool DoFormatObjs();
+
+ static SwObjectFormatterLayFrm* CreateObjFormatter(
+ SwLayoutFrm& _rAnchorLayFrm,
+ const SwPageFrm& _rPageFrm,
+ SwLayAction* _pLayAction );
+};
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/layout/objectformattertxtfrm.cxx b/sw/source/core/layout/objectformattertxtfrm.cxx
new file mode 100644
index 000000000000..a3593f5cc479
--- /dev/null
+++ b/sw/source/core/layout/objectformattertxtfrm.cxx
@@ -0,0 +1,814 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+#include <objectformattertxtfrm.hxx>
+#include <anchoredobject.hxx>
+#include <sortedobjs.hxx>
+#include <flyfrms.hxx>
+#include <txtfrm.hxx>
+#include <pagefrm.hxx>
+#include <rowfrm.hxx>
+#include <layouter.hxx>
+#include <frmfmt.hxx>
+#include <fmtanchr.hxx>
+#include <fmtwrapinfluenceonobjpos.hxx>
+#include <fmtfollowtextflow.hxx>
+#include <layact.hxx>
+
+using namespace ::com::sun::star;
+
+// =============================================================================
+
+// little helper class to forbid follow formatting for the given text frame
+class SwForbidFollowFormat
+{
+private:
+ SwTxtFrm& mrTxtFrm;
+ const bool bOldFollowFormatAllowed;
+
+public:
+ SwForbidFollowFormat( SwTxtFrm& _rTxtFrm )
+ : mrTxtFrm( _rTxtFrm ),
+ bOldFollowFormatAllowed( _rTxtFrm.FollowFormatAllowed() )
+ {
+ mrTxtFrm.ForbidFollowFormat();
+ }
+
+ ~SwForbidFollowFormat()
+ {
+ if ( bOldFollowFormatAllowed )
+ {
+ mrTxtFrm.AllowFollowFormat();
+ }
+ }
+};
+
+// =============================================================================
+// implementation of class <SwObjectFormatterTxtFrm>
+// =============================================================================
+SwObjectFormatterTxtFrm::SwObjectFormatterTxtFrm( SwTxtFrm& _rAnchorTxtFrm,
+ const SwPageFrm& _rPageFrm,
+ SwTxtFrm* _pMasterAnchorTxtFrm,
+ SwLayAction* _pLayAction )
+ : SwObjectFormatter( _rPageFrm, _pLayAction, true ),
+ mrAnchorTxtFrm( _rAnchorTxtFrm ),
+ mpMasterAnchorTxtFrm( _pMasterAnchorTxtFrm )
+{
+}
+
+SwObjectFormatterTxtFrm::~SwObjectFormatterTxtFrm()
+{
+}
+
+SwObjectFormatterTxtFrm* SwObjectFormatterTxtFrm::CreateObjFormatter(
+ SwTxtFrm& _rAnchorTxtFrm,
+ const SwPageFrm& _rPageFrm,
+ SwLayAction* _pLayAction )
+{
+ SwObjectFormatterTxtFrm* pObjFormatter = 0L;
+
+ // determine 'master' of <_rAnchorTxtFrm>, if anchor frame is a follow text frame.
+ SwTxtFrm* pMasterOfAnchorFrm = 0L;
+ if ( _rAnchorTxtFrm.IsFollow() )
+ {
+ pMasterOfAnchorFrm = _rAnchorTxtFrm.FindMaster();
+ while ( pMasterOfAnchorFrm && pMasterOfAnchorFrm->IsFollow() )
+ {
+ pMasterOfAnchorFrm = pMasterOfAnchorFrm->FindMaster();
+ }
+ }
+
+ // create object formatter, if floating screen objects are registered
+ // at anchor frame (or at 'master' anchor frame)
+ if ( _rAnchorTxtFrm.GetDrawObjs() ||
+ ( pMasterOfAnchorFrm && pMasterOfAnchorFrm->GetDrawObjs() ) )
+ {
+ pObjFormatter =
+ new SwObjectFormatterTxtFrm( _rAnchorTxtFrm, _rPageFrm,
+ pMasterOfAnchorFrm, _pLayAction );
+ }
+
+ return pObjFormatter;
+}
+
+SwFrm& SwObjectFormatterTxtFrm::GetAnchorFrm()
+{
+ return mrAnchorTxtFrm;
+}
+
+// #i40147# - add parameter <_bCheckForMovedFwd>.
+bool SwObjectFormatterTxtFrm::DoFormatObj( SwAnchoredObject& _rAnchoredObj,
+ const bool _bCheckForMovedFwd )
+{
+ // check, if only as-character anchored object have to be formatted, and
+ // check the anchor type
+ if ( FormatOnlyAsCharAnchored() &&
+ !(_rAnchoredObj.GetFrmFmt().GetAnchor().GetAnchorId() == FLY_AS_CHAR) )
+ {
+ return true;
+ }
+
+ // consider, if the layout action has to be
+ // restarted due to a delete of a page frame.
+ if ( GetLayAction() && GetLayAction()->IsAgain() )
+ {
+ return false;
+ }
+
+ bool bSuccess( true );
+
+ if ( _rAnchoredObj.IsFormatPossible() )
+ {
+ _rAnchoredObj.SetRestartLayoutProcess( false );
+
+ _FormatObj( _rAnchoredObj );
+ // consider, if the layout action has to be
+ // restarted due to a delete of a page frame.
+ if ( GetLayAction() && GetLayAction()->IsAgain() )
+ {
+ return false;
+ }
+
+ // check, if layout process has to be restarted.
+ // if yes, perform needed invalidations.
+
+ // no restart of layout process,
+ // if anchored object is anchored inside a Writer fly frame,
+ // its position is already locked, and it follows the text flow.
+ const bool bRestart =
+ _rAnchoredObj.RestartLayoutProcess() &&
+ !( _rAnchoredObj.PositionLocked() &&
+ _rAnchoredObj.GetAnchorFrm()->IsInFly() &&
+ _rAnchoredObj.GetFrmFmt().GetFollowTextFlow().GetValue() );
+ if ( bRestart )
+ {
+ bSuccess = false;
+ _InvalidatePrevObjs( _rAnchoredObj );
+ _InvalidateFollowObjs( _rAnchoredObj, true );
+ }
+
+ // format anchor text frame, if wrapping style influence of the object
+ // has to be considered and it's <NONE_SUCCESSIVE_POSITIONED>
+ // #i3317# - consider also anchored objects, whose
+ // wrapping style influence is temporarly considered.
+ // #i40147# - consider also anchored objects, for
+ // whose the check of a moved forward anchor frame is requested.
+ // revise decision made for i3317:
+ // anchored objects, whose wrapping style influence is temporarly considered,
+ // have to be considered in method <SwObjectFormatterTxtFrm::DoFormatObjs()>
+ if ( bSuccess &&
+ _rAnchoredObj.ConsiderObjWrapInfluenceOnObjPos() &&
+ ( _bCheckForMovedFwd ||
+ _rAnchoredObj.GetFrmFmt().GetWrapInfluenceOnObjPos().
+ // #i35017# - handle ITERATIVE as ONCE_SUCCESSIVE
+ GetWrapInfluenceOnObjPos( true ) ==
+ // #i35017# - constant name has changed
+ text::WrapInfluenceOnPosition::ONCE_SUCCESSIVE ) )
+ {
+ // #i26945# - check conditions for move forward of
+ // anchor text frame
+ // determine, if anchor text frame has previous frame
+ const bool bDoesAnchorHadPrev = ( mrAnchorTxtFrm.GetIndPrev() != 0 );
+
+ // #i40141# - use new method - it also formats the
+ // section the anchor frame is in.
+ _FormatAnchorFrmForCheckMoveFwd();
+
+ // #i35911#
+ if ( _rAnchoredObj.HasClearedEnvironment() )
+ {
+ _rAnchoredObj.SetClearedEnvironment( true );
+ // #i44049# - consider, that anchor frame
+ // could already been marked to move forward.
+ SwPageFrm* pAnchorPageFrm( mrAnchorTxtFrm.FindPageFrm() );
+ if ( pAnchorPageFrm != _rAnchoredObj.GetPageFrm() )
+ {
+ bool bInsert( true );
+ sal_uInt32 nToPageNum( 0L );
+ const SwDoc& rDoc = *(GetPageFrm().GetFmt()->GetDoc());
+ if ( SwLayouter::FrmMovedFwdByObjPos(
+ rDoc, mrAnchorTxtFrm, nToPageNum ) )
+ {
+ if ( nToPageNum < pAnchorPageFrm->GetPhyPageNum() )
+ SwLayouter::RemoveMovedFwdFrm( rDoc, mrAnchorTxtFrm );
+ else
+ bInsert = false;
+ }
+ if ( bInsert )
+ {
+ SwLayouter::InsertMovedFwdFrm( rDoc, mrAnchorTxtFrm,
+ pAnchorPageFrm->GetPhyPageNum() );
+ mrAnchorTxtFrm.InvalidatePos();
+ bSuccess = false;
+ _InvalidatePrevObjs( _rAnchoredObj );
+ _InvalidateFollowObjs( _rAnchoredObj, true );
+ }
+ else
+ {
+ OSL_FAIL( "<SwObjectFormatterTxtFrm::DoFormatObj(..)> - anchor frame not marked to move forward" );
+ }
+ }
+ }
+ else if ( !mrAnchorTxtFrm.IsFollow() && bDoesAnchorHadPrev )
+ {
+ // index of anchored object in collection of page numbers and
+ // anchor types
+ sal_uInt32 nIdx( CountOfCollected() );
+ OSL_ENSURE( nIdx > 0,
+ "<SwObjectFormatterTxtFrm::DoFormatObj(..)> - anchored object not collected!?" );
+ --nIdx;
+
+ sal_uInt32 nToPageNum( 0L );
+ // #i43913#
+ bool bDummy( false );
+ // #i58182# - consider new method signature
+ if ( SwObjectFormatterTxtFrm::CheckMovedFwdCondition( *GetCollectedObj( nIdx ),
+ GetPgNumOfCollected( nIdx ),
+ IsCollectedAnchoredAtMaster( nIdx ),
+ nToPageNum, bDummy ) )
+ {
+ // #i49987# - consider, that anchor frame
+ // could already been marked to move forward.
+ bool bInsert( true );
+ sal_uInt32 nMovedFwdToPageNum( 0L );
+ const SwDoc& rDoc = *(GetPageFrm().GetFmt()->GetDoc());
+ if ( SwLayouter::FrmMovedFwdByObjPos(
+ rDoc, mrAnchorTxtFrm, nMovedFwdToPageNum ) )
+ {
+ if ( nMovedFwdToPageNum < nToPageNum )
+ SwLayouter::RemoveMovedFwdFrm( rDoc, mrAnchorTxtFrm );
+ else
+ bInsert = false;
+ }
+ if ( bInsert )
+ {
+ // Indicate that anchor text frame has to move forward and
+ // invalidate its position to force a re-format.
+ SwLayouter::InsertMovedFwdFrm( rDoc, mrAnchorTxtFrm,
+ nToPageNum );
+ mrAnchorTxtFrm.InvalidatePos();
+
+ // Indicate restart of the layout process
+ bSuccess = false;
+
+ // If needed, invalidate previous objects anchored at same anchor
+ // text frame.
+ _InvalidatePrevObjs( _rAnchoredObj );
+
+ // Invalidate object and following objects for the restart of the
+ // layout process
+ _InvalidateFollowObjs( _rAnchoredObj, true );
+ }
+ else
+ {
+ OSL_FAIL( "<SwObjectFormatterTxtFrm::DoFormatObj(..)> - anchor frame not marked to move forward" );
+ }
+ }
+ }
+ // i40155# - mark anchor frame not to wrap around
+ // objects under the condition, that its follow contains all its text.
+ else if ( !mrAnchorTxtFrm.IsFollow() &&
+ mrAnchorTxtFrm.GetFollow() &&
+ mrAnchorTxtFrm.GetFollow()->GetOfst() == 0 )
+ {
+ SwLayouter::InsertFrmNotToWrap(
+ *(mrAnchorTxtFrm.FindPageFrm()->GetFmt()->GetDoc()),
+ mrAnchorTxtFrm );
+ SwLayouter::RemoveMovedFwdFrm(
+ *(mrAnchorTxtFrm.FindPageFrm()->GetFmt()->GetDoc()),
+ mrAnchorTxtFrm );
+ }
+ }
+ }
+
+ return bSuccess;
+}
+
+bool SwObjectFormatterTxtFrm::DoFormatObjs()
+{
+ if ( !mrAnchorTxtFrm.IsValid() )
+ {
+ if ( GetLayAction() &&
+ mrAnchorTxtFrm.FindPageFrm() != &GetPageFrm() )
+ {
+ // notify layout action, thus is can restart the layout process on
+ // a previous page.
+ GetLayAction()->SetAgain();
+ }
+ else
+ {
+ // the anchor text frame has to be valid, thus assert.
+ OSL_FAIL( "<SwObjectFormatterTxtFrm::DoFormatObjs()> called for invalidate anchor text frame." );
+ }
+
+ return false;
+ }
+
+ bool bSuccess( true );
+
+ if ( mrAnchorTxtFrm.IsFollow() )
+ {
+ // Only floating screen objects anchored as-character are directly
+ // registered at a follow text frame. The other floating screen objects
+ // are registered at the 'master' anchor text frame.
+ // Thus, format the other floating screen objects through the 'master'
+ // anchor text frame
+ OSL_ENSURE( mpMasterAnchorTxtFrm,
+ "SwObjectFormatterTxtFrm::DoFormatObjs() - missing 'master' anchor text frame" );
+ bSuccess = _FormatObjsAtFrm( mpMasterAnchorTxtFrm );
+
+ if ( bSuccess )
+ {
+ // format of as-character anchored floating screen objects - no failure
+ // excepted on the format of these objects.
+ bSuccess = _FormatObjsAtFrm();
+ }
+ }
+ else
+ {
+ bSuccess = _FormatObjsAtFrm();
+ }
+
+ // consider anchored objects, whose wrapping style influence are temporarly
+ // considered.
+ if ( bSuccess &&
+ ( ConsiderWrapOnObjPos() ||
+ ( !mrAnchorTxtFrm.IsFollow() &&
+ _AtLeastOneObjIsTmpConsiderWrapInfluence() ) ) )
+ {
+ const bool bDoesAnchorHadPrev = ( mrAnchorTxtFrm.GetIndPrev() != 0 );
+
+ // Format anchor text frame after its objects are formatted.
+ // Note: The format of the anchor frame also formats the invalid
+ // previous frames of the anchor frame. The format of the previous
+ // frames is needed to get a correct result of format of the
+ // anchor frame for the following check for moved forward anchors
+ // #i40141# - use new method - it also formats the
+ // section the anchor frame is in.
+ _FormatAnchorFrmForCheckMoveFwd();
+
+ sal_uInt32 nToPageNum( 0L );
+ // #i43913#
+ bool bInFollow( false );
+ SwAnchoredObject* pObj = 0L;
+ if ( !mrAnchorTxtFrm.IsFollow() )
+ {
+ pObj = _GetFirstObjWithMovedFwdAnchor(
+ // #i35017# - constant name has changed
+ text::WrapInfluenceOnPosition::ONCE_CONCURRENT,
+ nToPageNum, bInFollow );
+ }
+ // #i35911#
+ if ( pObj && pObj->HasClearedEnvironment() )
+ {
+ pObj->SetClearedEnvironment( true );
+ // #i44049# - consider, that anchor frame
+ // could already been marked to move forward.
+ SwPageFrm* pAnchorPageFrm( mrAnchorTxtFrm.FindPageFrm() );
+ // #i43913# - consider, that anchor frame
+ // is a follow or is in a follow row, which will move forward.
+ if ( pAnchorPageFrm != pObj->GetPageFrm() ||
+ bInFollow )
+ {
+ bool bInsert( true );
+ sal_uInt32 nTmpToPageNum( 0L );
+ const SwDoc& rDoc = *(GetPageFrm().GetFmt()->GetDoc());
+ if ( SwLayouter::FrmMovedFwdByObjPos(
+ rDoc, mrAnchorTxtFrm, nTmpToPageNum ) )
+ {
+ if ( nTmpToPageNum < pAnchorPageFrm->GetPhyPageNum() )
+ SwLayouter::RemoveMovedFwdFrm( rDoc, mrAnchorTxtFrm );
+ else
+ bInsert = false;
+ }
+ if ( bInsert )
+ {
+ SwLayouter::InsertMovedFwdFrm( rDoc, mrAnchorTxtFrm,
+ pAnchorPageFrm->GetPhyPageNum() );
+ mrAnchorTxtFrm.InvalidatePos();
+ bSuccess = false;
+ _InvalidatePrevObjs( *pObj );
+ _InvalidateFollowObjs( *pObj, true );
+ }
+ else
+ {
+ OSL_FAIL( "<SwObjectFormatterTxtFrm::DoFormatObjs(..)> - anchor frame not marked to move forward" );
+ }
+ }
+ }
+ else if ( pObj && bDoesAnchorHadPrev )
+ {
+ // Object found, whose anchor is moved forward
+
+ // #i49987# - consider, that anchor frame
+ // could already been marked to move forward.
+ bool bInsert( true );
+ sal_uInt32 nMovedFwdToPageNum( 0L );
+ const SwDoc& rDoc = *(GetPageFrm().GetFmt()->GetDoc());
+ if ( SwLayouter::FrmMovedFwdByObjPos(
+ rDoc, mrAnchorTxtFrm, nMovedFwdToPageNum ) )
+ {
+ if ( nMovedFwdToPageNum < nToPageNum )
+ SwLayouter::RemoveMovedFwdFrm( rDoc, mrAnchorTxtFrm );
+ else
+ bInsert = false;
+ }
+ if ( bInsert )
+ {
+ // Indicate that anchor text frame has to move forward and
+ // invalidate its position to force a re-format.
+ SwLayouter::InsertMovedFwdFrm( rDoc, mrAnchorTxtFrm, nToPageNum );
+ mrAnchorTxtFrm.InvalidatePos();
+
+ // Indicate restart of the layout process
+ bSuccess = false;
+
+ // If needed, invalidate previous objects anchored at same anchor
+ // text frame.
+ _InvalidatePrevObjs( *pObj );
+
+ // Invalidate object and following objects for the restart of the
+ // layout process
+ _InvalidateFollowObjs( *pObj, true );
+ }
+ else
+ {
+ OSL_FAIL( "<SwObjectFormatterTxtFrm::DoFormatObjs(..)> - anchor frame not marked to move forward" );
+ }
+ }
+ // #i40155# - mark anchor frame not to wrap around
+ // objects under the condition, that its follow contains all its text.
+ else if ( !mrAnchorTxtFrm.IsFollow() &&
+ mrAnchorTxtFrm.GetFollow() &&
+ mrAnchorTxtFrm.GetFollow()->GetOfst() == 0 )
+ {
+ SwLayouter::InsertFrmNotToWrap(
+ *(mrAnchorTxtFrm.FindPageFrm()->GetFmt()->GetDoc()),
+ mrAnchorTxtFrm );
+ SwLayouter::RemoveMovedFwdFrm(
+ *(mrAnchorTxtFrm.FindPageFrm()->GetFmt()->GetDoc()),
+ mrAnchorTxtFrm );
+ }
+ }
+
+ return bSuccess;
+}
+
+void SwObjectFormatterTxtFrm::_InvalidatePrevObjs( SwAnchoredObject& _rAnchoredObj )
+{
+ // invalidate all previous objects, whose wrapping influence on the object
+ // positioning is <NONE_CONCURRENT_POSIITIONED>.
+ // Note: list of objects at anchor frame is sorted by this property.
+ if ( _rAnchoredObj.GetFrmFmt().GetWrapInfluenceOnObjPos().
+ // #i35017# - handle ITERATIVE as ONCE_SUCCESSIVE
+ GetWrapInfluenceOnObjPos( true ) ==
+ // #i35017# - constant name has changed
+ text::WrapInfluenceOnPosition::ONCE_CONCURRENT )
+ {
+ const SwSortedObjs* pObjs = GetAnchorFrm().GetDrawObjs();
+ if ( pObjs )
+ {
+ // determine start index
+ sal_Int32 i = pObjs->ListPosOf( _rAnchoredObj ) - 1;
+ for ( ; i >= 0; --i )
+ {
+ SwAnchoredObject* pAnchoredObj = (*pObjs)[i];
+ if ( pAnchoredObj->GetFrmFmt().GetWrapInfluenceOnObjPos().
+ // #i35017# - handle ITERATIVE as ONCE_SUCCESSIVE
+ GetWrapInfluenceOnObjPos( true ) ==
+ // #i35017# - constant name has changed
+ text::WrapInfluenceOnPosition::ONCE_CONCURRENT )
+ {
+ pAnchoredObj->InvalidateObjPosForConsiderWrapInfluence( true );
+ }
+ }
+ }
+ }
+}
+
+void SwObjectFormatterTxtFrm::_InvalidateFollowObjs( SwAnchoredObject& _rAnchoredObj,
+ const bool _bInclObj )
+{
+ if ( _bInclObj )
+ {
+ _rAnchoredObj.InvalidateObjPosForConsiderWrapInfluence( true );
+ }
+
+ const SwSortedObjs* pObjs = GetPageFrm().GetSortedObjs();
+ if ( pObjs )
+ {
+ // determine start index
+ sal_uInt32 i = pObjs->ListPosOf( _rAnchoredObj ) + 1;
+ for ( ; i < pObjs->Count(); ++i )
+ {
+ SwAnchoredObject* pAnchoredObj = (*pObjs)[i];
+ pAnchoredObj->InvalidateObjPosForConsiderWrapInfluence( true );
+ }
+ }
+}
+
+SwAnchoredObject* SwObjectFormatterTxtFrm::_GetFirstObjWithMovedFwdAnchor(
+ const sal_Int16 _nWrapInfluenceOnPosition,
+ sal_uInt32& _noToPageNum,
+ bool& _boInFollow )
+{
+ // #i35017# - constant names have changed
+ OSL_ENSURE( _nWrapInfluenceOnPosition == text::WrapInfluenceOnPosition::ONCE_SUCCESSIVE ||
+ _nWrapInfluenceOnPosition == text::WrapInfluenceOnPosition::ONCE_CONCURRENT,
+ "<SwObjectFormatterTxtFrm::_GetFirstObjWithMovedFwdAnchor(..)> - invalid value for parameter <_nWrapInfluenceOnPosition>" );
+
+ SwAnchoredObject* pRetAnchoredObj = 0L;
+
+ sal_uInt32 i = 0L;
+ for ( ; i < CountOfCollected(); ++i )
+ {
+ SwAnchoredObject* pAnchoredObj = GetCollectedObj(i);
+ if ( pAnchoredObj->ConsiderObjWrapInfluenceOnObjPos() &&
+ pAnchoredObj->GetFrmFmt().GetWrapInfluenceOnObjPos().
+ // #i35017# - handle ITERATIVE as ONCE_SUCCESSIVE
+ GetWrapInfluenceOnObjPos( true ) == _nWrapInfluenceOnPosition )
+ {
+ // #i26945# - use new method <_CheckMovedFwdCondition(..)>
+ // #i43913#
+ // #i58182# - consider new method signature
+ if ( SwObjectFormatterTxtFrm::CheckMovedFwdCondition( *GetCollectedObj( i ),
+ GetPgNumOfCollected( i ),
+ IsCollectedAnchoredAtMaster( i ),
+ _noToPageNum, _boInFollow ) )
+ {
+ pRetAnchoredObj = pAnchoredObj;
+ break;
+ }
+ }
+ }
+
+ return pRetAnchoredObj;
+}
+
+// #i58182#
+// - replace private method by corresponding static public method
+bool SwObjectFormatterTxtFrm::CheckMovedFwdCondition(
+ SwAnchoredObject& _rAnchoredObj,
+ const sal_uInt32 _nFromPageNum,
+ const bool _bAnchoredAtMasterBeforeFormatAnchor,
+ sal_uInt32& _noToPageNum,
+ bool& _boInFollow )
+{
+ bool bAnchorIsMovedForward( false );
+
+ SwPageFrm* pPageFrmOfAnchor = _rAnchoredObj.FindPageFrmOfAnchor();
+ if ( pPageFrmOfAnchor )
+ {
+ const sal_uInt32 nPageNum = pPageFrmOfAnchor->GetPhyPageNum();
+ if ( nPageNum > _nFromPageNum )
+ {
+ _noToPageNum = nPageNum;
+ // Handling of special case:
+ // If anchor frame is move forward into a follow flow row,
+ // <_noToPageNum> is set to <_nFromPageNum + 1>, because it is
+ // possible that the anchor page frame isn't valid, because the
+ // page distance between master row and follow flow row is greater
+ // than 1.
+ if ( _noToPageNum > (_nFromPageNum + 1) )
+ {
+ SwFrm* pAnchorFrm = _rAnchoredObj.GetAnchorFrmContainingAnchPos();
+ if ( pAnchorFrm->IsInTab() &&
+ pAnchorFrm->IsInFollowFlowRow() )
+ {
+ _noToPageNum = _nFromPageNum + 1;
+ }
+ }
+ bAnchorIsMovedForward = true;
+ }
+ }
+ // #i26945# - check, if an at-paragraph|at-character
+ // anchored object is now anchored at a follow text frame, which will be
+ // on the next page. Also check, if an at-character anchored object
+ // is now anchored at a text frame, which is in a follow flow row,
+ // which will be on the next page.
+ if ( !bAnchorIsMovedForward &&
+ _bAnchoredAtMasterBeforeFormatAnchor &&
+ ((_rAnchoredObj.GetFrmFmt().GetAnchor().GetAnchorId() == FLY_AT_CHAR) ||
+ (_rAnchoredObj.GetFrmFmt().GetAnchor().GetAnchorId() == FLY_AT_PARA)))
+ {
+ SwFrm* pAnchorFrm = _rAnchoredObj.GetAnchorFrmContainingAnchPos();
+ OSL_ENSURE( pAnchorFrm->IsTxtFrm(),
+ "<SwObjectFormatterTxtFrm::CheckMovedFwdCondition(..) - wrong type of anchor frame>" );
+ SwTxtFrm* pAnchorTxtFrm = static_cast<SwTxtFrm*>(pAnchorFrm);
+ bool bCheck( false );
+ if ( pAnchorTxtFrm->IsFollow() )
+ {
+ bCheck = true;
+ }
+ else if( pAnchorTxtFrm->IsInTab() )
+ {
+ const SwRowFrm* pMasterRow = pAnchorTxtFrm->IsInFollowFlowRow();
+ if ( pMasterRow &&
+ pMasterRow->FindPageFrm() == pPageFrmOfAnchor )
+ {
+ bCheck = true;
+ }
+ }
+ if ( bCheck )
+ {
+ // check, if found text frame will be on the next page
+ // by checking, if it's in a column, which has no next.
+ SwFrm* pColFrm = pAnchorTxtFrm->FindColFrm();
+ while ( pColFrm && !pColFrm->GetNext() )
+ {
+ pColFrm = pColFrm->FindColFrm();
+ }
+ if ( !pColFrm || !pColFrm->GetNext() )
+ {
+ _noToPageNum = _nFromPageNum + 1;
+ bAnchorIsMovedForward = true;
+ // #i43913#
+ _boInFollow = true;
+ }
+ }
+ }
+
+ return bAnchorIsMovedForward;
+}
+
+// #i40140# - helper method to format layout frames used by
+// method <SwObjectFormatterTxtFrm::_FormatAnchorFrmForCheckMoveFwd()>
+// #i44049# - format till a certain lower frame, if provided.
+void lcl_FormatCntntOfLayoutFrm( SwLayoutFrm* pLayFrm,
+ SwFrm* pLastLowerFrm = 0L )
+{
+ SwFrm* pLowerFrm = pLayFrm->GetLower();
+ while ( pLowerFrm )
+ {
+ // #i44049#
+ if ( pLastLowerFrm && pLowerFrm == pLastLowerFrm )
+ {
+ break;
+ }
+ if ( pLowerFrm->IsLayoutFrm() )
+ lcl_FormatCntntOfLayoutFrm( static_cast<SwLayoutFrm*>(pLowerFrm),
+ pLastLowerFrm );
+ else
+ pLowerFrm->Calc();
+
+ pLowerFrm = pLowerFrm->GetNext();
+ }
+}
+
+/** method to format given anchor text frame and its previous frames
+
+ #i56300#
+ Usage: Needed to check, if the anchor text frame is moved forward
+ due to the positioning and wrapping of its anchored objects, and
+ to format the frames, which have become invalid due to the anchored
+ object formatting in the iterative object positioning algorithm
+*/
+void SwObjectFormatterTxtFrm::FormatAnchorFrmAndItsPrevs( SwTxtFrm& _rAnchorTxtFrm )
+{
+ // #i47014# - no format of section and previous columns
+ // for follow text frames.
+ if ( !_rAnchorTxtFrm.IsFollow() )
+ {
+ // if anchor frame is directly inside a section, format this section and
+ // its previous frames.
+ // Note: It's a very simple format without formatting objects.
+ if ( _rAnchorTxtFrm.IsInSct() )
+ {
+ SwFrm* pSectFrm = _rAnchorTxtFrm.GetUpper();
+ while ( pSectFrm )
+ {
+ if ( pSectFrm->IsSctFrm() || pSectFrm->IsCellFrm() )
+ {
+ break;
+ }
+ pSectFrm = pSectFrm->GetUpper();
+ }
+ if ( pSectFrm && pSectFrm->IsSctFrm() )
+ {
+ // #i44049#
+ _rAnchorTxtFrm.LockJoin();
+ SwFrm* pFrm = pSectFrm->GetUpper()->GetLower();
+ // #i49605# - section frame could move forward
+ // by the format of its previous frame.
+ // Thus, check for valid <pFrm>.
+ while ( pFrm && pFrm != pSectFrm )
+ {
+ if ( pFrm->IsLayoutFrm() )
+ lcl_FormatCntntOfLayoutFrm( static_cast<SwLayoutFrm*>(pFrm) );
+ else
+ pFrm->Calc();
+
+ pFrm = pFrm->GetNext();
+ }
+ lcl_FormatCntntOfLayoutFrm( static_cast<SwLayoutFrm*>(pSectFrm),
+ &_rAnchorTxtFrm );
+ // #i44049#
+ _rAnchorTxtFrm.UnlockJoin();
+ }
+ }
+
+ // #i40140# - if anchor frame is inside a column,
+ // format the content of the previous columns.
+ // Note: It's a very simple format without formatting objects.
+ SwFrm* pColFrmOfAnchor = _rAnchorTxtFrm.FindColFrm();
+ if ( pColFrmOfAnchor )
+ {
+ // #i44049#
+ _rAnchorTxtFrm.LockJoin();
+ SwFrm* pColFrm = pColFrmOfAnchor->GetUpper()->GetLower();
+ while ( pColFrm != pColFrmOfAnchor )
+ {
+ SwFrm* pFrm = pColFrm->GetLower();
+ while ( pFrm )
+ {
+ if ( pFrm->IsLayoutFrm() )
+ lcl_FormatCntntOfLayoutFrm( static_cast<SwLayoutFrm*>(pFrm) );
+ else
+ pFrm->Calc();
+
+ pFrm = pFrm->GetNext();
+ }
+
+ pColFrm = pColFrm->GetNext();
+ }
+ // #i44049#
+ _rAnchorTxtFrm.UnlockJoin();
+ }
+ }
+
+ // format anchor frame - format of its follow not needed
+ // #i43255# - forbid follow format, only if anchor text
+ // frame is in table
+ if ( _rAnchorTxtFrm.IsInTab() )
+ {
+ SwForbidFollowFormat aForbidFollowFormat( _rAnchorTxtFrm );
+ _rAnchorTxtFrm.Calc();
+ }
+ else
+ {
+ _rAnchorTxtFrm.Calc();
+ }
+}
+
+/** method to format the anchor frame for checking of the move forward condition
+
+ #i40141#
+*/
+void SwObjectFormatterTxtFrm::_FormatAnchorFrmForCheckMoveFwd()
+{
+ SwObjectFormatterTxtFrm::FormatAnchorFrmAndItsPrevs( mrAnchorTxtFrm );
+}
+
+/** method to determine if at least one anchored object has state
+ <temporarly consider wrapping style influence> set.
+*/
+bool SwObjectFormatterTxtFrm::_AtLeastOneObjIsTmpConsiderWrapInfluence()
+{
+ bool bRet( false );
+
+ const SwSortedObjs* pObjs = GetAnchorFrm().GetDrawObjs();
+ if ( pObjs && pObjs->Count() > 1 )
+ {
+ sal_uInt32 i = 0;
+ for ( ; i < pObjs->Count(); ++i )
+ {
+ SwAnchoredObject* pAnchoredObj = (*pObjs)[i];
+ if ( pAnchoredObj->ConsiderObjWrapInfluenceOnObjPos() )
+ {
+ bRet = true;
+ break;
+ }
+ }
+ }
+
+ return bRet;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/layout/objectformattertxtfrm.hxx b/sw/source/core/layout/objectformattertxtfrm.hxx
new file mode 100644
index 000000000000..3d526f9dd214
--- /dev/null
+++ b/sw/source/core/layout/objectformattertxtfrm.hxx
@@ -0,0 +1,201 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+#ifndef _OBJECTFORMATTERTXTFRM_HXX
+#define _OBJECTFORMATTERTXTFRM_HXX
+
+#include <objectformatter.hxx>
+#include <sal/types.h>
+
+class SwTxtFrm;
+
+// -----------------------------------------------------------------------------
+// #i28701#
+// Format floating screen objects, which are anchored at a given anchor text frame
+// and registered at the given page frame.
+// -----------------------------------------------------------------------------
+class SwObjectFormatterTxtFrm : public SwObjectFormatter
+{
+ private:
+ // anchor text frame
+ SwTxtFrm& mrAnchorTxtFrm;
+
+ // 'master' anchor text frame
+ SwTxtFrm* mpMasterAnchorTxtFrm;
+
+ SwObjectFormatterTxtFrm( SwTxtFrm& _rAnchorTxtFrm,
+ const SwPageFrm& _rPageFrm,
+ SwTxtFrm* _pMasterAnchorTxtFrm,
+ SwLayAction* _pLayAction );
+
+ /** method to invalidate objects, anchored previous to given object at
+ the anchor text frame
+
+ @param _rAnchoredObj
+ reference to anchored object - objects, anchored previous to
+ this one will be invalidated.
+ */
+ void _InvalidatePrevObjs( SwAnchoredObject& _rAnchoredObj );
+
+ /** method to invalidate objects, anchored after the given object at
+ the page frame
+
+ @param _rAnchoredObj
+ reference to anchored object - objects, anchored after this one will
+ be invalidated.
+
+ @param _bInclObj
+ boolean indicates, if given anchored object <_rAnchoredObj> also have
+ to be invalidated.
+ */
+ void _InvalidateFollowObjs( SwAnchoredObject& _rAnchoredObj,
+ const bool _bInclObj );
+
+ /** method to determine first anchored object, whose 'anchor is moved
+ forward'.
+
+ 'anchor (of an object) is moved forward', if the anchor frame
+ respectively the anchor character of the object isn't on the
+ proposed page frame. Instead its on a following page
+
+ #i26945# - For at-character anchored objects,
+ it has also to be checked, if the anchor character is in a follow
+ text frame, which would move to the next page.
+
+ #i43913# - add output parameter <_boInFollow>
+
+ @param _nWrapInfluenceOnPosition
+ input parameter - only object with this given wrapping style
+ influence are investigated.
+
+ @param _nFromPageNum
+ input parameter - number of page frame, the 'anchor' should be
+
+ @param _noToPageNum
+ output parameter - number of page frame, the 'anchor' of the returned
+ anchored object is.
+
+ @param _boInFollow
+ output parameter - boolean, indicating that anchor text frame is
+ currently on the same page, but it's a follow of in a follow row,
+ which will move forward. value only relevant, if method returns
+ an anchored object
+
+ @return SwAnchoredObject*
+ anchored object with a 'moved forward anchor'. If NULL, no such
+ anchored object is found.
+ */
+ SwAnchoredObject* _GetFirstObjWithMovedFwdAnchor(
+ const sal_Int16 _nWrapInfluenceOnPosition,
+ sal_uInt32& _noToPageNum,
+ bool& _boInFollow );
+
+ /** method to format the anchor frame for checking of the move forward condition
+
+ #i40141#
+ */
+ void _FormatAnchorFrmForCheckMoveFwd();
+
+ /** method to determine if at least one anchored object has state
+ <temporarly consider wrapping style influence> set.
+ */
+ bool _AtLeastOneObjIsTmpConsiderWrapInfluence();
+
+ protected:
+
+ virtual SwFrm& GetAnchorFrm();
+
+ public:
+ virtual ~SwObjectFormatterTxtFrm();
+
+ // #i40147# - add parameter <_bCheckForMovedFwd>.
+ virtual bool DoFormatObj( SwAnchoredObject& _rAnchoredObj,
+ const bool _bCheckForMovedFwd = false );
+ virtual bool DoFormatObjs();
+
+ /** method to create an instance of <SwObjectFormatterTxtFrm> is
+ necessary.
+ */
+ static SwObjectFormatterTxtFrm* CreateObjFormatter(
+ SwTxtFrm& _rAnchorTxtFrm,
+ const SwPageFrm& _rPageFrm,
+ SwLayAction* _pLayAction );
+
+ /** method to format given anchor text frame and its previous frames
+
+ #i56300#
+ Usage: Needed to check, if the anchor text frame is moved forward
+ due to the positioning and wrapping of its anchored objects, and
+ to format the frames, which have become invalid due to the anchored
+ object formatting in the iterative object positioning algorithm
+
+ @param _rAnchorTxtFrm
+ input parameter - reference to anchor text frame, which has to be
+ formatted including its previous frames of the page.
+ */
+ static void FormatAnchorFrmAndItsPrevs( SwTxtFrm& _rAnchorTxtFrm );
+
+ /** method to check the conditions, if 'anchor is moved forward'
+
+ #i26945#
+ #i43913# - add output parameter <_boInFollow>
+ #i58182# - replace method by a corresponding static
+ method, because it's needed for the iterative positioning algorithm.
+
+ @param _rAnchoredObj
+ input parameter - anchored object, for which the condition has to checked.
+
+ @param _nFromPageNum
+ input parameter - number of the page, on which the check is performed
+
+ @param _bAnchoredAtMasterBeforeFormatAnchor
+ input parameter - boolean indicating, that the given anchored object
+ was anchored at the master frame before the anchor frame has been
+ formatted.
+
+ @param _noToPageNum
+ output parameter - number of page frame, the 'anchor' of the returned
+ anchored object is.
+
+ @param _boInFollow
+ output parameter - boolean, indicating that anchor text frame is
+ currently on the same page, but it's a follow of in a follow row,
+ which will move forward. value only relevant, if method return <true>.
+
+ @return boolean
+ indicating, if 'anchor is moved forward'
+ */
+ static bool CheckMovedFwdCondition( SwAnchoredObject& _rAnchoredObj,
+ const sal_uInt32 _nFromPageNum,
+ const bool _bAnchoredAtMasterBeforeFormatAnchor,
+ sal_uInt32& _noToPageNum,
+ bool& _boInFollow );
+};
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/layout/objstmpconsiderwrapinfl.cxx b/sw/source/core/layout/objstmpconsiderwrapinfl.cxx
new file mode 100644
index 000000000000..1c32c9c75f26
--- /dev/null
+++ b/sw/source/core/layout/objstmpconsiderwrapinfl.cxx
@@ -0,0 +1,76 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+#include <objstmpconsiderwrapinfl.hxx>
+#include <anchoredobject.hxx>
+
+SwObjsMarkedAsTmpConsiderWrapInfluence::SwObjsMarkedAsTmpConsiderWrapInfluence()
+{
+}
+
+SwObjsMarkedAsTmpConsiderWrapInfluence::~SwObjsMarkedAsTmpConsiderWrapInfluence()
+{
+ Clear();
+}
+
+void SwObjsMarkedAsTmpConsiderWrapInfluence::Insert( SwAnchoredObject& _rAnchoredObj )
+{
+
+ bool bAlreadyInserted( false );
+ std::vector< SwAnchoredObject* >::const_iterator aIter = maObjsTmpConsiderWrapInfl.begin();
+ for ( ; aIter != maObjsTmpConsiderWrapInfl.end(); ++aIter )
+ {
+ const SwAnchoredObject* pAnchoredObj = *(aIter);
+ if ( pAnchoredObj == &_rAnchoredObj )
+ {
+ bAlreadyInserted = true;
+ break;
+ }
+ }
+
+ if ( !bAlreadyInserted )
+ {
+ maObjsTmpConsiderWrapInfl.push_back( &_rAnchoredObj );
+ }
+}
+
+void SwObjsMarkedAsTmpConsiderWrapInfluence::Clear()
+{
+ while ( maObjsTmpConsiderWrapInfl.size() )
+ {
+ SwAnchoredObject* pAnchoredObj = maObjsTmpConsiderWrapInfl.back();
+ pAnchoredObj->SetTmpConsiderWrapInfluence( false );
+ pAnchoredObj->SetClearedEnvironment( false );
+
+ maObjsTmpConsiderWrapInfl.pop_back();
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/layout/objstmpconsiderwrapinfl.hxx b/sw/source/core/layout/objstmpconsiderwrapinfl.hxx
new file mode 100644
index 000000000000..f5fd89b3b435
--- /dev/null
+++ b/sw/source/core/layout/objstmpconsiderwrapinfl.hxx
@@ -0,0 +1,50 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+#ifndef _OBJSTMPCONSIDERWRAPINFL_HXX
+#define _OBJSTMPCONSIDERWRAPINFL_HXX
+
+#include <vector>
+
+class SwAnchoredObject;
+
+class SwObjsMarkedAsTmpConsiderWrapInfluence
+{
+ private:
+ std::vector< SwAnchoredObject* > maObjsTmpConsiderWrapInfl;
+
+ public:
+ SwObjsMarkedAsTmpConsiderWrapInfluence();
+ ~SwObjsMarkedAsTmpConsiderWrapInfluence();
+
+ void Insert( SwAnchoredObject& _rAnchoredObj );
+ void Clear();
+};
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/layout/pagechg.cxx b/sw/source/core/layout/pagechg.cxx
new file mode 100644
index 000000000000..aa7aa23e02c0
--- /dev/null
+++ b/sw/source/core/layout/pagechg.cxx
@@ -0,0 +1,2454 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+#include <com/sun/star/embed/EmbedStates.hpp>
+#include <ndole.hxx>
+#include <docary.hxx>
+#include <svl/itemiter.hxx>
+#include <fmtfsize.hxx>
+#include <fmthdft.hxx>
+#include <fmtclds.hxx>
+#include <fmtanchr.hxx>
+#include <fmtpdsc.hxx>
+#include <fmtfordr.hxx>
+#include <fmtfld.hxx>
+#include <fmtornt.hxx>
+#include <ftninfo.hxx>
+#include <tgrditem.hxx>
+#include <viewopt.hxx>
+#include <docsh.hxx>
+
+#include "viewimp.hxx"
+#include "viewopt.hxx"
+#include "pagefrm.hxx"
+#include "rootfrm.hxx"
+#include "cntfrm.hxx"
+#include "flyfrm.hxx"
+#include "doc.hxx"
+#include "fesh.hxx"
+#include "dview.hxx"
+#include "dflyobj.hxx"
+#include "dcontact.hxx"
+#include "frmtool.hxx"
+#include "fldbas.hxx"
+#include "hints.hxx"
+#include "swtable.hxx"
+
+#include "ftnidx.hxx"
+#include "bodyfrm.hxx"
+#include "ftnfrm.hxx"
+#include "tabfrm.hxx"
+#include "txtfrm.hxx"
+#include "layact.hxx"
+#include "flyfrms.hxx"
+#include "htmltbl.hxx"
+#include "pagedesc.hxx"
+#include "poolfmt.hxx"
+#include <editeng/frmdiritem.hxx>
+#include <swfntcch.hxx> // SwFontAccess
+#include <sortedobjs.hxx>
+#include <switerator.hxx>
+#include <vcl/svapp.hxx>
+
+using namespace ::com::sun::star;
+
+
+/*************************************************************************
+|*
+|* SwBodyFrm::SwBodyFrm()
+|*
+|*************************************************************************/
+SwBodyFrm::SwBodyFrm( SwFrmFmt *pFmt, SwFrm* pSib ):
+ SwLayoutFrm( pFmt, pSib )
+{
+ nType = FRMC_BODY;
+}
+
+/*************************************************************************
+|*
+|* SwBodyFrm::Format()
+|*
+|*************************************************************************/
+void SwBodyFrm::Format( const SwBorderAttrs * )
+{
+ //Formatieren des Body ist zu einfach, deshalb bekommt er ein eigenes
+ //Format; Umrandungen und dergl. sind hier nicht zu beruecksichtigen.
+ //Breite ist die der PrtArea des Uppers, Hoehe ist die Hoehe der PrtArea
+ //des Uppers abzueglich der Nachbarn (Wird eigentlich eingestellt aber
+ //Vorsicht ist die Mutter der Robustheit).
+ //Die PrtArea ist stets so gross wie der Frm itself.
+
+ if ( !bValidSize )
+ {
+ SwTwips nHeight = GetUpper()->Prt().Height();
+ SwTwips nWidth = GetUpper()->Prt().Width();
+ const SwFrm *pFrm = GetUpper()->Lower();
+ do
+ {
+ if ( pFrm != this )
+ {
+ if( pFrm->IsVertical() )
+ nWidth -= pFrm->Frm().Width();
+ else
+ nHeight -= pFrm->Frm().Height();
+ }
+ pFrm = pFrm->GetNext();
+ } while ( pFrm );
+ if ( nHeight < 0 )
+ nHeight = 0;
+ Frm().Height( nHeight );
+ //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin
+ if( IsVertical() && !IsVertLR() && !IsReverse() && nWidth != Frm().Width() )
+ Frm().Pos().X() += Frm().Width() - nWidth;
+ Frm().Width( nWidth );
+ }
+
+ sal_Bool bNoGrid = sal_True;
+ if( GetUpper()->IsPageFrm() && ((SwPageFrm*)GetUpper())->HasGrid() )
+ {
+ GETGRID( ((SwPageFrm*)GetUpper()) )
+ if( pGrid )
+ {
+ bNoGrid = sal_False;
+ long nSum = pGrid->GetBaseHeight() + pGrid->GetRubyHeight();
+ SWRECTFN( this )
+ long nSize = (Frm().*fnRect->fnGetWidth)();
+ long nBorder = 0;
+ if( GRID_LINES_CHARS == pGrid->GetGridType() )
+ {
+ //for textgrid refactor
+ SwDoc *pDoc = GetFmt()->GetDoc();
+ nBorder = nSize % (GETGRIDWIDTH(pGrid, pDoc));
+ nSize -= nBorder;
+ nBorder /= 2;
+ }
+ (Prt().*fnRect->fnSetPosX)( nBorder );
+ (Prt().*fnRect->fnSetWidth)( nSize );
+
+ // Height of body frame:
+ nBorder = (Frm().*fnRect->fnGetHeight)();
+
+ // Number of possible lines in area of body frame:
+ long nNumberOfLines = nBorder / nSum;
+ if( nNumberOfLines > pGrid->GetLines() )
+ nNumberOfLines = pGrid->GetLines();
+
+ // Space required for nNumberOfLines lines:
+ nSize = nNumberOfLines * nSum;
+ nBorder -= nSize;
+ nBorder /= 2;
+
+ // #i21774# Footnotes and centering the grid does not work together:
+ const bool bAdjust = 0 == ((SwPageFrm*)GetUpper())->GetFmt()->GetDoc()->
+ GetFtnIdxs().Count();
+
+ (Prt().*fnRect->fnSetPosY)( bAdjust ? nBorder : 0 );
+ (Prt().*fnRect->fnSetHeight)( nSize );
+ }
+ }
+ if( bNoGrid )
+ {
+ Prt().Pos().X() = Prt().Pos().Y() = 0;
+ Prt().Height( Frm().Height() );
+ Prt().Width( Frm().Width() );
+ }
+ bValidSize = bValidPrtArea = sal_True;
+}
+
+void SwBodyFrm::Paint( const SwRect& rRect, const SwPrintData* ) const
+{
+#if OSL_DEBUG_LAYOUT > 1
+ // Paint a red border around the SwBodyFrm in debug mode
+ ViewShell *pSh = GetShell();
+ OutputDevice* pOut = pSh->GetOut();
+ pOut->Push();
+ pOut->SetLineColor(Color(255, 0, 0));
+ pOut->SetFillColor(COL_TRANSPARENT);
+ SwRect aRect = Frm();
+ pOut->DrawRect(aRect.SVRect());
+ pOut->Pop();
+#endif
+ SwLayoutFrm::Paint(rRect);
+}
+
+/*************************************************************************
+|*
+|* SwPageFrm::SwPageFrm(), ~SwPageFrm()
+|*
+|*************************************************************************/
+SwPageFrm::SwPageFrm( SwFrmFmt *pFmt, SwFrm* pSib, SwPageDesc *pPgDsc ) :
+ SwFtnBossFrm( pFmt, pSib ),
+ pSortedObjs( 0 ),
+ pDesc( pPgDsc ),
+ nPhyPageNum( 0 ),
+ // OD 2004-05-17 #i28701#
+ mbLayoutInProgress( false )
+{
+ SetDerivedVert( sal_False );
+ SetDerivedR2L( sal_False );
+ if( pDesc )
+ {
+ bHasGrid = sal_True;
+ GETGRID( this )
+ if( !pGrid )
+ bHasGrid = sal_False;
+ }
+ else
+ bHasGrid = sal_False;
+ SetMaxFtnHeight( pPgDsc->GetFtnInfo().GetHeight() ?
+ pPgDsc->GetFtnInfo().GetHeight() : LONG_MAX ),
+ nType = FRMC_PAGE;
+ bInvalidLayout = bInvalidCntnt = bInvalidSpelling = bInvalidSmartTags = bInvalidAutoCmplWrds = bInvalidWordCount = sal_True;
+ bInvalidFlyLayout = bInvalidFlyCntnt = bInvalidFlyInCnt = bFtnPage = bEndNotePage = sal_False;
+
+ ViewShell *pSh = getRootFrm()->GetCurrShell();
+ const bool bBrowseMode = pSh && pSh->GetViewOptions()->getBrowseMode();
+ if ( bBrowseMode )
+ {
+ Frm().Height( 0 );
+ long nWidth = pSh->VisArea().Width();
+ if ( !nWidth )
+ nWidth = 5000L; //aendert sich sowieso
+ Frm().Width ( nWidth );
+ }
+ else
+ Frm().SSize( pFmt->GetFrmSize().GetSize() );
+
+ //Body-Bereich erzeugen und einsetzen, aber nur wenn ich nicht gerade
+ //eine Leerseite bin.
+ SwDoc *pDoc = pFmt->GetDoc();
+ if ( sal_False == (bEmptyPage = pFmt == pDoc->GetEmptyPageFmt()) )
+ {
+ bEmptyPage = sal_False;
+ Calc(); //Damit die PrtArea stimmt.
+ SwBodyFrm *pBodyFrm = new SwBodyFrm( pDoc->GetDfltFrmFmt(), this );
+ pBodyFrm->ChgSize( Prt().SSize() );
+ pBodyFrm->Paste( this );
+ pBodyFrm->Calc(); //Damit die Spalten korrekt
+ //eingesetzt werden koennen.
+ pBodyFrm->InvalidatePos();
+
+ if ( bBrowseMode )
+ _InvalidateSize(); //Alles nur gelogen
+
+ //Header/Footer einsetzen, nur rufen wenn aktiv.
+ if ( pFmt->GetHeader().IsActive() )
+ PrepareHeader();
+ if ( pFmt->GetFooter().IsActive() )
+ PrepareFooter();
+
+ const SwFmtCol &rCol = pFmt->GetCol();
+ if ( rCol.GetNumCols() > 1 )
+ {
+ const SwFmtCol aOld; //ChgColumns() verlaesst sich darauf, dass ein
+ //Old-Wert hereingereicht wird.
+ pBodyFrm->ChgColumns( aOld, rCol );
+ }
+ }
+}
+
+SwPageFrm::~SwPageFrm()
+{
+ //FlyContainer entleeren, delete der Flys uebernimmt der Anchor
+ //(Basisklasse SwFrm)
+ if ( pSortedObjs )
+ {
+ //Objekte koennen (warum auch immer) auch an Seiten verankert sein,
+ //die vor Ihren Ankern stehen. Dann wuerde auf bereits freigegebenen
+ //Speicher zugegriffen.
+ for ( sal_uInt16 i = 0; i < pSortedObjs->Count(); ++i )
+ {
+ SwAnchoredObject* pAnchoredObj = (*pSortedObjs)[i];
+ pAnchoredObj->SetPageFrm( 0L );
+ }
+ delete pSortedObjs;
+ pSortedObjs = 0; //Auf 0 setzen, sonst rauchts beim Abmdelden von Flys!
+ }
+
+ //Damit der Zugriff auf zerstoerte Seiten verhindert werden kann.
+ if ( !IsEmptyPage() ) //#59184# sollte fuer Leerseiten unnoetig sein.
+ {
+ SwDoc *pDoc = GetFmt()->GetDoc();
+ if( pDoc && !pDoc->IsInDtor() )
+ {
+ ViewShell *pSh = getRootFrm()->GetCurrShell();
+ if ( pSh )
+ {
+ SwViewImp *pImp = pSh->Imp();
+ pImp->SetFirstVisPageInvalid();
+ if ( pImp->IsAction() )
+ pImp->GetLayAction().SetAgain();
+ // OD 12.02.2003 #i9719#, #105645# - retouche area of page
+ // including border and shadow area.
+ const bool bRightSidebar = (SidebarPosition() == sw::sidebarwindows::SIDEBAR_RIGHT);
+ SwRect aRetoucheRect;
+ SwPageFrm::GetBorderAndShadowBoundRect( Frm(), pSh, aRetoucheRect, IsLeftShadowNeeded(), IsRightShadowNeeded(), bRightSidebar );
+ pSh->AddPaintRect( aRetoucheRect );
+ }
+ }
+ }
+}
+
+
+void SwPageFrm::CheckGrid( sal_Bool bInvalidate )
+{
+ sal_Bool bOld = bHasGrid;
+ bHasGrid = sal_True;
+ GETGRID( this )
+ bHasGrid = 0 != pGrid;
+ if( bInvalidate || bOld != bHasGrid )
+ {
+ SwLayoutFrm* pBody = FindBodyCont();
+ if( pBody )
+ {
+ pBody->InvalidatePrt();
+ SwCntntFrm* pFrm = pBody->ContainsCntnt();
+ while( pBody->IsAnLower( pFrm ) )
+ {
+ ((SwTxtFrm*)pFrm)->Prepare( PREP_CLEAR );
+ pFrm = pFrm->GetNextCntntFrm();
+ }
+ }
+ SetCompletePaint();
+ }
+}
+
+
+void SwPageFrm::CheckDirection( sal_Bool bVert )
+{
+ sal_uInt16 nDir =
+ ((SvxFrameDirectionItem&)GetFmt()->GetFmtAttr( RES_FRAMEDIR )).GetValue();
+ if( bVert )
+ {
+ if( FRMDIR_HORI_LEFT_TOP == nDir || FRMDIR_HORI_RIGHT_TOP == nDir )
+ {
+ //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin
+ bVertLR = 0;
+ bVertical = 0;
+ }
+ else
+ {
+ const ViewShell *pSh = getRootFrm()->GetCurrShell();
+ if( pSh && pSh->GetViewOptions()->getBrowseMode() )
+ {
+ //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin
+ bVertLR = 0;
+ bVertical = 0;
+ }
+ else
+ {
+ bVertical = 1;
+ //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin
+ if(FRMDIR_VERT_TOP_RIGHT == nDir)
+ bVertLR = 0;
+ else if(FRMDIR_VERT_TOP_LEFT==nDir)
+ bVertLR = 1;
+ }
+ }
+
+ bReverse = 0;
+ bInvalidVert = 0;
+ }
+ else
+ {
+ if( FRMDIR_HORI_RIGHT_TOP == nDir )
+ bRightToLeft = 1;
+ else
+ bRightToLeft = 0;
+ bInvalidR2L = 0;
+ }
+}
+
+/*************************************************************************
+|*
+|* SwPageFrm::PreparePage()
+|*
+|* Beschreibung Erzeugt die Spezifischen Flys zur Seite und formatiert
+|* generischen Cntnt
+|*
+|*************************************************************************/
+void MA_FASTCALL lcl_FormatLay( SwLayoutFrm *pLay )
+{
+ //Alle LayoutFrms - nicht aber Tables, Flys o.ae. - formatieren.
+
+ SwFrm *pTmp = pLay->Lower();
+ //Erst die untergeordneten
+ while ( pTmp )
+ {
+ if ( pTmp->GetType() & 0x00FF )
+ ::lcl_FormatLay( (SwLayoutFrm*)pTmp );
+ pTmp = pTmp->GetNext();
+ }
+ pLay->Calc();
+}
+
+void MA_FASTCALL lcl_MakeObjs( const SwSpzFrmFmts &rTbl, SwPageFrm *pPage )
+{
+ //Anlegen bzw. registrieren von Flys und Drawobjekten.
+ //Die Formate stehen in der SpzTbl (vom Dokument).
+ //Flys werden angelegt, DrawObjekte werden bei der Seite angemeldet.
+
+ for ( sal_uInt16 i = 0; i < rTbl.Count(); ++i )
+ {
+ SdrObject *pSdrObj;
+ SwFrmFmt *pFmt = rTbl[i];
+ const SwFmtAnchor &rAnch = pFmt->GetAnchor();
+ if ( rAnch.GetPageNum() == pPage->GetPhyPageNum() )
+ {
+ if( rAnch.GetCntntAnchor() )
+ {
+ if (FLY_AT_PAGE == rAnch.GetAnchorId())
+ {
+ SwFmtAnchor aAnch( rAnch );
+ aAnch.SetAnchor( 0 );
+ pFmt->SetFmtAttr( aAnch );
+ }
+ else
+ continue;
+ }
+
+ //Wird ein Rahmen oder ein SdrObject beschrieben?
+ sal_Bool bSdrObj = RES_DRAWFRMFMT == pFmt->Which();
+ pSdrObj = 0;
+ if ( bSdrObj && 0 == (pSdrObj = pFmt->FindSdrObject()) )
+ {
+ OSL_FAIL( "DrawObject not found." );
+ pFmt->GetDoc()->DelFrmFmt( pFmt );
+ --i;
+ continue;
+ }
+ //Das Objekt kann noch an einer anderen Seite verankert sein.
+ //Z.B. beim Einfuegen einer neuen Seite aufgrund eines
+ //Pagedescriptor-Wechsels. Das Objekt muss dann umgehaengt
+ //werden.
+ //Fuer bestimmte Faelle ist das Objekt bereits an der richtigen
+ //Seite verankert. Das wird hier automatisch erledigt und braucht
+ //- wenngleich performater machbar - nicht extra codiert werden.
+ SwPageFrm *pPg = pPage->IsEmptyPage() ? (SwPageFrm*)pPage->GetNext() : pPage;
+ if ( bSdrObj )
+ {
+ // OD 23.06.2003 #108784# - consider 'virtual' drawing objects
+ SwDrawContact *pContact =
+ static_cast<SwDrawContact*>(::GetUserCall(pSdrObj));
+ if ( pSdrObj->ISA(SwDrawVirtObj) )
+ {
+ SwDrawVirtObj* pDrawVirtObj = static_cast<SwDrawVirtObj*>(pSdrObj);
+ if ( pContact )
+ {
+ pDrawVirtObj->RemoveFromWriterLayout();
+ pDrawVirtObj->RemoveFromDrawingPage();
+ pPg->AppendDrawObj( *(pContact->GetAnchoredObj( pDrawVirtObj )) );
+ }
+ }
+ else
+ {
+ if ( pContact->GetAnchorFrm() )
+ pContact->DisconnectFromLayout( false );
+ pPg->AppendDrawObj( *(pContact->GetAnchoredObj( pSdrObj )) );
+ }
+ }
+ else
+ {
+ SwIterator<SwFlyFrm,SwFmt> aIter( *pFmt );
+ SwFlyFrm *pFly = aIter.First();
+ if ( pFly)
+ {
+ if( pFly->GetAnchorFrm() )
+ pFly->AnchorFrm()->RemoveFly( pFly );
+ }
+ else
+ pFly = new SwFlyLayFrm( (SwFlyFrmFmt*)pFmt, pPg, pPg );
+ pPg->AppendFly( pFly );
+ ::RegistFlys( pPg, pFly );
+ }
+ }
+ }
+}
+
+void SwPageFrm::PreparePage( sal_Bool bFtn )
+{
+ SetFtnPage( bFtn );
+
+ // --> OD 2008-01-30 #i82258#
+ // Due to made change on OOo 2.0 code line, method <::lcl_FormatLay(..)> has
+ // the side effect, that the content of page header and footer are formatted.
+ // For this formatting it is needed that the anchored objects are registered
+ // at the <SwPageFrm> instance.
+ // Thus, first calling <::RegistFlys(..)>, then call <::lcl_FormatLay(..)>
+ ::RegistFlys( this, this );
+
+ if ( Lower() )
+ {
+ ::lcl_FormatLay( this );
+ }
+ // <--
+
+ //Flys und DrawObjekte die noch am Dokument bereitstehen.
+ //Fussnotenseiten tragen keine Seitengebundenen Flys!
+ //Es kann Flys und Objekte geben, die auf Leerseiten (Seitennummernmaessig)
+ //stehen wollen, diese werden jedoch von den Leerseiten ignoriert;
+ //sie werden von den Folgeseiten aufgenommen.
+ if ( !bFtn && !IsEmptyPage() )
+ {
+ SwDoc *pDoc = GetFmt()->GetDoc();
+
+ if ( GetPrev() && ((SwPageFrm*)GetPrev())->IsEmptyPage() )
+ lcl_MakeObjs( *pDoc->GetSpzFrmFmts(), (SwPageFrm*)GetPrev() );
+ lcl_MakeObjs( *pDoc->GetSpzFrmFmts(), this );
+
+ //Kopf-/Fusszeilen) formatieren.
+ SwLayoutFrm *pLow = (SwLayoutFrm*)Lower();
+ while ( pLow )
+ {
+ if ( pLow->GetType() & (FRMTYPE_HEADER|FRMTYPE_FOOTER) )
+ {
+ SwCntntFrm *pCntnt = pLow->ContainsCntnt();
+ while ( pCntnt && pLow->IsAnLower( pCntnt ) )
+ {
+ pCntnt->OptCalc(); //Nicht die Vorgaenger
+ pCntnt = pCntnt->GetNextCntntFrm();
+ }
+ }
+ pLow = (SwLayoutFrm*)pLow->GetNext();
+ }
+ }
+}
+
+/*************************************************************************
+|*
+|* SwPageFrm::Modify()
+|*
+|*************************************************************************/
+void SwPageFrm::Modify( const SfxPoolItem* pOld, const SfxPoolItem * pNew )
+{
+ ViewShell *pSh = getRootFrm()->GetCurrShell();
+ if ( pSh )
+ pSh->SetFirstVisPageInvalid();
+ sal_uInt8 nInvFlags = 0;
+
+ if( pNew && RES_ATTRSET_CHG == pNew->Which() )
+ {
+ SfxItemIter aNIter( *((SwAttrSetChg*)pNew)->GetChgSet() );
+ SfxItemIter aOIter( *((SwAttrSetChg*)pOld)->GetChgSet() );
+ SwAttrSetChg aOldSet( *(SwAttrSetChg*)pOld );
+ SwAttrSetChg aNewSet( *(SwAttrSetChg*)pNew );
+ while( sal_True )
+ {
+ _UpdateAttr( (SfxPoolItem*)aOIter.GetCurItem(),
+ (SfxPoolItem*)aNIter.GetCurItem(), nInvFlags,
+ &aOldSet, &aNewSet );
+ if( aNIter.IsAtEnd() )
+ break;
+ aNIter.NextItem();
+ aOIter.NextItem();
+ }
+ if ( aOldSet.Count() || aNewSet.Count() )
+ SwLayoutFrm::Modify( &aOldSet, &aNewSet );
+ }
+ else
+ _UpdateAttr( pOld, pNew, nInvFlags );
+
+ if ( nInvFlags != 0 )
+ {
+ InvalidatePage( this );
+ if ( nInvFlags & 0x01 )
+ _InvalidatePrt();
+ if ( nInvFlags & 0x02 )
+ SetCompletePaint();
+ if ( nInvFlags & 0x04 && GetNext() )
+ GetNext()->InvalidatePos();
+ if ( nInvFlags & 0x08 )
+ PrepareHeader();
+ if ( nInvFlags & 0x10 )
+ PrepareFooter();
+ if ( nInvFlags & 0x20 )
+ CheckGrid( nInvFlags & 0x40 );
+ }
+}
+
+void SwPageFrm::_UpdateAttr( const SfxPoolItem *pOld, const SfxPoolItem *pNew,
+ sal_uInt8 &rInvFlags,
+ SwAttrSetChg *pOldSet, SwAttrSetChg *pNewSet )
+{
+ sal_Bool bClear = sal_True;
+ const sal_uInt16 nWhich = pOld ? pOld->Which() : pNew ? pNew->Which() : 0;
+ switch( nWhich )
+ {
+ case RES_FMT_CHG:
+ {
+ //Wenn sich das FrmFmt aendert kann hier einiges passieren.
+ //Abgesehen von den Grossenverhaeltnissen sind noch andere
+ //Dinge betroffen.
+ //1. Spaltigkeit.
+ OSL_ENSURE( pOld && pNew, "FMT_CHG Missing Format." );
+ const SwFmt* pOldFmt = ((SwFmtChg*)pOld)->pChangedFmt;
+ const SwFmt* pNewFmt = ((SwFmtChg*)pNew)->pChangedFmt;
+ OSL_ENSURE( pOldFmt && pNewFmt, "FMT_CHG Missing Format." );
+
+ const SwFmtCol &rOldCol = pOldFmt->GetCol();
+ const SwFmtCol &rNewCol = pNewFmt->GetCol();
+ if( rOldCol != rNewCol )
+ {
+ SwLayoutFrm *pB = FindBodyCont();
+ OSL_ENSURE( pB, "Seite ohne Body." );
+ pB->ChgColumns( rOldCol, rNewCol );
+ rInvFlags |= 0x20;
+ }
+
+ //2. Kopf- und Fusszeilen.
+ const SwFmtHeader &rOldH = pOldFmt->GetHeader();
+ const SwFmtHeader &rNewH = pNewFmt->GetHeader();
+ if( rOldH != rNewH )
+ rInvFlags |= 0x08;
+
+ const SwFmtFooter &rOldF = pOldFmt->GetFooter();
+ const SwFmtFooter &rNewF = pNewFmt->GetFooter();
+ if( rOldF != rNewF )
+ rInvFlags |= 0x10;
+ CheckDirChange();
+ }
+ /* kein break hier */
+ case RES_FRM_SIZE:
+ {
+ const SwRect aOldPageFrmRect( Frm() );
+ ViewShell *pSh = getRootFrm()->GetCurrShell();
+ if( pSh && pSh->GetViewOptions()->getBrowseMode() )
+ {
+ bValidSize = sal_False;
+ // OD 28.10.2002 #97265# - Don't call <SwPageFrm::MakeAll()>
+ // Calculation of the page is not necessary, because its size is
+ // is invalidated here and further invalidation is done in the
+ // calling method <SwPageFrm::Modify(..)> and probably by calling
+ // <SwLayoutFrm::Modify(..)> at the end.
+ // It can also causes inconsistences, because the lowers are
+ // adjusted, but not calculated, and a <SwPageFrm::MakeAll()> of
+ // a next page is called. This is performed on the switch to the
+ // online layout.
+ //MakeAll();
+ }
+ else
+ {
+ const SwFmtFrmSize &rSz = nWhich == RES_FMT_CHG ?
+ ((SwFmtChg*)pNew)->pChangedFmt->GetFrmSize() :
+ (const SwFmtFrmSize&)*pNew;
+
+ Frm().Height( Max( rSz.GetHeight(), long(MINLAY) ) );
+ Frm().Width ( Max( rSz.GetWidth(), long(MINLAY) ) );
+
+ // PAGES01
+ if ( GetUpper() )
+ static_cast<SwRootFrm*>(GetUpper())->CheckViewLayout( 0, 0 );
+ }
+ //Window aufraeumen.
+ if( pSh && pSh->GetWin() && aOldPageFrmRect.HasArea() )
+ {
+ // OD 12.02.2003 #i9719#, #105645# - consider border and shadow of
+ // page frame for determine 'old' rectangle - it's used for invalidating.
+ const bool bRightSidebar = (SidebarPosition() == sw::sidebarwindows::SIDEBAR_RIGHT);
+ SwRect aOldRectWithBorderAndShadow;
+ SwPageFrm::GetBorderAndShadowBoundRect( aOldPageFrmRect, pSh, aOldRectWithBorderAndShadow,
+ IsLeftShadowNeeded(), IsRightShadowNeeded(), bRightSidebar );
+ pSh->InvalidateWindows( aOldRectWithBorderAndShadow );
+ }
+ rInvFlags |= 0x03;
+ if ( aOldPageFrmRect.Height() != Frm().Height() )
+ rInvFlags |= 0x04;
+ }
+ break;
+
+ case RES_COL:
+ {
+ SwLayoutFrm *pB = FindBodyCont();
+ OSL_ENSURE( pB, "Seite ohne Body." );
+ pB->ChgColumns( *(const SwFmtCol*)pOld, *(const SwFmtCol*)pNew );
+ rInvFlags |= 0x22;
+ }
+ break;
+
+ case RES_HEADER:
+ rInvFlags |= 0x08;
+ break;
+
+ case RES_FOOTER:
+ rInvFlags |= 0x10;
+ break;
+ case RES_TEXTGRID:
+ rInvFlags |= 0x60;
+ break;
+
+ case RES_PAGEDESC_FTNINFO:
+ //Die derzeit einzig sichere Methode:
+ ((SwRootFrm*)GetUpper())->SetSuperfluous();
+ SetMaxFtnHeight( pDesc->GetFtnInfo().GetHeight() );
+ if ( !GetMaxFtnHeight() )
+ SetMaxFtnHeight( LONG_MAX );
+ SetColMaxFtnHeight();
+ //Hier wird die Seite ggf. zerstoert!
+ ((SwRootFrm*)GetUpper())->RemoveFtns( 0, sal_False, sal_True );
+ break;
+ case RES_FRAMEDIR :
+ CheckDirChange();
+ break;
+
+ default:
+ bClear = sal_False;
+ }
+ if ( bClear )
+ {
+ if ( pOldSet || pNewSet )
+ {
+ if ( pOldSet )
+ pOldSet->ClearItem( nWhich );
+ if ( pNewSet )
+ pNewSet->ClearItem( nWhich );
+ }
+ else
+ SwLayoutFrm::Modify( pOld, pNew );
+ }
+}
+
+/*************************************************************************
+|*
+|* SwPageFrm::GetInfo()
+|*
+|* Beschreibung erfragt Informationen
+|*
+*************************************************************************/
+ // erfrage vom Modify Informationen
+sal_Bool SwPageFrm::GetInfo( SfxPoolItem & rInfo ) const
+{
+ if( RES_AUTOFMT_DOCNODE == rInfo.Which() )
+ {
+ // es gibt einen PageFrm also wird er benutzt
+ return sal_False;
+ }
+ return sal_True; // weiter suchen
+}
+
+/*************************************************************************
+|*
+|* SwPageFrm::SetPageDesc()
+|*
+|*************************************************************************/
+void SwPageFrm::SetPageDesc( SwPageDesc *pNew, SwFrmFmt *pFmt )
+{
+ pDesc = pNew;
+ if ( pFmt )
+ SetFrmFmt( pFmt );
+}
+
+/*************************************************************************
+|*
+|* SwPageFrm::FindPageDesc()
+|*
+|* Beschreibung Der richtige PageDesc wird bestimmt:
+|* 0. Vom Dokument bei Fussnotenseiten und Endnotenseiten
+|* 1. vom ersten BodyCntnt unterhalb der Seite.
+|* 2. vom PageDesc der vorstehenden Seite.
+|* 3. bei Leerseiten vom PageDesc der vorigen Seite.
+|* 3.1 vom PageDesc der folgenden Seite wenn es keinen Vorgaenger gibt.
+|* 4. es ist der Default-PageDesc sonst.
+|* 5. Im BrowseMode ist der Pagedesc immer der vom ersten Absatz im
+|* Dokument oder Standard (der 0-te) wenn der erste Absatz keinen
+|* wuenscht.
+|* (6. Im HTML-Mode ist der Pagedesc immer die HTML-Seitenvorlage.)
+|*
+|*************************************************************************/
+SwPageDesc *SwPageFrm::FindPageDesc()
+{
+ //0.
+ if ( IsFtnPage() )
+ {
+ SwDoc *pDoc = GetFmt()->GetDoc();
+ if ( IsEndNotePage() )
+ return pDoc->GetEndNoteInfo().GetPageDesc( *pDoc );
+ else
+ return pDoc->GetFtnInfo().GetPageDesc( *pDoc );
+ }
+
+ //6.
+ //if ( GetFmt()->GetDoc()->IsHTMLMode() )
+ // return GetFmt()->GetDoc()->GetPageDescFromPool( RES_POOLPAGE_HTML );
+
+ SwPageDesc *pRet = 0;
+
+ //5.
+ const ViewShell *pSh = getRootFrm()->GetCurrShell();
+ if( pSh && pSh->GetViewOptions()->getBrowseMode() )
+ {
+ SwCntntFrm *pFrm = GetUpper()->ContainsCntnt();
+ while ( !pFrm->IsInDocBody() )
+ pFrm = pFrm->GetNextCntntFrm();
+ SwFrm *pFlow = pFrm;
+ if ( pFlow->IsInTab() )
+ pFlow = pFlow->FindTabFrm();
+ pRet = (SwPageDesc*)pFlow->GetAttrSet()->GetPageDesc().GetPageDesc();
+ if ( !pRet )
+ pRet = &GetFmt()->GetDoc()->_GetPageDesc( 0 );
+ return pRet;
+ }
+
+ SwFrm *pFlow = FindFirstBodyCntnt();
+ if ( pFlow && pFlow->IsInTab() )
+ pFlow = pFlow->FindTabFrm();
+
+ //1.
+ if ( pFlow )
+ {
+ SwFlowFrm *pTmp = SwFlowFrm::CastFlowFrm( pFlow );
+ if ( !pTmp->IsFollow() )
+ pRet = (SwPageDesc*)pFlow->GetAttrSet()->GetPageDesc().GetPageDesc();
+ }
+
+ //3. und 3.1
+ if ( !pRet && IsEmptyPage() )
+ // FME 2008-03-03 #i81544# lijian/fme: an empty page should have
+ // the same page description as its prev, just like after construction
+ // of the empty page.
+ pRet = GetPrev() ? ((SwPageFrm*)GetPrev())->GetPageDesc() :
+ GetNext() ? ((SwPageFrm*)GetNext())->GetPageDesc() : 0;
+
+ //2.
+ if ( !pRet )
+ pRet = GetPrev() ?
+ ((SwPageFrm*)GetPrev())->GetPageDesc()->GetFollow() : 0;
+
+ //4.
+ if ( !pRet )
+ pRet = (SwPageDesc*)&(const_cast<const SwDoc *>(GetFmt()->GetDoc())
+ ->GetPageDesc( 0 ));
+
+
+ OSL_ENSURE( pRet, "Kein Descriptor gefunden." );
+ return pRet;
+}
+
+//Wenn der RootFrm seine Groesse aendert muss benachrichtigt werden.
+void AdjustSizeChgNotify( SwRootFrm *pRoot )
+{
+ const sal_Bool bOld = pRoot->IsSuperfluous();
+ pRoot->bCheckSuperfluous = sal_False;
+ ViewShell *pSh = pRoot->GetCurrShell();
+ if ( pSh )
+ {
+ do
+ {
+ if( pRoot == pSh->GetLayout() )
+ {
+ pSh->SizeChgNotify();
+ pSh->Imp()->NotifySizeChg( pRoot->Frm().SSize() );
+ }
+ pSh = (ViewShell*)pSh->GetNext();
+ } while ( pSh != pRoot->GetCurrShell() );
+ }
+ pRoot->bCheckSuperfluous = bOld;
+}
+
+
+inline void SetLastPage( SwPageFrm *pPage )
+{
+ ((SwRootFrm*)pPage->GetUpper())->pLastPage = pPage;
+}
+
+/*************************************************************************
+|*
+|* SwPageFrm::Cut()
+|*
+|*************************************************************************/
+void SwPageFrm::Cut()
+{
+ // PAGES01
+ //AdjustRootSize( CHG_CUTPAGE, 0 );
+
+ ViewShell *pSh = getRootFrm()->GetCurrShell();
+ if ( !IsEmptyPage() )
+ {
+ if ( GetNext() )
+ GetNext()->InvalidatePos();
+
+ //Flys deren Anker auf anderen Seiten stehen umhaengen.
+ //DrawObjecte spielen hier keine Rolle.
+ if ( GetSortedObjs() )
+ {
+ for ( int i = 0; GetSortedObjs() &&
+ (sal_uInt16)i < GetSortedObjs()->Count(); ++i )
+ {
+ // --> OD 2004-06-29 #i28701#
+ SwAnchoredObject* pAnchoredObj = (*GetSortedObjs())[i];
+
+ if ( pAnchoredObj->ISA(SwFlyAtCntFrm) )
+ {
+ SwFlyFrm* pFly = static_cast<SwFlyAtCntFrm*>(pAnchoredObj);
+ SwPageFrm *pAnchPage = pFly->GetAnchorFrm() ?
+ pFly->AnchorFrm()->FindPageFrm() : 0;
+ if ( pAnchPage && (pAnchPage != this) )
+ {
+ MoveFly( pFly, pAnchPage );
+ --i;
+ pFly->InvalidateSize();
+ pFly->_InvalidatePos();
+ }
+ }
+ // <--
+ }
+ }
+ //Window aufraeumen
+ if ( pSh && pSh->GetWin() )
+ pSh->InvalidateWindows( Frm() );
+ }
+
+ // die Seitennummer der Root runterzaehlen.
+ ((SwRootFrm*)GetUpper())->DecrPhyPageNums();
+ SwPageFrm *pPg = (SwPageFrm*)GetNext();
+ if ( pPg )
+ {
+ while ( pPg )
+ {
+ pPg->DecrPhyPageNum(); //inline --nPhyPageNum
+ pPg = (SwPageFrm*)pPg->GetNext();
+ }
+ }
+ else
+ ::SetLastPage( (SwPageFrm*)GetPrev() );
+
+ SwFrm* pRootFrm = GetUpper();
+
+ // Alle Verbindungen kappen.
+ Remove();
+
+ // PAGES01
+ if ( pRootFrm )
+ static_cast<SwRootFrm*>(pRootFrm)->CheckViewLayout( 0, 0 );
+}
+
+/*************************************************************************
+|*
+|* SwPageFrm::Paste()
+|*
+|*************************************************************************/
+void SwPageFrm::Paste( SwFrm* pParent, SwFrm* pSibling )
+{
+ OSL_ENSURE( pParent->IsRootFrm(), "Parent ist keine Root." );
+ OSL_ENSURE( pParent, "Kein Parent fuer Paste." );
+ OSL_ENSURE( pParent != this, "Bin selbst der Parent." );
+ OSL_ENSURE( pSibling != this, "Bin mein eigener Nachbar." );
+ OSL_ENSURE( !GetPrev() && !GetNext() && !GetUpper(),
+ "Bin noch irgendwo angemeldet." );
+
+ //In den Baum einhaengen.
+ InsertBefore( (SwLayoutFrm*)pParent, pSibling );
+
+ // die Seitennummer am Root hochzaehlen.
+ ((SwRootFrm*)GetUpper())->IncrPhyPageNums();
+ if( GetPrev() )
+ SetPhyPageNum( ((SwPageFrm*)GetPrev())->GetPhyPageNum() + 1 );
+ else
+ SetPhyPageNum( 1 );
+ SwPageFrm *pPg = (SwPageFrm*)GetNext();
+ if ( pPg )
+ {
+ while ( pPg )
+ {
+ pPg->IncrPhyPageNum(); //inline ++nPhyPageNum
+ pPg->_InvalidatePos();
+ pPg->InvalidateLayout();
+ pPg = (SwPageFrm*)pPg->GetNext();
+ }
+ }
+ else
+ ::SetLastPage( this );
+
+ if( Frm().Width() != pParent->Prt().Width() )
+ _InvalidateSize();
+
+ InvalidatePos();
+
+ ViewShell *pSh = getRootFrm()->GetCurrShell();
+ if ( pSh )
+ pSh->SetFirstVisPageInvalid();
+ // PAGES01
+ getRootFrm()->CheckViewLayout( 0, 0 );
+}
+
+/*************************************************************************
+|*
+|* SwPageFrm::PrepareRegisterChg()
+|*
+|*************************************************************************/
+void lcl_PrepFlyInCntRegister( SwCntntFrm *pFrm )
+{
+ pFrm->Prepare( PREP_REGISTER );
+ if( pFrm->GetDrawObjs() )
+ {
+ for( sal_uInt16 i = 0; i < pFrm->GetDrawObjs()->Count(); ++i )
+ {
+ // --> OD 2004-06-29 #i28701#
+ SwAnchoredObject* pAnchoredObj = (*pFrm->GetDrawObjs())[i];
+ if ( pAnchoredObj->ISA(SwFlyInCntFrm) )
+ {
+ SwFlyFrm* pFly = static_cast<SwFlyInCntFrm*>(pAnchoredObj);
+ SwCntntFrm *pCnt = pFly->ContainsCntnt();
+ while ( pCnt )
+ {
+ lcl_PrepFlyInCntRegister( pCnt );
+ pCnt = pCnt->GetNextCntntFrm();
+ }
+ }
+ // <--
+ }
+ }
+}
+
+void SwPageFrm::PrepareRegisterChg()
+{
+ SwCntntFrm *pFrm = FindFirstBodyCntnt();
+ while( pFrm )
+ {
+ lcl_PrepFlyInCntRegister( pFrm );
+ pFrm = pFrm->GetNextCntntFrm();
+ if( !IsAnLower( pFrm ) )
+ break;
+ }
+ if( GetSortedObjs() )
+ {
+ for( sal_uInt16 i = 0; i < GetSortedObjs()->Count(); ++i )
+ {
+ // --> OD 2004-06-29 #i28701#
+ SwAnchoredObject* pAnchoredObj = (*GetSortedObjs())[i];
+ if ( pAnchoredObj->ISA(SwFlyFrm) )
+ {
+ SwFlyFrm *pFly = static_cast<SwFlyFrm*>(pAnchoredObj);
+ pFrm = pFly->ContainsCntnt();
+ while ( pFrm )
+ {
+ ::lcl_PrepFlyInCntRegister( pFrm );
+ pFrm = pFrm->GetNextCntntFrm();
+ }
+ }
+ }
+ }
+}
+
+/*************************************************************************
+|*
+|* SwFrm::CheckPageDescs()
+|*
+|* Beschreibung Prueft alle Seiten ab der uebergebenen, daraufhin,
+|* ob sie das richtige FrmFmt verwenden. Wenn 'falsche' Seiten
+|* aufgespuehrt werden, so wird versucht die Situation moeglichst
+|* einfache zu bereinigen.
+|*
+|*************************************************************************/
+void SwFrm::CheckPageDescs( SwPageFrm *pStart, sal_Bool bNotifyFields )
+{
+ OSL_ENSURE( pStart, "Keine Startpage." );
+
+ ViewShell *pSh = pStart->getRootFrm()->GetCurrShell();
+ SwViewImp *pImp = pSh ? pSh->Imp() : 0;
+
+ if ( pImp && pImp->IsAction() && !pImp->GetLayAction().IsCheckPages() )
+ {
+ pImp->GetLayAction().SetCheckPageNum( pStart->GetPhyPageNum() );
+ return;
+ }
+
+ //Fuer das Aktualisieren der Seitennummern-Felder gibt nDocPos
+ //die Seitenposition an, _ab_ der invalidiert werden soll.
+ SwTwips nDocPos = LONG_MAX;
+
+ SwRootFrm *pRoot = (SwRootFrm*)pStart->GetUpper();
+ SwDoc* pDoc = pStart->GetFmt()->GetDoc();
+ const sal_Bool bFtns = 0 != pDoc->GetFtnIdxs().Count();
+
+ SwPageFrm *pPage = pStart;
+ if( pPage->GetPrev() && ((SwPageFrm*)pPage->GetPrev())->IsEmptyPage() )
+ pPage = (SwPageFrm*)pPage->GetPrev();
+ while ( pPage )
+ {
+ //gewuenschten PageDesc und FrmFmt festellen.
+ SwPageDesc *pDesc = pPage->FindPageDesc();
+ sal_Bool bCheckEmpty = pPage->IsEmptyPage();
+ sal_Bool bActOdd = pPage->OnRightPage();
+ sal_Bool bOdd = pPage->WannaRightPage();
+ SwFrmFmt *pFmtWish = bOdd ? pDesc->GetRightFmt()
+ : pDesc->GetLeftFmt();
+
+ if ( bActOdd != bOdd ||
+ pDesc != pPage->GetPageDesc() || //falscher Desc
+ ( pFmtWish != pPage->GetFmt() && //falsches Format und
+ ( !pPage->IsEmptyPage() || pFmtWish ) //nicht Leerseite
+ )
+ )
+ {
+ //Wenn wir schon ein Seite veraendern muessen kann das eine
+ //Weile dauern, deshalb hier den WaitCrsr pruefen.
+ if( pImp )
+ pImp->CheckWaitCrsr();
+
+ //Ab hier muessen die Felder invalidiert werden!
+ if ( nDocPos == LONG_MAX )
+ nDocPos = pPage->GetPrev() ?
+ pPage->GetPrev()->Frm().Top() : pPage->Frm().Top();
+
+ //Faelle:
+ //1. Wir haben eine EmptyPage und wollen eine "Normalseite".
+ // ->EmptyPage wegwerfen und weiter mit der naechsten.
+ //2. Wir haben eine EmptyPage und wollen eine EmptyPage mit
+ // anderem Descriptor.
+ // ->Descriptor austauschen.
+ //3. Wir haben eine "Normalseite" und wollen eine EmptyPage.
+ // ->Emptypage einfuegen, nicht aber wenn die Vorseite
+ // bereits eine EmptyPage ist -> 6.
+ //4. Wir haben eine "Normalseite" und wollen eine "Normalseite"
+ // mit anderem Descriptor
+ // ->Descriptor und Format austauschen
+ //5. Wir haben eine "Normalseite" und wollen eine "Normalseite"
+ // mit anderem Format
+ // ->Format austauschen.
+ //6. Wir haben kein Wunschformat erhalten, also nehmen wir das
+ // 'andere' Format (rechts/links) des PageDesc.
+
+ if ( pPage->IsEmptyPage() && ( pFmtWish || //1.
+ ( !bOdd && !pPage->GetPrev() ) ) )
+ {
+ SwPageFrm *pTmp = (SwPageFrm*)pPage->GetNext();
+ pPage->Cut();
+ delete pPage;
+ if ( pStart == pPage )
+ pStart = pTmp;
+ pPage = pTmp;
+ continue;
+ }
+ else if ( pPage->IsEmptyPage() && !pFmtWish && //2.
+ pDesc != pPage->GetPageDesc() )
+ {
+ pPage->SetPageDesc( pDesc, 0 );
+ }
+ else if ( !pPage->IsEmptyPage() && //3.
+ bActOdd != bOdd &&
+ ( ( !pPage->GetPrev() && !bOdd ) ||
+ ( pPage->GetPrev() &&
+ !((SwPageFrm*)pPage->GetPrev())->IsEmptyPage() )
+ )
+ )
+ {
+ if ( pPage->GetPrev() )
+ pDesc = ((SwPageFrm*)pPage->GetPrev())->GetPageDesc();
+ SwPageFrm *pTmp = new SwPageFrm( pDoc->GetEmptyPageFmt(),pRoot,pDesc);
+ pTmp->Paste( pRoot, pPage );
+ pTmp->PreparePage( sal_False );
+ pPage = pTmp;
+ }
+ else if ( pPage->GetPageDesc() != pDesc ) //4.
+ {
+ SwPageDesc *pOld = pPage->GetPageDesc();
+ pPage->SetPageDesc( pDesc, pFmtWish );
+ if ( bFtns )
+ {
+ //Wenn sich bestimmte Werte der FtnInfo veraendert haben
+ //muss etwas passieren. Wir versuchen den Schaden zu
+ //begrenzen.
+ //Wenn die Seiten keinen FtnCont hat, ist zwar theoretisches
+ //ein Problem denkbar, aber das ignorieren wir mit aller Kraft.
+ //Bei Aenderungen hoffen wir mal, dass eine Invalidierung
+ //ausreicht, denn alles andere wuerde viel Kraft kosten.
+ SwFtnContFrm *pCont = pPage->FindFtnCont();
+ if ( pCont && !(pOld->GetFtnInfo() == pDesc->GetFtnInfo()) )
+ pCont->_InvalidateAll();
+ }
+ }
+ else if ( pFmtWish && pPage->GetFmt() != pFmtWish ) //5.
+ {
+ pPage->SetFrmFmt( pFmtWish );
+ }
+ else if ( !pFmtWish ) //6.
+ {
+ //Format mit verdrehter Logic besorgen.
+ pFmtWish = bOdd ? pDesc->GetLeftFmt() : pDesc->GetRightFmt();
+ if ( pPage->GetFmt() != pFmtWish )
+ pPage->SetFrmFmt( pFmtWish );
+ }
+#if OSL_DEBUG_LEVEL > 1
+ else
+ {
+ OSL_FAIL( "CheckPageDescs, missing solution" );
+ }
+#endif
+ }
+ if ( bCheckEmpty )
+ {
+ //Es kann noch sein, dass die Leerseite schlicht ueberflussig ist.
+ //Obiger Algorithmus kann dies leider nicht feststellen.
+ //Eigentlich muesste die Leerseite einfach praeventiv entfernt
+ //werden; sie wuerde ja ggf. wieder eingefuegt.
+ //Die EmptyPage ist genau dann ueberfluessig, wenn die Folgeseite
+ //auch ohne sie auskommt. Dazu muessen wir uns die Verhaeltnisse
+ //genauer ansehen. Wir bestimmen den PageDesc und die virtuelle
+ //Seitennummer manuell.
+ SwPageFrm *pPg = (SwPageFrm*)pPage->GetNext();
+ if( !pPg || pPage->OnRightPage() == pPg->WannaRightPage() )
+ {
+ //Die Folgeseite hat kein Problem ein FrmFmt zu finden oder keinen
+ //Nachfolger, also ist die Leerseite ueberfluessig.
+ SwPageFrm *pTmp = (SwPageFrm*)pPage->GetNext();
+ pPage->Cut();
+ delete pPage;
+ if ( pStart == pPage )
+ pStart = pTmp;
+ pPage = pTmp;
+ continue;
+ }
+ }
+ pPage = (SwPageFrm*)pPage->GetNext();
+ }
+
+ pRoot->SetAssertFlyPages();
+ pRoot->AssertPageFlys( pStart );
+
+ if ( bNotifyFields && (!pImp || !pImp->IsUpdateExpFlds()) )
+ {
+ SwDocPosUpdate aMsgHnt( nDocPos );
+ pDoc->UpdatePageFlds( &aMsgHnt );
+ }
+
+#if OSL_DEBUG_LEVEL > 1
+ //Ein paar Pruefungen muessen schon erlaubt sein.
+
+ //1. Keine zwei EmptyPages hintereinander.
+ //2. Alle PageDescs richtig?
+ sal_Bool bEmpty = sal_False;
+ SwPageFrm *pPg = pStart;
+ while ( pPg )
+ {
+ if ( pPg->IsEmptyPage() )
+ {
+ if ( bEmpty )
+ {
+ OSL_FAIL( "Doppelte Leerseiten." );
+ break; //Einmal reicht.
+ }
+ bEmpty = sal_True;
+ }
+ else
+ bEmpty = sal_False;
+
+//MA 21. Jun. 95: Kann zu testzwecken 'rein, ist aber bei zyklen durchaus
+//moeglich: Ein paar Seiten, auf der ersten 'erste Seite' anwenden,
+//rechte als folge der ersten, linke als folge der rechten, rechte als
+//folge der linken.
+// OSL_ENSURE( pPg->GetPageDesc() == pPg->FindPageDesc(),
+// "Seite mit falschem Descriptor." );
+
+ pPg = (SwPageFrm*)pPg->GetNext();
+ }
+#endif
+}
+
+/*************************************************************************
+|*
+|* SwFrm::InsertPage()
+|*
+|*************************************************************************/
+SwPageFrm *SwFrm::InsertPage( SwPageFrm *pPrevPage, sal_Bool bFtn )
+{
+ SwRootFrm *pRoot = (SwRootFrm*)pPrevPage->GetUpper();
+ SwPageFrm *pSibling = (SwPageFrm*)pRoot->GetLower();
+ SwPageDesc *pDesc = pSibling->GetPageDesc();
+
+ pSibling = (SwPageFrm*)pPrevPage->GetNext();
+ //Rechte (ungerade) oder linke (gerade) Seite einfuegen?
+ sal_Bool bNextOdd = !pPrevPage->OnRightPage();
+ sal_Bool bWishedOdd = bNextOdd;
+
+ //Welcher PageDesc gilt?
+ //Bei CntntFrm der aus dem Format wenn einer angegeben ist,
+ //der Follow vom bereits in der PrevPage gueltigen sonst.
+ pDesc = 0;
+ if ( IsFlowFrm() && !SwFlowFrm::CastFlowFrm( this )->IsFollow() )
+ { SwFmtPageDesc &rDesc = (SwFmtPageDesc&)GetAttrSet()->GetPageDesc();
+ pDesc = rDesc.GetPageDesc();
+ if ( rDesc.GetNumOffset() )
+ {
+ bWishedOdd = rDesc.GetNumOffset() % 2 ? sal_True : sal_False;
+ //Die Gelegenheit nutzen wir um das Flag an der Root zu pflegen.
+ pRoot->SetVirtPageNum( sal_True );
+ }
+ }
+ if ( !pDesc )
+ pDesc = pPrevPage->GetPageDesc()->GetFollow();
+
+ OSL_ENSURE( pDesc, "Missing PageDesc" );
+ if( !(bWishedOdd ? pDesc->GetRightFmt() : pDesc->GetLeftFmt()) )
+ bWishedOdd = !bWishedOdd;
+
+ SwDoc *pDoc = pPrevPage->GetFmt()->GetDoc();
+ SwFrmFmt *pFmt;
+ sal_Bool bCheckPages = sal_False;
+ //Wenn ich kein FrmFmt fuer die Seite gefunden habe, muss ich eben eine
+ //Leerseite einfuegen.
+ if( bWishedOdd != bNextOdd )
+ { pFmt = pDoc->GetEmptyPageFmt();
+ SwPageDesc *pTmpDesc = pPrevPage->GetPageDesc();
+ SwPageFrm *pPage = new SwPageFrm( pFmt, pRoot, pTmpDesc );
+ pPage->Paste( pRoot, pSibling );
+ pPage->PreparePage( bFtn );
+ //Wenn der Sibling keinen Bodytext enthaelt kann ich ihn vernichten
+ //Es sei denn, es ist eine Fussnotenseite
+ if ( pSibling && !pSibling->IsFtnPage() &&
+ !pSibling->FindFirstBodyCntnt() )
+ {
+ SwPageFrm *pDel = pSibling;
+ pSibling = (SwPageFrm*)pSibling->GetNext();
+ if ( pDoc->GetFtnIdxs().Count() )
+ pRoot->RemoveFtns( pDel, sal_True );
+ pDel->Cut();
+ delete pDel;
+ }
+ else
+ bCheckPages = sal_True;
+ }
+ pFmt = bWishedOdd ? pDesc->GetRightFmt() : pDesc->GetLeftFmt();
+ OSL_ENSURE( pFmt, "Descriptor without format." );
+ SwPageFrm *pPage = new SwPageFrm( pFmt, pRoot, pDesc );
+ pPage->Paste( pRoot, pSibling );
+ pPage->PreparePage( bFtn );
+ //Wenn der Sibling keinen Bodytext enthaelt kann ich ihn vernichten
+ //Es sei denn es ist eine Fussnotenseite.
+ if ( pSibling && !pSibling->IsFtnPage() &&
+ !pSibling->FindFirstBodyCntnt() )
+ {
+ SwPageFrm *pDel = pSibling;
+ pSibling = (SwPageFrm*)pSibling->GetNext();
+ if ( pDoc->GetFtnIdxs().Count() )
+ pRoot->RemoveFtns( pDel, sal_True );
+ pDel->Cut();
+ delete pDel;
+ }
+ else
+ bCheckPages = sal_True;
+
+ if ( pSibling )
+ {
+ if ( bCheckPages )
+ {
+ CheckPageDescs( pSibling, sal_False );
+ ViewShell *pSh = getRootFrm()->GetCurrShell();
+ SwViewImp *pImp = pSh ? pSh->Imp() : 0;
+ if ( pImp && pImp->IsAction() && !pImp->GetLayAction().IsCheckPages() )
+ {
+ const sal_uInt16 nNum = pImp->GetLayAction().GetCheckPageNum();
+ if ( nNum == pPrevPage->GetPhyPageNum() + 1 )
+ pImp->GetLayAction().SetCheckPageNumDirect(
+ pSibling->GetPhyPageNum() );
+ return pPage;
+ }
+ }
+ else
+ pRoot->AssertPageFlys( pSibling );
+ }
+
+ //Fuer das Aktualisieren der Seitennummern-Felder gibt nDocPos
+ //die Seitenposition an, _ab_ der invalidiert werden soll.
+ ViewShell *pSh = getRootFrm()->GetCurrShell();
+ if ( !pSh || !pSh->Imp()->IsUpdateExpFlds() )
+ {
+ SwDocPosUpdate aMsgHnt( pPrevPage->Frm().Top() );
+ pDoc->UpdatePageFlds( &aMsgHnt );
+ }
+ return pPage;
+}
+
+sw::sidebarwindows::SidebarPosition SwPageFrm::SidebarPosition() const
+{
+ ViewShell *pSh = getRootFrm()->GetCurrShell();
+ if( !pSh || pSh->GetViewOptions()->getBrowseMode() )
+ {
+ return sw::sidebarwindows::SIDEBAR_RIGHT;
+ }
+ else
+ {
+ const bool bLTR = getRootFrm()->IsLeftToRightViewLayout();
+ const bool bBookMode = pSh->GetViewOptions()->IsViewLayoutBookMode();
+ const bool bRightSidebar = bLTR ? (!bBookMode || OnRightPage()) : (bBookMode && !OnRightPage());
+
+ return bRightSidebar
+ ? sw::sidebarwindows::SIDEBAR_RIGHT
+ : sw::sidebarwindows::SIDEBAR_LEFT;
+ }
+}
+
+/*************************************************************************
+|*
+|* SwRootFrm::GrowFrm()
+|*
+|*************************************************************************/
+
+SwTwips SwRootFrm::GrowFrm( SwTwips nDist, sal_Bool bTst, sal_Bool )
+{
+ if ( !bTst )
+ Frm().SSize().Height() += nDist;
+ return nDist;
+}
+/*************************************************************************
+|*
+|* SwRootFrm::ShrinkFrm()
+|*
+|*************************************************************************/
+SwTwips SwRootFrm::ShrinkFrm( SwTwips nDist, sal_Bool bTst, sal_Bool )
+{
+ OSL_ENSURE( nDist >= 0, "nDist < 0." );
+ OSL_ENSURE( nDist <= Frm().Height(), "nDist > als aktuelle Groesse." );
+
+ if ( !bTst )
+ Frm().SSize().Height() -= nDist;
+ return nDist;
+}
+
+/*************************************************************************
+|*
+|* SwRootFrm::RemoveSuperfluous()
+|*
+|* Beschreibung: Entfernung von ueberfluessigen Seiten.
+|* Arbeitet nur wenn das Flag bCheckSuperfluous gesetzt ist.
+|* Definition: Eine Seite ist genau dann leer, wenn der
+|* Body-Textbereich keinen CntntFrm enthaelt, aber nicht, wenn noch
+|* mindestens ein Fly an der Seite klebt.
+|* Die Seite ist auch dann nicht leer, wenn sie noch eine
+|* Fussnote enthaelt.
+|* Es muss zweimal angesetzt werden um leeren Seiten aufzuspueren:
+|* - einmal fuer die Endnotenseiten.
+|* - und einmal fuer die Seiten des Bodytextes.
+|*
+|*************************************************************************/
+void SwRootFrm::RemoveSuperfluous()
+{
+ if ( !IsSuperfluous() )
+ return;
+ bCheckSuperfluous = sal_False;
+
+ SwPageFrm *pPage = GetLastPage();
+ long nDocPos = LONG_MAX;
+
+ //Jetzt wird fuer die jeweils letzte Seite geprueft ob sie leer ist
+ //bei der ersten nicht leeren Seite wird die Schleife beendet.
+ do
+ {
+ bool bExistEssentialObjs = ( 0 != pPage->GetSortedObjs() );
+ if ( bExistEssentialObjs )
+ {
+ //Nur weil die Seite Flys hat sind wir noch lange nicht fertig,
+ //denn wenn alle Flys an generischem Inhalt haengen, so ist sie
+ //trotzdem ueberfluessig (Ueberpruefung auf DocBody sollte reichen).
+ // OD 19.06.2003 #108784# - consider that drawing objects in
+ // header/footer are supported now.
+ bool bOnlySuperfluosObjs = true;
+ SwSortedObjs &rObjs = *pPage->GetSortedObjs();
+ for ( sal_uInt16 i = 0; bOnlySuperfluosObjs && i < rObjs.Count(); ++i )
+ {
+ // --> OD 2004-06-29 #i28701#
+ SwAnchoredObject* pAnchoredObj = rObjs[i];
+ // OD 2004-01-19 #110582# - do not consider hidden objects
+ if ( pPage->GetFmt()->GetDoc()->IsVisibleLayerId(
+ pAnchoredObj->GetDrawObj()->GetLayer() ) &&
+ !pAnchoredObj->GetAnchorFrm()->FindFooterOrHeader() )
+ {
+ bOnlySuperfluosObjs = false;
+ }
+ // <--
+ }
+ bExistEssentialObjs = !bOnlySuperfluosObjs;
+ }
+
+ // OD 19.06.2003 #108784# - optimization: check first, if essential objects
+ // exists.
+ const SwLayoutFrm* pBody = 0;
+ if ( bExistEssentialObjs ||
+ pPage->FindFtnCont() ||
+ ( 0 != ( pBody = pPage->FindBodyCont() ) &&
+ ( pBody->ContainsCntnt() ||
+ // --> FME 2005-05-18 #i47580#
+ // Do not delete page if there's an empty tabframe
+ // left. I think it might be correct to use ContainsAny()
+ // instead of ContainsCntnt() to cover the empty-table-case,
+ // but I'm not fully sure, since ContainsAny() also returns
+ // SectionFrames. Therefore I prefer to do it the safe way:
+ ( pBody->Lower() && pBody->Lower()->IsTabFrm() ) ) ) )
+ // <--
+ {
+ if ( pPage->IsFtnPage() )
+ {
+ while ( pPage->IsFtnPage() )
+ {
+ pPage = (SwPageFrm*)pPage->GetPrev();
+ OSL_ENSURE( pPage, "Nur noch Endnotenseiten uebrig." );
+ }
+ continue;
+ }
+ else
+ pPage = 0;
+ }
+
+ if ( pPage )
+ {
+ SwPageFrm *pEmpty = pPage;
+ pPage = (SwPageFrm*)pPage->GetPrev();
+ if ( GetFmt()->GetDoc()->GetFtnIdxs().Count() )
+ RemoveFtns( pEmpty, sal_True );
+ pEmpty->Cut();
+ delete pEmpty;
+ nDocPos = pPage ? pPage->Frm().Top() : 0;
+ }
+ } while ( pPage );
+
+ ViewShell *pSh = getRootFrm()->GetCurrShell();
+ if ( nDocPos != LONG_MAX &&
+ (!pSh || !pSh->Imp()->IsUpdateExpFlds()) )
+ {
+ SwDocPosUpdate aMsgHnt( nDocPos );
+ GetFmt()->GetDoc()->UpdatePageFlds( &aMsgHnt );
+ }
+}
+
+/*************************************************************************
+|*
+|* SwRootFrm::AssertFlyPages()
+|*
+|* Beschreibung Stellt sicher, dass genuegend Seiten vorhanden
+|* sind, damit alle Seitengebundenen Rahmen und DrawObject
+|* untergebracht sind.
+|*
+|*************************************************************************/
+void SwRootFrm::AssertFlyPages()
+{
+ if ( !IsAssertFlyPages() )
+ return;
+ bAssertFlyPages = sal_False;
+
+ SwDoc *pDoc = GetFmt()->GetDoc();
+ const SwSpzFrmFmts *pTbl = pDoc->GetSpzFrmFmts();
+
+ //Auf welche Seite will der 'letzte' Fly?
+ sal_uInt16 nMaxPg = 0;
+ sal_uInt16 i;
+
+ for ( i = 0; i < pTbl->Count(); ++i )
+ {
+ const SwFmtAnchor &rAnch = (*pTbl)[i]->GetAnchor();
+ if ( !rAnch.GetCntntAnchor() && nMaxPg < rAnch.GetPageNum() )
+ nMaxPg = rAnch.GetPageNum();
+ }
+ //Wieviele Seiten haben wir derzeit?
+ SwPageFrm *pPage = (SwPageFrm*)Lower();
+ while ( pPage && pPage->GetNext() &&
+ !((SwPageFrm*)pPage->GetNext())->IsFtnPage() )
+ {
+ pPage = (SwPageFrm*)pPage->GetNext();
+ }
+
+ if ( nMaxPg > pPage->GetPhyPageNum() )
+ {
+ //Die Seiten werden ausgehend von der letzten Seite konsequent
+ //nach den Regeln der PageDescs weitergefuehrt.
+ sal_Bool bOdd = pPage->GetPhyPageNum() % 2 ? sal_True : sal_False;
+ SwPageDesc *pDesc = pPage->GetPageDesc();
+ SwFrm *pSibling = pPage->GetNext();
+ for ( i = pPage->GetPhyPageNum(); i < nMaxPg; ++i )
+ {
+ if ( !(bOdd ? pDesc->GetRightFmt() : pDesc->GetLeftFmt()) )
+ {
+ //Leerseite einfuegen, die Flys werden aber erst von
+ //der naechsten Seite aufgenommen!
+ pPage = new SwPageFrm( pDoc->GetEmptyPageFmt(), this, pDesc );
+ pPage->Paste( this, pSibling );
+ pPage->PreparePage( sal_False );
+ bOdd = bOdd ? sal_False : sal_True;
+ ++i;
+ }
+ pPage = new
+ SwPageFrm( (bOdd ? pDesc->GetRightFmt() :
+ pDesc->GetLeftFmt()), this, pDesc );
+ pPage->Paste( this, pSibling );
+ pPage->PreparePage( sal_False );
+ bOdd = bOdd ? sal_False : sal_True;
+ pDesc = pDesc->GetFollow();
+ }
+ //Jetzt koennen die Endnotenseiten natuerlich wieder krumm sein;
+ //in diesem Fall werden sie vernichtet.
+ if ( pDoc->GetFtnIdxs().Count() )
+ {
+ pPage = (SwPageFrm*)Lower();
+ while ( pPage && !pPage->IsFtnPage() )
+ pPage = (SwPageFrm*)pPage->GetNext();
+
+ if ( pPage )
+ {
+ SwPageDesc *pTmpDesc = pPage->FindPageDesc();
+ bOdd = pPage->OnRightPage();
+ if ( pPage->GetFmt() !=
+ (bOdd ? pTmpDesc->GetRightFmt() : pTmpDesc->GetLeftFmt()) )
+ RemoveFtns( pPage, sal_False, sal_True );
+ }
+ }
+ }
+}
+
+/*************************************************************************
+|*
+|* SwRootFrm::AssertPageFlys()
+|*
+|* Beschreibung Stellt sicher, dass ab der uebergebenen Seite
+|* auf allen Seiten die Seitengebunden Objecte auf der richtigen
+|* Seite (Seitennummer stehen).
+|*
+|*************************************************************************/
+void SwRootFrm::AssertPageFlys( SwPageFrm *pPage )
+{
+ while ( pPage )
+ {
+ if ( pPage->GetSortedObjs() )
+ {
+ pPage->GetSortedObjs();
+ for ( int i = 0;
+ pPage->GetSortedObjs() && sal_uInt16(i) < pPage->GetSortedObjs()->Count();
+ ++i)
+ {
+ // --> OD 2004-06-29 #i28701#
+ SwFrmFmt& rFmt = (*pPage->GetSortedObjs())[i]->GetFrmFmt();
+ const SwFmtAnchor &rAnch = rFmt.GetAnchor();
+ const sal_uInt16 nPg = rAnch.GetPageNum();
+ if ((rAnch.GetAnchorId() == FLY_AT_PAGE) &&
+ nPg != pPage->GetPhyPageNum() )
+ {
+ //Das er auf der falschen Seite steht muss noch nichts
+ //heissen, wenn er eigentlich auf der Vorseite
+ //stehen will und diese eine EmptyPage ist.
+ if( nPg && !(pPage->GetPhyPageNum()-1 == nPg &&
+ ((SwPageFrm*)pPage->GetPrev())->IsEmptyPage()) )
+ {
+ //Umhaengen kann er sich selbst, indem wir ihm
+ //einfach ein Modify mit seinem AnkerAttr schicken.
+#if OSL_DEBUG_LEVEL > 1
+ const sal_uInt32 nCnt = pPage->GetSortedObjs()->Count();
+ rFmt.NotifyClients( 0, (SwFmtAnchor*)&rAnch );
+ OSL_ENSURE( !pPage->GetSortedObjs() ||
+ nCnt != pPage->GetSortedObjs()->Count(),
+ "Object couldn't be reattached!" );
+#else
+ rFmt.NotifyClients( 0, (SwFmtAnchor*)&rAnch );
+#endif
+ --i;
+ }
+ }
+ }
+ }
+ pPage = (SwPageFrm*)pPage->GetNext();
+ }
+}
+
+/*************************************************************************
+|*
+|* SwRootFrm::ChgSize()
+|*
+|*************************************************************************/
+Size SwRootFrm::ChgSize( const Size& aNewSize )
+{
+ Frm().SSize() = aNewSize;
+ _InvalidatePrt();
+ bFixSize = sal_False;
+ return Frm().SSize();
+}
+
+/*************************************************************************
+|*
+|* SwRootFrm::MakeAll()
+|*
+|*************************************************************************/
+void SwRootFrm::MakeAll()
+{
+ if ( !bValidPos )
+ { bValidPos = sal_True;
+ aFrm.Pos().X() = aFrm.Pos().Y() = DOCUMENTBORDER;
+ }
+ if ( !bValidPrtArea )
+ { bValidPrtArea = sal_True;
+ aPrt.Pos().X() = aPrt.Pos().Y() = 0;
+ aPrt.SSize( aFrm.SSize() );
+ }
+ if ( !bValidSize )
+ //SSize wird von den Seiten (Cut/Paste) eingestellt.
+ bValidSize = sal_True;
+}
+
+/*************************************************************************
+|*
+|* SwRootFrm::ImplInvalidateBrowseWidth()
+|*
+|*************************************************************************/
+void SwRootFrm::ImplInvalidateBrowseWidth()
+{
+ bBrowseWidthValid = sal_False;
+ SwFrm *pPg = Lower();
+ while ( pPg )
+ {
+ pPg->InvalidateSize();
+ pPg = pPg->GetNext();
+ }
+}
+
+/*************************************************************************
+|*
+|* SwRootFrm::ImplCalcBrowseWidth()
+|*
+|*************************************************************************/
+void SwRootFrm::ImplCalcBrowseWidth()
+{
+ OSL_ENSURE( GetCurrShell() && GetCurrShell()->GetViewOptions()->getBrowseMode(),
+ "CalcBrowseWidth and not in BrowseView" );
+
+ //Die (minimale) Breite wird von Rahmen, Tabellen und Zeichenobjekten
+ //bestimmt. Die Breite wird nicht anhand ihrer aktuellen Groessen bestimmt,
+ //sondern anhand der Attribute. Es interessiert also nicht wie breit sie
+ //sind, sondern wie breit sie sein wollen.
+ //Rahmen und Zeichenobjekte innerhalb ander Objekte (Rahmen, Tabellen)
+ //Zaehlen nicht.
+ //Seitenraender und Spalten werden hier nicht beruecksichtigt.
+
+ SwFrm *pFrm = ContainsCntnt();
+ while ( pFrm && !pFrm->IsInDocBody() )
+ pFrm = ((SwCntntFrm*)pFrm)->GetNextCntntFrm();
+ if ( !pFrm )
+ return;
+
+ bBrowseWidthValid = sal_True;
+ ViewShell *pSh = getRootFrm()->GetCurrShell();
+ nBrowseWidth = pSh
+ ? MINLAY + 2 * pSh->GetOut()->
+ PixelToLogic( pSh->GetBrowseBorder() ).Width()
+ : 5000;
+ do
+ {
+ if ( pFrm->IsInTab() )
+ pFrm = pFrm->FindTabFrm();
+
+ if ( pFrm->IsTabFrm() &&
+ !((SwLayoutFrm*)pFrm)->GetFmt()->GetFrmSize().GetWidthPercent() )
+ {
+ SwBorderAttrAccess aAccess( SwFrm::GetCache(), pFrm );
+ const SwBorderAttrs &rAttrs = *aAccess.Get();
+ const SwFmtHoriOrient &rHori = rAttrs.GetAttrSet().GetHoriOrient();
+ long nWidth = rAttrs.GetSize().Width();
+ if ( nWidth < USHRT_MAX-2000 && //-2000, weil bei Randeinstellung per
+ //Zuppeln das USHRT_MAX verlorengeht!
+ text::HoriOrientation::FULL != rHori.GetHoriOrient() )
+ {
+ const SwHTMLTableLayout *pLayoutInfo =
+ ((const SwTabFrm *)pFrm)->GetTable()
+ ->GetHTMLTableLayout();
+ if ( pLayoutInfo )
+ nWidth = Min( nWidth, pLayoutInfo->GetBrowseWidthMin() );
+
+ switch ( rHori.GetHoriOrient() )
+ {
+ case text::HoriOrientation::NONE:
+ // OD 23.01.2003 #106895# - add 1st param to <SwBorderAttrs::CalcRight(..)>
+ nWidth += rAttrs.CalcLeft( pFrm ) + rAttrs.CalcRight( pFrm );
+ break;
+ case text::HoriOrientation::LEFT_AND_WIDTH:
+ nWidth += rAttrs.CalcLeft( pFrm );
+ break;
+ default:
+ break;
+
+ }
+ nBrowseWidth = Max( nBrowseWidth, nWidth );
+ }
+ }
+ else if ( pFrm->GetDrawObjs() )
+ {
+ for ( sal_uInt16 i = 0; i < pFrm->GetDrawObjs()->Count(); ++i )
+ {
+ // --> OD 2004-06-29 #i28701#
+ SwAnchoredObject* pAnchoredObj = (*pFrm->GetDrawObjs())[i];
+ const SwFrmFmt& rFmt = pAnchoredObj->GetFrmFmt();
+ const sal_Bool bFly = pAnchoredObj->ISA(SwFlyFrm);
+ if ((bFly && (WEIT_WECH == pAnchoredObj->GetObjRect().Width()))
+ || rFmt.GetFrmSize().GetWidthPercent())
+ {
+ continue;
+ }
+
+ long nWidth = 0;
+ switch ( rFmt.GetAnchor().GetAnchorId() )
+ {
+ case FLY_AS_CHAR:
+ nWidth = bFly ? rFmt.GetFrmSize().GetWidth() :
+ pAnchoredObj->GetObjRect().Width();
+ break;
+ case FLY_AT_PARA:
+ {
+ // --> FME 2004-09-13 #i33170#
+ // Reactivated old code because
+ // nWidth = pAnchoredObj->GetObjRect().Right()
+ // gives wrong results for objects that are still
+ // at position WEIT_WECH.
+ if ( bFly )
+ {
+ nWidth = rFmt.GetFrmSize().GetWidth();
+ const SwFmtHoriOrient &rHori = rFmt.GetHoriOrient();
+ switch ( rHori.GetHoriOrient() )
+ {
+ case text::HoriOrientation::NONE:
+ nWidth += rHori.GetPos();
+ break;
+ case text::HoriOrientation::INSIDE:
+ case text::HoriOrientation::LEFT:
+ if ( text::RelOrientation::PRINT_AREA == rHori.GetRelationOrient() )
+ nWidth += pFrm->Prt().Left();
+ break;
+ default:
+ break;
+ }
+ }
+ else
+ //Fuer Zeichenobjekte ist die Auswahl sehr klein,
+ //weil sie keine Attribute haben, also durch ihre
+ //aktuelle Groesse bestimmt werden.
+ nWidth = pAnchoredObj->GetObjRect().Right() -
+ pAnchoredObj->GetDrawObj()->GetAnchorPos().X();
+ // <--
+ }
+ break;
+ default: /* do nothing */;
+ }
+ nBrowseWidth = Max( nBrowseWidth, nWidth );
+ }
+ }
+ pFrm = pFrm->FindNextCnt();
+ } while ( pFrm );
+}
+
+/*************************************************************************
+|*
+|* SwRootFrm::StartAllAction()
+|*
+|*************************************************************************/
+
+void SwRootFrm::StartAllAction()
+{
+ ViewShell *pSh = GetCurrShell();
+ if ( pSh )
+ do
+ { if ( pSh->ISA( SwCrsrShell ) )
+ ((SwCrsrShell*)pSh)->StartAction();
+ else
+ pSh->StartAction();
+ pSh = (ViewShell*)pSh->GetNext();
+
+ } while ( pSh != GetCurrShell() );
+}
+
+void SwRootFrm::EndAllAction( sal_Bool bVirDev )
+{
+ ViewShell *pSh = GetCurrShell();
+ if ( pSh )
+ do
+ {
+ const sal_Bool bOldEndActionByVirDev = pSh->IsEndActionByVirDev();
+ pSh->SetEndActionByVirDev( bVirDev );
+ if ( pSh->ISA( SwCrsrShell ) )
+ {
+ ((SwCrsrShell*)pSh)->EndAction();
+ ((SwCrsrShell*)pSh)->CallChgLnk();
+ if ( pSh->ISA( SwFEShell ) )
+ ((SwFEShell*)pSh)->SetChainMarker();
+ }
+ else
+ pSh->EndAction();
+ pSh->SetEndActionByVirDev( bOldEndActionByVirDev );
+ pSh = (ViewShell*)pSh->GetNext();
+
+ } while ( pSh != GetCurrShell() );
+}
+
+void SwRootFrm::UnoRemoveAllActions()
+{
+ ViewShell *pSh = GetCurrShell();
+ if ( pSh )
+ do
+ {
+ // --> OD 2008-05-16 #i84729#
+ // No end action, if <ViewShell> instance is currently in its end action.
+ // Recursives calls to <::EndAction()> are not allowed.
+ if ( !pSh->IsInEndAction() )
+ {
+ DBG_ASSERT(!pSh->GetRestoreActions(), "Restore action count is already set!");
+ sal_Bool bCrsr = pSh->ISA( SwCrsrShell );
+ sal_Bool bFE = pSh->ISA( SwFEShell );
+ sal_uInt16 nRestore = 0;
+ while( pSh->ActionCount() )
+ {
+ if( bCrsr )
+ {
+ ((SwCrsrShell*)pSh)->EndAction();
+ ((SwCrsrShell*)pSh)->CallChgLnk();
+ if ( bFE )
+ ((SwFEShell*)pSh)->SetChainMarker();
+ }
+ else
+ pSh->EndAction();
+ nRestore++;
+ }
+ pSh->SetRestoreActions(nRestore);
+ }
+ // <--
+ pSh->LockView(sal_True);
+ pSh = (ViewShell*)pSh->GetNext();
+
+ } while ( pSh != GetCurrShell() );
+}
+
+void SwRootFrm::UnoRestoreAllActions()
+{
+ ViewShell *pSh = GetCurrShell();
+ if ( pSh )
+ do
+ {
+ sal_uInt16 nActions = pSh->GetRestoreActions();
+ while( nActions-- )
+ {
+ if ( pSh->ISA( SwCrsrShell ) )
+ ((SwCrsrShell*)pSh)->StartAction();
+ else
+ pSh->StartAction();
+ }
+ pSh->SetRestoreActions(0);
+ pSh->LockView(sal_False);
+ pSh = (ViewShell*)pSh->GetNext();
+
+ } while ( pSh != GetCurrShell() );
+}
+
+// PAGES01: Helper functions for SwRootFrm::CheckViewLayout
+void lcl_MoveAllLowers( SwFrm* pFrm, const Point& rOffset );
+
+void lcl_MoveAllLowerObjs( SwFrm* pFrm, const Point& rOffset )
+{
+ SwSortedObjs* pSortedObj = 0;
+ const bool bPage = pFrm->IsPageFrm();
+
+ if ( bPage )
+ pSortedObj = static_cast<SwPageFrm*>(pFrm)->GetSortedObjs();
+ else
+ pSortedObj = pFrm->GetDrawObjs();
+
+ for ( sal_uInt16 i = 0; pSortedObj && i < pSortedObj->Count(); ++i)
+ {
+ SwAnchoredObject* pAnchoredObj = (*pSortedObj)[i];
+
+ const SwFrmFmt& rObjFmt = pAnchoredObj->GetFrmFmt();
+ const SwFmtAnchor& rAnchor = rObjFmt.GetAnchor();
+
+ // all except from the as character anchored objects are moved
+ // when processing the page frame:
+ const bool bAsChar = (rAnchor.GetAnchorId() == FLY_AS_CHAR);
+ if ( !bPage && !bAsChar )
+ continue;
+
+ SwObjPositioningInProgress aPosInProgress( *pAnchoredObj );
+
+ if ( pAnchoredObj->ISA(SwFlyFrm) )
+ {
+ SwFlyFrm* pFlyFrm( static_cast<SwFlyFrm*>(pAnchoredObj) );
+ lcl_MoveAllLowers( pFlyFrm, rOffset );
+ pFlyFrm->NotifyDrawObj();
+ // --> let the active embedded object be moved
+ if ( pFlyFrm->Lower() )
+ {
+ if ( pFlyFrm->Lower()->IsNoTxtFrm() )
+ {
+ SwCntntFrm* pCntntFrm = static_cast<SwCntntFrm*>(pFlyFrm->Lower());
+ SwRootFrm* pRoot = pFlyFrm->Lower()->getRootFrm();
+ ViewShell *pSh = pRoot ? pRoot->GetCurrShell() : 0;
+ if ( pSh )
+ {
+ SwOLENode* pNode = pCntntFrm->GetNode()->GetOLENode();
+ if ( pNode )
+ {
+ svt::EmbeddedObjectRef& xObj = pNode->GetOLEObj().GetObject();
+ if ( xObj.is() )
+ {
+ ViewShell* pTmp = pSh;
+ do
+ {
+ SwFEShell* pFEShell = dynamic_cast< SwFEShell* >( pTmp );
+ if ( pFEShell )
+ pFEShell->MoveObjectIfActive( xObj, rOffset );
+ pTmp = static_cast<ViewShell*>( pTmp->GetNext() );
+ } while( pTmp != pSh );
+ }
+ }
+ }
+ }
+ }
+ // <--
+ }
+ else if ( pAnchoredObj->ISA(SwAnchoredDrawObject) )
+ {
+ SwAnchoredDrawObject* pAnchoredDrawObj( static_cast<SwAnchoredDrawObject*>(pAnchoredObj) );
+
+ // don't touch objects that are not yet positioned:
+ const bool bNotYetPositioned = pAnchoredDrawObj->NotYetPositioned();
+ if ( bNotYetPositioned )
+ continue;
+
+ const Point aCurrAnchorPos = pAnchoredDrawObj->GetDrawObj()->GetAnchorPos();
+ const Point aNewAnchorPos( ( aCurrAnchorPos + rOffset ) );
+ pAnchoredDrawObj->DrawObj()->SetAnchorPos( aNewAnchorPos );
+ pAnchoredDrawObj->SetLastObjRect( pAnchoredDrawObj->GetObjRect().SVRect() );
+ }
+ // --> OD 2009-08-20 #i92511#
+ // cache for object rectangle inclusive spaces has to be invalidated.
+ pAnchoredObj->InvalidateObjRectWithSpaces();
+ // <--
+ }
+}
+
+void lcl_MoveAllLowers( SwFrm* pFrm, const Point& rOffset )
+{
+ const SwRect aFrm( pFrm->Frm() );
+
+ // first move the current frame
+ pFrm->Frm().Pos() += rOffset;
+
+ // Don't forget accessibility:
+ if( pFrm->IsAccessibleFrm() )
+ {
+ SwRootFrm *pRootFrm = pFrm->getRootFrm();
+ if( pRootFrm && pRootFrm->IsAnyShellAccessible() &&
+ pRootFrm->GetCurrShell() )
+ {
+ pRootFrm->GetCurrShell()->Imp()->MoveAccessibleFrm( pFrm, aFrm );
+ }
+ }
+
+ // the move any objects
+ lcl_MoveAllLowerObjs( pFrm, rOffset );
+
+ // finally, for layout frames we have to call this function recursively:
+ if ( pFrm->ISA(SwLayoutFrm) )
+ {
+ SwFrm* pLowerFrm = pFrm->GetLower();
+ while ( pLowerFrm )
+ {
+ lcl_MoveAllLowers( pLowerFrm, rOffset );
+ pLowerFrm = pLowerFrm->GetNext();
+ }
+ }
+}
+
+// PAGES01: Calculate how the pages have to be positioned
+void SwRootFrm::CheckViewLayout( const SwViewOption* pViewOpt, const SwRect* pVisArea )
+{
+ // --> OD 2008-07-07 #i91432#
+ // No calculation of page positions, if only an empty page is present.
+ // This situation occurs when <SwRootFrm> instance is in construction
+ // and the document contains only left pages.
+ if ( Lower()->GetNext() == 0 &&
+ static_cast<SwPageFrm*>(Lower())->IsEmptyPage() )
+ {
+ return;
+ }
+ // <--
+
+ if ( !pVisArea )
+ {
+ // no early return for bNewPage
+ if ( mnViewWidth < 0 )
+ mnViewWidth = 0;
+ }
+ else
+ {
+ OSL_ENSURE( pViewOpt, "CheckViewLayout required ViewOptions" );
+
+ const sal_uInt16 nColumns = pViewOpt->GetViewLayoutColumns();
+ const bool bBookMode = pViewOpt->IsViewLayoutBookMode();
+
+ if ( nColumns == mnColumns && bBookMode == mbBookMode && pVisArea->Width() == mnViewWidth && !mbSidebarChanged )
+ return;
+
+ mnColumns = nColumns;
+ mbBookMode = bBookMode;
+ mnViewWidth = pVisArea->Width();
+ mbSidebarChanged = false;
+ }
+
+ if( GetFmt()->getIDocumentSettingAccess()->get(IDocumentSettingAccess::BROWSE_MODE ) )
+ {
+ mnColumns = 1;
+ mbBookMode = false;
+ }
+
+ Calc();
+
+ const sal_Bool bOldCallbackActionEnabled = IsCallbackActionEnabled();
+ SetCallbackActionEnabled( sal_False );
+
+ maPageRects.clear();
+
+ const long nBorder = Frm().Pos().X();
+ const long nVisWidth = mnViewWidth - 2 * nBorder;
+ const long nGapBetweenPages = GAPBETWEENPAGES;
+
+ // check how many pages fit into the first page layout row:
+ SwPageFrm* pPageFrm = static_cast<SwPageFrm*>(Lower());
+
+ // will contain the number of pages per row. 0 means that
+ // the page does not fit.
+ long nWidthRemain = nVisWidth;
+
+ // after one row has been processed, these variables contain
+ // the width of the row and the maxium of the page heights
+ long nCurrentRowHeight = 0;
+ long nCurrentRowWidth = 0;
+
+ // these variables are used to finally set the size of the
+ // root frame
+ long nSumRowHeight = 0;
+ SwTwips nMinPageLeft = TWIPS_MAX;
+ SwTwips nMaxPageRight = 0;
+ SwPageFrm* pStartOfRow = pPageFrm;
+ sal_uInt16 nNumberOfPagesInRow = mbBookMode ? 1 : 0; // in book view, start with right page
+ bool bFirstRow = true;
+
+ bool bPageChanged = false;
+ const bool bRTL = !IsLeftToRightViewLayout();
+ const SwTwips nSidebarWidth = SwPageFrm::GetSidebarBorderWidth( GetCurrShell() );
+
+ while ( pPageFrm )
+ {
+ // we consider the current page to be "start of row" if
+ // 1. it is the first page in the current row or
+ // 2. it is the second page in the row and the first page is an empty page in non-book view:
+ const bool bStartOfRow = pPageFrm == pStartOfRow ||
+ ( pStartOfRow->IsEmptyPage() && pPageFrm == pStartOfRow->GetNext() && !mbBookMode );
+
+ const bool bEmptyPage = pPageFrm->IsEmptyPage() && !mbBookMode;
+
+ // no half doc border space for first page in each row and
+ long nPageWidth = 0;
+ long nPageHeight = 0;
+
+ if ( mbBookMode )
+ {
+ const SwFrm& rFormatPage = pPageFrm->GetFormatPage();
+
+ nPageWidth = rFormatPage.Frm().Width() + nSidebarWidth + ((bStartOfRow || 1 == (pPageFrm->GetPhyPageNum()%2)) ? 0 : nGapBetweenPages);
+ nPageHeight = rFormatPage.Frm().Height() + nGapBetweenPages;
+ }
+ else
+ {
+ SwRect aPageFrm;
+ if ( !pPageFrm->IsEmptyPage() )
+ {
+ nPageWidth = pPageFrm->Frm().Width() + nSidebarWidth + (bStartOfRow ? 0 : nGapBetweenPages);
+ nPageHeight = pPageFrm->Frm().Height() + nGapBetweenPages;
+ }
+ }
+
+ if ( !bEmptyPage )
+ ++nNumberOfPagesInRow;
+
+ // finish current row if
+ // 1. in dynamic mode the current page does not fit anymore or
+ // 2. the current page exceeds the maximum number of columns
+ bool bRowFinished = (0 == mnColumns && nWidthRemain < nPageWidth ) ||
+ (0 != mnColumns && mnColumns < nNumberOfPagesInRow);
+
+ // make sure that at least one page goes to the current row:
+ if ( !bRowFinished || bStartOfRow )
+ {
+ // current page is allowed to be in current row
+ nWidthRemain = nWidthRemain - nPageWidth;
+
+ nCurrentRowWidth = nCurrentRowWidth + nPageWidth;
+ nCurrentRowHeight = Max( nCurrentRowHeight, nPageHeight );
+
+ pPageFrm = static_cast<SwPageFrm*>(pPageFrm->GetNext());
+
+ if ( !pPageFrm )
+ bRowFinished = true;
+ }
+
+ if ( bRowFinished )
+ {
+ // pPageFrm now points to the first page in the new row or null
+ // pStartOfRow points to the first page in the current row
+
+ // special centering for last row. pretend to fill the last row with virtual copies of the last page before centering:
+ if ( !pPageFrm && nWidthRemain > 0 )
+ {
+ // find last page in current row:
+ const SwPageFrm* pLastPageInCurrentRow = pStartOfRow;
+ while( pLastPageInCurrentRow->GetNext() )
+ pLastPageInCurrentRow = static_cast<const SwPageFrm*>(pLastPageInCurrentRow->GetNext());
+
+ if ( pLastPageInCurrentRow->IsEmptyPage() )
+ pLastPageInCurrentRow = static_cast<const SwPageFrm*>(pLastPageInCurrentRow->GetPrev());
+
+ // check how many times the last page would still fit into the remaining space:
+ sal_uInt16 nNumberOfVirtualPages = 0;
+ const sal_uInt16 nMaxNumberOfVirtualPages = mnColumns > 0 ? mnColumns - nNumberOfPagesInRow : USHRT_MAX;
+ SwTwips nRemain = nWidthRemain;
+ SwTwips nVirtualPagesWidth = 0;
+ SwTwips nLastPageWidth = pLastPageInCurrentRow->Frm().Width() + nSidebarWidth;
+
+ while ( ( mnColumns > 0 || nRemain > 0 ) && nNumberOfVirtualPages < nMaxNumberOfVirtualPages )
+ {
+ SwTwips nLastPageWidthWithGap = nLastPageWidth;
+ if ( !mbBookMode || ( 0 == (nNumberOfVirtualPages + nNumberOfPagesInRow) %2) )
+ nLastPageWidthWithGap += nGapBetweenPages;
+
+ if ( mnColumns > 0 || nLastPageWidthWithGap < nRemain )
+ {
+ ++nNumberOfVirtualPages;
+ nVirtualPagesWidth += nLastPageWidthWithGap;
+ }
+ nRemain = nRemain - nLastPageWidthWithGap;
+ }
+
+ nCurrentRowWidth = nCurrentRowWidth + nVirtualPagesWidth;
+ }
+
+ // first page in book mode is always special:
+ if ( bFirstRow && mbBookMode )
+ {
+ // #i88036#
+ nCurrentRowWidth +=
+ pStartOfRow->GetFormatPage().Frm().Width() + nSidebarWidth;
+ }
+
+ // center page if possible
+ const long nSizeDiff = nVisWidth > nCurrentRowWidth ?
+ ( nVisWidth - nCurrentRowWidth ) / 2 :
+ 0;
+
+ // adjust positions of pages in current row
+ long nX = nSizeDiff;
+
+ const long nRowStart = nBorder + nSizeDiff;
+ const long nRowEnd = nRowStart + nCurrentRowWidth;
+
+ if ( bFirstRow && mbBookMode )
+ {
+ // #i88036#
+ nX += pStartOfRow->GetFormatPage().Frm().Width() + nSidebarWidth;
+ }
+
+ SwPageFrm* pEndOfRow = pPageFrm;
+ SwPageFrm* pPageToAdjust = pStartOfRow;
+
+ do
+ {
+ const SwPageFrm* pFormatPage = pPageToAdjust;
+ if ( mbBookMode )
+ pFormatPage = &pPageToAdjust->GetFormatPage();
+
+ const SwTwips nCurrentPageWidth = pFormatPage->Frm().Width() + (pFormatPage->IsEmptyPage() ? 0 : nSidebarWidth);
+ const Point aOldPagePos = pPageToAdjust->Frm().Pos();
+ const bool bLeftSidebar = pPageToAdjust->SidebarPosition() == sw::sidebarwindows::SIDEBAR_LEFT;
+ const SwTwips nLeftPageAddOffset = bLeftSidebar ?
+ nSidebarWidth :
+ 0;
+
+ Point aNewPagePos( nBorder + nX, nBorder + nSumRowHeight );
+ Point aNewPagePosWithLeftOffset( nBorder + nX + nLeftPageAddOffset, nBorder + nSumRowHeight );
+
+ // RTL view layout: Calculate mirrored page position
+ if ( bRTL )
+ {
+ const long nXOffsetInRow = aNewPagePos.X() - nRowStart;
+ aNewPagePos.X() = nRowEnd - nXOffsetInRow - nCurrentPageWidth;
+ aNewPagePosWithLeftOffset = aNewPagePos;
+ aNewPagePosWithLeftOffset.X() += nLeftPageAddOffset;
+ }
+
+ if ( aNewPagePosWithLeftOffset != aOldPagePos )
+ {
+ lcl_MoveAllLowers( pPageToAdjust, aNewPagePosWithLeftOffset - aOldPagePos );
+ pPageToAdjust->SetCompletePaint();
+ bPageChanged = true;
+ }
+
+ // calculate area covered by the current page and store to
+ // maPageRects. This is used e.g., for cursor setting
+ const bool bFirstColumn = pPageToAdjust == pStartOfRow;
+ const bool bLastColumn = pPageToAdjust->GetNext() == pEndOfRow;
+ const bool bLastRow = !pEndOfRow;
+
+ nMinPageLeft = Min( nMinPageLeft, aNewPagePos.X() );
+ nMaxPageRight = Max( nMaxPageRight, aNewPagePos.X() + nCurrentPageWidth);
+
+ // border of nGapBetweenPages around the current page:
+ SwRect aPageRectWithBorders( aNewPagePos.X() - nGapBetweenPages,
+ aNewPagePos.Y(),
+ pPageToAdjust->Frm().SSize().Width() + nGapBetweenPages + nSidebarWidth,
+ nCurrentRowHeight );
+
+ static const long nOuterClickDiff = 1000000;
+
+ // adjust borders for these special cases:
+ if ( (bFirstColumn && !bRTL) || (bLastColumn && bRTL) )
+ aPageRectWithBorders.SubLeft( nOuterClickDiff );
+ if ( (bLastColumn && !bRTL) || (bFirstColumn && bRTL) )
+ aPageRectWithBorders.AddRight( nOuterClickDiff );
+ if ( bFirstRow )
+ aPageRectWithBorders.SubTop( nOuterClickDiff );
+ if ( bLastRow )
+ aPageRectWithBorders.AddBottom( nOuterClickDiff );
+
+ maPageRects.push_back( aPageRectWithBorders );
+
+ nX = nX + nCurrentPageWidth;
+ pPageToAdjust = static_cast<SwPageFrm*>(pPageToAdjust->GetNext());
+
+ // distance to next page
+ if ( pPageToAdjust && pPageToAdjust != pEndOfRow )
+ {
+ // in book view, we add the x gap before left (even) pages:
+ if ( mbBookMode )
+ {
+ if ( 0 == (pPageToAdjust->GetPhyPageNum()%2) )
+ nX = nX + nGapBetweenPages;
+ }
+ else
+ {
+ // in non-book view, dont add x gap before
+ // 1. the last empty page in a row
+ // 2. after an empty page
+ const bool bDontAddGap = ( pPageToAdjust->IsEmptyPage() && pPageToAdjust->GetNext() == pEndOfRow ) ||
+ ( static_cast<SwPageFrm*>(pPageToAdjust->GetPrev())->IsEmptyPage() );
+
+ if ( !bDontAddGap )
+ nX = nX + nGapBetweenPages;
+ }
+ }
+ }
+ while ( pPageToAdjust != pEndOfRow );
+
+ // adjust values for root frame size
+ nSumRowHeight = nSumRowHeight + nCurrentRowHeight;
+
+ // start new row:
+ nCurrentRowHeight = 0;
+ nCurrentRowWidth = 0;
+ pStartOfRow = pEndOfRow;
+ nWidthRemain = nVisWidth;
+ nNumberOfPagesInRow = 0;
+ bFirstRow = false;
+ } // end row finished
+ } // end while
+
+ // set size of root frame:
+ const Size aOldSize( Frm().SSize() );
+ const Size aNewSize( nMaxPageRight - nBorder, nSumRowHeight - nGapBetweenPages );
+
+ if ( bPageChanged || aNewSize != aOldSize )
+ {
+ ChgSize( aNewSize );
+ ::AdjustSizeChgNotify( this );
+ Calc();
+
+ ViewShell* pSh = GetCurrShell();
+
+ if ( pSh && pSh->GetDoc()->GetDocShell() )
+ {
+ pSh->SetFirstVisPageInvalid();
+ if (bOldCallbackActionEnabled)
+ {
+ pSh->InvalidateWindows( SwRect( 0, 0, LONG_MAX, LONG_MAX ) );
+ pSh->GetDoc()->GetDocShell()->Broadcast(SfxSimpleHint(SFX_HINT_DOCCHANGED));
+ }
+ }
+ }
+
+ maPagesArea.Pos( Frm().Pos() );
+ maPagesArea.SSize( aNewSize );
+ if ( TWIPS_MAX != nMinPageLeft )
+ maPagesArea._Left( nMinPageLeft );
+
+ SetCallbackActionEnabled( bOldCallbackActionEnabled );
+}
+
+bool SwRootFrm::IsLeftToRightViewLayout() const
+{
+ // Layout direction determined by layout direction of the first page.
+ // --> OD 2008-04-08 #i88036#
+ // Only ask a non-empty page frame for its layout direction
+// const SwPageFrm* pPage = dynamic_cast<const SwPageFrm*>(Lower());
+// return !pPage->IsRightToLeft() && !pPage->IsVertical();
+ const SwPageFrm& rPage =
+ dynamic_cast<const SwPageFrm*>(Lower())->GetFormatPage();
+ return !rPage.IsRightToLeft() && !rPage.IsVertical();
+ // <--
+}
+
+const SwPageFrm& SwPageFrm::GetFormatPage() const
+{
+ const SwPageFrm* pRet = this;
+ if ( IsEmptyPage() )
+ {
+ pRet = static_cast<const SwPageFrm*>( OnRightPage() ? GetNext() : GetPrev() );
+ // --> OD 2008-04-08 #i88035#
+ // Typically a right empty page frame has a next non-empty page frame and
+ // a left empty page frame has a previous non-empty page frame.
+ // But under certain cirsumstances this assumption is not true -
+ // e.g. during insertion of a left page at the end of the document right
+ // after a left page in an intermediate state a right empty page does not
+ // have a next page frame.
+ if ( pRet == 0 )
+ {
+ if ( OnRightPage() )
+ {
+ pRet = static_cast<const SwPageFrm*>( GetPrev() );
+ }
+ else
+ {
+ pRet = static_cast<const SwPageFrm*>( GetNext() );
+ }
+ }
+ OSL_ENSURE( pRet,
+ "<SwPageFrm::GetFormatPage()> - inconsistent layout: empty page without previous and next page frame --> crash." );
+ // <--
+ }
+ return *pRet;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/layout/pagedesc.cxx b/sw/source/core/layout/pagedesc.cxx
new file mode 100644
index 000000000000..dec5a75becf5
--- /dev/null
+++ b/sw/source/core/layout/pagedesc.cxx
@@ -0,0 +1,487 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+
+
+#include <hintids.hxx>
+#include <editeng/pbinitem.hxx>
+#include <editeng/ulspitem.hxx>
+#include <editeng/boxitem.hxx>
+#include <editeng/brshitem.hxx>
+#include <editeng/shaditem.hxx>
+#include <editeng/lrspitem.hxx>
+#include "editeng/frmdiritem.hxx"
+#include <fmtclds.hxx>
+#include <fmtfsize.hxx>
+#include <frmatr.hxx>
+#include <pagefrm.hxx>
+#include <pagedesc.hxx>
+#include <frmfmt.hxx>
+#include <fmtcol.hxx> // SwTxtFmtColl
+#include <node.hxx>
+#include <swtable.hxx>
+#include <frmtool.hxx>
+#include <doc.hxx> // fuer GetAttrPool
+#include <poolfmt.hxx>
+#include <switerator.hxx>
+
+/*************************************************************************
+|*
+|* SwPageDesc::SwPageDesc()
+|*
+|*************************************************************************/
+
+
+
+SwPageDesc::SwPageDesc( const String& rName, SwFrmFmt *pFmt, SwDoc *pDc ) :
+ SwModify( 0 ),
+ aDescName( rName ),
+ aMaster( pDc->GetAttrPool(), rName, pFmt ),
+ aLeft( pDc->GetAttrPool(), rName, pFmt ),
+ aDepend( this, 0 ),
+ pFollow( this ),
+ nRegHeight( 0 ),
+ nRegAscent( 0 ),
+ eUse( (UseOnPage)(nsUseOnPage::PD_ALL | nsUseOnPage::PD_HEADERSHARE | nsUseOnPage::PD_FOOTERSHARE) ),
+ bLandscape( sal_False ),
+ aFtnInfo()
+{
+}
+
+SwPageDesc::SwPageDesc( const SwPageDesc &rCpy ) :
+ SwModify( 0 ),
+ aDescName( rCpy.GetName() ),
+ aNumType( rCpy.GetNumType() ),
+ aMaster( rCpy.GetMaster() ),
+ aLeft( rCpy.GetLeft() ),
+ aDepend( this, (SwModify*)rCpy.aDepend.GetRegisteredIn() ),
+ pFollow( rCpy.pFollow ),
+ nRegHeight( rCpy.GetRegHeight() ),
+ nRegAscent( rCpy.GetRegAscent() ),
+ eUse( rCpy.ReadUseOn() ),
+ bLandscape( rCpy.GetLandscape() ),
+ aFtnInfo( rCpy.GetFtnInfo() )
+{
+}
+
+SwPageDesc & SwPageDesc::operator = (const SwPageDesc & rSrc)
+{
+ aDescName = rSrc.aDescName;
+ aNumType = rSrc.aNumType;
+ aMaster = rSrc.aMaster;
+ aLeft = rSrc.aLeft;
+
+ if (rSrc.pFollow == &rSrc)
+ pFollow = this;
+ else
+ pFollow = rSrc.pFollow;
+
+ nRegHeight = rSrc.nRegHeight;
+ nRegAscent = rSrc.nRegAscent;
+ eUse = rSrc.eUse;
+ bLandscape = rSrc.bLandscape;
+ return *this;
+}
+
+SwPageDesc::~SwPageDesc()
+{
+}
+
+/*************************************************************************
+|*
+|* SwPageDesc::Mirror()
+|*
+|* Beschreibung Gespiegelt werden nur die Raender.
+|* Attribute wie Umrandung und dergleichen werden 1:1 kopiert.
+|*
+|*************************************************************************/
+
+
+
+void SwPageDesc::Mirror()
+{
+ //Das Spiegeln findet nur beim RandAttribut statt, alle anderen Werte
+ //werden schlicht uebertragen.
+ SvxLRSpaceItem aLR( RES_LR_SPACE );
+ const SvxLRSpaceItem &rLR = aMaster.GetLRSpace();
+ aLR.SetLeft( rLR.GetRight() );
+ aLR.SetRight( rLR.GetLeft() );
+
+ SfxItemSet aSet( *aMaster.GetAttrSet().GetPool(),
+ aMaster.GetAttrSet().GetRanges() );
+ aSet.Put( aLR );
+ aSet.Put( aMaster.GetFrmSize() );
+ aSet.Put( aMaster.GetPaperBin() );
+ aSet.Put( aMaster.GetULSpace() );
+ aSet.Put( aMaster.GetBox() );
+ aSet.Put( aMaster.GetBackground() );
+ aSet.Put( aMaster.GetShadow() );
+ aSet.Put( aMaster.GetCol() );
+ aSet.Put( aMaster.GetFrmDir() ); // #112217#
+ aLeft.SetFmtAttr( aSet );
+}
+
+void SwPageDesc::ResetAllAttr( sal_Bool bLeft )
+{
+ SwFrmFmt& rFmt = bLeft ? GetLeft() : GetMaster();
+
+ // --> OD 2007-01-25 #i73790# - method renamed
+ rFmt.ResetAllFmtAttr();
+ // <--
+ rFmt.SetFmtAttr( SvxFrameDirectionItem(FRMDIR_HORI_LEFT_TOP, RES_FRAMEDIR) );
+}
+
+/*************************************************************************
+|*
+|* SwPageDesc::GetInfo()
+|*
+|* Beschreibung erfragt Informationen
+|*
+*************************************************************************/
+
+
+ // erfrage vom Modify Informationen
+sal_Bool SwPageDesc::GetInfo( SfxPoolItem & rInfo ) const
+{
+ if( !aMaster.GetInfo( rInfo ) )
+ return sal_False; // found
+ return aLeft.GetInfo( rInfo );
+}
+
+/*************************************************************************
+|*
+|* SwPageDesc::SetRegisterFmtColl()
+|*
+|* Beschreibung setzt die Vorlage fuer die Registerhaltigkeit
+|*
+*************************************************************************/
+
+
+void SwPageDesc::SetRegisterFmtColl( const SwTxtFmtColl* pFmt )
+{
+ if( pFmt != GetRegisterFmtColl() )
+ {
+ if( pFmt )
+ ((SwTxtFmtColl*)pFmt)->Add( &aDepend );
+ else
+ ((SwTxtFmtColl*)GetRegisterFmtColl())->Remove( &aDepend );
+
+ RegisterChange();
+ }
+}
+
+/*************************************************************************
+|*
+|* SwPageDesc::GetRegisterFmtColl()
+|*
+|* Beschreibung holt die Vorlage fuer die Registerhaltigkeit
+|*
+*************************************************************************/
+
+
+const SwTxtFmtColl* SwPageDesc::GetRegisterFmtColl() const
+{
+ const SwModify* pReg = aDepend.GetRegisteredIn();
+ return (SwTxtFmtColl*)pReg;
+}
+
+/*************************************************************************
+|*
+|* SwPageDesc::RegisterChange()
+|*
+|* Beschreibung benachrichtigt alle betroffenen PageFrames
+|*
+*************************************************************************/
+
+
+void SwPageDesc::RegisterChange()
+{
+ // --> OD 2004-06-15 #117072# - During destruction of the document <SwDoc>
+ // the page description is modified. Thus, do nothing, if the document
+ // is in destruction respectively if no viewshell exists.
+ SwDoc* pDoc = GetMaster().GetDoc();
+ if ( !pDoc || pDoc->IsInDtor() )
+ {
+ return;
+ }
+ ViewShell* pSh = 0L;
+ pDoc->GetEditShell( &pSh );
+ if ( !pSh )
+ {
+ return;
+ }
+
+ nRegHeight = 0;
+ {
+ SwIterator<SwFrm,SwFmt> aIter( GetMaster() );
+ for( SwFrm* pLast = aIter.First(); pLast; pLast = aIter.Next() )
+ {
+ if( pLast->IsPageFrm() )
+ ((SwPageFrm*)pLast)->PrepareRegisterChg();
+ }
+ }
+ {
+ SwIterator<SwFrm,SwFmt> aIter( GetLeft() );
+ for( SwFrm* pLast = aIter.First(); pLast; pLast = aIter.Next() )
+ {
+ if( pLast->IsPageFrm() )
+ ((SwPageFrm*)pLast)->PrepareRegisterChg();
+ }
+ }
+}
+
+/*************************************************************************
+|*
+|* SwPageDesc::Modify()
+|*
+|* Beschreibung reagiert insbesondere auf Aenderungen
+|* der Vorlage fuer die Registerhaltigkeit
+|*
+*************************************************************************/
+
+
+void SwPageDesc::Modify( const SfxPoolItem* pOld, const SfxPoolItem *pNew )
+{
+ const sal_uInt16 nWhich = pOld ? pOld->Which() : pNew ? pNew->Which() : 0;
+ NotifyClients( pOld, pNew );
+
+ if ( (RES_ATTRSET_CHG == nWhich) || (RES_FMT_CHG == nWhich)
+ || isCHRATR(nWhich) || (RES_PARATR_LINESPACING == nWhich) )
+ {
+ RegisterChange();
+ }
+}
+
+static const SwFrm* lcl_GetFrmOfNode( const SwNode& rNd )
+{
+ SwModify* pMod;
+ sal_uInt16 nFrmType = FRM_CNTNT;
+
+ if( rNd.IsCntntNode() )
+ {
+ pMod = &(SwCntntNode&)rNd;
+ }
+ else if( rNd.IsTableNode() )
+ {
+ pMod = ((SwTableNode&)rNd).GetTable().GetFrmFmt();
+ nFrmType = FRM_TAB;
+ }
+ else
+ pMod = 0;
+
+ Point aNullPt;
+ return pMod ? ::GetFrmOfModify( 0, *pMod, nFrmType, &aNullPt, 0, sal_False )
+ : 0;
+}
+
+const SwPageDesc* SwPageDesc::GetPageDescOfNode(const SwNode& rNd)
+{
+ const SwPageDesc* pRet = 0;
+ const SwFrm* pChkFrm = lcl_GetFrmOfNode( rNd );
+ if (pChkFrm && 0 != (pChkFrm = pChkFrm->FindPageFrm()))
+ pRet = ((const SwPageFrm*)pChkFrm)->GetPageDesc();
+ return pRet;
+}
+
+const SwFrmFmt* SwPageDesc::GetPageFmtOfNode( const SwNode& rNd,
+ sal_Bool bCheckForThisPgDc ) const
+{
+ // welches PageDescFormat ist fuer diesen Node gueltig?
+ const SwFrmFmt* pRet;
+ const SwFrm* pChkFrm = lcl_GetFrmOfNode( rNd );
+
+ if( pChkFrm && 0 != ( pChkFrm = pChkFrm->FindPageFrm() ))
+ {
+ const SwPageDesc* pPd = bCheckForThisPgDc ? this :
+ ((SwPageFrm*)pChkFrm)->GetPageDesc();
+ pRet = &pPd->GetMaster();
+ OSL_ENSURE( ((SwPageFrm*)pChkFrm)->GetPageDesc() == pPd, "Wrong node for detection of page format!" );
+ // an welchem Format haengt diese Seite?
+ if( !pChkFrm->KnowsFormat(*pRet) )
+ {
+ pRet = &pPd->GetLeft();
+ OSL_ENSURE( pChkFrm->KnowsFormat(*pRet), "Wrong node for detection of page format!" );
+ }
+ }
+ else
+ pRet = &GetMaster();
+ return pRet;
+}
+
+sal_Bool SwPageDesc::IsFollowNextPageOfNode( const SwNode& rNd ) const
+{
+ sal_Bool bRet = sal_False;
+ if( GetFollow() && this != GetFollow() )
+ {
+ const SwFrm* pChkFrm = lcl_GetFrmOfNode( rNd );
+ if( pChkFrm && 0 != ( pChkFrm = pChkFrm->FindPageFrm() ) &&
+ pChkFrm->IsPageFrm() &&
+ ( !pChkFrm->GetNext() || GetFollow() ==
+ ((SwPageFrm*)pChkFrm->GetNext())->GetPageDesc() ))
+ // die Seite gefunden, auf die der Follow verweist
+ bRet = sal_True;
+ }
+ return bRet;
+}
+
+/*************************************************************************
+|*
+|* SwPageFtnInfo::SwPageFtnInfo()
+|*
+|*************************************************************************/
+
+
+
+SwPageFtnInfo::SwPageFtnInfo() :
+ nMaxHeight( 0 ),
+// aPen( PEN_SOLID ),
+ nLineWidth(10),
+ eLineStyle( editeng::SOLID ),
+ aWidth( 25, 100 ),
+ nTopDist( 57 ), //1mm
+ nBottomDist( 57 )
+{
+ eAdj = FRMDIR_HORI_RIGHT_TOP == GetDefaultFrameDirection(GetAppLanguage()) ?
+ FTNADJ_RIGHT :
+ FTNADJ_LEFT;
+// aPen.SetWidth( 10 );
+}
+
+
+
+SwPageFtnInfo::SwPageFtnInfo( const SwPageFtnInfo &rCpy ) :
+ nMaxHeight( rCpy.GetHeight() ),
+ nLineWidth(rCpy.nLineWidth),
+ eLineStyle(rCpy.eLineStyle),
+ aLineColor(rCpy.aLineColor),
+ aWidth( rCpy.GetWidth() ),
+ eAdj( rCpy.GetAdj() ),
+ nTopDist( rCpy.GetTopDist() ),
+ nBottomDist( rCpy.GetBottomDist() )
+{
+}
+
+/*************************************************************************
+|*
+|* SwPageFtnInfo::operator=
+|*
+|*************************************************************************/
+
+
+
+SwPageFtnInfo &SwPageFtnInfo::operator=( const SwPageFtnInfo& rCpy )
+{
+ nMaxHeight = rCpy.GetHeight();
+ nLineWidth = rCpy.nLineWidth;
+ eLineStyle = rCpy.eLineStyle;
+ aLineColor = rCpy.aLineColor;
+ aWidth = rCpy.GetWidth();
+ eAdj = rCpy.GetAdj();
+ nTopDist = rCpy.GetTopDist();
+ nBottomDist = rCpy.GetBottomDist();
+ return *this;
+}
+/*************************************************************************
+|*
+|* SwPageFtnInfo::operator==
+|*
+|*************************************************************************/
+
+
+
+sal_Bool SwPageFtnInfo::operator==( const SwPageFtnInfo& rCmp ) const
+{
+ return ( nMaxHeight == rCmp.GetHeight() &&
+ nLineWidth == rCmp.nLineWidth &&
+ eLineStyle == rCmp.eLineStyle &&
+ aLineColor == rCmp.aLineColor &&
+ aWidth == rCmp.GetWidth() &&
+ eAdj == rCmp.GetAdj() &&
+ nTopDist == rCmp.GetTopDist() &&
+ nBottomDist== rCmp.GetBottomDist() );
+}
+
+SwPageDescExt::SwPageDescExt(const SwPageDesc & rPageDesc, SwDoc * _pDoc)
+ : aPageDesc(rPageDesc), pDoc(_pDoc)
+{
+ SetPageDesc(rPageDesc);
+}
+
+SwPageDescExt::SwPageDescExt(const SwPageDescExt & rSrc)
+ : aPageDesc(rSrc.aPageDesc), pDoc(rSrc.pDoc)
+{
+ SetPageDesc(rSrc.aPageDesc);
+}
+
+SwPageDescExt::~SwPageDescExt()
+{
+}
+
+const String & SwPageDescExt::GetName() const
+{
+ return aPageDesc.GetName();
+}
+
+void SwPageDescExt::SetPageDesc(const SwPageDesc & _aPageDesc)
+{
+ aPageDesc = _aPageDesc;
+
+ if (aPageDesc.GetFollow())
+ sFollow = aPageDesc.GetFollow()->GetName();
+}
+
+SwPageDescExt & SwPageDescExt::operator = (const SwPageDesc & rSrc)
+{
+ SetPageDesc(rSrc);
+
+ return *this;
+}
+
+SwPageDescExt & SwPageDescExt::operator = (const SwPageDescExt & rSrc)
+{
+ SetPageDesc(rSrc.aPageDesc);
+
+ return *this;
+}
+
+SwPageDescExt::operator SwPageDesc() const
+{
+ SwPageDesc aResult(aPageDesc);
+
+ SwPageDesc * pPageDesc = pDoc->GetPageDesc(sFollow);
+
+ if ( 0 != pPageDesc )
+ aResult.SetFollow(pPageDesc);
+
+ return aResult;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/layout/pagefrm.src b/sw/source/core/layout/pagefrm.src
new file mode 100644
index 000000000000..1c5cafc38c4d
--- /dev/null
+++ b/sw/source/core/layout/pagefrm.src
@@ -0,0 +1,7 @@
+#include "pagefrm.hrc"
+
+Bitmap BMP_PAGE_SHADOW_MASK
+{
+ File = "page-shadow-mask.png";
+};
+
diff --git a/sw/source/core/layout/paintfrm.cxx b/sw/source/core/layout/paintfrm.cxx
new file mode 100644
index 000000000000..8744151ef0e2
--- /dev/null
+++ b/sw/source/core/layout/paintfrm.cxx
@@ -0,0 +1,6701 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+#include <com/sun/star/text/HoriOrientation.hpp>
+#include <hintids.hxx>
+#include <vcl/sound.hxx>
+#include <tools/poly.hxx>
+#include <svl/svstdarr.hxx>
+#include <svx/xoutbmp.hxx>
+#include <sfx2/progress.hxx>
+#include <editeng/brshitem.hxx>
+#include <editeng/opaqitem.hxx>
+#include <editeng/prntitem.hxx>
+#include <editeng/boxitem.hxx>
+#include <editeng/shaditem.hxx>
+#include <svx/framelink.hxx>
+#include <vcl/graph.hxx>
+#include <svx/svdpagv.hxx>
+#include <tgrditem.hxx>
+#include <switerator.hxx>
+#include <fmtsrnd.hxx>
+#include <fmtclds.hxx>
+#include <tools/shl.hxx>
+#include <comcore.hrc>
+#include <swmodule.hxx>
+#include <rootfrm.hxx>
+#include <pagefrm.hxx>
+#include <cntfrm.hxx>
+#include <viewsh.hxx>
+#include <section.hxx>
+#include <sectfrm.hxx>
+#include <doc.hxx>
+#include <viewimp.hxx>
+#include <dflyobj.hxx>
+#include <flyfrm.hxx>
+#include <frmtool.hxx>
+#include <viewopt.hxx>
+#include <dview.hxx>
+#include <dcontact.hxx>
+#include <txtfrm.hxx>
+#include <ftnfrm.hxx>
+#include <tabfrm.hxx>
+#include <rowfrm.hxx>
+#include <cellfrm.hxx>
+#include <notxtfrm.hxx>
+#include <swregion.hxx>
+#include <layact.hxx>
+#include <pagedesc.hxx>
+#include <ptqueue.hxx>
+#include <noteurl.hxx>
+#include <virtoutp.hxx>
+#include <lineinfo.hxx>
+#include <dbg_lay.hxx>
+#include <accessibilityoptions.hxx>
+#include <docsh.hxx>
+#include <swtable.hxx>
+#include <svx/svdogrp.hxx>
+#include <sortedobjs.hxx>
+#include <EnhancedPDFExportHelper.hxx>
+#include <ndole.hxx>
+#include <svtools/chartprettypainter.hxx>
+#include <PostItMgr.hxx>
+#include <tools/color.hxx>
+#include <vcl/svapp.hxx>
+
+#define COL_NOTES_SIDEPANE RGB_COLORDATA(230,230,230)
+#define COL_NOTES_SIDEPANE_BORDER RGB_COLORDATA(200,200,200)
+#define COL_NOTES_SIDEPANE_SCROLLAREA RGB_COLORDATA(230,230,220)
+
+#include <svtools/borderhelper.hxx>
+
+#include "pagefrm.hrc"
+#include <drawinglayer/geometry/viewinformation2d.hxx>
+#include <drawinglayer/processor2d/baseprocessor2d.hxx>
+#include <drawinglayer/primitive2d/polygonprimitive2d.hxx>
+#include <drawinglayer/primitive2d/borderlineprimitive2d.hxx>
+#include <drawinglayer/primitive2d/discreteshadowprimitive2d.hxx>
+#include <svx/sdr/contact/objectcontacttools.hxx>
+#include <svx/unoapi.hxx>
+#include <basegfx/matrix/b2dhommatrix.hxx>
+
+using namespace ::editeng;
+using namespace ::com::sun::star;
+
+#define GETOBJSHELL() ((SfxObjectShell*)rSh.GetDoc()->GetDocShell())
+
+//Tabellenhilfslinien an?
+#define IS_SUBS_TABLE \
+ (pGlobalShell->GetViewOptions()->IsTable() && \
+ !pGlobalShell->GetViewOptions()->IsPagePreview()&&\
+ !pGlobalShell->GetViewOptions()->IsReadonly()&&\
+ !pGlobalShell->GetViewOptions()->IsFormView() &&\
+ SwViewOption::IsTableBoundaries())
+//sonstige Hilfslinien an?
+#define IS_SUBS (!pGlobalShell->GetViewOptions()->IsPagePreview() && \
+ !pGlobalShell->GetViewOptions()->IsReadonly() && \
+ !pGlobalShell->GetViewOptions()->IsFormView() &&\
+ SwViewOption::IsDocBoundaries())
+//Hilfslinien fuer Bereiche
+#define IS_SUBS_SECTION (!pGlobalShell->GetViewOptions()->IsPagePreview() && \
+ !pGlobalShell->GetViewOptions()->IsReadonly()&&\
+ !pGlobalShell->GetViewOptions()->IsFormView() &&\
+ SwViewOption::IsSectionBoundaries())
+#define IS_SUBS_FLYS (!pGlobalShell->GetViewOptions()->IsPagePreview() && \
+ !pGlobalShell->GetViewOptions()->IsReadonly()&&\
+ !pGlobalShell->GetViewOptions()->IsFormView() &&\
+ SwViewOption::IsObjectBoundaries())
+
+#define SW_MAXBORDERCACHE 20
+
+//Klassendeklarationen. Hier weil sie eben nur in diesem File benoetigt
+//werden.
+
+#define SUBCOL_PAGE 0x01 //Helplines of the page
+#define SUBCOL_BREAK 0x02 //Helpline for a page or column break
+#define SUBCOL_TAB 0x08 //Helplines inside tables
+#define SUBCOL_FLY 0x10 //Helplines inside fly frames
+#define SUBCOL_SECT 0x20 //Helplines inside sections
+
+//----- Klassen zum Sammeln von Umrandungen und Hilfslinien ---
+class SwLineRect : public SwRect
+{
+ Color aColor;
+ SvxBorderStyle nStyle;
+ const SwTabFrm *pTab;
+ sal_uInt8 nSubColor; //Hilfslinien einfaerben
+ sal_Bool bPainted; //schon gepaintet?
+ sal_uInt8 nLock; //Um die Linien zum Hell-Layer abzugrenzen.
+public:
+ SwLineRect( const SwRect &rRect, const Color *pCol, const SvxBorderStyle nStyle,
+ const SwTabFrm *pT , const sal_uInt8 nSCol );
+
+ const Color *GetColor() const { return &aColor;}
+ SvxBorderStyle GetStyle() const { return nStyle; }
+ const SwTabFrm *GetTab() const { return pTab; }
+ void SetPainted() { bPainted = sal_True; }
+ void Lock( sal_Bool bLock ) { if ( bLock )
+ ++nLock;
+ else if ( nLock )
+ --nLock;
+ }
+ sal_Bool IsPainted() const { return bPainted; }
+ sal_Bool IsLocked() const { return nLock != 0; }
+ sal_uInt8 GetSubColor() const { return nSubColor;}
+
+ sal_Bool MakeUnion( const SwRect &rRect );
+};
+
+SV_DECL_VARARR( SwLRects, SwLineRect, 100, 100 )
+
+class SwLineRects : public SwLRects
+{
+ sal_uInt16 nLastCount; //unuetze Durchlaeufe im PaintLines verhindern.
+public:
+ SwLineRects() : nLastCount( 0 ) {}
+ void AddLineRect( const SwRect& rRect, const Color *pColor, const SvxBorderStyle nStyle,
+ const SwTabFrm *pTab, const sal_uInt8 nSCol );
+ void ConnectEdges( OutputDevice *pOut );
+ void PaintLines ( OutputDevice *pOut );
+ void LockLines( sal_Bool bLock );
+
+ /// OD 13.08.2002 - correct type of function
+ sal_uInt16 Free() const { return nFree; }
+};
+
+class SwSubsRects : public SwLineRects
+{
+ void RemoveSuperfluousSubsidiaryLines( const SwLineRects &rRects ); //;-)
+public:
+ void PaintSubsidiary( OutputDevice *pOut, const SwLineRects *pRects );
+
+ inline void Ins( const SwRect &rRect, const sal_uInt8 nSCol );
+};
+
+//----------------- End Klassen Umrandungen ----------------------
+
+static ViewShell *pGlobalShell = 0;
+
+//Wenn durchsichtige FlyInCnts im PaintBackground gepainted werden so soll der
+//Hintergrund nicht mehr retouchiert werden.
+//static sal_Bool bLockFlyBackground = sal_False;
+
+//Wenn vom Fly ein Metafile abgezogen wird, so soll nur der FlyInhalt und vor
+//nur hintergrund vom FlyInhalt gepaintet werden.
+static sal_Bool bFlyMetafile = sal_False;
+static OutputDevice *pFlyMetafileOut = 0;
+
+//Die Retouche fuer Durchsichtige Flys wird vom Hintergrund der Flys
+//erledigt. Dabei darf der Fly selbst natuerlich nicht ausgespart werden.
+//siehe PaintBackground und lcl_SubtractFlys()
+static SwFlyFrm *pRetoucheFly = 0;
+static SwFlyFrm *pRetoucheFly2 = 0;
+
+//Groesse eines Pixel und die Haelfte davon. Wird jeweils bei Eintritt in
+//SwRootFrm::Paint neu gesetzt.
+static long nPixelSzW = 0, nPixelSzH = 0;
+static long nHalfPixelSzW = 0, nHalfPixelSzH = 0;
+static long nMinDistPixelW = 0, nMinDistPixelH = 0;
+
+//Aktueller Zoomfaktor
+static double aScaleX = 1.0;
+static double aScaleY = 1.0;
+static double aMinDistScale = 0.73;
+static double aEdgeScale = 0.5;
+
+//In pLines werden Umrandungen waehrend des Paint gesammelt und soweit
+//moeglich zusammengefasst.
+//In pSubsLines werden Hilfslinien gesammelt und zusammengefasst. Diese
+//werden vor der Ausgabe mit pLines abgeglichen, so dass moeglichst keine
+//Umrandungen von den Hilfslinen verdeckt werden.
+//bTablines ist waerend des Paints einer Tabelle sal_True.
+static SwLineRects *pLines = 0;
+static SwSubsRects *pSubsLines = 0;
+// OD 18.11.2002 #99672# - global variable for sub-lines of body, header, footer,
+// section and footnote frames.
+static SwSubsRects *pSpecSubsLines = 0;
+
+static SfxProgress *pProgress = 0;
+
+static SwFlyFrm *pFlyOnlyDraw = 0;
+
+//Damit die Flys auch fuer den Hack richtig gepaintet werden koennen.
+static sal_Bool bTableHack = sal_False;
+
+//Um das teure Ermitteln der RetoucheColor zu optimieren
+Color aGlobalRetoucheColor;
+
+//Statics fuer Umrandungsalignment setzen.
+// OD 05.05.2003 #107169# - adjustment for 'small' twip-to-pixel relations:
+// For 'small' twip-to-pixel relations (less then 2:1)
+// values of <nHalfPixelSzW> and <nHalfPixelSzH> are set to ZERO.
+void SwCalcPixStatics( OutputDevice *pOut )
+{
+ // OD 30.04.2003 #107169# - determine 'small' twip-to-pixel relation
+ sal_Bool bSmallTwipToPxRelW = sal_False;
+ sal_Bool bSmallTwipToPxRelH = sal_False;
+ {
+ Size aCheckTwipToPxRelSz( pOut->PixelToLogic( Size( 100, 100 )) );
+ if ( (aCheckTwipToPxRelSz.Width()/100.0) < 2.0 )
+ {
+ bSmallTwipToPxRelW = sal_True;
+ }
+ if ( (aCheckTwipToPxRelSz.Height()/100.0) < 2.0 )
+ {
+ bSmallTwipToPxRelH = sal_True;
+ }
+ }
+
+ Size aSz( pOut->PixelToLogic( Size( 1,1 )) );
+
+ nPixelSzW = aSz.Width();
+ if( !nPixelSzW )
+ nPixelSzW = 1;
+ nPixelSzH = aSz.Height();
+ if( !nPixelSzH )
+ nPixelSzH = 1;
+
+ // OD 06.05.2003 #107169# - consider 'small' twip-to-pixel relations
+ if ( !bSmallTwipToPxRelW )
+ {
+ nHalfPixelSzW = nPixelSzW / 2 + 1;
+ }
+ else
+ {
+ nHalfPixelSzW = 0;
+ }
+ // OD 06.05.2003 #107169# - consider 'small' twip-to-pixel relations
+ if ( !bSmallTwipToPxRelH )
+ {
+ nHalfPixelSzH = nPixelSzH / 2 + 1;
+ }
+ else
+ {
+ nHalfPixelSzH = 0;
+ }
+
+ nMinDistPixelW = nPixelSzW * 2 + 1;
+ nMinDistPixelH = nPixelSzH * 2 + 1;
+
+ const MapMode &rMap = pOut->GetMapMode();
+ aScaleX = rMap.GetScaleX();
+ aScaleY = rMap.GetScaleY();
+}
+
+//Zum Sichern der statics, damit das Paint (quasi) reentrant wird.
+class SwSavePaintStatics
+{
+ sal_Bool bSFlyMetafile,
+ bSPageOnly;
+ ViewShell *pSGlobalShell;
+ OutputDevice *pSFlyMetafileOut;
+ SwFlyFrm *pSRetoucheFly,
+ *pSRetoucheFly2,
+ *pSFlyOnlyDraw;
+ SwLineRects *pSLines;
+ SwSubsRects *pSSubsLines;
+ // --> OD 2005-07-04 #123196#
+ SwSubsRects* pSSpecSubsLines;
+ // <--
+ SfxProgress *pSProgress;
+ long nSPixelSzW,
+ nSPixelSzH,
+ nSHalfPixelSzW,
+ nSHalfPixelSzH,
+ nSMinDistPixelW,
+ nSMinDistPixelH;
+ Color aSGlobalRetoucheColor;
+ double aSScaleX,
+ aSScaleY;
+public:
+ SwSavePaintStatics();
+ ~SwSavePaintStatics();
+};
+
+SwSavePaintStatics::SwSavePaintStatics() :
+ bSFlyMetafile ( bFlyMetafile ),
+ pSGlobalShell ( pGlobalShell ),
+ pSFlyMetafileOut ( pFlyMetafileOut ),
+ pSRetoucheFly ( pRetoucheFly ),
+ pSRetoucheFly2 ( pRetoucheFly2 ),
+ pSFlyOnlyDraw ( pFlyOnlyDraw ),
+ pSLines ( pLines ),
+ pSSubsLines ( pSubsLines ),
+ // --> OD 2005-07-04 #123196#
+ pSSpecSubsLines ( pSpecSubsLines ),
+ // <--
+ pSProgress ( pProgress ),
+ nSPixelSzW ( nPixelSzW ),
+ nSPixelSzH ( nPixelSzH ),
+ nSHalfPixelSzW ( nHalfPixelSzW ),
+ nSHalfPixelSzH ( nHalfPixelSzH ),
+ nSMinDistPixelW ( nMinDistPixelW ),
+ nSMinDistPixelH ( nMinDistPixelH ),
+ aSGlobalRetoucheColor( aGlobalRetoucheColor ),
+ aSScaleX ( aScaleX ),
+ aSScaleY ( aScaleY )
+{
+ bFlyMetafile = sal_False;
+ pFlyMetafileOut = 0;
+ pRetoucheFly = 0;
+ pRetoucheFly2 = 0;
+ nPixelSzW = nPixelSzH =
+ nHalfPixelSzW = nHalfPixelSzH =
+ nMinDistPixelW = nMinDistPixelH = 0;
+ aScaleX = aScaleY = 1.0;
+ aMinDistScale = 0.73;
+ aEdgeScale = 0.5;
+ pLines = 0;
+ pSubsLines = 0;
+ // --> OD 2005-07-04 #123196#
+ pSpecSubsLines = 0L;
+ // <--
+ pProgress = 0;
+}
+
+SwSavePaintStatics::~SwSavePaintStatics()
+{
+ pGlobalShell = pSGlobalShell;
+ bFlyMetafile = bSFlyMetafile;
+ pFlyMetafileOut = pSFlyMetafileOut;
+ pRetoucheFly = pSRetoucheFly;
+ pRetoucheFly2 = pSRetoucheFly2;
+ pFlyOnlyDraw = pSFlyOnlyDraw;
+ pLines = pSLines;
+ pSubsLines = pSSubsLines;
+ // --> OD 2005-07-04 #123196#
+ pSpecSubsLines = pSSpecSubsLines;
+ // <--
+ pProgress = pSProgress;
+ nPixelSzW = nSPixelSzW;
+ nPixelSzH = nSPixelSzH;
+ nHalfPixelSzW = nSHalfPixelSzW;
+ nHalfPixelSzH = nSHalfPixelSzH;
+ nMinDistPixelW = nSMinDistPixelW;
+ nMinDistPixelH = nSMinDistPixelH;
+ aGlobalRetoucheColor = aSGlobalRetoucheColor;
+ aScaleX = aSScaleX;
+ aScaleY = aSScaleY;
+}
+
+//----------------- Implementierungen fuer Tabellenumrandung --------------
+
+SV_IMPL_VARARR( SwLRects, SwLineRect );
+
+SwLineRect::SwLineRect( const SwRect &rRect, const Color *pCol, const SvxBorderStyle nStyl,
+ const SwTabFrm *pT, const sal_uInt8 nSCol ) :
+ SwRect( rRect ),
+ nStyle( nStyl ),
+ pTab( pT ),
+ nSubColor( nSCol ),
+ bPainted( sal_False ),
+ nLock( 0 )
+{
+ if ( pCol != NULL )
+ aColor = *pCol;
+}
+
+sal_Bool SwLineRect::MakeUnion( const SwRect &rRect )
+{
+ //Es wurde bereits ausserhalb geprueft, ob die Rechtecke die gleiche
+ //Ausrichtung (horizontal bzw. vertikal), Farbe usw. besitzen.
+ if ( Height() > Width() ) //Vertikale Linie
+ {
+ if ( Left() == rRect.Left() && Width() == rRect.Width() )
+ {
+ //Zusammenfassen wenn kein Luecke zwischen den Linien ist.
+ const long nAdd = nPixelSzW + nHalfPixelSzW;
+ if ( Bottom() + nAdd >= rRect.Top() &&
+ Top() - nAdd <= rRect.Bottom() )
+ {
+ Bottom( Max( Bottom(), rRect.Bottom() ) );
+ Top ( Min( Top(), rRect.Top() ) );
+ return sal_True;
+ }
+ }
+ }
+ else
+ {
+ if ( Top() == rRect.Top() && Height() == rRect.Height() )
+ {
+ //Zusammenfassen wenn kein Luecke zwischen den Linien ist.
+ const long nAdd = nPixelSzW + nHalfPixelSzW;
+ if ( Right() + nAdd >= rRect.Left() &&
+ Left() - nAdd <= rRect.Right() )
+ {
+ Right( Max( Right(), rRect.Right() ) );
+ Left ( Min( Left(), rRect.Left() ) );
+ return sal_True;
+ }
+ }
+ }
+ return sal_False;
+}
+
+void SwLineRects::AddLineRect( const SwRect &rRect, const Color *pCol, const SvxBorderStyle nStyle,
+ const SwTabFrm *pTab, const sal_uInt8 nSCol )
+{
+ //Rueckwaerts durch, weil Linien die zusammengefasst werden koennen i.d.R.
+ //im gleichen Kontext gepaintet werden.
+ for ( sal_uInt16 i = Count(); i ; )
+ {
+ SwLineRect &rLRect = operator[](--i);
+ //Pruefen von Ausrichtung, Farbe, Tabelle.
+ if ( rLRect.GetTab() == pTab &&
+ !rLRect.IsPainted() && rLRect.GetSubColor() == nSCol &&
+ (rLRect.Height() > rLRect.Width()) == (rRect.Height() > rRect.Width()) &&
+ ((!rLRect.GetColor() && !pCol) ||
+ (rLRect.GetColor() && pCol && *rLRect.GetColor() == *pCol)) )
+ {
+ if ( rLRect.MakeUnion( rRect ) )
+ return;
+ }
+ }
+ Insert( SwLineRect( rRect, pCol, nStyle, pTab, nSCol ), Count() );
+}
+
+void SwLineRects::ConnectEdges( OutputDevice *pOut )
+{
+ if ( pOut->GetOutDevType() != OUTDEV_PRINTER )
+ {
+ //Fuer einen zu kleinen Zoom arbeite ich nicht.
+ if ( aScaleX < aEdgeScale || aScaleY < aEdgeScale )
+ return;
+ }
+
+ static const long nAdd = 20;
+
+ SvPtrarr aCheck( 64, 64 );
+
+ for ( int i = 0; i < (int)Count(); ++i )
+ {
+ SwLineRect &rL1 = operator[](sal_uInt16(i));
+ if ( !rL1.GetTab() || rL1.IsPainted() || rL1.IsLocked() )
+ continue;
+
+ aCheck.Remove( 0, aCheck.Count() );
+
+ const sal_Bool bVert = rL1.Height() > rL1.Width();
+ long nL1a, nL1b, nL1c, nL1d;
+
+ if ( bVert )
+ {
+ nL1a = rL1.Top(); nL1b = rL1.Left();
+ nL1c = rL1.Right(); nL1d = rL1.Bottom();
+ }
+ else
+ {
+ nL1a = rL1.Left(); nL1b = rL1.Top();
+ nL1c = rL1.Bottom(); nL1d = rL1.Right();
+ }
+
+ //Alle moeglicherweise mit i1 zu verbindenden Linien einsammeln.
+ for ( sal_uInt16 i2 = 0; i2 < Count(); ++i2 )
+ {
+ SwLineRect &rL2 = operator[](i2);
+ if ( rL2.GetTab() != rL1.GetTab() ||
+ rL2.IsPainted() ||
+ rL2.IsLocked() ||
+ (bVert == (rL2.Height() > rL2.Width())) )
+ continue;
+
+ long nL2a, nL2b, nL2c, nL2d;
+ if ( bVert )
+ {
+ nL2a = rL2.Top(); nL2b = rL2.Left();
+ nL2c = rL2.Right(); nL2d = rL2.Bottom();
+ }
+ else
+ {
+ nL2a = rL2.Left(); nL2b = rL2.Top();
+ nL2c = rL2.Bottom(); nL2d = rL2.Right();
+ }
+
+ if ( (nL1a - nAdd < nL2d && nL1d + nAdd > nL2a) &&
+ ((nL1b > nL2b && nL1c < nL2c) ||
+ (nL1c >= nL2c && nL1b - nAdd < nL2c) ||
+ (nL1b <= nL2b && nL1c + nAdd > nL2b)) )
+ {
+ SwLineRect *pMSC = &rL2;
+ aCheck.Insert( pMSC, aCheck.Count() );
+ }
+ }
+ if ( aCheck.Count() < 2 )
+ continue;
+
+ sal_Bool bRemove = sal_False;
+
+ //Fuer jede Linie jede alle folgenden checken.
+ for ( sal_uInt16 k = 0; !bRemove && k < aCheck.Count(); ++k )
+ {
+ SwLineRect &rR1 = (SwLineRect&)*(SwLineRect*)aCheck[k];
+
+ for ( sal_uInt16 k2 = k+1; !bRemove && k2 < aCheck.Count(); ++k2 )
+ {
+ SwLineRect &rR2 = (SwLineRect&)*(SwLineRect*)aCheck[k2];
+ if ( bVert )
+ {
+ SwLineRect *pLA = 0;
+ SwLineRect *pLB = 0;
+ if ( rR1.Top() < rR2.Top() )
+ {
+ pLA = &rR1; pLB = &rR2;
+ }
+ else if ( rR1.Top() > rR2.Top() )
+ {
+ pLA = &rR2; pLB = &rR1;
+ }
+ //beschreiben k1 und k2 eine Doppellinie?
+ if ( pLA && pLA->Bottom() + 60 > pLB->Top() )
+ {
+ if ( rL1.Top() < pLA->Top() )
+ {
+ if ( rL1.Bottom() == pLA->Bottom() )
+ continue; //kleiner Irrtum (woher?)
+
+ SwRect aIns( rL1 );
+ aIns.Bottom( pLA->Bottom() );
+ if ( !rL1.IsInside( aIns ) )
+ continue;
+ const sal_uInt16 nTmpFree = Free();
+ Insert( SwLineRect( aIns, rL1.GetColor(), SOLID,
+ rL1.GetTab(), SUBCOL_TAB ), Count() );
+ if ( !nTmpFree )
+ {
+ --i;
+ k = aCheck.Count();
+ break;
+ }
+ }
+
+ if ( rL1.Bottom() > pLB->Bottom() )
+ rL1.Top( pLB->Top() ); //i1 nach oben verlaengern
+ else
+ bRemove = sal_True; //abbrechen, i1 entfernen
+ }
+ }
+ else
+ {
+ SwLineRect *pLA = 0;
+ SwLineRect *pLB = 0;
+ if ( rR1.Left() < rR2.Left() )
+ {
+ pLA = &rR1; pLB = &rR2;
+ }
+ else if ( rR1.Left() > rR2.Left() )
+ {
+ pLA = &rR2; pLB = &rR1;
+ }
+ //Liegt eine 'doppellinie' vor?
+ if ( pLA && pLA->Right() + 60 > pLB->Left() )
+ {
+ if ( rL1.Left() < pLA->Left() )
+ {
+ if ( rL1.Right() == pLA->Right() )
+ continue; //kleiner irrtum
+
+ SwRect aIns( rL1 );
+ aIns.Right( pLA->Right() );
+ if ( !rL1.IsInside( aIns ) )
+ continue;
+ const sal_uInt16 nTmpFree = Free();
+ Insert( SwLineRect( aIns, rL1.GetColor(), SOLID,
+ rL1.GetTab(), SUBCOL_TAB ), Count() );
+ if ( !nTmpFree )
+ {
+ --i;
+ k = aCheck.Count();
+ break;
+ }
+ }
+ if ( rL1.Right() > pLB->Right() )
+ rL1.Left( pLB->Left() );
+ else
+ bRemove = sal_True;
+ }
+ }
+ }
+ }
+ if ( bRemove )
+ {
+ Remove( static_cast<sal_uInt16>(i), 1 );
+ --i; //keinen auslassen!
+ }
+ }
+}
+
+inline void SwSubsRects::Ins( const SwRect &rRect, const sal_uInt8 nSCol )
+{
+ //Linien die kuerzer als die breiteste Linienbreite sind werden
+ //nicht aufgenommen.
+ if ( rRect.Height() > DEF_LINE_WIDTH_4 || rRect.Width() > DEF_LINE_WIDTH_4 )
+ Insert( SwLineRect( rRect, 0, SOLID, 0, nSCol ), Count());
+}
+
+void SwSubsRects::RemoveSuperfluousSubsidiaryLines( const SwLineRects &rRects )
+{
+ //Alle Hilfslinien, die sich mit irgendwelchen Umrandungen decken werden
+ //entfernt bzw. zerstueckelt..
+ for ( sal_uInt16 i = 0; i < Count(); ++i )
+ {
+ // OD 18.11.2002 #99672# - get a copy instead of a reference, because
+ // an <insert> may destroy the object due to a necessary array resize.
+ const SwLineRect aSubsLineRect = SwLineRect( operator[](i) );
+
+ // OD 19.12.2002 #106318# - add condition <aSubsLineRect.IsLocked()>
+ // in order to consider only border lines, which are *not* locked.
+ if ( aSubsLineRect.IsPainted() ||
+ aSubsLineRect.IsLocked() )
+ continue;
+
+ const bool bVerticalSubs = aSubsLineRect.Height() > aSubsLineRect.Width();
+ SwRect aSubsRect( aSubsLineRect );
+ if ( bVerticalSubs )
+ {
+ aSubsRect.Left ( aSubsRect.Left() - (nPixelSzW+nHalfPixelSzW) );
+ aSubsRect.Right ( aSubsRect.Right() + (nPixelSzW+nHalfPixelSzW) );
+ }
+ else
+ {
+ aSubsRect.Top ( aSubsRect.Top() - (nPixelSzH+nHalfPixelSzH) );
+ aSubsRect.Bottom( aSubsRect.Bottom() + (nPixelSzH+nHalfPixelSzH) );
+ }
+ for ( sal_uInt16 k = 0; k < rRects.Count(); ++k )
+ {
+ SwLineRect &rLine = rRects[k];
+
+ // OD 20.12.2002 #106318# - do *not* consider painted or locked
+ // border lines.
+ // OD 20.01.2003 #i1837# - locked border lines have to be considered.
+ if ( rLine.IsLocked () )
+ continue;
+
+ if ( !bVerticalSubs == ( rLine.Height() > rLine.Width() ) ) //same direction?
+ continue;
+
+ if ( aSubsRect.IsOver( rLine ) )
+ {
+ if ( bVerticalSubs ) // Vertical?
+ {
+ if ( aSubsRect.Left() <= rLine.Right() &&
+ aSubsRect.Right() >= rLine.Left() )
+ {
+ long nTmp = rLine.Top()-(nPixelSzH+1);
+ if ( aSubsLineRect.Top() < nTmp )
+ {
+ SwRect aNewSubsRect( aSubsLineRect );
+ aNewSubsRect.Bottom( nTmp );
+ Insert( SwLineRect( aNewSubsRect, 0, aSubsLineRect.GetStyle(), 0,
+ aSubsLineRect.GetSubColor() ), Count());
+ }
+ nTmp = rLine.Bottom()+nPixelSzH+1;
+ if ( aSubsLineRect.Bottom() > nTmp )
+ {
+ SwRect aNewSubsRect( aSubsLineRect );
+ aNewSubsRect.Top( nTmp );
+ Insert( SwLineRect( aNewSubsRect, 0, aSubsLineRect.GetStyle(), 0,
+ aSubsLineRect.GetSubColor() ), Count());
+ }
+ Remove( i, 1 );
+ --i;
+ break;
+ }
+ }
+ else //Horizontal
+ {
+ if ( aSubsRect.Top() <= rLine.Bottom() &&
+ aSubsRect.Bottom() >= rLine.Top() )
+ {
+ long nTmp = rLine.Left()-(nPixelSzW+1);
+ if ( aSubsLineRect.Left() < nTmp )
+ {
+ SwRect aNewSubsRect( aSubsLineRect );
+ aNewSubsRect.Right( nTmp );
+ Insert( SwLineRect( aNewSubsRect, 0, aSubsLineRect.GetStyle(), 0,
+ aSubsLineRect.GetSubColor() ), Count());
+ }
+ nTmp = rLine.Right()+nPixelSzW+1;
+ if ( aSubsLineRect.Right() > nTmp )
+ {
+ SwRect aNewSubsRect( aSubsLineRect );
+ aNewSubsRect.Left( nTmp );
+ Insert( SwLineRect( aNewSubsRect, 0, aSubsLineRect.GetStyle(), 0,
+ aSubsLineRect.GetSubColor() ), Count());
+ }
+ Remove( i, 1 );
+ --i;
+ break;
+ }
+ }
+ }
+ }
+ }
+}
+
+void SwLineRects::LockLines( sal_Bool bLock )
+{
+ for ( sal_uInt16 i = 0; i < Count(); ++i )
+ operator[](i).Lock( bLock );
+}
+
+void lcl_DrawDashedRect( OutputDevice * pOut, SwLineRect & rLRect )
+{
+ double nHalfLWidth = rLRect.Height( );
+ if ( nHalfLWidth > 1 )
+ {
+ nHalfLWidth = nHalfLWidth / 2;
+ }
+ else
+ {
+ nHalfLWidth = 1;
+ }
+
+ long startX = rLRect.Left( );
+ long startY = rLRect.Top( ) + nHalfLWidth;
+ long endX = rLRect.Left( ) + rLRect.Width( );
+ long endY = rLRect.Top( ) + nHalfLWidth;
+
+ if ( rLRect.Height( ) > rLRect.Width( ) )
+ {
+ nHalfLWidth = rLRect.Width( );
+ if ( nHalfLWidth > 1 )
+ {
+ nHalfLWidth = nHalfLWidth / 2;
+ }
+ else
+ {
+ nHalfLWidth = 1;
+ }
+ startX = rLRect.Left( ) + nHalfLWidth;
+ startY = rLRect.Top( );
+ endX = rLRect.Left( ) + nHalfLWidth;
+ endY = rLRect.Top( ) + rLRect.Height( );
+ }
+
+ svtools::DrawLine( *pOut, Point( startX, startY ), Point( endX, endY ),
+ sal_uInt32( nHalfLWidth * 2 ), rLRect.GetStyle( ) );
+}
+
+void SwLineRects::PaintLines( OutputDevice *pOut )
+{
+ //Painten der Umrandungen. Leider muessen wir zweimal durch.
+ //Einmal fuer die innenliegenden und einmal fuer die Aussenkanten
+ //der Tabellen.
+ if ( Count() != nLastCount )
+ {
+ // --> FME 2004-06-24 #i16816# tagged pdf support
+ SwTaggedPDFHelper aTaggedPDFHelper( 0, 0, 0, *pOut );
+ // <--
+
+ // OD 2004-04-23 #116347#
+ pOut->Push( PUSH_FILLCOLOR|PUSH_LINECOLOR );
+ pOut->SetFillColor();
+ pOut->SetLineColor();
+ ConnectEdges( pOut );
+ const Color *pLast = 0;
+
+ sal_Bool bPaint2nd = sal_False;
+ sal_uInt16 nMinCount = Count();
+ sal_uInt16 i;
+
+ for ( i = 0; i < Count(); ++i )
+ {
+ SwLineRect &rLRect = operator[](i);
+
+ if ( rLRect.IsPainted() )
+ continue;
+
+ if ( rLRect.IsLocked() )
+ {
+ nMinCount = Min( nMinCount, i );
+ continue;
+ }
+
+ //Jetzt malen oder erst in der zweiten Runde?
+ sal_Bool bPaint = sal_True;
+ if ( rLRect.GetTab() )
+ {
+ if ( rLRect.Height() > rLRect.Width() )
+ {
+ //Senkrechte Kante, ueberlappt sie mit der TabellenKante?
+ SwTwips nLLeft = rLRect.Left() - 30,
+ nLRight = rLRect.Right() + 30,
+ nTLeft = rLRect.GetTab()->Frm().Left() + rLRect.GetTab()->Prt().Left(),
+ nTRight = rLRect.GetTab()->Frm().Left() + rLRect.GetTab()->Prt().Right();
+ if ( (nTLeft >= nLLeft && nTLeft <= nLRight) ||
+ (nTRight>= nLLeft && nTRight<= nLRight) )
+ bPaint = sal_False;
+ }
+ else
+ { //Waagerechte Kante, ueberlappt sie mit der Tabellenkante?
+ SwTwips nLTop = rLRect.Top() - 30,
+ nLBottom = rLRect.Bottom() + 30,
+ nTTop = rLRect.GetTab()->Frm().Top() + rLRect.GetTab()->Prt().Top(),
+ nTBottom = rLRect.GetTab()->Frm().Top() + rLRect.GetTab()->Prt().Bottom();
+ if ( (nTTop >= nLTop && nTTop <= nLBottom) ||
+ (nTBottom >= nLTop && nTBottom <= nLBottom) )
+ bPaint = sal_False;
+ }
+ }
+ if ( bPaint )
+ {
+ if ( !pLast || *pLast != *rLRect.GetColor() )
+ {
+ pLast = rLRect.GetColor();
+
+ sal_uLong nOldDrawMode = pOut->GetDrawMode();
+ if( pGlobalShell->GetWin() &&
+ Application::GetSettings().GetStyleSettings().GetHighContrastMode() )
+ pOut->SetDrawMode( 0 );
+
+ pOut->SetLineColor( *pLast );
+ pOut->SetFillColor( *pLast );
+ pOut->SetDrawMode( nOldDrawMode );
+ }
+
+ if( !rLRect.IsEmpty() )
+ lcl_DrawDashedRect( pOut, rLRect );
+ rLRect.SetPainted();
+ }
+ else
+ bPaint2nd = sal_True;
+ }
+ if ( bPaint2nd )
+ for ( i = 0; i < Count(); ++i )
+ {
+ SwLineRect &rLRect = operator[](i);
+ if ( rLRect.IsPainted() )
+ continue;
+
+ if ( rLRect.IsLocked() )
+ {
+ nMinCount = Min( nMinCount, i );
+ continue;
+ }
+
+ if ( !pLast || *pLast != *rLRect.GetColor() )
+ {
+ pLast = rLRect.GetColor();
+
+ sal_uLong nOldDrawMode = pOut->GetDrawMode();
+ if( pGlobalShell->GetWin() &&
+ Application::GetSettings().GetStyleSettings().GetHighContrastMode() )
+ {
+ pOut->SetDrawMode( 0 );
+ }
+
+ pOut->SetFillColor( *pLast );
+ pOut->SetDrawMode( nOldDrawMode );
+ }
+ if( !rLRect.IsEmpty() )
+ lcl_DrawDashedRect( pOut, rLRect );
+ rLRect.SetPainted();
+ }
+ nLastCount = nMinCount;
+ pOut->Pop();
+ }
+}
+
+void SwSubsRects::PaintSubsidiary( OutputDevice *pOut,
+ const SwLineRects *pRects )
+{
+ if ( Count() )
+ {
+ // --> FME 2004-06-24 #i16816# tagged pdf support
+ SwTaggedPDFHelper aTaggedPDFHelper( 0, 0, 0, *pOut );
+ // <--
+
+ //Alle Hilfslinien, die sich fast decken entfernen (Tabellen)
+ for ( sal_uInt16 i = 0; i < Count(); ++i )
+ {
+ SwLineRect &rLi = operator[](i);
+ const bool bVerticalSubs = rLi.Height() > rLi.Width();
+
+ for ( sal_uInt16 k = i+1; k < Count(); ++k )
+ {
+ SwLineRect &rLk = operator[](k);
+ if ( rLi.SSize() == rLk.SSize() )
+ {
+ if ( bVerticalSubs == ( rLk.Height() > rLk.Width() ) )
+ {
+ if ( bVerticalSubs )
+ {
+ long nLi = rLi.Right();
+ long nLk = rLk.Right();
+ if ( rLi.Top() == rLk.Top() &&
+ ((nLi < rLk.Left() && nLi+21 > rLk.Left()) ||
+ (nLk < rLi.Left() && nLk+21 > rLi.Left())))
+ {
+ Remove( k, 1 );
+ //Nicht mit der inneren Schleife weiter, weil
+ //das Array schrumpfen koennte!
+ --i; k = Count();
+ }
+ }
+ else
+ {
+ long nLi = rLi.Bottom();
+ long nLk = rLk.Bottom();
+ if ( rLi.Left() == rLk.Left() &&
+ ((nLi < rLk.Top() && nLi+21 > rLk.Top()) ||
+ (nLk < rLi.Top() && nLk+21 > rLi.Top())))
+ {
+ Remove( k, 1 );
+ --i; k = Count();
+ }
+ }
+ }
+ }
+ }
+ }
+
+ if ( pRects && pRects->Count() )
+ RemoveSuperfluousSubsidiaryLines( *pRects );
+
+ if ( Count() )
+ {
+ // OD 2004-04-23 #116347#
+ pOut->Push( PUSH_FILLCOLOR|PUSH_LINECOLOR );
+ pOut->SetLineColor();
+
+ // OD 14.01.2003 #106660# - reset draw mode in high contrast
+ // mode in order to get fill color set at output device.
+ // Recover draw mode after draw of lines.
+ // Necessary for the subsidiary lines painted by the fly frames.
+ sal_uLong nOldDrawMode = pOut->GetDrawMode();
+ if( pGlobalShell->GetWin() &&
+ Application::GetSettings().GetStyleSettings().GetHighContrastMode() )
+ {
+ pOut->SetDrawMode( 0 );
+ }
+
+ for ( sal_uInt16 i = 0; i < Count(); ++i )
+ {
+ SwLineRect &rLRect = operator[](i);
+ // OD 19.12.2002 #106318# - add condition <!rLRect.IsLocked()>
+ // to prevent paint of locked subsidiary lines.
+ if ( !rLRect.IsPainted() &&
+ !rLRect.IsLocked() )
+ {
+ const Color *pCol = 0;
+ switch ( rLRect.GetSubColor() )
+ {
+ case SUBCOL_PAGE: pCol = &SwViewOption::GetDocBoundariesColor(); break;
+ case SUBCOL_FLY: pCol = &SwViewOption::GetObjectBoundariesColor(); break;
+ case SUBCOL_TAB: pCol = &SwViewOption::GetTableBoundariesColor(); break;
+ case SUBCOL_SECT: pCol = &SwViewOption::GetSectionBoundColor(); break;
+ case SUBCOL_BREAK: pCol = &SwViewOption::GetPageBreakColor(); break;
+ }
+
+ if ( pOut->GetFillColor() != *pCol )
+ pOut->SetFillColor( *pCol );
+ pOut->DrawRect( rLRect.SVRect() );
+
+ rLRect.SetPainted();
+ }
+ }
+
+ // OD 14.01.2003 #106660# - recovering draw mode
+ pOut->SetDrawMode( nOldDrawMode );
+
+ pOut->Pop();
+ }
+ }
+}
+
+//-------------------------------------------------------------------------
+//Diverse Functions die in diesem File so verwendet werden.
+
+// OD 20.02.2003 - Note: function <SwAlignRect(..)> also used outside this file.
+// OD 29.04.2003 #107169# - correction: adjust rectangle on pixel level in order
+// to assure, that the border 'leaves its original pixel', if it has to.
+// No prior adjustments for odd relation between pixel and twip.
+void MA_FASTCALL SwAlignRect( SwRect &rRect, const ViewShell *pSh )
+{
+ if( !rRect.HasArea() )
+ return;
+
+ // OD 03.09.2002 #102450#
+ // Assure that view shell (parameter <pSh>) exists, if the output device
+ // is taken from this view shell --> no output device, no alignment.
+ // Output device taken from view shell <pSh>, if <bFlyMetafile> not set.
+ if ( !bFlyMetafile && !pSh )
+ {
+ return;
+ }
+
+ const OutputDevice *pOut = bFlyMetafile ?
+ pFlyMetafileOut : pSh->GetOut();
+
+ // OD 28.04.2003 #107169# - hold original rectangle in pixel
+ const Rectangle aOrgPxRect = pOut->LogicToPixel( rRect.SVRect() );
+ // OD 29.04.2003 #107169# - determine pixel-center rectangle in twip
+ const SwRect aPxCenterRect( pOut->PixelToLogic( aOrgPxRect ) );
+
+ // OD 06.05.2003 #107169# - perform adjustments on pixel level.
+ SwRect aAlignedPxRect( aOrgPxRect );
+ if ( rRect.Top() > aPxCenterRect.Top() )
+ {
+ // 'leave pixel overlapping on top'
+ aAlignedPxRect.Top( aAlignedPxRect.Top() + 1 );
+ }
+
+ if ( rRect.Bottom() < aPxCenterRect.Bottom() )
+ {
+ // 'leave pixel overlapping on bottom'
+ aAlignedPxRect.Bottom( aAlignedPxRect.Bottom() - 1 );
+ }
+
+ if ( rRect.Left() > aPxCenterRect.Left() )
+ {
+ // 'leave pixel overlapping on left'
+ aAlignedPxRect.Left( aAlignedPxRect.Left() + 1 );
+ }
+
+ if ( rRect.Right() < aPxCenterRect.Right() )
+ {
+ // 'leave pixel overlapping on right'
+ aAlignedPxRect.Right( aAlignedPxRect.Right() - 1 );
+ }
+
+ // OD 11.10.2002 #103636# - consider negative width/height
+ // check, if aligned SwRect has negative width/height.
+ // If Yes, adjust it to width/height = 0 twip.
+ // NOTE: A SwRect with negative width/height can occur, if the width/height
+ // of the given SwRect in twip was less than a pixel in twip and that
+ // the alignment calculates that the aligned SwRect should not contain
+ // the pixels the width/height is on.
+ if ( aAlignedPxRect.Width() < 0 )
+ {
+ aAlignedPxRect.Width(0);
+ }
+ if ( aAlignedPxRect.Height() < 0 )
+ {
+ aAlignedPxRect.Height(0);
+ }
+ // OD 30.04.2003 #107169# - consider zero width/height
+ // For converting a rectangle from pixel to logic it needs a width/height.
+ // Thus, set width/height to one, if it's zero and correct this on the twip
+ // level after the conversion.
+ sal_Bool bZeroWidth = sal_False;
+ if ( aAlignedPxRect.Width() == 0 )
+ {
+ aAlignedPxRect.Width(1);
+ bZeroWidth = sal_True;
+ }
+ sal_Bool bZeroHeight = sal_False;
+ if ( aAlignedPxRect.Height() == 0 )
+ {
+ aAlignedPxRect.Height(1);
+ bZeroHeight = sal_True;
+ }
+
+ rRect = pOut->PixelToLogic( aAlignedPxRect.SVRect() );
+
+ // OD 30.04.2003 #107169# - consider zero width/height and adjust calculated
+ // aligned twip rectangle.
+ // OD 19.05.2003 #109667# - reset width/height to zero; previous negative
+ // width/height haven't to be considered.
+ if ( bZeroWidth )
+ {
+ rRect.Width(0);
+ }
+ if ( bZeroHeight )
+ {
+ rRect.Height(0);
+ }
+}
+
+/** OD 19.05.2003 #109667# - helper method for twip adjustments on pixel base
+
+ method compares the x- or y-pixel position of two twip-point. If the x-/y-pixel
+ positions are the same, the x-/y-pixel position of the second twip point is
+ adjusted by a given amount of pixels.
+
+ @author OD
+*/
+void lcl_CompPxPosAndAdjustPos( const OutputDevice& _rOut,
+ const Point& _rRefPt,
+ Point& _rCompPt,
+ const sal_Bool _bChkXPos,
+ const sal_Int8 _nPxAdjustment )
+{
+ const Point aRefPxPt = _rOut.LogicToPixel( _rRefPt );
+ Point aCompPxPt = _rOut.LogicToPixel( _rCompPt );
+
+ if ( _bChkXPos )
+ {
+ if ( aCompPxPt.X() == aRefPxPt.X() )
+ {
+ aCompPxPt.X() += _nPxAdjustment ;
+ const Point aAdjustedCompPt = _rOut.PixelToLogic( aCompPxPt );
+ _rCompPt.X() = aAdjustedCompPt.X();
+ }
+ }
+ else
+ {
+ if ( aCompPxPt.Y() == aRefPxPt.Y() )
+ {
+ aCompPxPt.Y() += _nPxAdjustment ;
+ const Point aAdjustedCompPt = _rOut.PixelToLogic( aCompPxPt );
+ _rCompPt.Y() = aAdjustedCompPt.Y();
+ }
+ }
+}
+
+/** OD 25.09.2002 #99739# - method to pixel-align rectangle for drawing graphic object
+
+ Because for drawing a graphic left-top-corner and size coordinations are
+ used, these coordinations have to be determined on pixel level.
+ Thus, convert rectangle to pixel and then convert left-top-corner and
+ size of pixel rectangle back to logic.
+ This calculation is necessary, because there exists a different between
+ the convert from logic to pixel of a normal rectangle with its left-top-
+ and right-bottom-corner and the same convert of the same rectangle
+ with left-top-corner and size.
+ Call this method before each <GraphicObject.Draw(...)>
+
+ @author OD
+*/
+void SwAlignGrfRect( SwRect *pGrfRect, const OutputDevice &rOut )
+{
+ Rectangle aPxRect = rOut.LogicToPixel( pGrfRect->SVRect() );
+ pGrfRect->Pos( rOut.PixelToLogic( aPxRect.TopLeft() ) );
+ pGrfRect->SSize( rOut.PixelToLogic( aPxRect.GetSize() ) );
+}
+
+long MA_FASTCALL lcl_AlignWidth( const long nWidth )
+{
+ if ( nWidth )
+ {
+ const long nW = nWidth % nPixelSzW;
+
+ if ( !nW || nW > nHalfPixelSzW )
+ return Max(1L, nWidth - nHalfPixelSzW);
+ }
+ return nWidth;
+}
+
+long MA_FASTCALL lcl_AlignHeight( const long nHeight )
+{
+ if ( nHeight )
+ {
+ const long nH = nHeight % nPixelSzH;
+
+ if ( !nH || nH > nHalfPixelSzH )
+ return Max(1L, nHeight - nHalfPixelSzH);
+ }
+ return nHeight;
+}
+
+long MA_FASTCALL lcl_MinHeightDist( const long nDist )
+{
+ if ( aScaleX < aMinDistScale || aScaleY < aMinDistScale )
+ return nDist;
+ return ::lcl_AlignHeight( Max( nDist, nMinDistPixelH ));
+}
+
+long MA_FASTCALL lcl_MinWidthDist( const long nDist )
+{
+ if ( aScaleX < aMinDistScale || aScaleY < aMinDistScale )
+ return nDist;
+ return ::lcl_AlignWidth( Max( nDist, nMinDistPixelW ));
+}
+
+//Ermittelt PrtArea plus Umrandung plus Schatten.
+void MA_FASTCALL lcl_CalcBorderRect( SwRect &rRect, const SwFrm *pFrm,
+ const SwBorderAttrs &rAttrs,
+ const sal_Bool bShadow )
+{
+ // OD 23.01.2003 #106386# - special handling for cell frames.
+ // The printing area of a cell frame is completely enclosed in the frame area
+ // and a cell frame has no shadow. Thus, for cell frames the calculated
+ // area equals the frame area.
+ // Notes: Borders of cell frames in R2L text direction will switch its side
+ // - left border is painted on the right; right border on the left.
+ // See <lcl_PaintLeftLine> and <lcl_PaintRightLine>.
+ if( pFrm->IsSctFrm() )
+ {
+ rRect = pFrm->Prt();
+ rRect.Pos() += pFrm->Frm().Pos();
+ }
+ else if ( pFrm->IsCellFrm() )
+ rRect = pFrm->Frm();
+ else
+ {
+ rRect = pFrm->Prt();
+ rRect.Pos() += pFrm->Frm().Pos();
+
+ if ( rAttrs.IsLine() || rAttrs.IsBorderDist() ||
+ (bShadow && rAttrs.GetShadow().GetLocation() != SVX_SHADOW_NONE) )
+ {
+ //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin
+ SwRectFn fnRect = pFrm->IsVertical() ? ( pFrm->IsVertLR() ? fnRectVertL2R : fnRectVert ) : fnRectHori;
+
+ const SvxBoxItem &rBox = rAttrs.GetBox();
+ const sal_Bool bTop = 0 != (pFrm->*fnRect->fnGetTopMargin)();
+ if ( bTop )
+ {
+ SwTwips nDiff = rBox.GetTop() ?
+ rBox.CalcLineSpace( BOX_LINE_TOP ) :
+ ( rAttrs.IsBorderDist() ?
+ // OD 23.01.2003 #106386# - increase of distance by
+ // one twip is incorrect.
+ rBox.GetDistance( BOX_LINE_TOP ) : 0 );
+ if( nDiff )
+ (rRect.*fnRect->fnSubTop)( nDiff );
+ }
+
+ const sal_Bool bBottom = 0 != (pFrm->*fnRect->fnGetBottomMargin)();
+ if ( bBottom )
+ {
+ SwTwips nDiff = 0;
+ // --> collapsing borders FME 2005-05-27 #i29550#
+ if ( pFrm->IsTabFrm() &&
+ ((SwTabFrm*)pFrm)->IsCollapsingBorders() )
+ {
+ // For collapsing borders, we have to add the height of
+ // the height of the last line
+ nDiff = ((SwTabFrm*)pFrm)->GetBottomLineSize();
+ }
+ // <-- collapsing
+ else
+ {
+ nDiff = rBox.GetBottom() ?
+ rBox.CalcLineSpace( BOX_LINE_BOTTOM ) :
+ ( rAttrs.IsBorderDist() ?
+ // OD 23.01.2003 #106386# - increase of distance by
+ // one twip is incorrect.
+ rBox.GetDistance( BOX_LINE_BOTTOM ) : 0 );
+ }
+ if( nDiff )
+ (rRect.*fnRect->fnAddBottom)( nDiff );
+ }
+
+ if ( rBox.GetLeft() )
+ (rRect.*fnRect->fnSubLeft)( rBox.CalcLineSpace( BOX_LINE_LEFT ) );
+ else if ( rAttrs.IsBorderDist() )
+ // OD 23.01.2003 #106386# - increase of distance by one twip is incorrect.
+ (rRect.*fnRect->fnSubLeft)( rBox.GetDistance( BOX_LINE_LEFT ) );
+
+ if ( rBox.GetRight() )
+ (rRect.*fnRect->fnAddRight)( rBox.CalcLineSpace( BOX_LINE_RIGHT ) );
+ else if ( rAttrs.IsBorderDist() )
+ // OD 23.01.2003 #106386# - increase of distance by one twip is incorrect.
+ (rRect.*fnRect->fnAddRight)( rBox.GetDistance( BOX_LINE_RIGHT ) );
+
+ if ( bShadow && rAttrs.GetShadow().GetLocation() != SVX_SHADOW_NONE )
+ {
+ const SvxShadowItem &rShadow = rAttrs.GetShadow();
+ if ( bTop )
+ (rRect.*fnRect->fnSubTop)(rShadow.CalcShadowSpace(SHADOW_TOP));
+ (rRect.*fnRect->fnSubLeft)(rShadow.CalcShadowSpace(SHADOW_LEFT));
+ if ( bBottom )
+ (rRect.*fnRect->fnAddBottom)
+ (rShadow.CalcShadowSpace( SHADOW_BOTTOM ));
+ (rRect.*fnRect->fnAddRight)(rShadow.CalcShadowSpace(SHADOW_RIGHT));
+ }
+ }
+ }
+
+ ::SwAlignRect( rRect, pGlobalShell );
+}
+
+void MA_FASTCALL lcl_ExtendLeftAndRight( SwRect& _rRect,
+ const SwFrm& _rFrm,
+ const SwBorderAttrs& _rAttrs,
+ const SwRectFn& _rRectFn )
+{
+ // OD 21.05.2003 #108789# - extend left/right border/shadow rectangle to
+ // bottom of previous frame/to top of next frame, if border/shadow is joined
+ // with previous/next frame.
+ if ( _rAttrs.JoinedWithPrev( _rFrm ) )
+ {
+ const SwFrm* pPrevFrm = _rFrm.GetPrev();
+ (_rRect.*_rRectFn->fnSetTop)( (pPrevFrm->*_rRectFn->fnGetPrtBottom)() );
+ }
+ if ( _rAttrs.JoinedWithNext( _rFrm ) )
+ {
+ const SwFrm* pNextFrm = _rFrm.GetNext();
+ (_rRect.*_rRectFn->fnSetBottom)( (pNextFrm->*_rRectFn->fnGetPrtTop)() );
+ }
+}
+
+void MA_FASTCALL lcl_SubtractFlys( const SwFrm *pFrm, const SwPageFrm *pPage,
+ const SwRect &rRect, SwRegionRects &rRegion )
+{
+ const SwSortedObjs& rObjs = *pPage->GetSortedObjs();
+ const SwFlyFrm* pSelfFly = pFrm->IsInFly() ? pFrm->FindFlyFrm() : pRetoucheFly2;
+ if ( !pRetoucheFly )
+ pRetoucheFly = pRetoucheFly2;
+
+ for ( sal_uInt16 j = 0; (j < rObjs.Count()) && rRegion.Count(); ++j )
+ {
+ const SwAnchoredObject* pAnchoredObj = rObjs[j];
+ const SdrObject* pSdrObj = pAnchoredObj->GetDrawObj();
+
+ // OD 2004-01-15 #110582# - do not consider invisible objects
+ if ( !pPage->GetFmt()->GetDoc()->IsVisibleLayerId( pSdrObj->GetLayer() ) )
+ continue;
+
+ if ( !pAnchoredObj->ISA(SwFlyFrm) )
+ continue;
+
+ const SwFlyFrm *pFly = static_cast<const SwFlyFrm*>(pAnchoredObj);
+
+ if ( pSelfFly == pFly || pRetoucheFly == pFly || !rRect.IsOver( pFly->Frm() ) )
+ continue;
+
+ if ( !pFly->GetFmt()->GetPrint().GetValue() &&
+ (OUTDEV_PRINTER == pGlobalShell->GetOut()->GetOutDevType() ||
+ pGlobalShell->IsPreView()))
+ continue;
+
+ const sal_Bool bLowerOfSelf = pSelfFly && pFly->IsLowerOf( pSelfFly ) ?
+ sal_True : sal_False;
+
+ //Bei zeichengebundenem Fly nur diejenigen betrachten, in denen er
+ //nicht selbst verankert ist.
+ //#33429# Warum nur bei zeichengebundenen? Es macht doch nie Sinn
+ //Rahmen abzuziehen in denen er selbst verankert ist oder?
+ if ( pSelfFly && pSelfFly->IsLowerOf( pFly ) )
+ continue;
+
+ //#57194# Und warum gilt das nicht analog fuer den RetoucheFly?
+ if ( pRetoucheFly && pRetoucheFly->IsLowerOf( pFly ) )
+ continue;
+
+#if OSL_DEBUG_LEVEL > 1
+ //Flys, die innerhalb des eigenen verankert sind, muessen eine
+ //groessere OrdNum haben oder Zeichengebunden sein.
+ if ( pSelfFly && bLowerOfSelf )
+ {
+ OSL_ENSURE( pFly->IsFlyInCntFrm() ||
+ pSdrObj->GetOrdNumDirect() > pSelfFly->GetVirtDrawObj()->GetOrdNumDirect(),
+ "Fly with wrong z-Order" );
+ }
+#endif
+
+ sal_Bool bStopOnHell = sal_True;
+ if ( pSelfFly )
+ {
+ const SdrObject *pTmp = pSelfFly->GetVirtDrawObj();
+ if ( pSdrObj->GetLayer() == pTmp->GetLayer() )
+ {
+ if ( pSdrObj->GetOrdNumDirect() < pTmp->GetOrdNumDirect() )
+ //Im gleichen Layer werden nur obenliegende beachtet.
+ continue;
+ }
+ else
+ {
+ if ( !bLowerOfSelf && !pFly->GetFmt()->GetOpaque().GetValue() )
+ //Aus anderem Layer interessieren uns nur nicht transparente
+ //oder innenliegende
+ continue;
+ bStopOnHell = sal_False;
+ }
+ }
+ if ( pRetoucheFly )
+ {
+ const SdrObject *pTmp = pRetoucheFly->GetVirtDrawObj();
+ if ( pSdrObj->GetLayer() == pTmp->GetLayer() )
+ {
+ if ( pSdrObj->GetOrdNumDirect() < pTmp->GetOrdNumDirect() )
+ //Im gleichen Layer werden nur obenliegende beachtet.
+ continue;
+ }
+ else
+ {
+ if ( !pFly->IsLowerOf( pRetoucheFly ) && !pFly->GetFmt()->GetOpaque().GetValue() )
+ //Aus anderem Layer interessieren uns nur nicht transparente
+ //oder innenliegende
+ continue;
+ bStopOnHell = sal_False;
+ }
+ }
+
+ //Wenn der Inhalt des Fly Transparent ist, wird er nicht abgezogen, es sei denn
+ //er steht im Hell-Layer (#31941#)
+ const IDocumentDrawModelAccess* pIDDMA = pFly->GetFmt()->getIDocumentDrawModelAccess();
+ sal_Bool bHell = pSdrObj->GetLayer() == pIDDMA->GetHellId();
+ if ( (bStopOnHell && bHell) ||
+ /// OD 05.08.2002 - change internal order of condition
+ /// first check "!bHell", then "..->Lower()" and "..->IsNoTxtFrm()"
+ /// have not to be performed, if frame is in "Hell"
+ ( !bHell && pFly->Lower() && pFly->Lower()->IsNoTxtFrm() &&
+ ( ((SwNoTxtFrm*)pFly->Lower())->IsTransparent() ||
+ ((SwNoTxtFrm*)pFly->Lower())->HasAnimation() ||
+ pFly->GetFmt()->GetSurround().IsContour()
+ )
+ )
+ )
+ continue;
+
+ // OD 08.10.2002 #103898#
+ // Own if-statements for transparent background/shadow of fly frames
+ // (#99657#) in order to handle special conditions.
+ if ( pFly->IsBackgroundTransparent() )
+ {
+ // Background <pFly> is transparent drawn. Thus normally, its region
+ // have not to be substracted from given region.
+ // But, if method is called for a fly frame and
+ // <pFly> is a direct lower of this fly frame and
+ // <pFly> inherites its transparent background brush from its parent,
+ // then <pFly> frame area have to be subtracted from given region.
+ // NOTE: Because in Status Quo transparent backgrounds can only be
+ // assigned to fly frames, the handle of this special case
+ // avoids drawing of transparent areas more than once, if
+ // a fly frame inherites a transparent background from its
+ // parent fly frame.
+ if ( pFrm->IsFlyFrm() &&
+ (pFly->GetAnchorFrm()->FindFlyFrm() == pFrm) &&
+ static_cast<const SwFlyFrmFmt*>(pFly->GetFmt())->IsBackgroundBrushInherited()
+ )
+ {
+ SwRect aRect;
+ SwBorderAttrAccess aAccess( SwFrm::GetCache(), (SwFrm*)pFly );
+ const SwBorderAttrs &rAttrs = *aAccess.Get();
+ ::lcl_CalcBorderRect( aRect, pFly, rAttrs, sal_True );
+ rRegion -= aRect;
+ continue;
+ }
+ else
+ {
+ continue;
+ }
+ }
+ if ( pFly->IsShadowTransparent() )
+ {
+ continue;
+ }
+
+ if ( bHell && pFly->GetAnchorFrm()->IsInFly() )
+ {
+ //Damit die Umrandung nicht vom Hintergrund des anderen Flys
+ //zerlegt wird.
+ SwRect aRect;
+ SwBorderAttrAccess aAccess( SwFrm::GetCache(), (SwFrm*)pFly );
+ const SwBorderAttrs &rAttrs = *aAccess.Get();
+ ::lcl_CalcBorderRect( aRect, pFly, rAttrs, sal_True );
+ rRegion -= aRect;
+ }
+ else
+ {
+ SwRect aRect( pFly->Prt() );
+ aRect += pFly->Frm().Pos();
+ rRegion -= aRect;
+ }
+ }
+ if ( pRetoucheFly == pRetoucheFly2 )
+ pRetoucheFly = 0;
+}
+
+//---------------- Ausgabe fuer das BrushItem ----------------
+
+/** lcl_DrawGraphicBackgrd - local help method to draw a background for a graphic
+
+ OD 17.10.2002 #103876#
+ Under certain circumstances we have to draw a background for a graphic.
+ This method takes care of the conditions and draws the background with the
+ corresponding color.
+ Method introduced for bug fix #103876# in order to optimize drawing tiled
+ background graphics. Previously, this code was integrated in method
+ <lcl_DrawGraphic>.
+ Method implemented as a inline, checking the conditions and calling method
+ method <lcl_implDrawGraphicBackgrd(..)> for the intrinsic drawing.
+
+ @author OD
+
+ @param _rBackgrdBrush
+ background brush contain the color the background has to be drawn.
+
+ @param _pOut
+ output device the background has to be drawn in.
+
+ @param _rPaintRect
+ paint retangle in the output device, which has to be drawn with the background.
+ rectangle have to be aligned by method ::SwAlignRect
+
+ @param _rGraphicObj
+ graphic object, for which the background has to be drawn. Used for checking
+ the transparency of its bitmap, its type and if the graphic is drawn transparent
+
+ @param _bNumberingGraphic
+ boolean indicating that graphic is used as a numbering.
+
+ @param _bBackgrdAlreadyDrawn
+ boolean (optional; default: false) indicating, if the background is already drawn.
+*/
+void lcl_implDrawGraphicBackgrd( const SvxBrushItem& _rBackgrdBrush,
+ OutputDevice* _pOut,
+ const SwRect& _rAlignedPaintRect,
+ const GraphicObject& _rGraphicObj )
+{
+ /// determine color of background
+ /// If color of background brush is not "no fill"/"auto fill" or
+ /// <bFlyMetafile> is set, use color of background brush, otherwise
+ /// use global retouche color.
+ const Color aColor( ( (_rBackgrdBrush.GetColor() != COL_TRANSPARENT) || bFlyMetafile )
+ ? _rBackgrdBrush.GetColor()
+ : aGlobalRetoucheColor );
+
+ /// determine, if background color have to be drawn transparent
+ /// and calculate transparency percent value
+ sal_Int8 nTransparencyPercent = 0;
+ bool bDrawTransparent = false;
+ if ( aColor.GetTransparency() != 0 )
+ /// background color is transparent --> draw transparent.
+ {
+ bDrawTransparent = true;
+ nTransparencyPercent = (aColor.GetTransparency()*100 + 0x7F)/0xFF;
+ }
+ else if ( (_rGraphicObj.GetAttr().GetTransparency() != 0) &&
+ (_rBackgrdBrush.GetColor() == COL_TRANSPARENT) )
+ /// graphic is drawn transparent and background color is
+ /// "no fill"/"auto fill" --> draw transparent
+ {
+ bDrawTransparent = true;
+ nTransparencyPercent = (_rGraphicObj.GetAttr().GetTransparency()*100 + 0x7F)/0xFF;
+ }
+
+ if ( bDrawTransparent )
+ {
+ /// draw background transparent
+ if( _pOut->GetFillColor() != aColor.GetRGBColor() )
+ _pOut->SetFillColor( aColor.GetRGBColor() );
+ PolyPolygon aPoly( _rAlignedPaintRect.SVRect() );
+ _pOut->DrawTransparent( aPoly, nTransparencyPercent );
+ }
+ else
+ {
+ /// draw background opaque
+ if ( _pOut->GetFillColor() != aColor )
+ _pOut->SetFillColor( aColor );
+ _pOut->DrawRect( _rAlignedPaintRect.SVRect() );
+ }
+}
+
+inline void lcl_DrawGraphicBackgrd( const SvxBrushItem& _rBackgrdBrush,
+ OutputDevice* _pOut,
+ const SwRect& _rAlignedPaintRect,
+ const GraphicObject& _rGraphicObj,
+ bool _bNumberingGraphic,
+ bool _bBackgrdAlreadyDrawn = false )
+{
+ /// draw background with background color, if
+ /// (1) graphic is not used as a numbering AND
+ /// (2) background is not already drawn AND
+ /// (3) intrinsic graphic is transparent OR intrinsic graphic doesn't exists
+ if ( !_bNumberingGraphic &&
+ !_bBackgrdAlreadyDrawn &&
+ ( _rGraphicObj.IsTransparent() || _rGraphicObj.GetType() == GRAPHIC_NONE )
+ )
+ {
+ lcl_implDrawGraphicBackgrd( _rBackgrdBrush, _pOut, _rAlignedPaintRect, _rGraphicObj );
+ }
+}
+
+/// OD 06.08.2002 #99657# - Note: the transparency of the background graphic
+/// is saved in SvxBrushItem.GetGraphicObject(<shell>).GetAttr().Set/GetTransparency()
+/// and is considered in the drawing of the graphic.
+/// Thus, to provide transparent background graphic for text frames nothing
+/// has to be coded.
+/// OD 25.09.2002 #99739# - use align rectangle for drawing graphic
+/// OD 25.09.2002 #99739# - pixel-align coordinations for drawing graphic.
+/// OD 17.10.2002 #103876# - outsource code for drawing background of the graphic
+/// with a background color in method <lcl_DrawGraphicBackgrd>
+/// Also, change type of <bGrfNum> and <bClip> from <sal_Bool> to <bool>.
+void lcl_DrawGraphic( const SvxBrushItem& rBrush, OutputDevice *pOut,
+ ViewShell &rSh, const SwRect &rGrf, const SwRect &rOut,
+ bool bClip, bool bGrfNum,
+ bool bBackgrdAlreadyDrawn = false )
+ /// OD 02.09.2002 #99657#
+ /// add parameter <bBackgrdAlreadyDrawn> to indicate
+ /// that the background is already drawn.
+{
+ /// OD 25.09.2002 #99739# - calculate align rectangle from parameter <rGrf>
+ /// and use aligned rectangle <aAlignedGrfRect> in the following code
+ SwRect aAlignedGrfRect = rGrf;
+ ::SwAlignRect( aAlignedGrfRect, &rSh );
+
+ /// OD 17.10.2002 #103876# - change type from <sal_Bool> to <bool>.
+ const bool bNotInside = bClip && !rOut.IsInside( aAlignedGrfRect );
+ if ( bNotInside )
+ {
+ pOut->Push( PUSH_CLIPREGION );
+ pOut->IntersectClipRegion( rOut.SVRect() );
+ }
+
+ //Hier kein Link, wir wollen die Grafik synchron laden!
+ ((SvxBrushItem&)rBrush).SetDoneLink( Link() );
+ GraphicObject *pGrf = (GraphicObject*)rBrush.GetGraphicObject();
+
+ /// OD 17.10.2002 #103876# - outsourcing drawing of background with a background color.
+ ::lcl_DrawGraphicBackgrd( rBrush, pOut, aAlignedGrfRect, *pGrf, bGrfNum, bBackgrdAlreadyDrawn );
+
+ /// OD 25.09.2002 #99739# -
+ /// Because for drawing a graphic left-top-corner and size coordinations are
+ /// used, these coordinations have to be determined on pixel level.
+ ::SwAlignGrfRect( &aAlignedGrfRect, *pOut );
+ pGrf->DrawWithPDFHandling( *pOut, aAlignedGrfRect.Pos(), aAlignedGrfRect.SSize() );
+
+ if ( bNotInside )
+ pOut->Pop();
+} // end of method <lcl_DrawGraphic>
+
+void MA_FASTCALL DrawGraphic( const SvxBrushItem *pBrush,
+ OutputDevice *pOutDev,
+ const SwRect &rOrg,
+ const SwRect &rOut,
+ const sal_uInt8 nGrfNum,
+ const sal_Bool bConsiderBackgroundTransparency )
+ /// OD 05.08.2002 #99657# - add 6th parameter to indicate that method should
+ /// consider background transparency, saved in the color of the brush item
+{
+ ViewShell &rSh = *pGlobalShell;
+ /// OD 17.10.2002 #103876# - change type from <sal_Bool> to <bool>
+ bool bReplaceGrfNum = GRFNUM_REPLACE == nGrfNum;
+ bool bGrfNum = GRFNUM_NO != nGrfNum;
+ Size aGrfSize;
+ SvxGraphicPosition ePos = GPOS_NONE;
+ if( pBrush && !bReplaceGrfNum )
+ {
+ if( rSh.GetViewOptions()->IsGraphic() )
+ {
+ //#125488#: load graphic directly in PDF import
+ // --> OD 2006-08-25 #i68953# - also during print load graphic directly.
+ if ( (rSh).GetViewOptions()->IsPDFExport() ||
+ rSh.GetOut()->GetOutDevType() == OUTDEV_PRINTER )
+ // <--
+ {
+ ((SvxBrushItem*)pBrush)->PurgeMedium();
+ ((SvxBrushItem*)pBrush)->SetDoneLink( Link() );
+ }
+ else
+ ((SvxBrushItem*)pBrush)->SetDoneLink( STATIC_LINK(
+ rSh.GetDoc(), SwDoc, BackgroundDone ) );
+ //SfxObjectShell &rObjSh = *GETOBJSHELL();
+ const Graphic* pGrf = pBrush->GetGraphic();
+ if( pGrf && GRAPHIC_NONE != pGrf->GetType() )
+ {
+ ePos = pBrush->GetGraphicPos();
+ if( pGrf->IsSupportedGraphic() )
+ // don't the use the specific output device! Bug 94802
+ aGrfSize = ::GetGraphicSizeTwip( *pGrf, 0 );
+ }
+ }
+ else
+ bReplaceGrfNum = bGrfNum;
+ }
+
+ SwRect aGrf;
+ aGrf.SSize( aGrfSize );
+ sal_Bool bDraw = sal_True;
+ sal_Bool bRetouche = sal_True;
+ switch ( ePos )
+ {
+ case GPOS_LT:
+ aGrf.Pos() = rOrg.Pos();
+ break;
+
+ case GPOS_MT:
+ aGrf.Pos().Y() = rOrg.Top();
+ aGrf.Pos().X() = rOrg.Left() + rOrg.Width()/2 - aGrfSize.Width()/2;
+ break;
+
+ case GPOS_RT:
+ aGrf.Pos().Y() = rOrg.Top();
+ aGrf.Pos().X() = rOrg.Right() - aGrfSize.Width();
+ break;
+
+ case GPOS_LM:
+ aGrf.Pos().Y() = rOrg.Top() + rOrg.Height()/2 - aGrfSize.Height()/2;
+ aGrf.Pos().X() = rOrg.Left();
+ break;
+
+ case GPOS_MM:
+ aGrf.Pos().Y() = rOrg.Top() + rOrg.Height()/2 - aGrfSize.Height()/2;
+ aGrf.Pos().X() = rOrg.Left() + rOrg.Width()/2 - aGrfSize.Width()/2;
+ break;
+
+ case GPOS_RM:
+ aGrf.Pos().Y() = rOrg.Top() + rOrg.Height()/2 - aGrfSize.Height()/2;
+ aGrf.Pos().X() = rOrg.Right() - aGrfSize.Width();
+ break;
+
+ case GPOS_LB:
+ aGrf.Pos().Y() = rOrg.Bottom() - aGrfSize.Height();
+ aGrf.Pos().X() = rOrg.Left();
+ break;
+
+ case GPOS_MB:
+ aGrf.Pos().Y() = rOrg.Bottom() - aGrfSize.Height();
+ aGrf.Pos().X() = rOrg.Left() + rOrg.Width()/2 - aGrfSize.Width()/2;
+ break;
+
+ case GPOS_RB:
+ aGrf.Pos().Y() = rOrg.Bottom() - aGrfSize.Height();
+ aGrf.Pos().X() = rOrg.Right() - aGrfSize.Width();
+ break;
+
+ case GPOS_AREA:
+ aGrf = rOrg;
+ /// OD 05.09.2002 #102912#
+ /// In spite the fact that the background graphic have to fill the complete
+ /// area, it has been checked, if the graphic will completely fill out
+ /// the region to be painted <rOut> and thus, nothing has to be retouched.
+ /// For example, this is the case for a fly frame without a background
+ /// brush positioned on the border of the page and inherited the
+ /// background brush from the page.
+ bRetouche = !rOut.IsInside( aGrf );
+ break;
+
+ case GPOS_TILED:
+ {
+ // OD 17.10.2002 #103876# - draw background of tiled graphic
+ // before drawing tiled graphic in loop
+ // determine graphic object
+ GraphicObject* pGraphicObj = const_cast< GraphicObject* >(pBrush->GetGraphicObject());
+ // calculate aligned paint rectangle
+ SwRect aAlignedPaintRect = rOut;
+ ::SwAlignRect( aAlignedPaintRect, &rSh );
+ // OD 25.10.2002 #103876# - draw background color for aligned paint rectangle
+ lcl_DrawGraphicBackgrd( *pBrush, pOutDev, aAlignedPaintRect, *pGraphicObj, bGrfNum );
+
+ // set left-top-corner of background graphic to left-top-corner of the
+ // area, from which the background brush is determined.
+ aGrf.Pos() = rOrg.Pos();
+ // setup clipping at output device
+ pOutDev->Push( PUSH_CLIPREGION );
+ pOutDev->IntersectClipRegion( rOut.SVRect() );
+ // OD 28.10.2002 #103876# - use new method <GraphicObject::DrawTiled(::)>
+ {
+ // calculate paint offset
+ Point aPaintOffset( aAlignedPaintRect.Pos() - aGrf.Pos() );
+ // draw background graphic tiled for aligned paint rectangle
+ // --> OD 2005-02-15 #i42643# - apply fix #104004# for Calc
+ // also for Writer - see /sc/source/view/printfun.cxx
+ // For PDF export, every draw operation for bitmaps takes a
+ // noticeable amount of place (~50 characters). Thus, optimize
+ // between tile bitmap size and number of drawing operations here.
+ //
+ // A_out
+ // n_chars = k1 * ---------- + k2 * A_bitmap
+ // A_bitmap
+ //
+ // minimum n_chars is obtained for (derive for A_bitmap,
+ // set to 0, take positive solution):
+ // k1
+ // A_bitmap = Sqrt( ---- A_out )
+ // k2
+ //
+ // where k1 is the number of chars per draw operation, and
+ // k2 is the number of chars per bitmap pixel.
+ // This is approximately 50 and 7 for current PDF writer, respectively.
+ //
+ const double k1( 50 );
+ const double k2( 7 );
+ const Size aSize( aAlignedPaintRect.SSize() );
+ const double Abitmap( k1/k2 * static_cast<double>(aSize.Width())*aSize.Height() );
+
+ pGraphicObj->DrawTiled( pOutDev,
+ aAlignedPaintRect.SVRect(),
+ aGrf.SSize(),
+ Size( aPaintOffset.X(), aPaintOffset.Y() ),
+ NULL, GRFMGR_DRAW_STANDARD,
+ ::std::max( 128, static_cast<int>( sqrt(sqrt( Abitmap)) + .5 ) ) );
+ // <--
+ }
+ // reset clipping at output device
+ pOutDev->Pop();
+ // set <bDraw> and <bRetouche> to false, indicating that background
+ // graphic and background are already drawn.
+ bDraw = bRetouche = sal_False;
+ }
+ break;
+
+ case GPOS_NONE:
+ bDraw = sal_False;
+ break;
+
+ default: OSL_ENSURE( !pOutDev, "new Graphic position?" );
+ }
+
+ /// OD 02.09.2002 #99657#
+ /// init variable <bGrfBackgrdAlreadDrawn> to indicate, if background of
+ /// graphic is already drawn or not.
+ bool bGrfBackgrdAlreadyDrawn = false;
+ if ( bRetouche )
+ {
+ // OD 2004-04-23 #116347#
+ pOutDev->Push( PUSH_FILLCOLOR|PUSH_LINECOLOR );
+ pOutDev->SetLineColor();
+
+ // OD 07.08.2002 #99657# #GetTransChg#
+ // check, if a existing background graphic (not filling the complete
+ // background) is transparent drawn and the background color is
+ // "no fill" respectively "auto fill", if background transparency
+ // has to be considered.
+ // If YES, memorise transparency of background graphic.
+ // check also, if background graphic bitmap is transparent.
+ bool bTransparentGrfWithNoFillBackgrd = false;
+ sal_Int32 nGrfTransparency = 0;
+ bool bGrfIsTransparent = false;
+ if ( (ePos != GPOS_NONE) &&
+ (ePos != GPOS_TILED) && (ePos != GPOS_AREA)
+ )
+ {
+ GraphicObject *pGrf = (GraphicObject*)pBrush->GetGraphicObject();
+ if ( bConsiderBackgroundTransparency )
+ {
+ GraphicAttr pGrfAttr = pGrf->GetAttr();
+ if ( (pGrfAttr.GetTransparency() != 0) &&
+ ( pBrush && (pBrush->GetColor() == COL_TRANSPARENT) )
+ )
+ {
+ bTransparentGrfWithNoFillBackgrd = true;
+ nGrfTransparency = pGrfAttr.GetTransparency();
+ }
+ }
+ if ( pGrf->IsTransparent() )
+ {
+ bGrfIsTransparent = true;
+ }
+ }
+
+ /// OD 06.08.2002 #99657# #GetTransChg# - to get color of brush,
+ /// check background color against COL_TRANSPARENT ("no fill"/"auto fill")
+ /// instead of checking, if transparency is not set.
+ const Color aColor( pBrush &&
+ ( !(pBrush->GetColor() == COL_TRANSPARENT) ||
+ bFlyMetafile )
+ ? pBrush->GetColor()
+ : aGlobalRetoucheColor );
+
+ /// OD 08.08.2002 #99657# - determine, if background region have to be
+ /// drawn transparent.
+ /// background region has to be drawn transparent, if
+ /// background transparency have to be considered
+ /// AND
+ /// ( background color is transparent OR
+ /// background graphic is transparent and background color is "no fill"
+ /// )
+ sal_Bool bDrawTransparent = bConsiderBackgroundTransparency &&
+ ( ( aColor.GetTransparency() != 0) ||
+ bTransparentGrfWithNoFillBackgrd );
+
+ // --> OD 2008-06-02 #i75614#
+ // reset draw mode in high contrast mode in order to get fill color set
+ const sal_uLong nOldDrawMode = pOutDev->GetDrawMode();
+ if ( pGlobalShell->GetWin() &&
+ Application::GetSettings().GetStyleSettings().GetHighContrastMode() )
+ {
+ pOutDev->SetDrawMode( 0 );
+ }
+ // <--
+
+ /// OD 06.08.2002 #99657# - if background region have to be drawn
+ /// transparent, set only the RGB values of the background color as
+ /// the fill color for the output device.
+ if ( bDrawTransparent )
+ {
+ if( pOutDev->GetFillColor() != aColor.GetRGBColor() )
+ pOutDev->SetFillColor( aColor.GetRGBColor() );
+ }
+ else
+ {
+ if( pOutDev->GetFillColor() != aColor )
+ pOutDev->SetFillColor( aColor );
+ }
+
+ // --> OD 2008-06-02 #i75614#
+ // restore draw mode
+ pOutDev->SetDrawMode( nOldDrawMode );
+ // <--
+
+ /// OD 02.09.2002 #99657#
+ if ( bDrawTransparent )
+ {
+ /// background region have to be drawn transparent.
+ /// Thus, create a poly-polygon from the region and draw it with
+ /// the corresponding transparency precent.
+ PolyPolygon aDrawPoly( rOut.SVRect() );
+ if ( aGrf.HasArea() )
+ {
+ if ( !bGrfIsTransparent )
+ {
+ /// substract area of background graphic from draw area
+ /// OD 08.10.2002 #103898# - consider only that part of the
+ /// graphic area that is overlapping with draw area.
+ SwRect aTmpGrf = aGrf;
+ aTmpGrf.Intersection( rOut );
+ if ( aTmpGrf.HasArea() )
+ {
+ Polygon aGrfPoly( aTmpGrf.SVRect() );
+ aDrawPoly.Insert( aGrfPoly );
+ }
+ }
+ else
+ bGrfBackgrdAlreadyDrawn = true;
+ }
+ /// calculate transparency percent:
+ /// ( <transparency value[0x01..0xFF]>*100 + 0x7F ) / 0xFF
+ /// If there is a background graphic with a background color "no fill"/"auto fill",
+ /// the transparency value is taken from the background graphic,
+ /// otherwise take the transparency value from the color.
+ sal_Int8 nTransparencyPercent = static_cast<sal_Int8>(
+ (( bTransparentGrfWithNoFillBackgrd ? nGrfTransparency : aColor.GetTransparency()
+ )*100 + 0x7F)/0xFF);
+ /// draw poly-polygon transparent
+ pOutDev->DrawTransparent( aDrawPoly, nTransparencyPercent );
+ }
+ else
+ {
+ SwRegionRects aRegion( rOut, 4 );
+ if ( !bGrfIsTransparent )
+ aRegion -= aGrf;
+ else
+ bGrfBackgrdAlreadyDrawn = true;
+ /// loop rectangles of background region, which has to be drawn
+ for( sal_uInt16 i = 0; i < aRegion.Count(); ++i )
+ {
+ pOutDev->DrawRect( aRegion[i].SVRect() );
+ }
+ }
+ pOutDev ->Pop();
+ }
+
+ if( bDraw && aGrf.IsOver( rOut ) )
+ /// OD 02.09.2002 #99657#
+ /// add parameter <bGrfBackgrdAlreadyDrawn>
+ lcl_DrawGraphic( *pBrush, pOutDev, rSh, aGrf, rOut, true, bGrfNum,
+ bGrfBackgrdAlreadyDrawn );
+
+ if( bReplaceGrfNum )
+ {
+ const BitmapEx& rBmp = ViewShell::GetReplacementBitmap( false );
+ Font aTmp( pOutDev->GetFont() );
+ Graphic::DrawEx( pOutDev, aEmptyStr, aTmp, rBmp, rOrg.Pos(), rOrg.SSize() );
+ }
+}
+
+//------------------------------------------------------------------------
+
+/** local help method for SwRootFrm::Paint(..) - Adjust given rectangle to pixel size
+
+ By OD at 27.09.2002 for #103636#
+ In order to avoid paint errors caused by multiple alignments - e.g. method
+ ::SwAlignRect(..) - and other changes to the rectangle to be painted,
+ this method is called for the rectangle to be painted in order to
+ adjust it to the pixel it is overlapping.
+
+ @author OD
+*/
+void lcl_AdjustRectToPixelSize( SwRect& io_aSwRect, const OutputDevice &aOut )
+{
+ /// local constant object of class <Size> to determine number of Twips
+ /// representing a pixel.
+ const Size aTwipToPxSize( aOut.PixelToLogic( Size( 1,1 )) );
+
+ /// local object of class <Rectangle> in Twip coordinates
+ /// calculated from given rectangle aligned to pixel centers.
+ const Rectangle aPxCenterRect = aOut.PixelToLogic(
+ aOut.LogicToPixel( io_aSwRect.SVRect() ) );
+
+ /// local constant object of class <Rectangle> representing given rectangle
+ /// in pixel.
+ const Rectangle aOrgPxRect = aOut.LogicToPixel( io_aSwRect.SVRect() );
+
+ /// calculate adjusted rectangle from pixel centered rectangle.
+ /// Due to rounding differences <aPxCenterRect> doesn't exactly represents
+ /// the Twip-centers. Thus, adjust borders by half of pixel width/height plus 1.
+ /// Afterwards, adjust calculated Twip-positions of the all borders.
+ Rectangle aSizedRect = aPxCenterRect;
+ aSizedRect.Left() -= (aTwipToPxSize.Width()/2 + 1);
+ aSizedRect.Right() += (aTwipToPxSize.Width()/2 + 1);
+ aSizedRect.Top() -= (aTwipToPxSize.Height()/2 + 1);
+ aSizedRect.Bottom() += (aTwipToPxSize.Height()/2 + 1);
+
+ /// adjust left()
+ while ( (aOut.LogicToPixel(aSizedRect)).Left() < aOrgPxRect.Left() )
+ {
+ ++aSizedRect.Left();
+ }
+ /// adjust right()
+ while ( (aOut.LogicToPixel(aSizedRect)).Right() > aOrgPxRect.Right() )
+ {
+ --aSizedRect.Right();
+ }
+ /// adjust top()
+ while ( (aOut.LogicToPixel(aSizedRect)).Top() < aOrgPxRect.Top() )
+ {
+ ++aSizedRect.Top();
+ }
+ /// adjust bottom()
+ while ( (aOut.LogicToPixel(aSizedRect)).Bottom() > aOrgPxRect.Bottom() )
+ {
+ --aSizedRect.Bottom();
+ }
+
+ io_aSwRect = SwRect( aSizedRect );
+
+#if OSL_DEBUG_LEVEL > 1
+ Rectangle aTestOrgPxRect = aOut.LogicToPixel( io_aSwRect.SVRect() );
+ Rectangle aTestNewPxRect = aOut.LogicToPixel( aSizedRect );
+ OSL_ENSURE( aTestOrgPxRect == aTestNewPxRect,
+ "Error in lcl_AlignRectToPixelSize(..): Adjusted rectangle has incorrect position or size");
+ Rectangle aTestNewRect( aSizedRect );
+ /// check Left()
+ --aSizedRect.Left();
+ aTestNewPxRect = aOut.LogicToPixel( aSizedRect );
+ OSL_ENSURE( aTestOrgPxRect.Left() >= (aTestNewPxRect.Left()+1),
+ "Error in lcl_AlignRectToPixelSize(..): Left() not correct adjusted");
+ ++aSizedRect.Left();
+ /// check Right()
+ ++aSizedRect.Right();
+ aTestNewPxRect = aOut.LogicToPixel( aSizedRect );
+ OSL_ENSURE( aTestOrgPxRect.Right() <= (aTestNewPxRect.Right()-1),
+ "Error in lcl_AlignRectToPixelSize(..): Right() not correct adjusted");
+ --aSizedRect.Right();
+ /// check Top()
+ --aSizedRect.Top();
+ aTestNewPxRect = aOut.LogicToPixel( aSizedRect );
+ OSL_ENSURE( aTestOrgPxRect.Top() >= (aTestNewPxRect.Top()+1),
+ "Error in lcl_AlignRectToPixelSize(..): Top() not correct adjusted");
+ ++aSizedRect.Top();
+ /// check Bottom()
+ ++aSizedRect.Bottom();
+ aTestNewPxRect = aOut.LogicToPixel( aSizedRect );
+ OSL_ENSURE( aTestOrgPxRect.Bottom() <= (aTestNewPxRect.Bottom()-1),
+ "Error in lcl_AlignRectToPixelSize(..): Bottom() not correct adjusted");
+ --aSizedRect.Bottom();
+#endif
+}
+
+//
+// FUNCTIONS USED FOR COLLAPSING TABLE BORDER LINES START
+//
+
+struct SwLineEntry
+{
+ SwTwips mnKey;
+ SwTwips mnStartPos;
+ SwTwips mnEndPos;
+
+ svx::frame::Style maAttribute;
+
+ enum OverlapType { NO_OVERLAP, OVERLAP1, OVERLAP2, OVERLAP3 };
+
+public:
+ SwLineEntry( SwTwips nKey,
+ SwTwips nStartPos,
+ SwTwips nEndPos,
+ const svx::frame::Style& rAttribute );
+
+ OverlapType Overlaps( const SwLineEntry& rComp ) const;
+};
+
+SwLineEntry::SwLineEntry( SwTwips nKey,
+ SwTwips nStartPos,
+ SwTwips nEndPos,
+ const svx::frame::Style& rAttribute )
+ : mnKey( nKey ),
+ mnStartPos( nStartPos ),
+ mnEndPos( nEndPos ),
+ maAttribute( rAttribute )
+{
+}
+
+/*
+
+ 1. ---------- rOld
+ ---------- rNew
+
+ 2. ---------- rOld
+ ------------- rNew
+
+ 3. ------- rOld
+ ------------- rNew
+
+ 4. ------------- rOld
+ ---------- rNew
+
+ 5. ---------- rOld
+ ---- rNew
+
+ 6. ---------- rOld
+ ---------- rNew
+
+ 7. ------------- rOld
+ ---------- rNew
+
+ 8. ---------- rOld
+ ------------- rNew
+
+ 9. ---------- rOld
+ ---------- rNew
+*/
+
+SwLineEntry::OverlapType SwLineEntry::Overlaps( const SwLineEntry& rNew ) const
+{
+ SwLineEntry::OverlapType eRet = OVERLAP3;
+
+ if ( mnStartPos >= rNew.mnEndPos || mnEndPos <= rNew.mnStartPos )
+ eRet = NO_OVERLAP;
+
+ // 1, 2, 3
+ else if ( mnEndPos < rNew.mnEndPos )
+ eRet = OVERLAP1;
+
+ // 4, 5, 6, 7
+ else if ( mnStartPos <= rNew.mnStartPos && mnEndPos >= rNew.mnEndPos )
+ eRet = OVERLAP2;
+
+ // 8, 9
+ return eRet;
+}
+
+struct lt_SwLineEntry
+{
+ bool operator()( const SwLineEntry& e1, const SwLineEntry& e2 ) const
+ {
+ return e1.mnStartPos < e2.mnStartPos;
+ }
+};
+
+typedef std::set< SwLineEntry, lt_SwLineEntry > SwLineEntrySet;
+typedef std::set< SwLineEntry, lt_SwLineEntry >::iterator SwLineEntrySetIter;
+typedef std::set< SwLineEntry, lt_SwLineEntry >::const_iterator SwLineEntrySetConstIter;
+typedef std::map< SwTwips, SwLineEntrySet > SwLineEntryMap;
+typedef std::map< SwTwips, SwLineEntrySet >::iterator SwLineEntryMapIter;
+typedef std::map< SwTwips, SwLineEntrySet >::const_iterator SwLineEntryMapConstIter;
+
+class SwTabFrmPainter
+{
+ SwLineEntryMap maVertLines;
+ SwLineEntryMap maHoriLines;
+ const SwTabFrm& mrTabFrm;
+
+ void Insert( SwLineEntry&, bool bHori );
+ void Insert( const SwFrm& rFrm, const SvxBoxItem& rBoxItem );
+ void HandleFrame( const SwLayoutFrm& rFrm );
+ void FindStylesForLine( const Point&,
+ const Point&,
+ svx::frame::Style*,
+ bool bHori ) const;
+
+public:
+ SwTabFrmPainter( const SwTabFrm& rTabFrm );
+
+ void PaintLines( OutputDevice& rDev, const SwRect& rRect ) const;
+};
+
+SwTabFrmPainter::SwTabFrmPainter( const SwTabFrm& rTabFrm )
+ : mrTabFrm( rTabFrm )
+{
+ HandleFrame( rTabFrm );
+}
+
+void SwTabFrmPainter::HandleFrame( const SwLayoutFrm& rLayoutFrm )
+{
+ // Add border lines of cell frames. Skip covered cells. Skip cells
+ // in special row span row, which do not have a negative row span:
+ if ( rLayoutFrm.IsCellFrm() && !rLayoutFrm.IsCoveredCell() )
+ {
+ const SwCellFrm* pThisCell = static_cast<const SwCellFrm*>(&rLayoutFrm);
+ const SwRowFrm* pRowFrm = static_cast<const SwRowFrm*>(pThisCell->GetUpper());
+ const long nRowSpan = pThisCell->GetTabBox()->getRowSpan();
+ if ( !pRowFrm->IsRowSpanLine() || nRowSpan > 1 || nRowSpan < -1 )
+ {
+ SwBorderAttrAccess aAccess( SwFrm::GetCache(), &rLayoutFrm );
+ const SwBorderAttrs& rAttrs = *aAccess.Get();
+ const SvxBoxItem& rBox = rAttrs.GetBox();
+ Insert( rLayoutFrm, rBox );
+ }
+ }
+
+ // Recurse into lower layout frames, but do not recurse into lower tabframes.
+ const SwFrm* pLower = rLayoutFrm.Lower();
+ while ( pLower )
+ {
+ const SwLayoutFrm* pLowerLayFrm = dynamic_cast<const SwLayoutFrm*>(pLower);
+ if ( pLowerLayFrm && !pLowerLayFrm->IsTabFrm() )
+ HandleFrame( *pLowerLayFrm );
+
+ pLower = pLower->GetNext();
+ }
+}
+
+void SwTabFrmPainter::PaintLines( OutputDevice& rDev, const SwRect& rRect ) const
+{
+ // --> FME 2004-06-24 #i16816# tagged pdf support
+ SwTaggedPDFHelper aTaggedPDFHelper( 0, 0, 0, rDev );
+ // <--
+
+ const SwFrm* pTmpFrm = &mrTabFrm;
+ const bool bVert = pTmpFrm->IsVertical();
+
+ SwLineEntryMapConstIter aIter = maHoriLines.begin();
+ bool bHori = true;
+
+ // color for subsidiary lines:
+ const Color& rCol( SwViewOption::GetTableBoundariesColor() );
+
+ // high contrast mode:
+ // overrides the color of non-subsidiary lines.
+ const Color* pHCColor = 0;
+ sal_uLong nOldDrawMode = rDev.GetDrawMode();
+ if( pGlobalShell->GetWin() &&
+ Application::GetSettings().GetStyleSettings().GetHighContrastMode() )
+ {
+ pHCColor = &SwViewOption::GetFontColor();
+ rDev.SetDrawMode( 0 );
+ }
+
+ // set clip region:
+ rDev.Push( PUSH_CLIPREGION );
+ Size aSize( rRect.SSize() );
+ // Hack! Necessary, because the layout is not pixel aligned!
+ aSize.Width() += nPixelSzW; aSize.Height() += nPixelSzH;
+ rDev.SetClipRegion( Rectangle( rRect.Pos(), aSize ) );
+
+ // The following stuff if necessary to have the new table borders fit
+ // into a ::SwAlignRect adjusted world.
+ const SwTwips nTwipXCorr = bVert ? 0 : Max( 0L, nHalfPixelSzW - 2 ); // 1 < 2 < 3 ;-)
+ const SwTwips nTwipYCorr = !bVert ? 0 : Max( 0L, nHalfPixelSzW - 2 ); // 1 < 2 < 3 ;-)
+ const SwFrm* pUpper = mrTabFrm.GetUpper();
+ SwRect aUpper( pUpper->Prt() );
+ aUpper.Pos() += pUpper->Frm().Pos();
+ SwRect aUpperAligned( aUpper );
+ ::SwAlignRect( aUpperAligned, pGlobalShell );
+
+ while ( true )
+ {
+ if ( bHori && aIter == maHoriLines.end() )
+ {
+ aIter = maVertLines.begin();
+ bHori = false;
+ }
+
+ if ( !bHori && aIter == maVertLines.end() )
+ break;
+
+ const SwLineEntrySet& rEntrySet = (*aIter).second;
+ SwLineEntrySetConstIter aSetIter = rEntrySet.begin();
+ while ( aSetIter != rEntrySet.end() )
+ {
+ const SwLineEntry& rEntry = *aSetIter;
+ const svx::frame::Style& rEntryStyle( (*aSetIter).maAttribute );
+
+ Point aStart, aEnd;
+ if ( bHori )
+ {
+ aStart.X() = rEntry.mnStartPos;
+ aStart.Y() = rEntry.mnKey;
+ aEnd.X() = rEntry.mnEndPos;
+ aEnd.Y() = rEntry.mnKey;
+ }
+ else
+ {
+ aStart.X() = rEntry.mnKey;
+ aStart.Y() = rEntry.mnStartPos;
+ aEnd.X() = rEntry.mnKey;
+ aEnd.Y() = rEntry.mnEndPos;
+ }
+
+ SwRect aRepaintRect( aStart, aEnd );
+
+ // the repaint rectangle has to be moved a bit for the centered lines:
+ SwTwips nRepaintRectSize = !rEntryStyle.GetWidth() ? 1 : rEntryStyle.GetWidth();
+ if ( bHori )
+ {
+ aRepaintRect.Height( 2 * nRepaintRectSize );
+ aRepaintRect.Pos().Y() -= nRepaintRectSize;
+ }
+ else
+ {
+ aRepaintRect.Width( 2 * nRepaintRectSize );
+ aRepaintRect.Pos().X() -= nRepaintRectSize;
+ }
+
+ if ( rRect.IsOver( aRepaintRect ) )
+ {
+ svx::frame::Style aStyles[ 7 ];
+ aStyles[ 0 ] = rEntryStyle;
+ FindStylesForLine( aStart, aEnd, aStyles, bHori );
+
+ // subsidiary lines
+ const Color* pTmpColor = 0;
+ if ( 0 == aStyles[ 0 ].GetWidth() )
+ {
+ if ( IS_SUBS_TABLE && pGlobalShell->GetWin() )
+ aStyles[ 0 ].Set( rCol, rCol, rCol, false, 1, 0, 0 );
+ }
+ else
+ pTmpColor = pHCColor;
+
+ // The line sizes stored in the line style have to be adjusted as well.
+ // This will guarantee that lines with the same twip size will have the
+ // same pixel size.
+ for ( int i = 0; i < 7; ++i )
+ {
+ sal_uInt16 nPrim = aStyles[ i ].Prim();
+ sal_uInt16 nDist = aStyles[ i ].Dist();
+ sal_uInt16 nSecn = aStyles[ i ].Secn();
+
+ if ( nPrim > 0 )
+ nPrim = (sal_uInt16)( Max( 1L, nPixelSzH * ( nPrim / nPixelSzH ) ) );
+ if ( nDist > 0 )
+ nDist = (sal_uInt16)( Max( 1L, nPixelSzH * ( nDist / nPixelSzH ) ) );
+ if ( nSecn > 0 )
+ nSecn = (sal_uInt16)( Max( 1L, nPixelSzH * ( nSecn / nPixelSzH ) ) );
+
+ aStyles[ i ].Set( nPrim, nDist, nSecn );
+ }
+
+ // The (twip) positions will be adjusted to meet these requirements:
+ // 1. The y coordinates are located in the middle of the pixel grid
+ // 2. The x coordinated are located at the beginning of the pixel grid
+ // This is done, because the horizontal lines are painted "at beginning",
+ // whereas the vertical lines are painted "centered". By making the line
+ // sizes a multiple of one pixel size, we can assure, that all lines having
+ // the same twip size have the same pixel size, independent of their position
+ // on the screen.
+ Point aPaintStart = rDev.PixelToLogic( rDev.LogicToPixel( aStart ) );
+ Point aPaintEnd = rDev.PixelToLogic( rDev.LogicToPixel( aEnd ) );
+
+ if( pGlobalShell->GetWin() )
+ {
+ // The table borders do not use SwAlignRect, but all the other frames do.
+ // Therefore we tweak the outer borders a bit to achieve that the outer
+ // borders match the subsidiary lines of the upper:
+ if ( aStart.X() == aUpper.Left() )
+ aPaintStart.X() = aUpperAligned.Left();
+ else if ( aStart.X() == aUpper._Right() )
+ aPaintStart.X() = aUpperAligned._Right();
+ if ( aStart.Y() == aUpper.Top() )
+ aPaintStart.Y() = aUpperAligned.Top();
+ else if ( aStart.Y() == aUpper._Bottom() )
+ aPaintStart.Y() = aUpperAligned._Bottom();
+
+ if ( aEnd.X() == aUpper.Left() )
+ aPaintEnd.X() = aUpperAligned.Left();
+ else if ( aEnd.X() == aUpper._Right() )
+ aPaintEnd.X() = aUpperAligned._Right();
+ if ( aEnd.Y() == aUpper.Top() )
+ aPaintEnd.Y() = aUpperAligned.Top();
+ else if ( aEnd.Y() == aUpper._Bottom() )
+ aPaintEnd.Y() = aUpperAligned._Bottom();
+ }
+
+ aPaintStart.X() -= nTwipXCorr; // nHalfPixelSzW - 2 to assure that we do not leave the pixel
+ aPaintEnd.X() -= nTwipXCorr;
+ aPaintStart.Y() -= nTwipYCorr;
+ aPaintEnd.Y() -= nTwipYCorr;
+
+ // Here comes the painting stuff: Thank you, DR, great job!!!
+ if ( bHori )
+ {
+ mrTabFrm.ProcessPrimitives( svx::frame::CreateBorderPrimitives(
+ aPaintStart,
+ aPaintEnd,
+ aStyles[ 0 ], // current style
+ aStyles[ 1 ], // aLFromT
+ aStyles[ 2 ], // aLFromL
+ aStyles[ 3 ], // aLFromB
+ aStyles[ 4 ], // aRFromT
+ aStyles[ 5 ], // aRFromR
+ aStyles[ 6 ], // aRFromB
+ pTmpColor
+ )
+ );
+ }
+ else
+ {
+ mrTabFrm.ProcessPrimitives( svx::frame::CreateBorderPrimitives(
+ aPaintEnd,
+ aPaintStart,
+ aStyles[ 0 ], // current style
+ aStyles[ 4 ], // aBFromL
+ aStyles[ 5 ], // aBFromB
+ aStyles[ 6 ], // aBFromR
+ aStyles[ 1 ], // aTFromL
+ aStyles[ 2 ], // aTFromT
+ aStyles[ 3 ], // aTFromR
+ pTmpColor
+ )
+ );
+ }
+ }
+
+ ++aSetIter;
+ }
+
+ ++aIter;
+ }
+
+ // restore output device:
+ rDev.Pop();
+ rDev.SetDrawMode( nOldDrawMode );
+}
+
+// Finds the lines that join the line defined by (StartPoint, EndPoint) in either
+// StartPoint or Endpoint. The styles of these lines are required for DR's magic
+// line painting functions.
+void SwTabFrmPainter::FindStylesForLine( const Point& rStartPoint,
+ const Point& rEndPoint,
+ svx::frame::Style* pStyles,
+ bool bHori ) const
+{
+ // pStyles[ 1 ] = bHori ? aLFromT : TFromL
+ // pStyles[ 2 ] = bHori ? aLFromL : TFromT,
+ // pStyles[ 3 ] = bHori ? aLFromB : TFromR,
+ // pStyles[ 4 ] = bHori ? aRFromT : BFromL,
+ // pStyles[ 5 ] = bHori ? aRFromR : BFromB,
+ // pStyles[ 6 ] = bHori ? aRFromB : BFromR,
+
+ SwLineEntryMapConstIter aMapIter = maVertLines.find( rStartPoint.X() );
+ OSL_ENSURE( aMapIter != maVertLines.end(), "FindStylesForLine: Error" );
+ const SwLineEntrySet& rVertSet = (*aMapIter).second;
+ SwLineEntrySetConstIter aIter = rVertSet.begin();
+
+ while ( aIter != rVertSet.end() )
+ {
+ const SwLineEntry& rEntry = *aIter;
+ if ( bHori )
+ {
+ if ( rStartPoint.Y() == rEntry.mnStartPos )
+ pStyles[ 3 ] = rEntry.maAttribute;
+ else if ( rStartPoint.Y() == rEntry.mnEndPos )
+ pStyles[ 1 ] = rEntry.maAttribute;
+ }
+ else
+ {
+ if ( rStartPoint.Y() == rEntry.mnEndPos )
+ pStyles[ 2 ] = rEntry.maAttribute;
+ else if ( rEndPoint.Y() == rEntry.mnStartPos )
+ pStyles[ 5 ] = rEntry.maAttribute;
+ }
+ ++aIter;
+ }
+
+ aMapIter = maHoriLines.find( rStartPoint.Y() );
+ OSL_ENSURE( aMapIter != maHoriLines.end(), "FindStylesForLine: Error" );
+ const SwLineEntrySet& rHoriSet = (*aMapIter).second;
+ aIter = rHoriSet.begin();
+
+ while ( aIter != rHoriSet.end() )
+ {
+ const SwLineEntry& rEntry = *aIter;
+ if ( bHori )
+ {
+ if ( rStartPoint.X() == rEntry.mnEndPos )
+ pStyles[ 2 ] = rEntry.maAttribute;
+ else if ( rEndPoint.X() == rEntry.mnStartPos )
+ pStyles[ 5 ] = rEntry.maAttribute;
+ }
+ else
+ {
+ if ( rStartPoint.X() == rEntry.mnEndPos )
+ pStyles[ 1 ] = rEntry.maAttribute;
+ else if ( rStartPoint.X() == rEntry.mnStartPos )
+ pStyles[ 3 ] = rEntry.maAttribute;
+ }
+ ++aIter;
+ }
+
+ if ( bHori )
+ {
+ aMapIter = maVertLines.find( rEndPoint.X() );
+ OSL_ENSURE( aMapIter != maVertLines.end(), "FindStylesForLine: Error" );
+ const SwLineEntrySet& rVertSet2 = (*aMapIter).second;
+ aIter = rVertSet2.begin();
+
+ while ( aIter != rVertSet2.end() )
+ {
+ const SwLineEntry& rEntry = *aIter;
+ if ( rEndPoint.Y() == rEntry.mnStartPos )
+ pStyles[ 6 ] = rEntry.maAttribute;
+ else if ( rEndPoint.Y() == rEntry.mnEndPos )
+ pStyles[ 4 ] = rEntry.maAttribute;
+ ++aIter;
+ }
+ }
+ else
+ {
+ aMapIter = maHoriLines.find( rEndPoint.Y() );
+ OSL_ENSURE( aMapIter != maHoriLines.end(), "FindStylesForLine: Error" );
+ const SwLineEntrySet& rHoriSet2 = (*aMapIter).second;
+ aIter = rHoriSet2.begin();
+
+ while ( aIter != rHoriSet2.end() )
+ {
+ const SwLineEntry& rEntry = *aIter;
+ if ( rEndPoint.X() == rEntry.mnEndPos )
+ pStyles[ 4 ] = rEntry.maAttribute;
+ else if ( rEndPoint.X() == rEntry.mnStartPos )
+ pStyles[ 6 ] = rEntry.maAttribute;
+ ++aIter;
+ }
+ }
+}
+
+void SwTabFrmPainter::Insert( const SwFrm& rFrm, const SvxBoxItem& rBoxItem )
+{
+ std::vector< const SwFrm* > aTestVec;
+ aTestVec.push_back( &rFrm );
+ aTestVec.push_back( &rFrm );
+ aTestVec.push_back( &rFrm );
+
+ // build 4 line entries for the 4 borders:
+ SwRect aBorderRect = rFrm.Frm();
+ if ( rFrm.IsTabFrm() )
+ {
+ aBorderRect = rFrm.Prt();
+ aBorderRect.Pos() += rFrm.Frm().Pos();
+ }
+
+ const SwTwips nLeft = aBorderRect._Left();
+ const SwTwips nRight = aBorderRect._Right();
+ const SwTwips nTop = aBorderRect._Top();
+ const SwTwips nBottom = aBorderRect._Bottom();
+
+ svx::frame::Style aL( rBoxItem.GetLeft() );
+ svx::frame::Style aR( rBoxItem.GetRight() );
+ svx::frame::Style aT( rBoxItem.GetTop() );
+ svx::frame::Style aB( rBoxItem.GetBottom() );
+
+ const SwTwips nHalfTopWidth = aT.GetWidth() / 2;
+
+ aR.MirrorSelf();
+ aB.MirrorSelf();
+
+ bool bVert = mrTabFrm.IsVertical();
+ bool bR2L = mrTabFrm.IsRightToLeft();
+
+ aL.SetRefMode( svx::frame::REFMODE_CENTERED );
+ aR.SetRefMode( svx::frame::REFMODE_CENTERED );
+ aT.SetRefMode( !bVert ? svx::frame::REFMODE_BEGIN : svx::frame::REFMODE_END );
+ aB.SetRefMode( !bVert ? svx::frame::REFMODE_BEGIN : svx::frame::REFMODE_END );
+
+ SwLineEntry aLeft ( nLeft, nTop + nHalfTopWidth, nBottom + nHalfTopWidth, bVert ? aB : ( bR2L ? aR : aL ) );
+ SwLineEntry aRight ( nRight, nTop + nHalfTopWidth, nBottom + nHalfTopWidth, bVert ? aT : ( bR2L ? aL : aR ) );
+ SwLineEntry aTop ( nTop + nHalfTopWidth, nLeft, nRight, bVert ? aL : aT );
+ SwLineEntry aBottom( nBottom + nHalfTopWidth, nLeft, nRight, bVert ? aR : aB );
+
+ Insert( aLeft, false );
+ Insert( aRight, false );
+ Insert( aTop, true );
+ Insert( aBottom, true );
+
+ const SwRowFrm* pThisRowFrm = dynamic_cast<const SwRowFrm*>(rFrm.GetUpper());
+
+ // special case: #i9860#
+ // first line in follow table without repeated headlines
+ if ( pThisRowFrm &&
+ pThisRowFrm->GetUpper() == &mrTabFrm &&
+ mrTabFrm.IsFollow() &&
+ !mrTabFrm.GetTable()->GetRowsToRepeat() &&
+ (!pThisRowFrm->GetPrev() || static_cast<const SwRowFrm*>(pThisRowFrm->GetPrev())->IsRowSpanLine()) &&
+ !rBoxItem.GetTop() &&
+ rBoxItem.GetBottom() )
+ {
+ SwLineEntry aFollowTop( !bVert ? nTop : nRight, !bVert ? nLeft : nTop, !bVert ? nRight : nBottom, aB );
+ Insert( aFollowTop, !bVert );
+ }
+}
+
+void SwTabFrmPainter::Insert( SwLineEntry& rNew, bool bHori )
+{
+ // get all lines from structure, that have key entry of pLE
+ SwLineEntryMap* pLine2 = bHori ? &maHoriLines : &maVertLines;
+ const SwTwips nKey = rNew.mnKey;
+ SwLineEntryMapIter aMapIter = pLine2->find( nKey );
+
+ SwLineEntrySet* pLineSet = aMapIter != pLine2->end() ? &((*aMapIter).second) : 0;
+ if ( !pLineSet )
+ {
+ SwLineEntrySet aNewSet;
+ (*pLine2)[ nKey ] = aNewSet;
+ pLineSet = &(*pLine2)[ nKey ];
+ }
+ SwLineEntrySetIter aIter = pLineSet->begin();
+
+ while ( pLineSet && aIter != pLineSet->end() && rNew.mnStartPos < rNew.mnEndPos )
+ {
+ const SwLineEntry& rOld = *aIter;
+ const SwLineEntry::OverlapType nOverlapType = rOld.Overlaps( rNew );
+
+ const svx::frame::Style& rOldAttr = rOld.maAttribute;
+ const svx::frame::Style& rNewAttr = rNew.maAttribute;
+ const svx::frame::Style& rCmpAttr = rNewAttr > rOldAttr ? rNewAttr : rOldAttr;
+
+ if ( SwLineEntry::OVERLAP1 == nOverlapType )
+ {
+ OSL_ENSURE( rNew.mnStartPos >= rOld.mnStartPos, "Overlap type 3? How this?" );
+
+ // new left segment
+ const SwLineEntry aLeft( nKey, rOld.mnStartPos, rNew.mnStartPos, rOldAttr );
+
+ // new middle segment
+ const SwLineEntry aMiddle( nKey, rNew.mnStartPos, rOld.mnEndPos, rCmpAttr );
+
+ // new right segment
+ rNew.mnStartPos = rOld.mnEndPos;
+
+ // update current lines set
+ pLineSet->erase( aIter );
+ if ( aLeft.mnStartPos < aLeft.mnEndPos ) pLineSet->insert( aLeft );
+ if ( aMiddle.mnStartPos < aMiddle.mnEndPos ) pLineSet->insert( aMiddle );
+
+ aIter = pLineSet->begin();
+
+ continue; // start over
+ }
+ else if ( SwLineEntry::OVERLAP2 == nOverlapType )
+ {
+ // new left segment
+ const SwLineEntry aLeft( nKey, rOld.mnStartPos, rNew.mnStartPos, rOldAttr );
+
+ // new middle segment
+ const SwLineEntry aMiddle( nKey, rNew.mnStartPos, rNew.mnEndPos, rCmpAttr );
+
+ // new right segment
+ const SwLineEntry aRight( nKey, rNew.mnEndPos, rOld.mnEndPos, rOldAttr );
+
+ // update current lines set
+ pLineSet->erase( aIter );
+ if ( aLeft.mnStartPos < aLeft.mnEndPos ) pLineSet->insert( aLeft );
+ if ( aMiddle.mnStartPos < aMiddle.mnEndPos ) pLineSet->insert( aMiddle );
+ if ( aRight.mnStartPos < aRight.mnEndPos ) pLineSet->insert( aRight );
+
+ rNew.mnStartPos = rNew.mnEndPos; // rNew should not be inserted!
+
+ break; // we are finished
+ }
+ else if ( SwLineEntry::OVERLAP3 == nOverlapType )
+ {
+ // new left segment
+ const SwLineEntry aLeft( nKey, rNew.mnStartPos, rOld.mnStartPos, rNewAttr );
+
+ // new middle segment
+ const SwLineEntry aMiddle( nKey, rOld.mnStartPos, rNew.mnEndPos, rCmpAttr );
+
+ // new right segment
+ const SwLineEntry aRight( nKey, rNew.mnEndPos, rOld.mnEndPos, rOldAttr );
+
+ // update current lines set
+ pLineSet->erase( aIter );
+ if ( aLeft.mnStartPos < aLeft.mnEndPos ) pLineSet->insert( aLeft );
+ if ( aMiddle.mnStartPos < aMiddle.mnEndPos ) pLineSet->insert( aMiddle );
+ if ( aRight.mnStartPos < aRight.mnEndPos ) pLineSet->insert( aRight );
+
+ rNew.mnStartPos = rNew.mnEndPos; // rNew should not be inserted!
+
+ break; // we are finished
+ }
+
+ ++aIter;
+ }
+
+ if ( rNew.mnStartPos < rNew.mnEndPos ) // insert rest
+ pLineSet->insert( rNew );
+}
+
+//
+// FUNCTIONS USED FOR COLLAPSING TABLE BORDER LINES END
+//
+
+/*************************************************************************
+|*
+|* SwRootFrm::Paint()
+|*
+|* Beschreibung
+|* Fuer jede sichtbare Seite, die von Rect ber?hrt wird einmal Painten.
+|* 1. Umrandungen und Hintergruende Painten.
+|* 2. Den Draw Layer (Ramen und Zeichenobjekte) der unter dem Dokument
+|* liegt painten (Hoelle).
+|* 3. Den Dokumentinhalt (Text) Painten.
+|* 4. Den Drawlayer der ueber dem Dokuemnt liegt painten.
+|*
+|*************************************************************************/
+
+void
+SwRootFrm::Paint(SwRect const& rRect, SwPrintData const*const pPrintData) const
+{
+ OSL_ENSURE( Lower() && Lower()->IsPageFrm(), "Lower der Root keine Seite." );
+
+ PROTOCOL( this, PROT_FILE_INIT, 0, 0)
+
+ sal_Bool bResetRootPaint = sal_False;
+ ViewShell *pSh = pCurrShell;
+
+ if ( pSh->GetWin() )
+ {
+ if ( pSh->GetOut() == pSh->GetWin() && !pSh->GetWin()->IsVisible() )
+ {
+ return;
+ }
+ if ( SwRootFrm::bInPaint )
+ {
+ SwPaintQueue::Add( pSh, rRect );
+ return;
+ }
+ }
+ else
+ SwRootFrm::bInPaint = bResetRootPaint = sal_True;
+
+ SwSavePaintStatics *pStatics = 0;
+ if ( pGlobalShell )
+ pStatics = new SwSavePaintStatics();
+ pGlobalShell = pSh;
+
+ if( !pSh->GetWin() )
+ pProgress = SfxProgress::GetActiveProgress( (SfxObjectShell*) pSh->GetDoc()->GetDocShell() );
+
+ ::SwCalcPixStatics( pSh->GetOut() );
+ aGlobalRetoucheColor = pSh->Imp()->GetRetoucheColor();
+
+ //Ggf. eine Action ausloesen um klare Verhaeltnisse zu schaffen.
+ //Durch diesen Kunstgriff kann in allen Paints davon ausgegangen werden,
+ //das alle Werte gueltigt sind - keine Probleme, keine Sonderbehandlung(en).
+ // --> OD 2008-10-07 #i92745#
+ // Extend check on certain states of the 'current' <ViewShell> instance to
+ // all existing <ViewShell> instances.
+ bool bPerformLayoutAction( true );
+ {
+ ViewShell* pTmpViewShell = pSh;
+ do {
+ if ( pTmpViewShell->IsInEndAction() ||
+ pTmpViewShell->IsPaintInProgress() ||
+ ( pTmpViewShell->Imp()->IsAction() &&
+ pTmpViewShell->Imp()->GetLayAction().IsActionInProgress() ) )
+ {
+ bPerformLayoutAction = false;
+ }
+
+ pTmpViewShell = static_cast<ViewShell*>(pTmpViewShell->GetNext());
+ } while ( bPerformLayoutAction && pTmpViewShell != pSh );
+ }
+ if ( bPerformLayoutAction )
+ // <--
+ {
+ ((SwRootFrm*)this)->ResetTurbo();
+ SwLayAction aAction( (SwRootFrm*)this, pSh->Imp() );
+ aAction.SetPaint( sal_False );
+ aAction.SetComplete( sal_False );
+ aAction.SetReschedule( pProgress ? sal_True : sal_False );
+ aAction.Action();
+ ((SwRootFrm*)this)->ResetTurboFlag();
+ if ( !pSh->ActionPend() )
+ pSh->Imp()->DelRegion();
+ }
+
+ SwRect aRect( rRect );
+ aRect.Intersection( pSh->VisArea() );
+
+ const sal_Bool bExtraData = ::IsExtraData( GetFmt()->GetDoc() );
+
+ pLines = new SwLineRects; //Sammler fuer Umrandungen.
+
+ // #104289#. During painting, something (OLE) can
+ // load the linguistic, which in turn can cause a reformat
+ // of the document. Dangerous! We better set this flag to
+ // avoid the reformat.
+ const sal_Bool bOldAction = IsCallbackActionEnabled();
+ ((SwRootFrm*)this)->SetCallbackActionEnabled( sal_False );
+
+ const SwPageFrm *pPage = pSh->Imp()->GetFirstVisPage();
+
+ const bool bBookMode = pGlobalShell->GetViewOptions()->IsViewLayoutBookMode();
+ if ( bBookMode && pPage->GetPrev() && static_cast<const SwPageFrm*>(pPage->GetPrev())->IsEmptyPage() )
+ pPage = static_cast<const SwPageFrm*>(pPage->GetPrev());
+
+ // #i68597#
+ const bool bGridPainting(pSh->GetWin() && pSh->Imp()->HasDrawView() && pSh->Imp()->GetDrawView()->IsGridVisible());
+
+ // --> OD 2008-05-16 #i84659#
+// while ( pPage && !::IsShortCut( aRect, pPage->Frm() ) )
+ while ( pPage )
+ // <--
+ {
+ const bool bPaintRightShadow = pPage->IsRightShadowNeeded();
+ const bool bPaintLeftShadow = pPage->IsLeftShadowNeeded();
+ const bool bRightSidebar = pPage->SidebarPosition() == sw::sidebarwindows::SIDEBAR_RIGHT;
+
+ if ( !pPage->IsEmptyPage() )
+ {
+ SwRect aPaintRect;
+ SwPageFrm::GetBorderAndShadowBoundRect( pPage->Frm(), pSh, aPaintRect,
+ bPaintLeftShadow, bPaintRightShadow, bRightSidebar );
+
+ if ( aRect.IsOver( aPaintRect ) )
+ // <--
+ {
+ if ( pSh->GetWin() )
+ {
+ pSubsLines = new SwSubsRects;
+ // OD 18.11.2002 #99672# - create array for special sub-lines
+ pSpecSubsLines = new SwSubsRects;
+ }
+
+ aPaintRect._Intersection( aRect );
+
+ if ( bExtraData &&
+ pSh->GetWin() && pSh->IsInEndAction() )
+ {
+ // enlarge paint rectangle to complete page width, subtract
+ // current paint area and invalidate the resulting region.
+ SWRECTFN( pPage )
+ SwRect aPageRectTemp( aPaintRect );
+ (aPageRectTemp.*fnRect->fnSetLeftAndWidth)(
+ (pPage->Frm().*fnRect->fnGetLeft)(),
+ (pPage->Frm().*fnRect->fnGetWidth)() );
+ aPageRectTemp._Intersection( pSh->VisArea() );
+ Region aPageRectRegion( aPageRectTemp.SVRect() );
+ aPageRectRegion.Exclude( aPaintRect.SVRect() );
+ pSh->GetWin()->Invalidate( aPageRectRegion, INVALIDATE_CHILDREN );
+ }
+ // <--
+
+ // --> OD 2007-08-20 #i80793#
+ // enlarge paint rectangle for objects overlapping the same pixel
+ // in all cases and before the DrawingLayer overlay is initialized.
+ lcl_AdjustRectToPixelSize( aPaintRect, *(pSh->GetOut()) );
+ // <--
+
+ // #i68597#
+ // moved paint pre-process for DrawingLayer overlay here since the above
+ // code dependent from bExtraData may expand the PaintRect
+ {
+ // #i75172# if called from ViewShell::ImplEndAction it sould no longer
+ // really be used but handled by ViewShell::ImplEndAction already
+ const Region aDLRegion(aPaintRect.SVRect());
+ pSh->DLPrePaint2(aDLRegion);
+ }
+
+ if(OUTDEV_WINDOW == pGlobalShell->GetOut()->GetOutDevType())
+ {
+ /// OD 27.09.2002 #103636# - changed method SwLayVout::Enter(..)
+ /// 2nd parameter is no longer <const> and will be set to the
+ /// rectangle the virtual output device is calculated from <aPaintRect>,
+ /// if the virtual output is used.
+ pVout->Enter( pSh, aPaintRect, !bNoVirDev );
+
+ /// OD 27.09.2002 #103636# - adjust paint rectangle to pixel size
+ /// Thus, all objects overlapping on pixel level with the unadjusted
+ /// paint rectangle will be considered in the paint.
+ lcl_AdjustRectToPixelSize( aPaintRect, *(pSh->GetOut()) );
+ }
+
+ // maybe this can be put in the above scope. Since we are not sure, just leave it ATM
+ pVout->SetOrgRect( aPaintRect );
+
+ /// OD 29.08.2002 #102450#
+ /// determine background color of page for <PaintLayer> method
+ /// calls, paint <hell> or <heaven>
+ const Color aPageBackgrdColor = pPage->GetDrawBackgrdColor();
+
+ pPage->PaintBaBo( aPaintRect, pPage, sal_True );
+
+ if ( pSh->Imp()->HasDrawView() )
+ {
+ pLines->LockLines( sal_True );
+ // OD 29.08.2002 #102450# - add 3rd parameter
+ // OD 09.12.2002 #103045# - add 4th parameter for horizontal text direction.
+ const IDocumentDrawModelAccess* pIDDMA = pSh->getIDocumentDrawModelAccess();
+ pSh->Imp()->PaintLayer( pIDDMA->GetHellId(), pPrintData, aPaintRect,
+ &aPageBackgrdColor, (pPage->IsRightToLeft() ? true : false) );
+ pLines->PaintLines( pSh->GetOut() );
+ pLines->LockLines( sal_False );
+ }
+
+ if( pSh->GetWin() )
+ {
+ // OD 18.11.2002 #99672# - collect sub-lines
+ pPage->RefreshSubsidiary( aPaintRect );
+ // OD 18.11.2002 #99672# - paint special sub-lines
+ pSpecSubsLines->PaintSubsidiary( pSh->GetOut(), NULL );
+ }
+
+ pPage->Paint( aPaintRect );
+
+ // OD 20.12.2002 #94627# - no paint of page border and shadow, if
+ // writer is in place mode.
+ if( pSh->GetWin() && pSh->GetDoc()->GetDocShell() &&
+ !pSh->GetDoc()->GetDocShell()->IsInPlaceActive() )
+ {
+ // OD 12.02.2003 #i9719#, #105645# - use new method
+ // <SwPageFrm::PaintBorderAndShadow(..)>.
+ SwPageFrm::PaintBorderAndShadow( pPage->Frm(), pSh, bPaintLeftShadow, bPaintRightShadow, bRightSidebar );
+ SwPageFrm::PaintNotesSidebar( pPage->Frm(), pSh, pPage->GetPhyPageNum(), bRightSidebar);
+ }
+
+ pLines->PaintLines( pSh->GetOut() );
+
+ if ( pSh->Imp()->HasDrawView() )
+ {
+ /// OD 29.08.2002 #102450# - add 3rd parameter
+ // OD 09.12.2002 #103045# - add 4th parameter for horizontal text direction.
+ pSh->Imp()->PaintLayer( pSh->GetDoc()->GetHeavenId(), pPrintData, aPaintRect,
+ &aPageBackgrdColor,
+ (pPage->IsRightToLeft() ? true : false) );
+ }
+
+ if ( bExtraData )
+ pPage->RefreshExtraData( aPaintRect );
+
+ if ( pSh->GetWin() )
+ {
+ pSubsLines->PaintSubsidiary( pSh->GetOut(), pLines );
+ DELETEZ( pSubsLines );
+ DELETEZ( pSpecSubsLines );
+ }
+ pVout->Leave();
+
+ // #i68597#
+ // needed to move grid painting inside Begin/EndDrawLayer bounds and to change
+ // output rect for it accordingly
+ if(bGridPainting)
+ {
+ SdrPaintView* pPaintView = pSh->Imp()->GetDrawView();
+ SdrPageView* pPageView = pPaintView->GetSdrPageView();
+ pPageView->DrawPageViewGrid(*pSh->GetOut(), aPaintRect.SVRect(), SwViewOption::GetTextGridColor() );
+ }
+
+ // #i68597#
+ // moved paint post-process for DrawingLayer overlay here, see above
+ {
+ pSh->DLPostPaint2(true);
+ }
+ }
+ }
+ else if ( bBookMode && pSh->GetWin() && !pSh->GetDoc()->GetDocShell()->IsInPlaceActive() )
+ {
+ // paint empty page
+ SwRect aPaintRect;
+ SwRect aEmptyPageRect( pPage->Frm() );
+
+ // code from vprint.cxx
+ const SwPageFrm& rFormatPage = pPage->GetFormatPage();
+ aEmptyPageRect.SSize() = rFormatPage.Frm().SSize();
+
+ SwPageFrm::GetBorderAndShadowBoundRect( aEmptyPageRect, pSh, aPaintRect,
+ bPaintLeftShadow, bPaintRightShadow, bRightSidebar );
+ aPaintRect._Intersection( aRect );
+
+ if ( aRect.IsOver( aEmptyPageRect ) )
+ {
+ // #i75172# if called from ViewShell::ImplEndAction it sould no longer
+ // really be used but handled by ViewShell::ImplEndAction already
+ {
+ const Region aDLRegion(aPaintRect.SVRect());
+ pSh->DLPrePaint2(aDLRegion);
+ }
+
+ if( pSh->GetOut()->GetFillColor() != aGlobalRetoucheColor )
+ pSh->GetOut()->SetFillColor( aGlobalRetoucheColor );
+
+ pSh->GetOut()->SetLineColor(); // OD 20.02.2003 #107369# - no line color
+ // OD 20.02.2003 #107369# - use aligned page rectangle
+ {
+ SwRect aTmpPageRect( aEmptyPageRect );
+ ::SwAlignRect( aTmpPageRect, pSh );
+ aEmptyPageRect = aTmpPageRect;
+ }
+
+ pSh->GetOut()->DrawRect( aEmptyPageRect.SVRect() );
+
+ // paint empty page text
+ const Font& rEmptyPageFont = SwPageFrm::GetEmptyPageFont();
+ const Font aOldFont( pSh->GetOut()->GetFont() );
+
+ pSh->GetOut()->SetFont( rEmptyPageFont );
+ pSh->GetOut()->DrawText( aEmptyPageRect.SVRect(), SW_RESSTR( STR_EMPTYPAGE ),
+ TEXT_DRAW_VCENTER |
+ TEXT_DRAW_CENTER |
+ TEXT_DRAW_CLIP );
+
+ pSh->GetOut()->SetFont( aOldFont );
+ // paint shadow and border for empty page
+ // OD 19.02.2003 #107369# - use new method to paint page border and
+ // shadow
+ SwPageFrm::PaintBorderAndShadow( aEmptyPageRect, pSh, bPaintLeftShadow, bPaintRightShadow, bRightSidebar );
+ SwPageFrm::PaintNotesSidebar( aEmptyPageRect, pSh, pPage->GetPhyPageNum(), bRightSidebar);
+
+ {
+ pSh->DLPostPaint2(true);
+ }
+ }
+ }
+
+ OSL_ENSURE( !pPage->GetNext() || pPage->GetNext()->IsPageFrm(),
+ "Nachbar von Seite keine Seite." );
+ pPage = (SwPageFrm*)pPage->GetNext();
+ }
+
+ DELETEZ( pLines );
+
+ if ( bResetRootPaint )
+ SwRootFrm::bInPaint = sal_False;
+ if ( pStatics )
+ delete pStatics;
+ else
+ {
+ pProgress = 0;
+ pGlobalShell = 0;
+ }
+
+ ((SwRootFrm*)this)->SetCallbackActionEnabled( bOldAction );
+}
+
+/*************************************************************************
+|*
+|* SwLayoutFrm::Paint()
+|*
+|*************************************************************************/
+
+void MA_FASTCALL lcl_EmergencyFormatFtnCont( SwFtnContFrm *pCont )
+{
+ //Es kann sein, dass der Cont vernichtet wird.
+ SwCntntFrm *pCnt = pCont->ContainsCntnt();
+ while ( pCnt && pCnt->IsInFtn() )
+ {
+ pCnt->Calc();
+ pCnt = pCnt->GetNextCntntFrm();
+ }
+}
+
+class SwShortCut
+{
+ SwRectDist fnCheck;
+ long nLimit;
+public:
+ SwShortCut( const SwFrm& rFrm, const SwRect& rRect );
+ sal_Bool Stop( const SwRect& rRect ) const
+ { return (rRect.*fnCheck)( nLimit ) > 0; }
+};
+
+SwShortCut::SwShortCut( const SwFrm& rFrm, const SwRect& rRect )
+{
+ sal_Bool bVert = rFrm.IsVertical();
+ sal_Bool bR2L = rFrm.IsRightToLeft();
+ if( rFrm.IsNeighbourFrm() && bVert == bR2L )
+ {
+ if( bVert )
+ {
+ fnCheck = &SwRect::GetBottomDistance;
+ nLimit = rRect.Top();
+ }
+ else
+ {
+ fnCheck = &SwRect::GetLeftDistance;
+ nLimit = rRect.Left() + rRect.Width();
+ }
+ }
+ else if( bVert == rFrm.IsNeighbourFrm() )
+ {
+ fnCheck = &SwRect::GetTopDistance;
+ nLimit = rRect.Top() + rRect.Height();
+ }
+ else
+ {
+ //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin
+ if ( rFrm.IsVertLR() )
+ {
+ fnCheck = &SwRect::GetLeftDistance;
+ nLimit = rRect.Right();
+ }
+ else
+ {
+ fnCheck = &SwRect::GetRightDistance;
+ nLimit = rRect.Left();
+ }
+ }
+}
+
+void SwLayoutFrm::Paint(SwRect const& rRect, SwPrintData const*const) const
+{
+ ViewShell *pSh = getRootFrm()->GetCurrShell();
+
+ // --> FME 2004-06-24 #i16816# tagged pdf support
+ Frm_Info aFrmInfo( *this );
+ SwTaggedPDFHelper aTaggedPDFHelper( 0, &aFrmInfo, 0, *pSh->GetOut() );
+ // <--
+
+ const SwFrm *pFrm = Lower();
+ if ( !pFrm )
+ return;
+
+ SwShortCut aShortCut( *pFrm, rRect );
+ sal_Bool bCnt;
+ if ( sal_True == (bCnt = pFrm->IsCntntFrm()) )
+ pFrm->Calc();
+
+ if ( pFrm->IsFtnContFrm() )
+ {
+ ::lcl_EmergencyFormatFtnCont( (SwFtnContFrm*)pFrm );
+ pFrm = Lower();
+ }
+
+ const SwPageFrm *pPage = 0;
+ const sal_Bool bWin = pGlobalShell->GetWin() ? sal_True : sal_False;
+
+ while ( IsAnLower( pFrm ) )
+ {
+ SwRect aPaintRect( pFrm->PaintArea() );
+ if( aShortCut.Stop( aPaintRect ) )
+ break;
+ if ( bCnt && pProgress )
+ pProgress->Reschedule();
+
+ //Wenn ein Frm es explizit will muss retouchiert werden.
+ //Erst die Retouche, denn selbige koennte die aligned'en Raender
+ //plaetten.
+ if ( pFrm->IsRetouche() )
+ {
+ if ( pFrm->IsRetoucheFrm() && bWin && !pFrm->GetNext() )
+ { if ( !pPage )
+ pPage = FindPageFrm();
+ pFrm->Retouche( pPage, rRect );
+ }
+ pFrm->ResetRetouche();
+ }
+
+ if ( rRect.IsOver( aPaintRect ) )
+ {
+ if ( bCnt && pFrm->IsCompletePaint() &&
+ !rRect.IsInside( aPaintRect ) && GetpApp()->AnyInput( INPUT_KEYBOARD ) )
+ {
+ //fix(8104): Es kann vorkommen, dass die Verarbeitung nicht
+ //vollstaendig war, aber trotzdem Teile des Absatzes gepaintet
+ //werden. In der Folge werden dann evtl. wiederum andere Teile
+ //des Absatzes garnicht mehr gepaintet. Einziger Ausweg scheint
+ //hier ein Invalidieren der Windows zu sein.
+ //Um es nicht alzu Heftig werden zu lassen versuche ich hier
+ //das Rechteck zu begrenzen indem der gewuenschte Teil gepaintet
+ //und nur die uebrigen Absatzanteile invalidiert werden.
+ if ( aPaintRect.Left() == rRect.Left() &&
+ aPaintRect.Right() == rRect.Right() )
+ {
+ aPaintRect.Bottom( rRect.Top() - 1 );
+ if ( aPaintRect.Height() > 0 )
+ pGlobalShell->InvalidateWindows(aPaintRect);
+ aPaintRect.Top( rRect.Bottom() + 1 );
+ aPaintRect.Bottom( pFrm->Frm().Bottom() );
+ if ( aPaintRect.Height() > 0 )
+ pGlobalShell->InvalidateWindows(aPaintRect);
+ aPaintRect.Top( pFrm->Frm().Top() );
+ aPaintRect.Bottom( pFrm->Frm().Bottom() );
+ }
+ else
+ {
+ pGlobalShell->InvalidateWindows( aPaintRect );
+ pFrm = pFrm->GetNext();
+ if ( pFrm && (sal_True == (bCnt = pFrm->IsCntntFrm())) )
+ pFrm->Calc();
+ continue;
+ }
+ }
+ pFrm->ResetCompletePaint();
+ aPaintRect._Intersection( rRect );
+
+ pFrm->Paint( aPaintRect );
+
+ if ( Lower() && Lower()->IsColumnFrm() )
+ {
+ //Ggf. die Spaltentrennlinien malen. Fuer den Seitenbody ist
+ //nicht der Upper sondern die Seite Zustaendig.
+ const SwFrmFmt *pFmt = GetUpper() && GetUpper()->IsPageFrm()
+ ? GetUpper()->GetFmt()
+ : GetFmt();
+ const SwFmtCol &rCol = pFmt->GetCol();
+ if ( rCol.GetLineAdj() != COLADJ_NONE )
+ {
+ if ( !pPage )
+ pPage = pFrm->FindPageFrm();
+
+ PaintColLines( aPaintRect, rCol, pPage );
+ }
+ }
+ }
+ if ( !bCnt && pFrm->GetNext() && pFrm->GetNext()->IsFtnContFrm() )
+ ::lcl_EmergencyFormatFtnCont( (SwFtnContFrm*)pFrm->GetNext() );
+
+ pFrm = pFrm->GetNext();
+ if ( pFrm && (sal_True == (bCnt = pFrm->IsCntntFrm())) )
+ pFrm->Calc();
+ }
+}
+
+/** FlyFrm::IsBackgroundTransparent - for feature #99657#
+
+ OD 12.08.2002
+ determines, if background of fly frame has to be drawn transparent
+ declaration found in /core/inc/flyfrm.cxx
+ OD 08.10.2002 #103898# - If the background of the fly frame itself is not
+ transparent and the background is inherited from its parent/grandparent,
+ the background brush, used for drawing, has to be investigated for transparency.
+
+ @author OD
+
+ @return true, if background is transparent drawn.
+*/
+sal_Bool SwFlyFrm::IsBackgroundTransparent() const
+{
+ sal_Bool bBackgroundTransparent = GetFmt()->IsBackgroundTransparent();
+ if ( !bBackgroundTransparent &&
+ static_cast<const SwFlyFrmFmt*>(GetFmt())->IsBackgroundBrushInherited() )
+ {
+ const SvxBrushItem* pBackgrdBrush = 0;
+ const Color* pSectionTOXColor = 0;
+ SwRect aDummyRect;
+ if ( GetBackgroundBrush( pBackgrdBrush, pSectionTOXColor, aDummyRect, false) )
+ {
+ if ( pSectionTOXColor &&
+ (pSectionTOXColor->GetTransparency() != 0) &&
+ (pSectionTOXColor->GetColor() != COL_TRANSPARENT) )
+ {
+ bBackgroundTransparent = sal_True;
+ }
+ else if ( pBackgrdBrush )
+ {
+ if ( (pBackgrdBrush->GetColor().GetTransparency() != 0) &&
+ (pBackgrdBrush->GetColor() != COL_TRANSPARENT) )
+ {
+ bBackgroundTransparent = sal_True;
+ }
+ else
+ {
+ const GraphicObject *pTmpGrf =
+ static_cast<const GraphicObject*>(pBackgrdBrush->GetGraphicObject());
+ if ( (pTmpGrf) &&
+ (pTmpGrf->GetAttr().GetTransparency() != 0)
+ )
+ {
+ bBackgroundTransparent = sal_True;
+ }
+ }
+ }
+ }
+ }
+
+ return bBackgroundTransparent;
+};
+
+/** FlyFrm::IsShadowTransparent - for feature #99657#
+
+ OD 13.08.2002
+ determine, if shadow color of fly frame has to be drawn transparent
+ declaration found in /core/inc/flyfrm.cxx
+
+ @author OD
+
+ @return true, if shadow color is transparent.
+*/
+sal_Bool SwFlyFrm::IsShadowTransparent() const
+{
+ return GetFmt()->IsShadowTransparent();
+};
+
+/*************************************************************************
+|*
+|* SwFlyFrm::IsPaint()
+|*
+|*************************************************************************/
+
+sal_Bool SwFlyFrm::IsPaint( SdrObject *pObj, const ViewShell *pSh )
+{
+ SdrObjUserCall *pUserCall;
+
+ if ( 0 == ( pUserCall = GetUserCall(pObj) ) )
+ return sal_True;
+
+ //Attributabhaengig nicht fuer Drucker oder PreView painten
+ sal_Bool bPaint = pFlyOnlyDraw ||
+ ((SwContact*)pUserCall)->GetFmt()->GetPrint().GetValue();
+ if ( !bPaint )
+ bPaint = pSh->GetWin() && !pSh->IsPreView();
+
+ if ( bPaint )
+ {
+ //Das Paint kann evtl. von von uebergeordneten Flys verhindert werden.
+ SwFrm *pAnch = 0;
+ if ( pObj->ISA(SwVirtFlyDrawObj) )
+ {
+ SwFlyFrm *pFly = ((SwVirtFlyDrawObj*)pObj)->GetFlyFrm();
+ if ( pFlyOnlyDraw && pFlyOnlyDraw == pFly )
+ return sal_True;
+
+ //Die Anzeige eines Zwischenstadiums vermeiden, Flys die nicht mit
+ //der Seite auf der sie verankert sind ueberlappen werden auch
+ //nicht gepaintet.
+ //HACK: Ausnahme: Drucken von Rahmen in Tabellen, diese koennen
+ //bei uebergrossen Tabellen (HTML) schon mal auserhalb der Seite
+ //stehen.
+ SwPageFrm *pPage = pFly->FindPageFrm();
+ if ( pPage )
+ {
+ if ( pPage->Frm().IsOver( pFly->Frm() ) )
+ pAnch = pFly->AnchorFrm();
+ else if ( bTableHack &&
+ pFly->Frm().Top() >= pFly->GetAnchorFrm()->Frm().Top() &&
+ pFly->Frm().Top() < pFly->GetAnchorFrm()->Frm().Bottom() &&
+ long(pSh->GetOut()) ==
+ long(pSh->getIDocumentDeviceAccess()->getPrinter( false ) ) )
+ {
+ pAnch = pFly->AnchorFrm();
+ }
+ }
+
+ }
+ else
+ {
+ // OD 13.10.2003 #i19919# - consider 'virtual' drawing objects
+ // OD 2004-03-29 #i26791#
+ pAnch = ((SwDrawContact*)pUserCall)->GetAnchorFrm( pObj );
+ if ( pAnch )
+ {
+ if ( !pAnch->GetValidPosFlag() )
+ pAnch = 0;
+ else if ( long(pSh->GetOut()) == long(pSh->getIDocumentDeviceAccess()->getPrinter( false )))
+ {
+ //HACK: fuer das Drucken muessen wir ein paar Objekte
+ //weglassen, da diese sonst doppelt gedruckt werden.
+ //Die Objekte sollen gedruckt werden, wenn der TableHack
+ //gerade greift. In der Folge duerfen sie nicht gedruckt werden
+ //wenn sie mit der Seite dran sind, ueber der sie von der
+ //Position her gerade schweben.
+ const SwPageFrm *pPage = pAnch->FindPageFrm();
+ if ( !bTableHack &&
+ !pPage->Frm().IsOver( pObj->GetCurrentBoundRect() ) )
+ pAnch = 0;
+ }
+ }
+ else
+ {
+ // OD 02.07.2003 #108784# - debug assert
+ if ( !pObj->ISA(SdrObjGroup) )
+ {
+ OSL_FAIL( "<SwFlyFrm::IsPaint(..)> - paint of drawing object without anchor frame!?" );
+ }
+ }
+ }
+ if ( pAnch )
+ {
+ if ( pAnch->IsInFly() )
+ bPaint = SwFlyFrm::IsPaint( pAnch->FindFlyFrm()->GetVirtDrawObj(),
+ pSh );
+ else if ( pFlyOnlyDraw )
+ bPaint = sal_False;
+ }
+ else
+ bPaint = sal_False;
+ }
+ return bPaint;
+}
+
+/*************************************************************************
+|* SwCellFrm::Paint( const SwRect& ) const
+|*************************************************************************/
+void SwCellFrm::Paint(SwRect const& rRect, SwPrintData const*const) const
+{
+ if ( GetLayoutRowSpan() >= 1 )
+ SwLayoutFrm::Paint( rRect );
+}
+
+/*************************************************************************
+|*
+|* SwFlyFrm::Paint()
+|*
+|*************************************************************************/
+
+//Weiter unten definiert
+void MA_FASTCALL lcl_PaintLowerBorders( const SwLayoutFrm *pLay,
+ const SwRect &rRect, const SwPageFrm *pPage );
+
+void SwFlyFrm::Paint(SwRect const& rRect, SwPrintData const*const) const
+{
+ //wegen der Ueberlappung von Rahmen und Zeichenobjekten muessen die
+ //Flys ihre Umrandung (und die der Innenliegenden) direkt ausgeben.
+ //z.B. #33066#
+ pLines->LockLines(sal_True);
+
+ SwRect aRect( rRect );
+ aRect._Intersection( Frm() );
+
+ OutputDevice* pOut = pGlobalShell->GetOut();
+ pOut->Push( PUSH_CLIPREGION );
+ pOut->SetClipRegion();
+ const SwPageFrm* pPage = FindPageFrm();
+
+ const SwNoTxtFrm *pNoTxt = Lower() && Lower()->IsNoTxtFrm()
+ ? (SwNoTxtFrm*)Lower() : 0;
+
+ bool bIsChart = false; //#i102950# don't paint additional borders for charts
+ //check whether we have a chart
+ if(pNoTxt)
+ {
+ const SwNoTxtNode* pNoTNd = dynamic_cast<const SwNoTxtNode*>(pNoTxt->GetNode());
+ if( pNoTNd )
+ {
+ SwOLENode* pOLENd = const_cast<SwOLENode*>(pNoTNd->GetOLENode());
+ if( pOLENd && ChartPrettyPainter::IsChart( pOLENd->GetOLEObj().GetObject() ) )
+ bIsChart = true;
+ }
+ }
+
+ {
+ bool bContour = GetFmt()->GetSurround().IsContour();
+ PolyPolygon aPoly;
+ if ( bContour )
+ {
+ // OD 16.04.2003 #i13147# - add 2nd parameter with value <sal_True>
+ // to indicate that method is called for paint in order to avoid
+ // load of the intrinsic graphic.
+ bContour = GetContour( aPoly, sal_True );
+ }
+
+ // --> OD 2005-06-08 #i47804# - distinguish complete background paint
+ // and margin paint.
+ // paint complete background for Writer text fly frames
+ bool bPaintCompleteBack( !pNoTxt );
+ // <--
+ // paint complete background for transparent graphic and contour,
+ // if own background color exists.
+ const bool bIsGraphicTransparent = pNoTxt ? pNoTxt->IsTransparent() : false;
+ if ( !bPaintCompleteBack &&
+ ( bIsGraphicTransparent|| bContour ) )
+ {
+ const SvxBrushItem &rBack = GetFmt()->GetBackground();
+ // OD 07.08.2002 #99657# #GetTransChg#
+ // to determine, if background has to be painted, by checking, if
+ // background color is not COL_TRANSPARENT ("no fill"/"auto fill")
+ // or a background graphic exists.
+ bPaintCompleteBack = !(rBack.GetColor() == COL_TRANSPARENT) ||
+ rBack.GetGraphicPos() != GPOS_NONE;
+ }
+ // paint of margin needed.
+ const bool bPaintMarginOnly( !bPaintCompleteBack &&
+ Prt().SSize() != Frm().SSize() );
+
+ // --> OD 2005-06-08 #i47804# - paint background of parent fly frame
+ // for transparent graphics in layer Hell, if parent fly frame isn't
+ // in layer Hell. It's only painted the intersection between the
+ // parent fly frame area and the paint area <aRect>
+ const IDocumentDrawModelAccess* pIDDMA = GetFmt()->getIDocumentDrawModelAccess();
+
+ if ( bIsGraphicTransparent &&
+ GetVirtDrawObj()->GetLayer() == pIDDMA->GetHellId() &&
+ GetAnchorFrm()->FindFlyFrm() )
+ {
+ const SwFlyFrm* pParentFlyFrm = GetAnchorFrm()->FindFlyFrm();
+ if ( pParentFlyFrm->GetDrawObj()->GetLayer() !=
+ pIDDMA->GetHellId() )
+ {
+ SwFlyFrm* pOldRet = pRetoucheFly2;
+ pRetoucheFly2 = const_cast<SwFlyFrm*>(this);
+
+ SwBorderAttrAccess aAccess( SwFrm::GetCache(), pParentFlyFrm );
+ const SwBorderAttrs &rAttrs = *aAccess.Get();
+ SwRect aPaintRect( aRect );
+ aPaintRect._Intersection( pParentFlyFrm->Frm() );
+ pParentFlyFrm->PaintBackground( aPaintRect, pPage, rAttrs, sal_False, sal_False );
+
+ pRetoucheFly2 = pOldRet;
+ }
+ }
+
+ if ( bPaintCompleteBack || bPaintMarginOnly )
+ {
+ //#24926# JP 01.02.96, PaintBaBo in teilen hier, damit PaintBorder
+ //das orig. Rect bekommt, aber PaintBackground das begrenzte.
+
+ // OD 2004-04-23 #116347#
+ pOut->Push( PUSH_FILLCOLOR|PUSH_LINECOLOR );
+ pOut->SetLineColor();
+
+ pPage = FindPageFrm();
+
+ SwBorderAttrAccess aAccess( SwFrm::GetCache(), (SwFrm*)this );
+ const SwBorderAttrs &rAttrs = *aAccess.Get();
+
+ // paint background
+ {
+ SwRegionRects aRegion( aRect );
+ // --> OD 2007-12-13 #i80822#
+ // suppress painting of background in printing area for
+ // non-transparent graphics.
+ if ( bPaintMarginOnly ||
+ ( pNoTxt && !bIsGraphicTransparent ) )
+ // <--
+ {
+ //Was wir eigentlich Painten wollen ist der schmale Streifen
+ //zwischen PrtArea und aeusserer Umrandung.
+ SwRect aTmp( Prt() ); aTmp += Frm().Pos();
+ aRegion -= aTmp;
+ }
+ if ( bContour )
+ {
+ pOut->Push();
+ // --> OD 2007-12-13 #i80822#
+ // apply clip region under the same conditions, which are
+ // used in <SwNoTxtFrm::Paint(..)> to set the clip region
+ // for painting the graphic/OLE. Thus, the clip region is
+ // also applied for the PDF export.
+ ViewShell *pSh = getRootFrm()->GetCurrShell();
+ if ( !pOut->GetConnectMetaFile() || !pSh || !pSh->GetWin() )
+ // <--
+ {
+ pOut->SetClipRegion( aPoly );
+ }
+ for ( sal_uInt16 i = 0; i < aRegion.Count(); ++i )
+ PaintBackground( aRegion[i], pPage, rAttrs, sal_False, sal_True );
+ pOut->Pop();
+ }
+ else
+ for ( sal_uInt16 i = 0; i < aRegion.Count(); ++i )
+ PaintBackground( aRegion[i], pPage, rAttrs, sal_False, sal_True );
+ }
+
+ // OD 06.08.2002 #99657# - paint border before painting background
+ // paint border
+ {
+ SwRect aTmp( rRect );
+ PaintBorder( aTmp, pPage, rAttrs );
+ }
+
+ pOut->Pop();
+ }
+ }
+
+ // OD 19.12.2002 #106318# - fly frame will paint it's subsidiary lines and
+ // the subsidiary lines of its lowers on its own, due to overlapping with
+ // other fly frames or other objects.
+ if( pGlobalShell->GetWin()
+ && !bIsChart ) //#i102950# don't paint additional borders for charts
+ {
+ bool bSubsLineRectsCreated;
+ if ( pSubsLines )
+ {
+ // Lock already existing subsidiary lines
+ pSubsLines->LockLines( sal_True );
+ bSubsLineRectsCreated = false;
+ }
+ else
+ {
+ // create new subsidiardy lines
+ pSubsLines = new SwSubsRects;
+ bSubsLineRectsCreated = true;
+ }
+
+ bool bSpecSubsLineRectsCreated;
+ if ( pSpecSubsLines )
+ {
+ // Lock already existing special subsidiary lines
+ pSpecSubsLines->LockLines( sal_True );
+ bSpecSubsLineRectsCreated = false;
+ }
+ else
+ {
+ // create new special subsidiardy lines
+ pSpecSubsLines = new SwSubsRects;
+ bSpecSubsLineRectsCreated = true;
+ }
+ // Add subsidiary lines of fly frame and its lowers
+ RefreshLaySubsidiary( pPage, aRect );
+ // paint subsidiary lines of fly frame and its lowers
+ pSpecSubsLines->PaintSubsidiary( pOut, NULL );
+ pSubsLines->PaintSubsidiary( pOut, pLines );
+ if ( !bSubsLineRectsCreated )
+ // unlock subsidiary lines
+ pSubsLines->LockLines( sal_False );
+ else
+ // delete created subsidiary lines container
+ DELETEZ( pSubsLines );
+
+ if ( !bSpecSubsLineRectsCreated )
+ // unlock special subsidiary lines
+ pSpecSubsLines->LockLines( sal_False );
+ else
+ {
+ // delete created special subsidiary lines container
+ DELETEZ( pSpecSubsLines );
+ }
+ }
+
+ SwLayoutFrm::Paint( aRect );
+
+ Validate();
+
+ // OD 19.12.2002 #106318# - first paint lines added by fly frame paint
+ // and then unlock other lines.
+ pLines->PaintLines( pOut );
+ pLines->LockLines( sal_False );
+
+ pOut->Pop();
+
+ if ( pProgress && pNoTxt )
+ pProgress->Reschedule();
+}
+/*************************************************************************
+|*
+|* SwTabFrm::Paint()
+|*
+|*************************************************************************/
+
+void SwTabFrm::Paint(SwRect const& rRect, SwPrintData const*const) const
+{
+ if ( pGlobalShell->GetViewOptions()->IsTable() )
+ {
+ // --> collapsing borders FME 2005-05-27 #i29550#
+ if ( IsCollapsingBorders() )
+ {
+ SwBorderAttrAccess aAccess( SwFrm::GetCache(), (SwFrm*)this );
+ const SwBorderAttrs &rAttrs = *aAccess.Get();
+
+ // paint shadow
+ if ( rAttrs.GetShadow().GetLocation() != SVX_SHADOW_NONE )
+ {
+ SwRect aRect;
+ ::lcl_CalcBorderRect( aRect, this, rAttrs, sal_True );
+ PaintShadow( rRect, aRect, rAttrs );
+ }
+
+ // paint lines
+ SwTabFrmPainter aHelper( *this );
+ aHelper.PaintLines( *pGlobalShell->GetOut(), rRect );
+ }
+ // <-- collapsing
+
+ SwLayoutFrm::Paint( rRect );
+ }
+ // OD 10.01.2003 #i6467# - no light grey rectangle for page preview
+ else if ( pGlobalShell->GetWin() && !pGlobalShell->IsPreView() )
+ {
+ // OD 10.01.2003 #i6467# - intersect output rectangle with table frame
+ SwRect aTabRect( Prt() );
+ aTabRect.Pos() += Frm().Pos();
+ SwRect aTabOutRect( rRect );
+ aTabOutRect.Intersection( aTabRect );
+ pGlobalShell->GetViewOptions()->
+ DrawRect( pGlobalShell->GetOut(), aTabOutRect, COL_LIGHTGRAY );
+ }
+ ((SwTabFrm*)this)->ResetComplete();
+}
+
+/*************************************************************************
+|*
+|* SwFrm::PaintShadow()
+|*
+|* Beschreibung Malt einen Schatten wenns das FrmFormat fordert.
+|* Der Schatten wird immer an den auesseren Rand des OutRect gemalt.
+|* Das OutRect wird ggf. so verkleinert, dass auf diesem das
+|* malen der Umrandung stattfinden kann.
+|*
+|*************************************************************************/
+/// OD 23.08.2002 #99657#
+/// draw full shadow rectangle for frames with transparent drawn backgrounds.
+void SwFrm::PaintShadow( const SwRect& rRect, SwRect& rOutRect,
+ const SwBorderAttrs &rAttrs ) const
+{
+ const SvxShadowItem &rShadow = rAttrs.GetShadow();
+ const long nWidth = ::lcl_AlignWidth ( rShadow.GetWidth() );
+ const long nHeight = ::lcl_AlignHeight( rShadow.GetWidth() );
+
+ SwRects aRegion( 2, 2 );
+ SwRect aOut( rOutRect );
+
+ const sal_Bool bCnt = IsCntntFrm();
+ const sal_Bool bTop = !bCnt || rAttrs.GetTopLine ( *(this) ) ? sal_True : sal_False;
+ const sal_Bool bBottom = !bCnt || rAttrs.GetBottomLine( *(this) ) ? sal_True : sal_False;
+
+ SvxShadowLocation eLoc = rShadow.GetLocation();
+
+ SWRECTFN( this )
+ if( IsVertical() )
+ {
+ switch( eLoc )
+ {
+ case SVX_SHADOW_BOTTOMRIGHT: eLoc = SVX_SHADOW_BOTTOMLEFT; break;
+ case SVX_SHADOW_TOPLEFT: eLoc = SVX_SHADOW_TOPRIGHT; break;
+ case SVX_SHADOW_TOPRIGHT: eLoc = SVX_SHADOW_BOTTOMRIGHT; break;
+ case SVX_SHADOW_BOTTOMLEFT: eLoc = SVX_SHADOW_TOPLEFT; break;
+ default: break;
+ }
+ }
+
+ /// OD 23.08.2002 #99657# - determine, if full shadow rectangle have to
+ /// be drawn or only two shadow rectangles beside the frame.
+ /// draw full shadow rectangle, if frame background is drawn transparent.
+ /// Status Quo:
+ /// SwLayoutFrm can have transparent drawn backgrounds. Thus,
+ /// "asked" their frame format.
+ sal_Bool bDrawFullShadowRectangle =
+ ( IsLayoutFrm() &&
+ (static_cast<const SwLayoutFrm*>(this))->GetFmt()->IsBackgroundTransparent()
+ );
+ switch ( eLoc )
+ {
+ case SVX_SHADOW_BOTTOMRIGHT:
+ {
+ if ( bDrawFullShadowRectangle )
+ {
+ /// OD 06.08.2002 #99657# - draw full shadow rectangle
+ aOut.Top( aOut.Top() + nHeight );
+ aOut.Left( aOut.Left() + nWidth );
+ aRegion.Insert( aOut, aRegion.Count() );
+ }
+ else
+ {
+ aOut.Top ( aOut.Bottom() - nHeight );
+ aOut.Left( aOut.Left() + nWidth );
+ if ( bBottom )
+ aRegion.Insert( aOut, aRegion.Count() );
+ aOut.Left( aOut.Right() - nWidth );
+ aOut.Top ( rOutRect.Top() + nHeight );
+ if ( bBottom )
+ aOut.Bottom( aOut.Bottom() - nHeight );
+ if ( bCnt && (!bTop || !bBottom) )
+ ::lcl_ExtendLeftAndRight( aOut, *(this), rAttrs, fnRect );
+ aRegion.Insert( aOut, aRegion.Count() );
+ }
+
+ rOutRect.Right ( rOutRect.Right() - nWidth );
+ rOutRect.Bottom( rOutRect.Bottom()- nHeight );
+ }
+ break;
+ case SVX_SHADOW_TOPLEFT:
+ {
+ if ( bDrawFullShadowRectangle )
+ {
+ /// OD 06.08.2002 #99657# - draw full shadow rectangle
+ aOut.Bottom( aOut.Bottom() - nHeight );
+ aOut.Right( aOut.Right() - nWidth );
+ aRegion.Insert( aOut, aRegion.Count() );
+ }
+ else
+ {
+ aOut.Bottom( aOut.Top() + nHeight );
+ aOut.Right ( aOut.Right() - nWidth );
+ if ( bTop )
+ aRegion.Insert( aOut, aRegion.Count() );
+ aOut.Right ( aOut.Left() + nWidth );
+ aOut.Bottom( rOutRect.Bottom() - nHeight );
+ if ( bTop )
+ aOut.Top( aOut.Top() + nHeight );
+ if ( bCnt && (!bBottom || !bTop) )
+ ::lcl_ExtendLeftAndRight( aOut, *(this), rAttrs, fnRect );
+ aRegion.Insert( aOut, aRegion.Count() );
+ }
+
+ rOutRect.Left( rOutRect.Left() + nWidth );
+ rOutRect.Top( rOutRect.Top() + nHeight );
+ }
+ break;
+ case SVX_SHADOW_TOPRIGHT:
+ {
+ if ( bDrawFullShadowRectangle )
+ {
+ /// OD 06.08.2002 #99657# - draw full shadow rectangle
+ aOut.Bottom( aOut.Bottom() - nHeight);
+ aOut.Left( aOut.Left() + nWidth );
+ aRegion.Insert( aOut, aRegion.Count() );
+ }
+ else
+ {
+ aOut.Bottom( aOut.Top() + nHeight );
+ aOut.Left ( aOut.Left()+ nWidth );
+ if ( bTop )
+ aRegion.Insert( aOut, aRegion.Count() );
+ aOut.Left ( aOut.Right() - nWidth );
+ aOut.Bottom( rOutRect.Bottom() - nHeight );
+ if ( bTop )
+ aOut.Top( aOut.Top() + nHeight );
+ if ( bCnt && (!bBottom || bTop) )
+ ::lcl_ExtendLeftAndRight( aOut, *(this), rAttrs, fnRect );
+ aRegion.Insert( aOut, aRegion.Count() );
+ }
+
+ rOutRect.Right( rOutRect.Right() - nWidth );
+ rOutRect.Top( rOutRect.Top() + nHeight );
+ }
+ break;
+ case SVX_SHADOW_BOTTOMLEFT:
+ {
+ if ( bDrawFullShadowRectangle )
+ {
+ /// OD 06.08.2002 #99657# - draw full shadow rectangle
+ aOut.Top( aOut.Top() + nHeight );
+ aOut.Right( aOut.Right() - nWidth );
+ aRegion.Insert( aOut, aRegion.Count() );
+ }
+ else
+ {
+ aOut.Top ( aOut.Bottom()- nHeight );
+ aOut.Right( aOut.Right() - nWidth );
+ if ( bBottom )
+ aRegion.Insert( aOut, aRegion.Count() );
+ aOut.Right( aOut.Left() + nWidth );
+ aOut.Top( rOutRect.Top() + nHeight );
+ if ( bBottom )
+ aOut.Bottom( aOut.Bottom() - nHeight );
+ if ( bCnt && (!bTop || !bBottom) )
+ ::lcl_ExtendLeftAndRight( aOut, *(this), rAttrs, fnRect );
+ aRegion.Insert( aOut, aRegion.Count() );
+ }
+
+ rOutRect.Left( rOutRect.Left() + nWidth );
+ rOutRect.Bottom( rOutRect.Bottom() - nHeight );
+ }
+ break;
+ default:
+ OSL_ENSURE( !this, "new ShadowLocation() ?" );
+ break;
+ }
+
+ OutputDevice *pOut = pGlobalShell->GetOut();
+
+ sal_uLong nOldDrawMode = pOut->GetDrawMode();
+ Color aShadowColor( rShadow.GetColor() );
+ if( aRegion.Count() && pGlobalShell->GetWin() &&
+ Application::GetSettings().GetStyleSettings().GetHighContrastMode() )
+ {
+ // Is heigh contrast mode, the output device has already set the
+ // DRAWMODE_SETTINGSFILL flag. This causes the SetFillColor function
+ // to ignore the setting of a new color. Therefore we have to reset
+ // the drawing mode
+ pOut->SetDrawMode( 0 );
+ aShadowColor = SwViewOption::GetFontColor();
+ }
+
+ if ( pOut->GetFillColor() != aShadowColor )
+ pOut->SetFillColor( aShadowColor );
+
+ pOut->SetDrawMode( nOldDrawMode );
+
+ for ( sal_uInt16 i = 0; i < aRegion.Count(); ++i )
+ {
+ SwRect &rOut = aRegion[i];
+ aOut = rOut;
+ // OD 30.09.2002 #103636# - no SwAlign of shadow rectangle
+ // no alignment necessary, because (1) <rRect> is already aligned
+ // and because (2) paint of border and background will occur later.
+ // Thus, (1) assures that no conflicts with neighbour object will occure
+ // and (2) assures that border and background is not affected by the
+ // shadow paint.
+ /*
+ ::SwAlignRect( aOut, pGlobalShell );
+ */
+ if ( rRect.IsOver( aOut ) && aOut.Height() > 0 && aOut.Width() > 0 )
+ {
+ aOut._Intersection( rRect );
+ pOut->DrawRect( aOut.SVRect() );
+ }
+ }
+}
+
+/*************************************************************************
+|*
+|* SwFrm::PaintBorderLine()
+|*
+|*************************************************************************/
+
+void SwFrm::PaintBorderLine( const SwRect& rRect,
+ const SwRect& rOutRect,
+ const SwPageFrm *pPage,
+ const Color *pColor,
+ const SvxBorderStyle nStyle ) const
+{
+ if ( !rOutRect.IsOver( rRect ) )
+ return;
+
+ SwRect aOut( rOutRect );
+ aOut._Intersection( rRect );
+
+ const SwTabFrm *pTab = IsCellFrm() ? FindTabFrm() : 0;
+ sal_uInt8 nSubCol = ( IsCellFrm() || IsRowFrm() ) ? SUBCOL_TAB :
+ ( IsInSct() ? SUBCOL_SECT :
+ ( IsInFly() ? SUBCOL_FLY : SUBCOL_PAGE ) );
+ if( pColor && pGlobalShell->GetWin() &&
+ Application::GetSettings().GetStyleSettings().GetHighContrastMode() )
+ {
+ pColor = &SwViewOption::GetFontColor();
+ }
+
+ if ( pPage->GetSortedObjs() )
+ {
+ SwRegionRects aRegion( aOut, 4, 1 );
+ ::lcl_SubtractFlys( this, pPage, aOut, aRegion );
+ for ( sal_uInt16 i = 0; i < aRegion.Count(); ++i )
+ pLines->AddLineRect( aRegion[i], pColor, nStyle, pTab, nSubCol );
+ }
+ else
+ pLines->AddLineRect( aOut, pColor, nStyle, pTab, nSubCol );
+}
+
+/*************************************************************************
+|*
+|* SwFrm::PaintBorderLines()
+|*
+|* Beschreibung Nur alle Linien einfach oder alle Linien doppelt!!!!
+|*
+|*************************************************************************/
+
+// OD 29.04.2003 #107169# - method called for left and right border rectangles.
+// For a printer output device perform adjustment for non-overlapping top and
+// bottom border rectangles. Thus, add parameter <_bPrtOutputDev> to indicate
+// printer output device.
+// NOTE: For printer output device left/right border rectangle <_iorRect>
+// has to be already non-overlapping the outer top/bottom border rectangle.
+void MA_FASTCALL lcl_SubTopBottom( SwRect& _iorRect,
+ const SvxBoxItem& _rBox,
+ const SwBorderAttrs& _rAttrs,
+ const SwFrm& _rFrm,
+ const SwRectFn& _rRectFn,
+ const sal_Bool _bPrtOutputDev )
+{
+ const sal_Bool bCnt = _rFrm.IsCntntFrm();
+ if ( _rBox.GetTop() && _rBox.GetTop()->GetInWidth() &&
+ ( !bCnt || _rAttrs.GetTopLine( _rFrm ) )
+ )
+ {
+ // substract distance between outer and inner line.
+ SwTwips nDist = ::lcl_MinHeightDist( _rBox.GetTop()->GetDistance() );
+ // OD 19.05.2003 #109667# - non-overlapping border rectangles:
+ // adjust x-/y-position, if inner top line is a hair line (width = 1)
+ sal_Bool bIsInnerTopLineHairline = sal_False;
+ if ( !_bPrtOutputDev )
+ {
+ // additionally substract width of top outer line
+ // --> left/right inner/outer line doesn't overlap top outer line.
+ nDist += ::lcl_AlignHeight( _rBox.GetTop()->GetOutWidth() );
+ }
+ else
+ {
+ // OD 29.04.2003 #107169# - additionally substract width of top inner line
+ // --> left/right inner/outer line doesn't overlap top inner line.
+ nDist += ::lcl_AlignHeight( _rBox.GetTop()->GetInWidth() );
+ bIsInnerTopLineHairline = _rBox.GetTop()->GetInWidth() == 1;
+ }
+ (_iorRect.*_rRectFn->fnSubTop)( -nDist );
+ // OD 19.05.2003 #109667# - adjust calculated border top, if inner top line
+ // is a hair line
+ if ( bIsInnerTopLineHairline )
+ {
+ if ( _rFrm.IsVertical() )
+ {
+ // right of border rectangle has to be checked and adjusted
+ Point aCompPt( _iorRect.Right(), 0 );
+ Point aRefPt( aCompPt.X() + 1, aCompPt.Y() );
+ lcl_CompPxPosAndAdjustPos( *(pGlobalShell->GetOut()),
+ aRefPt, aCompPt,
+ sal_True, -1 );
+ _iorRect.Right( aCompPt.X() );
+ }
+ else
+ {
+ // top of border rectangle has to be checked and adjusted
+ Point aCompPt( 0, _iorRect.Top() );
+ Point aRefPt( aCompPt.X(), aCompPt.Y() - 1 );
+ lcl_CompPxPosAndAdjustPos( *(pGlobalShell->GetOut()),
+ aRefPt, aCompPt,
+ sal_False, +1 );
+ _iorRect.Top( aCompPt.Y() );
+ }
+ }
+ }
+
+ if ( _rBox.GetBottom() && _rBox.GetBottom()->GetInWidth() &&
+ ( !bCnt || _rAttrs.GetBottomLine( _rFrm ) )
+ )
+ {
+ // substract distance between outer and inner line.
+ SwTwips nDist = ::lcl_MinHeightDist( _rBox.GetBottom()->GetDistance() );
+ // OD 19.05.2003 #109667# - non-overlapping border rectangles:
+ // adjust x-/y-position, if inner bottom line is a hair line (width = 1)
+ sal_Bool bIsInnerBottomLineHairline = sal_False;
+ if ( !_bPrtOutputDev )
+ {
+ // additionally substract width of bottom outer line
+ // --> left/right inner/outer line doesn't overlap bottom outer line.
+ nDist += ::lcl_AlignHeight( _rBox.GetBottom()->GetOutWidth() );
+ }
+ else
+ {
+ // OD 29.04.2003 #107169# - additionally substract width of bottom inner line
+ // --> left/right inner/outer line doesn't overlap bottom inner line.
+ nDist += ::lcl_AlignHeight( _rBox.GetBottom()->GetInWidth() );
+ bIsInnerBottomLineHairline = _rBox.GetBottom()->GetInWidth() == 1;
+ }
+ (_iorRect.*_rRectFn->fnAddBottom)( -nDist );
+ // OD 19.05.2003 #109667# - adjust calculated border bottom, if inner
+ // bottom line is a hair line.
+ if ( bIsInnerBottomLineHairline )
+ {
+ if ( _rFrm.IsVertical() )
+ {
+ // left of border rectangle has to be checked and adjusted
+ Point aCompPt( _iorRect.Left(), 0 );
+ Point aRefPt( aCompPt.X() - 1, aCompPt.Y() );
+ lcl_CompPxPosAndAdjustPos( *(pGlobalShell->GetOut()),
+ aRefPt, aCompPt,
+ sal_True, +1 );
+ _iorRect.Left( aCompPt.X() );
+ }
+ else
+ {
+ // bottom of border rectangle has to be checked and adjusted
+ Point aCompPt( 0, _iorRect.Bottom() );
+ Point aRefPt( aCompPt.X(), aCompPt.Y() + 1 );
+ lcl_CompPxPosAndAdjustPos( *(pGlobalShell->GetOut()),
+ aRefPt, aCompPt,
+ sal_False, -1 );
+ _iorRect.Bottom( aCompPt.Y() );
+ }
+ }
+ }
+}
+
+// method called for top and bottom border rectangles.
+void MA_FASTCALL lcl_SubLeftRight( SwRect& rRect,
+ const SvxBoxItem& rBox,
+ const SwRectFn& rRectFn )
+{
+ if ( rBox.GetLeft() && rBox.GetLeft()->GetInWidth() )
+ {
+ const long nDist = ::lcl_MinWidthDist( rBox.GetLeft()->GetDistance() )
+ + ::lcl_AlignWidth( rBox.GetLeft()->GetOutWidth() );
+ (rRect.*rRectFn->fnSubLeft)( -nDist );
+ }
+
+ if ( rBox.GetRight() && rBox.GetRight()->GetInWidth() )
+ {
+ const long nDist = ::lcl_MinWidthDist( rBox.GetRight()->GetDistance() )
+ + ::lcl_AlignWidth( rBox.GetRight()->GetOutWidth() );
+ (rRect.*rRectFn->fnAddRight)( -nDist );
+ }
+}
+
+sal_uInt16 lcl_GetLineWidth( const SvxBorderLine* pLine )
+{
+ sal_uInt16 result = 0;
+
+ if ( pLine != NULL )
+ result = pLine->GetScaledWidth();
+
+ return result;
+}
+
+double lcl_GetExtent( const SvxBorderLine* pSideLine, const SvxBorderLine* pOppositeLine )
+{
+ double nExtent = 0.0;
+
+ if ( pSideLine && !pSideLine->isEmpty() )
+ nExtent = -lcl_GetLineWidth( pSideLine ) / 2.0;
+ else if ( pOppositeLine )
+ nExtent = lcl_GetLineWidth( pOppositeLine ) / 2.0;
+
+ return nExtent;
+}
+
+// OD 19.05.2003 #109667# - merge <lcl_PaintLeftLine> and <lcl_PaintRightLine>
+// into new method <lcl_PaintLeftRightLine(..)>
+void lcl_PaintLeftRightLine( const sal_Bool _bLeft,
+ const SwFrm& _rFrm,
+ const SwPageFrm& /*_rPage*/,
+ const SwRect& _rOutRect,
+ const SwRect& /*_rRect*/,
+ const SwBorderAttrs& _rAttrs,
+ const SwRectFn& _rRectFn )
+{
+ const SvxBoxItem& rBox = _rAttrs.GetBox();
+ const sal_Bool bR2L = _rFrm.IsCellFrm() && _rFrm.IsRightToLeft();
+ const SvxBorderLine* pLeftRightBorder = 0;
+ const SvxBorderLine* pTopBorder = rBox.GetTop();
+ const SvxBorderLine* pBottomBorder = rBox.GetBottom();
+
+ if ( _bLeft )
+ {
+ pLeftRightBorder = bR2L ? rBox.GetRight() : rBox.GetLeft();
+ }
+ else
+ {
+ pLeftRightBorder = bR2L ? rBox.GetLeft() : rBox.GetRight();
+ }
+ // OD 06.05.2003 #107169# - init boolean indicating printer output device.
+ const sal_Bool bPrtOutputDev =
+ ( OUTDEV_PRINTER == pGlobalShell->GetOut()->GetOutDevType() );
+
+ if ( !pLeftRightBorder )
+ {
+ return;
+ }
+
+ SwRect aRect( _rOutRect );
+ if ( _bLeft )
+ {
+ (aRect.*_rRectFn->fnAddRight)( ::lcl_AlignWidth( lcl_GetLineWidth( pLeftRightBorder ) ) -
+ (aRect.*_rRectFn->fnGetWidth)() );
+ }
+ else
+ {
+ (aRect.*_rRectFn->fnSubLeft)( ::lcl_AlignWidth( lcl_GetLineWidth( pLeftRightBorder ) ) -
+ (aRect.*_rRectFn->fnGetWidth)() );
+ }
+
+ const sal_Bool bCnt = _rFrm.IsCntntFrm();
+
+ if ( bCnt )
+ {
+ ::lcl_ExtendLeftAndRight( aRect, _rFrm, _rAttrs, _rRectFn );
+
+ // No Top / bottom borders for joint borders
+ if ( _rAttrs.JoinedWithPrev( _rFrm ) ) pTopBorder = NULL;
+ if ( _rAttrs.JoinedWithNext( _rFrm ) ) pBottomBorder = NULL;
+ }
+
+ // OD 06.05.2003 #107169# - adjustments for printer output device
+ if ( bPrtOutputDev )
+ {
+ // substract width of outer top line.
+ if ( rBox.GetTop() && (!bCnt || _rAttrs.GetTopLine( _rFrm )) )
+ {
+ long nDist = ::lcl_AlignHeight( rBox.GetTop()->GetOutWidth() );
+ (aRect.*_rRectFn->fnSubTop)( -nDist );
+ // OD 19.05.2003 #109667# - If outer top line is hair line, calculated
+ // top has to be adjusted.
+ if ( nDist == 1 )
+ {
+ if ( _rFrm.IsVertical() )
+ {
+ // right of border rectangle has to be checked and adjusted
+ Point aCompPt( aRect.Right(), 0 );
+ Point aRefPt( aCompPt.X() + 1, aCompPt.Y() );
+ lcl_CompPxPosAndAdjustPos( *(pGlobalShell->GetOut()),
+ aRefPt, aCompPt,
+ sal_True, -1 );
+ aRect.Right( aCompPt.X() );
+ }
+ else
+ {
+ // top of border rectangle has to be checked and adjusted
+ Point aCompPt( 0, aRect.Top() );
+ Point aRefPt( aCompPt.X(), aCompPt.Y() - 1 );
+ lcl_CompPxPosAndAdjustPos( *(pGlobalShell->GetOut()),
+ aRefPt, aCompPt,
+ sal_False, +1 );
+ aRect.Top( aCompPt.Y() );
+ }
+ }
+ }
+ // substract width of outer bottom line.
+ if ( rBox.GetBottom() && (!bCnt || _rAttrs.GetBottomLine( _rFrm )) )
+ {
+ long nDist = ::lcl_AlignHeight( rBox.GetBottom()->GetOutWidth());
+ (aRect.*_rRectFn->fnAddBottom)( -nDist );
+ // OD 19.05.2003 #109667# - If outer bottom line is hair line, calculated
+ // top has to be adjusted.
+ if ( nDist == 1 )
+ {
+ if ( _rFrm.IsVertical() )
+ {
+ // left of border rectangle has to be checked and adjusted
+ Point aCompPt( aRect.Left(), 0 );
+ Point aRefPt( aCompPt.X() - 1, aCompPt.Y() );
+ lcl_CompPxPosAndAdjustPos( *(pGlobalShell->GetOut()),
+ aRefPt, aCompPt,
+ sal_True, +1 );
+ aRect.Left( aCompPt.X() );
+ }
+ else
+ {
+ // bottom of border rectangle has to be checked and adjusted
+ Point aCompPt( 0, aRect.Bottom() );
+ Point aRefPt( aCompPt.X(), aCompPt.Y() + 1 );
+ lcl_CompPxPosAndAdjustPos( *(pGlobalShell->GetOut()),
+ aRefPt, aCompPt,
+ sal_False, -1 );
+ aRect.Bottom( aCompPt.Y() );
+ }
+ }
+ }
+ }
+
+ if ( !pLeftRightBorder->GetInWidth() )
+ {
+ // OD 06.05.2003 #107169# - add 6th parameter
+ ::lcl_SubTopBottom( aRect, rBox, _rAttrs, _rFrm, _rRectFn, bPrtOutputDev );
+ }
+
+ // TODO Postpone the processing of the primitives
+ if ( lcl_GetLineWidth( pLeftRightBorder ) > 0 )
+ {
+ drawinglayer::primitive2d::Primitive2DSequence aSequence( 1 );
+
+ double nExtentIS = lcl_GetExtent( pTopBorder, NULL );
+ double nExtentIE = lcl_GetExtent( pBottomBorder, NULL );
+ double nExtentOS = lcl_GetExtent( NULL, pTopBorder );
+ double nExtentOE = lcl_GetExtent( NULL, pBottomBorder );
+
+ if ( !_bLeft )
+ {
+ nExtentIS = lcl_GetExtent( NULL, pTopBorder );
+ nExtentIE = lcl_GetExtent( NULL, pBottomBorder );
+ nExtentOS = lcl_GetExtent( pTopBorder, NULL );
+ nExtentOE = lcl_GetExtent( pBottomBorder, NULL );
+ }
+
+ basegfx::B2DPoint aStart( aRect.Left() + aRect.Width() / 2.0, aRect.Top() + lcl_GetLineWidth( pTopBorder ) / 2.0 );
+ basegfx::B2DPoint aEnd( aRect.Left() + aRect.Width() / 2.0, aRect.Bottom() - lcl_GetLineWidth( pBottomBorder ) / 2.0 );
+
+ double nLeftWidth = !_bLeft ? pLeftRightBorder->GetOutWidth() : pLeftRightBorder->GetInWidth( );
+ double nRightWidth = !_bLeft ? pLeftRightBorder->GetInWidth() : pLeftRightBorder->GetOutWidth( );
+ Color aLeftColor = _bLeft ? pLeftRightBorder->GetColorOut( _bLeft ) : pLeftRightBorder->GetColorIn( _bLeft );
+ Color aRightColor = _bLeft ? pLeftRightBorder->GetColorIn( _bLeft ) : pLeftRightBorder->GetColorOut( _bLeft );
+
+ aSequence[0] = new drawinglayer::primitive2d::BorderLinePrimitive2D(
+ aStart, aEnd, nLeftWidth, pLeftRightBorder->GetDistance(), nRightWidth,
+ nExtentIS, nExtentIE, nExtentOS, nExtentOE,
+ aLeftColor.getBColor(), aRightColor.getBColor(),
+ pLeftRightBorder->GetColorGap().getBColor(),
+ pLeftRightBorder->HasGapColor(), pLeftRightBorder->GetStyle( ) );
+
+ _rFrm.ProcessPrimitives( aSequence );
+ }
+}
+
+// OD 19.05.2003 #109667# - merge <lcl_PaintTopLine> and <lcl_PaintBottomLine>
+// into <lcl_PaintTopLine>
+void lcl_PaintTopBottomLine( const sal_Bool _bTop,
+ const SwFrm& _rFrm,
+ const SwPageFrm& /*_rPage*/,
+ const SwRect& _rOutRect,
+ const SwRect& /*_rRect*/,
+ const SwBorderAttrs& _rAttrs,
+ const SwRectFn& _rRectFn )
+{
+ const SvxBoxItem& rBox = _rAttrs.GetBox();
+ const SvxBorderLine* pTopBottomBorder = 0;
+ const SvxBorderLine* pLeftBorder = rBox.GetLeft();
+ const SvxBorderLine* pRightBorder = rBox.GetRight();
+ if ( _bTop )
+ {
+ pTopBottomBorder = rBox.GetTop();
+ }
+ else
+ {
+ pTopBottomBorder = rBox.GetBottom();
+ }
+
+ if ( !pTopBottomBorder )
+ {
+ return;
+ }
+
+ SwRect aRect( _rOutRect );
+ if ( _bTop )
+ {
+ (aRect.*_rRectFn->fnAddBottom)( ::lcl_AlignHeight( lcl_GetLineWidth( pTopBottomBorder ) ) -
+ (aRect.*_rRectFn->fnGetHeight)() );
+ }
+ else
+ {
+ (aRect.*_rRectFn->fnSubTop)( ::lcl_AlignHeight( lcl_GetLineWidth( pTopBottomBorder ) ) -
+ (aRect.*_rRectFn->fnGetHeight)() );
+ }
+
+ // TODO Postpone the processing of the primitives
+ if ( lcl_GetLineWidth( pTopBottomBorder ) > 0 )
+ {
+ drawinglayer::primitive2d::Primitive2DSequence aSequence( 1 );
+
+ double nExtentIS = lcl_GetExtent( pRightBorder, NULL );
+ double nExtentIE = lcl_GetExtent( pLeftBorder, NULL );
+ double nExtentOS = lcl_GetExtent( NULL, pRightBorder );
+ double nExtentOE = lcl_GetExtent( NULL, pLeftBorder );
+
+ if ( !_bTop )
+ {
+ nExtentIS = lcl_GetExtent( NULL, pRightBorder );
+ nExtentIE = lcl_GetExtent( NULL, pLeftBorder );
+ nExtentOS = lcl_GetExtent( pRightBorder, NULL );
+ nExtentOE = lcl_GetExtent( pLeftBorder, NULL );
+ }
+
+ basegfx::B2DPoint aStart( aRect.Right() - lcl_GetLineWidth( pRightBorder ) / 2.0, aRect.Top() + aRect.Height() / 2.0 );
+ basegfx::B2DPoint aEnd( aRect.Left() + lcl_GetLineWidth( pLeftBorder ) / 2.0, aRect.Top() + aRect.Height() / 2.0 );
+
+ double nLeftWidth = !_bTop ? pTopBottomBorder->GetOutWidth() : pTopBottomBorder->GetInWidth( );
+ double nRightWidth = !_bTop ? pTopBottomBorder->GetInWidth() : pTopBottomBorder->GetOutWidth( );
+ Color aLeftColor = _bTop ? pTopBottomBorder->GetColorOut( _bTop ) : pTopBottomBorder->GetColorIn( _bTop );
+ Color aRightColor = _bTop ? pTopBottomBorder->GetColorIn( _bTop ) : pTopBottomBorder->GetColorOut( _bTop );
+
+ aSequence[0] = new drawinglayer::primitive2d::BorderLinePrimitive2D(
+ aStart, aEnd, nLeftWidth, pTopBottomBorder->GetDistance(), nRightWidth,
+ nExtentIS, nExtentIE, nExtentOS, nExtentOE,
+ aLeftColor.getBColor(), aRightColor.getBColor(),
+ pTopBottomBorder->GetColorGap().getBColor(),
+ pTopBottomBorder->HasGapColor(), pTopBottomBorder->GetStyle( ) );
+
+ _rFrm.ProcessPrimitives( aSequence );
+ }
+}
+
+/*************************************************************************
+|*
+|* const SwFrm* lcl_HasNextCell( const SwFrm& rFrm )
+|*
+|* No comment. #i15844#
+|*
+|*************************************************************************/
+
+const SwFrm* lcl_HasNextCell( const SwFrm& rFrm )
+{
+ OSL_ENSURE( rFrm.IsCellFrm(),
+ "lcl_HasNextCell( const SwFrm& rFrm ) should be called with SwCellFrm" );
+
+ const SwFrm* pTmpFrm = &rFrm;
+ do
+ {
+ if ( pTmpFrm->GetNext() )
+ return pTmpFrm->GetNext();
+
+ pTmpFrm = pTmpFrm->GetUpper()->GetUpper();
+ }
+ while ( pTmpFrm->IsCellFrm() );
+
+ return 0;
+}
+
+/*************************************************************************
+|*
+|* SwFrm::PaintBorder()
+|*
+|* Beschreibung Malt Schatten und Umrandung
+|*
+|*************************************************************************/
+
+/** local method to determine cell frame, from which the border attributes
+ for paint of top/bottom border has to be used.
+
+ OD 21.02.2003 #b4779636#, #107692#
+
+ @author OD
+
+ @param _pCellFrm
+ input parameter - constant pointer to cell frame for which the cell frame
+ for the border attributes has to be determined.
+
+ @param _rCellBorderAttrs
+ input parameter - constant reference to the border attributes of cell frame
+ <_pCellFrm>.
+
+ @param _bTop
+ input parameter - boolean, that controls, if cell frame for top border or
+ for bottom border has to be determined.
+
+ @return constant pointer to cell frame, for which the border attributes has
+ to be used
+*/
+const SwFrm* lcl_GetCellFrmForBorderAttrs( const SwFrm* _pCellFrm,
+ const SwBorderAttrs& _rCellBorderAttrs,
+ const bool _bTop )
+{
+ OSL_ENSURE( _pCellFrm, "No cell frame available, dying soon" );
+
+ // determine, if cell frame is at bottom/top border of a table frame and
+ // the table frame has/is a follow.
+ const SwFrm* pTmpFrm = _pCellFrm;
+ bool bCellAtBorder = true;
+ bool bCellAtLeftBorder = !_pCellFrm->GetPrev();
+ bool bCellAtRightBorder = !_pCellFrm->GetNext();
+ while( !pTmpFrm->IsRowFrm() || !pTmpFrm->GetUpper()->IsTabFrm() )
+ {
+ pTmpFrm = pTmpFrm->GetUpper();
+ if ( pTmpFrm->IsRowFrm() &&
+ (_bTop ? pTmpFrm->GetPrev() : pTmpFrm->GetNext())
+ )
+ {
+ bCellAtBorder = false;
+ }
+ if ( pTmpFrm->IsCellFrm() )
+ {
+ if ( pTmpFrm->GetPrev() )
+ {
+ bCellAtLeftBorder = false;
+ }
+ if ( pTmpFrm->GetNext() )
+ {
+ bCellAtRightBorder = false;
+ }
+ }
+ }
+ OSL_ENSURE( pTmpFrm && pTmpFrm->IsRowFrm(), "No RowFrm available" );
+
+ const SwLayoutFrm* pParentRowFrm = static_cast<const SwLayoutFrm*>(pTmpFrm);
+ const SwTabFrm* pParentTabFrm =
+ static_cast<const SwTabFrm*>(pParentRowFrm->GetUpper());
+
+ const bool bCellNeedsAttribute = bCellAtBorder &&
+ ( _bTop ?
+ // bCellInFirstRowWithMaster
+ ( !pParentRowFrm->GetPrev() &&
+ pParentTabFrm->IsFollow() &&
+ 0 == pParentTabFrm->GetTable()->GetRowsToRepeat() ) :
+ // bCellInLastRowWithFollow
+ ( !pParentRowFrm->GetNext() &&
+ pParentTabFrm->GetFollow() )
+ );
+
+ const SwFrm* pRet = _pCellFrm;
+ if ( bCellNeedsAttribute )
+ {
+ // determine, if cell frame has no borders inside the table.
+ const SwFrm* pNextCell = 0;
+ bool bNoBordersInside = false;
+
+ if ( bCellAtLeftBorder && ( 0 != ( pNextCell = lcl_HasNextCell( *_pCellFrm ) ) ) )
+ {
+ SwBorderAttrAccess aAccess( SwFrm::GetCache(), pNextCell );
+ const SwBorderAttrs &rBorderAttrs = *aAccess.Get();
+ const SvxBoxItem& rBorderBox = rBorderAttrs.GetBox();
+ bCellAtRightBorder = !lcl_HasNextCell( *pNextCell );
+ bNoBordersInside =
+ ( !rBorderBox.GetTop() || !pParentRowFrm->GetPrev() ) &&
+ !rBorderBox.GetLeft() &&
+ ( !rBorderBox.GetRight() || bCellAtRightBorder ) &&
+ ( !rBorderBox.GetBottom() || !pParentRowFrm->GetNext() );
+ }
+ else
+ {
+ const SvxBoxItem& rBorderBox = _rCellBorderAttrs.GetBox();
+ bNoBordersInside =
+ ( !rBorderBox.GetTop() || !pParentRowFrm->GetPrev() ) &&
+ ( !rBorderBox.GetLeft() || bCellAtLeftBorder ) &&
+ ( !rBorderBox.GetRight() || bCellAtRightBorder ) &&
+ ( !rBorderBox.GetBottom() || !pParentRowFrm->GetNext() );
+ }
+
+ if ( bNoBordersInside )
+ {
+ if ( _bTop && !_rCellBorderAttrs.GetBox().GetTop() )
+ {
+ // #b4779636#-hack:
+ // Cell frame has no top border and no border inside the table, but
+ // it is at the top border of a table frame, which is a follow.
+ // Thus, use border attributes of cell frame in first row of complete table.
+ // First, determine first table frame of complete table.
+ SwTabFrm* pMasterTabFrm = pParentTabFrm->FindMaster( true );
+ // determine first row of complete table.
+ const SwFrm* pFirstRow = pMasterTabFrm->GetLower();
+ // return first cell in first row
+ SwFrm* pLowerCell = const_cast<SwFrm*>(pFirstRow->GetLower());
+ while ( !pLowerCell->IsCellFrm() ||
+ ( pLowerCell->GetLower() && pLowerCell->GetLower()->IsRowFrm() )
+ )
+ {
+ pLowerCell = pLowerCell->GetLower();
+ }
+ OSL_ENSURE( pLowerCell && pLowerCell->IsCellFrm(), "No CellFrm available" );
+ pRet = pLowerCell;
+ }
+ else if ( !_bTop && !_rCellBorderAttrs.GetBox().GetBottom() )
+ {
+ // #b4779636#-hack:
+ // Cell frame has no bottom border and no border inside the table,
+ // but it is at the bottom border of a table frame, which has a follow.
+ // Thus, use border attributes of cell frame in last row of complete table.
+ // First, determine last table frame of complete table.
+ SwTabFrm* pLastTabFrm = const_cast<SwTabFrm*>(pParentTabFrm->GetFollow());
+ while ( pLastTabFrm->GetFollow() )
+ {
+ pLastTabFrm = pLastTabFrm->GetFollow();
+ }
+ // determine last row of complete table.
+ SwFrm* pLastRow = pLastTabFrm->GetLastLower();
+ // return first bottom border cell in last row
+ SwFrm* pLowerCell = const_cast<SwFrm*>(pLastRow->GetLower());
+ while ( !pLowerCell->IsCellFrm() ||
+ ( pLowerCell->GetLower() && pLowerCell->GetLower()->IsRowFrm() )
+ )
+ {
+ if ( pLowerCell->IsRowFrm() )
+ {
+ while ( pLowerCell->GetNext() )
+ {
+ pLowerCell = pLowerCell->GetNext();
+ }
+ }
+ pLowerCell = pLowerCell->GetLower();
+ }
+ OSL_ENSURE( pLowerCell && pLowerCell->IsCellFrm(), "No CellFrm available" );
+ pRet = pLowerCell;
+ }
+ }
+ }
+
+ return pRet;
+}
+
+void SwFrm::ProcessPrimitives( const drawinglayer::primitive2d::Primitive2DSequence& rSequence ) const
+{
+ basegfx::B2DRange aViewRange;
+
+ SdrPage *pDrawPage = getRootFrm()->GetCurrShell()->Imp()->GetPageView()->GetPage();
+ const drawinglayer::geometry::ViewInformation2D aNewViewInfos(
+ basegfx::B2DHomMatrix( ),
+ getRootFrm()->GetCurrShell()->GetOut()->GetViewTransformation(),
+ aViewRange,
+ GetXDrawPageForSdrPage( pDrawPage ),
+ 0.0,
+ uno::Sequence< beans::PropertyValue >() );
+
+ drawinglayer::processor2d::BaseProcessor2D * pProcessor2D =
+ sdr::contact::createBaseProcessor2DFromOutputDevice(
+ *getRootFrm()->GetCurrShell()->GetOut(),
+ aNewViewInfos );
+
+ if ( pProcessor2D )
+ {
+ pProcessor2D->process( rSequence );
+ delete pProcessor2D;
+ }
+}
+
+void SwFrm::PaintBorder( const SwRect& rRect, const SwPageFrm *pPage,
+ const SwBorderAttrs &rAttrs ) const
+{
+ //fuer (Row,Body,Ftn,Root,Column,NoTxt) gibt's hier nix zu tun
+ if ( (GetType() & 0x90C5) )
+ return;
+
+ if ( (GetType() & 0x2000) && //Cell
+ !pGlobalShell->GetViewOptions()->IsTable() )
+ return;
+
+ // --> collapsing borders FME 2005-05-27 #i29550#
+ if ( IsTabFrm() || IsCellFrm() || IsRowFrm() )
+ {
+ const SwTabFrm* pTabFrm = FindTabFrm();
+ if ( pTabFrm->IsCollapsingBorders() )
+ return;
+
+ if ( pTabFrm->GetTable()->IsNewModel() && ( !IsCellFrm() || IsCoveredCell() ) )
+ return;
+ }
+ // <--
+
+ const bool bLine = rAttrs.IsLine() ? true : false;
+ const bool bShadow = rAttrs.GetShadow().GetLocation() != SVX_SHADOW_NONE;
+
+ // OD 24.02.2003 #b4779636#, #107692# - flag to control,
+ // if #b4779636#-hack has to be used.
+ const bool bb4779636HackActive = true;
+ // OD 21.02.2003 #b4779636#, #107692#
+ const SwFrm* pCellFrmForBottomBorderAttrs = 0;
+ const SwFrm* pCellFrmForTopBorderAttrs = 0;
+ bool bFoundCellForTopOrBorderAttrs = false;
+ if ( bb4779636HackActive && IsCellFrm() )
+ {
+ pCellFrmForBottomBorderAttrs = lcl_GetCellFrmForBorderAttrs( this, rAttrs, false );
+ if ( pCellFrmForBottomBorderAttrs != this )
+ bFoundCellForTopOrBorderAttrs = true;
+ pCellFrmForTopBorderAttrs = lcl_GetCellFrmForBorderAttrs( this, rAttrs, true );
+ if ( pCellFrmForTopBorderAttrs != this )
+ bFoundCellForTopOrBorderAttrs = true;
+ }
+
+ // OD 24.02.2003 #b4779636#, #107692# - add condition <bFoundCellForTopOrBorderAttrs>
+ // for #b4779636#-hack
+ if ( bLine || bShadow || bFoundCellForTopOrBorderAttrs )
+ {
+ //Wenn das Rechteck vollstandig innerhalb der PrtArea liegt,
+ //so braucht kein Rand gepainted werden.
+ //Fuer die PrtArea muss der Aligned'e Wert zugrunde gelegt werden,
+ //anderfalls wuerden u.U. Teile nicht verarbeitet.
+ SwRect aRect( Prt() );
+ aRect += Frm().Pos();
+ ::SwAlignRect( aRect, pGlobalShell );
+ // OD 27.09.2002 #103636# - new local boolean variable in order to
+ // suspend border paint under special cases - see below.
+ // NOTE: This is a fix for the implementation of feature #99657#.
+ bool bDrawOnlyShadowForTransparentFrame = false;
+ if ( aRect.IsInside( rRect ) )
+ {
+ // OD 27.09.2002 #103636# - paint shadow, if background is transparent.
+ // Because of introduced transparent background for fly frame #99657#,
+ // the shadow have to be drawn if the background is transparent,
+ // in spite the fact that the paint rectangle <rRect> lies fully
+ // in the printing area.
+ // NOTE to chosen solution:
+ // On transparent background, continue processing, but suspend
+ // drawing of border by setting <bDrawOnlyShadowForTransparentFrame>
+ // to true.
+ if ( IsLayoutFrm() &&
+ static_cast<const SwLayoutFrm*>(this)->GetFmt()->IsBackgroundTransparent() )
+ {
+ bDrawOnlyShadowForTransparentFrame = true;
+ }
+ else
+ {
+ return;
+ }
+ }
+
+ if ( !pPage )
+ pPage = FindPageFrm();
+
+ ::lcl_CalcBorderRect( aRect, this, rAttrs, sal_True );
+ rAttrs.SetGetCacheLine( sal_True );
+ if ( bShadow )
+ PaintShadow( rRect, aRect, rAttrs );
+ // OD 27.09.2002 #103636# - suspend drawing of border
+ // add condition < NOT bDrawOnlyShadowForTransparentFrame > - see above
+ // OD 24.02.2003 #b4779636#, #107692# - add condition <bFoundCellForTopOrBorderAttrs>
+ // for #b4779636#-hack.
+ if ( ( bLine || bFoundCellForTopOrBorderAttrs ) &&
+ !bDrawOnlyShadowForTransparentFrame )
+ {
+ const SwFrm* pDirRefFrm = IsCellFrm() ? FindTabFrm() : this;
+ SWRECTFN( pDirRefFrm )
+ ::lcl_PaintLeftRightLine ( sal_True, *(this), *(pPage), aRect, rRect, rAttrs, fnRect );
+ ::lcl_PaintLeftRightLine ( sal_False, *(this), *(pPage), aRect, rRect, rAttrs, fnRect );
+ if ( !IsCntntFrm() || rAttrs.GetTopLine( *(this) ) )
+ {
+ // OD 21.02.2003 #b4779636#, #107692# -
+ // #b4779636#-hack: If another cell frame for top border
+ // paint is found, paint its top border.
+ if ( IsCellFrm() && pCellFrmForTopBorderAttrs != this )
+ {
+ SwBorderAttrAccess aAccess( SwFrm::GetCache(),
+ pCellFrmForTopBorderAttrs );
+ const SwBorderAttrs &rTopAttrs = *aAccess.Get();
+ ::lcl_PaintTopBottomLine( sal_True, *(this), *(pPage), aRect, rRect, rTopAttrs, fnRect );
+ }
+ else
+ {
+ ::lcl_PaintTopBottomLine( sal_True, *(this), *(pPage), aRect, rRect, rAttrs, fnRect );
+ }
+ }
+ if ( !IsCntntFrm() || rAttrs.GetBottomLine( *(this) ) )
+ {
+ // OD 21.02.2003 #b4779636#, #107692# -
+ // #b4779636#-hack: If another cell frame for bottom border
+ // paint is found, paint its bottom border.
+ if ( IsCellFrm() && pCellFrmForBottomBorderAttrs != this )
+ {
+ SwBorderAttrAccess aAccess( SwFrm::GetCache(),
+ pCellFrmForBottomBorderAttrs );
+ const SwBorderAttrs &rBottomAttrs = *aAccess.Get();
+ ::lcl_PaintTopBottomLine(sal_False, *(this), *(pPage), aRect, rRect, rBottomAttrs, fnRect);
+ }
+ else
+ {
+ ::lcl_PaintTopBottomLine(sal_False, *(this), *(pPage), aRect, rRect, rAttrs, fnRect);
+ }
+ }
+ }
+ rAttrs.SetGetCacheLine( sal_False );
+ }
+}
+/*************************************************************************
+|*
+|* SwFtnContFrm::PaintBorder()
+|*
+|* Beschreibung Spezialimplementierung wg. der Fussnotenlinie.
+|* Derzeit braucht nur der obere Rand beruecksichtigt werden.
+|* Auf andere Linien und Schatten wird verzichtet.
+|*
+|*************************************************************************/
+
+void SwFtnContFrm::PaintBorder( const SwRect& rRect, const SwPageFrm *pPage,
+ const SwBorderAttrs & ) const
+{
+ //Wenn das Rechteck vollstandig innerhalb der PrtArea liegt, so gibt es
+ //keinen Rand zu painten.
+ SwRect aRect( Prt() );
+ aRect.Pos() += Frm().Pos();
+ if ( !aRect.IsInside( rRect ) )
+ PaintLine( rRect, pPage );
+}
+/*************************************************************************
+|*
+|* SwFtnContFrm::PaintLine()
+|*
+|* Beschreibung Fussnotenline malen.
+|*
+|*************************************************************************/
+
+void SwFtnContFrm::PaintLine( const SwRect& rRect,
+ const SwPageFrm *pPage ) const
+{
+ //Laenge der Linie ergibt sich aus der prozentualen Angabe am PageDesc.
+ //Die Position ist ebenfalls am PageDesc angegeben.
+ //Der Pen steht direkt im PageDesc.
+
+ if ( !pPage )
+ pPage = FindPageFrm();
+ const SwPageFtnInfo &rInf = pPage->GetPageDesc()->GetFtnInfo();
+
+ SWRECTFN( this )
+ SwTwips nPrtWidth = (Prt().*fnRect->fnGetWidth)();
+ Fraction aFract( nPrtWidth, 1 );
+ const SwTwips nWidth = (long)(aFract *= rInf.GetWidth());
+
+ SwTwips nX = (this->*fnRect->fnGetPrtLeft)();
+ switch ( rInf.GetAdj() )
+ {
+ case FTNADJ_CENTER:
+ nX += nPrtWidth/2 - nWidth/2; break;
+ case FTNADJ_RIGHT:
+ nX += nPrtWidth - nWidth; break;
+ case FTNADJ_LEFT:
+ /* do nothing */; break;
+ default:
+ OSL_ENSURE( !this, "Neues Adjustment fuer Fussnotenlinie?" );
+ }
+ SwTwips nLineWidth = rInf.GetLineWidth();
+ const SwRect aLineRect = bVert ?
+ SwRect( Point(Frm().Left()+Frm().Width()-rInf.GetTopDist()-nLineWidth,
+ nX), Size( nLineWidth, nWidth ) )
+ : SwRect( Point( nX, Frm().Pos().Y() + rInf.GetTopDist() ),
+ Size( nWidth, rInf.GetLineWidth()));
+ if ( aLineRect.HasArea() )
+ PaintBorderLine( rRect, aLineRect , pPage, &rInf.GetLineColor(),
+ rInf.GetLineStyle() );
+}
+
+/*************************************************************************
+|*
+|* SwLayoutFrm::PaintColLines()
+|*
+|* Beschreibung Painted die Trennlinien fuer die innenliegenden
+|* Spalten.
+|*
+|*************************************************************************/
+
+void SwLayoutFrm::PaintColLines( const SwRect &rRect, const SwFmtCol &rFmtCol,
+ const SwPageFrm *pPage ) const
+{
+ const SwFrm *pCol = Lower();
+ if ( !pCol || !pCol->IsColumnFrm() )
+ return;
+ //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin
+ SwRectFn fnRect = pCol->IsVertical() ? ( pCol->IsVertLR() ? fnRectVertL2R : fnRectVert ) : fnRectHori;
+
+ SwRect aLineRect = Prt();
+ aLineRect += Frm().Pos();
+
+ SwTwips nTop = ((aLineRect.*fnRect->fnGetHeight)()*rFmtCol.GetLineHeight())
+ / 100 - (aLineRect.*fnRect->fnGetHeight)();
+ SwTwips nBottom = 0;
+
+ switch ( rFmtCol.GetLineAdj() )
+ {
+ case COLADJ_CENTER:
+ nBottom = nTop / 2; nTop -= nBottom; break;
+ case COLADJ_TOP:
+ nBottom = nTop; nTop = 0; break;
+ case COLADJ_BOTTOM:
+ break;
+ default:
+ OSL_ENSURE( !this, "Neues Adjustment fuer Spaltenlinie?" );
+ }
+
+ if( nTop )
+ (aLineRect.*fnRect->fnSubTop)( nTop );
+ if( nBottom )
+ (aLineRect.*fnRect->fnAddBottom)( nBottom );
+
+ SwTwips nPenHalf = rFmtCol.GetLineWidth();
+ (aLineRect.*fnRect->fnSetWidth)( nPenHalf );
+ nPenHalf /= 2;
+
+ //Damit uns nichts verlorengeht muessen wir hier etwas grosszuegiger sein.
+ SwRect aRect( rRect );
+ (aRect.*fnRect->fnSubLeft)( nPenHalf + nPixelSzW );
+ (aRect.*fnRect->fnAddRight)( nPenHalf + nPixelSzW );
+ SwRectGet fnGetX = IsRightToLeft() ? fnRect->fnGetLeft : fnRect->fnGetRight;
+ while ( pCol->GetNext() )
+ {
+ (aLineRect.*fnRect->fnSetPosX)
+ ( (pCol->Frm().*fnGetX)() - nPenHalf );
+ if ( aRect.IsOver( aLineRect ) )
+ PaintBorderLine( aRect, aLineRect , pPage, &rFmtCol.GetLineColor(),
+ rFmtCol.GetLineStyle() );
+ pCol = pCol->GetNext();
+ }
+}
+
+void SwPageFrm::PaintGrid( OutputDevice* pOut, SwRect &rRect ) const
+{
+ if( !bHasGrid || pRetoucheFly || pRetoucheFly2 )
+ return;
+ GETGRID( this )
+ if( pGrid && ( OUTDEV_PRINTER != pOut->GetOutDevType() ?
+ pGrid->GetDisplayGrid() : pGrid->GetPrintGrid() ) )
+ {
+ const SwLayoutFrm* pBody = FindBodyCont();
+ if( pBody )
+ {
+ SwRect aGrid( pBody->Prt() );
+ aGrid += pBody->Frm().Pos();
+
+ SwRect aInter( aGrid );
+ aInter.Intersection( rRect );
+ if( aInter.HasArea() )
+ {
+ sal_Bool bGrid = pGrid->GetRubyTextBelow();
+ sal_Bool bCell = GRID_LINES_CHARS == pGrid->GetGridType();
+ long nGrid = pGrid->GetBaseHeight();
+ const SwDoc* pDoc = GetFmt()->GetDoc();
+ long nGridWidth = GETGRIDWIDTH(pGrid,pDoc); //for textgrid refactor
+ long nRuby = pGrid->GetRubyHeight();
+ long nSum = nGrid + nRuby;
+ const Color *pCol = &pGrid->GetColor();
+
+ SwTwips nRight = aInter.Left() + aInter.Width();
+ SwTwips nBottom = aInter.Top() + aInter.Height();
+ if( IsVertical() )
+ {
+ SwTwips nOrig = aGrid.Left() + aGrid.Width();
+ SwTwips nY = nOrig + nSum *
+ ( ( nOrig - aInter.Left() ) / nSum );
+ SwRect aTmp( Point( nY, aInter.Top() ),
+ Size( 1, aInter.Height() ) );
+ SwTwips nX = aGrid.Top() + nGrid *
+ ( ( aInter.Top() - aGrid.Top() )/ nGrid );
+ if( nX < aInter.Top() )
+ nX += nGrid;
+ SwTwips nGridBottom = aGrid.Top() + aGrid.Height();
+ sal_Bool bLeft = aGrid.Top() >= aInter.Top();
+ sal_Bool bRight = nGridBottom <= nBottom;
+ sal_Bool bBorder = bLeft || bRight;
+ while( nY > nRight )
+ {
+ aTmp.Pos().X() = nY;
+ if( bGrid )
+ {
+ nY -= nGrid;
+ SwTwips nPosY = Max( aInter.Left(), nY );
+ SwTwips nHeight = Min(nRight, aTmp.Pos().X())-nPosY;
+ if( nHeight > 0 )
+ {
+ if( bCell )
+ {
+ SwRect aVert( Point( nPosY, nX ),
+ Size( nHeight, 1 ) );
+ while( aVert.Top() <= nBottom )
+ {
+ PaintBorderLine(rRect,aVert,this,pCol);
+ aVert.Pos().Y() += nGrid;
+ }
+ }
+ else if( bBorder )
+ {
+ SwRect aVert( Point( nPosY, aGrid.Top() ),
+ Size( nHeight, 1 ) );
+ if( bLeft )
+ PaintBorderLine(rRect,aVert,this,pCol);
+ if( bRight )
+ {
+ aVert.Pos().Y() = nGridBottom;
+ PaintBorderLine(rRect,aVert,this,pCol);
+ }
+ }
+ }
+ }
+ else
+ {
+ nY -= nRuby;
+ if( bBorder )
+ {
+ SwTwips nPos = Max( aInter.Left(), nY );
+ SwTwips nW = Min(nRight, aTmp.Pos().X()) - nPos;
+ SwRect aVert( Point( nPos, aGrid.Top() ),
+ Size( nW, 1 ) );
+ if( nW > 0 )
+ {
+ if( bLeft )
+ PaintBorderLine(rRect,aVert,this,pCol);
+ if( bRight )
+ {
+ aVert.Pos().Y() = nGridBottom;
+ PaintBorderLine(rRect,aVert,this,pCol);
+ }
+ }
+ }
+ }
+ bGrid = !bGrid;
+ }
+ while( nY >= aInter.Left() )
+ {
+ aTmp.Pos().X() = nY;
+ PaintBorderLine( rRect, aTmp, this, pCol);
+ if( bGrid )
+ {
+ nY -= nGrid;
+ SwTwips nHeight = aTmp.Pos().X()
+ - Max(aInter.Left(), nY );
+ if( nHeight > 0 )
+ {
+ if( bCell )
+ {
+ SwRect aVert( Point(aTmp.Pos().X()-nHeight,
+ nX ), Size( nHeight, 1 ) );
+ while( aVert.Top() <= nBottom )
+ {
+ PaintBorderLine(rRect,aVert,this,pCol);
+ aVert.Pos().Y() += nGrid;
+ }
+ }
+ else if( bBorder )
+ {
+ SwRect aVert( Point(aTmp.Pos().X()-nHeight,
+ aGrid.Top() ), Size( nHeight, 1 ) );
+ if( bLeft )
+ PaintBorderLine(rRect,aVert,this,pCol);
+ if( bRight )
+ {
+ aVert.Pos().Y() = nGridBottom;
+ PaintBorderLine(rRect,aVert,this,pCol);
+ }
+ }
+ }
+ }
+ else
+ {
+ nY -= nRuby;
+ if( bBorder )
+ {
+ SwTwips nPos = Max( aInter.Left(), nY );
+ SwTwips nW = Min(nRight, aTmp.Pos().X()) - nPos;
+ SwRect aVert( Point( nPos, aGrid.Top() ),
+ Size( nW, 1 ) );
+ if( nW > 0 )
+ {
+ if( bLeft )
+ PaintBorderLine(rRect,aVert,this,pCol);
+ if( bRight )
+ {
+ aVert.Pos().Y() = nGridBottom;
+ PaintBorderLine(rRect,aVert,this,pCol);
+ }
+ }
+ }
+ }
+ bGrid = !bGrid;
+ }
+ }
+ else
+ {
+ SwTwips nOrig = aGrid.Top();
+ SwTwips nY = nOrig + nSum *( (aInter.Top()-nOrig)/nSum );
+ SwRect aTmp( Point( aInter.Left(), nY ),
+ Size( aInter.Width(), 1 ) );
+ //for textgrid refactor
+ SwTwips nX = aGrid.Left() + nGridWidth *
+ ( ( aInter.Left() - aGrid.Left() )/ nGridWidth );
+ if( nX < aInter.Left() )
+ nX += nGridWidth;
+ SwTwips nGridRight = aGrid.Left() + aGrid.Width();
+ sal_Bool bLeft = aGrid.Left() >= aInter.Left();
+ sal_Bool bRight = nGridRight <= nRight;
+ sal_Bool bBorder = bLeft || bRight;
+ while( nY < aInter.Top() )
+ {
+ aTmp.Pos().Y() = nY;
+ if( bGrid )
+ {
+ nY += nGrid;
+ SwTwips nPosY = Max( aInter.Top(), aTmp.Pos().Y() );
+ SwTwips nHeight = Min(nBottom, nY ) - nPosY;
+ if( nHeight )
+ {
+ if( bCell )
+ {
+ SwRect aVert( Point( nX, nPosY ),
+ Size( 1, nHeight ) );
+ while( aVert.Left() <= nRight )
+ {
+ PaintBorderLine(rRect,aVert,this,pCol);
+ aVert.Pos().X() += nGridWidth; //for textgrid refactor
+ }
+ }
+ else if ( bBorder )
+ {
+ SwRect aVert( Point( aGrid.Left(), nPosY ),
+ Size( 1, nHeight ) );
+ if( bLeft )
+ PaintBorderLine(rRect,aVert,this,pCol);
+ if( bRight )
+ {
+ aVert.Pos().X() = nGridRight;
+ PaintBorderLine(rRect,aVert,this,pCol);
+ }
+ }
+ }
+ }
+ else
+ {
+ nY += nRuby;
+ if( bBorder )
+ {
+ SwTwips nPos = Max(aInter.Top(),aTmp.Pos().Y());
+ SwTwips nH = Min( nBottom, nY ) - nPos;
+ SwRect aVert( Point( aGrid.Left(), nPos ),
+ Size( 1, nH ) );
+ if( nH > 0 )
+ {
+ if( bLeft )
+ PaintBorderLine(rRect,aVert,this,pCol);
+ if( bRight )
+ {
+ aVert.Pos().X() = nGridRight;
+ PaintBorderLine(rRect,aVert,this,pCol);
+ }
+ }
+ }
+ }
+ bGrid = !bGrid;
+ }
+ while( nY <= nBottom )
+ {
+ aTmp.Pos().Y() = nY;
+ PaintBorderLine( rRect, aTmp, this, pCol);
+ if( bGrid )
+ {
+ nY += nGrid;
+ SwTwips nHeight = Min(nBottom, nY) - aTmp.Pos().Y();
+ if( nHeight )
+ {
+ if( bCell )
+ {
+ SwRect aVert( Point( nX, aTmp.Pos().Y() ),
+ Size( 1, nHeight ) );
+ while( aVert.Left() <= nRight )
+ {
+ PaintBorderLine( rRect, aVert, this, pCol);
+ aVert.Pos().X() += nGridWidth; //for textgrid refactor
+ }
+ }
+ else if( bBorder )
+ {
+ SwRect aVert( Point( aGrid.Left(),
+ aTmp.Pos().Y() ), Size( 1, nHeight ) );
+ if( bLeft )
+ PaintBorderLine(rRect,aVert,this,pCol);
+ if( bRight )
+ {
+ aVert.Pos().X() = nGridRight;
+ PaintBorderLine(rRect,aVert,this,pCol);
+ }
+ }
+ }
+ }
+ else
+ {
+ nY += nRuby;
+ if( bBorder )
+ {
+ SwTwips nPos = Max(aInter.Top(),aTmp.Pos().Y());
+ SwTwips nH = Min( nBottom, nY ) - nPos;
+ SwRect aVert( Point( aGrid.Left(), nPos ),
+ Size( 1, nH ) );
+ if( nH > 0 )
+ {
+ if( bLeft )
+ PaintBorderLine(rRect,aVert,this,pCol);
+ if( bRight )
+ {
+ aVert.Pos().X() = nGridRight;
+ PaintBorderLine(rRect,aVert,this,pCol);
+ }
+ }
+ }
+ }
+ bGrid = !bGrid;
+ }
+ }
+ }
+ }
+ }
+}
+
+/** paint margin area of a page
+
+ OD 20.11.2002 for #104598#:
+ implement paint of margin area; margin area will be painted for a
+ view shell with a window and if the document is not in online layout.
+
+ @author OD
+
+ @param _rOutputRect
+ input parameter - constant instance reference of the rectangle, for
+ which an output has to be generated.
+
+ @param _pViewShell
+ input parameter - instance of the view shell, on which the output
+ has to be generated.
+*/
+void SwPageFrm::PaintMarginArea( const SwRect& _rOutputRect,
+ ViewShell* _pViewShell ) const
+{
+ if ( _pViewShell->GetWin() &&
+ !_pViewShell->GetViewOptions()->getBrowseMode() )
+ {
+ SwRect aPgPrtRect( Prt() );
+ aPgPrtRect.Pos() += Frm().Pos();
+ if ( !aPgPrtRect.IsInside( _rOutputRect ) )
+ {
+ SwRect aPgRect = Frm();
+ aPgRect._Intersection( _rOutputRect );
+ if(aPgRect.Height() < 0 || aPgRect.Width() <= 0) // No intersection
+ return;
+ SwRegionRects aPgRegion( aPgRect );
+ aPgRegion -= aPgPrtRect;
+ const SwPageFrm* pPage = static_cast<const SwPageFrm*>(this);
+ if ( pPage->GetSortedObjs() )
+ ::lcl_SubtractFlys( this, pPage, aPgRect, aPgRegion );
+ if ( aPgRegion.Count() )
+ {
+ OutputDevice *pOut = _pViewShell->GetOut();
+ if ( pOut->GetFillColor() != aGlobalRetoucheColor )
+ pOut->SetFillColor( aGlobalRetoucheColor );
+ for ( sal_uInt16 i = 0; i < aPgRegion.Count(); ++i )
+ {
+ if ( 1 < aPgRegion.Count() )
+ {
+ ::SwAlignRect( aPgRegion[i], pGlobalShell );
+ if( !aPgRegion[i].HasArea() )
+ continue;
+ }
+ pOut->DrawRect(aPgRegion[i].SVRect());
+ }
+ }
+ }
+ }
+}
+
+const sal_Int8 SwPageFrm::mnShadowPxWidth = 9;
+
+sal_Bool SwPageFrm::IsRightShadowNeeded() const
+{
+ const ViewShell *pSh = getRootFrm()->GetCurrShell();
+ const bool bIsLTR = getRootFrm()->IsLeftToRightViewLayout();
+
+ // We paint the right shadow if we're not in book mode
+ // or if we've no sibling or are the last page of the "row"
+ return !pSh || (!pSh->GetViewOptions()->IsViewLayoutBookMode()) || !GetNext()
+ || (this == Lower()) || (bIsLTR && OnRightPage())
+ || (!bIsLTR && !OnRightPage());
+
+}
+
+sal_Bool SwPageFrm::IsLeftShadowNeeded() const
+{
+ const ViewShell *pSh = getRootFrm()->GetCurrShell();
+ const bool bIsLTR = getRootFrm()->IsLeftToRightViewLayout();
+
+ // We paint the left shadow if we're not in book mode
+ // or if we've no sibling or are the last page of the "row"
+ return !pSh || (!pSh->GetViewOptions()->IsViewLayoutBookMode()) || !GetPrev()
+ || (bIsLTR && !OnRightPage())
+ || (!bIsLTR && OnRightPage());
+}
+
+/** determine rectangle for bottom page shadow
+
+ OD 12.02.2003 for #i9719# and #105645#
+
+ @author OD
+*/
+/*static*/ void SwPageFrm::GetHorizontalShadowRect( const SwRect& _rPageRect,
+ const ViewShell* _pViewShell,
+ SwRect& _orHorizontalShadowRect,
+ bool bPaintLeftShadow,
+ bool bPaintRightShadow,
+ bool bRightSidebar )
+{
+ const SwPostItMgr *pMgr = _pViewShell ? _pViewShell->GetPostItMgr() : 0;
+ SwRect aAlignedPageRect( _rPageRect );
+ ::SwAlignRect( aAlignedPageRect, _pViewShell );
+ SwRect aPagePxRect =
+ _pViewShell->GetOut()->LogicToPixel( aAlignedPageRect.SVRect() );
+
+ long lShadowAdjustment = mnShadowPxWidth - 1; // TODO extract this
+
+ _orHorizontalShadowRect.Chg(
+ Point( aPagePxRect.Left() + (bPaintLeftShadow ? lShadowAdjustment : 0), 0 ),
+ Size( aPagePxRect.Width() - ( (bPaintLeftShadow ? lShadowAdjustment : 0) + (bPaintRightShadow ? lShadowAdjustment : 0) ),
+ mnShadowPxWidth ) );
+
+ if(pMgr && pMgr->ShowNotes() && pMgr->HasNotes())
+ {
+ // Notes are displayed, we've to extend borders
+ SwTwips aSidebarTotalWidth = pMgr->GetSidebarWidth(true) + pMgr->GetSidebarBorderWidth(true);
+ if(bRightSidebar)
+ _orHorizontalShadowRect.Right( _orHorizontalShadowRect.Right() + aSidebarTotalWidth );
+ else
+ _orHorizontalShadowRect.Left( _orHorizontalShadowRect.Left() - aSidebarTotalWidth );
+ }
+}
+
+/** paint page border and shadow
+
+ OD 12.02.2003 for #i9719# and #105645#
+ implement paint of page border and shadow
+
+ @author OD
+*/
+/*static*/ void SwPageFrm::PaintBorderAndShadow( const SwRect& _rPageRect,
+ const ViewShell* _pViewShell,
+ bool bPaintLeftShadow,
+ bool bPaintRightShadow,
+ bool bRightSidebar )
+{
+ // No shadow in prefs
+ if( !SwViewOption::IsShadow() ) return;
+
+ // --> FME 2004-06-24 #i16816# tagged pdf support
+ SwTaggedPDFHelper aTaggedPDFHelper( 0, 0, 0, *_pViewShell->GetOut() );
+ // <--
+
+ static drawinglayer::primitive2d::DiscreteShadow shadowMask( SW_RES( BMP_PAGE_SHADOW_MASK ) );
+ static BitmapEx aPageTopRightShadow;
+ static BitmapEx aPageBottomRightShadow;
+ static BitmapEx aPageBottomLeftShadow;
+ static BitmapEx aPageBottomShadowBase;
+ static BitmapEx aPageRightShadowBase;
+ static BitmapEx aPageTopShadowBase;
+ static BitmapEx aPageTopLeftShadow;
+ static BitmapEx aPageLeftShadowBase;
+ static Color aShadowColor( COL_AUTO );
+
+ SwRect aAlignedPageRect( _rPageRect );
+ ::SwAlignRect( aAlignedPageRect, _pViewShell );
+ SwRect aPagePxRect =
+ _pViewShell->GetOut()->LogicToPixel( aAlignedPageRect.SVRect() );
+
+
+ if(aShadowColor != SwViewOption::GetShadowColor() ) {
+ aShadowColor = SwViewOption::GetShadowColor();
+
+ AlphaMask aMask( shadowMask.getBottomRight().GetBitmap() );
+ Bitmap aFilledSquare( aMask.GetSizePixel(), 24 );
+ aFilledSquare.Erase( aShadowColor );
+ aPageBottomRightShadow = BitmapEx( aFilledSquare, aMask );
+
+ aMask = AlphaMask( shadowMask.getBottomLeft().GetBitmap() );
+ aFilledSquare = Bitmap( aMask.GetSizePixel(), 24 );
+ aFilledSquare.Erase( aShadowColor );
+ aPageBottomLeftShadow = BitmapEx( aFilledSquare, aMask );
+
+ aMask = AlphaMask( shadowMask.getBottom().GetBitmap() );
+ aFilledSquare = Bitmap( aMask.GetSizePixel(), 24 );
+ aFilledSquare.Erase( aShadowColor );
+ aPageBottomShadowBase = BitmapEx( aFilledSquare, aMask );
+
+ aMask = AlphaMask( shadowMask.getTop().GetBitmap() );
+ aFilledSquare = Bitmap( aMask.GetSizePixel(), 24 );
+ aFilledSquare.Erase( aShadowColor );
+ aPageTopShadowBase = BitmapEx( aFilledSquare, aMask );
+
+ aMask = AlphaMask( shadowMask.getTopRight().GetBitmap() );
+ aFilledSquare = Bitmap( aMask.GetSizePixel(), 24 );
+ aFilledSquare.Erase( aShadowColor );
+ aPageTopRightShadow = BitmapEx( aFilledSquare, aMask );
+
+ aMask = AlphaMask( shadowMask.getRight().GetBitmap() );
+ aFilledSquare = Bitmap( aMask.GetSizePixel(), 24 );
+ aFilledSquare.Erase( aShadowColor );
+ aPageRightShadowBase = BitmapEx( aFilledSquare, aMask );
+
+ aMask = AlphaMask( shadowMask.getTopLeft().GetBitmap() );
+ aFilledSquare = Bitmap( aMask.GetSizePixel(), 24 );
+ aFilledSquare.Erase( aShadowColor );
+ aPageTopLeftShadow = BitmapEx( aFilledSquare, aMask );
+
+ aMask = AlphaMask( shadowMask.getLeft().GetBitmap() );
+ aFilledSquare = Bitmap( aMask.GetSizePixel(), 24 );
+ aFilledSquare.Erase( aShadowColor );
+ aPageLeftShadowBase = BitmapEx( aFilledSquare, aMask );
+ }
+
+ SwRect aPaintRect;
+ OutputDevice *pOut = _pViewShell->GetOut();
+
+ SwPageFrm::GetHorizontalShadowRect( _rPageRect, _pViewShell, aPaintRect, bPaintLeftShadow, bPaintRightShadow, bRightSidebar );
+
+ // Right shadow & corners
+ if ( bPaintRightShadow )
+ {
+ pOut->DrawBitmapEx( pOut->PixelToLogic( Point( aPaintRect.Right() + 1, aPagePxRect.Bottom() + 1 - (aPageBottomRightShadow.GetSizePixel().Height() - mnShadowPxWidth) ) ),
+ aPageBottomRightShadow );
+ pOut->DrawBitmapEx( pOut->PixelToLogic( Point( aPaintRect.Right() + 1, aPagePxRect.Top() - mnShadowPxWidth ) ),
+ aPageTopRightShadow );
+ BitmapEx aPageRightShadow = aPageRightShadowBase;
+ aPageRightShadow.Scale( 1, aPagePxRect.Height() - 2 * (mnShadowPxWidth - 1) );
+ pOut->DrawBitmapEx( pOut->PixelToLogic( Point( aPaintRect.Right() + mnShadowPxWidth, aPagePxRect.Top() + mnShadowPxWidth - 1) ), aPageRightShadow );
+ }
+
+ // Left shadows and corners
+ if(bPaintLeftShadow)
+ {
+ const long lLeft = aPaintRect.Left() - aPageBottomLeftShadow.GetSizePixel().Width();
+ pOut->DrawBitmapEx( pOut->PixelToLogic( Point( lLeft,
+ aPagePxRect.Bottom() + 1 + mnShadowPxWidth - aPageBottomLeftShadow.GetSizePixel().Height() ) ), aPageBottomLeftShadow );
+ pOut->DrawBitmapEx( pOut->PixelToLogic( Point( lLeft, aPagePxRect.Top() - mnShadowPxWidth ) ), aPageTopLeftShadow );
+ BitmapEx aPageLeftShadow = aPageLeftShadowBase;
+ aPageLeftShadow.Scale( 1, aPagePxRect.Height() - 2 * (mnShadowPxWidth - 1) );
+ pOut->DrawBitmapEx( pOut->PixelToLogic( Point( lLeft, aPagePxRect.Top() + mnShadowPxWidth - 1) ), aPageLeftShadow );
+ }
+
+ BitmapEx aPageBottomShadow = aPageBottomShadowBase;
+ aPageBottomShadow.Scale( aPaintRect.Width(), 1 );
+ pOut->DrawBitmapEx( pOut->PixelToLogic( Point( aPaintRect.Left(), aPagePxRect.Bottom() + 1 ) ), aPageBottomShadow);
+ BitmapEx aPageTopShadow = aPageTopShadowBase;
+ aPageTopShadow.Scale( aPaintRect.Width(), 1 );
+ pOut->DrawBitmapEx( pOut->PixelToLogic( Point( aPaintRect.Left(), aPagePxRect.Top() - mnShadowPxWidth ) ), aPageTopShadow );
+}
+
+//mod #i6193# paint sidebar for notes
+//IMPORTANT: if you change the rects here, also change SwPostItMgr::ScrollbarHit
+/*static*/void SwPageFrm::PaintNotesSidebar(const SwRect& _rPageRect, ViewShell* _pViewShell, sal_uInt16 nPageNum, bool bRight)
+{
+ //TOOD: cut out scrollbar area and arrows out of sidepane rect, otherwise it could flicker when pressing arrow buttons
+ if (!_pViewShell )
+ return;
+
+ SwRect aPageRect( _rPageRect );
+ SwAlignRect( aPageRect, _pViewShell );
+
+ const SwPostItMgr *pMgr = _pViewShell->GetPostItMgr();
+ if (pMgr && pMgr->ShowNotes() && pMgr->HasNotes()) // do not show anything in print preview
+ {
+ sal_Int32 nScrollerHeight = pMgr->GetSidebarScrollerHeight();
+ const Rectangle &aVisRect = _pViewShell->VisArea().SVRect();
+ //draw border and sidepane
+ _pViewShell->GetOut()->SetLineColor();
+ if (!bRight)
+ {
+ _pViewShell->GetOut()->SetFillColor(COL_NOTES_SIDEPANE_BORDER);
+ _pViewShell->GetOut()->DrawRect(Rectangle(Point(aPageRect.Left()-pMgr->GetSidebarBorderWidth(),aPageRect.Top()),Size(pMgr->GetSidebarBorderWidth(),aPageRect.Height()))) ;
+ if (Application::GetSettings().GetStyleSettings().GetHighContrastMode() )
+ _pViewShell->GetOut()->SetFillColor(COL_BLACK);
+ else
+ _pViewShell->GetOut()->SetFillColor(COL_NOTES_SIDEPANE);
+ _pViewShell->GetOut()->DrawRect(Rectangle(Point(aPageRect.Left()-pMgr->GetSidebarWidth()-pMgr->GetSidebarBorderWidth(),aPageRect.Top()),Size(pMgr->GetSidebarWidth(),aPageRect.Height()))) ;
+ }
+ else
+ {
+ _pViewShell->GetOut()->SetFillColor(COL_NOTES_SIDEPANE_BORDER);
+ SwRect aSidebarBorder(aPageRect.TopRight(),Size(pMgr->GetSidebarBorderWidth(),aPageRect.Height()));
+ _pViewShell->GetOut()->DrawRect(aSidebarBorder.SVRect());
+ if (Application::GetSettings().GetStyleSettings().GetHighContrastMode() )
+ _pViewShell->GetOut()->SetFillColor(COL_BLACK);
+ else
+ _pViewShell->GetOut()->SetFillColor(COL_NOTES_SIDEPANE);
+ SwRect aSidebar(Point(aPageRect.Right()+pMgr->GetSidebarBorderWidth(),aPageRect.Top()),Size(pMgr->GetSidebarWidth(),aPageRect.Height()));
+ _pViewShell->GetOut()->DrawRect(aSidebar.SVRect());
+ }
+ if (pMgr->ShowScrollbar(nPageNum))
+ {
+ // draw scrollbar area and arrows
+ Point aPointBottom;
+ Point aPointTop;
+ aPointBottom = !bRight ? Point(aPageRect.Left() - pMgr->GetSidebarWidth() - pMgr->GetSidebarBorderWidth() + _pViewShell->GetOut()->PixelToLogic(Size(2,0)).Width(),aPageRect.Bottom()- _pViewShell->GetOut()->PixelToLogic(Size(0,2+pMgr->GetSidebarScrollerHeight())).Height()) :
+ Point(aPageRect.Right() + pMgr->GetSidebarBorderWidth() + _pViewShell->GetOut()->PixelToLogic(Size(2,0)).Width(),aPageRect.Bottom()- _pViewShell->GetOut()->PixelToLogic(Size(0,2+pMgr->GetSidebarScrollerHeight())).Height());
+ aPointTop = !bRight ? Point(aPageRect.Left() - pMgr->GetSidebarWidth() + _pViewShell->GetOut()->PixelToLogic(Size(2,0)).Width(),aPageRect.Top() + _pViewShell->GetOut()->PixelToLogic(Size(0,2)).Height()) :
+ Point(aPageRect.Right() + pMgr->GetSidebarBorderWidth() + _pViewShell->GetOut()->PixelToLogic(Size(2,0)).Width(),aPageRect.Top() + _pViewShell->GetOut()->PixelToLogic(Size(0,2)).Height());
+ Size aSize(pMgr->GetSidebarWidth() - _pViewShell->GetOut()->PixelToLogic(Size(4,0)).Width(), _pViewShell->GetOut()->PixelToLogic(Size(0,nScrollerHeight)).Height()) ;
+ Rectangle aRectBottom(aPointBottom,aSize);
+ Rectangle aRectTop(aPointTop,aSize);
+
+ if (aRectBottom.IsOver(aVisRect))
+ {
+
+ if (Application::GetSettings().GetStyleSettings().GetHighContrastMode() )
+ {
+ _pViewShell->GetOut()->SetLineColor(COL_WHITE);
+ _pViewShell->GetOut()->SetFillColor(COL_BLACK);
+ }
+ else
+ {
+ _pViewShell->GetOut()->SetLineColor(COL_BLACK);
+ _pViewShell->GetOut()->SetFillColor(COL_NOTES_SIDEPANE_SCROLLAREA);
+ }
+ _pViewShell->GetOut()->DrawRect(aRectBottom);
+ _pViewShell->GetOut()->DrawLine(aPointBottom + Point(pMgr->GetSidebarWidth()/3,0), aPointBottom + Point(pMgr->GetSidebarWidth()/3 , _pViewShell->GetOut()->PixelToLogic(Size(0,nScrollerHeight)).Height()));
+
+ _pViewShell->GetOut()->SetLineColor();
+ Point aMiddleFirst(aPointBottom + Point(pMgr->GetSidebarWidth()/6,_pViewShell->GetOut()->PixelToLogic(Size(0,nScrollerHeight)).Height()/2));
+ Point aMiddleSecond(aPointBottom + Point(pMgr->GetSidebarWidth()/3*2,_pViewShell->GetOut()->PixelToLogic(Size(0,nScrollerHeight)).Height()/2));
+ PaintNotesSidebarArrows(aMiddleFirst,aMiddleSecond,_pViewShell,pMgr->GetArrowColor(KEY_PAGEUP,nPageNum), pMgr->GetArrowColor(KEY_PAGEDOWN,nPageNum));
+ }
+ if (aRectTop.IsOver(aVisRect))
+ {
+ if (Application::GetSettings().GetStyleSettings().GetHighContrastMode() )
+ {
+ _pViewShell->GetOut()->SetLineColor(COL_WHITE);
+ _pViewShell->GetOut()->SetFillColor(COL_BLACK);
+ }
+ else
+ {
+ _pViewShell->GetOut()->SetLineColor(COL_BLACK);
+ _pViewShell->GetOut()->SetFillColor(COL_NOTES_SIDEPANE_SCROLLAREA);
+ }
+ _pViewShell->GetOut()->DrawRect(aRectTop);
+ _pViewShell->GetOut()->DrawLine(aPointTop + Point(pMgr->GetSidebarWidth()/3*2,0), aPointTop + Point(pMgr->GetSidebarWidth()/3*2 , _pViewShell->GetOut()->PixelToLogic(Size(0,nScrollerHeight)).Height()));
+
+ _pViewShell->GetOut()->SetLineColor();
+ Point aMiddleFirst(aPointTop + Point(pMgr->GetSidebarWidth()/3,_pViewShell->GetOut()->PixelToLogic(Size(0,nScrollerHeight)).Height()/2));
+ Point aMiddleSecond(aPointTop + Point(pMgr->GetSidebarWidth()/6*5,_pViewShell->GetOut()->PixelToLogic(Size(0,nScrollerHeight)).Height()/2));
+ PaintNotesSidebarArrows(aMiddleFirst,aMiddleSecond,_pViewShell, pMgr->GetArrowColor(KEY_PAGEUP,nPageNum), pMgr->GetArrowColor(KEY_PAGEDOWN,nPageNum));
+ }
+ }
+ }
+}
+
+/*static*/ void SwPageFrm::PaintNotesSidebarArrows(const Point &aMiddleFirst, const Point &aMiddleSecond, ViewShell* _pViewShell, const Color aColorUp, const Color aColorDown)
+{
+ Polygon aTriangleUp(3);
+ Polygon aTriangleDown(3);
+
+ aTriangleUp.SetPoint(aMiddleFirst + Point(0,_pViewShell->GetOut()->PixelToLogic(Size(0,-3)).Height()),0);
+ aTriangleUp.SetPoint(aMiddleFirst + Point(_pViewShell->GetOut()->PixelToLogic(Size(-3,0)).Width(),_pViewShell->GetOut()->PixelToLogic(Size(0,3)).Height()),1);
+ aTriangleUp.SetPoint(aMiddleFirst + Point(_pViewShell->GetOut()->PixelToLogic(Size(3,0)).Width(),_pViewShell->GetOut()->PixelToLogic(Size(0,3)).Height()),2);
+
+ aTriangleDown.SetPoint(aMiddleSecond + Point(_pViewShell->GetOut()->PixelToLogic(Size(-3,0)).Width(),_pViewShell->GetOut()->PixelToLogic(Size(0,-3)).Height()),0);
+ aTriangleDown.SetPoint(aMiddleSecond + Point(_pViewShell->GetOut()->PixelToLogic(Size(+3,0)).Width(),_pViewShell->GetOut()->PixelToLogic(Size(0,-3)).Height()),1);
+ aTriangleDown.SetPoint(aMiddleSecond + Point(0,_pViewShell->GetOut()->PixelToLogic(Size(0,3)).Height()),2);
+
+ _pViewShell->GetOut()->SetFillColor(aColorUp);
+ _pViewShell->GetOut()->DrawPolygon(aTriangleUp);
+ _pViewShell->GetOut()->SetFillColor(aColorDown);
+ _pViewShell->GetOut()->DrawPolygon(aTriangleDown);
+}
+
+/** get bound rectangle of border and shadow for repaints
+
+ OD 12.02.2003 for #i9719# and #105645#
+
+ author OD
+*/
+/*static*/ void SwPageFrm::GetBorderAndShadowBoundRect( const SwRect& _rPageRect,
+ const ViewShell* _pViewShell,
+ SwRect& _orBorderAndShadowBoundRect,
+ bool bLeftShadow,
+ bool bRightShadow,
+ bool bRightSidebar
+ )
+{
+ SwRect aAlignedPageRect( _rPageRect );
+ ::SwAlignRect( aAlignedPageRect, _pViewShell );
+ SwRect aPagePxRect =
+ _pViewShell->GetOut()->LogicToPixel( aAlignedPageRect.SVRect() );
+ aPagePxRect.Bottom( aPagePxRect.Bottom() + mnShadowPxWidth + 1 );
+ aPagePxRect.Top( aPagePxRect.Top() - mnShadowPxWidth - 1 );
+
+ SwRect aTmpRect;
+
+ // Always ask for full shadow since we want a bounding rect
+ // including at least the page frame
+ SwPageFrm::GetHorizontalShadowRect( _rPageRect, _pViewShell, aTmpRect, false, false, bRightSidebar );
+
+ if(bLeftShadow) aPagePxRect.Left( aTmpRect.Left() - mnShadowPxWidth - 1);
+ if(bRightShadow) aPagePxRect.Right( aTmpRect.Right() + mnShadowPxWidth + 1);
+
+ _orBorderAndShadowBoundRect = _pViewShell->GetOut()->PixelToLogic( aPagePxRect.SVRect() );
+}
+
+SwRect SwPageFrm::GetBoundRect() const
+{
+ const ViewShell *pSh = getRootFrm()->GetCurrShell();
+ SwRect aPageRect( Frm() );
+ SwRect aResult;
+
+ if(!pSh) {
+ return SwRect( Point(0, 0), Size(0, 0) );
+ }
+
+ SwPageFrm::GetBorderAndShadowBoundRect( aPageRect, pSh, aResult,
+ IsLeftShadowNeeded(), IsRightShadowNeeded(), SidebarPosition() == sw::sidebarwindows::SIDEBAR_RIGHT );
+ return aResult;
+}
+
+/*static*/ void SwPageFrm::AddSidebarBorders(SwRect &aRect, ViewShell* _pViewShell, bool bRightSidebar, bool bPx)
+{
+ const SwPostItMgr *pMgr = _pViewShell ? _pViewShell->GetPostItMgr() : 0;
+ if (pMgr && pMgr->ShowNotes() && pMgr->HasNotes())
+ {
+ if (!bRightSidebar)
+ aRect.SetLeftAndWidth(aRect.Left() - pMgr->GetSidebarWidth(bPx) - pMgr->GetSidebarBorderWidth(bPx), aRect.Width() + pMgr->GetSidebarWidth(bPx) + pMgr->GetSidebarBorderWidth(bPx));
+ else
+ aRect.AddRight(pMgr->GetSidebarWidth(bPx) + pMgr->GetSidebarBorderWidth(bPx));
+ }
+}
+
+/*static*/ void SwPageFrm::AddSidebarBorders(Rectangle &aRect, ViewShell* _pViewShell, bool bRightSidebar, bool bPx)
+{
+ const SwPostItMgr *pMgr = _pViewShell ? _pViewShell->GetPostItMgr() : 0;
+ if (pMgr && pMgr->ShowNotes() && pMgr->HasNotes())
+ {
+ if (!bRightSidebar)
+ aRect.Left() -= (pMgr->GetSidebarWidth(bPx) + pMgr->GetSidebarBorderWidth(bPx));
+ else
+ aRect.Right() += pMgr->GetSidebarWidth(bPx) + pMgr->GetSidebarBorderWidth(bPx);
+ }
+}
+
+/*static*/ SwTwips SwPageFrm::GetSidebarBorderWidth( const ViewShell* _pViewShell )
+{
+ const SwPostItMgr* pPostItMgr = _pViewShell ? _pViewShell->GetPostItMgr() : 0;
+ const SwTwips nRet = pPostItMgr && pPostItMgr->HasNotes() && pPostItMgr->ShowNotes() ? pPostItMgr->GetSidebarWidth() + pPostItMgr->GetSidebarBorderWidth() : 0;
+ return nRet;
+}
+
+/*************************************************************************
+|*
+|* SwFrm::PaintBaBo()
+|*
+|*************************************************************************/
+
+void SwFrm::PaintBaBo( const SwRect& rRect, const SwPageFrm *pPage,
+ const sal_Bool bLowerBorder ) const
+{
+ if ( !pPage )
+ pPage = FindPageFrm();
+
+ OutputDevice *pOut = pGlobalShell->GetOut();
+
+ // --> FME 2004-06-24 #i16816# tagged pdf support
+ SwTaggedPDFHelper aTaggedPDFHelper( 0, 0, 0, *pOut );
+ // <--
+
+ // OD 2004-04-23 #116347#
+ pOut->Push( PUSH_FILLCOLOR|PUSH_LINECOLOR );
+ pOut->SetLineColor();
+
+ SwBorderAttrAccess aAccess( SwFrm::GetCache(), (SwFrm*)this );
+ const SwBorderAttrs &rAttrs = *aAccess.Get();
+
+ // OD 20.11.2002 #104598# - take care of page margin area
+ // Note: code move from <SwFrm::PaintBackground(..)> to new method
+ // <SwPageFrm::Paintmargin(..)>.
+ if ( IsPageFrm() )
+ {
+ static_cast<const SwPageFrm*>(this)->PaintMarginArea( rRect, pGlobalShell );
+ }
+
+ // paint background
+ {
+ PaintBackground( rRect, pPage, rAttrs, sal_False, bLowerBorder );
+ }
+
+ // OD 06.08.2002 #99657# - paint border before painting background
+ // paint grid for page frame and paint border
+ {
+ SwRect aRect( rRect );
+ if( IsPageFrm() )
+ ((SwPageFrm*)this)->PaintGrid( pOut, aRect );
+ PaintBorder( aRect, pPage, rAttrs );
+ }
+
+ pOut->Pop();
+}
+
+/*************************************************************************
+|*
+|* SwFrm::PaintBackground()
+|*
+|*************************************************************************/
+/// OD 05.09.2002 #102912#
+/// Do not paint background for fly frames without a background brush by
+/// calling <PaintBaBo> at the page or at the fly frame its anchored
+void SwFrm::PaintBackground( const SwRect &rRect, const SwPageFrm *pPage,
+ const SwBorderAttrs & rAttrs,
+ const sal_Bool bLowerMode,
+ const sal_Bool bLowerBorder ) const
+{
+ // OD 20.01.2003 #i1837# - no paint of table background, if corresponding
+ // option is *not* set.
+ if( IsTabFrm() &&
+ !pGlobalShell->GetViewOptions()->IsTable() )
+ {
+ return;
+ }
+
+ // nothing to do for covered table cells:
+ if( IsCellFrm() && IsCoveredCell() )
+ return;
+
+ ViewShell *pSh = pGlobalShell;
+
+ // --> FME 2004-06-24 #i16816# tagged pdf support
+ SwTaggedPDFHelper aTaggedPDFHelper( 0, 0, 0, *pSh->GetOut() );
+ // <--
+
+ const SvxBrushItem* pItem;
+ /// OD 05.09.2002 #102912#
+ /// temporary background brush for a fly frame without a background brush
+ SvxBrushItem* pTmpBackBrush = 0;
+ const Color* pCol;
+ SwRect aOrigBackRect;
+ const sal_Bool bPageFrm = IsPageFrm();
+ sal_Bool bLowMode = sal_True;
+
+ sal_Bool bBack = GetBackgroundBrush( pItem, pCol, aOrigBackRect, bLowerMode );
+ //- Ausgabe wenn ein eigener Hintergrund mitgebracht wird.
+ bool bNoFlyBackground = !bFlyMetafile && !bBack && IsFlyFrm();
+ if ( bNoFlyBackground )
+ {
+ // OD 05.09.2002 #102912# - Fly frame has no background.
+ // Try to find background brush at parents, if previous call of
+ // <GetBackgroundBrush> disabled this option with the parameter <bLowerMode>
+ if ( bLowerMode )
+ {
+ bBack = GetBackgroundBrush( pItem, pCol, aOrigBackRect, false );
+ }
+ // If still no background found for the fly frame, initialize the
+ // background brush <pItem> with global retouche color and set <bBack>
+ // to sal_True, that fly frame will paint its background using this color.
+ if ( !bBack )
+ {
+ // OD 10.01.2003 #i6467# - on print output, pdf output and
+ // in embedded mode not editing color COL_WHITE is used instead of
+ // the global retouche color.
+ if ( pSh->GetOut()->GetOutDevType() == OUTDEV_PRINTER ||
+ pSh->GetViewOptions()->IsPDFExport() ||
+ ( pSh->GetDoc()->GetDocShell()->GetCreateMode() == SFX_CREATE_MODE_EMBEDDED &&
+ !pSh->GetDoc()->GetDocShell()->IsInPlaceActive()
+ )
+ )
+ {
+ pTmpBackBrush = new SvxBrushItem( Color( COL_WHITE ), RES_BACKGROUND );
+ }
+ else
+ {
+ pTmpBackBrush = new SvxBrushItem( aGlobalRetoucheColor, RES_BACKGROUND);
+ }
+ pItem = pTmpBackBrush;
+ bBack = true;
+ }
+ }
+
+ SwRect aPaintRect( Frm() );
+ if( IsTxtFrm() || IsSctFrm() )
+ aPaintRect = UnionFrm( sal_True );
+
+ if ( aPaintRect.IsOver( rRect ) )
+ {
+ if ( bBack || bPageFrm || !bLowerMode )
+ {
+ const sal_Bool bBrowse = pSh->GetViewOptions()->getBrowseMode();
+ SwRect aRect;
+ if ( (bPageFrm && bBrowse) ||
+ (IsTxtFrm() && Prt().SSize() == Frm().SSize()) )
+ {
+ aRect = Frm();
+ ::SwAlignRect( aRect, pGlobalShell );
+ }
+ else
+ {
+ ::lcl_CalcBorderRect( aRect, this, rAttrs, sal_False );
+ if ( (IsTxtFrm() || IsTabFrm()) && GetPrev() )
+ {
+ if ( GetPrev()->GetAttrSet()->GetBackground() ==
+ GetAttrSet()->GetBackground() )
+ {
+ aRect.Top( Frm().Top() );
+ }
+ }
+ }
+ aRect.Intersection( rRect );
+
+ OutputDevice *pOut = pSh->GetOut();
+
+ if ( aRect.HasArea() )
+ {
+ SvxBrushItem* pNewItem = 0;
+ SwRegionRects aRegion( aRect );
+ if( pCol )
+ {
+ pNewItem = new SvxBrushItem( *pCol, RES_BACKGROUND );
+ pItem = pNewItem;
+ }
+ if ( pPage->GetSortedObjs() )
+ ::lcl_SubtractFlys( this, pPage, aRect, aRegion );
+
+ {
+ /// OD 06.08.2002 #99657# - determine, if background transparency
+ /// have to be considered for drawing.
+ /// --> Status Quo: background transparency have to be
+ /// considered for fly frames
+ const sal_Bool bConsiderBackgroundTransparency = IsFlyFrm();
+ for ( sal_uInt16 i = 0; i < aRegion.Count(); ++i )
+ {
+ if ( 1 < aRegion.Count() )
+ {
+ ::SwAlignRect( aRegion[i], pGlobalShell );
+ if( !aRegion[i].HasArea() )
+ continue;
+ }
+ /// OD 06.08.2002 #99657# - add 6th parameter to indicate, if
+ /// background transparency have to be considered
+ /// Set missing 5th parameter to the default value GRFNUM_NO
+ /// - see declaration in /core/inc/frmtool.hxx.
+ ::DrawGraphic( pItem, pOut, aOrigBackRect, aRegion[i], GRFNUM_NO,
+ bConsiderBackgroundTransparency );
+ }
+ }
+ if( pCol )
+ delete pNewItem;
+ }
+ }
+ else
+ bLowMode = bLowerMode ? sal_True : sal_False;
+ }
+
+ /// OD 05.09.2002 #102912#
+ /// delete temporary background brush.
+ delete pTmpBackBrush;
+
+ //Jetzt noch Lower und dessen Nachbarn.
+ //Wenn ein Frn dabei die Kette verlaesst also nicht mehr Lower von mir ist
+ //so hoert der Spass auf.
+ const SwFrm *pFrm = GetLower();
+ if ( pFrm )
+ {
+ SwRect aFrmRect;
+ SwRect aRect( PaintArea() );
+ aRect._Intersection( rRect );
+ SwRect aBorderRect( aRect );
+ SwShortCut aShortCut( *pFrm, aBorderRect );
+ do
+ { if ( pProgress )
+ pProgress->Reschedule();
+
+ aFrmRect = pFrm->PaintArea();
+ if ( aFrmRect.IsOver( aBorderRect ) )
+ {
+ SwBorderAttrAccess aAccess( SwFrm::GetCache(), (SwFrm*)pFrm );
+ const SwBorderAttrs &rTmpAttrs = *aAccess.Get();
+ /// OD 06.08.2002 #99657# - paint border before painting background
+ if ( bLowerBorder )
+ pFrm->PaintBorder( aBorderRect, pPage, rTmpAttrs );
+ if ( ( pFrm->IsLayoutFrm() && bLowerBorder ) ||
+ aFrmRect.IsOver( aRect ) )
+ pFrm->PaintBackground( aRect, pPage, rTmpAttrs, bLowMode,
+ bLowerBorder );
+ }
+ pFrm = pFrm->GetNext();
+ } while ( pFrm && pFrm->GetUpper() == this &&
+ !aShortCut.Stop( aFrmRect ) );
+ }
+}
+
+/*************************************************************************
+|*
+|* SwPageFrm::RefreshSubsidiary()
+|*
+|* Beschreibung Erneuert alle Hilfslinien der Seite.
+|*
+|*************************************************************************/
+
+void SwPageFrm::RefreshSubsidiary( const SwRect &rRect ) const
+{
+ if ( IS_SUBS || IS_SUBS_TABLE || IS_SUBS_SECTION || IS_SUBS_FLYS )
+ {
+ SwRect aRect( rRect );
+ // OD 18.02.2003 #104989# - Not necessary and incorrect alignment of
+ // the output rectangle.
+ //::SwAlignRect( aRect, pGlobalShell );
+ if ( aRect.HasArea() )
+ {
+ //Beim Paint ueber die Root wird das Array von dort gesteuert.
+ //Anderfalls kuemmern wir uns selbst darum.
+ sal_Bool bDelSubs = sal_False;
+ if ( !pSubsLines )
+ {
+ pSubsLines = new SwSubsRects;
+ // OD 20.12.2002 #106318# - create container for special subsidiary lines
+ pSpecSubsLines = new SwSubsRects;
+ bDelSubs = sal_True;
+ }
+
+ RefreshLaySubsidiary( this, aRect );
+
+ if ( bDelSubs )
+ {
+ // OD 20.12.2002 #106318# - paint special subsidiary lines
+ // and delete its container
+ pSpecSubsLines->PaintSubsidiary( pGlobalShell->GetOut(), NULL );
+ DELETEZ( pSpecSubsLines );
+
+ pSubsLines->PaintSubsidiary( pGlobalShell->GetOut(), pLines );
+ DELETEZ( pSubsLines );
+ }
+ }
+ }
+}
+
+/*************************************************************************
+|*
+|* SwLayoutFrm::RefreshLaySubsidiary()
+|*
+|*************************************************************************/
+void SwLayoutFrm::RefreshLaySubsidiary( const SwPageFrm *pPage,
+ const SwRect &rRect ) const
+{
+ const sal_Bool bNoLowerColumn = !Lower() || !Lower()->IsColumnFrm();
+ const sal_Bool bSubsOpt = IS_SUBS;
+ const sal_Bool bSubsTable = ((GetType() & (FRM_ROW | FRM_CELL)) && IS_SUBS_TABLE);
+ const sal_Bool bSubsOther = (GetType() & (FRM_HEADER | FRM_FOOTER | FRM_FTN )) && bSubsOpt;
+ const sal_Bool bSubsSect = IsSctFrm() &&
+ bNoLowerColumn &&
+ IS_SUBS_SECTION;
+ const sal_Bool bSubsFly = IS_SUBS_FLYS &&
+ (GetType() & FRM_FLY) &&
+ bNoLowerColumn &&
+ (!Lower() || !Lower()->IsNoTxtFrm() ||
+ !((SwNoTxtFrm*)Lower())->HasAnimation());
+ sal_Bool bSubsBody = sal_False;
+ if ( GetType() & FRM_BODY )
+ {
+ if ( IsPageBodyFrm() )
+ bSubsBody = bSubsOpt && bNoLowerColumn; //nur ohne Spalten
+ else //Spaltenbody
+ {
+ if ( GetUpper()->GetUpper()->IsSctFrm() )
+ bSubsBody = IS_SUBS_SECTION;
+ else
+ bSubsBody = bSubsOpt;
+ }
+ }
+
+ if ( bSubsOther || bSubsSect || bSubsBody || bSubsTable || bSubsFly )
+ PaintSubsidiaryLines( pPage, rRect );
+
+ const SwFrm *pLow = Lower();
+ if( !pLow )
+ return;
+ SwShortCut aShortCut( *pLow, rRect );
+ while( pLow && !aShortCut.Stop( pLow->Frm() ) )
+ {
+ if ( pLow->Frm().IsOver( rRect ) && pLow->Frm().HasArea() )
+ {
+ if ( pLow->IsLayoutFrm() )
+ ((const SwLayoutFrm*)pLow)->RefreshLaySubsidiary( pPage, rRect);
+ else if ( pLow->GetDrawObjs() )
+ {
+ const SwSortedObjs& rObjs = *(pLow->GetDrawObjs());
+ for ( sal_uInt32 i = 0; i < rObjs.Count(); ++i )
+ {
+ const SwAnchoredObject* pAnchoredObj = rObjs[i];
+ if ( pPage->GetFmt()->GetDoc()->IsVisibleLayerId(
+ pAnchoredObj->GetDrawObj()->GetLayer() ) &&
+ pAnchoredObj->ISA(SwFlyFrm) )
+ {
+ const SwFlyFrm *pFly =
+ static_cast<const SwFlyFrm*>(pAnchoredObj);
+ if ( pFly->IsFlyInCntFrm() && pFly->Frm().IsOver( rRect ) )
+ {
+ if ( !pFly->Lower() || !pFly->Lower()->IsNoTxtFrm() ||
+ !((SwNoTxtFrm*)pFly->Lower())->HasAnimation())
+ pFly->RefreshLaySubsidiary( pPage, rRect );
+ }
+ }
+ }
+ }
+ }
+ pLow = pLow->GetNext();
+ }
+}
+
+/*************************************************************************
+|*
+|* SwLayoutFrm::PaintSubsidiaryLines()
+|*
+|* Beschreibung Hilfslinien um die PrtAreas malen
+|* Nur die LayoutFrm's die direkt Cntnt enthalten.
+|*
+|*************************************************************************/
+
+//Malt die angegebene Linie, achtet darauf, dass keine Flys uebermalt werden.
+
+typedef long Size::* SizePtr;
+typedef long Point::* PointPtr;
+
+PointPtr pX = &Point::nA;
+PointPtr pY = &Point::nB;
+SizePtr pWidth = &Size::nA;
+SizePtr pHeight = &Size::nB;
+
+// OD 18.11.2002 #99672# - new parameter <_pSubsLines>
+void MA_FASTCALL lcl_RefreshLine( const SwLayoutFrm *pLay,
+ const SwPageFrm *pPage,
+ const Point &rP1,
+ const Point &rP2,
+ const sal_uInt8 nSubColor,
+ SwLineRects* _pSubsLines )
+{
+ //In welche Richtung gehts? Kann nur Horizontal oder Vertikal sein.
+ OSL_ENSURE( ((rP1.X() == rP2.X()) || (rP1.Y() == rP2.Y())),
+ "Schraege Hilfslinien sind nicht erlaubt." );
+ const PointPtr pDirPt = rP1.X() == rP2.X() ? pY : pX;
+ const PointPtr pOthPt = pDirPt == pX ? pY : pX;
+ const SizePtr pDirSz = pDirPt == pX ? pWidth : pHeight;
+ const SizePtr pOthSz = pDirSz == pWidth ? pHeight : pWidth;
+ Point aP1( rP1 ),
+ aP2( rP2 );
+
+ while ( aP1.*pDirPt < aP2.*pDirPt )
+ { //Der Startpunkt wird jetzt, falls er in einem Fly sitzt, direkt
+ //hinter den Fly gesetzt.
+ //Wenn der Endpunkt in einem Fly sitzt oder zwischen Start und Endpunkt
+ //ein Fly sitzt, so wird der Endpunkt eben an den Start herangezogen.
+ //Auf diese art und weise wird eine Portion nach der anderen
+ //ausgegeben.
+
+ //Wenn ich selbst ein Fly bin, weiche ich nur denjenigen Flys aus,
+ //die 'ueber' mir sitzen; d.h. die in dem Array hinter mir stehen.
+ //Auch wenn ich in einem Fly sitze oder in einem Fly im Fly usw. weiche
+ //ich keinem dieser Flys aus.
+ SwOrderIter aIter( pPage );
+ const SwFlyFrm *pMyFly = pLay->FindFlyFrm();
+ if ( pMyFly )
+ {
+ aIter.Current( pMyFly->GetVirtDrawObj() );
+ while ( 0 != (pMyFly = pMyFly->GetAnchorFrm()->FindFlyFrm()) )
+ {
+ if ( aIter()->GetOrdNum() > pMyFly->GetVirtDrawObj()->GetOrdNum() )
+ aIter.Current( pMyFly->GetVirtDrawObj() );
+ }
+ }
+ else
+ aIter.Bottom();
+
+ while ( aIter() )
+ {
+ const SwVirtFlyDrawObj *pObj = (SwVirtFlyDrawObj*)aIter();
+ const SwFlyFrm *pFly = pObj ? pObj->GetFlyFrm() : 0;
+
+ //Mir selbst weiche ich natuerlich nicht aus. Auch wenn ich
+ //_in_ dem Fly sitze weiche ich nicht aus.
+ if ( !pFly || (pFly == pLay || pFly->IsAnLower( pLay )) )
+ {
+ aIter.Next();
+ continue;
+ }
+
+ // OD 19.12.2002 #106318# - do *not* consider fly frames with
+ // a transparent background.
+ // OD 2004-02-12 #110582#-2 - do *not* consider fly frame, which
+ // belongs to a invisible layer
+ if ( pFly->IsBackgroundTransparent() ||
+ !pFly->GetFmt()->GetDoc()->IsVisibleLayerId( pObj->GetLayer() ) )
+ {
+ aIter.Next();
+ continue;
+ }
+
+ //Sitzt das Obj auf der Linie
+ const Rectangle &rBound = pObj->GetCurrentBoundRect();
+ const Point aDrPt( rBound.TopLeft() );
+ const Size aDrSz( rBound.GetSize() );
+ if ( rP1.*pOthPt >= aDrPt.*pOthPt &&
+ rP1.*pOthPt <= (aDrPt.*pOthPt + aDrSz.*pOthSz) )
+ {
+ if ( aP1.*pDirPt >= aDrPt.*pDirPt &&
+ aP1.*pDirPt <= (aDrPt.*pDirPt + aDrSz.*pDirSz) )
+ aP1.*pDirPt = aDrPt.*pDirPt + aDrSz.*pDirSz;
+
+ if ( aP2.*pDirPt >= aDrPt.*pDirPt &&
+ aP1.*pDirPt < (aDrPt.*pDirPt - 1) )
+ aP2.*pDirPt = aDrPt.*pDirPt - 1;
+ }
+ aIter.Next();
+ }
+
+ if ( aP1.*pDirPt < aP2.*pDirPt )
+ {
+ SwRect aRect( aP1, aP2 );
+ // OD 18.11.2002 #99672# - use parameter <_pSubsLines> instead of
+ // global variable <pSubsLines>.
+ _pSubsLines->AddLineRect( aRect, 0, SOLID, 0, nSubColor );
+ }
+ aP1 = aP2;
+ aP1.*pDirPt += 1;
+ aP2 = rP2;
+ }
+}
+
+void SwLayoutFrm::PaintSubsidiaryLines( const SwPageFrm *pPage,
+ const SwRect &rRect ) const
+{
+ bool bNewTableModel = false;
+
+ // --> collapsing borders FME 2005-05-27 #i29550#
+ if ( IsTabFrm() || IsCellFrm() || IsRowFrm() )
+ {
+ const SwTabFrm* pTabFrm = FindTabFrm();
+ if ( pTabFrm->IsCollapsingBorders() )
+ return;
+
+ bNewTableModel = pTabFrm->GetTable()->IsNewModel();
+ // in the new table model, we have an early return for all cell-related
+ // frames, except from non-covered table cells
+ if ( bNewTableModel )
+ if ( IsTabFrm() ||
+ IsRowFrm() ||
+ ( IsCellFrm() && IsCoveredCell() ) )
+ return;
+ }
+ // <-- collapsing
+
+ const bool bFlys = pPage->GetSortedObjs() ? true : false;
+
+ const bool bCell = IsCellFrm() ? true : false;
+ // use frame area for cells
+ // OD 13.02.2003 #i3662# - for section use also frame area
+ const bool bUseFrmArea = bCell || IsSctFrm();
+ SwRect aOriginal( bUseFrmArea ? Frm() : Prt() );
+ if ( !bUseFrmArea )
+ aOriginal.Pos() += Frm().Pos();
+
+ // OD 13.02.2003 #i3662# - enlarge top of column body frame's printing area
+ // in sections to top of section frame.
+ const bool bColBodyInSection = IsBodyFrm() &&
+ !IsPageBodyFrm() &&
+ GetUpper()->GetUpper()->IsSctFrm();
+ if ( bColBodyInSection )
+ {
+ if ( IsVertical() )
+ aOriginal.Right( GetUpper()->GetUpper()->Frm().Right() );
+ else
+ aOriginal.Top( GetUpper()->GetUpper()->Frm().Top() );
+ }
+
+ ::SwAlignRect( aOriginal, pGlobalShell );
+
+ if ( !aOriginal.IsOver( rRect ) )
+ return;
+
+ SwRect aOut( aOriginal );
+ aOut._Intersection( rRect );
+ // OD 13.02.2003 #i3662# - do not intersect *enlarged* column body frame's
+ // printing area with the paint area of the body frame. Otherwise enlargement
+ // will get lost.
+ if ( !bColBodyInSection )
+ {
+ aOut.Intersection( PaintArea() );
+ }
+
+ const SwTwips nRight = aOut.Right();
+ const SwTwips nBottom= aOut.Bottom();
+
+ const Point aRT( nRight, aOut.Top() );
+ const Point aRB( nRight, nBottom );
+ const Point aLB( aOut.Left(), nBottom );
+
+ sal_uInt8 nSubColor = ( bCell || IsRowFrm() ) ? SUBCOL_TAB :
+ ( IsInSct() ? SUBCOL_SECT :
+ ( IsInFly() ? SUBCOL_FLY : SUBCOL_PAGE ) );
+
+ // OD 05.11.2002 #102406# - body frames are responsible for page/column breaks.
+ sal_Bool bBreak = sal_False;
+ if ( IsBodyFrm() )
+ {
+ const SwCntntFrm *pCnt = ContainsCntnt();
+ if ( pCnt )
+ {
+ // OD 05.11.2002 #102406# - adjust setting of <bBreak>.
+ bBreak = pCnt->IsPageBreak( sal_True ) ||
+ ( IsColBodyFrm() && pCnt->IsColBreak( sal_True ) );
+ }
+ }
+
+ // OD 18.11.2002 #99672# - collect body, header, footer, footnote and section
+ // sub-lines in <pSpecSubsLine> array.
+ const bool bSpecialSublines = IsBodyFrm() || IsHeaderFrm() || IsFooterFrm() ||
+ IsFtnFrm() || IsSctFrm();
+ SwLineRects* pUsedSubsLines = bSpecialSublines ? pSpecSubsLines : pSubsLines;
+
+ // NOTE: for cell frames only left and right (horizontal layout) respectively
+ // top and bottom (vertical layout) lines painted.
+ // NOTE2: this does not hold for the new table model!!! We paint the top border
+ // of each non-covered table cell.
+ const bool bVert = IsVertical() ? true : false;
+ if ( bFlys )
+ {
+ // OD 14.11.2002 #104822# - add control for drawing left and right lines
+ if ( !bCell || bNewTableModel || !bVert )
+ {
+ if ( aOriginal.Left() == aOut.Left() )
+ ::lcl_RefreshLine( this, pPage, aOut.Pos(), aLB, nSubColor,
+ pUsedSubsLines );
+ // OD 14.11.2002 #104821# - in vertical layout set page/column break at right
+ if ( aOriginal.Right() == nRight )
+ ::lcl_RefreshLine( this, pPage, aRT, aRB,
+ (bBreak && bVert) ? SUBCOL_BREAK : nSubColor,
+ pUsedSubsLines );
+ }
+ // OD 14.11.2002 #104822# - adjust control for drawing top and bottom lines
+ if ( !bCell || bNewTableModel || bVert )
+ {
+ if ( aOriginal.Top() == aOut.Top() )
+ // OD 14.11.2002 #104821# - in horizontal layout set page/column break at top
+ ::lcl_RefreshLine( this, pPage, aOut.Pos(), aRT,
+ (bBreak && !bVert) ? SUBCOL_BREAK : nSubColor,
+ pUsedSubsLines );
+ if ( aOriginal.Bottom() == nBottom )
+ ::lcl_RefreshLine( this, pPage, aLB, aRB, nSubColor,
+ pUsedSubsLines );
+ }
+ }
+ else
+ {
+ // OD 14.11.2002 #104822# - add control for drawing left and right lines
+ if ( !bCell || bNewTableModel || !bVert )
+ {
+ if ( aOriginal.Left() == aOut.Left() )
+ {
+ const SwRect aRect( aOut.Pos(), aLB );
+ pUsedSubsLines->AddLineRect( aRect, 0, SOLID, 0, nSubColor );
+ }
+ // OD 14.11.2002 #104821# - in vertical layout set page/column break at right
+ if ( aOriginal.Right() == nRight )
+ {
+ const SwRect aRect( aRT, aRB );
+ pUsedSubsLines->AddLineRect( aRect, 0, SOLID, 0,
+ (bBreak && bVert) ? SUBCOL_BREAK : nSubColor );
+ }
+ }
+ // OD 14.11.2002 #104822# - adjust control for drawing top and bottom lines
+ if ( !bCell || bNewTableModel || bVert )
+ {
+ if ( aOriginal.Top() == aOut.Top() )
+ {
+ // OD 14.11.2002 #104821# - in horizontal layout set page/column break at top
+ const SwRect aRect( aOut.Pos(), aRT );
+ pUsedSubsLines->AddLineRect( aRect, 0, SOLID, 0,
+ (bBreak && !bVert) ? SUBCOL_BREAK : nSubColor );
+ }
+ if ( aOriginal.Bottom() == nBottom )
+ {
+ const SwRect aRect( aLB, aRB );
+ pUsedSubsLines->AddLineRect( aRect, 0, SOLID, 0, nSubColor );
+ }
+ }
+ }
+}
+
+/*************************************************************************
+|*
+|* SwPageFrm::RefreshExtraData(), SwLayoutFrm::RefreshExtraData()
+|*
+|* Beschreibung Erneuert alle Extradaten (Zeilennummern usw) der Seite.
+|* Grundsaetzlich sind nur diejenigen Objekte beruecksichtig,
+|* die in die seitliche Ausdehnung des Rects ragen.
+|*
+|*************************************************************************/
+
+void SwPageFrm::RefreshExtraData( const SwRect &rRect ) const
+{
+ const SwLineNumberInfo &rInfo = GetFmt()->GetDoc()->GetLineNumberInfo();
+ sal_Bool bLineInFly = (rInfo.IsPaintLineNumbers() && rInfo.IsCountInFlys())
+ || (sal_Int16)SW_MOD()->GetRedlineMarkPos() != text::HoriOrientation::NONE;
+
+ SwRect aRect( rRect );
+ ::SwAlignRect( aRect, pGlobalShell );
+ if ( aRect.HasArea() )
+ {
+ SwLayoutFrm::RefreshExtraData( aRect );
+
+ if ( bLineInFly && GetSortedObjs() )
+ for ( sal_uInt16 i = 0; i < GetSortedObjs()->Count(); ++i )
+ {
+ const SwAnchoredObject* pAnchoredObj = (*GetSortedObjs())[i];
+ if ( pAnchoredObj->ISA(SwFlyFrm) )
+ {
+ const SwFlyFrm *pFly = static_cast<const SwFlyFrm*>(pAnchoredObj);
+ if ( pFly->Frm().Top() <= aRect.Bottom() &&
+ pFly->Frm().Bottom() >= aRect.Top() )
+ pFly->RefreshExtraData( aRect );
+ }
+ }
+ }
+}
+
+void SwLayoutFrm::RefreshExtraData( const SwRect &rRect ) const
+{
+
+ const SwLineNumberInfo &rInfo = GetFmt()->GetDoc()->GetLineNumberInfo();
+ sal_Bool bLineInBody = rInfo.IsPaintLineNumbers(),
+ bLineInFly = bLineInBody && rInfo.IsCountInFlys(),
+ bRedLine = (sal_Int16)SW_MOD()->GetRedlineMarkPos()!=text::HoriOrientation::NONE;
+
+ const SwCntntFrm *pCnt = ContainsCntnt();
+ while ( pCnt && IsAnLower( pCnt ) )
+ {
+ if ( pCnt->IsTxtFrm() && ( bRedLine ||
+ ( !pCnt->IsInTab() &&
+ ((bLineInBody && pCnt->IsInDocBody()) ||
+ (bLineInFly && pCnt->IsInFly())) ) ) &&
+ pCnt->Frm().Top() <= rRect.Bottom() &&
+ pCnt->Frm().Bottom() >= rRect.Top() )
+ {
+ ((SwTxtFrm*)pCnt)->PaintExtraData( rRect );
+ }
+ if ( bLineInFly && pCnt->GetDrawObjs() )
+ for ( sal_uInt32 i = 0; i < pCnt->GetDrawObjs()->Count(); ++i )
+ {
+ const SwAnchoredObject* pAnchoredObj = (*pCnt->GetDrawObjs())[i];
+ if ( pAnchoredObj->ISA(SwFlyFrm) )
+ {
+ const SwFlyFrm *pFly = static_cast<const SwFlyFrm*>(pAnchoredObj);
+ if ( pFly->IsFlyInCntFrm() &&
+ pFly->Frm().Top() <= rRect.Bottom() &&
+ pFly->Frm().Bottom() >= rRect.Top() )
+ pFly->RefreshExtraData( rRect );
+ }
+ }
+ pCnt = pCnt->GetNextCntntFrm();
+ }
+}
+
+/** SwPageFrm::GetDrawBackgrdColor - for #102450#
+
+ determine the color, that is respectively will be drawn as background
+ for the page frame.
+ Using existing method SwFrm::GetBackgroundBrush to determine the color
+ that is set at the page frame respectively is parent. If none is found
+ return the global retouche color
+
+ @author OD
+
+ @return Color
+*/
+const Color& SwPageFrm::GetDrawBackgrdColor() const
+{
+ const SvxBrushItem* pBrushItem;
+ const Color* pDummyColor;
+ SwRect aDummyRect;
+ if ( GetBackgroundBrush( pBrushItem, pDummyColor, aDummyRect, true) )
+ return pBrushItem->GetColor();
+ else
+ return aGlobalRetoucheColor;
+}
+
+/*************************************************************************
+|*
+|* SwPageFrm::GetEmptyPageFont()
+|*
+|* create/return font used to paint the "empty page" string
+|*
+|*************************************************************************/
+
+const Font& SwPageFrm::GetEmptyPageFont()
+{
+ static Font* pEmptyPgFont = 0;
+ if ( 0 == pEmptyPgFont )
+ {
+ pEmptyPgFont = new Font;
+ pEmptyPgFont->SetSize( Size( 0, 80 * 20 )); // == 80 pt
+ pEmptyPgFont->SetWeight( WEIGHT_BOLD );
+ pEmptyPgFont->SetStyleName( aEmptyStr );
+ pEmptyPgFont->SetName( String::CreateFromAscii(
+ RTL_CONSTASCII_STRINGPARAM( "Helvetica" )) );
+ pEmptyPgFont->SetFamily( FAMILY_SWISS );
+ pEmptyPgFont->SetTransparent( sal_True );
+ pEmptyPgFont->SetColor( COL_GRAY );
+ }
+
+ return *pEmptyPgFont;
+}
+
+/*************************************************************************
+|*
+|* SwFrm::Retouche
+|*
+|* Beschreibung Retouche fuer einen Bereich.
+|* Retouche wird nur dann durchgefuehrt, wenn der Frm der letzte seiner
+|* Kette ist. Der Gesamte Bereich des Upper unterhalb des Frm wird
+|* per PaintBackground gecleared.
+|*
+|*************************************************************************/
+
+void SwFrm::Retouche( const SwPageFrm * pPage, const SwRect &rRect ) const
+{
+ if ( bFlyMetafile )
+ return;
+
+ OSL_ENSURE( GetUpper(), "Retoucheversuch ohne Upper." );
+ OSL_ENSURE( getRootFrm()->GetCurrShell() && pGlobalShell->GetWin(), "Retouche auf dem Drucker?" );
+
+ SwRect aRetouche( GetUpper()->PaintArea() );
+ aRetouche.Top( Frm().Top() + Frm().Height() );
+ aRetouche.Intersection( pGlobalShell->VisArea() );
+
+ if ( aRetouche.HasArea() )
+ {
+ //Uebergebenes Rect ausparen. Dafuer brauchen wir leider eine Region
+ //zum ausstanzen.
+ SwRegionRects aRegion( aRetouche );
+ aRegion -= rRect;
+ ViewShell *pSh = getRootFrm()->GetCurrShell();
+
+ // --> FME 2004-06-24 #i16816# tagged pdf support
+ SwTaggedPDFHelper aTaggedPDFHelper( 0, 0, 0, *pSh->GetOut() );
+ // <--
+
+ for ( sal_uInt16 i = 0; i < aRegion.Count(); ++i )
+ {
+ SwRect &rRetouche = aRegion[i];
+
+ GetUpper()->PaintBaBo( rRetouche, pPage, sal_True );
+
+ //Hoelle und Himmel muessen auch refreshed werden.
+ //Um Rekursionen zu vermeiden muss mein Retouche Flag zuerst
+ //zurueckgesetzt werden!
+ ResetRetouche();
+ SwRect aRetouchePart( rRetouche );
+ if ( aRetouchePart.HasArea() )
+ {
+ // OD 30.08.2002 #102450#
+ // determine background color of page for <PaintLayer> method
+ // calls, painting <hell> or <heaven>
+ const Color aPageBackgrdColor = pPage->GetDrawBackgrdColor();
+ // OD 29.08.2002 #102450#
+ // add 3rd parameter to <PaintLayer> method calls
+ // OD 09.12.2002 #103045# - add 4th parameter for horizontal text direction.
+ const IDocumentDrawModelAccess* pIDDMA = pSh->getIDocumentDrawModelAccess();
+
+ pSh->Imp()->PaintLayer( pIDDMA->GetHellId(), 0,
+ aRetouchePart, &aPageBackgrdColor,
+ (pPage->IsRightToLeft() ? true : false) );
+ pSh->Imp()->PaintLayer( pIDDMA->GetHeavenId(), 0,
+ aRetouchePart, &aPageBackgrdColor,
+ (pPage->IsRightToLeft() ? true : false) );
+ }
+
+ SetRetouche();
+
+ //Da wir uns ausserhalb aller Paint-Bereiche begeben muessen hier
+ //leider die Hilfslinien erneuert werden.
+ pPage->RefreshSubsidiary( aRetouchePart );
+ }
+ }
+ if ( ViewShell::IsLstEndAction() )
+ ResetRetouche();
+}
+
+/** SwFrm::GetBackgroundBrush
+
+ @descr
+ determine the background brush for the frame:
+ the background brush is taken from it-self or from its parent (anchor/upper).
+ Normally, the background brush is taken, which has no transparent color or
+ which has a background graphic. But there are some special cases:
+ (1) No background brush is taken from a page frame, if view option "IsPageBack"
+ isn't set.
+ (2) Background brush from a index section is taken under special conditions.
+ In this case parameter <rpCol> is set to the index shading color.
+ (3) New (OD 20.08.2002) - Background brush is taken, if on background drawing
+ of the frame transparency is considered and its color is not "no fill"/"auto fill"
+ ---- old description in german:
+ Beschreibung Liefert die Backgroundbrush fuer den Bereich des
+ des Frm. Die Brush wird entweder von ihm selbst oder von einem
+ Upper vorgegeben, die erste Brush wird benutzt.
+ Ist fuer keinen Frm eine Brush angegeben, so wird sal_False zurueck-
+ geliefert.
+
+ @param rpBrush
+ output parameter - constant reference pointer the found background brush
+
+ @param rpCol
+ output parameter - constant reference pointer to the color of the index shading
+ set under special conditions, if background brush is taken from an index section.
+
+ @param rOrigRect
+ in-/output parameter - reference to the retangle the background brush is
+ considered for - adjusted to the frame, from which the background brush is
+ taken.
+
+ @parem bLowerMode
+ input parameter - boolean indicating, if background brush should *not* be
+ taken from parent.
+
+ @return true, if a background brush for the frame is found
+*/
+sal_Bool SwFrm::GetBackgroundBrush( const SvxBrushItem* & rpBrush,
+ const Color*& rpCol,
+ SwRect &rOrigRect,
+ sal_Bool bLowerMode ) const
+{
+ const SwFrm *pFrm = this;
+ ViewShell *pSh = getRootFrm()->GetCurrShell();
+ const SwViewOption *pOpt = pSh->GetViewOptions();
+ rpBrush = 0;
+ rpCol = NULL;
+ do
+ { if ( pFrm->IsPageFrm() && !pOpt->IsPageBack() )
+ return sal_False;
+
+ const SvxBrushItem &rBack = pFrm->GetAttrSet()->GetBackground();
+ if( pFrm->IsSctFrm() )
+ {
+ const SwSection* pSection = ((SwSectionFrm*)pFrm)->GetSection();
+ /// OD 20.08.2002 #99657# #GetTransChg#
+ /// Note: If frame <pFrm> is a section of the index and
+ /// it its background color is "no fill"/"auto fill" and
+ /// it has no background graphic and
+ /// we are not in the page preview and
+ /// we are not in read-only mode and
+ /// option "index shadings" is set and
+ /// the output is not the printer
+ /// then set <rpCol> to the color of the index shading
+ if( pSection && ( TOX_HEADER_SECTION == pSection->GetType() ||
+ TOX_CONTENT_SECTION == pSection->GetType() ) &&
+ (rBack.GetColor() == COL_TRANSPARENT) &&
+ ///rBack.GetColor().GetTransparency() &&
+ rBack.GetGraphicPos() == GPOS_NONE &&
+ !pOpt->IsPagePreview() &&
+ !pOpt->IsReadonly() &&
+ // --> FME 2004-06-29 #114856# Formular view
+ !pOpt->IsFormView() &&
+ // <--
+ SwViewOption::IsIndexShadings() &&
+ !pOpt->IsPDFExport() &&
+ pSh->GetOut()->GetOutDevType() != OUTDEV_PRINTER )
+ {
+ rpCol = &SwViewOption::GetIndexShadingsColor();
+ }
+ }
+
+ /// OD 20.08.2002 #99657#
+ /// determine, if background draw of frame <pFrm> considers transparency
+ /// --> Status Quo: background transparency have to be
+ /// considered for fly frames
+ const sal_Bool bConsiderBackgroundTransparency = pFrm->IsFlyFrm();
+ /// OD 20.08.2002 #99657#
+ /// add condition:
+ /// If <bConsiderBackgroundTransparency> is set - see above -,
+ /// return brush of frame <pFrm>, if its color is *not* "no fill"/"auto fill"
+ if ( !rBack.GetColor().GetTransparency() ||
+ rBack.GetGraphicPos() != GPOS_NONE ||
+ rpCol ||
+ (bConsiderBackgroundTransparency && (rBack.GetColor() != COL_TRANSPARENT))
+ )
+ {
+ rpBrush = &rBack;
+ if ( pFrm->IsPageFrm() &&
+ pSh->GetViewOptions()->getBrowseMode() )
+ rOrigRect = pFrm->Frm();
+ else
+ {
+ if ( pFrm->Frm().SSize() != pFrm->Prt().SSize() )
+ {
+ SwBorderAttrAccess aAccess( SwFrm::GetCache(), pFrm );
+ const SwBorderAttrs &rAttrs = *aAccess.Get();
+ ::lcl_CalcBorderRect( rOrigRect, pFrm, rAttrs, sal_False );
+ }
+ else
+ {
+ rOrigRect = pFrm->Prt();
+ rOrigRect += pFrm->Frm().Pos();
+ }
+ }
+ return sal_True;
+ }
+
+ if ( bLowerMode )
+ /// Do not try to get background brush from parent (anchor/upper)
+ return sal_False;
+
+ /// get parent frame - anchor or upper - for next loop
+ if ( pFrm->IsFlyFrm() )
+ /// OD 20.08.2002 - use "static_cast" instead of "old C-cast"
+ pFrm = (static_cast<const SwFlyFrm*>(pFrm))->GetAnchorFrm();
+ ///pFrm = ((SwFlyFrm*)pFrm)->GetAnchor();
+ else
+ pFrm = pFrm->GetUpper();
+
+ } while ( pFrm );
+
+ return sal_False;
+}
+
+/*************************************************************************
+|*
+|* SwFrmFmt::GetGraphic()
+|*
+|*************************************************************************/
+
+void SetOutDevAndWin( ViewShell *pSh, OutputDevice *pO,
+ Window *pW, sal_uInt16 nZoom )
+{
+ pSh->pOut = pO;
+ pSh->pWin = pW;
+ pSh->pOpt->SetZoom( nZoom );
+}
+
+Graphic SwFrmFmt::MakeGraphic( ImageMap* )
+{
+ return Graphic();
+}
+
+Graphic SwFlyFrmFmt::MakeGraphic( ImageMap* pMap )
+{
+ Graphic aRet;
+ //irgendeinen Fly suchen!
+ SwIterator<SwFrm,SwFmt> aIter( *this );
+ SwFrm *pFirst = aIter.First();
+ ViewShell *pSh;
+ if ( pFirst && 0 != ( pSh = pFirst->getRootFrm()->GetCurrShell()) )
+ {
+ ViewShell *pOldGlobal = pGlobalShell;
+ pGlobalShell = pSh;
+
+ sal_Bool bNoteURL = pMap &&
+ SFX_ITEM_SET != GetAttrSet().GetItemState( RES_URL, sal_True );
+ if( bNoteURL )
+ {
+ OSL_ENSURE( !pNoteURL, "MakeGraphic: pNoteURL already used? " );
+ pNoteURL = new SwNoteURL;
+ }
+ SwFlyFrm *pFly = (SwFlyFrm*)pFirst;
+
+ OutputDevice *pOld = pSh->GetOut();
+ VirtualDevice aDev( *pOld );
+ aDev.EnableOutput( sal_False );
+
+ GDIMetaFile aMet;
+ MapMode aMap( pOld->GetMapMode().GetMapUnit() );
+ aDev.SetMapMode( aMap );
+ aMet.SetPrefMapMode( aMap );
+
+ ::SwCalcPixStatics( pSh->GetOut() );
+ aMet.SetPrefSize( pFly->Frm().SSize() );
+
+ aMet.Record( &aDev );
+ aDev.SetLineColor();
+ aDev.SetFillColor();
+ aDev.SetFont( pOld->GetFont() );
+
+ //Rechteck ggf. ausdehnen, damit die Umrandunge mit aufgezeichnet werden.
+ SwRect aOut( pFly->Frm() );
+ SwBorderAttrAccess aAccess( SwFrm::GetCache(), pFly );
+ const SwBorderAttrs &rAttrs = *aAccess.Get();
+ if ( rAttrs.CalcRightLine() )
+ aOut.SSize().Width() += 2*nPixelSzW;
+ if ( rAttrs.CalcBottomLine() )
+ aOut.SSize().Height()+= 2*nPixelSzH;
+
+ // #i92711# start Pre/PostPaint encapsulation before pOut is changed to the buffering VDev
+ const Region aRepaintRegion(aOut.SVRect());
+ pSh->DLPrePaint2(aRepaintRegion);
+
+ Window *pWin = pSh->GetWin();
+ sal_uInt16 nZoom = pSh->GetViewOptions()->GetZoom();
+ ::SetOutDevAndWin( pSh, &aDev, 0, 100 );
+ bFlyMetafile = sal_True;
+ pFlyMetafileOut = pWin;
+
+ SwViewImp *pImp = pSh->Imp();
+ pFlyOnlyDraw = pFly;
+ pLines = new SwLineRects;
+
+ // OD 09.12.2002 #103045# - determine page, fly frame is on
+ const SwPageFrm* pFlyPage = pFly->FindPageFrm();
+ // OD 30.08.2002 #102450#
+ // determine color of page, the fly frame is on, for <PaintLayer> method
+ // calls, painting <hell> or <heaven>
+ const Color aPageBackgrdColor = pFlyPage->GetDrawBackgrdColor();
+ // OD 30.08.2002 #102450# - add 3rd parameter
+ // OD 09.12.2002 #103045# - add 4th parameter for horizontal text direction.
+ const IDocumentDrawModelAccess* pIDDMA = pSh->getIDocumentDrawModelAccess();
+ pImp->PaintLayer( pIDDMA->GetHellId(), 0, aOut, &aPageBackgrdColor,
+ (pFlyPage->IsRightToLeft() ? true : false) );
+ pLines->PaintLines( &aDev );
+ if ( pFly->IsFlyInCntFrm() )
+ pFly->Paint( aOut );
+ pLines->PaintLines( &aDev );
+ /// OD 30.08.2002 #102450# - add 3rd parameter
+ pImp->PaintLayer( pIDDMA->GetHeavenId(), 0, aOut, &aPageBackgrdColor,
+ (pFlyPage->IsRightToLeft() ? true : false) );
+ pLines->PaintLines( &aDev );
+ DELETEZ( pLines );
+ pFlyOnlyDraw = 0;
+
+ pFlyMetafileOut = 0;
+ bFlyMetafile = sal_False;
+ ::SetOutDevAndWin( pSh, pOld, pWin, nZoom );
+
+ // #i92711# end Pre/PostPaint encapsulation when pOut is back and content is painted
+ pSh->DLPostPaint2(true);
+
+ aMet.Stop();
+ aMet.Move( -pFly->Frm().Left(), -pFly->Frm().Top() );
+ aRet = Graphic( aMet );
+
+ if( bNoteURL )
+ {
+ OSL_ENSURE( pNoteURL, "MakeGraphic: Good Bye, NoteURL." );
+ pNoteURL->FillImageMap( pMap, pFly->Frm().Pos(), aMap );
+ delete pNoteURL;
+ pNoteURL = NULL;
+ }
+ pGlobalShell = pOldGlobal;
+ }
+ return aRet;
+}
+
+Graphic SwDrawFrmFmt::MakeGraphic( ImageMap* )
+{
+ Graphic aRet;
+ SdrModel *pMod = getIDocumentDrawModelAccess()->GetDrawModel();
+ if ( pMod )
+ {
+ SdrObject *pObj = FindSdrObject();
+ SdrView *pView = new SdrView( pMod );
+ SdrPageView *pPgView = pView->ShowSdrPage(pView->GetModel()->GetPage(0));
+ pView->MarkObj( pObj, pPgView );
+ aRet = pView->GetMarkedObjBitmap();
+ pView->HideSdrPage();
+ delete pView;
+ }
+ return aRet;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/layout/sectfrm.cxx b/sw/source/core/layout/sectfrm.cxx
new file mode 100644
index 000000000000..d7f5364c38f7
--- /dev/null
+++ b/sw/source/core/layout/sectfrm.cxx
@@ -0,0 +1,2779 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+#include <svl/smplhint.hxx>
+#include <svl/itemiter.hxx>
+#include <hints.hxx>
+#include <txtftn.hxx>
+#include <fmtftn.hxx>
+#include <fmtclbl.hxx>
+#include "sectfrm.hxx"
+#include "section.hxx" // SwSection
+#include "frmtool.hxx" // StackHack
+#include "doc.hxx" // SwDoc
+#include "cntfrm.hxx" // SwCntntFrm
+#include "rootfrm.hxx" // SwRootFrm
+#include "pagefrm.hxx" // SwPageFrm
+#include "fmtpdsc.hxx" // SwFmtPageDesc
+#include "fmtcntnt.hxx" // SwFmtCntnt
+#include "ndindex.hxx" // SwNodeIndex
+#include "ftnidx.hxx"
+#include "txtfrm.hxx" // SwTxtFrm
+#include "fmtclds.hxx" // SwFmtCol
+#include "colfrm.hxx" // SwColumnFrm
+#include "tabfrm.hxx" // SwTabFrm
+#include "flyfrm.hxx" // SwFlyFrm
+#include "ftnfrm.hxx" // SwFtnFrm
+#include "layouter.hxx" // SwLayouter
+#include "dbg_lay.hxx"
+#include "viewsh.hxx"
+#include "viewopt.hxx"
+#include "viewimp.hxx"
+#include <editeng/ulspitem.hxx>
+#include <editeng/lrspitem.hxx>
+#include <editeng/brshitem.hxx>
+#include <fmtftntx.hxx>
+// OD 2004-05-24 #i28701#
+#include <dflyobj.hxx>
+#include <flyfrms.hxx>
+#include <sortedobjs.hxx>
+
+SV_IMPL_PTRARR_SORT( SwDestroyList, SwSectionFrmPtr )
+
+/*************************************************************************
+|*
+|* SwSectionFrm::SwSectionFrm(), ~SwSectionFrm()
+|*
+|*************************************************************************/
+SwSectionFrm::SwSectionFrm( SwSection &rSect, SwFrm* pSib ) :
+ SwLayoutFrm( rSect.GetFmt(), pSib ),
+ SwFlowFrm( (SwFrm&)*this ),
+ pSection( &rSect )
+{
+ nType = FRMC_SECTION;
+
+ CalcFtnAtEndFlag();
+ CalcEndAtEndFlag();
+}
+
+SwSectionFrm::SwSectionFrm( SwSectionFrm &rSect, sal_Bool bMaster ) :
+ SwLayoutFrm( rSect.GetFmt(), rSect.getRootFrm() ),
+ SwFlowFrm( (SwFrm&)*this ),
+ pSection( rSect.GetSection() )
+{
+ bFtnAtEnd = rSect.IsFtnAtEnd();
+ bEndnAtEnd = rSect.IsEndnAtEnd();
+ bLockJoin = sal_False;
+ nType = FRMC_SECTION;
+
+ PROTOCOL( this, PROT_SECTION, bMaster ? ACT_CREATE_MASTER : ACT_CREATE_FOLLOW, &rSect )
+
+ if( bMaster )
+ {
+ if( rSect.IsFollow() )
+ {
+ SwSectionFrm* pMaster = rSect.FindMaster();
+ pMaster->SetFollow( this );
+ bIsFollow = sal_True;
+ }
+ else
+ rSect.bIsFollow = sal_True;
+ SetFollow( &rSect );
+ }
+ else
+ {
+ bIsFollow = sal_True;
+ SetFollow( rSect.GetFollow() );
+ rSect.SetFollow( this );
+ if( !GetFollow() )
+ rSect.SimpleFormat();
+ if( !rSect.IsColLocked() )
+ rSect.InvalidateSize();
+ }
+}
+
+// NOTE: call <SwSectionFrm::Init()> directly after creation of a new section
+// frame and its insert in the layout.
+void SwSectionFrm::Init()
+{
+ OSL_ENSURE( GetUpper(), "SwSectionFrm::Init before insertion?!" );
+ SWRECTFN( this )
+ long nWidth = (GetUpper()->Prt().*fnRect->fnGetWidth)();
+ (Frm().*fnRect->fnSetWidth)( nWidth );
+ (Frm().*fnRect->fnSetHeight)( 0 );
+
+ // #109700# LRSpace for sections
+ const SvxLRSpaceItem& rLRSpace = GetFmt()->GetLRSpace();
+ (Prt().*fnRect->fnSetLeft)( rLRSpace.GetLeft() );
+ (Prt().*fnRect->fnSetWidth)( nWidth - rLRSpace.GetLeft() -
+ rLRSpace.GetRight() );
+ (Prt().*fnRect->fnSetHeight)( 0 );
+
+ const SwFmtCol &rCol = GetFmt()->GetCol();
+ if( ( rCol.GetNumCols() > 1 || IsAnyNoteAtEnd() ) && !IsInFtn() )
+ {
+ const SwFmtCol *pOld = Lower() ? &rCol : new SwFmtCol;
+ ChgColumns( *pOld, rCol, IsAnyNoteAtEnd() );
+ if( pOld != &rCol )
+ delete pOld;
+ }
+}
+
+SwSectionFrm::~SwSectionFrm()
+{
+ if( GetFmt() && !GetFmt()->GetDoc()->IsInDtor() )
+ {
+ SwRootFrm *pRootFrm = getRootFrm();
+ if( pRootFrm )
+ pRootFrm->RemoveFromList( this ); //swmod 071108//swmod 071225
+ if( IsFollow() )
+ {
+ SwSectionFrm *pMaster = FindMaster();
+ if( pMaster )
+ {
+ PROTOCOL( this, PROT_SECTION, ACT_DEL_FOLLOW, pMaster )
+ pMaster->SetFollow( GetFollow() );
+ // Ein Master greift sich immer den Platz bis zur Unterkante seines
+ // Uppers. Wenn er keinen Follow mehr hat, kann er diesen ggf. wieder
+ // freigeben, deshalb wird die Size des Masters invalidiert.
+ if( !GetFollow() )
+ pMaster->InvalidateSize();
+ }
+ }
+ else if( HasFollow() )
+ {
+ PROTOCOL( this, PROT_SECTION, ACT_DEL_MASTER, GetFollow() )
+ GetFollow()->bIsFollow = sal_False;
+ }
+ }
+}
+
+
+/*************************************************************************
+|*
+|* SwSectionFrm::DelEmpty()
+|*
+|*************************************************************************/
+void SwSectionFrm::DelEmpty( sal_Bool bRemove )
+{
+ if( IsColLocked() )
+ {
+ OSL_ENSURE( !bRemove, "Don't delete locked SectionFrms" );
+ return;
+ }
+ SwFrm* pUp = GetUpper();
+ if( pUp )
+ {
+ // --> OD 2005-12-01 #i27138#
+ // notify accessibility paragraphs objects about changed
+ // CONTENT_FLOWS_FROM/_TO relation.
+ // Relation CONTENT_FLOWS_FROM for current next paragraph will change
+ // and relation CONTENT_FLOWS_TO for current previous paragraph will change.
+ {
+ ViewShell* pViewShell( getRootFrm()->GetCurrShell() );
+ if ( pViewShell && pViewShell->GetLayout() &&
+ pViewShell->GetLayout()->IsAnyShellAccessible() )
+ {
+ pViewShell->InvalidateAccessibleParaFlowRelation(
+ dynamic_cast<SwTxtFrm*>(FindNextCnt( true )),
+ dynamic_cast<SwTxtFrm*>(FindPrevCnt( true )) );
+ }
+ }
+ // <--
+ _Cut( bRemove );
+ }
+ if( IsFollow() )
+ {
+ SwSectionFrm *pMaster = FindMaster();
+ pMaster->SetFollow( GetFollow() );
+ // Ein Master greift sich immer den Platz bis zur Unterkante seines
+ // Uppers. Wenn er keinen Follow mehr hat, kann er diesen ggf. wieder
+ // freigeben, deshalb wird die Size des Masters invalidiert.
+ if( !GetFollow() && !pMaster->IsColLocked() )
+ pMaster->InvalidateSize();
+ bIsFollow = sal_False;
+ }
+ else if( HasFollow() )
+ GetFollow()->bIsFollow = sal_False;
+ pFollow = NULL;
+ if( pUp )
+ {
+ Frm().Height( 0 );
+ // Wenn wir sowieso sofort zerstoert werden, brauchen/duerfen wir
+ // uns gar nicht erst in die Liste eintragen
+ if( bRemove )
+ { // Wenn wir bereits halbtot waren vor diesem DelEmpty, so
+ // stehen wir vermutlich auch in der Liste und muessen uns
+ // dort austragen
+ if( !pSection && getRootFrm() )
+ getRootFrm()->RemoveFromList( this );
+ }
+ else if( getRootFrm() )
+ getRootFrm()->InsertEmptySct( this ); //swmod 071108//swmod 071225
+ pSection = NULL; // damit ist allerdings eine Reanimierung quasi ausgeschlossen
+ }
+}
+
+/*************************************************************************
+|*
+|* SwSectionFrm::Cut()
+|*
+|*************************************************************************/
+void SwSectionFrm::Cut()
+{
+ _Cut( sal_True );
+}
+
+void SwSectionFrm::_Cut( sal_Bool bRemove )
+{
+ OSL_ENSURE( GetUpper(), "Cut ohne Upper()." );
+
+ PROTOCOL( this, PROT_CUT, 0, GetUpper() )
+
+ SwPageFrm *pPage = FindPageFrm();
+ InvalidatePage( pPage );
+ SwFrm *pFrm = GetNext();
+ SwFrm* pPrepFrm = NULL;
+ while( pFrm && pFrm->IsSctFrm() && !((SwSectionFrm*)pFrm)->GetSection() )
+ pFrm = pFrm->GetNext();
+ if( pFrm )
+ { //Der alte Nachfolger hat evtl. einen Abstand zum Vorgaenger
+ //berechnet der ist jetzt wo er der erste wird obsolete
+ pFrm->_InvalidatePrt();
+ pFrm->_InvalidatePos();
+ if( pFrm->IsSctFrm() )
+ pFrm = ((SwSectionFrm*)pFrm)->ContainsAny();
+ if ( pFrm && pFrm->IsCntntFrm() )
+ {
+ pFrm->InvalidatePage( pPage );
+ if( IsInFtn() && !GetIndPrev() )
+ pPrepFrm = pFrm;
+ }
+ }
+ else
+ {
+ InvalidateNextPos();
+ //Einer muss die Retusche uebernehmen: Vorgaenger oder Upper
+ if ( 0 != (pFrm = GetPrev()) )
+ { pFrm->SetRetouche();
+ pFrm->Prepare( PREP_WIDOWS_ORPHANS );
+ if ( pFrm->IsCntntFrm() )
+ pFrm->InvalidatePage( pPage );
+ }
+ //Wenn ich der einzige FlowFrm in meinem Upper bin (war), so muss
+ //er die Retouche uebernehmen.
+ //Ausserdem kann eine Leerseite entstanden sein.
+ else
+ { SwRootFrm *pRoot = (SwRootFrm*)pPage->GetUpper();
+ pRoot->SetSuperfluous();
+ GetUpper()->SetCompletePaint();
+ }
+ }
+ //Erst removen, dann Upper Shrinken.
+ SwLayoutFrm *pUp = GetUpper();
+ if( bRemove )
+ {
+ Remove();
+ if( pUp && !pUp->Lower() && pUp->IsFtnFrm() && !pUp->IsColLocked() &&
+ pUp->GetUpper() )
+ {
+ pUp->Cut();
+ delete pUp;
+ pUp = NULL;
+ }
+ }
+ if( pPrepFrm )
+ pPrepFrm->Prepare( PREP_FTN );
+ if ( pUp )
+ {
+ SWRECTFN( this );
+ SwTwips nFrmHeight = (Frm().*fnRect->fnGetHeight)();
+ if( nFrmHeight > 0 )
+ {
+ if( !bRemove )
+ {
+ (Frm().*fnRect->fnSetHeight)( 0 );
+ (Prt().*fnRect->fnSetHeight)( 0 );
+ }
+ pUp->Shrink( nFrmHeight );
+ }
+ }
+}
+
+/*************************************************************************
+|*
+|* SwSectionFrm::Paste()
+|*
+|*************************************************************************/
+
+void SwSectionFrm::Paste( SwFrm* pParent, SwFrm* pSibling )
+{
+ OSL_ENSURE( pParent, "Kein Parent fuer Paste." );
+ OSL_ENSURE( pParent->IsLayoutFrm(), "Parent ist CntntFrm." );
+ OSL_ENSURE( pParent != this, "Bin selbst der Parent." );
+ OSL_ENSURE( pSibling != this, "Bin mein eigener Nachbar." );
+ OSL_ENSURE( !GetPrev() && !GetUpper(),
+ "Bin noch irgendwo angemeldet." );
+
+ PROTOCOL( this, PROT_PASTE, 0, GetUpper() )
+
+ //In den Baum einhaengen.
+ SwSectionFrm* pSect = pParent->FindSctFrm();
+ // --> OD 2008-06-23 #156927#
+ // Assure that parent is not inside a table frame, which is inside the found section frame.
+ if ( pSect )
+ {
+ SwTabFrm* pTableFrm = pParent->FindTabFrm();
+ if ( pTableFrm &&
+ pSect->IsAnLower( pTableFrm ) )
+ {
+ pSect = 0;
+ }
+ }
+ // <--
+
+ SWRECTFN( pParent )
+ if( pSect && HasToBreak( pSect ) )
+ {
+ if( pParent->IsColBodyFrm() ) // handelt es sich um einen spaltigen Bereich
+ {
+ // Falls wir zufaellig am Ende einer Spalte stehen, muss pSibling
+ // auf den ersten Frame der naechsten Spalte zeigen, damit
+ // der Inhalt der naechsten Spalte von InsertGroup richtig in den
+ // neu angelegten pSect umgehaengt wird.
+ SwColumnFrm *pCol = (SwColumnFrm*)pParent->GetUpper();
+ while( !pSibling && 0 != ( pCol = (SwColumnFrm*)pCol->GetNext() ) )
+ pSibling = ((SwLayoutFrm*)((SwColumnFrm*)pCol)->Lower())->Lower();
+ if( pSibling )
+ {
+ // Schlimmer noch: alle folgenden Spalteninhalte muessen
+ // an die pSibling-Kette angehaengt werden, damit sie
+ // mitgenommen werden.
+ SwFrm *pTmp = pSibling;
+ while ( 0 != ( pCol = (SwColumnFrm*)pCol->GetNext() ) )
+ {
+ while ( pTmp->GetNext() )
+ pTmp = pTmp->GetNext();
+ SwFrm* pSave = ::SaveCntnt( pCol );
+ ::RestoreCntnt( pSave, pSibling->GetUpper(), pTmp, true );
+ }
+ }
+ }
+ pParent = pSect;
+ pSect = new SwSectionFrm( *((SwSectionFrm*)pParent)->GetSection(), pParent );
+ // Wenn pParent in zwei Teile zerlegt wird, so muss sein Follow am
+ // neuen, zweiten Teil angebracht werden.
+ pSect->SetFollow( ((SwSectionFrm*)pParent)->GetFollow() );
+ ((SwSectionFrm*)pParent)->SetFollow( NULL );
+ if( pSect->GetFollow() )
+ pParent->_InvalidateSize();
+
+ InsertGroupBefore( pParent, pSibling, pSect );
+ pSect->Init();
+ (pSect->*fnRect->fnMakePos)( pSect->GetUpper(), pSect->GetPrev(), sal_True);
+ if( !((SwLayoutFrm*)pParent)->Lower() )
+ {
+ SwSectionFrm::MoveCntntAndDelete( (SwSectionFrm*)pParent, sal_False );
+ pParent = this;
+ }
+ }
+ else
+ InsertGroupBefore( pParent, pSibling, NULL );
+
+ _InvalidateAll();
+ SwPageFrm *pPage = FindPageFrm();
+ InvalidatePage( pPage );
+
+ if ( pSibling )
+ {
+ pSibling->_InvalidatePos();
+ pSibling->_InvalidatePrt();
+ if ( pSibling->IsCntntFrm() )
+ pSibling->InvalidatePage( pPage );
+ }
+
+ SwTwips nFrmHeight = (Frm().*fnRect->fnGetHeight)();
+ if( nFrmHeight )
+ pParent->Grow( nFrmHeight );
+
+ if ( GetPrev() )
+ {
+ if ( !IsFollow() )
+ {
+ GetPrev()->InvalidateSize();
+ if ( GetPrev()->IsCntntFrm() )
+ GetPrev()->InvalidatePage( pPage );
+ }
+ }
+}
+
+
+/*************************************************************************
+|*
+|* SwSectionFrm::HasToBreak()
+|*
+|* Hier wird entschieden, ob der this-SectionFrm den uebergebenen
+|* (Section)Frm aufbrechen soll oder nicht.
+|* Zunaechst werden uebergeordnete Bereiche immer aufgebrochen,
+|* spaeter koennte man es einstellbar machen.
+|*
+|*************************************************************************/
+
+sal_Bool SwSectionFrm::HasToBreak( const SwFrm* pFrm ) const
+{
+ if( !pFrm->IsSctFrm() )
+ return sal_False;
+
+ SwSectionFmt *pTmp = (SwSectionFmt*)GetFmt();
+// if( !pTmp->GetSect().GetValue() )
+// return sal_False;
+
+ const SwFrmFmt *pOtherFmt = ((SwSectionFrm*)pFrm)->GetFmt();
+ do
+ {
+ pTmp = pTmp->GetParent();
+ if( !pTmp )
+ return sal_False;
+ if( pTmp == pOtherFmt )
+ return sal_True;
+ } while( sal_True ); // ( pTmp->GetSect().GetValue() );
+}
+
+/*************************************************************************
+|*
+|* SwSectionFrm::MergeNext()
+|*
+|* Verschmilzt zwei SectionFrms, falls es sich um den
+|* gleichen Bereich handelt.
+|* Notwendig kann dies sein, wenn ein (Unter-)Bereich geloescht wird, der
+|* einen anderen in zwei Teile zerlegt hatte.
+|*
+|*************************************************************************/
+
+void SwSectionFrm::MergeNext( SwSectionFrm* pNxt )
+{
+ if( !pNxt->IsJoinLocked() && GetSection() == pNxt->GetSection() )
+ {
+ PROTOCOL( this, PROT_SECTION, ACT_MERGE, pNxt )
+
+ SwFrm* pTmp = ::SaveCntnt( pNxt );
+ if( pTmp )
+ {
+ SwFrm* pLast = Lower();
+ SwLayoutFrm* pLay = this;
+ if( pLast )
+ {
+ while( pLast->GetNext() )
+ pLast = pLast->GetNext();
+ if( pLast->IsColumnFrm() )
+ { // Spalten jetzt mit BodyFrm
+ pLay = (SwLayoutFrm*)((SwLayoutFrm*)pLast)->Lower();
+ pLast = pLay->Lower();
+ if( pLast )
+ while( pLast->GetNext() )
+ pLast = pLast->GetNext();
+ }
+ }
+ ::RestoreCntnt( pTmp, pLay, pLast, true );
+ }
+ SetFollow( pNxt->GetFollow() );
+ pNxt->SetFollow( NULL );
+ pNxt->bIsFollow = sal_False;
+ pNxt->Cut();
+ delete pNxt;
+ InvalidateSize();
+ }
+}
+
+/*************************************************************************
+|*
+|* SwSectionFrm::SplitSect()
+|*
+|* Zerteilt einen SectionFrm in zwei Teile, der zweite Teil beginnt mit dem
+|* uebergebenen Frame.
+|* Benoetigt wird dies beim Einfuegen eines inneren Bereichs, weil innerhalb
+|* von Rahmen oder Tabellenzellen das MoveFwd nicht den erwuenschten Effekt
+|* haben kann.
+|*
+|*************************************************************************/
+
+sal_Bool SwSectionFrm::SplitSect( SwFrm* pFrm, sal_Bool bApres )
+{
+ OSL_ENSURE( pFrm, "SplitSect: Why?" );
+ SwFrm* pOther = bApres ? pFrm->FindNext() : pFrm->FindPrev();
+ if( !pOther )
+ return sal_False;
+ SwSectionFrm* pSect = pOther->FindSctFrm();
+ if( pSect != this )
+ return sal_False;
+ // Den Inhalt zur Seite stellen
+ SwFrm* pSav = ::SaveCntnt( this, bApres ? pOther : pFrm );
+ OSL_ENSURE( pSav, "SplitSect: What's on?" );
+ if( pSav ) // Robust
+ { // Einen neuen SctFrm anlegen, nicht als Follow/Master
+ SwSectionFrm* pNew = new SwSectionFrm( *pSect->GetSection(), pSect );
+ pNew->InsertBehind( pSect->GetUpper(), pSect );
+ pNew->Init();
+ SWRECTFN( this )
+ (pNew->*fnRect->fnMakePos)( NULL, pSect, sal_True );
+ // OD 25.03.2003 #108339# - restore content:
+ // determine layout frame for restoring content after the initialization
+ // of the section frame. In the section initialization the columns are
+ // created.
+ {
+ SwLayoutFrm* pLay = pNew;
+ // Search for last layout frame, e.g. for columned sections.
+ while( pLay->Lower() && pLay->Lower()->IsLayoutFrm() )
+ pLay = (SwLayoutFrm*)pLay->Lower();
+ ::RestoreCntnt( pSav, pLay, NULL, true );
+ }
+ _InvalidateSize();
+ if( HasFollow() )
+ {
+ pNew->SetFollow( GetFollow() );
+ SetFollow( NULL );
+ }
+ return sal_True;
+ }
+ return sal_False;
+}
+
+/*************************************************************************
+|*
+|* SwSectionFrm::MoveCntntAndDelete()
+|*
+|* MoveCntnt wird zur Zerstoerung eines SectionFrms wg. Aufhebung oder
+|* Verstecken des Bereichs gerufen, um den Inhalt umzuhaengen.
+|* Wenn der SectionFrm keinen anderen aufbrach, so wird der Inhalt in
+|* den Upper bewegt. Anderfalls wird der Inhalt in den anderen SectionFrm
+|* umgehaengt, dieser muss ggf. gemergt werden.
+|*
+|*************************************************************************/
+// Wenn ein mehrspaltiger Bereich aufgehoben wird, muessen die ContentFrms
+// invalidiert werden
+
+void lcl_InvalidateInfFlags( SwFrm* pFrm, sal_Bool bInva )
+{
+ while ( pFrm )
+ {
+ pFrm->InvalidateInfFlags();
+ if( bInva )
+ {
+ pFrm->_InvalidatePos();
+ pFrm->_InvalidateSize();
+ pFrm->_InvalidatePrt();
+ }
+ if( pFrm->IsLayoutFrm() )
+ lcl_InvalidateInfFlags( ((SwLayoutFrm*)pFrm)->GetLower(), sal_False );
+ pFrm = pFrm->GetNext();
+ }
+}
+
+
+//
+// Works like SwCntntFrm::ImplGetNextCntntFrm, but starts with a LayoutFrm
+//
+SwCntntFrm* lcl_GetNextCntntFrm( const SwLayoutFrm* pLay, bool bFwd )
+{
+ if ( bFwd )
+ {
+ if ( pLay->GetNext() && pLay->GetNext()->IsCntntFrm() )
+ return (SwCntntFrm*)pLay->GetNext();
+ }
+ else
+ {
+ if ( pLay->GetPrev() && pLay->GetPrev()->IsCntntFrm() )
+ return (SwCntntFrm*)pLay->GetPrev();
+ }
+
+ // #100926#
+ const SwFrm* pFrm = pLay;
+ SwCntntFrm *pCntntFrm = 0;
+ sal_Bool bGoingUp = sal_True;
+ do {
+ const SwFrm *p = 0;
+ sal_Bool bGoingFwdOrBwd = sal_False, bGoingDown = sal_False;
+
+ bGoingDown = !bGoingUp && ( 0 != ( p = pFrm->IsLayoutFrm() ? ((SwLayoutFrm*)pFrm)->Lower() : 0 ) );
+ if ( !bGoingDown )
+ {
+ bGoingFwdOrBwd = ( 0 != ( p = pFrm->IsFlyFrm() ?
+ ( bFwd ? ((SwFlyFrm*)pFrm)->GetNextLink() : ((SwFlyFrm*)pFrm)->GetPrevLink() ) :
+ ( bFwd ? pFrm->GetNext() :pFrm->GetPrev() ) ) );
+ if ( !bGoingFwdOrBwd )
+ {
+ bGoingUp = (0 != (p = pFrm->GetUpper() ) );
+ if ( !bGoingUp )
+ return 0;
+ }
+ }
+
+ bGoingUp = !( bGoingFwdOrBwd || bGoingDown );
+
+ if( !bFwd && bGoingDown && p )
+ while ( p->GetNext() )
+ p = p->GetNext();
+
+ pFrm = p;
+ } while ( 0 == (pCntntFrm = (pFrm->IsCntntFrm() ? (SwCntntFrm*)pFrm:0) ));
+
+ return pCntntFrm;
+}
+
+#define FIRSTLEAF( pLayFrm ) ( ( pLayFrm->Lower() && pLayFrm->Lower()->IsColumnFrm() )\
+ ? pLayFrm->GetNextLayoutLeaf() \
+ : pLayFrm )
+
+void SwSectionFrm::MoveCntntAndDelete( SwSectionFrm* pDel, sal_Bool bSave )
+{
+ sal_Bool bSize = pDel->Lower() && pDel->Lower()->IsColumnFrm();
+ SwFrm* pPrv = pDel->GetPrev();
+ SwLayoutFrm* pUp = pDel->GetUpper();
+ // OD 27.03.2003 #i12711# - initialize local pointer variables.
+ SwSectionFrm* pPrvSct = NULL;
+ SwSectionFrm* pNxtSct = NULL;
+ SwSectionFmt* pParent = static_cast<SwSectionFmt*>(pDel->GetFmt())->GetParent();
+ if( pDel->IsInTab() && pParent )
+ {
+ SwTabFrm *pTab = pDel->FindTabFrm();
+ // Wenn wir innerhalb einer Tabelle liegen, koennen wir nur Bereiche
+ // aufgebrochen haben, die ebenfalls innerhalb liegen, nicht etwa
+ // einen Bereich, der die gesamte Tabelle umfasst.
+ if( pTab->IsInSct() && pParent == pTab->FindSctFrm()->GetFmt() )
+ pParent = NULL;
+ }
+ // Wenn unser Format einen Parent besitzt, so haben wir vermutlich
+ // einen anderen SectionFrm aufgebrochen, dies muss geprueft werden,
+ // dazu besorgen wir uns zunaechst den vorhergehende und den nach-
+ // folgenden CntntFrm, mal sehen, ob diese in SectionFrms liegen.
+ // OD 27.03.2003 #i12711# - check, if previous and next section belonging
+ // together and can be joined, *not* only if deleted section contains content.
+ if ( pParent )
+ {
+ SwFrm* pPrvCntnt = lcl_GetNextCntntFrm( pDel, false );
+ pPrvSct = pPrvCntnt ? pPrvCntnt->FindSctFrm() : NULL;
+ SwFrm* pNxtCntnt = lcl_GetNextCntntFrm( pDel, true );
+ pNxtSct = pNxtCntnt ? pNxtCntnt->FindSctFrm() : NULL;
+ }
+ else
+ {
+ pParent = NULL;
+ pPrvSct = pNxtSct = NULL;
+ }
+
+ // Jetzt wird der Inhalt beseite gestellt und der Frame zerstoert
+ SwFrm *pSave = bSave ? ::SaveCntnt( pDel ) : NULL;
+ sal_Bool bOldFtn = sal_True;
+ if( pSave && pUp->IsFtnFrm() )
+ {
+ bOldFtn = ((SwFtnFrm*)pUp)->IsColLocked();
+ ((SwFtnFrm*)pUp)->ColLock();
+ }
+ pDel->DelEmpty( sal_True );
+ delete pDel;
+ if( pParent )
+ { // Hier wird die geeignete Einfuegeposition gesucht
+ if( pNxtSct && pNxtSct->GetFmt() == pParent )
+ { // Hier koennen wir uns am Anfang einfuegen
+ pUp = FIRSTLEAF( pNxtSct );
+ pPrv = NULL;
+ if( pPrvSct && !( pPrvSct->GetFmt() == pParent ) )
+ pPrvSct = NULL; // damit nicht gemergt wird
+ }
+ else if( pPrvSct && pPrvSct->GetFmt() == pParent )
+ { // Wunderbar, hier koennen wir uns am Ende einfuegen
+ pUp = pPrvSct;
+ if( pUp->Lower() && pUp->Lower()->IsColumnFrm() )
+ {
+ pUp = static_cast<SwLayoutFrm*>(pUp->GetLastLower());
+ // Der Body der letzten Spalte
+ pUp = static_cast<SwLayoutFrm*>(pUp->Lower());
+ }
+ // damit hinter dem letzten eingefuegt wird
+ pPrv = pUp->GetLastLower();
+ pPrvSct = NULL; // damit nicht gemergt wird
+ }
+ else
+ {
+ if( pSave )
+ { // Folgende Situationen: Vor und hinter dem zu loeschenden Bereich
+ // ist entweder die Bereichsgrenze des umfassenden Bereichs oder
+ // es schliesst ein anderer (Geschwister-)Bereich direkt an, der
+ // vom gleichen Parent abgeleitet ist.
+ // Dann gibt es (noch) keinen Teil unseres Parents, der den Inhalt
+ // aufnehmen kann,also bauen wir ihn uns.
+ pPrvSct = new SwSectionFrm( *pParent->GetSection(), pUp );
+ pPrvSct->InsertBehind( pUp, pPrv );
+ pPrvSct->Init();
+ SWRECTFN( pUp )
+ (pPrvSct->*fnRect->fnMakePos)( pUp, pPrv, sal_True );
+ pUp = FIRSTLEAF( pPrvSct );
+ pPrv = NULL;
+ }
+ pPrvSct = NULL; // damit nicht gemergt wird
+ }
+ }
+ // Der Inhalt wird eingefuegt..
+ if( pSave )
+ {
+ lcl_InvalidateInfFlags( pSave, bSize );
+ ::RestoreCntnt( pSave, pUp, pPrv, true );
+ pUp->FindPageFrm()->InvalidateCntnt();
+ if( !bOldFtn )
+ ((SwFtnFrm*)pUp)->ColUnlock();
+ }
+ // jetzt koennen eventuell zwei Teile des uebergeordneten Bereich verschmelzen
+ if( pPrvSct && !pPrvSct->IsJoinLocked() )
+ {
+ OSL_ENSURE( pNxtSct, "MoveCntnt: No Merge" );
+ pPrvSct->MergeNext( pNxtSct );
+ }
+}
+
+void SwSectionFrm::MakeAll()
+{
+ if ( IsJoinLocked() || IsColLocked() || StackHack::IsLocked() || StackHack::Count() > 50 )
+ return;
+ if( !pSection ) // Durch DelEmpty
+ {
+#if OSL_DEBUG_LEVEL > 1
+ OSL_ENSURE( getRootFrm()->IsInDelList( this ), "SectionFrm without Section" );
+#endif
+ if( !bValidPos )
+ {
+ if( GetUpper() )
+ {
+ SWRECTFN( GetUpper() )
+ (this->*fnRect->fnMakePos)( GetUpper(), GetPrev(), sal_False );
+ }
+ }
+ bValidSize = bValidPos = bValidPrtArea = sal_True;
+ return;
+ }
+ LockJoin(); //Ich lass mich nicht unterwegs vernichten.
+
+ while( GetNext() && GetNext() == GetFollow() )
+ {
+ const SwFrm* pFoll = GetFollow();
+ MergeNext( (SwSectionFrm*)GetNext() );
+ if( pFoll == GetFollow() )
+ break;
+ }
+
+ // OD 2004-03-15 #116561# - In online layout join the follows, if section
+ // can grow.
+ const ViewShell *pSh = getRootFrm()->GetCurrShell();
+ if( pSh && pSh->GetViewOptions()->getBrowseMode() &&
+ ( Grow( LONG_MAX, true ) > 0 ) )
+ {
+ while( GetFollow() )
+ {
+ const SwFrm* pFoll = GetFollow();
+ MergeNext( GetFollow() );
+ if( pFoll == GetFollow() )
+ break;
+ }
+ }
+
+ // Ein Bereich mit Follow nimmt allen Platz bis zur Unterkante des Uppers
+ // in Anspruch. Bewegt er sich, so kann seine Groesse zu- oder abnehmen...
+ if( !bValidPos && ToMaximize( sal_False ) )
+ bValidSize = sal_False;
+
+#if OSL_DEBUG_LEVEL > 1
+ const SwFmtCol &rCol = GetFmt()->GetCol();
+ (void)rCol;
+#endif
+ SwLayoutFrm::MakeAll();
+ UnlockJoin();
+ if( pSection && IsSuperfluous() )
+ DelEmpty( sal_False );
+}
+
+sal_Bool SwSectionFrm::ShouldBwdMoved( SwLayoutFrm *, sal_Bool , sal_Bool & )
+{
+ OSL_FAIL( "Hups, wo ist meine Tarnkappe?" );
+ return sal_False;
+}
+
+const SwSectionFmt* SwSectionFrm::_GetEndSectFmt() const
+{
+ const SwSectionFmt *pFmt = pSection->GetFmt();
+ while( !pFmt->GetEndAtTxtEnd().IsAtEnd() )
+ {
+ if( pFmt->GetRegisteredIn()->ISA( SwSectionFmt ) )
+ pFmt = (SwSectionFmt*)pFmt->GetRegisteredIn();
+ else
+ return NULL;
+ }
+ return pFmt;
+}
+
+void lcl_FindCntntFrm( SwCntntFrm* &rpCntntFrm, SwFtnFrm* &rpFtnFrm,
+ SwFrm* pFrm, sal_Bool &rbChkFtn )
+{
+ if( pFrm )
+ {
+ while( pFrm->GetNext() )
+ pFrm = pFrm->GetNext();
+ while( !rpCntntFrm && pFrm )
+ {
+ if( pFrm->IsCntntFrm() )
+ rpCntntFrm = (SwCntntFrm*)pFrm;
+ else if( pFrm->IsLayoutFrm() )
+ {
+ if( pFrm->IsFtnFrm() )
+ {
+ if( rbChkFtn )
+ {
+ rpFtnFrm = (SwFtnFrm*)pFrm;
+ rbChkFtn = rpFtnFrm->GetAttr()->GetFtn().IsEndNote();
+ }
+ }
+ else
+ lcl_FindCntntFrm( rpCntntFrm, rpFtnFrm,
+ ((SwLayoutFrm*)pFrm)->Lower(), rbChkFtn );
+ }
+ pFrm = pFrm->GetPrev();
+ }
+ }
+}
+
+SwCntntFrm *SwSectionFrm::FindLastCntnt( sal_uInt8 nMode )
+{
+ SwCntntFrm *pRet = NULL;
+ SwFtnFrm *pFtnFrm = NULL;
+ SwSectionFrm *pSect = this;
+ if( nMode )
+ {
+ const SwSectionFmt *pFmt = IsEndnAtEnd() ? GetEndSectFmt() :
+ pSection->GetFmt();
+ do {
+ while( pSect->HasFollow() )
+ pSect = pSect->GetFollow();
+ SwFrm* pTmp = pSect->FindNext();
+ while( pTmp && pTmp->IsSctFrm() &&
+ !((SwSectionFrm*)pTmp)->GetSection() )
+ pTmp = pTmp->FindNext();
+ if( pTmp && pTmp->IsSctFrm() &&
+ ((SwSectionFrm*)pTmp)->IsDescendantFrom( pFmt ) )
+ pSect = (SwSectionFrm*)pTmp;
+ else
+ break;
+ } while( sal_True );
+ }
+ sal_Bool bFtnFound = nMode == FINDMODE_ENDNOTE;
+ do
+ {
+ lcl_FindCntntFrm( pRet, pFtnFrm, pSect->Lower(), bFtnFound );
+ if( pRet || !pSect->IsFollow() || !nMode ||
+ ( FINDMODE_MYLAST == nMode && this == pSect ) )
+ break;
+ pSect = pSect->FindMaster();
+ } while( pSect );
+ if( ( nMode == FINDMODE_ENDNOTE ) && pFtnFrm )
+ pRet = pFtnFrm->ContainsCntnt();
+ return pRet;
+}
+
+sal_Bool SwSectionFrm::CalcMinDiff( SwTwips& rMinDiff ) const
+{
+ if( ToMaximize( sal_True ) )
+ {
+ SWRECTFN( this )
+ rMinDiff = (GetUpper()->*fnRect->fnGetPrtBottom)();
+ rMinDiff = (Frm().*fnRect->fnBottomDist)( rMinDiff );
+ return sal_True;
+ }
+ return sal_False;
+}
+
+/*************************************************************************
+ *
+ * SwSectionFrm::CollectEndnotes( )
+ *
+ * CollectEndnotes looks for endnotes in the sectionfrm and his follows,
+ * the endnotes will cut off the layout and put into the array.
+ * If the first endnote is not a master-SwFtnFrm, the whole sectionfrm
+ * contains only endnotes and it is not necessary to collect them.
+ *
+ *************************************************************************/
+
+SwFtnFrm* lcl_FindEndnote( SwSectionFrm* &rpSect, sal_Bool &rbEmpty,
+ SwLayouter *pLayouter )
+{
+ // if rEmpty is set, the rpSect is already searched
+ SwSectionFrm* pSect = rbEmpty ? rpSect->GetFollow() : rpSect;
+ while( pSect )
+ {
+ OSL_ENSURE( (pSect->Lower() && pSect->Lower()->IsColumnFrm()) || pSect->GetUpper()->IsFtnFrm(),
+ "InsertEndnotes: Where's my column?" );
+
+ // i73332: Columned section in endnote
+ SwColumnFrm* pCol = 0;
+ if(pSect->Lower() && pSect->Lower()->IsColumnFrm())
+ pCol = (SwColumnFrm*)pSect->Lower();
+
+ while( pCol ) // check all columns
+ {
+ SwFtnContFrm* pFtnCont = pCol->FindFtnCont();
+ if( pFtnCont )
+ {
+ SwFtnFrm* pRet = (SwFtnFrm*)pFtnCont->Lower();
+ while( pRet ) // look for endnotes
+ {
+ if( pRet->GetAttr()->GetFtn().IsEndNote() )
+ {
+ if( pRet->GetMaster() )
+ {
+ if( pLayouter )
+ pLayouter->CollectEndnote( pRet );
+ else
+ return 0;
+ }
+ else
+ return pRet; // Found
+ }
+ pRet = (SwFtnFrm*)pRet->GetNext();
+ }
+ }
+ pCol = (SwColumnFrm*)pCol->GetNext();
+ }
+ rpSect = pSect;
+ pSect = pLayouter ? pSect->GetFollow() : NULL;
+ rbEmpty = sal_True;
+ }
+ return NULL;
+}
+
+void lcl_ColumnRefresh( SwSectionFrm* pSect, sal_Bool bFollow )
+{
+ while( pSect )
+ {
+ sal_Bool bOldLock = pSect->IsColLocked();
+ pSect->ColLock();
+ if( pSect->Lower() && pSect->Lower()->IsColumnFrm() )
+ {
+ SwColumnFrm *pCol = (SwColumnFrm*)pSect->Lower();
+ do
+ { pCol->_InvalidateSize();
+ pCol->_InvalidatePos();
+ ((SwLayoutFrm*)pCol)->Lower()->_InvalidateSize();
+ pCol->Calc(); // calculation of column and
+ ((SwLayoutFrm*)pCol)->Lower()->Calc(); // body
+ pCol = (SwColumnFrm*)pCol->GetNext();
+ } while ( pCol );
+ }
+ if( !bOldLock )
+ pSect->ColUnlock();
+ if( bFollow )
+ pSect = pSect->GetFollow();
+ else
+ pSect = NULL;
+ }
+}
+
+void SwSectionFrm::CollectEndnotes( SwLayouter* pLayouter )
+{
+ OSL_ENSURE( IsColLocked(), "CollectEndnotes: You love the risk?" );
+ // i73332: Section in footnode does not have columns!
+ OSL_ENSURE( (Lower() && Lower()->IsColumnFrm()) || GetUpper()->IsFtnFrm(), "Where's my column?" );
+
+ SwSectionFrm* pSect = this;
+ SwFtnFrm* pFtn;
+ sal_Bool bEmpty = sal_False;
+ // pSect is the last sectionfrm without endnotes or the this-pointer
+ // the first sectionfrm with endnotes may be destroyed, when the endnotes
+ // is cutted
+ while( 0 != (pFtn = lcl_FindEndnote( pSect, bEmpty, pLayouter )) )
+ pLayouter->CollectEndnote( pFtn );
+ if( pLayouter->HasEndnotes() )
+ lcl_ColumnRefresh( this, sal_True );
+}
+
+/*************************************************************************
+|*
+|* SwSectionFrm::_CheckClipping( sal_Bool bGrow, sal_Bool bMaximize )
+|*
+|* Beschreibung: Passt die Groesse an die Umgebung an.
+|* Wer einen Follow oder Fussnoten besitzt, soll bis zur Unterkante
+|* des Uppers gehen (bMaximize).
+|* Niemand darf ueber den Upper hinausgehen, ggf. darf man versuchen (bGrow)
+|* seinen Upper zu growen.
+|* Wenn die Groesse veraendert werden musste, wird der Inhalt kalkuliert.
+|*
+|*************************************************************************/
+
+/// OD 18.09.2002 #100522#
+/// perform calculation of content, only if height has changed.
+void SwSectionFrm::_CheckClipping( sal_Bool bGrow, sal_Bool bMaximize )
+{
+ SWRECTFN( this )
+ long nDiff;
+ SwTwips nDeadLine = (GetUpper()->*fnRect->fnGetPrtBottom)();
+ if( bGrow && ( !IsInFly() || !GetUpper()->IsColBodyFrm() ||
+ !FindFlyFrm()->IsLocked() ) )
+ {
+ nDiff = -(Frm().*fnRect->fnBottomDist)( nDeadLine );
+ if( !bMaximize )
+ nDiff += Undersize();
+ if( nDiff > 0 )
+ {
+ long nAdd = GetUpper()->Grow( nDiff );
+ if( bVert && !bRev )
+ nDeadLine -= nAdd;
+ else
+ nDeadLine += nAdd;
+ }
+ }
+ nDiff = -(Frm().*fnRect->fnBottomDist)( nDeadLine );
+ SetUndersized( !bMaximize && nDiff >= 0 );
+ const bool bCalc = ( IsUndersized() || bMaximize ) &&
+ ( nDiff ||
+ (Prt().*fnRect->fnGetTop)() > (Frm().*fnRect->fnGetHeight)() );
+ // OD 03.11.2003 #i19737# - introduce local variable <bExtraCalc> to indicate
+ // that a calculation has to be done beside the value of <bCalc>.
+ bool bExtraCalc = false;
+ if( !bCalc && !bGrow && IsAnyNoteAtEnd() && !IsInFtn() )
+ {
+ SwSectionFrm *pSect = this;
+ sal_Bool bEmpty = sal_False;
+ SwLayoutFrm* pFtn = IsEndnAtEnd() ?
+ lcl_FindEndnote( pSect, bEmpty, NULL ) : NULL;
+ if( pFtn )
+ {
+ pFtn = pFtn->FindFtnBossFrm();
+ SwFrm* pTmp = FindLastCntnt( FINDMODE_LASTCNT );
+ // OD 08.11.2002 #104840# - use <SwLayoutFrm::IsBefore(..)>
+ if ( pTmp && pFtn->IsBefore( pTmp->FindFtnBossFrm() ) )
+ bExtraCalc = true;
+ }
+ else if( GetFollow() && !GetFollow()->ContainsAny() )
+ bExtraCalc = true;
+ }
+ if ( bCalc || bExtraCalc )
+ {
+ nDiff = (*fnRect->fnYDiff)( nDeadLine, (Frm().*fnRect->fnGetTop)() );
+ if( nDiff < 0 )
+ {
+ nDiff = 0;
+ nDeadLine = (Frm().*fnRect->fnGetTop)();
+ }
+ const Size aOldSz( Prt().SSize() );
+ long nTop = (this->*fnRect->fnGetTopMargin)();
+ (Frm().*fnRect->fnSetBottom)( nDeadLine );
+ nDiff = (Frm().*fnRect->fnGetHeight)();
+ if( nTop > nDiff )
+ nTop = nDiff;
+ (this->*fnRect->fnSetYMargins)( nTop, 0 );
+
+ // OD 18.09.2002 #100522#
+ // Determine, if height has changed.
+ // Note: In vertical layout the height equals the width value.
+ bool bHeightChanged = bVert ?
+ (aOldSz.Width() != Prt().Width()) :
+ (aOldSz.Height() != Prt().Height());
+ // Wir haben zu guter Letzt noch einmal die Hoehe geaendert,
+ // dann wird das innere Layout (Columns) kalkuliert und
+ // der Inhalt ebenfalls.
+ // OD 18.09.2002 #100522#
+ // calculate content, only if height has changed.
+ // OD 03.11.2003 #i19737# - restriction of content calculation too strong.
+ // If an endnote has an incorrect position or a follow section contains
+ // no content except footnotes/endnotes, the content has also been calculated.
+ if ( ( bHeightChanged || bExtraCalc ) && Lower() )
+ {
+ if( Lower()->IsColumnFrm() )
+ {
+ lcl_ColumnRefresh( this, sal_False );
+ ::CalcCntnt( this );
+ }
+ else
+ {
+ ChgLowersProp( aOldSz );
+ if( !bMaximize && !IsCntntLocked() )
+ ::CalcCntnt( this );
+ }
+ }
+ }
+}
+
+void SwSectionFrm::SimpleFormat()
+{
+ if ( IsJoinLocked() || IsColLocked() )
+ return;
+ // OSL_ENSURE( pFollow, "SimpleFormat: Follow required" );
+ LockJoin();
+ SWRECTFN( this )
+ if( GetPrev() || GetUpper() )
+ {
+ // --> OD 2009-09-28 #b6882166#
+ // assure notifications on position changes.
+ const SwLayNotify aNotify( this );
+ // <--
+ (this->*fnRect->fnMakePos)( GetUpper(), GetPrev(), sal_False );
+ bValidPos = sal_True;
+ }
+ SwTwips nDeadLine = (GetUpper()->*fnRect->fnGetPrtBottom)();
+ // OD 22.10.2002 #97265# - call always method <lcl_ColumnRefresh(..)>, in
+ // order to get calculated lowers, not only if there space left in its upper.
+ if( (Frm().*fnRect->fnBottomDist)( nDeadLine ) >= 0 )
+ {
+ (Frm().*fnRect->fnSetBottom)( nDeadLine );
+ long nHeight = (Frm().*fnRect->fnGetHeight)();
+ long nTop = CalcUpperSpace();
+ if( nTop > nHeight )
+ nTop = nHeight;
+ (this->*fnRect->fnSetYMargins)( nTop, 0 );
+ }
+ lcl_ColumnRefresh( this, sal_False );
+ UnlockJoin();
+}
+
+// --> OD 2005-01-11 #i40147# - helper class to perform extra section format
+// to position anchored objects and to keep the position of whose objects locked.
+class ExtraFormatToPositionObjs
+{
+ private:
+ SwSectionFrm* mpSectFrm;
+ bool mbExtraFormatPerformed;
+
+ public:
+ ExtraFormatToPositionObjs( SwSectionFrm& _rSectFrm)
+ : mpSectFrm( &_rSectFrm ),
+ mbExtraFormatPerformed( false )
+ {}
+
+ ~ExtraFormatToPositionObjs()
+ {
+ if ( mbExtraFormatPerformed )
+ {
+ // release keep locked position of lower floating screen objects
+ SwPageFrm* pPageFrm = mpSectFrm->FindPageFrm();
+ SwSortedObjs* pObjs = pPageFrm ? pPageFrm->GetSortedObjs() : 0L;
+ if ( pObjs )
+ {
+ sal_uInt32 i = 0;
+ for ( i = 0; i < pObjs->Count(); ++i )
+ {
+ SwAnchoredObject* pAnchoredObj = (*pObjs)[i];
+
+ if ( mpSectFrm->IsAnLower( pAnchoredObj->GetAnchorFrm() ) )
+ {
+ pAnchoredObj->SetKeepPosLocked( false );
+ }
+ }
+ }
+ }
+ }
+
+ // --> OD 2008-06-20 #i81555#
+ void InitObjs( SwFrm& rFrm )
+ {
+ SwSortedObjs* pObjs = rFrm.GetDrawObjs();
+ if ( pObjs )
+ {
+ sal_uInt32 i = 0;
+ for ( i = 0; i < pObjs->Count(); ++i )
+ {
+ SwAnchoredObject* pAnchoredObj = (*pObjs)[i];
+
+ pAnchoredObj->UnlockPosition();
+ pAnchoredObj->SetClearedEnvironment( false );
+ }
+ }
+ SwLayoutFrm* pLayoutFrm = dynamic_cast<SwLayoutFrm*>(&rFrm);
+ if ( pLayoutFrm != 0 )
+ {
+ SwFrm* pLowerFrm = pLayoutFrm->GetLower();
+ while ( pLowerFrm != 0 )
+ {
+ InitObjs( *pLowerFrm );
+
+ pLowerFrm = pLowerFrm->GetNext();
+ }
+ }
+ }
+ // <--
+
+ void FormatSectionToPositionObjs()
+ {
+ // perform extra format for multi-columned section.
+ if ( mpSectFrm->Lower() && mpSectFrm->Lower()->IsColumnFrm() &&
+ mpSectFrm->Lower()->GetNext() )
+ {
+ // grow section till bottom of printing area of upper frame
+ SWRECTFN( mpSectFrm );
+ SwTwips nTopMargin = (mpSectFrm->*fnRect->fnGetTopMargin)();
+ Size aOldSectPrtSize( mpSectFrm->Prt().SSize() );
+ SwTwips nDiff = (mpSectFrm->Frm().*fnRect->fnBottomDist)(
+ (mpSectFrm->GetUpper()->*fnRect->fnGetPrtBottom)() );
+ (mpSectFrm->Frm().*fnRect->fnAddBottom)( nDiff );
+ (mpSectFrm->*fnRect->fnSetYMargins)( nTopMargin, 0 );
+ // --> OD 2006-05-08 #i59789#
+ // suppress formatting, if printing area of section is too narrow
+ if ( (mpSectFrm->Prt().*fnRect->fnGetHeight)() <= 0 )
+ {
+ return;
+ }
+ // <--
+ mpSectFrm->ChgLowersProp( aOldSectPrtSize );
+
+ // format column frames and its body and footnote container
+ SwColumnFrm* pColFrm = static_cast<SwColumnFrm*>(mpSectFrm->Lower());
+ while ( pColFrm )
+ {
+ pColFrm->Calc();
+ pColFrm->Lower()->Calc();
+ if ( pColFrm->Lower()->GetNext() )
+ {
+ pColFrm->Lower()->GetNext()->Calc();
+ }
+
+ pColFrm = static_cast<SwColumnFrm*>(pColFrm->GetNext());
+ }
+
+ // unlock position of lower floating screen objects for the extra format
+ // --> OD 2008-06-20 #i81555#
+ // Section frame can already have changed the page and its content
+ // can still be on the former page.
+ // Thus, initialize objects via lower-relationship
+ InitObjs( *mpSectFrm );
+ // <--
+
+ // format content - first with collecting its foot-/endnotes before content
+ // format, second without collecting its foot-/endnotes.
+ ::CalcCntnt( mpSectFrm );
+ ::CalcCntnt( mpSectFrm, true );
+
+ // keep locked position of lower floating screen objects
+ SwPageFrm* pPageFrm = mpSectFrm->FindPageFrm();
+ SwSortedObjs* pObjs = pPageFrm ? pPageFrm->GetSortedObjs() : 0L;
+ if ( pObjs )
+ {
+ sal_uInt32 i = 0;
+ for ( i = 0; i < pObjs->Count(); ++i )
+ {
+ SwAnchoredObject* pAnchoredObj = (*pObjs)[i];
+
+ if ( mpSectFrm->IsAnLower( pAnchoredObj->GetAnchorFrm() ) )
+ {
+ pAnchoredObj->SetKeepPosLocked( true );
+ }
+ }
+ }
+
+ mbExtraFormatPerformed = true;
+ }
+ }
+};
+
+/*************************************************************************
+|*
+|* SwSectionFrm::Format()
+|*
+|* Beschreibung: "Formatiert" den Frame; Frm und PrtArea.
+|*
+|*************************************************************************/
+
+void SwSectionFrm::Format( const SwBorderAttrs *pAttr )
+{
+ if( !pSection ) // Durch DelEmpty
+ {
+#if OSL_DEBUG_LEVEL > 1
+ OSL_ENSURE( getRootFrm()->IsInDelList( this ), "SectionFrm without Section" );
+#endif
+ bValidSize = bValidPos = bValidPrtArea = sal_True;
+ return;
+ }
+ SWRECTFN( this )
+ if ( !bValidPrtArea )
+ {
+ PROTOCOL( this, PROT_PRTAREA, 0, 0 )
+ bValidPrtArea = sal_True;
+ SwTwips nUpper = CalcUpperSpace();
+
+ // #109700# LRSpace for sections
+ const SvxLRSpaceItem& rLRSpace = GetFmt()->GetLRSpace();
+ (this->*fnRect->fnSetXMargins)( rLRSpace.GetLeft(), rLRSpace.GetRight() );
+
+ if( nUpper != (this->*fnRect->fnGetTopMargin)() )
+ {
+ bValidSize = sal_False;
+ SwFrm* pOwn = ContainsAny();
+ if( pOwn )
+ pOwn->_InvalidatePos();
+ }
+ (this->*fnRect->fnSetYMargins)( nUpper, 0 );
+ }
+
+ if ( !bValidSize )
+ {
+ PROTOCOL_ENTER( this, PROT_SIZE, 0, 0 )
+ const long nOldHeight = (Frm().*fnRect->fnGetHeight)();
+ sal_Bool bOldLock = IsColLocked();
+ ColLock();
+
+ bValidSize = sal_True;
+
+ //die Groesse wird nur dann vom Inhalt bestimmt, wenn der SectFrm
+ //keinen Follow hat. Anderfalls fuellt er immer den Upper bis
+ //zur Unterkante aus. Fuer den Textfluss ist nicht er, sondern sein
+ //Inhalt selbst verantwortlich.
+ sal_Bool bMaximize = ToMaximize( sal_False );
+
+ // OD 2004-05-17 #i28701# - If the wrapping style has to be considered
+ // on object positioning, an extra formatting has to be performed
+ // to determine the correct positions the floating screen objects.
+ // --> OD 2005-01-11 #i40147#
+ // use new helper class <ExtraFormatToPositionObjs>.
+ // This class additionally keep the locked position of the objects
+ // and releases this position lock keeping on destruction.
+ ExtraFormatToPositionObjs aExtraFormatToPosObjs( *this );
+ if ( !bMaximize &&
+ GetFmt()->getIDocumentSettingAccess()->get(IDocumentSettingAccess::CONSIDER_WRAP_ON_OBJECT_POSITION) &&
+ !GetFmt()->GetBalancedColumns().GetValue() )
+ {
+ aExtraFormatToPosObjs.FormatSectionToPositionObjs();
+ }
+ // <--
+
+ // Column widths have to be adjusted before calling _CheckClipping.
+ // _CheckClipping can cause the formatting of the lower frames
+ // which still have a width of 0.
+ const sal_Bool bHasColumns = Lower() && Lower()->IsColumnFrm();
+ if ( bHasColumns && Lower()->GetNext() )
+ AdjustColumns( 0, sal_False );
+
+ if( GetUpper() )
+ {
+ long nWidth = (GetUpper()->Prt().*fnRect->fnGetWidth)();
+ (aFrm.*fnRect->fnSetWidth)( nWidth );
+
+ // #109700# LRSpace for sections
+ const SvxLRSpaceItem& rLRSpace = GetFmt()->GetLRSpace();
+ (aPrt.*fnRect->fnSetWidth)( nWidth - rLRSpace.GetLeft() -
+ rLRSpace.GetRight() );
+
+ // OD 15.10.2002 #103517# - allow grow in online layout
+ // Thus, set <..IsBrowseMode()> as parameter <bGrow> on calling
+ // method <_CheckClipping(..)>.
+ const ViewShell *pSh = getRootFrm()->GetCurrShell();
+ _CheckClipping( pSh && pSh->GetViewOptions()->getBrowseMode(), bMaximize );
+ bMaximize = ToMaximize( sal_False );
+ bValidSize = sal_True;
+ }
+
+ //Breite der Spalten pruefen und ggf. einstellen.
+ if ( bHasColumns && ! Lower()->GetNext() && bMaximize )
+ ((SwColumnFrm*)Lower())->Lower()->Calc();
+
+ if ( !bMaximize )
+ {
+ SwTwips nRemaining = (this->*fnRect->fnGetTopMargin)();
+ SwFrm *pFrm = pLower;
+ if( pFrm )
+ {
+ if( pFrm->IsColumnFrm() && pFrm->GetNext() )
+ {
+ // --> OD 2006-05-08 #i61435#
+ // suppress formatting, if upper frame has height <= 0
+ if ( (GetUpper()->Frm().*fnRect->fnGetHeight)() > 0 )
+ {
+ FormatWidthCols( *pAttr, nRemaining, MINLAY );
+ }
+ // <--
+ // --> OD 2006-01-04 #126020# - adjust check for empty section
+ // --> OD 2006-02-01 #130797# - correct fix #126020#
+ while( HasFollow() && !GetFollow()->ContainsCntnt() &&
+ !GetFollow()->ContainsAny( true ) )
+ // <--
+ {
+ SwFrm* pOld = GetFollow();
+ GetFollow()->DelEmpty( sal_False );
+ if( pOld == GetFollow() )
+ break;
+ }
+ bMaximize = ToMaximize( sal_False );
+ nRemaining += (pFrm->Frm().*fnRect->fnGetHeight)();
+ }
+ else
+ {
+ if( pFrm->IsColumnFrm() )
+ {
+ pFrm->Calc();
+ pFrm = ((SwColumnFrm*)pFrm)->Lower();
+ pFrm->Calc();
+ pFrm = ((SwLayoutFrm*)pFrm)->Lower();
+ CalcFtnCntnt();
+ }
+ // Wenn wir in einem spaltigen Rahmen stehen und dieser
+ // gerade im FormatWidthCols ein CalcCntnt ruft, muss
+ // unser Inhalt ggf. kalkuliert werden.
+ if( pFrm && !pFrm->IsValid() && IsInFly() &&
+ FindFlyFrm()->IsColLocked() )
+ ::CalcCntnt( this );
+ nRemaining += InnerHeight();
+ bMaximize = HasFollow();
+ }
+ }
+
+ SwTwips nDiff = (Frm().*fnRect->fnGetHeight)() - nRemaining;
+ if( nDiff < 0)
+ {
+ SwTwips nDeadLine = (GetUpper()->*fnRect->fnGetPrtBottom)();
+ {
+ long nBottom = (Frm().*fnRect->fnGetBottom)();
+ nBottom = (*fnRect->fnYInc)( nBottom, -nDiff );
+ long nTmpDiff = (*fnRect->fnYDiff)( nBottom, nDeadLine );
+ if( nTmpDiff > 0 )
+ {
+ nTmpDiff = GetUpper()->Grow( nTmpDiff, sal_True );
+ nDeadLine = (*fnRect->fnYInc)( nDeadLine, nTmpDiff );
+ nTmpDiff = (*fnRect->fnYDiff)( nBottom, nDeadLine );
+ if( nTmpDiff > 0 )
+ nDiff += nTmpDiff;
+ if( nDiff > 0 )
+ nDiff = 0;
+ }
+ }
+ }
+ if( nDiff )
+ {
+ long nTmp = nRemaining - (Frm().*fnRect->fnGetHeight)();
+ long nTop = (this->*fnRect->fnGetTopMargin)();
+ (Frm().*fnRect->fnAddBottom)( nTmp );
+ (this->*fnRect->fnSetYMargins)( nTop, 0 );
+ InvalidateNextPos();
+ if( pLower && ( !pLower->IsColumnFrm() || !pLower->GetNext() ) )
+ {
+ // Wenn ein einspaltiger Bereich gerade den Platz geschaffen
+ // hat, den sich die "undersized" Absaetze gewuenscht haben,
+ // muessen diese invalidiert und kalkuliert werden, damit
+ // sie diesen ausfuellen.
+ pFrm = pLower;
+ if( pFrm->IsColumnFrm() )
+ {
+ pFrm->_InvalidateSize();
+ pFrm->_InvalidatePos();
+ pFrm->Calc();
+ pFrm = ((SwColumnFrm*)pFrm)->Lower();
+ pFrm->Calc();
+ pFrm = ((SwLayoutFrm*)pFrm)->Lower();
+ CalcFtnCntnt();
+ }
+ sal_Bool bUnderSz = sal_False;
+ while( pFrm )
+ {
+ if( pFrm->IsTxtFrm() && ((SwTxtFrm*)pFrm)->IsUndersized() )
+ {
+ pFrm->Prepare( PREP_ADJUST_FRM );
+ bUnderSz = sal_True;
+ }
+ pFrm = pFrm->GetNext();
+ }
+ if( bUnderSz && !IsCntntLocked() )
+ ::CalcCntnt( this );
+ }
+ }
+ }
+
+ //Unterkante des Uppers nicht ueberschreiten. Fuer Sections mit
+ //Follows die Unterkante auch nicht unterschreiten.
+ if ( GetUpper() )
+ _CheckClipping( sal_True, bMaximize );
+ if( !bOldLock )
+ ColUnlock();
+ long nDiff = nOldHeight - (Frm().*fnRect->fnGetHeight)();
+ if( nDiff > 0 )
+ {
+ if( !GetNext() )
+ SetRetouche(); // Dann muessen wir die Retusche selbst uebernehmen
+ if( GetUpper() && !GetUpper()->IsFooterFrm() )
+ GetUpper()->Shrink( nDiff );
+ }
+ if( IsUndersized() )
+ bValidPrtArea = sal_True;
+ }
+}
+
+/*************************************************************************
+|*
+|* SwFrm::GetNextSctLeaf()
+|*
+|* Beschreibung Liefert das naechste Layoutblatt in das der Frame
+|* gemoved werden kann.
+|* Neue Seiten werden nur dann erzeugt, wenn der Parameter sal_True ist.
+|*
+|*************************************************************************/
+
+
+SwLayoutFrm *SwFrm::GetNextSctLeaf( MakePageType eMakePage )
+{
+ //Achtung: Geschachtelte Bereiche werden zur Zeit nicht unterstuetzt.
+
+ PROTOCOL_ENTER( this, PROT_LEAF, ACT_NEXT_SECT, GetUpper()->FindSctFrm() )
+
+ // Abkuerzungen fuer spaltige Bereiche, wenn wir noch nicht in der letzten Spalte sind.
+ // Koennen wir in die naechste Spalte des Bereichs rutschen?
+ if( IsColBodyFrm() && GetUpper()->GetNext() )
+ return (SwLayoutFrm*)((SwLayoutFrm*)GetUpper()->GetNext())->Lower();
+ if( GetUpper()->IsColBodyFrm() && GetUpper()->GetUpper()->GetNext() )
+ return (SwLayoutFrm*)((SwLayoutFrm*)GetUpper()->GetUpper()->GetNext())->Lower();
+ // Innerhalb von Bereichen in Tabellen oder Bereichen in Kopf/Fusszeilen kann
+ // nur ein Spaltenwechsel erfolgen, eine der oberen Abkuerzungen haette zuschlagen muessen
+ if( GetUpper()->IsInTab() || FindFooterOrHeader() )
+ return 0;
+
+//MA 03. Feb. 99: Warum GetUpper()? Das knallt mit Buch.sgl weil im
+//FlyAtCnt::MakeFlyPos ein Orient der SectionFrm ist und auf diesen ein
+//GetLeaf gerufen wird.
+// SwSectionFrm *pSect = GetUpper()->FindSctFrm();
+ SwSectionFrm *pSect = FindSctFrm();
+ sal_Bool bWrongPage = sal_False;
+ OSL_ENSURE( pSect, "GetNextSctLeaf: Missing SectionFrm" );
+
+ // Hier eine Abkuerzung fuer Bereiche mit Follows,
+ // dieser kann akzeptiert werden, wenn keine Spalten oder Seiten (ausser Dummyseiten)
+ // dazwischen liegen.
+ // Bei verketteten Rahmen und ind Fussnoten wuerde die Abkuerzung noch aufwendiger
+ if( pSect->HasFollow() && pSect->IsInDocBody() )
+ {
+ if( pSect->GetFollow() == pSect->GetNext() )
+ {
+ SwPageFrm *pPg = pSect->GetFollow()->FindPageFrm();
+ if( WrongPageDesc( pPg ) )
+ bWrongPage = sal_True;
+ else
+ return FIRSTLEAF( pSect->GetFollow() );
+ }
+ else
+ {
+ SwFrm* pTmp;
+ if( !pSect->GetUpper()->IsColBodyFrm() ||
+ 0 == ( pTmp = pSect->GetUpper()->GetUpper()->GetNext() ) )
+ pTmp = pSect->FindPageFrm()->GetNext();
+ if( pTmp ) // ist jetzt die naechste Spalte oder Seite
+ {
+ SwFrm* pTmpX = pTmp;
+ if( pTmp->IsPageFrm() && ((SwPageFrm*)pTmp)->IsEmptyPage() )
+ pTmp = pTmp->GetNext(); // Dummyseiten ueberspringen
+ SwFrm *pUp = pSect->GetFollow()->GetUpper();
+ // pUp wird die Spalte, wenn der Follow in einer "nicht ersten" Spalte
+ // liegt, ansonsten die Seite:
+ if( !pUp->IsColBodyFrm() ||
+ !( pUp = pUp->GetUpper() )->GetPrev() )
+ pUp = pUp->FindPageFrm();
+ // Jetzt muessen pUp und pTmp die gleiche Seite/Spalte sein,
+ // sonst liegen Seiten oder Spalten zwischen Master und Follow.
+ if( pUp == pTmp || pUp->GetNext() == pTmpX )
+ {
+ SwPageFrm* pNxtPg = pUp->IsPageFrm() ?
+ (SwPageFrm*)pUp : pUp->FindPageFrm();
+ if( WrongPageDesc( pNxtPg ) )
+ bWrongPage = sal_True;
+ else
+ return FIRSTLEAF( pSect->GetFollow() );
+ }
+ }
+ }
+ }
+
+ // Immer im gleichen Bereich landen: Body wieder in Body etc.
+ const sal_Bool bBody = IsInDocBody();
+ const sal_Bool bFtnPage = FindPageFrm()->IsFtnPage();
+
+ SwLayoutFrm *pLayLeaf;
+ // Eine Abkuerzung fuer TabFrms, damit nicht alle Zellen abgehuehnert werden
+ if( bWrongPage )
+ pLayLeaf = 0;
+ else if( IsTabFrm() )
+ {
+ SwCntntFrm* pTmpCnt = ((SwTabFrm*)this)->FindLastCntnt();
+ pLayLeaf = pTmpCnt ? pTmpCnt->GetUpper() : 0;
+ }
+ else
+ {
+ pLayLeaf = GetNextLayoutLeaf();
+ if( IsColumnFrm() )
+ {
+ while( pLayLeaf && ((SwColumnFrm*)this)->IsAnLower( pLayLeaf ) )
+ pLayLeaf = pLayLeaf->GetNextLayoutLeaf();
+ }
+ }
+
+ SwLayoutFrm *pOldLayLeaf = 0; //Damit bei neu erzeugten Seiten
+ //nicht wieder vom Anfang gesucht
+ //wird.
+
+ while( sal_True )
+ {
+ if( pLayLeaf )
+ {
+ // Ein Layoutblatt wurde gefunden, mal sehen, ob er mich aufnehmen kann,
+ // ob hier ein weiterer SectionFrm eingefuegt werden kann
+ // oder ob wir weitersuchen muessen.
+ SwPageFrm* pNxtPg = pLayLeaf->FindPageFrm();
+ if ( !bFtnPage && pNxtPg->IsFtnPage() )
+ { //Wenn ich bei den Endnotenseiten angelangt bin hat sichs.
+ pLayLeaf = 0;
+ continue;
+ }
+ // Einmal InBody, immer InBody, nicht in Tabellen hinein
+ // und nicht in fremde Bereiche hinein
+ if ( (bBody && !pLayLeaf->IsInDocBody()) ||
+ (IsInFtn() != pLayLeaf->IsInFtn() ) ||
+ pLayLeaf->IsInTab() ||
+ ( pLayLeaf->IsInSct() && ( !pSect->HasFollow()
+ || pSect->GetFollow() != pLayLeaf->FindSctFrm() ) ) )
+ {
+ //Er will mich nicht; neuer Versuch, neues Glueck
+ pOldLayLeaf = pLayLeaf;
+ pLayLeaf = pLayLeaf->GetNextLayoutLeaf();
+ continue;
+ }
+ if( WrongPageDesc( pNxtPg ) )
+ {
+ if( bWrongPage )
+ break; // there's a column between me and my right page
+ pLayLeaf = 0;
+ bWrongPage = sal_True;
+ pOldLayLeaf = 0;
+ continue;
+ }
+ }
+ //Es gibt keinen passenden weiteren LayoutFrm, also muss eine
+ //neue Seite her, allerdings nuetzen uns innerhalb eines Rahmens
+ //neue Seiten nichts.
+ else if( !pSect->IsInFly() &&
+ ( eMakePage == MAKEPAGE_APPEND || eMakePage == MAKEPAGE_INSERT ) )
+ {
+ InsertPage(pOldLayLeaf ? pOldLayLeaf->FindPageFrm() : FindPageFrm(),
+ sal_False );
+ //und nochmal das ganze
+ pLayLeaf = pOldLayLeaf ? pOldLayLeaf : GetNextLayoutLeaf();
+ continue;
+ }
+ break;
+ }
+
+ if( pLayLeaf )
+ {
+ // Das passende Layoutblatt haben wir gefunden, wenn es dort bereits einen
+ // Follow unseres Bereichs gibt, nehmen wir dessen erstes Layoutblatt,
+ // andernfalls wird es Zeit, einen Bereichsfollow zu erzeugen
+ SwSectionFrm* pNew;
+
+ //Dies kann entfallen, wenn bei existierenden Follows bereits abgekuerzt wurde
+ SwFrm* pFirst = pLayLeaf->Lower();
+ // Auch hier muessen zum Loeschen angemeldete SectionFrms ignoriert werden
+ while( pFirst && pFirst->IsSctFrm() && !((SwSectionFrm*)pFirst)->GetSection() )
+ pFirst = pFirst->GetNext();
+ if( pFirst && pFirst->IsSctFrm() && pSect->GetFollow() == pFirst )
+ pNew = pSect->GetFollow();
+ else if( MAKEPAGE_NOSECTION == eMakePage )
+ return pLayLeaf;
+ else
+ {
+ pNew = new SwSectionFrm( *pSect, sal_False );
+ pNew->InsertBefore( pLayLeaf, pLayLeaf->Lower() );
+ pNew->Init();
+ SWRECTFN( pNew )
+ (pNew->*fnRect->fnMakePos)( pLayLeaf, NULL, sal_True );
+
+ // Wenn unser Bereichsframe einen Nachfolger hat, so muss dieser
+ // umgehaengt werden hinter den neuen Follow der Bereichsframes.
+ SwFrm* pTmp = pSect->GetNext();
+ if( pTmp && pTmp != pSect->GetFollow() )
+ {
+ SwFlowFrm* pNxt;
+ SwCntntFrm* pNxtCntnt = NULL;
+ if( pTmp->IsCntntFrm() )
+ {
+ pNxt = (SwCntntFrm*)pTmp;
+ pNxtCntnt = (SwCntntFrm*)pTmp;
+ }
+ else
+ {
+ pNxtCntnt = ((SwLayoutFrm*)pTmp)->ContainsCntnt();
+ if( pTmp->IsSctFrm() )
+ pNxt = (SwSectionFrm*)pTmp;
+ else
+ {
+ OSL_ENSURE( pTmp->IsTabFrm(), "GetNextSctLeaf: Wrong Type" );
+ pNxt = (SwTabFrm*)pTmp;
+ }
+ while( !pNxtCntnt && 0 != ( pTmp = pTmp->GetNext() ) )
+ {
+ if( pTmp->IsCntntFrm() )
+ pNxtCntnt = (SwCntntFrm*)pTmp;
+ else
+ pNxtCntnt = ((SwLayoutFrm*)pTmp)->ContainsCntnt();
+ }
+ }
+ if( pNxtCntnt )
+ {
+ SwFtnBossFrm* pOldBoss = pSect->FindFtnBossFrm( sal_True );
+ if( pOldBoss == pNxtCntnt->FindFtnBossFrm( sal_True ) )
+ {
+ SwSaveFtnHeight aHeight( pOldBoss,
+ pOldBoss->Frm().Top() + pOldBoss->Frm().Height() );
+ pSect->GetUpper()->MoveLowerFtns( pNxtCntnt, pOldBoss,
+ pLayLeaf->FindFtnBossFrm( sal_True ), sal_False );
+ }
+ }
+ ((SwFlowFrm*)pNxt)->MoveSubTree( pLayLeaf, pNew->GetNext() );
+ }
+ if( pNew->GetFollow() )
+ pNew->SimpleFormat();
+ }
+ // Das gesuchte Layoutblatt ist jetzt das erste des ermittelten SctFrms:
+ pLayLeaf = FIRSTLEAF( pNew );
+ }
+ return pLayLeaf;
+}
+
+/*************************************************************************
+|*
+|* SwFrm::GetPrevSctLeaf()
+|*
+|* Beschreibung Liefert das vorhergehende LayoutBlatt in das der
+|* Frame gemoved werden kann.
+|*
+|*************************************************************************/
+
+
+SwLayoutFrm *SwFrm::GetPrevSctLeaf( MakePageType )
+{
+ PROTOCOL_ENTER( this, PROT_LEAF, ACT_PREV_SECT, GetUpper()->FindSctFrm() )
+
+ SwLayoutFrm* pCol;
+ // ColumnFrm beinhalten jetzt stets einen BodyFrm
+ if( IsColBodyFrm() )
+ pCol = GetUpper();
+ else if( GetUpper()->IsColBodyFrm() )
+ pCol = GetUpper()->GetUpper();
+ else
+ pCol = NULL;
+ sal_Bool bJump = sal_False;
+ if( pCol )
+ {
+ if( pCol->GetPrev() )
+ {
+ do
+ {
+ pCol = (SwLayoutFrm*)pCol->GetPrev();
+ // Gibt es dort Inhalt?
+ if( ((SwLayoutFrm*)pCol->Lower())->Lower() )
+ {
+ if( bJump ) // Haben wir eine leere Spalte uebersprungen?
+ SwFlowFrm::SetMoveBwdJump( sal_True );
+ return (SwLayoutFrm*)pCol->Lower(); // Der Spaltenbody
+ }
+ bJump = sal_True;
+ } while( pCol->GetPrev() );
+
+ // Hier landen wir, wenn alle Spalten leer sind,
+ // pCol ist jetzt die erste Spalte, wir brauchen aber den Body:
+ pCol = (SwLayoutFrm*)pCol->Lower();
+ }
+ else
+ pCol = NULL;
+ }
+
+ if( bJump ) // Haben wir eine leere Spalte uebersprungen?
+ SwFlowFrm::SetMoveBwdJump( sal_True );
+
+ // Innerhalb von Bereichen in Tabellen oder Bereichen in Kopf/Fusszeilen kann
+ // nur ein Spaltenwechsel erfolgen, eine der oberen Abkuerzungen haette
+ // zuschlagen muessen, ebenso wenn der Bereich einen pPrev hat.
+ // Jetzt ziehen wir sogar eine leere Spalte in Betracht...
+ OSL_ENSURE( FindSctFrm(), "GetNextSctLeaf: Missing SectionFrm" );
+ if( ( IsInTab() && !IsTabFrm() ) || FindFooterOrHeader() )
+ return pCol;
+
+ // === IMPORTANT ===
+ // Precondition, which needs to be hold, is that the <this> frame can be
+ // inside a table, but then the found section frame <pSect> is also inside
+ // this table.
+ SwSectionFrm *pSect = FindSctFrm();
+
+ // --> OD 2009-01-16 #i95698#
+ // A table cell containing directly a section does not break - see lcl_FindSectionsInRow(..)
+ // Thus, a table inside a section, which is inside another table can only
+ // flow backward in the columns of its section.
+ // Note: The table cell, which contains the section, can not have a master table cell.
+ if ( IsTabFrm() && pSect->IsInTab() )
+ {
+ return pCol;
+ }
+ // <--
+
+ {
+ SwFrm *pPrv;
+ if( 0 != ( pPrv = pSect->GetIndPrev() ) )
+ {
+ // Herumlungernde, halbtote SectionFrms sollen uns nicht beirren
+ while( pPrv && pPrv->IsSctFrm() && !((SwSectionFrm*)pPrv)->GetSection() )
+ pPrv = pPrv->GetPrev();
+ if( pPrv )
+ return pCol;
+ }
+ }
+
+ const sal_Bool bBody = IsInDocBody();
+ const sal_Bool bFly = IsInFly();
+
+ SwLayoutFrm *pLayLeaf = GetPrevLayoutLeaf();
+ SwLayoutFrm *pPrevLeaf = 0;
+
+ while ( pLayLeaf )
+ {
+ //In Tabellen oder Bereiche geht's niemals hinein.
+ if ( pLayLeaf->IsInTab() || pLayLeaf->IsInSct() )
+ {
+ pLayLeaf = pLayLeaf->GetPrevLayoutLeaf();
+ }
+ else if ( bBody && pLayLeaf->IsInDocBody() )
+ {
+ // If there is a pLayLeaf has a lower pLayLeaf is the frame we are looking for.
+ // Exception: pLayLeaf->Lower() is a zombie section frame
+ const SwFrm* pTmp = pLayLeaf->Lower();
+ // OD 11.04.2003 #108824# - consider, that the zombie section frame
+ // can have frame below it in the found layout leaf.
+ // Thus, skipping zombie section frame, if possible.
+ while ( pTmp && pTmp->IsSctFrm() &&
+ !( static_cast<const SwSectionFrm*>(pTmp)->GetSection() ) &&
+ pTmp->GetNext()
+ )
+ {
+ pTmp = pTmp->GetNext();
+ }
+ if ( pTmp &&
+ ( !pTmp->IsSctFrm() ||
+ ( static_cast<const SwSectionFrm*>(pTmp)->GetSection() )
+ )
+ )
+ {
+ break;
+ }
+ pPrevLeaf = pLayLeaf;
+ pLayLeaf = pLayLeaf->GetPrevLayoutLeaf();
+ if ( pLayLeaf )
+ SwFlowFrm::SetMoveBwdJump( sal_True );
+ }
+ else if ( bFly )
+ break; //Cntnts in Flys sollte jedes Layout-Blatt recht sein. Warum?
+ else
+ pLayLeaf = pLayLeaf->GetPrevLayoutLeaf();
+ }
+ if( !pLayLeaf )
+ {
+ if( !pPrevLeaf )
+ return pCol;
+ pLayLeaf = pPrevLeaf;
+ }
+
+ SwSectionFrm* pNew = NULL;
+ // Zunaechst einmal an das Ende des Layoutblatts gehen
+ SwFrm *pTmp = pLayLeaf->Lower();
+ if( pTmp )
+ {
+ while( pTmp->GetNext() )
+ pTmp = pTmp->GetNext();
+ if( pTmp->IsSctFrm() )
+ {
+ // Halbtote stoeren hier nur...
+ while( !((SwSectionFrm*)pTmp)->GetSection() && pTmp->GetPrev() &&
+ pTmp->GetPrev()->IsSctFrm() )
+ pTmp = pTmp->GetPrev();
+ if( ((SwSectionFrm*)pTmp)->GetFollow() == pSect )
+ pNew = (SwSectionFrm*)pTmp;
+ }
+ }
+ if( !pNew )
+ {
+ pNew = new SwSectionFrm( *pSect, sal_True );
+ pNew->InsertBefore( pLayLeaf, NULL );
+ pNew->Init();
+ SWRECTFN( pNew )
+ (pNew->*fnRect->fnMakePos)( pLayLeaf, pNew->GetPrev(), sal_True );
+
+ pLayLeaf = FIRSTLEAF( pNew );
+ if( !pNew->Lower() ) // einspaltige Bereiche formatieren
+ {
+ pNew->MakePos();
+ pLayLeaf->Format(); // damit die PrtArea fuers MoveBwd stimmt
+ }
+ else
+ pNew->SimpleFormat();
+ }
+ else
+ {
+ pLayLeaf = FIRSTLEAF( pNew );
+ if( pLayLeaf->IsColBodyFrm() )
+ {
+ // In existent section columns we're looking for the last not empty
+ // column.
+ SwLayoutFrm *pTmpLay = pLayLeaf;
+ while( pLayLeaf->GetUpper()->GetNext() )
+ {
+ pLayLeaf = (SwLayoutFrm*)((SwLayoutFrm*)pLayLeaf->GetUpper()->GetNext())->Lower();
+ if( pLayLeaf->Lower() )
+ pTmpLay = pLayLeaf;
+ }
+ // If we skipped an empty column, we've to set the jump-flag
+ if( pLayLeaf != pTmpLay )
+ {
+ pLayLeaf = pTmpLay;
+ SwFlowFrm::SetMoveBwdJump( sal_True );
+ }
+ }
+ }
+ return pLayLeaf;
+}
+
+SwTwips lcl_DeadLine( const SwFrm* pFrm )
+{
+ const SwLayoutFrm* pUp = pFrm->GetUpper();
+ while( pUp && pUp->IsInSct() )
+ {
+ if( pUp->IsSctFrm() )
+ pUp = pUp->GetUpper();
+ // Spalten jetzt mit BodyFrm
+ else if( pUp->IsColBodyFrm() && pUp->GetUpper()->GetUpper()->IsSctFrm() )
+ pUp = pUp->GetUpper()->GetUpper();
+ else
+ break;
+ }
+ SWRECTFN( pFrm )
+ return pUp ? (pUp->*fnRect->fnGetPrtBottom)() :
+ (pFrm->Frm().*fnRect->fnGetBottom)();
+}
+
+// SwSectionFrm::Growable(..) prueft, ob der SectionFrm noch wachsen kann,
+// ggf. muss die Umgebung gefragt werden
+
+sal_Bool SwSectionFrm::Growable() const
+{
+ SWRECTFN( this )
+ if( (*fnRect->fnYDiff)( lcl_DeadLine( this ),
+ (Frm().*fnRect->fnGetBottom)() ) > 0 )
+ return sal_True;
+
+ return ( GetUpper() && ((SwFrm*)GetUpper())->Grow( LONG_MAX, sal_True ) );
+}
+
+/*************************************************************************
+|*
+|* SwSectionFrm::_Grow(), _Shrink()
+|*
+|*************************************************************************/
+
+SwTwips SwSectionFrm::_Grow( SwTwips nDist, sal_Bool bTst )
+{
+ if ( !IsColLocked() && !HasFixSize() )
+ {
+ SWRECTFN( this )
+ long nFrmHeight = (Frm().*fnRect->fnGetHeight)();
+ if( nFrmHeight > 0 && nDist > (LONG_MAX - nFrmHeight) )
+ nDist = LONG_MAX - nFrmHeight;
+
+ if ( nDist <= 0L )
+ return 0L;
+
+ sal_Bool bInCalcCntnt = GetUpper() && IsInFly() && FindFlyFrm()->IsLocked();
+ // OD 2004-03-15 #116561# - allow grow in online layout
+ sal_Bool bGrow = !Lower() || !Lower()->IsColumnFrm() || !Lower()->GetNext() ||
+ GetSection()->GetFmt()->GetBalancedColumns().GetValue();
+ if( !bGrow )
+ {
+ const ViewShell *pSh = getRootFrm()->GetCurrShell();
+ bGrow = pSh && pSh->GetViewOptions()->getBrowseMode();
+ }
+ if( bGrow )
+ {
+ SwTwips nGrow;
+ if( IsInFtn() )
+ nGrow = 0;
+ else
+ {
+ nGrow = lcl_DeadLine( this );
+ nGrow = (*fnRect->fnYDiff)( nGrow,
+ (Frm().*fnRect->fnGetBottom)() );
+ }
+ SwTwips nSpace = nGrow;
+ if( !bInCalcCntnt && nGrow < nDist && GetUpper() )
+ nGrow += GetUpper()->Grow( LONG_MAX, sal_True );
+
+ if( nGrow > nDist )
+ nGrow = nDist;
+ if( nGrow <= 0 )
+ {
+ nGrow = 0;
+ if( nDist && !bTst )
+ {
+ if( bInCalcCntnt )
+ _InvalidateSize();
+ else
+ InvalidateSize();
+ }
+ }
+ else if( !bTst )
+ {
+ if( bInCalcCntnt )
+ _InvalidateSize();
+ else if( nSpace < nGrow && nDist != nSpace + GetUpper()->
+ Grow( nGrow - nSpace, sal_False ) )
+ InvalidateSize();
+ else
+ {
+ const SvxGraphicPosition ePos =
+ GetAttrSet()->GetBackground().GetGraphicPos();
+ if ( GPOS_RT < ePos && GPOS_TILED != ePos )
+ {
+ SetCompletePaint();
+ InvalidatePage();
+ }
+ if( GetUpper() && GetUpper()->IsHeaderFrm() )
+ GetUpper()->InvalidateSize();
+ }
+ (Frm().*fnRect->fnAddBottom)( nGrow );
+ long nPrtHeight = (Prt().*fnRect->fnGetHeight)() + nGrow;
+ (Prt().*fnRect->fnSetHeight)( nPrtHeight );
+
+ if( Lower() && Lower()->IsColumnFrm() && Lower()->GetNext() )
+ {
+ SwFrm* pTmp = Lower();
+ do
+ {
+ pTmp->_InvalidateSize();
+ pTmp = pTmp->GetNext();
+ } while ( pTmp );
+ _InvalidateSize();
+ }
+ if( GetNext() )
+ {
+ SwFrm *pFrm = GetNext();
+ while( pFrm && pFrm->IsSctFrm() && !((SwSectionFrm*)pFrm)->GetSection() )
+ pFrm = pFrm->GetNext();
+ if( pFrm )
+ {
+ if( bInCalcCntnt )
+ pFrm->_InvalidatePos();
+ else
+ pFrm->InvalidatePos();
+ }
+ }
+ // --> OD 2004-07-05 #i28701# - Due to the new object positioning
+ // the frame on the next page/column can flow backward (e.g. it
+ // was moved forward due to the positioning of its objects ).
+ // Thus, invalivate this next frame, if document compatibility
+ // option 'Consider wrapping style influence on object positioning' is ON.
+ else if ( GetFmt()->getIDocumentSettingAccess()->get(IDocumentSettingAccess::CONSIDER_WRAP_ON_OBJECT_POSITION) )
+ {
+ InvalidateNextPos();
+ }
+ // <--
+ }
+ return nGrow;
+ }
+ if ( !bTst )
+ {
+ if( bInCalcCntnt )
+ _InvalidateSize();
+ else
+ InvalidateSize();
+ }
+ }
+ return 0L;
+}
+
+SwTwips SwSectionFrm::_Shrink( SwTwips nDist, sal_Bool bTst )
+{
+ if ( Lower() && !IsColLocked() && !HasFixSize() )
+ {
+ if( ToMaximize( sal_False ) )
+ {
+ if( !bTst )
+ InvalidateSize();
+ }
+ else
+ {
+ SWRECTFN( this )
+ long nFrmHeight = (Frm().*fnRect->fnGetHeight)();
+ if ( nDist > nFrmHeight )
+ nDist = nFrmHeight;
+
+ if ( Lower()->IsColumnFrm() && Lower()->GetNext() && // FtnAtEnd
+ !GetSection()->GetFmt()->GetBalancedColumns().GetValue() )
+ { //Bei Spaltigkeit ubernimmt das Format die Kontrolle ueber
+ //das Wachstum (wg. des Ausgleichs).
+ if ( !bTst )
+ InvalidateSize();
+ return nDist;
+ }
+ else if( !bTst )
+ {
+ const SvxGraphicPosition ePos =
+ GetAttrSet()->GetBackground().GetGraphicPos();
+ if ( GPOS_RT < ePos && GPOS_TILED != ePos )
+ {
+ SetCompletePaint();
+ InvalidatePage();
+ }
+ (Frm().*fnRect->fnAddBottom)( -nDist );
+ long nPrtHeight = (Prt().*fnRect->fnGetHeight)() - nDist;
+ (Prt().*fnRect->fnSetHeight)( nPrtHeight );
+
+ // We do not allow a section frame to shrink the its upper
+ // footer frame. This is because in the calculation of a
+ // footer frame, the content of the section frame is _not_
+ // calculated. If there is a fly frame overlapping with the
+ // footer frame, the section frame is not affected by this
+ // during the calculation of the footer frame size.
+ // The footer frame does not grow in its FormatSize function
+ // but during the calculation of the content of the section
+ // frame. The section frame grows until some of its text is
+ // located on top of the fly frame. The next call of CalcCntnt
+ // tries to shrink the section and here it would also shrink
+ // the footer. This may not happen, because shrinking the footer
+ // would cause the top of the section frame to overlap with the
+ // fly frame again, this would result in a perfect loop.
+ if( GetUpper() && !GetUpper()->IsFooterFrm() )
+ GetUpper()->Shrink( nDist, bTst );
+
+ if( Lower() && Lower()->IsColumnFrm() && Lower()->GetNext() )
+ {
+ SwFrm* pTmp = Lower();
+ do
+ {
+ pTmp->_InvalidateSize();
+ pTmp = pTmp->GetNext();
+ } while ( pTmp );
+ }
+ if( GetNext() )
+ {
+ SwFrm* pFrm = GetNext();
+ while( pFrm && pFrm->IsSctFrm() && !((SwSectionFrm*)pFrm)->GetSection() )
+ pFrm = pFrm->GetNext();
+ if( pFrm )
+ pFrm->InvalidatePos();
+ else
+ SetRetouche();
+ }
+ else
+ SetRetouche();
+ return nDist;
+ }
+ }
+ }
+ return 0L;
+}
+
+/*************************************************************************
+|*
+|* SwSectionFrm::MoveAllowed()
+|*
+|* Wann sind Frms innerhalb eines SectionFrms moveable?
+|* Wenn sie noch nicht in der letzten Spalte des SectionFrms sind,
+|* wenn es einen Follow gibt,
+|* wenn der SectionFrm nicht mehr wachsen kann, wird es komplizierter,
+|* dann kommt es darauf an, ob der SectionFrm ein naechstes Layoutblatt
+|* finden kann. In (spaltigen/verketteten) Flys wird dies via GetNextLayout
+|* geprueft, in Tabellen und in Kopf/Fusszeilen gibt es keins, im DocBody
+|* und auch im Fussnoten dagegen immer.
+|*
+|* Benutzt wird diese Routine im TxtFormatter, um zu entscheiden, ob ein
+|* (Absatz-)Follow erzeugt werden darf oder ob der Absatz zusammenhalten muss.
+|*
+|*************************************************************************/
+
+sal_Bool SwSectionFrm::MoveAllowed( const SwFrm* pFrm) const
+{
+ // Gibt es einen Follow oder ist der Frame nicht in der letzten Spalte?
+ if( HasFollow() || ( pFrm->GetUpper()->IsColBodyFrm() &&
+ pFrm->GetUpper()->GetUpper()->GetNext() ) )
+ return sal_True;
+ if( pFrm->IsInFtn() )
+ {
+ if( IsInFtn() )
+ {
+ if( GetUpper()->IsInSct() )
+ {
+ if( Growable() )
+ return sal_False;
+ return GetUpper()->FindSctFrm()->MoveAllowed( this );
+ }
+ else
+ return sal_True;
+ }
+ // The content of footnote inside a columned sectionfrm is moveable
+ // except in the last column
+ const SwLayoutFrm *pLay = pFrm->FindFtnFrm()->GetUpper()->GetUpper();
+ if( pLay->IsColumnFrm() && pLay->GetNext() )
+ {
+ // The first paragraph in the first footnote in the first column
+ // in the sectionfrm at the top of the page is not moveable,
+ // if the columnbody is empty.
+ sal_Bool bRet = sal_False;
+ if( pLay->GetIndPrev() || pFrm->GetIndPrev() ||
+ pFrm->FindFtnFrm()->GetPrev() )
+ bRet = sal_True;
+ else
+ {
+ SwLayoutFrm* pBody = ((SwColumnFrm*)pLay)->FindBodyCont();
+ if( pBody && pBody->Lower() )
+ bRet = sal_True;
+ }
+ if( bRet && ( IsFtnAtEnd() || !Growable() ) )
+ return sal_True;
+ }
+ }
+ // Oder kann der Bereich noch wachsen?
+ if( !IsColLocked() && Growable() )
+ return sal_False;
+ // Jetzt muss untersucht werden, ob es ein Layoutblatt gibt, in dem
+ // ein Bereichsfollow erzeugt werden kann.
+ if( IsInTab() || ( !IsInDocBody() && FindFooterOrHeader() ) )
+ return sal_False; // In Tabellen/Kopf/Fusszeilen geht es nicht
+ if( IsInFly() ) // Bei spaltigen oder verketteten Rahmen
+ return 0 != ((SwFrm*)GetUpper())->GetNextLeaf( MAKEPAGE_NONE );
+ return sal_True;
+}
+
+/** Called for a frame inside a section with no direct previous frame (or only
+ previous empty section frames) the previous frame of the outer section is
+ returned, if the frame is the first flowing content of this section.
+
+ Note: For a frame inside a table frame, which is inside a section frame,
+ NULL is returned.
+*/
+SwFrm* SwFrm::_GetIndPrev() const
+{
+ SwFrm *pRet = NULL;
+ // --> OD 2007-09-04 #i79774#, #b659654#
+ // Do not assert, if the frame has a direct previous frame, because it
+ // could be an empty section frame. The caller has to assure, that the
+ // frame has no direct previous frame or only empty section frames as
+ // previous frames.
+ OSL_ENSURE( /*!pPrev &&*/ IsInSct(), "Why?" );
+ // <--
+ const SwFrm* pSct = GetUpper();
+ if( !pSct )
+ return NULL;
+ if( pSct->IsSctFrm() )
+ pRet = pSct->GetIndPrev();
+ else if( pSct->IsColBodyFrm() && (pSct = pSct->GetUpper()->GetUpper())->IsSctFrm() )
+ {
+ // Do not return the previous frame of the outer section, if in one
+ // of the previous columns is content.
+ const SwFrm* pCol = GetUpper()->GetUpper()->GetPrev();
+ while( pCol )
+ {
+ OSL_ENSURE( pCol->IsColumnFrm(), "GetIndPrev(): ColumnFrm expected" );
+ OSL_ENSURE( pCol->GetLower() && pCol->GetLower()->IsBodyFrm(),
+ "GetIndPrev(): Where's the body?");
+ if( ((SwLayoutFrm*)((SwLayoutFrm*)pCol)->Lower())->Lower() )
+ return NULL;
+ pCol = pCol->GetPrev();
+ }
+ pRet = pSct->GetIndPrev();
+ }
+
+ // skip empty section frames
+ while( pRet && pRet->IsSctFrm() && !((SwSectionFrm*)pRet)->GetSection() )
+ pRet = pRet->GetIndPrev();
+ return pRet;
+}
+
+SwFrm* SwFrm::_GetIndNext()
+{
+ OSL_ENSURE( !pNext && IsInSct(), "Why?" );
+ SwFrm* pSct = GetUpper();
+ if( !pSct )
+ return NULL;
+ if( pSct->IsSctFrm() )
+ return pSct->GetIndNext();
+ if( pSct->IsColBodyFrm() && (pSct = pSct->GetUpper()->GetUpper())->IsSctFrm() )
+ { // Wir duerfen nur den Nachfolger des SectionFrms zurueckliefern,
+ // wenn in keiner folgenden Spalte mehr Inhalt ist
+ SwFrm* pCol = GetUpper()->GetUpper()->GetNext();
+ while( pCol )
+ {
+ OSL_ENSURE( pCol->IsColumnFrm(), "GetIndNext(): ColumnFrm expected" );
+ OSL_ENSURE( pCol->GetLower() && pCol->GetLower()->IsBodyFrm(),
+ "GetIndNext(): Where's the body?");
+ if( ((SwLayoutFrm*)((SwLayoutFrm*)pCol)->Lower())->Lower() )
+ return NULL;
+ pCol = pCol->GetNext();
+ }
+ return pSct->GetIndNext();
+ }
+ return NULL;
+}
+
+sal_Bool SwSectionFrm::IsDescendantFrom( const SwSectionFmt* pFmt ) const
+{
+ if( !pSection || !pFmt )
+ return sal_False;
+ const SwSectionFmt *pMyFmt = pSection->GetFmt();
+ while( pFmt != pMyFmt )
+ {
+ if( pMyFmt->GetRegisteredIn()->ISA( SwSectionFmt ) )
+ pMyFmt = (SwSectionFmt*)pMyFmt->GetRegisteredIn();
+ else
+ return sal_False;
+ }
+ return sal_True;
+}
+
+void SwSectionFrm::CalcFtnAtEndFlag()
+{
+ SwSectionFmt *pFmt = GetSection()->GetFmt();
+ sal_uInt16 nVal = pFmt->GetFtnAtTxtEnd( sal_False ).GetValue();
+ bFtnAtEnd = FTNEND_ATPGORDOCEND != nVal;
+ bOwnFtnNum = FTNEND_ATTXTEND_OWNNUMSEQ == nVal ||
+ FTNEND_ATTXTEND_OWNNUMANDFMT == nVal;
+ while( !bFtnAtEnd && !bOwnFtnNum )
+ {
+ if( pFmt->GetRegisteredIn()->ISA( SwSectionFmt ) )
+ pFmt = (SwSectionFmt*)pFmt->GetRegisteredIn();
+ else
+ break;
+ nVal = pFmt->GetFtnAtTxtEnd( sal_False ).GetValue();
+ if( FTNEND_ATPGORDOCEND != nVal )
+ {
+ bFtnAtEnd = sal_True;
+ bOwnFtnNum = bOwnFtnNum ||FTNEND_ATTXTEND_OWNNUMSEQ == nVal ||
+ FTNEND_ATTXTEND_OWNNUMANDFMT == nVal;
+ }
+ }
+}
+
+sal_Bool SwSectionFrm::IsEndnoteAtMyEnd() const
+{
+ return pSection->GetFmt()->GetEndAtTxtEnd( sal_False ).IsAtEnd();
+}
+
+void SwSectionFrm::CalcEndAtEndFlag()
+{
+ SwSectionFmt *pFmt = GetSection()->GetFmt();
+ bEndnAtEnd = pFmt->GetEndAtTxtEnd( sal_False ).IsAtEnd();
+ while( !bEndnAtEnd )
+ {
+ if( pFmt->GetRegisteredIn()->ISA( SwSectionFmt ) )
+ pFmt = (SwSectionFmt*)pFmt->GetRegisteredIn();
+ else
+ break;
+ bEndnAtEnd = pFmt->GetEndAtTxtEnd( sal_False ).IsAtEnd();
+ }
+}
+
+/*************************************************************************
+|*
+|* SwSectionFrm::Modify()
+|*
+|*************************************************************************/
+
+void SwSectionFrm::Modify( const SfxPoolItem* pOld, const SfxPoolItem * pNew )
+{
+ sal_uInt8 nInvFlags = 0;
+
+ if( pNew && RES_ATTRSET_CHG == pNew->Which() )
+ {
+ SfxItemIter aNIter( *((SwAttrSetChg*)pNew)->GetChgSet() );
+ SfxItemIter aOIter( *((SwAttrSetChg*)pOld)->GetChgSet() );
+ SwAttrSetChg aOldSet( *(SwAttrSetChg*)pOld );
+ SwAttrSetChg aNewSet( *(SwAttrSetChg*)pNew );
+ while( sal_True )
+ {
+ _UpdateAttr( (SfxPoolItem*)aOIter.GetCurItem(),
+ (SfxPoolItem*)aNIter.GetCurItem(), nInvFlags,
+ &aOldSet, &aNewSet );
+ if( aNIter.IsAtEnd() )
+ break;
+ aNIter.NextItem();
+ aOIter.NextItem();
+ }
+ if ( aOldSet.Count() || aNewSet.Count() )
+ SwLayoutFrm::Modify( &aOldSet, &aNewSet );
+ }
+ else
+ _UpdateAttr( pOld, pNew, nInvFlags );
+
+ if ( nInvFlags != 0 )
+ {
+ if ( nInvFlags & 0x01 )
+ InvalidateSize();
+ if ( nInvFlags & 0x10 )
+ SetCompletePaint();
+ }
+}
+
+void SwSectionFrm::SwClientNotify( const SwModify& rMod, const SfxHint& rHint )
+{
+ const SfxSimpleHint* pSimpleHint = dynamic_cast<const SfxSimpleHint*>(&rHint);
+ if ( pSimpleHint && pSimpleHint->GetId() == SFX_HINT_DYING && &rMod == GetRegisteredIn() )
+ {
+ SwSectionFrm::MoveCntntAndDelete( this, sal_True );
+ }
+}
+
+void SwSectionFrm::_UpdateAttr( const SfxPoolItem *pOld, const SfxPoolItem *pNew,
+ sal_uInt8 &rInvFlags,
+ SwAttrSetChg *pOldSet, SwAttrSetChg *pNewSet )
+{
+ sal_Bool bClear = sal_True;
+ const sal_uInt16 nWhich = pOld ? pOld->Which() : pNew ? pNew->Which() : 0;
+ switch( nWhich )
+ { // Mehrspaltigkeit in Fussnoten unterdruecken...
+ case RES_FMT_CHG:
+ {
+ const SwFmtCol& rNewCol = GetFmt()->GetCol();
+ if( !IsInFtn() )
+ {
+ //Dummer Fall. Bei der Zuweisung einer Vorlage k?nnen wir uns
+ //nicht auf das alte Spaltenattribut verlassen. Da diese
+ //wenigstens anzahlgemass fuer ChgColumns vorliegen muessen,
+ //bleibt uns nur einen temporaeres Attribut zu basteln.
+ SwFmtCol aCol;
+ if ( Lower() && Lower()->IsColumnFrm() )
+ {
+ sal_uInt16 nCol = 0;
+ SwFrm *pTmp = Lower();
+ do
+ { ++nCol;
+ pTmp = pTmp->GetNext();
+ } while ( pTmp );
+ aCol.Init( nCol, 0, 1000 );
+ }
+ sal_Bool bChgFtn = IsFtnAtEnd();
+ sal_Bool bChgEndn = IsEndnAtEnd();
+ sal_Bool bChgMyEndn = IsEndnoteAtMyEnd();
+ CalcFtnAtEndFlag();
+ CalcEndAtEndFlag();
+ bChgFtn = ( bChgFtn != IsFtnAtEnd() ) ||
+ ( bChgEndn != IsEndnAtEnd() ) ||
+ ( bChgMyEndn != IsEndnoteAtMyEnd() );
+ ChgColumns( aCol, rNewCol, bChgFtn );
+ rInvFlags |= 0x10;
+ }
+ rInvFlags |= 0x01;
+ bClear = sal_False;
+ }
+ break;
+
+ case RES_COL:
+ if( !IsInFtn() )
+ {
+ ChgColumns( *(const SwFmtCol*)pOld, *(const SwFmtCol*)pNew );
+ rInvFlags |= 0x11;
+ }
+ break;
+
+ case RES_FTN_AT_TXTEND:
+ if( !IsInFtn() )
+ {
+ sal_Bool bOld = IsFtnAtEnd();
+ CalcFtnAtEndFlag();
+ if( bOld != IsFtnAtEnd() )
+ {
+ const SwFmtCol& rNewCol = GetFmt()->GetCol();
+ ChgColumns( rNewCol, rNewCol, sal_True );
+ rInvFlags |= 0x01;
+ }
+ }
+ break;
+
+ case RES_END_AT_TXTEND:
+ if( !IsInFtn() )
+ {
+ sal_Bool bOld = IsEndnAtEnd();
+ sal_Bool bMyOld = IsEndnoteAtMyEnd();
+ CalcEndAtEndFlag();
+ if( bOld != IsEndnAtEnd() || bMyOld != IsEndnoteAtMyEnd())
+ {
+ const SwFmtCol& rNewCol = GetFmt()->GetCol();
+ ChgColumns( rNewCol, rNewCol, sal_True );
+ rInvFlags |= 0x01;
+ }
+ }
+ break;
+ case RES_COLUMNBALANCE:
+ rInvFlags |= 0x01;
+ break;
+
+ case RES_FRAMEDIR :
+ SetDerivedR2L( sal_False );
+ CheckDirChange();
+ break;
+
+ case RES_PROTECT:
+ {
+ ViewShell *pSh = getRootFrm()->GetCurrShell();
+ if( pSh && pSh->GetLayout()->IsAnyShellAccessible() )
+ pSh->Imp()->InvalidateAccessibleEditableState( sal_True, this );
+ }
+ break;
+
+ default:
+ bClear = sal_False;
+ }
+ if ( bClear )
+ {
+ if ( pOldSet || pNewSet )
+ {
+ if ( pOldSet )
+ pOldSet->ClearItem( nWhich );
+ if ( pNewSet )
+ pNewSet->ClearItem( nWhich );
+ }
+ else
+ SwLayoutFrm::Modify( pOld, pNew );
+ }
+}
+
+/*--------------------------------------------------
+ * SwSectionFrm::ToMaximize(..): A follow or a ftncontainer at the end of the
+ * page causes a maximal Size of the sectionframe.
+ * --------------------------------------------------*/
+
+sal_Bool SwSectionFrm::ToMaximize( sal_Bool bCheckFollow ) const
+{
+ if( HasFollow() )
+ {
+ if( !bCheckFollow ) // Don't check superfluous follows
+ return sal_True;
+ const SwSectionFrm* pFoll = GetFollow();
+ while( pFoll && pFoll->IsSuperfluous() )
+ pFoll = pFoll->GetFollow();
+ if( pFoll )
+ return sal_True;
+ }
+ if( IsFtnAtEnd() )
+ return sal_False;
+ const SwFtnContFrm* pCont = ContainsFtnCont();
+ if( !IsEndnAtEnd() )
+ return 0 != pCont;
+ sal_Bool bRet = sal_False;
+ while( pCont && !bRet )
+ {
+ if( pCont->FindFootNote() )
+ bRet = sal_True;
+ else
+ pCont = ContainsFtnCont( pCont );
+ }
+ return bRet;
+}
+
+/*--------------------------------------------------
+ * sal_Bool SwSectionFrm::ContainsFtnCont()
+ * checks every Column for FtnContFrms.
+ * --------------------------------------------------*/
+
+SwFtnContFrm* SwSectionFrm::ContainsFtnCont( const SwFtnContFrm* pCont ) const
+{
+ SwFtnContFrm* pRet = NULL;
+ const SwLayoutFrm* pLay;
+ if( pCont )
+ {
+ pLay = pCont->FindFtnBossFrm( 0 );
+ OSL_ENSURE( IsAnLower( pLay ), "ConatainsFtnCont: Wrong FtnContainer" );
+ pLay = (SwLayoutFrm*)pLay->GetNext();
+ }
+ else if( Lower() && Lower()->IsColumnFrm() )
+ pLay = (SwLayoutFrm*)Lower();
+ else
+ pLay = NULL;
+ while ( !pRet && pLay )
+ {
+ if( pLay->Lower() && pLay->Lower()->GetNext() )
+ {
+ OSL_ENSURE( pLay->Lower()->GetNext()->IsFtnContFrm(),
+ "ToMaximize: Unexspected Frame" );
+ pRet = (SwFtnContFrm*)pLay->Lower()->GetNext();
+ }
+ OSL_ENSURE( !pLay->GetNext() || pLay->GetNext()->IsLayoutFrm(),
+ "ToMaximize: ColFrm exspected" );
+ pLay = (SwLayoutFrm*)pLay->GetNext();
+ }
+ return pRet;
+}
+
+void SwSectionFrm::InvalidateFtnPos()
+{
+ SwFtnContFrm* pCont = ContainsFtnCont( NULL );
+ if( pCont )
+ {
+ SwFrm *pTmp = pCont->ContainsCntnt();
+ if( pTmp )
+ pTmp->_InvalidatePos();
+ }
+}
+
+/*--------------------------------------------------
+ * SwSectionFrm::Undersize() liefert den Betrag, um den der Bereich gern
+ * groesser waere, wenn in ihm Undersized TxtFrms liegen, ansonsten Null.
+ * Das Undersized-Flag wird ggf. korrigiert.
+ * --------------------------------------------------*/
+
+long SwSectionFrm::Undersize( sal_Bool bOverSize )
+{
+ bUndersized = sal_False;
+ SWRECTFN( this )
+ long nRet = InnerHeight() - (Prt().*fnRect->fnGetHeight)();
+ if( nRet > 0 )
+ bUndersized = sal_True;
+ else if( !bOverSize )
+ nRet = 0;
+ return nRet;
+}
+
+/// OD 01.04.2003 #108446# - determine next frame for footnote/endnote formatting
+/// before format of current one, because current one can move backward.
+/// After moving backward to a previous page method <FindNext()> will return
+/// the text frame presenting the first page footnote, if it exists. Thus, the
+/// rest of the footnote/endnote container would not be formatted.
+void SwSectionFrm::CalcFtnCntnt()
+{
+ SwFtnContFrm* pCont = ContainsFtnCont();
+ if( pCont )
+ {
+ SwFrm* pFrm = pCont->ContainsAny();
+ if( pFrm )
+ pCont->Calc();
+ while( pFrm && IsAnLower( pFrm ) )
+ {
+ SwFtnFrm* pFtn = pFrm->FindFtnFrm();
+ if( pFtn )
+ pFtn->Calc();
+ // OD 01.04.2003 #108446# - determine next frame before format current frame.
+ SwFrm* pNextFrm = 0;
+ {
+ if( pFrm->IsSctFrm() )
+ {
+ pNextFrm = static_cast<SwSectionFrm*>(pFrm)->ContainsAny();
+ }
+ if( !pNextFrm )
+ {
+ pNextFrm = pFrm->FindNext();
+ }
+ }
+ pFrm->Calc();
+ pFrm = pNextFrm;
+ }
+ }
+}
+
+/* --------------------------------------------------
+ * Wenn ein SectionFrm leerlaeuft, z.B. weil sein Inhalt die Seite/Spalte wechselt,
+ * so wird er nicht sofort zerstoert (es koennte noch jemand auf dem Stack einen Pointer
+ * auf ihn halten), sondern er traegt sich in eine Liste am RootFrm ein, die spaeter
+ * abgearbeitet wird (in LayAction::Action u.a.). Seine Groesse wird auf Null gesetzt und
+ * sein Zeiger auf seine Section ebenfalls. Solche zum Loeschen vorgesehene SectionFrms
+ * muessen vom Layout/beim Formatieren ignoriert werden.
+ *
+ * Mit InsertEmptySct nimmt der RootFrm einen SectionFrm in die Liste auf,
+ * mit RemoveFromList kann ein SectionFrm wieder aus der Liste entfernt werden (Dtor),
+ * mit DeleteEmptySct wird die Liste abgearbeitet und die SectionFrms zerstoert
+ * --------------------------------------------------*/
+
+void SwRootFrm::InsertEmptySct( SwSectionFrm* pDel )
+{
+ if( !pDestroy )
+ pDestroy = new SwDestroyList;
+ sal_uInt16 nPos;
+ if( !pDestroy->Seek_Entry( pDel, &nPos ) )
+ pDestroy->Insert( pDel );
+}
+
+void SwRootFrm::_DeleteEmptySct()
+{
+ OSL_ENSURE( pDestroy, "Keine Liste, keine Kekse" );
+ while( pDestroy->Count() )
+ {
+ SwSectionFrm* pSect = (*pDestroy)[0];
+ pDestroy->Remove( sal_uInt16(0) );
+ OSL_ENSURE( !pSect->IsColLocked() && !pSect->IsJoinLocked(),
+ "DeleteEmptySct: Locked SectionFrm" );
+ if( !pSect->Frm().HasArea() && !pSect->ContainsCntnt() )
+ {
+ SwLayoutFrm* pUp = pSect->GetUpper();
+ pSect->Remove();
+ delete pSect;
+ if( pUp && !pUp->Lower() )
+ {
+ if( pUp->IsPageBodyFrm() )
+ pUp->getRootFrm()->SetSuperfluous();
+ else if( pUp->IsFtnFrm() && !pUp->IsColLocked() &&
+ pUp->GetUpper() )
+ {
+ pUp->Cut();
+ delete pUp;
+ }
+ }
+ }
+ else {
+ OSL_ENSURE( pSect->GetSection(), "DeleteEmptySct: Halbtoter SectionFrm?!" );
+ }
+ }
+}
+
+void SwRootFrm::_RemoveFromList( SwSectionFrm* pSct )
+{
+ OSL_ENSURE( pDestroy, "Where's my list?" );
+ sal_uInt16 nPos;
+ if( pDestroy->Seek_Entry( pSct, &nPos ) )
+ pDestroy->Remove( nPos );
+}
+
+#if OSL_DEBUG_LEVEL > 1
+
+sal_Bool SwRootFrm::IsInDelList( SwSectionFrm* pSct ) const
+{
+ sal_uInt16 nPos;
+ return ( pDestroy && pDestroy->Seek_Entry( pSct, &nPos ) );
+}
+
+#endif
+
+bool SwSectionFrm::IsBalancedSection() const
+{
+ bool bRet = false;
+ if ( GetSection() && Lower() && Lower()->IsColumnFrm() && Lower()->GetNext() )
+ {
+ bRet = !GetSection()->GetFmt()->GetBalancedColumns().GetValue();
+ }
+ return bRet;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/layout/softpagebreak.cxx b/sw/source/core/layout/softpagebreak.cxx
new file mode 100644
index 000000000000..c27bd3753637
--- /dev/null
+++ b/sw/source/core/layout/softpagebreak.cxx
@@ -0,0 +1,157 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+#include "ndtxt.hxx"
+#include "txtfrm.hxx"
+#include "pagefrm.hxx"
+#include "swtable.hxx"
+#include "frmfmt.hxx"
+#include "rowfrm.hxx"
+#include "tabfrm.hxx"
+#include "switerator.hxx"
+
+void SwTxtNode::fillSoftPageBreakList( SwSoftPageBreakList& rBreak ) const
+{
+ SwIterator<SwTxtFrm,SwTxtNode> aIter( *this );
+ for( const SwTxtFrm *pFrm = aIter.First(); pFrm; pFrm = aIter.Next() )
+ {
+ // No soft page break in header or footer
+ if( pFrm->FindFooterOrHeader() || pFrm->IsInFly() )
+ return;
+ // No soft page break if I'm not the first frame in my layout frame
+ if( pFrm->GetIndPrev() )
+ continue;
+ const SwPageFrm* pPage = pFrm->FindPageFrm();
+ // No soft page break at the first page
+ if( pPage && pPage->GetPrev() )
+ {
+ const SwCntntFrm* pFirst2 = pPage->FindFirstBodyCntnt();
+ // Special handling for content frame in table frames
+ if( pFrm->IsInTab() )
+ {
+ // No soft page break if I'm in a table but the first content frame
+ // at my page is not in a table
+ if( !pFirst2->IsInTab() )
+ continue;
+ const SwLayoutFrm *pRow = pFrm->GetUpper();
+ // Looking for the "most upper" row frame,
+ // skipping sub tables and/or table in table
+ while( !pRow->IsRowFrm() || !pRow->GetUpper()->IsTabFrm() ||
+ pRow->GetUpper()->GetUpper()->IsInTab() )
+ pRow = pRow->GetUpper();
+ const SwTabFrm *pTab = pRow->FindTabFrm();
+ // For master tables the soft page break will exported at the table row,
+ // not at the content frame.
+ // If the first content is outside my table frame, no soft page break.
+ if( !pTab->IsFollow() || !pTab->IsAnLower( pFirst2 ) )
+ continue;
+ // Only content of non-heading-rows can get a soft page break
+ const SwFrm* pFirstRow = pTab->GetFirstNonHeadlineRow();
+ // If there's no follow flow line, the soft page break will be
+ // exported at the row, not at the content.
+ if( pRow == pFirstRow &&
+ pTab->FindMaster( false )->HasFollowFlowLine() )
+ {
+ // Now we have the row which causes a new page,
+ // this row is a follow flow line and therefor cannot get
+ // the soft page break itself.
+ // Every first content frame of every cell frane in this row
+ // will get the soft page break
+ const SwFrm* pCell = pRow->Lower();
+ while( pCell )
+ {
+ pFirst2 = static_cast<const SwLayoutFrm*>(pCell)->ContainsCntnt();
+ if( pFirst2 == pFrm )
+ { // Here we are: a first content inside a cell
+ // inside the splitted row => soft page break
+ rBreak.insert( pFrm->GetOfst() );
+ break;
+ }
+ pCell = pCell->GetNext();
+ }
+ }
+ }
+ else // No soft page break if there's a "hard" page break attribute
+ if( pFirst2 == pFrm && !pFrm->IsPageBreak( sal_True ) )
+ rBreak.insert( pFrm->GetOfst() );
+ }
+ }
+}
+
+bool SwTableLine::hasSoftPageBreak() const
+{
+ // No soft page break for sub tables
+ if( GetUpper() || !GetFrmFmt() )
+ return false;
+ SwIterator<SwRowFrm,SwFmt> aIter( *GetFrmFmt() );
+ for( SwRowFrm* pLast = aIter.First(); pLast; pLast = aIter.Next() )
+ {
+ if( pLast->GetTabLine() == this )
+ {
+ const SwTabFrm* pTab = pLast->FindTabFrm();
+ // No soft page break for
+ // tables with prevs, i.e. if the frame is not the first in its layout frame
+ // tables in footer or header
+ // tables in flies
+ // inner tables of nested tables
+ // master table frames with "hard" page break attribute
+ if( pTab->GetIndPrev() || pTab->FindFooterOrHeader()
+ || pTab->IsInFly() || pTab->GetUpper()->IsInTab() ||
+ ( !pTab->IsFollow() && pTab->IsPageBreak( sal_True ) ) )
+ return false;
+ const SwPageFrm* pPage = pTab->FindPageFrm();
+ // No soft page break at the first page of the document
+ if( pPage && !pPage->GetPrev() )
+ return false;
+ const SwCntntFrm* pFirst = pPage->FindFirstBodyCntnt();
+ // No soft page break for
+ // tables which does not contain the first body content of the page
+ if( !pFirst || !pTab->IsAnLower( pFirst->FindTabFrm() ) )
+ return false;
+ // The row which could get a soft page break must be either the first
+ // row of a master table frame or the first "non-headline-row" of a
+ // follow table frame...
+ const SwFrm* pRow = pTab->IsFollow() ?
+ pTab->GetFirstNonHeadlineRow() : pTab->Lower();
+ if( pRow == pLast )
+ {
+ // The last check: no soft page break for "follow" table lines
+ if( pTab->IsFollow() && pTab->FindMaster( false )->HasFollowFlowLine() )
+ return false;
+ return true;
+ }
+ return false;
+ }
+ }
+ return false;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/layout/sortedobjs.cxx b/sw/source/core/layout/sortedobjs.cxx
new file mode 100644
index 000000000000..e984d278f4e7
--- /dev/null
+++ b/sw/source/core/layout/sortedobjs.cxx
@@ -0,0 +1,79 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+#include <sortedobjs.hxx>
+#include <sortedobjsimpl.hxx>
+
+SwSortedObjs::SwSortedObjs()
+ : mpImpl( new SwSortedObjsImpl )
+{
+}
+
+SwSortedObjs::~SwSortedObjs()
+{
+ delete mpImpl;
+}
+
+sal_uInt32 SwSortedObjs::Count() const
+{
+ return mpImpl->Count();
+}
+
+SwAnchoredObject* SwSortedObjs::operator[]( sal_uInt32 _nIndex ) const
+{
+ return (*mpImpl)[ _nIndex ];
+}
+
+bool SwSortedObjs::Insert( SwAnchoredObject& _rAnchoredObj )
+{
+ return mpImpl->Insert( _rAnchoredObj );
+}
+
+bool SwSortedObjs::Remove( SwAnchoredObject& _rAnchoredObj )
+{
+ return mpImpl->Remove( _rAnchoredObj );
+}
+
+bool SwSortedObjs::Contains( const SwAnchoredObject& _rAnchoredObj ) const
+{
+ return mpImpl->Contains( _rAnchoredObj );
+}
+
+bool SwSortedObjs::Update( SwAnchoredObject& _rAnchoredObj )
+{
+ return mpImpl->Update( _rAnchoredObj );
+}
+
+sal_uInt32 SwSortedObjs::ListPosOf( const SwAnchoredObject& _rAnchoredObj ) const
+{
+ return mpImpl->ListPosOf( _rAnchoredObj );
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/layout/sortedobjsimpl.cxx b/sw/source/core/layout/sortedobjsimpl.cxx
new file mode 100644
index 000000000000..dc81c71f0355
--- /dev/null
+++ b/sw/source/core/layout/sortedobjsimpl.cxx
@@ -0,0 +1,312 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+#include <sortedobjsimpl.hxx>
+
+#include <algorithm>
+#include <anchoredobject.hxx>
+#include <frmfmt.hxx>
+#include <svx/svdobj.hxx>
+#include <pam.hxx>
+#include <txtfrm.hxx>
+#include <ndtxt.hxx>
+#include <fmtsrnd.hxx>
+#include <fmtwrapinfluenceonobjpos.hxx>
+#include <IDocumentDrawModelAccess.hxx>
+
+
+using namespace ::com::sun::star;
+
+typedef std::vector< SwAnchoredObject* >::iterator tIter;
+typedef std::vector< SwAnchoredObject* >::const_iterator tConstIter;
+
+
+SwSortedObjsImpl::SwSortedObjsImpl()
+{
+}
+
+SwSortedObjsImpl::~SwSortedObjsImpl()
+{
+}
+
+sal_uInt32 SwSortedObjsImpl::Count() const
+{
+ return maSortedObjLst.size();
+}
+
+SwAnchoredObject* SwSortedObjsImpl::operator[]( sal_uInt32 _nIndex )
+{
+ SwAnchoredObject* pAnchoredObj = 0L;
+
+ if ( _nIndex >= Count() )
+ {
+ OSL_FAIL( "<SwSortedObjsImpl::operator[]> - index out of range" );
+ }
+ else
+ {
+ pAnchoredObj = maSortedObjLst[ _nIndex ];
+ }
+
+ return pAnchoredObj;
+}
+
+struct ObjAnchorOrder
+{
+ bool operator()( const SwAnchoredObject* _pListedAnchoredObj,
+ const SwAnchoredObject* _pNewAnchoredObj )
+ {
+ // get attributes of listed object
+ const SwFrmFmt& rFmtListed = _pListedAnchoredObj->GetFrmFmt();
+ const SwFmtAnchor* pAnchorListed = &(rFmtListed.GetAnchor());
+
+ // get attributes of new object
+ const SwFrmFmt& rFmtNew = _pNewAnchoredObj->GetFrmFmt();
+ const SwFmtAnchor* pAnchorNew = &(rFmtNew.GetAnchor());
+
+ // check for to-page anchored objects
+ if ((pAnchorListed->GetAnchorId() == FLY_AT_PAGE) &&
+ (pAnchorNew ->GetAnchorId() != FLY_AT_PAGE))
+ {
+ return true;
+ }
+ else if ((pAnchorListed->GetAnchorId() != FLY_AT_PAGE) &&
+ (pAnchorNew ->GetAnchorId() == FLY_AT_PAGE))
+ {
+ return false;
+ }
+ else if ((pAnchorListed->GetAnchorId() == FLY_AT_PAGE) &&
+ (pAnchorNew ->GetAnchorId() == FLY_AT_PAGE))
+ {
+ return pAnchorListed->GetOrder() < pAnchorNew->GetOrder();
+ }
+
+ // Both objects aren't anchored to page.
+ // Thus, check for to-fly anchored objects
+ if ((pAnchorListed->GetAnchorId() == FLY_AT_FLY) &&
+ (pAnchorNew ->GetAnchorId() != FLY_AT_FLY))
+ {
+ return true;
+ }
+ else if ((pAnchorListed->GetAnchorId() != FLY_AT_FLY) &&
+ (pAnchorNew ->GetAnchorId() == FLY_AT_FLY))
+ {
+ return false;
+ }
+ else if ((pAnchorListed->GetAnchorId() == FLY_AT_FLY) &&
+ (pAnchorNew ->GetAnchorId() == FLY_AT_FLY))
+ {
+ return pAnchorListed->GetOrder() < pAnchorNew->GetOrder();
+ }
+
+ // Both objects aren't anchor to page or to fly
+ // Thus, compare content anchor nodes, if existing.
+ const SwPosition* pCntntAnchorListed = pAnchorListed->GetCntntAnchor();
+ const SwPosition* pCntntAnchorNew = pAnchorNew->GetCntntAnchor();
+ if ( pCntntAnchorListed && pCntntAnchorNew &&
+ pCntntAnchorListed->nNode != pCntntAnchorNew->nNode )
+ {
+ return pCntntAnchorListed->nNode < pCntntAnchorNew->nNode;
+ }
+
+ // objects anchored at the same content.
+ // --> OD 2006-11-29 #???# - objects have to be ordered by anchor node position
+ // Thus, compare content anchor node positions and anchor type,
+ // if not anchored at-paragraph
+ if ((pAnchorListed->GetAnchorId() != FLY_AT_PARA) &&
+ (pAnchorNew ->GetAnchorId() != FLY_AT_PARA) &&
+ pCntntAnchorListed && pCntntAnchorNew )
+ {
+ if ( pCntntAnchorListed->nContent != pCntntAnchorNew->nContent )
+ {
+ return pCntntAnchorListed->nContent < pCntntAnchorNew->nContent;
+ }
+ else if ((pAnchorListed->GetAnchorId() == FLY_AT_CHAR) &&
+ (pAnchorNew ->GetAnchorId() == FLY_AS_CHAR))
+ {
+ return true;
+ }
+ else if ((pAnchorListed->GetAnchorId() == FLY_AS_CHAR) &&
+ (pAnchorNew ->GetAnchorId() == FLY_AT_CHAR))
+ {
+ return false;
+ }
+ }
+ // <--
+
+ // objects anchored at the same content and at the same content anchor
+ // node position with the same anchor type
+ // Thus, compare its wrapping style including its layer
+ const IDocumentDrawModelAccess* pIDDMA = rFmtListed.getIDocumentDrawModelAccess();
+ const SdrLayerID nHellId = pIDDMA->GetHellId();
+ const SdrLayerID nInvisibleHellId = pIDDMA->GetInvisibleHellId();
+ const bool bWrapThroughOrHellListed =
+ rFmtListed.GetSurround().GetSurround() == SURROUND_THROUGHT ||
+ _pListedAnchoredObj->GetDrawObj()->GetLayer() == nHellId ||
+ _pListedAnchoredObj->GetDrawObj()->GetLayer() == nInvisibleHellId;
+ const bool bWrapThroughOrHellNew =
+ rFmtNew.GetSurround().GetSurround() == SURROUND_THROUGHT ||
+ _pNewAnchoredObj->GetDrawObj()->GetLayer() == nHellId ||
+ _pNewAnchoredObj->GetDrawObj()->GetLayer() == nInvisibleHellId;
+ if ( bWrapThroughOrHellListed != bWrapThroughOrHellNew )
+ {
+ if ( bWrapThroughOrHellListed )
+ return false;
+ else
+ return true;
+ }
+ else if ( bWrapThroughOrHellListed && bWrapThroughOrHellNew )
+ {
+ return pAnchorListed->GetOrder() < pAnchorNew->GetOrder();
+ }
+
+ // objects anchored at the same content with a set text wrapping
+ // Thus, compare wrap influences on object position
+ const SwFmtWrapInfluenceOnObjPos* pWrapInfluenceOnObjPosListed =
+ &(rFmtListed.GetWrapInfluenceOnObjPos());
+ const SwFmtWrapInfluenceOnObjPos* pWrapInfluenceOnObjPosNew =
+ &(rFmtNew.GetWrapInfluenceOnObjPos());
+ // --> OD 2004-10-18 #i35017# - handle ITERATIVE as ONCE_SUCCESSIVE
+ if ( pWrapInfluenceOnObjPosListed->GetWrapInfluenceOnObjPos( true ) !=
+ pWrapInfluenceOnObjPosNew->GetWrapInfluenceOnObjPos( true ) )
+ // <--
+ {
+ // --> OD 2004-10-18 #i35017# - constant name has changed
+ if ( pWrapInfluenceOnObjPosListed->GetWrapInfluenceOnObjPos( true )
+ == text::WrapInfluenceOnPosition::ONCE_SUCCESSIVE )
+ // <--
+ return true;
+ else
+ return false;
+ }
+
+ // objects anchored at the same content position/page/fly with same
+ // wrap influence.
+ // Thus, compare anchor order number
+ return pAnchorListed->GetOrder() < pAnchorNew->GetOrder();
+ }
+};
+
+bool SwSortedObjsImpl::Insert( SwAnchoredObject& _rAnchoredObj )
+{
+ // --> OD 2005-08-18 #i51941#
+ if ( Contains( _rAnchoredObj ) )
+ {
+ // list already contains object
+#if OSL_DEBUG_LEVEL > 1
+ OSL_FAIL( "<SwSortedObjsImpl::Insert()> - already contains object" );
+#endif
+ return true;
+ }
+
+ // find insert position
+ tIter aInsPosIter = std::lower_bound( maSortedObjLst.begin(),
+ maSortedObjLst.end(),
+ &_rAnchoredObj, ObjAnchorOrder() );
+
+ // insert object into list
+ maSortedObjLst.insert( aInsPosIter, &_rAnchoredObj );
+
+ return Contains( _rAnchoredObj );
+}
+
+bool SwSortedObjsImpl::Remove( SwAnchoredObject& _rAnchoredObj )
+{
+ bool bRet = true;
+
+ tIter aDelPosIter = std::find( maSortedObjLst.begin(),
+ maSortedObjLst.end(),
+ &_rAnchoredObj );
+
+ if ( aDelPosIter == maSortedObjLst.end() )
+ {
+ // object not found.
+ bRet = false;
+#if OSL_DEBUG_LEVEL > 1
+ OSL_FAIL( "<SwSortedObjsImpl::Remove()> - object not found" );
+#endif
+ }
+ else
+ {
+ maSortedObjLst.erase( aDelPosIter );
+ }
+
+ return bRet;
+}
+
+bool SwSortedObjsImpl::Contains( const SwAnchoredObject& _rAnchoredObj ) const
+{
+ tConstIter aIter = std::find( maSortedObjLst.begin(), maSortedObjLst.end(),
+ &_rAnchoredObj );
+
+ return aIter != maSortedObjLst.end();
+}
+
+bool SwSortedObjsImpl::Update( SwAnchoredObject& _rAnchoredObj )
+{
+ if ( !Contains( _rAnchoredObj ) )
+ {
+ // given anchored object not found in list
+ OSL_FAIL( "<SwSortedObjsImpl::Update(..) - sorted list doesn't contain given anchored object" );
+ return false;
+ }
+
+ if ( Count() == 1 )
+ {
+ // given anchored object is the only one in the list.
+ return true;
+ }
+
+ Remove( _rAnchoredObj );
+ Insert( _rAnchoredObj );
+
+ return Contains( _rAnchoredObj );
+}
+
+sal_uInt32 SwSortedObjsImpl::ListPosOf( const SwAnchoredObject& _rAnchoredObj ) const
+{
+ sal_uInt32 nRetLstPos = Count();
+
+ tConstIter aIter = std::find( maSortedObjLst.begin(), maSortedObjLst.end(),
+ &_rAnchoredObj );
+
+ if ( aIter != maSortedObjLst.end() )
+ {
+ // --> OD 2005-08-18 #i51941#
+// nRetLstPos = aIter - maSortedObjLst.begin();
+ std::vector< SwAnchoredObject* >::difference_type nPos =
+ aIter - maSortedObjLst.begin();
+ nRetLstPos = sal_uInt32( nPos );
+ // <--
+ }
+
+ return nRetLstPos;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/layout/ssfrm.cxx b/sw/source/core/layout/ssfrm.cxx
new file mode 100644
index 000000000000..1bfaa40c7ae8
--- /dev/null
+++ b/sw/source/core/layout/ssfrm.cxx
@@ -0,0 +1,814 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+#include <ftnfrm.hxx>
+#include <pagefrm.hxx>
+#include <rootfrm.hxx>
+#include <cntfrm.hxx>
+#include <doc.hxx>
+#include <node.hxx>
+#include <dview.hxx>
+#include <dcontact.hxx>
+#include <dflyobj.hxx>
+#include <flyfrm.hxx>
+#include <txtfrm.hxx> // ClearPara()
+#include <cellfrm.hxx>
+#include <swtable.hxx>
+#include <fmtfsize.hxx>
+#include <ftnidx.hxx>
+#include <txtftn.hxx>
+#include <ndtxt.hxx>
+#include <ndindex.hxx>
+#include <frmtool.hxx>
+#include <pagedesc.hxx>
+#include <editeng/boxitem.hxx>
+#include <editeng/shaditem.hxx>
+#include <fmtclds.hxx>
+#include <viewsh.hxx>
+#include <viewimp.hxx>
+#include <sortedobjs.hxx>
+#include <hints.hxx>
+#include <switerator.hxx>
+
+ // No inline cause we need the function pointers
+long SwFrm::GetTopMargin() const
+ { return Prt().Top(); }
+long SwFrm::GetBottomMargin() const
+ { return Frm().Height() -Prt().Height() -Prt().Top(); }
+long SwFrm::GetLeftMargin() const
+ { return Prt().Left(); }
+long SwFrm::GetRightMargin() const
+ { return Frm().Width() - Prt().Width() - Prt().Left(); }
+long SwFrm::GetPrtLeft() const
+ { return Frm().Left() + Prt().Left(); }
+long SwFrm::GetPrtBottom() const
+ { return Frm().Top() + Prt().Height() + Prt().Top(); }
+long SwFrm::GetPrtRight() const
+ { return Frm().Left() + Prt().Width() + Prt().Left(); }
+long SwFrm::GetPrtTop() const
+ { return Frm().Top() + Prt().Top(); }
+
+sal_Bool SwFrm::SetMinLeft( long nDeadline )
+{
+ SwTwips nDiff = nDeadline - Frm().Left();
+ if( nDiff > 0 )
+ {
+ Frm().Left( nDeadline );
+ Prt().Width( Prt().Width() - nDiff );
+ return sal_True;
+ }
+ return sal_False;
+}
+
+sal_Bool SwFrm::SetMaxBottom( long nDeadline )
+{
+ SwTwips nDiff = Frm().Top() + Frm().Height() - nDeadline;
+ if( nDiff > 0 )
+ {
+ Frm().Height( Frm().Height() - nDiff );
+ Prt().Height( Prt().Height() - nDiff );
+ return sal_True;
+ }
+ return sal_False;
+}
+
+sal_Bool SwFrm::SetMinTop( long nDeadline )
+{
+ SwTwips nDiff = nDeadline - Frm().Top();
+ if( nDiff > 0 )
+ {
+ Frm().Top( nDeadline );
+ Prt().Height( Prt().Height() - nDiff );
+ return sal_True;
+ }
+ return sal_False;
+}
+
+sal_Bool SwFrm::SetMaxRight( long nDeadline )
+{
+ SwTwips nDiff = Frm().Left() + Frm().Width() - nDeadline;
+ if( nDiff > 0 )
+ {
+ Frm().Width( Frm().Width() - nDiff );
+ Prt().Width( Prt().Width() - nDiff );
+ return sal_True;
+ }
+ return sal_False;
+}
+
+void SwFrm::MakeBelowPos( const SwFrm* pUp, const SwFrm* pPrv, sal_Bool bNotify )
+{
+ if( pPrv )
+ {
+ aFrm.Pos( pPrv->Frm().Pos() );
+ aFrm.Pos().Y() += pPrv->Frm().Height();
+ }
+ else
+ {
+ aFrm.Pos( pUp->Frm().Pos() );
+ aFrm.Pos() += pUp->Prt().Pos();
+ }
+ if( bNotify )
+ aFrm.Pos().Y() += 1;
+}
+
+void SwFrm::MakeUpperPos( const SwFrm* pUp, const SwFrm* pPrv, sal_Bool bNotify )
+{
+ if( pPrv )
+ {
+ aFrm.Pos( pPrv->Frm().Pos() );
+ aFrm.Pos().Y() -= Frm().Height();
+ }
+ else
+ {
+ aFrm.Pos( pUp->Frm().Pos() );
+ aFrm.Pos() += pUp->Prt().Pos();
+ aFrm.Pos().Y() += pUp->Prt().Height() - aFrm.Height();
+ }
+ if( bNotify )
+ aFrm.Pos().Y() -= 1;
+}
+
+void SwFrm::MakeLeftPos( const SwFrm* pUp, const SwFrm* pPrv, sal_Bool bNotify )
+{
+ if( pPrv )
+ {
+ aFrm.Pos( pPrv->Frm().Pos() );
+ aFrm.Pos().X() -= Frm().Width();
+ }
+ else
+ {
+ aFrm.Pos( pUp->Frm().Pos() );
+ aFrm.Pos() += pUp->Prt().Pos();
+ aFrm.Pos().X() += pUp->Prt().Width() - aFrm.Width();
+ }
+ if( bNotify )
+ aFrm.Pos().X() -= 1;
+}
+
+void SwFrm::MakeRightPos( const SwFrm* pUp, const SwFrm* pPrv, sal_Bool bNotify )
+{
+ if( pPrv )
+ {
+ aFrm.Pos( pPrv->Frm().Pos() );
+ aFrm.Pos().X() += pPrv->Frm().Width();
+ }
+ else
+ {
+ aFrm.Pos( pUp->Frm().Pos() );
+ aFrm.Pos() += pUp->Prt().Pos();
+ }
+ if( bNotify )
+ aFrm.Pos().X() += 1;
+}
+
+void SwFrm::SetTopBottomMargins( long nTop, long nBot )
+{
+ Prt().Top( nTop );
+ Prt().Height( Frm().Height() - nTop - nBot );
+}
+
+void SwFrm::SetBottomTopMargins( long nBot, long nTop )
+{
+ Prt().Top( nTop );
+ Prt().Height( Frm().Height() - nTop - nBot );
+}
+
+void SwFrm::SetLeftRightMargins( long nLeft, long nRight)
+{
+ Prt().Left( nLeft );
+ Prt().Width( Frm().Width() - nLeft - nRight );
+}
+
+void SwFrm::SetRightLeftMargins( long nRight, long nLeft)
+{
+ Prt().Left( nLeft );
+ Prt().Width( Frm().Width() - nLeft - nRight );
+}
+
+const sal_uInt16 nMinVertCellHeight = 1135;
+
+/*--------------------------------------------------
+ * SwFrm::CheckDirChange(..)
+ * checks the layout direction and
+ * invalidates the lower frames rekursivly, if necessary.
+ * --------------------------------------------------*/
+
+void SwFrm::CheckDirChange()
+{
+ sal_Bool bOldVert = GetVerticalFlag();
+ sal_Bool bOldRev = IsReverse();
+ sal_Bool bOldR2L = GetRightToLeftFlag();
+ SetInvalidVert( sal_True );
+ SetInvalidR2L( sal_True );
+ sal_Bool bChg = bOldR2L != IsRightToLeft();
+ //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin
+ sal_Bool bOldVertL2R = IsVertLR();
+ if( ( IsVertical() != bOldVert ) || bChg || IsReverse() != bOldRev || bOldVertL2R != IsVertLR() )
+ {
+ InvalidateAll();
+ if( IsLayoutFrm() )
+ {
+ // set minimum row height for vertical cells in horizontal table:
+ if ( IsCellFrm() && GetUpper() )
+ {
+ if ( IsVertical() != GetUpper()->IsVertical() &&
+ ((SwCellFrm*)this)->GetTabBox()->getRowSpan() == 1 )
+ {
+ SwTableLine* pLine = (SwTableLine*)((SwCellFrm*)this)->GetTabBox()->GetUpper();
+ SwFrmFmt* pFrmFmt = pLine->GetFrmFmt();
+ SwFmtFrmSize aNew( pFrmFmt->GetFrmSize() );
+ if ( ATT_FIX_SIZE != aNew.GetHeightSizeType() )
+ aNew.SetHeightSizeType( ATT_MIN_SIZE );
+ if ( aNew.GetHeight() < nMinVertCellHeight )
+ aNew.SetHeight( nMinVertCellHeight );
+ SwDoc* pDoc = pFrmFmt->GetDoc();
+ pDoc->SetAttr( aNew, *pLine->ClaimFrmFmt() );
+ }
+ }
+
+ SwFrm* pFrm = ((SwLayoutFrm*)this)->Lower();
+ const SwFmtCol* pCol = NULL;
+ SwLayoutFrm* pBody = 0;
+ if( pFrm )
+ {
+ if( IsPageFrm() )
+ {
+ // If we're a page frame and we change our layout direction,
+ // we have to look for columns and rearrange them.
+ pBody = ((SwPageFrm*)this)->FindBodyCont();
+ if(pBody && pBody->Lower() && pBody->Lower()->IsColumnFrm())
+ pCol = &((SwPageFrm*)this)->GetFmt()->GetCol();
+ }
+ else if( pFrm->IsColumnFrm() )
+ {
+ pBody = ((SwLayoutFrm*)this);
+ const SwFrmFmt *pFmt = pBody->GetFmt();
+ if( pFmt )
+ pCol = &pFmt->GetCol();
+ }
+ }
+ while( pFrm )
+ {
+ pFrm->CheckDirChange();
+ pFrm = pFrm->GetNext();
+ }
+ if( pCol )
+ pBody->AdjustColumns( pCol, sal_True );
+ }
+ else if( IsTxtFrm() )
+ ((SwTxtFrm*)this)->Prepare( PREP_CLEAR );
+
+ // --> OD 2004-07-27 #i31698# - notify anchored objects also for page frames.
+ // Remove code above for special handling of page frames
+ if ( GetDrawObjs() )
+ {
+ const SwSortedObjs *pObjs = GetDrawObjs();
+ sal_uInt32 nCnt = pObjs->Count();
+ for ( sal_uInt32 i = 0; i < nCnt; ++i )
+ {
+ SwAnchoredObject* pAnchoredObj = (*pObjs)[i];
+ if( pAnchoredObj->ISA(SwFlyFrm) )
+ static_cast<SwFlyFrm*>(pAnchoredObj)->CheckDirChange();
+ else
+ {
+ // OD 2004-04-06 #i26791# - direct object
+ // positioning no longer needed. Instead
+ // invalidate
+ pAnchoredObj->InvalidateObjPos();
+ }
+ // --> OD 2004-07-27 #i31698# - update layout direction of
+ // anchored object
+ {
+ ::setContextWritingMode( pAnchoredObj->DrawObj(), pAnchoredObj->GetAnchorFrmContainingAnchPos() );
+ pAnchoredObj->UpdateLayoutDir();
+ }
+ // <--
+ }
+ }
+ }
+}
+
+/*--------------------------------------------------
+ * SwFrm::GetFrmAnchorPos(..)
+ * returns the position for anchors based on frame direction
+ * --------------------------------------------------*/
+// OD 2004-03-10 #i11860# - consider lower space and line spacing of
+// previous frame according to new option 'Use former object positioning'
+Point SwFrm::GetFrmAnchorPos( sal_Bool bIgnoreFlysAnchoredAtThisFrame ) const
+{
+ Point aAnchor = Frm().Pos();
+ //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin
+ if ( ( IsVertical() && !IsVertLR() ) || IsRightToLeft() )
+ aAnchor.X() += Frm().Width();
+
+ if ( IsTxtFrm() )
+ {
+ SwTwips nBaseOfstForFly =
+ ((SwTxtFrm*)this)->GetBaseOfstForFly( bIgnoreFlysAnchoredAtThisFrame );
+ if ( IsVertical() )
+ aAnchor.Y() += nBaseOfstForFly;
+ else
+ aAnchor.X() += nBaseOfstForFly;
+
+ // OD 2004-03-10 #i11860# - if option 'Use former object positioning'
+ // is OFF, consider the lower space and the line spacing of the
+ // previous frame and the spacing considered for the page grid
+ const SwTxtFrm* pThisTxtFrm = static_cast<const SwTxtFrm*>(this);
+ const SwTwips nUpperSpaceAmountConsideredForPrevFrmAndPageGrid =
+ pThisTxtFrm->GetUpperSpaceAmountConsideredForPrevFrmAndPageGrid();
+ if ( IsVertical() )
+ {
+ aAnchor.X() -= nUpperSpaceAmountConsideredForPrevFrmAndPageGrid;
+ }
+ else
+ {
+ aAnchor.Y() += nUpperSpaceAmountConsideredForPrevFrmAndPageGrid;
+ }
+ }
+
+ return aAnchor;
+}
+
+
+/*************************************************************************
+|*
+|* SwFrm::~SwFrm()
+|*
+|*************************************************************************/
+
+SwFrm::~SwFrm()
+{
+ // accessible objects for fly and cell frames have been already disposed
+ // by the destructors of the derived classes.
+ if( IsAccessibleFrm() && !(IsFlyFrm() || IsCellFrm()) && GetDep() )
+ {
+ SwRootFrm *pRootFrm = getRootFrm();
+ if( pRootFrm && pRootFrm->IsAnyShellAccessible() )
+ {
+ ViewShell *pVSh = pRootFrm->GetCurrShell();
+ if( pVSh && pVSh->Imp() )
+ {
+ OSL_ENSURE( !GetLower(), "Lowers should be dispose already!" );
+ pVSh->Imp()->DisposeAccessibleFrm( this );
+ }
+ }
+ }
+
+ if( pDrawObjs )
+ {
+ for ( sal_uInt32 i = pDrawObjs->Count(); i; )
+ {
+ SwAnchoredObject* pAnchoredObj = (*pDrawObjs)[--i];
+ if ( pAnchoredObj->ISA(SwFlyFrm) )
+ delete pAnchoredObj;
+ else
+ {
+ SdrObject* pSdrObj = pAnchoredObj->DrawObj();
+ SwDrawContact* pContact =
+ static_cast<SwDrawContact*>(pSdrObj->GetUserCall());
+ OSL_ENSURE( pContact,
+ "<SwFrm::~SwFrm> - missing contact for drawing object" );
+ if ( pContact )
+ {
+ pContact->DisconnectObjFromLayout( pSdrObj );
+ }
+ }
+ }
+ if ( pDrawObjs )
+ delete pDrawObjs;
+ }
+
+#if OSL_DEBUG_LEVEL > 1
+ // JP 15.10.2001: for detection of access to deleted frames
+ pDrawObjs = (SwSortedObjs*)0x33333333;
+#endif
+}
+
+/*************************************************************************/
+
+const SwFrmFmt * SwLayoutFrm::GetFmt() const
+{
+ return static_cast< const SwFlyFrmFmt * >( GetDep() );
+}
+
+SwFrmFmt * SwLayoutFrm::GetFmt()
+{
+ return static_cast< SwFlyFrmFmt * >( GetDep() );
+}
+
+
+/*************************************************************************
+|*
+|* SwLayoutFrm::SetFrmFmt()
+|*
+|*************************************************************************/
+
+
+void SwLayoutFrm::SetFrmFmt( SwFrmFmt *pNew )
+{
+ if ( pNew != GetFmt() )
+ {
+ SwFmtChg aOldFmt( GetFmt() );
+ pNew->Add( this );
+ SwFmtChg aNewFmt( pNew );
+ ModifyNotification( &aOldFmt, &aNewFmt );
+ }
+}
+
+/*************************************************************************
+|* SwCntntFrm::SwCntntFrm()
+|*************************************************************************/
+SwCntntFrm::SwCntntFrm( SwCntntNode * const pCntnt, SwFrm* pSib ) :
+ SwFrm( pCntnt, pSib ),
+ SwFlowFrm( (SwFrm&)*this )
+{
+}
+
+/*************************************************************************
+|* SwCntntFrm::~SwCntntFrm()
+|*************************************************************************/
+SwCntntFrm::~SwCntntFrm()
+{
+ SwCntntNode* pCNd;
+ if( 0 != ( pCNd = PTR_CAST( SwCntntNode, GetRegisteredIn() )) &&
+ !pCNd->GetDoc()->IsInDtor() )
+ {
+ //Bei der Root abmelden wenn ich dort noch im Turbo stehe.
+ SwRootFrm *pRoot = getRootFrm();
+ if( pRoot && pRoot->GetTurbo() == this )
+ {
+ pRoot->DisallowTurbo();
+ pRoot->ResetTurbo();
+ }
+ if( IsTxtFrm() && ((SwTxtFrm*)this)->HasFtn() )
+ {
+ SwTxtNode *pTxtNd = ((SwTxtFrm*)this)->GetTxtNode();
+ const SwFtnIdxs &rFtnIdxs = pCNd->GetDoc()->GetFtnIdxs();
+ sal_uInt16 nPos;
+ sal_uLong nIndex = pCNd->GetIndex();
+ rFtnIdxs.SeekEntry( *pTxtNd, &nPos );
+ SwTxtFtn* pTxtFtn;
+ if( nPos < rFtnIdxs.Count() )
+ {
+ while( nPos && pTxtNd == &(rFtnIdxs[ nPos ]->GetTxtNode()) )
+ --nPos;
+ if( nPos || pTxtNd != &(rFtnIdxs[ nPos ]->GetTxtNode()) )
+ ++nPos;
+ }
+ while( nPos < rFtnIdxs.Count() )
+ {
+ pTxtFtn = rFtnIdxs[ nPos ];
+ if( pTxtFtn->GetTxtNode().GetIndex() > nIndex )
+ break;
+ pTxtFtn->DelFrms( this );
+ ++nPos;
+ }
+ }
+ }
+}
+
+void SwCntntFrm::RegisterToNode( SwCntntNode& rNode )
+{
+ rNode.Add( this );
+}
+
+void SwCntntFrm::DelFrms( const SwCntntNode& rNode )
+{
+ SwIterator<SwCntntFrm,SwCntntNode> aIter( rNode );
+ for( SwCntntFrm* pFrm = aIter.First(); pFrm; pFrm = aIter.Next() )
+ {
+ // --> OD 2005-12-01 #i27138#
+ // notify accessibility paragraphs objects about changed
+ // CONTENT_FLOWS_FROM/_TO relation.
+ // Relation CONTENT_FLOWS_FROM for current next paragraph will change
+ // and relation CONTENT_FLOWS_TO for current previous paragraph will change.
+ if ( pFrm->IsTxtFrm() )
+ {
+ ViewShell* pViewShell( pFrm->getRootFrm()->GetCurrShell() );
+ if ( pViewShell && pViewShell->GetLayout() &&
+ pViewShell->GetLayout()->IsAnyShellAccessible() )
+ {
+ pViewShell->InvalidateAccessibleParaFlowRelation(
+ dynamic_cast<SwTxtFrm*>(pFrm->FindNextCnt( true )),
+ dynamic_cast<SwTxtFrm*>(pFrm->FindPrevCnt( true )) );
+ }
+ }
+ // <--
+ if( pFrm->HasFollow() )
+ pFrm->GetFollow()->_SetIsFollow( pFrm->IsFollow() );
+ if( pFrm->IsFollow() )
+ {
+ SwCntntFrm* pMaster = (SwTxtFrm*)pFrm->FindMaster();
+ pMaster->SetFollow( pFrm->GetFollow() );
+ pFrm->_SetIsFollow( sal_False );
+ }
+ pFrm->SetFollow( 0 );//Damit er nicht auf dumme Gedanken kommt.
+ //Andernfalls kann es sein, dass ein Follow
+ //vor seinem Master zerstoert wird, der Master
+ //greift dann ueber den ungueltigen
+ //Follow-Pointer auf fremdes Memory zu.
+ //Die Kette darf hier zerknauscht werden, weil
+ //sowieso alle zerstoert werden.
+ if( pFrm->GetUpper() && pFrm->IsInFtn() && !pFrm->GetIndNext() &&
+ !pFrm->GetIndPrev() )
+ {
+ SwFtnFrm *pFtn = pFrm->FindFtnFrm();
+ OSL_ENSURE( pFtn, "You promised a FtnFrm?" );
+ SwCntntFrm* pCFrm;
+ if( !pFtn->GetFollow() && !pFtn->GetMaster() &&
+ 0 != ( pCFrm = pFtn->GetRefFromAttr()) && pCFrm->IsFollow() )
+ {
+ OSL_ENSURE( pCFrm->IsTxtFrm(), "NoTxtFrm has Footnote?" );
+ ((SwTxtFrm*)pCFrm->FindMaster())->Prepare( PREP_FTN_GONE );
+ }
+ }
+ pFrm->Cut();
+ delete pFrm;
+ }
+}
+
+/*************************************************************************
+|*
+|* SwLayoutFrm::~SwLayoutFrm
+|*
+|*************************************************************************/
+
+
+SwLayoutFrm::~SwLayoutFrm()
+{
+ SwFrm *pFrm = pLower;
+
+ if( GetFmt() && !GetFmt()->GetDoc()->IsInDtor() )
+ {
+ while ( pFrm )
+ {
+ //Erst die Objs des Frm vernichten, denn diese koennen sich sonst nach
+ //dem Remove nicht mehr bei der Seite abmelden.
+ //Falls sich einer nicht abmeldet wollen wir nicht gleich
+ //endlos schleifen.
+
+ sal_uInt32 nCnt;
+ while ( pFrm->GetDrawObjs() && pFrm->GetDrawObjs()->Count() )
+ {
+ nCnt = pFrm->GetDrawObjs()->Count();
+ // --> OD 2004-06-30 #i28701#
+ SwAnchoredObject* pAnchoredObj = (*pFrm->GetDrawObjs())[0];
+ if ( pAnchoredObj->ISA(SwFlyFrm) )
+ delete pAnchoredObj;
+ else
+ {
+ SdrObject* pSdrObj = pAnchoredObj->DrawObj();
+ SwDrawContact* pContact =
+ static_cast<SwDrawContact*>(pSdrObj->GetUserCall());
+ OSL_ENSURE( pContact,
+ "<SwFrm::~SwFrm> - missing contact for drawing object" );
+ if ( pContact )
+ {
+ pContact->DisconnectObjFromLayout( pSdrObj );
+ }
+ }
+ if ( pFrm->GetDrawObjs() &&
+ nCnt == pFrm->GetDrawObjs()->Count() )
+ {
+ pFrm->GetDrawObjs()->Remove( *pAnchoredObj );
+ }
+ // <--
+ }
+ pFrm->Remove();
+ delete pFrm;
+ pFrm = pLower;
+ }
+ //Fly's vernichten. Der letzte loescht gleich das Array.
+ sal_uInt32 nCnt;
+ while ( GetDrawObjs() && GetDrawObjs()->Count() )
+ {
+ nCnt = GetDrawObjs()->Count();
+
+ // --> OD 2004-06-30 #i28701#
+ SwAnchoredObject* pAnchoredObj = (*GetDrawObjs())[0];
+ if ( pAnchoredObj->ISA(SwFlyFrm) )
+ delete pAnchoredObj;
+ else
+ {
+ SdrObject* pSdrObj = pAnchoredObj->DrawObj();
+ SwDrawContact* pContact =
+ static_cast<SwDrawContact*>(pSdrObj->GetUserCall());
+ OSL_ENSURE( pContact,
+ "<SwFrm::~SwFrm> - missing contact for drawing object" );
+ if ( pContact )
+ {
+ pContact->DisconnectObjFromLayout( pSdrObj );
+ }
+ }
+ if ( GetDrawObjs() && nCnt == GetDrawObjs()->Count() )
+ {
+ GetDrawObjs()->Remove( *pAnchoredObj );
+ }
+ // <--
+ }
+ }
+ else
+ {
+ while( pFrm )
+ {
+ SwFrm *pNxt = pFrm->GetNext();
+ delete pFrm;
+ pFrm = pNxt;
+ }
+ }
+}
+
+/*************************************************************************
+|*
+|* SwFrm::PaintArea()
+|*
+|* The paintarea is the area, in which the content of a frame is allowed
+|* to be displayed. This region could be larger than the printarea (Prt())
+|* of the upper, it includes e.g. often the margin of the page.
+|*
+|*************************************************************************/
+
+const SwRect SwFrm::PaintArea() const
+{
+ // NEW TABLES
+ // Cell frames may not leave their upper:
+ SwRect aRect = IsRowFrm() ? GetUpper()->Frm() : Frm();
+ const sal_Bool bVert = IsVertical();
+ //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin
+ SwRectFn fnRect = bVert ? ( IsVertLR() ? fnRectVertL2R : fnRectVert ) : fnRectHori;
+ long nRight = (aRect.*fnRect->fnGetRight)();
+ long nLeft = (aRect.*fnRect->fnGetLeft)();
+ const SwFrm* pTmp = this;
+ sal_Bool bLeft = sal_True;
+ sal_Bool bRight = sal_True;
+ long nRowSpan = 0;
+ while( pTmp )
+ {
+ if( pTmp->IsCellFrm() && pTmp->GetUpper() &&
+ pTmp->GetUpper()->IsVertical() != pTmp->IsVertical() )
+ nRowSpan = ((SwCellFrm*)pTmp)->GetTabBox()->getRowSpan();
+ long nTmpRight = (pTmp->Frm().*fnRect->fnGetRight)();
+ long nTmpLeft = (pTmp->Frm().*fnRect->fnGetLeft)();
+ if( pTmp->IsRowFrm() && nRowSpan > 1 )
+ {
+ const SwFrm* pNxt = pTmp;
+ while( --nRowSpan > 0 && pNxt->GetNext() )
+ pNxt = pNxt->GetNext();
+ if( pTmp->IsVertical() )
+ nTmpLeft = (pNxt->Frm().*fnRect->fnGetLeft)();
+ else
+ nTmpRight = (pNxt->Frm().*fnRect->fnGetRight)();
+ }
+ OSL_ENSURE( pTmp, "PaintArea lost in time and space" );
+ if( pTmp->IsPageFrm() || pTmp->IsFlyFrm() ||
+ pTmp->IsCellFrm() || pTmp->IsRowFrm() || //nobody leaves a table!
+ pTmp->IsRootFrm() )
+ {
+ if( bLeft || nLeft < nTmpLeft )
+ nLeft = nTmpLeft;
+ if( bRight || nTmpRight < nRight )
+ nRight = nTmpRight;
+ if( pTmp->IsPageFrm() || pTmp->IsFlyFrm() || pTmp->IsRootFrm() )
+ break;
+ bLeft = sal_False;
+ bRight = sal_False;
+ }
+ else if( pTmp->IsColumnFrm() ) // nobody enters neightbour columns
+ {
+ sal_Bool bR2L = pTmp->IsRightToLeft();
+ // the first column has _no_ influence to the left range
+ if( bR2L ? pTmp->GetNext() : pTmp->GetPrev() )
+ {
+ if( bLeft || nLeft < nTmpLeft )
+ nLeft = nTmpLeft;
+ bLeft = sal_False;
+ }
+ // the last column has _no_ influence to the right range
+ if( bR2L ? pTmp->GetPrev() : pTmp->GetNext() )
+ {
+ if( bRight || nTmpRight < nRight )
+ nRight = nTmpRight;
+ bRight = sal_False;
+ }
+ }
+ else if( bVert && pTmp->IsBodyFrm() )
+ {
+ // Header and footer frames have always horizontal direction and
+ // limit the body frame.
+ // A previous frame of a body frame must be a header,
+ // the next frame of a body frame may be a footnotecontainer or
+ // a footer. The footnotecontainer has the same direction like
+ // the body frame.
+ if( pTmp->GetPrev() && ( bLeft || nLeft < nTmpLeft ) )
+ {
+ nLeft = nTmpLeft;
+ bLeft = sal_False;
+ }
+ if( pTmp->GetNext() &&
+ ( pTmp->GetNext()->IsFooterFrm() || pTmp->GetNext()->GetNext() )
+ && ( bRight || nTmpRight < nRight ) )
+ {
+ nRight = nTmpRight;
+ bRight = sal_False;
+ }
+ }
+ pTmp = pTmp->GetUpper();
+ }
+ (aRect.*fnRect->fnSetLeft)( nLeft );
+ (aRect.*fnRect->fnSetRight)( nRight );
+ return aRect;
+}
+
+/*************************************************************************
+|*
+|* SwFrm::UnionFrm()
+|*
+|* The unionframe is the framearea (Frm()) of a frame expanded by the
+|* printarea, if there's a negative margin at the left or right side.
+|*
+|*************************************************************************/
+
+const SwRect SwFrm::UnionFrm( sal_Bool bBorder ) const
+{
+ sal_Bool bVert = IsVertical();
+ //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin
+ SwRectFn fnRect = bVert ? ( IsVertLR() ? fnRectVertL2R : fnRectVert ) : fnRectHori;
+ long nLeft = (Frm().*fnRect->fnGetLeft)();
+ long nWidth = (Frm().*fnRect->fnGetWidth)();
+ long nPrtLeft = (Prt().*fnRect->fnGetLeft)();
+ long nPrtWidth = (Prt().*fnRect->fnGetWidth)();
+ if( nPrtLeft + nPrtWidth > nWidth )
+ nWidth = nPrtLeft + nPrtWidth;
+ if( nPrtLeft < 0 )
+ {
+ nLeft += nPrtLeft;
+ nWidth -= nPrtLeft;
+ }
+ SwTwips nRight = nLeft + nWidth;
+ long nAdd = 0;
+ if( bBorder )
+ {
+ SwBorderAttrAccess aAccess( SwFrm::GetCache(), this );
+ const SwBorderAttrs &rAttrs = *aAccess.Get();
+ const SvxBoxItem &rBox = rAttrs.GetBox();
+ if ( rBox.GetLeft() )
+ nLeft -= rBox.CalcLineSpace( BOX_LINE_LEFT );
+ else if ( rAttrs.IsBorderDist() )
+ nLeft -= rBox.GetDistance( BOX_LINE_LEFT ) + 1;
+ if ( rBox.GetRight() )
+ nAdd += rBox.CalcLineSpace( BOX_LINE_RIGHT );
+ else if ( rAttrs.IsBorderDist() )
+ nAdd += rBox.GetDistance( BOX_LINE_RIGHT ) + 1;
+ if( rAttrs.GetShadow().GetLocation() != SVX_SHADOW_NONE )
+ {
+ const SvxShadowItem &rShadow = rAttrs.GetShadow();
+ nLeft -= rShadow.CalcShadowSpace( SHADOW_LEFT );
+ nAdd += rShadow.CalcShadowSpace( SHADOW_RIGHT );
+ }
+ }
+ if( IsTxtFrm() && ((SwTxtFrm*)this)->HasPara() )
+ {
+ long nTmp = ((SwTxtFrm*)this)->HangingMargin();
+ if( nTmp > nAdd )
+ nAdd = nTmp;
+ }
+ nWidth = nRight + nAdd - nLeft;
+ SwRect aRet( Frm() );
+ (aRet.*fnRect->fnSetPosX)( nLeft );
+ (aRet.*fnRect->fnSetWidth)( nWidth );
+ return aRet;
+}
+
+
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/layout/swselectionlist.cxx b/sw/source/core/layout/swselectionlist.cxx
new file mode 100644
index 000000000000..e2997db0a6bc
--- /dev/null
+++ b/sw/source/core/layout/swselectionlist.cxx
@@ -0,0 +1,96 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+#include <swselectionlist.hxx>
+#include <layfrm.hxx>
+#include <flyfrm.hxx>
+#include <ftnfrm.hxx>
+
+/** This class is used as parameter for functions to create a rectangular text selection
+*/
+
+namespace {
+
+ /** Find the context of a given frame
+
+ A context is the environment where text is allowed to flow.
+ The context is represented by
+ - the SwRootFrm if the frame is part of a page body
+ - the SwHeaderFrm if the frame is part of a page header
+ - the SwFooterFrm if the frame is part of a page footer
+ - the (master) SwFtnFrm if the frame is part of footnote
+ - the (first) SwFlyFrm if the frame is part of a (linked) fly frame
+
+ @param pFrm
+ the given frame
+
+ @return the context of the frame, represented by a SwFrm*
+ */
+ const SwFrm* getContext( const SwFrm* pFrm )
+ {
+ while( pFrm )
+ {
+ if( pFrm->IsRootFrm() || pFrm->IsHeaderFrm() || pFrm->IsFooterFrm() )
+ break;
+ if( pFrm->IsFlyFrm() )
+ {
+ const SwFlyFrm* pFly = static_cast<const SwFlyFrm*>( pFrm );
+ while( pFly->GetPrevLink() )
+ pFly = pFly->GetPrevLink();
+ break;
+ }
+ if( pFrm->IsFtnFrm() )
+ {
+ const SwFtnFrm* pFtn = static_cast<const SwFtnFrm*>( pFrm );
+ while( pFtn->GetMaster() )
+ pFtn = pFtn->GetMaster();
+ break;
+ }
+ pFrm = pFrm->GetUpper();
+ }
+ return pFrm;
+ }
+}
+
+SwSelectionList::SwSelectionList( const SwFrm* pInitCxt ) :
+ pContext( getContext( pInitCxt ) )
+{
+}
+
+bool SwSelectionList::checkContext( const SwFrm* pCheck )
+{
+ pCheck = getContext( pCheck );
+ if( !pContext )
+ pContext = pCheck;
+ return pContext == pCheck;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/layout/tabfrm.cxx b/sw/source/core/layout/tabfrm.cxx
new file mode 100644
index 000000000000..08f756d65b87
--- /dev/null
+++ b/sw/source/core/layout/tabfrm.cxx
@@ -0,0 +1,5798 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+#include "pagefrm.hxx"
+#include "rootfrm.hxx"
+#include "cntfrm.hxx"
+#include "viewsh.hxx"
+#include "doc.hxx"
+#include "docsh.hxx"
+#include "viewimp.hxx"
+#include "swtable.hxx"
+#include "dflyobj.hxx"
+#include "flyfrm.hxx"
+#include "frmtool.hxx"
+#include "frmfmt.hxx"
+#include "dcontact.hxx"
+#include <anchoreddrawobject.hxx>
+#include <fmtanchr.hxx>
+#include "viewopt.hxx"
+#include "hints.hxx"
+#include "dbg_lay.hxx"
+#include <ftnidx.hxx>
+#include <svl/itemiter.hxx>
+#include <docary.hxx>
+#include <editeng/keepitem.hxx>
+#include <editeng/ulspitem.hxx>
+#include <editeng/lrspitem.hxx>
+#include <editeng/brshitem.hxx>
+#include <editeng/boxitem.hxx>
+#include <vcl/outdev.hxx>
+#include <fmtlsplt.hxx>
+#include <fmtrowsplt.hxx>
+#include <fmtsrnd.hxx>
+#include <fmtornt.hxx>
+#include <fmtpdsc.hxx>
+#include <fmtfsize.hxx>
+#include <swtblfmt.hxx>
+#include <ndtxt.hxx>
+#include "tabfrm.hxx"
+#include "rowfrm.hxx"
+#include "cellfrm.hxx"
+#include "flyfrms.hxx"
+#include "txtfrm.hxx" //HasFtn()
+#include "htmltbl.hxx"
+#include "sectfrm.hxx" //SwSectionFrm
+#include <fmtfollowtextflow.hxx>
+#include <sortedobjs.hxx>
+#include <objectformatter.hxx>
+#include <layouter.hxx>
+#include <switerator.hxx>
+
+extern void AppendObjs( const SwSpzFrmFmts *pTbl, sal_uLong nIndex,
+ SwFrm *pFrm, SwPageFrm *pPage );
+
+using namespace ::com::sun::star;
+
+
+/*************************************************************************
+|*
+|* SwTabFrm::SwTabFrm(), ~SwTabFrm()
+|*
+|*************************************************************************/
+SwTabFrm::SwTabFrm( SwTable &rTab, SwFrm* pSib ):
+ SwLayoutFrm( rTab.GetFrmFmt(), pSib ),
+ SwFlowFrm( (SwFrm&)*this ),
+ pTable( &rTab )
+{
+ bComplete = bCalcLowers = bONECalcLowers = bLowersFormatted = bLockBackMove =
+ bResizeHTMLTable = bHasFollowFlowLine = bIsRebuildLastLine =
+ bRestrictTableGrowth = bRemoveFollowFlowLinePending = sal_False;
+ // --> OD 2004-10-04 #i26945#
+ bConsiderObjsForMinCellHeight = sal_True;
+ bObjsDoesFit = sal_True;
+ // <--
+ bFixSize = sal_False; //Nicht nochmal auf die Importfilter hereinfallen.
+ nType = FRMC_TAB;
+
+ //Gleich die Zeilen erzeugen und einfuegen.
+ const SwTableLines &rLines = rTab.GetTabLines();
+ SwFrm *pTmpPrev = 0;
+ for ( sal_uInt16 i = 0; i < rLines.Count(); ++i )
+ {
+ SwRowFrm *pNew = new SwRowFrm( *rLines[i], this );
+ if( pNew->Lower() )
+ {
+ pNew->InsertBehind( this, pTmpPrev );
+ pTmpPrev = pNew;
+ }
+ else
+ delete pNew;
+ }
+ OSL_ENSURE( Lower() && Lower()->IsRowFrm(), "SwTabFrm::SwTabFrm: No rows." );
+}
+
+SwTabFrm::SwTabFrm( SwTabFrm &rTab ) :
+ SwLayoutFrm( rTab.GetFmt(), &rTab ),
+ SwFlowFrm( (SwFrm&)*this ),
+ pTable( rTab.GetTable() )
+{
+ bIsFollow = sal_True;
+ bLockJoin = bComplete = bONECalcLowers = bCalcLowers = bLowersFormatted = bLockBackMove =
+ bResizeHTMLTable = bHasFollowFlowLine = bIsRebuildLastLine =
+ bRestrictTableGrowth = bRemoveFollowFlowLinePending = sal_False;
+ // --> OD 2004-10-04 #i26945#
+ bConsiderObjsForMinCellHeight = sal_True;
+ bObjsDoesFit = sal_True;
+ // <--
+ bFixSize = sal_False; //Nicht nochmal auf die Importfilter hereinfallen.
+ nType = FRMC_TAB;
+
+ SetFollow( rTab.GetFollow() );
+ rTab.SetFollow( this );
+}
+
+extern const SwTable *pColumnCacheLastTable;
+extern const SwTabFrm *pColumnCacheLastTabFrm;
+extern const SwFrm *pColumnCacheLastCellFrm;
+extern const SwTable *pRowCacheLastTable;
+extern const SwTabFrm *pRowCacheLastTabFrm;
+extern const SwFrm *pRowCacheLastCellFrm;
+
+SwTabFrm::~SwTabFrm()
+{
+ // There is some terrible code in fetab.cxx, that
+ // makes use of these global pointers. Obviously
+ // this code did not consider that a TabFrm can be
+ // deleted.
+ if ( this == pColumnCacheLastTabFrm )
+ {
+ pColumnCacheLastTable = NULL;
+ pColumnCacheLastTabFrm = NULL;
+ pColumnCacheLastCellFrm= NULL;
+ pRowCacheLastTable = NULL;
+ pRowCacheLastTabFrm = NULL;
+ pRowCacheLastCellFrm= NULL;
+ }
+}
+
+/*************************************************************************
+|*
+|* SwTabFrm::JoinAndDelFollows()
+|*
+|*************************************************************************/
+void SwTabFrm::JoinAndDelFollows()
+{
+ SwTabFrm *pFoll = GetFollow();
+ if ( pFoll->HasFollow() )
+ pFoll->JoinAndDelFollows();
+ pFoll->Cut();
+ SetFollow( pFoll->GetFollow() );
+ delete pFoll;
+}
+
+/*************************************************************************
+|*
+|* SwTabFrm::RegistFlys()
+|*
+|*************************************************************************/
+void SwTabFrm::RegistFlys()
+{
+ OSL_ENSURE( Lower() && Lower()->IsRowFrm(), "Keine Zeilen." );
+
+ SwPageFrm *pPage = FindPageFrm();
+ if ( pPage )
+ {
+ SwRowFrm *pRow = (SwRowFrm*)Lower();
+ do
+ {
+ pRow->RegistFlys( pPage );
+ pRow = (SwRowFrm*)pRow->GetNext();
+ } while ( pRow );
+ }
+}
+
+/*************************************************************************
+|* Some prototypes
+|*************************************************************************/
+void MA_FASTCALL SwInvalidateAll( SwFrm *pFrm, long nBottom );
+void MA_FASTCALL lcl_RecalcRow( SwRowFrm& rRow, long nBottom );
+sal_Bool lcl_ArrangeLowers( SwLayoutFrm *pLay, long lYStart, sal_Bool bInva );
+// --> OD 2004-10-15 #i26945# - add parameter <_bOnlyRowsAndCells> to control
+// that only row and cell frames are formatted.
+sal_Bool MA_FASTCALL lcl_InnerCalcLayout( SwFrm *pFrm,
+ long nBottom,
+ bool _bOnlyRowsAndCells = false );
+// <--
+// OD 2004-02-18 #106629# - correct type of 1st parameter
+// --> OD 2004-10-04 #i26945# - add parameter <_bConsiderObjs> in order to
+// control, if floating screen objects have to be considered for the minimal
+// cell height.
+SwTwips MA_FASTCALL lcl_CalcMinRowHeight( const SwRowFrm *pRow,
+ const sal_Bool _bConsiderObjs );
+// <--
+SwTwips lcl_CalcTopAndBottomMargin( const SwLayoutFrm&, const SwBorderAttrs& );
+
+/*************************************************************************
+|* START: local helper functions for repeated headlines
+|*************************************************************************/
+
+SwTwips lcl_GetHeightOfRows( const SwFrm* pStart, long nCount )
+{
+ if ( !nCount || !pStart)
+ return 0;
+
+ SwTwips nRet = 0;
+ SWRECTFN( pStart )
+ while ( pStart && nCount > 0 )
+ {
+ nRet += (pStart->Frm().*fnRect->fnGetHeight)();
+ pStart = pStart->GetNext();
+ --nCount;
+ }
+
+ return nRet;
+}
+
+/*************************************************************************
+|* END: local helper functions for repeated headlines
+|*************************************************************************/
+
+/*************************************************************************
+|* START: local helper functions for splitting row frames
+|*************************************************************************/
+
+//
+// Local helper function to insert a new follow flow line
+//
+SwRowFrm* lcl_InsertNewFollowFlowLine( SwTabFrm& rTab, const SwFrm& rTmpRow, bool bRowSpanLine )
+{
+ OSL_ENSURE( rTmpRow.IsRowFrm(), "No row frame to copy for FollowFlowLine" );
+ const SwRowFrm& rRow = (SwRowFrm&)rTmpRow;
+
+ rTab.SetFollowFlowLine( sal_True );
+ SwRowFrm *pFollowFlowLine = new SwRowFrm(*rRow.GetTabLine(), &rTab, false );
+ pFollowFlowLine->SetRowSpanLine( bRowSpanLine );
+ SwFrm* pFirstRow = rTab.GetFollow()->GetFirstNonHeadlineRow();
+ pFollowFlowLine->InsertBefore( rTab.GetFollow(), pFirstRow );
+ return pFollowFlowLine;
+}
+
+// --> OD 2004-11-05 #i26945# - local helper function to invalidate all lower
+// objects. By parameter <_bMoveObjsOutOfRange> it can be controlled, if
+// additionally the objects are moved 'out of range'.
+void lcl_InvalidateLowerObjs( SwLayoutFrm& _rLayoutFrm,
+ const bool _bMoveObjsOutOfRange = false,
+ SwPageFrm* _pPageFrm = 0L )
+{
+ // determine page frame, if needed
+ if ( !_pPageFrm )
+ {
+ _pPageFrm = _rLayoutFrm.FindPageFrm();
+ OSL_ENSURE( _pPageFrm,
+ "<lcl_InvalidateLowerObjs(..)> - missing page frame -> no move of lower objects out of range" );
+ if ( !_pPageFrm )
+ {
+ return;
+ }
+ }
+
+ // loop on lower frames
+ SwFrm* pLowerFrm = _rLayoutFrm.Lower();
+ while ( pLowerFrm )
+ {
+ if ( pLowerFrm->IsLayoutFrm() )
+ {
+ ::lcl_InvalidateLowerObjs( *(static_cast<SwLayoutFrm*>(pLowerFrm)),
+ _bMoveObjsOutOfRange, _pPageFrm );
+ }
+ if ( pLowerFrm->GetDrawObjs() )
+ {
+ for ( sal_uInt16 i = 0; i < pLowerFrm->GetDrawObjs()->Count(); ++i )
+ {
+ SwAnchoredObject* pAnchoredObj = (*pLowerFrm->GetDrawObjs())[i];
+
+ // invalidate position of anchored object
+ pAnchoredObj->SetTmpConsiderWrapInfluence( false );
+ pAnchoredObj->SetConsiderForTextWrap( false );
+ pAnchoredObj->UnlockPosition();
+ pAnchoredObj->InvalidateObjPos();
+
+ // move anchored object 'out of range'
+ if ( _bMoveObjsOutOfRange )
+ {
+ // indicate, that positioning is progress to avoid
+ // modification of the anchored object resp. its attributes
+ // due to the movement
+ SwObjPositioningInProgress aObjPosInProgress( *pAnchoredObj );
+ pAnchoredObj->SetObjLeft( _pPageFrm->Frm().Right() );
+ // --> OD 2004-11-24 #115759# - reset character rectangle,
+ // top of line and relative position in order to assure,
+ // that anchored object is correctly positioned.
+ pAnchoredObj->ClearCharRectAndTopOfLine();
+ pAnchoredObj->SetCurrRelPos( Point( 0, 0 ) );
+ if ( pAnchoredObj->GetFrmFmt().GetAnchor().GetAnchorId()
+ == FLY_AS_CHAR )
+ {
+ pAnchoredObj->AnchorFrm()
+ ->Prepare( PREP_FLY_ATTR_CHG,
+ &(pAnchoredObj->GetFrmFmt()) );
+ }
+ // <--
+ if ( pAnchoredObj->ISA(SwFlyFrm) )
+ {
+ SwFlyFrm *pFly = static_cast<SwFlyFrm*>(pAnchoredObj);
+ pFly->GetVirtDrawObj()->SetRectsDirty();
+ pFly->GetVirtDrawObj()->SetChanged();
+ }
+ }
+
+ // If anchored object is a fly frame, invalidate its lower objects
+ if ( pAnchoredObj->ISA(SwFlyFrm) )
+ {
+ SwFlyFrm *pFly = static_cast<SwFlyFrm*>(pAnchoredObj);
+ ::lcl_InvalidateLowerObjs( *pFly, _bMoveObjsOutOfRange, _pPageFrm );
+ }
+ }
+ }
+ pLowerFrm = pLowerFrm->GetNext();
+ }
+}
+// <--
+//
+// Local helper function to shrink all lowers of rRow to 0 height
+//
+void lcl_ShrinkCellsAndAllContent( SwRowFrm& rRow )
+{
+ SwCellFrm* pCurrMasterCell = static_cast<SwCellFrm*>(rRow.Lower());
+ SWRECTFN( pCurrMasterCell )
+
+ while ( pCurrMasterCell )
+ {
+ // NEW TABLES
+ SwCellFrm& rToAdjust = pCurrMasterCell->GetTabBox()->getRowSpan() < 1 ?
+ const_cast<SwCellFrm&>(pCurrMasterCell->FindStartEndOfRowSpanCell( true, true )) :
+ *pCurrMasterCell;
+
+ // --> OD 2004-10-04 #i26945#
+ // all lowers should have the correct position
+ lcl_ArrangeLowers( &rToAdjust,
+ (rToAdjust.*fnRect->fnGetPrtTop)(),
+ sal_False );
+ // <--
+ // TODO: Optimize number of frames which are set to 0 height
+ // we have to start with the last lower frame, otherwise
+ // the shrink will not shrink the current cell
+ SwFrm* pTmp = rToAdjust.GetLastLower();
+
+ if ( pTmp && pTmp->IsRowFrm() )
+ {
+ SwRowFrm* pTmpRow = (SwRowFrm*)pTmp;
+ lcl_ShrinkCellsAndAllContent( *pTmpRow );
+ }
+ else
+ {
+ // TODO: Optimize number of frames which are set to 0 height
+ while ( pTmp )
+ {
+ // the frames have to be shrunk
+ if ( pTmp && pTmp->IsTabFrm() )
+ {
+ SwRowFrm* pTmpRow = (SwRowFrm*)((SwTabFrm*)pTmp)->Lower();
+ while ( pTmpRow )
+ {
+ lcl_ShrinkCellsAndAllContent( *pTmpRow );
+ pTmpRow = (SwRowFrm*)pTmpRow->GetNext();
+ }
+ }
+ else
+ {
+ pTmp->Shrink( (pTmp->Frm().*fnRect->fnGetHeight)() );
+ (pTmp->Prt().*fnRect->fnSetTop)( 0 );
+ (pTmp->Prt().*fnRect->fnSetHeight)( 0 );
+ }
+
+ pTmp = pTmp->GetPrev();
+ }
+
+ // all lowers should have the correct position
+ lcl_ArrangeLowers( &rToAdjust,
+ (rToAdjust.*fnRect->fnGetPrtTop)(),
+ sal_False );
+ }
+
+ pCurrMasterCell = static_cast<SwCellFrm*>(pCurrMasterCell->GetNext());
+ }
+}
+
+//
+// Local helper function to move the content from rSourceLine to rDestLine
+// The content is inserted behind the last content in the corresponding
+// cell in rDestLine.
+//
+void lcl_MoveRowContent( SwRowFrm& rSourceLine, SwRowFrm& rDestLine )
+{
+ SwCellFrm* pCurrDestCell = (SwCellFrm*)rDestLine.Lower();
+ SwCellFrm* pCurrSourceCell = (SwCellFrm*)rSourceLine.Lower();
+
+ // Move content of follow cells into master cells
+ while ( pCurrSourceCell )
+ {
+ if ( pCurrSourceCell->Lower() && pCurrSourceCell->Lower()->IsRowFrm() )
+ {
+ SwRowFrm* pTmpSourceRow = (SwRowFrm*)pCurrSourceCell->Lower();
+ while ( pTmpSourceRow )
+ {
+ // --> FME 2006-01-10 #125926# Achtung! It is possible,
+ // that pTmpSourceRow->IsFollowFlowRow() but pTmpDestRow
+ // cannot be found. In this case, we have to move the complete
+ // row.
+ SwRowFrm* pTmpDestRow = (SwRowFrm*)pCurrDestCell->Lower();
+ // <--
+
+ if ( pTmpSourceRow->IsFollowFlowRow() && pTmpDestRow )
+ {
+ // move content from follow flow row to pTmpDestRow:
+ while ( pTmpDestRow->GetNext() )
+ pTmpDestRow = (SwRowFrm*)pTmpDestRow->GetNext();
+
+ OSL_ENSURE( pTmpDestRow->GetFollowRow() == pTmpSourceRow, "Knoten in der Tabelle" );
+
+ lcl_MoveRowContent( *pTmpSourceRow, *pTmpDestRow );
+ pTmpDestRow->SetFollowRow( pTmpSourceRow->GetFollowRow() );
+ pTmpSourceRow->Remove();
+ delete pTmpSourceRow;
+ }
+ else
+ {
+ // move complete row:
+ pTmpSourceRow->Remove();
+ pTmpSourceRow->InsertBefore( pCurrDestCell, 0 );
+ }
+
+ pTmpSourceRow = (SwRowFrm*)pCurrSourceCell->Lower();
+ }
+ }
+ else
+ {
+ SwFrm *pTmp = ::SaveCntnt( (SwCellFrm*)pCurrSourceCell );
+ if ( pTmp )
+ {
+ // NEW TABLES
+ SwCellFrm* pDestCell = static_cast<SwCellFrm*>(pCurrDestCell);
+ if ( pDestCell->GetTabBox()->getRowSpan() < 1 )
+ pDestCell = & const_cast<SwCellFrm&>(pDestCell->FindStartEndOfRowSpanCell( true, true ));
+
+ // Find last content
+ SwFrm* pFrm = pDestCell->GetLastLower();
+ ::RestoreCntnt( pTmp, pDestCell, pFrm, true );
+ }
+ }
+ pCurrDestCell = (SwCellFrm*)pCurrDestCell->GetNext();
+ pCurrSourceCell = (SwCellFrm*)pCurrSourceCell->GetNext();
+ }
+}
+
+//
+// Local helper function to move all footnotes in rRowFrm from
+// the footnote boss of rSource to the footnote boss of rDest.
+//
+void lcl_MoveFootnotes( SwTabFrm& rSource, SwTabFrm& rDest, SwLayoutFrm& rRowFrm )
+{
+ if ( 0 != rSource.GetFmt()->GetDoc()->GetFtnIdxs().Count() )
+ {
+ SwFtnBossFrm* pOldBoss = rSource.FindFtnBossFrm( sal_True );
+ SwFtnBossFrm* pNewBoss = rDest.FindFtnBossFrm( sal_True );
+ rRowFrm.MoveLowerFtns( 0, pOldBoss, pNewBoss, sal_True );
+ }
+}
+
+//
+// Local helper function to handle nested table cells before the split process
+//
+void lcl_PreprocessRowsInCells( SwTabFrm& rTab, SwRowFrm& rLastLine,
+ SwRowFrm& rFollowFlowLine, SwTwips nRemain )
+{
+ SwCellFrm* pCurrLastLineCell = (SwCellFrm*)rLastLine.Lower();
+ SwCellFrm* pCurrFollowFlowLineCell = (SwCellFrm*)rFollowFlowLine.Lower();
+
+ SWRECTFN( pCurrLastLineCell )
+
+ //
+ // Move content of follow cells into master cells
+ //
+ while ( pCurrLastLineCell )
+ {
+ if ( pCurrLastLineCell->Lower() && pCurrLastLineCell->Lower()->IsRowFrm() )
+ {
+ SwTwips nTmpCut = nRemain;
+ SwRowFrm* pTmpLastLineRow = (SwRowFrm*)pCurrLastLineCell->Lower();
+
+ // --> OD 2004-10-04 #i26945#
+ SwTwips nCurrentHeight =
+ lcl_CalcMinRowHeight( pTmpLastLineRow,
+ rTab.IsConsiderObjsForMinCellHeight() );
+ // <--
+ while ( pTmpLastLineRow && pTmpLastLineRow->GetNext() && nTmpCut > nCurrentHeight )
+ {
+ nTmpCut -= nCurrentHeight;
+ pTmpLastLineRow = (SwRowFrm*)pTmpLastLineRow->GetNext();
+ // --> OD 2004-10-04 #i26945#
+ nCurrentHeight =
+ lcl_CalcMinRowHeight( pTmpLastLineRow,
+ rTab.IsConsiderObjsForMinCellHeight() );
+ // <--
+ }
+
+ //
+ // pTmpLastLineRow does not fit to the line or it is the last line
+ //
+ if ( pTmpLastLineRow )
+ {
+ //
+ // Check if we can move pTmpLastLineRow to the follow table,
+ // or if we have to split the line:
+ //
+ SwFrm* pCell = pTmpLastLineRow->Lower();
+ bool bTableLayoutToComplex = false;
+ long nMinHeight = 0;
+
+ //
+ // We have to take into account:
+ // 1. The fixed height of the row
+ // 2. The borders of the cells inside the row
+ // 3. The minimum height of the row
+ //
+ if ( pTmpLastLineRow->HasFixSize() )
+ nMinHeight = (pTmpLastLineRow->Frm().*fnRect->fnGetHeight)();
+ else
+ {
+ while ( pCell )
+ {
+ if ( ((SwCellFrm*)pCell)->Lower() &&
+ ((SwCellFrm*)pCell)->Lower()->IsRowFrm() )
+ {
+ bTableLayoutToComplex = true;
+ break;
+ }
+
+ SwBorderAttrAccess aAccess( SwFrm::GetCache(), pCell );
+ const SwBorderAttrs &rAttrs = *aAccess.Get();
+ nMinHeight = Max( nMinHeight, lcl_CalcTopAndBottomMargin( *(SwLayoutFrm*)pCell, rAttrs ) );
+ pCell = pCell->GetNext();
+ }
+
+ const SwFmtFrmSize &rSz = pTmpLastLineRow->GetFmt()->GetFrmSize();
+ if ( rSz.GetHeightSizeType() == ATT_MIN_SIZE )
+ nMinHeight = Max( nMinHeight, rSz.GetHeight() );
+ }
+
+ //
+ // 1. Case:
+ // The line completely fits into the master table.
+ // Nevertheless, we build a follow (otherwise painting problems
+ // with empty cell).
+ //
+ // 2. Case:
+ // The line has to be split, the minimum height still fits into
+ // the master table, and the table structure is not to complex.
+ //
+ if ( nTmpCut > nCurrentHeight ||
+ ( pTmpLastLineRow->IsRowSplitAllowed() &&
+ !bTableLayoutToComplex && nMinHeight < nTmpCut ) )
+ {
+ // The line has to be split:
+ SwRowFrm* pNewRow = new SwRowFrm( *pTmpLastLineRow->GetTabLine(), &rTab, false );
+ pNewRow->SetFollowFlowRow( true );
+ pNewRow->SetFollowRow( pTmpLastLineRow->GetFollowRow() );
+ pTmpLastLineRow->SetFollowRow( pNewRow );
+ pNewRow->InsertBehind( pCurrFollowFlowLineCell, 0 );
+ pTmpLastLineRow = (SwRowFrm*)pTmpLastLineRow->GetNext();
+ }
+
+ //
+ // The following lines have to be moved:
+ //
+ while ( pTmpLastLineRow )
+ {
+ SwRowFrm* pTmp = (SwRowFrm*)pTmpLastLineRow->GetNext();
+ lcl_MoveFootnotes( rTab, *rTab.GetFollow(), *pTmpLastLineRow );
+ pTmpLastLineRow->Remove();
+ pTmpLastLineRow->InsertBefore( pCurrFollowFlowLineCell, 0 );
+ pTmpLastLineRow->Shrink( ( pTmpLastLineRow->Frm().*fnRect->fnGetHeight)() );
+ pCurrFollowFlowLineCell->Grow( ( pTmpLastLineRow->Frm().*fnRect->fnGetHeight)() );
+ pTmpLastLineRow = pTmp;
+ }
+ }
+ }
+
+ pCurrLastLineCell = (SwCellFrm*)pCurrLastLineCell->GetNext();
+ pCurrFollowFlowLineCell = (SwCellFrm*)pCurrFollowFlowLineCell->GetNext();
+ }
+}
+
+//
+// Local helper function to handle nested table cells after the split process
+//
+void lcl_PostprocessRowsInCells( SwTabFrm& rTab, SwRowFrm& rLastLine )
+{
+ SwCellFrm* pCurrMasterCell = (SwCellFrm*)rLastLine.Lower();
+ while ( pCurrMasterCell )
+ {
+ if ( pCurrMasterCell->Lower() &&
+ pCurrMasterCell->Lower()->IsRowFrm() )
+ {
+ SwRowFrm* pRowFrm = static_cast<SwRowFrm*>(pCurrMasterCell->GetLastLower());
+
+ if ( NULL != pRowFrm->GetPrev() && !pRowFrm->ContainsCntnt() )
+ {
+ OSL_ENSURE( pRowFrm->GetFollowRow(), "Deleting row frame without follow" );
+
+ // The footnotes have to be moved:
+ lcl_MoveFootnotes( rTab, *rTab.GetFollow(), *pRowFrm );
+ pRowFrm->Cut();
+ SwRowFrm* pFollowRow = pRowFrm->GetFollowRow();
+ pRowFrm->Paste( pFollowRow->GetUpper(), pFollowRow );
+ pRowFrm->SetFollowRow( pFollowRow->GetFollowRow() );
+ lcl_MoveRowContent( *pFollowRow, *pRowFrm );
+ pFollowRow->Cut();
+ delete pFollowRow;
+ ::SwInvalidateAll( pCurrMasterCell, LONG_MAX );
+ }
+ }
+
+ pCurrMasterCell = (SwCellFrm*)pCurrMasterCell->GetNext();
+ }
+}
+
+//
+// Local helper function to re-calculate the split line.
+//
+inline void TableSplitRecalcLock( SwFlowFrm *pTab ) { pTab->LockJoin(); }
+inline void TableSplitRecalcUnlock( SwFlowFrm *pTab ) { pTab->UnlockJoin(); }
+
+bool lcl_RecalcSplitLine( SwRowFrm& rLastLine, SwRowFrm& rFollowLine,
+ SwTwips nRemainingSpaceForLastRow )
+{
+ bool bRet = true;
+
+ SwTabFrm& rTab = (SwTabFrm&)*rLastLine.GetUpper();
+
+ //
+ // If there are nested cells in rLastLine, the recalculation of the last
+ // line needs some preprocessing.
+ //
+ lcl_PreprocessRowsInCells( rTab, rLastLine, rFollowLine, nRemainingSpaceForLastRow );
+
+ //
+ // Here the recalculation process starts:
+ //
+ rTab.SetRebuildLastLine( sal_True );
+ // --> OD 2004-10-15 #i26945#
+ rTab.SetDoesObjsFit( sal_True );
+ // <--
+ SWRECTFN( rTab.GetUpper() )
+
+ // --> OD 2004-11-05 #i26945# - invalidate and move floating screen
+ // objects 'out of range'
+ ::lcl_InvalidateLowerObjs( rLastLine, true );
+ // <--
+ //
+ // manipulate row and cell sizes
+ //
+ // --> OD 2004-10-04 #i26945# - Do *not* consider floating screen objects
+ // for the minimal cell height.
+ rTab.SetConsiderObjsForMinCellHeight( sal_False );
+ ::lcl_ShrinkCellsAndAllContent( rLastLine );
+ rTab.SetConsiderObjsForMinCellHeight( sal_True );
+ // <--
+
+ //
+ // invalidate last line
+ //
+ ::SwInvalidateAll( &rLastLine, LONG_MAX );
+
+ //
+ // Lock this tab frame and its follow
+ //
+ bool bUnlockMaster = false;
+ bool bUnlockFollow = false;
+ SwTabFrm* pMaster = rTab.IsFollow() ? (SwTabFrm*)rTab.FindMaster() : 0;
+ if ( pMaster && !pMaster->IsJoinLocked() )
+ {
+ bUnlockMaster = true;
+ ::TableSplitRecalcLock( pMaster );
+ }
+ if ( !rTab.GetFollow()->IsJoinLocked() )
+ {
+ bUnlockFollow = true;
+ ::TableSplitRecalcLock( rTab.GetFollow() );
+ }
+
+ //
+ // Do the recalculation
+ //
+ lcl_RecalcRow( rLastLine, LONG_MAX );
+ // --> OD 2004-11-23 #115759# - force a format of the last line in order to
+ // get the correct height.
+ rLastLine.InvalidateSize();
+ rLastLine.Calc();
+ // <--
+
+ //
+ // Unlock this tab frame and its follow
+ //
+ if ( bUnlockFollow )
+ ::TableSplitRecalcUnlock( rTab.GetFollow() );
+ if ( bUnlockMaster )
+ ::TableSplitRecalcUnlock( pMaster );
+
+ //
+ // If there are nested cells in rLastLine, the recalculation of the last
+ // line needs some postprocessing.
+ //
+ lcl_PostprocessRowsInCells( rTab, rLastLine );
+
+ //
+ // Do a couple of checks on the current situation.
+ //
+ // If we are not happy with the current situation we return false.
+ // This will start a new try to split the table, this time we do not
+ // try to split the table rows.
+ //
+
+ //
+ // 1. Check if table fits to its upper.
+ // --> OD 2004-10-15 #i26945# - include check, if objects fit
+ //
+ const SwTwips nDistanceToUpperPrtBottom =
+ (rTab.Frm().*fnRect->fnBottomDist)( (rTab.GetUpper()->*fnRect->fnGetPrtBottom)());
+ if ( nDistanceToUpperPrtBottom < 0 || !rTab.DoesObjsFit() )
+ bRet = false;
+ // <--
+
+ //
+ // 2. Check if each cell in the last line has at least one content frame.
+ //
+ // Note: a FollowFlowRow may contains empty cells!
+ //
+ if ( bRet )
+ {
+ if ( !rLastLine.IsInFollowFlowRow() )
+ {
+ SwCellFrm* pCurrMasterCell = (SwCellFrm*)rLastLine.Lower();
+ while ( pCurrMasterCell )
+ {
+ if ( !pCurrMasterCell->ContainsCntnt() && pCurrMasterCell->GetTabBox()->getRowSpan() >= 1 )
+ {
+ bRet = false;
+ break;
+ }
+ pCurrMasterCell = (SwCellFrm*)pCurrMasterCell->GetNext();
+ }
+ }
+ }
+
+ //
+ // 3. Check if last line does not contain any content:
+ //
+ if ( bRet )
+ {
+ if ( !rLastLine.ContainsCntnt() )
+ {
+ bRet = false;
+ }
+ }
+
+
+ //
+ // 4. Check if follow flow line does not contain content:
+ //
+ if ( bRet )
+ {
+ if ( !rFollowLine.IsRowSpanLine() && !rFollowLine.ContainsCntnt() )
+ {
+ bRet = false;
+ }
+ }
+
+ if ( bRet )
+ {
+ //
+ // Everything looks fine. Splitting seems to be successful. We invalidate
+ // rFollowLine to force a new formatting.
+ //
+ ::SwInvalidateAll( &rFollowLine, LONG_MAX );
+ }
+ else
+ {
+ //
+ // Splitting the table row gave us an unexpected result.
+ // Everything has to be prepared for a second try to split
+ // the table, this time without splitting the row.
+ //
+ ::SwInvalidateAll( &rLastLine, LONG_MAX );
+ }
+
+ rTab.SetRebuildLastLine( sal_False );
+ // --> OD 2004-10-15 #i26945#
+ rTab.SetDoesObjsFit( sal_True );
+ // <--
+
+ return bRet;
+}
+
+//
+// Sets the correct height for all spanned cells
+//
+void lcl_AdjustRowSpanCells( SwRowFrm* pRow )
+{
+ SWRECTFN( pRow )
+ SwCellFrm* pCellFrm = static_cast<SwCellFrm*>(pRow->GetLower());
+ while ( pCellFrm )
+ {
+ const long nLayoutRowSpan = pCellFrm->GetLayoutRowSpan();
+ if ( nLayoutRowSpan > 1 )
+ {
+ // calculate height of cell:
+ const long nNewCellHeight = lcl_GetHeightOfRows( pRow, nLayoutRowSpan );
+ const long nDiff = nNewCellHeight - (pCellFrm->Frm().*fnRect->fnGetHeight)();
+ if ( nDiff )
+ (pCellFrm->Frm().*fnRect->fnAddBottom)( nDiff );
+ }
+
+ pCellFrm = static_cast<SwCellFrm*>(pCellFrm->GetNext());
+ }
+}
+
+//
+// Returns the maximum layout row span of the row
+// Looking for the next row that contains no covered cells:
+long lcl_GetMaximumLayoutRowSpan( const SwRowFrm& rRow )
+{
+ long nRet = 1;
+
+ const SwRowFrm* pCurrentRowFrm = static_cast<const SwRowFrm*>(rRow.GetNext());
+ bool bNextRow = false;
+
+ while ( pCurrentRowFrm )
+ {
+ // if there is any covered cell, we proceed to the next row frame
+ const SwCellFrm* pLower = static_cast<const SwCellFrm*>( pCurrentRowFrm->Lower());
+ while ( pLower )
+ {
+ if ( pLower->GetTabBox()->getRowSpan() < 0 )
+ {
+ ++nRet;
+ bNextRow = true;
+ break;
+ }
+ pLower = static_cast<const SwCellFrm*>(pLower->GetNext());
+ }
+ pCurrentRowFrm = bNextRow ?
+ static_cast<const SwRowFrm*>(pCurrentRowFrm->GetNext() ) :
+ 0;
+ }
+
+ return nRet;
+}
+
+/*************************************************************************
+|* END: local helper functions for splitting row frames
+|*************************************************************************/
+
+//
+// Function to remove the FollowFlowLine of rTab.
+// The content of the FollowFlowLine is moved to the associated line in the
+// master table.
+//
+bool SwTabFrm::RemoveFollowFlowLine()
+{
+ // find FollowFlowLine
+ SwRowFrm* pFollowFlowLine = static_cast<SwRowFrm*>(GetFollow()->GetFirstNonHeadlineRow());
+
+ // find last row in master
+ SwFrm* pLastLine = GetLastLower();
+
+ OSL_ENSURE( HasFollowFlowLine() &&
+ pFollowFlowLine &&
+ pLastLine, "There should be a flowline in the follow" );
+
+ // We have to reset the flag here, because lcl_MoveRowContent
+ // calls a GrowFrm(), which has a different bahavior if
+ // this flag is set.
+ SetFollowFlowLine( sal_False );
+
+ // --> FME 2007-07-19 #140081# Make code robust.
+ if ( !pFollowFlowLine || !pLastLine )
+ return true;
+
+ // Move content
+ lcl_MoveRowContent( *pFollowFlowLine, *(SwRowFrm*)pLastLine );
+
+ // NEW TABLES
+ // If a row span follow flow line is removed, we want to move the whole span
+ // to the master:
+ long nRowsToMove = lcl_GetMaximumLayoutRowSpan( *pFollowFlowLine );
+
+ if ( nRowsToMove > 1 )
+ {
+ SWRECTFN( this )
+ SwFrm* pRow = pFollowFlowLine->GetNext();
+ SwFrm* pInsertBehind = GetLastLower();
+ SwTwips nGrow = 0;
+
+ while ( pRow && nRowsToMove-- > 1 )
+ {
+ SwFrm* pNxt = pRow->GetNext();
+ nGrow += (pRow->Frm().*fnRect->fnGetHeight)();
+
+ // The footnotes have to be moved:
+ lcl_MoveFootnotes( *GetFollow(), *this, (SwRowFrm&)*pRow );
+
+ pRow->Remove();
+ pRow->InsertBehind( this, pInsertBehind );
+ pRow->_InvalidateAll();
+ pRow->CheckDirChange();
+ pInsertBehind = pRow;
+ pRow = pNxt;
+ }
+
+ SwFrm* pFirstRow = Lower();
+ while ( pFirstRow )
+ {
+ lcl_AdjustRowSpanCells( static_cast<SwRowFrm*>(pFirstRow) );
+ pFirstRow = pFirstRow->GetNext();
+ }
+
+ Grow( nGrow );
+ GetFollow()->Shrink( nGrow );
+ }
+
+ bool bJoin = !pFollowFlowLine->GetNext();
+ pFollowFlowLine->Cut();
+ delete pFollowFlowLine;
+
+ return bJoin;
+}
+
+// --> OD 2004-10-04 #i26945# - Floating screen objects are no longer searched.
+bool lcl_FindSectionsInRow( const SwRowFrm& rRow )
+{
+ bool bRet = false;
+ SwCellFrm* pLower = (SwCellFrm*)rRow.Lower();
+ while ( pLower )
+ {
+ if ( pLower->IsVertical() != rRow.IsVertical() )
+ return true;
+
+ SwFrm* pTmpFrm = pLower->Lower();
+ while ( pTmpFrm )
+ {
+ if ( pTmpFrm->IsRowFrm() )
+ {
+ bRet = lcl_FindSectionsInRow( *(SwRowFrm*)pTmpFrm );
+ }
+ else
+ {
+ // --> OD 2004-10-04 #i26945# - search only for sections
+ bRet = pTmpFrm->IsSctFrm();
+ // <--
+ }
+
+ if ( bRet )
+ return true;
+ pTmpFrm = pTmpFrm->GetNext();
+ }
+
+ pLower = (SwCellFrm*)pLower->GetNext();
+ }
+ return bRet;
+}
+
+/*************************************************************************
+|*
+|* SwTabFrm::Split(), Join()
+|*
+|*************************************************************************/
+bool SwTabFrm::Split( const SwTwips nCutPos, bool bTryToSplit, bool bTableRowKeep )
+{
+ bool bRet = true;
+
+ SWRECTFN( this )
+
+ // --> OD 2004-10-14 #i26745# - format row and cell frames of table
+ {
+ this->Lower()->_InvalidatePos();
+ // --> OD 2005-03-30 #i43913# - correction:
+ // call method <lcl_InnerCalcLayout> with first lower.
+ lcl_InnerCalcLayout( this->Lower(), LONG_MAX, true );
+ // <--
+ }
+ // <--
+
+ //Um die Positionen der Zellen mit der CutPos zu vergleichen muessen sie
+ //ausgehend von der Tabelle nacheinander berechnet werden. Sie koennen
+ //wg. Positionsaenderungen der Tabelle durchaus ungueltig sein.
+ SwRowFrm *pRow = static_cast<SwRowFrm*>(Lower());
+ if( !pRow )
+ return bRet;
+
+ const sal_uInt16 nRepeat = GetTable()->GetRowsToRepeat();
+ sal_uInt16 nRowCount = 0; // pRow currently points to the first row
+
+ SwTwips nRemainingSpaceForLastRow =
+ (*fnRect->fnYDiff)( nCutPos, (Frm().*fnRect->fnGetTop)() );
+ nRemainingSpaceForLastRow -= (this->*fnRect->fnGetTopMargin)();
+
+ //
+ // Make pRow point to the line that does not fit anymore:
+ //
+ while( pRow->GetNext() &&
+ nRemainingSpaceForLastRow >= ( (pRow->Frm().*fnRect->fnGetHeight)() +
+ (IsCollapsingBorders() ?
+ pRow->GetBottomLineSize() :
+ 0 ) ) )
+ {
+ if( bTryToSplit || !pRow->IsRowSpanLine() ||
+ 0 != (pRow->Frm().*fnRect->fnGetHeight)() )
+ ++nRowCount;
+ nRemainingSpaceForLastRow -= (pRow->Frm().*fnRect->fnGetHeight)();
+ pRow = static_cast<SwRowFrm*>(pRow->GetNext());
+ }
+
+ //
+ // bSplitRowAllowed: Row may be split according to its attributes.
+ // bTryToSplit: Row will never be split if bTryToSplit = false.
+ // This can either be passed as a parameter, indicating
+ // that we are currently doing the second try to split the
+ // table, or it will be set to falseunder certain
+ // conditions that are not suitable for splitting
+ // the row.
+ //
+ bool bSplitRowAllowed = pRow->IsRowSplitAllowed();
+
+ // --> FME 2004-06-03 #i29438#
+ // --> OD 2004-10-04 #i26945# - Floating screen objects no longer forbid
+ // a splitting of the table row.
+ // Special DoNotSplit case 1:
+ // Search for sections inside pRow:
+ //
+ if ( lcl_FindSectionsInRow( *pRow ) )
+ {
+ bTryToSplit = false;
+ }
+ // <--
+
+ // --> FME 2004-06-07 #i29771#
+ // To avoid loops, we do some checks before actually trying to split
+ // the row. Maybe we should keep the next row in this table.
+ // Note: This is only done if we are at the beginning of our upper
+ bool bKeepNextRow = false;
+ if ( nRowCount < nRepeat )
+ {
+ //
+ // First case: One of the repeated headline does not fit to the page anymore.
+ // At least one more non-heading row has to stay in this table in
+ // order to avoid loops:
+ //
+ OSL_ENSURE( !GetIndPrev(), "Table is supposed to be at beginning" );
+ bKeepNextRow = true;
+ }
+ else if ( !GetIndPrev() && nRepeat == nRowCount )
+ {
+ //
+ // Second case: The first non-headline row does not fit to the page.
+ // If it is not allowed to be split, or it contains a sub-row that
+ // is not allowed to be split, we keep the row in this table:
+ //
+ if ( bTryToSplit && bSplitRowAllowed )
+ {
+ // Check if there are (first) rows inside this row,
+ // which are not allowed to be split.
+ SwCellFrm* pLowerCell = pRow ? (SwCellFrm*)pRow->Lower() : 0;
+ while ( pLowerCell )
+ {
+ if ( pLowerCell->Lower() && pLowerCell->Lower()->IsRowFrm() )
+ {
+ const SwRowFrm* pLowerRow = (SwRowFrm*)pLowerCell->Lower();
+ if ( !pLowerRow->IsRowSplitAllowed() &&
+ (pLowerRow->Frm().*fnRect->fnGetHeight)() >
+ nRemainingSpaceForLastRow )
+ {
+ bKeepNextRow = true;
+ break;
+ }
+ }
+ pLowerCell = (SwCellFrm*)pLowerCell->GetNext();
+ }
+ }
+ else
+ bKeepNextRow = true;
+ }
+
+ //
+ // Better keep the next row in this table:
+ //
+ if ( bKeepNextRow )
+ {
+ pRow = GetFirstNonHeadlineRow();
+ if( pRow && pRow->IsRowSpanLine() && 0 == (pRow->Frm().*fnRect->fnGetHeight)() )
+ pRow = static_cast<SwRowFrm*>(pRow->GetNext());
+ if ( pRow )
+ {
+ pRow = static_cast<SwRowFrm*>(pRow->GetNext());
+ ++nRowCount;
+ }
+ }
+
+ //
+ // No more row to split or to move to follow table:
+ //
+ if ( !pRow )
+ return bRet;
+
+ //
+ // We try to split the row if
+ // - the attributes of the row are set accordingly and
+ // - we are allowed to do so
+ // - the it should not keep with the next row
+ //
+ bSplitRowAllowed = bSplitRowAllowed && bTryToSplit &&
+ ( !bTableRowKeep ||
+ !pRow->ShouldRowKeepWithNext() );
+
+ // Adjust pRow according to the keep-with-next attribute:
+ if ( !bSplitRowAllowed && bTableRowKeep )
+ {
+ SwRowFrm* pTmpRow = static_cast<SwRowFrm*>(pRow->GetPrev());
+ SwRowFrm* pOldRow = pRow;
+ while ( pTmpRow && pTmpRow->ShouldRowKeepWithNext() &&
+ nRowCount > nRepeat )
+ {
+ pRow = pTmpRow;
+ --nRowCount;
+ pTmpRow = static_cast<SwRowFrm*>(pTmpRow->GetPrev());
+ }
+
+ // loop prevention
+ if ( nRowCount == nRepeat && !GetIndPrev())
+ {
+ pRow = pOldRow;
+ }
+ }
+
+ //
+ // If we do not indent to split pRow, we check if we are
+ // allowed to move pRow to a follow. Otherwise we return
+ // false, indicating an error
+ //
+ if ( !bSplitRowAllowed )
+ {
+ SwRowFrm* pFirstNonHeadlineRow = GetFirstNonHeadlineRow();
+ if ( pRow == pFirstNonHeadlineRow )
+ return false;
+
+ // --> OD 2008-10-21 #i91764#
+ // Ignore row span lines
+ SwRowFrm* pTmpRow = pFirstNonHeadlineRow;
+ while ( pTmpRow && pTmpRow->IsRowSpanLine() )
+ {
+ pTmpRow = static_cast<SwRowFrm*>(pTmpRow->GetNext());
+ }
+ if ( !pTmpRow || pRow == pTmpRow )
+ {
+ return false;
+ }
+ // <--
+ }
+
+ //
+ // Build follow table if not already done:
+ //
+ sal_Bool bNewFollow;
+ SwTabFrm *pFoll;
+ if ( GetFollow() )
+ {
+ pFoll = GetFollow();
+ bNewFollow = sal_False;
+ }
+ else
+ {
+ bNewFollow = sal_True;
+ pFoll = new SwTabFrm( *this );
+
+ //
+ // We give the follow table an initial width.
+ //
+ (pFoll->Frm().*fnRect->fnAddWidth)( (Frm().*fnRect->fnGetWidth)() );
+ (pFoll->Prt().*fnRect->fnAddWidth)( (Prt().*fnRect->fnGetWidth)() );
+ (pFoll->Frm().*fnRect->fnSetLeft)( (Frm().*fnRect->fnGetLeft)() );
+
+ //
+ // Insert the new follow table
+ //
+ pFoll->InsertBehind( GetUpper(), this );
+
+ //
+ // Repeat the headlines.
+ //
+ for ( nRowCount = 0; nRowCount < nRepeat; ++nRowCount )
+ {
+ // Insert new headlines:
+ bDontCreateObjects = sal_True; //frmtool
+ SwRowFrm* pHeadline = new SwRowFrm(
+ *GetTable()->GetTabLines()[ nRowCount ], this );
+ pHeadline->SetRepeatedHeadline( true );
+ bDontCreateObjects = sal_False;
+ pHeadline->InsertBefore( pFoll, 0 );
+
+ SwPageFrm *pPage = pHeadline->FindPageFrm();
+ const SwSpzFrmFmts *pTbl = GetFmt()->GetDoc()->GetSpzFrmFmts();
+ if( pTbl->Count() )
+ {
+ sal_uLong nIndex;
+ SwCntntFrm* pFrm = pHeadline->ContainsCntnt();
+ while( pFrm )
+ {
+ nIndex = pFrm->GetNode()->GetIndex();
+ AppendObjs( pTbl, nIndex, pFrm, pPage );
+ pFrm = pFrm->GetNextCntntFrm();
+ if( !pHeadline->IsAnLower( pFrm ) )
+ break;
+ }
+ }
+ }
+ }
+
+ SwRowFrm* pLastRow = 0; // will point to the last remaining line in master
+ SwRowFrm* pFollowRow = 0; // points to either the follow flow line of the
+ // first regular line in the follow
+
+ if ( bSplitRowAllowed )
+ {
+ // If the row that does not fit anymore is allowed
+ // to be split, the next row has to be moved to the follow table.
+ pLastRow = pRow;
+ pRow = static_cast<SwRowFrm*>(pRow->GetNext());
+
+ // new follow flow line for last row of master table
+ pFollowRow = lcl_InsertNewFollowFlowLine( *this, *pLastRow, false );
+ }
+ else
+ {
+ pFollowRow = pRow;
+
+ // NEW TABLES
+ // check if we will break a row span by moving pFollowRow to the follow:
+ // In this case we want to reformat the last line.
+ const SwCellFrm* pCellFrm = static_cast<const SwCellFrm*>(pFollowRow->GetLower());
+ while ( pCellFrm )
+ {
+ if ( pCellFrm->GetTabBox()->getRowSpan() < 1 )
+ {
+ pLastRow = static_cast<SwRowFrm*>(pRow->GetPrev());
+ break;
+ }
+
+ pCellFrm = static_cast<const SwCellFrm*>(pCellFrm->GetNext());
+ }
+
+ // new follow flow line for last row of master table
+ if ( pLastRow )
+ pFollowRow = lcl_InsertNewFollowFlowLine( *this, *pLastRow, true );
+ }
+
+ SwTwips nRet = 0;
+
+ //Optimierung beim neuen Follow braucht's kein Paste und dann kann
+ //das Optimierte Insert verwendet werden (nur dann treten gluecklicher weise
+ //auch groessere Mengen von Rows auf).
+ if ( bNewFollow )
+ {
+ SwFrm* pNxt = 0;
+ SwFrm* pInsertBehind = pFoll->GetLastLower();
+
+ while ( pRow )
+ {
+ pNxt = pRow->GetNext();
+ nRet += (pRow->Frm().*fnRect->fnGetHeight)();
+ // The footnotes do not have to be moved, this is done in the
+ // MoveFwd of the follow table!!!
+ pRow->Remove();
+ pRow->InsertBehind( pFoll, pInsertBehind );
+ pRow->_InvalidateAll();
+ pInsertBehind = pRow;
+ pRow = static_cast<SwRowFrm*>(pNxt);
+ }
+ }
+ else
+ {
+ SwFrm* pNxt = 0;
+ SwFrm* pPasteBefore = HasFollowFlowLine() ?
+ pFollowRow->GetNext() :
+ pFoll->GetFirstNonHeadlineRow();
+
+ while ( pRow )
+ {
+ pNxt = pRow->GetNext();
+ nRet += (pRow->Frm().*fnRect->fnGetHeight)();
+
+ // The footnotes have to be moved:
+ lcl_MoveFootnotes( *this, *GetFollow(), *pRow );
+
+ pRow->Remove();
+ pRow->Paste( pFoll, pPasteBefore );
+
+ pRow->CheckDirChange();
+ pRow = static_cast<SwRowFrm*>(pNxt);
+ }
+ }
+
+ Shrink( nRet );
+
+ // we rebuild the last line to assure that it will be fully formatted
+ if ( pLastRow )
+ {
+ // recalculate the split line
+ bRet = lcl_RecalcSplitLine( *pLastRow, *pFollowRow, nRemainingSpaceForLastRow );
+
+ // NEW TABLES
+ // check if each cell in the row span line has a good height
+ if ( bRet && pFollowRow->IsRowSpanLine() )
+ lcl_AdjustRowSpanCells( pFollowRow );
+
+ // We The RowSplitLine stuff did not work. In this case we conceal the split error:
+ if ( !bRet && !bSplitRowAllowed )
+ {
+ bRet = true;
+ }
+ }
+
+ return bRet;
+}
+
+bool SwTabFrm::Join()
+{
+ OSL_ENSURE( !HasFollowFlowLine(), "Joining follow flow line" );
+
+ SwTabFrm *pFoll = GetFollow();
+
+ if ( !pFoll->IsJoinLocked() )
+ {
+ SWRECTFN( this )
+ pFoll->Cut(); //Erst ausschneiden um unuetze Benachrichtigungen zu
+ //minimieren.
+
+ SwFrm *pRow = pFoll->GetFirstNonHeadlineRow(),
+ *pNxt;
+
+ SwFrm* pPrv = GetLastLower();
+
+ SwTwips nHeight = 0; //Gesamthoehe der eingefuegten Zeilen als Return.
+ while ( pRow )
+ {
+ pNxt = pRow->GetNext();
+ nHeight += (pRow->Frm().*fnRect->fnGetHeight)();
+ pRow->Remove();
+ pRow->_InvalidateAll();
+ pRow->InsertBehind( this, pPrv );
+ pRow->CheckDirChange();
+ pPrv = pRow;
+ pRow = pNxt;
+ }
+
+ SetFollow( pFoll->GetFollow() );
+ SetFollowFlowLine( pFoll->HasFollowFlowLine() );
+ delete pFoll;
+
+ Grow( nHeight );
+ }
+
+ return true;
+}
+
+/*************************************************************************
+|*
+|* SwTabFrm::MakeAll()
+|*
+|*************************************************************************/
+void MA_FASTCALL SwInvalidatePositions( SwFrm *pFrm, long nBottom )
+{
+ // LONG_MAX == nBottom means we have to calculate all
+ sal_Bool bAll = LONG_MAX == nBottom;
+ SWRECTFN( pFrm )
+ do
+ { pFrm->_InvalidatePos();
+ pFrm->_InvalidateSize();
+ if( pFrm->IsLayoutFrm() )
+ {
+ if ( ((SwLayoutFrm*)pFrm)->Lower() )
+ {
+ ::SwInvalidatePositions( ((SwLayoutFrm*)pFrm)->Lower(), nBottom);
+ // --> OD 2004-11-05 #i26945#
+ ::lcl_InvalidateLowerObjs( *(static_cast<SwLayoutFrm*>(pFrm)) );
+ // <--
+ }
+ }
+ else
+ pFrm->Prepare( PREP_ADJUST_FRM );
+ pFrm = pFrm->GetNext();
+ } while ( pFrm &&
+ ( bAll ||
+ (*fnRect->fnYDiff)( (pFrm->Frm().*fnRect->fnGetTop)(), nBottom ) < 0 ) );
+}
+
+void MA_FASTCALL SwInvalidateAll( SwFrm *pFrm, long nBottom )
+{
+ // LONG_MAX == nBottom means we have to calculate all
+ sal_Bool bAll = LONG_MAX == nBottom;
+ SWRECTFN( pFrm )
+ do
+ {
+ pFrm->_InvalidatePos();
+ pFrm->_InvalidateSize();
+ pFrm->_InvalidatePrt();
+ if( pFrm->IsLayoutFrm() )
+ {
+ // NEW TABLES
+ SwLayoutFrm* pToInvalidate = static_cast<SwLayoutFrm*>(pFrm);
+ SwCellFrm* pThisCell = dynamic_cast<SwCellFrm*>(pFrm);
+ if ( pThisCell && pThisCell->GetTabBox()->getRowSpan() < 1 )
+ {
+ pToInvalidate = & const_cast<SwCellFrm&>(pThisCell->FindStartEndOfRowSpanCell( true, true ));
+ pToInvalidate->_InvalidatePos();
+ pToInvalidate->_InvalidateSize();
+ pToInvalidate->_InvalidatePrt();
+ }
+
+ if ( pToInvalidate->Lower() )
+ ::SwInvalidateAll( pToInvalidate->Lower(), nBottom);
+ }
+ else
+ pFrm->Prepare( PREP_CLEAR );
+
+ pFrm = pFrm->GetNext();
+ } while ( pFrm &&
+ ( bAll ||
+ (*fnRect->fnYDiff)( (pFrm->Frm().*fnRect->fnGetTop)(), nBottom ) < 0 ) );
+}
+
+// --> collapsing borders FME 2005-05-27 #i29550#
+void lcl_InvalidateAllLowersPrt( SwLayoutFrm* pLayFrm )
+{
+ pLayFrm->_InvalidatePrt();
+ pLayFrm->_InvalidateSize();
+ pLayFrm->SetCompletePaint();
+
+ SwFrm* pFrm = pLayFrm->Lower();
+
+ while ( pFrm )
+ {
+ if ( pFrm->IsLayoutFrm() )
+ lcl_InvalidateAllLowersPrt( (SwLayoutFrm*)pFrm );
+ else
+ {
+ pFrm->_InvalidatePrt();
+ pFrm->_InvalidateSize();
+ pFrm->SetCompletePaint();
+ }
+
+ pFrm = pFrm->GetNext();
+ }
+}
+// <-- collapsing
+
+bool SwCntntFrm::CalcLowers( SwLayoutFrm* pLay, const SwLayoutFrm* pDontLeave,
+ long nBottom, bool bSkipRowSpanCells )
+{
+ if ( !pLay )
+ return sal_True;
+
+ // LONG_MAX == nBottom means we have to calculate all
+ bool bAll = LONG_MAX == nBottom;
+ bool bRet = sal_False;
+ SwCntntFrm *pCnt = pLay->ContainsCntnt();
+ SWRECTFN( pLay )
+
+ // FME 2007-08-30 #i81146# new loop control
+ sal_uInt16 nLoopControlRuns = 0;
+ const sal_uInt16 nLoopControlMax = 10;
+ const SwModify* pLoopControlCond = 0;
+
+ while ( pCnt && pDontLeave->IsAnLower( pCnt ) )
+ {
+ // --> OD 2004-11-23 #115759# - check, if a format of content frame is
+ // possible. Thus, 'copy' conditions, found at the beginning of
+ // <SwCntntFrm::MakeAll(..)>, and check these.
+ const bool bFormatPossible = !pCnt->IsJoinLocked() &&
+ ( !pCnt->IsTxtFrm() ||
+ !static_cast<SwTxtFrm*>(pCnt)->IsLocked() ) &&
+ ( pCnt->IsFollow() || !StackHack::IsLocked() );
+
+ // NEW TABLES
+ bool bSkipContent = false;
+ if ( bSkipRowSpanCells && pCnt->IsInTab() )
+ {
+ const SwFrm* pCell = pCnt->GetUpper();
+ while ( pCell && !pCell->IsCellFrm() )
+ pCell = pCell->GetUpper();
+ if ( pCell && 1 != static_cast<const SwCellFrm*>( pCell )->GetLayoutRowSpan() )
+ bSkipContent = true;
+ }
+
+ if ( bFormatPossible && !bSkipContent )
+ {
+ bRet |= !pCnt->IsValid();
+ // --> OD 2004-10-06 #i26945# - no extra invalidation of floating
+ // screen objects needed.
+ // Thus, delete call of method <SwFrm::InvalidateObjs( true )>
+ // <--
+ pCnt->Calc();
+ // OD 2004-05-11 #i28701# - usage of new method <::FormatObjsAtFrm(..)>
+ // to format the floating screen objects
+ // --> OD 2005-05-03 #i46941# - frame has to be valid
+ // Note: frame could be invalid after calling its format, if it's locked.
+ OSL_ENSURE( !pCnt->IsTxtFrm() ||
+ pCnt->IsValid() ||
+ static_cast<SwTxtFrm*>(pCnt)->IsJoinLocked(),
+ "<SwCntntFrm::CalcLowers(..)> - text frame invalid and not locked." );
+ if ( pCnt->IsTxtFrm() && pCnt->IsValid() )
+ {
+ // --> OD 2004-11-02 #i23129#, #i36347# - pass correct page frame to
+ // the object formatter
+ if ( !SwObjectFormatter::FormatObjsAtFrm( *pCnt,
+ *(pCnt->FindPageFrm()) ) )
+ // <--
+ {
+ if ( pCnt->GetRegisteredIn() == pLoopControlCond )
+ ++nLoopControlRuns;
+ else
+ {
+ nLoopControlRuns = 0;
+ pLoopControlCond = pCnt->GetRegisteredIn();
+ }
+
+ if ( nLoopControlRuns < nLoopControlMax )
+ {
+ // restart format with first content
+ pCnt = pLay->ContainsCntnt();
+ continue;
+ }
+
+#if OSL_DEBUG_LEVEL > 1
+ OSL_FAIL( "LoopControl in SwCntntFrm::CalcLowers" )
+#endif
+ }
+ }
+ pCnt->GetUpper()->Calc();
+ }
+ // <--
+ if( ! bAll && (*fnRect->fnYDiff)((pCnt->Frm().*fnRect->fnGetTop)(), nBottom) > 0 )
+ break;
+ pCnt = pCnt->GetNextCntntFrm();
+ }
+ return bRet;
+}
+
+// --> OD 2004-10-15 #i26945# - add parameter <_bOnlyRowsAndCells> to control
+// that only row and cell frames are formatted.
+sal_Bool MA_FASTCALL lcl_InnerCalcLayout( SwFrm *pFrm,
+ long nBottom,
+ bool _bOnlyRowsAndCells )
+{
+ // LONG_MAX == nBottom means we have to calculate all
+ sal_Bool bAll = LONG_MAX == nBottom;
+ sal_Bool bRet = sal_False;
+ const SwFrm* pOldUp = pFrm->GetUpper();
+ SWRECTFN( pFrm )
+ do
+ {
+ // --> OD 2004-10-15 #i26945# - parameter <_bOnlyRowsAndCells> controls,
+ // if only row and cell frames are formatted.
+ if ( pFrm->IsLayoutFrm() &&
+ ( !_bOnlyRowsAndCells || pFrm->IsRowFrm() || pFrm->IsCellFrm() ) )
+ // <--
+ {
+ // --> FME 2006-02-23 #130744# An invalid locked table frame will
+ // not be calculated => It will not become valid =>
+ // Loop in lcl_RecalcRow(). Therefore we do not consider them for bRet.
+ bRet |= !pFrm->IsValid() && ( !pFrm->IsTabFrm() || !static_cast<SwTabFrm*>(pFrm)->IsJoinLocked() );
+ // <--
+ pFrm->Calc();
+ if( static_cast<SwLayoutFrm*>(pFrm)->Lower() )
+ bRet |= lcl_InnerCalcLayout( static_cast<SwLayoutFrm*>(pFrm)->Lower(), nBottom);
+
+ // NEW TABLES
+ SwCellFrm* pThisCell = dynamic_cast<SwCellFrm*>(pFrm);
+ if ( pThisCell && pThisCell->GetTabBox()->getRowSpan() < 1 )
+ {
+ SwCellFrm& rToCalc = const_cast<SwCellFrm&>(pThisCell->FindStartEndOfRowSpanCell( true, true ));
+ bRet |= !rToCalc.IsValid();
+ rToCalc.Calc();
+ if ( rToCalc.Lower() )
+ bRet |= lcl_InnerCalcLayout( rToCalc.Lower(), nBottom);
+ }
+ }
+ pFrm = pFrm->GetNext();
+ } while( pFrm &&
+ ( bAll ||
+ (*fnRect->fnYDiff)((pFrm->Frm().*fnRect->fnGetTop)(), nBottom) < 0 )
+ && pFrm->GetUpper() == pOldUp );
+ return bRet;
+}
+
+void MA_FASTCALL lcl_RecalcRow( SwRowFrm& rRow, long nBottom )
+{
+ // --> OD 2004-10-05 #i26945# - For correct appliance of the 'straightforward
+ // object positioning process, it's needed to notify that the page frame,
+ // on which the given layout frame is in, is in its layout process.
+ SwPageFrm* pPageFrm = rRow.FindPageFrm();
+ if ( pPageFrm && !pPageFrm->IsLayoutInProgress() )
+ pPageFrm->SetLayoutInProgress( true );
+ else
+ pPageFrm = 0L;
+ // <--
+
+ // FME 2007-08-30 #i81146# new loop control
+ sal_uInt16 nLoopControlRuns_1 = 0;
+ sal_uInt16 nLoopControlStage_1 = 0;
+ const sal_uInt16 nLoopControlMax = 10;
+
+ bool bCheck = true;
+ do
+ {
+ // FME 2007-08-30 #i81146# new loop control
+ sal_uInt16 nLoopControlRuns_2 = 0;
+ sal_uInt16 nLoopControlStage_2 = 0;
+
+ while( lcl_InnerCalcLayout( &rRow, nBottom ) )
+ {
+ if ( ++nLoopControlRuns_2 > nLoopControlMax )
+ {
+#if OSL_DEBUG_LEVEL > 1
+ OSL_ENSURE( 0 != nLoopControlStage_2, "LoopControl_2 in lcl_RecalcRow: Stage 1!" );
+ OSL_ENSURE( 1 != nLoopControlStage_2, "LoopControl_2 in lcl_RecalcRow: Stage 2!!" );
+ OSL_ENSURE( 2 > nLoopControlStage_2, "LoopControl_2 in lcl_RecalcRow: Stage 3!!!" );
+#endif
+ rRow.ValidateThisAndAllLowers( nLoopControlStage_2++ );
+ nLoopControlRuns_2 = 0;
+ if( nLoopControlStage_2 > 2 )
+ break;
+ }
+
+ bCheck = true;
+ }
+
+ if( bCheck )
+ {
+ // --> OD 2004-11-23 #115759# - force another format of the
+ // lowers, if at least one of it was invalid.
+ bCheck = SwCntntFrm::CalcLowers( &rRow, rRow.GetUpper(), nBottom, true );
+ // <--
+
+ // NEW TABLES
+ // First we calculate the cells with row span of < 1, afterwards
+ // all cells with row span of > 1:
+ for ( int i = 0; i < 2; ++i )
+ {
+ SwCellFrm* pCellFrm = static_cast<SwCellFrm*>(rRow.Lower());
+ while ( pCellFrm )
+ {
+ const bool bCalc = 0 == i ?
+ pCellFrm->GetLayoutRowSpan() < 1 :
+ pCellFrm->GetLayoutRowSpan() > 1;
+
+ if ( bCalc )
+ {
+ SwCellFrm& rToRecalc = 0 == i ?
+ const_cast<SwCellFrm&>(pCellFrm->FindStartEndOfRowSpanCell( true, true )) :
+ *pCellFrm;
+ bCheck |= SwCntntFrm::CalcLowers( &rToRecalc, &rToRecalc, nBottom, false );
+ }
+
+ pCellFrm = static_cast<SwCellFrm*>(pCellFrm->GetNext());
+ }
+ }
+
+ if ( bCheck )
+ {
+ if ( ++nLoopControlRuns_1 > nLoopControlMax )
+ {
+#if OSL_DEBUG_LEVEL > 1
+ OSL_ENSURE( 0 != nLoopControlStage_1, "LoopControl_1 in lcl_RecalcRow: Stage 1!" );
+ OSL_ENSURE( 1 != nLoopControlStage_1, "LoopControl_1 in lcl_RecalcRow: Stage 2!!" );
+ OSL_ENSURE( 2 > nLoopControlStage_1, "LoopControl_1 in lcl_RecalcRow: Stage 3!!!" );
+#endif
+ rRow.ValidateThisAndAllLowers( nLoopControlStage_1++ );
+ nLoopControlRuns_1 = 0;
+ if( nLoopControlStage_1 > 2 )
+ break;
+ }
+
+ continue;
+ }
+ }
+ break;
+ } while( true );
+
+ // --> OD 2004-10-05 #i26945#
+ if ( pPageFrm )
+ pPageFrm->SetLayoutInProgress( false );
+ // <--
+}
+
+void MA_FASTCALL lcl_RecalcTable( SwTabFrm& rTab,
+ SwLayoutFrm *pFirstRow,
+ SwLayNotify &rNotify )
+{
+ if ( rTab.Lower() )
+ {
+ if ( !pFirstRow )
+ {
+ pFirstRow = (SwLayoutFrm*)rTab.Lower();
+ rNotify.SetLowersComplete( sal_True );
+ }
+ ::SwInvalidatePositions( pFirstRow, LONG_MAX );
+ lcl_RecalcRow( static_cast<SwRowFrm&>(*pFirstRow), LONG_MAX );
+ }
+}
+
+// This is a new function to check the first condition whether
+// a tab frame may move backward. It replaces the formerly used
+// GetIndPrev(), which did not work correctly for #i5947#
+bool lcl_NoPrev( const SwFrm& rFrm )
+{
+ // --> OD 2007-09-04 #i79774#, #b6596954#
+ // skip empty sections on investigation of direct previous frame.
+ // use information, that at least one empty section is skipped in the following code.
+ bool bSkippedDirectPrevEmptySection( false );
+ if ( rFrm.GetPrev() )
+ {
+ const SwFrm* pPrev( rFrm.GetPrev() );
+ while ( pPrev &&
+ pPrev->IsSctFrm() &&
+ !dynamic_cast<const SwSectionFrm*>(pPrev)->GetSection() )
+ {
+ pPrev = pPrev->GetPrev();
+ bSkippedDirectPrevEmptySection = true;
+ }
+ if ( pPrev )
+ {
+ return false;
+ }
+ }
+
+ if ( ( !bSkippedDirectPrevEmptySection && !rFrm.GetIndPrev() ) ||
+ ( bSkippedDirectPrevEmptySection &&
+ ( !rFrm.IsInSct() || !rFrm._GetIndPrev() ) ) )
+ {
+ return true;
+ }
+ // <--
+
+ // I do not have a direct prev, but I have an indirect prev.
+ // In section frames I have to check if I'm located inside
+ // the first column:
+ if ( rFrm.IsInSct() )
+ {
+ const SwFrm* pSct = rFrm.GetUpper();
+ if ( pSct && pSct->IsColBodyFrm() &&
+ (pSct = pSct->GetUpper()->GetUpper())->IsSctFrm() )
+ {
+ const SwFrm* pPrevCol = rFrm.GetUpper()->GetUpper()->GetPrev();
+ if ( pPrevCol )
+ // I'm not inside the first column and do not have a direct
+ // prev. I can try to go backward.
+ return true;
+ }
+ }
+
+ return false;
+}
+
+#define KEEPTAB ( !GetFollow() && !IsFollow() )
+
+// --> OD 2005-09-28 #b6329202# - helper method to find next content frame of
+// a table frame and format it to assure keep attribute.
+// method return true, if a next content frame is formatted.
+// Precondition: The given table frame hasn't a follow and isn't a follow.
+SwFrm* lcl_FormatNextCntntForKeep( SwTabFrm* pTabFrm )
+{
+ // find next content, table or section
+ SwFrm* pNxt = pTabFrm->FindNext();
+
+ // skip empty sections
+ while ( pNxt && pNxt->IsSctFrm() &&
+ !static_cast<SwSectionFrm*>(pNxt)->GetSection() )
+ {
+ pNxt = pNxt->FindNext();
+ }
+
+ // if found next frame is a section, get its first content.
+ if ( pNxt && pNxt->IsSctFrm() )
+ {
+ pNxt = static_cast<SwSectionFrm*>(pNxt)->ContainsAny();
+ }
+
+ // format found next frame.
+ // if table frame is inside another table, method <SwFrm::MakeAll()> is
+ // called to avoid that the superior table frame is formatted.
+ if ( pNxt )
+ {
+ if ( pTabFrm->GetUpper()->IsInTab() )
+ pNxt->MakeAll();
+ else
+ pNxt->Calc();
+ }
+
+ return pNxt;
+}
+
+void SwTabFrm::MakeAll()
+{
+ if ( IsJoinLocked() || StackHack::IsLocked() || StackHack::Count() > 50 )
+ return;
+
+ if ( HasFollow() )
+ {
+ SwTabFrm* pFollowFrm = (SwTabFrm*)GetFollow();
+ OSL_ENSURE( !pFollowFrm->IsJoinLocked() || !pFollowFrm->IsRebuildLastLine(),
+ "SwTabFrm::MakeAll for master while follow is in RebuildLastLine()" );
+ if ( pFollowFrm->IsJoinLocked() && pFollowFrm->IsRebuildLastLine() )
+ return;
+ }
+
+ PROTOCOL_ENTER( this, PROT_MAKEALL, 0, 0 )
+
+ LockJoin(); //Ich lass mich nicht unterwegs vernichten.
+ SwLayNotify aNotify( this ); //uebernimmt im DTor die Benachrichtigung
+ // If pos is invalid, we have to call a SetInvaKeep at aNotify.
+ // Otherwise the keep atribute would not work in front of a table.
+ const sal_Bool bOldValidPos = GetValidPosFlag();
+
+ //Wenn mein direkter Nachbar gleichzeitig mein Follow ist
+ //verleibe ich mir das Teil ein.
+ // OD 09.04.2003 #108698# - join all follows, which are placed on the
+ // same page/column.
+ // OD 29.04.2003 #109213# - join follow, only if join for the follow
+ // is not locked. Otherwise, join will not be performed and this loop
+ // will be endless.
+ while ( GetNext() && GetNext() == GetFollow() &&
+ !GetFollow()->IsJoinLocked()
+ )
+ {
+ if ( HasFollowFlowLine() )
+ RemoveFollowFlowLine();
+ Join();
+ }
+
+ // The bRemoveFollowFlowLinePending is set if the split attribute of the
+ // last line is set:
+ if ( IsRemoveFollowFlowLinePending() && HasFollowFlowLine() )
+ {
+ if ( RemoveFollowFlowLine() )
+ Join();
+ SetRemoveFollowFlowLinePending( sal_False );
+ }
+
+ if ( bResizeHTMLTable ) //Optimiertes Zusammenspiel mit Grow/Shrink des Inhaltes
+ {
+ bResizeHTMLTable = sal_False;
+ SwHTMLTableLayout *pLayout = GetTable()->GetHTMLTableLayout();
+ if ( pLayout )
+ bCalcLowers = pLayout->Resize(
+ pLayout->GetBrowseWidthByTabFrm( *this ), sal_False );
+ }
+
+
+ sal_Bool bMakePage = sal_True; //solange sal_True kann eine neue Seite
+ //angelegt werden (genau einmal)
+ sal_Bool bMovedBwd = sal_False; //Wird sal_True wenn der Frame zurueckfliesst
+ sal_Bool bMovedFwd = sal_False; //solange sal_False kann der Frm zurueck-
+ //fliessen (solange, bis er einmal
+ //vorwaerts ge'moved wurde).
+ sal_Bool bSplit = sal_False; //Wird sal_True wenn der Frm gesplittet wurde.
+ const sal_Bool bFtnsInDoc = 0 != GetFmt()->GetDoc()->GetFtnIdxs().Count();
+ sal_Bool bMoveable;
+ const sal_Bool bFly = IsInFly();
+
+ SwBorderAttrAccess *pAccess= new SwBorderAttrAccess( SwFrm::GetCache(), this );
+ const SwBorderAttrs *pAttrs = pAccess->Get();
+
+ // The beloved keep attribute
+ const bool bKeep = IsKeep( pAttrs->GetAttrSet() );
+
+ // All rows should keep together
+ // OD 2004-05-25 #i21478# - don't split table, if it has to keep with next
+ const bool bDontSplit = !IsFollow() &&
+ ( !GetFmt()->GetLayoutSplit().GetValue() || bKeep );
+
+ // The number of repeated headlines
+ const sal_uInt16 nRepeat = GetTable()->GetRowsToRepeat();
+
+ // This flag indicates that we are allowed to try to split the
+ // table rows.
+ bool bTryToSplit = true;
+
+ // --> FME 2006-02-16 #131283#
+ // Indicates that two individual rows may keep together, based on the keep
+ // attribute set at the first paragraph in the first cell.
+ const bool bTableRowKeep = !bDontSplit && GetFmt()->GetDoc()->get(IDocumentSettingAccess::TABLE_ROW_KEEP);
+
+ // The Magic Move: Used for the table row keep feature.
+ // If only the last row of the table wants to keep (implicitely by setting
+ // keep for the first paragraph in the first cell), and this table does
+ // not have a next, the last line will be cut. Loop prevention: Only
+ // one try.
+ bool bLastRowHasToMoveToFollow = false;
+ bool bLastRowMoveNoMoreTries = false;
+
+ // Join follow table, if this table is not allowed to split:
+ if ( bDontSplit )
+ {
+ while ( GetFollow() && !GetFollow()->IsJoinLocked() )
+ {
+ if ( HasFollowFlowLine() )
+ RemoveFollowFlowLine();
+ Join();
+ }
+ }
+
+ // Join follow table, if this does not have enough (repeated) lines:
+ if ( nRepeat )
+ {
+ if( GetFollow() && !GetFollow()->IsJoinLocked() &&
+ 0 == GetFirstNonHeadlineRow() )
+ {
+ if ( HasFollowFlowLine() )
+ RemoveFollowFlowLine();
+ Join();
+ }
+ }
+
+ // Join follow table, if last row of this table should keep:
+ if ( bTableRowKeep && GetFollow() && !GetFollow()->IsJoinLocked() )
+ {
+ const SwRowFrm* pTmpRow = static_cast<const SwRowFrm*>(GetLastLower());
+ if ( pTmpRow && pTmpRow->ShouldRowKeepWithNext() )
+ {
+ if ( HasFollowFlowLine() )
+ RemoveFollowFlowLine();
+ Join();
+ }
+ }
+
+ //Einen Frischling moven wir gleich schon einmal vorwaerts...
+ if ( !Frm().Top() && IsFollow() )
+ {
+ SwFrm *pPre = GetPrev();
+ if ( pPre && pPre->IsTabFrm() && ((SwTabFrm*)pPre)->GetFollow() == this)
+ {
+ if ( !MoveFwd( bMakePage, sal_False ) )
+ bMakePage = sal_False;
+ bMovedFwd = sal_True;
+ }
+ }
+
+ int nUnSplitted = 5; // Just another loop control :-(
+ SWRECTFN( this )
+ while ( !bValidPos || !bValidSize || !bValidPrtArea )
+ {
+ if ( sal_True == (bMoveable = IsMoveable()) )
+ if ( CheckMoveFwd( bMakePage, bKeep && KEEPTAB, bMovedBwd ) )
+ {
+ bMovedFwd = sal_True;
+ bCalcLowers = sal_True;
+ // --> OD 2009-08-12 #i99267#
+ // reset <bSplit> after forward move to assure that follows
+ // can be joined, if further space is available.
+ bSplit = sal_False;
+ // <--
+ }
+
+ Point aOldPos( (Frm().*fnRect->fnGetPos)() );
+ MakePos();
+
+ if ( aOldPos != (Frm().*fnRect->fnGetPos)() )
+ {
+ if ( aOldPos.Y() != (Frm().*fnRect->fnGetTop)() )
+ {
+ SwHTMLTableLayout *pLayout = GetTable()->GetHTMLTableLayout();
+ if( pLayout )
+ {
+ delete pAccess;
+ bCalcLowers |= pLayout->Resize(
+ pLayout->GetBrowseWidthByTabFrm( *this ), sal_False );
+ pAccess = new SwBorderAttrAccess( SwFrm::GetCache(), this );
+ pAttrs = pAccess->Get();
+ }
+
+ bValidPrtArea = sal_False;
+ aNotify.SetLowersComplete( sal_False );
+ }
+ SwFrm *pPre;
+ if ( bKeep || (0 != (pPre = FindPrev()) &&
+ pPre->GetAttrSet()->GetKeep().GetValue()) )
+ {
+ bCalcLowers = sal_True;
+ // --> OD 2009-03-06 #i99267#
+ // reset <bSplit> after forward move to assure that follows
+ // can be joined, if further space is available.
+ bSplit = sal_False;
+ // <--
+ }
+ }
+
+ //Wir muessen die Hoehe der ersten Zeile kennen, denn nur wenn diese
+ //kleiner wird muss ggf. der Master angestossen werden um noetigenfalls
+ //die Zeile aufzunehmen.
+ long n1StLineHeight = 0;
+ if ( IsFollow() )
+ {
+ SwFrm* pFrm = GetFirstNonHeadlineRow();
+ if ( pFrm )
+ n1StLineHeight = (pFrm->Frm().*fnRect->fnGetHeight)();
+ }
+
+ if ( !bValidSize || !bValidPrtArea )
+ {
+ const long nOldPrtWidth = (Prt().*fnRect->fnGetWidth)();
+ const long nOldFrmWidth = (Frm().*fnRect->fnGetWidth)();
+ const Point aOldPrtPos = (Prt().*fnRect->fnGetPos)();
+ Format( pAttrs );
+
+ SwHTMLTableLayout *pLayout = GetTable()->GetHTMLTableLayout();
+ if ( pLayout &&
+ ((Prt().*fnRect->fnGetWidth)() != nOldPrtWidth ||
+ (Frm().*fnRect->fnGetWidth)() != nOldFrmWidth) )
+ {
+ delete pAccess;
+ bCalcLowers |= pLayout->Resize(
+ pLayout->GetBrowseWidthByTabFrm( *this ), sal_False );
+ pAccess= new SwBorderAttrAccess( SwFrm::GetCache(), this );
+ pAttrs = pAccess->Get();
+ }
+ if ( aOldPrtPos != (Prt().*fnRect->fnGetPos)() )
+ aNotify.SetLowersComplete( sal_False );
+ }
+
+ //Wenn ich der erste einer Kette bin koennte ich mal sehen ob
+ //ich zurueckfliessen kann (wenn ich mich ueberhaupt bewegen soll).
+ //Damit es keine Oszillation gibt, darf ich nicht gerade vorwaerts
+ //geflosssen sein.
+ if ( !bMovedFwd && (bMoveable || bFly) && lcl_NoPrev( *this ) )
+ {
+ //Bei Follows muss der Master benachrichtigt
+ //werden. Der Follow muss nur dann Moven, wenn er leere Blaetter
+ //ueberspringen muss.
+ if ( IsFollow() )
+ {
+ //Nur wenn die Hoehe der ersten Zeile kleiner geworder ist.
+ SwFrm *pFrm = GetFirstNonHeadlineRow();
+ if( pFrm && n1StLineHeight >(pFrm->Frm().*fnRect->fnGetHeight )() )
+ {
+ SwTabFrm *pMaster = (SwTabFrm*)FindMaster();
+ sal_Bool bDummy;
+ if ( ShouldBwdMoved( pMaster->GetUpper(), sal_False, bDummy ) )
+ pMaster->InvalidatePos();
+ }
+ }
+ SwFtnBossFrm *pOldBoss = bFtnsInDoc ? FindFtnBossFrm( sal_True ) : 0;
+ sal_Bool bReformat;
+ if ( MoveBwd( bReformat ) )
+ {
+ SWREFRESHFN( this )
+ bMovedBwd = sal_True;
+ aNotify.SetLowersComplete( sal_False );
+ if ( bFtnsInDoc )
+ MoveLowerFtns( 0, pOldBoss, 0, sal_True );
+ if ( bReformat || bKeep )
+ {
+ long nOldTop = (Frm().*fnRect->fnGetTop)();
+ MakePos();
+ if( nOldTop != (Frm().*fnRect->fnGetTop)() )
+ {
+ SwHTMLTableLayout *pHTMLLayout =
+ GetTable()->GetHTMLTableLayout();
+ if( pHTMLLayout )
+ {
+ delete pAccess;
+ bCalcLowers |= pHTMLLayout->Resize(
+ pHTMLLayout->GetBrowseWidthByTabFrm( *this ),
+ sal_False );
+
+ pAccess= new SwBorderAttrAccess(
+ SwFrm::GetCache(), this );
+ pAttrs = pAccess->Get();
+ }
+
+ bValidPrtArea = sal_False;
+ Format( pAttrs );
+ }
+ lcl_RecalcTable( *this, 0, aNotify );
+ bLowersFormatted = sal_True;
+ if ( bKeep && KEEPTAB )
+ {
+ // --> OD 2005-09-28 #b6329202#
+ // Consider case that table is inside another table,
+ // because it has to be avoided, that superior table
+ // is formatted.
+ // Thus, find next content, table or section
+ // and, if a section is found, get its first
+ // content.
+ if ( 0 != lcl_FormatNextCntntForKeep( this ) && !GetNext() )
+ {
+ bValidPos = sal_False;
+ }
+ // <--
+ }
+ }
+ }
+ }
+
+ //Wieder ein Wert ungueltig? - dann nochmal das ganze...
+ if ( !bValidPos || !bValidSize || !bValidPrtArea )
+ continue;
+
+ // check, if calculation of table frame is ready.
+
+ /// OD 23.10.2002 #103517# - Local variable <nDistanceToUpperPrtBottom>
+ /// Introduce local variable and init it with the distance from the
+ /// table frame bottom to the bottom of the upper printing area.
+ /// Note: negative values denotes the situation that table frame doesn't
+ /// fit in its upper.
+
+ SwTwips nDistanceToUpperPrtBottom =
+ (Frm().*fnRect->fnBottomDist)( (GetUpper()->*fnRect->fnGetPrtBottom)());
+
+ /// OD 23.10.2002 #103517# - In online layout try to grow upper of table
+ /// frame, if table frame doesn't fit in its upper.
+ const ViewShell *pSh = getRootFrm()->GetCurrShell();
+ const bool bBrowseMode = pSh && pSh->GetViewOptions()->getBrowseMode();
+ if ( nDistanceToUpperPrtBottom < 0 && bBrowseMode )
+ {
+ if ( GetUpper()->Grow( -nDistanceToUpperPrtBottom ) )
+ {
+ // upper is grown --> recalculate <nDistanceToUpperPrtBottom>
+ nDistanceToUpperPrtBottom =
+ (Frm().*fnRect->fnBottomDist)( (GetUpper()->*fnRect->fnGetPrtBottom)());
+ }
+ }
+
+ // If there is still some space left in the upper, we check if we
+ // can join some rows of the follow.
+ // Setting bLastRowHasToMoveToFollow to true means we want to force
+ // the table to be split! Only skip this if condition once.
+ if( nDistanceToUpperPrtBottom >= 0 && !bLastRowHasToMoveToFollow )
+ {
+ // OD 23.10.2002 - translate german commentary
+ // If there is space left in the upper printing area, join as for trial
+ // at least one further row of an existing follow.
+ if ( !bSplit && GetFollow() )
+ {
+ sal_Bool bDummy;
+ if ( GetFollow()->ShouldBwdMoved( GetUpper(), sal_False, bDummy ) )
+ {
+ SwFrm *pTmp = GetUpper();
+ SwTwips nDeadLine = (pTmp->*fnRect->fnGetPrtBottom)();
+ if ( bBrowseMode )
+ nDeadLine += pTmp->Grow( LONG_MAX, sal_True );
+ if( (Frm().*fnRect->fnBottomDist)( nDeadLine ) > 0 )
+ {
+ //
+ // First, we remove an existing follow flow line.
+ //
+ if ( HasFollowFlowLine() )
+ {
+ SwFrm* pLastLine = const_cast<SwFrm*>(GetLastLower());
+ RemoveFollowFlowLine();
+ // invalidate and rebuild last row
+ if ( pLastLine )
+ {
+ ::SwInvalidateAll( pLastLine, LONG_MAX );
+ SetRebuildLastLine( sal_True );
+ lcl_RecalcRow( static_cast<SwRowFrm&>(*pLastLine), LONG_MAX );
+ SetRebuildLastLine( sal_False );
+ }
+
+ SwFrm* pRow = GetFollow()->GetFirstNonHeadlineRow();
+
+ if ( !pRow || !pRow->GetNext() )
+ //Der Follow wird leer und damit ueberfluessig.
+ Join();
+
+ continue;
+ }
+
+ //
+ // If there is no follow flow line, we move the first
+ // row in the follow table to the master table.
+ //
+ SwRowFrm *pRow = GetFollow()->GetFirstNonHeadlineRow();
+
+ //Der Follow wird leer und damit ueberfluessig.
+ if ( !pRow )
+ {
+ Join();
+ continue;
+ }
+
+ const SwTwips nOld = (Frm().*fnRect->fnGetHeight)();
+ long nRowsToMove = lcl_GetMaximumLayoutRowSpan( *pRow );
+ SwFrm* pRowToMove = pRow;
+
+ while ( pRowToMove && nRowsToMove-- > 0 )
+ {
+ const sal_Bool bMoveFtns = bFtnsInDoc && !GetFollow()->IsJoinLocked();
+
+ SwFtnBossFrm *pOldBoss = 0;
+ if ( bMoveFtns )
+ pOldBoss = pRowToMove->FindFtnBossFrm( sal_True );
+
+ SwFrm* pNextRow = pRowToMove->GetNext();
+
+ if ( !pNextRow )
+ //Der Follow wird leer und damit ueberfluessig.
+ Join();
+ else
+ {
+ pRowToMove->Cut();
+ pRowToMove->Paste( this );
+ }
+
+ //Die Fussnoten verschieben!
+ if ( bMoveFtns )
+ if ( ((SwLayoutFrm*)pRowToMove)->MoveLowerFtns(
+ 0, pOldBoss, FindFtnBossFrm( sal_True ), sal_True ) )
+ GetUpper()->Calc();
+
+ pRowToMove = pNextRow;
+ }
+
+ if ( nOld != (Frm().*fnRect->fnGetHeight)() )
+ lcl_RecalcTable( *this, (SwLayoutFrm*)pRow, aNotify );
+
+ continue;
+ }
+ }
+ }
+ else if ( KEEPTAB )
+ {
+ bool bFormat = false;
+ if ( bKeep )
+ bFormat = true;
+ else if ( bTableRowKeep && !bLastRowMoveNoMoreTries )
+ {
+ // We only want to give the last row one chance to move
+ // to the follow table. Set the flag as early as possible:
+ bLastRowMoveNoMoreTries = true;
+
+ // The last line of the table has to be cut off if:
+ // 1. The table does not want to keep with its next
+ // 2. The compatibility option is set and the table is allowed to split
+ // 3. We did not already cut off the last row
+ // 4. There is not break after attribute set at the table
+ // 5. There is no break before attribute set behind the table
+ // 6. There is no section change behind the table (see IsKeep)
+ // 7. The last table row wants to keep with its next.
+ const SwRowFrm* pLastRow = static_cast<const SwRowFrm*>(GetLastLower());
+ if ( pLastRow && IsKeep( pAttrs->GetAttrSet(), true ) &&
+ pLastRow->ShouldRowKeepWithNext() )
+ bFormat = true;
+ }
+
+ if ( bFormat )
+ {
+ delete pAccess;
+
+ // --> OD 2005-09-28 #b6329202#
+ // Consider case that table is inside another table, because
+ // it has to be avoided, that superior table is formatted.
+ // Thus, find next content, table or section and, if a section
+ // is found, get its first content.
+ const SwFrm* pTmpNxt = lcl_FormatNextCntntForKeep( this );
+ // <--
+
+ pAccess= new SwBorderAttrAccess( SwFrm::GetCache(), this );
+ pAttrs = pAccess->Get();
+
+ // The last row wants to keep with the frame behind the table.
+ // Check if the next frame is on a different page and valid.
+ // In this case we do a magic trick:
+ if ( !bKeep && !GetNext() && pTmpNxt && pTmpNxt->IsValid() )
+ {
+ bValidPos = sal_False;
+ bLastRowHasToMoveToFollow = true;
+ }
+ }
+ }
+
+ if ( IsValid() )
+ {
+ if ( bCalcLowers )
+ {
+ lcl_RecalcTable( *this, 0, aNotify );
+ bLowersFormatted = sal_True;
+ bCalcLowers = sal_False;
+ }
+ else if ( bONECalcLowers )
+ {
+ lcl_RecalcRow( static_cast<SwRowFrm&>(*Lower()), LONG_MAX );
+ bONECalcLowers = sal_False;
+ }
+ }
+ continue;
+ }
+
+ //Ich passe nicht mehr in meinen Uebergeordneten, also ist es jetzt
+ //an der Zeit moeglichst konstruktive Veranderungen vorzunehmen
+
+ //Wenn ich den uebergeordneten Frm nicht verlassen darf, habe
+ //ich ein Problem; Frei nach Artur Dent tun wir das einzige das man
+ //mit einen nicht loesbaren Problem tun kann: wir ignorieren es - und
+ //zwar mit aller Kraft.
+ if ( !bMoveable )
+ {
+ if ( bCalcLowers && IsValid() )
+ {
+ lcl_RecalcTable( *this, 0, aNotify );
+ bLowersFormatted = sal_True;
+ bCalcLowers = sal_False;
+ }
+ else if ( bONECalcLowers )
+ {
+ lcl_RecalcRow( static_cast<SwRowFrm&>(*Lower()), LONG_MAX );
+ bONECalcLowers = sal_False;
+ }
+
+ // It does not make sense to cut off the last line if we are
+ // not moveable:
+ bLastRowHasToMoveToFollow = false;
+
+ continue;
+ }
+
+ if ( bCalcLowers && IsValid() )
+ {
+ lcl_RecalcTable( *this, 0, aNotify );
+ bLowersFormatted = sal_True;
+ bCalcLowers = sal_False;
+ if( !IsValid() )
+ continue;
+ }
+
+ //
+ // First try to split the table. Condition:
+ // 1. We have at least one non headline row
+ // 2. If this row wants to keep, we need an additional row
+ // 3. The table is allowed to split or we do not have an pIndPrev:
+ //
+ SwFrm* pIndPrev = GetIndPrev();
+ const SwRowFrm* pFirstNonHeadlineRow = GetFirstNonHeadlineRow();
+
+ if ( pFirstNonHeadlineRow && nUnSplitted > 0 &&
+ ( !bTableRowKeep || pFirstNonHeadlineRow->GetNext() || !pFirstNonHeadlineRow->ShouldRowKeepWithNext() ) &&
+ ( !bDontSplit || !pIndPrev ) )
+ {
+ // --> FME 2004-06-03 #i29438#
+ // Special DoNotSplit case:
+ // We better avoid splitting of a row frame if we are inside a columned
+ // section which has a height of 0, because this is not growable and thus
+ // all kinds of unexpected things could happen.
+ if ( IsInSct() &&
+ (FindSctFrm())->Lower()->IsColumnFrm() &&
+ 0 == (GetUpper()->Frm().*fnRect->fnGetHeight)() )
+ {
+ bTryToSplit = false;
+ }
+ // <--
+
+ // 1. Try: bTryToSplit = true => Try to split the row.
+ // 2. Try: bTryToSplit = false => Split the table between the rows.
+ if ( pFirstNonHeadlineRow->GetNext() || bTryToSplit )
+ {
+ SwTwips nDeadLine = (GetUpper()->*fnRect->fnGetPrtBottom)();
+ if( IsInSct() || GetUpper()->IsInTab() ) // TABLE IN TABLE)
+ nDeadLine = (*fnRect->fnYInc)( nDeadLine,
+ GetUpper()->Grow( LONG_MAX, sal_True ) );
+
+ ::lcl_RecalcRow( static_cast<SwRowFrm&>(*Lower()), nDeadLine );
+ bLowersFormatted = sal_True;
+ aNotify.SetLowersComplete( sal_True );
+
+ // One more check if its really necessary to split the table.
+ // 1. The table either has to exceed the deadline or
+ // 2. We explicitly want to cut off the last row.
+ if( (Frm().*fnRect->fnBottomDist)( nDeadLine ) > 0 && !bLastRowHasToMoveToFollow )
+ {
+ continue;
+ }
+
+ // Set to false again as early as possible.
+ bLastRowHasToMoveToFollow = false;
+
+ // --> FME 2005-08-03 #i52781#
+ // YaSC - Yet another special case:
+ // If our upper is inside a table cell which is not allowed
+ // to split, we do not try to split:
+ if ( GetUpper()->IsInTab() )
+ {
+ const SwFrm* pTmpRow = GetUpper();
+ while ( pTmpRow && !pTmpRow->IsRowFrm() )
+ pTmpRow = pTmpRow->GetUpper();
+ if ( pTmpRow && !static_cast<const SwRowFrm*>(pTmpRow)->IsRowSplitAllowed() )
+ continue;
+ }
+ // <--
+
+ sal_uInt16 nMinNumOfLines = nRepeat;
+
+ if ( bTableRowKeep )
+ {
+ const SwRowFrm* pTmpRow = pFirstNonHeadlineRow;
+ while ( pTmpRow && pTmpRow->ShouldRowKeepWithNext() )
+ {
+ ++nMinNumOfLines;
+ pTmpRow = static_cast<const SwRowFrm*>(pTmpRow->GetNext());
+ }
+ // Check if all lines want to keep together and we
+ // have a pIndPrev. In this case we set nDeadLine
+ // to 0, forcing the table to move forward.
+ if ( !pTmpRow && pIndPrev )
+ nDeadLine = 0;
+ }
+
+ if ( !bTryToSplit )
+ ++nMinNumOfLines;
+
+ const SwTwips nBreakLine = (*fnRect->fnYInc)(
+ (Frm().*fnRect->fnGetTop)(),
+ (this->*fnRect->fnGetTopMargin)() +
+ lcl_GetHeightOfRows( GetLower(), nMinNumOfLines ) );
+
+ // Some more checks if we want to call the split algorithm or not:
+ // The repeating lines / keeping lines still fit into the upper or
+ // if we do not have an (in)direkt Prev, we split anyway.
+ if( (*fnRect->fnYDiff)(nDeadLine, nBreakLine) >=0 || !pIndPrev )
+ {
+ aNotify.SetLowersComplete( sal_False );
+ bSplit = sal_True;
+
+ //
+ // An existing follow flow line has to be removed.
+ //
+ if ( HasFollowFlowLine() )
+ RemoveFollowFlowLine();
+
+ const bool bSplitError = !Split( nDeadLine, bTryToSplit, bTableRowKeep );
+ if( !bTryToSplit && !bSplitError && nUnSplitted > 0 )
+ --nUnSplitted;
+
+ // --> FME 2004-06-09 #i29771# Two tries to split the table:
+ // If an error occurred during splitting. We start a second
+ // try, this time without splitting of table rows.
+ if ( bSplitError )
+ {
+ if ( HasFollowFlowLine() )
+ RemoveFollowFlowLine();
+ }
+
+ // --> FME 2005-02-10 #119477#
+ // If splitting the table was successfull or not,
+ // we do not want to have 'empty' follow tables.
+ if ( GetFollow() && !GetFollow()->GetFirstNonHeadlineRow() )
+ Join();
+ // <--
+
+
+ // We want to restore the situation before the failed
+ // split operation as good as possible. Therefore we
+ // do some more calculations. Note: Restricting this
+ // to nDeadLine may not be enough.
+ if ( bSplitError && bTryToSplit ) // no restart if we did not try to split: i72847, i79426
+ {
+ lcl_RecalcRow( static_cast<SwRowFrm&>(*Lower()), LONG_MAX );
+ bValidPos = sal_False;
+ bTryToSplit = false;
+ continue;
+ }
+ // <--
+
+ bTryToSplit = !bSplitError;
+
+ //Damit es nicht zu Oszillationen kommt, muss der
+ //Follow gleich gueltig gemacht werden.
+ if ( GetFollow() )
+ {
+ // --> OD 2007-11-30 #i80924#
+ // After a successful split assure that the first row
+ // is invalid. When graphics are present, this isn't hold.
+ // Note: defect i80924 could also be fixed, if it is
+ // assured, that <SwLayNotify::bLowersComplete> is only
+ // set, if all lower are valid *and* are correct laid out.
+ if ( !bSplitError && GetFollow()->GetLower() )
+ {
+ GetFollow()->GetLower()->InvalidatePos();
+ }
+ // <--
+ SWRECTFNX( GetFollow() )
+
+ static sal_uInt8 nStack = 0;
+ if ( !StackHack::IsLocked() && nStack < 4 )
+ {
+ ++nStack;
+ StackHack aHack;
+ delete pAccess;
+
+ GetFollow()->MakeAll();
+
+ pAccess= new SwBorderAttrAccess( SwFrm::GetCache(), this );
+ pAttrs = pAccess->Get();
+
+ ((SwTabFrm*)GetFollow())->SetLowersFormatted(sal_False);
+ // --> OD 2005-03-30 #i43913# - lock follow table
+ // to avoid its formatting during the format of
+ // its content.
+ const bool bOldJoinLock = GetFollow()->IsJoinLocked();
+ GetFollow()->LockJoin();
+ // <--
+ ::lcl_RecalcRow( static_cast<SwRowFrm&>(*GetFollow()->Lower()),
+ (GetFollow()->GetUpper()->Frm().*fnRectX->fnGetBottom)() );
+ // --> OD 2005-03-30 #i43913#
+ // --> FME 2006-04-05 #i63632# Do not unlock the
+ // follow if it wasn't locked before.
+ if ( !bOldJoinLock )
+ GetFollow()->UnlockJoin();
+ // <--
+
+ if ( !GetFollow()->GetFollow() )
+ {
+ SwFrm* pNxt = ((SwFrm*)GetFollow())->FindNext();
+ if ( pNxt )
+ {
+ // OD 26.08.2003 #i18103# - no formatting
+ // of found next frame, if its a follow
+ // section of the 'ColLocked' section,
+ // the follow table is in.
+ bool bCalcNxt = true;
+ if ( GetFollow()->IsInSct() && pNxt->IsSctFrm() )
+ {
+ SwSectionFrm* pSct = GetFollow()->FindSctFrm();
+ if ( pSct->IsColLocked() &&
+ pSct->GetFollow() == pNxt )
+ {
+ bCalcNxt = false;
+ }
+ }
+ if ( bCalcNxt )
+ {
+ pNxt->Calc();
+ }
+ }
+ }
+ --nStack;
+ }
+ else if ( GetFollow() == GetNext() )
+ ((SwTabFrm*)GetFollow())->MoveFwd( sal_True, sal_False );
+ }
+ continue;
+ }
+ }
+ }
+
+ // Set to false again as early as possible.
+ bLastRowHasToMoveToFollow = false;
+
+ if( IsInSct() && bMovedFwd && bMakePage && GetUpper()->IsColBodyFrm() &&
+ GetUpper()->GetUpper()->GetUpper()->IsSctFrm() &&
+ ( GetUpper()->GetUpper()->GetPrev() || GetIndPrev() ) &&
+ ((SwSectionFrm*)GetUpper()->GetUpper()->GetUpper())->MoveAllowed(this) )
+ bMovedFwd = sal_False;
+
+ // --> FME 2004-06-09 #i29771# Reset bTryToSplit flag on change of upper
+ const SwFrm* pOldUpper = GetUpper();
+ // <--
+
+ //Mal sehen ob ich irgenwo Platz finde...
+ if ( !bMovedFwd && !MoveFwd( bMakePage, sal_False ) )
+ bMakePage = sal_False;
+
+ // --> FME 2004-06-09 #i29771# Reset bSplitError flag on change of upper
+ if ( GetUpper() != pOldUpper )
+ {
+ bTryToSplit = true;
+ nUnSplitted = 5;
+ }
+ // <--
+
+ SWREFRESHFN( this )
+ bMovedFwd = bCalcLowers = sal_True;
+ aNotify.SetLowersComplete( sal_False );
+ if ( IsFollow() )
+ { //Um Oszillationen zu vermeiden sollte kein ungueltiger Master
+ //zurueckbleiben.
+ SwTabFrm *pTab = FindMaster();
+ if ( pTab->GetUpper() )
+ pTab->GetUpper()->Calc();
+ pTab->Calc();
+ pTab->SetLowersFormatted( sal_False );
+ }
+
+ //Wenn mein direkter Nachbar jetzt gleichzeitig mein Follow ist
+ //verleibe ich mir das Teil ein.
+ if ( ( GetNext() && GetNext() == GetFollow() ) || !GetLower() )
+ {
+ if ( HasFollowFlowLine() )
+ RemoveFollowFlowLine();
+ if ( GetFollow() )
+ Join();
+ }
+
+ if ( bMovedBwd && GetUpper() )
+ //Beim zurueckfliessen wurde der Upper angeregt sich vollstaendig
+ //zu Painten, dass koennen wir uns jetzt nach dem hin und her
+ //fliessen sparen.
+ GetUpper()->ResetCompletePaint();
+
+ if ( bCalcLowers && IsValid() )
+ {
+ // --> OD 2005-05-11 #i44910# - format of lower frames unnecessary
+ // and can cause layout loops, if table doesn't fit and isn't
+ // allowed to split.
+ SwTwips nDistToUpperPrtBottom =
+ (Frm().*fnRect->fnBottomDist)( (GetUpper()->*fnRect->fnGetPrtBottom)());
+ if ( nDistToUpperPrtBottom >= 0 || bTryToSplit )
+ {
+ lcl_RecalcTable( *this, 0, aNotify );
+ bLowersFormatted = sal_True;
+ bCalcLowers = sal_False;
+ }
+#if OSL_DEBUG_LEVEL > 1
+ else
+ {
+ OSL_FAIL( "debug assertion: <SwTabFrm::MakeAll()> - format of table lowers suppressed by fix i44910" );
+ }
+#endif
+ // <--
+ }
+
+ } //while ( !bValidPos || !bValidSize || !bValidPrtArea )
+
+ //Wenn mein direkter Vorgaenger jetzt mein Master ist, so kann er mich
+ //bei der nachstbesten Gelegenheit vernichten.
+ if ( IsFollow() )
+ {
+ SwFrm *pPre = GetPrev();
+ if ( pPre && pPre->IsTabFrm() && ((SwTabFrm*)pPre)->GetFollow() == this)
+ pPre->InvalidatePos();
+ }
+
+ bCalcLowers = bONECalcLowers = sal_False;
+ delete pAccess;
+ UnlockJoin();
+ if ( bMovedFwd || bMovedBwd || !bOldValidPos )
+ aNotify.SetInvaKeep();
+}
+
+/*************************************************************************
+|*
+|* SwTabFrm::CalcFlyOffsets()
+|*
+|* Beschreibung: Berechnet die Offsets, die durch FlyFrames
+|* entstehen.
+|*
+|*************************************************************************/
+sal_Bool SwTabFrm::CalcFlyOffsets( SwTwips& rUpper,
+ long& rLeftOffset,
+ long& rRightOffset ) const
+{
+ sal_Bool bInvalidatePrtArea = sal_False;
+ const SwPageFrm *pPage = FindPageFrm();
+ const SwFlyFrm* pMyFly = FindFlyFrm();
+
+ // --> #108724# Page header/footer content doesn't have to wrap around
+ // floating screen objects
+
+ const IDocumentSettingAccess* pIDSA = GetFmt()->getIDocumentSettingAccess();
+ const bool bWrapAllowed = pIDSA->get(IDocumentSettingAccess::USE_FORMER_TEXT_WRAPPING) ||
+ ( !IsInFtn() && 0 == FindFooterOrHeader() );
+ // <--
+
+ if ( pPage->GetSortedObjs() && bWrapAllowed )
+ {
+ SWRECTFN( this )
+ const bool bConsiderWrapOnObjPos = pIDSA->get(IDocumentSettingAccess::CONSIDER_WRAP_ON_OBJECT_POSITION);
+ long nPrtPos = (Frm().*fnRect->fnGetTop)();
+ nPrtPos = (*fnRect->fnYInc)( nPrtPos, rUpper );
+ SwRect aRect( Frm() );
+ long nYDiff = (*fnRect->fnYDiff)( (Prt().*fnRect->fnGetTop)(), rUpper );
+ if( nYDiff > 0 )
+ (aRect.*fnRect->fnAddBottom)( -nYDiff );
+ for ( sal_uInt16 i = 0; i < pPage->GetSortedObjs()->Count(); ++i )
+ {
+ SwAnchoredObject* pAnchoredObj = (*pPage->GetSortedObjs())[i];
+ if ( pAnchoredObj->ISA(SwFlyFrm) )
+ {
+ SwFlyFrm *pFly = static_cast<SwFlyFrm*>(pAnchoredObj);
+ const SwRect aFlyRect = pFly->GetObjRectWithSpaces();
+ // --> OD 2004-10-07 #i26945# - correction of conditions,
+ // if Writer fly frame has to be considered:
+ // - no need to check, if top of Writer fly frame differs
+ // from WEIT_WECH, because its also check, if the Writer
+ // fly frame rectangle overlaps with <aRect>
+ // - no check, if bottom of anchor frame is prior the top of
+ // the table, because Writer fly frames can be negative positioned.
+ // - correct check, if the Writer fly frame is an lower of the
+ // table, because table lines/rows can split and a at-character
+ // anchored Writer fly frame could be positioned in the follow
+ // flow line.
+ // - add condition, that an existing anchor character text frame
+ // has to be on the same page as the table.
+ // E.g., it could happen, that the fly frame is still registered
+ // at the page frame, the table is on, but it's anchor character
+ // text frame has already changed its page.
+ const SwTxtFrm* pAnchorCharFrm = pFly->FindAnchorCharFrm();
+ bool bConsiderFly =
+ // --> OD 2005-04-06 #i46807# - do not consider invalid
+ // Writer fly frames.
+ pFly->IsValid() &&
+ // <--
+ // fly anchored at character
+ pFly->IsFlyAtCntFrm() &&
+ // fly overlaps with corresponding table rectangle
+ aFlyRect.IsOver( aRect ) &&
+ // fly isn't lower of table and
+ // anchor character frame of fly isn't lower of table
+ ( !IsAnLower( pFly ) &&
+ ( !pAnchorCharFrm || !IsAnLower( pAnchorCharFrm ) ) ) &&
+ // table isn't lower of fly
+ !pFly->IsAnLower( this ) &&
+ // fly is lower of fly, the table is in
+ // --> OD 2005-05-31 #123274# - correction:
+ // assure that fly isn't a lower of a fly, the table isn't in.
+ // E.g., a table in the body doesn't wrap around a graphic,
+ // which is inside a frame.
+ ( ( !pMyFly ||
+ pMyFly->IsAnLower( pFly ) ) &&
+ pMyFly == pFly->GetAnchorFrmContainingAnchPos()->FindFlyFrm() ) &&
+ // <--
+ // anchor frame not on following page
+ pPage->GetPhyPageNum() >=
+ pFly->GetAnchorFrm()->FindPageFrm()->GetPhyPageNum() &&
+ // anchor character text frame on same page
+ ( !pAnchorCharFrm ||
+ pAnchorCharFrm->FindPageFrm()->GetPhyPageNum() ==
+ pPage->GetPhyPageNum() );
+
+ if ( bConsiderFly )
+ {
+ const SwFrm* pFlyHeaderFooterFrm = pFly->GetAnchorFrm()->FindFooterOrHeader();
+ const SwFrm* pThisHeaderFooterFrm = FindFooterOrHeader();
+
+ if ( pFlyHeaderFooterFrm != pThisHeaderFooterFrm &&
+ // --> FME 2007-07-02 #148493# If bConsiderWrapOnObjPos is set,
+ // we want to consider the fly if it is located in the header and
+ // the table is located in the body:
+ ( !bConsiderWrapOnObjPos || 0 != pThisHeaderFooterFrm || !pFlyHeaderFooterFrm->IsHeaderFrm() ) )
+ bConsiderFly = false;
+ // <--
+ }
+
+ if ( bConsiderFly )
+ // <--
+ {
+ const SwFmtSurround &rSur = pFly->GetFmt()->GetSurround();
+ const SwFmtHoriOrient &rHori= pFly->GetFmt()->GetHoriOrient();
+ if ( SURROUND_NONE == rSur.GetSurround() )
+ {
+ long nBottom = (aFlyRect.*fnRect->fnGetBottom)();
+ if( (*fnRect->fnYDiff)( nPrtPos, nBottom ) < 0 )
+ nPrtPos = nBottom;
+ bInvalidatePrtArea = sal_True;
+ }
+ if ( (SURROUND_RIGHT == rSur.GetSurround() ||
+ SURROUND_PARALLEL == rSur.GetSurround())&&
+ text::HoriOrientation::LEFT == rHori.GetHoriOrient() )
+ {
+ const long nWidth = (*fnRect->fnXDiff)(
+ (aFlyRect.*fnRect->fnGetRight)(),
+ (pFly->GetAnchorFrm()->Frm().*fnRect->fnGetLeft)() );
+ rLeftOffset = Max( rLeftOffset, nWidth );
+ bInvalidatePrtArea = sal_True;
+ }
+ if ( (SURROUND_LEFT == rSur.GetSurround() ||
+ SURROUND_PARALLEL == rSur.GetSurround())&&
+ text::HoriOrientation::RIGHT == rHori.GetHoriOrient() )
+ {
+ const long nWidth = (*fnRect->fnXDiff)(
+ (pFly->GetAnchorFrm()->Frm().*fnRect->fnGetRight)(),
+ (aFlyRect.*fnRect->fnGetLeft)() );
+ rRightOffset = Max( rRightOffset, nWidth );
+ bInvalidatePrtArea = sal_True;
+ }
+ }
+ }
+ }
+ rUpper = (*fnRect->fnYDiff)( nPrtPos, (Frm().*fnRect->fnGetTop)() );
+ }
+
+ return bInvalidatePrtArea;
+}
+
+/*************************************************************************
+|*
+|* SwTabFrm::Format()
+|*
+|* Beschreibung: "Formatiert" den Frame; Frm und PrtArea
+|* Die Fixsize wird hier nicht eingestellt.
+|*
+|*************************************************************************/
+void SwTabFrm::Format( const SwBorderAttrs *pAttrs )
+{
+ OSL_ENSURE( pAttrs, "TabFrm::Format, pAttrs ist 0." );
+
+ SWRECTFN( this )
+ if ( !bValidSize )
+ {
+ long nDiff = (GetUpper()->Prt().*fnRect->fnGetWidth)() -
+ (Frm().*fnRect->fnGetWidth)();
+ if( nDiff )
+ (aFrm.*fnRect->fnAddRight)( nDiff );
+ }
+
+ //VarSize ist immer die Hoehe.
+ //Fuer den oberen/unteren Rand gelten die selben Regeln wie fuer
+ //cntfrms (sie MakePrtArea() von diesen).
+
+ SwTwips nUpper = CalcUpperSpace( pAttrs );
+
+ //Wir wollen Rahmen ausweichen. Zwei Moeglichkeiten:
+ //1. Es gibt Rahmen mit SurroundNone, diesen wird vollsaendig ausgewichen
+ //2. Es gibt Rahmen mit Umlauf nur rechts bzw. nur links und diese sind
+ // rechts bzw. links ausgerichtet, diese geben ein Minimum fuer die
+ // Raender vor.
+ long nTmpRight = -1000000,
+ nLeftOffset = 0;
+ if( CalcFlyOffsets( nUpper, nLeftOffset, nTmpRight ) )
+ bValidPrtArea = sal_False;
+ long nRightOffset = Max( 0L, nTmpRight );
+
+ SwTwips nLower = pAttrs->CalcBottomLine();
+ // --> collapsing borders FME 2005-05-27 #i29550#
+ if ( IsCollapsingBorders() )
+ nLower += GetBottomLineSize();
+ // <-- collapsing
+
+ if ( !bValidPrtArea )
+ { bValidPrtArea = sal_True;
+
+ //Die Breite der PrtArea wird vom FrmFmt vorgegeben, die Raender
+ //sind entsprechend einzustellen.
+ //Mindestraender werden von Umrandung und Schatten vorgegeben.
+ //Die Rander werden so eingestellt, dass die PrtArea nach dem
+ //angegebenen Adjustment im Frm ausgerichtet wird.
+ //Wenn das Adjustment 0 ist, so werden die Rander anhand des
+ //Randattributes eingestellt.
+
+ const SwTwips nOldHeight = (Prt().*fnRect->fnGetHeight)();
+ const SwTwips nMax = (aFrm.*fnRect->fnGetWidth)();
+
+ // OD 14.03.2003 #i9040# - adjust variable names.
+ const SwTwips nLeftLine = pAttrs->CalcLeftLine();
+ const SwTwips nRightLine = pAttrs->CalcRightLine();
+
+ //Die Breite ist evtl. eine Prozentangabe. Wenn die Tabelle irgendwo
+ //'drinsteckt bezieht sie sich auf die Umgebung. Ist es der Body, so
+ //bezieht sie sich in der BrowseView auf die Bildschirmbreite.
+ const SwFmtFrmSize &rSz = GetFmt()->GetFrmSize();
+ // OD 14.03.2003 #i9040# - adjust variable name.
+ const SwTwips nWishedTableWidth = CalcRel( rSz, sal_True );
+
+ sal_Bool bCheckBrowseWidth = sal_False;
+
+ // OD 14.03.2003 #i9040# - insert new variables for left/right spacing.
+ SwTwips nLeftSpacing = 0;
+ SwTwips nRightSpacing = 0;
+ switch ( GetFmt()->GetHoriOrient().GetHoriOrient() )
+ {
+ case text::HoriOrientation::LEFT:
+ {
+ // left indent:
+ nLeftSpacing = nLeftLine + nLeftOffset;
+ // OD 06.03.2003 #i9040# - correct calculation of right indent:
+ // - Consider right indent given by right line attributes.
+ // - Consider negative right indent.
+ // wished right indent determined by wished table width and
+ // left offset given by surround fly frames on the left:
+ const SwTwips nWishRight = nMax - nWishedTableWidth - nLeftOffset;
+ if ( nRightOffset > 0 )
+ {
+ // surrounding fly frames on the right
+ // -> right indent is maximun of given right offset
+ // and wished right offset.
+ nRightSpacing = nRightLine + Max( nRightOffset, nWishRight );
+ }
+ else
+ {
+ // no surrounding fly frames on the right
+ // If intrinsic right indent (intrinsic means not considering
+ // determined left indent) is negative,
+ // then hold this intrinsic indent,
+ // otherwise non negative wished right indent is hold.
+ nRightSpacing = nRightLine +
+ ( ( (nWishRight+nLeftOffset) < 0 ) ?
+ (nWishRight+nLeftOffset) :
+ Max( 0L, nWishRight ) );
+ }
+ }
+ break;
+ case text::HoriOrientation::RIGHT:
+ {
+ // right indent:
+ nRightSpacing = nRightLine + nRightOffset;
+ // OD 06.03.2003 #i9040# - correct calculation of left indent:
+ // - Consider left indent given by left line attributes.
+ // - Consider negative left indent.
+ // wished left indent determined by wished table width and
+ // right offset given by surrounding fyl frames on the right:
+ const SwTwips nWishLeft = nMax - nWishedTableWidth - nRightOffset;
+ if ( nLeftOffset > 0 )
+ {
+ // surrounding fly frames on the left
+ // -> right indent is maximun of given left offset
+ // and wished left offset.
+ nLeftSpacing = nLeftLine + Max( nLeftOffset, nWishLeft );
+ }
+ else
+ {
+ // no surrounding fly frames on the left
+ // If intrinsic left indent (intrinsic = not considering
+ // determined right indent) is negative,
+ // then hold this intrinsic indent,
+ // otherwise non negative wished left indent is hold.
+ nLeftSpacing = nLeftLine +
+ ( ( (nWishLeft+nRightOffset) < 0 ) ?
+ (nWishLeft+nRightOffset) :
+ Max( 0L, nWishLeft ) );
+ }
+ }
+ break;
+ case text::HoriOrientation::CENTER:
+ {
+ // OD 07.03.2003 #i9040# - consider left/right line attribute.
+ // OD 10.03.2003 #i9040# -
+ const SwTwips nCenterSpacing = ( nMax - nWishedTableWidth ) / 2;
+ nLeftSpacing = nLeftLine +
+ ( (nLeftOffset > 0) ?
+ Max( nCenterSpacing, nLeftOffset ) :
+ nCenterSpacing );
+ nRightSpacing = nRightLine +
+ ( (nRightOffset > 0) ?
+ Max( nCenterSpacing, nRightOffset ) :
+ nCenterSpacing );
+ }
+ break;
+ case text::HoriOrientation::FULL:
+ //Das Teil dehnt sich ueber die gesamte Breite aus.
+ //Nur die fuer die Umrandung benoetigten Freiraeume
+ //werden beruecksichtigt.
+ //Die Attributwerte von LRSpace werden bewusst missachtet!
+ bCheckBrowseWidth = sal_True;
+ nLeftSpacing = nLeftLine + nLeftOffset;
+ nRightSpacing = nRightLine + nRightOffset;
+ break;
+ case text::HoriOrientation::NONE:
+ {
+ //Die Raender werden vom Randattribut bestimmt.
+ nLeftSpacing = pAttrs->CalcLeft( this );
+ if( nLeftOffset )
+ {
+ // OD 07.03.2003 #i9040# - surround fly frames only, if
+ // they overlap with the table.
+ // Thus, take maximun of left spacing and left offset.
+ // OD 10.03.2003 #i9040# - consider left line attribute.
+ nLeftSpacing = Max( nLeftSpacing, ( nLeftOffset + nLeftLine ) );
+ }
+ // OD 23.01.2003 #106895# - add 1st param to <SwBorderAttrs::CalcRight(..)>
+ nRightSpacing = pAttrs->CalcRight( this );
+ if( nRightOffset )
+ {
+ // OD 07.03.2003 #i9040# - surround fly frames only, if
+ // they overlap with the table.
+ // Thus, take maximun of right spacing and right offset.
+ // OD 10.03.2003 #i9040# - consider right line attribute.
+ nRightSpacing = Max( nRightSpacing, ( nRightOffset + nRightLine ) );
+ }
+ }
+ break;
+ case text::HoriOrientation::LEFT_AND_WIDTH:
+ {
+ //Linker Rand und die Breite zaehlen (Word-Spezialitaet)
+ // OD 10.03.2003 #i9040# - no width alignment in online mode.
+ //bCheckBrowseWidth = sal_True;
+ nLeftSpacing = pAttrs->CalcLeft( this );
+ if( nLeftOffset )
+ {
+ // OD 10.03.2003 #i9040# - surround fly frames only, if
+ // they overlap with the table.
+ // Thus, take maximun of right spacing and right offset.
+ // OD 10.03.2003 #i9040# - consider left line attribute.
+ nLeftSpacing = Max( nLeftSpacing, ( pAttrs->CalcLeftLine() + nLeftOffset ) );
+ }
+ // OD 10.03.2003 #i9040# - consider right and left line attribute.
+ const SwTwips nWishRight =
+ nMax - (nLeftSpacing-pAttrs->CalcLeftLine()) - nWishedTableWidth;
+ nRightSpacing = nRightLine +
+ ( (nRightOffset > 0) ?
+ Max( nWishRight, nRightOffset ) :
+ nWishRight );
+ }
+ break;
+ default:
+ OSL_FAIL( "Ungueltige orientation fuer Table." );
+ }
+
+ // --> OD 2004-07-15 #i26250# - extend bottom printing area, if table
+ // is last content inside a table cell.
+ if ( GetFmt()->getIDocumentSettingAccess()->get(IDocumentSettingAccess::ADD_PARA_SPACING_TO_TABLE_CELLS) &&
+ GetUpper()->IsInTab() && !GetIndNext() )
+ {
+ nLower += pAttrs->GetULSpace().GetLower();
+ }
+ // <--
+ (this->*fnRect->fnSetYMargins)( nUpper, nLower );
+ if( (nMax - MINLAY) < (nLeftSpacing + nRightSpacing) )
+ (this->*fnRect->fnSetXMargins)( 0, 0 );
+ else
+ (this->*fnRect->fnSetXMargins)( nLeftSpacing, nRightSpacing );
+
+ ViewShell *pSh = getRootFrm()->GetCurrShell();
+ if ( bCheckBrowseWidth &&
+ pSh && pSh->GetViewOptions()->getBrowseMode() &&
+ GetUpper()->IsPageBodyFrm() && // nur PageBodyFrms, nicht etwa ColBodyFrms
+ pSh->VisArea().Width() )
+ {
+ //Nicht ueber die Kante des sichbaren Bereiches hinausragen.
+ //Die Seite kann breiter sein, weil es Objekte mit "ueberbreite"
+ //geben kann (RootFrm::ImplCalcBrowseWidth())
+ long nWidth = pSh->GetBrowseWidth();
+ nWidth -= Prt().Left();
+ nWidth -= pAttrs->CalcRightLine();
+ Prt().Width( Min( nWidth, Prt().Width() ) );
+ }
+
+ if ( nOldHeight != (Prt().*fnRect->fnGetHeight)() )
+ bValidSize = sal_False;
+ }
+
+ if ( !bValidSize )
+ {
+ bValidSize = sal_True;
+
+ //Die Groesse wird durch den Inhalt plus den Raendern bestimmt.
+ SwTwips nRemaining = 0, nDiff;
+ SwFrm *pFrm = pLower;
+ while ( pFrm )
+ {
+ nRemaining += (pFrm->Frm().*fnRect->fnGetHeight)();
+ pFrm = pFrm->GetNext();
+ }
+ //Jetzt noch die Raender addieren
+ nRemaining += nUpper + nLower;
+
+ nDiff = (Frm().*fnRect->fnGetHeight)() - nRemaining;
+ if ( nDiff > 0 )
+ Shrink( nDiff );
+ else if ( nDiff < 0 )
+ Grow( -nDiff );
+ }
+}
+/*************************************************************************
+|*
+|* SwTabFrm::GrowFrm()
+|*
+|*************************************************************************/
+SwTwips SwTabFrm::GrowFrm( SwTwips nDist, sal_Bool bTst, sal_Bool bInfo )
+{
+ SWRECTFN( this )
+ SwTwips nHeight =(Frm().*fnRect->fnGetHeight)();
+ if( nHeight > 0 && nDist > ( LONG_MAX - nHeight ) )
+ nDist = LONG_MAX - nHeight;
+
+ if ( bTst && !IsRestrictTableGrowth() )
+ return nDist;
+
+ if ( GetUpper() )
+ {
+ SwRect aOldFrm( Frm() );
+
+ //Der Upper wird nur soweit wie notwendig gegrowed. In nReal wird erstmal
+ //die bereits zur Verfuegung stehende Strecke bereitgestellt.
+ SwTwips nReal = (GetUpper()->Prt().*fnRect->fnGetHeight)();
+ SwFrm *pFrm = GetUpper()->Lower();
+ while ( pFrm && GetFollow() != pFrm )
+ {
+ nReal -= (pFrm->Frm().*fnRect->fnGetHeight)();
+ pFrm = pFrm->GetNext();
+ }
+
+ if ( nReal < nDist )
+ {
+ long nTmp = GetUpper()->Grow( nDist - ( nReal > 0 ? nReal : 0), bTst, bInfo );
+
+ if ( IsRestrictTableGrowth() )
+ {
+ nTmp = Min( nDist, nReal + nTmp );
+ nDist = nTmp < 0 ? 0 : nTmp;
+ }
+ }
+
+ if ( !bTst )
+ {
+ (Frm().*fnRect->fnAddBottom)( nDist );
+
+ SwRootFrm *pRootFrm = getRootFrm();
+ if( pRootFrm && pRootFrm->IsAnyShellAccessible() &&
+ pRootFrm->GetCurrShell() )
+ {
+ pRootFrm->GetCurrShell()->Imp()->MoveAccessibleFrm( this, aOldFrm );
+ }
+ }
+ }
+
+ if ( !bTst && ( nDist || IsRestrictTableGrowth() ) )
+ {
+ SwPageFrm *pPage = FindPageFrm();
+ if ( GetNext() )
+ {
+ GetNext()->_InvalidatePos();
+ if ( GetNext()->IsCntntFrm() )
+ GetNext()->InvalidatePage( pPage );
+ }
+ // --> OD 2004-07-05 #i28701# - Due to the new object positioning the
+ // frame on the next page/column can flow backward (e.g. it was moved
+ // forward due to the positioning of its objects ). Thus, invalivate this
+ // next frame, if document compatibility option 'Consider wrapping style
+ // influence on object positioning' is ON.
+ else if ( GetFmt()->getIDocumentSettingAccess()->get(IDocumentSettingAccess::CONSIDER_WRAP_ON_OBJECT_POSITION) )
+ {
+ InvalidateNextPos();
+ }
+ // <--
+ _InvalidateAll();
+ InvalidatePage( pPage );
+ SetComplete();
+
+ const SvxGraphicPosition ePos = GetFmt()->GetBackground().GetGraphicPos();
+ if ( GPOS_NONE != ePos && GPOS_TILED != ePos )
+ SetCompletePaint();
+ }
+
+ return nDist;
+}
+/*************************************************************************
+|*
+|* SwTabFrm::Modify()
+|*
+|*************************************************************************/
+void SwTabFrm::Modify( const SfxPoolItem* pOld, const SfxPoolItem * pNew )
+{
+ sal_uInt8 nInvFlags = 0;
+ sal_Bool bAttrSetChg = pNew && RES_ATTRSET_CHG == pNew->Which();
+
+ if( bAttrSetChg )
+ {
+ SfxItemIter aNIter( *((SwAttrSetChg*)pNew)->GetChgSet() );
+ SfxItemIter aOIter( *((SwAttrSetChg*)pOld)->GetChgSet() );
+ SwAttrSetChg aOldSet( *(SwAttrSetChg*)pOld );
+ SwAttrSetChg aNewSet( *(SwAttrSetChg*)pNew );
+ while( sal_True )
+ {
+ _UpdateAttr( (SfxPoolItem*)aOIter.GetCurItem(),
+ (SfxPoolItem*)aNIter.GetCurItem(), nInvFlags,
+ &aOldSet, &aNewSet );
+ if( aNIter.IsAtEnd() )
+ break;
+ aNIter.NextItem();
+ aOIter.NextItem();
+ }
+ if ( aOldSet.Count() || aNewSet.Count() )
+ SwLayoutFrm::Modify( &aOldSet, &aNewSet );
+ }
+ else
+ _UpdateAttr( pOld, pNew, nInvFlags );
+
+ if ( nInvFlags != 0 )
+ {
+ SwPageFrm *pPage = FindPageFrm();
+ InvalidatePage( pPage );
+ if ( nInvFlags & 0x02 )
+ _InvalidatePrt();
+ if ( nInvFlags & 0x40 )
+ _InvalidatePos();
+ SwFrm *pTmp;
+ if ( 0 != (pTmp = GetIndNext()) )
+ {
+ if ( nInvFlags & 0x04 )
+ {
+ pTmp->_InvalidatePrt();
+ if ( pTmp->IsCntntFrm() )
+ pTmp->InvalidatePage( pPage );
+ }
+ if ( nInvFlags & 0x10 )
+ pTmp->SetCompletePaint();
+ }
+ if ( nInvFlags & 0x08 && 0 != (pTmp = GetPrev()) )
+ {
+ pTmp->_InvalidatePrt();
+ if ( pTmp->IsCntntFrm() )
+ pTmp->InvalidatePage( pPage );
+ }
+ if ( nInvFlags & 0x20 )
+ {
+ if ( pPage && pPage->GetUpper() && !IsFollow() )
+ ((SwRootFrm*)pPage->GetUpper())->InvalidateBrowseWidth();
+ }
+ if ( nInvFlags & 0x80 )
+ InvalidateNextPos();
+ }
+}
+
+void SwTabFrm::_UpdateAttr( const SfxPoolItem *pOld, const SfxPoolItem *pNew,
+ sal_uInt8 &rInvFlags,
+ SwAttrSetChg *pOldSet, SwAttrSetChg *pNewSet )
+{
+ sal_Bool bClear = sal_True;
+ const sal_uInt16 nWhich = pOld ? pOld->Which() : pNew ? pNew->Which() : 0;
+ switch( nWhich )
+ {
+ case RES_TBLHEADLINECHG:
+ if ( IsFollow() )
+ {
+ // Delete remaining headlines:
+ SwRowFrm* pLowerRow = 0;
+ while ( 0 != ( pLowerRow = (SwRowFrm*)Lower() ) && pLowerRow->IsRepeatedHeadline() )
+ {
+ pLowerRow->Cut();
+ delete pLowerRow;
+ }
+
+ // insert new headlines
+ const sal_uInt16 nNewRepeat = GetTable()->GetRowsToRepeat();
+ for ( sal_uInt16 nIdx = 0; nIdx < nNewRepeat; ++nIdx )
+ {
+ bDontCreateObjects = sal_True; //frmtool
+ SwRowFrm* pHeadline = new SwRowFrm( *GetTable()->GetTabLines()[ nIdx ], this );
+ pHeadline->SetRepeatedHeadline( true );
+ bDontCreateObjects = sal_False;
+ pHeadline->Paste( this, pLowerRow );
+ }
+ }
+ rInvFlags |= 0x02;
+ break;
+
+ case RES_FRM_SIZE:
+ case RES_HORI_ORIENT:
+ rInvFlags |= 0x22;
+ break;
+
+ case RES_PAGEDESC: //Attributaenderung (an/aus)
+ if ( IsInDocBody() )
+ {
+ rInvFlags |= 0x40;
+ SwPageFrm *pPage = FindPageFrm();
+ if ( !GetPrev() )
+ CheckPageDescs( pPage );
+ if ( pPage && GetFmt()->GetPageDesc().GetNumOffset() )
+ ((SwRootFrm*)pPage->GetUpper())->SetVirtPageNum( sal_True );
+ SwDocPosUpdate aMsgHnt( pPage->Frm().Top() );
+ GetFmt()->GetDoc()->UpdatePageFlds( &aMsgHnt );
+ }
+ break;
+
+ case RES_BREAK:
+ rInvFlags |= 0xC0;
+ break;
+
+ case RES_LAYOUT_SPLIT:
+ if ( !IsFollow() )
+ rInvFlags |= 0x40;
+ break;
+ case RES_FRAMEDIR :
+ SetDerivedR2L( sal_False );
+ CheckDirChange();
+ break;
+ case RES_COLLAPSING_BORDERS :
+ rInvFlags |= 0x02;
+ lcl_InvalidateAllLowersPrt( this );
+ break;
+ case RES_UL_SPACE:
+ rInvFlags |= 0x1C;
+ /* kein Break hier */
+
+ default:
+ bClear = sal_False;
+ }
+ if ( bClear )
+ {
+ if ( pOldSet || pNewSet )
+ {
+ if ( pOldSet )
+ pOldSet->ClearItem( nWhich );
+ if ( pNewSet )
+ pNewSet->ClearItem( nWhich );
+ }
+ else
+ SwLayoutFrm::Modify( pOld, pNew );
+ }
+}
+
+/*************************************************************************
+|*
+|* SwTabFrm::GetInfo()
+|*
+|*************************************************************************/
+sal_Bool SwTabFrm::GetInfo( SfxPoolItem &rHnt ) const
+{
+ if ( RES_VIRTPAGENUM_INFO == rHnt.Which() && IsInDocBody() && !IsFollow() )
+ {
+ SwVirtPageNumInfo &rInfo = (SwVirtPageNumInfo&)rHnt;
+ const SwPageFrm *pPage = FindPageFrm();
+ if ( pPage )
+ {
+ if ( pPage == rInfo.GetOrigPage() && !GetPrev() )
+ {
+ //Das sollte er sein (kann allenfalls temporaer anders sein,
+ // sollte uns das beunruhigen?)
+ rInfo.SetInfo( pPage, this );
+ return sal_False;
+ }
+ if ( pPage->GetPhyPageNum() < rInfo.GetOrigPage()->GetPhyPageNum() &&
+ (!rInfo.GetPage() || pPage->GetPhyPageNum() > rInfo.GetPage()->GetPhyPageNum()))
+ {
+ //Das koennte er sein.
+ rInfo.SetInfo( pPage, this );
+ }
+ }
+ }
+ return sal_True;
+}
+
+/*************************************************************************
+|*
+|* SwTabFrm::FindLastCntnt()
+|*
+|*************************************************************************/
+SwCntntFrm *SwTabFrm::FindLastCntnt()
+{
+ SwFrm *pRet = pLower;
+
+ while ( pRet && !pRet->IsCntntFrm() )
+ {
+ SwFrm *pOld = pRet;
+
+ SwFrm *pTmp = pRet; // To skip empty section frames
+ while ( pRet->GetNext() )
+ {
+ pRet = pRet->GetNext();
+ if( !pRet->IsSctFrm() || ((SwSectionFrm*)pRet)->GetSection() )
+ pTmp = pRet;
+ }
+ pRet = pTmp;
+
+ if ( pRet->GetLower() )
+ pRet = pRet->GetLower();
+ if ( pRet == pOld )
+ {
+ // Wenn am Ende der letzten Zelle ein spaltiger Bereich steht,
+ // der eine leere letzte Spalte hat, muessen wir noch die anderen
+ // Spalten abklappern, dies erledigt SwSectionFrm::FindLastCntnt
+ if( pRet->IsColBodyFrm() )
+ {
+#if OSL_DEBUG_LEVEL > 1
+ SwSectionFrm* pSect = pRet->FindSctFrm();
+ OSL_ENSURE( pSect, "Wo kommt denn die Spalte her?");
+ OSL_ENSURE( IsAnLower( pSect ), "Gespaltene Zelle?" );
+#endif
+ return pRet->FindSctFrm()->FindLastCntnt();
+ }
+
+ //
+ // pRet may be a cell frame without a lower (cell has been split).
+ // We have to find the last content the hard way:
+ //
+ OSL_ENSURE( pRet->IsCellFrm(), "SwTabFrm::FindLastCntnt failed" );
+ const SwFrm* pRow = pRet->GetUpper();
+ while ( pRow && !pRow->GetUpper()->IsTabFrm() )
+ pRow = pRow->GetUpper();
+ SwCntntFrm* pCntntFrm = ((SwLayoutFrm*)pRow)->ContainsCntnt();
+ pRet = 0;
+
+ while ( pCntntFrm && ((SwLayoutFrm*)pRow)->IsAnLower( pCntntFrm ) )
+ {
+ pRet = pCntntFrm;
+ pCntntFrm = pCntntFrm->GetNextCntntFrm();
+ }
+ }
+ }
+
+ // #112929# There actually is a situation, which results in pRet = 0:
+ // Insert frame, insert table via text <-> table. This gives you a frame
+ // containing a table without any other content frames. Split the table
+ // and undo the splitting. This operation gives us a table frame without
+ // a lower.
+ if ( pRet )
+ {
+ while ( pRet->GetNext() )
+ pRet = pRet->GetNext();
+
+ if( pRet->IsSctFrm() )
+ pRet = ((SwSectionFrm*)pRet)->FindLastCntnt();
+ }
+
+ return (SwCntntFrm*)pRet;
+}
+
+/*************************************************************************
+|*
+|* SwTabFrm::GetLeaf()
+|*
+|*************************************************************************/
+SwLayoutFrm *SwTabFrm::GetLeaf( MakePageType eMakePage, sal_Bool bFwd )
+{
+ SwLayoutFrm *pRet;
+ if ( bFwd )
+ {
+ pRet = GetNextLeaf( eMakePage );
+ while ( IsAnLower( pRet ) )
+ pRet = pRet->GetNextLeaf( eMakePage );
+ }
+ else
+ pRet = GetPrevLeaf();
+ if ( pRet )
+ pRet->Calc();
+ return pRet;
+}
+
+/*************************************************************************
+|*
+|* SwTabFrm::ShouldBwdMoved()
+|*
+|* Beschreibung Returnwert sagt ob der Frm verschoben werden sollte
+|*
+|*************************************************************************/
+sal_Bool SwTabFrm::ShouldBwdMoved( SwLayoutFrm *pNewUpper, sal_Bool, sal_Bool &rReformat )
+{
+ rReformat = sal_False;
+ if ( (SwFlowFrm::IsMoveBwdJump() || !IsPrevObjMove()) )
+ {
+ //Das zurueckfliessen von Frm's ist leider etwas Zeitintensiv.
+ //Der haufigste Fall ist der, dass dort wo der Frm hinfliessen
+ //moechte die FixSize die gleiche ist, die der Frm selbst hat.
+ //In diesem Fall kann einfach geprueft werden, ob der Frm genug
+ //Platz fuer seine VarSize findet, ist dies nicht der Fall kann
+ //gleich auf das Verschieben verzichtet werden.
+ //Die Pruefung, ob der Frm genug Platz findet fuehrt er selbst
+ //durch, dabei wird beruecksichtigt, dass er sich moeglicherweise
+ //aufspalten kann.
+ //Wenn jedoch die FixSize eine andere ist oder Flys im Spiel sind
+ //(an der alten oder neuen Position) hat alle Prueferei keinen Sinn
+ //der Frm muss dann halt Probehalber verschoben werden (Wenn ueberhaupt
+ //etwas Platz zur Verfuegung steht).
+
+ //Die FixSize der Umgebungen in denen Tabellen herumlungern ist immer
+ //Die Breite.
+
+ SwPageFrm *pOldPage = FindPageFrm(),
+ *pNewPage = pNewUpper->FindPageFrm();
+ sal_Bool bMoveAnyway = sal_False;
+ SwTwips nSpace = 0;
+
+ SWRECTFN( this )
+ if ( !SwFlowFrm::IsMoveBwdJump() )
+ {
+
+ long nOldWidth = (GetUpper()->Prt().*fnRect->fnGetWidth)();
+ SWRECTFNX( pNewUpper );
+ long nNewWidth = (pNewUpper->Prt().*fnRectX->fnGetWidth)();
+ if( Abs( nNewWidth - nOldWidth ) < 2 )
+ {
+ if( sal_False ==
+ ( bMoveAnyway = BwdMoveNecessary( pOldPage, Frm() ) > 1 ) )
+ {
+ SwRect aRect( pNewUpper->Prt() );
+ aRect.Pos() += pNewUpper->Frm().Pos();
+ const SwFrm *pPrevFrm = pNewUpper->Lower();
+ while ( pPrevFrm && pPrevFrm != this )
+ {
+ (aRect.*fnRectX->fnSetTop)( (pPrevFrm->Frm().*fnRectX->
+ fnGetBottom)() );
+ pPrevFrm = pPrevFrm->GetNext();
+ }
+ bMoveAnyway = BwdMoveNecessary( pNewPage, aRect) > 1;
+
+ // --> FME 2006-01-20 #i54861# Due to changes made in PrepareMake,
+ // the tabfrm may not have a correct position. Therefore
+ // it is possible that pNewUpper->Prt().Height == 0. In this
+ // case the above calculation of nSpace might give wrong
+ // results and we really do not want to MoveBackwrd into a
+ // 0 height frame. If nTmpSpace is already <= 0, we take this
+ // value:
+ const SwTwips nTmpSpace = (aRect.*fnRectX->fnGetHeight)();
+ if ( (pNewUpper->Prt().*fnRectX->fnGetHeight)() > 0 || nTmpSpace <= 0 )
+ nSpace = nTmpSpace;
+ // <--
+
+ const ViewShell *pSh = getRootFrm()->GetCurrShell();
+ if( pSh && pSh->GetViewOptions()->getBrowseMode() )
+ nSpace += pNewUpper->Grow( LONG_MAX, sal_True );
+ }
+ }
+ else if( !bLockBackMove )
+ bMoveAnyway = sal_True;
+ }
+ else if( !bLockBackMove )
+ bMoveAnyway = sal_True;
+
+ if ( bMoveAnyway )
+ return rReformat = sal_True;
+ else if ( !bLockBackMove && nSpace > 0 )
+ {
+ // --> OD 2004-10-05 #i26945# - check, if follow flow line
+ // contains frame, which are moved forward due to its object
+ // positioning.
+ SwRowFrm* pFirstRow = GetFirstNonHeadlineRow();
+ if ( pFirstRow && pFirstRow->IsInFollowFlowRow() &&
+ SwLayouter::DoesRowContainMovedFwdFrm(
+ *(pFirstRow->GetFmt()->GetDoc()),
+ *(pFirstRow) ) )
+ {
+ return sal_False;
+ }
+ // <--
+ SwTwips nTmpHeight = CalcHeightOfFirstContentLine();
+
+ // --> FME 2005-01-17 #118840#
+ // For some mysterious reason, I changed the good old
+ // 'return nHeight <= nSpace' to 'return nTmpHeight < nSpace'.
+ // This obviously results in problems with table frames in
+ // sections. Remember: Every twip is sacred.
+ return nTmpHeight <= nSpace;
+ // <--
+ }
+ }
+ return sal_False;
+}
+
+/*************************************************************************
+|*
+|* SwTabFrm::Cut()
+|*
+|*************************************************************************/
+void SwTabFrm::Cut()
+{
+ OSL_ENSURE( GetUpper(), "Cut ohne Upper()." );
+
+ SwPageFrm *pPage = FindPageFrm();
+ InvalidatePage( pPage );
+ SwFrm *pFrm = GetNext();
+ if( pFrm )
+ { //Der alte Nachfolger hat evtl. einen Abstand zum Vorgaenger
+ //berechnet der ist jetzt wo er der erste wird obsolete
+ pFrm->_InvalidatePrt();
+ pFrm->_InvalidatePos();
+ if ( pFrm->IsCntntFrm() )
+ pFrm->InvalidatePage( pPage );
+ if( IsInSct() && !GetPrev() )
+ {
+ SwSectionFrm* pSct = FindSctFrm();
+ if( !pSct->IsFollow() )
+ {
+ pSct->_InvalidatePrt();
+ pSct->InvalidatePage( pPage );
+ }
+ }
+ }
+ else
+ {
+ InvalidateNextPos();
+ //Einer muss die Retusche uebernehmen: Vorgaenger oder Upper
+ if ( 0 != (pFrm = GetPrev()) )
+ { pFrm->SetRetouche();
+ pFrm->Prepare( PREP_WIDOWS_ORPHANS );
+ pFrm->_InvalidatePos();
+ if ( pFrm->IsCntntFrm() )
+ pFrm->InvalidatePage( pPage );
+ }
+ //Wenn ich der einzige FlowFrm in meinem Upper bin (war), so muss
+ //er die Retouche uebernehmen.
+ //Ausserdem kann eine Leerseite entstanden sein.
+ else
+ { SwRootFrm *pRoot = (SwRootFrm*)pPage->GetUpper();
+ pRoot->SetSuperfluous();
+ GetUpper()->SetCompletePaint();
+ if( IsInSct() )
+ {
+ SwSectionFrm* pSct = FindSctFrm();
+ if( !pSct->IsFollow() )
+ {
+ pSct->_InvalidatePrt();
+ pSct->InvalidatePage( pPage );
+ }
+ }
+ }
+ }
+
+ //Erst removen, dann Upper Shrinken.
+ SwLayoutFrm *pUp = GetUpper();
+ SWRECTFN( this )
+ Remove();
+ if ( pUp )
+ {
+ OSL_ENSURE( !pUp->IsFtnFrm(), "Tabelle in Fussnote." );
+ SwSectionFrm *pSct = 0;
+ // --> OD 2006-01-04 #126020# - adjust check for empty section
+ // --> OD 2006-02-01 #130797# - correct fix #126020#
+ if ( !pUp->Lower() && pUp->IsInSct() &&
+ !(pSct = pUp->FindSctFrm())->ContainsCntnt() &&
+ !pSct->ContainsAny( true ) )
+ // <--
+ {
+ if ( pUp->GetUpper() )
+ {
+ pSct->DelEmpty( sal_False );
+ pSct->_InvalidateSize();
+ }
+ }
+ else if( (Frm().*fnRect->fnGetHeight)() )
+ {
+ // OD 26.08.2003 #i18103# - *no* 'ColUnlock' of section -
+ // undo changes of fix for #104992#
+ pUp->Shrink( Frm().Height() );
+ }
+ }
+
+ if ( pPage && !IsFollow() && pPage->GetUpper() )
+ ((SwRootFrm*)pPage->GetUpper())->InvalidateBrowseWidth();
+}
+
+/*************************************************************************
+|*
+|* SwTabFrm::Paste()
+|*
+|*************************************************************************/
+void SwTabFrm::Paste( SwFrm* pParent, SwFrm* pSibling )
+{
+ OSL_ENSURE( pParent, "Kein Parent fuer Paste." );
+ OSL_ENSURE( pParent->IsLayoutFrm(), "Parent ist CntntFrm." );
+ OSL_ENSURE( pParent != this, "Bin selbst der Parent." );
+ OSL_ENSURE( pSibling != this, "Bin mein eigener Nachbar." );
+ OSL_ENSURE( !GetPrev() && !GetNext() && !GetUpper(),
+ "Bin noch irgendwo angemeldet." );
+
+ //In den Baum einhaengen.
+ InsertBefore( (SwLayoutFrm*)pParent, pSibling );
+
+ _InvalidateAll();
+ SwPageFrm *pPage = FindPageFrm();
+ InvalidatePage( pPage );
+
+ if ( GetNext() )
+ {
+ GetNext()->_InvalidatePos();
+ GetNext()->_InvalidatePrt();
+ if ( GetNext()->IsCntntFrm() )
+ GetNext()->InvalidatePage( pPage );
+ }
+
+ SWRECTFN( this )
+ if( (Frm().*fnRect->fnGetHeight)() )
+ pParent->Grow( (Frm().*fnRect->fnGetHeight)() );
+
+ if( (Frm().*fnRect->fnGetWidth)() != (pParent->Prt().*fnRect->fnGetWidth)() )
+ Prepare( PREP_FIXSIZE_CHG );
+ if ( GetPrev() )
+ {
+ if ( !IsFollow() )
+ {
+ GetPrev()->InvalidateSize();
+ if ( GetPrev()->IsCntntFrm() )
+ GetPrev()->InvalidatePage( pPage );
+ }
+ }
+ else if ( GetNext() )
+ //Bei CntntFrm's gilt es den Abstand zum Vorgaenger/Nachfolger
+ //zu beachten. Faelle (beide treten immer gleichzeitig auf):
+ //a) Der Cntnt wird der erste einer Kette
+ //b) Der neue Nachfolger war vorher der erste einer Kette
+ GetNext()->_InvalidatePrt();
+
+ if ( pPage && !IsFollow() )
+ {
+ if ( pPage->GetUpper() )
+ ((SwRootFrm*)pPage->GetUpper())->InvalidateBrowseWidth();
+
+ if ( !GetPrev() )//Mindestens fuer HTML mit Tabelle am Anfang notwendig.
+ {
+ const SwPageDesc *pDesc = GetFmt()->GetPageDesc().GetPageDesc();
+ if ( (pDesc && pDesc != pPage->GetPageDesc()) ||
+ (!pDesc && pPage->GetPageDesc() !=
+ &(const_cast<const SwDoc *>(GetFmt()->GetDoc())
+ ->GetPageDesc(0))) )
+ CheckPageDescs( pPage, sal_True );
+ }
+ }
+}
+
+/*************************************************************************
+|*
+|* SwTabFrm::Prepare()
+|*
+|*************************************************************************/
+void SwTabFrm::Prepare( const PrepareHint eHint, const void *, sal_Bool )
+{
+ if( PREP_BOSS_CHGD == eHint )
+ CheckDirChange();
+}
+
+/*************************************************************************
+|*
+|* SwRowFrm::SwRowFrm(), ~SwRowFrm()
+|*
+|*************************************************************************/
+SwRowFrm::SwRowFrm( const SwTableLine &rLine, SwFrm* pSib, bool bInsertContent ):
+ SwLayoutFrm( rLine.GetFrmFmt(), pSib ),
+ pTabLine( &rLine ),
+ pFollowRow( 0 ),
+ // --> collapsing borders FME 2005-05-27 #i29550#
+ mnTopMarginForLowers( 0 ),
+ mnBottomMarginForLowers( 0 ),
+ mnBottomLineSize( 0 ),
+ // <-- collapsing
+ // --> split table rows
+ bIsFollowFlowRow( false ),
+ // <-- split table rows
+ bIsRepeatedHeadline( false ),
+ mbIsRowSpanLine( false )
+{
+ nType = FRMC_ROW;
+
+ //Gleich die Boxen erzeugen und einfuegen.
+ const SwTableBoxes &rBoxes = rLine.GetTabBoxes();
+ SwFrm *pTmpPrev = 0;
+ for ( sal_uInt16 i = 0; i < rBoxes.Count(); ++i )
+ {
+ SwCellFrm *pNew = new SwCellFrm( *rBoxes[i], this, bInsertContent );
+ pNew->InsertBehind( this, pTmpPrev );
+ pTmpPrev = pNew;
+ }
+}
+
+SwRowFrm::~SwRowFrm()
+{
+ SwModify* pMod = GetFmt();
+ if( pMod )
+ {
+ pMod->Remove( this ); // austragen,
+ if( !pMod->GetDepends() )
+ delete pMod; // und loeschen
+ }
+}
+
+/*************************************************************************
+|*
+|* SwRowFrm::RegistFlys()
+|*
+|*************************************************************************/
+void SwRowFrm::RegistFlys( SwPageFrm *pPage )
+{
+ ::RegistFlys( pPage ? pPage : FindPageFrm(), this );
+}
+
+/*************************************************************************
+|*
+|* SwRowFrm::Modify()
+|*
+|*************************************************************************/
+void SwRowFrm::Modify( const SfxPoolItem* pOld, const SfxPoolItem * pNew )
+{
+ sal_Bool bAttrSetChg = pNew && RES_ATTRSET_CHG == pNew->Which();
+ const SfxPoolItem *pItem = 0;
+
+ if( bAttrSetChg )
+ {
+ const SwAttrSet* pChgSet = ((SwAttrSetChg*)pNew)->GetChgSet();
+ pChgSet->GetItemState( RES_FRM_SIZE, sal_False, &pItem);
+ if ( !pItem )
+ pChgSet->GetItemState( RES_ROW_SPLIT, sal_False, &pItem);
+ }
+ else if ( RES_FRM_SIZE == pNew->Which() || RES_ROW_SPLIT == pNew->Which() )
+ pItem = pNew;
+
+ if ( pItem )
+ {
+ SwTabFrm *pTab = FindTabFrm();
+ if ( pTab )
+ {
+ const bool bInFirstNonHeadlineRow = pTab->IsFollow() &&
+ this == pTab->GetFirstNonHeadlineRow();
+ // --> FME 2004-10-27 #i35063#
+ // Invalidation required is pRow is last row
+ if ( bInFirstNonHeadlineRow || !GetNext() )
+ // <--
+ {
+ if ( bInFirstNonHeadlineRow )
+ pTab = pTab->FindMaster();
+ pTab->InvalidatePos();
+ }
+ }
+ }
+
+ SwLayoutFrm::Modify( pOld, pNew );
+}
+
+
+
+/*************************************************************************
+|*
+|* SwRowFrm::MakeAll()
+|*
+|*************************************************************************/
+void SwRowFrm::MakeAll()
+{
+ if ( !GetNext() )
+ bValidSize = sal_False;
+ SwLayoutFrm::MakeAll();
+}
+
+/*************************************************************************
+|*
+|* SwRowFrm::Format()
+|*
+|*************************************************************************/
+long MA_FASTCALL CalcHeightWidthFlys( const SwFrm *pFrm )
+{
+ SWRECTFN( pFrm )
+ long nHeight = 0;
+ const SwFrm* pTmp = pFrm->IsSctFrm() ?
+ ((SwSectionFrm*)pFrm)->ContainsCntnt() : pFrm;
+ while( pTmp )
+ {
+ // --> OD 2004-10-08 #i26945# - consider follow text frames
+ const SwSortedObjs* pObjs( 0L );
+ bool bIsFollow( false );
+ if ( pTmp->IsTxtFrm() && static_cast<const SwTxtFrm*>(pTmp)->IsFollow() )
+ {
+ const SwFrm* pMaster;
+ // --> FME 2005-04-01 #i46450# Master does not necessarily have
+ // to exist if this function is called from JoinFrm() ->
+ // Cut() -> Shrink()
+ const SwTxtFrm* pTmpFrm = static_cast<const SwTxtFrm*>(pTmp);
+ if ( pTmpFrm->GetPrev() && pTmpFrm->GetPrev()->IsTxtFrm() &&
+ static_cast<const SwTxtFrm*>(pTmpFrm->GetPrev())->GetFollow() &&
+ static_cast<const SwTxtFrm*>(pTmpFrm->GetPrev())->GetFollow() != pTmp )
+ pMaster = 0;
+ else
+ pMaster = pTmpFrm->FindMaster();
+
+ if ( pMaster )
+ {
+ pObjs = static_cast<const SwTxtFrm*>(pTmp)->FindMaster()->GetDrawObjs();
+ bIsFollow = true;
+ }
+ }
+ else
+ {
+ pObjs = pTmp->GetDrawObjs();
+ }
+ if ( pObjs )
+ // <--
+ {
+ for ( sal_uInt16 i = 0; i < pObjs->Count(); ++i )
+ {
+ const SwAnchoredObject* pAnchoredObj = (*pObjs)[i];
+ // --> OD 2004-10-08 #i26945# - if <pTmp> is follow, the
+ // anchor character frame has to be <pTmp>.
+ if ( bIsFollow &&
+ const_cast<SwAnchoredObject*>(pAnchoredObj)->FindAnchorCharFrm() != pTmp )
+ {
+ continue;
+ }
+ // <--
+ // --> OD 2004-10-04 #i26945# - consider also drawing objects
+ {
+ // OD 30.09.2003 #i18732# - only objects, which follow
+ // the text flow have to be considered.
+ const SwFrmFmt& rFrmFmt = pAnchoredObj->GetFrmFmt();
+ const bool bConsiderObj =
+ (rFrmFmt.GetAnchor().GetAnchorId() != FLY_AS_CHAR) &&
+ pAnchoredObj->GetObjRect().Top() != WEIT_WECH &&
+ rFrmFmt.GetFollowTextFlow().GetValue() &&
+ pAnchoredObj->GetPageFrm() == pTmp->FindPageFrm();
+ if ( bConsiderObj )
+ {
+ const SwFmtFrmSize &rSz = rFrmFmt.GetFrmSize();
+ if( !rSz.GetHeightPercent() )
+ {
+ const SwTwips nDistOfFlyBottomToAnchorTop =
+ (pAnchoredObj->GetObjRect().*fnRect->fnGetHeight)() +
+ ( bVert ?
+ pAnchoredObj->GetCurrRelPos().X() :
+ pAnchoredObj->GetCurrRelPos().Y() );
+
+ const SwTwips nFrmDiff =
+ (*fnRect->fnYDiff)(
+ (pTmp->Frm().*fnRect->fnGetTop)(),
+ (pFrm->Frm().*fnRect->fnGetTop)() );
+
+ nHeight = Max( nHeight, nDistOfFlyBottomToAnchorTop + nFrmDiff -
+ (pFrm->Frm().*fnRect->fnGetHeight)() );
+
+ // --> FME 2006-01-24 #i56115# The first height calculation
+ // gives wrong results if pFrm->Prt().Y() > 0. We do
+ // a second calculation based on the actual rectangles of
+ // pFrm and pAnchoredObj, and use the maximum of the results.
+ // I do not want to remove the first calculation because
+ // if clipping has been applied, using the GetCurrRelPos
+ // might be the better option to calculate nHeight.
+ const SwTwips nDistOfFlyBottomToAnchorTop2 = (*fnRect->fnYDiff)(
+ (pAnchoredObj->GetObjRect().*fnRect->fnGetBottom)(),
+ (pFrm->Frm().*fnRect->fnGetBottom)() );
+
+ nHeight = Max( nHeight, nDistOfFlyBottomToAnchorTop2 );
+ // <--
+ }
+ }
+ }
+ // <--
+ }
+ }
+ if( !pFrm->IsSctFrm() )
+ break;
+ pTmp = pTmp->FindNextCnt();
+ if( !((SwSectionFrm*)pFrm)->IsAnLower( pTmp ) )
+ break;
+ }
+ return nHeight;
+}
+
+SwTwips lcl_CalcTopAndBottomMargin( const SwLayoutFrm& rCell, const SwBorderAttrs& rAttrs )
+{
+ const SwTabFrm* pTab = rCell.FindTabFrm();
+ SwTwips nTopSpace = 0;
+ SwTwips nBottomSpace = 0;
+
+ // --> collapsing borders FME 2005-05-27 #i29550#
+ if ( pTab->IsCollapsingBorders() && rCell.Lower() && !rCell.Lower()->IsRowFrm() )
+ {
+ nTopSpace = ((SwRowFrm*)rCell.GetUpper())->GetTopMarginForLowers();
+ nBottomSpace = ((SwRowFrm*)rCell.GetUpper())->GetBottomMarginForLowers();
+ }
+ // <-- collapsing
+ else
+ {
+ if ( pTab->IsVertical() != rCell.IsVertical() )
+ {
+ nTopSpace = rAttrs.CalcLeft( &rCell );
+ nBottomSpace = rAttrs.CalcRight( &rCell );
+ }
+ else
+ {
+ nTopSpace = rAttrs.CalcTop();
+ nBottomSpace = rAttrs.CalcBottom();
+ }
+ }
+
+ return nTopSpace + nBottomSpace;
+}
+
+
+// --> OD 2004-10-04 #i26945# - add parameter <_bConsiderObjs> in order to
+// control, if floating screen objects have to be considered for the minimal
+// cell height.
+SwTwips MA_FASTCALL lcl_CalcMinCellHeight( const SwLayoutFrm *_pCell,
+ const sal_Bool _bConsiderObjs,
+ const SwBorderAttrs *pAttrs = 0 )
+{
+ SWRECTFN( _pCell )
+ SwTwips nHeight = 0;
+ const SwFrm* pLow = _pCell->Lower();
+ if ( pLow )
+ {
+ long nFlyAdd = 0;
+ while ( pLow )
+ {
+ // OD 2004-02-18 #106629# - change condition and switch then-body
+ // and else-body
+ if ( pLow->IsRowFrm() )
+ {
+ // --> OD 2004-10-04 #i26945#
+ nHeight += ::lcl_CalcMinRowHeight( static_cast<const SwRowFrm*>(pLow),
+ _bConsiderObjs );
+ // <--
+ }
+ else
+ {
+ long nLowHeight = (pLow->Frm().*fnRect->fnGetHeight)();
+ nHeight += nLowHeight;
+ // --> OD 2004-10-04 #i26945#
+ if ( _bConsiderObjs )
+ {
+ nFlyAdd = Max( 0L, nFlyAdd - nLowHeight );
+ nFlyAdd = Max( nFlyAdd, ::CalcHeightWidthFlys( pLow ) );
+ }
+ // <--
+ }
+
+ pLow = pLow->GetNext();
+ }
+ if ( nFlyAdd )
+ nHeight += nFlyAdd;
+ }
+ //Der Border will natuerlich auch mitspielen, er kann leider nicht
+ //aus PrtArea und Frm errechnet werden, da diese in beliebiger
+ //Kombination ungueltig sein koennen.
+ if ( _pCell->Lower() )
+ {
+ if ( pAttrs )
+ nHeight += lcl_CalcTopAndBottomMargin( *_pCell, *pAttrs );
+ else
+ {
+ SwBorderAttrAccess aAccess( SwFrm::GetCache(), _pCell );
+ const SwBorderAttrs &rAttrs = *aAccess.Get();
+ nHeight += lcl_CalcTopAndBottomMargin( *_pCell, rAttrs );
+ }
+ }
+ return nHeight;
+}
+
+// OD 2004-02-18 #106629# - correct type of 1st parameter
+// --> OD 2004-10-04 #i26945# - add parameter <_bConsiderObjs> in order to control,
+// if floating screen objects have to be considered for the minimal cell height
+SwTwips MA_FASTCALL lcl_CalcMinRowHeight( const SwRowFrm* _pRow,
+ const sal_Bool _bConsiderObjs )
+{
+ SWRECTFN( _pRow )
+
+ const SwFmtFrmSize &rSz = _pRow->GetFmt()->GetFrmSize();
+
+ if ( _pRow->HasFixSize() && !_pRow->IsRowSpanLine() )
+ {
+ OSL_ENSURE( ATT_FIX_SIZE == rSz.GetHeightSizeType(), "pRow claims to have fixed size" );
+ return rSz.GetHeight();
+ }
+
+ SwTwips nHeight = 0;
+ const SwCellFrm* pLow = static_cast<const SwCellFrm*>(_pRow->Lower());
+ while ( pLow )
+ {
+ SwTwips nTmp = 0;
+ const long nRowSpan = pLow->GetLayoutRowSpan();
+ // --> NEW TABLES
+ // Consider height of
+ // 1. current cell if RowSpan == 1
+ // 2. current cell if cell is "follow" cell of a cell with RowSpan == -1
+ // 3. master cell if RowSpan == -1
+ if ( 1 == nRowSpan )
+ {
+ nTmp = ::lcl_CalcMinCellHeight( pLow, _bConsiderObjs );
+ }
+ else if ( -1 == nRowSpan )
+ {
+ // Height of the last cell of a row span is height of master cell
+ // minus the height of the other rows which are covered by the master
+ // cell:
+ const SwCellFrm& rMaster = pLow->FindStartEndOfRowSpanCell( true, true );
+ nTmp = ::lcl_CalcMinCellHeight( &rMaster, _bConsiderObjs );
+ const SwFrm* pMasterRow = rMaster.GetUpper();
+ while ( pMasterRow && pMasterRow != _pRow )
+ {
+ nTmp -= (pMasterRow->Frm().*fnRect->fnGetHeight)();
+ pMasterRow = pMasterRow->GetNext();
+ }
+ }
+ // <-- NEW TABLES
+
+ // Do not consider rotated cells:
+ if ( ( 0 != pLow->IsVertical() ) == ( 0 != bVert ) && nTmp > nHeight )
+ nHeight = nTmp;
+
+ pLow = static_cast<const SwCellFrm*>(pLow->GetNext());
+ }
+ if ( rSz.GetHeightSizeType() == ATT_MIN_SIZE && !_pRow->IsRowSpanLine() )
+ nHeight = Max( nHeight, rSz.GetHeight() );
+ return nHeight;
+}
+
+// --> collapsing borders FME 2005-05-27 #i29550#
+
+// Calculate the maximum of (TopLineSize + TopLineDist) over all lowers:
+sal_uInt16 lcl_GetTopSpace( const SwRowFrm& rRow )
+{
+ sal_uInt16 nTopSpace = 0;
+ for ( SwCellFrm* pCurrLower = (SwCellFrm*)rRow.Lower(); pCurrLower;
+ pCurrLower = (SwCellFrm*)pCurrLower->GetNext() )
+ {
+ sal_uInt16 nTmpTopSpace = 0;
+ if ( pCurrLower->Lower() && pCurrLower->Lower()->IsRowFrm() )
+ nTmpTopSpace = lcl_GetTopSpace( *(SwRowFrm*)pCurrLower->Lower() );
+ else
+ {
+ const SwAttrSet& rSet = ((SwCellFrm*)pCurrLower)->GetFmt()->GetAttrSet();
+ const SvxBoxItem& rBoxItem = rSet.GetBox();
+ nTmpTopSpace = rBoxItem.CalcLineSpace( BOX_LINE_TOP, sal_True );
+ }
+ nTopSpace = Max( nTopSpace, nTmpTopSpace );
+ }
+ return nTopSpace;
+}
+
+// Calculate the maximum of TopLineDist over all lowers:
+sal_uInt16 lcl_GetTopLineDist( const SwRowFrm& rRow )
+{
+ sal_uInt16 nTopLineDist = 0;
+ for ( SwCellFrm* pCurrLower = (SwCellFrm*)rRow.Lower(); pCurrLower;
+ pCurrLower = (SwCellFrm*)pCurrLower->GetNext() )
+ {
+ sal_uInt16 nTmpTopLineDist = 0;
+ if ( pCurrLower->Lower() && pCurrLower->Lower()->IsRowFrm() )
+ nTmpTopLineDist = lcl_GetTopLineDist( *(SwRowFrm*)pCurrLower->Lower() );
+ else
+ {
+ const SwAttrSet& rSet = ((SwCellFrm*)pCurrLower)->GetFmt()->GetAttrSet();
+ const SvxBoxItem& rBoxItem = rSet.GetBox();
+ nTmpTopLineDist = rBoxItem.GetDistance( BOX_LINE_TOP );
+ }
+ nTopLineDist = Max( nTopLineDist, nTmpTopLineDist );
+ }
+ return nTopLineDist;
+}
+
+// Calculate the maximum of BottomLineSize over all lowers:
+sal_uInt16 lcl_GetBottomLineSize( const SwRowFrm& rRow )
+{
+ sal_uInt16 nBottomLineSize = 0;
+ for ( SwCellFrm* pCurrLower = (SwCellFrm*)rRow.Lower(); pCurrLower;
+ pCurrLower = (SwCellFrm*)pCurrLower->GetNext() )
+ {
+ sal_uInt16 nTmpBottomLineSize = 0;
+ if ( pCurrLower->Lower() && pCurrLower->Lower()->IsRowFrm() )
+ {
+ const SwFrm* pRow = pCurrLower->GetLastLower();
+ nTmpBottomLineSize = lcl_GetBottomLineSize( *(SwRowFrm*)pRow );
+ }
+ else
+ {
+ const SwAttrSet& rSet = ((SwCellFrm*)pCurrLower)->GetFmt()->GetAttrSet();
+ const SvxBoxItem& rBoxItem = rSet.GetBox();
+ nTmpBottomLineSize = rBoxItem.CalcLineSpace( BOX_LINE_BOTTOM, sal_True ) -
+ rBoxItem.GetDistance( BOX_LINE_BOTTOM );
+ }
+ nBottomLineSize = Max( nBottomLineSize, nTmpBottomLineSize );
+ }
+ return nBottomLineSize;
+}
+
+// Calculate the maximum of BottomLineDist over all lowers:
+sal_uInt16 lcl_GetBottomLineDist( const SwRowFrm& rRow )
+{
+ sal_uInt16 nBottomLineDist = 0;
+ for ( SwCellFrm* pCurrLower = (SwCellFrm*)rRow.Lower(); pCurrLower;
+ pCurrLower = (SwCellFrm*)pCurrLower->GetNext() )
+ {
+ sal_uInt16 nTmpBottomLineDist = 0;
+ if ( pCurrLower->Lower() && pCurrLower->Lower()->IsRowFrm() )
+ {
+ const SwFrm* pRow = pCurrLower->GetLastLower();
+ nTmpBottomLineDist = lcl_GetBottomLineDist( *(SwRowFrm*)pRow );
+ }
+ else
+ {
+ const SwAttrSet& rSet = ((SwCellFrm*)pCurrLower)->GetFmt()->GetAttrSet();
+ const SvxBoxItem& rBoxItem = rSet.GetBox();
+ nTmpBottomLineDist = rBoxItem.GetDistance( BOX_LINE_BOTTOM );
+ }
+ nBottomLineDist = Max( nBottomLineDist, nTmpBottomLineDist );
+ }
+ return nBottomLineDist;
+}
+
+// <-- collapsing
+
+void SwRowFrm::Format( const SwBorderAttrs *pAttrs )
+{
+ SWRECTFN( this )
+ OSL_ENSURE( pAttrs, "SwRowFrm::Format ohne Attrs." );
+
+ const sal_Bool bFix = bFixSize;
+
+ if ( !bValidPrtArea )
+ {
+ //RowFrms haben keine Umrandung usw. also entspricht die PrtArea immer
+ //dem Frm.
+ bValidPrtArea = sal_True;
+ aPrt.Left( 0 );
+ aPrt.Top( 0 );
+ aPrt.Width ( aFrm.Width() );
+ aPrt.Height( aFrm.Height() );
+
+ // --> collapsing borders FME 2005-05-27 #i29550#
+ // Here we calculate the top-printing area for the lower cell frames
+ SwTabFrm* pTabFrm = FindTabFrm();
+ if ( pTabFrm->IsCollapsingBorders() )
+ {
+ const sal_uInt16 nTopSpace = lcl_GetTopSpace( *this );
+ const sal_uInt16 nTopLineDist = lcl_GetTopLineDist( *this );
+ const sal_uInt16 nBottomLineSize = lcl_GetBottomLineSize( *this );
+ const sal_uInt16 nBottomLineDist = lcl_GetBottomLineDist( *this );
+
+
+ const SwRowFrm* pPreviousRow = 0;
+
+ // --> FME 2004-09-14 #i32456#
+ // In order to calculate the top printing area for the lower cell
+ // frames, we have to find the 'previous' row frame and compare
+ // the bottom values of the 'previous' row with the 'top' values
+ // of this row. The best way to find the 'previous' row is to
+ // use the table structure:
+ const SwTable* pTable = pTabFrm->GetTable();
+ const SwTableLine* pPrevTabLine = 0;
+ const SwRowFrm* pTmpRow = this;
+
+ while ( pTmpRow && !pPrevTabLine )
+ {
+ sal_uInt16 nIdx = 0;
+ const SwTableLines& rLines = pTmpRow->GetTabLine()->GetUpper() ?
+ pTmpRow->GetTabLine()->GetUpper()->GetTabLines() :
+ pTable->GetTabLines();
+
+ while ( rLines[ nIdx ] != pTmpRow->GetTabLine() )
+ ++nIdx;
+
+ if ( nIdx > 0 )
+ {
+ // pTmpRow has a 'previous' row in the table structure:
+ pPrevTabLine = rLines[ nIdx - 1 ];
+ }
+ else
+ {
+ // pTmpRow is a first row in the table structue.
+ // We go up in the table structure:
+ pTmpRow = pTmpRow->GetUpper()->GetUpper() &&
+ pTmpRow->GetUpper()->GetUpper()->IsRowFrm() ?
+ static_cast<const SwRowFrm*>( pTmpRow->GetUpper()->GetUpper() ) :
+ 0;
+ }
+ }
+
+ // If we found a 'previous' row, we look for the appropriate row frame:
+ if ( pPrevTabLine )
+ {
+ SwIterator<SwRowFrm,SwFmt> aIter( *pPrevTabLine->GetFrmFmt() );
+ for ( SwRowFrm* pRow = aIter.First(); pRow; pRow = aIter.Next() )
+ {
+ // --> OD 2004-11-23 #115759# - do *not* take repeated
+ // headlines, because during split of table it can be
+ // invalid and thus can't provide correct border values.
+ if ( pRow->GetTabLine() == pPrevTabLine &&
+ !pRow->IsRepeatedHeadline() )
+ // <--
+ {
+ pPreviousRow = pRow;
+ break;
+ }
+ }
+ }
+ // <--
+
+ sal_uInt16 nTopPrtMargin = nTopSpace;
+ if ( pPreviousRow )
+ {
+ const sal_uInt16 nTmpPrtMargin = pPreviousRow->GetBottomLineSize() + nTopLineDist;
+ if ( nTmpPrtMargin > nTopPrtMargin )
+ nTopPrtMargin = nTmpPrtMargin;
+ }
+
+ // table has to be notified if it has to change its lower
+ // margin due to changes of nBottomLineSize:
+ if ( !GetNext() && nBottomLineSize != GetBottomLineSize() )
+ pTabFrm->_InvalidatePrt();
+
+ // If there are rows nested inside this row, the nested rows
+ // may not have been calculated yet. Therefore the
+ // ::lcl_CalcMinRowHeight( this ) operation later in this
+ // function cannot consider the correct border values. We
+ // have to trigger the invalidation of the outer row frame
+ // manually:
+ // Note: If any further invalidations should be necessary, we
+ // should consider moving the invalidation stuff to the
+ // appropriate SwNotify object.
+ if ( GetUpper()->GetUpper()->IsRowFrm() &&
+ ( nBottomLineDist != GetBottomMarginForLowers() ||
+ nTopPrtMargin != GetTopMarginForLowers() ) )
+ GetUpper()->GetUpper()->_InvalidateSize();
+
+ SetBottomMarginForLowers( nBottomLineDist ); // 3.
+ SetBottomLineSize( nBottomLineSize ); // 4.
+ SetTopMarginForLowers( nTopPrtMargin ); // 5.
+
+ }
+// <-- collapsing
+ }
+
+ while ( !bValidSize )
+ {
+ bValidSize = sal_True;
+
+#if OSL_DEBUG_LEVEL > 1
+ if ( HasFixSize() )
+ {
+ const SwFmtFrmSize &rFrmSize = GetFmt()->GetFrmSize();
+ OSL_ENSURE( rFrmSize.GetSize().Height() > 0, "Hat ihn" );
+ }
+#endif
+ const SwTwips nDiff = (Frm().*fnRect->fnGetHeight)() -
+ ( HasFixSize() && !IsRowSpanLine()
+ ? pAttrs->GetSize().Height()
+ // --> OD 2004-10-04 #i26945#
+ : ::lcl_CalcMinRowHeight( this,
+ FindTabFrm()->IsConsiderObjsForMinCellHeight() ) );
+ // <--
+ if ( nDiff )
+ {
+ bFixSize = sal_False;
+ if ( nDiff > 0 )
+ Shrink( nDiff, sal_False, sal_True );
+ else if ( nDiff < 0 )
+ Grow( -nDiff );
+ bFixSize = bFix;
+ }
+ }
+
+ // last row will fill the space in its upper.
+ if ( !GetNext() )
+ {
+ //Der letzte fuellt den verbleibenden Raum im Upper aus.
+ SwTwips nDiff = (GetUpper()->Prt().*fnRect->fnGetHeight)();
+ SwFrm *pSibling = GetUpper()->Lower();
+ do
+ { nDiff -= (pSibling->Frm().*fnRect->fnGetHeight)();
+ pSibling = pSibling->GetNext();
+ } while ( pSibling );
+ if ( nDiff > 0 )
+ {
+ bFixSize = sal_False;
+ Grow( nDiff );
+ bFixSize = bFix;
+ bValidSize = sal_True;
+ }
+ }
+}
+
+/*************************************************************************
+|*
+|* SwRowFrm::AdjustCells()
+|*
+|*************************************************************************/
+void SwRowFrm::AdjustCells( const SwTwips nHeight, const sal_Bool bHeight )
+{
+ SwFrm *pFrm = Lower();
+ if ( bHeight )
+ {
+ SwRootFrm *pRootFrm = getRootFrm();
+ SWRECTFN( this )
+ SwRect aOldFrm;
+
+ while ( pFrm )
+ {
+ SwFrm* pNotify = 0;
+
+ SwCellFrm* pCellFrm = static_cast<SwCellFrm*>(pFrm);
+
+ // NEW TABLES
+ // Which cells need to be adjusted if the current row changes
+ // its height?
+
+ // Current frame is a covered frame:
+ // Set new height for covered cell and adjust master cell:
+ if ( pCellFrm->GetTabBox()->getRowSpan() < 1 )
+ {
+ // Set height of current (covered) cell to new line height.
+ const long nDiff = nHeight - (pCellFrm->Frm().*fnRect->fnGetHeight)();
+ if ( nDiff )
+ {
+ (pCellFrm->Frm().*fnRect->fnAddBottom)( nDiff );
+ pCellFrm->_InvalidatePrt();
+ }
+ }
+
+ SwCellFrm* pToAdjust = 0;
+ SwFrm* pToAdjustRow = 0;
+
+ // If current frame is covered frame, we still want to adjust the
+ // height of the cell starting the row span
+ if ( pCellFrm->GetLayoutRowSpan() < 1 )
+ {
+ pToAdjust = const_cast< SwCellFrm*>(&pCellFrm->FindStartEndOfRowSpanCell( true, true ));
+ pToAdjustRow = pToAdjust->GetUpper();
+ }
+ else
+ {
+ pToAdjust = pCellFrm;
+ pToAdjustRow = this;
+ }
+
+ // Set height of master cell to height of all lines spanned by this line.
+ long nRowSpan = pToAdjust->GetLayoutRowSpan();
+ SwTwips nSumRowHeight = 0;
+ while ( pToAdjustRow )
+ {
+ // Use new height for the current row:
+ nSumRowHeight += pToAdjustRow == this ?
+ nHeight :
+ (pToAdjustRow->Frm().*fnRect->fnGetHeight)();
+
+ if ( nRowSpan-- == 1 )
+ break;
+
+ pToAdjustRow = pToAdjustRow->GetNext();
+ }
+
+ if ( pToAdjustRow && pToAdjustRow != this )
+ pToAdjustRow->_InvalidateSize();
+
+ const long nDiff = nSumRowHeight - (pToAdjust->Frm().*fnRect->fnGetHeight)();
+ if ( nDiff )
+ {
+ aOldFrm = pToAdjust->Frm();
+ (pToAdjust->Frm().*fnRect->fnAddBottom)( nDiff );
+ pNotify = pToAdjust;
+ }
+
+ if ( pNotify )
+ {
+ if( pRootFrm && pRootFrm->IsAnyShellAccessible() && pRootFrm->GetCurrShell() )
+ pRootFrm->GetCurrShell()->Imp()->MoveAccessibleFrm( pNotify, aOldFrm );
+
+ pNotify->_InvalidatePrt();
+ }
+
+ pFrm = pFrm->GetNext();
+ }
+ }
+ else
+ { while ( pFrm )
+ {
+ pFrm->_InvalidateAll();
+ pFrm = pFrm->GetNext();
+ }
+ }
+ InvalidatePage();
+}
+
+/*************************************************************************
+|*
+|* SwRowFrm::Cut()
+|*
+|*************************************************************************/
+void SwRowFrm::Cut()
+{
+ SwTabFrm *pTab = FindTabFrm();
+ if ( pTab && pTab->IsFollow() && this == pTab->GetFirstNonHeadlineRow() )
+ {
+ pTab->FindMaster()->InvalidatePos();
+ }
+
+ // --> OD 2010-02-17 #i103961#
+ // notification for accessibility
+ {
+ SwRootFrm *pRootFrm = getRootFrm();
+ if( pRootFrm && pRootFrm->IsAnyShellAccessible() )
+ {
+ ViewShell* pVSh = pRootFrm->GetCurrShell();
+ if ( pVSh && pVSh->Imp() )
+ {
+ SwFrm* pCellFrm( GetLower() );
+ while ( pCellFrm )
+ {
+ OSL_ENSURE( pCellFrm->IsCellFrm(),
+ "<SwRowFrm::Cut()> - unexpected type of SwRowFrm lower." );
+ pVSh->Imp()->DisposeAccessibleFrm( pCellFrm );
+
+ pCellFrm = pCellFrm->GetNext();
+ }
+ }
+ }
+ }
+ // <--
+
+ SwLayoutFrm::Cut();
+}
+
+/*************************************************************************
+|*
+|* SwRowFrm::GrowFrm()
+|*
+|*************************************************************************/
+
+
+SwTwips SwRowFrm::GrowFrm( SwTwips nDist, sal_Bool bTst, sal_Bool bInfo )
+{
+ SwTwips nReal = 0;
+
+ SwTabFrm* pTab = FindTabFrm();
+ SWRECTFN( pTab )
+
+ bool bRestrictTableGrowth;
+ bool bHasFollowFlowLine = pTab->HasFollowFlowLine();
+
+ if ( GetUpper()->IsTabFrm() )
+ {
+ const SwRowFrm* pFollowFlowRow = IsInSplitTableRow();
+ bRestrictTableGrowth = pFollowFlowRow && !pFollowFlowRow->IsRowSpanLine();
+ }
+ else
+ {
+ OSL_ENSURE( GetUpper()->IsCellFrm(), "RowFrm->GetUpper neither table nor cell" );
+ bRestrictTableGrowth = GetFollowRow() && bHasFollowFlowLine;
+ OSL_ENSURE( !bRestrictTableGrowth || !GetNext(),
+ "GetFollowRow for row frame that has a Next" );
+
+ //
+ // There may still be some space left in my direct upper:
+ //
+ const SwTwips nAdditionalSpace =
+ (Frm().*fnRect->fnBottomDist)( (GetUpper()->GetUpper()->*fnRect->fnGetPrtBottom)() );
+ if ( bRestrictTableGrowth && nAdditionalSpace > 0 )
+ {
+ nReal = Min( nAdditionalSpace, nDist );
+ nDist -= nReal;
+ if ( !bTst )
+ (Frm().*fnRect->fnAddBottom)( nReal );
+ }
+ }
+
+ if ( bRestrictTableGrowth )
+ pTab->SetRestrictTableGrowth( sal_True );
+ else
+ {
+ // Ok, this looks like a hack, indeed, it is a hack.
+ // If the current row frame is inside another cell frame,
+ // and the current row frame has no follow, it should not
+ // be allowed to grow. In fact, setting bRestrictTableGrowth
+ // to 'false' does not work, because the surrounding RowFrm
+ // would set this to 'true'.
+ pTab->SetFollowFlowLine( sal_False );
+ }
+
+ nReal += SwLayoutFrm::GrowFrm( nDist, bTst, bInfo);
+
+ pTab->SetRestrictTableGrowth( sal_False );
+ pTab->SetFollowFlowLine( bHasFollowFlowLine );
+
+ //Hoehe der Zellen auf den neuesten Stand bringen.
+ if ( !bTst )
+ {
+ SWRECTFNX( this )
+ AdjustCells( (Prt().*fnRectX->fnGetHeight)() + nReal, sal_True );
+ if ( nReal )
+ SetCompletePaint();
+ }
+
+ return nReal;
+}
+
+/*************************************************************************
+|*
+|* SwRowFrm::ShrinkFrm()
+|*
+|*************************************************************************/
+SwTwips SwRowFrm::ShrinkFrm( SwTwips nDist, sal_Bool bTst, sal_Bool bInfo )
+{
+ SWRECTFN( this )
+ if( HasFixSize() )
+ {
+ AdjustCells( (Prt().*fnRect->fnGetHeight)(), sal_True );
+ return 0L;
+ }
+
+ //bInfo wird ggf. vom SwRowFrm::Format auf sal_True gesetzt, hier muss dann
+ //entsprechend reagiert werden
+ const sal_Bool bShrinkAnyway = bInfo;
+
+ //Nur soweit Shrinken, wie es der Inhalt der groessten Zelle zulaesst.
+ SwTwips nRealDist = nDist;
+ {
+ const SwFmtFrmSize &rSz = GetFmt()->GetFrmSize();
+ SwTwips nMinHeight = rSz.GetHeightSizeType() == ATT_MIN_SIZE ?
+ rSz.GetHeight() :
+ 0;
+
+ // Only necessary to calculate minimal row height if height
+ // of pRow is at least nMinHeight. Otherwise nMinHeight is the
+ // minimum height.
+ if( nMinHeight < (Frm().*fnRect->fnGetHeight)() )
+ {
+ // --> OD 2004-10-04 #i26945#
+ OSL_ENSURE( FindTabFrm(), "<SwRowFrm::ShrinkFrm(..)> - no table frame -> crash." );
+ const bool bConsiderObjs( FindTabFrm()->IsConsiderObjsForMinCellHeight() );
+ // <--
+ nMinHeight = lcl_CalcMinRowHeight( this, bConsiderObjs );
+ }
+
+ if ( ((Frm().*fnRect->fnGetHeight)() - nRealDist) < nMinHeight )
+ nRealDist = (Frm().*fnRect->fnGetHeight)() - nMinHeight;
+ }
+ if ( nRealDist < 0 )
+ nRealDist = 0;
+
+ SwTwips nReal = nRealDist;
+ if ( nReal )
+ {
+ if ( !bTst )
+ {
+ SwTwips nHeight = (Frm().*fnRect->fnGetHeight)();
+ (Frm().*fnRect->fnSetHeight)( nHeight - nReal );
+ //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin
+ if( IsVertical() && !IsVertLR() && !bRev )
+ Frm().Pos().X() += nReal;
+ }
+
+ SwTwips nTmp = GetUpper()->Shrink( nReal, bTst );
+ if ( !bShrinkAnyway && !GetNext() && nTmp != nReal )
+ {
+ //Der letzte bekommt den Rest im Upper und nimmt deshalb
+ //ggf. Ruecksichten (sonst: Endlosschleife)
+ if ( !bTst )
+ {
+ nReal -= nTmp;
+ SwTwips nHeight = (Frm().*fnRect->fnGetHeight)();
+ (Frm().*fnRect->fnSetHeight)( nHeight + nReal );
+ //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin
+ if( IsVertical() && !IsVertLR() && !bRev )
+ Frm().Pos().X() -= nReal;
+ }
+ nReal = nTmp;
+ }
+ }
+
+ //Geeignet invalidieren und die Hoehe der Zellen auf den neuesten
+ //Stand bringen.
+ if ( !bTst )
+ {
+ if ( nReal )
+ {
+ if ( GetNext() )
+ GetNext()->_InvalidatePos();
+ _InvalidateAll();
+ SetCompletePaint();
+
+ SwTabFrm *pTab = FindTabFrm();
+ if ( !pTab->IsRebuildLastLine() && pTab->IsFollow() &&
+ this == pTab->GetFirstNonHeadlineRow() )
+ {
+ SwTabFrm* pMasterTab = const_cast< SwTabFrm* >( pTab->FindMaster() );
+ pMasterTab->InvalidatePos();
+ }
+ }
+ AdjustCells( (Prt().*fnRect->fnGetHeight)() - nReal, sal_True );
+ }
+ return nReal;
+}
+
+/*************************************************************************
+|*
+|* SwRowFrm::IsRowSplitAllowed()
+|*
+|*************************************************************************/
+bool SwRowFrm::IsRowSplitAllowed() const
+{
+ // Fixed size rows are never allowed to split:
+ if ( HasFixSize() )
+ {
+ OSL_ENSURE( ATT_FIX_SIZE == GetFmt()->GetFrmSize().GetHeightSizeType(), "pRow claims to have fixed size" );
+ return false;
+ }
+
+ // Repeated headlines are never allowed to split:
+ const SwTabFrm* pTabFrm = FindTabFrm();
+ if ( pTabFrm->GetTable()->GetRowsToRepeat() > 0 &&
+ pTabFrm->IsInHeadline( *this ) )
+ return false;
+
+ const SwTableLineFmt* pFrmFmt = (SwTableLineFmt*)GetTabLine()->GetFrmFmt();
+ const SwFmtRowSplit& rLP = pFrmFmt->GetRowSplit();
+ return 0 != rLP.GetValue();
+}
+
+/*************************************************************************
+|*
+|* SwRowFrm::ShouldRowKeepWithNext()
+|*
+|*************************************************************************/
+bool SwRowFrm::ShouldRowKeepWithNext() const
+{
+ bool bRet = false;
+
+ const SwCellFrm* pCell = static_cast<const SwCellFrm*>(Lower());
+ const SwFrm* pTxt = pCell->Lower();
+
+ if ( pTxt && pTxt->IsTxtFrm() )
+ {
+ bRet = static_cast<const SwTxtFrm*>(pTxt)->GetTxtNode()->GetSwAttrSet().GetKeep().GetValue();
+ }
+ return bRet;
+}
+
+/*************************************************************************
+|*
+|* SwCellFrm::SwCellFrm(), ~SwCellFrm()
+|*
+|*************************************************************************/
+SwCellFrm::SwCellFrm( const SwTableBox &rBox, SwFrm* pSib, bool bInsertContent ) :
+ SwLayoutFrm( rBox.GetFrmFmt(), pSib ),
+ pTabBox( &rBox )
+{
+ nType = FRMC_CELL;
+
+ if ( !bInsertContent )
+ return;
+
+ //Wenn ein StartIdx vorhanden ist, so werden CntntFrms in der Zelle
+ //angelegt, andernfalls muessen Rows vorhanden sein und diese werden
+ //angelegt.
+ if ( rBox.GetSttIdx() )
+ {
+ sal_uLong nIndex = rBox.GetSttIdx();
+ ::_InsertCnt( this, rBox.GetFrmFmt()->GetDoc(), ++nIndex );
+ }
+ else
+ {
+ const SwTableLines &rLines = rBox.GetTabLines();
+ SwFrm *pTmpPrev = 0;
+ for ( sal_uInt16 i = 0; i < rLines.Count(); ++i )
+ {
+ SwRowFrm *pNew = new SwRowFrm( *rLines[i], this, bInsertContent );
+ pNew->InsertBehind( this, pTmpPrev );
+ pTmpPrev = pNew;
+ }
+ }
+}
+
+SwCellFrm::~SwCellFrm()
+{
+ SwModify* pMod = GetFmt();
+ if( pMod )
+ {
+ // At this stage the lower frames aren't destroyed already,
+ // therfor we have to do a recursive dispose.
+ SwRootFrm *pRootFrm = getRootFrm();
+ if( pRootFrm && pRootFrm->IsAnyShellAccessible() &&
+ pRootFrm->GetCurrShell() )
+ {
+ pRootFrm->GetCurrShell()->Imp()->DisposeAccessibleFrm( this, sal_True );
+ }
+
+ pMod->Remove( this ); // austragen,
+ if( !pMod->GetDepends() )
+ delete pMod; // und loeschen
+ }
+}
+
+/*************************************************************************
+|*
+|* SwCellFrm::Format()
+|*
+|*************************************************************************/
+sal_Bool lcl_ArrangeLowers( SwLayoutFrm *pLay, long lYStart, sal_Bool bInva )
+{
+ sal_Bool bRet = sal_False;
+ SwFrm *pFrm = pLay->Lower();
+ SWRECTFN( pLay )
+ while ( pFrm )
+ {
+ long nFrmTop = (pFrm->Frm().*fnRect->fnGetTop)();
+ if( nFrmTop != lYStart )
+ {
+ bRet = sal_True;
+ const long lDiff = (*fnRect->fnYDiff)( lYStart, nFrmTop );
+ const long lDiffX = lYStart - nFrmTop;
+ (pFrm->Frm().*fnRect->fnSubTop)( -lDiff );
+ (pFrm->Frm().*fnRect->fnAddBottom)( lDiff );
+ pFrm->SetCompletePaint();
+ if ( !pFrm->GetNext() )
+ pFrm->SetRetouche();
+ if( bInva )
+ pFrm->Prepare( PREP_POS_CHGD );
+ if ( pFrm->IsLayoutFrm() && ((SwLayoutFrm*)pFrm)->Lower() )
+ lcl_ArrangeLowers( (SwLayoutFrm*)pFrm,
+ (((SwLayoutFrm*)pFrm)->Lower()->Frm().*fnRect->fnGetTop)()
+ + lDiffX, bInva );
+ if ( pFrm->GetDrawObjs() )
+ {
+ for ( sal_uInt16 i = 0; i < pFrm->GetDrawObjs()->Count(); ++i )
+ {
+ SwAnchoredObject* pAnchoredObj = (*pFrm->GetDrawObjs())[i];
+ // --> OD 2004-10-08 #i26945# - check, if anchored object
+ // is lower of layout frame by checking, if the anchor
+ // frame, which contains the anchor position, is a lower
+ // of the layout frame.
+ if ( !pLay->IsAnLower( pAnchoredObj->GetAnchorFrmContainingAnchPos() ) )
+ {
+ continue;
+ }
+ // <--
+ // --> OD 2005-08-08 #i52904# - distinguish between anchored
+ // objects, whose vertical position depends on its anchor
+ // frame and whose vertical position is independent
+ // from its anchor frame.
+ bool bVertPosDepOnAnchor( true );
+ {
+ SwFmtVertOrient aVert( pAnchoredObj->GetFrmFmt().GetVertOrient() );
+ switch ( aVert.GetRelationOrient() )
+ {
+ case text::RelOrientation::PAGE_FRAME:
+ case text::RelOrientation::PAGE_PRINT_AREA:
+ bVertPosDepOnAnchor = false;
+ break;
+ default: break;
+ }
+ }
+ if ( pAnchoredObj->ISA(SwFlyFrm) )
+ {
+ SwFlyFrm *pFly = static_cast<SwFlyFrm*>(pAnchoredObj);
+
+ // OD 2004-05-18 #i28701# - no direct move of objects,
+ // which are anchored to-paragraph/to-character, if
+ // the wrapping style influence has to be considered
+ // on the object positioning.
+ // --> OD 2005-08-08 #i52904# - no direct move of objects,
+ // whose vertical position doesn't depend on anchor frame.
+ const bool bDirectMove =
+ WEIT_WECH != pFly->Frm().Top() &&
+ bVertPosDepOnAnchor &&
+ !pFly->ConsiderObjWrapInfluenceOnObjPos();
+ // <--
+ if ( bDirectMove )
+ {
+ (pFly->Frm().*fnRect->fnSubTop)( -lDiff );
+ (pFly->Frm().*fnRect->fnAddBottom)( lDiff );
+ pFly->GetVirtDrawObj()->SetRectsDirty();
+ // --> OD 2004-08-17 - also notify view of <SdrObject>
+ // instance, which represents the Writer fly frame in
+ // the drawing layer
+ pFly->GetVirtDrawObj()->SetChanged();
+ // <--
+ // --> OD 2006-10-13 #i58280#
+ pFly->InvalidateObjRectWithSpaces();
+ // <--
+ }
+
+ if ( pFly->IsFlyInCntFrm() )
+ {
+ static_cast<SwFlyInCntFrm*>(pFly)->AddRefOfst( lDiff );
+ // --> OD 2004-12-02 #115759# - reset current relative
+ // position to get re-positioned, if not directly moved.
+ if ( !bDirectMove )
+ {
+ pAnchoredObj->SetCurrRelPos( Point( 0, 0 ) );
+ }
+ // <--
+ }
+ else if( pFly->IsAutoPos() )
+ {
+ pFly->AddLastCharY( lDiff );
+ // OD 2004-05-18 #i28701# - follow-up of #i22341#
+ // <mnLastTopOfLine> has also been adjusted.
+ pFly->AddLastTopOfLineY( lDiff );
+ }
+ // --> OD 2004-11-05 #i26945# - re-registration at
+ // page frame of anchor frame, if table frame isn't
+ // a follow table and table frame isn't in its
+ // rebuild of last line.
+ const SwTabFrm* pTabFrm = pLay->FindTabFrm();
+ // --> OD 2004-11-23 #115759#
+ // - save: check, if table frame is found.
+ if ( pTabFrm &&
+ !( pTabFrm->IsFollow() &&
+ pTabFrm->FindMaster()->IsRebuildLastLine() ) &&
+ pFly->IsFlyFreeFrm() )
+ // <--
+ {
+ SwPageFrm* pPageFrm = pFly->GetPageFrm();
+ SwPageFrm* pPageOfAnchor = pFrm->FindPageFrm();
+ if ( pPageFrm != pPageOfAnchor )
+ {
+ pFly->InvalidatePos();
+ if ( pPageFrm )
+ pPageFrm->MoveFly( pFly, pPageOfAnchor );
+ else
+ pPageOfAnchor->AppendFlyToPage( pFly );
+ }
+ }
+ // <--
+ // OD 2004-05-11 #i28701# - Because of the introduction
+ // of new positionings and alignments (e.g. aligned at
+ // page area, but anchored at-character), the position
+ // of the Writer fly frame has to be invalidated.
+ pFly->InvalidatePos();
+
+ // --> OD 2004-11-04 #i26945# - follow-up of #i3317#
+ // No arrangement of lowers, if Writer fly frame isn't
+ // moved
+ if ( bDirectMove &&
+ ::lcl_ArrangeLowers( pFly,
+ (pFly->*fnRect->fnGetPrtTop)(),
+ bInva ) )
+ // <--
+ {
+ pFly->SetCompletePaint();
+ }
+ }
+ else if ( pAnchoredObj->ISA(SwAnchoredDrawObject) )
+ {
+ // --> OD 2004-11-05 #i26945#
+ const SwTabFrm* pTabFrm = pLay->FindTabFrm();
+ if ( pTabFrm &&
+ !( pTabFrm->IsFollow() &&
+ pTabFrm->FindMaster()->IsRebuildLastLine() ) &&
+ !pAnchoredObj->GetFrmFmt().GetAnchor().GetAnchorId()
+ == FLY_AS_CHAR )
+ {
+ SwPageFrm* pPageFrm = pAnchoredObj->GetPageFrm();
+ SwPageFrm* pPageOfAnchor = pFrm->FindPageFrm();
+ if ( pPageFrm != pPageOfAnchor )
+ {
+ pAnchoredObj->InvalidateObjPos();
+ if ( pPageFrm )
+ {
+ pPageFrm->RemoveDrawObjFromPage( *pAnchoredObj );
+ }
+ pPageOfAnchor->AppendDrawObjToPage( *pAnchoredObj );
+ }
+ }
+ // --> OD 2004-07-01 #i28701# - adjust last character
+ // rectangle and last top of line.
+ pAnchoredObj->AddLastCharY( lDiff );
+ pAnchoredObj->AddLastTopOfLineY( lDiff );
+ // --> OD 2005-08-08 #i52904# - re-introduce direct move
+ // of drawing objects
+ const bool bDirectMove =
+ static_cast<const SwDrawFrmFmt&>(pAnchoredObj->GetFrmFmt()).IsPosAttrSet() &&
+ bVertPosDepOnAnchor &&
+ !pAnchoredObj->ConsiderObjWrapInfluenceOnObjPos();
+ if ( bDirectMove )
+ {
+ SwObjPositioningInProgress aObjPosInProgress( *pAnchoredObj );
+ if ( bVert )
+ {
+ pAnchoredObj->DrawObj()->Move( Size( lDiff, 0 ) );
+ }
+ else
+ {
+ pAnchoredObj->DrawObj()->Move( Size( 0, lDiff ) );
+ }
+ // --> OD 2006-10-13 #i58280#
+ pAnchoredObj->InvalidateObjRectWithSpaces();
+ // <--
+ }
+ // <--
+ pAnchoredObj->InvalidateObjPos();
+ }
+ else
+ {
+ OSL_FAIL( "<lcl_ArrangeLowers(..)> - unknown type of anchored object!" );
+ }
+ }
+ }
+ }
+ // Columns and cells are ordered horizontal, not vertical
+ if( !pFrm->IsColumnFrm() && !pFrm->IsCellFrm() )
+ lYStart = (*fnRect->fnYInc)( lYStart,
+ (pFrm->Frm().*fnRect->fnGetHeight)() );
+
+ // Nowadays, the content inside a cell can flow into the follow table.
+ // Thus, the cell may only grow up to the end of the environment.
+ // So the content may have grown, but the cell could not grow.
+ // Therefore we have to trigger a formatting for the frames, which do
+ // not fit into the cell anymore:
+ SwTwips nDistanceToUpperPrtBottom =
+ (pFrm->Frm().*fnRect->fnBottomDist)( (pLay->*fnRect->fnGetPrtBottom)());
+ // --> OD 2006-01-19 #i56146# - Revise fix of issue #i26945#
+ // do *not* consider content inside fly frames, if it's an undersized paragraph.
+ // --> OD 2004-10-08 #i26945# - consider content inside fly frames
+ if ( nDistanceToUpperPrtBottom < 0 &&
+ ( ( pFrm->IsInFly() &&
+ ( !pFrm->IsTxtFrm() ||
+ !static_cast<SwTxtFrm*>(pFrm)->IsUndersized() ) ) ||
+ pFrm->IsInSplitTableRow() ) )
+ // <--
+ {
+ pFrm->InvalidatePos();
+ }
+
+ pFrm = pFrm->GetNext();
+ }
+ return bRet;
+}
+
+void SwCellFrm::Format( const SwBorderAttrs *pAttrs )
+{
+ OSL_ENSURE( pAttrs, "CellFrm::Format, pAttrs ist 0." );
+ const SwTabFrm* pTab = FindTabFrm();
+ SWRECTFN( pTab )
+
+ if ( !bValidPrtArea )
+ {
+ bValidPrtArea = sal_True;
+
+ //Position einstellen.
+ if ( Lower() )
+ {
+ SwTwips nTopSpace, nBottomSpace, nLeftSpace, nRightSpace;
+ // --> collapsing borders FME 2005-05-27 #i29550#
+ if ( pTab->IsCollapsingBorders() && !Lower()->IsRowFrm() )
+ {
+ const SvxBoxItem& rBoxItem = pAttrs->GetBox();
+ nLeftSpace = rBoxItem.GetDistance( BOX_LINE_LEFT );
+ nRightSpace = rBoxItem.GetDistance( BOX_LINE_RIGHT );
+ nTopSpace = ((SwRowFrm*)GetUpper())->GetTopMarginForLowers();
+ nBottomSpace = ((SwRowFrm*)GetUpper())->GetBottomMarginForLowers();
+ }
+ else
+ {
+ // <-- collapsing
+ // OD 23.01.2003 #106895# - add 1st param to <SwBorderAttrs::CalcRight(..)>
+ nLeftSpace = pAttrs->CalcLeft( this );
+ nRightSpace = pAttrs->CalcRight( this );
+ nTopSpace = pAttrs->CalcTop();
+ nBottomSpace = pAttrs->CalcBottom();
+ }
+ (this->*fnRect->fnSetXMargins)( nLeftSpace, nRightSpace );
+ (this->*fnRect->fnSetYMargins)( nTopSpace, nBottomSpace );
+ }
+ }
+ // --> OD 2004-10-04 #i26945#
+ long nRemaining = GetTabBox()->getRowSpan() >= 1 ?
+ ::lcl_CalcMinCellHeight( this, pTab->IsConsiderObjsForMinCellHeight(), pAttrs ) :
+ 0;
+ // <--
+ if ( !bValidSize )
+ {
+ bValidSize = sal_True;
+
+ //Die VarSize der CellFrms ist immer die Breite.
+ //Tatsaechlich ist die Breite jedoch nicht Variabel, sie wird durch das
+ //Format vorgegeben. Dieser Vorgegebene Wert muss aber nun wiederum
+ //nicht der tatsaechlichen Breite entsprechen. Die Breite wird auf
+ //Basis des Attributes errechnet, der Wert im Attribut passt zu dem
+ //gewuenschten Wert des TabFrms. Anpassungen die dort vorgenommen
+ //wurden werden hier Proportional beruecksichtigt.
+ //Wenn die Celle keinen Nachbarn mehr hat beruecksichtigt sie nicht
+ //die Attribute, sonder greift sich einfach den Rest des
+ //Uppers
+ SwTwips nWidth;
+ if ( GetNext() )
+ {
+ const SwTwips nWish = pTab->GetFmt()->GetFrmSize().GetWidth();
+ nWidth = pAttrs->GetSize().Width();
+
+ OSL_ENSURE( nWish, "Tabelle ohne Breite?" );
+ OSL_ENSURE( nWidth <= nWish, "Zelle breiter als Tabelle." );
+ OSL_ENSURE( nWidth > 0, "Box without width" );
+
+ const long nPrtWidth = (pTab->Prt().*fnRect->fnGetWidth)();
+ if ( nWish != nPrtWidth )
+ {
+ // Avoid rounding problems, at least for the new table model
+ if ( pTab->GetTable()->IsNewModel() )
+ {
+ // 1. sum of widths of cells up to this cell (in model)
+ const SwTableLine* pTabLine = GetTabBox()->GetUpper();
+ const SwTableBoxes& rBoxes = pTabLine->GetTabBoxes();
+ const SwTableBox* pTmpBox = 0;
+
+ SwTwips nSumWidth = 0;
+ sal_uInt16 i = 0;
+ do
+ {
+ pTmpBox = rBoxes[ i++ ];
+ nSumWidth += pTmpBox->GetFrmFmt()->GetFrmSize().GetWidth();
+ }
+ while ( pTmpBox != GetTabBox() );
+
+ // 2. calculate actual width of cells up to this one
+ double nTmpWidth = nSumWidth;
+ nTmpWidth *= nPrtWidth;
+ nTmpWidth /= nWish;
+ nWidth = (SwTwips)nTmpWidth;
+
+ // 3. calculate frame widths of cells up to this one:
+ const SwFrm* pTmpCell = static_cast<const SwLayoutFrm*>(GetUpper())->Lower();
+ SwTwips nSumFrameWidths = 0;
+ while ( pTmpCell != this )
+ {
+ nSumFrameWidths += (pTmpCell->Frm().*fnRect->fnGetWidth)();
+ pTmpCell = pTmpCell->GetNext();
+ }
+
+ nWidth = nWidth - nSumFrameWidths;
+ }
+ else
+ {
+ // #i12092# use double instead of long,
+ // otherwise this could lead to overflows
+ double nTmpWidth = nWidth;
+ nTmpWidth *= nPrtWidth;
+ nTmpWidth /= nWish;
+ nWidth = (SwTwips)nTmpWidth;
+ }
+ }
+ }
+ else
+ {
+ OSL_ENSURE( pAttrs->GetSize().Width() > 0, "Box without width" );
+ nWidth = (GetUpper()->Prt().*fnRect->fnGetWidth)();
+ SwFrm *pPre = GetUpper()->Lower();
+ while ( pPre != this )
+ {
+ nWidth -= (pPre->Frm().*fnRect->fnGetWidth)();
+ pPre = pPre->GetNext();
+ }
+ }
+ const long nDiff = nWidth - (Frm().*fnRect->fnGetWidth)();
+ if( IsNeighbourFrm() && IsRightToLeft() )
+ (Frm().*fnRect->fnSubLeft)( nDiff );
+ else
+ (Frm().*fnRect->fnAddRight)( nDiff );
+ (Prt().*fnRect->fnAddRight)( nDiff );
+
+ //Jetzt die Hoehe einstellen, sie wird vom Inhalt und den Raendern
+ //bestimmt.
+ const long nDiffHeight = nRemaining - (Frm().*fnRect->fnGetHeight)();
+ if ( nDiffHeight )
+ {
+ if ( nDiffHeight > 0 )
+ {
+ //Wieder validieren wenn kein Wachstum stattgefunden hat.
+ //Invalidiert wird durch AdjustCells von der Row.
+ if ( !Grow( nDiffHeight ) )
+ bValidSize = bValidPrtArea = sal_True;
+ }
+ else
+ {
+ //Nur dann invalidiert lassen, wenn tatsaechlich
+ //geshrinkt wurde; das kann abgelehnt werden, weil alle
+ //nebeneinanderliegenden Zellen gleichgross sein muessen.
+ if ( !Shrink( -nDiffHeight ) )
+ bValidSize = bValidPrtArea = sal_True;
+ }
+ }
+ }
+ const SwFmtVertOrient &rOri = pAttrs->GetAttrSet().GetVertOrient();
+
+ if ( !Lower() )
+ return;
+
+ // From now on, all operations are related to the table cell.
+ SWREFRESHFN( this )
+
+ SwPageFrm* pPg = 0;
+ if ( !FindTabFrm()->IsRebuildLastLine() && text::VertOrientation::NONE != rOri.GetVertOrient() &&
+ // --> OD 2008-07-16 #158225# no vertical alignment of covered cells
+ !IsCoveredCell() &&
+ // <--
+ // --> FME 2004-06-29 #116532# Do not consider vertical alignment in grid mode
+ !(pPg = FindPageFrm())->HasGrid() )
+ // <--
+ {
+ if ( !Lower()->IsCntntFrm() && !Lower()->IsSctFrm() && !Lower()->IsTabFrm() )
+ {
+ // OSL_ENSURE(fuer HTML-Import!
+ OSL_ENSURE( !this, "VAlign an Zelle ohne Inhalt" );
+ return;
+ }
+ sal_Bool bVertDir = sal_True;
+ // --> OD 2005-03-30 #i43913# - no vertical alignment, if wrapping
+ // style influence is considered on object positioning and
+ // an object is anchored inside the cell.
+ const bool bConsiderWrapOnObjPos( GetFmt()->getIDocumentSettingAccess()->get(IDocumentSettingAccess::CONSIDER_WRAP_ON_OBJECT_POSITION) );
+ // <--
+ //Keine Ausrichtung wenn Rahmen mit Umlauf in die Zelle ragen.
+ if ( pPg->GetSortedObjs() )
+ {
+ SwRect aRect( Prt() ); aRect += Frm().Pos();
+ for ( sal_uInt16 i = 0; i < pPg->GetSortedObjs()->Count(); ++i )
+ {
+ const SwAnchoredObject* pAnchoredObj = (*pPg->GetSortedObjs())[i];
+ SwRect aTmp( pAnchoredObj->GetObjRect() );
+ if ( aTmp.IsOver( aRect ) )
+ {
+ const SwFrmFmt& rAnchoredObjFrmFmt = pAnchoredObj->GetFrmFmt();
+ const SwFmtSurround &rSur = rAnchoredObjFrmFmt.GetSurround();
+
+ if ( SURROUND_THROUGHT != rSur.GetSurround() )
+ {
+ // frames, which the cell is a lower of, aren't relevant
+ if ( pAnchoredObj->ISA(SwFlyFrm) )
+ {
+ const SwFlyFrm *pFly =
+ static_cast<const SwFlyFrm*>(pAnchoredObj);
+ if ( pFly->IsAnLower( this ) )
+ continue;
+ }
+
+ const SwFrm* pAnch = pAnchoredObj->GetAnchorFrm();
+ // --> OD 2005-03-30 #i43913#
+ // --> OD 2005-08-08 #i52904# - no vertical alignment,
+ // if object, anchored inside cell, has temporarly
+ // consider its wrapping style on object positioning.
+ // --> FME 2006-02-01 #i58806# - no vertical alignment
+ // if object does not follow the text flow.
+ if ( bConsiderWrapOnObjPos ||
+ !IsAnLower( pAnch ) ||
+ pAnchoredObj->IsTmpConsiderWrapInfluence() ||
+ !rAnchoredObjFrmFmt.GetFollowTextFlow().GetValue() )
+ // <--
+ {
+ bVertDir = sal_False;
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ long nPrtHeight = (Prt().*fnRect->fnGetHeight)();
+ if( ( bVertDir && ( nRemaining -= lcl_CalcTopAndBottomMargin( *this, *pAttrs ) ) < nPrtHeight ) ||
+ (Lower()->Frm().*fnRect->fnGetTop)() != (this->*fnRect->fnGetPrtTop)() )
+ {
+ long nDiff = (Prt().*fnRect->fnGetHeight)() - nRemaining;
+ if ( nDiff >= 0 )
+ {
+ long lTopOfst = 0;
+ if ( bVertDir )
+ {
+ switch ( rOri.GetVertOrient() )
+ {
+ case text::VertOrientation::CENTER: lTopOfst = nDiff / 2; break;
+ case text::VertOrientation::BOTTOM: lTopOfst = nDiff; break;
+ default: break;
+ };
+ }
+ long nTmp = (*fnRect->fnYInc)(
+ (this->*fnRect->fnGetPrtTop)(), lTopOfst );
+ if ( lcl_ArrangeLowers( this, nTmp, !bVertDir ) )
+ SetCompletePaint();
+ }
+ }
+ }
+ else
+ {
+ //Ist noch eine alte Ausrichtung beruecksichtigt worden?
+ if ( Lower()->IsCntntFrm() )
+ {
+ const long lYStart = (this->*fnRect->fnGetPrtTop)();
+ lcl_ArrangeLowers( this, lYStart, sal_True );
+ }
+ }
+}
+
+/*************************************************************************
+|*
+|* SwCellFrm::Modify()
+|*
+|*************************************************************************/
+
+void SwCellFrm::Modify( const SfxPoolItem* pOld, const SfxPoolItem * pNew )
+{
+ sal_Bool bAttrSetChg = pNew && RES_ATTRSET_CHG == pNew->Which();
+ const SfxPoolItem *pItem = 0;
+
+ if( bAttrSetChg )
+ ((SwAttrSetChg*)pNew)->GetChgSet()->GetItemState( RES_VERT_ORIENT, sal_False, &pItem);
+ else if ( RES_VERT_ORIENT == pNew->Which() )
+ pItem = pNew;
+
+ if ( pItem )
+ {
+ sal_Bool bInva = sal_True;
+ if ( text::VertOrientation::NONE == ((SwFmtVertOrient*)pItem)->GetVertOrient() &&
+ // OD 04.11.2003 #112910#
+ Lower() && Lower()->IsCntntFrm() )
+ {
+ SWRECTFN( this )
+ const long lYStart = (this->*fnRect->fnGetPrtTop)();
+ bInva = lcl_ArrangeLowers( this, lYStart, sal_False );
+ }
+ if ( bInva )
+ {
+ SetCompletePaint();
+ InvalidatePrt();
+ }
+ }
+
+ if ( ( bAttrSetChg &&
+ SFX_ITEM_SET == ((SwAttrSetChg*)pNew)->GetChgSet()->GetItemState( RES_PROTECT, sal_False ) ) ||
+ RES_PROTECT == pNew->Which() )
+ {
+ ViewShell *pSh = getRootFrm()->GetCurrShell();
+ if( pSh && pSh->GetLayout()->IsAnyShellAccessible() )
+ pSh->Imp()->InvalidateAccessibleEditableState( sal_True, this );
+ }
+
+ if ( bAttrSetChg &&
+ SFX_ITEM_SET == ((SwAttrSetChg*)pNew)->GetChgSet()->GetItemState( RES_FRAMEDIR, sal_False, &pItem ) )
+ {
+ SetDerivedVert( sal_False );
+ CheckDirChange();
+ }
+
+ // --> collapsing borders FME 2005-05-27 #i29550#
+ if ( bAttrSetChg &&
+ SFX_ITEM_SET == ((SwAttrSetChg*)pNew)->GetChgSet()->GetItemState( RES_BOX, sal_False, &pItem ) )
+ {
+ SwFrm* pTmpUpper = GetUpper();
+ while ( pTmpUpper->GetUpper() && !pTmpUpper->GetUpper()->IsTabFrm() )
+ pTmpUpper = pTmpUpper->GetUpper();
+
+ SwTabFrm* pTabFrm = (SwTabFrm*)pTmpUpper->GetUpper();
+ if ( pTabFrm->IsCollapsingBorders() )
+ {
+ // Invalidate lowers of this and next row:
+ lcl_InvalidateAllLowersPrt( (SwRowFrm*)pTmpUpper );
+ pTmpUpper = pTmpUpper->GetNext();
+ if ( pTmpUpper )
+ lcl_InvalidateAllLowersPrt( (SwRowFrm*)pTmpUpper );
+ else
+ pTabFrm->InvalidatePrt();
+ }
+ }
+ // <-- collapsing
+
+ SwLayoutFrm::Modify( pOld, pNew );
+}
+
+/*************************************************************************
+|* SwCellFrm::GetLayoutRowSpan() const
+|*************************************************************************/
+
+long SwCellFrm::GetLayoutRowSpan() const
+{
+ long nRet = GetTabBox()->getRowSpan();
+ if ( nRet < 1 )
+ {
+ const SwFrm* pRow = GetUpper();
+ const SwTabFrm* pTab = static_cast<const SwTabFrm*>(pRow->GetUpper());
+
+ if ( pTab && pTab->IsFollow() && pRow == pTab->GetFirstNonHeadlineRow() )
+ nRet = -nRet;
+ }
+ return nRet;
+}
+
+// --> OD 2010-02-17 #i103961#
+void SwCellFrm::Cut()
+{
+ // notification for accessibility
+ {
+ SwRootFrm *pRootFrm = getRootFrm();
+ if( pRootFrm && pRootFrm->IsAnyShellAccessible() )
+ {
+ ViewShell* pVSh = pRootFrm->GetCurrShell();
+ if ( pVSh && pVSh->Imp() )
+ {
+ pVSh->Imp()->DisposeAccessibleFrm( this );
+ }
+ }
+ }
+
+ SwLayoutFrm::Cut();
+}
+// <--
+
+//
+// Helper functions for repeated headlines:
+//
+
+/*
+ * SwTabFrm::IsInHeadline( const SwFrm& rFrm )
+ */
+bool SwTabFrm::IsInHeadline( const SwFrm& rFrm ) const
+{
+ OSL_ENSURE( IsAnLower( &rFrm ) && rFrm.IsInTab(),
+ "SwTabFrm::IsInHeadline called for frame not lower of table" );
+
+ const SwFrm* pTmp = &rFrm;
+ while ( !pTmp->GetUpper()->IsTabFrm() )
+ pTmp = pTmp->GetUpper();
+
+ return GetTable()->IsHeadline( *((SwRowFrm*)pTmp)->GetTabLine() );
+}
+
+/*
+ * SwTabFrm::GetFirstNonHeadlineRow()
+ *
+ * If this is a master table, we can may assume, that there are at least
+ * nRepeat lines in the table.
+ * If this is a follow table, there are intermediate states for the table
+ * layout, e.g., during deletion of rows, which makes it necessary to find
+ * the first non-headline row by evaluating the headline flag at the row frame.
+ */
+SwRowFrm* SwTabFrm::GetFirstNonHeadlineRow() const
+{
+ SwRowFrm* pRet = (SwRowFrm*)Lower();
+ if ( pRet )
+ {
+ if ( IsFollow() )
+ {
+ while ( pRet && pRet->IsRepeatedHeadline() )
+ pRet = (SwRowFrm*)pRet->GetNext();
+ }
+ else
+ {
+ sal_uInt16 nRepeat = GetTable()->GetRowsToRepeat();
+ while ( pRet && nRepeat > 0 )
+ {
+ pRet = (SwRowFrm*)pRet->GetNext();
+ --nRepeat;
+ }
+ }
+ }
+
+ return (SwRowFrm*)pRet;
+}
+
+/*
+ * SwTable::IsHeadline()
+ */
+bool SwTable::IsHeadline( const SwTableLine& rLine ) const
+{
+ for ( sal_uInt16 i = 0; i < GetRowsToRepeat(); ++i )
+ if ( GetTabLines()[ i ] == &rLine )
+ return true;
+
+ return false;
+}
+
+bool SwTabFrm::IsLayoutSplitAllowed() const
+{
+ return GetFmt()->GetLayoutSplit().GetValue();
+}
+
+// --> collapsing borders FME 2005-05-27 #i29550#
+
+sal_uInt16 SwTabFrm::GetBottomLineSize() const
+{
+ OSL_ENSURE( IsCollapsingBorders(),
+ "BottomLineSize only required for collapsing borders" );
+
+ OSL_ENSURE( Lower(), "Warning! Trying to prevent a crash, please inform FME" );
+
+ const SwFrm* pTmp = GetLastLower();
+
+ // --> FME 2005-12-07 #124755# Try to make code robust:
+ if ( !pTmp ) return 0;
+ // <--
+
+ return static_cast<const SwRowFrm*>(pTmp)->GetBottomLineSize();
+}
+
+bool SwTabFrm::IsCollapsingBorders() const
+{
+ return ((SfxBoolItem&)GetFmt()->GetAttrSet().Get( RES_COLLAPSING_BORDERS )).GetValue();
+}
+
+// <-- collapsing
+
+
+//
+// Local helper function to calculate height of first text row
+//
+SwTwips lcl_CalcHeightOfFirstContentLine( const SwRowFrm& rSourceLine )
+{
+ // Find corresponding split line in master table
+ const SwTabFrm* pTab = rSourceLine.FindTabFrm();
+ SWRECTFN( pTab )
+ const SwCellFrm* pCurrSourceCell = (SwCellFrm*)rSourceLine.Lower();
+
+ //
+ // 1. Case: rSourceLine is a follow flow line.
+ // In this case we have to return the minimum of the heights
+ // of the first lines in rSourceLine.
+ //
+ // 2. Case: rSourceLine is not a follow flow line.
+ // In this case we have to return the maximum of the heights
+ // of the first lines in rSourceLine.
+ //
+ bool bIsInFollowFlowLine = rSourceLine.IsInFollowFlowRow();
+ SwTwips nHeight = bIsInFollowFlowLine ? LONG_MAX : 0;
+
+ while ( pCurrSourceCell )
+ {
+ // NEW TABLES
+ // Skip cells which are not responsible for the height of
+ // the follow flow line:
+ if ( bIsInFollowFlowLine && pCurrSourceCell->GetLayoutRowSpan() > 1 )
+ {
+ pCurrSourceCell = (SwCellFrm*)pCurrSourceCell->GetNext();
+ continue;
+ }
+
+ const SwFrm *pTmp = pCurrSourceCell->Lower();
+ if ( pTmp )
+ {
+ SwTwips nTmpHeight = USHRT_MAX;
+ // --> FME 2004-09-14 #i32456# Consider lower row frames
+ if ( pTmp->IsRowFrm() )
+ {
+ const SwRowFrm* pTmpSourceRow = (SwRowFrm*)pCurrSourceCell->Lower();
+ nTmpHeight = lcl_CalcHeightOfFirstContentLine( *pTmpSourceRow );
+ }
+ // <--
+ if ( pTmp->IsTabFrm() )
+ {
+ nTmpHeight = ((SwTabFrm*)pTmp)->CalcHeightOfFirstContentLine();
+ }
+ else if ( pTmp->IsTxtFrm() )
+ {
+ SwTxtFrm* pTxtFrm = (SwTxtFrm*)pTmp;
+ pTxtFrm->GetFormatted();
+ nTmpHeight = pTxtFrm->FirstLineHeight();
+ }
+
+ if ( USHRT_MAX != nTmpHeight )
+ {
+ const SwCellFrm* pPrevCell = pCurrSourceCell->GetPreviousCell();
+ if ( pPrevCell )
+ {
+ // If we are in a split row, there may be some space
+ // left in the cell frame of the master row.
+ // We look for the minimum of all first line heights;
+ SwTwips nReal = (pPrevCell->Prt().*fnRect->fnGetHeight)();
+ const SwFrm* pFrm = pPrevCell->Lower();
+ const SwFrm* pLast = pFrm;
+ while ( pFrm )
+ {
+ nReal -= (pFrm->Frm().*fnRect->fnGetHeight)();
+ pLast = pFrm;
+ pFrm = pFrm->GetNext();
+ }
+
+ // --> FME, OD 2004-07-15 #i26831#, #i26520#
+ // The additional lower space of the current last.
+ // --> OD 2004-11-25 #115759# - do *not* consider the
+ // additional lower space for 'master' text frames
+ if ( pLast && pLast->IsFlowFrm() &&
+ ( !pLast->IsTxtFrm() ||
+ !static_cast<const SwTxtFrm*>(pLast)->GetFollow() ) )
+ // <--
+ {
+ nReal += SwFlowFrm::CastFlowFrm(pLast)->CalcAddLowerSpaceAsLastInTableCell();
+ }
+ // Don't forget the upper space and lower space,
+ // --> OD 2004-11-25 #115759# - do *not* consider the upper
+ // and the lower space for follow text frames.
+ if ( pTmp->IsFlowFrm() &&
+ ( !pTmp->IsTxtFrm() ||
+ !static_cast<const SwTxtFrm*>(pTmp)->IsFollow() ) )
+ {
+ nTmpHeight += SwFlowFrm::CastFlowFrm(pTmp)->CalcUpperSpace( NULL, pLast);
+ nTmpHeight += SwFlowFrm::CastFlowFrm(pTmp)->CalcLowerSpace();
+ }
+ // <--
+ // --> OD 2004-11-25 #115759# - consider additional lower
+ // space of <pTmp>, if contains only one line.
+ // In this case it would be the new last text frame, which
+ // would have no follow and thus would add this space.
+ if ( pTmp->IsTxtFrm() &&
+ const_cast<SwTxtFrm*>(static_cast<const SwTxtFrm*>(pTmp))
+ ->GetLineCount( STRING_LEN ) == 1 )
+ {
+ nTmpHeight += SwFlowFrm::CastFlowFrm(pTmp)
+ ->CalcAddLowerSpaceAsLastInTableCell();
+ }
+ // <--
+ if ( nReal > 0 )
+ nTmpHeight -= nReal;
+ }
+ else
+ {
+ // pFirstRow is not a FollowFlowRow. In this case,
+ // we look for the maximum of all first line heights:
+ SwBorderAttrAccess aAccess( SwFrm::GetCache(), pCurrSourceCell );
+ const SwBorderAttrs &rAttrs = *aAccess.Get();
+ nTmpHeight += rAttrs.CalcTop() + rAttrs.CalcBottom();
+ // --> OD 2004-07-16 #i26250#
+ // Don't forget the upper space and lower space,
+ if ( pTmp->IsFlowFrm() )
+ {
+ nTmpHeight += SwFlowFrm::CastFlowFrm(pTmp)->CalcUpperSpace();
+ nTmpHeight += SwFlowFrm::CastFlowFrm(pTmp)->CalcLowerSpace();
+ }
+ // <--
+ }
+ }
+
+ if ( bIsInFollowFlowLine )
+ {
+ // minimum
+ if ( nTmpHeight < nHeight )
+ nHeight = nTmpHeight;
+ }
+ else
+ {
+ // maximum
+ if ( nTmpHeight > nHeight && USHRT_MAX != nTmpHeight )
+ nHeight = nTmpHeight;
+ }
+ }
+
+ pCurrSourceCell = (SwCellFrm*)pCurrSourceCell->GetNext();
+ }
+
+ return ( LONG_MAX == nHeight ) ? 0 : nHeight;
+}
+
+//
+// Function to calculate height of first text row
+//
+SwTwips SwTabFrm::CalcHeightOfFirstContentLine() const
+{
+ SWRECTFN( this )
+
+ const bool bDontSplit = !IsFollow() && !GetFmt()->GetLayoutSplit().GetValue();
+
+ if ( bDontSplit )
+ {
+ // Table is not allowed to split: Take the whole height, that's all
+ return (Frm().*fnRect->fnGetHeight)();
+ }
+
+ SwRowFrm* pFirstRow = 0;
+ SwTwips nTmpHeight = 0;
+
+ pFirstRow = GetFirstNonHeadlineRow();
+ OSL_ENSURE( !IsFollow() || pFirstRow, "FollowTable without Lower" );
+
+ // NEW TABLES
+ if ( pFirstRow && pFirstRow->IsRowSpanLine() && pFirstRow->GetNext() )
+ pFirstRow = static_cast<SwRowFrm*>(pFirstRow->GetNext());
+
+ // Calculate the height of the headlines:
+ const sal_uInt16 nRepeat = GetTable()->GetRowsToRepeat();
+ SwTwips nRepeatHeight = nRepeat ? lcl_GetHeightOfRows( GetLower(), nRepeat ) : 0;
+
+ // Calculate the height of the keeping lines
+ // (headlines + following keeping lines):
+ SwTwips nKeepHeight = nRepeatHeight;
+ if ( GetFmt()->GetDoc()->get(IDocumentSettingAccess::TABLE_ROW_KEEP) )
+ {
+ sal_uInt16 nKeepRows = nRepeat;
+
+ // Check how many rows want to keep together
+ while ( pFirstRow && pFirstRow->ShouldRowKeepWithNext() )
+ {
+ ++nKeepRows;
+ pFirstRow = static_cast<SwRowFrm*>(pFirstRow->GetNext());
+ }
+
+ if ( nKeepRows > nRepeat )
+ nKeepHeight = lcl_GetHeightOfRows( GetLower(), nKeepRows );
+ }
+
+ // For master tables, the height of the headlines + the heigth of the
+ // keeping lines (if any) has to be considered. For follow tables, we
+ // only consider the height of the keeping rows without the repeated lines:
+ if ( !IsFollow() )
+ {
+ nTmpHeight = nKeepHeight;
+ }
+ else
+ {
+ nTmpHeight = nKeepHeight - nRepeatHeight;
+ }
+
+ // pFirstRow row is the first non-heading row.
+ // nTmpHeight is the height of the heading row if we are a follow.
+ if ( pFirstRow )
+ {
+ const bool bSplittable = pFirstRow->IsRowSplitAllowed();
+ const SwTwips nFirstLineHeight = (pFirstRow->Frm().*fnRect->fnGetHeight)();
+
+ if ( !bSplittable )
+ {
+ // pFirstRow is not splittable, but it is still possible that the line height of pFirstRow
+ // actually is determined by a lower cell with rowspan = -1. In this case we should not
+ // just return the height of the first line. Basically we need to get the height of the
+ // line as it would be on the last page. Since this is quite complicated to calculate,
+ // we olny calculate the height of the first line.
+ if ( pFirstRow->GetPrev() &&
+ static_cast<SwRowFrm*>(pFirstRow->GetPrev())->IsRowSpanLine() )
+ {
+ // Calculate maximum height of all cells with rowspan = 1:
+ SwTwips nMaxHeight = 0;
+ const SwCellFrm* pLower2 = static_cast<const SwCellFrm*>(pFirstRow->Lower());
+ while ( pLower2 )
+ {
+ if ( 1 == pLower2->GetTabBox()->getRowSpan() )
+ {
+ const SwTwips nCellHeight = lcl_CalcMinCellHeight( pLower2, sal_True );
+ nMaxHeight = Max( nCellHeight, nMaxHeight );
+ }
+ pLower2 = static_cast<const SwCellFrm*>(pLower2->GetNext());
+ }
+ nTmpHeight += nMaxHeight;
+ }
+ else
+ {
+ nTmpHeight += nFirstLineHeight;
+ }
+ }
+
+ // --> FME 2004-11-18 #118411#
+ // Optimization: lcl_CalcHeightOfFirstContentLine actually can trigger
+ // a formatting of the row frame (via the GetFormatted()). We don't
+ // want this formatting if the row does not have a height.
+ else if ( 0 != nFirstLineHeight )
+ // <--
+ {
+ const bool bOldJoinLock = IsJoinLocked();
+ ((SwTabFrm*)this)->LockJoin();
+ const SwTwips nHeightOfFirstContentLine = lcl_CalcHeightOfFirstContentLine( *(SwRowFrm*)pFirstRow );
+
+ // Consider minimum row height:
+ const SwFmtFrmSize &rSz = static_cast<const SwRowFrm*>(pFirstRow)->GetFmt()->GetFrmSize();
+ const SwTwips nMinRowHeight = rSz.GetHeightSizeType() == ATT_MIN_SIZE ?
+ rSz.GetHeight() : 0;
+
+ nTmpHeight += Max( nHeightOfFirstContentLine, nMinRowHeight );
+
+ if ( !bOldJoinLock )
+ ((SwTabFrm*)this)->UnlockJoin();
+ }
+ }
+
+ return nTmpHeight;
+}
+
+//
+// Some more functions for covered/covering cells. This way inclusion of
+// SwCellFrm can be avoided
+//
+
+bool SwFrm::IsLeaveUpperAllowed() const
+{
+ const SwCellFrm* pThisCell = dynamic_cast<const SwCellFrm*>(this);
+ return pThisCell && pThisCell->GetLayoutRowSpan() > 1;
+}
+
+bool SwFrm::IsCoveredCell() const
+{
+ const SwCellFrm* pThisCell = dynamic_cast<const SwCellFrm*>(this);
+ return pThisCell && pThisCell->GetLayoutRowSpan() < 1;
+}
+
+bool SwFrm::IsInCoveredCell() const
+{
+ bool bRet = false;
+
+ const SwFrm* pThis = this;
+ while ( pThis && !pThis->IsCellFrm() )
+ pThis = pThis->GetUpper();
+
+ if ( pThis )
+ bRet = pThis->IsCoveredCell();
+
+ return bRet;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/layout/trvlfrm.cxx b/sw/source/core/layout/trvlfrm.cxx
new file mode 100644
index 000000000000..2673082d5468
--- /dev/null
+++ b/sw/source/core/layout/trvlfrm.cxx
@@ -0,0 +1,2611 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+
+#include <hintids.hxx>
+#include <hints.hxx>
+#include <tools/bigint.hxx>
+#include <editeng/protitem.hxx>
+#include <vcl/settings.hxx>
+#include <vcl/outdev.hxx>
+#include <fmtpdsc.hxx>
+#include <fmtsrnd.hxx>
+#include <pagedesc.hxx>
+#include <pagefrm.hxx>
+#include <rootfrm.hxx>
+#include <cntfrm.hxx>
+#include <ftnfrm.hxx>
+#include <flyfrm.hxx>
+#include <tabfrm.hxx>
+#include <rowfrm.hxx>
+#include <cellfrm.hxx>
+#include <txtfrm.hxx>
+#include <viewsh.hxx>
+#include <viewopt.hxx>
+#include <doc.hxx>
+#include <viscrs.hxx>
+#include <frmfmt.hxx>
+#include <swtable.hxx>
+#include <dflyobj.hxx>
+#include <crstate.hxx>
+#include <frmtool.hxx>
+#include <ndtxt.hxx>
+// OD 2004-05-24 #i28701#
+#include <sortedobjs.hxx>
+
+// FLT_MAX
+#include <cfloat>
+#include <swselectionlist.hxx>
+
+//Fuer SwFlyFrm::GetCrsrOfst
+class SwCrsrOszControl
+{
+public:
+ // damit schon der Compiler die Klasse initialisieren kann, keinen
+ // DTOR und member als publics:
+ const SwFlyFrm *pEntry;
+ const SwFlyFrm *pStk1;
+ const SwFlyFrm *pStk2;
+
+//public:
+// SwCrsrOszControl() : pStk1( 0 ), pStk2( 0 ) {}; // ; <- ????
+
+ sal_Bool ChkOsz( const SwFlyFrm *pFly )
+ {
+ sal_Bool bRet = sal_True;
+ if ( pFly != pStk1 && pFly != pStk2 )
+ {
+ pStk1 = pStk2;
+ pStk2 = pFly;
+ bRet = sal_False;
+ }
+ return bRet;
+ }
+ void Entry( const SwFlyFrm *pFly )
+ {
+ if ( !pEntry )
+ pEntry = pStk1 = pFly;
+ }
+ void Exit( const SwFlyFrm *pFly )
+ {
+ if ( pFly == pEntry )
+ pEntry = pStk1 = pStk2 = 0;
+ }
+};
+
+static SwCrsrOszControl aOszCtrl = { 0, 0, 0 };
+
+/*************************************************************************
+|*
+|* SwLayoutFrm::GetCrsrOfst()
+|*
+|* Beschreibung: Sucht denjenigen CntntFrm, innerhalb dessen
+|* PrtArea der Point liegt.
+|*
+|*************************************************************************/
+sal_Bool SwLayoutFrm::GetCrsrOfst( SwPosition *pPos, Point &rPoint,
+ SwCrsrMoveState* pCMS ) const
+{
+ sal_Bool bRet = sal_False;
+ const SwFrm *pFrm = Lower();
+ while ( !bRet && pFrm )
+ {
+ pFrm->Calc();
+
+ // --> FME 2005-05-13 #i43742# New function: SW_CONTENT_CHECK
+ const bool bCntntCheck = pFrm->IsTxtFrm() && pCMS && pCMS->bCntntCheck;
+ const SwRect aPaintRect( bCntntCheck ?
+ pFrm->UnionFrm() :
+ pFrm->PaintArea() );
+ // <--
+
+ if ( aPaintRect.IsInside( rPoint ) &&
+ ( bCntntCheck || pFrm->GetCrsrOfst( pPos, rPoint, pCMS ) ) )
+ bRet = sal_True;
+ else
+ pFrm = pFrm->GetNext();
+ if ( pCMS && pCMS->bStop )
+ return sal_False;
+ }
+ return bRet;
+}
+
+/*************************************************************************
+|*
+|* SwPageFrm::GetCrsrOfst()
+|*
+|* Beschreibung: Sucht die Seite, innerhalb der der gesuchte Point
+|* liegt.
+|*
+|*************************************************************************/
+
+sal_Bool SwPageFrm::GetCrsrOfst( SwPosition *pPos, Point &rPoint,
+ SwCrsrMoveState* pCMS ) const
+{
+ sal_Bool bRet = sal_False;
+ Point aPoint( rPoint );
+
+ // check, if we have to adjust the point
+ if ( !Frm().IsInside( aPoint ) )
+ {
+ aPoint.X() = Max( aPoint.X(), Frm().Left() );
+ aPoint.X() = Min( aPoint.X(), Frm().Right() );
+ aPoint.Y() = Max( aPoint.Y(), Frm().Top() );
+ aPoint.Y() = Min( aPoint.Y(), Frm().Bottom() );
+ }
+
+ //Wenn kein Cntnt unterhalb der Seite 'antwortet', so korrigieren
+ //wir den StartPoint und fangen nochmal eine Seite vor der
+ //aktuellen an. Mit Flys ist es dann allerdings vorbei.
+ if ( SwLayoutFrm::GetCrsrOfst( pPos, aPoint, pCMS ) )
+ bRet = sal_True;
+ else
+ {
+ if ( pCMS && (pCMS->bStop || pCMS->bExactOnly) )
+ {
+ ((SwCrsrMoveState*)pCMS)->bStop = sal_True;
+ return sal_False;
+ }
+ const SwCntntFrm *pCnt = GetCntntPos( aPoint, sal_False, sal_False, sal_False, pCMS, sal_False );
+ if ( pCMS && pCMS->bStop )
+ return sal_False;
+
+ OSL_ENSURE( pCnt, "Crsr is gone to a Black hole" );
+ if( pCMS && pCMS->pFill && pCnt->IsTxtFrm() )
+ bRet = pCnt->GetCrsrOfst( pPos, rPoint, pCMS );
+ else
+ bRet = pCnt->GetCrsrOfst( pPos, aPoint, pCMS );
+
+ if ( !bRet )
+ {
+ // Set point to pCnt, delete mark
+ // this may happen, if pCnt is hidden
+ *pPos = SwPosition( *pCnt->GetNode(), SwIndex( (SwTxtNode*)pCnt->GetNode(), 0 ) );
+ bRet = sal_True;
+ }
+ }
+
+ if ( !bRet )
+ {
+ //Koennte ein Freifliegender gemeint sein?
+ //Wenn sein Inhalt geschuetzt werden soll, so ist nix mit Crsr
+ //hineinsetzen, dadurch sollten alle Aenderungen unmoeglich sein.
+ if ( GetSortedObjs() )
+ {
+ SwOrderIter aIter( this );
+ aIter.Top();
+ while ( aIter() )
+ {
+ const SwVirtFlyDrawObj* pObj =
+ static_cast<const SwVirtFlyDrawObj*>(aIter());
+ const SwFlyFrm* pFly = pObj ? pObj->GetFlyFrm() : 0;
+ if ( pFly &&
+ ( ( pCMS ? pCMS->bSetInReadOnly : sal_False ) ||
+ !pFly->IsProtected() ) &&
+ pFly->GetCrsrOfst( pPos, aPoint, pCMS ) )
+ {
+ bRet = sal_True;
+ break;
+ }
+
+ if ( pCMS && pCMS->bStop )
+ return sal_False;
+ aIter.Prev();
+ }
+ }
+ }
+
+ if ( bRet )
+ rPoint = aPoint;
+
+ return bRet;
+}
+
+bool SwLayoutFrm::FillSelection( SwSelectionList& rList, const SwRect& rRect ) const
+{
+ bool bRet = false;
+ if( rRect.IsOver(PaintArea()) )
+ {
+ const SwFrm* pFrm = Lower();
+ while( pFrm )
+ {
+ pFrm->FillSelection( rList, rRect );
+ pFrm = pFrm->GetNext();
+ }
+ }
+ return bRet;
+}
+
+bool SwPageFrm::FillSelection( SwSelectionList& rList, const SwRect& rRect ) const
+{
+ bool bRet = false;
+ if( rRect.IsOver(PaintArea()) )
+ {
+ bRet = SwLayoutFrm::FillSelection( rList, rRect );
+ if( GetSortedObjs() )
+ {
+ const SwSortedObjs &rObjs = *GetSortedObjs();
+ for ( sal_uInt16 i = 0; i < rObjs.Count(); ++i )
+ {
+ const SwAnchoredObject* pAnchoredObj = rObjs[i];
+ if( !pAnchoredObj->ISA(SwFlyFrm) )
+ continue;
+ const SwFlyFrm* pFly = static_cast<const SwFlyFrm*>(pAnchoredObj);
+ if( pFly->FillSelection( rList, rRect ) )
+ bRet = true;
+ }
+ }
+ }
+ return bRet;
+}
+
+bool SwRootFrm::FillSelection( SwSelectionList& aSelList, const SwRect& rRect) const
+{
+ const SwFrm *pPage = Lower();
+ const long nBottom = rRect.Bottom();
+ while( pPage )
+ {
+ if( pPage->Frm().Top() < nBottom )
+ {
+ if( pPage->Frm().Bottom() > rRect.Top() )
+ pPage->FillSelection( aSelList, rRect );
+ pPage = pPage->GetNext();
+ }
+ else
+ pPage = 0;
+ }
+ return !aSelList.isEmpty();
+}
+
+/*************************************************************************
+|*
+|* SwRootFrm::GetCrsrOfst()
+|*
+|* Beschreibung: Reicht Primaer den Aufruf an die erste Seite weiter.
+|* Wenn der 'reingereichte Point veraendert wird,
+|* so wird sal_False zurueckgegeben.
+|*
+|*************************************************************************/
+sal_Bool SwRootFrm::GetCrsrOfst( SwPosition *pPos, Point &rPoint,
+ SwCrsrMoveState* pCMS ) const
+{
+ sal_Bool bOldAction = IsCallbackActionEnabled();
+ ((SwRootFrm*)this)->SetCallbackActionEnabled( sal_False );
+ OSL_ENSURE( (Lower() && Lower()->IsPageFrm()), "Keinen PageFrm gefunden." );
+ if( pCMS && pCMS->pFill )
+ ((SwCrsrMoveState*)pCMS)->bFillRet = sal_False;
+ Point aOldPoint = rPoint;
+
+ // PAGES01
+ // search for page containing rPoint. The borders around the pages are considerd
+ const SwPageFrm* pPage = GetPageAtPos( rPoint, 0, true );
+
+ // --> OD 2008-12-23 #i95626#
+ // special handling for <rPoint> beyond root frames area
+ if ( !pPage &&
+ rPoint.X() > Frm().Right() &&
+ rPoint.Y() > Frm().Bottom() )
+ {
+ pPage = dynamic_cast<const SwPageFrm*>(Lower());
+ while ( pPage && pPage->GetNext() )
+ {
+ pPage = dynamic_cast<const SwPageFrm*>(pPage->GetNext());
+ }
+ }
+ // <--
+ if ( pPage )
+ {
+ pPage->SwPageFrm::GetCrsrOfst( pPos, rPoint, pCMS );
+ }
+
+ ((SwRootFrm*)this)->SetCallbackActionEnabled( bOldAction );
+ if( pCMS )
+ {
+ if( pCMS->bStop )
+ return sal_False;
+ if( pCMS->pFill )
+ return pCMS->bFillRet;
+ }
+ return aOldPoint == rPoint;
+}
+
+/*************************************************************************
+|*
+|* SwCellFrm::GetCrsrOfst()
+|*
+|* Beschreibung Wenn es sich um eine Cntnt-tragende Cell handelt wird
+|* der Crsr notfalls mit Gewalt in einen der CntntFrms
+|* gesetzt.
+|* In geschuetzte Zellen gibt es hier keinen Eingang.
+|*
+|*************************************************************************/
+sal_Bool SwCellFrm::GetCrsrOfst( SwPosition *pPos, Point &rPoint,
+ SwCrsrMoveState* pCMS ) const
+{
+ // cell frame does not necessarily have a lower (split table cell)
+ if ( !Lower() )
+ return sal_False;
+
+ if ( !(pCMS?pCMS->bSetInReadOnly:sal_False) &&
+ GetFmt()->GetProtect().IsCntntProtected() )
+ return sal_False;
+
+ if ( pCMS && pCMS->eState == MV_TBLSEL )
+ {
+ const SwTabFrm *pTab = FindTabFrm();
+ if ( pTab->IsFollow() && pTab->IsInHeadline( *this ) )
+ {
+ ((SwCrsrMoveState*)pCMS)->bStop = sal_True;
+ return sal_False;
+ }
+ }
+
+ if ( Lower() )
+ {
+ if ( Lower()->IsLayoutFrm() )
+ return SwLayoutFrm::GetCrsrOfst( pPos, rPoint, pCMS );
+ else
+ {
+ Calc();
+ sal_Bool bRet = sal_False;
+
+ const SwFrm *pFrm = Lower();
+ while ( pFrm && !bRet )
+ {
+ pFrm->Calc();
+ if ( pFrm->Frm().IsInside( rPoint ) )
+ {
+ bRet = pFrm->GetCrsrOfst( pPos, rPoint, pCMS );
+ if ( pCMS && pCMS->bStop )
+ return sal_False;
+ }
+ pFrm = pFrm->GetNext();
+ }
+ if ( !bRet )
+ {
+ Point *pPoint = pCMS && pCMS->pFill ? new Point( rPoint ) : NULL;
+ const SwCntntFrm *pCnt = GetCntntPos( rPoint, sal_True );
+ if( pPoint && pCnt->IsTxtFrm() )
+ {
+ pCnt->GetCrsrOfst( pPos, *pPoint, pCMS );
+ rPoint = *pPoint;
+ }
+ else
+ pCnt->GetCrsrOfst( pPos, rPoint, pCMS );
+ delete pPoint;
+ }
+ return sal_True;
+ }
+ }
+
+ return sal_False;
+}
+
+/*************************************************************************
+|*
+|* SwFlyFrm::GetCrsrOfst()
+|*
+|*************************************************************************/
+//Problem: Wenn zwei Flys genau gleich gross sind und auf derselben
+//Position stehen, so liegt jeder innerhalb des anderen.
+//Da jeweils geprueft wird, ob der Point nicht zufaellig innerhalb eines
+//anderen Flys liegt, der sich vollstaendig innerhalb des aktuellen befindet
+//und ggf. ein rekursiver Aufruf erfolgt wuerde o.g. Situation zu einer
+//endlosen Rekursion fuehren.
+//Mit der Hilfsklasse SwCrsrOszControl unterbinden wir die Rekursion. Das
+//GetCrsrOfst entscheidet sich bei einer Rekursion fuer denjenigen der
+//am weitesten oben liegt.
+
+sal_Bool SwFlyFrm::GetCrsrOfst( SwPosition *pPos, Point &rPoint,
+ SwCrsrMoveState* pCMS ) const
+{
+ aOszCtrl.Entry( this );
+
+ //Wenn der Point innerhalb des Fly sitzt wollen wir energisch
+ //versuchen den Crsr hineinzusetzen.
+ //Wenn der Point allerdings in einem Flys sitzt, der sich vollstaendig
+ //innerhalb des aktuellen befindet, so wird fuer diesen das
+ //GetCrsrOfst gerufen.
+ Calc();
+ sal_Bool bInside = Frm().IsInside( rPoint ) && Lower(),
+ bRet = sal_False;
+
+ //Wenn der Frm eine Grafik enthaelt, aber nur Text gewuenscht ist, so
+ //nimmt er den Crsr grundsaetzlich nicht an.
+ if ( bInside && pCMS && pCMS->eState == MV_SETONLYTEXT &&
+ (!Lower() || Lower()->IsNoTxtFrm()) )
+ bInside = sal_False;
+
+ const SwPageFrm *pPage = FindPageFrm();
+ if ( bInside && pPage && pPage->GetSortedObjs() )
+ {
+ SwOrderIter aIter( pPage );
+ aIter.Top();
+ while ( aIter() && !bRet )
+ {
+ const SwVirtFlyDrawObj* pObj = static_cast<const SwVirtFlyDrawObj*>(aIter());
+ const SwFlyFrm* pFly = pObj ? pObj->GetFlyFrm() : 0;
+ if ( pFly && pFly->Frm().IsInside( rPoint ) &&
+ Frm().IsInside( pFly->Frm() ) )
+ {
+ if ( aOszCtrl.ChkOsz( pFly ) ||
+ sal_True == (bRet = pFly->GetCrsrOfst( pPos, rPoint, pCMS )))
+ break;
+ if ( pCMS && pCMS->bStop )
+ return sal_False;
+ }
+ aIter.Next();
+ }
+ }
+
+ while ( bInside && !bRet )
+ {
+ const SwFrm *pFrm = Lower();
+ while ( pFrm && !bRet )
+ {
+ pFrm->Calc();
+ if ( pFrm->Frm().IsInside( rPoint ) )
+ {
+ bRet = pFrm->GetCrsrOfst( pPos, rPoint, pCMS );
+ if ( pCMS && pCMS->bStop )
+ return sal_False;
+ }
+ pFrm = pFrm->GetNext();
+ }
+ if ( !bRet )
+ {
+ Point *pPoint = pCMS && pCMS->pFill ? new Point( rPoint ) : NULL;
+ const SwCntntFrm *pCnt = GetCntntPos(
+ rPoint, sal_True, sal_False, sal_False, pCMS );
+ if ( pCMS && pCMS->bStop )
+ return sal_False;
+ if( pPoint && pCnt->IsTxtFrm() )
+ {
+ pCnt->GetCrsrOfst( pPos, *pPoint, pCMS );
+ rPoint = *pPoint;
+ }
+ else
+ pCnt->GetCrsrOfst( pPos, rPoint, pCMS );
+ delete pPoint;
+ bRet = sal_True;
+ }
+ }
+ aOszCtrl.Exit( this );
+ return bRet;
+}
+
+/*************************************************************************
+|*
+|* Beschreibung Layoutabhaengiges Cursortravelling
+|*
+|*************************************************************************/
+sal_Bool SwCntntFrm::LeftMargin(SwPaM *pPam) const
+{
+ if( pPam->GetNode() != (SwCntntNode*)GetNode() )
+ return sal_False;
+ ((SwCntntNode*)GetNode())->
+ MakeStartIndex((SwIndex *) &pPam->GetPoint()->nContent);
+ return sal_True;
+}
+
+sal_Bool SwCntntFrm::RightMargin(SwPaM *pPam, sal_Bool) const
+{
+ if( pPam->GetNode() != (SwCntntNode*)GetNode() )
+ return sal_False;
+ ((SwCntntNode*)GetNode())->
+ MakeEndIndex((SwIndex *) &pPam->GetPoint()->nContent);
+ return sal_True;
+}
+
+const SwCntntFrm *lcl_GetNxtCnt( const SwCntntFrm* pCnt )
+{
+ return pCnt->GetNextCntntFrm();
+}
+
+const SwCntntFrm *lcl_GetPrvCnt( const SwCntntFrm* pCnt )
+{
+ return pCnt->GetPrevCntntFrm();
+}
+
+typedef const SwCntntFrm *(*GetNxtPrvCnt)( const SwCntntFrm* );
+
+//Frame in wiederholter Headline?
+sal_Bool lcl_IsInRepeatedHeadline( const SwFrm *pFrm,
+ const SwTabFrm** ppTFrm = 0 )
+{
+ const SwTabFrm *pTab = pFrm->FindTabFrm();
+ if( ppTFrm )
+ *ppTFrm = pTab;
+ return pTab && pTab->IsFollow() && pTab->IsInHeadline( *pFrm );
+}
+
+
+//Ueberspringen geschuetzter Tabellenzellen. Optional auch
+//Ueberspringen von wiederholten Headlines.
+//MA 26. Jan. 98: Chg auch andere Geschuetzte Bereiche ueberspringen.
+// FME: Skip follow flow cells
+const SwCntntFrm * MA_FASTCALL lcl_MissProtectedFrames( const SwCntntFrm *pCnt,
+ GetNxtPrvCnt fnNxtPrv,
+ sal_Bool bMissHeadline,
+ sal_Bool bInReadOnly,
+ sal_Bool bMissFollowFlowLine )
+{
+ if ( pCnt && pCnt->IsInTab() )
+ {
+ sal_Bool bProtect = sal_True;
+ while ( pCnt && bProtect )
+ {
+ const SwLayoutFrm *pCell = pCnt->GetUpper();
+ while ( pCell && !pCell->IsCellFrm() )
+ pCell = pCell->GetUpper();
+ if ( !pCell ||
+ (( ( bInReadOnly || !pCell->GetFmt()->GetProtect().IsCntntProtected() ) &&
+ ( !bMissHeadline || !lcl_IsInRepeatedHeadline( pCell ) ) &&
+ ( !bMissFollowFlowLine || !pCell->IsInFollowFlowRow() ) &&
+ !pCell->IsCoveredCell()) ) )
+ bProtect = sal_False;
+ else
+ pCnt = (*fnNxtPrv)( pCnt );
+ }
+ }
+ else if ( !bInReadOnly )
+ while ( pCnt && pCnt->IsProtected() )
+ pCnt = (*fnNxtPrv)( pCnt );
+
+ return pCnt;
+}
+
+sal_Bool MA_FASTCALL lcl_UpDown( SwPaM *pPam, const SwCntntFrm *pStart,
+ GetNxtPrvCnt fnNxtPrv, sal_Bool bInReadOnly )
+{
+ OSL_ENSURE( pPam->GetNode() == (SwCntntNode*)pStart->GetNode(),
+ "lcl_UpDown arbeitet nicht fuer andere." );
+
+ const SwCntntFrm *pCnt = 0;
+
+ //Wenn gerade eine Tabellenselection laeuft muss ein bischen getricktst
+ //werden: Beim hochlaufen an den Anfang der Zelle gehen, beim runterlaufen
+ //an das Ende der Zelle gehen.
+ sal_Bool bTblSel = false;
+ if ( pStart->IsInTab() &&
+ pPam->GetNode( sal_True )->StartOfSectionNode() !=
+ pPam->GetNode( sal_False )->StartOfSectionNode() )
+ {
+ bTblSel = true;
+ const SwLayoutFrm *pCell = pStart->GetUpper();
+ while ( !pCell->IsCellFrm() )
+ pCell = pCell->GetUpper();
+
+ //
+ // Check, if cell has a Prev/Follow cell:
+ //
+ const bool bFwd = ( fnNxtPrv == lcl_GetNxtCnt );
+ const SwLayoutFrm* pTmpCell = bFwd ?
+ ((SwCellFrm*)pCell)->GetFollowCell() :
+ ((SwCellFrm*)pCell)->GetPreviousCell();
+
+ const SwCntntFrm* pTmpStart = pStart;
+ while ( pTmpCell && 0 != ( pTmpStart = pTmpCell->ContainsCntnt() ) )
+ {
+ pCell = pTmpCell;
+ pTmpCell = bFwd ?
+ ((SwCellFrm*)pCell)->GetFollowCell() :
+ ((SwCellFrm*)pCell)->GetPreviousCell();
+ }
+ const SwCntntFrm *pNxt = pCnt = pTmpStart;
+
+ while ( pCell->IsAnLower( pNxt ) )
+ {
+ pCnt = pNxt;
+ pNxt = (*fnNxtPrv)( pNxt );
+ }
+ }
+
+ pCnt = (*fnNxtPrv)( pCnt ? pCnt : pStart );
+ pCnt = ::lcl_MissProtectedFrames( pCnt, fnNxtPrv, sal_True, bInReadOnly, bTblSel );
+
+
+ const SwTabFrm *pStTab = pStart->FindTabFrm();
+ const SwTabFrm *pTable = 0;
+ const sal_Bool bTab = pStTab || (pCnt && pCnt->IsInTab()) ? sal_True : sal_False;
+ sal_Bool bEnd = bTab ? sal_False : sal_True;
+
+ const SwFrm* pVertRefFrm = pStart;
+ if ( bTblSel && pStTab )
+ pVertRefFrm = pStTab;
+ SWRECTFN( pVertRefFrm )
+
+ SwTwips nX = 0;
+ if ( bTab )
+ {
+ //
+ // pStart or pCnt is inside a table. nX will be used for travelling:
+ //
+ SwRect aRect( pStart->Frm() );
+ pStart->GetCharRect( aRect, *pPam->GetPoint() );
+ Point aCenter = aRect.Center();
+ nX = bVert ? aCenter.Y() : aCenter.X();
+
+ pTable = pCnt ? pCnt->FindTabFrm() : 0;
+ if ( !pTable )
+ pTable = pStTab;
+
+ if ( pStTab &&
+ !pStTab->GetUpper()->IsInTab() &&
+ !pTable->GetUpper()->IsInTab() )
+ {
+ const SwFrm *pCell = pStart->GetUpper();
+ while ( pCell && !pCell->IsCellFrm() )
+ pCell = pCell->GetUpper();
+ OSL_ENSURE( pCell, "Zelle nicht gefunden." );
+ nX = (pCell->Frm().*fnRect->fnGetLeft)() +
+ (pCell->Frm().*fnRect->fnGetWidth)() / 2;
+
+ //Der Fluss fuehrt von einer Tabelle in die nachste. Der X-Wert
+ //muss ausgehend von der Mitte der Startzelle um die Verschiebung
+ //der Tabellen korrigiert werden.
+ if ( pStTab != pTable )
+ {
+ nX += (pTable->Frm().*fnRect->fnGetLeft)() -
+ (pStTab->Frm().*fnRect->fnGetLeft)();
+ }
+ }
+
+ //
+ // Restrict nX to the left and right borders of pTab:
+ // (is this really necessary?)
+ //
+ if ( !pTable->GetUpper()->IsInTab() )
+ {
+ const sal_Bool bRTL = pTable->IsRightToLeft();
+ const long nPrtLeft = bRTL ?
+ (pTable->*fnRect->fnGetPrtRight)() :
+ (pTable->*fnRect->fnGetPrtLeft)();
+ if ( bRTL != (nX < nPrtLeft) )
+ nX = nPrtLeft;
+ else
+ {
+ const long nPrtRight = bRTL ?
+ (pTable->*fnRect->fnGetPrtLeft)() :
+ (pTable->*fnRect->fnGetPrtRight)();
+ if ( bRTL != (nX > nPrtRight) )
+ nX = nPrtRight;
+ }
+ }
+ }
+
+ do
+ {
+ //Wenn ich im DokumentBody bin, so will ich da auch bleiben
+ if ( pStart->IsInDocBody() )
+ {
+ while ( pCnt && (!pCnt->IsInDocBody() ||
+ (pCnt->IsTxtFrm() && ((SwTxtFrm*)pCnt)->IsHiddenNow())))
+ {
+ pCnt = (*fnNxtPrv)( pCnt );
+ pCnt = ::lcl_MissProtectedFrames( pCnt, fnNxtPrv, sal_True, bInReadOnly, bTblSel );
+ }
+ }
+
+ //Wenn ich im Fussnotenbereich bin, so versuche ich notfalls den naechsten
+ //Fussnotenbereich zu erreichen.
+ else if ( pStart->IsInFtn() )
+ {
+ while ( pCnt && (!pCnt->IsInFtn() ||
+ (pCnt->IsTxtFrm() && ((SwTxtFrm*)pCnt)->IsHiddenNow())))
+ {
+ pCnt = (*fnNxtPrv)( pCnt );
+ pCnt = ::lcl_MissProtectedFrames( pCnt, fnNxtPrv, sal_True, bInReadOnly, bTblSel );
+ }
+ }
+
+ //In Flys kann es Blind weitergehen solange ein Cntnt
+ //gefunden wird.
+ else if ( pStart->IsInFly() )
+ {
+ if ( pCnt && pCnt->IsTxtFrm() && ((SwTxtFrm*)pCnt)->IsHiddenNow() )
+ {
+ pCnt = (*fnNxtPrv)( pCnt );
+ pCnt = ::lcl_MissProtectedFrames( pCnt, fnNxtPrv, sal_True, bInReadOnly, bTblSel );
+ }
+ }
+
+ //Andernfalls weigere ich mich einfach den derzeitigen Bereich zu
+ //verlassen.
+ else if ( pCnt )
+ {
+ const SwFrm *pUp = pStart->GetUpper(); //Head/Foot
+ while ( pUp && pUp->GetUpper() && !(pUp->GetType() & 0x0018 ) )
+ pUp = pUp->GetUpper();
+ sal_Bool bSame = sal_False;
+ const SwFrm *pCntUp = pCnt->GetUpper();
+ while ( pCntUp && !bSame )
+ { if ( pUp == pCntUp )
+ bSame = sal_True;
+ else
+ pCntUp = pCntUp->GetUpper();
+ }
+ if ( !bSame )
+ pCnt = 0;
+ else if ( pCnt && pCnt->IsTxtFrm() && ((SwTxtFrm*)pCnt)->IsHiddenNow() ) // i73332
+ {
+ pCnt = (*fnNxtPrv)( pCnt );
+ pCnt = ::lcl_MissProtectedFrames( pCnt, fnNxtPrv, sal_True, bInReadOnly, bTblSel );
+ }
+ }
+
+ if ( bTab )
+ {
+ if ( !pCnt )
+ bEnd = sal_True;
+ else
+ { const SwTabFrm *pTab = pCnt->FindTabFrm();
+ if( !pTab )
+ bEnd = sal_True;
+ else
+ {
+ if ( pTab != pTable )
+ {
+ //Der Fluss fuehrt von einer Tabelle in die nachste. Der
+ //X-Wert muss um die Verschiebung der Tabellen korrigiert
+ //werden.
+ if ( pTable &&
+ !pTab->GetUpper()->IsInTab() &&
+ !pTable->GetUpper()->IsInTab() )
+ nX += pTab->Frm().Left() - pTable->Frm().Left();
+ pTable = pTab;
+ }
+ const SwLayoutFrm *pCell = pTable ? pCnt->GetUpper() : 0;
+ while ( pCell && !pCell->IsCellFrm() )
+ pCell = pCell->GetUpper();
+
+ Point aInsideCell;
+ Point aInsideCnt;
+ if ( pCell )
+ {
+ long nTmpTop = (pCell->Frm().*fnRect->fnGetTop)();
+ if ( bVert )
+ {
+ if ( nTmpTop )
+ --nTmpTop;
+
+ aInsideCell = Point( nTmpTop, nX );
+ }
+ else
+ aInsideCell = Point( nX, nTmpTop );
+ }
+
+ long nTmpTop = (pCnt->Frm().*fnRect->fnGetTop)();
+ if ( bVert )
+ {
+ if ( nTmpTop )
+ --nTmpTop;
+
+ aInsideCnt = Point( nTmpTop, nX );
+ }
+ else
+ aInsideCnt = Point( nX, nTmpTop );
+
+ if ( pCell && pCell->Frm().IsInside( aInsideCell ) )
+ {
+ bEnd = sal_True;
+ //Jetzt noch schnell den richtigen Cntnt in der Zelle
+ //greifen.
+ if ( !pCnt->Frm().IsInside( aInsideCnt ) )
+ {
+ pCnt = pCell->ContainsCntnt();
+ if ( fnNxtPrv == lcl_GetPrvCnt )
+ while ( pCell->IsAnLower(pCnt->GetNextCntntFrm()) )
+ pCnt = pCnt->GetNextCntntFrm();
+ }
+ }
+ else if ( pCnt->Frm().IsInside( aInsideCnt ) )
+ bEnd = sal_True;
+ }
+ }
+ if ( !bEnd )
+ {
+ pCnt = (*fnNxtPrv)( pCnt );
+ pCnt = ::lcl_MissProtectedFrames( pCnt, fnNxtPrv, sal_True, bInReadOnly, bTblSel );
+ }
+ }
+
+ } while ( !bEnd ||
+ (pCnt && pCnt->IsTxtFrm() && ((SwTxtFrm*)pCnt)->IsHiddenNow()));
+
+ if( pCnt )
+ { // setze den Point auf den Content-Node
+ SwCntntNode *pCNd = (SwCntntNode*)pCnt->GetNode();
+ pPam->GetPoint()->nNode = *pCNd;
+ if ( fnNxtPrv == lcl_GetPrvCnt )
+ pCNd->MakeEndIndex( (SwIndex*)&pPam->GetPoint()->nContent );
+ else
+ pCNd->MakeStartIndex( (SwIndex*)&pPam->GetPoint()->nContent );
+ return sal_True;
+ }
+ return sal_False;
+}
+
+sal_Bool SwCntntFrm::UnitUp( SwPaM* pPam, const SwTwips, sal_Bool bInReadOnly ) const
+{
+ return ::lcl_UpDown( pPam, this, lcl_GetPrvCnt, bInReadOnly );
+}
+
+sal_Bool SwCntntFrm::UnitDown( SwPaM* pPam, const SwTwips, sal_Bool bInReadOnly ) const
+{
+ return ::lcl_UpDown( pPam, this, lcl_GetNxtCnt, bInReadOnly );
+}
+
+/*************************************************************************
+|*
+|* SwRootFrm::GetCurrPage()
+|*
+|* Beschreibung: Liefert die Nummer der aktuellen Seite.
+|* Wenn die Methode einen PaM bekommt, so ist die aktuelle Seite
+|* diejenige in der der PaM sitzt. Anderfalls ist die aktuelle
+|* Seite die erste Seite innerhalb der VisibleArea.
+|* Es wird nur auf den vorhandenen Seiten gearbeitet!
+|*
+|*************************************************************************/
+sal_uInt16 SwRootFrm::GetCurrPage( const SwPaM *pActualCrsr ) const
+{
+ OSL_ENSURE( pActualCrsr, "Welche Seite soll's denn sein?" );
+ SwFrm const*const pActFrm = pActualCrsr->GetPoint()->nNode.GetNode().
+ GetCntntNode()->getLayoutFrm( this, 0,
+ pActualCrsr->GetPoint(),
+ sal_False );
+ return pActFrm->FindPageFrm()->GetPhyPageNum();
+}
+
+/*************************************************************************
+|*
+|* SwRootFrm::SetCurrPage()
+|*
+|* Beschreibung: Liefert einen PaM der am Anfang der gewuenschten
+|* Seite sitzt.
+|* Formatiert wird soweit notwendig
+|* Liefert Null, wenn die Operation nicht moeglich ist.
+|* Der PaM sitzt in der letzten Seite, wenn die Seitenzahl zu gross
+|* gewaehlt wurde.
+|*
+|*************************************************************************/
+sal_uInt16 SwRootFrm::SetCurrPage( SwCursor* pToSet, sal_uInt16 nPageNum )
+{
+ OSL_ENSURE( Lower() && Lower()->IsPageFrm(), "Keine Seite vorhanden." );
+
+ SwPageFrm *pPage = (SwPageFrm*)Lower();
+ sal_Bool bEnd =sal_False;
+ while ( !bEnd && pPage->GetPhyPageNum() != nPageNum )
+ { if ( pPage->GetNext() )
+ pPage = (SwPageFrm*)pPage->GetNext();
+ else
+ { //Ersten CntntFrm Suchen, und solange Formatieren bis
+ //eine neue Seite angefangen wird oder bis die CntntFrm's alle
+ //sind.
+ const SwCntntFrm *pCntnt = pPage->ContainsCntnt();
+ while ( pCntnt && pPage->IsAnLower( pCntnt ) )
+ {
+ pCntnt->Calc();
+ pCntnt = pCntnt->GetNextCntntFrm();
+ }
+ //Jetzt ist entweder eine neue Seite da, oder die letzte Seite
+ //ist gefunden.
+ if ( pPage->GetNext() )
+ pPage = (SwPageFrm*)pPage->GetNext();
+ else
+ bEnd = sal_True;
+ }
+ }
+ //pPage zeigt jetzt auf die 'gewuenschte' Seite. Jetzt muss noch der
+ //PaM auf den Anfang des ersten CntntFrm im Body-Text erzeugt werden.
+ //Wenn es sich um eine Fussnotenseite handelt, wird der PaM in die erste
+ //Fussnote gesetzt.
+ const SwCntntFrm *pCntnt = pPage->ContainsCntnt();
+ if ( pPage->IsFtnPage() )
+ while ( pCntnt && !pCntnt->IsInFtn() )
+ pCntnt = pCntnt->GetNextCntntFrm();
+ else
+ while ( pCntnt && !pCntnt->IsInDocBody() )
+ pCntnt = pCntnt->GetNextCntntFrm();
+ if ( pCntnt )
+ {
+ SwCntntNode* pCNd = (SwCntntNode*)pCntnt->GetNode();
+ pToSet->GetPoint()->nNode = *pCNd;
+ pCNd->MakeStartIndex( (SwIndex*)&pToSet->GetPoint()->nContent );
+ pToSet->GetPoint()->nContent = ((SwTxtFrm*)pCntnt)->GetOfst();
+
+ SwShellCrsr* pSCrsr = dynamic_cast<SwShellCrsr*>(pToSet);
+ if( pSCrsr )
+ {
+ Point &rPt = pSCrsr->GetPtPos();
+ rPt = pCntnt->Frm().Pos();
+ rPt += pCntnt->Prt().Pos();
+ }
+ return pPage->GetPhyPageNum();
+ }
+ return 0;
+}
+
+/*************************************************************************
+|*
+|* SwCntntFrm::StartxxPage(), EndxxPage()
+|*
+|* Beschreibung Cursor an Anfang/Ende der aktuellen/vorherigen/
+|* naechsten Seite. Alle sechs Methoden rufen GetFrmInPage() mit der
+|* entsprechenden Parametrisierung.
+|* Zwei Parameter steuern die Richtung: einer bestimmt die Seite, der
+|* andere Anfang/Ende.
+|* Fuer die Bestimmung der Seite und des Cntnt (Anfang/Ende) werden
+|* die im folgenden definierten Funktionen benutzt.
+|*
+|*************************************************************************/
+SwCntntFrm *GetFirstSub( const SwLayoutFrm *pLayout )
+{
+ return ((SwPageFrm*)pLayout)->FindFirstBodyCntnt();
+}
+
+SwCntntFrm *GetLastSub( const SwLayoutFrm *pLayout )
+{
+ return ((SwPageFrm*)pLayout)->FindLastBodyCntnt();
+}
+
+SwLayoutFrm *GetNextFrm( const SwLayoutFrm *pFrm )
+{
+ SwLayoutFrm *pNext =
+ (pFrm->GetNext() && pFrm->GetNext()->IsLayoutFrm()) ?
+ (SwLayoutFrm*)pFrm->GetNext() : 0;
+ // #i39402# in case of an empty page
+ if(pNext && !pNext->ContainsCntnt())
+ pNext = (pNext->GetNext() && pNext->GetNext()->IsLayoutFrm()) ?
+ (SwLayoutFrm*)pNext->GetNext() : 0;
+ return pNext;
+}
+
+SwLayoutFrm *GetThisFrm( const SwLayoutFrm *pFrm )
+{
+ return (SwLayoutFrm*)pFrm;
+}
+
+SwLayoutFrm *GetPrevFrm( const SwLayoutFrm *pFrm )
+{
+ SwLayoutFrm *pPrev =
+ (pFrm->GetPrev() && pFrm->GetPrev()->IsLayoutFrm()) ?
+ (SwLayoutFrm*)pFrm->GetPrev() : 0;
+ // #i39402# in case of an empty page
+ if(pPrev && !pPrev->ContainsCntnt())
+ pPrev = (pPrev->GetPrev() && pPrev->GetPrev()->IsLayoutFrm()) ?
+ (SwLayoutFrm*)pPrev->GetPrev() : 0;
+ return pPrev;
+}
+
+//Jetzt koennen auch die Funktionspointer initalisiert werden;
+//sie sind in cshtyp.hxx declariert.
+SwPosPage fnPageStart = GetFirstSub;
+SwPosPage fnPageEnd = GetLastSub;
+SwWhichPage fnPagePrev = GetPrevFrm;
+SwWhichPage fnPageCurr = GetThisFrm;
+SwWhichPage fnPageNext = GetNextFrm;
+
+//Liefert den ersten/den letzten Contentframe (gesteuert ueber
+//den Parameter fnPosPage) in der
+//aktuellen/vorhergehenden/folgenden Seite (gesteuert durch den
+//Parameter fnWhichPage).
+sal_Bool GetFrmInPage( const SwCntntFrm *pCnt, SwWhichPage fnWhichPage,
+ SwPosPage fnPosPage, SwPaM *pPam )
+{
+ //Erstmal die gewuenschte Seite besorgen, anfangs die aktuelle, dann
+ //die die per fnWichPage gewuenscht wurde
+ const SwLayoutFrm *pLayoutFrm = pCnt->FindPageFrm();
+ if ( !pLayoutFrm || (0 == (pLayoutFrm = (*fnWhichPage)(pLayoutFrm))) )
+ return sal_False;
+
+ //Jetzt den gewuenschen CntntFrm unterhalb der Seite
+ if( 0 == (pCnt = (*fnPosPage)(pLayoutFrm)) )
+ return sal_False;
+ else
+ {
+ // repeated headlines in tables
+ if ( pCnt->IsInTab() && fnPosPage == GetFirstSub )
+ {
+ const SwTabFrm* pTab = pCnt->FindTabFrm();
+ if ( pTab->IsFollow() )
+ {
+ if ( pTab->IsInHeadline( *pCnt ) )
+ {
+ SwLayoutFrm* pRow = pTab->GetFirstNonHeadlineRow();
+ if ( pRow )
+ {
+ // We are in the first line of a follow table
+ // with repeated headings.
+ // To actually make a "real" move we take the first content
+ // of the next row
+ pCnt = pRow->ContainsCntnt();
+ if ( ! pCnt )
+ return sal_False;
+ }
+ }
+ }
+ }
+
+ SwCntntNode *pCNd = (SwCntntNode*)pCnt->GetNode();
+ pPam->GetPoint()->nNode = *pCNd;
+ xub_StrLen nIdx;
+ if( fnPosPage == GetFirstSub )
+ nIdx = ((SwTxtFrm*)pCnt)->GetOfst();
+ else
+ nIdx = pCnt->GetFollow() ?
+ ((SwTxtFrm*)pCnt)->GetFollow()->GetOfst()-1 : pCNd->Len();
+ pPam->GetPoint()->nContent.Assign( pCNd, nIdx );
+ return sal_True;
+ }
+}
+
+/*************************************************************************
+|*
+|* SwLayoutFrm::GetCntntPos()
+|*
+|* Beschreibung Es wird der nachstliegende Cntnt zum uebergebenen
+|* gesucht. Betrachtet werden die vorhergehende, die
+|* aktuelle und die folgende Seite.
+|* Wenn kein Inhalt gefunden wird, so wird der Bereich
+ * erweitert bis einer gefunden wird.
+|* Zurueckgegeben wird die 'Semantisch richtige' Position
+|* innerhalb der PrtArea des gefundenen CntntFrm
+|*
+|*************************************************************************/
+sal_uLong CalcDiff( const Point &rPt1, const Point &rPt2 )
+{
+ //Jetzt die Entfernung zwischen den beiden Punkten berechnen.
+ //'Delta' X^2 + 'Delta'Y^2 = 'Entfernung'^2
+ sal_uInt32 dX = Max( rPt1.X(), rPt2.X() ) -
+ Min( rPt1.X(), rPt2.X() ),
+ dY = Max( rPt1.Y(), rPt2.Y() ) -
+ Min( rPt1.Y(), rPt2.Y() );
+ BigInt dX1( dX ), dY1( dY );
+ dX1 *= dX1; dY1 *= dY1;
+ return ::SqRt( dX1 + dY1 );
+}
+
+// lcl_Inside ueberprueft, ob der Punkt innerhalb des Seitenteils liegt, in dem
+// auch der CntntFrame liegt. Als Seitenteile gelten in diesem Zusammenhang
+// Kopfzeile, Seitenbody, Fusszeile und FussnotenContainer.
+// Dies dient dazu, dass ein CntntFrm, der im "richtigen" Seitenteil liegt,
+// eher akzeptiert wird als ein anderer, der nicht dort liegt, auch wenn
+// dessen Abstand zum Punkt geringer ist.
+
+const SwLayoutFrm* lcl_Inside( const SwCntntFrm *pCnt, Point& rPt )
+{
+ const SwLayoutFrm* pUp = pCnt->GetUpper();
+ while( pUp )
+ {
+ if( pUp->IsPageBodyFrm() || pUp->IsFooterFrm() || pUp->IsHeaderFrm() )
+ {
+ if( rPt.Y() >= pUp->Frm().Top() && rPt.Y() <= pUp->Frm().Bottom() )
+ return pUp;
+ return NULL;
+ }
+ if( pUp->IsFtnContFrm() )
+ return pUp->Frm().IsInside( rPt ) ? pUp : NULL;
+ pUp = pUp->GetUpper();
+ }
+ return NULL;
+}
+
+const SwCntntFrm *SwLayoutFrm::GetCntntPos( Point& rPoint,
+ const sal_Bool bDontLeave,
+ const sal_Bool bBodyOnly,
+ const sal_Bool bCalc,
+ const SwCrsrMoveState *pCMS,
+ const sal_Bool bDefaultExpand ) const
+{
+ //Ersten CntntFrm ermitteln.
+ const SwLayoutFrm *pStart = (!bDontLeave && bDefaultExpand && GetPrev()) ?
+ (SwLayoutFrm*)GetPrev() : this;
+ const SwCntntFrm *pCntnt = pStart->ContainsCntnt();
+
+ if ( !pCntnt && (GetPrev() && !bDontLeave) )
+ pCntnt = ContainsCntnt();
+
+ if ( bBodyOnly && pCntnt && !pCntnt->IsInDocBody() )
+ while ( pCntnt && !pCntnt->IsInDocBody() )
+ pCntnt = pCntnt->GetNextCntntFrm();
+
+ const SwCntntFrm *pActual= pCntnt;
+ const SwLayoutFrm *pInside = NULL;
+ sal_uInt16 nMaxPage = GetPhyPageNum() + (bDefaultExpand ? 1 : 0);
+ Point aPoint = rPoint;
+ sal_uLong nDistance = ULONG_MAX;
+
+ while ( sal_True ) //Sicherheitsschleifchen, damit immer einer gefunden wird.
+ {
+ while ( pCntnt &&
+ ((!bDontLeave || IsAnLower( pCntnt )) &&
+ (pCntnt->GetPhyPageNum() <= nMaxPage)) )
+ {
+ if ( ( bCalc || pCntnt->Frm().Width() ) &&
+ ( !bBodyOnly || pCntnt->IsInDocBody() ) )
+ {
+ //Wenn der Cntnt in einem geschuetzen Bereich (Zelle, Ftn, Section)
+ //liegt, wird der nachste Cntnt der nicht geschuetzt ist gesucht.
+ const SwCntntFrm *pComp = pCntnt;
+ pCntnt = ::lcl_MissProtectedFrames( pCntnt, lcl_GetNxtCnt, sal_False,
+ pCMS ? pCMS->bSetInReadOnly : sal_False, sal_False );
+ if ( pComp != pCntnt )
+ continue;
+
+ if ( !pCntnt->IsTxtFrm() || !((SwTxtFrm*)pCntnt)->IsHiddenNow() )
+ {
+ if ( bCalc )
+ pCntnt->Calc();
+
+ SwRect aCntFrm( pCntnt->UnionFrm() );
+ if ( aCntFrm.IsInside( rPoint ) )
+ {
+ pActual = pCntnt;
+ aPoint = rPoint;
+ break;
+ }
+ //Die Strecke von rPoint zum dichtesten Punkt von pCntnt wird
+ //jetzt berechnet.
+ Point aCntntPoint( rPoint );
+
+ //Erst die Vertikale Position einstellen
+ if ( aCntFrm.Top() > aCntntPoint.Y() )
+ aCntntPoint.Y() = aCntFrm.Top();
+ else if ( aCntFrm.Bottom() < aCntntPoint.Y() )
+ aCntntPoint.Y() = aCntFrm.Bottom();
+
+ //Jetzt die Horizontale Position
+ if ( aCntFrm.Left() > aCntntPoint.X() )
+ aCntntPoint.X() = aCntFrm.Left();
+ else if ( aCntFrm.Right() < aCntntPoint.X() )
+ aCntntPoint.X() = aCntFrm.Right();
+
+ // pInside ist ein Seitenbereich, in dem der Punkt liegt,
+ // sobald pInside!=0 ist, werden nur noch Frames akzeptiert,
+ // die innerhalb liegen.
+ if( !pInside || ( pInside->IsAnLower( pCntnt ) &&
+ ( !pCntnt->IsInFtn() || pInside->IsFtnContFrm() ) ) )
+ {
+ const sal_uLong nDiff = ::CalcDiff( aCntntPoint, rPoint );
+ sal_Bool bBetter = nDiff < nDistance; // Dichter dran
+ if( !pInside )
+ {
+ pInside = lcl_Inside( pCntnt, rPoint );
+ if( pInside ) // Im "richtigen" Seitenteil
+ bBetter = sal_True;
+ }
+ if( bBetter )
+ {
+ aPoint = aCntntPoint;
+ nDistance = nDiff;
+ pActual = pCntnt;
+ }
+ }
+ }
+ }
+ pCntnt = pCntnt->GetNextCntntFrm();
+ if ( bBodyOnly )
+ while ( pCntnt && !pCntnt->IsInDocBody() )
+ pCntnt = pCntnt->GetNextCntntFrm();
+ }
+ if ( !pActual )
+ { //Wenn noch keiner gefunden wurde muss der Suchbereich erweitert
+ //werden, irgenwann muessen wir einen Finden!
+ //MA 09. Jan. 97: Opt fuer viele leere Seiten, wenn wir nur im
+ //Body suchen, koennen wir den Suchbereich gleich in einem
+ //Schritt hinreichend erweitern.
+ if ( bBodyOnly )
+ {
+ while ( !pCntnt && pStart->GetPrev() )
+ {
+ ++nMaxPage;
+ if( !pStart->GetPrev()->IsLayoutFrm() )
+ return 0;
+ pStart = (SwLayoutFrm*)pStart->GetPrev();
+ pCntnt = pStart->IsInDocBody()
+ ? pStart->ContainsCntnt()
+ : pStart->FindPageFrm()->FindFirstBodyCntnt();
+ }
+ if ( !pCntnt ) //irgendwann muessen wir mit irgendeinem Anfangen!
+ {
+ pCntnt = pStart->FindPageFrm()->GetUpper()->ContainsCntnt();
+ while ( pCntnt && !pCntnt->IsInDocBody() )
+ pCntnt = pCntnt->GetNextCntntFrm();
+ if ( !pCntnt )
+ return 0; //Es gibt noch keine Dokumentinhalt!
+ }
+ }
+ else
+ {
+ ++nMaxPage;
+ if ( pStart->GetPrev() )
+ {
+ if( !pStart->GetPrev()->IsLayoutFrm() )
+ return 0;
+ pStart = (SwLayoutFrm*)pStart->GetPrev();
+ pCntnt = pStart->ContainsCntnt();
+ }
+ else //irgendwann muessen wir mit irgendeinem Anfangen!
+ pCntnt = pStart->FindPageFrm()->GetUpper()->ContainsCntnt();
+ }
+ pActual = pCntnt;
+ }
+ else
+ break;
+ }
+
+#if OSL_DEBUG_LEVEL > 1
+ OSL_ENSURE( pActual, "Keinen Cntnt gefunden." );
+ if ( bBodyOnly )
+ OSL_ENSURE( pActual->IsInDocBody(), "Cnt nicht im Body." );
+#endif
+
+ //Spezialfall fuer das selektieren von Tabellen, nicht in wiederholte
+ //TblHedlines.
+ if ( pActual->IsInTab() && pCMS && pCMS->eState == MV_TBLSEL )
+ {
+ const SwTabFrm *pTab = pActual->FindTabFrm();
+ if ( pTab->IsFollow() && pTab->IsInHeadline( *pActual ) )
+ {
+ ((SwCrsrMoveState*)pCMS)->bStop = sal_True;
+ return 0;
+ }
+ }
+
+ //Jetzt noch eine kleine Korrektur beim ersten/letzten
+ Size aActualSize( pActual->Prt().SSize() );
+ if ( aActualSize.Height() > pActual->GetUpper()->Prt().Height() )
+ aActualSize.Height() = pActual->GetUpper()->Prt().Height();
+
+ SWRECTFN( pActual )
+ if ( !pActual->GetPrev() &&
+ (*fnRect->fnYDiff)( (pActual->*fnRect->fnGetPrtTop)(),
+ bVert ? rPoint.X() : rPoint.Y() ) > 0 )
+ {
+ aPoint.Y() = pActual->Frm().Top() + pActual->Prt().Top();
+ aPoint.X() = pActual->Frm().Left() +
+ ( pActual->IsRightToLeft() || bVert ?
+ pActual->Prt().Right() :
+ pActual->Prt().Left() );
+ }
+ else if ( !pActual->GetNext() &&
+ (*fnRect->fnYDiff)( (pActual->*fnRect->fnGetPrtBottom)(),
+ bVert ? rPoint.X() : rPoint.Y() ) < 0 )
+ {
+ aPoint.Y() = pActual->Frm().Top() + pActual->Prt().Bottom();
+ aPoint.X() = pActual->Frm().Left() +
+ ( pActual->IsRightToLeft() || bVert ?
+ pActual->Prt().Left() :
+ pActual->Prt().Right() );
+ }
+
+ //Und den Point in die PrtArea bringen
+ if ( bCalc )
+ pActual->Calc();
+ const SwRect aRect( pActual->Frm().Pos() + pActual->Prt().Pos(),
+ aActualSize );
+ if ( aPoint.Y() < aRect.Top() )
+ aPoint.Y() = aRect.Top();
+ else if ( aPoint.Y() > aRect.Bottom() )
+ aPoint.Y() = aRect.Bottom();
+ if ( aPoint.X() < aRect.Left() )
+ aPoint.X() = aRect.Left();
+ else if ( aPoint.X() > aRect.Right() )
+ aPoint.X() = aRect.Right();
+ rPoint = aPoint;
+ return pActual;
+}
+
+/*************************************************************************
+|*
+|* SwPageFrm::GetCntntPosition()
+|*
+|* Beschreibung Analog zu SwLayoutFrm::GetCntntPos().
+|* Spezialisiert fuer Felder in Rahmen.
+|*
+|*************************************************************************/
+void SwPageFrm::GetCntntPosition( const Point &rPt, SwPosition &rPos ) const
+{
+ //Ersten CntntFrm ermitteln.
+ const SwCntntFrm *pCntnt = ContainsCntnt();
+ if ( pCntnt )
+ {
+ //Einen weiter zurueck schauen (falls moeglich).
+ const SwCntntFrm *pTmp = pCntnt->GetPrevCntntFrm();
+ while ( pTmp && !pTmp->IsInDocBody() )
+ pTmp = pTmp->GetPrevCntntFrm();
+ if ( pTmp )
+ pCntnt = pTmp;
+ }
+ else
+ pCntnt = GetUpper()->ContainsCntnt();
+
+ const SwCntntFrm *pAct = pCntnt;
+ Point aAct = rPt;
+ sal_uLong nDist = ULONG_MAX;
+
+ while ( pCntnt )
+ {
+ SwRect aCntFrm( pCntnt->UnionFrm() );
+ if ( aCntFrm.IsInside( rPt ) )
+ {
+ //dichter gehts nimmer.
+ pAct = pCntnt;
+ break;
+ }
+
+ //Die Strecke von rPt zum dichtesten Punkt von pCntnt berechnen.
+ Point aPoint( rPt );
+
+ //Erst die vertikale Position einstellen
+ if ( aCntFrm.Top() > rPt.Y() )
+ aPoint.Y() = aCntFrm.Top();
+ else if ( aCntFrm.Bottom() < rPt.Y() )
+ aPoint.Y() = aCntFrm.Bottom();
+
+ //Jetzt die horizontale Position
+ if ( aCntFrm.Left() > rPt.X() )
+ aPoint.X() = aCntFrm.Left();
+ else if ( aCntFrm.Right() < rPt.X() )
+ aPoint.X() = aCntFrm.Right();
+
+ const sal_uLong nDiff = ::CalcDiff( aPoint, rPt );
+ if ( nDiff < nDist )
+ {
+ aAct = aPoint;
+ nDist = nDiff;
+ pAct = pCntnt;
+ }
+ else if ( aCntFrm.Top() > Frm().Bottom() )
+ //Dichter wirds im Sinne der Felder nicht mehr!
+ break;
+
+ pCntnt = pCntnt->GetNextCntntFrm();
+ while ( pCntnt && !pCntnt->IsInDocBody() )
+ pCntnt = pCntnt->GetNextCntntFrm();
+ }
+
+ //Und den Point in die PrtArea bringen
+ const SwRect aRect( pAct->Frm().Pos() + pAct->Prt().Pos(), pAct->Prt().SSize() );
+ if ( aAct.Y() < aRect.Top() )
+ aAct.Y() = aRect.Top();
+ else if ( aAct.Y() > aRect.Bottom() )
+ aAct.Y() = aRect.Bottom();
+ if ( aAct.X() < aRect.Left() )
+ aAct.X() = aRect.Left();
+ else if ( aAct.X() > aRect.Right() )
+ aAct.X() = aRect.Right();
+
+ if( !pAct->IsValid() )
+ {
+ // CntntFrm nicht formatiert -> immer auf Node-Anfang
+ SwCntntNode* pCNd = (SwCntntNode*)pAct->GetNode();
+ OSL_ENSURE( pCNd, "Wo ist mein CntntNode?" );
+ rPos.nNode = *pCNd;
+ rPos.nContent.Assign( pCNd, 0 );
+ }
+ else
+ {
+ SwCrsrMoveState aTmpState( MV_SETONLYTEXT );
+ pAct->GetCrsrOfst( &rPos, aAct, &aTmpState );
+ }
+}
+
+/*************************************************************************
+|*
+|* SwRootFrm::GetNextPrevCntntPos()
+|*
+|* Beschreibung Es wird der naechstliegende Cntnt zum uebergebenen
+|* Point gesucht. Es wird nur im BodyText gesucht.
+|*
+|*************************************************************************/
+
+// --> OD 2005-05-25 #123110# - helper class to disable creation of an action
+// by a callback event - e.g., change event from a drawing object
+class DisableCallbackAction
+{
+ private:
+ SwRootFrm& mrRootFrm;
+ sal_Bool mbOldCallbackActionState;
+
+ public:
+ DisableCallbackAction( const SwRootFrm& _rRootFrm ) :
+ mrRootFrm( const_cast<SwRootFrm&>(_rRootFrm) ),
+ mbOldCallbackActionState( _rRootFrm.IsCallbackActionEnabled() )
+ {
+ mrRootFrm.SetCallbackActionEnabled( sal_False );
+ }
+
+ ~DisableCallbackAction()
+ {
+ mrRootFrm.SetCallbackActionEnabled( mbOldCallbackActionState );
+ }
+};
+// <--
+
+//!!!!! Es wird nur der vertikal naechstliegende gesucht.
+//JP 11.10.2001: only in tables we try to find the right column - Bug 72294
+Point SwRootFrm::GetNextPrevCntntPos( const Point& rPoint, sal_Bool bNext ) const
+{
+ // --> OD 2005-05-25 #123110# - disable creation of an action by a callback
+ // event during processing of this method. Needed because formatting is
+ // triggered by this method.
+ DisableCallbackAction aDisableCallbackAction( *this );
+ // <--
+ //Ersten CntntFrm und seinen Nachfolger im Body-Bereich suchen
+ //Damit wir uns nicht tot suchen (und vor allem nicht zuviel formatieren)
+ //gehen wir schon mal von der richtigen Seite aus.
+ SwLayoutFrm *pPage = (SwLayoutFrm*)Lower();
+ if( pPage )
+ while( pPage->GetNext() && pPage->Frm().Bottom() < rPoint.Y() )
+ pPage = (SwLayoutFrm*)pPage->GetNext();
+
+ const SwCntntFrm *pCnt = pPage ? pPage->ContainsCntnt() : ContainsCntnt();
+ while ( pCnt && !pCnt->IsInDocBody() )
+ pCnt = pCnt->GetNextCntntFrm();
+
+ if ( !pCnt )
+ return Point( 0, 0 );
+
+ pCnt->Calc();
+ if( !bNext )
+ {
+ // Solange der Point vor dem ersten CntntFrm liegt und es noch
+ // vorhergehende Seiten gibt gehe ich jeweils eine Seite nach vorn.
+ while ( rPoint.Y() < pCnt->Frm().Top() && pPage->GetPrev() )
+ {
+ pPage = (SwLayoutFrm*)pPage->GetPrev();
+ pCnt = pPage->ContainsCntnt();
+ while ( !pCnt )
+ {
+ pPage = (SwLayoutFrm*)pPage->GetPrev();
+ if ( pPage )
+ pCnt = pPage->ContainsCntnt();
+ else
+ return ContainsCntnt()->UnionFrm().Pos();
+ }
+ pCnt->Calc();
+ }
+ }
+
+ //Liegt der Point ueber dem ersten CntntFrm?
+ if ( rPoint.Y() < pCnt->Frm().Top() && !lcl_IsInRepeatedHeadline( pCnt ) )
+ return pCnt->UnionFrm().Pos();
+
+ while ( pCnt )
+ {
+ //Liegt der Point im aktuellen CntntFrm?
+ SwRect aCntFrm( pCnt->UnionFrm() );
+ if ( aCntFrm.IsInside( rPoint ) && !lcl_IsInRepeatedHeadline( pCnt ))
+ return rPoint;
+
+ //Ist der aktuelle der letzte CntntFrm? ||
+ //Wenn der naechste CntntFrm hinter dem Point liegt, ist der
+ //aktuelle der gesuchte.
+ const SwCntntFrm *pNxt = pCnt->GetNextCntntFrm();
+ while ( pNxt && !pNxt->IsInDocBody() )
+ pNxt = pNxt->GetNextCntntFrm();
+
+ //Liegt der Point hinter dem letzten CntntFrm?
+ if ( !pNxt )
+ return Point( aCntFrm.Right(), aCntFrm.Bottom() );
+
+ //Wenn der naechste CntntFrm hinter dem Point liegt ist er der
+ //gesuchte.
+ const SwTabFrm* pTFrm;
+ pNxt->Calc();
+ if( pNxt->Frm().Top() > rPoint.Y() &&
+ !lcl_IsInRepeatedHeadline( pCnt, &pTFrm ) &&
+ ( !pTFrm || pNxt->Frm().Left() > rPoint.X() ))
+ {
+ if( bNext )
+ return pNxt->Frm().Pos();
+ return Point( aCntFrm.Right(), aCntFrm.Bottom() );
+ }
+ pCnt = pNxt;
+ }
+ return Point( 0, 0 );
+}
+
+/*************************************************************************
+|*
+|* SwRootFrm::GetPagePos()
+|*
+|* Beschreibung: Liefert die absolute Dokumentpositon der gewuenschten
+|* Seite.
+|* Formatiert wird nur soweit notwendig und nur dann wenn bFormat=sal_True
+|* Liefert Null, wenn die Operation nicht moeglich ist.
+|* Die Pos ist die der letzten Seite, wenn die Seitenzahl zu gross
+|* gewaehlt wurde.
+|*
+|*************************************************************************/
+Point SwRootFrm::GetPagePos( sal_uInt16 nPageNum ) const
+{
+ OSL_ENSURE( Lower() && Lower()->IsPageFrm(), "Keine Seite vorhanden." );
+
+ const SwPageFrm *pPage = (const SwPageFrm*)Lower();
+ while ( sal_True )
+ {
+ if ( pPage->GetPhyPageNum() >= nPageNum || !pPage->GetNext() )
+ break;
+ pPage = (const SwPageFrm*)pPage->GetNext();
+ }
+ return pPage->Frm().Pos();
+}
+
+/** get page frame by phyiscal page number
+
+ OD 14.01.2003 #103492#
+
+ @return pointer to the page frame with the given physical page number
+*/
+SwPageFrm* SwRootFrm::GetPageByPageNum( sal_uInt16 _nPageNum ) const
+{
+ const SwPageFrm* pPageFrm = static_cast<const SwPageFrm*>( Lower() );
+ while ( pPageFrm && pPageFrm->GetPhyPageNum() < _nPageNum )
+ {
+ pPageFrm = static_cast<const SwPageFrm*>( pPageFrm->GetNext() );
+ }
+
+ if ( pPageFrm && pPageFrm->GetPhyPageNum() == _nPageNum )
+ {
+ return const_cast<SwPageFrm*>( pPageFrm );
+ }
+ else
+ {
+ return 0;
+ }
+}
+
+/*************************************************************************
+|*
+|* SwRootFrm::IsDummyPage(sal_uInt16)
+|*
+|* Description: Returns sal_True, when the given physical pagenumber does't exist
+|* or this page is an empty page.
+|*************************************************************************/
+sal_Bool SwRootFrm::IsDummyPage( sal_uInt16 nPageNum ) const
+{
+ if( !Lower() || !nPageNum || nPageNum > GetPageNum() )
+ return sal_True;
+
+ const SwPageFrm *pPage = (const SwPageFrm*)Lower();
+ while( pPage && nPageNum < pPage->GetPhyPageNum() )
+ pPage = (const SwPageFrm*)pPage->GetNext();
+ return pPage ? pPage->IsEmptyPage() : sal_True;
+}
+
+
+/*************************************************************************
+|*
+|* SwFrm::IsProtected()
+|*
+|* Beschreibung Ist der Frm bzw. die Section in der er steht
+|* geschuetzt?
+|* Auch Fly in Fly in ... und Fussnoten
+|*
+|*
+|*************************************************************************/
+sal_Bool SwFrm::IsProtected() const
+{
+ if (this->IsCntntFrm() && ((SwCntntFrm*)this)->GetNode())
+ {
+ const SwDoc *pDoc=((SwCntntFrm*)this)->GetNode()->GetDoc();
+ bool isFormProtected=pDoc->get(IDocumentSettingAccess::PROTECT_FORM );
+ if (isFormProtected)
+ {
+ return sal_False; // TODO a hack for now, well deal with it laster, I we return true here we have a "double" locking
+ }
+ }
+ //Der Frm kann in Rahmen, Zellen oder Bereichen geschuetzt sein.
+ //Geht auch FlyFrms rekursiv hoch. Geht auch von Fussnoten zum Anker.
+ const SwFrm *pFrm = this;
+ do
+ {
+ if ( pFrm->IsCntntFrm() )
+ {
+ if ( ((SwCntntFrm*)pFrm)->GetNode() &&
+ ((SwCntntFrm*)pFrm)->GetNode()->IsInProtectSect() )
+ return sal_True;
+ }
+ else
+ {
+ if ( ((SwLayoutFrm*)pFrm)->GetFmt() &&
+ ((SwLayoutFrm*)pFrm)->GetFmt()->
+ GetProtect().IsCntntProtected() )
+ return sal_True;
+ if ( pFrm->IsCoveredCell() )
+ return sal_True;
+ }
+ if ( pFrm->IsFlyFrm() )
+ {
+ //Der Schutz des Inhaltes kann bei Verkettung vom Master der Kette
+ //vorgegeben werden.
+ if ( ((SwFlyFrm*)pFrm)->GetPrevLink() )
+ {
+ SwFlyFrm *pMaster = (SwFlyFrm*)pFrm;
+ do
+ { pMaster = pMaster->GetPrevLink();
+ } while ( pMaster->GetPrevLink() );
+ if ( pMaster->IsProtected() )
+ return sal_True;
+ }
+ pFrm = ((SwFlyFrm*)pFrm)->GetAnchorFrm();
+ }
+ else if ( pFrm->IsFtnFrm() )
+ pFrm = ((SwFtnFrm*)pFrm)->GetRef();
+ else
+ pFrm = pFrm->GetUpper();
+
+ } while ( pFrm );
+
+ return sal_False;
+}
+
+/*************************************************************************
+|*
+|* SwFrm::GetPhyPageNum()
+|* Beschreibung: Liefert die physikalische Seitennummer
+|*
+|*
+|*************************************************************************/
+sal_uInt16 SwFrm::GetPhyPageNum() const
+{
+ const SwPageFrm *pPage = FindPageFrm();
+ return pPage ? pPage->GetPhyPageNum() : 0;
+}
+
+/*--------------------------------------------------
+ * SwFrm::WannaRightPage()
+ * decides if the page want to be a rightpage or not.
+ * If the first content of the page has a page descriptor,
+ * we take the follow of the page descriptor of the last not empty page.
+ * If this descriptor allows only right(left) pages and the page
+ * isn't an empty page then it wanna be such right(left) page.
+ * If the descriptor allows right and left pages, we look for a number offset
+ * in the first content. If there is one, odd number results right pages,
+ * even number results left pages.
+ * If there is no number offset, we take the physical page number instead,
+ * but a previous empty page don't count.
+ * --------------------------------------------------*/
+
+sal_Bool SwFrm::WannaRightPage() const
+{
+ const SwPageFrm *pPage = FindPageFrm();
+ if ( !pPage || !pPage->GetUpper() )
+ return sal_True;
+
+ const SwFrm *pFlow = pPage->FindFirstBodyCntnt();
+ SwPageDesc *pDesc = 0;
+ sal_uInt16 nPgNum = 0;
+ if ( pFlow )
+ {
+ if ( pFlow->IsInTab() )
+ pFlow = pFlow->FindTabFrm();
+ const SwFlowFrm *pTmp = SwFlowFrm::CastFlowFrm( pFlow );
+ if ( !pTmp->IsFollow() )
+ {
+ const SwFmtPageDesc& rPgDesc = pFlow->GetAttrSet()->GetPageDesc();
+ pDesc = (SwPageDesc*)rPgDesc.GetPageDesc();
+ nPgNum = rPgDesc.GetNumOffset();
+ }
+ }
+ if ( !pDesc )
+ {
+ SwPageFrm *pPrv = (SwPageFrm*)pPage->GetPrev();
+ if( pPrv && pPrv->IsEmptyPage() )
+ pPrv = (SwPageFrm*)pPrv->GetPrev();
+ if( pPrv )
+ pDesc = pPrv->GetPageDesc()->GetFollow();
+ else
+ {
+ const SwDoc* pDoc = pPage->GetFmt()->GetDoc();
+ pDesc = (SwPageDesc*)&pDoc->GetPageDesc( 0 );
+ }
+ }
+ OSL_ENSURE( pDesc, "No pagedescriptor" );
+ sal_Bool bOdd;
+ if( nPgNum )
+ bOdd = nPgNum % 2 ? sal_True : sal_False;
+ else
+ {
+ bOdd = pPage->OnRightPage();
+ if( pPage->GetPrev() && ((SwPageFrm*)pPage->GetPrev())->IsEmptyPage() )
+ bOdd = !bOdd;
+ }
+ if( !pPage->IsEmptyPage() )
+ {
+ if( !pDesc->GetRightFmt() )
+ bOdd = sal_False;
+ else if( !pDesc->GetLeftFmt() )
+ bOdd = sal_True;
+ }
+ return bOdd;
+}
+
+/*************************************************************************
+|*
+|* SwFrm::GetVirtPageNum()
+|* Beschreibung: Liefert die virtuelle Seitennummer mit Offset
+|*
+|*************************************************************************/
+sal_uInt16 SwFrm::GetVirtPageNum() const
+{
+ const SwPageFrm *pPage = FindPageFrm();
+ if ( !pPage || !pPage->GetUpper() )
+ return 0;
+
+ sal_uInt16 nPhyPage = pPage->GetPhyPageNum();
+ if ( !((SwRootFrm*)pPage->GetUpper())->IsVirtPageNum() )
+ return nPhyPage;
+
+ //Den am naechsten stehenden Absatz mit virtueller Seitennummer suchen.
+ //Da das rueckwaertsuchen insgesamt sehr viel Zeit verschlingt suchen
+ //wir jetzt gezielt ueber die Abhaengigkeiten.
+ //von den PageDescs bekommen wir die Attribute, von den Attributen
+ //wiederum bekommen wir die Absaetze.
+ const SwPageFrm *pVirtPage = 0;
+ const SwFrm *pFrm = 0;
+ const SfxItemPool &rPool = pPage->GetFmt()->GetDoc()->GetAttrPool();
+ const SfxPoolItem* pItem;
+ sal_uInt32 nMaxItems = rPool.GetItemCount2( RES_PAGEDESC );
+ for( sal_uInt32 n = 0; n < nMaxItems; ++n )
+ {
+ if( 0 == (pItem = rPool.GetItem2( RES_PAGEDESC, n ) ))
+ continue;
+
+ const SwFmtPageDesc *pDesc = (SwFmtPageDesc*)pItem;
+ if ( pDesc->GetNumOffset() && pDesc->GetDefinedIn() )
+ {
+ const SwModify *pMod = pDesc->GetDefinedIn();
+ SwVirtPageNumInfo aInfo( pPage );
+ pMod->GetInfo( aInfo );
+ if ( aInfo.GetPage() )
+ {
+ if( !pVirtPage || ( pVirtPage && aInfo.GetPage()->
+ GetPhyPageNum() > pVirtPage->GetPhyPageNum() ) )
+ {
+ pVirtPage = aInfo.GetPage();
+ pFrm = aInfo.GetFrm();
+ }
+ }
+ }
+ }
+ if ( pFrm )
+ return nPhyPage - pFrm->GetPhyPageNum() +
+ pFrm->GetAttrSet()->GetPageDesc().GetNumOffset();
+ return nPhyPage;
+}
+
+/*************************************************************************
+|*
+|* SwRootFrm::MakeTblCrsrs()
+|*
+|*************************************************************************/
+//Ermitteln und einstellen derjenigen Zellen die von der Selektion
+//eingeschlossen sind.
+
+bool SwRootFrm::MakeTblCrsrs( SwTableCursor& rTblCrsr )
+{
+ //Union-Rects und Tabellen (Follows) der Selektion besorgen.
+ OSL_ENSURE( rTblCrsr.GetCntntNode() && rTblCrsr.GetCntntNode( sal_False ),
+ "Tabselection nicht auf Cnt." );
+
+ bool bRet = false;
+
+ // For new table models there's no need to ask the layout..
+ if( rTblCrsr.NewTableSelection() )
+ return true;
+
+ Point aPtPt, aMkPt;
+ {
+ SwShellCrsr* pShCrsr = dynamic_cast<SwShellCrsr*>(&rTblCrsr);
+
+ if( pShCrsr )
+ {
+ aPtPt = pShCrsr->GetPtPos();
+ aMkPt = pShCrsr->GetMkPos();
+ }
+ }
+
+ // --> FME 2008-01-14 #151012# Made code robust here:
+ const SwCntntNode* pTmpStartNode = rTblCrsr.GetCntntNode();
+ const SwCntntNode* pTmpEndNode = rTblCrsr.GetCntntNode(sal_False);
+
+ const SwFrm* pTmpStartFrm = pTmpStartNode ? pTmpStartNode->getLayoutFrm( this, &aPtPt, 0, sal_False ) : 0;
+ const SwFrm* pTmpEndFrm = pTmpEndNode ? pTmpEndNode->getLayoutFrm( this, &aMkPt, 0, sal_False ) : 0;
+
+ const SwLayoutFrm* pStart = pTmpStartFrm ? pTmpStartFrm->GetUpper() : 0;
+ const SwLayoutFrm* pEnd = pTmpEndFrm ? pTmpEndFrm->GetUpper() : 0;
+
+ OSL_ENSURE( pStart && pEnd, "MakeTblCrsrs: Good to have the code robust here!" );
+ // <--
+
+ /* #109590# Only change table boxes if the frames are
+ valid. Needed because otherwise the table cursor after moving
+ table cells by dnd resulted in an empty tables cursor. */
+ if ( pStart && pEnd && pStart->IsValid() && pEnd->IsValid())
+ {
+ SwSelUnions aUnions;
+ ::MakeSelUnions( aUnions, pStart, pEnd );
+
+ SwSelBoxes aNew;
+
+ const sal_Bool bReadOnlyAvailable = rTblCrsr.IsReadOnlyAvailable();
+
+ for ( sal_uInt16 i = 0; i < aUnions.Count(); ++i )
+ {
+ SwSelUnion *pUnion = aUnions[i];
+ const SwTabFrm *pTable = pUnion->GetTable();
+
+ // Skip any repeated headlines in the follow:
+ SwLayoutFrm* pRow = pTable->IsFollow() ?
+ pTable->GetFirstNonHeadlineRow() :
+ (SwLayoutFrm*)pTable->Lower();
+
+ while ( pRow )
+ {
+ if ( pRow->Frm().IsOver( pUnion->GetUnion() ) )
+ {
+ const SwLayoutFrm *pCell = pRow->FirstCell();
+
+ while ( pCell && pRow->IsAnLower( pCell ) )
+ {
+ OSL_ENSURE( pCell->IsCellFrm(), "Frame ohne Celle" );
+ if( IsFrmInTblSel( pUnion->GetUnion(), pCell ) &&
+ (bReadOnlyAvailable ||
+ !pCell->GetFmt()->GetProtect().IsCntntProtected()))
+ {
+ SwTableBox* pInsBox = (SwTableBox*)
+ ((SwCellFrm*)pCell)->GetTabBox();
+ aNew.Insert( pInsBox );
+ }
+ if ( pCell->GetNext() )
+ {
+ pCell = (const SwLayoutFrm*)pCell->GetNext();
+ if ( pCell->Lower() && pCell->Lower()->IsRowFrm() )
+ pCell = pCell->FirstCell();
+ }
+ else
+ {
+ const SwLayoutFrm* pLastCell = pCell;
+ do
+ {
+ pCell = pCell->GetNextLayoutLeaf();
+ } while ( pCell && pLastCell->IsAnLower( pCell ) );
+ // Fuer (spaltige) Bereiche...
+ if( pCell && pCell->IsInTab() )
+ {
+ while( !pCell->IsCellFrm() )
+ {
+ pCell = pCell->GetUpper();
+ OSL_ENSURE( pCell, "Where's my cell?" );
+ }
+ }
+ }
+ }
+ }
+ pRow = (SwLayoutFrm*)pRow->GetNext();
+ }
+ }
+
+ rTblCrsr.ActualizeSelection( aNew );
+ bRet = true;
+ }
+
+ return bRet;
+}
+
+
+/*************************************************************************
+|*
+|* SwRootFrm::CalcFrmRects
+|*
+|*************************************************************************/
+
+/*
+ * nun koennen folgende Situationen auftreten:
+ * 1. Start und Ende liegen in einer Bildschirm - Zeile und im
+ * gleichen Node
+ * -> aus Start und End ein Rectangle, dann Ok
+ * 2. Start und Ende liegen in einem Frame (dadurch im gleichen Node!)
+ * -> Start nach rechts, End nach links erweitern,
+ * und bei mehr als 2 Bildschirm - Zeilen, das dazwischen
+ * liegende berechnen
+ * 3. Start und Ende liegen in verschiedenen Frames
+ * -> Start nach rechts erweitern, bis Frame-Ende Rect berechnen
+ * Ende nach links erweitern, bis Frame-Start Rect berechnen
+ * und bei mehr als 2 Frames von allen dazwischen liegenden
+ * Frames die PrtArea dazu.
+ * 4. Wenn es sich um eine Tabellenselektion handelt wird fuer jeden
+ * PaM im Ring der CellFrm besorgt, dessen PrtArea wird zu den
+ * Rechtecken addiert.
+ *
+ * Grosser Umbau wg. der FlyFrm; denn diese muessen ausgespart werden.
+ * Ausnahmen: - Der Fly in dem die Selektion stattfindet (wenn sie in einem Fly
+ * stattfindet).
+ * - Die Flys, die vom Text unterlaufen werden.
+ * Arbeitsweise: Zuerst wird eine SwRegion mit der Root initialisiert.
+ * Aus der Region werden die zu invertierenden Bereiche
+ * ausgestantzt. Die Region wird Komprimiert und letztlich
+ * invertiert. Damit liegen dann die zu invertierenden
+ * Rechtecke vor.
+ * Am Ende werden die Flys aus der Region ausgestanzt.
+ */
+
+inline void Sub( SwRegionRects& rRegion, const SwRect& rRect )
+{
+ if( rRect.Width() > 1 && rRect.Height() > 1 &&
+ rRect.IsOver( rRegion.GetOrigin() ))
+ rRegion -= rRect;
+}
+
+void SwRootFrm::CalcFrmRects( SwShellCrsr &rCrsr, sal_Bool bIsTblMode )
+{
+ SwPosition *pStartPos = rCrsr.Start(),
+ *pEndPos = rCrsr.GetPoint() == pStartPos ?
+ rCrsr.GetMark() : rCrsr.GetPoint();
+
+ ViewShell *pSh = GetCurrShell();
+
+// --> FME 2004-06-08 #i12836# enhanced pdf
+ SwRegionRects aRegion( pSh && !pSh->GetViewOptions()->IsPDFExport() ?
+ pSh->VisArea() :
+ Frm() );
+// <--
+ if( !pStartPos->nNode.GetNode().IsCntntNode() ||
+ !pStartPos->nNode.GetNode().GetCntntNode()->getLayoutFrm(this) ||
+ ( pStartPos->nNode != pEndPos->nNode &&
+ ( !pEndPos->nNode.GetNode().IsCntntNode() ||
+ !pEndPos->nNode.GetNode().GetCntntNode()->getLayoutFrm(this) ) ) )
+ {
+ return;
+ }
+
+ //Erstmal die CntntFrms zum Start und End besorgen, die brauch ich auf
+ //jedenfall.
+ SwCntntFrm const* pStartFrm = pStartPos->nNode.GetNode().
+ GetCntntNode()->getLayoutFrm( this, &rCrsr.GetSttPos(), pStartPos );
+
+ SwCntntFrm const* pEndFrm = pEndPos->nNode.GetNode().
+ GetCntntNode()->getLayoutFrm( this, &rCrsr.GetEndPos(), pEndPos );
+
+ OSL_ENSURE( (pStartFrm && pEndFrm), "Keine CntntFrms gefunden." );
+
+ //Damit die FlyFrms, in denen selektierte Frames stecken, nicht
+ //abgezogen werden
+ SwSortedObjs aSortObjs;
+ if ( pStartFrm->IsInFly() )
+ {
+ const SwAnchoredObject* pObj = pStartFrm->FindFlyFrm();
+ OSL_ENSURE( pObj, "No Start Object." );
+ if (pObj) aSortObjs.Insert( *(const_cast<SwAnchoredObject*>(pObj)) );
+ const SwAnchoredObject* pObj2 = pEndFrm->FindFlyFrm();
+ OSL_ENSURE( pObj2, "No Start Object." );
+ if (pObj2) aSortObjs.Insert( *(const_cast<SwAnchoredObject*>(pObj2)) );
+ }
+
+ //Fall 4: Tabellenselection
+ if( bIsTblMode )
+ {
+ const SwFrm *pCell = pStartFrm->GetUpper();
+ while ( !pCell->IsCellFrm() )
+ pCell = pCell->GetUpper();
+ SwRect aTmp( pCell->Prt() );
+ aTmp.Pos() += pCell->Frm().Pos();
+ aRegion.ChangeOrigin( aTmp );
+ aRegion.Remove( 0, aRegion.Count() );
+ aRegion.Insert( aTmp, 0 );
+ }
+ else
+ {
+ // falls eine nicht erlaubte Selection besteht, dann korrigiere das
+ // nicht erlaubt ist Header/Footer/TableHeadline ueber 2 Seiten
+ do { // middle check loop
+ const SwLayoutFrm* pSttLFrm = pStartFrm->GetUpper();
+ const sal_uInt16 cHdFtTblHd = FRM_HEADER | FRM_FOOTER | FRM_TAB;
+ while( pSttLFrm &&
+ ! (cHdFtTblHd & pSttLFrm->GetType() ))
+ pSttLFrm = pSttLFrm->GetUpper();
+ if( !pSttLFrm )
+ break;
+ const SwLayoutFrm* pEndLFrm = pEndFrm->GetUpper();
+ while( pEndLFrm &&
+ ! (cHdFtTblHd & pEndLFrm->GetType() ))
+ pEndLFrm = pEndLFrm->GetUpper();
+ if( !pEndLFrm )
+ break;
+
+ OSL_ENSURE( pEndLFrm->GetType() == pSttLFrm->GetType(),
+ "Selection ueber unterschiedliche Inhalte" );
+ switch( pSttLFrm->GetType() )
+ {
+ case FRM_HEADER:
+ case FRM_FOOTER:
+ // auf unterschiedlichen Seiten ??
+ // dann immer auf die Start-Seite
+ if( pEndLFrm->FindPageFrm() != pSttLFrm->FindPageFrm() )
+ {
+ // End- auf den Start-CntntFrame setzen
+ if( pStartPos == rCrsr.GetPoint() )
+ pEndFrm = pStartFrm;
+ else
+ pStartFrm = pEndFrm;
+ }
+ break;
+ case FRM_TAB:
+ // auf unterschiedlichen Seiten ??
+ // existiert
+ // dann teste auf Tabelle-Headline
+ {
+ const SwTabFrm* pTabFrm = (SwTabFrm*)pSttLFrm;
+ if( ( pTabFrm->GetFollow() ||
+ ((SwTabFrm*)pEndLFrm)->GetFollow() ) &&
+ pTabFrm->GetTable()->GetRowsToRepeat() > 0 &&
+ pTabFrm->GetLower() != ((SwTabFrm*)pEndLFrm)->GetLower() &&
+ ( lcl_IsInRepeatedHeadline( pStartFrm ) ||
+ lcl_IsInRepeatedHeadline( pEndFrm ) ) )
+ {
+ // End- auf den Start-CntntFrame setzen
+ if( pStartPos == rCrsr.GetPoint() )
+ pEndFrm = pStartFrm;
+ else
+ pStartFrm = pEndFrm;
+ }
+ }
+ break;
+ }
+ } while( sal_False );
+
+ SwCrsrMoveState aTmpState( MV_NONE );
+ aTmpState.b2Lines = sal_True;
+ aTmpState.bNoScroll = sal_True;
+ aTmpState.nCursorBidiLevel = pStartFrm->IsRightToLeft() ? 1 : 0;
+
+ //CntntRects zu Start- und EndFrms.
+ SwRect aStRect, aEndRect;
+ pStartFrm->GetCharRect( aStRect, *pStartPos, &aTmpState );
+ Sw2LinesPos *pSt2Pos = aTmpState.p2Lines;
+ aTmpState.p2Lines = NULL;
+ aTmpState.nCursorBidiLevel = pEndFrm->IsRightToLeft() ? 1 : 0;
+
+ pEndFrm->GetCharRect ( aEndRect, *pEndPos, &aTmpState );
+ Sw2LinesPos *pEnd2Pos = aTmpState.p2Lines;
+
+ SwRect aStFrm ( pStartFrm->UnionFrm( sal_True ) );
+ aStFrm.Intersection( pStartFrm->PaintArea() );
+ SwRect aEndFrm( pStartFrm == pEndFrm ? aStFrm :
+ pEndFrm->UnionFrm( sal_True ) );
+ if( pStartFrm != pEndFrm )
+ aEndFrm.Intersection( pEndFrm->PaintArea() );
+ SWRECTFN( pStartFrm )
+ const sal_Bool bR2L = pStartFrm->IsRightToLeft();
+ const sal_Bool bEndR2L = pEndFrm->IsRightToLeft();
+
+ // If there's no doubleline portion involved or start and end are both
+ // in the same doubleline portion, all works fine, but otherwise
+ // we need the following...
+ if( pSt2Pos != pEnd2Pos && ( !pSt2Pos || !pEnd2Pos ||
+ pSt2Pos->aPortion != pEnd2Pos->aPortion ) )
+ {
+ // If we have a start(end) position inside a doubleline portion
+ // the surrounded part of the doubleline portion is subtracted
+ // from the region and the aStRect(aEndRect) is set to the
+ // end(start) of the doubleline portion.
+ if( pSt2Pos )
+ {
+ SwRect aTmp( aStRect );
+
+ // BiDi-Portions are swimming against the current.
+ const sal_Bool bPorR2L = ( MT_BIDI == pSt2Pos->nMultiType ) ?
+ ! bR2L :
+ bR2L;
+
+ if( MT_BIDI == pSt2Pos->nMultiType &&
+ (pSt2Pos->aPortion2.*fnRect->fnGetWidth)() )
+ {
+ // nested bidi portion
+ long nRightAbs = (pSt2Pos->aPortion.*fnRect->fnGetRight)();
+ nRightAbs -= (pSt2Pos->aPortion2.*fnRect->fnGetLeft)();
+ long nLeftAbs = nRightAbs - (pSt2Pos->aPortion2.*fnRect->fnGetWidth)();
+
+ (aTmp.*fnRect->fnSetRight)( nRightAbs );
+
+ if ( ! pEnd2Pos || pEnd2Pos->aPortion != pSt2Pos->aPortion )
+ {
+ SwRect aTmp2( pSt2Pos->aPortion );
+ (aTmp2.*fnRect->fnSetRight)( nLeftAbs );
+ aTmp2.Intersection( aEndFrm );
+ Sub( aRegion, aTmp2 );
+ }
+ }
+ else
+ {
+ if( bPorR2L )
+ (aTmp.*fnRect->fnSetLeft)(
+ (pSt2Pos->aPortion.*fnRect->fnGetLeft)() );
+ else
+ (aTmp.*fnRect->fnSetRight)(
+ (pSt2Pos->aPortion.*fnRect->fnGetRight)() );
+ }
+
+ if( MT_ROT_90 == pSt2Pos->nMultiType ||
+ (pSt2Pos->aPortion.*fnRect->fnGetTop)() ==
+ (aTmp.*fnRect->fnGetTop)() )
+ {
+ (aTmp.*fnRect->fnSetTop)(
+ (pSt2Pos->aLine.*fnRect->fnGetTop)() );
+ }
+
+ aTmp.Intersection( aStFrm );
+ Sub( aRegion, aTmp );
+
+ SwTwips nTmp = (pSt2Pos->aLine.*fnRect->fnGetBottom)();
+ if( MT_ROT_90 != pSt2Pos->nMultiType &&
+ (aStRect.*fnRect->fnBottomDist)( nTmp ) > 0 )
+ {
+ (aTmp.*fnRect->fnSetTop)( (aTmp.*fnRect->fnGetBottom)() );
+ (aTmp.*fnRect->fnSetBottom)( nTmp );
+ if( (aStRect.*fnRect->fnBottomDist)(
+ (pSt2Pos->aPortion.*fnRect->fnGetBottom)() ) > 0 )
+ {
+ if( bPorR2L )
+ (aTmp.*fnRect->fnSetRight)(
+ (pSt2Pos->aPortion.*fnRect->fnGetRight)() );
+ else
+ (aTmp.*fnRect->fnSetLeft)(
+ (pSt2Pos->aPortion.*fnRect->fnGetLeft)() );
+ }
+ aTmp.Intersection( aStFrm );
+ Sub( aRegion, aTmp );
+ }
+
+ aStRect = pSt2Pos->aLine;
+ (aStRect.*fnRect->fnSetLeft)( bR2L ?
+ (pSt2Pos->aPortion.*fnRect->fnGetLeft)() :
+ (pSt2Pos->aPortion.*fnRect->fnGetRight)() );
+ (aStRect.*fnRect->fnSetWidth)( 1 );
+ }
+
+ if( pEnd2Pos )
+ {
+ SWRECTFNX( pEndFrm )
+ SwRect aTmp( aEndRect );
+
+ // BiDi-Portions are swimming against the current.
+ const sal_Bool bPorR2L = ( MT_BIDI == pEnd2Pos->nMultiType ) ?
+ ! bEndR2L :
+ bEndR2L;
+
+ if( MT_BIDI == pEnd2Pos->nMultiType &&
+ (pEnd2Pos->aPortion2.*fnRectX->fnGetWidth)() )
+ {
+ // nested bidi portion
+ long nRightAbs = (pEnd2Pos->aPortion.*fnRectX->fnGetRight)();
+ nRightAbs = nRightAbs - (pEnd2Pos->aPortion2.*fnRectX->fnGetLeft)();
+ long nLeftAbs = nRightAbs - (pEnd2Pos->aPortion2.*fnRectX->fnGetWidth)();
+
+ (aTmp.*fnRectX->fnSetLeft)( nLeftAbs );
+
+ if ( ! pSt2Pos || pSt2Pos->aPortion != pEnd2Pos->aPortion )
+ {
+ SwRect aTmp2( pEnd2Pos->aPortion );
+ (aTmp2.*fnRectX->fnSetLeft)( nRightAbs );
+ aTmp2.Intersection( aEndFrm );
+ Sub( aRegion, aTmp2 );
+ }
+ }
+ else
+ {
+ if ( bPorR2L )
+ (aTmp.*fnRectX->fnSetRight)(
+ (pEnd2Pos->aPortion.*fnRectX->fnGetRight)() );
+ else
+ (aTmp.*fnRectX->fnSetLeft)(
+ (pEnd2Pos->aPortion.*fnRectX->fnGetLeft)() );
+ }
+
+ if( MT_ROT_90 == pEnd2Pos->nMultiType ||
+ (pEnd2Pos->aPortion.*fnRectX->fnGetBottom)() ==
+ (aEndRect.*fnRectX->fnGetBottom)() )
+ {
+ (aTmp.*fnRectX->fnSetBottom)(
+ (pEnd2Pos->aLine.*fnRectX->fnGetBottom)() );
+ }
+
+ aTmp.Intersection( aEndFrm );
+ Sub( aRegion, aTmp );
+
+ // The next statement means neither ruby nor rotate(90):
+ if( !( MT_RUBY & pEnd2Pos->nMultiType ) )
+ {
+ SwTwips nTmp = (pEnd2Pos->aLine.*fnRectX->fnGetTop)();
+ if( (aEndRect.*fnRectX->fnGetTop)() != nTmp )
+ {
+ (aTmp.*fnRectX->fnSetBottom)(
+ (aTmp.*fnRectX->fnGetTop)() );
+ (aTmp.*fnRectX->fnSetTop)( nTmp );
+ if( (aEndRect.*fnRectX->fnGetTop)() !=
+ (pEnd2Pos->aPortion.*fnRectX->fnGetTop)() )
+ {
+ if( bPorR2L )
+ (aTmp.*fnRectX->fnSetLeft)(
+ (pEnd2Pos->aPortion.*fnRectX->fnGetLeft)() );
+ else
+ (aTmp.*fnRectX->fnSetRight)(
+ (pEnd2Pos->aPortion.*fnRectX->fnGetRight)() );
+ }
+ aTmp.Intersection( aEndFrm );
+ Sub( aRegion, aTmp );
+ }
+ }
+
+ aEndRect = pEnd2Pos->aLine;
+ (aEndRect.*fnRectX->fnSetLeft)( bEndR2L ?
+ (pEnd2Pos->aPortion.*fnRectX->fnGetRight)() :
+ (pEnd2Pos->aPortion.*fnRectX->fnGetLeft)() );
+ (aEndRect.*fnRectX->fnSetWidth)( 1 );
+ }
+ }
+ else if( pSt2Pos && pEnd2Pos &&
+ MT_BIDI == pSt2Pos->nMultiType &&
+ MT_BIDI == pEnd2Pos->nMultiType &&
+ pSt2Pos->aPortion == pEnd2Pos->aPortion &&
+ pSt2Pos->aPortion2 != pEnd2Pos->aPortion2 )
+ {
+ // This is the ugly special case, where the selection starts and
+ // ends in the same bidi portion but one start or end is inside a
+ // nested bidi portion.
+
+ if ( (pSt2Pos->aPortion2.*fnRect->fnGetWidth)() )
+ {
+ SwRect aTmp( aStRect );
+ long nRightAbs = (pSt2Pos->aPortion.*fnRect->fnGetRight)();
+ nRightAbs -= (pSt2Pos->aPortion2.*fnRect->fnGetLeft)();
+ long nLeftAbs = nRightAbs - (pSt2Pos->aPortion2.*fnRect->fnGetWidth)();
+
+ (aTmp.*fnRect->fnSetRight)( nRightAbs );
+ aTmp.Intersection( aStFrm );
+ Sub( aRegion, aTmp );
+
+ aStRect = pSt2Pos->aLine;
+ (aStRect.*fnRect->fnSetLeft)( bR2L ? nRightAbs : nLeftAbs );
+ (aStRect.*fnRect->fnSetWidth)( 1 );
+ }
+
+ SWRECTFNX( pEndFrm )
+ if ( (pEnd2Pos->aPortion2.*fnRectX->fnGetWidth)() )
+ {
+ SwRect aTmp( aEndRect );
+ long nRightAbs = (pEnd2Pos->aPortion.*fnRectX->fnGetRight)();
+ nRightAbs -= (pEnd2Pos->aPortion2.*fnRectX->fnGetLeft)();
+ long nLeftAbs = nRightAbs - (pEnd2Pos->aPortion2.*fnRectX->fnGetWidth)();
+
+ (aTmp.*fnRectX->fnSetLeft)( nLeftAbs );
+ aTmp.Intersection( aEndFrm );
+ Sub( aRegion, aTmp );
+
+ aEndRect = pEnd2Pos->aLine;
+ (aEndRect.*fnRectX->fnSetLeft)( bEndR2L ? nLeftAbs : nRightAbs );
+ (aEndRect.*fnRectX->fnSetWidth)( 1 );
+ }
+ }
+
+ // The charrect may be outside the paintarea (for cursortravelling)
+ // but the selection has to be restricted to the paintarea
+ if( aStRect.Left() < aStFrm.Left() )
+ aStRect.Left( aStFrm.Left() );
+ else if( aStRect.Left() > aStFrm.Right() )
+ aStRect.Left( aStFrm.Right() );
+ SwTwips nTmp = aStRect.Right();
+ if( nTmp < aStFrm.Left() )
+ aStRect.Right( aStFrm.Left() );
+ else if( nTmp > aStFrm.Right() )
+ aStRect.Right( aStFrm.Right() );
+ if( aEndRect.Left() < aEndFrm.Left() )
+ aEndRect.Left( aEndFrm.Left() );
+ else if( aEndRect.Left() > aEndFrm.Right() )
+ aEndRect.Left( aEndFrm.Right() );
+ nTmp = aEndRect.Right();
+ if( nTmp < aEndFrm.Left() )
+ aEndRect.Right( aEndFrm.Left() );
+ else if( nTmp > aEndFrm.Right() )
+ aEndRect.Right( aEndFrm.Right() );
+
+ if( pStartFrm == pEndFrm )
+ {
+ sal_Bool bSameRotatedOrBidi = pSt2Pos && pEnd2Pos &&
+ ( MT_BIDI & pSt2Pos->nMultiType ) &&
+ pSt2Pos->aPortion == pEnd2Pos->aPortion;
+ //case 1: (Same frame and same row)
+ if( bSameRotatedOrBidi ||
+ (aStRect.*fnRect->fnGetTop)() == (aEndRect.*fnRect->fnGetTop)() )
+ {
+ Point aTmpSt( aStRect.Pos() );
+ Point aTmpEnd( aEndRect.Right(), aEndRect.Bottom() );
+ if( bSameRotatedOrBidi || bR2L )
+ {
+ if( aTmpSt.Y() > aTmpEnd.Y() )
+ {
+ long nTmpY = aTmpEnd.Y();
+ aTmpEnd.Y() = aTmpSt.Y();
+ aTmpSt.Y() = nTmpY;
+ }
+ if( aTmpSt.X() > aTmpEnd.X() )
+ {
+ long nTmpX = aTmpEnd.X();
+ aTmpEnd.X() = aTmpSt.X();
+ aTmpSt.X() = nTmpX;
+ }
+ }
+
+ SwRect aTmp = SwRect( aTmpSt, aTmpEnd );
+ // Bug 34888: falls Inhalt selektiert ist, der keinen Platz
+ // einnimmt (z.B. PostIts,RefMarks, TOXMarks),
+ // dann mindestens die Breite des Crsr setzen.
+ if( 1 == (aTmp.*fnRect->fnGetWidth)() &&
+ pStartPos->nContent.GetIndex() !=
+ pEndPos->nContent.GetIndex() )
+ {
+ OutputDevice* pOut = pSh->GetOut();
+ long nCrsrWidth = pOut->GetSettings().GetStyleSettings().
+ GetCursorSize();
+ (aTmp.*fnRect->fnSetWidth)( pOut->PixelToLogic(
+ Size( nCrsrWidth, 0 ) ).Width() );
+ }
+ aTmp.Intersection( aStFrm );
+ Sub( aRegion, aTmp );
+ }
+ //case 2: (Same frame, but not the same line)
+ else
+ {
+ SwTwips lLeft, lRight;
+ if( pSt2Pos && pEnd2Pos && pSt2Pos->aPortion == pEnd2Pos->aPortion )
+ {
+ lLeft = (pSt2Pos->aPortion.*fnRect->fnGetLeft)();
+ lRight = (pSt2Pos->aPortion.*fnRect->fnGetRight)();
+ }
+ else
+ {
+ lLeft = (pStartFrm->Frm().*fnRect->fnGetLeft)() +
+ (pStartFrm->Prt().*fnRect->fnGetLeft)();
+ lRight = (pStartFrm->Frm().*fnRect->fnGetLeft)() +
+ (pStartFrm->Prt().*fnRect->fnGetRight)();
+ }
+ if( lLeft < (aStFrm.*fnRect->fnGetLeft)() )
+ lLeft = (aStFrm.*fnRect->fnGetLeft)();
+ if( lRight > (aStFrm.*fnRect->fnGetRight)() )
+ lRight = (aStFrm.*fnRect->fnGetRight)();
+ SwRect aSubRect( aStRect );
+ //First line
+ if( bR2L )
+ (aSubRect.*fnRect->fnSetLeft)( lLeft );
+ else
+ (aSubRect.*fnRect->fnSetRight)( lRight );
+ Sub( aRegion, aSubRect );
+
+ //If there's at least a twips between start- and endline,
+ //so the whole area between will be added.
+ SwTwips aTmpBottom = (aStRect.*fnRect->fnGetBottom)();
+ SwTwips aTmpTop = (aEndRect.*fnRect->fnGetTop)();
+ if( aTmpBottom != aTmpTop )
+ {
+ (aSubRect.*fnRect->fnSetLeft)( lLeft );
+ (aSubRect.*fnRect->fnSetRight)( lRight );
+ (aSubRect.*fnRect->fnSetTop)( aTmpBottom );
+ (aSubRect.*fnRect->fnSetBottom)( aTmpTop );
+ Sub( aRegion, aSubRect );
+ }
+ //and the last line
+ aSubRect = aEndRect;
+ if( bR2L )
+ (aSubRect.*fnRect->fnSetRight)( lRight );
+ else
+ (aSubRect.*fnRect->fnSetLeft)( lLeft );
+ Sub( aRegion, aSubRect );
+ }
+ }
+ //case 3: (Different frames, maybe with ohther frames between
+ else
+ {
+ //The startframe first...
+ SwRect aSubRect( aStRect );
+ if( bR2L )
+ (aSubRect.*fnRect->fnSetLeft)( (aStFrm.*fnRect->fnGetLeft)());
+ else
+ (aSubRect.*fnRect->fnSetRight)( (aStFrm.*fnRect->fnGetRight)());
+ Sub( aRegion, aSubRect );
+ SwTwips nTmpTwips = (aStRect.*fnRect->fnGetBottom)();
+ if( (aStFrm.*fnRect->fnGetBottom)() != nTmpTwips )
+ {
+ aSubRect = aStFrm;
+ (aSubRect.*fnRect->fnSetTop)( nTmpTwips );
+ Sub( aRegion, aSubRect );
+ }
+
+ //Now the frames between, if there are any
+ sal_Bool bBody = pStartFrm->IsInDocBody();
+ const SwTableBox* pCellBox = pStartFrm->GetUpper()->IsCellFrm() ?
+ ((SwCellFrm*)pStartFrm->GetUpper())->GetTabBox() : 0;
+ const SwCntntFrm *pCntnt = pStartFrm->GetNextCntntFrm();
+ SwRect aPrvRect;
+
+ // --> OD 2006-01-24 #123908# - introduce robust code:
+ // The stacktrace issue reveals that <pCntnt> could be NULL.
+ // One root cause found by AMA - see #130650#
+ OSL_ENSURE( pCntnt,
+ "<SwRootFrm::CalcFrmRects(..)> - no content frame. This is a serious defect -> please inform OD" );
+ while ( pCntnt && pCntnt != pEndFrm )
+ // <--
+ {
+ if ( pCntnt->IsInFly() )
+ {
+ const SwAnchoredObject* pObj = pCntnt->FindFlyFrm();
+ aSortObjs.Insert( *(const_cast<SwAnchoredObject*>(pObj)) );
+ }
+
+ // Consider only frames which have the same IsInDocBody value like pStartFrm
+ // If pStartFrm is inside a SwCellFrm, consider only frames which are inside the
+ // same cell frame (or its follow cell)
+ const SwTableBox* pTmpCellBox = pCntnt->GetUpper()->IsCellFrm() ?
+ ((SwCellFrm*)pCntnt->GetUpper())->GetTabBox() : 0;
+ if ( bBody == pCntnt->IsInDocBody() &&
+ ( !pCellBox || pCellBox == pTmpCellBox ) )
+ {
+ SwRect aCRect( pCntnt->UnionFrm( sal_True ) );
+ aCRect.Intersection( pCntnt->PaintArea() );
+ if( aCRect.IsOver( aRegion.GetOrigin() ))
+ {
+ SwRect aTmp( aPrvRect );
+ aTmp.Union( aCRect );
+ if ( (aPrvRect.Height() * aPrvRect.Width() +
+ aCRect.Height() * aCRect.Width()) ==
+ (aTmp.Height() * aTmp.Width()) )
+ {
+ aPrvRect.Union( aCRect );
+ }
+ else
+ {
+ if ( aPrvRect.HasArea() )
+ Sub( aRegion, aPrvRect );
+ aPrvRect = aCRect;
+ }
+ }
+ }
+ pCntnt = pCntnt->GetNextCntntFrm();
+ // --> OD 2006-01-24 #123908#
+ OSL_ENSURE( pCntnt,
+ "<SwRootFrm::CalcFrmRects(..)> - no content frame. This is a serious defect -> please inform OD" );
+ // <--
+ }
+ if ( aPrvRect.HasArea() )
+ Sub( aRegion, aPrvRect );
+
+ //At least the endframe...
+ bVert = pEndFrm->IsVertical();
+ bRev = pEndFrm->IsReverse();
+ //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin
+ fnRect = bVert ? ( bRev ? fnRectVL2R : ( pEndFrm->IsVertLR() ? fnRectVertL2R : fnRectVert ) ) :
+ ( bRev ? fnRectB2T : fnRectHori );
+ nTmpTwips = (aEndRect.*fnRect->fnGetTop)();
+ if( (aEndFrm.*fnRect->fnGetTop)() != nTmpTwips )
+ {
+ aSubRect = aEndFrm;
+ (aSubRect.*fnRect->fnSetBottom)( nTmpTwips );
+ Sub( aRegion, aSubRect );
+ }
+ aSubRect = aEndRect;
+ if( bEndR2L )
+ (aSubRect.*fnRect->fnSetRight)((aEndFrm.*fnRect->fnGetRight)());
+ else
+ (aSubRect.*fnRect->fnSetLeft)( (aEndFrm.*fnRect->fnGetLeft)() );
+ Sub( aRegion, aSubRect );
+ }
+
+// aRegion.Compress( sal_False );
+ aRegion.Invert();
+ delete pSt2Pos;
+ delete pEnd2Pos;
+ }
+
+ //Flys mit Durchlauf ausstanzen. Nicht ausgestanzt werden Flys:
+ //- die Lower des StartFrm/EndFrm sind (FlyInCnt und alle Flys die wiederum
+ // darin sitzen)
+ //- in der Z-Order ueber denjenigen Flys stehen in denen sich der StartFrm
+ // befindet.
+ const SwPageFrm *pPage = pStartFrm->FindPageFrm();
+ const SwPageFrm *pEndPage = pEndFrm->FindPageFrm();
+
+ while ( pPage )
+ {
+ if ( pPage->GetSortedObjs() )
+ {
+ const SwSortedObjs &rObjs = *pPage->GetSortedObjs();
+ for ( sal_uInt16 i = 0; i < rObjs.Count(); ++i )
+ {
+ SwAnchoredObject* pAnchoredObj = rObjs[i];
+ if ( !pAnchoredObj->ISA(SwFlyFrm) )
+ continue;
+ const SwFlyFrm* pFly = static_cast<const SwFlyFrm*>(pAnchoredObj);
+ const SwVirtFlyDrawObj* pObj = pFly->GetVirtDrawObj();
+ const SwFmtSurround &rSur = pFly->GetFmt()->GetSurround();
+ if ( !pFly->IsAnLower( pStartFrm ) &&
+ (rSur.GetSurround() != SURROUND_THROUGHT &&
+ !rSur.IsContour()) )
+ {
+ if ( aSortObjs.Contains( *pAnchoredObj ) )
+ continue;
+
+ sal_Bool bSub = sal_True;
+ const sal_uInt32 nPos = pObj->GetOrdNum();
+ for ( sal_uInt16 k = 0; bSub && k < aSortObjs.Count(); ++k )
+ {
+ OSL_ENSURE( aSortObjs[k]->ISA(SwFlyFrm),
+ "<SwRootFrm::CalcFrmRects(..)> - object in <aSortObjs> of unexcepted type" );
+ const SwFlyFrm* pTmp = static_cast<SwFlyFrm*>(aSortObjs[k]);
+ do
+ { if ( nPos < pTmp->GetVirtDrawObj()->GetOrdNumDirect() )
+ bSub = sal_False;
+ else
+ pTmp = pTmp->GetAnchorFrm()->FindFlyFrm();
+ } while ( bSub && pTmp );
+ }
+ if ( bSub )
+ Sub( aRegion, pFly->Frm() );
+ }
+ }
+ }
+ if ( pPage == pEndPage )
+ break;
+ else
+ pPage = (SwPageFrm*)pPage->GetNext();
+ }
+
+ //Weil's besser aussieht noch die DropCaps ausschliessen.
+ SwRect aDropRect;
+ if ( pStartFrm->IsTxtFrm() )
+ {
+ if ( ((SwTxtFrm*)pStartFrm)->GetDropRect( aDropRect ) )
+ Sub( aRegion, aDropRect );
+ }
+ if ( pEndFrm != pStartFrm && pEndFrm->IsTxtFrm() )
+ {
+ if ( ((SwTxtFrm*)pEndFrm)->GetDropRect( aDropRect ) )
+ Sub( aRegion, aDropRect );
+ }
+
+ rCrsr.Remove( 0, rCrsr.Count() );
+ rCrsr.Insert( &aRegion, 0 );
+}
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/layout/unusedf.cxx b/sw/source/core/layout/unusedf.cxx
new file mode 100644
index 000000000000..7c38aaa4430e
--- /dev/null
+++ b/sw/source/core/layout/unusedf.cxx
@@ -0,0 +1,92 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+#include "rootfrm.hxx"
+#include "cntfrm.hxx"
+#include "flyfrm.hxx"
+
+
+void SwFrm::Format( const SwBorderAttrs * )
+{
+ OSL_FAIL( "Format() der Basisklasse gerufen." );
+}
+
+void SwFrm::Paint(SwRect const&, SwPrintData const*const) const
+{
+ OSL_FAIL( "Paint() der Basisklasse gerufen." );
+}
+
+sal_Bool SwCntntFrm::WouldFit( SwTwips &, sal_Bool&, sal_Bool )
+{
+ OSL_FAIL( "WouldFit des CntntFrm gerufen." );
+ return sal_False;
+}
+
+bool SwFrm::FillSelection( SwSelectionList& , const SwRect& ) const
+{
+ OSL_FAIL( "Don't call this function at the base class!" );
+ return false;
+}
+
+sal_Bool SwFrm::GetCrsrOfst( SwPosition *, Point&, SwCrsrMoveState* ) const
+{
+ OSL_FAIL( "GetCrsrOfst der Basisklasse, hi!" );
+ return sal_False;
+}
+
+#if OSL_DEBUG_LEVEL > 1
+
+void SwRootFrm::Cut()
+{
+ OSL_FAIL( "Cut() des RootFrm gerufen." );
+}
+
+void SwRootFrm::Paste( SwFrm *, SwFrm * )
+{
+ OSL_FAIL( "Paste() des RootFrm gerufen." );
+}
+
+void SwFlyFrm::Paste( SwFrm *, SwFrm * )
+{
+ OSL_FAIL( "Paste() des FlyFrm gerufen." );
+}
+
+#endif
+
+sal_Bool SwFrm::GetCharRect( SwRect&, const SwPosition&,
+ SwCrsrMoveState* ) const
+{
+ OSL_FAIL( "GetCharRect() der Basis gerufen." );
+ return sal_False;
+}
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/layout/virtoutp.cxx b/sw/source/core/layout/virtoutp.cxx
new file mode 100644
index 000000000000..d769f3c4987a
--- /dev/null
+++ b/sw/source/core/layout/virtoutp.cxx
@@ -0,0 +1,258 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+
+#include <vcl/window.hxx>
+
+#include "hintids.hxx"
+#include "viewsh.hxx"
+#include "virtoutp.hxx"
+#include "viewopt.hxx"
+#include "rootfrm.hxx"
+// OD 12.11.2002 #96272# - include declaration for <SetMappingForVirtDev>
+#include "setmapvirtdev.hxx"
+
+#if OSL_DEBUG_LEVEL > 1
+
+/*************************************************************************
+ * class DbgRect
+ *************************************************************************/
+
+class DbgRect
+{
+ OutputDevice *pOut;
+public:
+ DbgRect( OutputDevice *pOut, const Rectangle &rRect,
+ const ColorData eColor = COL_LIGHTBLUE );
+};
+
+inline DbgRect::DbgRect( OutputDevice *pOutDev, const Rectangle &rRect,
+ const ColorData eColor )
+ :pOut( pOutDev )
+{
+ if( pOut )
+ {
+ pOut->Push( PUSH_FILLCOLOR|PUSH_LINECOLOR );
+ pOut->SetLineColor( eColor );
+ pOut->SetFillColor();
+ pOut->DrawRect( rRect );
+ pOut->Pop();
+ }
+}
+
+#endif
+
+/* class SwLayVout verwaltet das virtuelle Outputdevice
+ * Es gibt von dieser Klasse einen statischen Member am RootFrm,
+ * dieser wird in _FrmInit angelegt und in _FrmFinit zerstoert.
+ * */
+
+sal_Bool SwRootFrm::FlushVout()
+{
+ if( SwRootFrm::pVout->IsFlushable() )
+ {
+ SwRootFrm::pVout->_Flush();
+ return sal_True;
+ }
+ return sal_False;
+}
+
+sal_Bool SwRootFrm::HasSameRect( const SwRect& rRect )
+{
+ if( SwRootFrm::pVout->IsFlushable() )
+ return ( rRect == SwRootFrm::pVout->GetOrgRect() );
+ return sal_False;
+}
+
+/** method to set mapping/pixel offset for virtual output device
+
+ OD 12.11.2002 #96272# - method implements two solutions for the mapping of
+ the virtual output device:
+ The old solution set the origin of the mapping mode, which will be used in
+ the virtual output device. This causes several paint errors, because of the
+ different roundings in the virtual output device and the original output device.
+ The new solution avoids the rounding differences between virtual and original
+ output device by setting a pixel offset at the virtual output device.
+ A define controls, which solution is used, in order to switch in escalation
+ back to old solution.
+
+ @author OD
+
+ @param _pOrgOutDev
+ input parameter - constant instance of the original output device, for which
+ the virtual output device is created.
+
+ @param _pVirDev
+ input/output parameter - instance of the virtual output device.
+
+ @param _pMapMode
+ input/output parameter - instance of the mapping mode, which will be set
+ at the virtual output device.
+
+ @param _rNewOrigin
+ input parameter - constant instance of the origin, which will be used in
+ the virtual output device
+*/
+// define to control, if old or new solution for setting the mapping for
+// an virtual output device is used.
+void SetMappingForVirtDev( const Point& _rNewOrigin,
+ MapMode* ,
+ const OutputDevice* _pOrgOutDev,
+ VirtualDevice* _pVirDev )
+{
+ // new solution: set pixel offset at virtual output device
+ Point aPixelOffset = _pOrgOutDev->LogicToPixel( _rNewOrigin );
+ _pVirDev->SetPixelOffset( Size( -aPixelOffset.X(), -aPixelOffset.Y() ) );
+}
+
+
+/*************************************************************************
+ * SwVOut::DoesFit()
+ *************************************************************************/
+
+// rSize muss in Pixel-Koordinaten vorliegen!
+sal_Bool SwLayVout::DoesFit( const Size &rNew )
+{
+ if( rNew.Height() > VIRTUALHEIGHT )
+ return sal_False;
+ if( rNew.Width() <= 0 || rNew.Height() <= 0 )
+ return sal_False;
+ if( rNew.Width() <= aSize.Width() )
+ return sal_True;
+ if( !pVirDev )
+ {
+ pVirDev = new VirtualDevice();
+ pVirDev->SetLineColor();
+ if( pOut )
+ {
+ if( pVirDev->GetFillColor() != pOut->GetFillColor() )
+ pVirDev->SetFillColor( pOut->GetFillColor() );
+ }
+ }
+
+ if( rNew.Width() > aSize.Width() )
+ {
+ aSize.Width() = rNew.Width();
+ if( !pVirDev->SetOutputSizePixel( aSize ) )
+ {
+ delete pVirDev;
+ pVirDev = NULL;
+ aSize.Width() = 0;
+ return sal_False;
+ }
+ }
+ return sal_True;
+}
+
+/*************************************************************************
+ * SwLayVout::Enter
+ *************************************************************************/
+/// OD 27.09.2002 #103636# - change 2nd parameter <rRect> - no longer <const>
+/// in order to return value of class member variable <aRect>, if virtual
+/// output is used.
+/// <aRect> contains the rectangle that represents the area the virtual
+/// output device is used for and that is flushed at the end.
+void SwLayVout::Enter( ViewShell *pShell, SwRect &rRect, sal_Bool bOn )
+{
+ Flush();
+
+#if OSL_DEBUG_LEVEL > 1
+ if( pShell->GetViewOptions()->IsTest3() )
+ {
+ ++nCount;
+ return;
+ }
+#endif
+
+ bOn = bOn && !nCount && rRect.HasArea() && pShell->GetWin();
+ ++nCount;
+ if( bOn )
+ {
+ pSh = pShell;
+ pOut = NULL;
+ OutputDevice *pO = pSh->GetOut();
+// Auf dem Drucker oder einem virt. Outputdevice wird nicht getrickst...
+ if( OUTDEV_WINDOW != pO->GetOutDevType() )
+ return;
+
+ pOut = pO;
+ Size aPixSz( pOut->PixelToLogic( Size( 1,1 )) );
+ SwRect aTmp( rRect );
+ aTmp.SSize().Width() += aPixSz.Width()/2 + 1;
+ aTmp.SSize().Height()+= aPixSz.Height()/2 + 1;
+ Rectangle aTmpRect( pO->LogicToPixel( aTmp.SVRect() ) );
+
+ OSL_ENSURE( !pSh->GetWin()->IsReallyVisible() ||
+ aTmpRect.GetWidth() <= pSh->GetWin()->GetOutputSizePixel().Width() + 2,
+ "Paintwidth bigger than visarea?" );
+ // Passt das Rechteck in unseren Buffer ?
+ if( !DoesFit( aTmpRect.GetSize() ) )
+ {
+ pOut = NULL;
+ return;
+ }
+
+ aRect = SwRect( pO->PixelToLogic( aTmpRect ) );
+
+ SetOutDev( pSh, pVirDev );
+
+ if( pVirDev->GetFillColor() != pOut->GetFillColor() )
+ pVirDev->SetFillColor( pOut->GetFillColor() );
+
+ MapMode aMapMode( pOut->GetMapMode() );
+ // OD 12.11.2002 #96272# - use method to set mapping
+ //aMapMode.SetOrigin( Point(0,0) - aRect.Pos() );
+ ::SetMappingForVirtDev( aRect.Pos(), &aMapMode, pOut, pVirDev );
+
+ if( aMapMode != pVirDev->GetMapMode() )
+ pVirDev->SetMapMode( aMapMode );
+
+ /// OD 27.09.2002 #103636# - set value of parameter <rRect>
+ rRect = aRect;
+ }
+}
+
+/*************************************************************************
+ * SwLayVout::Flush()
+ *************************************************************************/
+
+void SwLayVout::_Flush()
+{
+ OSL_ENSURE( pVirDev, "SwLayVout::DrawOut: nothing left Toulouse" );
+ Rectangle aTmp( aRect.SVRect() );
+ pOut->DrawOutDev( aRect.Pos(), aRect.SSize(),
+ aRect.Pos(), aRect.SSize(), *pVirDev );
+ SetOutDev( pSh, pOut );
+ pOut = NULL;
+}
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/layout/virtoutp.hxx b/sw/source/core/layout/virtoutp.hxx
new file mode 100644
index 000000000000..f3f27a184150
--- /dev/null
+++ b/sw/source/core/layout/virtoutp.hxx
@@ -0,0 +1,77 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+#ifndef _VIRTOUTP_HXX
+#define _VIRTOUTP_HXX
+
+#include <vcl/virdev.hxx>
+
+#include "swtypes.hxx" // UCHAR
+#include "swrect.hxx" // SwRect
+
+class ViewShell;
+#define VIRTUALHEIGHT 64
+
+/*************************************************************************
+ * class SwTxtVout
+ *************************************************************************/
+
+class SwLayVout
+{
+ friend void _FrmFinit(); //loescht das Vout
+private:
+ ViewShell* pSh;
+ OutputDevice* pOut;
+ VirtualDevice* pVirDev;
+ SwRect aRect;
+ SwRect aOrgRect;
+ Size aSize;
+ sal_uInt16 nCount;
+
+ sal_Bool DoesFit( const Size &rOut );
+
+public:
+ SwLayVout() : pSh(0), pOut(0), pVirDev(0), aSize(0, VIRTUALHEIGHT), nCount(0) {}
+ ~SwLayVout() { delete pVirDev; }
+
+ /// OD 27.09.2002 #103636# - change 2nd parameter <rRect> - no longer <const>
+ void Enter( ViewShell *pShell, SwRect &rRect, sal_Bool bOn );
+ void Leave() { --nCount; Flush(); }
+
+ void SetOrgRect( SwRect &rRect ) { aOrgRect = rRect; }
+ const SwRect& GetOrgRect() const { return aOrgRect; }
+
+ sal_Bool IsFlushable() { return 0 != pOut; }
+ void _Flush();
+ void Flush() { if( pOut ) _Flush(); }
+};
+
+
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/layout/wsfrm.cxx b/sw/source/core/layout/wsfrm.cxx
new file mode 100644
index 000000000000..0d9f04e62d9c
--- /dev/null
+++ b/sw/source/core/layout/wsfrm.cxx
@@ -0,0 +1,3967 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+#include <hintids.hxx>
+#include <hints.hxx>
+#include <tools/pstm.hxx>
+#include <vcl/outdev.hxx>
+#include <svl/itemiter.hxx>
+#include <editeng/brshitem.hxx>
+#include <editeng/keepitem.hxx>
+#include <editeng/brkitem.hxx>
+#include <fmtornt.hxx>
+#include <pagefrm.hxx>
+#include <section.hxx>
+#include <rootfrm.hxx>
+#include <cntfrm.hxx>
+#include <dcontact.hxx>
+#include <anchoreddrawobject.hxx>
+#include <fmtanchr.hxx>
+#include <viewsh.hxx>
+#include <viewimp.hxx>
+#include "viewopt.hxx"
+#include <doc.hxx>
+#include <fesh.hxx>
+#include <docsh.hxx>
+#include <flyfrm.hxx>
+#include <frmtool.hxx>
+#include <ftninfo.hxx>
+#include <dflyobj.hxx>
+#include <fmtclbl.hxx>
+#include <fmtfordr.hxx>
+#include <fmtfsize.hxx>
+#include <fmtpdsc.hxx>
+#include <txtftn.hxx>
+#include <fmtftn.hxx>
+#include <fmtsrnd.hxx>
+#include <ftnfrm.hxx>
+#include <tabfrm.hxx>
+#include <htmltbl.hxx>
+#include <flyfrms.hxx>
+#include <sectfrm.hxx>
+#include <fmtclds.hxx>
+#include <txtfrm.hxx>
+#include <ndtxt.hxx>
+#include <bodyfrm.hxx>
+#include <cellfrm.hxx>
+#include <dbg_lay.hxx>
+#include <editeng/frmdiritem.hxx>
+// OD 2004-05-24 #i28701#
+#include <sortedobjs.hxx>
+
+
+using namespace ::com::sun::star;
+
+
+/*************************************************************************
+|*
+|* SwFrm::SwFrm()
+|*
+|*************************************************************************/
+
+SwFrm::SwFrm( SwModify *pMod, SwFrm* pSib ) :
+ SwClient( pMod ),
+ // --> OD 2006-05-10 #i65250#
+ mnFrmId( SwFrm::mnLastFrmId++ ),
+ // <--
+ mpRoot( pSib ? pSib->getRootFrm() : 0 ),
+ pUpper( 0 ),
+ pNext( 0 ),
+ pPrev( 0 ),
+ pDrawObjs( 0 )
+ , bInfBody( sal_False )
+ , bInfTab ( sal_False )
+ , bInfFly ( sal_False )
+ , bInfFtn ( sal_False )
+ , bInfSct ( sal_False )
+{
+#if OSL_DEBUG_LEVEL > 1
+ bFlag01 = bFlag02 = bFlag03 = bFlag04 = bFlag05 = 0;
+#endif
+
+ OSL_ENSURE( pMod, "Kein Frameformat uebergeben." );
+ bInvalidR2L = bInvalidVert = 1;
+ //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin
+ bDerivedR2L = bDerivedVert = bRightToLeft = bVertical = bReverse = bVertLR = 0;
+
+ bValidPos = bValidPrtArea = bValidSize = bValidLineNum = bRetouche =
+ bFixSize = bColLocked = sal_False;
+ bCompletePaint = bInfInvalid = sal_True;
+}
+
+const IDocumentDrawModelAccess* SwFrm::getIDocumentDrawModelAccess()
+{
+ return GetUpper()->GetFmt()->getIDocumentDrawModelAccess();
+}
+
+bool SwFrm::KnowsFormat( const SwFmt& rFmt ) const
+{
+ return GetRegisteredIn() == &rFmt;
+}
+
+void SwFrm::RegisterToFormat( SwFmt& rFmt )
+{
+ rFmt.Add( this );
+}
+
+void SwFrm::CheckDir( sal_uInt16 nDir, sal_Bool bVert, sal_Bool bOnlyBiDi, sal_Bool bBrowse )
+{
+ if( FRMDIR_ENVIRONMENT == nDir || ( bVert && bOnlyBiDi ) )
+ {
+ bDerivedVert = 1;
+ if( FRMDIR_ENVIRONMENT == nDir )
+ bDerivedR2L = 1;
+ SetDirFlags( bVert );
+ }
+ else if( bVert )
+ {
+ bInvalidVert = 0;
+ if( FRMDIR_HORI_LEFT_TOP == nDir || FRMDIR_HORI_RIGHT_TOP == nDir
+ || bBrowse )
+ //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin
+ {
+ bVertical = 0;
+ bVertLR = 0;
+ }
+ else
+ {
+ bVertical = 1;
+ if(FRMDIR_VERT_TOP_RIGHT == nDir)
+ bVertLR = 0;
+ else if(FRMDIR_VERT_TOP_LEFT==nDir)
+ bVertLR = 1;
+ }
+ }
+ else
+ {
+ bInvalidR2L = 0;
+ if( FRMDIR_HORI_RIGHT_TOP == nDir )
+ bRightToLeft = 1;
+ else
+ bRightToLeft = 0;
+ }
+}
+
+void SwFrm::CheckDirection( sal_Bool bVert )
+{
+ if( bVert )
+ {
+ if( !IsHeaderFrm() && !IsFooterFrm() )
+ {
+ bDerivedVert = 1;
+ SetDirFlags( bVert );
+ }
+ }
+ else
+ {
+ bDerivedR2L = 1;
+ SetDirFlags( bVert );
+ }
+}
+
+void SwSectionFrm::CheckDirection( sal_Bool bVert )
+{
+ const SwFrmFmt* pFmt = GetFmt();
+ if( pFmt )
+ {
+ const ViewShell *pSh = getRootFrm()->GetCurrShell();
+ const sal_Bool bBrowseMode = pSh && pSh->GetViewOptions()->getBrowseMode();
+ CheckDir(((SvxFrameDirectionItem&)pFmt->GetFmtAttr(RES_FRAMEDIR)).GetValue(),
+ bVert, sal_True, bBrowseMode );
+ }
+ else
+ SwFrm::CheckDirection( bVert );
+}
+
+void SwFlyFrm::CheckDirection( sal_Bool bVert )
+{
+ const SwFrmFmt* pFmt = GetFmt();
+ if( pFmt )
+ {
+ const ViewShell *pSh = getRootFrm()->GetCurrShell();
+ const sal_Bool bBrowseMode = pSh && pSh->GetViewOptions()->getBrowseMode();
+ CheckDir(((SvxFrameDirectionItem&)pFmt->GetFmtAttr(RES_FRAMEDIR)).GetValue(),
+ bVert, sal_False, bBrowseMode );
+ }
+ else
+ SwFrm::CheckDirection( bVert );
+}
+
+void SwTabFrm::CheckDirection( sal_Bool bVert )
+{
+ const SwFrmFmt* pFmt = GetFmt();
+ if( pFmt )
+ {
+ const ViewShell *pSh = getRootFrm()->GetCurrShell();
+ const sal_Bool bBrowseMode = pSh && pSh->GetViewOptions()->getBrowseMode();
+ CheckDir(((SvxFrameDirectionItem&)pFmt->GetFmtAttr(RES_FRAMEDIR)).GetValue(),
+ bVert, sal_True, bBrowseMode );
+ }
+ else
+ SwFrm::CheckDirection( bVert );
+}
+
+void SwCellFrm::CheckDirection( sal_Bool bVert )
+{
+ const SwFrmFmt* pFmt = GetFmt();
+ const SfxPoolItem* pItem;
+ // --> FME 2006-03-30 #b6402837# Check if the item is set, before actually
+ // using it. Otherwise the dynamic pool default is used, which may be set
+ // to LTR in case of OOo 1.0 documents.
+ // <--
+ if( pFmt && SFX_ITEM_SET == pFmt->GetItemState( RES_FRAMEDIR, sal_True, &pItem ) )
+ {
+ const SvxFrameDirectionItem* pFrmDirItem = static_cast<const SvxFrameDirectionItem*>(pItem);
+ const ViewShell *pSh = getRootFrm()->GetCurrShell();
+ const sal_Bool bBrowseMode = pSh && pSh->GetViewOptions()->getBrowseMode();
+ CheckDir( pFrmDirItem->GetValue(), bVert, sal_False, bBrowseMode );
+ }
+ else
+ SwFrm::CheckDirection( bVert );
+}
+
+void SwTxtFrm::CheckDirection( sal_Bool bVert )
+{
+ const ViewShell *pSh = getRootFrm()->GetCurrShell();
+ const sal_Bool bBrowseMode = pSh && pSh->GetViewOptions()->getBrowseMode();
+ CheckDir( GetTxtNode()->GetSwAttrSet().GetFrmDir().GetValue(), bVert,
+ sal_True, bBrowseMode );
+}
+
+/*************************************************************************/
+void SwFrm::Modify( const SfxPoolItem* pOld, const SfxPoolItem * pNew )
+{
+ sal_uInt8 nInvFlags = 0;
+
+ if( pNew && RES_ATTRSET_CHG == pNew->Which() )
+ {
+ SfxItemIter aNIter( *((SwAttrSetChg*)pNew)->GetChgSet() );
+ SfxItemIter aOIter( *((SwAttrSetChg*)pOld)->GetChgSet() );
+ while( sal_True )
+ {
+ _UpdateAttrFrm( (SfxPoolItem*)aOIter.GetCurItem(),
+ (SfxPoolItem*)aNIter.GetCurItem(), nInvFlags );
+ if( aNIter.IsAtEnd() )
+ break;
+ aNIter.NextItem();
+ aOIter.NextItem();
+ }
+ }
+ else
+ _UpdateAttrFrm( pOld, pNew, nInvFlags );
+
+ if ( nInvFlags != 0 )
+ {
+ SwPageFrm *pPage = FindPageFrm();
+ InvalidatePage( pPage );
+ if ( nInvFlags & 0x01 )
+ {
+ _InvalidatePrt();
+ if( !GetPrev() && IsTabFrm() && IsInSct() )
+ FindSctFrm()->_InvalidatePrt();
+ }
+ if ( nInvFlags & 0x02 )
+ _InvalidateSize();
+ if ( nInvFlags & 0x04 )
+ _InvalidatePos();
+ if ( nInvFlags & 0x08 )
+ SetCompletePaint();
+ SwFrm *pNxt;
+ if ( nInvFlags & 0x30 && 0 != (pNxt = GetNext()) )
+ {
+ pNxt->InvalidatePage( pPage );
+ if ( nInvFlags & 0x10 )
+ pNxt->_InvalidatePos();
+ if ( nInvFlags & 0x20 )
+ pNxt->SetCompletePaint();
+ }
+ }
+}
+
+void SwFrm::_UpdateAttrFrm( const SfxPoolItem *pOld, const SfxPoolItem *pNew,
+ sal_uInt8 &rInvFlags )
+{
+ sal_uInt16 nWhich = pOld ? pOld->Which() : pNew ? pNew->Which() : 0;
+ switch( nWhich )
+ {
+ case RES_BOX:
+ case RES_SHADOW:
+ Prepare( PREP_FIXSIZE_CHG );
+ // hier kein break !
+ case RES_LR_SPACE:
+ case RES_UL_SPACE:
+ rInvFlags |= 0x0B;
+ break;
+
+ case RES_HEADER_FOOTER_EAT_SPACING:
+ rInvFlags |= 0x03;
+ break;
+
+ case RES_BACKGROUND:
+ rInvFlags |= 0x28;
+ break;
+
+ case RES_KEEP:
+ rInvFlags |= 0x04;
+ break;
+
+ case RES_FRM_SIZE:
+ ReinitializeFrmSizeAttrFlags();
+ rInvFlags |= 0x13;
+ break;
+
+ case RES_FMT_CHG:
+ rInvFlags |= 0x0F;
+ break;
+
+ case RES_ROW_SPLIT:
+ {
+ if ( IsRowFrm() )
+ {
+ sal_Bool bInFollowFlowRow = 0 != IsInFollowFlowRow();
+ if ( bInFollowFlowRow || 0 != IsInSplitTableRow() )
+ {
+ SwTabFrm* pTab = FindTabFrm();
+ if ( bInFollowFlowRow )
+ pTab = pTab->FindMaster();
+ pTab->SetRemoveFollowFlowLinePending( sal_True );
+ }
+ }
+ break;
+ }
+ case RES_COL:
+ OSL_FAIL( "Spalten fuer neuen FrmTyp?" );
+ break;
+
+ default:
+ /* do Nothing */;
+ }
+}
+
+/*************************************************************************
+|*
+|* SwFrm::Prepare()
+|*
+|*************************************************************************/
+void SwFrm::Prepare( const PrepareHint, const void *, sal_Bool )
+{
+ /* Do nothing */
+}
+
+/*************************************************************************
+|*
+|* SwFrm::InvalidatePage()
+|* Beschreibung: Invalidiert die Seite, in der der Frm gerade steht.
+|* Je nachdem ob es ein Layout, Cntnt oder FlyFrm ist wird die Seite
+|* entsprechend Invalidiert.
+|*
+|*************************************************************************/
+void SwFrm::InvalidatePage( const SwPageFrm *pPage ) const
+{
+ if ( !pPage )
+ {
+ pPage = FindPageFrm();
+ // --> OD 2004-07-02 #i28701# - for at-character and as-character
+ // anchored Writer fly frames additionally invalidate also page frame
+ // its 'anchor character' is on.
+ if ( pPage && pPage->GetUpper() && IsFlyFrm() )
+ {
+ const SwFlyFrm* pFlyFrm = static_cast<const SwFlyFrm*>(this);
+ if ( pFlyFrm->IsAutoPos() || pFlyFrm->IsFlyInCntFrm() )
+ {
+ // --> OD 2004-09-23 #i33751#, #i34060# - method <GetPageFrmOfAnchor()>
+ // is replaced by method <FindPageFrmOfAnchor()>. It's return value
+ // have to be checked.
+ SwPageFrm* pPageFrmOfAnchor =
+ const_cast<SwFlyFrm*>(pFlyFrm)->FindPageFrmOfAnchor();
+ if ( pPageFrmOfAnchor && pPageFrmOfAnchor != pPage )
+ // <--
+ {
+ InvalidatePage( pPageFrmOfAnchor );
+ }
+ }
+ }
+ // <--
+ }
+
+ if ( pPage && pPage->GetUpper() )
+ {
+ if ( pPage->GetFmt()->GetDoc()->IsInDtor() )
+ return;
+
+ SwRootFrm *pRoot = (SwRootFrm*)pPage->GetUpper();
+ const SwFlyFrm *pFly = FindFlyFrm();
+ if ( IsCntntFrm() )
+ {
+ if ( pRoot->IsTurboAllowed() )
+ {
+ // JP 21.09.95: wenn sich der ContentFrame 2 mal eintragen
+ // will, kann es doch eine TurboAction bleiben.
+ // ODER????
+ if ( !pRoot->GetTurbo() || this == pRoot->GetTurbo() )
+ pRoot->SetTurbo( (const SwCntntFrm*)this );
+ else
+ {
+ pRoot->DisallowTurbo();
+ //Die Seite des Turbo koennte eine andere als die meinige
+ //sein, deshalb muss sie invalidiert werden.
+ const SwFrm *pTmp = pRoot->GetTurbo();
+ pRoot->ResetTurbo();
+ pTmp->InvalidatePage();
+ }
+ }
+ if ( !pRoot->GetTurbo() )
+ {
+ if ( pFly )
+ { if( !pFly->IsLocked() )
+ {
+ if ( pFly->IsFlyInCntFrm() )
+ { pPage->InvalidateFlyInCnt();
+ ((SwFlyInCntFrm*)pFly)->InvalidateCntnt();
+ pFly->GetAnchorFrm()->InvalidatePage();
+ }
+ else
+ pPage->InvalidateFlyCntnt();
+ }
+ }
+ else
+ pPage->InvalidateCntnt();
+ }
+ }
+ else
+ {
+ pRoot->DisallowTurbo();
+ if ( pFly )
+ {
+ if ( !pFly->IsLocked() )
+ {
+ if ( pFly->IsFlyInCntFrm() )
+ {
+ pPage->InvalidateFlyInCnt();
+ ((SwFlyInCntFrm*)pFly)->InvalidateLayout();
+ pFly->GetAnchorFrm()->InvalidatePage();
+ }
+ else
+ pPage->InvalidateFlyLayout();
+ }
+ }
+ else
+ pPage->InvalidateLayout();
+
+ if ( pRoot->GetTurbo() )
+ { const SwFrm *pTmp = pRoot->GetTurbo();
+ pRoot->ResetTurbo();
+ pTmp->InvalidatePage();
+ }
+ }
+ pRoot->SetIdleFlags();
+
+ const SwTxtFrm *pTxtFrm = dynamic_cast< const SwTxtFrm * >(this);
+ if (pTxtFrm)
+ {
+ const SwTxtNode *pTxtNode = pTxtFrm->GetTxtNode();
+ if (pTxtNode && pTxtNode->IsGrammarCheckDirty())
+ pRoot->SetNeedGrammarCheck( sal_True );
+ }
+ }
+}
+
+/*************************************************************************
+|*
+|* SwFrm::ChgSize()
+|*
+|*************************************************************************/
+Size SwFrm::ChgSize( const Size& aNewSize )
+{
+ bFixSize = sal_True;
+ const Size aOldSize( Frm().SSize() );
+ if ( aNewSize == aOldSize )
+ return aOldSize;
+
+ if ( GetUpper() )
+ {
+ SWRECTFN2( this )
+ SwRect aNew( Point(0,0), aNewSize );
+ (aFrm.*fnRect->fnSetWidth)( (aNew.*fnRect->fnGetWidth)() );
+ long nNew = (aNew.*fnRect->fnGetHeight)();
+ long nDiff = nNew - (aFrm.*fnRect->fnGetHeight)();
+ if( nDiff )
+ {
+ if ( GetUpper()->IsFtnBossFrm() && HasFixSize() &&
+ NA_GROW_SHRINK !=
+ ((SwFtnBossFrm*)GetUpper())->NeighbourhoodAdjustment( this ) )
+ {
+ (aFrm.*fnRect->fnSetHeight)( nNew );
+ SwTwips nReal = ((SwLayoutFrm*)this)->AdjustNeighbourhood(nDiff);
+ if ( nReal != nDiff )
+ (aFrm.*fnRect->fnSetHeight)( nNew - nDiff + nReal );
+ }
+ else
+ {
+ // OD 24.10.2002 #97265# - grow/shrink not for neighbour frames
+ // NOTE: neighbour frames are cell and column frames.
+ if ( !bNeighb )
+ {
+ if ( nDiff > 0 )
+ Grow( nDiff );
+ else
+ Shrink( -nDiff );
+
+ if ( GetUpper() && (aFrm.*fnRect->fnGetHeight)() != nNew )
+ GetUpper()->_InvalidateSize();
+ }
+
+ // Auch wenn das Grow/Shrink noch nicht die gewuenschte Breite eingestellt hat,
+ // wie z.B. beim Aufruf durch ChgColumns, um die Spaltenbreiten einzustellen,
+ // wird die Breite jetzt gesetzt.
+ (aFrm.*fnRect->fnSetHeight)( nNew );
+ }
+ }
+ }
+ else
+ aFrm.SSize( aNewSize );
+
+ if ( Frm().SSize() != aOldSize )
+ {
+ SwPageFrm *pPage = FindPageFrm();
+ if ( GetNext() )
+ {
+ GetNext()->_InvalidatePos();
+ GetNext()->InvalidatePage( pPage );
+ }
+ if( IsLayoutFrm() )
+ {
+ if( IsRightToLeft() )
+ _InvalidatePos();
+ if( ((SwLayoutFrm*)this)->Lower() )
+ ((SwLayoutFrm*)this)->Lower()->_InvalidateSize();
+ }
+ _InvalidatePrt();
+ _InvalidateSize();
+ InvalidatePage( pPage );
+ }
+
+ return aFrm.SSize();
+}
+
+/*************************************************************************
+|*
+|* SwFrm::InsertBefore()
+|*
+|* Beschreibung SwFrm wird in eine bestehende Struktur eingefuegt
+|* Eingefuegt wird unterhalb des Parent und entweder
+|* vor pBehind oder am Ende der Kette wenn pBehind
+|* leer ist.
+|*
+|*************************************************************************/
+void SwFrm::InsertBefore( SwLayoutFrm* pParent, SwFrm* pBehind )
+{
+ OSL_ENSURE( pParent, "Kein Parent fuer Insert." );
+ OSL_ENSURE( (!pBehind || (pBehind && pParent == pBehind->GetUpper())),
+ "Framebaum inkonsistent." );
+
+ pUpper = pParent;
+ pNext = pBehind;
+ if( pBehind )
+ { //Einfuegen vor pBehind.
+ if( 0 != (pPrev = pBehind->pPrev) )
+ pPrev->pNext = this;
+ else
+ pUpper->pLower = this;
+ pBehind->pPrev = this;
+ }
+ else
+ { //Einfuegen am Ende, oder als ersten Node im Unterbaum
+ pPrev = pUpper->Lower();
+ if ( pPrev )
+ {
+ while( pPrev->pNext )
+ pPrev = pPrev->pNext;
+ pPrev->pNext = this;
+ }
+ else
+ pUpper->pLower = this;
+ }
+}
+
+/*************************************************************************
+|*
+|* SwFrm::InsertBehind()
+|*
+|* Beschreibung SwFrm wird in eine bestehende Struktur eingefuegt
+|* Eingefuegt wird unterhalb des Parent und entweder
+|* hinter pBefore oder am Anfang der Kette wenn pBefore
+|* leer ist.
+|*
+|*************************************************************************/
+void SwFrm::InsertBehind( SwLayoutFrm *pParent, SwFrm *pBefore )
+{
+ OSL_ENSURE( pParent, "Kein Parent fuer Insert." );
+ OSL_ENSURE( (!pBefore || (pBefore && pParent == pBefore->GetUpper())),
+ "Framebaum inkonsistent." );
+
+ pUpper = pParent;
+ pPrev = pBefore;
+ if ( pBefore )
+ {
+ //Einfuegen hinter pBefore
+ if ( 0 != (pNext = pBefore->pNext) )
+ pNext->pPrev = this;
+ pBefore->pNext = this;
+ }
+ else
+ {
+ //Einfuegen am Anfang der Kette
+ pNext = pParent->Lower();
+ if ( pParent->Lower() )
+ pParent->Lower()->pPrev = this;
+ pParent->pLower = this;
+ }
+}
+
+/*************************************************************************
+|*
+|* SwFrm::InsertGroup()
+|*
+|* Beschreibung Eine Kette von SwFrms wird in eine bestehende Struktur
+|* eingefuegt
+|*
+|* Bisher wird dies genutzt, um einen SectionFrame, der ggf. schon Geschwister
+|* mit sich bringt, in eine bestehende Struktur einzufuegen.
+|*
+|* Wenn man den dritten Parameter als NULL uebergibt, entspricht
+|* diese Methode dem SwFrm::InsertBefore(..), nur eben mit Geschwistern.
+|*
+|* Wenn man einen dritten Parameter uebergibt, passiert folgendes:
+|* this wird pNext von pParent,
+|* pSct wird pNext vom Letzten der this-Kette,
+|* pBehind wird vom pParent an den pSct umgehaengt.
+|* Dies dient dazu: ein SectionFrm (this) wird nicht als
+|* Kind an einen anderen SectionFrm (pParent) gehaengt, sondern pParent
+|* wird in zwei Geschwister aufgespalten (pParent+pSct) und this dazwischen
+|* eingebaut.
+|*
+|*************************************************************************/
+void SwFrm::InsertGroupBefore( SwFrm* pParent, SwFrm* pBehind, SwFrm* pSct )
+{
+ OSL_ENSURE( pParent, "Kein Parent fuer Insert." );
+ OSL_ENSURE( (!pBehind || ( (pBehind && (pParent == pBehind->GetUpper()))
+ || ((pParent->IsSctFrm() && pBehind->GetUpper()->IsColBodyFrm())) ) ),
+ "Framebaum inkonsistent." );
+ if( pSct )
+ {
+ pUpper = pParent->GetUpper();
+ SwFrm *pLast = this;
+ while( pLast->GetNext() )
+ {
+ pLast = pLast->GetNext();
+ pLast->pUpper = GetUpper();
+ }
+ if( pBehind )
+ {
+ pLast->pNext = pSct;
+ pSct->pPrev = pLast;
+ pSct->pNext = pParent->GetNext();
+ }
+ else
+ {
+ pLast->pNext = pParent->GetNext();
+ if( pLast->GetNext() )
+ pLast->GetNext()->pPrev = pLast;
+ }
+ pParent->pNext = this;
+ pPrev = pParent;
+ if( pSct->GetNext() )
+ pSct->GetNext()->pPrev = pSct;
+ while( pLast->GetNext() )
+ {
+ pLast = pLast->GetNext();
+ pLast->pUpper = GetUpper();
+ }
+ if( pBehind )
+ { //Einfuegen vor pBehind.
+ if( pBehind->GetPrev() )
+ pBehind->GetPrev()->pNext = NULL;
+ else
+ pBehind->GetUpper()->pLower = NULL;
+ pBehind->pPrev = NULL;
+ SwLayoutFrm* pTmp = (SwLayoutFrm*)pSct;
+ if( pTmp->Lower() )
+ {
+ OSL_ENSURE( pTmp->Lower()->IsColumnFrm(), "InsertGrp: Used SectionFrm" );
+ pTmp = (SwLayoutFrm*)((SwLayoutFrm*)pTmp->Lower())->Lower();
+ OSL_ENSURE( pTmp, "InsertGrp: Missing ColBody" );
+ }
+ pBehind->pUpper = pTmp;
+ pBehind->GetUpper()->pLower = pBehind;
+ pLast = pBehind->GetNext();
+ while ( pLast )
+ {
+ pLast->pUpper = pBehind->GetUpper();
+ pLast = pLast->GetNext();
+ };
+ }
+ else
+ {
+ OSL_ENSURE( pSct->IsSctFrm(), "InsertGroup: For SectionFrms only" );
+ delete ((SwSectionFrm*)pSct);
+ }
+ }
+ else
+ {
+ pUpper = (SwLayoutFrm*)pParent;
+ SwFrm *pLast = this;
+ while( pLast->GetNext() )
+ {
+ pLast = pLast->GetNext();
+ pLast->pUpper = GetUpper();
+ }
+ pLast->pNext = pBehind;
+ if( pBehind )
+ { //Einfuegen vor pBehind.
+ if( 0 != (pPrev = pBehind->pPrev) )
+ pPrev->pNext = this;
+ else
+ pUpper->pLower = this;
+ pBehind->pPrev = pLast;
+ }
+ else
+ { //Einfuegen am Ende, oder des ersten Nodes im Unterbaum
+ pPrev = pUpper->Lower();
+ if ( pPrev )
+ {
+ while( pPrev->pNext )
+ pPrev = pPrev->pNext;
+ pPrev->pNext = this;
+ }
+ else
+ pUpper->pLower = this;
+ }
+ }
+}
+
+/*************************************************************************
+|*
+|* SwFrm::Remove()
+|*
+|*************************************************************************/
+void SwFrm::Remove()
+{
+ OSL_ENSURE( pUpper, "Removen ohne Upper?" );
+
+ if( pPrev )
+ // einer aus der Mitte wird removed
+ pPrev->pNext = pNext;
+ else
+ { // der erste in einer Folge wird removed
+ OSL_ENSURE( pUpper->pLower == this, "Layout inkonsistent." );
+ pUpper->pLower = pNext;
+ }
+ if( pNext )
+ pNext->pPrev = pPrev;
+
+ // Verbindung kappen.
+ pNext = pPrev = 0;
+ pUpper = 0;
+}
+/*************************************************************************
+|*
+|* SwCntntFrm::Paste()
+|*
+|*************************************************************************/
+void SwCntntFrm::Paste( SwFrm* pParent, SwFrm* pSibling)
+{
+ OSL_ENSURE( pParent, "Kein Parent fuer Paste." );
+ OSL_ENSURE( pParent->IsLayoutFrm(), "Parent ist CntntFrm." );
+ OSL_ENSURE( pParent != this, "Bin selbst der Parent." );
+ OSL_ENSURE( pSibling != this, "Bin mein eigener Nachbar." );
+ OSL_ENSURE( !GetPrev() && !GetNext() && !GetUpper(),
+ "Bin noch irgendwo angemeldet." );
+ OSL_ENSURE( !pSibling || pSibling->IsFlowFrm(),
+ "<SwCntntFrm::Paste(..)> - sibling not of expected type." );
+
+ //In den Baum einhaengen.
+ InsertBefore( (SwLayoutFrm*)pParent, pSibling );
+
+ SwPageFrm *pPage = FindPageFrm();
+ _InvalidateAll();
+ InvalidatePage( pPage );
+
+ if( pPage )
+ {
+ pPage->InvalidateSpelling();
+ pPage->InvalidateSmartTags(); // SMARTTAGS
+ pPage->InvalidateAutoCompleteWords();
+ pPage->InvalidateWordCount();
+ }
+
+ if ( GetNext() )
+ {
+ SwFrm* pNxt = GetNext();
+ pNxt->_InvalidatePrt();
+ pNxt->_InvalidatePos();
+ pNxt->InvalidatePage( pPage );
+ if( pNxt->IsSctFrm() )
+ pNxt = ((SwSectionFrm*)pNxt)->ContainsCntnt();
+ if( pNxt && pNxt->IsTxtFrm() && pNxt->IsInFtn() )
+ pNxt->Prepare( PREP_FTN, 0, sal_False );
+ }
+
+ if ( Frm().Height() )
+ pParent->Grow( Frm().Height() );
+
+ if ( Frm().Width() != pParent->Prt().Width() )
+ Prepare( PREP_FIXSIZE_CHG );
+
+ if ( GetPrev() )
+ {
+ if ( IsFollow() )
+ //Ich bin jetzt direkter Nachfolger meines Masters geworden
+ ((SwCntntFrm*)GetPrev())->Prepare( PREP_FOLLOW_FOLLOWS );
+ else
+ {
+ if ( GetPrev()->Frm().Height() !=
+ GetPrev()->Prt().Height() + GetPrev()->Prt().Top() )
+ //Umrandung zu beruecksichtigen?
+ GetPrev()->_InvalidatePrt();
+ // OD 18.02.2003 #104989# - force complete paint of previous frame,
+ // if frame is inserted at the end of a section frame, in order to
+ // get subsidiary lines repainted for the section.
+ if ( pParent->IsSctFrm() && !GetNext() )
+ {
+ // force complete paint of previous frame, if new inserted frame
+ // in the section is the last one.
+ GetPrev()->SetCompletePaint();
+ }
+ GetPrev()->InvalidatePage( pPage );
+ }
+ }
+ if ( IsInFtn() )
+ {
+ SwFrm* pFrm = GetIndPrev();
+ if( pFrm && pFrm->IsSctFrm() )
+ pFrm = ((SwSectionFrm*)pFrm)->ContainsAny();
+ if( pFrm )
+ pFrm->Prepare( PREP_QUOVADIS, 0, sal_False );
+ if( !GetNext() )
+ {
+ pFrm = FindFtnFrm()->GetNext();
+ if( pFrm && 0 != (pFrm=((SwLayoutFrm*)pFrm)->ContainsAny()) )
+ pFrm->_InvalidatePrt();
+ }
+ }
+
+ _InvalidateLineNum();
+ SwFrm *pNxt = FindNextCnt();
+ if ( pNxt )
+ {
+ while ( pNxt && pNxt->IsInTab() )
+ {
+ if( 0 != (pNxt = pNxt->FindTabFrm()) )
+ pNxt = pNxt->FindNextCnt();
+ }
+ if ( pNxt )
+ {
+ pNxt->_InvalidateLineNum();
+ if ( pNxt != GetNext() )
+ pNxt->InvalidatePage();
+ }
+ }
+}
+
+/*************************************************************************
+|*
+|* SwCntntFrm::Cut()
+|*
+|*************************************************************************/
+void SwCntntFrm::Cut()
+{
+ OSL_ENSURE( GetUpper(), "Cut ohne Upper()." );
+
+ SwPageFrm *pPage = FindPageFrm();
+ InvalidatePage( pPage );
+ SwFrm *pFrm = GetIndPrev();
+ if( pFrm )
+ {
+ if( pFrm->IsSctFrm() )
+ pFrm = ((SwSectionFrm*)pFrm)->ContainsAny();
+ if ( pFrm && pFrm->IsCntntFrm() )
+ {
+ pFrm->_InvalidatePrt();
+ if( IsInFtn() )
+ pFrm->Prepare( PREP_QUOVADIS, 0, sal_False );
+ }
+ // --> OD 2004-07-15 #i26250# - invalidate printing area of previous
+ // table frame.
+ else if ( pFrm && pFrm->IsTabFrm() )
+ {
+ pFrm->InvalidatePrt();
+ }
+ // <--
+ }
+
+ SwFrm *pNxt = FindNextCnt();
+ if ( pNxt )
+ {
+ while ( pNxt && pNxt->IsInTab() )
+ {
+ if( 0 != (pNxt = pNxt->FindTabFrm()) )
+ pNxt = pNxt->FindNextCnt();
+ }
+ if ( pNxt )
+ {
+ pNxt->_InvalidateLineNum();
+ if ( pNxt != GetNext() )
+ pNxt->InvalidatePage();
+ }
+ }
+
+ if( 0 != (pFrm = GetIndNext()) )
+ { //Der alte Nachfolger hat evtl. einen Abstand zum Vorgaenger
+ //berechnet, der ist jetzt, wo er der erste wird obsolet bzw. anders.
+ pFrm->_InvalidatePrt();
+ pFrm->_InvalidatePos();
+ pFrm->InvalidatePage( pPage );
+ if( pFrm->IsSctFrm() )
+ {
+ pFrm = ((SwSectionFrm*)pFrm)->ContainsAny();
+ if( pFrm )
+ {
+ pFrm->_InvalidatePrt();
+ pFrm->_InvalidatePos();
+ pFrm->InvalidatePage( pPage );
+ }
+ }
+ if( pFrm && IsInFtn() )
+ pFrm->Prepare( PREP_ERGOSUM, 0, sal_False );
+ if( IsInSct() && !GetPrev() )
+ {
+ SwSectionFrm* pSct = FindSctFrm();
+ if( !pSct->IsFollow() )
+ {
+ pSct->_InvalidatePrt();
+ pSct->InvalidatePage( pPage );
+ }
+ }
+ }
+ else
+ {
+ InvalidateNextPos();
+ //Einer muss die Retusche uebernehmen: Vorgaenger oder Upper
+ if ( 0 != (pFrm = GetPrev()) )
+ { pFrm->SetRetouche();
+ pFrm->Prepare( PREP_WIDOWS_ORPHANS );
+ pFrm->_InvalidatePos();
+ pFrm->InvalidatePage( pPage );
+ }
+ //Wenn ich der einzige CntntFrm in meinem Upper bin (war), so muss
+ //er die Retouche uebernehmen.
+ //Ausserdem kann eine Leerseite entstanden sein.
+ else
+ { SwRootFrm *pRoot = getRootFrm();
+ if ( pRoot )
+ {
+ pRoot->SetSuperfluous();
+ GetUpper()->SetCompletePaint();
+ GetUpper()->InvalidatePage( pPage );
+ }
+ if( IsInSct() )
+ {
+ SwSectionFrm* pSct = FindSctFrm();
+ if( !pSct->IsFollow() )
+ {
+ pSct->_InvalidatePrt();
+ pSct->InvalidatePage( pPage );
+ }
+ }
+ // --> FME 2005-08-03 #i52253# The master table should take care
+ // of removing the follow flow line.
+ if ( IsInTab() )
+ {
+ SwTabFrm* pThisTab = FindTabFrm();
+ SwTabFrm* pMasterTab = pThisTab && pThisTab->IsFollow() ? pThisTab->FindMaster() : 0;
+ if ( pMasterTab )
+ {
+ pMasterTab->_InvalidatePos();
+ pMasterTab->SetRemoveFollowFlowLinePending( sal_True );
+ }
+ }
+ // <--
+ }
+ }
+ //Erst removen, dann Upper Shrinken.
+ SwLayoutFrm *pUp = GetUpper();
+ Remove();
+ if ( pUp )
+ {
+ SwSectionFrm *pSct = 0;
+ if ( !pUp->Lower() &&
+ ( ( pUp->IsFtnFrm() && !pUp->IsColLocked() ) ||
+ ( pUp->IsInSct() &&
+ // --> FME 2004-06-03 #i29438#
+ // We have to consider the case that the section may be "empty"
+ // except from a temporary empty table frame.
+ // This can happen due to the new cell split feature.
+ !pUp->IsCellFrm() &&
+ // <--
+ // --> OD 2006-01-04 #126020# - adjust check for empty section
+ // --> OD 2006-02-01 #130797# - correct fix #126020#
+ !(pSct = pUp->FindSctFrm())->ContainsCntnt() &&
+ !pSct->ContainsAny( true ) ) ) )
+ // <--
+ {
+ if ( pUp->GetUpper() )
+ {
+ // --> OD 2006-09-25 #b6448963#
+ // prevent delete of <ColLocked> footnote frame
+ if ( pUp->IsFtnFrm() && !pUp->IsColLocked())
+ // <--
+ {
+ if( pUp->GetNext() && !pUp->GetPrev() )
+ {
+ SwFrm* pTmp = ((SwLayoutFrm*)pUp->GetNext())->ContainsAny();
+ if( pTmp )
+ pTmp->_InvalidatePrt();
+ }
+ pUp->Cut();
+ delete pUp;
+ }
+ else
+ {
+ // --> OD 2006-09-25 #b6448963#
+ if ( pSct->IsColLocked() || !pSct->IsInFtn() ||
+ ( pUp->IsFtnFrm() && pUp->IsColLocked() ) )
+ // <--
+ {
+ pSct->DelEmpty( sal_False );
+ // Wenn ein gelockter Bereich nicht geloescht werden darf,
+ // so ist zumindest seine Groesse durch das Entfernen seines
+ // letzten Contents ungueltig geworden.
+ pSct->_InvalidateSize();
+ }
+ else
+ {
+ pSct->DelEmpty( sal_True );
+ delete pSct;
+ }
+ }
+ }
+ }
+ else
+ {
+ SWRECTFN( this )
+ long nFrmHeight = (Frm().*fnRect->fnGetHeight)();
+ if( nFrmHeight )
+ pUp->Shrink( nFrmHeight );
+ }
+ }
+}
+
+/*************************************************************************
+|*
+|* SwLayoutFrm::Paste()
+|*
+|*************************************************************************/
+void SwLayoutFrm::Paste( SwFrm* pParent, SwFrm* pSibling)
+{
+ OSL_ENSURE( pParent, "Kein Parent fuer Paste." );
+ OSL_ENSURE( pParent->IsLayoutFrm(), "Parent ist CntntFrm." );
+ OSL_ENSURE( pParent != this, "Bin selbst der Parent." );
+ OSL_ENSURE( pSibling != this, "Bin mein eigener Nachbar." );
+ OSL_ENSURE( !GetPrev() && !GetNext() && !GetUpper(),
+ "Bin noch irgendwo angemeldet." );
+
+ //In den Baum einhaengen.
+ InsertBefore( (SwLayoutFrm*)pParent, pSibling );
+
+ // OD 24.10.2002 #103517# - correct setting of variable <fnRect>
+ // <fnRect> is used for the following:
+ // (1) To invalidate the frame's size, if its size, which has to be the
+ // same as its upper/parent, differs from its upper's/parent's.
+ // (2) To adjust/grow the frame's upper/parent, if it has a dimension in its
+ // size, which is not determined by its upper/parent.
+ // Which size is which depends on the frame type and the layout direction
+ // (vertical or horizontal).
+ // There are the following cases:
+ // (A) Header and footer frames both in vertical and in horizontal layout
+ // have to size the width to the upper/parent. A dimension in the height
+ // has to cause a adjustment/grow of the upper/parent.
+ // --> <fnRect> = fnRectHori
+ // (B) Cell and column frames in vertical layout, the width has to be the
+ // same as upper/parent and a dimension in height causes adjustment/grow
+ // of the upper/parent.
+ // --> <fnRect> = fnRectHori
+ // in horizontal layout the other way around
+ // --> <fnRect> = fnRectVert
+ // (C) Other frames in vertical layout, the height has to be the
+ // same as upper/parent and a dimension in width causes adjustment/grow
+ // of the upper/parent.
+ // --> <fnRect> = fnRectVert
+ // in horizontal layout the other way around
+ // --> <fnRect> = fnRectHori
+ //SwRectFn fnRect = IsVertical() ? fnRectHori : fnRectVert;
+ SwRectFn fnRect;
+ if ( IsHeaderFrm() || IsFooterFrm() )
+ fnRect = fnRectHori;
+ else if ( IsCellFrm() || IsColumnFrm() )
+ //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin
+ fnRect = GetUpper()->IsVertical() ? fnRectHori : ( GetUpper()->IsVertLR() ? fnRectVertL2R : fnRectVert );
+ else
+ //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin
+ fnRect = GetUpper()->IsVertical() ? ( GetUpper()->IsVertLR() ? fnRectVertL2R : fnRectVert ) : fnRectHori;
+
+
+ if( (Frm().*fnRect->fnGetWidth)() != (pParent->Prt().*fnRect->fnGetWidth)())
+ _InvalidateSize();
+ _InvalidatePos();
+ const SwPageFrm *pPage = FindPageFrm();
+ InvalidatePage( pPage );
+ SwFrm *pFrm;
+ if( !IsColumnFrm() )
+ {
+ if( 0 != ( pFrm = GetIndNext() ) )
+ {
+ pFrm->_InvalidatePos();
+ if( IsInFtn() )
+ {
+ if( pFrm->IsSctFrm() )
+ pFrm = ((SwSectionFrm*)pFrm)->ContainsAny();
+ if( pFrm )
+ pFrm->Prepare( PREP_ERGOSUM, 0, sal_False );
+ }
+ }
+ if ( IsInFtn() && 0 != ( pFrm = GetIndPrev() ) )
+ {
+ if( pFrm->IsSctFrm() )
+ pFrm = ((SwSectionFrm*)pFrm)->ContainsAny();
+ if( pFrm )
+ pFrm->Prepare( PREP_QUOVADIS, 0, sal_False );
+ }
+ }
+
+ if( (Frm().*fnRect->fnGetHeight)() )
+ {
+ // AdjustNeighbourhood wird jetzt auch in Spalten aufgerufen,
+ // die sich nicht in Rahmen befinden
+ sal_uInt8 nAdjust = GetUpper()->IsFtnBossFrm() ?
+ ((SwFtnBossFrm*)GetUpper())->NeighbourhoodAdjustment( this )
+ : NA_GROW_SHRINK;
+ SwTwips nGrow = (Frm().*fnRect->fnGetHeight)();
+ if( NA_ONLY_ADJUST == nAdjust )
+ AdjustNeighbourhood( nGrow );
+ else
+ {
+ SwTwips nReal = 0;
+ if( NA_ADJUST_GROW == nAdjust )
+ nReal = AdjustNeighbourhood( nGrow );
+ if( nReal < nGrow )
+ nReal += pParent->Grow( nGrow - nReal );
+ if( NA_GROW_ADJUST == nAdjust && nReal < nGrow )
+ AdjustNeighbourhood( nGrow - nReal );
+ }
+ }
+}
+
+/*************************************************************************
+|*
+|* SwLayoutFrm::Cut()
+|*
+|*************************************************************************/
+void SwLayoutFrm::Cut()
+{
+ if ( GetNext() )
+ GetNext()->_InvalidatePos();
+
+ SWRECTFN( this )
+ SwTwips nShrink = (Frm().*fnRect->fnGetHeight)();
+
+ //Erst removen, dann Upper Shrinken.
+ SwLayoutFrm *pUp = GetUpper();
+
+ // AdjustNeighbourhood wird jetzt auch in Spalten aufgerufen,
+ // die sich nicht in Rahmen befinden
+
+ // Remove must not be called before a AdjustNeighbourhood, but it has to
+ // be called before the upper-shrink-call, if the upper-shrink takes care
+ // of his content
+ if ( pUp && nShrink )
+ {
+ if( pUp->IsFtnBossFrm() )
+ {
+ sal_uInt8 nAdjust= ((SwFtnBossFrm*)pUp)->NeighbourhoodAdjustment( this );
+ if( NA_ONLY_ADJUST == nAdjust )
+ AdjustNeighbourhood( -nShrink );
+ else
+ {
+ SwTwips nReal = 0;
+ if( NA_ADJUST_GROW == nAdjust )
+ nReal = -AdjustNeighbourhood( -nShrink );
+ if( nReal < nShrink )
+ {
+ SwTwips nOldHeight = (Frm().*fnRect->fnGetHeight)();
+ (Frm().*fnRect->fnSetHeight)( 0 );
+ nReal += pUp->Shrink( nShrink - nReal );
+ (Frm().*fnRect->fnSetHeight)( nOldHeight );
+ }
+ if( NA_GROW_ADJUST == nAdjust && nReal < nShrink )
+ AdjustNeighbourhood( nReal - nShrink );
+ }
+ Remove();
+ }
+ else
+ {
+ Remove();
+ pUp->Shrink( nShrink );
+ }
+ }
+ else
+ Remove();
+
+ if( pUp && !pUp->Lower() )
+ {
+ pUp->SetCompletePaint();
+ pUp->InvalidatePage();
+ }
+}
+
+/*************************************************************************
+|*
+|* SwFrm::Grow()
+|*
+|*************************************************************************/
+SwTwips SwFrm::Grow( SwTwips nDist, sal_Bool bTst, sal_Bool bInfo )
+{
+ OSL_ENSURE( nDist >= 0, "Negatives Wachstum?" );
+
+ PROTOCOL_ENTER( this, bTst ? PROT_GROW_TST : PROT_GROW, 0, &nDist )
+
+ if ( nDist )
+ {
+ SWRECTFN( this )
+
+ SwTwips nPrtHeight = (Prt().*fnRect->fnGetHeight)();
+ if( nPrtHeight > 0 && nDist > (LONG_MAX - nPrtHeight) )
+ nDist = LONG_MAX - nPrtHeight;
+
+ if ( IsFlyFrm() )
+ return ((SwFlyFrm*)this)->_Grow( nDist, bTst );
+ else if( IsSctFrm() )
+ return ((SwSectionFrm*)this)->_Grow( nDist, bTst );
+ else
+ {
+ const SwCellFrm* pThisCell = dynamic_cast<const SwCellFrm*>(this);
+ if ( pThisCell )
+ {
+ const SwTabFrm* pTab = FindTabFrm();
+
+ // NEW TABLES
+ if ( ( 0 != pTab->IsVertical() ) != ( 0 != IsVertical() ) ||
+ pThisCell->GetLayoutRowSpan() < 1 )
+ return 0;
+ }
+
+ const SwTwips nReal = GrowFrm( nDist, bTst, bInfo );
+ if( !bTst )
+ {
+ nPrtHeight = (Prt().*fnRect->fnGetHeight)();
+ (Prt().*fnRect->fnSetHeight)( nPrtHeight +
+ ( IsCntntFrm() ? nDist : nReal ) );
+ }
+ return nReal;
+ }
+ }
+ return 0L;
+}
+
+/*************************************************************************
+|*
+|* SwFrm::Shrink()
+|*
+|*************************************************************************/
+SwTwips SwFrm::Shrink( SwTwips nDist, sal_Bool bTst, sal_Bool bInfo )
+{
+ OSL_ENSURE( nDist >= 0, "Negative Verkleinerung?" );
+
+ PROTOCOL_ENTER( this, bTst ? PROT_SHRINK_TST : PROT_SHRINK, 0, &nDist )
+
+ if ( nDist )
+ {
+ if ( IsFlyFrm() )
+ return ((SwFlyFrm*)this)->_Shrink( nDist, bTst );
+ else if( IsSctFrm() )
+ return ((SwSectionFrm*)this)->_Shrink( nDist, bTst );
+ else
+ {
+ const SwCellFrm* pThisCell = dynamic_cast<const SwCellFrm*>(this);
+ if ( pThisCell )
+ {
+ const SwTabFrm* pTab = FindTabFrm();
+
+ // NEW TABLES
+ if ( ( 0 != pTab->IsVertical() ) != ( 0 != IsVertical() ) ||
+ pThisCell->GetLayoutRowSpan() < 1 )
+ return 0;
+ }
+
+ SWRECTFN( this )
+ SwTwips nReal = (Frm().*fnRect->fnGetHeight)();
+ ShrinkFrm( nDist, bTst, bInfo );
+ nReal -= (Frm().*fnRect->fnGetHeight)();
+ if( !bTst )
+ {
+ const SwTwips nPrtHeight = (Prt().*fnRect->fnGetHeight)();
+ (Prt().*fnRect->fnSetHeight)( nPrtHeight -
+ ( IsCntntFrm() ? nDist : nReal ) );
+ }
+ return nReal;
+ }
+ }
+ return 0L;
+}
+
+/*************************************************************************
+|*
+|* SwFrm::AdjustNeighbourhood()
+|*
+|* Beschreibung Wenn sich die Groesse eines Frm's direkt unterhalb
+|* eines Fussnotenbosses (Seite/Spalte) veraendert hat, so muss dieser
+|* "Normalisiert" werden.
+|* Es gibt dort immer einen Frame, der den "maximal moeglichen" Raum
+|* einnimmt (der Frame, der den Body.Text enhaelt) und keinen oder
+|* mehrere Frames die den Platz einnehmen den sie halt brauchen
+|* (Kopf-/Fussbereich, Fussnoten).
+|* Hat sich einer der Frames veraendert, so muss der Body-Text-Frame
+|* entsprechen wachsen oder schrumpfen; unabhaegig davon, dass er fix ist.
+|* !! Ist es moeglich dies allgemeiner zu loesen, also nicht auf die
+|* Seite beschraenkt und nicht auf einen Speziellen Frame, der den
+|* maximalen Platz einnimmt (gesteuert ueber Attribut FrmSize)? Probleme:
+|* Was ist wenn mehrere Frames nebeneinander stehen, die den maximalen
+|* Platz einnehmen?
+|* Wie wird der Maximale Platz berechnet?
+|* Wie klein duerfen diese Frames werden?
+|*
+|* Es wird auf jeden Fall nur so viel Platz genehmigt, dass ein
+|* Minimalwert fuer die Hoehe des Bodys nicht unterschritten wird.
+|*
+|* Parameter: nDiff ist der Betrag, um den Platz geschaffen werden muss
+|*
+|*************************************************************************/
+SwTwips SwFrm::AdjustNeighbourhood( SwTwips nDiff, sal_Bool bTst )
+{
+ PROTOCOL_ENTER( this, PROT_ADJUSTN, 0, &nDiff );
+
+ if ( !nDiff || !GetUpper()->IsFtnBossFrm() ) // nur innerhalb von Seiten/Spalten
+ return 0L;
+
+ const ViewShell *pSh = getRootFrm()->GetCurrShell();
+ const sal_Bool bBrowse = pSh && pSh->GetViewOptions()->getBrowseMode();
+
+ //Der (Page)Body veraendert sich nur im BrowseMode, aber nicht wenn er
+ //Spalten enthaelt.
+ if ( IsPageBodyFrm() && (!bBrowse ||
+ (((SwLayoutFrm*)this)->Lower() &&
+ ((SwLayoutFrm*)this)->Lower()->IsColumnFrm())) )
+ return 0L;
+
+ //In der BrowseView kann der PageFrm selbst ersteinmal einiges von den
+ //Wuenschen abfangen.
+ long nBrowseAdd = 0;
+ if ( bBrowse && GetUpper()->IsPageFrm() ) // nur (Page)BodyFrms
+ {
+ ViewShell *pViewShell = getRootFrm()->GetCurrShell();
+ SwLayoutFrm *pUp = GetUpper();
+ long nChg;
+ const long nUpPrtBottom = pUp->Frm().Height() -
+ pUp->Prt().Height() - pUp->Prt().Top();
+ SwRect aInva( pUp->Frm() );
+ if ( pViewShell )
+ {
+ aInva.Pos().X() = pViewShell->VisArea().Left();
+ aInva.Width( pViewShell->VisArea().Width() );
+ }
+ if ( nDiff > 0 )
+ {
+ nChg = BROWSE_HEIGHT - pUp->Frm().Height();
+ nChg = Min( nDiff, nChg );
+
+ if ( !IsBodyFrm() )
+ {
+ SetCompletePaint();
+ if ( !pViewShell || pViewShell->VisArea().Height() >= pUp->Frm().Height() )
+ {
+ //Ersteinmal den Body verkleinern. Der waechst dann schon
+ //wieder.
+ SwFrm *pBody = ((SwFtnBossFrm*)pUp)->FindBodyCont();
+ const long nTmp = nChg - pBody->Prt().Height();
+ if ( !bTst )
+ {
+ pBody->Frm().Height(Max( 0L, pBody->Frm().Height() - nChg ));
+ pBody->_InvalidatePrt();
+ pBody->_InvalidateSize();
+ if ( pBody->GetNext() )
+ pBody->GetNext()->_InvalidatePos();
+ if ( !IsHeaderFrm() )
+ pBody->SetCompletePaint();
+ }
+ nChg = nTmp <= 0 ? 0 : nTmp;
+ }
+ }
+
+ const long nTmp = nUpPrtBottom + 20;
+ aInva.Top( aInva.Bottom() - nTmp );
+ aInva.Height( nChg + nTmp );
+ }
+ else
+ {
+ //Die Seite kann bis auf 0 schrumpfen. Die erste Seite bleibt
+ //mindestens so gross wie die VisArea.
+ nChg = nDiff;
+ long nInvaAdd = 0;
+ if ( pViewShell && !pUp->GetPrev() &&
+ pUp->Frm().Height() + nDiff < pViewShell->VisArea().Height() )
+ {
+ //Das heisst aber wiederum trotzdem, das wir geeignet invalidieren
+ //muessen.
+ nChg = pViewShell->VisArea().Height() - pUp->Frm().Height();
+ nInvaAdd = -(nDiff - nChg);
+ }
+
+ //Invalidieren inklusive unterem Rand.
+ long nBorder = nUpPrtBottom + 20;
+ nBorder -= nChg;
+ aInva.Top( aInva.Bottom() - (nBorder+nInvaAdd) );
+ if ( !IsBodyFrm() )
+ {
+ SetCompletePaint();
+ if ( !IsHeaderFrm() )
+ ((SwFtnBossFrm*)pUp)->FindBodyCont()->SetCompletePaint();
+ }
+ //Wegen der Rahmen die Seite invalidieren. Dadurch wird die Seite
+ //wieder entsprechend gross wenn ein Rahmen nicht passt. Das
+ //funktioniert anderfalls nur zufaellig fuer absatzgebundene Rahmen
+ //(NotifyFlys).
+ pUp->InvalidateSize();
+ }
+ if ( !bTst )
+ {
+ //Unabhaengig von nChg
+ if ( pViewShell && aInva.HasArea() && pUp->GetUpper() )
+ pViewShell->InvalidateWindows( aInva );
+ }
+ if ( !bTst && nChg )
+ {
+ const SwRect aOldRect( pUp->Frm() );
+ pUp->Frm().SSize().Height() += nChg;
+ pUp->Prt().SSize().Height() += nChg;
+ if ( pViewShell )
+ pViewShell->Imp()->SetFirstVisPageInvalid();
+
+ if ( GetNext() )
+ GetNext()->_InvalidatePos();
+
+ //Ggf. noch ein Repaint ausloesen.
+ const SvxGraphicPosition ePos = pUp->GetFmt()->GetBackground().GetGraphicPos();
+ if ( ePos != GPOS_NONE && ePos != GPOS_TILED )
+ pViewShell->InvalidateWindows( pUp->Frm() );
+
+ if ( pUp->GetUpper() )
+ {
+ if ( pUp->GetNext() )
+ pUp->GetNext()->InvalidatePos();
+
+ //Mies aber wahr: im Notify am ViewImp wird evtl. ein Calc
+ //auf die Seite und deren Lower gerufen. Die Werte sollten
+ //unverandert bleiben, weil der Aufrufer bereits fuer die
+ //Anpassung von Frm und Prt sorgen wird.
+ const long nOldFrmHeight = Frm().Height();
+ const long nOldPrtHeight = Prt().Height();
+ const sal_Bool bOldComplete = IsCompletePaint();
+ if ( IsBodyFrm() )
+ Prt().SSize().Height() = nOldFrmHeight;
+
+ // PAGES01
+ if ( pUp->GetUpper() )
+ static_cast<SwRootFrm*>(pUp->GetUpper())->CheckViewLayout( 0, 0 );
+ //((SwPageFrm*)pUp)->AdjustRootSize( CHG_CHGPAGE, &aOldRect );
+
+ Frm().SSize().Height() = nOldFrmHeight;
+ Prt().SSize().Height() = nOldPrtHeight;
+ bCompletePaint = bOldComplete;
+ }
+ if ( !IsBodyFrm() )
+ pUp->_InvalidateSize();
+ InvalidatePage( (SwPageFrm*)pUp );
+ }
+ nDiff -= nChg;
+ if ( !nDiff )
+ return nChg;
+ else
+ nBrowseAdd = nChg;
+ }
+
+ const SwFtnBossFrm *pBoss = (SwFtnBossFrm*)GetUpper();
+
+ SwTwips nReal = 0,
+ nAdd = 0;
+ SwFrm *pFrm = 0;
+ SWRECTFN( this )
+
+ if( IsBodyFrm() )
+ {
+ if( IsInSct() )
+ {
+ SwSectionFrm *pSect = FindSctFrm();
+ if( nDiff > 0 && pSect->IsEndnAtEnd() && GetNext() &&
+ GetNext()->IsFtnContFrm() )
+ {
+ SwFtnContFrm* pCont = (SwFtnContFrm*)GetNext();
+ SwTwips nMinH = 0;
+ SwFtnFrm* pFtn = (SwFtnFrm*)pCont->Lower();
+ sal_Bool bFtn = sal_False;
+ while( pFtn )
+ {
+ if( !pFtn->GetAttr()->GetFtn().IsEndNote() )
+ {
+ nMinH += (pFtn->Frm().*fnRect->fnGetHeight)();
+ bFtn = sal_True;
+ }
+ pFtn = (SwFtnFrm*)pFtn->GetNext();
+ }
+ if( bFtn )
+ nMinH += (pCont->Prt().*fnRect->fnGetTop)();
+ nReal = (pCont->Frm().*fnRect->fnGetHeight)() - nMinH;
+ if( nReal > nDiff )
+ nReal = nDiff;
+ if( nReal > 0 )
+ pFrm = GetNext();
+ else
+ nReal = 0;
+ }
+ if( !bTst && !pSect->IsColLocked() )
+ pSect->InvalidateSize();
+ }
+ if( !pFrm )
+ return nBrowseAdd;
+ }
+ else
+ {
+ const sal_Bool bFtnPage = pBoss->IsPageFrm() && ((SwPageFrm*)pBoss)->IsFtnPage();
+ if ( bFtnPage && !IsFtnContFrm() )
+ pFrm = (SwFrm*)pBoss->FindFtnCont();
+ if ( !pFrm )
+ pFrm = (SwFrm*)pBoss->FindBodyCont();
+
+ if ( !pFrm )
+ return 0;
+
+ //Wenn ich keinen finde eruebrigt sich alles weitere.
+ nReal = (pFrm->Frm().*fnRect->fnGetHeight)();
+ if( nReal > nDiff )
+ nReal = nDiff;
+ if( !bFtnPage )
+ {
+ //Minimalgrenze beachten!
+ if( nReal )
+ {
+ const SwTwips nMax = pBoss->GetVarSpace();
+ if ( nReal > nMax )
+ nReal = nMax;
+ }
+ if( !IsFtnContFrm() && nDiff > nReal &&
+ pFrm->GetNext() && pFrm->GetNext()->IsFtnContFrm()
+ && ( pFrm->GetNext()->IsVertical() == IsVertical() )
+ )
+ {
+ //Wenn der Body nicht genuegend her gibt, kann ich noch mal
+ //schauen ob es eine Fussnote gibt, falls ja kann dieser
+ //entsprechend viel gemopst werden.
+ const SwTwips nAddMax = (pFrm->GetNext()->Frm().*fnRect->
+ fnGetHeight)();
+ nAdd = nDiff - nReal;
+ if ( nAdd > nAddMax )
+ nAdd = nAddMax;
+ if ( !bTst )
+ {
+ (pFrm->GetNext()->Frm().*fnRect->fnSetHeight)(nAddMax-nAdd);
+ //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin
+ if( bVert && !bVertL2R && !bRev )
+ pFrm->GetNext()->Frm().Pos().X() += nAdd;
+ pFrm->GetNext()->InvalidatePrt();
+ if ( pFrm->GetNext()->GetNext() )
+ pFrm->GetNext()->GetNext()->_InvalidatePos();
+ }
+ }
+ }
+ }
+
+ if ( !bTst && nReal )
+ {
+ SwTwips nTmp = (pFrm->Frm().*fnRect->fnGetHeight)();
+ (pFrm->Frm().*fnRect->fnSetHeight)( nTmp - nReal );
+ //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin
+ if( bVert && !bVertL2R && !bRev )
+ pFrm->Frm().Pos().X() += nReal;
+ pFrm->InvalidatePrt();
+ if ( pFrm->GetNext() )
+ pFrm->GetNext()->_InvalidatePos();
+ if( nReal < 0 && pFrm->IsInSct() )
+ {
+ SwLayoutFrm* pUp = pFrm->GetUpper();
+ if( pUp && 0 != ( pUp = pUp->GetUpper() ) && pUp->IsSctFrm() &&
+ !pUp->IsColLocked() )
+ pUp->InvalidateSize();
+ }
+ if( ( IsHeaderFrm() || IsFooterFrm() ) && pBoss->GetDrawObjs() )
+ {
+ const SwSortedObjs &rObjs = *pBoss->GetDrawObjs();
+ OSL_ENSURE( pBoss->IsPageFrm(), "Header/Footer out of page?" );
+ for ( sal_uInt16 i = 0; i < rObjs.Count(); ++i )
+ {
+ SwAnchoredObject* pAnchoredObj = rObjs[i];
+ if ( pAnchoredObj->ISA(SwFlyFrm) )
+ {
+ SwFlyFrm* pFly = static_cast<SwFlyFrm*>(pAnchoredObj);
+ OSL_ENSURE( !pFly->IsFlyInCntFrm(), "FlyInCnt at Page?" );
+ const SwFmtVertOrient &rVert =
+ pFly->GetFmt()->GetVertOrient();
+ // Wann muss invalidiert werden?
+ // Wenn ein Rahmen am SeitenTextBereich ausgerichtet ist,
+ // muss bei Aenderung des Headers ein TOP, MIDDLE oder NONE,
+ // bei Aenderung des Footers ein BOTTOM oder MIDDLE
+ // ausgerichteter Rahmen seine Position neu berechnen.
+ if( ( rVert.GetRelationOrient() == text::RelOrientation::PRINT_AREA ||
+ rVert.GetRelationOrient() == text::RelOrientation::PAGE_PRINT_AREA ) &&
+ ((IsHeaderFrm() && rVert.GetVertOrient()!=text::VertOrientation::BOTTOM) ||
+ (IsFooterFrm() && rVert.GetVertOrient()!=text::VertOrientation::NONE &&
+ rVert.GetVertOrient() != text::VertOrientation::TOP)) )
+ {
+ pFly->_InvalidatePos();
+ pFly->_Invalidate();
+ }
+ }
+ }
+ }
+ }
+ return (nBrowseAdd + nReal + nAdd);
+}
+
+/*************************************************************************
+|*
+|* SwFrm::ImplInvalidateSize(), ImplInvalidatePrt(), ImplInvalidatePos(),
+|* ImplInvalidateLineNum()
+|*
+|*************************************************************************/
+/** method to perform additional actions on an invalidation
+
+ OD 2004-05-19 #i28701#
+
+ @author OD
+*/
+void SwFrm::_ActionOnInvalidation( const InvalidationType )
+{
+ // default behaviour is to perform no additional action
+}
+
+/** method to determine, if an invalidation is allowed.
+
+ OD 2004-05-19 #i28701#
+
+ @author OD
+*/
+bool SwFrm::_InvalidationAllowed( const InvalidationType ) const
+{
+ // default behaviour is to allow invalidation
+ return true;
+}
+
+void SwFrm::ImplInvalidateSize()
+{
+ if ( _InvalidationAllowed( INVALID_SIZE ) )
+ {
+ bValidSize = sal_False;
+ if ( IsFlyFrm() )
+ ((SwFlyFrm*)this)->_Invalidate();
+ else
+ InvalidatePage();
+
+ // OD 2004-05-19 #i28701#
+ _ActionOnInvalidation( INVALID_SIZE );
+ }
+}
+
+void SwFrm::ImplInvalidatePrt()
+{
+ if ( _InvalidationAllowed( INVALID_PRTAREA ) )
+ {
+ bValidPrtArea = sal_False;
+ if ( IsFlyFrm() )
+ ((SwFlyFrm*)this)->_Invalidate();
+ else
+ InvalidatePage();
+
+ // OD 2004-05-19 #i28701#
+ _ActionOnInvalidation( INVALID_PRTAREA );
+ }
+}
+
+void SwFrm::ImplInvalidatePos()
+{
+ if ( _InvalidationAllowed( INVALID_POS ) )
+ {
+ bValidPos = sal_False;
+ if ( IsFlyFrm() )
+ {
+ ((SwFlyFrm*)this)->_Invalidate();
+ }
+ else
+ {
+ InvalidatePage();
+ }
+
+ // OD 2004-05-19 #i28701#
+ _ActionOnInvalidation( INVALID_POS );
+ }
+}
+
+void SwFrm::ImplInvalidateLineNum()
+{
+ if ( _InvalidationAllowed( INVALID_LINENUM ) )
+ {
+ bValidLineNum = sal_False;
+ OSL_ENSURE( IsTxtFrm(), "line numbers are implemented for text only" );
+ InvalidatePage();
+
+ // OD 2004-05-19 #i28701#
+ _ActionOnInvalidation( INVALID_LINENUM );
+ }
+}
+
+/*************************************************************************
+|*
+|* SwFrm::ReinitializeFrmSizeAttrFlags
+|*
+|*************************************************************************/
+void SwFrm::ReinitializeFrmSizeAttrFlags()
+{
+ const SwFmtFrmSize &rFmtSize = GetAttrSet()->GetFrmSize();
+ if ( ATT_VAR_SIZE == rFmtSize.GetHeightSizeType() ||
+ ATT_MIN_SIZE == rFmtSize.GetHeightSizeType())
+ {
+ bFixSize = sal_False;
+ if ( GetType() & (FRM_HEADER | FRM_FOOTER | FRM_ROW) )
+ {
+ SwFrm *pFrm = ((SwLayoutFrm*)this)->Lower();
+ while ( pFrm )
+ { pFrm->_InvalidateSize();
+ pFrm->_InvalidatePrt();
+ pFrm = pFrm->GetNext();
+ }
+ SwCntntFrm *pCnt = ((SwLayoutFrm*)this)->ContainsCntnt();
+ // --> OD 2004-12-20 #i36991# - be save.
+ // E.g., a row can contain *no* content.
+ if ( pCnt )
+ {
+ pCnt->InvalidatePage();
+ do
+ {
+ pCnt->Prepare( PREP_ADJUST_FRM );
+ pCnt->_InvalidateSize();
+ pCnt = pCnt->GetNextCntntFrm();
+ } while ( ((SwLayoutFrm*)this)->IsAnLower( pCnt ) );
+ }
+ // <--
+ }
+ }
+ else if ( rFmtSize.GetHeightSizeType() == ATT_FIX_SIZE )
+ {
+ if( IsVertical() )
+ ChgSize( Size( rFmtSize.GetWidth(), Frm().Height()));
+ else
+ ChgSize( Size( Frm().Width(), rFmtSize.GetHeight()));
+ }
+}
+
+/*************************************************************************
+|* SwFrm::ValidateThisAndAllLowers()
+ *
+ * FME 2007-08-30 #i81146# new loop control
+|*************************************************************************/
+void SwFrm::ValidateThisAndAllLowers( const sal_uInt16 nStage )
+{
+ // Stage 0: Only validate frames. Do not process any objects.
+ // Stage 1: Only validate fly frames and all of their contents.
+ // Stage 2: Validate all.
+
+ const bool bOnlyObject = 1 == nStage;
+ const bool bIncludeObjects = 1 <= nStage;
+
+ if ( !bOnlyObject || ISA(SwFlyFrm) )
+ {
+ bValidSize = sal_True;
+ bValidPrtArea = sal_True;
+ bValidPos = sal_True;
+ }
+
+ if ( bIncludeObjects )
+ {
+ const SwSortedObjs* pObjs = GetDrawObjs();
+ if ( pObjs )
+ {
+ const sal_uInt32 nCnt = pObjs->Count();
+ for ( sal_uInt32 i = 0; i < nCnt; ++i )
+ {
+ SwAnchoredObject* pAnchObj = (*pObjs)[i];
+ if ( pAnchObj->ISA(SwFlyFrm) )
+ static_cast<SwFlyFrm*>(pAnchObj)->ValidateThisAndAllLowers( 2 );
+ else if ( pAnchObj->ISA(SwAnchoredDrawObject) )
+ static_cast<SwAnchoredDrawObject*>(pAnchObj)->ValidateThis();
+ }
+ }
+ }
+
+ if ( IsLayoutFrm() )
+ {
+ SwFrm* pLower = static_cast<SwLayoutFrm*>(this)->Lower();
+ while ( pLower )
+ {
+ pLower->ValidateThisAndAllLowers( nStage );
+ pLower = pLower->GetNext();
+ }
+ }
+}
+
+/*************************************************************************
+|*
+|* SwCntntFrm::GrowFrm()
+|*
+|*************************************************************************/
+SwTwips SwCntntFrm::GrowFrm( SwTwips nDist, sal_Bool bTst, sal_Bool bInfo )
+{
+ SWRECTFN( this )
+
+ SwTwips nFrmHeight = (Frm().*fnRect->fnGetHeight)();
+ if( nFrmHeight > 0 &&
+ nDist > (LONG_MAX - nFrmHeight ) )
+ nDist = LONG_MAX - nFrmHeight;
+
+ const ViewShell *pSh = getRootFrm()->GetCurrShell();
+ const sal_Bool bBrowse = pSh && pSh->GetViewOptions()->getBrowseMode();
+ const sal_uInt16 nTmpType = bBrowse ? 0x2084: 0x2004; //Row+Cell, Browse mit Body
+ if( !(GetUpper()->GetType() & nTmpType) && GetUpper()->HasFixSize() )
+ {
+ if ( !bTst )
+ {
+ (Frm().*fnRect->fnSetHeight)( nFrmHeight + nDist );
+ //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin
+ if( IsVertical() && !IsVertLR() && !IsReverse() )
+ Frm().Pos().X() -= nDist;
+ if ( GetNext() )
+ {
+ GetNext()->InvalidatePos();
+ }
+ // --> OD 2004-07-05 #i28701# - Due to the new object positioning the
+ // frame on the next page/column can flow backward (e.g. it was moved forward
+ // due to the positioning of its objects ). Thus, invalivate this next frame,
+ // if document compatibility option 'Consider wrapping style influence on
+ // object positioning' is ON.
+ else if ( GetUpper()->GetFmt()->getIDocumentSettingAccess()->get(IDocumentSettingAccess::CONSIDER_WRAP_ON_OBJECT_POSITION) )
+ {
+ InvalidateNextPos();
+ }
+ // <--
+ }
+ return 0;
+ }
+
+ SwTwips nReal = (GetUpper()->Prt().*fnRect->fnGetHeight)();
+ SwFrm *pFrm = GetUpper()->Lower();
+ while( pFrm && nReal > 0 )
+ { nReal -= (pFrm->Frm().*fnRect->fnGetHeight)();
+ pFrm = pFrm->GetNext();
+ }
+
+ if ( !bTst )
+ {
+ //Cntnts werden immer auf den gewuenschten Wert gebracht.
+ long nOld = (Frm().*fnRect->fnGetHeight)();
+ (Frm().*fnRect->fnSetHeight)( nOld + nDist );
+ //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin
+ if( IsVertical()&& !IsVertLR() && !IsReverse() )
+ Frm().Pos().X() -= nDist;
+ if ( nOld && IsInTab() )
+ {
+ SwTabFrm *pTab = FindTabFrm();
+ if ( pTab->GetTable()->GetHTMLTableLayout() &&
+ !pTab->IsJoinLocked() &&
+ !pTab->GetFmt()->GetDoc()->GetDocShell()->IsReadOnly() )
+ {
+ pTab->InvalidatePos();
+ pTab->SetResizeHTMLTable();
+ }
+ }
+ }
+
+ //Upper nur growen wenn notwendig.
+ if ( nReal < nDist )
+ {
+ if( GetUpper() )
+ {
+ if( bTst || !GetUpper()->IsFooterFrm() )
+ nReal = GetUpper()->Grow( nDist - (nReal > 0 ? nReal : 0),
+ bTst, bInfo );
+ else
+ {
+ nReal = 0;
+ GetUpper()->InvalidateSize();
+ }
+ }
+ else
+ nReal = 0;
+ }
+ else
+ nReal = nDist;
+
+ // --> OD 2004-07-05 #i28701# - Due to the new object positioning the
+ // frame on the next page/column can flow backward (e.g. it was moved forward
+ // due to the positioning of its objects ). Thus, invalivate this next frame,
+ // if document compatibility option 'Consider wrapping style influence on
+ // object positioning' is ON.
+ if ( !bTst )
+ {
+ if ( GetNext() )
+ {
+ GetNext()->InvalidatePos();
+ }
+ else if ( GetUpper()->GetFmt()->getIDocumentSettingAccess()->get(IDocumentSettingAccess::CONSIDER_WRAP_ON_OBJECT_POSITION) )
+ {
+ InvalidateNextPos();
+ }
+ }
+ // <--
+
+ return nReal;
+}
+
+/*************************************************************************
+|*
+|* SwCntntFrm::ShrinkFrm()
+|*
+|*************************************************************************/
+SwTwips SwCntntFrm::ShrinkFrm( SwTwips nDist, sal_Bool bTst, sal_Bool bInfo )
+{
+ SWRECTFN( this )
+ OSL_ENSURE( nDist >= 0, "nDist < 0" );
+ OSL_ENSURE( nDist <= (Frm().*fnRect->fnGetHeight)(),
+ "nDist > als aktuelle Grosse." );
+
+ if ( !bTst )
+ {
+ SwTwips nRstHeight;
+ if( GetUpper() )
+ nRstHeight = (Frm().*fnRect->fnBottomDist)
+ ( (GetUpper()->*fnRect->fnGetPrtBottom)() );
+ else
+ nRstHeight = 0;
+ if( nRstHeight < 0 )
+ {
+ SwTwips nNextHeight = 0;
+ if( GetUpper()->IsSctFrm() && nDist > LONG_MAX/2 )
+ {
+ SwFrm *pNxt = GetNext();
+ while( pNxt )
+ {
+ nNextHeight += (pNxt->Frm().*fnRect->fnGetHeight)();
+ pNxt = pNxt->GetNext();
+ }
+ }
+ nRstHeight = nDist + nRstHeight - nNextHeight;
+ }
+ else
+ nRstHeight = nDist;
+ (Frm().*fnRect->fnSetHeight)( (Frm().*fnRect->fnGetHeight)() - nDist );
+ //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin
+ if( IsVertical() && !IsVertLR() )
+ Frm().Pos().X() += nDist;
+ nDist = nRstHeight;
+ if ( IsInTab() )
+ {
+ SwTabFrm *pTab = FindTabFrm();
+ if ( pTab->GetTable()->GetHTMLTableLayout() &&
+ !pTab->IsJoinLocked() &&
+ !pTab->GetFmt()->GetDoc()->GetDocShell()->IsReadOnly() )
+ {
+ pTab->InvalidatePos();
+ pTab->SetResizeHTMLTable();
+ }
+ }
+ }
+
+ SwTwips nReal;
+ if( GetUpper() && nDist > 0 )
+ {
+ if( bTst || !GetUpper()->IsFooterFrm() )
+ nReal = GetUpper()->Shrink( nDist, bTst, bInfo );
+ else
+ {
+ nReal = 0;
+
+ // #108745# Sorry, dear old footer friend, I'm not gonna invalidate you,
+ // if there are any objects anchored inside your content, which
+ // overlap with the shrinking frame.
+ // This may lead to a footer frame that is too big, but this is better
+ // than looping.
+ // #109722# : The fix for #108745# was too strict.
+
+ bool bInvalidate = true;
+ const SwRect aRect( Frm() );
+ const SwPageFrm* pPage = FindPageFrm();
+ const SwSortedObjs* pSorted = pPage ? pPage->GetSortedObjs() : 0;
+ if( pSorted )
+ {
+ for ( sal_uInt16 i = 0; i < pSorted->Count(); ++i )
+ {
+ const SwAnchoredObject* pAnchoredObj = (*pSorted)[i];
+ const SwRect aBound( pAnchoredObj->GetObjRectWithSpaces() );
+
+ if( aBound.Left() > aRect.Right() )
+ continue;
+
+ if( aBound.IsOver( aRect ) )
+ {
+ const SwFrmFmt& rFmt = pAnchoredObj->GetFrmFmt();
+ if( SURROUND_THROUGHT != rFmt.GetSurround().GetSurround() )
+ {
+ const SwFrm* pAnchor = pAnchoredObj->GetAnchorFrm();
+ if ( pAnchor && pAnchor->FindFooterOrHeader() == GetUpper() )
+ {
+ bInvalidate = false;
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ if ( bInvalidate )
+ GetUpper()->InvalidateSize();
+ }
+ }
+ else
+ nReal = 0;
+
+ if ( !bTst )
+ {
+ //Die Position des naechsten Frm's veraendert sich auf jeden Fall.
+ InvalidateNextPos();
+
+ //Wenn ich keinen Nachfolger habe, so muss ich mich eben selbst um
+ //die Retusche kuemmern.
+ if ( !GetNext() )
+ SetRetouche();
+ }
+ return nReal;
+}
+
+/*************************************************************************
+|*
+|* SwCntntFrm::Modify()
+|*
+|*************************************************************************/
+void SwCntntFrm::Modify( const SfxPoolItem* pOld, const SfxPoolItem * pNew )
+{
+ sal_uInt8 nInvFlags = 0;
+
+ if( pNew && RES_ATTRSET_CHG == pNew->Which() )
+ {
+ SfxItemIter aNIter( *((SwAttrSetChg*)pNew)->GetChgSet() );
+ SfxItemIter aOIter( *((SwAttrSetChg*)pOld)->GetChgSet() );
+ SwAttrSetChg aOldSet( *(SwAttrSetChg*)pOld );
+ SwAttrSetChg aNewSet( *(SwAttrSetChg*)pNew );
+ while( sal_True )
+ {
+ _UpdateAttr( (SfxPoolItem*)aOIter.GetCurItem(),
+ (SfxPoolItem*)aNIter.GetCurItem(), nInvFlags,
+ &aOldSet, &aNewSet );
+ if( aNIter.IsAtEnd() )
+ break;
+ aNIter.NextItem();
+ aOIter.NextItem();
+ }
+ if ( aOldSet.Count() || aNewSet.Count() )
+ SwFrm::Modify( &aOldSet, &aNewSet );
+ }
+ else
+ _UpdateAttr( pOld, pNew, nInvFlags );
+
+ if ( nInvFlags != 0 )
+ {
+ SwPageFrm *pPage = FindPageFrm();
+ InvalidatePage( pPage );
+ if ( nInvFlags & 0x01 )
+ SetCompletePaint();
+ if ( nInvFlags & 0x02 )
+ _InvalidatePos();
+ if ( nInvFlags & 0x04 )
+ _InvalidateSize();
+ if ( nInvFlags & 0x88 )
+ {
+ if( IsInSct() && !GetPrev() )
+ {
+ SwSectionFrm *pSect = FindSctFrm();
+ if( pSect->ContainsAny() == this )
+ {
+ pSect->_InvalidatePrt();
+ pSect->InvalidatePage( pPage );
+ }
+ }
+ _InvalidatePrt();
+ }
+ SwFrm* pNextFrm = GetIndNext();
+ if ( pNextFrm && nInvFlags & 0x10)
+ {
+ pNextFrm->_InvalidatePrt();
+ pNextFrm->InvalidatePage( pPage );
+ }
+ if ( pNextFrm && nInvFlags & 0x80 )
+ {
+ pNextFrm->SetCompletePaint();
+ }
+ if ( nInvFlags & 0x20 )
+ {
+ SwFrm* pPrevFrm = GetPrev();
+ if ( pPrevFrm )
+ {
+ pPrevFrm->_InvalidatePrt();
+ pPrevFrm->InvalidatePage( pPage );
+ }
+ }
+ if ( nInvFlags & 0x40 )
+ InvalidateNextPos();
+ }
+}
+
+void SwCntntFrm::_UpdateAttr( const SfxPoolItem* pOld, const SfxPoolItem* pNew,
+ sal_uInt8 &rInvFlags,
+ SwAttrSetChg *pOldSet, SwAttrSetChg *pNewSet )
+{
+ sal_Bool bClear = sal_True;
+ sal_uInt16 nWhich = pOld ? pOld->Which() : pNew ? pNew->Which() : 0;
+ switch ( nWhich )
+ {
+ case RES_FMT_CHG:
+ rInvFlags = 0xFF;
+ /* kein break hier */
+
+ case RES_PAGEDESC: //Attributaenderung (an/aus)
+ if ( IsInDocBody() && !IsInTab() )
+ {
+ rInvFlags |= 0x02;
+ SwPageFrm *pPage = FindPageFrm();
+ if ( !GetPrev() )
+ CheckPageDescs( pPage );
+ if ( pPage && GetAttrSet()->GetPageDesc().GetNumOffset() )
+ ((SwRootFrm*)pPage->GetUpper())->SetVirtPageNum( sal_True );
+ SwDocPosUpdate aMsgHnt( pPage->Frm().Top() );
+ pPage->GetFmt()->GetDoc()->UpdatePageFlds( &aMsgHnt );
+ }
+ break;
+
+ case RES_UL_SPACE:
+ {
+ // OD 2004-02-18 #106629# - correction
+ // Invalidation of the printing area of next frame, not only
+ // for footnote content.
+ if ( !GetIndNext() )
+ {
+ SwFrm* pNxt = FindNext();
+ if ( pNxt )
+ {
+ SwPageFrm* pPg = pNxt->FindPageFrm();
+ pNxt->InvalidatePage( pPg );
+ pNxt->_InvalidatePrt();
+ if( pNxt->IsSctFrm() )
+ {
+ SwFrm* pCnt = ((SwSectionFrm*)pNxt)->ContainsAny();
+ if( pCnt )
+ {
+ pCnt->_InvalidatePrt();
+ pCnt->InvalidatePage( pPg );
+ }
+ }
+ pNxt->SetCompletePaint();
+ }
+ }
+ // OD 2004-03-17 #i11860#
+ if ( GetIndNext() &&
+ !GetUpper()->GetFmt()->getIDocumentSettingAccess()->get(IDocumentSettingAccess::USE_FORMER_OBJECT_POS) )
+ {
+ // OD 2004-07-01 #i28701# - use new method <InvalidateObjs(..)>
+ GetIndNext()->InvalidateObjs( true );
+ }
+ Prepare( PREP_UL_SPACE ); //TxtFrm muss Zeilenabst. korrigieren.
+ rInvFlags |= 0x80;
+ /* kein Break hier */
+ }
+ case RES_LR_SPACE:
+ case RES_BOX:
+ case RES_SHADOW:
+ Prepare( PREP_FIXSIZE_CHG );
+ SwFrm::Modify( pOld, pNew );
+ rInvFlags |= 0x30;
+ break;
+
+ case RES_BREAK:
+ {
+ rInvFlags |= 0x42;
+ const IDocumentSettingAccess* pIDSA = GetUpper()->GetFmt()->getIDocumentSettingAccess();
+ if( pIDSA->get(IDocumentSettingAccess::PARA_SPACE_MAX) ||
+ pIDSA->get(IDocumentSettingAccess::PARA_SPACE_MAX_AT_PAGES) )
+ {
+ rInvFlags |= 0x1;
+ SwFrm* pNxt = FindNext();
+ if( pNxt )
+ {
+ SwPageFrm* pPg = pNxt->FindPageFrm();
+ pNxt->InvalidatePage( pPg );
+ pNxt->_InvalidatePrt();
+ if( pNxt->IsSctFrm() )
+ {
+ SwFrm* pCnt = ((SwSectionFrm*)pNxt)->ContainsAny();
+ if( pCnt )
+ {
+ pCnt->_InvalidatePrt();
+ pCnt->InvalidatePage( pPg );
+ }
+ }
+ pNxt->SetCompletePaint();
+ }
+ }
+ }
+ break;
+
+ // OD 2004-02-26 #i25029#
+ case RES_PARATR_CONNECT_BORDER:
+ {
+ rInvFlags |= 0x01;
+ if ( IsTxtFrm() )
+ {
+ InvalidateNextPrtArea();
+ }
+ if ( !GetIndNext() && IsInTab() && IsInSplitTableRow() )
+ {
+ FindTabFrm()->InvalidateSize();
+ }
+ }
+ break;
+
+ case RES_PARATR_TABSTOP:
+ case RES_CHRATR_PROPORTIONALFONTSIZE:
+ case RES_CHRATR_SHADOWED:
+ case RES_CHRATR_AUTOKERN:
+ case RES_CHRATR_UNDERLINE:
+ case RES_CHRATR_OVERLINE:
+ case RES_CHRATR_KERNING:
+ case RES_CHRATR_FONT:
+ case RES_CHRATR_FONTSIZE:
+ case RES_CHRATR_ESCAPEMENT:
+ case RES_CHRATR_CONTOUR:
+ case RES_PARATR_NUMRULE:
+ rInvFlags |= 0x01;
+ break;
+
+
+ case RES_FRM_SIZE:
+ rInvFlags |= 0x01;
+ /* no break here */
+
+ default:
+ bClear = sal_False;
+ }
+ if ( bClear )
+ {
+ if ( pOldSet || pNewSet )
+ {
+ if ( pOldSet )
+ pOldSet->ClearItem( nWhich );
+ if ( pNewSet )
+ pNewSet->ClearItem( nWhich );
+ }
+ else
+ SwFrm::Modify( pOld, pNew );
+ }
+}
+
+/*************************************************************************
+|*
+|* SwLayoutFrm::SwLayoutFrm()
+|*
+|*************************************************************************/
+SwLayoutFrm::SwLayoutFrm( SwFrmFmt* pFmt, SwFrm* pSib ):
+ SwFrm( pFmt, pSib ),
+ pLower( 0 )
+{
+ const SwFmtFrmSize &rFmtSize = pFmt->GetFrmSize();
+ if ( rFmtSize.GetHeightSizeType() == ATT_FIX_SIZE )
+ bFixSize = sal_True;
+}
+
+// --> OD 2004-06-29 #i28701#
+TYPEINIT1(SwLayoutFrm,SwFrm);
+// <--
+/*--------------------------------------------------
+ * SwLayoutFrm::InnerHeight()
+ * --------------------------------------------------*/
+
+SwTwips SwLayoutFrm::InnerHeight() const
+{
+ if( !Lower() )
+ return 0;
+ SwTwips nRet = 0;
+ const SwFrm* pCnt = Lower();
+ SWRECTFN( this )
+ if( pCnt->IsColumnFrm() || pCnt->IsCellFrm() )
+ {
+ do
+ {
+ SwTwips nTmp = ((SwLayoutFrm*)pCnt)->InnerHeight();
+ if( pCnt->GetValidPrtAreaFlag() )
+ nTmp += (pCnt->Frm().*fnRect->fnGetHeight)() -
+ (pCnt->Prt().*fnRect->fnGetHeight)();
+ if( nRet < nTmp )
+ nRet = nTmp;
+ pCnt = pCnt->GetNext();
+ } while ( pCnt );
+ }
+ else
+ {
+ do
+ {
+ nRet += (pCnt->Frm().*fnRect->fnGetHeight)();
+ if( pCnt->IsCntntFrm() && ((SwTxtFrm*)pCnt)->IsUndersized() )
+ nRet += ((SwTxtFrm*)pCnt)->GetParHeight() -
+ (pCnt->Prt().*fnRect->fnGetHeight)();
+ if( pCnt->IsLayoutFrm() && !pCnt->IsTabFrm() )
+ nRet += ((SwLayoutFrm*)pCnt)->InnerHeight() -
+ (pCnt->Prt().*fnRect->fnGetHeight)();
+ pCnt = pCnt->GetNext();
+ } while( pCnt );
+
+ }
+ return nRet;
+}
+
+/*************************************************************************
+|*
+|* SwLayoutFrm::GrowFrm()
+|*
+|*************************************************************************/
+SwTwips SwLayoutFrm::GrowFrm( SwTwips nDist, sal_Bool bTst, sal_Bool bInfo )
+{
+ const ViewShell *pSh = getRootFrm()->GetCurrShell();
+ const sal_Bool bBrowse = pSh && pSh->GetViewOptions()->getBrowseMode();
+ const sal_uInt16 nTmpType = bBrowse ? 0x2084: 0x2004; //Row+Cell, Browse mit Body
+ if( !(GetType() & nTmpType) && HasFixSize() )
+ return 0;
+
+ SWRECTFN( this )
+ const SwTwips nFrmHeight = (Frm().*fnRect->fnGetHeight)();
+ const SwTwips nFrmPos = Frm().Pos().X();
+
+ if ( nFrmHeight > 0 && nDist > (LONG_MAX - nFrmHeight) )
+ nDist = LONG_MAX - nFrmHeight;
+
+ SwTwips nMin = 0;
+ if ( GetUpper() && !IsCellFrm() )
+ {
+ SwFrm *pFrm = GetUpper()->Lower();
+ while( pFrm )
+ { nMin += (pFrm->Frm().*fnRect->fnGetHeight)();
+ pFrm = pFrm->GetNext();
+ }
+ nMin = (GetUpper()->Prt().*fnRect->fnGetHeight)() - nMin;
+ if ( nMin < 0 )
+ nMin = 0;
+ }
+
+ SwRect aOldFrm( Frm() );
+ sal_Bool bMoveAccFrm = sal_False;
+
+ sal_Bool bChgPos = IsVertical() && !IsReverse();
+ if ( !bTst )
+ {
+ (Frm().*fnRect->fnSetHeight)( nFrmHeight + nDist );
+ //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin
+ if( bChgPos && !IsVertLR() )
+ Frm().Pos().X() -= nDist;
+ bMoveAccFrm = sal_True;
+ }
+
+ SwTwips nReal = nDist - nMin;
+ if ( nReal > 0 )
+ {
+ if ( GetUpper() )
+ { // AdjustNeighbourhood jetzt auch in Spalten (aber nicht in Rahmen)
+ sal_uInt8 nAdjust = GetUpper()->IsFtnBossFrm() ?
+ ((SwFtnBossFrm*)GetUpper())->NeighbourhoodAdjustment( this )
+ : NA_GROW_SHRINK;
+ if( NA_ONLY_ADJUST == nAdjust )
+ nReal = AdjustNeighbourhood( nReal, bTst );
+ else
+ {
+ if( NA_ADJUST_GROW == nAdjust )
+ nReal += AdjustNeighbourhood( nReal, bTst );
+
+ SwTwips nGrow = 0;
+ if( 0 < nReal )
+ {
+ SwFrm* pToGrow = GetUpper();
+ // NEW TABLES
+ // A cell with a row span of > 1 is allowed to grow the
+ // line containing the end of the row span if it is
+ // located in the same table frame:
+ const SwCellFrm* pThisCell = dynamic_cast<const SwCellFrm*>(this);
+ if ( pThisCell && pThisCell->GetLayoutRowSpan() > 1 )
+ {
+ SwCellFrm& rEndCell = const_cast<SwCellFrm&>(pThisCell->FindStartEndOfRowSpanCell( false, true ));
+ if ( -1 == rEndCell.GetTabBox()->getRowSpan() )
+ pToGrow = rEndCell.GetUpper();
+ else
+ pToGrow = 0;
+ }
+
+ nGrow = pToGrow ? pToGrow->Grow( nReal, bTst, bInfo ) : 0;
+ }
+
+ if( NA_GROW_ADJUST == nAdjust && nGrow < nReal )
+ nReal += AdjustNeighbourhood( nReal - nGrow, bTst );
+
+ if ( IsFtnFrm() && (nGrow != nReal) && GetNext() )
+ {
+ //Fussnoten koennen ihre Nachfolger verdraengen.
+ SwTwips nSpace = bTst ? 0 : -nDist;
+ const SwFrm *pFrm = GetUpper()->Lower();
+ do
+ { nSpace += (pFrm->Frm().*fnRect->fnGetHeight)();
+ pFrm = pFrm->GetNext();
+ } while ( pFrm != GetNext() );
+ nSpace = (GetUpper()->Prt().*fnRect->fnGetHeight)() -nSpace;
+ if ( nSpace < 0 )
+ nSpace = 0;
+ nSpace += nGrow;
+ if ( nReal > nSpace )
+ nReal = nSpace;
+ if ( nReal && !bTst )
+ ((SwFtnFrm*)this)->InvalidateNxtFtnCnts( FindPageFrm() );
+ }
+ else
+ nReal = nGrow;
+ }
+ }
+ else
+ nReal = 0;
+
+ nReal += nMin;
+ }
+ else
+ nReal = nDist;
+
+ if ( !bTst )
+ {
+ if( nReal != nDist &&
+ // NEW TABLES
+ ( !IsCellFrm() || static_cast<SwCellFrm*>(this)->GetLayoutRowSpan() > 1 ) )
+ {
+ (Frm().*fnRect->fnSetHeight)( nFrmHeight + nReal );
+ //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin
+ if( bChgPos && !IsVertLR() )
+ Frm().Pos().X() = nFrmPos - nReal;
+ bMoveAccFrm = sal_True;
+ }
+
+ if ( nReal )
+ {
+ SwPageFrm *pPage = FindPageFrm();
+ if ( GetNext() )
+ {
+ GetNext()->_InvalidatePos();
+ if ( GetNext()->IsCntntFrm() )
+ GetNext()->InvalidatePage( pPage );
+ }
+ if ( !IsPageBodyFrm() )
+ {
+ _InvalidateAll();
+ InvalidatePage( pPage );
+ }
+ if ( !(GetType() & 0x1823) ) //Tab, Row, FtnCont, Root, Page
+ NotifyLowerObjs();
+
+ if( IsCellFrm() )
+ InvaPercentLowers( nReal );
+
+ const SvxGraphicPosition ePos = GetFmt()->GetBackground().GetGraphicPos();
+ if ( GPOS_NONE != ePos && GPOS_TILED != ePos )
+ SetCompletePaint();
+ }
+ }
+
+ if( bMoveAccFrm && IsAccessibleFrm() )
+ {
+ SwRootFrm *pRootFrm = getRootFrm();
+ if( pRootFrm && pRootFrm->IsAnyShellAccessible() &&
+ pRootFrm->GetCurrShell() )
+ {
+ pRootFrm->GetCurrShell()->Imp()->MoveAccessibleFrm( this, aOldFrm );
+ }
+ }
+ return nReal;
+}
+
+/*************************************************************************
+|*
+|* SwLayoutFrm::ShrinkFrm()
+|*
+|*************************************************************************/
+SwTwips SwLayoutFrm::ShrinkFrm( SwTwips nDist, sal_Bool bTst, sal_Bool bInfo )
+{
+ const ViewShell *pSh = getRootFrm()->GetCurrShell();
+ const sal_Bool bBrowse = pSh && pSh->GetViewOptions()->getBrowseMode();
+ const sal_uInt16 nTmpType = bBrowse ? 0x2084: 0x2004; //Row+Cell, Browse mit Body
+ if( !(GetType() & nTmpType) && HasFixSize() )
+ return 0;
+
+ OSL_ENSURE( nDist >= 0, "nDist < 0" );
+ SWRECTFN( this )
+ SwTwips nFrmHeight = (Frm().*fnRect->fnGetHeight)();
+ if ( nDist > nFrmHeight )
+ nDist = nFrmHeight;
+
+ SwTwips nMin = 0;
+ sal_Bool bChgPos = IsVertical() && !IsReverse();
+ if ( Lower() )
+ {
+ if( !Lower()->IsNeighbourFrm() )
+ { const SwFrm *pFrm = Lower();
+ const long nTmp = (Prt().*fnRect->fnGetHeight)();
+ while( pFrm && nMin < nTmp )
+ { nMin += (pFrm->Frm().*fnRect->fnGetHeight)();
+ pFrm = pFrm->GetNext();
+ }
+ }
+ }
+ SwTwips nReal = nDist;
+ SwTwips nMinDiff = (Prt().*fnRect->fnGetHeight)() - nMin;
+ if( nReal > nMinDiff )
+ nReal = nMinDiff;
+ if( nReal <= 0 )
+ return nDist;
+
+ SwRect aOldFrm( Frm() );
+ sal_Bool bMoveAccFrm = sal_False;
+
+ SwTwips nRealDist = nReal;
+ if ( !bTst )
+ {
+ (Frm().*fnRect->fnSetHeight)( nFrmHeight - nReal );
+ //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin
+ if( bChgPos && !IsVertLR() )
+ Frm().Pos().X() += nReal;
+ bMoveAccFrm = sal_True;
+ }
+
+ sal_uInt8 nAdjust = GetUpper() && GetUpper()->IsFtnBossFrm() ?
+ ((SwFtnBossFrm*)GetUpper())->NeighbourhoodAdjustment( this )
+ : NA_GROW_SHRINK;
+
+ // AdjustNeighbourhood auch in Spalten (aber nicht in Rahmen)
+ if( NA_ONLY_ADJUST == nAdjust )
+ {
+ if ( IsPageBodyFrm() && !bBrowse )
+ nReal = nDist;
+ else
+ { nReal = AdjustNeighbourhood( -nReal, bTst );
+ nReal *= -1;
+ if ( !bTst && IsBodyFrm() && nReal < nRealDist )
+ {
+ (Frm().*fnRect->fnSetHeight)( (Frm().*fnRect->fnGetHeight)()
+ + nRealDist - nReal );
+ //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin
+ if( bChgPos && !IsVertLR() )
+ Frm().Pos().X() += nRealDist - nReal;
+ OSL_ENSURE( !IsAccessibleFrm(), "bMoveAccFrm has to be set!" );
+ }
+ }
+ }
+ else if( IsColumnFrm() || IsColBodyFrm() )
+ {
+ SwTwips nTmp = GetUpper()->Shrink( nReal, bTst, bInfo );
+ if ( nTmp != nReal )
+ {
+ (Frm().*fnRect->fnSetHeight)( (Frm().*fnRect->fnGetHeight)()
+ + nReal - nTmp );
+ //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin
+ if( bChgPos && !IsVertLR() )
+ Frm().Pos().X() += nTmp - nReal;
+ OSL_ENSURE( !IsAccessibleFrm(), "bMoveAccFrm has to be set!" );
+ nReal = nTmp;
+ }
+ }
+ else
+ {
+ SwTwips nShrink = nReal;
+ SwFrm* pToShrink = GetUpper();
+ const SwCellFrm* pThisCell = dynamic_cast<const SwCellFrm*>(this);
+ // NEW TABLES
+ if ( pThisCell && pThisCell->GetLayoutRowSpan() > 1 )
+ {
+ SwCellFrm& rEndCell = const_cast<SwCellFrm&>(pThisCell->FindStartEndOfRowSpanCell( false, true ));
+ pToShrink = rEndCell.GetUpper();
+ }
+
+ nReal = pToShrink ? pToShrink->Shrink( nShrink, bTst, bInfo ) : 0;
+ if( ( NA_GROW_ADJUST == nAdjust || NA_ADJUST_GROW == nAdjust )
+ && nReal < nShrink )
+ AdjustNeighbourhood( nReal - nShrink );
+ }
+
+ if( bMoveAccFrm && IsAccessibleFrm() )
+ {
+ SwRootFrm *pRootFrm = getRootFrm();
+ if( pRootFrm && pRootFrm->IsAnyShellAccessible() &&
+ pRootFrm->GetCurrShell() )
+ {
+ pRootFrm->GetCurrShell()->Imp()->MoveAccessibleFrm( this, aOldFrm );
+ }
+ }
+ if ( !bTst && (IsCellFrm() || IsColumnFrm() ? nReal : nRealDist) )
+ {
+ SwPageFrm *pPage = FindPageFrm();
+ if ( GetNext() )
+ {
+ GetNext()->_InvalidatePos();
+ if ( GetNext()->IsCntntFrm() )
+ GetNext()->InvalidatePage( pPage );
+ if ( IsTabFrm() )
+ ((SwTabFrm*)this)->SetComplete();
+ }
+ else
+ { if ( IsRetoucheFrm() )
+ SetRetouche();
+ if ( IsTabFrm() )
+ {
+ if( IsTabFrm() )
+ ((SwTabFrm*)this)->SetComplete();
+ if ( Lower() ) //Kann auch im Join stehen und leer sein!
+ InvalidateNextPos();
+ }
+ }
+ if ( !IsBodyFrm() )
+ {
+ _InvalidateAll();
+ InvalidatePage( pPage );
+ const SvxGraphicPosition ePos = GetFmt()->GetBackground().GetGraphicPos();
+ if ( GPOS_NONE != ePos && GPOS_TILED != ePos )
+ SetCompletePaint();
+ }
+
+ if ( !(GetType() & 0x1823) ) //Tab, Row, FtnCont, Root, Page
+ NotifyLowerObjs();
+
+ if( IsCellFrm() )
+ InvaPercentLowers( nReal );
+
+ SwCntntFrm *pCnt;
+ if( IsFtnFrm() && !((SwFtnFrm*)this)->GetAttr()->GetFtn().IsEndNote() &&
+ ( GetFmt()->GetDoc()->GetFtnInfo().ePos != FTNPOS_CHAPTER ||
+ ( IsInSct() && FindSctFrm()->IsFtnAtEnd() ) ) &&
+ 0 != (pCnt = ((SwFtnFrm*)this)->GetRefFromAttr() ) )
+ {
+ if ( pCnt->IsFollow() )
+ { // Wenn wir sowieso schon in einer anderen Spalte/Seite sitzen
+ // als der Frame mit der Referenz, dann brauchen wir nicht
+ // auch noch seinen Master zu invalidieren.
+ SwFrm *pTmp = pCnt->FindFtnBossFrm(sal_True) == FindFtnBossFrm(sal_True)
+ ? pCnt->FindMaster()->GetFrm() : pCnt;
+ pTmp->Prepare( PREP_ADJUST_FRM );
+ pTmp->InvalidateSize();
+ }
+ else
+ pCnt->InvalidatePos();
+ }
+ }
+ return nReal;
+}
+/*************************************************************************
+|*
+|* SwLayoutFrm::ChgLowersProp()
+|*
+|* Beschreibung Aendert die Grosse der direkt untergeordneten Frm's
+|* die eine Fixe Groesse haben, proportional zur Groessenaenderung der
+|* PrtArea des Frm's.
+|* Die Variablen Frm's werden auch proportional angepasst; sie werden
+|* sich schon wieder zurechtwachsen/-schrumpfen.
+|*
+|*************************************************************************/
+void SwLayoutFrm::ChgLowersProp( const Size& rOldSize )
+{
+ // no change of lower properties for root frame or if no lower exists.
+ if ( IsRootFrm() || !Lower() )
+ return;
+
+ // declare and init <SwFrm* pLowerFrm> with first lower
+ SwFrm *pLowerFrm = Lower();
+
+ // declare and init const booleans <bHeightChgd> and <bWidthChg>
+ const bool bHeightChgd = rOldSize.Height() != Prt().Height();
+ const bool bWidthChgd = rOldSize.Width() != Prt().Width();
+
+ // declare and init variables <bVert>, <bRev> and <fnRect>
+ SWRECTFN( this )
+
+ // This shortcut basically tries to handle only lower frames that
+ // are affected by the size change. Otherwise much more lower frames
+ // are invalidated.
+ if ( !( bVert ? bHeightChgd : bWidthChgd ) &&
+ ! Lower()->IsColumnFrm() &&
+ ( ( IsBodyFrm() && IsInDocBody() && ( !IsInSct() || !FindSctFrm()->IsColLocked() ) ) ||
+ // --> FME 2004-07-21 #i10826# Section frames without columns should not
+ // invalidate all lowers!
+ IsSctFrm() ) )
+ // <--
+ {
+ // Determine page frame the body frame resp. the section frame belongs to.
+ SwPageFrm *pPage = FindPageFrm();
+ // Determine last lower by traveling through them using <GetNext()>.
+ // During travel check each section frame, if it will be sized to
+ // maximum. If Yes, invalidate size of section frame and set
+ // corresponding flags at the page.
+ do
+ {
+ if( pLowerFrm->IsSctFrm() &&((SwSectionFrm*)pLowerFrm)->_ToMaximize() )
+ {
+ pLowerFrm->_InvalidateSize();
+ pLowerFrm->InvalidatePage( pPage );
+ }
+ if( pLowerFrm->GetNext() )
+ pLowerFrm = pLowerFrm->GetNext();
+ else
+ break;
+ } while( sal_True );
+ // If found last lower is a section frame containing no section
+ // (section frame isn't valid and will be deleted in the future),
+ // travel backwards.
+ while( pLowerFrm->IsSctFrm() && !((SwSectionFrm*)pLowerFrm)->GetSection() &&
+ pLowerFrm->GetPrev() )
+ pLowerFrm = pLowerFrm->GetPrev();
+ // If found last lower is a section frame, set <pLowerFrm> to its last
+ // content, if the section frame is valid and is not sized to maximum.
+ // Otherwise set <pLowerFrm> to NULL - In this case body frame only
+ // contains invalid section frames.
+ if( pLowerFrm->IsSctFrm() )
+ pLowerFrm = ((SwSectionFrm*)pLowerFrm)->GetSection() &&
+ !((SwSectionFrm*)pLowerFrm)->ToMaximize( sal_False ) ?
+ ((SwSectionFrm*)pLowerFrm)->FindLastCntnt() : NULL;
+
+ // continue with found last lower, probably the last content of a section
+ if ( pLowerFrm )
+ {
+ // If <pLowerFrm> is in a table frame, set <pLowerFrm> to this table
+ // frame and continue.
+ if ( pLowerFrm->IsInTab() )
+ {
+ // OD 28.10.2002 #97265# - safeguard for setting <pLowerFrm> to
+ // its table frame - check, if the table frame is also a lower
+ // of the body frame, in order to assure that <pLowerFrm> is not
+ // set to a frame, which is an *upper* of the body frame.
+ SwFrm* pTableFrm = pLowerFrm->FindTabFrm();
+ if ( IsAnLower( pTableFrm ) )
+ {
+ pLowerFrm = pTableFrm;
+ }
+ }
+ // Check, if variable size of body frame resp. section frame has grown
+ // OD 28.10.2002 #97265# - correct check, if variable size has grown.
+ SwTwips nOldHeight = bVert ? rOldSize.Width() : rOldSize.Height();
+ if( nOldHeight < (Prt().*fnRect->fnGetHeight)() )
+ {
+ // If variable size of body|section frame has grown, only found
+ // last lower and the position of the its next have to be invalidated.
+ pLowerFrm->_InvalidateAll();
+ pLowerFrm->InvalidatePage( pPage );
+ if( !pLowerFrm->IsFlowFrm() ||
+ !SwFlowFrm::CastFlowFrm( pLowerFrm )->HasFollow() )
+ pLowerFrm->InvalidateNextPos( sal_True );
+ if ( pLowerFrm->IsTxtFrm() )
+ ((SwCntntFrm*)pLowerFrm)->Prepare( PREP_ADJUST_FRM );
+ }
+ else
+ {
+ // variable size of body|section frame has shrinked. Thus,
+ // invalidate all lowers not matching the new body|section size
+ // and the dedicated new last lower.
+ if( bVert )
+ {
+ SwTwips nBot = Frm().Left() + Prt().Left();
+ while ( pLowerFrm->GetPrev() && pLowerFrm->Frm().Left() < nBot )
+ {
+ pLowerFrm->_InvalidateAll();
+ pLowerFrm->InvalidatePage( pPage );
+ pLowerFrm = pLowerFrm->GetPrev();
+ }
+ }
+ else
+ {
+ SwTwips nBot = Frm().Top() + Prt().Bottom();
+ while ( pLowerFrm->GetPrev() && pLowerFrm->Frm().Top() > nBot )
+ {
+ pLowerFrm->_InvalidateAll();
+ pLowerFrm->InvalidatePage( pPage );
+ pLowerFrm = pLowerFrm->GetPrev();
+ }
+ }
+ if ( pLowerFrm )
+ {
+ pLowerFrm->_InvalidateSize();
+ pLowerFrm->InvalidatePage( pPage );
+ if ( pLowerFrm->IsTxtFrm() )
+ ((SwCntntFrm*)pLowerFrm)->Prepare( PREP_ADJUST_FRM );
+ }
+ }
+ // --> OD 2005-01-31 #i41694# - improvement by removing duplicates
+ if ( pLowerFrm )
+ {
+ if ( pLowerFrm->IsInSct() )
+ {
+ // --> OD 2005-01-31 #i41694# - follow-up of issue #i10826#:
+ // No invalidation of section frame, if it's the this.
+ SwFrm* pSectFrm = pLowerFrm->FindSctFrm();
+ if( pSectFrm != this && IsAnLower( pSectFrm ) )
+ {
+ pSectFrm->_InvalidateSize();
+ pSectFrm->InvalidatePage( pPage );
+ }
+ // <--
+ }
+ }
+ // <--
+ }
+ return;
+ } // end of { special case }
+
+
+ // Invalidate page for content only once.
+ bool bInvaPageForCntnt = true;
+
+ // Declare booleans <bFixChgd> and <bVarChgd>, indicating for text frame
+ // adjustment, if fixed/variable size has changed.
+ bool bFixChgd, bVarChgd;
+ if( bVert == pLowerFrm->IsNeighbourFrm() )
+ {
+ bFixChgd = bWidthChgd;
+ bVarChgd = bHeightChgd;
+ }
+ else
+ {
+ bFixChgd = bHeightChgd;
+ bVarChgd = bWidthChgd;
+ }
+
+ // Declare const unsigned short <nFixWidth> and init it this frame types
+ // which has fixed width in vertical respectively horizontal layout.
+ // In vertical layout these are neighbour frames (cell and column frames),
+ // header frames and footer frames.
+ // In horizontal layout these are all frames, which aren't neighbour frames.
+ const sal_uInt16 nFixWidth = bVert ? (FRM_NEIGHBOUR | FRM_HEADFOOT)
+ : ~FRM_NEIGHBOUR;
+
+ // Declare const unsigned short <nFixHeight> and init it this frame types
+ // which has fixed height in vertical respectively horizontal layout.
+ // In vertical layout these are all frames, which aren't neighbour frames,
+ // header frames, footer frames, body frames or foot note container frames.
+ // In horizontal layout these are neighbour frames.
+ const sal_uInt16 nFixHeight= bVert ? ~(FRM_NEIGHBOUR | FRM_HEADFOOT | FRM_BODYFTNC)
+ : FRM_NEIGHBOUR;
+
+ // Travel through all lowers using <GetNext()>
+ while ( pLowerFrm )
+ {
+ if ( pLowerFrm->IsTxtFrm() )
+ {
+ // Text frames will only be invalidated - prepare invalidation
+ if ( bFixChgd )
+ static_cast<SwCntntFrm*>(pLowerFrm)->Prepare( PREP_FIXSIZE_CHG );
+ if ( bVarChgd )
+ static_cast<SwCntntFrm*>(pLowerFrm)->Prepare( PREP_ADJUST_FRM );
+ }
+ else
+ {
+ // If lower isn't a table, row, cell or section frame, adjust its
+ // frame size.
+ const sal_uInt16 nLowerType = pLowerFrm->GetType();
+ if ( !(nLowerType & (FRM_TAB|FRM_ROW|FRM_CELL|FRM_SECTION)) )
+ {
+ if ( bWidthChgd )
+ {
+ if( nLowerType & nFixWidth )
+ {
+ // Considering previous conditions:
+ // In vertical layout set width of column, header and
+ // footer frames to its upper width.
+ // In horizontal layout set width of header, footer,
+ // foot note container, foot note, body and no-text
+ // frames to its upper width.
+ pLowerFrm->Frm().Width( Prt().Width() );
+ }
+ else if( rOldSize.Width() && !pLowerFrm->IsFtnFrm() )
+ {
+ // Adjust frame width proportional, if lower isn't a
+ // foot note frame and condition <nLowerType & nFixWidth>
+ // isn't true.
+ // Considering previous conditions:
+ // In vertical layout these are foot note container,
+ // body and no-text frames.
+ // In horizontal layout these are column and no-text frames.
+ // OD 24.10.2002 #97265# - <double> calculation
+ // Perform <double> calculation of new width, if
+ // one of the coefficients is greater than 50000
+ SwTwips nNewWidth;
+ if ( (pLowerFrm->Frm().Width() > 50000) ||
+ (Prt().Width() > 50000) )
+ {
+ double nNewWidthTmp =
+ ( double(pLowerFrm->Frm().Width())
+ * double(Prt().Width()) )
+ / double(rOldSize.Width());
+ nNewWidth = SwTwips(nNewWidthTmp);
+ }
+ else
+ {
+ nNewWidth =
+ (pLowerFrm->Frm().Width() * Prt().Width()) / rOldSize.Width();
+ }
+ pLowerFrm->Frm().Width( nNewWidth );
+ }
+ }
+ if ( bHeightChgd )
+ {
+ if( nLowerType & nFixHeight )
+ {
+ // Considering previous conditions:
+ // In vertical layout set height of foot note and
+ // no-text frames to its upper height.
+ // In horizontal layout set height of column frames
+ // to its upper height.
+ pLowerFrm->Frm().Height( Prt().Height() );
+ }
+ // OD 01.10.2002 #102211#
+ // add conditions <!pLowerFrm->IsHeaderFrm()> and
+ // <!pLowerFrm->IsFooterFrm()> in order to avoid that
+ // the <Grow> of header or footer are overwritten.
+ // NOTE: Height of header/footer frame is determined by contents.
+ else if ( rOldSize.Height() &&
+ !pLowerFrm->IsFtnFrm() &&
+ !pLowerFrm->IsHeaderFrm() &&
+ !pLowerFrm->IsFooterFrm()
+ )
+ {
+ // Adjust frame height proportional, if lower isn't a
+ // foot note, a header or a footer frame and
+ // condition <nLowerType & nFixHeight> isn't true.
+ // Considering previous conditions:
+ // In vertical layout these are column, foot note container,
+ // body and no-text frames.
+ // In horizontal layout these are column, foot note
+ // container, body and no-text frames.
+
+ // OD 29.10.2002 #97265# - special case for page lowers
+ // The page lowers that have to be adjusted on page height
+ // change are the body frame and the foot note container
+ // frame.
+ // In vertical layout the height of both is directly
+ // adjusted to the page height change.
+ // In horizontal layout the height of the body frame is
+ // directly adjsuted to the page height change and the
+ // foot note frame height isn't touched, because its
+ // determined by its content.
+ // OD 31.03.2003 #108446# - apply special case for page
+ // lowers - see description above - also for section columns.
+ if ( IsPageFrm() ||
+ ( IsColumnFrm() && IsInSct() )
+ )
+ {
+ OSL_ENSURE( pLowerFrm->IsBodyFrm() || pLowerFrm->IsFtnContFrm(),
+ "ChgLowersProp - only for body or foot note container" );
+ if ( pLowerFrm->IsBodyFrm() || pLowerFrm->IsFtnContFrm() )
+ {
+ if ( IsVertical() || pLowerFrm->IsBodyFrm() )
+ {
+ SwTwips nNewHeight =
+ pLowerFrm->Frm().Height() +
+ ( Prt().Height() - rOldSize.Height() );
+ if ( nNewHeight < 0)
+ {
+ // OD 01.04.2003 #108446# - adjust assertion condition and text
+ OSL_ENSURE( !( IsPageFrm() &&
+ (pLowerFrm->Frm().Height()>0) &&
+ (pLowerFrm->IsValid()) ),
+ "ChgLowersProg - negative height for lower.");
+ nNewHeight = 0;
+ }
+ pLowerFrm->Frm().Height( nNewHeight );
+ }
+ }
+ }
+ else
+ {
+ SwTwips nNewHeight;
+ // OD 24.10.2002 #97265# - <double> calculation
+ // Perform <double> calculation of new height, if
+ // one of the coefficients is greater than 50000
+ if ( (pLowerFrm->Frm().Height() > 50000) ||
+ (Prt().Height() > 50000) )
+ {
+ double nNewHeightTmp =
+ ( double(pLowerFrm->Frm().Height())
+ * double(Prt().Height()) )
+ / double(rOldSize.Height());
+ nNewHeight = SwTwips(nNewHeightTmp);
+ }
+ else
+ {
+ nNewHeight = ( pLowerFrm->Frm().Height()
+ * Prt().Height() ) / rOldSize.Height();
+ }
+ if( !pLowerFrm->GetNext() )
+ {
+ SwTwips nSum = Prt().Height();
+ SwFrm* pTmp = Lower();
+ while( pTmp->GetNext() )
+ {
+ if( !pTmp->IsFtnContFrm() || !pTmp->IsVertical() )
+ nSum -= pTmp->Frm().Height();
+ pTmp = pTmp->GetNext();
+ }
+ if( nSum - nNewHeight == 1 &&
+ nSum == pLowerFrm->Frm().Height() )
+ nNewHeight = nSum;
+ }
+ pLowerFrm->Frm().Height( nNewHeight );
+ }
+ }
+ }
+ }
+ } // end of else { NOT text frame }
+
+ pLowerFrm->_InvalidateAll();
+ if ( bInvaPageForCntnt && pLowerFrm->IsCntntFrm() )
+ {
+ pLowerFrm->InvalidatePage();
+ bInvaPageForCntnt = false;
+ }
+
+ if ( !pLowerFrm->GetNext() && pLowerFrm->IsRetoucheFrm() )
+ {
+ //Wenn ein Wachstum stattgefunden hat, und die untergeordneten
+ //zur Retouche faehig sind (derzeit Tab, Section und Cntnt), so
+ //trigger ich sie an.
+ if ( rOldSize.Height() < Prt().SSize().Height() ||
+ rOldSize.Width() < Prt().SSize().Width() )
+ pLowerFrm->SetRetouche();
+ }
+ pLowerFrm = pLowerFrm->GetNext();
+ }
+
+ // Finally adjust the columns if width is set to auto
+ // Possible optimisation: execute this code earlier in this function and
+ // return???
+ if ( ( (bVert && bHeightChgd) || (! bVert && bWidthChgd) ) &&
+ Lower()->IsColumnFrm() )
+ {
+ // get column attribute
+ const SwFmtCol* pColAttr = NULL;
+ if ( IsPageBodyFrm() )
+ {
+ OSL_ENSURE( GetUpper()->IsPageFrm(), "Upper is not page frame" );
+ pColAttr = &GetUpper()->GetFmt()->GetCol();
+ }
+ else
+ {
+ OSL_ENSURE( IsFlyFrm() || IsSctFrm(), "Columns not in fly or section" );
+ pColAttr = &GetFmt()->GetCol();
+ }
+
+ if ( pColAttr->IsOrtho() && pColAttr->GetNumCols() > 1 )
+ AdjustColumns( pColAttr, sal_False );
+ }
+}
+
+/*************************************************************************
+|*
+|* SwLayoutFrm::Format()
+|*
+|* Beschreibung: "Formatiert" den Frame; Frm und PrtArea.
+|* Die Fixsize wird hier nicht eingestellt.
+|*
+|*************************************************************************/
+void SwLayoutFrm::Format( const SwBorderAttrs *pAttrs )
+{
+ OSL_ENSURE( pAttrs, "LayoutFrm::Format, pAttrs ist 0." );
+
+ if ( bValidPrtArea && bValidSize )
+ return;
+
+ const sal_uInt16 nLeft = (sal_uInt16)pAttrs->CalcLeft( this );
+ const sal_uInt16 nUpper = pAttrs->CalcTop();
+
+ const sal_uInt16 nRight = (sal_uInt16)((SwBorderAttrs*)pAttrs)->CalcRight( this );
+ const sal_uInt16 nLower = pAttrs->CalcBottom();
+ sal_Bool bVert = IsVertical() && !IsPageFrm();
+ //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin
+ SwRectFn fnRect = bVert ? ( IsVertLR() ? fnRectVertL2R : fnRectVert ) : fnRectHori;
+ if ( !bValidPrtArea )
+ {
+ bValidPrtArea = sal_True;
+ (this->*fnRect->fnSetXMargins)( nLeft, nRight );
+ (this->*fnRect->fnSetYMargins)( nUpper, nLower );
+ }
+
+ if ( !bValidSize )
+ {
+ if ( !HasFixSize() )
+ {
+ const SwTwips nBorder = nUpper + nLower;
+ const SwFmtFrmSize &rSz = GetFmt()->GetFrmSize();
+ SwTwips nMinHeight = rSz.GetHeightSizeType() == ATT_MIN_SIZE ? rSz.GetHeight() : 0;
+ do
+ { bValidSize = sal_True;
+
+ //Die Groesse in der VarSize wird durch den Inhalt plus den
+ //Raendern bestimmt.
+ SwTwips nRemaining = 0;
+ SwFrm *pFrm = Lower();
+ while ( pFrm )
+ { nRemaining += (pFrm->Frm().*fnRect->fnGetHeight)();
+ if( pFrm->IsTxtFrm() && ((SwTxtFrm*)pFrm)->IsUndersized() )
+ // Dieser TxtFrm waere gern ein bisschen groesser
+ nRemaining += ((SwTxtFrm*)pFrm)->GetParHeight()
+ - (pFrm->Prt().*fnRect->fnGetHeight)();
+ else if( pFrm->IsSctFrm() && ((SwSectionFrm*)pFrm)->IsUndersized() )
+ nRemaining += ((SwSectionFrm*)pFrm)->Undersize();
+ pFrm = pFrm->GetNext();
+ }
+ nRemaining += nBorder;
+ nRemaining = Max( nRemaining, nMinHeight );
+ const SwTwips nDiff = nRemaining-(Frm().*fnRect->fnGetHeight)();
+ const long nOldLeft = (Frm().*fnRect->fnGetLeft)();
+ const long nOldTop = (Frm().*fnRect->fnGetTop)();
+ if ( nDiff )
+ {
+ if ( nDiff > 0 )
+ Grow( nDiff );
+ else
+ Shrink( -nDiff );
+ //Schnell auf dem kurzen Dienstweg die Position updaten.
+ MakePos();
+ }
+ //Unterkante des Uppers nicht ueberschreiten.
+ if ( GetUpper() && (Frm().*fnRect->fnGetHeight)() )
+ {
+ const SwTwips nLimit = (GetUpper()->*fnRect->fnGetPrtBottom)();
+ if( (this->*fnRect->fnSetLimit)( nLimit ) &&
+ nOldLeft == (Frm().*fnRect->fnGetLeft)() &&
+ nOldTop == (Frm().*fnRect->fnGetTop)() )
+ bValidSize = bValidPrtArea = sal_True;
+ }
+ } while ( !bValidSize );
+ }
+ else if ( GetType() & 0x0018 )
+ {
+ do
+ { if ( Frm().Height() != pAttrs->GetSize().Height() )
+ ChgSize( Size( Frm().Width(), pAttrs->GetSize().Height()));
+ bValidSize = sal_True;
+ MakePos();
+ } while ( !bValidSize );
+ }
+ else
+ bValidSize = sal_True;
+ }
+}
+
+/*************************************************************************
+|*
+|* SwLayoutFrm::InvalidatePercentLowers()
+|*
+|*************************************************************************/
+static void InvaPercentFlys( SwFrm *pFrm, SwTwips nDiff )
+{
+ OSL_ENSURE( pFrm->GetDrawObjs(), "Can't find any Objects" );
+ for ( sal_uInt16 i = 0; i < pFrm->GetDrawObjs()->Count(); ++i )
+ {
+ SwAnchoredObject* pAnchoredObj = (*pFrm->GetDrawObjs())[i];
+ if ( pAnchoredObj->ISA(SwFlyFrm) )
+ {
+ SwFlyFrm *pFly = static_cast<SwFlyFrm*>(pAnchoredObj);
+ const SwFmtFrmSize &rSz = pFly->GetFmt()->GetFrmSize();
+ if ( rSz.GetWidthPercent() || rSz.GetHeightPercent() )
+ {
+ sal_Bool bNotify = sal_True;
+ // If we've a fly with more than 90% relative height...
+ if( rSz.GetHeightPercent() > 90 && pFly->GetAnchorFrm() &&
+ rSz.GetHeightPercent() != 0xFF && nDiff )
+ {
+ const SwFrm *pRel = pFly->IsFlyLayFrm() ? pFly->GetAnchorFrm():
+ pFly->GetAnchorFrm()->GetUpper();
+ // ... and we have already more than 90% height and we
+ // not allow the text to go through...
+ // then a notifycation could cause an endless loop, e.g.
+ // 100% height and no text wrap inside a cell of a table.
+ if( pFly->Frm().Height()*10 >
+ ( nDiff + pRel->Prt().Height() )*9 &&
+ pFly->GetFmt()->GetSurround().GetSurround() !=
+ SURROUND_THROUGHT )
+ bNotify = sal_False;
+ }
+ if( bNotify )
+ pFly->InvalidateSize();
+ }
+ }
+ }
+}
+
+void SwLayoutFrm::InvaPercentLowers( SwTwips nDiff )
+{
+ if ( GetDrawObjs() )
+ ::InvaPercentFlys( this, nDiff );
+
+ SwFrm *pFrm = ContainsCntnt();
+ if ( pFrm )
+ do
+ {
+ if ( pFrm->IsInTab() && !IsTabFrm() )
+ {
+ SwFrm *pTmp = pFrm->FindTabFrm();
+ OSL_ENSURE( pTmp, "Where's my TabFrm?" );
+ if( IsAnLower( pTmp ) )
+ pFrm = pTmp;
+ }
+
+ if ( pFrm->IsTabFrm() )
+ {
+ const SwFmtFrmSize &rSz = ((SwLayoutFrm*)pFrm)->GetFmt()->GetFrmSize();
+ if ( rSz.GetWidthPercent() || rSz.GetHeightPercent() )
+ pFrm->InvalidatePrt();
+ }
+ else if ( pFrm->GetDrawObjs() )
+ ::InvaPercentFlys( pFrm, nDiff );
+ pFrm = pFrm->FindNextCnt();
+ } while ( pFrm && IsAnLower( pFrm ) ) ;
+}
+
+/*************************************************************************
+|*
+|* SwLayoutFrm::CalcRel()
+|*
+|*************************************************************************/
+long SwLayoutFrm::CalcRel( const SwFmtFrmSize &rSz, sal_Bool ) const
+{
+ long nRet = rSz.GetWidth(),
+ nPercent = rSz.GetWidthPercent();
+
+ if ( nPercent )
+ {
+ const SwFrm *pRel = GetUpper();
+ long nRel = LONG_MAX;
+ const ViewShell *pSh = getRootFrm()->GetCurrShell();
+ const sal_Bool bBrowseMode = pSh && pSh->GetViewOptions()->getBrowseMode();
+ if( pRel->IsPageBodyFrm() && pSh && bBrowseMode && pSh->VisArea().Width() )
+ {
+ nRel = pSh->GetBrowseWidth();
+ long nDiff = nRel - pRel->Prt().Width();
+ if ( nDiff > 0 )
+ nRel -= nDiff;
+ }
+ nRel = Min( nRel, pRel->Prt().Width() );
+ nRet = nRel * nPercent / 100;
+ }
+ return nRet;
+}
+
+/*************************************************************************
+|* Local helpers for SwLayoutFrm::FormatWidthCols()
+|*************************************************************************/
+long MA_FASTCALL lcl_CalcMinColDiff( SwLayoutFrm *pLayFrm )
+{
+ long nDiff = 0, nFirstDiff = 0;
+ SwLayoutFrm *pCol = (SwLayoutFrm*)pLayFrm->Lower();
+ OSL_ENSURE( pCol, "Where's the columnframe?" );
+ SwFrm *pFrm = pCol->Lower();
+ do
+ {
+ if( pFrm && pFrm->IsBodyFrm() )
+ pFrm = ((SwBodyFrm*)pFrm)->Lower();
+ if ( pFrm && pFrm->IsTxtFrm() )
+ {
+ const long nTmp = ((SwTxtFrm*)pFrm)->FirstLineHeight();
+ if ( nTmp != USHRT_MAX )
+ {
+ if ( pCol == pLayFrm->Lower() )
+ nFirstDiff = nTmp;
+ else
+ nDiff = nDiff ? Min( nDiff, nTmp ) : nTmp;
+ }
+ }
+ //Leere Spalten ueberspringen!
+ pCol = (SwLayoutFrm*)pCol->GetNext();
+ while ( pCol && 0 == (pFrm = pCol->Lower()) )
+ pCol = (SwLayoutFrm*)pCol->GetNext();
+
+ } while ( pFrm && pCol );
+
+ return nDiff ? nDiff : nFirstDiff ? nFirstDiff : 240;
+}
+
+sal_Bool lcl_IsFlyHeightClipped( SwLayoutFrm *pLay )
+{
+ SwFrm *pFrm = pLay->ContainsCntnt();
+ while ( pFrm )
+ {
+ if ( pFrm->IsInTab() )
+ pFrm = pFrm->FindTabFrm();
+
+ if ( pFrm->GetDrawObjs() )
+ {
+ sal_uInt32 nCnt = pFrm->GetDrawObjs()->Count();
+ for ( sal_uInt16 i = 0; i < nCnt; ++i )
+ {
+ SwAnchoredObject* pAnchoredObj = (*pFrm->GetDrawObjs())[i];
+ if ( pAnchoredObj->ISA(SwFlyFrm) )
+ {
+ SwFlyFrm* pFly = static_cast<SwFlyFrm*>(pAnchoredObj);
+ if ( pFly->IsHeightClipped() &&
+ ( !pFly->IsFlyFreeFrm() || pFly->GetPageFrm() ) )
+ return sal_True;
+ }
+ }
+ }
+ pFrm = pFrm->FindNextCnt();
+ }
+ return sal_False;
+}
+
+/*************************************************************************
+|* SwLayoutFrm::FormatWidthCols()
+|*************************************************************************/
+void SwLayoutFrm::FormatWidthCols( const SwBorderAttrs &rAttrs,
+ const SwTwips nBorder, const SwTwips nMinHeight )
+{
+ //Wenn Spalten im Spiel sind, so wird die Groesse an der
+ //letzten Spalte ausgerichtet.
+ //1. Inhalt formatieren.
+ //2. Hoehe der letzten Spalte ermitteln, wenn diese zu
+ // zu gross ist muss der Fly wachsen.
+ // Der Betrag um den der Fly waechst ist aber nicht etwa
+ // der Betrag des Ueberhangs, denn wir muessen davon
+ // ausgehen, dass etwas Masse zurueckfliesst und so
+ // zusaetzlicher Platz geschaffen wird.
+ // Im Ersten Ansatz ist der Betrag um den gewachsen wird
+ // der Ueberhang geteilt durch die Spaltenanzahl oder
+ // der Ueberhang selbst wenn er kleiner als die Spalten-
+ // anzahl ist.
+ //3. Weiter mit 1. bis zur Stabilitaet.
+
+ const SwFmtCol &rCol = rAttrs.GetAttrSet().GetCol();
+ const sal_uInt16 nNumCols = rCol.GetNumCols();
+
+ sal_Bool bEnd = sal_False;
+ sal_Bool bBackLock = sal_False;
+ ViewShell *pSh = getRootFrm()->GetCurrShell();
+ SwViewImp *pImp = pSh ? pSh->Imp() : 0;
+ {
+ // Zugrunde liegender Algorithmus
+ // Es wird versucht, eine optimale Hoehe fuer die Spalten zu finden.
+ // nMinimum beginnt mit der uebergebenen Mindesthoehe und wird dann als
+ // Maximum der Hoehen gepflegt, bei denen noch Spalteninhalt aus einer
+ // Spalte herausragt.
+ // nMaximum beginnt bei LONG_MAX und wird als Minimum der Hoehen gepflegt,
+ // bei denen der Inhalt gepasst hat.
+ // Bei spaltigen Bereichen beginnt nMaximum bei dem maximalen Wert, den
+ // die Umgebung vorgibt, dies kann natuerlich ein Wert sein, bei dem noch
+ // Inhalt heraushaengt.
+ // Es werden die Spalten formatiert, wenn Inhalt heraushaengt, wird nMinimum
+ // ggf. angepasst, dann wird gewachsen, mindestens um nMinDiff, aber nicht ueber
+ // ein groesseres nMaximum hinaus. Wenn kein Inhalt heraushaengt, sondern
+ // noch Luft in einer Spalte ist, schrumpfen wir entsprechend, mindestens um
+ // nMinDiff, aber nicht unter das nMinimum.
+ // Abgebrochen wird, wenn kein Inhalt mehr heraushaengt und das Minimum sich auf
+ // weniger als ein MinDiff dem Maximum angenaehert hat oder das von der
+ // Umgebung vorgegebene Maximum erreicht ist und trotzdem Inhalt heraus-
+ // haengt.
+
+ // Kritik an der Implementation
+ // 1. Es kann theoretisch Situationen geben, in denen der Inhalt in einer geringeren
+ // Hoehe passt und in einer groesseren Hoehe nicht passt. Damit der Code robust
+ // gegen solche Verhaeltnisse ist, sind ein paar Abfragen bezgl. Minimum und Maximum
+ // drin, die wahrscheinlich niemals zuschlagen koennen.
+ // 2. Es wird fuer das Schrumpfen das gleiche nMinDiff benutzt wie fuer das Wachstum,
+ // das nMinDiff ist allerdings mehr oder weniger die kleinste erste Zeilenhoehe und
+ // als Mindestwert fuer das Schrumpfen nicht unbedingt optimal.
+
+ long nMinimum = nMinHeight;
+ long nMaximum;
+ sal_Bool bNoBalance = sal_False;
+ SWRECTFN( this )
+ if( IsSctFrm() )
+ {
+ nMaximum = (Frm().*fnRect->fnGetHeight)() - nBorder +
+ (Frm().*fnRect->fnBottomDist)(
+ (GetUpper()->*fnRect->fnGetPrtBottom)() );
+ nMaximum += GetUpper()->Grow( LONG_MAX, sal_True );
+ if( nMaximum < nMinimum )
+ {
+ if( nMaximum < 0 )
+ nMinimum = nMaximum = 0;
+ else
+ nMinimum = nMaximum;
+ }
+ if( nMaximum > BROWSE_HEIGHT )
+ nMaximum = BROWSE_HEIGHT;
+
+ bNoBalance = ((SwSectionFrm*)this)->GetSection()->GetFmt()->
+ GetBalancedColumns().GetValue();
+ SwFrm* pAny = ContainsAny();
+ if( bNoBalance ||
+ ( !(Frm().*fnRect->fnGetHeight)() && pAny ) )
+ {
+ long nTop = (this->*fnRect->fnGetTopMargin)();
+ // --> OD 2004-11-01 #i23129# - correction: enlarge section
+ // to the calculated maximum height.
+ (Frm().*fnRect->fnAddBottom)( nMaximum -
+ (Frm().*fnRect->fnGetHeight)() );
+ // <--
+ if( nTop > nMaximum )
+ nTop = nMaximum;
+ (this->*fnRect->fnSetYMargins)( nTop, 0 );
+ }
+ if( !pAny && !((SwSectionFrm*)this)->IsFtnLock() )
+ {
+ SwFtnContFrm* pFtnCont = ((SwSectionFrm*)this)->ContainsFtnCont();
+ if( pFtnCont )
+ {
+ SwFrm* pFtnAny = pFtnCont->ContainsAny();
+ if( pFtnAny && pFtnAny->IsValid() )
+ {
+ bBackLock = sal_True;
+ ((SwSectionFrm*)this)->SetFtnLock( sal_True );
+ }
+ }
+ }
+ }
+ else
+ nMaximum = LONG_MAX;
+
+ // --> OD 2004-08-25 #i3317# - reset temporarly consideration
+ // of wrapping style influence
+ SwPageFrm* pPageFrm = FindPageFrm();
+ SwSortedObjs* pObjs = pPageFrm ? pPageFrm->GetSortedObjs() : 0L;
+ if ( pObjs )
+ {
+ sal_uInt32 i = 0;
+ for ( i = 0; i < pObjs->Count(); ++i )
+ {
+ SwAnchoredObject* pAnchoredObj = (*pObjs)[i];
+
+ if ( IsAnLower( pAnchoredObj->GetAnchorFrm() ) )
+ {
+ pAnchoredObj->SetTmpConsiderWrapInfluence( false );
+ }
+ }
+ }
+ // <--
+ do
+ {
+ //Kann eine Weile dauern, deshalb hier auf Waitcrsr pruefen.
+ if ( pImp )
+ pImp->CheckWaitCrsr();
+
+ bValidSize = sal_True;
+ //Erstmal die Spalten formatieren, das entlastet den
+ //Stack ein wenig.
+ //Bei der Gelegenheit stellen wir auch gleich mal die
+ //Breiten und Hoehen der Spalten ein (so sie denn falsch sind).
+ SwLayoutFrm *pCol = (SwLayoutFrm*)Lower();
+
+ // --> FME 2004-07-19 #i27399#
+ // Simply setting the column width based on the values returned by
+ // CalcColWidth does not work for automatic column width.
+ AdjustColumns( &rCol, sal_False );
+ // <--
+
+ for ( sal_uInt16 i = 0; i < nNumCols; ++i )
+ {
+ pCol->Calc();
+ // ColumnFrms besitzen jetzt einen BodyFrm, der auch kalkuliert werden will
+ pCol->Lower()->Calc();
+ if( pCol->Lower()->GetNext() )
+ pCol->Lower()->GetNext()->Calc(); // SwFtnCont
+ pCol = (SwLayoutFrm*)pCol->GetNext();
+ }
+
+ ::CalcCntnt( this );
+
+ pCol = (SwLayoutFrm*)Lower();
+ OSL_ENSURE( pCol && pCol->GetNext(), ":-( Spalten auf Urlaub?");
+ // bMinDiff wird gesetzt, wenn es keine leere Spalte gibt
+ sal_Bool bMinDiff = sal_True;
+ // OD 28.03.2003 #108446# - check for all column content and all columns
+ while ( bMinDiff && pCol )
+ {
+ bMinDiff = 0 != pCol->ContainsCntnt();
+ pCol = (SwLayoutFrm*)pCol->GetNext();
+ }
+ pCol = (SwLayoutFrm*)Lower();
+ // OD 28.03.2003 #108446# - initialize local variable
+ SwFrm *pLow = NULL;
+ SwTwips nDiff = 0;
+ SwTwips nMaxFree = 0;
+ SwTwips nAllFree = LONG_MAX;
+ // bFoundLower wird gesetzt, wenn es mind. eine nichtleere Spalte gibt
+ sal_Bool bFoundLower = sal_False;
+ while( pCol )
+ {
+ SwLayoutFrm* pLay = (SwLayoutFrm*)pCol->Lower();
+ SwTwips nInnerHeight = (pLay->Frm().*fnRect->fnGetHeight)() -
+ (pLay->Prt().*fnRect->fnGetHeight)();
+ if( pLay->Lower() )
+ {
+ bFoundLower = sal_True;
+ nInnerHeight += pLay->InnerHeight();
+ }
+ else if( nInnerHeight < 0 )
+ nInnerHeight = 0;
+
+ if( pLay->GetNext() )
+ {
+ bFoundLower = sal_True;
+ pLay = (SwLayoutFrm*)pLay->GetNext();
+ OSL_ENSURE( pLay->IsFtnContFrm(),"FtnContainer exspected" );
+ nInnerHeight += pLay->InnerHeight();
+ nInnerHeight += (pLay->Frm().*fnRect->fnGetHeight)() -
+ (pLay->Prt().*fnRect->fnGetHeight)();
+ }
+ nInnerHeight -= (pCol->Prt().*fnRect->fnGetHeight)();
+ if( nInnerHeight > nDiff )
+ {
+ nDiff = nInnerHeight;
+ nAllFree = 0;
+ }
+ else
+ {
+ if( nMaxFree < -nInnerHeight )
+ nMaxFree = -nInnerHeight;
+ if( nAllFree > -nInnerHeight )
+ nAllFree = -nInnerHeight;
+ }
+ pCol = (SwLayoutFrm*)pCol->GetNext();
+ }
+
+ if ( bFoundLower || ( IsSctFrm() && ((SwSectionFrm*)this)->HasFollow() ) )
+ {
+ SwTwips nMinDiff = ::lcl_CalcMinColDiff( this );
+ // Hier wird entschieden, ob wir wachsen muessen, naemlich wenn
+ // ein Spalteninhalt (nDiff) oder ein Fly herausragt.
+ // Bei spaltigen Bereichen wird beruecksichtigt, dass mit dem
+ // Besitz eines nichtleeren Follows die Groesse festgelegt ist.
+ if ( nDiff || ::lcl_IsFlyHeightClipped( this ) ||
+ ( IsSctFrm() && ((SwSectionFrm*)this)->CalcMinDiff( nMinDiff ) ) )
+ {
+ long nPrtHeight = (Prt().*fnRect->fnGetHeight)();
+ // Das Minimum darf nicht kleiner sein als unsere PrtHeight,
+ // solange noch etwas herausragt.
+ if( nMinimum < nPrtHeight )
+ nMinimum = nPrtHeight;
+ // Es muss sichergestellt sein, dass das Maximum nicht kleiner
+ // als die PrtHeight ist, wenn noch etwas herausragt
+ if( nMaximum < nPrtHeight )
+ nMaximum = nPrtHeight; // Robust, aber kann das ueberhaupt eintreten?
+ if( !nDiff ) // wenn nur Flys herausragen, wachsen wir um nMinDiff
+ nDiff = nMinDiff;
+ // Wenn wir um mehr als nMinDiff wachsen wollen, wird dies auf die
+ // Spalten verteilt
+ if ( Abs(nDiff - nMinDiff) > nNumCols && nDiff > (long)nNumCols )
+ nDiff /= nNumCols;
+
+ if ( bMinDiff )
+ { // Wenn es keinen leeren Spalten gibt, wollen wir mind. um nMinDiff
+ // wachsen. Sonderfall: Wenn wir kleiner als die minimale Frmhoehe
+ // sind und die PrtHeight kleiner als nMinDiff ist, wachsen wir so,
+ // dass die PrtHeight hinterher genau nMinDiff ist.
+ long nFrmHeight = (Frm().*fnRect->fnGetHeight)();
+ if ( nFrmHeight > nMinHeight || nPrtHeight >= nMinDiff )
+ nDiff = Max( nDiff, nMinDiff );
+ else if( nDiff < nMinDiff )
+ nDiff = nMinDiff - nPrtHeight + 1;
+ }
+ // nMaximum ist eine Groesse, in der der Inhalt gepasst hat,
+ // oder der von der Umgebung vorgegebene Wert, deshalb
+ // brauchen wir nicht ueber diesen Wrt hinauswachsen.
+ if( nDiff + nPrtHeight > nMaximum )
+ nDiff = nMaximum - nPrtHeight;
+ }
+ else if( nMaximum > nMinimum ) // Wir passen, haben wir auch noch Spielraum?
+ {
+ long nPrtHeight = (Prt().*fnRect->fnGetHeight)();
+ if ( nMaximum < nPrtHeight )
+ nDiff = nMaximum - nPrtHeight; // wir sind ueber eine funktionierende
+ // Hoehe hinausgewachsen und schrumpfen wieder auf diese zurueck,
+ // aber kann das ueberhaupt eintreten?
+ else
+ { // Wir haben ein neues Maximum, eine Groesse, fuer die der Inhalt passt.
+ nMaximum = nPrtHeight;
+ // Wenn der Freiraum in den Spalten groesser ist als nMinDiff und wir
+ // nicht dadurch wieder unter das Minimum rutschen, wollen wir ein wenig
+ // Luft herauslassen.
+ if ( !bNoBalance &&
+ // --> OD 2004-11-04 #i23129# - <nMinDiff> can be
+ // big, because of an object at the beginning of
+ // a column. Thus, decrease optimization here.
+ //nMaxFree >= nMinDiff &&
+ nMaxFree > 0 &&
+ // <--
+ ( !nAllFree ||
+ nMinimum < nPrtHeight - nMinDiff ) )
+ {
+ nMaxFree /= nNumCols; // auf die Spalten verteilen
+ nDiff = nMaxFree < nMinDiff ? -nMinDiff : -nMaxFree; // mind. nMinDiff
+ if( nPrtHeight + nDiff <= nMinimum ) // Unter das Minimum?
+ nDiff = ( nMinimum - nMaximum ) / 2; // dann lieber die Mitte
+ }
+ else if( nAllFree )
+ {
+ nDiff = -nAllFree;
+ if( nPrtHeight + nDiff <= nMinimum ) // Less than minimum?
+ nDiff = ( nMinimum - nMaximum ) / 2; // Take the center
+ }
+ }
+ }
+ if( nDiff ) // jetzt wird geschrumpft oder gewachsen..
+ {
+ Size aOldSz( Prt().SSize() );
+ long nTop = (this->*fnRect->fnGetTopMargin)();
+ nDiff = (Prt().*fnRect->fnGetHeight)() + nDiff + nBorder -
+ (Frm().*fnRect->fnGetHeight)();
+ (Frm().*fnRect->fnAddBottom)( nDiff );
+ // --> OD 2006-08-16 #i68520#
+ if ( dynamic_cast<SwFlyFrm*>(this) )
+ {
+ dynamic_cast<SwFlyFrm*>(this)->InvalidateObjRectWithSpaces();
+ }
+ // <--
+ (this->*fnRect->fnSetYMargins)( nTop, nBorder - nTop );
+ ChgLowersProp( aOldSz );
+ NotifyLowerObjs();
+
+ // --> OD 2004-08-25 #i3317# - reset temporarly consideration
+ // of wrapping style influence
+ SwPageFrm* pTmpPageFrm = FindPageFrm();
+ SwSortedObjs* pTmpObjs = pTmpPageFrm ? pTmpPageFrm->GetSortedObjs() : 0L;
+ if ( pTmpObjs )
+ {
+ sal_uInt32 i = 0;
+ for ( i = 0; i < pTmpObjs->Count(); ++i )
+ {
+ SwAnchoredObject* pAnchoredObj = (*pTmpObjs)[i];
+
+ if ( IsAnLower( pAnchoredObj->GetAnchorFrm() ) )
+ {
+ pAnchoredObj->SetTmpConsiderWrapInfluence( false );
+ }
+ }
+ }
+ // <--
+ //Es muss geeignet invalidiert werden, damit
+ //sich die Frms huebsch ausbalancieren
+ //- Der jeweils erste ab der zweiten Spalte bekommt
+ // ein InvalidatePos();
+ pCol = (SwLayoutFrm*)Lower()->GetNext();
+ while ( pCol )
+ {
+ pLow = pCol->Lower();
+ if ( pLow )
+ pLow->_InvalidatePos();
+ pCol = (SwLayoutFrm*)pCol->GetNext();
+ }
+ if( IsSctFrm() && ((SwSectionFrm*)this)->HasFollow() )
+ {
+ // Wenn wir einen Follow erzeugt haben, muessen wir
+ // seinem Inhalt die Chance geben, im CalcCntnt
+ // zurueckzufliessen
+ SwCntntFrm* pTmpCntnt =
+ ((SwSectionFrm*)this)->GetFollow()->ContainsCntnt();
+ if( pTmpCntnt )
+ pTmpCntnt->_InvalidatePos();
+ }
+ }
+ else
+ bEnd = sal_True;
+ }
+ else
+ bEnd = sal_True;
+
+ } while ( !bEnd || !bValidSize );
+ }
+ // OD 01.04.2003 #108446# - Don't collect endnotes for sections. Thus, set
+ // 2nd parameter to <true>.
+ ::CalcCntnt( this, true );
+ if( IsSctFrm() )
+ {
+ // OD 14.03.2003 #i11760# - adjust 2nd parameter - sal_True --> true
+ ::CalcCntnt( this, true );
+ if( bBackLock )
+ ((SwSectionFrm*)this)->SetFtnLock( sal_False );
+ }
+}
+
+
+/*************************************************************************
+|*
+|* SwRootFrm::InvalidateAllCntnt()
+|*
+|*************************************************************************/
+
+SwCntntFrm* lcl_InvalidateSection( SwFrm *pCnt, sal_uInt8 nInv )
+{
+ SwSectionFrm* pSect = pCnt->FindSctFrm();
+ // Wenn unser CntntFrm in einer Tabelle oder Fussnote steht, sind nur
+ // Bereiche gemeint, die ebenfalls innerhalb liegen.
+ // Ausnahme: Wenn direkt eine Tabelle uebergeben wird.
+ if( ( ( pCnt->IsInTab() && !pSect->IsInTab() ) ||
+ ( pCnt->IsInFtn() && !pSect->IsInFtn() ) ) && !pCnt->IsTabFrm() )
+ return NULL;
+ if( nInv & INV_SIZE )
+ pSect->_InvalidateSize();
+ if( nInv & INV_POS )
+ pSect->_InvalidatePos();
+ if( nInv & INV_PRTAREA )
+ pSect->_InvalidatePrt();
+ SwFlowFrm *pFoll = pSect->GetFollow();
+ // Temporary separation from follow
+ pSect->SetFollow( NULL );
+ SwCntntFrm* pRet = pSect->FindLastCntnt();
+ pSect->SetFollow( pFoll );
+ return pRet;
+}
+
+SwCntntFrm* lcl_InvalidateTable( SwTabFrm *pTable, sal_uInt8 nInv )
+{
+ if( ( nInv & INV_SECTION ) && pTable->IsInSct() )
+ lcl_InvalidateSection( pTable, nInv );
+ if( nInv & INV_SIZE )
+ pTable->_InvalidateSize();
+ if( nInv & INV_POS )
+ pTable->_InvalidatePos();
+ if( nInv & INV_PRTAREA )
+ pTable->_InvalidatePrt();
+ return pTable->FindLastCntnt();
+}
+
+void lcl_InvalidateAllCntnt( SwCntntFrm *pCnt, sal_uInt8 nInv );
+
+void lcl_InvalidateCntnt( SwCntntFrm *pCnt, sal_uInt8 nInv )
+{
+ SwCntntFrm *pLastTabCnt = NULL;
+ SwCntntFrm *pLastSctCnt = NULL;
+ while ( pCnt )
+ {
+ if( nInv & INV_SECTION )
+ {
+ if( pCnt->IsInSct() )
+ {
+ // Siehe oben bei Tabellen
+ if( !pLastSctCnt )
+ pLastSctCnt = lcl_InvalidateSection( pCnt, nInv );
+ if( pLastSctCnt == pCnt )
+ pLastSctCnt = NULL;
+ }
+#if OSL_DEBUG_LEVEL > 1
+ else
+ OSL_ENSURE( !pLastSctCnt, "Where's the last SctCntnt?" );
+#endif
+ }
+ if( nInv & INV_TABLE )
+ {
+ if( pCnt->IsInTab() )
+ {
+ // Um nicht fuer jeden CntntFrm einer Tabelle das FindTabFrm() zu rufen
+ // und wieder die gleiche Tabelle zu invalidieren, merken wir uns den letzten
+ // CntntFrm der Tabelle und reagieren erst wieder auf IsInTab(), wenn wir
+ // an diesem vorbei sind.
+ // Beim Eintritt in die Tabelle wird der LastSctCnt auf Null gesetzt,
+ // damit Bereiche im Innern der Tabelle richtig invalidiert werden.
+ // Sollte die Tabelle selbst in einem Bereich stehen, so wird an
+ // diesem die Invalidierung bis zu dreimal durchgefuehrt, das ist vertretbar.
+ if( !pLastTabCnt )
+ {
+ pLastTabCnt = lcl_InvalidateTable( pCnt->FindTabFrm(), nInv );
+ pLastSctCnt = NULL;
+ }
+ if( pLastTabCnt == pCnt )
+ {
+ pLastTabCnt = NULL;
+ pLastSctCnt = NULL;
+ }
+ }
+#if OSL_DEBUG_LEVEL > 1
+ else
+ OSL_ENSURE( !pLastTabCnt, "Where's the last TabCntnt?" );
+#endif
+ }
+
+ if( nInv & INV_SIZE )
+ pCnt->Prepare( PREP_CLEAR, 0, sal_False );
+ if( nInv & INV_POS )
+ pCnt->_InvalidatePos();
+ if( nInv & INV_PRTAREA )
+ pCnt->_InvalidatePrt();
+ if ( nInv & INV_LINENUM )
+ pCnt->InvalidateLineNum();
+ if ( pCnt->GetDrawObjs() )
+ lcl_InvalidateAllCntnt( pCnt, nInv );
+ pCnt = pCnt->GetNextCntntFrm();
+ }
+}
+
+void lcl_InvalidateAllCntnt( SwCntntFrm *pCnt, sal_uInt8 nInv )
+{
+ SwSortedObjs &rObjs = *pCnt->GetDrawObjs();
+ for ( sal_uInt16 i = 0; i < rObjs.Count(); ++i )
+ {
+ SwAnchoredObject* pAnchoredObj = rObjs[i];
+ if ( pAnchoredObj->ISA(SwFlyFrm) )
+ {
+ SwFlyFrm *pFly = static_cast<SwFlyFrm*>(pAnchoredObj);
+ if ( pFly->IsFlyInCntFrm() )
+ {
+ ::lcl_InvalidateCntnt( pFly->ContainsCntnt(), nInv );
+ if( nInv & INV_DIRECTION )
+ pFly->CheckDirChange();
+ }
+ }
+ }
+}
+
+void SwRootFrm::InvalidateAllCntnt( sal_uInt8 nInv )
+{
+ // Erst werden alle Seitengebundenen FlyFrms abgearbeitet.
+ SwPageFrm *pPage = (SwPageFrm*)Lower();
+ while( pPage )
+ {
+ pPage->InvalidateFlyLayout();
+ pPage->InvalidateFlyCntnt();
+ pPage->InvalidateFlyInCnt();
+ pPage->InvalidateLayout();
+ pPage->InvalidateCntnt();
+ pPage->InvalidatePage( pPage ); //Damit ggf. auch der Turbo verschwindet
+
+ if ( pPage->GetSortedObjs() )
+ {
+ const SwSortedObjs &rObjs = *pPage->GetSortedObjs();
+ for ( sal_uInt16 i = 0; i < rObjs.Count(); ++i )
+ {
+ SwAnchoredObject* pAnchoredObj = rObjs[i];
+ if ( pAnchoredObj->ISA(SwFlyFrm) )
+ {
+ SwFlyFrm* pFly = static_cast<SwFlyFrm*>(pAnchoredObj);
+ ::lcl_InvalidateCntnt( pFly->ContainsCntnt(), nInv );
+ if ( nInv & INV_DIRECTION )
+ pFly->CheckDirChange();
+ }
+ }
+ }
+ if( nInv & INV_DIRECTION )
+ pPage->CheckDirChange();
+ pPage = (SwPageFrm*)(pPage->GetNext());
+ }
+
+ //Hier den gesamten Dokumentinhalt und die zeichengebundenen Flys.
+ ::lcl_InvalidateCntnt( ContainsCntnt(), nInv );
+
+ if( nInv & INV_PRTAREA )
+ {
+ ViewShell *pSh = getRootFrm()->GetCurrShell();
+ if( pSh )
+ pSh->InvalidateWindows( Frm() );
+ }
+}
+
+/** method to invalidate/re-calculate the position of all floating
+ screen objects (Writer fly frames and drawing objects), which are
+ anchored to paragraph or to character.
+
+ OD 2004-03-16 #i11860#
+
+ @author OD
+*/
+void SwRootFrm::InvalidateAllObjPos()
+{
+ const SwPageFrm* pPageFrm = static_cast<const SwPageFrm*>(Lower());
+ while( pPageFrm )
+ {
+ pPageFrm->InvalidateFlyLayout();
+
+ if ( pPageFrm->GetSortedObjs() )
+ {
+ const SwSortedObjs& rObjs = *(pPageFrm->GetSortedObjs());
+ for ( sal_uInt8 i = 0; i < rObjs.Count(); ++i )
+ {
+ SwAnchoredObject* pAnchoredObj = rObjs[i];
+ const SwFmtAnchor& rAnch = pAnchoredObj->GetFrmFmt().GetAnchor();
+ if ((rAnch.GetAnchorId() != FLY_AT_PARA) &&
+ (rAnch.GetAnchorId() != FLY_AT_CHAR))
+ {
+ // only to paragraph and to character anchored objects are considered.
+ continue;
+ }
+ // --> OD 2004-07-07 #i28701# - special invalidation for anchored
+ // objects, whose wrapping style influence has to be considered.
+ if ( pAnchoredObj->ConsiderObjWrapInfluenceOnObjPos() )
+ pAnchoredObj->InvalidateObjPosForConsiderWrapInfluence( true );
+ else
+ pAnchoredObj->InvalidateObjPos();
+ // <--
+ }
+ }
+
+ pPageFrm = static_cast<const SwPageFrm*>(pPageFrm->GetNext());
+ }
+}
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/objectpositioning/anchoredobjectposition.cxx b/sw/source/core/objectpositioning/anchoredobjectposition.cxx
new file mode 100644
index 000000000000..251bee71213e
--- /dev/null
+++ b/sw/source/core/objectpositioning/anchoredobjectposition.cxx
@@ -0,0 +1,1100 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+#include <anchoredobjectposition.hxx>
+#ifndef _ENVIRONMENTOFANCHOREDOBJECT
+#include <environmentofanchoredobject.hxx>
+#endif
+#include <flyfrm.hxx>
+#include <flyfrms.hxx>
+#include <txtfrm.hxx>
+#include <pagefrm.hxx>
+#include <frmtool.hxx>
+#include <svx/svdobj.hxx>
+#include <dflyobj.hxx>
+#include <dcontact.hxx>
+#include <frmfmt.hxx>
+#include <fmtornt.hxx>
+// #i62875#
+#include <fmtfollowtextflow.hxx>
+#include <editeng/lrspitem.hxx>
+#include <editeng/ulspitem.hxx>
+#include <ndtxt.hxx>
+#include <IDocumentSettingAccess.hxx>
+
+using namespace ::com::sun::star;
+using namespace objectpositioning;
+
+// **************************************************************************
+// constructor, destructor, initialization
+// **************************************************************************
+SwAnchoredObjectPosition::SwAnchoredObjectPosition( SdrObject& _rDrawObj )
+ : mrDrawObj( _rDrawObj ),
+ mbIsObjFly( false ),
+ mpAnchoredObj( 0 ),
+ mpAnchorFrm( 0 ),
+ mpContact( 0 ),
+ // #i62875#
+ mbFollowTextFlow( false ),
+ mbDoNotCaptureAnchoredObj( false )
+{
+#if OSL_DEBUG_LEVEL > 1
+ // assert, if object isn't of excepted type
+ const bool bObjOfExceptedType =
+ mrDrawObj.ISA(SwVirtFlyDrawObj) || // object representing fly frame
+ mrDrawObj.ISA(SwDrawVirtObj) || // 'virtual' drawing object
+ ( !mrDrawObj.ISA(SdrVirtObj) && // 'master' drawing object
+ !mrDrawObj.ISA(SwFlyDrawObj) ); // - indirectly checked
+ (void) bObjOfExceptedType;
+ OSL_ENSURE( bObjOfExceptedType,
+ "SwAnchoredObjectPosition(..) - object of unexcepted type!" );
+#endif
+
+ _GetInfoAboutObj();
+}
+
+/** determine information about object
+
+ members <mbIsObjFly>, <mpFrmOfObj>, <mpAnchorFrm>, <mpContact>,
+ <mbFollowTextFlow> and <mbDoNotCaptureAnchoredObj> are set
+
+ @author OD
+*/
+void SwAnchoredObjectPosition::_GetInfoAboutObj()
+{
+ // determine, if object represents a fly frame
+ {
+ mbIsObjFly = mrDrawObj.ISA(SwVirtFlyDrawObj);
+ }
+
+ // determine contact object
+ {
+ mpContact = static_cast<SwContact*>(GetUserCall( &mrDrawObj ));
+ OSL_ENSURE( mpContact,
+ "SwAnchoredObjectPosition::_GetInfoAboutObj() - missing SwContact-object." );
+ }
+
+ // determine anchored object, the object belongs to
+ {
+ // #i26791#
+ mpAnchoredObj = mpContact->GetAnchoredObj( &mrDrawObj );
+ OSL_ENSURE( mpAnchoredObj,
+ "SwAnchoredObjectPosition::_GetInfoAboutObj() - missing anchored object." );
+ }
+
+ // determine frame, the object is anchored at
+ {
+ // #i26791#
+ mpAnchorFrm = mpAnchoredObj->AnchorFrm();
+ OSL_ENSURE( mpAnchorFrm,
+ "SwAnchoredObjectPosition::_GetInfoAboutObj() - missing anchor frame." );
+ }
+
+ // determine format the object belongs to
+ {
+ // #i28701#
+ mpFrmFmt = &mpAnchoredObj->GetFrmFmt();
+ OSL_ENSURE( mpFrmFmt,
+ "<SwAnchoredObjectPosition::_GetInfoAboutObj() - missing frame format." );
+ }
+
+ // #i62875# - determine attribute value of <Follow-Text-Flow>
+ {
+ mbFollowTextFlow = mpFrmFmt->GetFollowTextFlow().GetValue();
+ }
+
+ // determine, if anchored object has not to be captured on the page.
+ // the following conditions must be hold to *not* capture it:
+ // - corresponding document compatibility flag is set
+ // - it's a drawing object
+ // - it doesn't follow the text flow
+ {
+ mbDoNotCaptureAnchoredObj = !mbIsObjFly && !mbFollowTextFlow &&
+ mpFrmFmt->getIDocumentSettingAccess()->get(IDocumentSettingAccess::DO_NOT_CAPTURE_DRAW_OBJS_ON_PAGE);
+ }
+}
+
+SwAnchoredObjectPosition::~SwAnchoredObjectPosition()
+{}
+
+bool SwAnchoredObjectPosition::IsAnchoredToChar() const
+{
+ return false;
+}
+
+const SwFrm* SwAnchoredObjectPosition::ToCharOrientFrm() const
+{
+ return NULL;
+}
+
+const SwRect* SwAnchoredObjectPosition::ToCharRect() const
+{
+ return NULL;
+}
+
+// #i22341#
+SwTwips SwAnchoredObjectPosition::ToCharTopOfLine() const
+{
+ return 0L;
+}
+
+/** helper method to determine top of a frame for the vertical
+ object positioning
+
+ #i11860#
+
+ @author OD
+*/
+SwTwips SwAnchoredObjectPosition::_GetTopForObjPos( const SwFrm& _rFrm,
+ const SwRectFn& _fnRect,
+ const bool _bVert ) const
+{
+ SwTwips nTopOfFrmForObjPos = (_rFrm.Frm().*_fnRect->fnGetTop)();
+
+ if ( _rFrm.IsTxtFrm() )
+ {
+ const SwTxtFrm& rTxtFrm = static_cast<const SwTxtFrm&>(_rFrm);
+ if ( _bVert )
+ {
+ nTopOfFrmForObjPos -=
+ rTxtFrm.GetUpperSpaceAmountConsideredForPrevFrmAndPageGrid();
+ }
+ else
+ {
+ nTopOfFrmForObjPos +=
+ rTxtFrm.GetUpperSpaceAmountConsideredForPrevFrmAndPageGrid();
+ }
+ }
+
+ return nTopOfFrmForObjPos;
+}
+
+void SwAnchoredObjectPosition::_GetVertAlignmentValues(
+ const SwFrm& _rVertOrientFrm,
+ const SwFrm& _rPageAlignLayFrm,
+ const sal_Int16 _eRelOrient,
+ SwTwips& _orAlignAreaHeight,
+ SwTwips& _orAlignAreaOffset ) const
+{
+ SwTwips nHeight = 0;
+ SwTwips nOffset = 0;
+ SWRECTFN( (&_rVertOrientFrm) )
+ // #i11860# - top of <_rVertOrientFrm> for object positioning
+ const SwTwips nVertOrientTop = _GetTopForObjPos( _rVertOrientFrm, fnRect, bVert );
+ // #i11860# - upper space amount of <_rVertOrientFrm> considered
+ // for previous frame
+ const SwTwips nVertOrientUpperSpaceForPrevFrmAndPageGrid =
+ _rVertOrientFrm.IsTxtFrm()
+ ? static_cast<const SwTxtFrm&>(_rVertOrientFrm).
+ GetUpperSpaceAmountConsideredForPrevFrmAndPageGrid()
+ : 0;
+ switch ( _eRelOrient )
+ {
+ case text::RelOrientation::FRAME:
+ {
+ // #i11860# - consider upper space of previous frame
+ nHeight = (_rVertOrientFrm.Frm().*fnRect->fnGetHeight)() -
+ nVertOrientUpperSpaceForPrevFrmAndPageGrid;
+ nOffset = 0;
+ }
+ break;
+ case text::RelOrientation::PRINT_AREA:
+ {
+ nHeight = (_rVertOrientFrm.Prt().*fnRect->fnGetHeight)();
+ // #i11860# - consider upper space of previous frame
+ nOffset = (_rVertOrientFrm.*fnRect->fnGetTopMargin)() -
+ nVertOrientUpperSpaceForPrevFrmAndPageGrid;
+ // if aligned to page in horizontal layout, consider header and
+ // footer frame height appropriately.
+ if( _rVertOrientFrm.IsPageFrm() && !bVert )
+ {
+ const SwFrm* pPrtFrm =
+ static_cast<const SwPageFrm&>(_rVertOrientFrm).Lower();
+ while( pPrtFrm )
+ {
+ if( pPrtFrm->IsHeaderFrm() )
+ {
+ nHeight -= pPrtFrm->Frm().Height();
+ nOffset += pPrtFrm->Frm().Height();
+ }
+ else if( pPrtFrm->IsFooterFrm() )
+ {
+ nHeight -= pPrtFrm->Frm().Height();
+ }
+ pPrtFrm = pPrtFrm->GetNext();
+ }
+ }
+ }
+ break;
+ case text::RelOrientation::PAGE_FRAME:
+ {
+ nHeight = (_rPageAlignLayFrm.Frm().*fnRect->fnGetHeight)();
+ nOffset = (*fnRect->fnYDiff)(
+ (_rPageAlignLayFrm.Frm().*fnRect->fnGetTop)(),
+ nVertOrientTop );
+ }
+ break;
+ case text::RelOrientation::PAGE_PRINT_AREA:
+ {
+ nHeight = (_rPageAlignLayFrm.Prt().*fnRect->fnGetHeight)();
+ nOffset = (_rPageAlignLayFrm.*fnRect->fnGetTopMargin)() +
+ (*fnRect->fnYDiff)(
+ (_rPageAlignLayFrm.Frm().*fnRect->fnGetTop)(),
+ nVertOrientTop );
+ // if aligned to page in horizontal layout, consider header and
+ // footer frame height appropriately.
+ if( _rPageAlignLayFrm.IsPageFrm() && !bVert )
+ {
+ const SwFrm* pPrtFrm =
+ static_cast<const SwPageFrm&>(_rPageAlignLayFrm).Lower();
+ while( pPrtFrm )
+ {
+ if( pPrtFrm->IsHeaderFrm() )
+ {
+ nHeight -= pPrtFrm->Frm().Height();
+ nOffset += pPrtFrm->Frm().Height();
+ }
+ else if( pPrtFrm->IsFooterFrm() )
+ {
+ nHeight -= pPrtFrm->Frm().Height();
+ }
+ pPrtFrm = pPrtFrm->GetNext();
+ }
+ }
+ }
+ break;
+ // #i22341# - vertical alignment at top of line
+ case text::RelOrientation::TEXT_LINE:
+ {
+ if ( IsAnchoredToChar() )
+ {
+ nHeight = 0;
+ nOffset = (*fnRect->fnYDiff)( ToCharTopOfLine(), nVertOrientTop );
+ }
+ else
+ {
+ OSL_FAIL( "<SwAnchoredObjectPosition::_GetVertAlignmentValues(..)> - invalid relative alignment" );
+ }
+ }
+ break;
+ case text::RelOrientation::CHAR:
+ {
+ if ( IsAnchoredToChar() )
+ {
+ nHeight = (ToCharRect()->*fnRect->fnGetHeight)();
+ nOffset = (*fnRect->fnYDiff)( (ToCharRect()->*fnRect->fnGetTop)(),
+ nVertOrientTop );
+ }
+ else
+ {
+ OSL_FAIL( "<SwAnchoredObjectPosition::_GetVertAlignmentValues(..)> - invalid relative alignment" );
+ }
+ }
+ break;
+ // no break here, because text::RelOrientation::CHAR is invalid, if !mbAnchorToChar
+ default:
+ {
+ OSL_FAIL( "<SwAnchoredObjectPosition::_GetVertAlignmentValues(..)> - invalid relative alignment" );
+ }
+ }
+
+ _orAlignAreaHeight = nHeight;
+ _orAlignAreaOffset = nOffset;
+}
+
+// #i26791# - add output parameter <_roVertOffsetToFrmAnchorPos>
+SwTwips SwAnchoredObjectPosition::_GetVertRelPos(
+ const SwFrm& _rVertOrientFrm,
+ const SwFrm& _rPageAlignLayFrm,
+ const sal_Int16 _eVertOrient,
+ const sal_Int16 _eRelOrient,
+ const SwTwips _nVertPos,
+ const SvxLRSpaceItem& _rLRSpacing,
+ const SvxULSpaceItem& _rULSpacing,
+ SwTwips& _roVertOffsetToFrmAnchorPos ) const
+{
+ SwTwips nRelPosY = 0;
+ SWRECTFN( (&_rVertOrientFrm) );
+
+ SwTwips nAlignAreaHeight;
+ SwTwips nAlignAreaOffset;
+ _GetVertAlignmentValues( _rVertOrientFrm, _rPageAlignLayFrm,
+ _eRelOrient, nAlignAreaHeight, nAlignAreaOffset );
+
+ nRelPosY = nAlignAreaOffset;
+ const SwRect aObjBoundRect( GetAnchoredObj().GetObjRect() );
+ const SwTwips nObjHeight = (aObjBoundRect.*fnRect->fnGetHeight)();
+
+ switch ( _eVertOrient )
+ {
+ case text::VertOrientation::NONE:
+ {
+ // 'manual' vertical position
+ nRelPosY += _nVertPos;
+ }
+ break;
+ case text::VertOrientation::TOP:
+ {
+ //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin
+ nRelPosY += bVert
+ ? ( bVertL2R
+ ? _rLRSpacing.GetLeft()
+ : _rLRSpacing.GetRight() )
+ : _rULSpacing.GetUpper();
+ }
+ break;
+ case text::VertOrientation::CENTER:
+ {
+ nRelPosY += (nAlignAreaHeight / 2) - (nObjHeight / 2);
+ }
+ break;
+ case text::VertOrientation::BOTTOM:
+ {
+ //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin
+ nRelPosY += nAlignAreaHeight -
+ ( nObjHeight + ( bVert
+ ? ( bVertL2R
+ ? _rLRSpacing.GetRight()
+ : _rLRSpacing.GetLeft() )
+ : _rULSpacing.GetLower() ) );
+ }
+ break;
+ default:
+ {
+ OSL_FAIL( "<SwAnchoredObjectPosition::_GetVertRelPos(..) - invalid vertical positioning" );
+ }
+ }
+
+ // #i26791#
+ _roVertOffsetToFrmAnchorPos = nAlignAreaOffset;
+
+ return nRelPosY;
+}
+
+/** adjust calculated vertical in order to keep object inside
+ 'page' alignment layout frame.
+
+ #i28701# - parameter <_nTopOfAnch> and <_bVert> added
+ #i31805# - add parameter <_bCheckBottom>
+ #i26945# - add parameter <_bFollowTextFlow>
+ #i62875# - method now private and renamed.
+ OD 2009-09-01 #mongolianlayout# - add parameter <bVertL2R>
+
+ @author OD
+*/
+SwTwips SwAnchoredObjectPosition::_ImplAdjustVertRelPos( const SwTwips nTopOfAnch,
+ const bool bVert,
+ const bool bVertL2R,
+ const SwFrm& rPageAlignLayFrm,
+ const SwTwips nProposedRelPosY,
+ const bool bFollowTextFlow,
+ const bool bCheckBottom ) const
+{
+ SwTwips nAdjustedRelPosY = nProposedRelPosY;
+
+ const Size aObjSize( GetAnchoredObj().GetObjRect().SSize() );
+
+ // determine the area of 'page' alignment frame, to which the vertical
+ // position is restricted.
+ // #i28701# - Extend restricted area for the vertical
+ // position to area of the page frame, if wrapping style influence is
+ // considered on object positioning. Needed to avoid layout loops in the
+ // object positioning algorithm considering the wrapping style influence
+ // caused by objects, which follow the text flow and thus are restricted
+ // to its environment (e.g. page header/footer).
+ SwRect aPgAlignArea;
+ {
+ // #i26945# - no extension of restricted area, if
+ // object's attribute follow text flow is set and its inside a table
+ if ( GetFrmFmt().getIDocumentSettingAccess()->get(IDocumentSettingAccess::CONSIDER_WRAP_ON_OBJECT_POSITION) &&
+ ( !bFollowTextFlow ||
+ !GetAnchoredObj().GetAnchorFrm()->IsInTab() ) )
+ {
+ aPgAlignArea = rPageAlignLayFrm.FindPageFrm()->Frm();
+ }
+ else
+ {
+ aPgAlignArea = rPageAlignLayFrm.Frm();
+ }
+ }
+
+ if ( bVert )
+ {
+ // #i31805# - consider value of <_bCheckBottom>
+ if ( !bVertL2R )
+ // <--
+ {
+ if ( bCheckBottom &&
+ nTopOfAnch - nAdjustedRelPosY - aObjSize.Width() <
+ aPgAlignArea.Left() )
+ {
+ nAdjustedRelPosY = aPgAlignArea.Left() +
+ nTopOfAnch -
+ aObjSize.Width();
+ }
+ // #i32964# - correction
+ if ( nTopOfAnch - nAdjustedRelPosY > aPgAlignArea.Right() )
+ {
+ nAdjustedRelPosY = nTopOfAnch - aPgAlignArea.Right();
+ }
+ }
+ else
+ {
+ if ( bCheckBottom &&
+ nTopOfAnch + nAdjustedRelPosY + aObjSize.Width() >
+ aPgAlignArea.Right() )
+ {
+ nAdjustedRelPosY = aPgAlignArea.Right() -
+ nTopOfAnch -
+ aObjSize.Width();
+ }
+ if ( nTopOfAnch + nAdjustedRelPosY < aPgAlignArea.Left() )
+ {
+ nAdjustedRelPosY = aPgAlignArea.Left() - nTopOfAnch;
+ }
+ }
+ }
+ else
+ {
+ // #i31805# - consider value of <bCheckBottom>
+ if ( bCheckBottom &&
+ nTopOfAnch + nAdjustedRelPosY + aObjSize.Height() >
+ aPgAlignArea.Top() + aPgAlignArea.Height() )
+ {
+ nAdjustedRelPosY = aPgAlignArea.Top() + aPgAlignArea.Height() -
+ nTopOfAnch -
+ aObjSize.Height();
+ }
+ if ( nTopOfAnch + nAdjustedRelPosY < aPgAlignArea.Top() )
+ {
+ nAdjustedRelPosY = aPgAlignArea.Top() - nTopOfAnch;
+ }
+ }
+
+ return nAdjustedRelPosY;
+}
+
+/** adjust calculated horizontal in order to keep object inside
+ 'page' alignment layout frame.
+
+ #i62875# - method now private and renamed.
+
+ @author OD
+*/
+SwTwips SwAnchoredObjectPosition::_ImplAdjustHoriRelPos(
+ const SwFrm& _rPageAlignLayFrm,
+ const SwTwips _nProposedRelPosX ) const
+{
+ SwTwips nAdjustedRelPosX = _nProposedRelPosX;
+
+ const SwFrm& rAnchorFrm = GetAnchorFrm();
+ const bool bVert = rAnchorFrm.IsVertical();
+
+ const Size aObjSize( GetAnchoredObj().GetObjRect().SSize() );
+
+ if( bVert )
+ {
+ if ( rAnchorFrm.Frm().Top() + nAdjustedRelPosX + aObjSize.Height() >
+ _rPageAlignLayFrm.Frm().Bottom() )
+ {
+ nAdjustedRelPosX = _rPageAlignLayFrm.Frm().Bottom() -
+ rAnchorFrm.Frm().Top() -
+ aObjSize.Height();
+ }
+ if ( rAnchorFrm.Frm().Top() + nAdjustedRelPosX <
+ _rPageAlignLayFrm.Frm().Top() )
+ {
+ nAdjustedRelPosX = _rPageAlignLayFrm.Frm().Top() -
+ rAnchorFrm.Frm().Top();
+ }
+ }
+ else
+ {
+ if ( rAnchorFrm.Frm().Left() + nAdjustedRelPosX + aObjSize.Width() >
+ _rPageAlignLayFrm.Frm().Right() )
+ {
+ nAdjustedRelPosX = _rPageAlignLayFrm.Frm().Right() -
+ rAnchorFrm.Frm().Left() -
+ aObjSize.Width();
+ }
+ if ( rAnchorFrm.Frm().Left() + nAdjustedRelPosX <
+ _rPageAlignLayFrm.Frm().Left() )
+ {
+ nAdjustedRelPosX = _rPageAlignLayFrm.Frm().Left() -
+ rAnchorFrm.Frm().Left();
+ }
+ }
+
+ return nAdjustedRelPosX;
+}
+
+/** determine alignment value for horizontal position of object
+
+ @author OD
+*/
+void SwAnchoredObjectPosition::_GetHoriAlignmentValues( const SwFrm& _rHoriOrientFrm,
+ const SwFrm& _rPageAlignLayFrm,
+ const sal_Int16 _eRelOrient,
+ const bool _bObjWrapThrough,
+ SwTwips& _orAlignAreaWidth,
+ SwTwips& _orAlignAreaOffset,
+ bool& _obAlignedRelToPage ) const
+{
+ SwTwips nWidth = 0;
+ SwTwips nOffset = 0;
+ SWRECTFN( (&_rHoriOrientFrm) )
+ switch ( _eRelOrient )
+ {
+ case text::RelOrientation::PRINT_AREA:
+ {
+ nWidth = (_rHoriOrientFrm.Prt().*fnRect->fnGetWidth)();
+ nOffset = (_rHoriOrientFrm.*fnRect->fnGetLeftMargin)();
+ if ( _rHoriOrientFrm.IsTxtFrm() )
+ {
+ // consider movement of text frame left
+ nOffset += static_cast<const SwTxtFrm&>(_rHoriOrientFrm).GetBaseOfstForFly( !_bObjWrapThrough );
+ }
+ else if ( _rHoriOrientFrm.IsPageFrm() && bVert )
+ {
+ // for to-page anchored objects, consider header/footer frame
+ // in vertical layout
+ const SwFrm* pPrtFrm =
+ static_cast<const SwPageFrm&>(_rHoriOrientFrm).Lower();
+ while( pPrtFrm )
+ {
+ if( pPrtFrm->IsHeaderFrm() )
+ {
+ nWidth -= pPrtFrm->Frm().Height();
+ nOffset += pPrtFrm->Frm().Height();
+ }
+ else if( pPrtFrm->IsFooterFrm() )
+ {
+ nWidth -= pPrtFrm->Frm().Height();
+ }
+ pPrtFrm = pPrtFrm->GetNext();
+ }
+ }
+ break;
+ }
+ case text::RelOrientation::PAGE_LEFT:
+ {
+ // align at left border of page frame/fly frame/cell frame
+ nWidth = (_rPageAlignLayFrm.*fnRect->fnGetLeftMargin)();
+ nOffset = (*fnRect->fnXDiff)(
+ (_rPageAlignLayFrm.Frm().*fnRect->fnGetLeft)(),
+ (_rHoriOrientFrm.Frm().*fnRect->fnGetLeft)() );
+ _obAlignedRelToPage = true;
+ }
+ break;
+ case text::RelOrientation::PAGE_RIGHT:
+ {
+ // align at right border of page frame/fly frame/cell frame
+ nWidth = (_rPageAlignLayFrm.*fnRect->fnGetRightMargin)();
+ nOffset = (*fnRect->fnXDiff)(
+ (_rPageAlignLayFrm.*fnRect->fnGetPrtRight)(),
+ (_rHoriOrientFrm.Frm().*fnRect->fnGetLeft)() );
+ _obAlignedRelToPage = true;
+ }
+ break;
+ case text::RelOrientation::FRAME_LEFT:
+ {
+ // align at left border of anchor frame
+ nWidth = (_rHoriOrientFrm.*fnRect->fnGetLeftMargin)();
+ nOffset = 0;
+ }
+ break;
+ case text::RelOrientation::FRAME_RIGHT:
+ {
+ // align at right border of anchor frame
+ // Unify and simplify
+ nWidth = (_rHoriOrientFrm.*fnRect->fnGetRightMargin)();
+ nOffset = (_rHoriOrientFrm.Prt().*fnRect->fnGetRight)();
+ }
+ break;
+ case text::RelOrientation::CHAR:
+ {
+ // alignment relative to character - assure, that corresponding
+ // character rectangle is set.
+ if ( IsAnchoredToChar() )
+ {
+ nWidth = 0;
+ nOffset = (*fnRect->fnXDiff)(
+ (ToCharRect()->*fnRect->fnGetLeft)(),
+ (ToCharOrientFrm()->Frm().*fnRect->fnGetLeft)() );
+ break;
+ }
+ // no break!
+ }
+ case text::RelOrientation::PAGE_PRINT_AREA:
+ {
+ nWidth = (_rPageAlignLayFrm.Prt().*fnRect->fnGetWidth)();
+ nOffset = (*fnRect->fnXDiff)(
+ (_rPageAlignLayFrm.*fnRect->fnGetPrtLeft)(),
+ (_rHoriOrientFrm.Frm().*fnRect->fnGetLeft)() );
+ if ( _rHoriOrientFrm.IsPageFrm() && bVert )
+ {
+ // for to-page anchored objects, consider header/footer frame
+ // in vertical layout
+ const SwFrm* pPrtFrm =
+ static_cast<const SwPageFrm&>(_rHoriOrientFrm).Lower();
+ while( pPrtFrm )
+ {
+ if( pPrtFrm->IsHeaderFrm() )
+ {
+ nWidth -= pPrtFrm->Frm().Height();
+ nOffset += pPrtFrm->Frm().Height();
+ }
+ else if( pPrtFrm->IsFooterFrm() )
+ {
+ nWidth -= pPrtFrm->Frm().Height();
+ }
+ pPrtFrm = pPrtFrm->GetNext();
+ }
+ }
+ _obAlignedRelToPage = true;
+ break;
+ }
+ case text::RelOrientation::PAGE_FRAME:
+ {
+ nWidth = (_rPageAlignLayFrm.Frm().*fnRect->fnGetWidth)();
+ nOffset = (*fnRect->fnXDiff)(
+ (_rPageAlignLayFrm.Frm().*fnRect->fnGetLeft)(),
+ (_rHoriOrientFrm.Frm().*fnRect->fnGetLeft)() );
+ _obAlignedRelToPage = true;
+ break;
+ }
+ default:
+ {
+ nWidth = (_rHoriOrientFrm.Frm().*fnRect->fnGetWidth)();
+ nOffset = _rHoriOrientFrm.IsTxtFrm() ?
+ static_cast<const SwTxtFrm&>(_rHoriOrientFrm).GetBaseOfstForFly( !_bObjWrapThrough ) :
+ 0;
+ break;
+ }
+ }
+
+ _orAlignAreaWidth = nWidth;
+ _orAlignAreaOffset = nOffset;
+}
+
+/** toggle given horizontal orientation and relative alignment
+
+ @author OD
+*/
+void SwAnchoredObjectPosition::_ToggleHoriOrientAndAlign(
+ const bool _bToggleLeftRight,
+ sal_Int16& _ioeHoriOrient,
+ sal_Int16& _iopeRelOrient
+ ) const
+{
+ if( _bToggleLeftRight )
+ {
+ // toggle orientation
+ switch ( _ioeHoriOrient )
+ {
+ case text::HoriOrientation::RIGHT :
+ {
+ _ioeHoriOrient = text::HoriOrientation::LEFT;
+ }
+ break;
+ case text::HoriOrientation::LEFT :
+ {
+ _ioeHoriOrient = text::HoriOrientation::RIGHT;
+ }
+ break;
+ default:
+ break;
+ }
+
+ // toggle relative alignment
+ switch ( _iopeRelOrient )
+ {
+ case text::RelOrientation::PAGE_RIGHT :
+ {
+ _iopeRelOrient = text::RelOrientation::PAGE_LEFT;
+ }
+ break;
+ case text::RelOrientation::PAGE_LEFT :
+ {
+ _iopeRelOrient = text::RelOrientation::PAGE_RIGHT;
+ }
+ break;
+ case text::RelOrientation::FRAME_RIGHT :
+ {
+ _iopeRelOrient = text::RelOrientation::FRAME_LEFT;
+ }
+ break;
+ case text::RelOrientation::FRAME_LEFT :
+ {
+ _iopeRelOrient = text::RelOrientation::FRAME_RIGHT;
+ }
+ break;
+ default:
+ break;
+ }
+ }
+}
+
+/** calculate relative horizontal position
+
+ @author OD
+*/
+SwTwips SwAnchoredObjectPosition::_CalcRelPosX(
+ const SwFrm& _rHoriOrientFrm,
+ const SwEnvironmentOfAnchoredObject& _rEnvOfObj,
+ const SwFmtHoriOrient& _rHoriOrient,
+ const SvxLRSpaceItem& _rLRSpacing,
+ const SvxULSpaceItem& _rULSpacing,
+ const bool _bObjWrapThrough,
+ const SwTwips _nRelPosY,
+ SwTwips& _roHoriOffsetToFrmAnchorPos
+ ) const
+{
+ // determine 'page' alignment layout frame
+ const SwFrm& rPageAlignLayFrm =
+ _rEnvOfObj.GetHoriEnvironmentLayoutFrm( _rHoriOrientFrm );
+
+ const bool bEvenPage = !rPageAlignLayFrm.OnRightPage();
+ const bool bToggle = _rHoriOrient.IsPosToggle() && bEvenPage;
+
+ // determine orientation and relative alignment
+ sal_Int16 eHoriOrient = _rHoriOrient.GetHoriOrient();
+ sal_Int16 eRelOrient = _rHoriOrient.GetRelationOrient();
+ // toggle orientation and relative alignment
+ _ToggleHoriOrientAndAlign( bToggle, eHoriOrient, eRelOrient );
+
+ // determine alignment parameter
+ // <nWidth>: 'width' of alignment area
+ // <nOffset>: offset of alignment area, relative to 'left' of anchor frame
+ SwTwips nWidth = 0;
+ SwTwips nOffset = 0;
+ bool bAlignedRelToPage = false;
+ _GetHoriAlignmentValues( _rHoriOrientFrm, rPageAlignLayFrm,
+ eRelOrient, _bObjWrapThrough,
+ nWidth, nOffset, bAlignedRelToPage );
+
+ const SwFrm& rAnchorFrm = GetAnchorFrm();
+ SWRECTFN( (&_rHoriOrientFrm) )
+ SwTwips nObjWidth = (GetAnchoredObj().GetObjRect().*fnRect->fnGetWidth)();
+ SwTwips nRelPosX = nOffset;
+ if ( _rHoriOrient.GetHoriOrient() == text::HoriOrientation::NONE )
+ {
+ // 'manual' horizonal position
+ const bool bR2L = rAnchorFrm.IsRightToLeft();
+ if( IsAnchoredToChar() && text::RelOrientation::CHAR == eRelOrient )
+ {
+ if( bR2L )
+ nRelPosX -= _rHoriOrient.GetPos();
+ else
+ nRelPosX += _rHoriOrient.GetPos();
+ }
+ else if ( bToggle || ( !_rHoriOrient.IsPosToggle() && bR2L ) )
+ {
+ // Correction: consider <nOffset> also for
+ // toggling from left to right.
+ nRelPosX += nWidth - nObjWidth - _rHoriOrient.GetPos();
+ }
+ else
+ {
+ nRelPosX += _rHoriOrient.GetPos();
+ }
+ }
+ else if ( text::HoriOrientation::CENTER == eHoriOrient )
+ nRelPosX += (nWidth / 2) - (nObjWidth / 2);
+ else if ( text::HoriOrientation::RIGHT == eHoriOrient )
+ nRelPosX += nWidth -
+ ( nObjWidth +
+ ( bVert ? _rULSpacing.GetLower() : _rLRSpacing.GetRight() ) );
+ else
+ nRelPosX += bVert ? _rULSpacing.GetUpper() : _rLRSpacing.GetLeft();
+
+ // adjust relative position by distance between anchor frame and
+ // the frame, the object is oriented at.
+ if ( &rAnchorFrm != &_rHoriOrientFrm )
+ {
+ SwTwips nLeftOrient = (_rHoriOrientFrm.Frm().*fnRect->fnGetLeft)();
+ SwTwips nLeftAnchor = (rAnchorFrm.Frm().*fnRect->fnGetLeft)();
+ nRelPosX += (*fnRect->fnXDiff)( nLeftOrient, nLeftAnchor );
+ }
+
+ // adjust calculated relative horizontal position, in order to
+ // keep object inside 'page' alignment layout frame
+ const SwFrm& rEnvironmentLayFrm =
+ _rEnvOfObj.GetHoriEnvironmentLayoutFrm( _rHoriOrientFrm );
+ nRelPosX = _AdjustHoriRelPos( rEnvironmentLayFrm, nRelPosX );
+
+ // if object is a Writer fly frame and it's anchored to a content and
+ // it is horizontal positioned left or right, but not relative to character,
+ // it has to be drawn aside another object, which have the same horizontal
+ // position and lay below it.
+ if ( GetAnchoredObj().ISA(SwFlyFrm) &&
+ ( GetContact().ObjAnchoredAtPara() || GetContact().ObjAnchoredAtChar() ) &&
+ ( eHoriOrient == text::HoriOrientation::LEFT || eHoriOrient == text::HoriOrientation::RIGHT ) &&
+ eRelOrient != text::RelOrientation::CHAR )
+ {
+ nRelPosX = _AdjustHoriRelPosForDrawAside( _rHoriOrientFrm,
+ nRelPosX, _nRelPosY,
+ eHoriOrient, eRelOrient,
+ _rLRSpacing, _rULSpacing,
+ bEvenPage );
+ }
+
+ // #i26791#
+ _roHoriOffsetToFrmAnchorPos = nOffset;
+
+ return nRelPosX;
+}
+
+// **************************************************************************
+// method incl. helper methods for adjusting proposed horizontal position,
+// if object has to draw aside another object.
+// **************************************************************************
+/** adjust calculated horizontal position in order to draw object
+ aside other objects with same positioning
+
+ @author OD
+*/
+SwTwips SwAnchoredObjectPosition::_AdjustHoriRelPosForDrawAside(
+ const SwFrm& _rHoriOrientFrm,
+ const SwTwips _nProposedRelPosX,
+ const SwTwips _nRelPosY,
+ const sal_Int16 _eHoriOrient,
+ const sal_Int16 _eRelOrient,
+ const SvxLRSpaceItem& _rLRSpacing,
+ const SvxULSpaceItem& _rULSpacing,
+ const bool _bEvenPage
+ ) const
+{
+ // #i26791#
+ if ( !GetAnchorFrm().ISA(SwTxtFrm) ||
+ !GetAnchoredObj().ISA(SwFlyAtCntFrm) )
+ {
+ OSL_FAIL( "<SwAnchoredObjectPosition::_AdjustHoriRelPosForDrawAside(..) - usage for wrong anchor type" );
+ return _nProposedRelPosX;
+ }
+
+ const SwTxtFrm& rAnchorTxtFrm = static_cast<const SwTxtFrm&>(GetAnchorFrm());
+ // #i26791#
+ const SwFlyAtCntFrm& rFlyAtCntFrm =
+ static_cast<const SwFlyAtCntFrm&>(GetAnchoredObj());
+ const SwRect aObjBoundRect( GetAnchoredObj().GetObjRect() );
+ SWRECTFN( (&_rHoriOrientFrm) )
+
+ SwTwips nAdjustedRelPosX = _nProposedRelPosX;
+
+ // determine proposed object bound rectangle
+ Point aTmpPos = (rAnchorTxtFrm.Frm().*fnRect->fnGetPos)();
+ if( bVert )
+ {
+ aTmpPos.X() -= _nRelPosY + aObjBoundRect.Width();
+ aTmpPos.Y() += nAdjustedRelPosX;
+ }
+ else
+ {
+ aTmpPos.X() += nAdjustedRelPosX;
+ aTmpPos.Y() += _nRelPosY;
+ }
+ SwRect aTmpObjRect( aTmpPos, aObjBoundRect.SSize() );
+
+ const sal_uInt32 nObjOrdNum = GetObject().GetOrdNum();
+ const SwPageFrm* pObjPage = rFlyAtCntFrm.FindPageFrm();
+ const SwFrm* pObjContext = ::FindKontext( &rAnchorTxtFrm, FRM_COLUMN );
+ sal_uLong nObjIndex = rAnchorTxtFrm.GetTxtNode()->GetIndex();
+ SwOrderIter aIter( pObjPage, sal_True );
+ const SwFlyFrm* pFly = ((SwVirtFlyDrawObj*)aIter.Bottom())->GetFlyFrm();
+ while ( pFly && nObjOrdNum > pFly->GetVirtDrawObj()->GetOrdNumDirect() )
+ {
+ if ( _DrawAsideFly( pFly, aTmpObjRect, pObjContext, nObjIndex,
+ _bEvenPage, _eHoriOrient, _eRelOrient ) )
+ {
+ if( bVert )
+ {
+ const SvxULSpaceItem& rOtherUL = pFly->GetFmt()->GetULSpace();
+ const SwTwips nOtherTop = pFly->Frm().Top() - rOtherUL.GetUpper();
+ const SwTwips nOtherBot = pFly->Frm().Bottom() + rOtherUL.GetLower();
+ if ( nOtherTop <= aTmpObjRect.Bottom() + _rULSpacing.GetLower() &&
+ nOtherBot >= aTmpObjRect.Top() - _rULSpacing.GetUpper() )
+ {
+ if ( _eHoriOrient == text::HoriOrientation::LEFT )
+ {
+ SwTwips nTmp = nOtherBot + 1 + _rULSpacing.GetUpper() -
+ rAnchorTxtFrm.Frm().Top();
+ if ( nTmp > nAdjustedRelPosX &&
+ rAnchorTxtFrm.Frm().Top() + nTmp +
+ aObjBoundRect.Height() + _rULSpacing.GetLower()
+ <= pObjPage->Frm().Height() + pObjPage->Frm().Top() )
+ {
+ nAdjustedRelPosX = nTmp;
+ }
+ }
+ else if ( _eHoriOrient == text::HoriOrientation::RIGHT )
+ {
+ SwTwips nTmp = nOtherTop - 1 - _rULSpacing.GetLower() -
+ aObjBoundRect.Height() -
+ rAnchorTxtFrm.Frm().Top();
+ if ( nTmp < nAdjustedRelPosX &&
+ rAnchorTxtFrm.Frm().Top() + nTmp - _rULSpacing.GetUpper()
+ >= pObjPage->Frm().Top() )
+ {
+ nAdjustedRelPosX = nTmp;
+ }
+ }
+ aTmpObjRect.Pos().Y() = rAnchorTxtFrm.Frm().Top() +
+ nAdjustedRelPosX;
+ }
+ }
+ else
+ {
+ const SvxLRSpaceItem& rOtherLR = pFly->GetFmt()->GetLRSpace();
+ const SwTwips nOtherLeft = pFly->Frm().Left() - rOtherLR.GetLeft();
+ const SwTwips nOtherRight = pFly->Frm().Right() + rOtherLR.GetRight();
+ if( nOtherLeft <= aTmpObjRect.Right() + _rLRSpacing.GetRight() &&
+ nOtherRight >= aTmpObjRect.Left() - _rLRSpacing.GetLeft() )
+ {
+ if ( _eHoriOrient == text::HoriOrientation::LEFT )
+ {
+ SwTwips nTmp = nOtherRight + 1 + _rLRSpacing.GetLeft() -
+ rAnchorTxtFrm.Frm().Left();
+ if ( nTmp > nAdjustedRelPosX &&
+ rAnchorTxtFrm.Frm().Left() + nTmp +
+ aObjBoundRect.Width() + _rLRSpacing.GetRight()
+ <= pObjPage->Frm().Width() + pObjPage->Frm().Left() )
+ {
+ nAdjustedRelPosX = nTmp;
+ }
+ }
+ else if ( _eHoriOrient == text::HoriOrientation::RIGHT )
+ {
+ SwTwips nTmp = nOtherLeft - 1 - _rLRSpacing.GetRight() -
+ aObjBoundRect.Width() -
+ rAnchorTxtFrm.Frm().Left();
+ if ( nTmp < nAdjustedRelPosX &&
+ rAnchorTxtFrm.Frm().Left() + nTmp - _rLRSpacing.GetLeft()
+ >= pObjPage->Frm().Left() )
+ {
+ nAdjustedRelPosX = nTmp;
+ }
+ }
+ aTmpObjRect.Pos().X() = rAnchorTxtFrm.Frm().Left() +
+ nAdjustedRelPosX;
+ }
+ } // end of <if (bVert)>
+ } // end of <if _DrawAsideFly(..)>
+
+ pFly = ((SwVirtFlyDrawObj*)aIter.Next())->GetFlyFrm();
+ } // end of <loop on fly frames
+
+ return nAdjustedRelPosX;
+}
+
+/** detemine, if object has to draw aside given fly frame
+
+ method used by <_AdjustHoriRelPosForDrawAside(..)>
+
+ @author OD
+*/
+bool SwAnchoredObjectPosition::_DrawAsideFly( const SwFlyFrm* _pFly,
+ const SwRect& _rObjRect,
+ const SwFrm* _pObjContext,
+ const sal_uLong _nObjIndex,
+ const bool _bEvenPage,
+ const sal_Int16 _eHoriOrient,
+ const sal_Int16 _eRelOrient
+ ) const
+{
+ bool bRetVal = false;
+
+ SWRECTFN( (&GetAnchorFrm()) )
+
+ if ( _pFly->IsFlyAtCntFrm() &&
+ (_pFly->Frm().*fnRect->fnBottomDist)( (_rObjRect.*fnRect->fnGetTop)() ) < 0 &&
+ (_rObjRect.*fnRect->fnBottomDist)( (_pFly->Frm().*fnRect->fnGetTop)() ) < 0 &&
+ ::FindKontext( _pFly->GetAnchorFrm(), FRM_COLUMN ) == _pObjContext )
+ {
+ sal_uLong nOtherIndex =
+ static_cast<const SwTxtFrm*>(_pFly->GetAnchorFrm())->GetTxtNode()->GetIndex();
+ if( _nObjIndex >= nOtherIndex )
+ {
+ const SwFmtHoriOrient& rHori = _pFly->GetFmt()->GetHoriOrient();
+ sal_Int16 eOtherRelOrient = rHori.GetRelationOrient();
+ if( text::RelOrientation::CHAR != eOtherRelOrient )
+ {
+ sal_Int16 eOtherHoriOrient = rHori.GetHoriOrient();
+ _ToggleHoriOrientAndAlign( _bEvenPage && rHori.IsPosToggle(),
+ eOtherHoriOrient,
+ eOtherRelOrient );
+ if ( eOtherHoriOrient == _eHoriOrient &&
+ _Minor( _eRelOrient, eOtherRelOrient, text::HoriOrientation::LEFT == _eHoriOrient ) )
+ {
+ bRetVal = true;
+ }
+ }
+ }
+ }
+
+ return bRetVal;
+}
+
+/** determine, if object has to draw aside another object
+
+ the different alignments of the objects determines, if one has
+ to draw aside another one. Thus, the given alignment are checked
+ against each other, which one has to be drawn aside the other one.
+ depending on parameter _bLeft check is done for left or right
+ positioning.
+ method used by <_DrawAsideFly(..)>
+
+ @author OD
+*/
+bool SwAnchoredObjectPosition::_Minor( sal_Int16 _eRelOrient1,
+ sal_Int16 _eRelOrient2,
+ bool _bLeft ) const
+{
+ bool bRetVal;
+
+ // draw aside order for left horizontal position
+ //! one array entry for each value in text::RelOrientation
+ static sal_uInt16 const aLeft[ 10 ] =
+ { 5, 6, 0, 1, 8, 4, 7, 2, 3, 9 };
+ // draw aside order for right horizontal position
+ //! one array entry for each value in text::RelOrientation
+ static sal_uInt16 const aRight[ 10 ] =
+ { 5, 6, 0, 8, 1, 7, 4, 2, 3, 9 };
+
+ // decide depending on given order, which frame has to draw aside another frame
+ if( _bLeft )
+ bRetVal = aLeft[ _eRelOrient1 ] >= aLeft[ _eRelOrient2 ];
+ else
+ bRetVal = aRight[ _eRelOrient1 ] >= aRight[ _eRelOrient2 ];
+
+ return bRetVal;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/objectpositioning/ascharanchoredobjectposition.cxx b/sw/source/core/objectpositioning/ascharanchoredobjectposition.cxx
new file mode 100644
index 000000000000..a5facaf474b9
--- /dev/null
+++ b/sw/source/core/objectpositioning/ascharanchoredobjectposition.cxx
@@ -0,0 +1,458 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+#include <ascharanchoredobjectposition.hxx>
+#include <frame.hxx>
+#include <txtfrm.hxx>
+#include <flyfrms.hxx>
+#include <svx/svdobj.hxx>
+#include <dcontact.hxx>
+#include <frmfmt.hxx>
+#include <frmatr.hxx>
+#include <editeng/lrspitem.hxx>
+#include <editeng/ulspitem.hxx>
+#include <fmtornt.hxx>
+
+#include <com/sun/star/text/HoriOrientation.hpp>
+
+
+using namespace ::com::sun::star;
+using namespace objectpositioning;
+
+/** constructor
+
+ @author OD
+*/
+SwAsCharAnchoredObjectPosition::SwAsCharAnchoredObjectPosition(
+ SdrObject& _rDrawObj,
+ const Point& _rProposedAnchorPos,
+ const AsCharFlags _nFlags,
+ const SwTwips _nLineAscent,
+ const SwTwips _nLineDescent,
+ const SwTwips _nLineAscentInclObjs,
+ const SwTwips _nLineDescentInclObjs )
+ : SwAnchoredObjectPosition( _rDrawObj ),
+ mrProposedAnchorPos( _rProposedAnchorPos ),
+ mnFlags( _nFlags ),
+ mnLineAscent( _nLineAscent ),
+ mnLineDescent( _nLineDescent ),
+ mnLineAscentInclObjs( _nLineAscentInclObjs ),
+ mnLineDescentInclObjs( _nLineDescentInclObjs ),
+ maAnchorPos ( Point() ),
+ mnRelPos ( 0 ),
+ maObjBoundRect ( SwRect() ),
+ mnLineAlignment ( 0 )
+{}
+
+/** destructor
+
+ @author OD
+*/
+SwAsCharAnchoredObjectPosition::~SwAsCharAnchoredObjectPosition()
+{}
+
+/** method to cast <SwAnchoredObjectPosition::GetAnchorFrm()> to needed type
+
+ @author OD
+*/
+const SwTxtFrm& SwAsCharAnchoredObjectPosition::GetAnchorTxtFrm() const
+{
+ OSL_ENSURE( GetAnchorFrm().ISA(SwTxtFrm),
+ "SwAsCharAnchoredObjectPosition::GetAnchorTxtFrm() - wrong anchor frame type" );
+
+ return static_cast<const SwTxtFrm&>(GetAnchorFrm());
+}
+
+/** calculate position for object
+
+ OD 30.07.2003 #110978#
+ members <maAnchorPos>, <mnRelPos>, <maObjBoundRect> and
+ <mnLineAlignment> are calculated.
+ calculated position is set at the given object.
+
+ @author OD
+*/
+void SwAsCharAnchoredObjectPosition::CalcPosition()
+{
+ const SwTxtFrm& rAnchorFrm = GetAnchorTxtFrm();
+ // swap anchor frame, if swapped. Note: destructor takes care of the 'undo'
+ SwFrmSwapper aFrmSwapper( &rAnchorFrm, false );
+
+ SWRECTFN( ( &rAnchorFrm ) )
+
+ Point aAnchorPos( mrProposedAnchorPos );
+
+ const SwFrmFmt& rFrmFmt = GetFrmFmt();
+
+ SwRect aObjBoundRect( GetAnchoredObj().GetObjRect() );
+ SwTwips nObjWidth = (aObjBoundRect.*fnRect->fnGetWidth)();
+
+ // determine spacing values considering layout-/text-direction
+ const SvxLRSpaceItem& rLRSpace = rFrmFmt.GetLRSpace();
+ const SvxULSpaceItem& rULSpace = rFrmFmt.GetULSpace();
+ SwTwips nLRSpaceLeft, nLRSpaceRight, nULSpaceUpper, nULSpaceLower;
+ {
+ if ( rAnchorFrm.IsVertical() )
+ {
+ // Seems to be easier to do it all the horizontal way
+ // So, from now on think horizontal.
+ rAnchorFrm.SwitchVerticalToHorizontal( aObjBoundRect );
+ rAnchorFrm.SwitchVerticalToHorizontal( aAnchorPos );
+
+ // convert the spacing values
+ nLRSpaceLeft = rULSpace.GetUpper();
+ nLRSpaceRight = rULSpace.GetLower();
+ nULSpaceUpper = rLRSpace.GetRight();
+ nULSpaceLower = rLRSpace.GetLeft();
+ }
+ else
+ {
+ if ( rAnchorFrm.IsRightToLeft() )
+ {
+ nLRSpaceLeft = rLRSpace.GetRight();
+ nLRSpaceRight = rLRSpace.GetLeft();
+ }
+ else
+ {
+ nLRSpaceLeft = rLRSpace.GetLeft();
+ nLRSpaceRight = rLRSpace.GetRight();
+ }
+
+ nULSpaceUpper = rULSpace.GetUpper();
+ nULSpaceLower = rULSpace.GetLower();
+ }
+ }
+
+ // consider left and upper spacing by adjusting anchor position.
+ // left spacing is only considered, if requested.
+ if( mnFlags & AS_CHAR_ULSPACE )
+ {
+ aAnchorPos.X() += nLRSpaceLeft;
+ }
+ aAnchorPos.Y() += nULSpaceUpper;
+
+ // for drawing objects: consider difference between its bounding rectangle
+ // and its snapping rectangle by adjusting anchor position.
+ // left difference is only considered, if requested.
+ if( !IsObjFly() )
+ {
+ SwRect aSnapRect = GetObject().GetSnapRect();
+ if ( rAnchorFrm.IsVertical() )
+ {
+ rAnchorFrm.SwitchVerticalToHorizontal( aSnapRect );
+ }
+
+ if( mnFlags & AS_CHAR_ULSPACE )
+ {
+ aAnchorPos.X() += aSnapRect.Left() - aObjBoundRect.Left();
+ }
+ aAnchorPos.Y() += aSnapRect.Top() - aObjBoundRect.Top();
+ }
+
+ // enlarge bounding rectangle of object by its spacing.
+ aObjBoundRect.Left( aObjBoundRect.Left() - nLRSpaceLeft );
+ aObjBoundRect.Width( aObjBoundRect.Width() + nLRSpaceRight );
+ aObjBoundRect.Top( aObjBoundRect.Top() - nULSpaceUpper );
+ aObjBoundRect.Height( aObjBoundRect.Height() + nULSpaceLower );
+
+ // calculate relative position to given base line.
+ const SwFmtVertOrient& rVert = rFrmFmt.GetVertOrient();
+ const SwTwips nObjBoundHeight = ( mnFlags & AS_CHAR_ROTATE )
+ ? aObjBoundRect.Width()
+ : aObjBoundRect.Height();
+ const SwTwips nRelPos = _GetRelPosToBase( nObjBoundHeight, rVert );
+
+ // for initial positioning:
+ // adjust the proposed anchor position by difference between
+ // calculated relative position to base line and current maximal line ascent.
+ // Note: In the following line formatting the base line will be adjusted
+ // by the same difference.
+ if( mnFlags & AS_CHAR_INIT && nRelPos < 0 && mnLineAscentInclObjs < -nRelPos )
+ {
+ if( mnFlags & AS_CHAR_ROTATE )
+ aAnchorPos.X() -= mnLineAscentInclObjs + nRelPos;
+ else
+ aAnchorPos.Y() -= mnLineAscentInclObjs + nRelPos;
+ }
+
+ // consider BIDI-multiportion by adjusting proposed anchor position
+ if( mnFlags & AS_CHAR_BIDI )
+ aAnchorPos.X() -= aObjBoundRect.Width();
+
+ // calculate relative position considering rotation and inside rotation
+ // reverse direction.
+ Point aRelPos;
+ {
+ if( mnFlags & AS_CHAR_ROTATE )
+ {
+ if( mnFlags & AS_CHAR_REVERSE )
+ aRelPos.X() = -nRelPos - aObjBoundRect.Width();
+ else
+ {
+ aRelPos.X() = nRelPos;
+ aRelPos.Y() = -aObjBoundRect.Height();
+ }
+ }
+ else
+ aRelPos.Y() = nRelPos;
+ }
+
+ if( !IsObjFly() )
+ {
+ if( !( mnFlags & AS_CHAR_QUICK ) )
+ {
+ // save calculated Y-position value for 'automatic' vertical positioning,
+ // in order to avoid a switch to 'manual' vertical positioning in
+ // <SwDrawContact::_Changed(..)>.
+ const sal_Int16 eVertOrient = rVert.GetVertOrient();
+ if( rVert.GetPos() != nRelPos && eVertOrient != text::VertOrientation::NONE )
+ {
+ SwFmtVertOrient aVert( rVert );
+ aVert.SetPos( nRelPos );
+ const_cast<SwFrmFmt&>(rFrmFmt).LockModify();
+ const_cast<SwFrmFmt&>(rFrmFmt).SetFmtAttr( aVert );
+ const_cast<SwFrmFmt&>(rFrmFmt).UnlockModify();
+ }
+
+ // determine absolute anchor position considering layout directions.
+ // Note: Use copy of <aAnchorPos>, because it's needed for
+ // setting relative position.
+ Point aAbsAnchorPos( aAnchorPos );
+ if ( rAnchorFrm.IsRightToLeft() )
+ {
+ rAnchorFrm.SwitchLTRtoRTL( aAbsAnchorPos );
+ aAbsAnchorPos.X() -= nObjWidth;
+ }
+ if ( rAnchorFrm.IsVertical() )
+ rAnchorFrm.SwitchHorizontalToVertical( aAbsAnchorPos );
+
+ // set proposed anchor position at the drawing object.
+ // OD 2004-04-06 #i26791# - distinction between 'master' drawing
+ // object and 'virtual' drawing object no longer needed.
+ GetObject().SetAnchorPos( aAbsAnchorPos );
+
+ // move drawing object to set its correct relative position.
+ {
+ SwRect aSnapRect = GetObject().GetSnapRect();
+ if ( rAnchorFrm.IsVertical() )
+ rAnchorFrm.SwitchVerticalToHorizontal( aSnapRect );
+
+ Point aDiff;
+ if ( rAnchorFrm.IsRightToLeft() )
+ aDiff = aRelPos + aAbsAnchorPos - aSnapRect.TopLeft();
+ else
+ aDiff = aRelPos + aAnchorPos - aSnapRect.TopLeft();
+
+ if ( rAnchorFrm.IsVertical() )
+ aDiff = Point( -aDiff.Y(), aDiff.X() );
+
+ // OD 2004-04-06 #i26791# - distinction between 'master' drawing
+ // object and 'virtual' drawing object no longer needed.
+ GetObject().Move( Size( aDiff.X(), aDiff.Y() ) );
+ }
+ }
+
+ // switch horizontal, LTR anchor position to absolute values.
+ if ( rAnchorFrm.IsRightToLeft() )
+ {
+ rAnchorFrm.SwitchLTRtoRTL( aAnchorPos );
+ aAnchorPos.X() -= nObjWidth;
+ }
+ if ( rAnchorFrm.IsVertical() )
+ rAnchorFrm.SwitchHorizontalToVertical( aAnchorPos );
+
+ // --> OD 2005-03-09 #i44347# - keep last object rectangle at anchored object
+ OSL_ENSURE( GetAnchoredObj().ISA(SwAnchoredDrawObject),
+ "<SwAsCharAnchoredObjectPosition::CalcPosition()> - wrong type of anchored object." );
+ SwAnchoredDrawObject& rAnchoredDrawObj =
+ static_cast<SwAnchoredDrawObject&>( GetAnchoredObj() );
+ rAnchoredDrawObj.SetLastObjRect( rAnchoredDrawObj.GetObjRect().SVRect() );
+ // <--
+ }
+ else
+ {
+ // determine absolute anchor position and calculate corresponding
+ // relative position and its relative position attribute.
+ // Note: The relative position contains the spacing values.
+ Point aRelAttr;
+ if ( rAnchorFrm.IsRightToLeft() )
+ {
+ rAnchorFrm.SwitchLTRtoRTL( aAnchorPos );
+ aAnchorPos.X() -= nObjWidth;
+ }
+ if ( rAnchorFrm.IsVertical() )
+ {
+ rAnchorFrm.SwitchHorizontalToVertical( aAnchorPos );
+ aRelAttr = Point( -nRelPos, 0 );
+ aRelPos = Point( -aRelPos.Y(), aRelPos.X() );
+ }
+ else
+ aRelAttr = Point( 0, nRelPos );
+
+ // OD 2004-03-23 #i26791#
+ OSL_ENSURE( GetAnchoredObj().ISA(SwFlyInCntFrm),
+ "<SwAsCharAnchoredObjectPosition::CalcPosition()> - wrong anchored object." );
+ const SwFlyInCntFrm& rFlyInCntFrm =
+ static_cast<const SwFlyInCntFrm&>(GetAnchoredObj());
+ if ( !(mnFlags & AS_CHAR_QUICK) &&
+ ( aAnchorPos != rFlyInCntFrm.GetRefPoint() ||
+ aRelAttr != rFlyInCntFrm.GetCurrRelPos() ) )
+ {
+ // set new anchor position and relative position
+ SwFlyInCntFrm* pFlyInCntFrm = &(const_cast<SwFlyInCntFrm&>(rFlyInCntFrm));
+ pFlyInCntFrm->SetRefPoint( aAnchorPos, aRelAttr, aRelPos );
+ if( nObjWidth != (pFlyInCntFrm->Frm().*fnRect->fnGetWidth)() )
+ {
+ // recalculate object bound rectangle, if object width has changed.
+ aObjBoundRect = GetAnchoredObj().GetObjRect();
+ aObjBoundRect.Left( aObjBoundRect.Left() - rLRSpace.GetLeft() );
+ aObjBoundRect.Width( aObjBoundRect.Width() + rLRSpace.GetRight() );
+ aObjBoundRect.Top( aObjBoundRect.Top() - rULSpace.GetUpper() );
+ aObjBoundRect.Height( aObjBoundRect.Height() + rULSpace.GetLower() );
+ }
+ }
+ OSL_ENSURE( (rFlyInCntFrm.Frm().*fnRect->fnGetHeight)(),
+ "SwAnchoredObjectPosition::CalcPosition(..) - fly frame has an invalid height" );
+ }
+
+ // keep calculated values
+ maAnchorPos = aAnchorPos;
+ mnRelPos = nRelPos;
+ maObjBoundRect = aObjBoundRect;
+}
+
+/** determine the relative position to base line for object position type AS_CHAR
+
+ OD 29.07.2003 #110978#
+ Note about values set at member <mnLineAlignment> -
+ value gives feedback for the line formatting.
+ 0 - no feedback; 1|2|3 - proposed formatting of characters
+ at top|at center|at bottom of line.
+
+ @author OD
+*/
+SwTwips SwAsCharAnchoredObjectPosition::_GetRelPosToBase(
+ const SwTwips _nObjBoundHeight,
+ const SwFmtVertOrient& _rVert )
+{
+ SwTwips nRelPosToBase = 0;
+
+ mnLineAlignment = 0;
+
+ const sal_Int16 eVertOrient = _rVert.GetVertOrient();
+
+ if ( eVertOrient == text::VertOrientation::NONE )
+ nRelPosToBase = _rVert.GetPos();
+ else
+ {
+ if ( eVertOrient == text::VertOrientation::CENTER )
+ nRelPosToBase -= _nObjBoundHeight / 2;
+ else if ( eVertOrient == text::VertOrientation::TOP )
+ nRelPosToBase -= _nObjBoundHeight;
+ else if ( eVertOrient == text::VertOrientation::BOTTOM )
+ nRelPosToBase = 0;
+ else if ( eVertOrient == text::VertOrientation::CHAR_CENTER )
+ nRelPosToBase -= ( _nObjBoundHeight + mnLineAscent - mnLineDescent ) / 2;
+ else if ( eVertOrient == text::VertOrientation::CHAR_TOP )
+ nRelPosToBase -= mnLineAscent;
+ else if ( eVertOrient == text::VertOrientation::CHAR_BOTTOM )
+ nRelPosToBase += mnLineDescent - _nObjBoundHeight;
+ else
+ {
+ if( _nObjBoundHeight >= mnLineAscentInclObjs + mnLineDescentInclObjs )
+ {
+ // object is at least as high as the line. Thus, no more is
+ // positioning necessary. Also, the max. ascent isn't changed.
+ nRelPosToBase -= mnLineAscentInclObjs;
+ if ( eVertOrient == text::VertOrientation::LINE_CENTER )
+ mnLineAlignment = 2;
+ else if ( eVertOrient == text::VertOrientation::LINE_TOP )
+ mnLineAlignment = 1;
+ else if ( eVertOrient == text::VertOrientation::LINE_BOTTOM )
+ mnLineAlignment = 3;
+ }
+ else if ( eVertOrient == text::VertOrientation::LINE_CENTER )
+ {
+ nRelPosToBase -= ( _nObjBoundHeight + mnLineAscentInclObjs - mnLineDescentInclObjs ) / 2;
+ mnLineAlignment = 2;
+ }
+ else if ( eVertOrient == text::VertOrientation::LINE_TOP )
+ {
+ nRelPosToBase -= mnLineAscentInclObjs;
+ mnLineAlignment = 1;
+ }
+ else if ( eVertOrient == text::VertOrientation::LINE_BOTTOM )
+ {
+ nRelPosToBase += mnLineDescentInclObjs - _nObjBoundHeight;
+ mnLineAlignment = 3;
+ }
+ }
+ }
+
+ return nRelPosToBase;
+}
+
+/** calculated anchored position for object position
+
+ @author OD
+*/
+Point SwAsCharAnchoredObjectPosition::GetAnchorPos() const
+{
+ return maAnchorPos;
+}
+
+/** calculated relative position to base line for object position
+
+ @author OD
+*/
+SwTwips SwAsCharAnchoredObjectPosition::GetRelPosY() const
+{
+ return mnRelPos;
+}
+
+/** determined object rectangle including spacing for object
+
+ @author OD
+*/
+SwRect SwAsCharAnchoredObjectPosition::GetObjBoundRectInclSpacing() const
+{
+ return maObjBoundRect;
+}
+
+/** determined line alignment
+
+ @author OD
+*/
+sal_uInt8 SwAsCharAnchoredObjectPosition::GetLineAlignment() const
+{
+ return mnLineAlignment;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/objectpositioning/environmentofanchoredobject.cxx b/sw/source/core/objectpositioning/environmentofanchoredobject.cxx
new file mode 100644
index 000000000000..80122c27905c
--- /dev/null
+++ b/sw/source/core/objectpositioning/environmentofanchoredobject.cxx
@@ -0,0 +1,116 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+#ifndef _ENVIRONMENTOFANCHOREDOBJECT
+#include <environmentofanchoredobject.hxx>
+#endif
+#include <frame.hxx>
+#include <pagefrm.hxx>
+#include <flyfrm.hxx>
+
+using namespace objectpositioning;
+
+SwEnvironmentOfAnchoredObject::SwEnvironmentOfAnchoredObject(
+ const bool _bFollowTextFlow )
+ : mbFollowTextFlow( _bFollowTextFlow )
+{}
+
+SwEnvironmentOfAnchoredObject::~SwEnvironmentOfAnchoredObject()
+{}
+
+/** determine environment layout frame for possible horizontal object positions
+
+ @author OD
+*/
+const SwLayoutFrm& SwEnvironmentOfAnchoredObject::GetHoriEnvironmentLayoutFrm(
+ const SwFrm& _rHoriOrientFrm ) const
+{
+ const SwFrm* pHoriEnvironmentLayFrm = &_rHoriOrientFrm;
+
+ if ( !mbFollowTextFlow )
+ {
+ // No exception any more for page alignment.
+ // the page frame determines the horizontal layout environment.
+ pHoriEnvironmentLayFrm = _rHoriOrientFrm.FindPageFrm();
+ }
+ else
+ {
+ while ( !pHoriEnvironmentLayFrm->IsCellFrm() &&
+ !pHoriEnvironmentLayFrm->IsFlyFrm() &&
+ !pHoriEnvironmentLayFrm->IsPageFrm() )
+ {
+ pHoriEnvironmentLayFrm = pHoriEnvironmentLayFrm->GetUpper();
+ OSL_ENSURE( pHoriEnvironmentLayFrm,
+ "SwEnvironmentOfAnchoredObject::GetHoriEnvironmentLayoutFrm(..) - no page|fly|cell frame found" );
+ }
+ }
+
+ OSL_ENSURE( pHoriEnvironmentLayFrm->ISA(SwLayoutFrm),
+ "SwEnvironmentOfAnchoredObject::GetHoriEnvironmentLayoutFrm(..) - found frame isn't a layout frame" );
+
+ return static_cast<const SwLayoutFrm&>(*pHoriEnvironmentLayFrm);
+}
+
+/** determine environment layout frame for possible vertical object positions
+*/
+const SwLayoutFrm& SwEnvironmentOfAnchoredObject::GetVertEnvironmentLayoutFrm(
+ const SwFrm& _rVertOrientFrm ) const
+{
+ const SwFrm* pVertEnvironmentLayFrm = &_rVertOrientFrm;
+
+ if ( !mbFollowTextFlow )
+ {
+ // No exception any more for page alignment.
+ // the page frame determines the vertical layout environment.
+ pVertEnvironmentLayFrm = _rVertOrientFrm.FindPageFrm();
+ }
+ else
+ {
+ while ( !pVertEnvironmentLayFrm->IsCellFrm() &&
+ !pVertEnvironmentLayFrm->IsFlyFrm() &&
+ !pVertEnvironmentLayFrm->IsHeaderFrm() &&
+ !pVertEnvironmentLayFrm->IsFooterFrm() &&
+ !pVertEnvironmentLayFrm->IsFtnFrm() &&
+ !pVertEnvironmentLayFrm->IsPageBodyFrm() &&
+ !pVertEnvironmentLayFrm->IsPageFrm() )
+ {
+ pVertEnvironmentLayFrm = pVertEnvironmentLayFrm->GetUpper();
+ OSL_ENSURE( pVertEnvironmentLayFrm,
+ "SwEnvironmentOfAnchoredObject::GetVertEnvironmentLayoutFrm(..) - proposed frame not found" );
+ }
+ }
+
+ OSL_ENSURE( pVertEnvironmentLayFrm->ISA(SwLayoutFrm),
+ "SwEnvironmentOfAnchoredObject::GetVertEnvironmentLayoutFrm(..) - found frame isn't a layout frame" );
+
+ return static_cast<const SwLayoutFrm&>(*pVertEnvironmentLayFrm);
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/objectpositioning/tocntntanchoredobjectposition.cxx b/sw/source/core/objectpositioning/tocntntanchoredobjectposition.cxx
new file mode 100644
index 000000000000..e4a199695fd8
--- /dev/null
+++ b/sw/source/core/objectpositioning/tocntntanchoredobjectposition.cxx
@@ -0,0 +1,1129 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+#include <tocntntanchoredobjectposition.hxx>
+#include <anchoredobject.hxx>
+#include <frame.hxx>
+#include <txtfrm.hxx>
+#include <pagefrm.hxx>
+#include <sectfrm.hxx>
+// #i26945#
+#include <tabfrm.hxx>
+#include "rootfrm.hxx"
+#include "viewopt.hxx"
+#include "viewsh.hxx"
+#include <frmfmt.hxx>
+#include <IDocumentSettingAccess.hxx>
+#include <fmtsrnd.hxx>
+#include <fmtfsize.hxx>
+#include <fmtanchr.hxx>
+#include <fmtornt.hxx>
+#include <editeng/lrspitem.hxx>
+#include <editeng/ulspitem.hxx>
+#include <svx/svdobj.hxx>
+#include <pam.hxx>
+#include <environmentofanchoredobject.hxx>
+#include <frmtool.hxx>
+#include <ndtxt.hxx>
+#include <dflyobj.hxx>
+
+using namespace objectpositioning;
+using namespace ::com::sun::star;
+
+
+SwToCntntAnchoredObjectPosition::SwToCntntAnchoredObjectPosition( SdrObject& _rDrawObj )
+ : SwAnchoredObjectPosition ( _rDrawObj ),
+ mpVertPosOrientFrm( 0 ),
+ // #i26791#
+ maOffsetToFrmAnchorPos( Point() ),
+ mbAnchorToChar ( false ),
+ mpToCharOrientFrm( 0 ),
+ mpToCharRect( 0 ),
+ // #i22341#
+ mnToCharTopOfLine( 0 )
+{}
+
+SwToCntntAnchoredObjectPosition::~SwToCntntAnchoredObjectPosition()
+{}
+
+bool SwToCntntAnchoredObjectPosition::IsAnchoredToChar() const
+{
+ return mbAnchorToChar;
+}
+
+const SwFrm* SwToCntntAnchoredObjectPosition::ToCharOrientFrm() const
+{
+ return mpToCharOrientFrm;
+}
+
+const SwRect* SwToCntntAnchoredObjectPosition::ToCharRect() const
+{
+ return mpToCharRect;
+}
+
+// #i22341#
+SwTwips SwToCntntAnchoredObjectPosition::ToCharTopOfLine() const
+{
+ return mnToCharTopOfLine;
+}
+
+SwTxtFrm& SwToCntntAnchoredObjectPosition::GetAnchorTxtFrm() const
+{
+ OSL_ENSURE( GetAnchorFrm().ISA(SwTxtFrm),
+ "SwToCntntAnchoredObjectPosition::GetAnchorTxtFrm() - wrong anchor frame type" );
+
+ return static_cast<SwTxtFrm&>(GetAnchorFrm());
+}
+
+// #i23512#
+bool lcl_DoesVertPosFits( const SwTwips _nRelPosY,
+ const SwTwips _nAvail,
+ const SwLayoutFrm* _pUpperOfOrientFrm,
+ const bool _bBrowse,
+ const bool _bGrowInTable,
+ SwLayoutFrm*& _orpLayoutFrmToGrow )
+{
+ bool bVertPosFits = false;
+
+ if ( _nRelPosY <= _nAvail )
+ {
+ bVertPosFits = true;
+ }
+ else if ( _bBrowse )
+ {
+ if ( _pUpperOfOrientFrm->IsInSct() )
+ {
+ SwSectionFrm* pSctFrm =
+ const_cast<SwSectionFrm*>(_pUpperOfOrientFrm->FindSctFrm());
+ bVertPosFits = pSctFrm->GetUpper()->Grow( _nRelPosY - _nAvail, sal_True ) > 0;
+ // Note: do not provide a layout frame for a grow.
+ }
+ else
+ {
+ bVertPosFits = const_cast<SwLayoutFrm*>(_pUpperOfOrientFrm)->
+ Grow( _nRelPosY - _nAvail, sal_True ) > 0;
+ if ( bVertPosFits )
+ _orpLayoutFrmToGrow = const_cast<SwLayoutFrm*>(_pUpperOfOrientFrm);
+ }
+ }
+ else if ( _pUpperOfOrientFrm->IsInTab() && _bGrowInTable )
+ {
+ // #i45085# - check, if upper frame would grow the
+ // excepted amount of twips.
+ const SwTwips nTwipsGrown = const_cast<SwLayoutFrm*>(_pUpperOfOrientFrm)->
+ Grow( _nRelPosY - _nAvail, sal_True ) > 0;
+ bVertPosFits = ( nTwipsGrown == ( _nRelPosY - _nAvail ) );
+ if ( bVertPosFits )
+ _orpLayoutFrmToGrow = const_cast<SwLayoutFrm*>(_pUpperOfOrientFrm);
+ }
+
+ return bVertPosFits;
+}
+
+void SwToCntntAnchoredObjectPosition::CalcPosition()
+{
+ // get format of object
+ const SwFrmFmt& rFrmFmt = GetFrmFmt();
+
+ // declare and set <pFooter> to footer frame, if object is anchored
+ // at a frame belonging to the footer.
+ const SwFrm* pFooter = GetAnchorFrm().FindFooterOrHeader();
+ if ( pFooter && !pFooter->IsFooterFrm() )
+ pFooter = NULL;
+
+ // declare and set <bBrowse> to true, if document is in browser mode and
+ // object is anchored at the body, but not at frame belonging to a table.
+ bool bBrowse = GetAnchorFrm().IsInDocBody() && !GetAnchorFrm().IsInTab();
+ if( bBrowse )
+ {
+ const ViewShell *pSh = GetAnchorFrm().getRootFrm()->GetCurrShell();
+ if( !pSh || !pSh->GetViewOptions()->getBrowseMode() )
+ bBrowse = false;
+ }
+
+ // determine left/right and its upper/lower spacing.
+ const SvxLRSpaceItem &rLR = rFrmFmt.GetLRSpace();
+ const SvxULSpaceItem &rUL = rFrmFmt.GetULSpace();
+
+ // determine, if object has no surrounding.
+ const SwFmtSurround& rSurround = rFrmFmt.GetSurround();
+ const bool bNoSurround = rSurround.GetSurround() == SURROUND_NONE;
+ const bool bWrapThrough = rSurround.GetSurround() == SURROUND_THROUGHT;
+
+ // new class <SwEnvironmentOfAnchoredObject>
+ SwEnvironmentOfAnchoredObject aEnvOfObj( DoesObjFollowsTextFlow() );
+
+ // #i18732# - grow only, if object has to follow the text flow
+ const bool bGrow = DoesObjFollowsTextFlow() &&
+ ( !GetAnchorFrm().IsInTab() ||
+ !rFrmFmt.GetFrmSize().GetHeightPercent() );
+
+ // get text frame the object is anchored at
+ const SwTxtFrm& rAnchorTxtFrm = GetAnchorTxtFrm();
+ SWRECTFN( (&rAnchorTxtFrm) )
+
+ const SwRect aObjBoundRect( GetAnchoredObj().GetObjRect() );
+
+ // local variable keeping the calculated relative position; initialized with
+ // current relative position.
+ // #i26791# - use new object instance of <SwAnchoredObject>
+ Point aRelPos( GetAnchoredObj().GetCurrRelPos() );
+
+ SwTwips nRelDiff = 0;
+
+ bool bMoveable = rAnchorTxtFrm.IsMoveable();
+
+ // determine frame the object position has to be oriented at.
+ const SwTxtFrm* pOrientFrm = &rAnchorTxtFrm;
+ const SwTxtFrm* pAnchorFrmForVertPos = &rAnchorTxtFrm;
+ {
+ // if object is at-character anchored, determine character-rectangle
+ // and frame, position has to be oriented at.
+ mbAnchorToChar = (FLY_AT_CHAR == rFrmFmt.GetAnchor().GetAnchorId());
+ if ( mbAnchorToChar )
+ {
+ const SwFmtAnchor& rAnch = rFrmFmt.GetAnchor();
+ // #i26791# - use new object instance of <SwAnchoredObject>
+ // Due to table break algorithm the character
+ // rectangle can have no height. Thus, check also the width
+ if ( ( !GetAnchoredObj().GetLastCharRect().Height() &&
+ !GetAnchoredObj().GetLastCharRect().Width() ) ||
+ !GetAnchoredObj().GetLastTopOfLine() )
+ {
+ // #i111886#
+ // Check existence of paragraph portion information in order
+ // to avoid formatting which could cause deletion of follow frames.
+ GetAnchoredObj().CheckCharRectAndTopOfLine();
+
+ // Due to table break algorithm the character
+ // rectangle can have no height. Thus, check also the width
+ if ( ( !GetAnchoredObj().GetLastCharRect().Height() &&
+ !GetAnchoredObj().GetLastCharRect().Width() ) ||
+ !GetAnchoredObj().GetLastTopOfLine() )
+ {
+ // Get default for <mpVertPosOrientFrm>, if it's not set.
+ if ( !mpVertPosOrientFrm )
+ {
+ mpVertPosOrientFrm = rAnchorTxtFrm.GetUpper();
+ }
+ return;
+ }
+ }
+ mpToCharRect = &(GetAnchoredObj().GetLastCharRect());
+ // #i22341# - get top of line, in which the anchor character is.
+ mnToCharTopOfLine = GetAnchoredObj().GetLastTopOfLine();
+ pOrientFrm = &(const_cast<SwTxtFrm&>(rAnchorTxtFrm).GetFrmAtOfst(
+ rAnch.GetCntntAnchor()->nContent.GetIndex() ) );
+ mpToCharOrientFrm = pOrientFrm;
+ }
+ }
+ SWREFRESHFN( pOrientFrm )
+
+ // determine vertical position
+ {
+
+ // determine vertical positioning and alignment attributes
+ SwFmtVertOrient aVert( rFrmFmt.GetVertOrient() );
+
+ // #i18732# - determine layout frame for vertical
+ // positions aligned to 'page areas'.
+ const SwLayoutFrm& rPageAlignLayFrm =
+ aEnvOfObj.GetVertEnvironmentLayoutFrm( *pOrientFrm );
+
+ if ( aVert.GetVertOrient() != text::VertOrientation::NONE )
+ {
+ // #i18732# - adjustments for follow text flow or not
+ // AND vertical alignment at 'page areas'.
+ SwTwips nAlignAreaHeight;
+ SwTwips nAlignAreaOffset;
+ _GetVertAlignmentValues( *pOrientFrm, rPageAlignLayFrm,
+ aVert.GetRelationOrient(),
+ nAlignAreaHeight, nAlignAreaOffset );
+
+ // determine relative vertical position
+ SwTwips nRelPosY = nAlignAreaOffset;
+ const SwTwips nObjHeight = (aObjBoundRect.*fnRect->fnGetHeight)();
+ //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin
+ const SwTwips nUpperSpace = bVert
+ ? ( bVertL2R
+ ? rLR.GetLeft()
+ : rLR.GetRight() )
+ : rUL.GetUpper();
+ // --> OD 2009-08-31 #monglianlayout#
+ const SwTwips nLowerSpace = bVert
+ ? ( bVertL2R
+ ? rLR.GetLeft()
+ : rLR.GetRight() )
+ : rUL.GetLower();
+ // <--
+ switch ( aVert.GetVertOrient() )
+ {
+ case text::VertOrientation::CHAR_BOTTOM:
+ {
+ if ( mbAnchorToChar )
+ {
+ // bottom (to character anchored)
+ nRelPosY += nAlignAreaHeight + nUpperSpace;
+ //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin
+ if ( bVert && !bVertL2R )
+ {
+ nRelPosY += nObjHeight;
+ }
+ break;
+ }
+ }
+ // no break here
+ case text::VertOrientation::TOP:
+ {
+ // #i22341# - special case for vertical
+ // alignment at top of line
+ if ( mbAnchorToChar &&
+ aVert.GetRelationOrient() == text::RelOrientation::TEXT_LINE )
+ {
+ nRelPosY -= (nObjHeight + nLowerSpace);
+ }
+ else
+ {
+ nRelPosY += nUpperSpace;
+ }
+ }
+ break;
+ // #i22341#
+ case text::VertOrientation::LINE_TOP:
+ {
+ if ( mbAnchorToChar &&
+ aVert.GetRelationOrient() == text::RelOrientation::TEXT_LINE )
+ {
+ nRelPosY -= (nObjHeight + nLowerSpace);
+ }
+ else
+ {
+ OSL_FAIL( "<SwToCntntAnchoredObjectPosition::CalcPosition()> - unknown combination of vertical position and vertical alignment." );
+ }
+ }
+ break;
+ case text::VertOrientation::CENTER:
+ {
+ nRelPosY += (nAlignAreaHeight / 2) - (nObjHeight / 2);
+ }
+ break;
+ // #i22341#
+ case text::VertOrientation::LINE_CENTER:
+ {
+ if ( mbAnchorToChar &&
+ aVert.GetRelationOrient() == text::RelOrientation::TEXT_LINE )
+ {
+ nRelPosY += (nAlignAreaHeight / 2) - (nObjHeight / 2);
+ }
+ else
+ {
+ OSL_FAIL( "<SwToCntntAnchoredObjectPosition::CalcPosition()> - unknown combination of vertical position and vertical alignment." );
+ }
+ }
+ break;
+ case text::VertOrientation::BOTTOM:
+ {
+ if ( ( aVert.GetRelationOrient() == text::RelOrientation::FRAME ||
+ aVert.GetRelationOrient() == text::RelOrientation::PRINT_AREA ) &&
+ bNoSurround )
+ {
+ // bottom (aligned to 'paragraph areas')
+ nRelPosY += nAlignAreaHeight + nUpperSpace;
+ }
+ else
+ {
+ // #i22341# - special case for vertical
+ // alignment at top of line
+ if ( mbAnchorToChar &&
+ aVert.GetRelationOrient() == text::RelOrientation::TEXT_LINE )
+ {
+ nRelPosY += nUpperSpace;
+ }
+ else
+ {
+ nRelPosY += nAlignAreaHeight -
+ ( nObjHeight + nLowerSpace );
+ }
+ }
+ }
+ break;
+ // #i22341#
+ case text::VertOrientation::LINE_BOTTOM:
+ {
+ if ( mbAnchorToChar &&
+ aVert.GetRelationOrient() == text::RelOrientation::TEXT_LINE )
+ {
+ nRelPosY += nUpperSpace;
+ }
+ else
+ {
+ OSL_FAIL( "<SwToCntntAnchoredObjectPosition::CalcPosition()> - unknown combination of vertical position and vertical alignment." );
+ }
+ }
+ break;
+ default:
+ break;
+ }
+
+ // adjust relative position by distance between anchor frame and
+ // the frame, the object is oriented at.
+ // #i28701# - correction: adjust relative position,
+ // only if the floating screen object has to follow the text flow.
+ if ( DoesObjFollowsTextFlow() && pOrientFrm != &rAnchorTxtFrm )
+ {
+ // #i11860# - use new method <_GetTopForObjPos>
+ // to get top of frame for object positioning.
+ const SwTwips nTopOfOrient = _GetTopForObjPos( *pOrientFrm, fnRect, bVert );
+ nRelPosY += (*fnRect->fnYDiff)( nTopOfOrient,
+ _GetTopForObjPos( rAnchorTxtFrm, fnRect, bVert ) );
+ }
+
+ // #i42124# - capture object inside vertical
+ // layout environment.
+ {
+ const SwTwips nTopOfAnch =
+ _GetTopForObjPos( *pOrientFrm, fnRect, bVert );
+ const SwLayoutFrm& rVertEnvironLayFrm =
+ aEnvOfObj.GetVertEnvironmentLayoutFrm(
+ *(pOrientFrm->GetUpper()) );
+ const bool bCheckBottom = !DoesObjFollowsTextFlow();
+ nRelPosY = _AdjustVertRelPos( nTopOfAnch, bVert, bVertL2R,
+ rVertEnvironLayFrm, nRelPosY,
+ DoesObjFollowsTextFlow(),
+ bCheckBottom );
+ }
+
+ // keep calculated relative vertical position - needed for filters
+ // (including the xml-filter)
+ {
+ // determine position
+ SwTwips nAttrRelPosY = nRelPosY - nAlignAreaOffset;
+ // set
+ if ( nAttrRelPosY != aVert.GetPos() )
+ {
+ aVert.SetPos( nAttrRelPosY );
+ const_cast<SwFrmFmt&>(rFrmFmt).LockModify();
+ const_cast<SwFrmFmt&>(rFrmFmt).SetFmtAttr( aVert );
+ const_cast<SwFrmFmt&>(rFrmFmt).UnlockModify();
+ }
+ }
+
+ // determine absolute 'vertical' position, depending on layout-direction
+ // #i26791# - determine offset to 'vertical' frame
+ // anchor position, depending on layout-direction
+ if ( bVert )
+ {
+ aRelPos.X() = nRelPosY;
+ maOffsetToFrmAnchorPos.X() = nAlignAreaOffset;
+ }
+ else
+ {
+ aRelPos.Y() = nRelPosY;
+ maOffsetToFrmAnchorPos.Y() = nAlignAreaOffset;
+ }
+ }
+
+ // Determine upper of frame vertical position is oriented at.
+ // #i28701# - determine 'virtual' anchor frame.
+ // This frame is used in the following instead of the 'real' anchor
+ // frame <rAnchorTxtFrm> for the 'vertical' position in all cases.
+ const SwLayoutFrm* pUpperOfOrientFrm = 0L;
+ {
+ // #i28701# - As long as the anchor frame is on the
+ // same page as <pOrientFrm> and the vertical position isn't aligned
+ // automatic at the anchor character or the top of the line of the
+ // anchor character, the anchor frame determines the vertical position.
+ if ( &rAnchorTxtFrm == pOrientFrm ||
+ ( rAnchorTxtFrm.FindPageFrm() == pOrientFrm->FindPageFrm() &&
+ aVert.GetVertOrient() == text::VertOrientation::NONE &&
+ aVert.GetRelationOrient() != text::RelOrientation::CHAR &&
+ aVert.GetRelationOrient() != text::RelOrientation::TEXT_LINE ) )
+ {
+ pUpperOfOrientFrm = rAnchorTxtFrm.GetUpper();
+ pAnchorFrmForVertPos = &rAnchorTxtFrm;
+ }
+ else
+ {
+ pUpperOfOrientFrm = pOrientFrm->GetUpper();
+ pAnchorFrmForVertPos = pOrientFrm;
+ }
+ }
+
+ // ignore one-column sections.
+ // #i23512# - correction: also ignore one-columned
+ // sections with footnotes/endnotes
+ if ( pUpperOfOrientFrm->IsInSct() )
+ {
+ const SwSectionFrm* pSctFrm = pUpperOfOrientFrm->FindSctFrm();
+ const bool bIgnoreSection = pUpperOfOrientFrm->IsSctFrm() ||
+ ( pSctFrm->Lower()->IsColumnFrm() &&
+ !pSctFrm->Lower()->GetNext() );
+ if ( bIgnoreSection )
+ pUpperOfOrientFrm = pSctFrm->GetUpper();
+ }
+
+ if ( aVert.GetVertOrient() == text::VertOrientation::NONE )
+ {
+ // local variable <nRelPosY> for calculation of relative vertical
+ // distance to anchor.
+ SwTwips nRelPosY = 0;
+ // #i26791# - local variable <nVertOffsetToFrmAnchorPos>
+ // for determination of the 'vertical' offset to the frame anchor
+ // position
+ SwTwips nVertOffsetToFrmAnchorPos( 0L );
+ // #i22341# - add special case for vertical alignment
+ // at top of line.
+ if ( mbAnchorToChar &&
+ ( aVert.GetRelationOrient() == text::RelOrientation::CHAR ||
+ aVert.GetRelationOrient() == text::RelOrientation::TEXT_LINE ) )
+ {
+ // #i11860# - use new method <_GetTopForObjPos>
+ // to get top of frame for object positioning.
+ SwTwips nTopOfOrient = _GetTopForObjPos( *pOrientFrm, fnRect, bVert );
+ if ( aVert.GetRelationOrient() == text::RelOrientation::CHAR )
+ {
+ nVertOffsetToFrmAnchorPos = (*fnRect->fnYDiff)(
+ (ToCharRect()->*fnRect->fnGetBottom)(),
+ nTopOfOrient );
+ }
+ else
+ {
+ nVertOffsetToFrmAnchorPos = (*fnRect->fnYDiff)( ToCharTopOfLine(),
+ nTopOfOrient );
+ }
+ nRelPosY = nVertOffsetToFrmAnchorPos - aVert.GetPos();
+ }
+ else
+ {
+ // #i28701# - correction: use <pAnchorFrmForVertPos>
+ // instead of <pOrientFrm> and do not adjust relative position
+ // to get correct vertical position.
+ nVertOffsetToFrmAnchorPos = 0L;
+ // #i11860# - use new method <_GetTopForObjPos>
+ // to get top of frame for object positioning.
+ const SwTwips nTopOfOrient =
+ _GetTopForObjPos( *pAnchorFrmForVertPos, fnRect, bVert );
+ // Increase <nRelPosY> by margin height,
+ // if position is vertical aligned to "paragraph text area"
+ if ( aVert.GetRelationOrient() == text::RelOrientation::PRINT_AREA )
+ {
+ // #i11860# - consider upper space amount of previous frame
+ SwTwips nTopMargin = (pAnchorFrmForVertPos->*fnRect->fnGetTopMargin)();
+ if ( pAnchorFrmForVertPos->IsTxtFrm() )
+ {
+ nTopMargin -= static_cast<const SwTxtFrm*>(pAnchorFrmForVertPos)->
+ GetUpperSpaceAmountConsideredForPrevFrmAndPageGrid();
+ }
+ nVertOffsetToFrmAnchorPos += nTopMargin;
+ }
+ // #i18732# - adjust <nRelPosY> by difference
+ // between 'page area' and 'anchor' frame, if position is
+ // vertical aligned to 'page areas'
+ else if ( aVert.GetRelationOrient() == text::RelOrientation::PAGE_FRAME )
+ {
+ nVertOffsetToFrmAnchorPos += (*fnRect->fnYDiff)(
+ (rPageAlignLayFrm.Frm().*fnRect->fnGetTop)(),
+ nTopOfOrient );
+ }
+ else if ( aVert.GetRelationOrient() == text::RelOrientation::PAGE_PRINT_AREA )
+ {
+ SwRect aPgPrtRect( rPageAlignLayFrm.Frm() );
+ if ( rPageAlignLayFrm.IsPageFrm() )
+ {
+ aPgPrtRect =
+ static_cast<const SwPageFrm&>(rPageAlignLayFrm).PrtWithoutHeaderAndFooter();
+ }
+ nVertOffsetToFrmAnchorPos += (*fnRect->fnYDiff)(
+ (aPgPrtRect.*fnRect->fnGetTop)(),
+ nTopOfOrient );
+ }
+ nRelPosY = nVertOffsetToFrmAnchorPos + aVert.GetPos();
+ }
+
+ // <pUpperOfOrientFrm>: layout frame, at which the position has to
+ // is oriented at
+ // <nRelPosY>: rest of the relative distance in the current
+ // layout frame
+ // <nAvail>: space, which is available in the current
+ // layout frame
+
+ // #i26791# - determine offset to 'vertical'
+ // frame anchor position, depending on layout-direction
+ if ( bVert )
+ maOffsetToFrmAnchorPos.X() = nVertOffsetToFrmAnchorPos;
+ else
+ maOffsetToFrmAnchorPos.Y() = nVertOffsetToFrmAnchorPos;
+ // <--
+ // #i11860# - use new method <_GetTopForObjPos>
+ // to get top of frame for object positioning.
+ const SwTwips nTopOfAnch = _GetTopForObjPos( *pAnchorFrmForVertPos, fnRect, bVert );
+ if( nRelPosY <= 0 )
+ {
+ // Allow negative position, but keep it
+ // inside environment layout frame.
+ const SwLayoutFrm& rVertEnvironLayFrm =
+ aEnvOfObj.GetVertEnvironmentLayoutFrm( *pUpperOfOrientFrm );
+ // #i31805# - do not check, if bottom of
+ // anchored object would fit into environment layout frame, if
+ // anchored object has to follow the text flow.
+ const bool bCheckBottom = !DoesObjFollowsTextFlow();
+ nRelPosY = _AdjustVertRelPos( nTopOfAnch, bVert, bVertL2R,
+ rVertEnvironLayFrm, nRelPosY,
+ DoesObjFollowsTextFlow(),
+ bCheckBottom );
+ if ( bVert )
+ aRelPos.X() = nRelPosY;
+ else
+ aRelPos.Y() = nRelPosY;
+ }
+ else
+ {
+ SWREFRESHFN( pAnchorFrmForVertPos )
+ SwTwips nAvail =
+ (*fnRect->fnYDiff)( (pUpperOfOrientFrm->*fnRect->fnGetPrtBottom)(),
+ nTopOfAnch );
+ const bool bInFtn = pAnchorFrmForVertPos->IsInFtn();
+ while ( nRelPosY )
+ {
+ // #i23512# - correction:
+ // consider section frame for grow in online layout.
+ // use new local method <lcl_DoesVertPosFits(..)>
+ SwLayoutFrm* pLayoutFrmToGrow = 0L;
+ const bool bDoesVertPosFits = lcl_DoesVertPosFits(
+ nRelPosY, nAvail, pUpperOfOrientFrm, bBrowse,
+ bGrow, pLayoutFrmToGrow );
+
+ if ( bDoesVertPosFits )
+ {
+ SwTwips nTmpRelPosY =
+ (*fnRect->fnYDiff)( (pUpperOfOrientFrm->*fnRect->fnGetPrtBottom)(),
+ nTopOfAnch ) -
+ nAvail + nRelPosY;
+ // #i28701# - adjust calculated
+ // relative vertical position to object's environment.
+ const SwFrm& rVertEnvironLayFrm =
+ aEnvOfObj.GetVertEnvironmentLayoutFrm( *pUpperOfOrientFrm );
+ // Do not check, if bottom of
+ // anchored object would fit into environment layout
+ // frame, if anchored object has to follow the text flow.
+ const bool bCheckBottom = !DoesObjFollowsTextFlow();
+ nTmpRelPosY = _AdjustVertRelPos( nTopOfAnch, bVert, bVertL2R,
+ rVertEnvironLayFrm,
+ nTmpRelPosY,
+ DoesObjFollowsTextFlow(),
+ bCheckBottom );
+ if ( bVert )
+ aRelPos.X() = nTmpRelPosY;
+ else
+ aRelPos.Y() = nTmpRelPosY;
+
+ // #i23512# - use local variable
+ // <pLayoutFrmToGrow> provided by new method
+ // <lcl_DoesVertPosFits(..)>.
+ if ( pLayoutFrmToGrow )
+ {
+ pLayoutFrmToGrow->Grow( nRelPosY - nAvail );
+ }
+ // <--
+ nRelPosY = 0;
+ }
+ else
+ {
+ // #i26495# - floating screen objects,
+ // which are anchored inside a table, doesn't follow
+ // the text flow.
+ if ( DoesObjFollowsTextFlow() &&
+ !( aVert.GetRelationOrient() == text::RelOrientation::PAGE_FRAME ||
+ aVert.GetRelationOrient() == text::RelOrientation::PAGE_PRINT_AREA ) &&
+ !GetAnchorFrm().IsInTab() )
+ {
+ if ( bMoveable )
+ {
+ // follow the text flow
+ nRelPosY -= nAvail;
+ MakePageType eMakePage = bInFtn ? MAKEPAGE_NONE
+ : MAKEPAGE_APPEND;
+ const bool bInSct = pUpperOfOrientFrm->IsInSct();
+ if( bInSct )
+ eMakePage = MAKEPAGE_NOSECTION;
+
+ const SwLayoutFrm* pTmp =
+ pUpperOfOrientFrm->GetLeaf( eMakePage, sal_True, &rAnchorTxtFrm );
+ if ( pTmp &&
+ ( !bInSct ||
+ pUpperOfOrientFrm->FindSctFrm()->IsAnFollow( pTmp->FindSctFrm() ) ) )
+ {
+ pUpperOfOrientFrm = pTmp;
+ bMoveable = rAnchorTxtFrm.IsMoveable( (SwLayoutFrm*)pUpperOfOrientFrm );
+ SWREFRESHFN( pUpperOfOrientFrm )
+ nAvail = (pUpperOfOrientFrm->Prt().*fnRect->fnGetHeight)();
+ }
+ else
+ {
+ // if there isn't enough space in the (colmuned)
+ // section, leave it and set available space <nAvail>
+ // to the space below the section.
+ // if the new available space isn't also enough,
+ // new pages can be created.
+ if( bInSct )
+ {
+ const SwFrm* pSct = pUpperOfOrientFrm->FindSctFrm();
+ pUpperOfOrientFrm = pSct->GetUpper();
+ nAvail = (*fnRect->fnYDiff)(
+ (pUpperOfOrientFrm->*fnRect->fnGetPrtBottom)(),
+ (pSct->*fnRect->fnGetPrtBottom)() );
+ }
+ else
+ {
+#if OSL_DEBUG_LEVEL > 1
+ OSL_FAIL( "<SwToCntntAnchoredObjectPosition::CalcPosition()> - code under investigation by OD, please inform OD about this assertion!" );
+#endif
+ nRelDiff = nRelPosY;
+ nRelPosY = 0;
+ }
+ }
+ }
+ else
+ {
+ nRelPosY = 0;
+ }
+ }
+ else
+ {
+ // #i18732# - do not follow text flow respectively
+ // align at 'page areas', but stay inside given environment
+ const SwFrm& rVertEnvironLayFrm =
+ aEnvOfObj.GetVertEnvironmentLayoutFrm( *pUpperOfOrientFrm );
+ nRelPosY = _AdjustVertRelPos( nTopOfAnch, bVert, bVertL2R,
+ rVertEnvironLayFrm,
+ nRelPosY,
+ DoesObjFollowsTextFlow() );
+ if( bVert )
+ aRelPos.X() = nRelPosY;
+ else
+ aRelPos.Y() = nRelPosY;
+ nRelPosY = 0;
+ }
+ }
+ } // end of <while ( nRelPosY )>
+ } // end of else <nRelPosY <= 0>
+ } // end of <aVert.GetVertOrient() == text::VertOrientation::NONE>
+
+ //Damit das Teil ggf. auf die richtige Seite gestellt und in die
+ //PrtArea des LayLeaf gezogen werden kann, muss hier seine
+ //absolute Position berechnet werden.
+ const SwTwips nTopOfAnch = _GetTopForObjPos( *pAnchorFrmForVertPos, fnRect, bVert );
+ if( bVert )
+ {
+ // --> OD 2009-08-31 #monglianlayout#
+ if ( !bVertL2R )
+ {
+ GetAnchoredObj().SetObjLeft( nTopOfAnch -
+ ( aRelPos.X() - nRelDiff ) -
+ aObjBoundRect.Width() );
+ }
+ else
+ {
+ GetAnchoredObj().SetObjLeft( nTopOfAnch +
+ ( aRelPos.X() - nRelDiff ) );
+ }
+ // <--
+ }
+ else
+ {
+ GetAnchoredObj().SetObjTop( nTopOfAnch +
+ ( aRelPos.Y() - nRelDiff ) );
+ }
+
+ // grow environment under certain conditions
+ // ignore one-column sections.
+ // #i23512# - correction: also ignore one-columned
+ // sections with footnotes/endnotes
+ if ( pUpperOfOrientFrm->IsInSct() )
+ {
+ const SwSectionFrm* pSctFrm = pUpperOfOrientFrm->FindSctFrm();
+ const bool bIgnoreSection = pUpperOfOrientFrm->IsSctFrm() ||
+ ( pSctFrm->Lower()->IsColumnFrm() &&
+ !pSctFrm->Lower()->GetNext() );
+ if ( bIgnoreSection )
+ pUpperOfOrientFrm = pSctFrm->GetUpper();
+ }
+ SwTwips nDist = (GetAnchoredObj().GetObjRect().*fnRect->fnBottomDist)(
+ (pUpperOfOrientFrm->*fnRect->fnGetPrtBottom)() );
+ if( nDist < 0 )
+ {
+ // #i23512# - correction:
+ // consider section frame for grow in online layout and
+ // consider page alignment for grow in table.
+ SwLayoutFrm* pLayoutFrmToGrow = 0L;
+ if ( bBrowse && rAnchorTxtFrm.IsMoveable() )
+ {
+ if ( pUpperOfOrientFrm->IsInSct() )
+ {
+ pLayoutFrmToGrow = const_cast<SwLayoutFrm*>(
+ pUpperOfOrientFrm->FindSctFrm()->GetUpper());
+ nDist = (GetAnchoredObj().GetObjRect().*fnRect->fnBottomDist)(
+ (pLayoutFrmToGrow->*fnRect->fnGetPrtBottom)() );
+ if ( nDist >= 0 )
+ {
+ pLayoutFrmToGrow = 0L;
+ }
+ }
+ else
+ {
+ pLayoutFrmToGrow =
+ const_cast<SwLayoutFrm*>(pUpperOfOrientFrm);
+ }
+ }
+ else if ( rAnchorTxtFrm.IsInTab() && bGrow )
+ {
+ pLayoutFrmToGrow = const_cast<SwLayoutFrm*>(pUpperOfOrientFrm);
+ }
+ if ( pLayoutFrmToGrow )
+ {
+ pLayoutFrmToGrow->Grow( -nDist );
+ }
+ // <--
+ }
+
+ if ( DoesObjFollowsTextFlow() &&
+ !( aVert.GetRelationOrient() == text::RelOrientation::PAGE_FRAME ||
+ aVert.GetRelationOrient() == text::RelOrientation::PAGE_PRINT_AREA ) )
+ {
+
+ nDist = (GetAnchoredObj().GetObjRect().*fnRect->fnBottomDist)(
+ (pUpperOfOrientFrm->*fnRect->fnGetPrtBottom)() );
+ // #i26945# - floating screen objects, which are
+ // anchored inside a table, doesn't follow the text flow. But, they
+ // have to stay inside its layout environment.
+ if ( nDist < 0 && pOrientFrm->IsInTab() )
+ {
+ // If the anchor frame is the first content of the table cell
+ // and has no follow, the table frame is notified,
+ // that the object doesn't fit into the table cell.
+ // Adjustment of position isn't needed in this case.
+ if ( pOrientFrm == &rAnchorTxtFrm &&
+ !pOrientFrm->GetFollow() &&
+ !pOrientFrm->GetIndPrev() )
+ {
+ const_cast<SwTabFrm*>(pOrientFrm->FindTabFrm())
+ ->SetDoesObjsFit( sal_False );
+ }
+ else
+ {
+ SwTwips nTmpRelPosY( 0L );
+ if ( bVert )
+ nTmpRelPosY = aRelPos.X() - nDist;
+ else
+ nTmpRelPosY = aRelPos.Y() + nDist;
+ const SwLayoutFrm& rVertEnvironLayFrm =
+ aEnvOfObj.GetVertEnvironmentLayoutFrm( *pUpperOfOrientFrm );
+ nTmpRelPosY = _AdjustVertRelPos( nTopOfAnch, bVert, bVertL2R,
+ rVertEnvironLayFrm,
+ nTmpRelPosY,
+ DoesObjFollowsTextFlow(),
+ false );
+ if ( bVert )
+ {
+ aRelPos.X() = nTmpRelPosY;
+ // --> OD 2009-08-31 #mongolianlayout#
+ if ( !bVertL2R )
+ {
+ GetAnchoredObj().SetObjLeft( nTopOfAnch -
+ aRelPos.X() -
+ aObjBoundRect.Width() );
+ }
+ else
+ {
+ GetAnchoredObj().SetObjLeft( nTopOfAnch + aRelPos.X() );
+ }
+ // <--
+ }
+ else
+ {
+ aRelPos.Y() = nTmpRelPosY;
+ GetAnchoredObj().SetObjTop( nTopOfAnch + aRelPos.Y() );
+ }
+ // If the anchor frame is the first content of the table cell
+ // and the object still doesn't fit, the table frame is notified,
+ // that the object doesn't fit into the table cell.
+ nDist = (GetAnchoredObj().GetObjRect().*fnRect->fnBottomDist)(
+ (pUpperOfOrientFrm->*fnRect->fnGetPrtBottom)() );
+ if ( nDist < 0 &&
+ pOrientFrm == &rAnchorTxtFrm && !pOrientFrm->GetIndPrev() )
+ {
+ const_cast<SwTabFrm*>(pOrientFrm->FindTabFrm())
+ ->SetDoesObjsFit( sal_False );
+ }
+ }
+ }
+ else
+ {
+ // follow text flow
+ const bool bInFtn = rAnchorTxtFrm.IsInFtn();
+ while( bMoveable && nDist < 0 )
+ {
+ bool bInSct = pUpperOfOrientFrm->IsInSct();
+ if ( bInSct )
+ {
+ const SwLayoutFrm* pTmp = pUpperOfOrientFrm->FindSctFrm()->GetUpper();
+ nDist = (GetAnchoredObj().GetObjRect().*fnRect->fnBottomDist)(
+ (pTmp->*fnRect->fnGetPrtBottom)() );
+ // #i23129# - Try to flow into next
+ // section|section column. Thus, do *not* leave section
+ // area, if anchored object doesn't fit into upper of section.
+ // But the anchored object is allowed to overlap bottom
+ // section|section column.
+ if ( nDist >= 0 )
+ {
+ break;
+ }
+ }
+ if ( !bInSct &&
+ (GetAnchoredObj().GetObjRect().*fnRect->fnGetTop)() ==
+ (pUpperOfOrientFrm->*fnRect->fnGetPrtTop)() )
+ //Das teil passt nimmer, da hilft auch kein moven.
+ break;
+
+ const SwLayoutFrm* pNextLay = pUpperOfOrientFrm->GetLeaf(
+ ( bInSct
+ ? MAKEPAGE_NOSECTION
+ : ( bInFtn ? MAKEPAGE_NONE : MAKEPAGE_APPEND ) ),
+ sal_True, &rAnchorTxtFrm );
+ // correction:
+ // If anchor is in footnote and proposed next layout environment
+ // isn't a footnote frame, object can't follow the text flow
+ if ( bInFtn && pNextLay && !pNextLay->IsFtnFrm() )
+ {
+ pNextLay = 0L;
+ }
+ if ( pNextLay )
+ {
+ SWRECTFNX( pNextLay )
+ if ( !bInSct ||
+ ( pUpperOfOrientFrm->FindSctFrm()->IsAnFollow( pNextLay->FindSctFrm() ) &&
+ (pNextLay->Prt().*fnRectX->fnGetHeight)() ) )
+ {
+ SwTwips nTmpRelPosY =
+ (*fnRect->fnYDiff)( (pNextLay->*fnRect->fnGetPrtTop)(),
+ nTopOfAnch );
+ if ( bVert )
+ aRelPos.X() = nTmpRelPosY;
+ else
+ aRelPos.Y() = nTmpRelPosY;
+ pUpperOfOrientFrm = pNextLay;
+ SWREFRESHFN( pUpperOfOrientFrm )
+ bMoveable = rAnchorTxtFrm.IsMoveable( (SwLayoutFrm*)pUpperOfOrientFrm );
+ if( bVertX )
+ {
+ // --> OD 2009-08-31 #mongolianlayout#
+ if ( !bVertL2R )
+ {
+ GetAnchoredObj().SetObjLeft( nTopOfAnch -
+ aRelPos.X() -
+ aObjBoundRect.Width() );
+ }
+ else
+ {
+ GetAnchoredObj().SetObjLeft( nTopOfAnch +
+ aRelPos.X() );
+ }
+ // <--
+ }
+ else
+ GetAnchoredObj().SetObjTop( nTopOfAnch +
+ aRelPos.Y() );
+ nDist = (GetAnchoredObj().GetObjRect().*fnRect->fnBottomDist)(
+ (pUpperOfOrientFrm->*fnRect->fnGetPrtBottom)() );
+ }
+ // #i23129# - leave section area
+ else if ( bInSct )
+ {
+ const SwLayoutFrm* pTmp = pUpperOfOrientFrm->FindSctFrm()->GetUpper();
+ nDist = (GetAnchoredObj().GetObjRect().*fnRect->fnBottomDist)(
+ (pTmp->*fnRect->fnGetPrtBottom)() );
+ if( nDist < 0 )
+ pUpperOfOrientFrm = pTmp;
+ else
+ break;
+ }
+ }
+ else if ( bInSct )
+ {
+ // Wenn wir innerhalb des Bereich nicht genug Platz haben, gucken
+ // wir uns mal die Seite an.
+ const SwLayoutFrm* pTmp = pUpperOfOrientFrm->FindSctFrm()->GetUpper();
+ nDist = (GetAnchoredObj().GetObjRect().*fnRect->fnBottomDist)(
+ (pTmp->*fnRect->fnGetPrtBottom)() );
+ if( nDist < 0 )
+ pUpperOfOrientFrm = pTmp;
+ else
+ break;
+ }
+ else
+ bMoveable = false;
+ }
+ }
+ }
+
+ // keep layout frame vertical position is oriented at.
+ mpVertPosOrientFrm = pUpperOfOrientFrm;
+
+ }
+
+ // determine 'horizontal' position
+ {
+ // determine horizontal positioning and alignment attributes
+ SwFmtHoriOrient aHori( rFrmFmt.GetHoriOrient() );
+
+ // set calculated vertical position in order to determine correct
+ // frame, the horizontal position is oriented at.
+ const SwTwips nTopOfAnch = _GetTopForObjPos( *pAnchorFrmForVertPos, fnRect, bVert );
+ if( bVert )
+ {
+ // --> OD 2009-08-31 #mongolianlayout#
+ if ( !bVertL2R )
+ {
+ GetAnchoredObj().SetObjLeft( nTopOfAnch -
+ aRelPos.X() - aObjBoundRect.Width() );
+ }
+ else
+ {
+ GetAnchoredObj().SetObjLeft( nTopOfAnch + aRelPos.X() );
+ }
+ // <--
+ }
+ else
+ GetAnchoredObj().SetObjTop( nTopOfAnch + aRelPos.Y() );
+
+ // determine frame, horizontal position is oriented at.
+ // #i28701# - If floating screen object doesn't follow
+ // the text flow, its horizontal position is oriented at <pOrientFrm>.
+ const SwFrm* pHoriOrientFrm = DoesObjFollowsTextFlow()
+ ? &_GetHoriVirtualAnchor( *mpVertPosOrientFrm )
+ : pOrientFrm;
+
+ // #i26791# - get 'horizontal' offset to frame anchor position.
+ SwTwips nHoriOffsetToFrmAnchorPos( 0L );
+ SwTwips nRelPosX = _CalcRelPosX( *pHoriOrientFrm, aEnvOfObj,
+ aHori, rLR, rUL, bWrapThrough,
+ ( bVert ? aRelPos.X() : aRelPos.Y() ),
+ nHoriOffsetToFrmAnchorPos );
+
+ // #i26791# - determine offset to 'horizontal' frame
+ // anchor position, depending on layout-direction
+ if ( bVert )
+ {
+ aRelPos.Y() = nRelPosX;
+ maOffsetToFrmAnchorPos.Y() = nHoriOffsetToFrmAnchorPos;
+ }
+ else
+ {
+ aRelPos.X() = nRelPosX;
+ maOffsetToFrmAnchorPos.X() = nHoriOffsetToFrmAnchorPos;
+ }
+
+ // save calculated horizontal position - needed for filters
+ // (including the xml-filter)
+ {
+ SwTwips nAttrRelPosX = nRelPosX - nHoriOffsetToFrmAnchorPos;
+ if ( aHori.GetHoriOrient() != text::HoriOrientation::NONE &&
+ aHori.GetPos() != nAttrRelPosX )
+ {
+ aHori.SetPos( nAttrRelPosX );
+ const_cast<SwFrmFmt&>(rFrmFmt).LockModify();
+ const_cast<SwFrmFmt&>(rFrmFmt).SetFmtAttr( aHori );
+ const_cast<SwFrmFmt&>(rFrmFmt).UnlockModify();
+ }
+ }
+ }
+
+ // set absolute position at object
+ const SwTwips nTopOfAnch = _GetTopForObjPos( *pAnchorFrmForVertPos, fnRect, bVert );
+ if( bVert )
+ {
+ // --> OD 2009-08-31 #mongolianlayout#
+ if ( !bVertL2R )
+ {
+ GetAnchoredObj().SetObjLeft( nTopOfAnch -
+ aRelPos.X() - aObjBoundRect.Width() );
+ }
+ else
+ {
+ GetAnchoredObj().SetObjLeft( nTopOfAnch + aRelPos.X() );
+ }
+ // <--
+ GetAnchoredObj().SetObjTop( rAnchorTxtFrm.Frm().Top() +
+ aRelPos.Y() );
+ }
+ else
+ {
+ GetAnchoredObj().SetObjLeft( rAnchorTxtFrm.Frm().Left() +
+ aRelPos.X() );
+ GetAnchoredObj().SetObjTop( nTopOfAnch + aRelPos.Y() );
+ }
+
+ // set relative position at object
+ GetAnchoredObj().SetCurrRelPos( aRelPos );
+}
+
+/** determine frame for horizontal position
+
+ @author OD
+*/
+const SwFrm& SwToCntntAnchoredObjectPosition::_GetHoriVirtualAnchor(
+ const SwLayoutFrm& _rProposedFrm ) const
+{
+ const SwFrm* pHoriVirtAnchFrm = &_rProposedFrm;
+
+ // Search for first lower content frame, which is the anchor or a follow
+ // of the anchor (Note: <Anchor.IsAnFollow( Anchor )> is true)
+ // If none found, <_rProposedFrm> is returned.
+ const SwFrm* pFrm = _rProposedFrm.Lower();
+ while ( pFrm )
+ {
+ if ( pFrm->IsCntntFrm() &&
+ GetAnchorTxtFrm().IsAnFollow( static_cast<const SwCntntFrm*>(pFrm) ) )
+ {
+ pHoriVirtAnchFrm = pFrm;
+ break;
+ }
+ pFrm = pFrm->GetNext();
+ }
+
+ return *pHoriVirtAnchFrm;
+}
+
+const SwLayoutFrm& SwToCntntAnchoredObjectPosition::GetVertPosOrientFrm() const
+{
+ return *mpVertPosOrientFrm;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/objectpositioning/tolayoutanchoredobjectposition.cxx b/sw/source/core/objectpositioning/tolayoutanchoredobjectposition.cxx
new file mode 100644
index 000000000000..3567441ae68b
--- /dev/null
+++ b/sw/source/core/objectpositioning/tolayoutanchoredobjectposition.cxx
@@ -0,0 +1,257 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+#include <tolayoutanchoredobjectposition.hxx>
+#include <anchoredobject.hxx>
+#include <frame.hxx>
+#include <pagefrm.hxx>
+#include <svx/svdobj.hxx>
+#include <frmfmt.hxx>
+#include <fmtanchr.hxx>
+#include <fmtornt.hxx>
+#include <fmtsrnd.hxx>
+#include <IDocumentSettingAccess.hxx>
+#include <frmatr.hxx>
+#include "viewsh.hxx"
+#include "viewopt.hxx"
+#include "rootfrm.hxx"
+#include <editeng/lrspitem.hxx>
+#include <editeng/ulspitem.hxx>
+
+using namespace objectpositioning;
+using namespace ::com::sun::star;
+
+
+SwToLayoutAnchoredObjectPosition::SwToLayoutAnchoredObjectPosition( SdrObject& _rDrawObj )
+ : SwAnchoredObjectPosition( _rDrawObj ),
+ maRelPos( Point() ),
+ // --> OD 2004-06-17 #i26791#
+ maOffsetToFrmAnchorPos( Point() )
+{}
+
+SwToLayoutAnchoredObjectPosition::~SwToLayoutAnchoredObjectPosition()
+{}
+
+/** calculate position for object position type TO_LAYOUT
+
+ @author OD
+*/
+void SwToLayoutAnchoredObjectPosition::CalcPosition()
+{
+ const SwRect aObjBoundRect( GetAnchoredObj().GetObjRect() );
+
+ SWRECTFN( (&GetAnchorFrm()) );
+
+ const SwFrmFmt& rFrmFmt = GetFrmFmt();
+ const SvxLRSpaceItem &rLR = rFrmFmt.GetLRSpace();
+ const SvxULSpaceItem &rUL = rFrmFmt.GetULSpace();
+
+ const bool bFlyAtFly = FLY_AT_FLY == rFrmFmt.GetAnchor().GetAnchorId();
+
+ // determine position.
+ // 'vertical' and 'horizontal' position are calculated separately
+ Point aRelPos;
+
+ // calculate 'vertical' position
+ SwFmtVertOrient aVert( rFrmFmt.GetVertOrient() );
+ {
+ // to-frame anchored objects are *only* vertical positioned centered or
+ // bottom, if its wrap mode is 'throught' and its anchor frame has fixed
+ // size. Otherwise, it's positioned top.
+ sal_Int16 eVertOrient = aVert.GetVertOrient();
+ if ( ( bFlyAtFly &&
+ ( eVertOrient == text::VertOrientation::CENTER ||
+ eVertOrient == text::VertOrientation::BOTTOM ) &&
+ SURROUND_THROUGHT != rFrmFmt.GetSurround().GetSurround() &&
+ !GetAnchorFrm().HasFixSize() ) )
+ {
+ eVertOrient = text::VertOrientation::TOP;
+ }
+ // --> OD 2004-06-17 #i26791# - get vertical offset to frame anchor position.
+ SwTwips nVertOffsetToFrmAnchorPos( 0L );
+ SwTwips nRelPosY =
+ _GetVertRelPos( GetAnchorFrm(), GetAnchorFrm(), eVertOrient,
+ aVert.GetRelationOrient(), aVert.GetPos(),
+ rLR, rUL, nVertOffsetToFrmAnchorPos );
+
+
+ // keep the calculated relative vertical position - needed for filters
+ // (including the xml-filter)
+ {
+ SwTwips nAttrRelPosY = nRelPosY - nVertOffsetToFrmAnchorPos;
+ if ( aVert.GetVertOrient() != text::VertOrientation::NONE &&
+ aVert.GetPos() != nAttrRelPosY )
+ {
+ aVert.SetPos( nAttrRelPosY );
+ const_cast<SwFrmFmt&>(rFrmFmt).LockModify();
+ const_cast<SwFrmFmt&>(rFrmFmt).SetFmtAttr( aVert );
+ const_cast<SwFrmFmt&>(rFrmFmt).UnlockModify();
+ }
+ }
+
+ // determine absolute 'vertical' position, depending on layout-direction
+ // --> OD 2004-06-17 #i26791# - determine offset to 'vertical' frame
+ // anchor position, depending on layout-direction
+ if( bVert )
+ {
+ OSL_ENSURE( !bRev, "<SwToLayoutAnchoredObjectPosition::CalcPosition()> - reverse layout set." );
+ //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin
+ if ( bVertL2R )
+ aRelPos.X() = nRelPosY;
+ else
+ aRelPos.X() = -nRelPosY - aObjBoundRect.Width();
+ maOffsetToFrmAnchorPos.X() = nVertOffsetToFrmAnchorPos;
+ }
+ else
+ {
+ aRelPos.Y() = nRelPosY;
+ maOffsetToFrmAnchorPos.Y() = nVertOffsetToFrmAnchorPos;
+ }
+
+ // if in online-layout the bottom of to-page anchored object is beyond
+ // the page bottom, the page frame has to grow by growing its body frame.
+ const ViewShell *pSh = GetAnchorFrm().getRootFrm()->GetCurrShell();
+ if ( !bFlyAtFly && GetAnchorFrm().IsPageFrm() &&
+ pSh && pSh->GetViewOptions()->getBrowseMode() )
+ {
+ const long nAnchorBottom = GetAnchorFrm().Frm().Bottom();
+ const long nBottom = GetAnchorFrm().Frm().Top() +
+ aRelPos.Y() + aObjBoundRect.Height();
+ if ( nAnchorBottom < nBottom )
+ {
+ static_cast<SwPageFrm&>(GetAnchorFrm()).
+ FindBodyCont()->Grow( nBottom - nAnchorBottom );
+ }
+ }
+ } // end of determination of vertical position
+
+ // calculate 'horizontal' position
+ SwFmtHoriOrient aHori( rFrmFmt.GetHoriOrient() );
+ {
+ // consider toggle of horizontal position for even pages.
+ const bool bToggle = aHori.IsPosToggle() &&
+ !GetAnchorFrm().FindPageFrm()->OnRightPage();
+ sal_Int16 eHoriOrient = aHori.GetHoriOrient();
+ sal_Int16 eRelOrient = aHori.GetRelationOrient();
+ // toggle orientation
+ _ToggleHoriOrientAndAlign( bToggle, eHoriOrient, eRelOrient );
+
+ // determine alignment values:
+ // <nWidth>: 'width' of the alignment area
+ // <nOffset>: offset of alignment area, relative to 'left' of
+ // frame anchor position
+ SwTwips nWidth, nOffset;
+ {
+ bool bDummy; // in this context irrelevant output parameter
+ _GetHoriAlignmentValues( GetAnchorFrm(), GetAnchorFrm(),
+ eRelOrient, false,
+ nWidth, nOffset, bDummy );
+ }
+
+ SwTwips nObjWidth = (aObjBoundRect.*fnRect->fnGetWidth)();
+
+ // determine relative horizontal position
+ SwTwips nRelPosX;
+ if ( text::HoriOrientation::NONE == eHoriOrient )
+ {
+ if( bToggle ||
+ ( !aHori.IsPosToggle() && GetAnchorFrm().IsRightToLeft() ) )
+ {
+ nRelPosX = nWidth - nObjWidth - aHori.GetPos();
+ }
+ else
+ {
+ nRelPosX = aHori.GetPos();
+ }
+ }
+ else if ( text::HoriOrientation::CENTER == eHoriOrient )
+ nRelPosX = (nWidth / 2) - (nObjWidth / 2);
+ else if ( text::HoriOrientation::RIGHT == eHoriOrient )
+ nRelPosX = nWidth - ( nObjWidth +
+ ( bVert ? rUL.GetLower() : rLR.GetRight() ) );
+ else
+ nRelPosX = bVert ? rUL.GetUpper() : rLR.GetLeft();
+ nRelPosX += nOffset;
+
+ // no 'negative' relative horizontal position
+ // OD 06.11.2003 #FollowTextFlowAtFrame# - negative positions allow for
+ // to frame anchored objects.
+ if ( !bFlyAtFly && nRelPosX < 0 )
+ {
+ nRelPosX = 0;
+ }
+
+ // determine absolute 'horizontal' position, depending on layout-direction
+ // --> OD 2004-06-17 #i26791# - determine offset to 'horizontal' frame
+ // anchor position, depending on layout-direction
+ //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin
+ // --> OD 2009-09-04 #mongolianlayout#
+ if( bVert || bVertL2R )
+ // <--
+ {
+
+ aRelPos.Y() = nRelPosX;
+ maOffsetToFrmAnchorPos.Y() = nOffset;
+ }
+ else
+ {
+ aRelPos.X() = nRelPosX;
+ maOffsetToFrmAnchorPos.X() = nOffset;
+ }
+
+ // keep the calculated relative horizontal position - needed for filters
+ // (including the xml-filter)
+ {
+ SwTwips nAttrRelPosX = nRelPosX - nOffset;
+ if ( text::HoriOrientation::NONE != aHori.GetHoriOrient() &&
+ aHori.GetPos() != nAttrRelPosX )
+ {
+ aHori.SetPos( nAttrRelPosX );
+ const_cast<SwFrmFmt&>(rFrmFmt).LockModify();
+ const_cast<SwFrmFmt&>(rFrmFmt).SetFmtAttr( aHori );
+ const_cast<SwFrmFmt&>(rFrmFmt).UnlockModify();
+ }
+ }
+ } // end of determination of horizontal position
+
+ // keep calculate relative position
+ maRelPos = aRelPos;
+}
+
+/** calculated relative position for object position
+
+ @author OD
+*/
+Point SwToLayoutAnchoredObjectPosition::GetRelPos() const
+{
+ return maRelPos;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/ole/ndole.cxx b/sw/source/core/ole/ndole.cxx
new file mode 100644
index 000000000000..a9b3d43007fb
--- /dev/null
+++ b/sw/source/core/ole/ndole.cxx
@@ -0,0 +1,997 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+#include <com/sun/star/embed/NoVisualAreaSizeException.hpp>
+#include <com/sun/star/container/XChild.hpp>
+#include <com/sun/star/embed/XEmbedPersist.hpp>
+#include <com/sun/star/embed/XLinkageSupport.hpp>
+#include <com/sun/star/embed/Aspects.hpp>
+#include <com/sun/star/embed/EmbedMisc.hpp>
+#include <com/sun/star/embed/EmbedStates.hpp>
+#include <com/sun/star/util/XCloseable.hpp>
+#include <com/sun/star/util/XModifiable.hpp>
+#include <com/sun/star/document/XEventBroadcaster.hpp>
+#include <cppuhelper/implbase1.hxx>
+
+#include <cppuhelper/implbase2.hxx>
+#include <toolkit/helper/vclunohelper.hxx>
+#include <hintids.hxx>
+#include <tools/urlobj.hxx>
+#include <sfx2/docfile.hxx>
+#include <sfx2/app.hxx>
+#include <sfx2/linkmgr.hxx>
+#include <unotools/configitem.hxx>
+#include <vcl/outdev.hxx>
+#include <fmtanchr.hxx>
+#include <frmfmt.hxx>
+#include <doc.hxx>
+#include <docsh.hxx>
+#include <pam.hxx>
+#include <section.hxx>
+#include <cntfrm.hxx>
+#include <frmatr.hxx>
+#include <ndole.hxx>
+
+#include <comphelper/classids.hxx>
+#include <vcl/graph.hxx>
+#include <sot/formats.hxx>
+#include <unotools/ucbstreamhelper.hxx>
+#include <svtools/filter.hxx>
+#include <comcore.hrc>
+
+using rtl::OUString;
+using namespace utl;
+using namespace com::sun::star::uno;
+using namespace com::sun::star;
+
+class SwOLELRUCache : private SvPtrarr, private utl::ConfigItem
+{
+ sal_uInt16 nLRU_InitSize;
+ sal_Bool bInUnload;
+ uno::Sequence< rtl::OUString > GetPropertyNames();
+
+public:
+ SwOLELRUCache();
+
+ virtual void Notify( const uno::Sequence<
+ rtl::OUString>& aPropertyNames );
+ virtual void Commit();
+ void Load();
+
+ void SetInUnload( sal_Bool bFlag ) { bInUnload = bFlag; }
+ using SvPtrarr::Count;
+
+ void InsertObj( SwOLEObj& rObj );
+ void RemoveObj( SwOLEObj& rObj );
+
+ void RemovePtr( SwOLEObj* pObj )
+ {
+ sal_uInt16 nPos = SvPtrarr::GetPos( pObj );
+ if( USHRT_MAX != nPos )
+ SvPtrarr::Remove( nPos );
+ }
+};
+
+SwOLELRUCache* pOLELRU_Cache = 0;
+
+class SwOLEListener_Impl : public ::cppu::WeakImplHelper1< embed::XStateChangeListener >
+{
+ SwOLEObj* mpObj;
+public:
+ SwOLEListener_Impl( SwOLEObj* pObj );
+ void Release();
+ virtual void SAL_CALL changingState( const lang::EventObject& aEvent, ::sal_Int32 nOldState, ::sal_Int32 nNewState ) throw (embed::WrongStateException, uno::RuntimeException);
+ virtual void SAL_CALL stateChanged( const lang::EventObject& aEvent, ::sal_Int32 nOldState, ::sal_Int32 nNewState ) throw (uno::RuntimeException);
+ virtual void SAL_CALL disposing( const lang::EventObject& aEvent ) throw (uno::RuntimeException);
+};
+
+SwOLEListener_Impl::SwOLEListener_Impl( SwOLEObj* pObj )
+: mpObj( pObj )
+{
+ if ( mpObj->IsOleRef() && mpObj->GetOleRef()->getCurrentState() == embed::EmbedStates::RUNNING )
+ {
+ pOLELRU_Cache->InsertObj( *mpObj );
+ }
+}
+
+void SAL_CALL SwOLEListener_Impl::changingState( const lang::EventObject&, ::sal_Int32 , ::sal_Int32 ) throw (embed::WrongStateException, uno::RuntimeException)
+{
+}
+
+void SAL_CALL SwOLEListener_Impl::stateChanged( const lang::EventObject&, ::sal_Int32 nOldState, ::sal_Int32 nNewState ) throw (uno::RuntimeException)
+{
+ if ( mpObj && nOldState == embed::EmbedStates::LOADED && nNewState == embed::EmbedStates::RUNNING )
+ {
+ if( !pOLELRU_Cache )
+ pOLELRU_Cache = new SwOLELRUCache;
+ pOLELRU_Cache->InsertObj( *mpObj );
+ }
+ else if ( mpObj && nNewState == embed::EmbedStates::LOADED && nOldState == embed::EmbedStates::RUNNING )
+ {
+ if ( pOLELRU_Cache )
+ pOLELRU_Cache->RemoveObj( *mpObj );
+ }
+}
+
+void SwOLEListener_Impl::Release()
+{
+ if ( mpObj && pOLELRU_Cache )
+ pOLELRU_Cache->RemoveObj( *mpObj );
+ mpObj=0;
+ release();
+}
+
+void SAL_CALL SwOLEListener_Impl::disposing( const lang::EventObject& ) throw (uno::RuntimeException)
+{
+ if ( mpObj && pOLELRU_Cache )
+ pOLELRU_Cache->RemoveObj( *mpObj );
+}
+
+// --------------------
+// SwEmbedObjectLink
+// --------------------
+// TODO/LATER: actually SwEmbedObjectLink should be used here, but because different objects are used to control
+// embedded object different link objects with the same functionality had to be implemented
+
+class SwEmbedObjectLink : public sfx2::SvBaseLink
+{
+ SwOLENode* pOleNode;
+
+public:
+ SwEmbedObjectLink(SwOLENode* pNode);
+ virtual ~SwEmbedObjectLink();
+
+ virtual void Closed();
+ virtual void DataChanged( const String& rMimeType,
+ const uno::Any & rValue );
+
+ sal_Bool Connect() { return GetRealObject() != NULL; }
+};
+
+// -----------------------------------------------------------------------------
+
+SwEmbedObjectLink::SwEmbedObjectLink(SwOLENode* pNode):
+ ::sfx2::SvBaseLink( ::sfx2::LINKUPDATE_ONCALL, SOT_FORMATSTR_ID_SVXB ),
+ pOleNode(pNode)
+{
+ SetSynchron( sal_False );
+}
+
+// -----------------------------------------------------------------------------
+
+SwEmbedObjectLink::~SwEmbedObjectLink()
+{
+}
+
+// -----------------------------------------------------------------------------
+
+void SwEmbedObjectLink::DataChanged( const String& ,
+ const uno::Any & )
+{
+ if ( !pOleNode->UpdateLinkURL_Impl() )
+ {
+ // the link URL was not changed
+ uno::Reference< embed::XEmbeddedObject > xObject = pOleNode->GetOLEObj().GetOleRef();
+ OSL_ENSURE( xObject.is(), "The object must exist always!\n" );
+ if ( xObject.is() )
+ {
+ // let the object reload the link
+ // TODO/LATER: reload call could be used for this case
+
+ try
+ {
+ sal_Int32 nState = xObject->getCurrentState();
+ if ( nState != embed::EmbedStates::LOADED )
+ {
+ // in some cases the linked file probably is not locked so it could be changed
+ xObject->changeState( embed::EmbedStates::LOADED );
+ xObject->changeState( nState );
+ }
+ }
+ catch ( uno::Exception& )
+ {
+ }
+ }
+ }
+
+ pOleNode->GetNewReplacement();
+}
+
+// -----------------------------------------------------------------------------
+
+void SwEmbedObjectLink::Closed()
+{
+ pOleNode->BreakFileLink_Impl();
+ SvBaseLink::Closed();
+}
+
+
+// --------------------
+// SwOLENode
+// --------------------
+
+SwOLENode::SwOLENode( const SwNodeIndex &rWhere,
+ const svt::EmbeddedObjectRef& xObj,
+ SwGrfFmtColl *pGrfColl,
+ SwAttrSet* pAutoAttr ) :
+ SwNoTxtNode( rWhere, ND_OLENODE, pGrfColl, pAutoAttr ),
+ aOLEObj( xObj ),
+ pGraphic(0),
+ bOLESizeInvalid( sal_False ),
+ mpObjectLink( NULL )
+{
+ aOLEObj.SetNode( this );
+}
+
+SwOLENode::SwOLENode( const SwNodeIndex &rWhere,
+ const String &rString,
+ sal_Int64 nAspect,
+ SwGrfFmtColl *pGrfColl,
+ SwAttrSet* pAutoAttr ) :
+ SwNoTxtNode( rWhere, ND_OLENODE, pGrfColl, pAutoAttr ),
+ aOLEObj( rString, nAspect ),
+ pGraphic(0),
+ bOLESizeInvalid( sal_False ),
+ mpObjectLink( NULL )
+{
+ aOLEObj.SetNode( this );
+}
+
+SwOLENode::~SwOLENode()
+{
+ DisconnectFileLink_Impl();
+ delete pGraphic;
+}
+
+Graphic* SwOLENode::GetGraphic()
+{
+ if ( aOLEObj.GetOleRef().is() )
+ return aOLEObj.xOLERef.GetGraphic();
+ return pGraphic;
+}
+
+SwCntntNode *SwOLENode::SplitCntntNode( const SwPosition & )
+{
+ // OLE-Objecte vervielfaeltigen ??
+ OSL_FAIL( "OleNode: can't split." );
+ return this;
+}
+
+// Laden eines in den Undo-Bereich verschobenen OLE-Objekts
+
+sal_Bool SwOLENode::RestorePersistentData()
+{
+ DBG_ASSERT( aOLEObj.GetOleRef().is(), "No object to restore!" );
+ if ( aOLEObj.xOLERef.is() )
+ {
+ // Falls bereits eine SvPersist-Instanz existiert, nehmen wir diese
+ SfxObjectShell* p = GetDoc()->GetPersist();
+ if( !p )
+ {
+ // TODO/LATER: reicht hier nicht ein EmbeddedObjectContainer? Was passiert mit
+ // diesem Dokument?
+ OSL_ENSURE( !this, "warum wird hier eine DocShell angelegt?" );
+ p = new SwDocShell( GetDoc(), SFX_CREATE_MODE_INTERNAL );
+ p->DoInitNew( NULL );
+ }
+
+ uno::Reference < container::XChild > xChild( aOLEObj.xOLERef.GetObject(), uno::UNO_QUERY );
+ if ( xChild.is() )
+ xChild->setParent( p->GetModel() );
+
+ DBG_ASSERT( aOLEObj.aName.Len(), "No object name!" );
+ ::rtl::OUString aObjName;
+ if ( !p->GetEmbeddedObjectContainer().InsertEmbeddedObject( aOLEObj.xOLERef.GetObject(), aObjName ) )
+ {
+ if ( xChild.is() )
+ xChild->setParent( 0 );
+ OSL_FAIL( "InsertObject failed" );
+ }
+ else
+ {
+ aOLEObj.aName = aObjName;
+ aOLEObj.xOLERef.AssignToContainer( &p->GetEmbeddedObjectContainer(), aObjName );
+ CheckFileLink_Impl();
+ }
+ }
+
+ return sal_True;
+}
+
+// OLE object is transported into UNDO area
+sal_Bool SwOLENode::SavePersistentData()
+{
+ if( aOLEObj.xOLERef.is() )
+ {
+ comphelper::EmbeddedObjectContainer* pCnt = aOLEObj.xOLERef.GetContainer();
+
+#if OSL_DEBUG_LEVEL > 0
+ SfxObjectShell* p = GetDoc()->GetPersist();
+ DBG_ASSERT( p, "No document!" );
+ if( p )
+ {
+ comphelper::EmbeddedObjectContainer& rCnt = p->GetEmbeddedObjectContainer();
+ OSL_ENSURE( !pCnt || &rCnt == pCnt, "The helper is assigned to unexpected container!\n" );
+ }
+#endif
+
+ if ( pCnt && pCnt->HasEmbeddedObject( aOLEObj.aName ) )
+ {
+ uno::Reference < container::XChild > xChild( aOLEObj.xOLERef.GetObject(), uno::UNO_QUERY );
+ if ( xChild.is() )
+ xChild->setParent( 0 );
+
+ pCnt->RemoveEmbeddedObject( aOLEObj.aName, sal_False );
+
+ // TODO/LATER: aOLEObj.aName has no meaning here, since the undo container contains the object
+ // by different name, in future it might makes sence that the name is transported here.
+ aOLEObj.xOLERef.AssignToContainer( 0, aOLEObj.aName );
+ try
+ {
+ // "unload" object
+ aOLEObj.xOLERef->changeState( embed::EmbedStates::LOADED );
+ }
+ catch ( uno::Exception& )
+ {
+ }
+ }
+ }
+
+ DisconnectFileLink_Impl();
+
+ return sal_True;
+}
+
+
+SwOLENode * SwNodes::MakeOLENode( const SwNodeIndex & rWhere,
+ const svt::EmbeddedObjectRef& xObj,
+ SwGrfFmtColl* pGrfColl,
+ SwAttrSet* pAutoAttr )
+{
+ OSL_ENSURE( pGrfColl,"SwNodes::MakeOLENode: Formatpointer ist 0." );
+
+ SwOLENode *pNode =
+ new SwOLENode( rWhere, xObj, pGrfColl, pAutoAttr );
+
+ // set parent if XChild is supported
+ //!! needed to supply Math objects with a valid reference device
+ uno::Reference< container::XChild > xChild( pNode->GetOLEObj().GetObject().GetObject(), UNO_QUERY );
+ if (xChild.is())
+ {
+ SwDocShell *pDocSh = GetDoc()->GetDocShell();
+ if (pDocSh)
+ xChild->setParent( pDocSh->GetModel() );
+ }
+
+ return pNode;
+}
+
+
+SwOLENode * SwNodes::MakeOLENode( const SwNodeIndex & rWhere,
+ const String &rName, sal_Int64 nAspect, SwGrfFmtColl* pGrfColl, SwAttrSet* pAutoAttr )
+{
+ OSL_ENSURE( pGrfColl,"SwNodes::MakeOLENode: Formatpointer ist 0." );
+
+ SwOLENode *pNode =
+ new SwOLENode( rWhere, rName, nAspect, pGrfColl, pAutoAttr );
+
+ // set parent if XChild is supported
+ //!! needed to supply Math objects with a valid reference device
+ uno::Reference< container::XChild > xChild( pNode->GetOLEObj().GetObject().GetObject(), UNO_QUERY );
+ if (xChild.is())
+ {
+ SwDocShell *pDocSh= GetDoc()->GetDocShell();
+ if (pDocSh)
+ xChild->setParent( pDocSh->GetModel() );
+ }
+
+ return pNode;
+}
+
+Size SwOLENode::GetTwipSize() const
+{
+ MapMode aMapMode( MAP_TWIP );
+ return ((SwOLENode*)this)->aOLEObj.GetObject().GetSize( &aMapMode );
+}
+
+SwCntntNode* SwOLENode::MakeCopy( SwDoc* pDoc, const SwNodeIndex& rIdx ) const
+{
+ // Falls bereits eine SvPersist-Instanz existiert, nehmen wir diese
+ SfxObjectShell* pPersistShell = pDoc->GetPersist();
+ if( !pPersistShell )
+ {
+ // TODO/LATER: is EmbeddedObjectContainer not enough?
+ // the created document will be closed by pDoc ( should use SfxObjectShellLock )
+ pPersistShell = new SwDocShell( pDoc, SFX_CREATE_MODE_INTERNAL );
+ pDoc->SetTmpDocShell( pPersistShell );
+ pPersistShell->DoInitNew( NULL );
+ }
+
+ // Wir hauen das Ding auf SvPersist-Ebene rein
+ // TODO/LATER: check if using the same naming scheme for all apps works here
+ ::rtl::OUString aNewName/*( Sw3Io::UniqueName( p->GetStorage(), "Obj" ) )*/;
+ SfxObjectShell* pSrc = GetDoc()->GetPersist();
+
+ pPersistShell->GetEmbeddedObjectContainer().CopyAndGetEmbeddedObject(
+ pSrc->GetEmbeddedObjectContainer(),
+ pSrc->GetEmbeddedObjectContainer().GetEmbeddedObject( aOLEObj.aName ),
+ aNewName );
+
+ SwOLENode* pOLENd = pDoc->GetNodes().MakeOLENode( rIdx, aNewName, GetAspect(),
+ (SwGrfFmtColl*)pDoc->GetDfltGrfFmtColl(),
+ (SwAttrSet*)GetpSwAttrSet() );
+
+ pOLENd->SetChartTblName( GetChartTblName() );
+ pOLENd->SetTitle( GetTitle() );
+ pOLENd->SetDescription( GetDescription() );
+ pOLENd->SetContour( HasContour(), HasAutomaticContour() );
+ pOLENd->SetAspect( GetAspect() ); // the replacement image must be already copied
+
+ pOLENd->SetOLESizeInvalid( sal_True );
+ pDoc->SetOLEPrtNotifyPending();
+
+ return pOLENd;
+}
+
+sal_Bool SwOLENode::IsInGlobalDocSection() const
+{
+ // suche den "Body Anchor"
+ sal_uLong nEndExtraIdx = GetNodes().GetEndOfExtras().GetIndex();
+ const SwNode* pAnchorNd = this;
+ do {
+ SwFrmFmt* pFlyFmt = pAnchorNd->GetFlyFmt();
+ if( !pFlyFmt )
+ return sal_False;
+
+ const SwFmtAnchor& rAnchor = pFlyFmt->GetAnchor();
+ if( !rAnchor.GetCntntAnchor() )
+ return sal_False;
+
+ pAnchorNd = &rAnchor.GetCntntAnchor()->nNode.GetNode();
+ } while( pAnchorNd->GetIndex() < nEndExtraIdx );
+
+ const SwSectionNode* pSectNd = pAnchorNd->FindSectionNode();
+ if( !pSectNd )
+ return sal_False;
+
+ while( pSectNd )
+ {
+ pAnchorNd = pSectNd;
+ pSectNd = pAnchorNd->StartOfSectionNode()->FindSectionNode();
+ }
+
+ // in pAnchorNd steht der zuletzt gefundene Section Node. Der muss
+ // jetzt die Bedingung fuers GlobalDoc erfuellen.
+ pSectNd = (SwSectionNode*)pAnchorNd;
+ return FILE_LINK_SECTION == pSectNd->GetSection().GetType() &&
+ pSectNd->GetIndex() > nEndExtraIdx;
+}
+
+sal_Bool SwOLENode::IsOLEObjectDeleted() const
+{
+ sal_Bool bRet = sal_False;
+ if( aOLEObj.xOLERef.is() )
+ {
+ SfxObjectShell* p = GetDoc()->GetPersist();
+ if( p ) // muss da sein
+ {
+ return !p->GetEmbeddedObjectContainer().HasEmbeddedObject( aOLEObj.aName );
+ }
+ }
+ return bRet;
+}
+
+void SwOLENode::GetNewReplacement()
+{
+ if ( aOLEObj.xOLERef.is() )
+ aOLEObj.xOLERef.UpdateReplacement();
+}
+
+sal_Bool SwOLENode::UpdateLinkURL_Impl()
+{
+ sal_Bool bResult = sal_False;
+
+ if ( mpObjectLink )
+ {
+ String aNewLinkURL;
+ GetDoc()->GetLinkManager().GetDisplayNames( mpObjectLink, 0, &aNewLinkURL, 0, 0 );
+ if ( !aNewLinkURL.EqualsIgnoreCaseAscii( maLinkURL ) )
+ {
+ if ( !aOLEObj.xOLERef.is() )
+ aOLEObj.GetOleRef();
+
+ uno::Reference< embed::XEmbeddedObject > xObj = aOLEObj.xOLERef.GetObject();
+ uno::Reference< embed::XCommonEmbedPersist > xPersObj( xObj, uno::UNO_QUERY );
+ OSL_ENSURE( xPersObj.is(), "The object must exist!\n" );
+ if ( xPersObj.is() )
+ {
+ try
+ {
+ sal_Int32 nCurState = xObj->getCurrentState();
+ if ( nCurState != embed::EmbedStates::LOADED )
+ xObj->changeState( embed::EmbedStates::LOADED );
+
+ // TODO/LATER: there should be possible to get current mediadescriptor settings from the object
+ uno::Sequence< beans::PropertyValue > aArgs( 1 );
+ aArgs[0].Name = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "URL" ) );
+ aArgs[0].Value <<= ::rtl::OUString( aNewLinkURL );
+ xPersObj->reload( aArgs, uno::Sequence< beans::PropertyValue >() );
+
+ maLinkURL = aNewLinkURL;
+ bResult = sal_True;
+
+ if ( nCurState != embed::EmbedStates::LOADED )
+ xObj->changeState( nCurState );
+ }
+ catch( uno::Exception& )
+ {}
+ }
+
+ if ( !bResult )
+ {
+ // TODO/LATER: return the old name to the link manager, is it possible?
+ }
+ }
+ }
+
+ return bResult;
+}
+
+void SwOLENode::BreakFileLink_Impl()
+{
+ SfxObjectShell* pPers = GetDoc()->GetPersist();
+
+ if ( pPers )
+ {
+ uno::Reference< embed::XStorage > xStorage = pPers->GetStorage();
+ if ( xStorage.is() )
+ {
+ try
+ {
+ uno::Reference< embed::XLinkageSupport > xLinkSupport( aOLEObj.GetOleRef(), uno::UNO_QUERY_THROW );
+ xLinkSupport->breakLink( xStorage, aOLEObj.GetCurrentPersistName() );
+ DisconnectFileLink_Impl();
+ maLinkURL = String();
+ }
+ catch( uno::Exception& )
+ {
+ }
+ }
+ }
+}
+
+void SwOLENode::DisconnectFileLink_Impl()
+{
+ if ( mpObjectLink )
+ {
+ GetDoc()->GetLinkManager().Remove( mpObjectLink );
+ mpObjectLink = NULL;
+ }
+}
+
+void SwOLENode::CheckFileLink_Impl()
+{
+ if ( aOLEObj.xOLERef.GetObject().is() && !mpObjectLink )
+ {
+ try
+ {
+ uno::Reference< embed::XLinkageSupport > xLinkSupport( aOLEObj.xOLERef.GetObject(), uno::UNO_QUERY_THROW );
+ if ( xLinkSupport->isLink() )
+ {
+ String aLinkURL = xLinkSupport->getLinkURL();
+ if ( aLinkURL.Len() )
+ {
+ // this is a file link so the model link manager should handle it
+ mpObjectLink = new SwEmbedObjectLink( this );
+ maLinkURL = aLinkURL;
+ GetDoc()->GetLinkManager().InsertFileLink( *mpObjectLink, OBJECT_CLIENT_OLE, aLinkURL, NULL, NULL );
+ mpObjectLink->Connect();
+ }
+ }
+ }
+ catch( uno::Exception& )
+ {
+ }
+ }
+}
+
+// --> OD 2009-03-05 #i99665#
+bool SwOLENode::IsChart() const
+{
+ bool bIsChart( false );
+
+ const uno::Reference< embed::XEmbeddedObject > xEmbObj =
+ const_cast<SwOLEObj&>(GetOLEObj()).GetOleRef();
+ if ( xEmbObj.is() )
+ {
+ SvGlobalName aClassID( xEmbObj->getClassID() );
+ bIsChart = SotExchange::IsChart( aClassID );
+ }
+
+ return bIsChart;
+}
+// <--
+
+SwOLEObj::SwOLEObj( const svt::EmbeddedObjectRef& xObj ) :
+ pOLENd( 0 ),
+ pListener( 0 ),
+ xOLERef( xObj )
+{
+ xOLERef.Lock( sal_True );
+ if ( xObj.is() )
+ {
+ pListener = new SwOLEListener_Impl( this );
+ pListener->acquire();
+ xObj->addStateChangeListener( pListener );
+ }
+}
+
+
+SwOLEObj::SwOLEObj( const String &rString, sal_Int64 nAspect ) :
+ pOLENd( 0 ),
+ pListener( 0 ),
+ aName( rString )
+{
+ xOLERef.Lock( sal_True );
+ xOLERef.SetViewAspect( nAspect );
+}
+
+
+SwOLEObj::~SwOLEObj()
+{
+ if( pListener )
+ {
+ if ( xOLERef.is() )
+ xOLERef->removeStateChangeListener( pListener );
+ pListener->Release();
+ }
+
+ if( pOLENd && !pOLENd->GetDoc()->IsInDtor() )
+ {
+ // if the model is not currently in destruction it means that this object should be removed from the model
+ comphelper::EmbeddedObjectContainer* pCnt = xOLERef.GetContainer();
+
+#if OSL_DEBUG_LEVEL > 0
+ SfxObjectShell* p = pOLENd->GetDoc()->GetPersist();
+ DBG_ASSERT( p, "No document!" );
+ if( p )
+ {
+ comphelper::EmbeddedObjectContainer& rCnt = p->GetEmbeddedObjectContainer();
+ OSL_ENSURE( !pCnt || &rCnt == pCnt, "The helper is assigned to unexpected container!\n" );
+ }
+#endif
+
+ if ( pCnt && pCnt->HasEmbeddedObject( aName ) )
+ {
+ uno::Reference < container::XChild > xChild( xOLERef.GetObject(), uno::UNO_QUERY );
+ if ( xChild.is() )
+ xChild->setParent( 0 );
+
+ // not already removed by deleting the object
+ xOLERef.AssignToContainer( 0, aName );
+
+ // unlock object so that object can be closed in RemoveEmbeddedObject
+ // successful closing of the object will automatically clear the reference then
+ xOLERef.Lock(sal_False);
+
+ // Always remove object from conteiner it is connected to
+ try
+ {
+ pCnt->RemoveEmbeddedObject( aName );
+ }
+ catch ( uno::Exception& )
+ {
+ }
+ }
+
+ }
+
+ if ( xOLERef.is() )
+ // in case the object wasn't closed: release it
+ // in case the object was not in the container: it's still locked, try to close
+ xOLERef.Clear();
+}
+
+
+void SwOLEObj::SetNode( SwOLENode* pNode )
+{
+ pOLENd = pNode;
+ if ( !aName.Len() )
+ {
+ SwDoc* pDoc = pNode->GetDoc();
+
+ // Falls bereits eine SvPersist-Instanz existiert, nehmen wir diese
+ SfxObjectShell* p = pDoc->GetPersist();
+ if( !p )
+ {
+ // TODO/LATER: reicht hier nicht ein EmbeddedObjectContainer? Was passiert mit
+ // diesem Dokument?
+ OSL_ENSURE( !this, "warum wird hier eine DocShell angelegt?" );
+ p = new SwDocShell( pDoc, SFX_CREATE_MODE_INTERNAL );
+ p->DoInitNew( NULL );
+ }
+
+ ::rtl::OUString aObjName;
+ uno::Reference < container::XChild > xChild( xOLERef.GetObject(), uno::UNO_QUERY );
+ if ( xChild.is() && xChild->getParent() != p->GetModel() )
+ // it is possible that the parent was set already
+ xChild->setParent( p->GetModel() );
+ if (!p->GetEmbeddedObjectContainer().InsertEmbeddedObject( xOLERef.GetObject(), aObjName ) )
+ {
+ OSL_FAIL( "InsertObject failed" );
+ if ( xChild.is() )
+ xChild->setParent( 0 );
+ }
+ else
+ xOLERef.AssignToContainer( &p->GetEmbeddedObjectContainer(), aObjName );
+
+ ( (SwOLENode*)pOLENd )->CheckFileLink_Impl(); // for this notification nonconst access is required
+
+ aName = aObjName;
+ }
+}
+
+sal_Bool SwOLEObj::IsOleRef() const
+{
+ return xOLERef.is();
+}
+
+const uno::Reference < embed::XEmbeddedObject > SwOLEObj::GetOleRef()
+{
+ if( !xOLERef.is() )
+ {
+ SfxObjectShell* p = pOLENd->GetDoc()->GetPersist();
+ OSL_ENSURE( p, "kein SvPersist vorhanden" );
+
+ uno::Reference < embed::XEmbeddedObject > xObj = p->GetEmbeddedObjectContainer().GetEmbeddedObject( aName );
+ OSL_ENSURE( !xOLERef.is(), "rekursiver Aufruf von GetOleRef() ist nicht erlaubt" );
+
+ if ( !xObj.is() )
+ {
+ //Das Teil konnte nicht geladen werden (wahrsch. Kaputt).
+ Rectangle aArea;
+ SwFrm *pFrm = pOLENd->getLayoutFrm(0);
+ if ( pFrm )
+ {
+ Size aSz( pFrm->Frm().SSize() );
+ const MapMode aSrc ( MAP_TWIP );
+ const MapMode aDest( MAP_100TH_MM );
+ aSz = OutputDevice::LogicToLogic( aSz, aSrc, aDest );
+ aArea.SetSize( aSz );
+ }
+ else
+ aArea.SetSize( Size( 5000, 5000 ) );
+ // TODO/LATER: set replacement graphic for dead object
+ // It looks as if it should work even without the object, because the replace will be generated automatically
+ ::rtl::OUString aTmpName;
+ xObj = p->GetEmbeddedObjectContainer().CreateEmbeddedObject( SvGlobalName( SO3_DUMMY_CLASSID ).GetByteSequence(), aTmpName );
+ }
+ // else
+ {
+ xOLERef.Assign( xObj, xOLERef.GetViewAspect() );
+ xOLERef.AssignToContainer( &p->GetEmbeddedObjectContainer(), aName );
+ pListener = new SwOLEListener_Impl( this );
+ pListener->acquire();
+ xObj->addStateChangeListener( pListener );
+ }
+
+ ( (SwOLENode*)pOLENd )->CheckFileLink_Impl(); // for this notification nonconst access is required
+ }
+ else if ( xOLERef->getCurrentState() == embed::EmbedStates::RUNNING )
+ {
+ // move object to first position in cache
+ if( !pOLELRU_Cache )
+ pOLELRU_Cache = new SwOLELRUCache;
+ pOLELRU_Cache->InsertObj( *this );
+ }
+
+ return xOLERef.GetObject();
+}
+
+svt::EmbeddedObjectRef& SwOLEObj::GetObject()
+{
+ GetOleRef();
+ return xOLERef;
+}
+
+sal_Bool SwOLEObj::UnloadObject()
+{
+ sal_Bool bRet = sal_True;
+ if ( pOLENd )
+ {
+ const SwDoc* pDoc = pOLENd->GetDoc();
+ bRet = UnloadObject( xOLERef.GetObject(), pDoc, xOLERef.GetViewAspect() );
+ }
+
+ return bRet;
+}
+
+sal_Bool SwOLEObj::UnloadObject( uno::Reference< embed::XEmbeddedObject > xObj, const SwDoc* pDoc, sal_Int64 nAspect )
+{
+ if ( !pDoc )
+ return sal_False;
+
+ sal_Bool bRet = sal_True;
+ sal_Int32 nState = xObj.is() ? xObj->getCurrentState() : embed::EmbedStates::LOADED;
+ sal_Bool bIsActive = ( nState != embed::EmbedStates::LOADED && nState != embed::EmbedStates::RUNNING );
+ sal_Int64 nMiscStatus = xObj->getStatus( nAspect );
+
+ if( nState != embed::EmbedStates::LOADED && !pDoc->IsInDtor() && !bIsActive &&
+ embed::EmbedMisc::MS_EMBED_ALWAYSRUN != ( nMiscStatus & embed::EmbedMisc::MS_EMBED_ALWAYSRUN ) &&
+ embed::EmbedMisc::EMBED_ACTIVATEIMMEDIATELY != ( nMiscStatus & embed::EmbedMisc::EMBED_ACTIVATEIMMEDIATELY ) )
+ {
+ SfxObjectShell* p = pDoc->GetPersist();
+ if( p )
+ {
+ if( pDoc->get(IDocumentSettingAccess::PURGE_OLE) )
+ {
+ try
+ {
+ uno::Reference < util::XModifiable > xMod( xObj->getComponent(), uno::UNO_QUERY );
+ if( xMod.is() && xMod->isModified() )
+ {
+ uno::Reference < embed::XEmbedPersist > xPers( xObj, uno::UNO_QUERY );
+ if ( xPers.is() )
+ xPers->storeOwn();
+ else {
+ OSL_FAIL("Modified object without persistance in cache!");
+ }
+ }
+
+ // setting object to loaded state will remove it from cache
+ xObj->changeState( embed::EmbedStates::LOADED );
+ }
+ catch ( uno::Exception& )
+ {
+ bRet = sal_False;
+ }
+ }
+ else
+ bRet = sal_False;
+ }
+ }
+
+ return bRet;
+}
+
+String SwOLEObj::GetDescription()
+{
+ String aResult;
+ uno::Reference< embed::XEmbeddedObject > xEmbObj = GetOleRef();
+ if ( xEmbObj.is() )
+ {
+ SvGlobalName aClassID( xEmbObj->getClassID() );
+ if ( SotExchange::IsMath( aClassID ) )
+ aResult = SW_RES(STR_MATH_FORMULA);
+ else if ( SotExchange::IsChart( aClassID ) )
+ aResult = SW_RES(STR_CHART);
+ else
+ aResult = SW_RES(STR_OLE);
+ }
+
+ return aResult;
+}
+
+
+SwOLELRUCache::SwOLELRUCache()
+ : SvPtrarr( 64, 16 ),
+ utl::ConfigItem(OUString(RTL_CONSTASCII_USTRINGPARAM("Office.Common/Cache"))),
+ nLRU_InitSize( 20 ),
+ bInUnload( sal_False )
+{
+ EnableNotification( GetPropertyNames() );
+ Load();
+}
+
+uno::Sequence< rtl::OUString > SwOLELRUCache::GetPropertyNames()
+{
+ Sequence< OUString > aNames( 1 );
+ OUString* pNames = aNames.getArray();
+ pNames[0] = OUString(RTL_CONSTASCII_USTRINGPARAM("Writer/OLE_Objects"));
+ return aNames;
+}
+
+void SwOLELRUCache::Notify( const uno::Sequence< rtl::OUString>& )
+{
+ Load();
+}
+
+void SwOLELRUCache::Commit()
+{
+}
+
+void SwOLELRUCache::Load()
+{
+ Sequence< OUString > aNames( GetPropertyNames() );
+ Sequence< Any > aValues = GetProperties( aNames );
+ const Any* pValues = aValues.getConstArray();
+ DBG_ASSERT( aValues.getLength() == aNames.getLength(), "GetProperties failed" );
+ if( aValues.getLength() == aNames.getLength() && pValues->hasValue() )
+ {
+ sal_Int32 nVal = 0;
+ *pValues >>= nVal;
+
+ {
+ if( nVal < nLRU_InitSize )
+ {
+ // size of cache has been changed
+ sal_uInt16 nCount = SvPtrarr::Count();
+ sal_uInt16 nPos = nCount;
+
+ // try to remove the last entries until new maximum size is reached
+ while( nCount > nVal )
+ {
+ SwOLEObj* pObj = (SwOLEObj*) SvPtrarr::GetObject( --nPos );
+ if ( pObj->UnloadObject() )
+ nCount--;
+ if ( !nPos )
+ break;
+ }
+ }
+ }
+
+ nLRU_InitSize = (sal_uInt16)nVal;
+ }
+}
+
+void SwOLELRUCache::InsertObj( SwOLEObj& rObj )
+{
+ SwOLEObj* pObj = &rObj;
+ sal_uInt16 nPos = SvPtrarr::GetPos( pObj );
+ if( nPos )
+ {
+ // object is currently not the first in cache
+ if( USHRT_MAX != nPos )
+ SvPtrarr::Remove( nPos );
+
+ SvPtrarr::Insert( pObj, 0 );
+
+ // try to remove objects if necessary (of course not the freshly inserted one at nPos=0)
+ sal_uInt16 nCount = SvPtrarr::Count();
+ nPos = nCount-1;
+ while( nPos && nCount > nLRU_InitSize )
+ {
+ pObj = (SwOLEObj*) SvPtrarr::GetObject( nPos-- );
+ if ( pObj->UnloadObject() )
+ nCount--;
+ }
+ }
+}
+
+void SwOLELRUCache::RemoveObj( SwOLEObj& rObj )
+{
+ sal_uInt16 nPos = SvPtrarr::GetPos( &rObj );
+ if ( nPos != 0xFFFF )
+ SvPtrarr::Remove( nPos );
+ if( !Count() )
+ DELETEZ( pOLELRU_Cache );
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/para/paratr.cxx b/sw/source/core/para/paratr.cxx
new file mode 100644
index 000000000000..02c154b130f6
--- /dev/null
+++ b/sw/source/core/para/paratr.cxx
@@ -0,0 +1,278 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+#include "hintids.hxx"
+#include <swtypes.hxx>
+#include "unomid.h"
+#include <com/sun/star/style/LineSpacingMode.hpp>
+#include <com/sun/star/style/ParagraphAdjust.hpp>
+#include <com/sun/star/style/DropCapFormat.hpp>
+#include <com/sun/star/style/LineSpacing.hpp>
+#include <com/sun/star/text/RelOrientation.hpp>
+#include <com/sun/star/text/VertOrientation.hpp>
+#include <com/sun/star/text/HorizontalAdjust.hpp>
+#include <com/sun/star/text/DocumentStatistic.hpp>
+#include <com/sun/star/text/HoriOrientation.hpp>
+#include <com/sun/star/text/HoriOrientationFormat.hpp>
+#include <com/sun/star/text/NotePrintMode.hpp>
+#include <com/sun/star/text/SizeType.hpp>
+#include <com/sun/star/text/VertOrientationFormat.hpp>
+#include <com/sun/star/text/WrapTextMode.hpp>
+#include <unostyle.hxx>
+#include <SwStyleNameMapper.hxx>
+#include "paratr.hxx"
+#include "charfmt.hxx"
+#include "cmdid.h"
+
+using namespace ::com::sun::star;
+
+TYPEINIT2_AUTOFACTORY( SwFmtDrop, SfxPoolItem, SwClient);
+TYPEINIT1_AUTOFACTORY( SwRegisterItem, SfxBoolItem);
+TYPEINIT1_AUTOFACTORY( SwNumRuleItem, SfxStringItem);
+TYPEINIT1_AUTOFACTORY( SwParaConnectBorderItem, SfxBoolItem);
+
+/*************************************************************************
+|* Beschreibung Methoden von SwFmtDrop
+*************************************************************************/
+
+
+
+SwFmtDrop::SwFmtDrop()
+ : SfxPoolItem( RES_PARATR_DROP ),
+ SwClient( 0 ),
+ pDefinedIn( 0 ),
+ nDistance( 0 ),
+ nReadFmt( USHRT_MAX ),
+ nLines( 0 ),
+ nChars( 0 ),
+ bWholeWord( sal_False )
+{
+}
+
+
+
+SwFmtDrop::SwFmtDrop( const SwFmtDrop &rCpy )
+ : SfxPoolItem( RES_PARATR_DROP ),
+ SwClient( rCpy.GetRegisteredInNonConst() ),
+ pDefinedIn( 0 ),
+ nDistance( rCpy.GetDistance() ),
+ nReadFmt( rCpy.nReadFmt ),
+ nLines( rCpy.GetLines() ),
+ nChars( rCpy.GetChars() ),
+ bWholeWord( rCpy.GetWholeWord() )
+{
+}
+
+
+
+SwFmtDrop::~SwFmtDrop()
+{
+}
+
+
+
+void SwFmtDrop::SetCharFmt( SwCharFmt *pNew )
+{
+ //Ummelden
+ if ( GetRegisteredIn() )
+ GetRegisteredInNonConst()->Remove( this );
+ if(pNew)
+ pNew->Add( this );
+ nReadFmt = USHRT_MAX;
+}
+
+
+
+void SwFmtDrop::Modify( const SfxPoolItem*, const SfxPoolItem * )
+{
+ if( pDefinedIn )
+ {
+ if( !pDefinedIn->ISA( SwFmt ))
+ pDefinedIn->ModifyNotification( this, this );
+ else if( pDefinedIn->GetDepends() &&
+ !pDefinedIn->IsModifyLocked() )
+ {
+ // selbst den Abhaengigen vom Format bescheid sagen. Das
+ // Format selbst wuerde es nicht weitergeben, weil es ueber
+ // die Abpruefung nicht hinauskommt.
+ pDefinedIn->ModifyBroadcast( this, this );
+ }
+ }
+}
+
+sal_Bool SwFmtDrop::GetInfo( SfxPoolItem& ) const
+{
+ return sal_True; // weiter
+}
+
+int SwFmtDrop::operator==( const SfxPoolItem& rAttr ) const
+{
+ OSL_ENSURE( SfxPoolItem::operator==( rAttr ), "keine gleichen Attribute" );
+ return ( nLines == ((SwFmtDrop&)rAttr).GetLines() &&
+ nChars == ((SwFmtDrop&)rAttr).GetChars() &&
+ nDistance == ((SwFmtDrop&)rAttr).GetDistance() &&
+ bWholeWord == ((SwFmtDrop&)rAttr).GetWholeWord() &&
+ GetCharFmt() == ((SwFmtDrop&)rAttr).GetCharFmt() &&
+ pDefinedIn == ((SwFmtDrop&)rAttr).pDefinedIn );
+}
+
+SfxPoolItem* SwFmtDrop::Clone( SfxItemPool* ) const
+{
+ return new SwFmtDrop( *this );
+}
+
+bool SwFmtDrop::QueryValue( uno::Any& rVal, sal_uInt8 nMemberId ) const
+{
+ switch(nMemberId&~CONVERT_TWIPS)
+ {
+ case MID_DROPCAP_LINES : rVal <<= (sal_Int16)nLines; break;
+ case MID_DROPCAP_COUNT : rVal <<= (sal_Int16)nChars; break;
+ case MID_DROPCAP_DISTANCE : rVal <<= (sal_Int16) TWIP_TO_MM100_UNSIGNED(nDistance); break;
+ case MID_DROPCAP_FORMAT:
+ {
+ style::DropCapFormat aDrop;
+ aDrop.Lines = nLines ;
+ aDrop.Count = nChars ;
+ aDrop.Distance = TWIP_TO_MM100_UNSIGNED(nDistance);
+ rVal.setValue(&aDrop, ::getCppuType((const style::DropCapFormat*)0));
+ }
+ break;
+ case MID_DROPCAP_WHOLE_WORD:
+ rVal.setValue(&bWholeWord, ::getBooleanCppuType());
+ break;
+ case MID_DROPCAP_CHAR_STYLE_NAME :
+ {
+ rtl::OUString sName;
+ if(GetCharFmt())
+ sName = SwStyleNameMapper::GetProgName(
+ GetCharFmt()->GetName(), nsSwGetPoolIdFromName::GET_POOLID_CHRFMT );
+ rVal <<= sName;
+ }
+ break;
+ }
+ return true;
+}
+
+bool SwFmtDrop::PutValue( const uno::Any& rVal, sal_uInt8 nMemberId )
+{
+ switch(nMemberId&~CONVERT_TWIPS)
+ {
+ case MID_DROPCAP_LINES :
+ {
+ sal_Int8 nTemp = 0;
+ rVal >>= nTemp;
+ if(nTemp >=1 && nTemp < 0x7f)
+ nLines = (sal_uInt8)nTemp;
+ }
+ break;
+ case MID_DROPCAP_COUNT :
+ {
+ sal_Int16 nTemp = 0;
+ rVal >>= nTemp;
+ if(nTemp >=1 && nTemp < 0x7f)
+ nChars = (sal_uInt8)nTemp;
+ }
+ break;
+ case MID_DROPCAP_DISTANCE :
+ {
+ sal_Int16 nVal = 0;
+ if ( rVal >>= nVal )
+ nDistance = (sal_Int16) MM100_TO_TWIP((sal_Int32)nVal);
+ else
+ return false;
+ break;
+ }
+ case MID_DROPCAP_FORMAT:
+ {
+ if(rVal.getValueType() == ::getCppuType((const style::DropCapFormat*)0))
+ {
+ const style::DropCapFormat* pDrop = (const style::DropCapFormat*)rVal.getValue();
+ nLines = pDrop->Lines;
+ nChars = pDrop->Count;
+ nDistance = MM100_TO_TWIP(pDrop->Distance);
+ }
+ else {
+ }
+ }
+ break;
+ case MID_DROPCAP_WHOLE_WORD:
+ bWholeWord = *(sal_Bool*)rVal.getValue();
+ break;
+ case MID_DROPCAP_CHAR_STYLE_NAME :
+ OSL_FAIL("char format cannot be set in PutValue()!");
+ break;
+ }
+ return true;
+}
+
+// class SwRegisterItem -------------------------------------------------
+
+
+SfxPoolItem* SwRegisterItem::Clone( SfxItemPool * ) const
+{
+ return new SwRegisterItem( *this );
+}
+
+// class SwNumRuleItem -------------------------------------------------
+SfxPoolItem* SwNumRuleItem::Clone( SfxItemPool * ) const
+{
+ return new SwNumRuleItem( *this );
+}
+int SwNumRuleItem::operator==( const SfxPoolItem& rAttr ) const
+{
+ OSL_ENSURE( SfxPoolItem::operator==( rAttr ), "keine gleichen Attribute" );
+
+ return GetValue() == ((SwNumRuleItem&)rAttr).GetValue();
+}
+
+bool SwNumRuleItem::QueryValue( uno::Any& rVal, sal_uInt8 ) const
+{
+ rtl::OUString sRet = SwStyleNameMapper::GetProgName(GetValue(), nsSwGetPoolIdFromName::GET_POOLID_NUMRULE );
+ rVal <<= sRet;
+ return true;
+}
+
+bool SwNumRuleItem::PutValue( const uno::Any& rVal, sal_uInt8 )
+{
+ rtl::OUString uName;
+ rVal >>= uName;
+ SetValue(SwStyleNameMapper::GetUIName(uName, nsSwGetPoolIdFromName::GET_POOLID_NUMRULE));
+ return true;
+}
+
+SfxPoolItem* SwParaConnectBorderItem::Clone( SfxItemPool * ) const
+{
+ return new SwParaConnectBorderItem( *this );
+}
+
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/sw3io/sw3convert.cxx b/sw/source/core/sw3io/sw3convert.cxx
new file mode 100644
index 000000000000..8605e23f6204
--- /dev/null
+++ b/sw/source/core/sw3io/sw3convert.cxx
@@ -0,0 +1,413 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+
+
+#include <stdlib.h>
+
+#include <stdio.h>
+#include "hintids.hxx"
+#include <tools/resid.hxx>
+#include <svl/macitem.hxx>
+#include <svl/zforlist.hxx>
+#include <svl/zformat.hxx>
+#include <svl/urihelper.hxx>
+#include <sfx2/linkmgr.hxx>
+
+#ifndef _SVSTDARR_USHORTS_DECL
+#define _SVSTDARR_USHORTS
+#include <svl/svstdarr.hxx>
+#endif
+#include <editeng/lrspitem.hxx>
+#include <editeng/tstpitem.hxx>
+#include <fmtinfmt.hxx>
+#include <fmtfld.hxx>
+#include <frmatr.hxx>
+#include "doc.hxx"
+#include "docary.hxx"
+#include "fldbas.hxx"
+#include "flddat.hxx"
+#include "docufld.hxx"
+#include "chpfld.hxx"
+#include "ddefld.hxx"
+#include "expfld.hxx"
+#include "reffld.hxx"
+#include "usrfld.hxx"
+#include "dbfld.hxx"
+#include "txtfld.hxx"
+#include "ndtxt.hxx"
+
+//really used ids from old sw3ids.hxx
+#define SWG_INETBROWSER 0x000e // URL-Grf-Nodes, Browse-Flag, Format-Ums.
+#define SWG_NEWFIELDS 0x0200 // Felder mit Numberformatter-Zahlenformat
+#define SWG_EXPORT40 0x0110 // Version fuer 4.0-Export ab 5.0
+
+using namespace nsSwDocInfoSubType;
+
+struct OldFormats
+{
+ NfIndexTableOffset eFormatIdx;
+ sal_uInt16 nOldFormat;
+};
+
+static OldFormats aOldDateFmt40[] =
+{
+ // Datumsfelder:
+ { NF_DATE_SYSTEM_SHORT, DFF_SSYS }, // Kurzes Systemdatum
+ { NF_DATE_SYSTEM_LONG, DFF_LSYS }, // Langes Systemdatum
+ { NF_DATE_SYS_DDMMYY, DFF_DMY }, // 06.10.64
+ { NF_DATE_SYS_DDMMYYYY, DFF_DMYY }, // 06.10.1964
+ { NF_DATE_SYS_DMMMYY, DFF_DMMY }, // 06. Okt 64
+ { NF_DATE_SYS_DMMMYYYY, DFF_DMMYY }, // 06. Okt 1964
+ { NF_DATE_DIN_DMMMMYYYY, DFF_DMMMYY }, // 06. Oktober 1964
+ { NF_DATE_DIN_DMMMMYYYY, DFF_DMMMY }, // 06. Oktober 64
+ { NF_DATE_SYS_NNDMMMYY, DFF_DDMMY }, // Di, 06. Okt 64
+ { NF_DATE_SYS_NNDMMMMYYYY, DFF_DDMMMY }, // Di, 06. Oktober 64
+ { NF_DATE_SYS_NNDMMMMYYYY, DFF_DDMMMYY }, // Di, 06. Oktober 1964
+ { NF_DATE_SYS_NNNNDMMMMYYYY, DFF_DDDMMMYY }, // Dienstag, 06. Oktober 1964
+ { NF_DATE_SYS_NNNNDMMMMYYYY, DFF_DDDMMMY }, // Dienstag, 06. Oktober 64
+ { NF_DATE_SYS_MMYY, DFF_MY }, // 10.64
+ { NF_DATE_DIN_MMDD, DFF_MD }, // 10-06
+ { NF_DATE_DIN_YYMMDD, DFF_YMD }, // 64-10-06
+ { NF_DATE_DIN_YYYYMMDD, DFF_YYMD }, // 1964-10-06
+
+ { NF_NUMERIC_START, 0 } // Tabellenende
+};
+
+static OldFormats aOldDateFmt30[] =
+{
+ // Datumsfelder:
+ { NF_DATE_SYSTEM_SHORT, DFF_SSYS }, // Kurzes Systemdatum
+ { NF_DATE_SYSTEM_LONG, DFF_LSYS }, // Langes Systemdatum
+ { NF_DATE_SYS_DDMMYY, DFF_DMY }, // 06.10.64
+ { NF_DATE_SYS_DDMMYYYY, DFF_DMYY }, // 06.10.1964
+ { NF_DATE_SYS_DMMMYY, DFF_DMMY }, // 06. Okt 64
+ { NF_DATE_SYS_DMMMYYYY, 4 /*DFF_DMMYY*/ }, // 06. Okt 1964
+ { NF_DATE_DIN_DMMMMYYYY, 5 /*DFF_DMMMYY*/ }, // 06. Oktober 1964
+ { NF_DATE_DIN_DMMMMYYYY, 5 /*DFF_DMMMY*/ }, // 06. Oktober 64
+ { NF_DATE_SYS_NNDMMMMYYYY, 6 /*DFF_DDMMMYY*/ }, // Di, 06. Oktober 1964
+ { NF_DATE_SYS_NNDMMMYY, 6 /*DFF_DDMMY*/ }, // Di, 06. Okt 64
+ { NF_DATE_SYS_NNDMMMMYYYY, 6 /*DFF_DDMMMY*/ }, // Di, 06. Oktober 64
+ { NF_DATE_SYS_NNNNDMMMMYYYY, 7 /*DFF_DDDMMMYY*/ }, // Dienstag, 06. Oktober 1964
+ { NF_DATE_SYS_NNNNDMMMMYYYY, 7 /*DFF_DDDMMMY*/ }, // Dienstag, 06. Oktober 64
+ { NF_DATE_SYS_MMYY, 2 /*DFF_MY*/ }, // 10.64
+ { NF_DATE_DIN_MMDD, DFF_MD }, // 10-06
+ { NF_DATE_DIN_YYMMDD, DFF_YMD }, // 64-10-06
+ { NF_DATE_DIN_YYYYMMDD, DFF_YYMD }, // 1964-10-06
+
+ { NF_NUMERIC_START, 0 } // Tabellenende
+};
+
+static OldFormats aOldTimeFmt[] =
+{
+ // Zeitfelder:
+ { NF_TIME_HHMMSS, TF_SYSTEM }, // Systemzeit
+ { NF_TIME_HHMM, TF_SSMM_24 }, // 23:25
+ { NF_TIME_HHMMAMPM, TF_SSMM_12 }, // 11:25 PM
+
+ { NF_NUMERIC_START, 0 } // Tabellenende
+};
+
+static OldFormats aOldGetSetExpFmt40[] =
+{
+ { NF_TEXT, VVF_CMD }, // Kommando anzeigen
+ { NF_TEXT, VVF_INVISIBLE }, // unsichtbar
+ { NF_PERCENT_INT, VVF_XXP }, // 1234%
+ { NF_PERCENT_DEC2, VVF_XX_XXP }, // 1.234,56%
+ { NF_TEXT, VVF_CLEAR }, // ???
+
+ { NF_NUMBER_SYSTEM, VVF_SYS }, // Zahlenformat aus der
+ // Systemeinstellung
+ { NF_NUMBER_INT, VVF_X }, // 1234
+ { NF_NUMBER_DEC2, VVF_X_X }, // 1234,5
+ { NF_NUMBER_DEC2, VVF_X_XX }, // 1245,56
+ { NF_NUMBER_1000DEC2, VVF_XX_XX }, // 1.234,56
+ { NF_NUMBER_1000DEC2, VVF_XX_X }, // 1.234,5
+ { NF_NUMBER_1000DEC2, VVF_XX_XXX }, // 1.234,567
+ { NF_CURRENCY_1000DEC2, VVF_SYS_CUR }, // W?hrungsformat aus der
+ // Systemeinstellung
+ // (1.234,00 DM)
+ { NF_CURRENCY_1000INT, VVF_X_CUR }, // 1234 DM
+ { NF_CURRENCY_1000DEC2, VVF_XX_XX_CUR }, // 1234,56 DM 1234,00 DM
+ { NF_CURRENCY_1000DEC2_DASHED, VVF_XX_X0_CUR }, // 1234,56 DM 1234,-- DM
+ { NF_CURRENCY_1000INT, VVF_CUR_X }, // DM 1234
+ { NF_CURRENCY_1000DEC2, VVF_CUR_XX_XX }, // DM 1234,56 DM 1234,00
+ { NF_CURRENCY_1000DEC2_DASHED, VVF_CUR_XX_X0 }, // DM 1234,56 DM 1234,--
+
+ { NF_NUMERIC_START, 0 } // Tabellenende
+};
+
+static OldFormats aOldGetSetExpFmt30[] =
+{
+ { NF_TEXT, VVF_CMD }, // Kommando anzeigen
+ { NF_TEXT, VVF_INVISIBLE }, // unsichtbar
+ { NF_PERCENT_INT, VVF_XXP }, // 1234%
+ { NF_PERCENT_DEC2, VVF_XX_XXP }, // 1.234,56%
+ { NF_TEXT, VVF_CLEAR }, // ???
+
+ { NF_NUMBER_SYSTEM, 0x0020 }, // Zahlenformat aus der
+ // Systemeinstellung
+ { NF_NUMBER_INT, 0x0080 }, // 1234
+ { NF_NUMBER_1000DEC2, 0x0100 }, // 1.234,56
+ { NF_NUMBER_DEC2, 0x0100 }, // 1234,5
+ { NF_NUMBER_DEC2, 0x0100 }, // 1245,56
+ { NF_NUMBER_1000DEC2, 0x0100 }, // 1.234,5
+ { NF_NUMBER_1000DEC2, 0x0100 }, // 1.234,567
+ { NF_CURRENCY_1000DEC2, 0x0200 }, // W?hrungsformat aus der
+ // Systemeinstellung
+ // (1.234,00 DM)
+ { NF_CURRENCY_1000INT, 0x1000 }, // 1234 DM
+ { NF_CURRENCY_1000DEC2, 0x1000 }, // 1234,56 DM 1234,00 DM
+ { NF_CURRENCY_1000DEC2_DASHED, 0x1000 }, // 1234,56 DM 1234,-- DM
+ { NF_CURRENCY_1000INT, 0x1000 }, // DM 1234
+ { NF_CURRENCY_1000DEC2, 0x1000 }, // DM 1234,56 DM 1234,00
+ { NF_CURRENCY_1000DEC2_DASHED, 0x1000 }, // DM 1234,56 DM 1234,--
+
+ { NF_NUMERIC_START, 0 } // Tabellenende
+};
+
+SW_DLLPUBLIC void sw3io_ConvertFromOldField( SwDoc& rDoc, sal_uInt16& rWhich,
+ sal_uInt16& rSubType, sal_uLong &rFmt,
+ sal_uInt16 nVersion )
+{
+ const OldFormats *pOldFmt = 0L;
+
+ switch( rWhich )
+ {
+ case RES_DATEFLD:
+ case RES_FIXDATEFLD:
+ if( nVersion < SWG_NEWFIELDS )
+ {
+ rSubType = DATEFLD;
+ if( RES_FIXDATEFLD == rWhich )
+ rSubType |= FIXEDFLD;
+ rWhich = RES_DATETIMEFLD;
+ pOldFmt = nVersion<SWG_INETBROWSER ? aOldDateFmt30
+ : aOldDateFmt40;
+ }
+ break;
+
+ case RES_TIMEFLD:
+ case RES_FIXTIMEFLD:
+ if( nVersion < SWG_NEWFIELDS )
+ {
+ rSubType = TIMEFLD;
+ if( RES_FIXTIMEFLD == rWhich )
+ rSubType |= FIXEDFLD;
+ rWhich = RES_DATETIMEFLD;
+ pOldFmt = aOldTimeFmt;
+ }
+ break;
+
+ case RES_DBFLD:
+ if( nVersion < SWG_NEWFIELDS )
+ {
+ rSubType = nsSwExtendedSubType::SUB_OWN_FMT;
+ pOldFmt = nVersion<SWG_INETBROWSER ? aOldGetSetExpFmt30
+ : aOldGetSetExpFmt40;
+ }
+ break;
+
+ case RES_TABLEFLD:
+ case RES_GETEXPFLD:
+ case RES_SETEXPFLD:
+ case RES_USERFLD:
+ if( nVersion < SWG_NEWFIELDS )
+ {
+ if( rFmt == VVF_INVISIBLE )
+ {
+ rSubType = nsSwExtendedSubType::SUB_INVISIBLE;
+ rFmt = 0;
+ }
+ else if( rFmt == VVF_CMD )
+ {
+ rSubType = nsSwExtendedSubType::SUB_CMD;
+ rFmt = 0;
+ }
+ else
+ {
+ // Kleiner Hack: Bei Numernkreisen wird das
+ // unkonvertierte Format noch benoetigt. Wir merken es
+ // uns voruebergehend mal im Subtyp, sofern es
+ // ueberhaupt als entsprechendes Format in Frage kommt.
+ if( RES_SETEXPFLD==rWhich &&
+ /*rFmt >= (sal_uInt16)SVX_NUM_CHARS_UPPER_LETTER && always true*/
+ rFmt <= (sal_uInt16)SVX_NUM_BITMAP )
+ {
+ rSubType = (sal_uInt16)rFmt;
+ }
+ pOldFmt = nVersion<SWG_INETBROWSER ? aOldGetSetExpFmt30
+ : aOldGetSetExpFmt40;
+ }
+ }
+ break;
+ case RES_DOCINFOFLD:
+ if( nVersion < SWG_NEWFIELDS )
+ {
+ switch( rFmt )
+ {
+ case RF_AUTHOR: rSubType = DI_SUB_AUTHOR; break;
+ case RF_TIME: rSubType = DI_SUB_TIME; break;
+ case RF_DATE: rSubType = DI_SUB_DATE; break;
+ case RF_ALL: rSubType = DI_SUB_DATE; break;
+ }
+ rFmt = 0;
+ }
+ break;
+ }
+
+ if( pOldFmt )
+ {
+ SvNumberFormatter *pFormatter = rDoc.GetNumberFormatter();
+ sal_uInt16 i = 0;
+
+ while( pOldFmt[i].eFormatIdx != NF_NUMERIC_START ||
+ pOldFmt[i].nOldFormat)
+ {
+ if( rFmt == pOldFmt[i].nOldFormat )
+ {
+ rFmt = pFormatter->GetFormatIndex(pOldFmt[i].eFormatIdx, LANGUAGE_SYSTEM);
+ break;
+ }
+ i++;
+ }
+ }
+}
+SW_DLLPUBLIC void sw3io_ConvertToOldField( const SwField* pFld, sal_uInt16& rWhich,
+ sal_uLong& rFmt, sal_uLong nFFVersion )
+{
+ const OldFormats *pOldFmt = 0L;
+ sal_uLong nOldFmt = rFmt;
+
+ switch( rWhich )
+ {
+ case RES_DOCINFOFLD:
+ if( SOFFICE_FILEFORMAT_40 >= nFFVersion )
+ {
+ switch (pFld->GetSubType() & 0xff00)
+ {
+ case DI_SUB_AUTHOR: rFmt = RF_AUTHOR; break;
+ case DI_SUB_TIME: rFmt = RF_TIME; break;
+ case DI_SUB_DATE: rFmt = RF_DATE; break;
+ }
+ }
+ break;
+
+ case RES_DATETIMEFLD:
+ if( SOFFICE_FILEFORMAT_40 >= nFFVersion )
+ {
+ sal_uInt16 nSubType = ((SwDateTimeField*) pFld)->GetSubType();
+ switch( nSubType )
+ {
+ case DATEFLD: rWhich = RES_DATEFLD; break;
+ case TIMEFLD: rWhich = RES_TIMEFLD; break;
+ case DATEFLD|FIXEDFLD: rWhich = RES_FIXDATEFLD; break;
+ case TIMEFLD|FIXEDFLD: rWhich = RES_FIXTIMEFLD; break;
+ }
+
+ if( nSubType & DATEFLD )
+ {
+ rFmt = DFF_DMY;
+ pOldFmt = aOldDateFmt40;
+ }
+ else
+ {
+ rFmt = TF_SYSTEM;
+ pOldFmt = aOldTimeFmt;
+ }
+ }
+ break;
+
+ case RES_DBFLD:
+ case RES_TABLEFLD:
+ case RES_GETEXPFLD:
+ case RES_SETEXPFLD:
+ case RES_USERFLD:
+ if( SOFFICE_FILEFORMAT_40 >= nFFVersion )
+ {
+ sal_uInt16 nSubType = pFld->GetSubType();
+
+ if (nSubType & nsSwExtendedSubType::SUB_INVISIBLE)
+ rFmt = VVF_INVISIBLE;
+ else if (nSubType & nsSwExtendedSubType::SUB_CMD)
+ rFmt = VVF_CMD;
+ else if( !(nsSwGetSetExpType::GSE_SEQ & nSubType) )
+ {
+ pOldFmt = aOldGetSetExpFmt40;
+ rFmt = VVF_SYS;
+ }
+ }
+ break;
+
+ case RES_GETREFFLD:
+ if( SOFFICE_FILEFORMAT_31 == nFFVersion )
+ {
+ switch( rFmt )
+ {
+ case REF_PAGE:
+ case REF_CHAPTER:
+ case REF_CONTENT:
+ break;
+
+ default:
+ rFmt = REF_PAGE;
+ break;
+ }
+ }
+ break;
+ }
+
+ if( pOldFmt && nOldFmt )
+ {
+ SvNumberFormatter *pFormatter = ((SwValueField*)pFld)->GetDoc()->GetNumberFormatter();
+ const SvNumberformat* pEntry = pFormatter->GetEntry( nOldFmt );
+
+ if( pEntry )
+ {
+ sal_uInt16 i = 0;
+ while( pOldFmt[i].eFormatIdx != NF_NUMERIC_START ||
+ pOldFmt[i].nOldFormat )
+ {
+ sal_uLong nKey = pFormatter->GetFormatIndex(
+ pOldFmt[i].eFormatIdx, pEntry->GetLanguage() );
+
+ if( nOldFmt == nKey )
+ {
+ rFmt = pOldFmt[i].nOldFormat;
+ break;
+ }
+ i++;
+ }
+ }
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/sw3io/swacorr.cxx b/sw/source/core/sw3io/swacorr.cxx
new file mode 100644
index 000000000000..86bd02e76a30
--- /dev/null
+++ b/sw/source/core/sw3io/swacorr.cxx
@@ -0,0 +1,105 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+
+#include <tools/urlobj.hxx>
+#include <swacorr.hxx>
+#include <swblocks.hxx>
+#include "SwXMLTextBlocks.hxx"
+#include <swerror.h>
+#include <docsh.hxx>
+#include <editsh.hxx>
+#include <sot/storage.hxx>
+
+using namespace ::com::sun::star;
+
+
+TYPEINIT1( SwAutoCorrect, SvxAutoCorrect );
+
+
+ // - return den Ersetzungstext (nur fuer SWG-Format, alle anderen
+ // koennen aus der Wortliste herausgeholt werden!)
+ // rShort ist der Stream-Name - gecryptet!
+
+sal_Bool SwAutoCorrect::GetLongText( const uno::Reference < embed::XStorage >& rStg, const String& rFileName, const String& rShort, String& rLong )
+{
+ sal_uLong nRet = 0;
+ if (rStg.is())
+ {
+ // mba: relative URLs don't make sense here
+ SwXMLTextBlocks aBlk( rStg, rFileName );
+ nRet = aBlk.GetText( rShort, rLong );
+ }
+ else {
+ OSL_ENSURE( rStg.is(), "Someone passed SwAutoCorrect::GetLongText a dud storage!");
+ }
+ return !IsError( nRet ) && rLong.Len();
+}
+
+ // - Text mit Attributierung (kann nur der SWG - SWG-Format!)
+ // rShort ist der Stream-Name - gecryptet!
+sal_Bool SwAutoCorrect::PutText( const uno::Reference < embed::XStorage >& rStg, const String& rFileName, const String& rShort,
+ SfxObjectShell& rObjSh, String& rLong )
+{
+ if( !rObjSh.IsA( TYPE(SwDocShell) ) )
+ return sal_False;
+
+ SwDocShell& rDShell = (SwDocShell&)rObjSh;
+ sal_uLong nRet = 0;
+
+ // mba: relative URLs don't make sense here
+ SwXMLTextBlocks aBlk( rStg, rFileName );
+ SwDoc* pDoc = aBlk.GetDoc();
+
+ nRet = aBlk.BeginPutDoc( rShort, rShort );
+ if( !IsError( nRet ) )
+ {
+ ((SwEditShell*)rDShell.GetWrtShell())->_CopySelToDoc( pDoc );
+ nRet = aBlk.PutDoc();
+ aBlk.AddName ( rShort, rShort, sal_False );
+ if( !IsError( nRet ) )
+ nRet = aBlk.GetText( rShort, rLong );
+ }
+ return !IsError( nRet );
+}
+
+
+SwAutoCorrect::SwAutoCorrect( const SvxAutoCorrect& rACorr )
+ : SvxAutoCorrect( rACorr )
+{
+ SwEditShell::SetAutoFmtFlags(&GetSwFlags());
+}
+
+SwAutoCorrect::~SwAutoCorrect()
+{
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/swg/SwXMLBlockExport.cxx b/sw/source/core/swg/SwXMLBlockExport.cxx
new file mode 100644
index 000000000000..674a33fe2c4f
--- /dev/null
+++ b/sw/source/core/swg/SwXMLBlockExport.cxx
@@ -0,0 +1,145 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+#include <SwXMLBlockExport.hxx>
+#include <SwXMLTextBlocks.hxx>
+#include <xmloff/nmspmap.hxx>
+#include <xmloff/xmlnmspe.hxx>
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star;
+using namespace ::xmloff::token;
+using ::rtl::OUString;
+
+// #110680#
+SwXMLBlockListExport::SwXMLBlockListExport(
+ const uno::Reference< lang::XMultiServiceFactory > xServiceFactory,
+ SwXMLTextBlocks & rBlocks,
+ const rtl::OUString &rFileName,
+ uno::Reference< xml::sax::XDocumentHandler> &rHandler)
+: SvXMLExport( xServiceFactory, rFileName, rHandler ),
+ rBlockList(rBlocks)
+{
+ _GetNamespaceMap().Add( GetXMLToken ( XML_NP_BLOCK_LIST ),
+ GetXMLToken ( XML_N_BLOCK_LIST ),
+ XML_NAMESPACE_BLOCKLIST );
+}
+
+sal_uInt32 SwXMLBlockListExport::exportDoc(enum XMLTokenEnum )
+{
+ GetDocHandler()->startDocument();
+
+ AddAttribute ( XML_NAMESPACE_NONE,
+ _GetNamespaceMap().GetAttrNameByKey ( XML_NAMESPACE_BLOCKLIST ),
+ _GetNamespaceMap().GetNameByKey ( XML_NAMESPACE_BLOCKLIST ) );
+ AddAttribute( XML_NAMESPACE_BLOCKLIST,
+ XML_LIST_NAME,
+ OUString (rBlockList.GetName()));
+ {
+ SvXMLElementExport pRoot (*this, XML_NAMESPACE_BLOCKLIST, XML_BLOCK_LIST, sal_True, sal_True);
+ sal_uInt16 nBlocks= rBlockList.GetCount();
+ for ( sal_uInt16 i = 0; i < nBlocks; i++)
+ {
+ AddAttribute( XML_NAMESPACE_BLOCKLIST,
+ XML_ABBREVIATED_NAME,
+ OUString(rBlockList.GetShortName(i)));
+ AddAttribute( XML_NAMESPACE_BLOCKLIST,
+ XML_PACKAGE_NAME,
+ OUString(rBlockList.GetPackageName(i)));
+ AddAttribute( XML_NAMESPACE_BLOCKLIST,
+ XML_NAME,
+ OUString(rBlockList.GetLongName(i)));
+ AddAttribute( XML_NAMESPACE_BLOCKLIST,
+ XML_UNFORMATTED_TEXT,
+ rBlockList.IsOnlyTextBlock(i) ? XML_TRUE : XML_FALSE );
+
+ SvXMLElementExport aBlock( *this, XML_NAMESPACE_BLOCKLIST, XML_BLOCK, sal_True, sal_True);
+ }
+ }
+ GetDocHandler()->endDocument();
+ return 0;
+}
+
+// #110680#
+SwXMLTextBlockExport::SwXMLTextBlockExport(
+ const uno::Reference< lang::XMultiServiceFactory > xServiceFactory,
+ SwXMLTextBlocks & rBlocks,
+ const rtl::OUString &rFileName,
+ uno::Reference< xml::sax::XDocumentHandler> &rHandler)
+: SvXMLExport( xServiceFactory, rFileName, rHandler ),
+ rBlockList(rBlocks)
+{
+ _GetNamespaceMap().Add( GetXMLToken ( XML_NP_BLOCK_LIST ),
+ GetXMLToken ( XML_N_BLOCK_LIST ),
+ XML_NAMESPACE_BLOCKLIST );
+ _GetNamespaceMap().Add( GetXMLToken ( XML_NP_OFFICE ),
+ GetXMLToken(XML_N_OFFICE_OOO),
+ XML_NAMESPACE_OFFICE );
+ _GetNamespaceMap().Add( GetXMLToken ( XML_NP_TEXT ),
+ GetXMLToken(XML_N_TEXT_OOO),
+ XML_NAMESPACE_TEXT );
+}
+
+sal_uInt32 SwXMLTextBlockExport::exportDoc(const String &rText)
+{
+ GetDocHandler()->startDocument();
+
+ AddAttribute ( XML_NAMESPACE_NONE,
+ _GetNamespaceMap().GetAttrNameByKey ( XML_NAMESPACE_BLOCKLIST ),
+ _GetNamespaceMap().GetNameByKey ( XML_NAMESPACE_BLOCKLIST ) );
+ AddAttribute ( XML_NAMESPACE_NONE,
+ _GetNamespaceMap().GetAttrNameByKey ( XML_NAMESPACE_TEXT ),
+ _GetNamespaceMap().GetNameByKey ( XML_NAMESPACE_TEXT ) );
+ AddAttribute ( XML_NAMESPACE_NONE,
+ _GetNamespaceMap().GetAttrNameByKey ( XML_NAMESPACE_OFFICE ),
+ _GetNamespaceMap().GetNameByKey ( XML_NAMESPACE_OFFICE ) );
+ AddAttribute( XML_NAMESPACE_BLOCKLIST,
+ XML_LIST_NAME,
+ OUString (rBlockList.GetName()));
+ {
+ SvXMLElementExport aDocument (*this, XML_NAMESPACE_OFFICE, XML_DOCUMENT, sal_True, sal_True);
+ {
+ SvXMLElementExport aBody (*this, XML_NAMESPACE_OFFICE, XML_BODY, sal_True, sal_True);
+ {
+ xub_StrLen nPos = 0;
+ do
+ {
+ String sTemp ( rText.GetToken( 0, '\015', nPos ) );
+ SvXMLElementExport aPara (*this, XML_NAMESPACE_TEXT, XML_P, sal_True, sal_False);
+ GetDocHandler()->characters(sTemp);
+ } while (STRING_NOTFOUND != nPos );
+ }
+
+ }
+ }
+ GetDocHandler()->endDocument();
+ return 0;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/swg/SwXMLBlockImport.cxx b/sw/source/core/swg/SwXMLBlockImport.cxx
new file mode 100644
index 000000000000..c7499c69f0e4
--- /dev/null
+++ b/sw/source/core/swg/SwXMLBlockImport.cxx
@@ -0,0 +1,119 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+#include <SwXMLBlockImport.hxx>
+#include <xmloff/nmspmap.hxx>
+#include <xmloff/xmlnmspe.hxx>
+#include <SwXMLBlockListContext.hxx>
+#include <SwXMLTextBlocks.hxx>
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star;
+using namespace ::xmloff::token;
+using ::rtl::OUString;
+
+sal_Char const sXML_np__block_list[] = "_block-list";
+sal_Char const sXML_np__office[] = "_ooffice";
+sal_Char const sXML_np__text[] = "_otext";
+
+// #110680#
+SwXMLBlockListImport::SwXMLBlockListImport(
+ const uno::Reference< lang::XMultiServiceFactory > xServiceFactory,
+ SwXMLTextBlocks &rBlocks )
+: SvXMLImport( xServiceFactory, 0 ),
+ rBlockList (rBlocks)
+{
+ GetNamespaceMap().Add( OUString ( RTL_CONSTASCII_USTRINGPARAM ( sXML_np__block_list ) ),
+ GetXMLToken ( XML_N_BLOCK_LIST ),
+ XML_NAMESPACE_BLOCKLIST );
+}
+
+SwXMLBlockListImport::~SwXMLBlockListImport ( void )
+ throw ()
+{
+}
+
+SvXMLImportContext *SwXMLBlockListImport::CreateContext(
+ sal_uInt16 nPrefix,
+ const OUString& rLocalName,
+ const uno::Reference< xml::sax::XAttributeList > & xAttrList )
+{
+ SvXMLImportContext *pContext = 0;
+ if ( XML_NAMESPACE_BLOCKLIST == nPrefix &&
+ IsXMLToken ( rLocalName, XML_BLOCK_LIST ) )
+ pContext = new SwXMLBlockListContext( *this, nPrefix, rLocalName,
+ xAttrList );
+ else
+ pContext = SvXMLImport::CreateContext( nPrefix, rLocalName, xAttrList );
+ return pContext;
+}
+
+// #110680#
+SwXMLTextBlockImport::SwXMLTextBlockImport(
+ const uno::Reference< lang::XMultiServiceFactory > xServiceFactory,
+ SwXMLTextBlocks &rBlocks,
+ String & rNewText,
+ sal_Bool bNewTextOnly )
+: SvXMLImport(xServiceFactory, IMPORT_ALL ),
+ rBlockList ( rBlocks ),
+ bTextOnly ( bNewTextOnly ),
+ m_rText ( rNewText )
+{
+ GetNamespaceMap().Add( OUString( RTL_CONSTASCII_USTRINGPARAM ( sXML_np__office ) ),
+ GetXMLToken(XML_N_OFFICE_OOO),
+ XML_NAMESPACE_OFFICE );
+ GetNamespaceMap().Add( OUString( RTL_CONSTASCII_USTRINGPARAM ( sXML_np__text ) ),
+ GetXMLToken(XML_N_TEXT_OOO),
+ XML_NAMESPACE_TEXT );
+}
+
+SwXMLTextBlockImport::~SwXMLTextBlockImport ( void )
+ throw()
+{
+}
+
+SvXMLImportContext *SwXMLTextBlockImport::CreateContext(
+ sal_uInt16 nPrefix,
+ const OUString& rLocalName,
+ const uno::Reference< xml::sax::XAttributeList > & xAttrList )
+{
+ SvXMLImportContext *pContext = 0;
+ if( XML_NAMESPACE_OFFICE == nPrefix &&
+ IsXMLToken ( rLocalName, bTextOnly ? XML_DOCUMENT : XML_DOCUMENT_CONTENT ) )
+ pContext = new SwXMLTextBlockDocumentContext( *this, nPrefix, rLocalName, xAttrList );
+ else
+ pContext = SvXMLImport::CreateContext( nPrefix, rLocalName, xAttrList );
+ return pContext;
+}
+void SAL_CALL SwXMLTextBlockImport::endDocument(void)
+ throw( xml::sax::SAXException, uno::RuntimeException )
+{
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/swg/SwXMLBlockListContext.cxx b/sw/source/core/swg/SwXMLBlockListContext.cxx
new file mode 100644
index 000000000000..babaada52596
--- /dev/null
+++ b/sw/source/core/swg/SwXMLBlockListContext.cxx
@@ -0,0 +1,253 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+#include <SwXMLBlockListContext.hxx>
+#include <SwXMLBlockImport.hxx>
+#include <SwXMLTextBlocks.hxx>
+#include <xmloff/nmspmap.hxx>
+#include <xmloff/xmlnmspe.hxx>
+#include <unotools/charclass.hxx>
+#include <swtypes.hxx>
+
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star;
+using namespace ::xmloff::token;
+using ::rtl::OUString;
+
+SwXMLBlockListContext::SwXMLBlockListContext(
+ SwXMLBlockListImport& rImport,
+ sal_uInt16 nPrefix,
+ const OUString& rLocalName,
+ const uno::Reference<
+ xml::sax::XAttributeList > & xAttrList ) :
+ SvXMLImportContext ( rImport, nPrefix, rLocalName ),
+ rLocalRef (rImport)
+{
+ sal_Int16 nAttrCount = xAttrList.is() ? xAttrList->getLength() : 0;
+ for (sal_Int16 i=0; i < nAttrCount; i++)
+ {
+ const OUString& rAttrName = xAttrList->getNameByIndex( i );
+ OUString aLocalName;
+ sal_uInt16 nPrefx = rImport.GetNamespaceMap().GetKeyByAttrName( rAttrName, &aLocalName);
+ const OUString& rAttrValue = xAttrList->getValueByIndex( i );
+ if ( XML_NAMESPACE_BLOCKLIST == nPrefx )
+ {
+ if ( IsXMLToken ( aLocalName, XML_LIST_NAME ) )
+ {
+ rImport.getBlockList().SetName(rAttrValue);
+ break;
+ }
+ }
+ }
+}
+
+SwXMLBlockListContext::~SwXMLBlockListContext ( void )
+{
+}
+
+SvXMLImportContext *SwXMLBlockListContext::CreateChildContext(
+ sal_uInt16 nPrefix,
+ const OUString& rLocalName,
+ const uno::Reference< xml::sax::XAttributeList > & xAttrList )
+{
+ SvXMLImportContext *pContext = 0;
+ if (nPrefix == XML_NAMESPACE_BLOCKLIST &&
+ IsXMLToken ( rLocalName, XML_BLOCK ) )
+ pContext = new SwXMLBlockContext (rLocalRef, nPrefix, rLocalName, xAttrList);
+ else
+ pContext = new SvXMLImportContext( rLocalRef, nPrefix, rLocalName);
+ return pContext;
+}
+
+SwXMLBlockContext::SwXMLBlockContext(
+ SwXMLBlockListImport& rImport,
+ sal_uInt16 nPrefix,
+ const OUString& rLocalName,
+ const uno::Reference<
+ xml::sax::XAttributeList > & xAttrList ) :
+ SvXMLImportContext ( rImport, nPrefix, rLocalName ),
+ rLocalRef(rImport)
+{
+ static const CharClass & rCC = GetAppCharClass();
+ String aShort, aLong, aPackageName;
+ sal_Bool bTextOnly = sal_False;
+
+ sal_Int16 nAttrCount = xAttrList.is() ? xAttrList->getLength() : 0;
+ for (sal_Int16 i=0; i < nAttrCount; i++)
+ {
+ const OUString& rAttrName = xAttrList->getNameByIndex( i );
+ OUString aLocalName;
+ sal_uInt16 nPrefx = rImport.GetNamespaceMap().GetKeyByAttrName( rAttrName, &aLocalName);
+ const OUString& rAttrValue = xAttrList->getValueByIndex( i );
+ if (XML_NAMESPACE_BLOCKLIST == nPrefx)
+ {
+ if ( IsXMLToken ( aLocalName, XML_ABBREVIATED_NAME ) )
+ {
+ aShort = rCC.upper(rAttrValue);
+ }
+ else if ( IsXMLToken ( aLocalName, XML_NAME ) )
+ {
+ aLong = rAttrValue;
+ }
+ else if ( IsXMLToken ( aLocalName, XML_PACKAGE_NAME ) )
+ {
+ aPackageName = rAttrValue;
+ }
+ else if ( IsXMLToken ( aLocalName, XML_UNFORMATTED_TEXT ) )
+ {
+ if ( IsXMLToken ( rAttrValue, XML_TRUE ) )
+ bTextOnly = sal_True;
+ }
+ }
+ }
+ if (!aShort.Len() || !aLong.Len() || !aPackageName.Len())
+ return;
+ rImport.getBlockList().AddName( aShort, aLong, aPackageName, bTextOnly);
+}
+
+SwXMLBlockContext::~SwXMLBlockContext ( void )
+{
+}
+
+SwXMLTextBlockDocumentContext::SwXMLTextBlockDocumentContext(
+ SwXMLTextBlockImport& rImport,
+ sal_uInt16 nPrefix,
+ const OUString& rLocalName,
+ const uno::Reference<
+ xml::sax::XAttributeList > & ) :
+ SvXMLImportContext ( rImport, nPrefix, rLocalName ),
+ rLocalRef(rImport)
+{
+}
+
+SvXMLImportContext *SwXMLTextBlockDocumentContext::CreateChildContext(
+ sal_uInt16 nPrefix,
+ const OUString& rLocalName,
+ const uno::Reference< xml::sax::XAttributeList > & xAttrList )
+{
+ SvXMLImportContext *pContext = 0;
+ if (nPrefix == XML_NAMESPACE_OFFICE &&
+ IsXMLToken ( rLocalName, XML_BODY ) )
+ pContext = new SwXMLTextBlockBodyContext (rLocalRef, nPrefix, rLocalName, xAttrList);
+ else
+ pContext = new SvXMLImportContext( rLocalRef, nPrefix, rLocalName);
+ return pContext;
+}
+SwXMLTextBlockDocumentContext::~SwXMLTextBlockDocumentContext ( void )
+{
+}
+
+
+SwXMLTextBlockTextContext::SwXMLTextBlockTextContext(
+ SwXMLTextBlockImport& rImport,
+ sal_uInt16 nPrefix,
+ const OUString& rLocalName,
+ const uno::Reference<
+ xml::sax::XAttributeList > & ) :
+ SvXMLImportContext ( rImport, nPrefix, rLocalName ),
+ rLocalRef(rImport)
+{
+}
+
+SvXMLImportContext *SwXMLTextBlockTextContext::CreateChildContext(
+ sal_uInt16 nPrefix,
+ const OUString& rLocalName,
+ const uno::Reference< xml::sax::XAttributeList > & xAttrList )
+{
+ SvXMLImportContext *pContext = 0;
+ if (nPrefix == XML_NAMESPACE_TEXT &&
+ IsXMLToken ( rLocalName, XML_P ) )
+ pContext = new SwXMLTextBlockParContext (rLocalRef, nPrefix, rLocalName, xAttrList);
+ else
+ pContext = new SvXMLImportContext( rLocalRef, nPrefix, rLocalName);
+ return pContext;
+}
+SwXMLTextBlockTextContext::~SwXMLTextBlockTextContext ( void )
+{
+}
+
+
+SwXMLTextBlockBodyContext::SwXMLTextBlockBodyContext(
+ SwXMLTextBlockImport& rImport,
+ sal_uInt16 nPrefix,
+ const OUString& rLocalName,
+ const uno::Reference<
+ xml::sax::XAttributeList > & ) :
+ SvXMLImportContext ( rImport, nPrefix, rLocalName ),
+ rLocalRef(rImport)
+{
+}
+
+SvXMLImportContext *SwXMLTextBlockBodyContext::CreateChildContext(
+ sal_uInt16 nPrefix,
+ const OUString& rLocalName,
+ const uno::Reference< xml::sax::XAttributeList > & xAttrList )
+{
+ SvXMLImportContext *pContext = 0;
+ if (nPrefix == XML_NAMESPACE_OFFICE &&
+ IsXMLToken ( rLocalName, XML_TEXT ) )
+ pContext = new SwXMLTextBlockTextContext (rLocalRef, nPrefix, rLocalName, xAttrList);
+ else if (nPrefix == XML_NAMESPACE_TEXT &&
+ IsXMLToken ( rLocalName, XML_P ) )
+ pContext = new SwXMLTextBlockParContext (rLocalRef, nPrefix, rLocalName, xAttrList);
+ else
+ pContext = new SvXMLImportContext( rLocalRef, nPrefix, rLocalName);
+ return pContext;
+}
+SwXMLTextBlockBodyContext::~SwXMLTextBlockBodyContext ( void )
+{
+}
+SwXMLTextBlockParContext::SwXMLTextBlockParContext(
+ SwXMLTextBlockImport& rImport,
+ sal_uInt16 nPrefix,
+ const OUString& rLocalName,
+ const uno::Reference<
+ xml::sax::XAttributeList > & ) :
+ SvXMLImportContext ( rImport, nPrefix, rLocalName ),
+ rLocalRef(rImport)
+{
+}
+
+void SwXMLTextBlockParContext::Characters( const ::rtl::OUString& rChars )
+{
+ rLocalRef.m_rText.Append ( rChars.getStr());
+}
+SwXMLTextBlockParContext::~SwXMLTextBlockParContext ( void )
+{
+ if (rLocalRef.bTextOnly)
+ rLocalRef.m_rText.AppendAscii( "\015" );
+ else
+ {
+ if (rLocalRef.m_rText.GetChar ( rLocalRef.m_rText.Len()) != ' ' )
+ rLocalRef.m_rText.AppendAscii( " " );
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/swg/SwXMLSectionList.cxx b/sw/source/core/swg/SwXMLSectionList.cxx
new file mode 100644
index 000000000000..1aebeb72cf22
--- /dev/null
+++ b/sw/source/core/swg/SwXMLSectionList.cxx
@@ -0,0 +1,157 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+#define _SVSTDARR_STRINGSDTOR
+#define _SVSTDARR_STRINGS
+#include <svl/svstdarr.hxx>
+#include <SwXMLSectionList.hxx>
+#include <xmloff/nmspmap.hxx>
+#include <xmloff/xmlnmspe.hxx>
+
+using namespace ::com::sun::star;
+using ::rtl::OUString;
+using namespace ::xmloff::token;
+
+sal_Char const sXML_np__office[] = "_ooffice";
+sal_Char const sXML_np__text[] = "_otext";
+
+// #110680#
+SwXMLSectionList::SwXMLSectionList(
+ const uno::Reference< lang::XMultiServiceFactory > xServiceFactory,
+ SvStrings & rNewSectionList)
+: SvXMLImport( xServiceFactory ),
+ rSectionList ( rNewSectionList )
+{
+ GetNamespaceMap().Add( OUString( RTL_CONSTASCII_USTRINGPARAM ( sXML_np__office ) ),
+ GetXMLToken(XML_N_OFFICE_OOO),
+ XML_NAMESPACE_OFFICE );
+ GetNamespaceMap().Add( OUString( RTL_CONSTASCII_USTRINGPARAM ( sXML_np__text ) ),
+ GetXMLToken(XML_N_TEXT_OOO),
+ XML_NAMESPACE_TEXT );
+}
+
+SwXMLSectionList::~SwXMLSectionList ( void )
+ throw()
+{
+}
+
+SvXMLImportContext *SwXMLSectionList::CreateContext(
+ sal_uInt16 nPrefix,
+ const OUString& rLocalName,
+ const uno::Reference< xml::sax::XAttributeList > & xAttrList )
+{
+ SvXMLImportContext *pContext = 0;
+
+ if(( nPrefix == XML_NAMESPACE_OFFICE && IsXMLToken ( rLocalName, XML_BODY )) ||
+ ( nPrefix == XML_NAMESPACE_TEXT &&
+ (IsXMLToken ( rLocalName, XML_P ) ||
+ IsXMLToken ( rLocalName, XML_H ) ||
+ IsXMLToken ( rLocalName, XML_A ) ||
+ IsXMLToken ( rLocalName, XML_SPAN ) ||
+ IsXMLToken ( rLocalName, XML_SECTION ) ||
+ IsXMLToken ( rLocalName, XML_INDEX_BODY ) ||
+ IsXMLToken ( rLocalName, XML_INDEX_TITLE )||
+ IsXMLToken ( rLocalName, XML_INSERTION ) ||
+ IsXMLToken ( rLocalName, XML_DELETION ) )
+ )
+ )
+ {
+ pContext = new SvXMLSectionListContext (*this, nPrefix, rLocalName, xAttrList);
+ }
+ else
+ pContext = SvXMLImport::CreateContext( nPrefix, rLocalName, xAttrList );
+ return pContext;
+}
+
+SvXMLSectionListContext::SvXMLSectionListContext(
+ SwXMLSectionList& rImport,
+ sal_uInt16 nPrefix,
+ const OUString& rLocalName,
+ const uno::Reference< xml::sax::XAttributeList > & ) :
+ SvXMLImportContext ( rImport, nPrefix, rLocalName ),
+ rLocalRef(rImport)
+{
+}
+
+SvXMLImportContext *SvXMLSectionListContext::CreateChildContext(
+ sal_uInt16 nPrefix,
+ const OUString& rLocalName,
+ const uno::Reference< xml::sax::XAttributeList > & xAttrList )
+{
+ SvXMLImportContext *pContext = 0;
+ String sName;
+
+ if (nPrefix == XML_NAMESPACE_TEXT && ( IsXMLToken ( rLocalName, XML_SECTION ) ||
+ IsXMLToken ( rLocalName, XML_BOOKMARK) ) )
+ {
+ sal_Int16 nAttrCount = xAttrList.is() ? xAttrList->getLength() : 0;
+
+ for (sal_Int16 i=0; i < nAttrCount; i++)
+ {
+ const OUString& rAttrName = xAttrList->getNameByIndex( i );
+ OUString aLocalName;
+ sal_uInt16 nPrefx = rLocalRef.GetNamespaceMap().GetKeyByAttrName( rAttrName, &aLocalName);
+ const OUString& rAttrValue = xAttrList->getValueByIndex( i );
+ if (XML_NAMESPACE_TEXT == nPrefx && IsXMLToken ( aLocalName, XML_NAME ) )
+ sName = rAttrValue;
+ }
+ if ( sName.Len() )
+ rLocalRef.rSectionList.Insert ( new String(sName), rLocalRef.rSectionList.Count() );
+ }
+
+ pContext = new SvXMLSectionListContext (rLocalRef, nPrefix, rLocalName, xAttrList);
+ return pContext;
+}
+SvXMLSectionListContext::~SvXMLSectionListContext ( void )
+{
+}
+
+SvXMLIgnoreSectionListContext::SvXMLIgnoreSectionListContext(
+ SwXMLSectionList& rImport,
+ sal_uInt16 nPrefix,
+ const OUString& rLocalName,
+ const uno::Reference< xml::sax::XAttributeList > & ) :
+ SvXMLImportContext ( rImport, nPrefix, rLocalName ),
+ rLocalRef(rImport)
+{
+}
+
+SvXMLIgnoreSectionListContext::~SvXMLIgnoreSectionListContext ( void )
+{
+}
+SvXMLImportContext *SvXMLIgnoreSectionListContext::CreateChildContext(
+ sal_uInt16 nPrefix,
+ const OUString& rLocalName,
+ const uno::Reference< xml::sax::XAttributeList > & xAttrList )
+{
+ return new SvXMLIgnoreSectionListContext (rLocalRef, nPrefix, rLocalName, xAttrList);
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/swg/SwXMLTextBlocks.cxx b/sw/source/core/swg/SwXMLTextBlocks.cxx
new file mode 100644
index 000000000000..a8f9412dc67a
--- /dev/null
+++ b/sw/source/core/swg/SwXMLTextBlocks.cxx
@@ -0,0 +1,606 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+#include <com/sun/star/embed/ElementModes.hpp>
+#include <com/sun/star/embed/XTransactedObject.hpp>
+#include <tools/urlobj.hxx>
+#include <sot/stg.hxx>
+#include <sfx2/docfile.hxx>
+#include <unotools/localfilehelper.hxx>
+#include <unotools/ucbstreamhelper.hxx>
+
+#include <comphelper/storagehelper.hxx>
+#include <doc.hxx>
+#include <IDocumentUndoRedo.hxx>
+#include <docsh.hxx>
+#include <pam.hxx>
+#include <swblocks.hxx>
+#include <ndtxt.hxx>
+#include <shellio.hxx>
+#include <poolfmt.hxx>
+#include <SwXMLTextBlocks.hxx>
+#include <SwXMLBlockImport.hxx>
+#include <SwXMLBlockExport.hxx>
+#include <swerror.h>
+
+#define STREAM_STGREAD ( STREAM_READ | STREAM_SHARE_DENYWRITE | STREAM_NOCREATE )
+#define STREAM_STGWRITE ( STREAM_READ | STREAM_WRITE | STREAM_SHARE_DENYWRITE )
+
+using namespace ::com::sun::star;
+
+
+void SwXMLTextBlocks::InitBlockMode ( const uno::Reference < embed::XStorage >& rStorage )
+{
+ xBlkRoot = rStorage;
+ xRoot = 0;
+}
+
+void SwXMLTextBlocks::ResetBlockMode ( )
+{
+ xBlkRoot = 0;
+ xRoot = 0;
+}
+
+SwXMLTextBlocks::SwXMLTextBlocks( const String& rFile )
+: SwImpBlocks( rFile ), bAutocorrBlock( sal_False ), nFlags ( 0 )
+{
+ SwDocShell* pDocSh = new SwDocShell ( SFX_CREATE_MODE_INTERNAL );
+ if( !pDocSh->DoInitNew( 0 ) )
+ return;
+ bReadOnly = sal_True;
+ pDoc = pDocSh->GetDoc();
+ xDocShellRef = pDocSh;
+ pDoc->SetOle2Link( Link() );
+ pDoc->GetIDocumentUndoRedo().DoUndo(false);
+ pDoc->acquire();
+ uno::Reference< embed::XStorage > refStg;
+ if( !aDateModified.GetDate() || !aTimeModified.GetTime() )
+ Touch(); // falls neu angelegt -> neuen ZeitStempel besorgen
+ try
+ {
+ refStg = comphelper::OStorageHelper::GetStorageFromURL( rFile, embed::ElementModes::READWRITE );
+ bReadOnly = sal_False;
+ }
+ catch( const uno::Exception& )
+ {
+ //couldn't open the file - maybe it's readonly
+ }
+ if( !refStg.is())
+ {
+ try
+ {
+ refStg = comphelper::OStorageHelper::GetStorageFromURL( rFile, embed::ElementModes::READ );
+ }
+ catch( const uno::Exception& )
+ {
+ OSL_FAIL("exception while creating AutoText storage");
+ }
+ }
+ InitBlockMode ( refStg );
+ ReadInfo();
+ ResetBlockMode ();
+ bInfoChanged = sal_False;
+}
+
+SwXMLTextBlocks::SwXMLTextBlocks( const uno::Reference < embed::XStorage >& rStg, const String& rName )
+: SwImpBlocks( rName )
+, bAutocorrBlock( sal_True )
+, nFlags ( 0 )
+{
+ SwDocShell* pDocSh = new SwDocShell ( SFX_CREATE_MODE_INTERNAL );
+ if( !pDocSh->DoInitNew( 0 ) )
+ return;
+ bReadOnly = sal_False;
+ pDoc = pDocSh->GetDoc();
+ xDocShellRef = pDocSh;
+ pDoc->SetOle2Link( Link() );
+ pDoc->GetIDocumentUndoRedo().DoUndo(false);
+ pDoc->acquire();
+
+ InitBlockMode ( rStg );
+ ReadInfo();
+ bInfoChanged = sal_False;
+}
+
+SwXMLTextBlocks::~SwXMLTextBlocks()
+{
+ if ( bInfoChanged )
+ WriteInfo();
+ ResetBlockMode ();
+ if(xDocShellRef.Is())
+ xDocShellRef->DoClose();
+ xDocShellRef = 0;
+ if( pDoc && !pDoc->release() )
+ delete pDoc;
+}
+
+void SwXMLTextBlocks::ClearDoc()
+{
+ SwDocShell * pDocShell = pDoc->GetDocShell();
+ pDocShell->InvalidateModel();
+ pDocShell->ReactivateModel();
+
+ pDoc->ClearDoc();
+ pDocShell->ClearEmbeddedObjects();
+}
+void SwXMLTextBlocks::AddName( const String& rShort, const String& rLong, sal_Bool bOnlyTxt )
+{
+ sal_uInt16 nIdx = GetIndex( rShort );
+ SwBlockName* pNew = NULL;
+ if( nIdx != (sal_uInt16) -1 )
+ aNames.DeleteAndDestroy( nIdx );
+
+ GeneratePackageName( rShort, aPackageName );
+ pNew = new SwBlockName( rShort, rLong, aPackageName );
+
+ pNew->bIsOnlyTxtFlagInit = sal_True;
+ pNew->bIsOnlyTxt = bOnlyTxt;
+ aNames.C40_PTR_INSERT( SwBlockName, pNew );
+ bInfoChanged = sal_True;
+}
+void SwXMLTextBlocks::AddName( const String& rShort, const String& rLong,
+ const String& rPackageName, sal_Bool bOnlyTxt )
+{
+ sal_uInt16 nIdx = GetIndex( rShort );
+ if( nIdx != (sal_uInt16) -1 )
+ aNames.DeleteAndDestroy( nIdx );
+ SwBlockName* pNew = new SwBlockName( rShort, rLong, rPackageName );
+ pNew->bIsOnlyTxtFlagInit = sal_True;
+ pNew->bIsOnlyTxt = bOnlyTxt;
+ aNames.C40_PTR_INSERT( SwBlockName, pNew );
+ bInfoChanged = sal_True;
+}
+
+sal_uLong SwXMLTextBlocks::Delete( sal_uInt16 n )
+{
+ String aPckName (aNames[ n ]->aPackageName);
+ uno::Reference < container::XNameAccess > xAccess( xBlkRoot, uno::UNO_QUERY );
+ if ( xAccess.is() &&
+ xAccess->hasByName( aPckName ) && xBlkRoot->isStreamElement( aPckName ) )
+ {
+ try
+ {
+ xBlkRoot->removeElement ( aPckName );
+ uno::Reference < embed::XTransactedObject > xTrans( xBlkRoot, uno::UNO_QUERY );
+ if ( xTrans.is() )
+ xTrans->commit();
+ return 0;
+ }
+ catch ( uno::Exception)
+ {
+ return ERR_SWG_WRITE_ERROR;
+ }
+ }
+ return 0;
+}
+
+sal_uLong SwXMLTextBlocks::Rename( sal_uInt16 nIdx, const String& rNewShort, const String& )
+{
+ DBG_ASSERT( xBlkRoot.is(), "No storage set" );
+ if(!xBlkRoot.is())
+ return 0;
+ String aOldName (aNames[ nIdx ]->aPackageName);
+ aShort = rNewShort;
+ GeneratePackageName( aShort, aPackageName );
+ if (IsOnlyTextBlock ( nIdx ) )
+ {
+ String sExt( String::CreateFromAscii( ".xml" ));
+ String aOldStreamName( aOldName ); aOldStreamName += sExt;
+ String aNewStreamName( aPackageName ); aNewStreamName += sExt;
+
+ xRoot = xBlkRoot->openStorageElement( aOldName, embed::ElementModes::READWRITE );
+ xRoot->renameElement ( aOldStreamName, aNewStreamName );
+ uno::Reference < embed::XTransactedObject > xTrans( xRoot, uno::UNO_QUERY );
+ if ( xTrans.is() )
+ xTrans->commit();
+ xRoot = 0;
+ }
+
+ if(aOldName != aPackageName)
+ {
+ try
+ {
+ xBlkRoot->renameElement ( aOldName, aPackageName );
+ }
+ catch( const container::ElementExistException& rEx )
+ {
+ (void)rEx;
+ }
+ }
+ uno::Reference < embed::XTransactedObject > xTrans( xBlkRoot, uno::UNO_QUERY );
+ if ( xTrans.is() )
+ xTrans->commit();
+ // No need to commit xBlkRoot here as SwTextBlocks::Rename calls
+ // WriteInfo which does the commit
+ return 0;
+}
+
+sal_uLong SwXMLTextBlocks::CopyBlock( SwImpBlocks& rDestImp, String& rShort,
+ const String& rLong)
+{
+ sal_uLong nError = 0;
+ OpenFile(sal_True);
+ rDestImp.OpenFile(sal_False);
+ String aGroup( rShort );
+ sal_Bool bTextOnly = IsOnlyTextBlock ( rShort ) ;//pImp->pBlkRoot->IsStream( aGroup );
+ sal_uInt16 nIndex = GetIndex ( rShort );
+ String sDestShortName( GetPackageName (nIndex) );
+ sal_uInt16 nIdx = 0;
+
+ DBG_ASSERT( xBlkRoot.is(), "No storage set" );
+ if(!xBlkRoot.is())
+ return ERR_SWG_WRITE_ERROR;
+
+ uno::Reference < container::XNameAccess > xAccess( ((SwXMLTextBlocks&)rDestImp).xBlkRoot, uno::UNO_QUERY );
+ while ( xAccess->hasByName( sDestShortName ) )
+ {
+ ++nIdx;
+ //falls wirklich mal einer so verrueckt ist
+ if(USHRT_MAX == nIdx)
+ {
+ CloseFile();
+ rDestImp.CloseFile();
+ return ERR_SWG_WRITE_ERROR;
+ }
+ sDestShortName += String::CreateFromInt32( nIdx );
+ }
+
+ try
+ {
+ uno::Reference < embed::XStorage > rSourceRoot = xBlkRoot->openStorageElement( aGroup, embed::ElementModes::READ );
+ uno::Reference < embed::XStorage > rDestRoot = ((SwXMLTextBlocks&)rDestImp).xBlkRoot->openStorageElement( sDestShortName, embed::ElementModes::READWRITE );
+ rSourceRoot->copyToStorage( rDestRoot );
+ }
+ catch ( uno::Exception& )
+ {
+ nError = ERR_SWG_WRITE_ERROR;
+ }
+
+ if(!nError)
+ {
+ rShort = sDestShortName;
+ ((SwXMLTextBlocks&)rDestImp).AddName( rShort, rLong, bTextOnly );
+ ((SwXMLTextBlocks&)rDestImp).MakeBlockList();
+ }
+ CloseFile();
+ rDestImp.CloseFile();
+ return nError;
+}
+
+
+sal_uLong SwXMLTextBlocks::StartPutBlock( const String& rShort, const String& rPackageName )
+{
+ DBG_ASSERT( xBlkRoot.is(), "No storage set" );
+ if(!xBlkRoot.is())
+ return 0;
+ GetIndex ( rShort );
+ try
+ {
+ xRoot = xBlkRoot->openStorageElement( rPackageName, embed::ElementModes::READWRITE );
+
+ uno::Reference< beans::XPropertySet > xRootProps( xRoot, uno::UNO_QUERY_THROW );
+ ::rtl::OUString aPropName( RTL_CONSTASCII_USTRINGPARAM("MediaType") );
+ ::rtl::OUString aMime( SotExchange::GetFormatMimeType( SOT_FORMATSTR_ID_STARWRITER_8 ) );
+ xRootProps->setPropertyValue( aPropName, uno::makeAny( aMime ) );
+ }
+ catch (uno::Exception&)
+ {
+ }
+ return 0;
+}
+sal_uLong SwXMLTextBlocks::BeginPutDoc( const String& rShort, const String& rLong )
+{
+ // In der Basisklasse ablegen!
+ aShort = rShort;
+ aLong = rLong;
+ GeneratePackageName( rShort, aPackageName );
+ SetIsTextOnly( rShort, sal_False);
+ return StartPutBlock (rShort, aPackageName);
+}
+
+sal_uLong SwXMLTextBlocks::PutBlock( SwPaM& , const String& )
+{
+ sal_uLong nRes = 0;
+ sal_uInt16 nCommitFlags = nFlags & (SWXML_CONVBLOCK|SWXML_NOROOTCOMMIT);
+
+ nFlags |= nCommitFlags;
+
+ WriterRef xWrt;
+ ::GetXMLWriter ( aEmptyStr, GetBaseURL(), xWrt);
+ SwWriter aWriter (xRoot, *pDoc );
+
+ xWrt->bBlock = sal_True;
+ nRes = aWriter.Write ( xWrt );
+ xWrt->bBlock = sal_False;
+ // Save OLE objects if there are some
+ SwDocShell *pDocSh = pDoc->GetDocShell();
+
+ sal_Bool bHasChildren = pDocSh && pDocSh->GetEmbeddedObjectContainer().HasEmbeddedObjects();
+ if( !nRes && bHasChildren )
+ {
+ // we have to write to the temporary storage first, since the used below functions are optimized
+ // TODO/LATER: it is only a temporary solution, that should be changed soon, the used methods should be
+ // called without optimization
+
+ sal_Bool bOK = sal_False;
+
+ if ( xRoot.is() )
+ {
+ SfxMedium* pTmpMedium = NULL;
+ try
+ {
+ uno::Reference< embed::XStorage > xTempStorage =
+ ::comphelper::OStorageHelper::GetTemporaryStorage();
+
+ xRoot->copyToStorage( xTempStorage );
+
+ // TODO/LATER: no progress bar?!
+ // TODO/MBA: strange construct
+ pTmpMedium = new SfxMedium( xTempStorage, GetBaseURL() );
+ sal_Bool bTmpOK = pDocSh->SaveAsChildren( *pTmpMedium );
+ if( bTmpOK )
+ bTmpOK = pDocSh->SaveCompletedChildren( sal_False );
+
+ xTempStorage->copyToStorage( xRoot );
+ bOK = bTmpOK;
+ }
+ catch( uno::Exception& )
+ {
+ }
+
+ if ( pTmpMedium )
+ DELETEZ( pTmpMedium );
+ }
+
+ if( !bOK )
+ nRes = ERR_SWG_WRITE_ERROR;
+ }
+
+ try
+ {
+ uno::Reference < embed::XTransactedObject > xTrans( xRoot, uno::UNO_QUERY );
+ if ( xTrans.is() )
+ xTrans->commit();
+ xRoot = 0;
+ if ( !nCommitFlags )
+ {
+ uno::Reference < embed::XTransactedObject > xTmpTrans( xBlkRoot, uno::UNO_QUERY );
+ if ( xTmpTrans.is() )
+ xTmpTrans->commit();
+ }
+ }
+ catch (uno::Exception&)
+ {
+ }
+
+ //TODO/LATER: error handling
+ return 0;
+}
+
+sal_uLong SwXMLTextBlocks::PutDoc()
+{
+ SwPaM* pPaM = MakePaM();
+ sal_uLong nErr = PutBlock(*pPaM, aLong);
+ delete pPaM;
+ return nErr;
+}
+
+sal_uLong SwXMLTextBlocks::GetText( sal_uInt16 nIdx, String& rText )
+{
+ return GetBlockText( aNames[ nIdx ]->aShort, rText );
+}
+
+sal_uLong SwXMLTextBlocks::GetText( const String& rShort, String& rText )
+{
+ return GetBlockText( rShort, rText );
+}
+
+
+sal_uLong SwXMLTextBlocks::MakeBlockList()
+{
+ WriteInfo();
+ return 0;
+}
+
+sal_Bool SwXMLTextBlocks::PutMuchEntries( sal_Bool bOn )
+{
+ sal_Bool bRet = sal_False;
+ if( bOn )
+ {
+ if( bInPutMuchBlocks )
+ {
+ OSL_ENSURE( !this, "verschachtelte Aufrufe sind nicht erlaubt" );
+ }
+ else if( !IsFileChanged() )
+ {
+ bRet = 0 == OpenFile( sal_False );
+ if( bRet )
+ {
+ nFlags |= SWXML_NOROOTCOMMIT;
+ bInPutMuchBlocks = sal_True;
+ }
+ }
+ }
+ else if( bInPutMuchBlocks )
+ {
+ nFlags &= ~SWXML_NOROOTCOMMIT;
+ if( xBlkRoot.is() )
+ {
+ try
+ {
+ uno::Reference < embed::XTransactedObject > xTrans( xBlkRoot, uno::UNO_QUERY );
+ if ( xTrans.is() )
+ xTrans->commit();
+ MakeBlockList();
+ CloseFile();
+ Touch();
+ bInPutMuchBlocks = sal_False;
+ bRet = sal_True;
+ }
+ catch (uno::Exception&)
+ {
+ }
+ }
+ }
+ return bRet;
+}
+
+sal_uLong SwXMLTextBlocks::OpenFile( sal_Bool bRdOnly )
+{
+ if( bAutocorrBlock )
+ return 0;
+ sal_uLong nRet = 0;
+ try
+ {
+ uno::Reference < embed::XStorage > refStg = comphelper::OStorageHelper::GetStorageFromURL( aFile,
+ bRdOnly ? embed::ElementModes::READ : embed::ElementModes::READWRITE );
+ InitBlockMode ( refStg );
+ }
+ catch ( uno::Exception& )
+ {
+ //TODO/LATER: error handling
+ nRet = 1;
+ }
+
+ return nRet;
+}
+
+void SwXMLTextBlocks::CloseFile()
+{
+ if ( !bAutocorrBlock )
+ {
+ if (bInfoChanged)
+ WriteInfo();
+ ResetBlockMode();
+ }
+}
+
+void SwXMLTextBlocks::SetIsTextOnly( const String& rShort, sal_Bool bNewValue )
+{
+ sal_uInt16 nIdx = GetIndex ( rShort );
+ if (nIdx != (sal_uInt16) -1 && nIdx != USHRT_MAX)
+ aNames[nIdx]->bIsOnlyTxt = bNewValue;
+}
+
+void SwXMLTextBlocks::SetIsTextOnly( sal_uInt16 nIdx, sal_Bool bNewValue )
+{
+ aNames[nIdx]->bIsOnlyTxt = bNewValue;
+}
+
+sal_Bool SwXMLTextBlocks::IsOnlyTextBlock( const String& rShort ) const
+{
+ sal_uInt16 nIdx = GetIndex ( rShort );
+ sal_Bool bRet = sal_False;
+ if (nIdx != (sal_uInt16) -1 && nIdx != USHRT_MAX)
+ {
+ bRet = aNames[nIdx]->bIsOnlyTxt;
+ }
+ return bRet;
+}
+sal_Bool SwXMLTextBlocks::IsOnlyTextBlock( sal_uInt16 nIdx ) const
+{
+ return aNames[nIdx]->bIsOnlyTxt;
+}
+
+sal_Bool SwXMLTextBlocks::IsFileUCBStorage( const String & rFileName)
+{
+ String aName( rFileName );
+ INetURLObject aObj( aName );
+ if ( aObj.GetProtocol() == INET_PROT_NOT_VALID )
+ {
+ String aURL;
+ ::utl::LocalFileHelper::ConvertPhysicalNameToURL( aName, aURL );
+ aObj.SetURL( aURL );
+ aName = aObj.GetMainURL( INetURLObject::NO_DECODE );
+ }
+
+ SvStream * pStm = ::utl::UcbStreamHelper::CreateStream( aName, STREAM_STD_READ );
+ sal_Bool bRet = UCBStorage::IsStorageFile( pStm );
+ delete pStm;
+ return bRet;
+}
+
+
+
+short SwXMLTextBlocks::GetFileType ( void ) const
+{
+ return SWBLK_XML;
+}
+
+void SwXMLTextBlocks::GeneratePackageName ( const String& rShort, String& rPackageName )
+{
+ rPackageName = rShort;
+ xub_StrLen nPos = 0;
+ sal_Unicode pDelims[] = { '!', '/', ':', '.', '\\', 0 };
+ ByteString sByte ( rPackageName, RTL_TEXTENCODING_UTF7);
+ rPackageName = String (sByte, RTL_TEXTENCODING_ASCII_US);
+ while( STRING_NOTFOUND != ( nPos = rPackageName.SearchChar( pDelims, nPos )))
+ {
+ rPackageName.SetChar( nPos, '_' );
+ ++nPos;
+ }
+}
+
+sal_uLong SwXMLTextBlocks::PutText( const String& rShort, const String& rName,
+ const String& rText )
+{
+ sal_uLong nRes = 0;
+ aShort = rShort;
+ aLong = rName;
+ aCur = rText;
+ SetIsTextOnly( aShort, sal_True );
+ GeneratePackageName( rShort, aPackageName );
+ ClearDoc();
+ nRes = PutBlockText( rShort, rName, rText, aPackageName );
+ return nRes;
+}
+
+void SwXMLTextBlocks::MakeBlockText( const String& rText )
+{
+ SwTxtNode* pTxtNode = pDoc->GetNodes()[ pDoc->GetNodes().GetEndOfContent().
+ GetIndex() - 1 ]->GetTxtNode();
+ if( pTxtNode->GetTxtColl() == pDoc->GetDfltTxtFmtColl() )
+ pTxtNode->ChgFmtColl( pDoc->GetTxtCollFromPool( RES_POOLCOLL_STANDARD ));
+
+ xub_StrLen nPos = 0;
+ do
+ {
+ if ( nPos )
+ {
+ pTxtNode = (SwTxtNode*)pTxtNode->AppendNode( SwPosition( *pTxtNode ) );
+ }
+ SwIndex aIdx( pTxtNode );
+ String sTemp(rText.GetToken( 0, '\015', nPos ) );
+ pTxtNode->InsertText( sTemp, aIdx );
+ } while ( STRING_NOTFOUND != nPos );
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/swg/SwXMLTextBlocks1.cxx b/sw/source/core/swg/SwXMLTextBlocks1.cxx
new file mode 100644
index 000000000000..1b27ecdfeff6
--- /dev/null
+++ b/sw/source/core/swg/SwXMLTextBlocks1.cxx
@@ -0,0 +1,737 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+#include <com/sun/star/embed/ElementModes.hpp>
+#include <com/sun/star/embed/XTransactedObject.hpp>
+#include <svl/macitem.hxx>
+#include <svtools/unoevent.hxx>
+#include <sfx2/docfile.hxx>
+#include <unotools/streamwrap.hxx>
+#include <comphelper/processfactory.hxx>
+#include <com/sun/star/xml/sax/InputSource.hpp>
+#include <com/sun/star/io/XActiveDataSource.hpp>
+#include <com/sun/star/xml/sax/XParser.hpp>
+#include <com/sun/star/document/XStorageBasedDocument.hpp>
+#include <doc.hxx>
+#include <docsh.hxx>
+#include <shellio.hxx>
+#include <SwXMLTextBlocks.hxx>
+#include <SwXMLBlockImport.hxx>
+#include <SwXMLBlockExport.hxx>
+#include <swevent.hxx>
+#include <swerror.h>
+
+
+#define STREAM_STGREAD ( STREAM_READ | STREAM_SHARE_DENYWRITE | STREAM_NOCREATE )
+#define STREAM_STGWRITE ( STREAM_READ | STREAM_WRITE | STREAM_SHARE_DENYWRITE )
+
+sal_Char XMLN_BLOCKLIST[] = "BlockList.xml";
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::container;
+using ::rtl::OUString;
+
+using ::xmloff::token::XML_BLOCK_LIST;
+using ::xmloff::token::XML_UNFORMATTED_TEXT;
+using ::xmloff::token::GetXMLToken;
+
+sal_uLong SwXMLTextBlocks::GetDoc( sal_uInt16 nIdx )
+{
+ String aFolderName ( GetPackageName ( nIdx ) );
+
+ if (!IsOnlyTextBlock ( nIdx ) )
+ {
+ try
+ {
+ xRoot = xBlkRoot->openStorageElement( aFolderName, embed::ElementModes::READ );
+ xMedium = new SfxMedium(xRoot, GetBaseURL());
+ SwReader aReader(*xMedium,aFolderName, pDoc );
+ ReadXML->SetBlockMode( sal_True );
+ aReader.Read( *ReadXML );
+ ReadXML->SetBlockMode( sal_False );
+ // Ole objects fails to display when inserted into document
+ // because the ObjectReplacement folder ( and contents are missing )
+ rtl::OUString sObjReplacements( RTL_CONSTASCII_USTRINGPARAM( "ObjectReplacements" ) );
+ if ( xRoot->hasByName( sObjReplacements ) )
+ {
+ uno::Reference< document::XStorageBasedDocument > xDocStor( pDoc->GetDocShell()->GetModel(), uno::UNO_QUERY_THROW );
+ uno::Reference< embed::XStorage > xStr( xDocStor->getDocumentStorage() );
+ if ( xStr.is() )
+ {
+ xRoot->copyElementTo( sObjReplacements, xStr, sObjReplacements );
+ uno::Reference< embed::XTransactedObject > xTrans( xStr, uno::UNO_QUERY );
+ if ( xTrans.is() )
+ xTrans->commit();
+ }
+ }
+ }
+ catch( uno::Exception& )
+ {
+ }
+
+ xRoot = 0;
+ }
+ else
+ {
+ String aStreamName = aFolderName + (OUString) String::CreateFromAscii(".xml");
+ try
+ {
+ xRoot = xBlkRoot->openStorageElement( aFolderName, embed::ElementModes::READ );
+ uno::Reference < io::XStream > xStream = xRoot->openStreamElement( aStreamName, embed::ElementModes::READ );
+
+ uno::Reference< lang::XMultiServiceFactory > xServiceFactory =
+ comphelper::getProcessServiceFactory();
+ OSL_ENSURE( xServiceFactory.is(), "XMLReader::Read: got no service manager" );
+ if( !xServiceFactory.is() )
+ {
+ // Throw an exception ?
+ }
+
+ xml::sax::InputSource aParserInput;
+ aParserInput.sSystemId = aNames [ nIdx ] ->aPackageName;
+
+ aParserInput.aInputStream = xStream->getInputStream();
+
+ // get parser
+ uno::Reference< XInterface > xXMLParser = xServiceFactory->createInstance(
+ OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.xml.sax.Parser")));
+ OSL_ENSURE( xXMLParser.is(),
+ "XMLReader::Read: com.sun.star.xml.sax.Parser service missing" );
+ if( !xXMLParser.is() )
+ {
+ // Maybe throw an exception?
+ }
+
+ // get filter
+ // #110680#
+ // uno::Reference< xml::sax::XDocumentHandler > xFilter = new SwXMLTextBlockImport( *this, aCur, sal_True );
+ uno::Reference< xml::sax::XDocumentHandler > xFilter = new SwXMLTextBlockImport( xServiceFactory, *this, aCur, sal_True );
+
+ // connect parser and filter
+ uno::Reference< xml::sax::XParser > xParser( xXMLParser, UNO_QUERY );
+ xParser->setDocumentHandler( xFilter );
+
+ // parse
+ try
+ {
+ xParser->parseStream( aParserInput );
+ }
+ catch( xml::sax::SAXParseException& )
+ {
+ // re throw ?
+ }
+ catch( xml::sax::SAXException& )
+ {
+ // re throw ?
+ }
+ catch( io::IOException& )
+ {
+ // re throw ?
+ }
+
+ bInfoChanged = sal_False;
+ MakeBlockText(aCur);
+ }
+ catch( uno::Exception& )
+ {
+ }
+
+ xRoot = 0;
+ }
+ return 0;
+}
+
+// event description for autotext events; this constant should really be
+// taken from unocore/unoevents.cxx or ui/unotxt.cxx
+const struct SvEventDescription aAutotextEvents[] =
+{
+ { SW_EVENT_START_INS_GLOSSARY, "OnInsertStart" },
+ { SW_EVENT_END_INS_GLOSSARY, "OnInsertDone" },
+ { 0, NULL }
+};
+
+sal_uLong SwXMLTextBlocks::GetMacroTable( sal_uInt16 nIdx,
+ SvxMacroTableDtor& rMacroTbl,
+ sal_Bool bFileAlreadyOpen )
+{
+ // set current auto text
+
+ aShort = aNames[ nIdx ]->aShort;
+ aLong = aNames[ nIdx ]->aLong;
+ aPackageName = aNames[ nIdx ]->aPackageName;
+
+ sal_uLong nRet = 0;
+
+ // open stream in proper sub-storage
+ if( !bFileAlreadyOpen )
+ {
+ CloseFile();
+ nRet = OpenFile ( sal_True );
+ }
+ if ( 0 == nRet )
+ {
+ try
+ {
+ xRoot = xBlkRoot->openStorageElement( aPackageName, embed::ElementModes::READ );
+ long nTmp = SOT_FORMATSTR_ID_STARWRITER_60;
+ sal_Bool bOasis = ( SotStorage::GetVersion( xRoot ) > nTmp );
+
+ OUString sStreamName(RTL_CONSTASCII_USTRINGPARAM("atevent.xml"));
+ uno::Reference < io::XStream > xDocStream = xRoot->openStreamElement(
+ sStreamName, embed::ElementModes::READ );
+ DBG_ASSERT(xDocStream.is(), "Can't create stream");
+ if ( xDocStream.is() )
+ {
+ uno::Reference<io::XInputStream> xInputStream = xDocStream->getInputStream();
+
+ // prepare ParserInputSrouce
+ xml::sax::InputSource aParserInput;
+ aParserInput.sSystemId = aName;
+ aParserInput.aInputStream = xInputStream;
+
+ // get service factory
+ uno::Reference< lang::XMultiServiceFactory > xServiceFactory =
+ comphelper::getProcessServiceFactory();
+ if ( xServiceFactory.is() )
+ {
+
+ // get parser
+ OUString sParserService( RTL_CONSTASCII_USTRINGPARAM(
+ "com.sun.star.xml.sax.Parser" ) );
+ uno::Reference< xml::sax::XParser > xParser(
+ xServiceFactory->createInstance(sParserService),
+ UNO_QUERY );
+ DBG_ASSERT( xParser.is(), "Can't create parser" );
+ if( xParser.is() )
+ {
+ // create descriptor and reference to it. Either
+ // both or neither must be kept because of the
+ // reference counting!
+ SvMacroTableEventDescriptor* pDescriptor =
+ new SvMacroTableEventDescriptor(aAutotextEvents);
+ uno::Reference<XNameReplace> xReplace = pDescriptor;
+ Sequence<Any> aFilterArguments( 1 );
+ aFilterArguments[0] <<= xReplace;
+
+ // get filter
+ OUString sFilterComponent = bOasis
+ ? OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.comp.Writer.XMLOasisAutotextEventsImporter"))
+ : OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.comp.Writer.XMLAutotextEventsImporter"));
+ uno::Reference< xml::sax::XDocumentHandler > xFilter(
+ xServiceFactory->createInstanceWithArguments(
+ sFilterComponent, aFilterArguments),
+ UNO_QUERY );
+ DBG_ASSERT( xFilter.is(),
+ "can't instantiate atevents filter");
+ if ( xFilter.is() )
+ {
+ // connect parser and filter
+ xParser->setDocumentHandler( xFilter );
+
+ // connect model and filter
+ uno::Reference<document::XImporter> xImporter( xFilter,
+ UNO_QUERY );
+
+ // we don't need a model
+ // xImporter->setTargetDocument( xModelComponent );
+
+ // parse the stream
+ try
+ {
+ xParser->parseStream( aParserInput );
+ }
+ catch( xml::sax::SAXParseException& )
+ {
+ // workaround for #83452#: SetSize doesn't work
+ // nRet = ERR_SWG_READ_ERROR;
+ }
+ catch( xml::sax::SAXException& )
+ {
+ nRet = ERR_SWG_READ_ERROR;
+ }
+ catch( io::IOException& )
+ {
+ nRet = ERR_SWG_READ_ERROR;
+ }
+
+ // and finally, copy macro into table
+ if (0 == nRet)
+ pDescriptor->copyMacrosIntoTable(rMacroTbl);
+ }
+ else
+ nRet = ERR_SWG_READ_ERROR;
+ }
+ else
+ nRet = ERR_SWG_READ_ERROR;
+
+ }
+ else
+ nRet = ERR_SWG_READ_ERROR;
+ }
+ else
+ nRet = ERR_SWG_READ_ERROR;
+ }
+ catch( uno::Exception& )
+ {
+ nRet = ERR_SWG_READ_ERROR;
+ }
+ }
+ else
+ nRet = ERR_SWG_READ_ERROR;
+
+ // success!
+ return nRet;
+}
+
+
+sal_uLong SwXMLTextBlocks::GetBlockText( const String& rShort, String& rText )
+{
+ sal_uLong n = 0;
+ sal_Bool bTextOnly = sal_True;
+ String aFolderName;
+ GeneratePackageName ( rShort, aFolderName );
+ String aStreamName = aFolderName + (OUString) String::CreateFromAscii(".xml");
+ rText.Erase();
+
+ try
+ {
+ xRoot = xBlkRoot->openStorageElement( aFolderName, embed::ElementModes::READ );
+ uno::Reference < container::XNameAccess > xAccess( xRoot, uno::UNO_QUERY );
+ if ( !xAccess->hasByName( aStreamName ) || !xRoot->isStreamElement( aStreamName ) )
+ {
+ bTextOnly = sal_False;
+ aStreamName = String::CreateFromAscii("content.xml");
+ }
+
+ uno::Reference < io::XStream > xContents = xRoot->openStreamElement( aStreamName, embed::ElementModes::READ );
+ uno::Reference< lang::XMultiServiceFactory > xServiceFactory =
+ comphelper::getProcessServiceFactory();
+ OSL_ENSURE( xServiceFactory.is(), "XMLReader::Read: got no service manager" );
+ if( !xServiceFactory.is() )
+ {
+ // Throw an exception ?
+ }
+
+ xml::sax::InputSource aParserInput;
+ aParserInput.sSystemId = aName;
+ aParserInput.aInputStream = xContents->getInputStream();
+
+ // get parser
+ uno::Reference< XInterface > xXMLParser = xServiceFactory->createInstance(
+ OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.xml.sax.Parser")) );
+ OSL_ENSURE( xXMLParser.is(),
+ "XMLReader::Read: com.sun.star.xml.sax.Parser service missing" );
+ if( !xXMLParser.is() )
+ {
+ // Maybe throw an exception?
+ }
+
+ // get filter
+ // #110680#
+ // uno::Reference< xml::sax::XDocumentHandler > xFilter = new SwXMLTextBlockImport( *this, rText, bTextOnly );
+ uno::Reference< xml::sax::XDocumentHandler > xFilter = new SwXMLTextBlockImport( xServiceFactory, *this, rText, bTextOnly );
+
+ // connect parser and filter
+ uno::Reference< xml::sax::XParser > xParser( xXMLParser, UNO_QUERY );
+ xParser->setDocumentHandler( xFilter );
+
+ // parse
+ try
+ {
+ xParser->parseStream( aParserInput );
+ }
+ catch( xml::sax::SAXParseException& )
+ {
+ // re throw ?
+ }
+ catch( xml::sax::SAXException& )
+ {
+ // re throw ?
+ }
+ catch( io::IOException& )
+ {
+ // re throw ?
+ }
+
+ xRoot = 0;
+ }
+ catch ( uno::Exception& )
+ {
+ OSL_FAIL( "Tried to open non-existent folder or stream!");
+ }
+
+ return n;
+}
+
+sal_uLong SwXMLTextBlocks::PutBlockText( const String& rShort, const String& ,
+ const String& rText, const String& rPackageName )
+{
+ GetIndex ( rShort );
+ /*
+ if (xBlkRoot->IsContained ( rPackageName ) )
+ {
+ xBlkRoot->Remove ( rPackageName );
+ xBlkRoot->Commit ( );
+ }
+ */
+ String aFolderName( rPackageName );
+ String aStreamName = aFolderName + (OUString) String::CreateFromAscii(".xml");
+
+ uno::Reference< lang::XMultiServiceFactory > xServiceFactory =
+ comphelper::getProcessServiceFactory();
+ OSL_ENSURE( xServiceFactory.is(),
+ "XMLReader::Read: got no service manager" );
+ if( !xServiceFactory.is() )
+ {
+ // Throw an exception ?
+ }
+
+ uno::Reference < XInterface > xWriter (xServiceFactory->createInstance(
+ OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.xml.sax.Writer"))));
+ DBG_ASSERT(xWriter.is(),"com.sun.star.xml.sax.Writer service missing");
+ sal_uLong nRes = 0;
+
+ try
+ {
+ xRoot = xBlkRoot->openStorageElement( aFolderName, embed::ElementModes::WRITE );
+ uno::Reference < io::XStream > xDocStream = xRoot->openStreamElement( aStreamName,
+ embed::ElementModes::WRITE | embed::ElementModes::TRUNCATE );
+
+ uno::Reference < beans::XPropertySet > xSet( xDocStream, uno::UNO_QUERY );
+ String aPropName( String::CreateFromAscii( RTL_CONSTASCII_STRINGPARAM("MediaType") ) );
+ OUString aMime ( RTL_CONSTASCII_USTRINGPARAM ( "text/xml") );
+ Any aAny;
+ aAny <<= aMime;
+ xSet->setPropertyValue( aPropName, aAny );
+ uno::Reference < io::XOutputStream > xOut = xDocStream->getOutputStream();
+ uno::Reference<io::XActiveDataSource> xSrc(xWriter, uno::UNO_QUERY);
+ xSrc->setOutputStream(xOut);
+
+ uno::Reference<xml::sax::XDocumentHandler> xHandler(xWriter,
+ uno::UNO_QUERY);
+
+ // #110680#
+ // SwXMLTextBlockExport aExp(*this, GetXMLToken ( XML_UNFORMATTED_TEXT ), xHandler);
+ SwXMLTextBlockExport aExp( xServiceFactory, *this, GetXMLToken ( XML_UNFORMATTED_TEXT ), xHandler);
+
+ aExp.exportDoc( rText );
+
+ uno::Reference < embed::XTransactedObject > xTrans( xRoot, uno::UNO_QUERY );
+ if ( xTrans.is() )
+ xTrans->commit();
+
+ if (! (nFlags & SWXML_NOROOTCOMMIT) )
+ {
+ uno::Reference < embed::XTransactedObject > xTmpTrans( xBlkRoot, uno::UNO_QUERY );
+ if ( xTmpTrans.is() )
+ xTmpTrans->commit();
+ }
+ }
+ catch ( uno::Exception& )
+ {
+ nRes = ERR_SWG_WRITE_ERROR;
+ }
+
+ xRoot = 0;
+
+ //TODO/LATER: error handling
+ /*
+ sal_uLong nErr = xBlkRoot->GetError();
+ sal_uLong nRes = 0;
+ if( nErr == SVSTREAM_DISK_FULL )
+ nRes = ERR_W4W_WRITE_FULL;
+ else if( nErr != SVSTREAM_OK )
+ nRes = ERR_SWG_WRITE_ERROR;
+ */
+ if( !nRes ) // damit ueber GetText & nCur aufs Doc zugegriffen
+ MakeBlockText( rText );
+
+ return nRes;
+}
+
+void SwXMLTextBlocks::ReadInfo( void )
+{
+ try
+ {
+ const OUString sDocName( RTL_CONSTASCII_USTRINGPARAM( XMLN_BLOCKLIST ) );
+ uno::Reference < container::XNameAccess > xAccess( xBlkRoot, uno::UNO_QUERY );
+ if ( xAccess.is() && xAccess->hasByName( sDocName ) && xBlkRoot->isStreamElement( sDocName ) )
+ {
+ uno::Reference< lang::XMultiServiceFactory > xServiceFactory =
+ comphelper::getProcessServiceFactory();
+ OSL_ENSURE( xServiceFactory.is(),
+ "XMLReader::Read: got no service manager" );
+ if( !xServiceFactory.is() )
+ {
+ // Throw an exception ?
+ }
+
+ xml::sax::InputSource aParserInput;
+ aParserInput.sSystemId = sDocName;
+
+ uno::Reference < io::XStream > xDocStream = xBlkRoot->openStreamElement( sDocName, embed::ElementModes::READ );
+ aParserInput.aInputStream = xDocStream->getInputStream();
+
+ // get parser
+ uno::Reference< XInterface > xXMLParser = xServiceFactory->createInstance(
+ OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.xml.sax.Parser")));
+ OSL_ENSURE( xXMLParser.is(),
+ "XMLReader::Read: com.sun.star.xml.sax.Parser service missing" );
+ if( !xXMLParser.is() )
+ {
+ // Maybe throw an exception?
+ }
+
+ // get filter
+ // #110680#
+ // uno::Reference< xml::sax::XDocumentHandler > xFilter = new SwXMLBlockListImport( *this );
+ uno::Reference< xml::sax::XDocumentHandler > xFilter = new SwXMLBlockListImport( xServiceFactory, *this );
+
+ // connect parser and filter
+ uno::Reference< xml::sax::XParser > xParser( xXMLParser, UNO_QUERY );
+ xParser->setDocumentHandler( xFilter );
+
+ // parse
+ try
+ {
+ xParser->parseStream( aParserInput );
+ }
+ catch( xml::sax::SAXParseException& )
+ {
+ // re throw ?
+ }
+ catch( xml::sax::SAXException& )
+ {
+ // re throw ?
+ }
+ catch( io::IOException& )
+ {
+ // re throw ?
+ }
+ }
+ }
+ catch ( uno::Exception& )
+ {
+ }
+}
+void SwXMLTextBlocks::WriteInfo( void )
+{
+ if ( xBlkRoot.is() || 0 == OpenFile ( sal_False ) )
+ {
+ uno::Reference< lang::XMultiServiceFactory > xServiceFactory =
+ comphelper::getProcessServiceFactory();
+ DBG_ASSERT( xServiceFactory.is(),
+ "XMLReader::Read: got no service manager" );
+ if( !xServiceFactory.is() )
+ {
+ // Throw an exception ?
+ }
+
+ uno::Reference < XInterface > xWriter (xServiceFactory->createInstance(
+ OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.xml.sax.Writer"))));
+ DBG_ASSERT(xWriter.is(),"com.sun.star.xml.sax.Writer service missing");
+ OUString sDocName( RTL_CONSTASCII_USTRINGPARAM( XMLN_BLOCKLIST ) );
+
+ /*
+ if ( xBlkRoot->IsContained( sDocName) )
+ {
+ xBlkRoot->Remove ( sDocName );
+ xBlkRoot->Commit();
+ }
+ */
+
+ try
+ {
+ uno::Reference < io::XStream > xDocStream = xBlkRoot->openStreamElement( sDocName,
+ embed::ElementModes::WRITE | embed::ElementModes::TRUNCATE );
+
+ uno::Reference < beans::XPropertySet > xSet( xDocStream, uno::UNO_QUERY );
+ String aPropName( String::CreateFromAscii( RTL_CONSTASCII_STRINGPARAM("MediaType") ) );
+ OUString aMime ( RTL_CONSTASCII_USTRINGPARAM ( "text/xml") );
+ Any aAny;
+ aAny <<= aMime;
+ xSet->setPropertyValue( aPropName, aAny );
+ uno::Reference < io::XOutputStream > xOut = xDocStream->getOutputStream();
+ uno::Reference<io::XActiveDataSource> xSrc(xWriter, uno::UNO_QUERY);
+ xSrc->setOutputStream(xOut);
+
+ uno::Reference<xml::sax::XDocumentHandler> xHandler(xWriter, uno::UNO_QUERY);
+
+ SwXMLBlockListExport aExp( xServiceFactory, *this, OUString(RTL_CONSTASCII_USTRINGPARAM(XMLN_BLOCKLIST)), xHandler);
+
+ aExp.exportDoc( XML_BLOCK_LIST );
+
+ uno::Reference < embed::XTransactedObject > xTrans( xBlkRoot, uno::UNO_QUERY );
+ if ( xTrans.is() )
+ xTrans->commit();
+ }
+ catch ( uno::Exception& )
+ {
+ }
+
+ bInfoChanged = sal_False;
+ return;
+ }
+}
+
+sal_uLong SwXMLTextBlocks::SetMacroTable(
+ sal_uInt16 nIdx,
+ const SvxMacroTableDtor& rMacroTbl,
+ sal_Bool bFileAlreadyOpen )
+{
+ // set current autotext
+ aShort = aNames[ nIdx ]->aShort;
+ aLong = aNames[ nIdx ]->aLong;
+ aPackageName = aNames[ nIdx ]->aPackageName;
+
+ // start XML autotext event export
+ sal_uLong nRes = 0;
+
+ uno::Reference< lang::XMultiServiceFactory > xServiceFactory =
+ comphelper::getProcessServiceFactory();
+ OSL_ENSURE( xServiceFactory.is(),
+ "XML autotext event write:: got no service manager" );
+ if( !xServiceFactory.is() )
+ return ERR_SWG_WRITE_ERROR;
+
+ // Get model
+ uno::Reference< lang::XComponent > xModelComp(
+ pDoc->GetDocShell()->GetModel(), UNO_QUERY );
+ OSL_ENSURE( xModelComp.is(), "XMLWriter::Write: got no model" );
+ if( !xModelComp.is() )
+ return ERR_SWG_WRITE_ERROR;
+
+ // open stream in proper sub-storage
+ if( !bFileAlreadyOpen )
+ {
+ CloseFile(); // close (it may be open in read-only-mode)
+ nRes = OpenFile ( sal_False );
+ }
+
+ if ( 0 == nRes )
+ {
+ try
+ {
+ xRoot = xBlkRoot->openStorageElement( aPackageName, embed::ElementModes::WRITE );
+ OUString sStreamName( RTL_CONSTASCII_USTRINGPARAM("atevent.xml") );
+ long nTmp = SOT_FORMATSTR_ID_STARWRITER_60;
+ sal_Bool bOasis = ( SotStorage::GetVersion( xRoot ) > nTmp );
+
+ uno::Reference < io::XStream > xDocStream = xRoot->openStreamElement( sStreamName,
+ embed::ElementModes::WRITE | embed::ElementModes::TRUNCATE );
+
+ uno::Reference < beans::XPropertySet > xSet( xDocStream, uno::UNO_QUERY );
+ String aPropName( String::CreateFromAscii( RTL_CONSTASCII_STRINGPARAM("MediaType") ) );
+ OUString aMime ( RTL_CONSTASCII_USTRINGPARAM ( "text/xml") );
+ Any aAny;
+ aAny <<= aMime;
+ xSet->setPropertyValue( aPropName, aAny );
+ uno::Reference < io::XOutputStream > xOutputStream = xDocStream->getOutputStream();
+
+ // get XML writer
+ uno::Reference< io::XActiveDataSource > xSaxWriter(
+ xServiceFactory->createInstance(
+ OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.xml.sax.Writer")) ),
+ UNO_QUERY );
+ OSL_ENSURE( xSaxWriter.is(), "can't instantiate XML writer" );
+ if( xSaxWriter.is() )
+ {
+
+ // connect XML writer to output stream
+ xSaxWriter->setOutputStream( xOutputStream );
+ uno::Reference<xml::sax::XDocumentHandler> xDocHandler(
+ xSaxWriter, UNO_QUERY);
+
+ // construct events object
+ uno::Reference<XNameAccess> xEvents =
+ new SvMacroTableEventDescriptor(rMacroTbl,aAutotextEvents);
+
+ // prepare arguments (prepend doc handler to given arguments)
+ Sequence<Any> aParams(2);
+ aParams[0] <<= xDocHandler;
+ aParams[1] <<= xEvents;
+
+
+ // get filter component
+ OUString sFilterComponent = bOasis
+ ? OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.comp.Writer.XMLOasisAutotextEventsExporter"))
+ : OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.comp.Writer.XMLAutotextEventsExporter"));
+ uno::Reference< document::XExporter > xExporter(
+ xServiceFactory->createInstanceWithArguments(
+ sFilterComponent, aParams), UNO_QUERY);
+ OSL_ENSURE( xExporter.is(),
+ "can't instantiate export filter component" );
+ if( xExporter.is() )
+ {
+ // connect model and filter
+ xExporter->setSourceDocument( xModelComp );
+
+ // filter!
+ Sequence<beans::PropertyValue> aFilterProps( 0 );
+ uno::Reference < document::XFilter > xFilter( xExporter,
+ UNO_QUERY );
+ xFilter->filter( aFilterProps );
+ }
+ else
+ nRes = ERR_SWG_WRITE_ERROR;
+ }
+ else
+ nRes = ERR_SWG_WRITE_ERROR;
+
+ // finally, commit stream, sub-storage and storage
+ uno::Reference < embed::XTransactedObject > xTmpTrans( xRoot, uno::UNO_QUERY );
+ if ( xTmpTrans.is() )
+ xTmpTrans->commit();
+
+ if ( !bFileAlreadyOpen )
+ {
+ uno::Reference < embed::XTransactedObject > xTrans( xBlkRoot, uno::UNO_QUERY );
+ if ( xTrans.is() )
+ xTrans->commit();
+ }
+
+ xRoot = 0;
+ }
+ catch ( uno::Exception& )
+ {
+ nRes = ERR_SWG_WRITE_ERROR;
+ }
+
+ if( !bFileAlreadyOpen )
+ CloseFile();
+ }
+ else
+ nRes = ERR_SWG_WRITE_ERROR;
+
+ return nRes;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/swg/swblocks.cxx b/sw/source/core/swg/swblocks.cxx
new file mode 100644
index 000000000000..f673905dab26
--- /dev/null
+++ b/sw/source/core/swg/swblocks.cxx
@@ -0,0 +1,657 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+
+#include <sfx2/docfilt.hxx>
+#include <sot/storage.hxx>
+#include <tools/urlobj.hxx>
+#include <svl/fstathelper.hxx>
+#include <svl/macitem.hxx>
+#include <unotools/charclass.hxx>
+#include <frmfmt.hxx>
+#include <doc.hxx>
+#include <docary.hxx>
+#include <pam.hxx>
+#include <shellio.hxx>
+#include <swblocks.hxx>
+#include <ndtxt.hxx>
+#include <mdiexp.hxx> // Progress
+#include <SwXMLTextBlocks.hxx>
+#include <docsh.hxx>
+#include <swunohelper.hxx>
+
+#include <statstr.hrc>
+#include <swerror.h>
+
+SV_IMPL_OP_PTRARR_SORT( SwBlockNames, SwBlockName* );
+
+//////////////////////////////////////////////////////////////////////////
+
+// Hash-Code errechnen (muss nicht eindeutig sein)
+
+
+sal_uInt16 SwImpBlocks::Hash( const String& r )
+{
+ sal_uInt16 n = 0;
+ xub_StrLen nLen = r.Len();
+ if( nLen > 8 )
+ nLen = 8;
+ const sal_Unicode* p = r.GetBuffer();
+ while( nLen-- )
+ n = ( n << 1 ) + *p++;
+ return n;
+}
+
+
+SwBlockName::SwBlockName( const String& rShort, const String& rLong, long n )
+ : nPos( n ), aShort( rShort ), aLong( rLong ), aPackageName (rShort),
+ bIsOnlyTxtFlagInit( sal_False ), bIsOnlyTxt( sal_False )
+{
+ nHashS = SwImpBlocks::Hash( rShort );
+ nHashL = SwImpBlocks::Hash( rLong );
+}
+SwBlockName::SwBlockName( const String& rShort, const String& rLong, const String& rPackageName)
+ : nPos( 0 ), aShort( rShort ), aLong( rLong ), aPackageName (rPackageName),
+ bIsOnlyTxtFlagInit( sal_False ), bIsOnlyTxt( sal_False )
+{
+ nHashS = SwImpBlocks::Hash( rShort );
+ nHashL = SwImpBlocks::Hash( rLong );
+}
+
+
+// Ist die angegebene Datei ein Storage oder gibt es sie nicht?
+
+short SwImpBlocks::GetFileType( const String& rFile )
+{
+ if( !FStatHelper::IsDocument( rFile ) )
+ return SWBLK_NO_FILE;
+ if( SwXMLTextBlocks::IsFileUCBStorage( rFile ) )
+ return SWBLK_XML;
+ if( SvStorage::IsStorageFile( rFile ) )
+ return SWBLK_SW3;
+ //otherwise return NONE
+ return SWBLK_NONE;
+}
+
+
+SwImpBlocks::SwImpBlocks( const String& rFile, sal_Bool )
+ : aFile( rFile ), pDoc( 0 ), nCur( (sal_uInt16)-1 ),
+ bReadOnly( sal_True ), bInPutMuchBlocks( sal_False )
+{
+ FStatHelper::GetModifiedDateTimeOfFile( rFile,
+ &aDateModified, &aTimeModified );
+ INetURLObject aObj(rFile);
+ aObj.setExtension( aEmptyStr );
+ aName = aObj.GetBase();
+}
+
+
+SwImpBlocks::~SwImpBlocks()
+{
+ aNames.DeleteAndDestroy( 0, aNames.Count() );
+}
+
+// Loeschen des Inhaltes des Dokuments
+void SwImpBlocks::ClearDoc()
+{
+ pDoc->ClearDoc();
+}
+
+sal_uLong SwImpBlocks::GetDocForConversion( sal_uInt16 n )
+{
+ return GetDoc( n );
+}
+
+// Erzeugen eines PaMs, der das ganze Dokument umfasst
+SwPaM* SwImpBlocks::MakePaM()
+{
+ SwPaM* pPam = new SwPaM( pDoc->GetNodes().GetEndOfContent() );
+ pPam->Move( fnMoveBackward, fnGoDoc );
+ pPam->SetMark();
+ pPam->Move( fnMoveForward, fnGoDoc );
+ pPam->Exchange();
+ return pPam;
+}
+
+
+sal_uInt16 SwImpBlocks::GetCount() const
+{
+ return aNames.Count();
+}
+
+// Case Insensitive
+sal_uInt16 SwImpBlocks::GetIndex( const String& rShort ) const
+{
+ String s( GetAppCharClass().upper( rShort ) );
+ sal_uInt16 nHash = Hash( s );
+ for( sal_uInt16 i = 0; i < aNames.Count(); i++ )
+ {
+ SwBlockName* pName = aNames[ i ];
+ if( pName->nHashS == nHash
+ && pName->aShort == s )
+ return i;
+ }
+ return (sal_uInt16) -1;
+}
+
+
+sal_uInt16 SwImpBlocks::GetLongIndex( const String& rLong ) const
+{
+ sal_uInt16 nHash = Hash( rLong );
+ for( sal_uInt16 i = 0; i < aNames.Count(); i++ )
+ {
+ SwBlockName* pName = aNames[ i ];
+ if( pName->nHashL == nHash
+ && pName->aLong == rLong )
+ return i;
+ }
+ return (sal_uInt16) -1;
+}
+
+
+const String& SwImpBlocks::GetShortName( sal_uInt16 n ) const
+{
+ if( n < aNames.Count() )
+ return aNames[ n ]->aShort;
+ return aEmptyStr;
+}
+
+
+const String& SwImpBlocks::GetLongName( sal_uInt16 n ) const
+{
+ if( n < aNames.Count() )
+ return aNames[ n ]->aLong;
+ return aEmptyStr;
+}
+
+const String& SwImpBlocks::GetPackageName( sal_uInt16 n ) const
+{
+ if( n < aNames.Count() )
+ return aNames[ n ]->aPackageName;
+ return aEmptyStr;
+}
+
+void SwImpBlocks::AddName( const String& rShort, const String& rLong,
+ sal_Bool bOnlyTxt )
+{
+ sal_uInt16 nIdx = GetIndex( rShort );
+ if( nIdx != (sal_uInt16) -1 )
+ aNames.DeleteAndDestroy( nIdx );
+ SwBlockName* pNew = new SwBlockName( rShort, rLong, 0L );
+ pNew->bIsOnlyTxtFlagInit = sal_True;
+ pNew->bIsOnlyTxt = bOnlyTxt;
+ aNames.C40_PTR_INSERT( SwBlockName, pNew );
+}
+
+
+
+sal_Bool SwImpBlocks::IsFileChanged() const
+{
+ Date aTempDateModified( aDateModified );
+ Time aTempTimeModified( aTimeModified );
+ return FStatHelper::GetModifiedDateTimeOfFile( aFile,
+ &aTempDateModified, &aTempTimeModified ) &&
+ ( aDateModified != aTempDateModified ||
+ aTimeModified != aTempTimeModified );
+}
+
+
+void SwImpBlocks::Touch()
+{
+ FStatHelper::GetModifiedDateTimeOfFile( aFile,
+ &aDateModified, &aTimeModified );
+}
+
+sal_Bool SwImpBlocks::IsOnlyTextBlock( const String& ) const
+{
+ return sal_False;
+}
+
+sal_uLong SwImpBlocks::GetMacroTable( sal_uInt16, SvxMacroTableDtor&, sal_Bool )
+{
+ return 0;
+}
+
+sal_uLong SwImpBlocks::SetMacroTable( sal_uInt16 ,
+ const SvxMacroTableDtor& , sal_Bool )
+{
+ return 0;
+}
+
+sal_Bool SwImpBlocks::PutMuchEntries( sal_Bool )
+{
+ return sal_False;
+}
+
+////////////////////////////////////////////////////////////////////////////
+
+
+SwTextBlocks::SwTextBlocks( const String& rFile )
+ : pImp( 0 ), nErr( 0 )
+{
+ INetURLObject aObj(rFile);
+ String sFileName = aObj.GetMainURL( INetURLObject::NO_DECODE );
+ switch( SwImpBlocks::GetFileType( rFile ) )
+ {
+ case SWBLK_XML: pImp = new SwXMLTextBlocks( sFileName ); break;
+ case SWBLK_NO_FILE: pImp = new SwXMLTextBlocks( sFileName ); break;
+ }
+ if( !pImp )
+ nErr = ERR_SWG_FILE_FORMAT_ERROR;
+}
+
+SwTextBlocks::~SwTextBlocks()
+{
+ delete pImp;
+}
+
+const String& SwTextBlocks::GetName()
+{
+ return pImp ? pImp->aName : aEmptyStr;
+}
+
+
+void SwTextBlocks::SetName( const String& r )
+{
+ if( pImp )
+ pImp->SetName( r );
+}
+
+
+sal_Bool SwTextBlocks::IsOld() const
+{
+ if (pImp)
+ {
+ short nType = pImp->GetFileType();
+ if (SWBLK_SW3 == nType || SWBLK_SW2 == nType )
+ return sal_True;
+ }
+ return sal_False;
+}
+
+
+sal_uInt16 SwTextBlocks::GetCount() const
+{
+ return pImp ? pImp->GetCount() : 0;
+}
+
+
+sal_uInt16 SwTextBlocks::GetIndex( const String& r ) const
+{
+ return pImp ? pImp->GetIndex( r ) : (sal_uInt16) -1;
+}
+
+
+sal_uInt16 SwTextBlocks::GetLongIndex( const String& r ) const
+{
+ return pImp ? (sal_uInt16)(pImp->GetLongIndex( r )) : (sal_uInt16) -1;
+}
+
+
+const String& SwTextBlocks::GetShortName( sal_uInt16 n ) const
+{
+ if( pImp )
+ return pImp->GetShortName( n );
+ return aEmptyStr;
+}
+
+
+const String& SwTextBlocks::GetLongName( sal_uInt16 n ) const
+{
+ if( pImp )
+ return pImp->GetLongName( n );
+ return aEmptyStr;
+}
+
+
+sal_Bool SwTextBlocks::Delete( sal_uInt16 n )
+{
+ if( pImp && !pImp->bInPutMuchBlocks )
+ {
+ if( pImp->IsFileChanged() )
+ nErr = ERR_TXTBLOCK_NEWFILE_ERROR;
+ else if( 0 == (nErr = pImp->OpenFile( sal_False ) ))
+ {
+ nErr = pImp->Delete( n );
+ if( !nErr )
+ pImp->aNames.DeleteAndDestroy( n );
+ if( n == pImp->nCur )
+ pImp->nCur = (sal_uInt16) -1;
+ if( !nErr )
+ nErr = pImp->MakeBlockList();
+ }
+ pImp->CloseFile();
+ pImp->Touch();
+
+ return sal_Bool( nErr == 0 );
+ }
+ return sal_False;
+}
+
+
+sal_uInt16 SwTextBlocks::Rename( sal_uInt16 n, const String* s, const String* l )
+{
+ sal_uInt16 nIdx = (sal_uInt16)-1;
+ if( pImp && !pImp->bInPutMuchBlocks )
+ {
+ pImp->nCur = nIdx;
+ String aNew, aLong;
+ if( s )
+ aNew = aLong = *s;
+ if( l )
+ aLong = *l;
+ if( !aNew.Len() )
+ {
+ OSL_ENSURE( !this, "Kein Kurzname in Rename angegeben" );
+ nErr = ERR_SWG_INTERNAL_ERROR; return (sal_uInt16) -1;
+ }
+
+ if( pImp->IsFileChanged() )
+ nErr = ERR_TXTBLOCK_NEWFILE_ERROR;
+ else if( 0 == ( nErr = pImp->OpenFile( sal_False )))
+ {
+ // Vorher den neuen Eintrag in die Liste setzen!
+ GetAppCharClass().toUpper( aNew );
+ nErr = pImp->Rename( n, aNew, aLong );
+ if( !nErr )
+ {
+ sal_Bool bOnlyTxt = pImp->aNames[ n ]->bIsOnlyTxt;
+ pImp->aNames.DeleteAndDestroy( n );
+ pImp->AddName( aNew, aLong, bOnlyTxt );
+ nErr = pImp->MakeBlockList();
+ }
+ }
+ pImp->CloseFile();
+ pImp->Touch();
+ if( !nErr )
+ nIdx = pImp->GetIndex( aNew );
+ }
+ return nIdx;
+}
+
+sal_uLong SwTextBlocks::CopyBlock( SwTextBlocks& rSource, String& rSrcShort,
+ const String& rLong )
+{
+ sal_Bool bIsOld = sal_False;
+ if (rSource.pImp)
+ {
+ short nType = rSource.pImp->GetFileType();
+ if (SWBLK_SW2 == nType || SWBLK_SW3 == nType )
+ bIsOld = sal_True;
+ }
+ if( bIsOld ) //rSource.IsOld() )
+ nErr = ERR_SWG_OLD_GLOSSARY;
+ else if( pImp->bInPutMuchBlocks )
+ nErr = ERR_SWG_INTERNAL_ERROR;
+ else
+ nErr = pImp->CopyBlock(*rSource.pImp, rSrcShort, rLong);
+ return nErr;
+}
+
+sal_Bool SwTextBlocks::BeginGetDoc( sal_uInt16 n )
+{
+ if( pImp && !pImp->bInPutMuchBlocks )
+ {
+// diese Optimierierung darf es nicht mehr geben. OLE-Objecte muessen auf
+// ihre SubStorages zugreifem koennen!
+// if( n == pImp->nCur )
+// return sal_True;
+
+ if( pImp->IsFileChanged() )
+ nErr = ERR_TXTBLOCK_NEWFILE_ERROR;
+ else if( 0 == ( nErr = pImp->OpenFile( sal_True )))
+ {
+ pImp->ClearDoc();
+ nErr = pImp->GetDoc( n );
+ if( nErr )
+ pImp->nCur = (sal_uInt16)-1;
+ else
+ pImp->nCur = n;
+ }
+ return sal_Bool( nErr == 0 );
+ }
+ return sal_False;
+}
+
+
+void SwTextBlocks::EndGetDoc()
+{
+ if( pImp && !pImp->bInPutMuchBlocks )
+ pImp->CloseFile();
+}
+
+
+sal_Bool SwTextBlocks::BeginPutDoc( const String& s, const String& l )
+{
+ if( pImp )
+ {
+ sal_Bool bOk = pImp->bInPutMuchBlocks;
+ if( !bOk )
+ {
+ if( pImp->IsFileChanged() )
+ nErr = ERR_TXTBLOCK_NEWFILE_ERROR;
+ else
+ nErr = pImp->OpenFile( sal_False );
+ bOk = 0 == nErr;
+ }
+ if( bOk )
+ {
+ String aNew( s );
+ GetAppCharClass().toUpper( aNew );
+ nErr = pImp->BeginPutDoc( aNew, l );
+ }
+ if( nErr )
+ pImp->CloseFile();
+ }
+ return 0 == nErr;
+}
+
+
+sal_uInt16 SwTextBlocks::PutDoc()
+{
+ sal_uInt16 nIdx = (sal_uInt16)-1;
+ if( pImp )
+ {
+ nErr = pImp->PutDoc();
+ if( !nErr )
+ {
+ pImp->nCur = GetIndex( pImp->aShort );
+ if( pImp->nCur != (sal_uInt16) -1 )
+ pImp->aNames[ pImp->nCur ]->aLong = pImp->aLong;
+ else
+ {
+ pImp->AddName( pImp->aShort, pImp->aLong );
+ pImp->nCur = pImp->GetIndex( pImp->aShort );
+ }
+ if( !pImp->bInPutMuchBlocks )
+ nErr = pImp->MakeBlockList();
+ }
+ if( !pImp->bInPutMuchBlocks )
+ {
+ pImp->CloseFile();
+ pImp->Touch();
+ }
+ nIdx = pImp->nCur;
+ }
+ return nIdx;
+}
+
+sal_uInt16 SwTextBlocks::PutText( const String& rShort, const String& rName,
+ const String& rTxt )
+{
+ sal_uInt16 nIdx = (sal_uInt16) -1;
+ if( pImp )
+ {
+ sal_Bool bOk = pImp->bInPutMuchBlocks;
+ if( !bOk )
+ {
+ if( pImp->IsFileChanged() )
+ nErr = ERR_TXTBLOCK_NEWFILE_ERROR;
+ else
+ nErr = pImp->OpenFile( sal_False );
+ bOk = 0 == nErr;
+ }
+ if( bOk )
+ {
+ String aNew( rShort );
+ GetAppCharClass().toUpper( aNew );
+ nErr = pImp->PutText( aNew, rName, rTxt );
+ pImp->nCur = (sal_uInt16) -1;
+ if( !nErr )
+ {
+ nIdx = GetIndex( pImp->aShort );
+ if( nIdx != (sal_uInt16) -1 )
+ pImp->aNames[ nIdx ]->aLong = rName;
+ else
+ {
+ pImp->AddName( pImp->aShort, rName, sal_True );
+ nIdx = pImp->GetIndex( pImp->aShort );
+ }
+ if( !pImp->bInPutMuchBlocks )
+ nErr = pImp->MakeBlockList();
+ }
+ }
+ if( !pImp->bInPutMuchBlocks )
+ {
+ pImp->CloseFile();
+ pImp->Touch();
+ }
+ }
+ return nIdx;
+}
+
+
+SwDoc* SwTextBlocks::GetDoc()
+{
+ if( pImp )
+ return pImp->pDoc;
+ return 0;
+}
+
+
+void SwTextBlocks::ClearDoc()
+{
+ if( pImp )
+ pImp->ClearDoc();
+ pImp->nCur = (sal_uInt16) -1;
+}
+
+
+const String& SwTextBlocks::GetFileName() const
+{
+ return pImp->GetFileName();
+}
+
+
+sal_Bool SwTextBlocks::IsReadOnly() const
+{
+ return pImp->bReadOnly;
+}
+
+sal_Bool SwTextBlocks::IsOnlyTextBlock( sal_uInt16 nIdx ) const
+{
+ sal_Bool bRet = sal_False;
+ if( pImp && !pImp->bInPutMuchBlocks )
+ {
+ SwBlockName* pBlkNm = pImp->aNames[ nIdx ];
+ if( !pBlkNm->bIsOnlyTxtFlagInit &&
+ !pImp->IsFileChanged() && !pImp->OpenFile( sal_True ) )
+ {
+ pBlkNm->bIsOnlyTxt = pImp->IsOnlyTextBlock( pBlkNm->aShort );
+ pBlkNm->bIsOnlyTxtFlagInit = sal_True;
+ pImp->CloseFile();
+ }
+ bRet = pBlkNm->bIsOnlyTxt;
+ }
+ return bRet;
+}
+
+sal_Bool SwTextBlocks::IsOnlyTextBlock( const String& rShort ) const
+{
+ sal_uInt16 nIdx = pImp->GetIndex( rShort );
+ if( USHRT_MAX != nIdx )
+ {
+ if( pImp->aNames[ nIdx ]->bIsOnlyTxtFlagInit )
+ return pImp->aNames[ nIdx ]->bIsOnlyTxt;
+ return IsOnlyTextBlock( nIdx );
+ }
+
+ OSL_ENSURE( !this, "ungueltiger Name" );
+ return sal_False;
+}
+
+sal_Bool SwTextBlocks::GetMacroTable( sal_uInt16 nIdx, SvxMacroTableDtor& rMacroTbl )
+{
+ sal_Bool bRet = sal_True;
+ if ( pImp && !pImp->bInPutMuchBlocks )
+ bRet = ( 0 == pImp->GetMacroTable( nIdx, rMacroTbl ) );
+ return bRet;
+}
+
+sal_Bool SwTextBlocks::SetMacroTable( sal_uInt16 nIdx,
+ const SvxMacroTableDtor& rMacroTbl )
+{
+ sal_Bool bRet = sal_True;
+ if ( pImp && !pImp->bInPutMuchBlocks )
+ bRet = ( 0 == pImp->SetMacroTable( nIdx, rMacroTbl ) );
+ return bRet;
+}
+
+sal_Bool SwTextBlocks::StartPutMuchBlockEntries()
+{
+ sal_Bool bRet = sal_False;
+ if( !IsOld() && pImp )
+ bRet = pImp->PutMuchEntries( sal_True );
+ return bRet;
+}
+
+void SwTextBlocks::EndPutMuchBlockEntries()
+{
+ if( pImp )
+ pImp->PutMuchEntries( sal_False );
+}
+
+String SwTextBlocks::GetBaseURL() const
+{
+ String sRet;
+ if(pImp)
+ sRet = pImp->GetBaseURL();
+ return sRet;
+}
+
+void SwTextBlocks::SetBaseURL( const String& rURL )
+{
+ if(pImp)
+ pImp->SetBaseURL(rURL);
+}
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/table/swnewtable.cxx b/sw/source/core/table/swnewtable.cxx
new file mode 100644
index 000000000000..f11fcd0be3bf
--- /dev/null
+++ b/sw/source/core/table/swnewtable.cxx
@@ -0,0 +1,2175 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+#include <swtable.hxx>
+#include <tblsel.hxx>
+#include <tblrwcl.hxx>
+#include <node.hxx>
+#include <UndoTable.hxx>
+#include <pam.hxx>
+#include <frmfmt.hxx>
+#include <frmatr.hxx>
+#include <cellfrm.hxx>
+#include <fmtfsize.hxx>
+#include <doc.hxx>
+#include <IDocumentUndoRedo.hxx>
+#include <vector>
+#include <set>
+#include <list>
+#include <memory>
+#include <editeng/boxitem.hxx>
+#include <editeng/protitem.hxx>
+#include <swtblfmt.hxx>
+#include <switerator.hxx>
+
+#if OSL_DEBUG_LEVEL > 1
+#define CHECK_TABLE(t) (t).CheckConsistency();
+#else
+#define CHECK_TABLE(t)
+#endif
+
+// ---------------------------------------------------------------
+
+/** SwBoxSelection is a small helperclass (structure) to handle selections
+ of cells (boxes) between table functions
+
+ It contains an "array" of table boxes, a rectangulare selection of table boxes.
+ To be more specific, it contains a vector of box selections,
+ every box selection (SwSelBoxes) contains the selected boxes inside one row.
+ The member mnMergeWidth contains the width of the selected boxes
+*/
+
+class SwBoxSelection
+{
+public:
+ std::vector<const SwSelBoxes*> aBoxes;
+ long mnMergeWidth;
+ SwBoxSelection() : mnMergeWidth(0) {}
+ bool isEmpty() const { return aBoxes.size() == 0; }
+ void insertBoxes( const SwSelBoxes* pNew ){ aBoxes.insert( aBoxes.end(), pNew ); }
+};
+
+/** NewMerge(..) removes the superfluous cells after cell merge
+
+SwTable::NewMerge(..) does some cleaning up,
+it simply deletes the superfluous cells ("cell span")
+and notifies the Undo about it.
+The main work has been done by SwTable::PrepareMerge(..) already.
+
+@param rBoxes
+the boxes to remove
+
+@param pUndo
+the undo object to notify, maybe empty
+
+@return sal_True for compatibility reasons with OldMerge(..)
+*/
+
+sal_Bool SwTable::NewMerge( SwDoc* pDoc, const SwSelBoxes& rBoxes,
+ const SwSelBoxes& rMerged, SwTableBox*, SwUndoTblMerge* pUndo )
+{
+ if( pUndo )
+ pUndo->SetSelBoxes( rBoxes );
+ DeleteSel( pDoc, rBoxes, &rMerged, 0, sal_True, sal_True );
+
+ CHECK_TABLE( *this )
+ return sal_True;
+}
+
+/** lcl_CheckMinMax helps evaluating (horizontal) min/max of boxes
+
+lcl_CheckMinMax(..) compares the left border and the right border
+of a given cell with the given range and sets it accordingly.
+
+@param rMin
+will be decremented if necessary to the left border of the cell
+
+@param rMax
+will be incremented if necessary to the right border of the cell
+
+@param rLine
+the row (table line) of the interesting box
+
+@param nCheck
+the index of the box in the table box array of the given row
+
+@param bSet
+if bSet is false, rMin and rMax will be manipulated if necessary
+if bSet is true, rMin and rMax will be set to the left and right border of the box
+
+*/
+
+void lcl_CheckMinMax( long& rMin, long& rMax, const SwTableLine& rLine, sal_uInt16 nCheck, bool bSet )
+{
+ ++nCheck;
+ if( rLine.GetTabBoxes().Count() < nCheck )
+ { // robust
+ OSL_FAIL( "Box out of table line" );
+ nCheck = rLine.GetTabBoxes().Count();
+ }
+
+ long nNew = 0; // will be the right border of the current box
+ long nWidth = 0; // the width of the current box
+ for( sal_uInt16 nCurrBox = 0; nCurrBox < nCheck; ++nCurrBox )
+ {
+ SwTableBox* pBox = rLine.GetTabBoxes()[nCurrBox];
+ OSL_ENSURE( pBox, "Missing table box" );
+ nWidth = pBox->GetFrmFmt()->GetFrmSize().GetWidth();
+ nNew += nWidth;
+ }
+ // nNew is the right border of the wished box
+ if( bSet || nNew > rMax )
+ rMax = nNew;
+ nNew -= nWidth; // nNew becomes the left border of the wished box
+ if( bSet || nNew < rMin )
+ rMin = nNew;
+}
+
+/** lcl_Box2LeftBorder(..) delivers the left (logical) border of a table box
+
+The left logical border of a table box is the sum of the cell width before this
+box.
+
+@param rBox
+is the requested table box
+
+@return is the left logical border (long, even it cannot be negative)
+
+*/
+
+long lcl_Box2LeftBorder( const SwTableBox& rBox )
+{
+ if( !rBox.GetUpper() )
+ return 0;
+ long nLeft = 0;
+ const SwTableLine &rLine = *rBox.GetUpper();
+ sal_uInt16 nCount = rLine.GetTabBoxes().Count();
+ for( sal_uInt16 nCurrBox = 0; nCurrBox < nCount; ++nCurrBox )
+ {
+ SwTableBox* pBox = rLine.GetTabBoxes()[nCurrBox];
+ OSL_ENSURE( pBox, "Missing table box" );
+ if( pBox == &rBox )
+ return nLeft;
+ nLeft += pBox->GetFrmFmt()->GetFrmSize().GetWidth();
+ }
+ OSL_FAIL( "Box not found in own upper?" );
+ return nLeft;
+}
+
+/** lcl_LeftBorder2Box delivers the box to a given left border
+
+It's used to find the master/follow table boxes in previous/next rows.
+Don't call this function to check if there is such a box,
+call it if you know there has to be such box.
+
+@param nLeft
+the left border (logical x-value) of the demanded box
+
+@param rLine
+the row (table line) to be scanned
+
+@return a pointer to the table box inside the given row with the wished left border
+
+*/
+
+SwTableBox* lcl_LeftBorder2Box( long nLeft, const SwTableLine* pLine )
+{
+ if( !pLine )
+ return 0;
+ long nCurrLeft = 0;
+ sal_uInt16 nCount = pLine->GetTabBoxes().Count();
+ for( sal_uInt16 nCurrBox = 0; nCurrBox < nCount; ++nCurrBox )
+ {
+ SwTableBox* pBox = pLine->GetTabBoxes()[nCurrBox];
+ OSL_ENSURE( pBox, "Missing table box" );
+ if( nCurrLeft >= nLeft && pBox->GetFrmFmt()->GetFrmSize().GetWidth() )
+ {
+ OSL_ENSURE( nCurrLeft == nLeft, "Wrong box found" );
+ return pBox;
+ }
+ nCurrLeft += pBox->GetFrmFmt()->GetFrmSize().GetWidth();
+ }
+ OSL_FAIL( "Didn't found wished box" );
+ return 0;
+}
+
+/** lcl_ChangeRowSpan corrects row span after insertion/deletion of rows
+
+lcl_ChangeRowSpan(..) has to be called after an insertion or deletion of rows
+to adjust the row spans of previous rows accordingly.
+If rows are deleted, the previous rows with row spans into the deleted area
+have to be decremented by the number of _overlapped_ inserted rows.
+If rows are inserted, the previous rows with row span into the inserted area
+have to be incremented by the number of inserted rows.
+For those row spans which ends exactly above the inserted area it has to be
+decided by the parameter bSingle if they have to be expanded or not.
+
+@param rTable
+the table to manipulate (has to be a new model table)
+
+@param nDiff
+the number of rows which has been inserted (nDiff > 0) or deleted (nDiff < 0)
+
+@param nRowIdx
+the index of the first row which has to be checked
+
+@param bSingle
+true if the new inserted row should not extend row spans which ends in the row above
+this is for rows inserted by UI "insert row"
+false if all cells of an inserted row has to be overlapped by the previous row
+this is for rows inserted by "split row"
+false is also needed for deleted rows
+
+*/
+
+void lcl_ChangeRowSpan( const SwTable& rTable, const long nDiff,
+ sal_uInt16 nRowIdx, const bool bSingle )
+{
+ if( !nDiff || nRowIdx >= rTable.GetTabLines().Count() )
+ return;
+ OSL_ENSURE( !bSingle || nDiff > 0, "Don't set bSingle when deleting lines!" );
+ bool bGoOn;
+ // nDistance is the distance between the current row and the critical row,
+ // e.g. the deleted rows or the inserted rows.
+ // If the row span is lower than the distance there is nothing to do
+ // because the row span ends before the critical area.
+ // When the inserted rows should not be overlapped by row spans which ends
+ // exactly in the row above, the trick is to start with a distance of 1.
+ long nDistance = bSingle ? 1 : 0;
+ do
+ {
+ bGoOn = false; // will be set to true if we found a non-master cell
+ // which has to be manipulated => we have to chekc the previous row, too.
+ const SwTableLine* pLine = rTable.GetTabLines()[ nRowIdx ];
+ sal_uInt16 nBoxCount = pLine->GetTabBoxes().Count();
+ for( sal_uInt16 nCurrBox = 0; nCurrBox < nBoxCount; ++nCurrBox )
+ {
+ long nRowSpan = pLine->GetTabBoxes()[nCurrBox]->getRowSpan();
+ long nAbsSpan = nRowSpan > 0 ? nRowSpan : -nRowSpan;
+ // Check if the last overlapped cell is above or below
+ // the critical area
+ if( nAbsSpan > nDistance )
+ {
+ if( nDiff > 0 )
+ {
+ if( nRowSpan > 0 )
+ nRowSpan += nDiff; // increment row span of master cell
+ else
+ {
+ nRowSpan -= nDiff; // increment row span of non-master cell
+ bGoOn = true;
+ }
+ }
+ else
+ {
+ if( nRowSpan > 0 )
+ { // A master cell
+ // end of row span behind the deleted area ..
+ if( nRowSpan - nDistance > -nDiff )
+ nRowSpan += nDiff;
+ else // .. or inside the deleted area
+ nRowSpan = nDistance + 1;
+ }
+ else
+ { // Same for a non-master cell
+ if( nRowSpan + nDistance < nDiff )
+ nRowSpan -= nDiff;
+ else
+ nRowSpan = -nDistance - 1;
+ bGoOn = true; // We have to continue
+ }
+ }
+ pLine->GetTabBoxes()[ nCurrBox ]->setRowSpan( nRowSpan );
+ }
+ }
+ ++nDistance;
+ if( nRowIdx )
+ --nRowIdx;
+ else
+ bGoOn = false; //robust
+ } while( bGoOn );
+}
+
+/** CollectBoxSelection(..) create a rectangulare selection based on the given SwPaM
+ and prepares the selected cells for merging
+*/
+
+SwBoxSelection* SwTable::CollectBoxSelection( const SwPaM& rPam ) const
+{
+ OSL_ENSURE( bNewModel, "Don't call me for old tables" );
+ if( !aLines.Count() )
+ return 0;
+ const SwNode* pStartNd = rPam.Start()->nNode.GetNode().FindTableBoxStartNode();
+ const SwNode* pEndNd = rPam.End()->nNode.GetNode().FindTableBoxStartNode();
+ if( !pStartNd || !pEndNd || pStartNd == pEndNd )
+ return 0;
+
+ sal_uInt16 nLines = aLines.Count();
+ sal_uInt16 nTop = 0, nBottom = 0;
+ long nMin = 0, nMax = 0;
+ int nFound = 0;
+ for( sal_uInt16 nRow = 0; nFound < 2 && nRow < nLines; ++nRow )
+ {
+ SwTableLine* pLine = aLines[nRow];
+ OSL_ENSURE( pLine, "Missing table line" );
+ sal_uInt16 nCols = pLine->GetTabBoxes().Count();
+ for( sal_uInt16 nCol = 0; nCol < nCols; ++nCol )
+ {
+ SwTableBox* pBox = pLine->GetTabBoxes()[nCol];
+ OSL_ENSURE( pBox, "Missing table box" );
+ if( nFound )
+ {
+ if( pBox->GetSttNd() == pEndNd )
+ {
+ nBottom = nRow;
+ lcl_CheckMinMax( nMin, nMax, *pLine, nCol, false );
+ ++nFound;
+ break;
+ }
+ }
+ else if( pBox->GetSttNd() == pStartNd )
+ {
+ nTop = nRow;
+ lcl_CheckMinMax( nMin, nMax, *pLine, nCol, true );
+ ++nFound;
+ }
+ }
+ }
+ if( nFound < 2 )
+ return 0;
+
+ bool bOkay = true;
+ long nMid = ( nMin + nMax ) / 2;
+
+ SwBoxSelection* pRet = new SwBoxSelection();
+ std::list< std::pair< SwTableBox*, long > > aNewWidthList;
+ sal_uInt16 nCheckBottom = nBottom;
+ long nLeftSpan = 0;
+ long nRightSpan = 0;
+ long nLeftSpanCnt = 0;
+ long nRightSpanCnt = 0;
+ for( sal_uInt16 nRow = nTop; nRow <= nBottom && bOkay; ++nRow )
+ {
+ SwTableLine* pLine = aLines[nRow];
+ OSL_ENSURE( pLine, "Missing table line" );
+ SwSelBoxes *pBoxes = new SwSelBoxes();
+ long nLeft = 0;
+ long nRight = 0;
+ long nRowSpan = 1;
+ sal_uInt16 nCount = pLine->GetTabBoxes().Count();
+ for( sal_uInt16 nCurrBox = 0; nCurrBox < nCount; ++nCurrBox )
+ {
+ SwTableBox* pBox = pLine->GetTabBoxes()[nCurrBox];
+ OSL_ENSURE( pBox, "Missing table box" );
+ nLeft = nRight;
+ nRight += pBox->GetFrmFmt()->GetFrmSize().GetWidth();
+ nRowSpan = pBox->getRowSpan();
+ if( nRight <= nMin )
+ {
+ if( nRight == nMin && nLeftSpanCnt )
+ bOkay = false;
+ continue;
+ }
+ SwTableBox* pInnerBox = 0;
+ SwTableBox* pLeftBox = 0;
+ SwTableBox* pRightBox = 0;
+ long nDiff = 0;
+ long nDiff2 = 0;
+ if( nLeft < nMin )
+ {
+ if( nRight >= nMid || nRight + nLeft >= nMin + nMin )
+ {
+ if( nCurrBox )
+ {
+ pBoxes->Insert( pBox );
+ pInnerBox = pBox;
+ pLeftBox = pLine->GetTabBoxes()[nCurrBox-1];
+ nDiff = nMin - nLeft;
+ if( nRight > nMax )
+ {
+ if( nCurrBox+1 < nCount )
+ {
+ pRightBox = pLine->GetTabBoxes()[nCurrBox+1];
+ nDiff2 = nRight - nMax;
+ }
+ else
+ bOkay = false;
+ }
+ else if( nRightSpanCnt && nRight == nMax )
+ bOkay = false;
+ }
+ else
+ bOkay = false;
+ }
+ else if( nCurrBox+1 < nCount )
+ {
+ pLeftBox = pBox;
+ pInnerBox = pLine->GetTabBoxes()[nCurrBox+1];
+ nDiff = nMin - nRight;
+ }
+ else
+ bOkay = false;
+ }
+ else if( nRight <= nMax )
+ {
+ pBoxes->Insert( pBox );
+ if( nRow == nTop && nRowSpan < 0 )
+ {
+ bOkay = false;
+ break;
+ }
+ if( nRowSpan > 1 && nRow + nRowSpan - 1 > nBottom )
+ nBottom = nRow + (sal_uInt16)nRowSpan - 1;
+ if( nRowSpan < -1 && nRow - nRowSpan - 1 > nBottom )
+ nBottom = (sal_uInt16)(nRow - nRowSpan - 1);
+ if( nRightSpanCnt && nRight == nMax )
+ bOkay = false;
+ }
+ else if( nLeft < nMax )
+ {
+ if( nLeft <= nMid || nRight + nLeft <= nMax )
+ {
+ if( nCurrBox+1 < nCount )
+ {
+ pBoxes->Insert( pBox );
+ pInnerBox = pBox;
+ pRightBox = pLine->GetTabBoxes()[nCurrBox+1];
+ nDiff = nRight - nMax;
+ }
+ else
+ bOkay = false;
+ }
+ else if( nCurrBox )
+ {
+ pRightBox = pBox;
+ pInnerBox = pLine->GetTabBoxes()[nCurrBox-1];
+ nDiff = nLeft - nMax;
+ }
+ else
+ bOkay = false;
+ }
+ else
+ break;
+ if( pInnerBox )
+ {
+ if( nRow == nBottom )
+ {
+ long nTmpSpan = pInnerBox->getRowSpan();
+ if( nTmpSpan > 1 )
+ nBottom += (sal_uInt16)nTmpSpan - 1;
+ else if( nTmpSpan < -1 )
+ nBottom = (sal_uInt16)( nBottom - nTmpSpan - 1 );
+ }
+ SwTableBox* pOuterBox = pLeftBox;
+ do
+ {
+ if( pOuterBox )
+ {
+ long nOutSpan = pOuterBox->getRowSpan();
+ if( nOutSpan != 1 )
+ {
+ sal_uInt16 nCheck = nRow;
+ if( nOutSpan < 0 )
+ {
+ const SwTableBox& rBox =
+ pOuterBox->FindStartOfRowSpan( *this, USHRT_MAX );
+ nOutSpan = rBox.getRowSpan();
+ const SwTableLine* pTmpL = rBox.GetUpper();
+ nCheck = GetTabLines().C40_GETPOS( SwTableLine, pTmpL );
+ if( nCheck < nTop )
+ bOkay = false;
+ if( pOuterBox == pLeftBox )
+ {
+ if( !nLeftSpanCnt || nMin - nDiff != nLeftSpan )
+ bOkay = false;
+ }
+ else
+ {
+ if( !nRightSpanCnt || nMax + nDiff != nRightSpan )
+ bOkay = false;
+ }
+ }
+ else
+ {
+ if( pOuterBox == pLeftBox )
+ {
+ if( nLeftSpanCnt )
+ bOkay = false;
+ nLeftSpan = nMin - nDiff;
+ nLeftSpanCnt = nOutSpan;
+ }
+ else
+ {
+ if( nRightSpanCnt )
+ bOkay = false;
+ nRightSpan = nMax + nDiff;
+ nRightSpanCnt = nOutSpan;
+ }
+ }
+ nCheck += (sal_uInt16)nOutSpan - 1;
+ if( nCheck > nCheckBottom )
+ nCheckBottom = nCheck;
+ }
+ else if( ( nLeftSpanCnt && pLeftBox == pOuterBox ) ||
+ ( nRightSpanCnt && pRightBox == pOuterBox ) )
+ bOkay = false;
+ std::pair< SwTableBox*, long > aTmp;
+ aTmp.first = pInnerBox;
+ aTmp.second = -nDiff;
+ aNewWidthList.push_back( aTmp );
+ aTmp.first = pOuterBox;
+ aTmp.second = nDiff;
+ aNewWidthList.push_back( aTmp );
+ }
+ pOuterBox = pOuterBox == pRightBox ? 0 : pRightBox;
+ if( nDiff2 )
+ nDiff = nDiff2;
+ } while( pOuterBox );
+ }
+ }
+ if( nLeftSpanCnt )
+ --nLeftSpanCnt;
+ if( nRightSpanCnt )
+ --nRightSpanCnt;
+ pRet->insertBoxes( pBoxes );
+ }
+ pRet->mnMergeWidth = nMax - nMin;
+ if( nCheckBottom > nBottom )
+ bOkay = false;
+ if( bOkay )
+ {
+ std::list< std::pair< SwTableBox*, long > >::iterator
+ pCurr = aNewWidthList.begin();
+ while( pCurr != aNewWidthList.end() )
+ {
+ SwFrmFmt* pFmt = pCurr->first->ClaimFrmFmt();
+ long nNewWidth = pFmt->GetFrmSize().GetWidth() + pCurr->second;
+ pFmt->SetFmtAttr( SwFmtFrmSize( ATT_VAR_SIZE, nNewWidth, 0 ) );
+ ++pCurr;
+ }
+ }
+ else
+ {
+ delete pRet;
+ pRet = 0;
+ }
+ return pRet;
+}
+
+/** lcl_InvalidateCellFrm(..) invalidates all layout representations of a given cell
+ to initiate a reformatting
+*/
+
+void lcl_InvalidateCellFrm( const SwTableBox& rBox )
+{
+ SwIterator<SwCellFrm,SwFmt> aIter( *rBox.GetFrmFmt() );
+ for( SwCellFrm* pCell = aIter.First(); pCell; pCell = aIter.Next() )
+ {
+ if( pCell->GetTabBox() == &rBox )
+ {
+ pCell->InvalidateSize();
+ SwFrm* pLower = pCell->GetLower();
+ if( pLower )
+ pLower->_InvalidateSize();
+ }
+ }
+}
+
+/** lcl_InsertPosition(..) evaluates the insert positions in every table line,
+ when a selection of cells is given and returns the average cell widths
+*/
+
+long lcl_InsertPosition( SwTable &rTable, std::vector<sal_uInt16>& rInsPos,
+ const SwSelBoxes& rBoxes, sal_Bool bBehind )
+{
+ sal_Int32 nAddWidth = 0;
+ long nCount = 0;
+ for( sal_uInt16 j = 0; j < rBoxes.Count(); ++j )
+ {
+ SwTableBox *pBox = rBoxes[j];
+ SwTableLine* pLine = pBox->GetUpper();
+ long nWidth = rBoxes[j]->GetFrmFmt()->GetFrmSize().GetWidth();
+ nAddWidth += nWidth;
+ sal_uInt16 nCurrBox = pLine->GetTabBoxes().C40_GETPOS(SwTableBox, pBox );
+ sal_uInt16 nCurrLine = rTable.GetTabLines().C40_GETPOS(SwTableLine, pLine );
+ OSL_ENSURE( nCurrLine != USHRT_MAX, "Time to say Good-Bye.." );
+ if( rInsPos[ nCurrLine ] == USHRT_MAX )
+ {
+ rInsPos[ nCurrLine ] = nCurrBox;
+ ++nCount;
+ }
+ else if( ( rInsPos[ nCurrLine ] > nCurrBox ) == !bBehind )
+ rInsPos[ nCurrLine ] = nCurrBox;
+ }
+ if( nCount )
+ nAddWidth /= nCount;
+ return nAddWidth;
+}
+
+/** SwTable::NewInsertCol(..) insert new column(s) into a table
+
+
+@param pDoc
+the document
+
+@param rBoxes
+the selected boxes
+
+@param nCnt
+the number of columns to insert
+
+@param bBehind
+insertion behind (true) or before (false) the selected boxes
+
+@return true, if any insertion has been done successfully
+
+*/
+
+sal_Bool SwTable::NewInsertCol( SwDoc* pDoc, const SwSelBoxes& rBoxes,
+ sal_uInt16 nCnt, sal_Bool bBehind )
+{
+ if( !aLines.Count() || !nCnt )
+ return sal_False;
+
+ CHECK_TABLE( *this )
+ long nNewBoxWidth = 0;
+ std::vector< sal_uInt16 > aInsPos( aLines.Count(), USHRT_MAX );
+ { // Calculation of the insert positions and the width of the new boxes
+ sal_uInt64 nTableWidth = 0;
+ for( sal_uInt16 i = 0; i < aLines[0]->GetTabBoxes().Count(); ++i )
+ nTableWidth += aLines[0]->GetTabBoxes()[i]->GetFrmFmt()->GetFrmSize().GetWidth();
+
+ // Fill the vector of insert positions and the (average) width to insert
+ sal_uInt64 nAddWidth = lcl_InsertPosition( *this, aInsPos, rBoxes, bBehind );
+
+ // Given is the (average) width of the selected boxes, if we would
+ // insert nCnt of columns the table would grow
+ // So we will shrink the table first, then insert the new boxes and
+ // get a table with the same width than before.
+ // But we will not shrink the table by the full already calculated value,
+ // we will reduce this value proportional to the old table width
+ nAddWidth *= nCnt; // we have to insert nCnt boxes per line
+ sal_uInt64 nResultingWidth = nAddWidth + nTableWidth;
+ if( !nResultingWidth )
+ return sal_False;
+ nAddWidth = (nAddWidth * nTableWidth) / nResultingWidth;
+ nNewBoxWidth = long( nAddWidth / nCnt ); // Rounding
+ nAddWidth = nNewBoxWidth * nCnt; // Rounding
+ if( !nAddWidth || nAddWidth >= nTableWidth )
+ return sal_False;
+ AdjustWidths( static_cast< long >(nTableWidth), static_cast< long >(nTableWidth - nAddWidth) );
+ }
+
+ _FndBox aFndBox( 0, 0 );
+ aFndBox.SetTableLines( rBoxes, *this );
+ aFndBox.DelFrms( *this );
+
+ SwTableNode* pTblNd = GetTableNode();
+ std::vector<SwTableBoxFmt*> aInsFormat( nCnt, 0 );
+ sal_uInt16 nLastLine = USHRT_MAX;
+ long nLastRowSpan = 1;
+
+ for( sal_uInt16 i = 0; i < aLines.Count(); ++i )
+ {
+ SwTableLine* pLine = aLines[ i ];
+ sal_uInt16 nInsPos = aInsPos[i];
+ OSL_ENSURE( nInsPos != USHRT_MAX, "Didn't found insert position" );
+ SwTableBox* pBox = pLine->GetTabBoxes()[ nInsPos ];
+ if( bBehind )
+ ++nInsPos;
+ SwTableBoxFmt* pBoxFrmFmt = (SwTableBoxFmt*)pBox->GetFrmFmt();
+ ::_InsTblBox( pDoc, pTblNd, pLine, pBoxFrmFmt, pBox, nInsPos, nCnt );
+ long nRowSpan = pBox->getRowSpan();
+ long nDiff = i - nLastLine;
+ bool bNewSpan = false;
+ if( nLastLine != USHRT_MAX && nDiff <= nLastRowSpan &&
+ nRowSpan != nDiff - nLastRowSpan )
+ {
+ bNewSpan = true;
+ while( nLastLine < i )
+ {
+ SwTableLine* pTmpLine = aLines[ nLastLine ];
+ sal_uInt16 nTmpPos = aInsPos[nLastLine];
+ if( bBehind )
+ ++nTmpPos;
+ for( sal_uInt16 j = 0; j < nCnt; ++j )
+ pTmpLine->GetTabBoxes()[nTmpPos+j]->setRowSpan( nDiff );
+ if( nDiff > 0 )
+ nDiff = -nDiff;
+ ++nDiff;
+ ++nLastLine;
+ }
+ }
+ if( nRowSpan > 0 )
+ bNewSpan = true;
+ if( bNewSpan )
+ {
+ nLastLine = i;
+ if( nRowSpan < 0 )
+ nLastRowSpan = -nRowSpan;
+ else
+ nLastRowSpan = nRowSpan;
+ }
+ const SvxBoxItem& aSelBoxItem = pBoxFrmFmt->GetBox();
+ SvxBoxItem* pNoRightBorder = 0;
+ if( aSelBoxItem.GetRight() )
+ {
+ pNoRightBorder = new SvxBoxItem( aSelBoxItem );
+ pNoRightBorder->SetLine( 0, BOX_LINE_RIGHT );
+ }
+ for( sal_uInt16 j = 0; j < nCnt; ++j )
+ {
+ SwTableBox *pCurrBox = pLine->GetTabBoxes()[nInsPos+j];
+ if( bNewSpan )
+ {
+ pCurrBox->setRowSpan( nLastRowSpan );
+ SwFrmFmt* pFrmFmt = pCurrBox->ClaimFrmFmt();
+ SwFmtFrmSize aFrmSz( pFrmFmt->GetFrmSize() );
+ aFrmSz.SetWidth( nNewBoxWidth );
+ pFrmFmt->SetFmtAttr( aFrmSz );
+ if( pNoRightBorder && ( !bBehind || j+1 < nCnt ) )
+ pFrmFmt->SetFmtAttr( *pNoRightBorder );
+ aInsFormat[j] = (SwTableBoxFmt*)pFrmFmt;
+ }
+ else
+ pCurrBox->ChgFrmFmt( aInsFormat[j] );
+ }
+ if( bBehind && pNoRightBorder )
+ {
+ SwFrmFmt* pFrmFmt = pBox->ClaimFrmFmt();
+ pFrmFmt->SetFmtAttr( *pNoRightBorder );
+ }
+ delete pNoRightBorder;
+ }
+
+ aFndBox.MakeFrms( *this );
+#if OSL_DEBUG_LEVEL > 1
+ {
+ const SwTableBoxes &rTabBoxes = aLines[0]->GetTabBoxes();
+ long nNewWidth = 0;
+ for( sal_uInt16 i = 0; i < rTabBoxes.Count(); ++i )
+ nNewWidth += rTabBoxes[i]->GetFrmFmt()->GetFrmSize().GetWidth();
+ OSL_ENSURE( nNewWidth > 0, "Very small" );
+ }
+#endif
+ CHECK_TABLE( *this )
+
+ return sal_True;
+}
+
+/** SwTable::PrepareMerge(..) some preparation for the coming Merge(..)
+
+For the old table model, ::GetMergeSel(..) is called only,
+for the new table model, PrepareMerge does the main work.
+It modifices all cells to merge (width, border, rowspan etc.) and collects
+the cells which have to be deleted by Merge(..) afterwards.
+If there are superfluous rows, these cells are put into the deletion list as well.
+
+@param rPam
+the selection to merge
+
+@param rBoxes
+should be empty at the beginning, at the end it is filled with boxes to delete.
+
+@param ppMergeBox
+will be set to the master cell box
+
+@param pUndo
+the undo object to record all changes
+can be Null, e.g. when called by Redo(..)
+
+@return
+
+*/
+
+bool SwTable::PrepareMerge( const SwPaM& rPam, SwSelBoxes& rBoxes,
+ SwSelBoxes& rMerged, SwTableBox** ppMergeBox, SwUndoTblMerge* pUndo )
+{
+ if( !bNewModel )
+ {
+ ::GetMergeSel( rPam, rBoxes, ppMergeBox, pUndo );
+ return rBoxes.Count() > 1;
+ }
+ CHECK_TABLE( *this )
+ // We have to assert a "rectangular" box selection before we start to merge
+ std::auto_ptr< SwBoxSelection > pSel( CollectBoxSelection( rPam ) );
+ if( !pSel.get() || pSel->isEmpty() )
+ return false;
+ // Now we should have a rectangle of boxes,
+ // i.e. contiguous cells in contiguous rows
+ bool bMerge = false; // will be set if any content is transferred from
+ // a "not already overlapped" cell into the new master cell.
+ SwTableBox *pMergeBox = (*pSel->aBoxes[0])[0]; // the master cell box
+ if( !pMergeBox )
+ return false;
+ (*ppMergeBox) = pMergeBox;
+ // The new master box will get the left and the top border of the top-left
+ // box of the selection and because the new master cell _is_ the top-left
+ // box, the left and right border does not need to be changed.
+ // The right and bottom border instead has to be derived from the right-
+ // bottom box of the selection. If this is a overlapped cell,
+ // the appropiate master box.
+ SwTableBox* pLastBox = 0; // the right-bottom (master) cell
+ SwDoc* pDoc = GetFrmFmt()->GetDoc();
+ SwPosition aInsPos( *pMergeBox->GetSttNd()->EndOfSectionNode() );
+ SwPaM aChkPam( aInsPos );
+ // The number of lines in the selection rectangle: nLineCount
+ const sal_uInt16 nLineCount = sal_uInt16(pSel->aBoxes.size());
+ // BTW: nLineCount is the rowspan of the new master cell
+ long nRowSpan = nLineCount;
+ // We will need the first and last line of the selection
+ // to check if there any superfluous row after merging
+ SwTableLine* pFirstLn = 0;
+ SwTableLine* pLastLn = 0;
+ // Iteration over the lines of the selection...
+ for( sal_uInt16 nCurrLine = 0; nCurrLine < nLineCount; ++nCurrLine )
+ {
+ // The selected boxes in the current line
+ const SwSelBoxes* pBoxes = pSel->aBoxes[ nCurrLine ];
+ sal_uInt16 nColCount = pBoxes->Count();
+ // Iteration over the selected cell in the current row
+ for( sal_uInt16 nCurrCol = 0; nCurrCol < nColCount; ++nCurrCol )
+ {
+ SwTableBox* pBox = (*pBoxes)[nCurrCol];
+ rMerged.Insert( pBox );
+ // Only the first selected cell in every row will be alive,
+ // the other will be deleted => put into rBoxes
+ if( nCurrCol )
+ rBoxes.Insert( pBox );
+ else
+ {
+ if( nCurrLine == 1 )
+ pFirstLn = pBox->GetUpper(); // we need this line later on
+ if( nCurrLine + 1 == nLineCount )
+ pLastLn = pBox->GetUpper(); // and this one, too.
+ }
+ // A box has to be merged if it's not the master box itself,
+ // but an already overlapped cell must not be merged as well.
+ bool bDoMerge = pBox != pMergeBox && pBox->getRowSpan() > 0;
+ // The last box has to be in the last "column" of the selection
+ // and it has to be a master cell
+ if( nCurrCol+1 == nColCount && pBox->getRowSpan() > 0 )
+ pLastBox = pBox;
+ if( bDoMerge )
+ {
+ bMerge = true;
+ // If the cell to merge contains only one empty paragraph,
+ // we do not transfer this paragraph.
+ if( !IsEmptyBox( *pBox, aChkPam ) )
+ {
+ SwNodeIndex& rInsPosNd = aInsPos.nNode;
+ SwPaM aPam( aInsPos );
+ aPam.GetPoint()->nNode.Assign( *pBox->GetSttNd()->EndOfSectionNode(), -1 );
+ SwCntntNode* pCNd = aPam.GetCntntNode();
+ sal_uInt16 nL = pCNd ? pCNd->Len() : 0;
+ aPam.GetPoint()->nContent.Assign( pCNd, nL );
+ SwNodeIndex aSttNdIdx( *pBox->GetSttNd(), 1 );
+ bool const bUndo = pDoc->GetIDocumentUndoRedo().DoesUndo();
+ if( pUndo )
+ {
+ pDoc->GetIDocumentUndoRedo().DoUndo(false);
+ }
+ pDoc->AppendTxtNode( *aPam.GetPoint() );
+ if( pUndo )
+ {
+ pDoc->GetIDocumentUndoRedo().DoUndo(bUndo);
+ }
+ SwNodeRange aRg( aSttNdIdx, aPam.GetPoint()->nNode );
+ if( pUndo )
+ pUndo->MoveBoxCntnt( pDoc, aRg, rInsPosNd );
+ else
+ {
+ pDoc->MoveNodeRange( aRg, rInsPosNd,
+ IDocumentContentOperations::DOC_NO_DELFRMS );
+ }
+ }
+ }
+ // Only the cell of the first selected column will stay alive
+ // and got a new row span
+ if( !nCurrCol )
+ pBox->setRowSpan( nRowSpan );
+ }
+ if( nRowSpan > 0 ) // the master cell is done, from now on we set
+ nRowSpan = -nRowSpan; // negative row spans
+ ++nRowSpan; // ... -3, -2, -1
+ }
+ if( bMerge )
+ {
+ // A row containing overlapped cells is superfluous,
+ // these cells can be put into rBoxes for deletion
+ _FindSuperfluousRows( rBoxes, pFirstLn, pLastLn );
+ // pNewFmt will be set to the new master box and the overlapped cells
+ SwFrmFmt* pNewFmt = pMergeBox->ClaimFrmFmt();
+ pNewFmt->SetFmtAttr( SwFmtFrmSize( ATT_VAR_SIZE, pSel->mnMergeWidth, 0 ) );
+ for( sal_uInt16 nCurrLine = 0; nCurrLine < nLineCount; ++nCurrLine )
+ {
+ const SwSelBoxes* pBoxes = pSel->aBoxes[ nCurrLine ];
+ sal_uInt16 nColCount = pBoxes->Count();
+ for( sal_uInt16 nCurrCol = 0; nCurrCol < nColCount; ++nCurrCol )
+ {
+ SwTableBox* pBox = (*pBoxes)[nCurrCol];
+ if( nCurrCol )
+ {
+ // Even this box will be deleted soon,
+ // we have to correct the width to avoid side effects
+ SwFrmFmt* pFmt = pBox->ClaimFrmFmt();
+ pFmt->SetFmtAttr( SwFmtFrmSize( ATT_VAR_SIZE, 0, 0 ) );
+ }
+ else
+ pBox->ChgFrmFmt( (SwTableBoxFmt*)pNewFmt );
+ }
+ }
+ if( pLastBox ) // Robust
+ {
+ // The new borders of the master cell...
+ SvxBoxItem aBox( pMergeBox->GetFrmFmt()->GetBox() );
+ bool bOld = aBox.GetRight() || aBox.GetBottom();
+ const SvxBoxItem& rBox = pLastBox->GetFrmFmt()->GetBox();
+ aBox.SetLine( rBox.GetRight(), BOX_LINE_RIGHT );
+ aBox.SetLine( rBox.GetBottom(), BOX_LINE_BOTTOM );
+ if( bOld || aBox.GetLeft() || aBox.GetTop() || aBox.GetRight() || aBox.GetBottom() )
+ (*ppMergeBox)->GetFrmFmt()->SetFmtAttr( aBox );
+ }
+
+ if( pUndo )
+ pUndo->AddNewBox( pMergeBox->GetSttIdx() );
+ }
+ return bMerge;
+}
+
+/** SwTable::_FindSuperfluousRows(..) is looking for superfluous rows, i.e. rows
+ containing overlapped cells only.
+*/
+
+void SwTable::_FindSuperfluousRows( SwSelBoxes& rBoxes,
+ SwTableLine* pFirstLn, SwTableLine* pLastLn )
+{
+ if( !pFirstLn || !pLastLn )
+ {
+ if( !rBoxes.Count() )
+ return;
+ pFirstLn = rBoxes[0]->GetUpper();
+ pLastLn = rBoxes[ rBoxes.Count() - 1 ]->GetUpper();
+ }
+ sal_uInt16 nFirstLn = GetTabLines().C40_GETPOS(SwTableLine, pFirstLn );
+ sal_uInt16 nLastLn = GetTabLines().C40_GETPOS(SwTableLine, pLastLn );
+ for( sal_uInt16 nRow = nFirstLn; nRow <= nLastLn; ++nRow )
+ {
+ SwTableLine* pLine = aLines[nRow];
+ OSL_ENSURE( pLine, "Missing table line" );
+ sal_uInt16 nCols = pLine->GetTabBoxes().Count();
+ bool bSuperfl = true;
+ for( sal_uInt16 nCol = 0; nCol < nCols; ++nCol )
+ {
+ SwTableBox *pBox = pLine->GetTabBoxes()[nCol];
+ if( pBox->getRowSpan() > 0 &&
+ USHRT_MAX == rBoxes.GetPos( pBox ) )
+ {
+ bSuperfl = false;
+ break;
+ }
+ }
+ if( bSuperfl )
+ {
+ for( sal_uInt16 nCol = 0; nCol < nCols; ++nCol )
+ {
+ SwTableBox* pBox = pLine->GetTabBoxes()[nCol];
+ rBoxes.Insert( pBox );
+ }
+ }
+ }
+}
+
+/** SwTableBox::FindStartOfRowSpan(..) retruns the "master" cell, the cell which
+ overlaps the given cell, it maybe the cell itself.
+*/
+
+SwTableBox& SwTableBox::FindStartOfRowSpan( const SwTable& rTable, sal_uInt16 nMaxStep )
+{
+ if( getRowSpan() > 0 || !nMaxStep )
+ return *this;
+
+ long nLeftBorder = lcl_Box2LeftBorder( *this );
+ SwTableBox* pBox = this;
+ const SwTableLine* pMyUpper = GetUpper();
+ sal_uInt16 nLine = rTable.GetTabLines().C40_GETPOS(SwTableLine, pMyUpper );
+ if( nLine && nLine < rTable.GetTabLines().Count() )
+ {
+ SwTableBox* pNext;
+ do
+ {
+ pNext = lcl_LeftBorder2Box( nLeftBorder, rTable.GetTabLines()[--nLine] );
+ if( pNext )
+ pBox = pNext;
+ } while( nLine && --nMaxStep && pNext && pBox->getRowSpan() < 1 );
+ }
+
+ return *pBox;
+}
+
+/** SwTableBox::FindEndOfRowSpan(..) returns the last overlapped cell if there is
+ any. Otherwise the cell itself will returned.
+*/
+
+SwTableBox& SwTableBox::FindEndOfRowSpan( const SwTable& rTable, sal_uInt16 nMaxStep )
+{
+ long nAbsSpan = getRowSpan();
+ if( nAbsSpan < 0 )
+ nAbsSpan = -nAbsSpan;
+ if( nAbsSpan == 1 || !nMaxStep )
+ return *this;
+
+ if( nMaxStep > --nAbsSpan )
+ nMaxStep = (sal_uInt16)nAbsSpan;
+ const SwTableLine* pMyUpper = GetUpper();
+ sal_uInt16 nLine = rTable.GetTabLines().C40_GETPOS(SwTableLine, pMyUpper );
+ nMaxStep = nLine + nMaxStep;
+ if( nMaxStep >= rTable.GetTabLines().Count() )
+ nMaxStep = rTable.GetTabLines().Count() - 1;
+ long nLeftBorder = lcl_Box2LeftBorder( *this );
+ SwTableBox* pBox =
+ lcl_LeftBorder2Box( nLeftBorder, rTable.GetTabLines()[ nMaxStep ] );
+ if ( !pBox )
+ pBox = this;
+
+ return *pBox;
+}
+
+/** lcl_getAllMergedBoxes(..) collects all overlapped boxes to a given (master) box
+*/
+
+void lcl_getAllMergedBoxes( const SwTable& rTable, SwSelBoxes& rBoxes, SwTableBox& rBox )
+{
+ SwTableBox* pBox = &rBox;
+ OSL_ENSURE( pBox == &rBox.FindStartOfRowSpan( rTable, USHRT_MAX ), "Not a master box" );
+ rBoxes.Insert( pBox );
+ if( pBox->getRowSpan() == 1 )
+ return;
+ const SwTableLine* pMyUpper = pBox->GetUpper();
+ sal_uInt16 nLine = rTable.GetTabLines().C40_GETPOS(SwTableLine, pMyUpper );
+ long nLeftBorder = lcl_Box2LeftBorder( *pBox );
+ sal_uInt16 nCount = rTable.GetTabLines().Count();
+ while( ++nLine < nCount && pBox && pBox->getRowSpan() != -1 )
+ {
+ pBox = lcl_LeftBorder2Box( nLeftBorder, rTable.GetTabLines()[nLine] );
+ if( pBox )
+ rBoxes.Insert( pBox );
+ };
+}
+
+/** lcl_UnMerge(..) manipulates the row span attribute of a given master cell
+ and its overlapped cells to split them into several pieces.
+*/
+
+void lcl_UnMerge( const SwTable& rTable, SwTableBox& rBox, sal_uInt16 nCnt,
+ sal_Bool bSameHeight )
+{
+ SwSelBoxes aBoxes;
+ lcl_getAllMergedBoxes( rTable, aBoxes, rBox );
+ sal_uInt16 nCount = aBoxes.Count();
+ if( nCount < 2 )
+ return;
+ if( nCnt > nCount )
+ nCnt = nCount;
+ sal_uInt16 *pSplitIdx = new sal_uInt16[ nCnt ];
+ if( bSameHeight )
+ {
+ SwTwips *pHeights = new SwTwips[ nCount ];
+ SwTwips nHeight = 0;
+ for( sal_uInt16 i = 0; i < nCount; ++i )
+ {
+ SwTableLine* pLine = aBoxes[ i ]->GetUpper();
+ SwFrmFmt *pRowFmt = pLine->GetFrmFmt();
+ pHeights[ i ] = pRowFmt->GetFrmSize().GetHeight();
+ nHeight += pHeights[ i ];
+ }
+ SwTwips nSumH = 0;
+ sal_uInt16 nIdx = 0;
+ for( sal_uInt16 i = 1; i <= nCnt; ++i )
+ {
+ SwTwips nSplit = ( i * nHeight ) / nCnt;
+ while( nSumH < nSplit && nIdx < nCount )
+ nSumH += pHeights[ nIdx++ ];
+ pSplitIdx[ i - 1 ] = nIdx;
+ }
+ delete[] pHeights;
+ }
+ else
+ {
+ for( long i = 1; i <= nCnt; ++i )
+ pSplitIdx[ i - 1 ] = (sal_uInt16)( ( i * nCount ) / nCnt );
+ }
+ sal_uInt16 nIdx = 0;
+ for( long i = 0; i < nCnt; ++i )
+ {
+ sal_uInt16 nNextIdx = pSplitIdx[ i ];
+ aBoxes[ nIdx ]->setRowSpan( nNextIdx - nIdx );
+ lcl_InvalidateCellFrm( *aBoxes[ nIdx ] );
+ while( ++nIdx < nNextIdx )
+ aBoxes[ nIdx ]->setRowSpan( nIdx - nNextIdx );
+ }
+ delete[] pSplitIdx;
+}
+
+/** lcl_FillSelBoxes(..) puts all boxes of a given line into the selection structure
+*/
+
+void lcl_FillSelBoxes( SwSelBoxes &rBoxes, SwTableLine &rLine )
+{
+ sal_uInt16 nBoxCount = rLine.GetTabBoxes().Count();
+ sal_uInt16 nCurrBox;
+ for( nCurrBox = 0; nCurrBox < nBoxCount; ++nCurrBox )
+ rBoxes.Insert( rLine.GetTabBoxes()[nCurrBox] );
+}
+
+/** SwTable::InsertSpannedRow(..) inserts "superfluous" rows, i.e. rows containig
+ overlapped cells only. This is a preparation for an upcoming split.
+*/
+
+void SwTable::InsertSpannedRow( SwDoc* pDoc, sal_uInt16 nRowIdx, sal_uInt16 nCnt )
+{
+ CHECK_TABLE( *this )
+ OSL_ENSURE( nCnt && nRowIdx < GetTabLines().Count(), "Wrong call of InsertSpannedRow" );
+ SwSelBoxes aBoxes;
+ SwTableLine& rLine = *GetTabLines()[ nRowIdx ];
+ lcl_FillSelBoxes( aBoxes, rLine );
+ SwFmtFrmSize aFSz( rLine.GetFrmFmt()->GetFrmSize() );
+ if( ATT_VAR_SIZE != aFSz.GetHeightSizeType() )
+ {
+ SwFrmFmt* pFrmFmt = rLine.ClaimFrmFmt();
+ long nNewHeight = aFSz.GetHeight() / ( nCnt + 1 );
+ if( !nNewHeight )
+ ++nNewHeight;
+ aFSz.SetHeight( nNewHeight );
+ pFrmFmt->SetFmtAttr( aFSz );
+ }
+ _InsertRow( pDoc, aBoxes, nCnt, sal_True );
+ sal_uInt16 nBoxCount = rLine.GetTabBoxes().Count();
+ for( sal_uInt16 n = 0; n < nCnt; ++n )
+ {
+ SwTableLine *pNewLine = GetTabLines()[ nRowIdx + nCnt - n ];
+ for( sal_uInt16 nCurrBox = 0; nCurrBox < nBoxCount; ++nCurrBox )
+ {
+ long nRowSpan = rLine.GetTabBoxes()[nCurrBox]->getRowSpan();
+ if( nRowSpan > 0 )
+ nRowSpan = - nRowSpan;
+ pNewLine->GetTabBoxes()[ nCurrBox ]->setRowSpan( nRowSpan - n );
+ }
+ }
+ lcl_ChangeRowSpan( *this, nCnt, nRowIdx, false );
+ CHECK_TABLE( *this )
+}
+
+typedef std::pair< sal_uInt16, sal_uInt16 > SwLineOffset;
+typedef std::list< SwLineOffset > SwLineOffsetArray;
+
+/******************************************************************************
+When a couple of table boxes has to be split,
+lcl_SophisticatedFillLineIndices delivers the information where and how many
+rows have to be inserted.
+Input
+ rTable: the table to manipulate
+ rBoxes: an array of boxes to split
+ nCnt: how many parts are wanted
+Output
+ rArr: a list of pairs ( line index, number of lines to insert )
+
+******************************************************************************/
+
+void lcl_SophisticatedFillLineIndices( SwLineOffsetArray &rArr,
+ const SwTable& rTable, const SwSelBoxes& rBoxes, sal_uInt16 nCnt )
+{
+ std::list< SwLineOffset > aBoxes;
+ SwLineOffset aLnOfs( USHRT_MAX, USHRT_MAX );
+ for( sal_uInt16 i = 0; i < rBoxes.Count(); ++i )
+ { // Collect all end line indices and the row spans
+ const SwTableBox &rBox = rBoxes[ i ]->FindStartOfRowSpan( rTable );
+ OSL_ENSURE( rBox.getRowSpan() > 0, "Didn't I say 'StartOfRowSpan' ??" );
+ if( nCnt > rBox.getRowSpan() )
+ {
+ const SwTableLine *pLine = rBox.GetUpper();
+ const sal_uInt16 nEnd = sal_uInt16( rBox.getRowSpan() +
+ rTable.GetTabLines().C40_GETPOS( SwTableLine, pLine ) );
+ // The next if statement is a small optimization
+ if( aLnOfs.first != nEnd || aLnOfs.second != rBox.getRowSpan() )
+ {
+ aLnOfs.first = nEnd; // ok, this is the line behind the box
+ aLnOfs.second = sal_uInt16( rBox.getRowSpan() ); // the row span
+ aBoxes.insert( aBoxes.end(), aLnOfs );
+ }
+ }
+ }
+ // As I said, I noted the line index _behind_ the last line of the boxes
+ // in the resulting array the index has to be _on_ the line
+ // nSum is to evaluate the wished value
+ sal_uInt16 nSum = 1;
+ while( aBoxes.size() )
+ {
+ // I. step:
+ // Looking for the "smallest" line end with the smallest row span
+ std::list< SwLineOffset >::iterator pCurr = aBoxes.begin();
+ aLnOfs = *pCurr; // the line end and row span of the first box
+ while( ++pCurr != aBoxes.end() )
+ {
+ if( aLnOfs.first > pCurr->first )
+ { // Found a smaller line end
+ aLnOfs.first = pCurr->first;
+ aLnOfs.second = pCurr->second; // row span
+ }
+ else if( aLnOfs.first == pCurr->first &&
+ aLnOfs.second < pCurr->second )
+ aLnOfs.second = pCurr->second; // Found a smaller row span
+ }
+ OSL_ENSURE( aLnOfs.second < nCnt, "Clean-up failed" );
+ aLnOfs.second = nCnt - aLnOfs.second; // the number of rows to insert
+ rArr.insert( rArr.end(),
+ SwLineOffset( aLnOfs.first - nSum, aLnOfs.second ) );
+ // the correction has to be incremented because in the following
+ // loops the line ends were manipulated
+ nSum = nSum + aLnOfs.second;
+
+ pCurr = aBoxes.begin();
+ while( pCurr != aBoxes.end() )
+ {
+ if( pCurr->first == aLnOfs.first )
+ { // These boxes can be removed because the last insertion
+ // of rows will expand their row span above the needed value
+ std::list< SwLineOffset >::iterator pDel = pCurr;
+ ++pCurr;
+ aBoxes.erase( pDel );
+ }
+ else
+ {
+ bool bBefore = ( pCurr->first - pCurr->second < aLnOfs.first );
+ // Manipulation of the end line indices as if the rows are
+ // already inserted
+ pCurr->first = pCurr->first + aLnOfs.second;
+ if( bBefore )
+ { // If the insertion is inside the box,
+ // its row span has to be incremented
+ pCurr->second = pCurr->second + aLnOfs.second;
+ if( pCurr->second >= nCnt )
+ { // if the row span is bigger than the split factor
+ // this box is done
+ std::list< SwLineOffset >::iterator pDel = pCurr;
+ ++pCurr;
+ aBoxes.erase( pDel );
+ }
+ else
+ ++pCurr;
+ }
+ else
+ ++pCurr;
+ }
+ }
+ }
+}
+
+typedef std::set< SwTwips > SwSplitLines;
+
+/** lcl_CalculateSplitLineHeights(..) delivers all y-positions where table rows have
+ to be splitted to fulfill the requested "split same height"
+*/
+
+sal_uInt16 lcl_CalculateSplitLineHeights( SwSplitLines &rCurr, SwSplitLines &rNew,
+ const SwTable& rTable, const SwSelBoxes& rBoxes, sal_uInt16 nCnt )
+{
+ if( nCnt < 2 )
+ return 0;
+ std::list< SwLineOffset > aBoxes;
+ SwLineOffset aLnOfs( USHRT_MAX, USHRT_MAX );
+ sal_uInt16 nFirst = USHRT_MAX; // becomes the index of the first line
+ sal_uInt16 nLast = 0; // becomes the index of the last line of the splitting
+ for( sal_uInt16 i = 0; i < rBoxes.Count(); ++i )
+ { // Collect all pairs (start+end) of line indices to split
+ const SwTableBox &rBox = rBoxes[ i ]->FindStartOfRowSpan( rTable );
+ OSL_ENSURE( rBox.getRowSpan() > 0, "Didn't I say 'StartOfRowSpan' ??" );
+ const SwTableLine *pLine = rBox.GetUpper();
+ const sal_uInt16 nStart = rTable.GetTabLines().C40_GETPOS( SwTableLine, pLine );
+ const sal_uInt16 nEnd = sal_uInt16( rBox.getRowSpan() + nStart - 1 );
+ // The next if statement is a small optimization
+ if( aLnOfs.first != nStart || aLnOfs.second != nEnd )
+ {
+ aLnOfs.first = nStart;
+ aLnOfs.second = nEnd;
+ aBoxes.insert( aBoxes.end(), aLnOfs );
+ if( nStart < nFirst )
+ nFirst = nStart;
+ if( nEnd > nLast )
+ nLast = nEnd;
+ }
+ }
+
+ if( aBoxes.empty() )
+ return 0;
+ SwTwips nHeight = 0;
+ SwTwips* pLines = new SwTwips[ nLast + 1 - nFirst ];
+ for( sal_uInt16 i = nFirst; i <= nLast; ++i )
+ {
+ bool bLayoutAvailable = false;
+ nHeight += rTable.GetTabLines()[ i ]->GetTableLineHeight( bLayoutAvailable );
+ rCurr.insert( rCurr.end(), nHeight );
+ pLines[ i - nFirst ] = nHeight;
+ }
+ std::list< SwLineOffset >::iterator pSplit = aBoxes.begin();
+ while( pSplit != aBoxes.end() )
+ {
+ SwTwips nBase = pSplit->first <= nFirst ? 0 :
+ pLines[ pSplit->first - nFirst - 1 ];
+ SwTwips nDiff = pLines[ pSplit->second - nFirst ] - nBase;
+ for( sal_uInt16 i = 1; i < nCnt; ++i )
+ {
+ SwTwips nSplit = nBase + ( i * nDiff ) / nCnt;
+ rNew.insert( nSplit );
+ }
+ ++pSplit;
+ }
+ delete[] pLines;
+ return nFirst;
+}
+
+/** lcl_LineIndex(..) delivers the line index of the line behind or above
+ the box selection.
+*/
+
+sal_uInt16 lcl_LineIndex( const SwTable& rTable, const SwSelBoxes& rBoxes,
+ bool bBehind )
+{
+ sal_uInt16 nDirect = USHRT_MAX;
+ sal_uInt16 nSpan = USHRT_MAX;
+ for( sal_uInt16 i = 0; i < rBoxes.Count(); ++i )
+ {
+ SwTableBox *pBox = rBoxes[i];
+ const SwTableLine* pLine = rBoxes[i]->GetUpper();
+ sal_uInt16 nPos = rTable.GetTabLines().C40_GETPOS( SwTableLine, pLine );
+ if( USHRT_MAX != nPos )
+ {
+ if( bBehind )
+ {
+ if( nPos > nDirect || nDirect == USHRT_MAX )
+ nDirect = nPos;
+ long nRowSpan = pBox->getRowSpan();
+ if( nRowSpan < 2 )
+ nSpan = 0;
+ else if( nSpan )
+ {
+ sal_uInt16 nEndOfRowSpan = (sal_uInt16)(nPos + nRowSpan - 1);
+ if( nEndOfRowSpan > nSpan || nSpan == USHRT_MAX )
+ nSpan = nEndOfRowSpan;
+ }
+ }
+ else if( nPos < nDirect )
+ nDirect = nPos;
+ }
+ }
+ if( nSpan && nSpan < USHRT_MAX )
+ return nSpan;
+ return nDirect;
+}
+
+/** SwTable::NewSplitRow(..) splits all selected boxes horizontally.
+*/
+
+sal_Bool SwTable::NewSplitRow( SwDoc* pDoc, const SwSelBoxes& rBoxes, sal_uInt16 nCnt,
+ sal_Bool bSameHeight )
+{
+ CHECK_TABLE( *this )
+ ++nCnt;
+ _FndBox aFndBox( 0, 0 );
+ aFndBox.SetTableLines( rBoxes, *this );
+
+ if( bSameHeight && pDoc->GetCurrentViewShell() ) //swmod 071108//swmod 071225
+ {
+ SwSplitLines aRowLines;
+ SwSplitLines aSplitLines;
+ sal_uInt16 nFirst = lcl_CalculateSplitLineHeights( aRowLines, aSplitLines,
+ *this, rBoxes, nCnt );
+ aFndBox.DelFrms( *this );
+ SwTwips nLast = 0;
+ SwSplitLines::iterator pSplit = aSplitLines.begin();
+ SwSplitLines::iterator pCurr = aRowLines.begin();
+ while( pCurr != aRowLines.end() )
+ {
+ while( pSplit != aSplitLines.end() && *pSplit < *pCurr )
+ {
+ InsertSpannedRow( pDoc, nFirst, 1 );
+ SwTableLine* pRow = GetTabLines()[ nFirst ];
+ SwFrmFmt* pRowFmt = pRow->ClaimFrmFmt();
+ SwFmtFrmSize aFSz( pRowFmt->GetFrmSize() );
+ aFSz.SetHeightSizeType( ATT_MIN_SIZE );
+ aFSz.SetHeight( *pSplit - nLast );
+ pRowFmt->SetFmtAttr( aFSz );
+ nLast = *pSplit;
+ ++pSplit;
+ ++nFirst;
+ }
+ if( pSplit != aSplitLines.end() && *pCurr == *pSplit )
+ ++pSplit;
+ SwTableLine* pRow = GetTabLines()[ nFirst ];
+ SwFrmFmt* pRowFmt = pRow->ClaimFrmFmt();
+ SwFmtFrmSize aFSz( pRowFmt->GetFrmSize() );
+ aFSz.SetHeightSizeType( ATT_MIN_SIZE );
+ aFSz.SetHeight( *pCurr - nLast );
+ pRowFmt->SetFmtAttr( aFSz );
+ nLast = *pCurr;
+ ++pCurr;
+ ++nFirst;
+ }
+ }
+ else
+ {
+ aFndBox.DelFrms( *this );
+ bSameHeight = sal_False;
+ }
+ if( !bSameHeight )
+ {
+ SwLineOffsetArray aLineOffs;
+ lcl_SophisticatedFillLineIndices( aLineOffs, *this, rBoxes, nCnt );
+ SwLineOffsetArray::reverse_iterator pCurr( aLineOffs.rbegin() );
+ while( pCurr != aLineOffs.rend() )
+ {
+ InsertSpannedRow( pDoc, pCurr->first, pCurr->second );
+ ++pCurr;
+ }
+ }
+
+ std::set< sal_uInt16> aIndices;
+ for( sal_uInt16 i = 0; i < rBoxes.Count(); ++i )
+ {
+ OSL_ENSURE( rBoxes[i]->getRowSpan() != 1, "Forgot to split?" );
+ if( rBoxes[i]->getRowSpan() > 1 )
+ aIndices.insert( i );
+ }
+
+ std::set< sal_uInt16 >::iterator pCurrBox = aIndices.begin();
+ while( pCurrBox != aIndices.end() )
+ lcl_UnMerge( *this, *rBoxes[*pCurrBox++], nCnt, bSameHeight );
+
+ CHECK_TABLE( *this )
+ //Layout updaten
+ aFndBox.MakeFrms( *this );
+
+ return sal_True;
+}
+
+/** SwTable::InsertRow(..) inserts one or more rows before or behind the selected
+ boxes.
+*/
+
+sal_Bool SwTable::InsertRow( SwDoc* pDoc, const SwSelBoxes& rBoxes,
+ sal_uInt16 nCnt, sal_Bool bBehind )
+{
+ bool bRet = false;
+ if( IsNewModel() )
+ {
+ CHECK_TABLE( *this )
+ sal_uInt16 nRowIdx = lcl_LineIndex( *this, rBoxes, bBehind );
+ if( nRowIdx < USHRT_MAX )
+ {
+ _FndBox aFndBox( 0, 0 );
+ aFndBox.SetTableLines( rBoxes, *this );
+ aFndBox.DelFrms( *this );
+
+ bRet = true;
+ SwTableLine *pLine = GetTabLines()[ nRowIdx ];
+ SwSelBoxes aLineBoxes;
+ lcl_FillSelBoxes( aLineBoxes, *pLine );
+ _InsertRow( pDoc, aLineBoxes, nCnt, bBehind );
+ sal_uInt16 nBoxCount = pLine->GetTabBoxes().Count();
+ sal_uInt16 nOfs = bBehind ? 0 : 1;
+ for( sal_uInt16 n = 0; n < nCnt; ++n )
+ {
+ SwTableLine *pNewLine = GetTabLines()[ nRowIdx+nCnt-n-nOfs];
+ for( sal_uInt16 nCurrBox = 0; nCurrBox < nBoxCount; ++nCurrBox )
+ {
+ long nRowSpan = pLine->GetTabBoxes()[nCurrBox]->getRowSpan();
+ if( bBehind )
+ {
+ if( nRowSpan == 1 || nRowSpan == -1 )
+ nRowSpan = n + 1;
+ else if( nRowSpan > 1 )
+ nRowSpan = - nRowSpan;
+ }
+ else
+ {
+ if( nRowSpan > 0 )
+ nRowSpan = n + 1;
+ else
+ --nRowSpan;
+ }
+ pNewLine->GetTabBoxes()[ nCurrBox ]->setRowSpan( nRowSpan - n );
+ }
+ }
+ if( bBehind )
+ ++nRowIdx;
+ if( nRowIdx )
+ lcl_ChangeRowSpan( *this, nCnt, --nRowIdx, true );
+ //Layout update
+ aFndBox.MakeFrms( *this );
+ }
+ CHECK_TABLE( *this )
+ }
+ else
+ bRet = _InsertRow( pDoc, rBoxes, nCnt, bBehind );
+ return bRet;
+}
+
+/** SwTable::PrepareDelBoxes(..) adjusts the row span attributes for an upcoming
+ deletion of table cells and invalidates the layout of these cells.
+*/
+
+void SwTable::PrepareDelBoxes( const SwSelBoxes& rBoxes )
+{
+ if( IsNewModel() )
+ {
+ for( sal_uInt16 i = 0; i < rBoxes.Count(); ++i )
+ {
+ SwTableBox* pBox = rBoxes[i];
+ long nRowSpan = pBox->getRowSpan();
+ if( nRowSpan != 1 && pBox->GetFrmFmt()->GetFrmSize().GetWidth() )
+ {
+ long nLeft = lcl_Box2LeftBorder( *pBox );
+ SwTableLine *pLine = pBox->GetUpper();
+ sal_uInt16 nLinePos = GetTabLines().C40_GETPOS(SwTableLine, pLine);
+ OSL_ENSURE( nLinePos < USHRT_MAX, "Box/table mismatch" );
+ if( nRowSpan > 1 )
+ {
+ if( ++nLinePos < GetTabLines().Count() )
+ {
+ pLine = GetTabLines()[ nLinePos ];
+ pBox = lcl_LeftBorder2Box( nLeft, pLine );
+ OSL_ENSURE( pBox, "RowSpan irritation I" );
+ if( pBox )
+ pBox->setRowSpan( --nRowSpan );
+ }
+ }
+ else if( nLinePos > 0 )
+ {
+ do
+ {
+ pLine = GetTabLines()[ --nLinePos ];
+ pBox = lcl_LeftBorder2Box( nLeft, pLine );
+ OSL_ENSURE( pBox, "RowSpan irritation II" );
+ if( pBox )
+ {
+ nRowSpan = pBox->getRowSpan();
+ if( nRowSpan > 1 )
+ {
+ lcl_InvalidateCellFrm( *pBox );
+ --nRowSpan;
+ }
+ else
+ ++nRowSpan;
+ pBox->setRowSpan( nRowSpan );
+ }
+ else
+ nRowSpan = 1;
+ }
+ while( nRowSpan < 0 && nLinePos > 0 );
+ }
+ }
+ }
+ }
+}
+
+/** lcl_SearchSelBox(..) adds cells of a given table row to the selection structure
+ if it overlaps with the given x-position range
+*/
+
+void lcl_SearchSelBox( const SwTable &rTable, SwSelBoxes& rBoxes, long nMin, long nMax,
+ SwTableLine& rLine, bool bChkProtected, bool bColumn )
+{
+ long nLeft = 0;
+ long nRight = 0;
+ long nMid = ( nMax + nMin )/ 2;
+ sal_uInt16 nCount = rLine.GetTabBoxes().Count();
+ for( sal_uInt16 nCurrBox = 0; nCurrBox < nCount; ++nCurrBox )
+ {
+ SwTableBox* pBox = rLine.GetTabBoxes()[nCurrBox];
+ OSL_ENSURE( pBox, "Missing table box" );
+ long nWidth = pBox->GetFrmFmt()->GetFrmSize().GetWidth();
+ nRight += nWidth;
+ if( nRight > nMin )
+ {
+ bool bAdd = false;
+ if( nRight <= nMax )
+ bAdd = nLeft >= nMin || nRight >= nMid ||
+ nRight - nMin > nMin - nLeft;
+ else
+ bAdd = nLeft <= nMid || nRight - nMax < nMax - nLeft;
+ long nRowSpan = pBox->getRowSpan();
+ if( bAdd &&
+ ( !bChkProtected ||
+ !pBox->GetFrmFmt()->GetProtect().IsCntntProtected() ) )
+ {
+ sal_uInt16 nOldCnt = rBoxes.Count();
+ rBoxes.Insert( pBox );
+ if( bColumn && nRowSpan != 1 && nOldCnt < rBoxes.Count() )
+ {
+ SwTableBox *pMasterBox = pBox->getRowSpan() > 0 ? pBox
+ : &pBox->FindStartOfRowSpan( rTable, USHRT_MAX );
+ lcl_getAllMergedBoxes( rTable, rBoxes, *pMasterBox );
+ }
+ }
+ }
+ if( nRight >= nMax )
+ break;
+ nLeft = nRight;
+ }
+}
+
+/** void SwTable::CreateSelection(..) fills the selection structure with table cells
+ for a given SwPaM, ie. start and end position inside a table
+*/
+
+void SwTable::CreateSelection( const SwPaM& rPam, SwSelBoxes& rBoxes,
+ const SearchType eSearch, bool bChkProtected ) const
+{
+ OSL_ENSURE( bNewModel, "Don't call me for old tables" );
+ if( !aLines.Count() )
+ return;
+ const SwNode* pStartNd = rPam.GetPoint()->nNode.GetNode().FindTableBoxStartNode();
+ const SwNode* pEndNd = rPam.GetMark()->nNode.GetNode().FindTableBoxStartNode();
+ if( !pStartNd || !pEndNd )
+ return;
+ CreateSelection( pStartNd, pEndNd, rBoxes, eSearch, bChkProtected );
+}
+
+/** void SwTable::CreateSelection(..) fills the selection structure with table cells
+ for given start and end nodes inside a table
+*/
+void SwTable::CreateSelection( const SwNode* pStartNd, const SwNode* pEndNd,
+ SwSelBoxes& rBoxes, const SearchType eSearch, bool bChkProtected ) const
+{
+ // SwSelBoxes aKeepBoxes;
+ if( rBoxes.Count() )
+ {
+ // aKeepBoxes.Insert( &rBoxes );
+ rBoxes.Remove( sal_uInt16(0), rBoxes.Count() );
+ }
+ // Looking for start and end of the selection given by SwNode-pointer
+ sal_uInt16 nLines = aLines.Count();
+ // nTop becomes the line number of the upper box
+ // nBottom becomes the line number of the lower box
+ sal_uInt16 nTop = 0, nBottom = 0;
+ // nUpperMin becomes the left border value of the upper box
+ // nUpperMax becomes the right border of the upper box
+ // nLowerMin and nLowerMax the borders of the lower box
+ long nUpperMin = 0, nUpperMax = 0;
+ long nLowerMin = 0, nLowerMax = 0;
+ // nFound will incremented if a box is found
+ // 0 => no box found; 1 => the upper box has been found; 2 => both found
+ int nFound = 0;
+ for( sal_uInt16 nRow = 0; nFound < 2 && nRow < nLines; ++nRow )
+ {
+ SwTableLine* pLine = aLines[nRow];
+ OSL_ENSURE( pLine, "Missing table line" );
+ sal_uInt16 nCols = pLine->GetTabBoxes().Count();
+ for( sal_uInt16 nCol = 0; nCol < nCols; ++nCol )
+ {
+ SwTableBox* pBox = pLine->GetTabBoxes()[nCol];
+ OSL_ENSURE( pBox, "Missing table box" );
+ if( pBox->GetSttNd() == pEndNd || pBox->GetSttNd() == pStartNd )
+ {
+ if( !bChkProtected ||
+ !pBox->GetFrmFmt()->GetProtect().IsCntntProtected() )
+ rBoxes.Insert( pBox );
+ if( nFound )
+ {
+ nBottom = nRow;
+ lcl_CheckMinMax( nLowerMin, nLowerMax, *pLine, nCol, true );
+ ++nFound;
+ break;
+ }
+ else
+ {
+ nTop = nRow;
+ lcl_CheckMinMax( nUpperMin, nUpperMax, *pLine, nCol, true );
+ ++nFound;
+ // If start and end node are identical, we're nearly done..
+ if( pEndNd == pStartNd )
+ {
+ nBottom = nTop;
+ nLowerMin = nUpperMin;
+ nLowerMax = nUpperMax;
+ ++nFound;
+ }
+ }
+ }
+ }
+ }
+ if( nFound < 2 )
+ return; // At least one node was not a part of the given table
+ if( eSearch == SEARCH_ROW )
+ {
+ // Selection of a row is quiet easy:
+ // every (unprotected) box between start and end line
+ // with a positive row span will be collected
+ for( sal_uInt16 nRow = nTop; nRow <= nBottom; ++nRow )
+ {
+ SwTableLine* pLine = aLines[nRow];
+ OSL_ENSURE( pLine, "Missing table line" );
+ sal_uInt16 nCount = pLine->GetTabBoxes().Count();
+ for( sal_uInt16 nCurrBox = 0; nCurrBox < nCount; ++nCurrBox )
+ {
+ SwTableBox* pBox = pLine->GetTabBoxes()[nCurrBox];
+ OSL_ENSURE( pBox, "Missing table box" );
+ if( pBox->getRowSpan() > 0 && ( !bChkProtected ||
+ !pBox->GetFrmFmt()->GetProtect().IsCntntProtected() ) )
+ rBoxes.Insert( pBox );
+ }
+ }
+ return;
+ }
+ bool bCombine = nTop == nBottom;
+ if( !bCombine )
+ {
+ long nMinWidth = nUpperMax - nUpperMin;
+ long nTmp = nLowerMax - nLowerMin;
+ if( nMinWidth > nTmp )
+ nMinWidth = nTmp;
+ nTmp = nLowerMax < nUpperMax ? nLowerMax : nUpperMax;
+ nTmp -= ( nLowerMin < nUpperMin ) ? nUpperMin : nLowerMin;
+ // If the overlapping between upper and lower box is less than half
+ // of the width (of the smaller cell), bCombine is set,
+ // e.g. if upper and lower cell are in different columns
+ bCombine = ( nTmp + nTmp < nMinWidth );
+ }
+ if( bCombine )
+ {
+ if( nUpperMin < nLowerMin )
+ nLowerMin = nUpperMin;
+ else
+ nUpperMin = nLowerMin;
+ if( nUpperMax > nLowerMax )
+ nLowerMax = nUpperMax;
+ else
+ nUpperMax = nLowerMax;
+ }
+ const bool bColumn = eSearch == SEARCH_COL;
+ if( bColumn )
+ {
+ for( sal_uInt16 i = 0; i < nTop; ++i )
+ lcl_SearchSelBox( *this, rBoxes, nUpperMin, nUpperMax,
+ *aLines[i], bChkProtected, bColumn );
+ }
+
+ {
+ long nMin = nUpperMin < nLowerMin ? nUpperMin : nLowerMin;
+ long nMax = nUpperMax < nLowerMax ? nLowerMax : nUpperMax;
+ for( sal_uInt16 i = nTop; i <= nBottom; ++i )
+ lcl_SearchSelBox( *this, rBoxes, nMin, nMax, *aLines[i],
+ bChkProtected, bColumn );
+ }
+ if( bColumn )
+ {
+ for( sal_uInt16 i = nBottom + 1; i < nLines; ++i )
+ lcl_SearchSelBox( *this, rBoxes, nLowerMin, nLowerMax, *aLines[i],
+ bChkProtected, true );
+ }
+}
+
+/** void SwTable::ExpandColumnSelection(..) adds cell to the give selection to
+ assure that at least one cell of every row is part of the selection.
+*/
+
+void SwTable::ExpandColumnSelection( SwSelBoxes& rBoxes, long &rMin, long &rMax ) const
+{
+ OSL_ENSURE( bNewModel, "Don't call me for old tables" );
+ rMin = 0;
+ rMax = 0;
+ if( !aLines.Count() || !rBoxes.Count() )
+ return;
+
+ sal_uInt16 nLineCnt = aLines.Count();
+ sal_uInt16 nBoxCnt = rBoxes.Count();
+ sal_uInt16 nBox = 0;
+ for( sal_uInt16 nRow = 0; nRow < nLineCnt && nBox < nBoxCnt; ++nRow )
+ {
+ SwTableLine* pLine = aLines[nRow];
+ OSL_ENSURE( pLine, "Missing table line" );
+ sal_uInt16 nCols = pLine->GetTabBoxes().Count();
+ for( sal_uInt16 nCol = 0; nCol < nCols; ++nCol )
+ {
+ SwTableBox* pBox = pLine->GetTabBoxes()[nCol];
+ OSL_ENSURE( pBox, "Missing table box" );
+ if( pBox == rBoxes[nBox] )
+ {
+ lcl_CheckMinMax( rMin, rMax, *pLine, nCol, nBox == 0 );
+ if( ++nBox >= nBoxCnt )
+ break;
+ }
+ }
+ }
+ nBox = 0;
+ for( sal_uInt16 nRow = 0; nRow < nLineCnt; ++nRow )
+ {
+ SwTableLine* pLine = aLines[nRow];
+ sal_uInt16 nCols = pLine->GetTabBoxes().Count();
+ long nLeft = 0;
+ long nRight = 0;
+ for( sal_uInt16 nCurrBox = 0; nCurrBox < nCols; ++nCurrBox )
+ {
+ nLeft = nRight;
+ SwTableBox* pBox = pLine->GetTabBoxes()[nCurrBox];
+ nRight += pBox->GetFrmFmt()->GetFrmSize().GetWidth();
+ if( nLeft >= rMin && nRight <= rMax )
+ rBoxes.Insert( pBox );
+ }
+ }
+}
+
+/** SwTable::PrepareDeleteCol(..) adjusts the widths of the neighbour cells of
+ a cell selection for an upcoming (column) deletion
+*/
+void SwTable::PrepareDeleteCol( long nMin, long nMax )
+{
+ OSL_ENSURE( bNewModel, "Don't call me for old tables" );
+ if( !aLines.Count() || nMax < nMin )
+ return;
+ long nMid = nMin ? ( nMin + nMax ) / 2 : 0;
+ const SwTwips nTabSize = GetFrmFmt()->GetFrmSize().GetWidth();
+ if( nTabSize == nMax )
+ nMid = nMax;
+ sal_uInt16 nLineCnt = aLines.Count();
+ for( sal_uInt16 nRow = 0; nRow < nLineCnt; ++nRow )
+ {
+ SwTableLine* pLine = aLines[nRow];
+ sal_uInt16 nCols = pLine->GetTabBoxes().Count();
+ long nLeft = 0;
+ long nRight = 0;
+ for( sal_uInt16 nCurrBox = 0; nCurrBox < nCols; ++nCurrBox )
+ {
+ nLeft = nRight;
+ SwTableBox* pBox = pLine->GetTabBoxes()[nCurrBox];
+ nRight += pBox->GetFrmFmt()->GetFrmSize().GetWidth();
+ if( nRight < nMin )
+ continue;
+ if( nLeft > nMax )
+ break;
+ long nNewWidth = -1;
+ if( nLeft < nMin )
+ {
+ if( nRight <= nMax )
+ nNewWidth = nMid - nLeft;
+ }
+ else if( nRight > nMax )
+ nNewWidth = nRight - nMid;
+ else
+ nNewWidth = 0;
+ if( nNewWidth >= 0 )
+ {
+ SwFrmFmt* pFrmFmt = pBox->ClaimFrmFmt();
+ SwFmtFrmSize aFrmSz( pFrmFmt->GetFrmSize() );
+ aFrmSz.SetWidth( nNewWidth );
+ pFrmFmt->SetFmtAttr( aFrmSz );
+ }
+ }
+ }
+}
+
+
+
+/** SwTable::ExpandSelection(..) adds all boxes to the box selections which are
+ overlapped by it.
+*/
+
+void SwTable::ExpandSelection( SwSelBoxes& rBoxes ) const
+{
+ for( sal_uInt16 i = 0; i < rBoxes.Count(); ++i )
+ {
+ SwTableBox *pBox = rBoxes[i];
+ long nRowSpan = pBox->getRowSpan();
+ if( nRowSpan != 1 )
+ {
+ SwTableBox *pMasterBox = nRowSpan > 0 ? pBox
+ : &pBox->FindStartOfRowSpan( *this, USHRT_MAX );
+ lcl_getAllMergedBoxes( *this, rBoxes, *pMasterBox );
+ }
+ }
+}
+
+/** SwTable::CheckRowSpan(..) looks for the next line without an overlapping to
+ the previous line.
+*/
+
+void SwTable::CheckRowSpan( SwTableLinePtr &rpLine, bool bUp ) const
+{
+ OSL_ENSURE( IsNewModel(), "Don't call me for old tables" );
+ sal_uInt16 nLineIdx = GetTabLines().C40_GETPOS( SwTableLine, rpLine );
+ OSL_ENSURE( nLineIdx < GetTabLines().Count(), "Start line out of range" );
+ bool bChange = true;
+ if( bUp )
+ {
+ while( bChange )
+ {
+ bChange = false;
+ rpLine = GetTabLines()[ nLineIdx ];
+ sal_uInt16 nCols = rpLine->GetTabBoxes().Count();
+ for( sal_uInt16 nCol = 0; !bChange && nCol < nCols; ++nCol )
+ {
+ SwTableBox* pBox = rpLine->GetTabBoxes()[nCol];
+ if( pBox->getRowSpan() > 1 || pBox->getRowSpan() < -1 )
+ bChange = true;
+ }
+ if( bChange )
+ {
+ if( nLineIdx )
+ --nLineIdx;
+ else
+ {
+ bChange = false;
+ rpLine = 0;
+ }
+ }
+ }
+ }
+ else
+ {
+ sal_uInt16 nMaxLine = GetTabLines().Count();
+ while( bChange )
+ {
+ bChange = false;
+ rpLine = GetTabLines()[ nLineIdx ];
+ sal_uInt16 nCols = rpLine->GetTabBoxes().Count();
+ for( sal_uInt16 nCol = 0; !bChange && nCol < nCols; ++nCol )
+ {
+ SwTableBox* pBox = rpLine->GetTabBoxes()[nCol];
+ if( pBox->getRowSpan() < 0 )
+ bChange = true;
+ }
+ if( bChange )
+ {
+ ++nLineIdx;
+ if( nLineIdx >= nMaxLine )
+ {
+ bChange = false;
+ rpLine = 0;
+ }
+ }
+ }
+ }
+}
+
+// This structure corrects the row span attributes for a top line of a table
+// In a top line no negative row span is allowed, so these have to be corrected.
+// If there has been at least one correction, all values are stored
+// and can be used by undo of table split
+SwSaveRowSpan::SwSaveRowSpan( SwTableBoxes& rBoxes, sal_uInt16 nSplitLn )
+ : mnSplitLine( nSplitLn )
+{
+ bool bDontSave = true; // nothing changed, nothing to save
+ sal_uInt16 nColCount = rBoxes.Count();
+ OSL_ENSURE( nColCount, "Empty Table Line" );
+ mnRowSpans.resize( nColCount );
+ for( sal_uInt16 nCurrCol = 0; nCurrCol < nColCount; ++nCurrCol )
+ {
+ SwTableBox* pBox = rBoxes[nCurrCol];
+ OSL_ENSURE( pBox, "Missing Table Box" );
+ long nRowSp = pBox->getRowSpan();
+ mnRowSpans[ nCurrCol ] = nRowSp;
+ if( nRowSp < 0 )
+ {
+ bDontSave = false;
+ nRowSp = -nRowSp;
+ pBox->setRowSpan( nRowSp ); // correction needed
+ }
+ }
+ if( bDontSave )
+ mnRowSpans.clear();
+}
+
+// This function is called by undo of table split to restore the old row span
+// values at the split line
+void SwTable::RestoreRowSpan( const SwSaveRowSpan& rSave )
+{
+ if( !IsNewModel() ) // for new model only
+ return;
+ sal_uInt16 nLineCount = GetTabLines().Count();
+ OSL_ENSURE( rSave.mnSplitLine < nLineCount, "Restore behind last line?" );
+ if( rSave.mnSplitLine < nLineCount )
+ {
+ SwTableLine* pLine = GetTabLines()[rSave.mnSplitLine];
+ sal_uInt16 nColCount = pLine->GetTabBoxes().Count();
+ OSL_ENSURE( nColCount, "Empty Table Line" );
+ OSL_ENSURE( nColCount == rSave.mnRowSpans.size(), "Wrong row span store" );
+ if( nColCount == rSave.mnRowSpans.size() )
+ {
+ for( sal_uInt16 nCurrCol = 0; nCurrCol < nColCount; ++nCurrCol )
+ {
+ SwTableBox* pBox = pLine->GetTabBoxes()[nCurrCol];
+ OSL_ENSURE( pBox, "Missing Table Box" );
+ long nRowSp = pBox->getRowSpan();
+ if( nRowSp != rSave.mnRowSpans[ nCurrCol ] )
+ {
+ OSL_ENSURE( -nRowSp == rSave.mnRowSpans[ nCurrCol ], "Pardon me?!" );
+ OSL_ENSURE( rSave.mnRowSpans[ nCurrCol ] < 0, "Pardon me?!" );
+ pBox->setRowSpan( -nRowSp );
+
+ sal_uInt16 nLine = rSave.mnSplitLine;
+ if( nLine )
+ {
+ long nLeftBorder = lcl_Box2LeftBorder( *pBox );
+ SwTableBox* pNext;
+ do
+ {
+ pNext = lcl_LeftBorder2Box( nLeftBorder, GetTabLines()[--nLine] );
+ if( pNext )
+ {
+ pBox = pNext;
+ long nNewSpan = pBox->getRowSpan();
+ if( pBox->getRowSpan() < 1 )
+ nNewSpan -= nRowSp;
+ else
+ {
+ nNewSpan += nRowSp;
+ pNext = 0;
+ }
+ pBox->setRowSpan( nNewSpan );
+ }
+ } while( nLine && pNext );
+ }
+ }
+ }
+ }
+ }
+}
+
+SwSaveRowSpan* SwTable::CleanUpTopRowSpan( sal_uInt16 nSplitLine )
+{
+ SwSaveRowSpan* pRet = 0;
+ if( !IsNewModel() )
+ return pRet;
+ pRet = new SwSaveRowSpan( GetTabLines()[0]->GetTabBoxes(), nSplitLine );
+ if( pRet->mnRowSpans.size() == 0 )
+ {
+ delete pRet;
+ pRet = 0;
+ }
+ return pRet;
+}
+
+void SwTable::CleanUpBottomRowSpan( sal_uInt16 nDelLines )
+{
+ if( !IsNewModel() )
+ return;
+ sal_uInt16 nLastLine = GetTabLines().Count()-1;
+ SwTableLine* pLine = GetTabLines()[nLastLine];
+ sal_uInt16 nColCount = pLine->GetTabBoxes().Count();
+ OSL_ENSURE( nColCount, "Empty Table Line" );
+ for( sal_uInt16 nCurrCol = 0; nCurrCol < nColCount; ++nCurrCol )
+ {
+ SwTableBox* pBox = pLine->GetTabBoxes()[nCurrCol];
+ OSL_ENSURE( pBox, "Missing Table Box" );
+ long nRowSp = pBox->getRowSpan();
+ if( nRowSp < 0 )
+ nRowSp = -nRowSp;
+ if( nRowSp > 1 )
+ {
+ lcl_ChangeRowSpan( *this, -static_cast<long>(nDelLines), nLastLine, false );
+ break;
+ }
+ }
+}
+
+#if OSL_DEBUG_LEVEL > 1
+
+struct RowSpanCheck
+{
+ long nRowSpan;
+ SwTwips nLeft;
+ SwTwips nRight;
+};
+
+void SwTable::CheckConsistency() const
+{
+ if( !IsNewModel() )
+ return;
+ sal_uInt16 nLineCount = GetTabLines().Count();
+ const SwTwips nTabSize = GetFrmFmt()->GetFrmSize().GetWidth();
+ SwTwips nLineWidth = 0;
+ std::list< RowSpanCheck > aRowSpanCells;
+ std::list< RowSpanCheck >::iterator aIter = aRowSpanCells.end();
+ for( sal_uInt16 nCurrLine = 0; nCurrLine < nLineCount; ++nCurrLine )
+ {
+ SwTwips nWidth = 0;
+ SwTableLine* pLine = GetTabLines()[nCurrLine];
+ OSL_ENSURE( pLine, "Missing Table Line" );
+ sal_uInt16 nColCount = pLine->GetTabBoxes().Count();
+ OSL_ENSURE( nColCount, "Empty Table Line" );
+ for( sal_uInt16 nCurrCol = 0; nCurrCol < nColCount; ++nCurrCol )
+ {
+ SwTableBox* pBox = pLine->GetTabBoxes()[nCurrCol];
+ OSL_ENSURE( pBox, "Missing Table Box" );
+ SwTwips nNewWidth = pBox->GetFrmFmt()->GetFrmSize().GetWidth() + nWidth;
+ long nRowSp = pBox->getRowSpan();
+ if( nRowSp < 0 )
+ {
+ OSL_ENSURE( aIter != aRowSpanCells.end(), "Missing master box" );
+ OSL_ENSURE( aIter->nLeft == nWidth && aIter->nRight == nNewWidth,
+ "Wrong position/size of overlapped table box" );
+ --(aIter->nRowSpan);
+ OSL_ENSURE( aIter->nRowSpan == -nRowSp, "Wrong row span value" );
+ if( nRowSp == -1 )
+ {
+ std::list< RowSpanCheck >::iterator aEraseIter = aIter;
+ ++aIter;
+ aRowSpanCells.erase( aEraseIter );
+ }
+ else
+ ++aIter;
+ }
+ else if( nRowSp != 1 )
+ {
+ OSL_ENSURE( nRowSp, "Zero row span?!" );
+ RowSpanCheck aEntry;
+ aEntry.nLeft = nWidth;
+ aEntry.nRight = nNewWidth;
+ aEntry.nRowSpan = nRowSp;
+ aRowSpanCells.insert( aIter, aEntry );
+ }
+ nWidth = nNewWidth;
+ }
+ if( !nCurrLine )
+ nLineWidth = nWidth;
+ OSL_ENSURE( nWidth == nLineWidth, "Different Line Widths" );
+ OSL_ENSURE( nWidth == nTabSize, "Boxen der Line zu klein/gross" );
+ OSL_ENSURE( nWidth >= 0 && nWidth <= USHRT_MAX, "Width out of range" );
+ OSL_ENSURE( aIter == aRowSpanCells.end(), "Missing overlapped box" );
+ aIter = aRowSpanCells.begin();
+ }
+ bool bEmpty = aRowSpanCells.empty();
+ OSL_ENSURE( bEmpty, "Open row span detected" );
+}
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/table/swtable.cxx b/sw/source/core/table/swtable.cxx
new file mode 100644
index 000000000000..8a9c2349d3fc
--- /dev/null
+++ b/sw/source/core/table/swtable.cxx
@@ -0,0 +1,2824 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+#include <ctype.h>
+#include <float.h>
+#include <hintids.hxx>
+#include <hints.hxx> // fuer SwAttrSetChg
+#include <editeng/lrspitem.hxx>
+#include <editeng/shaditem.hxx>
+#include <editeng/adjitem.hxx>
+#include <editeng/colritem.hxx>
+#include <sfx2/linkmgr.hxx>
+#include <editeng/boxitem.hxx>
+#include <fmtfsize.hxx>
+#include <fmtornt.hxx>
+#include <fmtpdsc.hxx>
+#include <fldbas.hxx>
+#include <fmtfld.hxx>
+#include <frmatr.hxx>
+#include <doc.hxx>
+#include <docary.hxx> // fuer RedlineTbl()
+#include <frame.hxx>
+#include <swtable.hxx>
+#include <ndtxt.hxx>
+#include <tabcol.hxx>
+#include <tabfrm.hxx>
+#include <cellfrm.hxx>
+#include <rowfrm.hxx>
+#include <swserv.hxx>
+#include <expfld.hxx>
+#include <mdiexp.hxx>
+#include <cellatr.hxx>
+#include <txatbase.hxx>
+#include <htmltbl.hxx>
+#include <swtblfmt.hxx>
+#include <ndindex.hxx>
+#include <tblrwcl.hxx>
+#include <shellres.hxx>
+#include <viewsh.hxx>
+#include <redline.hxx>
+#include <list>
+#include <switerator.hxx>
+
+#if OSL_DEBUG_LEVEL > 1
+#define CHECK_TABLE(t) (t).CheckConsistency();
+#else
+#define CHECK_TABLE(t)
+#endif
+
+using namespace com::sun::star;
+
+TYPEINIT1( SwTable, SwClient );
+TYPEINIT1( SwTableBox, SwClient );
+TYPEINIT1( SwTableLine, SwClient );
+TYPEINIT1( SwTableFmt, SwFrmFmt );
+TYPEINIT1( SwTableBoxFmt, SwFrmFmt );
+TYPEINIT1( SwTableLineFmt, SwFrmFmt );
+
+SV_IMPL_PTRARR(SwTableLines,SwTableLine*);
+SV_IMPL_PTRARR(SwTableBoxes,SwTableBox*);
+SV_IMPL_PTRARR_SORT(SwTableSortBoxes,SwTableBoxPtr);
+
+SV_IMPL_REF( SwServerObject )
+
+#define COLFUZZY 20
+
+void ChgTextToNum( SwTableBox& rBox, const String& rTxt, const Color* pCol,
+ sal_Bool bChgAlign,sal_uLong nNdPos );
+//----------------------------------
+
+class SwTableBox_Impl
+{
+ Color *mpUserColor, *mpNumFmtColor;
+ long mnRowSpan;
+ bool mbDummyFlag;
+
+ void SetNewCol( Color** ppCol, const Color* pNewCol );
+public:
+ SwTableBox_Impl() : mpUserColor(0), mpNumFmtColor(0), mnRowSpan(1),
+ mbDummyFlag( false ) {}
+ ~SwTableBox_Impl() { delete mpUserColor; delete mpNumFmtColor; }
+
+ const Color* GetSaveUserColor() const { return mpUserColor; }
+ const Color* GetSaveNumFmtColor() const { return mpNumFmtColor; }
+ void SetSaveUserColor(const Color* p ) { SetNewCol( &mpUserColor, p ); }
+ void SetSaveNumFmtColor( const Color* p ) { SetNewCol( &mpNumFmtColor, p ); }
+ long getRowSpan() const { return mnRowSpan; }
+ void setRowSpan( long nNewRowSpan ) { mnRowSpan = nNewRowSpan; }
+ bool getDummyFlag() const { return mbDummyFlag; }
+ void setDummyFlag( bool bDummy ) { mbDummyFlag = bDummy; }
+};
+
+// ----------- Inlines -----------------------------
+
+inline const Color* SwTableBox::GetSaveUserColor() const
+{
+ return pImpl ? pImpl->GetSaveUserColor() : 0;
+}
+
+inline const Color* SwTableBox::GetSaveNumFmtColor() const
+{
+ return pImpl ? pImpl->GetSaveNumFmtColor() : 0;
+}
+
+inline void SwTableBox::SetSaveUserColor(const Color* p )
+{
+ if( pImpl )
+ pImpl->SetSaveUserColor( p );
+ else if( p )
+ ( pImpl = new SwTableBox_Impl ) ->SetSaveUserColor( p );
+}
+
+inline void SwTableBox::SetSaveNumFmtColor( const Color* p )
+{
+ if( pImpl )
+ pImpl->SetSaveNumFmtColor( p );
+ else if( p )
+ ( pImpl = new SwTableBox_Impl )->SetSaveNumFmtColor( p );
+}
+
+long SwTableBox::getRowSpan() const
+{
+ return pImpl ? pImpl->getRowSpan() : 1;
+}
+
+void SwTableBox::setRowSpan( long nNewRowSpan )
+{
+ if( !pImpl )
+ {
+ if( nNewRowSpan == 1 )
+ return;
+ pImpl = new SwTableBox_Impl();
+ }
+ pImpl->setRowSpan( nNewRowSpan );
+}
+
+bool SwTableBox::getDummyFlag() const
+{
+ return pImpl ? pImpl->getDummyFlag() : false;
+}
+
+void SwTableBox::setDummyFlag( bool bDummy )
+{
+ if( !pImpl )
+ {
+ if( !bDummy )
+ return;
+ pImpl = new SwTableBox_Impl();
+ }
+ pImpl->setDummyFlag( bDummy );
+}
+
+//JP 15.09.98: Bug 55741 - Keep tabs (front and rear)
+String& lcl_TabToBlankAtSttEnd( String& rTxt )
+{
+ sal_Unicode c;
+ xub_StrLen n;
+
+ for( n = 0; n < rTxt.Len() && ' ' >= ( c = rTxt.GetChar( n )); ++n )
+ if( '\x9' == c )
+ rTxt.SetChar( n, ' ' );
+ for( n = rTxt.Len(); n && ' ' >= ( c = rTxt.GetChar( --n )); )
+ if( '\x9' == c )
+ rTxt.SetChar( n, ' ' );
+ return rTxt;
+}
+
+String& lcl_DelTabsAtSttEnd( String& rTxt )
+{
+ sal_Unicode c;
+ xub_StrLen n;
+
+ for( n = 0; n < rTxt.Len() && ' ' >= ( c = rTxt.GetChar( n )); ++n )
+ if( '\x9' == c )
+ rTxt.Erase( n--, 1 );
+ for( n = rTxt.Len(); n && ' ' >= ( c = rTxt.GetChar( --n )); )
+ if( '\x9' == c )
+ rTxt.Erase( n, 1 );
+ return rTxt;
+}
+
+void _InsTblBox( SwDoc* pDoc, SwTableNode* pTblNd,
+ SwTableLine* pLine, SwTableBoxFmt* pBoxFrmFmt,
+ SwTableBox* pBox,
+ sal_uInt16 nInsPos, sal_uInt16 nCnt )
+{
+ OSL_ENSURE( pBox->GetSttNd(), "Box ohne Start-Node" );
+ SwNodeIndex aIdx( *pBox->GetSttNd(), +1 );
+ SwCntntNode* pCNd = aIdx.GetNode().GetCntntNode();
+ if( !pCNd )
+ pCNd = pDoc->GetNodes().GoNext( &aIdx );
+ OSL_ENSURE( pCNd, "Box ohne ContentNode" );
+
+ if( pCNd->IsTxtNode() )
+ {
+ if( pBox->GetSaveNumFmtColor() && pCNd->GetpSwAttrSet() )
+ {
+ SwAttrSet aAttrSet( *pCNd->GetpSwAttrSet() );
+ if( pBox->GetSaveUserColor() )
+ aAttrSet.Put( SvxColorItem( *pBox->GetSaveUserColor(), RES_CHRATR_COLOR ));
+ else
+ aAttrSet.ClearItem( RES_CHRATR_COLOR );
+ pDoc->GetNodes().InsBoxen( pTblNd, pLine, pBoxFrmFmt,
+ ((SwTxtNode*)pCNd)->GetTxtColl(),
+ &aAttrSet, nInsPos, nCnt );
+ }
+ else
+ pDoc->GetNodes().InsBoxen( pTblNd, pLine, pBoxFrmFmt,
+ ((SwTxtNode*)pCNd)->GetTxtColl(),
+ pCNd->GetpSwAttrSet(),
+ nInsPos, nCnt );
+ }
+ else
+ pDoc->GetNodes().InsBoxen( pTblNd, pLine, pBoxFrmFmt,
+ (SwTxtFmtColl*)pDoc->GetDfltTxtFmtColl(), 0,
+ nInsPos, nCnt );
+
+ long nRowSpan = pBox->getRowSpan();
+ if( nRowSpan != 1 )
+ {
+ SwTableBoxes& rTblBoxes = pLine->GetTabBoxes();
+ for( sal_uInt16 i = 0; i < nCnt; ++i )
+ {
+ pBox = rTblBoxes[ i + nInsPos ];
+ pBox->setRowSpan( nRowSpan );
+ }
+ }
+}
+
+/*************************************************************************
+|*
+|* SwTable::SwTable()
+|*
+|*************************************************************************/
+SwTable::SwTable( SwTableFmt* pFmt )
+ : SwClient( pFmt ),
+ pHTMLLayout( 0 ),
+ pTableNode( 0 ),
+ nGrfsThatResize( 0 ),
+ nRowsToRepeat( 1 ),
+ bModifyLocked( sal_False ),
+ bNewModel( sal_True )
+{
+ // default value set in the options
+ eTblChgMode = (TblChgMode)GetTblChgDefaultMode();
+}
+
+SwTable::SwTable( const SwTable& rTable )
+ : SwClient( rTable.GetFrmFmt() ),
+ pHTMLLayout( 0 ),
+ pTableNode( 0 ),
+ eTblChgMode( rTable.eTblChgMode ),
+ nGrfsThatResize( 0 ),
+ nRowsToRepeat( rTable.GetRowsToRepeat() ),
+ bModifyLocked( sal_False ),
+ bNewModel( rTable.bNewModel )
+{
+}
+
+void DelBoxNode( SwTableSortBoxes& rSortCntBoxes )
+{
+ for( sal_uInt16 n = 0; n < rSortCntBoxes.Count(); ++n )
+ rSortCntBoxes[ n ]->pSttNd = 0;
+}
+
+SwTable::~SwTable()
+{
+ if( refObj.Is() )
+ {
+ SwDoc* pDoc = GetFrmFmt()->GetDoc();
+ if( !pDoc->IsInDtor() ) // then remove from the list
+ pDoc->GetLinkManager().RemoveServer( &refObj );
+
+ refObj->Closed();
+ }
+
+ // ist die Tabelle der letzte Client im FrameFormat, kann dieses
+ // geloescht werden
+ SwTableFmt* pFmt = (SwTableFmt*)GetFrmFmt();
+ pFmt->Remove( this ); // austragen,
+
+ if( !pFmt->GetDepends() )
+ pFmt->GetDoc()->DelTblFrmFmt( pFmt ); // und loeschen
+
+ // Loesche die Pointer aus dem SortArray der Boxen, die
+ // Objecte bleiben erhalten und werden vom DTOR der Lines/Boxes
+ // Arrays geloescht.
+ //JP: reicht leider nicht, es muessen die Pointer auf den StartNode
+ // der Section geloescht werden
+ DelBoxNode( aSortCntBoxes );
+ aSortCntBoxes.Remove( (sal_uInt16)0, aSortCntBoxes.Count() );
+ delete pHTMLLayout;
+}
+
+/*************************************************************************
+|*
+|* SwTable::Modify()
+|*
+|*************************************************************************/
+inline void FmtInArr( SvPtrarr& rFmtArr, SwFmt* pBoxFmt )
+{
+ sal_Bool bRet = USHRT_MAX != rFmtArr.GetPos( (VoidPtr)pBoxFmt );
+ if( !bRet )
+ rFmtArr.Insert( (VoidPtr)pBoxFmt, rFmtArr.Count() );
+}
+
+void lcl_ModifyBoxes( SwTableBoxes &rBoxes, const long nOld,
+ const long nNew, SvPtrarr& rFmtArr );
+
+void lcl_ModifyLines( SwTableLines &rLines, const long nOld,
+ const long nNew, SvPtrarr& rFmtArr, const bool bCheckSum )
+{
+ for ( sal_uInt16 i = 0; i < rLines.Count(); ++i )
+ ::lcl_ModifyBoxes( rLines[i]->GetTabBoxes(), nOld, nNew, rFmtArr );
+ if( bCheckSum )
+ {
+ for( sal_uInt16 i = 0; i < rFmtArr.Count(); ++i )
+ {
+ SwFmt* pFmt = (SwFmt*)rFmtArr[i];
+ sal_uInt64 nBox = pFmt->GetFrmSize().GetWidth();
+ nBox *= nNew;
+ nBox /= nOld;
+ SwFmtFrmSize aNewBox( ATT_VAR_SIZE, SwTwips(nBox), 0 );
+ pFmt->LockModify();
+ pFmt->SetFmtAttr( aNewBox );
+ pFmt->UnlockModify();
+ }
+ }
+}
+
+void lcl_ModifyBoxes( SwTableBoxes &rBoxes, const long nOld,
+ const long nNew, SvPtrarr& rFmtArr )
+{
+ sal_uInt64 nSum = 0; // To avoid rounding errors we summarize all box widths
+ sal_uInt64 nOriginalSum = 0; // Sum of original widths
+ for ( sal_uInt16 i = 0; i < rBoxes.Count(); ++i )
+ {
+ SwTableBox &rBox = *rBoxes[i];
+ if ( rBox.GetTabLines().Count() )
+ {
+ // For SubTables the rounding problem will not be solved :-(
+ ::lcl_ModifyLines( rBox.GetTabLines(), nOld, nNew, rFmtArr, false );
+ }
+ //Die Box anpassen
+ SwFrmFmt *pFmt = rBox.GetFrmFmt();
+ sal_uInt64 nBox = pFmt->GetFrmSize().GetWidth();
+ nOriginalSum += nBox;
+ nBox *= nNew;
+ nBox /= nOld;
+ sal_uInt64 nWishedSum = nOriginalSum;
+ nWishedSum *= nNew;
+ nWishedSum /= nOld;
+ nWishedSum -= nSum;
+ if( nWishedSum > 0 )
+ {
+ if( nBox == nWishedSum )
+ FmtInArr( rFmtArr, pFmt );
+ else
+ {
+ nBox = nWishedSum;
+ pFmt = rBox.ClaimFrmFmt();
+ SwFmtFrmSize aNewBox( ATT_VAR_SIZE, static_cast< SwTwips >(nBox), 0 );
+ pFmt->LockModify();
+ pFmt->SetFmtAttr( aNewBox );
+ pFmt->UnlockModify();
+ }
+ }
+ else {
+ OSL_FAIL( "Rounding error" );
+ }
+ nSum += nBox;
+ }
+}
+
+void SwTable::Modify( const SfxPoolItem* pOld, const SfxPoolItem *pNew )
+{
+ // fange SSize Aenderungen ab, um die Lines/Boxen anzupassen
+ sal_uInt16 nWhich = pOld ? pOld->Which() : pNew ? pNew->Which() : 0 ;
+ const SwFmtFrmSize* pNewSize = 0, *pOldSize = 0;
+
+ if( RES_ATTRSET_CHG == nWhich )
+ {
+ if( SFX_ITEM_SET == ((SwAttrSetChg*)pNew)->GetChgSet()->GetItemState(
+ RES_FRM_SIZE, sal_False, (const SfxPoolItem**)&pNewSize ))
+ pOldSize = &((SwAttrSetChg*)pOld)->GetChgSet()->GetFrmSize();
+ }
+ else if( RES_FRM_SIZE == nWhich )
+ {
+ pOldSize = (const SwFmtFrmSize*)pOld;
+ pNewSize = (const SwFmtFrmSize*)pNew;
+ }
+ else
+ CheckRegistration( pOld, pNew );
+
+ if( pOldSize || pNewSize )
+ {
+ if ( !IsModifyLocked() )
+ {
+ OSL_ENSURE( pOldSize && pOldSize->Which() == RES_FRM_SIZE &&
+ pNewSize && pNewSize->Which() == RES_FRM_SIZE,
+ "Kein Old oder New fuer FmtFrmSize-Modify der SwTable." );
+ AdjustWidths( pOldSize->GetWidth(), pNewSize->GetWidth() );
+ }
+ }
+}
+
+void SwTable::AdjustWidths( const long nOld, const long nNew )
+{
+ SvPtrarr aFmtArr( (sal_uInt8)aLines[0]->GetTabBoxes().Count(), 1 );
+ ::lcl_ModifyLines( aLines, nOld, nNew, aFmtArr, true );
+}
+
+/*************************************************************************
+|*
+|* SwTable::GetTabCols()
+|*
+|*************************************************************************/
+void lcl_RefreshHidden( SwTabCols &rToFill, sal_uInt16 nPos )
+{
+ for ( sal_uInt16 i = 0; i < rToFill.Count(); ++i )
+ {
+ if ( Abs((long)(nPos - rToFill[i])) <= COLFUZZY )
+ {
+ rToFill.SetHidden( i, sal_False );
+ break;
+ }
+ }
+}
+
+void lcl_SortedTabColInsert( SwTabCols &rToFill, const SwTableBox *pBox,
+ const SwFrmFmt *pTabFmt, const sal_Bool bHidden,
+ const bool bRefreshHidden )
+{
+ const long nWish = pTabFmt->GetFrmSize().GetWidth();
+ const long nAct = rToFill.GetRight() - rToFill.GetLeft(); // +1 why?
+
+ //Der Wert fuer die linke Kante der Box errechnet sich aus den
+ //Breiten der vorhergehenden Boxen.
+ sal_uInt16 nPos = 0;
+ sal_uInt16 nSum = 0;
+ sal_uInt16 nLeftMin = 0;
+ sal_uInt16 nRightMax = 0;
+ const SwTableBox *pCur = pBox;
+ const SwTableLine *pLine = pBox->GetUpper();
+ while ( pLine )
+ { const SwTableBoxes &rBoxes = pLine->GetTabBoxes();
+ for ( sal_uInt16 i = 0; i < rBoxes.Count(); ++i )
+ {
+ SwTwips nWidth = rBoxes[i]->GetFrmFmt()->GetFrmSize().GetWidth();
+ nSum = (sal_uInt16)(nSum + nWidth);
+ sal_uInt64 nTmp = nSum;
+ nTmp *= nAct;
+ nTmp /= nWish;
+ if (rBoxes[i] != pCur)
+ {
+ if ( pLine == pBox->GetUpper() || 0 == nLeftMin )
+ nLeftMin = (sal_uInt16)(nTmp - nPos);
+ nPos = (sal_uInt16)nTmp;
+ }
+ else
+ {
+ nSum = (sal_uInt16)(nSum - nWidth);
+ if ( 0 == nRightMax )
+ nRightMax = (sal_uInt16)(nTmp - nPos);
+ break;
+ }
+ }
+ pCur = pLine->GetUpper();
+ pLine = pCur ? pCur->GetUpper() : 0;
+ }
+
+ sal_Bool bInsert = !bRefreshHidden;
+ for ( sal_uInt16 j = 0; bInsert && (j < rToFill.Count()); ++j )
+ {
+ long nCmp = rToFill[j];
+ if ( (nPos >= ((nCmp >= COLFUZZY) ? nCmp - COLFUZZY : nCmp)) &&
+ (nPos <= (nCmp + COLFUZZY)) )
+ {
+ bInsert = sal_False; //Hat ihn schon.
+ }
+ else if ( nPos < nCmp )
+ {
+ bInsert = sal_False;
+ rToFill.Insert( nPos, bHidden, j );
+ }
+ }
+ if ( bInsert )
+ rToFill.Insert( nPos, bHidden, rToFill.Count() );
+ else if ( bRefreshHidden )
+ ::lcl_RefreshHidden( rToFill, nPos );
+
+ if ( bHidden && !bRefreshHidden )
+ {
+ // calculate minimum/maximum values for the existing entries:
+ nLeftMin = nPos - nLeftMin;
+ nRightMax = nPos + nRightMax;
+
+ // check if nPos is entry:
+ bool bFoundPos = false;
+ bool bFoundMax = false;
+ for ( sal_uInt16 j = 0; !(bFoundPos && bFoundMax ) && j < rToFill.Count(); ++j )
+ {
+ SwTabColsEntry& rEntry = rToFill.GetEntry( j );
+ long nCmp = rToFill[j];
+
+ if ( (nPos >= ((nCmp >= COLFUZZY) ? nCmp - COLFUZZY : nCmp)) &&
+ (nPos <= (nCmp + COLFUZZY)) )
+ {
+ // check if nLeftMin is > old minimum for entry nPos:
+ const long nOldMin = rEntry.nMin;
+ if ( nLeftMin > nOldMin )
+ rEntry.nMin = nLeftMin;
+ // check if nRightMin is < old maximum for entry nPos:
+ const long nOldMax = rEntry.nMax;
+ if ( nRightMax < nOldMax )
+ rEntry.nMax = nRightMax;
+
+ bFoundPos = true;
+ }
+ else if ( (nRightMax >= ((nCmp >= COLFUZZY) ? nCmp - COLFUZZY : nCmp)) &&
+ (nRightMax <= (nCmp + COLFUZZY)) )
+ {
+ // check if nPos is > old minimum for entry nRightMax:
+ const long nOldMin = rEntry.nMin;
+ if ( nPos > nOldMin )
+ rEntry.nMin = nPos;
+
+ bFoundMax = true;
+ }
+ }
+ }
+}
+
+void lcl_ProcessBoxGet( const SwTableBox *pBox, SwTabCols &rToFill,
+ const SwFrmFmt *pTabFmt, bool bRefreshHidden )
+{
+ if ( pBox->GetTabLines().Count() )
+ {
+ const SwTableLines &rLines = pBox->GetTabLines();
+ for ( sal_uInt16 i = 0; i < rLines.Count(); ++i )
+ { const SwTableBoxes &rBoxes = rLines[i]->GetTabBoxes();
+ for ( sal_uInt16 j = 0; j < rBoxes.Count(); ++j )
+ ::lcl_ProcessBoxGet( rBoxes[j], rToFill, pTabFmt, bRefreshHidden);
+ }
+ }
+ else
+ ::lcl_SortedTabColInsert( rToFill, pBox, pTabFmt, sal_False, bRefreshHidden );
+}
+
+void lcl_ProcessLineGet( const SwTableLine *pLine, SwTabCols &rToFill,
+ const SwFrmFmt *pTabFmt )
+{
+ for ( sal_uInt16 i = 0; i < pLine->GetTabBoxes().Count(); ++i )
+ {
+ const SwTableBox *pBox = pLine->GetTabBoxes()[i];
+ if ( pBox->GetSttNd() )
+ ::lcl_SortedTabColInsert( rToFill, pBox, pTabFmt, sal_True, sal_False );
+ else
+ for ( sal_uInt16 j = 0; j < pBox->GetTabLines().Count(); ++j )
+ ::lcl_ProcessLineGet( pBox->GetTabLines()[j], rToFill, pTabFmt );
+ }
+}
+
+// MS: Sonst Absturz auf der DEC-Kiste
+//
+#if defined(ALPHA) && defined(WNT)
+#pragma optimize("", off)
+#endif
+
+void SwTable::GetTabCols( SwTabCols &rToFill, const SwTableBox *pStart,
+ sal_Bool bRefreshHidden, sal_Bool bCurRowOnly ) const
+{
+ //MA 30. Nov. 95: Opt: wenn bHidden gesetzt ist, wird nur das Hidden
+ //Array aktualisiert.
+ if ( bRefreshHidden )
+ {
+ // remove corrections
+ sal_uInt16 i;
+ for ( i = 0; i < rToFill.Count(); ++i )
+ {
+ SwTabColsEntry& rEntry = rToFill.GetEntry( i );
+ rEntry.nPos -= rToFill.GetLeft();
+ rEntry.nMin -= rToFill.GetLeft();
+ rEntry.nMax -= rToFill.GetLeft();
+ }
+
+ //Alle sind hidden, dann die sichtbaren eintragen.
+ for ( i = 0; i < rToFill.Count(); ++i )
+ rToFill.SetHidden( i, sal_True );
+ }
+ else
+ {
+ rToFill.Remove( 0, rToFill.Count() );
+ }
+
+ //Eingetragen werden:
+ //1. Alle Boxen unterhalb der dem Start uebergeordneten Line sowie
+ // deren untergeordnete Boxen falls vorhanden.
+ //2. Ausgehend von der Line die uebergeordnete Box sowie deren Nachbarn;
+ // nicht aber deren untergeordnete.
+ //3. Mit der der Boxenkette uebergeordneten Line wieder wie 2. bis einer
+ // Line keine Box (sondern die Table) uebergeordnet ist.
+ //Es werden nur diejenigen Boxen eingetragen, die keine weiteren Zeilen
+ //enhalten. Die eintragende Funktion sorgt dafuer, dass keine doppelten
+ //eingetragen werden. Um dies zu gewaehrleisten wird mit einer gewissen
+ //Unschaerfe gearbeitet (um Rundungsfehler auszuschalten).
+ //Es werden nur die linken Kanten der Boxen eingetragen.
+ //Am Schluss wird der Erste wieder ausgetragen denn er ist bereits vom
+ //Rand abgedeckt.
+
+ //4. Nochmalige abscannen der Tabelle und eintragen _aller_ Boxen,
+ // jetzt aber als Hidden.
+
+ const SwFrmFmt *pTabFmt = GetFrmFmt();
+
+ //1.
+ const SwTableBoxes &rBoxes = pStart->GetUpper()->GetTabBoxes();
+
+ sal_uInt16 i;
+ for ( i = 0; i < rBoxes.Count(); ++i )
+ ::lcl_ProcessBoxGet( rBoxes[i], rToFill, pTabFmt, bRefreshHidden );
+
+ //2. und 3.
+ const SwTableLine *pLine = pStart->GetUpper()->GetUpper() ?
+ pStart->GetUpper()->GetUpper()->GetUpper() : 0;
+ while ( pLine )
+ {
+ const SwTableBoxes &rBoxes2 = pLine->GetTabBoxes();
+ for ( sal_uInt16 k = 0; k < rBoxes2.Count(); ++k )
+ ::lcl_SortedTabColInsert( rToFill, rBoxes2[k],
+ pTabFmt, sal_False, bRefreshHidden );
+ pLine = pLine->GetUpper() ? pLine->GetUpper()->GetUpper() : 0;
+ }
+
+ if ( !bRefreshHidden )
+ {
+ //4.
+ if ( !bCurRowOnly )
+ {
+ for ( i = 0; i < aLines.Count(); ++i )
+ ::lcl_ProcessLineGet( aLines[i], rToFill, pTabFmt );
+ }
+
+ rToFill.Remove( 0, 1 );
+ }
+
+ //Die Koordinaten sind jetzt relativ zum linken Rand der Tabelle - also
+ //relativ zum nLeft vom SwTabCols. Die Werte werden aber relativ zum
+ //linken Rand - also nLeftMin vom SwTabCols - erwartet.
+ //Alle Werte muessen also um nLeft erweitert werden.
+ for ( i = 0; i < rToFill.Count(); ++i )
+ {
+ SwTabColsEntry& rEntry = rToFill.GetEntry( i );
+ rEntry.nPos += rToFill.GetLeft();
+ rEntry.nMin += rToFill.GetLeft();
+ rEntry.nMax += rToFill.GetLeft();
+ }
+}
+
+#if defined(ALPHA) && defined(WNT)
+#pragma optimize("", on)
+#endif
+
+/*************************************************************************
+|*
+|* SwTable::SetTabCols()
+|*
+|*************************************************************************/
+//Struktur zur Parameteruebergabe
+struct Parm
+{
+ const SwTabCols &rNew;
+ const SwTabCols &rOld;
+ long nNewWish,
+ nOldWish;
+ SvPtrarr aBoxArr;
+ SwShareBoxFmts aShareFmts;
+
+ Parm( const SwTabCols &rN, const SwTabCols &rO ) :
+ rNew( rN ), rOld( rO ), nNewWish(0), nOldWish(0), aBoxArr( 10, 1 ){}
+};
+inline sal_Bool BoxInArr( SvPtrarr& rArr, SwTableBox* pBox )
+{
+ sal_Bool bRet = USHRT_MAX != rArr.GetPos( (VoidPtr)pBox );
+ if( !bRet )
+ rArr.Insert( (VoidPtr)pBox, rArr.Count() );
+ return bRet;
+}
+
+void lcl_ProcessBoxSet( SwTableBox *pBox, Parm &rParm );
+
+void lcl_ProcessLine( SwTableLine *pLine, Parm &rParm )
+{
+ SwTableBoxes &rBoxes = pLine->GetTabBoxes();
+ for ( int i = rBoxes.Count()-1; i >= 0; --i )
+ ::lcl_ProcessBoxSet( rBoxes[ static_cast< sal_uInt16 >(i) ], rParm );
+}
+
+void lcl_ProcessBoxSet( SwTableBox *pBox, Parm &rParm )
+{
+ if ( pBox->GetTabLines().Count() )
+ { SwTableLines &rLines = pBox->GetTabLines();
+ for ( int i = rLines.Count()-1; i >= 0; --i )
+ lcl_ProcessLine( rLines[ static_cast< sal_uInt16 >(i) ], rParm );
+ }
+ else
+ {
+ //Aktuelle Position (linke und rechte Kante berechnen) und im
+ //alten TabCols suchen. Im neuen TabCols die Werte vergleichen und
+ //wenn es Unterschiede gibt die Box entsprechend anpassen.
+ //Wenn an der veraenderten Kante kein Nachbar existiert werden auch
+ //alle uebergeordneten Boxen angepasst.
+
+ const long nOldAct = rParm.rOld.GetRight() -
+ rParm.rOld.GetLeft(); // +1 why?
+
+ //Der Wert fuer die linke Kante der Box errechnet sich aus den
+ //Breiten der vorhergehenden Boxen plus dem linken Rand
+ long nLeft = rParm.rOld.GetLeft();
+ const SwTableBox *pCur = pBox;
+ const SwTableLine *pLine = pBox->GetUpper();
+
+ while ( pLine )
+ { const SwTableBoxes &rBoxes = pLine->GetTabBoxes();
+ for ( sal_uInt16 i = 0; (i < rBoxes.Count()) && (rBoxes[i] != pCur); ++i)
+ {
+ sal_uInt64 nWidth = rBoxes[i]->GetFrmFmt()->
+ GetFrmSize().GetWidth();
+ nWidth *= nOldAct;
+ nWidth /= rParm.nOldWish;
+ nLeft += (sal_uInt16)nWidth;
+ }
+ pCur = pLine->GetUpper();
+ pLine = pCur ? pCur->GetUpper() : 0;
+ }
+ long nLeftDiff;
+ long nRightDiff = 0;
+ if ( nLeft != rParm.rOld.GetLeft() ) //Es gibt noch Boxen davor.
+ {
+ //Rechte Kante ist linke Kante plus Breite.
+ sal_uInt64 nWidth = pBox->GetFrmFmt()->GetFrmSize().GetWidth();
+ nWidth *= nOldAct;
+ nWidth /= rParm.nOldWish;
+ long nRight = nLeft + (long)nWidth;
+ sal_uInt16 nLeftPos = USHRT_MAX,
+ nRightPos = USHRT_MAX;
+ for ( sal_uInt16 i = 0; i < rParm.rOld.Count(); ++i )
+ {
+ if ( nLeft >= (rParm.rOld[i] - COLFUZZY) &&
+ nLeft <= (rParm.rOld[i] + COLFUZZY) )
+ nLeftPos = i;
+ else if ( nRight >= (rParm.rOld[i] - COLFUZZY) &&
+ nRight <= (rParm.rOld[i] + COLFUZZY) )
+ nRightPos = i;
+ }
+ nLeftDiff = nLeftPos != USHRT_MAX ?
+ (int)rParm.rOld[nLeftPos] - (int)rParm.rNew[nLeftPos] : 0;
+ nRightDiff= nRightPos!= USHRT_MAX ?
+ (int)rParm.rNew[nRightPos] - (int)rParm.rOld[nRightPos] : 0;
+ }
+ else //Die erste Box.
+ {
+ nLeftDiff = (long)rParm.rOld.GetLeft() - (long)rParm.rNew.GetLeft();
+ if ( rParm.rOld.Count() )
+ {
+ //Differnz zu der Kante berechnen, von der die erste Box
+ //beruehrt wird.
+ sal_uInt64 nWidth = pBox->GetFrmFmt()->GetFrmSize().GetWidth();
+ nWidth *= nOldAct;
+ nWidth /= rParm.nOldWish;
+ long nTmp = (long)nWidth;
+ nTmp += rParm.rOld.GetLeft();
+ sal_uInt16 nLeftPos = USHRT_MAX;
+ for ( sal_uInt16 i = 0; i < rParm.rOld.Count() &&
+ nLeftPos == USHRT_MAX; ++i )
+ {
+ if ( nTmp >= (rParm.rOld[i] - COLFUZZY) &&
+ nTmp <= (rParm.rOld[i] + COLFUZZY) )
+ nLeftPos = i;
+ }
+ if ( nLeftPos != USHRT_MAX )
+ nRightDiff = (long)rParm.rNew[nLeftPos] -
+ (long)rParm.rOld[nLeftPos];
+ }
+ }
+
+ if( pBox->getRowSpan() == 1 )
+ {
+ SwTableBoxes& rTblBoxes = pBox->GetUpper()->GetTabBoxes();
+ sal_uInt16 nPos = rTblBoxes.C40_GETPOS( SwTableBox, pBox );
+ if( nPos && rTblBoxes[ nPos - 1 ]->getRowSpan() != 1 )
+ nLeftDiff = 0;
+ if( nPos + 1 < rTblBoxes.Count() &&
+ rTblBoxes[ nPos + 1 ]->getRowSpan() != 1 )
+ nRightDiff = 0;
+ }
+ else
+ nLeftDiff = nRightDiff = 0;
+
+ if ( nLeftDiff || nRightDiff )
+ {
+ //Die Differenz ist der tatsaechliche Differenzbetrag; die
+ //Attribute der Boxen um diesen Betrag anzupassen macht keinen
+ //Sinn wenn die Tabelle gestrecht ist. Der Differenzbetrag muss
+ //entsprechend umgerechnet werden.
+ long nTmp = rParm.rNew.GetRight() - rParm.rNew.GetLeft(); // +1 why?
+ nLeftDiff *= rParm.nNewWish;
+ nLeftDiff /= nTmp;
+ nRightDiff *= rParm.nNewWish;
+ nRightDiff /= nTmp;
+ long nDiff = nLeftDiff + nRightDiff;
+
+ //Box und alle uebergeordneten um den Differenzbetrag anpassen.
+ while ( pBox )
+ {
+ SwFmtFrmSize aFmtFrmSize( pBox->GetFrmFmt()->GetFrmSize() );
+ aFmtFrmSize.SetWidth( aFmtFrmSize.GetWidth() + nDiff );
+ if ( aFmtFrmSize.GetWidth() < 0 )
+ aFmtFrmSize.SetWidth( -aFmtFrmSize.GetWidth() );
+ rParm.aShareFmts.SetSize( *pBox, aFmtFrmSize );
+
+ // The outer cells of the last row are responsible to adjust a surrounding cell.
+ // Last line check:
+ if ( pBox->GetUpper()->GetUpper() &&
+ pBox->GetUpper() != pBox->GetUpper()->GetUpper()->GetTabLines()
+ [pBox->GetUpper()->GetUpper()->GetTabLines().Count()-1])
+ {
+ pBox = 0;
+ }
+ else
+ {
+ // Middle cell check:
+ if ( pBox != pBox->GetUpper()->GetTabBoxes()[0] )
+ nDiff = nRightDiff;
+
+ if ( pBox != pBox->GetUpper()->GetTabBoxes()
+ [pBox->GetUpper()->GetTabBoxes().Count()-1] )
+ nDiff -= nRightDiff;
+
+ pBox = nDiff ? pBox->GetUpper()->GetUpper() : 0;
+ }
+ }
+ }
+ }
+}
+
+void lcl_ProcessBoxPtr( SwTableBox *pBox, SvPtrarr &rBoxArr,
+ sal_Bool bBefore )
+{
+ if ( pBox->GetTabLines().Count() )
+ {
+ const SwTableLines &rLines = pBox->GetTabLines();
+ for ( sal_uInt16 i = 0; i < rLines.Count(); ++i )
+ {
+ const SwTableBoxes &rBoxes = rLines[i]->GetTabBoxes();
+ for ( sal_uInt16 j = 0; j < rBoxes.Count(); ++j )
+ ::lcl_ProcessBoxPtr( rBoxes[j], rBoxArr, bBefore );
+ }
+ }
+ else if ( bBefore )
+ rBoxArr.Insert( (VoidPtr)pBox, 0 );
+ else
+ rBoxArr.Insert( (VoidPtr)pBox, rBoxArr.Count() );
+}
+
+void lcl_AdjustBox( SwTableBox *pBox, const long nDiff, Parm &rParm );
+
+void lcl_AdjustLines( SwTableLines &rLines, const long nDiff, Parm &rParm )
+{
+ for ( sal_uInt16 i = 0; i < rLines.Count(); ++i )
+ {
+ SwTableBox *pBox = rLines[i]->GetTabBoxes()
+ [rLines[i]->GetTabBoxes().Count()-1];
+ lcl_AdjustBox( pBox, nDiff, rParm );
+ }
+}
+
+void lcl_AdjustBox( SwTableBox *pBox, const long nDiff, Parm &rParm )
+{
+ if ( pBox->GetTabLines().Count() )
+ ::lcl_AdjustLines( pBox->GetTabLines(), nDiff, rParm );
+
+ //Groesse der Box anpassen.
+ SwFmtFrmSize aFmtFrmSize( pBox->GetFrmFmt()->GetFrmSize() );
+ aFmtFrmSize.SetWidth( aFmtFrmSize.GetWidth() + nDiff );
+
+ rParm.aShareFmts.SetSize( *pBox, aFmtFrmSize );
+}
+
+void SwTable::SetTabCols( const SwTabCols &rNew, const SwTabCols &rOld,
+ const SwTableBox *pStart, sal_Bool bCurRowOnly )
+{
+ CHECK_TABLE( *this )
+
+ SetHTMLTableLayout( 0 ); // MIB 9.7.97: HTML-Layout loeschen
+
+ // FME: Made rOld const. The caller is responsible for passing correct
+ // values of rOld. Therefore we do not have to call GetTabCols anymore:
+ //GetTabCols( rOld, pStart );
+
+ Parm aParm( rNew, rOld );
+
+ OSL_ENSURE( rOld.Count() == rNew.Count(), "Columnanzahl veraendert.");
+
+ //Raender verarbeiten. Groesse der Tabelle und ein paar Boxen mussen
+ //angepasst werden. Bei der Groesseneinstellung darf allerdings das
+ //Modify nicht verarbeitet werden - dieses wuerde alle Boxen anpassen
+ //und das koennen wir ueberhaupt nicht gebrauchen.
+ SwFrmFmt *pFmt = GetFrmFmt();
+ aParm.nOldWish = aParm.nNewWish = pFmt->GetFrmSize().GetWidth();
+ if ( (rOld.GetLeft() != rNew.GetLeft()) ||
+ (rOld.GetRight()!= rNew.GetRight()) )
+ {
+ LockModify();
+ {
+ SvxLRSpaceItem aLR( pFmt->GetLRSpace() );
+ SvxShadowItem aSh( pFmt->GetShadow() );
+
+ SwTwips nShRight = aSh.CalcShadowSpace( SHADOW_RIGHT );
+ SwTwips nShLeft = aSh.CalcShadowSpace( SHADOW_LEFT );
+
+ aLR.SetLeft ( rNew.GetLeft() - nShLeft );
+ aLR.SetRight( rNew.GetRightMax() - rNew.GetRight() - nShRight );
+ pFmt->SetFmtAttr( aLR );
+
+ //Die Ausrichtung der Tabelle muss entsprechend angepasst werden,
+ //das geschieht so, dass die Tabelle genauso stehenbleibt wie der
+ //Anwender sie gerade hingezuppelt hat.
+ SwFmtHoriOrient aOri( pFmt->GetHoriOrient() );
+ if(text::HoriOrientation::NONE != aOri.GetHoriOrient())
+ {
+ const sal_Bool bLeftDist = rNew.GetLeft() != nShLeft;
+ const sal_Bool bRightDist = rNew.GetRight() + nShRight != rNew.GetRightMax();
+ if(!bLeftDist && !bRightDist)
+ aOri.SetHoriOrient( text::HoriOrientation::FULL );
+ else if(!bRightDist && rNew.GetLeft() > nShLeft )
+ aOri.SetHoriOrient( text::HoriOrientation::RIGHT );
+ else if(!bLeftDist && rNew.GetRight() + nShRight < rNew.GetRightMax())
+ aOri.SetHoriOrient( text::HoriOrientation::LEFT );
+ else
+ aOri.SetHoriOrient( text::HoriOrientation::LEFT_AND_WIDTH );
+ }
+ pFmt->SetFmtAttr( aOri );
+ }
+ const long nAct = rOld.GetRight() - rOld.GetLeft(); // +1 why?
+ long nTabDiff = 0;
+
+ if ( rOld.GetLeft() != rNew.GetLeft() )
+ {
+ nTabDiff = rOld.GetLeft() - rNew.GetLeft();
+ nTabDiff *= aParm.nOldWish;
+ nTabDiff /= nAct;
+ }
+ if ( rOld.GetRight() != rNew.GetRight() )
+ {
+ long nDiff = rNew.GetRight() - rOld.GetRight();
+ nDiff *= aParm.nOldWish;
+ nDiff /= nAct;
+ nTabDiff += nDiff;
+ if( !IsNewModel() )
+ ::lcl_AdjustLines( GetTabLines(), nDiff, aParm );
+ }
+
+ //Groesse der Tabelle anpassen. Es muss beachtet werden, das die
+ //Tabelle gestrecht sein kann.
+ if ( nTabDiff )
+ {
+ aParm.nNewWish += nTabDiff;
+ if ( aParm.nNewWish < 0 )
+ aParm.nNewWish = USHRT_MAX; //Uuups! Eine Rolle rueckwaerts.
+ SwFmtFrmSize aSz( pFmt->GetFrmSize() );
+ if ( aSz.GetWidth() != aParm.nNewWish )
+ {
+ aSz.SetWidth( aParm.nNewWish );
+ aSz.SetWidthPercent( 0 );
+ pFmt->SetFmtAttr( aSz );
+ }
+ }
+ UnlockModify();
+ }
+
+ if( IsNewModel() )
+ NewSetTabCols( aParm, rNew, rOld, pStart, bCurRowOnly );
+ else
+ {
+ if ( bCurRowOnly )
+ {
+ //Um die aktuelle Zeile anzupassen muessen wir analog zu dem
+ //Verfahren zum fuellen der TabCols (siehe GetTabCols()) die
+ //Boxen der aktuellen Zeile abklappern.
+ //Leider muessen wir auch hier dafuer sorgen, dass die Boxen von
+ //hinten nach vorne bzw. von innen nach aussen veraendert werden.
+ //Der beste Weg hierzu scheint mir darin zu liegen die
+ //entsprechenden Boxen in einem PtrArray vorzumerken.
+
+ const SwTableBoxes &rBoxes = pStart->GetUpper()->GetTabBoxes();
+ for ( sal_uInt16 i = 0; i < rBoxes.Count(); ++i )
+ ::lcl_ProcessBoxPtr( rBoxes[i], aParm.aBoxArr, sal_False );
+
+ const SwTableLine *pLine = pStart->GetUpper()->GetUpper() ?
+ pStart->GetUpper()->GetUpper()->GetUpper() : 0;
+ const SwTableBox *pExcl = pStart->GetUpper()->GetUpper();
+ while ( pLine )
+ {
+ const SwTableBoxes &rBoxes2 = pLine->GetTabBoxes();
+ sal_Bool bBefore = sal_True;
+ for ( sal_uInt16 i = 0; i < rBoxes2.Count(); ++i )
+ {
+ if ( rBoxes2[i] != pExcl )
+ ::lcl_ProcessBoxPtr( rBoxes2[i], aParm.aBoxArr, bBefore );
+ else
+ bBefore = sal_False;
+ }
+ pExcl = pLine->GetUpper();
+ pLine = pLine->GetUpper() ? pLine->GetUpper()->GetUpper() : 0;
+ }
+ //Nachdem wir haufenweise Boxen (hoffentlich alle und in der richtigen
+ //Reihenfolge) eingetragen haben, brauchen diese nur noch rueckwaerts
+ //verarbeitet zu werden.
+ for ( int j = aParm.aBoxArr.Count()-1; j >= 0; --j )
+ {
+ SwTableBox *pBox = (SwTableBox*)aParm.aBoxArr[ static_cast< sal_uInt16 >(j)];
+ ::lcl_ProcessBoxSet( pBox, aParm );
+ }
+ }
+ else
+ { //Die gesamte Tabelle anzupassen ist 'einfach'.
+ //Es werden alle Boxen, die keine Lines mehr enthalten angepasst.
+ //Diese Boxen passen alle uebergeordneten Boxen entsprechend mit an.
+ //Um uns nicht selbst hereinzulegen muss natuerlich rueckwaerst
+ //gearbeitet werden!
+ SwTableLines &rLines = GetTabLines();
+ for ( int i = rLines.Count()-1; i >= 0; --i )
+ ::lcl_ProcessLine( rLines[ static_cast< sal_uInt16 >(i) ], aParm );
+ }
+ }
+
+#if OSL_DEBUG_LEVEL > 1
+ {
+// steht im tblrwcl.cxx
+extern void _CheckBoxWidth( const SwTableLine&, SwTwips );
+ // checke doch mal ob die Tabellen korrekte Breiten haben
+ SwTwips nSize = GetFrmFmt()->GetFrmSize().GetWidth();
+ for( sal_uInt16 n = 0; n < aLines.Count(); ++n )
+ _CheckBoxWidth( *aLines[ n ], nSize );
+ }
+#endif
+}
+
+typedef std::pair<sal_uInt16, sal_uInt16> ColChange;
+typedef std::list< ColChange > ChangeList;
+
+static void lcl_AdjustWidthsInLine( SwTableLine* pLine, ChangeList& rOldNew,
+ Parm& rParm, sal_uInt16 nColFuzzy )
+{
+ ChangeList::iterator pCurr = rOldNew.begin();
+ if( pCurr == rOldNew.end() )
+ return;
+ sal_uInt16 nCount = pLine->GetTabBoxes().Count();
+ sal_uInt16 i = 0;
+ SwTwips nBorder = 0;
+ SwTwips nRest = 0;
+ while( i < nCount )
+ {
+ SwTableBox* pBox = pLine->GetTabBoxes()[i++];
+ SwTwips nWidth = pBox->GetFrmFmt()->GetFrmSize().GetWidth();
+ SwTwips nNewWidth = nWidth - nRest;
+ nRest = 0;
+ nBorder += nWidth;
+ if( pCurr != rOldNew.end() && nBorder + nColFuzzy >= pCurr->first )
+ {
+ nBorder -= nColFuzzy;
+ while( pCurr != rOldNew.end() && nBorder > pCurr->first )
+ ++pCurr;
+ if( pCurr != rOldNew.end() )
+ {
+ nBorder += nColFuzzy;
+ if( nBorder + nColFuzzy >= pCurr->first )
+ {
+ if( pCurr->second == pCurr->first )
+ nRest = 0;
+ else
+ nRest = pCurr->second - nBorder;
+ nNewWidth += nRest;
+ ++pCurr;
+ }
+ }
+ }
+ if( nNewWidth != nWidth )
+ {
+ if( nNewWidth < 0 )
+ {
+ nRest += 1 - nNewWidth;
+ nNewWidth = 1;
+ }
+ SwFmtFrmSize aFmtFrmSize( pBox->GetFrmFmt()->GetFrmSize() );
+ aFmtFrmSize.SetWidth( nNewWidth );
+ rParm.aShareFmts.SetSize( *pBox, aFmtFrmSize );
+ }
+ }
+}
+
+static void lcl_CalcNewWidths( std::list<sal_uInt16> &rSpanPos, ChangeList& rChanges,
+ SwTableLine* pLine, long nWish, long nWidth, bool bTop )
+{
+ if( !rChanges.size() )
+ {
+ rSpanPos.clear();
+ return;
+ }
+ if( !rSpanPos.size() )
+ {
+ rChanges.clear();
+ return;
+ }
+ std::list<sal_uInt16> aNewSpanPos;
+ ChangeList aNewChanges;
+ ChangeList::iterator pCurr = rChanges.begin();
+ aNewChanges.push_back( *pCurr ); // Nullposition
+ std::list<sal_uInt16>::iterator pSpan = rSpanPos.begin();
+ sal_uInt16 nCurr = 0;
+ sal_uInt16 nOrgSum = 0;
+ bool bRowSpan = false;
+ sal_uInt16 nRowSpanCount = 0;
+ sal_uInt16 nCount = pLine->GetTabBoxes().Count();
+ for( sal_uInt16 nCurrBox = 0; nCurrBox < nCount; ++nCurrBox )
+ {
+ SwTableBox* pBox = pLine->GetTabBoxes()[nCurrBox];
+ SwTwips nCurrWidth = pBox->GetFrmFmt()->GetFrmSize().GetWidth();
+ const long nRowSpan = pBox->getRowSpan();
+ const bool bCurrRowSpan = bTop ? nRowSpan < 0 :
+ ( nRowSpan > 1 || nRowSpan < -1 );
+ if( bRowSpan || bCurrRowSpan )
+ aNewSpanPos.push_back( nRowSpanCount );
+ bRowSpan = bCurrRowSpan;
+ nOrgSum = (sal_uInt16)(nOrgSum + nCurrWidth);
+ sal_uInt64 nSum = nOrgSum;
+ nSum *= nWidth;
+ nSum /= nWish;
+ nSum *= nWish;
+ nSum /= nWidth;
+ sal_uInt16 nPos = (sal_uInt16)nSum;
+ while( pCurr != rChanges.end() && pCurr->first < nPos )
+ {
+#if OSL_DEBUG_LEVEL > 1
+ sal_uInt16 nTemp = pCurr->first;
+ nTemp = pCurr->second;
+#endif
+ ++nCurr;
+ ++pCurr;
+ }
+ bool bNew = true;
+ if( pCurr != rChanges.end() && pCurr->first <= nPos &&
+ pCurr->first != pCurr->second )
+ {
+ while( pSpan != rSpanPos.end() && *pSpan < nCurr )
+ ++pSpan;
+ if( pSpan != rSpanPos.end() && *pSpan == nCurr )
+ {
+ aNewChanges.push_back( *pCurr );
+ ++nRowSpanCount;
+ bNew = false;
+ }
+ }
+ if( bNew )
+ {
+ ColChange aTmp( nPos, nPos );
+ aNewChanges.push_back( aTmp );
+ ++nRowSpanCount;
+ }
+ }
+
+ pCurr = aNewChanges.begin();
+ ChangeList::iterator pLast = pCurr;
+ ChangeList::iterator pLeftMove = pCurr;
+ while( pCurr != aNewChanges.end() )
+ {
+ if( pLeftMove == pCurr )
+ {
+ while( ++pLeftMove != aNewChanges.end() && pLeftMove->first <= pLeftMove->second )
+ ;
+ }
+ if( pCurr->second == pCurr->first )
+ {
+ if( pLeftMove != aNewChanges.end() && pCurr->second > pLeftMove->second )
+ {
+ if( pLeftMove->first == pLast->first )
+ pCurr->second = pLeftMove->second;
+ else
+ {
+ sal_uInt64 nTmp = pCurr->first - pLast->first;
+ nTmp *= pLeftMove->second - pLast->second;
+ nTmp /= pLeftMove->first - pLast->first;
+ nTmp += pLast->second;
+ pCurr->second = (sal_uInt16)nTmp;
+ }
+ }
+ pLast = pCurr;
+ ++pCurr;
+ }
+ else if( pCurr->second > pCurr->first )
+ {
+ pLast = pCurr;
+ ++pCurr;
+ ChangeList::iterator pNext = pCurr;
+ while( pNext != pLeftMove && pNext->second == pNext->first &&
+ pNext->second < pLast->second )
+ ++pNext;
+ while( pCurr != pNext )
+ {
+ if( pNext == aNewChanges.end() || pNext->first == pLast->first )
+ pCurr->second = pLast->second;
+ else
+ {
+ sal_uInt64 nTmp = pCurr->first - pLast->first;
+ nTmp *= pNext->second - pLast->second;
+ nTmp /= pNext->first - pLast->first;
+ nTmp += pLast->second;
+ pCurr->second = (sal_uInt16)nTmp;
+ }
+ ++pCurr;
+ }
+ pLast = pCurr;
+ }
+ else
+ {
+ pLast = pCurr;
+ ++pCurr;
+ }
+ }
+
+ rChanges.clear();
+ ChangeList::iterator pCopy = aNewChanges.begin();
+ while( pCopy != aNewChanges.end() )
+ rChanges.push_back( *pCopy++ );
+ rSpanPos.clear();
+ std::list<sal_uInt16>::iterator pSpCopy = aNewSpanPos.begin();
+ while( pSpCopy != aNewSpanPos.end() )
+ rSpanPos.push_back( *pSpCopy++ );
+}
+
+void SwTable::NewSetTabCols( Parm &rParm, const SwTabCols &rNew,
+ const SwTabCols &rOld, const SwTableBox *pStart, sal_Bool bCurRowOnly )
+{
+#if OSL_DEBUG_LEVEL > 1
+ static int nCallCount = 0;
+ ++nCallCount;
+#endif
+ // First step: evaluate which lines have been moved/which widths changed
+ ChangeList aOldNew;
+ const long nNewWidth = rParm.rNew.GetRight() - rParm.rNew.GetLeft();
+ const long nOldWidth = rParm.rOld.GetRight() - rParm.rOld.GetLeft();
+ if( nNewWidth < 1 || nOldWidth < 1 )
+ return;
+ for( sal_uInt16 i = 0; i <= rOld.Count(); ++i )
+ {
+ sal_uInt64 nNewPos;
+ sal_uInt64 nOldPos;
+ if( i == rOld.Count() )
+ {
+ nOldPos = rParm.rOld.GetRight() - rParm.rOld.GetLeft();
+ nNewPos = rParm.rNew.GetRight() - rParm.rNew.GetLeft();
+ }
+ else
+ {
+ nOldPos = rOld[i] - rParm.rOld.GetLeft();
+ nNewPos = rNew[i] - rParm.rNew.GetLeft();
+ }
+ nNewPos *= rParm.nNewWish;
+ nNewPos /= nNewWidth;
+ nOldPos *= rParm.nOldWish;
+ nOldPos /= nOldWidth;
+ if( nOldPos != nNewPos && nNewPos > 0 && nOldPos > 0 )
+ {
+ ColChange aChg( (sal_uInt16)nOldPos, (sal_uInt16)nNewPos );
+ aOldNew.push_back( aChg );
+ }
+ }
+ // Finished first step
+ int nCount = aOldNew.size();
+ if( !nCount )
+ return; // no change, nothing to do
+ SwTableLines &rLines = GetTabLines();
+ if( bCurRowOnly )
+ {
+ const SwTableLine* pCurrLine = pStart->GetUpper();
+ sal_uInt16 nCurr = rLines.C40_GETPOS( SwTableLine, pCurrLine );
+ if( nCurr >= USHRT_MAX )
+ return;
+
+ ColChange aChg( 0, 0 );
+ aOldNew.push_front( aChg );
+ std::list<sal_uInt16> aRowSpanPos;
+ if( nCurr )
+ {
+ ChangeList aCopy;
+ ChangeList::iterator pCop = aOldNew.begin();
+ sal_uInt16 nPos = 0;
+ while( pCop != aOldNew.end() )
+ {
+ aCopy.push_back( *pCop );
+ ++pCop;
+ aRowSpanPos.push_back( nPos++ );
+ }
+ lcl_CalcNewWidths( aRowSpanPos, aCopy, rLines[nCurr],
+ rParm.nOldWish, nOldWidth, true );
+ bool bGoOn = aRowSpanPos.size() > 0;
+ sal_uInt16 j = nCurr;
+ while( bGoOn )
+ {
+ lcl_CalcNewWidths( aRowSpanPos, aCopy, rLines[--j],
+ rParm.nOldWish, nOldWidth, true );
+ lcl_AdjustWidthsInLine( rLines[j], aCopy, rParm, 0 );
+ bGoOn = aRowSpanPos.size() > 0 && j > 0;
+ };
+ aRowSpanPos.clear();
+ }
+ if( nCurr+1 < rLines.Count() )
+ {
+ ChangeList aCopy;
+ ChangeList::iterator pCop = aOldNew.begin();
+ sal_uInt16 nPos = 0;
+ while( pCop != aOldNew.end() )
+ {
+ aCopy.push_back( *pCop );
+ ++pCop;
+ aRowSpanPos.push_back( nPos++ );
+ }
+ lcl_CalcNewWidths( aRowSpanPos, aCopy, rLines[nCurr],
+ rParm.nOldWish, nOldWidth, false );
+ bool bGoOn = aRowSpanPos.size() > 0;
+ sal_uInt16 j = nCurr;
+ while( bGoOn )
+ {
+ lcl_CalcNewWidths( aRowSpanPos, aCopy, rLines[++j],
+ rParm.nOldWish, nOldWidth, false );
+ lcl_AdjustWidthsInLine( rLines[j], aCopy, rParm, 0 );
+ bGoOn = aRowSpanPos.size() > 0 && j+1 < rLines.Count();
+ };
+ }
+ ::lcl_AdjustWidthsInLine( rLines[nCurr], aOldNew, rParm, 1 );
+ }
+ else for( sal_uInt16 i = 0; i < rLines.Count(); ++i )
+ ::lcl_AdjustWidthsInLine( rLines[i], aOldNew, rParm, COLFUZZY );
+ CHECK_TABLE( *this )
+}
+
+
+/*************************************************************************
+|*
+|* const SwTableBox* SwTable::GetTblBox( const Strn?ng& rName ) const
+|* gebe den Pointer auf die benannte Box zurueck.
+|*
+|*************************************************************************/
+
+sal_Bool IsValidRowName( const String& rStr )
+{
+ sal_Bool bIsValid = sal_True;
+ xub_StrLen nLen = rStr.Len();
+ for (xub_StrLen i = 0; i < nLen && bIsValid; ++i)
+ {
+ const sal_Unicode cChar = rStr.GetChar(i);
+ if (cChar < '0' || cChar > '9')
+ bIsValid = sal_False;
+ }
+ return bIsValid;
+}
+
+// --> OD 2007-08-03 #i80314#
+// add 3rd parameter and its handling
+sal_uInt16 SwTable::_GetBoxNum( String& rStr, sal_Bool bFirstPart,
+ const bool bPerformValidCheck )
+{
+ sal_uInt16 nRet = 0;
+ xub_StrLen nPos = 0;
+ if( bFirstPart ) // sal_True == column; sal_False == row
+ {
+ // die 1. ist mit Buchstaben addressiert!
+ sal_Unicode cChar;
+ sal_Bool bFirst = sal_True;
+ while( 0 != ( cChar = rStr.GetChar( nPos )) &&
+ ( (cChar >= 'A' && cChar <= 'Z') ||
+ (cChar >= 'a' && cChar <= 'z') ) )
+ {
+ if( (cChar -= 'A') >= 26 )
+ cChar -= 'a' - '[';
+ if( bFirst )
+ bFirst = sal_False;
+ else
+ ++nRet;
+ nRet = nRet * 52 + cChar;
+ ++nPos;
+ }
+ rStr.Erase( 0, nPos ); // Zeichen aus dem String loeschen
+ }
+ else if( STRING_NOTFOUND == ( nPos = rStr.Search( aDotStr ) ))
+ {
+ nRet = 0;
+ if ( !bPerformValidCheck || IsValidRowName( rStr ) )
+ {
+ nRet = static_cast<sal_uInt16>(rStr.ToInt32());
+ }
+ rStr.Erase();
+ }
+ else
+ {
+ nRet = 0;
+ String aTxt( rStr.Copy( 0, nPos ) );
+ if ( !bPerformValidCheck || IsValidRowName( aTxt ) )
+ {
+ nRet = static_cast<sal_uInt16>(aTxt.ToInt32());
+ }
+ rStr.Erase( 0, nPos+1 );
+ }
+ return nRet;
+}
+// <--
+
+// --> OD 2007-08-03 #i80314#
+// add 2nd parameter and its handling
+const SwTableBox* SwTable::GetTblBox( const String& rName,
+ const bool bPerformValidCheck ) const
+{
+ const SwTableBox* pBox = 0;
+ const SwTableLine* pLine;
+ const SwTableLines* pLines;
+ const SwTableBoxes* pBoxes;
+
+ sal_uInt16 nLine, nBox;
+ String aNm( rName );
+ while( aNm.Len() )
+ {
+ nBox = SwTable::_GetBoxNum( aNm, 0 == pBox, bPerformValidCheck );
+ // erste Box ?
+ if( !pBox )
+ pLines = &GetTabLines();
+ else
+ {
+ pLines = &pBox->GetTabLines();
+ if( nBox )
+ --nBox;
+ }
+
+ nLine = SwTable::_GetBoxNum( aNm, sal_False, bPerformValidCheck );
+
+ // bestimme die Line
+ if( !nLine || nLine > pLines->Count() )
+ return 0;
+ pLine = (*pLines)[ nLine-1 ];
+
+ // bestimme die Box
+ pBoxes = &pLine->GetTabBoxes();
+ if( nBox >= pBoxes->Count() )
+ return 0;
+ pBox = (*pBoxes)[ nBox ];
+ }
+
+ // abpruefen, ob die gefundene Box auch wirklich eine Inhaltstragende
+ // Box ist ??
+ if( pBox && !pBox->GetSttNd() )
+ {
+ OSL_FAIL( "Box ohne Inhalt, suche die naechste !!" );
+ // "herunterfallen lassen" bis zur ersten Box
+ while( pBox->GetTabLines().Count() )
+ pBox = pBox->GetTabLines()[0]->GetTabBoxes()[0];
+ }
+ return pBox;
+}
+
+SwTableBox* SwTable::GetTblBox( sal_uLong nSttIdx )
+{
+ //MA: Zur Optimierung nicht immer umstaendlich das ganze SortArray abhuenern.
+ //OS: #102675# converting text to table tries und certain conditions
+ // to ask for a table box of a table that is not yet having a format
+ if(!GetFrmFmt())
+ return 0;
+ SwTableBox* pRet = 0;
+ SwNodes& rNds = GetFrmFmt()->GetDoc()->GetNodes();
+ sal_uLong nIndex = nSttIdx + 1;
+ SwCntntNode* pCNd = 0;
+ SwTableNode* pTblNd = 0;
+
+ while ( nIndex < rNds.Count() )
+ {
+ pTblNd = rNds[ nIndex ]->GetTableNode();
+ if ( pTblNd )
+ break;
+
+ pCNd = rNds[ nIndex ]->GetCntntNode();
+ if ( pCNd )
+ break;
+
+ ++nIndex;
+ }
+
+ if ( pCNd || pTblNd )
+ {
+ SwModify* pModify = pCNd;
+ // --> FME 2007-3-26 #144862# Better handling of table in table:
+ if ( pTblNd && pTblNd->GetTable().GetFrmFmt() )
+ pModify = pTblNd->GetTable().GetFrmFmt();
+ // <--
+
+ SwFrm* pFrm = SwIterator<SwFrm,SwModify>::FirstElement( *pModify );
+ while ( pFrm && !pFrm->IsCellFrm() )
+ pFrm = pFrm->GetUpper();
+ if ( pFrm )
+ pRet = (SwTableBox*)((SwCellFrm*)pFrm)->GetTabBox();
+ }
+
+ //Falls es das Layout noch nicht gibt oder sonstwie etwas schieft geht.
+ if ( !pRet )
+ {
+ for( sal_uInt16 n = aSortCntBoxes.Count(); n; )
+ if( aSortCntBoxes[ --n ]->GetSttIdx() == nSttIdx )
+ return aSortCntBoxes[ n ];
+ }
+ return pRet;
+}
+
+sal_Bool SwTable::IsTblComplex() const
+{
+ // returnt sal_True wenn sich in der Tabelle Verschachtelungen befinden
+ // steht eine Box nicht in der obersten Line, da wurde gesplittet/
+ // gemergt und die Struktur ist komplexer.
+ for( sal_uInt16 n = 0; n < aSortCntBoxes.Count(); ++n )
+ if( aSortCntBoxes[ n ]->GetUpper()->GetUpper() )
+ return sal_True;
+ return sal_False;
+}
+
+
+
+/*************************************************************************
+|*
+|* SwTableLine::SwTableLine()
+|*
+|*************************************************************************/
+SwTableLine::SwTableLine( SwTableLineFmt *pFmt, sal_uInt16 nBoxes,
+ SwTableBox *pUp )
+ : SwClient( pFmt ),
+ aBoxes( (sal_uInt8)nBoxes, 1 ),
+ pUpper( pUp )
+{
+}
+
+SwTableLine::~SwTableLine()
+{
+ // ist die TabelleLine der letzte Client im FrameFormat, kann dieses
+ // geloescht werden
+ SwModify* pMod = GetFrmFmt();
+ pMod->Remove( this ); // austragen,
+ if( !pMod->GetDepends() )
+ delete pMod; // und loeschen
+}
+
+/*************************************************************************
+|*
+|* SwTableLine::ClaimFrmFmt(), ChgFrmFmt()
+|*
+|*************************************************************************/
+SwFrmFmt* SwTableLine::ClaimFrmFmt()
+{
+ // This method makes sure that this object is an exclusive SwTableLine client
+ // of an SwTableLineFmt object
+ // If other SwTableLine objects currently listen to the same SwTableLineFmt as
+ // this one, something needs to be done
+ SwTableLineFmt *pRet = (SwTableLineFmt*)GetFrmFmt();
+ SwIterator<SwTableLine,SwFmt> aIter( *pRet );
+ for( SwTableLine* pLast = aIter.First(); pLast; pLast = aIter.Next() )
+ {
+ if ( pLast != this )
+ {
+ // found another SwTableLine that is a client of the current Fmt
+ // create a new Fmt as a copy and use it for this object
+ SwTableLineFmt *pNewFmt = pRet->GetDoc()->MakeTableLineFmt();
+ *pNewFmt = *pRet;
+
+ // register SwRowFrms that know me as clients at the new Fmt
+ SwIterator<SwRowFrm,SwFmt> aFrmIter( *pRet );
+ for( SwRowFrm* pFrm = aFrmIter.First(); pFrm; pFrm = aFrmIter.Next() )
+ if( pFrm->GetTabLine() == this )
+ pFrm->RegisterToFormat( *pNewFmt );
+
+ // register myself
+ pNewFmt->Add( this );
+ pRet = pNewFmt;
+ break;
+ }
+ }
+
+ return pRet;
+}
+
+void SwTableLine::ChgFrmFmt( SwTableLineFmt *pNewFmt )
+{
+ SwFrmFmt *pOld = GetFrmFmt();
+ SwIterator<SwRowFrm,SwFmt> aIter( *pOld );
+
+ //Erstmal die Frms ummelden.
+ for( SwRowFrm* pRow = aIter.First(); pRow; pRow = aIter.Next() )
+ {
+ if( pRow->GetTabLine() == this )
+ {
+ pRow->RegisterToFormat( *pNewFmt );
+
+ pRow->InvalidateSize();
+ pRow->_InvalidatePrt();
+ pRow->SetCompletePaint();
+ pRow->ReinitializeFrmSizeAttrFlags();
+
+ // --> FME 2004-10-27 #i35063#
+ // consider 'split row allowed' attribute
+ SwTabFrm* pTab = pRow->FindTabFrm();
+ bool bInFollowFlowRow = false;
+ const bool bInFirstNonHeadlineRow = pTab->IsFollow() &&
+ pRow == pTab->GetFirstNonHeadlineRow();
+ if ( bInFirstNonHeadlineRow ||
+ !pRow->GetNext() ||
+ 0 != ( bInFollowFlowRow = pRow->IsInFollowFlowRow() ) ||
+ 0 != pRow->IsInSplitTableRow() )
+ {
+ if ( bInFirstNonHeadlineRow || bInFollowFlowRow )
+ pTab = pTab->FindMaster();
+
+ pTab->SetRemoveFollowFlowLinePending( sal_True );
+ pTab->InvalidatePos();
+ }
+ // <--
+ }
+ }
+
+ //Jetzt noch mich selbst ummelden.
+ pNewFmt->Add( this );
+
+ if ( !pOld->GetDepends() )
+ delete pOld;
+}
+
+SwTwips SwTableLine::GetTableLineHeight( bool& bLayoutAvailable ) const
+{
+ SwTwips nRet = 0;
+ bLayoutAvailable = false;
+ SwIterator<SwRowFrm,SwFmt> aIter( *GetFrmFmt() );
+ // A row could appear several times in headers/footers so only one chain of master/follow tables
+ // will be accepted...
+ const SwTabFrm* pChain = NULL; // My chain
+ for( SwRowFrm* pLast = aIter.First(); pLast; pLast = aIter.Next() )
+ {
+ if( pLast->GetTabLine() == this )
+ {
+ const SwTabFrm* pTab = pLast->FindTabFrm();
+ bLayoutAvailable = ( pTab && pTab->IsVertical() ) ?
+ ( 0 < pTab->Frm().Height() ) :
+ ( 0 < pTab->Frm().Width() );
+
+ // The first one defines the chain, if a chain is defined, only members of the chain
+ // will be added.
+ if( !pChain || pChain->IsAnFollow( pTab ) || pTab->IsAnFollow( pChain ) )
+ {
+ pChain = pTab; // defines my chain (even it is already)
+ if( pTab->IsVertical() )
+ nRet += pLast->Frm().Width();
+ else
+ nRet += pLast->Frm().Height();
+ // Optimization, if there are no master/follows in my chain, nothing more to add
+ if( !pTab->HasFollow() && !pTab->IsFollow() )
+ break;
+ // This is not an optimization, this is necessary to avoid double additions of
+ // repeating rows
+ if( pTab->IsInHeadline(*pLast) )
+ break;
+ }
+ }
+ }
+ return nRet;
+}
+
+/*************************************************************************
+|*
+|* SwTableBox::SwTableBox()
+|*
+|*************************************************************************/
+SwTableBox::SwTableBox( SwTableBoxFmt* pFmt, sal_uInt16 nLines, SwTableLine *pUp )
+ : SwClient( 0 ),
+ aLines( (sal_uInt8)nLines, 1 ),
+ pSttNd( 0 ),
+ pUpper( pUp ),
+ pImpl( 0 )
+{
+ CheckBoxFmt( pFmt )->Add( this );
+}
+
+SwTableBox::SwTableBox( SwTableBoxFmt* pFmt, const SwNodeIndex &rIdx,
+ SwTableLine *pUp )
+ : SwClient( 0 ),
+ aLines( 0, 0 ),
+ pUpper( pUp ),
+ pImpl( 0 )
+{
+ CheckBoxFmt( pFmt )->Add( this );
+
+ pSttNd = rIdx.GetNode().GetStartNode();
+
+ // an der Table eintragen
+ const SwTableNode* pTblNd = pSttNd->FindTableNode();
+ OSL_ENSURE( pTblNd, "in welcher Tabelle steht denn die Box?" );
+ SwTableSortBoxes& rSrtArr = (SwTableSortBoxes&)pTblNd->GetTable().
+ GetTabSortBoxes();
+ SwTableBox* p = this; // error: &this
+ rSrtArr.Insert( p ); // eintragen
+}
+
+SwTableBox::SwTableBox( SwTableBoxFmt* pFmt, const SwStartNode& rSttNd, SwTableLine *pUp ) :
+ SwClient( 0 ),
+ aLines( 0, 0 ),
+ pSttNd( &rSttNd ),
+ pUpper( pUp ),
+ pImpl( 0 )
+{
+ CheckBoxFmt( pFmt )->Add( this );
+
+ // an der Table eintragen
+ const SwTableNode* pTblNd = pSttNd->FindTableNode();
+ OSL_ENSURE( pTblNd, "in welcher Tabelle steht denn die Box?" );
+ SwTableSortBoxes& rSrtArr = (SwTableSortBoxes&)pTblNd->GetTable().
+ GetTabSortBoxes();
+ SwTableBox* p = this; // error: &this
+ rSrtArr.Insert( p ); // eintragen
+}
+
+SwTableBox::~SwTableBox()
+{
+ // Inhaltstragende Box ?
+ if( !GetFrmFmt()->GetDoc()->IsInDtor() && pSttNd )
+ {
+ // an der Table austragen
+ const SwTableNode* pTblNd = pSttNd->FindTableNode();
+ OSL_ENSURE( pTblNd, "in welcher Tabelle steht denn die Box?" );
+ SwTableSortBoxes& rSrtArr = (SwTableSortBoxes&)pTblNd->GetTable().
+ GetTabSortBoxes();
+ SwTableBox *p = this; // error: &this
+ rSrtArr.Remove( p ); // austragen
+ }
+
+ // ist die TabelleBox der letzte Client im FrameFormat, kann dieses
+ // geloescht werden
+ SwModify* pMod = GetFrmFmt();
+ pMod->Remove( this ); // austragen,
+ if( !pMod->GetDepends() )
+ delete pMod; // und loeschen
+
+ delete pImpl;
+}
+
+SwTableBoxFmt* SwTableBox::CheckBoxFmt( SwTableBoxFmt* pFmt )
+{
+ // sollte das Format eine Formel oder einen Value tragen, dann muss die
+ // Box alleine am Format haengen. Ggfs. muss ein neues angelegt werden.
+ if( SFX_ITEM_SET == pFmt->GetItemState( RES_BOXATR_VALUE, sal_False ) ||
+ SFX_ITEM_SET == pFmt->GetItemState( RES_BOXATR_FORMULA, sal_False ) )
+ {
+ SwTableBox* pOther = SwIterator<SwTableBox,SwFmt>::FirstElement( *pFmt );
+ if( pOther )
+ {
+ SwTableBoxFmt* pNewFmt = pFmt->GetDoc()->MakeTableBoxFmt();
+ pNewFmt->LockModify();
+ *pNewFmt = *pFmt;
+
+ // Values und Formeln entfernen
+ pNewFmt->ResetFmtAttr( RES_BOXATR_FORMULA, RES_BOXATR_VALUE );
+ pNewFmt->UnlockModify();
+
+ pFmt = pNewFmt;
+ }
+ }
+ return pFmt;
+}
+
+/*************************************************************************
+|*
+|* SwTableBox::ClaimFrmFmt(), ChgFrmFmt()
+|*
+|*************************************************************************/
+SwFrmFmt* SwTableBox::ClaimFrmFmt()
+{
+ // This method makes sure that this object is an exclusive SwTableBox client
+ // of an SwTableBoxFmt object
+ // If other SwTableBox objects currently listen to the same SwTableBoxFmt as
+ // this one, something needs to be done
+ SwTableBoxFmt *pRet = (SwTableBoxFmt*)GetFrmFmt();
+ SwIterator<SwTableBox,SwFmt> aIter( *pRet );
+ for( SwTableBox* pLast = aIter.First(); pLast; pLast = aIter.Next() )
+ {
+ if ( pLast != this )
+ {
+ // Found another SwTableBox object
+ // create a new Fmt as a copy and assign me to it
+ // don't copy values and formulas
+ SwTableBoxFmt* pNewFmt = pRet->GetDoc()->MakeTableBoxFmt();
+ pNewFmt->LockModify();
+ *pNewFmt = *pRet;
+ pNewFmt->ResetFmtAttr( RES_BOXATR_FORMULA, RES_BOXATR_VALUE );
+ pNewFmt->UnlockModify();
+
+ // re-register SwCellFrm objects that know me
+ SwIterator<SwCellFrm,SwFmt> aFrmIter( *pRet );
+ for( SwCellFrm* pCell = aFrmIter.First(); pCell; pCell = aFrmIter.Next() )
+ if( pCell->GetTabBox() == this )
+ pCell->RegisterToFormat( *pNewFmt );
+
+ // re-register myself
+ pNewFmt->Add( this );
+ pRet = pNewFmt;
+ break;
+ }
+ }
+ return pRet;
+}
+
+void SwTableBox::ChgFrmFmt( SwTableBoxFmt* pNewFmt )
+{
+ SwFrmFmt *pOld = GetFrmFmt();
+ SwIterator<SwCellFrm,SwFmt> aIter( *pOld );
+
+ //Erstmal die Frms ummelden.
+ for( SwCellFrm* pCell = aIter.First(); pCell; pCell = aIter.Next() )
+ {
+ if( pCell->GetTabBox() == this )
+ {
+ pCell->RegisterToFormat( *pNewFmt );
+ pCell->InvalidateSize();
+ pCell->_InvalidatePrt();
+ pCell->SetCompletePaint();
+ pCell->SetDerivedVert( sal_False );
+ pCell->CheckDirChange();
+
+ // --> FME 2005-04-15 #i47489#
+ // make sure that the row will be formatted, in order
+ // to have the correct Get(Top|Bottom)MarginForLowers values
+ // set at the row.
+ const SwTabFrm* pTab = pCell->FindTabFrm();
+ if ( pTab && pTab->IsCollapsingBorders() )
+ {
+ SwFrm* pRow = pCell->GetUpper();
+ pRow->_InvalidateSize();
+ pRow->_InvalidatePrt();
+ }
+ // <--
+ }
+ }
+
+ //Jetzt noch mich selbst ummelden.
+ pNewFmt->Add( this );
+
+ if( !pOld->GetDepends() )
+ delete pOld;
+}
+
+/*************************************************************************
+|*
+|* String SwTableBox::GetName() const
+|* gebe den Namen dieser Box zurueck. Dieser wird dynamisch bestimmt
+|* und ergibt sich aus der Position in den Lines/Boxen/Tabelle
+|*
+|*************************************************************************/
+void lcl_GetTblBoxColStr( sal_uInt16 nCol, String& rNm )
+{
+ const sal_uInt16 coDiff = 52; // 'A'-'Z' 'a' - 'z'
+ sal_uInt16 nCalc;
+
+ do {
+ nCalc = nCol % coDiff;
+ if( nCalc >= 26 )
+ rNm.Insert( sal_Unicode('a' - 26 + nCalc ), 0 );
+ else
+ rNm.Insert( sal_Unicode('A' + nCalc ), 0 );
+
+ if( 0 == (nCol = nCol - nCalc) )
+ break;
+ nCol /= coDiff;
+ --nCol;
+ } while( 1 );
+}
+
+String SwTableBox::GetName() const
+{
+ if( !pSttNd ) // keine Content Box ??
+ {
+ // die naechste erste Box suchen ??
+ return aEmptyStr;
+ }
+
+ const SwTable& rTbl = pSttNd->FindTableNode()->GetTable();
+ sal_uInt16 nPos;
+ String sNm, sTmp;
+ const SwTableBox* pBox = this;
+ do {
+ const SwTableBoxes* pBoxes = &pBox->GetUpper()->GetTabBoxes();
+ const SwTableLine* pLine = pBox->GetUpper();
+ // auf oberstere Ebene ?
+ const SwTableLines* pLines = pLine->GetUpper()
+ ? &pLine->GetUpper()->GetTabLines() : &rTbl.GetTabLines();
+
+ sTmp = String::CreateFromInt32( nPos = pLines->GetPos( pLine ) + 1 );
+ if( sNm.Len() )
+ sNm.Insert( aDotStr, 0 ).Insert( sTmp, 0 );
+ else
+ sNm = sTmp;
+
+ sTmp = String::CreateFromInt32(( nPos = pBoxes->GetPos( pBox )) + 1 );
+ if( 0 != ( pBox = pLine->GetUpper()) )
+ sNm.Insert( aDotStr, 0 ).Insert( sTmp, 0 );
+ else
+ ::lcl_GetTblBoxColStr( nPos, sNm );
+
+ } while( pBox );
+ return sNm;
+}
+
+sal_Bool SwTableBox::IsInHeadline( const SwTable* pTbl ) const
+{
+ if( !GetUpper() ) // sollte nur beim Merge vorkommen.
+ return sal_False;
+
+ if( !pTbl )
+ pTbl = &pSttNd->FindTableNode()->GetTable();
+
+ const SwTableLine* pLine = GetUpper();
+ while( pLine->GetUpper() )
+ pLine = pLine->GetUpper()->GetUpper();
+
+ // Headerline?
+ return pTbl->GetTabLines()[ 0 ] == pLine;
+}
+
+#if OSL_DEBUG_LEVEL > 1
+
+sal_uLong SwTableBox::GetSttIdx() const
+{
+ return pSttNd ? pSttNd->GetIndex() : 0;
+}
+#endif
+
+ // erfrage vom Client Informationen
+sal_Bool SwTable::GetInfo( SfxPoolItem& rInfo ) const
+{
+ switch( rInfo.Which() )
+ {
+ case RES_AUTOFMT_DOCNODE:
+ {
+ const SwTableNode* pTblNode = GetTableNode();
+ if( pTblNode && &pTblNode->GetNodes() == ((SwAutoFmtGetDocNode&)rInfo).pNodes )
+ {
+ if ( aSortCntBoxes.Count() )
+ {
+ SwNodeIndex aIdx( *aSortCntBoxes[ 0 ]->GetSttNd() );
+ ((SwAutoFmtGetDocNode&)rInfo).pCntntNode =
+ GetFrmFmt()->GetDoc()->GetNodes().GoNext( &aIdx );
+ }
+ return sal_False;
+ }
+ break;
+ }
+ case RES_FINDNEARESTNODE:
+ if( GetFrmFmt() && ((SwFmtPageDesc&)GetFrmFmt()->GetFmtAttr(
+ RES_PAGEDESC )).GetPageDesc() &&
+ aSortCntBoxes.Count() &&
+ aSortCntBoxes[ 0 ]->GetSttNd()->GetNodes().IsDocNodes() )
+ ((SwFindNearestNode&)rInfo).CheckNode( *
+ aSortCntBoxes[ 0 ]->GetSttNd()->FindTableNode() );
+ break;
+
+ case RES_CONTENT_VISIBLE:
+ {
+ ((SwPtrMsgPoolItem&)rInfo).pObject = SwIterator<SwFrm,SwFmt>::FirstElement( *GetFrmFmt() );
+ }
+ return sal_False;
+ }
+ return sal_True;
+}
+
+SwTable * SwTable::FindTable( SwFrmFmt const*const pFmt )
+{
+ return (pFmt)
+ ? SwIterator<SwTable,SwFmt>::FirstElement(*pFmt)
+ : 0;
+}
+
+SwTableNode* SwTable::GetTableNode() const
+{
+ return GetTabSortBoxes().Count() ?
+ (SwTableNode*)GetTabSortBoxes()[ 0 ]->GetSttNd()->FindTableNode() :
+ pTableNode;
+}
+
+void SwTable::SetRefObject( SwServerObject* pObj )
+{
+ if( refObj.Is() )
+ refObj->Closed();
+
+ refObj = pObj;
+}
+
+
+void SwTable::SetHTMLTableLayout( SwHTMLTableLayout *p )
+{
+ delete pHTMLLayout;
+ pHTMLLayout = p;
+}
+
+void ChgTextToNum( SwTableBox& rBox, const String& rTxt, const Color* pCol,
+ sal_Bool bChgAlign )
+{
+ sal_uLong nNdPos = rBox.IsValidNumTxtNd( sal_True );
+ ChgTextToNum( rBox,rTxt,pCol,bChgAlign,nNdPos);
+}
+void ChgTextToNum( SwTableBox& rBox, const String& rTxt, const Color* pCol,
+ sal_Bool bChgAlign,sal_uLong nNdPos )
+{
+
+ if( ULONG_MAX != nNdPos )
+ {
+ SwDoc* pDoc = rBox.GetFrmFmt()->GetDoc();
+ SwTxtNode* pTNd = pDoc->GetNodes()[ nNdPos ]->GetTxtNode();
+ const SfxPoolItem* pItem;
+
+ // Ausrichtung umsetzen
+ if( bChgAlign )
+ {
+ pItem = &pTNd->SwCntntNode::GetAttr( RES_PARATR_ADJUST );
+ SvxAdjust eAdjust = ((SvxAdjustItem*)pItem)->GetAdjust();
+ if( SVX_ADJUST_LEFT == eAdjust || SVX_ADJUST_BLOCK == eAdjust )
+ {
+ SvxAdjustItem aAdjust( *(SvxAdjustItem*)pItem );
+ aAdjust.SetAdjust( SVX_ADJUST_RIGHT );
+ pTNd->SetAttr( aAdjust );
+ }
+ }
+
+ // Farbe umsetzen oder "Benutzer Farbe" sichern
+ if( !pTNd->GetpSwAttrSet() || SFX_ITEM_SET != pTNd->GetpSwAttrSet()->
+ GetItemState( RES_CHRATR_COLOR, sal_False, &pItem ))
+ pItem = 0;
+
+ const Color* pOldNumFmtColor = rBox.GetSaveNumFmtColor();
+ const Color* pNewUserColor = pItem ? &((SvxColorItem*)pItem)->GetValue() : 0;
+
+ if( ( pNewUserColor && pOldNumFmtColor &&
+ *pNewUserColor == *pOldNumFmtColor ) ||
+ ( !pNewUserColor && !pOldNumFmtColor ))
+ {
+ // User Color nicht veraendern aktuellen Werte setzen
+ // ggfs. die alte NumFmtColor loeschen
+ if( pCol )
+ // ggfs. die Farbe setzen
+ pTNd->SetAttr( SvxColorItem( *pCol, RES_CHRATR_COLOR ));
+ else if( pItem )
+ {
+ pNewUserColor = rBox.GetSaveUserColor();
+ if( pNewUserColor )
+ pTNd->SetAttr( SvxColorItem( *pNewUserColor, RES_CHRATR_COLOR ));
+ else
+ pTNd->ResetAttr( RES_CHRATR_COLOR );
+ }
+ }
+ else
+ {
+ // User Color merken, ggfs. die NumFormat Color setzen, aber
+ // nie die Farbe zurueck setzen
+ rBox.SetSaveUserColor( pNewUserColor );
+
+ if( pCol )
+ // ggfs. die Farbe setzen
+ pTNd->SetAttr( SvxColorItem( *pCol, RES_CHRATR_COLOR ));
+
+ }
+ rBox.SetSaveNumFmtColor( pCol );
+
+ if( pTNd->GetTxt() != rTxt )
+ {
+ // Text austauschen
+ //JP 15.09.98: Bug 55741 - Tabs beibehalten (vorne und hinten!)
+ const String& rOrig = pTNd->GetTxt();
+ xub_StrLen n;
+
+ for( n = 0; n < rOrig.Len() && '\x9' == rOrig.GetChar( n ); ++n )
+ ;
+ for( ; n < rOrig.Len() && '\x01' == rOrig.GetChar( n ); ++n )
+ ;
+ SwIndex aIdx( pTNd, n );
+ for( n = rOrig.Len(); n && '\x9' == rOrig.GetChar( --n ); )
+ ;
+ n -= aIdx.GetIndex() - 1;
+
+ //JP 06.04.99: Bug 64321 - DontExpand-Flags vorm Austauschen
+ // zuruecksetzen, damit sie wieder aufgespannt werden
+ {
+ SwIndex aResetIdx( aIdx, n );
+ pTNd->DontExpandFmt( aResetIdx, sal_False, sal_False );
+ }
+
+ if( !pDoc->IsIgnoreRedline() && pDoc->GetRedlineTbl().Count() )
+ {
+ SwPaM aTemp(*pTNd, 0, *pTNd, rOrig.Len());
+ pDoc->DeleteRedline(aTemp, true, USHRT_MAX);
+ }
+
+ pTNd->EraseText( aIdx, n,
+ IDocumentContentOperations::INS_EMPTYEXPAND );
+ pTNd->InsertText( rTxt, aIdx,
+ IDocumentContentOperations::INS_EMPTYEXPAND );
+
+ if( pDoc->IsRedlineOn() )
+ {
+ SwPaM aTemp(*pTNd, 0, *pTNd, rTxt.Len());
+ pDoc->AppendRedline(new SwRedline(nsRedlineType_t::REDLINE_INSERT, aTemp), true);
+ }
+ }
+
+ // vertikale Ausrichtung umsetzen
+ if( bChgAlign &&
+ ( SFX_ITEM_SET != rBox.GetFrmFmt()->GetItemState(
+ RES_VERT_ORIENT, sal_True, &pItem ) ||
+ text::VertOrientation::TOP == ((SwFmtVertOrient*)pItem)->GetVertOrient() ))
+ {
+ rBox.GetFrmFmt()->SetFmtAttr( SwFmtVertOrient( 0, text::VertOrientation::BOTTOM ));
+ }
+ }
+}
+
+void ChgNumToText( SwTableBox& rBox, sal_uLong nFmt )
+{
+ sal_uLong nNdPos = rBox.IsValidNumTxtNd( sal_False );
+ if( ULONG_MAX != nNdPos )
+ {
+ SwDoc* pDoc = rBox.GetFrmFmt()->GetDoc();
+ SwTxtNode* pTNd = pDoc->GetNodes()[ nNdPos ]->GetTxtNode();
+ sal_Bool bChgAlign = pDoc->IsInsTblAlignNum();
+ const SfxPoolItem* pItem;
+
+ Color* pCol = 0;
+ if( NUMBERFORMAT_TEXT != nFmt )
+ {
+ // speziellen Textformat:
+ String sTmp, sTxt( pTNd->GetTxt() );
+ pDoc->GetNumberFormatter()->GetOutputString( sTxt, nFmt, sTmp, &pCol );
+ if( sTxt != sTmp )
+ {
+ // Text austauschen
+ SwIndex aIdx( pTNd, sTxt.Len() );
+ //JP 06.04.99: Bug 64321 - DontExpand-Flags vorm Austauschen
+ // zuruecksetzen, damit sie wieder aufgespannt werden
+ pTNd->DontExpandFmt( aIdx, sal_False, sal_False );
+ aIdx = 0;
+ pTNd->EraseText( aIdx, STRING_LEN,
+ IDocumentContentOperations::INS_EMPTYEXPAND );
+ pTNd->InsertText( sTmp, aIdx,
+ IDocumentContentOperations::INS_EMPTYEXPAND );
+ }
+ }
+
+ const SfxItemSet* pAttrSet = pTNd->GetpSwAttrSet();
+
+ // Ausrichtung umsetzen
+ if( bChgAlign && pAttrSet && SFX_ITEM_SET == pAttrSet->GetItemState(
+ RES_PARATR_ADJUST, sal_False, &pItem ) &&
+ SVX_ADJUST_RIGHT == ((SvxAdjustItem*)pItem)->GetAdjust() )
+ {
+ pTNd->SetAttr( SvxAdjustItem( SVX_ADJUST_LEFT, RES_PARATR_ADJUST ) );
+ }
+
+ // Farbe umsetzen oder "Benutzer Farbe" sichern
+ if( !pAttrSet || SFX_ITEM_SET != pAttrSet->
+ GetItemState( RES_CHRATR_COLOR, sal_False, &pItem ))
+ pItem = 0;
+
+ const Color* pOldNumFmtColor = rBox.GetSaveNumFmtColor();
+ const Color* pNewUserColor = pItem ? &((SvxColorItem*)pItem)->GetValue() : 0;
+
+ if( ( pNewUserColor && pOldNumFmtColor &&
+ *pNewUserColor == *pOldNumFmtColor ) ||
+ ( !pNewUserColor && !pOldNumFmtColor ))
+ {
+ // User Color nicht veraendern aktuellen Werte setzen
+ // ggfs. die alte NumFmtColor loeschen
+ if( pCol )
+ // ggfs. die Farbe setzen
+ pTNd->SetAttr( SvxColorItem( *pCol, RES_CHRATR_COLOR ));
+ else if( pItem )
+ {
+ pNewUserColor = rBox.GetSaveUserColor();
+ if( pNewUserColor )
+ pTNd->SetAttr( SvxColorItem( *pNewUserColor, RES_CHRATR_COLOR ));
+ else
+ pTNd->ResetAttr( RES_CHRATR_COLOR );
+ }
+ }
+ else
+ {
+ // User Color merken, ggfs. die NumFormat Color setzen, aber
+ // nie die Farbe zurueck setzen
+ rBox.SetSaveUserColor( pNewUserColor );
+
+ if( pCol )
+ // ggfs. die Farbe setzen
+ pTNd->SetAttr( SvxColorItem( *pCol, RES_CHRATR_COLOR ));
+
+ }
+ rBox.SetSaveNumFmtColor( pCol );
+
+
+ // vertikale Ausrichtung umsetzen
+ if( bChgAlign &&
+ SFX_ITEM_SET == rBox.GetFrmFmt()->GetItemState(
+ RES_VERT_ORIENT, sal_False, &pItem ) &&
+ text::VertOrientation::BOTTOM == ((SwFmtVertOrient*)pItem)->GetVertOrient() )
+ {
+ rBox.GetFrmFmt()->SetFmtAttr( SwFmtVertOrient( 0, text::VertOrientation::TOP ));
+ }
+ }
+}
+
+// zum Erkennen von Veraenderungen (haupts. TableBoxAttribute)
+void SwTableBoxFmt::Modify( const SfxPoolItem* pOld, const SfxPoolItem* pNew )
+{
+ if( !IsModifyLocked() && !IsInDocDTOR() )
+ {
+ const SwTblBoxNumFormat *pNewFmt = 0;
+ const SwTblBoxFormula *pNewFml = 0;
+ const SwTblBoxValue *pNewVal = 0;
+ sal_uLong nOldFmt = NUMBERFORMAT_TEXT;
+
+ switch( pNew ? pNew->Which() : 0 )
+ {
+ case RES_ATTRSET_CHG:
+ {
+ const SfxItemSet& rSet = *((SwAttrSetChg*)pNew)->GetChgSet();
+ if( SFX_ITEM_SET == rSet.GetItemState( RES_BOXATR_FORMAT,
+ sal_False, (const SfxPoolItem**)&pNewFmt ) )
+ nOldFmt = ((SwTblBoxNumFormat&)((SwAttrSetChg*)pOld)->
+ GetChgSet()->Get( RES_BOXATR_FORMAT )).GetValue();
+ rSet.GetItemState( RES_BOXATR_FORMULA, sal_False,
+ (const SfxPoolItem**)&pNewFml );
+ }
+ break;
+
+ case RES_BOXATR_FORMAT:
+ pNewFmt = (SwTblBoxNumFormat*)pNew;
+ nOldFmt = ((SwTblBoxNumFormat*)pOld)->GetValue();
+ break;
+ case RES_BOXATR_FORMULA:
+ pNewFml = (SwTblBoxFormula*)pNew;
+ break;
+ case RES_BOXATR_VALUE:
+ pNewVal = (SwTblBoxValue*)pNew;
+ break;
+ }
+
+ // es hat sich etwas getan und im Set ist noch irgendein BoxAttribut
+ // vorhanden!
+ if( pNewFmt || pNewFml || pNewVal )
+ {
+ GetDoc()->SetFieldsDirty(true, NULL, 0);
+
+ if( SFX_ITEM_SET == GetItemState( RES_BOXATR_FORMAT, sal_False ) ||
+ SFX_ITEM_SET == GetItemState( RES_BOXATR_VALUE, sal_False ) ||
+ SFX_ITEM_SET == GetItemState( RES_BOXATR_FORMULA, sal_False ) )
+ {
+ // die Box holen
+ SwIterator<SwTableBox,SwFmt> aIter( *this );
+ SwTableBox* pBox = aIter.First();
+ if( pBox )
+ {
+ OSL_ENSURE( !aIter.Next(), "keine Box oder mehrere am Format" );
+
+ sal_uLong nNewFmt;
+ if( pNewFmt )
+ {
+ nNewFmt = pNewFmt->GetValue();
+ // neu Formatieren
+ // ist es neuer oder wurde der akt. entfernt?
+ if( SFX_ITEM_SET != GetItemState( RES_BOXATR_VALUE, sal_False ))
+ pNewFmt = 0;
+ }
+ else
+ {
+ // das akt. Item besorgen
+ GetItemState( RES_BOXATR_FORMAT, sal_False,
+ (const SfxPoolItem**)&pNewFmt );
+ nOldFmt = GetTblBoxNumFmt().GetValue();
+ nNewFmt = pNewFmt ? pNewFmt->GetValue() : nOldFmt;
+ }
+
+ // ist es neuer oder wurde der akt. entfernt?
+ if( pNewVal )
+ {
+ if( NUMBERFORMAT_TEXT != nNewFmt )
+ {
+ if( SFX_ITEM_SET == GetItemState(
+ RES_BOXATR_VALUE, sal_False ))
+ nOldFmt = NUMBERFORMAT_TEXT;
+ else
+ nNewFmt = NUMBERFORMAT_TEXT;
+ }
+ else if( NUMBERFORMAT_TEXT == nNewFmt )
+ nOldFmt = 0;
+ }
+
+ // Logik:
+ // ValueAenderung: -> "simuliere" eine FormatAenderung!
+ // FormatAenderung:
+ // Text -> !Text oder FormatAenderung:
+ // - Ausrichtung auf RECHTS, wenn LINKS oder Blocksatz
+ // - vertikale Ausrichtung auf UNTEN wenn OBEN oder nicht
+ // gesetzt ist.
+ // - Text ersetzen (Farbe?? neg. Zahlen ROT??)
+ // !Text -> Text:
+ // - Ausrichtung auf LINKS, wenn RECHTS
+ // - vertikale Ausrichtung auf OEBN, wenn UNTEN gesetzt ist
+
+ SvNumberFormatter* pNumFmtr = GetDoc()->GetNumberFormatter();
+ sal_Bool bNewIsTxtFmt = pNumFmtr->IsTextFormat( nNewFmt ) ||
+ NUMBERFORMAT_TEXT == nNewFmt;
+
+ if( (!bNewIsTxtFmt && nOldFmt != nNewFmt) || pNewFml )
+ {
+ sal_Bool bChgTxt = sal_True;
+ double fVal = 0;
+ if( !pNewVal && SFX_ITEM_SET != GetItemState(
+ RES_BOXATR_VALUE, sal_False, (const SfxPoolItem**)&pNewVal ))
+ {
+ // es wurde noch nie ein Wert gesetzt, dann versuche
+ // doch mal den Inhalt auszuwerten
+ sal_uLong nNdPos = pBox->IsValidNumTxtNd( sal_True );
+ if( ULONG_MAX != nNdPos )
+ {
+ sal_uInt32 nTmpFmtIdx = nNewFmt;
+ String aTxt( GetDoc()->GetNodes()[ nNdPos ]
+ ->GetTxtNode()->GetRedlineTxt());
+ if( !aTxt.Len() )
+ bChgTxt = sal_False;
+ else
+ {
+ //JP 15.09.98: Bug 55741 - Tabs beibehalten
+ lcl_TabToBlankAtSttEnd( aTxt );
+
+ // JP 22.04.98: Bug 49659 -
+ // Sonderbehandlung fuer Prozent
+ sal_Bool bIsNumFmt = sal_False;
+ if( NUMBERFORMAT_PERCENT ==
+ pNumFmtr->GetType( nNewFmt ))
+ {
+ sal_uInt32 nTmpFmt = 0;
+ if( pNumFmtr->IsNumberFormat(
+ aTxt, nTmpFmt, fVal ))
+ {
+ if( NUMBERFORMAT_NUMBER ==
+ pNumFmtr->GetType( nTmpFmt ))
+ aTxt += '%';
+
+ bIsNumFmt = pNumFmtr->IsNumberFormat(
+ aTxt, nTmpFmtIdx, fVal );
+ }
+ }
+ else
+ bIsNumFmt = pNumFmtr->IsNumberFormat(
+ aTxt, nTmpFmtIdx, fVal );
+
+ if( bIsNumFmt )
+ {
+ // dann setze den Value direkt in den Set -
+ // ohne Modify
+ int bIsLockMod = IsModifyLocked();
+ LockModify();
+ SetFmtAttr( SwTblBoxValue( fVal ));
+ if( !bIsLockMod )
+ UnlockModify();
+ }
+ }
+ }
+ }
+ else
+ fVal = pNewVal->GetValue();
+
+ // den Inhalt mit dem neuen Wert Formtieren und in den Absatz
+ // schbreiben
+ Color* pCol = 0;
+ String sNewTxt;
+ if( DBL_MAX == fVal )
+ sNewTxt = ViewShell::GetShellRes()->aCalc_Error;
+ else
+ {
+ pNumFmtr->GetOutputString( fVal, nNewFmt, sNewTxt, &pCol );
+
+ if( !bChgTxt )
+ sNewTxt.Erase();
+ }
+
+ // ueber alle Boxen
+ ChgTextToNum( *pBox, sNewTxt, pCol,
+ GetDoc()->IsInsTblAlignNum() );
+
+ }
+ else if( bNewIsTxtFmt && nOldFmt != nNewFmt )
+ {
+ ChgNumToText( *pBox, nNewFmt );
+ }
+ }
+ }
+ }
+ }
+ // Und die Basis-Klasse rufen
+ SwFrmFmt::Modify( pOld, pNew );
+}
+
+sal_Bool SwTableBox::HasNumCntnt( double& rNum, sal_uInt32& rFmtIndex,
+ sal_Bool& rIsEmptyTxtNd ) const
+{
+ sal_Bool bRet = sal_False;
+ sal_uLong nNdPos = IsValidNumTxtNd( sal_True );
+ if( ULONG_MAX != nNdPos )
+ {
+ String aTxt( pSttNd->GetNodes()[ nNdPos ]->GetTxtNode()->
+ GetRedlineTxt() );
+ //JP 15.09.98: Bug 55741 - Tabs beibehalten
+ lcl_TabToBlankAtSttEnd( aTxt );
+ rIsEmptyTxtNd = 0 == aTxt.Len();
+ SvNumberFormatter* pNumFmtr = GetFrmFmt()->GetDoc()->GetNumberFormatter();
+
+ const SfxPoolItem* pItem;
+ if( SFX_ITEM_SET == GetFrmFmt()->GetItemState( RES_BOXATR_FORMAT,
+ sal_False, &pItem ))
+ {
+ rFmtIndex = ((SwTblBoxNumFormat*)pItem)->GetValue();
+ // JP 22.04.98: Bug 49659 - Sonderbehandlung fuer Prozent
+ if( !rIsEmptyTxtNd &&
+ NUMBERFORMAT_PERCENT == pNumFmtr->GetType( rFmtIndex ))
+ {
+ sal_uInt32 nTmpFmt = 0;
+ if( pNumFmtr->IsNumberFormat( aTxt, nTmpFmt, rNum ) &&
+ NUMBERFORMAT_NUMBER == pNumFmtr->GetType( nTmpFmt ))
+ aTxt += '%';
+ }
+ }
+ else
+ rFmtIndex = 0;
+
+ bRet = pNumFmtr->IsNumberFormat( aTxt, rFmtIndex, rNum );
+ }
+ else
+ rIsEmptyTxtNd = sal_False;
+ return bRet;
+}
+
+sal_Bool SwTableBox::IsNumberChanged() const
+{
+ sal_Bool bRet = sal_True;
+
+ if( SFX_ITEM_SET == GetFrmFmt()->GetItemState( RES_BOXATR_FORMULA, sal_False ))
+ {
+ const SwTblBoxNumFormat *pNumFmt;
+ const SwTblBoxValue *pValue;
+
+ if( SFX_ITEM_SET != GetFrmFmt()->GetItemState( RES_BOXATR_VALUE, sal_False,
+ (const SfxPoolItem**)&pValue ))
+ pValue = 0;
+ if( SFX_ITEM_SET != GetFrmFmt()->GetItemState( RES_BOXATR_FORMAT, sal_False,
+ (const SfxPoolItem**)&pNumFmt ))
+ pNumFmt = 0;
+
+ sal_uLong nNdPos;
+ if( pNumFmt && pValue &&
+ ULONG_MAX != ( nNdPos = IsValidNumTxtNd( sal_True ) ) )
+ {
+ String sNewTxt, sOldTxt( pSttNd->GetNodes()[ nNdPos ]->
+ GetTxtNode()->GetRedlineTxt() );
+ lcl_DelTabsAtSttEnd( sOldTxt );
+
+ Color* pCol = 0;
+ GetFrmFmt()->GetDoc()->GetNumberFormatter()->GetOutputString(
+ pValue->GetValue(), pNumFmt->GetValue(), sNewTxt, &pCol );
+
+ bRet = sNewTxt != sOldTxt ||
+ !( ( !pCol && !GetSaveNumFmtColor() ) ||
+ ( pCol && GetSaveNumFmtColor() &&
+ *pCol == *GetSaveNumFmtColor() ));
+ }
+ }
+ return bRet;
+}
+
+sal_uLong SwTableBox::IsValidNumTxtNd( sal_Bool bCheckAttr ) const
+{
+ sal_uLong nPos = ULONG_MAX;
+ if( pSttNd )
+ {
+ SwNodeIndex aIdx( *pSttNd );
+ sal_uLong nIndex = aIdx.GetIndex();
+ const sal_uLong nIndexEnd = pSttNd->GetNodes()[ nIndex ]->EndOfSectionIndex();
+ const SwTxtNode *pTextNode = 0;
+ while( ++nIndex < nIndexEnd )
+ {
+ const SwNode* pNode = pSttNd->GetNodes()[nIndex];
+ if( pNode->IsTableNode() )
+ {
+ pTextNode = 0;
+ break;
+ }
+ if( pNode->IsTxtNode() )
+ {
+ if( pTextNode )
+ {
+ pTextNode = 0;
+ break;
+ }
+ else
+ {
+ pTextNode = pNode->GetTxtNode();
+ nPos = nIndex;
+ }
+ }
+ }
+ if( pTextNode )
+ {
+ if( bCheckAttr )
+ {
+ const SwpHints* pHts = pTextNode->GetpSwpHints();
+ const String& rTxt = pTextNode->GetTxt();
+ // dann teste doch mal, ob das wirklich nur Text im Node steht!
+ // Flys/Felder/..
+ if( pHts )
+ {
+ for( sal_uInt16 n = 0; n < pHts->Count(); ++n )
+ {
+ const SwTxtAttr* pAttr = (*pHts)[ n ];
+ if( RES_TXTATR_NOEND_BEGIN <= pAttr->Which() ||
+ *pAttr->GetStart() ||
+ *pAttr->GetAnyEnd() < rTxt.Len() )
+ {
+ if ( pAttr->Which() == RES_TXTATR_FIELD )
+ {
+ const SwField* pField = pAttr->GetFld().GetFld();
+ if ( pField && pField->GetTypeId() == TYP_SETFLD )
+ {
+ continue;
+ }
+ }
+ nPos = ULONG_MAX;
+ break;
+ }
+ }
+ }
+ }
+ }
+ else
+ nPos = ULONG_MAX;
+ }
+ return nPos;
+}
+
+// ist das eine FormelBox oder eine Box mit numerischen Inhalt (AutoSum)
+sal_uInt16 SwTableBox::IsFormulaOrValueBox() const
+{
+ sal_uInt16 nWhich = 0;
+ const SwTxtNode* pTNd;
+ SwFrmFmt* pFmt = GetFrmFmt();
+ if( SFX_ITEM_SET == pFmt->GetItemState( RES_BOXATR_FORMULA, sal_False ))
+ nWhich = RES_BOXATR_FORMULA;
+ else if( SFX_ITEM_SET == pFmt->GetItemState( RES_BOXATR_VALUE, sal_False ) &&
+ !pFmt->GetDoc()->GetNumberFormatter()->IsTextFormat(
+ pFmt->GetTblBoxNumFmt().GetValue() ))
+ nWhich = RES_BOXATR_VALUE;
+ else if( pSttNd && pSttNd->GetIndex() + 2 == pSttNd->EndOfSectionIndex()
+ && 0 != ( pTNd = pSttNd->GetNodes()[ pSttNd->GetIndex() + 1 ]
+ ->GetTxtNode() ) && !pTNd->GetTxt().Len() )
+ nWhich = USHRT_MAX;
+
+ return nWhich;
+}
+
+void SwTableBox::ActualiseValueBox()
+{
+ const SfxPoolItem *pFmtItem, *pValItem;
+ SwFrmFmt* pFmt = GetFrmFmt();
+ if( SFX_ITEM_SET == pFmt->GetItemState( RES_BOXATR_FORMAT, sal_True, &pFmtItem )
+ && SFX_ITEM_SET == pFmt->GetItemState( RES_BOXATR_VALUE, sal_True, &pValItem ))
+ {
+ const sal_uLong nFmtId = ((SwTblBoxNumFormat*)pFmtItem)->GetValue();
+ sal_uLong nNdPos = ULONG_MAX;
+ SvNumberFormatter* pNumFmtr = pFmt->GetDoc()->GetNumberFormatter();
+
+ if( !pNumFmtr->IsTextFormat( nFmtId ) &&
+ ULONG_MAX != (nNdPos = IsValidNumTxtNd( sal_True )) )
+ {
+ double fVal = ((SwTblBoxValue*)pValItem)->GetValue();
+ Color* pCol = 0;
+ String sNewTxt;
+ pNumFmtr->GetOutputString( fVal, nFmtId, sNewTxt, &pCol );
+
+ const String& rTxt = pSttNd->GetNodes()[ nNdPos ]->GetTxtNode()->GetTxt();
+ if( rTxt != sNewTxt )
+ ChgTextToNum( *this, sNewTxt, pCol, sal_False ,nNdPos);
+ }
+ }
+}
+
+void SwTableBox_Impl::SetNewCol( Color** ppCol, const Color* pNewCol )
+{
+ if( *ppCol != pNewCol )
+ {
+ delete *ppCol;
+ if( pNewCol )
+ *ppCol = new Color( *pNewCol );
+ else
+ *ppCol = 0;
+ }
+}
+
+struct SwTableCellInfo::Impl
+{
+ const SwTable * m_pTable;
+ const SwCellFrm * m_pCellFrm;
+ const SwTabFrm * m_pTabFrm;
+ typedef ::std::set<const SwTableBox *> TableBoxes_t;
+ TableBoxes_t m_HandledTableBoxes;
+
+public:
+ Impl()
+ : m_pTable(NULL), m_pCellFrm(NULL), m_pTabFrm(NULL)
+ {
+ }
+
+ ~Impl() {}
+
+ void setTable(const SwTable * pTable) {
+ m_pTable = pTable;
+ SwFrmFmt * pFrmFmt = m_pTable->GetFrmFmt();
+ m_pTabFrm = SwIterator<SwTabFrm,SwFmt>::FirstElement(*pFrmFmt);
+ if (m_pTabFrm->IsFollow())
+ m_pTabFrm = m_pTabFrm->FindMaster(true);
+ }
+ const SwTable * getTable() const { return m_pTable; }
+
+ const SwCellFrm * getCellFrm() const { return m_pCellFrm; }
+
+ const SwFrm * getNextFrmInTable(const SwFrm * pFrm);
+ const SwCellFrm * getNextCellFrm(const SwFrm * pFrm);
+ const SwCellFrm * getNextTableBoxsCellFrm(const SwFrm * pFrm);
+ bool getNext();
+};
+
+const SwFrm * SwTableCellInfo::Impl::getNextFrmInTable(const SwFrm * pFrm)
+{
+ const SwFrm * pResult = NULL;
+
+ if (((! pFrm->IsTabFrm()) || pFrm == m_pTabFrm) && pFrm->GetLower())
+ pResult = pFrm->GetLower();
+ else if (pFrm->GetNext())
+ pResult = pFrm->GetNext();
+ else
+ {
+ while (pFrm->GetUpper() != NULL)
+ {
+ pFrm = pFrm->GetUpper();
+
+ if (pFrm->IsTabFrm())
+ {
+ m_pTabFrm = static_cast<const SwTabFrm *>(pFrm)->GetFollow();
+ pResult = m_pTabFrm;
+ break;
+ }
+ else if (pFrm->GetNext())
+ {
+ pResult = pFrm->GetNext();
+ break;
+ }
+ }
+ }
+
+ return pResult;
+}
+
+const SwCellFrm * SwTableCellInfo::Impl::getNextCellFrm(const SwFrm * pFrm)
+{
+ const SwCellFrm * pResult = NULL;
+
+ while ((pFrm = getNextFrmInTable(pFrm)) != NULL)
+ {
+ if (pFrm->IsCellFrm())
+ {
+ pResult = static_cast<const SwCellFrm *>(pFrm);
+ break;
+ }
+ }
+
+ return pResult;
+}
+
+const SwCellFrm * SwTableCellInfo::Impl::getNextTableBoxsCellFrm(const SwFrm * pFrm)
+{
+ const SwCellFrm * pResult = NULL;
+
+ while ((pFrm = getNextCellFrm(pFrm)) != NULL)
+ {
+ const SwCellFrm * pCellFrm = static_cast<const SwCellFrm *>(pFrm);
+ const SwTableBox * pTabBox = pCellFrm->GetTabBox();
+ TableBoxes_t::const_iterator aIt = m_HandledTableBoxes.find(pTabBox);
+
+ if (aIt == m_HandledTableBoxes.end())
+ {
+ pResult = pCellFrm;
+ m_HandledTableBoxes.insert(pTabBox);
+ break;
+ }
+ }
+
+ return pResult;
+}
+
+const SwCellFrm * SwTableCellInfo::getCellFrm() const
+{
+ return m_pImpl->getCellFrm();
+}
+
+bool SwTableCellInfo::Impl::getNext()
+{
+ if (m_pCellFrm == NULL)
+ {
+ if (m_pTabFrm != NULL)
+ m_pCellFrm = Impl::getNextTableBoxsCellFrm(m_pTabFrm);
+ }
+ else
+ m_pCellFrm = Impl::getNextTableBoxsCellFrm(m_pCellFrm);
+
+ return m_pCellFrm != NULL;
+}
+
+SwTableCellInfo::SwTableCellInfo(const SwTable * pTable)
+{
+ m_pImpl.reset(new Impl());
+ m_pImpl->setTable(pTable);
+}
+
+SwTableCellInfo::~SwTableCellInfo()
+{
+}
+
+bool SwTableCellInfo::getNext()
+{
+ return m_pImpl->getNext();
+}
+
+SwRect SwTableCellInfo::getRect() const
+{
+ SwRect aRet;
+
+ if (getCellFrm() != NULL)
+ aRet = getCellFrm()->Frm();
+
+ return aRet;
+}
+
+const SwTableBox * SwTableCellInfo::getTableBox() const
+{
+ const SwTableBox * pRet = NULL;
+
+ if (getCellFrm() != NULL)
+ pRet = getCellFrm()->GetTabBox();
+
+ return pRet;
+}
+
+void SwTable::RegisterToFormat( SwFmt& rFmt )
+{
+ rFmt.Add( this );
+}
+
+void SwTableLine::RegisterToFormat( SwFmt& rFmt )
+{
+ rFmt.Add( this );
+}
+
+void SwTableBox::RegisterToFormat( SwFmt& rFmt )
+{
+ rFmt.Add( this );
+}
+
+void SwTableBox::ForgetFrmFmt()
+{
+ if ( GetRegisteredIn() )
+ GetRegisteredInNonConst()->Remove(this);
+}
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/text/EnhancedPDFExportHelper.cxx b/sw/source/core/text/EnhancedPDFExportHelper.cxx
new file mode 100644
index 000000000000..623272cd4919
--- /dev/null
+++ b/sw/source/core/text/EnhancedPDFExportHelper.cxx
@@ -0,0 +1,2205 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+#include <com/sun/star/embed/XEmbeddedObject.hpp>
+#include <com/sun/star/i18n/ScriptType.hdl>
+#include <EnhancedPDFExportHelper.hxx>
+#include <hintids.hxx>
+
+#include <vcl/outdev.hxx>
+#include <tools/multisel.hxx>
+#include <editeng/adjitem.hxx>
+#include <editeng/lrspitem.hxx>
+#include <editeng/langitem.hxx>
+#include <editeng/scripttypeitem.hxx>
+#include <tools/urlobj.hxx>
+#include <svl/zforlist.hxx>
+#include <swatrset.hxx>
+#include <frmatr.hxx>
+#include <paratr.hxx>
+#include <ndtxt.hxx>
+#include <ndole.hxx>
+#include <section.hxx>
+#include <tox.hxx>
+#include <fmtfld.hxx>
+#include <txtinet.hxx>
+#include <fmtinfmt.hxx>
+#include <fchrfmt.hxx>
+#include <charfmt.hxx>
+#include <fmtanchr.hxx>
+#include <fmturl.hxx>
+#include <editsh.hxx>
+#include <viscrs.hxx>
+#include <txtfld.hxx>
+#include <reffld.hxx>
+#include <doc.hxx>
+#include <docary.hxx>
+#include <crsskip.hxx>
+#include <mdiexp.hxx>
+#include <docufld.hxx>
+#include <ftnidx.hxx>
+#include <txtftn.hxx>
+#include <fmtftn.hxx>
+#include <rootfrm.hxx>
+#include <pagefrm.hxx>
+#include <txtfrm.hxx>
+#include <tabfrm.hxx>
+#include <rowfrm.hxx>
+#include <cellfrm.hxx>
+#include <sectfrm.hxx>
+#include <flyfrm.hxx>
+#include <notxtfrm.hxx>
+#include <porfld.hxx>
+#include <SwStyleNameMapper.hxx>
+#include <itrpaint.hxx>
+#include "i18npool/mslangid.hxx"
+#include <IMark.hxx>
+#include <SwNodeNum.hxx>
+#include <switerator.hxx>
+#include <stack>
+
+#include <tools/globname.hxx>
+
+using namespace ::com::sun::star;
+
+//
+// Some static data structures
+//
+TableColumnsMap SwEnhancedPDFExportHelper::aTableColumnsMap;
+LinkIdMap SwEnhancedPDFExportHelper::aLinkIdMap;
+NumListIdMap SwEnhancedPDFExportHelper::aNumListIdMap;
+NumListBodyIdMap SwEnhancedPDFExportHelper::aNumListBodyIdMap;
+FrmTagIdMap SwEnhancedPDFExportHelper::aFrmTagIdMap;
+
+LanguageType SwEnhancedPDFExportHelper::eLanguageDefault = 0;
+
+#if OSL_DEBUG_LEVEL > 1
+
+static std::vector< sal_uInt16 > aStructStack;
+
+void lcl_DBGCheckStack()
+{
+ /* NonStructElement = 0 Document = 1 Part = 2
+ * Article = 3 Section = 4 Division = 5
+ * BlockQuote = 6 Caption = 7 TOC = 8
+ * TOCI = 9 Index = 10 Paragraph = 11
+ * Heading = 12 H1-6 = 13 - 18 List = 19
+ * ListItem = 20 LILabel = 21 LIBody = 22
+ * Table = 23 TableRow = 24 TableHeader = 25
+ * TableData = 26 Span = 27 Quote = 28
+ * Note = 29 Reference = 30 BibEntry = 31
+ * Code = 32 Link = 33 Figure = 34
+ * Formula = 35 Form = 36 Continued frame = 99
+ */
+
+ sal_uInt16 nElement;
+ std::vector< sal_uInt16 >::iterator aIter;
+ for ( aIter = aStructStack.begin(); aIter != aStructStack.end(); ++aIter )
+ {
+ nElement = *aIter;
+ }
+}
+
+#endif
+
+namespace
+{
+// ODF Style Names:
+const String aTableHeadingName = String::CreateFromAscii("Table Heading");
+const String aQuotations = String::CreateFromAscii("Quotations");
+const String aCaption = String::CreateFromAscii("Caption");
+const String aHeading = String::CreateFromAscii("Heading");
+const String aQuotation = String::CreateFromAscii("Quotation");
+const String aSourceText = String::CreateFromAscii("Source Text");
+
+// PDF Tag Names:
+const String aDocumentString = String::CreateFromAscii("Document");
+const String aDivString = String::CreateFromAscii("Div");
+const String aSectString = String::CreateFromAscii("Sect");
+const String aHString = String::CreateFromAscii("H");
+const String aH1String = String::CreateFromAscii("H1");
+const String aH2String = String::CreateFromAscii("H2");
+const String aH3String = String::CreateFromAscii("H3");
+const String aH4String = String::CreateFromAscii("H4");
+const String aH5String = String::CreateFromAscii("H5");
+const String aH6String = String::CreateFromAscii("H6");
+const String aListString = String::CreateFromAscii("L");
+const String aListItemString = String::CreateFromAscii("LI");
+const String aListBodyString = String::CreateFromAscii("LBody");
+const String aBlockQuoteString = String::CreateFromAscii("BlockQuote");
+const String aCaptionString = String::CreateFromAscii("Caption");
+const String aIndexString = String::CreateFromAscii("Index");
+const String aTOCString = String::CreateFromAscii("TOC");
+const String aTOCIString = String::CreateFromAscii("TOCI");
+const String aTableString = String::CreateFromAscii("Table");
+const String aTRString = String::CreateFromAscii("TR");
+const String aTDString = String::CreateFromAscii("TD");
+const String aTHString = String::CreateFromAscii("TH");
+const String aBibEntryString = String::CreateFromAscii("BibEntry");
+const String aQuoteString = String::CreateFromAscii("Quote");
+const String aSpanString = String::CreateFromAscii("Span");
+const String aCodeString = String::CreateFromAscii("Code");
+const String aFigureString = String::CreateFromAscii("Figure");
+const String aFormulaString = String::CreateFromAscii("Formula");
+const String aLinkString = String::CreateFromAscii("Link");
+const String aNoteString = String::CreateFromAscii("Note");
+const String aEmptyString = String::CreateFromAscii("");
+
+// returns true if first paragraph in cell frame has 'table heading' style
+bool lcl_IsHeadlineCell( const SwCellFrm& rCellFrm )
+{
+ bool bRet = false;
+
+ const SwCntntFrm *pCnt = rCellFrm.ContainsCntnt();
+ if ( pCnt && pCnt->IsTxtFrm() )
+ {
+ const SwTxtNode* pTxtNode = static_cast<const SwTxtFrm*>(pCnt)->GetTxtNode();
+ const SwFmt* pTxtFmt = pTxtNode->GetFmtColl();
+
+ String sStyleName;
+ SwStyleNameMapper::FillProgName( pTxtFmt->GetName(), sStyleName, nsSwGetPoolIdFromName::GET_POOLID_TXTCOLL, sal_True );
+ bRet = sStyleName == aTableHeadingName;
+ }
+
+ return bRet;
+}
+
+// List all frames for which the NonStructElement tag is set:
+bool lcl_IsInNonStructEnv( const SwFrm& rFrm )
+{
+ bool bRet = false;
+
+ if ( 0 != rFrm.FindFooterOrHeader() &&
+ !rFrm.IsHeaderFrm() && !rFrm.IsFooterFrm() )
+ {
+ bRet = true;
+ }
+ else if ( rFrm.IsInTab() && !rFrm.IsTabFrm() )
+ {
+ const SwTabFrm* pTabFrm = rFrm.FindTabFrm();
+ if ( rFrm.GetUpper() != pTabFrm &&
+ pTabFrm->IsFollow() && pTabFrm->IsInHeadline( rFrm ) )
+ bRet = true;
+ }
+
+ return bRet;
+}
+
+// Generate key from frame for reopening tags:
+void* lcl_GetKeyFromFrame( const SwFrm& rFrm )
+{
+ void* pKey = 0;
+
+ if ( rFrm.IsPageFrm() )
+ pKey = (void*)static_cast<const SwPageFrm&>(rFrm).GetFmt()->getIDocumentSettingAccess();
+ else if ( rFrm.IsTxtFrm() )
+ pKey = (void*)static_cast<const SwTxtFrm&>(rFrm).GetTxtNode();
+ else if ( rFrm.IsSctFrm() )
+ pKey = (void*)static_cast<const SwSectionFrm&>(rFrm).GetSection();
+ else if ( rFrm.IsTabFrm() )
+ pKey = (void*)static_cast<const SwTabFrm&>(rFrm).GetTable();
+ else if ( rFrm.IsRowFrm() )
+ pKey = (void*)static_cast<const SwRowFrm&>(rFrm).GetTabLine();
+ else if ( rFrm.IsCellFrm() )
+ {
+ const SwTabFrm* pTabFrm = rFrm.FindTabFrm();
+ const SwTable* pTable = pTabFrm->GetTable();
+ pKey = (void*) & static_cast<const SwCellFrm&>(rFrm).GetTabBox()->FindStartOfRowSpan( *pTable );
+ }
+
+ return pKey;
+}
+
+bool lcl_HasPreviousParaSameNumRule( const SwTxtNode& rNode )
+{
+ bool bRet = false;
+ SwNodeIndex aIdx( rNode );
+ const SwDoc* pDoc = rNode.GetDoc();
+ const SwNodes& rNodes = pDoc->GetNodes();
+ const SwNode* pNode = &rNode;
+ const SwNumRule* pNumRule = rNode.GetNumRule();
+
+ while (! (pNode == rNodes.DocumentSectionStartNode((SwNode*)&rNode) ) )
+ {
+ --aIdx;
+
+ if (aIdx.GetNode().IsTxtNode())
+ {
+ const SwTxtNode* pPrevTxtNd = aIdx.GetNode().GetTxtNode();
+ const SwNumRule * pPrevNumRule = pPrevTxtNd->GetNumRule();
+
+ // We find the previous text node. Now check, if the previous text node
+ // has the same numrule like rNode:
+ if ( (pPrevNumRule == pNumRule) &&
+ (!pPrevTxtNd->IsOutline() == !rNode.IsOutline()))
+ bRet = true;
+
+ break;
+ }
+
+ pNode = &aIdx.GetNode();
+ }
+ return bRet;
+}
+
+} // end namespace
+
+/*
+ * SwTaggedPDFHelper::SwTaggedPDFHelper()
+ */
+SwTaggedPDFHelper::SwTaggedPDFHelper( const Num_Info* pNumInfo,
+ const Frm_Info* pFrmInfo,
+ const Por_Info* pPorInfo,
+ OutputDevice& rOut )
+ : nEndStructureElement( 0 ),
+ nRestoreCurrentTag( -1 ),
+ mpNumInfo( pNumInfo ),
+ mpFrmInfo( pFrmInfo ),
+ mpPorInfo( pPorInfo )
+{
+ mpPDFExtOutDevData =
+ PTR_CAST( vcl::PDFExtOutDevData, rOut.GetExtOutDevData() );
+
+ if ( mpPDFExtOutDevData && mpPDFExtOutDevData->GetIsExportTaggedPDF() )
+ {
+#if OSL_DEBUG_LEVEL > 1
+ sal_Int32 nCurrentStruct = mpPDFExtOutDevData->GetCurrentStructureElement();
+ lcl_DBGCheckStack();
+#endif
+ if ( mpNumInfo )
+ BeginNumberedListStructureElements();
+ else if ( mpFrmInfo )
+ BeginBlockStructureElements();
+ else if ( mpPorInfo )
+ BeginInlineStructureElements();
+ else
+ BeginTag( vcl::PDFWriter::NonStructElement, aEmptyString );
+
+#if OSL_DEBUG_LEVEL > 1
+ nCurrentStruct = mpPDFExtOutDevData->GetCurrentStructureElement();
+ lcl_DBGCheckStack();
+#endif
+ }
+}
+
+
+/*
+ * SwTaggedPDFHelper::~SwTaggedPDFHelper()
+ */
+SwTaggedPDFHelper::~SwTaggedPDFHelper()
+{
+ if ( mpPDFExtOutDevData && mpPDFExtOutDevData->GetIsExportTaggedPDF() )
+ {
+#if OSL_DEBUG_LEVEL > 1
+ sal_Int32 nCurrentStruct = mpPDFExtOutDevData->GetCurrentStructureElement();
+ lcl_DBGCheckStack();
+#endif
+ EndStructureElements();
+
+#if OSL_DEBUG_LEVEL > 1
+ nCurrentStruct = mpPDFExtOutDevData->GetCurrentStructureElement();
+ lcl_DBGCheckStack();
+#endif
+
+ }
+}
+
+/*
+ * SwTaggedPDFHelper::CheckReopenTag()
+ */
+bool SwTaggedPDFHelper::CheckReopenTag()
+{
+ bool bRet = false;
+ sal_Int32 nReopenTag = -1;
+ bool bContinue = false; // in some cases we just have to reopen a tag without early returning
+
+ if ( mpFrmInfo )
+ {
+ const SwFrm& rFrm = mpFrmInfo->mrFrm;
+ const SwFrm* pKeyFrm = 0;
+ void* pKey = 0;
+
+ // Reopen an existing structure element if
+ // - rFrm is not the first page frame (reopen Document tag)
+ // - rFrm is a follow frame (reopen Master tag)
+ // - rFrm is a fly frame anchored at content (reopen Anchor paragraph tag)
+ // - rFrm is a fly frame anchord at page (reopen Document tag)
+ // - rFrm is a follow flow row (reopen TableRow tag)
+ // - rFrm is a cell frame in a follow flow row (reopen TableData tag)
+ if ( ( rFrm.IsPageFrm() && static_cast<const SwPageFrm&>(rFrm).GetPrev() ) ||
+ ( rFrm.IsFlowFrm() && SwFlowFrm::CastFlowFrm(&rFrm)->IsFollow() ) ||
+ ( rFrm.IsRowFrm() && rFrm.IsInFollowFlowRow() ) ||
+ ( rFrm.IsCellFrm() && const_cast<SwFrm&>(rFrm).GetPrevCellLeaf( MAKEPAGE_NONE ) ) )
+ {
+ pKeyFrm = &rFrm;
+ }
+ else if ( rFrm.IsFlyFrm() )
+ {
+ const SwFmtAnchor& rAnchor =
+ static_cast<const SwFlyFrm*>(&rFrm)->GetFmt()->GetAnchor();
+ if ((FLY_AT_PARA == rAnchor.GetAnchorId()) ||
+ (FLY_AT_CHAR == rAnchor.GetAnchorId()) ||
+ (FLY_AT_PAGE == rAnchor.GetAnchorId()))
+ {
+ pKeyFrm = static_cast<const SwFlyFrm&>(rFrm).GetAnchorFrm();
+ bContinue = true;
+ }
+ }
+
+ if ( pKeyFrm )
+ {
+ pKey = lcl_GetKeyFromFrame( *pKeyFrm );
+
+ if ( pKey )
+ {
+ FrmTagIdMap& rFrmTagIdMap = SwEnhancedPDFExportHelper::GetFrmTagIdMap();
+ const FrmTagIdMap::const_iterator aIter = rFrmTagIdMap.find( pKey );
+ nReopenTag = (*aIter).second;
+ }
+ }
+ }
+
+ if ( -1 != nReopenTag )
+ {
+ nRestoreCurrentTag = mpPDFExtOutDevData->GetCurrentStructureElement();
+ const bool bSuccess = mpPDFExtOutDevData->SetCurrentStructureElement( nReopenTag );
+ OSL_ENSURE( bSuccess, "Failed to reopen tag" );
+
+#if OSL_DEBUG_LEVEL > 1
+ aStructStack.push_back( 99 );
+#endif
+
+ bRet = bSuccess;
+ }
+
+ return bRet && !bContinue;
+}
+
+
+/*
+ * SwTaggedPDFHelper::CheckRestoreTag()
+ */
+bool SwTaggedPDFHelper::CheckRestoreTag() const
+{
+ bool bRet = false;
+ if ( nRestoreCurrentTag != -1 )
+ {
+ const bool bSuccess = mpPDFExtOutDevData->SetCurrentStructureElement( nRestoreCurrentTag );
+ (void)bSuccess;
+ OSL_ENSURE( bSuccess, "Failed to restore reopened tag" );
+
+#if OSL_DEBUG_LEVEL > 1
+ aStructStack.pop_back();
+#endif
+
+ bRet = true;
+ }
+
+ return bRet;
+}
+
+
+/*
+ * SwTaggedPDFHelper::BeginTag()
+ */
+void SwTaggedPDFHelper::BeginTag( vcl::PDFWriter::StructElement eType, const String& rString )
+{
+ // write new tag
+ const sal_Int32 nId = mpPDFExtOutDevData->BeginStructureElement( eType, rtl::OUString( rString ) );
+ ++nEndStructureElement;
+
+#if OSL_DEBUG_LEVEL > 1
+ aStructStack.push_back( static_cast<sal_uInt16>(eType) );
+#endif
+
+ // Store the id of the current structure element if
+ // - it is a list structure element
+ // - it is a list body element with children
+ // - rFrm is the first page frame
+ // - rFrm is a master frame
+ // - rFrm has objects anchored to it
+ // - rFrm is a row frame or cell frame in a split table row
+
+ if ( mpNumInfo )
+ {
+ const SwTxtFrm& rTxtFrm = static_cast<const SwTxtFrm&>(mpNumInfo->mrFrm);
+ const SwTxtNode* pTxtNd = rTxtFrm.GetTxtNode();
+ const SwNodeNum* pNodeNum = pTxtNd->GetNum();
+
+ if ( vcl::PDFWriter::List == eType )
+ {
+ NumListIdMap& rNumListIdMap = SwEnhancedPDFExportHelper::GetNumListIdMap();
+ rNumListIdMap[ pNodeNum ] = nId;
+ }
+ else if ( vcl::PDFWriter::LIBody == eType )
+ {
+ NumListBodyIdMap& rNumListBodyIdMap = SwEnhancedPDFExportHelper::GetNumListBodyIdMap();
+ rNumListBodyIdMap[ pNodeNum ] = nId;
+ }
+ }
+ else if ( mpFrmInfo )
+ {
+ const SwFrm& rFrm = mpFrmInfo->mrFrm;
+
+ if ( ( rFrm.IsPageFrm() && !static_cast<const SwPageFrm&>(rFrm).GetPrev() ) ||
+ ( rFrm.IsFlowFrm() && !SwFlowFrm::CastFlowFrm(&rFrm)->IsFollow() && SwFlowFrm::CastFlowFrm(&rFrm)->HasFollow() ) ||
+ ( rFrm.IsTxtFrm() && rFrm.GetDrawObjs() ) ||
+ ( rFrm.IsRowFrm() && rFrm.IsInSplitTableRow() ) ||
+ ( rFrm.IsCellFrm() && const_cast<SwFrm&>(rFrm).GetNextCellLeaf( MAKEPAGE_NONE ) ) )
+ {
+ const void* pKey = lcl_GetKeyFromFrame( rFrm );
+
+ if ( pKey )
+ {
+ FrmTagIdMap& rFrmTagIdMap = SwEnhancedPDFExportHelper::GetFrmTagIdMap();
+ rFrmTagIdMap[ pKey ] = nId;
+ }
+ }
+ }
+
+ SetAttributes( eType );
+}
+
+
+/*
+ * SwTaggedPDFHelper::EndTag()
+ */
+void SwTaggedPDFHelper::EndTag()
+{
+ mpPDFExtOutDevData->EndStructureElement();
+
+#if OSL_DEBUG_LEVEL > 1
+ aStructStack.pop_back();
+#endif
+}
+
+
+/*
+ * SwTaggedPDFHelper::SetAttributes()
+ *
+ * Sets the attributes according to the structure type.
+ */
+void SwTaggedPDFHelper::SetAttributes( vcl::PDFWriter::StructElement eType )
+{
+ vcl::PDFWriter::StructAttributeValue eVal;
+ sal_Int32 nVal;
+
+ /*
+ * ATTRIBUTES FOR BLSE
+ */
+ if ( mpFrmInfo )
+ {
+ const SwFrm* pFrm = &mpFrmInfo->mrFrm;
+ SWRECTFN( pFrm )
+
+ bool bPlacement = false;
+ bool bWritingMode = false;
+ bool bSpaceBefore = false;
+ bool bSpaceAfter = false;
+ bool bStartIndent = false;
+ bool bEndIndent = false;
+ bool bTextIndent = false;
+ bool bTextAlign = false;
+ bool bAlternateText = false;
+ bool bWidth = false;
+ bool bHeight = false;
+ bool bBox = false;
+ bool bRowSpan = false;
+
+ //
+ // Check which attributes to set:
+ //
+ switch ( eType )
+ {
+ case vcl::PDFWriter::Document :
+ bWritingMode = true;
+ break;
+
+ case vcl::PDFWriter::Table :
+ bPlacement =
+ bWritingMode =
+ bSpaceBefore =
+ bSpaceAfter =
+ bStartIndent =
+ bEndIndent =
+ bWidth =
+ bHeight =
+ bBox = true;
+ break;
+
+ case vcl::PDFWriter::TableRow :
+ bPlacement =
+ bWritingMode = true;
+ break;
+
+ case vcl::PDFWriter::TableHeader :
+ case vcl::PDFWriter::TableData :
+ bPlacement =
+ bWritingMode =
+ bWidth =
+ bHeight =
+ bRowSpan = true;
+ break;
+
+ case vcl::PDFWriter::H1 :
+ case vcl::PDFWriter::H2 :
+ case vcl::PDFWriter::H3 :
+ case vcl::PDFWriter::H4 :
+ case vcl::PDFWriter::H5 :
+ case vcl::PDFWriter::H6 :
+ case vcl::PDFWriter::Paragraph :
+ case vcl::PDFWriter::Heading :
+ case vcl::PDFWriter::Caption :
+ case vcl::PDFWriter::BlockQuote :
+
+ bPlacement =
+ bWritingMode =
+ bSpaceBefore =
+ bSpaceAfter =
+ bStartIndent =
+ bEndIndent =
+ bTextIndent =
+ bTextAlign = true;
+ break;
+
+ case vcl::PDFWriter::Formula :
+ case vcl::PDFWriter::Figure :
+ bPlacement =
+ bAlternateText =
+ bWidth =
+ bHeight =
+ bBox = true;
+ break;
+ default :
+ break;
+ }
+
+ //
+ // Set the attributes:
+ //
+ if ( bPlacement )
+ {
+ eVal = vcl::PDFWriter::TableHeader == eType ||
+ vcl::PDFWriter::TableData == eType ?
+ vcl::PDFWriter::Inline :
+ vcl::PDFWriter::Block;
+
+ mpPDFExtOutDevData->SetStructureAttribute( vcl::PDFWriter::Placement, eVal );
+ }
+
+ if ( bWritingMode )
+ {
+ eVal = pFrm->IsVertical() ?
+ vcl::PDFWriter::TbRl :
+ pFrm->IsRightToLeft() ?
+ vcl::PDFWriter::RlTb :
+ vcl::PDFWriter::LrTb;
+
+ if ( vcl::PDFWriter::LrTb != eVal )
+ mpPDFExtOutDevData->SetStructureAttribute( vcl::PDFWriter::WritingMode, eVal );
+ }
+
+ if ( bSpaceBefore )
+ {
+ nVal = (pFrm->*fnRect->fnGetTopMargin)();
+ if ( 0 != nVal )
+ mpPDFExtOutDevData->SetStructureAttributeNumerical( vcl::PDFWriter::SpaceBefore, nVal );
+ }
+
+ if ( bSpaceAfter )
+ {
+ nVal = (pFrm->*fnRect->fnGetBottomMargin)();
+ if ( 0 != nVal )
+ mpPDFExtOutDevData->SetStructureAttributeNumerical( vcl::PDFWriter::SpaceAfter, nVal );
+ }
+
+ if ( bStartIndent )
+ {
+ nVal = (pFrm->*fnRect->fnGetLeftMargin)();
+ if ( 0 != nVal )
+ mpPDFExtOutDevData->SetStructureAttributeNumerical( vcl::PDFWriter::StartIndent, nVal );
+ }
+
+ if ( bEndIndent )
+ {
+ nVal = (pFrm->*fnRect->fnGetRightMargin)();
+ if ( 0 != nVal )
+ mpPDFExtOutDevData->SetStructureAttributeNumerical( vcl::PDFWriter::EndIndent, nVal );
+ }
+
+ if ( bTextIndent )
+ {
+ OSL_ENSURE( pFrm->IsTxtFrm(), "Frame type <-> tag attribute mismatch" );
+ const SvxLRSpaceItem &rSpace =
+ static_cast<const SwTxtFrm*>(pFrm)->GetTxtNode()->GetSwAttrSet().GetLRSpace();
+ nVal = rSpace.GetTxtFirstLineOfst();
+ if ( 0 != nVal )
+ mpPDFExtOutDevData->SetStructureAttributeNumerical( vcl::PDFWriter::TextIndent, nVal );
+ }
+
+ if ( bTextAlign )
+ {
+ OSL_ENSURE( pFrm->IsTxtFrm(), "Frame type <-> tag attribute mismatch" );
+ const SwAttrSet& aSet = static_cast<const SwTxtFrm*>(pFrm)->GetTxtNode()->GetSwAttrSet();
+ const SvxAdjust nAdjust = aSet.GetAdjust().GetAdjust();
+ if ( SVX_ADJUST_BLOCK == nAdjust || SVX_ADJUST_CENTER == nAdjust ||
+ ( (pFrm->IsRightToLeft() && SVX_ADJUST_LEFT == nAdjust) ||
+ (!pFrm->IsRightToLeft() && SVX_ADJUST_RIGHT == nAdjust) ) )
+ {
+ eVal = SVX_ADJUST_BLOCK == nAdjust ?
+ vcl::PDFWriter::Justify :
+ SVX_ADJUST_CENTER == nAdjust ?
+ vcl::PDFWriter::Center :
+ vcl::PDFWriter::End;
+
+ mpPDFExtOutDevData->SetStructureAttribute( vcl::PDFWriter::TextAlign, eVal );
+ }
+ }
+
+ if ( bAlternateText )
+ {
+ OSL_ENSURE( pFrm->IsFlyFrm(), "Frame type <-> tag attribute mismatch" );
+ const SwFlyFrm* pFly = static_cast<const SwFlyFrm*>(pFrm);
+ if ( pFly->Lower() && pFly->Lower()->IsNoTxtFrm() )
+ {
+ const SwNoTxtFrm* pNoTxtFrm = static_cast<const SwNoTxtFrm*>(pFly->Lower());
+ const SwNoTxtNode* pNoTxtNode = static_cast<const SwNoTxtNode*>(pNoTxtFrm->GetNode());
+
+ const String aAlternateTxt( pNoTxtNode->GetTitle() );
+ mpPDFExtOutDevData->SetAlternateText( aAlternateTxt );
+ }
+ }
+
+ if ( bWidth )
+ {
+ nVal = (pFrm->Frm().*fnRect->fnGetWidth)();
+ mpPDFExtOutDevData->SetStructureAttributeNumerical( vcl::PDFWriter::Width, nVal );
+ }
+
+ if ( bHeight )
+ {
+ nVal = (pFrm->Frm().*fnRect->fnGetHeight)();
+ mpPDFExtOutDevData->SetStructureAttributeNumerical( vcl::PDFWriter::Height, nVal );
+ }
+
+ if ( bBox )
+ {
+ // BBox only for non-split tables:
+ if ( vcl::PDFWriter::Table != eType ||
+ ( pFrm->IsTabFrm() &&
+ !static_cast<const SwTabFrm*>(pFrm)->IsFollow() &&
+ !static_cast<const SwTabFrm*>(pFrm)->HasFollow() ) )
+ mpPDFExtOutDevData->SetStructureBoundingBox( pFrm->Frm().SVRect() );
+ }
+
+ if ( bRowSpan )
+ {
+ const SwCellFrm* pThisCell = dynamic_cast<const SwCellFrm*>(pFrm);
+ if ( pThisCell )
+ {
+ nVal = pThisCell->GetTabBox()->getRowSpan();
+ if ( nVal > 1 )
+ mpPDFExtOutDevData->SetStructureAttributeNumerical( vcl::PDFWriter::RowSpan, nVal );
+
+ // calculate colspan:
+ const SwTabFrm* pTabFrm = pThisCell->FindTabFrm();
+ const SwTable* pTable = pTabFrm->GetTable();
+
+ SWRECTFNX( pTabFrm )
+
+ const TableColumnsMapEntry& rCols = SwEnhancedPDFExportHelper::GetTableColumnsMap()[ pTable ];
+
+ const long nLeft = (pThisCell->Frm().*fnRectX->fnGetLeft)();
+ const long nRight = (pThisCell->Frm().*fnRectX->fnGetRight)();
+ const TableColumnsMapEntry::const_iterator aLeftIter = rCols.find( nLeft );
+ const TableColumnsMapEntry::const_iterator aRightIter = rCols.find( nRight );
+
+ OSL_ENSURE( aLeftIter != rCols.end() && aRightIter != rCols.end(), "Colspan trouble" );
+ if ( aLeftIter != rCols.end() && aRightIter != rCols.end() )
+ {
+ nVal = std::distance( aLeftIter, aRightIter );
+ if ( nVal > 1 )
+ mpPDFExtOutDevData->SetStructureAttributeNumerical( vcl::PDFWriter::ColSpan, nVal );
+ }
+ }
+ }
+ }
+
+ /*
+ * ATTRIBUTES FOR ILSE
+ */
+ else if ( mpPorInfo )
+ {
+ const SwLinePortion* pPor = &mpPorInfo->mrPor;
+ const SwTxtPaintInfo& rInf = mpPorInfo->mrTxtPainter.GetInfo();
+
+ bool bActualText = false;
+ bool bBaselineShift = false;
+ bool bTextDecorationType = false;
+ bool bLinkAttribute = false;
+ bool bLanguage = false;
+
+ //
+ // Check which attributes to set:
+ //
+ switch ( eType )
+ {
+ case vcl::PDFWriter::Span :
+ case vcl::PDFWriter::Quote :
+ case vcl::PDFWriter::Code :
+ if( POR_HYPHSTR == pPor->GetWhichPor() || POR_SOFTHYPHSTR == pPor->GetWhichPor() )
+ bActualText = true;
+ else
+ {
+ bBaselineShift =
+ bTextDecorationType =
+ bLanguage = true;
+ }
+ break;
+
+ case vcl::PDFWriter::Link :
+ bTextDecorationType =
+ bBaselineShift =
+ bLinkAttribute =
+ bLanguage = true;
+ break;
+
+ default:
+ break;
+ }
+
+ if ( bActualText )
+ {
+ const String aActualTxt( rInf.GetTxt(), rInf.GetIdx(), pPor->GetLen() );
+ mpPDFExtOutDevData->SetActualText( aActualTxt );
+ }
+
+ if ( bBaselineShift )
+ {
+ // TODO: Calculate correct values!
+ nVal = rInf.GetFont()->GetEscapement();
+ if ( nVal > 0 ) nVal = 33;
+ else if ( nVal < 0 ) nVal = -33;
+
+ if ( 0 != nVal )
+ {
+ nVal = nVal * pPor->Height() / 100;
+ mpPDFExtOutDevData->SetStructureAttributeNumerical( vcl::PDFWriter::BaselineShift, nVal );
+ }
+ }
+
+ if ( bTextDecorationType )
+ {
+ if ( UNDERLINE_NONE != rInf.GetFont()->GetUnderline() )
+ mpPDFExtOutDevData->SetStructureAttribute( vcl::PDFWriter::TextDecorationType, vcl::PDFWriter::Underline );
+ if ( UNDERLINE_NONE != rInf.GetFont()->GetOverline() )
+ mpPDFExtOutDevData->SetStructureAttribute( vcl::PDFWriter::TextDecorationType, vcl::PDFWriter::Overline );
+ if ( STRIKEOUT_NONE != rInf.GetFont()->GetStrikeout() )
+ mpPDFExtOutDevData->SetStructureAttribute( vcl::PDFWriter::TextDecorationType, vcl::PDFWriter::LineThrough );
+ if ( EMPHASISMARK_NONE != rInf.GetFont()->GetEmphasisMark() )
+ mpPDFExtOutDevData->SetStructureAttribute( vcl::PDFWriter::TextDecorationType, vcl::PDFWriter::Overline );
+ }
+
+ if ( bLanguage )
+ {
+
+ const LanguageType nCurrentLanguage = rInf.GetFont()->GetLanguage();
+ const LanguageType nDefaultLang = SwEnhancedPDFExportHelper::GetDefaultLanguage();
+
+ if ( nDefaultLang != nCurrentLanguage )
+ mpPDFExtOutDevData->SetStructureAttributeNumerical( vcl::PDFWriter::Language, nCurrentLanguage );
+ }
+
+ if ( bLinkAttribute )
+ {
+ const LinkIdMap& rLinkIdMap = SwEnhancedPDFExportHelper::GetLinkIdMap();
+ SwRect aPorRect;
+ rInf.CalcRect( *pPor, &aPorRect );
+ const Point aPorCenter = aPorRect.Center();
+ LinkIdMap::const_iterator aIter;
+ for ( aIter = rLinkIdMap.begin(); aIter != rLinkIdMap.end(); ++aIter )
+ {
+ const SwRect& rLinkRect = (*aIter).first;
+ if ( rLinkRect.IsInside( aPorCenter ) )
+ {
+ sal_Int32 nLinkId = (*aIter).second;
+ mpPDFExtOutDevData->SetStructureAttributeNumerical( vcl::PDFWriter::LinkAnnotation, nLinkId );
+ break;
+ }
+ }
+ }
+ }
+}
+
+/*
+ * SwTaggedPDFHelper::BeginNumberedListStructureElements()
+ */
+void SwTaggedPDFHelper::BeginNumberedListStructureElements()
+{
+ OSL_ENSURE( mpNumInfo, "List without mpNumInfo?" );
+ if ( !mpNumInfo )
+ return;
+
+ const SwFrm& rFrm = mpNumInfo->mrFrm;
+ OSL_ENSURE( rFrm.IsTxtFrm(), "numbered only for text frames" );
+ const SwTxtFrm& rTxtFrm = static_cast<const SwTxtFrm&>(rFrm);
+
+ //
+ // Lowers of NonStructureElements should not be considered:
+ //
+ if ( lcl_IsInNonStructEnv( rTxtFrm ) || rTxtFrm.IsFollow() )
+ return;
+
+ const SwTxtNode* pTxtNd = rTxtFrm.GetTxtNode();
+ const SwNumRule* pNumRule = pTxtNd->GetNumRule();
+ const SwNodeNum* pNodeNum = pTxtNd->GetNum();
+
+ const bool bNumbered = !pTxtNd->IsOutline() && pNodeNum && pNodeNum->GetParent() && pNumRule;
+
+ // Check, if we have to reopen a list or a list body:
+ // First condition:
+ // Paragraph is numbered/bulleted
+ if ( !bNumbered )
+ return;
+
+ const SwNumberTreeNode* pParent = pNodeNum->GetParent();
+ const bool bSameNumbering = lcl_HasPreviousParaSameNumRule(*pTxtNd);
+
+ // Second condition: current numbering is not 'interrupted'
+ if ( bSameNumbering )
+ {
+ sal_Int32 nReopenTag = -1;
+
+ // Two cases:
+ // 1. We have to reopen an existing list body tag:
+ // - If the current node is either the first child of its parent
+ // and its level > 1 or
+ // - Numbering should restart at the current node and its level > 1
+ // - The current item has no label
+ const bool bNewSubListStart = pParent->GetParent() && (pParent->IsFirst( pNodeNum ) || pTxtNd->IsListRestart() );
+ const bool bNoLabel = !pTxtNd->IsCountedInList() && !pTxtNd->IsListRestart();
+ if ( bNewSubListStart || bNoLabel )
+ {
+ // Fine, we try to reopen the appropriate list body
+ NumListBodyIdMap& rNumListBodyIdMap = SwEnhancedPDFExportHelper::GetNumListBodyIdMap();
+
+ if ( bNewSubListStart )
+ {
+ // The list body tag associated with the parent has to be reopened
+ // to start a new list inside the list body
+ NumListBodyIdMap::const_iterator aIter;
+
+ do
+ aIter = rNumListBodyIdMap.find( pParent );
+ while ( aIter == rNumListBodyIdMap.end() && 0 != ( pParent = pParent->GetParent() ) );
+
+ if ( aIter != rNumListBodyIdMap.end() )
+ nReopenTag = (*aIter).second;
+ }
+ else // if(bNoLabel)
+ {
+ // The list body tag of a 'counted' predecessor has to be reopened
+ const SwNumberTreeNode* pPrevious = pNodeNum->GetPred(true);
+ while ( pPrevious )
+ {
+ if ( pPrevious->IsCounted())
+ {
+ // get id of list body tag
+ const NumListBodyIdMap::const_iterator aIter = rNumListBodyIdMap.find( pPrevious );
+ if ( aIter != rNumListBodyIdMap.end() )
+ {
+ nReopenTag = (*aIter).second;
+ break;
+ }
+ }
+ pPrevious = pPrevious->GetPred(true);
+ }
+ }
+ }
+ // 2. We have to reopen an existing list tag:
+ else if ( !pParent->IsFirst( pNodeNum ) && !pTxtNd->IsListRestart() )
+ {
+ // any other than the first node in a list level has to reopen the current
+ // list. The current list is associated in a map with the first child of the list:
+ NumListIdMap& rNumListIdMap = SwEnhancedPDFExportHelper::GetNumListIdMap();
+
+ // Search backwards and check if any of the previous nodes has a list associated with it:
+ const SwNumberTreeNode* pPrevious = pNodeNum->GetPred(true);
+ while ( pPrevious )
+ {
+ // get id of list tag
+ const NumListIdMap::const_iterator aIter = rNumListIdMap.find( pPrevious );
+ if ( aIter != rNumListIdMap.end() )
+ {
+ nReopenTag = (*aIter).second;
+ break;
+ }
+
+ pPrevious = pPrevious->GetPred(true);
+ }
+ }
+
+ if ( -1 != nReopenTag )
+ {
+ nRestoreCurrentTag = mpPDFExtOutDevData->GetCurrentStructureElement();
+ mpPDFExtOutDevData->SetCurrentStructureElement( nReopenTag );
+
+#if OSL_DEBUG_LEVEL > 1
+ aStructStack.push_back( 99 );
+#endif
+ }
+ }
+ else
+ {
+ // clear list maps in case a list has been interrupted
+ NumListIdMap& rNumListIdMap = SwEnhancedPDFExportHelper::GetNumListIdMap();
+ rNumListIdMap.clear();
+ NumListBodyIdMap& rNumListBodyIdMap = SwEnhancedPDFExportHelper::GetNumListBodyIdMap();
+ rNumListBodyIdMap.clear();
+ }
+
+ // New tags:
+ const bool bNewListTag = (pNodeNum->GetParent()->IsFirst( pNodeNum ) || pTxtNd->IsListRestart() || !bSameNumbering);
+ const bool bNewItemTag = bNewListTag || pTxtNd->IsCountedInList(); // If the text node is not counted, we do not start a new list item:
+
+ if ( bNewListTag )
+ BeginTag( vcl::PDFWriter::List, aListString );
+
+ if ( bNewItemTag )
+ {
+ BeginTag( vcl::PDFWriter::ListItem, aListItemString );
+ BeginTag( vcl::PDFWriter::LIBody, aListBodyString );
+ }
+}
+
+/*
+ * SwTaggedPDFHelper::BeginBlockStructureElements()
+ */
+void SwTaggedPDFHelper::BeginBlockStructureElements()
+{
+ const SwFrm* pFrm = &mpFrmInfo->mrFrm;
+
+ //
+ // Lowers of NonStructureElements should not be considered:
+ //
+ if ( lcl_IsInNonStructEnv( *pFrm ) )
+ return;
+
+ // Check if we have to reopen an existing structure element.
+ // This has to be done e.g., if pFrm is a follow frame.
+ if ( CheckReopenTag() )
+ return;
+
+ sal_uInt16 nPDFType = USHRT_MAX;
+ String aPDFType;
+
+ switch ( pFrm->GetType() )
+ {
+ /*
+ * GROUPING ELEMENTS
+ */
+
+ case FRM_PAGE :
+ //
+ // Document: Document
+ //
+ nPDFType = vcl::PDFWriter::Document;
+ aPDFType = aDocumentString;
+ break;
+
+ case FRM_HEADER :
+ case FRM_FOOTER :
+ //
+ // Header, Footer: NonStructElement
+ //
+ nPDFType = vcl::PDFWriter::NonStructElement;
+ break;
+
+ case FRM_FTNCONT :
+ //
+ // Footnote container: Division
+ //
+ nPDFType = vcl::PDFWriter::Division;
+ aPDFType = aDivString;
+ break;
+
+ case FRM_FTN :
+ //
+ // Footnote frame: Note
+ //
+ // Note: vcl::PDFWriter::Note is actually a ILSE. Nevertheless
+ // we treat it like a grouping element!
+ nPDFType = vcl::PDFWriter::Note;
+ aPDFType = aNoteString;
+ break;
+
+ case FRM_SECTION :
+ //
+ // Section: TOX, Index, or Sect
+ //
+ {
+ const SwSection* pSection =
+ static_cast<const SwSectionFrm*>(pFrm)->GetSection();
+ if ( TOX_CONTENT_SECTION == pSection->GetType() )
+ {
+ const SwTOXBase* pTOXBase = pSection->GetTOXBase();
+ if ( pTOXBase )
+ {
+ if ( TOX_INDEX == pTOXBase->GetType() )
+ {
+ nPDFType = vcl::PDFWriter::Index;
+ aPDFType = aIndexString;
+ }
+ else
+ {
+ nPDFType = vcl::PDFWriter::TOC;
+ aPDFType = aTOCString;
+ }
+ }
+ }
+ else if ( CONTENT_SECTION == pSection->GetType() )
+ {
+ nPDFType = vcl::PDFWriter::Section;
+ aPDFType = aSectString;
+ }
+ }
+ break;
+
+ /*
+ * BLOCK-LEVEL STRUCTURE ELEMENTS
+ */
+
+ case FRM_TXT :
+ {
+ const SwTxtNode* pTxtNd =
+ static_cast<const SwTxtFrm*>(pFrm)->GetTxtNode();
+
+ const SwFmt* pTxtFmt = pTxtNd->GetFmtColl();
+ const SwFmt* pParentTxtFmt = pTxtFmt ? pTxtFmt->DerivedFrom() : NULL;
+
+ String sStyleName;
+ String sParentStyleName;
+
+ if ( pTxtFmt)
+ SwStyleNameMapper::FillProgName( pTxtFmt->GetName(), sStyleName, nsSwGetPoolIdFromName::GET_POOLID_TXTCOLL, sal_True );
+ if ( pParentTxtFmt)
+ SwStyleNameMapper::FillProgName( pParentTxtFmt->GetName(), sParentStyleName, nsSwGetPoolIdFromName::GET_POOLID_TXTCOLL, sal_True );
+
+ // This is the default. If the paragraph could not be mapped to
+ // any of the standard pdf tags, we write a user defined tag
+ // <stylename> with role = P
+ nPDFType = static_cast<sal_uInt16>(vcl::PDFWriter::Paragraph);
+ aPDFType = sStyleName;
+
+ //
+ // Quotations: BlockQuote
+ //
+ if ( sStyleName == aQuotations )
+ {
+ nPDFType = static_cast<sal_uInt16>(vcl::PDFWriter::BlockQuote);
+ aPDFType = aBlockQuoteString;
+ }
+
+ //
+ // Caption: Caption
+ //
+ else if ( sStyleName == aCaption)
+ {
+ nPDFType = static_cast<sal_uInt16>(vcl::PDFWriter::Caption);
+ aPDFType = aCaptionString;
+ }
+
+ //
+ // Caption: Caption
+ //
+ else if ( sParentStyleName == aCaption)
+ {
+ nPDFType = static_cast<sal_uInt16>(vcl::PDFWriter::Caption);
+ aPDFType = sStyleName.Append(aCaptionString);
+ }
+
+ //
+ // Heading: H
+ //
+ else if ( sStyleName == aHeading )
+ {
+ nPDFType = static_cast<sal_uInt16>(vcl::PDFWriter::Heading);
+ aPDFType = aHString;
+ }
+
+ //
+ // Heading: H1 - H6
+ //
+ if ( pTxtNd->IsOutline() )
+ {
+ //int nRealLevel = pTxtNd->GetOutlineLevel(); //#outline level,zhaojianwei
+ int nRealLevel = pTxtNd->GetAttrOutlineLevel()-1; //<-end,zhaojianwei
+ nRealLevel = nRealLevel > 5 ? 5 : nRealLevel;
+
+ nPDFType = static_cast<sal_uInt16>(vcl::PDFWriter::H1 + nRealLevel);
+ switch(nRealLevel)
+ {
+ case 0 :
+ aPDFType = aH1String;
+ break;
+ case 1 :
+ aPDFType = aH2String;
+ break;
+ case 2 :
+ aPDFType = aH3String;
+ break;
+ case 3 :
+ aPDFType = aH4String;
+ break;
+ case 4 :
+ aPDFType = aH5String;
+ break;
+ default:
+ aPDFType = aH6String;
+ break;
+ }
+ }
+
+ //
+ // Section: TOCI
+ //
+ else if ( pFrm->IsInSct() )
+ {
+ const SwSectionFrm* pSctFrm = pFrm->FindSctFrm();
+ const SwSection* pSection =
+ static_cast<const SwSectionFrm*>(pSctFrm)->GetSection();
+
+ if ( TOX_CONTENT_SECTION == pSection->GetType() )
+ {
+ const SwTOXBase* pTOXBase = pSection->GetTOXBase();
+ if ( pTOXBase && TOX_INDEX != pTOXBase->GetType() )
+ {
+ // Special case: Open additional TOCI tag:
+ BeginTag( vcl::PDFWriter::TOCI, aTOCIString );
+ }
+ }
+ }
+ }
+ break;
+
+ case FRM_TAB :
+ //
+ // TabFrm: Table
+ //
+ nPDFType = vcl::PDFWriter::Table;
+ aPDFType = aTableString;
+
+ {
+ // set up table column data:
+ const SwTabFrm* pTabFrm = static_cast<const SwTabFrm*>(pFrm);
+ const SwTable* pTable = pTabFrm->GetTable();
+
+ TableColumnsMap& rTableColumnsMap = SwEnhancedPDFExportHelper::GetTableColumnsMap();
+ const TableColumnsMap::const_iterator aIter = rTableColumnsMap.find( pTable );
+
+ if ( aIter == rTableColumnsMap.end() )
+ {
+ SWRECTFN( pTabFrm )
+ TableColumnsMapEntry& rCols = rTableColumnsMap[ pTable ];
+
+ const SwTabFrm* pMasterFrm = pTabFrm->IsFollow() ? pTabFrm->FindMaster( true ) : pTabFrm;
+
+ while ( pMasterFrm )
+ {
+ const SwRowFrm* pRowFrm = static_cast<const SwRowFrm*>(pMasterFrm->GetLower());
+
+ while ( pRowFrm )
+ {
+ const SwFrm* pCellFrm = pRowFrm->GetLower();
+
+ const long nLeft = (pCellFrm->Frm().*fnRect->fnGetLeft)();
+ rCols.insert( nLeft );
+
+ while ( pCellFrm )
+ {
+ const long nRight = (pCellFrm->Frm().*fnRect->fnGetRight)();
+ rCols.insert( nRight );
+ pCellFrm = pCellFrm->GetNext();
+ }
+ pRowFrm = static_cast<const SwRowFrm*>(pRowFrm->GetNext());
+ }
+ pMasterFrm = static_cast<const SwTabFrm*>(pMasterFrm->GetFollow());
+ }
+ }
+ }
+
+ break;
+
+ /*
+ * TABLE ELEMENTS
+ */
+
+ case FRM_ROW :
+ //
+ // RowFrm: TR
+ //
+ if ( !static_cast<const SwRowFrm*>(pFrm)->IsRepeatedHeadline() )
+ {
+ nPDFType = vcl::PDFWriter::TableRow;
+ aPDFType = aTRString;
+ }
+ else
+ {
+ nPDFType = vcl::PDFWriter::NonStructElement;
+ }
+ break;
+
+ case FRM_CELL :
+ //
+ // CellFrm: TH, TD
+ //
+ {
+ const SwTabFrm* pTable = static_cast<const SwCellFrm*>(pFrm)->FindTabFrm();
+ if ( pTable->IsInHeadline( *pFrm ) || lcl_IsHeadlineCell( *static_cast<const SwCellFrm*>(pFrm) ) )
+ {
+ nPDFType = vcl::PDFWriter::TableHeader;
+ aPDFType = aTHString;
+ }
+ else
+ {
+ nPDFType = vcl::PDFWriter::TableData;
+ aPDFType = aTDString;
+ }
+ }
+ break;
+
+ /*
+ * ILLUSTRATION
+ */
+
+ case FRM_FLY :
+ //
+ // FlyFrm: Figure, Formula, Control
+ // fly in content or fly at page
+ {
+ bool bFormula = false;
+ const SwFlyFrm* pFly = static_cast<const SwFlyFrm*>(pFrm);
+ if ( pFly->Lower() && pFly->Lower()->IsNoTxtFrm() )
+ {
+ const SwNoTxtFrm* pNoTxtFrm = static_cast<const SwNoTxtFrm*>(pFly->Lower());
+ SwOLENode* pOLENd = const_cast<SwOLENode*>(pNoTxtFrm->GetNode()->GetOLENode());
+ if ( pOLENd )
+ {
+ SwOLEObj& aOLEObj = pOLENd->GetOLEObj();
+ uno::Reference< embed::XEmbeddedObject > aRef = aOLEObj.GetOleRef();
+ if ( aRef.is() )
+ {
+ bFormula = 0 != SotExchange::IsMath( SvGlobalName( aRef->getClassID() ) );
+ }
+ }
+ if ( bFormula )
+ {
+ nPDFType = vcl::PDFWriter::Formula;
+ aPDFType = aFormulaString;
+ }
+ else
+ {
+ nPDFType = vcl::PDFWriter::Figure;
+ aPDFType = aFigureString;
+ }
+ }
+ else
+ {
+ nPDFType = vcl::PDFWriter::Division;
+ aPDFType = aDivString;
+ }
+ }
+ break;
+ }
+
+ if ( USHRT_MAX != nPDFType )
+ {
+ BeginTag( static_cast<vcl::PDFWriter::StructElement>(nPDFType), aPDFType );
+ }
+}
+
+
+/*
+ * SwTaggedPDFHelper::EndStructureElements()
+ */
+void SwTaggedPDFHelper::EndStructureElements()
+{
+ while ( nEndStructureElement > 0 )
+ {
+ EndTag();
+ --nEndStructureElement;
+ }
+
+ CheckRestoreTag();
+}
+
+
+/*
+ * SwTaggedPDFHelper::BeginInlineStructureElements()
+ */
+void SwTaggedPDFHelper::BeginInlineStructureElements()
+{
+ const SwLinePortion* pPor = &mpPorInfo->mrPor;
+ const SwTxtPaintInfo& rInf = mpPorInfo->mrTxtPainter.GetInfo();
+ const SwTxtFrm* pFrm = rInf.GetTxtFrm();
+
+ //
+ // Lowers of NonStructureElements should not be considered:
+ //
+ if ( lcl_IsInNonStructEnv( *pFrm ) )
+ return;
+
+ sal_uInt16 nPDFType = USHRT_MAX;
+ String aPDFType;
+
+ switch ( pPor->GetWhichPor() )
+ {
+ // Check for alternative spelling:
+ case POR_HYPHSTR :
+ case POR_SOFTHYPHSTR :
+ nPDFType = vcl::PDFWriter::Span;
+ aPDFType = aSpanString;
+ break;
+
+ case POR_LAY :
+ case POR_TXT :
+ case POR_PARA :
+ {
+ SwTxtNode* pNd = (SwTxtNode*)pFrm->GetTxtNode();
+ SwTxtAttr const*const pInetFmtAttr =
+ pNd->GetTxtAttrAt(rInf.GetIdx(), RES_TXTATR_INETFMT);
+
+ String sStyleName;
+ if ( !pInetFmtAttr )
+ {
+ ::std::vector<SwTxtAttr *> const charAttrs(
+ pNd->GetTxtAttrsAt(rInf.GetIdx(), RES_TXTATR_CHARFMT));
+ // TODO: handle more than 1 char style?
+ const SwCharFmt* pCharFmt = (charAttrs.size())
+ ? (*charAttrs.begin())->GetCharFmt().GetCharFmt() : 0;
+ if ( pCharFmt )
+ SwStyleNameMapper::FillProgName( pCharFmt->GetName(), sStyleName, nsSwGetPoolIdFromName::GET_POOLID_TXTCOLL, sal_True );
+ }
+
+ // Check for Link:
+ if( pInetFmtAttr )
+ {
+ nPDFType = vcl::PDFWriter::Link;
+ aPDFType = aLinkString;
+ }
+ // Check for Quote/Code character style:
+ else if ( sStyleName == aQuotation )
+ {
+ nPDFType = vcl::PDFWriter::Quote;
+ aPDFType = aQuoteString;
+ }
+ else if ( sStyleName == aSourceText )
+ {
+ nPDFType = vcl::PDFWriter::Code;
+ aPDFType = aCodeString;
+ }
+ else
+ {
+ const LanguageType nCurrentLanguage = rInf.GetFont()->GetLanguage();
+ const sal_uInt16 nFont = rInf.GetFont()->GetActual();
+ const LanguageType nDefaultLang = SwEnhancedPDFExportHelper::GetDefaultLanguage();
+
+ if ( UNDERLINE_NONE != rInf.GetFont()->GetUnderline() ||
+ UNDERLINE_NONE != rInf.GetFont()->GetOverline() ||
+ STRIKEOUT_NONE != rInf.GetFont()->GetStrikeout() ||
+ EMPHASISMARK_NONE != rInf.GetFont()->GetEmphasisMark() ||
+ 0 != rInf.GetFont()->GetEscapement() ||
+ SW_LATIN != nFont ||
+ nCurrentLanguage != nDefaultLang ||
+ sStyleName.Len() > 0 )
+ {
+ nPDFType = vcl::PDFWriter::Span;
+ if ( sStyleName.Len() > 0 )
+ aPDFType = sStyleName;
+ else
+ aPDFType = aSpanString;
+ }
+ }
+ }
+ break;
+
+ case POR_FTN :
+ nPDFType = vcl::PDFWriter::Link;
+ aPDFType = aLinkString;
+ break;
+
+ case POR_FLD :
+ {
+ // check field type:
+ const xub_StrLen nIdx = static_cast<const SwFldPortion*>(pPor)->IsFollow() ?
+ rInf.GetIdx() - 1 :
+ rInf.GetIdx();
+ const SwTxtAttr* pHint = mpPorInfo->mrTxtPainter.GetAttr( nIdx );
+ const SwField* pFld = 0;
+ if ( pHint && RES_TXTATR_FIELD == pHint->Which() )
+ {
+ pFld = (SwField*)pHint->GetFld().GetFld();
+ if ( RES_GETREFFLD == pFld->Which() )
+ {
+ nPDFType = vcl::PDFWriter::Link;
+ aPDFType = aLinkString;
+ }
+ else if ( RES_AUTHORITY == pFld->Which() )
+ {
+ nPDFType = vcl::PDFWriter::BibEntry;
+ aPDFType = aBibEntryString;
+ }
+ }
+ }
+ break;
+
+ case POR_TAB :
+ case POR_TABRIGHT :
+ case POR_TABCENTER :
+ case POR_TABDECIMAL :
+ nPDFType = vcl::PDFWriter::NonStructElement;
+ break;
+ }
+
+ if ( USHRT_MAX != nPDFType )
+ {
+ BeginTag( static_cast<vcl::PDFWriter::StructElement>(nPDFType), aPDFType );
+ }
+}
+
+/*
+ * static SwTaggedPDFHelper::IsExportTaggedPDF
+ */
+ bool SwTaggedPDFHelper::IsExportTaggedPDF( const OutputDevice& rOut )
+ {
+ vcl::PDFExtOutDevData* pPDFExtOutDevData = PTR_CAST( vcl::PDFExtOutDevData, rOut.GetExtOutDevData() );
+ return pPDFExtOutDevData && pPDFExtOutDevData->GetIsExportTaggedPDF();
+ }
+
+/*
+ * SwEnhancedPDFExportHelper::SwEnhancedPDFExportHelper()
+ */
+SwEnhancedPDFExportHelper::SwEnhancedPDFExportHelper( SwEditShell& rSh,
+ OutputDevice& rOut,
+ const rtl::OUString& rPageRange,
+ bool bSkipEmptyPages,
+ bool bEditEngineOnly )
+ : mrSh( rSh ),
+ mrOut( rOut ),
+ pPageRange( 0 ),
+ mbSkipEmptyPages( bSkipEmptyPages ),
+ mbEditEngineOnly( bEditEngineOnly )
+{
+ if ( rPageRange.getLength() )
+ pPageRange = new MultiSelection( rPageRange );
+
+ aTableColumnsMap.clear();
+ aLinkIdMap.clear();
+ aNumListIdMap.clear();
+ aNumListBodyIdMap.clear();
+ aFrmTagIdMap.clear();
+
+#if OSL_DEBUG_LEVEL > 1
+ aStructStack.clear();
+#endif
+
+ const sal_uInt8 nScript = (sal_uInt8)GetI18NScriptTypeOfLanguage( (sal_uInt16)GetAppLanguage() );
+ sal_uInt16 nLangRes = RES_CHRATR_LANGUAGE;
+
+ if ( i18n::ScriptType::ASIAN == nScript )
+ nLangRes = RES_CHRATR_CJK_LANGUAGE;
+ else if ( i18n::ScriptType::COMPLEX == nScript )
+ nLangRes = RES_CHRATR_CTL_LANGUAGE;
+
+ eLanguageDefault = static_cast<const SvxLanguageItem*>(&mrSh.GetDoc()->GetDefault( nLangRes ))->GetLanguage();
+
+ EnhancedPDFExport();
+}
+
+SwEnhancedPDFExportHelper::~SwEnhancedPDFExportHelper()
+{
+ delete pPageRange;
+}
+
+/*
+ * SwEnhancedPDFExportHelper::EnhancedPDFExport()
+ */
+void SwEnhancedPDFExportHelper::EnhancedPDFExport()
+{
+ vcl::PDFExtOutDevData* pPDFExtOutDevData =
+ PTR_CAST( vcl::PDFExtOutDevData, mrOut.GetExtOutDevData() );
+
+ if ( !pPDFExtOutDevData )
+ return;
+
+ //
+ // set the document locale
+ //
+ com::sun::star::lang::Locale aDocLocale = MsLangId::convertLanguageToLocale( SwEnhancedPDFExportHelper::GetDefaultLanguage() );
+ pPDFExtOutDevData->SetDocumentLocale( aDocLocale );
+
+ //
+ // Prepare the output device:
+ //
+ mrOut.Push( PUSH_MAPMODE );
+ MapMode aMapMode( mrOut.GetMapMode() );
+ aMapMode.SetMapUnit( MAP_TWIP );
+ mrOut.SetMapMode( aMapMode );
+
+ //
+ // Create new cursor and lock the view:
+ //
+ SwDoc* pDoc = mrSh.GetDoc();
+ mrSh.SwCrsrShell::Push();
+ mrSh.SwCrsrShell::ClearMark();
+ const sal_Bool bOldLockView = mrSh.IsViewLocked();
+ mrSh.LockView( sal_True );
+
+ if ( !mbEditEngineOnly )
+ {
+ //
+ // POSTITS
+ //
+ if ( pPDFExtOutDevData->GetIsExportNotes() )
+ {
+ SwFieldType* pType = mrSh.GetFldType( RES_POSTITFLD, aEmptyStr );
+ SwIterator<SwFmtFld,SwFieldType> aIter( *pType );
+ for( SwFmtFld* pFirst = aIter.First(); pFirst; )
+ {
+ if( pFirst->GetTxtFld() && pFirst->IsFldInDoc() )
+ {
+ const SwTxtNode* pTNd = (SwTxtNode*)pFirst->GetTxtFld()->GetpTxtNode();
+ OSL_ENSURE( 0 != pTNd, "Enhanced pdf export - text node is missing" );
+
+ // 1. Check if the whole paragraph is hidden
+ // 2. Move to the field
+ // 3. Check for hidden text attribute
+ if ( !pTNd->IsHidden() &&
+ mrSh.GotoFld( *pFirst ) &&
+ !mrSh.SelectHiddenRange() )
+ {
+ // Link Rectangle
+ const SwRect& rNoteRect = mrSh.GetCharRect();
+
+ // Link PageNum
+ const sal_Int32 nNotePageNum = CalcOutputPageNum( rNoteRect );
+ if ( -1 != nNotePageNum )
+ {
+ // Link Note
+ vcl::PDFNote aNote;
+
+ // Use the NumberFormatter to get the date string:
+ const SwPostItField* pField = (SwPostItField*)pFirst->GetFld();
+ SvNumberFormatter* pNumFormatter = pDoc->GetNumberFormatter();
+ const Date aDateDiff( pField->GetDate() -
+ *pNumFormatter->GetNullDate() );
+ const sal_uLong nFormat =
+ pNumFormatter->GetStandardFormat( NUMBERFORMAT_DATE, pField->GetLanguage() );
+ String sDate;
+ Color* pColor;
+ pNumFormatter->GetOutputString( aDateDiff.GetDate(), nFormat, sDate, &pColor );
+
+ // The title should consist of the author and the date:
+ String sTitle( pField->GetPar1() );
+ sTitle.AppendAscii( RTL_CONSTASCII_STRINGPARAM( ", " ) );
+ sTitle += sDate;
+ aNote.Title = sTitle;
+ // Guess what the contents contains...
+ aNote.Contents = pField->GetTxt();
+
+ // Link Export
+ pPDFExtOutDevData->CreateNote( rNoteRect.SVRect(), aNote, nNotePageNum );
+ }
+ }
+ }
+ pFirst = aIter.Next();
+ mrSh.SwCrsrShell::ClearMark();
+ }
+ }
+
+ //
+ // HYPERLINKS
+ //
+ SwGetINetAttrs aArr;
+ const sal_uInt16 nHyperLinkCount = mrSh.GetINetAttrs( aArr );
+ for( sal_uInt16 n = 0; n < nHyperLinkCount; ++n )
+ {
+ SwGetINetAttr* p = aArr[ n ];
+ OSL_ENSURE( 0 != p, "Enhanced pdf export - SwGetINetAttr is missing" );
+
+ const SwTxtNode* pTNd = p->rINetAttr.GetpTxtNode();
+ OSL_ENSURE( 0 != pTNd, "Enhanced pdf export - text node is missing" );
+
+ // 1. Check if the whole paragraph is hidden
+ // 2. Move to the hyperlink
+ // 3. Check for hidden text attribute
+ if ( !pTNd->IsHidden() &&
+ mrSh.GotoINetAttr( p->rINetAttr ) &&
+ !mrSh.SelectHiddenRange() )
+ {
+ // Select the hyperlink:
+ mrSh.SwCrsrShell::Right( 1, CRSR_SKIP_CHARS );
+ if ( mrSh.SwCrsrShell::SelectTxtAttr( RES_TXTATR_INETFMT, sal_True ) )
+ {
+ // First, we create the destination, because there may be more
+ // than one link to this destination:
+ String aURL( INetURLObject::decode(
+ p->rINetAttr.GetINetFmt().GetValue(),
+ INET_HEX_ESCAPE,
+ INetURLObject::DECODE_UNAMBIGUOUS,
+ RTL_TEXTENCODING_UTF8 ) );
+
+ // We have to distinguish between intern and real URLs
+ const bool bIntern = '#' == aURL.GetChar( 0 );
+
+ // _GetCrsr() is a SwShellCrsr, which is derived from
+ // SwSelPaintRects, therefore the rectangles of the current
+ // selection can be easily obtained:
+ // Note: We make a copy of the rectangles, because they may
+ // be deleted again in JumpToSwMark.
+ SwRects aTmp;
+ aTmp.Insert( mrSh.SwCrsrShell::_GetCrsr(), 0 );
+ OSL_ENSURE( aTmp.Count() > 0, "Enhanced pdf export - rectangles are missing" );
+
+ // Create the destination for internal links:
+ sal_Int32 nDestId = -1;
+ if ( bIntern )
+ {
+ aURL.Erase( 0, 1 );
+ mrSh.SwCrsrShell::ClearMark();
+ JumpToSwMark( &mrSh, aURL );
+
+ // Destination Rectangle
+ const SwRect& rDestRect = mrSh.GetCharRect();
+
+ // Destination PageNum
+ const sal_Int32 nDestPageNum = CalcOutputPageNum( rDestRect );
+
+ // Destination Export
+ if ( -1 != nDestPageNum )
+ nDestId = pPDFExtOutDevData->CreateDest( rDestRect.SVRect(), nDestPageNum );
+ }
+
+ if ( !bIntern || -1 != nDestId )
+ {
+ // --> FME 2005-05-09 #i44368# Links in Header/Footer
+ const SwPosition aPos( *pTNd );
+ const bool bHeaderFooter = pDoc->IsInHeaderFooter( aPos.nNode );
+ // <--
+
+ // Create links for all selected rectangles:
+ const sal_uInt16 nNumOfRects = aTmp.Count();
+ for ( sal_uInt16 i = 0; i < nNumOfRects; ++i )
+ {
+ // Link Rectangle
+ const SwRect& rLinkRect( aTmp[ i ] );
+
+ // Link PageNum
+ const sal_Int32 nLinkPageNum = CalcOutputPageNum( rLinkRect );
+
+ if ( -1 != nLinkPageNum )
+ {
+ // Link Export
+ const sal_Int32 nLinkId =
+ pPDFExtOutDevData->CreateLink( rLinkRect.SVRect(), nLinkPageNum );
+
+ // Store link info for tagged pdf output:
+ const IdMapEntry aLinkEntry( rLinkRect, nLinkId );
+ aLinkIdMap.push_back( aLinkEntry );
+
+ // Connect Link and Destination:
+ if ( bIntern )
+ pPDFExtOutDevData->SetLinkDest( nLinkId, nDestId );
+ else
+ pPDFExtOutDevData->SetLinkURL( nLinkId, aURL );
+
+ // --> FME 2005-05-09 #i44368# Links in Header/Footer
+ if ( bHeaderFooter )
+ MakeHeaderFooterLinks( *pPDFExtOutDevData, *pTNd, rLinkRect, nDestId, aURL, bIntern );
+ // <--
+ }
+ }
+ }
+ }
+ }
+ mrSh.SwCrsrShell::ClearMark();
+ }
+
+ //
+ // HYPERLINKS (Graphics, Frames, OLEs )
+ //
+ const SwSpzFrmFmts* pTbl = pDoc->GetSpzFrmFmts();
+ const sal_uInt16 nSpzFrmFmtsCount = pTbl->Count();
+ for( sal_uInt16 n = 0; n < nSpzFrmFmtsCount; ++n )
+ {
+ const SwFrmFmt* pFrmFmt = (*pTbl)[n];
+ const SfxPoolItem* pItem;
+ if ( RES_DRAWFRMFMT != pFrmFmt->Which() &&
+ SFX_ITEM_SET == pFrmFmt->GetAttrSet().GetItemState( RES_URL, sal_True, &pItem ) )
+ {
+ String aURL( static_cast<const SwFmtURL*>(pItem)->GetURL() );
+ const bool bIntern = '#' == aURL.GetChar( 0 );
+
+ // Create the destination for internal links:
+ sal_Int32 nDestId = -1;
+ if ( bIntern )
+ {
+ aURL.Erase( 0, 1 );
+ mrSh.SwCrsrShell::ClearMark();
+ JumpToSwMark( &mrSh, aURL );
+
+ // Destination Rectangle
+ const SwRect& rDestRect = mrSh.GetCharRect();
+
+ // Destination PageNum
+ const sal_Int32 nDestPageNum = CalcOutputPageNum( rDestRect );
+
+ // Destination Export
+ if ( -1 != nDestPageNum )
+ nDestId = pPDFExtOutDevData->CreateDest( rDestRect.SVRect(), nDestPageNum );
+ }
+
+ if ( !bIntern || -1 != nDestId )
+ {
+ Point aNullPt;
+ const SwRect aLinkRect = pFrmFmt->FindLayoutRect( sal_False, &aNullPt );
+
+ // Link PageNum
+ const sal_Int32 nLinkPageNum = CalcOutputPageNum( aLinkRect );
+
+ // Link Export
+ if ( -1 != nLinkPageNum )
+ {
+ const sal_Int32 nLinkId =
+ pPDFExtOutDevData->CreateLink( aLinkRect.SVRect(), nLinkPageNum );
+
+ // Connect Link and Destination:
+ if ( bIntern )
+ pPDFExtOutDevData->SetLinkDest( nLinkId, nDestId );
+ else
+ pPDFExtOutDevData->SetLinkURL( nLinkId, aURL );
+
+ // --> FME 2005-05-09 #i44368# Links in Header/Footer
+ const SwFmtAnchor &rAnch = pFrmFmt->GetAnchor();
+ if (FLY_AT_PAGE != rAnch.GetAnchorId())
+ {
+ const SwPosition* pPosition = rAnch.GetCntntAnchor();
+ if ( pPosition && pDoc->IsInHeaderFooter( pPosition->nNode ) )
+ {
+ const SwTxtNode* pTNd = pPosition->nNode.GetNode().GetTxtNode();
+ if ( pTNd )
+ MakeHeaderFooterLinks( *pPDFExtOutDevData, *pTNd, aLinkRect, nDestId, aURL, bIntern );
+ }
+ }
+ // <--
+ }
+ }
+ }
+ mrSh.SwCrsrShell::ClearMark();
+ }
+
+ //
+ // REFERENCES
+ //
+ SwFieldType* pType = mrSh.GetFldType( RES_GETREFFLD, aEmptyStr );
+ SwIterator<SwFmtFld,SwFieldType> aIter( *pType );
+ for( SwFmtFld* pFirst = aIter.First(); pFirst; )
+ {
+ if( pFirst->GetTxtFld() && pFirst->IsFldInDoc() )
+ {
+ const SwTxtNode* pTNd = (SwTxtNode*)pFirst->GetTxtFld()->GetpTxtNode();
+ OSL_ENSURE( 0 != pTNd, "Enhanced pdf export - text node is missing" );
+
+ // 1. Check if the whole paragraph is hidden
+ // 2. Move to the field
+ // 3. Check for hidden text attribute
+ if ( !pTNd->IsHidden() &&
+ mrSh.GotoFld( *pFirst ) &&
+ !mrSh.SelectHiddenRange() )
+ {
+ // Select the field:
+ mrSh.SwCrsrShell::SetMark();
+ mrSh.SwCrsrShell::Right( 1, CRSR_SKIP_CHARS );
+
+ // Link Rectangles
+ SwRects aTmp;
+ aTmp.Insert( mrSh.SwCrsrShell::_GetCrsr(), 0 );
+ OSL_ENSURE( aTmp.Count() > 0, "Enhanced pdf export - rectangles are missing" );
+
+ mrSh.SwCrsrShell::ClearMark();
+
+ // Destination Rectangle
+ const SwGetRefField* pField =
+ (SwGetRefField*)pFirst->GetFld();
+ const String& rRefName = pField->GetSetRefName();
+ mrSh.GotoRefMark( rRefName, pField->GetSubType(), pField->GetSeqNo() );
+ const SwRect& rDestRect = mrSh.GetCharRect();
+
+ // Destination PageNum
+ const sal_Int32 nDestPageNum = CalcOutputPageNum( rDestRect );
+
+ if ( -1 != nDestPageNum )
+ {
+ // Destination Export
+ const sal_Int32 nDestId = pPDFExtOutDevData->CreateDest( rDestRect.SVRect(), nDestPageNum );
+
+ // --> FME 2005-05-09 #i44368# Links in Header/Footer
+ const SwPosition aPos( *pTNd );
+ const bool bHeaderFooter = pDoc->IsInHeaderFooter( aPos.nNode );
+ // <--
+
+ // Create links for all selected rectangles:
+ const sal_uInt16 nNumOfRects = aTmp.Count();
+ for ( sal_uInt16 i = 0; i < nNumOfRects; ++i )
+ {
+ // Link rectangle
+ const SwRect& rLinkRect( aTmp[ i ] );
+
+ // Link PageNum
+ const sal_Int32 nLinkPageNum = CalcOutputPageNum( rLinkRect );
+
+ if ( -1 != nLinkPageNum )
+ {
+ // Link Export
+ const sal_Int32 nLinkId =
+ pPDFExtOutDevData->CreateLink( rLinkRect.SVRect(), nLinkPageNum );
+
+ // Store link info for tagged pdf output:
+ const IdMapEntry aLinkEntry( rLinkRect, nLinkId );
+ aLinkIdMap.push_back( aLinkEntry );
+
+ // Connect Link and Destination:
+ pPDFExtOutDevData->SetLinkDest( nLinkId, nDestId );
+
+ // --> FME 2005-05-09 #i44368# Links in Header/Footer
+ if ( bHeaderFooter )
+ {
+ const String aDummy;
+ MakeHeaderFooterLinks( *pPDFExtOutDevData, *pTNd, rLinkRect, nDestId, aDummy, true );
+ }
+ // <--
+ }
+ }
+ }
+ }
+ }
+ pFirst = aIter.Next();
+ mrSh.SwCrsrShell::ClearMark();
+ }
+
+ //
+ // FOOTNOTES
+ //
+ const sal_uInt16 nFtnCount = pDoc->GetFtnIdxs().Count();
+ for ( sal_uInt16 nIdx = 0; nIdx < nFtnCount; ++nIdx )
+ {
+ // Set cursor to text node that contains the footnote:
+ const SwTxtFtn* pTxtFtn = pDoc->GetFtnIdxs()[ nIdx ];
+ SwTxtNode& rTNd = const_cast<SwTxtNode&>(pTxtFtn->GetTxtNode());
+
+ mrSh._GetCrsr()->GetPoint()->nNode = rTNd;
+ mrSh._GetCrsr()->GetPoint()->nContent.Assign( &rTNd, *pTxtFtn->GetStart() );
+
+ // 1. Check if the whole paragraph is hidden
+ // 2. Check for hidden text attribute
+ if ( static_cast<const SwTxtNode&>(rTNd).IsHidden() ||
+ mrSh.SelectHiddenRange() )
+ continue;
+
+ SwCrsrSaveState aSaveState( *mrSh._GetCrsr() );
+
+ // Select the footnote:
+ mrSh.SwCrsrShell::SetMark();
+ mrSh.SwCrsrShell::Right( 1, CRSR_SKIP_CHARS );
+
+ // Link Rectangle
+ SwRects aTmp;
+ aTmp.Insert( mrSh.SwCrsrShell::_GetCrsr(), 0 );
+ OSL_ENSURE( aTmp.Count() > 0, "Enhanced pdf export - rectangles are missing" );
+ const SwRect aLinkRect( aTmp[ 0 ] );
+
+ mrSh._GetCrsr()->RestoreSavePos();
+ mrSh.SwCrsrShell::ClearMark();
+
+ // Goto footnote text:
+ if ( mrSh.GotoFtnTxt() )
+ {
+ // Link PageNum
+ const sal_Int32 nLinkPageNum = CalcOutputPageNum( aLinkRect );
+
+ if ( -1 != nLinkPageNum )
+ {
+ // Link Export
+ const sal_Int32 nLinkId =
+ pPDFExtOutDevData->CreateLink( aLinkRect.SVRect(), nLinkPageNum );
+
+ // Store link info for tagged pdf output:
+ const IdMapEntry aLinkEntry( aLinkRect, nLinkId );
+ aLinkIdMap.push_back( aLinkEntry );
+
+ // Destination Rectangle
+ const SwRect& rDestRect = mrSh.GetCharRect();
+
+ // Destination PageNum
+ const sal_Int32 nDestPageNum = CalcOutputPageNum( rDestRect );
+
+ if ( -1 != nDestPageNum )
+ {
+ // Destination Export
+ const sal_Int32 nDestId = pPDFExtOutDevData->CreateDest( rDestRect.SVRect(), nDestPageNum );
+
+ // Connect Link and Destination:
+ pPDFExtOutDevData->SetLinkDest( nLinkId, nDestId );
+ }
+ }
+ }
+ }
+
+ //
+ // OUTLINE
+ //
+ if( pPDFExtOutDevData->GetIsExportBookmarks() )
+ {
+ typedef std::pair< sal_Int8, sal_Int32 > StackEntry;
+ std::stack< StackEntry > aOutlineStack;
+ aOutlineStack.push( StackEntry( -1, -1 ) ); // push default value
+
+ const sal_uInt16 nOutlineCount =
+ static_cast<sal_uInt16>(mrSh.getIDocumentOutlineNodesAccess()->getOutlineNodesCount());
+ for ( sal_uInt16 i = 0; i < nOutlineCount; ++i )
+ {
+ // Check if outline is hidden
+ const SwTxtNode* pTNd = mrSh.GetNodes().GetOutLineNds()[ i ]->GetTxtNode();
+ OSL_ENSURE( 0 != pTNd, "Enhanced pdf export - text node is missing" );
+
+ if ( pTNd->IsHidden() ||
+ // --> FME 2005-01-10 #i40292# Skip empty outlines:
+ 0 == pTNd->GetTxt().Len() )
+ // <--
+ continue;
+
+ // Get parent id from stack:
+ const sal_Int8 nLevel = (sal_Int8)mrSh.getIDocumentOutlineNodesAccess()->getOutlineLevel( i );
+ sal_Int8 nLevelOnTopOfStack = aOutlineStack.top().first;
+ while ( nLevelOnTopOfStack >= nLevel &&
+ nLevelOnTopOfStack != -1 )
+ {
+ aOutlineStack.pop();
+ nLevelOnTopOfStack = aOutlineStack.top().first;
+ }
+ const sal_Int32 nParent = aOutlineStack.top().second;
+
+ // Destination rectangle
+ mrSh.GotoOutline(i);
+ const SwRect& rDestRect = mrSh.GetCharRect();
+
+ // Destination PageNum
+ const sal_Int32 nDestPageNum = CalcOutputPageNum( rDestRect );
+
+ if ( -1 != nDestPageNum )
+ {
+ // Destination Export
+ const sal_Int32 nDestId =
+ pPDFExtOutDevData->CreateDest( rDestRect.SVRect(), nDestPageNum );
+
+ // Outline entry text
+ const String& rEntry = mrSh.getIDocumentOutlineNodesAccess()->getOutlineText( i );
+
+ // Create a new outline item:
+ const sal_Int32 nOutlineId =
+ pPDFExtOutDevData->CreateOutlineItem( nParent, rEntry, nDestId );
+
+ // Push current level and nOutlineId on stack:
+ aOutlineStack.push( StackEntry( nLevel, nOutlineId ) );
+ }
+ }
+ }
+
+ if( pPDFExtOutDevData->GetIsExportNamedDestinations() )
+ {
+ //---> i56629 the iteration to convert the OOo bookmark (#bookmark)
+ // into PDF named destination, see section 8.2.1 in PDF 1.4 spec
+ // We need:
+ // 1. a name for the destination, formed from the standard OOo bookmark name
+ // 2. the destination, obtained from where the bookmark destination lies
+ IDocumentMarkAccess* const pMarkAccess = mrSh.GetDoc()->getIDocumentMarkAccess();
+ for(IDocumentMarkAccess::const_iterator_t ppMark = pMarkAccess->getBookmarksBegin();
+ ppMark != pMarkAccess->getBookmarksEnd();
+ ppMark++)
+ {
+ //get the name
+ const ::sw::mark::IMark* pBkmk = ppMark->get();
+ mrSh.SwCrsrShell::ClearMark();
+ rtl::OUString sBkName = pBkmk->GetName();
+
+ //jump to it
+ JumpToSwMark( &mrSh, sBkName );
+
+ // Destination Rectangle
+ const SwRect& rDestRect = mrSh.GetCharRect();
+
+ // Destination PageNum
+ const sal_Int32 nDestPageNum = CalcOutputPageNum( rDestRect );
+
+ // Destination Export
+ if ( -1 != nDestPageNum )
+ pPDFExtOutDevData->CreateNamedDest( sBkName, rDestRect.SVRect(), nDestPageNum );
+ }
+ mrSh.SwCrsrShell::ClearMark();
+ //<--- i56629
+ }
+ }
+ else
+ {
+ //
+ // LINKS FROM EDITENGINE
+ //
+ std::vector< vcl::PDFExtOutDevBookmarkEntry >& rBookmarks = pPDFExtOutDevData->GetBookmarks();
+ std::vector< vcl::PDFExtOutDevBookmarkEntry >::const_iterator aIBeg = rBookmarks.begin();
+ const std::vector< vcl::PDFExtOutDevBookmarkEntry >::const_iterator aIEnd = rBookmarks.end();
+ while ( aIBeg != aIEnd )
+ {
+ String aBookmarkName( aIBeg->aBookmark );
+ const bool bIntern = '#' == aBookmarkName.GetChar( 0 );
+ if ( bIntern )
+ {
+ aBookmarkName.Erase( 0, 1 );
+ JumpToSwMark( &mrSh, aBookmarkName );
+
+ // Destination Rectangle
+ const SwRect& rDestRect = mrSh.GetCharRect();
+
+ // Destination PageNum
+ const sal_Int32 nDestPageNum = CalcOutputPageNum( rDestRect );
+
+ if ( -1 != nDestPageNum )
+ {
+ // Destination Export
+ const sal_Int32 nDestId =
+ pPDFExtOutDevData->CreateDest( rDestRect.SVRect(), nDestPageNum );
+
+ // Connect Link and Destination:
+ pPDFExtOutDevData->SetLinkDest( aIBeg->nLinkId, nDestId );
+ }
+ }
+ else
+ pPDFExtOutDevData->SetLinkURL( aIBeg->nLinkId, aBookmarkName );
+
+ ++aIBeg;
+ }
+ rBookmarks.clear();
+ }
+
+ // Restore view, cursor, and outdev:
+ mrSh.LockView( bOldLockView );
+ mrSh.SwCrsrShell::Pop( sal_False );
+ mrOut.Pop();
+}
+
+/*
+ * SwEnhancedPDFExportHelper::CalcOutputPageNum()
+ */
+sal_Int32 SwEnhancedPDFExportHelper::CalcOutputPageNum( const SwRect& rRect ) const
+{
+ // Document page numbers are 0, 1, 2, ...
+ const sal_Int32 nPageNumOfRect = mrSh.GetPageNumAndSetOffsetForPDF( mrOut, rRect );
+
+ // Shortcut:
+ if ( -1 == nPageNumOfRect || ( !pPageRange && !mbSkipEmptyPages ) )
+ return nPageNumOfRect;
+
+ // pPageRange page numbers are 1, 2, 3, ...
+ if ( pPageRange && !pPageRange->IsSelected( nPageNumOfRect + 1 ) )
+ return -1;
+
+ // What will be the page number of page nPageNumOfRect in the output doc?
+ sal_Int32 nOutputPageNum = -1;
+ const SwRootFrm* pRootFrm = mrSh.GetLayout();
+ const SwPageFrm* pCurrPage = static_cast<const SwPageFrm*>(pRootFrm->Lower());
+
+ for ( sal_Int32 nPageIndex = 0;
+ nPageIndex <= nPageNumOfRect && pCurrPage;
+ ++nPageIndex )
+ {
+ if ( ( !pPageRange || pPageRange->IsSelected( nPageIndex + 1 ) ) &&
+ ( !mbSkipEmptyPages || !pCurrPage->IsEmptyPage() ) )
+ ++nOutputPageNum;
+
+ pCurrPage = static_cast<const SwPageFrm*>(pCurrPage->GetNext());
+ }
+
+ // pdf export page numbers are 0, 1, 2, ...
+ return nOutputPageNum;
+}
+
+void SwEnhancedPDFExportHelper::MakeHeaderFooterLinks( vcl::PDFExtOutDevData& rPDFExtOutDevData,
+ const SwTxtNode& rTNd,
+ const SwRect& rLinkRect,
+ sal_Int32 nDestId,
+ const String& rURL,
+ bool bIntern ) const
+{
+ // We assume, that the primary link has just been exported. Therefore
+ // the offset of the link rectangle calculates as follows:
+ const Point aOffset = rLinkRect.Pos() + mrOut.GetMapMode().GetOrigin();
+
+ SwIterator<SwTxtFrm,SwTxtNode> aIter( rTNd );
+ for ( SwTxtFrm* pTmpFrm = aIter.First(); pTmpFrm; pTmpFrm = aIter.Next() )
+ {
+ // Add offset to current page:
+ const SwPageFrm* pPageFrm = pTmpFrm->FindPageFrm();
+ SwRect aHFLinkRect( rLinkRect );
+ aHFLinkRect.Pos() = pPageFrm->Frm().Pos() + aOffset;
+
+ // #i97135# the gcc_x64 optimizer gets aHFLinkRect != rLinkRect wrong
+ // fool it by comparing the position only (the width and height are the
+ // same anyway)
+ if ( aHFLinkRect.Pos() != rLinkRect.Pos() )
+ {
+ // Link PageNum
+ const sal_Int32 nHFLinkPageNum = CalcOutputPageNum( aHFLinkRect );
+
+ if ( -1 != nHFLinkPageNum )
+ {
+ // Link Export
+ const sal_Int32 nHFLinkId =
+ rPDFExtOutDevData.CreateLink( aHFLinkRect.SVRect(), nHFLinkPageNum );
+
+ // Connect Link and Destination:
+ if ( bIntern )
+ rPDFExtOutDevData.SetLinkDest( nHFLinkId, nDestId );
+ else
+ rPDFExtOutDevData.SetLinkURL( nHFLinkId, rURL );
+ }
+ }
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/text/SwGrammarMarkUp.cxx b/sw/source/core/text/SwGrammarMarkUp.cxx
new file mode 100644
index 000000000000..b3873d6b7ff9
--- /dev/null
+++ b/sw/source/core/text/SwGrammarMarkUp.cxx
@@ -0,0 +1,168 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+#include "SwGrammarMarkUp.hxx"
+
+SwGrammarMarkUp::~SwGrammarMarkUp()
+{
+}
+
+SwWrongList* SwGrammarMarkUp::Clone()
+{
+ SwWrongList* pClone = new SwGrammarMarkUp();
+ pClone->CopyFrom( *this );
+ return pClone;
+}
+
+void SwGrammarMarkUp::CopyFrom( const SwWrongList& rCopy )
+{
+ maSentence = ((const SwGrammarMarkUp&)rCopy).maSentence;
+ SwWrongList::CopyFrom( rCopy );
+}
+
+
+void SwGrammarMarkUp::MoveGrammar( xub_StrLen nPos, long nDiff )
+{
+ Move( nPos, nDiff );
+ if( !maSentence.size() )
+ return;
+ std::vector< xub_StrLen >::iterator pIter = maSentence.begin();
+ while( pIter != maSentence.end() && *pIter < nPos )
+ ++pIter;
+ xub_StrLen nEnd = nDiff < 0 ? xub_StrLen(nPos - nDiff) : nPos;
+ while( pIter != maSentence.end() )
+ {
+ if( *pIter >= nEnd )
+ *pIter = xub_StrLen( *pIter + nDiff );
+ else
+ *pIter = nPos;
+ ++pIter;
+ }
+}
+
+SwGrammarMarkUp* SwGrammarMarkUp::SplitGrammarList( xub_StrLen nSplitPos )
+{
+ SwGrammarMarkUp* pNew = (SwGrammarMarkUp*)SplitList( nSplitPos );
+ if( !maSentence.size() )
+ return pNew;
+ std::vector< xub_StrLen >::iterator pIter = maSentence.begin();
+ while( pIter != maSentence.end() && *pIter < nSplitPos )
+ ++pIter;
+ if( pIter != maSentence.begin() )
+ {
+ if( !pNew ) {
+ pNew = new SwGrammarMarkUp();
+ pNew->SetInvalid( 0, STRING_LEN );
+ }
+ pNew->maSentence.insert( pNew->maSentence.begin(), maSentence.begin(), pIter );
+ maSentence.erase( maSentence.begin(), pIter );
+ }
+ return pNew;
+}
+
+void SwGrammarMarkUp::JoinGrammarList( SwGrammarMarkUp* pNext, xub_StrLen nInsertPos )
+{
+ JoinList( pNext, nInsertPos );
+ if (pNext)
+ {
+ if( !pNext->maSentence.size() )
+ return;
+ std::vector< xub_StrLen >::iterator pIter = pNext->maSentence.begin();
+ while( pIter != pNext->maSentence.end() )
+ {
+ *pIter = *pIter + nInsertPos;
+ ++pIter;
+ }
+ maSentence.insert( maSentence.end(), pNext->maSentence.begin(), pNext->maSentence.end() );
+ }
+}
+
+void SwGrammarMarkUp::ClearGrammarList( xub_StrLen nSentenceEnd )
+{
+ if( STRING_LEN == nSentenceEnd ) {
+ ClearList();
+ maSentence.clear();
+ Validate();
+ } else if( GetBeginInv() <= nSentenceEnd ) {
+ std::vector< xub_StrLen >::iterator pIter = maSentence.begin();
+ xub_StrLen nStart = 0;
+ while( pIter != maSentence.end() && *pIter < GetBeginInv() )
+ {
+ nStart = *pIter;
+ ++pIter;
+ }
+ std::vector< xub_StrLen >::iterator pLast = pIter;
+ while( pLast != maSentence.end() && *pLast <= nSentenceEnd )
+ ++pLast;
+ maSentence.erase( pIter, pLast );
+ RemoveEntry( nStart, nSentenceEnd );
+ SetInvalid( nSentenceEnd + 1, STRING_LEN );
+ }
+}
+
+void SwGrammarMarkUp::setSentence( xub_StrLen nStart )
+{
+ std::vector< xub_StrLen >::iterator pIter = maSentence.begin();
+ while( pIter != maSentence.end() && *pIter < nStart )
+ ++pIter;
+ if( pIter == maSentence.end() || *pIter > nStart )
+ maSentence.insert( pIter, nStart );
+}
+
+xub_StrLen SwGrammarMarkUp::getSentenceStart( xub_StrLen nPos )
+{
+ if( !maSentence.size() )
+ return 0;
+ std::vector< xub_StrLen >::iterator pIter = maSentence.begin();
+ while( pIter != maSentence.end() && *pIter < nPos )
+ ++pIter;
+ if( pIter != maSentence.begin() )
+ --pIter;
+ xub_StrLen nRet = 0;
+ if( pIter != maSentence.end() && *pIter < nPos )
+ nRet = *pIter;
+ return nRet;
+}
+
+xub_StrLen SwGrammarMarkUp::getSentenceEnd( xub_StrLen nPos )
+{
+ if( !maSentence.size() )
+ return STRING_LEN;
+ std::vector< xub_StrLen >::iterator pIter = maSentence.begin();
+ while( pIter != maSentence.end() && *pIter <= nPos )
+ ++pIter;
+ xub_StrLen nRet = STRING_LEN;
+ if( pIter != maSentence.end() )
+ nRet = *pIter;
+ return nRet;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/text/atrhndl.hxx b/sw/source/core/text/atrhndl.hxx
new file mode 100644
index 000000000000..1befde44e5d5
--- /dev/null
+++ b/sw/source/core/text/atrhndl.hxx
@@ -0,0 +1,182 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef _ATRHNDL_HXX
+#define _ATRHNDL_HXX
+
+#define INITIAL_NUM_ATTR 3
+#define NUM_ATTRIBUTE_STACKS 40
+
+#include <txatbase.hxx>
+#include <swfntcch.hxx>
+
+class SwAttrSet;
+class IDocumentSettingAccess;
+class ViewShell;
+class SfxPoolItem;
+extern const sal_uInt8 StackPos[];
+
+/*************************************************************************
+ * class SwAttrHandler
+ *
+ * Used by Attribute Iterators to organize attributes on stacks to
+ * find the valid attribute in each category
+ *************************************************************************/
+
+class SwAttrHandler
+{
+private:
+
+ /*************************************************************************
+ * class SwAttrStack
+ *
+ * Container for SwTxtAttr Objects
+ *************************************************************************/
+
+ class SwAttrStack
+ {
+ private:
+ SwTxtAttr* pInitialArray[ INITIAL_NUM_ATTR ];
+ SwTxtAttr** pArray;
+ sal_uInt16 nCount; // number of elements on stack
+ sal_uInt16 nSize; // number of positions in Array
+
+ public:
+ // Ctor, Dtor
+ inline SwAttrStack();
+ inline ~SwAttrStack() {
+ if ( nSize > INITIAL_NUM_ATTR ) delete [] pArray; }
+
+ // reset stack
+ inline void Reset() { nCount = 0; };
+
+ // insert on top
+ inline void Push( const SwTxtAttr& rAttr ) { Insert( rAttr, nCount ); };
+ // insert at specified position, take care for not inserting behind
+ // the value returned by Count()
+ void Insert( const SwTxtAttr& rAttr, const sal_uInt16 nPos );
+
+ // remove specified attribute
+ void Remove( const SwTxtAttr& rAttr );
+
+ // get attribute from top if exists, otherwise 0
+ const SwTxtAttr* Top() const;
+
+ // number of elements on stack
+ inline sal_uInt16 Count() const { return nCount; };
+
+ // returns position of rAttr on Stack if found, otherwise USHRT_MAX
+ // can be used for Remove of an attribute
+ sal_uInt16 Pos( const SwTxtAttr& rAttr ) const;
+ };
+
+ SwAttrStack aAttrStack[ NUM_ATTRIBUTE_STACKS ]; // stack collection
+ const SfxPoolItem* pDefaultArray[ NUM_DEFAULT_VALUES ];
+ const IDocumentSettingAccess* mpIDocumentSettingAccess;
+ const ViewShell* mpShell;
+
+ // This is the base font for the paragraph. It is stored in order to have
+ // a template, if we have to restart the attribute evaluation
+ SwFont* pFnt;
+
+ sal_Bool bVertLayout;
+
+ // change font according to pool item
+ void FontChg(const SfxPoolItem& rItem, SwFont& rFnt, sal_Bool bPush );
+
+ // push attribute to specified stack, returns true, if attribute has
+ // been pushed on top of stack (important for stacks containing different
+ // attributes with different priority and redlining)
+ sal_Bool Push( const SwTxtAttr& rAttr, const SfxPoolItem& rItem );
+
+ // apply top attribute on stack to font
+ void ActivateTop( SwFont& rFnt, sal_uInt16 nStackPos );
+
+public:
+ // Ctor
+ SwAttrHandler();
+ ~SwAttrHandler();
+
+ // set default attributes to values in rAttrSet or from cache
+ void Init( const SwAttrSet& rAttrSet,
+ const IDocumentSettingAccess& rIDocumentSettingAccess,
+ const ViewShell* pShell );
+ void Init( const SfxPoolItem** pPoolItem, const SwAttrSet* pAttrSet,
+ const IDocumentSettingAccess& rIDocumentSettingAccess,
+ const ViewShell* pShell, SwFont& rFnt,
+ sal_Bool bVertLayout );
+
+ // remove everything from internal stacks, keep default data
+ void Reset( );
+
+ // insert specified attribute and change font
+ void PushAndChg( const SwTxtAttr& rAttr, SwFont& rFnt );
+
+ // remove specified attribute and reset font
+ void PopAndChg( const SwTxtAttr& rAttr, SwFont& rFnt );
+ void Pop( const SwTxtAttr& rAttr );
+
+ // apply script dependent attributes
+// void ChangeScript( SwFont& rFnt, const sal_uInt8 nScr );
+
+ // returns the default value for stack nStack
+ inline const SfxPoolItem& GetDefault( const sal_uInt16 nAttribID ) const;
+ // do not call these if you only used the small init function
+ inline void ResetFont( SwFont& rFnt ) const;
+ inline const SwFont* GetFont() const;
+
+ void GetDefaultAscentAndHeight(ViewShell* pShell,
+ OutputDevice& rOut,
+ sal_uInt16& nAscent,
+ sal_uInt16& nHeight) const;
+};
+
+inline const SfxPoolItem& SwAttrHandler::GetDefault( const sal_uInt16 nAttribID ) const
+{
+ OSL_ENSURE( nAttribID < RES_TXTATR_END,
+ "this attrib does not ex."
+ );
+ OSL_ENSURE( pDefaultArray[ StackPos[ nAttribID ] ], "array not initialized" );
+ return *pDefaultArray[ StackPos[ nAttribID ] ];
+}
+
+inline void SwAttrHandler::ResetFont( SwFont& rFnt ) const
+{
+ OSL_ENSURE( pFnt, "ResetFont without a font" );
+ if ( pFnt )
+ rFnt = *pFnt;
+};
+
+inline const SwFont* SwAttrHandler::GetFont() const
+{
+ return pFnt;
+};
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/text/atrstck.cxx b/sw/source/core/text/atrstck.cxx
new file mode 100644
index 000000000000..92e88ecde74a
--- /dev/null
+++ b/sw/source/core/text/atrstck.cxx
@@ -0,0 +1,957 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+
+#include <atrhndl.hxx>
+#include <svl/itemiter.hxx>
+#include <vcl/outdev.hxx>
+#include <editeng/cmapitem.hxx>
+#include <editeng/colritem.hxx>
+#include <editeng/cntritem.hxx>
+#include <editeng/crsditem.hxx>
+#include <editeng/escpitem.hxx>
+#include <editeng/fontitem.hxx>
+#include <editeng/fhgtitem.hxx>
+#include <editeng/kernitem.hxx>
+#include <editeng/charreliefitem.hxx>
+#include <editeng/langitem.hxx>
+#include <editeng/postitem.hxx>
+#include <editeng/shdditem.hxx>
+#include <editeng/udlnitem.hxx>
+#include <editeng/wghtitem.hxx>
+#include <editeng/wrlmitem.hxx>
+#include <editeng/akrnitem.hxx>
+#include <editeng/blnkitem.hxx>
+#include <editeng/charrotateitem.hxx>
+#include <editeng/emphitem.hxx>
+#include <editeng/charscaleitem.hxx>
+#include <editeng/twolinesitem.hxx>
+#include <editeng/charhiddenitem.hxx>
+#include <viewopt.hxx>
+#include <charfmt.hxx>
+#include <fchrfmt.hxx>
+#include <fmtautofmt.hxx>
+#include <editeng/brshitem.hxx>
+#include <fmtinfmt.hxx>
+#include <txtinet.hxx>
+#include <IDocumentSettingAccess.hxx>
+#include <viewsh.hxx> // ViewShell
+#include <viewopt.hxx> // SwViewOptions
+
+#define STACK_INCREMENT 4
+
+/*************************************************************************
+ * Attribute to Stack Mapping
+ *
+ * Attributes applied to a text are pushed on different stacks. For each
+ * stack, the top most attribute on the stack is valid. Because some
+ * kinds of attributes have to be pushed to the same stacks we map their
+ * ids to stack ids
+ * Attention: The first NUM_DEFAULT_VALUES ( defined in swfntcch.hxx == 35 )
+ * are stored in the defaultitem-cache, if you add one, you have to increase
+ * NUM_DEFAULT_VALUES.
+ * Also adjust NUM_ATTRIBUTE_STACKS in atrhndl.hxx.
+ *************************************************************************/
+
+const sal_uInt8 StackPos[ static_cast<sal_uInt16>(RES_TXTATR_WITHEND_END) -
+ static_cast<sal_uInt16>(RES_CHRATR_BEGIN) + 1 ] =
+{
+ 0, // // 0
+ 1, // RES_CHRATR_CASEMAP = RES_CHRATR_BEGIN // 1
+ 0, // RES_CHRATR_CHARSETCOLOR, // 2
+ 2, // RES_CHRATR_COLOR, // 3
+ 3, // RES_CHRATR_CONTOUR, // 4
+ 4, // RES_CHRATR_CROSSEDOUT, // 5
+ 5, // RES_CHRATR_ESCAPEMENT, // 6
+ 6, // RES_CHRATR_FONT, // 7
+ 7, // RES_CHRATR_FONTSIZE, // 8
+ 8, // RES_CHRATR_KERNING, // 9
+ 9, // RES_CHRATR_LANGUAGE, // 10
+ 10, // RES_CHRATR_POSTURE, // 11
+ 0, // RES_CHRATR_PROPORTIONALFONTSIZE, // 12
+ 11, // RES_CHRATR_SHADOWED, // 13
+ 12, // RES_CHRATR_UNDERLINE, // 14
+ 13, // RES_CHRATR_WEIGHT, // 15
+ 14, // RES_CHRATR_WORDLINEMODE, // 16
+ 15, // RES_CHRATR_AUTOKERN, // 17
+ 16, // RES_CHRATR_BLINK, // 18
+ 17, // RES_CHRATR_NOHYPHEN, // 19
+ 0, // RES_CHRATR_NOLINEBREAK, // 20
+ 18, // RES_CHRATR_BACKGROUND, // 21
+ 19, // RES_CHRATR_CJK_FONT, // 22
+ 20, // RES_CHRATR_CJK_FONTSIZE, // 23
+ 21, // RES_CHRATR_CJK_LANGUAGE, // 24
+ 22, // RES_CHRATR_CJK_POSTURE, // 25
+ 23, // RES_CHRATR_CJK_WEIGHT, // 26
+ 24, // RES_CHRATR_CTL_FONT, // 27
+ 25, // RES_CHRATR_CTL_FONTSIZE, // 28
+ 26, // RES_CHRATR_CTL_LANGUAGE, // 29
+ 27, // RES_CHRATR_CTL_POSTURE, // 30
+ 28, // RES_CHRATR_CTL_WEIGHT, // 31
+ 29, // RES_CHRATR_ROTATE, // 32
+ 30, // RES_CHRATR_EMPHASIS_MARK, // 33
+ 31, // RES_CHRATR_TWO_LINES, // 34
+ 32, // RES_CHRATR_SCALEW, // 35
+ 33, // RES_CHRATR_RELIEF, // 36
+ 34, // RES_CHRATR_HIDDEN, // 37
+ 35, // RES_CHRATR_OVERLINE, // 38
+ 0, // RES_CHRATR_DUMMY1, // 39
+ 0, // RES_CHRATR_DUMMY2, // 40
+ 36, // RES_TXTATR_REFMARK, // 41
+ 37, // RES_TXTATR_TOXMARK, // 42
+ 38, // RES_TXTATR_META, // 43
+ 38, // RES_TXTATR_METAFIELD, // 44
+ 0, // RES_TXTATR_AUTOFMT, // 45
+ 0, // RES_TXTATR_INETFMT // 46
+ 0, // RES_TXTATR_CHARFMT, // 47
+ 39, // RES_TXTATR_CJK_RUBY, // 48
+ 0, // RES_TXTATR_UNKNOWN_CONTAINER, // 49
+ 0, // RES_TXTATR_DUMMY5 // 50
+};
+
+/*************************************************************************
+ * CharFmt::GetItem
+ * returns the item set associated with an character/inet/auto style
+ *************************************************************************/
+
+namespace CharFmt
+{
+
+const SfxItemSet* GetItemSet( const SfxPoolItem& rAttr )
+{
+ const SfxItemSet* pSet = 0;
+
+ if ( RES_TXTATR_AUTOFMT == rAttr.Which() )
+ {
+ pSet = static_cast<const SwFmtAutoFmt&>(rAttr).GetStyleHandle().get();
+ }
+ else
+ {
+ // aus der Vorlage die Attribute holen:
+ SwCharFmt* pFmt = RES_TXTATR_INETFMT == rAttr.Which() ?
+ ((SwFmtINetFmt&)rAttr).GetTxtINetFmt()->GetCharFmt() :
+ ((SwFmtCharFmt&)rAttr).GetCharFmt();
+ if( pFmt )
+ {
+ pSet = &pFmt->GetAttrSet();
+ }
+ }
+
+ return pSet;
+}
+
+/*************************************************************************
+ * CharFmt::GetItem
+ * extracts pool item of type nWhich from rAttr
+ *************************************************************************/
+
+const SfxPoolItem* GetItem( const SwTxtAttr& rAttr, sal_uInt16 nWhich )
+{
+ if ( RES_TXTATR_INETFMT == rAttr.Which() ||
+ RES_TXTATR_CHARFMT == rAttr.Which() ||
+ RES_TXTATR_AUTOFMT == rAttr.Which() )
+ {
+ const SfxItemSet* pSet = CharFmt::GetItemSet( rAttr.GetAttr() );
+ if ( !pSet ) return 0;
+
+ bool bInParent = RES_TXTATR_AUTOFMT != rAttr.Which();
+ const SfxPoolItem* pItem;
+ sal_Bool bRet = SFX_ITEM_SET == pSet->GetItemState( nWhich, bInParent, &pItem );
+
+ return bRet ? pItem : 0;
+ }
+
+ return ( nWhich == rAttr.Which() ) ? &rAttr.GetAttr() : 0;
+}
+
+/*************************************************************************
+ * CharFmt::IsItemIncluded
+ * checks if item is included in character/inet/auto style
+ *************************************************************************/
+
+sal_Bool IsItemIncluded( const sal_uInt16 nWhich, const SwTxtAttr *pAttr )
+{
+ sal_Bool bRet = sal_False;
+
+ const SfxItemSet* pItemSet = CharFmt::GetItemSet( pAttr->GetAttr() );
+ if ( pItemSet )
+ bRet = SFX_ITEM_SET == pItemSet->GetItemState( nWhich, sal_True );
+
+ return bRet;
+}
+
+}
+
+/*************************************************************************
+ * lcl_ChgHyperLinkColor
+ * The color of hyperlinks is taken from the associated character attribute,
+ * depending on its 'visited' state. There are actually two cases, which
+ * should override the colors from the character attribute:
+ * 1. We never take the 'visited' color during printing/pdf export/preview
+ * 2. The user has choosen to override these colors in the view options
+ *************************************************************************/
+
+bool lcl_ChgHyperLinkColor( const SwTxtAttr& rAttr,
+ const SfxPoolItem& rItem,
+ const ViewShell* pShell,
+ Color* pColor )
+{
+ if ( !pShell ||
+ RES_TXTATR_INETFMT != rAttr.Which() ||
+ RES_CHRATR_COLOR != rItem.Which() )
+ return false;
+
+ // --> FME 2004-09-13 #i15455#
+ // 1. case:
+ // We do not want to show visited links:
+ // (printing, pdf export, page preview)
+ //
+ if ( pShell->GetOut()->GetOutDevType() == OUTDEV_PRINTER ||
+ pShell->GetViewOptions()->IsPDFExport() ||
+ pShell->GetViewOptions()->IsPagePreview() )
+ {
+ if ( ((SwTxtINetFmt&)rAttr).IsVisited() )
+ {
+ if ( pColor )
+ {
+ // take color from character format 'unvisited link'
+ SwTxtINetFmt& rInetAttr( const_cast<SwTxtINetFmt&>(
+ static_cast<const SwTxtINetFmt&>(rAttr)) );
+ rInetAttr.SetVisited( false );
+ const SwCharFmt* pTmpFmt = ((SwTxtINetFmt&)rAttr).GetCharFmt();
+ const SfxPoolItem* pItem;
+ pTmpFmt->GetItemState( RES_CHRATR_COLOR, sal_True, &pItem );
+ *pColor = ((SvxColorItem*)pItem)->GetValue();
+ rInetAttr.SetVisited( true );
+ }
+ return true;
+ }
+
+ return false;
+ }
+ // <--
+
+ //
+ // 2. case:
+ // We do not want to apply the color set in the hyperlink
+ // attribute, instead we take the colors from the view options:
+ //
+ if ( pShell->GetWin() &&
+ (
+ (((SwTxtINetFmt&)rAttr).IsVisited() && SwViewOption::IsVisitedLinks()) ||
+ (!((SwTxtINetFmt&)rAttr).IsVisited() && SwViewOption::IsLinks())
+ )
+ )
+ {
+ if ( pColor )
+ {
+ if ( ((SwTxtINetFmt&)rAttr).IsVisited() )
+ {
+ // take color from view option 'visited link color'
+ *pColor = SwViewOption::GetVisitedLinksColor();
+ }
+ else
+ {
+ // take color from view option 'unvisited link color'
+ *pColor = SwViewOption::GetLinksColor();
+ }
+ }
+ return true;
+ }
+
+ return false;
+}
+
+/*************************************************************************
+ * SwAttrHandler::SwAttrStack::SwAttrStack()
+ *************************************************************************/
+
+inline SwAttrHandler::SwAttrStack::SwAttrStack()
+ : nCount( 0 ), nSize( INITIAL_NUM_ATTR )
+{
+ pArray = pInitialArray;
+}
+
+/*************************************************************************
+ * SwAttrHandler::SwAttrStack::Insert()
+ *************************************************************************/
+
+void SwAttrHandler::SwAttrStack::Insert( const SwTxtAttr& rAttr, const sal_uInt16 nPos )
+{
+ // do we still have enough space?
+ if ( nCount >= nSize )
+ {
+ // we are still in our initial array
+ if ( INITIAL_NUM_ATTR == nSize )
+ {
+ nSize += STACK_INCREMENT;
+ pArray = new SwTxtAttr*[ nSize ];
+ // copy from pInitArray to new Array
+ memcpy( pArray, pInitialArray,
+ INITIAL_NUM_ATTR * sizeof(SwTxtAttr*)
+ );
+ }
+ // we are in new memory
+ else
+ {
+ nSize += STACK_INCREMENT;
+ SwTxtAttr** pTmpArray = new SwTxtAttr*[ nSize ];
+ // copy from pArray to new Array
+ memcpy( pTmpArray, pArray, nCount * sizeof(SwTxtAttr*) );
+ // free old array
+ delete [] pArray;
+ pArray = pTmpArray;
+ }
+ }
+
+ OSL_ENSURE( nPos <= nCount, "wrong position for insert operation");
+
+ if ( nPos < nCount )
+ memmove( pArray + nPos + 1, pArray + nPos,
+ ( nCount - nPos ) * sizeof(SwTxtAttr*)
+ );
+ pArray[ nPos ] = (SwTxtAttr*)&rAttr;
+
+ nCount++;
+}
+
+/*************************************************************************
+ * SwAttrHandler::SwAttrStack::Remove()
+ *************************************************************************/
+
+void SwAttrHandler::SwAttrStack::Remove( const SwTxtAttr& rAttr )
+{
+ sal_uInt16 nPos = Pos( rAttr );
+ if ( nPos < nCount )
+ {
+ memmove( pArray + nPos, pArray + nPos + 1,
+ ( nCount - 1 - nPos ) * sizeof(SwTxtAttr*)
+ );
+ nCount--;
+ }
+}
+
+/*************************************************************************
+ * SwAttrHandler::SwAttrStack::Top()
+ *************************************************************************/
+
+const SwTxtAttr* SwAttrHandler::SwAttrStack::Top() const
+{
+ return nCount ? pArray[ nCount - 1 ] : 0;
+}
+
+/*************************************************************************
+ * SwAttrHandler::SwAttrStack::Pos()
+ *************************************************************************/
+
+sal_uInt16 SwAttrHandler::SwAttrStack::Pos( const SwTxtAttr& rAttr ) const
+{
+ if ( ! nCount )
+ // empty stack
+ return USHRT_MAX;
+
+ for ( sal_uInt16 nIdx = nCount; nIdx > 0; )
+ {
+ if ( &rAttr == pArray[ --nIdx ] )
+ return nIdx;
+ }
+
+ // element not found
+ return USHRT_MAX;
+}
+
+/*************************************************************************
+ * SwAttrHandler::SwAttrHandler()
+ *************************************************************************/
+
+SwAttrHandler::SwAttrHandler() : mpShell( 0 ), pFnt( 0 ), bVertLayout( sal_False )
+
+{
+ memset( pDefaultArray, 0, NUM_DEFAULT_VALUES * sizeof(SfxPoolItem*) );
+}
+
+SwAttrHandler::~SwAttrHandler()
+{
+ delete pFnt;
+}
+
+/*************************************************************************
+ * SwAttrHandler::Init()
+ *************************************************************************/
+
+void SwAttrHandler::Init( const SwAttrSet& rAttrSet,
+ const IDocumentSettingAccess& rIDocumentSettingAcces,
+ const ViewShell* pSh )
+{
+ mpIDocumentSettingAccess = &rIDocumentSettingAcces;
+ mpShell = pSh;
+
+ for ( sal_uInt16 i = RES_CHRATR_BEGIN; i < RES_CHRATR_END; i++ )
+ pDefaultArray[ StackPos[ i ] ] = &rAttrSet.Get( i, sal_True );
+}
+
+void SwAttrHandler::Init( const SfxPoolItem** pPoolItem, const SwAttrSet* pAS,
+ const IDocumentSettingAccess& rIDocumentSettingAcces,
+ const ViewShell* pSh,
+ SwFont& rFnt, sal_Bool bVL )
+{
+ // initialize default array
+ memcpy( pDefaultArray, pPoolItem,
+ NUM_DEFAULT_VALUES * sizeof(SfxPoolItem*) );
+
+ mpIDocumentSettingAccess = &rIDocumentSettingAcces;
+ mpShell = pSh;
+
+ // do we have to apply additional paragraph attributes?
+ bVertLayout = bVL;
+
+ if ( pAS && pAS->Count() )
+ {
+ SfxItemIter aIter( *pAS );
+ sal_uInt16 nWhich;
+ const SfxPoolItem* pItem = aIter.GetCurItem();
+ while( sal_True )
+ {
+ nWhich = pItem->Which();
+ if (isCHRATR(nWhich))
+ {
+ pDefaultArray[ StackPos[ nWhich ] ] = pItem;
+ FontChg( *pItem, rFnt, sal_True );
+ }
+
+ if( aIter.IsAtEnd() )
+ break;
+
+ pItem = aIter.NextItem();
+ }
+ }
+
+ // It is possible, that Init is called more than once, e.g., in a
+ // SwTxtFrm::FormatOnceMore situation.
+ delete pFnt;
+ pFnt = new SwFont( rFnt );
+}
+
+void SwAttrHandler::Reset( )
+{
+ for ( sal_uInt16 i = 0; i < NUM_ATTRIBUTE_STACKS; i++ )
+ aAttrStack[ i ].Reset();
+}
+
+/*************************************************************************
+ * SwAttrHandler::PushAndChg()
+ *************************************************************************/
+
+void SwAttrHandler::PushAndChg( const SwTxtAttr& rAttr, SwFont& rFnt )
+{
+ // these special attributes in fact represent a collection of attributes
+ // they have to be pushed to each stack they belong to
+ if ( RES_TXTATR_INETFMT == rAttr.Which() ||
+ RES_TXTATR_CHARFMT == rAttr.Which() ||
+ RES_TXTATR_AUTOFMT == rAttr.Which() )
+ {
+ const SfxItemSet* pSet = CharFmt::GetItemSet( rAttr.GetAttr() );
+ if ( !pSet ) return;
+
+ for ( sal_uInt16 i = RES_CHRATR_BEGIN; i < RES_CHRATR_END; i++)
+ {
+ const SfxPoolItem* pItem;
+ sal_Bool bRet = SFX_ITEM_SET == pSet->GetItemState( i, rAttr.Which() != RES_TXTATR_AUTOFMT, &pItem );
+
+ if ( bRet )
+ {
+ // we push rAttr onto the appropriate stack
+ if ( Push( rAttr, *pItem ) )
+ {
+ // we let pItem change rFnt
+ Color aColor;
+ if ( lcl_ChgHyperLinkColor( rAttr, *pItem, mpShell, &aColor ) )
+ {
+ SvxColorItem aItemNext( aColor, RES_CHRATR_COLOR );
+ FontChg( aItemNext, rFnt, sal_True );
+ }
+ else
+ FontChg( *pItem, rFnt, sal_True );
+ }
+ }
+ }
+ }
+ // this is the usual case, we have a basic attribute, push it onto the
+ // stack and change the font
+ else
+ {
+ if ( Push( rAttr, rAttr.GetAttr() ) )
+ // we let pItem change rFnt
+ FontChg( rAttr.GetAttr(), rFnt, sal_True );
+ }
+}
+
+/*************************************************************************
+ * SwAttrHandler::Push()
+ *************************************************************************/
+
+sal_Bool SwAttrHandler::Push( const SwTxtAttr& rAttr, const SfxPoolItem& rItem )
+{
+ OSL_ENSURE( rItem.Which() < RES_TXTATR_WITHEND_END,
+ "I do not want this attribute, nWhich >= RES_TXTATR_WITHEND_END" );
+
+ // robust
+ if ( RES_TXTATR_WITHEND_END <= rItem.Which() )
+ return sal_False;
+
+ sal_uInt16 nStack = StackPos[ rItem.Which() ];
+
+ // attributes originating from redlining have highest priority
+ // second priority are hyperlink attributes, which have a color replacement
+ const SwTxtAttr* pTopAttr = aAttrStack[ nStack ].Top();
+ if ( !pTopAttr || rAttr.IsPriorityAttr() ||
+ ( !pTopAttr->IsPriorityAttr() &&
+ !lcl_ChgHyperLinkColor( *pTopAttr, rItem, mpShell, 0 ) ) )
+ {
+ aAttrStack[ nStack ].Push( rAttr );
+ return sal_True;
+ }
+
+ sal_uInt16 nPos = aAttrStack[ nStack ].Count();
+ OSL_ENSURE( nPos, "empty stack?" );
+ aAttrStack[ nStack ].Insert( rAttr, nPos - 1 );
+ return sal_False;
+}
+
+/*************************************************************************
+ * SwAttrHandler::PopAndChg()
+ *************************************************************************/
+
+void SwAttrHandler::PopAndChg( const SwTxtAttr& rAttr, SwFont& rFnt )
+{
+ if ( RES_TXTATR_WITHEND_END <= rAttr.Which() )
+ return; // robust
+
+ // these special attributes in fact represent a collection of attributes
+ // they have to be removed from each stack they belong to
+ if ( RES_TXTATR_INETFMT == rAttr.Which() ||
+ RES_TXTATR_CHARFMT == rAttr.Which() ||
+ RES_TXTATR_AUTOFMT == rAttr.Which() )
+ {
+ const SfxItemSet* pSet = CharFmt::GetItemSet( rAttr.GetAttr() );
+ if ( !pSet ) return;
+
+ for ( sal_uInt16 i = RES_CHRATR_BEGIN; i < RES_CHRATR_END; i++)
+ {
+ const SfxPoolItem* pItem;
+ sal_Bool bRet = SFX_ITEM_SET == pSet->GetItemState( i, RES_TXTATR_AUTOFMT != rAttr.Which(), &pItem );
+ if ( bRet )
+ {
+ // we remove rAttr from the appropriate stack
+ sal_uInt16 nStackPos = StackPos[ i ];
+ aAttrStack[ nStackPos ].Remove( rAttr );
+ // reset font according to attribute on top of stack
+ // or default value
+ ActivateTop( rFnt, i );
+ }
+ }
+ }
+ // this is the usual case, we have a basic attribute, remove it from the
+ // stack and reset the font
+ else
+ {
+ aAttrStack[ StackPos[ rAttr.Which() ] ].Remove( rAttr );
+ // reset font according to attribute on top of stack
+ // or default value
+ ActivateTop( rFnt, rAttr.Which() );
+ }
+}
+
+/*************************************************************************
+ * SwAttrHandler::Pop()
+ *
+ * only used during redlining
+ *************************************************************************/
+
+void SwAttrHandler::Pop( const SwTxtAttr& rAttr )
+{
+ OSL_ENSURE( rAttr.Which() < RES_TXTATR_WITHEND_END,
+ "I do not have this attribute, nWhich >= RES_TXTATR_WITHEND_END" );
+
+ if ( rAttr.Which() < RES_TXTATR_WITHEND_END )
+ {
+ aAttrStack[ StackPos[ rAttr.Which() ] ].Remove( rAttr );
+ }
+}
+
+/*************************************************************************
+ * SwAttrHandler::ActivateTop()
+ *************************************************************************/
+void SwAttrHandler::ActivateTop( SwFont& rFnt, const sal_uInt16 nAttr )
+{
+ OSL_ENSURE( nAttr < RES_TXTATR_WITHEND_END,
+ "I cannot activate this attribute, nWhich >= RES_TXTATR_WITHEND_END" );
+
+ const sal_uInt16 nStackPos = StackPos[ nAttr ];
+ const SwTxtAttr* pTopAt = aAttrStack[ nStackPos ].Top();
+ if ( pTopAt )
+ {
+ // check if top attribute is collection of attributes
+ if ( RES_TXTATR_INETFMT == pTopAt->Which() ||
+ RES_TXTATR_CHARFMT == pTopAt->Which() ||
+ RES_TXTATR_AUTOFMT == pTopAt->Which() )
+ {
+ const SfxItemSet* pSet = CharFmt::GetItemSet( pTopAt->GetAttr() );
+ const SfxPoolItem* pItemNext;
+ pSet->GetItemState( nAttr, RES_TXTATR_AUTOFMT != pTopAt->Which(), &pItemNext );
+
+ Color aColor;
+ if ( lcl_ChgHyperLinkColor( *pTopAt, *pItemNext, mpShell, &aColor ) )
+ {
+ SvxColorItem aItemNext( aColor, RES_CHRATR_COLOR );
+ FontChg( aItemNext, rFnt, sal_False );
+ }
+ else
+ FontChg( *pItemNext, rFnt, sal_False );
+ }
+ else
+ FontChg( pTopAt->GetAttr(), rFnt, sal_False );
+ }
+
+ // default value has to be set, we only have default values for char attribs
+ else if ( nStackPos < NUM_DEFAULT_VALUES )
+ FontChg( *pDefaultArray[ nStackPos ], rFnt, sal_False );
+ else if ( RES_TXTATR_REFMARK == nAttr )
+ rFnt.GetRef()--;
+ else if ( RES_TXTATR_TOXMARK == nAttr )
+ rFnt.GetTox()--;
+ else if ( (RES_TXTATR_META == nAttr) || (RES_TXTATR_METAFIELD == nAttr) )
+ {
+ rFnt.GetMeta()--;
+ }
+ else if ( RES_TXTATR_CJK_RUBY == nAttr )
+ {
+ // ruby stack has no more attributes
+ // check, if an rotation attribute has to be applied
+ sal_uInt16 nTwoLineStack = StackPos[ RES_CHRATR_TWO_LINES ];
+ sal_Bool bTwoLineAct = sal_False;
+ const SfxPoolItem* pTwoLineItem = 0;
+ const SwTxtAttr* pTwoLineAttr = aAttrStack[ nTwoLineStack ].Top();
+
+ if ( pTwoLineAttr )
+ {
+ pTwoLineItem = CharFmt::GetItem( *pTwoLineAttr, RES_CHRATR_TWO_LINES );
+ bTwoLineAct = ((SvxTwoLinesItem*)pTwoLineItem)->GetValue();
+ }
+ else
+ bTwoLineAct =
+ ((SvxTwoLinesItem*)pDefaultArray[ nTwoLineStack ])->GetValue();
+
+ if ( bTwoLineAct )
+ return;
+
+ // eventually, an rotate attribute has to be activated
+ sal_uInt16 nRotateStack = StackPos[ RES_CHRATR_ROTATE ];
+ const SfxPoolItem* pRotateItem = 0;
+ const SwTxtAttr* pRotateAttr = aAttrStack[ nRotateStack ].Top();
+
+ if ( pRotateAttr )
+ {
+ pRotateItem = CharFmt::GetItem( *pRotateAttr, RES_CHRATR_ROTATE );
+ rFnt.SetVertical( ((SvxCharRotateItem*)pRotateItem)->GetValue(),
+ bVertLayout );
+ }
+ else
+ rFnt.SetVertical(
+ ((SvxCharRotateItem*)pDefaultArray[ nRotateStack ])->GetValue(),
+ bVertLayout
+ );
+ }
+}
+
+/*************************************************************************
+ * Font Changing Function
+ *
+ * When popping an attribute from the stack, the top mose remaining
+ * attribute in the stack becomes valid. The following function change
+ * a font depending on the stack id.
+ *************************************************************************/
+
+void SwAttrHandler::FontChg(const SfxPoolItem& rItem, SwFont& rFnt, sal_Bool bPush )
+{
+ switch ( rItem.Which() )
+ {
+ case RES_CHRATR_CASEMAP :
+ rFnt.SetCaseMap( ((SvxCaseMapItem&)rItem).GetCaseMap() );
+ break;
+ case RES_CHRATR_COLOR :
+ rFnt.SetColor( ((SvxColorItem&)rItem).GetValue() );
+ break;
+ case RES_CHRATR_CONTOUR :
+ rFnt.SetOutline( ((SvxContourItem&)rItem).GetValue() );
+ break;
+ case RES_CHRATR_CROSSEDOUT :
+ rFnt.SetStrikeout( ((SvxCrossedOutItem&)rItem).GetStrikeout() );
+ break;
+ case RES_CHRATR_ESCAPEMENT :
+ rFnt.SetEscapement( ((SvxEscapementItem&)rItem).GetEsc() );
+ rFnt.SetProportion( ((SvxEscapementItem&)rItem).GetProp() );
+ break;
+ case RES_CHRATR_FONT :
+ rFnt.SetName( ((SvxFontItem&)rItem).GetFamilyName(), SW_LATIN );
+ rFnt.SetStyleName( ((SvxFontItem&)rItem).GetStyleName(), SW_LATIN );
+ rFnt.SetFamily( ((SvxFontItem&)rItem).GetFamily(), SW_LATIN );
+ rFnt.SetPitch( ((SvxFontItem&)rItem).GetPitch(), SW_LATIN );
+ rFnt.SetCharSet( ((SvxFontItem&)rItem).GetCharSet(), SW_LATIN );
+ break;
+ case RES_CHRATR_FONTSIZE :
+ rFnt.SetSize(Size(0,((SvxFontHeightItem&)rItem).GetHeight() ), SW_LATIN );
+ break;
+ case RES_CHRATR_KERNING :
+ rFnt.SetFixKerning( ((SvxKerningItem&)rItem).GetValue() );
+ break;
+ case RES_CHRATR_LANGUAGE :
+ rFnt.SetLanguage( ((SvxLanguageItem&)rItem).GetLanguage(), SW_LATIN );
+ break;
+ case RES_CHRATR_POSTURE :
+ rFnt.SetItalic( ((SvxPostureItem&)rItem).GetPosture(), SW_LATIN );
+ break;
+ case RES_CHRATR_SHADOWED :
+ rFnt.SetShadow( ((SvxShadowedItem&)rItem).GetValue() );
+ break;
+ case RES_CHRATR_UNDERLINE :
+ {
+ const sal_uInt16 nStackPos = StackPos[ RES_CHRATR_HIDDEN ];
+ const SwTxtAttr* pTopAt = aAttrStack[ nStackPos ].Top();
+
+ const SfxPoolItem* pTmpItem = pTopAt ?
+ CharFmt::GetItem( *pTopAt, RES_CHRATR_HIDDEN ) :
+ pDefaultArray[ nStackPos ];
+
+ if( (mpShell && !mpShell->GetWin()) ||
+ (pTmpItem && !static_cast<const SvxCharHiddenItem*>(pTmpItem)->GetValue()) )
+ {
+ rFnt.SetUnderline( ((SvxUnderlineItem&)rItem).GetLineStyle() );
+ rFnt.SetUnderColor( ((SvxUnderlineItem&)rItem).GetColor() );
+ }
+ break;
+ }
+ case RES_CHRATR_OVERLINE :
+ rFnt.SetOverline( ((SvxOverlineItem&)rItem).GetLineStyle() );
+ rFnt.SetOverColor( ((SvxOverlineItem&)rItem).GetColor() );
+ break;
+ case RES_CHRATR_WEIGHT :
+ rFnt.SetWeight( ((SvxWeightItem&)rItem).GetWeight(), SW_LATIN );
+ break;
+ case RES_CHRATR_WORDLINEMODE :
+ rFnt.SetWordLineMode( ((SvxWordLineModeItem&)rItem).GetValue() );
+ break;
+ case RES_CHRATR_AUTOKERN :
+ if( ((SvxAutoKernItem&)rItem).GetValue() )
+ {
+ rFnt.SetAutoKern( ( !mpIDocumentSettingAccess ||
+ !mpIDocumentSettingAccess->get(IDocumentSettingAccess::KERN_ASIAN_PUNCTUATION) ) ?
+ KERNING_FONTSPECIFIC :
+ KERNING_ASIAN );
+ }
+ else
+ rFnt.SetAutoKern( 0 );
+ break;
+ case RES_CHRATR_BLINK :
+ rFnt.SetBlink( ((SvxBlinkItem&)rItem).GetValue() );
+ break;
+ case RES_CHRATR_BACKGROUND :
+ rFnt.SetBackColor(new Color( ((SvxBrushItem&)rItem).GetColor() ) );
+ break;
+ case RES_CHRATR_CJK_FONT :
+ rFnt.SetName( ((SvxFontItem&)rItem).GetFamilyName(), SW_CJK );
+ rFnt.SetStyleName( ((SvxFontItem&)rItem).GetStyleName(), SW_CJK );
+ rFnt.SetFamily( ((SvxFontItem&)rItem).GetFamily(), SW_CJK );
+ rFnt.SetPitch( ((SvxFontItem&)rItem).GetPitch(), SW_CJK );
+ rFnt.SetCharSet( ((SvxFontItem&)rItem).GetCharSet(), SW_CJK );
+ break;
+ case RES_CHRATR_CJK_FONTSIZE :
+ rFnt.SetSize(Size( 0, ((SvxFontHeightItem&)rItem).GetHeight()), SW_CJK);
+ break;
+ case RES_CHRATR_CJK_LANGUAGE :
+ rFnt.SetLanguage( ((SvxLanguageItem&)rItem).GetLanguage(), SW_CJK );
+ break;
+ case RES_CHRATR_CJK_POSTURE :
+ rFnt.SetItalic( ((SvxPostureItem&)rItem).GetPosture(), SW_CJK );
+ break;
+ case RES_CHRATR_CJK_WEIGHT :
+ rFnt.SetWeight( ((SvxWeightItem&)rItem).GetWeight(), SW_CJK );
+ break;
+ case RES_CHRATR_CTL_FONT :
+ rFnt.SetName( ((SvxFontItem&)rItem).GetFamilyName(), SW_CTL );
+ rFnt.SetStyleName( ((SvxFontItem&)rItem).GetStyleName(), SW_CTL );
+ rFnt.SetFamily( ((SvxFontItem&)rItem).GetFamily(), SW_CTL );
+ rFnt.SetPitch( ((SvxFontItem&)rItem).GetPitch(), SW_CTL );
+ rFnt.SetCharSet( ((SvxFontItem&)rItem).GetCharSet(), SW_CTL );
+ break;
+ case RES_CHRATR_CTL_FONTSIZE :
+ rFnt.SetSize(Size(0, ((SvxFontHeightItem&)rItem).GetHeight() ), SW_CTL);
+ break;
+ case RES_CHRATR_CTL_LANGUAGE :
+ rFnt.SetLanguage( ((SvxLanguageItem&)rItem).GetLanguage(), SW_CTL );
+ break;
+ case RES_CHRATR_CTL_POSTURE :
+ rFnt.SetItalic( ((SvxPostureItem&)rItem).GetPosture(), SW_CTL );
+ break;
+ case RES_CHRATR_CTL_WEIGHT :
+ rFnt.SetWeight( ((SvxWeightItem&)rItem).GetWeight(), SW_CTL );
+ break;
+ case RES_CHRATR_EMPHASIS_MARK :
+ rFnt.SetEmphasisMark(
+ ((SvxEmphasisMarkItem&)rItem).GetEmphasisMark()
+ );
+ break;
+ case RES_CHRATR_SCALEW :
+ rFnt.SetPropWidth( ((SvxCharScaleWidthItem&)rItem).GetValue() );
+ break;
+ case RES_CHRATR_RELIEF :
+ rFnt.SetRelief( (FontRelief)((SvxCharReliefItem&)rItem).GetValue() );
+ break;
+ case RES_CHRATR_HIDDEN :
+ if( mpShell && mpShell->GetWin())
+ {
+ if ( ((SvxCharHiddenItem&)rItem).GetValue() )
+ rFnt.SetUnderline( UNDERLINE_DOTTED );
+ else
+ ActivateTop( rFnt, RES_CHRATR_UNDERLINE );
+ }
+ break;
+ case RES_CHRATR_ROTATE :
+ {
+ // rotate attribute is applied, when:
+ // 1. ruby stack is empty and
+ // 2. top of two line stack ( or default attribute )is an
+ // deactivated two line attribute
+ const bool bRuby =
+ 0 != aAttrStack[ StackPos[ RES_TXTATR_CJK_RUBY ] ].Count();
+
+ if ( bRuby )
+ break;
+
+ sal_uInt16 nTwoLineStack = StackPos[ RES_CHRATR_TWO_LINES ];
+ sal_Bool bTwoLineAct = sal_False;
+ const SfxPoolItem* pTwoLineItem = 0;
+ const SwTxtAttr* pTwoLineAttr = aAttrStack[ nTwoLineStack ].Top();
+
+ if ( pTwoLineAttr )
+ {
+ pTwoLineItem = CharFmt::GetItem( *pTwoLineAttr, RES_CHRATR_TWO_LINES );
+ bTwoLineAct = ((SvxTwoLinesItem*)pTwoLineItem)->GetValue();
+ }
+ else
+ bTwoLineAct =
+ ((SvxTwoLinesItem*)pDefaultArray[ nTwoLineStack ])->GetValue();
+
+ if ( !bTwoLineAct )
+ rFnt.SetVertical( ((SvxCharRotateItem&)rItem).GetValue(),
+ bVertLayout );
+
+ break;
+ }
+ case RES_CHRATR_TWO_LINES :
+ {
+ sal_Bool bRuby = 0 !=
+ aAttrStack[ StackPos[ RES_TXTATR_CJK_RUBY ] ].Count();
+ sal_Bool bTwoLineAct = sal_False;
+
+ // two line is activated, if
+ // 1. no ruby attribute is set and
+ // 2. attribute is active
+ bTwoLineAct = ((SvxTwoLinesItem&)rItem).GetValue();
+
+ if ( !bRuby && bTwoLineAct )
+ {
+ rFnt.SetVertical( 0, bVertLayout );
+ break;
+ }
+
+ // a deactivating two line attribute is on top of stack,
+ // check if rotate attribute has to be enabled
+ if ( bRuby )
+ break;
+
+ sal_uInt16 nRotateStack = StackPos[ RES_CHRATR_ROTATE ];
+ const SfxPoolItem* pRotateItem = 0;
+ const SwTxtAttr* pRotateAttr = aAttrStack[ nRotateStack ].Top();
+
+ if ( pRotateAttr )
+ {
+ pRotateItem = CharFmt::GetItem( *pRotateAttr, RES_CHRATR_ROTATE );
+ rFnt.SetVertical( ((SvxCharRotateItem*)pRotateItem)->GetValue(),
+ bVertLayout );
+ }
+ else
+ rFnt.SetVertical(
+ ((SvxCharRotateItem*)pDefaultArray[ nRotateStack ])->GetValue(),
+ bVertLayout
+ );
+ break;
+ }
+ case RES_TXTATR_CJK_RUBY :
+ rFnt.SetVertical( 0, bVertLayout );
+ break;
+ case RES_TXTATR_REFMARK :
+ if ( bPush )
+ rFnt.GetRef()++;
+ else
+ rFnt.GetRef()--;
+ break;
+ case RES_TXTATR_TOXMARK :
+ if ( bPush )
+ rFnt.GetTox()++;
+ else
+ rFnt.GetTox()--;
+ break;
+ case RES_TXTATR_META:
+ case RES_TXTATR_METAFIELD:
+ if ( bPush )
+ rFnt.GetMeta()++;
+ else
+ rFnt.GetMeta()--;
+ break;
+ }
+}
+
+// Takes the default font and calculated the ascent and height
+void SwAttrHandler::GetDefaultAscentAndHeight( ViewShell* pShell, OutputDevice& rOut,
+ sal_uInt16& nAscent, sal_uInt16& nHeight ) const
+{
+ OSL_ENSURE( pFnt, "No font available for GetDefaultAscentAndHeight" );
+
+ if ( pFnt )
+ {
+ SwFont aFont( *pFnt );
+ nHeight = aFont.GetHeight( pShell, rOut );
+ nAscent = aFont.GetAscent( pShell, rOut );
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/text/blink.cxx b/sw/source/core/text/blink.cxx
new file mode 100644
index 000000000000..fac71e3b7d5b
--- /dev/null
+++ b/sw/source/core/text/blink.cxx
@@ -0,0 +1,200 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+
+#include <tools/debug.hxx>
+#include "viewsh.hxx"
+#include "rootfrm.hxx" // GetOleShell()
+#include "txtfrm.hxx" // FindRootFrm()
+#include "blink.hxx"
+#include "porlin.hxx"
+#include "porlay.hxx" // SwLineLayout
+
+// Sichtbare Zeit:
+#define BLINK_ON_TIME 2400L
+// Nihct sichtbare Zeit:
+#define BLINK_OFF_TIME 800L
+
+/*************************************************************************
+ * pBlink zeigt auf die Instanz, bei der sich blinkende Portions anmelden
+ * muessen, ggf. muss pBlink erst per new SwBlink angelegt werden.
+ * Diese werden dann rhythmisch zum Repaint angeregt und koennen abfragen,
+ * ob sie zur Zeit sichtbar oder unsichtbar sein sollen ( IsVisible() ).
+ *************************************************************************/
+SwBlink *pBlink = NULL;
+
+
+// Liste von blinkenden Portions
+SV_IMPL_OP_PTRARR_SORT( SwBlinkList, SwBlinkPortionPtr )
+
+SwBlink::SwBlink()
+{
+ bVisible = sal_True;
+ // Den Timer vorbereiten
+ aTimer.SetTimeout( BLINK_ON_TIME );
+ aTimer.SetTimeoutHdl( LINK(this, SwBlink, Blinker) );
+}
+
+SwBlink::~SwBlink( )
+{
+ aTimer.Stop();
+}
+
+/*************************************************************************
+ * SwBlink::Blinker (Timerablauf):
+ * Sichtbar/unsichtbar-Flag toggeln.
+ * Repaint-Rechtecke der Blinkportions ermitteln und an ihren OleShells
+ * invalidieren.
+ *************************************************************************/
+
+IMPL_LINK( SwBlink, Blinker, Timer *, EMPTYARG )
+{
+ bVisible = !bVisible;
+ if( bVisible )
+ aTimer.SetTimeout( BLINK_ON_TIME );
+ else
+ aTimer.SetTimeout( BLINK_OFF_TIME );
+ if( aList.Count() )
+ {
+
+ for( MSHORT nPos = 0; nPos < aList.Count(); )
+ {
+ const SwBlinkPortion* pTmp = aList[ nPos ];
+ if( pTmp->GetRootFrm() &&
+ ((SwRootFrm*)pTmp->GetRootFrm())->GetCurrShell() )
+ {
+ ++nPos;
+
+ Point aPos = pTmp->GetPos();
+ long nWidth, nHeight;
+ switch ( pTmp->GetDirection() )
+ {
+ case 900:
+ aPos.X() -= pTmp->GetPortion()->GetAscent();
+ aPos.Y() -= pTmp->GetPortion()->Width();
+ nWidth = pTmp->GetPortion()->SvLSize().Height();
+ nHeight = pTmp->GetPortion()->SvLSize().Width();
+ break;
+ case 1800:
+ aPos.Y() -= pTmp->GetPortion()->Height() -
+ pTmp->GetPortion()->GetAscent();
+ aPos.X() -= pTmp->GetPortion()->Width();
+ nWidth = pTmp->GetPortion()->SvLSize().Width();
+ nHeight = pTmp->GetPortion()->SvLSize().Height();
+ break;
+ case 2700:
+ aPos.X() -= pTmp->GetPortion()->Height() -
+ pTmp->GetPortion()->GetAscent();
+ nWidth = pTmp->GetPortion()->SvLSize().Height();
+ nHeight = pTmp->GetPortion()->SvLSize().Width();
+ break;
+ default:
+ aPos.Y() -= pTmp->GetPortion()->GetAscent();
+ nWidth = pTmp->GetPortion()->SvLSize().Width();
+ nHeight = pTmp->GetPortion()->SvLSize().Height();
+ }
+
+ Rectangle aRefresh( aPos, Size( nWidth, nHeight ) );
+ aRefresh.Right() += ( aRefresh.Bottom()- aRefresh.Top() ) / 8;
+ ((SwRootFrm*)pTmp->GetRootFrm())
+ ->GetCurrShell()->InvalidateWindows( aRefresh );
+ }
+ else // Portions ohne Shell koennen aus der Liste entfernt werden.
+ aList.Remove( nPos );
+ }
+ }
+ else // Wenn die Liste leer ist, kann der Timer gestoppt werden.
+ aTimer.Stop();
+ return sal_True;
+}
+
+void SwBlink::Insert( const Point& rPoint, const SwLinePortion* pPor,
+ const SwTxtFrm *pTxtFrm, sal_uInt16 nDir )
+{
+ SwBlinkPortion *pBlinkPor = new SwBlinkPortion( pPor, nDir );
+
+ MSHORT nPos;
+ if( aList.Seek_Entry( pBlinkPor, &nPos ) )
+ {
+ aList[ nPos ]->SetPos( rPoint );
+ delete pBlinkPor;
+ }
+ else
+ {
+ pBlinkPor->SetPos( rPoint );
+ pBlinkPor->SetRootFrm( pTxtFrm->getRootFrm() );
+ aList.Insert( pBlinkPor );
+ pTxtFrm->SetBlinkPor();
+ if( pPor->IsLayPortion() || pPor->IsParaPortion() )
+ ((SwLineLayout*)pPor)->SetBlinking( sal_True );
+
+ if( !aTimer.IsActive() )
+ aTimer.Start();
+ }
+}
+
+void SwBlink::Replace( const SwLinePortion* pOld, const SwLinePortion* pNew )
+{
+ // setting direction to 0 because direction does not matter
+ // for this operation
+ SwBlinkPortion aBlink( pOld, 0 );
+ MSHORT nPos;
+ if( aList.Seek_Entry( &aBlink, &nPos ) )
+ {
+ SwBlinkPortion* pTmp = new SwBlinkPortion( aList[ nPos ], pNew );
+ aList.Remove( nPos );
+ aList.Insert( pTmp );
+ }
+}
+
+void SwBlink::Delete( const SwLinePortion* pPor )
+{
+ // setting direction to 0 because direction does not matter
+ // for this operation
+ SwBlinkPortion aBlink( pPor, 0 );
+ MSHORT nPos;
+ if( aList.Seek_Entry( &aBlink, &nPos ) )
+ aList.Remove( nPos );
+}
+
+void SwBlink::FrmDelete( const SwRootFrm* pRoot )
+{
+ for( MSHORT nPos = 0; nPos < aList.Count(); )
+ {
+ if( pRoot == aList[ nPos ]->GetRootFrm() )
+ aList.Remove( nPos );
+ else
+ ++nPos;
+ }
+}
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/text/frmcrsr.cxx b/sw/source/core/text/frmcrsr.cxx
new file mode 100644
index 000000000000..2f35e82649b5
--- /dev/null
+++ b/sw/source/core/text/frmcrsr.cxx
@@ -0,0 +1,1752 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+
+#include "ndtxt.hxx" // GetNode()
+#include "pam.hxx" // SwPosition
+#include "frmtool.hxx"
+#include "viewopt.hxx"
+#include "paratr.hxx"
+#include "rootfrm.hxx"
+#include "pagefrm.hxx"
+#include "colfrm.hxx"
+#include "txttypes.hxx"
+#include <sfx2/printer.hxx>
+#include <editeng/lrspitem.hxx>
+#include <editeng/tstpitem.hxx>
+#include <editeng/ulspitem.hxx>
+#include <editeng/lspcitem.hxx>
+#include <pormulti.hxx> // SwMultiPortion
+#include <doc.hxx>
+#include <sortedobjs.hxx>
+
+#include <unicode/ubidi.h>
+
+#include "txtfrm.hxx" // SwTxtFrm
+#include "inftxt.hxx" // SwTxtSizeInfo
+#include "itrtxt.hxx" // SwTxtCursor
+#include "crstate.hxx" // SwTxtCursor
+#include "viewsh.hxx" // InvalidateWindows
+#include "swfntcch.hxx" // SwFontAccess
+#include "flyfrm.hxx"
+
+#if OSL_DEBUG_LEVEL > 1
+#include "txtpaint.hxx"
+#endif
+
+#define MIN_OFFSET_STEP 10
+
+using namespace ::com::sun::star;
+
+
+/*
+ * 1170-SurvivalKit: Wie gelangt man hinter das letzte Zeichen der Zeile.
+ * - RightMargin verzichtet auf den Positionsausgleich mit -1
+ * - GetCharRect liefert bei MV_RIGHTMARGIN ein GetEndCharRect
+ * - GetEndCharRect setzt bRightMargin auf sal_True
+ * - SwTxtCursor::bRightMargin wird per CharCrsrToLine auf sal_False gesetzt
+ */
+
+/*************************************************************************
+ * GetAdjFrmAtPos()
+ *************************************************************************/
+
+SwTxtFrm *GetAdjFrmAtPos( SwTxtFrm *pFrm, const SwPosition &rPos,
+ const sal_Bool bRightMargin, const sal_Bool bNoScroll = sal_True )
+{
+ // 8810: vgl. 1170, RightMargin in der letzten Masterzeile...
+ const xub_StrLen nOffset = rPos.nContent.GetIndex();
+ SwTxtFrm *pFrmAtPos = pFrm;
+ if( !bNoScroll || pFrm->GetFollow() )
+ {
+ pFrmAtPos = pFrm->GetFrmAtPos( rPos );
+ if( nOffset < pFrmAtPos->GetOfst() &&
+ !pFrmAtPos->IsFollow() )
+ {
+ xub_StrLen nNew = nOffset;
+ if( nNew < MIN_OFFSET_STEP )
+ nNew = 0;
+ else
+ nNew -= MIN_OFFSET_STEP;
+ lcl_ChangeOffset( pFrmAtPos, nNew );
+ }
+ }
+ while( pFrm != pFrmAtPos )
+ {
+ pFrm = pFrmAtPos;
+ pFrm->GetFormatted();
+ pFrmAtPos = (SwTxtFrm*)pFrm->GetFrmAtPos( rPos );
+ }
+
+ if( nOffset && bRightMargin )
+ {
+ while( pFrmAtPos && pFrmAtPos->GetOfst() == nOffset &&
+ pFrmAtPos->IsFollow() )
+ {
+ pFrmAtPos->GetFormatted();
+ pFrmAtPos = pFrmAtPos->FindMaster();
+ }
+ OSL_ENSURE( pFrmAtPos, "+GetCharRect: no frame with my rightmargin" );
+ }
+ return pFrmAtPos ? pFrmAtPos : pFrm;
+}
+
+sal_Bool lcl_ChangeOffset( SwTxtFrm* pFrm, xub_StrLen nNew )
+{
+ // In Bereichen und ausserhalb von Flies wird nicht mehr gescrollt.
+ OSL_ENSURE( !pFrm->IsFollow(), "Illegal Scrolling by Follow!" );
+ if( pFrm->GetOfst() != nNew && !pFrm->IsInSct() )
+ {
+ SwFlyFrm *pFly = pFrm->FindFlyFrm();
+ // Vorsicht, wenn z.B. bei einem spaltigen Rahmen die Groesse noch invalide ist,
+ // duerfen wir nicht mal eben herumscrollen
+ if ( ( pFly && pFly->IsValid() &&
+ !pFly->GetNextLink() && !pFly->GetPrevLink() ) ||
+ ( !pFly && pFrm->IsInTab() ) )
+ {
+ ViewShell* pVsh = pFrm->getRootFrm()->GetCurrShell();
+ if( pVsh )
+ {
+ if( pVsh->GetNext() != pVsh ||
+ ( pFrm->GetDrawObjs() && pFrm->GetDrawObjs()->Count() ) )
+ {
+ if( !pFrm->GetOfst() )
+ return sal_False;
+ nNew = 0;
+ }
+ pFrm->SetOfst( nNew );
+ pFrm->SetPara( 0 );
+ pFrm->GetFormatted();
+ if( pFrm->Frm().HasArea() )
+ pFrm->getRootFrm()->GetCurrShell()->InvalidateWindows( pFrm->Frm() );
+ return sal_True;
+ }
+ }
+ }
+ return sal_False;
+}
+
+/*************************************************************************
+ * GetFrmAtOfst(), GetFrmAtPos()
+ *************************************************************************/
+
+// OD 07.10.2003 #110978#
+SwTxtFrm& SwTxtFrm::GetFrmAtOfst( const xub_StrLen nWhere )
+{
+ SwTxtFrm* pRet = this;
+ while( pRet->HasFollow() && nWhere >= pRet->GetFollow()->GetOfst() )
+ pRet = pRet->GetFollow();
+ return *pRet;
+}
+
+SwTxtFrm *SwTxtFrm::GetFrmAtPos( const SwPosition &rPos )
+{
+ SwTxtFrm *pFoll = (SwTxtFrm*)this;
+ while( pFoll->GetFollow() )
+ {
+ if( rPos.nContent.GetIndex() > pFoll->GetFollow()->GetOfst() )
+ pFoll = pFoll->GetFollow();
+ else
+ {
+ if( rPos.nContent.GetIndex() == pFoll->GetFollow()->GetOfst()
+ && !SwTxtCursor::IsRightMargin() )
+ pFoll = pFoll->GetFollow();
+ else
+ break;
+ }
+ }
+ return pFoll;
+}
+
+/*************************************************************************
+ * SwTxtFrm::GetCharRect()
+ *************************************************************************/
+
+/*
+ * GetCharRect() findet die Characterzelle des Characters, dass
+ * durch aPos beschrieben wird. GetCrsrOfst() findet den
+ * umgekehrten Weg: Von einer Dokumentkoordinate zu einem Pam.
+ * Beide sind virtuell in der Framebasisklasse und werden deshalb
+ * immer angezogen.
+ */
+
+sal_Bool SwTxtFrm::GetCharRect( SwRect& rOrig, const SwPosition &rPos,
+ SwCrsrMoveState *pCMS ) const
+{
+ OSL_ENSURE( ! IsVertical() || ! IsSwapped(),"SwTxtFrm::GetCharRect with swapped frame" );
+
+ if( IsLocked() || IsHiddenNow() )
+ return sal_False;
+
+ //Erstmal den richtigen Frm finden, dabei muss beachtet werden, dass:
+ //- die gecachten Informationen verworfen sein koennen (GetPara() == 0)
+ //- das ein Follow gemeint sein kann
+ //- das die Kette der Follows dynamisch waechst; der in den wir
+ // schliesslich gelangen muss aber Formatiert sein.
+
+ // opt: reading ahead erspart uns ein GetAdjFrmAtPos
+ const sal_Bool bRightMargin = pCMS && ( MV_RIGHTMARGIN == pCMS->eState );
+ const sal_Bool bNoScroll = pCMS && pCMS->bNoScroll;
+ SwTxtFrm *pFrm = GetAdjFrmAtPos( (SwTxtFrm*)this, rPos, bRightMargin,
+ bNoScroll );
+ pFrm->GetFormatted();
+ const SwFrm* pTmpFrm = (SwFrm*)pFrm->GetUpper();
+
+ SWRECTFN ( pFrm )
+ const SwTwips nUpperMaxY = (pTmpFrm->*fnRect->fnGetPrtBottom)();
+ const SwTwips nFrmMaxY = (pFrm->*fnRect->fnGetPrtBottom)();
+
+ // nMaxY is an absolute value
+ //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin
+ SwTwips nMaxY = bVert ?
+ ( bVertL2R ? Min( nFrmMaxY, nUpperMaxY ) : Max( nFrmMaxY, nUpperMaxY ) ) :
+ Min( nFrmMaxY, nUpperMaxY );
+
+ sal_Bool bRet = sal_False;
+
+ if ( pFrm->IsEmpty() || ! (pFrm->Prt().*fnRect->fnGetHeight)() )
+ {
+ Point aPnt1 = pFrm->Frm().Pos() + pFrm->Prt().Pos();
+ SwTxtNode* pTxtNd = ((SwTxtFrm*)this)->GetTxtNode();
+ short nFirstOffset;
+ pTxtNd->GetFirstLineOfsWithNum( nFirstOffset );
+
+ Point aPnt2;
+ if ( bVert )
+ {
+ if( nFirstOffset > 0 )
+ aPnt1.Y() += nFirstOffset;
+ //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin
+ if ( aPnt1.X() < nMaxY && !bVertL2R )
+ aPnt1.X() = nMaxY;
+ aPnt2.X() = aPnt1.X() + pFrm->Prt().Width();
+ aPnt2.Y() = aPnt1.Y();
+ if( aPnt2.X() < nMaxY )
+ aPnt2.X() = nMaxY;
+ }
+ else
+ {
+ if( nFirstOffset > 0 )
+ aPnt1.X() += nFirstOffset;
+
+ if( aPnt1.Y() > nMaxY )
+ aPnt1.Y() = nMaxY;
+ aPnt2.X() = aPnt1.X();
+ aPnt2.Y() = aPnt1.Y() + pFrm->Prt().Height();
+ if( aPnt2.Y() > nMaxY )
+ aPnt2.Y() = nMaxY;
+ }
+
+ rOrig = SwRect( aPnt1, aPnt2 );
+
+ if ( pCMS )
+ {
+ pCMS->aRealHeight.X() = 0;
+ pCMS->aRealHeight.Y() = bVert ? -rOrig.Width() : rOrig.Height();
+ }
+
+ if ( pFrm->IsRightToLeft() )
+ pFrm->SwitchLTRtoRTL( rOrig );
+
+ bRet = sal_True;
+ }
+ else
+ {
+ if( !pFrm->HasPara() )
+ return sal_False;
+
+ SwFrmSwapper aSwapper( pFrm, sal_True );
+ if ( bVert )
+ nMaxY = pFrm->SwitchVerticalToHorizontal( nMaxY );
+
+ sal_Bool bGoOn = sal_True;
+ xub_StrLen nOffset = rPos.nContent.GetIndex();
+ xub_StrLen nNextOfst;
+
+ do
+ {
+ {
+ SwTxtSizeInfo aInf( pFrm );
+ SwTxtCursor aLine( pFrm, &aInf );
+ nNextOfst = aLine.GetEnd();
+ // Siehe Kommentar in AdjustFrm
+ // 1170: das letzte Zeichen der Zeile mitnehmen?
+ bRet = bRightMargin ? aLine.GetEndCharRect( &rOrig, nOffset, pCMS, nMaxY )
+ : aLine.GetCharRect( &rOrig, nOffset, pCMS, nMaxY );
+ }
+
+ if ( pFrm->IsRightToLeft() )
+ pFrm->SwitchLTRtoRTL( rOrig );
+
+ if ( bVert )
+ pFrm->SwitchHorizontalToVertical( rOrig );
+
+ if( pFrm->IsUndersized() && pCMS && !pFrm->GetNext() &&
+ (rOrig.*fnRect->fnGetBottom)() == nUpperMaxY &&
+ pFrm->GetOfst() < nOffset &&
+ !pFrm->IsFollow() && !bNoScroll &&
+ pFrm->GetTxtNode()->GetTxt().Len() != nNextOfst )
+ bGoOn = lcl_ChangeOffset( pFrm, nNextOfst );
+ else
+ bGoOn = sal_False;
+ } while ( bGoOn );
+
+ if ( pCMS )
+ {
+ if ( pFrm->IsRightToLeft() )
+ {
+ if( pCMS->b2Lines && pCMS->p2Lines)
+ {
+ pFrm->SwitchLTRtoRTL( pCMS->p2Lines->aLine );
+ pFrm->SwitchLTRtoRTL( pCMS->p2Lines->aPortion );
+ }
+ }
+
+ if ( bVert )
+ {
+ if ( pCMS->bRealHeight )
+ {
+ pCMS->aRealHeight.Y() = -pCMS->aRealHeight.Y();
+ if ( pCMS->aRealHeight.Y() < 0 )
+ {
+ // writing direction is from top to bottom
+ pCMS->aRealHeight.X() = ( rOrig.Width() -
+ pCMS->aRealHeight.X() +
+ pCMS->aRealHeight.Y() );
+ }
+ }
+ if( pCMS->b2Lines && pCMS->p2Lines)
+ {
+ pFrm->SwitchHorizontalToVertical( pCMS->p2Lines->aLine );
+ pFrm->SwitchHorizontalToVertical( pCMS->p2Lines->aPortion );
+ }
+ }
+
+ }
+ }
+ if( bRet )
+ {
+ SwPageFrm *pPage = pFrm->FindPageFrm();
+ OSL_ENSURE( pPage, "Text esaped from page?" );
+ const SwTwips nOrigTop = (rOrig.*fnRect->fnGetTop)();
+ const SwTwips nPageTop = (pPage->Frm().*fnRect->fnGetTop)();
+ const SwTwips nPageBott = (pPage->Frm().*fnRect->fnGetBottom)();
+
+ // Following situation: if the frame is in an invalid sectionframe,
+ // it's possible that the frame is outside the page. If we restrict
+ // the cursor position to the page area, we enforce the formatting
+ // of the page, of the section frame and the frame himself.
+ if( (*fnRect->fnYDiff)( nPageTop, nOrigTop ) > 0 )
+ (rOrig.*fnRect->fnSetTop)( nPageTop );
+
+ if ( (*fnRect->fnYDiff)( nOrigTop, nPageBott ) > 0 )
+ (rOrig.*fnRect->fnSetTop)( nPageBott );
+ }
+
+ return bRet;
+}
+
+/*************************************************************************
+ * SwTxtFrm::GetAutoPos()
+ *************************************************************************/
+
+/*
+ * GetAutoPos() findet die Characterzelle des Characters, dass
+ * durch aPos beschrieben wird und wird von autopositionierten Rahmen genutzt.
+ */
+
+sal_Bool SwTxtFrm::GetAutoPos( SwRect& rOrig, const SwPosition &rPos ) const
+{
+ if( IsHiddenNow() )
+ return sal_False;
+
+ xub_StrLen nOffset = rPos.nContent.GetIndex();
+ SwTxtFrm* pFrm = &(const_cast<SwTxtFrm*>(this)->GetFrmAtOfst( nOffset ));
+
+ pFrm->GetFormatted();
+ const SwFrm* pTmpFrm = (SwFrm*)pFrm->GetUpper();
+
+ SWRECTFN( pTmpFrm )
+ SwTwips nUpperMaxY = (pTmpFrm->*fnRect->fnGetPrtBottom)();
+
+ // nMaxY is in absolute value
+ //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin
+ SwTwips nMaxY = bVert ?
+ ( bVertL2R ? Min( (pFrm->*fnRect->fnGetPrtBottom)(), nUpperMaxY ) : Max( (pFrm->*fnRect->fnGetPrtBottom)(), nUpperMaxY ) ) :
+ Min( (pFrm->*fnRect->fnGetPrtBottom)(), nUpperMaxY );
+
+ if ( pFrm->IsEmpty() || ! (pFrm->Prt().*fnRect->fnGetHeight)() )
+ {
+ Point aPnt1 = pFrm->Frm().Pos() + pFrm->Prt().Pos();
+ Point aPnt2;
+ if ( bVert )
+ {
+ if ( aPnt1.X() < nMaxY && !bVertL2R )
+ aPnt1.X() = nMaxY;
+
+ aPnt2.X() = aPnt1.X() + pFrm->Prt().Width();
+ aPnt2.Y() = aPnt1.Y();
+ if( aPnt2.X() < nMaxY )
+ aPnt2.X() = nMaxY;
+ }
+ else
+ {
+ if( aPnt1.Y() > nMaxY )
+ aPnt1.Y() = nMaxY;
+ aPnt2.X() = aPnt1.X();
+ aPnt2.Y() = aPnt1.Y() + pFrm->Prt().Height();
+ if( aPnt2.Y() > nMaxY )
+ aPnt2.Y() = nMaxY;
+ }
+ rOrig = SwRect( aPnt1, aPnt2 );
+ return sal_True;
+ }
+ else
+ {
+ if( !pFrm->HasPara() )
+ return sal_False;
+
+ SwFrmSwapper aSwapper( pFrm, sal_True );
+ if ( bVert )
+ nMaxY = pFrm->SwitchVerticalToHorizontal( nMaxY );
+
+ SwTxtSizeInfo aInf( pFrm );
+ SwTxtCursor aLine( pFrm, &aInf );
+ SwCrsrMoveState aTmpState( MV_SETONLYTEXT );
+ aTmpState.bRealHeight = sal_True;
+ if( aLine.GetCharRect( &rOrig, nOffset, &aTmpState, nMaxY ) )
+ {
+ if( aTmpState.aRealHeight.X() >= 0 )
+ {
+ rOrig.Pos().Y() += aTmpState.aRealHeight.X();
+ rOrig.Height( aTmpState.aRealHeight.Y() );
+ }
+
+ if ( pFrm->IsRightToLeft() )
+ pFrm->SwitchLTRtoRTL( rOrig );
+
+ if ( bVert )
+ pFrm->SwitchHorizontalToVertical( rOrig );
+
+ return sal_True;
+ }
+ return sal_False;
+ }
+}
+
+/** determine top of line for given position in the text frame
+
+ OD 11.11.2003 #i22341#
+ OD 2004-03-18 #114789# - corrections:
+ - Top of first paragraph line is the top of the printing area of the text frame
+ - If a proportional line spacing is applied use top of anchor character as
+ top of the line.
+
+ @author OD
+*/
+bool SwTxtFrm::GetTopOfLine( SwTwips& _onTopOfLine,
+ const SwPosition& _rPos ) const
+{
+ bool bRet = true;
+
+ // get position offset
+ xub_StrLen nOffset = _rPos.nContent.GetIndex();
+
+ if ( GetTxt().Len() < nOffset )
+ {
+ bRet = false;
+ }
+ else
+ {
+ SWRECTFN( this )
+ if ( IsEmpty() || !(Prt().*fnRect->fnGetHeight)() )
+ {
+ // OD 2004-03-18 #i11860# - consider upper space amount considered
+ // for previous frame and the page grid.
+ _onTopOfLine = (this->*fnRect->fnGetPrtTop)();
+ }
+ else
+ {
+ // determine formatted text frame that contains the requested position
+ SwTxtFrm* pFrm = &(const_cast<SwTxtFrm*>(this)->GetFrmAtOfst( nOffset ));
+ pFrm->GetFormatted();
+ SWREFRESHFN( pFrm )
+ // OD 2004-03-18 #114789# - If proportional line spacing is applied
+ // to the text frame, the top of the anchor character is also the
+ // top of the line.
+ // Otherwise the line layout determines the top of the line
+ const SvxLineSpacingItem& rSpace = GetAttrSet()->GetLineSpacing();
+ if ( rSpace.GetInterLineSpaceRule() == SVX_INTER_LINE_SPACE_PROP )
+ {
+ SwRect aCharRect;
+ if ( GetAutoPos( aCharRect, _rPos ) )
+ {
+ _onTopOfLine = (aCharRect.*fnRect->fnGetTop)();
+ }
+ else
+ {
+ bRet = false;
+ }
+ }
+ else
+ {
+ // assure that text frame is in a horizontal layout
+ SwFrmSwapper aSwapper( pFrm, sal_True );
+ // determine text line that contains the requested position
+ SwTxtSizeInfo aInf( pFrm );
+ SwTxtCursor aLine( pFrm, &aInf );
+ aLine.CharCrsrToLine( nOffset );
+ // determine top of line
+ _onTopOfLine = aLine.Y();
+ if ( bVert )
+ {
+ _onTopOfLine = pFrm->SwitchHorizontalToVertical( _onTopOfLine );
+ }
+ }
+ }
+ }
+
+ return bRet;
+}
+
+/*************************************************************************
+ * SwTxtFrm::_GetCrsrOfst()
+ *************************************************************************/
+
+// Minimaler Abstand von nichtleeren Zeilen etwas weniger als 2 cm
+#define FILL_MIN_DIST 1100
+
+struct SwFillData
+{
+ SwRect aFrm;
+ const SwCrsrMoveState *pCMS;
+ SwPosition* pPos;
+ const Point& rPoint;
+ SwTwips nLineWidth;
+ sal_Bool bFirstLine : 1;
+ sal_Bool bInner : 1;
+ sal_Bool bColumn : 1;
+ sal_Bool bEmpty : 1;
+ SwFillData( const SwCrsrMoveState *pC, SwPosition* pP, const SwRect& rR,
+ const Point& rPt ) : aFrm( rR ), pCMS( pC ), pPos( pP ), rPoint( rPt ),
+ nLineWidth( 0 ), bFirstLine( sal_True ), bInner( sal_False ), bColumn( sal_False ),
+ bEmpty( sal_True ){}
+ SwFillMode Mode() const { return pCMS->pFill->eMode; }
+ long X() const { return rPoint.X(); }
+ long Y() const { return rPoint.Y(); }
+ long Left() const { return aFrm.Left(); }
+ long Right() const { return aFrm.Right(); }
+ long Bottom() const { return aFrm.Bottom(); }
+ SwRect& Frm() { return aFrm; }
+ SwFillCrsrPos &Fill() const { return *pCMS->pFill; }
+ void SetTab( MSHORT nNew ) { pCMS->pFill->nTabCnt = nNew; }
+ void SetSpace( MSHORT nNew ) { pCMS->pFill->nSpaceCnt = nNew; }
+ void SetOrient( const sal_Int16 eNew ){ pCMS->pFill->eOrient = eNew; }
+};
+
+sal_Bool SwTxtFrm::_GetCrsrOfst(SwPosition* pPos, const Point& rPoint,
+ const sal_Bool bChgFrm, SwCrsrMoveState* pCMS ) const
+{
+ // 8804: _GetCrsrOfst wird vom GetCrsrOfst und GetKeyCrsrOfst gerufen.
+ // In keinem Fall nur ein return sal_False.
+
+ if( IsLocked() || IsHiddenNow() )
+ return sal_False;
+
+ ((SwTxtFrm*)this)->GetFormatted();
+
+ Point aOldPoint( rPoint );
+
+ if ( IsVertical() )
+ {
+ SwitchVerticalToHorizontal( (Point&)rPoint );
+ ((SwTxtFrm*)this)->SwapWidthAndHeight();
+ }
+
+ if ( IsRightToLeft() )
+ SwitchRTLtoLTR( (Point&)rPoint );
+
+ SwFillData *pFillData = ( pCMS && pCMS->pFill ) ?
+ new SwFillData( pCMS, pPos, Frm(), rPoint ) : NULL;
+
+ if ( IsEmpty() )
+ {
+ SwTxtNode* pTxtNd = ((SwTxtFrm*)this)->GetTxtNode();
+ pPos->nNode = *pTxtNd;
+ pPos->nContent.Assign( pTxtNd, 0 );
+ if( pCMS && pCMS->bFieldInfo )
+ {
+ SwTwips nDiff = rPoint.X() - Frm().Left() - Prt().Left();
+ if( nDiff > 50 || nDiff < 0 )
+ ((SwCrsrMoveState*)pCMS)->bPosCorr = sal_True;
+ }
+ }
+ else
+ {
+ SwTxtSizeInfo aInf( (SwTxtFrm*)this );
+ SwTxtCursor aLine( ((SwTxtFrm*)this), &aInf );
+
+ // Siehe Kommentar in AdjustFrm()
+ SwTwips nMaxY = Frm().Top() + Prt().Top() + Prt().Height();
+ aLine.TwipsToLine( rPoint.Y() );
+ while( aLine.Y() + aLine.GetLineHeight() > nMaxY )
+ {
+ if( !aLine.Prev() )
+ break;
+ }
+
+ if( aLine.GetDropLines() >= aLine.GetLineNr() && 1 != aLine.GetLineNr()
+ && rPoint.X() < aLine.FirstLeft() + aLine.GetDropLeft() )
+ while( aLine.GetLineNr() > 1 )
+ aLine.Prev();
+
+ xub_StrLen nOffset = aLine.GetCrsrOfst( pPos, rPoint, bChgFrm, pCMS );
+
+ if( pCMS && pCMS->eState == MV_NONE && aLine.GetEnd() == nOffset )
+ ((SwCrsrMoveState*)pCMS)->eState = MV_RIGHTMARGIN;
+
+ // 6776: pPos ist ein reiner IN-Parameter, der nicht ausgewertet werden darf.
+ // Das pIter->GetCrsrOfst returnt aus einer Verschachtelung mit STRING_LEN.
+ // Wenn SwTxtIter::GetCrsrOfst von sich aus weitere GetCrsrOfst
+ // ruft, so aendert sich nNode der Position. In solchen Faellen
+ // darf pPos nicht berechnet werden.
+ if( STRING_LEN != nOffset )
+ {
+ SwTxtNode* pTxtNd = ((SwTxtFrm*)this)->GetTxtNode();
+ pPos->nNode = *pTxtNd;
+ pPos->nContent.Assign( pTxtNd, nOffset );
+ if( pFillData )
+ {
+ if( pTxtNd->GetTxt().Len() > nOffset ||
+ rPoint.Y() < Frm().Top() )
+ pFillData->bInner = sal_True;
+ pFillData->bFirstLine = aLine.GetLineNr() < 2;
+ if( pTxtNd->GetTxt().Len() )
+ {
+ pFillData->bEmpty = sal_False;
+ pFillData->nLineWidth = aLine.GetCurr()->Width();
+ }
+ }
+ }
+ }
+ sal_Bool bChgFillData = sal_False;
+ if( pFillData && FindPageFrm()->Frm().IsInside( aOldPoint ) )
+ {
+ FillCrsrPos( *pFillData );
+ bChgFillData = sal_True;
+ }
+
+ if ( IsVertical() )
+ {
+ if ( bChgFillData )
+ SwitchHorizontalToVertical( pFillData->Fill().aCrsr.Pos() );
+ ((SwTxtFrm*)this)->SwapWidthAndHeight();
+ }
+
+ if ( IsRightToLeft() && bChgFillData )
+ {
+ SwitchLTRtoRTL( pFillData->Fill().aCrsr.Pos() );
+ const sal_Int16 eOrient = pFillData->pCMS->pFill->eOrient;
+
+ if ( text::HoriOrientation::LEFT == eOrient )
+ pFillData->SetOrient( text::HoriOrientation::RIGHT );
+ else if ( text::HoriOrientation::RIGHT == eOrient )
+ pFillData->SetOrient( text::HoriOrientation::LEFT );
+ }
+
+ (Point&)rPoint = aOldPoint;
+ delete pFillData;
+
+ return sal_True;
+}
+
+/*************************************************************************
+ * virtual SwTxtFrm::GetCrsrOfst()
+ *************************************************************************/
+
+sal_Bool SwTxtFrm::GetCrsrOfst(SwPosition* pPos, Point& rPoint,
+ SwCrsrMoveState* pCMS ) const
+{
+ MSHORT nChgFrm = 2;
+ if( pCMS )
+ {
+ if( MV_UPDOWN == pCMS->eState )
+ nChgFrm = 0;
+ else if( MV_SETONLYTEXT == pCMS->eState ||
+ MV_TBLSEL == pCMS->eState )
+ nChgFrm = 1;
+ }
+ return _GetCrsrOfst( pPos, rPoint, nChgFrm != 0, pCMS );
+}
+
+/*************************************************************************
+ * SwTxtFrm::LeftMargin()
+ *************************************************************************/
+
+/*
+ * Layout-orientierte Cursorbewegungen
+ */
+
+/*
+ * an den Zeilenanfang
+ */
+
+sal_Bool SwTxtFrm::LeftMargin(SwPaM *pPam) const
+{
+ if( ((const SwNode*)pPam->GetNode()) != GetNode() )
+ pPam->GetPoint()->nNode = *((SwTxtFrm*)this)->GetTxtNode();
+
+ SwTxtFrm *pFrm = GetAdjFrmAtPos( (SwTxtFrm*)this, *pPam->GetPoint(),
+ SwTxtCursor::IsRightMargin() );
+ pFrm->GetFormatted();
+ xub_StrLen nIndx;
+ if ( pFrm->IsEmpty() )
+ nIndx = 0;
+ else
+ {
+ SwTxtSizeInfo aInf( pFrm );
+ SwTxtCursor aLine( pFrm, &aInf );
+
+ aLine.CharCrsrToLine(pPam->GetPoint()->nContent.GetIndex());
+ nIndx = aLine.GetStart();
+ if( pFrm->GetOfst() && !pFrm->IsFollow() && !aLine.GetPrev() )
+ {
+ lcl_ChangeOffset( pFrm, 0 );
+ nIndx = 0;
+ }
+ }
+ pPam->GetPoint()->nContent = SwIndex( pFrm->GetTxtNode(), nIndx );
+ SwTxtCursor::SetRightMargin( sal_False );
+ return sal_True;
+}
+
+/*************************************************************************
+ * SwTxtFrm::RightMargin()
+ *************************************************************************/
+
+/*
+ * An das Zeilenende:Das ist die Position vor dem letzten
+ * Character in der Zeile. Ausnahme: In der letzten Zeile soll
+ * der Cursor auch hinter dem letzten Character stehen koennen,
+ * um Text anhaengen zu koennen.
+ *
+ */
+
+sal_Bool SwTxtFrm::RightMargin(SwPaM *pPam, sal_Bool bAPI) const
+{
+ if( ((const SwNode*)pPam->GetNode()) != GetNode() )
+ pPam->GetPoint()->nNode = *((SwTxtFrm*)this)->GetTxtNode();
+
+ SwTxtFrm *pFrm = GetAdjFrmAtPos( (SwTxtFrm*)this, *pPam->GetPoint(),
+ SwTxtCursor::IsRightMargin() );
+ pFrm->GetFormatted();
+ xub_StrLen nRightMargin;
+ if ( IsEmpty() )
+ nRightMargin = 0;
+ else
+ {
+ SwTxtSizeInfo aInf( pFrm );
+ SwTxtCursor aLine( pFrm, &aInf );
+
+ aLine.CharCrsrToLine(pPam->GetPoint()->nContent.GetIndex());
+ nRightMargin = aLine.GetStart() + aLine.GetCurr()->GetLen();
+
+ // Harte Zeilenumbrueche lassen wir hinter uns.
+ if( aLine.GetCurr()->GetLen() &&
+ CH_BREAK == aInf.GetTxt().GetChar( nRightMargin - 1 ) )
+ --nRightMargin;
+ else if( !bAPI && (aLine.GetNext() || pFrm->GetFollow()) )
+ {
+ while( nRightMargin > aLine.GetStart() &&
+ ' ' == aInf.GetTxt().GetChar( nRightMargin - 1 ) )
+ --nRightMargin;
+ }
+ }
+ pPam->GetPoint()->nContent = SwIndex( pFrm->GetTxtNode(), nRightMargin );
+ SwTxtCursor::SetRightMargin( !bAPI );
+ return sal_True;
+}
+
+/*************************************************************************
+ * SwTxtFrm::_UnitUp()
+ *************************************************************************/
+
+//Die beiden folgenden Methoden versuchen zunaechst den Crsr in die
+//nachste/folgende Zeile zu setzen. Gibt es im Frame keine vorhergehende/
+//folgende Zeile, so wird der Aufruf an die Basisklasse weitergeleitet.
+//Die Horizontale Ausrichtung des Crsr wird hinterher von der CrsrShell
+//vorgenommen.
+
+class SwSetToRightMargin
+{
+ sal_Bool bRight;
+public:
+ inline SwSetToRightMargin() : bRight( sal_False ) { }
+ inline ~SwSetToRightMargin() { SwTxtCursor::SetRightMargin( bRight ); }
+ inline void SetRight( const sal_Bool bNew ) { bRight = bNew; }
+};
+
+sal_Bool SwTxtFrm::_UnitUp( SwPaM *pPam, const SwTwips nOffset,
+ sal_Bool bSetInReadOnly ) const
+{
+ // 8626: Im Notfall den RightMargin setzen.
+ SwSetToRightMargin aSet;
+
+ if( IsInTab() &&
+ pPam->GetNode( sal_True )->StartOfSectionNode() !=
+ pPam->GetNode( sal_False )->StartOfSectionNode() )
+ {
+ //Wenn der PaM in unterschiedlichen Boxen sitzt, so handelt es sich um
+ //eine Tabellenselektion; diese wird von der Basisklasse abgearbeitet.
+ return SwCntntFrm::UnitUp( pPam, nOffset, bSetInReadOnly );
+ }
+
+ ((SwTxtFrm*)this)->GetFormatted();
+ const xub_StrLen nPos = pPam->GetPoint()->nContent.GetIndex();
+ SwRect aCharBox;
+
+ if( !IsEmpty() && !IsHiddenNow() )
+ {
+ xub_StrLen nFormat = STRING_LEN;
+ do
+ {
+ if( nFormat != STRING_LEN && !IsFollow() )
+ lcl_ChangeOffset( ((SwTxtFrm*)this), nFormat );
+
+ SwTxtSizeInfo aInf( (SwTxtFrm*)this );
+ SwTxtCursor aLine( ((SwTxtFrm*)this), &aInf );
+
+ // 8116: Flys ohne Umlauf und IsDummy(); hier wegoptimiert
+ if( nPos )
+ aLine.CharCrsrToLine( nPos );
+ else
+ aLine.Top();
+
+ const SwLineLayout *pPrevLine = aLine.GetPrevLine();
+ const xub_StrLen nStart = aLine.GetStart();
+ aLine.GetCharRect( &aCharBox, nPos );
+
+ sal_Bool bSecondOfDouble = ( aInf.IsMulti() && ! aInf.IsFirstMulti() );
+ sal_Bool bPrevLine = ( pPrevLine && pPrevLine != aLine.GetCurr() );
+
+ if( !pPrevLine && !bSecondOfDouble && GetOfst() && !IsFollow() )
+ {
+ nFormat = GetOfst();
+ xub_StrLen nDiff = aLine.GetLength();
+ if( !nDiff )
+ nDiff = MIN_OFFSET_STEP;
+ if( nFormat > nDiff )
+ nFormat = nFormat - nDiff;
+ else
+ nFormat = 0;
+ continue;
+ }
+
+ // we select the target line for the cursor, in case we are in a
+ // double line portion, prev line = curr line
+ if( bPrevLine && !bSecondOfDouble )
+ {
+ aLine.PrevLine();
+ while ( aLine.GetStart() == nStart &&
+ 0 != ( pPrevLine = aLine.GetPrevLine() ) &&
+ pPrevLine != aLine.GetCurr() )
+ aLine.PrevLine();
+ }
+
+ if ( bPrevLine || bSecondOfDouble )
+ {
+ aCharBox.SSize().Width() /= 2;
+ aCharBox.Pos().X() = aCharBox.Pos().X() - 150;
+
+ // siehe Kommentar in SwTxtFrm::GetCrsrOfst()
+#if OSL_DEBUG_LEVEL > 1
+ const sal_uLong nOldNode = pPam->GetPoint()->nNode.GetIndex();
+#endif
+ // Der Node soll nicht gewechselt werden
+ xub_StrLen nTmpOfst = aLine.GetCrsrOfst( pPam->GetPoint(),
+ aCharBox.Pos(), sal_False );
+#if OSL_DEBUG_LEVEL > 1
+ OSL_ENSURE( nOldNode == pPam->GetPoint()->nNode.GetIndex(),
+ "SwTxtFrm::UnitUp: illegal node change" );
+#endif
+
+ // 7684: Wir stellen sicher, dass wir uns nach oben bewegen.
+ if( nTmpOfst >= nStart && nStart && !bSecondOfDouble )
+ {
+ nTmpOfst = nStart;
+ aSet.SetRight( sal_True );
+ }
+ pPam->GetPoint()->nContent =
+ SwIndex( ((SwTxtFrm*)this)->GetTxtNode(), nTmpOfst );
+ return sal_True;
+ }
+
+ if ( IsFollow() )
+ {
+ aLine.GetCharRect( &aCharBox, nPos );
+ aCharBox.SSize().Width() /= 2;
+ }
+ break;
+ } while ( sal_True );
+ }
+ /* Wenn this ein Follow ist und ein Prev miszlang, so
+ * muessen wir in die letzte Zeile des Master ... und der sind wir.
+ * Oder wir sind ein Follow mit Follow, dann muessen wir uns den
+ * Master extra besorgen...
+ */
+ if ( IsFollow() )
+ {
+ const SwTxtFrm *pTmpPrev = FindMaster();
+ xub_StrLen nOffs = GetOfst();
+ if( pTmpPrev )
+ {
+ ViewShell *pSh = getRootFrm()->GetCurrShell();
+ sal_Bool bProtectedAllowed = pSh && pSh->GetViewOptions()->IsCursorInProtectedArea();
+ const SwTxtFrm *pPrevPrev = pTmpPrev;
+ // Hier werden geschuetzte Frames und Frame ohne Inhalt ausgelassen
+ while( pPrevPrev && ( pPrevPrev->GetOfst() == nOffs ||
+ ( !bProtectedAllowed && pPrevPrev->IsProtected() ) ) )
+ {
+ pTmpPrev = pPrevPrev;
+ nOffs = pTmpPrev->GetOfst();
+ if ( pPrevPrev->IsFollow() )
+ pPrevPrev = pTmpPrev->FindMaster();
+ else
+ pPrevPrev = NULL;
+ }
+ if ( !pPrevPrev )
+ return pTmpPrev->SwCntntFrm::UnitUp( pPam, nOffset, bSetInReadOnly );
+ aCharBox.Pos().Y() = pPrevPrev->Frm().Bottom() - 1;
+ return pPrevPrev->GetKeyCrsrOfst( pPam->GetPoint(), aCharBox.Pos() );
+ }
+ }
+ return SwCntntFrm::UnitUp( pPam, nOffset, bSetInReadOnly );
+}
+
+//
+// Used for Bidi. nPos is the logical position in the string, bLeft indicates
+// if left arrow or right arrow was pressed. The return values are:
+// nPos: the new visual position
+// bLeft: whether the break iterator has to add or subtract from the
+// current position
+void lcl_VisualMoveRecursion( const SwLineLayout& rCurrLine, xub_StrLen nIdx,
+ xub_StrLen& nPos, sal_Bool& bRight,
+ sal_uInt8& nCrsrLevel, sal_uInt8 nDefaultDir )
+{
+ const SwLinePortion* pPor = rCurrLine.GetFirstPortion();
+ const SwLinePortion* pLast = 0;
+
+ // what's the current portion
+ while ( pPor && nIdx + pPor->GetLen() <= nPos )
+ {
+ nIdx = nIdx + pPor->GetLen();
+ pLast = pPor;
+ pPor = pPor->GetPortion();
+ }
+
+ if ( bRight )
+ {
+ sal_Bool bRecurse = pPor && pPor->IsMultiPortion() &&
+ ((SwMultiPortion*)pPor)->IsBidi();
+
+ // 1. special case: at beginning of bidi portion
+ if ( bRecurse && nIdx == nPos )
+ {
+ nPos = nPos + pPor->GetLen();
+
+ // leave bidi portion
+ if ( nCrsrLevel != nDefaultDir )
+ {
+ bRecurse = sal_False;
+ }
+ else
+ // special case:
+ // buffer: abcXYZ123 in LTR paragraph
+ // view: abc123ZYX
+ // cursor is between c and X in the buffer and cursor level = 0
+ nCrsrLevel++;
+ }
+
+ // 2. special case: at beginning of portion after bidi portion
+ else if ( pLast && pLast->IsMultiPortion() &&
+ ((SwMultiPortion*)pLast)->IsBidi() && nIdx == nPos )
+ {
+ // enter bidi portion
+ if ( nCrsrLevel != nDefaultDir )
+ {
+ bRecurse = sal_True;
+ nIdx = nIdx - pLast->GetLen();
+ pPor = pLast;
+ }
+ }
+
+ // Recursion
+ if ( bRecurse )
+ {
+ const SwLineLayout& rLine = ((SwMultiPortion*)pPor)->GetRoot();
+ xub_StrLen nTmpPos = nPos - nIdx;
+ sal_Bool bTmpForward = ! bRight;
+ sal_uInt8 nTmpCrsrLevel = nCrsrLevel;
+ lcl_VisualMoveRecursion( rLine, 0, nTmpPos, bTmpForward,
+ nTmpCrsrLevel, nDefaultDir + 1 );
+
+ nPos = nTmpPos + nIdx;
+ bRight = bTmpForward;
+ nCrsrLevel = nTmpCrsrLevel;
+ }
+
+ // go forward
+ else
+ {
+ bRight = sal_True;
+ nCrsrLevel = nDefaultDir;
+ }
+
+ }
+ else
+ {
+ sal_Bool bRecurse = pPor && pPor->IsMultiPortion() && ((SwMultiPortion*)pPor)->IsBidi();
+
+ // 1. special case: at beginning of bidi portion
+ if ( bRecurse && nIdx == nPos )
+ {
+ // leave bidi portion
+ if ( nCrsrLevel == nDefaultDir )
+ {
+ bRecurse = sal_False;
+ }
+ }
+
+ // 2. special case: at beginning of portion after bidi portion
+ else if ( pLast && pLast->IsMultiPortion() &&
+ ((SwMultiPortion*)pLast)->IsBidi() && nIdx == nPos )
+ {
+ nPos = nPos - pLast->GetLen();
+
+ // enter bidi portion
+ if ( nCrsrLevel % 2 == nDefaultDir % 2 )
+ {
+ bRecurse = sal_True;
+ nIdx = nIdx - pLast->GetLen();
+ pPor = pLast;
+
+ // special case:
+ // buffer: abcXYZ123 in LTR paragraph
+ // view: abc123ZYX
+ // cursor is behind 3 in the buffer and cursor level = 2
+ if ( nDefaultDir + 2 == nCrsrLevel )
+ nPos = nPos + pLast->GetLen();
+ }
+ }
+
+ // go forward
+ if ( bRecurse )
+ {
+ const SwLineLayout& rLine = ((SwMultiPortion*)pPor)->GetRoot();
+ xub_StrLen nTmpPos = nPos - nIdx;
+ sal_Bool bTmpForward = ! bRight;
+ sal_uInt8 nTmpCrsrLevel = nCrsrLevel;
+ lcl_VisualMoveRecursion( rLine, 0, nTmpPos, bTmpForward,
+ nTmpCrsrLevel, nDefaultDir + 1 );
+
+ // special case:
+ // buffer: abcXYZ123 in LTR paragraph
+ // view: abc123ZYX
+ // cursor is between Z and 1 in the buffer and cursor level = 2
+ if ( nTmpPos == pPor->GetLen() && nTmpCrsrLevel == nDefaultDir + 1 )
+ {
+ nTmpPos = nTmpPos - pPor->GetLen();
+ nTmpCrsrLevel = nDefaultDir;
+ bTmpForward = ! bTmpForward;
+ }
+
+ nPos = nTmpPos + nIdx;
+ bRight = bTmpForward;
+ nCrsrLevel = nTmpCrsrLevel;
+ }
+
+ // go backward
+ else
+ {
+ bRight = sal_False;
+ nCrsrLevel = nDefaultDir;
+ }
+ }
+}
+
+void SwTxtFrm::PrepareVisualMove( xub_StrLen& nPos, sal_uInt8& nCrsrLevel,
+ sal_Bool& bForward, sal_Bool bInsertCrsr )
+{
+ if( IsEmpty() || IsHiddenNow() )
+ return;
+
+ ((SwTxtFrm*)this)->GetFormatted();
+
+ SwTxtSizeInfo aInf( (SwTxtFrm*)this );
+ SwTxtCursor aLine( ((SwTxtFrm*)this), &aInf );
+
+ if( nPos )
+ aLine.CharCrsrToLine( nPos );
+ else
+ aLine.Top();
+
+ const SwLineLayout* pLine = aLine.GetCurr();
+ const xub_StrLen nStt = aLine.GetStart();
+ const xub_StrLen nLen = pLine->GetLen();
+
+ // We have to distinguish between an insert and overwrite cursor:
+ // The insert cursor position depends on the cursor level:
+ // buffer: abcXYZdef in LTR paragraph
+ // display: abcZYXdef
+ // If cursor is between c and X in the buffer and cursor level is 0,
+ // the cursor blinks between c and Z and -> sets the cursor between Z and Y.
+ // If the cursor level is 1, the cursor blinks between X and d and
+ // -> sets the cursor between d and e.
+ // The overwrite cursor simply travels to the next visual character.
+ if ( bInsertCrsr )
+ {
+ lcl_VisualMoveRecursion( *pLine, nStt, nPos, bForward,
+ nCrsrLevel, IsRightToLeft() ? 1 : 0 );
+ return;
+ }
+
+ const sal_uInt8 nDefaultDir = static_cast<sal_uInt8>(IsRightToLeft() ? UBIDI_RTL : UBIDI_LTR);
+ const sal_Bool bVisualRight = ( nDefaultDir == UBIDI_LTR && bForward ) ||
+ ( nDefaultDir == UBIDI_RTL && ! bForward );
+
+ //
+ // Bidi functions from icu 2.0
+ //
+ const sal_Unicode* pLineString = GetTxtNode()->GetTxt().GetBuffer();
+ pLine += nStt;
+
+ UErrorCode nError = U_ZERO_ERROR;
+ UBiDi* pBidi = ubidi_openSized( nLen, 0, &nError );
+ ubidi_setPara( pBidi, reinterpret_cast<const UChar *>(pLineString), nLen, nDefaultDir, NULL, &nError ); // UChar != sal_Unicode in MinGW
+
+ xub_StrLen nTmpPos;
+ sal_Bool bOutOfBounds = sal_False;
+
+ if ( nPos < nStt + nLen )
+ {
+ nTmpPos = (xub_StrLen)ubidi_getVisualIndex( pBidi, nPos, &nError );
+
+ // visual indices are always LTR aligned
+ if ( bVisualRight )
+ {
+ if ( nTmpPos + 1 < nStt + nLen )
+ ++nTmpPos;
+ else
+ {
+ nPos = nDefaultDir == UBIDI_RTL ? 0 : nStt + nLen;
+ bOutOfBounds = sal_True;
+ }
+ }
+ else
+ {
+ if ( nTmpPos )
+ --nTmpPos;
+ else
+ {
+ nPos = nDefaultDir == UBIDI_RTL ? nStt + nLen : 0;
+ bOutOfBounds = sal_True;
+ }
+ }
+ }
+ else
+ {
+ nTmpPos = nDefaultDir == UBIDI_LTR ? nPos - 1 : 0;
+ }
+
+ if ( ! bOutOfBounds )
+ {
+ nPos = (xub_StrLen)ubidi_getLogicalIndex( pBidi, nTmpPos, &nError );
+
+ if ( bForward )
+ {
+ if ( nPos )
+ --nPos;
+ else
+ {
+ ++nPos;
+ bForward = ! bForward;
+ }
+ }
+ else
+ ++nPos;
+ }
+
+ ubidi_close( pBidi );
+}
+
+/*************************************************************************
+ * SwTxtFrm::_UnitDown()
+ *************************************************************************/
+
+sal_Bool SwTxtFrm::_UnitDown(SwPaM *pPam, const SwTwips nOffset,
+ sal_Bool bSetInReadOnly ) const
+{
+
+ if ( IsInTab() &&
+ pPam->GetNode( sal_True )->StartOfSectionNode() !=
+ pPam->GetNode( sal_False )->StartOfSectionNode() )
+ {
+ //Wenn der PaM in unterschiedlichen Boxen sitzt, so handelt es sich um
+ //eine Tabellenselektion; diese wird von der Basisklasse abgearbeitet.
+ return SwCntntFrm::UnitDown( pPam, nOffset, bSetInReadOnly );
+ }
+ ((SwTxtFrm*)this)->GetFormatted();
+ const xub_StrLen nPos = pPam->GetPoint()->nContent.GetIndex();
+ SwRect aCharBox;
+ const SwCntntFrm *pTmpFollow = 0;
+
+ if ( IsVertical() )
+ ((SwTxtFrm*)this)->SwapWidthAndHeight();
+
+ if ( !IsEmpty() && !IsHiddenNow() )
+ {
+ xub_StrLen nFormat = STRING_LEN;
+ do
+ {
+ if( nFormat != STRING_LEN && !IsFollow() &&
+ !lcl_ChangeOffset( ((SwTxtFrm*)this), nFormat ) )
+ break;
+
+ SwTxtSizeInfo aInf( (SwTxtFrm*)this );
+ SwTxtCursor aLine( ((SwTxtFrm*)this), &aInf );
+ nFormat = aLine.GetEnd();
+
+ aLine.CharCrsrToLine( nPos );
+
+ const SwLineLayout* pNextLine = aLine.GetNextLine();
+ const xub_StrLen nStart = aLine.GetStart();
+ aLine.GetCharRect( &aCharBox, nPos );
+
+ sal_Bool bFirstOfDouble = ( aInf.IsMulti() && aInf.IsFirstMulti() );
+
+ if( pNextLine || bFirstOfDouble )
+ {
+ aCharBox.SSize().Width() /= 2;
+#if OSL_DEBUG_LEVEL > 1
+ // siehe Kommentar in SwTxtFrm::GetCrsrOfst()
+ const sal_uLong nOldNode = pPam->GetPoint()->nNode.GetIndex();
+#endif
+ if ( pNextLine && ! bFirstOfDouble )
+ aLine.NextLine();
+
+ xub_StrLen nTmpOfst = aLine.GetCrsrOfst( pPam->GetPoint(),
+ aCharBox.Pos(), sal_False );
+#if OSL_DEBUG_LEVEL > 1
+ OSL_ENSURE( nOldNode == pPam->GetPoint()->nNode.GetIndex(),
+ "SwTxtFrm::UnitDown: illegal node change" );
+#endif
+
+ // 7684: Wir stellen sicher, dass wir uns nach unten bewegen.
+ if( nTmpOfst <= nStart && ! bFirstOfDouble )
+ nTmpOfst = nStart + 1;
+ pPam->GetPoint()->nContent =
+ SwIndex( ((SwTxtFrm*)this)->GetTxtNode(), nTmpOfst );
+
+ if ( IsVertical() )
+ ((SwTxtFrm*)this)->SwapWidthAndHeight();
+
+ return sal_True;
+ }
+ if( 0 != ( pTmpFollow = GetFollow() ) )
+ { // geschuetzte Follows auslassen
+ const SwCntntFrm* pTmp = pTmpFollow;
+ ViewShell *pSh = getRootFrm()->GetCurrShell();
+ if( !pSh || !pSh->GetViewOptions()->IsCursorInProtectedArea() )
+ {
+ while( pTmpFollow && pTmpFollow->IsProtected() )
+ {
+ pTmp = pTmpFollow;
+ pTmpFollow = pTmpFollow->GetFollow();
+ }
+ }
+ if( !pTmpFollow ) // nur noch geschuetzte
+ {
+ if ( IsVertical() )
+ ((SwTxtFrm*)this)->SwapWidthAndHeight();
+ return pTmp->SwCntntFrm::UnitDown( pPam, nOffset, bSetInReadOnly );
+ }
+
+ aLine.GetCharRect( &aCharBox, nPos );
+ aCharBox.SSize().Width() /= 2;
+ }
+ else if( !IsFollow() )
+ {
+ xub_StrLen nTmpLen = aInf.GetTxt().Len();
+ if( aLine.GetEnd() < nTmpLen )
+ {
+ if( nFormat <= GetOfst() )
+ {
+ nFormat = Min( xub_StrLen( GetOfst() + MIN_OFFSET_STEP ),
+ nTmpLen );
+ if( nFormat <= GetOfst() )
+ break;
+ }
+ continue;
+ }
+ }
+ break;
+ } while( sal_True );
+ }
+ else
+ pTmpFollow = GetFollow();
+
+ if ( IsVertical() )
+ ((SwTxtFrm*)this)->SwapWidthAndHeight();
+
+ // Bei Follows schlagen wir eine Abkuerzung
+ if( pTmpFollow )
+ {
+ aCharBox.Pos().Y() = pTmpFollow->Frm().Top() + 1;
+ return ((SwTxtFrm*)pTmpFollow)->GetKeyCrsrOfst( pPam->GetPoint(),
+ aCharBox.Pos() );
+ }
+ return SwCntntFrm::UnitDown( pPam, nOffset, bSetInReadOnly );
+}
+
+/*************************************************************************
+ * virtual SwTxtFrm::UnitUp()
+ *************************************************************************/
+
+sal_Bool SwTxtFrm::UnitUp(SwPaM *pPam, const SwTwips nOffset,
+ sal_Bool bSetInReadOnly ) const
+{
+ /* Im CrsrSh::Up() wird CntntNode::GetFrm() gerufen.
+ * Dies liefert _immer_ den Master zurueck.
+ * Um das Cursortravelling nicht zu belasten, korrigieren wir
+ * hier im SwTxtFrm.
+ * Wir ermittelt UnitUp fuer pFrm, pFrm ist entweder ein Master (=this)
+ * oder ein Follow (!=this)
+ */
+ const SwTxtFrm *pFrm = GetAdjFrmAtPos( (SwTxtFrm*)this, *(pPam->GetPoint()),
+ SwTxtCursor::IsRightMargin() );
+ const sal_Bool bRet = pFrm->_UnitUp( pPam, nOffset, bSetInReadOnly );
+
+ // 8626: kein SwTxtCursor::SetRightMargin( sal_False );
+ // statt dessen steht ein SwSetToRightMargin im _UnitUp
+ return bRet;
+}
+
+/*************************************************************************
+ * virtual SwTxtFrm::UnitDown()
+ *************************************************************************/
+
+sal_Bool SwTxtFrm::UnitDown(SwPaM *pPam, const SwTwips nOffset,
+ sal_Bool bSetInReadOnly ) const
+{
+ const SwTxtFrm *pFrm = GetAdjFrmAtPos((SwTxtFrm*)this, *(pPam->GetPoint()),
+ SwTxtCursor::IsRightMargin() );
+ const sal_Bool bRet = pFrm->_UnitDown( pPam, nOffset, bSetInReadOnly );
+ SwTxtCursor::SetRightMargin( sal_False );
+ return bRet;
+}
+
+void SwTxtFrm::FillCrsrPos( SwFillData& rFill ) const
+{
+ if( !rFill.bColumn && GetUpper()->IsColBodyFrm() ) // ColumnFrms jetzt mit BodyFrm
+ {
+ const SwColumnFrm* pTmp =
+ (SwColumnFrm*)GetUpper()->GetUpper()->GetUpper()->Lower(); // die 1. Spalte
+ // der erste SwFrm im BodyFrm der ersten Spalte
+ const SwFrm* pFrm = ((SwLayoutFrm*)pTmp->Lower())->Lower();
+ MSHORT nNextCol = 0;
+ // In welcher Spalte landen wir?
+ while( rFill.X() > pTmp->Frm().Right() && pTmp->GetNext() )
+ {
+ pTmp = (SwColumnFrm*)pTmp->GetNext();
+ if( ((SwLayoutFrm*)pTmp->Lower())->Lower() ) // ColumnFrms jetzt mit BodyFrm
+ {
+ pFrm = ((SwLayoutFrm*)pTmp->Lower())->Lower();
+ nNextCol = 0;
+ }
+ else
+ ++nNextCol; // leere Spalten erfordern Spaltenumbrueche
+ }
+ if( pTmp != GetUpper()->GetUpper() ) // Sind wir in einer anderen Spalte gelandet?
+ {
+ if( !pFrm )
+ return;
+ if( nNextCol )
+ {
+ while( pFrm->GetNext() )
+ pFrm = pFrm->GetNext();
+ }
+ else
+ {
+ while( pFrm->GetNext() && pFrm->Frm().Bottom() < rFill.Y() )
+ pFrm = pFrm->GetNext();
+ }
+ // Kein Fuellen, wenn als letzter Frame in der anvisierten
+ // Spalte kein Absatz, sondern z.B. eine Tabelle steht
+ if( pFrm->IsTxtFrm() )
+ {
+ rFill.Fill().nColumnCnt = nNextCol;
+ rFill.bColumn = sal_True;
+ if( rFill.pPos )
+ {
+ SwTxtNode* pTxtNd = ((SwTxtFrm*)pFrm)->GetTxtNode();
+ rFill.pPos->nNode = *pTxtNd;
+ rFill.pPos->nContent.Assign( pTxtNd, pTxtNd->GetTxt().Len() );
+ }
+ if( nNextCol )
+ {
+ rFill.aFrm = pTmp->Prt();
+ rFill.aFrm += pTmp->Frm().Pos();
+ }
+ else
+ rFill.aFrm = pFrm->Frm();
+ ((SwTxtFrm*)pFrm)->FillCrsrPos( rFill );
+ }
+ return;
+ }
+ }
+ sal_Bool bFill = sal_True;
+ SwFont *pFnt;
+ SwTxtFmtColl* pColl = GetTxtNode()->GetTxtColl();
+ MSHORT nFirst = GetTxtNode()->GetSwAttrSet().GetULSpace().GetLower();
+ SwTwips nDiff = rFill.Y() - Frm().Bottom();
+ if( nDiff < nFirst )
+ nDiff = -1;
+ else
+ pColl = &pColl->GetNextTxtFmtColl();
+ SwAttrSet aSet( ((SwDoc*)GetTxtNode()->GetDoc())->GetAttrPool(), aTxtFmtCollSetRange );
+ const SwAttrSet* pSet = &pColl->GetAttrSet();
+ ViewShell *pSh = getRootFrm()->GetCurrShell();
+ if( GetTxtNode()->HasSwAttrSet() )
+ {
+ aSet.Put( *GetTxtNode()->GetpSwAttrSet() );
+ aSet.SetParent( pSet );
+ pSet = &aSet;
+ pFnt = new SwFont( pSet, GetNode()->getIDocumentSettingAccess() );
+ }
+ else
+ {
+ SwFontAccess aFontAccess( pColl, pSh );
+ pFnt = new SwFont( *aFontAccess.Get()->GetFont() );
+ pFnt->ChkMagic( pSh, pFnt->GetActual() );
+ }
+ OutputDevice* pOut = pSh->GetOut();
+ if( !pSh->GetViewOptions()->getBrowseMode() || pSh->GetViewOptions()->IsPrtFormat() )
+ pOut = GetTxtNode()->getIDocumentDeviceAccess()->getReferenceDevice( true );
+
+ pFnt->SetFntChg( sal_True );
+ pFnt->ChgPhysFnt( pSh, *pOut );
+
+ SwTwips nLineHeight = pFnt->GetHeight( pSh, *pOut );
+
+ if( nLineHeight )
+ {
+ const SvxULSpaceItem &rUL = pSet->GetULSpace();
+ SwTwips nDist = Max( rUL.GetLower(), rUL.GetUpper() );
+ if( rFill.Fill().nColumnCnt )
+ {
+ rFill.aFrm.Height( nLineHeight );
+ nDiff = rFill.Y() - rFill.Bottom();
+ nFirst = 0;
+ }
+ else if( nDist < nFirst )
+ nFirst = nFirst - (sal_uInt16)nDist;
+ else
+ nFirst = 0;
+ nDist = Max( nDist, long( GetLineSpace() ) );
+ nDist += nLineHeight;
+ nDiff -= nFirst;
+
+ if( nDiff > 0 )
+ {
+ nDiff /= nDist;
+ rFill.Fill().nParaCnt = static_cast<sal_uInt16>(nDiff + 1);
+ rFill.nLineWidth = 0;
+ rFill.bInner = sal_False;
+ rFill.bEmpty = sal_True;
+ rFill.SetOrient( text::HoriOrientation::LEFT );
+ }
+ else
+ nDiff = -1;
+ if( rFill.bInner )
+ bFill = sal_False;
+ else
+ {
+ const SvxTabStopItem &rRuler = pSet->GetTabStops();
+ const SvxLRSpaceItem &rLRSpace = pSet->GetLRSpace();
+
+ SwRect &rRect = rFill.Fill().aCrsr;
+ rRect.Top( rFill.Bottom() + (nDiff+1) * nDist - nLineHeight );
+ if( nFirst && nDiff > -1 )
+ rRect.Top( rRect.Top() + nFirst );
+ rRect.Height( nLineHeight );
+ SwTwips nLeft = rFill.Left() + rLRSpace.GetLeft() +
+ GetTxtNode()->GetLeftMarginWithNum( sal_False );
+ SwTwips nRight = rFill.Right() - rLRSpace.GetRight();
+ SwTwips nCenter = ( nLeft + nRight ) / 2;
+ rRect.Left( nLeft );
+ if( FILL_MARGIN == rFill.Mode() )
+ {
+ if( rFill.bEmpty )
+ {
+ rFill.SetOrient( text::HoriOrientation::LEFT );
+ if( rFill.X() < nCenter )
+ {
+ if( rFill.X() > ( nLeft + 2 * nCenter ) / 3 )
+ {
+ rFill.SetOrient( text::HoriOrientation::CENTER );
+ rRect.Left( nCenter );
+ }
+ }
+ else if( rFill.X() > ( nRight + 2 * nCenter ) / 3 )
+ {
+ rFill.SetOrient( text::HoriOrientation::RIGHT );
+ rRect.Left( nRight );
+ }
+ else
+ {
+ rFill.SetOrient( text::HoriOrientation::CENTER );
+ rRect.Left( nCenter );
+ }
+ }
+ else
+ bFill = sal_False;
+ }
+ else
+ {
+ SwTwips nSpace = 0;
+ if( FILL_TAB != rFill.Mode() )
+ {
+static sal_Char const sDoubleSpace[] = " ";
+ const XubString aTmp( sDoubleSpace, RTL_TEXTENCODING_MS_1252 );
+
+ SwDrawTextInfo aDrawInf( pSh, *pOut, 0, aTmp, 0, 2 );
+ nSpace = pFnt->_GetTxtSize( aDrawInf ).Width()/2;
+ }
+ if( rFill.X() >= nRight )
+ {
+ if( FILL_INDENT != rFill.Mode() && ( rFill.bEmpty ||
+ rFill.X() > rFill.nLineWidth + FILL_MIN_DIST ) )
+ {
+ rFill.SetOrient( text::HoriOrientation::RIGHT );
+ rRect.Left( nRight );
+ }
+ else
+ bFill = sal_False;
+ }
+ else if( FILL_INDENT == rFill.Mode() )
+ {
+ SwTwips nIndent = rFill.X();
+ if( !rFill.bEmpty || nIndent > nRight )
+ bFill = sal_False;
+ else
+ {
+ nIndent -= rFill.Left();
+ if( nIndent >= 0 && nSpace )
+ {
+ nIndent /= nSpace;
+ nIndent *= nSpace;
+ rFill.SetTab( MSHORT( nIndent ) );
+ rRect.Left( nIndent + rFill.Left() );
+ }
+ else
+ bFill = sal_False;
+ }
+ }
+ else if( rFill.X() > nLeft )
+ {
+ SwTwips nTxtLeft = rFill.Left() + rLRSpace.GetTxtLeft() +
+ GetTxtNode()->GetLeftMarginWithNum( sal_True );
+ rFill.nLineWidth += rFill.bFirstLine ? nLeft : nTxtLeft;
+ SwTwips nLeftTab = nLeft;
+ SwTwips nRightTab = nLeft;
+ MSHORT nSpaceCnt = 0;
+ MSHORT nTabCnt = 0;
+ MSHORT nIdx = 0;
+ do
+ {
+ nLeftTab = nRightTab;
+ if( nIdx < rRuler.Count() )
+ {
+ const SvxTabStop &rTabStop = rRuler.operator[](nIdx);
+ nRightTab = nTxtLeft + rTabStop.GetTabPos();
+ if( nLeftTab < nTxtLeft && nRightTab > nTxtLeft )
+ nRightTab = nTxtLeft;
+ else
+ ++nIdx;
+ if( nRightTab > rFill.nLineWidth )
+ ++nTabCnt;
+ }
+ else
+ {
+ const SvxTabStopItem& rTab =
+ (const SvxTabStopItem &)pSet->
+ GetPool()->GetDefaultItem( RES_PARATR_TABSTOP );
+ MSHORT nDefTabDist = (MSHORT)rTab.GetStart()->GetTabPos();
+ nRightTab = nLeftTab - nTxtLeft;
+ nRightTab /= nDefTabDist;
+ nRightTab = nRightTab * nDefTabDist + nTxtLeft;
+ while ( nRightTab <= nLeftTab )
+ nRightTab += nDefTabDist;
+ if( nRightTab > rFill.nLineWidth )
+ ++nTabCnt;
+ while ( nRightTab < rFill.X() )
+ {
+ nRightTab += nDefTabDist;
+ if( nRightTab > rFill.nLineWidth )
+ ++nTabCnt;
+ }
+ if( nLeftTab < nRightTab - nDefTabDist )
+ nLeftTab = nRightTab - nDefTabDist;
+ }
+ if( nRightTab > nRight )
+ nRightTab = nRight;
+ }
+ while( rFill.X() > nRightTab );
+ --nTabCnt;
+ if( FILL_TAB != rFill.Mode() )
+ {
+ if( nSpace > 0 )
+ {
+ if( !nTabCnt )
+ nLeftTab = rFill.nLineWidth;
+ while( nLeftTab < rFill.X() )
+ {
+ nLeftTab += nSpace;
+ ++nSpaceCnt;
+ }
+ if( nSpaceCnt )
+ {
+ nLeftTab -= nSpace;
+ --nSpaceCnt;
+ }
+ if( rFill.X() - nLeftTab > nRightTab - rFill.X() )
+ {
+ nSpaceCnt = 0;
+ ++nTabCnt;
+ rRect.Left( nRightTab );
+ }
+ else
+ {
+ if( rFill.X() - nLeftTab > nSpace/2 )
+ {
+ ++nSpaceCnt;
+ rRect.Left( nLeftTab + nSpace );
+ }
+ else
+ rRect.Left( nLeftTab );
+ }
+ }
+ else if( rFill.X() - nLeftTab < nRightTab - rFill.X() )
+ rRect.Left( nLeftTab );
+ else
+ {
+ if( nRightTab >= nRight )
+ {
+ rFill.SetOrient( text::HoriOrientation::RIGHT );
+ rRect.Left( nRight );
+ nTabCnt = 0;
+ nSpaceCnt = 0;
+ }
+ else
+ {
+ rRect.Left( nRightTab );
+ ++nTabCnt;
+ }
+ }
+ }
+ else
+ {
+ if( rFill.X() - nLeftTab < nRightTab - rFill.X() )
+ rRect.Left( nLeftTab );
+ else
+ {
+ if( nRightTab >= nRight )
+ {
+ rFill.SetOrient( text::HoriOrientation::RIGHT );
+ rRect.Left( nRight );
+ nTabCnt = 0;
+ nSpaceCnt = 0;
+ }
+ else
+ {
+ rRect.Left( nRightTab );
+ ++nTabCnt;
+ }
+ }
+ }
+ rFill.SetTab( nTabCnt );
+ rFill.SetSpace( nSpaceCnt );
+ if( bFill )
+ {
+ if( Abs( rFill.X() - nCenter ) <=
+ Abs( rFill.X() - rRect.Left() ) )
+ {
+ rFill.SetOrient( text::HoriOrientation::CENTER );
+ rFill.SetTab( 0 );
+ rFill.SetSpace( 0 );
+ rRect.Left( nCenter );
+ }
+ if( !rFill.bEmpty )
+ rFill.nLineWidth += FILL_MIN_DIST;
+ if( rRect.Left() < rFill.nLineWidth )
+ bFill = sal_False;
+ }
+ }
+ }
+ // Gehen wir ueber die Unterkante der Seite/Spalte etc. hinaus?
+ const SwFrm* pUp = GetUpper();
+ if( pUp->IsInSct() )
+ {
+ if( pUp->IsSctFrm() )
+ pUp = pUp->GetUpper();
+ else if( pUp->IsColBodyFrm() &&
+ pUp->GetUpper()->GetUpper()->IsSctFrm() )
+ pUp = pUp->GetUpper()->GetUpper()->GetUpper();
+ }
+ SWRECTFN( this )
+ SwTwips nLimit = (pUp->*fnRect->fnGetPrtBottom)();
+ SwTwips nRectBottom = rRect.Bottom();
+ if ( bVert )
+ nRectBottom = SwitchHorizontalToVertical( nRectBottom );
+
+ if( (*fnRect->fnYDiff)( nLimit, nRectBottom ) < 0 )
+ bFill = sal_False;
+ else
+ rRect.Width( 1 );
+ }
+ }
+ else
+ bFill = sal_False;
+ ((SwCrsrMoveState*)rFill.pCMS)->bFillRet = bFill;
+ delete pFnt;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/text/frmform.cxx b/sw/source/core/text/frmform.cxx
new file mode 100644
index 000000000000..e28b1694d8a6
--- /dev/null
+++ b/sw/source/core/text/frmform.cxx
@@ -0,0 +1,2068 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+#include <hintids.hxx>
+#include <editeng/keepitem.hxx>
+#include <editeng/hyznitem.hxx>
+#include <pagefrm.hxx> // ChangeFtnRef
+#include <ndtxt.hxx> // MakeFrm()
+#include <dcontact.hxx> // SwDrawContact
+#include <dflyobj.hxx> // SwVirtFlyDrawObj
+#include <flyfrm.hxx>
+#include <ftnfrm.hxx> // SwFtnFrm
+#include <txtftn.hxx>
+#include <fmtftn.hxx>
+#include <paratr.hxx>
+#include <viewopt.hxx> // SwViewOptions
+#include <viewsh.hxx> // ViewShell
+#include <frmatr.hxx>
+#include <pam.hxx>
+#include <flyfrms.hxx>
+#include <fmtanchr.hxx>
+#include <itrform2.hxx> // SwTxtFormatter
+#include <widorp.hxx> // Widows and Orphans
+#include <txtcache.hxx>
+#include <porrst.hxx> // SwEmptyPortion
+#include <blink.hxx> // pBlink
+#include <porfld.hxx> // SwFldPortion
+#include <sectfrm.hxx> // SwSectionFrm
+#include <pormulti.hxx> // SwMultiPortion
+
+#include <rootfrm.hxx>
+#include <frmfmt.hxx> // SwFrmFmt
+// OD 2004-05-24 #i28701#
+#include <sortedobjs.hxx>
+
+// Toleranzwert in der Formatierung und Textausgabe.
+#define SLOPPY_TWIPS 5
+
+class FormatLevel
+{
+ static MSHORT nLevel;
+public:
+ inline FormatLevel() { ++nLevel; }
+ inline ~FormatLevel() { --nLevel; }
+ inline MSHORT GetLevel() const { return nLevel; }
+ static sal_Bool LastLevel() { return 10 < nLevel; }
+};
+MSHORT FormatLevel::nLevel = 0;
+
+/*************************************************************************
+ * ValidateTxt/Frm()
+ *************************************************************************/
+
+void ValidateTxt( SwFrm *pFrm ) // Freund vom Frame
+{
+ if ( ( ! pFrm->IsVertical() &&
+ pFrm->Frm().Width() == pFrm->GetUpper()->Prt().Width() ) ||
+ ( pFrm->IsVertical() &&
+ pFrm->Frm().Height() == pFrm->GetUpper()->Prt().Height() ) )
+ pFrm->bValidSize = sal_True;
+}
+
+void SwTxtFrm::ValidateFrm()
+{
+ // Umgebung validieren, um Oszillationen zu verhindern.
+ SWAP_IF_SWAPPED( this )
+
+ if ( !IsInFly() && !IsInTab() )
+ { //Innerhalb eines Flys nur this validieren, der Rest sollte eigentlich
+ //nur fuer Fussnoten notwendig sein und die gibt es innerhalb von
+ //Flys nicht. Fix fuer 5544
+ SwSectionFrm* pSct = FindSctFrm();
+ if( pSct )
+ {
+ if( !pSct->IsColLocked() )
+ pSct->ColLock();
+ else
+ pSct = NULL;
+ }
+
+ SwFrm *pUp = GetUpper();
+ pUp->Calc();
+ if( pSct )
+ pSct->ColUnlock();
+ }
+ ValidateTxt( this );
+
+ //MA: mindestens das MustFit-Flag muessen wir retten!
+ OSL_ENSURE( HasPara(), "ResetPreps(), missing ParaPortion." );
+ SwParaPortion *pPara = GetPara();
+ const sal_Bool bMustFit = pPara->IsPrepMustFit();
+ ResetPreps();
+ pPara->SetPrepMustFit( bMustFit );
+
+ UNDO_SWAP( this )
+}
+
+/*************************************************************************
+ * ValidateBodyFrm()
+ *************************************************************************/
+
+// nach einem RemoveFtn muss der BodyFrm und alle innenliegenden kalkuliert
+// werden, damit die DeadLine richtig sitzt.
+// Erst wird nach aussen hin gesucht, beim Rueckweg werden alle kalkuliert.
+
+void _ValidateBodyFrm( SwFrm *pFrm )
+{
+ if( pFrm && !pFrm->IsCellFrm() )
+ {
+ if( !pFrm->IsBodyFrm() && pFrm->GetUpper() )
+ _ValidateBodyFrm( pFrm->GetUpper() );
+ if( !pFrm->IsSctFrm() )
+ pFrm->Calc();
+ else
+ {
+ sal_Bool bOld = ((SwSectionFrm*)pFrm)->IsCntntLocked();
+ ((SwSectionFrm*)pFrm)->SetCntntLock( sal_True );
+ pFrm->Calc();
+ if( !bOld )
+ ((SwSectionFrm*)pFrm)->SetCntntLock( sal_False );
+ }
+ }
+}
+
+void SwTxtFrm::ValidateBodyFrm()
+{
+ SWAP_IF_SWAPPED( this )
+
+ //siehe Kommtar in ValidateFrm()
+ if ( !IsInFly() && !IsInTab() &&
+ !( IsInSct() && FindSctFrm()->Lower()->IsColumnFrm() ) )
+ _ValidateBodyFrm( GetUpper() );
+
+ UNDO_SWAP( this )
+}
+
+/*************************************************************************
+ * SwTxtFrm::FindBodyFrm()
+ *************************************************************************/
+
+sal_Bool SwTxtFrm::_GetDropRect( SwRect &rRect ) const
+{
+ SWAP_IF_NOT_SWAPPED( this )
+
+ OSL_ENSURE( HasPara(), "SwTxtFrm::_GetDropRect: try again next year." );
+ SwTxtSizeInfo aInf( (SwTxtFrm*)this );
+ SwTxtMargin aLine( (SwTxtFrm*)this, &aInf );
+ if( aLine.GetDropLines() )
+ {
+ rRect.Top( aLine.Y() );
+ rRect.Left( aLine.GetLineStart() );
+ rRect.Height( aLine.GetDropHeight() );
+ rRect.Width( aLine.GetDropLeft() );
+
+ if ( IsRightToLeft() )
+ SwitchLTRtoRTL( rRect );
+
+ if ( IsVertical() )
+ SwitchHorizontalToVertical( rRect );
+ UNDO_SWAP( this )
+ return sal_True;
+ }
+
+ UNDO_SWAP( this )
+
+ return sal_False;
+}
+
+/*************************************************************************
+ * SwTxtFrm::FindBodyFrm()
+ *************************************************************************/
+
+const SwBodyFrm *SwTxtFrm::FindBodyFrm() const
+{
+ if ( IsInDocBody() )
+ {
+ const SwFrm *pFrm = GetUpper();
+ while( pFrm && !pFrm->IsBodyFrm() )
+ pFrm = pFrm->GetUpper();
+ return (const SwBodyFrm*)pFrm;
+ }
+ return 0;
+}
+
+/*************************************************************************
+ * SwTxtFrm::CalcFollow()
+ *************************************************************************/
+
+sal_Bool SwTxtFrm::CalcFollow( const xub_StrLen nTxtOfst )
+{
+ SWAP_IF_SWAPPED( this )
+
+ OSL_ENSURE( HasFollow(), "CalcFollow: missing Follow." );
+
+ SwTxtFrm* pMyFollow = GetFollow();
+
+ SwParaPortion *pPara = GetPara();
+ sal_Bool bFollowFld = pPara ? pPara->IsFollowField() : sal_False;
+
+ if( !pMyFollow->GetOfst() || pMyFollow->GetOfst() != nTxtOfst ||
+ bFollowFld || pMyFollow->IsFieldFollow() ||
+ ( pMyFollow->IsVertical() && !pMyFollow->Prt().Width() ) ||
+ ( ! pMyFollow->IsVertical() && !pMyFollow->Prt().Height() ) )
+ {
+#if OSL_DEBUG_LEVEL > 1
+ const SwFrm *pOldUp = GetUpper();
+#endif
+
+ SWRECTFN ( this )
+ SwTwips nOldBottom = (GetUpper()->Frm().*fnRect->fnGetBottom)();
+ SwTwips nMyPos = (Frm().*fnRect->fnGetTop)();
+
+ const SwPageFrm *pPage = 0;
+ sal_Bool bOldInvaCntnt = sal_True;
+ if ( !IsInFly() && GetNext() )
+ {
+ pPage = FindPageFrm();
+ //Minimieren - sprich ggf. zuruecksetzen - der Invalidierungen s.u.
+ bOldInvaCntnt = pPage->IsInvalidCntnt();
+ }
+
+ pMyFollow->_SetOfst( nTxtOfst );
+ pMyFollow->SetFieldFollow( bFollowFld );
+ if( HasFtn() || pMyFollow->HasFtn() )
+ {
+ ValidateFrm();
+ ValidateBodyFrm();
+ if( pPara )
+ {
+ *(pPara->GetReformat()) = SwCharRange();
+ *(pPara->GetDelta()) = 0;
+ }
+ }
+
+ //Der Fussnotenbereich darf sich keinesfalls vergrossern.
+ SwSaveFtnHeight aSave( FindFtnBossFrm( sal_True ), LONG_MAX );
+
+ pMyFollow->CalcFtnFlag();
+ if ( !pMyFollow->GetNext() && !pMyFollow->HasFtn() )
+ nOldBottom = bVert ? 0 : LONG_MAX;
+
+ while( sal_True )
+ {
+ if( !FormatLevel::LastLevel() )
+ {
+ // Weenn der Follow in einem spaltigen Bereich oder einem
+ // spaltigen Rahmen steckt, muss zunaechst dieser kalkuliert
+ // werden, da das FormatWidthCols() nicht funktioniert, wenn
+ // es aus dem MakeAll des _gelockten_ Follows heraus gerufen
+ // wird.
+ SwSectionFrm* pSct = pMyFollow->FindSctFrm();
+ if( pSct && !pSct->IsAnLower( this ) )
+ {
+ if( pSct->GetFollow() )
+ pSct->SimpleFormat();
+ else if( ( pSct->IsVertical() && !pSct->Frm().Width() ) ||
+ ( ! pSct->IsVertical() && !pSct->Frm().Height() ) )
+ break;
+ }
+ // OD 14.03.2003 #i11760# - intrinsic format of follow is controlled.
+ if ( FollowFormatAllowed() )
+ {
+ // OD 14.03.2003 #i11760# - no nested format of follows, if
+ // text frame is contained in a column frame.
+ // Thus, forbid intrinsic format of follow.
+ {
+ bool bIsFollowInColumn = false;
+ SwFrm* pFollowUpper = pMyFollow->GetUpper();
+ while ( pFollowUpper )
+ {
+ if ( pFollowUpper->IsColumnFrm() )
+ {
+ bIsFollowInColumn = true;
+ break;
+ }
+ if ( pFollowUpper->IsPageFrm() ||
+ pFollowUpper->IsFlyFrm() )
+ {
+ break;
+ }
+ pFollowUpper = pFollowUpper->GetUpper();
+ }
+ if ( bIsFollowInColumn )
+ {
+ pMyFollow->ForbidFollowFormat();
+ }
+ }
+
+ pMyFollow->Calc();
+ // Der Follow merkt anhand seiner Frm().Height(), dass was schief
+ // gelaufen ist.
+ OSL_ENSURE( !pMyFollow->GetPrev(), "SwTxtFrm::CalcFollow: cheesy follow" );
+ if( pMyFollow->GetPrev() )
+ {
+ pMyFollow->Prepare( PREP_CLEAR );
+ pMyFollow->Calc();
+ OSL_ENSURE( !pMyFollow->GetPrev(), "SwTxtFrm::CalcFollow: very cheesy follow" );
+ }
+
+ // OD 14.03.2003 #i11760# - reset control flag for follow format.
+ pMyFollow->AllowFollowFormat();
+ }
+
+ //Sicherstellen, dass der Follow gepaintet wird.
+ pMyFollow->SetCompletePaint();
+ }
+
+ pPara = GetPara();
+ //Solange der Follow wg. Orphans Zeilen angefordert, bekommt er
+ //diese und wird erneut formatiert, falls moeglich.
+ if( pPara && pPara->IsPrepWidows() )
+ CalcPreps();
+ else
+ break;
+ }
+
+ if( HasFtn() || pMyFollow->HasFtn() )
+ {
+ ValidateBodyFrm();
+ ValidateFrm();
+ if( pPara )
+ {
+ *(pPara->GetReformat()) = SwCharRange();
+ *(pPara->GetDelta()) = 0;
+ }
+ }
+
+ if ( pPage )
+ {
+ if ( !bOldInvaCntnt )
+ pPage->ValidateCntnt();
+ }
+
+#if OSL_DEBUG_LEVEL > 1
+ OSL_ENSURE( pOldUp == GetUpper(), "SwTxtFrm::CalcFollow: heavy follow" );
+#endif
+
+ const long nRemaining =
+ - (GetUpper()->Frm().*fnRect->fnBottomDist)( nOldBottom );
+ if ( nRemaining > 0 && !GetUpper()->IsSctFrm() &&
+ nRemaining != ( bVert ?
+ nMyPos - Frm().Right() :
+ Frm().Top() - nMyPos ) )
+ {
+ UNDO_SWAP( this )
+ return sal_True;
+ }
+ }
+
+ UNDO_SWAP( this )
+
+ return sal_False;
+}
+
+/*************************************************************************
+ * SwTxtFrm::AdjustFrm()
+ *************************************************************************/
+
+void SwTxtFrm::AdjustFrm( const SwTwips nChgHght, sal_Bool bHasToFit )
+{
+ if( IsUndersized() )
+ {
+ if( GetOfst() && !IsFollow() ) // ein gescrollter Absatz (undersized)
+ return;
+ SetUndersized( nChgHght == 0 || bHasToFit );
+ }
+
+ // AdjustFrm is called with a swapped frame during
+ // formatting but the frame is not swapped during FormatEmpty
+ SWAP_IF_SWAPPED( this )
+ SWRECTFN ( this )
+
+ // Die Size-Variable des Frames wird durch Grow inkrementiert
+ // oder durch Shrink dekrementiert. Wenn die Groesse
+ // unveraendert ist, soll nichts passieren!
+ if( nChgHght >= 0)
+ {
+ SwTwips nChgHeight = nChgHght;
+ if( nChgHght && !bHasToFit )
+ {
+ if( IsInFtn() && !IsInSct() )
+ {
+ SwTwips nReal = Grow( nChgHght, sal_True );
+ if( nReal < nChgHght )
+ {
+ SwTwips nBot = (*fnRect->fnYInc)( (Frm().*fnRect->fnGetBottom)(),
+ nChgHght - nReal );
+ SwFrm* pCont = FindFtnFrm()->GetUpper();
+
+ if( (pCont->Frm().*fnRect->fnBottomDist)( nBot ) > 0 )
+ {
+ (Frm().*fnRect->fnAddBottom)( nChgHght );
+ if( bVert )
+ Prt().SSize().Width() += nChgHght;
+ else
+ Prt().SSize().Height() += nChgHght;
+ UNDO_SWAP( this )
+ return;
+ }
+ }
+ }
+
+ Grow( nChgHght );
+
+ if ( IsInFly() )
+ {
+ //MA 06. May. 93: Wenn einer der Upper ein Fly ist, so ist es
+ //sehr wahrscheinlich, dass dieser Fly durch das Grow seine
+ //Position veraendert - also muss auch meine Position korrigiert
+ //werden (sonst ist die Pruefung s.u. nicht aussagekraeftig).
+ //Die Vorgaenger muessen berechnet werden, damit die Position
+ //korrekt berechnet werden kann.
+ if ( GetPrev() )
+ {
+ SwFrm *pPre = GetUpper()->Lower();
+ do
+ { pPre->Calc();
+ pPre = pPre->GetNext();
+ } while ( pPre && pPre != this );
+ }
+ const Point aOldPos( Frm().Pos() );
+ MakePos();
+ if ( aOldPos != Frm().Pos() )
+ {
+ // OD 2004-07-01 #i28701# - use new method <SwFrm::InvalidateObjs(..)>
+ // No format is performed for the floating screen objects.
+ InvalidateObjs( true );
+ }
+ }
+ nChgHeight = 0;
+ }
+ // Ein Grow() wird von der Layout-Seite immer akzeptiert,
+ // also auch, wenn die FixSize des umgebenden Layoutframes
+ // dies nicht zulassen sollte. Wir ueberpruefen diesen
+ // Fall und korrigieren die Werte.
+ // MA 06. May. 93: Der Frm darf allerdings auch im Notfall nicht
+ // weiter geschrumpft werden als es seine Groesse zulaesst.
+ SwTwips nRstHeight;
+ if ( IsVertical() )
+ {
+ OSL_ENSURE( ! IsSwapped(),"Swapped frame while calculating nRstHeight" );
+
+ //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin
+ if ( IsVertLR() )
+ nRstHeight = GetUpper()->Frm().Left()
+ + GetUpper()->Prt().Left()
+ + GetUpper()->Prt().Width()
+ - Frm().Left();
+ else
+ nRstHeight = Frm().Left() + Frm().Width() -
+ ( GetUpper()->Frm().Left() + GetUpper()->Prt().Left() );
+ }
+ else
+ nRstHeight = GetUpper()->Frm().Top()
+ + GetUpper()->Prt().Top()
+ + GetUpper()->Prt().Height()
+ - Frm().Top();
+
+ //In Tabellenzellen kann ich mir evtl. noch ein wenig dazuholen, weil
+ //durch eine vertikale Ausrichtung auch oben noch Raum sein kann.
+ // --> OD 2004-11-25 #115759# - assure, that first lower in upper
+ // is the current one or is valid.
+ if ( IsInTab() &&
+ ( GetUpper()->Lower() == this ||
+ GetUpper()->Lower()->IsValid() ) )
+ // <--
+ {
+ long nAdd = (*fnRect->fnYDiff)( (GetUpper()->Lower()->Frm().*fnRect->fnGetTop)(),
+ (GetUpper()->*fnRect->fnGetPrtTop)() );
+ OSL_ENSURE( nAdd >= 0, "Ey" );
+ nRstHeight += nAdd;
+ }
+
+/* ------------------------------------
+ * #50964#: nRstHeight < 0 bedeutet, dass der TxtFrm komplett ausserhalb seines
+ * Upper liegt. Dies kann passieren, wenn er innerhalb eines FlyAtCntFrm liegt, der
+ * durch das Grow() die Seite gewechselt hat. In so einem Fall ist es falsch, der
+ * folgenden Grow-Versuch durchzufuehren. Im Bugfall fuehrte dies sogar zur
+ * Endlosschleife.
+ * -----------------------------------*/
+ SwTwips nFrmHeight = (Frm().*fnRect->fnGetHeight)();
+ SwTwips nPrtHeight = (Prt().*fnRect->fnGetHeight)();
+
+ if( nRstHeight < nFrmHeight )
+ {
+ //Kann sein, dass ich die richtige Grosse habe, der Upper aber zu
+ //klein ist und der Upper noch Platz schaffen kann.
+ if( ( nRstHeight >= 0 || ( IsInFtn() && IsInSct() ) ) && !bHasToFit )
+ nRstHeight += GetUpper()->Grow( nFrmHeight - nRstHeight );
+ // In spaltigen Bereichen wollen wir moeglichst nicht zu gross werden, damit
+ // nicht ueber GetNextSctLeaf weitere Bereiche angelegt werden. Stattdessen
+ // schrumpfen wir und notieren bUndersized, damit FormatWidthCols die richtige
+ // Spaltengroesse ermitteln kann.
+ if ( nRstHeight < nFrmHeight )
+ {
+ if( bHasToFit || !IsMoveable() ||
+ ( IsInSct() && !FindSctFrm()->MoveAllowed(this) ) )
+ {
+ SetUndersized( sal_True );
+ Shrink( Min( ( nFrmHeight - nRstHeight), nPrtHeight ) );
+ }
+ else
+ SetUndersized( sal_False );
+ }
+ }
+ else if( nChgHeight )
+ {
+ if( nRstHeight - nFrmHeight < nChgHeight )
+ nChgHeight = nRstHeight - nFrmHeight;
+ if( nChgHeight )
+ Grow( nChgHeight );
+ }
+ }
+ else
+ Shrink( -nChgHght );
+
+ UNDO_SWAP( this )
+}
+
+/*************************************************************************
+ * SwTxtFrm::AdjustFollow()
+ *************************************************************************/
+
+/* AdjustFollow erwartet folgende Situation:
+ * Der SwTxtIter steht am unteren Ende des Masters, der Offset wird
+ * im Follow eingestellt.
+ * nOffset haelt den Offset im Textstring, ab dem der Master abschliesst
+ * und der Follow beginnt. Wenn er 0 ist, wird der FolgeFrame geloescht.
+ */
+
+void SwTxtFrm::_AdjustFollow( SwTxtFormatter &rLine,
+ const xub_StrLen nOffset, const xub_StrLen nEnd,
+ const sal_uInt8 nMode )
+{
+ SwFrmSwapper aSwapper( this, sal_False );
+
+ // Wir haben den Rest der Textmasse: alle Follows loeschen
+ // Sonderfall sind DummyPortions()
+ // - special cases are controlled by parameter <nMode>.
+ if( HasFollow() && !(nMode & 1) && nOffset == nEnd )
+ {
+ while( GetFollow() )
+ {
+ if( ((SwTxtFrm*)GetFollow())->IsLocked() )
+ {
+ OSL_FAIL( "+SwTxtFrm::JoinFrm: Follow ist locked." );
+ return;
+ }
+ JoinFrm();
+ }
+
+ return;
+ }
+
+ // Tanz auf dem Vulkan: Wir formatieren eben schnell noch einmal
+ // die letzte Zeile fuer das QuoVadis-Geraffel. Selbstverstaendlich
+ // kann sich dadurch auch der Offset verschieben:
+ const xub_StrLen nNewOfst = ( IsInFtn() && ( !GetIndNext() || HasFollow() ) ) ?
+ rLine.FormatQuoVadis(nOffset) : nOffset;
+
+ if( !(nMode & 1) )
+ {
+ // Wir klauen unseren Follows Textmasse, dabei kann es passieren,
+ // dass wir einige Follows Joinen muessen.
+ while( GetFollow() && GetFollow()->GetFollow() &&
+ nNewOfst >= GetFollow()->GetFollow()->GetOfst() )
+ {
+ JoinFrm();
+ }
+ }
+
+ // Der Ofst hat sich verschoben.
+ if( GetFollow() )
+ {
+#if OSL_DEBUG_LEVEL > 1
+ static sal_Bool bTest = sal_False;
+ if( !bTest || ( nMode & 1 ) )
+#endif
+ if ( nMode )
+ GetFollow()->ManipOfst( 0 );
+
+ if ( CalcFollow( nNewOfst ) ) // CalcFollow erst zum Schluss, dort erfolgt ein SetOfst
+ rLine.SetOnceMore( sal_True );
+ }
+}
+
+/*************************************************************************
+ * SwTxtFrm::JoinFrm()
+ *************************************************************************/
+
+SwCntntFrm *SwTxtFrm::JoinFrm()
+{
+ OSL_ENSURE( GetFollow(), "+SwTxtFrm::JoinFrm: no follow" );
+ SwTxtFrm *pFoll = GetFollow();
+
+ SwTxtFrm *pNxt = pFoll->GetFollow();
+
+ // Alle Fussnoten des zu zerstoerenden Follows werden auf uns
+ // umgehaengt.
+ xub_StrLen nStart = pFoll->GetOfst();
+ if ( pFoll->HasFtn() )
+ {
+ const SwpHints *pHints = pFoll->GetTxtNode()->GetpSwpHints();
+ if( pHints )
+ {
+ SwFtnBossFrm *pFtnBoss = 0;
+ SwFtnBossFrm *pEndBoss = 0;
+ for ( sal_uInt16 i = 0; i < pHints->Count(); ++i )
+ {
+ const SwTxtAttr *pHt = (*pHints)[i];
+ if( RES_TXTATR_FTN==pHt->Which() && *pHt->GetStart()>=nStart )
+ {
+ if( pHt->GetFtn().IsEndNote() )
+ {
+ if( !pEndBoss )
+ pEndBoss = pFoll->FindFtnBossFrm();
+ pEndBoss->ChangeFtnRef( pFoll, (SwTxtFtn*)pHt, this );
+ }
+ else
+ {
+ if( !pFtnBoss )
+ pFtnBoss = pFoll->FindFtnBossFrm( sal_True );
+ pFtnBoss->ChangeFtnRef( pFoll, (SwTxtFtn*)pHt, this );
+ }
+ SetFtn( sal_True );
+ }
+ }
+ }
+ }
+
+#if OSL_DEBUG_LEVEL > 1
+ else if ( pFoll->GetValidPrtAreaFlag() ||
+ pFoll->GetValidSizeFlag() )
+ {
+ pFoll->CalcFtnFlag();
+ OSL_ENSURE( !pFoll->HasFtn(), "Missing FtnFlag." );
+ }
+#endif
+
+ pFoll->MoveFlyInCnt( this, nStart, STRING_LEN );
+ pFoll->SetFtn( sal_False );
+ // --> OD 2005-12-01 #i27138#
+ // notify accessibility paragraphs objects about changed CONTENT_FLOWS_FROM/_TO relation.
+ // Relation CONTENT_FLOWS_FROM for current next paragraph will change
+ // and relation CONTENT_FLOWS_TO for current previous paragraph, which
+ // is <this>, will change.
+ {
+ ViewShell* pViewShell( pFoll->getRootFrm()->GetCurrShell() );
+ if ( pViewShell && pViewShell->GetLayout() &&
+ pViewShell->GetLayout()->IsAnyShellAccessible() )
+ {
+ pViewShell->InvalidateAccessibleParaFlowRelation(
+ dynamic_cast<SwTxtFrm*>(pFoll->FindNextCnt( true )),
+ this );
+ }
+ }
+ // <--
+ pFoll->Cut();
+ delete pFoll;
+ pFollow = pNxt;
+ return pNxt;
+}
+
+/*************************************************************************
+ * SwTxtFrm::SplitFrm()
+ *************************************************************************/
+
+SwCntntFrm *SwTxtFrm::SplitFrm( const xub_StrLen nTxtPos )
+{
+ SWAP_IF_SWAPPED( this )
+
+ // Durch das Paste wird ein Modify() an mich verschickt.
+ // Damit meine Daten nicht verschwinden, locke ich mich.
+ SwTxtFrmLocker aLock( this );
+ SwTxtFrm *pNew = (SwTxtFrm *)(GetTxtNode()->MakeFrm( this ));
+ pNew->bIsFollow = sal_True;
+
+ pNew->SetFollow( GetFollow() );
+ SetFollow( pNew );
+
+ pNew->Paste( GetUpper(), GetNext() );
+ // --> OD 2005-12-01 #i27138#
+ // notify accessibility paragraphs objects about changed CONTENT_FLOWS_FROM/_TO relation.
+ // Relation CONTENT_FLOWS_FROM for current next paragraph will change
+ // and relation CONTENT_FLOWS_TO for current previous paragraph, which
+ // is <this>, will change.
+ {
+ ViewShell* pViewShell( pNew->getRootFrm()->GetCurrShell() );
+ if ( pViewShell && pViewShell->GetLayout() &&
+ pViewShell->GetLayout()->IsAnyShellAccessible() )
+ {
+ pViewShell->InvalidateAccessibleParaFlowRelation(
+ dynamic_cast<SwTxtFrm*>(pNew->FindNextCnt( true )),
+ this );
+ }
+ }
+ // <--
+
+ // Wenn durch unsere Aktionen Fussnoten in pNew landen,
+ // so muessen sie umgemeldet werden.
+ if ( HasFtn() )
+ {
+ const SwpHints *pHints = GetTxtNode()->GetpSwpHints();
+ if( pHints )
+ {
+ SwFtnBossFrm *pFtnBoss = 0;
+ SwFtnBossFrm *pEndBoss = 0;
+ for ( sal_uInt16 i = 0; i < pHints->Count(); ++i )
+ {
+ const SwTxtAttr *pHt = (*pHints)[i];
+ if( RES_TXTATR_FTN==pHt->Which() && *pHt->GetStart()>=nTxtPos )
+ {
+ if( pHt->GetFtn().IsEndNote() )
+ {
+ if( !pEndBoss )
+ pEndBoss = FindFtnBossFrm();
+ pEndBoss->ChangeFtnRef( this, (SwTxtFtn*)pHt, pNew );
+ }
+ else
+ {
+ if( !pFtnBoss )
+ pFtnBoss = FindFtnBossFrm( sal_True );
+ pFtnBoss->ChangeFtnRef( this, (SwTxtFtn*)pHt, pNew );
+ }
+ pNew->SetFtn( sal_True );
+ }
+ }
+ }
+ }
+
+#if OSL_DEBUG_LEVEL > 1
+ else
+ {
+ CalcFtnFlag( nTxtPos-1 );
+ OSL_ENSURE( !HasFtn(), "Missing FtnFlag." );
+ }
+#endif
+
+ MoveFlyInCnt( pNew, nTxtPos, STRING_LEN );
+
+ // Kein SetOfst oder CalcFollow, weil gleich ohnehin ein AdjustFollow folgt.
+
+ pNew->ManipOfst( nTxtPos );
+
+ UNDO_SWAP( this )
+ return pNew;
+}
+
+
+/*************************************************************************
+ * virtual SwTxtFrm::SetOfst()
+ *************************************************************************/
+
+void SwTxtFrm::_SetOfst( const xub_StrLen nNewOfst )
+{
+ // Die Invalidierung unseres Follows ist nicht noetig.
+ // Wir sind ein Follow, werden gleich formatiert und
+ // rufen von dort aus das SetOfst() !
+ nOfst = nNewOfst;
+ SwParaPortion *pPara = GetPara();
+ if( pPara )
+ {
+ SwCharRange &rReformat = *(pPara->GetReformat());
+ rReformat.Start() = 0;
+ rReformat.Len() = GetTxt().Len();
+ *(pPara->GetDelta()) = rReformat.Len();
+ }
+ InvalidateSize();
+}
+
+/*************************************************************************
+ * SwTxtFrm::CalcPreps
+ *************************************************************************/
+
+sal_Bool SwTxtFrm::CalcPreps()
+{
+ OSL_ENSURE( ! IsVertical() || ! IsSwapped(), "SwTxtFrm::CalcPreps with swapped frame" );
+ SWRECTFN( this );
+
+ SwParaPortion *pPara = GetPara();
+ if ( !pPara )
+ return sal_False;
+ sal_Bool bPrep = pPara->IsPrep();
+ sal_Bool bPrepWidows = pPara->IsPrepWidows();
+ sal_Bool bPrepAdjust = pPara->IsPrepAdjust();
+ sal_Bool bPrepMustFit = pPara->IsPrepMustFit();
+ ResetPreps();
+
+ sal_Bool bRet = sal_False;
+ if( bPrep && !pPara->GetReformat()->Len() )
+ {
+ // PREP_WIDOWS bedeutet, dass im Follow die Orphans-Regel
+ // zuschlug.
+ // Es kann in unguenstigen Faellen vorkommen, dass auch ein
+ // PrepAdjust vorliegt (3680)!
+ if( bPrepWidows )
+ {
+ if( !GetFollow() )
+ {
+ OSL_ENSURE( GetFollow(), "+SwTxtFrm::CalcPreps: no credits" );
+ return sal_False;
+ }
+
+ // Wir muessen uns auf zwei Faelle einstellen:
+ // Wir konnten dem Follow noch ein paar Zeilen abgeben,
+ // -> dann muessen wir schrumpfen
+ // oder wir muessen auf die naechste Seite
+ // -> dann lassen wir unseren Frame zu gross werden.
+
+ SwTwips nChgHeight = GetParHeight();
+ if( nChgHeight >= (Prt().*fnRect->fnGetHeight)() )
+ {
+ if( bPrepMustFit )
+ {
+ GetFollow()->SetJustWidow( sal_True );
+ GetFollow()->Prepare( PREP_CLEAR );
+ }
+ else if ( bVert )
+ {
+ Frm().Width( Frm().Width() + Frm().Left() );
+ Prt().Width( Prt().Width() + Frm().Left() );
+ Frm().Left( 0 );
+ SetWidow( sal_True );
+ }
+ else
+ {
+ SwTwips nTmp = LONG_MAX - (Frm().Top()+10000);
+ SwTwips nDiff = nTmp - Frm().Height();
+ Frm().Height( nTmp );
+ Prt().Height( Prt().Height() + nDiff );
+ SetWidow( sal_True );
+ }
+ }
+ else
+ {
+ OSL_ENSURE( nChgHeight < (Prt().*fnRect->fnGetHeight)(),
+ "+SwTxtFrm::CalcPrep: wanna shrink" );
+
+ nChgHeight = (Prt().*fnRect->fnGetHeight)() - nChgHeight;
+
+ GetFollow()->SetJustWidow( sal_True );
+ GetFollow()->Prepare( PREP_CLEAR );
+ Shrink( nChgHeight );
+ SwRect &rRepaint = *(pPara->GetRepaint());
+
+ if ( bVert )
+ {
+ SwRect aRepaint( Frm().Pos() + Prt().Pos(), Prt().SSize() );
+ SwitchVerticalToHorizontal( aRepaint );
+ rRepaint.Chg( aRepaint.Pos(), aRepaint.SSize() );
+ }
+ else
+ rRepaint.Chg( Frm().Pos() + Prt().Pos(), Prt().SSize() );
+
+ if( 0 >= rRepaint.Width() )
+ rRepaint.Width(1);
+ }
+ bRet = sal_True;
+ }
+
+ else if ( bPrepAdjust )
+ {
+ if ( HasFtn() )
+ {
+ if( !CalcPrepFtnAdjust() )
+ {
+ if( bPrepMustFit )
+ {
+ SwTxtLineAccess aAccess( this );
+ aAccess.GetPara()->SetPrepMustFit( sal_True );
+ }
+ return sal_False;
+ }
+ }
+
+ SWAP_IF_NOT_SWAPPED( this )
+
+ SwTxtFormatInfo aInf( this );
+ SwTxtFormatter aLine( this, &aInf );
+
+ WidowsAndOrphans aFrmBreak( this );
+ // Egal was die Attribute meinen, bei MustFit wird
+ // der Absatz im Notfall trotzdem gesplittet...
+ if( bPrepMustFit )
+ {
+ aFrmBreak.SetKeep( sal_False );
+ aFrmBreak.ClrOrphLines();
+ }
+ // Bevor wir FormatAdjust aufrufen muessen wir dafuer
+ // sorgen, dass die Zeilen, die unten raushaengen
+ // auch tatsaechlich abgeschnitten werden.
+ // OD 2004-02-25 #i16128# - method renamed
+ sal_Bool bBreak = aFrmBreak.IsBreakNowWidAndOrp( aLine );
+ bRet = sal_True;
+ while( !bBreak && aLine.Next() )
+ {
+ // OD 2004-02-25 #i16128# - method renamed
+ bBreak = aFrmBreak.IsBreakNowWidAndOrp( aLine );
+ }
+ if( bBreak )
+ {
+ // Es gibt Komplikationen: wenn TruncLines gerufen wird,
+ // veraendern sich ploetzlich die Bedingungen in
+ // IsInside, so dass IsBreakNow andere Ergebnisse
+ // liefern kann. Aus diesem Grund wird rFrmBreak bekannt
+ // gegeben, dass da wo rLine steht, das Ende erreicht
+ // ist. Mal sehen, ob's klappt ...
+ aLine.TruncLines();
+ aFrmBreak.SetRstHeight( aLine );
+ FormatAdjust( aLine, aFrmBreak, aInf.GetTxt().Len(), aInf.IsStop() );
+ }
+ else
+ {
+ if( !GetFollow() )
+ {
+ FormatAdjust( aLine, aFrmBreak,
+ aInf.GetTxt().Len(), aInf.IsStop() );
+ }
+ else if ( !aFrmBreak.IsKeepAlways() )
+ {
+ // Siehe Bug: 2320
+ // Vor dem Master wird eine Zeile geloescht, der Follow
+ // koennte eine Zeile abgeben.
+ const SwCharRange aFollowRg( GetFollow()->GetOfst(), 1 );
+ *(pPara->GetReformat()) += aFollowRg;
+ // Es soll weitergehen!
+ bRet = sal_False;
+ }
+ }
+
+ UNDO_SWAP( this )
+ // Eine letzte Ueberpruefung, falls das FormatAdjust() nichts
+ // brachte, muessen wir amputieren.
+ if( bPrepMustFit )
+ {
+ const SwTwips nMust = (GetUpper()->*fnRect->fnGetPrtBottom)();
+ const SwTwips nIs = (Frm().*fnRect->fnGetBottom)();
+
+ if( bVert && nIs < nMust )
+ {
+ Shrink( nMust - nIs );
+ if( Prt().Width() < 0 )
+ Prt().Width( 0 );
+ SetUndersized( sal_True );
+ }
+ else if ( ! bVert && nIs > nMust )
+ {
+ Shrink( nIs - nMust );
+ if( Prt().Height() < 0 )
+ Prt().Height( 0 );
+ SetUndersized( sal_True );
+ }
+ }
+ }
+ }
+ pPara->SetPrepMustFit( bPrepMustFit );
+ return bRet;
+}
+
+
+/*************************************************************************
+ * SwTxtFrm::FormatAdjust()
+ *************************************************************************/
+
+// Hier werden die Fussnoten und "als Zeichen"-gebundenen Objekte umgehaengt
+#define CHG_OFFSET( pFrm, nNew )\
+ {\
+ if( pFrm->GetOfst() < nNew )\
+ pFrm->MoveFlyInCnt( this, 0, nNew );\
+ else if( pFrm->GetOfst() > nNew )\
+ MoveFlyInCnt( pFrm, nNew, STRING_LEN );\
+ }
+
+void SwTxtFrm::FormatAdjust( SwTxtFormatter &rLine,
+ WidowsAndOrphans &rFrmBreak,
+ const xub_StrLen nStrLen,
+ const sal_Bool bDummy )
+{
+ SWAP_IF_NOT_SWAPPED( this )
+
+ SwParaPortion *pPara = rLine.GetInfo().GetParaPortion();
+
+ xub_StrLen nEnd = rLine.GetStart();
+
+ sal_Bool bHasToFit = pPara->IsPrepMustFit();
+
+ // Das StopFlag wird durch Fussnoten gesetzt,
+ // die auf die naechste Seite wollen.
+ // OD, FME 2004-03-03 - call base class method <SwTxtFrmBreak::IsBreakNow(..)>
+ // instead of method <WidowsAndOrphans::IsBreakNow(..)> to get a break,
+ // even if due to widow rule no enough lines exists.
+ sal_uInt8 nNew = ( !GetFollow() &&
+ nEnd < nStrLen &&
+ ( rLine.IsStop() ||
+ ( bHasToFit
+ ? ( rLine.GetLineNr() > 1 &&
+ !rFrmBreak.IsInside( rLine ) )
+ : rFrmBreak.IsBreakNow( rLine ) ) ) )
+ ? 1 : 0;
+ if ( nNew )
+ SplitFrm( nEnd );
+
+ const SwFrm *pBodyFrm = (const SwFrm*)(FindBodyFrm());
+
+ const long nBodyHeight = pBodyFrm ? ( IsVertical() ?
+ pBodyFrm->Frm().Width() :
+ pBodyFrm->Frm().Height() ) : 0;
+
+ // Wenn die aktuellen Werte berechnet wurden, anzeigen, dass
+ // sie jetzt gueltig sind.
+ *(pPara->GetReformat()) = SwCharRange();
+ sal_Bool bDelta = *pPara->GetDelta() != 0;
+ *(pPara->GetDelta()) = 0;
+
+ if( rLine.IsStop() )
+ {
+ rLine.TruncLines( sal_True );
+ nNew = 1;
+ }
+
+ // FindBreak schneidet die letzte Zeile ab.
+ if( !rFrmBreak.FindBreak( this, rLine, bHasToFit ) )
+ {
+ // Wenn wir bis zum Ende durchformatiert haben, wird nEnd auf das Ende
+ // gesetzt. In AdjustFollow wird dadurch ggf. JoinFrm() ausgefuehrt.
+ // Ansonsten ist nEnd das Ende der letzten Zeile im Master.
+ xub_StrLen nOld = nEnd;
+ nEnd = rLine.GetEnd();
+ if( GetFollow() )
+ {
+ if( nNew && nOld < nEnd )
+ RemoveFtn( nOld, nEnd - nOld );
+ CHG_OFFSET( GetFollow(), nEnd )
+ if( !bDelta )
+ GetFollow()->ManipOfst( nEnd );
+ }
+ }
+ else
+ { // Wenn wir Zeilen abgeben, darf kein Join auf den Folows gerufen werden,
+ // im Gegenteil, es muss ggf. sogar ein Follow erzeugt werden.
+ // Dies muss auch geschehen, wenn die Textmasse komplett im Master
+ // bleibt, denn es k???nnte ja ein harter Zeilenumbruch noch eine weitere
+ // Zeile (ohne Textmassse) notwendig machen!
+ nEnd = rLine.GetEnd();
+ if( GetFollow() )
+ {
+ // OD 21.03.2003 #108121# - Another case for not joining the follow:
+ // Text frame has no content, but a numbering. Then, do *not* join.
+ // Example of this case: When an empty, but numbered paragraph
+ // at the end of page is completely displaced by a fly frame.
+ // Thus, the text frame introduced a follow by a
+ // <SwTxtFrm::SplitFrm(..)> - see below. The follow then shows
+ // the numbering and must stay.
+ if ( GetFollow()->GetOfst() != nEnd ||
+ GetFollow()->IsFieldFollow() ||
+ ( nStrLen == 0 && GetTxtNode()->GetNumRule())
+ )
+ {
+ nNew |= 3;
+ }
+ CHG_OFFSET( GetFollow(), nEnd )
+ GetFollow()->ManipOfst( nEnd );
+ }
+ else
+ {
+ // OD 21.03.2003 #108121# - Only split frame, if the frame contains
+ // content or contains no content, but has a numbering.
+ if ( nStrLen > 0 ||
+ ( nStrLen == 0 && GetTxtNode()->GetNumRule())
+ )
+ {
+ SplitFrm( nEnd );
+ nNew |= 3;
+ }
+ }
+ // Wenn sich die Resthoehe geaendert hat, z.B. durch RemoveFtn()
+ // dann muessen wir auffuellen, um Oszillationen zu vermeiden!
+ if( bDummy && pBodyFrm &&
+ nBodyHeight < ( IsVertical() ?
+ pBodyFrm->Frm().Width() :
+ pBodyFrm->Frm().Height() ) )
+ rLine.MakeDummyLine();
+ }
+
+ // In AdjustFrm() stellen wir uns selbst per Grow/Shrink ein,
+ // in AdjustFollow() stellen wir unseren FolgeFrame ein.
+
+ const SwTwips nDocPrtTop = Frm().Top() + Prt().Top();
+ const SwTwips nOldHeight = Prt().SSize().Height();
+ const SwTwips nChg = rLine.CalcBottomLine() - nDocPrtTop - nOldHeight;
+
+ // Vertical Formatting:
+ // The (rotated) repaint rectangle's x coordinate referes to the frame.
+ // If the frame grows (or shirks) the repaint rectangle cannot simply
+ // be rotated back after formatting, because we use the upper left point
+ // of the frame for rotation. This point changes when growing/shrinking.
+
+ //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin
+ if ( IsVertical() && !IsVertLR() && nChg )
+ {
+ SwRect &rRepaint = *(pPara->GetRepaint());
+ rRepaint.Left( rRepaint.Left() - nChg );
+ rRepaint.Width( rRepaint.Width() - nChg );
+ }
+
+ AdjustFrm( nChg, bHasToFit );
+
+ if( HasFollow() || IsInFtn() )
+ _AdjustFollow( rLine, nEnd, nStrLen, nNew );
+
+ pPara->SetPrepMustFit( sal_False );
+
+ UNDO_SWAP( this )
+}
+
+/*************************************************************************
+ * SwTxtFrm::FormatLine()
+ *************************************************************************/
+
+// bPrev zeigt an, ob Reformat.Start() wegen Prev() vorgezogen wurde.
+// Man weiss sonst nicht, ob man Repaint weiter einschraenken kann oder nicht.
+
+
+sal_Bool SwTxtFrm::FormatLine( SwTxtFormatter &rLine, const sal_Bool bPrev )
+{
+ OSL_ENSURE( ! IsVertical() || IsSwapped(),
+ "SwTxtFrm::FormatLine( rLine, bPrev) with unswapped frame" );
+ SwParaPortion *pPara = rLine.GetInfo().GetParaPortion();
+ const SwLineLayout *pOldCur = rLine.GetCurr();
+ const xub_StrLen nOldLen = pOldCur->GetLen();
+ const KSHORT nOldAscent = pOldCur->GetAscent();
+ const KSHORT nOldHeight = pOldCur->Height();
+ const SwTwips nOldWidth = pOldCur->Width() + pOldCur->GetHangingMargin();
+ const sal_Bool bOldHyph = pOldCur->IsEndHyph();
+ SwTwips nOldTop = 0;
+ SwTwips nOldBottom = 0;
+ if( rLine.GetCurr()->IsClipping() )
+ rLine.CalcUnclipped( nOldTop, nOldBottom );
+
+ const xub_StrLen nNewStart = rLine.FormatLine( rLine.GetStart() );
+
+ OSL_ENSURE( Frm().Pos().Y() + Prt().Pos().Y() == rLine.GetFirstPos(),
+ "SwTxtFrm::FormatLine: frame leaves orbit." );
+ OSL_ENSURE( rLine.GetCurr()->Height(),
+ "SwTxtFrm::FormatLine: line height is zero" );
+
+ // Das aktuelle Zeilenumbruchobjekt.
+ const SwLineLayout *pNew = rLine.GetCurr();
+
+ sal_Bool bUnChg = nOldLen == pNew->GetLen() &&
+ bOldHyph == pNew->IsEndHyph();
+ if ( bUnChg && !bPrev )
+ {
+ const long nWidthDiff = nOldWidth > pNew->Width()
+ ? nOldWidth - pNew->Width()
+ : pNew->Width() - nOldWidth;
+
+ // we only declare a line as unchanged, if its main values have not
+ // changed and it is not the last line (!paragraph end symbol!)
+ bUnChg = nOldHeight == pNew->Height() &&
+ nOldAscent == pNew->GetAscent() &&
+ nWidthDiff <= SLOPPY_TWIPS &&
+ pOldCur->GetNext();
+ }
+
+ // rRepaint wird berechnet:
+ const SwTwips nBottom = rLine.Y() + rLine.GetLineHeight();
+ SwRepaint &rRepaint = *(pPara->GetRepaint());
+ if( bUnChg && rRepaint.Top() == rLine.Y()
+ && (bPrev || nNewStart <= pPara->GetReformat()->Start())
+ && ( nNewStart < GetTxtNode()->GetTxt().Len() ) )
+ {
+ rRepaint.Top( nBottom );
+ rRepaint.Height( 0 );
+ }
+ else
+ {
+ if( nOldTop )
+ {
+ if( nOldTop < rRepaint.Top() )
+ rRepaint.Top( nOldTop );
+ if( !rLine.IsUnclipped() || nOldBottom > rRepaint.Bottom() )
+ {
+ rRepaint.Bottom( nOldBottom - 1 );
+ rLine.SetUnclipped( sal_True );
+ }
+ }
+ if( rLine.GetCurr()->IsClipping() && rLine.IsFlyInCntBase() )
+ {
+ SwTwips nTmpTop, nTmpBottom;
+ rLine.CalcUnclipped( nTmpTop, nTmpBottom );
+ if( nTmpTop < rRepaint.Top() )
+ rRepaint.Top( nTmpTop );
+ if( !rLine.IsUnclipped() || nTmpBottom > rRepaint.Bottom() )
+ {
+ rRepaint.Bottom( nTmpBottom - 1 );
+ rLine.SetUnclipped( sal_True );
+ }
+ }
+ else
+ {
+ if( !rLine.IsUnclipped() || nBottom > rRepaint.Bottom() )
+ {
+ rRepaint.Bottom( nBottom - 1 );
+ rLine.SetUnclipped( sal_False );
+ }
+ }
+ SwTwips nRght = Max( nOldWidth, pNew->Width() +
+ pNew->GetHangingMargin() );
+ ViewShell *pSh = getRootFrm()->GetCurrShell();
+ const SwViewOption *pOpt = pSh ? pSh->GetViewOptions() : 0;
+ if( pOpt && (pOpt->IsParagraph() || pOpt->IsLineBreak()) )
+ nRght += ( Max( nOldAscent, pNew->GetAscent() ) );
+ else
+ nRght += ( Max( nOldAscent, pNew->GetAscent() ) / 4);
+ nRght += rLine.GetLeftMargin();
+ if( rRepaint.GetOfst() || rRepaint.GetRightOfst() < nRght )
+ rRepaint.SetRightOfst( nRght );
+
+ // Finally we enlarge the repaint rectangle if we found an underscore
+ // within our line. 40 Twips should be enough
+ const sal_Bool bHasUnderscore =
+ ( rLine.GetInfo().GetUnderScorePos() < nNewStart );
+ if ( bHasUnderscore || rLine.GetCurr()->HasUnderscore() )
+ rRepaint.Bottom( rRepaint.Bottom() + 40 );
+
+ ((SwLineLayout*)rLine.GetCurr())->SetUnderscore( bHasUnderscore );
+ }
+ if( !bUnChg )
+ rLine.SetChanges();
+
+ // Die gute, alte nDelta-Berechnung:
+ *(pPara->GetDelta()) -= long(pNew->GetLen()) - long(nOldLen);
+
+ // Stop!
+ if( rLine.IsStop() )
+ return sal_False;
+
+ // Unbedingt noch eine Zeile
+ if( rLine.IsNewLine() )
+ return sal_True;
+
+ // bis zum Ende des Strings ?
+ if( nNewStart >= GetTxtNode()->GetTxt().Len() )
+ return sal_False;
+
+ if( rLine.GetInfo().IsShift() )
+ return sal_True;
+
+ // Ende des Reformats erreicht ?
+ const xub_StrLen nEnd = pPara->GetReformat()->Start() +
+ pPara->GetReformat()->Len();
+
+ if( nNewStart <= nEnd )
+ return sal_True;
+
+ return 0 != *(pPara->GetDelta());
+}
+
+/*************************************************************************
+ * SwTxtFrm::_Format()
+ *************************************************************************/
+
+void SwTxtFrm::_Format( SwTxtFormatter &rLine, SwTxtFormatInfo &rInf,
+ const sal_Bool bAdjust )
+{
+ OSL_ENSURE( ! IsVertical() || IsSwapped(),"SwTxtFrm::_Format with unswapped frame" );
+
+ SwParaPortion *pPara = rLine.GetInfo().GetParaPortion();
+ rLine.SetUnclipped( sal_False );
+
+ // Das war dem C30 zu kompliziert: aString( GetTxt() );
+ const XubString &rString = GetTxtNode()->GetTxt();
+ const xub_StrLen nStrLen = rString.Len();
+
+ SwCharRange &rReformat = *(pPara->GetReformat());
+ SwRepaint &rRepaint = *(pPara->GetRepaint());
+ SwRepaint *pFreeze = NULL;
+
+ // Aus Performancegruenden wird in Init() rReformat auf STRING_LEN gesetzt.
+ // Fuer diesen Fall wird rReformat angepasst.
+ if( rReformat.Len() > nStrLen )
+ rReformat.Len() = nStrLen;
+
+ // Optimiert:
+ xub_StrLen nEnd = rReformat.Start() + rReformat.Len();
+ if( nEnd > nStrLen )
+ {
+ rReformat.Len() = nStrLen - rReformat.Start();
+ nEnd = nStrLen;
+ }
+
+ SwTwips nOldBottom;
+ if( GetOfst() && !IsFollow() )
+ {
+ rLine.Bottom();
+ nOldBottom = rLine.Y();
+ rLine.Top();
+ }
+ else
+ nOldBottom = 0;
+ rLine.CharToLine( rReformat.Start() );
+
+ // Worte koennen durch Fortfall oder Einfuegen eines Space
+ // auf die Zeile vor der editierten hinausgezogen werden,
+ // deshalb muss diese ebenfalls formatiert werden.
+ // Optimierung: Wenn rReformat erst hinter dem ersten Wort der
+ // Zeile beginnt, so kann diese Zeile die vorige nicht mehr beeinflussen.
+ // AMA: Leider doch, Textgroessenaenderungen + FlyFrames, die Rueckwirkung
+ // kann im Extremfall mehrere Zeilen (Frames!!!) betreffen!
+
+ // --> FME 2005-04-18 #i46560#
+ // FME: Yes, consider this case: (word ) has to go to the next line
+ // because ) is a forbidden character at the beginning of a line although
+ // (word would still fit on the previous line. Adding text right in front
+ // of ) would not trigger a reformatting of the previous line. Adding 1
+ // to the result of FindBrk() does not solve the problem in all cases,
+ // nevertheless it should be sufficient.
+ // <--
+ sal_Bool bPrev = rLine.GetPrev() &&
+ ( FindBrk( rString, rLine.GetStart(), rReformat.Start() + 1 )
+ // --> FME 2005-04-18 #i46560#
+ + 1
+ // <--
+ >= rReformat.Start() ||
+ rLine.GetCurr()->IsRest() );
+ if( bPrev )
+ {
+ while( rLine.Prev() )
+ if( rLine.GetCurr()->GetLen() && !rLine.GetCurr()->IsRest() )
+ {
+ if( !rLine.GetStart() )
+ rLine.Top(); // damit NumDone nicht durcheinander kommt
+ break;
+ }
+ xub_StrLen nNew = rLine.GetStart() + rLine.GetLength();
+ if( nNew )
+ {
+ --nNew;
+ if( CH_BREAK == rString.GetChar( nNew ) )
+ {
+ ++nNew;
+ rLine.Next();
+ bPrev = sal_False;
+ }
+ }
+ rReformat.Len() += rReformat.Start() - nNew;
+ rReformat.Start() = nNew;
+ }
+
+ rRepaint.SetOfst( 0 );
+ rRepaint.SetRightOfst( 0 );
+ rRepaint.Chg( Frm().Pos() + Prt().Pos(), Prt().SSize() );
+ if( pPara->IsMargin() )
+ rRepaint.Width( rRepaint.Width() + pPara->GetHangingMargin() );
+ rRepaint.Top( rLine.Y() );
+ if( 0 >= rRepaint.Width() )
+ rRepaint.Width(1);
+ WidowsAndOrphans aFrmBreak( this, rInf.IsTest() ? 1 : 0 );
+
+ // rLine steht jetzt auf der ersten Zeile, die formatiert werden
+ // muss. Das Flag bFirst sorgt dafuer, dass nicht Next() gerufen wird.
+ // Das ganze sieht verdreht aus, aber es muss sichergestellt werden,
+ // dass bei IsBreakNow rLine auf der Zeile zum stehen kommt, die
+ // nicht mehr passt.
+ sal_Bool bFirst = sal_True;
+ sal_Bool bFormat = sal_True;
+
+ // 5383: Das CharToLine() kann uns auch in den roten Bereich fuehren.
+ // In diesem Fall muessen wir zurueckwandern, bis die Zeile, die
+ // nicht mehr passt in rLine eingestellt ist. Ansonsten geht Textmasse
+ // verloren, weil der Ofst im Follow falsch eingestellt wird.
+
+ // OD 2004-02-25 #i16128# - method renamed
+ sal_Bool bBreak = ( !pPara->IsPrepMustFit() || rLine.GetLineNr() > 1 )
+ && aFrmBreak.IsBreakNowWidAndOrp( rLine );
+ if( bBreak )
+ {
+ sal_Bool bPrevDone = 0 != rLine.Prev();
+ // OD 2004-02-25 #i16128# - method renamed
+ while( bPrevDone && aFrmBreak.IsBreakNowWidAndOrp(rLine) )
+ bPrevDone = 0 != rLine.Prev();
+ if( bPrevDone )
+ {
+ aFrmBreak.SetKeep( sal_False );
+ rLine.Next();
+ }
+ rLine.TruncLines();
+
+ // auf Nummer sicher:
+ // OD 2004-02-25 #i16128# - method renamed
+ bBreak = aFrmBreak.IsBreakNowWidAndOrp(rLine) &&
+ ( !pPara->IsPrepMustFit() || rLine.GetLineNr() > 1 );
+ }
+
+ /* Bedeutung der folgenden Flags:
+ Ist das Watch(End/Mid)Hyph-Flag gesetzt, so muss formatiert werden, wenn
+ eine Trennung am (Zeilenende/Fly) vorliegt, sofern MaxHyph erreicht ist.
+ Das Jump(End/Mid)Flag bedeutet, dass die naechste Zeile, bei der keine
+ Trennung (Zeilenende/Fly) vorliegt, formatiert werden muss, da jetzt
+ umgebrochen werden koennte, was vorher moeglicherweise durch MaxHyph
+ verboten war.
+ Watch(End/Mid)Hyph wird gesetzt, wenn die letzte formatierte Zeile eine
+ Trennstelle erhalten hat, vorher aber keine hatte,
+ Jump(End/Mid)Hyph, wenn eine Trennstelle verschwindet.
+ */
+ sal_Bool bJumpEndHyph = sal_False,
+ bWatchEndHyph = sal_False,
+ bJumpMidHyph = sal_False,
+ bWatchMidHyph = sal_False;
+
+ const SwAttrSet& rAttrSet = GetTxtNode()->GetSwAttrSet();
+ sal_Bool bMaxHyph = ( 0 !=
+ ( rInf.MaxHyph() = rAttrSet.GetHyphenZone().GetMaxHyphens() ) );
+ if ( bMaxHyph )
+ rLine.InitCntHyph();
+
+ if( IsFollow() && IsFieldFollow() && rLine.GetStart() == GetOfst() )
+ {
+ const SwLineLayout* pLine;
+ {
+ SwTxtFrm *pMaster = FindMaster();
+ OSL_ENSURE( pMaster, "SwTxtFrm::Format: homeless follow" );
+ if( !pMaster->HasPara() )
+ pMaster->GetFormatted();
+ SwTxtSizeInfo aInf( pMaster );
+ SwTxtIter aMasterLine( pMaster, &aInf );
+ aMasterLine.Bottom();
+ pLine = aMasterLine.GetCurr();
+ }
+ SwLinePortion* pRest =
+ rLine.MakeRestPortion( pLine, GetOfst() );
+ if( pRest )
+ rInf.SetRest( pRest );
+ else
+ SetFieldFollow( sal_False );
+ }
+
+ /* Zum Abbruchkriterium:
+ * Um zu erkennen, dass eine Zeile nicht mehr auf die Seite passt,
+ * muss sie formatiert werden. Dieser Ueberhang wird z.B. in AdjustFollow
+ * wieder entfernt.
+ * Eine weitere Komplikation: wenn wir der Master sind, so muessen
+ * wir die Zeilen durchgehen, da es ja sein kann, dass eine Zeile
+ * vom Follow in den Master rutschen kann.
+ */
+ do
+ {
+ if( bFirst )
+ bFirst = sal_False;
+ else
+ {
+ if ( bMaxHyph )
+ {
+ if ( rLine.GetCurr()->IsEndHyph() )
+ rLine.CntEndHyph()++;
+ else
+ rLine.CntEndHyph() = 0;
+ if ( rLine.GetCurr()->IsMidHyph() )
+ rLine.CntMidHyph()++;
+ else
+ rLine.CntMidHyph() = 0;
+ }
+ if( !rLine.Next() )
+ {
+ if( !bFormat )
+ {
+ SwLinePortion* pRest =
+ rLine.MakeRestPortion( rLine.GetCurr(), rLine.GetEnd() );
+ if( pRest )
+ rInf.SetRest( pRest );
+ }
+ rLine.Insert( new SwLineLayout() );
+ rLine.Next();
+ bFormat = sal_True;
+ }
+ }
+ if ( !bFormat && bMaxHyph &&
+ (bWatchEndHyph || bJumpEndHyph || bWatchMidHyph || bJumpMidHyph) )
+ {
+ if ( rLine.GetCurr()->IsEndHyph() )
+ {
+ if ( bWatchEndHyph )
+ bFormat = ( rLine.CntEndHyph() == rInf.MaxHyph() );
+ }
+ else
+ {
+ bFormat = bJumpEndHyph;
+ bWatchEndHyph = sal_False;
+ bJumpEndHyph = sal_False;
+ }
+ if ( rLine.GetCurr()->IsMidHyph() )
+ {
+ if ( bWatchMidHyph && !bFormat )
+ bFormat = ( rLine.CntEndHyph() == rInf.MaxHyph() );
+ }
+ else
+ {
+ bFormat = bFormat || bJumpMidHyph;
+ bWatchMidHyph = sal_False;
+ bJumpMidHyph = sal_False;
+ }
+ }
+ if( bFormat )
+ {
+ sal_Bool bOldEndHyph = rLine.GetCurr()->IsEndHyph();
+ sal_Bool bOldMidHyph = rLine.GetCurr()->IsMidHyph();
+ bFormat = FormatLine( rLine, bPrev );
+ //9334: Es kann nur ein bPrev geben... (???)
+ bPrev = sal_False;
+ if ( bMaxHyph )
+ {
+ if ( rLine.GetCurr()->IsEndHyph() != bOldEndHyph )
+ {
+ bWatchEndHyph = !bOldEndHyph;
+ bJumpEndHyph = bOldEndHyph;
+ }
+ if ( rLine.GetCurr()->IsMidHyph() != bOldMidHyph )
+ {
+ bWatchMidHyph = !bOldMidHyph;
+ bJumpMidHyph = bOldMidHyph;
+ }
+ }
+ }
+
+ if( !rInf.IsNewLine() )
+ {
+ if( !bFormat )
+ bFormat = 0 != rInf.GetRest();
+ if( rInf.IsStop() || rInf.GetIdx() >= nStrLen )
+ break;
+ if( !bFormat && ( !bMaxHyph || ( !bWatchEndHyph &&
+ !bJumpEndHyph && !bWatchMidHyph && !bJumpMidHyph ) ) )
+ {
+ if( GetFollow() )
+ {
+ while( rLine.Next() )
+ ; //Nothing
+ pFreeze = new SwRepaint( rRepaint ); // to minimize painting
+ }
+ else
+ break;
+ }
+ }
+ // OD 2004-02-25 #i16128# - method renamed
+ bBreak = aFrmBreak.IsBreakNowWidAndOrp(rLine);
+ }while( !bBreak );
+
+ if( pFreeze )
+ {
+ rRepaint = *pFreeze;
+ delete pFreeze;
+ }
+
+ if( !rLine.IsStop() )
+ {
+ // Wurde aller Text formatiert und gibt es noch weitere
+ // Zeilenobjekte, dann sind diese jetzt ueberfluessig,
+ // weil der Text kuerzer geworden ist.
+ if( rLine.GetStart() + rLine.GetLength() >= nStrLen &&
+ rLine.GetCurr()->GetNext() )
+ {
+ rLine.TruncLines();
+ rLine.SetTruncLines( sal_True );
+ }
+ }
+
+ if( !rInf.IsTest() )
+ {
+ // Bei OnceMore lohnt sich kein FormatAdjust
+ if( bAdjust || !rLine.GetDropFmt() || !rLine.CalcOnceMore() )
+ {
+ FormatAdjust( rLine, aFrmBreak, nStrLen, rInf.IsStop() );
+ }
+ if( rRepaint.HasArea() )
+ SetRepaint();
+ rLine.SetTruncLines( sal_False );
+ if( nOldBottom ) // Bei "gescollten" Absaetzen wird
+ { // noch ueberprueft, ob durch Schrumpfen
+ rLine.Bottom(); // das Scrolling ueberfluessig wurde.
+ SwTwips nNewBottom = rLine.Y();
+ if( nNewBottom < nOldBottom )
+ _SetOfst( 0 );
+ }
+ }
+}
+
+/*************************************************************************
+ * SwTxtFrm::Format()
+ *************************************************************************/
+
+void SwTxtFrm::FormatOnceMore( SwTxtFormatter &rLine, SwTxtFormatInfo &rInf )
+{
+ OSL_ENSURE( ! IsVertical() || IsSwapped(),
+ "A frame is not swapped in SwTxtFrm::FormatOnceMore" );
+
+ SwParaPortion *pPara = rLine.GetInfo().GetParaPortion();
+ if( !pPara )
+ return;
+
+ // ggf gegen pPara
+ KSHORT nOld = ((const SwTxtMargin&)rLine).GetDropHeight();
+ sal_Bool bShrink = sal_False,
+ bGrow = sal_False,
+ bGoOn = rLine.IsOnceMore();
+ sal_uInt8 nGo = 0;
+ while( bGoOn )
+ {
+ ++nGo;
+ rInf.Init();
+ rLine.Top();
+ if( !rLine.GetDropFmt() )
+ rLine.SetOnceMore( sal_False );
+ SwCharRange aRange( 0, rInf.GetTxt().Len() );
+ *(pPara->GetReformat()) = aRange;
+ _Format( rLine, rInf );
+
+ bGoOn = rLine.IsOnceMore();
+ if( bGoOn )
+ {
+ const KSHORT nNew = ((const SwTxtMargin&)rLine).GetDropHeight();
+ if( nOld == nNew )
+ bGoOn = sal_False;
+ else
+ {
+ if( nOld > nNew )
+ bShrink = sal_True;
+ else
+ bGrow = sal_True;
+
+ if( bShrink == bGrow || 5 < nGo )
+ bGoOn = sal_False;
+
+ nOld = nNew;
+ }
+
+ // 6107: Wenn was schief ging, muss noch einmal formatiert werden.
+ if( !bGoOn )
+ {
+ rInf.CtorInitTxtFormatInfo( this );
+ rLine.CtorInitTxtFormatter( this, &rInf );
+ rLine.SetDropLines( 1 );
+ rLine.CalcDropHeight( 1 );
+ SwCharRange aTmpRange( 0, rInf.GetTxt().Len() );
+ *(pPara->GetReformat()) = aTmpRange;
+ _Format( rLine, rInf, sal_True );
+ // 8047: Wir painten alles...
+ SetCompletePaint();
+ }
+ }
+ }
+}
+
+/*************************************************************************
+ * SwTxtFrm::_Format()
+ *************************************************************************/
+
+
+void SwTxtFrm::_Format( SwParaPortion *pPara )
+{
+ const xub_StrLen nStrLen = GetTxt().Len();
+
+ if ( !nStrLen )
+ {
+ // Leere Zeilen werden nicht lange gequaelt:
+ // pPara wird blank geputzt
+ // entspricht *pPara = SwParaPortion;
+ sal_Bool bMustFit = pPara->IsPrepMustFit();
+ pPara->Truncate();
+ pPara->FormatReset();
+ if( pBlink && pPara->IsBlinking() )
+ pBlink->Delete( pPara );
+
+ // delete pSpaceAdd und pKanaComp
+ pPara->FinishSpaceAdd();
+ pPara->FinishKanaComp();
+ pPara->ResetFlags();
+ pPara->SetPrepMustFit( bMustFit );
+ }
+
+ OSL_ENSURE( ! IsSwapped(), "A frame is swapped before _Format" );
+
+ if ( IsVertical() )
+ SwapWidthAndHeight();
+
+ SwTxtFormatInfo aInf( this );
+ SwTxtFormatter aLine( this, &aInf );
+
+ // OD 2004-01-15 #110582#
+ HideAndShowObjects();
+
+ _Format( aLine, aInf );
+
+ if( aLine.IsOnceMore() )
+ FormatOnceMore( aLine, aInf );
+
+ if ( IsVertical() )
+ SwapWidthAndHeight();
+
+ OSL_ENSURE( ! IsSwapped(), "A frame is swapped after _Format" );
+
+ if( 1 < aLine.GetDropLines() )
+ {
+ if( SVX_ADJUST_LEFT != aLine.GetAdjust() &&
+ SVX_ADJUST_BLOCK != aLine.GetAdjust() )
+ {
+ aLine.CalcDropAdjust();
+ aLine.SetPaintDrop( sal_True );
+ }
+
+ if( aLine.IsPaintDrop() )
+ {
+ aLine.CalcDropRepaint();
+ aLine.SetPaintDrop( sal_False );
+ }
+ }
+}
+
+/*************************************************************************
+ * SwTxtFrm::Format()
+ *************************************************************************/
+
+/*
+ * Format berechnet die Groesse des Textframes und ruft, wenn
+ * diese feststeht, Shrink() oder Grow(), um die Framegroesse dem
+ * evtl. veraenderten Platzbedarf anzupassen.
+ */
+
+void SwTxtFrm::Format( const SwBorderAttrs * )
+{
+#if OSL_DEBUG_LEVEL > 1
+ const XubString aXXX = GetTxtNode()->GetTxt();
+ const SwTwips nDbgY = Frm().Top();
+ (void)nDbgY;
+ const SwPageFrm *pDbgPage = FindPageFrm();
+ const MSHORT nDbgPageNr = pDbgPage->GetPhyPageNum();
+ (void)nDbgPageNr;
+ // Um zu gucken, ob es einen Ftn-Bereich gibt.
+ const SwFrm *pDbgFtnCont = (const SwFrm*)(FindPageFrm()->FindFtnCont());
+ (void)pDbgFtnCont;
+
+ // nStopAt laesst sich vom CV bearbeiten.
+ static MSHORT nStopAt = 0;
+ if( nStopAt == GetFrmId() )
+ {
+ int i = GetFrmId();
+ (void)i;
+ }
+#endif
+
+ SWRECTFN( this )
+
+ CalcAdditionalFirstLineOffset();
+
+ // Vom Berichtsautopiloten oder ueber die BASIC-Schnittstelle kommen
+ // gelegentlich TxtFrms mit einer Breite <=0.
+ if( (Prt().*fnRect->fnGetWidth)() <= 0 )
+ {
+ // Wenn MustFit gesetzt ist, schrumpfen wir ggf. auf die Unterkante
+ // des Uppers, ansonsten nehmen wir einfach eine Standardgroesse
+ // von 12 Pt. ein (240 Twip).
+ SwTxtLineAccess aAccess( this );
+ long nFrmHeight = (Frm().*fnRect->fnGetHeight)();
+ if( aAccess.GetPara()->IsPrepMustFit() )
+ {
+ const SwTwips nLimit = (GetUpper()->*fnRect->fnGetPrtBottom)();
+ const SwTwips nDiff = - (Frm().*fnRect->fnBottomDist)( nLimit );
+ if( nDiff > 0 )
+ Shrink( nDiff );
+ }
+ else if( 240 < nFrmHeight )
+ Shrink( nFrmHeight - 240 );
+ else if( 240 > nFrmHeight )
+ Grow( 240 - nFrmHeight );
+ nFrmHeight = (Frm().*fnRect->fnGetHeight)();
+
+ long nTop = (this->*fnRect->fnGetTopMargin)();
+ if( nTop > nFrmHeight )
+ (this->*fnRect->fnSetYMargins)( nFrmHeight, 0 );
+ else if( (Prt().*fnRect->fnGetHeight)() < 0 )
+ (Prt().*fnRect->fnSetHeight)( 0 );
+ return;
+ }
+
+ const xub_StrLen nStrLen = GetTxtNode()->GetTxt().Len();
+ if ( nStrLen || !FormatEmpty() )
+ {
+
+ SetEmpty( sal_False );
+ // Um nicht durch verschachtelte Formats irritiert zu werden.
+ FormatLevel aLevel;
+ if( 12 == aLevel.GetLevel() )
+ return;
+
+ // Die Formatinformationen duerfen u.U. nicht veraendert werden.
+ if( IsLocked() )
+ return;
+
+ // 8708: Vorsicht, das Format() kann auch durch GetFormatted()
+ // angestossen werden.
+ if( IsHiddenNow() )
+ {
+ long nPrtHeight = (Prt().*fnRect->fnGetHeight)();
+ if( nPrtHeight )
+ {
+ HideHidden();
+ Shrink( nPrtHeight );
+ }
+ else
+ {
+ // OD 2004-01-20 #110582# - assure that objects anchored
+ // at paragraph resp. at/as character inside paragraph
+ // are hidden.
+ HideAndShowObjects();
+ }
+ ChgThisLines();
+ return;
+ }
+
+ // Waehrend wir formatieren, wollen wir nicht gestoert werden.
+ SwTxtFrmLocker aLock(this);
+ SwTxtLineAccess aAccess( this );
+ const sal_Bool bNew = !aAccess.SwTxtLineAccess::IsAvailable();
+ const sal_Bool bSetOfst = ( GetOfst() && GetOfst() > GetTxtNode()->GetTxt().Len() );
+
+ if( CalcPreps() )
+ ; // nothing
+ // Wir returnen, wenn schon formatiert wurde, nicht aber, wenn
+ // der TxtFrm gerade erzeugt wurde und ueberhaupt keine Format-
+ // informationen vorliegen.
+ else if( !bNew && !aAccess.GetPara()->GetReformat()->Len() )
+ {
+ if( GetTxtNode()->GetSwAttrSet().GetRegister().GetValue() )
+ {
+ aAccess.GetPara()->SetPrepAdjust( sal_True );
+ aAccess.GetPara()->SetPrep( sal_True );
+ CalcPreps();
+ }
+ SetWidow( sal_False );
+ }
+ else if( bSetOfst && IsFollow() )
+ {
+ SwTxtFrm *pMaster = FindMaster();
+ OSL_ENSURE( pMaster, "SwTxtFrm::Format: homeless follow" );
+ if( pMaster )
+ pMaster->Prepare( PREP_FOLLOW_FOLLOWS );
+ SwTwips nMaxY = (GetUpper()->*fnRect->fnGetPrtBottom)();
+ if( (Frm().*fnRect->fnOverStep)( nMaxY ) )
+ (this->*fnRect->fnSetLimit)( nMaxY );
+ else if( (Frm().*fnRect->fnBottomDist)( nMaxY ) < 0 )
+ (Frm().*fnRect->fnAddBottom)( -(Frm().*fnRect->fnGetHeight)() );
+ }
+ else
+ {
+ // bSetOfst here means that we have the "red arrow situation"
+ if ( bSetOfst )
+ _SetOfst( 0 );
+
+ const sal_Bool bOrphan = IsWidow();
+ const SwFtnBossFrm* pFtnBoss = HasFtn() ? FindFtnBossFrm() : 0;
+ SwTwips nFtnHeight = 0;
+ if( pFtnBoss )
+ {
+ const SwFtnContFrm* pCont = pFtnBoss->FindFtnCont();
+ nFtnHeight = pCont ? (pCont->Frm().*fnRect->fnGetHeight)() : 0;
+ }
+ do
+ {
+ _Format( aAccess.GetPara() );
+ if( pFtnBoss && nFtnHeight )
+ {
+ const SwFtnContFrm* pCont = pFtnBoss->FindFtnCont();
+ SwTwips nNewHeight = pCont ? (pCont->Frm().*fnRect->fnGetHeight)() : 0;
+ // If we lost some footnotes, we may have more space
+ // for our main text, so we have to format again ...
+ if( nNewHeight < nFtnHeight )
+ nFtnHeight = nNewHeight;
+ else
+ break;
+ }
+ else
+ break;
+ } while ( pFtnBoss );
+ if( bOrphan )
+ {
+ ValidateFrm();
+ SetWidow( sal_False );
+ }
+ }
+ if( IsEmptyMaster() )
+ {
+ SwFrm* pPre = GetPrev();
+ if( pPre &&
+ // --> FME 2004-07-22 #i10826# It's the first, it cannot keep!
+ pPre->GetIndPrev() &&
+ // <--
+ pPre->GetAttrSet()->GetKeep().GetValue() )
+ {
+ pPre->InvalidatePos();
+ }
+ }
+ }
+
+ ChgThisLines();
+
+ // the PrepMustFit should not survive a Format operation
+ SwParaPortion *pPara = GetPara();
+ if ( pPara )
+ pPara->SetPrepMustFit( sal_False );
+
+#if OSL_DEBUG_LEVEL > 1
+ // Hier ein Instrumentarium, um ungewoehnlichen Master/Follow-Kombinationen,
+ // insbesondere bei Fussnoten, auf die Schliche zu kommen
+ if( IsFollow() || GetFollow() )
+ {
+ SwTxtFrm *pTmpFrm = IsFollow() ? FindMaster() : this;
+ const SwPageFrm *pTmpPage = pTmpFrm->FindPageFrm();
+ MSHORT nPgNr = pTmpPage->GetPhyPageNum();
+ MSHORT nLast;
+ MSHORT nDummy = 0; // nur zum Breakpoint setzen
+ while( pTmpFrm->GetFollow() )
+ {
+ pTmpFrm = pTmpFrm->GetFollow();
+ nLast = nPgNr;
+ pTmpPage = pTmpFrm->FindPageFrm();
+ nPgNr = pTmpPage->GetPhyPageNum();
+ if( nLast > nPgNr )
+ ++nDummy; // schon fast eine Assertion wert
+ else if( nLast == nPgNr )
+ ++nDummy; // bei Spalten voellig normal, aber sonst!?
+ else if( nLast < nPgNr - 1 )
+ ++nDummy; // kann schon mal temporaer vorkommen
+ }
+ }
+#endif
+
+ CalcBaseOfstForFly();
+ // OD 2004-03-17 #i11860#
+ _CalcHeightOfLastLine();
+}
+
+/*************************************************************************
+ * SwTxtFrm::FormatQuick()
+ *
+ * bForceQuickFormat is set if GetFormatted() has been called during the
+ * painting process. Actually I cannot imagine a situation which requires
+ * a full formatting of the paragraph during painting, on the other hand
+ * a full formatting can cause the invalidation of other layout frames,
+ * e.g., if there are footnotes in this paragraph, and invalid layout
+ * frames will not calculated during the painting. So I actually want to
+ * avoid a formatting during painting, but since I'm a coward, I'll only
+ * force the quick formatting in the situation of issue i29062.
+ *************************************************************************/
+
+sal_Bool SwTxtFrm::FormatQuick( bool bForceQuickFormat )
+{
+ OSL_ENSURE( ! IsVertical() || ! IsSwapped(),
+ "SwTxtFrm::FormatQuick with swapped frame" );
+
+#if OSL_DEBUG_LEVEL > 1
+ const XubString aXXX = GetTxtNode()->GetTxt();
+ const SwTwips nDbgY = Frm().Top();
+ (void)nDbgY;
+ // nStopAt laesst sich vom CV bearbeiten.
+ static MSHORT nStopAt = 0;
+ if( nStopAt == GetFrmId() )
+ {
+ int i = GetFrmId();
+ (void)i;
+ }
+#endif
+
+ if( IsEmpty() && FormatEmpty() )
+ return sal_True;
+
+ // Wir sind sehr waehlerisch:
+ if( HasPara() || IsWidow() || IsLocked()
+ || !GetValidSizeFlag() ||
+ ( ( IsVertical() ? Prt().Width() : Prt().Height() ) && IsHiddenNow() ) )
+ return sal_False;
+
+ SwTxtLineAccess aAccess( this );
+ SwParaPortion *pPara = aAccess.GetPara();
+ if( !pPara )
+ return sal_False;
+
+ SwFrmSwapper aSwapper( this, sal_True );
+
+ SwTxtFrmLocker aLock(this);
+ SwTxtFormatInfo aInf( this, sal_False, sal_True );
+ if( 0 != aInf.MaxHyph() ) // 27483: MaxHyphen beachten!
+ return sal_False;
+
+ SwTxtFormatter aLine( this, &aInf );
+
+ // DropCaps sind zu kompliziert...
+ if( aLine.GetDropFmt() )
+ return sal_False;
+
+ xub_StrLen nStart = GetOfst();
+ const xub_StrLen nEnd = GetFollow()
+ ? GetFollow()->GetOfst() : aInf.GetTxt().Len();
+ do
+ {
+ nStart = aLine.FormatLine( nStart );
+ if( aInf.IsNewLine() || (!aInf.IsStop() && nStart < nEnd) )
+ aLine.Insert( new SwLineLayout() );
+ } while( aLine.Next() );
+
+ // Last exit: die Hoehen muessen uebereinstimmen.
+ Point aTopLeft( Frm().Pos() );
+ aTopLeft += Prt().Pos();
+ const SwTwips nNewHeight = aLine.Y() + aLine.GetLineHeight();
+ const SwTwips nOldHeight = aTopLeft.Y() + Prt().Height();
+
+ if( !bForceQuickFormat && nNewHeight != nOldHeight && !IsUndersized() )
+ {
+ // Achtung: Durch FormatLevel==12 kann diese Situation auftreten, don't panic!
+ const xub_StrLen nStrt = GetOfst();
+ _InvalidateRange( SwCharRange( nStrt, nEnd - nStrt) );
+ return sal_False;
+ }
+
+ if( pFollow && nStart != ((SwTxtFrm*)pFollow)->GetOfst() )
+ return sal_False; // kann z.B. durch Orphans auftreten (35083,35081)
+
+ // Geschafft, wir sind durch ...
+
+ // Repaint setzen
+ pPara->GetRepaint()->Pos( aTopLeft );
+ pPara->GetRepaint()->SSize( Prt().SSize() );
+
+ // Reformat loeschen
+ *(pPara->GetReformat()) = SwCharRange();
+ *(pPara->GetDelta()) = 0;
+
+ return sal_True;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/text/frminf.cxx b/sw/source/core/text/frminf.cxx
new file mode 100644
index 000000000000..530c93a51825
--- /dev/null
+++ b/sw/source/core/text/frminf.cxx
@@ -0,0 +1,378 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+
+#include <pam.hxx> // GetSpaces
+#include <frminf.hxx> // SwTxtFrminfo
+#include <itrtxt.hxx> // SwTxtMargin
+
+/*************************************************************************
+ * SwTxtMargin::GetTxtStart()
+ *************************************************************************/
+
+xub_StrLen SwTxtMargin::GetTxtStart() const
+{
+ const XubString &rTxt = GetInfo().GetTxt();
+ const xub_StrLen nTmpPos = nStart;
+ const xub_StrLen nEnd = nTmpPos + pCurr->GetLen();
+ xub_StrLen i;
+
+ for( i = nTmpPos; i < nEnd; ++i )
+ {
+ const xub_Unicode aChar = rTxt.GetChar( i );
+ if( CH_TAB != aChar && ' ' != aChar )
+ return i;
+ }
+ return i;
+}
+
+/*************************************************************************
+ * SwTxtMargin::GetTxtEnd()
+ *************************************************************************/
+
+xub_StrLen SwTxtMargin::GetTxtEnd() const
+{
+ const XubString &rTxt = GetInfo().GetTxt();
+ const xub_StrLen nTmpPos = nStart;
+ const xub_StrLen nEnd = nTmpPos + pCurr->GetLen();
+ long i;
+ for( i = nEnd - 1; i >= nTmpPos; --i )
+ {
+ xub_Unicode aChar = rTxt.GetChar( static_cast<xub_StrLen>(i) );
+ if( CH_TAB != aChar && CH_BREAK != aChar && ' ' != aChar )
+ return static_cast<xub_StrLen>(i + 1);
+ }
+ return static_cast<xub_StrLen>(i + 1);
+}
+
+/*************************************************************************
+ * SwTxtFrmInfo::IsOneLine()
+ *************************************************************************/
+
+// Passt der Absatz in eine Zeile?
+sal_Bool SwTxtFrmInfo::IsOneLine() const
+{
+ const SwLineLayout *pLay = pFrm->GetPara();
+ if( !pLay )
+ return sal_False;
+ else
+ {
+ // 6575: bei Follows natuerlich sal_False
+ if( pFrm->GetFollow() )
+ return sal_False;
+ pLay = pLay->GetNext();
+ while( pLay )
+ {
+ if( pLay->GetLen() )
+ return sal_False;
+ pLay = pLay->GetNext();
+ }
+ return sal_True;
+ }
+}
+
+/*************************************************************************
+ * SwTxtFrmInfo::IsFilled()
+ *************************************************************************/
+
+// Ist die Zeile zu X% gefuellt?
+sal_Bool SwTxtFrmInfo::IsFilled( const sal_uInt8 nPercent ) const
+{
+ const SwLineLayout *pLay = pFrm->GetPara();
+ if( !pLay )
+ return sal_False;
+ else
+ {
+ long nWidth = pFrm->Prt().Width();
+ nWidth *= nPercent;
+ nWidth /= 100;
+ return KSHORT(nWidth) <= pLay->Width();
+ }
+}
+
+/*************************************************************************
+ * SwTxtFrmInfo::GetLineStart()
+ *************************************************************************/
+
+// Wo beginnt der Text (ohne whitespaces)? ( Dokument global )
+SwTwips SwTxtFrmInfo::GetLineStart( const SwTxtCursor &rLine ) const
+{
+ xub_StrLen nTxtStart = rLine.GetTxtStart();
+ SwTwips nStart;
+ if( rLine.GetStart() == nTxtStart )
+ nStart = rLine.GetLineStart();
+ else
+ {
+ SwRect aRect;
+ if( ((SwTxtCursor&)rLine).GetCharRect( &aRect, nTxtStart ) )
+ nStart = aRect.Left();
+ else
+ nStart = rLine.GetLineStart();
+ }
+ return nStart;
+}
+
+
+/*************************************************************************
+ * SwTxtFrmInfo::GetLineStart()
+ *************************************************************************/
+
+// Wo beginnt der Text (ohne whitespaces)? (rel. im Frame)
+SwTwips SwTxtFrmInfo::GetLineStart() const
+{
+ SwTxtSizeInfo aInf( (SwTxtFrm*)pFrm );
+ SwTxtCursor aLine( (SwTxtFrm*)pFrm, &aInf );
+ return GetLineStart( aLine ) - pFrm->Frm().Left() - pFrm->Prt().Left();
+}
+
+// errechne die Position des Zeichens und gebe die Mittelposition zurueck
+SwTwips SwTxtFrmInfo::GetCharPos( xub_StrLen nChar, sal_Bool bCenter ) const
+{
+ SWRECTFN( pFrm )
+ SwFrmSwapper aSwapper( pFrm, sal_True );
+
+ SwTxtSizeInfo aInf( (SwTxtFrm*)pFrm );
+ SwTxtCursor aLine( (SwTxtFrm*)pFrm, &aInf );
+
+ SwTwips nStt, nNext;
+ SwRect aRect;
+ if( ((SwTxtCursor&)aLine).GetCharRect( &aRect, nChar ) )
+ {
+ if ( bVert )
+ pFrm->SwitchHorizontalToVertical( aRect );
+
+ nStt = (aRect.*fnRect->fnGetLeft)();
+ }
+ else
+ nStt = aLine.GetLineStart();
+
+ if( !bCenter )
+ return nStt - (pFrm->Frm().*fnRect->fnGetLeft)();
+
+ if( ((SwTxtCursor&)aLine).GetCharRect( &aRect, nChar+1 ) )
+ {
+ if ( bVert )
+ pFrm->SwitchHorizontalToVertical( aRect );
+
+ nNext = (aRect.*fnRect->fnGetLeft)();
+ }
+ else
+ nNext = aLine.GetLineStart();
+
+ return (( nNext + nStt ) / 2 ) - (pFrm->Frm().*fnRect->fnGetLeft)();
+}
+
+/*************************************************************************
+ * SwTxtFrmInfo::GetSpaces()
+ *************************************************************************/
+
+SwPaM *AddPam( SwPaM *pPam, const SwTxtFrm* pTxtFrm,
+ const xub_StrLen nPos, const xub_StrLen nLen )
+{
+ if( nLen )
+ {
+ // Es koennte auch der erste sein.
+ if( pPam->HasMark() )
+ {
+ // liegt die neue Position genau hinter der aktuellen, dann
+ // erweiter den Pam einfach
+ if( nPos == pPam->GetPoint()->nContent.GetIndex() )
+ {
+ pPam->GetPoint()->nContent += nLen;
+ return pPam;
+ }
+ pPam = new SwPaM( *pPam );
+ }
+
+ SwIndex &rContent = pPam->GetPoint()->nContent;
+ rContent.Assign( (SwTxtNode*)pTxtFrm->GetTxtNode(), nPos );
+ pPam->SetMark();
+ rContent += nLen;
+ }
+ return pPam;
+}
+
+// Sammelt die whitespaces am Zeilenbeginn und -ende im Pam
+void SwTxtFrmInfo::GetSpaces( SwPaM &rPam, sal_Bool bWithLineBreak ) const
+{
+ SwTxtSizeInfo aInf( (SwTxtFrm*)pFrm );
+ SwTxtMargin aLine( (SwTxtFrm*)pFrm, &aInf );
+ SwPaM *pPam = &rPam;
+ sal_Bool bFirstLine = sal_True;
+ do {
+
+ if( aLine.GetCurr()->GetLen() )
+ {
+ xub_StrLen nPos = aLine.GetTxtStart();
+ // Bug 49649: von der ersten Line die Blanks/Tabs NICHT
+ // mit selektieren
+ if( !bFirstLine && nPos > aLine.GetStart() )
+ pPam = AddPam( pPam, pFrm, aLine.GetStart(),
+ nPos - aLine.GetStart() );
+
+ // Bug 49649: von der letzten Line die Blanks/Tabs NICHT
+ // mit selektieren
+ if( aLine.GetNext() )
+ {
+ nPos = aLine.GetTxtEnd();
+
+ if( nPos < aLine.GetEnd() )
+ {
+ MSHORT nOff = !bWithLineBreak && CH_BREAK ==
+ aLine.GetInfo().GetChar( aLine.GetEnd() - 1 )
+ ? 1 : 0;
+ pPam = AddPam( pPam, pFrm, nPos, aLine.GetEnd() - nPos - nOff );
+ }
+ }
+ }
+ bFirstLine = sal_False;
+ }
+ while( aLine.Next() );
+}
+
+/*************************************************************************
+ * SwTxtFrmInfo::IsBullet()
+ *************************************************************************/
+
+// Ist an der Textposition ein Bullet/Symbol etc?
+// Fonts: CharSet, SYMBOL und DONTKNOW
+sal_Bool SwTxtFrmInfo::IsBullet( xub_StrLen nTxtStart ) const
+{
+ SwTxtSizeInfo aInf( (SwTxtFrm*)pFrm );
+ SwTxtMargin aLine( (SwTxtFrm*)pFrm, &aInf );
+ aInf.SetIdx( nTxtStart );
+ return aLine.IsSymbol( nTxtStart );
+}
+
+/*************************************************************************
+ * SwTxtFrmInfo::GetFirstIndent()
+ *************************************************************************/
+
+// Ermittelt Erstzeileneinzug
+// Voraussetzung fuer pos. oder neg. EZE ist, dass alle
+// Zeilen ausser der ersten Zeile den selben linken Rand haben.
+// Wir wollen nicht so knauserig sein und arbeiten mit einer Toleranz
+// von TOLERANCE Twips.
+
+#define TOLERANCE 20
+
+SwTwips SwTxtFrmInfo::GetFirstIndent() const
+{
+ SwTxtSizeInfo aInf( (SwTxtFrm*)pFrm );
+ SwTxtCursor aLine( (SwTxtFrm*)pFrm, &aInf );
+ const SwTwips nFirst = GetLineStart( aLine );
+ if( !aLine.Next() )
+ return 0;
+
+ SwTwips nLeft = GetLineStart( aLine );
+ while( aLine.Next() )
+ {
+ if( aLine.GetCurr()->GetLen() )
+ {
+ const SwTwips nCurrLeft = GetLineStart( aLine );
+ if( nLeft + TOLERANCE < nCurrLeft ||
+ nLeft - TOLERANCE > nCurrLeft )
+ return 0;
+ }
+ }
+
+ // Vorerst wird nur +1, -1 und 0 returnt.
+ if( nLeft == nFirst )
+ return 0;
+ else
+ if( nLeft > nFirst )
+ return -1;
+ else
+ return +1;
+}
+
+/*************************************************************************
+ * SwTxtFrmInfo::GetBigIndent()
+ *************************************************************************/
+
+KSHORT SwTxtFrmInfo::GetBigIndent( xub_StrLen& rFndPos,
+ const SwTxtFrm *pNextFrm ) const
+{
+ SwTxtSizeInfo aInf( (SwTxtFrm*)pFrm );
+ SwTxtCursor aLine( (SwTxtFrm*)pFrm, &aInf );
+ SwTwips nNextIndent = 0;
+
+ if( pNextFrm )
+ {
+ // ich bin einzeilig
+ SwTxtSizeInfo aNxtInf( (SwTxtFrm*)pNextFrm );
+ SwTxtCursor aNxtLine( (SwTxtFrm*)pNextFrm, &aNxtInf );
+ nNextIndent = GetLineStart( aNxtLine );
+ }
+ else
+ {
+ // ich bin mehrzeilig
+ if( aLine.Next() )
+ {
+ nNextIndent = GetLineStart( aLine );
+ aLine.Prev();
+ }
+ }
+
+ if( nNextIndent <= GetLineStart( aLine ) )
+ return 0;
+
+ const Point aPoint( nNextIndent, aLine.Y() );
+ rFndPos = aLine.GetCrsrOfst( 0, aPoint, sal_False );
+ if( 1 >= rFndPos )
+ return 0;
+
+ // steht vor einem "nicht Space"
+ const XubString& rTxt = aInf.GetTxt();
+ xub_Unicode aChar = rTxt.GetChar( rFndPos );
+ if( CH_TAB == aChar || CH_BREAK == aChar || ' ' == aChar ||
+ (( CH_TXTATR_BREAKWORD == aChar || CH_TXTATR_INWORD == aChar ) &&
+ aInf.HasHint( rFndPos ) ) )
+ return 0;
+
+ // und hinter einem "Space"
+ aChar = rTxt.GetChar( rFndPos - 1 );
+ if( CH_TAB != aChar && CH_BREAK != aChar &&
+ ( ( CH_TXTATR_BREAKWORD != aChar && CH_TXTATR_INWORD != aChar ) ||
+ !aInf.HasHint( rFndPos - 1 ) ) &&
+ // mehr als 2 Blanks !!
+ ( ' ' != aChar || ' ' != rTxt.GetChar( rFndPos - 2 ) ) )
+ return 0;
+
+ SwRect aRect;
+ return aLine.GetCharRect( &aRect, rFndPos )
+ ? KSHORT( aRect.Left() - pFrm->Frm().Left() - pFrm->Prt().Left())
+ : 0;
+}
+
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/text/frmpaint.cxx b/sw/source/core/text/frmpaint.cxx
new file mode 100644
index 000000000000..d20b8e328f49
--- /dev/null
+++ b/sw/source/core/text/frmpaint.cxx
@@ -0,0 +1,743 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+#include <com/sun/star/text/HoriOrientation.hpp>
+#include <hintids.hxx>
+#include <vcl/sound.hxx>
+#include <tools/shl.hxx> // SW_MOD
+#include <editeng/pgrditem.hxx>
+#include <editeng/lrspitem.hxx>
+#include <pagedesc.hxx> // SwPageDesc
+#include <tgrditem.hxx>
+#include <paratr.hxx>
+
+#include <fmtline.hxx>
+#include <lineinfo.hxx>
+#include <charfmt.hxx>
+#include "rootfrm.hxx"
+#include <pagefrm.hxx>
+#include <viewsh.hxx> // ViewShell
+#include <viewimp.hxx> // SwViewImp
+#include <viewopt.hxx> // SwViewOption
+#include <frmtool.hxx> // DrawGraphic
+#include <txtfrm.hxx> // SwTxtFrm
+#include <itrpaint.hxx> // SwTxtPainter
+#include <txtpaint.hxx> // SwSaveClip
+#include <txtcache.hxx> // SwTxtLineAccess
+#include <flyfrm.hxx> // SwFlyFrm
+#include <redlnitr.hxx> // SwRedlineItr
+#include <swmodule.hxx> // SW_MOD
+#include <tabfrm.hxx> // SwTabFrm (Redlining)
+#include <SwGrammarMarkUp.hxx>
+
+// --> FME 2004-06-08 #i12836# enhanced pdf export
+#include <EnhancedPDFExportHelper.hxx>
+// <--
+
+#include <IDocumentStylePoolAccess.hxx>
+#include <IDocumentLineNumberAccess.hxx>
+
+// --> OD 2006-06-27 #b6440955#
+// variable moved to class <numfunc:GetDefBulletConfig>
+//extern const sal_Char sBulletFntName[];
+namespace numfunc
+{
+ extern const String& GetDefBulletFontname();
+ extern bool IsDefBulletFontUserDefined();
+}
+// <--
+
+
+#define REDLINE_DISTANCE 567/4
+#define REDLINE_MINDIST 567/10
+
+using namespace ::com::sun::star;
+
+////////////////////////////////////////////////////////////
+
+sal_Bool bInitFont = sal_True;
+
+class SwExtraPainter
+{
+ SwSaveClip aClip;
+ SwRect aRect;
+ const SwTxtFrm* pTxtFrm;
+ ViewShell *pSh;
+ SwFont* pFnt;
+ const SwLineNumberInfo &rLineInf;
+ SwTwips nX;
+ SwTwips nRedX;
+ sal_uLong nLineNr;
+ MSHORT nDivider;
+ sal_Bool bGoLeft;
+ sal_Bool bLineNum;
+ inline sal_Bool IsClipChg() { return aClip.IsChg(); }
+public:
+ SwExtraPainter( const SwTxtFrm *pFrm, ViewShell *pVwSh,
+ const SwLineNumberInfo &rLnInf, const SwRect &rRct,
+ sal_Int16 eHor, sal_Bool bLnNm );
+ ~SwExtraPainter() { delete pFnt; }
+ inline SwFont* GetFont() const { return pFnt; }
+ inline void IncLineNr() { ++nLineNr; }
+ inline sal_Bool HasNumber() { return !( nLineNr % rLineInf.GetCountBy() ); }
+ inline sal_Bool HasDivider() { if( !nDivider ) return sal_False;
+ return !(nLineNr % rLineInf.GetDividerCountBy()); }
+
+ void PaintExtra( SwTwips nY, long nAsc, long nMax, sal_Bool bRed );
+ void PaintRedline( SwTwips nY, long nMax );
+};
+
+
+SwExtraPainter::SwExtraPainter( const SwTxtFrm *pFrm, ViewShell *pVwSh,
+ const SwLineNumberInfo &rLnInf, const SwRect &rRct,
+ sal_Int16 eHor, sal_Bool bLnNm )
+ : aClip( pVwSh->GetWin() || pFrm->IsUndersized() ? pVwSh->GetOut() : 0 ),
+ aRect( rRct ), pTxtFrm( pFrm ), pSh( pVwSh ), pFnt( 0 ), rLineInf( rLnInf ),
+ nLineNr( 1L ), bLineNum( bLnNm )
+{
+ if( pFrm->IsUndersized() )
+ {
+ SwTwips nBottom = pFrm->Frm().Bottom();
+ if( aRect.Bottom() > nBottom )
+ aRect.Bottom( nBottom );
+ }
+ MSHORT nVirtPageNum = 0;
+ if( bLineNum )
+ { /* initialisiert die Member, die bei Zeilennumerierung notwendig sind:
+
+ nDivider, wie oft ist ein Teilerstring gewuenscht, 0 == nie;
+ nX, X-Position der Zeilennummern;
+ pFnt, der Font der Zeilennummern;
+ nLineNr, die erste Zeilennummer;
+ bLineNum wird ggf.wieder auf sal_False gesetzt, wenn die Numerierung sich
+ komplett ausserhalb des Paint-Rechtecks aufhaelt. */
+ nDivider = rLineInf.GetDivider().Len() ? rLineInf.GetDividerCountBy() : 0;
+ nX = pFrm->Frm().Left();
+ SwCharFmt* pFmt = rLineInf.GetCharFmt( const_cast<IDocumentStylePoolAccess&>(*pFrm->GetNode()->getIDocumentStylePoolAccess()) );
+ OSL_ENSURE( pFmt, "PaintExtraData without CharFmt" );
+ pFnt = new SwFont( &pFmt->GetAttrSet(), pFrm->GetTxtNode()->getIDocumentSettingAccess() );
+ pFnt->Invalidate();
+ pFnt->ChgPhysFnt( pSh, *pSh->GetOut() );
+ pFnt->SetVertical( 0, pFrm->IsVertical() );
+ nLineNr += pFrm->GetAllLines() - pFrm->GetThisLines();
+ LineNumberPosition ePos = rLineInf.GetPos();
+ if( ePos != LINENUMBER_POS_LEFT && ePos != LINENUMBER_POS_RIGHT )
+ {
+ if( pFrm->FindPageFrm()->OnRightPage() )
+ {
+ nVirtPageNum = 1;
+ ePos = ePos == LINENUMBER_POS_INSIDE ?
+ LINENUMBER_POS_LEFT : LINENUMBER_POS_RIGHT;
+ }
+ else
+ {
+ nVirtPageNum = 2;
+ ePos = ePos == LINENUMBER_POS_OUTSIDE ?
+ LINENUMBER_POS_LEFT : LINENUMBER_POS_RIGHT;
+ }
+ }
+ if( LINENUMBER_POS_LEFT == ePos )
+ {
+ bGoLeft = sal_True;
+ nX -= rLineInf.GetPosFromLeft();
+ if( nX < aRect.Left() )
+ bLineNum = sal_False;
+ }
+ else
+ {
+ bGoLeft = sal_False;
+ nX += pFrm->Frm().Width() + rLineInf.GetPosFromLeft();
+ if( nX > aRect.Right() )
+ bLineNum = sal_False;
+ }
+ }
+ if( eHor != text::HoriOrientation::NONE )
+ {
+ if( text::HoriOrientation::INSIDE == eHor || text::HoriOrientation::OUTSIDE == eHor )
+ {
+ if( !nVirtPageNum )
+ nVirtPageNum = pFrm->FindPageFrm()->OnRightPage() ? 1 : 2;
+ if( nVirtPageNum % 2 )
+ eHor = eHor == text::HoriOrientation::INSIDE ? text::HoriOrientation::LEFT : text::HoriOrientation::RIGHT;
+ else
+ eHor = eHor == text::HoriOrientation::OUTSIDE ? text::HoriOrientation::LEFT : text::HoriOrientation::RIGHT;
+ }
+ const SwFrm* pTmpFrm = pFrm->FindTabFrm();
+ if( !pTmpFrm )
+ pTmpFrm = pFrm;
+ nRedX = text::HoriOrientation::LEFT == eHor ? pTmpFrm->Frm().Left() - REDLINE_DISTANCE :
+ pTmpFrm->Frm().Right() + REDLINE_DISTANCE;
+ }
+}
+
+/*************************************************************************
+ * SwExtraPainter::PaintExtra()
+ **************************************************************************/
+
+void SwExtraPainter::PaintExtra( SwTwips nY, long nAsc, long nMax, sal_Bool bRed )
+{
+ //Zeilennummer ist staerker als der Teiler
+ const XubString aTmp( HasNumber() ? rLineInf.GetNumType().GetNumStr( nLineNr )
+ : rLineInf.GetDivider() );
+
+ // get script type of line numbering:
+ pFnt->SetActual( SwScriptInfo::WhichFont( 0, &aTmp, 0 ) );
+
+ SwDrawTextInfo aDrawInf( pSh, *pSh->GetOut(), 0, aTmp, 0, aTmp.Len() );
+ aDrawInf.SetSpace( 0 );
+ aDrawInf.SetWrong( NULL );
+ aDrawInf.SetGrammarCheck( NULL );
+ aDrawInf.SetSmartTags( NULL ); // SMARTTAGS
+ aDrawInf.SetLeft( 0 );
+ aDrawInf.SetRight( LONG_MAX );
+ aDrawInf.SetFrm( pTxtFrm );
+ aDrawInf.SetFont( pFnt );
+ aDrawInf.SetSnapToGrid( sal_False );
+ aDrawInf.SetIgnoreFrmRTL( sal_True );
+
+ sal_Bool bTooBig = pFnt->GetSize( pFnt->GetActual() ).Height() > nMax &&
+ pFnt->GetHeight( pSh, *pSh->GetOut() ) > nMax;
+ SwFont* pTmpFnt;
+ if( bTooBig )
+ {
+ pTmpFnt = new SwFont( *GetFont() );
+ if( nMax >= 20 )
+ {
+ nMax *= 17;
+ nMax /= 20;
+ }
+ pTmpFnt->SetSize( Size( 0, nMax ), pTmpFnt->GetActual() );
+ }
+ else
+ pTmpFnt = GetFont();
+ Point aTmpPos( nX, nY );
+ aTmpPos.Y() += nAsc;
+ sal_Bool bPaint = sal_True;
+ if( !IsClipChg() )
+ {
+ Size aSize = pTmpFnt->_GetTxtSize( aDrawInf );
+ if( bGoLeft )
+ aTmpPos.X() -= aSize.Width();
+ // calculate rectangle containing the line number
+ SwRect aRct( Point( aTmpPos.X(),
+ aTmpPos.Y() - pTmpFnt->GetAscent( pSh, *pSh->GetOut() )
+ ), aSize );
+ if( !aRect.IsInside( aRct ) )
+ {
+ if( aRct.Intersection( aRect ).IsEmpty() )
+ bPaint = sal_False;
+ else
+ aClip.ChgClip( aRect, pTxtFrm );
+ }
+ }
+ else if( bGoLeft )
+ aTmpPos.X() -= pTmpFnt->_GetTxtSize( aDrawInf ).Width();
+ aDrawInf.SetPos( aTmpPos );
+ if( bPaint )
+ pTmpFnt->_DrawText( aDrawInf );
+
+ if( bTooBig )
+ delete pTmpFnt;
+ if( bRed )
+ {
+ long nDiff = bGoLeft ? nRedX - nX : nX - nRedX;
+ if( nDiff > REDLINE_MINDIST )
+ PaintRedline( nY, nMax );
+ }
+}
+
+void SwExtraPainter::PaintRedline( SwTwips nY, long nMax )
+{
+ Point aStart( nRedX, nY );
+ Point aEnd( nRedX, nY + nMax );
+
+ if( !IsClipChg() )
+ {
+ SwRect aRct( aStart, aEnd );
+ if( !aRect.IsInside( aRct ) )
+ {
+ if( aRct.Intersection( aRect ).IsEmpty() )
+ return;
+ aClip.ChgClip( aRect, pTxtFrm );
+ }
+ }
+ const Color aOldCol( pSh->GetOut()->GetLineColor() );
+ pSh->GetOut()->SetLineColor( SW_MOD()->GetRedlineMarkColor() );
+
+ if ( pTxtFrm->IsVertical() )
+ {
+ pTxtFrm->SwitchHorizontalToVertical( aStart );
+ pTxtFrm->SwitchHorizontalToVertical( aEnd );
+ }
+
+ pSh->GetOut()->DrawLine( aStart, aEnd );
+ pSh->GetOut()->SetLineColor( aOldCol );
+}
+
+void SwTxtFrm::PaintExtraData( const SwRect &rRect ) const
+{
+ if( Frm().Top() > rRect.Bottom() || Frm().Bottom() < rRect.Top() )
+ return;
+
+ const SwTxtNode& rTxtNode = *GetTxtNode();
+ const IDocumentRedlineAccess* pIDRA = rTxtNode.getIDocumentRedlineAccess();
+ const SwLineNumberInfo &rLineInf = rTxtNode.getIDocumentLineNumberAccess()->GetLineNumberInfo();
+ const SwFmtLineNumber &rLineNum = GetAttrSet()->GetLineNumber();
+ sal_Bool bLineNum = !IsInTab() && rLineInf.IsPaintLineNumbers() &&
+ ( !IsInFly() || rLineInf.IsCountInFlys() ) && rLineNum.IsCount();
+ sal_Int16 eHor = (sal_Int16)SW_MOD()->GetRedlineMarkPos();
+ if( eHor != text::HoriOrientation::NONE && !IDocumentRedlineAccess::IsShowChanges( pIDRA->GetRedlineMode() ) )
+ eHor = text::HoriOrientation::NONE;
+ sal_Bool bRedLine = eHor != text::HoriOrientation::NONE;
+ if ( bLineNum || bRedLine )
+ {
+ if( IsLocked() || IsHiddenNow() || !Prt().Height() )
+ return;
+ ViewShell *pSh = getRootFrm()->GetCurrShell();
+
+ SWAP_IF_NOT_SWAPPED( this )
+ SwRect rOldRect( rRect );
+
+ if ( IsVertical() )
+ SwitchVerticalToHorizontal( (SwRect&)rRect );
+
+ SwLayoutModeModifier aLayoutModeModifier( *pSh->GetOut() );
+ aLayoutModeModifier.Modify( sal_False );
+
+ // --> FME 2004-06-24 #i16816# tagged pdf support
+ SwTaggedPDFHelper aTaggedPDFHelper( 0, 0, 0, *pSh->GetOut() );
+ // <--
+
+ SwExtraPainter aExtra( this, pSh, rLineInf, rRect, eHor, bLineNum );
+
+ if( HasPara() )
+ {
+ SwTxtFrmLocker aLock((SwTxtFrm*)this);
+
+ SwTxtLineAccess aAccess( (SwTxtFrm*)this );
+ aAccess.GetPara();
+
+ SwTxtPaintInfo aInf( (SwTxtFrm*)this, rRect );
+
+ aLayoutModeModifier.Modify( sal_False );
+
+ SwTxtPainter aLine( (SwTxtFrm*)this, &aInf );
+ sal_Bool bNoDummy = !aLine.GetNext(); // Nur eine Leerzeile!
+
+ while( aLine.Y() + aLine.GetLineHeight() <= rRect.Top() )
+ {
+ if( !aLine.GetCurr()->IsDummy() &&
+ ( rLineInf.IsCountBlankLines() ||
+ aLine.GetCurr()->HasCntnt() ) )
+ aExtra.IncLineNr();
+ if( !aLine.Next() )
+ {
+ (SwRect&)rRect = rOldRect;
+ UNDO_SWAP( this )
+ return;
+ }
+ }
+
+ long nBottom = rRect.Bottom();
+
+ sal_Bool bNoPrtLine = 0 == GetMinPrtLine();
+ if( !bNoPrtLine )
+ {
+ while ( aLine.Y() < GetMinPrtLine() )
+ {
+ if( ( rLineInf.IsCountBlankLines() || aLine.GetCurr()->HasCntnt() )
+ && !aLine.GetCurr()->IsDummy() )
+ aExtra.IncLineNr();
+ if( !aLine.Next() )
+ break;
+ }
+ bNoPrtLine = aLine.Y() >= GetMinPrtLine();
+ }
+ if( bNoPrtLine )
+ {
+ do
+ {
+ if( bNoDummy || !aLine.GetCurr()->IsDummy() )
+ {
+ sal_Bool bRed = bRedLine && aLine.GetCurr()->HasRedline();
+ if( rLineInf.IsCountBlankLines() || aLine.GetCurr()->HasCntnt() )
+ {
+ if( bLineNum &&
+ ( aExtra.HasNumber() || aExtra.HasDivider() ) )
+ {
+ KSHORT nTmpHeight, nTmpAscent;
+ aLine.CalcAscentAndHeight( nTmpAscent, nTmpHeight );
+ aExtra.PaintExtra( aLine.Y(), nTmpAscent,
+ nTmpHeight, bRed );
+ bRed = sal_False;
+ }
+ aExtra.IncLineNr();
+ }
+ if( bRed )
+ aExtra.PaintRedline( aLine.Y(), aLine.GetLineHeight() );
+ }
+ } while( aLine.Next() && aLine.Y() <= nBottom );
+ }
+ }
+ else
+ {
+ bRedLine &= ( MSHRT_MAX!= pIDRA->GetRedlinePos(rTxtNode, USHRT_MAX) );
+
+ if( bLineNum && rLineInf.IsCountBlankLines() &&
+ ( aExtra.HasNumber() || aExtra.HasDivider() ) )
+ {
+ aExtra.PaintExtra( Frm().Top()+Prt().Top(), aExtra.GetFont()
+ ->GetAscent( pSh, *pSh->GetOut() ), Prt().Height(), bRedLine );
+ }
+ else if( bRedLine )
+ aExtra.PaintRedline( Frm().Top()+Prt().Top(), Prt().Height() );
+ }
+
+ (SwRect&)rRect = rOldRect;
+ UNDO_SWAP( this )
+ }
+}
+
+/*************************************************************************
+ * SwTxtFrm::Paint()
+ *************************************************************************/
+
+SwRect SwTxtFrm::Paint()
+{
+#if OSL_DEBUG_LEVEL > 1
+ const SwTwips nDbgY = Frm().Top();
+ (void)nDbgY;
+#endif
+
+ // finger layout
+ OSL_ENSURE( GetValidPosFlag(), "+SwTxtFrm::Paint: no Calc()" );
+
+ SwRect aRet( Prt() );
+ if ( IsEmpty() || !HasPara() )
+ aRet += Frm().Pos();
+ else
+ {
+ // AMA: Wir liefern jetzt mal das richtige Repaintrechteck zurueck,
+ // d.h. als linken Rand den berechneten PaintOfst!
+ SwRepaint *pRepaint = GetPara()->GetRepaint();
+ long l;
+ //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin
+ if ( IsVertLR() ) // mba: the following line was added, but we don't need it for the existing directions; kept for IsVertLR(), but should be checked
+ pRepaint->Chg( ( GetUpper()->Frm() ).Pos() + ( GetUpper()->Prt() ).Pos(), ( GetUpper()->Prt() ).SSize() );
+
+ if( pRepaint->GetOfst() )
+ pRepaint->Left( pRepaint->GetOfst() );
+
+ l = pRepaint->GetRightOfst();
+ if( l && ( pRepaint->GetOfst() || l > pRepaint->Right() ) )
+ pRepaint->Right( l );
+ pRepaint->SetOfst( 0 );
+ aRet = *pRepaint;
+
+ if ( IsRightToLeft() )
+ SwitchLTRtoRTL( aRet );
+
+ if ( IsVertical() )
+ SwitchHorizontalToVertical( aRet );
+ }
+ ResetRepaint();
+
+ return aRet;
+}
+
+/*************************************************************************
+ * SwTxtFrm::Paint()
+ *************************************************************************/
+
+sal_Bool SwTxtFrm::PaintEmpty( const SwRect &rRect, sal_Bool bCheck ) const
+{
+ ViewShell *pSh = getRootFrm()->GetCurrShell();
+ if( pSh && ( pSh->GetViewOptions()->IsParagraph() || bInitFont ) )
+ {
+ bInitFont = sal_False;
+ SwTxtFly aTxtFly( this );
+ aTxtFly.SetTopRule();
+ SwRect aRect;
+ if( bCheck && aTxtFly.IsOn() && aTxtFly.IsAnyObj( aRect ) )
+ return sal_False;
+ else if( pSh->GetWin() )
+ {
+ SwFont *pFnt;
+ const SwTxtNode& rTxtNode = *GetTxtNode();
+ if ( rTxtNode.HasSwAttrSet() )
+ {
+ const SwAttrSet *pAttrSet = &( rTxtNode.GetSwAttrSet() );
+ pFnt = new SwFont( pAttrSet, rTxtNode.getIDocumentSettingAccess() );
+ }
+ else
+ {
+ SwFontAccess aFontAccess( &rTxtNode.GetAnyFmtColl(), pSh );
+ pFnt = new SwFont( *aFontAccess.Get()->GetFont() );
+ }
+
+ const IDocumentRedlineAccess* pIDRA = rTxtNode.getIDocumentRedlineAccess();
+ if( IDocumentRedlineAccess::IsShowChanges( pIDRA->GetRedlineMode() ) )
+ {
+ MSHORT nRedlPos = pIDRA->GetRedlinePos( rTxtNode, USHRT_MAX );
+ if( MSHRT_MAX != nRedlPos )
+ {
+ SwAttrHandler aAttrHandler;
+ aAttrHandler.Init( rTxtNode.GetSwAttrSet(),
+ *rTxtNode.getIDocumentSettingAccess(), NULL );
+ SwRedlineItr aRedln( rTxtNode, *pFnt, aAttrHandler, nRedlPos, sal_True );
+ }
+ }
+
+ if( pSh->GetViewOptions()->IsParagraph() && Prt().Height() )
+ {
+ if( RTL_TEXTENCODING_SYMBOL == pFnt->GetCharSet( SW_LATIN ) &&
+ pFnt->GetName( SW_LATIN ) != numfunc::GetDefBulletFontname() )
+ {
+ pFnt->SetFamily( FAMILY_DONTKNOW, SW_LATIN );
+ pFnt->SetName( numfunc::GetDefBulletFontname(), SW_LATIN );
+ pFnt->SetStyleName( aEmptyStr, SW_LATIN );
+ pFnt->SetCharSet( RTL_TEXTENCODING_SYMBOL, SW_LATIN );
+ }
+ pFnt->SetVertical( 0, IsVertical() );
+ SwFrmSwapper aSwapper( this, sal_True );
+ SwLayoutModeModifier aLayoutModeModifier( *pSh->GetOut() );
+ aLayoutModeModifier.Modify( IsRightToLeft() );
+
+ pFnt->Invalidate();
+ pFnt->ChgPhysFnt( pSh, *pSh->GetOut() );
+ Point aPos = Frm().Pos() + Prt().Pos();
+
+ const SvxLRSpaceItem &rSpace =
+ GetTxtNode()->GetSwAttrSet().GetLRSpace();
+
+ if ( rSpace.GetTxtFirstLineOfst() > 0 )
+ aPos.X() += rSpace.GetTxtFirstLineOfst();
+
+ SwSaveClip *pClip;
+ if( IsUndersized() )
+ {
+ pClip = new SwSaveClip( pSh->GetOut() );
+ pClip->ChgClip( rRect );
+ }
+ else
+ pClip = NULL;
+
+ aPos.Y() += pFnt->GetAscent( pSh, *pSh->GetOut() );
+
+ if ( GetTxtNode()->GetSwAttrSet().GetParaGrid().GetValue() &&
+ IsInDocBody() )
+ {
+ GETGRID( FindPageFrm() )
+ if ( pGrid )
+ {
+ // center character in grid line
+ aPos.Y() += ( pGrid->GetBaseHeight() -
+ pFnt->GetHeight( pSh, *pSh->GetOut() ) ) / 2;
+
+ if ( ! pGrid->GetRubyTextBelow() )
+ aPos.Y() += pGrid->GetRubyHeight();
+ }
+ }
+
+ // Don't show the paragraph mark for collapsed paragraphs, when they are hidden
+ if ( EmptyHeight( ) > 1 )
+ {
+ const XubString aTmp( CH_PAR );
+ SwDrawTextInfo aDrawInf( pSh, *pSh->GetOut(), 0, aTmp, 0, 1 );
+ aDrawInf.SetLeft( rRect.Left() );
+ aDrawInf.SetRight( rRect.Right() );
+ aDrawInf.SetPos( aPos );
+ aDrawInf.SetSpace( 0 );
+ aDrawInf.SetKanaComp( 0 );
+ aDrawInf.SetWrong( NULL );
+ aDrawInf.SetGrammarCheck( NULL );
+ aDrawInf.SetSmartTags( NULL ); // SMARTTAGS
+ aDrawInf.SetFrm( this );
+ aDrawInf.SetFont( pFnt );
+ aDrawInf.SetSnapToGrid( sal_False );
+
+ pFnt->_DrawText( aDrawInf );
+ }
+ delete pClip;
+ }
+ delete pFnt;
+ return sal_True;
+ }
+ }
+ else
+ return sal_True;
+ return sal_False;
+}
+
+/*************************************************************************
+ * SwTxtFrm::Paint()
+ *************************************************************************/
+
+void SwTxtFrm::Paint(SwRect const& rRect, SwPrintData const*const) const
+{
+ ResetRepaint();
+
+ // --> FME 2004-06-24 #i16816# tagged pdf support
+ ViewShell *pSh = getRootFrm()->GetCurrShell();
+
+ Num_Info aNumInfo( *this );
+ SwTaggedPDFHelper aTaggedPDFHelperNumbering( &aNumInfo, 0, 0, *pSh->GetOut() );
+
+ Frm_Info aFrmInfo( *this );
+ SwTaggedPDFHelper aTaggedPDFHelperParagraph( 0, &aFrmInfo, 0, *pSh->GetOut() );
+ // <--
+
+ if( !IsEmpty() || !PaintEmpty( rRect, sal_True ) )
+ {
+#if OSL_DEBUG_LEVEL > 1
+ const SwTwips nDbgY = Frm().Top();
+ (void)nDbgY;
+#endif
+
+ if( IsLocked() || IsHiddenNow() || ! Prt().HasArea() )
+ return;
+
+ //Kann gut sein, dass mir der IdleCollector mir die gecachten
+ //Informationen entzogen hat.
+ if( !HasPara() )
+ {
+ OSL_ENSURE( GetValidPosFlag(), "+SwTxtFrm::Paint: no Calc()" );
+
+ // --> FME 2004-10-29 #i29062# pass info that we are currently
+ // painting.
+ ((SwTxtFrm*)this)->GetFormatted( true );
+ // <--
+ if( IsEmpty() )
+ {
+ PaintEmpty( rRect, sal_False );
+ return;
+ }
+ if( !HasPara() )
+ {
+ OSL_ENSURE( !this, "+SwTxtFrm::Paint: missing format information" );
+ return;
+ }
+ }
+
+ // Waehrend wir painten, wollen wir nicht gestoert werden.
+ // Aber erst hinter dem Format() !
+ SwTxtFrmLocker aLock((SwTxtFrm*)this);
+
+ //Hier wird ggf. nur der Teil des TxtFrm ausgegeben, der sich veraendert
+ //hat und der in dem Bereich liegt, dessen Ausgabe angefordert wurde.
+ //Man kann jetzt auf die Idee kommen, dass der Bereich rRect ausgegeben
+ //werden _muss_ obwohl rRepaint gesetzt ist; in der Tat kann dieses
+ //Problem nicht formal vermieden werden. Gluecklicherweise koennen
+ //wir davon ausgehen, dass rRepaint immer dann leer ist, wenn der Frm
+ //komplett gepainted werden muss.
+ SwTxtLineAccess aAccess( (SwTxtFrm*)this );
+ SwParaPortion *pPara = aAccess.GetPara();
+
+ SwRepaint &rRepaint = *(pPara->GetRepaint());
+
+ // Das Recycling muss abgeschaltet werden, wenn wir uns im
+ // FlyCntFrm befinden, weil ein DrawRect fuer die Retusche der
+ // Zeile aufgerufen wird.
+ if( rRepaint.GetOfst() )
+ {
+ const SwFlyFrm *pFly = FindFlyFrm();
+ if( pFly && pFly->IsFlyInCntFrm() )
+ rRepaint.SetOfst( 0 );
+ }
+
+ // Hier holen wir uns den String fuer die Ausgabe, besonders
+ // die Laenge ist immer wieder interessant.
+
+ // Rectangle
+ OSL_ENSURE( ! IsSwapped(), "A frame is swapped before Paint" );
+ SwRect aOldRect( rRect );
+
+ SWAP_IF_NOT_SWAPPED( this )
+
+ if ( IsVertical() )
+ SwitchVerticalToHorizontal( (SwRect&)rRect );
+
+ if ( IsRightToLeft() )
+ SwitchRTLtoLTR( (SwRect&)rRect );
+
+ SwTxtPaintInfo aInf( (SwTxtFrm*)this, rRect );
+ aInf.SetWrongList( ( (SwTxtNode*)GetTxtNode() )->GetWrong() );
+ aInf.SetGrammarCheckList( ( (SwTxtNode*)GetTxtNode() )->GetGrammarCheck() );
+ aInf.SetSmartTags( ( (SwTxtNode*)GetTxtNode() )->GetSmartTags() ); // SMARTTAGS
+ aInf.GetTxtFly()->SetTopRule();
+
+ SwTxtPainter aLine( (SwTxtFrm*)this, &aInf );
+ // Eine Optimierung, die sich lohnt: wenn kein freifliegender Frame
+ // in unsere Zeile ragt, schaltet sich der SwTxtFly einfach ab:
+ aInf.GetTxtFly()->Relax();
+
+ OutputDevice* pOut = aInf.GetOut();
+ const sal_Bool bOnWin = pSh->GetWin() != 0;
+
+ SwSaveClip aClip( bOnWin || IsUndersized() ? pOut : 0 );
+
+ // Ausgabeschleife: Fuer jede Zeile ... (die noch zu sehen ist) ...
+ // rRect muss angepasst werden (Top+1, Bottom-1), weil der Iterator
+ // die Zeilen nahtlos aneinanderfuegt.
+ aLine.TwipsToLine( rRect.Top() + 1 );
+ long nBottom = rRect.Bottom();
+
+ sal_Bool bNoPrtLine = 0 == GetMinPrtLine();
+ if( !bNoPrtLine )
+ {
+ while ( aLine.Y() < GetMinPrtLine() && aLine.Next() )
+ ;
+ bNoPrtLine = aLine.Y() >= GetMinPrtLine();
+ }
+ if( bNoPrtLine )
+ {
+ do
+ {
+ aLine.DrawTextLine( rRect, aClip, IsUndersized() );
+
+ } while( aLine.Next() && aLine.Y() <= nBottom );
+ }
+
+ // Einmal reicht:
+ if( aLine.IsPaintDrop() )
+ aLine.PaintDropPortion();
+
+ if( rRepaint.HasArea() )
+ rRepaint.Clear();
+
+ UNDO_SWAP( this )
+ (SwRect&)rRect = aOldRect;
+
+ OSL_ENSURE( ! IsSwapped(), "A frame is swapped after Paint" );
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/text/guess.cxx b/sw/source/core/text/guess.cxx
new file mode 100644
index 000000000000..31e0a4d8ed73
--- /dev/null
+++ b/sw/source/core/text/guess.cxx
@@ -0,0 +1,554 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+
+#include <ctype.h>
+#include <editeng/unolingu.hxx>
+#include <tools/shl.hxx> // needed for SW_MOD() macro
+#include <dlelstnr.hxx>
+#include <swmodule.hxx>
+#include <IDocumentSettingAccess.hxx>
+#include <guess.hxx>
+#include <inftxt.hxx>
+#include <pagefrm.hxx>
+#include <pagedesc.hxx> // SwPageDesc
+#include <tgrditem.hxx>
+#include <com/sun/star/i18n/BreakType.hpp>
+#include <com/sun/star/i18n/WordType.hpp>
+#include <unotools/charclass.hxx>
+#include <porfld.hxx>
+
+using ::rtl::OUString;
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::i18n;
+using namespace ::com::sun::star::beans;
+using namespace ::com::sun::star::linguistic2;
+
+#define CH_FULL_BLANK 0x3000
+
+/*************************************************************************
+ * SwTxtGuess::Guess
+ *
+ * provides information for line break calculation
+ * returns true if no line break has to be performed
+ * otherwise possible break or hyphenation position is determined
+ *************************************************************************/
+
+sal_Bool SwTxtGuess::Guess( const SwTxtPortion& rPor, SwTxtFormatInfo &rInf,
+ const KSHORT nPorHeight )
+{
+ nCutPos = rInf.GetIdx();
+
+ // Leere Strings sind immer 0
+ if( !rInf.GetLen() || !rInf.GetTxt().Len() )
+ return sal_False;
+
+ OSL_ENSURE( rInf.GetIdx() < rInf.GetTxt().Len(),
+ "+SwTxtGuess::Guess: invalid SwTxtFormatInfo" );
+
+ OSL_ENSURE( nPorHeight, "+SwTxtGuess::Guess: no height" );
+
+ sal_uInt16 nMinSize;
+ sal_uInt16 nMaxSizeDiff;
+
+ const SwScriptInfo& rSI =
+ ((SwParaPortion*)rInf.GetParaPortion())->GetScriptInfo();
+
+ sal_uInt16 nMaxComp = ( SW_CJK == rInf.GetFont()->GetActual() ) &&
+ rSI.CountCompChg() &&
+ ! rInf.IsMulti() &&
+ ! rPor.InFldGrp() &&
+ ! rPor.IsDropPortion() ?
+ 10000 :
+ 0 ;
+
+ SwTwips nLineWidth = rInf.Width() - rInf.X();
+ xub_StrLen nMaxLen = rInf.GetTxt().Len() - rInf.GetIdx();
+
+ if ( rInf.GetLen() < nMaxLen )
+ nMaxLen = rInf.GetLen();
+
+ if( !nMaxLen )
+ return sal_False;
+
+ KSHORT nItalic = 0;
+ if( ITALIC_NONE != rInf.GetFont()->GetItalic() && !rInf.NotEOL() )
+ {
+ sal_Bool bAddItalic = sal_True;
+
+ // do not add extra italic value if we have an active character grid
+ if ( rInf.SnapToGrid() )
+ {
+ GETGRID( rInf.GetTxtFrm()->FindPageFrm() )
+ bAddItalic = !pGrid || GRID_LINES_CHARS != pGrid->GetGridType();
+ }
+
+ // do not add extra italic value for an isolated blank:
+ if ( 1 == rInf.GetLen() &&
+ CH_BLANK == rInf.GetTxt().GetChar( rInf.GetIdx() ) )
+ bAddItalic = sal_False;
+
+ nItalic = bAddItalic ? nPorHeight / 12 : 0;
+
+ nLineWidth -= nItalic;
+
+ // --> FME 2005-05-13 #i46524# LineBreak bug with italics
+ if ( nLineWidth < 0 ) nLineWidth = 0;
+ // <--
+ }
+
+ // first check if everything fits to line
+ if ( long ( nLineWidth ) * 2 > long ( nMaxLen ) * nPorHeight )
+ {
+ // call GetTxtSize with maximum compression (for kanas)
+ rInf.GetTxtSize( &rSI, rInf.GetIdx(), nMaxLen,
+ nMaxComp, nMinSize, nMaxSizeDiff );
+
+ nBreakWidth = nMinSize;
+
+ if ( nBreakWidth <= nLineWidth )
+ {
+ // portion fits to line
+ nCutPos = rInf.GetIdx() + nMaxLen;
+ if( nItalic &&
+ ( nCutPos >= rInf.GetTxt().Len() ||
+ // --> FME 2005-05-13 #i48035# Needed for CalcFitToContent
+ // if first line ends with a manual line break
+ rInf.GetTxt().GetChar( nCutPos ) == CH_BREAK ) )
+ // <--
+ nBreakWidth = nBreakWidth + nItalic;
+
+ // save maximum width for later use
+ if ( nMaxSizeDiff )
+ rInf.SetMaxWidthDiff( (sal_uLong)&rPor, nMaxSizeDiff );
+
+ return sal_True;
+ }
+ }
+
+ sal_Bool bHyph = rInf.IsHyphenate() && !rInf.IsHyphForbud();
+ xub_StrLen nHyphPos = 0;
+
+ // nCutPos is the first character not fitting to the current line
+ // nHyphPos is the first character not fitting to the current line,
+ // considering an additional "-" for hyphenation
+ if( bHyph )
+ {
+ nCutPos = rInf.GetTxtBreak( nLineWidth, nMaxLen, nMaxComp, nHyphPos );
+
+ if ( !nHyphPos && rInf.GetIdx() )
+ nHyphPos = rInf.GetIdx() - 1;
+ }
+ else
+ {
+ nCutPos = rInf.GetTxtBreak( nLineWidth, nMaxLen, nMaxComp );
+
+#if OSL_DEBUG_LEVEL > 1
+ if ( STRING_LEN != nCutPos )
+ {
+ rInf.GetTxtSize( &rSI, rInf.GetIdx(), nCutPos - rInf.GetIdx(),
+ nMaxComp, nMinSize, nMaxSizeDiff );
+ OSL_ENSURE( nMinSize <= nLineWidth, "What a Guess!!!" );
+ }
+#endif
+ }
+
+ if( nCutPos > rInf.GetIdx() + nMaxLen )
+ {
+ // second check if everything fits to line
+ nCutPos = nBreakPos = rInf.GetIdx() + nMaxLen - 1;
+ rInf.GetTxtSize( &rSI, rInf.GetIdx(), nMaxLen, nMaxComp,
+ nMinSize, nMaxSizeDiff );
+
+ nBreakWidth = nMinSize;
+
+ // Der folgende Vergleich sollte eigenlich immer sal_True ergeben, sonst
+ // hat es wohl bei GetTxtBreak einen Pixel-Rundungsfehler gegeben...
+ if ( nBreakWidth <= nLineWidth )
+ {
+ if( nItalic && ( nBreakPos + 1 ) >= rInf.GetTxt().Len() )
+ nBreakWidth = nBreakWidth + nItalic;
+
+ // save maximum width for later use
+ if ( nMaxSizeDiff )
+ rInf.SetMaxWidthDiff( (sal_uLong)&rPor, nMaxSizeDiff );
+
+ return sal_True;
+ }
+ }
+
+ // we have to trigger an underflow for a footnote portion
+ // which does not fit to the current line
+ if ( rPor.IsFtnPortion() )
+ {
+ nBreakPos = rInf.GetIdx();
+ nCutPos = rInf.GetLen();
+ return sal_False;
+ }
+
+ xub_StrLen nPorLen = 0;
+ // do not call the break iterator nCutPos is a blank
+ xub_Unicode cCutChar = rInf.GetTxt().GetChar( nCutPos );
+ if( CH_BLANK == cCutChar || CH_FULL_BLANK == cCutChar )
+ {
+ nBreakPos = nCutPos;
+ xub_StrLen nX = nBreakPos;
+
+ // we step back until a non blank character has been found
+ // or there is only one more character left
+ while( nX && nBreakPos > rInf.GetLineStart() + 1 &&
+ ( CH_BLANK == ( cCutChar = rInf.GetChar( --nX ) ) ||
+ CH_FULL_BLANK == cCutChar ) )
+ --nBreakPos;
+
+ if( nBreakPos > rInf.GetIdx() )
+ nPorLen = nBreakPos - rInf.GetIdx();
+ while( ++nCutPos < rInf.GetTxt().Len() &&
+ ( CH_BLANK == ( cCutChar = rInf.GetChar( nCutPos ) ) ||
+ CH_FULL_BLANK == cCutChar ) )
+ ; // nothing
+
+ nBreakStart = nCutPos;
+ }
+ else if( pBreakIt->GetBreakIter().is() )
+ {
+ // New: We should have a look into the last portion, if it was a
+ // field portion. For this, we expand the text of the field portion
+ // into our string. If the line break position is inside of before
+ // the field portion, we trigger an underflow.
+
+ xub_StrLen nOldIdx = rInf.GetIdx();
+ xub_Unicode cFldChr = 0;
+
+#if OSL_DEBUG_LEVEL > 1
+ XubString aDebugString;
+#endif
+
+ // be careful: a field portion can be both: 0x01 (common field)
+ // or 0x02 (the follow of a footnode)
+ if ( rInf.GetLast() && rInf.GetLast()->InFldGrp() &&
+ ! rInf.GetLast()->IsFtnPortion() &&
+ rInf.GetIdx() > rInf.GetLineStart() &&
+ CH_TXTATR_BREAKWORD ==
+ ( cFldChr = rInf.GetTxt().GetChar( rInf.GetIdx() - 1 ) ) )
+ {
+ SwFldPortion* pFld = (SwFldPortion*)rInf.GetLast();
+ XubString aTxt;
+ pFld->GetExpTxt( rInf, aTxt );
+
+ if ( aTxt.Len() )
+ {
+ nFieldDiff = aTxt.Len() - 1;
+ nCutPos = nCutPos + nFieldDiff;
+ nHyphPos = nHyphPos + nFieldDiff;
+
+#if OSL_DEBUG_LEVEL > 1
+ aDebugString = rInf.GetTxt();
+#endif
+
+ XubString& rOldTxt = (XubString&)rInf.GetTxt();
+ rOldTxt.Erase( rInf.GetIdx() - 1, 1 );
+ rOldTxt.Insert( aTxt, rInf.GetIdx() - 1 );
+ rInf.SetIdx( rInf.GetIdx() + nFieldDiff );
+ }
+ else
+ cFldChr = 0;
+ }
+
+ LineBreakHyphenationOptions aHyphOpt;
+ Reference< XHyphenator > xHyph;
+ if( bHyph )
+ {
+ xHyph = ::GetHyphenator();
+ aHyphOpt = LineBreakHyphenationOptions( xHyph,
+ rInf.GetHyphValues(), nHyphPos );
+ }
+
+ // Get Language for break iterator.
+ // We have to switch the current language if we have a script
+ // change at nCutPos. Otherwise LATIN punctuation would never
+ // be allowed to be hanging punctuation.
+ // NEVER call GetLang if the string has been modified!!!
+ LanguageType aLang = rInf.GetFont()->GetLanguage();
+
+ // If we are inside a field portion, we use a temporar string which
+ // differs from the string at the textnode. Therefore we are not allowed
+ // to call the GetLang function.
+ if ( nCutPos && ! rPor.InFldGrp() )
+ {
+ const CharClass& rCC = GetAppCharClass();
+
+ // step back until a non-punctuation character is reached
+ xub_StrLen nLangIndex = nCutPos;
+
+ // If a field has been expanded right in front of us we do not
+ // step further than the beginning of the expanded field
+ // (which is the position of the field placeholder in our
+ // original string).
+ const xub_StrLen nDoNotStepOver = CH_TXTATR_BREAKWORD == cFldChr ?
+ rInf.GetIdx() - nFieldDiff - 1:
+ 0;
+
+ while ( nLangIndex > nDoNotStepOver &&
+ ! rCC.isLetterNumeric( rInf.GetTxt(), nLangIndex ) )
+ --nLangIndex;
+
+ // last "real" character is not inside our current portion
+ // we have to check the script type of the last "real" character
+ if ( nLangIndex < rInf.GetIdx() )
+ {
+ sal_uInt16 nScript = pBreakIt->GetRealScriptOfText( rInf.GetTxt(),
+ nLangIndex );
+ OSL_ENSURE( nScript, "Script is not between 1 and 4" );
+
+ // compare current script with script from last "real" character
+ if ( nScript - 1 != rInf.GetFont()->GetActual() )
+ aLang = rInf.GetTxtFrm()->GetTxtNode()->GetLang(
+ CH_TXTATR_BREAKWORD == cFldChr ?
+ nDoNotStepOver :
+ nLangIndex, 0, nScript );
+ }
+ }
+
+ const ForbiddenCharacters aForbidden(
+ *rInf.GetTxtFrm()->GetNode()->getIDocumentSettingAccess()->getForbiddenCharacters( aLang, true ) );
+
+ const sal_Bool bAllowHanging = rInf.IsHanging() && ! rInf.IsMulti() &&
+ ! rPor.InFldGrp();
+
+ LineBreakUserOptions aUserOpt(
+ aForbidden.beginLine, aForbidden.endLine,
+ rInf.HasForbiddenChars(), bAllowHanging, sal_False );
+
+ //! register listener to LinguServiceEvents now in order to get
+ //! notified about relevant changes in the future
+ SwModule *pModule = SW_MOD();
+ if (!pModule->GetLngSvcEvtListener().is())
+ pModule->CreateLngSvcEvtListener();
+
+ // !!! We must have a local copy of the locale, because inside
+ // getLineBreak the LinguEventListener can trigger a new formatting,
+ // which can corrupt the locale pointer inside pBreakIt.
+ const lang::Locale aLocale = pBreakIt->GetLocale( aLang );
+
+ // determines first possible line break from nRightPos to
+ // start index of current line
+ LineBreakResults aResult = pBreakIt->GetBreakIter()->getLineBreak(
+ rInf.GetTxt(), nCutPos, aLocale,
+ rInf.GetLineStart(), aHyphOpt, aUserOpt );
+
+ nBreakPos = (xub_StrLen)aResult.breakIndex;
+
+ // if we are formatting multi portions we want to allow line breaks
+ // at the border between single line and multi line portion
+ // we have to be carefull with footnote portions, they always come in
+ // with an index 0
+ if ( nBreakPos < rInf.GetLineStart() && rInf.IsFirstMulti() &&
+ ! rInf.IsFtnInside() )
+ nBreakPos = rInf.GetLineStart();
+
+ nBreakStart = nBreakPos;
+
+ bHyph = BreakType::HYPHENATION == aResult.breakType;
+
+ if ( bHyph && nBreakPos != STRING_LEN)
+ {
+ // found hyphenation position within line
+ // nBreakPos is set to the hyphenation position
+ xHyphWord = aResult.rHyphenatedWord;
+ nBreakPos += xHyphWord->getHyphenationPos() + 1;
+
+#if OSL_DEBUG_LEVEL > 1
+ // e.g., Schif-fahrt, referes to our string
+ const String aWord = xHyphWord->getWord();
+ // e.g., Schiff-fahrt, referes to the word after hyphenation
+ const String aHyphenatedWord = xHyphWord->getHyphenatedWord();
+ // e.g., Schif-fahrt: 5, referes to our string
+ const sal_uInt16 nHyphenationPos = xHyphWord->getHyphenationPos();
+ (void)nHyphenationPos;
+ // e.g., Schiff-fahrt: 6, referes to the word after hyphenation
+ const sal_uInt16 nHyphenPos = xHyphWord->getHyphenPos();
+ (void)nHyphenPos;
+#endif
+
+ // if not in interactive mode, we have to break behind a soft hyphen
+ if ( ! rInf.IsInterHyph() && rInf.GetIdx() )
+ {
+ const long nSoftHyphPos =
+ xHyphWord->getWord().indexOf( CHAR_SOFTHYPHEN );
+
+ if ( nSoftHyphPos >= 0 &&
+ nBreakStart + nSoftHyphPos <= nBreakPos &&
+ nBreakPos > rInf.GetLineStart() )
+ nBreakPos = rInf.GetIdx() - 1;
+ }
+
+ if( nBreakPos >= rInf.GetIdx() )
+ {
+ nPorLen = nBreakPos - rInf.GetIdx();
+ if( '-' == rInf.GetTxt().GetChar( nBreakPos - 1 ) )
+ xHyphWord = NULL;
+ }
+ }
+ else if ( !bHyph && nBreakPos >= rInf.GetLineStart() )
+ {
+ OSL_ENSURE( nBreakPos != STRING_LEN, "we should have found a break pos" );
+
+ // found break position within line
+ xHyphWord = NULL;
+
+ // check, if break position is soft hyphen and an underflow
+ // has to be triggered
+ if( nBreakPos > rInf.GetLineStart() && rInf.GetIdx() &&
+ CHAR_SOFTHYPHEN == rInf.GetTxt().GetChar( nBreakPos - 1 ) )
+ nBreakPos = rInf.GetIdx() - 1;
+
+ // Delete any blanks at the end of a line, but be careful:
+ // If a field has been expanded, we do not want to delete any
+ // blanks inside the field portion. This would cause an unwanted
+ // underflow
+ xub_StrLen nX = nBreakPos;
+ while( nX > rInf.GetLineStart() &&
+ ( CH_TXTATR_BREAKWORD != cFldChr || nX > rInf.GetIdx() ) &&
+ ( CH_BLANK == rInf.GetChar( --nX ) ||
+ CH_FULL_BLANK == rInf.GetChar( nX ) ) )
+ nBreakPos = nX;
+ if( nBreakPos > rInf.GetIdx() )
+ nPorLen = nBreakPos - rInf.GetIdx();
+ }
+ else
+ {
+ // no line break found, setting nBreakPos to STRING_LEN
+ // causes a break cut
+ nBreakPos = STRING_LEN;
+ OSL_ENSURE( nCutPos >= rInf.GetIdx(), "Deep cut" );
+ nPorLen = nCutPos - rInf.GetIdx();
+ }
+
+ if( nBreakPos > nCutPos && nBreakPos != STRING_LEN )
+ {
+ const xub_StrLen nHangingLen = nBreakPos - nCutPos;
+ SwPosSize aTmpSize = rInf.GetTxtSize( &rSI, nCutPos,
+ nHangingLen, 0 );
+ OSL_ENSURE( !pHanging, "A hanging portion is hanging around" );
+ pHanging = new SwHangingPortion( aTmpSize );
+ pHanging->SetLen( nHangingLen );
+ nPorLen = nCutPos - rInf.GetIdx();
+ }
+
+ // If we expanded a field, we must repair the original string.
+ // In case we do not trigger an underflow, we correct the nBreakPos
+ // value, but we cannot correct the nBreakStart value:
+ // If we have found a hyphenation position, nBreakStart can lie before
+ // the field.
+ if ( CH_TXTATR_BREAKWORD == cFldChr )
+ {
+ if ( nBreakPos < rInf.GetIdx() )
+ nBreakPos = nOldIdx - 1;
+ else if ( STRING_LEN != nBreakPos )
+ {
+ OSL_ENSURE( nBreakPos >= nFieldDiff, "I've got field trouble!" );
+ nBreakPos = nBreakPos - nFieldDiff;
+ }
+
+ OSL_ENSURE( nCutPos >= rInf.GetIdx() && nCutPos >= nFieldDiff,
+ "I've got field trouble, part2!" );
+ nCutPos = nCutPos - nFieldDiff;
+
+ XubString& rOldTxt = (XubString&)rInf.GetTxt();
+ rOldTxt.Erase( nOldIdx - 1, nFieldDiff + 1 );
+ rOldTxt.Insert( cFldChr, nOldIdx - 1 );
+ rInf.SetIdx( nOldIdx );
+
+#if OSL_DEBUG_LEVEL > 1
+ OSL_ENSURE( aDebugString == rInf.GetTxt(),
+ "Somebody, somebody, somebody put something in my string" );
+#endif
+ }
+ }
+
+ if( nPorLen )
+ {
+ rInf.GetTxtSize( &rSI, rInf.GetIdx(), nPorLen,
+ nMaxComp, nMinSize, nMaxSizeDiff );
+
+ // save maximum width for later use
+ if ( nMaxSizeDiff )
+ rInf.SetMaxWidthDiff( (sal_uLong)&rPor, nMaxSizeDiff );
+
+ nBreakWidth = nItalic + nMinSize;
+ }
+ else
+ nBreakWidth = 0;
+
+ if( pHanging )
+ nBreakPos = nCutPos;
+
+ return sal_False;
+}
+
+/*************************************************************************
+ * SwTxtGuess::AlternativeSpelling
+ *************************************************************************/
+
+// returns true if word at position nPos has a diffenrent spelling
+// if hyphenated at this position (old german spelling)
+
+sal_Bool SwTxtGuess::AlternativeSpelling( const SwTxtFormatInfo &rInf,
+ const xub_StrLen nPos )
+{
+ // get word boundaries
+ xub_StrLen nWordLen;
+
+ Boundary aBound =
+ pBreakIt->GetBreakIter()->getWordBoundary( rInf.GetTxt(), nPos,
+ pBreakIt->GetLocale( rInf.GetFont()->GetLanguage() ),
+ WordType::DICTIONARY_WORD, sal_True );
+ nBreakStart = (xub_StrLen)aBound.startPos;
+ nWordLen = static_cast<xub_StrLen>(aBound.endPos - nBreakStart);
+
+ // if everything else fails, we want to cut at nPos
+ nCutPos = nPos;
+
+ XubString aTxt( rInf.GetTxt().Copy( nBreakStart, nWordLen ) );
+
+ // check, if word has alternative spelling
+ Reference< XHyphenator > xHyph( ::GetHyphenator() );
+ OSL_ENSURE( xHyph.is(), "Hyphenator is missing");
+ //! subtract 1 since the UNO-interface is 0 based
+ xHyphWord = xHyph->queryAlternativeSpelling( OUString(aTxt),
+ pBreakIt->GetLocale( rInf.GetFont()->GetLanguage() ),
+ nPos - nBreakStart, rInf.GetHyphValues() );
+ return xHyphWord.is() && xHyphWord->isAlternativeSpelling();
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/text/guess.hxx b/sw/source/core/text/guess.hxx
new file mode 100644
index 000000000000..3f2e457a609e
--- /dev/null
+++ b/sw/source/core/text/guess.hxx
@@ -0,0 +1,76 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+#ifndef _GUESS_HXX
+#define _GUESS_HXX
+#include <com/sun/star/linguistic2/XHyphenatedWord.hpp>
+
+#include "txttypes.hxx"
+#include "breakit.hxx"
+#include "porrst.hxx" // SwHangingPortion
+
+class SwTxtFormatInfo;
+
+/*************************************************************************
+ * class SwTxtGuess
+ *************************************************************************/
+
+class SwTxtGuess
+{
+ ::com::sun::star::uno::Reference< ::com::sun::star::linguistic2::XHyphenatedWord > xHyphWord;
+ SwHangingPortion *pHanging; // for hanging punctuation
+ xub_StrLen nCutPos; // this character doesn't fit
+ xub_StrLen nBreakStart; // start index of word containing line break
+ xub_StrLen nBreakPos; // start index of break position
+ xub_StrLen nFieldDiff; // absolut positions can be wrong if we
+ // a field in the text has been expanded
+ KSHORT nBreakWidth; // width of the broken portion
+public:
+ inline SwTxtGuess(): pHanging( NULL ), nCutPos(0), nBreakStart(0),
+ nBreakPos(0), nFieldDiff(0), nBreakWidth(0)
+ { }
+ ~SwTxtGuess() { delete pHanging; }
+
+ // true, if current portion still fits to current line
+ sal_Bool Guess( const SwTxtPortion& rPor, SwTxtFormatInfo &rInf,
+ const KSHORT nHeight );
+ sal_Bool AlternativeSpelling( const SwTxtFormatInfo &rInf, const xub_StrLen nPos );
+
+ inline SwHangingPortion* GetHangingPortion() const { return pHanging; }
+ inline void ClearHangingPortion() { pHanging = NULL; }
+ inline KSHORT BreakWidth() const { return nBreakWidth; }
+ inline xub_StrLen CutPos() const { return nCutPos; }
+ inline xub_StrLen BreakStart() const { return nBreakStart; }
+ inline xub_StrLen BreakPos() const {return nBreakPos; }
+ inline xub_StrLen FieldDiff() const {return nFieldDiff; }
+ inline ::com::sun::star::uno::Reference< ::com::sun::star::linguistic2::XHyphenatedWord > HyphWord() const
+ { return xHyphWord; }
+};
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/text/inftxt.cxx b/sw/source/core/text/inftxt.cxx
new file mode 100644
index 000000000000..f9e2f8f203b5
--- /dev/null
+++ b/sw/source/core/text/inftxt.cxx
@@ -0,0 +1,1942 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+
+#include <com/sun/star/uno/Sequence.h>
+#include <unotools/linguprops.hxx>
+#include <unotools/lingucfg.hxx>
+#include <hintids.hxx>
+#include <sfx2/printer.hxx>
+#include <editeng/hyznitem.hxx>
+#include <editeng/escpitem.hxx>
+#include <editeng/hngpnctitem.hxx>
+#include <editeng/scriptspaceitem.hxx>
+#include <editeng/brshitem.hxx>
+#include <editeng/splwrap.hxx>
+#include <editeng/pgrditem.hxx>
+#include <editeng/tstpitem.hxx>
+
+#include <SwSmartTagMgr.hxx>
+#include <linguistic/lngprops.hxx>
+#include <editeng/unolingu.hxx>
+#include <breakit.hxx>
+#include <editeng/forbiddenruleitem.hxx>
+#include <txatbase.hxx>
+#include <fmtinfmt.hxx>
+#include <swmodule.hxx>
+#include <vcl/svapp.hxx>
+#include <vcl/wrkwin.hxx>
+#include <viewsh.hxx> // ViewShell
+#include <viewopt.hxx> // SwViewOptions
+#include <frmtool.hxx> // DrawGraphic
+#include <IDocumentSettingAccess.hxx>
+#include <IDocumentDeviceAccess.hxx>
+#include <paratr.hxx> // SwFmtDrop
+#include <rootfrm.hxx> // SwRootFrm
+#include <inftxt.hxx> // SwTxtInfo
+#include <blink.hxx> // SwBlink
+#include <noteurl.hxx> // SwNoteURL
+#include <porftn.hxx> // SwFtnPortion
+#include <porrst.hxx> // SwHangingPortion
+#include <itratr.hxx>
+#include <accessibilityoptions.hxx>
+#include <wrong.hxx>
+#include <doc.hxx>
+#include <pam.hxx>
+#include <SwGrammarMarkUp.hxx>
+#include <cstdio>
+// --> FME 2004-06-08 #i12836# enhanced pdf export
+#include <EnhancedPDFExportHelper.hxx>
+// <--
+
+#include <unomid.h>
+
+#ifdef DEBUG
+#include <stdio.h>
+#endif
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::linguistic2;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::beans;
+
+
+#define CHAR_UNDERSCORE ((sal_Unicode)0x005F)
+#define CHAR_LEFT_ARROW ((sal_Unicode)0x25C0)
+#define CHAR_RIGHT_ARROW ((sal_Unicode)0x25B6)
+#define CHAR_TAB ((sal_Unicode)0x2192)
+#define CHAR_TAB_RTL ((sal_Unicode)0x2190)
+#define CHAR_LINEBREAK ((sal_Unicode)0x21B5)
+#define CHAR_LINEBREAK_RTL ((sal_Unicode)0x21B3)
+
+#define DRAW_SPECIAL_OPTIONS_CENTER 1
+#define DRAW_SPECIAL_OPTIONS_ROTATE 2
+
+// --> OD 2006-06-27 #b6440955#
+// variable moved to class <numfunc:GetDefBulletConfig>
+//extern const sal_Char sBulletFntName[];
+namespace numfunc
+{
+ extern const String& GetDefBulletFontname();
+ extern bool IsDefBulletFontUserDefined();
+}
+// <--
+
+#if OSL_DEBUG_LEVEL > 1
+// Test2: WYSIWYG++
+// Test4: WYSIWYG debug
+static sal_Bool bDbgLow = sal_False;
+#endif
+
+#if OSL_DEBUG_LEVEL > 1
+sal_Bool SwTxtSizeInfo::IsOptCalm() const { return !GetOpt().IsTest3(); }
+sal_Bool SwTxtSizeInfo::IsOptLow() const { return bDbgLow; }
+sal_Bool SwTxtSizeInfo::IsOptDbg() const { return GetOpt().IsTest4(); }
+sal_Bool SwTxtSizeInfo::IsOptTest1() const { return GetOpt().IsTest1(); }
+sal_Bool SwTxtSizeInfo::IsOptTest2() const { return GetOpt().IsTest2(); }
+sal_Bool SwTxtSizeInfo::IsOptTest3() const { return GetOpt().IsTest3(); }
+sal_Bool SwTxtSizeInfo::IsOptTest4() const { return GetOpt().IsTest4(); }
+sal_Bool SwTxtSizeInfo::IsOptTest5() const { return GetOpt().IsTest5(); }
+sal_Bool SwTxtSizeInfo::IsOptTest6() const { return GetOpt().IsTest6(); }
+sal_Bool SwTxtSizeInfo::IsOptTest7() const { return GetOpt().IsTest7(); }
+sal_Bool SwTxtSizeInfo::IsOptTest8() const { return GetOpt().IsTest8(); }
+#endif
+
+/*************************************************************************
+ * SwLineInfo::SwLineInfo()
+ *************************************************************************/
+
+SwLineInfo::SwLineInfo()
+ : pRuler( 0 ),
+ pSpace( 0 ),
+ nVertAlign( 0 ),
+ nDefTabStop( 0 ),
+ bListTabStopIncluded( false ),
+ nListTabStopPosition( 0 )
+{
+}
+
+SwLineInfo::~SwLineInfo()
+{
+ delete pRuler;
+}
+void SwLineInfo::CtorInitLineInfo( const SwAttrSet& rAttrSet,
+ const SwTxtNode& rTxtNode )
+{
+ delete pRuler;
+ pRuler = new SvxTabStopItem( rAttrSet.GetTabStops() );
+ if ( rTxtNode.GetListTabStopPosition( nListTabStopPosition ) )
+ {
+ bListTabStopIncluded = true;
+
+ // insert the list tab stop into SvxTabItem instance <pRuler>
+ const SvxTabStop aListTabStop( nListTabStopPosition,
+ SVX_TAB_ADJUST_LEFT );
+ pRuler->Insert( aListTabStop );
+
+ // remove default tab stops, which are before the inserted list tab stop
+ for ( sal_uInt16 i = 0; i < pRuler->Count(); i++ )
+ {
+ if ( (*pRuler)[i].GetTabPos() < nListTabStopPosition &&
+ (*pRuler)[i].GetAdjustment() == SVX_TAB_ADJUST_DEFAULT )
+ {
+ pRuler->Remove(i);
+ continue;
+ }
+ }
+ }
+
+ if ( !rTxtNode.getIDocumentSettingAccess()->get(IDocumentSettingAccess::TABS_RELATIVE_TO_INDENT) )
+ {
+ // remove default tab stop at position 0
+ for ( sal_uInt16 i = 0; i < pRuler->Count(); i++ )
+ {
+ if ( (*pRuler)[i].GetTabPos() == 0 &&
+ (*pRuler)[i].GetAdjustment() == SVX_TAB_ADJUST_DEFAULT )
+ {
+ pRuler->Remove(i);
+ break;
+ }
+ }
+ }
+
+ pSpace = &rAttrSet.GetLineSpacing();
+ nVertAlign = rAttrSet.GetParaVertAlign().GetValue();
+ nDefTabStop = MSHRT_MAX;
+}
+
+/*************************************************************************
+ * SwTxtInfo::CtorInitTxtInfo()
+ *************************************************************************/
+
+void SwTxtInfo::CtorInitTxtInfo( SwTxtFrm *pFrm )
+{
+ pPara = pFrm->GetPara();
+ nTxtStart = pFrm->GetOfst();
+ if( !pPara )
+ {
+ OSL_ENSURE( pPara, "+SwTxtInfo::CTOR: missing paragraph information" );
+ pFrm->Format();
+ pPara = pFrm->GetPara();
+ }
+}
+
+SwTxtInfo::SwTxtInfo( const SwTxtInfo &rInf )
+ : pPara( ((SwTxtInfo&)rInf).GetParaPortion() ),
+ nTxtStart( rInf.GetTxtStart() )
+{ }
+
+
+#if OSL_DEBUG_LEVEL > 1
+/*************************************************************************
+ * ChkOutDev()
+ *************************************************************************/
+
+void ChkOutDev( const SwTxtSizeInfo &rInf )
+{
+ if ( !rInf.GetVsh() )
+ return;
+
+ const OutputDevice* pOut = rInf.GetOut();
+ const OutputDevice* pRef = rInf.GetRefDev();
+ OSL_ENSURE( pOut && pRef, "ChkOutDev: invalid output devices" );
+}
+#endif // PRODUCT
+
+
+inline xub_StrLen GetMinLen( const SwTxtSizeInfo &rInf )
+{
+ const xub_StrLen nInfLen = rInf.GetIdx() + rInf.GetLen();
+ return Min( rInf.GetTxt().Len(), nInfLen );
+}
+
+
+SwTxtSizeInfo::SwTxtSizeInfo( const SwTxtSizeInfo &rNew )
+ : SwTxtInfo( rNew ),
+ pKanaComp(((SwTxtSizeInfo&)rNew).GetpKanaComp()),
+ pVsh(((SwTxtSizeInfo&)rNew).GetVsh()),
+ pOut(((SwTxtSizeInfo&)rNew).GetOut()),
+ pRef(((SwTxtSizeInfo&)rNew).GetRefDev()),
+ pFnt(((SwTxtSizeInfo&)rNew).GetFont()),
+ pUnderFnt(((SwTxtSizeInfo&)rNew).GetUnderFnt()),
+ pFrm(rNew.pFrm),
+ pOpt(&rNew.GetOpt()),
+ pTxt(&rNew.GetTxt()),
+ nIdx(rNew.GetIdx()),
+ nLen(rNew.GetLen()),
+ nKanaIdx( rNew.GetKanaIdx() ),
+ bOnWin( rNew.OnWin() ),
+ bNotEOL( rNew.NotEOL() ),
+ bURLNotify( rNew.URLNotify() ),
+ bStopUnderFlow( rNew.StopUnderFlow() ),
+ bFtnInside( rNew.IsFtnInside() ),
+ bOtherThanFtnInside( rNew.IsOtherThanFtnInside() ),
+ bMulti( rNew.IsMulti() ),
+ bFirstMulti( rNew.IsFirstMulti() ),
+ bRuby( rNew.IsRuby() ),
+ bHanging( rNew.IsHanging() ),
+ bScriptSpace( rNew.HasScriptSpace() ),
+ bForbiddenChars( rNew.HasForbiddenChars() ),
+ bSnapToGrid( rNew.SnapToGrid() ),
+ nDirection( rNew.GetDirection() )
+{
+#if OSL_DEBUG_LEVEL > 1
+ ChkOutDev( *this );
+#endif
+}
+
+void SwTxtSizeInfo::CtorInitTxtSizeInfo( SwTxtFrm *pFrame, SwFont *pNewFnt,
+ const xub_StrLen nNewIdx, const xub_StrLen nNewLen )
+{
+ pKanaComp = NULL;
+ nKanaIdx = 0;
+ pFrm = pFrame;
+ CtorInitTxtInfo( pFrm );
+ const SwTxtNode *pNd = pFrm->GetTxtNode();
+ pVsh = pFrm->getRootFrm()->GetCurrShell();
+
+ // Get the output and reference device
+ if ( pVsh )
+ {
+ pOut = pVsh->GetOut();
+ pRef = &pVsh->GetRefDev();
+ bOnWin = pVsh->GetWin() || OUTDEV_WINDOW == pOut->GetOutDevType();
+ }
+ else
+ {
+ //Zugriff ueber StarONE, es muss keine Shell existieren oder aktiv sein.
+ if ( pNd->getIDocumentSettingAccess()->get(IDocumentSettingAccess::HTML_MODE) )
+ {
+ //in Ermangelung eines Besseren kann hier ja wohl nur noch das
+ //AppWin genommen werden?
+ pOut = GetpApp()->GetDefaultDevice();
+ }
+ else
+ pOut = pNd->getIDocumentDeviceAccess()->getPrinter( false );
+
+ pRef = pOut;
+ }
+
+#if OSL_DEBUG_LEVEL > 1
+ ChkOutDev( *this );
+#endif
+
+ // Set default layout mode ( LTR or RTL ).
+ if ( pFrm->IsRightToLeft() )
+ {
+ pOut->SetLayoutMode( TEXT_LAYOUT_BIDI_STRONG | TEXT_LAYOUT_BIDI_RTL );
+ pRef->SetLayoutMode( TEXT_LAYOUT_BIDI_STRONG | TEXT_LAYOUT_BIDI_RTL );
+ nDirection = DIR_RIGHT2LEFT;
+ }
+ else
+ {
+ pOut->SetLayoutMode( TEXT_LAYOUT_BIDI_STRONG );
+ pRef->SetLayoutMode( TEXT_LAYOUT_BIDI_STRONG );
+ nDirection = DIR_LEFT2RIGHT;
+ }
+
+ //
+ // The Options
+ //
+ pOpt = pVsh ?
+ pVsh->GetViewOptions() :
+ SW_MOD()->GetViewOption( pNd->getIDocumentSettingAccess()->get(IDocumentSettingAccess::HTML_MODE) ); //Options vom Module wg. StarONE
+
+ // bURLNotify wird gesetzt, wenn MakeGraphic dies vorbereitet
+ // TODO: Aufdr?seln
+ bURLNotify = pNoteURL && !bOnWin;
+
+ SetSnapToGrid( pNd->GetSwAttrSet().GetParaGrid().GetValue() &&
+ pFrm->IsInDocBody() );
+
+ pFnt = pNewFnt;
+ pUnderFnt = 0;
+ pTxt = &pNd->GetTxt();
+
+ nIdx = nNewIdx;
+ nLen = nNewLen;
+ bNotEOL = sal_False;
+ bStopUnderFlow = bFtnInside = bOtherThanFtnInside = sal_False;
+ bMulti = bFirstMulti = bRuby = bHanging = bScriptSpace =
+ bForbiddenChars = sal_False;
+
+ SetLen( GetMinLen( *this ) );
+}
+
+SwTxtSizeInfo::SwTxtSizeInfo( const SwTxtSizeInfo &rNew, const XubString &rTxt,
+ const xub_StrLen nIndex, const xub_StrLen nLength )
+ : SwTxtInfo( rNew ),
+ pKanaComp(((SwTxtSizeInfo&)rNew).GetpKanaComp()),
+ pVsh(((SwTxtSizeInfo&)rNew).GetVsh()),
+ pOut(((SwTxtSizeInfo&)rNew).GetOut()),
+ pRef(((SwTxtSizeInfo&)rNew).GetRefDev()),
+ pFnt(((SwTxtSizeInfo&)rNew).GetFont()),
+ pUnderFnt(((SwTxtSizeInfo&)rNew).GetUnderFnt()),
+ pFrm( rNew.pFrm ),
+ pOpt(&rNew.GetOpt()),
+ pTxt(&rTxt),
+ nIdx(nIndex),
+ nLen(nLength),
+ nKanaIdx( rNew.GetKanaIdx() ),
+ bOnWin( rNew.OnWin() ),
+ bNotEOL( rNew.NotEOL() ),
+ bURLNotify( rNew.URLNotify() ),
+ bStopUnderFlow( rNew.StopUnderFlow() ),
+ bFtnInside( rNew.IsFtnInside() ),
+ bOtherThanFtnInside( rNew.IsOtherThanFtnInside() ),
+ bMulti( rNew.IsMulti() ),
+ bFirstMulti( rNew.IsFirstMulti() ),
+ bRuby( rNew.IsRuby() ),
+ bHanging( rNew.IsHanging() ),
+ bScriptSpace( rNew.HasScriptSpace() ),
+ bForbiddenChars( rNew.HasForbiddenChars() ),
+ bSnapToGrid( rNew.SnapToGrid() ),
+ nDirection( rNew.GetDirection() )
+{
+#if OSL_DEBUG_LEVEL > 1
+ ChkOutDev( *this );
+#endif
+ SetLen( GetMinLen( *this ) );
+}
+
+/*************************************************************************
+ * SwTxtSizeInfo::SelectFont()
+ *************************************************************************/
+
+void SwTxtSizeInfo::SelectFont()
+{
+ // 8731: Der Weg muss ueber ChgPhysFnt gehen, sonst geraet
+ // der FontMetricCache durcheinander. In diesem Fall steht pLastMet
+ // auf dem alten Wert.
+ // Falsch: GetOut()->SetFont( GetFont()->GetFnt() );
+ GetFont()->Invalidate();
+ GetFont()->ChgPhysFnt( pVsh, *GetOut() );
+}
+
+/*************************************************************************
+ * SwTxtSizeInfo::NoteAnimation()
+ *************************************************************************/
+
+void SwTxtSizeInfo::NoteAnimation() const
+{
+ if( OnWin() )
+ SwRootFrm::FlushVout();
+
+ OSL_ENSURE( pOut == pVsh->GetOut(),
+ "SwTxtSizeInfo::NoteAnimation() changed pOut" );
+}
+
+/*************************************************************************
+ * SwTxtSizeInfo::GetTxtSize()
+ *************************************************************************/
+
+SwPosSize SwTxtSizeInfo::GetTxtSize( OutputDevice* pOutDev,
+ const SwScriptInfo* pSI,
+ const XubString& rTxt,
+ const xub_StrLen nIndex,
+ const xub_StrLen nLength,
+ const sal_uInt16 nComp ) const
+{
+ SwDrawTextInfo aDrawInf( pVsh, *pOutDev, pSI, rTxt, nIndex, nLength );
+ aDrawInf.SetFrm( pFrm );
+ aDrawInf.SetFont( pFnt );
+ aDrawInf.SetSnapToGrid( SnapToGrid() );
+ aDrawInf.SetKanaComp( nComp );
+ SwPosSize aSize = pFnt->_GetTxtSize( aDrawInf );
+ return aSize;
+}
+
+/*************************************************************************
+ * SwTxtSizeInfo::GetTxtSize()
+ *************************************************************************/
+
+SwPosSize SwTxtSizeInfo::GetTxtSize() const
+{
+ const SwScriptInfo& rSI =
+ ( (SwParaPortion*)GetParaPortion() )->GetScriptInfo();
+
+ // in some cases, compression is not allowed or surpressed for
+ // performance reasons
+ sal_uInt16 nComp =( SW_CJK == GetFont()->GetActual() &&
+ rSI.CountCompChg() &&
+ ! IsMulti() ) ?
+ GetKanaComp() :
+ 0 ;
+
+ SwDrawTextInfo aDrawInf( pVsh, *pOut, &rSI, *pTxt, nIdx, nLen );
+ aDrawInf.SetFrm( pFrm );
+ aDrawInf.SetFont( pFnt );
+ aDrawInf.SetSnapToGrid( SnapToGrid() );
+ aDrawInf.SetKanaComp( nComp );
+ return pFnt->_GetTxtSize( aDrawInf );
+}
+
+/*************************************************************************
+ * SwTxtSizeInfo::GetTxtSize()
+ *************************************************************************/
+
+void SwTxtSizeInfo::GetTxtSize( const SwScriptInfo* pSI, const xub_StrLen nIndex,
+ const xub_StrLen nLength, const sal_uInt16 nComp,
+ sal_uInt16& nMinSize, sal_uInt16& nMaxSizeDiff ) const
+{
+ SwDrawTextInfo aDrawInf( pVsh, *pOut, pSI, *pTxt, nIndex, nLength );
+ aDrawInf.SetFrm( pFrm );
+ aDrawInf.SetFont( pFnt );
+ aDrawInf.SetSnapToGrid( SnapToGrid() );
+ aDrawInf.SetKanaComp( nComp );
+ SwPosSize aSize = pFnt->_GetTxtSize( aDrawInf );
+ nMaxSizeDiff = (sal_uInt16)aDrawInf.GetKanaDiff();
+ nMinSize = aSize.Width();
+}
+
+/*************************************************************************
+ * SwTxtSizeInfo::GetTxtBreak()
+ *************************************************************************/
+
+xub_StrLen SwTxtSizeInfo::GetTxtBreak( const long nLineWidth,
+ const xub_StrLen nMaxLen,
+ const sal_uInt16 nComp ) const
+{
+ const SwScriptInfo& rScriptInfo =
+ ( (SwParaPortion*)GetParaPortion() )->GetScriptInfo();
+
+ OSL_ENSURE( pRef == pOut, "GetTxtBreak is supposed to use the RefDev" );
+ SwDrawTextInfo aDrawInf( pVsh, *pOut, &rScriptInfo,
+ *pTxt, GetIdx(), nMaxLen );
+ aDrawInf.SetFrm( pFrm );
+ aDrawInf.SetFont( pFnt );
+ aDrawInf.SetSnapToGrid( SnapToGrid() );
+ aDrawInf.SetKanaComp( nComp );
+ aDrawInf.SetHyphPos( 0 );
+
+ return pFnt->GetTxtBreak( aDrawInf, nLineWidth );
+}
+
+/*************************************************************************
+ * SwTxtSizeInfo::GetTxtBreak()
+ *************************************************************************/
+
+xub_StrLen SwTxtSizeInfo::GetTxtBreak( const long nLineWidth,
+ const xub_StrLen nMaxLen,
+ const sal_uInt16 nComp,
+ xub_StrLen& rExtraCharPos ) const
+{
+ const SwScriptInfo& rScriptInfo =
+ ( (SwParaPortion*)GetParaPortion() )->GetScriptInfo();
+
+ OSL_ENSURE( pRef == pOut, "GetTxtBreak is supposed to use the RefDev" );
+ SwDrawTextInfo aDrawInf( pVsh, *pOut, &rScriptInfo,
+ *pTxt, GetIdx(), nMaxLen );
+ aDrawInf.SetFrm( pFrm );
+ aDrawInf.SetFont( pFnt );
+ aDrawInf.SetSnapToGrid( SnapToGrid() );
+ aDrawInf.SetKanaComp( nComp );
+ aDrawInf.SetHyphPos( &rExtraCharPos );
+
+ return pFnt->GetTxtBreak( aDrawInf, nLineWidth );
+}
+
+/*************************************************************************
+ * SwTxtPaintInfo::CtorInitTxtPaintInfo()
+ *************************************************************************/
+
+void SwTxtPaintInfo::CtorInitTxtPaintInfo( SwTxtFrm *pFrame, const SwRect &rPaint )
+{
+ CtorInitTxtSizeInfo( pFrame );
+ aTxtFly.CtorInitTxtFly( pFrame ),
+ aPaintRect = rPaint;
+ nSpaceIdx = 0;
+ pSpaceAdd = NULL;
+ pWrongList = NULL;
+ pGrammarCheckList = NULL;
+ pSmartTags = NULL; // SMARTTAGS
+
+#if OSL_DEBUG_LEVEL > 1
+ pBrushItem = ((SvxBrushItem*)-1);
+#else
+ pBrushItem = 0;
+#endif
+}
+
+SwTxtPaintInfo::SwTxtPaintInfo( const SwTxtPaintInfo &rInf, const XubString &rTxt )
+ : SwTxtSizeInfo( rInf, rTxt ),
+ pWrongList( rInf.GetpWrongList() ),
+ pGrammarCheckList( rInf.GetGrammarCheckList() ),
+ pSmartTags( rInf.GetSmartTags() ), // SMARTTAGS
+ pSpaceAdd( rInf.GetpSpaceAdd() ),
+ pBrushItem( rInf.GetBrushItem() ),
+ aTxtFly( *rInf.GetTxtFly() ),
+ aPos( rInf.GetPos() ),
+ aPaintRect( rInf.GetPaintRect() ),
+ nSpaceIdx( rInf.GetSpaceIdx() )
+{ }
+
+SwTxtPaintInfo::SwTxtPaintInfo( const SwTxtPaintInfo &rInf )
+ : SwTxtSizeInfo( rInf ),
+ pWrongList( rInf.GetpWrongList() ),
+ pGrammarCheckList( rInf.GetGrammarCheckList() ),
+ pSmartTags( rInf.GetSmartTags() ), // SMARTTAGS
+ pSpaceAdd( rInf.GetpSpaceAdd() ),
+ pBrushItem( rInf.GetBrushItem() ),
+ aTxtFly( *rInf.GetTxtFly() ),
+ aPos( rInf.GetPos() ),
+ aPaintRect( rInf.GetPaintRect() ),
+ nSpaceIdx( rInf.GetSpaceIdx() )
+{ }
+
+extern Color aGlobalRetoucheColor;
+
+/*************************************************************************
+ * lcl_IsDarkBackground
+ *
+ * Returns if the current background color is dark.
+ *************************************************************************/
+
+sal_Bool lcl_IsDarkBackground( const SwTxtPaintInfo& rInf )
+{
+ const Color* pCol = rInf.GetFont()->GetBackColor();
+ if( ! pCol || COL_TRANSPARENT == pCol->GetColor() )
+ {
+ const SvxBrushItem* pItem;
+ SwRect aOrigBackRect;
+
+ /// OD 21.08.2002
+ /// consider, that [GetBackgroundBrush(...)] can set <pCol>
+ /// - see implementation in /core/layout/paintfrm.cxx
+ /// OD 21.08.2002 #99657#
+ /// There is a background color, if there is a background brush and
+ /// its color is *not* "no fill"/"auto fill".
+ if( rInf.GetTxtFrm()->GetBackgroundBrush( pItem, pCol, aOrigBackRect, sal_False ) )
+ {
+ if ( !pCol )
+ pCol = &pItem->GetColor();
+
+ /// OD 30.08.2002 #99657#
+ /// determined color <pCol> can be <COL_TRANSPARENT>. Thus, check it.
+ if ( pCol->GetColor() == COL_TRANSPARENT)
+ pCol = NULL;
+ }
+ else
+ pCol = NULL;
+ }
+
+
+ if( !pCol )
+ pCol = &aGlobalRetoucheColor;
+
+ return pCol->IsDark();
+}
+
+/*************************************************************************
+ * SwTxtPaintInfo::_DrawText()
+ *************************************************************************/
+
+void SwTxtPaintInfo::_DrawText( const XubString &rText, const SwLinePortion &rPor,
+ const xub_StrLen nStart, const xub_StrLen nLength,
+ const sal_Bool bKern, const sal_Bool bWrong,
+ const sal_Bool bSmartTag,
+ const sal_Bool bGrammarCheck ) // SMARTTAGS
+{
+ if( !nLength )
+ return;
+
+ if( GetFont()->IsBlink() && OnWin() && rPor.Width() )
+ {
+ // check if accessibility options allow blinking portions:
+ const ViewShell* pSh = GetTxtFrm()->getRootFrm()->GetCurrShell();
+ if ( pSh && ! pSh->GetAccessibilityOptions()->IsStopAnimatedText() &&
+ ! pSh->IsPreView() )
+ {
+ if( !pBlink )
+ pBlink = new SwBlink();
+
+ Point aPoint( aPos );
+
+ if ( GetTxtFrm()->IsRightToLeft() )
+ GetTxtFrm()->SwitchLTRtoRTL( aPoint );
+
+ if ( TEXT_LAYOUT_BIDI_STRONG != GetOut()->GetLayoutMode() )
+ aPoint.X() -= rPor.Width();
+
+ if ( GetTxtFrm()->IsVertical() )
+ GetTxtFrm()->SwitchHorizontalToVertical( aPoint );
+
+ pBlink->Insert( aPoint, &rPor, GetTxtFrm(), pFnt->GetOrientation() );
+
+ if( !pBlink->IsVisible() )
+ return;
+ }
+ else
+ {
+ delete pBlink;
+ pBlink = NULL;
+ }
+ }
+
+ // The SwScriptInfo is useless if we are inside a field portion
+ SwScriptInfo* pSI = 0;
+ if ( ! rPor.InFldGrp() )
+ pSI = &GetParaPortion()->GetScriptInfo();
+
+ // in some cases, kana compression is not allowed or surpressed for
+ // performance reasons
+ sal_uInt16 nComp = 0;
+ if ( ! IsMulti() )
+ nComp = GetKanaComp();
+
+ sal_Bool bCfgIsAutoGrammar = sal_False;
+ SvtLinguConfig().GetProperty( C2U( UPN_IS_GRAMMAR_AUTO ) ) >>= bCfgIsAutoGrammar;
+ const sal_Bool bBullet = OnWin() && GetOpt().IsBlank() && IsNoSymbol();
+ const sal_Bool bTmpWrong = bWrong && OnWin() && GetOpt().IsOnlineSpell();
+ const sal_Bool bTmpGrammarCheck = bGrammarCheck && OnWin() && bCfgIsAutoGrammar && GetOpt().IsOnlineSpell();
+ const sal_Bool bTmpSmart = bSmartTag && OnWin() && !GetOpt().IsPagePreview() && SwSmartTagMgr::Get().IsSmartTagsEnabled(); // SMARTTAGS
+
+ OSL_ENSURE( GetParaPortion(), "No paragraph!");
+ SwDrawTextInfo aDrawInf( pFrm->getRootFrm()->GetCurrShell(), *pOut, pSI, rText, nStart, nLength,
+ rPor.Width(), bBullet );
+
+ aDrawInf.SetLeft( GetPaintRect().Left() );
+ aDrawInf.SetRight( GetPaintRect().Right() );
+ aDrawInf.SetUnderFnt( pUnderFnt );
+
+ const long nSpaceAdd = ( rPor.IsBlankPortion() || rPor.IsDropPortion() ||
+ rPor.InNumberGrp() ) ? 0 : GetSpaceAdd();
+ if ( nSpaceAdd )
+ {
+ xub_StrLen nCharCnt;
+ // --> FME 2005-04-04 #i41860# Thai justified alignemt needs some
+ // additional information:
+ aDrawInf.SetNumberOfBlanks( rPor.InTxtGrp() ?
+ static_cast<const SwTxtPortion&>(rPor).GetSpaceCnt( *this, nCharCnt ) :
+ 0 );
+ // <--
+ }
+
+ aDrawInf.SetSpace( nSpaceAdd );
+ aDrawInf.SetKanaComp( nComp );
+
+ // the font is used to identify the current script via nActual
+ aDrawInf.SetFont( pFnt );
+ // the frame is used to identify the orientation
+ aDrawInf.SetFrm( GetTxtFrm() );
+ // we have to know if the paragraph should snap to grid
+ aDrawInf.SetSnapToGrid( SnapToGrid() );
+ // for underlining we must know when not to add extra space behind
+ // a character in justified mode
+ aDrawInf.SetSpaceStop( ! rPor.GetPortion() ||
+ rPor.GetPortion()->InFixMargGrp() ||
+ rPor.GetPortion()->IsHolePortion() );
+
+ if( GetTxtFly()->IsOn() )
+ {
+ // aPos muss als TopLeft vorliegen, weil die ClipRects sonst
+ // nicht berechnet werden koennen.
+ const Point aPoint( aPos.X(), aPos.Y() - rPor.GetAscent() );
+ const Size aSize( rPor.Width(), rPor.Height() );
+ aDrawInf.SetPos( aPoint );
+ aDrawInf.SetSize( aSize );
+ aDrawInf.SetAscent( rPor.GetAscent() );
+ aDrawInf.SetKern( bKern ? rPor.Width() : 0 );
+ aDrawInf.SetWrong( bTmpWrong ? pWrongList : NULL );
+ aDrawInf.SetGrammarCheck( bTmpGrammarCheck ? pGrammarCheckList : NULL );
+ aDrawInf.SetSmartTags( bTmpSmart ? pSmartTags : NULL ); // SMARTTAGS
+ GetTxtFly()->DrawTextOpaque( aDrawInf );
+ }
+ else
+ {
+ aDrawInf.SetPos( aPos );
+ if( bKern )
+ pFnt->_DrawStretchText( aDrawInf );
+ else
+ {
+ aDrawInf.SetWrong( bTmpWrong ? pWrongList : NULL );
+ aDrawInf.SetGrammarCheck( bTmpGrammarCheck ? pGrammarCheckList : NULL );
+ aDrawInf.SetSmartTags( bTmpSmart ? pSmartTags : NULL ); // SMARTTAGS
+ pFnt->_DrawText( aDrawInf );
+ }
+ }
+}
+
+/*************************************************************************
+ * SwTxtPaintInfo::CalcRect()
+ *************************************************************************/
+
+void SwTxtPaintInfo::CalcRect( const SwLinePortion& rPor,
+ SwRect* pRect, SwRect* pIntersect ) const
+{
+ Size aSize( rPor.Width(), rPor.Height() );
+ if( rPor.IsHangingPortion() )
+ aSize.Width() = ((SwHangingPortion&)rPor).GetInnerWidth();
+ if( rPor.InSpaceGrp() && GetSpaceAdd() )
+ {
+ SwTwips nAdd = rPor.CalcSpacing( GetSpaceAdd(), *this );
+ if( rPor.InFldGrp() && GetSpaceAdd() < 0 && nAdd )
+ nAdd += GetSpaceAdd() / SPACING_PRECISION_FACTOR;
+ aSize.Width() += nAdd;
+ }
+
+ Point aPoint;
+
+ if( IsRotated() )
+ {
+ long nTmp = aSize.Width();
+ aSize.Width() = aSize.Height();
+ aSize.Height() = nTmp;
+ if ( 1 == GetDirection() )
+ {
+ aPoint.A() = X() - rPor.GetAscent();
+ aPoint.B() = Y() - aSize.Height();
+ }
+ else
+ {
+ aPoint.A() = X() - rPor.Height() + rPor.GetAscent();
+ aPoint.B() = Y();
+ }
+ }
+ else
+ {
+ aPoint.A() = X();
+ //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin
+ if ( GetTxtFrm()->IsVertLR() )
+ aPoint.B() = Y() - rPor.Height() + rPor.GetAscent();
+ else
+ aPoint.B() = Y() - rPor.GetAscent();
+ }
+
+ // Adjust x coordinate if we are inside a bidi portion
+ const sal_Bool bFrmDir = GetTxtFrm()->IsRightToLeft();
+ sal_Bool bCounterDir = ( ! bFrmDir && DIR_RIGHT2LEFT == GetDirection() ) ||
+ ( bFrmDir && DIR_LEFT2RIGHT == GetDirection() );
+
+ if ( bCounterDir )
+ aPoint.A() -= aSize.Width();
+
+ SwRect aRect( aPoint, aSize );
+
+ if ( GetTxtFrm()->IsRightToLeft() )
+ GetTxtFrm()->SwitchLTRtoRTL( aRect );
+
+ if ( GetTxtFrm()->IsVertical() )
+ GetTxtFrm()->SwitchHorizontalToVertical( aRect );
+
+ if ( pRect )
+ *pRect = aRect;
+
+ if( aRect.HasArea() && pIntersect )
+ {
+ ::SwAlignRect( aRect, (ViewShell*)GetVsh() );
+
+ if ( GetOut()->IsClipRegion() )
+ {
+ SwRect aClip( GetOut()->GetClipRegion().GetBoundRect() );
+ aRect.Intersection( aClip );
+ }
+
+ *pIntersect = aRect;
+ }
+}
+
+/*************************************************************************
+ * lcl_DrawSpecial
+ *
+ * Draws a special portion, e.g., line break portion, tab portion.
+ * rPor - The portion
+ * rRect - The rectangle surrounding the character
+ * pCol - Specify a color for the character
+ * bCenter - Draw the character centered, otherwise left aligned
+ * bRotate - Rotate the character if character rotation is set
+ *************************************************************************/
+
+static void lcl_DrawSpecial( const SwTxtPaintInfo& rInf, const SwLinePortion& rPor,
+ SwRect& rRect, const Color* pCol, sal_Unicode cChar,
+ sal_uInt8 nOptions )
+{
+ sal_Bool bCenter = 0 != ( nOptions & DRAW_SPECIAL_OPTIONS_CENTER );
+ sal_Bool bRotate = 0 != ( nOptions & DRAW_SPECIAL_OPTIONS_ROTATE );
+
+ // rRect is given in absolute coordinates
+ if ( rInf.GetTxtFrm()->IsRightToLeft() )
+ rInf.GetTxtFrm()->SwitchRTLtoLTR( rRect );
+ if ( rInf.GetTxtFrm()->IsVertical() )
+ rInf.GetTxtFrm()->SwitchVerticalToHorizontal( rRect );
+
+ const SwFont* pOldFnt = rInf.GetFont();
+
+ // Font is generated only once:
+ static SwFont* pFnt = 0;
+ if ( ! pFnt )
+ {
+ pFnt = new SwFont( *pOldFnt );
+ pFnt->SetFamily( FAMILY_DONTKNOW, pFnt->GetActual() );
+ pFnt->SetName( numfunc::GetDefBulletFontname(), pFnt->GetActual() );
+ pFnt->SetStyleName( aEmptyStr, pFnt->GetActual() );
+ pFnt->SetCharSet( RTL_TEXTENCODING_SYMBOL, pFnt->GetActual() );
+ }
+
+ // Some of the current values are set at the font:
+ if ( ! bRotate )
+ pFnt->SetVertical( 0, rInf.GetTxtFrm()->IsVertical() );
+ else
+ pFnt->SetVertical( pOldFnt->GetOrientation() );
+
+ if ( pCol )
+ pFnt->SetColor( *pCol );
+ else
+ pFnt->SetColor( pOldFnt->GetColor() );
+
+ Size aFontSize( 0, SPECIAL_FONT_HEIGHT );
+ pFnt->SetSize( aFontSize, pFnt->GetActual() );
+
+ ((SwTxtPaintInfo&)rInf).SetFont( pFnt );
+
+ // The maximum width depends on the current orientation
+ const sal_uInt16 nDir = pFnt->GetOrientation( rInf.GetTxtFrm()->IsVertical() );
+ SwTwips nMaxWidth = 0;
+ switch ( nDir )
+ {
+ case 0 :
+ nMaxWidth = rRect.Width();
+ break;
+ case 900 :
+ case 2700 :
+ nMaxWidth = rRect.Height();
+ break;
+ default:
+ OSL_FAIL( "Unknown direction set at font" );
+ break;
+ }
+
+ // check if char fits into rectangle
+ const XubString aTmp( cChar );
+ aFontSize = rInf.GetTxtSize( aTmp ).SvLSize();
+ while ( aFontSize.Width() > nMaxWidth )
+ {
+ SwTwips nFactor = ( 100 * aFontSize.Width() ) / nMaxWidth;
+ const SwTwips nOldWidth = aFontSize.Width();
+
+ // new height for font
+ const sal_uInt8 nAct = pFnt->GetActual();
+ aFontSize.Height() = ( 100 * pFnt->GetSize( nAct ).Height() ) / nFactor;
+ aFontSize.Width() = ( 100 * pFnt->GetSize( nAct).Width() ) / nFactor;
+
+ if ( !aFontSize.Width() && !aFontSize.Height() )
+ break;
+
+ pFnt->SetSize( aFontSize, nAct );
+
+ aFontSize = rInf.GetTxtSize( aTmp ).SvLSize();
+
+ if ( aFontSize.Width() >= nOldWidth )
+ break;
+ }
+
+ const Point aOldPos( rInf.GetPos() );
+
+ // adjust values so that tab is vertically and horizontally centered
+ SwTwips nX = rRect.Left();
+ SwTwips nY = rRect.Top();
+ switch ( nDir )
+ {
+ case 0 :
+ if ( bCenter )
+ nX += ( rRect.Width() - aFontSize.Width() ) / 2;
+ nY += ( rRect.Height() - aFontSize.Height() ) / 2 + rInf.GetAscent();
+ break;
+ case 900 :
+ if ( bCenter )
+ nX += ( rRect.Width() - aFontSize.Height() ) / 2 + rInf.GetAscent();
+ nY += ( rRect.Height() + aFontSize.Width() ) / 2;
+ break;
+ case 2700 :
+ if ( bCenter )
+ nX += ( rRect.Width() + aFontSize.Height() ) / 2 - rInf.GetAscent();
+ nY += ( rRect.Height() - aFontSize.Width() ) / 2;
+ break;
+ }
+
+ Point aTmpPos( nX, nY );
+ ((SwTxtPaintInfo&)rInf).SetPos( aTmpPos );
+ sal_uInt16 nOldWidth = rPor.Width();
+ ((SwLinePortion&)rPor).Width( (sal_uInt16)aFontSize.Width() );
+ rInf.DrawText( aTmp, rPor );
+ ((SwLinePortion&)rPor).Width( nOldWidth );
+ ((SwTxtPaintInfo&)rInf).SetFont( (SwFont*)pOldFnt );
+ ((SwTxtPaintInfo&)rInf).SetPos( aOldPos );
+}
+
+/*************************************************************************
+ * SwTxtPaintInfo::DrawRect()
+ *************************************************************************/
+
+void SwTxtPaintInfo::DrawRect( const SwRect &rRect, sal_Bool bNoGraphic,
+ sal_Bool bRetouche ) const
+{
+ if ( OnWin() || !bRetouche )
+ {
+ if( aTxtFly.IsOn() )
+ ((SwTxtPaintInfo*)this)->GetTxtFly()->
+ DrawFlyRect( pOut, rRect, *this, bNoGraphic );
+ else if ( bNoGraphic )
+ pOut->DrawRect( rRect.SVRect() );
+ else
+ {
+ OSL_ENSURE( ((SvxBrushItem*)-1) != pBrushItem, "DrawRect: Uninitialized BrushItem!" );
+ ::DrawGraphic( pBrushItem, pOut, aItemRect, rRect );
+ }
+ }
+}
+
+/*************************************************************************
+ * SwTxtPaintInfo::DrawTab()
+ *************************************************************************/
+
+void SwTxtPaintInfo::DrawTab( const SwLinePortion &rPor ) const
+{
+ if( OnWin() )
+ {
+ SwRect aRect;
+ CalcRect( rPor, &aRect );
+
+ if ( ! aRect.HasArea() )
+ return;
+
+ const sal_Unicode cChar = GetTxtFrm()->IsRightToLeft() ?
+ CHAR_TAB_RTL : CHAR_TAB;
+ const sal_uInt8 nOptions = DRAW_SPECIAL_OPTIONS_CENTER |
+ DRAW_SPECIAL_OPTIONS_ROTATE;
+ lcl_DrawSpecial( *this, rPor, aRect, 0, cChar, nOptions );
+ }
+}
+
+/*************************************************************************
+ * SwTxtPaintInfo::DrawLineBreak()
+ *************************************************************************/
+
+void SwTxtPaintInfo::DrawLineBreak( const SwLinePortion &rPor ) const
+{
+ if( OnWin() )
+ {
+ KSHORT nOldWidth = rPor.Width();
+ ((SwLinePortion&)rPor).Width( LINE_BREAK_WIDTH );
+
+ SwRect aRect;
+ CalcRect( rPor, &aRect );
+
+ if( aRect.HasArea() )
+ {
+ const sal_Unicode cChar = GetTxtFrm()->IsRightToLeft() ?
+ CHAR_LINEBREAK_RTL : CHAR_LINEBREAK;
+ const sal_uInt8 nOptions = 0;
+ lcl_DrawSpecial( *this, rPor, aRect, 0, cChar, nOptions );
+ }
+
+ ((SwLinePortion&)rPor).Width( nOldWidth );
+ }
+}
+
+
+/*************************************************************************
+ * SwTxtPaintInfo::DrawRedArrow()
+ *************************************************************************/
+
+void SwTxtPaintInfo::DrawRedArrow( const SwLinePortion &rPor ) const
+{
+ Size aSize( SPECIAL_FONT_HEIGHT, SPECIAL_FONT_HEIGHT );
+ SwRect aRect( ((SwArrowPortion&)rPor).GetPos(), aSize );
+ sal_Unicode cChar;
+ if( ((SwArrowPortion&)rPor).IsLeft() )
+ {
+ aRect.Pos().Y() += 20 - GetAscent();
+ aRect.Pos().X() += 20;
+ if( aSize.Height() > rPor.Height() )
+ aRect.Height( rPor.Height() );
+ cChar = CHAR_LEFT_ARROW;
+ }
+ else
+ {
+ if( aSize.Height() > rPor.Height() )
+ aRect.Height( rPor.Height() );
+ aRect.Pos().Y() -= aRect.Height() + 20;
+ aRect.Pos().X() -= aRect.Width() + 20;
+ cChar = CHAR_RIGHT_ARROW;
+ }
+
+ if ( GetTxtFrm()->IsVertical() )
+ GetTxtFrm()->SwitchHorizontalToVertical( aRect );
+
+ Color aCol( COL_LIGHTRED );
+
+ if( aRect.HasArea() )
+ {
+ const sal_uInt8 nOptions = 0;
+ lcl_DrawSpecial( *this, rPor, aRect, &aCol, cChar, nOptions );
+ }
+}
+
+
+/*************************************************************************
+ * SwTxtPaintInfo::DrawPostIts()
+ *************************************************************************/
+
+void SwTxtPaintInfo::DrawPostIts( const SwLinePortion&, sal_Bool bScript ) const
+{
+ if( OnWin() && pOpt->IsPostIts() )
+ {
+ Size aSize;
+ Point aTmp;
+
+ const sal_uInt16 nPostItsWidth = pOpt->GetPostItsWidth( GetOut() );
+ const sal_uInt16 nFontHeight = pFnt->GetHeight( pVsh, *GetOut() );
+ const sal_uInt16 nFontAscent = pFnt->GetAscent( pVsh, *GetOut() );
+
+ switch ( pFnt->GetOrientation( GetTxtFrm()->IsVertical() ) )
+ {
+ case 0 :
+ aSize.Width() = nPostItsWidth;
+ aSize.Height() = nFontHeight;
+ aTmp.X() = aPos.X();
+ aTmp.Y() = aPos.Y() - nFontAscent;
+ break;
+ case 900 :
+ aSize.Height() = nPostItsWidth;
+ aSize.Width() = nFontHeight;
+ aTmp.X() = aPos.X() - nFontAscent;
+ aTmp.Y() = aPos.Y();
+ break;
+ case 2700 :
+ aSize.Height() = nPostItsWidth;
+ aSize.Width() = nFontHeight;
+ aTmp.X() = aPos.X() - nFontHeight +
+ nFontAscent;
+ aTmp.Y() = aPos.Y();
+ break;
+ }
+
+ SwRect aTmpRect( aTmp, aSize );
+
+ if ( GetTxtFrm()->IsRightToLeft() )
+ GetTxtFrm()->SwitchLTRtoRTL( aTmpRect );
+
+ if ( GetTxtFrm()->IsVertical() )
+ GetTxtFrm()->SwitchHorizontalToVertical( aTmpRect );
+
+ const Rectangle aRect( aTmpRect.SVRect() );
+ pOpt->PaintPostIts( (OutputDevice*)GetOut(), aRect, bScript );
+ }
+}
+
+void SwTxtPaintInfo::DrawCheckBox( const SwFieldFormPortion &rPor, bool checked) const
+{
+ SwRect aIntersect;
+ CalcRect( rPor, &aIntersect, 0 );
+ if ( aIntersect.HasArea() )
+ {
+ if (OnWin() && SwViewOption::IsFieldShadings() &&
+ !GetOpt().IsPagePreview())
+ {
+ OutputDevice* pOut_ = (OutputDevice*)GetOut();
+ pOut_->Push( PUSH_LINECOLOR | PUSH_FILLCOLOR );
+ pOut_->SetFillColor( SwViewOption::GetFieldShadingsColor() );
+ pOut_->SetLineColor();
+ pOut_->DrawRect( aIntersect.SVRect() );
+ pOut_->Pop();
+ }
+ const int delta=10;
+ Rectangle r(aIntersect.Left()+delta, aIntersect.Top()+delta, aIntersect.Right()-delta, aIntersect.Bottom()-delta);
+ pOut->Push( PUSH_LINECOLOR | PUSH_FILLCOLOR );
+ pOut->SetLineColor( Color(0, 0, 0));
+ pOut->SetFillColor();
+ pOut->DrawRect( r );
+ if (checked) {
+ pOut->DrawLine(r.TopLeft(), r.BottomRight());
+ pOut->DrawLine(r.TopRight(), r.BottomLeft());
+ }
+ pOut->Pop();
+ }
+}
+/*************************************************************************
+ * SwTxtPaintInfo::DrawBackGround()
+ *************************************************************************/
+void SwTxtPaintInfo::DrawBackground( const SwLinePortion &rPor ) const
+{
+ OSL_ENSURE( OnWin(), "SwTxtPaintInfo::DrawBackground: printer polution ?" );
+
+ SwRect aIntersect;
+ CalcRect( rPor, 0, &aIntersect );
+
+ if ( aIntersect.HasArea() )
+ {
+ OutputDevice* pTmpOut = (OutputDevice*)GetOut();
+ pTmpOut->Push( PUSH_LINECOLOR | PUSH_FILLCOLOR );
+
+ // For dark background we do not want to have a filled rectangle
+ if ( GetVsh() && GetVsh()->GetWin() && lcl_IsDarkBackground( *this ) )
+ {
+ pTmpOut->SetLineColor( SwViewOption::GetFontColor().GetColor() );
+ }
+ else
+ {
+ pTmpOut->SetFillColor( SwViewOption::GetFieldShadingsColor() );
+ pTmpOut->SetLineColor();
+ }
+
+ DrawRect( aIntersect, sal_True );
+ pTmpOut->Pop();
+ }
+}
+
+void SwTxtPaintInfo::_DrawBackBrush( const SwLinePortion &rPor ) const
+{
+ {
+ SwRect aIntersect;
+ CalcRect( rPor, &aIntersect, 0 );
+ if(aIntersect.HasArea())
+ {
+ SwTxtNode *pNd = pFrm->GetTxtNode();
+ const ::sw::mark::IMark* pFieldmark = NULL;
+ if(pNd)
+ {
+ const SwDoc *doc=pNd->GetDoc();
+ if(doc)
+ {
+ SwIndex aIndex(pNd, GetIdx());
+ SwPosition aPosition(*pNd, aIndex);
+ pFieldmark=doc->getIDocumentMarkAccess()->getFieldmarkFor(aPosition);
+ }
+ }
+ bool bIsStartMark=(1==GetLen() && CH_TXT_ATR_FIELDSTART==GetTxt().GetChar(GetIdx()));
+ if(pFieldmark) {
+ OSL_TRACE("Found Fieldmark");
+#if DEBUG
+ rtl::OUString str = pFieldmark->ToString( );
+ fprintf( stderr, "%s\n", rtl::OUStringToOString( str, RTL_TEXTENCODING_UTF8 ).getStr( ) );
+#endif
+ }
+ if(bIsStartMark) OSL_TRACE("Found StartMark");
+ if (OnWin() && (pFieldmark!=NULL || bIsStartMark) &&
+ SwViewOption::IsFieldShadings() &&
+ !GetOpt().IsPagePreview())
+ {
+ OutputDevice* pOutDev = (OutputDevice*)GetOut();
+ pOutDev->Push( PUSH_LINECOLOR | PUSH_FILLCOLOR );
+ pOutDev->SetFillColor( SwViewOption::GetFieldShadingsColor() );
+ pOutDev->SetLineColor( );
+ pOutDev->DrawRect( aIntersect.SVRect() );
+ pOutDev->Pop();
+ }
+ }
+ }
+ if( !pFnt->GetBackColor() ) return;
+
+ OSL_ENSURE( pFnt->GetBackColor(), "DrawBackBrush: Lost Color" );
+
+ SwRect aIntersect;
+ CalcRect( rPor, 0, &aIntersect );
+
+ if ( aIntersect.HasArea() )
+ {
+ OutputDevice* pTmpOut = (OutputDevice*)GetOut();
+
+ // --> FME 2004-06-24 #i16816# tagged pdf support
+ SwTaggedPDFHelper aTaggedPDFHelper( 0, 0, 0, *pTmpOut );
+ // <--
+
+ pTmpOut->Push( PUSH_LINECOLOR | PUSH_FILLCOLOR );
+
+ pTmpOut->SetFillColor( *pFnt->GetBackColor() );
+ pTmpOut->SetLineColor();
+
+ DrawRect( aIntersect, sal_True, sal_False );
+
+ pTmpOut->Pop();
+ }
+}
+
+/*************************************************************************
+ * SwTxtPaintInfo::DrawViewOpt()
+ *************************************************************************/
+
+void SwTxtPaintInfo::DrawViewOpt( const SwLinePortion &rPor,
+ const MSHORT nWhich ) const
+{
+ if( OnWin() && !IsMulti() )
+ {
+ sal_Bool bDraw = sal_False;
+ switch( nWhich )
+ {
+ case POR_FTN:
+ case POR_QUOVADIS:
+ case POR_NUMBER:
+ case POR_FLD:
+ case POR_URL:
+ case POR_HIDDEN:
+ case POR_TOX:
+ case POR_REF:
+ case POR_META:
+ case POR_CONTROLCHAR:
+ if ( !GetOpt().IsPagePreview() &&
+ !GetOpt().IsReadonly() &&
+ SwViewOption::IsFieldShadings() &&
+ (POR_NUMBER != nWhich ||
+ pFrm->GetTxtNode()->HasMarkedLabel())) // #i27615#
+ bDraw = sal_True;
+ break;
+ case POR_TAB: if ( GetOpt().IsTab() ) bDraw = sal_True; break;
+ case POR_SOFTHYPH: if ( GetOpt().IsSoftHyph() )bDraw = sal_True; break;
+ case POR_BLANK: if ( GetOpt().IsHardBlank())bDraw = sal_True; break;
+ default:
+ {
+ OSL_ENSURE( !this, "SwTxtPaintInfo::DrawViewOpt: don't know how to draw this" );
+ break;
+ }
+ }
+ if ( bDraw )
+ DrawBackground( rPor );
+ }
+}
+
+/*************************************************************************
+ * SwTxtPaintInfo::_NotifyURL()
+ *************************************************************************/
+
+void SwTxtPaintInfo::_NotifyURL( const SwLinePortion &rPor ) const
+{
+ OSL_ENSURE( pNoteURL, "NotifyURL: pNoteURL gone with the wind!" );
+
+ SwRect aIntersect;
+ CalcRect( rPor, 0, &aIntersect );
+
+ if( aIntersect.HasArea() )
+ {
+ SwTxtNode *pNd = (SwTxtNode*)GetTxtFrm()->GetTxtNode();
+ SwTxtAttr *const pAttr =
+ pNd->GetTxtAttrAt(GetIdx(), RES_TXTATR_INETFMT);
+ if( pAttr )
+ {
+ const SwFmtINetFmt& rFmt = pAttr->GetINetFmt();
+ pNoteURL->InsertURLNote( rFmt.GetValue(), rFmt.GetTargetFrame(),
+ aIntersect );
+ }
+ }
+}
+
+/*************************************************************************
+ * lcl_InitHyphValues()
+ *************************************************************************/
+
+static void lcl_InitHyphValues( PropertyValues &rVals,
+ sal_Int16 nMinLeading, sal_Int16 nMinTrailing )
+{
+ sal_Int32 nLen = rVals.getLength();
+
+ if (0 == nLen) // yet to be initialized?
+ {
+ rVals.realloc( 2 );
+ PropertyValue *pVal = rVals.getArray();
+
+ pVal[0].Name = C2U( UPN_HYPH_MIN_LEADING );
+ pVal[0].Handle = UPH_HYPH_MIN_LEADING;
+ pVal[0].Value <<= nMinLeading;
+
+ pVal[1].Name = C2U( UPN_HYPH_MIN_TRAILING );
+ pVal[1].Handle = UPH_HYPH_MIN_TRAILING;
+ pVal[1].Value <<= nMinTrailing;
+ }
+ else if (2 == nLen) // already initialized once?
+ {
+ PropertyValue *pVal = rVals.getArray();
+ pVal[0].Value <<= nMinLeading;
+ pVal[1].Value <<= nMinTrailing;
+ }
+ else {
+ OSL_FAIL( "unxpected size of sequence" );
+ }
+}
+
+/*************************************************************************
+ * SwTxtFormatInfo::GetHyphValues()
+ *************************************************************************/
+
+const PropertyValues & SwTxtFormatInfo::GetHyphValues() const
+{
+ DBG_ASSERT( 2 == aHyphVals.getLength(),
+ "hyphenation values not yet initialized" );
+ return aHyphVals;
+}
+
+/*************************************************************************
+ * SwTxtFormatInfo::InitHyph()
+ *************************************************************************/
+
+sal_Bool SwTxtFormatInfo::InitHyph( const sal_Bool bAutoHyphen )
+{
+ const SwAttrSet& rAttrSet = GetTxtFrm()->GetTxtNode()->GetSwAttrSet();
+ SetHanging( rAttrSet.GetHangingPunctuation().GetValue() );
+ SetScriptSpace( rAttrSet.GetScriptSpace().GetValue() );
+ SetForbiddenChars( rAttrSet.GetForbiddenRule().GetValue() );
+ const SvxHyphenZoneItem &rAttr = rAttrSet.GetHyphenZone();
+ MaxHyph() = rAttr.GetMaxHyphens();
+ sal_Bool bAuto = bAutoHyphen || rAttr.IsHyphen();
+ if( bAuto || bInterHyph )
+ {
+ nHyphStart = nHyphWrdStart = STRING_LEN;
+ nHyphWrdLen = 0;
+
+ const sal_Int16 nMinimalLeading = Max(rAttr.GetMinLead(), sal_uInt8(2));
+ const sal_Int16 nMinimalTrailing = rAttr.GetMinTrail();
+ lcl_InitHyphValues( aHyphVals, nMinimalLeading, nMinimalTrailing);
+ }
+ return bAuto;
+}
+
+/*************************************************************************
+ * SwTxtFormatInfo::CtorInitTxtFormatInfo()
+ *************************************************************************/
+
+void SwTxtFormatInfo::CtorInitTxtFormatInfo( SwTxtFrm *pNewFrm, const sal_Bool bNewInterHyph,
+ const sal_Bool bNewQuick, const sal_Bool bTst )
+{
+ CtorInitTxtPaintInfo( pNewFrm, SwRect() );
+
+ bQuick = bNewQuick;
+ bInterHyph = bNewInterHyph;
+
+ //! needs to be done in this order
+ nMinLeading = 2;
+ nMinTrailing = 2;
+ nMinWordLength = 0;
+ bAutoHyph = InitHyph();
+
+ bIgnoreFly = sal_False;
+ bFakeLineStart = sal_False;
+ bShift = sal_False;
+ bDropInit = sal_False;
+ bTestFormat = bTst;
+ nLeft = 0;
+ nRight = 0;
+ nFirst = 0;
+ nRealWidth = 0;
+ nForcedLeftMargin = 0;
+ pRest = 0;
+ nLineHeight = 0;
+ nLineNettoHeight = 0;
+ SetLineStart(0);
+ Init();
+}
+
+/*************************************************************************
+ * SwTxtFormatInfo::IsHyphenate()
+ *************************************************************************/
+// Trennen oder nicht trennen, das ist hier die Frage:
+// - in keinem Fall trennen, wenn der Hyphenator ERROR zurueckliefert,
+// oder wenn als Sprache NOLANGUAGE eingestellt ist.
+// - ansonsten immer trennen, wenn interaktive Trennung vorliegt
+// - wenn keine interakt. Trennung, dann nur trennen, wenn im ParaFmt
+// automatische Trennung eingestellt ist.
+
+sal_Bool SwTxtFormatInfo::IsHyphenate() const
+{
+ if( !bInterHyph && !bAutoHyph )
+ return sal_False;
+
+ LanguageType eTmp = GetFont()->GetLanguage();
+ if( LANGUAGE_DONTKNOW == eTmp || LANGUAGE_NONE == eTmp )
+ return sal_False;
+
+ uno::Reference< XHyphenator > xHyph = ::GetHyphenator();
+ if (bInterHyph && xHyph.is())
+ SvxSpellWrapper::CheckHyphLang( xHyph, eTmp );
+
+ if( !xHyph.is() || !xHyph->hasLocale( pBreakIt->GetLocale(eTmp) ) )
+ return sal_False;
+ return sal_True;
+}
+
+/*************************************************************************
+ * SwTxtFormatInfo::GetDropFmt()
+ *************************************************************************/
+
+// Dropcaps vom SwTxtFormatter::CTOR gerufen.
+const SwFmtDrop *SwTxtFormatInfo::GetDropFmt() const
+{
+ const SwFmtDrop *pDrop = &GetTxtFrm()->GetTxtNode()->GetSwAttrSet().GetDrop();
+ if( 1 >= pDrop->GetLines() ||
+ ( !pDrop->GetChars() && !pDrop->GetWholeWord() ) )
+ pDrop = 0;
+ return pDrop;
+}
+
+/*************************************************************************
+ * SwTxtFormatInfo::Init()
+ *************************************************************************/
+
+void SwTxtFormatInfo::Init()
+{
+ // Nicht initialisieren: pRest, nLeft, nRight, nFirst, nRealWidth
+ X(0);
+ bArrowDone = bFull = bFtnDone = bErgoDone = bNumDone = bNoEndHyph =
+ bNoMidHyph = bStop = bNewLine = bUnderFlow = sal_False;
+
+ // generally we do not allow number portions in follows, except...
+ if ( GetTxtFrm()->IsFollow() )
+ {
+ const SwTxtFrm* pMaster = GetTxtFrm()->FindMaster();
+ const SwLinePortion* pTmpPara = pMaster->GetPara();
+
+ // there is a master for this follow and the master does not have
+ // any contents (especially it does not have a number portion)
+ bNumDone = ! pTmpPara ||
+ ! ((SwParaPortion*)pTmpPara)->GetFirstPortion()->IsFlyPortion();
+ }
+
+ pRoot = 0;
+ pLast = 0;
+ pFly = 0;
+ pLastFld = 0;
+ pLastTab = 0;
+ pUnderFlow = 0;
+ cTabDecimal = 0;
+ nWidth = nRealWidth;
+ nForcedLeftMargin = 0;
+ nSoftHyphPos = 0;
+ nUnderScorePos = STRING_LEN;
+ cHookChar = 0;
+ SetIdx(0);
+ SetLen( GetTxt().Len() );
+ SetPaintOfst(0);
+}
+
+/*--------------------------------------------------
+ * There are a few differences between a copy constructor
+ * and the following constructor for multi-line formatting.
+ * The root is the first line inside the multi-portion,
+ * the line start is the actual position in the text,
+ * the line width is the rest width from the surrounding line
+ * and the bMulti and bFirstMulti-flag has to be set correctly.
+ * --------------------------------------------------*/
+
+SwTxtFormatInfo::SwTxtFormatInfo( const SwTxtFormatInfo& rInf,
+ SwLineLayout& rLay, SwTwips nActWidth ) : SwTxtPaintInfo( rInf )
+{
+ pRoot = &rLay;
+ pLast = &rLay;
+ pFly = NULL;
+ pLastFld = NULL;
+ pUnderFlow = NULL;
+ pRest = NULL;
+ pLastTab = NULL;
+
+ nSoftHyphPos = 0;
+ nUnderScorePos = STRING_LEN;
+ nHyphStart = 0;
+ nHyphWrdStart = 0;
+ nHyphWrdLen = 0;
+ nLineStart = rInf.GetIdx();
+ nLeft = rInf.nLeft;
+ nRight = rInf.nRight;
+ nFirst = rInf.nLeft;
+ nRealWidth = KSHORT(nActWidth);
+ nWidth = nRealWidth;
+ nLineHeight = 0;
+ nLineNettoHeight = 0;
+ nForcedLeftMargin = 0;
+
+ nMinLeading = 0;
+ nMinTrailing = 0;
+ nMinWordLength = 0;
+ bFull = sal_False;
+ bFtnDone = sal_True;
+ bErgoDone = sal_True;
+ bNumDone = sal_True;
+ bArrowDone = sal_True;
+ bStop = sal_False;
+ bNewLine = sal_True;
+ bShift = sal_False;
+ bUnderFlow = sal_False;
+ bInterHyph = sal_False;
+ bAutoHyph = sal_False;
+ bDropInit = sal_False;
+ bQuick = rInf.bQuick;
+ bNoEndHyph = sal_False;
+ bNoMidHyph = sal_False;
+ bIgnoreFly = sal_False;
+ bFakeLineStart = sal_False;
+
+ cTabDecimal = 0;
+ cHookChar = 0;
+ nMaxHyph = 0;
+ bTestFormat = rInf.bTestFormat;
+ SetMulti( sal_True );
+ SetFirstMulti( rInf.IsFirstMulti() );
+}
+
+/*************************************************************************
+ * SwTxtFormatInfo::_CheckFtnPortion()
+ *************************************************************************/
+
+sal_Bool SwTxtFormatInfo::_CheckFtnPortion( SwLineLayout* pCurr )
+{
+ KSHORT nHeight = pCurr->GetRealHeight();
+ SwLinePortion *pPor = pCurr->GetPortion();
+ sal_Bool bRet = sal_False;
+ while( pPor )
+ {
+ if( pPor->IsFtnPortion() && nHeight > ((SwFtnPortion*)pPor)->Orig() )
+ {
+ bRet = sal_True;
+ SetLineHeight( nHeight );
+ SetLineNettoHeight( pCurr->Height() );
+ break;
+ }
+ pPor = pPor->GetPortion();
+ }
+ return bRet;
+}
+
+
+
+
+/*************************************************************************
+ * SwTxtFormatInfo::ScanPortionEnd()
+ *************************************************************************/
+xub_StrLen SwTxtFormatInfo::ScanPortionEnd( const xub_StrLen nStart,
+ const xub_StrLen nEnd )
+{
+ cHookChar = 0;
+ xub_StrLen i = nStart;
+
+ //
+ // Used for decimal tab handling:
+ //
+ const xub_Unicode cTabDec = GetLastTab() ? (sal_Unicode)GetTabDecimal() : 0;
+ const xub_Unicode cThousandSep = ',' == cTabDec ? '.' : ',';
+ // --> FME 2006-01-23 #i45951# German (Switzerland) uses ' as thousand separator:
+ const xub_Unicode cThousandSep2 = ',' == cTabDec ? '.' : '\'';
+ // <--
+
+ bool bNumFound = false;
+ const bool bTabCompat = GetTxtFrm()->GetTxtNode()->getIDocumentSettingAccess()->get(IDocumentSettingAccess::TAB_COMPAT);
+
+ for( ; i < nEnd; ++i )
+ {
+ const xub_Unicode cPos = GetChar( i );
+ switch( cPos )
+ {
+ case CH_TXTATR_BREAKWORD:
+ case CH_TXTATR_INWORD:
+ if( !HasHint( i ))
+ break;
+ // no break;
+
+ case CHAR_SOFTHYPHEN:
+ case CHAR_HARDHYPHEN:
+ case CHAR_HARDBLANK:
+ case CH_TAB:
+ case CH_BREAK:
+ case CHAR_ZWSP :
+ case CHAR_ZWNBSP :
+ cHookChar = cPos;
+ return i;
+
+ case CHAR_UNDERSCORE:
+ if ( STRING_LEN == nUnderScorePos )
+ nUnderScorePos = i;
+ break;
+
+ default:
+ if ( cTabDec )
+ {
+ if( cTabDec == cPos )
+ {
+ OSL_ENSURE( cPos, "Unexpected end of string" );
+ if( cPos ) // robust
+ {
+ cHookChar = cPos;
+ return i;
+ }
+ }
+
+ //
+ // Compatibility: First non-digit character behind a
+ // a digit character becomes the hook character
+ //
+ if ( bTabCompat )
+ {
+ if ( ( 0x2F < cPos && cPos < 0x3A ) ||
+ ( bNumFound && ( cPos == cThousandSep || cPos == cThousandSep2 ) ) )
+ {
+ bNumFound = true;
+ }
+ else
+ {
+ if ( bNumFound )
+ {
+ cHookChar = cPos;
+ SetTabDecimal( cPos );
+ return i;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ // --> FME 2006-01-13 #130210# Check if character *behind* the portion has
+ // to become the hook:
+ if ( i == nEnd && i < GetTxt().Len() && bNumFound )
+ {
+ const xub_Unicode cPos = GetChar( i );
+ if ( cPos != cTabDec && cPos != cThousandSep && cPos !=cThousandSep2 && ( 0x2F >= cPos || cPos >= 0x3A ) )
+ {
+ cHookChar = GetChar( i );
+ SetTabDecimal( cHookChar );
+ }
+ }
+
+ return i;
+}
+
+sal_Bool SwTxtFormatInfo::LastKernPortion()
+{
+ if( GetLast() )
+ {
+ if( GetLast()->IsKernPortion() )
+ return sal_True;
+ if( GetLast()->Width() || ( GetLast()->GetLen() &&
+ !GetLast()->IsHolePortion() ) )
+ return sal_False;
+ }
+ SwLinePortion* pPor = GetRoot();
+ SwLinePortion *pKern = NULL;
+ while( pPor )
+ {
+ if( pPor->IsKernPortion() )
+ pKern = pPor;
+ else if( pPor->Width() || ( pPor->GetLen() && !pPor->IsHolePortion() ) )
+ pKern = NULL;
+ pPor = pPor->GetPortion();
+ }
+ if( pKern )
+ {
+ SetLast( pKern );
+ return sal_True;
+ }
+ return sal_False;
+}
+
+/*************************************************************************
+ * class SwTxtSlot
+ *************************************************************************/
+
+SwTxtSlot::SwTxtSlot( const SwTxtSizeInfo *pNew, const SwLinePortion *pPor,
+ bool bTxtLen, bool bExgLists, const sal_Char *pCh )
+ : pOldTxt( 0 ),
+ pOldSmartTagList( 0 ),
+ pOldGrammarCheckList( 0 ),
+ pTempList( 0 )
+{
+ if( pCh )
+ {
+ aTxt = XubString( pCh, RTL_TEXTENCODING_MS_1252 );
+ bOn = sal_True;
+ }
+ else
+ bOn = pPor->GetExpTxt( *pNew, aTxt );
+
+ // Der Text wird ausgetauscht...
+ if( bOn )
+ {
+ pInf = (SwTxtSizeInfo*)pNew;
+ nIdx = pInf->GetIdx();
+ nLen = pInf->GetLen();
+ pOldTxt = &(pInf->GetTxt());
+ pInf->SetTxt( aTxt );
+ pInf->SetIdx( 0 );
+ pInf->SetLen( bTxtLen ? pInf->GetTxt().Len() : pPor->GetLen() );
+
+ // ST2
+ if ( bExgLists )
+ {
+ pOldSmartTagList = static_cast<SwTxtPaintInfo*>(pInf)->GetSmartTags();
+ if ( pOldSmartTagList )
+ {
+ const sal_uInt16 nPos = pOldSmartTagList->GetWrongPos(nIdx);
+ const xub_StrLen nListPos = pOldSmartTagList->Pos(nPos);
+ if( nListPos == nIdx )
+ ((SwTxtPaintInfo*)pInf)->SetSmartTags( pOldSmartTagList->SubList( nPos ) );
+ else if( !pTempList && nPos < pOldSmartTagList->Count() && nListPos < nIdx && aTxt.Len() )
+ {
+ pTempList = new SwWrongList( WRONGLIST_SMARTTAG );
+ pTempList->Insert( rtl::OUString(), 0, 0, aTxt.Len(), 0 );
+ ((SwTxtPaintInfo*)pInf)->SetSmartTags( pTempList );
+ }
+ else
+ ((SwTxtPaintInfo*)pInf)->SetSmartTags( 0);
+ }
+ pOldGrammarCheckList = static_cast<SwTxtPaintInfo*>(pInf)->GetGrammarCheckList();
+ if ( pOldGrammarCheckList )
+ {
+ const sal_uInt16 nPos = pOldGrammarCheckList->GetWrongPos(nIdx);
+ const xub_StrLen nListPos = pOldGrammarCheckList->Pos(nPos);
+ if( nListPos == nIdx )
+ ((SwTxtPaintInfo*)pInf)->SetGrammarCheckList( pOldGrammarCheckList->SubList( nPos ) );
+ else if( !pTempList && nPos < pOldGrammarCheckList->Count() && nListPos < nIdx && aTxt.Len() )
+ {
+ pTempList = new SwWrongList( WRONGLIST_GRAMMAR );
+ pTempList->Insert( rtl::OUString(), 0, 0, aTxt.Len(), 0 );
+ ((SwTxtPaintInfo*)pInf)->SetGrammarCheckList( pTempList );
+ }
+ else
+ ((SwTxtPaintInfo*)pInf)->SetGrammarCheckList( 0);
+ }
+ }
+ }
+}
+
+/*************************************************************************
+ * SwTxtSlot::~SwTxtSlot()
+ *************************************************************************/
+
+SwTxtSlot::~SwTxtSlot()
+{
+ if( bOn )
+ {
+ pInf->SetTxt( *pOldTxt );
+ pInf->SetIdx( nIdx );
+ pInf->SetLen( nLen );
+
+ // ST2
+ // Restore old smart tag list
+ if ( pOldSmartTagList )
+ ((SwTxtPaintInfo*)pInf)->SetSmartTags( pOldSmartTagList );
+ if ( pOldGrammarCheckList )
+ ((SwTxtPaintInfo*)pInf)->SetGrammarCheckList( pOldGrammarCheckList );
+ delete pTempList;
+ }
+}
+
+/*************************************************************************
+ * SwFontSave::SwFontSave()
+ *************************************************************************/
+
+SwFontSave::SwFontSave( const SwTxtSizeInfo &rInf, SwFont *pNew,
+ SwAttrIter* pItr )
+ : pFnt( pNew ? ((SwTxtSizeInfo&)rInf).GetFont() : 0 )
+{
+ if( pFnt )
+ {
+ pInf = &((SwTxtSizeInfo&)rInf);
+ // In these cases we temporarily switch to the new font:
+ // 1. the fonts have a different magic number
+ // 2. they have different script types
+ // 3. their background colors differ (this is not covered by 1.)
+ if( pFnt->DifferentMagic( pNew, pFnt->GetActual() ) ||
+ pNew->GetActual() != pFnt->GetActual() ||
+ ( ! pNew->GetBackColor() && pFnt->GetBackColor() ) ||
+ ( pNew->GetBackColor() && ! pFnt->GetBackColor() ) ||
+ ( pNew->GetBackColor() && pFnt->GetBackColor() &&
+ ( *pNew->GetBackColor() != *pFnt->GetBackColor() ) ) )
+ {
+ pNew->SetTransparent( sal_True );
+ pNew->SetAlign( ALIGN_BASELINE );
+ pInf->SetFont( pNew );
+ }
+ else
+ pFnt = 0;
+ pNew->Invalidate();
+ pNew->ChgPhysFnt( pInf->GetVsh(), *pInf->GetOut() );
+ if( pItr && pItr->GetFnt() == pFnt )
+ {
+ pIter = pItr;
+ pIter->SetFnt( pNew );
+ }
+ else
+ pIter = NULL;
+ }
+}
+
+/*************************************************************************
+ * SwFontSave::~SwFontSave()
+ *************************************************************************/
+
+SwFontSave::~SwFontSave()
+{
+ if( pFnt )
+ {
+ // SwFont zurueckstellen
+ pFnt->Invalidate();
+ pInf->SetFont( pFnt );
+ if( pIter )
+ {
+ pIter->SetFnt( pFnt );
+ pIter->nPos = STRING_LEN;
+ }
+ }
+}
+
+/*************************************************************************
+ * SwDefFontSave::SwDefFontSave()
+ *************************************************************************/
+
+SwDefFontSave::SwDefFontSave( const SwTxtSizeInfo &rInf )
+ : pFnt( ((SwTxtSizeInfo&)rInf).GetFont() )
+{
+ const sal_Bool bTmpAlter = pFnt->GetFixKerning() ||
+ ( RTL_TEXTENCODING_SYMBOL == pFnt->GetCharSet(pFnt->GetActual()) )
+ ;
+
+ const sal_Bool bFamily = bTmpAlter &&
+ pFnt->GetName( pFnt->GetActual() ) != numfunc::GetDefBulletFontname();
+ const sal_Bool bRotation = (sal_Bool)pFnt->GetOrientation() &&
+ ! rInf.GetTxtFrm()->IsVertical();
+
+ if( bFamily || bRotation )
+ {
+ pNewFnt = new SwFont( *pFnt );
+
+ if ( bFamily )
+ {
+ pNewFnt->SetFamily( FAMILY_DONTKNOW, pFnt->GetActual() );
+ pNewFnt->SetName( numfunc::GetDefBulletFontname(), pFnt->GetActual() );
+ pNewFnt->SetStyleName( aEmptyStr, pFnt->GetActual() );
+ pNewFnt->SetCharSet( RTL_TEXTENCODING_SYMBOL, pFnt->GetActual() );
+ pNewFnt->SetFixKerning( 0 );
+ }
+
+ if ( bRotation )
+ pNewFnt->SetVertical( 0, rInf.GetTxtFrm()->IsVertical() );
+
+ pInf = &((SwTxtSizeInfo&)rInf);
+ pNewFnt->Invalidate();
+ pInf->SetFont( pNewFnt );
+ }
+ else
+ {
+ pFnt = 0;
+ pNewFnt = 0;
+ }
+}
+
+/*************************************************************************
+ * SwDefFontSave::~SwDefFontSave()
+ *************************************************************************/
+
+SwDefFontSave::~SwDefFontSave()
+{
+ if( pFnt )
+ {
+ delete pNewFnt;
+ // SwFont zurueckstellen
+ pFnt->Invalidate();
+ pInf->SetFont( pFnt );
+ }
+}
+
+/*************************************************************************
+ * SwTxtFormatInfo::ChgHyph()
+ *************************************************************************/
+
+sal_Bool SwTxtFormatInfo::ChgHyph( const sal_Bool bNew )
+{
+ const sal_Bool bOld = bAutoHyph;
+ if( bAutoHyph != bNew )
+ {
+ bAutoHyph = bNew;
+ InitHyph( bNew );
+ // 5744: Sprache am Hyphenator einstellen.
+ if( pFnt )
+ pFnt->ChgPhysFnt( pVsh, *pOut );
+ }
+ return bOld;
+}
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/text/inftxt.hxx b/sw/source/core/text/inftxt.hxx
new file mode 100644
index 000000000000..45f153c53612
--- /dev/null
+++ b/sw/source/core/text/inftxt.hxx
@@ -0,0 +1,896 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+#ifndef _INFTXT_HXX
+#define _INFTXT_HXX
+#include <com/sun/star/linguistic2/XHyphenatedWord.hpp>
+#include <com/sun/star/beans/PropertyValues.hpp>
+
+#include <tools/table.hxx>
+
+#include "swtypes.hxx"
+#include "txttypes.hxx"
+#include "swrect.hxx"
+#include "txtfly.hxx"
+#include "swfont.hxx"
+#include "porlay.hxx"
+#include "txtfrm.hxx"
+#include "ndtxt.hxx"
+#include <editeng/paravertalignitem.hxx>
+
+class Font;
+class OutputDevice;
+class SvxBrushItem;
+class SvxLineSpacingItem;
+class SvxTabStop;
+class SvxTabStopItem;
+class SwAttrSet;
+class SwFldPortion;
+class SwFlyPortion;
+class SwFmtDrop;
+class SwLineLayout;
+class SwLinePortion;
+class SwParaPortion;
+class SwTabPortion;
+class SwTxtFrm;
+class SwTxtSizeInfo;
+class SwViewOption;
+class ViewShell;
+class SwTxtFtn;
+class SwAttrIter;
+struct SwMultiCreator;
+class SwMultiPortion;
+class SwWrongList;
+
+/* Minimum: Prozentwert fuers kernen */
+#define MINKERNPERCENT 5
+#define ARROW_WIDTH 200
+#define DIR_LEFT2RIGHT 0
+#define DIR_BOTTOM2TOP 1
+#define DIR_RIGHT2LEFT 2
+#define DIR_TOP2BOTTOM 3
+
+#if OSL_DEBUG_LEVEL > 1
+#define OPTCALM( rInf ) (rInf).IsOptCalm()
+#define OPTLOW( rInf ) (rInf).IsOptLow()
+#define OPTDBG( rInf ) (rInf).IsOptDbg()
+#else
+#define OPTCALM( rInf ) sal_True
+#define OPTLOW( rInf ) sal_False
+#define OPTDBG( rInf ) sal_False
+#endif
+
+/*************************************************************************
+ * class SwLineInfo
+ *************************************************************************/
+
+// Beruecksichtigt das Attribut LineSpace bei der Hoehen/Ascentberechnung.
+
+class SwLineInfo
+{
+ friend class SwTxtIter;
+
+ SvxTabStopItem* pRuler;
+ const SvxLineSpacingItem *pSpace;
+ sal_uInt16 nVertAlign;
+ KSHORT nDefTabStop;
+ bool bListTabStopIncluded;
+ long nListTabStopPosition;
+
+ void CtorInitLineInfo( const SwAttrSet& rAttrSet,
+ const SwTxtNode& rTxtNode );
+
+ SwLineInfo();
+ ~SwLineInfo();
+public:
+// const SvxTabStop *GetTabStop( const SwTwips nLinePos,
+// const SwTwips nLeft,
+ // #i24363# tab stops relative to indent - returns the tab stop following nSearchPos or NULL
+ const SvxTabStop *GetTabStop( const SwTwips nSearchPos,
+ const SwTwips nRight ) const;
+ inline const SvxLineSpacingItem *GetLineSpacing() const { return pSpace; }
+ inline KSHORT GetDefTabStop() const { return nDefTabStop; }
+ inline void SetDefTabStop( KSHORT nNew ) const
+ { ( (SwLineInfo*)this )->nDefTabStop = nNew; }
+
+ // vertical alignment
+ inline sal_uInt16 GetVertAlign() const { return nVertAlign; }
+ inline sal_Bool HasSpecialAlign( sal_Bool bVert ) const
+ { return bVert ?
+ ( SvxParaVertAlignItem::BASELINE != nVertAlign ) :
+ ( SvxParaVertAlignItem::BASELINE != nVertAlign &&
+ SvxParaVertAlignItem::AUTOMATIC != nVertAlign ); }
+
+ sal_uInt16 NumberOfTabStops() const;
+
+ inline bool IsListTabStopIncluded() const
+ {
+ return bListTabStopIncluded;
+ }
+ inline long GetListTabStopPosition() const
+ {
+ return nListTabStopPosition;
+ }
+
+// friend ostream &operator<<( ostream &rOS, const SwLineInfo &rInf );
+ friend SvStream &operator<<( SvStream &rOS, const SwLineInfo &rInf );
+};
+
+/*************************************************************************
+ * class SwTxtInfo
+ *************************************************************************/
+
+class SwTxtInfo
+{
+ // Implementation in txthyph.cxx
+ friend void SetParaPortion( SwTxtInfo *pInf, SwParaPortion *pRoot );
+ SwParaPortion *pPara;
+ xub_StrLen nTxtStart; // TxtOfst bei Follows
+
+protected:
+ inline SwTxtInfo() : pPara(0) {}
+public:
+ void CtorInitTxtInfo( SwTxtFrm *pFrm );
+ SwTxtInfo( const SwTxtInfo &rInf );
+ inline SwTxtInfo( SwTxtFrm *pFrm ) { CtorInitTxtInfo( pFrm ); }
+ inline SwParaPortion *GetParaPortion() { return pPara; }
+ inline const SwParaPortion *GetParaPortion() const { return pPara; }
+ inline xub_StrLen GetTxtStart() const { return nTxtStart; }
+
+ friend SvStream &operator<<( SvStream &rOS, const SwTxtInfo &rInf );
+};
+
+/*************************************************************************
+ * class SwTxtSizeInfo
+ *************************************************************************/
+
+DECLARE_TABLE( SwTxtPortionTable, sal_IntPtr )
+
+class SwTxtSizeInfo : public SwTxtInfo
+{
+protected:
+ // during formatting, a small database is built, mapping portion pointers
+ // to their maximum size (used for kana compression)
+ SwTxtPortionTable aMaxWidth;
+ // for each line, an array of compression values is calculated
+ // this array is passed over to the info structure
+ SvUShorts* pKanaComp;
+
+ ViewShell *pVsh;
+
+ // pOut is the output device, pRef is the device used for formatting
+ OutputDevice* pOut;
+ OutputDevice* pRef;
+
+ SwFont *pFnt;
+ SwUnderlineFont *pUnderFnt; // Font for underlining
+ SwTxtFrm *pFrm;
+ const SwViewOption *pOpt;
+ const XubString *pTxt;
+ xub_StrLen nIdx, nLen;
+ sal_uInt16 nKanaIdx;
+ sal_Bool bOnWin : 1;
+ sal_Bool bNotEOL : 1;
+ sal_Bool bURLNotify : 1;
+ sal_Bool bStopUnderFlow : 1;// Underflow gestoppt z.B. von einer FlyPortion
+ sal_Bool bFtnInside : 1; // the current line contains a footnote
+ sal_Bool bOtherThanFtnInside : 1; // the current line contains another portion than a footnote portion.
+ // needed for checking keep together of footnote portion with previous portion
+ sal_Bool bMulti : 1; // inside a multiportion
+ sal_Bool bFirstMulti : 1; // this flag is used for two purposes:
+ // - the multiportion is the first lineportion
+ // - indicates, if we are currently in second
+ // line of multi portion
+ sal_Bool bRuby : 1; // during the formatting of a phonetic line
+ sal_Bool bHanging : 1; // formatting of hanging punctuation allowed
+ sal_Bool bScriptSpace : 1; // space between different scripts (Asian/Latin)
+ sal_Bool bForbiddenChars : 1; // Forbidden start/endline characters
+ sal_Bool bSnapToGrid : 1; // paragraph snaps to grid
+ sal_uInt8 nDirection : 2; // writing direction: 0/90/180/270 degree
+
+protected:
+ void CtorInitTxtSizeInfo( SwTxtFrm *pFrm, SwFont *pFnt = 0,
+ const xub_StrLen nIdx = 0,
+ const xub_StrLen nLen = STRING_LEN );
+ SwTxtSizeInfo() : pKanaComp(0), pVsh(0), pOut(0), pRef(0), pFnt(0), pUnderFnt(0), pFrm(0), pOpt(0), pTxt(0) {}
+public:
+ SwTxtSizeInfo( const SwTxtSizeInfo &rInf );
+ SwTxtSizeInfo( const SwTxtSizeInfo &rInf, const XubString &rTxt,
+ const xub_StrLen nIdx = 0,
+ const xub_StrLen nLen = STRING_LEN );
+
+ inline SwTxtSizeInfo( SwTxtFrm *pTxtFrm, SwFont *pTxtFnt = 0,
+ const xub_StrLen nIndex = 0,
+ const xub_StrLen nLength = STRING_LEN )
+ { CtorInitTxtSizeInfo( pTxtFrm, pTxtFnt, nIndex, nLength ); }
+
+ // GetMultiAttr returns the text attribute of the multiportion,
+ // if rPos is inside any multi-line part.
+ // rPos will set to the end of the multi-line part.
+ SwMultiCreator* GetMultiCreator( xub_StrLen &rPos, SwMultiPortion* pM ) const;
+
+ inline sal_Bool OnWin() const { return bOnWin; }
+ inline void SetOnWin( const sal_Bool bNew ) { bOnWin = bNew; }
+ inline sal_Bool NotEOL() const { return bNotEOL; }
+ inline void SetNotEOL( const sal_Bool bNew ) { bNotEOL = bNew; }
+ inline sal_Bool URLNotify() const { return bURLNotify; }
+ inline void SetURLNotify( const sal_Bool bNew ) { bURLNotify = bNew; }
+ inline sal_Bool StopUnderFlow() const { return bStopUnderFlow; }
+ inline void SetStopUnderFlow( const sal_Bool bNew ) { bStopUnderFlow = bNew; }
+ inline sal_Bool IsFtnInside() const { return bFtnInside; }
+ inline void SetFtnInside( const sal_Bool bNew ) { bFtnInside = bNew; }
+ inline sal_Bool IsOtherThanFtnInside() const { return bOtherThanFtnInside; }
+ inline void SetOtherThanFtnInside( const sal_Bool bNew ) { bOtherThanFtnInside = bNew; }
+ inline sal_Bool IsMulti() const { return bMulti; }
+ inline void SetMulti( const sal_Bool bNew ) { bMulti = bNew; }
+ inline sal_Bool IsFirstMulti() const { return bFirstMulti; }
+ inline void SetFirstMulti( const sal_Bool bNew ) { bFirstMulti = bNew; }
+ inline sal_Bool IsRuby() const { return bRuby; }
+ inline void SetRuby( const sal_Bool bNew ) { bRuby = bNew; }
+ inline sal_Bool IsHanging() const { return bHanging; }
+ inline void SetHanging( const sal_Bool bNew ) { bHanging = bNew; }
+ inline sal_Bool HasScriptSpace() const { return bScriptSpace; }
+ inline void SetScriptSpace( const sal_Bool bNew ) { bScriptSpace = bNew; }
+ inline sal_Bool HasForbiddenChars() const { return bForbiddenChars; }
+ inline void SetForbiddenChars( const sal_Bool bN ) { bForbiddenChars = bN; }
+ inline sal_Bool SnapToGrid() const { return bSnapToGrid; }
+ inline void SetSnapToGrid( const sal_Bool bN ) { bSnapToGrid = bN; }
+ inline sal_uInt8 GetDirection() const { return nDirection; }
+ inline void SetDirection( const sal_uInt8 nNew ) { nDirection = nNew; }
+ inline sal_Bool IsRotated() const { return 0 != ( 1 & nDirection ); }
+
+ inline ViewShell *GetVsh() { return pVsh; }
+ inline const ViewShell *GetVsh() const { return pVsh; }
+
+ inline OutputDevice *GetOut() { return pOut; }
+ inline const OutputDevice *GetOut() const { return pOut; }
+ inline void SetOut( OutputDevice* pNewOut ) { pOut = pNewOut; }
+
+ inline OutputDevice *GetRefDev() { return pRef; }
+ inline const OutputDevice *GetRefDev() const { return pRef; }
+
+ inline SwFont *GetFont() { return pFnt; }
+ inline const SwFont *GetFont() const { return pFnt; }
+ inline void SetFont( SwFont *pNew ) { pFnt = pNew; }
+ void SelectFont();
+ inline void SetUnderFnt( SwUnderlineFont* pNew ) { pUnderFnt = pNew; }
+ inline SwUnderlineFont* GetUnderFnt() const { return pUnderFnt; }
+
+ inline const SwViewOption &GetOpt() const { return *pOpt; }
+ inline const XubString &GetTxt() const { return *pTxt; }
+ inline xub_Unicode GetChar( const xub_StrLen nPos ) const
+ { return pTxt->GetChar( nPos ); }
+
+ inline KSHORT GetTxtHeight() const;
+
+ //
+ // GetTxtSize
+ //
+ SwPosSize GetTxtSize( OutputDevice* pOut, const SwScriptInfo* pSI,
+ const XubString& rTxt, const xub_StrLen nIdx,
+ const xub_StrLen nLen, const sal_uInt16 nComp ) const;
+ SwPosSize GetTxtSize() const;
+ void GetTxtSize( const SwScriptInfo* pSI, const xub_StrLen nIdx,
+ const xub_StrLen nLen, const sal_uInt16 nComp,
+ sal_uInt16& nMinSize, sal_uInt16& nMaxSizeDiff ) const;
+ inline SwPosSize GetTxtSize( const SwScriptInfo* pSI, const xub_StrLen nIdx,
+ const xub_StrLen nLen, const sal_uInt16 nComp ) const;
+ inline SwPosSize GetTxtSize( const XubString &rTxt ) const;
+
+ //
+ // GetTxtBreak
+ //
+ xub_StrLen GetTxtBreak( const long nLineWidth,
+ const xub_StrLen nMaxLen,
+ const sal_uInt16 nComp ) const;
+ xub_StrLen GetTxtBreak( const long nLineWidth,
+ const xub_StrLen nMaxLen,
+ const sal_uInt16 nComp,
+ xub_StrLen& rExtraCharPos ) const;
+
+ inline KSHORT GetAscent() const;
+
+ inline xub_StrLen GetIdx() const { return nIdx; }
+ inline void SetIdx( const xub_StrLen nNew ) { nIdx = nNew; }
+ inline xub_StrLen GetLen() const { return nLen; }
+ inline void SetLen( const xub_StrLen nNew ) { nLen = nNew; }
+ inline void SetTxt( const XubString &rNew ){ pTxt = &rNew; }
+
+ friend SvStream &operator<<( SvStream &rOS, const SwTxtSizeInfo &rInf );
+
+// 7780: Keine Bullets beim Symbol-Zeichensatz!
+ inline sal_Bool IsNoSymbol() const
+ { return RTL_TEXTENCODING_SYMBOL != pFnt->GetCharSet( pFnt->GetActual() ); }
+
+ void NoteAnimation() const;
+
+ // Home is where Your heart is...
+ inline SwTxtFrm *GetTxtFrm() { return pFrm; }
+ inline const SwTxtFrm *GetTxtFrm() const { return pFrm; }
+
+ inline sal_Bool HasHint( xub_StrLen nPos ) const
+ { return _HasHint( pFrm->GetTxtNode(), nPos ); }
+ static sal_Bool _HasHint( const SwTxtNode* pTxtNode, xub_StrLen nPos );
+
+ // If Kana Compression is enabled, a minimum and maximum portion width
+ // is calculated. We format lines with minimal size and share remaining
+ // space among compressed kanas.
+ // During formatting, the maximum values of compressable portions are
+ // stored in aMaxWidth and discarded after a line has been formatted.
+ inline void SetMaxWidthDiff( sal_uLong nKey, sal_uInt16 nVal )
+ {
+ aMaxWidth.Insert( nKey, nVal );
+ };
+ inline sal_uInt16 GetMaxWidthDiff( sal_uLong nKey )
+ {
+ return (sal_uInt16)aMaxWidth.Get( nKey );
+ };
+ inline void ResetMaxWidthDiff()
+ {
+ aMaxWidth.Clear();
+ };
+ inline sal_Bool CompressLine()
+ {
+ return (sal_Bool)aMaxWidth.Count();
+ };
+
+ //
+ // Feature: Kana Compression
+ //
+ inline MSHORT GetKanaIdx() const { return nKanaIdx; }
+ inline void ResetKanaIdx(){ nKanaIdx = 0; }
+ inline void SetKanaIdx( MSHORT nNew ) { nKanaIdx = nNew; }
+ inline void IncKanaIdx() { ++nKanaIdx; }
+ inline void SetKanaComp( SvUShorts *pNew ){ pKanaComp = pNew; }
+ inline SvUShorts* GetpKanaComp() const { return pKanaComp; }
+ inline sal_uInt16 GetKanaComp() const
+ { return ( pKanaComp && nKanaIdx < pKanaComp->Count() )
+ ? (*pKanaComp)[nKanaIdx] : 0; }
+
+#if OSL_DEBUG_LEVEL > 1
+ sal_Bool IsOptCalm() const;
+ sal_Bool IsOptLow() const;
+ sal_Bool IsOptDbg() const;
+ sal_Bool IsOptTest1() const;
+ sal_Bool IsOptTest2() const;
+ sal_Bool IsOptTest3() const;
+ sal_Bool IsOptTest4() const;
+ sal_Bool IsOptTest5() const;
+ sal_Bool IsOptTest6() const;
+ sal_Bool IsOptTest7() const;
+ sal_Bool IsOptTest8() const;
+#endif
+};
+
+/*************************************************************************
+ * class SwTxtPaintInfo
+ *************************************************************************/
+
+class SwTxtPaintInfo : public SwTxtSizeInfo
+{
+ const SwWrongList *pWrongList;
+ const SwWrongList *pGrammarCheckList;
+ const SwWrongList *pSmartTags; // SMARTTAGS
+ std::vector<long>* pSpaceAdd;
+ const SvxBrushItem *pBrushItem; // Fuer den Hintergrund
+ SwRect aItemRect; // ebenfalls fuer den Hintergrund
+ SwTxtFly aTxtFly; // FlyFrm-Berechnung
+ Point aPos; // Ausgabeposition
+ SwRect aPaintRect; // Original Ausgaberechteck (aus Layout-Paint)
+
+ MSHORT nSpaceIdx;
+ void _DrawText( const XubString &rText, const SwLinePortion &rPor,
+ const xub_StrLen nIdx, const xub_StrLen nLen,
+ const sal_Bool bKern, const sal_Bool bWrong = sal_False,
+ const sal_Bool bSmartTag = sal_False,
+ const sal_Bool bGrammarCheck = sal_False ); // SMARTTAGS
+
+ SwTxtPaintInfo &operator=(const SwTxtPaintInfo&);
+ void _NotifyURL( const SwLinePortion &rPor ) const;
+ void _DrawBackBrush( const SwLinePortion &rPor ) const;
+
+protected:
+#if OSL_DEBUG_LEVEL > 1
+ SwTxtPaintInfo() { pFrm = 0; pWrongList = 0; pGrammarCheckList = 0; pSmartTags = 0; pSpaceAdd = 0;
+ pBrushItem = ((SvxBrushItem*)-1);}
+#else
+ SwTxtPaintInfo() { pFrm = 0; pWrongList = 0; pGrammarCheckList = 0; pWrongList = 0; pSmartTags = 0; pSpaceAdd = 0; pBrushItem = 0;}
+#endif
+public:
+ SwTxtPaintInfo( const SwTxtPaintInfo &rInf );
+ SwTxtPaintInfo( const SwTxtPaintInfo &rInf, const XubString &rTxt );
+
+ void CtorInitTxtPaintInfo( SwTxtFrm *pFrame, const SwRect &rPaint );
+
+ void SetBack( const SvxBrushItem *pItem,
+ const SwRect &rRect ) { pBrushItem = pItem; aItemRect = rRect;}
+ const SvxBrushItem *GetBrushItem() const { return pBrushItem; }
+ const SwRect &GetBrushRect() const { return aItemRect; }
+
+ inline SwTxtPaintInfo( SwTxtFrm *pFrame, const SwRect &rPaint )
+ { CtorInitTxtPaintInfo( pFrame, rPaint ); }
+
+ inline SwTwips X() const { return aPos.X(); }
+ inline void X( const long nNew ) { aPos.X() = nNew; }
+ inline SwTwips Y() const { return aPos.Y(); }
+ inline void Y( const SwTwips nNew ) { aPos.Y() = nNew; }
+
+ inline SwTxtFly *GetTxtFly() { return &aTxtFly; }
+ inline const SwTxtFly *GetTxtFly() const { return &aTxtFly; }
+ inline void DrawText( const XubString &rText, const SwLinePortion &rPor,
+ const xub_StrLen nIdx = 0,
+ const xub_StrLen nLen = STRING_LEN,
+ const sal_Bool bKern = sal_False) const;
+ inline void DrawText( const SwLinePortion &rPor, const xub_StrLen nLen,
+ const sal_Bool bKern = sal_False ) const;
+ inline void DrawMarkedText( const SwLinePortion &rPor, const xub_StrLen nLen,
+ const sal_Bool bKern,
+ const sal_Bool bWrong,
+ const sal_Bool bSmartTags,
+ const sal_Bool bGrammarCheck ) const;
+
+ void DrawRect( const SwRect &rRect, sal_Bool bNoGraphic = sal_False,
+ sal_Bool bRetouche = sal_True ) const;
+ void DrawTab( const SwLinePortion &rPor ) const;
+ void DrawLineBreak( const SwLinePortion &rPor ) const;
+ void DrawRedArrow( const SwLinePortion &rPor ) const;
+ void DrawPostIts( const SwLinePortion &rPor, sal_Bool bScript ) const;
+ void DrawBackground( const SwLinePortion &rPor ) const;
+ void DrawViewOpt( const SwLinePortion &rPor, const MSHORT nWhich ) const;
+ inline void DrawBackBrush( const SwLinePortion &rPor ) const
+ { /* if( pFnt->GetBackColor() ) */ _DrawBackBrush( rPor ); }
+
+ void DrawCheckBox( const SwFieldFormPortion &rPor, bool checked) const;
+
+ inline void NotifyURL( const SwLinePortion &rPor ) const
+ { if( URLNotify() ) _NotifyURL( rPor ); }
+
+ void CalcRect( const SwLinePortion& rPor, SwRect* pRect, SwRect* pIntersect = 0 ) const;
+
+ inline SwTwips GetPaintOfst() const;
+ inline void SetPaintOfst( const SwTwips nNew );
+ inline const Point &GetPos() const { return aPos; }
+ inline void SetPos( const Point &rNew ) { aPos = rNew; }
+
+ inline const SwRect &GetPaintRect() const { return aPaintRect; }
+ inline void SetPaintRect( const SwRect &rNew ) { aPaintRect = rNew; }
+
+ friend SvStream &operator<<( SvStream &rOS, const SwTxtPaintInfo &rInf );
+
+ //
+ // STUFF FOR JUSTIFIED ALIGNMENT
+ //
+ inline MSHORT GetSpaceIdx() const { return nSpaceIdx; }
+ inline void ResetSpaceIdx(){nSpaceIdx = 0; }
+ inline void SetSpaceIdx( MSHORT nNew ) { nSpaceIdx = nNew; }
+ inline void IncSpaceIdx() { ++nSpaceIdx; }
+ inline void RemoveFirstSpaceAdd() { pSpaceAdd->erase( pSpaceAdd->begin() ); }
+ inline long GetSpaceAdd() const
+ { return ( pSpaceAdd && nSpaceIdx < pSpaceAdd->size() )
+ ? (*pSpaceAdd)[nSpaceIdx] : 0; }
+
+ inline void SetpSpaceAdd( std::vector<long>* pNew ){ pSpaceAdd = pNew; }
+ inline std::vector<long>* GetpSpaceAdd() const { return pSpaceAdd; }
+
+
+ inline void SetWrongList( const SwWrongList *pNew ){ pWrongList = pNew; }
+ inline const SwWrongList* GetpWrongList() const { return pWrongList; }
+
+ inline void SetGrammarCheckList( const SwWrongList *pNew ){ pGrammarCheckList = pNew; }
+ inline const SwWrongList* GetGrammarCheckList() const { return pGrammarCheckList; }
+
+ // SMARTTAGS
+ inline void SetSmartTags( const SwWrongList *pNew ){ pSmartTags = pNew; }
+ inline const SwWrongList* GetSmartTags() const { return pSmartTags; }
+};
+
+/*************************************************************************
+ * class SwTxtFormatInfo
+ *************************************************************************/
+
+class SwTxtFormatInfo : public SwTxtPaintInfo
+{
+ // temporary arguments for hyphenation
+ com::sun::star::beans::PropertyValues aHyphVals;
+
+ SwLineLayout *pRoot; // die Root der aktuellen Zeile (pCurr)
+ SwLinePortion *pLast; // die letzte Portion
+ SwFlyPortion *pFly; // die nachfolgende FlyPortion
+ SwFldPortion *pLastFld; // umgebrochenes Feld
+ SwLinePortion *pUnderFlow; // Unterlaufsituation: letzte Portion
+ SwLinePortion *pRest; // Rest ist der Beginn der naechsten Zeile
+
+ SwTabPortion *pLastTab; // die _letzte_ TabPortion
+
+ xub_StrLen nSoftHyphPos; // SoftHyphPos fuer Hyphenate
+ xub_StrLen nHyphStart; // TxtPos, an der die interakt.Tr.z.Z. steht
+ xub_StrLen nHyphWrdStart; // gefundene Wort-Position
+ xub_StrLen nHyphWrdLen; // gefundene Wort-Laenge
+ xub_StrLen nLineStart; // aktueller Zeilenbeginn im rTxt
+ xub_StrLen nUnderScorePos; // enlarge repaint if underscore has been found
+ // --> FME 2004-11-25 #i34348# Changed type from sal_uInt16 to SwTwips
+ SwTwips nLeft; // linker Rand
+ SwTwips nRight; // rechter Rand
+ SwTwips nFirst; // EZE
+ // <--
+ KSHORT nRealWidth; // "echte" Zeilenbreite
+ KSHORT nWidth; // "virtuelle" Zeilenbreite
+ KSHORT nLineHeight; // endgueltige Hoehe nach CalcLine
+ KSHORT nLineNettoHeight; // line height without spacing
+ KSHORT nForcedLeftMargin; // Verschiebung des linken Rands wg. Rahmen
+
+ sal_Int16 nMinLeading; // minimum number of chars before hyphenation point
+ sal_Int16 nMinTrailing; // minimum number of chars after hyphenation point
+ sal_Int16 nMinWordLength; // minimum length of word to be hyphenated
+
+ sal_Bool bFull : 1; // Zeile ist voll
+ sal_Bool bFtnDone : 1; // Ftn bereits formatiert
+ sal_Bool bErgoDone : 1; // ErgoDone bereits formatiert
+ sal_Bool bNumDone : 1; // bNumDone bereits formatiert
+ sal_Bool bArrowDone : 1; // Pfeil nach links bei gescrollten Absaetzen
+ sal_Bool bStop : 1; // Sofort abbrechen, Zeile verwerfen.
+ sal_Bool bNewLine : 1; // Noch eine weitere Zeile formatieren.
+ sal_Bool bShift : 1; // Positionsaend.: Repaint bis auf Weiteres
+ sal_Bool bUnderFlow : 1; // Kontext: UnderFlow() ?
+ sal_Bool bInterHyph: 1; // interaktive Trennung ?
+ sal_Bool bAutoHyph : 1; // automatische Trennung ?
+ sal_Bool bDropInit : 1; // DropWidth einstellen.
+ sal_Bool bQuick : 1; // FormatQuick()
+ sal_Bool bNoEndHyph : 1; // Trennung am Zeilenende abgeschaltet wg. MaxHyphens
+ sal_Bool bNoMidHyph : 1; // Trennung vor Flies abgeschaltet wg. MaxHyphens
+ sal_Bool bIgnoreFly: 1; // FitToContent ignoriert Flies
+ sal_Bool bFakeLineStart: 1; // String has been replaced by field portion
+ // info structure only pretends that we are at
+ // the beginning of a line
+
+ xub_Unicode cTabDecimal; // das _aktuelle_ Dezimalzeichen
+ xub_Unicode cHookChar; // fuer Tabs in Feldern etc.
+ sal_uInt8 nMaxHyph; // max. Zeilenanz. aufeinanderfolg. Trenn.
+ sal_Bool bTestFormat; // Testformatierung aus WouldFit, keine Benachrichtigungen etc.
+
+ // Hyphenating ...
+ sal_Bool InitHyph( const sal_Bool bAuto = sal_False );
+ sal_Bool _CheckFtnPortion( SwLineLayout* pCurr );
+
+public:
+ void CtorInitTxtFormatInfo( SwTxtFrm *pFrm, const sal_Bool bInterHyph = sal_False,
+ const sal_Bool bQuick = sal_False, const sal_Bool bTst = sal_False );
+ inline SwTxtFormatInfo(SwTxtFrm *pFrame,const sal_Bool bInterHyphL=sal_False,
+ const sal_Bool bQuickL = sal_False, const sal_Bool bTst = sal_False )
+ { CtorInitTxtFormatInfo( pFrame, bInterHyphL, bQuickL, bTst ); }
+
+ // For the formatting inside a double line in a line (multi-line portion)
+ // we need a modified text-format-info:
+ SwTxtFormatInfo( const SwTxtFormatInfo& rInf, SwLineLayout& rLay,
+ SwTwips nActWidth );
+
+ inline KSHORT Width() const { return nWidth; }
+ inline void Width( const KSHORT nNew ) { nWidth = nNew; }
+ void Init();
+
+ // liefert die erste veraenderte Position im Absatz zurueck
+ inline xub_StrLen GetReformatStart() const;
+
+ // Raender
+ inline SwTwips Left() const { return nLeft; }
+ inline void Left( const SwTwips nNew ) { nLeft = nNew; }
+ inline SwTwips Right() const { return nRight; }
+ inline void Right( const SwTwips nNew ) { nRight = nNew; }
+ inline SwTwips First() const { return nFirst; }
+ inline void First( const SwTwips nNew ) { nFirst = nNew; }
+ inline SwTwips CurrLeft() const { return (nLineStart ? nLeft : nFirst); }
+ inline KSHORT RealWidth() const { return nRealWidth; }
+ inline void RealWidth( const KSHORT nNew ) { nRealWidth = nNew; }
+ inline KSHORT ForcedLeftMargin() const { return nForcedLeftMargin; }
+ inline void ForcedLeftMargin( const KSHORT nN ) { nForcedLeftMargin = nN; }
+
+ inline sal_uInt8 &MaxHyph() { return nMaxHyph; }
+ inline const sal_uInt8 &MaxHyph() const { return nMaxHyph; }
+
+ inline SwLineLayout *GetRoot() { return pRoot; }
+ inline const SwLineLayout *GetRoot() const { return pRoot; }
+
+ inline void SetRoot( SwLineLayout *pNew ) { pRoot = pNew; }
+ inline SwLinePortion *GetLast() { return pLast; }
+ inline void SetLast( SwLinePortion *pNewLast ) { pLast = pNewLast; }
+ inline sal_Bool IsFull() const { return bFull; }
+ inline void SetFull( const sal_Bool bNew ) { bFull = bNew; }
+ inline sal_Bool IsHyphForbud() const
+ { return pFly ? bNoMidHyph : bNoEndHyph; }
+ inline void SetHyphForbud( const sal_Bool bNew )
+ { if ( pFly ) bNoMidHyph = bNew; else bNoEndHyph = bNew; }
+ inline void ChkNoHyph( const sal_uInt8 bEnd, const sal_uInt8 bMid )
+ { bNoEndHyph = (nMaxHyph && bEnd >= nMaxHyph);
+ bNoMidHyph = (nMaxHyph && bMid >= nMaxHyph); }
+ inline sal_Bool IsIgnoreFly() const { return bIgnoreFly; }
+ inline void SetIgnoreFly( const sal_Bool bNew ) { bIgnoreFly = bNew; }
+ inline sal_Bool IsFakeLineStart() const { return bFakeLineStart; }
+ inline void SetFakeLineStart( const sal_Bool bNew ) { bFakeLineStart = bNew; }
+ inline sal_Bool IsStop() const { return bStop; }
+ inline void SetStop( const sal_Bool bNew ) { bStop = bNew; }
+ inline SwLinePortion *GetRest() { return pRest; }
+ inline void SetRest( SwLinePortion *pNewRest ) { pRest = pNewRest; }
+ inline sal_Bool IsNewLine() const { return bNewLine; }
+ inline void SetNewLine( const sal_Bool bNew ) { bNewLine = bNew; }
+ inline sal_Bool IsShift() const { return bShift; }
+ inline void SetShift( const sal_Bool bNew ) { bShift = bNew; }
+ inline sal_Bool IsInterHyph() const { return bInterHyph; }
+ inline sal_Bool IsAutoHyph() const { return bAutoHyph; }
+ inline sal_Bool IsUnderFlow() const { return bUnderFlow; }
+ inline void ClrUnderFlow() { bUnderFlow = sal_False; }
+ inline sal_Bool IsDropInit() const { return bDropInit; }
+ inline void SetDropInit( const sal_Bool bNew ) { bDropInit = bNew; }
+ inline sal_Bool IsQuick() const { return bQuick; }
+ inline sal_Bool IsTest() const { return bTestFormat; }
+
+ inline xub_StrLen GetLineStart() const { return nLineStart; }
+ inline void SetLineStart( const xub_StrLen nNew ) { nLineStart = nNew; }
+
+ // these are used during fly calculation
+ inline KSHORT GetLineHeight() const { return nLineHeight; }
+ inline void SetLineHeight( const KSHORT nNew ) { nLineHeight = nNew; }
+ inline KSHORT GetLineNettoHeight() const { return nLineNettoHeight; }
+ inline void SetLineNettoHeight( const KSHORT nNew ) { nLineNettoHeight = nNew; }
+
+ inline const SwLinePortion *GetUnderFlow() const { return pUnderFlow; }
+ inline SwLinePortion *GetUnderFlow() { return pUnderFlow; }
+ inline void SetUnderFlow( SwLinePortion *pNew )
+ { pUnderFlow = pNew; bUnderFlow = sal_True; }
+ inline xub_StrLen GetSoftHyphPos() const { return nSoftHyphPos; }
+ inline void SetSoftHyphPos( const xub_StrLen nNew ) { nSoftHyphPos = nNew; }
+
+ inline void SetParaFtn();
+
+ // FlyFrms
+ inline SwFlyPortion *GetFly() { return pFly; }
+ inline void SetFly( SwFlyPortion *pNew ) { pFly = pNew; }
+
+ inline const SwAttrSet& GetCharAttr() const;
+
+ // Tabs
+ inline SwTabPortion *GetLastTab() { return pLastTab; }
+ inline void SetLastTab( SwTabPortion *pNew ) { pLastTab = pNew; }
+ inline xub_Unicode GetTabDecimal() const { return cTabDecimal; }
+ inline void SetTabDecimal( const xub_Unicode cNew ) { cTabDecimal = cNew;}
+
+ // Last*
+ inline SwFldPortion *GetLastFld() { return pLastFld; }
+ inline void SetLastFld( SwFldPortion *pNew ) { pLastFld = pNew; }
+
+ inline void ClearHookChar() { cHookChar = 0; }
+ inline void SetHookChar( const xub_Unicode cNew ) { cHookChar = cNew; }
+ inline xub_Unicode GetHookChar() const { return cHookChar; }
+
+ // Done-Flags
+ inline sal_Bool IsFtnDone() const { return bFtnDone; }
+ inline void SetFtnDone( const sal_Bool bNew ) { bFtnDone = bNew; }
+ inline sal_Bool IsErgoDone() const { return bErgoDone; }
+ inline void SetErgoDone( const sal_Bool bNew ) { bErgoDone = bNew; }
+ inline sal_Bool IsNumDone() const { return bNumDone; }
+ inline void SetNumDone( const sal_Bool bNew ) { bNumDone = bNew; }
+ inline sal_Bool IsArrowDone() const { return bArrowDone; }
+ inline void SetArrowDone( const sal_Bool bNew ) { bArrowDone = bNew; }
+
+ // Fuer SwTxtPortion::Hyphenate
+ inline sal_Bool IsSoftHyph( const xub_StrLen nPos ) const;
+ sal_Bool ChgHyph( const sal_Bool bNew );
+
+ // Soll die Trennhilfe angeschmissen werden?
+ sal_Bool IsHyphenate() const;
+ inline void SetHyphStart( const xub_StrLen nNew ) { nHyphStart = nNew; }
+ inline xub_StrLen GetHyphStart() const { return nHyphStart; }
+ inline void SetHyphWrdStart( const xub_StrLen nNew ) { nHyphWrdStart = nNew; }
+ inline xub_StrLen GetHyphWrdStart() const { return nHyphWrdStart; }
+ inline void SetHyphWrdLen( const xub_StrLen nNew ) { nHyphWrdLen = nNew; }
+ inline xub_StrLen GetHyphWrdLen() const { return nHyphWrdLen; }
+ inline xub_StrLen GetUnderScorePos() const { return nUnderScorePos; }
+ inline void SetUnderScorePos( xub_StrLen nNew ) { nUnderScorePos = nNew; }
+
+ // ruft HyphenateWord() des Hyphenators
+ ::com::sun::star::uno::Reference<
+ ::com::sun::star::linguistic2::XHyphenatedWord >
+ HyphWord( const String &rTxt, const sal_uInt16 nMinTrail );
+ const com::sun::star::beans::PropertyValues &
+ GetHyphValues() const;
+
+ sal_Bool CheckFtnPortion( SwLineLayout* pCurr )
+ { return IsFtnInside() && _CheckFtnPortion( pCurr ); }
+
+ // Dropcaps vom SwTxtFormatter::CTOR gerufen.
+ const SwFmtDrop *GetDropFmt() const;
+
+ // setzt die FormatInfo wieder in den Anfangszustand
+ void Reset( const SwTxtFrm *pFrame); // , const sal_Bool bAll );
+
+ // Sets the last SwKernPortion as pLast, if it is followed by empty portions
+ sal_Bool LastKernPortion();
+
+ // Sucht ab nIdx bis nEnd nach Tabs, TabDec, TXTATR und BRK.
+ // Return: gefundene Position, setzt ggf. cHookChar
+ xub_StrLen ScanPortionEnd( const xub_StrLen nStart, const xub_StrLen nEnd );
+
+// friend ostream &operator<<( ostream &rOS, const SwTxtFormatInfo &rInf );
+ friend SvStream &operator<<( SvStream &rOS, const SwTxtFormatInfo &rInf );
+};
+
+/*************************************************************************
+ * class SwTxtSlot
+ *************************************************************************/
+
+// Fuer die Textersetzung und Restaurierung der SwTxtSizeInfo.
+// Die Art und Weise ist etwas kriminell, rInf ist const und wird
+// trotzdem veraendert. Da rInf im DTOR wieder restauriert wird,
+// ist dies zulaessig, es handelt sich um ein "logisches const".
+
+class SwTxtSlot
+{
+ XubString aTxt;
+ const XubString *pOldTxt;
+ const SwWrongList* pOldSmartTagList;
+ const SwWrongList* pOldGrammarCheckList;
+ SwWrongList* pTempList;
+ xub_StrLen nIdx;
+ xub_StrLen nLen;
+ sal_Bool bOn;
+protected:
+ SwTxtSizeInfo *pInf;
+public:
+ // Der Ersetzungstring kommt wahlweise aus der Portion via GetExpText()
+ // oder aus dem char Pointer pCh, wenn dieser ungleich NULL ist.
+ SwTxtSlot( const SwTxtSizeInfo *pNew, const SwLinePortion *pPor, bool bTxtLen,
+ bool bExgLists, const sal_Char *pCh = NULL );
+ ~SwTxtSlot();
+ inline sal_Bool IsOn() const { return bOn; }
+};
+
+/*************************************************************************
+ * class SwFontSave
+ *************************************************************************/
+
+class SwFontSave
+{
+ SwTxtSizeInfo *pInf;
+ SwFont *pFnt;
+ SwAttrIter *pIter;
+public:
+ SwFontSave( const SwTxtSizeInfo &rInf, SwFont *pFnt,
+ SwAttrIter* pItr = NULL );
+ ~SwFontSave();
+};
+
+/*************************************************************************
+ * class SwDefFontSave
+ *************************************************************************/
+
+class SwDefFontSave
+{
+ SwTxtSizeInfo *pInf;
+ SwFont *pFnt;
+ SwFont *pNewFnt;
+ sal_Bool bAlter;
+public:
+ SwDefFontSave( const SwTxtSizeInfo &rInf );
+ ~SwDefFontSave();
+};
+
+/*************************************************************************
+ * Inline-Implementierungen SwTxtSizeInfo
+ *************************************************************************/
+
+inline KSHORT SwTxtSizeInfo::GetAscent() const
+{
+ OSL_ENSURE( GetOut(), "SwTxtSizeInfo::GetAscent() without pOut" );
+ return ((SwFont*)GetFont())->GetAscent( pVsh, *GetOut() );
+}
+
+inline KSHORT SwTxtSizeInfo::GetTxtHeight() const
+{
+ OSL_ENSURE( GetOut(), "SwTxtSizeInfo::GetTxtHeight() without pOut" );
+ return ((SwFont*)GetFont())->GetHeight( pVsh, *GetOut() );
+}
+
+inline SwPosSize SwTxtSizeInfo::GetTxtSize( const XubString &rTxt ) const
+{
+ return GetTxtSize( pOut, 0, rTxt, 0, rTxt.Len(), 0 );
+}
+
+inline SwPosSize SwTxtSizeInfo::GetTxtSize( const SwScriptInfo* pSI,
+ const xub_StrLen nNewIdx,
+ const xub_StrLen nNewLen,
+ const sal_uInt16 nCompress ) const
+{
+ return GetTxtSize( pOut, pSI, *pTxt, nNewIdx, nNewLen, nCompress );
+}
+
+/*************************************************************************
+ * Inline-Implementierungen SwTxtPaintInfo
+ *************************************************************************/
+
+inline SwTwips SwTxtPaintInfo::GetPaintOfst() const
+{
+ return GetParaPortion()->GetRepaint()->GetOfst();
+}
+
+inline void SwTxtPaintInfo::SetPaintOfst( const SwTwips nNew )
+{
+ GetParaPortion()->GetRepaint()->SetOfst( nNew );
+}
+
+
+inline void SwTxtPaintInfo::DrawText( const XubString &rText,
+ const SwLinePortion &rPor,
+ const xub_StrLen nStart, const xub_StrLen nLength,
+ const sal_Bool bKern ) const
+{
+ ((SwTxtPaintInfo*)this)->_DrawText( rText, rPor, nStart, nLength, bKern );
+}
+
+inline void SwTxtPaintInfo::DrawText( const SwLinePortion &rPor,
+ const xub_StrLen nLength, const sal_Bool bKern ) const
+{
+ ((SwTxtPaintInfo*)this)->_DrawText( *pTxt, rPor, nIdx, nLength, bKern );
+}
+
+inline void SwTxtPaintInfo::DrawMarkedText( const SwLinePortion &rPor,
+ const xub_StrLen nLength,
+ const sal_Bool bKern,
+ const sal_Bool bWrong,
+ const sal_Bool bSmartTags,
+ const sal_Bool bGrammarCheck ) const
+{
+ ((SwTxtPaintInfo*)this)->_DrawText( *pTxt, rPor, nIdx, nLength, bKern, bWrong, bSmartTags, bGrammarCheck );
+}
+
+/*************************************************************************
+ * Inline-Implementierungen SwTxtFormatInfo
+ *************************************************************************/
+
+inline xub_StrLen SwTxtFormatInfo::GetReformatStart() const
+{
+ return GetParaPortion()->GetReformat()->Start();
+}
+
+inline const SwAttrSet& SwTxtFormatInfo::GetCharAttr() const
+{
+ return GetTxtFrm()->GetTxtNode()->GetSwAttrSet();
+}
+
+inline void SwTxtFormatInfo::SetParaFtn()
+{
+ GetTxtFrm()->SetFtn( sal_True );
+}
+
+inline sal_Bool SwTxtFormatInfo::IsSoftHyph( const xub_StrLen nPos ) const
+{
+ return CHAR_SOFTHYPHEN == GetTxtFrm()->GetTxtNode()->GetTxt().GetChar(nPos);
+}
+
+
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/text/itradj.cxx b/sw/source/core/text/itradj.cxx
new file mode 100644
index 000000000000..9323716fd6b2
--- /dev/null
+++ b/sw/source/core/text/itradj.cxx
@@ -0,0 +1,901 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+ /*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+#include <com/sun/star/i18n/ScriptType.hdl>
+#include <vcl/outdev.hxx>
+#include <IDocumentSettingAccess.hxx>
+
+#include "frame.hxx" // CalcFlyAdjust()
+#include "paratr.hxx"
+#include "itrtxt.hxx"
+#include "porglue.hxx"
+#include "porlay.hxx"
+#include "porfly.hxx" // CalcFlyAdjust()
+#include "pordrop.hxx" // CalcFlyAdjust()
+#include "pormulti.hxx"
+#include <portab.hxx>
+
+#define MIN_TAB_WIDTH 60
+
+using namespace ::com::sun::star;
+
+/*************************************************************************
+ * SwTxtAdjuster::FormatBlock()
+ *************************************************************************/
+
+void SwTxtAdjuster::FormatBlock( )
+{
+ // In der letzten Zeile gibt's keinen Blocksatz.
+ // Und bei Tabulatoren aus Tradition auch nicht.
+ // 7701: wenn Flys im Spiel sind, geht's weiter
+
+ const SwLinePortion *pFly = 0;
+
+ sal_Bool bSkip = !IsLastBlock() &&
+ nStart + pCurr->GetLen() >= GetInfo().GetTxt().Len();
+
+ // ????: mehrzeilige Felder sind fies: wir muessen kontrollieren,
+ // ob es noch andere Textportions im Absatz gibt.
+ if( bSkip )
+ {
+ const SwLineLayout *pLay = pCurr->GetNext();
+ while( pLay && !pLay->GetLen() )
+ {
+ const SwLinePortion *pPor = pCurr->GetFirstPortion();
+ while( pPor && bSkip )
+ {
+ if( pPor->InTxtGrp() )
+ bSkip = sal_False;
+ pPor = pPor->GetPortion();
+ }
+ pLay = bSkip ? pLay->GetNext() : 0;
+ }
+ }
+
+ if( bSkip )
+ {
+ if( !GetInfo().GetParaPortion()->HasFly() )
+ {
+ if( IsLastCenter() )
+ CalcFlyAdjust( pCurr );
+ pCurr->FinishSpaceAdd();
+ return;
+ }
+ else
+ {
+ const SwLinePortion *pTmpFly = NULL;
+
+ // 7701: beim letzten Fly soll Schluss sein
+ const SwLinePortion *pPos = pCurr->GetFirstPortion();
+ while( pPos )
+ {
+ // Ich suche jetzt den letzten Fly, hinter dem noch Text ist:
+ if( pPos->IsFlyPortion() )
+ pTmpFly = pPos; // Ein Fly wurde gefunden
+ else if ( pTmpFly && pPos->InTxtGrp() )
+ {
+ pFly = pTmpFly; // Ein Fly mit nachfolgendem Text!
+ pTmpFly = NULL;
+ }
+ pPos = pPos->GetPortion();
+ }
+ // 8494: Wenn keiner gefunden wurde, ist sofort Schluss!
+ if( !pFly )
+ {
+ if( IsLastCenter() )
+ CalcFlyAdjust( pCurr );
+ pCurr->FinishSpaceAdd();
+ return;
+ }
+ }
+ }
+
+ const xub_StrLen nOldIdx = GetInfo().GetIdx();
+ GetInfo().SetIdx( nStart );
+ CalcNewBlock( pCurr, pFly );
+ GetInfo().SetIdx( nOldIdx );
+ GetInfo().GetParaPortion()->GetRepaint()->SetOfst(0);
+}
+
+/*************************************************************************
+ * lcl_CheckKashidaPositions()
+ *************************************************************************/
+bool lcl_CheckKashidaPositions( SwScriptInfo& rSI, SwTxtSizeInfo& rInf, SwTxtIter& rItr,
+ xub_StrLen& nKashidas, xub_StrLen& nGluePortion )
+{
+ // i60594 validate Kashida justification
+ xub_StrLen nIdx = rItr.GetStart();
+ xub_StrLen nEnd = rItr.GetEnd();
+
+ // Note on calling KashidaJustify():
+ // Kashida positions may be marked as invalid. Therefore KashidaJustify may return the clean
+ // total number of kashida positions, or the number of kashida positions after some positions
+ // have been dropped.
+ // Here we want the clean total, which is OK: We have called ClearKashidaInvalid() before.
+ nKashidas = rSI.KashidaJustify ( 0, 0, rItr.GetStart(), rItr.GetLength(), 0 );
+
+ if (!nKashidas) // nothing to do
+ return true;
+
+ // kashida positions found in SwScriptInfo are not necessarily valid in every font
+ // if two characters are replaced by a ligature glyph, there will be no place for a kashida
+ xub_StrLen* pKashidaPos = new xub_StrLen [ nKashidas ];
+ xub_StrLen* pKashidaPosDropped = new xub_StrLen [ nKashidas ];
+ rSI.GetKashidaPositions ( nIdx, rItr.GetLength(), pKashidaPos );
+ xub_StrLen nKashidaIdx = 0;
+ while ( nKashidas && nIdx < nEnd )
+ {
+ rItr.SeekAndChgAttrIter( nIdx, rInf.GetOut() );
+ xub_StrLen nNext = rItr.GetNextAttr();
+
+ // is there also a script change before?
+ // if there is, nNext should point to the script change
+ xub_StrLen nNextScript = rSI.NextScriptChg( nIdx );
+ if( nNextScript < nNext )
+ nNext = nNextScript;
+
+ if ( nNext == STRING_LEN || nNext > nEnd )
+ nNext = nEnd;
+ xub_StrLen nKashidasInAttr = rSI.KashidaJustify ( 0, 0, nIdx, nNext - nIdx );
+ if ( nKashidasInAttr )
+ {
+ xub_StrLen nKashidasDropped = 0;
+ if ( !SwScriptInfo::IsArabicText( rInf.GetTxt(), nIdx, nNext - nIdx ) )
+ {
+ nKashidasDropped = nKashidasInAttr;
+ nKashidas -= nKashidasDropped;
+ }
+ else
+ {
+ sal_uLong nOldLayout = rInf.GetOut()->GetLayoutMode();
+ rInf.GetOut()->SetLayoutMode ( nOldLayout | TEXT_LAYOUT_BIDI_RTL );
+ nKashidasDropped = rInf.GetOut()->ValidateKashidas ( rInf.GetTxt(), nIdx, nNext - nIdx,
+ nKashidasInAttr, pKashidaPos + nKashidaIdx,
+ pKashidaPosDropped );
+ rInf.GetOut()->SetLayoutMode ( nOldLayout );
+ if ( nKashidasDropped )
+ {
+ rSI.MarkKashidasInvalid ( nKashidasDropped, pKashidaPosDropped );
+ nKashidas -= nKashidasDropped;
+ nGluePortion -= nKashidasDropped;
+ }
+ }
+ nKashidaIdx += nKashidasInAttr;
+ }
+ nIdx = nNext;
+ }
+ delete[] pKashidaPos;
+ delete[] pKashidaPosDropped;
+
+ // return false if all kashidas have been eliminated
+ return (nKashidas > 0);
+}
+
+/*************************************************************************
+ * lcl_CheckKashidaWidth()
+ *************************************************************************/
+bool lcl_CheckKashidaWidth ( SwScriptInfo& rSI, SwTxtSizeInfo& rInf, SwTxtIter& rItr, xub_StrLen& nKashidas,
+ xub_StrLen& nGluePortion, const long nGluePortionWidth, long& nSpaceAdd )
+{
+ // check kashida width
+ // if width is smaller than minimal kashida width allowed by fonts in the current line
+ // drop one kashida after the other until kashida width is OK
+ bool bAddSpaceChanged;
+ while ( nKashidas )
+ {
+ bAddSpaceChanged = false;
+ xub_StrLen nIdx = rItr.GetStart();
+ xub_StrLen nEnd = rItr.GetEnd();
+ while ( nIdx < nEnd )
+ {
+ rItr.SeekAndChgAttrIter( nIdx, rInf.GetOut() );
+ xub_StrLen nNext = rItr.GetNextAttr();
+
+ // is there also a script change before?
+ // if there is, nNext should point to the script change
+ xub_StrLen nNextScript = rSI.NextScriptChg( nIdx );
+ if( nNextScript < nNext )
+ nNext = nNextScript;
+
+ if ( nNext == STRING_LEN || nNext > nEnd )
+ nNext = nEnd;
+ xub_StrLen nKashidasInAttr = rSI.KashidaJustify ( 0, 0, nIdx, nNext - nIdx );
+
+ long nFontMinKashida = rInf.GetOut()->GetMinKashida();
+ if ( nFontMinKashida && nKashidasInAttr && SwScriptInfo::IsArabicText( rInf.GetTxt(), nIdx, nNext - nIdx ) )
+ {
+ xub_StrLen nKashidasDropped = 0;
+ while ( nKashidas && nGluePortion && nKashidasInAttr &&
+ nSpaceAdd / SPACING_PRECISION_FACTOR < nFontMinKashida )
+ {
+ --nGluePortion;
+ --nKashidas;
+ --nKashidasInAttr;
+ ++nKashidasDropped;
+ if( !nKashidas || !nGluePortion ) // nothing left, return false to
+ return false; // do regular blank justification
+
+ nSpaceAdd = nGluePortionWidth / nGluePortion;
+ bAddSpaceChanged = true;
+ }
+ if( nKashidasDropped )
+ rSI.MarkKashidasInvalid( nKashidasDropped, nIdx, nNext - nIdx );
+ }
+ if ( bAddSpaceChanged )
+ break; // start all over again
+ nIdx = nNext;
+ }
+ if ( !bAddSpaceChanged )
+ break; // everything was OK
+ }
+ return true;
+}
+
+/*************************************************************************
+ * SwTxtAdjuster::CalcNewBlock()
+ *
+ * CalcNewBlock() darf erst nach CalcLine() gerufen werden !
+ * Aufgespannt wird immer zwischen zwei RandPortions oder FixPortions
+ * (Tabs und Flys). Dabei werden die Glues gezaehlt und ExpandBlock gerufen.
+ *************************************************************************/
+
+void SwTxtAdjuster::CalcNewBlock( SwLineLayout *pCurrent,
+ const SwLinePortion *pStopAt, SwTwips nReal, bool bSkipKashida )
+{
+ OSL_ENSURE( GetInfo().IsMulti() || SVX_ADJUST_BLOCK == GetAdjust(),
+ "CalcNewBlock: Why?" );
+ OSL_ENSURE( pCurrent->Height(), "SwTxtAdjuster::CalcBlockAdjust: missing CalcLine()" );
+
+ pCurrent->InitSpaceAdd();
+ xub_StrLen nGluePortion = 0;
+ xub_StrLen nCharCnt = 0;
+ MSHORT nSpaceIdx = 0;
+
+ // i60591: hennerdrews
+ SwScriptInfo& rSI = GetInfo().GetParaPortion()->GetScriptInfo();
+ SwTxtSizeInfo aInf ( GetTxtFrm() );
+ SwTxtIter aItr ( GetTxtFrm(), &aInf );
+
+ if ( rSI.CountKashida() )
+ {
+ while (aItr.GetCurr() != pCurrent && aItr.GetNext())
+ aItr.Next();
+
+ if( bSkipKashida )
+ {
+ rSI.SetNoKashidaLine ( aItr.GetStart(), aItr.GetLength());
+ }
+ else
+ {
+ rSI.ClearKashidaInvalid ( aItr.GetStart(), aItr.GetLength() );
+ rSI.ClearNoKashidaLine( aItr.GetStart(), aItr.GetLength() );
+ }
+ }
+
+ // Nicht vergessen:
+ // CalcRightMargin() setzt pCurrent->Width() auf die Zeilenbreite !
+ if (!bSkipKashida)
+ CalcRightMargin( pCurrent, nReal );
+
+ // --> FME 2005-06-08 #i49277#
+ const sal_Bool bDoNotJustifyLinesWithManualBreak =
+ GetTxtFrm()->GetNode()->getIDocumentSettingAccess()->get(IDocumentSettingAccess::DO_NOT_JUSTIFY_LINES_WITH_MANUAL_BREAK);
+ // <--
+
+ SwLinePortion *pPos = pCurrent->GetPortion();
+
+ while( pPos )
+ {
+ if ( bDoNotJustifyLinesWithManualBreak &&
+ pPos->IsBreakPortion() && !IsLastBlock() )
+ {
+ pCurrent->FinishSpaceAdd();
+ break;
+ }
+
+ if ( pPos->InTxtGrp() )
+ nGluePortion = nGluePortion + ((SwTxtPortion*)pPos)->GetSpaceCnt( GetInfo(), nCharCnt );
+ else if( pPos->IsMultiPortion() )
+ {
+ SwMultiPortion* pMulti = (SwMultiPortion*)pPos;
+ // a multiportion with a tabulator inside breaks the text adjustment
+ // a ruby portion will not be stretched by text adjustment
+ // a double line portion takes additional space for each blank
+ // in the wider line
+ if( pMulti->HasTabulator() )
+ {
+ if ( nSpaceIdx == pCurrent->GetLLSpaceAddCount() )
+ pCurrent->SetLLSpaceAdd( 0, nSpaceIdx );
+
+ nSpaceIdx++;
+ nGluePortion = 0;
+ nCharCnt = 0;
+ }
+ else if( pMulti->IsDouble() )
+ nGluePortion = nGluePortion + ((SwDoubleLinePortion*)pMulti)->GetSpaceCnt();
+ else if ( pMulti->IsBidi() )
+ nGluePortion = nGluePortion + ((SwBidiPortion*)pMulti)->GetSpaceCnt( GetInfo() ); // i60594
+ }
+
+ if( pPos->InGlueGrp() )
+ {
+ if( pPos->InFixMargGrp() )
+ {
+ if ( nSpaceIdx == pCurrent->GetLLSpaceAddCount() )
+ pCurrent->SetLLSpaceAdd( 0, nSpaceIdx );
+
+ const long nGluePortionWidth = static_cast<SwGluePortion*>(pPos)->GetPrtGlue() *
+ SPACING_PRECISION_FACTOR;
+
+ xub_StrLen nKashidas = 0;
+ if( nGluePortion && rSI.CountKashida() && !bSkipKashida )
+ {
+ // kashida positions found in SwScriptInfo are not necessarily valid in every font
+ // if two characters are replaced by a ligature glyph, there will be no place for a kashida
+ if ( !lcl_CheckKashidaPositions ( rSI, aInf, aItr, nKashidas, nGluePortion ))
+ {
+ // all kashida positions are invalid
+ // do regular blank justification
+ pCurrent->FinishSpaceAdd();
+ GetInfo().SetIdx( nStart );
+ CalcNewBlock( pCurrent, pStopAt, nReal, true );
+ return;
+ }
+ }
+
+ if( nGluePortion )
+ {
+ long nSpaceAdd = nGluePortionWidth / nGluePortion;
+
+ // i60594
+ if( rSI.CountKashida() && !bSkipKashida )
+ {
+ if( !lcl_CheckKashidaWidth( rSI, aInf, aItr, nKashidas, nGluePortion, nGluePortionWidth, nSpaceAdd ))
+ {
+ // no kashidas left
+ // do regular blank justification
+ pCurrent->FinishSpaceAdd();
+ GetInfo().SetIdx( nStart );
+ CalcNewBlock( pCurrent, pStopAt, nReal, true );
+ return;
+ }
+ }
+
+ pCurrent->SetLLSpaceAdd( nSpaceAdd , nSpaceIdx );
+ pPos->Width( ( (SwGluePortion*)pPos )->GetFixWidth() );
+ }
+ else if ( IsOneBlock() && nCharCnt > 1 )
+ {
+ const long nSpaceAdd = - nGluePortionWidth / ( nCharCnt - 1 );
+ pCurrent->SetLLSpaceAdd( nSpaceAdd, nSpaceIdx );
+ pPos->Width( ( (SwGluePortion*)pPos )->GetFixWidth() );
+ }
+
+ nSpaceIdx++;
+ nGluePortion = 0;
+ nCharCnt = 0;
+ }
+ else
+ ++nGluePortion;
+ }
+ GetInfo().SetIdx( GetInfo().GetIdx() + pPos->GetLen() );
+ if ( pPos == pStopAt )
+ {
+ pCurrent->SetLLSpaceAdd( 0, nSpaceIdx );
+ break;
+ }
+ pPos = pPos->GetPortion();
+ }
+}
+
+/*************************************************************************
+ * SwTxtAdjuster::CalcKanaAdj()
+ *************************************************************************/
+
+SwTwips SwTxtAdjuster::CalcKanaAdj( SwLineLayout* pCurrent )
+{
+ OSL_ENSURE( pCurrent->Height(), "SwTxtAdjuster::CalcBlockAdjust: missing CalcLine()" );
+ OSL_ENSURE( !pCurrent->GetpKanaComp(), "pKanaComp already exists!!" );
+
+ SvUShorts *pNewKana = new SvUShorts;
+ pCurrent->SetKanaComp( pNewKana );
+
+ const sal_uInt16 nNull = 0;
+ MSHORT nKanaIdx = 0;
+ long nKanaDiffSum = 0;
+ SwTwips nRepaintOfst = 0;
+ SwTwips nX = 0;
+ sal_Bool bNoCompression = sal_False;
+
+ // Nicht vergessen:
+ // CalcRightMargin() setzt pCurrent->Width() auf die Zeilenbreite !
+ CalcRightMargin( pCurrent, 0 );
+
+ SwLinePortion* pPos = pCurrent->GetPortion();
+
+ while( pPos )
+ {
+ if ( pPos->InTxtGrp() )
+ {
+ // get maximum portion width from info structure, calculated
+ // during text formatting
+ sal_uInt16 nMaxWidthDiff = GetInfo().GetMaxWidthDiff( (sal_uLong)pPos );
+
+ // check, if information is stored under other key
+ if ( !nMaxWidthDiff && pPos == pCurrent->GetFirstPortion() )
+ nMaxWidthDiff = GetInfo().GetMaxWidthDiff( (sal_uLong)pCurrent );
+
+ // calculate difference between portion width and max. width
+ nKanaDiffSum += nMaxWidthDiff;
+
+ // we store the beginning of the first compressable portion
+ // for repaint
+ if ( nMaxWidthDiff && !nRepaintOfst )
+ nRepaintOfst = nX + GetLeftMargin();
+ }
+ else if( pPos->InGlueGrp() && pPos->InFixMargGrp() )
+ {
+ if ( nKanaIdx == pCurrent->GetKanaComp().Count() )
+ pCurrent->GetKanaComp().Insert( nNull, nKanaIdx );
+
+ sal_uInt16 nRest;
+
+ if ( pPos->InTabGrp() )
+ {
+ nRest = ! bNoCompression &&
+ ( pPos->Width() > MIN_TAB_WIDTH ) ?
+ pPos->Width() - MIN_TAB_WIDTH :
+ 0;
+
+ // for simplifying the handling of left, right ... tabs,
+ // we do expand portions, which are lying behind
+ // those special tabs
+ bNoCompression = !pPos->IsTabLeftPortion();
+ }
+ else
+ {
+ nRest = ! bNoCompression ?
+ ((SwGluePortion*)pPos)->GetPrtGlue() :
+ 0;
+
+ bNoCompression = sal_False;
+ }
+
+ if( nKanaDiffSum )
+ {
+ sal_uLong nCompress = ( 10000 * nRest ) / nKanaDiffSum;
+
+ if ( nCompress >= 10000 )
+ // kanas can be expanded to 100%, and there is still
+ // some space remaining
+ nCompress = 0;
+
+ else
+ nCompress = 10000 - nCompress;
+
+ ( pCurrent->GetKanaComp() )[ nKanaIdx ] = (sal_uInt16)nCompress;
+ nKanaDiffSum = 0;
+ }
+
+ nKanaIdx++;
+ }
+
+ nX += pPos->Width();
+ pPos = pPos->GetPortion();
+ }
+
+ // set portion width
+ nKanaIdx = 0;
+ sal_uInt16 nCompress = ( pCurrent->GetKanaComp() )[ nKanaIdx ];
+ pPos = pCurrent->GetPortion();
+ long nDecompress = 0;
+ nKanaDiffSum = 0;
+
+ while( pPos )
+ {
+ if ( pPos->InTxtGrp() )
+ {
+ const sal_uInt16 nMinWidth = pPos->Width();
+
+ // get maximum portion width from info structure, calculated
+ // during text formatting
+ sal_uInt16 nMaxWidthDiff = GetInfo().GetMaxWidthDiff( (sal_uLong)pPos );
+
+ // check, if information is stored under other key
+ if ( !nMaxWidthDiff && pPos == pCurrent->GetFirstPortion() )
+ nMaxWidthDiff = GetInfo().GetMaxWidthDiff( (sal_uLong)pCurrent );
+ nKanaDiffSum += nMaxWidthDiff;
+ pPos->Width( nMinWidth +
+ ( ( 10000 - nCompress ) * nMaxWidthDiff ) / 10000 );
+ nDecompress += pPos->Width() - nMinWidth;
+ }
+ else if( pPos->InGlueGrp() && pPos->InFixMargGrp() )
+ {
+ if( nCompress )
+ {
+ nKanaDiffSum *= nCompress;
+ nKanaDiffSum /= 10000;
+ }
+
+ pPos->Width( static_cast<sal_uInt16>(pPos->Width() - nDecompress) );
+
+ if ( pPos->InTabGrp() )
+ // set fix width to width
+ ((SwTabPortion*)pPos)->SetFixWidth( pPos->Width() );
+
+ const SvUShorts& rKanaComp = pCurrent->GetKanaComp();
+ if ( ++nKanaIdx < rKanaComp.Count() )
+ nCompress = ( pCurrent->GetKanaComp() )[ nKanaIdx ];
+
+ nKanaDiffSum = 0;
+ nDecompress = 0;
+ }
+ pPos = pPos->GetPortion();
+ }
+
+ return nRepaintOfst;
+}
+
+/*************************************************************************
+ * SwTxtAdjuster::CalcRightMargin()
+ *************************************************************************/
+
+SwMarginPortion *SwTxtAdjuster::CalcRightMargin( SwLineLayout *pCurrent,
+ SwTwips nReal )
+{
+ long nRealWidth;
+ const sal_uInt16 nRealHeight = GetLineHeight();
+ const sal_uInt16 nLineHeight = pCurrent->Height();
+
+ KSHORT nPrtWidth = pCurrent->PrtWidth();
+ SwLinePortion *pLast = pCurrent->FindLastPortion();
+
+ if( GetInfo().IsMulti() )
+ nRealWidth = nReal;
+ else
+ {
+ nRealWidth = GetLineWidth();
+ // Fuer jeden FlyFrm, der in den rechten Rand hineinragt,
+ // wird eine FlyPortion angelegt.
+ const long nLeftMar = GetLeftMargin();
+ SwRect aCurrRect( nLeftMar + nPrtWidth, Y() + nRealHeight - nLineHeight,
+ nRealWidth - nPrtWidth, nLineHeight );
+
+ SwFlyPortion *pFly = CalcFlyPortion( nRealWidth, aCurrRect );
+ while( pFly && long( nPrtWidth )< nRealWidth )
+ {
+ pLast->Append( pFly );
+ pLast = pFly;
+ if( pFly->Fix() > nPrtWidth )
+ pFly->Width( ( pFly->Fix() - nPrtWidth) + pFly->Width() + 1);
+ nPrtWidth += pFly->Width() + 1;
+ aCurrRect.Left( nLeftMar + nPrtWidth );
+ pFly = CalcFlyPortion( nRealWidth, aCurrRect );
+ }
+ if( pFly )
+ delete pFly;
+ }
+
+ SwMarginPortion *pRight = new SwMarginPortion( 0 );
+ pLast->Append( pRight );
+
+ if( long( nPrtWidth )< nRealWidth )
+ pRight->PrtWidth( KSHORT( nRealWidth - nPrtWidth ) );
+
+ // pCurrent->Width() wird auf die reale Groesse gesetzt,
+ // da jetzt die MarginPortions eingehaengt sind.
+ // Dieser Trick hat wundersame Auswirkungen.
+ // Wenn pCurrent->Width() == nRealWidth ist, dann wird das gesamte
+ // Adjustment implizit ausgecontert. GetLeftMarginAdjust() und
+ // IsBlocksatz() sind der Meinung, sie haetten eine mit Zeichen
+ // gefuellte Zeile.
+
+ pCurrent->PrtWidth( KSHORT( nRealWidth ) );
+ return pRight;
+}
+
+/*************************************************************************
+ * SwTxtAdjuster::CalcFlyAdjust()
+ *************************************************************************/
+
+void SwTxtAdjuster::CalcFlyAdjust( SwLineLayout *pCurrent )
+{
+ // 1) Es wird ein linker Rand eingefuegt:
+ SwMarginPortion *pLeft = pCurrent->CalcLeftMargin();
+ SwGluePortion *pGlue = pLeft; // die letzte GluePortion
+
+
+ // 2) Es wird ein rechter Rand angehaengt:
+ // CalcRightMargin berechnet auch eventuelle Ueberlappungen mit
+ // FlyFrms.
+ CalcRightMargin( pCurrent );
+
+ SwLinePortion *pPos = pLeft->GetPortion();
+ xub_StrLen nLen = 0;
+
+ // Wenn wir nur eine Zeile vorliegen haben und die Textportion zusammen
+ // haengend ist und wenn zentriert wird, dann ...
+
+ sal_Bool bComplete = 0 == nStart;
+ const sal_Bool bTabCompat = GetTxtFrm()->GetNode()->getIDocumentSettingAccess()->get(IDocumentSettingAccess::TAB_COMPAT);
+ sal_Bool bMultiTab = sal_False;
+
+ while( pPos )
+ {
+ if ( pPos->IsMultiPortion() && ((SwMultiPortion*)pPos)->HasTabulator() )
+ bMultiTab = sal_True;
+ else if( pPos->InFixMargGrp() &&
+ ( bTabCompat ? ! pPos->InTabGrp() : ! bMultiTab ) )
+ {
+ // in tab compat mode we do not want to change tab portions
+ // in non tab compat mode we do not want to change margins if we
+ // found a multi portion with tabs
+ if( SVX_ADJUST_RIGHT == GetAdjust() )
+ ((SwGluePortion*)pPos)->MoveAllGlue( pGlue );
+ else
+ {
+ // Eine schlaue Idee von MA:
+ // Fuer die erste Textportion wird rechtsbuendig eingestellt,
+ // fuer die letzte linksbuendig.
+
+ // Die erste Textportion kriegt den ganzen Glue
+ // Aber nur, wenn wir mehr als eine Zeile besitzen.
+ if( bComplete && GetInfo().GetTxt().Len() == nLen )
+ ((SwGluePortion*)pPos)->MoveHalfGlue( pGlue );
+ else
+ {
+ if ( ! bTabCompat )
+ {
+ if( pLeft == pGlue )
+ {
+ // Wenn es nur einen linken und rechten Rand gibt,
+ // dann teilen sich die Raender den Glue.
+ if( nLen + pPos->GetLen() >= pCurrent->GetLen() )
+ ((SwGluePortion*)pPos)->MoveHalfGlue( pGlue );
+ else
+ ((SwGluePortion*)pPos)->MoveAllGlue( pGlue );
+ }
+ else
+ {
+ // Die letzte Textportion behaelt sein Glue
+ if( !pPos->IsMarginPortion() )
+ ((SwGluePortion*)pPos)->MoveHalfGlue( pGlue );
+ }
+ }
+ else
+ ((SwGluePortion*)pPos)->MoveHalfGlue( pGlue );
+ }
+ }
+
+ pGlue = (SwFlyPortion*)pPos;
+ bComplete = sal_False;
+ }
+ nLen = nLen + pPos->GetLen();
+ pPos = pPos->GetPortion();
+ }
+
+ if( ! bTabCompat && ! bMultiTab && SVX_ADJUST_RIGHT == GetAdjust() )
+ // portions are moved to the right if possible
+ pLeft->AdjustRight( pCurrent );
+}
+
+/*************************************************************************
+ * SwTxtAdjuster::CalcAdjLine()
+ *************************************************************************/
+
+void SwTxtAdjuster::CalcAdjLine( SwLineLayout *pCurrent )
+{
+ OSL_ENSURE( pCurrent->IsFormatAdj(), "CalcAdjLine: Why?" );
+
+ pCurrent->SetFormatAdj(sal_False);
+
+ SwParaPortion* pPara = GetInfo().GetParaPortion();
+
+ switch( GetAdjust() )
+ {
+ case SVX_ADJUST_RIGHT:
+ case SVX_ADJUST_CENTER:
+ {
+ CalcFlyAdjust( pCurrent );
+ pPara->GetRepaint()->SetOfst( 0 );
+ break;
+ }
+ case SVX_ADJUST_BLOCK:
+ {
+ FormatBlock();
+ break;
+ }
+ default : return;
+ }
+}
+
+/*************************************************************************
+ * SwTxtAdjuster::CalcFlyPortion()
+ *
+ * Die Berechnung hat es in sich: nCurrWidth geibt die Breite _vor_ dem
+ * aufaddieren des Wortes das noch auf die Zeile passt! Aus diesem Grund
+ * stimmt die Breite der FlyPortion auch, wenn die Blockierungssituation
+ * bFirstWord && !WORDFITS eintritt.
+ *************************************************************************/
+
+SwFlyPortion *SwTxtAdjuster::CalcFlyPortion( const long nRealWidth,
+ const SwRect &rCurrRect )
+{
+ SwTxtFly aTxtFly( GetTxtFrm() );
+
+ const KSHORT nCurrWidth = pCurr->PrtWidth();
+ SwFlyPortion *pFlyPortion = 0;
+
+ SwRect aLineVert( rCurrRect );
+ if ( GetTxtFrm()->IsRightToLeft() )
+ GetTxtFrm()->SwitchLTRtoRTL( aLineVert );
+ if ( GetTxtFrm()->IsVertical() )
+ GetTxtFrm()->SwitchHorizontalToVertical( aLineVert );
+
+ // aFlyRect ist dokumentglobal !
+ SwRect aFlyRect( aTxtFly.GetFrm( aLineVert ) );
+
+ if ( GetTxtFrm()->IsRightToLeft() )
+ GetTxtFrm()->SwitchRTLtoLTR( aFlyRect );
+ if ( GetTxtFrm()->IsVertical() )
+ GetTxtFrm()->SwitchVerticalToHorizontal( aFlyRect );
+
+ // Wenn ein Frame ueberlappt, wird eine Portion eroeffnet.
+ if( aFlyRect.HasArea() )
+ {
+ // aLocal ist framelokal
+ SwRect aLocal( aFlyRect );
+ aLocal.Pos( aLocal.Left() - GetLeftMargin(), aLocal.Top() );
+ if( nCurrWidth > aLocal.Left() )
+ aLocal.Left( nCurrWidth );
+
+ // Wenn das Rechteck breiter als die Zeile ist, stutzen
+ // wir es ebenfalls zurecht.
+ KSHORT nLocalWidth = KSHORT( aLocal.Left() + aLocal.Width() );
+ if( nRealWidth < long( nLocalWidth ) )
+ aLocal.Width( nRealWidth - aLocal.Left() );
+ GetInfo().GetParaPortion()->SetFly( sal_True );
+ pFlyPortion = new SwFlyPortion( aLocal );
+ pFlyPortion->Height( KSHORT( rCurrRect.Height() ) );
+ // Die Width koennte kleiner sein als die FixWidth, daher:
+ pFlyPortion->AdjFixWidth();
+ }
+ return pFlyPortion;
+}
+
+/*************************************************************************
+ * SwTxtPainter::_CalcDropAdjust()
+ *************************************************************************/
+
+// 6721: Drops und Adjustment
+// CalcDropAdjust wird ggf. am Ende von Format() gerufen.
+
+void SwTxtAdjuster::CalcDropAdjust()
+{
+ OSL_ENSURE( 1<GetDropLines() && SVX_ADJUST_LEFT!=GetAdjust() && SVX_ADJUST_BLOCK!=GetAdjust(),
+ "CalcDropAdjust: No reason for DropAdjustment." );
+
+ const MSHORT nLineNumber = GetLineNr();
+
+ // 1) Dummies ueberspringen
+ Top();
+
+ if( !pCurr->IsDummy() || NextLine() )
+ {
+ // Erst adjustieren.
+ GetAdjusted();
+
+ SwLinePortion *pPor = pCurr->GetFirstPortion();
+
+ // 2) Sicherstellen, dass die DropPortion dabei ist.
+ // 3) pLeft: Die GluePor vor der DropPor
+ if( pPor->InGlueGrp() && pPor->GetPortion()
+ && pPor->GetPortion()->IsDropPortion() )
+ {
+ const SwLinePortion *pDropPor = (SwDropPortion*) pPor->GetPortion();
+ SwGluePortion *pLeft = (SwGluePortion*) pPor;
+
+ // 4) pRight: Die GluePor hinter der DropPor suchen
+ pPor = pPor->GetPortion();
+ while( pPor && !pPor->InFixMargGrp() )
+ pPor = pPor->GetPortion();
+
+ SwGluePortion *pRight = ( pPor && pPor->InGlueGrp() ) ?
+ (SwGluePortion*) pPor : 0;
+ if( pRight && pRight != pLeft )
+ {
+ // 5) nMinLeft berechnen. Wer steht am weitesten links?
+ const KSHORT nDropLineStart =
+ KSHORT(GetLineStart()) + pLeft->Width() + pDropPor->Width();
+ KSHORT nMinLeft = nDropLineStart;
+ for( MSHORT i = 1; i < GetDropLines(); ++i )
+ {
+ if( NextLine() )
+ {
+ // Erst adjustieren.
+ GetAdjusted();
+
+ pPor = pCurr->GetFirstPortion();
+ const SwMarginPortion *pMar = pPor->IsMarginPortion() ?
+ (SwMarginPortion*)pPor : 0;
+ if( !pMar )
+ nMinLeft = 0;
+ else
+ {
+ const KSHORT nLineStart =
+ KSHORT(GetLineStart()) + pMar->Width();
+ if( nMinLeft > nLineStart )
+ nMinLeft = nLineStart;
+ }
+ }
+ }
+
+ // 6) Den Glue zwischen pLeft und pRight neu verteilen.
+ if( nMinLeft < nDropLineStart )
+ {
+ // Glue wird immer von pLeft nach pRight abgegeben,
+ // damit der Text nach links wandert.
+ const short nGlue = nDropLineStart - nMinLeft;
+ if( !nMinLeft )
+ pLeft->MoveAllGlue( pRight );
+ else
+ pLeft->MoveGlue( pRight, nGlue );
+ }
+ }
+ }
+ }
+
+ if( nLineNumber != GetLineNr() )
+ {
+ Top();
+ while( nLineNumber != GetLineNr() && Next() )
+ ;
+ }
+}
+
+/*************************************************************************
+ * SwTxtAdjuster::CalcDropRepaint()
+ *************************************************************************/
+
+void SwTxtAdjuster::CalcDropRepaint()
+{
+ Top();
+ SwRepaint &rRepaint = *GetInfo().GetParaPortion()->GetRepaint();
+ if( rRepaint.Top() > Y() )
+ rRepaint.Top( Y() );
+ for( MSHORT i = 1; i < GetDropLines(); ++i )
+ NextLine();
+ const SwTwips nBottom = Y() + GetLineHeight() - 1;
+ if( rRepaint.Bottom() < nBottom )
+ rRepaint.Bottom( nBottom );
+}
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/text/itratr.cxx b/sw/source/core/text/itratr.cxx
new file mode 100644
index 000000000000..cb1209b893be
--- /dev/null
+++ b/sw/source/core/text/itratr.cxx
@@ -0,0 +1,1075 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+
+#include <hintids.hxx>
+#include <editeng/charscaleitem.hxx>
+#include <txtatr.hxx>
+#include <sfx2/printer.hxx>
+#include <svx/svdobj.hxx>
+#include <vcl/window.hxx>
+#include <vcl/svapp.hxx>
+#include <fmtanchr.hxx>
+#include <fmtfsize.hxx>
+#include <fmtornt.hxx>
+#include <fmtflcnt.hxx>
+#include <fmtcntnt.hxx>
+#include <fmtftn.hxx>
+#include <frmatr.hxx>
+#include <frmfmt.hxx>
+#include <fmtfld.hxx>
+#include <doc.hxx>
+#include <viewsh.hxx> // ViewShell
+#include <rootfrm.hxx>
+#include <docary.hxx>
+#include <ndtxt.hxx>
+#include <dcontact.hxx>
+#include <fldbas.hxx> // SwField
+#include <pam.hxx> // SwPosition (lcl_MinMaxNode)
+#include <itratr.hxx>
+#include <htmltbl.hxx>
+#include <swtable.hxx>
+#include <redlnitr.hxx>
+#include <fmtsrnd.hxx>
+#include <itrtxt.hxx>
+#include <breakit.hxx>
+#include <com/sun/star/i18n/WordType.hpp>
+#include <com/sun/star/i18n/ScriptType.hdl>
+#include <editeng/lrspitem.hxx>
+#include <switerator.hxx>
+
+using namespace ::com::sun::star::i18n;
+using namespace ::com::sun::star;
+
+/*************************************************************************
+ * SwAttrIter::Chg()
+ *************************************************************************/
+
+void SwAttrIter::Chg( SwTxtAttr *pHt )
+{
+ OSL_ENSURE( pHt && pFnt, "No attribute of font available for change");
+ if( pRedln && pRedln->IsOn() )
+ pRedln->ChangeTxtAttr( pFnt, *pHt, sal_True );
+ else
+ aAttrHandler.PushAndChg( *pHt, *pFnt );
+ nChgCnt++;
+}
+
+/*************************************************************************
+ * SwAttrIter::Rst()
+ *************************************************************************/
+
+void SwAttrIter::Rst( SwTxtAttr *pHt )
+{
+ OSL_ENSURE( pHt && pFnt, "No attribute of font available for reset");
+ // get top from stack after removing pHt
+ if( pRedln && pRedln->IsOn() )
+ pRedln->ChangeTxtAttr( pFnt, *pHt, sal_False );
+ else
+ aAttrHandler.PopAndChg( *pHt, *pFnt );
+ nChgCnt--;
+}
+
+/*************************************************************************
+ * virtual SwAttrIter::~SwAttrIter()
+ *************************************************************************/
+
+SwAttrIter::~SwAttrIter()
+{
+ delete pRedln;
+ delete pFnt;
+}
+
+/*************************************************************************
+ * SwAttrIter::GetAttr()
+ *
+ * Liefert fuer eine Position das Attribut, wenn das Attribut genau auf
+ * der Position nPos liegt und kein EndIndex besitzt.
+ * GetAttr() wird fuer Attribute benoetigt, die die Formatierung beeinflussen
+ * sollen, ohne dabei den Inhalt des Strings zu veraendern. Solche "entarteten"
+ * Attribute sind z.B. Felder (die expandierten Text bereit halten) und
+ * zeilengebundene Frames. Um Mehrdeutigkeiten zwischen verschiedenen
+ * solcher Attribute zu vermeiden, werden beim Anlegen eines Attributs
+ * an der Startposition ein Sonderzeichen in den String einfuegt.
+ * Der Formatierer stoesst auf das Sonderzeichen und holt sich per
+ * GetAttr() das entartete Attribut.
+ *************************************************************************/
+
+SwTxtAttr *SwAttrIter::GetAttr( const xub_StrLen nPosition ) const
+{
+ return (m_pTxtNode) ? m_pTxtNode->GetTxtAttrForCharAt(nPosition) : 0;
+}
+
+/*************************************************************************
+ * SwAttrIter::SeekAndChg()
+ *************************************************************************/
+
+sal_Bool SwAttrIter::SeekAndChgAttrIter( const xub_StrLen nNewPos, OutputDevice* pOut )
+{
+ sal_Bool bChg = nStartIndex && nNewPos == nPos ? pFnt->IsFntChg() : Seek( nNewPos );
+ if ( pLastOut != pOut )
+ {
+ pLastOut = pOut;
+ pFnt->SetFntChg( sal_True );
+ bChg = sal_True;
+ }
+ if( bChg )
+ {
+ // wenn der Aenderungszaehler auf Null ist, kennen wir die MagicNo
+ // des gewuenschten Fonts ...
+ if ( !nChgCnt && !nPropFont )
+ pFnt->SetMagic( aMagicNo[ pFnt->GetActual() ],
+ aFntIdx[ pFnt->GetActual() ], pFnt->GetActual() );
+ pFnt->ChgPhysFnt( pShell, *pOut );
+ }
+ return bChg;
+}
+
+sal_Bool SwAttrIter::IsSymbol( const xub_StrLen nNewPos )
+{
+ Seek( nNewPos );
+ if ( !nChgCnt && !nPropFont )
+ pFnt->SetMagic( aMagicNo[ pFnt->GetActual() ],
+ aFntIdx[ pFnt->GetActual() ], pFnt->GetActual() );
+ return pFnt->IsSymbol( pShell );
+}
+
+/*************************************************************************
+ * SwAttrIter::SeekStartAndChg()
+ *************************************************************************/
+
+sal_Bool SwAttrIter::SeekStartAndChgAttrIter( OutputDevice* pOut, const sal_Bool bParaFont )
+{
+ if ( pRedln && pRedln->ExtOn() )
+ pRedln->LeaveExtend( *pFnt, 0 );
+
+ // reset font to its original state
+ aAttrHandler.Reset();
+ aAttrHandler.ResetFont( *pFnt );
+
+ nStartIndex = nEndIndex = nPos = nChgCnt = 0;
+ if( nPropFont )
+ pFnt->SetProportion( nPropFont );
+ if( pRedln )
+ {
+ pRedln->Clear( pFnt );
+ if( !bParaFont )
+ nChgCnt = nChgCnt + pRedln->Seek( *pFnt, 0, STRING_LEN );
+ else
+ pRedln->Reset();
+ }
+
+ if ( pHints && !bParaFont )
+ {
+ SwTxtAttr *pTxtAttr;
+ // Solange wir noch nicht am Ende des StartArrays angekommen sind &&
+ // das TextAttribut an Position 0 beginnt ...
+ while ( ( nStartIndex < pHints->GetStartCount() ) &&
+ !(*(pTxtAttr=pHints->GetStart(nStartIndex))->GetStart()) )
+ {
+ // oeffne die TextAttribute
+ Chg( pTxtAttr );
+ nStartIndex++;
+ }
+ }
+
+ sal_Bool bChg = pFnt->IsFntChg();
+ if ( pLastOut != pOut )
+ {
+ pLastOut = pOut;
+ pFnt->SetFntChg( sal_True );
+ bChg = sal_True;
+ }
+ if( bChg )
+ {
+ // wenn der Aenderungszaehler auf Null ist, kennen wir die MagicNo
+ // des gewuenschten Fonts ...
+ if ( !nChgCnt && !nPropFont )
+ pFnt->SetMagic( aMagicNo[ pFnt->GetActual() ],
+ aFntIdx[ pFnt->GetActual() ], pFnt->GetActual() );
+ pFnt->ChgPhysFnt( pShell, *pOut );
+ }
+ return bChg;
+}
+
+/*************************************************************************
+ * SwAttrIter::SeekFwd()
+ *************************************************************************/
+
+// AMA: Neuer AttrIter Nov 94
+
+void SwAttrIter::SeekFwd( const xub_StrLen nNewPos )
+{
+ SwTxtAttr *pTxtAttr;
+
+ if ( nStartIndex ) // wenn ueberhaupt schon Attribute geoeffnet wurden...
+ {
+ // Schliesse Attr, die z. Z. geoeffnet sind, vor nNewPos+1 aber enden.
+
+ // Solange wir noch nicht am Ende des EndArrays angekommen sind &&
+ // das TextAttribut vor oder an der neuen Position endet ...
+ while ( ( nEndIndex < pHints->GetEndCount() ) &&
+ (*(pTxtAttr=pHints->GetEnd(nEndIndex))->GetAnyEnd()<=nNewPos))
+ {
+ // schliesse die TextAttribute, deren StartPos vor
+ // oder an der alten nPos lag, die z.Z. geoeffnet sind.
+ if (*pTxtAttr->GetStart() <= nPos) Rst( pTxtAttr );
+ nEndIndex++;
+ }
+ }
+ else // ueberlies die nicht geoeffneten Enden
+ {
+ while ( ( nEndIndex < pHints->GetEndCount() ) &&
+ (*(pTxtAttr=pHints->GetEnd(nEndIndex))->GetAnyEnd()<=nNewPos))
+ {
+ nEndIndex++;
+ }
+ }
+ // Solange wir noch nicht am Ende des StartArrays angekommen sind &&
+ // das TextAttribut vor oder an der neuen Position beginnt ...
+ while ( ( nStartIndex < pHints->GetStartCount() ) &&
+ (*(pTxtAttr=pHints->GetStart(nStartIndex))->GetStart()<=nNewPos))
+ {
+ // oeffne die TextAttribute, deren Ende hinter der neuen Position liegt
+ if ( *pTxtAttr->GetAnyEnd() > nNewPos ) Chg( pTxtAttr );
+ nStartIndex++;
+ }
+
+}
+
+/*************************************************************************
+ * SwAttrIter::Seek()
+ *************************************************************************/
+
+sal_Bool SwAttrIter::Seek( const xub_StrLen nNewPos )
+{
+ if ( pRedln && pRedln->ExtOn() )
+ pRedln->LeaveExtend( *pFnt, nNewPos );
+
+ if( pHints )
+ {
+ if( !nNewPos || nNewPos < nPos )
+ {
+ if( pRedln )
+ pRedln->Clear( NULL );
+
+ // reset font to its original state
+ aAttrHandler.Reset();
+ aAttrHandler.ResetFont( *pFnt );
+
+ if( nPropFont )
+ pFnt->SetProportion( nPropFont );
+ nStartIndex = nEndIndex = nPos = 0;
+ nChgCnt = 0;
+
+ // Achtung!
+ // resetting the font here makes it necessary to apply any
+ // changes for extended input directly to the font
+ if ( pRedln && pRedln->ExtOn() )
+ {
+ pRedln->UpdateExtFont( *pFnt );
+ ++nChgCnt;
+ }
+ }
+ SeekFwd( nNewPos );
+ }
+
+ pFnt->SetActual( SwScriptInfo::WhichFont( nNewPos, 0, pScriptInfo ) );
+
+ if( pRedln )
+ nChgCnt = nChgCnt + pRedln->Seek( *pFnt, nNewPos, nPos );
+ nPos = nNewPos;
+
+ if( nPropFont )
+ pFnt->SetProportion( nPropFont );
+
+ return pFnt->IsFntChg();
+}
+
+/*************************************************************************
+ * SwAttrIter::GetNextAttr()
+ *************************************************************************/
+
+xub_StrLen SwAttrIter::GetNextAttr( ) const
+{
+ xub_StrLen nNext = STRING_LEN;
+ if( pHints )
+ {
+ if (pHints->GetStartCount() > nStartIndex) // Gibt es noch Starts?
+ nNext = (*pHints->GetStart(nStartIndex)->GetStart());
+ if (pHints->GetEndCount() > nEndIndex) // Gibt es noch Enden?
+ {
+ xub_StrLen nNextEnd = (*pHints->GetEnd(nEndIndex)->GetAnyEnd());
+ if ( nNextEnd<nNext ) nNext = nNextEnd; // Wer ist naeher?
+ }
+ }
+ if (m_pTxtNode!=NULL) {
+ //TODO maybe use hints like FieldHints for this instead of looking at the text...
+ int l=(nNext<m_pTxtNode->Len()?nNext:m_pTxtNode->Len());
+ sal_uInt16 p=nPos;
+ const sal_Unicode *txt=m_pTxtNode->GetTxt().GetBuffer();
+ while(p<l && txt[p]!=CH_TXT_ATR_FIELDSTART && txt[p]!=CH_TXT_ATR_FIELDEND && txt[p]!=CH_TXT_ATR_FORMELEMENT) p++;
+ if ((p<l && p>nPos) || nNext<=p)
+ nNext=p;
+ else
+ nNext=p+1;
+ }
+ if( pRedln )
+ return pRedln->GetNextRedln( nNext );
+ return nNext;
+}
+
+#if OSL_DEBUG_LEVEL > 1
+/*************************************************************************
+ * SwAttrIter::Dump()
+ *************************************************************************/
+
+void SwAttrIter::Dump( SvStream &/*rOS*/ ) const
+{
+// Noch nicht an den neuen Attributiterator angepasst ...
+}
+
+#endif
+
+class SwMinMaxArgs
+{
+public:
+ OutputDevice* pOut;
+ ViewShell* pSh;
+ sal_uLong &rMin;
+ sal_uLong &rMax;
+ sal_uLong &rAbsMin;
+ long nRowWidth;
+ long nWordWidth;
+ long nWordAdd;
+ xub_StrLen nNoLineBreak;
+ SwMinMaxArgs( OutputDevice* pOutI, ViewShell* pShI, sal_uLong& rMinI, sal_uLong &rMaxI, sal_uLong &rAbsI )
+ : pOut( pOutI ), pSh( pShI ), rMin( rMinI ), rMax( rMaxI ), rAbsMin( rAbsI )
+ { nRowWidth = nWordWidth = nWordAdd = 0; nNoLineBreak = STRING_LEN; }
+ void Minimum( long nNew ) const { if( (long)rMin < nNew ) rMin = nNew; }
+ void NewWord() { nWordAdd = nWordWidth = 0; }
+};
+
+sal_Bool lcl_MinMaxString( SwMinMaxArgs& rArg, SwFont* pFnt, const XubString &rTxt,
+ xub_StrLen nIdx, xub_StrLen nEnd )
+{
+ sal_Bool bRet = sal_False;
+ while( nIdx < nEnd )
+ {
+ xub_StrLen nStop = nIdx;
+ sal_Bool bClear;
+ LanguageType eLang = pFnt->GetLanguage();
+ if( pBreakIt->GetBreakIter().is() )
+ {
+ bClear = CH_BLANK == rTxt.GetChar( nStop );
+ Boundary aBndry( pBreakIt->GetBreakIter()->getWordBoundary( rTxt, nIdx,
+ pBreakIt->GetLocale( eLang ),
+ WordType::DICTIONARY_WORD, sal_True ) );
+ nStop = (xub_StrLen)aBndry.endPos;
+ if( nIdx <= aBndry.startPos && nIdx && nIdx-1 != rArg.nNoLineBreak )
+ rArg.NewWord();
+ if( nStop == nIdx )
+ ++nStop;
+ if( nStop > nEnd )
+ nStop = nEnd;
+ }
+ else
+ {
+ while( nStop < nEnd && CH_BLANK != rTxt.GetChar( nStop ) )
+ ++nStop;
+ bClear = nStop == nIdx;
+ if ( bClear )
+ {
+ rArg.NewWord();
+ while( nStop < nEnd && CH_BLANK == rTxt.GetChar( nStop ) )
+ ++nStop;
+ }
+ }
+
+ SwDrawTextInfo aDrawInf( rArg.pSh, *rArg.pOut, 0, rTxt, nIdx, nStop - nIdx );
+ long nAktWidth = pFnt->_GetTxtSize( aDrawInf ).Width();
+ rArg.nRowWidth += nAktWidth;
+ if( bClear )
+ rArg.NewWord();
+ else
+ {
+ rArg.nWordWidth += nAktWidth;
+ if( (long)rArg.rAbsMin < rArg.nWordWidth )
+ rArg.rAbsMin = rArg.nWordWidth;
+ rArg.Minimum( rArg.nWordWidth + rArg.nWordAdd );
+ bRet = sal_True;
+ }
+ nIdx = nStop;
+ }
+ return bRet;
+}
+
+sal_Bool SwTxtNode::IsSymbol( const xub_StrLen nBegin ) const//swmodtest 080307
+{
+ SwScriptInfo aScriptInfo;
+ SwAttrIter aIter( *(SwTxtNode*)this, aScriptInfo );
+ aIter.Seek( nBegin );
+ return aIter.GetFnt()->IsSymbol(
+ const_cast<ViewShell *>(getIDocumentLayoutAccess()->GetCurrentViewShell()) );//swmod 080311
+}
+
+class SwMinMaxNodeArgs
+{
+public:
+ sal_uLong nMaxWidth; // Summe aller Rahmenbreite
+ long nMinWidth; // Breitester Rahmen
+ long nLeftRest; // noch nicht von Rahmen ueberdeckter Platz im l. Rand
+ long nRightRest; // noch nicht von Rahmen ueberdeckter Platz im r. Rand
+ long nLeftDiff; // Min/Max-Differenz des Rahmens im linken Rand
+ long nRightDiff; // Min/Max-Differenz des Rahmens im rechten Rand
+ sal_uLong nIndx; // Indexnummer des Nodes
+ void Minimum( long nNew ) { if( nNew > nMinWidth ) nMinWidth = nNew; }
+};
+
+sal_Bool lcl_MinMaxNode( const SwFrmFmtPtr& rpNd, void* pArgs )
+{
+ const SwFmtAnchor& rFmtA = ((SwFrmFmt*)rpNd)->GetAnchor();
+
+ bool bCalculate = false;
+ if ((FLY_AT_PARA == rFmtA.GetAnchorId()) ||
+ (FLY_AT_CHAR == rFmtA.GetAnchorId()))
+ {
+ bCalculate = true;
+ }
+
+ if (bCalculate)
+ {
+ const SwMinMaxNodeArgs *pIn = (const SwMinMaxNodeArgs*)pArgs;
+ const SwPosition *pPos = rFmtA.GetCntntAnchor();
+ OSL_ENSURE(pPos && pIn, "Unexpected NULL arguments");
+ if (!pPos || !pIn || pIn->nIndx != pPos->nNode.GetIndex())
+ bCalculate = false;
+ }
+
+ if (bCalculate)
+ {
+ long nMin, nMax;
+ SwHTMLTableLayout *pLayout = 0;
+ MSHORT nWhich = ((SwFrmFmt*)rpNd)->Which();
+ if( RES_DRAWFRMFMT != nWhich )
+ {
+ // Enthaelt der Rahmen zu Beginn oder am Ende eine Tabelle?
+ const SwNodes& rNodes = static_cast<SwFrmFmt*>(rpNd)->GetDoc()->GetNodes();
+ const SwFmtCntnt& rFlyCntnt = ((SwFrmFmt*)rpNd)->GetCntnt();
+ sal_uLong nStt = rFlyCntnt.GetCntntIdx()->GetIndex();
+ SwTableNode* pTblNd = rNodes[nStt+1]->GetTableNode();
+ if( !pTblNd )
+ {
+ SwNode *pNd = rNodes[nStt];
+ pNd = rNodes[pNd->EndOfSectionIndex()-1];
+ if( pNd->IsEndNode() )
+ pTblNd = pNd->StartOfSectionNode()->GetTableNode();
+ }
+
+ if( pTblNd )
+ pLayout = pTblNd->GetTable().GetHTMLTableLayout();
+ }
+
+ const SwFmtHoriOrient& rOrient = ((SwFrmFmt*)rpNd)->GetHoriOrient();
+ sal_Int16 eHoriOri = rOrient.GetHoriOrient();
+
+ long nDiff;
+ if( pLayout )
+ {
+ nMin = pLayout->GetMin();
+ nMax = pLayout->GetMax();
+ nDiff = nMax - nMin;
+ }
+ else
+ {
+ if( RES_DRAWFRMFMT == nWhich )
+ {
+ const SdrObject* pSObj = rpNd->FindSdrObject();
+ if( pSObj )
+ nMin = pSObj->GetCurrentBoundRect().GetWidth();
+ else
+ nMin = 0;
+
+ }
+ else
+ {
+ const SwFmtFrmSize &rSz = ( (SwFrmFmt*)rpNd )->GetFrmSize();
+ nMin = rSz.GetWidth();
+ }
+ nMax = nMin;
+ nDiff = 0;
+ }
+
+ const SvxLRSpaceItem &rLR = ( (SwFrmFmt*)rpNd )->GetLRSpace();
+ nMin += rLR.GetLeft();
+ nMin += rLR.GetRight();
+ nMax += rLR.GetLeft();
+ nMax += rLR.GetRight();
+
+ if( SURROUND_THROUGHT == ((SwFrmFmt*)rpNd)->GetSurround().GetSurround() )
+ {
+ ( (SwMinMaxNodeArgs*)pArgs )->Minimum( nMin );
+ return sal_True;
+ }
+
+ // Rahmen, die recht bzw. links ausgerichtet sind, gehen nur
+ // teilweise in die Max-Berechnung ein, da der Rand schon berueck-
+ // sichtigt wird. Nur wenn die Rahmen in den Textkoerper ragen,
+ // wird dieser Teil hinzuaddiert.
+ switch( eHoriOri )
+ {
+ case text::HoriOrientation::RIGHT:
+ {
+ if( nDiff )
+ {
+ ((SwMinMaxNodeArgs*)pArgs)->nRightRest -=
+ ((SwMinMaxNodeArgs*)pArgs)->nRightDiff;
+ ((SwMinMaxNodeArgs*)pArgs)->nRightDiff = nDiff;
+ }
+ if( text::RelOrientation::FRAME != rOrient.GetRelationOrient() )
+ {
+ if( ((SwMinMaxNodeArgs*)pArgs)->nRightRest > 0 )
+ ((SwMinMaxNodeArgs*)pArgs)->nRightRest = 0;
+ }
+ ((SwMinMaxNodeArgs*)pArgs)->nRightRest -= nMin;
+ break;
+ }
+ case text::HoriOrientation::LEFT:
+ {
+ if( nDiff )
+ {
+ ((SwMinMaxNodeArgs*)pArgs)->nLeftRest -=
+ ((SwMinMaxNodeArgs*)pArgs)->nLeftDiff;
+ ((SwMinMaxNodeArgs*)pArgs)->nLeftDiff = nDiff;
+ }
+ if( text::RelOrientation::FRAME != rOrient.GetRelationOrient() &&
+ ((SwMinMaxNodeArgs*)pArgs)->nLeftRest < 0 )
+ ((SwMinMaxNodeArgs*)pArgs)->nLeftRest = 0;
+ ((SwMinMaxNodeArgs*)pArgs)->nLeftRest -= nMin;
+ break;
+ }
+ default:
+ {
+ ( (SwMinMaxNodeArgs*)pArgs )->nMaxWidth += nMax;
+ ( (SwMinMaxNodeArgs*)pArgs )->Minimum( nMin );
+ }
+ }
+ }
+ return sal_True;
+}
+
+#define FLYINCNT_MIN_WIDTH 284
+
+// changing this method very likely requires changing of
+// "GetScalingOfSelectedText"
+void SwTxtNode::GetMinMaxSize( sal_uLong nIndex, sal_uLong& rMin, sal_uLong &rMax,
+ sal_uLong& rAbsMin, OutputDevice* pOut ) const
+{
+ ViewShell* pSh = 0;
+ GetDoc()->GetEditShell( &pSh );
+ if( !pOut )
+ {
+ if( pSh )
+ pOut = pSh->GetWin();
+ if( !pOut )
+ pOut = GetpApp()->GetDefaultDevice();
+ }
+
+ MapMode aOldMap( pOut->GetMapMode() );
+ pOut->SetMapMode( MapMode( MAP_TWIP ) );
+
+ rMin = 0;
+ rMax = 0;
+ rAbsMin = 0;
+
+ const SvxLRSpaceItem &rSpace = GetSwAttrSet().GetLRSpace();
+ long nLROffset = rSpace.GetTxtLeft() + GetLeftMarginWithNum( sal_True );
+ short nFLOffs;
+ // Bei Numerierung ist ein neg. Erstzeileneinzug vermutlich
+ // bereits gefuellt...
+ if( !GetFirstLineOfsWithNum( nFLOffs ) || nFLOffs > nLROffset )
+ nLROffset = nFLOffs;
+
+ SwMinMaxNodeArgs aNodeArgs;
+ aNodeArgs.nMinWidth = 0;
+ aNodeArgs.nMaxWidth = 0;
+ aNodeArgs.nLeftRest = nLROffset;
+ aNodeArgs.nRightRest = rSpace.GetRight();
+ aNodeArgs.nLeftDiff = 0;
+ aNodeArgs.nRightDiff = 0;
+ if( nIndex )
+ {
+ SwSpzFrmFmts* pTmp = (SwSpzFrmFmts*)GetDoc()->GetSpzFrmFmts();
+ if( pTmp )
+ {
+ aNodeArgs.nIndx = nIndex;
+ pTmp->ForEach( &lcl_MinMaxNode, &aNodeArgs );
+ }
+ }
+ if( aNodeArgs.nLeftRest < 0 )
+ aNodeArgs.Minimum( nLROffset - aNodeArgs.nLeftRest );
+ aNodeArgs.nLeftRest -= aNodeArgs.nLeftDiff;
+ if( aNodeArgs.nLeftRest < 0 )
+ aNodeArgs.nMaxWidth -= aNodeArgs.nLeftRest;
+
+ if( aNodeArgs.nRightRest < 0 )
+ aNodeArgs.Minimum( rSpace.GetRight() - aNodeArgs.nRightRest );
+ aNodeArgs.nRightRest -= aNodeArgs.nRightDiff;
+ if( aNodeArgs.nRightRest < 0 )
+ aNodeArgs.nMaxWidth -= aNodeArgs.nRightRest;
+
+ SwScriptInfo aScriptInfo;
+ SwAttrIter aIter( *(SwTxtNode*)this, aScriptInfo );
+ xub_StrLen nIdx = 0;
+ aIter.SeekAndChgAttrIter( nIdx, pOut );
+ xub_StrLen nLen = m_Text.Len();
+ long nAktWidth = 0;
+ MSHORT nAdd = 0;
+ SwMinMaxArgs aArg( pOut, pSh, rMin, rMax, rAbsMin );
+ while( nIdx < nLen )
+ {
+ xub_StrLen nNextChg = aIter.GetNextAttr();
+ xub_StrLen nStop = aScriptInfo.NextScriptChg( nIdx );
+ if( nNextChg > nStop )
+ nNextChg = nStop;
+ SwTxtAttr *pHint = NULL;
+ xub_Unicode cChar = CH_BLANK;
+ nStop = nIdx;
+ while( nStop < nLen && nStop < nNextChg &&
+ CH_TAB != ( cChar = m_Text.GetChar( nStop ) ) &&
+ CH_BREAK != cChar && CHAR_HARDBLANK != cChar &&
+ CHAR_HARDHYPHEN != cChar && CHAR_SOFTHYPHEN != cChar &&
+ !pHint )
+ {
+ if( ( CH_TXTATR_BREAKWORD != cChar && CH_TXTATR_INWORD != cChar )
+ || ( 0 == ( pHint = aIter.GetAttr( nStop ) ) ) )
+ ++nStop;
+ }
+ if ( lcl_MinMaxString( aArg, aIter.GetFnt(), m_Text, nIdx, nStop ) )
+ {
+ nAdd = 20;
+ }
+ nIdx = nStop;
+ aIter.SeekAndChgAttrIter( nIdx, pOut );
+ switch( cChar )
+ {
+ case CH_BREAK :
+ {
+ if( (long)rMax < aArg.nRowWidth )
+ rMax = aArg.nRowWidth;
+ aArg.nRowWidth = 0;
+ aArg.NewWord();
+ aIter.SeekAndChgAttrIter( ++nIdx, pOut );
+ }
+ break;
+ case CH_TAB :
+ {
+ aArg.NewWord();
+ aIter.SeekAndChgAttrIter( ++nIdx, pOut );
+ }
+ break;
+ case CHAR_SOFTHYPHEN:
+ ++nIdx;
+ break;
+ case CHAR_HARDBLANK:
+ case CHAR_HARDHYPHEN:
+ {
+ XubString sTmp( cChar );
+ SwDrawTextInfo aDrawInf( const_cast<ViewShell *>(getIDocumentLayoutAccess()->GetCurrentViewShell()),
+ *pOut, 0, sTmp, 0, 1, 0, sal_False );//swmod 080311
+ nAktWidth = aIter.GetFnt()->_GetTxtSize( aDrawInf ).Width();
+ aArg.nWordWidth += nAktWidth;
+ aArg.nRowWidth += nAktWidth;
+ if( (long)rAbsMin < aArg.nWordWidth )
+ rAbsMin = aArg.nWordWidth;
+ aArg.Minimum( aArg.nWordWidth + aArg.nWordAdd );
+ aArg.nNoLineBreak = nIdx++;
+ }
+ break;
+ case CH_TXTATR_BREAKWORD:
+ case CH_TXTATR_INWORD:
+ {
+ if( !pHint )
+ break;
+ long nOldWidth = aArg.nWordWidth;
+ long nOldAdd = aArg.nWordAdd;
+ aArg.NewWord();
+
+ switch( pHint->Which() )
+ {
+ case RES_TXTATR_FLYCNT :
+ {
+ SwFrmFmt *pFrmFmt = pHint->GetFlyCnt().GetFrmFmt();
+ const SvxLRSpaceItem &rLR = pFrmFmt->GetLRSpace();
+ if( RES_DRAWFRMFMT == pFrmFmt->Which() )
+ {
+ const SdrObject* pSObj = pFrmFmt->FindSdrObject();
+ if( pSObj )
+ nAktWidth = pSObj->GetCurrentBoundRect().GetWidth();
+ else
+ nAktWidth = 0;
+ }
+ else
+ {
+ const SwFmtFrmSize& rTmpSize = pFrmFmt->GetFrmSize();
+ if( RES_FLYFRMFMT == pFrmFmt->Which()
+ && rTmpSize.GetWidthPercent() )
+ {
+/*-----------------------------------------------------------------------------
+ * Hier ein HACK fuer folgende Situation: In dem Absatz befindet sich
+ * ein Textrahmen mit relativer Groesse. Dann nehmen wir mal als minimale
+ * Breite 0,5 cm und als maximale KSHRT_MAX.
+ * Sauberer und vielleicht spaeter notwendig waere es, ueber den Inhalt
+ * des Textrahmens zu iterieren und GetMinMaxSize rekursiv zu rufen.
+ * --------------------------------------------------------------------------*/
+ nAktWidth = FLYINCNT_MIN_WIDTH; // 0,5 cm
+ if( (long)rMax < KSHRT_MAX )
+ rMax = KSHRT_MAX;
+ }
+ else
+ nAktWidth = pFrmFmt->GetFrmSize().GetWidth();
+ }
+ nAktWidth += rLR.GetLeft();
+ nAktWidth += rLR.GetRight();
+ aArg.nWordAdd = nOldWidth + nOldAdd;
+ aArg.nWordWidth = nAktWidth;
+ aArg.nRowWidth += nAktWidth;
+ if( (long)rAbsMin < aArg.nWordWidth )
+ rAbsMin = aArg.nWordWidth;
+ aArg.Minimum( aArg.nWordWidth + aArg.nWordAdd );
+ break;
+ }
+ case RES_TXTATR_FTN :
+ {
+ const XubString aTxt = pHint->GetFtn().GetNumStr();
+ if( lcl_MinMaxString( aArg, aIter.GetFnt(), aTxt, 0,
+ aTxt.Len() ) )
+ nAdd = 20;
+ break;
+ }
+ case RES_TXTATR_FIELD :
+ {
+ SwField *pFld = (SwField*)pHint->GetFld().GetFld();
+ const String aTxt = pFld->ExpandField(true);
+ if( lcl_MinMaxString( aArg, aIter.GetFnt(), aTxt, 0,
+ aTxt.Len() ) )
+ nAdd = 20;
+ break;
+ }
+ default: aArg.nWordWidth = nOldWidth;
+ aArg.nWordAdd = nOldAdd;
+
+ }
+ aIter.SeekAndChgAttrIter( ++nIdx, pOut );
+ }
+ break;
+ }
+ }
+ if( (long)rMax < aArg.nRowWidth )
+ rMax = aArg.nRowWidth;
+
+ nLROffset += rSpace.GetRight();
+
+ rAbsMin += nLROffset;
+ rAbsMin += nAdd;
+ rMin += nLROffset;
+ rMin += nAdd;
+ if( (long)rMin < aNodeArgs.nMinWidth )
+ rMin = aNodeArgs.nMinWidth;
+ if( (long)rAbsMin < aNodeArgs.nMinWidth )
+ rAbsMin = aNodeArgs.nMinWidth;
+ rMax += aNodeArgs.nMaxWidth;
+ rMax += nLROffset;
+ rMax += nAdd;
+ if( rMax < rMin ) // z.B. Rahmen mit Durchlauf gehen zunaechst nur
+ rMax = rMin; // in das Minimum ein
+ pOut->SetMapMode( aOldMap );
+}
+
+/*************************************************************************
+ * SwTxtNode::GetScalingOfSelectedText()
+ *
+ * Calculates the width of the text part specified by nStt and nEnd,
+ * the height of the line containing nStt is devided by this width,
+ * indicating the scaling factor, if the text part is rotated.
+ * Having CH_BREAKs in the text part, this method returns the scaling
+ * factor for the longest of the text parts separated by the CH_BREAKs.
+ *
+ * changing this method very likely requires changing of "GetMinMaxSize"
+ *************************************************************************/
+
+sal_uInt16 SwTxtNode::GetScalingOfSelectedText( xub_StrLen nStt, xub_StrLen nEnd )
+ const
+{
+ ViewShell* pSh = NULL;
+ OutputDevice* pOut = NULL;
+ GetDoc()->GetEditShell( &pSh );
+
+ if ( pSh )
+ pOut = &pSh->GetRefDev();
+ else
+ {
+ //Zugriff ueber StarONE, es muss keine Shell existieren oder aktiv sein.
+ if ( getIDocumentSettingAccess()->get(IDocumentSettingAccess::HTML_MODE) )
+ pOut = GetpApp()->GetDefaultDevice();
+ else
+ pOut = getIDocumentDeviceAccess()->getReferenceDevice( true );
+ }
+
+ OSL_ENSURE( pOut, "GetScalingOfSelectedText without outdev" );
+
+ MapMode aOldMap( pOut->GetMapMode() );
+ pOut->SetMapMode( MapMode( MAP_TWIP ) );
+
+ if ( nStt == nEnd )
+ {
+ if ( !pBreakIt->GetBreakIter().is() )
+ return 100;
+
+ SwScriptInfo aScriptInfo;
+ SwAttrIter aIter( *(SwTxtNode*)this, aScriptInfo );
+ aIter.SeekAndChgAttrIter( nStt, pOut );
+
+ Boundary aBound =
+ pBreakIt->GetBreakIter()->getWordBoundary( GetTxt(), nStt,
+ pBreakIt->GetLocale( aIter.GetFnt()->GetLanguage() ),
+ WordType::DICTIONARY_WORD, sal_True );
+
+ if ( nStt == aBound.startPos )
+ {
+ // cursor is at left or right border of word
+ pOut->SetMapMode( aOldMap );
+ return 100;
+ }
+
+ nStt = (xub_StrLen)aBound.startPos;
+ nEnd = (xub_StrLen)aBound.endPos;
+
+ if ( nStt == nEnd )
+ {
+ pOut->SetMapMode( aOldMap );
+ return 100;
+ }
+ }
+
+ SwScriptInfo aScriptInfo;
+ SwAttrIter aIter( *(SwTxtNode*)this, aScriptInfo );
+
+ // We do not want scaling attributes to be considered during this
+ // calculation. For this, we push a temporary scaling attribute with
+ // scaling value 100 and priority flag on top of the scaling stack
+ SwAttrHandler& rAH = aIter.GetAttrHandler();
+ SvxCharScaleWidthItem aItem(100, RES_CHRATR_SCALEW);
+ SwTxtAttrEnd aAttr( aItem, nStt, nEnd );
+ aAttr.SetPriorityAttr( sal_True );
+ rAH.PushAndChg( aAttr, *(aIter.GetFnt()) );
+
+ xub_StrLen nIdx = nStt;
+
+ sal_uLong nWidth = 0;
+ sal_uLong nProWidth = 0;
+
+ while( nIdx < nEnd )
+ {
+ aIter.SeekAndChgAttrIter( nIdx, pOut );
+
+ // scan for end of portion
+ xub_StrLen nNextChg = aIter.GetNextAttr();
+ xub_StrLen nStop = aScriptInfo.NextScriptChg( nIdx );
+ if( nNextChg > nStop )
+ nNextChg = nStop;
+
+ nStop = nIdx;
+ xub_Unicode cChar = CH_BLANK;
+ SwTxtAttr* pHint = NULL;
+
+ // stop at special characters in [ nIdx, nNextChg ]
+ while( nStop < nEnd && nStop < nNextChg )
+ {
+ cChar = m_Text.GetChar( nStop );
+ if (
+ CH_TAB == cChar ||
+ CH_BREAK == cChar ||
+ CHAR_HARDBLANK == cChar ||
+ CHAR_HARDHYPHEN == cChar ||
+ CHAR_SOFTHYPHEN == cChar ||
+ (
+ (CH_TXTATR_BREAKWORD == cChar || CH_TXTATR_INWORD == cChar) &&
+ (0 == (pHint = aIter.GetAttr(nStop)))
+ )
+ )
+ {
+ break;
+ }
+ else
+ ++nStop;
+ }
+
+ // calculate text widths up to cChar
+ if ( nStop > nIdx )
+ {
+ SwDrawTextInfo aDrawInf( pSh, *pOut, 0, GetTxt(), nIdx, nStop - nIdx );
+ nProWidth += aIter.GetFnt()->_GetTxtSize( aDrawInf ).Width();
+ }
+
+ nIdx = nStop;
+ aIter.SeekAndChgAttrIter( nIdx, pOut );
+
+ if ( cChar == CH_BREAK )
+ {
+ nWidth = Max( nWidth, nProWidth );
+ nProWidth = 0;
+ nIdx++;
+ }
+ else if ( cChar == CH_TAB )
+ {
+ // tab receives width of one space
+ XubString sTmp( CH_BLANK );
+ SwDrawTextInfo aDrawInf( pSh, *pOut, 0, sTmp, 0, 1 );
+ nProWidth += aIter.GetFnt()->_GetTxtSize( aDrawInf ).Width();
+ nIdx++;
+ }
+ else if ( cChar == CHAR_SOFTHYPHEN )
+ ++nIdx;
+ else if ( cChar == CHAR_HARDBLANK || cChar == CHAR_HARDHYPHEN )
+ {
+ XubString sTmp( cChar );
+ SwDrawTextInfo aDrawInf( pSh, *pOut, 0, sTmp, 0, 1 );
+ nProWidth += aIter.GetFnt()->_GetTxtSize( aDrawInf ).Width();
+ nIdx++;
+ }
+ else if ( pHint && ( cChar == CH_TXTATR_BREAKWORD || CH_TXTATR_INWORD ) )
+ {
+ switch( pHint->Which() )
+ {
+ case RES_TXTATR_FTN :
+ {
+ const XubString aTxt = pHint->GetFtn().GetNumStr();
+ SwDrawTextInfo aDrawInf( pSh, *pOut, 0, aTxt, 0, aTxt.Len() );
+
+ nProWidth += aIter.GetFnt()->_GetTxtSize( aDrawInf ).Width();
+ break;
+ }
+ case RES_TXTATR_FIELD :
+ {
+ SwField *pFld = (SwField*)pHint->GetFld().GetFld();
+ String const aTxt = pFld->ExpandField(true);
+ SwDrawTextInfo aDrawInf( pSh, *pOut, 0, aTxt, 0, aTxt.Len() );
+
+ nProWidth += aIter.GetFnt()->_GetTxtSize( aDrawInf ).Width();
+ break;
+ }
+ default:
+ {
+ // any suggestions for a default action?
+ }
+ } // end of switch
+ nIdx++;
+ } // end of while
+ }
+
+ nWidth = Max( nWidth, nProWidth );
+
+ // search for a text frame this node belongs to
+ SwIterator<SwTxtFrm,SwTxtNode> aFrmIter( *this );
+ SwTxtFrm* pFrm = 0;
+ for( SwTxtFrm* pTmpFrm = aFrmIter.First(); pTmpFrm; pTmpFrm = aFrmIter.Next() )
+ {
+ if ( pTmpFrm->GetOfst() <= nStt &&
+ ( !pTmpFrm->GetFollow() ||
+ pTmpFrm->GetFollow()->GetOfst() > nStt ) )
+ {
+ pFrm = pTmpFrm;
+ break;
+ }
+ }
+
+ // search for the line containing nStt
+ if ( pFrm && pFrm->HasPara() )
+ {
+ SwTxtInfo aInf( pFrm );
+ SwTxtIter aLine( pFrm, &aInf );
+ aLine.CharToLine( nStt );
+ pOut->SetMapMode( aOldMap );
+ return (sal_uInt16)( nWidth ?
+ ( ( 100 * aLine.GetCurr()->Height() ) / nWidth ) : 0 );
+ }
+ // no frame or no paragraph, we take the height of the character
+ // at nStt as line height
+
+ aIter.SeekAndChgAttrIter( nStt, pOut );
+ pOut->SetMapMode( aOldMap );
+
+ SwDrawTextInfo aDrawInf( pSh, *pOut, 0, GetTxt(), nStt, 1 );
+ return (sal_uInt16)
+ ( nWidth ? ((100 * aIter.GetFnt()->_GetTxtSize( aDrawInf ).Height()) / nWidth ) : 0 );
+}
+
+sal_uInt16 SwTxtNode::GetWidthOfLeadingTabs() const
+{
+ sal_uInt16 nRet = 0;
+
+ xub_StrLen nIdx = 0;
+ sal_Unicode cCh;
+
+ while ( nIdx < GetTxt().Len() &&
+ ( '\t' == ( cCh = GetTxt().GetChar( nIdx ) ) ||
+ ' ' == cCh ) )
+ ++nIdx;
+
+ if ( nIdx > 0 )
+ {
+ SwPosition aPos( *this );
+ aPos.nContent += nIdx;
+
+ // Find the non-follow text frame:
+ SwIterator<SwTxtFrm,SwTxtNode> aIter( *this );
+ for( SwTxtFrm* pFrm = aIter.First(); pFrm; pFrm = aIter.Next() )
+ {
+ // Only consider master frames:
+ if ( !pFrm->IsFollow() )
+ {
+ SWRECTFN( pFrm )
+ SwRect aRect;
+ pFrm->GetCharRect( aRect, aPos );
+ nRet = (sal_uInt16)
+ ( pFrm->IsRightToLeft() ?
+ (pFrm->*fnRect->fnGetPrtRight)() - (aRect.*fnRect->fnGetRight)() :
+ (aRect.*fnRect->fnGetLeft)() - (pFrm->*fnRect->fnGetPrtLeft)() );
+ break;
+ }
+ }
+ }
+
+ return nRet;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/text/itratr.hxx b/sw/source/core/text/itratr.hxx
new file mode 100644
index 000000000000..a9e5b455e1f9
--- /dev/null
+++ b/sw/source/core/text/itratr.hxx
@@ -0,0 +1,136 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+#ifndef _ITRATR_HXX
+#define _ITRATR_HXX
+#include <atrhndl.hxx>
+
+#include "txttypes.hxx"
+#include "swfont.hxx"
+#include "porlay.hxx"
+
+#define _SVSTDARR_XUB_STRLEN
+#define _SVSTDARR_USHORTS
+#include <svl/svstdarr.hxx>
+
+class OutputDevice;
+class SwFont;
+class SwpHints;
+class SwTxtAttr;
+class SwAttrSet;
+class SwTxtNode;
+class SwRedlineItr;
+class ViewShell;
+class SwTxtFrm;
+
+/*************************************************************************
+ * class SwAttrIter
+ *************************************************************************/
+
+class SwAttrIter
+{
+ friend class SwFontSave;
+protected:
+
+ SwAttrHandler aAttrHandler;
+ ViewShell *pShell;
+ SwFont *pFnt;
+ SwpHints *pHints;
+ const SwAttrSet* pAttrSet; // das Char-Attribut-Set
+ SwScriptInfo* pScriptInfo;
+
+private:
+ OutputDevice *pLastOut;
+ MSHORT nChgCnt;
+ SwRedlineItr *pRedln;
+ xub_StrLen nStartIndex, nEndIndex, nPos;
+ sal_uInt8 nPropFont;
+ void SeekFwd( const xub_StrLen nPos );
+ inline void SetFnt( SwFont* pNew ) { pFnt = pNew; }
+ const void* aMagicNo[ SW_SCRIPTS ];
+ MSHORT aFntIdx[ SW_SCRIPTS ];
+ const SwTxtNode* m_pTxtNode;
+
+protected:
+ void Chg( SwTxtAttr *pHt );
+ void Rst( SwTxtAttr *pHt );
+ void CtorInitAttrIter( SwTxtNode& rTxtNode, SwScriptInfo& rScrInf, SwTxtFrm* pFrm = 0 );
+ inline SwAttrIter(SwTxtNode* pTxtNode)
+ : pShell(0), pFnt(0), pHints(0), pAttrSet(0), pScriptInfo(0), pLastOut(0), nChgCnt(0), pRedln(0), nPropFont(0), m_pTxtNode(pTxtNode) {
+ aMagicNo[SW_LATIN] = aMagicNo[SW_CJK] = aMagicNo[SW_CTL] = NULL;
+ }
+
+public:
+ // Konstruktor, Destruktor
+ inline SwAttrIter( SwTxtNode& rTxtNode, SwScriptInfo& rScrInf )
+ : pShell(0), pFnt(0), pHints(0), pScriptInfo(0), pLastOut(0), nChgCnt(0), pRedln(0),nPropFont(0), m_pTxtNode(&rTxtNode)
+ { CtorInitAttrIter( rTxtNode, rScrInf ); }
+
+ virtual ~SwAttrIter();
+
+ inline SwRedlineItr *GetRedln() { return pRedln; }
+ // Liefert im Parameter die Position des naechsten Wechsels vor oder an
+ // der uebergebenen Characterposition zurueck. Liefert sal_False, wenn vor
+ // oder an dieser Position kein Wechsel mehr erfolgt, sal_True sonst.
+ xub_StrLen GetNextAttr( ) const;
+ // Macht die an der Characterposition i gueltigen Attribute im
+ // logischen Font wirksam.
+ sal_Bool Seek( const xub_StrLen nPos );
+ // Bastelt den Font an der gew. Position via Seek und fragt ihn,
+ // ob er ein Symbolfont ist.
+ sal_Bool IsSymbol( const xub_StrLen nPos );
+
+ // Fuehrt ChgPhysFnt aus, wenn Seek() sal_True zurueckliefert.
+ sal_Bool SeekAndChgAttrIter( const xub_StrLen nPos, OutputDevice* pOut );
+ sal_Bool SeekStartAndChgAttrIter( OutputDevice* pOut, const sal_Bool bParaFont = sal_False );
+
+ // Gibt es ueberhaupt Attributwechsel ?
+ inline sal_Bool HasHints() const { return 0 != pHints; }
+
+ // liefert fuer eine Position das Attribut
+ SwTxtAttr *GetAttr( const xub_StrLen nPos ) const;
+
+ inline const SwAttrSet* GetAttrSet() const { return pAttrSet; }
+
+ inline const SwpHints *GetHints() const { return pHints; }
+
+ inline SwFont *GetFnt() { return pFnt; }
+ inline const SwFont *GetFnt() const { return pFnt; }
+
+ inline sal_uInt8 GetPropFont() const { return nPropFont; }
+ inline void SetPropFont( const sal_uInt8 nNew ) { nPropFont = nNew; }
+
+ inline SwAttrHandler& GetAttrHandler() { return aAttrHandler; }
+
+#if OSL_DEBUG_LEVEL > 1
+ void Dump( SvStream &rOS ) const;
+#endif
+};
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/text/itrcrsr.cxx b/sw/source/core/text/itrcrsr.cxx
new file mode 100644
index 000000000000..ff3f2b87f166
--- /dev/null
+++ b/sw/source/core/text/itrcrsr.cxx
@@ -0,0 +1,1880 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+#include "hintids.hxx"
+#include "ndtxt.hxx"
+#include "frmfmt.hxx"
+#include "paratr.hxx"
+#include "flyfrm.hxx"
+#include "pam.hxx"
+#include "swselectionlist.hxx"
+#include <sortedobjs.hxx>
+#include <editeng/protitem.hxx>
+#include <editeng/adjitem.hxx>
+#include <editeng/lspcitem.hxx>
+#include <editeng/lrspitem.hxx>
+#include <frmatr.hxx>
+#include <pagedesc.hxx> // SwPageDesc
+#include <tgrditem.hxx>
+#include <IDocumentSettingAccess.hxx>
+#include <pagefrm.hxx>
+
+#include "itrtxt.hxx"
+#include "txtfrm.hxx"
+#include "flyfrms.hxx"
+#include "porglue.hxx" // SwFlyCnt
+#include "porfld.hxx" // SwFldPortion::IsFollow()
+#include "porfly.hxx" // GetFlyCrsrOfst()
+#include "pordrop.hxx"
+#include "crstate.hxx" // SwCrsrMoveState
+#include <pormulti.hxx> // SwMultiPortion
+// --> OD 2010-05-05 #i111284#
+#include <numrule.hxx>
+// <--
+
+// Nicht reentrant !!!
+// wird in GetCharRect gesetzt und im UnitUp/Down ausgewertet.
+sal_Bool SwTxtCursor::bRightMargin = sal_False;
+
+
+/*************************************************************************
+ * lcl_GetCharRectInsideField
+ *
+ * After calculating the position of a character during GetCharRect
+ * this function allows to find the coordinates of a position (defined
+ * in pCMS->pSpecialPos) inside a special portion (e.g., a field)
+ *************************************************************************/
+void lcl_GetCharRectInsideField( SwTxtSizeInfo& rInf, SwRect& rOrig,
+ const SwCrsrMoveState& rCMS,
+ const SwLinePortion& rPor )
+{
+ OSL_ENSURE( rCMS.pSpecialPos, "Information about special pos missing" );
+
+ if ( rPor.InFldGrp() && ((SwFldPortion&)rPor).GetExp().Len() )
+ {
+ const sal_uInt16 nCharOfst = rCMS.pSpecialPos->nCharOfst;
+ sal_uInt16 nFldIdx = 0;
+ sal_uInt16 nFldLen = 0;
+
+ const XubString* pString = 0;
+ const SwLinePortion* pPor = &rPor;
+ do
+ {
+ if ( pPor->InFldGrp() )
+ {
+ pString = &((SwFldPortion*)pPor)->GetExp();
+ nFldLen = pString->Len();
+ }
+ else
+ {
+ pString = 0;
+ nFldLen = 0;
+ }
+
+ if ( ! pPor->GetPortion() || nFldIdx + nFldLen > nCharOfst )
+ break;
+
+ nFldIdx = nFldIdx + nFldLen;
+ rOrig.Pos().X() += pPor->Width();
+ pPor = pPor->GetPortion();
+
+ } while ( sal_True );
+
+ OSL_ENSURE( nCharOfst >= nFldIdx, "Request of position inside field failed" );
+ sal_uInt16 nLen = nCharOfst - nFldIdx + 1;
+
+ if ( pString )
+ {
+ // get script for field portion
+ rInf.GetFont()->SetActual( SwScriptInfo::WhichFont( 0, pString, 0 ) );
+
+ xub_StrLen nOldLen = pPor->GetLen();
+ ((SwLinePortion*)pPor)->SetLen( nLen - 1 );
+ const SwTwips nX1 = pPor->GetLen() ?
+ pPor->GetTxtSize( rInf ).Width() :
+ 0;
+
+ SwTwips nX2 = 0;
+ if ( rCMS.bRealWidth )
+ {
+ ((SwLinePortion*)pPor)->SetLen( nLen );
+ nX2 = pPor->GetTxtSize( rInf ).Width();
+ }
+
+ ((SwLinePortion*)pPor)->SetLen( nOldLen );
+
+ rOrig.Pos().X() += nX1;
+ rOrig.Width( ( nX2 > nX1 ) ?
+ ( nX2 - nX1 ) :
+ 1 );
+ }
+ }
+ else
+ {
+ // special cases: no common fields, e.g., graphic number portion,
+ // FlyInCntPortions, Notes
+ rOrig.Width( rCMS.bRealWidth && rPor.Width() ? rPor.Width() : 1 );
+ }
+}
+
+// --> OD 2010-05-05 #i111284#
+namespace {
+ bool AreListLevelIndentsApplicableAndLabelAlignmentActive( const SwTxtNode& rTxtNode )
+ {
+ bool bRet( false );
+
+ if ( rTxtNode.AreListLevelIndentsApplicable() )
+ {
+ const SwNumFmt& rNumFmt =
+ rTxtNode.GetNumRule()->Get( static_cast<sal_uInt16>(rTxtNode.GetActualListLevel()) );
+ if ( rNumFmt.GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_ALIGNMENT )
+ {
+ bRet = true;
+ }
+ }
+
+ return bRet;
+ }
+} // end of anonymous namespace
+// <--
+
+/*************************************************************************
+ * SwTxtMargin::CtorInitTxtMargin()
+ *************************************************************************/
+void SwTxtMargin::CtorInitTxtMargin( SwTxtFrm *pNewFrm, SwTxtSizeInfo *pNewInf )
+{
+ CtorInitTxtIter( pNewFrm, pNewInf );
+
+ pInf = pNewInf;
+ GetInfo().SetFont( GetFnt() );
+ const SwTxtNode *pNode = pFrm->GetTxtNode();
+
+ const SvxLRSpaceItem &rSpace = pFrm->GetTxtNode()->GetSwAttrSet().GetLRSpace();
+ // --> OD 2009-09-08 #i95907#, #b6879723#
+ // --> OD 2010-05-05 #i111284#
+ const bool bListLevelIndentsApplicableAndLabelAlignmentActive(
+ AreListLevelIndentsApplicableAndLabelAlignmentActive( *(pFrm->GetTxtNode()) ) );
+ // <--
+
+ //
+ // Carefully adjust the text formatting ranges.
+ //
+ // This whole area desperately needs some rework. There are
+ // quite a couple of values that need to be considered:
+ // 1. paragraph indent
+ // 2. paragraph first line indent
+ // 3. numbering indent
+ // 4. numbering spacing to text
+ // 5. paragraph border
+ // Note: These values have already been used during calculation
+ // of the printing area of the paragraph.
+ const int nLMWithNum = pNode->GetLeftMarginWithNum( sal_True );
+ if ( pFrm->IsRightToLeft() )
+ {
+ // this calculation is identical this the calculation for L2R layout - see below
+ nLeft = pFrm->Frm().Left() +
+ pFrm->Prt().Left() +
+ nLMWithNum -
+ pNode->GetLeftMarginWithNum( sal_False ) -
+ // --> OD 2009-09-08 #i95907#, #b6879723#
+ // --> OD 2010-05-05 #i111284#
+// rSpace.GetLeft() +
+// rSpace.GetTxtLeft();
+ ( bListLevelIndentsApplicableAndLabelAlignmentActive
+ ? 0
+ : ( rSpace.GetLeft() - rSpace.GetTxtLeft() ) );
+ // <--
+ }
+ else
+ {
+ // --> OD 2009-09-08 #i95907#, #b6879723#
+ // --> OD 2010-05-05 #i111284#
+// if ( !pNode->getIDocumentSettingAccess()->get(IDocumentSettingAccess::IGNORE_FIRST_LINE_INDENT_IN_NUMBERING) )
+ if ( bListLevelIndentsApplicableAndLabelAlignmentActive ||
+ !pNode->getIDocumentSettingAccess()->get(IDocumentSettingAccess::IGNORE_FIRST_LINE_INDENT_IN_NUMBERING) )
+ // <--
+ {
+ // this calculation is identical this the calculation for R2L layout - see above
+ nLeft = pFrm->Frm().Left() +
+ pFrm->Prt().Left() +
+ nLMWithNum -
+ pNode->GetLeftMarginWithNum( sal_False ) -
+ // --> OD 2009-09-08 #i95907#, #b6879723#
+ // --> OD 2010-05-05 #i111284#
+// rSpace.GetLeft() +
+// rSpace.GetTxtLeft();
+ ( bListLevelIndentsApplicableAndLabelAlignmentActive
+ ? 0
+ : ( rSpace.GetLeft() - rSpace.GetTxtLeft() ) );
+ // <--
+ }
+ else
+ {
+ nLeft = pFrm->Frm().Left() +
+ Max( long( rSpace.GetTxtLeft() + nLMWithNum ),
+ pFrm->Prt().Left() );
+ }
+ }
+
+ nRight = pFrm->Frm().Left() + pFrm->Prt().Left() + pFrm->Prt().Width();
+
+ if( nLeft >= nRight &&
+ // --> FME 2005-08-10 #i53066# Omit adjustment of nLeft for numbered
+ // paras inside cells inside new documents:
+ ( pNode->getIDocumentSettingAccess()->get(IDocumentSettingAccess::IGNORE_FIRST_LINE_INDENT_IN_NUMBERING) ||
+ !pFrm->IsInTab() ||
+ !nLMWithNum ) )
+ // <--
+ {
+ nLeft = pFrm->Prt().Left() + pFrm->Frm().Left();
+ if( nLeft >= nRight ) // z.B. bei grossen Absatzeinzuegen in schmalen Tabellenspalten
+ nRight = nLeft + 1; // einen goennen wir uns immer
+ }
+
+ if( pFrm->IsFollow() && pFrm->GetOfst() )
+ nFirst = nLeft;
+ else
+ {
+ short nFLOfst = 0;
+ long nFirstLineOfs = 0;
+ if( !pNode->GetFirstLineOfsWithNum( nFLOfst ) &&
+ rSpace.IsAutoFirst() )
+ {
+ nFirstLineOfs = GetFnt()->GetSize( GetFnt()->GetActual() ).Height();
+ const SvxLineSpacingItem *pSpace = aLineInf.GetLineSpacing();
+ if( pSpace )
+ {
+ switch( pSpace->GetLineSpaceRule() )
+ {
+ case SVX_LINE_SPACE_AUTO:
+ break;
+ case SVX_LINE_SPACE_MIN:
+ {
+ if( nFirstLineOfs < KSHORT( pSpace->GetLineHeight() ) )
+ nFirstLineOfs = pSpace->GetLineHeight();
+ break;
+ }
+ case SVX_LINE_SPACE_FIX:
+ nFirstLineOfs = pSpace->GetLineHeight();
+ break;
+ default: OSL_FAIL( ": unknown LineSpaceRule" );
+ }
+ switch( pSpace->GetInterLineSpaceRule() )
+ {
+ case SVX_INTER_LINE_SPACE_OFF:
+ break;
+ case SVX_INTER_LINE_SPACE_PROP:
+ {
+ long nTmp = pSpace->GetPropLineSpace();
+ // 50% ist das Minimum, bei 0% schalten wir auf
+ // den Defaultwert 100% um ...
+ if( nTmp < 50 )
+ nTmp = nTmp ? 50 : 100;
+
+ nTmp *= nFirstLineOfs;
+ nTmp /= 100;
+ if( !nTmp )
+ ++nTmp;
+ nFirstLineOfs = (KSHORT)nTmp;
+ break;
+ }
+ case SVX_INTER_LINE_SPACE_FIX:
+ {
+ nFirstLineOfs += pSpace->GetInterLineSpace();
+ break;
+ }
+ default: OSL_FAIL( ": unknown InterLineSpaceRule" );
+ }
+ }
+ }
+ else
+ nFirstLineOfs = nFLOfst;
+
+ // --> OD 2009-09-08 #i95907#, #b6879723#
+ // --> OD 2010-05-05 #i111284#
+// if ( pFrm->IsRightToLeft() ||
+// !pNode->getIDocumentSettingAccess()->get(IDocumentSettingAccess::IGNORE_FIRST_LINE_INDENT_IN_NUMBERING) )
+ if ( pFrm->IsRightToLeft() ||
+ bListLevelIndentsApplicableAndLabelAlignmentActive ||
+ !pNode->getIDocumentSettingAccess()->get(IDocumentSettingAccess::IGNORE_FIRST_LINE_INDENT_IN_NUMBERING) )
+ // <--
+ {
+ nFirst = nLeft + nFirstLineOfs;
+ }
+ else
+ {
+ nFirst = pFrm->Frm().Left() +
+ Max( rSpace.GetTxtLeft() + nLMWithNum+ nFirstLineOfs,
+ pFrm->Prt().Left() );
+ }
+
+ // Note: <SwTxtFrm::GetAdditionalFirstLineOffset()> returns a negative
+ // value for the new list label postion and space mode LABEL_ALIGNMENT
+ // and label alignment CENTER and RIGHT in L2R layout respectively
+ // label alignment LEFT and CENTER in R2L layout
+ nFirst += pFrm->GetAdditionalFirstLineOffset();
+
+ if( nFirst >= nRight )
+ nFirst = nRight - 1;
+ }
+ const SvxAdjustItem& rAdjust = pFrm->GetTxtNode()->GetSwAttrSet().GetAdjust();
+ nAdjust = static_cast<sal_uInt16>(rAdjust.GetAdjust());
+
+ // left is left and right is right
+ if ( pFrm->IsRightToLeft() )
+ {
+ if ( SVX_ADJUST_LEFT == nAdjust )
+ nAdjust = SVX_ADJUST_RIGHT;
+ else if ( SVX_ADJUST_RIGHT == nAdjust )
+ nAdjust = SVX_ADJUST_LEFT;
+ }
+
+ bOneBlock = rAdjust.GetOneWord() == SVX_ADJUST_BLOCK;
+ bLastBlock = rAdjust.GetLastBlock() == SVX_ADJUST_BLOCK;
+ bLastCenter = rAdjust.GetLastBlock() == SVX_ADJUST_CENTER;
+
+ // --> OD 2008-07-01 #i91133#
+ mnTabLeft = pNode->GetLeftMarginForTabCalculation();
+ // <--
+
+#if OSL_DEBUG_LEVEL > 1
+ static sal_Bool bOne = sal_False;
+ static sal_Bool bLast = sal_False;
+ static sal_Bool bCenter = sal_False;
+ bOneBlock |= bOne;
+ bLastBlock |= bLast;
+ bLastCenter |= bCenter;
+#endif
+ DropInit();
+}
+
+/*************************************************************************
+ * SwTxtMargin::DropInit()
+ *************************************************************************/
+void SwTxtMargin::DropInit()
+{
+ nDropLeft = nDropLines = nDropHeight = nDropDescent = 0;
+ const SwParaPortion *pPara = GetInfo().GetParaPortion();
+ if( pPara )
+ {
+ const SwDropPortion *pPorDrop = pPara->FindDropPortion();
+ if ( pPorDrop )
+ {
+ nDropLeft = pPorDrop->GetDropLeft();
+ nDropLines = pPorDrop->GetLines();
+ nDropHeight = pPorDrop->GetDropHeight();
+ nDropDescent = pPorDrop->GetDropDescent();
+ }
+ }
+}
+
+/*************************************************************************
+ * SwTxtMargin::GetLineStart()
+ *************************************************************************/
+
+// Unter Beruecksichtigung des Erstzeileneinzuges und der angebenen Breite.
+SwTwips SwTxtMargin::GetLineStart() const
+{
+ SwTwips nRet = GetLeftMargin();
+ if( GetAdjust() != SVX_ADJUST_LEFT &&
+ !pCurr->GetFirstPortion()->IsMarginPortion() )
+ {
+ // Wenn die erste Portion ein Margin ist, dann wird das
+ // Adjustment durch die Portions ausgedrueckt.
+ if( GetAdjust() == SVX_ADJUST_RIGHT )
+ nRet = Right() - CurrWidth();
+ else if( GetAdjust() == SVX_ADJUST_CENTER )
+ nRet += (GetLineWidth() - CurrWidth()) / 2;
+ }
+ return nRet;
+}
+
+/*************************************************************************
+ * SwTxtCursor::CtorInitTxtCursor()
+ *************************************************************************/
+void SwTxtCursor::CtorInitTxtCursor( SwTxtFrm *pNewFrm, SwTxtSizeInfo *pNewInf )
+{
+ CtorInitTxtMargin( pNewFrm, pNewInf );
+ // 6096: Vorsicht, die Iteratoren sind abgeleitet!
+ // GetInfo().SetOut( GetInfo().GetWin() );
+}
+
+/*************************************************************************
+ * SwTxtCursor::GetEndCharRect()
+ *************************************************************************/
+
+// 1170: Antikbug: Shift-Ende vergisst das letzte Zeichen ...
+
+sal_Bool SwTxtCursor::GetEndCharRect( SwRect* pOrig, const xub_StrLen nOfst,
+ SwCrsrMoveState* pCMS, const long nMax )
+{
+ // 1170: Mehrdeutigkeit von Dokumentpositionen
+ bRightMargin = sal_True;
+ CharCrsrToLine(nOfst);
+
+ // Etwas verdreht: nOfst bezeichnet die Position hinter dem letzten
+ // Zeichen der letzten Zeile == Position vor dem ersten Zeichen der
+ // Zeile in der wir gerade stehen:
+ if( nOfst != GetStart() || !pCurr->GetLen() )
+ {
+ // 8810: Masterzeile RightMargin, danach LeftMargin
+ const sal_Bool bRet = GetCharRect( pOrig, nOfst, pCMS, nMax );
+ bRightMargin = nOfst >= GetEnd() && nOfst < GetInfo().GetTxt().Len();
+ return bRet;
+ }
+
+ if( !GetPrev() || !GetPrev()->GetLen() || !PrevLine() )
+ return GetCharRect( pOrig, nOfst, pCMS, nMax );
+
+ // Adjustierung ggf. nachholen
+ GetAdjusted();
+
+ KSHORT nX = 0;
+ KSHORT nLast = 0;
+ SwLinePortion *pPor = pCurr->GetFirstPortion();
+
+ KSHORT nTmpHeight, nTmpAscent;
+ CalcAscentAndHeight( nTmpAscent, nTmpHeight );
+ KSHORT nPorHeight = nTmpHeight;
+ KSHORT nPorAscent = nTmpAscent;
+
+ // Die letzte Text/EndPortion der Zeile suchen
+ while( pPor )
+ {
+ nX = nX + pPor->Width();
+ if( pPor->InTxtGrp() || ( pPor->GetLen() && !pPor->IsFlyPortion()
+ && !pPor->IsHolePortion() ) || pPor->IsBreakPortion() )
+ {
+ nLast = nX;
+ nPorHeight = pPor->Height();
+ nPorAscent = pPor->GetAscent();
+ }
+ pPor = pPor->GetPortion();
+ }
+
+ const Size aCharSize( 1, nTmpHeight );
+ pOrig->Pos( GetTopLeft() );
+ pOrig->SSize( aCharSize );
+ pOrig->Pos().X() += nLast;
+ const SwTwips nTmpRight = Right() - 1;
+ if( pOrig->Left() > nTmpRight )
+ pOrig->Pos().X() = nTmpRight;
+
+ if ( pCMS && pCMS->bRealHeight )
+ {
+ if ( nTmpAscent > nPorAscent )
+ pCMS->aRealHeight.X() = nTmpAscent - nPorAscent;
+ else
+ pCMS->aRealHeight.X() = 0;
+ OSL_ENSURE( nPorHeight, "GetCharRect: Missing Portion-Height" );
+ pCMS->aRealHeight.Y() = nPorHeight;
+ }
+
+ return sal_True;
+}
+
+/*************************************************************************
+ * void SwTxtCursor::_GetCharRect(..)
+ * internal function, called by SwTxtCursor::GetCharRect() to calculate
+ * the relative character position in the current line.
+ * pOrig referes to x and y coordinates, width and height of the cursor
+ * pCMS is used for restricting the cursor, if there are different font
+ * heights in one line ( first value = offset to y of pOrig, second
+ * value = real height of (shortened) cursor
+ *************************************************************************/
+
+void SwTxtCursor::_GetCharRect( SwRect* pOrig, const xub_StrLen nOfst,
+ SwCrsrMoveState* pCMS )
+{
+ const XubString &rText = GetInfo().GetTxt();
+ SwTxtSizeInfo aInf( GetInfo(), rText, nStart );
+ if( GetPropFont() )
+ aInf.GetFont()->SetProportion( GetPropFont() );
+ KSHORT nTmpAscent, nTmpHeight; // Zeilenhoehe
+ CalcAscentAndHeight( nTmpAscent, nTmpHeight );
+ const Size aCharSize( 1, nTmpHeight );
+ const Point aCharPos;
+ pOrig->Pos( aCharPos );
+ pOrig->SSize( aCharSize );
+
+ // If we are looking for a position inside a field which covers
+ // more than one line we may not skip any "empty portions" at the
+ // beginning of a line
+ const sal_Bool bInsideFirstField = pCMS && pCMS->pSpecialPos &&
+ ( pCMS->pSpecialPos->nLineOfst ||
+ SP_EXTEND_RANGE_BEFORE ==
+ pCMS->pSpecialPos->nExtendRange );
+
+ sal_Bool bWidth = pCMS && pCMS->bRealWidth;
+ if( !pCurr->GetLen() && !pCurr->Width() )
+ {
+ if ( pCMS && pCMS->bRealHeight )
+ {
+ pCMS->aRealHeight.X() = 0;
+ pCMS->aRealHeight.Y() = nTmpHeight;
+ }
+ }
+ else
+ {
+ KSHORT nPorHeight = nTmpHeight;
+ KSHORT nPorAscent = nTmpAscent;
+ SwTwips nX = 0;
+ SwTwips nTmpFirst = 0;
+ SwLinePortion *pPor = pCurr->GetFirstPortion();
+ SwBidiPortion* pLastBidiPor = 0;
+ SwTwips nLastBidiPorWidth = 0;
+ SvUShorts* pKanaComp = pCurr->GetpKanaComp();
+ MSHORT nSpaceIdx = 0;
+ MSHORT nKanaIdx = 0;
+ long nSpaceAdd = pCurr->IsSpaceAdd() ? pCurr->GetLLSpaceAdd( 0 ) : 0;
+
+ sal_Bool bNoTxt = sal_True;
+
+ // Zuerst werden alle Portions ohne Len am Zeilenanfang uebersprungen.
+ // Ausnahme bilden die fiesen Spezialportions aus WhichFirstPortion:
+ // Num, ErgoSum, FtnNum, FeldReste
+ // 8477: aber auch die einzige Textportion einer leeren Zeile mit
+ // Right/Center-Adjustment! Also nicht nur pPor->GetExpandPortion() ...
+ while( pPor && !pPor->GetLen() && ! bInsideFirstField )
+ {
+ nX += pPor->Width();
+ if ( pPor->InSpaceGrp() && nSpaceAdd )
+ nX += pPor->CalcSpacing( nSpaceAdd, aInf );
+ if( bNoTxt )
+ nTmpFirst = nX;
+ // 8670: EndPortions zaehlen hier einmal als TxtPortions.
+// if( pPor->InTxtGrp() || pPor->IsBreakPortion() )
+ if( pPor->InTxtGrp() || pPor->IsBreakPortion() || pPor->InTabGrp() )
+ {
+ bNoTxt = sal_False;
+ nTmpFirst = nX;
+ }
+ if( pPor->IsMultiPortion() && ((SwMultiPortion*)pPor)->HasTabulator() )
+ {
+ if ( pCurr->IsSpaceAdd() )
+ {
+ if ( ++nSpaceIdx < pCurr->GetLLSpaceAddCount() )
+ nSpaceAdd = pCurr->GetLLSpaceAdd( nSpaceIdx );
+ else
+ nSpaceAdd = 0;
+ }
+
+ if( pKanaComp && ( nKanaIdx + 1 ) < pKanaComp->Count() )
+ ++nKanaIdx;
+ }
+ if( pPor->InFixMargGrp() )
+ {
+ if( pPor->IsMarginPortion() )
+ bNoTxt = sal_False;
+ else
+ {
+ // fix margin portion => next SpaceAdd, KanaComp value
+ if ( pCurr->IsSpaceAdd() )
+ {
+ if ( ++nSpaceIdx < pCurr->GetLLSpaceAddCount() )
+ nSpaceAdd = pCurr->GetLLSpaceAdd( nSpaceIdx );
+ else
+ nSpaceAdd = 0;
+ }
+
+ if( pKanaComp && ( nKanaIdx + 1 ) < pKanaComp->Count() )
+ ++nKanaIdx;
+ }
+ }
+ pPor = pPor->GetPortion();
+ }
+
+ if( !pPor )
+ {
+ // Es sind nur Spezialportions unterwegs.
+ nX = nTmpFirst;
+ }
+ else
+ {
+ if( !pPor->IsMarginPortion() && !pPor->IsPostItsPortion() &&
+ (!pPor->InFldGrp() || pPor->GetAscent() ) )
+ {
+ nPorHeight = pPor->Height();
+ nPorAscent = pPor->GetAscent();
+ }
+ while( pPor && !pPor->IsBreakPortion() && ( aInf.GetIdx() < nOfst ||
+ ( bWidth && ( pPor->IsKernPortion() || pPor->IsMultiPortion() ) ) ) )
+ {
+ if( !pPor->IsMarginPortion() && !pPor->IsPostItsPortion() &&
+ (!pPor->InFldGrp() || pPor->GetAscent() ) )
+ {
+ nPorHeight = pPor->Height();
+ nPorAscent = pPor->GetAscent();
+ }
+
+ // If we are behind the portion, we add the portion width to
+ // nX. Special case: nOfst = aInf.GetIdx() + pPor->GetLen().
+ // For common portions (including BidiPortions) we want to add
+ // the portion width to nX. For MultiPortions, nExtra = 0,
+ // therefore we go to the 'else' branch and start a recursion.
+ const sal_uInt8 nExtra = pPor->IsMultiPortion() &&
+ ! ((SwMultiPortion*)pPor)->IsBidi() &&
+ ! bWidth ? 0 : 1;
+ if ( aInf.GetIdx() + pPor->GetLen() < nOfst + nExtra )
+ {
+ if ( pPor->InSpaceGrp() && nSpaceAdd )
+ nX += pPor->PrtWidth() +
+ pPor->CalcSpacing( nSpaceAdd, aInf );
+ else
+ {
+ if( pPor->InFixMargGrp() && ! pPor->IsMarginPortion() )
+ {
+ // update to current SpaceAdd, KanaComp values
+ if ( pCurr->IsSpaceAdd() )
+ {
+ if ( ++nSpaceIdx < pCurr->GetLLSpaceAddCount() )
+ nSpaceAdd = pCurr->GetLLSpaceAdd( nSpaceIdx );
+ else
+ nSpaceAdd = 0;
+ }
+
+ if ( pKanaComp &&
+ ( nKanaIdx + 1 ) < pKanaComp->Count()
+ )
+ ++nKanaIdx;
+ }
+ if ( !pPor->IsFlyPortion() || ( pPor->GetPortion() &&
+ !pPor->GetPortion()->IsMarginPortion() ) )
+ nX += pPor->PrtWidth();
+ }
+ if( pPor->IsMultiPortion() )
+ {
+ if ( ((SwMultiPortion*)pPor)->HasTabulator() )
+ {
+ if ( pCurr->IsSpaceAdd() )
+ {
+ if ( ++nSpaceIdx < pCurr->GetLLSpaceAddCount() )
+ nSpaceAdd = pCurr->GetLLSpaceAdd( nSpaceIdx );
+ else
+ nSpaceAdd = 0;
+ }
+
+ if( pKanaComp && ( nKanaIdx + 1 ) < pKanaComp->Count() )
+ ++nKanaIdx;
+ }
+
+ // if we are right behind a BidiPortion, we have to
+ // hold a pointer to the BidiPortion in order to
+ // find the correct cursor position, depending on the
+ // cursor level
+ if ( ((SwMultiPortion*)pPor)->IsBidi() &&
+ aInf.GetIdx() + pPor->GetLen() == nOfst )
+ {
+ pLastBidiPor = (SwBidiPortion*)pPor;
+ nLastBidiPorWidth = pLastBidiPor->Width() +
+ pLastBidiPor->CalcSpacing( nSpaceAdd, aInf );;
+ }
+ }
+
+ aInf.SetIdx( aInf.GetIdx() + pPor->GetLen() );
+ pPor = pPor->GetPortion();
+ }
+ else
+ {
+ if( pPor->IsMultiPortion() )
+ {
+ nTmpAscent = AdjustBaseLine( *pCurr, pPor );
+ GetInfo().SetMulti( sal_True );
+ pOrig->Pos().Y() += nTmpAscent - nPorAscent;
+
+ if( pCMS && pCMS->b2Lines )
+ {
+ sal_Bool bRecursion = sal_True;
+ if ( ! pCMS->p2Lines )
+ {
+ pCMS->p2Lines = new Sw2LinesPos;
+ pCMS->p2Lines->aLine = SwRect(aCharPos, aCharSize);
+ bRecursion = sal_False;
+ }
+
+ if( ((SwMultiPortion*)pPor)->HasRotation() )
+ {
+ if( ((SwMultiPortion*)pPor)->IsRevers() )
+ pCMS->p2Lines->nMultiType = MT_ROT_270;
+ else
+ pCMS->p2Lines->nMultiType = MT_ROT_90;
+ }
+ else if( ((SwMultiPortion*)pPor)->IsDouble() )
+ pCMS->p2Lines->nMultiType = MT_TWOLINE;
+ else if( ((SwMultiPortion*)pPor)->IsBidi() )
+ pCMS->p2Lines->nMultiType = MT_BIDI;
+ else
+ pCMS->p2Lines->nMultiType = MT_RUBY;
+
+ SwTwips nTmpWidth = pPor->Width();
+ if( nSpaceAdd )
+ nTmpWidth += pPor->CalcSpacing(nSpaceAdd, aInf);
+
+ SwRect aRect( Point(aCharPos.X() + nX, pOrig->Top() ),
+ Size( nTmpWidth, pPor->Height() ) );
+
+ if ( ! bRecursion )
+ pCMS->p2Lines->aPortion = aRect;
+ else
+ pCMS->p2Lines->aPortion2 = aRect;
+ }
+
+ // In a multi-portion we use GetCharRect()-function
+ // recursively and must add the x-position
+ // of the multi-portion.
+ xub_StrLen nOldStart = nStart;
+ SwTwips nOldY = nY;
+ sal_uInt8 nOldProp = GetPropFont();
+ nStart = aInf.GetIdx();
+ SwLineLayout* pOldCurr = pCurr;
+ pCurr = &((SwMultiPortion*)pPor)->GetRoot();
+ if( ((SwMultiPortion*)pPor)->IsDouble() )
+ SetPropFont( 50 );
+
+ GETGRID( GetTxtFrm()->FindPageFrm() )
+ const sal_Bool bHasGrid = pGrid && GetInfo().SnapToGrid();
+ const sal_uInt16 nRubyHeight = bHasGrid ?
+ pGrid->GetRubyHeight() : 0;
+
+ if( nStart + pCurr->GetLen() <= nOfst && GetNext() &&
+ ( ! ((SwMultiPortion*)pPor)->IsRuby() ||
+ ((SwMultiPortion*)pPor)->OnTop() ) )
+ {
+ sal_uInt16 nOffset;
+ // in grid mode we may only add the height of the
+ // ruby line if ruby line is on top
+ if ( bHasGrid &&
+ ((SwMultiPortion*)pPor)->IsRuby() &&
+ ((SwMultiPortion*)pPor)->OnTop() )
+ nOffset = nRubyHeight;
+ else
+ nOffset = GetLineHeight();
+
+ pOrig->Pos().Y() += nOffset;
+ Next();
+ }
+
+ sal_Bool bSpaceChg = ((SwMultiPortion*)pPor)->
+ ChgSpaceAdd( pCurr, nSpaceAdd );
+ Point aOldPos = pOrig->Pos();
+
+ // Ok, for ruby portions in grid mode we have to
+ // temporarily set the inner line height to the
+ // outer line height because that value is needed
+ // for the adjustment inside the recursion
+ const sal_uInt16 nOldRubyHeight = pCurr->Height();
+ const sal_uInt16 nOldRubyRealHeight = pCurr->GetRealHeight();
+ const sal_Bool bChgHeight =
+ ((SwMultiPortion*)pPor)->IsRuby() && bHasGrid;
+
+ if ( bChgHeight )
+ {
+ pCurr->Height( pOldCurr->Height() - nRubyHeight );
+ pCurr->SetRealHeight( pOldCurr->GetRealHeight() -
+ nRubyHeight );
+ }
+
+ SwLayoutModeModifier aLayoutModeModifier( *GetInfo().GetOut() );
+ if ( ((SwMultiPortion*)pPor)->IsBidi() )
+ {
+ aLayoutModeModifier.Modify(
+ ((SwBidiPortion*)pPor)->GetLevel() % 2 );
+ }
+
+ _GetCharRect( pOrig, nOfst, pCMS );
+
+ if ( bChgHeight )
+ {
+ pCurr->Height( nOldRubyHeight );
+ pCurr->SetRealHeight( nOldRubyRealHeight );
+ }
+
+ // if we are still in the first row of
+ // our 2 line multiportion, we use the FirstMulti flag
+ // to indicate this
+ if ( ((SwMultiPortion*)pPor)->IsDouble() )
+ {
+ // the recursion may have damaged our font size
+ SetPropFont( nOldProp );
+ if ( !nOldProp )
+ nOldProp = 100;
+ GetInfo().GetFont()->SetProportion( 100 );
+
+ if ( pCurr == &((SwMultiPortion*)pPor)->GetRoot() )
+ {
+ GetInfo().SetFirstMulti( sal_True );
+
+ // we want to treat a double line portion like a
+ // single line portion, if there is no text in
+ // the second line
+ if ( !pCurr->GetNext() ||
+ !pCurr->GetNext()->GetLen() )
+ GetInfo().SetMulti( sal_False );
+ }
+ }
+ // ruby portions are treated like single line portions
+ else if( ((SwMultiPortion*)pPor)->IsRuby() ||
+ ((SwMultiPortion*)pPor)->IsBidi() )
+ GetInfo().SetMulti( sal_False );
+
+ // calculate cursor values
+ if( ((SwMultiPortion*)pPor)->HasRotation() )
+ {
+ GetInfo().SetMulti( sal_False );
+ long nTmp = pOrig->Width();
+ pOrig->Width( pOrig->Height() );
+ pOrig->Height( nTmp );
+ nTmp = pOrig->Left() - aOldPos.X();
+
+ // if we travel into our rotated portion from
+ // a line below, we have to take care, that the
+ // y coord in pOrig is less than line height:
+ if ( nTmp )
+ nTmp--;
+
+ pOrig->Pos().X() = nX + aOldPos.X();
+ if( ((SwMultiPortion*)pPor)->IsRevers() )
+ pOrig->Pos().Y() = aOldPos.Y() + nTmp;
+ else
+ pOrig->Pos().Y() = aOldPos.Y()
+ + pPor->Height() - nTmp - pOrig->Height();
+ if ( pCMS && pCMS->bRealHeight )
+ {
+ pCMS->aRealHeight.Y() = -pCMS->aRealHeight.Y();
+ // result for rotated multi portion is not
+ // correct for reverse (270 degree) portions
+ if( ((SwMultiPortion*)pPor)->IsRevers() )
+ {
+ if ( SvxParaVertAlignItem::AUTOMATIC ==
+ GetLineInfo().GetVertAlign() )
+ // if vertical alignment is set to auto,
+ // we switch from base line alignment
+ // to centered alignment
+ pCMS->aRealHeight.X() =
+ ( pOrig->Width() +
+ pCMS->aRealHeight.Y() ) / 2;
+ else
+ pCMS->aRealHeight.X() =
+ ( pOrig->Width() -
+ pCMS->aRealHeight.X() +
+ pCMS->aRealHeight.Y() );
+ }
+ }
+ }
+ else
+ {
+ pOrig->Pos().Y() += aOldPos.Y();
+ if ( ((SwMultiPortion*)pPor)->IsBidi() )
+ {
+ const SwTwips nPorWidth = pPor->Width() +
+ pPor->CalcSpacing( nSpaceAdd, aInf );
+ const SwTwips nInsideOfst = pOrig->Pos().X();
+ pOrig->Pos().X() = nX + nPorWidth -
+ nInsideOfst - pOrig->Width();
+ }
+ else
+ pOrig->Pos().X() += nX;
+
+ if( ((SwMultiPortion*)pPor)->HasBrackets() )
+ pOrig->Pos().X() +=
+ ((SwDoubleLinePortion*)pPor)->PreWidth();
+ }
+
+ if( bSpaceChg )
+ SwDoubleLinePortion::ResetSpaceAdd( pCurr );
+
+ pCurr = pOldCurr;
+ nStart = nOldStart;
+ nY = nOldY;
+ bPrev = sal_False;
+
+ return;
+ }
+ if ( pPor->PrtWidth() )
+ {
+ xub_StrLen nOldLen = pPor->GetLen();
+ pPor->SetLen( nOfst - aInf.GetIdx() );
+ aInf.SetLen( pPor->GetLen() );
+ if( nX || !pPor->InNumberGrp() )
+ {
+ SeekAndChg( aInf );
+ const sal_Bool bOldOnWin = aInf.OnWin();
+ aInf.SetOnWin( sal_False ); // keine BULLETs!
+ SwTwips nTmp = nX;
+ aInf.SetKanaComp( pKanaComp );
+ aInf.SetKanaIdx( nKanaIdx );
+ nX += pPor->GetTxtSize( aInf ).Width();
+ aInf.SetOnWin( bOldOnWin );
+ if ( pPor->InSpaceGrp() && nSpaceAdd )
+ nX += pPor->CalcSpacing( nSpaceAdd, aInf );
+ if( bWidth )
+ {
+ pPor->SetLen( pPor->GetLen() + 1 );
+ aInf.SetLen( pPor->GetLen() );
+ aInf.SetOnWin( sal_False ); // keine BULLETs!
+ nTmp += pPor->GetTxtSize( aInf ).Width();
+ aInf.SetOnWin( bOldOnWin );
+ if ( pPor->InSpaceGrp() && nSpaceAdd )
+ nTmp += pPor->CalcSpacing(nSpaceAdd, aInf);
+ pOrig->Width( nTmp - nX );
+ }
+ }
+ pPor->SetLen( nOldLen );
+ }
+ bWidth = sal_False;
+ break;
+ }
+ }
+ }
+
+ if( pPor )
+ {
+ OSL_ENSURE( !pPor->InNumberGrp() || bInsideFirstField, "Number surprise" );
+ sal_Bool bEmptyFld = sal_False;
+ if( pPor->InFldGrp() && pPor->GetLen() )
+ {
+ SwFldPortion *pTmp = (SwFldPortion*)pPor;
+ while( pTmp->HasFollow() && !pTmp->GetExp().Len() )
+ {
+ KSHORT nAddX = pTmp->Width();
+ SwLinePortion *pNext = pTmp->GetPortion();
+ while( pNext && !pNext->InFldGrp() )
+ {
+ OSL_ENSURE( !pNext->GetLen(), "Where's my field follow?" );
+ nAddX = nAddX + pNext->Width();
+ pNext = pNext->GetPortion();
+ }
+ if( !pNext )
+ break;
+ pTmp = (SwFldPortion*)pNext;
+ nPorHeight = pTmp->Height();
+ nPorAscent = pTmp->GetAscent();
+ nX += nAddX;
+ bEmptyFld = sal_True;
+ }
+ }
+ // 8513: Felder im Blocksatz, ueberspringen
+ while( pPor && !pPor->GetLen() && ! bInsideFirstField &&
+ ( pPor->IsFlyPortion() || pPor->IsKernPortion() ||
+ pPor->IsBlankPortion() || pPor->InTabGrp() ||
+ ( !bEmptyFld && pPor->InFldGrp() ) ) )
+ {
+ if ( pPor->InSpaceGrp() && nSpaceAdd )
+ nX += pPor->PrtWidth() +
+ pPor->CalcSpacing( nSpaceAdd, aInf );
+ else
+ {
+ if( pPor->InFixMargGrp() && ! pPor->IsMarginPortion() )
+ {
+ if ( pCurr->IsSpaceAdd() )
+ {
+ if ( ++nSpaceIdx < pCurr->GetLLSpaceAddCount() )
+ nSpaceAdd = pCurr->GetLLSpaceAdd( nSpaceIdx );
+ else
+ nSpaceAdd = 0;
+ }
+
+ if( pKanaComp && ( nKanaIdx + 1 ) < pKanaComp->Count() )
+ ++nKanaIdx;
+ }
+ if ( !pPor->IsFlyPortion() || ( pPor->GetPortion() &&
+ !pPor->GetPortion()->IsMarginPortion() ) )
+ nX += pPor->PrtWidth();
+ }
+ if( pPor->IsMultiPortion() &&
+ ((SwMultiPortion*)pPor)->HasTabulator() )
+ {
+ if ( pCurr->IsSpaceAdd() )
+ {
+ if ( ++nSpaceIdx < pCurr->GetLLSpaceAddCount() )
+ nSpaceAdd = pCurr->GetLLSpaceAdd( nSpaceIdx );
+ else
+ nSpaceAdd = 0;
+ }
+
+ if( pKanaComp && ( nKanaIdx + 1 ) < pKanaComp->Count() )
+ ++nKanaIdx;
+ }
+ if( !pPor->IsFlyPortion() )
+ {
+ nPorHeight = pPor->Height();
+ nPorAscent = pPor->GetAscent();
+ }
+ pPor = pPor->GetPortion();
+ }
+
+ if( aInf.GetIdx() == nOfst && pPor && pPor->InHyphGrp() &&
+ pPor->GetPortion() && pPor->GetPortion()->InFixGrp() )
+ {
+ // Alle Sonderportions muessen uebersprungen werden
+ // Beispiel: zu-[FLY]sammen, 'u' == 19, 's' == 20; Right()
+ // Ohne den Ausgleich landen wir vor '-' mit dem
+ // Ausgleich vor 's'.
+ while( pPor && !pPor->GetLen() )
+ {
+ nX += pPor->Width();
+ if( !pPor->IsMarginPortion() )
+ {
+ nPorHeight = pPor->Height();
+ nPorAscent = pPor->GetAscent();
+ }
+ pPor = pPor->GetPortion();
+ }
+ }
+ if( pPor && pCMS )
+ {
+ if( pCMS->bFieldInfo && pPor->InFldGrp() && pPor->Width() )
+ pOrig->Width( pPor->Width() );
+ if( pPor->IsDropPortion() )
+ {
+ nPorAscent = ((SwDropPortion*)pPor)->GetDropHeight();
+ // The drop height is only calculated, if we have more than
+ // one line. Otherwise it is 0.
+ if ( ! nPorAscent)
+ nPorAscent = pPor->Height();
+ nPorHeight = nPorAscent;
+ pOrig->Height( nPorHeight +
+ ((SwDropPortion*)pPor)->GetDropDescent() );
+ if( nTmpHeight < pOrig->Height() )
+ {
+ nTmpAscent = nPorAscent;
+ nTmpHeight = sal_uInt16( pOrig->Height() );
+ }
+ }
+ if( bWidth && pPor->PrtWidth() && pPor->GetLen() &&
+ aInf.GetIdx() == nOfst )
+ {
+ if( !pPor->IsFlyPortion() && pPor->Height() &&
+ pPor->GetAscent() )
+ {
+ nPorHeight = pPor->Height();
+ nPorAscent = pPor->GetAscent();
+ }
+ SwTwips nTmp;
+ if( 2 > pPor->GetLen() )
+ {
+ nTmp = pPor->Width();
+ if ( pPor->InSpaceGrp() && nSpaceAdd )
+ nTmp += pPor->CalcSpacing( nSpaceAdd, aInf );
+ }
+ else
+ {
+ const sal_Bool bOldOnWin = aInf.OnWin();
+ xub_StrLen nOldLen = pPor->GetLen();
+ pPor->SetLen( 1 );
+ aInf.SetLen( pPor->GetLen() );
+ SeekAndChg( aInf );
+ aInf.SetOnWin( sal_False ); // keine BULLETs!
+ aInf.SetKanaComp( pKanaComp );
+ aInf.SetKanaIdx( nKanaIdx );
+ nTmp = pPor->GetTxtSize( aInf ).Width();
+ aInf.SetOnWin( bOldOnWin );
+ if ( pPor->InSpaceGrp() && nSpaceAdd )
+ nTmp += pPor->CalcSpacing( nSpaceAdd, aInf );
+ pPor->SetLen( nOldLen );
+ }
+ pOrig->Width( nTmp );
+ }
+
+ // travel inside field portion?
+ if ( pCMS->pSpecialPos )
+ {
+ // apply attributes to font
+ Seek( nOfst );
+ lcl_GetCharRectInsideField( aInf, *pOrig, *pCMS, *pPor );
+ }
+ }
+ }
+
+ // special case: We are at the beginning of a BidiPortion or
+ // directly behind a BidiPortion
+ if ( pCMS &&
+ ( pLastBidiPor ||
+ ( pPor &&
+ pPor->IsMultiPortion() &&
+ ((SwMultiPortion*)pPor)->IsBidi() ) ) )
+ {
+ // we determine if the cursor has to blink before or behind
+ // the bidi portion
+ if ( pLastBidiPor )
+ {
+ const sal_uInt8 nPortionLevel = pLastBidiPor->GetLevel();
+
+ if ( pCMS->nCursorBidiLevel >= nPortionLevel )
+ {
+ // we came from inside the bidi portion, we want to blink
+ // behind the portion
+ pOrig->Pos().X() -= nLastBidiPorWidth;
+
+ // Again, there is a special case: logically behind
+ // the portion can actually mean that the cursor is inside
+ // the portion. This can happen is the last portion
+ // inside the bidi portion is a nested bidi portion
+ SwLineLayout& rLineLayout =
+ ((SwMultiPortion*)pLastBidiPor)->GetRoot();
+
+ const SwLinePortion *pLast = rLineLayout.FindLastPortion();
+ if ( pLast->IsMultiPortion() )
+ {
+ OSL_ENSURE( ((SwMultiPortion*)pLast)->IsBidi(),
+ "Non-BidiPortion inside BidiPortion" );
+ pOrig->Pos().X() += pLast->Width() +
+ pLast->CalcSpacing( nSpaceAdd, aInf );
+ }
+ }
+ }
+ else
+ {
+ const sal_uInt8 nPortionLevel = ((SwBidiPortion*)pPor)->GetLevel();
+
+ if ( pCMS->nCursorBidiLevel >= nPortionLevel )
+ {
+ // we came from inside the bidi portion, we want to blink
+ // behind the portion
+ pOrig->Pos().X() += pPor->Width() +
+ pPor->CalcSpacing( nSpaceAdd, aInf );
+ }
+ }
+ }
+
+ pOrig->Pos().X() += nX;
+
+ if ( pCMS && pCMS->bRealHeight )
+ {
+ nTmpAscent = AdjustBaseLine( *pCurr, 0, nPorHeight, nPorAscent );
+ if ( nTmpAscent > nPorAscent )
+ pCMS->aRealHeight.X() = nTmpAscent - nPorAscent;
+ else
+ pCMS->aRealHeight.X() = 0;
+ OSL_ENSURE( nPorHeight, "GetCharRect: Missing Portion-Height" );
+ if ( nTmpHeight > nPorHeight )
+ pCMS->aRealHeight.Y() = nPorHeight;
+ else
+ pCMS->aRealHeight.Y() = nTmpHeight;
+ }
+ }
+}
+
+/*************************************************************************
+ * SwTxtCursor::GetCharRect()
+ *************************************************************************/
+
+sal_Bool SwTxtCursor::GetCharRect( SwRect* pOrig, const xub_StrLen nOfst,
+ SwCrsrMoveState* pCMS, const long nMax )
+{
+ CharCrsrToLine(nOfst);
+
+ // Indicates that a position inside a special portion (field, number portion)
+ // is requested.
+ const sal_Bool bSpecialPos = pCMS && pCMS->pSpecialPos;
+ xub_StrLen nFindOfst = nOfst;
+
+ if ( bSpecialPos )
+ {
+ const sal_uInt8 nExtendRange = pCMS->pSpecialPos->nExtendRange;
+
+ OSL_ENSURE( ! pCMS->pSpecialPos->nLineOfst || SP_EXTEND_RANGE_BEFORE != nExtendRange,
+ "LineOffset AND Number Portion?" );
+
+ // portions which are behind the string
+ if ( SP_EXTEND_RANGE_BEHIND == nExtendRange )
+ ++nFindOfst;
+
+ // skip lines for fields which cover more than one line
+ for ( sal_uInt16 i = 0; i < pCMS->pSpecialPos->nLineOfst; i++ )
+ Next();
+ }
+
+ // Adjustierung ggf. nachholen
+ GetAdjusted();
+
+ const Point aCharPos( GetTopLeft() );
+ sal_Bool bRet = sal_True;
+
+ _GetCharRect( pOrig, nFindOfst, pCMS );
+
+ const SwTwips nTmpRight = Right() - 12;
+
+ pOrig->Pos().X() += aCharPos.X();
+ pOrig->Pos().Y() += aCharPos.Y();
+
+ if( pCMS && pCMS->b2Lines && pCMS->p2Lines )
+ {
+ pCMS->p2Lines->aLine.Pos().X() += aCharPos.X();
+ pCMS->p2Lines->aLine.Pos().Y() += aCharPos.Y();
+ pCMS->p2Lines->aPortion.Pos().X() += aCharPos.X();
+ pCMS->p2Lines->aPortion.Pos().Y() += aCharPos.Y();
+ }
+
+ if( pOrig->Left() > nTmpRight )
+ pOrig->Pos().X() = nTmpRight;
+
+ if( nMax )
+ {
+ if( pOrig->Top() + pOrig->Height() > nMax )
+ {
+ if( pOrig->Top() > nMax )
+ pOrig->Top( nMax );
+ pOrig->Height( nMax - pOrig->Top() );
+ }
+ if ( pCMS && pCMS->bRealHeight && pCMS->aRealHeight.Y() >= 0 )
+ {
+ long nTmp = pCMS->aRealHeight.X() + pOrig->Top();
+ if( nTmp >= nMax )
+ {
+ pCMS->aRealHeight.X() = nMax - pOrig->Top();
+ pCMS->aRealHeight.Y() = 0;
+ }
+ else if( nTmp + pCMS->aRealHeight.Y() > nMax )
+ pCMS->aRealHeight.Y() = nMax - nTmp;
+ }
+ }
+ long nOut = pOrig->Right() - GetTxtFrm()->Frm().Right();
+ if( nOut > 0 )
+ {
+ if( GetTxtFrm()->Frm().Width() < GetTxtFrm()->Prt().Left()
+ + GetTxtFrm()->Prt().Width() )
+ nOut += GetTxtFrm()->Frm().Width() - GetTxtFrm()->Prt().Left()
+ - GetTxtFrm()->Prt().Width();
+ if( nOut > 0 )
+ pOrig->Pos().X() -= nOut + 10;
+ }
+ return bRet;
+}
+
+/*************************************************************************
+ * SwTxtCursor::GetCrsrOfst()
+ *
+ * Return: Offset im String
+ *************************************************************************/
+xub_StrLen SwTxtCursor::GetCrsrOfst( SwPosition *pPos, const Point &rPoint,
+ const MSHORT nChgNode, SwCrsrMoveState* pCMS ) const
+{
+ // Adjustierung ggf. nachholen
+ GetAdjusted();
+
+ const XubString &rText = GetInfo().GetTxt();
+ xub_StrLen nOffset = 0;
+
+ // x ist der horizontale Offset innerhalb der Zeile.
+ SwTwips x = rPoint.X();
+ const SwTwips nLeftMargin = GetLineStart();
+ SwTwips nRightMargin = GetLineEnd();
+ if( nRightMargin == nLeftMargin )
+ nRightMargin += 30;
+
+ const sal_Bool bLeftOver = x < nLeftMargin;
+ if( bLeftOver )
+ x = nLeftMargin;
+ const sal_Bool bRightOver = x > nRightMargin;
+ if( bRightOver )
+ x = nRightMargin;
+
+ sal_Bool bRightAllowed = pCMS && ( pCMS->eState == MV_NONE );
+
+ // Bis hierher in Dokumentkoordinaten.
+ x -= nLeftMargin;
+
+ KSHORT nX = KSHORT( x );
+
+ // Wenn es in der Zeile Attributwechsel gibt, den Abschnitt
+ // suchen, in dem nX liegt.
+ SwLinePortion *pPor = pCurr->GetFirstPortion();
+ xub_StrLen nCurrStart = nStart;
+ sal_Bool bHolePortion = sal_False;
+ sal_Bool bLastHyph = sal_False;
+
+ SvUShorts *pKanaComp = pCurr->GetpKanaComp();
+ xub_StrLen nOldIdx = GetInfo().GetIdx();
+ MSHORT nSpaceIdx = 0;
+ MSHORT nKanaIdx = 0;
+ long nSpaceAdd = pCurr->IsSpaceAdd() ? pCurr->GetLLSpaceAdd( 0 ) : 0;
+ short nKanaComp = pKanaComp ? (*pKanaComp)[0] : 0;
+
+ // nWidth ist die Breite der Zeile, oder die Breite des
+ // Abschnitts mit dem Fontwechsel, in dem nX liegt.
+
+ KSHORT nWidth = pPor->Width();
+ if ( pCurr->IsSpaceAdd() || pKanaComp )
+ {
+ if ( pPor->InSpaceGrp() && nSpaceAdd )
+ {
+ ((SwTxtSizeInfo&)GetInfo()).SetIdx( nCurrStart );
+ nWidth = nWidth + sal_uInt16( pPor->CalcSpacing( nSpaceAdd, GetInfo() ) );
+ }
+ if( ( pPor->InFixMargGrp() && ! pPor->IsMarginPortion() ) ||
+ ( pPor->IsMultiPortion() && ((SwMultiPortion*)pPor)->HasTabulator() )
+ )
+ {
+ if ( pCurr->IsSpaceAdd() )
+ {
+ if ( ++nSpaceIdx < pCurr->GetLLSpaceAddCount() )
+ nSpaceAdd = pCurr->GetLLSpaceAdd( nSpaceIdx );
+ else
+ nSpaceAdd = 0;
+ }
+
+ if( pKanaComp )
+ {
+ if ( nKanaIdx + 1 < pKanaComp->Count() )
+ nKanaComp = (*pKanaComp)[++nKanaIdx];
+ else
+ nKanaComp = 0;
+ }
+ }
+ }
+
+ KSHORT nWidth30;
+ if ( pPor->IsPostItsPortion() )
+ nWidth30 = 30 + pPor->GetViewWidth( GetInfo() ) / 2;
+ else
+ nWidth30 = ! nWidth && pPor->GetLen() && pPor->InToxRefOrFldGrp() ?
+ 30 :
+ nWidth;
+
+ while( pPor->GetPortion() && nWidth30 < nX && !pPor->IsBreakPortion() )
+ {
+ nX = nX - nWidth;
+ nCurrStart = nCurrStart + pPor->GetLen();
+ bHolePortion = pPor->IsHolePortion();
+ pPor = pPor->GetPortion();
+ nWidth = pPor->Width();
+ if ( pCurr->IsSpaceAdd() || pKanaComp )
+ {
+ if ( pPor->InSpaceGrp() && nSpaceAdd )
+ {
+ ((SwTxtSizeInfo&)GetInfo()).SetIdx( nCurrStart );
+ nWidth = nWidth + sal_uInt16( pPor->CalcSpacing( nSpaceAdd, GetInfo() ) );
+ }
+
+ if( ( pPor->InFixMargGrp() && ! pPor->IsMarginPortion() ) ||
+ ( pPor->IsMultiPortion() && ((SwMultiPortion*)pPor)->HasTabulator() )
+ )
+ {
+ if ( pCurr->IsSpaceAdd() )
+ {
+ if ( ++nSpaceIdx < pCurr->GetLLSpaceAddCount() )
+ nSpaceAdd = pCurr->GetLLSpaceAdd( nSpaceIdx );
+ else
+ nSpaceAdd = 0;
+ }
+
+ if ( pKanaComp )
+ {
+ if( nKanaIdx + 1 < pKanaComp->Count() )
+ nKanaComp = (*pKanaComp)[++nKanaIdx];
+ else
+ nKanaComp = 0;
+ }
+ }
+ }
+
+ if ( pPor->IsPostItsPortion() )
+ nWidth30 = 30 + pPor->GetViewWidth( GetInfo() ) / 2;
+ else
+ nWidth30 = ! nWidth && pPor->GetLen() && pPor->InToxRefOrFldGrp() ?
+ 30 :
+ nWidth;
+ if( !pPor->IsFlyPortion() && !pPor->IsMarginPortion() )
+ bLastHyph = pPor->InHyphGrp();
+ }
+
+ const sal_Bool bLastPortion = (0 == pPor->GetPortion());
+
+ if( nX==nWidth )
+ {
+ SwLinePortion *pNextPor = pPor->GetPortion();
+ while( pNextPor && pNextPor->InFldGrp() && !pNextPor->Width() )
+ {
+ nCurrStart = nCurrStart + pPor->GetLen();
+ pPor = pNextPor;
+ if( !pPor->IsFlyPortion() && !pPor->IsMarginPortion() )
+ bLastHyph = pPor->InHyphGrp();
+ pNextPor = pPor->GetPortion();
+ }
+ }
+
+ ((SwTxtSizeInfo&)GetInfo()).SetIdx( nOldIdx );
+
+ xub_StrLen nLength = pPor->GetLen();
+
+ sal_Bool bFieldInfo = pCMS && pCMS->bFieldInfo;
+
+ if( bFieldInfo && ( nWidth30 < nX || bRightOver || bLeftOver ||
+ ( pPor->InNumberGrp() && !pPor->IsFtnNumPortion() ) ||
+ ( pPor->IsMarginPortion() && nWidth > nX + 30 ) ) )
+ ((SwCrsrMoveState*)pCMS)->bPosCorr = sal_True;
+
+
+ // #i27615#
+ if (pCMS)
+ {
+ if( pCMS->bInFrontOfLabel)
+ {
+ if (! (2 * nX < nWidth && pPor->InNumberGrp() &&
+ !pPor->IsFtnNumPortion()))
+ pCMS->bInFrontOfLabel = sal_False;
+ }
+ }
+
+ // 7684: Wir sind genau auf der HyphPortion angelangt und muessen dafuer
+ // sorgen, dass wir in dem String landen.
+ // 7993: Wenn die Laenge 0 ist muessen wir raus...
+ if( !nLength )
+ {
+ if( pCMS )
+ {
+ if( pPor->IsFlyPortion() && bFieldInfo )
+ ((SwCrsrMoveState*)pCMS)->bPosCorr = sal_True;
+
+ if (!bRightOver && nX)
+ {
+ if( pPor->IsFtnNumPortion())
+ ((SwCrsrMoveState*)pCMS)->bFtnNoInfo = sal_True;
+ else if (pPor->InNumberGrp() ) // #i23726#
+ {
+ ((SwCrsrMoveState*)pCMS)->nInNumPostionOffset = nX;
+ ((SwCrsrMoveState*)pCMS)->bInNumPortion = sal_True;
+ }
+ }
+ }
+ if( !nCurrStart )
+ return 0;
+
+ // 7849, 7816: auf pPor->GetHyphPortion kann nicht verzichtet werden!
+ if( bHolePortion || ( !bRightAllowed && bLastHyph ) ||
+ ( pPor->IsMarginPortion() && !pPor->GetPortion() &&
+ // 46598: In der letzten Zeile eines zentrierten Absatzes wollen
+ // wir auch mal hinter dem letzten Zeichen landen.
+ nCurrStart < rText.Len() ) )
+ --nCurrStart;
+ else if( pPor->InFldGrp() && ((SwFldPortion*)pPor)->IsFollow()
+ && nWidth > nX )
+ {
+ if( bFieldInfo )
+ --nCurrStart;
+ else
+ {
+ KSHORT nHeight = pPor->Height();
+ if ( !nHeight || nHeight > nWidth )
+ nHeight = nWidth;
+ if( nChgNode && nWidth - nHeight/2 > nX )
+ --nCurrStart;
+ }
+ }
+ return nCurrStart;
+ }
+ if ( 1 == nLength )
+ {
+ if ( nWidth )
+ {
+ // Sonst kommen wir nicht mehr in zeichengeb. Rahmen hinein...
+ if( !( nChgNode && pPos && pPor->IsFlyCntPortion() ) )
+ {
+ if ( pPor->InFldGrp() ||
+ ( pPor->IsMultiPortion() &&
+ ((SwMultiPortion*)pPor)->IsBidi() ) )
+ {
+ KSHORT nHeight = 0;
+ if( !bFieldInfo )
+ {
+ nHeight = pPor->Height();
+ if ( !nHeight || nHeight > nWidth )
+ nHeight = nWidth;
+ }
+
+ if( nWidth - nHeight/2 <= nX &&
+ ( ! pPor->InFldGrp() ||
+ !((SwFldPortion*)pPor)->HasFollow() ) )
+ ++nCurrStart;
+ }
+ else if ( ( !pPor->IsFlyPortion() || ( pPor->GetPortion() &&
+ !pPor->GetPortion()->IsMarginPortion() &&
+ !pPor->GetPortion()->IsHolePortion() ) )
+ && ( nWidth/2 < nX ) &&
+ ( !bFieldInfo ||
+ ( pPor->GetPortion() &&
+ pPor->GetPortion()->IsPostItsPortion() ) )
+ && ( bRightAllowed || !bLastHyph ))
+ ++nCurrStart;
+
+ // if we want to get the position inside the field, we should not return
+ if ( !pCMS || !pCMS->pSpecialPos )
+ return nCurrStart;
+ }
+ }
+ else
+ {
+ if ( pPor->IsPostItsPortion() || pPor->IsBreakPortion() ||
+ pPor->InToxRefGrp() )
+ return nCurrStart;
+ if ( pPor->InFldGrp() )
+ {
+ if( bRightOver && !((SwFldPortion*)pPor)->HasFollow() )
+ ++nCurrStart;
+ return nCurrStart;
+ }
+ }
+ }
+
+ if( bLastPortion && (pCurr->GetNext() || pFrm->GetFollow() ) )
+ --nLength;
+
+ if( nWidth > nX ||
+ ( nWidth == nX && pPor->IsMultiPortion() && ((SwMultiPortion*)pPor)->IsDouble() ) )
+ {
+ if( pPor->IsMultiPortion() )
+ {
+ // In a multi-portion we use GetCrsrOfst()-function recursively
+ SwTwips nTmpY = rPoint.Y() - pCurr->GetAscent() + pPor->GetAscent();
+ // if we are in the first line of a double line portion, we have
+ // to add a value to nTmpY for not staying in this line
+ // we also want to skip the first line, if we are inside ruby
+ if ( ( ((SwTxtSizeInfo*)pInf)->IsMulti() &&
+ ((SwTxtSizeInfo*)pInf)->IsFirstMulti() ) ||
+ ( ((SwMultiPortion*)pPor)->IsRuby() &&
+ ((SwMultiPortion*)pPor)->OnTop() ) )
+ nTmpY += ((SwMultiPortion*)pPor)->Height();
+
+ // Important for cursor traveling in ruby portions:
+ // We have to set nTmpY to 0 in order to stay in the first row
+ // if the phonetic line is the second row
+ if ( ((SwMultiPortion*)pPor)->IsRuby() &&
+ ! ((SwMultiPortion*)pPor)->OnTop() )
+ nTmpY = 0;
+
+ SwTxtCursorSave aSave( (SwTxtCursor*)this, (SwMultiPortion*)pPor,
+ nTmpY, nX, nCurrStart, nSpaceAdd );
+
+ SwLayoutModeModifier aLayoutModeModifier( *GetInfo().GetOut() );
+ if ( ((SwMultiPortion*)pPor)->IsBidi() )
+ {
+ const sal_uInt8 nBidiLevel = ((SwBidiPortion*)pPor)->GetLevel();
+ aLayoutModeModifier.Modify( nBidiLevel % 2 );
+ }
+
+ if( ((SwMultiPortion*)pPor)->HasRotation() )
+ {
+ nTmpY -= nY;
+ if( !((SwMultiPortion*)pPor)->IsRevers() )
+ nTmpY = pPor->Height() - nTmpY;
+ if( nTmpY < 0 )
+ nTmpY = 0;
+ nX = (KSHORT)nTmpY;
+ }
+
+ if( ((SwMultiPortion*)pPor)->HasBrackets() )
+ {
+ sal_uInt16 nPreWidth = ((SwDoubleLinePortion*)pPor)->PreWidth();
+ if ( nX > nPreWidth )
+ nX = nX - nPreWidth;
+ else
+ nX = 0;
+ }
+
+ return GetCrsrOfst( pPos, Point( GetLineStart() + nX, rPoint.Y() ),
+ nChgNode, pCMS );
+ }
+ if( pPor->InTxtGrp() )
+ {
+ sal_uInt8 nOldProp;
+ if( GetPropFont() )
+ {
+ ((SwFont*)GetFnt())->SetProportion( GetPropFont() );
+ nOldProp = GetFnt()->GetPropr();
+ }
+ else
+ nOldProp = 0;
+ {
+ SwTxtSizeInfo aSizeInf( GetInfo(), rText, nCurrStart );
+ ((SwTxtCursor*)this)->SeekAndChg( aSizeInf );
+ SwTxtSlot aDiffTxt( &aSizeInf, ((SwTxtPortion*)pPor), false, false );
+ SwFontSave aSave( aSizeInf, pPor->IsDropPortion() ?
+ ((SwDropPortion*)pPor)->GetFnt() : NULL );
+
+ SwParaPortion* pPara = (SwParaPortion*)GetInfo().GetParaPortion();
+ OSL_ENSURE( pPara, "No paragraph!" );
+
+ SwDrawTextInfo aDrawInf( aSizeInf.GetVsh(),
+ *aSizeInf.GetOut(),
+ &pPara->GetScriptInfo(),
+ aSizeInf.GetTxt(),
+ aSizeInf.GetIdx(),
+ pPor->GetLen() );
+ aDrawInf.SetOfst( nX );
+
+ if ( nSpaceAdd )
+ {
+ xub_StrLen nCharCnt;
+ // --> FME 2005-04-04 #i41860# Thai justified alignemt needs some
+ // additional information:
+ aDrawInf.SetNumberOfBlanks( pPor->InTxtGrp() ?
+ static_cast<const SwTxtPortion*>(pPor)->GetSpaceCnt( aSizeInf, nCharCnt ) :
+ 0 );
+ // <--
+ }
+
+ if ( pPor->InFldGrp() && pCMS && pCMS->pSpecialPos )
+ aDrawInf.SetLen( STRING_LEN ); // SMARTTAGS
+
+ aDrawInf.SetSpace( nSpaceAdd );
+ aDrawInf.SetFont( aSizeInf.GetFont() );
+ aDrawInf.SetFrm( pFrm );
+ aDrawInf.SetSnapToGrid( aSizeInf.SnapToGrid() );
+ aDrawInf.SetPosMatchesBounds( pCMS && pCMS->bPosMatchesBounds );
+
+ if ( SW_CJK == aSizeInf.GetFont()->GetActual() &&
+ pPara->GetScriptInfo().CountCompChg() &&
+ ! pPor->InFldGrp() )
+ aDrawInf.SetKanaComp( nKanaComp );
+
+ nLength = aSizeInf.GetFont()->_GetCrsrOfst( aDrawInf );
+
+ // get position inside field portion?
+ if ( pPor->InFldGrp() && pCMS && pCMS->pSpecialPos )
+ {
+ pCMS->pSpecialPos->nCharOfst = nLength;
+ nLength = 0; // SMARTTAGS
+ }
+
+ // set cursor bidi level
+ if ( pCMS )
+ ((SwCrsrMoveState*)pCMS)->nCursorBidiLevel =
+ aDrawInf.GetCursorBidiLevel();
+
+ if( bFieldInfo && nLength == pPor->GetLen() &&
+ ( ! pPor->GetPortion() ||
+ ! pPor->GetPortion()->IsPostItsPortion() ) )
+ --nLength;
+ }
+ if( nOldProp )
+ ((SwFont*)GetFnt())->SetProportion( nOldProp );
+ }
+ else
+ {
+ if( nChgNode && pPos && pPor->IsFlyCntPortion()
+ && !( (SwFlyCntPortion*)pPor )->IsDraw() )
+ {
+ // JP 24.11.94: liegt die Pos nicht im Fly, dann
+ // darf nicht mit STRING_LEN returnt werden!
+ // (BugId: 9692 + Aenderung in feshview)
+ SwFlyInCntFrm *pTmp = ( (SwFlyCntPortion*)pPor )->GetFlyFrm();
+ sal_Bool bChgNode = 1 < nChgNode;
+ if( !bChgNode )
+ {
+ SwFrm* pLower = pTmp->GetLower();
+ if( pLower && (pLower->IsTxtFrm() || pLower->IsLayoutFrm()) )
+ bChgNode = sal_True;
+ }
+ Point aTmpPoint( rPoint );
+
+ if ( pFrm->IsRightToLeft() )
+ pFrm->SwitchLTRtoRTL( aTmpPoint );
+
+ if ( pFrm->IsVertical() )
+ pFrm->SwitchHorizontalToVertical( aTmpPoint );
+
+ if( bChgNode && pTmp->Frm().IsInside( aTmpPoint ) &&
+ !( pTmp->IsProtected() ) )
+ {
+ nLength = ((SwFlyCntPortion*)pPor)->
+ GetFlyCrsrOfst( nX, aTmpPoint, pPos, pCMS );
+ // Sobald der Frame gewechselt wird, muessen wir aufpassen, dass
+ // unser Font wieder im OutputDevice steht.
+ // vgl. Paint und new SwFlyCntPortion !
+ ((SwTxtSizeInfo*)pInf)->SelectFont();
+
+ // 6776: Das pIter->GetCrsrOfst returnt
+ // aus einer Verschachtelung mit STRING_LEN.
+ return STRING_LEN;
+ }
+ }
+ else
+ nLength = pPor->GetCrsrOfst( nX );
+ }
+ }
+ nOffset = nCurrStart + nLength;
+
+ // 7684: Wir sind vor der HyphPortion angelangt und muessen dafuer
+ // sorgen, dass wir in dem String landen.
+ // Bei Zeilenenden vor FlyFrms muessen ebenso behandelt werden.
+
+ if( nOffset && pPor->GetLen() == nLength && pPor->GetPortion() &&
+ !pPor->GetPortion()->GetLen() && pPor->GetPortion()->InHyphGrp() )
+ --nOffset;
+
+ return nOffset;
+}
+
+/** Looks for text portions which are inside the given rectangle
+
+ For a rectangular text selection every text portions which is inside the given
+ rectangle has to be put into the SwSelectionList as SwPaM
+ From these SwPaM the SwCursors will be created.
+
+ @param rSelList
+ The container for the overlapped text portions
+
+ @param rRect
+ A rectangle in document coordinates, text inside this rectangle has to be
+ selected.
+
+ @return [ true, false ]
+ true if any overlapping text portion has been found and put into list
+ false if no portion overlaps, the list has been unchanged
+*/
+bool SwTxtFrm::FillSelection( SwSelectionList& rSelList, const SwRect& rRect ) const
+{
+ bool bRet = false;
+ // PaintArea() instead Frm() for negative indents
+ SwRect aTmpFrm( PaintArea() );
+ if( !rRect.IsOver( aTmpFrm ) )
+ return false;
+ if( rSelList.checkContext( this ) )
+ {
+ SwRect aRect( aTmpFrm );
+ aRect.Intersection( rRect );
+ // rNode without const to create SwPaMs
+ SwCntntNode &rNode = const_cast<SwCntntNode&>( *GetNode() );
+ SwNodeIndex aIdx( rNode );
+ SwPosition aPosL( aIdx, SwIndex( &rNode, 0 ) );
+ if( IsEmpty() )
+ {
+ SwPaM *pPam = new SwPaM( aPosL, aPosL );
+ rSelList.insertPaM( pPam );
+ }
+ else if( aRect.HasArea() )
+ {
+ xub_StrLen nOld = STRING_LEN;
+ SwPosition aPosR( aPosL );
+ Point aPoint;
+ SwTxtInfo aInf( const_cast<SwTxtFrm*>(this) );
+ SwTxtIter aLine( const_cast<SwTxtFrm*>(this), &aInf );
+ // We have to care for top-to-bottom layout, where right becomes top etc.
+ SWRECTFN( this )
+ SwTwips nTop = (aRect.*fnRect->fnGetTop)();
+ SwTwips nBottom = (aRect.*fnRect->fnGetBottom)();
+ SwTwips nLeft = (aRect.*fnRect->fnGetLeft)();
+ SwTwips nRight = (aRect.*fnRect->fnGetRight)();
+ SwTwips nY = aLine.Y(); // Top position of the first line
+ SwTwips nLastY = nY;
+ while( nY < nTop && aLine.Next() ) // line above rectangle
+ {
+ nLastY = nY;
+ nY = aLine.Y();
+ }
+ bool bLastLine = false;
+ if( nY < nTop && !aLine.GetNext() )
+ {
+ bLastLine = true;
+ nY += aLine.GetLineHeight();
+ }
+ do // check the lines for overlapping
+ {
+ if( nLastY < nTop ) // if the last line was above rectangle
+ nLastY = nTop;
+ if( nY > nBottom ) // if the current line leaves the rectangle
+ nY = nBottom;
+ if( nY >= nLastY ) // gotcha: overlapping
+ {
+ nLastY += nY;
+ nLastY /= 2;
+ if( bVert )
+ {
+ aPoint.X() = nLastY;
+ aPoint.Y() = nLeft;
+ }
+ else
+ {
+ aPoint.X() = nLeft;
+ aPoint.Y() = nLastY;
+ }
+ // Looking for the position of the left border of the rectangle
+ // in this text line
+ SwCrsrMoveState aState( MV_UPDOWN );
+ if( GetCrsrOfst( &aPosL, aPoint, &aState ) )
+ {
+ if( bVert )
+ {
+ aPoint.X() = nLastY;
+ aPoint.Y() = nRight;
+ }
+ else
+ {
+ aPoint.X() = nRight;
+ aPoint.Y() = nLastY;
+ }
+ // If we get a right position and if the left position
+ // is not the same like the left position of the line before
+ // which cound happen e.g. for field portions or fly frames
+ // a SwPaM will be inserted with these positions
+ if( GetCrsrOfst( &aPosR, aPoint, &aState ) &&
+ nOld != aPosL.nContent.GetIndex() )
+ {
+ SwPaM *pPam = new SwPaM( aPosL, aPosR );
+ rSelList.insertPaM( pPam );
+ nOld = aPosL.nContent.GetIndex();
+ }
+ }
+ }
+ if( aLine.Next() )
+ {
+ nLastY = nY;
+ nY = aLine.Y();
+ }
+ else if( !bLastLine )
+ {
+ bLastLine = true;
+ nLastY = nY;
+ nY += aLine.GetLineHeight();
+ }
+ else
+ break;
+ }while( nLastY < nBottom );
+ }
+ }
+ if( GetDrawObjs() )
+ {
+ const SwSortedObjs &rObjs = *GetDrawObjs();
+ for ( sal_uInt16 i = 0; i < rObjs.Count(); ++i )
+ {
+ const SwAnchoredObject* pAnchoredObj = rObjs[i];
+ if( !pAnchoredObj->ISA(SwFlyFrm) )
+ continue;
+ const SwFlyFrm* pFly = static_cast<const SwFlyFrm*>(pAnchoredObj);
+ if( pFly->IsFlyInCntFrm() && pFly->FillSelection( rSelList, rRect ) )
+ bRet = true;
+ }
+ }
+ return bRet;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/text/itrform2.cxx b/sw/source/core/text/itrform2.cxx
new file mode 100644
index 000000000000..a31fd130f38d
--- /dev/null
+++ b/sw/source/core/text/itrform2.cxx
@@ -0,0 +1,2162 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+#include "hintids.hxx"
+
+#include <com/sun/star/i18n/ScriptType.hdl>
+#include <editeng/lspcitem.hxx>
+#include <txtftn.hxx>
+#include <fmtftn.hxx>
+#include <ftninfo.hxx>
+#include <charfmt.hxx>
+#include <editeng/charrotateitem.hxx>
+#include <layfrm.hxx> // GetFrmRstHeight, etc
+#include <viewsh.hxx>
+#include <viewopt.hxx> // SwViewOptions
+#include <paratr.hxx> // SwFmtDrop
+#include <itrform2.hxx>
+#include <porrst.hxx>
+#include <portab.hxx> // pLastTab->
+#include <porfly.hxx> // CalcFlyWidth
+#include <portox.hxx> // WhichTxtPortion
+#include <porref.hxx> // WhichTxtPortion
+#include <porfld.hxx> // SwNumberPortion fuer CalcAscent()
+#include <porftn.hxx> // SwFtnPortion
+#include <porhyph.hxx>
+#include <guess.hxx>
+#include <blink.hxx> // pBlink
+#include <ftnfrm.hxx> // WhichFirstPortion() -> mal Verlagern.
+#include <redlnitr.hxx> // SwRedlineItr
+#include <pagefrm.hxx>
+#include <pagedesc.hxx> // SwPageDesc
+#include <tgrditem.hxx>
+#include <doc.hxx> // SwDoc
+#include <pormulti.hxx> // SwMultiPortion
+#include <unotools/charclass.hxx>
+
+#include <vector>
+
+#if OSL_DEBUG_LEVEL > 1
+#include <ndtxt.hxx> // pSwpHints, Ausgabeoperator
+#endif
+
+using namespace ::com::sun::star;
+
+extern sal_Bool IsUnderlineBreak( const SwLinePortion& rPor, const SwFont& rFnt );
+
+namespace {
+ //! Calculates and sets optimal repaint offset for the current line
+ static long lcl_CalcOptRepaint( SwTxtFormatter &rThis,
+ SwLineLayout &rCurr,
+ const xub_StrLen nOldLineEnd,
+ const std::vector<long> &rFlyStarts );
+ //! Determine if we need to build hidden portions
+ static bool lcl_BuildHiddenPortion( const SwTxtSizeInfo& rInf, xub_StrLen &rPos );
+}
+
+#define MAX_TXTPORLEN 300
+
+inline void ClearFly( SwTxtFormatInfo &rInf )
+{
+ if( rInf.GetFly() )
+ {
+ delete rInf.GetFly();
+ rInf.SetFly(0);
+ }
+}
+
+/*************************************************************************
+ * SwTxtFormatter::CtorInitTxtFormatter()
+ *************************************************************************/
+
+void SwTxtFormatter::CtorInitTxtFormatter( SwTxtFrm *pNewFrm, SwTxtFormatInfo *pNewInf )
+{
+ CtorInitTxtPainter( pNewFrm, pNewInf );
+ pInf = pNewInf;
+ pDropFmt = GetInfo().GetDropFmt();
+ pMulti = NULL;
+
+ bOnceMore = sal_False;
+ bFlyInCntBase = sal_False;
+ bChanges = sal_False;
+ bTruncLines = sal_False;
+ nCntEndHyph = 0;
+ nCntMidHyph = 0;
+ nLeftScanIdx = STRING_LEN;
+ nRightScanIdx = 0;
+ m_nHintEndIndex = 0;
+
+ if( nStart > GetInfo().GetTxt().Len() )
+ {
+ OSL_ENSURE( !this, "+SwTxtFormatter::CTOR: bad offset" );
+ nStart = GetInfo().GetTxt().Len();
+ }
+
+}
+
+/*************************************************************************
+ * SwTxtFormatter::DTOR
+ *************************************************************************/
+
+SwTxtFormatter::~SwTxtFormatter()
+{
+ // Auesserst unwahrscheinlich aber denkbar.
+ // z.B.: Feld spaltet sich auf, Widows schlagen zu
+ if( GetInfo().GetRest() )
+ {
+ delete GetInfo().GetRest();
+ GetInfo().SetRest(0);
+ }
+}
+
+/*************************************************************************
+ * SwTxtFormatter::Insert()
+ *************************************************************************/
+
+void SwTxtFormatter::Insert( SwLineLayout *pLay )
+{
+ // Einfuegen heute mal ausnahmsweise hinter dem aktuellen Element.
+ if ( pCurr )
+ {
+ pLay->SetNext( pCurr->GetNext() );
+ pCurr->SetNext( pLay );
+ }
+ else
+ pCurr = pLay;
+}
+
+/*************************************************************************
+ * SwTxtFormatter::GetFrmRstHeight()
+ *************************************************************************/
+
+KSHORT SwTxtFormatter::GetFrmRstHeight() const
+{
+ // 8725: Uns interessiert die Resthoehe bezogen auf die Seite.
+ // Wenn wir in einer Tabelle stehen, dann ist pFrm->GetUpper() nicht
+ // die Seite. GetFrmRstHeight() wird im Zusammenhang mit den Ftn
+ // gerufen.
+ // Falsch: const SwFrm *pUpper = pFrm->GetUpper();
+ const SwFrm *pPage = (const SwFrm*)pFrm->FindPageFrm();
+ const SwTwips nHeight = pPage->Frm().Top()
+ + pPage->Prt().Top()
+ + pPage->Prt().Height() - Y();
+ if( 0 > nHeight )
+ return pCurr->Height();
+ else
+ return KSHORT( nHeight );
+}
+
+/*************************************************************************
+ * SwTxtFormatter::UnderFlow()
+ *************************************************************************/
+
+SwLinePortion *SwTxtFormatter::UnderFlow( SwTxtFormatInfo &rInf )
+{
+ // Werte sichern und rInf initialisieren.
+ SwLinePortion *pUnderFlow = rInf.GetUnderFlow();
+ if( !pUnderFlow )
+ return 0;
+
+ // Wir formatieren rueckwaerts, d.h. dass Attributwechsel in der
+ // naechsten Zeile durchaus noch einmal drankommen koennen.
+ // Zu beobachten in 8081.sdw, wenn man in der ersten Zeile Text eingibt.
+
+ const xub_StrLen nSoftHyphPos = rInf.GetSoftHyphPos();
+ const xub_StrLen nUnderScorePos = rInf.GetUnderScorePos();
+
+ // 8358, 8359: Flys sichern und auf 0 setzen, sonst GPF
+ // 3983: Nicht ClearFly(rInf) !
+ SwFlyPortion *pFly = rInf.GetFly();
+ rInf.SetFly( 0 );
+
+ FeedInf( rInf );
+ rInf.SetLast( pCurr );
+ // pUnderFlow braucht nicht deletet werden, weil es im folgenden
+ // Truncate() untergehen wird.
+ rInf.SetUnderFlow(0);
+ rInf.SetSoftHyphPos( nSoftHyphPos );
+ rInf.SetUnderScorePos( nUnderScorePos );
+ rInf.SetPaintOfst( GetLeftMargin() );
+
+ // Wir suchen die Portion mit der Unterlaufposition
+ SwLinePortion *pPor = pCurr->GetFirstPortion();
+ if( pPor != pUnderFlow )
+ {
+ // pPrev wird die letzte Portion vor pUnderFlow,
+ // die noch eine echte Breite hat.
+ // Ausnahme: SoftHyphPortions duerfen dabei natuerlich
+ // nicht vergessen werden, obwohl sie keine Breite haben.
+ SwLinePortion *pTmpPrev = pPor;
+ while( pPor && pPor != pUnderFlow )
+ {
+ if( !pPor->IsKernPortion() &&
+ ( pPor->Width() || pPor->IsSoftHyphPortion() ) )
+ {
+ while( pTmpPrev != pPor )
+ {
+ pTmpPrev->Move( rInf );
+ rInf.SetLast( pTmpPrev );
+ pTmpPrev = pTmpPrev->GetPortion();
+ OSL_ENSURE( pTmpPrev, "UnderFlow: Loosing control!" );
+ };
+ }
+ pPor = pPor->GetPortion();
+ }
+ pPor = pTmpPrev;
+ if( pPor && // Flies + Initialen werden nicht beim UnderFlow mitgenommen
+ ( pPor->IsFlyPortion() || pPor->IsDropPortion() ||
+ pPor->IsFlyCntPortion() ) )
+ {
+ pPor->Move( rInf );
+ rInf.SetLast( pPor );
+ rInf.SetStopUnderFlow( sal_True );
+ pPor = pUnderFlow;
+ }
+ }
+
+ // Was? Die Unterlaufsituation ist nicht in der Portion-Kette ?
+ OSL_ENSURE( pPor, "SwTxtFormatter::UnderFlow: overflow but underflow" );
+
+ // OD 2004-05-26 #i29529# - correction: no delete of footnotes
+// if( rInf.IsFtnInside() && pPor && !rInf.IsQuick() )
+// {
+// SwLinePortion *pTmp = pPor->GetPortion();
+// while( pTmp )
+// {
+// if( pTmp->IsFtnPortion() )
+// ((SwFtnPortion*)pTmp)->ClearFtn();
+// pTmp = pTmp->GetPortion();
+// }
+// }
+
+ /*--------------------------------------------------
+ * 9849: Schnellschuss
+ * --------------------------------------------------*/
+ if ( pPor==rInf.GetLast() )
+ {
+ // Hier landen wir, wenn die UnderFlow-ausloesende Portion sich
+ // ueber die ganze Zeile erstreckt, z. B. wenn ein Wort ueber
+ // mehrere Zeilen geht und in der zweiten Zeile in einen Fly
+ // hineinlaeuft!
+ rInf.SetFly( pFly ); // wg. 28300
+ pPor->Truncate();
+ return pPor; // Reicht das?
+ }
+ /*---------------------------------------------------
+ * Ende des Schnellschusses wg. 9849
+ * --------------------------------------------------*/
+
+ // 4656: X + Width == 0 bei SoftHyph > Zeile ?!
+ if( !pPor || !(rInf.X() + pPor->Width()) )
+ {
+ delete pFly;
+ return 0;
+ }
+
+ // Vorbereitungen auf's Format()
+ // Wir muessen die Kette hinter pLast abknipsen, weil
+ // nach dem Format() ein Insert erfolgt.
+ SeekAndChg( rInf );
+
+ // line width is adjusted, so that pPor does not fit to current
+ // line anymore
+ rInf.Width( (sal_uInt16)(rInf.X() + (pPor->Width() ? pPor->Width() - 1 : 0)) );
+ rInf.SetLen( pPor->GetLen() );
+ rInf.SetFull( sal_False );
+ if( pFly )
+ {
+ // Aus folgendem Grund muss die FlyPortion neu berechnet werden:
+ // Wenn durch einen grossen Font in der Mitte der Zeile die Grundlinie
+ // abgesenkt wird und dadurch eine Ueberlappung mit eine Fly entsteht,
+ // so hat die FlyPortion eine falsche Groesse/Fixsize.
+ rInf.SetFly( pFly );
+ CalcFlyWidth( rInf );
+ }
+ rInf.GetLast()->SetPortion(0);
+
+ // Eine Ausnahme bildet das SwLineLayout, dass sich beim
+ // ersten Portionwechsel aufspaltet. Hier nun der umgekehrte Weg:
+ if( rInf.GetLast() == pCurr )
+ {
+ if( pPor->InTxtGrp() && !pPor->InExpGrp() )
+ {
+ MSHORT nOldWhich = pCurr->GetWhichPor();
+ *(SwLinePortion*)pCurr = *pPor;
+ pCurr->SetPortion( pPor->GetPortion() );
+ pCurr->SetWhichPor( nOldWhich );
+ pPor->SetPortion( 0 );
+ delete pPor;
+ pPor = pCurr;
+ }
+ }
+ pPor->Truncate();
+ SwLinePortion *const pRest( rInf.GetRest() );
+ if (pRest && pRest->InFldGrp() &&
+ static_cast<SwFldPortion*>(pRest)->IsNoLength())
+ {
+ // HACK: decrement again, so we pick up the suffix in next line!
+ --m_nHintEndIndex;
+ }
+ delete pRest;
+ rInf.SetRest(0);
+ return pPor;
+}
+
+/*************************************************************************
+ * SwTxtFormatter::InsertPortion()
+ *************************************************************************/
+
+void SwTxtFormatter::InsertPortion( SwTxtFormatInfo &rInf,
+ SwLinePortion *pPor ) const
+{
+ // Die neue Portion wird eingefuegt,
+ // bei dem LineLayout ist allerdings alles anders...
+ if( pPor == pCurr )
+ {
+ if ( pCurr->GetPortion() )
+ {
+ pPor = pCurr->GetPortion();
+ }
+
+ // --> OD 2010-07-07 #i112181#
+ rInf.SetOtherThanFtnInside( rInf.IsOtherThanFtnInside() || !pPor->IsFtnPortion() );
+ // <--
+ }
+ else
+ {
+ SwLinePortion *pLast = rInf.GetLast();
+ if( pLast->GetPortion() )
+ {
+ while( pLast->GetPortion() )
+ pLast = pLast->GetPortion();
+ rInf.SetLast( pLast );
+ }
+ pLast->Insert( pPor );
+
+ rInf.SetOtherThanFtnInside( rInf.IsOtherThanFtnInside() || !pPor->IsFtnPortion() );
+
+ // Maxima anpassen:
+ if( pCurr->Height() < pPor->Height() )
+ pCurr->Height( pPor->Height() );
+ if( pCurr->GetAscent() < pPor->GetAscent() )
+ pCurr->SetAscent( pPor->GetAscent() );
+ }
+
+ // manchmal werden ganze Ketten erzeugt (z.B. durch Hyphenate)
+ rInf.SetLast( pPor );
+ while( pPor )
+ {
+ pPor->Move( rInf );
+ rInf.SetLast( pPor );
+ pPor = pPor->GetPortion();
+ }
+}
+
+/*************************************************************************
+ * SwTxtFormatter::BuildPortion()
+ *************************************************************************/
+
+void SwTxtFormatter::BuildPortions( SwTxtFormatInfo &rInf )
+{
+ OSL_ENSURE( rInf.GetTxt().Len() < STRING_LEN,
+ "SwTxtFormatter::BuildPortions: bad text length in info" );
+
+ rInf.ChkNoHyph( CntEndHyph(), CntMidHyph() );
+
+ // Erst NewTxtPortion() entscheidet, ob pCurr in pPor landet.
+ // Wir muessen in jedem Fall dafuer sorgen, dass der Font eingestellt
+ // wird. In CalcAscent geschieht dies automatisch.
+ rInf.SetLast( pCurr );
+ rInf.ForcedLeftMargin( 0 );
+
+ OSL_ENSURE( pCurr->FindLastPortion() == pCurr, "pLast supposed to equal pCurr" );
+
+ if( !pCurr->GetAscent() && !pCurr->Height() )
+ CalcAscent( rInf, pCurr );
+
+ SeekAndChg( rInf );
+
+ // In CalcFlyWidth wird Width() verkuerzt, wenn eine FlyPortion vorliegt.
+ OSL_ENSURE( !rInf.X() || pMulti, "SwTxtFormatter::BuildPortion X=0?" );
+ CalcFlyWidth( rInf );
+ SwFlyPortion *pFly = rInf.GetFly();
+ if( pFly )
+ {
+ if ( 0 < pFly->Fix() )
+ ClearFly( rInf );
+ else
+ rInf.SetFull(sal_True);
+ }
+
+ SwLinePortion *pPor = NewPortion( rInf );
+
+ // Asian grid stuff
+ GETGRID( pFrm->FindPageFrm() )
+ const sal_Bool bHasGrid = pGrid && rInf.SnapToGrid() &&
+ GRID_LINES_CHARS == pGrid->GetGridType();
+
+ const SwDoc *pDoc = rInf.GetTxtFrm()->GetNode()->GetDoc();
+ const sal_uInt16 nGridWidth = bHasGrid ?
+ GETGRIDWIDTH(pGrid,pDoc) : 0; //for textgrid refactor
+
+ // used for grid mode only:
+ // the pointer is stored, because after formatting of non-asian text,
+ // the width of the kerning portion has to be adjusted
+ SwKernPortion* pGridKernPortion = 0;
+
+ sal_Bool bFull;
+ SwTwips nUnderLineStart = 0;
+ rInf.Y( Y() );
+
+ while( pPor && !rInf.IsStop() )
+ {
+ OSL_ENSURE( rInf.GetLen() < STRING_LEN &&
+ rInf.GetIdx() <= rInf.GetTxt().Len(),
+ "SwTxtFormatter::BuildPortions: bad length in info" );
+
+ // We have to check the script for fields in order to set the
+ // correct nActual value for the font.
+ if( pPor->InFldGrp() )
+ ((SwFldPortion*)pPor)->CheckScript( rInf );
+
+ if( ! bHasGrid && rInf.HasScriptSpace() &&
+ rInf.GetLast() && rInf.GetLast()->InTxtGrp() &&
+ rInf.GetLast()->Width() && !rInf.GetLast()->InNumberGrp() )
+ {
+ sal_uInt8 nNxtActual = rInf.GetFont()->GetActual();
+ sal_uInt8 nLstActual = nNxtActual;
+ sal_uInt16 nLstHeight = (sal_uInt16)rInf.GetFont()->GetHeight();
+ sal_Bool bAllowBefore = sal_False;
+ sal_Bool bAllowBehind = sal_False;
+ const CharClass& rCC = GetAppCharClass();
+
+ // are there any punctuation characters on both sides
+ // of the kerning portion?
+ if ( pPor->InFldGrp() )
+ {
+ XubString aAltTxt;
+ if ( ((SwFldPortion*)pPor)->GetExpTxt( rInf, aAltTxt ) &&
+ aAltTxt.Len() )
+ {
+ bAllowBehind = rCC.isLetterNumeric( aAltTxt, 0 );
+
+ const SwFont* pTmpFnt = ((SwFldPortion*)pPor)->GetFont();
+ if ( pTmpFnt )
+ nNxtActual = pTmpFnt->GetActual();
+ }
+ }
+ else
+ bAllowBehind = rCC.isLetterNumeric( rInf.GetTxt(), rInf.GetIdx() );
+
+ const SwLinePortion* pLast = rInf.GetLast();
+ if ( bAllowBehind && pLast )
+ {
+ if ( pLast->InFldGrp() )
+ {
+ XubString aAltTxt;
+ if ( ((SwFldPortion*)pLast)->GetExpTxt( rInf, aAltTxt ) &&
+ aAltTxt.Len() )
+ {
+ bAllowBefore = rCC.isLetterNumeric( aAltTxt, aAltTxt.Len() - 1 );
+
+ const SwFont* pTmpFnt = ((SwFldPortion*)pLast)->GetFont();
+ if ( pTmpFnt )
+ {
+ nLstActual = pTmpFnt->GetActual();
+ nLstHeight = (sal_uInt16)pTmpFnt->GetHeight();
+ }
+ }
+ }
+ else if ( rInf.GetIdx() )
+ {
+ bAllowBefore = rCC.isLetterNumeric( rInf.GetTxt(), rInf.GetIdx() - 1 );
+ // Note: ScriptType returns values in [1,4]
+ if ( bAllowBefore )
+ nLstActual = pScriptInfo->ScriptType( rInf.GetIdx() - 1 ) - 1;
+ }
+
+ nLstHeight /= 5;
+ // does the kerning portion still fit into the line?
+ if( bAllowBefore && ( nLstActual != nNxtActual ) &&
+ nLstHeight && rInf.X() + nLstHeight <= rInf.Width() )
+ {
+ SwKernPortion* pKrn =
+ new SwKernPortion( *rInf.GetLast(), nLstHeight,
+ pLast->InFldGrp() && pPor->InFldGrp() );
+ rInf.GetLast()->SetPortion( NULL );
+ InsertPortion( rInf, pKrn );
+ }
+ }
+ }
+ else if ( bHasGrid && ! pGridKernPortion && ! pMulti )
+ {
+ // insert a grid kerning portion
+ if ( ! pGridKernPortion )
+ pGridKernPortion = pPor->IsKernPortion() ?
+ (SwKernPortion*)pPor :
+ new SwKernPortion( *pCurr );
+
+ // if we have a new GridKernPortion, we initially calculate
+ // its size so that its ends on the grid
+ const SwPageFrm* pPageFrm = pFrm->FindPageFrm();
+ const SwLayoutFrm* pBody = pPageFrm->FindBodyCont();
+ SWRECTFN( pPageFrm )
+
+ const long nGridOrigin = pBody ?
+ (pBody->*fnRect->fnGetPrtLeft)() :
+ (pPageFrm->*fnRect->fnGetPrtLeft)();
+
+ SwTwips nStartX = rInf.X() + GetLeftMargin();
+ if ( bVert )
+ {
+ Point aPoint( nStartX, 0 );
+ pFrm->SwitchHorizontalToVertical( aPoint );
+ nStartX = aPoint.Y();
+ }
+
+ const SwTwips nOfst = nStartX - nGridOrigin;
+ if ( nOfst )
+ {
+ const sal_uLong i = ( nOfst > 0 ) ?
+ ( ( nOfst - 1 ) / nGridWidth + 1 ) :
+ 0;
+ const SwTwips nKernWidth = i * nGridWidth - nOfst;
+ const SwTwips nRestWidth = rInf.Width() - rInf.X();
+
+ if ( nKernWidth <= nRestWidth )
+ pGridKernPortion->Width( (sal_uInt16)nKernWidth );
+ }
+
+ if ( pGridKernPortion != pPor )
+ InsertPortion( rInf, pGridKernPortion );
+ }
+
+ // the multi-portion has it's own format function
+ if( pPor->IsMultiPortion() && ( !pMulti || pMulti->IsBidi() ) )
+ bFull = BuildMultiPortion( rInf, *((SwMultiPortion*)pPor) );
+ else
+ bFull = pPor->Format( rInf );
+
+ if( rInf.IsRuby() && !rInf.GetRest() )
+ bFull = sal_True;
+
+ // if we are underlined, we store the beginning of this underlined
+ // segment for repaint optimization
+ if ( UNDERLINE_NONE != pFnt->GetUnderline() && ! nUnderLineStart )
+ nUnderLineStart = GetLeftMargin() + rInf.X();
+
+ if ( pPor->IsFlyPortion() )
+ pCurr->SetFly( sal_True );
+ // some special cases, where we have to take care for the repaint
+ // offset:
+ // 1. Underlined portions due to special underline feature
+ // 2. Right Tab
+ // 3. BidiPortions
+ // 4. other Multiportions
+ // 5. DropCaps
+ // 6. Grid Mode
+ else if ( ( ! rInf.GetPaintOfst() || nUnderLineStart < rInf.GetPaintOfst() ) &&
+ // 1. Underlined portions
+ nUnderLineStart &&
+ // reformat is at end of an underlined portion and next portion
+ // is not underlined
+ ( ( rInf.GetReformatStart() == rInf.GetIdx() &&
+ UNDERLINE_NONE == pFnt->GetUnderline()
+ ) ||
+ // reformat is inside portion and portion is underlined
+ ( rInf.GetReformatStart() >= rInf.GetIdx() &&
+ rInf.GetReformatStart() <= rInf.GetIdx() + pPor->GetLen() &&
+ UNDERLINE_NONE != pFnt->GetUnderline() ) ) )
+ rInf.SetPaintOfst( nUnderLineStart );
+ else if ( ! rInf.GetPaintOfst() &&
+ // 2. Right Tab
+ ( ( pPor->InTabGrp() && !pPor->IsTabLeftPortion() ) ||
+ // 3. BidiPortions
+ ( pPor->IsMultiPortion() && ((SwMultiPortion*)pPor)->IsBidi() ) ||
+ // 4. Multi Portion and 5. Drop Caps
+ ( ( pPor->IsDropPortion() || pPor->IsMultiPortion() ) &&
+ rInf.GetReformatStart() >= rInf.GetIdx() &&
+ rInf.GetReformatStart() <= rInf.GetIdx() + pPor->GetLen() )
+ // 6. Grid Mode
+ || ( bHasGrid && SW_CJK != pFnt->GetActual() )
+ )
+ )
+ // we store the beginning of the critical portion as our
+ // paint offset
+ rInf.SetPaintOfst( GetLeftMargin() + rInf.X() );
+
+ // under one of these conditions we are allowed to delete the
+ // start of the underline portion
+ if ( IsUnderlineBreak( *pPor, *pFnt ) )
+ nUnderLineStart = 0;
+
+ if( pPor->IsFlyCntPortion() || ( pPor->IsMultiPortion() &&
+ ((SwMultiPortion*)pPor)->HasFlyInCntnt() ) )
+ SetFlyInCntBase();
+ // 5964: bUnderFlow muss zurueckgesetzt werden, sonst wird beim
+ // naechsten Softhyphen wieder umgebrochen!
+ if ( !bFull )
+ {
+ rInf.ClrUnderFlow();
+ if( ! bHasGrid && rInf.HasScriptSpace() && pPor->InTxtGrp() &&
+ pPor->GetLen() && !pPor->InFldGrp() )
+ {
+ // The distance between two different scripts is set
+ // to 20% of the fontheight.
+ xub_StrLen nTmp = rInf.GetIdx() + pPor->GetLen();
+ if( nTmp == pScriptInfo->NextScriptChg( nTmp - 1 ) &&
+ nTmp != rInf.GetTxt().Len() )
+ {
+ sal_uInt16 nDist = (sal_uInt16)(rInf.GetFont()->GetHeight()/5);
+
+ if( nDist )
+ {
+ // we do not want a kerning portion if any end
+ // would be a punctuation character
+ const CharClass& rCC = GetAppCharClass();
+ if ( rCC.isLetterNumeric( rInf.GetTxt(), nTmp - 1 ) &&
+ rCC.isLetterNumeric( rInf.GetTxt(), nTmp ) )
+ {
+ // does the kerning portion still fit into the line?
+ if ( rInf.X() + pPor->Width() + nDist <= rInf.Width() )
+ new SwKernPortion( *pPor, nDist );
+ else
+ bFull = sal_True;
+ }
+ }
+ }
+ }
+ }
+
+ if ( bHasGrid && pPor != pGridKernPortion && ! pMulti )
+ {
+ xub_StrLen nTmp = rInf.GetIdx() + pPor->GetLen();
+ const SwTwips nRestWidth = rInf.Width() - rInf.X() - pPor->Width();
+
+ const sal_uInt8 nCurrScript = pFnt->GetActual(); // pScriptInfo->ScriptType( rInf.GetIdx() );
+ const sal_uInt8 nNextScript = nTmp >= rInf.GetTxt().Len() ?
+ SW_CJK :
+ SwScriptInfo::WhichFont( nTmp, 0, pScriptInfo );
+
+ // snap non-asian text to grid if next portion is ASIAN or
+ // there are no more portions in this line
+ // be careful when handling an underflow event: the gridkernportion
+ // could have been deleted
+ if ( nRestWidth > 0 && SW_CJK != nCurrScript &&
+ ! rInf.IsUnderFlow() && ( bFull || SW_CJK == nNextScript ) )
+ {
+ OSL_ENSURE( pGridKernPortion, "No GridKernPortion available" );
+
+ // calculate size
+ SwLinePortion* pTmpPor = pGridKernPortion->GetPortion();
+ sal_uInt16 nSumWidth = pPor->Width();
+ while ( pTmpPor )
+ {
+ nSumWidth = nSumWidth + pTmpPor->Width();
+ pTmpPor = pTmpPor->GetPortion();
+ }
+
+ const sal_uInt16 i = nSumWidth ?
+ ( nSumWidth - 1 ) / nGridWidth + 1 :
+ 0;
+ const SwTwips nTmpWidth = i * nGridWidth;
+ const SwTwips nKernWidth = Min( (SwTwips)(nTmpWidth - nSumWidth),
+ nRestWidth );
+ const sal_uInt16 nKernWidth_1 = (sal_uInt16)(nKernWidth / 2);
+
+ OSL_ENSURE( nKernWidth <= nRestWidth,
+ "Not enough space left for adjusting non-asian text in grid mode" );
+
+ pGridKernPortion->Width( pGridKernPortion->Width() + nKernWidth_1 );
+ rInf.X( rInf.X() + nKernWidth_1 );
+
+ if ( ! bFull )
+ new SwKernPortion( *pPor, (short)(nKernWidth - nKernWidth_1),
+ sal_False, sal_True );
+
+ pGridKernPortion = 0;
+ }
+ else if ( pPor->IsMultiPortion() || pPor->InFixMargGrp() ||
+ pPor->IsFlyCntPortion() || pPor->InNumberGrp() ||
+ pPor->InFldGrp() || nCurrScript != nNextScript )
+ // next portion should snap to grid
+ pGridKernPortion = 0;
+ }
+
+ rInf.SetFull( bFull );
+
+ // Restportions von mehrzeiligen Feldern haben bisher noch
+ // nicht den richtigen Ascent.
+ if ( !pPor->GetLen() && !pPor->IsFlyPortion()
+ && !pPor->IsGrfNumPortion() && ! pPor->InNumberGrp()
+ && !pPor->IsMultiPortion() )
+ CalcAscent( rInf, pPor );
+
+ InsertPortion( rInf, pPor );
+ pPor = NewPortion( rInf );
+ }
+
+ if( !rInf.IsStop() )
+ {
+ // der letzte rechte, zentrierte, dezimale Tab
+ SwTabPortion *pLastTab = rInf.GetLastTab();
+ if( pLastTab )
+ pLastTab->FormatEOL( rInf );
+ else if( rInf.GetLast() && rInf.LastKernPortion() )
+ rInf.GetLast()->FormatEOL( rInf );
+ }
+ if( pCurr->GetPortion() && pCurr->GetPortion()->InNumberGrp()
+ && ((SwNumberPortion*)pCurr->GetPortion())->IsHide() )
+ rInf.SetNumDone( sal_False );
+
+ // 3260, 3860: Fly auf jeden Fall loeschen!
+ ClearFly( rInf );
+}
+
+/*************************************************************************
+ * SwTxtFormatter::CalcAdjustLine()
+ *************************************************************************/
+
+void SwTxtFormatter::CalcAdjustLine( SwLineLayout *pCurrent )
+{
+ if( SVX_ADJUST_LEFT != GetAdjust() && !pMulti)
+ {
+ pCurrent->SetFormatAdj(sal_True);
+ if( IsFlyInCntBase() )
+ {
+ CalcAdjLine( pCurrent );
+ // 23348: z.B. bei zentrierten Flys muessen wir den RefPoint
+ // auf jeden Fall umsetzen, deshalb bAllWays = sal_True
+ UpdatePos( pCurrent, GetTopLeft(), GetStart(), sal_True );
+ }
+ }
+}
+
+/*************************************************************************
+ * SwTxtFormatter::CalcAscent()
+ *************************************************************************/
+
+void SwTxtFormatter::CalcAscent( SwTxtFormatInfo &rInf, SwLinePortion *pPor )
+{
+ if ( pPor->InFldGrp() && ((SwFldPortion*)pPor)->GetFont() )
+ {
+ // Numerierungen + InterNetFlds koennen einen eigenen Font beinhalten,
+ // dann ist ihre Groesse unabhaengig von harten Attributierungen.
+ SwFont* pFldFnt = ((SwFldPortion*)pPor)->pFnt;
+ SwFontSave aSave( rInf, pFldFnt );
+ ((SwFldPortion*)pPor)->Height( pFldFnt->GetHeight( rInf.GetVsh(), *rInf.GetOut() ) );
+ ((SwFldPortion*)pPor)->SetAscent( pFldFnt->GetAscent( rInf.GetVsh(), *rInf.GetOut() ) );
+ }
+ // --> OD 2008-06-05 #i89179#
+ // tab portion representing the list tab of a list label gets the
+ // same height and ascent as the corresponding number portion
+ else if ( pPor->InTabGrp() && pPor->GetLen() == 0 &&
+ rInf.GetLast() && rInf.GetLast()->InNumberGrp() &&
+ static_cast<const SwNumberPortion*>(rInf.GetLast())->HasFont() )
+ {
+ const SwLinePortion* pLast = rInf.GetLast();
+ pPor->Height( pLast->Height() );
+ pPor->SetAscent( pLast->GetAscent() );
+ }
+ // <--
+ else
+ {
+ const SwLinePortion *pLast = rInf.GetLast();
+ sal_Bool bChg;
+
+ // Fallunterscheidung: in leeren Zeilen werden die Attribute
+ // per SeekStart angeschaltet.
+ const sal_Bool bFirstPor = rInf.GetLineStart() == rInf.GetIdx();
+ if ( pPor->IsQuoVadisPortion() )
+ bChg = SeekStartAndChg( rInf, sal_True );
+ else
+ {
+ if( bFirstPor )
+ {
+ if( rInf.GetTxt().Len() )
+ {
+ if ( pPor->GetLen() || !rInf.GetIdx()
+ || ( pCurr != pLast && !pLast->IsFlyPortion() )
+ || !pCurr->IsRest() ) // statt !rInf.GetRest()
+ bChg = SeekAndChg( rInf );
+ else
+ bChg = SeekAndChgBefore( rInf );
+ }
+ else if ( pMulti )
+ // do not open attributes starting at 0 in empty multi
+ // portions (rotated numbering followed by a footnote
+ // can cause trouble, because the footnote attribute
+ // starts at 0, but if we open it, the attribute handler
+ // cannot handle it.
+ bChg = sal_False;
+ else
+ bChg = SeekStartAndChg( rInf );
+ }
+ else
+ bChg = SeekAndChg( rInf );
+ }
+ if( bChg || bFirstPor || !pPor->GetAscent()
+ || !rInf.GetLast()->InTxtGrp() )
+ {
+ pPor->SetAscent( rInf.GetAscent() );
+ pPor->Height( rInf.GetTxtHeight() );
+ }
+ else
+ {
+ pPor->Height( pLast->Height() );
+ pPor->SetAscent( pLast->GetAscent() );
+ }
+ }
+}
+
+/*************************************************************************
+ * class SwMetaPortion
+ *************************************************************************/
+
+class SwMetaPortion : public SwTxtPortion
+{
+public:
+ inline SwMetaPortion() { SetWhichPor( POR_META ); }
+ virtual void Paint( const SwTxtPaintInfo &rInf ) const;
+// OUTPUT_OPERATOR
+};
+
+//CLASSIO( SwMetaPortion )
+
+/*************************************************************************
+ * virtual SwMetaPortion::Paint()
+ *************************************************************************/
+
+void SwMetaPortion::Paint( const SwTxtPaintInfo &rInf ) const
+{
+ if ( Width() )
+ {
+ rInf.DrawViewOpt( *this, POR_META );
+ SwTxtPortion::Paint( rInf );
+ }
+}
+
+
+/*************************************************************************
+ * SwTxtFormatter::WhichTxtPor()
+ *************************************************************************/
+
+SwTxtPortion *SwTxtFormatter::WhichTxtPor( SwTxtFormatInfo &rInf ) const
+{
+ SwTxtPortion *pPor = 0;
+ if( GetFnt()->IsTox() )
+ pPor = new SwToxPortion;
+ else
+ {
+ if( GetFnt()->IsRef() )
+ pPor = new SwRefPortion;
+ else if (GetFnt()->IsMeta())
+ {
+ pPor = new SwMetaPortion;
+ }
+ else
+ {
+ // Erst zum Schluss !
+ // Wenn pCurr keine Breite hat, kann sie trotzdem schon Inhalt haben,
+ // z.B. bei nicht darstellbaren Zeichen.
+ if( rInf.GetLen() > 0 )
+ {
+ if( rInf.GetTxt().GetChar(rInf.GetIdx())==CH_TXT_ATR_FIELDSTART )
+ pPor = new SwFieldMarkPortion();
+ else if( rInf.GetTxt().GetChar(rInf.GetIdx())==CH_TXT_ATR_FIELDEND )
+ pPor = new SwFieldMarkPortion();
+ else if( rInf.GetTxt().GetChar(rInf.GetIdx())==CH_TXT_ATR_FORMELEMENT )
+ pPor = new SwFieldFormPortion();
+ }
+ if( !pPor )
+ {
+ if( !rInf.X() && !pCurr->GetPortion() && !pCurr->GetLen() && !GetFnt()->IsURL() )
+ pPor = pCurr;
+ else
+ {
+ pPor = new SwTxtPortion;
+ if( GetFnt()->IsURL() )
+ pPor->SetWhichPor( POR_URL );
+ }
+ }
+ }
+ }
+ return pPor;
+}
+
+/*************************************************************************
+ * SwTxtFormatter::NewTxtPortion()
+ *************************************************************************/
+// Die Laenge wird ermittelt, folgende Portion-Grenzen sind definiert:
+// 1) Tabs
+// 2) Linebreaks
+// 3) CH_TXTATR_BREAKWORD / CH_TXTATR_INWORD
+// 4) naechster Attributwechsel
+
+SwTxtPortion *SwTxtFormatter::NewTxtPortion( SwTxtFormatInfo &rInf )
+{
+ // Wenn wir am Zeilenbeginn stehen, nehmen wir pCurr
+ // Wenn pCurr nicht von SwTxtPortion abgeleitet ist,
+ // muessen wir duplizieren ...
+ Seek( rInf.GetIdx() );
+ SwTxtPortion *pPor = WhichTxtPor( rInf );
+
+ // until next attribute change:
+ const xub_StrLen nNextAttr = GetNextAttr();
+ xub_StrLen nNextChg = Min( nNextAttr, rInf.GetTxt().Len() );
+
+ // end of script type:
+ const xub_StrLen nNextScript = pScriptInfo->NextScriptChg( rInf.GetIdx() );
+ nNextChg = Min( nNextChg, nNextScript );
+
+ // end of direction:
+ const xub_StrLen nNextDir = pScriptInfo->NextDirChg( rInf.GetIdx() );
+ nNextChg = Min( nNextChg, nNextDir );
+
+ // 7515, 7516, 3470, 6441 : Turbo-Boost
+ // Es wird unterstellt, dass die Buchstaben eines Fonts nicht
+ // groesser als doppelt so breit wie hoch sind.
+ // 7659: Ganz verrueckt: man muss sich auf den Ascent beziehen.
+ // Falle: GetSize() enthaelt die Wunschhoehe, die reale Hoehe
+ // ergibt sich erst im CalcAscent!
+ // 7697: Das Verhaeltnis ist noch krasser: ein Blank im Times
+ // New Roman besitzt einen Ascent von 182, eine Hoehe von 200
+ // und eine Breite von 53! Daraus folgt, dass eine Zeile mit
+ // vielen Blanks falsch eingeschaetzt wird. Wir erhoehen von
+ // Faktor 2 auf 8 (wg. negativen Kernings).
+
+ pPor->SetLen(1);
+ CalcAscent( rInf, pPor );
+
+ const SwFont* pTmpFnt = rInf.GetFont();
+ KSHORT nExpect = Min( KSHORT( ((Font *)pTmpFnt)->GetSize().Height() ),
+ KSHORT( pPor->GetAscent() ) ) / 8;
+ if ( !nExpect )
+ nExpect = 1;
+ nExpect = (sal_uInt16)(rInf.GetIdx() + ((rInf.Width() - rInf.X()) / nExpect));
+ if( nExpect > rInf.GetIdx() && nNextChg > nExpect )
+ nNextChg = Min( nExpect, rInf.GetTxt().Len() );
+
+ // we keep an invariant during method calls:
+ // there are no portion ending characters like hard spaces
+ // or tabs in [ nLeftScanIdx, nRightScanIdx ]
+ if ( nLeftScanIdx <= rInf.GetIdx() && rInf.GetIdx() <= nRightScanIdx )
+ {
+ if ( nNextChg > nRightScanIdx )
+ nNextChg = nRightScanIdx =
+ rInf.ScanPortionEnd( nRightScanIdx, nNextChg );
+ }
+ else
+ {
+ nLeftScanIdx = rInf.GetIdx();
+ nNextChg = nRightScanIdx =
+ rInf.ScanPortionEnd( rInf.GetIdx(), nNextChg );
+ }
+
+ pPor->SetLen( nNextChg - rInf.GetIdx() );
+ rInf.SetLen( pPor->GetLen() );
+ return pPor;
+}
+
+
+/*************************************************************************
+ * SwTxtFormatter::WhichFirstPortion()
+ *************************************************************************/
+
+SwLinePortion *SwTxtFormatter::WhichFirstPortion(SwTxtFormatInfo &rInf)
+{
+ SwLinePortion *pPor = 0;
+
+ if( rInf.GetRest() )
+ {
+ // 5010: Tabs und Felder
+ if( '\0' != rInf.GetHookChar() )
+ return 0;
+
+ pPor = rInf.GetRest();
+ if( pPor->IsErgoSumPortion() )
+ rInf.SetErgoDone(sal_True);
+ else
+ if( pPor->IsFtnNumPortion() )
+ rInf.SetFtnDone(sal_True);
+ else
+ if( pPor->InNumberGrp() )
+ rInf.SetNumDone(sal_True);
+ if( pPor )
+ {
+ rInf.SetRest(0);
+ pCurr->SetRest( sal_True );
+ return pPor;
+ }
+ }
+
+ // ???? und ????: im Follow duerfen wir schon stehen,
+ // entscheidend ist, ob pFrm->GetOfst() == 0 ist!
+ if( rInf.GetIdx() )
+ {
+ // Nun koennen auch FtnPortions und ErgoSumPortions
+ // verlaengert werden.
+
+ // 1) Die ErgoSumTexte
+ if( !rInf.IsErgoDone() )
+ {
+ if( pFrm->IsInFtn() && !pFrm->GetIndPrev() )
+ pPor = (SwLinePortion*)NewErgoSumPortion( rInf );
+ rInf.SetErgoDone( sal_True );
+ }
+
+ // 2) Arrow portions
+ if( !pPor && !rInf.IsArrowDone() )
+ {
+ if( pFrm->GetOfst() && !pFrm->IsFollow() &&
+ rInf.GetIdx() == pFrm->GetOfst() )
+ pPor = new SwArrowPortion( *pCurr );
+ rInf.SetArrowDone( sal_True );
+ }
+
+ // 3) Kerning portions at beginning of line in grid mode
+ if ( ! pPor && ! pCurr->GetPortion() )
+ {
+ GETGRID( GetTxtFrm()->FindPageFrm() )
+ if ( pGrid )
+ pPor = new SwKernPortion( *pCurr );
+ }
+
+ // 4) Die Zeilenreste (mehrzeilige Felder)
+ if( !pPor )
+ {
+ pPor = rInf.GetRest();
+ // 6922: Nur bei pPor natuerlich.
+ if( pPor )
+ {
+ pCurr->SetRest( sal_True );
+ rInf.SetRest(0);
+ }
+ }
+ }
+ else
+ {
+ // 5) Die Fussnotenzahlen
+ if( !rInf.IsFtnDone() )
+ {
+ OSL_ENSURE( ( ! rInf.IsMulti() && ! pMulti ) || pMulti->HasRotation(),
+ "Rotated number portion trouble" );
+
+ sal_Bool bFtnNum = pFrm->IsFtnNumFrm();
+ rInf.GetParaPortion()->SetFtnNum( bFtnNum );
+ if( bFtnNum )
+ pPor = (SwLinePortion*)NewFtnNumPortion( rInf );
+ rInf.SetFtnDone( sal_True );
+ }
+
+ // 6) Die ErgoSumTexte gibt es natuerlich auch im TextMaster,
+ // entscheidend ist, ob der SwFtnFrm ein Follow ist.
+ if( !rInf.IsErgoDone() && !pPor && ! rInf.IsMulti() )
+ {
+ if( pFrm->IsInFtn() && !pFrm->GetIndPrev() )
+ pPor = (SwLinePortion*)NewErgoSumPortion( rInf );
+ rInf.SetErgoDone( sal_True );
+ }
+
+ // 7) Die Numerierungen
+ if( !rInf.IsNumDone() && !pPor )
+ {
+ OSL_ENSURE( ( ! rInf.IsMulti() && ! pMulti ) || pMulti->HasRotation(),
+ "Rotated number portion trouble" );
+
+ // Wenn wir im Follow stehen, dann natuerlich nicht.
+ if( GetTxtFrm()->GetTxtNode()->GetNumRule() )
+ pPor = (SwLinePortion*)NewNumberPortion( rInf );
+ rInf.SetNumDone( sal_True );
+ }
+ // 8) Die DropCaps
+ if( !pPor && GetDropFmt() && ! rInf.IsMulti() )
+ pPor = (SwLinePortion*)NewDropPortion( rInf );
+
+ // 9) Kerning portions at beginning of line in grid mode
+ if ( !pPor && !pCurr->GetPortion() )
+ {
+ GETGRID( GetTxtFrm()->FindPageFrm() )
+ if ( pGrid )
+ pPor = new SwKernPortion( *pCurr );
+ }
+ }
+
+ // 10) Decimal tab portion at the beginning of each line in table cells
+ if ( !pPor && !pCurr->GetPortion() &&
+ GetTxtFrm()->IsInTab() &&
+ GetTxtFrm()->GetTxtNode()->getIDocumentSettingAccess()->get(IDocumentSettingAccess::TAB_COMPAT) )
+ {
+ pPor = NewTabPortion( rInf, true );
+ }
+
+ // 11) suffix of meta-field
+ if (!pPor)
+ {
+ pPor = TryNewNoLengthPortion(rInf);
+ }
+
+ return pPor;
+}
+
+sal_Bool lcl_OldFieldRest( const SwLineLayout* pCurr )
+{
+ if( !pCurr->GetNext() )
+ return sal_False;
+ const SwLinePortion *pPor = pCurr->GetNext()->GetPortion();
+ sal_Bool bRet = sal_False;
+ while( pPor && !bRet )
+ {
+ bRet = (pPor->InFldGrp() && ((SwFldPortion*)pPor)->IsFollow()) ||
+ (pPor->IsMultiPortion() && ((SwMultiPortion*)pPor)->IsFollowFld());
+ if( !pPor->GetLen() )
+ break;
+ pPor = pPor->GetPortion();
+ }
+ return bRet;
+}
+
+/*************************************************************************
+ * SwTxtFormatter::NewPortion()
+ *************************************************************************/
+
+/* NewPortion stellt rInf.nLen ein.
+ * Eine SwTxtPortion wird begrenzt durch ein tab, break, txtatr,
+ * attrwechsel.
+ * Drei Faelle koennen eintreten:
+ * 1) Die Zeile ist voll und der Umbruch wurde nicht emuliert
+ * -> return 0;
+ * 2) Die Zeile ist voll und es wurde ein Umbruch emuliert
+ * -> Breite neu einstellen und return new FlyPortion
+ * 3) Es muss eine neue Portion gebaut werden.
+ * -> CalcFlyWidth emuliert ggf. die Breite und return Portion
+ */
+
+SwLinePortion *SwTxtFormatter::NewPortion( SwTxtFormatInfo &rInf )
+{
+ // Underflow hat Vorrang
+ rInf.SetStopUnderFlow( sal_False );
+ if( rInf.GetUnderFlow() )
+ {
+ OSL_ENSURE( rInf.IsFull(), "SwTxtFormatter::NewPortion: underflow but not full" );
+ return UnderFlow( rInf );
+ }
+
+ // Wenn die Zeile voll ist, koennten noch Flys oder
+ // UnderFlow-LinePortions warten ...
+ if( rInf.IsFull() )
+ {
+ // ????: LineBreaks und Flys (bug05.sdw)
+ // 8450: IsDummy()
+ if( rInf.IsNewLine() && (!rInf.GetFly() || !pCurr->IsDummy()) )
+ return 0;
+
+ // Wenn der Text an den Fly gestossen ist, oder wenn
+ // der Fly als erstes drankommt, weil er ueber dem linken
+ // Rand haengt, wird GetFly() returnt.
+ // Wenn IsFull() und kein GetFly() vorhanden ist, gibt's
+ // naturgemaesz eine 0.
+ if( rInf.GetFly() )
+ {
+ if( rInf.GetLast()->IsBreakPortion() )
+ {
+ delete rInf.GetFly();
+ rInf.SetFly( 0 );
+ }
+
+ return rInf.GetFly();
+ }
+ // Ein fieser Sonderfall: ein Rahmen ohne Umlauf kreuzt den
+ // Ftn-Bereich. Wir muessen die Ftn-Portion als Zeilenrest
+ // bekanntgeben, damit SwTxtFrm::Format nicht abbricht
+ // (die Textmasse wurde ja durchformatiert).
+ if( rInf.GetRest() )
+ rInf.SetNewLine( sal_True );
+ else
+ {
+ // Wenn die naechste Zeile mit einem Rest eines Feldes beginnt,
+ // jetzt aber kein Rest mehr anliegt,
+ // muss sie auf jeden Fall neu formatiert werden!
+ if( lcl_OldFieldRest( GetCurr() ) )
+ rInf.SetNewLine( sal_True );
+ else
+ {
+ SwLinePortion *pFirst = WhichFirstPortion( rInf );
+ if( pFirst )
+ {
+ rInf.SetNewLine( sal_True );
+ if( pFirst->InNumberGrp() )
+ rInf.SetNumDone( sal_False) ;
+ delete pFirst;
+ }
+ }
+ }
+
+ return 0;
+ }
+
+ SwLinePortion *pPor = WhichFirstPortion( rInf );
+
+ // Check for Hidden Portion:
+ if ( !pPor )
+ {
+ xub_StrLen nEnd = rInf.GetIdx();
+ if ( ::lcl_BuildHiddenPortion( rInf, nEnd ) )
+ pPor = new SwHiddenTextPortion( nEnd - rInf.GetIdx() );
+ }
+
+ if( !pPor )
+ {
+ if( ( !pMulti || pMulti->IsBidi() ) &&
+ // --> FME 2005-02-14 #i42734#
+ // No multi portion if there is a hook character waiting:
+ ( !rInf.GetRest() || '\0' == rInf.GetHookChar() ) )
+ // <--
+ {
+ // We open a multiportion part, if we enter a multi-line part
+ // of the paragraph.
+ xub_StrLen nEnd = rInf.GetIdx();
+ SwMultiCreator* pCreate = rInf.GetMultiCreator( nEnd, pMulti );
+ if( pCreate )
+ {
+ SwMultiPortion* pTmp = NULL;
+
+ if ( SW_MC_BIDI == pCreate->nId )
+ pTmp = new SwBidiPortion( nEnd, pCreate->nLevel );
+ else if ( SW_MC_RUBY == pCreate->nId )
+ {
+ Seek( rInf.GetIdx() );
+ sal_Bool bRubyTop;
+ sal_Bool* pRubyPos = 0;
+
+ if ( rInf.SnapToGrid() )
+ {
+ GETGRID( GetTxtFrm()->FindPageFrm() )
+ if ( pGrid )
+ {
+ bRubyTop = ! pGrid->GetRubyTextBelow();
+ pRubyPos = &bRubyTop;
+ }
+ }
+
+ pTmp = new SwRubyPortion( *pCreate, *rInf.GetFont(),
+ *GetTxtFrm()->GetTxtNode()->getIDocumentSettingAccess(),
+ nEnd, 0, pRubyPos );
+ }
+ else if( SW_MC_ROTATE == pCreate->nId )
+ pTmp = new SwRotatedPortion( *pCreate, nEnd,
+ GetTxtFrm()->IsRightToLeft() );
+ else
+ pTmp = new SwDoubleLinePortion( *pCreate, nEnd );
+
+ delete pCreate;
+ CalcFlyWidth( rInf );
+
+ return pTmp;
+ }
+ }
+ // 5010: Tabs und Felder
+ xub_Unicode cChar = rInf.GetHookChar();
+
+ if( cChar )
+ {
+ /* Wir holen uns nocheinmal cChar, um sicherzustellen, dass das
+ * Tab jetzt wirklich ansteht und nicht auf die naechste Zeile
+ * gewandert ist ( so geschehen hinter Rahmen ).
+ * Wenn allerdings eine FldPortion im Rest wartet, muessen wir
+ * das cChar natuerlich aus dem Feldinhalt holen, z.B. bei
+ * DezimalTabs und Feldern (22615)
+ */
+ if( !rInf.GetRest() || !rInf.GetRest()->InFldGrp() )
+ cChar = rInf.GetChar( rInf.GetIdx() );
+ rInf.ClearHookChar();
+ }
+ else
+ {
+ if( rInf.GetIdx() >= rInf.GetTxt().Len() )
+ {
+ rInf.SetFull(sal_True);
+ CalcFlyWidth( rInf );
+ return pPor;
+ }
+ cChar = rInf.GetChar( rInf.GetIdx() );
+ }
+
+ switch( cChar )
+ {
+ case CH_TAB:
+ pPor = NewTabPortion( rInf, false ); break;
+
+ case CH_BREAK:
+ pPor = new SwBreakPortion( *rInf.GetLast() ); break;
+
+ case CHAR_SOFTHYPHEN: // soft hyphen
+ pPor = new SwSoftHyphPortion; break;
+
+ case CHAR_HARDBLANK: // no-break space
+ pPor = new SwBlankPortion( ' ' ); break;
+
+ case CHAR_HARDHYPHEN: // non-breaking hyphen
+ pPor = new SwBlankPortion( '-' ); break;
+
+ case CHAR_ZWSP: // zero width space
+ case CHAR_ZWNBSP : // word joiner
+// case CHAR_RLM : // right to left mark
+// case CHAR_LRM : // left to right mark
+ pPor = new SwControlCharPortion( cChar ); break;
+
+ case CH_TXTATR_BREAKWORD:
+ case CH_TXTATR_INWORD:
+ if( rInf.HasHint( rInf.GetIdx() ) )
+ {
+ pPor = NewExtraPortion( rInf );
+ break;
+ }
+ // No break
+ default :
+ {
+ SwTabPortion* pLastTabPortion = rInf.GetLastTab();
+ if ( pLastTabPortion && cChar == rInf.GetTabDecimal() )
+ {
+ // --> FME 2005-12-19 #127428# Abandon dec. tab position if line is full:
+ // We have a decimal tab portion in the line and the next character has to be
+ // aligned at the tab stop position. We store the width from the beginning of
+ // the tab stop portion up to the portion containint the decimal separator:
+ if ( GetTxtFrm()->GetTxtNode()->getIDocumentSettingAccess()->get(IDocumentSettingAccess::TAB_COMPAT) /*rInf.GetVsh()->IsTabCompat();*/ &&
+ POR_TABDECIMAL == pLastTabPortion->GetWhichPor() )
+ {
+ OSL_ENSURE( rInf.X() >= pLastTabPortion->Fix(), "Decimal tab stop position cannot be calculated" );
+ const sal_uInt16 nWidthOfPortionsUpToDecimalPosition = (sal_uInt16)(rInf.X() - pLastTabPortion->Fix() );
+ static_cast<SwTabDecimalPortion*>(pLastTabPortion)->SetWidthOfPortionsUpToDecimalPosition( nWidthOfPortionsUpToDecimalPosition );
+ rInf.SetTabDecimal( 0 );
+ }
+ // <--
+ else
+ rInf.SetFull( rInf.GetLastTab()->Format( rInf ) );
+ }
+
+ if( rInf.GetRest() )
+ {
+ if( rInf.IsFull() )
+ {
+ rInf.SetNewLine(sal_True);
+ return 0;
+ }
+ pPor = rInf.GetRest();
+ rInf.SetRest(0);
+ }
+ else
+ {
+ if( rInf.IsFull() )
+ return 0;
+ pPor = NewTxtPortion( rInf );
+ }
+ break;
+ }
+ }
+
+ // Wenn eine Portion erzeugt wird, obwohl eine RestPortion ansteht,
+ // dann haben wir es mit einem Feld zu tun, das sich aufgesplittet
+ // hat, weil z.B. ein Tab enthalten ist.
+ if( pPor && rInf.GetRest() )
+ pPor->SetLen( 0 );
+
+ // robust:
+ if( !pPor || rInf.IsStop() )
+ {
+ delete pPor;
+ return 0;
+ }
+ }
+
+ // Special portions containing numbers (footnote anchor, footnote number,
+ // numbering) can be contained in a rotated portion, if the user
+ // choose a rotated character attribute.
+ if ( pPor && ! pMulti )
+ {
+ if ( pPor->IsFtnPortion() )
+ {
+ const SwTxtFtn* pTxtFtn = ((SwFtnPortion*)pPor)->GetTxtFtn();
+
+ if ( pTxtFtn )
+ {
+ SwFmtFtn& rFtn = (SwFmtFtn&)pTxtFtn->GetFtn();
+ const SwDoc *pDoc = rInf.GetTxtFrm()->GetNode()->GetDoc();
+ const SwEndNoteInfo* pInfo;
+ if( rFtn.IsEndNote() )
+ pInfo = &pDoc->GetEndNoteInfo();
+ else
+ pInfo = &pDoc->GetFtnInfo();
+ const SwAttrSet& rSet = pInfo->GetAnchorCharFmt((SwDoc&)*pDoc)->GetAttrSet();
+
+ const SfxPoolItem* pItem;
+ sal_uInt16 nDir = 0;
+ if( SFX_ITEM_SET == rSet.GetItemState( RES_CHRATR_ROTATE,
+ sal_True, &pItem ))
+ nDir = ((SvxCharRotateItem*)pItem)->GetValue();
+
+ if ( 0 != nDir )
+ {
+ delete pPor;
+ pPor = new SwRotatedPortion( rInf.GetIdx() + 1, 900 == nDir ?
+ DIR_BOTTOM2TOP :
+ DIR_TOP2BOTTOM );
+ }
+ }
+ }
+ else if ( pPor->InNumberGrp() )
+ {
+ const SwFont* pNumFnt = ((SwFldPortion*)pPor)->GetFont();
+
+ if ( pNumFnt )
+ {
+ sal_uInt16 nDir = pNumFnt->GetOrientation( rInf.GetTxtFrm()->IsVertical() );
+ if ( 0 != nDir )
+ {
+ delete pPor;
+ pPor = new SwRotatedPortion( 0, 900 == nDir ?
+ DIR_BOTTOM2TOP :
+ DIR_TOP2BOTTOM );
+
+ rInf.SetNumDone( sal_False );
+ rInf.SetFtnDone( sal_False );
+ }
+ }
+ }
+ }
+
+ // Der Font wird im Outputdevice eingestellt,
+ // der Ascent und die Hoehe werden berechnet.
+ if( !pPor->GetAscent() && !pPor->Height() )
+ CalcAscent( rInf, pPor );
+ rInf.SetLen( pPor->GetLen() );
+
+ // In CalcFlyWidth wird Width() verkuerzt, wenn eine FlyPortion vorliegt.
+ CalcFlyWidth( rInf );
+
+ // Man darf nicht vergessen, dass pCurr als GetLast() vernuenftige
+ // Werte bereithalten muss:
+ if( !pCurr->Height() )
+ {
+ OSL_ENSURE( pCurr->Height(), "SwTxtFormatter::NewPortion: limbo dance" );
+ pCurr->Height( pPor->Height() );
+ pCurr->SetAscent( pPor->GetAscent() );
+ }
+
+ OSL_ENSURE( !pPor || pPor->Height(),
+ "SwTxtFormatter::NewPortion: something went wrong");
+ if( pPor->IsPostItsPortion() && rInf.X() >= rInf.Width() && rInf.GetFly() )
+ {
+ delete pPor;
+ pPor = rInf.GetFly();
+ }
+ return pPor;
+}
+
+/*************************************************************************
+ * SwTxtFormatter::FormatLine()
+ *************************************************************************/
+
+xub_StrLen SwTxtFormatter::FormatLine( const xub_StrLen nStartPos )
+{
+ OSL_ENSURE( ! pFrm->IsVertical() || pFrm->IsSwapped(),
+ "SwTxtFormatter::FormatLine( nStartPos ) with unswapped frame" );
+
+ // For the formatting routines, we set pOut to the reference device.
+ SwHookOut aHook( GetInfo() );
+ if( GetInfo().GetLen() < GetInfo().GetTxt().Len() )
+ GetInfo().SetLen( GetInfo().GetTxt().Len() );
+
+ sal_Bool bBuild = sal_True;
+ SetFlyInCntBase( sal_False );
+ GetInfo().SetLineHeight( 0 );
+ GetInfo().SetLineNettoHeight( 0 );
+
+ // Recycling muss bei geaenderter Zeilenhoehe unterdrueckt werden
+ // und auch bei geaendertem Ascent (Absenken der Grundlinie).
+ const KSHORT nOldHeight = pCurr->Height();
+ const KSHORT nOldAscent = pCurr->GetAscent();
+
+ pCurr->SetEndHyph( sal_False );
+ pCurr->SetMidHyph( sal_False );
+
+ // fly positioning can make it necessary format a line several times
+ // for this, we have to keep a copy of our rest portion
+ SwLinePortion* pFld = GetInfo().GetRest();
+ SwFldPortion* pSaveFld = 0;
+
+ if ( pFld && pFld->InFldGrp() && !pFld->IsFtnPortion() )
+ pSaveFld = new SwFldPortion( *((SwFldPortion*)pFld) );
+
+ // for an optimal repaint rectangle, we want to compare fly portions
+ // before and after the BuildPortions call
+ const sal_Bool bOptimizeRepaint = AllowRepaintOpt();
+ const xub_StrLen nOldLineEnd = nStartPos + pCurr->GetLen();
+ std::vector<long> flyStarts;
+
+ // these are the conditions for a fly position comparison
+ if ( bOptimizeRepaint && pCurr->IsFly() )
+ {
+ SwLinePortion* pPor = pCurr->GetFirstPortion();
+ long nPOfst = 0;
+ while ( pPor )
+ {
+ if ( pPor->IsFlyPortion() )
+ // insert start value of fly portion
+ flyStarts.push_back( nPOfst );
+
+ nPOfst += pPor->Width();
+ pPor = pPor->GetPortion();
+ }
+ }
+
+ // Hier folgt bald die Unterlaufpruefung.
+ while( bBuild )
+ {
+ GetInfo().SetFtnInside( sal_False );
+ GetInfo().SetOtherThanFtnInside( sal_False );
+
+ // These values must not be reset by FormatReset();
+ sal_Bool bOldNumDone = GetInfo().IsNumDone();
+ sal_Bool bOldArrowDone = GetInfo().IsArrowDone();
+ sal_Bool bOldErgoDone = GetInfo().IsErgoDone();
+
+ // besides other things, this sets the repaint offset to 0
+ FormatReset( GetInfo() );
+
+ GetInfo().SetNumDone( bOldNumDone );
+ GetInfo().SetArrowDone( bOldArrowDone );
+ GetInfo().SetErgoDone( bOldErgoDone );
+
+ // build new portions for this line
+ BuildPortions( GetInfo() );
+
+ if( GetInfo().IsStop() )
+ {
+ pCurr->SetLen( 0 );
+ pCurr->Height( GetFrmRstHeight() + 1 );
+ pCurr->SetRealHeight( GetFrmRstHeight() + 1 );
+ pCurr->Width(0);
+ pCurr->Truncate();
+ return nStartPos;
+ }
+ else if( GetInfo().IsDropInit() )
+ {
+ DropInit();
+ GetInfo().SetDropInit( sal_False );
+ }
+
+ pCurr->CalcLine( *this, GetInfo() );
+ CalcRealHeight( GetInfo().IsNewLine() );
+
+ if ( IsFlyInCntBase() && !IsQuick() )
+ {
+ KSHORT nTmpAscent, nTmpHeight;
+ CalcAscentAndHeight( nTmpAscent, nTmpHeight );
+ AlignFlyInCntBase( Y() + long( nTmpAscent ) );
+ pCurr->CalcLine( *this, GetInfo() );
+ CalcRealHeight();
+ }
+
+ // bBuild entscheidet, ob noch eine Ehrenrunde gedreht wird
+ if ( pCurr->GetRealHeight() <= GetInfo().GetLineHeight() )
+ {
+ pCurr->SetRealHeight( GetInfo().GetLineHeight() );
+ bBuild = sal_False;
+ }
+ else
+ {
+ bBuild = ( GetInfo().GetTxtFly()->IsOn() && ChkFlyUnderflow(GetInfo()) )
+ || GetInfo().CheckFtnPortion(pCurr);
+ if( bBuild )
+ {
+ GetInfo().SetNumDone( bOldNumDone );
+ GetInfo().ResetMaxWidthDiff();
+
+ // delete old rest
+ if ( GetInfo().GetRest() )
+ {
+ delete GetInfo().GetRest();
+ GetInfo().SetRest( 0 );
+ }
+
+ // set original rest portion
+ if ( pSaveFld )
+ GetInfo().SetRest( new SwFldPortion( *pSaveFld ) );
+
+ pCurr->SetLen( 0 );
+ pCurr->Width(0);
+ pCurr->Truncate();
+ }
+ }
+ }
+
+ // calculate optimal repaint rectangle
+ if ( bOptimizeRepaint )
+ {
+ GetInfo().SetPaintOfst( ::lcl_CalcOptRepaint( *this, *pCurr, nOldLineEnd, flyStarts ) );
+ flyStarts.clear();
+ }
+ else
+ // Special case: We do not allow an optimitation of the repaint
+ // area, but during formatting the repaint offset is set to indicate
+ // a maximum value for the offset. This value has to be reset:
+ GetInfo().SetPaintOfst( 0 );
+
+ // This corrects the start of the reformat range if something has
+ // moved to the next line. Otherwise IsFirstReformat in AllowRepaintOpt
+ // will give us a wrong result if we have to reformat another line
+ GetInfo().GetParaPortion()->GetReformat()->LeftMove( GetInfo().GetIdx() );
+
+ // delete master copy of rest portion
+ if ( pSaveFld )
+ delete pSaveFld;
+
+ xub_StrLen nNewStart = nStartPos + pCurr->GetLen();
+
+ // adjust text if kana compression is enabled
+ if ( GetInfo().CompressLine() )
+ {
+ SwTwips nRepaintOfst = CalcKanaAdj( pCurr );
+
+ // adjust repaint offset
+ if ( nRepaintOfst < GetInfo().GetPaintOfst() )
+ GetInfo().SetPaintOfst( nRepaintOfst );
+ }
+
+ CalcAdjustLine( pCurr );
+
+ if( nOldHeight != pCurr->Height() || nOldAscent != pCurr->GetAscent() )
+ {
+ SetFlyInCntBase();
+ GetInfo().SetPaintOfst( 0 ); //geaenderte Zeilenhoehe => kein Recycling
+ // alle weiteren Zeilen muessen gepaintet und, wenn Flys im Spiel sind
+ // auch formatiert werden.
+ GetInfo().SetShift( sal_True );
+ }
+
+ if ( IsFlyInCntBase() && !IsQuick() )
+ UpdatePos( pCurr, GetTopLeft(), GetStart() );
+
+ return nNewStart;
+}
+
+/*************************************************************************
+ * SwTxtFormatter::RecalcRealHeight()
+ *************************************************************************/
+
+void SwTxtFormatter::RecalcRealHeight()
+{
+ sal_Bool bMore = sal_True;
+ while(bMore)
+ {
+ CalcRealHeight();
+ bMore = Next() != 0;
+ }
+}
+
+/*************************************************************************
+ * SwTxtFormatter::CalcRealHeight()
+ *************************************************************************/
+
+void SwTxtFormatter::CalcRealHeight( sal_Bool bNewLine )
+{
+ KSHORT nLineHeight = pCurr->Height();
+ pCurr->SetClipping( sal_False );
+
+ GETGRID( pFrm->FindPageFrm() )
+ if ( pGrid && GetInfo().SnapToGrid() )
+ {
+ const sal_uInt16 nGridWidth = pGrid->GetBaseHeight();
+ const sal_uInt16 nRubyHeight = pGrid->GetRubyHeight();
+ const sal_Bool bRubyTop = ! pGrid->GetRubyTextBelow();
+
+ nLineHeight = nGridWidth + nRubyHeight;
+ sal_uInt16 nLineDist = nLineHeight;
+
+ while ( pCurr->Height() > nLineHeight )
+ nLineHeight = nLineHeight + nLineDist;
+
+ KSHORT nAsc = pCurr->GetAscent() +
+ ( bRubyTop ?
+ ( nLineHeight - pCurr->Height() + nRubyHeight ) / 2 :
+ ( nLineHeight - pCurr->Height() - nRubyHeight ) / 2 );
+
+ pCurr->Height( nLineHeight );
+ pCurr->SetAscent( nAsc );
+ pInf->GetParaPortion()->SetFixLineHeight();
+
+ // we ignore any line spacing options except from ...
+ const SvxLineSpacingItem* pSpace = aLineInf.GetLineSpacing();
+ if ( ! IsParaLine() && pSpace &&
+ SVX_INTER_LINE_SPACE_PROP == pSpace->GetInterLineSpaceRule() )
+ {
+ sal_uLong nTmp = pSpace->GetPropLineSpace();
+
+ if( nTmp < 100 )
+ nTmp = 100;
+
+ nTmp *= nLineHeight;
+ nLineHeight = (sal_uInt16)(nTmp / 100);
+ }
+
+ pCurr->SetRealHeight( nLineHeight );
+ return;
+ }
+
+ // Das Dummyflag besitzen Zeilen, die nur Flyportions enthalten, diese
+ // sollten kein Register etc. beachten. Dummerweise hat kann es eine leere
+ // Zeile am Absatzende geben (bei leeren Abs?tzen oder nach einem
+ // Shift-Return), die das Register durchaus beachten soll.
+ if( !pCurr->IsDummy() || ( !pCurr->GetNext() &&
+ GetStart() >= GetTxtFrm()->GetTxt().Len() && !bNewLine ) )
+ {
+ const SvxLineSpacingItem *pSpace = aLineInf.GetLineSpacing();
+ if( pSpace )
+ {
+ switch( pSpace->GetLineSpaceRule() )
+ {
+ case SVX_LINE_SPACE_AUTO:
+ if (pSpace->GetInterLineSpaceRule()==SVX_INTER_LINE_SPACE_PROP) {
+ long nTmp = pSpace->GetPropLineSpace();
+ if (nTmp<100) { // code adaped from fixed line height
+ nTmp *= nLineHeight;
+ nTmp /= 100;
+ if( !nTmp )
+ ++nTmp;
+ nLineHeight = (KSHORT)nTmp;
+/*
+ //@TODO figure out how WW maps ascent and descent
+ //in case of prop line spacing <100%
+ KSHORT nAsc = ( 4 * nLineHeight ) / 5; // 80%
+ if( nAsc < pCurr->GetAscent() ||
+ nLineHeight - nAsc < pCurr->Height() -
+pCurr->GetAscent() )
+ pCurr->SetClipping( sal_True );
+ pCurr->SetAscent( nAsc );
+*/
+ pCurr->Height( nLineHeight );
+ pInf->GetParaPortion()->SetFixLineHeight();
+ }
+ }
+ break;
+ case SVX_LINE_SPACE_MIN:
+ {
+ if( nLineHeight < KSHORT( pSpace->GetLineHeight() ) )
+ nLineHeight = pSpace->GetLineHeight();
+ break;
+ }
+ case SVX_LINE_SPACE_FIX:
+ {
+ nLineHeight = pSpace->GetLineHeight();
+ KSHORT nAsc = ( 4 * nLineHeight ) / 5; // 80%
+ if( nAsc < pCurr->GetAscent() ||
+ nLineHeight - nAsc < pCurr->Height() - pCurr->GetAscent() )
+ pCurr->SetClipping( sal_True );
+ pCurr->Height( nLineHeight );
+ pCurr->SetAscent( nAsc );
+ pInf->GetParaPortion()->SetFixLineHeight();
+ }
+ break;
+ default: OSL_FAIL( ": unknown LineSpaceRule" );
+ }
+ if( !IsParaLine() )
+ switch( pSpace->GetInterLineSpaceRule() )
+ {
+ case SVX_INTER_LINE_SPACE_OFF:
+ break;
+ case SVX_INTER_LINE_SPACE_PROP:
+ {
+ long nTmp = pSpace->GetPropLineSpace();
+ // 50% ist das Minimum, bei 0% schalten wir auf
+ // den Defaultwert 100% um ...
+ if( nTmp < 50 )
+ nTmp = nTmp ? 50 : 100;
+
+ nTmp *= nLineHeight;
+ nTmp /= 100;
+ if( !nTmp )
+ ++nTmp;
+ nLineHeight = (KSHORT)nTmp;
+ break;
+ }
+ case SVX_INTER_LINE_SPACE_FIX:
+ {
+ nLineHeight = nLineHeight + pSpace->GetInterLineSpace();
+ break;
+ }
+ default: OSL_FAIL( ": unknown InterLineSpaceRule" );
+ }
+ }
+#if OSL_DEBUG_LEVEL > 1
+ KSHORT nDummy = nLineHeight + 1;
+ (void)nDummy;
+#endif
+
+ if( IsRegisterOn() )
+ {
+ SwTwips nTmpY = Y() + pCurr->GetAscent() + nLineHeight - pCurr->Height();
+ SWRECTFN( pFrm )
+ if ( bVert )
+ nTmpY = pFrm->SwitchHorizontalToVertical( nTmpY );
+ nTmpY = (*fnRect->fnYDiff)( nTmpY, RegStart() );
+ KSHORT nDiff = KSHORT( nTmpY % RegDiff() );
+ if( nDiff )
+ nLineHeight += RegDiff() - nDiff;
+ }
+ }
+ pCurr->SetRealHeight( nLineHeight );
+}
+
+/*************************************************************************
+ * SwTxtFormatter::FeedInf()
+ *************************************************************************/
+
+void SwTxtFormatter::FeedInf( SwTxtFormatInfo &rInf ) const
+{
+ // 3260, 3860: Fly auf jeden Fall loeschen!
+ ClearFly( rInf );
+ rInf.Init();
+
+ rInf.ChkNoHyph( CntEndHyph(), CntMidHyph() );
+ rInf.SetRoot( pCurr );
+ rInf.SetLineStart( nStart );
+ rInf.SetIdx( nStart );
+
+ // Handle overflows:
+ // --> FME 2004-11-25 #i34348# Changed type from sal_uInt16 to SwTwips
+ SwTwips nTmpLeft = Left();
+ SwTwips nTmpRight = Right();
+ SwTwips nTmpFirst = FirstLeft();
+ // <--
+
+ if ( nTmpLeft > USHRT_MAX ||
+ nTmpRight > USHRT_MAX ||
+ nTmpFirst > USHRT_MAX )
+ {
+ SWRECTFN( rInf.GetTxtFrm() )
+ nTmpLeft = (rInf.GetTxtFrm()->Frm().*fnRect->fnGetLeft)();
+ nTmpRight = (rInf.GetTxtFrm()->Frm().*fnRect->fnGetRight)();
+ nTmpFirst = nTmpLeft;
+ }
+
+ rInf.Left( nTmpLeft );
+ rInf.Right( nTmpRight );
+ rInf.First( nTmpFirst );
+
+ rInf.RealWidth( KSHORT(rInf.Right()) - KSHORT(GetLeftMargin()) );
+ rInf.Width( rInf.RealWidth() );
+ if( ((SwTxtFormatter*)this)->GetRedln() )
+ {
+ ((SwTxtFormatter*)this)->GetRedln()->Clear( ((SwTxtFormatter*)this)->GetFnt() );
+ ((SwTxtFormatter*)this)->GetRedln()->Reset();
+ }
+}
+
+/*************************************************************************
+ * SwTxtFormatter::FormatReset()
+ *************************************************************************/
+
+void SwTxtFormatter::FormatReset( SwTxtFormatInfo &rInf )
+{
+ pCurr->Truncate();
+ pCurr->Init();
+ if( pBlink && pCurr->IsBlinking() )
+ pBlink->Delete( pCurr );
+
+ // delete pSpaceAdd und pKanaComp
+ pCurr->FinishSpaceAdd();
+ pCurr->FinishKanaComp();
+ pCurr->ResetFlags();
+ FeedInf( rInf );
+}
+
+/*************************************************************************
+ * SwTxtFormatter::CalcOnceMore()
+ *************************************************************************/
+
+sal_Bool SwTxtFormatter::CalcOnceMore()
+{
+ if( pDropFmt )
+ {
+ const KSHORT nOldDrop = GetDropHeight();
+ CalcDropHeight( pDropFmt->GetLines() );
+ bOnceMore = nOldDrop != GetDropHeight();
+ }
+ else
+ bOnceMore = sal_False;
+ return bOnceMore;
+}
+
+/*************************************************************************
+ * SwTxtFormatter::CalcBottomLine()
+ *************************************************************************/
+
+SwTwips SwTxtFormatter::CalcBottomLine() const
+{
+ SwTwips nRet = Y() + GetLineHeight();
+ SwTwips nMin = GetInfo().GetTxtFly()->GetMinBottom();
+ if( nMin && ++nMin > nRet )
+ {
+ SwTwips nDist = pFrm->Frm().Height() - pFrm->Prt().Height()
+ - pFrm->Prt().Top();
+ if( nRet + nDist < nMin )
+ {
+ sal_Bool bRepaint = HasTruncLines() &&
+ GetInfo().GetParaPortion()->GetRepaint()->Bottom() == nRet-1;
+ nRet = nMin - nDist;
+ if( bRepaint )
+ {
+ ((SwRepaint*)GetInfo().GetParaPortion()
+ ->GetRepaint())->Bottom( nRet-1 );
+ ((SwTxtFormatInfo&)GetInfo()).SetPaintOfst( 0 );
+ }
+ }
+ }
+ return nRet;
+}
+
+/*************************************************************************
+ * SwTxtFormatter::_CalcFitToContent()
+ *
+ * FME/OD: This routine does a limited text formatting.
+ *************************************************************************/
+
+SwTwips SwTxtFormatter::_CalcFitToContent()
+{
+ FormatReset( GetInfo() );
+ BuildPortions( GetInfo() );
+ pCurr->CalcLine( *this, GetInfo() );
+ return pCurr->Width();
+}
+
+/*************************************************************************
+ * SwTxtFormatter::AllowRepaintOpt()
+ *
+ * determines if the calculation of a repaint offset is allowed
+ * otherwise each line is painted from 0 (this is a copy of the beginning
+ * of the former SwTxtFormatter::Recycle() function
+ *************************************************************************/
+sal_Bool SwTxtFormatter::AllowRepaintOpt() const
+{
+ // reformat position in front of current line? Only in this case
+ // we want to set the repaint offset
+ sal_Bool bOptimizeRepaint = nStart < GetInfo().GetReformatStart() &&
+ pCurr->GetLen();
+
+ // a special case is the last line of a block adjusted paragraph:
+ if ( bOptimizeRepaint )
+ {
+ switch( GetAdjust() )
+ {
+ case SVX_ADJUST_BLOCK:
+ {
+ if( IsLastBlock() || IsLastCenter() )
+ bOptimizeRepaint = sal_False;
+ else
+ {
+ // ????: Blank in der letzten Masterzeile (blocksat.sdw)
+ bOptimizeRepaint = 0 == pCurr->GetNext() && !pFrm->GetFollow();
+ if ( bOptimizeRepaint )
+ {
+ SwLinePortion *pPos = pCurr->GetFirstPortion();
+ while ( pPos && !pPos->IsFlyPortion() )
+ pPos = pPos->GetPortion();
+ bOptimizeRepaint = !pPos;
+ }
+ }
+ break;
+ }
+ case SVX_ADJUST_CENTER:
+ case SVX_ADJUST_RIGHT:
+ bOptimizeRepaint = sal_False;
+ break;
+ default: ;
+ }
+ }
+
+ // Schon wieder ein Sonderfall: unsichtbare SoftHyphs
+ const xub_StrLen nReformat = GetInfo().GetReformatStart();
+ if( bOptimizeRepaint && STRING_LEN != nReformat )
+ {
+ const xub_Unicode cCh = GetInfo().GetTxt().GetChar( nReformat );
+ bOptimizeRepaint = ( CH_TXTATR_BREAKWORD != cCh && CH_TXTATR_INWORD != cCh )
+ || ! GetInfo().HasHint( nReformat );
+ }
+
+ return bOptimizeRepaint;
+}
+
+namespace {
+ /*************************************************************************
+ * ::CalcOptRepaint()
+ *
+ * calculates and sets optimal repaint offset for the current line
+ *************************************************************************/
+ long lcl_CalcOptRepaint( SwTxtFormatter &rThis,
+ SwLineLayout &rCurr,
+ const xub_StrLen nOldLineEnd,
+ const std::vector<long> &rFlyStarts )
+ {
+ SwTxtFormatInfo txtFmtInfo = rThis.GetInfo();
+ if ( txtFmtInfo.GetIdx() < txtFmtInfo.GetReformatStart() )
+ // the reformat position is behind our new line, that means
+ // something of our text has moved to the next line
+ return 0;
+
+ xub_StrLen nReformat = Min( txtFmtInfo.GetReformatStart(), nOldLineEnd );
+
+ // in case we do not have any fly in our line, our repaint position
+ // is the changed position - 1
+ if ( rFlyStarts.empty() && ! rCurr.IsFly() )
+ {
+ // this is the maximum repaint offset determined during formatting
+ // for example: the beginning of the first right tab stop
+ // if this value is 0, this means that we do not have an upper
+ // limit for the repaint offset
+ const long nFormatRepaint = txtFmtInfo.GetPaintOfst();
+
+ if ( nReformat < txtFmtInfo.GetLineStart() + 3 )
+ return 0;
+
+ // step back two positions for smoother repaint
+ nReformat -= 2;
+
+ #ifndef QUARTZ
+ #ifndef ENABLE_GRAPHITE
+ // --> FME 2004-09-27 #i28795#, #i34607#, #i38388#
+ // step back six(!) more characters for complex scripts
+ // this is required e.g., for Khmer (thank you, Javier!)
+ const SwScriptInfo& rSI = txtFmtInfo.GetParaPortion()->GetScriptInfo();
+ xub_StrLen nMaxContext = 0;
+ if( ::i18n::ScriptType::COMPLEX == rSI.ScriptType( nReformat ) )
+ nMaxContext = 6;
+ #else
+ // Some Graphite fonts need context for scripts not marked as complex
+ static const xub_StrLen nMaxContext = 10;
+ #endif
+ #else
+ // some fonts like Quartz's Zapfino need more context
+ // TODO: query FontInfo for maximum unicode context
+ static const xub_StrLen nMaxContext = 8;
+ #endif
+ if( nMaxContext > 0 )
+ {
+ if ( nReformat > txtFmtInfo.GetLineStart() + nMaxContext )
+ nReformat = nReformat - nMaxContext;
+ else
+ nReformat = txtFmtInfo.GetLineStart();
+ }
+ // <--
+
+ // Weird situation: Our line used to end with a hole portion
+ // and we delete some characters at the end of our line. We have
+ // to take care for repainting the blanks which are not anymore
+ // covered by the hole portion
+ while ( nReformat > txtFmtInfo.GetLineStart() &&
+ CH_BLANK == txtFmtInfo.GetChar( nReformat ) )
+ --nReformat;
+
+ OSL_ENSURE( nReformat < txtFmtInfo.GetIdx(), "Reformat too small for me!" );
+ SwRect aRect;
+
+ // Note: GetChareRect is not const. It definitely changes the
+ // bMulti flag. We have to save and resore the old value.
+ sal_Bool bOldMulti = txtFmtInfo.IsMulti();
+ rThis.GetCharRect( &aRect, nReformat );
+ txtFmtInfo.SetMulti( bOldMulti );
+
+ return nFormatRepaint ? Min( aRect.Left(), nFormatRepaint ) :
+ aRect.Left();
+ }
+ else
+ {
+ // nReformat may be wrong, if something around flys has changed:
+ // we compare the former and the new fly positions in this line
+ // if anything has changed, we carefully have to adjust the right
+ // repaint position
+ long nPOfst = 0;
+ sal_uInt16 nCnt = 0;
+ sal_uInt16 nX = 0;
+ sal_uInt16 nIdx = rThis.GetInfo().GetLineStart();
+ SwLinePortion* pPor = rCurr.GetFirstPortion();
+
+ while ( pPor )
+ {
+ if ( pPor->IsFlyPortion() )
+ {
+ // compare start of fly with former start of fly
+ if (nCnt < rFlyStarts.size() &&
+ nX == rFlyStarts[ nCnt ] &&
+ nIdx < nReformat
+ )
+ // found fix position, nothing has changed left from nX
+ nPOfst = nX + pPor->Width();
+ else
+ break;
+
+ nCnt++;
+ }
+ nX = nX + pPor->Width();
+ nIdx = nIdx + pPor->GetLen();
+ pPor = pPor->GetPortion();
+ }
+
+ return nPOfst + rThis.GetLeftMargin();
+ }
+ }
+
+ // Determine if we need to build hidden portions
+ bool lcl_BuildHiddenPortion( const SwTxtSizeInfo& rInf, xub_StrLen &rPos )
+ {
+ // Only if hidden text should not be shown:
+ // if ( rInf.GetVsh() && rInf.GetVsh()->GetWin() && rInf.GetOpt().IsShowHiddenChar() )
+ const bool bShowInDocView = rInf.GetVsh() && rInf.GetVsh()->GetWin() && rInf.GetOpt().IsShowHiddenChar();
+ const bool bShowForPrinting = rInf.GetOpt().IsShowHiddenChar( sal_True ) && rInf.GetOpt().IsPrinting();
+ if (bShowInDocView || bShowForPrinting)
+ return false;
+
+ const SwScriptInfo& rSI = rInf.GetParaPortion()->GetScriptInfo();
+ xub_StrLen nHiddenStart;
+ xub_StrLen nHiddenEnd;
+ rSI.GetBoundsOfHiddenRange( rPos, nHiddenStart, nHiddenEnd );
+ if ( nHiddenEnd )
+ {
+ rPos = nHiddenEnd;
+ return true;
+ }
+
+ return false;
+ }
+
+} //end unnamed namespace
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/text/itrform2.hxx b/sw/source/core/text/itrform2.hxx
new file mode 100644
index 000000000000..a838806a11c8
--- /dev/null
+++ b/sw/source/core/text/itrform2.hxx
@@ -0,0 +1,213 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+#ifndef _ITRFORM2_HXX
+#define _ITRFORM2_HXX
+#include "itrpaint.hxx"
+
+class SwFlyCntPortion;
+class SwInterHyphInfo;
+class SwDropPortion;
+class SwFmtDrop;
+class SwTxtAttr;
+class SwNumberPortion;
+class SwErgoSumPortion;
+class SwExpandPortion;
+class SwMultiPortion;
+class SwFtnPortion;
+
+/*************************************************************************
+ * class SwTxtFormatter
+ *************************************************************************/
+
+class SwTxtFormatter : public SwTxtPainter
+{
+ const SwFmtDrop *pDropFmt;
+ SwMultiPortion* pMulti; // during formatting a multi-portion
+ sal_uInt8 nCntEndHyph; // zaehlt aufeinanderfolgende Hyphens am Zeilenende
+ sal_uInt8 nCntMidHyph; // zaehlt aufeinanderfolgende Hyphens vor Flies
+ xub_StrLen nLeftScanIdx; // for increasing performance during
+ xub_StrLen nRightScanIdx; // scanning for portion ends
+ sal_Bool bOnceMore : 1; // noch 'ne Runde?
+ sal_Bool bFlyInCntBase : 1; // Base-Referenz der zeichengeb. Rahmen setzen
+ sal_Bool bChanges : 1; // Flag, fuer die Berechnung des Repaint-Rechtecks
+ sal_Bool bTruncLines : 1; // Flag, Repaint-Rechtecks ggf. erweitern
+ sal_Bool bUnclipped : 1; // Flag, ob Repaint groesser als feste Zeilenhoehe
+ sal_uInt16 m_nHintEndIndex; // HACK for TryNewNoLengthPortion
+ SwLinePortion *NewPortion( SwTxtFormatInfo &rInf );
+ SwTxtPortion *NewTxtPortion( SwTxtFormatInfo &rInf );
+ SwLinePortion *NewExtraPortion( SwTxtFormatInfo &rInf );
+ SwTabPortion *NewTabPortion( SwTxtFormatInfo &rInf, bool bAuto ) const;
+ SwNumberPortion *NewNumberPortion( SwTxtFormatInfo &rInf ) const;
+ SwDropPortion *NewDropPortion( SwTxtFormatInfo &rInf );
+ SwNumberPortion *NewFtnNumPortion( SwTxtFormatInfo &rInf ) const;
+ SwErgoSumPortion *NewErgoSumPortion( SwTxtFormatInfo &rInf ) const;
+ SwExpandPortion *NewFldPortion( SwTxtFormatInfo &rInf,
+ const SwTxtAttr *pHt ) const;
+ SwFtnPortion *NewFtnPortion( SwTxtFormatInfo &rInf, SwTxtAttr *pHt );
+ SwFlyCntPortion *NewFlyCntPortion( SwTxtFormatInfo &rInf,
+ SwTxtAttr *pHt ) const;
+ SwLinePortion *WhichFirstPortion( SwTxtFormatInfo &rInf );
+ SwTxtPortion *WhichTxtPor( SwTxtFormatInfo &rInf ) const;
+ SwExpandPortion * TryNewNoLengthPortion( SwTxtFormatInfo & rInfo );
+
+ // Das Herzstueck der Formatierung
+ void BuildPortions( SwTxtFormatInfo &rInf );
+ sal_Bool BuildMultiPortion( SwTxtFormatInfo &rInf, SwMultiPortion& rMulti );
+
+ // Berechnung des emulierten rechten Rands
+ void CalcFlyWidth( SwTxtFormatInfo &rInf );
+
+ // wird von SwTxtFormatter wegen UpdatePos ueberladen
+ void CalcAdjustLine( SwLineLayout *pCurr );
+
+ // consideres line spacing attributes
+ void CalcRealHeight( sal_Bool bNewLine = sal_False );
+
+ // uebertraegt die Daten nach rInf
+ void FeedInf( SwTxtFormatInfo &rInf ) const;
+
+ // behandelt die Unterlaufsituationen
+ SwLinePortion *UnderFlow( SwTxtFormatInfo &rInf );
+
+ // errechnet den Ascent und die Hoehe aus der Fontmetric
+ void CalcAscent( SwTxtFormatInfo &rInf, SwLinePortion *pPor );
+
+ // determines, if a optimized repaint rectange is allowed
+ sal_Bool AllowRepaintOpt() const;
+
+ // wird von FormatLine gerufen.
+ void FormatReset( SwTxtFormatInfo &rInf );
+
+ // durch das Adjustment aendert sich die Position der Portions
+ void UpdatePos( SwLineLayout *pCurr, Point aStart, xub_StrLen nStartIdx,
+ sal_Bool bAllWays = sal_False ) const;
+
+ // Setze alle FlyInCntFrms auf die uebergebene BaseLine
+ void AlignFlyInCntBase( long nBaseLine ) const;
+
+ // Unterlaufbedingungen bei Flys
+ sal_Bool ChkFlyUnderflow( SwTxtFormatInfo &rInf ) const;
+
+ // Portion einfuegen.
+ void InsertPortion( SwTxtFormatInfo &rInf, SwLinePortion *pPor ) const;
+
+ // schaetzt die Hoehe fuer die DropPortion
+ void GuessDropHeight( const MSHORT nLines );
+
+public:
+ // errechnet die Hoehe fuer die DropPortion
+ void CalcDropHeight( const MSHORT nLines );
+
+ // errechnet den Bottom des Absatzes, beruecksichtigt an diesem verankerte
+ // Objekte mit Umlauf 1. Absatz.
+ SwTwips CalcBottomLine() const;
+
+ // Beruecksichtigt zeichengebundene Objekte bei der Repaintrechteck-
+ // berechnung in Zeilen mit fester Zeilenhoehe
+ void CalcUnclipped( SwTwips& rTop, SwTwips& rBottom );
+
+ // u.a. fuer DropCaps
+ sal_Bool CalcOnceMore();
+
+ void CtorInitTxtFormatter( SwTxtFrm *pFrm, SwTxtFormatInfo *pInf );
+ inline SwTxtFormatter( SwTxtFrm *pTxtFrm, SwTxtFormatInfo *pTxtFmtInf ) : SwTxtPainter(pTxtFrm!=NULL?pTxtFrm->GetTxtNode():NULL)
+ { CtorInitTxtFormatter( pTxtFrm, pTxtFmtInf ); }
+ ~SwTxtFormatter();
+
+ xub_StrLen FormatLine( const xub_StrLen nStart );
+
+ void RecalcRealHeight();
+
+ // Wir formatieren eine Zeile fuer die interaktive Trennung
+ sal_Bool Hyphenate( SwInterHyphInfo &rInf );
+
+ // Spezialmethode fuer QuoVadis-Texte
+ // nErgo ist die Seitennummer der ErgoSum-Ftn
+ // Bei 0 ist es noch unklar.
+ xub_StrLen FormatQuoVadis( const xub_StrLen nStart );
+
+ // Die Notbremse: Formatierung abbrechen, Zeile verwerfen.
+ inline sal_Bool IsStop() const { return GetInfo().IsStop(); }
+
+ // Das Gegenstueck: Formatierung unbedingt fortsetzen.
+ inline sal_Bool IsNewLine() const { return GetInfo().IsNewLine(); }
+
+ // FormatQuick(); auffrischen von Formatinformationen
+ inline sal_Bool IsQuick() const { return GetInfo().IsQuick(); }
+
+ // erzeugt ggfs. ein SwLineLayout, dass Ftn/Fly--Oszillation unterbindet.
+ void MakeDummyLine();
+
+ // SwTxtIter-Funktionalitaet
+ void Insert( SwLineLayout *pLine );
+
+ // die noch verbleibende Hoehe bis zum Seitenrand
+ KSHORT GetFrmRstHeight() const;
+
+ // Wie breit waerest Du ohne rechte Begrenzungen (Flys etc.)?
+ SwTwips _CalcFitToContent( );
+
+ SwLinePortion* MakeRestPortion(const SwLineLayout* pLine, xub_StrLen nPos);
+
+ inline const SwFmtDrop *GetDropFmt() const { return pDropFmt; }
+ inline void ClearDropFmt() { pDropFmt = 0; }
+
+ inline SwMultiPortion *GetMulti() const { return pMulti; }
+
+ inline sal_Bool IsOnceMore() const { return bOnceMore; }
+ inline void SetOnceMore( sal_Bool bNew ) { bOnceMore = bNew; }
+
+ inline sal_Bool HasChanges() const { return bChanges; }
+ inline void SetChanges() { bChanges = sal_True; }
+
+ inline sal_Bool HasTruncLines() const { return bTruncLines; }
+ inline void SetTruncLines( sal_Bool bNew ) { bTruncLines = bNew; }
+
+ inline sal_Bool IsUnclipped() const { return bUnclipped; }
+ inline void SetUnclipped( sal_Bool bNew ) { bUnclipped = bNew; }
+
+ inline sal_Bool IsFlyInCntBase() const { return bFlyInCntBase; }
+ inline void SetFlyInCntBase( sal_Bool bNew = sal_True ){ bFlyInCntBase = bNew; }
+
+ inline SwTxtFormatInfo &GetInfo()
+ { return (SwTxtFormatInfo&)SwTxtIter::GetInfo(); }
+ inline const SwTxtFormatInfo &GetInfo() const
+ { return (const SwTxtFormatInfo&)SwTxtIter::GetInfo(); }
+
+ inline void InitCntHyph() { CntHyphens( nCntEndHyph, nCntMidHyph ); }
+ inline const sal_uInt8 &CntEndHyph() const { return nCntEndHyph; }
+ inline const sal_uInt8 &CntMidHyph() const { return nCntMidHyph; }
+ inline sal_uInt8 &CntEndHyph() { return nCntEndHyph; }
+ inline sal_uInt8 &CntMidHyph() { return nCntMidHyph; }
+};
+
+
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/text/itrpaint.cxx b/sw/source/core/text/itrpaint.cxx
new file mode 100644
index 000000000000..0571efb8a5d3
--- /dev/null
+++ b/sw/source/core/text/itrpaint.cxx
@@ -0,0 +1,708 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+
+#include "hintids.hxx"
+#include "flyfrm.hxx" // SwFlyInCntFrm
+#include "viewopt.hxx" // SwViewOptions
+#include "txtatr.hxx" // SwINetFmt
+#include <tools/multisel.hxx>
+#include <editeng/escpitem.hxx>
+#include <editeng/udlnitem.hxx>
+#include <editeng/lrspitem.hxx>
+#include <txtinet.hxx>
+#include <fchrfmt.hxx>
+#include <frmatr.hxx>
+#include <sfx2/printer.hxx>
+#include <fmtftn.hxx>
+#include <fmtfld.hxx>
+#include <fldbas.hxx> // SwField
+#include <rootfrm.hxx>
+#include <pagefrm.hxx>
+#include <pagedesc.hxx> // SwPageDesc
+#include <tgrditem.hxx>
+
+// --> FME 2004-06-08 #i12836# enhanced pdf export
+#include <EnhancedPDFExportHelper.hxx>
+// <--
+
+
+#include "flyfrms.hxx"
+#include "viewsh.hxx"
+#include "itrpaint.hxx"
+#include "txtfrm.hxx" // pFrm
+#include "txtfly.hxx"
+#include "swfont.hxx"
+#include "txtpaint.hxx"
+#include "portab.hxx" // SwTabPortion::IsFilled
+#include "porfly.hxx" // SwFlyCntPortion
+#include "porfld.hxx" // SwGrfNumPortion
+#include "frmfmt.hxx" // LRSpace
+#include "txatbase.hxx" // SwTxtAttr
+#include "charfmt.hxx" // SwFmtCharFmt
+#include "redlnitr.hxx" // SwRedlineItr
+#include "porrst.hxx" // SwArrowPortion
+#include "pormulti.hxx"
+
+/*************************************************************************
+ * IsUnderlineBreak
+ *
+ * Returns, if we have an underline breaking situation
+ * Adding some more conditions here means you also have to change them
+ * in SwTxtPainter::CheckSpecialUnderline
+ *************************************************************************/
+sal_Bool IsUnderlineBreak( const SwLinePortion& rPor, const SwFont& rFnt )
+{
+ return UNDERLINE_NONE == rFnt.GetUnderline() ||
+ rPor.IsFlyPortion() || rPor.IsFlyCntPortion() ||
+ rPor.IsBreakPortion() || rPor.IsMarginPortion() ||
+ rPor.IsHolePortion() ||
+ ( rPor.IsMultiPortion() && ! ((SwMultiPortion&)rPor).IsBidi() ) ||
+ rFnt.GetEscapement() < 0 || rFnt.IsWordLineMode() ||
+ SVX_CASEMAP_KAPITAELCHEN == rFnt.GetCaseMap();
+}
+
+/*************************************************************************
+ * SwTxtPainter::CtorInitTxtPainter()
+ *************************************************************************/
+void SwTxtPainter::CtorInitTxtPainter( SwTxtFrm *pNewFrm, SwTxtPaintInfo *pNewInf )
+{
+ CtorInitTxtCursor( pNewFrm, pNewInf );
+ pInf = pNewInf;
+ SwFont *pMyFnt = GetFnt();
+ GetInfo().SetFont( pMyFnt );
+#if OSL_DEBUG_LEVEL > 1
+ if( ALIGN_BASELINE != pMyFnt->GetAlign() )
+ {
+ OSL_ENSURE( ALIGN_BASELINE == pMyFnt->GetAlign(),
+ "+SwTxtPainter::CTOR: font alignment revolution" );
+ pMyFnt->SetAlign( ALIGN_BASELINE );
+ }
+#endif
+ bPaintDrop = sal_False;
+}
+
+
+/*************************************************************************
+ * SwTxtPainter::CalcPaintOfst()
+ *************************************************************************/
+SwLinePortion *SwTxtPainter::CalcPaintOfst( const SwRect &rPaint )
+{
+ SwLinePortion *pPor = pCurr->GetFirstPortion();
+ GetInfo().SetPaintOfst( 0 );
+ SwTwips nPaintOfst = rPaint.Left();
+
+ // nPaintOfst wurde exakt auf das Ende eingestellt, deswegen <=
+ // nPaintOfst ist dokumentglobal, deswegen nLeftMar aufaddieren
+ // const KSHORT nLeftMar = KSHORT(GetLeftMargin());
+ // 8310: painten von LineBreaks in leeren Zeilen.
+ if( nPaintOfst && pCurr->Width() )
+ {
+ SwLinePortion *pLast = 0;
+ // 7529 und 4757: nicht <= nPaintOfst
+ while( pPor && GetInfo().X() + pPor->Width() + (pPor->Height()/2)
+ < nPaintOfst )
+ {
+ if( pPor->InSpaceGrp() && GetInfo().GetSpaceAdd() )
+ {
+ long nTmp = GetInfo().X() +pPor->Width() +
+ pPor->CalcSpacing( GetInfo().GetSpaceAdd(), GetInfo() );
+ if( nTmp + (pPor->Height()/2) >= nPaintOfst )
+ break;
+ GetInfo().X( nTmp );
+ GetInfo().SetIdx( GetInfo().GetIdx() + pPor->GetLen() );
+ }
+ else
+ pPor->Move( GetInfo() );
+ pLast = pPor;
+ pPor = pPor->GetPortion();
+ }
+
+ // 7529: bei PostIts auch pLast returnen.
+ if( pLast && !pLast->Width() && pLast->IsPostItsPortion() )
+ {
+ pPor = pLast;
+ GetInfo().SetIdx( GetInfo().GetIdx() - pPor->GetLen() );
+ }
+ }
+ return pPor;
+}
+
+/*************************************************************************
+ * SwTxtPainter::DrawTextLine()
+ *
+ * Es gibt zwei Moeglichkeiten bei transparenten Font auszugeben:
+ * 1) DrawRect auf die ganze Zeile und die DrawText hinterher
+ * (objektiv schnell, subjektiv langsam).
+ * 2) Fuer jede Portion ein DrawRect mit anschliessendem DrawText
+ * ausgefuehrt (objektiv langsam, subjektiv schnell).
+ * Da der User in der Regel subjektiv urteilt, wird die 2. Methode
+ * als Default eingestellt.
+ *************************************************************************/
+void SwTxtPainter::DrawTextLine( const SwRect &rPaint, SwSaveClip &rClip,
+ const sal_Bool bUnderSz )
+{
+#if OSL_DEBUG_LEVEL > 1
+// sal_uInt16 nFntHeight = GetInfo().GetFont()->GetHeight( GetInfo().GetVsh(), GetInfo().GetOut() );
+// sal_uInt16 nFntAscent = GetInfo().GetFont()->GetAscent( GetInfo().GetVsh(), GetInfo().GetOut() );
+#endif
+
+ // Adjustierung ggf. nachholen
+ GetAdjusted();
+ GetInfo().SetpSpaceAdd( pCurr->GetpLLSpaceAdd() );
+ GetInfo().ResetSpaceIdx();
+ GetInfo().SetKanaComp( pCurr->GetpKanaComp() );
+ GetInfo().ResetKanaIdx();
+ // Die Groesse des Frames
+ GetInfo().SetIdx( GetStart() );
+ GetInfo().SetPos( GetTopLeft() );
+
+ const sal_Bool bDrawInWindow = GetInfo().OnWin();
+
+ // 6882: Leerzeilen duerfen nicht wegoptimiert werden bei Paragraphzeichen.
+ const sal_Bool bEndPor = GetInfo().GetOpt().IsParagraph() && !GetInfo().GetTxt().Len();
+
+ SwLinePortion *pPor = bEndPor ? pCurr->GetFirstPortion() : CalcPaintOfst( rPaint );
+
+ // Optimierung!
+ const SwTwips nMaxRight = Min( rPaint.Right(), Right() );
+ const SwTwips nTmpLeft = GetInfo().X();
+ if( !bEndPor && nTmpLeft >= nMaxRight )
+ return;
+
+ // DropCaps!
+ // 7538: natuerlich auch auf dem Drucker
+ if( !bPaintDrop )
+ {
+ // 8084: Optimierung, weniger Painten.
+ // AMA: Durch 8084 wurde 7538 wiederbelebt!
+ // bDrawInWindow entfernt, damit DropCaps auch gedruckt werden
+ bPaintDrop = pPor == pCurr->GetFirstPortion()
+ && GetDropLines() >= GetLineNr();
+ }
+
+ KSHORT nTmpHeight, nTmpAscent;
+ CalcAscentAndHeight( nTmpAscent, nTmpHeight );
+
+ // bClip entscheidet darueber, ob geclippt werden muss.
+ // Das Ganze muss vor der Retusche stehen
+
+ sal_Bool bClip = ( bDrawInWindow || bUnderSz ) && !rClip.IsChg();
+ if( bClip && pPor )
+ {
+ // Wenn TopLeft oder BottomLeft der Line ausserhalb liegen,
+ // muss geclippt werden. Die Ueberpruefung auf Right() erfolgt
+ // in der folgenden Ausgabeschleife...
+
+ if( GetInfo().GetPos().X() < rPaint.Left() ||
+ GetInfo().GetPos().Y() < rPaint.Top() ||
+ GetInfo().GetPos().Y() + nTmpHeight > rPaint.Top() + rPaint.Height() )
+ {
+ bClip = sal_False;
+ rClip.ChgClip( rPaint, pFrm, pCurr->HasUnderscore() );
+ }
+#if OSL_DEBUG_LEVEL > 1
+ static sal_Bool bClipAlways = sal_False;
+ if( bClip && bClipAlways )
+ { bClip = sal_False;
+ rClip.ChgClip( rPaint );
+ }
+#endif
+ }
+
+ // Alignment:
+ OutputDevice* pOut = GetInfo().GetOut();
+ Point aPnt1( nTmpLeft, GetInfo().GetPos().Y() );
+ if ( aPnt1.X() < rPaint.Left() )
+ aPnt1.X() = rPaint.Left();
+ if ( aPnt1.Y() < rPaint.Top() )
+ aPnt1.Y() = rPaint.Top();
+ Point aPnt2( GetInfo().GetPos().X() + nMaxRight - GetInfo().X(),
+ GetInfo().GetPos().Y() + nTmpHeight );
+ if ( aPnt2.X() > rPaint.Right() )
+ aPnt2.X() = rPaint.Right();
+ if ( aPnt2.Y() > rPaint.Bottom() )
+ aPnt2.Y() = rPaint.Bottom();
+
+ const SwRect aLineRect( aPnt1, aPnt2 );
+
+ if( pCurr->IsClipping() )
+ {
+ rClip.ChgClip( aLineRect, pFrm );
+ bClip = sal_False;
+ }
+
+ if( !pPor && !bEndPor )
+ return;
+
+ // Baseline-Ausgabe auch bei nicht-TxtPortions (vgl. TabPor mit Fill)
+ // if no special vertical alignment is used,
+ // we calculate Y value for the whole line
+ GETGRID( GetTxtFrm()->FindPageFrm() )
+ const sal_Bool bAdjustBaseLine =
+ GetLineInfo().HasSpecialAlign( GetTxtFrm()->IsVertical() ) ||
+ ( 0 != pGrid );
+ const SwTwips nLineBaseLine = GetInfo().GetPos().Y() + nTmpAscent;
+ if ( ! bAdjustBaseLine )
+ GetInfo().Y( nLineBaseLine );
+
+ // 7529: PostIts prepainten
+ if( GetInfo().OnWin() && pPor && !pPor->Width() )
+ {
+ SeekAndChg( GetInfo() );
+
+ if( bAdjustBaseLine )
+ {
+ const SwTwips nOldY = GetInfo().Y();
+
+ GetInfo().Y( GetInfo().GetPos().Y() + AdjustBaseLine( *pCurr, 0,
+ GetInfo().GetFont()->GetHeight( GetInfo().GetVsh(), *pOut ),
+ GetInfo().GetFont()->GetAscent( GetInfo().GetVsh(), *pOut )
+ ) );
+
+ pPor->PrePaint( GetInfo(), pPor );
+ GetInfo().Y( nOldY );
+ }
+ else
+ pPor->PrePaint( GetInfo(), pPor );
+ }
+
+ // 7923: EndPortions geben auch Zeichen aus, deswegen den Fnt wechseln!
+ if( bEndPor )
+ SeekStartAndChg( GetInfo() );
+
+ sal_Bool bRest = pCurr->IsRest();
+ sal_Bool bFirst = sal_True;
+
+ SwArrowPortion *pArrow = NULL;
+ // Reference portion for the paragraph end portion
+ SwLinePortion* pEndTempl = pCurr->GetFirstPortion();
+
+ while( pPor )
+ {
+ sal_Bool bSeeked = sal_True;
+ GetInfo().SetLen( pPor->GetLen() );
+
+ const SwTwips nOldY = GetInfo().Y();
+
+ if ( bAdjustBaseLine )
+ {
+ GetInfo().Y( GetInfo().GetPos().Y() + AdjustBaseLine( *pCurr, pPor ) );
+
+ // we store the last portion, because a possible paragraph
+ // end character has the same font as this portion
+ // (only in special vertical alignment case, otherwise the first
+ // portion of the line is used)
+ if ( pPor->Width() && pPor->InTxtGrp() )
+ pEndTempl = pPor;
+ }
+
+ // Ein Sonderfall sind GluePortions, die Blanks ausgeben.
+
+ // 6168: Der Rest einer FldPortion zog sich die Attribute der naechsten
+ // Portion an, dies wird durch SeekAndChgBefore vermieden:
+ if( ( bRest && pPor->InFldGrp() && !pPor->GetLen() ) )
+ SeekAndChgBefore( GetInfo() );
+ else if ( pPor->IsQuoVadisPortion() )
+ {
+ xub_StrLen nOffset = GetInfo().GetIdx();
+ SeekStartAndChg( GetInfo(), sal_True );
+ if( GetRedln() && pCurr->HasRedline() )
+ GetRedln()->Seek( *pFnt, nOffset, 0 );
+ }
+ else if( pPor->InTxtGrp() || pPor->InFldGrp() || pPor->InTabGrp() )
+ SeekAndChg( GetInfo() );
+ else if ( !bFirst && pPor->IsBreakPortion() && GetInfo().GetOpt().IsParagraph() )
+ {
+ // Paragraphzeichen sollten den gleichen Font wie das Zeichen vor
+ // haben, es sei denn, es gibt Redlining in dem Absatz.
+ if( GetRedln() )
+ SeekAndChg( GetInfo() );
+ else
+ SeekAndChgBefore( GetInfo() );
+ }
+ else
+ bSeeked = sal_False;
+
+// bRest = sal_False;
+
+ // Wenn das Ende der Portion hinausragt, wird geclippt.
+ // Es wird ein Sicherheitsabstand von Height-Halbe aufaddiert,
+ // damit die TTF-"f" nicht im Seitenrand haengen...
+ if( bClip &&
+ GetInfo().X() + pPor->Width() + ( pPor->Height() / 2 ) > nMaxRight )
+ {
+ bClip = sal_False;
+ rClip.ChgClip( rPaint, pFrm, pCurr->HasUnderscore() );
+ }
+
+ // Portions, die "unter" dem Text liegen wie PostIts
+ SwLinePortion *pNext = pPor->GetPortion();
+ if( GetInfo().OnWin() && pNext && !pNext->Width() )
+ {
+ // Fix 11289: Felder waren hier ausgeklammert wg. Last!=Owner beim
+ // Laden von Brief.sdw. Jetzt sind die Felder wieder zugelassen,
+ // durch bSeeked wird Last!=Owner vermieden.
+ if ( !bSeeked )
+ SeekAndChg( GetInfo() );
+ pNext->PrePaint( GetInfo(), pPor );
+ }
+
+ // We calculate a separate font for underlining.
+ CheckSpecialUnderline( pPor, bAdjustBaseLine ? nOldY : 0 );
+ SwUnderlineFont* pUnderLineFnt = GetInfo().GetUnderFnt();
+ if ( pUnderLineFnt )
+ {
+ const Point aTmpPoint( GetInfo().X(),
+ bAdjustBaseLine ?
+ pUnderLineFnt->GetPos().Y() :
+ nLineBaseLine );
+ pUnderLineFnt->SetPos( aTmpPoint );
+ }
+
+
+ // in extended input mode we do not want a common underline font.
+ SwUnderlineFont* pOldUnderLineFnt = 0;
+ if ( GetRedln() && GetRedln()->ExtOn() )
+ {
+ pOldUnderLineFnt = GetInfo().GetUnderFnt();
+ GetInfo().SetUnderFnt( 0 );
+ }
+
+ {
+ // --> FME 2004-06-24 #i16816# tagged pdf support
+ Por_Info aPorInfo( *pPor, *this );
+ SwTaggedPDFHelper aTaggedPDFHelper( 0, 0, &aPorInfo, *pOut );
+ // <--
+
+ if( pPor->IsMultiPortion() )
+ PaintMultiPortion( rPaint, (SwMultiPortion&)*pPor );
+ else
+ pPor->Paint( GetInfo() );
+ }
+
+ // reset underline font
+ if ( pOldUnderLineFnt )
+ GetInfo().SetUnderFnt( pOldUnderLineFnt );
+
+ // reset (for special vertical alignment)
+ GetInfo().Y( nOldY );
+
+ if( GetFnt()->IsURL() && pPor->InTxtGrp() )
+ GetInfo().NotifyURL( *pPor );
+
+ bFirst &= !pPor->GetLen();
+ if( pNext || !pPor->IsMarginPortion() )
+ pPor->Move( GetInfo() );
+ if( pPor->IsArrowPortion() && GetInfo().OnWin() && !pArrow )
+ pArrow = (SwArrowPortion*)pPor;
+
+ pPor = bDrawInWindow || GetInfo().X() <= nMaxRight ||
+ // --> FME 2004-06-24 #i16816# tagged pdf support
+ ( GetInfo().GetVsh() &&
+ GetInfo().GetVsh()->GetViewOptions()->IsPDFExport() &&
+ pNext && pNext->IsHolePortion() ) ?
+ // <--
+ pNext :
+ 0;
+ }
+
+ // delete underline font
+ delete GetInfo().GetUnderFnt();
+ GetInfo().SetUnderFnt( 0 );
+
+ // paint remaining stuff
+ if( bDrawInWindow )
+ {
+ // If special vertical alignment is enabled, GetInfo().Y() is the
+ // top of the current line. Therefore is has to be adjusted for
+ // the painting of the remaining stuff. We first store the old value.
+ const SwTwips nOldY = GetInfo().Y();
+
+ if( !GetNextLine() &&
+ GetInfo().GetVsh() && !GetInfo().GetVsh()->IsPreView() &&
+ GetInfo().GetOpt().IsParagraph() && !GetTxtFrm()->GetFollow() &&
+ GetInfo().GetIdx() >= GetInfo().GetTxt().Len() )
+ {
+ const SwTmpEndPortion aEnd( *pEndTempl );
+ GetFnt()->ChgPhysFnt( GetInfo().GetVsh(), *pOut );
+
+ if ( bAdjustBaseLine )
+ GetInfo().Y( GetInfo().GetPos().Y()
+ + AdjustBaseLine( *pCurr, &aEnd ) );
+
+ aEnd.Paint( GetInfo() );
+ GetInfo().Y( nOldY );
+ }
+ if( GetInfo().GetVsh() && !GetInfo().GetVsh()->IsPreView() )
+ {
+ const sal_Bool bNextUndersized =
+ ( GetTxtFrm()->GetNext() &&
+ 0 == GetTxtFrm()->GetNext()->Prt().Height() &&
+ GetTxtFrm()->GetNext()->IsTxtFrm() &&
+ ((SwTxtFrm*)GetTxtFrm()->GetNext())->IsUndersized() ) ;
+
+ if( bUnderSz || bNextUndersized )
+ {
+ if ( bAdjustBaseLine )
+ GetInfo().Y( GetInfo().GetPos().Y() + pCurr->GetAscent() );
+
+ if( pArrow )
+ GetInfo().DrawRedArrow( *pArrow );
+
+ // GetInfo().Y() must be current baseline.
+ SwTwips nDiff = GetInfo().Y() + nTmpHeight - nTmpAscent - GetTxtFrm()->Frm().Bottom();
+ if( ( nDiff > 0 &&
+ ( GetEnd() < GetInfo().GetTxt().Len() ||
+ ( nDiff > nTmpHeight/2 && GetPrevLine() ) ) ) ||
+ (nDiff >= 0 && bNextUndersized) )
+
+ {
+ SwArrowPortion aArrow( GetInfo() );
+ GetInfo().DrawRedArrow( aArrow );
+ }
+
+ GetInfo().Y( nOldY );
+ }
+ }
+ }
+
+ if( pCurr->IsClipping() )
+ rClip.ChgClip( rPaint, pFrm );
+}
+
+void SwTxtPainter::CheckSpecialUnderline( const SwLinePortion* pPor,
+ long nAdjustBaseLine )
+{
+ // Check if common underline should not be continued.
+ if ( IsUnderlineBreak( *pPor, *pFnt ) )
+ {
+ // delete underline font
+ delete GetInfo().GetUnderFnt();
+ GetInfo().SetUnderFnt( 0 );
+ return;
+ }
+
+ // If current underline matches the common underline font, we continue
+ // to use the common underline font.
+ if ( GetInfo().GetUnderFnt() &&
+ GetInfo().GetUnderFnt()->GetFont().GetUnderline() ==
+ GetFnt()->GetUnderline() )
+ return;
+
+ // calculate the new common underline font
+ SwFont* pUnderlineFnt = 0;
+ Point aCommonBaseLine;
+
+ Range aRange( 0, GetInfo().GetTxt().Len() );
+ MultiSelection aUnderMulti( aRange );
+
+ OSL_ENSURE( GetFnt() && UNDERLINE_NONE != GetFnt()->GetUnderline(),
+ "CheckSpecialUnderline without underlined font" );
+ const SwFont* pParaFnt = GetAttrHandler().GetFont();
+ if( pParaFnt && pParaFnt->GetUnderline() == GetFnt()->GetUnderline() )
+ aUnderMulti.SelectAll();
+
+ SwTxtAttr* pTxtAttr;
+ if( HasHints() )
+ {
+ sal_Bool bUnder = sal_False;
+ MSHORT nTmp = 0;
+
+ while( nTmp < pHints->GetStartCount() )
+ {
+ pTxtAttr = pHints->GetStart( nTmp++ );
+ sal_Bool bUnderSelect = sal_False;
+
+ const SvxUnderlineItem* pItem =
+ static_cast<const SvxUnderlineItem*>(CharFmt::GetItem( *pTxtAttr, RES_CHRATR_UNDERLINE ));
+
+ if ( pItem )
+ {
+ bUnder = sal_True;
+ bUnderSelect = pFnt->GetUnderline() == pItem->GetLineStyle();
+ }
+
+ if( bUnder )
+ {
+ xub_StrLen nSt = *pTxtAttr->GetStart();
+ xub_StrLen nEnd = *pTxtAttr->GetEnd();
+ if( nEnd > nSt )
+ {
+ Range aTmp( nSt, nEnd - 1 );
+ if( bUnder )
+ aUnderMulti.Select( aTmp, bUnderSelect );
+ }
+ bUnder = sal_False;
+ }
+ }
+ }
+
+ MSHORT i;
+ xub_StrLen nIndx = GetInfo().GetIdx();
+ long nUnderStart = 0;
+ long nUnderEnd = 0;
+ MSHORT nCnt = (MSHORT)aUnderMulti.GetRangeCount();
+
+ // find the underline range the current portion is contained in
+ for( i = 0; i < nCnt; ++i )
+ {
+ const Range& rRange = aUnderMulti.GetRange( i );
+ if( nUnderEnd == rRange.Min() )
+ nUnderEnd = rRange.Max();
+ else if( nIndx >= rRange.Min() )
+ {
+ nUnderStart = rRange.Min();
+ nUnderEnd = rRange.Max();
+ }
+ else
+ break;
+ }
+
+ // restrict start and end to current line
+ if ( GetStart() > nUnderStart )
+ nUnderStart = GetStart();
+
+ if ( GetEnd() && GetEnd() <= nUnderEnd )
+ nUnderEnd = GetEnd() - 1;
+
+
+ // check, if underlining is not isolated
+ if ( nIndx + GetInfo().GetLen() < nUnderEnd + 1 )
+ {
+ //
+ // here starts the algorithm for calculating the underline font
+ //
+ SwScriptInfo& rScriptInfo = GetInfo().GetParaPortion()->GetScriptInfo();
+ SwAttrIter aIter( *(SwTxtNode*)GetInfo().GetTxtFrm()->GetTxtNode(),
+ rScriptInfo );
+
+ xub_StrLen nTmpIdx = nIndx;
+ sal_uLong nSumWidth = 0;
+ sal_uLong nSumHeight = 0;
+ sal_uLong nBold = 0;
+ sal_uInt16 nMaxBaseLineOfst = 0;
+ sal_uInt16 nNumberOfPortions = 0;
+
+ while( nTmpIdx <= nUnderEnd && pPor )
+ {
+ if ( pPor->IsFlyPortion() || pPor->IsFlyCntPortion() ||
+ pPor->IsBreakPortion() || pPor->IsMarginPortion() ||
+ pPor->IsHolePortion() ||
+ ( pPor->IsMultiPortion() && ! ((SwMultiPortion*)pPor)->IsBidi() ) )
+ break;
+
+ aIter.Seek( nTmpIdx );
+
+ if ( aIter.GetFnt()->GetEscapement() < 0 || pFnt->IsWordLineMode() ||
+ SVX_CASEMAP_KAPITAELCHEN == pFnt->GetCaseMap() )
+ break;
+
+ if ( !aIter.GetFnt()->GetEscapement() )
+ {
+ nSumWidth += pPor->Width();
+ const sal_uLong nFontHeight = aIter.GetFnt()->GetHeight();
+
+ // If we do not have a common baseline we take the baseline
+ // and the font of the lowest portion.
+ if ( nAdjustBaseLine )
+ {
+ sal_uInt16 nTmpBaseLineOfst = AdjustBaseLine( *pCurr, pPor );
+ if ( nMaxBaseLineOfst < nTmpBaseLineOfst )
+ {
+ nMaxBaseLineOfst = nTmpBaseLineOfst;
+ nSumHeight = nFontHeight;
+ }
+ }
+ // in horizontal layout we build a weighted sum of the heights
+ else
+ nSumHeight += pPor->Width() * nFontHeight;
+
+ if ( WEIGHT_NORMAL != aIter.GetFnt()->GetWeight() )
+ nBold += pPor->Width();
+ }
+
+ ++nNumberOfPortions;
+
+ nTmpIdx = nTmpIdx + pPor->GetLen();
+ pPor = pPor->GetPortion();
+ }
+
+ // resulting height
+ if ( nNumberOfPortions > 1 && nSumWidth )
+ {
+ const sal_uLong nNewFontHeight = nAdjustBaseLine ?
+ nSumHeight :
+ nSumHeight / nSumWidth;
+
+ pUnderlineFnt = new SwFont( *GetInfo().GetFont() );
+
+ // font height
+ const sal_uInt8 nActual = pUnderlineFnt->GetActual();
+ pUnderlineFnt->SetSize( Size( pUnderlineFnt->GetSize( nActual ).Width(),
+ nNewFontHeight ), nActual );
+
+ // font weight
+ if ( 2 * nBold > nSumWidth )
+ pUnderlineFnt->SetWeight( WEIGHT_BOLD, nActual );
+ else
+ pUnderlineFnt->SetWeight( WEIGHT_NORMAL, nActual );
+
+ // common base line
+ aCommonBaseLine.Y() = nAdjustBaseLine + nMaxBaseLineOfst;
+ }
+ }
+
+ // an escaped redlined portion should also have a special underlining
+ if( ! pUnderlineFnt && pFnt->GetEscapement() > 0 && GetRedln() &&
+ GetRedln()->ChkSpecialUnderline() )
+ pUnderlineFnt = new SwFont( *pFnt );
+
+ delete GetInfo().GetUnderFnt();
+
+ if ( pUnderlineFnt )
+ {
+ pUnderlineFnt->SetProportion( 100 );
+ pUnderlineFnt->SetEscapement( 0 );
+ pUnderlineFnt->SetStrikeout( STRIKEOUT_NONE );
+ pUnderlineFnt->SetOverline( UNDERLINE_NONE );
+ const Color aFillColor( COL_TRANSPARENT );
+ pUnderlineFnt->SetFillColor( aFillColor );
+
+ GetInfo().SetUnderFnt( new SwUnderlineFont( *pUnderlineFnt,
+ aCommonBaseLine ) );
+ }
+ else
+ // I'm sorry, we do not have a special underlining font for you.
+ GetInfo().SetUnderFnt( 0 );
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/text/itrpaint.hxx b/sw/source/core/text/itrpaint.hxx
new file mode 100644
index 000000000000..4304676f3f97
--- /dev/null
+++ b/sw/source/core/text/itrpaint.hxx
@@ -0,0 +1,72 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+#ifndef _ITRPAINT_HXX
+#define _ITRPAINT_HXX
+#include "itrtxt.hxx"
+
+class SwSaveClip; // SwTxtPainter
+class SwMultiPortion;
+
+/*************************************************************************
+ * class SwTxtPainter
+ *************************************************************************/
+
+class SwTxtPainter : public SwTxtCursor
+{
+ sal_Bool bPaintDrop;
+
+ SwLinePortion *CalcPaintOfst( const SwRect &rPaint );
+ void CheckSpecialUnderline( const SwLinePortion* pPor,
+ long nAdjustBaseLine = 0 );
+protected:
+ void CtorInitTxtPainter( SwTxtFrm *pFrm, SwTxtPaintInfo *pInf );
+ inline SwTxtPainter(SwTxtNode* pTxtNode) : SwTxtCursor(pTxtNode) { }
+
+public:
+ inline SwTxtPainter( SwTxtFrm *pTxtFrm, SwTxtPaintInfo *pTxtPaintInf ) : SwTxtCursor(pTxtFrm!=NULL?pTxtFrm->GetTxtNode():NULL)
+ { CtorInitTxtPainter( pTxtFrm, pTxtPaintInf ); }
+ void DrawTextLine( const SwRect &rPaint, SwSaveClip &rClip,
+ const sal_Bool bUnderSz );
+ void PaintDropPortion();
+ // if PaintMultiPortion is called recursively, we have to pass the
+ // surrounding SwBidiPortion
+ void PaintMultiPortion( const SwRect &rPaint, SwMultiPortion& rMulti,
+ const SwMultiPortion* pEnvPor = 0 );
+ inline void SetPaintDrop( const sal_Bool bNew ) { bPaintDrop = bNew; }
+ inline sal_Bool IsPaintDrop() const { return bPaintDrop; }
+ inline SwTxtPaintInfo &GetInfo()
+ { return (SwTxtPaintInfo&)SwTxtIter::GetInfo(); }
+ inline const SwTxtPaintInfo &GetInfo() const
+ { return (const SwTxtPaintInfo&)SwTxtIter::GetInfo(); }
+};
+
+
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/text/itrtxt.cxx b/sw/source/core/text/itrtxt.cxx
new file mode 100644
index 000000000000..93cba310f3be
--- /dev/null
+++ b/sw/source/core/text/itrtxt.cxx
@@ -0,0 +1,513 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+
+#include "ndtxt.hxx"
+#include "flyfrm.hxx"
+#include "paratr.hxx"
+#include <vcl/outdev.hxx>
+#include <editeng/paravertalignitem.hxx>
+
+#include "pormulti.hxx"
+#include <pagefrm.hxx>
+#include <pagedesc.hxx> // SwPageDesc
+#include <tgrditem.hxx>
+#include <porfld.hxx>
+
+#include "itrtxt.hxx"
+#include "txtfrm.hxx"
+#include "porfly.hxx"
+
+#if OSL_DEBUG_LEVEL > 1
+#include "txtfrm.hxx" // GetFrmID,
+#endif
+
+/*************************************************************************
+ * SwTxtIter::CtorInitTxtIter()
+ *************************************************************************/
+
+void SwTxtIter::CtorInitTxtIter( SwTxtFrm *pNewFrm, SwTxtInfo *pNewInf )
+{
+ SwTxtNode *pNode = pNewFrm->GetTxtNode();
+
+ OSL_ENSURE( pNewFrm->GetPara(), "No paragraph" );
+
+ CtorInitAttrIter( *pNode, pNewFrm->GetPara()->GetScriptInfo(), pNewFrm );
+
+ pFrm = pNewFrm;
+ pInf = pNewInf;
+ aLineInf.CtorInitLineInfo( pNode->GetSwAttrSet(), *pNode );
+ nFrameStart = pFrm->Frm().Pos().Y() + pFrm->Prt().Pos().Y();
+ SwTxtIter::Init();
+ if( pNode->GetSwAttrSet().GetRegister().GetValue() )
+ bRegisterOn = pFrm->FillRegister( nRegStart, nRegDiff );
+ else
+ bRegisterOn = sal_False;
+}
+
+/*************************************************************************
+ * SwTxtIter::Init()
+ *************************************************************************/
+
+void SwTxtIter::Init()
+{
+ pCurr = pInf->GetParaPortion();
+ nStart = pInf->GetTxtStart();
+ nY = nFrameStart;
+ bPrev = sal_True;
+ pPrev = 0;
+ nLineNr = 1;
+}
+
+/*************************************************************************
+ * SwTxtIter::_GetHeightAndAscent()
+ *************************************************************************/
+
+void SwTxtIter::CalcAscentAndHeight( KSHORT &rAscent, KSHORT &rHeight ) const
+{
+ rHeight = GetLineHeight();
+ rAscent = pCurr->GetAscent() + rHeight - pCurr->Height();
+}
+
+/*************************************************************************
+ * SwTxtIter::_GetPrev()
+ *************************************************************************/
+
+SwLineLayout *SwTxtIter::_GetPrev()
+{
+ pPrev = 0;
+ bPrev = sal_True;
+ SwLineLayout *pLay = pInf->GetParaPortion();
+ if( pCurr == pLay )
+ return 0;
+ while( pLay->GetNext() != pCurr )
+ pLay = pLay->GetNext();
+ return pPrev = pLay;
+}
+
+/*************************************************************************
+ * SwTxtIter::GetPrev()
+ *************************************************************************/
+
+const SwLineLayout *SwTxtIter::GetPrev()
+{
+ if(! bPrev)
+ _GetPrev();
+ return pPrev;
+}
+
+/*************************************************************************
+ * SwTxtIter::Prev()
+ *************************************************************************/
+
+const SwLineLayout *SwTxtIter::Prev()
+{
+ if( !bPrev )
+ _GetPrev();
+ if( pPrev )
+ {
+ bPrev = sal_False;
+ pCurr = pPrev;
+ nStart = nStart - pCurr->GetLen();
+ nY = nY - GetLineHeight();
+ if( !pCurr->IsDummy() && !(--nLineNr) )
+ ++nLineNr;
+ return pCurr;
+ }
+ else
+ return 0;
+}
+
+/*************************************************************************
+ * SwTxtIter::Next()
+ *************************************************************************/
+
+const SwLineLayout *SwTxtIter::Next()
+{
+ if(pCurr->GetNext())
+ {
+ pPrev = pCurr;
+ bPrev = sal_True;
+ nStart = nStart + pCurr->GetLen();
+ nY += GetLineHeight();
+ if( pCurr->GetLen() || ( nLineNr>1 && !pCurr->IsDummy() ) )
+ ++nLineNr;
+ return pCurr = pCurr->GetNext();
+ }
+ else
+ return 0;
+}
+
+/*************************************************************************
+ * SwTxtIter::NextLine()
+ *************************************************************************/
+
+const SwLineLayout *SwTxtIter::NextLine()
+{
+ const SwLineLayout *pNext = Next();
+ while( pNext && pNext->IsDummy() && pNext->GetNext() )
+ {
+ pNext = Next();
+ }
+ return pNext;
+}
+
+/*************************************************************************
+ * SwTxtIter::GetNextLine()
+ *************************************************************************/
+
+const SwLineLayout *SwTxtIter::GetNextLine() const
+{
+ const SwLineLayout *pNext = pCurr->GetNext();
+ while( pNext && pNext->IsDummy() && pNext->GetNext() )
+ {
+ pNext = pNext->GetNext();
+ }
+ return (SwLineLayout*)pNext;
+}
+
+/*************************************************************************
+ * SwTxtIter::GetPrevLine()
+ *************************************************************************/
+
+const SwLineLayout *SwTxtIter::GetPrevLine()
+{
+ const SwLineLayout *pRoot = pInf->GetParaPortion();
+ if( pRoot == pCurr )
+ return 0;
+ const SwLineLayout *pLay = pRoot;
+
+ while( pLay->GetNext() != pCurr )
+ pLay = pLay->GetNext();
+
+ if( pLay->IsDummy() )
+ {
+ const SwLineLayout *pTmp = pRoot;
+ pLay = pRoot->IsDummy() ? 0 : pRoot;
+ while( pTmp->GetNext() != pCurr )
+ {
+ if( !pTmp->IsDummy() )
+ pLay = pTmp;
+ pTmp = pTmp->GetNext();
+ }
+ }
+
+ // Wenn sich nichts getan hat, dann gibt es nur noch Dummys
+ return (SwLineLayout*)pLay;
+}
+
+/*************************************************************************
+ * SwTxtIter::PrevLine()
+ *************************************************************************/
+
+const SwLineLayout *SwTxtIter::PrevLine()
+{
+ const SwLineLayout *pMyPrev = Prev();
+ if( !pMyPrev )
+ return 0;
+
+ const SwLineLayout *pLast = pMyPrev;
+ while( pMyPrev && pMyPrev->IsDummy() )
+ {
+ pLast = pMyPrev;
+ pMyPrev = Prev();
+ }
+ return (SwLineLayout*)(pMyPrev ? pMyPrev : pLast);
+}
+
+/*************************************************************************
+ * SwTxtIter::Bottom()
+ *************************************************************************/
+
+void SwTxtIter::Bottom()
+{
+ while( Next() )
+ {
+ // nothing
+ }
+}
+
+/*************************************************************************
+ * SwTxtIter::CharToLine()
+ *************************************************************************/
+
+void SwTxtIter::CharToLine(const xub_StrLen nChar)
+{
+ while( nStart + pCurr->GetLen() <= nChar && Next() )
+ ;
+ while( nStart > nChar && Prev() )
+ ;
+}
+
+/*************************************************************************
+ * SwTxtIter::CharCrsrToLine()
+ *************************************************************************/
+
+// 1170: beruecksichtigt Mehrdeutigkeiten:
+const SwLineLayout *SwTxtCursor::CharCrsrToLine( const xub_StrLen nPosition )
+{
+ CharToLine( nPosition );
+ if( nPosition != nStart )
+ bRightMargin = sal_False;
+ sal_Bool bPrevious = bRightMargin && pCurr->GetLen() && GetPrev() &&
+ GetPrev()->GetLen();
+ if( bPrevious && nPosition && CH_BREAK == GetInfo().GetChar( nPosition-1 ) )
+ bPrevious = sal_False;
+ return bPrevious ? PrevLine() : pCurr;
+}
+
+/*************************************************************************
+ * SwTxtCrsr::AdjustBaseLine()
+ *************************************************************************/
+
+sal_uInt16 SwTxtCursor::AdjustBaseLine( const SwLineLayout& rLine,
+ const SwLinePortion* pPor,
+ sal_uInt16 nPorHeight, sal_uInt16 nPorAscent,
+ const sal_Bool bAutoToCentered ) const
+{
+ if ( pPor )
+ {
+ nPorHeight = pPor->Height();
+ nPorAscent = pPor->GetAscent();
+ }
+
+ sal_uInt16 nOfst = rLine.GetRealHeight() - rLine.Height();
+
+ GETGRID( pFrm->FindPageFrm() )
+ const sal_Bool bHasGrid = pGrid && GetInfo().SnapToGrid();
+
+ if ( bHasGrid )
+ {
+ const sal_uInt16 nRubyHeight = pGrid->GetRubyHeight();
+ const sal_Bool bRubyTop = ! pGrid->GetRubyTextBelow();
+
+ if ( GetInfo().IsMulti() )
+ // we are inside the GetCharRect recursion for multi portions
+ // we center the portion in its surrounding line
+ nOfst = ( pCurr->Height() - nPorHeight ) / 2 + nPorAscent;
+ else
+ {
+ // We have to take care for ruby portions.
+ // The ruby portion is NOT centered
+ nOfst = nOfst + nPorAscent;
+
+ if ( ! pPor || ! pPor->IsMultiPortion() ||
+ ! ((SwMultiPortion*)pPor)->IsRuby() )
+ {
+ // Portions which are bigger than on grid distance are
+ // centered inside the whole line.
+
+ //for text refactor
+ const sal_uInt16 nLineNetto = rLine.Height() - nRubyHeight;
+ //const sal_uInt16 nLineNetto = ( nPorHeight > nGridWidth ) ?
+ // rLine.Height() - nRubyHeight :
+ // nGridWidth;
+ nOfst += ( nLineNetto - nPorHeight ) / 2;
+ if ( bRubyTop )
+ nOfst = nOfst + nRubyHeight;
+ }
+ }
+ }
+ else
+ {
+ switch ( GetLineInfo().GetVertAlign() ) {
+ case SvxParaVertAlignItem::TOP :
+ nOfst = nOfst + nPorAscent;
+ break;
+ case SvxParaVertAlignItem::CENTER :
+ OSL_ENSURE( rLine.Height() >= nPorHeight, "Portion height > Line height");
+ nOfst += ( rLine.Height() - nPorHeight ) / 2 + nPorAscent;
+ break;
+ case SvxParaVertAlignItem::BOTTOM :
+ nOfst += rLine.Height() - nPorHeight + nPorAscent;
+ break;
+ case SvxParaVertAlignItem::AUTOMATIC :
+ if ( bAutoToCentered || GetInfo().GetTxtFrm()->IsVertical() )
+ {
+ //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin
+ if( GetInfo().GetTxtFrm()->IsVertLR() )
+ nOfst += rLine.Height() - ( rLine.Height() - nPorHeight ) / 2 - nPorAscent;
+ else
+ nOfst += ( rLine.Height() - nPorHeight ) / 2 + nPorAscent;
+ break;
+ }
+ case SvxParaVertAlignItem::BASELINE :
+ // base line
+ nOfst = nOfst + rLine.GetAscent();
+ break;
+ }
+ }
+
+ return nOfst;
+}
+
+/*************************************************************************
+ * SwTxtIter::TwipsToLine()
+ *************************************************************************/
+
+const SwLineLayout *SwTxtIter::TwipsToLine( const SwTwips y)
+{
+ while( nY + GetLineHeight() <= y && Next() )
+ ;
+ while( nY > y && Prev() )
+ ;
+ return pCurr;
+}
+
+//
+// Local helper function to check, if pCurr needs a field rest portion:
+//
+sal_Bool lcl_NeedsFieldRest( const SwLineLayout* pCurr )
+{
+ const SwLinePortion *pPor = pCurr->GetPortion();
+ sal_Bool bRet = sal_False;
+ while( pPor && !bRet )
+ {
+ bRet = pPor->InFldGrp() && ((SwFldPortion*)pPor)->HasFollow();
+ if( !pPor->GetPortion() || !pPor->GetPortion()->InFldGrp() )
+ break;
+ pPor = pPor->GetPortion();
+ }
+ return bRet;
+}
+
+/*************************************************************************
+ * SwTxtIter::TruncLines()
+ *************************************************************************/
+
+void SwTxtIter::TruncLines( sal_Bool bNoteFollow )
+{
+ SwLineLayout *pDel = pCurr->GetNext();
+ const xub_StrLen nEnd = nStart + pCurr->GetLen();
+
+ if( pDel )
+ {
+ pCurr->SetNext( 0 );
+ if( GetHints() && bNoteFollow )
+ {
+ GetInfo().GetParaPortion()->SetFollowField( pDel->IsRest() ||
+ lcl_NeedsFieldRest( pCurr ) );
+
+ // bug 88534: wrong positioning of flys
+ SwTxtFrm* pFollow = GetTxtFrm()->GetFollow();
+ if ( pFollow && ! pFollow->IsLocked() &&
+ nEnd == pFollow->GetOfst() )
+ {
+ xub_StrLen nRangeEnd = nEnd;
+ SwLineLayout* pLine = pDel;
+
+ // determine range to be searched for flys anchored as characters
+ while ( pLine )
+ {
+ nRangeEnd = nRangeEnd + pLine->GetLen();
+ pLine = pLine->GetNext();
+ }
+
+ SwpHints* pTmpHints = GetTxtFrm()->GetTxtNode()->GetpSwpHints();
+
+ // examine hints in range nEnd - (nEnd + nRangeChar)
+ for( sal_uInt16 i = 0; i < pTmpHints->Count(); i++ )
+ {
+ const SwTxtAttr* pHt = pTmpHints->GetTextHint( i );
+ if( RES_TXTATR_FLYCNT == pHt->Which() )
+ {
+ // check, if hint is in our range
+ const sal_uInt16 nTmpPos = *pHt->GetStart();
+ if ( nEnd <= nTmpPos && nTmpPos < nRangeEnd )
+ pFollow->_InvalidateRange(
+ SwCharRange( nTmpPos, nTmpPos ), 0 );
+ }
+ }
+ }
+ }
+ delete pDel;
+ }
+ if( pCurr->IsDummy() &&
+ !pCurr->GetLen() &&
+ nStart < GetTxtFrm()->GetTxt().Len() )
+ pCurr->SetRealHeight( 1 );
+ if( GetHints() )
+ pFrm->RemoveFtn( nEnd );
+}
+
+/*************************************************************************
+ * SwTxtIter::CntHyphens()
+ *************************************************************************/
+
+void SwTxtIter::CntHyphens( sal_uInt8 &nEndCnt, sal_uInt8 &nMidCnt) const
+{
+ nEndCnt = 0;
+ nMidCnt = 0;
+ if ( bPrev && pPrev && !pPrev->IsEndHyph() && !pPrev->IsMidHyph() )
+ return;
+ SwLineLayout *pLay = pInf->GetParaPortion();
+ if( pCurr == pLay )
+ return;
+ while( pLay != pCurr )
+ {
+ if ( pLay->IsEndHyph() )
+ nEndCnt++;
+ else
+ nEndCnt = 0;
+ if ( pLay->IsMidHyph() )
+ nMidCnt++;
+ else
+ nMidCnt = 0;
+ pLay = pLay->GetNext();
+ }
+}
+
+/*************************************************************************
+ * SwHookOut
+ *
+ * Change current output device to formatting device, this has to be done before
+ * formatting.
+ *************************************************************************/
+
+SwHookOut::SwHookOut( SwTxtSizeInfo& rInfo ) :
+ pInf( &rInfo ),
+ pOut( rInfo.GetOut() ),
+ bOnWin( rInfo.OnWin() )
+{
+ OSL_ENSURE( rInfo.GetRefDev(), "No reference device for text formatting" );
+
+ // set new values
+ rInfo.SetOut( rInfo.GetRefDev() );
+ rInfo.SetOnWin( sal_False );
+}
+
+SwHookOut::~SwHookOut()
+{
+ pInf->SetOut( pOut );
+ pInf->SetOnWin( bOnWin );
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/text/itrtxt.hxx b/sw/source/core/text/itrtxt.hxx
new file mode 100644
index 000000000000..46ec8cfd7964
--- /dev/null
+++ b/sw/source/core/text/itrtxt.hxx
@@ -0,0 +1,348 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+#ifndef _ITRTXT_HXX
+#define _ITRTXT_HXX
+#include "swtypes.hxx"
+#include "itratr.hxx"
+#include "inftxt.hxx"
+
+class SwTxtFrm;
+struct SwPosition;
+struct SwCrsrMoveState;
+class SwMarginPortion;
+class SwFlyPortion;
+
+/*************************************************************************
+ * class SwTxtIter
+ *************************************************************************/
+
+class SwTxtIter : public SwAttrIter
+{
+protected:
+ SwLineInfo aLineInf;
+ SwTxtFrm *pFrm;
+ SwTxtInfo *pInf;
+ SwLineLayout *pCurr;
+ SwLineLayout *pPrev;
+ SwTwips nFrameStart;
+ SwTwips nY;
+ SwTwips nRegStart; // Anfangsposition (Y) des Registers
+ xub_StrLen nStart; // Start im Textstring, Ende = pCurr->GetLen()
+ KSHORT nRegDiff; // Zeilenabstand des Registers
+ MSHORT nLineNr; // Zeilennummer
+ sal_Bool bPrev : 1;
+ sal_Bool bRegisterOn : 1; // Registerhaltigkeit
+ sal_Bool bOneBlock : 1; // Blocksatz: Einzelwoerter austreiben
+ sal_Bool bLastBlock : 1; // Blocksatz: Auch die letzte Zeile
+ sal_Bool bLastCenter : 1; // Blocksatz: Letzte Zeile zentrieren
+
+ SwLineLayout *_GetPrev();
+
+ // Zuruecksetzen in die erste Zeile.
+ void Init();
+ void CtorInitTxtIter( SwTxtFrm *pFrm, SwTxtInfo *pInf );
+ inline SwTxtIter(SwTxtNode* pTxtNode)
+ : SwAttrIter(pTxtNode)
+ , pFrm(NULL)
+ , pInf(NULL)
+ , pCurr(NULL)
+ , pPrev(NULL)
+ {}
+public:
+ inline SwTxtIter( SwTxtFrm *pTxtFrm, SwTxtInfo *pTxtInf ) : SwAttrIter(pTxtFrm!=NULL?pTxtFrm->GetTxtNode():NULL)
+ { CtorInitTxtIter( pTxtFrm, pTxtInf ); }
+ inline const SwLineLayout *GetCurr() const { return pCurr; } // niemals 0!
+ inline const SwLineLayout *GetNext() const { return pCurr->GetNext(); }
+ const SwLineLayout *GetPrev();
+ inline xub_StrLen GetLength() const { return pCurr->GetLen(); }
+ inline MSHORT GetLineNr() const { return nLineNr; }
+ inline xub_StrLen GetStart() const { return nStart; }
+ inline xub_StrLen GetEnd() const { return GetStart() + GetLength(); }
+ inline SwTwips Y() const { return nY; }
+
+ inline SwTwips RegStart() const { return nRegStart; }
+ inline KSHORT RegDiff() const { return nRegDiff; }
+ inline sal_Bool IsRegisterOn() const { return bRegisterOn; }
+
+ inline SwTxtInfo &GetInfo() { return *pInf; }
+ inline const SwTxtInfo &GetInfo() const { return *pInf; }
+
+ inline void Top() { Init(); }
+ void Bottom();
+ const SwLineLayout *Next();
+ const SwLineLayout *Prev();
+
+ // Ueberspringt die Dummyzeilen der FlyFrms
+ const SwLineLayout *NextLine();
+ const SwLineLayout *PrevLine();
+ const SwLineLayout *GetNextLine() const;
+ const SwLineLayout *GetPrevLine();
+
+ void CharToLine( const xub_StrLen );
+ const SwLineLayout *TwipsToLine(const SwTwips);
+
+ // schneidet ab pCurr alle ab.
+ void TruncLines( sal_Bool bNoteFollow = sal_False );
+
+ inline KSHORT GetLineHeight() const { return pCurr->GetRealHeight(); }
+ void CalcAscentAndHeight( KSHORT &rAscent, KSHORT &rHeight ) const;
+
+ // 5298, viel Aerger durch die Abfrage auf pCurr == pPara
+ inline sal_Bool IsFirstTxtLine() const
+ { return nStart == GetInfo().GetTxtStart() &&
+ !( pCurr->IsDummy() && GetNextLine() ); }
+
+ // Als Ersatz fuer das alte IsFirstLine()
+ inline sal_Bool IsParaLine() const
+ { return pCurr == pInf->GetParaPortion(); }
+
+ const SwLineInfo &GetLineInfo() const { return aLineInf; }
+ inline SwTwips GetFirstPos() const { return nFrameStart; }
+ inline sal_Bool SeekAndChg( SwTxtSizeInfo &rInf );
+ inline sal_Bool SeekAndChgBefore( SwTxtSizeInfo &rInf );
+ inline sal_Bool SeekStartAndChg( SwTxtSizeInfo &rInf, const sal_Bool bPara=sal_False );
+
+ inline SwTxtFrm *GetTxtFrm() { return pFrm; }
+ inline const SwTxtFrm *GetTxtFrm() const { return pFrm; }
+
+ // zaehlt aufeinanderfolgende Trennungen, um MaxHyphens einzuhalten
+ void CntHyphens( sal_uInt8 &nEndCnt, sal_uInt8 &nMidCnt) const;
+};
+
+/*************************************************************************
+ * class SwTxtMargin
+ *************************************************************************/
+
+class SwTxtMargin : public SwTxtIter
+{
+private:
+ SwTwips nLeft;
+ SwTwips nRight;
+ SwTwips nFirst;
+ KSHORT nDropLeft;
+ KSHORT nDropHeight;
+ KSHORT nDropDescent;
+ MSHORT nDropLines;
+ MSHORT nAdjust;
+ // --> OD 2008-06-30 #i91133#
+ SwTwips mnTabLeft;
+ // <--
+
+protected:
+ // fuer FormatQuoVadis
+ inline void Right( const SwTwips nNew ) { nRight = nNew; }
+ // fuer CalcFlyAdjust
+ inline void SetDropLeft( const KSHORT nNew ) { nDropLeft = nNew; }
+
+ void CtorInitTxtMargin( SwTxtFrm *pFrm, SwTxtSizeInfo *pInf );
+ inline SwTxtMargin(SwTxtNode* pTxtNode) : SwTxtIter(pTxtNode) { }
+public:
+ inline SwTxtMargin( SwTxtFrm *pTxtFrm, SwTxtSizeInfo *pTxtSizeInf ) : SwTxtIter(pTxtFrm!=NULL?pTxtFrm->GetTxtNode():NULL)
+ { CtorInitTxtMargin( pTxtFrm, pTxtSizeInf ); }
+ inline SwTwips GetLeftMargin() const;
+ inline SwTwips Left() const;
+ inline SwTwips Right() const { return nRight; }
+ inline SwTwips FirstLeft() const { return nFirst; }
+ inline SwTwips CurrWidth() const { return pCurr->PrtWidth(); }
+ SwTwips GetLineStart() const;
+ inline SwTwips GetLineEnd() const { return GetLineStart() + CurrWidth(); }
+ inline Point GetTopLeft() const { return Point( GetLineStart(), Y() ); }
+ inline sal_Bool IsOneBlock() const { return bOneBlock; }
+ inline sal_Bool IsLastBlock() const { return bLastBlock; }
+ inline sal_Bool IsLastCenter() const { return bLastCenter; }
+ inline MSHORT GetAdjust() const { return nAdjust; }
+ inline KSHORT GetLineWidth() const
+ { return KSHORT( Right() - GetLeftMargin() + 1 ); }
+ inline SwTwips GetLeftMin() const { return nFirst < nLeft ? nFirst : nLeft; }
+ inline sal_Bool HasNegFirst() const { return nFirst < nLeft; }
+
+ // --> OD 2008-06-30 #i91133#
+ inline SwTwips GetTabLeft() const
+ {
+ return mnTabLeft;
+ }
+ // <--
+ // DropCaps
+ inline MSHORT GetDropLines() const { return nDropLines; }
+ inline void SetDropLines( const MSHORT nNew ) { nDropLines = nNew; }
+ inline KSHORT GetDropLeft() const { return nDropLeft; }
+ inline KSHORT GetDropHeight() const { return nDropHeight; }
+ inline void SetDropHeight( const KSHORT nNew ) { nDropHeight = nNew; }
+ inline KSHORT GetDropDescent() const { return nDropDescent; }
+ inline void SetDropDescent( const KSHORT nNew ) { nDropDescent = nNew; }
+ void DropInit();
+
+ // liefert TxtPos fuer Start und Ende der aktuellen Zeile ohne whitespaces
+ // In frminf.cxx implementiert.
+ xub_StrLen GetTxtStart() const;
+ xub_StrLen GetTxtEnd() const;
+
+ inline SwTxtSizeInfo &GetInfo()
+ { return (SwTxtSizeInfo&)SwTxtIter::GetInfo(); }
+ inline const SwTxtSizeInfo &GetInfo() const
+ { return (const SwTxtSizeInfo&)SwTxtIter::GetInfo(); }
+
+};
+
+
+/*************************************************************************
+ * class SwTxtAdjuster
+ *************************************************************************/
+
+class SwTxtAdjuster : public SwTxtMargin
+{
+ // Gleicht die Portions aus, wenn Adjustment und FlyFrms vorliegen.
+ void CalcFlyAdjust( SwLineLayout *pCurr );
+
+ // ruft SplitGlues und CalcBlockAdjust
+ void FormatBlock( );
+
+ // Erstellt bei kurzen Zeilen die Glue-Kette.
+ SwMarginPortion* CalcRightMargin( SwLineLayout *pCurr, SwTwips nReal = 0 );
+
+ // Berechnung des Adjustments (FlyPortions)
+ SwFlyPortion *CalcFlyPortion( const long nRealWidth,
+ const SwRect &rCurrRect );
+
+protected:
+ inline SwTxtAdjuster(SwTxtNode* pTxtNode) : SwTxtMargin(pTxtNode) { }
+ // spannt beim Blocksatz die Glues auf.
+ void CalcNewBlock( SwLineLayout *pCurr, const SwLinePortion *pStopAt,
+ SwTwips nReal = 0, bool bSkipKashida = false );
+ SwTwips CalcKanaAdj( SwLineLayout *pCurr );
+public:
+ inline SwTxtAdjuster( SwTxtFrm *pTxtFrm, SwTxtSizeInfo *pTxtSizeInf ) : SwTxtMargin(pTxtFrm!=NULL?pTxtFrm->GetTxtNode():NULL)
+ { CtorInitTxtMargin( pTxtFrm, pTxtSizeInf ); }
+
+ // wird von SwTxtFormatter wegen UpdatePos ueberladen
+ void CalcAdjLine( SwLineLayout *pCurr );
+
+ // sorgt fuer das nachtraegliche adjustieren
+ inline void GetAdjusted() const
+ {
+ if( pCurr->IsFormatAdj() )
+ ((SwTxtAdjuster*)this)->CalcAdjLine( pCurr );
+ }
+
+ // DropCaps-Extrawurst
+ void CalcDropAdjust();
+ void CalcDropRepaint();
+};
+
+/*************************************************************************
+ * class SwTxtCursor
+ *************************************************************************/
+
+class SwTxtCursor : public SwTxtAdjuster
+{
+ // A small helper-class to save SwTxtCursor member, manipulate them
+ // and to restore them
+ friend class SwTxtCursorSave;
+
+ // 1170: Mehrdeutigkeiten
+ static sal_Bool bRightMargin;
+ void _GetCharRect(SwRect *, const xub_StrLen, SwCrsrMoveState* );
+protected:
+ void CtorInitTxtCursor( SwTxtFrm *pFrm, SwTxtSizeInfo *pInf );
+ inline SwTxtCursor(SwTxtNode* pTxtNode) : SwTxtAdjuster(pTxtNode) { }
+public:
+ inline SwTxtCursor( SwTxtFrm *pTxtFrm, SwTxtSizeInfo *pTxtSizeInf ) : SwTxtAdjuster(pTxtFrm!=NULL?pTxtFrm->GetTxtNode():NULL)
+ { CtorInitTxtCursor( pTxtFrm, pTxtSizeInf ); }
+ sal_Bool GetCharRect(SwRect *, const xub_StrLen, SwCrsrMoveState* = 0,
+ const long nMax = 0 );
+ sal_Bool GetEndCharRect(SwRect *, const xub_StrLen, SwCrsrMoveState* = 0,
+ const long nMax = 0 );
+ xub_StrLen GetCrsrOfst( SwPosition *pPos, const Point &rPoint,
+ const MSHORT nChgNode, SwCrsrMoveState* = 0 ) const;
+ // 1170: beruecksichtigt Mehrdeutigkeiten; Implementierung s.u.
+ const SwLineLayout *CharCrsrToLine( const xub_StrLen nPos );
+
+ // calculates baseline for portion rPor
+ // bAutoToCentered indicates, if AUTOMATIC mode means CENTERED or BASELINE
+ sal_uInt16 AdjustBaseLine( const SwLineLayout& rLine, const SwLinePortion* pPor,
+ sal_uInt16 nPorHeight = 0, sal_uInt16 nAscent = 0,
+ const sal_Bool bAutoToCentered = sal_False ) const;
+
+ static inline void SetRightMargin( const sal_Bool bNew ){ bRightMargin = bNew; }
+ static inline sal_Bool IsRightMargin() { return bRightMargin; }
+};
+
+/*************************************************************************
+ * SwHookOut
+ *
+ * Change current output device to printer, this has to be done before
+ * formatting.
+ *************************************************************************/
+
+class SwHookOut
+{
+ SwTxtSizeInfo* pInf;
+ OutputDevice* pOut;
+ sal_Bool bOnWin;
+public:
+ SwHookOut( SwTxtSizeInfo& rInfo );
+ ~SwHookOut();
+};
+
+/*************************************************************************
+ * Inline-Implementierungen
+ *************************************************************************/
+
+inline sal_Bool SwTxtIter::SeekAndChg( SwTxtSizeInfo &rInf )
+{
+ return SeekAndChgAttrIter( rInf.GetIdx(), rInf.GetOut() );
+}
+
+inline sal_Bool SwTxtIter::SeekAndChgBefore( SwTxtSizeInfo &rInf )
+{
+ if ( rInf.GetIdx() )
+ return SeekAndChgAttrIter( rInf.GetIdx()-1, rInf.GetOut() );
+ else
+ return SeekAndChgAttrIter( rInf.GetIdx(), rInf.GetOut() );
+}
+
+inline sal_Bool SwTxtIter::SeekStartAndChg( SwTxtSizeInfo &rInf, const sal_Bool bPara )
+{
+ return SeekStartAndChgAttrIter( rInf.GetOut(), bPara );
+}
+
+inline SwTwips SwTxtMargin::GetLeftMargin() const
+{
+ return IsFirstTxtLine() ? nFirst : Left();
+}
+
+inline SwTwips SwTxtMargin::Left() const
+{
+ return (nDropLines >= nLineNr && 1 != nLineNr) ? nFirst + nDropLeft : nLeft;
+}
+
+
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/text/noteurl.cxx b/sw/source/core/text/noteurl.cxx
new file mode 100644
index 000000000000..2e5cbcc692a7
--- /dev/null
+++ b/sw/source/core/text/noteurl.cxx
@@ -0,0 +1,89 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+
+
+#include "swtypes.hxx"
+#include <vcl/outdev.hxx>
+#include <svtools/imaprect.hxx>
+#include <svtools/imap.hxx>
+
+#include "txttypes.hxx"
+#include "noteurl.hxx"
+
+// globale Variable, wird in noteurl.Hxx bekanntgegeben
+SwNoteURL *pNoteURL = NULL;
+
+SV_IMPL_PTRARR( SwURLNoteList, SwURLNotePtr )
+
+
+void SwNoteURL::InsertURLNote( const XubString& rURL, const XubString& rTarget,
+ const SwRect& rRect )
+{
+ MSHORT i;
+ MSHORT nCount = aList.Count();
+ for( i = 0; i < nCount; i++ )
+ if( rRect == aList.GetObject(i)->GetRect() )
+ break;
+ if( i == nCount )
+ {
+ SwURLNote *pNew = new SwURLNote( rURL, rTarget, rRect );
+ aList.Insert( pNew, nCount );
+ }
+}
+
+
+void SwNoteURL::FillImageMap( ImageMap *pMap, const Point &rPos,
+ const MapMode& rMap )
+{
+ OSL_ENSURE( pMap, "FillImageMap: No ImageMap, no cookies!" );
+ MSHORT nCount = Count();
+ if( nCount )
+ {
+ MapMode aMap( MAP_100TH_MM );
+ for( MSHORT i = 0; i < nCount; ++i )
+ {
+ const SwURLNote &rNote = GetURLNote( i );
+ SwRect aSwRect( rNote.GetRect() );
+ aSwRect -= rPos;
+ Rectangle aRect( OutputDevice::LogicToLogic( aSwRect.SVRect(),
+ rMap, aMap ) );
+ IMapRectangleObject aObj( aRect, rNote.GetURL(), aEmptyStr, aEmptyStr,
+ rNote.GetTarget(), aEmptyStr, sal_True, sal_False );
+ pMap->InsertIMapObject( aObj );
+ }
+ }
+}
+
+
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/text/pordrop.hxx b/sw/source/core/text/pordrop.hxx
new file mode 100644
index 000000000000..41179f534f4f
--- /dev/null
+++ b/sw/source/core/text/pordrop.hxx
@@ -0,0 +1,122 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+#ifndef _PORDROP_HXX
+#define _PORDROP_HXX
+
+#include "portxt.hxx"
+
+class SwFont;
+
+// DropCap-Cache, globale Variable, in txtinit.cxx initialisiert/zerstoert
+// und in txtdrop.cxx benutzt bei der Initialenberechnung
+
+class SwDropCapCache;
+extern SwDropCapCache *pDropCapCache;
+
+/*************************************************************************
+ * class SwDropPortionPart
+ *
+ * A drop portion can consist of one or more parts in order to allow
+ * attribute changes inside them.
+ *************************************************************************/
+
+class SwDropPortionPart
+{
+ SwDropPortionPart* pFollow;
+ SwFont* pFnt;
+ xub_StrLen nLen;
+ sal_uInt16 nWidth;
+
+public:
+ SwDropPortionPart( SwFont& rFont, const xub_StrLen nL )
+ : pFollow( 0 ), pFnt( &rFont ), nLen( nL ), nWidth( 0 ) {};
+ ~SwDropPortionPart();
+
+ inline SwDropPortionPart* GetFollow() const { return pFollow; };
+ inline void SetFollow( SwDropPortionPart* pNew ) { pFollow = pNew; };
+ inline SwFont& GetFont() const { return *pFnt; }
+ inline xub_StrLen GetLen() const { return nLen; }
+ inline sal_uInt16 GetWidth() const { return nWidth; }
+ inline void SetWidth( sal_uInt16 nNew ) { nWidth = nNew; }
+};
+
+/*************************************************************************
+ * class SwDropPortion
+ *************************************************************************/
+
+class SwDropPortion : public SwTxtPortion
+{
+ friend class SwDropCapCache;
+ SwDropPortionPart* pPart; // due to script / attribute changes
+ MSHORT nLines; // Anzahl der Zeilen
+ KSHORT nDropHeight; // Hoehe
+ KSHORT nDropDescent; // Abstand zur naechsten Zeile
+ KSHORT nDistance; // Abstand zum Text
+ KSHORT nFix; // Fixposition
+ short nX; // X-PaintOffset
+ short nY; // Y-Offset
+
+ sal_Bool FormatTxt( SwTxtFormatInfo &rInf );
+ void PaintTxt( const SwTxtPaintInfo &rInf ) const;
+
+ inline void Fix( const KSHORT nNew ) { nFix = nNew; }
+public:
+ SwDropPortion( const MSHORT nLineCnt,
+ const KSHORT nDropHeight,
+ const KSHORT nDropDescent,
+ const KSHORT nDistance );
+ virtual ~SwDropPortion();
+
+ virtual void Paint( const SwTxtPaintInfo &rInf ) const;
+ void PaintDrop( const SwTxtPaintInfo &rInf ) const;
+ virtual sal_Bool Format( SwTxtFormatInfo &rInf );
+ virtual SwPosSize GetTxtSize( const SwTxtSizeInfo &rInfo ) const;
+ virtual xub_StrLen GetCrsrOfst( const MSHORT nOfst ) const;
+
+ inline MSHORT GetLines() const { return nLines; }
+ inline KSHORT GetDistance() const { return nDistance; }
+ inline KSHORT GetDropHeight() const { return nDropHeight; }
+ inline KSHORT GetDropDescent() const { return nDropDescent; }
+ inline KSHORT GetDropLeft() const { return Width() + nFix; }
+
+ inline SwDropPortionPart* GetPart() const { return pPart; }
+ inline void SetPart( SwDropPortionPart* pNew ) { pPart = pNew; }
+
+ inline void SetY( short nNew ) { nY = nNew; }
+
+ inline SwFont* GetFnt() const { return pPart ? &pPart->GetFont() : NULL; }
+
+ static void DeleteDropCapCache();
+
+ OUTPUT_OPERATOR
+};
+
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/text/porexp.cxx b/sw/source/core/text/porexp.cxx
new file mode 100644
index 000000000000..344bc25b1f10
--- /dev/null
+++ b/sw/source/core/text/porexp.cxx
@@ -0,0 +1,314 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+
+#include <viewopt.hxx> // SwViewOptions
+#include <SwPortionHandler.hxx>
+#include <inftxt.hxx>
+#include <porexp.hxx>
+
+/*************************************************************************
+ * class SwExpandPortion
+ *************************************************************************/
+
+xub_StrLen SwExpandPortion::GetCrsrOfst( const MSHORT nOfst ) const
+{ return SwLinePortion::GetCrsrOfst( nOfst ); }
+
+/*************************************************************************
+ * virtual SwExpandPortion::GetExpTxt()
+ *************************************************************************/
+
+sal_Bool SwExpandPortion::GetExpTxt( const SwTxtSizeInfo&,
+ XubString &rTxt ) const
+{
+ rTxt.Erase();
+ // Nicht etwa: return 0 != rTxt.Len();
+ // Weil: leere Felder ersetzen CH_TXTATR gegen einen Leerstring
+ return sal_True;
+}
+
+/*************************************************************************
+ * virtual SwExpandPortion::HandlePortion()
+ *************************************************************************/
+
+void SwExpandPortion::HandlePortion( SwPortionHandler& rPH ) const
+{
+ String aString;
+ rPH.Special( GetLen(), aString, GetWhichPor() );
+}
+
+/*************************************************************************
+ * virtual SwExpandPortion::GetTxtSize()
+ *************************************************************************/
+
+SwPosSize SwExpandPortion::GetTxtSize( const SwTxtSizeInfo &rInf ) const
+{
+ SwTxtSlot aDiffTxt( &rInf, this, false, false );
+ return rInf.GetTxtSize();
+}
+
+/*************************************************************************
+ * virtual SwExpandPortion::Format()
+ *************************************************************************/
+
+// 5010: Exp und Tabs
+
+sal_Bool SwExpandPortion::Format( SwTxtFormatInfo &rInf )
+{
+ SwTxtSlot aDiffTxt( &rInf, this, true, false );
+ const xub_StrLen nFullLen = rInf.GetLen();
+
+ // So komisch es aussieht, die Abfrage auf GetLen() muss wegen der
+ // ExpandPortions _hinter_ aDiffTxt (vgl. SoftHyphs)
+ // sal_False returnen wegen SetFull ...
+ if( !nFullLen )
+ {
+ // nicht Init(), weil wir Hoehe und Ascent brauchen
+ Width(0);
+ return sal_False;
+ }
+ return SwTxtPortion::Format( rInf );
+}
+
+/*************************************************************************
+ * virtual SwExpandPortion::Paint()
+ *************************************************************************/
+
+void SwExpandPortion::Paint( const SwTxtPaintInfo &rInf ) const
+{
+ SwTxtSlot aDiffTxt( &rInf, this, true, true );
+
+ rInf.DrawBackBrush( *this );
+
+ // do we have to repaint a post it portion?
+ if( rInf.OnWin() && pPortion && !pPortion->Width() )
+ pPortion->PrePaint( rInf, this );
+
+ // The contents of field portions is not considered during the
+ // calculation of the directions. Therefore we let vcl handle
+ // the calculation by removing the BIDI_STRONG_FLAG temporarily.
+ SwLayoutModeModifier aLayoutModeModifier( *rInf.GetOut() );
+ aLayoutModeModifier.SetAuto();
+
+ // ST2
+ if ( rInf.GetSmartTags() || rInf.GetGrammarCheckList() )
+ rInf.DrawMarkedText( *this, rInf.GetLen(), sal_False, sal_False,
+ 0 != rInf.GetSmartTags(), 0 != rInf.GetGrammarCheckList() );
+ else
+ rInf.DrawText( *this, rInf.GetLen(), sal_False );
+}
+
+/*************************************************************************
+ * class SwBlankPortion
+ *************************************************************************/
+
+SwLinePortion *SwBlankPortion::Compress() { return this; }
+
+/*************************************************************************
+ * SwBlankPortion::MayUnderFlow()
+ *************************************************************************/
+
+// 5497: Es gibt schon Gemeinheiten auf der Welt...
+// Wenn eine Zeile voll mit HardBlanks ist und diese ueberlaeuft,
+// dann duerfen keine Underflows generiert werden!
+// Komplikationen bei Flys...
+
+MSHORT SwBlankPortion::MayUnderFlow( const SwTxtFormatInfo &rInf,
+ xub_StrLen nIdx, sal_Bool bUnderFlow ) const
+{
+ if( rInf.StopUnderFlow() )
+ return 0;
+ const SwLinePortion *pPos = rInf.GetRoot();
+ if( pPos->GetPortion() )
+ pPos = pPos->GetPortion();
+ while( pPos && pPos->IsBlankPortion() )
+ pPos = pPos->GetPortion();
+ if( !pPos || !rInf.GetIdx() || ( !pPos->GetLen() && pPos == rInf.GetRoot() ) )
+ return 0; // Nur noch BlankPortions unterwegs
+ // Wenn vor uns ein Blank ist, brauchen wir kein Underflow ausloesen,
+ // wenn hinter uns ein Blank ist, brauchen wir kein Underflow weiterreichen
+ if( bUnderFlow && CH_BLANK == rInf.GetTxt().GetChar( nIdx + 1) )
+ return 0;
+ if( nIdx && !((SwTxtFormatInfo&)rInf).GetFly() )
+ {
+ while( pPos && !pPos->IsFlyPortion() )
+ pPos = pPos->GetPortion();
+ if( !pPos )
+ {
+ //Hier wird ueberprueft, ob es in dieser Zeile noch sinnvolle Umbrueche
+ //gibt, Blanks oder Felder etc., wenn nicht, kein Underflow.
+ //Wenn Flys im Spiel sind, lassen wir das Underflow trotzdem zu.
+ xub_StrLen nBlank = nIdx;
+ while( --nBlank > rInf.GetLineStart() )
+ {
+ const xub_Unicode cCh = rInf.GetChar( nBlank );
+ if( CH_BLANK == cCh ||
+ (( CH_TXTATR_BREAKWORD == cCh || CH_TXTATR_INWORD == cCh )
+ && rInf.HasHint( nBlank ) ) )
+ break;
+ }
+ if( nBlank <= rInf.GetLineStart() )
+ return 0;
+ }
+ }
+ xub_Unicode cCh;
+ if( nIdx < 2 || CH_BLANK == (cCh = rInf.GetChar( nIdx - 1 )) )
+ return 1;
+ if( CH_BREAK == cCh )
+ return 0;
+ return 2;
+}
+
+/*************************************************************************
+ * virtual SwBlankPortion::FormatEOL()
+ *************************************************************************/
+// Format end of Line
+
+void SwBlankPortion::FormatEOL( SwTxtFormatInfo &rInf )
+{
+ MSHORT nMay = MayUnderFlow( rInf, rInf.GetIdx() - nLineLength, sal_True );
+ if( nMay )
+ {
+ if( nMay > 1 )
+ {
+ if( rInf.GetLast() == this )
+ rInf.SetLast( FindPrevPortion( rInf.GetRoot() ) );
+ rInf.X( rInf.X() - PrtWidth() );
+ rInf.SetIdx( rInf.GetIdx() - GetLen() );
+ }
+ Truncate();
+ rInf.SetUnderFlow( this );
+ if( rInf.GetLast()->IsKernPortion() )
+ rInf.SetUnderFlow( rInf.GetLast() );
+ }
+}
+
+/*************************************************************************
+ * virtual SwBlankPortion::Format()
+ *************************************************************************/
+
+// 7771: UnderFlows weiterreichen und selbst ausloesen!
+sal_Bool SwBlankPortion::Format( SwTxtFormatInfo &rInf )
+{
+ const sal_Bool bFull = rInf.IsUnderFlow() || SwExpandPortion::Format( rInf );
+ if( bFull && MayUnderFlow( rInf, rInf.GetIdx(), rInf.IsUnderFlow() ) )
+ {
+ Truncate();
+ rInf.SetUnderFlow( this );
+ if( rInf.GetLast()->IsKernPortion() )
+ rInf.SetUnderFlow( rInf.GetLast() );
+ }
+ return bFull;
+}
+
+/*************************************************************************
+ * virtual SwBlankPortion::Paint()
+ *************************************************************************/
+
+void SwBlankPortion::Paint( const SwTxtPaintInfo &rInf ) const
+{
+ if( !bMulti ) // No gray background for multiportion brackets
+ rInf.DrawViewOpt( *this, POR_BLANK );
+ SwExpandPortion::Paint( rInf );
+}
+
+/*************************************************************************
+ * virtual SwBlankPortion::GetExpTxt()
+ *************************************************************************/
+
+sal_Bool SwBlankPortion::GetExpTxt( const SwTxtSizeInfo&, XubString &rTxt ) const
+{
+ rTxt = cChar;
+ return sal_True;
+}
+
+/*************************************************************************
+ * virtual SwBlankPortion::HandlePortion()
+ *************************************************************************/
+
+void SwBlankPortion::HandlePortion( SwPortionHandler& rPH ) const
+{
+ String aString( cChar );
+ rPH.Special( GetLen(), aString, GetWhichPor() );
+}
+
+/*************************************************************************
+ * class SwPostItsPortion
+ *************************************************************************/
+
+SwPostItsPortion::SwPostItsPortion( sal_Bool bScrpt )
+ : nViewWidth(0), bScript( bScrpt )
+{
+ nLineLength = 1;
+ SetWhichPor( POR_POSTITS );
+}
+
+void SwPostItsPortion::Paint( const SwTxtPaintInfo &rInf ) const
+{
+ if( rInf.OnWin() && Width() )
+ rInf.DrawPostIts( *this, IsScript() );
+}
+
+KSHORT SwPostItsPortion::GetViewWidth( const SwTxtSizeInfo &rInf ) const
+{
+ // Nicht zu fassen: PostIts sind immer zu sehen.
+ return rInf.OnWin() ?
+ (KSHORT)rInf.GetOpt().GetPostItsWidth( rInf.GetOut() ) : 0;
+}
+
+/*************************************************************************
+ * virtual SwPostItsPortion::Format()
+ *************************************************************************/
+
+sal_Bool SwPostItsPortion::Format( SwTxtFormatInfo &rInf )
+{
+ sal_Bool bRet = SwLinePortion::Format( rInf );
+ // 32749: PostIts sollen keine Auswirkung auf Zeilenhoehe etc. haben
+ SetAscent( 1 );
+ Height( 1 );
+ return bRet;
+}
+
+/*************************************************************************
+ * virtual SwPostItsPortion::GetExpTxt()
+ *************************************************************************/
+
+sal_Bool SwPostItsPortion::GetExpTxt( const SwTxtSizeInfo &rInf,
+ XubString &rTxt ) const
+{
+ if( rInf.OnWin() && rInf.GetOpt().IsPostIts() )
+ rTxt = ' ';
+ else
+ rTxt.Erase();
+ return sal_True;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/text/porexp.hxx b/sw/source/core/text/porexp.hxx
new file mode 100644
index 000000000000..5761431810f5
--- /dev/null
+++ b/sw/source/core/text/porexp.hxx
@@ -0,0 +1,111 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef _POREXP_HXX
+#define _POREXP_HXX
+
+#include "portxt.hxx"
+
+/*************************************************************************
+ * class SwExpandPortion
+ *************************************************************************/
+
+class SwExpandPortion : public SwTxtPortion
+{
+public:
+ inline SwExpandPortion() { SetWhichPor( POR_EXP ); }
+ virtual sal_Bool Format( SwTxtFormatInfo &rInf );
+ virtual xub_StrLen GetCrsrOfst( const MSHORT nOfst ) const;
+ virtual sal_Bool GetExpTxt( const SwTxtSizeInfo &rInf, XubString &rTxt ) const;
+ virtual SwPosSize GetTxtSize( const SwTxtSizeInfo &rInfo ) const;
+ virtual void Paint( const SwTxtPaintInfo &rInf ) const;
+
+ // Accessibility: pass information about this portion to the PortionHandler
+ virtual void HandlePortion( SwPortionHandler& rPH ) const;
+
+ OUTPUT_OPERATOR
+};
+
+
+/*************************************************************************
+ * class SwBlankPortion
+ *************************************************************************/
+
+class SwBlankPortion : public SwExpandPortion
+{
+ xub_Unicode cChar;
+ sal_Bool bMulti; // For multiportion brackets
+public:
+ inline SwBlankPortion( xub_Unicode cCh, sal_Bool bMult = sal_False )
+ : cChar( cCh ), bMulti( bMult )
+ { cChar = cCh; SetLen(1); SetWhichPor( POR_BLANK ); }
+
+ sal_Bool IsMulti() const { return bMulti; }
+ void SetMulti( sal_Bool bNew ) { bMulti = bNew; }
+
+ virtual SwLinePortion *Compress();
+ virtual sal_Bool GetExpTxt( const SwTxtSizeInfo &rInf, XubString &rTxt ) const;
+ virtual void FormatEOL( SwTxtFormatInfo &rInf );
+ virtual sal_Bool Format( SwTxtFormatInfo &rInf );
+ virtual void Paint( const SwTxtPaintInfo &rInf ) const;
+ MSHORT MayUnderFlow( const SwTxtFormatInfo &rInf, xub_StrLen nIdx,
+ sal_Bool bUnderFlow ) const;
+
+ // Accessibility: pass information about this portion to the PortionHandler
+ virtual void HandlePortion( SwPortionHandler& rPH ) const;
+
+ OUTPUT_OPERATOR
+};
+
+/*************************************************************************
+ * class SwPostItsPortion
+ *************************************************************************/
+
+class SwPostItsPortion : public SwExpandPortion
+{
+ KSHORT nViewWidth;
+ sal_Bool bScript;
+public:
+ SwPostItsPortion( sal_Bool bScrpt );
+ virtual void Paint( const SwTxtPaintInfo &rInf ) const;
+ virtual sal_Bool Format( SwTxtFormatInfo &rInf );
+ virtual KSHORT GetViewWidth( const SwTxtSizeInfo &rInf ) const;
+ virtual sal_Bool GetExpTxt( const SwTxtSizeInfo &rInf, XubString &rTxt ) const;
+ sal_Bool IsScript() const { return bScript; }
+ OUTPUT_OPERATOR
+};
+
+
+CLASSIO( SwExpandPortion )
+CLASSIO( SwBlankPortion )
+CLASSIO( SwPostItsPortion )
+
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/text/porfld.cxx b/sw/source/core/text/porfld.cxx
new file mode 100644
index 000000000000..e6548d6add0c
--- /dev/null
+++ b/sw/source/core/text/porfld.cxx
@@ -0,0 +1,1374 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+
+#include <hintids.hxx>
+
+#include <com/sun/star/i18n/ScriptType.hdl>
+#include <vcl/graph.hxx>
+#include <editeng/brshitem.hxx>
+#include <vcl/metric.hxx>
+#include <vcl/outdev.hxx>
+#include <viewopt.hxx> // SwViewOptions
+#include <SwPortionHandler.hxx>
+#include <porlay.hxx>
+#include <porfld.hxx>
+#include <inftxt.hxx>
+#include <blink.hxx> // pBlink
+#include <frmtool.hxx> // DrawGraphic
+#include <viewsh.hxx>
+#include <docsh.hxx>
+#include <doc.hxx>
+#include "rootfrm.hxx"
+#include <breakit.hxx>
+#include <porrst.hxx>
+#include <porftn.hxx> // SwFtnPortion
+#include <accessibilityoptions.hxx>
+#include <editeng/lrspitem.hxx>
+
+#include <unicode/ubidi.h>
+
+using namespace ::com::sun::star;
+
+/*************************************************************************
+ * class SwFldPortion
+ *************************************************************************/
+
+SwLinePortion *SwFldPortion::Compress()
+{ return (GetLen() || aExpand.Len() || SwLinePortion::Compress()) ? this : 0; }
+
+SwFldPortion *SwFldPortion::Clone( const XubString &rExpand ) const
+{
+ SwFont *pNewFnt;
+ if( 0 != ( pNewFnt = pFnt ) )
+ {
+ pNewFnt = new SwFont( *pFnt );
+ }
+ // --> OD 2009-11-25 #i107143#
+ // pass placeholder property to created <SwFldPortion> instance.
+ SwFldPortion* pClone = new SwFldPortion( rExpand, pNewFnt, bPlaceHolder );
+ // <--
+ pClone->SetNextOffset( nNextOffset );
+ pClone->m_bNoLength = this->m_bNoLength;
+ return pClone;
+}
+
+void SwFldPortion::TakeNextOffset( const SwFldPortion* pFld )
+{
+ OSL_ENSURE( pFld, "TakeNextOffset: Missing Source" );
+ nNextOffset = pFld->GetNextOffset();
+ aExpand.Erase( 0, nNextOffset );
+ bFollow = sal_True;
+}
+
+SwFldPortion::SwFldPortion( const XubString &rExpand, SwFont *pFont, sal_Bool bPlaceHold )
+ : aExpand(rExpand), pFnt(pFont), nNextOffset(0), nNextScriptChg(STRING_LEN), nViewWidth(0),
+ bFollow( sal_False ), bHasFollow( sal_False ), bPlaceHolder( bPlaceHold )
+ , m_bNoLength( sal_False )
+{
+ SetWhichPor( POR_FLD );
+}
+
+SwFldPortion::SwFldPortion( const SwFldPortion& rFld )
+ : SwExpandPortion( rFld ),
+ aExpand( rFld.GetExp() ),
+ nNextOffset( rFld.GetNextOffset() ),
+ nNextScriptChg( rFld.GetNextScriptChg() ),
+ bFollow( rFld.IsFollow() ),
+ bLeft( rFld.IsLeft() ),
+ bHide( rFld.IsHide() ),
+ bCenter( rFld.IsCenter() ),
+ bHasFollow( rFld.HasFollow() ),
+ bPlaceHolder( rFld.bPlaceHolder )
+ , m_bNoLength( rFld.m_bNoLength )
+{
+ if ( rFld.HasFont() )
+ pFnt = new SwFont( *rFld.GetFont() );
+ else
+ pFnt = 0;
+
+ SetWhichPor( POR_FLD );
+}
+
+SwFldPortion::~SwFldPortion()
+{
+ delete pFnt;
+ if( pBlink )
+ pBlink->Delete( this );
+}
+
+/*************************************************************************
+ * virtual SwFldPortion::GetViewWidth()
+ *************************************************************************/
+
+KSHORT SwFldPortion::GetViewWidth( const SwTxtSizeInfo &rInf ) const
+{
+ // Wir stehen zwar im const, aber nViewWidth sollte erst im letzten
+ // Moment errechnet werden:
+ SwFldPortion* pThis = (SwFldPortion*)this;
+ if( !Width() && rInf.OnWin() && !rInf.GetOpt().IsPagePreview() &&
+ !rInf.GetOpt().IsReadonly() && SwViewOption::IsFieldShadings() )
+ {
+ if( !nViewWidth )
+ pThis->nViewWidth = rInf.GetTxtSize( ' ' ).Width();
+ }
+ else
+ pThis->nViewWidth = 0;
+ return nViewWidth;
+}
+
+/*************************************************************************
+ * virtual SwFldPortion::Format()
+ *************************************************************************/
+
+// 8653: in keinem Fall nur SetLen(0);
+
+/*************************************************************************
+ * Hilfsklasse SwFldSlot
+ **************************************************************************/
+
+class SwFldSlot
+{
+ const XubString *pOldTxt;
+ XubString aTxt;
+ xub_StrLen nIdx;
+ xub_StrLen nLen;
+ sal_Bool bOn;
+ SwTxtFormatInfo *pInf;
+public:
+ SwFldSlot( const SwTxtFormatInfo* pNew, const SwFldPortion *pPor );
+ ~SwFldSlot();
+};
+
+SwFldSlot::SwFldSlot( const SwTxtFormatInfo* pNew, const SwFldPortion *pPor )
+{
+ bOn = pPor->GetExpTxt( *pNew, aTxt );
+
+ // Der Text wird ausgetauscht...
+ if( bOn )
+ {
+ pInf = (SwTxtFormatInfo*)pNew;
+ nIdx = pInf->GetIdx();
+ nLen = pInf->GetLen();
+ pOldTxt = &(pInf->GetTxt());
+ pInf->SetLen( aTxt.Len() );
+ if( pPor->IsFollow() )
+ {
+ pInf->SetFakeLineStart( nIdx > pInf->GetLineStart() );
+ pInf->SetIdx( 0 );
+ }
+ else
+ {
+ XubString aTmp( aTxt );
+ aTxt = *pOldTxt;
+ aTxt.Erase( nIdx, 1 );
+ aTxt.Insert( aTmp, nIdx );
+ }
+ pInf->SetTxt( aTxt );
+ }
+}
+
+SwFldSlot::~SwFldSlot()
+{
+ if( bOn )
+ {
+ pInf->SetTxt( *pOldTxt );
+ pInf->SetIdx( nIdx );
+ pInf->SetLen( nLen );
+ pInf->SetFakeLineStart( sal_False );
+ }
+}
+
+void SwFldPortion::CheckScript( const SwTxtSizeInfo &rInf )
+{
+ String aTxt;
+ if( GetExpTxt( rInf, aTxt ) && aTxt.Len() && pBreakIt->GetBreakIter().is() )
+ {
+ sal_uInt8 nActual = pFnt ? pFnt->GetActual() : rInf.GetFont()->GetActual();
+ sal_uInt16 nScript;
+ {
+ nScript = pBreakIt->GetBreakIter()->getScriptType( aTxt, 0 );
+ xub_StrLen nChg = 0;
+ if( i18n::ScriptType::WEAK == nScript )
+ {
+ nChg =(xub_StrLen)pBreakIt->GetBreakIter()->endOfScript(aTxt,0,nScript);
+ if( nChg < aTxt.Len() )
+ nScript = pBreakIt->GetBreakIter()->getScriptType( aTxt, nChg );
+ }
+
+ //
+ // nNextScriptChg will be evaluated during SwFldPortion::Format()
+ //
+ if ( nChg < aTxt.Len() )
+ nNextScriptChg = (xub_StrLen)pBreakIt->GetBreakIter()->endOfScript( aTxt, nChg, nScript );
+ else
+ nNextScriptChg = aTxt.Len();
+
+ }
+ sal_uInt8 nTmp;
+ switch ( nScript ) {
+ case i18n::ScriptType::LATIN : nTmp = SW_LATIN; break;
+ case i18n::ScriptType::ASIAN : nTmp = SW_CJK; break;
+ case i18n::ScriptType::COMPLEX : nTmp = SW_CTL; break;
+ default: nTmp = nActual;
+ }
+
+ // #i16354# Change script type for RTL text to CTL.
+ const SwScriptInfo& rSI = rInf.GetParaPortion()->GetScriptInfo();
+ // --> OD 2009-01-29 #i98418#
+// const sal_uInt8 nFldDir = IsNumberPortion() ?
+ const sal_uInt8 nFldDir = ( IsNumberPortion() || IsFtnNumPortion() ) ?
+ rSI.GetDefaultDir() :
+ rSI.DirType( IsFollow() ? rInf.GetIdx() - 1 : rInf.GetIdx() );
+ // <--
+ if ( UBIDI_RTL == nFldDir )
+ {
+ UErrorCode nError = U_ZERO_ERROR;
+ UBiDi* pBidi = ubidi_openSized( aTxt.Len(), 0, &nError );
+ ubidi_setPara( pBidi, reinterpret_cast<const UChar *>(aTxt.GetBuffer()), aTxt.Len(), nFldDir, NULL, &nError );
+ int32_t nEnd;
+ UBiDiLevel nCurrDir;
+ ubidi_getLogicalRun( pBidi, 0, &nEnd, &nCurrDir );
+ ubidi_close( pBidi );
+ const xub_StrLen nNextDirChg = (xub_StrLen)nEnd;
+ nNextScriptChg = Min( nNextScriptChg, nNextDirChg );
+
+ // #i89825# change the script type also to CTL
+ // if there is no strong LTR char in the LTR run (numbers)
+ if ( nCurrDir != UBIDI_RTL )
+ {
+ nCurrDir = UBIDI_RTL;
+ for ( xub_StrLen nCharIdx = 0; nCharIdx < nEnd; ++nCharIdx )
+ {
+ UCharDirection nCharDir = u_charDirection ( aTxt.GetChar ( nCharIdx ));
+ if ( nCharDir == U_LEFT_TO_RIGHT ||
+ nCharDir == U_LEFT_TO_RIGHT_EMBEDDING ||
+ nCharDir == U_LEFT_TO_RIGHT_OVERRIDE )
+ {
+ nCurrDir = UBIDI_LTR;
+ break;
+ }
+ }
+ }
+
+ if ( nCurrDir == UBIDI_RTL )
+ nTmp = SW_CTL;
+ }
+
+ // --> OD 2009-01-29 #i98418#
+ // keep determined script type for footnote portions as preferred script type.
+ // For footnote portions a font can not be created directly - see footnote
+ // portion format method.
+// if( !IsFtnPortion() && nTmp != nActual )
+ if ( IsFtnPortion() )
+ {
+ dynamic_cast<SwFtnPortion*>(this)->SetPreferredScriptType( nTmp );
+ }
+ else if ( nTmp != nActual )
+ {
+ if( !pFnt )
+ pFnt = new SwFont( *rInf.GetFont() );
+ pFnt->SetActual( nTmp );
+ }
+ // <--
+ }
+}
+
+sal_Bool SwFldPortion::Format( SwTxtFormatInfo &rInf )
+{
+ // Scope wegen aDiffTxt::DTOR!
+ xub_StrLen nRest;
+ sal_Bool bFull;
+ sal_Bool bEOL = sal_False;
+ long nTxtRest = rInf.GetTxt().Len() - rInf.GetIdx();
+ {
+ SwFldSlot aDiffTxt( &rInf, this );
+ SwLayoutModeModifier aLayoutModeModifier( *rInf.GetOut() );
+ aLayoutModeModifier.SetAuto();
+
+ // Field portion has to be split in several parts if
+ // 1. There are script/direction changes inside the field
+ // 2. There are portion breaks (tab, break) inside the field:
+ const xub_StrLen nOldFullLen = rInf.GetLen();
+ xub_StrLen nFullLen = rInf.ScanPortionEnd( rInf.GetIdx(), rInf.GetIdx() + nOldFullLen ) - rInf.GetIdx();
+ if ( nNextScriptChg < nFullLen )
+ {
+ nFullLen = nNextScriptChg;
+ rInf.SetHookChar( 0 );
+ }
+ rInf.SetLen( nFullLen );
+
+ if ( STRING_LEN != rInf.GetUnderScorePos() &&
+ rInf.GetUnderScorePos() > rInf.GetIdx() )
+ rInf.SetUnderScorePos( rInf.GetIdx() );
+
+ if( pFnt )
+ pFnt->GoMagic( rInf.GetVsh(), pFnt->GetActual() );
+
+ SwFontSave aSave( rInf, pFnt );
+
+ // 8674: Laenge muss 0 sein, bei bFull nach Format ist die Laenge
+ // gesetzt und wird in nRest uebertragen. Ansonsten bleibt die
+ // Laenge erhalten und wuerde auch in nRest einfliessen!
+ SetLen(0);
+ const MSHORT nFollow = IsFollow() ? 0 : 1;
+
+ // So komisch es aussieht, die Abfrage auf GetLen() muss wegen der
+ // ExpandPortions _hinter_ aDiffTxt (vgl. SoftHyphs)
+ // sal_False returnen wegen SetFull ...
+ if( !nFullLen )
+ {
+ // nicht Init(), weil wir Hoehe und Ascent brauchen
+ Width(0);
+ bFull = rInf.Width() <= rInf.GetPos().X();
+ }
+ else
+ {
+ xub_StrLen nOldLineStart = rInf.GetLineStart();
+ if( IsFollow() )
+ rInf.SetLineStart( 0 );
+ rInf.SetNotEOL( nFullLen == nOldFullLen && nTxtRest > nFollow );
+
+ // the height depending on the fields font is set,
+ // this is required for SwTxtGuess::Guess
+ Height( rInf.GetTxtHeight() );
+ // If a kerning portion is inserted after our field portion,
+ // the ascent and height must be known
+ SetAscent( rInf.GetAscent() );
+ bFull = SwTxtPortion::Format( rInf );
+ rInf.SetNotEOL( sal_False );
+ rInf.SetLineStart( nOldLineStart );
+ }
+ xub_StrLen nTmpLen = GetLen();
+ bEOL = !nTmpLen && nFollow && bFull;
+ nRest = nOldFullLen - nTmpLen;
+
+ // Das Zeichen wird in der ersten Portion gehalten.
+ // Unbedingt nach Format!
+ SetLen( (m_bNoLength) ? 0 : nFollow );
+
+ if( nRest )
+ {
+ // aExpand ist noch nicht gekuerzt worden, der neue Ofst
+ // ergibt sich durch nRest.
+ xub_StrLen nNextOfst = aExpand.Len() - nRest;
+
+ if ( IsQuoVadisPortion() )
+ nNextOfst = nNextOfst + ((SwQuoVadisPortion*)this)->GetContTxt().Len();
+
+ XubString aNew( aExpand, nNextOfst, STRING_LEN );
+ aExpand.Erase( nNextOfst, STRING_LEN );
+
+ // These characters should not be contained in the follow
+ // field portion. They are handled via the HookChar mechanism.
+ switch( aNew.GetChar( 0 ))
+ {
+ case CH_BREAK : bFull = sal_True;
+ // kein break;
+ case ' ' :
+ case CH_TAB :
+ case CHAR_HARDHYPHEN: // non-breaking hyphen
+ case CHAR_SOFTHYPHEN:
+ case CHAR_HARDBLANK:
+ // --> FME 2006-01-11 #i59759# Erase additional control
+ // characters from field string, otherwise we get stuck in
+ // a loop.
+ case CHAR_ZWSP :
+ case CHAR_ZWNBSP :
+ // case CHAR_RLM :
+ // case CHAR_LRM :
+ // <--
+ // --> OD 2010-06-03 #i111750#
+ // - Erasing further control characters from field string in
+ // to avoid loop.
+ case CH_TXTATR_BREAKWORD:
+ case CH_TXTATR_INWORD:
+ // <--
+ {
+ aNew.Erase( 0, 1 );
+ ++nNextOfst;
+ break;
+ }
+ default: ;
+ }
+
+ // Even if there is no more text left for a follow field,
+ // we have to build a follow field portion (without font),
+ // otherwise the HookChar mechanism would not work.
+ SwFldPortion *pFld = Clone( aNew );
+ if( aNew.Len() && !pFld->GetFont() )
+ {
+ SwFont *pNewFnt = new SwFont( *rInf.GetFont() );
+ pFld->SetFont( pNewFnt );
+ }
+ pFld->SetFollow( sal_True );
+ SetHasFollow( sal_True );
+ // In nNextOffset steht bei einem neuangelegten Feld zunaechst
+ // der Offset, an dem es selbst im Originalstring beginnt.
+ // Wenn beim Formatieren ein FollowFeld angelegt wird, wird
+ // der Offset dieses FollowFelds in nNextOffset festgehalten.
+ nNextOffset = nNextOffset + nNextOfst;
+ pFld->SetNextOffset( nNextOffset );
+ rInf.SetRest( pFld );
+ }
+ }
+
+ if( bEOL && rInf.GetLast() && !rInf.GetUnderFlow() )
+ rInf.GetLast()->FormatEOL( rInf );
+ return bFull;
+}
+
+/*************************************************************************
+ * virtual SwFldPortion::Paint()
+ *************************************************************************/
+
+void SwFldPortion::Paint( const SwTxtPaintInfo &rInf ) const
+{
+ SwFontSave aSave( rInf, pFnt );
+
+ OSL_ENSURE( GetLen() <= 1, "SwFldPortion::Paint: rest-portion polution?" );
+ if( Width() && ( !bPlaceHolder || rInf.GetOpt().IsShowPlaceHolderFields() ) )
+ {
+ // Dies ist eine freizuegige Auslegung der Hintergrundbelegung ...
+ rInf.DrawViewOpt( *this, POR_FLD );
+ SwExpandPortion::Paint( rInf );
+ }
+}
+
+/*************************************************************************
+ * virtual SwFldPortion::GetExpTxt()
+ *************************************************************************/
+
+sal_Bool SwFldPortion::GetExpTxt( const SwTxtSizeInfo &rInf, XubString &rTxt ) const
+{
+ rTxt = aExpand;
+ if( !rTxt.Len() && rInf.OnWin() &&
+ !rInf.GetOpt().IsPagePreview() && !rInf.GetOpt().IsReadonly() &&
+ SwViewOption::IsFieldShadings() &&
+ !HasFollow() )
+ rTxt = ' ';
+ return sal_True;
+}
+
+/*************************************************************************
+ * virtual SwFldPortion::HandlePortion()
+ *************************************************************************/
+
+void SwFldPortion::HandlePortion( SwPortionHandler& rPH ) const
+{
+ rPH.Special( GetLen(), aExpand, GetWhichPor() );
+}
+
+/*************************************************************************
+ * virtual SwFldPortion::GetTxtSize()
+ *************************************************************************/
+
+SwPosSize SwFldPortion::GetTxtSize( const SwTxtSizeInfo &rInf ) const
+{
+ SwFontSave aSave( rInf, pFnt );
+ SwPosSize aSize( SwExpandPortion::GetTxtSize( rInf ) );
+ return aSize;
+}
+
+/*************************************************************************
+ * class SwHiddenPortion
+ *************************************************************************/
+
+SwFldPortion *SwHiddenPortion::Clone(const XubString &rExpand ) const
+{
+ SwFont *pNewFnt;
+ if( 0 != ( pNewFnt = pFnt ) )
+ pNewFnt = new SwFont( *pFnt );
+ return new SwHiddenPortion( rExpand, pNewFnt );
+}
+
+/*************************************************************************
+ * virtual SwHiddenPortion::Paint()
+ *************************************************************************/
+
+void SwHiddenPortion::Paint( const SwTxtPaintInfo &rInf ) const
+{
+ if( Width() )
+ {
+ SwFontSave aSave( rInf, pFnt );
+ rInf.DrawViewOpt( *this, POR_HIDDEN );
+ SwExpandPortion::Paint( rInf );
+ }
+}
+
+/*************************************************************************
+ * virtual SwHiddenPortion::GetExpTxt()
+ *************************************************************************/
+
+sal_Bool SwHiddenPortion::GetExpTxt( const SwTxtSizeInfo &rInf, XubString &rTxt ) const
+{
+ // Nicht auf IsHidden() abfragen !
+ return SwFldPortion::GetExpTxt( rInf, rTxt );
+}
+
+/*************************************************************************
+ * class SwNumberPortion
+ *************************************************************************/
+
+SwNumberPortion::SwNumberPortion( const XubString &rExpand,
+ SwFont *pFont,
+ const sal_Bool bLft,
+ const sal_Bool bCntr,
+ const KSHORT nMinDst,
+ const bool bLabelAlignmentPosAndSpaceModeActive )
+ : SwFldPortion( rExpand, pFont ),
+ nFixWidth(0),
+ nMinDist( nMinDst ),
+ mbLabelAlignmentPosAndSpaceModeActive( bLabelAlignmentPosAndSpaceModeActive )
+{
+ SetWhichPor( POR_NUMBER );
+ SetLeft( bLft );
+ SetHide( sal_False );
+ SetCenter( bCntr );
+}
+
+xub_StrLen SwNumberPortion::GetCrsrOfst( const MSHORT ) const
+{
+ return 0;
+}
+
+SwFldPortion *SwNumberPortion::Clone( const XubString &rExpand ) const
+{
+ SwFont *pNewFnt;
+ if( 0 != ( pNewFnt = pFnt ) )
+ pNewFnt = new SwFont( *pFnt );
+
+ return new SwNumberPortion( rExpand, pNewFnt, IsLeft(), IsCenter(),
+ nMinDist, mbLabelAlignmentPosAndSpaceModeActive );
+}
+
+/*************************************************************************
+ * virtual SwNumberPortion::Format()
+ *************************************************************************/
+
+// 5010: Wir sind in der Lage, mehrzeilige NumFelder anzulegen!
+// 3689: Fies ist, wenn man in der Dialogbox soviel Davor-Text
+// eingibt, bis die Zeile ueberlaeuft.
+// Man muss die Fly-Ausweichmanoever beachten!
+
+sal_Bool SwNumberPortion::Format( SwTxtFormatInfo &rInf )
+{
+ SetHide( sal_False );
+ const sal_Bool bFull = SwFldPortion::Format( rInf );
+ SetLen( 0 );
+ // a numbering portion can be contained in a rotated portion!!!
+ nFixWidth = rInf.IsMulti() ? Height() : Width();
+ rInf.SetNumDone( !rInf.GetRest() );
+ if( rInf.IsNumDone() )
+ {
+// SetAscent( rInf.GetAscent() );
+ OSL_ENSURE( Height() && nAscent, "NumberPortions without Height | Ascent" );
+
+ long nDiff( 0 );
+
+ if ( !mbLabelAlignmentPosAndSpaceModeActive )
+ {
+ if ( !rInf.GetTxtFrm()->GetTxtNode()->getIDocumentSettingAccess()->get(IDocumentSettingAccess::IGNORE_FIRST_LINE_INDENT_IN_NUMBERING) &&
+ // --> FME 2004-08-13 #i32902#
+ !IsFtnNumPortion() )
+ // <--
+ {
+ nDiff = rInf.Left()
+ + rInf.GetTxtFrm()->GetTxtNode()->
+ GetSwAttrSet().GetLRSpace().GetTxtFirstLineOfst()
+ - rInf.First()
+ + rInf.ForcedLeftMargin();
+ }
+ else
+ {
+ nDiff = rInf.Left() - rInf.First() + rInf.ForcedLeftMargin();
+ }
+ }
+ // Ein Vorschlag von Juergen und Volkmar:
+ // Der Textteil hinter der Numerierung sollte immer
+ // mindestens beim linken Rand beginnen.
+ if( nDiff < 0 )
+ nDiff = 0;
+ else if ( nDiff > rInf.X() )
+ nDiff -= rInf.X();
+ else
+ nDiff = 0;
+
+ if( nDiff < nFixWidth + nMinDist )
+ nDiff = nFixWidth + nMinDist;
+ // 2739: Numerierung weicht Fly aus, kein nDiff in der zweiten Runde
+ // fieser Sonderfall: FlyFrm liegt in dem Bereich,
+ // den wir uns gerade unter den Nagel reissen wollen.
+ // Die NumberPortion wird als verborgen markiert.
+ const sal_Bool bFly = rInf.GetFly() ||
+ ( rInf.GetLast() && rInf.GetLast()->IsFlyPortion() );
+ if( nDiff > rInf.Width() )
+ {
+ nDiff = rInf.Width();
+ if ( bFly )
+ SetHide( sal_True );
+ }
+
+ // A numbering portion can be inside a SwRotatedPortion. Then the
+ // Height has to be changed
+ if ( rInf.IsMulti() )
+ {
+ if ( Height() < nDiff )
+ Height( KSHORT( nDiff ) );
+ }
+ else if( Width() < nDiff )
+ Width( KSHORT(nDiff) );
+ }
+ return bFull;
+}
+
+void SwNumberPortion::FormatEOL( SwTxtFormatInfo& )
+{
+/* Ein FormatEOL deutet daraufhin, dass der folgende Text
+ * nicht mit auf die Zeile passte. Damit die Numerierung mitwandert,
+ * wird diese NumberPortion verborgen.
+ */
+
+ // This caused trouble with flys anchored as characters.
+ // If one of these is numbered but does not fit to the line,
+ // it calls this function, causing a loop because both the number
+ // portion and the fly portion go to the next line
+// SetHide( sal_True );
+}
+
+/*************************************************************************
+ * virtual SwNumberPortion::Paint()
+ *************************************************************************/
+
+void SwNumberPortion::Paint( const SwTxtPaintInfo &rInf ) const
+{
+/* Eine verborgene NumberPortion wird nicht angezeigt, es sei denn, es gibt
+ * Textportions in dieser Zeile oder es gibt ueberhaupt nur eine einzige Zeile.
+ */
+
+ if ( IsHide() && rInf.GetParaPortion() && rInf.GetParaPortion()->GetNext() )
+ {
+ SwLinePortion *pTmp = GetPortion();
+ while ( pTmp && !pTmp->InTxtGrp() )
+ pTmp = pTmp->GetPortion();
+ if ( !pTmp )
+ return;
+ }
+
+ // calculate the width of the number portion, including follows
+ const KSHORT nOldWidth = Width();
+ sal_uInt16 nSumWidth = 0;
+ sal_uInt16 nOffset = 0;
+
+ const SwLinePortion* pTmp = this;
+ while ( pTmp && pTmp->InNumberGrp() )
+ {
+ nSumWidth = nSumWidth + pTmp->Width();
+ if ( ((SwNumberPortion*)pTmp)->HasFollow() )
+ pTmp = pTmp->GetPortion();
+ else
+ {
+ nOffset = pTmp->Width() - ((SwNumberPortion*)pTmp)->nFixWidth;
+ break;
+ }
+ }
+
+ // The master portion takes care for painting the background of the
+ // follow field portions
+ if ( ! IsFollow() )
+ {
+ SwLinePortion *pThis = (SwLinePortion*)this;
+ pThis->Width( nSumWidth );
+ rInf.DrawViewOpt( *this, POR_NUMBER );
+ pThis->Width( nOldWidth );
+ }
+
+ if( aExpand.Len() )
+ {
+ const SwFont *pTmpFnt = rInf.GetFont();
+ sal_Bool bPaintSpace = ( UNDERLINE_NONE != pTmpFnt->GetUnderline() ||
+ UNDERLINE_NONE != pTmpFnt->GetOverline() ||
+ STRIKEOUT_NONE != pTmpFnt->GetStrikeout() ) &&
+ !pTmpFnt->IsWordLineMode();
+ if( bPaintSpace && pFnt )
+ bPaintSpace = ( UNDERLINE_NONE != pFnt->GetUnderline() ||
+ UNDERLINE_NONE != pFnt->GetOverline() ||
+ STRIKEOUT_NONE != pFnt->GetStrikeout() ) &&
+ !pFnt->IsWordLineMode();
+
+ SwFontSave aSave( rInf, pFnt );
+
+ if( nFixWidth == Width() && ! HasFollow() )
+ SwExpandPortion::Paint( rInf );
+ else
+ {
+ // logisches const: Width wird wieder zurueckgesetzt
+ SwLinePortion *pThis = (SwLinePortion*)this;
+ bPaintSpace = bPaintSpace && nFixWidth < nOldWidth;
+ KSHORT nSpaceOffs = nFixWidth;
+ pThis->Width( nFixWidth );
+
+ if( ( IsLeft() && ! rInf.GetTxtFrm()->IsRightToLeft() ) ||
+ ( ! IsLeft() && ! IsCenter() && rInf.GetTxtFrm()->IsRightToLeft() ) )
+ SwExpandPortion::Paint( rInf );
+ else
+ {
+ SwTxtPaintInfo aInf( rInf );
+ if( nOffset < nMinDist )
+ nOffset = 0;
+ else
+ {
+ if( IsCenter() )
+ {
+ /* #110778# a / 2 * 2 == a is not a tautology */
+ KSHORT nTmpOffset = nOffset;
+ nOffset /= 2;
+ if( nOffset < nMinDist )
+ nOffset = nTmpOffset - nMinDist;
+ }
+ else
+ nOffset = nOffset - nMinDist;
+ }
+ aInf.X( aInf.X() + nOffset );
+ SwExpandPortion::Paint( aInf );
+ if( bPaintSpace )
+ nSpaceOffs = nSpaceOffs + nOffset;
+ }
+ if( bPaintSpace && nOldWidth > nSpaceOffs )
+ {
+ SwTxtPaintInfo aInf( rInf );
+static sal_Char const sDoubleSpace[] = " ";
+ aInf.X( aInf.X() + nSpaceOffs );
+
+ // --> FME 2005-08-12 #i53199# Adjust position of underline:
+ if ( rInf.GetUnderFnt() )
+ {
+ const Point aNewPos( aInf.GetPos().X(), rInf.GetUnderFnt()->GetPos().Y() );
+ rInf.GetUnderFnt()->SetPos( aNewPos );
+ }
+ // <--
+
+ pThis->Width( nOldWidth - nSpaceOffs + 12 );
+ {
+ SwTxtSlot aDiffTxt( &aInf, this, true, false, sDoubleSpace );
+ aInf.DrawText( *this, aInf.GetLen(), sal_True );
+ }
+ }
+ pThis->Width( nOldWidth );
+ }
+ }
+}
+
+
+/*************************************************************************
+ * class SwBulletPortion
+ *************************************************************************/
+
+SwBulletPortion::SwBulletPortion( const xub_Unicode cBullet,
+ const XubString& rBulletFollowedBy,
+ SwFont *pFont,
+ const sal_Bool bLft,
+ const sal_Bool bCntr,
+ const KSHORT nMinDst,
+ const bool bLabelAlignmentPosAndSpaceModeActive )
+ : SwNumberPortion( XubString( rBulletFollowedBy ).Insert( cBullet, 0 ) ,
+ pFont, bLft, bCntr, nMinDst,
+ bLabelAlignmentPosAndSpaceModeActive )
+{
+ SetWhichPor( POR_BULLET );
+}
+
+/*************************************************************************
+ * class SwGrfNumPortion
+ *************************************************************************/
+
+#define GRFNUM_SECURE 10
+
+SwGrfNumPortion::SwGrfNumPortion(
+ SwFrm*,
+ const XubString& rGraphicFollowedBy,
+ const SvxBrushItem* pGrfBrush,
+ const SwFmtVertOrient* pGrfOrient, const Size& rGrfSize,
+ const sal_Bool bLft, const sal_Bool bCntr, const KSHORT nMinDst,
+ const bool bLabelAlignmentPosAndSpaceModeActive ) :
+ SwNumberPortion( rGraphicFollowedBy, NULL, bLft, bCntr, nMinDst,
+ bLabelAlignmentPosAndSpaceModeActive ),
+ pBrush( new SvxBrushItem(RES_BACKGROUND) ), nId( 0 )
+{
+ SetWhichPor( POR_GRFNUM );
+ SetAnimated( sal_False );
+ bReplace = sal_False;
+ if( pGrfBrush )
+ {
+ *pBrush = *pGrfBrush;
+ const Graphic* pGraph = pGrfBrush->GetGraphic();
+ if( pGraph )
+ SetAnimated( pGraph->IsAnimated() );
+ else
+ bReplace = sal_True;
+ }
+ if( pGrfOrient )
+ {
+ nYPos = pGrfOrient->GetPos();
+ eOrient = pGrfOrient->GetVertOrient();
+ }
+ else
+ {
+ nYPos = 0;
+ eOrient = text::VertOrientation::TOP;
+ }
+ Width( static_cast<sal_uInt16>(rGrfSize.Width() + 2 * GRFNUM_SECURE) );
+ nFixWidth = Width();
+ nGrfHeight = rGrfSize.Height() + 2 * GRFNUM_SECURE;
+ Height( KSHORT(nGrfHeight) );
+ bNoPaint = sal_False;
+}
+
+SwGrfNumPortion::~SwGrfNumPortion()
+{
+ if ( IsAnimated() )
+ ( (Graphic*) pBrush->GetGraphic() )->StopAnimation( 0, nId );
+ delete pBrush;
+}
+
+void SwGrfNumPortion::StopAnimation( OutputDevice* pOut )
+{
+ if ( IsAnimated() )
+ ( (Graphic*) pBrush->GetGraphic() )->StopAnimation( pOut, nId );
+}
+
+sal_Bool SwGrfNumPortion::Format( SwTxtFormatInfo &rInf )
+{
+ SetHide( sal_False );
+// Width( nFixWidth );
+ KSHORT nFollowedByWidth( 0 );
+ if ( mbLabelAlignmentPosAndSpaceModeActive )
+ {
+ SwFldPortion::Format( rInf );
+ nFollowedByWidth = Width();
+ SetLen( 0 );
+ }
+ Width( nFixWidth + nFollowedByWidth );
+ // <--
+ const sal_Bool bFull = rInf.Width() < rInf.X() + Width();
+ const sal_Bool bFly = rInf.GetFly() ||
+ ( rInf.GetLast() && rInf.GetLast()->IsFlyPortion() );
+ SetAscent( static_cast<sal_uInt16>(GetRelPos() > 0 ? GetRelPos() : 0) );
+ if( GetAscent() > Height() )
+ Height( GetAscent() );
+
+ if( bFull )
+ {
+ Width( rInf.Width() - (KSHORT)rInf.X() );
+ if( bFly )
+ {
+ SetLen( 0 );
+ SetNoPaint( sal_True );
+ rInf.SetNumDone( sal_False );
+ return sal_True;
+ }
+ }
+ rInf.SetNumDone( sal_True );
+// long nDiff = rInf.Left() - rInf.First() + rInf.ForcedLeftMargin();
+ long nDiff = mbLabelAlignmentPosAndSpaceModeActive
+ ? 0
+ : rInf.Left() - rInf.First() + rInf.ForcedLeftMargin();
+ // <--
+ // Ein Vorschlag von Juergen und Volkmar:
+ // Der Textteil hinter der Numerierung sollte immer
+ // mindestens beim linken Rand beginnen.
+ if( nDiff < 0 )
+ nDiff = 0;
+ else if ( nDiff > rInf.X() )
+ nDiff -= rInf.X();
+ if( nDiff < nFixWidth + nMinDist )
+ nDiff = nFixWidth + nMinDist;
+ // 2739: Numerierung weicht Fly aus, kein nDiff in der zweiten Runde
+ // fieser Sonderfall: FlyFrm liegt in dem Bereich,
+ // den wir uns gerade unter den Nagel reissen wollen.
+ // Die NumberPortion wird als verborgen markiert.
+ if( nDiff > rInf.Width() )
+ {
+ nDiff = rInf.Width();
+ if( bFly )
+ SetHide( sal_True );
+ }
+
+ if( Width() < nDiff )
+ Width( KSHORT(nDiff) );
+ return bFull;
+}
+
+void SwGrfNumPortion::Paint( const SwTxtPaintInfo &rInf ) const
+{
+ if( DontPaint() )
+ return;
+/* Eine verborgene NumberPortion wird nicht angezeigt, es sei denn, es gibt
+ * Textportions in dieser Zeile oder es gibt ueberhaupt nur eine einzige Zeile.
+ */
+ if ( IsHide() && rInf.GetParaPortion() && rInf.GetParaPortion()->GetNext() )
+ {
+ SwLinePortion *pTmp = GetPortion();
+ while ( pTmp && !pTmp->InTxtGrp() )
+ pTmp = pTmp->GetPortion();
+ if ( !pTmp )
+ return;
+ }
+ Point aPos( rInf.X() + GRFNUM_SECURE, rInf.Y() - GetRelPos() + GRFNUM_SECURE );
+ long nTmpWidth = Max( (long)0, (long)(nFixWidth - 2 * GRFNUM_SECURE) );
+ Size aSize( nTmpWidth, GetGrfHeight() - 2 * GRFNUM_SECURE );
+
+ const sal_Bool bTmpLeft = mbLabelAlignmentPosAndSpaceModeActive ||
+ ( IsLeft() && ! rInf.GetTxtFrm()->IsRightToLeft() ) ||
+ ( ! IsLeft() && ! IsCenter() && rInf.GetTxtFrm()->IsRightToLeft() );
+
+ if( nFixWidth < Width() && !bTmpLeft )
+ {
+ KSHORT nOffset = Width() - nFixWidth;
+ if( nOffset < nMinDist )
+ nOffset = 0;
+ else
+ {
+ if( IsCenter() )
+ {
+ nOffset /= 2;
+ if( nOffset < nMinDist )
+ nOffset = Width() - nFixWidth - nMinDist;
+ }
+ else
+ nOffset = nOffset - nMinDist;
+ }
+ aPos.X() += nOffset;
+ }
+
+ if( bReplace )
+ {
+ KSHORT nTmpH = GetPortion() ? GetPortion()->GetAscent() : 120;
+ aSize = Size( nTmpH, nTmpH );
+ aPos.Y() = rInf.Y() - nTmpH;
+ }
+ SwRect aTmp( aPos, aSize );
+
+ sal_Bool bDraw = sal_True;
+
+ if ( IsAnimated() )
+ {
+ bDraw = !rInf.GetOpt().IsGraphic();
+ if( !nId )
+ {
+ SetId( long( rInf.GetTxtFrm() ) );
+ rInf.GetTxtFrm()->SetAnimation();
+ }
+ if( aTmp.IsOver( rInf.GetPaintRect() ) && !bDraw )
+ {
+ rInf.NoteAnimation();
+ const ViewShell* pViewShell = rInf.GetVsh();
+
+ // virtual device, not pdf export
+ if( OUTDEV_VIRDEV == rInf.GetOut()->GetOutDevType() &&
+ pViewShell && pViewShell->GetWin() )
+ {
+ ( (Graphic*) pBrush->GetGraphic() )->StopAnimation(0,nId);
+ rInf.GetTxtFrm()->getRootFrm()->GetCurrShell()->InvalidateWindows( aTmp );
+ }
+
+
+ else if ( pViewShell &&
+ !pViewShell->GetAccessibilityOptions()->IsStopAnimatedGraphics() &&
+ !pViewShell->IsPreView() &&
+ // --> FME 2004-06-21 #i9684# Stop animation during printing/pdf export.
+ pViewShell->GetWin() )
+ // <--
+ {
+ ( (Graphic*) pBrush->GetGraphic() )->StartAnimation(
+ (OutputDevice*)rInf.GetOut(), aPos, aSize, nId );
+ }
+
+ // pdf export, printing, preview, stop animations...
+ else
+ bDraw = sal_True;
+ }
+ if( bDraw )
+ ( (Graphic*) pBrush->GetGraphic() )->StopAnimation( 0, nId );
+ }
+
+ SwRect aRepaint( rInf.GetPaintRect() );
+ const SwTxtFrm& rFrm = *rInf.GetTxtFrm();
+ if( rFrm.IsVertical() )
+ {
+ rFrm.SwitchHorizontalToVertical( aTmp );
+ rFrm.SwitchHorizontalToVertical( aRepaint );
+ }
+
+ if( rFrm.IsRightToLeft() )
+ {
+ rFrm.SwitchLTRtoRTL( aTmp );
+ rFrm.SwitchLTRtoRTL( aRepaint );
+ }
+
+ if( bDraw && aTmp.HasArea() )
+ DrawGraphic( pBrush, (OutputDevice*)rInf.GetOut(),
+ aTmp, aRepaint, bReplace ? GRFNUM_REPLACE : GRFNUM_YES );
+}
+
+void SwGrfNumPortion::SetBase( long nLnAscent, long nLnDescent,
+ long nFlyAsc, long nFlyDesc )
+{
+ if ( GetOrient() != text::VertOrientation::NONE )
+ {
+ SetRelPos( 0 );
+ if ( GetOrient() == text::VertOrientation::CENTER )
+ SetRelPos( GetGrfHeight() / 2 );
+ else if ( GetOrient() == text::VertOrientation::TOP )
+ SetRelPos( GetGrfHeight() - GRFNUM_SECURE );
+ else if ( GetOrient() == text::VertOrientation::BOTTOM )
+ ;
+ else if ( GetOrient() == text::VertOrientation::CHAR_CENTER )
+ SetRelPos( ( GetGrfHeight() + nLnAscent - nLnDescent ) / 2 );
+ else if ( GetOrient() == text::VertOrientation::CHAR_TOP )
+ SetRelPos( nLnAscent );
+ else if ( GetOrient() == text::VertOrientation::CHAR_BOTTOM )
+ SetRelPos( GetGrfHeight() - nLnDescent );
+ else
+ {
+ if( GetGrfHeight() >= nFlyAsc + nFlyDesc )
+ {
+ // wenn ich genauso gross bin wie die Zeile, brauche ich mich
+ // nicht an der Zeile nicht weiter ausrichten, ich lasse
+ // dann auch den max. Ascent der Zeile unveraendert
+
+ SetRelPos( nFlyAsc );
+ }
+ else if ( GetOrient() == text::VertOrientation::LINE_CENTER )
+ SetRelPos( ( GetGrfHeight() + nFlyAsc - nFlyDesc ) / 2 );
+ else if ( GetOrient() == text::VertOrientation::LINE_TOP )
+ SetRelPos( nFlyAsc );
+ else if ( GetOrient() == text::VertOrientation::LINE_BOTTOM )
+ SetRelPos( GetGrfHeight() - nFlyDesc );
+ }
+ }
+}
+
+void SwTxtFrm::StopAnimation( OutputDevice* pOut )
+{
+ OSL_ENSURE( HasAnimation(), "SwTxtFrm::StopAnimation: Which Animation?" );
+ if( HasPara() )
+ {
+ SwLineLayout *pLine = GetPara();
+ while( pLine )
+ {
+ SwLinePortion *pPor = pLine->GetPortion();
+ while( pPor )
+ {
+ if( pPor->IsGrfNumPortion() )
+ ((SwGrfNumPortion*)pPor)->StopAnimation( pOut );
+ // Die Numerierungsportion sitzt immer vor dem ersten Zeichen,
+ // deshalb koennen wir abbrechen, sobald wir eine Portion mit
+ // einer Laenge > 0 erreicht haben.
+ pPor = pPor->GetLen() ? 0 : pPor->GetPortion();
+ }
+ pLine = pLine->GetLen() ? 0 : pLine->GetNext();
+ }
+ }
+}
+
+/*************************************************************************
+ * SwCombinedPortion::SwCombinedPortion(..)
+ * initializes the script array and clears the width array
+ *************************************************************************/
+
+SwCombinedPortion::SwCombinedPortion( const XubString &rTxt )
+ : SwFldPortion( rTxt )
+{
+ SetLen(1);
+ SetWhichPor( POR_COMBINED );
+ if( aExpand.Len() > 6 )
+ aExpand.Erase( 6 );
+ // Initialization of the scripttype array,
+ // the arrays of width and position are filled by the format function
+ if( pBreakIt->GetBreakIter().is() )
+ {
+ sal_uInt8 nScr = SW_SCRIPTS;
+ for( sal_uInt16 i = 0; i < rTxt.Len(); ++i )
+ {
+ sal_uInt16 nScript = pBreakIt->GetBreakIter()->getScriptType( rTxt, i );
+ switch ( nScript ) {
+ case i18n::ScriptType::LATIN : nScr = SW_LATIN; break;
+ case i18n::ScriptType::ASIAN : nScr = SW_CJK; break;
+ case i18n::ScriptType::COMPLEX : nScr = SW_CTL; break;
+ }
+ aScrType[i] = nScr;
+ }
+ }
+ else
+ {
+ for( sal_uInt16 i = 0; i < 6; aScrType[i++] = 0 )
+ ; // nothing
+ }
+ memset( &aWidth, 0, sizeof(aWidth) );
+}
+
+/*************************************************************************
+ * SwCombinedPortion::Paint(..)
+ *************************************************************************/
+
+void SwCombinedPortion::Paint( const SwTxtPaintInfo &rInf ) const
+{
+ OSL_ENSURE( GetLen() <= 1, "SwFldPortion::Paint: rest-portion polution?" );
+ if( Width() )
+ {
+ rInf.DrawBackBrush( *this );
+ rInf.DrawViewOpt( *this, POR_FLD );
+
+ // do we have to repaint a post it portion?
+ if( rInf.OnWin() && pPortion && !pPortion->Width() )
+ pPortion->PrePaint( rInf, this );
+
+ sal_uInt16 nCount = aExpand.Len();
+ if( !nCount )
+ return;
+ OSL_ENSURE( nCount < 7, "Too much combined characters" );
+
+ // the first character of the second row
+ sal_uInt16 nTop = ( nCount + 1 ) / 2;
+
+ SwFont aTmpFont( *rInf.GetFont() );
+ aTmpFont.SetProportion( nProportion ); // a smaller font
+ SwFontSave aFontSave( rInf, &aTmpFont );
+
+ sal_uInt16 i = 0;
+ Point aOldPos = rInf.GetPos();
+ Point aOutPos( aOldPos.X(), aOldPos.Y() - nUpPos );// Y of the first row
+ while( i < nCount )
+ {
+ if( i == nTop ) // change the row
+ aOutPos.Y() = aOldPos.Y() + nLowPos; // Y of the second row
+ aOutPos.X() = aOldPos.X() + aPos[i]; // X position
+ const sal_uInt8 nAct = aScrType[i]; // script type
+ aTmpFont.SetActual( nAct );
+ // if there're more than 4 characters to display, we choose fonts
+ // with 2/3 of the original font width.
+ if( aWidth[ nAct ] )
+ {
+ Size aTmpSz = aTmpFont.GetSize( nAct );
+ if( aTmpSz.Width() != aWidth[ nAct ] )
+ {
+ aTmpSz.Width() = aWidth[ nAct ];
+ aTmpFont.SetSize( aTmpSz, nAct );
+ }
+ }
+ ((SwTxtPaintInfo&)rInf).SetPos( aOutPos );
+ rInf.DrawText( aExpand, *this, i, 1 );
+ ++i;
+ }
+ // rInf is const, so we have to take back our manipulations
+ ((SwTxtPaintInfo&)rInf).SetPos( aOldPos );
+ }
+}
+
+/*************************************************************************
+ * SwCombinedPortion::Format(..)
+ *************************************************************************/
+
+sal_Bool SwCombinedPortion::Format( SwTxtFormatInfo &rInf )
+{
+ sal_uInt16 nCount = aExpand.Len();
+ if( !nCount )
+ {
+ Width( 0 );
+ return sal_False;
+ }
+
+ OSL_ENSURE( nCount < 7, "Too much combined characters" );
+ // If there are leading "weak"-scripttyped characters in this portion,
+ // they get the actual scripttype.
+ sal_uInt16 i = 0;
+ while( i < nCount && SW_SCRIPTS == aScrType[i] )
+ aScrType[i++] = rInf.GetFont()->GetActual();
+ if( nCount > 4 )
+ {
+ // more than four? Ok, then we need the 2/3 font width
+ i = 0;
+ while( i < aExpand.Len() )
+ {
+ OSL_ENSURE( aScrType[i] < SW_SCRIPTS, "Combined: Script fault" );
+ if( !aWidth[ aScrType[i] ] )
+ {
+ rInf.GetOut()->SetFont( rInf.GetFont()->GetFnt( aScrType[i] ) );
+ aWidth[ aScrType[i] ] =
+ static_cast<sal_uInt16>(2 * rInf.GetOut()->GetFontMetric().GetSize().Width() / 3);
+ }
+ ++i;
+ }
+ }
+
+ sal_uInt16 nTop = ( nCount + 1 ) / 2; // the first character of the second line
+ ViewShell *pSh = rInf.GetTxtFrm()->getRootFrm()->GetCurrShell();
+ SwFont aTmpFont( *rInf.GetFont() );
+ SwFontSave aFontSave( rInf, &aTmpFont );
+ nProportion = 55;
+ // In nMainAscent/Descent we store the ascent and descent
+ // of the original surrounding font
+ sal_uInt16 nMaxDescent, nMaxAscent, nMaxWidth;
+ sal_uInt16 nMainDescent = rInf.GetFont()->GetHeight( pSh, *rInf.GetOut() );
+ const sal_uInt16 nMainAscent = rInf.GetFont()->GetAscent( pSh, *rInf.GetOut() );
+ nMainDescent = nMainDescent - nMainAscent;
+ // we start with a 50% font, but if we notice that the combined portion
+ // becomes bigger than the surrounding font, we check 45% and maybe 40%.
+ do
+ {
+ nProportion -= 5;
+ aTmpFont.SetProportion( nProportion );
+ i = 0;
+ memset( &aPos, 0, sizeof(aPos) );
+ nMaxDescent = 0;
+ nMaxAscent = 0;
+ nMaxWidth = 0;
+ nUpPos = nLowPos = 0;
+
+ // Now we get the width of all characters.
+ // The ascent and the width of the first line are stored in the
+ // ascent member of the portion, the descent in nLowPos.
+ // The ascent, descent and width of the second line are stored in the
+ // local nMaxAscent, nMaxDescent and nMaxWidth variables.
+ while( i < nCount )
+ {
+ sal_uInt8 nScrp = aScrType[i];
+ aTmpFont.SetActual( nScrp );
+ if( aWidth[ nScrp ] )
+ {
+ Size aFontSize( aTmpFont.GetSize( nScrp ) );
+ aFontSize.Width() = aWidth[ nScrp ];
+ aTmpFont.SetSize( aFontSize, nScrp );
+ }
+
+ SwDrawTextInfo aDrawInf( pSh, *rInf.GetOut(), 0, aExpand, i, 1 );
+ Size aSize = aTmpFont._GetTxtSize( aDrawInf );
+ sal_uInt16 nAsc = aTmpFont.GetAscent( pSh, *rInf.GetOut() );
+ aPos[ i ] = (sal_uInt16)aSize.Width();
+ if( i == nTop ) // enter the second line
+ {
+ nLowPos = nMaxDescent;
+ Height( nMaxDescent + nMaxAscent );
+ Width( nMaxWidth );
+ SetAscent( nMaxAscent );
+ nMaxAscent = 0;
+ nMaxDescent = 0;
+ nMaxWidth = 0;
+ }
+ nMaxWidth = nMaxWidth + aPos[ i++ ];
+ if( nAsc > nMaxAscent )
+ nMaxAscent = nAsc;
+ if( aSize.Height() - nAsc > nMaxDescent )
+ nMaxDescent = static_cast<sal_uInt16>(aSize.Height() - nAsc);
+ }
+ // for one or two characters we double the width of the portion
+ if( nCount < 3 )
+ {
+ nMaxWidth *= 2;
+ Width( 2*Width() );
+ if( nCount < 2 )
+ {
+ Height( nMaxAscent + nMaxDescent );
+ nLowPos = nMaxDescent;
+ }
+ }
+ Height( Height() + nMaxDescent + nMaxAscent );
+ nUpPos = nMaxAscent;
+ SetAscent( Height() - nMaxDescent - nLowPos );
+ } while( nProportion > 40 && ( GetAscent() > nMainAscent ||
+ Height() - GetAscent() > nMainDescent ) );
+ // if the combined portion is smaller than the surrounding text,
+ // the portion grows. This looks better, if there's a character background.
+ if( GetAscent() < nMainAscent )
+ {
+ Height( Height() + nMainAscent - GetAscent() );
+ SetAscent( nMainAscent );
+ }
+ if( Height() < nMainAscent + nMainDescent )
+ Height( nMainAscent + nMainDescent );
+
+ // We calculate the x positions of the characters in both lines..
+ sal_uInt16 nTopDiff = 0;
+ sal_uInt16 nBotDiff = 0;
+ if( nMaxWidth > Width() )
+ {
+ nTopDiff = ( nMaxWidth - Width() ) / 2;
+ Width( nMaxWidth );
+ }
+ else
+ nBotDiff = ( Width() - nMaxWidth ) / 2;
+ switch( nTop)
+ {
+ case 3: aPos[1] = aPos[0] + nTopDiff; // no break
+ case 2: aPos[nTop-1] = Width() - aPos[nTop-1];
+ }
+ aPos[0] = 0;
+ switch( nCount )
+ {
+ case 5: aPos[4] = aPos[3] + nBotDiff; // no break
+ case 3: aPos[nTop] = nBotDiff; break;
+ case 6: aPos[4] = aPos[3] + nBotDiff; // no break
+ case 4: aPos[nTop] = 0; // no break
+ case 2: aPos[nCount-1] = Width() - aPos[nCount-1];
+ }
+
+ // Does the combined portion fit the line?
+ const sal_Bool bFull = rInf.Width() < rInf.X() + Width();
+ if( bFull )
+ {
+ if( rInf.GetLineStart() == rInf.GetIdx() && (!rInf.GetLast()->InFldGrp()
+ || !((SwFldPortion*)rInf.GetLast())->IsFollow() ) )
+ Width( (sal_uInt16)( rInf.Width() - rInf.X() ) );
+ else
+ {
+ Truncate();
+ Width( 0 );
+ SetLen( 0 );
+ if( rInf.GetLast() )
+ rInf.GetLast()->FormatEOL( rInf );
+ }
+ }
+ return bFull;
+}
+
+/*************************************************************************
+ * SwCombinedPortion::GetViewWidth(..)
+ *************************************************************************/
+
+KSHORT SwCombinedPortion::GetViewWidth( const SwTxtSizeInfo &rInf ) const
+{
+ if( !GetLen() ) // for the dummy part at the end of the line, where
+ return 0; // the combined portion doesn't fit.
+ return SwFldPortion::GetViewWidth( rInf );
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/text/porfld.hxx b/sw/source/core/text/porfld.hxx
new file mode 100644
index 000000000000..47890c7d05ea
--- /dev/null
+++ b/sw/source/core/text/porfld.hxx
@@ -0,0 +1,269 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+#ifndef _PORFLD_HXX
+#define _PORFLD_HXX
+
+#include "swtypes.hxx"
+#include "porexp.hxx"
+#include <fmtornt.hxx>
+
+class SwFont;
+class SvxBrushItem;
+class SwFmtVertOrient;
+class SwFrm;
+
+/*************************************************************************
+ * class SwFldPortion
+ *************************************************************************/
+
+class SwFldPortion : public SwExpandPortion
+{
+ friend class SwTxtFormatter;
+protected:
+ XubString aExpand; // das expandierte Feld
+ SwFont *pFnt; // Fuer mehrzeilige Felder
+ xub_StrLen nNextOffset; // Offset des Follows im Originalstring
+ xub_StrLen nNextScriptChg;
+ KSHORT nViewWidth; // Screenbreite fuer leere Felder
+ sal_Bool bFollow : 1; // 2. oder weiterer Teil eines Feldes
+ sal_Bool bLeft : 1; // wird von SwNumberPortion benutzt
+ sal_Bool bHide : 1; // wird von SwNumberPortion benutzt
+ sal_Bool bCenter : 1; // wird von SwNumberPortion benutzt
+ sal_Bool bHasFollow : 1; // geht in der naechsten Zeile weiter
+ sal_Bool bAnimated : 1; // wird von SwGrfNumPortion benutzt
+ sal_Bool bNoPaint : 1; // wird von SwGrfNumPortion benutzt
+ sal_Bool bReplace : 1; // wird von SwGrfNumPortion benutzt
+ const sal_Bool bPlaceHolder : 1;
+ sal_Bool m_bNoLength : 1; // HACK for meta suffix (no CH_TXTATR)
+
+ inline void SetFont( SwFont *pNew ) { pFnt = pNew; }
+ inline bool IsNoLength() const { return m_bNoLength; }
+ inline void SetNoLength() { m_bNoLength = sal_True; }
+
+public:
+ SwFldPortion( const SwFldPortion& rFld );
+ SwFldPortion( const XubString &rExpand, SwFont *pFnt = 0, sal_Bool bPlaceHolder = sal_False );
+ ~SwFldPortion();
+
+ void TakeNextOffset( const SwFldPortion* pFld );
+ void CheckScript( const SwTxtSizeInfo &rInf );
+ inline sal_Bool HasFont() const { return 0 != pFnt; }
+ // --> OD 2008-06-05 #i89179# - made public
+ inline const SwFont *GetFont() const { return pFnt; }
+ // <--
+
+ inline const XubString &GetExp() const { return aExpand; }
+ virtual sal_Bool GetExpTxt( const SwTxtSizeInfo &rInf, XubString &rTxt ) const;
+ virtual sal_Bool Format( SwTxtFormatInfo &rInf );
+ virtual void Paint( const SwTxtPaintInfo &rInf ) const;
+
+ // leere Felder sind auch erlaubt
+ virtual SwLinePortion *Compress();
+
+ virtual KSHORT GetViewWidth( const SwTxtSizeInfo &rInf ) const;
+
+ inline sal_Bool IsFollow() const { return bFollow; }
+ inline void SetFollow( sal_Bool bNew ) { bFollow = bNew; }
+
+ inline sal_Bool IsLeft() const { return bLeft; }
+ inline void SetLeft( sal_Bool bNew ) { bLeft = bNew; }
+
+ inline sal_Bool IsHide() const { return bHide; }
+ inline void SetHide( sal_Bool bNew ) { bHide = bNew; }
+
+ inline sal_Bool IsCenter() const { return bCenter; }
+ inline void SetCenter( sal_Bool bNew ) { bCenter = bNew; }
+
+ inline sal_Bool HasFollow() const { return bHasFollow; }
+ inline void SetHasFollow( sal_Bool bNew ) { bHasFollow = bNew; }
+
+ inline xub_StrLen GetNextOffset() const { return nNextOffset; }
+ inline void SetNextOffset( xub_StrLen nNew ) { nNextOffset = nNew; }
+
+ inline xub_StrLen GetNextScriptChg() const { return nNextScriptChg; }
+ inline void SetNextScriptChg( xub_StrLen nNew ) { nNextScriptChg = nNew; }
+
+ // Felder-Cloner fuer SplitGlue
+ virtual SwFldPortion *Clone( const XubString &rExpand ) const;
+
+ // Extra-GetTxtSize wegen pFnt
+ virtual SwPosSize GetTxtSize( const SwTxtSizeInfo &rInfo ) const;
+
+ // Accessibility: pass information about this portion to the PortionHandler
+ virtual void HandlePortion( SwPortionHandler& rPH ) const;
+
+ OUTPUT_OPERATOR
+};
+
+/*************************************************************************
+ * class SwHiddenPortion
+ *************************************************************************/
+// Unterscheidung nur fuer's Painten/verstecken.
+
+class SwHiddenPortion : public SwFldPortion
+{
+public:
+ inline SwHiddenPortion( const XubString &rExpand, SwFont *pFntL = 0 )
+ : SwFldPortion( rExpand, pFntL )
+ { SetLen(1); SetWhichPor( POR_HIDDEN ); }
+ virtual void Paint( const SwTxtPaintInfo &rInf ) const;
+ virtual sal_Bool GetExpTxt( const SwTxtSizeInfo &rInf, XubString &rTxt ) const;
+
+ // Felder-Cloner fuer SplitGlue
+ virtual SwFldPortion *Clone( const XubString &rExpand ) const;
+ OUTPUT_OPERATOR
+};
+
+/*************************************************************************
+ * class SwNumberPortion
+ *************************************************************************/
+
+class SwNumberPortion : public SwFldPortion
+{
+protected:
+ KSHORT nFixWidth; // vgl. Glues
+ KSHORT nMinDist; // minimaler Abstand zum Text
+ bool mbLabelAlignmentPosAndSpaceModeActive;
+
+public:
+ SwNumberPortion( const XubString &rExpand,
+ SwFont *pFnt,
+ const sal_Bool bLeft,
+ const sal_Bool bCenter,
+ const KSHORT nMinDst,
+ const bool bLabelAlignmentPosAndSpaceModeActive );
+ virtual void Paint( const SwTxtPaintInfo &rInf ) const;
+ virtual xub_StrLen GetCrsrOfst( const MSHORT nOfst ) const;
+ virtual sal_Bool Format( SwTxtFormatInfo &rInf );
+
+ // Felder-Cloner fuer SplitGlue
+ virtual SwFldPortion *Clone( const XubString &rExpand ) const;
+ virtual void FormatEOL( SwTxtFormatInfo &rInf );
+
+ OUTPUT_OPERATOR
+};
+
+/*************************************************************************
+ * class SwBulletPortion
+ *************************************************************************/
+
+class SwBulletPortion : public SwNumberPortion
+{
+public:
+ SwBulletPortion( const xub_Unicode cCh,
+ const XubString& rBulletFollowedBy,
+ SwFont *pFnt,
+ const sal_Bool bLeft,
+ const sal_Bool bCenter,
+ const KSHORT nMinDst,
+ const bool bLabelAlignmentPosAndSpaceModeActive );
+ OUTPUT_OPERATOR
+};
+
+/*************************************************************************
+ * class SwBmpBulletPortion
+ *************************************************************************/
+
+class SwGrfNumPortion : public SwNumberPortion
+{
+ SvxBrushItem* pBrush;
+ long nId; //fuer StopAnimation
+ SwTwips nYPos; //Enthaelt _immer_ die aktuelle RelPos.
+ SwTwips nGrfHeight;
+ sal_Int16 eOrient;
+public:
+ SwGrfNumPortion( SwFrm *pFrm,
+ const XubString& rGraphicFollowedBy,
+ const SvxBrushItem* pGrfBrush,
+ const SwFmtVertOrient* pGrfOrient,
+ const Size& rGrfSize,
+ const sal_Bool bLeft,
+ const sal_Bool bCenter,
+ const KSHORT nMinDst,
+ const bool bLabelAlignmentPosAndSpaceModeActive );
+ ~SwGrfNumPortion();
+ virtual void Paint( const SwTxtPaintInfo &rInf ) const;
+ virtual sal_Bool Format( SwTxtFormatInfo &rInf );
+
+ void SetBase( long nLnAscent, long nLnDescent,
+ long nFlyAscent, long nFlyDescent );
+
+ void StopAnimation( OutputDevice* pOut );
+
+ inline sal_Bool IsAnimated() const { return bAnimated; }
+ inline void SetAnimated( sal_Bool bNew ) { bAnimated = bNew; }
+ inline sal_Bool DontPaint() const { return bNoPaint; }
+ inline void SetNoPaint( sal_Bool bNew ) { bNoPaint = bNew; }
+ inline void SetRelPos( SwTwips nNew ) { nYPos = nNew; }
+ inline void SetId( long nNew ) const
+ { ((SwGrfNumPortion*)this)->nId = nNew; }
+ inline SwTwips GetRelPos() const { return nYPos; }
+ inline SwTwips GetGrfHeight() const { return nGrfHeight; }
+ inline SwTwips GetId() const { return nId; }
+ inline sal_Int16 GetOrient() const { return eOrient; }
+
+ OUTPUT_OPERATOR
+};
+
+/*************************************************************************
+ * class SwCombinedPortion
+ * Used in for asian layout specialities to display up to six characters
+ * in 2 rows and 2-3 columns.
+ * e.g.
+ *
+ * A.. A.. A.B A.B A.B.C A.B.C
+ * ... ..B .C. C.D .D.E. D.E.F
+ *************************************************************************/
+
+class SwCombinedPortion : public SwFldPortion
+{
+ sal_uInt16 aPos[6]; // up to six X positions
+ sal_uInt16 aWidth[3]; // one width for every scripttype
+ sal_uInt8 aScrType[6]; // scripttype of every character
+ sal_uInt16 nUpPos; // the Y position of the upper baseline
+ sal_uInt16 nLowPos; // the Y position of the lower baseline
+ sal_uInt8 nProportion; // relative font height
+public:
+ SwCombinedPortion( const XubString &rExpand );
+ virtual void Paint( const SwTxtPaintInfo &rInf ) const;
+ virtual sal_Bool Format( SwTxtFormatInfo &rInf );
+ virtual KSHORT GetViewWidth( const SwTxtSizeInfo &rInf ) const;
+ OUTPUT_OPERATOR
+};
+
+
+CLASSIO( SwHiddenPortion )
+CLASSIO( SwNumberPortion )
+CLASSIO( SwBulletPortion )
+CLASSIO( SwGrfNumPortion )
+CLASSIO( SwCombinedPortion )
+
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/text/porfly.cxx b/sw/source/core/text/porfly.cxx
new file mode 100644
index 000000000000..c8515e1500f8
--- /dev/null
+++ b/sw/source/core/text/porfly.cxx
@@ -0,0 +1,457 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+
+#include "dcontact.hxx" // SwDrawContact
+#include "dflyobj.hxx" // SwVirtFlyDrawObj
+#include "pam.hxx" // SwPosition
+#include "flyfrm.hxx" // SwFlyInCntFrm
+#include "rootfrm.hxx"
+#include "frmfmt.hxx" // SwFrmFmt
+#include "viewsh.hxx"
+
+#include <vcl/outdev.hxx>
+#include <editeng/lrspitem.hxx>
+#include <editeng/ulspitem.hxx>
+#include <fmtanchr.hxx>
+#include <fmtflcnt.hxx>
+#include <fmtornt.hxx>
+#include <frmatr.hxx>
+#include "flyfrms.hxx"
+#include "txatbase.hxx" // SwTxtAttr
+#include "porfly.hxx"
+#include "porlay.hxx" // SetFly
+#include "inftxt.hxx" // SwTxtPaintInfo
+
+// OD 2004-05-24 #i28701#
+#include <sortedobjs.hxx>
+
+
+/*************************************************************************
+ * class SwFlyPortion
+ *
+ * Wir erwarten ein framelokales SwRect !
+ *************************************************************************/
+
+void SwFlyPortion::Paint( const SwTxtPaintInfo& ) const
+{
+}
+
+/*************************************************************************
+ * virtual SwFlyPortion::Format()
+ *************************************************************************/
+sal_Bool SwFlyPortion::Format( SwTxtFormatInfo &rInf )
+{
+ OSL_ENSURE( Fix() >= rInf.X(), "SwFlyPortion::Format: rush hour" );
+ // 8537: Tabs muessen expandiert werden.
+ if( rInf.GetLastTab() )
+ ((SwLinePortion*)rInf.GetLastTab())->FormatEOL( rInf );
+
+ // Der Glue wird aufgespannt.
+ rInf.GetLast()->FormatEOL( rInf );
+ PrtWidth( static_cast<sal_uInt16>(Fix() - rInf.X() + PrtWidth()) );
+ if( !Width() )
+ {
+ OSL_ENSURE( Width(), "+SwFlyPortion::Format: a fly is a fly is a fly" );
+ Width(1);
+ }
+
+ // Restaurierung
+ rInf.SetFly( 0 );
+ rInf.Width( rInf.RealWidth() );
+ rInf.GetParaPortion()->SetFly( sal_True );
+
+ // trailing blank:
+ if( rInf.GetIdx() < rInf.GetTxt().Len() && 1 < rInf.GetIdx()
+ && !rInf.GetRest()
+ && ' ' == rInf.GetChar( rInf.GetIdx() )
+ && ' ' != rInf.GetChar( rInf.GetIdx() - 1 )
+ && ( !rInf.GetLast() || !rInf.GetLast()->IsBreakPortion() ) )
+ {
+ SetBlankWidth( rInf.GetTxtSize( ' ' ).Width() );
+ SetLen( 1 );
+ }
+
+ const sal_uInt16 nNewWidth = static_cast<sal_uInt16>(rInf.X() + PrtWidth());
+ if( rInf.Width() <= nNewWidth )
+ {
+ Truncate();
+ if( nNewWidth > rInf.Width() )
+ {
+ PrtWidth( nNewWidth - rInf.Width() );
+ SetFixWidth( PrtWidth() );
+ }
+ return sal_True;
+ }
+ return sal_False;
+}
+
+/*************************************************************************
+ * virtual SwFlyCntPortion::Format()
+ *************************************************************************/
+sal_Bool SwFlyCntPortion::Format( SwTxtFormatInfo &rInf )
+{
+ sal_Bool bFull = rInf.Width() < rInf.X() + PrtWidth();
+
+ if( bFull )
+ {
+ // 3924: wenn die Zeile voll ist und der zeichengebundene Frame am
+ // Anfang der Zeile steht.
+ // 5157: nicht wenn einem Fly ausgewichen werden kann!
+ // "Begin of line" criteria ( ! rInf.X() ) has to be extended.
+ // KerningPortions at beginning of line, e.g., for grid layout
+ // must be considered.
+ const SwLinePortion* pLastPor = rInf.GetLast();
+ const sal_uInt16 nLeft = ( pLastPor &&
+ ( pLastPor->IsKernPortion() ||
+ pLastPor->IsErgoSumPortion() ) ) ?
+ pLastPor->Width() :
+ 0;
+
+ if( nLeft == rInf.X() && ! rInf.GetFly() )
+ {
+ Width( rInf.Width() );
+ bFull = sal_False; // Damit Notizen noch in dieser Zeile landen
+ }
+ else
+ {
+ if( !rInf.GetFly() )
+ rInf.SetNewLine( sal_True );
+ Width(0);
+ SetAscent(0);
+ SetLen(0);
+ if( rInf.GetLast() )
+ rInf.GetLast()->FormatEOL( rInf );
+
+ return bFull;
+ }
+ }
+
+ rInf.GetParaPortion()->SetFly( sal_True );
+ return bFull;
+}
+
+/*************************************************************************
+ * SwTxtFrm::MoveFlyInCnt() haengt jetzt die zeichengebundenen Objekte
+ * innerhalb des angegebenen Bereichs um, damit koennen diese vom Master
+ * zum Follow oder umgekehrt wandern.
+ *************************************************************************/
+void SwTxtFrm::MoveFlyInCnt( SwTxtFrm *pNew, xub_StrLen nStart, xub_StrLen nEnd )
+{
+ SwSortedObjs *pObjs = 0L;
+ if ( 0 != (pObjs = GetDrawObjs()) )
+ {
+ for ( sal_uInt32 i = 0; GetDrawObjs() && i < pObjs->Count(); ++i )
+ {
+ // OD 2004-03-29 #i26791#
+ // --> OD 2004-07-06 #i28701# - consider changed type of
+ // <SwSortedList> entries
+ SwAnchoredObject* pAnchoredObj = (*pObjs)[i];
+ const SwFmtAnchor& rAnch = pAnchoredObj->GetFrmFmt().GetAnchor();
+ if (rAnch.GetAnchorId() == FLY_AS_CHAR)
+ {
+ const SwPosition* pPos = rAnch.GetCntntAnchor();
+ xub_StrLen nIdx = pPos->nContent.GetIndex();
+ if ( nIdx >= nStart && nEnd > nIdx )
+ {
+ if ( pAnchoredObj->ISA(SwFlyFrm) )
+ {
+ RemoveFly( static_cast<SwFlyFrm*>(pAnchoredObj) );
+ pNew->AppendFly( static_cast<SwFlyFrm*>(pAnchoredObj) );
+ }
+ else if ( pAnchoredObj->ISA(SwAnchoredDrawObject) )
+ {
+ RemoveDrawObj( *pAnchoredObj );
+ pNew->AppendDrawObj( *pAnchoredObj );
+ }
+ --i;
+ }
+ }
+ // <--
+ }
+ }
+}
+
+/*************************************************************************
+ * SwTxtFrm::CalcFlyPos()
+ *************************************************************************/
+xub_StrLen SwTxtFrm::CalcFlyPos( SwFrmFmt* pSearch )
+{
+ SwpHints* pHints = GetTxtNode()->GetpSwpHints();
+ OSL_ENSURE( pHints, "CalcFlyPos: Why me?" );
+ if( !pHints )
+ return STRING_LEN;
+ SwTxtAttr* pFound = NULL;
+ for ( sal_uInt16 i = 0; i < pHints->Count(); i++)
+ {
+ SwTxtAttr *pHt = pHints->GetTextHint( i );
+ if( RES_TXTATR_FLYCNT == pHt->Which() )
+ {
+ SwFrmFmt* pFrmFmt = pHt->GetFlyCnt().GetFrmFmt();
+ if( pFrmFmt == pSearch )
+ pFound = pHt;
+ }
+ }
+ OSL_ENSURE( pHints, "CalcFlyPos: Not Found!" );
+ if( !pFound )
+ return STRING_LEN;
+ return *pFound->GetStart();
+}
+
+/*************************************************************************
+ * virtual SwFlyCntPortion::Paint()
+ *************************************************************************/
+void SwFlyCntPortion::Paint( const SwTxtPaintInfo &rInf ) const
+{
+ if( bDraw )
+ {
+ if( !((SwDrawContact*)pContact)->GetAnchorFrm() )
+ {
+ // OD 2004-04-01 #i26791# - no direct positioning of the drawing
+ // object is needed.
+ SwDrawContact* pDrawContact = static_cast<SwDrawContact*>(pContact);
+ pDrawContact->ConnectToLayout();
+ }
+ }
+ else
+ {
+ // Baseline-Ausgabe !
+ // 7922: Bei CompletePaint alles painten
+ SwRect aRepaintRect( rInf.GetPaintRect() );
+
+ if ( rInf.GetTxtFrm()->IsRightToLeft() )
+ rInf.GetTxtFrm()->SwitchLTRtoRTL( aRepaintRect );
+
+ if ( rInf.GetTxtFrm()->IsVertical() )
+ rInf.GetTxtFrm()->SwitchHorizontalToVertical( aRepaintRect );
+
+ if( (GetFlyFrm()->IsCompletePaint() ||
+ GetFlyFrm()->Frm().IsOver( aRepaintRect )) &&
+ SwFlyFrm::IsPaint( (SdrObject*)GetFlyFrm()->GetVirtDrawObj(),
+ GetFlyFrm()->getRootFrm()->GetCurrShell() ))
+ {
+ SwRect aRect( GetFlyFrm()->Frm() );
+ if( !GetFlyFrm()->IsCompletePaint() )
+ aRect._Intersection( aRepaintRect );
+
+
+ // GetFlyFrm() may change the layout mode at the output device.
+ {
+ SwLayoutModeModifier aLayoutModeModifier( *rInf.GetOut() );
+ GetFlyFrm()->Paint( aRect );
+ }
+ ((SwTxtPaintInfo&)rInf).GetRefDev()->SetLayoutMode(
+ rInf.GetOut()->GetLayoutMode() );
+
+ // Es hilft alles nichts, im zeichengebundenen Frame kann wer weiss
+ // was am OutputDevice eingestellt sein, wir muessen unseren Font
+ // wieder hineinselektieren. Dass wir im const stehen, soll uns
+ // daran nicht hindern:
+ ((SwTxtPaintInfo&)rInf).SelectFont();
+
+ // I want to know if this can really happen. So here comes a new
+ OSL_ENSURE( ! rInf.GetVsh() || rInf.GetVsh()->GetOut() == rInf.GetOut(),
+ "SwFlyCntPortion::Paint: Outdev has changed" );
+ if( rInf.GetVsh() )
+ ((SwTxtPaintInfo&)rInf).SetOut( rInf.GetVsh()->GetOut() );
+ }
+ }
+}
+
+/*************************************************************************
+ * SwFlyCntPortion::SwFlyCntPortion()
+ *
+ * Es werden die Masze vom pFly->OutRect() eingestellt.
+ * Es erfolgt ein SetBase() !
+ *************************************************************************/
+// OD 29.07.2003 #110978# - use new datatype for parameter <nFlags>
+SwFlyCntPortion::SwFlyCntPortion( const SwTxtFrm& rFrm,
+ SwFlyInCntFrm *pFly, const Point &rBase,
+ long nLnAscent, long nLnDescent,
+ long nFlyAsc, long nFlyDesc,
+ objectpositioning::AsCharFlags nFlags ) :
+ pContact( pFly ),
+ bDraw( sal_False ),
+ bMax( sal_False ),
+ nAlign( 0 )
+{
+ OSL_ENSURE( pFly, "SwFlyCntPortion::SwFlyCntPortion: no SwFlyInCntFrm!" );
+ nLineLength = 1;
+ nFlags |= AS_CHAR_ULSPACE | AS_CHAR_INIT;
+ SetBase( rFrm, rBase, nLnAscent, nLnDescent, nFlyAsc, nFlyDesc, nFlags );
+ SetWhichPor( POR_FLYCNT );
+}
+
+// OD 29.07.2003 #110978# - use new datatype for parameter <nFlags>
+SwFlyCntPortion::SwFlyCntPortion( const SwTxtFrm& rFrm,
+ SwDrawContact *pDrawContact, const Point &rBase,
+ long nLnAscent, long nLnDescent,
+ long nFlyAsc, long nFlyDesc,
+ objectpositioning::AsCharFlags nFlags ) :
+ pContact( pDrawContact ),
+ bDraw( sal_True ),
+ bMax( sal_False ),
+ nAlign( 0 )
+{
+ OSL_ENSURE( pDrawContact, "SwFlyCntPortion::SwFlyCntPortion: no SwDrawContact!" );
+ if( !pDrawContact->GetAnchorFrm() )
+ {
+ // OD 2004-04-01 #i26791# - no direct positioning needed any more
+ pDrawContact->ConnectToLayout();
+ // --> OD 2005-01-14 #i40333# - follow-up of #i35635#
+ // move object to visible layer
+ pDrawContact->MoveObjToVisibleLayer( pDrawContact->GetMaster() );
+ // <--
+ }
+ nLineLength = 1;
+ nFlags |= AS_CHAR_ULSPACE | AS_CHAR_INIT;
+
+ SetBase( rFrm, rBase, nLnAscent, nLnDescent, nFlyAsc, nFlyDesc, nFlags );
+
+ SetWhichPor( POR_FLYCNT );
+}
+
+
+/*************************************************************************
+ * SwFlyCntPortion::SetBase()
+ *
+ * Nach dem Setzen des RefPoints muss der Ascent neu berechnet werden,
+ * da er von der RelPos abhaengt.
+ * pFly->GetRelPos().Y() bezeichnet die relative Position zur Baseline.
+ * Bei 0 liegt der obere Rand des FlyCnt auf der Baseline der Zeile.
+ *************************************************************************/
+// OD 29.07.2003 #110978# - use new datatype for parameter <nFlags>
+void SwFlyCntPortion::SetBase( const SwTxtFrm& rFrm, const Point &rBase,
+ long nLnAscent, long nLnDescent,
+ long nFlyAsc, long nFlyDesc,
+ objectpositioning::AsCharFlags nFlags )
+{
+ // Note: rBase have to be an absolute value
+
+ // OD 28.10.2003 #113049# - use new class to position object
+ // determine drawing object
+ SdrObject* pSdrObj = 0L;
+ if( bDraw )
+ {
+ // OD 20.06.2003 #108784# - determine drawing object ('master' or 'virtual')
+ // by frame.
+ pSdrObj = GetDrawContact()->GetDrawObjectByAnchorFrm( rFrm );
+ if ( !pSdrObj )
+ {
+ OSL_FAIL( "SwFlyCntPortion::SetBase(..) - No drawing object found by <GetDrawContact()->GetDrawObjectByAnchorFrm( rFrm )>" );
+ pSdrObj = GetDrawContact()->GetMaster();
+ }
+ // --> OD 2007-11-29 #i65798#
+ // call <SwAnchoredDrawObject::MakeObjPos()> to assure that flag at
+ // the <DrawFrmFmt> and at the <SwAnchoredDrawObject> instance are
+ // correctly set.
+ if ( pSdrObj )
+ {
+ GetDrawContact()->GetAnchoredObj( pSdrObj )->MakeObjPos();
+ }
+ // <--
+ }
+ else
+ {
+ pSdrObj = GetFlyFrm()->GetVirtDrawObj();
+ }
+
+ // position object
+ objectpositioning::SwAsCharAnchoredObjectPosition aObjPositioning(
+ *pSdrObj,
+ rBase, nFlags,
+ nLnAscent, nLnDescent, nFlyAsc, nFlyDesc );
+
+ // OD 2004-04-13 #i26791# - scope of local variable <aObjPosInProgress>
+ {
+ // OD 2004-04-13 #i26791#
+ SwObjPositioningInProgress aObjPosInProgress( *pSdrObj );
+ aObjPositioning.CalcPosition();
+ }
+
+ SetAlign( aObjPositioning.GetLineAlignment() );
+
+ aRef = aObjPositioning.GetAnchorPos();
+ if( nFlags & AS_CHAR_ROTATE )
+ SvXSize( aObjPositioning.GetObjBoundRectInclSpacing().SSize() );
+ else
+ SvLSize( aObjPositioning.GetObjBoundRectInclSpacing().SSize() );
+ if( Height() )
+ {
+ SwTwips nRelPos = aObjPositioning.GetRelPosY();
+ if ( nRelPos < 0 )
+ {
+ nAscent = static_cast<sal_uInt16>(-nRelPos);
+ if( nAscent > Height() )
+ Height( nAscent );
+ }
+ else
+ {
+ nAscent = 0;
+ Height( Height() + static_cast<sal_uInt16>(nRelPos) );
+ }
+ }
+ else
+ {
+ Height( 1 );
+ nAscent = 0;
+ }
+}
+
+/*************************************************************************
+ * virtual SwFlyCntPortion::GetFlyCrsrOfst()
+ *************************************************************************/
+
+xub_StrLen SwFlyCntPortion::GetFlyCrsrOfst( const KSHORT nOfst,
+ const Point &rPoint, SwPosition *pPos, SwCrsrMoveState* pCMS ) const
+{
+ // Da die FlyCnt nicht an der Seite haengen, wird ihr
+ // GetCrsrOfst() nicht gerufen. Um die Layoutseite
+ // von unnoetiger Verwaltung zu entlasten, ruft der Absatz
+ // das GetCrsrOfst des FlyFrm, wenn es erforderlich ist.
+ Point aPoint( rPoint );
+ if( !pPos || bDraw || !( GetFlyFrm()->GetCrsrOfst( pPos, aPoint, pCMS ) ) )
+ return SwLinePortion::GetCrsrOfst( nOfst );
+ else
+ return 0;
+}
+
+/*************************************************************************
+ * virtual SwFlyCntPortion::GetCrsrOfst()
+ *************************************************************************/
+
+xub_StrLen SwFlyCntPortion::GetCrsrOfst( const KSHORT nOfst ) const
+{
+ // OSL_ENSURE( !this, "SwFlyCntPortion::GetCrsrOfst: use GetFlyCrsrOfst()" );
+ return SwLinePortion::GetCrsrOfst( nOfst );
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/text/porfly.hxx b/sw/source/core/text/porfly.hxx
new file mode 100644
index 000000000000..ed2a7d5d8e65
--- /dev/null
+++ b/sw/source/core/text/porfly.hxx
@@ -0,0 +1,111 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+#ifndef _PORFLY_HXX
+#define _PORFLY_HXX
+// OD 28.10.2003 #113049#
+#include <ascharanchoredobjectposition.hxx>
+
+#include "porglue.hxx"
+
+class SwDrawContact;
+class SwFlyInCntFrm;
+class SwTxtFrm;
+struct SwCrsrMoveState;
+
+/*************************************************************************
+ * class SwFlyPortion
+ *************************************************************************/
+
+class SwFlyPortion : public SwFixPortion
+{
+ KSHORT nBlankWidth;
+public:
+ inline SwFlyPortion( const SwRect &rFlyRect )
+ : SwFixPortion(rFlyRect), nBlankWidth( 0 ) { SetWhichPor( POR_FLY ); }
+ inline KSHORT GetBlankWidth( ) const { return nBlankWidth; }
+ inline void SetBlankWidth( const KSHORT nNew ) { nBlankWidth = nNew; }
+ virtual void Paint( const SwTxtPaintInfo &rInf ) const;
+ virtual sal_Bool Format( SwTxtFormatInfo &rInf );
+ OUTPUT_OPERATOR
+};
+
+/*************************************************************************
+ * class SwFlyCntPortion
+ *************************************************************************/
+
+class SwFlyCntPortion : public SwLinePortion
+{
+ void *pContact; // bDraw ? DrawContact : FlyInCntFrm
+ Point aRef; // Relativ zu diesem Point wird die AbsPos berechnet.
+ sal_Bool bDraw : 1; // DrawContact?
+ sal_Bool bMax : 1; // Zeilenausrichtung und Hoehe == Zeilenhoehe
+ sal_uInt8 nAlign : 3; // Zeilenausrichtung? Nein, oben, mitte, unten
+ virtual xub_StrLen GetCrsrOfst( const KSHORT nOfst ) const;
+
+public:
+ // OD 29.07.2003 #110978# - use new datatype for parameter <nFlags>
+ SwFlyCntPortion( const SwTxtFrm& rFrm, SwFlyInCntFrm *pFly,
+ const Point &rBase,
+ long nAscent, long nDescent, long nFlyAsc, long nFlyDesc,
+ objectpositioning::AsCharFlags nFlags );
+ // OD 29.07.2003 #110978# - use new datatype for parameter <nFlags>
+ SwFlyCntPortion( const SwTxtFrm& rFrm, SwDrawContact *pDrawContact,
+ const Point &rBase,
+ long nAscent, long nDescent, long nFlyAsc, long nFlyDesc,
+ objectpositioning::AsCharFlags nFlags );
+ inline const Point& GetRefPoint() const { return aRef; }
+ inline SwFlyInCntFrm *GetFlyFrm() { return (SwFlyInCntFrm*)pContact; }
+ inline const SwFlyInCntFrm *GetFlyFrm() const
+ { return (SwFlyInCntFrm*)pContact; }
+ inline SwDrawContact *GetDrawContact() { return (SwDrawContact*)pContact; }
+ inline const SwDrawContact* GetDrawContact() const
+ { return (SwDrawContact*)pContact; }
+ inline sal_Bool IsDraw() const { return bDraw; }
+ inline sal_Bool IsMax() const { return bMax; }
+ inline sal_uInt8 GetAlign() const { return nAlign; }
+ inline void SetAlign( sal_uInt8 nNew ) { nAlign = nNew; }
+ inline void SetMax( sal_Bool bNew ) { bMax = bNew; }
+ // OD 29.07.2003 #110978# - use new datatype for parameter <nFlags>
+ void SetBase( const SwTxtFrm& rFrm, const Point &rBase,
+ long nLnAscent, long nLnDescent,
+ long nFlyAscent, long nFlyDescent,
+ objectpositioning::AsCharFlags nFlags );
+ xub_StrLen GetFlyCrsrOfst( const KSHORT nOfst, const Point &rPoint,
+ SwPosition *pPos, SwCrsrMoveState* pCMS ) const;
+ virtual sal_Bool Format( SwTxtFormatInfo &rInf );
+ virtual void Paint( const SwTxtPaintInfo &rInf ) const;
+ OUTPUT_OPERATOR
+};
+
+CLASSIO( SwFlyPortion )
+CLASSIO( SwFlyCntPortion )
+
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/text/porftn.hxx b/sw/source/core/text/porftn.hxx
new file mode 100644
index 000000000000..384577d627ab
--- /dev/null
+++ b/sw/source/core/text/porftn.hxx
@@ -0,0 +1,131 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+#ifndef _PORFTN_HXX
+#define _PORFTN_HXX
+
+#include "porfld.hxx"
+
+class SwTxtFrm;
+class SwTxtFtn;
+
+/*************************************************************************
+ * class SwFtnPortion
+ *************************************************************************/
+
+class SwFtnPortion : public SwFldPortion
+{
+ SwTxtFrm *pFrm; // um im Dtor RemoveFtn rufen zu koennen.
+ SwTxtFtn *pFtn;
+ KSHORT nOrigHeight;
+ // --> OD 2009-01-29 #i98418#
+ bool mbPreferredScriptTypeSet;
+ sal_uInt8 mnPreferredScriptType;
+ // <--
+public:
+ SwFtnPortion( const XubString &rExpand, SwTxtFrm *pFrm, SwTxtFtn *pFtn,
+ KSHORT nOrig = KSHRT_MAX );
+ inline KSHORT& Orig() { return nOrigHeight; }
+
+ virtual void Paint( const SwTxtPaintInfo &rInf ) const;
+ virtual sal_Bool GetExpTxt( const SwTxtSizeInfo &rInf, XubString &rTxt ) const;
+ virtual SwPosSize GetTxtSize( const SwTxtSizeInfo &rInfo ) const;
+ virtual sal_Bool Format( SwTxtFormatInfo &rInf );
+
+ // --> OD 2009-01-29 #i98418#
+ void SetPreferredScriptType( sal_uInt8 nPreferredScriptType );
+ // <--
+
+ const SwTxtFtn* GetTxtFtn() const { return pFtn; };
+ OUTPUT_OPERATOR
+};
+
+/*************************************************************************
+ * class SwFtnNumPortion
+ *************************************************************************/
+
+class SwFtnNumPortion : public SwNumberPortion
+{
+public:
+ inline SwFtnNumPortion( const XubString &rExpand, SwFont *pFntL )
+ : SwNumberPortion( rExpand, pFntL, sal_True, sal_False, 0, false )
+ { SetWhichPor( POR_FTNNUM ); }
+
+ OUTPUT_OPERATOR
+};
+
+/*************************************************************************
+ * class SwQuoVadisPortion
+ *************************************************************************/
+
+class SwQuoVadisPortion : public SwFldPortion
+{
+ XubString aErgo;
+public:
+ SwQuoVadisPortion( const XubString &rExp, const XubString& rStr );
+ virtual sal_Bool Format( SwTxtFormatInfo &rInf );
+ virtual void Paint( const SwTxtPaintInfo &rInf ) const;
+ virtual sal_Bool GetExpTxt( const SwTxtSizeInfo &rInf, XubString &rTxt ) const;
+
+ inline void SetNumber( const XubString& rStr ) { aErgo = rStr; }
+ inline const XubString &GetQuoTxt() const { return aExpand; }
+ inline const XubString &GetContTxt() const { return aErgo; }
+
+ // Felder-Cloner fuer SplitGlue
+ virtual SwFldPortion *Clone( const XubString &rExpand ) const;
+
+ // Accessibility: pass information about this portion to the PortionHandler
+ virtual void HandlePortion( SwPortionHandler& rPH ) const;
+
+ OUTPUT_OPERATOR
+};
+
+/*************************************************************************
+ * class SwErgoSumPortion
+ *************************************************************************/
+
+class SwErgoSumPortion : public SwFldPortion
+{
+public:
+ SwErgoSumPortion( const XubString &rExp, const XubString& rStr );
+ virtual xub_StrLen GetCrsrOfst( const KSHORT nOfst ) const;
+ virtual sal_Bool Format( SwTxtFormatInfo &rInf );
+
+ // Felder-Cloner fuer SplitGlue
+ virtual SwFldPortion *Clone( const XubString &rExpand ) const;
+ OUTPUT_OPERATOR
+};
+
+CLASSIO( SwFtnPortion )
+CLASSIO( SwFtnNumPortion )
+CLASSIO( SwQuoVadisPortion )
+CLASSIO( SwErgoSumPortion )
+
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/text/porglue.cxx b/sw/source/core/text/porglue.cxx
new file mode 100644
index 000000000000..f36a2e9d6539
--- /dev/null
+++ b/sw/source/core/text/porglue.cxx
@@ -0,0 +1,315 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+
+
+#include "swrect.hxx"
+#include "paratr.hxx" // pTabStop, ADJ*
+#include "viewopt.hxx" // SwViewOptions
+#include <SwPortionHandler.hxx>
+
+#include "porglue.hxx"
+#include "inftxt.hxx"
+#include "porlay.hxx" // SwParaPortion, SetFull
+#include "porfly.hxx" // SwParaPortion, SetFull
+
+/*************************************************************************
+ * class SwGluePortion
+ *************************************************************************/
+
+SwGluePortion::SwGluePortion( const KSHORT nInitFixWidth )
+ : nFixWidth( nInitFixWidth )
+{
+ PrtWidth( nFixWidth );
+ SetWhichPor( POR_GLUE );
+}
+
+/*************************************************************************
+ * virtual SwGluePortion::GetCrsrOfst()
+ *************************************************************************/
+
+xub_StrLen SwGluePortion::GetCrsrOfst( const KSHORT nOfst ) const
+{
+ if( !GetLen() || nOfst > GetLen() || !Width() )
+ return SwLinePortion::GetCrsrOfst( nOfst );
+ else
+ return nOfst / (Width() / GetLen());
+}
+
+/*************************************************************************
+ * virtual SwGluePortion::GetTxtSize()
+ *************************************************************************/
+
+SwPosSize SwGluePortion::GetTxtSize( const SwTxtSizeInfo &rInf ) const
+{
+ if( 1 >= GetLen() || rInf.GetLen() > GetLen() || !Width() || !GetLen() )
+ return SwPosSize(*this);
+ else
+ return SwPosSize( (Width() / GetLen()) * rInf.GetLen(), Height() );
+}
+
+/*************************************************************************
+ * virtual SwGluePortion::GetExpTxt()
+ *************************************************************************/
+
+sal_Bool SwGluePortion::GetExpTxt( const SwTxtSizeInfo &rInf, XubString &rTxt ) const
+{
+ if( GetLen() && rInf.OnWin() &&
+ rInf.GetOpt().IsBlank() && rInf.IsNoSymbol() )
+ {
+ rTxt.Fill( GetLen(), CH_BULLET );
+ return sal_True;
+ }
+ return sal_False;
+}
+
+/*************************************************************************
+ * virtual SwGluePortion::Paint()
+ *************************************************************************/
+
+void SwGluePortion::Paint( const SwTxtPaintInfo &rInf ) const
+{
+ if( !GetLen() )
+ return;
+
+ if( rInf.GetFont()->IsPaintBlank() )
+ {
+ XubString aTxt;
+ aTxt.Fill( GetFixWidth() / GetLen(), ' ' );
+ SwTxtPaintInfo aInf( rInf, aTxt );
+ aInf.DrawText( *this, aTxt.Len(), sal_True );
+ }
+
+ if( rInf.OnWin() && rInf.GetOpt().IsBlank() && rInf.IsNoSymbol() )
+ {
+#if OSL_DEBUG_LEVEL > 1
+ const xub_Unicode cChar = rInf.GetChar( rInf.GetIdx() );
+ OSL_ENSURE( CH_BLANK == cChar || CH_BULLET == cChar,
+ "SwGluePortion::Paint: blank expected" );
+#endif
+ if( 1 == GetLen() )
+ {
+ String aBullet( CH_BULLET );
+ SwPosSize aBulletSize( rInf.GetTxtSize( aBullet ) );
+ Point aPos( rInf.GetPos() );
+ aPos.X() += (Width()/2) - (aBulletSize.Width()/2);
+ SwTxtPaintInfo aInf( rInf, aBullet );
+ aInf.SetPos( aPos );
+ SwTxtPortion aBulletPor;
+ aBulletPor.Width( aBulletSize.Width() );
+ aBulletPor.Height( aBulletSize.Height() );
+ aBulletPor.SetAscent( GetAscent() );
+ aInf.DrawText( aBulletPor, aBullet.Len(), sal_True );
+ }
+ else
+ {
+ SwTxtSlot aSlot( &rInf, this, true, false );
+ rInf.DrawText( *this, rInf.GetLen(), sal_True );
+ }
+ }
+}
+
+/*************************************************************************
+ * SwGluePortion::MoveGlue()
+ *************************************************************************/
+
+void SwGluePortion::MoveGlue( SwGluePortion *pTarget, const short nPrtGlue )
+{
+ short nPrt = Min( nPrtGlue, GetPrtGlue() );
+ if( 0 < nPrt )
+ {
+ pTarget->AddPrtWidth( nPrt );
+ SubPrtWidth( nPrt );
+ }
+}
+
+/*************************************************************************
+ * void SwGluePortion::Join()
+ *************************************************************************/
+
+void SwGluePortion::Join( SwGluePortion *pVictim )
+{
+ // Die GluePortion wird ausgesogen und weggespuelt ...
+ AddPrtWidth( pVictim->PrtWidth() );
+ SetLen( pVictim->GetLen() + GetLen() );
+ if( Height() < pVictim->Height() )
+ Height( pVictim->Height() );
+
+ AdjFixWidth();
+ Cut( pVictim );
+ delete pVictim;
+}
+
+/*************************************************************************
+ * class SwFixPortion
+ *************************************************************************/
+
+// Wir erwarten ein framelokales SwRect !
+SwFixPortion::SwFixPortion( const SwRect &rRect )
+ :SwGluePortion( KSHORT(rRect.Width()) ), nFix( KSHORT(rRect.Left()) )
+{
+ Height( KSHORT(rRect.Height()) );
+ SetWhichPor( POR_FIX );
+}
+
+SwFixPortion::SwFixPortion(const KSHORT nFixedWidth, const KSHORT nFixedPos)
+ : SwGluePortion(nFixedWidth), nFix(nFixedPos)
+{
+ SetWhichPor( POR_FIX );
+}
+
+/*************************************************************************
+ * class SwMarginPortion
+ *************************************************************************/
+
+SwMarginPortion::SwMarginPortion( const KSHORT nFixedWidth )
+ :SwGluePortion( nFixedWidth )
+{
+ SetWhichPor( POR_MARGIN );
+}
+
+/*************************************************************************
+ * SwMarginPortion::AdjustRight()
+ *
+ * In der umschliessenden Schleife werden alle Portions durchsucht,
+ * dabei werden erst die am Ende liegenden GluePortions verarbeitet.
+ * Das Ende wird nach jeder Schleife nach vorne verlegt, bis keine
+ * GluePortions mehr vorhanden sind.
+ * Es werden immer GluePortion-Paare betrachtet (pLeft und pRight),
+ * wobei Textportions zwischen pLeft und pRight hinter pRight verschoben
+ * werden, wenn pRight genuegend Glue besitzt. Bei jeder Verschiebung
+ * wandert ein Teil des Glues von pRight nach pLeft.
+ * Im naechsten Schleifendurchlauf ist pLeft das pRight und das Spiel
+ * beginnt von vorne.
+ *************************************************************************/
+
+void SwMarginPortion::AdjustRight( const SwLineLayout *pCurr )
+{
+ SwGluePortion *pRight = 0;
+ sal_Bool bNoMove = 0 != pCurr->GetpKanaComp();
+ while( pRight != this )
+ {
+
+ // 1) Wir suchen den linken Glue
+ SwLinePortion *pPos = (SwLinePortion*)this;
+ SwGluePortion *pLeft = 0;
+ while( pPos )
+ {
+ if( pPos->InFixMargGrp() )
+ pLeft = (SwGluePortion*)pPos;
+ pPos = pPos->GetPortion();
+ if( pPos == pRight)
+ pPos = 0;
+ }
+
+ // Zwei nebeneinander liegende FlyPortions verschmelzen
+ if( pRight && pLeft->GetPortion() == pRight )
+ {
+ pRight->MoveAllGlue( pLeft );
+ pRight = 0;
+ }
+ KSHORT nRightGlue = pRight && 0 < pRight->GetPrtGlue()
+ ? KSHORT(pRight->GetPrtGlue()) : 0;
+ // 2) linken und rechten Glue ausgleichen
+ // Bei Tabs haengen wir nix um ...
+ if( pLeft && nRightGlue && !pRight->InTabGrp() )
+ {
+ // pPrev ist die Portion, die unmittelbar vor pRight liegt.
+ SwLinePortion *pPrev = pRight->FindPrevPortion( pLeft );
+
+ if ( pRight->IsFlyPortion() && pRight->GetLen() )
+ {
+ SwFlyPortion *pFly = (SwFlyPortion *)pRight;
+ if ( pFly->GetBlankWidth() < nRightGlue )
+ {
+ // Hier entsteht eine neue TxtPortion, die dass zuvor
+ // vom Fly verschluckte Blank reaktiviert.
+ nRightGlue = nRightGlue - pFly->GetBlankWidth();
+ pFly->SubPrtWidth( pFly->GetBlankWidth() );
+ pFly->SetLen( 0 );
+ SwTxtPortion *pNewPor = new SwTxtPortion;
+ pNewPor->SetLen( 1 );
+ pNewPor->Height( pFly->Height() );
+ pNewPor->Width( pFly->GetBlankWidth() );
+ pFly->Insert( pNewPor );
+ }
+ else
+ pPrev = pLeft;
+ }
+ while( pPrev != pLeft )
+ {
+ if( bNoMove || pPrev->PrtWidth() >= nRightGlue ||
+ pPrev->InHyphGrp() || pPrev->IsKernPortion() )
+ {
+ // Die Portion, die vor pRight liegt kann nicht
+ // verschoben werden, weil kein Glue mehr vorhanden ist.
+ // Wir fuehren die Abbruchbedingung herbei:
+ pPrev = pLeft;
+ }
+ else
+ {
+ nRightGlue = nRightGlue - pPrev->PrtWidth();
+ // pPrev wird hinter pRight verschoben.
+ // Dazu wird der Gluewert zwischen pRight und pLeft
+ // ausgeglichen.
+ pRight->MoveGlue( pLeft, short( pPrev->PrtWidth() ) );
+ // Jetzt wird die Verkettung gerichtet.
+ SwLinePortion *pPrevPrev = pPrev->FindPrevPortion( pLeft );
+ pPrevPrev->SetPortion( pRight );
+ pPrev->SetPortion( pRight->GetPortion() );
+ pRight->SetPortion( pPrev );
+ if ( pPrev->GetPortion() && pPrev->InTxtGrp()
+ && pPrev->GetPortion()->IsHolePortion() )
+ {
+ SwHolePortion *pHolePor =
+ (SwHolePortion*)pPrev->GetPortion();
+ if ( !pHolePor->GetPortion() ||
+ !pHolePor->GetPortion()->InFixMargGrp() )
+ {
+ pPrev->AddPrtWidth( pHolePor->GetBlankWidth() );
+ pPrev->SetLen( pPrev->GetLen() + 1 );
+ pPrev->SetPortion( pHolePor->GetPortion() );
+ delete pHolePor;
+ }
+ }
+ pPrev = pPrevPrev;
+ }
+ }
+ }
+ // Wenn es keinen linken Glue mehr gibt, wird die Abbruchbedingung
+ // herbeigefuehrt.
+ pRight = pLeft ? pLeft : (SwGluePortion*)this;
+ }
+}
+
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/text/porglue.hxx b/sw/source/core/text/porglue.hxx
new file mode 100644
index 000000000000..a498c46cbb7e
--- /dev/null
+++ b/sw/source/core/text/porglue.hxx
@@ -0,0 +1,134 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+#ifndef _PORGLUE_HXX
+#define _PORGLUE_HXX
+
+#include "porlin.hxx"
+
+class SwRect;
+class SwLineLayout;
+
+/*************************************************************************
+ * class SwGluePortion
+ *************************************************************************/
+
+class SwGluePortion : public SwLinePortion
+{
+private:
+ KSHORT nFixWidth;
+public:
+ SwGluePortion( const KSHORT nInitFixWidth );
+
+ void Join( SwGluePortion *pVictim );
+
+ inline short GetPrtGlue() const;
+ inline KSHORT GetFixWidth() const { return nFixWidth; }
+ inline void SetFixWidth( const KSHORT nNew ) { nFixWidth = nNew; }
+ void MoveGlue( SwGluePortion *pTarget, const short nPrtGlue );
+ inline void MoveAllGlue( SwGluePortion *pTarget );
+ inline void MoveHalfGlue( SwGluePortion *pTarget );
+ inline void AdjFixWidth();
+ virtual void Paint( const SwTxtPaintInfo &rInf ) const;
+ virtual xub_StrLen GetCrsrOfst( const KSHORT nOfst ) const;
+ virtual SwPosSize GetTxtSize( const SwTxtSizeInfo &rInfo ) const;
+ virtual sal_Bool GetExpTxt( const SwTxtSizeInfo &rInf, XubString &rTxt ) const;
+
+ OUTPUT_OPERATOR
+};
+
+/*************************************************************************
+ * class SwFixPortion
+ *************************************************************************/
+
+class SwFixPortion : public SwGluePortion
+{
+ KSHORT nFix; // der Width-Offset in der Zeile
+public:
+ SwFixPortion( const SwRect &rFlyRect );
+ SwFixPortion( const KSHORT nFixWidth, const KSHORT nFixPos );
+ inline void Fix( const KSHORT nNewFix ) { nFix = nNewFix; }
+ inline KSHORT Fix() const { return nFix; }
+ OUTPUT_OPERATOR
+};
+
+/*************************************************************************
+ * class SwMarginPortion
+ *************************************************************************/
+
+class SwMarginPortion : public SwGluePortion
+{
+public:
+ SwMarginPortion( const KSHORT nFixWidth );
+ void AdjustRight( const SwLineLayout* pCurr );
+ OUTPUT_OPERATOR
+};
+
+/*************************************************************************
+ * inline SwGluePortion::GetPrtGlue()
+ *************************************************************************/
+
+inline short SwGluePortion::GetPrtGlue() const
+{ return Width() - nFixWidth; }
+
+/*************************************************************************
+ * inline SwGluePortion::AdjFixWidth()
+ * Die FixWidth darf niemals groesser sein als die Gesamtbreite !
+ *************************************************************************/
+
+inline void SwGluePortion::AdjFixWidth()
+{
+ if( nFixWidth > PrtWidth() )
+ nFixWidth = PrtWidth();
+}
+
+/*************************************************************************
+ * inline SwGluePortion::MoveGlue()
+ *************************************************************************/
+
+inline void SwGluePortion::MoveAllGlue( SwGluePortion *pTarget )
+{
+ MoveGlue( pTarget, GetPrtGlue() );
+}
+
+/*************************************************************************
+ * inline SwGluePortion::MoveHalfGlue()
+ *************************************************************************/
+
+inline void SwGluePortion::MoveHalfGlue( SwGluePortion *pTarget )
+{
+ MoveGlue( pTarget, GetPrtGlue() / 2 );
+}
+
+CLASSIO( SwGluePortion )
+CLASSIO( SwFixPortion )
+CLASSIO( SwMarginPortion )
+
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/text/porhyph.hxx b/sw/source/core/text/porhyph.hxx
new file mode 100644
index 000000000000..c3f2934cedc8
--- /dev/null
+++ b/sw/source/core/text/porhyph.hxx
@@ -0,0 +1,122 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+#ifndef _PORHYPH_HXX
+#define _PORHYPH_HXX
+
+#include "porexp.hxx"
+
+/*************************************************************************
+ * class SwHyphPortion
+ *************************************************************************/
+
+class SwHyphPortion : public SwExpandPortion
+{
+public:
+ inline SwHyphPortion( ) { SetWhichPor( POR_HYPH ); }
+ virtual sal_Bool GetExpTxt( const SwTxtSizeInfo &rInf, XubString &rTxt ) const;
+ virtual sal_Bool Format( SwTxtFormatInfo &rInf );
+
+ // Accessibility: pass information about this portion to the PortionHandler
+ virtual void HandlePortion( SwPortionHandler& rPH ) const;
+
+ OUTPUT_OPERATOR
+};
+
+/*************************************************************************
+ * class SwHyphStrPortion
+ *************************************************************************/
+
+class SwHyphStrPortion : public SwHyphPortion
+{
+ XubString aExpand;
+public:
+ inline SwHyphStrPortion( const XubString &rStr );
+ virtual sal_Bool GetExpTxt( const SwTxtSizeInfo &rInf, XubString &rTxt ) const;
+
+ // Accessibility: pass information about this portion to the PortionHandler
+ virtual void HandlePortion( SwPortionHandler& rPH ) const;
+
+ OUTPUT_OPERATOR
+};
+
+/*************************************************************************
+ * class SwSoftHyphPortion
+ *************************************************************************/
+
+class SwSoftHyphPortion : public SwHyphPortion
+{
+ sal_Bool bExpand;
+ KSHORT nViewWidth;
+ KSHORT nHyphWidth;
+
+public:
+ SwSoftHyphPortion();
+ virtual sal_Bool GetExpTxt( const SwTxtSizeInfo &rInf, XubString &rTxt ) const;
+ virtual SwLinePortion *Compress();
+ virtual void Paint( const SwTxtPaintInfo &rInf ) const;
+ virtual sal_Bool Format( SwTxtFormatInfo &rInf );
+ virtual void FormatEOL( SwTxtFormatInfo &rInf );
+ inline void SetExpand( const sal_Bool bNew ) { bExpand = bNew; }
+ sal_Bool IsExpand() const { return bExpand; }
+
+ virtual KSHORT GetViewWidth( const SwTxtSizeInfo &rInf ) const;
+
+ // Accessibility: pass information about this portion to the PortionHandler
+ virtual void HandlePortion( SwPortionHandler& rPH ) const;
+
+ OUTPUT_OPERATOR
+};
+
+/*************************************************************************
+ * class SwSoftHyphStrPortion
+ *************************************************************************/
+
+class SwSoftHyphStrPortion : public SwHyphStrPortion
+{
+public:
+ SwSoftHyphStrPortion( const XubString &rStr );
+ virtual void Paint( const SwTxtPaintInfo &rInf ) const;
+ OUTPUT_OPERATOR
+};
+
+inline SwHyphStrPortion::SwHyphStrPortion( const XubString &rStr )
+ : aExpand( rStr )
+{
+ aExpand += '-';
+ SetWhichPor( POR_HYPHSTR );
+}
+
+CLASSIO( SwHyphPortion )
+CLASSIO( SwHyphStrPortion )
+CLASSIO( SwSoftHyphPortion )
+CLASSIO( SwSoftHyphStrPortion )
+
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/text/porlay.cxx b/sw/source/core/text/porlay.cxx
new file mode 100644
index 000000000000..5da6fd03f352
--- /dev/null
+++ b/sw/source/core/text/porlay.cxx
@@ -0,0 +1,2424 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+#include "porlay.hxx"
+#include "itrform2.hxx"
+#include "porglue.hxx"
+#include "porexp.hxx" // SwQuoVadisPortion
+#include "blink.hxx" // pBlink
+#include "redlnitr.hxx" // SwRedlineItr
+#include "porfly.hxx" // SwFlyCntPortion
+#include <porrst.hxx> // SwHangingPortion
+#include <pormulti.hxx> // SwMultiPortion
+#include <breakit.hxx>
+#include <unicode/uchar.h>
+#include <com/sun/star/i18n/ScriptType.hdl>
+#include <com/sun/star/i18n/CTLScriptType.hdl>
+#include <com/sun/star/i18n/WordType.hdl>
+#include <paratr.hxx>
+#include <editeng/adjitem.hxx>
+#include <editeng/scripttypeitem.hxx>
+#include <editeng/charhiddenitem.hxx>
+#include <vcl/outdev.hxx>
+#include <editeng/blnkitem.hxx>
+#include <tools/multisel.hxx>
+#include <unotools/charclass.hxx>
+#include <i18npool/mslangid.hxx>
+#include <charfmt.hxx>
+#include <fchrfmt.hxx>
+#include <docary.hxx> // SwRedlineTbl
+#include <redline.hxx> // SwRedline
+#include <section.hxx>
+#include <switerator.hxx>
+#include <IDocumentRedlineAccess.hxx>
+#include <IDocumentSettingAccess.hxx>
+#include <IDocumentContentOperations.hxx>
+
+using namespace ::com::sun::star;
+using namespace i18n::ScriptType;
+
+#include <unicode/ubidi.h>
+#include <i18nutil/unicode.hxx> //unicode::getUnicodeScriptType
+
+sal_Bool isAlefChar ( xub_Unicode cCh )
+{
+ return ( cCh == 0x622 || cCh == 0x623 || cCh == 0x625 || cCh == 0x627 ||
+ cCh == 0x622 || cCh == 0x671 || cCh == 0x672 || cCh == 0x673 || cCh == 0x675 );
+}
+
+sal_Bool isWawChar ( xub_Unicode cCh )
+{
+ return ( cCh == 0x624 || cCh == 0x648 || cCh == 0x676 || cCh == 0x677 ||
+ ( cCh >= 0x6C4 && cCh <= 0x6CB ) || cCh == 0x6CF );
+}
+
+sal_Bool isDalChar ( xub_Unicode cCh )
+{
+ return ( cCh == 0x62F || cCh == 0x630 || cCh == 0x688 || cCh == 0x689 || cCh == 0x690 );
+}
+
+sal_Bool isRehChar ( xub_Unicode cCh )
+{
+ return ( cCh == 0x631 || cCh == 0x632 || ( cCh >= 0x691 && cCh <= 0x699 ));
+}
+
+sal_Bool isTehMarbutaChar ( xub_Unicode cCh )
+{
+ return ( cCh == 0x629 || cCh == 0x6C0 );
+}
+
+sal_Bool isBaaChar ( xub_Unicode cCh )
+{
+ return ( cCh == 0x628 || cCh == 0x62A || cCh == 0x62B || cCh == 0x679 || cCh == 0x680 );
+}
+
+sal_Bool isYehChar ( xub_Unicode cCh )
+{
+ return ( cCh == 0x626 || cCh == 0x649 || cCh == 0x64A || cCh == 0x678 || cCh == 0x6CC ||
+ cCh == 0x6CE || cCh == 0x6D0 || cCh == 0x6D1 );
+}
+
+sal_Bool isSeenOrSadChar ( xub_Unicode cCh )
+{
+ return ( ( cCh >= 0x633 && cCh <= 0x636 ) || ( cCh >= 0x69A && cCh <= 0x69E )
+ || cCh == 0x6FA || cCh == 0x6FB );
+}
+
+sal_Bool isHahChar ( xub_Unicode cCh )
+{
+ return ( ( cCh >= 0x62C && cCh <= 0x62E ) || ( cCh >= 0x681 && cCh <= 0x687 )
+ || cCh == 0x6BF );
+}
+
+sal_Bool isAinChar ( xub_Unicode cCh )
+{
+ return ( cCh == 0x639 || cCh == 0x63A || cCh == 0x6A0 || cCh == 0x6FC );
+}
+
+sal_Bool isKafChar ( xub_Unicode cCh )
+{
+ return ( cCh == 0x643 || ( cCh >= 0x6AC && cCh <= 0x6AE ) );
+}
+
+sal_Bool isLamChar ( xub_Unicode cCh )
+{
+ return ( cCh == 0x644 || ( cCh >= 0x6B5 && cCh <= 0x6B8 ) );
+}
+
+sal_Bool isGafChar ( xub_Unicode cCh )
+{
+ return ( cCh == 0x6A9 || cCh == 0x6AB ||( cCh >= 0x6AF && cCh <= 0x6B4 ) );
+}
+
+sal_Bool isQafChar ( xub_Unicode cCh )
+{
+ return ( cCh == 0x642 || cCh == 0x6A7 || cCh == 0x6A8 );
+}
+
+sal_Bool isFeChar ( xub_Unicode cCh )
+{
+ return ( cCh == 0x641 || ( cCh >= 0x6A1 && cCh <= 0x6A6 ) );
+}
+sal_Bool isTransparentChar ( xub_Unicode cCh )
+{
+ return ( ( cCh >= 0x610 && cCh <= 0x61A ) ||
+ ( cCh >= 0x64B && cCh <= 0x65E ) ||
+ ( cCh == 0x670 ) ||
+ ( cCh >= 0x6D6 && cCh <= 0x6DC ) ||
+ ( cCh >= 0x6DF && cCh <= 0x6E4 ) ||
+ ( cCh >= 0x6E7 && cCh <= 0x6E8 ) ||
+ ( cCh >= 0x6EA && cCh <= 0x6ED ));
+}
+
+/*************************************************************************
+ * lcl_IsLigature
+ *
+ * Checks if cCh + cNectCh builds a ligature (used for Kashidas)
+ *************************************************************************/
+
+sal_Bool lcl_IsLigature( xub_Unicode cCh, xub_Unicode cNextCh )
+{
+ // Lam + Alef
+ return ( isLamChar ( cCh ) && isAlefChar ( cNextCh ));
+}
+
+/*************************************************************************
+ * lcl_ConnectToPrev
+ *
+ * Checks if cCh is connectable to cPrevCh (used for Kashidas)
+ *************************************************************************/
+
+sal_Bool lcl_ConnectToPrev( xub_Unicode cCh, xub_Unicode cPrevCh )
+{
+ // Alef, Dal, Thal, Reh, Zain, and Waw do not connect to the left
+ // Uh, there seem to be some more characters that are not connectable
+ // to the left. So we look for the characters that are actually connectable
+ // to the left. Here is the complete list of WH:
+
+ // (hennerdrewes):
+ // added lam forms 0x06B5..0x06B8
+ // added 0x6FA..0x6FC, according to unicode documentation, although not present in my fonts
+ // added heh goal 0x6C1
+ sal_Bool bRet = 0x628 == cPrevCh ||
+ ( 0x62A <= cPrevCh && cPrevCh <= 0x62E ) ||
+ ( 0x633 <= cPrevCh && cPrevCh <= 0x647 ) ||
+ 0x649 == cPrevCh || // Alef Maksura does connect !!!
+ 0x64A == cPrevCh ||
+ ( 0x678 <= cPrevCh && cPrevCh <= 0x687 ) ||
+ ( 0x69A <= cPrevCh && cPrevCh <= 0x6C1 ) ||
+ ( 0x6C3 <= cPrevCh && cPrevCh <= 0x6D3 ) ||
+ ( 0x6FA <= cPrevCh && cPrevCh <= 0x6FC ) ;
+
+ // check for ligatures cPrevChar + cChar
+ if( bRet )
+ bRet = !lcl_IsLigature( cPrevCh, cCh );
+ return bRet;
+}
+
+/*************************************************************************
+ * lcl_HasStrongLTR
+ *************************************************************************/
+ bool lcl_HasStrongLTR ( const String& rTxt, xub_StrLen nStart, xub_StrLen nEnd )
+ {
+ for ( xub_StrLen nCharIdx = nStart; nCharIdx < nEnd; ++nCharIdx )
+ {
+ const UCharDirection nCharDir = u_charDirection ( rTxt.GetChar ( nCharIdx ));
+ if ( nCharDir == U_LEFT_TO_RIGHT ||
+ nCharDir == U_LEFT_TO_RIGHT_EMBEDDING ||
+ nCharDir == U_LEFT_TO_RIGHT_OVERRIDE )
+ return true;
+ }
+ return false;
+ }
+
+/*************************************************************************
+ * SwLineLayout::~SwLineLayout()
+ *
+ * class SwLineLayout: Das Layout einer einzelnen Zeile. Dazu
+ * gehoeren vor allen Dingen die Dimension, die Anzahl der
+ * Character und der Wortzwischenraeume in der Zeile.
+ * Zeilenobjekte werden in einem eigenen Pool verwaltet, um zu
+ * erreichen, dass sie im Speicher moeglichst beeinander liegen
+ * (d.h. zusammen gepaged werden und den Speicher nicht
+ * fragmentieren).
+ *************************************************************************/
+
+SwLineLayout::~SwLineLayout()
+{
+ Truncate();
+ if( GetNext() )
+ delete GetNext();
+ if( pBlink )
+ pBlink->Delete( this );
+ delete pLLSpaceAdd;
+ if ( pKanaComp )
+ delete pKanaComp;
+}
+
+/*************************************************************************
+ * virtual SwLineLayout::Insert()
+ *************************************************************************/
+
+SwLinePortion *SwLineLayout::Insert( SwLinePortion *pIns )
+{
+ // Erster Attributwechsel, Masse und Laengen
+ // aus *pCurr in die erste Textportion kopieren.
+ if( !pPortion )
+ {
+ if( GetLen() )
+ {
+ pPortion = new SwTxtPortion( *(SwLinePortion*)this );
+ if( IsBlinking() && pBlink )
+ {
+ SetBlinking( sal_False );
+ pBlink->Replace( this, pPortion );
+ }
+ }
+ else
+ {
+ SetPortion( pIns );
+ return pIns;
+ }
+ }
+ // mit Skope aufrufen, sonst Rekursion !
+ return pPortion->SwLinePortion::Insert( pIns );
+}
+
+/*************************************************************************
+ * virtual SwLineLayout::Append()
+ *************************************************************************/
+
+SwLinePortion *SwLineLayout::Append( SwLinePortion *pIns )
+{
+ // Erster Attributwechsel, Masse und Laengen
+ // aus *pCurr in die erste Textportion kopieren.
+ if( !pPortion )
+ pPortion = new SwTxtPortion( *(SwLinePortion*)this );
+ // mit Skope aufrufen, sonst Rekursion !
+ return pPortion->SwLinePortion::Append( pIns );
+}
+
+/*************************************************************************
+ * virtual SwLineLayout::Format()
+ *************************************************************************/
+
+// fuer die Sonderbehandlung bei leeren Zeilen
+
+sal_Bool SwLineLayout::Format( SwTxtFormatInfo &rInf )
+{
+ if( GetLen() )
+ return SwTxtPortion::Format( rInf );
+ else
+ {
+ Height( rInf.GetTxtHeight() );
+ return sal_True;
+ }
+}
+
+/*************************************************************************
+ * SwLineLayout::CalcLeftMargin()
+ *
+ * Wir sammeln alle FlyPortions am Anfang der Zeile zu einer MarginPortion.
+ *************************************************************************/
+
+SwMarginPortion *SwLineLayout::CalcLeftMargin()
+{
+ SwMarginPortion *pLeft = (GetPortion() && GetPortion()->IsMarginPortion()) ?
+ (SwMarginPortion *)GetPortion() : 0;
+ if( !GetPortion() )
+ SetPortion( new SwTxtPortion( *(SwLinePortion*)this ) );
+ if( !pLeft )
+ {
+ pLeft = new SwMarginPortion( 0 );
+ pLeft->SetPortion( GetPortion() );
+ SetPortion( pLeft );
+ }
+ else
+ {
+ pLeft->Height( 0 );
+ pLeft->Width( 0 );
+ pLeft->SetLen( 0 );
+ pLeft->SetAscent( 0 );
+ pLeft->SetPortion( NULL );
+ pLeft->SetFixWidth(0);
+ }
+
+ SwLinePortion *pPos = pLeft->GetPortion();
+ while( pPos )
+ {
+ if( pPos->IsFlyPortion() )
+ {
+ // Die FlyPortion wird ausgesogen ...
+ pLeft->Join( (SwGluePortion*)pPos );
+ pPos = pLeft->GetPortion();
+ if( GetpKanaComp() )
+ GetKanaComp().Remove( 0, 1 );
+ }
+ else
+ pPos = 0;
+ }
+ return pLeft;
+}
+
+/*************************************************************************
+ * SwLineLayout::InitSpaceAdd()
+ *************************************************************************/
+
+void SwLineLayout::InitSpaceAdd()
+{
+ if ( !pLLSpaceAdd )
+ CreateSpaceAdd();
+ else
+ SetLLSpaceAdd( 0, 0 );
+}
+
+/*************************************************************************
+ * SwLineLayout::CreateSpaceAdd()
+ *************************************************************************/
+
+void SwLineLayout::CreateSpaceAdd( const long nInit )
+{
+ pLLSpaceAdd = new std::vector<long>;
+ SetLLSpaceAdd( nInit, 0 );
+}
+
+/*************************************************************************
+ * Local helper function. Returns true if there are only blanks
+ * in [nStt, nEnd[
+ *************************************************************************/
+
+bool lcl_HasOnlyBlanks( const XubString& rTxt, xub_StrLen nStt, xub_StrLen nEnd )
+{
+ bool bBlankOnly = true;
+ while ( nStt < nEnd )
+ {
+ const xub_Unicode cChar = rTxt.GetChar( nStt++ );
+ if ( ' ' != cChar && 0x3000 != cChar )
+ {
+ bBlankOnly = false;
+ break;
+ }
+ }
+ return bBlankOnly;
+}
+
+/*************************************************************************
+ * SwLineLayout::CalcLine()
+ *
+ * Aus FormatLine() ausgelagert.
+ *************************************************************************/
+
+void SwLineLayout::CalcLine( SwTxtFormatter &rLine, SwTxtFormatInfo &rInf )
+{
+ const KSHORT nLineWidth = rInf.RealWidth();
+
+ KSHORT nFlyAscent = 0;
+ KSHORT nFlyHeight = 0;
+ KSHORT nFlyDescent = 0;
+ sal_Bool bOnlyPostIts = sal_True;
+ SetHanging( sal_False );
+
+ sal_Bool bTmpDummy = ( 0 == GetLen() );
+ SwFlyCntPortion* pFlyCnt = 0;
+ if( bTmpDummy )
+ {
+ nFlyAscent = 0;
+ nFlyHeight = 0;
+ nFlyDescent = 0;
+ }
+
+ // --> FME 2006-03-01 #i3952#
+ const bool bIgnoreBlanksAndTabsForLineHeightCalculation =
+ rInf.GetTxtFrm()->GetNode()->getIDocumentSettingAccess()->get(IDocumentSettingAccess::IGNORE_TABS_AND_BLANKS_FOR_LINE_CALCULATION);
+
+ bool bHasBlankPortion = false;
+ bool bHasOnlyBlankPortions = true;
+ // <--
+
+ if( pPortion )
+ {
+ SetCntnt( sal_False );
+ if( pPortion->IsBreakPortion() )
+ {
+ SetLen( pPortion->GetLen() );
+ if( GetLen() )
+ bTmpDummy = sal_False;
+ }
+ else
+ {
+ Init( GetPortion() );
+ SwLinePortion *pPos = pPortion;
+ SwLinePortion *pLast = this;
+ KSHORT nMaxDescent = 0;
+
+ // Eine Gruppe ist ein Abschnitt in der Portion-Kette von
+ // pCurr oder einer Fix-Portion bis zum Ende bzw. zur naechsten
+ // Fix-Portion.
+ while( pPos )
+ {
+ OSL_ENSURE( POR_LIN != pPos->GetWhichPor(),
+ "SwLineLayout::CalcLine: don't use SwLinePortions !" );
+
+ // Null-Portions werden eliminiert. Sie koennen entstehen,
+ // wenn zwei FlyFrms ueberlappen.
+ if( !pPos->Compress() )
+ {
+ // 8110: Hoehe und Ascent nur uebernehmen, wenn sonst in der
+ // Zeile nichts mehr los ist.
+ if( !pPos->GetPortion() )
+ {
+ if( !Height() )
+ Height( pPos->Height() );
+ if( !GetAscent() )
+ SetAscent( pPos->GetAscent() );
+ }
+ delete pLast->Cut( pPos );
+ pPos = pLast->GetPortion();
+ continue;
+ }
+
+ const xub_StrLen nPorSttIdx = rInf.GetLineStart() + nLineLength;
+ nLineLength = nLineLength + pPos->GetLen();
+ AddPrtWidth( pPos->Width() );
+
+ // --> FME 2006-03-01 #i3952#
+ if ( bIgnoreBlanksAndTabsForLineHeightCalculation )
+ {
+ if ( pPos->InTabGrp() || pPos->IsHolePortion() ||
+ ( pPos->IsTextPortion() &&
+ lcl_HasOnlyBlanks( rInf.GetTxt(), nPorSttIdx, nPorSttIdx + pPos->GetLen() ) ) )
+ {
+ pLast = pPos;
+ pPos = pPos->GetPortion();
+ bHasBlankPortion = true;
+ continue;
+ }
+ }
+ // <--
+
+ bHasOnlyBlankPortions = false;
+
+ // Es gab Attributwechsel: Laengen und Masse aufaddieren;
+ // bzw.Maxima bilden.
+
+ KSHORT nPosHeight = pPos->Height();
+ KSHORT nPosAscent = pPos->GetAscent();
+
+ OSL_ENSURE( nPosHeight >= nPosAscent,
+ "SwLineLayout::CalcLine: bad ascent or height" );
+
+ if( pPos->IsHangingPortion() )
+ {
+ SetHanging( sal_True );
+ rInf.GetParaPortion()->SetMargin( sal_True );
+ }
+
+ // Damit ein Paragraphende-Zeichen nicht durch ein Descent zu einer
+ // geaenderten Zeilenhoehe und zum Umformatieren fuehrt.
+ if ( !pPos->IsBreakPortion() || !Height() )
+ {
+ bOnlyPostIts &= pPos->IsPostItsPortion();
+
+ if( bTmpDummy && !nLineLength )
+ {
+ if( pPos->IsFlyPortion() )
+ {
+ if( nFlyHeight < nPosHeight )
+ nFlyHeight = nPosHeight;
+ if( nFlyAscent < nPosAscent )
+ nFlyAscent = nPosAscent;
+ if( nFlyDescent < nPosHeight - nPosAscent )
+ nFlyDescent = nPosHeight - nPosAscent;
+ }
+ else
+ {
+ if( pPos->InNumberGrp() )
+ {
+ KSHORT nTmp = rInf.GetFont()->GetAscent(
+ rInf.GetVsh(), *rInf.GetOut() );
+ if( nTmp > nPosAscent )
+ {
+ nPosHeight += nTmp - nPosAscent;
+ nPosAscent = nTmp;
+ }
+ nTmp = rInf.GetFont()->GetHeight( rInf.GetVsh(),
+ *rInf.GetOut() );
+ if( nTmp > nPosHeight )
+ nPosHeight = nTmp;
+ }
+ Height( nPosHeight );
+ nAscent = nPosAscent;
+ nMaxDescent = nPosHeight - nPosAscent;
+ }
+ }
+ else if( !pPos->IsFlyPortion() )
+ {
+ if( Height() < nPosHeight )
+ Height( nPosHeight );
+ if( pPos->IsFlyCntPortion() || ( pPos->IsMultiPortion()
+ && ((SwMultiPortion*)pPos)->HasFlyInCntnt() ) )
+ rLine.SetFlyInCntBase();
+ if( pPos->IsFlyCntPortion() &&
+ ((SwFlyCntPortion*)pPos)->GetAlign() )
+ {
+ ((SwFlyCntPortion*)pPos)->SetMax( sal_False );
+ if( !pFlyCnt || pPos->Height() > pFlyCnt->Height() )
+ pFlyCnt = (SwFlyCntPortion*)pPos;
+ }
+ else
+ {
+ if( nAscent < nPosAscent )
+ nAscent = nPosAscent;
+ if( nMaxDescent < nPosHeight - nPosAscent )
+ nMaxDescent = nPosHeight - nPosAscent;
+ }
+ }
+ }
+ else if( pPos->GetLen() )
+ bTmpDummy = sal_False;
+
+ if( !HasCntnt() && !pPos->InNumberGrp() )
+ {
+ if ( pPos->InExpGrp() )
+ {
+ XubString aTxt;
+ if( pPos->GetExpTxt( rInf, aTxt ) && aTxt.Len() )
+ SetCntnt( sal_True );
+ }
+ else if( ( pPos->InTxtGrp() || pPos->IsMultiPortion() ) &&
+ pPos->GetLen() )
+ SetCntnt( sal_True );
+ }
+
+ bTmpDummy = bTmpDummy && !HasCntnt() &&
+ ( !pPos->Width() || pPos->IsFlyPortion() );
+
+ pLast = pPos;
+ pPos = pPos->GetPortion();
+ }
+
+ if( pFlyCnt )
+ {
+ if( pFlyCnt->Height() == Height() )
+ {
+ pFlyCnt->SetMax( sal_True );
+ if( Height() > nMaxDescent + nAscent )
+ {
+ if( 3 == pFlyCnt->GetAlign() ) // Bottom
+ nAscent = Height() - nMaxDescent;
+ else if( 2 == pFlyCnt->GetAlign() ) // Center
+ nAscent = ( Height() + nAscent - nMaxDescent ) / 2;
+ }
+ pFlyCnt->SetAscent( nAscent );
+ }
+ }
+
+ if( bTmpDummy && nFlyHeight )
+ {
+ nAscent = nFlyAscent;
+ if( nFlyDescent > nFlyHeight - nFlyAscent )
+ Height( nFlyHeight + nFlyDescent );
+ else
+ Height( nFlyHeight );
+ }
+ else if( nMaxDescent > Height() - nAscent )
+ Height( nMaxDescent + nAscent );
+
+ if( bOnlyPostIts && !( bHasBlankPortion && bHasOnlyBlankPortions ) )
+ {
+ Height( rInf.GetFont()->GetHeight( rInf.GetVsh(), *rInf.GetOut() ) );
+ nAscent = rInf.GetFont()->GetAscent( rInf.GetVsh(), *rInf.GetOut() );
+ }
+ }
+ }
+ else
+ {
+ SetCntnt( !bTmpDummy );
+
+ // --> FME 2006-03-01 #i3952#
+ if ( bIgnoreBlanksAndTabsForLineHeightCalculation &&
+ lcl_HasOnlyBlanks( rInf.GetTxt(), rInf.GetLineStart(), rInf.GetLineStart() + GetLen() ) )
+ {
+ bHasBlankPortion = true;
+ }
+ // <--
+ }
+
+ // --> FME 2006-03-01 #i3952#
+ if ( bHasBlankPortion && bHasOnlyBlankPortions )
+ {
+ sal_uInt16 nTmpAscent = GetAscent();
+ sal_uInt16 nTmpHeight = Height();
+ rLine.GetAttrHandler().GetDefaultAscentAndHeight( rInf.GetVsh(), *rInf.GetOut(), nTmpAscent, nTmpHeight );
+ SetAscent( nTmpAscent );
+ Height( nTmpHeight );
+ }
+ // <--
+
+ // Robust:
+ if( nLineWidth < Width() )
+ Width( nLineWidth );
+ OSL_ENSURE( nLineWidth >= Width(), "SwLineLayout::CalcLine: line is bursting" );
+ SetDummy( bTmpDummy );
+ SetRedline( rLine.GetRedln() &&
+ rLine.GetRedln()->CheckLine( rLine.GetStart(), rLine.GetEnd() ) );
+}
+
+// --> OD 2005-05-20 #i47162# - add optional parameter <_bNoFlyCntPorAndLinePor>
+// to control, if the fly content portions and line portion are considered.
+void SwLineLayout::MaxAscentDescent( SwTwips& _orAscent,
+ SwTwips& _orDescent,
+ SwTwips& _orObjAscent,
+ SwTwips& _orObjDescent,
+ const SwLinePortion* _pDontConsiderPortion,
+ const bool _bNoFlyCntPorAndLinePor ) const
+{
+ _orAscent = 0;
+ _orDescent = 0;
+ _orObjAscent = 0;
+ _orObjDescent = 0;
+
+ const SwLinePortion* pTmpPortion = this;
+ if ( !pTmpPortion->GetLen() && pTmpPortion->GetPortion() )
+ {
+ pTmpPortion = pTmpPortion->GetPortion();
+ }
+
+ while ( pTmpPortion )
+ {
+ if ( !pTmpPortion->IsBreakPortion() && !pTmpPortion->IsFlyPortion() &&
+ ( !_bNoFlyCntPorAndLinePor ||
+ ( !pTmpPortion->IsFlyCntPortion() &&
+ !(pTmpPortion == this && pTmpPortion->GetPortion() ) ) ) )
+ {
+ SwTwips nPortionAsc = static_cast<SwTwips>(pTmpPortion->GetAscent());
+ SwTwips nPortionDesc = static_cast<SwTwips>(pTmpPortion->Height()) -
+ nPortionAsc;
+
+ const sal_Bool bFlyCmp = pTmpPortion->IsFlyCntPortion() ?
+ static_cast<const SwFlyCntPortion*>(pTmpPortion)->IsMax() :
+ !( pTmpPortion == _pDontConsiderPortion );
+
+ if ( bFlyCmp )
+ {
+ _orObjAscent = Max( _orObjAscent, nPortionAsc );
+ _orObjDescent = Max( _orObjDescent, nPortionDesc );
+ }
+
+ if ( !pTmpPortion->IsFlyCntPortion() && !pTmpPortion->IsGrfNumPortion() )
+ {
+ _orAscent = Max( _orAscent, nPortionAsc );
+ _orDescent = Max( _orDescent, nPortionDesc );
+ }
+ }
+ pTmpPortion = pTmpPortion->GetPortion();
+ }
+}
+
+/*************************************************************************
+ * class SwCharRange
+ *************************************************************************/
+
+SwCharRange &SwCharRange::operator+=(const SwCharRange &rRange)
+{
+ if(0 != rRange.nLen ) {
+ if(0 == nLen) {
+ nStart = rRange.nStart;
+ nLen = rRange.nLen ;
+ }
+ else {
+ if(rRange.nStart + rRange.nLen > nStart + nLen) {
+ nLen = rRange.nStart + rRange.nLen - nStart;
+ }
+ if(rRange.nStart < nStart) {
+ nLen += nStart - rRange.nStart;
+ nStart = rRange.nStart;
+ }
+ }
+ }
+ return *this;
+}
+
+/*************************************************************************
+ * SwScriptInfo::SwScriptInfo()
+ *************************************************************************/
+SwScriptInfo::SwScriptInfo() :
+ nInvalidityPos( 0 ),
+ nDefaultDir( 0 )
+{
+};
+
+/*************************************************************************
+ * SwScriptInfo::~SwScriptInfo()
+ *************************************************************************/
+SwScriptInfo::~SwScriptInfo()
+{
+}
+
+/*************************************************************************
+ * SwScriptInfo::WhichFont()
+ *
+ * Converts i18n Script Type (LATIN, ASIAN, COMPLEX, WEAK) to
+ * Sw Script Types (SW_LATIN, SW_CJK, SW_CTL), used to identify the font
+ *************************************************************************/
+sal_uInt8 SwScriptInfo::WhichFont( xub_StrLen nIdx, const String* pTxt, const SwScriptInfo* pSI )
+{
+ OSL_ENSURE( pTxt || pSI,"How should I determine the script type?" );
+ sal_uInt16 nScript;
+
+ // First we try to use our SwScriptInfo
+ if ( pSI )
+ nScript = pSI->ScriptType( nIdx );
+ else
+ // Ok, we have to ask the break iterator
+ nScript = pBreakIt->GetRealScriptOfText( *pTxt, nIdx );
+
+ switch ( nScript ) {
+ case i18n::ScriptType::LATIN : return SW_LATIN;
+ case i18n::ScriptType::ASIAN : return SW_CJK;
+ case i18n::ScriptType::COMPLEX : return SW_CTL;
+ }
+
+ OSL_FAIL( "Somebody tells lies about the script type!" );
+ return SW_LATIN;
+}
+
+/*************************************************************************
+ * SwScriptInfo::InitScriptInfo()
+ *
+ * searches for script changes in rTxt and stores them
+ *************************************************************************/
+
+void SwScriptInfo::InitScriptInfo( const SwTxtNode& rNode )
+{
+ InitScriptInfo( rNode, nDefaultDir == UBIDI_RTL );
+}
+
+void SwScriptInfo::InitScriptInfo( const SwTxtNode& rNode, sal_Bool bRTL )
+{
+ if( !pBreakIt->GetBreakIter().is() )
+ return;
+
+ const String& rTxt = rNode.GetTxt();
+
+ //
+ // HIDDEN TEXT INFORMATION
+ //
+ Range aRange( 0, rTxt.Len() ? rTxt.Len() - 1 : 0 );
+ MultiSelection aHiddenMulti( aRange );
+ CalcHiddenRanges( rNode, aHiddenMulti );
+
+ aHiddenChg.clear();
+ sal_uInt16 i = 0;
+ for( i = 0; i < aHiddenMulti.GetRangeCount(); ++i )
+ {
+ const Range& rRange = aHiddenMulti.GetRange( i );
+ const xub_StrLen nStart = (xub_StrLen)rRange.Min();
+ const xub_StrLen nEnd = (xub_StrLen)rRange.Max() + 1;
+
+ aHiddenChg.push_back( nStart );
+ aHiddenChg.push_back( nEnd );
+ }
+
+ //
+ // SCRIPT AND SCRIPT RELATED INFORMATION
+ //
+
+ xub_StrLen nChg = nInvalidityPos;
+
+ // STRING_LEN means the data structure is up to date
+ nInvalidityPos = STRING_LEN;
+
+ // this is the default direction
+ nDefaultDir = static_cast<sal_uInt8>(bRTL ? UBIDI_RTL : UBIDI_LTR);
+
+ // counter for script info arrays
+ sal_uInt16 nCnt = 0;
+ // counter for compression information arrays
+ sal_uInt16 nCntComp = 0;
+ // counter for kashida array
+ sal_uInt16 nCntKash = 0;
+
+ sal_uInt8 nScript = i18n::ScriptType::LATIN;
+
+ // compression type
+ const SwCharCompressType aCompEnum = rNode.getIDocumentSettingAccess()->getCharacterCompressionType();
+
+ // justification type
+ const sal_Bool bAdjustBlock = SVX_ADJUST_BLOCK ==
+ rNode.GetSwAttrSet().GetAdjust().GetAdjust();
+
+ //
+ // FIND INVALID RANGES IN SCRIPT INFO ARRAYS:
+ //
+
+ if( nChg )
+ {
+ // if change position = 0 we do not use any data from the arrays
+ // because by deleting all characters of the first group at the beginning
+ // of a paragraph nScript is set to a wrong value
+ OSL_ENSURE( CountScriptChg(), "Where're my changes of script?" );
+ while( nCnt < CountScriptChg() )
+ {
+ if ( nChg > GetScriptChg( nCnt ) )
+ nCnt++;
+ else
+ {
+ nScript = GetScriptType( nCnt );
+ break;
+ }
+ }
+ if( CHARCOMPRESS_NONE != aCompEnum )
+ {
+ while( nCntComp < CountCompChg() )
+ {
+ if ( nChg > GetCompStart( nCntComp ) )
+ nCntComp++;
+ else
+ break;
+ }
+ }
+ if ( bAdjustBlock )
+ {
+ while( nCntKash < CountKashida() )
+ {
+ if ( nChg > GetKashida( nCntKash ) )
+ nCntKash++;
+ else
+ break;
+ }
+ }
+ }
+
+ //
+ // ADJUST nChg VALUE:
+ //
+
+ // by stepping back one position we know that we are inside a group
+ // declared as an nScript group
+ if ( nChg )
+ --nChg;
+
+ const xub_StrLen nGrpStart = nCnt ? GetScriptChg( nCnt - 1 ) : 0;
+
+ // we go back in our group until we reach the first character of
+ // type nScript
+ while ( nChg > nGrpStart &&
+ nScript != pBreakIt->GetBreakIter()->getScriptType( rTxt, nChg ) )
+ --nChg;
+
+ // If we are at the start of a group, we do not trust nScript,
+ // we better get nScript from the breakiterator:
+ if ( nChg == nGrpStart )
+ nScript = (sal_uInt8)pBreakIt->GetBreakIter()->getScriptType( rTxt, nChg );
+
+ //
+ // INVALID DATA FROM THE SCRIPT INFO ARRAYS HAS TO BE DELETED:
+ //
+
+ // remove invalid entries from script information arrays
+ aScriptChanges.erase( aScriptChanges.begin() + nCnt, aScriptChanges.end() );
+
+ // get the start of the last compression group
+ sal_uInt16 nLastCompression = nChg;
+ if( nCntComp )
+ {
+ --nCntComp;
+ nLastCompression = GetCompStart( nCntComp );
+ if( nChg >= nLastCompression + GetCompLen( nCntComp ) )
+ {
+ nLastCompression = nChg;
+ ++nCntComp;
+ }
+ }
+
+ // remove invalid entries from compression information arrays
+ aCompressionChanges.erase(aCompressionChanges.begin() + nCntComp, aCompressionChanges.end() );
+
+ // get the start of the last kashida group
+ sal_uInt16 nLastKashida = nChg;
+ if( nCntKash && i18n::ScriptType::COMPLEX == nScript )
+ {
+ --nCntKash;
+ nLastKashida = GetKashida( nCntKash );
+ }
+
+ // remove invalid entries from kashida array
+ aKashida.erase( aKashida.begin() + nCntKash, aKashida.end() );
+
+ //
+ // TAKE CARE OF WEAK CHARACTERS: WE MUST FIND AN APPROPRIATE
+ // SCRIPT FOR WEAK CHARACTERS AT THE BEGINNING OF A PARAGRAPH
+ //
+
+ if( WEAK == pBreakIt->GetBreakIter()->getScriptType( rTxt, nChg ) )
+ {
+ // If the beginning of the current group is weak, this means that
+ // all of the characters in this grounp are weak. We have to assign
+ // the scripts to these characters depending on the fonts which are
+ // set for these characters to display them.
+ xub_StrLen nEnd =
+ (xub_StrLen)pBreakIt->GetBreakIter()->endOfScript( rTxt, nChg, WEAK );
+
+ if( nEnd > rTxt.Len() )
+ nEnd = rTxt.Len();
+
+ nScript = (sal_uInt8)GetI18NScriptTypeOfLanguage( (sal_uInt16)GetAppLanguage() );
+
+ OSL_ENSURE( i18n::ScriptType::LATIN == nScript ||
+ i18n::ScriptType::ASIAN == nScript ||
+ i18n::ScriptType::COMPLEX == nScript, "Wrong default language" );
+
+ nChg = nEnd;
+
+ // Get next script type or set to weak in order to exit
+ sal_uInt8 nNextScript = ( nEnd < rTxt.Len() ) ?
+ (sal_uInt8)pBreakIt->GetBreakIter()->getScriptType( rTxt, nEnd ) :
+ (sal_uInt8)WEAK;
+
+ if ( nScript != nNextScript )
+ {
+ aScriptChanges.push_back( ScriptChangeInfo(nEnd, nScript) );
+ nCnt++;
+ nScript = nNextScript;
+ }
+ }
+
+ //
+ // UPDATE THE SCRIPT INFO ARRAYS:
+ //
+
+ while ( nChg < rTxt.Len() || ( aScriptChanges.empty() && !rTxt.Len() ) )
+ {
+ OSL_ENSURE( i18n::ScriptType::WEAK != nScript,
+ "Inserting WEAK into SwScriptInfo structure" );
+ OSL_ENSURE( STRING_LEN != nChg, "65K? Strange length of script section" );
+
+ xub_StrLen nSearchStt = nChg;
+ nChg = (xub_StrLen)pBreakIt->GetBreakIter()->endOfScript( rTxt, nSearchStt, nScript );
+
+ if ( nChg > rTxt.Len() )
+ nChg = rTxt.Len();
+
+ // --> FME 2008-09-17 #i28203#
+ // for 'complex' portions, we make sure that a portion does not contain more
+ // than one script:
+ if( i18n::ScriptType::COMPLEX == nScript && pBreakIt->GetScriptTypeDetector().is() )
+ {
+ const short nScriptType = pBreakIt->GetScriptTypeDetector()->getCTLScriptType( rTxt, nSearchStt );
+ xub_StrLen nNextCTLScriptStart = nSearchStt;
+ short nCurrentScriptType = nScriptType;
+ while( com::sun::star::i18n::CTLScriptType::CTL_UNKNOWN == nCurrentScriptType || nScriptType == nCurrentScriptType )
+ {
+ nNextCTLScriptStart = (xub_StrLen)pBreakIt->GetScriptTypeDetector()->endOfCTLScriptType( rTxt, nNextCTLScriptStart );
+ if( nNextCTLScriptStart < rTxt.Len() && nNextCTLScriptStart < nChg )
+ nCurrentScriptType = pBreakIt->GetScriptTypeDetector()->getCTLScriptType( rTxt, nNextCTLScriptStart );
+ else
+ break;
+ }
+ nChg = Min( nChg, nNextCTLScriptStart );
+ }
+ // <--
+
+ // special case for dotted circle since it can be used with complex
+ // before a mark, so we want it associated with the mark's script
+ if (nChg < rTxt.Len() && nChg > 0 && (i18n::ScriptType::WEAK ==
+ pBreakIt->GetBreakIter()->getScriptType(rTxt,nChg - 1)))
+ {
+ int8_t nType = u_charType(rTxt.GetChar(nChg) );
+ if (nType == U_NON_SPACING_MARK || nType == U_ENCLOSING_MARK ||
+ nType == U_COMBINING_SPACING_MARK )
+ {
+ aScriptChanges.push_back( ScriptChangeInfo(nChg-1, nScript) );
+ }
+ else
+ {
+ aScriptChanges.push_back( ScriptChangeInfo(nChg, nScript) );
+ }
+ }
+ else
+ {
+ aScriptChanges.push_back( ScriptChangeInfo(nChg, nScript) );
+ }
+ ++nCnt;
+
+ // if current script is asian, we search for compressable characters
+ // in this range
+ if ( CHARCOMPRESS_NONE != aCompEnum &&
+ i18n::ScriptType::ASIAN == nScript )
+ {
+ sal_uInt8 ePrevState = NONE;
+ sal_uInt8 eState;
+ sal_uInt16 nPrevChg = nLastCompression;
+
+ while ( nLastCompression < nChg )
+ {
+ xub_Unicode cChar = rTxt.GetChar( nLastCompression );
+
+ // examine current character
+ switch ( cChar )
+ {
+ // Left punctuation found
+ case 0x3008: case 0x300A: case 0x300C: case 0x300E:
+ case 0x3010: case 0x3014: case 0x3016: case 0x3018:
+ case 0x301A: case 0x301D:
+ eState = SPECIAL_LEFT;
+ break;
+ // Right punctuation found
+ case 0x3001: case 0x3002: case 0x3009: case 0x300B:
+ case 0x300D: case 0x300F: case 0x3011: case 0x3015:
+ case 0x3017: case 0x3019: case 0x301B: case 0x301E:
+ case 0x301F:
+ eState = SPECIAL_RIGHT;
+ break;
+ default:
+ eState = static_cast<sal_uInt8>( ( 0x3040 <= cChar && 0x3100 > cChar ) ? KANA : NONE );
+ }
+
+ // insert range of compressable characters
+ if( ePrevState != eState )
+ {
+ if ( ePrevState != NONE )
+ {
+ // insert start and type
+ if ( CHARCOMPRESS_PUNCTUATION_KANA == aCompEnum ||
+ ePrevState != KANA )
+ {
+ aCompressionChanges.push_back( CompressionChangeInfo(nPrevChg, nLastCompression - nPrevChg, ePrevState) );
+ }
+ }
+
+ ePrevState = eState;
+ nPrevChg = nLastCompression;
+ }
+
+ nLastCompression++;
+ }
+
+ // we still have to examine last entry
+ if ( ePrevState != NONE )
+ {
+ // insert start and type
+ if ( CHARCOMPRESS_PUNCTUATION_KANA == aCompEnum ||
+ ePrevState != KANA )
+ {
+ aCompressionChanges.push_back( CompressionChangeInfo(nPrevChg, nLastCompression - nPrevChg, ePrevState) );
+ }
+ }
+ }
+
+ // we search for connecting opportunities (kashida)
+ else if ( bAdjustBlock && i18n::ScriptType::COMPLEX == nScript )
+ {
+ SwScanner aScanner( rNode, rNode.GetTxt(), 0, 0,
+ i18n::WordType::DICTIONARY_WORD,
+ nLastKashida, nChg );
+
+ // the search has to be performed on a per word base
+ while ( aScanner.NextWord() )
+ {
+ const XubString& rWord = aScanner.GetWord();
+
+ xub_StrLen nIdx = 0;
+ xub_StrLen nKashidaPos = STRING_LEN;
+ xub_Unicode cCh;
+ xub_Unicode cPrevCh = 0;
+
+ sal_uInt16 nPriorityLevel = 7; // 0..6 = level found
+ // 7 not found
+
+ xub_StrLen nWordLen = rWord.Len();
+
+ // ignore trailing vowel chars
+ while( nWordLen && isTransparentChar( rWord.GetChar( nWordLen - 1 )))
+ --nWordLen;
+
+ while (nIdx < nWordLen)
+ {
+ cCh = rWord.GetChar( nIdx );
+
+ // 1. Priority:
+ // after user inserted kashida
+ if ( 0x640 == cCh )
+ {
+ nKashidaPos = aScanner.GetBegin() + nIdx;
+ nPriorityLevel = 0;
+ }
+
+ // 2. Priority:
+ // after a Seen or Sad
+ if (nPriorityLevel >= 1 && nIdx < nWordLen - 1)
+ {
+ if( isSeenOrSadChar( cCh )
+ && (rWord.GetChar( nIdx+1 ) != 0x200C) ) // #i98410#: prevent ZWNJ expansion
+ {
+ nKashidaPos = aScanner.GetBegin() + nIdx;
+ nPriorityLevel = 1;
+ }
+ }
+
+ // 3. Priority:
+ // before final form of Teh Marbuta, Hah, Dal
+ if ( nPriorityLevel >= 2 && nIdx > 0 )
+ {
+ if ( isTehMarbutaChar ( cCh ) || // Teh Marbuta (right joining)
+ isDalChar ( cCh ) || // Dal (right joining) final form may appear in the middle of word
+ ( isHahChar ( cCh ) && nIdx == nWordLen - 1)) // Hah (dual joining) only at end of word
+ {
+
+ OSL_ENSURE( 0 != cPrevCh, "No previous character" );
+ // check if character is connectable to previous character,
+ if ( lcl_ConnectToPrev( cCh, cPrevCh ) )
+ {
+ nKashidaPos = aScanner.GetBegin() + nIdx - 1;
+ nPriorityLevel = 2;
+ }
+ }
+ }
+
+ // 4. Priority:
+ // before final form of Alef, Lam or Kaf
+ if ( nPriorityLevel >= 3 && nIdx > 0 )
+ {
+ if ( isAlefChar ( cCh ) || // Alef (right joining) final form may appear in the middle of word
+ (( isLamChar ( cCh ) || // Lam
+ isKafChar ( cCh ) || // Kaf (both dual joining)
+ isGafChar ( cCh ) )
+ && nIdx == nWordLen - 1)) // only at end of word
+ {
+ OSL_ENSURE( 0 != cPrevCh, "No previous character" );
+ // check if character is connectable to previous character,
+ if ( lcl_ConnectToPrev( cCh, cPrevCh ) )
+ {
+ nKashidaPos = aScanner.GetBegin() + nIdx - 1;
+ nPriorityLevel = 3;
+ }
+ }
+ }
+
+ // 5. Priority:
+ // before media Bah
+ if ( nPriorityLevel >= 4 && nIdx > 0 && nIdx < nWordLen - 1 )
+ {
+ if ( isBaaChar ( cCh )) // Bah
+ {
+ // check if next character is Reh, Yeh or Alef Maksura
+ xub_Unicode cNextCh = rWord.GetChar( nIdx + 1 );
+ if ( isRehChar ( cNextCh ) || isYehChar ( cNextCh ))
+ {
+ OSL_ENSURE( 0 != cPrevCh, "No previous character" );
+ // check if character is connectable to previous character,
+ if ( lcl_ConnectToPrev( cCh, cPrevCh ) )
+ {
+ nKashidaPos = aScanner.GetBegin() + nIdx - 1;
+ nPriorityLevel = 4;
+ }
+ }
+ }
+ }
+
+ // 6. Priority:
+ // before the final form of Waw, Ain, Qaf and Fa
+ if ( nPriorityLevel >= 5 && nIdx > 0 )
+ {
+ if ( isWawChar ( cCh ) || // Wav (right joining)
+ // final form may appear in the middle of word
+ (( isAinChar ( cCh ) || // Ain (dual joining)
+ isQafChar ( cCh ) || // Qaf (dual joining)
+ isFeChar ( cCh ) ) // Feh (dual joining)
+ && nIdx == nWordLen - 1)) // only at end of word
+ {
+ OSL_ENSURE( 0 != cPrevCh, "No previous character" );
+ // check if character is connectable to previous character,
+ if ( lcl_ConnectToPrev( cCh, cPrevCh ) )
+ {
+ nKashidaPos = aScanner.GetBegin() + nIdx - 1;
+ nPriorityLevel = 5;
+ }
+ }
+ }
+
+ // other connecting possibilities
+ if ( nPriorityLevel >= 6 && nIdx > 0 )
+ {
+ // remaining right joiners
+ // Reh, Zain, Thal,
+ if ( isRehChar ( cCh ) || // Reh Zain (right joining)
+ // final form may appear in the middle of word
+ ( 0x60C <= cCh && 0x6FE >= cCh // all others
+ && nIdx == nWordLen - 1)) // only at end of word
+ {
+ OSL_ENSURE( 0 != cPrevCh, "No previous character" );
+ // check if character is connectable to previous character,
+ if ( lcl_ConnectToPrev( cCh, cPrevCh ) )
+ {
+ nKashidaPos = aScanner.GetBegin() + nIdx - 1;
+ nPriorityLevel = 6;
+ }
+ }
+ }
+
+ // Do not consider Fathatan, Dammatan, Kasratan, Fatha,
+ // Damma, Kasra, Shadda and Sukun when checking if
+ // a character can be connected to previous character.
+ if ( !isTransparentChar ( cCh) )
+ cPrevCh = cCh;
+
+ ++nIdx;
+ } // end of current word
+
+ if ( STRING_LEN != nKashidaPos )
+ {
+ aKashida.insert( aKashida.begin() + nCntKash, nKashidaPos);
+ nCntKash++;
+ }
+ } // end of kashida search
+ }
+
+ if ( nChg < rTxt.Len() )
+ nScript = (sal_uInt8)pBreakIt->GetBreakIter()->getScriptType( rTxt, nChg );
+
+ nLastCompression = nChg;
+ nLastKashida = nChg;
+ }
+
+#if OSL_DEBUG_LEVEL > 1
+ // check kashida data
+ long nTmpKashidaPos = -1;
+ sal_Bool bWrongKash = sal_False;
+ for (i = 0; i < aKashida.size(); ++i )
+ {
+ long nCurrKashidaPos = GetKashida( i );
+ if ( nCurrKashidaPos <= nTmpKashidaPos )
+ {
+ bWrongKash = sal_True;
+ break;
+ }
+ nTmpKashidaPos = nCurrKashidaPos;
+ }
+ OSL_ENSURE( ! bWrongKash, "Kashida array contains wrong data" );
+#endif
+
+ // remove invalid entries from direction information arrays
+ aDirectionChanges.clear();
+
+ // Perform Unicode Bidi Algorithm for text direction information
+ bool bPerformUBA = UBIDI_LTR != nDefaultDir;
+ nCnt = 0;
+ while( !bPerformUBA && nCnt < CountScriptChg() )
+ {
+ if ( i18n::ScriptType::COMPLEX == GetScriptType( nCnt++ ) )
+ bPerformUBA = true;
+ }
+
+ // do not call the unicode bidi algorithm if not required
+ if ( bPerformUBA )
+ {
+ UpdateBidiInfo( rTxt );
+
+ // #i16354# Change script type for RTL text to CTL:
+ // 1. All text in RTL runs will use the CTL font
+ // #i89825# change the script type also to CTL (hennerdrewes)
+ // 2. Text in embedded LTR runs that does not have any strong LTR characters (numbers!)
+ for ( sal_uInt32 nDirIdx = 0; nDirIdx < aDirectionChanges.size(); ++nDirIdx )
+ {
+ const sal_uInt8 nCurrDirType = GetDirType( nDirIdx );
+ // nStart ist start of RTL run:
+ const xub_StrLen nStart = nDirIdx > 0 ? GetDirChg( nDirIdx - 1 ) : 0;
+ // nEnd is end of RTL run:
+ const xub_StrLen nEnd = GetDirChg( nDirIdx );
+
+ if ( nCurrDirType % 2 == UBIDI_RTL || // text in RTL run
+ ( nCurrDirType > UBIDI_LTR && !lcl_HasStrongLTR( rTxt, nStart, nEnd ) ) ) // non-strong text in embedded LTR run
+ {
+ // nScriptIdx points into the ScriptArrays:
+ size_t nScriptIdx = 0;
+
+ // Skip entries in ScriptArray which are not inside the RTL run:
+ // Make nScriptIdx become the index of the script group with
+ // 1. nStartPosOfGroup <= nStart and
+ // 2. nEndPosOfGroup > nStart
+ while ( GetScriptChg( nScriptIdx ) <= nStart )
+ ++nScriptIdx;
+
+ const xub_StrLen nStartPosOfGroup = nScriptIdx ? GetScriptChg( nScriptIdx - 1 ) : 0;
+ const sal_uInt8 nScriptTypeOfGroup = GetScriptType( nScriptIdx );
+
+ OSL_ENSURE( nStartPosOfGroup <= nStart && GetScriptChg( nScriptIdx ) > nStart,
+ "Script override with CTL font trouble" );
+
+ // Check if we have to insert a new script change at
+ // position nStart. If nStartPosOfGroup < nStart,
+ // we have to insert a new script change:
+ if ( nStart > 0 && nStartPosOfGroup < nStart )
+ {
+ aScriptChanges.insert(aScriptChanges.begin() + nScriptIdx,
+ ScriptChangeInfo(nStart, nScriptTypeOfGroup) );
+ ++nScriptIdx;
+ }
+
+ // Remove entries in ScriptArray which end inside the RTL run:
+ while ( nScriptIdx < aScriptChanges.size() && GetScriptChg( nScriptIdx ) <= nEnd )
+ {
+ aScriptChanges.erase(aScriptChanges.begin() + nScriptIdx);
+ }
+
+ // Insert a new entry in ScriptArray for the end of the RTL run:
+ aScriptChanges.insert(aScriptChanges.begin() + nScriptIdx,
+ ScriptChangeInfo(nEnd, i18n::ScriptType::COMPLEX) );
+
+#if OSL_DEBUG_LEVEL > 1
+ // Check that ScriptChangeInfos are in increasing order of
+ // position and that we don't have "empty" changes.
+ sal_uInt8 nLastTyp = i18n::ScriptType::WEAK;
+ xub_StrLen nLastPos = 0;
+ for (std::vector<ScriptChangeInfo>::const_iterator i2 = aScriptChanges.begin(); i2 < aScriptChanges.end(); ++i2)
+ {
+ OSL_ENSURE( nLastTyp != i2->type &&
+ nLastPos < i2->position,
+ "Heavy InitScriptType() confusion" );
+ nLastPos = i2->position;
+ nLastTyp = i2->type;
+ }
+#endif
+ }
+ }
+ }
+}
+
+void SwScriptInfo::UpdateBidiInfo( const String& rTxt )
+{
+ // remove invalid entries from direction information arrays
+ aDirectionChanges.clear();
+ //
+ // Bidi functions from icu 2.0
+ //
+ UErrorCode nError = U_ZERO_ERROR;
+ UBiDi* pBidi = ubidi_openSized( rTxt.Len(), 0, &nError );
+ nError = U_ZERO_ERROR;
+
+ ubidi_setPara( pBidi, reinterpret_cast<const UChar *>(rTxt.GetBuffer()), rTxt.Len(), // UChar != sal_Unicode in MinGW
+ nDefaultDir, NULL, &nError );
+ nError = U_ZERO_ERROR;
+ long nCount = ubidi_countRuns( pBidi, &nError );
+ int32_t nStart = 0;
+ int32_t nEnd;
+ UBiDiLevel nCurrDir;
+ for ( sal_uInt16 nIdx = 0; nIdx < nCount; ++nIdx )
+ {
+ ubidi_getLogicalRun( pBidi, nStart, &nEnd, &nCurrDir );
+ aDirectionChanges.push_back( DirectionChangeInfo(nEnd, nCurrDir) );
+ nStart = nEnd;
+ }
+
+ ubidi_close( pBidi );
+}
+
+
+/*************************************************************************
+ * SwScriptInfo::NextScriptChg(..)
+ * returns the position of the next character which belongs to another script
+ * than the character of the actual (input) position.
+ * If there's no script change until the end of the paragraph, it will return
+ * STRING_LEN.
+ * Scripts are Asian (Chinese, Japanese, Korean),
+ * Latin ( English etc.)
+ * and Complex ( Hebrew, Arabian )
+ *************************************************************************/
+
+xub_StrLen SwScriptInfo::NextScriptChg( const xub_StrLen nPos ) const
+{
+ sal_uInt16 nEnd = CountScriptChg();
+ for( sal_uInt16 nX = 0; nX < nEnd; ++nX )
+ {
+ if( nPos < GetScriptChg( nX ) )
+ return GetScriptChg( nX );
+ }
+
+ return STRING_LEN;
+}
+
+/*************************************************************************
+ * SwScriptInfo::ScriptType(..)
+ * returns the script of the character at the input position
+ *************************************************************************/
+
+sal_uInt8 SwScriptInfo::ScriptType( const xub_StrLen nPos ) const
+{
+ sal_uInt16 nEnd = CountScriptChg();
+ for( sal_uInt16 nX = 0; nX < nEnd; ++nX )
+ {
+ if( nPos < GetScriptChg( nX ) )
+ return GetScriptType( nX );
+ }
+
+ // the default is the application language script
+ return (sal_uInt8)GetI18NScriptTypeOfLanguage( (sal_uInt16)GetAppLanguage() );
+}
+
+xub_StrLen SwScriptInfo::NextDirChg( const xub_StrLen nPos,
+ const sal_uInt8* pLevel ) const
+{
+ sal_uInt8 nCurrDir = pLevel ? *pLevel : 62;
+ sal_uInt16 nEnd = CountDirChg();
+ for( sal_uInt16 nX = 0; nX < nEnd; ++nX )
+ {
+ if( nPos < GetDirChg( nX ) &&
+ ( nX + 1 == nEnd || GetDirType( nX + 1 ) <= nCurrDir ) )
+ return GetDirChg( nX );
+ }
+
+ return STRING_LEN;
+}
+
+sal_uInt8 SwScriptInfo::DirType( const xub_StrLen nPos ) const
+{
+ sal_uInt16 nEnd = CountDirChg();
+ for( sal_uInt16 nX = 0; nX < nEnd; ++nX )
+ {
+ if( nPos < GetDirChg( nX ) )
+ return GetDirType( nX );
+ }
+
+ return 0;
+}
+
+/*************************************************************************
+ * SwScriptInfo::MaskHiddenRanges(..)
+ * Takes a string and replaced the hidden ranges with cChar.
+ **************************************************************************/
+
+sal_uInt16 SwScriptInfo::MaskHiddenRanges( const SwTxtNode& rNode, XubString& rText,
+ const xub_StrLen nStt, const xub_StrLen nEnd,
+ const xub_Unicode cChar )
+{
+ OSL_ENSURE( rNode.GetTxt().Len() == rText.Len(), "MaskHiddenRanges, string len mismatch" );
+
+ PositionList aList;
+ xub_StrLen nHiddenStart;
+ xub_StrLen nHiddenEnd;
+ sal_uInt16 nNumOfHiddenChars = 0;
+ GetBoundsOfHiddenRange( rNode, 0, nHiddenStart, nHiddenEnd, &aList );
+ PositionList::const_reverse_iterator rFirst( aList.end() );
+ PositionList::const_reverse_iterator rLast( aList.begin() );
+ while ( rFirst != rLast )
+ {
+ nHiddenEnd = *(rFirst++);
+ nHiddenStart = *(rFirst++);
+
+ if ( nHiddenEnd < nStt || nHiddenStart > nEnd )
+ continue;
+
+ while ( nHiddenStart < nHiddenEnd && nHiddenStart < nEnd )
+ {
+ if ( nHiddenStart >= nStt && nHiddenStart < nEnd )
+ {
+ rText.SetChar( nHiddenStart, cChar );
+ ++nNumOfHiddenChars;
+ }
+ ++nHiddenStart;
+ }
+ }
+
+ return nNumOfHiddenChars;
+}
+
+/*************************************************************************
+ * SwScriptInfo::DeleteHiddenRanges(..)
+ * Takes a SwTxtNode and deletes the hidden ranges from the node.
+ **************************************************************************/
+
+void SwScriptInfo::DeleteHiddenRanges( SwTxtNode& rNode )
+{
+ PositionList aList;
+ xub_StrLen nHiddenStart;
+ xub_StrLen nHiddenEnd;
+ GetBoundsOfHiddenRange( rNode, 0, nHiddenStart, nHiddenEnd, &aList );
+ PositionList::const_reverse_iterator rFirst( aList.end() );
+ PositionList::const_reverse_iterator rLast( aList.begin() );
+ while ( rFirst != rLast )
+ {
+ nHiddenEnd = *(rFirst++);
+ nHiddenStart = *(rFirst++);
+
+ SwPaM aPam( rNode, nHiddenStart, rNode, nHiddenEnd );
+ rNode.getIDocumentContentOperations()->DeleteRange( aPam );
+ }
+}
+
+/*************************************************************************
+ * SwScriptInfo::GetBoundsOfHiddenRange(..)
+ * static version
+ **************************************************************************/
+
+bool SwScriptInfo::GetBoundsOfHiddenRange( const SwTxtNode& rNode, xub_StrLen nPos,
+ xub_StrLen& rnStartPos, xub_StrLen& rnEndPos,
+ PositionList* pList )
+{
+ rnStartPos = STRING_LEN;
+ rnEndPos = 0;
+
+ bool bNewContainsHiddenChars = false;
+
+ //
+ // Optimization: First examine the flags at the text node:
+ //
+ if ( !rNode.IsCalcHiddenCharFlags() )
+ {
+ bool bWholePara = rNode.HasHiddenCharAttribute( true );
+ bool bContainsHiddenChars = rNode.HasHiddenCharAttribute( false );
+ if ( !bContainsHiddenChars )
+ return false;
+
+ if ( bWholePara )
+ {
+ if ( pList )
+ {
+ pList->push_back( 0 );
+ pList->push_back( rNode.GetTxt().Len() );
+ }
+
+ rnStartPos = 0;
+ rnEndPos = rNode.GetTxt().Len();
+ return true;
+ }
+ }
+
+ const SwScriptInfo* pSI = SwScriptInfo::GetScriptInfo( rNode );
+ if ( pSI )
+ {
+ //
+ // Check first, if we have a valid SwScriptInfo object for this text node:
+ //
+ bNewContainsHiddenChars = pSI->GetBoundsOfHiddenRange( nPos, rnStartPos, rnEndPos, pList );
+ const bool bNewHiddenCharsHidePara = ( rnStartPos == 0 && rnEndPos >= rNode.GetTxt().Len() );
+ rNode.SetHiddenCharAttribute( bNewHiddenCharsHidePara, bNewContainsHiddenChars );
+ }
+ else
+ {
+ //
+ // No valid SwScriptInfo Object, we have to do it the hard way:
+ //
+ Range aRange( 0, rNode.GetTxt().Len() ? rNode.GetTxt().Len() - 1 : 0 );
+ MultiSelection aHiddenMulti( aRange );
+ SwScriptInfo::CalcHiddenRanges( rNode, aHiddenMulti );
+ for( sal_uInt16 i = 0; i < aHiddenMulti.GetRangeCount(); ++i )
+ {
+ const Range& rRange = aHiddenMulti.GetRange( i );
+ const xub_StrLen nHiddenStart = (xub_StrLen)rRange.Min();
+ const xub_StrLen nHiddenEnd = (xub_StrLen)rRange.Max() + 1;
+
+ if ( nHiddenStart > nPos )
+ break;
+ else if ( nHiddenStart <= nPos && nPos < nHiddenEnd )
+ {
+ rnStartPos = nHiddenStart;
+ rnEndPos = Min( nHiddenEnd, rNode.GetTxt().Len() );
+ break;
+ }
+ }
+
+ if ( pList )
+ {
+ for( sal_uInt16 i = 0; i < aHiddenMulti.GetRangeCount(); ++i )
+ {
+ const Range& rRange = aHiddenMulti.GetRange( i );
+ pList->push_back( (xub_StrLen)rRange.Min() );
+ pList->push_back( (xub_StrLen)rRange.Max() + 1 );
+ }
+ }
+
+ bNewContainsHiddenChars = aHiddenMulti.GetRangeCount() > 0;
+ }
+
+ return bNewContainsHiddenChars;
+}
+
+/*************************************************************************
+ * SwScriptInfo::GetBoundsOfHiddenRange(..)
+ * non-static version
+ **************************************************************************/
+
+bool SwScriptInfo::GetBoundsOfHiddenRange( xub_StrLen nPos, xub_StrLen& rnStartPos,
+ xub_StrLen& rnEndPos, PositionList* pList ) const
+{
+ rnStartPos = STRING_LEN;
+ rnEndPos = 0;
+
+ sal_uInt16 nEnd = CountHiddenChg();
+ for( sal_uInt16 nX = 0; nX < nEnd; ++nX )
+ {
+ const xub_StrLen nHiddenStart = GetHiddenChg( nX++ );
+ const xub_StrLen nHiddenEnd = GetHiddenChg( nX );
+
+ if ( nHiddenStart > nPos )
+ break;
+ else if ( nHiddenStart <= nPos && nPos < nHiddenEnd )
+ {
+ rnStartPos = nHiddenStart;
+ rnEndPos = nHiddenEnd;
+ break;
+ }
+ }
+
+ if ( pList )
+ {
+ for( sal_uInt16 nX = 0; nX < nEnd; ++nX )
+ {
+ pList->push_back( GetHiddenChg( nX++ ) );
+ pList->push_back( GetHiddenChg( nX ) );
+ }
+ }
+
+ return CountHiddenChg() > 0;
+}
+
+/*************************************************************************
+ * SwScriptInfo::IsInHiddenRange()
+ **************************************************************************/
+
+bool SwScriptInfo::IsInHiddenRange( const SwTxtNode& rNode, xub_StrLen nPos )
+{
+ xub_StrLen nStartPos;
+ xub_StrLen nEndPos;
+ SwScriptInfo::GetBoundsOfHiddenRange( rNode, nPos, nStartPos, nEndPos );
+ return nStartPos != STRING_LEN;
+}
+
+
+#if OSL_DEBUG_LEVEL > 1
+/*************************************************************************
+ * SwScriptInfo::CompType(..)
+ * returns the type of the compressed character
+ *************************************************************************/
+
+sal_uInt8 SwScriptInfo::CompType( const xub_StrLen nPos ) const
+{
+ sal_uInt16 nEnd = CountCompChg();
+ for( sal_uInt16 nX = 0; nX < nEnd; ++nX )
+ {
+ xub_StrLen nChg = GetCompStart( nX );
+
+ if ( nPos < nChg )
+ return NONE;
+
+ if( nPos < nChg + GetCompLen( nX ) )
+ return GetCompType( nX );
+ }
+ return NONE;
+}
+#endif
+
+/*************************************************************************
+ * SwScriptInfo::HasKana()
+ * returns, if there are compressable kanas or specials
+ * betwenn nStart and nEnd
+ *************************************************************************/
+
+sal_uInt16 SwScriptInfo::HasKana( xub_StrLen nStart, const xub_StrLen nLen ) const
+{
+ sal_uInt16 nCnt = CountCompChg();
+ xub_StrLen nEnd = nStart + nLen;
+
+ for( sal_uInt16 nX = 0; nX < nCnt; ++nX )
+ {
+ xub_StrLen nKanaStart = GetCompStart( nX );
+ xub_StrLen nKanaEnd = nKanaStart + GetCompLen( nX );
+
+ if ( nKanaStart >= nEnd )
+ return USHRT_MAX;
+
+ if ( nStart < nKanaEnd )
+ return nX;
+ }
+
+ return USHRT_MAX;
+}
+
+/*************************************************************************
+ * SwScriptInfo::Compress()
+ *************************************************************************/
+
+long SwScriptInfo::Compress( sal_Int32* pKernArray, xub_StrLen nIdx, xub_StrLen nLen,
+ const sal_uInt16 nCompress, const sal_uInt16 nFontHeight,
+ Point* pPoint ) const
+{
+ OSL_ENSURE( nCompress, "Compression without compression?!" );
+ OSL_ENSURE( nLen, "Compression without text?!" );
+ sal_uInt16 nCompCount = CountCompChg();
+
+ // In asian typography, there are full width and half width characters.
+ // Full width punctuation characters can be compressed by 50 %
+ // to determine this, we compare the font width with 75 % of its height
+ sal_uInt16 nMinWidth = ( 3 * nFontHeight ) / 4;
+
+ sal_uInt16 nCompIdx = HasKana( nIdx, nLen );
+
+ if ( USHRT_MAX == nCompIdx )
+ return 0;
+
+ xub_StrLen nChg = GetCompStart( nCompIdx );
+ xub_StrLen nCompLen = GetCompLen( nCompIdx );
+ sal_uInt16 nI = 0;
+ nLen = nLen + nIdx;
+
+ if( nChg > nIdx )
+ {
+ nI = nChg - nIdx;
+ nIdx = nChg;
+ }
+ else if( nIdx < nChg + nCompLen )
+ nCompLen -= nIdx - nChg;
+
+ if( nIdx > nLen || nCompIdx >= nCompCount )
+ return 0;
+
+ long nSub = 0;
+ long nLast = nI ? pKernArray[ nI - 1 ] : 0;
+ do
+ {
+ sal_uInt16 nType = GetCompType( nCompIdx );
+#if OSL_DEBUG_LEVEL > 1
+ OSL_ENSURE( nType == CompType( nIdx ), "Gimme the right type!" );
+#endif
+ nCompLen = nCompLen + nIdx;
+ if( nCompLen > nLen )
+ nCompLen = nLen;
+
+ // are we allowed to compress the character?
+ if ( pKernArray[ nI ] - nLast < nMinWidth )
+ {
+ nIdx++; nI++;
+ }
+ else
+ {
+ while( nIdx < nCompLen )
+ {
+ OSL_ENSURE( SwScriptInfo::NONE != nType, "None compression?!" );
+
+ // nLast is width of current character
+ nLast -= pKernArray[ nI ];
+
+ nLast *= nCompress;
+ long nMove = 0;
+ if( SwScriptInfo::KANA != nType )
+ {
+ nLast /= 20000;
+ if( pPoint && SwScriptInfo::SPECIAL_LEFT == nType )
+ {
+ if( nI )
+ nMove = nLast;
+ else
+ {
+ pPoint->X() += nLast;
+ nLast = 0;
+ }
+ }
+ }
+ else
+ nLast /= 100000;
+ nSub -= nLast;
+ nLast = pKernArray[ nI ];
+ if( nMove )
+ pKernArray[ nI - 1 ] += nMove;
+ pKernArray[ nI++ ] -= nSub;
+ ++nIdx;
+ }
+ }
+
+ if( nIdx < nLen )
+ {
+ xub_StrLen nTmpChg;
+ if( ++nCompIdx < nCompCount )
+ {
+ nTmpChg = GetCompStart( nCompIdx );
+ if( nTmpChg > nLen )
+ nTmpChg = nLen;
+ nCompLen = GetCompLen( nCompIdx );
+ }
+ else
+ nTmpChg = nLen;
+ while( nIdx < nTmpChg )
+ {
+ nLast = pKernArray[ nI ];
+ pKernArray[ nI++ ] -= nSub;
+ ++nIdx;
+ }
+ }
+ else
+ break;
+ } while( nIdx < nLen );
+ return nSub;
+}
+
+/*************************************************************************
+ * SwScriptInfo::KashidaJustify()
+ *************************************************************************/
+
+// Note on calling KashidaJustify():
+// Kashida positions may be marked as invalid. Therefore KashidaJustify may return the clean
+// total number of kashida positions, or the number of kashida positions after some positions
+// have been dropped, depending on the state of the aKashidaInvalid array.
+
+sal_uInt16 SwScriptInfo::KashidaJustify( sal_Int32* pKernArray,
+ sal_Int32* pScrArray,
+ xub_StrLen nStt,
+ xub_StrLen nLen,
+ long nSpaceAdd ) const
+{
+ OSL_ENSURE( nLen, "Kashida justification without text?!" );
+
+ if( !IsKashidaLine(nStt))
+ return STRING_LEN;
+
+ // evaluate kashida informatin in collected in SwScriptInfo
+
+ sal_uInt16 nCntKash = 0;
+ while( nCntKash < CountKashida() )
+ {
+ if ( nStt <= GetKashida( nCntKash ) )
+ break;
+ else
+ nCntKash++;
+ }
+
+ const xub_StrLen nEnd = nStt + nLen;
+
+ sal_uInt16 nCntKashEnd = nCntKash;
+ while ( nCntKashEnd < CountKashida() )
+ {
+ if ( nEnd <= GetKashida( nCntKashEnd ) )
+ break;
+ else
+ nCntKashEnd++;
+ }
+
+ sal_uInt16 nActualKashCount = nCntKashEnd - nCntKash;
+ for ( sal_uInt16 i = nCntKash; i < nCntKashEnd; ++i )
+ {
+ if ( nActualKashCount && !IsKashidaValid ( i ) )
+ --nActualKashCount;
+ }
+
+ if ( !pKernArray )
+ return nActualKashCount;
+
+ // do nothing if there is no more kashida
+ if ( nCntKash < CountKashida() )
+ {
+ // skip any invalid kashidas
+ while ( ! IsKashidaValid ( nCntKash ) && nCntKash < nCntKashEnd )
+ ++nCntKash;
+
+ xub_StrLen nKashidaPos = GetKashida( nCntKash );
+ xub_StrLen nIdx = nKashidaPos;
+ long nKashAdd = nSpaceAdd;
+
+ while ( nIdx < nEnd )
+ {
+ sal_uInt16 nArrayPos = nIdx - nStt;
+
+ // next kashida position
+ ++nCntKash;
+ while ( ! IsKashidaValid ( nCntKash ) && nCntKash < nCntKashEnd )
+ ++nCntKash;
+
+ nIdx = nCntKash < CountKashida() && IsKashidaValid ( nCntKash ) ? GetKashida( nCntKash ) : nEnd;
+ if ( nIdx > nEnd )
+ nIdx = nEnd;
+
+ const sal_uInt16 nArrayEnd = nIdx - nStt;
+
+ while ( nArrayPos < nArrayEnd )
+ {
+ pKernArray[ nArrayPos ] += nKashAdd;
+ if ( pScrArray )
+ pScrArray[ nArrayPos ] += nKashAdd;
+ ++nArrayPos;
+ }
+ nKashAdd += nSpaceAdd;
+ }
+ }
+
+ return 0;
+}
+
+/*************************************************************************
+ * SwScriptInfo::IsArabicText()
+ *
+ * Checks if the current text is 'Arabic' text. Note that only the first
+ * character has to be checked because a ctl portion only contains one
+ * script, see NewTxtPortion
+ *************************************************************************/
+sal_Bool SwScriptInfo::IsArabicText( const XubString& rTxt, xub_StrLen nStt, xub_StrLen nLen )
+{
+ using namespace ::com::sun::star::i18n;
+ static ScriptTypeList typeList[] = {
+ { UnicodeScript_kArabic, UnicodeScript_kArabic, UnicodeScript_kArabic }, // 11,
+ { UnicodeScript_kScriptCount, UnicodeScript_kScriptCount, UnicodeScript_kScriptCount } // 88
+ };
+
+ // go forward if current position does not hold a regular character:
+ const CharClass& rCC = GetAppCharClass();
+ sal_Int32 nIdx = nStt;
+ const xub_StrLen nEnd = nStt + nLen;
+ while ( nIdx < nEnd && !rCC.isLetterNumeric( rTxt, (xub_StrLen)nIdx ) )
+ {
+ ++nIdx;
+ }
+
+ if( nIdx == nEnd )
+ {
+ // no regular character found in this portion. Go backward:
+ --nIdx;
+ while ( nIdx >= 0 && !rCC.isLetterNumeric( rTxt, (xub_StrLen)nIdx ) )
+ {
+ --nIdx;
+ }
+ }
+
+ if( nIdx >= 0 )
+ {
+ const xub_Unicode cCh = rTxt.GetChar( (xub_StrLen)nIdx );
+ const sal_Int16 type = unicode::getUnicodeScriptType( cCh, typeList, UnicodeScript_kScriptCount );
+ return type == UnicodeScript_kArabic;
+ }
+ return sal_False;
+}
+
+/*************************************************************************
+ * SwScriptInfo::IsKashidaValid()
+ *************************************************************************/
+
+sal_Bool SwScriptInfo::IsKashidaValid ( xub_StrLen nKashPos ) const
+{
+ for ( size_t i = 0; i < aKashidaInvalid.size(); ++i )
+ {
+ if ( aKashidaInvalid [ i ] == nKashPos )
+ return false;
+ }
+ return true;
+}
+
+/*************************************************************************
+ * SwScriptInfo::ClearKashidaInvalid()
+ *************************************************************************/
+
+void SwScriptInfo::ClearKashidaInvalid ( xub_StrLen nKashPos )
+{
+ for ( size_t i = 0; i < aKashidaInvalid.size(); ++i )
+ {
+ if ( aKashidaInvalid [ i ] == nKashPos )
+ {
+ aKashidaInvalid.erase ( aKashidaInvalid.begin() + i );
+ return;
+ }
+ }
+}
+
+/*************************************************************************
+ * SwScriptInfo::MarkOrClearKashidaInvalid()
+ *************************************************************************/
+// bMark == true:
+// marks the first valid kashida in the given text range as invalid
+
+// bMark == false:
+// clears all kashida invalid flags in the given text range
+
+bool SwScriptInfo::MarkOrClearKashidaInvalid ( xub_StrLen nStt, xub_StrLen nLen, bool bMark, xub_StrLen nMarkCount )
+{
+ sal_uInt16 nCntKash = 0;
+ while( nCntKash < CountKashida() )
+ {
+ if ( nStt <= GetKashida( nCntKash ) )
+ break;
+ else
+ nCntKash++;
+ }
+
+ const xub_StrLen nEnd = nStt + nLen;
+
+ while ( nCntKash < CountKashida() )
+ {
+ if ( nEnd <= GetKashida( nCntKash ) )
+ break;
+ else
+ {
+ if(bMark)
+ {
+ if ( IsKashidaValid ( nCntKash ) )
+ {
+ MarkKashidaInvalid ( nCntKash );
+ --nMarkCount;
+ if(!nMarkCount)
+ return true;
+ }
+ }
+ else
+ {
+ ClearKashidaInvalid ( nCntKash );
+ }
+ nCntKash++;
+ }
+ }
+ return false;
+}
+
+void SwScriptInfo::MarkKashidaInvalid ( xub_StrLen nKashPos )
+{
+ aKashidaInvalid.push_back( nKashPos );
+}
+
+/*************************************************************************
+ * SwScriptInfo::GetKashidaPositions()
+ *************************************************************************/
+// retrieve the kashida positions in the given text range
+sal_uInt16 SwScriptInfo::GetKashidaPositions ( xub_StrLen nStt, xub_StrLen nLen,
+ xub_StrLen* pKashidaPosition )
+{
+ sal_uInt16 nCntKash = 0;
+ while( nCntKash < CountKashida() )
+ {
+ if ( nStt <= GetKashida( nCntKash ) )
+ break;
+ else
+ nCntKash++;
+ }
+
+ const xub_StrLen nEnd = nStt + nLen;
+
+ sal_uInt16 nCntKashEnd = nCntKash;
+ while ( nCntKashEnd < CountKashida() )
+ {
+ if ( nEnd <= GetKashida( nCntKashEnd ) )
+ break;
+ else
+ {
+ pKashidaPosition [ nCntKashEnd - nCntKash ] = GetKashida ( nCntKashEnd );
+ nCntKashEnd++;
+ }
+ }
+ return nCntKashEnd - nCntKash;
+}
+
+void SwScriptInfo::SetNoKashidaLine ( xub_StrLen nStt, xub_StrLen nLen )
+{
+ aNoKashidaLine.push_back( nStt );
+ aNoKashidaLineEnd.push_back( nStt+nLen );
+}
+
+/*************************************************************************
+ * SwScriptInfo::IsKashidaLine()
+ *************************************************************************/
+// determines if the line uses kashida justification
+
+bool SwScriptInfo::IsKashidaLine ( xub_StrLen nCharIdx ) const
+{
+ for( size_t i = 0; i < aNoKashidaLine.size(); ++i )
+ {
+ if( nCharIdx >= aNoKashidaLine[ i ] && nCharIdx < aNoKashidaLineEnd[ i ])
+ return false;
+ }
+ return true;
+}
+/*************************************************************************
+ * SwScriptInfo::ClearKashidaLine()
+ *************************************************************************/
+
+void SwScriptInfo::ClearNoKashidaLine ( xub_StrLen nStt, xub_StrLen nLen )
+{
+ size_t i = 0;
+ while( i < aNoKashidaLine.size())
+ {
+ if( nStt + nLen >= aNoKashidaLine[ i ] && nStt < aNoKashidaLineEnd [ i ] )
+ {
+ aNoKashidaLine.erase(aNoKashidaLine.begin() + i);
+ aNoKashidaLineEnd.erase(aNoKashidaLineEnd.begin() + i);
+ }
+ else
+ ++i;
+ }
+}
+
+/*************************************************************************
+ * SwScriptInfo::MarkKashidasInvalid()
+ *************************************************************************/
+// mark the given character indices as invalid kashida positions
+bool SwScriptInfo::MarkKashidasInvalid ( xub_StrLen nCnt, xub_StrLen* pKashidaPositions )
+{
+ OSL_ENSURE( pKashidaPositions && nCnt > 0, "Where are kashidas?" );
+
+ sal_uInt16 nCntKash = 0;
+ xub_StrLen nKashidaPosIdx = 0;
+
+ while ( nCntKash < CountKashida() && nKashidaPosIdx < nCnt )
+ {
+ if ( pKashidaPositions [nKashidaPosIdx] > GetKashida( nCntKash ) )
+ {
+ nCntKash++;
+ continue;
+ }
+
+ if ( pKashidaPositions [nKashidaPosIdx] == GetKashida( nCntKash ) && IsKashidaValid ( nCntKash ) )
+ {
+ MarkKashidaInvalid ( nCntKash );
+ }
+ else
+ return false; // something is wrong
+ nKashidaPosIdx++;
+ }
+ return true;
+}
+
+/*************************************************************************
+ * SwScriptInfo::ThaiJustify()
+ *************************************************************************/
+
+sal_uInt16 SwScriptInfo::ThaiJustify( const XubString& rTxt, sal_Int32* pKernArray,
+ sal_Int32* pScrArray, xub_StrLen nStt,
+ xub_StrLen nLen, xub_StrLen nNumberOfBlanks,
+ long nSpaceAdd )
+{
+ OSL_ENSURE( nStt + nLen <= rTxt.Len(), "String in ThaiJustify too small" );
+
+ SwTwips nNumOfTwipsToDistribute = nSpaceAdd * nNumberOfBlanks /
+ SPACING_PRECISION_FACTOR;
+
+ long nSpaceSum = 0;
+ sal_uInt16 nCnt = 0;
+
+ for ( sal_uInt16 nI = 0; nI < nLen; ++nI )
+ {
+ const xub_Unicode cCh = rTxt.GetChar( nStt + nI );
+
+ // check if character is not above or below base
+ if ( ( 0xE34 > cCh || cCh > 0xE3A ) &&
+ ( 0xE47 > cCh || cCh > 0xE4E ) && cCh != 0xE31 )
+ {
+ if ( nNumberOfBlanks > 0 )
+ {
+ nSpaceAdd = nNumOfTwipsToDistribute / nNumberOfBlanks;
+ --nNumberOfBlanks;
+ nNumOfTwipsToDistribute -= nSpaceAdd;
+ }
+ nSpaceSum += nSpaceAdd;
+ ++nCnt;
+ }
+
+ if ( pKernArray ) pKernArray[ nI ] += nSpaceSum;
+ if ( pScrArray ) pScrArray[ nI ] += nSpaceSum;
+ }
+
+ return nCnt;
+}
+
+/*************************************************************************
+ * SwScriptInfo::GetScriptInfo()
+ *************************************************************************/
+
+SwScriptInfo* SwScriptInfo::GetScriptInfo( const SwTxtNode& rTNd,
+ sal_Bool bAllowInvalid )
+{
+ SwIterator<SwTxtFrm,SwTxtNode> aIter( rTNd );
+ SwScriptInfo* pScriptInfo = 0;
+
+ for( SwTxtFrm* pLast = aIter.First(); pLast; pLast = aIter.Next() )
+ {
+ pScriptInfo = (SwScriptInfo*)pLast->GetScriptInfo();
+ if ( pScriptInfo )
+ {
+ if ( !bAllowInvalid && STRING_LEN != pScriptInfo->GetInvalidity() )
+ pScriptInfo = 0;
+ else break;
+ }
+ }
+
+ return pScriptInfo;
+}
+
+/*************************************************************************
+ * SwParaPortion::SwParaPortion()
+ *************************************************************************/
+SwParaPortion::SwParaPortion()
+{
+ FormatReset();
+ bFlys = bFtnNum = bMargin = sal_False;
+ SetWhichPor( POR_PARA );
+}
+
+/*************************************************************************
+ * SwParaPortion::~SwParaPortion()
+ *************************************************************************/
+SwParaPortion::~SwParaPortion()
+{
+}
+
+/*************************************************************************
+ * SwParaPortion::GetParLen()
+ *************************************************************************/
+xub_StrLen SwParaPortion::GetParLen() const
+{
+ xub_StrLen nLen = 0;
+ const SwLineLayout *pLay = this;
+ while( pLay )
+ {
+ nLen = nLen + pLay->GetLen();
+ pLay = pLay->GetNext();
+ }
+ return nLen;
+}
+
+/*************************************************************************
+ * SwParaPortion::FindDropPortion()
+ *************************************************************************/
+
+const SwDropPortion *SwParaPortion::FindDropPortion() const
+{
+ const SwLineLayout *pLay = this;
+ while( pLay && pLay->IsDummy() )
+ pLay = pLay->GetNext();
+ while( pLay )
+ {
+ const SwLinePortion *pPos = pLay->GetPortion();
+ while ( pPos && !pPos->GetLen() )
+ pPos = pPos->GetPortion();
+ if( pPos && pPos->IsDropPortion() )
+ return (SwDropPortion *)pPos;
+ pLay = pLay->GetLen() ? NULL : pLay->GetNext();
+ }
+ return NULL;
+}
+
+/*************************************************************************
+ * SwLineLayout::Init()
+ *************************************************************************/
+
+void SwLineLayout::Init( SwLinePortion* pNextPortion )
+{
+ Height( 0 );
+ Width( 0 );
+ SetLen( 0 );
+ SetAscent( 0 );
+ SetRealHeight( 0 );
+ SetPortion( pNextPortion );
+}
+
+/*--------------------------------------------------
+ * HangingMargin()
+ * looks for hanging punctuation portions in the paragraph
+ * and return the maximum right offset of them.
+ * If no such portion is found, the Margin/Hanging-flags will be atualized.
+ * --------------------------------------------------*/
+
+SwTwips SwLineLayout::_GetHangingMargin() const
+{
+ SwLinePortion* pPor = GetPortion();
+ sal_Bool bFound = sal_False;
+ SwTwips nDiff = 0;
+ while( pPor)
+ {
+ if( pPor->IsHangingPortion() )
+ {
+ nDiff = ((SwHangingPortion*)pPor)->GetInnerWidth() - pPor->Width();
+ if( nDiff )
+ bFound = sal_True;
+ }
+ // the last post its portion
+ else if ( pPor->IsPostItsPortion() && ! pPor->GetPortion() )
+ nDiff = nAscent;
+
+ pPor = pPor->GetPortion();
+ }
+ if( !bFound ) // actualize the hanging-flag
+ ((SwLineLayout*)this)->SetHanging( sal_False );
+ return nDiff;
+}
+
+SwTwips SwTxtFrm::HangingMargin() const
+{
+ OSL_ENSURE( HasPara(), "Don't call me without a paraportion" );
+ if( !GetPara()->IsMargin() )
+ return 0;
+ const SwLineLayout* pLine = GetPara();
+ SwTwips nRet = 0;
+ do
+ {
+ SwTwips nDiff = pLine->GetHangingMargin();
+ if( nDiff > nRet )
+ nRet = nDiff;
+ pLine = pLine->GetNext();
+ } while ( pLine );
+ if( !nRet ) // actualize the margin-flag
+ ((SwParaPortion*)GetPara())->SetMargin( sal_False );
+ return nRet;
+}
+
+
+/*************************************************************************
+ * SwScriptInfo::CalcHiddenRanges()
+ *
+ * Returns a MultiSection indicating the hidden ranges.
+ *************************************************************************/
+
+void SwScriptInfo::CalcHiddenRanges( const SwTxtNode& rNode, MultiSelection& rHiddenMulti )
+{
+ const SfxPoolItem* pItem = 0;
+ if( SFX_ITEM_SET == rNode.GetSwAttrSet().GetItemState( RES_CHRATR_HIDDEN, sal_True, &pItem ) &&
+ ((SvxCharHiddenItem*)pItem)->GetValue() )
+ {
+ rHiddenMulti.SelectAll();
+ }
+
+ const SwpHints* pHints = rNode.GetpSwpHints();
+ const SwTxtAttr* pTxtAttr = 0;
+
+ if( pHints )
+ {
+ MSHORT nTmp = 0;
+
+ while( nTmp < pHints->GetStartCount() )
+ {
+ pTxtAttr = pHints->GetStart( nTmp++ );
+ const SvxCharHiddenItem* pHiddenItem = static_cast<const SvxCharHiddenItem*>( CharFmt::GetItem( *pTxtAttr, RES_CHRATR_HIDDEN ) );
+ if( pHiddenItem )
+ {
+ xub_StrLen nSt = *pTxtAttr->GetStart();
+ xub_StrLen nEnd = *pTxtAttr->GetEnd();
+ if( nEnd > nSt )
+ {
+ Range aTmp( nSt, nEnd - 1 );
+ rHiddenMulti.Select( aTmp, pHiddenItem->GetValue() );
+ }
+ }
+ }
+ }
+
+ // If there are any hidden ranges in the current text node, we have
+ // to unhide the redlining ranges:
+ const IDocumentRedlineAccess& rIDRA = *rNode.getIDocumentRedlineAccess();
+ if ( rHiddenMulti.GetRangeCount() && IDocumentRedlineAccess::IsShowChanges( rIDRA.GetRedlineMode() ) )
+ {
+ sal_uInt16 nAct = rIDRA.GetRedlinePos( rNode, USHRT_MAX );
+
+ for ( ; nAct < rIDRA.GetRedlineTbl().Count(); nAct++ )
+ {
+ const SwRedline* pRed = rIDRA.GetRedlineTbl()[ nAct ];
+
+ if ( pRed->Start()->nNode > rNode.GetIndex() )
+ break;
+
+ xub_StrLen nRedlStart;
+ xub_StrLen nRedlnEnd;
+ pRed->CalcStartEnd( rNode.GetIndex(), nRedlStart, nRedlnEnd );
+ if ( nRedlnEnd > nRedlStart )
+ {
+ Range aTmp( nRedlStart, nRedlnEnd - 1 );
+ rHiddenMulti.Select( aTmp, false );
+ }
+ }
+ }
+
+ //
+ // We calculated a lot of stuff. Finally we can update the flags at the text node.
+ //
+ const bool bNewContainsHiddenChars = rHiddenMulti.GetRangeCount() > 0;
+ bool bNewHiddenCharsHidePara = false;
+ if ( bNewContainsHiddenChars )
+ {
+ const Range& rRange = rHiddenMulti.GetRange( 0 );
+ const xub_StrLen nHiddenStart = (xub_StrLen)rRange.Min();
+ const xub_StrLen nHiddenEnd = (xub_StrLen)rRange.Max() + 1;
+ bNewHiddenCharsHidePara = ( nHiddenStart == 0 && nHiddenEnd >= rNode.GetTxt().Len() );
+ }
+ rNode.SetHiddenCharAttribute( bNewHiddenCharsHidePara, bNewContainsHiddenChars );
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/text/porlay.hxx b/sw/source/core/text/porlay.hxx
new file mode 100644
index 000000000000..fb9ffd504152
--- /dev/null
+++ b/sw/source/core/text/porlay.hxx
@@ -0,0 +1,436 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+#ifndef _PORLAY_HXX
+#define _PORLAY_HXX
+
+#include <tools/string.hxx>
+#include <tools/fract.hxx>
+#include <scriptinfo.hxx>
+
+#include "swrect.hxx" // SwRepaint
+#include "portxt.hxx"
+#include "swfont.hxx"
+
+#include <vector>
+
+class SwMarginPortion;
+class SwDropPortion;
+class SvStream;
+class SwTxtFormatter;
+
+/*************************************************************************
+ * class SwCharRange
+ *************************************************************************/
+
+class SwCharRange
+{
+ xub_StrLen nStart, nLen;
+public:
+ inline SwCharRange( const xub_StrLen nInitStart = 0,
+ const xub_StrLen nInitLen = 0): nStart( nInitStart ), nLen(nInitLen) {}
+ inline xub_StrLen &Start() { return nStart; }
+ inline const xub_StrLen &Start() const { return nStart; }
+ inline void LeftMove( xub_StrLen nNew )
+ { if ( nNew < nStart ) { nLen += nStart-nNew; nStart = nNew; } }
+ inline xub_StrLen End() const
+ { return nStart + nLen; }
+ inline xub_StrLen &Len() { return nLen; }
+ inline const xub_StrLen &Len() const { return nLen; }
+ inline sal_Bool operator<(const SwCharRange &rRange) const
+ { return nStart < rRange.nStart; }
+ inline sal_Bool operator>(const SwCharRange &rRange) const
+ { return nStart + nLen > rRange.nStart + rRange.nLen; }
+ inline sal_Bool operator!=(const SwCharRange &rRange) const
+ { return *this < rRange || *this > rRange; }
+ SwCharRange &operator+=(const SwCharRange &rRange);
+};
+
+/*************************************************************************
+ * class SwRepaint
+ *************************************************************************/
+
+// SwRepaint ist ein dokumentglobales SwRect mit einem nOfst der angibt,
+// ab wo in der ersten Zeile gepaintet werden soll
+// und einem nRightOfst, der den rechten Rand bestimmt
+class SwRepaint : public SwRect
+{
+ SwTwips nOfst;
+ SwTwips nRightOfst;
+public:
+ SwRepaint() : SwRect(), nOfst( 0 ), nRightOfst( 0 ) {}
+ SwRepaint( const SwRepaint& rRep ) : SwRect( rRep ), nOfst( rRep.nOfst ),
+ nRightOfst( rRep.nRightOfst ) {}
+
+ SwTwips GetOfst() const { return nOfst; }
+ void SetOfst( const SwTwips nNew ) { nOfst = nNew; }
+ SwTwips GetRightOfst() const { return nRightOfst; }
+ void SetRightOfst( const SwTwips nNew ) { nRightOfst = nNew; }
+};
+
+/*************************************************************************
+ * class SwLineLayout
+ *************************************************************************/
+
+class SwLineLayout : public SwTxtPortion
+{
+private:
+ SwLineLayout *pNext; // Die naechste Zeile.
+ std::vector<long>* pLLSpaceAdd; // Used for justified alignment.
+ SvUShorts* pKanaComp; // Used for Kana compression.
+ KSHORT nRealHeight; // Die aus Zeilenabstand/Register resultierende Hoehe.
+ sal_Bool bFormatAdj : 1;
+ sal_Bool bDummy : 1;
+ sal_Bool bFntChg : 1;
+ sal_Bool bEndHyph : 1;
+ sal_Bool bMidHyph : 1;
+ sal_Bool bTab : 1;
+ sal_Bool bFly : 1;
+ sal_Bool bRest : 1;
+ sal_Bool bBlinking : 1;
+ sal_Bool bClipping : 1; // Clipping erforderlich wg. exakter Zeilenhoehe
+ sal_Bool bContent : 1; // enthaelt Text, fuer Zeilennumerierung
+ sal_Bool bRedline : 1; // enthaelt Redlining
+ sal_Bool bForcedLeftMargin : 1; // vom Fly verschobener linker Einzug
+ sal_Bool bHanging : 1; // contents a hanging portion in the margin
+ sal_Bool bUnderscore : 1;
+
+ SwTwips _GetHangingMargin() const;
+
+public:
+ // von SwLinePortion
+ virtual SwLinePortion *Insert( SwLinePortion *pPortion );
+ virtual SwLinePortion *Append( SwLinePortion *pPortion );
+ inline SwLinePortion *GetFirstPortion() const;
+
+ // Flags
+ inline void ResetFlags();
+ inline void SetFormatAdj( const sal_Bool bNew ) { bFormatAdj = bNew; }
+ inline sal_Bool IsFormatAdj() const { return bFormatAdj; }
+ inline void SetFntChg( const sal_Bool bNew ) { bFntChg = bNew; }
+ inline sal_Bool IsFntChg() const { return bFntChg; }
+ inline void SetEndHyph( const sal_Bool bNew ) { bEndHyph = bNew; }
+ inline sal_Bool IsEndHyph() const { return bEndHyph; }
+ inline void SetMidHyph( const sal_Bool bNew ) { bMidHyph = bNew; }
+ inline sal_Bool IsMidHyph() const { return bMidHyph; }
+ inline void SetTab( const sal_Bool bNew ) { bTab = bNew; }
+ inline sal_Bool IsTab() const { return bTab; }
+ inline void SetFly( const sal_Bool bNew ) { bFly = bNew; }
+ inline sal_Bool IsFly() const { return bFly; }
+ inline void SetRest( const sal_Bool bNew ) { bRest = bNew; }
+ inline sal_Bool IsRest() const { return bRest; }
+ inline void SetBlinking( const sal_Bool bNew = sal_True ) { bBlinking = bNew; }
+ inline sal_Bool IsBlinking() const { return bBlinking; }
+ inline void SetCntnt( const sal_Bool bNew = sal_True ) { bContent = bNew; }
+ inline sal_Bool HasCntnt() const { return bContent; }
+ inline void SetRedline( const sal_Bool bNew = sal_True ) { bRedline = bNew; }
+ inline sal_Bool HasRedline() const { return bRedline; }
+ inline void SetForcedLeftMargin( const sal_Bool bNew = sal_True ) { bForcedLeftMargin = bNew; }
+ inline sal_Bool HasForcedLeftMargin() const { return bForcedLeftMargin; }
+ inline void SetHanging( const sal_Bool bNew = sal_True ) { bHanging = bNew; }
+ inline sal_Bool IsHanging() const { return bHanging; }
+ inline void SetUnderscore( const sal_Bool bNew = sal_True ) { bUnderscore = bNew; }
+ inline sal_Bool HasUnderscore() const { return bUnderscore; }
+
+ // Beruecksichtigung von Dummyleerzeilen
+ // 4147, 8221:
+ inline void SetDummy( const sal_Bool bNew ) { bDummy = bNew; }
+ inline sal_Bool IsDummy() const { return bDummy; }
+
+ inline void SetClipping( const sal_Bool bNew ) { bClipping = bNew; }
+ inline sal_Bool IsClipping() const { return bClipping; }
+
+ inline SwLineLayout();
+ virtual ~SwLineLayout();
+
+ inline SwLineLayout *GetNext() { return pNext; }
+ inline const SwLineLayout *GetNext() const { return pNext; }
+ inline void SetNext( SwLineLayout *pNew ) { pNext = pNew; }
+
+ void Init( SwLinePortion *pNextPortion = NULL);
+
+ // Sammelt die Daten fuer die Zeile.
+ void CalcLine( SwTxtFormatter &rLine, SwTxtFormatInfo &rInf );
+
+ inline void SetRealHeight( KSHORT nNew ) { nRealHeight = nNew; }
+ inline KSHORT GetRealHeight() const { return nRealHeight; }
+
+ // Erstellt bei kurzen Zeilen die Glue-Kette.
+ SwMarginPortion *CalcLeftMargin();
+
+ inline SwTwips GetHangingMargin() const
+ { return _GetHangingMargin(); }
+
+ // fuer die Sonderbehandlung bei leeren Zeilen
+ virtual sal_Bool Format( SwTxtFormatInfo &rInf );
+
+ //
+ // STUFF FOR JUSTIFIED ALIGNMENT
+ //
+ inline sal_Bool IsSpaceAdd() { return pLLSpaceAdd != NULL; }
+ void InitSpaceAdd(); // Creates pLLSpaceAdd if necessary
+ void CreateSpaceAdd( const long nInit = 0 );
+ inline void FinishSpaceAdd() { delete pLLSpaceAdd; pLLSpaceAdd = NULL; }
+ inline sal_uInt16 GetLLSpaceAddCount() const { return sal::static_int_cast< sal_uInt16 >(pLLSpaceAdd->size()); }
+ inline void SetLLSpaceAdd( long nNew, sal_uInt16 nIdx )
+ {
+ if ( nIdx == GetLLSpaceAddCount() )
+ pLLSpaceAdd->push_back( nNew );
+ else
+ (*pLLSpaceAdd)[ nIdx ] = nNew;
+ }
+ inline long GetLLSpaceAdd( sal_uInt16 nIdx ) { return (*pLLSpaceAdd)[ nIdx ]; }
+ inline void RemoveFirstLLSpaceAdd() { pLLSpaceAdd->erase( pLLSpaceAdd->begin() ); }
+ inline std::vector<long>* GetpLLSpaceAdd() const { return pLLSpaceAdd; }
+
+ //
+ // STUFF FOR KANA COMPRESSION
+ //
+ inline void SetKanaComp( SvUShorts* pNew ){ pKanaComp = pNew; }
+ inline void FinishKanaComp() { delete pKanaComp; pKanaComp = NULL; }
+ inline SvUShorts* GetpKanaComp() const { return pKanaComp; }
+ inline SvUShorts& GetKanaComp() { return *pKanaComp; }
+
+ /** determine ascent and descent for positioning of as-character anchored
+ object
+
+ OD 07.01.2004 #i11859# - previously local method <lcl_MaxAscDescent>
+ Method calculates maximum ascents and descents of the line layout.
+ One value considering as-character anchored objects, one without these
+ objects.
+ Portions for other anchored objects aren't considered.
+ OD 2005-05-20 #i47162# - add optional parameter <_bNoFlyCntPorAndLinePor>
+ to control, if the fly content portions and line portion are considered.
+
+ @param _orAscent
+ output parameter - maximum ascent without as-character anchored objects
+
+ @param _orDescent
+ output parameter - maximum descent without as-character anchored objects
+
+ @param _orObjAscent
+ output parameter - maximum ascent with as-character anchored objects
+
+ @param _orObjDescent
+ output parameter - maximum descent with as-character anchored objects
+
+ @param _pDontConsiderPortion
+ input parameter - portion, which isn't considered for calculating
+ <_orObjAscent> and <_orObjDescent>, if it isn't a portion for a
+ as-character anchored object or it isn't as high as the line.
+
+ @param _bNoFlyCntPorAndLinePor
+ optional input parameter - boolean, indicating that fly content portions
+ and the line portion are considered or not.
+
+ @author OD
+ */
+ void MaxAscentDescent( SwTwips& _orAscent,
+ SwTwips& _orDescent,
+ SwTwips& _orObjAscent,
+ SwTwips& _orObjDescent,
+ const SwLinePortion* _pDontConsiderPortion = NULL,
+ const bool _bNoFlyCntPorAndLinePor = false ) const;
+
+#if OSL_DEBUG_LEVEL > 1
+ void DebugPortions( SvStream &rOs, const XubString &rTxt,
+ const xub_StrLen nStart ); //$ ostream
+
+ void dumpLineAsXml(xmlTextWriter* writer, sal_uInt16& ofs, String& aText);
+#endif
+
+ OUTPUT_OPERATOR
+ DECL_FIXEDMEMPOOL_NEWDEL(SwLineLayout)
+};
+
+class SwParaPortion : public SwLineLayout
+{
+ // neu zu paintender Bereich
+ SwRepaint aRepaint;
+ // neu zu formatierender Bereich
+ SwCharRange aReformat;
+ SwScriptInfo aScriptInfo;
+// Fraction aZoom;
+ long nDelta;
+
+ // Wenn ein SwTxtFrm gelocked ist, werden keine Veraenderungen an den
+ // Formatierungsdaten (unter pLine) vorgenommen (vgl. ORPHANS)
+ sal_Bool bFlys : 1; // Ueberlappen Flys ?
+ sal_Bool bPrep : 1; // PREP_*
+ sal_Bool bPrepWidows : 1; // PREP_WIDOWS
+ sal_Bool bPrepAdjust : 1; // PREP_ADJUST_FRM
+ sal_Bool bPrepMustFit : 1; // PREP_MUST_FIT
+ sal_Bool bFollowField : 1; // Es steht noch ein Feldrest fuer den Follow an.
+
+ sal_Bool bFixLineHeight : 1; // Feste Zeilenhoehe
+ sal_Bool bFtnNum : 1; // contents a footnotenumberportion
+ sal_Bool bMargin : 1; // contents a hanging punctuation in the margin
+
+ sal_Bool bFlag00 : 1; //
+ sal_Bool bFlag11 : 1; //
+ sal_Bool bFlag12 : 1; //
+ sal_Bool bFlag13 : 1; //
+ sal_Bool bFlag14 : 1; //
+ sal_Bool bFlag15 : 1; //
+ sal_Bool bFlag16 : 1; //
+
+public:
+ SwParaPortion();
+ virtual ~SwParaPortion();
+
+ // setzt alle Formatinformationen zurueck (ausser bFlys wg. 9916)
+ inline void FormatReset();
+
+ // Setzt die Flags zurueck
+ inline void ResetPreps();
+
+ // Get/Set-Methoden
+ inline SwRepaint *GetRepaint() { return &aRepaint; }
+ inline const SwRepaint *GetRepaint() const { return &aRepaint; }
+ inline SwCharRange *GetReformat() { return &aReformat; }
+ inline const SwCharRange *GetReformat() const { return &aReformat; }
+ inline long *GetDelta() { return &nDelta; }
+ inline const long *GetDelta() const { return &nDelta; }
+ inline SwScriptInfo& GetScriptInfo() { return aScriptInfo; }
+ inline const SwScriptInfo& GetScriptInfo() const { return aScriptInfo; }
+
+ // fuer SwTxtFrm::Format: liefert die aktuelle Laenge des Absatzes
+ xub_StrLen GetParLen() const;
+
+ // fuer Prepare()
+ sal_Bool UpdateQuoVadis( const XubString &rQuo );
+
+ // Flags
+ inline void SetFly( const sal_Bool bNew = sal_True ) { bFlys = bNew; }
+ inline sal_Bool HasFly() const { return bFlys; }
+
+ // Preps
+ inline void SetPrep( const sal_Bool bNew = sal_True ) { bPrep = bNew; }
+ inline sal_Bool IsPrep() const { return bPrep; }
+ inline void SetPrepWidows( const sal_Bool bNew = sal_True ) { bPrepWidows = bNew; }
+ inline sal_Bool IsPrepWidows() const { return bPrepWidows; }
+ inline void SetPrepMustFit( const sal_Bool bNew = sal_True ) { bPrepMustFit = bNew; }
+ inline sal_Bool IsPrepMustFit() const { return bPrepMustFit; }
+ inline void SetPrepAdjust( const sal_Bool bNew = sal_True ) { bPrepAdjust = bNew; }
+ inline sal_Bool IsPrepAdjust() const { return bPrepAdjust; }
+ inline void SetFollowField( const sal_Bool bNew = sal_True ) { bFollowField = bNew; }
+ inline sal_Bool IsFollowField() const { return bFollowField; }
+ inline void SetFixLineHeight( const sal_Bool bNew = sal_True ) { bFixLineHeight = bNew; }
+ inline sal_Bool IsFixLineHeight() const { return bFixLineHeight; }
+
+ inline void SetFtnNum( const sal_Bool bNew = sal_True ) { bFtnNum = bNew; }
+ inline sal_Bool IsFtnNum() const { return bFtnNum; }
+ inline void SetMargin( const sal_Bool bNew = sal_True ) { bMargin = bNew; }
+ inline sal_Bool IsMargin() const { return bMargin; }
+ inline void SetFlag00( const sal_Bool bNew = sal_True ) { bFlag00 = bNew; }
+ inline sal_Bool IsFlag00() const { return bFlag00; }
+ inline void SetFlag11( const sal_Bool bNew = sal_True ) { bFlag11 = bNew; }
+ inline sal_Bool IsFlag11() const { return bFlag11; }
+ inline void SetFlag12( const sal_Bool bNew = sal_True ) { bFlag12 = bNew; }
+ inline sal_Bool IsFlag12() const { return bFlag12; }
+ inline void SetFlag13( const sal_Bool bNew = sal_True ) { bFlag13 = bNew; }
+ inline sal_Bool IsFlag13() const { return bFlag13; }
+ inline void SetFlag14( const sal_Bool bNew = sal_True ) { bFlag14 = bNew; }
+ inline sal_Bool IsFlag14() const { return bFlag14; }
+ inline void SetFlag15( const sal_Bool bNew = sal_True ) { bFlag15 = bNew; }
+ inline sal_Bool IsFlag15() const { return bFlag15; }
+ inline void SetFlag16( const sal_Bool bNew = sal_True ) { bFlag16 = bNew; }
+ inline sal_Bool IsFlag16() const { return bFlag16; }
+
+ // schneller, hoeher, weiter: Read/Write-Methoden fuer den SWG-Filter
+ SvStream &ReadSwg ( SvStream& rStream ); //$ istream
+ SvStream &WriteSwg( SvStream& rStream ); //$ ostream
+
+ // nErgo in der QuoVadisPortion setzen
+ void SetErgoSumNum( const XubString &rErgo );
+
+ const SwDropPortion *FindDropPortion() const;
+
+#if OSL_DEBUG_LEVEL > 1
+ void dumpAsXml( xmlTextWriter* writer, SwTxtFrm* pTxtFrm );
+#endif
+
+ OUTPUT_OPERATOR
+ DECL_FIXEDMEMPOOL_NEWDEL(SwParaPortion)
+};
+
+/*************************************************************************
+ * Inline-Implementierungen
+ *************************************************************************/
+
+inline void SwLineLayout::ResetFlags()
+{
+ bFormatAdj = bDummy = bFntChg = bTab = bEndHyph = bMidHyph = bFly
+ = bRest = bBlinking = bClipping = bContent = bRedline
+ = bForcedLeftMargin = bHanging = sal_False;
+}
+
+inline SwLineLayout::SwLineLayout()
+ : pNext( 0 ), pLLSpaceAdd( 0 ), pKanaComp( 0 ), nRealHeight( 0 ),
+ bUnderscore( sal_False )
+{
+ ResetFlags();
+ SetWhichPor( POR_LAY );
+}
+
+inline void SwParaPortion::ResetPreps()
+{
+ bPrep = bPrepWidows = bPrepAdjust = bPrepMustFit = sal_False;
+}
+
+inline void SwParaPortion::FormatReset()
+{
+ nDelta = 0;
+ aReformat = SwCharRange( 0, STRING_LEN );
+// AMA 9916: bFlys muss in SwTxtFrm::_Format() erhalten bleiben, damit
+// leere Absaetze, die Rahmen ohne Umfluss ausweichen mussten, sich
+// neu formatieren, wenn der Rahmen aus dem Bereich verschwindet.
+// bFlys = sal_False;
+ ResetPreps();
+ bFollowField = bFixLineHeight = bMargin = sal_False;
+}
+
+#ifdef UNX
+// C30 ist mit dem ternaeren Ausdruck ueberfordert.
+inline SwLinePortion *SwLineLayout::GetFirstPortion() const
+{
+ SwLinePortion *pTmp = pPortion;
+ if ( !pPortion )
+ pTmp = (SwLinePortion*)this;
+ return( pTmp );
+}
+#else
+inline SwLinePortion *SwLineLayout::GetFirstPortion() const
+{ return( pPortion ? pPortion : (SwLinePortion*)this ); }
+#endif
+
+CLASSIO( SwLineLayout )
+CLASSIO( SwParaPortion )
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/text/porlin.cxx b/sw/source/core/text/porlin.cxx
new file mode 100644
index 000000000000..da677f83c077
--- /dev/null
+++ b/sw/source/core/text/porlin.cxx
@@ -0,0 +1,420 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+
+#include <vcl/outdev.hxx>
+#include <SwPortionHandler.hxx>
+
+#include "porlin.hxx"
+#include "inftxt.hxx"
+#include "portxt.hxx"
+#include "pormulti.hxx"
+#include "porglue.hxx"
+#include "blink.hxx"
+#if OSL_DEBUG_LEVEL > 1
+
+sal_Bool ChkChain( SwLinePortion *pStart )
+{
+ SwLinePortion *pPor = pStart->GetPortion();
+ MSHORT nCount = 0;
+ while( pPor )
+ {
+ ++nCount;
+ OSL_ENSURE( nCount < 200 && pPor != pStart,
+ "ChkChain(): lost in chains" );
+ if( nCount >= 200 || pPor == pStart )
+ {
+ // der Lebensretter
+ pPor = pStart->GetPortion();
+ pStart->SetPortion(0);
+ pPor->Truncate();
+ pStart->SetPortion( pPor );
+ return sal_False;
+ }
+ pPor = pPor->GetPortion();
+ }
+ return sal_True;
+}
+#endif
+
+#if OSL_DEBUG_LEVEL > 1
+const sal_Char *GetPortionName( const MSHORT nType );
+#endif
+
+SwLinePortion::~SwLinePortion()
+{
+ if( pBlink )
+ pBlink->Delete( this );
+}
+
+SwLinePortion *SwLinePortion::Compress()
+{
+ return GetLen() || Width() ? this : 0;
+}
+
+KSHORT SwLinePortion::GetViewWidth( const SwTxtSizeInfo & ) const
+{
+ return 0;
+}
+
+/*************************************************************************
+ * SwLinePortion::SwLinePortion( )
+ *************************************************************************/
+
+SwLinePortion::SwLinePortion( ) :
+ pPortion( NULL ),
+ nLineLength( 0 ),
+ nAscent( 0 )
+{
+}
+
+/*************************************************************************
+ * SwLinePortion::PrePaint()
+ *************************************************************************/
+
+void SwLinePortion::PrePaint( const SwTxtPaintInfo& rInf,
+ const SwLinePortion* pLast ) const
+{
+ OSL_ENSURE( rInf.OnWin(), "SwLinePortion::PrePaint: don't prepaint on a printer");
+ OSL_ENSURE( !Width(), "SwLinePortion::PrePaint: For Width()==0 only!");
+
+ const KSHORT nViewWidth = GetViewWidth( rInf );
+
+ if( ! nViewWidth )
+ return;
+
+ const KSHORT nHalfView = nViewWidth / 2;
+ sal_uInt16 nLastWidth = pLast->Width();
+
+ if ( pLast->InSpaceGrp() && rInf.GetSpaceAdd() )
+ nLastWidth = nLastWidth + (sal_uInt16)pLast->CalcSpacing( rInf.GetSpaceAdd(), rInf );
+
+ KSHORT nPos;
+ SwTxtPaintInfo aInf( rInf );
+
+ const sal_Bool bBidiPor = ( rInf.GetTxtFrm()->IsRightToLeft() ) !=
+ ( 0 != ( TEXT_LAYOUT_BIDI_RTL & rInf.GetOut()->GetLayoutMode() ) );
+
+ sal_uInt16 nDir = bBidiPor ?
+ 1800 :
+ rInf.GetFont()->GetOrientation( rInf.GetTxtFrm()->IsVertical() );
+
+ switch ( nDir )
+ {
+ case 0 :
+ nPos = KSHORT( rInf.X() );
+ if( nLastWidth > nHalfView )
+ nPos += nLastWidth - nHalfView;
+ aInf.X( nPos );
+ break;
+ case 900 :
+ nPos = KSHORT( rInf.Y() );
+ if( nLastWidth > nHalfView )
+ nPos -= nLastWidth + nHalfView;
+ aInf.Y( nPos );
+ break;
+ case 1800 :
+ nPos = KSHORT( rInf.X() );
+ if( nLastWidth > nHalfView )
+ nPos -= nLastWidth + nHalfView;
+ aInf.X( nPos );
+ break;
+ case 2700 :
+ nPos = KSHORT( rInf.Y() );
+ if( nLastWidth > nHalfView )
+ nPos += nLastWidth - nHalfView;
+ aInf.Y( nPos );
+ break;
+ }
+
+ SwLinePortion *pThis = (SwLinePortion*)this;
+ pThis->Width( nViewWidth );
+ Paint( aInf );
+ pThis->Width(0);
+}
+
+/*************************************************************************
+ * SwLinePortion::CalcTxtSize()
+ *************************************************************************/
+
+void SwLinePortion::CalcTxtSize( const SwTxtSizeInfo &rInf )
+{
+ if( GetLen() == rInf.GetLen() )
+ *((SwPosSize*)this) = GetTxtSize( rInf );
+ else
+ {
+ SwTxtSizeInfo aInf( rInf );
+ aInf.SetLen( GetLen() );
+ *((SwPosSize*)this) = GetTxtSize( aInf );
+ }
+}
+
+/*************************************************************************
+ * SwLinePortion::Truncate()
+ *
+ * Es werden alle nachfolgenden Portions geloescht.
+ *************************************************************************/
+
+void SwLinePortion::_Truncate()
+{
+ SwLinePortion *pPos = pPortion;
+ do
+ { OSL_ENSURE( pPos != this, "SwLinePortion::Truncate: loop" );
+ SwLinePortion *pLast = pPos;
+ pPos = pPos->GetPortion();
+ pLast->SetPortion( 0 );
+ delete pLast;
+
+ } while( pPos );
+
+ pPortion = 0;
+}
+
+/*************************************************************************
+ * virtual SwLinePortion::Insert()
+ *
+ * Es wird immer hinter uns eingefuegt.
+ *************************************************************************/
+
+SwLinePortion *SwLinePortion::Insert( SwLinePortion *pIns )
+{
+ pIns->FindLastPortion()->SetPortion( pPortion );
+ SetPortion( pIns );
+#if OSL_DEBUG_LEVEL > 1
+ ChkChain( this );
+#endif
+ return pIns;
+}
+
+/*************************************************************************
+ * SwLinePortion::FindLastPortion()
+ *************************************************************************/
+
+SwLinePortion *SwLinePortion::FindLastPortion()
+{
+ SwLinePortion *pPos = this;
+ // An das Ende wandern und pLinPortion an den letzten haengen ...
+ while( pPos->GetPortion() )
+ {
+ pPos = pPos->GetPortion();
+ }
+ return pPos;
+}
+
+/*************************************************************************
+ * virtual SwLinePortion::Append()
+ *************************************************************************/
+
+SwLinePortion *SwLinePortion::Append( SwLinePortion *pIns )
+{
+ SwLinePortion *pPos = FindLastPortion();
+ pPos->SetPortion( pIns );
+ pIns->SetPortion( 0 );
+#if OSL_DEBUG_LEVEL > 1
+ ChkChain( this );
+#endif
+ return pIns;
+}
+
+/*************************************************************************
+ * virtual SwLinePortion::Cut()
+ *************************************************************************/
+
+SwLinePortion *SwLinePortion::Cut( SwLinePortion *pVictim )
+{
+ SwLinePortion *pPrev = pVictim->FindPrevPortion( this );
+ OSL_ENSURE( pPrev, "SwLinePortion::Cut(): can't cut" );
+ pPrev->SetPortion( pVictim->GetPortion() );
+ pVictim->SetPortion(0);
+ return pVictim;
+}
+
+/*************************************************************************
+ * SwLinePortion::FindPrevPortion()
+ *************************************************************************/
+
+SwLinePortion *SwLinePortion::FindPrevPortion( const SwLinePortion *pRoot )
+{
+ OSL_ENSURE( pRoot != this, "SwLinePortion::FindPrevPortion(): invalid root" );
+ SwLinePortion *pPos = (SwLinePortion*)pRoot;
+ while( pPos->GetPortion() && pPos->GetPortion() != this )
+ {
+ pPos = pPos->GetPortion();
+ }
+ OSL_ENSURE( pPos->GetPortion(),
+ "SwLinePortion::FindPrevPortion: blowing in the wind");
+ return pPos;
+}
+
+/*************************************************************************
+ * virtual SwLinePortion::GetCrsrOfst()
+ *************************************************************************/
+
+xub_StrLen SwLinePortion::GetCrsrOfst( const KSHORT nOfst ) const
+{
+ if( nOfst > ( PrtWidth() / 2 ) )
+ return GetLen();
+ else
+ return 0;
+}
+
+/*************************************************************************
+ * virtual SwLinePortion::GetTxtSize()
+ *************************************************************************/
+
+SwPosSize SwLinePortion::GetTxtSize( const SwTxtSizeInfo & ) const
+{
+ OSL_ENSURE( !this, "SwLinePortion::GetTxtSize: don't ask me about sizes, "
+ "I'm only a stupid SwLinePortion" );
+ return SwPosSize();
+}
+
+#if OSL_DEBUG_LEVEL > 1
+
+/*************************************************************************
+ * virtual SwLinePortion::Check()
+ *************************************************************************/
+
+sal_Bool SwLinePortion::Check( SvStream &, SwTxtSizeInfo & ) //$ ostream
+{
+ return sal_True;
+}
+#endif
+
+/*************************************************************************
+ * virtual SwLinePortion::Format()
+ *************************************************************************/
+
+sal_Bool SwLinePortion::Format( SwTxtFormatInfo &rInf )
+{
+ if( rInf.X() > rInf.Width() )
+ {
+ Truncate();
+ rInf.SetUnderFlow( this );
+ return sal_True;
+ }
+
+ const SwLinePortion *pLast = rInf.GetLast();
+ Height( pLast->Height() );
+ SetAscent( pLast->GetAscent() );
+ const KSHORT nNewWidth = static_cast<sal_uInt16>(rInf.X() + PrtWidth());
+ // Nur Portions mit echter Breite koennen ein sal_True zurueckliefern
+ // Notizen beispielsweise setzen niemals bFull==sal_True
+ if( rInf.Width() <= nNewWidth && PrtWidth() && ! IsKernPortion() )
+ {
+ Truncate();
+ if( nNewWidth > rInf.Width() )
+ PrtWidth( nNewWidth - rInf.Width() );
+ rInf.GetLast()->FormatEOL( rInf );
+ return sal_True;
+ }
+ return sal_False;
+}
+
+/*************************************************************************
+ * virtual SwLinePortion::FormatEOL()
+ *************************************************************************/
+
+// Format end of line
+
+void SwLinePortion::FormatEOL( SwTxtFormatInfo & )
+{ }
+
+/*************************************************************************
+ * SwLinePortion::Move()
+ *************************************************************************/
+
+void SwLinePortion::Move( SwTxtPaintInfo &rInf )
+{
+ sal_Bool bB2T = rInf.GetDirection() == DIR_BOTTOM2TOP;
+ const sal_Bool bFrmDir = rInf.GetTxtFrm()->IsRightToLeft();
+ sal_Bool bCounterDir = ( ! bFrmDir && DIR_RIGHT2LEFT == rInf.GetDirection() ) ||
+ ( bFrmDir && DIR_LEFT2RIGHT == rInf.GetDirection() );
+
+ if ( InSpaceGrp() && rInf.GetSpaceAdd() )
+ {
+ SwTwips nTmp = PrtWidth() + CalcSpacing( rInf.GetSpaceAdd(), rInf );
+ if( rInf.IsRotated() )
+ rInf.Y( rInf.Y() + ( bB2T ? -nTmp : nTmp ) );
+ else if ( bCounterDir )
+ rInf.X( rInf.X() - nTmp );
+ else
+ rInf.X( rInf.X() + nTmp );
+ }
+ else
+ {
+ if( InFixMargGrp() && !IsMarginPortion() )
+ {
+ rInf.IncSpaceIdx();
+ rInf.IncKanaIdx();
+ }
+ if( rInf.IsRotated() )
+ rInf.Y( rInf.Y() + ( bB2T ? -PrtWidth() : PrtWidth() ) );
+ else if ( bCounterDir )
+ rInf.X( rInf.X() - PrtWidth() );
+ else
+ rInf.X( rInf.X() + PrtWidth() );
+ }
+ if( IsMultiPortion() && ((SwMultiPortion*)this)->HasTabulator() )
+ rInf.IncSpaceIdx();
+
+ rInf.SetIdx( rInf.GetIdx() + GetLen() );
+}
+
+/*************************************************************************
+ * virtual SwLinePortion::CalcSpacing()
+ *************************************************************************/
+
+long SwLinePortion::CalcSpacing( long , const SwTxtSizeInfo & ) const
+{
+ return 0;
+}
+
+/*************************************************************************
+ * virtual SwLinePortion::GetExpTxt()
+ *************************************************************************/
+
+sal_Bool SwLinePortion::GetExpTxt( const SwTxtSizeInfo &, XubString & ) const
+{
+ return sal_False;
+}
+
+/*************************************************************************
+ * virtual SwLinePortion::HandlePortion()
+ *************************************************************************/
+
+void SwLinePortion::HandlePortion( SwPortionHandler& rPH ) const
+{
+ String aString;
+ rPH.Special( GetLen(), aString, GetWhichPor() );
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/text/porlin.hxx b/sw/source/core/text/porlin.hxx
new file mode 100644
index 000000000000..a4f887113173
--- /dev/null
+++ b/sw/source/core/text/porlin.hxx
@@ -0,0 +1,254 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+#ifndef _PORLIN_HXX
+#define _PORLIN_HXX
+
+#include "possiz.hxx" // SwPosSize
+
+#if OSL_DEBUG_LEVEL > 1
+#include <libxml/xmlwriter.h>
+#endif
+
+class XubString;
+class SwTxtSizeInfo;
+class SwTxtPaintInfo;
+class SwTxtFormatInfo;
+class SwPortionHandler;
+
+// Die Ausgabeoperatoren der Portions sind virtuelle Methoden der Portion.
+// Das CLASSIO-Makro implementiert die 'freischwebende' Funktion.
+// Auf diese Weise erhaelt man beide Vorteile: virtuelle Ausgabeoperatoren
+// und allgemeine Verwendbarkeit.
+#if OSL_DEBUG_LEVEL > 1
+#define OUTPUT_OPERATOR virtual SvStream &operator<<( SvStream & aOs ) const;
+#else
+#define OUTPUT_OPERATOR
+#endif
+
+// Portiongruppen
+#define PORGRP_TXT 0x8000
+#define PORGRP_EXP 0x4000
+#define PORGRP_FLD 0x2000
+#define PORGRP_HYPH 0x1000
+#define PORGRP_NUMBER 0x0800
+#define PORGRP_GLUE 0x0400
+#define PORGRP_FIX 0x0200
+#define PORGRP_TAB 0x0100
+#define PORGRP_NOTRECY 0x0080
+// kleine Spezialgruppen
+#define PORGRP_FIXMARG 0x0040
+//#define PORGRP_? 0x0020
+#define PORGRP_TABNOTLFT 0x0010
+#define PORGRP_TOXREF 0x0008
+
+/*************************************************************************
+ * class SwLinePortion
+ *************************************************************************/
+
+class SwLinePortion: public SwPosSize
+{
+protected:
+ // Hier gibt es Bereiche mit unterschiedlichen Attributen.
+ SwLinePortion *pPortion;
+ // Anzahl der Zeichen und Spaces auf der Zeile
+ xub_StrLen nLineLength;
+ KSHORT nAscent; // Maximaler Ascender
+
+ SwLinePortion();
+private:
+ MSHORT nWhichPor; // Who's who?
+
+ void _Truncate();
+
+public:
+ inline SwLinePortion(const SwLinePortion &rPortion);
+ virtual ~SwLinePortion();
+
+ // Zugriffsmethoden
+ inline SwLinePortion *GetPortion() const { return( pPortion ); }
+ inline SwLinePortion &operator=(const SwLinePortion &rPortion);
+ inline sal_Bool operator==( const SwLinePortion &rPortion ) const;
+ inline xub_StrLen GetLen() const { return nLineLength; }
+ inline void SetLen( const xub_StrLen nLen ) { nLineLength = nLen; }
+ inline void SetPortion( SwLinePortion *pNew ){ pPortion = pNew; }
+ inline KSHORT &GetAscent() { return nAscent; }
+ inline KSHORT GetAscent() const { return nAscent; }
+ inline void SetAscent( const KSHORT nNewAsc ) { nAscent = nNewAsc; }
+ inline void PrtWidth( KSHORT nNewWidth ) { Width( nNewWidth ); }
+ inline KSHORT PrtWidth() const { return Width(); }
+ inline void AddPrtWidth( const KSHORT nNew ) { Width( Width() + nNew ); }
+ inline void SubPrtWidth( const KSHORT nNew ) { Width( Width() - nNew ); }
+
+ inline const SwPosSize &PrtSize() const { return *this; }
+
+ // Einfuegeoperationen:
+ virtual SwLinePortion *Insert( SwLinePortion *pPortion );
+ virtual SwLinePortion *Append( SwLinePortion *pPortion );
+ SwLinePortion *Cut( SwLinePortion *pVictim );
+ inline void Truncate();
+
+ // liefert 0 zurueck, wenn keine Nutzdaten enthalten sind.
+ virtual SwLinePortion *Compress();
+
+ inline void SetWhichPor( const MSHORT nNew ) { nWhichPor = nNew; }
+ inline MSHORT GetWhichPor( ) const { return nWhichPor; }
+
+// Gruppenabfragen:
+ inline sal_Bool InTxtGrp( ) const { return nWhichPor & PORGRP_TXT ? sal_True : sal_False; }
+ inline sal_Bool InGlueGrp( ) const { return nWhichPor & PORGRP_GLUE ? sal_True : sal_False;}
+ inline sal_Bool InTabGrp( ) const { return nWhichPor & PORGRP_TAB ? sal_True : sal_False; }
+ inline sal_Bool InHyphGrp( ) const { return nWhichPor & PORGRP_HYPH ? sal_True : sal_False;}
+ inline sal_Bool InNumberGrp( )const { return nWhichPor & PORGRP_NUMBER ? sal_True : sal_False;}
+ inline sal_Bool InFixGrp( ) const { return nWhichPor & PORGRP_FIX ? sal_True : sal_False; }
+ inline sal_Bool InFldGrp( ) const { return nWhichPor & PORGRP_FLD ? sal_True : sal_False; }
+ inline sal_Bool InToxRefGrp( ) const { return nWhichPor & PORGRP_TOXREF ? sal_True : sal_False; }
+ inline sal_Bool InToxRefOrFldGrp( ) const { return nWhichPor &
+ ( PORGRP_FLD | PORGRP_TOXREF ) ? sal_True : sal_False; }
+ inline sal_Bool InExpGrp( ) const { return nWhichPor & PORGRP_EXP ? sal_True : sal_False; }
+ inline sal_Bool InTabnLftGrp( ) const
+ { return nWhichPor & PORGRP_TABNOTLFT ? sal_True : sal_False; }
+ inline sal_Bool InFixMargGrp( )const
+ { return nWhichPor & PORGRP_FIXMARG ? sal_True : sal_False; }
+ inline sal_Bool InSpaceGrp( )const
+ { return InTxtGrp() || IsMultiPortion(); }
+// Individuelle Abfragen:
+ inline sal_Bool IsGrfNumPortion( )const{ return nWhichPor == POR_GRFNUM; }
+ inline sal_Bool IsFlyCntPortion( )const{ return nWhichPor == POR_FLYCNT; }
+ inline sal_Bool IsBlankPortion( ) const{ return nWhichPor == POR_BLANK; }
+ inline sal_Bool IsBreakPortion( ) const{ return nWhichPor == POR_BRK; }
+ inline sal_Bool IsErgoSumPortion()const{ return nWhichPor == POR_ERGOSUM;}
+ inline sal_Bool IsQuoVadisPortion()const{ return nWhichPor==POR_QUOVADIS;}
+ inline sal_Bool IsTabCntPortion( )const{ return nWhichPor==POR_TABCENTER;}
+ inline sal_Bool IsTabDecimalPortion() const { return nWhichPor == POR_TABDECIMAL;}
+ inline sal_Bool IsTabLeftPortion()const{ return nWhichPor == POR_TABLEFT;}
+ inline sal_Bool IsFtnNumPortion( )const{ return nWhichPor == POR_FTNNUM; }
+ inline sal_Bool IsFtnPortion( ) const{ return nWhichPor == POR_FTN; }
+ inline sal_Bool IsTmpEndPortion( )const{ return nWhichPor == POR_TMPEND; }
+ inline sal_Bool IsDropPortion( ) const{ return nWhichPor == POR_DROP; }
+ inline sal_Bool IsLayPortion( ) const{ return nWhichPor == POR_LAY; }
+ inline sal_Bool IsParaPortion( ) const{ return nWhichPor == POR_PARA; }
+ inline sal_Bool IsMarginPortion( )const{ return nWhichPor == POR_MARGIN; }
+ inline sal_Bool IsFlyPortion( ) const{ return nWhichPor == POR_FLY; }
+ inline sal_Bool IsHolePortion( ) const{ return nWhichPor == POR_HOLE; }
+ inline sal_Bool IsSoftHyphPortion()const{ return nWhichPor==POR_SOFTHYPH;}
+ inline sal_Bool IsPostItsPortion()const{ return nWhichPor == POR_POSTITS;}
+ inline sal_Bool IsCombinedPortion()const{ return nWhichPor==POR_COMBINED;}
+ inline sal_Bool IsTextPortion( ) const{ return nWhichPor == POR_TXT; }
+ inline sal_Bool IsURLPortion( ) const{ return nWhichPor == POR_URL; }
+ inline sal_Bool IsHangingPortion( ) const{ return nWhichPor == POR_HNG; }
+ inline sal_Bool IsKernPortion( ) const{ return nWhichPor == POR_KERN; }
+ inline sal_Bool IsArrowPortion( ) const{ return nWhichPor == POR_ARROW; }
+ inline sal_Bool IsMultiPortion( ) const{ return nWhichPor == POR_MULTI; }
+ inline sal_Bool IsNumberPortion( ) const{ return nWhichPor == POR_NUMBER; } // #i23726#
+ inline sal_Bool IsControlCharPortion() const { return nWhichPor == POR_CONTROLCHAR; }
+
+ // Positionierung
+ SwLinePortion *FindPrevPortion( const SwLinePortion *pRoot );
+ SwLinePortion *FindLastPortion();
+
+ virtual xub_StrLen GetCrsrOfst( const KSHORT nOfst ) const;
+ virtual SwPosSize GetTxtSize( const SwTxtSizeInfo &rInfo ) const;
+ void CalcTxtSize( const SwTxtSizeInfo &rInfo );
+
+ // Ausgabe
+ virtual void Paint( const SwTxtPaintInfo &rInf ) const = 0;
+ void PrePaint( const SwTxtPaintInfo &rInf, const SwLinePortion *pLast ) const;
+
+#if OSL_DEBUG_LEVEL > 1
+ virtual sal_Bool Check( SvStream &rOs, SwTxtSizeInfo &rInfo ); //$ ostream
+#endif
+
+ virtual sal_Bool Format( SwTxtFormatInfo &rInf );
+ // wird fuer die letzte Portion der Zeile extra gerufen
+ virtual void FormatEOL( SwTxtFormatInfo &rInf );
+ void Move( SwTxtPaintInfo &rInf );
+
+ // Fuer SwTxtSlot
+ virtual sal_Bool GetExpTxt( const SwTxtSizeInfo &rInf, XubString &rTxt ) const;
+
+ // fuer SwFldPortion, SwSoftHyphPortion
+ virtual KSHORT GetViewWidth( const SwTxtSizeInfo &rInf ) const;
+
+ // for text- and multi-portions
+ virtual long CalcSpacing( long nSpaceAdd, const SwTxtSizeInfo &rInf ) const;
+
+ // Accessibility: pass information about this portion to the PortionHandler
+ virtual void HandlePortion( SwPortionHandler& rPH ) const;
+
+#if OSL_DEBUG_LEVEL > 1
+ void dumpPortionAsXml(sal_uInt16 ofs, String& aText, xmlTextWriter* writer);
+#endif
+ OUTPUT_OPERATOR
+};
+
+
+/*************************************************************************
+ * inline - Implementations
+ *************************************************************************/
+
+inline SwLinePortion &SwLinePortion::operator=(const SwLinePortion &rPortion)
+{
+ *(SwPosSize*)this = rPortion;
+ nLineLength = rPortion.nLineLength;
+ nAscent = rPortion.nAscent;
+ nWhichPor = rPortion.nWhichPor;
+ return *this;
+}
+
+inline sal_Bool SwLinePortion::operator==(const SwLinePortion &rPortion ) const
+{
+ return( Height() == rPortion.Height() &&
+ Width() == rPortion.Width() &&
+ nLineLength == rPortion.GetLen() &&
+ nAscent == rPortion.GetAscent() );
+}
+
+inline SwLinePortion::SwLinePortion(const SwLinePortion &rPortion) :
+ SwPosSize( rPortion ),
+ pPortion( 0 ),
+ nLineLength( rPortion.nLineLength ),
+ nAscent( rPortion.nAscent ),
+ nWhichPor( rPortion.nWhichPor )
+{
+}
+
+inline void SwLinePortion::Truncate()
+{
+ if ( pPortion )
+ _Truncate();
+}
+
+
+//$ ostream
+#define CLASSIO( class )
+
+CLASSIO( SwLinePortion )
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/text/pormulti.cxx b/sw/source/core/text/pormulti.cxx
new file mode 100644
index 000000000000..25ff3d0b047f
--- /dev/null
+++ b/sw/source/core/text/pormulti.cxx
@@ -0,0 +1,2411 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+
+#include <hintids.hxx>
+
+#include <com/sun/star/i18n/ScriptType.hdl>
+#include <editeng/twolinesitem.hxx>
+#include <editeng/charrotateitem.hxx>
+#include <vcl/outdev.hxx>
+#include <fmtfld.hxx>
+#include <fldbas.hxx> // SwField
+#include <txatbase.hxx>
+#include <fmtruby.hxx> // SwFmtRuby
+#include <txtatr.hxx> // SwTxtRuby
+#include <charfmt.hxx>
+#include <txtinet.hxx>
+#include <fchrfmt.hxx>
+#include <layfrm.hxx> // GetUpper()
+#include <SwPortionHandler.hxx>
+#include <pormulti.hxx> // SwMultiPortion
+#include <inftxt.hxx> // SwTxtSizeInfo
+#include <itrpaint.hxx> // SwTxtPainter
+#include <viewopt.hxx> // SwViewOptions
+#include <itrform2.hxx> // SwTxtFormatter
+#include <porfld.hxx> // SwFldPortion
+#include <porglue.hxx>
+#include <breakit.hxx>
+#include <pagefrm.hxx>
+#include <rowfrm.hxx>
+#include <pagedesc.hxx> // SwPageDesc
+#include <tgrditem.hxx>
+#include <swtable.hxx>
+#include <fmtfsize.hxx>
+
+using namespace ::com::sun::star;
+extern sal_Bool IsUnderlineBreak( const SwLinePortion& rPor, const SwFont& rFnt );
+
+/*--------------------------------------------------
+ * class SwMultiPortion
+ *
+ * A SwMultiPortion is not a simple portion,
+ * it's a container, which contains almost a SwLineLayoutPortion.
+ * This SwLineLayout could be followed by other textportions via pPortion
+ * and by another SwLineLayout via pNext to realize a doubleline portion.
+ * --------------------------------------------------*/
+
+SwMultiPortion::~SwMultiPortion()
+{
+ delete pFldRest;
+}
+
+void SwMultiPortion::Paint( const SwTxtPaintInfo & ) const
+{
+ OSL_FAIL( "Don't try SwMultiPortion::Paint, try SwTxtPainter::PaintMultiPortion" );
+}
+
+/*--------------------------------------------------
+ * Summarize the internal lines to calculate the (external) size.
+ * The internal line has to calculate first.
+ * --------------------------------------------------*/
+
+void SwMultiPortion::CalcSize( SwTxtFormatter& rLine, SwTxtFormatInfo &rInf )
+{
+ Width( 0 );
+ Height( 0 );
+ SetAscent( 0 );
+ SetFlyInCntnt( sal_False );
+ SwLineLayout *pLay = &GetRoot();
+ do
+ {
+ pLay->CalcLine( rLine, rInf );
+ if( rLine.IsFlyInCntBase() )
+ SetFlyInCntnt( sal_True );
+ if( IsRuby() && ( OnTop() == ( pLay == &GetRoot() ) ) )
+ {
+ // An empty phonetic line don't need an ascent or a height.
+ if( !pLay->Width() )
+ {
+ pLay->SetAscent( 0 );
+ pLay->Height( 0 );
+ }
+ if( OnTop() )
+ SetAscent( GetAscent() + pLay->Height() );
+ }
+ else
+ SetAscent( GetAscent() + pLay->GetAscent() );
+ Height( Height() + pLay->Height() );
+ if( Width() < pLay->Width() )
+ Width( pLay->Width() );
+ pLay = pLay->GetNext();
+ } while ( pLay );
+ if( HasBrackets() )
+ {
+ KSHORT nTmp = ((SwDoubleLinePortion*)this)->GetBrackets()->nHeight;
+ if( nTmp > Height() )
+ {
+ KSHORT nAdd = ( nTmp - Height() ) / 2;
+ GetRoot().SetAscent( GetRoot().GetAscent() + nAdd );
+ GetRoot().Height( GetRoot().Height() + nAdd );
+ Height( nTmp );
+ }
+ nTmp = ((SwDoubleLinePortion*)this)->GetBrackets()->nAscent;
+ if( nTmp > GetAscent() )
+ SetAscent( nTmp );
+ }
+}
+
+long SwMultiPortion::CalcSpacing( long , const SwTxtSizeInfo & ) const
+{
+ return 0;
+}
+
+sal_Bool SwMultiPortion::ChgSpaceAdd( SwLineLayout*, long ) const
+{
+ return sal_False;
+}
+
+/*************************************************************************
+ * virtual SwMultiPortion::HandlePortion()
+ *************************************************************************/
+
+void SwMultiPortion::HandlePortion( SwPortionHandler& rPH ) const
+{
+ rPH.Text( GetLen(), GetWhichPor() );
+}
+
+/*--------------------------------------------------
+ * SwMultiPortion::ActualizeTabulator()
+ * sets the tabulator-flag, if there's any tabulator-portion inside.
+ * --------------------------------------------------*/
+
+void SwMultiPortion::ActualizeTabulator()
+{
+ SwLinePortion* pPor = GetRoot().GetFirstPortion();
+ // First line
+ for( bTab1 = bTab2 = sal_False; pPor; pPor = pPor->GetPortion() )
+ if( pPor->InTabGrp() )
+ SetTab1( sal_True );
+ if( GetRoot().GetNext() )
+ {
+ // Second line
+ pPor = GetRoot().GetNext()->GetFirstPortion();
+ do
+ {
+ if( pPor->InTabGrp() )
+ SetTab2( sal_True );
+ pPor = pPor->GetPortion();
+ } while ( pPor );
+ }
+}
+
+/*--------------------------------------------------
+ * SwRotatedPortion::SwRotatedPortion(..)
+ * --------------------------------------------------*/
+
+SwRotatedPortion::SwRotatedPortion( const SwMultiCreator& rCreate,
+ xub_StrLen nEnd, sal_Bool bRTL ) : SwMultiPortion( nEnd )
+{
+ const SvxCharRotateItem* pRot = (SvxCharRotateItem*)rCreate.pItem;
+ if( !pRot )
+ {
+ const SwTxtAttr& rAttr = *rCreate.pAttr;
+ const SfxPoolItem *const pItem =
+ CharFmt::GetItem(rAttr, RES_CHRATR_ROTATE);
+ if ( pItem )
+ {
+ pRot = static_cast<const SvxCharRotateItem*>(pItem);
+ }
+ }
+ if( pRot )
+ {
+ sal_uInt8 nDir;
+ if ( bRTL )
+ nDir = pRot->IsBottomToTop() ? 3 : 1;
+ else
+ nDir = pRot->IsBottomToTop() ? 1 : 3;
+
+ SetDirection( nDir );
+ }
+}
+
+/*---------------------------------------------------
+ * SwBidiPortion::SwBidiPortion(..)
+ * --------------------------------------------------*/
+
+SwBidiPortion::SwBidiPortion( xub_StrLen nEnd, sal_uInt8 nLv )
+ : SwMultiPortion( nEnd ), nLevel( nLv )
+{
+ SetBidi();
+
+ if ( nLevel % 2 )
+ SetDirection( DIR_RIGHT2LEFT );
+ else
+ SetDirection( DIR_LEFT2RIGHT );
+}
+
+
+long SwBidiPortion::CalcSpacing( long nSpaceAdd, const SwTxtSizeInfo& rInf ) const
+{
+ return HasTabulator() ? 0 : GetSpaceCnt(rInf) * nSpaceAdd / SPACING_PRECISION_FACTOR;
+}
+
+sal_Bool SwBidiPortion::ChgSpaceAdd( SwLineLayout* pCurr, long nSpaceAdd ) const
+{
+ sal_Bool bRet = sal_False;
+ if( !HasTabulator() && nSpaceAdd > 0 && !pCurr->IsSpaceAdd() )
+ {
+ pCurr->CreateSpaceAdd();
+ pCurr->SetLLSpaceAdd( nSpaceAdd, 0 );
+ bRet = sal_True;
+ }
+
+ return bRet;
+}
+
+xub_StrLen SwBidiPortion::GetSpaceCnt( const SwTxtSizeInfo &rInf ) const
+{
+ // Calculate number of blanks for justified alignment
+ SwLinePortion* pPor = GetRoot().GetFirstPortion();
+ xub_StrLen nTmpStart = rInf.GetIdx();
+ xub_StrLen nNull = 0;
+ xub_StrLen nBlanks;
+
+ for( nBlanks = 0; pPor; pPor = pPor->GetPortion() )
+ {
+ if( pPor->InTxtGrp() )
+ nBlanks = nBlanks + ((SwTxtPortion*)pPor)->GetSpaceCnt( rInf, nNull );
+ else if ( pPor->IsMultiPortion() &&
+ ((SwMultiPortion*)pPor)->IsBidi() )
+ nBlanks = nBlanks + ((SwBidiPortion*)pPor)->GetSpaceCnt( rInf );
+
+ ((SwTxtSizeInfo &)rInf).SetIdx( rInf.GetIdx() + pPor->GetLen() );
+ }
+ ((SwTxtSizeInfo &)rInf).SetIdx( nTmpStart );
+ return nBlanks;
+}
+
+/*--------------------------------------------------
+ * SwDoubleLinePortion::SwDoubleLinePortion(..)
+ * This constructor is for the continuation of a doubleline portion
+ * in the next line.
+ * It takes the same brackets and if the original has no content except
+ * brackets, these will be deleted.
+ * --------------------------------------------------*/
+
+SwDoubleLinePortion::SwDoubleLinePortion( SwDoubleLinePortion& rDouble,
+ xub_StrLen nEnd ) :
+ SwMultiPortion( nEnd ),
+ pBracket( 0 )
+{
+ SetDirection( rDouble.GetDirection() );
+ SetDouble();
+ if( rDouble.GetBrackets() )
+ {
+ SetBrackets( rDouble );
+ // An empty multiportion needs no brackets.
+ // Notice: GetLen() might be zero, if the multiportion contains
+ // the second part of a field and the width might be zero, if
+ // it contains a note only. In this cases the brackets are okay.
+ // But if the length and the width are both zero, the portion
+ // is really empty.
+ if( rDouble.Width() == rDouble.BracketWidth() )
+ rDouble.ClearBrackets();
+ }
+}
+
+/*--------------------------------------------------
+ * SwDoubleLinePortion::SwDoubleLinePortion(..)
+ * This constructor uses the textattribut to get the right brackets.
+ * The textattribut could be a 2-line-attribute or a character- or
+ * internetstyle, which contains the 2-line-attribute.
+ * --------------------------------------------------*/
+
+SwDoubleLinePortion::SwDoubleLinePortion( const SwMultiCreator& rCreate,
+ xub_StrLen nEnd ) : SwMultiPortion( nEnd ), pBracket( new SwBracket() )
+{
+ SetDouble();
+ const SvxTwoLinesItem* pTwo = (SvxTwoLinesItem*)rCreate.pItem;
+ if( pTwo )
+ pBracket->nStart = 0;
+ else
+ {
+ const SwTxtAttr& rAttr = *rCreate.pAttr;
+ pBracket->nStart = *rAttr.GetStart();
+
+ const SfxPoolItem * const pItem =
+ CharFmt::GetItem( rAttr, RES_CHRATR_TWO_LINES );
+ if ( pItem )
+ {
+ pTwo = static_cast<const SvxTwoLinesItem*>(pItem);
+ }
+ }
+ if( pTwo )
+ {
+ pBracket->cPre = pTwo->GetStartBracket();
+ pBracket->cPost = pTwo->GetEndBracket();
+ }
+ else
+ {
+ pBracket->cPre = 0;
+ pBracket->cPost = 0;
+ }
+ sal_uInt8 nTmp = SW_SCRIPTS;
+ if( pBracket->cPre > 255 )
+ {
+ String aTxt( pBracket->cPre );
+ nTmp = SwScriptInfo::WhichFont( 0, &aTxt, 0 );
+ }
+ pBracket->nPreScript = nTmp;
+ nTmp = SW_SCRIPTS;
+ if( pBracket->cPost > 255 )
+ {
+ String aTxt( pBracket->cPost );
+ nTmp = SwScriptInfo::WhichFont( 0, &aTxt, 0 );
+ }
+ pBracket->nPostScript = nTmp;
+
+ if( !pBracket->cPre && !pBracket->cPost )
+ {
+ delete pBracket;
+ pBracket = 0;
+ }
+
+ // double line portions have the same direction as the frame directions
+ if ( rCreate.nLevel % 2 )
+ SetDirection( DIR_RIGHT2LEFT );
+ else
+ SetDirection( DIR_LEFT2RIGHT );
+}
+
+
+/*--------------------------------------------------
+ * SwMultiPortion::PaintBracket paints the wished bracket,
+ * if the multiportion has surrounding brackets.
+ * The X-position of the SwTxtPaintInfo will be modified:
+ * the open bracket sets position behind itself,
+ * the close bracket in front of itself.
+ * --------------------------------------------------*/
+
+void SwDoubleLinePortion::PaintBracket( SwTxtPaintInfo &rInf,
+ long nSpaceAdd,
+ sal_Bool bOpen ) const
+{
+ sal_Unicode cCh = bOpen ? pBracket->cPre : pBracket->cPost;
+ if( !cCh )
+ return;
+ KSHORT nChWidth = bOpen ? PreWidth() : PostWidth();
+ if( !nChWidth )
+ return;
+ if( !bOpen )
+ rInf.X( rInf.X() + Width() - PostWidth() +
+ ( nSpaceAdd > 0 ? CalcSpacing( nSpaceAdd, rInf ) : 0 ) );
+
+ SwBlankPortion aBlank( cCh, sal_True );
+ aBlank.SetAscent( pBracket->nAscent );
+ aBlank.Width( nChWidth );
+ aBlank.Height( pBracket->nHeight );
+ {
+ SwFont* pTmpFnt = new SwFont( *rInf.GetFont() );
+ sal_uInt8 nAct = bOpen ? pBracket->nPreScript : pBracket->nPostScript;
+ if( SW_SCRIPTS > nAct )
+ pTmpFnt->SetActual( nAct );
+ pTmpFnt->SetProportion( 100 );
+ SwFontSave aSave( rInf, pTmpFnt );
+ aBlank.Paint( rInf );
+ delete pTmpFnt;
+ }
+ if( bOpen )
+ rInf.X( rInf.X() + PreWidth() );
+}
+
+/*--------------------------------------------------
+ * SwDoubleLinePortion::SetBrackets creates the bracket-structur
+ * and fills it, if not both characters are 0x00.
+ * --------------------------------------------------*/
+
+void SwDoubleLinePortion::SetBrackets( const SwDoubleLinePortion& rDouble )
+{
+ if( rDouble.pBracket )
+ {
+ pBracket = new SwBracket;
+ pBracket->cPre = rDouble.pBracket->cPre;
+ pBracket->cPost = rDouble.pBracket->cPost;
+ pBracket->nPreScript = rDouble.pBracket->nPreScript;
+ pBracket->nPostScript = rDouble.pBracket->nPostScript;
+ pBracket->nStart = rDouble.pBracket->nStart;
+ }
+}
+
+/*--------------------------------------------------
+ * SwDoubleLinePortion::FormatBrackets
+ * calculates the size of the brackets => pBracket,
+ * reduces the nMaxWidth-parameter ( minus bracket-width )
+ * and moves the rInf-x-position behind the opening bracket.
+ * --------------------------------------------------*/
+
+void SwDoubleLinePortion::FormatBrackets( SwTxtFormatInfo &rInf, SwTwips& nMaxWidth )
+{
+ nMaxWidth -= rInf.X();
+ SwFont* pTmpFnt = new SwFont( *rInf.GetFont() );
+ pTmpFnt->SetProportion( 100 );
+ pBracket->nAscent = 0;
+ pBracket->nHeight = 0;
+ if( pBracket->cPre )
+ {
+ String aStr( pBracket->cPre );
+ sal_uInt8 nActualScr = pTmpFnt->GetActual();
+ if( SW_SCRIPTS > pBracket->nPreScript )
+ pTmpFnt->SetActual( pBracket->nPreScript );
+ SwFontSave aSave( rInf, pTmpFnt );
+ SwPosSize aSize = rInf.GetTxtSize( aStr );
+ pBracket->nAscent = rInf.GetAscent();
+ pBracket->nHeight = aSize.Height();
+ pTmpFnt->SetActual( nActualScr );
+ if( nMaxWidth > aSize.Width() )
+ {
+ pBracket->nPreWidth = aSize.Width();
+ nMaxWidth -= aSize.Width();
+ rInf.X( rInf.X() + aSize.Width() );
+ }
+ else
+ {
+ pBracket->nPreWidth = 0;
+ nMaxWidth = 0;
+ }
+ }
+ else
+ pBracket->nPreWidth = 0;
+ if( pBracket->cPost )
+ {
+ String aStr( pBracket->cPost );
+ if( SW_SCRIPTS > pBracket->nPostScript )
+ pTmpFnt->SetActual( pBracket->nPostScript );
+ SwFontSave aSave( rInf, pTmpFnt );
+ SwPosSize aSize = rInf.GetTxtSize( aStr );
+ KSHORT nTmpAsc = rInf.GetAscent();
+ if( nTmpAsc > pBracket->nAscent )
+ {
+ pBracket->nHeight += nTmpAsc - pBracket->nAscent;
+ pBracket->nAscent = nTmpAsc;
+ }
+ if( aSize.Height() > pBracket->nHeight )
+ pBracket->nHeight = aSize.Height();
+ if( nMaxWidth > aSize.Width() )
+ {
+ pBracket->nPostWidth = aSize.Width();
+ nMaxWidth -= aSize.Width();
+ }
+ else
+ {
+ pBracket->nPostWidth = 0;
+ nMaxWidth = 0;
+ }
+ }
+ else
+ pBracket->nPostWidth = 0;
+ nMaxWidth += rInf.X();
+}
+
+/*--------------------------------------------------
+ * SwDoubleLinePortion::CalcBlanks
+ * calculates the number of blanks in each line and
+ * the difference of the width of the two lines.
+ * These results are used from the text adjustment.
+ * --------------------------------------------------*/
+
+void SwDoubleLinePortion::CalcBlanks( SwTxtFormatInfo &rInf )
+{
+ SwLinePortion* pPor = GetRoot().GetFirstPortion();
+ xub_StrLen nNull = 0;
+ xub_StrLen nStart = rInf.GetIdx();
+ SetTab1( sal_False );
+ SetTab2( sal_False );
+ for( nBlank1 = 0; pPor; pPor = pPor->GetPortion() )
+ {
+ if( pPor->InTxtGrp() )
+ nBlank1 = nBlank1 + ((SwTxtPortion*)pPor)->GetSpaceCnt( rInf, nNull );
+ rInf.SetIdx( rInf.GetIdx() + pPor->GetLen() );
+ if( pPor->InTabGrp() )
+ SetTab1( sal_True );
+ }
+ nLineDiff = GetRoot().Width();
+ if( GetRoot().GetNext() )
+ {
+ pPor = GetRoot().GetNext()->GetFirstPortion();
+ nLineDiff -= GetRoot().GetNext()->Width();
+ }
+ for( nBlank2 = 0; pPor; pPor = pPor->GetPortion() )
+ {
+ if( pPor->InTxtGrp() )
+ nBlank2 = nBlank2 + ((SwTxtPortion*)pPor)->GetSpaceCnt( rInf, nNull );
+ rInf.SetIdx( rInf.GetIdx() + pPor->GetLen() );
+ if( pPor->InTabGrp() )
+ SetTab2( sal_True );
+ }
+ rInf.SetIdx( nStart );
+}
+
+long SwDoubleLinePortion::CalcSpacing( long nSpaceAdd, const SwTxtSizeInfo & ) const
+{
+ return HasTabulator() ? 0 : GetSpaceCnt() * nSpaceAdd / SPACING_PRECISION_FACTOR;
+}
+
+/*--------------------------------------------------
+ * SwDoubleLinePortion::ChangeSpaceAdd(..)
+ * merges the spaces for text adjustment from the inner and outer part.
+ * Inside the doubleline portion the wider line has no spaceadd-array, the
+ * smaller line has such an array to reach width of the wider line.
+ * If the surrounding line has text adjustment and the doubleline portion
+ * contains no tabulator, it is necessary to create/manipulate the inner
+ * space arrays.
+ * --------------------------------------------------*/
+
+sal_Bool SwDoubleLinePortion::ChgSpaceAdd( SwLineLayout* pCurr,
+ long nSpaceAdd ) const
+{
+ sal_Bool bRet = sal_False;
+ if( !HasTabulator() && nSpaceAdd > 0 )
+ {
+ if( !pCurr->IsSpaceAdd() )
+ {
+ // The wider line gets the spaceadd from the surrounding line direct
+ pCurr->CreateSpaceAdd();
+ pCurr->SetLLSpaceAdd( nSpaceAdd, 0 );
+ bRet = sal_True;
+ }
+ else
+ {
+ xub_StrLen nMyBlank = GetSmallerSpaceCnt();
+ xub_StrLen nOther = GetSpaceCnt();
+ SwTwips nMultiSpace = pCurr->GetLLSpaceAdd( 0 ) * nMyBlank + nOther * nSpaceAdd;
+
+ if( nMyBlank )
+ nMultiSpace /= nMyBlank;
+
+ if( nMultiSpace < KSHRT_MAX * SPACING_PRECISION_FACTOR )
+ {
+// pCurr->SetLLSpaceAdd( nMultiSpace, 0 );
+ // --> FME 2006-07-11 #i65711# SetLLSpaceAdd replaces the first value,
+ // instead we want to insert a new first value:
+ std::vector<long>* pVec = pCurr->GetpLLSpaceAdd();
+ pVec->insert( pVec->begin(), nMultiSpace );
+ // <--
+ bRet = sal_True;
+ }
+ }
+ }
+ return bRet;
+}
+/*--------------------------------------------------
+ * SwDoubleLinePortion::ResetSpaceAdd(..)
+ * cancels the manipulation from SwDoubleLinePortion::ChangeSpaceAdd(..)
+ * --------------------------------------------------*/
+
+void SwDoubleLinePortion::ResetSpaceAdd( SwLineLayout* pCurr )
+{
+ pCurr->RemoveFirstLLSpaceAdd();;
+ if( !pCurr->GetLLSpaceAddCount() )
+ pCurr->FinishSpaceAdd();
+}
+
+SwDoubleLinePortion::~SwDoubleLinePortion()
+{
+ delete pBracket;
+}
+
+/*--------------------------------------------------
+ * SwRubyPortion::SwRubyPortion(..)
+ * constructs a ruby portion, i.e. an additional text is displayed
+ * beside the main text, e.g. phonetic characters.
+ * --------------------------------------------------*/
+
+
+SwRubyPortion::SwRubyPortion( const SwRubyPortion& rRuby, xub_StrLen nEnd ) :
+ SwMultiPortion( nEnd ),
+ nRubyOffset( rRuby.GetRubyOffset() ),
+ nAdjustment( rRuby.GetAdjustment() )
+{
+ SetDirection( rRuby.GetDirection() ),
+ SetTop( rRuby.OnTop() );
+ SetRuby();
+}
+
+/*--------------------------------------------------
+ * SwRubyPortion::SwRubyPortion(..)
+ * constructs a ruby portion, i.e. an additional text is displayed
+ * beside the main text, e.g. phonetic characters.
+ * --------------------------------------------------*/
+
+SwRubyPortion::SwRubyPortion( const SwMultiCreator& rCreate, const SwFont& rFnt,
+ const IDocumentSettingAccess& rIDocumentSettingAccess,
+ xub_StrLen nEnd, xub_StrLen nOffs,
+ const sal_Bool* pForceRubyPos )
+ : SwMultiPortion( nEnd )
+{
+ SetRuby();
+ OSL_ENSURE( SW_MC_RUBY == rCreate.nId, "Ruby expected" );
+ OSL_ENSURE( RES_TXTATR_CJK_RUBY == rCreate.pAttr->Which(), "Wrong attribute" );
+ const SwFmtRuby& rRuby = rCreate.pAttr->GetRuby();
+ nAdjustment = rRuby.GetAdjustment();
+ nRubyOffset = nOffs;
+
+ // in grid mode we force the ruby text to the upper or lower line
+ if ( pForceRubyPos )
+ SetTop( *pForceRubyPos );
+ else
+ SetTop( ! rRuby.GetPosition() );
+
+ const SwCharFmt* pFmt = ((SwTxtRuby*)rCreate.pAttr)->GetCharFmt();
+ SwFont *pRubyFont;
+ if( pFmt )
+ {
+ const SwAttrSet& rSet = pFmt->GetAttrSet();
+ pRubyFont = new SwFont( rFnt );
+ pRubyFont->SetDiffFnt( &rSet, &rIDocumentSettingAccess );
+
+ // we do not allow a vertical font for the ruby text
+ pRubyFont->SetVertical( rFnt.GetOrientation() );
+ }
+ else
+ pRubyFont = NULL;
+
+ String aStr( rRuby.GetText(), nOffs, STRING_LEN );
+ SwFldPortion *pFld = new SwFldPortion( aStr, pRubyFont );
+ pFld->SetNextOffset( nOffs );
+ pFld->SetFollow( sal_True );
+
+ if( OnTop() )
+ GetRoot().SetPortion( pFld );
+ else
+ {
+ GetRoot().SetNext( new SwLineLayout() );
+ GetRoot().GetNext()->SetPortion( pFld );
+ }
+
+ // ruby portions have the same direction as the frame directions
+ if ( rCreate.nLevel % 2 )
+ {
+ // switch right and left ruby adjustment in rtl environment
+ if ( 0 == nAdjustment )
+ nAdjustment = 2;
+ else if ( 2 == nAdjustment )
+ nAdjustment = 0;
+
+ SetDirection( DIR_RIGHT2LEFT );
+ }
+ else
+ SetDirection( DIR_LEFT2RIGHT );
+}
+
+/*--------------------------------------------------
+ * SwRubyPortion::_Adjust(..)
+ * In ruby portion there are different alignments for
+ * the ruby text and the main text.
+ * Left, right, centered and two possibilities of block adjustment
+ * The block adjustment is realized by spacing between the characteres,
+ * either with a half space or no space in front of the first letter and
+ * a half space at the end of the last letter.
+ * Notice: the smaller line will be manipulated, normally it's the ruby line,
+ * but it could be the main text, too.
+ * If there is a tabulator in smaller line, no adjustment is possible.
+ * --------------------------------------------------*/
+
+void SwRubyPortion::_Adjust( SwTxtFormatInfo &rInf )
+{
+ SwTwips nLineDiff = GetRoot().Width() - GetRoot().GetNext()->Width();
+ xub_StrLen nOldIdx = rInf.GetIdx();
+ if( !nLineDiff )
+ return;
+ SwLineLayout *pCurr;
+ if( nLineDiff < 0 )
+ { // The first line has to be adjusted.
+ if( GetTab1() )
+ return;
+ pCurr = &GetRoot();
+ nLineDiff = -nLineDiff;
+ }
+ else
+ { // The second line has to be adjusted.
+ if( GetTab2() )
+ return;
+ pCurr = GetRoot().GetNext();
+ rInf.SetIdx( nOldIdx + GetRoot().GetLen() );
+ }
+ KSHORT nLeft = 0; // the space in front of the first letter
+ KSHORT nRight = 0; // the space at the end of the last letter
+ sal_uInt16 nSub = 0;
+ switch ( nAdjustment )
+ {
+ case 1: nRight = static_cast<sal_uInt16>(nLineDiff / 2); // no break
+ case 2: nLeft = static_cast<sal_uInt16>(nLineDiff - nRight); break;
+ case 3: nSub = 1; // no break
+ case 4:
+ {
+ xub_StrLen nCharCnt = 0;
+ SwLinePortion *pPor;
+ for( pPor = pCurr->GetFirstPortion(); pPor; pPor = pPor->GetPortion() )
+ {
+ if( pPor->InTxtGrp() )
+ ((SwTxtPortion*)pPor)->GetSpaceCnt( rInf, nCharCnt );
+ rInf.SetIdx( rInf.GetIdx() + pPor->GetLen() );
+ }
+ if( nCharCnt > nSub )
+ {
+ SwTwips nCalc = nLineDiff / ( nCharCnt - nSub );
+ short nTmp;
+ if( nCalc < SHRT_MAX )
+ nTmp = -short(nCalc);
+ else
+ nTmp = SHRT_MIN;
+
+ pCurr->CreateSpaceAdd( SPACING_PRECISION_FACTOR * nTmp );
+ nLineDiff -= nCalc * ( nCharCnt - 1 );
+ }
+ if( nLineDiff > 1 )
+ {
+ nRight = static_cast<sal_uInt16>(nLineDiff / 2);
+ nLeft = static_cast<sal_uInt16>(nLineDiff - nRight);
+ }
+ break;
+ }
+ default: OSL_FAIL( "New ruby adjustment" );
+ }
+ if( nLeft || nRight )
+ {
+ if( !pCurr->GetPortion() )
+ pCurr->SetPortion( new SwTxtPortion( *pCurr ) );
+ SwMarginPortion *pMarg = new SwMarginPortion( 0 );
+ if( nLeft )
+ {
+ pMarg->AddPrtWidth( nLeft );
+ pMarg->SetPortion( pCurr->GetPortion() );
+ pCurr->SetPortion( pMarg );
+ }
+ if( nRight )
+ {
+ pMarg = new SwMarginPortion( 0 );
+ pMarg->AddPrtWidth( nRight );
+ pCurr->FindLastPortion()->Append( pMarg );
+ }
+ }
+
+ pCurr->Width( Width() );
+ rInf.SetIdx( nOldIdx );
+}
+
+/*--------------------------------------------------
+ * CalcRubyOffset()
+ * has to change the nRubyOffset, if there's a fieldportion
+ * in the phonetic line.
+ * The nRubyOffset is the position in the rubystring, where the
+ * next SwRubyPortion has start the displaying of the phonetics.
+ * --------------------------------------------------*/
+
+void SwRubyPortion::CalcRubyOffset()
+{
+ const SwLineLayout *pCurr = &GetRoot();
+ if( !OnTop() )
+ {
+ pCurr = pCurr->GetNext();
+ if( !pCurr )
+ return;
+ }
+ const SwLinePortion *pPor = pCurr->GetFirstPortion();
+ const SwFldPortion *pFld = NULL;
+ while( pPor )
+ {
+ if( pPor->InFldGrp() )
+ pFld = (SwFldPortion*)pPor;
+ pPor = pPor->GetPortion();
+ }
+ if( pFld )
+ {
+ if( pFld->HasFollow() )
+ nRubyOffset = pFld->GetNextOffset();
+ else
+ nRubyOffset = STRING_LEN;
+ }
+}
+
+/*--------------------------------------------------
+ * SwTxtSizeInfo::GetMultiCreator(..)
+ * If we (e.g. the position rPos) are inside a two-line-attribute or
+ * a ruby-attribute, the attribute will be returned in a SwMultiCreator-struct,
+ * otherwise the function returns zero.
+ * The rPos parameter is set to the end of the multiportion,
+ * normally this is the end of the attribute,
+ * but sometimes it is the start of another attribute, which finished or
+ * interrupts the first attribute.
+ * E.g. a ruby portion interrupts a 2-line-attribute, a 2-line-attribute
+ * with different brackets interrupts another 2-line-attribute.
+ * --------------------------------------------------*/
+
+/*--------------------------------------------------
+ * lcl_Has2Lines(..)
+ * is a little help function for GetMultiCreator(..)
+ * It extracts the 2-line-format from a 2-line-attribute or a character style.
+ * The rValue is set to sal_True, if the 2-line-attribute's value is set and
+ * no 2-line-format reference is passed. If there is a 2-line-format reference,
+ * then the rValue is set only, if the 2-line-attribute's value is set _and_
+ * the 2-line-formats has the same brackets.
+ * --------------------------------------------------*/
+
+sal_Bool lcl_Has2Lines( const SwTxtAttr& rAttr, const SvxTwoLinesItem* &rpRef,
+ sal_Bool &rValue )
+{
+ const SfxPoolItem* pItem = CharFmt::GetItem( rAttr, RES_CHRATR_TWO_LINES );
+ if( pItem )
+ {
+ rValue = ((SvxTwoLinesItem*)pItem)->GetValue();
+ if( !rpRef )
+ rpRef = (SvxTwoLinesItem*)pItem;
+ else if( ((SvxTwoLinesItem*)pItem)->GetEndBracket() !=
+ rpRef->GetEndBracket() ||
+ ((SvxTwoLinesItem*)pItem)->GetStartBracket() !=
+ rpRef->GetStartBracket() )
+ rValue = sal_False;
+ return sal_True;
+ }
+ return sal_False;
+}
+
+/*--------------------------------------------------
+ * lcl_HasRotation(..)
+ * is a little help function for GetMultiCreator(..)
+ * It extracts the charrotation from a charrotate-attribute or a character style.
+ * The rValue is set to sal_True, if the charrotate-attribute's value is set and
+ * no charrotate-format reference is passed.
+ * If there is a charrotate-format reference, then the rValue is set only,
+ * if the charrotate-attribute's value is set _and_ identical
+ * to the charrotate-format's value.
+ * --------------------------------------------------*/
+
+sal_Bool lcl_HasRotation( const SwTxtAttr& rAttr,
+ const SvxCharRotateItem* &rpRef, sal_Bool &rValue )
+{
+ const SfxPoolItem* pItem = CharFmt::GetItem( rAttr, RES_CHRATR_ROTATE );
+ if ( pItem )
+ {
+ rValue = 0 != ((SvxCharRotateItem*)pItem)->GetValue();
+ if( !rpRef )
+ rpRef = (SvxCharRotateItem*)pItem;
+ else if( ((SvxCharRotateItem*)pItem)->GetValue() !=
+ rpRef->GetValue() )
+ rValue = sal_False;
+ return sal_True;
+ }
+
+ return sal_False;
+}
+
+SwMultiCreator* SwTxtSizeInfo::GetMultiCreator( xub_StrLen &rPos,
+ SwMultiPortion* pMulti ) const
+{
+ SwScriptInfo& rSI = ((SwParaPortion*)GetParaPortion())->GetScriptInfo();
+
+ // get the last embedding level
+ sal_uInt8 nCurrLevel;
+ if ( pMulti )
+ {
+ OSL_ENSURE( pMulti->IsBidi(), "Nested MultiPortion is not BidiPortion" );
+ // level associated with bidi-portion;
+ nCurrLevel = ((SwBidiPortion*)pMulti)->GetLevel();
+ }
+ else
+ // no nested bidi portion required
+ nCurrLevel = GetTxtFrm()->IsRightToLeft() ? 1 : 0;
+
+ // check if there is a field at rPos:
+ sal_uInt8 nNextLevel = nCurrLevel;
+ sal_Bool bFldBidi = sal_False;
+
+ if ( CH_TXTATR_BREAKWORD == GetChar( rPos ) )
+ {
+ bFldBidi = sal_True;
+/*
+ // examining the script of the field text should be sufficient
+ // for 99% of all cases
+ XubString aTxt = GetTxtFrm()->GetTxtNode()->GetExpandTxt( rPos, 1 );
+
+ if ( pBreakIt->GetBreakIter().is() && aTxt.Len() )
+ {
+ sal_Bool bFldDir = ( i18n::ScriptType::COMPLEX ==
+ pBreakIt->GetRealScriptOfText( aTxt, 0 ) );
+ sal_Bool bCurrDir = ( 0 != ( nCurrLevel % 2 ) );
+ if ( bFldDir != bCurrDir )
+ {
+ nNextLevel = nCurrLevel + 1;
+ bFldBidi = sal_True;
+ }
+ }*/
+ }
+ else
+ nNextLevel = rSI.DirType( rPos );
+
+ if ( GetTxt().Len() != rPos && nNextLevel > nCurrLevel )
+ {
+ rPos = bFldBidi ? rPos + 1 : rSI.NextDirChg( rPos, &nCurrLevel );
+ if ( STRING_LEN == rPos )
+ return NULL;
+ SwMultiCreator *pRet = new SwMultiCreator;
+ pRet->pItem = NULL;
+ pRet->pAttr = NULL;
+ pRet->nId = SW_MC_BIDI;
+ pRet->nLevel = nCurrLevel + 1;
+ return pRet;
+ }
+
+ // a bidi portion can only contain other bidi portions
+ if ( pMulti )
+ return NULL;
+
+ const SvxCharRotateItem* pRotate = NULL;
+ const SfxPoolItem* pRotItem;
+ if( SFX_ITEM_SET == pFrm->GetTxtNode()->GetSwAttrSet().
+ GetItemState( RES_CHRATR_ROTATE, sal_True, &pRotItem ) &&
+ ((SvxCharRotateItem*)pRotItem)->GetValue() )
+ pRotate = (SvxCharRotateItem*)pRotItem;
+ else
+ pRotItem = NULL;
+ const SvxTwoLinesItem* p2Lines = NULL;
+ const SfxPoolItem* pItem;
+ if( SFX_ITEM_SET == pFrm->GetTxtNode()->GetSwAttrSet().
+ GetItemState( RES_CHRATR_TWO_LINES, sal_True, &pItem ) &&
+ ((SvxTwoLinesItem*)pItem)->GetValue() )
+ p2Lines = (SvxTwoLinesItem*)pItem;
+ else
+ pItem = NULL;
+
+ const SwpHints *pHints = pFrm->GetTxtNode()->GetpSwpHints();
+ if( !pHints && !p2Lines && !pRotate )
+ return NULL;
+ const SwTxtAttr *pRuby = NULL;
+ sal_Bool bTwo = sal_False;
+ sal_Bool bRot = sal_False;
+ sal_uInt16 n2Lines = USHRT_MAX;
+ sal_uInt16 nRotate = USHRT_MAX;
+ sal_uInt16 nCount = pHints ? pHints->Count() : 0;
+ sal_uInt16 i;
+ for( i = 0; i < nCount; ++i )
+ {
+ const SwTxtAttr *pTmp = (*pHints)[i];
+ xub_StrLen nStart = *pTmp->GetStart();
+ if( rPos < nStart )
+ break;
+ if( *pTmp->GetAnyEnd() > rPos )
+ {
+ if( RES_TXTATR_CJK_RUBY == pTmp->Which() )
+ pRuby = pTmp;
+ else
+ {
+ const SvxCharRotateItem* pRoTmp = NULL;
+ if( lcl_HasRotation( *pTmp, pRoTmp, bRot ) )
+ {
+ nRotate = bRot ? i : nCount;
+ pRotate = pRoTmp;
+ }
+ const SvxTwoLinesItem* p2Tmp = NULL;
+ if( lcl_Has2Lines( *pTmp, p2Tmp, bTwo ) )
+ {
+ n2Lines = bTwo ? i : nCount;
+ p2Lines = p2Tmp;
+ }
+ }
+ }
+ }
+ if( pRuby )
+ { // The winner is ... a ruby attribute and so
+ // the end of the multiportion is the end of the ruby attribute.
+ rPos = *pRuby->GetEnd();
+ SwMultiCreator *pRet = new SwMultiCreator;
+ pRet->pItem = NULL;
+ pRet->pAttr = pRuby;
+ pRet->nId = SW_MC_RUBY;
+ pRet->nLevel = GetTxtFrm()->IsRightToLeft() ? 1 : 0;
+ return pRet;
+ }
+ if( n2Lines < nCount || ( pItem && pItem == p2Lines &&
+ rPos < GetTxt().Len() ) )
+ { // The winner is a 2-line-attribute,
+ // the end of the multiportion depends on the following attributes...
+ SwMultiCreator *pRet = new SwMultiCreator;
+
+ // We note the endpositions of the 2-line attributes in aEnd as stack
+ SvXub_StrLens aEnd;
+
+ // The bOn flag signs the state of the last 2-line attribute in the
+ // aEnd-stack, it is compatible with the winner-attribute or
+ // it interrupts the other attribute.
+ sal_Bool bOn = sal_True;
+
+ if( n2Lines < nCount )
+ {
+ pRet->pItem = NULL;
+ pRet->pAttr = (*pHints)[n2Lines];
+ aEnd.push_front( *pRet->pAttr->GetEnd() );
+ if( pItem )
+ {
+ aEnd.front() = GetTxt().Len();
+ bOn = ((SvxTwoLinesItem*)pItem)->GetEndBracket() ==
+ p2Lines->GetEndBracket() &&
+ ((SvxTwoLinesItem*)pItem)->GetStartBracket() ==
+ p2Lines->GetStartBracket();
+ }
+ }
+ else
+ {
+ pRet->pItem = pItem;
+ pRet->pAttr = NULL;
+ aEnd.push_front( GetTxt().Len() );
+ }
+ pRet->nId = SW_MC_DOUBLE;
+ pRet->nLevel = GetTxtFrm()->IsRightToLeft() ? 1 : 0;
+
+ // n2Lines is the index of the last 2-line-attribute, which contains
+ // the actual position.
+ i = 0;
+ // At this moment we know that at position rPos the "winner"-attribute
+ // causes a 2-line-portion. The end of the attribute is the end of the
+ // portion, if there's no interrupting attribute.
+ // There are two kinds of interruptors:
+ // - ruby attributes stops the 2-line-attribute, the end of the
+ // multiline is the start of the ruby attribute
+ // - 2-line-attributes with value "Off" or with different brackets,
+ // these attributes may interrupt the winner, but they could be
+ // neutralized by another 2-line-attribute starting at the same
+ // position with the same brackets as the winner-attribute.
+
+ // In the following loop rPos is the critical position and it will be
+ // evaluated, if at rPos starts a interrupting or a maintaining
+ // continuity attribute.
+ while( i < nCount )
+ {
+ const SwTxtAttr *pTmp = (*pHints)[i++];
+ if( *pTmp->GetAnyEnd() <= rPos )
+ continue;
+ if( rPos < *pTmp->GetStart() )
+ {
+ // If bOn is sal_False and the next attribute starts later than rPos
+ // the winner attribute is interrupted at rPos.
+ // If the start of the next atribute is behind the end of
+ // the last attribute on the aEnd-stack, this is the endposition
+ // on the stack is the end of the 2-line portion.
+ if( !bOn || aEnd.back() < *pTmp->GetStart() )
+ break;
+ // At this moment, bOn is sal_True and the next attribute starts
+ // behind rPos, so we could move rPos to the next startpoint
+ rPos = *pTmp->GetStart();
+ // We clean up the aEnd-stack, endpositions equal to rPos are
+ // superfluous.
+ while( !aEnd.empty() && aEnd.back() <= rPos )
+ {
+ bOn = !bOn;
+ aEnd.pop_back();
+ }
+ // If the endstack is empty, we simulate an attribute with
+ // state sal_True and endposition rPos
+ if( aEnd.empty() )
+ {
+ aEnd.push_front( rPos );
+ bOn = sal_True;
+ }
+ }
+ // A ruby attribute stops the 2-line immediately
+ if( RES_TXTATR_CJK_RUBY == pTmp->Which() )
+ return pRet;
+ if( lcl_Has2Lines( *pTmp, p2Lines, bTwo ) )
+ { // We have an interesting attribute..
+ if( bTwo == bOn )
+ { // .. with the same state, so the last attribute could
+ // be continued.
+ if( aEnd.back() < *pTmp->GetEnd() )
+ aEnd.back() = *pTmp->GetEnd();
+ }
+ else
+ { // .. with a different state.
+ bOn = bTwo;
+ // If this is smaller than the last on the stack, we put
+ // it on the stack. If it has the same endposition, the last
+ // could be removed.
+ if( aEnd.back() > *pTmp->GetEnd() )
+ aEnd.push_back( *pTmp->GetEnd() );
+ else if( aEnd.size() > 1 )
+ aEnd.pop_back();
+ else
+ aEnd.back() = *pTmp->GetEnd();
+ }
+ }
+ }
+ if( bOn && !aEnd.empty() )
+ rPos = aEnd.back();
+ return pRet;
+ }
+ if( nRotate < nCount || ( pRotItem && pRotItem == pRotate &&
+ rPos < GetTxt().Len() ) )
+ { // The winner is a rotate-attribute,
+ // the end of the multiportion depends on the following attributes...
+ SwMultiCreator *pRet = new SwMultiCreator;
+ pRet->nId = SW_MC_ROTATE;
+
+ // We note the endpositions of the 2-line attributes in aEnd as stack
+ SvXub_StrLens aEnd;
+
+ // The bOn flag signs the state of the last 2-line attribute in the
+ // aEnd-stack, which could interrupts the winning rotation attribute.
+ sal_Bool bOn = pItem ? sal_True : sal_False;
+ aEnd.push_front( GetTxt().Len() );
+ // n2Lines is the index of the last 2-line-attribute, which contains
+ // the actual position.
+ i = 0;
+ xub_StrLen n2Start = rPos;
+ while( i < nCount )
+ {
+ const SwTxtAttr *pTmp = (*pHints)[i++];
+ if( *pTmp->GetAnyEnd() <= n2Start )
+ continue;
+ if( n2Start < *pTmp->GetStart() )
+ {
+ if( bOn || aEnd.back() < *pTmp->GetStart() )
+ break;
+ n2Start = *pTmp->GetStart();
+ while( !aEnd.empty() && aEnd.back() <= n2Start )
+ {
+ bOn = !bOn;
+ aEnd.pop_back();
+ }
+ if( aEnd.empty() )
+ {
+ aEnd.push_front( n2Start );
+ bOn = sal_False;
+ }
+ }
+ // A ruby attribute stops immediately
+ if( RES_TXTATR_CJK_RUBY == pTmp->Which() )
+ {
+ bOn = sal_True;
+ break;
+ }
+ p2Lines = NULL;
+ if( lcl_Has2Lines( *pTmp, p2Lines, bTwo ) )
+ {
+ if( bTwo == bOn )
+ {
+ if( aEnd.back() < *pTmp->GetEnd() )
+ aEnd.back() = *pTmp->GetEnd();
+ }
+ else
+ {
+ bOn = bTwo;
+ if( aEnd.back() > *pTmp->GetEnd() )
+ aEnd.push_back( *pTmp->GetEnd() );
+ else if( aEnd.size() > 1 )
+ aEnd.pop_back();
+ else
+ aEnd.back() = *pTmp->GetEnd();
+ }
+ }
+ }
+ if( !bOn && !aEnd.empty() )
+ n2Start = aEnd.back();
+
+ if( !aEnd.empty() )
+ aEnd.clear();
+
+ bOn = sal_True;
+ if( nRotate < nCount )
+ {
+ pRet->pItem = NULL;
+ pRet->pAttr = (*pHints)[nRotate];
+ aEnd.push_front( *pRet->pAttr->GetEnd() );
+ if( pRotItem )
+ {
+ aEnd.front() = GetTxt().Len();
+ bOn = ((SvxCharRotateItem*)pRotItem)->GetValue() ==
+ pRotate->GetValue();
+ }
+ }
+ else
+ {
+ pRet->pItem = pRotItem;
+ pRet->pAttr = NULL;
+ aEnd.push_front( GetTxt().Len() );
+ }
+ i = 0;
+ while( i < nCount )
+ {
+ const SwTxtAttr *pTmp = (*pHints)[i++];
+ if( *pTmp->GetAnyEnd() <= rPos )
+ continue;
+ if( rPos < *pTmp->GetStart() )
+ {
+ if( !bOn || aEnd.back() < *pTmp->GetStart() )
+ break;
+ rPos = *pTmp->GetStart();
+ while( !aEnd.empty() && aEnd.back() <= rPos )
+ {
+ bOn = !bOn;
+ aEnd.pop_back();
+ }
+ if( aEnd.empty() )
+ {
+ aEnd.push_front( rPos );
+ bOn = sal_True;
+ }
+ }
+ if( RES_TXTATR_CJK_RUBY == pTmp->Which() )
+ {
+ bOn = sal_False;
+ break;
+ }
+ if( lcl_HasRotation( *pTmp, pRotate, bTwo ) )
+ {
+ if( bTwo == bOn )
+ {
+ if( aEnd.back() < *pTmp->GetEnd() )
+ aEnd.back() = *pTmp->GetEnd();
+ }
+ else
+ {
+ bOn = bTwo;
+ if( aEnd.back() > *pTmp->GetEnd() )
+ aEnd.push_back( *pTmp->GetEnd() );
+ else if( aEnd.size() > 1 )
+ aEnd.pop_back();
+ else
+ aEnd.back() = *pTmp->GetEnd();
+ }
+ }
+ }
+ if( bOn && !aEnd.empty() )
+ rPos = aEnd.back();
+ if( rPos > n2Start )
+ rPos = n2Start;
+ return pRet;
+ }
+ return NULL;
+}
+
+/*--------------------------------------------------
+ * SwSpaceManipulator
+ * is a little helper class to manage the spaceadd-arrays of the text adjustment
+ * during a PaintMultiPortion.
+ * The constructor prepares the array for the first line of multiportion,
+ * the SecondLine-function restores the values for the first line and prepares
+ * the second line.
+ * The destructor restores the values of the last manipulation.
+ * --------------------------------------------------*/
+
+class SwSpaceManipulator
+{
+ SwTxtPaintInfo& rInfo;
+ SwMultiPortion& rMulti;
+ std::vector<long>* pOldSpaceAdd;
+ MSHORT nOldSpIdx;
+ long nSpaceAdd;
+ sal_Bool bSpaceChg : 1;
+ sal_uInt8 nOldDir : 2;
+public:
+ SwSpaceManipulator( SwTxtPaintInfo& rInf, SwMultiPortion& rMult );
+ ~SwSpaceManipulator();
+ void SecondLine();
+ inline long GetSpaceAdd() const { return nSpaceAdd; }
+};
+
+SwSpaceManipulator::SwSpaceManipulator( SwTxtPaintInfo& rInf,
+ SwMultiPortion& rMult ) :
+ rInfo( rInf ), rMulti( rMult )
+{
+ pOldSpaceAdd = rInfo.GetpSpaceAdd();
+ nOldSpIdx = rInfo.GetSpaceIdx();
+ nOldDir = rInfo.GetDirection();
+ rInfo.SetDirection( rMulti.GetDirection() );
+ bSpaceChg = sal_False;
+
+ if( rMulti.IsDouble() )
+ {
+ nSpaceAdd = ( pOldSpaceAdd && !rMulti.HasTabulator() ) ?
+ rInfo.GetSpaceAdd() : 0;
+ if( rMulti.GetRoot().IsSpaceAdd() )
+ {
+ rInfo.SetpSpaceAdd( rMulti.GetRoot().GetpLLSpaceAdd() );
+ rInfo.ResetSpaceIdx();
+ bSpaceChg = rMulti.ChgSpaceAdd( &rMulti.GetRoot(), nSpaceAdd );
+ }
+ else if( rMulti.HasTabulator() )
+ rInfo.SetpSpaceAdd( NULL );
+ }
+ else if ( ! rMulti.IsBidi() )
+ {
+ rInfo.SetpSpaceAdd( rMulti.GetRoot().GetpLLSpaceAdd() );
+ rInfo.ResetSpaceIdx();
+ }
+}
+
+void SwSpaceManipulator::SecondLine()
+{
+ if( bSpaceChg )
+ {
+ rInfo.RemoveFirstSpaceAdd();
+ bSpaceChg = sal_False;
+ }
+ SwLineLayout *pLay = rMulti.GetRoot().GetNext();
+ if( pLay->IsSpaceAdd() )
+ {
+ rInfo.SetpSpaceAdd( pLay->GetpLLSpaceAdd() );
+ rInfo.ResetSpaceIdx();
+ bSpaceChg = rMulti.ChgSpaceAdd( pLay, nSpaceAdd );
+ }
+ else
+ {
+ rInfo.SetpSpaceAdd( (!rMulti.IsDouble() || rMulti.HasTabulator() ) ?
+ 0 : pOldSpaceAdd );
+ rInfo.SetSpaceIdx( nOldSpIdx);
+ }
+}
+
+SwSpaceManipulator::~SwSpaceManipulator()
+{
+ if( bSpaceChg )
+ {
+ rInfo.RemoveFirstSpaceAdd();
+ bSpaceChg = sal_False;
+ }
+ rInfo.SetpSpaceAdd( pOldSpaceAdd );
+ rInfo.SetSpaceIdx( nOldSpIdx);
+ rInfo.SetDirection( nOldDir );
+}
+
+/*--------------------------------------------------
+ * SwTxtPainter::PaintMultiPortion manages the paint for a SwMultiPortion.
+ * External, for the calling function, it seems to be a normal Paint-function,
+ * internal it is like a SwTxtFrm::Paint with multiple DrawTextLines
+ * --------------------------------------------------*/
+
+void SwTxtPainter::PaintMultiPortion( const SwRect &rPaint,
+ SwMultiPortion& rMulti, const SwMultiPortion* pEnvPor )
+{
+ GETGRID( pFrm->FindPageFrm() )
+ const sal_Bool bHasGrid = pGrid && GetInfo().SnapToGrid();
+ sal_uInt16 nRubyHeight = 0;
+ sal_Bool bRubyTop = sal_False;
+
+ if ( bHasGrid )
+ {
+ nRubyHeight = pGrid->GetRubyHeight();
+ bRubyTop = ! pGrid->GetRubyTextBelow();
+ }
+
+ // do not allow grid mode for first line in ruby portion
+ const sal_Bool bRubyInGrid = bHasGrid && rMulti.IsRuby();
+
+ const sal_uInt16 nOldHeight = rMulti.Height();
+ const sal_Bool bOldGridModeAllowed = GetInfo().SnapToGrid();
+
+ if ( bRubyInGrid )
+ {
+ GetInfo().SetSnapToGrid( ! bRubyTop );
+ rMulti.Height( pCurr->Height() );
+ }
+
+ SwLayoutModeModifier aLayoutModeModifier( *GetInfo().GetOut() );
+ sal_uInt8 nEnvDir = 0;
+ sal_uInt8 nThisDir = 0;
+ sal_uInt8 nFrmDir = 0;
+ if ( rMulti.IsBidi() )
+ {
+ // these values are needed for the calculation of the x coordinate
+ // and the layout mode
+ OSL_ENSURE( ! pEnvPor || pEnvPor->IsBidi(),
+ "Oh no, I expected a BidiPortion" );
+ nFrmDir = GetInfo().GetTxtFrm()->IsRightToLeft() ? 1 : 0;
+ nEnvDir = pEnvPor ? ((SwBidiPortion*)pEnvPor)->GetLevel() % 2 : nFrmDir;
+ nThisDir = ((SwBidiPortion&)rMulti).GetLevel() % 2;
+ }
+
+#if OSL_DEBUG_LEVEL > 1
+ // only paint first level bidi portions
+ if( rMulti.Width() > 1 && ! pEnvPor )
+ GetInfo().DrawViewOpt( rMulti, POR_FLD );
+#endif
+
+ if ( bRubyInGrid )
+ rMulti.Height( nOldHeight );
+
+ // do we have to repaint a post it portion?
+ if( GetInfo().OnWin() && rMulti.GetPortion() &&
+ ! rMulti.GetPortion()->Width() )
+ rMulti.GetPortion()->PrePaint( GetInfo(), &rMulti );
+
+ // old values must be saved and restored at the end
+ xub_StrLen nOldLen = GetInfo().GetLen();
+ KSHORT nOldX = KSHORT(GetInfo().X());
+ long nOldY = GetInfo().Y();
+ xub_StrLen nOldIdx = GetInfo().GetIdx();
+
+ SwSpaceManipulator aManip( GetInfo(), rMulti );
+
+ SwFontSave *pFontSave;
+ SwFont* pTmpFnt;
+
+ if( rMulti.IsDouble() )
+ {
+ pTmpFnt = new SwFont( *GetInfo().GetFont() );
+ if( rMulti.IsDouble() )
+ {
+ SetPropFont( 50 );
+ pTmpFnt->SetProportion( GetPropFont() );
+ }
+ pFontSave = new SwFontSave( GetInfo(), pTmpFnt, this );
+ }
+ else
+ {
+ pFontSave = NULL;
+ pTmpFnt = NULL;
+ }
+
+ if( rMulti.HasBrackets() )
+ {
+ xub_StrLen nTmpOldIdx = GetInfo().GetIdx();
+ GetInfo().SetIdx(((SwDoubleLinePortion&)rMulti).GetBrackets()->nStart);
+ SeekAndChg( GetInfo() );
+ ((SwDoubleLinePortion&)rMulti).PaintBracket( GetInfo(), 0, sal_True );
+ GetInfo().SetIdx( nTmpOldIdx );
+ }
+
+ KSHORT nTmpX = KSHORT(GetInfo().X());
+
+ SwLineLayout* pLay = &rMulti.GetRoot();// the first line of the multiportion
+ SwLinePortion* pPor = pLay->GetFirstPortion();//first portion of these line
+ SwTwips nOfst = 0;
+
+ // GetInfo().Y() is the baseline from the surrounding line. We must switch
+ // this temporary to the baseline of the inner lines of the multiportion.
+ if( rMulti.HasRotation() )
+ {
+ if( rMulti.IsRevers() )
+ {
+ GetInfo().Y( nOldY - rMulti.GetAscent() );
+ nOfst = nTmpX + rMulti.Width();
+ }
+ else
+ {
+ GetInfo().Y( nOldY - rMulti.GetAscent() + rMulti.Height() );
+ nOfst = nTmpX;
+ }
+ }
+ else if ( rMulti.IsBidi() )
+ {
+ // does the current bidi portion has the same direction
+ // as its environment?
+ if ( nEnvDir != nThisDir )
+ {
+ // different directions, we have to adjust the x coordinate
+ SwTwips nMultiWidth = rMulti.Width() +
+ rMulti.CalcSpacing( GetInfo().GetSpaceAdd(), GetInfo() );
+
+ if ( nFrmDir == nThisDir )
+ GetInfo().X( GetInfo().X() - nMultiWidth );
+ else
+ GetInfo().X( GetInfo().X() + nMultiWidth );
+ }
+
+ nOfst = nOldY - rMulti.GetAscent();
+
+ // set layout mode
+ aLayoutModeModifier.Modify( nThisDir );
+ }
+ else
+ nOfst = nOldY - rMulti.GetAscent();
+
+ sal_Bool bRest = pLay->IsRest();
+ sal_Bool bFirst = sal_True;
+
+ OSL_ENSURE( 0 == GetInfo().GetUnderFnt() || rMulti.IsBidi(),
+ " Only BiDi portions are allowed to use the common underlining font" );
+
+ do
+ {
+ if ( bHasGrid )
+ {
+ if( rMulti.HasRotation() )
+ {
+ const sal_uInt16 nAdjustment = ( pLay->Height() - pPor->Height() ) / 2 +
+ pPor->GetAscent();
+ if( rMulti.IsRevers() )
+ GetInfo().X( nOfst - nAdjustment );
+ else
+ GetInfo().X( nOfst + nAdjustment );
+ }
+ else
+ {
+ // special treatment for ruby portions in grid mode
+ SwTwips nAdjustment = 0;
+ if ( rMulti.IsRuby() )
+ {
+ if ( bRubyTop != ( pLay == &rMulti.GetRoot() ) )
+ // adjust base text
+ nAdjustment = ( pCurr->Height() - nRubyHeight - pPor->Height() ) / 2;
+ else if ( bRubyTop )
+ // adjust upper ruby text
+ nAdjustment = nRubyHeight - pPor->Height();
+ // else adjust lower ruby text
+ }
+
+ GetInfo().Y( nOfst + nAdjustment + pPor->GetAscent() );
+ }
+ }
+ else if( rMulti.HasRotation() )
+ {
+ if( rMulti.IsRevers() )
+ GetInfo().X( nOfst - AdjustBaseLine( *pLay, pPor, 0, 0, sal_True ) );
+ else
+ GetInfo().X( nOfst + AdjustBaseLine( *pLay, pPor ) );
+ }
+ else
+ GetInfo().Y( nOfst + AdjustBaseLine( *pLay, pPor ) );
+
+ sal_Bool bSeeked = sal_True;
+ GetInfo().SetLen( pPor->GetLen() );
+
+ if( bRest && pPor->InFldGrp() && !pPor->GetLen() )
+ {
+ if( ((SwFldPortion*)pPor)->HasFont() )
+ bSeeked = sal_False;
+ else
+ SeekAndChgBefore( GetInfo() );
+ }
+ else if( pPor->InTxtGrp() || pPor->InFldGrp() || pPor->InTabGrp() )
+ SeekAndChg( GetInfo() );
+ else if ( !bFirst && pPor->IsBreakPortion() && GetInfo().GetOpt().IsParagraph() )
+ {
+ if( GetRedln() )
+ SeekAndChg( GetInfo() );
+ else
+ SeekAndChgBefore( GetInfo() );
+ }
+ else
+ bSeeked = sal_False;
+
+ SwLinePortion *pNext = pPor->GetPortion();
+ if(GetInfo().OnWin() && pNext && !pNext->Width() )
+ {
+ if ( !bSeeked )
+ SeekAndChg( GetInfo() );
+ pNext->PrePaint( GetInfo(), pPor );
+ }
+
+ CheckSpecialUnderline( pPor );
+ SwUnderlineFont* pUnderLineFnt = GetInfo().GetUnderFnt();
+ if ( pUnderLineFnt )
+ {
+ if ( rMulti.IsDouble() )
+ pUnderLineFnt->GetFont().SetProportion( 50 );
+ pUnderLineFnt->SetPos( GetInfo().GetPos() );
+ }
+
+ if ( rMulti.IsBidi() )
+ {
+ // we do not allow any rotation inside a bidi portion
+ SwFont* pTmpFont = GetInfo().GetFont();
+ pTmpFont->SetVertical( 0, GetInfo().GetTxtFrm()->IsVertical() );
+ }
+
+ if( pPor->IsMultiPortion() && ((SwMultiPortion*)pPor)->IsBidi() )
+ {
+ // but we do allow nested bidi portions
+ OSL_ENSURE( rMulti.IsBidi(), "Only nesting of bidi portions is allowed" );
+ PaintMultiPortion( rPaint, (SwMultiPortion&)*pPor, &rMulti );
+ }
+ else
+ pPor->Paint( GetInfo() );
+
+ if( GetFnt()->IsURL() && pPor->InTxtGrp() )
+ GetInfo().NotifyURL( *pPor );
+
+ bFirst &= !pPor->GetLen();
+ if( pNext || !pPor->IsMarginPortion() )
+ pPor->Move( GetInfo() );
+
+ pPor = pNext;
+
+ // If there's no portion left, we go to the next line
+ if( !pPor && pLay->GetNext() )
+ {
+ pLay = pLay->GetNext();
+ pPor = pLay->GetFirstPortion();
+ bRest = pLay->IsRest();
+ aManip.SecondLine();
+
+ // delete underline font
+ delete GetInfo().GetUnderFnt();
+ GetInfo().SetUnderFnt( 0 );
+
+ if( rMulti.HasRotation() )
+ {
+ if( rMulti.IsRevers() )
+ {
+ nOfst += pLay->Height();
+ GetInfo().Y( nOldY - rMulti.GetAscent() );
+ }
+ else
+ {
+ nOfst -= pLay->Height();
+ GetInfo().Y( nOldY - rMulti.GetAscent() + rMulti.Height() );
+ }
+ }
+ else if ( bHasGrid && rMulti.IsRuby() )
+ {
+ GetInfo().X( nTmpX );
+ if ( bRubyTop )
+ {
+ nOfst += nRubyHeight;
+ GetInfo().SetSnapToGrid( sal_True );
+ }
+ else
+ {
+ nOfst += pCurr->Height() - nRubyHeight;
+ GetInfo().SetSnapToGrid( sal_False );
+ }
+ } else
+ {
+ GetInfo().X( nTmpX );
+ // We switch to the baseline of the next inner line
+ nOfst += rMulti.GetRoot().Height();
+ }
+ }
+ } while( pPor );
+
+ if ( bRubyInGrid )
+ GetInfo().SetSnapToGrid( bOldGridModeAllowed );
+
+ // delete underline font
+ if ( ! rMulti.IsBidi() )
+ {
+ delete GetInfo().GetUnderFnt();
+ GetInfo().SetUnderFnt( 0 );
+ }
+
+ GetInfo().SetIdx( nOldIdx );
+ GetInfo().Y( nOldY );
+
+ if( rMulti.HasBrackets() )
+ {
+ xub_StrLen nTmpOldIdx = GetInfo().GetIdx();
+ GetInfo().SetIdx(((SwDoubleLinePortion&)rMulti).GetBrackets()->nStart);
+ SeekAndChg( GetInfo() );
+ GetInfo().X( nOldX );
+ ((SwDoubleLinePortion&)rMulti).PaintBracket( GetInfo(),
+ aManip.GetSpaceAdd(), sal_False );
+ GetInfo().SetIdx( nTmpOldIdx );
+ }
+ // Restore the saved values
+ GetInfo().X( nOldX );
+ GetInfo().SetLen( nOldLen );
+ delete pFontSave;
+ delete pTmpFnt;
+ SetPropFont( 0 );
+}
+
+sal_Bool lcl_ExtractFieldFollow( SwLineLayout* pLine, SwLinePortion* &rpFld )
+{
+ SwLinePortion* pLast = pLine;
+ rpFld = pLine->GetPortion();
+ while( rpFld && !rpFld->InFldGrp() )
+ {
+ pLast = rpFld;
+ rpFld = rpFld->GetPortion();
+ }
+ sal_Bool bRet = rpFld != 0;
+ if( bRet )
+ {
+ if( ((SwFldPortion*)rpFld)->IsFollow() )
+ {
+ rpFld->Truncate();
+ pLast->SetPortion( NULL );
+ }
+ else
+ rpFld = NULL;
+ }
+ pLine->Truncate();
+ return bRet;
+}
+
+/*----------------------------------------------------
+ * lcl_TruncateMultiPortion
+ * If a multi portion completely has to go to the
+ * next line, this function is called to trunctate
+ * the rest of the remaining multi portion
+ * --------------------------------------------------*/
+
+void lcl_TruncateMultiPortion( SwMultiPortion& rMulti, SwTxtFormatInfo& rInf,
+ xub_StrLen nStartIdx )
+{
+ rMulti.GetRoot().Truncate();
+ rMulti.GetRoot().SetLen(0);
+ rMulti.GetRoot().Width(0);
+// rMulti.CalcSize( *this, aInf );
+ if ( rMulti.GetRoot().GetNext() )
+ {
+ rMulti.GetRoot().GetNext()->Truncate();
+ rMulti.GetRoot().GetNext()->SetLen( 0 );
+ rMulti.GetRoot().GetNext()->Width( 0 );
+ }
+ rMulti.Width( 0 );
+ rMulti.SetLen(0);
+ rInf.SetIdx( nStartIdx );
+}
+
+/*-----------------------------------------------------------------------------
+ * SwTxtFormatter::BuildMultiPortion
+ * manages the formatting of a SwMultiPortion. External, for the calling
+ * function, it seems to be a normal Format-function, internal it is like a
+ * SwTxtFrm::_Format with multiple BuildPortions
+ *---------------------------------------------------------------------------*/
+
+sal_Bool SwTxtFormatter::BuildMultiPortion( SwTxtFormatInfo &rInf,
+ SwMultiPortion& rMulti )
+{
+ SwTwips nMaxWidth = rInf.Width();
+ KSHORT nOldX = 0;
+
+ if( rMulti.HasBrackets() )
+ {
+ xub_StrLen nOldIdx = rInf.GetIdx();
+ rInf.SetIdx( ((SwDoubleLinePortion&)rMulti).GetBrackets()->nStart );
+ SeekAndChg( rInf );
+ nOldX = KSHORT(GetInfo().X());
+ ((SwDoubleLinePortion&)rMulti).FormatBrackets( rInf, nMaxWidth );
+ rInf.SetIdx( nOldIdx );
+ }
+
+ SeekAndChg( rInf );
+ SwFontSave *pFontSave;
+ if( rMulti.IsDouble() )
+ {
+ SwFont* pTmpFnt = new SwFont( *rInf.GetFont() );
+ if( rMulti.IsDouble() )
+ {
+ SetPropFont( 50 );
+ pTmpFnt->SetProportion( GetPropFont() );
+ }
+ pFontSave = new SwFontSave( rInf, pTmpFnt, this );
+ }
+ else
+ pFontSave = NULL;
+
+ SwLayoutModeModifier aLayoutModeModifier( *GetInfo().GetOut() );
+ if ( rMulti.IsBidi() )
+ {
+ // set layout mode
+ aLayoutModeModifier.Modify( ! rInf.GetTxtFrm()->IsRightToLeft() );
+ }
+
+ SwTwips nTmpX = 0;
+
+ if( rMulti.HasRotation() )
+ {
+ // For nMaxWidth we take the height of the body frame.
+ // #i25067#: If the current frame is inside a table, we restrict
+ // nMaxWidth to the current frame height, unless the frame size
+ // attribute is set to variable size:
+
+ // We set nTmpX (which is used for portion calculating) to the
+ // current Y value
+ const SwPageFrm* pPage = pFrm->FindPageFrm();
+ OSL_ENSURE( pPage, "No page in frame!");
+ const SwLayoutFrm* pUpperFrm = pPage;
+
+ if ( pFrm->IsInTab() )
+ {
+ pUpperFrm = pFrm->GetUpper();
+ while ( pUpperFrm && !pUpperFrm->IsCellFrm() )
+ pUpperFrm = pUpperFrm->GetUpper();
+ OSL_ENSURE( pUpperFrm, "pFrm is in table but does not have an upper cell frame" );
+ const SwTableLine* pLine = ((SwRowFrm*)pUpperFrm->GetUpper())->GetTabLine();
+ const SwFmtFrmSize& rFrmFmtSize = pLine->GetFrmFmt()->GetFrmSize();
+ if ( ATT_VAR_SIZE == rFrmFmtSize.GetHeightSizeType() )
+ pUpperFrm = pPage;
+ }
+ if ( pUpperFrm == pPage && !pFrm->IsInFtn() )
+ pUpperFrm = pPage->FindBodyCont();
+
+ nMaxWidth = pUpperFrm ?
+ ( rInf.GetTxtFrm()->IsVertical() ?
+ pUpperFrm->Prt().Width() :
+ pUpperFrm->Prt().Height() ) :
+ USHRT_MAX;
+ }
+ else
+ nTmpX = rInf.X();
+
+ SwMultiPortion* pOldMulti = pMulti;
+
+ pMulti = &rMulti;
+ SwLineLayout *pOldCurr = pCurr;
+ xub_StrLen nOldStart = GetStart();
+ SwTwips nMinWidth = nTmpX + 1;
+ SwTwips nActWidth = nMaxWidth;
+ const xub_StrLen nStartIdx = rInf.GetIdx();
+ xub_StrLen nMultiLen = rMulti.GetLen();
+
+ SwLinePortion *pFirstRest;
+ SwLinePortion *pSecondRest;
+ if( rMulti.IsFormatted() )
+ {
+ if( !lcl_ExtractFieldFollow( &rMulti.GetRoot(), pFirstRest )
+ && rMulti.IsDouble() && rMulti.GetRoot().GetNext() )
+ lcl_ExtractFieldFollow( rMulti.GetRoot().GetNext(), pFirstRest );
+ if( !rMulti.IsDouble() && rMulti.GetRoot().GetNext() )
+ lcl_ExtractFieldFollow( rMulti.GetRoot().GetNext(), pSecondRest );
+ else
+ pSecondRest = NULL;
+ }
+ else
+ {
+ pFirstRest = rMulti.GetRoot().GetPortion();
+ pSecondRest = rMulti.GetRoot().GetNext() ?
+ rMulti.GetRoot().GetNext()->GetPortion() : NULL;
+ if( pFirstRest )
+ rMulti.GetRoot().SetPortion( NULL );
+ if( pSecondRest )
+ rMulti.GetRoot().GetNext()->SetPortion( NULL );
+ rMulti.SetFormatted();
+ nMultiLen = nMultiLen - rInf.GetIdx();
+ }
+
+ // save some values
+ const XubString* pOldTxt = &(rInf.GetTxt());
+ const SwTwips nOldPaintOfst = rInf.GetPaintOfst();
+
+ XubString aMultiStr( rInf.GetTxt(), 0, nMultiLen + rInf.GetIdx() );
+ rInf.SetTxt( aMultiStr );
+ SwTxtFormatInfo aInf( rInf, rMulti.GetRoot(), nActWidth );
+ // Do we allow break cuts? The FirstMulti-Flag is evaluated during
+ // line break determination.
+ sal_Bool bFirstMulti = rInf.GetIdx() != rInf.GetLineStart();
+
+ SwLinePortion *pNextFirst = NULL;
+ SwLinePortion *pNextSecond = NULL;
+ sal_Bool bRet = sal_False;
+
+ GETGRID( pFrm->FindPageFrm() )
+ const sal_Bool bHasGrid = pGrid && GRID_LINES_CHARS == pGrid->GetGridType();
+
+ sal_Bool bRubyTop = sal_False;
+
+ if ( bHasGrid )
+ bRubyTop = ! pGrid->GetRubyTextBelow();
+
+ do
+ {
+ pCurr = &rMulti.GetRoot();
+ nStart = nStartIdx;
+ bRet = sal_False;
+ FormatReset( aInf );
+ aInf.X( nTmpX );
+ aInf.Width( KSHORT(nActWidth) );
+ aInf.RealWidth( KSHORT(nActWidth) );
+ aInf.SetFirstMulti( bFirstMulti );
+ aInf.SetNumDone( rInf.IsNumDone() );
+ aInf.SetFtnDone( rInf.IsFtnDone() );
+
+ if( pFirstRest )
+ {
+ OSL_ENSURE( pFirstRest->InFldGrp(), "BuildMulti: Fieldrest expected");
+ SwFldPortion *pFld =
+ ((SwFldPortion*)pFirstRest)->Clone(
+ ((SwFldPortion*)pFirstRest)->GetExp() );
+ pFld->SetFollow( sal_True );
+ aInf.SetRest( pFld );
+ }
+ aInf.SetRuby( rMulti.IsRuby() && rMulti.OnTop() );
+
+ // in grid mode we temporarily have to disable the grid for the ruby line
+ const sal_Bool bOldGridModeAllowed = GetInfo().SnapToGrid();
+ if ( bHasGrid && aInf.IsRuby() && bRubyTop )
+ aInf.SetSnapToGrid( sal_False );
+
+ // If there's no more rubytext, then buildportion is forbidden
+ if( pFirstRest || !aInf.IsRuby() )
+ BuildPortions( aInf );
+
+ aInf.SetSnapToGrid( bOldGridModeAllowed );
+
+ rMulti.CalcSize( *this, aInf );
+ pCurr->SetRealHeight( pCurr->Height() );
+
+ if( rMulti.IsBidi() )
+ {
+ pNextFirst = aInf.GetRest();
+ break;
+ }
+
+ if( rMulti.HasRotation() && !rMulti.IsDouble() )
+ break;
+ // second line has to be formatted
+ else if( pCurr->GetLen()<nMultiLen || rMulti.IsRuby() || aInf.GetRest())
+ {
+ xub_StrLen nFirstLen = pCurr->GetLen();
+ delete pCurr->GetNext();
+ pCurr->SetNext( new SwLineLayout() );
+ pCurr = pCurr->GetNext();
+ nStart = aInf.GetIdx();
+ aInf.X( nTmpX );
+ SwTxtFormatInfo aTmp( aInf, *pCurr, nActWidth );
+ if( rMulti.IsRuby() )
+ {
+ aTmp.SetRuby( !rMulti.OnTop() );
+ pNextFirst = aInf.GetRest();
+ if( pSecondRest )
+ {
+ OSL_ENSURE( pSecondRest->InFldGrp(), "Fieldrest expected");
+ SwFldPortion *pFld = ((SwFldPortion*)pSecondRest)->Clone(
+ ((SwFldPortion*)pSecondRest)->GetExp() );
+ pFld->SetFollow( sal_True );
+ aTmp.SetRest( pFld );
+ }
+ if( !rMulti.OnTop() && nFirstLen < nMultiLen )
+ bRet = sal_True;
+ }
+ else
+ aTmp.SetRest( aInf.GetRest() );
+ aInf.SetRest( NULL );
+
+ // in grid mode we temporarily have to disable the grid for the ruby line
+ if ( bHasGrid && aTmp.IsRuby() && ! bRubyTop )
+ aTmp.SetSnapToGrid( sal_False );
+
+ BuildPortions( aTmp );
+
+ aTmp.SetSnapToGrid( bOldGridModeAllowed );
+
+ rMulti.CalcSize( *this, aInf );
+ rMulti.GetRoot().SetRealHeight( rMulti.GetRoot().Height() );
+ pCurr->SetRealHeight( pCurr->Height() );
+ if( rMulti.IsRuby() )
+ {
+ pNextSecond = aTmp.GetRest();
+ if( pNextFirst )
+ bRet = sal_True;
+ }
+ else
+ pNextFirst = aTmp.GetRest();
+ if( ( !aTmp.IsRuby() && nFirstLen + pCurr->GetLen() < nMultiLen )
+ || aTmp.GetRest() )
+ // our guess for width of multiportion was too small,
+ // text did not fit into multiportion
+ bRet = sal_True;
+ }
+ if( rMulti.IsRuby() )
+ break;
+ if( bRet )
+ {
+ // our guess for multiportion width was too small,
+ // we set min to act
+ nMinWidth = nActWidth;
+ nActWidth = ( 3 * nMaxWidth + nMinWidth + 3 ) / 4;
+ if ( nActWidth == nMaxWidth && rInf.GetLineStart() == rInf.GetIdx() )
+ // we have too less space, we must allow break cuts
+ // ( the first multi flag is considered during TxtPortion::_Format() )
+ bFirstMulti = sal_False;
+ if( nActWidth <= nMinWidth )
+ break;
+ }
+ else
+ {
+ // For Solaris, this optimisation can causes trouble:
+ // Setting this to the portion width ( = rMulti.Width() )
+ // can make GetTextBreak inside SwTxtGuess::Guess return to small
+ // values. Therefore we add some extra twips.
+ if( nActWidth > nTmpX + rMulti.Width() + 6 )
+ nActWidth = nTmpX + rMulti.Width() + 6;
+ nMaxWidth = nActWidth;
+ nActWidth = ( 3 * nMaxWidth + nMinWidth + 3 ) / 4;
+ if( nActWidth >= nMaxWidth )
+ break;
+ // we do not allow break cuts during formatting
+ bFirstMulti = sal_True;
+ }
+ delete pNextFirst;
+ pNextFirst = NULL;
+ } while ( sal_True );
+
+ pMulti = pOldMulti;
+
+ pCurr = pOldCurr;
+ nStart = nOldStart;
+ SetPropFont( 0 );
+
+ rMulti.SetLen( rMulti.GetRoot().GetLen() + ( rMulti.GetRoot().GetNext() ?
+ rMulti.GetRoot().GetNext()->GetLen() : 0 ) );
+
+ if( rMulti.IsDouble() )
+ {
+ ((SwDoubleLinePortion&)rMulti).CalcBlanks( rInf );
+ if( ((SwDoubleLinePortion&)rMulti).GetLineDiff() )
+ {
+ SwLineLayout* pLine = &rMulti.GetRoot();
+ if( ((SwDoubleLinePortion&)rMulti).GetLineDiff() > 0 )
+ {
+ rInf.SetIdx( nStartIdx + pLine->GetLen() );
+ pLine = pLine->GetNext();
+ }
+ if( pLine )
+ {
+ GetInfo().SetMulti( sal_True );
+ CalcNewBlock( pLine, NULL, rMulti.Width() );
+ GetInfo().SetMulti( sal_False );
+ }
+ rInf.SetIdx( nStartIdx );
+ }
+ if( ((SwDoubleLinePortion&)rMulti).GetBrackets() )
+ {
+ rMulti.Width( rMulti.Width() +
+ ((SwDoubleLinePortion&)rMulti).BracketWidth() );
+ GetInfo().X( nOldX );
+ }
+ }
+ else
+ {
+ rMulti.ActualizeTabulator();
+ if( rMulti.IsRuby() )
+ {
+ ((SwRubyPortion&)rMulti).Adjust( rInf );
+ ((SwRubyPortion&)rMulti).CalcRubyOffset();
+ }
+ }
+ if( rMulti.HasRotation() )
+ {
+ SwTwips nH = rMulti.Width();
+ SwTwips nAsc = rMulti.GetAscent() + ( nH - rMulti.Height() )/2;
+ if( nAsc > nH )
+ nAsc = nH;
+ else if( nAsc < 0 )
+ nAsc = 0;
+ rMulti.Width( rMulti.Height() );
+ rMulti.Height( KSHORT(nH) );
+ rMulti.SetAscent( KSHORT(nAsc) );
+ bRet = ( rInf.GetPos().X() + rMulti.Width() > rInf.Width() ) &&
+ nStartIdx != rInf.GetLineStart();
+ }
+ else if ( rMulti.IsBidi() )
+ {
+ bRet = rMulti.GetLen() < nMultiLen || pNextFirst;
+ }
+
+ // line break has to be performed!
+ if( bRet )
+ {
+ OSL_ENSURE( !pNextFirst || pNextFirst->InFldGrp(),
+ "BuildMultiPortion: Surprising restportion, field expected" );
+ SwMultiPortion *pTmp;
+ if( rMulti.IsDouble() )
+ pTmp = new SwDoubleLinePortion( ((SwDoubleLinePortion&)rMulti),
+ nMultiLen + rInf.GetIdx() );
+ else if( rMulti.IsRuby() )
+ {
+ OSL_ENSURE( !pNextSecond || pNextSecond->InFldGrp(),
+ "BuildMultiPortion: Surprising restportion, field expected" );
+
+ if ( rInf.GetIdx() == rInf.GetLineStart() )
+ {
+ // the ruby portion has to be split in two portions
+ pTmp = new SwRubyPortion( ((SwRubyPortion&)rMulti),
+ nMultiLen + rInf.GetIdx() );
+
+ if( pNextSecond )
+ {
+ pTmp->GetRoot().SetNext( new SwLineLayout() );
+ pTmp->GetRoot().GetNext()->SetPortion( pNextSecond );
+ }
+ pTmp->SetFollowFld();
+ }
+ else
+ {
+ // we try to keep our ruby portion together
+ lcl_TruncateMultiPortion( rMulti, rInf, nStartIdx );
+ pTmp = 0;
+ }
+ }
+ else if( rMulti.HasRotation() )
+ {
+ // we try to keep our rotated portion together
+ lcl_TruncateMultiPortion( rMulti, rInf, nStartIdx );
+ pTmp = new SwRotatedPortion( nMultiLen + rInf.GetIdx(),
+ rMulti.GetDirection() );
+ }
+ // during a recursion of BuildMultiPortions we may not build
+ // a new SwBidiPortion, this would cause a memory leak
+ else if( rMulti.IsBidi() && ! pMulti )
+ {
+ if ( ! rMulti.GetLen() )
+ lcl_TruncateMultiPortion( rMulti, rInf, nStartIdx );
+
+ // If there is a HolePortion at the end of the bidi portion,
+ // it has to be moved behind the bidi portion. Otherwise
+ // the visual cursor travelling gets into trouble.
+ SwLineLayout& aRoot = rMulti.GetRoot();
+ SwLinePortion* pPor = aRoot.GetFirstPortion();
+ while ( pPor )
+ {
+ if ( pPor->GetPortion() && pPor->GetPortion()->IsHolePortion() )
+ {
+ SwLinePortion* pHolePor = pPor->GetPortion();
+ pPor->SetPortion( NULL );
+ aRoot.SetLen( aRoot.GetLen() - pHolePor->GetLen() );
+ rMulti.SetLen( rMulti.GetLen() - pHolePor->GetLen() );
+ rMulti.SetPortion( pHolePor );
+ break;
+ }
+ pPor = pPor->GetPortion();
+ }
+
+ pTmp = new SwBidiPortion( nMultiLen + rInf.GetIdx(),
+ ((SwBidiPortion&)rMulti).GetLevel() );
+ }
+ else
+ pTmp = NULL;
+
+ if ( ! rMulti.GetLen() && rInf.GetLast() )
+ {
+ SeekAndChgBefore( rInf );
+ rInf.GetLast()->FormatEOL( rInf );
+ }
+
+ if( pNextFirst && pTmp )
+ {
+ pTmp->SetFollowFld();
+ pTmp->GetRoot().SetPortion( pNextFirst );
+ }
+ else
+ // A follow field portion is still waiting. If nobody wants it,
+ // we delete it.
+ delete pNextFirst;
+
+ rInf.SetRest( pTmp );
+ }
+
+ rInf.SetTxt( *pOldTxt );
+ rInf.SetPaintOfst( nOldPaintOfst );
+ rInf.SetStop( aInf.IsStop() );
+ rInf.SetNumDone( sal_True );
+ rInf.SetFtnDone( sal_True );
+ SeekAndChg( rInf );
+ delete pFirstRest;
+ delete pSecondRest;
+ delete pFontSave;
+ return bRet;
+}
+
+/*--------------------------------------------------
+ * SwTxtFormatter::MakeRestPortion(..)
+ * When a fieldportion at the end of line breaks and needs a following
+ * fieldportion in the next line, then the "restportion" of the formatinfo
+ * has to be set. Normally this happens during the formatting of the first
+ * part of the fieldportion.
+ * But sometimes the formatting starts at the line with the following part,
+ * exspecally when the following part is on the next page.
+ * In this case the MakeRestPortion-function has to create the following part.
+ * The first parameter is the line that contains possibly a first part
+ * of a field. When the function finds such field part, it creates the right
+ * restportion. This may be a multiportion, e.g. if the field is surrounded by
+ * a doubleline- or ruby-portion.
+ * The second parameter is the start index of the line.
+ * --------------------------------------------------*/
+
+SwLinePortion* SwTxtFormatter::MakeRestPortion( const SwLineLayout* pLine,
+ xub_StrLen nPosition )
+{
+ if( !nPosition )
+ return NULL;
+ xub_StrLen nMultiPos = nPosition - pLine->GetLen();
+ const SwMultiPortion *pTmpMulti = NULL;
+ const SwMultiPortion *pHelpMulti = NULL;
+ const SwLinePortion* pPor = pLine->GetFirstPortion();
+ SwFldPortion *pFld = NULL;
+ while( pPor )
+ {
+ if( pPor->GetLen() )
+ {
+ if( !pHelpMulti )
+ {
+ nMultiPos = nMultiPos + pPor->GetLen();
+ pTmpMulti = NULL;
+ }
+ }
+ if( pPor->InFldGrp() )
+ {
+ if( !pHelpMulti )
+ pTmpMulti = NULL;
+ pFld = (SwFldPortion*)pPor;
+ }
+ else if( pPor->IsMultiPortion() )
+ {
+ OSL_ENSURE( !pHelpMulti || pHelpMulti->IsBidi(),
+ "Nested multiportions are forbidden." );
+
+ pFld = NULL;
+ pTmpMulti = (SwMultiPortion*)pPor;
+ }
+ pPor = pPor->GetPortion();
+ // If the last portion is a multi-portion, we enter it
+ // and look for a field portion inside.
+ // If we are already in a multiportion, we could change to the
+ // next line
+ if( !pPor && pTmpMulti )
+ {
+ if( pHelpMulti )
+ { // We're already inside the multiportion, let's take the second
+ // line, if we are in a double line portion
+ if( !pHelpMulti->IsRuby() )
+ pPor = pHelpMulti->GetRoot().GetNext();
+ pTmpMulti = NULL;
+ }
+ else
+ { // Now we enter a multiportion, in a ruby portion we take the
+ // main line, not the phonetic line, in a doublelineportion we
+ // starts with the first line.
+ pHelpMulti = pTmpMulti;
+ nMultiPos = nMultiPos - pHelpMulti->GetLen();
+ if( pHelpMulti->IsRuby() && pHelpMulti->OnTop() )
+ pPor = pHelpMulti->GetRoot().GetNext();
+ else
+ pPor = pHelpMulti->GetRoot().GetFirstPortion();
+ }
+ }
+ }
+ if( pFld && !pFld->HasFollow() )
+ pFld = NULL;
+
+ SwLinePortion *pRest = NULL;
+ if( pFld )
+ {
+ const SwTxtAttr *pHint = GetAttr( nPosition - 1 );
+ if( pHint && pHint->Which() == RES_TXTATR_FIELD )
+ {
+ pRest = NewFldPortion( GetInfo(), pHint );
+ if( pRest->InFldGrp() )
+ ((SwFldPortion*)pRest)->TakeNextOffset( pFld );
+ else
+ {
+ delete pRest;
+ pRest = NULL;
+ }
+ }
+ }
+ if( !pHelpMulti )
+ return pRest;
+
+ nPosition = nMultiPos + pHelpMulti->GetLen();
+ SwMultiCreator* pCreate = GetInfo().GetMultiCreator( nMultiPos, 0 );
+
+ if ( !pCreate )
+ {
+ OSL_ENSURE( !pHelpMulti->GetLen(), "Multiportion without attribut?" );
+ if ( nMultiPos )
+ --nMultiPos;
+ pCreate = GetInfo().GetMultiCreator( --nMultiPos, 0 );
+ }
+
+ if (!pCreate)
+ return pRest;
+
+ if( pRest || nMultiPos > nPosition || ( pHelpMulti->IsRuby() &&
+ ((SwRubyPortion*)pHelpMulti)->GetRubyOffset() < STRING_LEN ) )
+ {
+ SwMultiPortion* pTmp;
+ if( pHelpMulti->IsDouble() )
+ pTmp = new SwDoubleLinePortion( *pCreate, nMultiPos );
+ else if( pHelpMulti->IsBidi() )
+ pTmp = new SwBidiPortion( nMultiPos, pCreate->nLevel );
+ else if( pHelpMulti->IsRuby() )
+ {
+ sal_Bool bRubyTop;
+ sal_Bool* pRubyPos = 0;
+
+ if ( GetInfo().SnapToGrid() )
+ {
+ GETGRID( pFrm->FindPageFrm() )
+ if ( pGrid )
+ {
+ bRubyTop = ! pGrid->GetRubyTextBelow();
+ pRubyPos = &bRubyTop;
+ }
+ }
+
+ pTmp = new SwRubyPortion( *pCreate, *GetInfo().GetFont(),
+ *pFrm->GetTxtNode()->getIDocumentSettingAccess(),
+ nMultiPos, ((SwRubyPortion*)pHelpMulti)->GetRubyOffset(),
+ pRubyPos );
+ }
+ else if( pHelpMulti->HasRotation() )
+ pTmp = new SwRotatedPortion( nMultiPos, pHelpMulti->GetDirection() );
+ else
+ {
+ delete pCreate;
+ return pRest;
+ }
+ delete pCreate;
+ pTmp->SetFollowFld();
+ if( pRest )
+ {
+ SwLineLayout *pLay = &pTmp->GetRoot();
+ if( pTmp->IsRuby() && pTmp->OnTop() )
+ {
+ pLay->SetNext( new SwLineLayout() );
+ pLay = pLay->GetNext();
+ }
+ pLay->SetPortion( pRest );
+ }
+ return pTmp;
+ }
+ return pRest;
+}
+
+
+
+/*--------------------------------------------------
+ * SwTxtCursorSave notes the start and current line of a SwTxtCursor,
+ * sets them to the values for GetCrsrOfst inside a multiportion
+ * and restores them in the destructor.
+ * --------------------------------------------------*/
+
+SwTxtCursorSave::SwTxtCursorSave( SwTxtCursor* pTxtCursor,
+ SwMultiPortion* pMulti,
+ SwTwips nY,
+ sal_uInt16& nX,
+ xub_StrLen nCurrStart,
+ long nSpaceAdd )
+{
+ pTxtCrsr = pTxtCursor;
+ nStart = pTxtCursor->nStart;
+ pTxtCursor->nStart = nCurrStart;
+ pCurr = pTxtCursor->pCurr;
+ pTxtCursor->pCurr = &pMulti->GetRoot();
+ while( pTxtCursor->Y() + pTxtCursor->GetLineHeight() < nY &&
+ pTxtCursor->Next() )
+ ; // nothing
+ nWidth = pTxtCursor->pCurr->Width();
+ nOldProp = pTxtCursor->GetPropFont();
+
+ if ( pMulti->IsDouble() || pMulti->IsBidi() )
+ {
+ bSpaceChg = pMulti->ChgSpaceAdd( pTxtCursor->pCurr, nSpaceAdd );
+
+ sal_uInt16 nSpaceCnt;
+ if ( pMulti->IsDouble() )
+ {
+ pTxtCursor->SetPropFont( 50 );
+ nSpaceCnt = ((SwDoubleLinePortion*)pMulti)->GetSpaceCnt();
+ }
+ else
+ {
+ const xub_StrLen nOldIdx = pTxtCursor->GetInfo().GetIdx();
+ pTxtCursor->GetInfo().SetIdx ( nCurrStart );
+ nSpaceCnt = ((SwBidiPortion*)pMulti)->GetSpaceCnt(pTxtCursor->GetInfo());
+ pTxtCursor->GetInfo().SetIdx ( nOldIdx );
+ }
+
+ if( nSpaceAdd > 0 && !pMulti->HasTabulator() )
+ pTxtCursor->pCurr->Width( static_cast<sal_uInt16>(nWidth + nSpaceAdd * nSpaceCnt / SPACING_PRECISION_FACTOR ) );
+
+ // For a BidiPortion we have to calculate the offset from the
+ // end of the portion
+ if ( nX && pMulti->IsBidi() )
+ nX = pTxtCursor->pCurr->Width() - nX;
+ }
+ else
+ bSpaceChg = sal_False;
+}
+
+SwTxtCursorSave::~SwTxtCursorSave()
+{
+ if( bSpaceChg )
+ SwDoubleLinePortion::ResetSpaceAdd( pTxtCrsr->pCurr );
+ pTxtCrsr->pCurr->Width( KSHORT(nWidth) );
+ pTxtCrsr->pCurr = pCurr;
+ pTxtCrsr->nStart = nStart;
+ pTxtCrsr->SetPropFont( nOldProp );
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/text/pormulti.hxx b/sw/source/core/text/pormulti.hxx
new file mode 100644
index 000000000000..4facac70a342
--- /dev/null
+++ b/sw/source/core/text/pormulti.hxx
@@ -0,0 +1,271 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+#ifndef _PORMULTI_HXX
+#define _PORMULTI_HXX
+
+#include "porlay.hxx"
+#include "porexp.hxx"
+
+class SwTxtFormatInfo;
+class SwFldPortion;
+class SwTxtCursor;
+class SwLineLayout;
+class SwTxtPaintInfo;
+class SwTxtAttr;
+class SfxPoolItem;
+class SwFont;
+
+/*--------------------------------------------------
+ * SwMultiCreator is a small structur to create a multiportion.
+ * It contains the kind of multiportion and a textattribute
+ * or a poolitem.
+ * The GetMultiCreator-function fills this structur and
+ * the Ctor of the SwMultiPortion uses it.
+ * --------------------------------------------------*/
+
+#define SW_MC_DOUBLE 0
+#define SW_MC_RUBY 1
+#define SW_MC_ROTATE 2
+#define SW_MC_BIDI 3
+
+struct SwMultiCreator
+{
+ const SwTxtAttr* pAttr;
+ const SfxPoolItem* pItem;
+ sal_uInt8 nId;
+ sal_uInt8 nLevel;
+};
+
+/*--------------------------------------------------
+ * A two-line-portion (SwMultiPortion) could have surrounding brackets,
+ * in this case the structur SwBracket will be used.
+ * --------------------------------------------------*/
+
+struct SwBracket
+{
+ xub_StrLen nStart; // Start of text attribute determins the font
+ KSHORT nAscent; // Ascent of the brackets
+ KSHORT nHeight; // Height of them
+ KSHORT nPreWidth; // Width of the opening bracket
+ KSHORT nPostWidth; // Width of the closing bracket
+ sal_Unicode cPre; // Initial character, e.g. '('
+ sal_Unicode cPost; // Final character, e.g. ')'
+ sal_uInt8 nPreScript; // Script of the initial character
+ sal_uInt8 nPostScript; // Script of the final character
+};
+
+/*--------------------------------------------------
+ * The SwMultiPortion is line portion inside a line portion,
+ * it's a group of portions,
+ * e.g. a double line portion in a line
+ * or phonetics (ruby)
+ * or combined characters
+ * or a rotated portion.
+ * --------------------------------------------------*/
+
+class SwMultiPortion : public SwLinePortion
+{
+ SwLineLayout aRoot; // One or more lines
+ SwFldPortion *pFldRest; // Field rest from the previous line
+ sal_Bool bTab1 :1; // First line tabulator
+ sal_Bool bTab2 :1; // Second line includes tabulator
+ sal_Bool bDouble :1; // Double line
+ sal_Bool bRuby :1; // Phonetics
+ sal_Bool bBidi :1;
+ sal_Bool bTop :1; // Phonetic position
+ sal_Bool bFormatted :1; // Already formatted
+ sal_Bool bFollowFld :1; // Field follow inside
+ sal_uInt8 nDirection:2; // Direction (0/90/180/270 degrees)
+ sal_Bool bFlyInCntnt:1; // Fly as character inside
+protected:
+ SwMultiPortion( xub_StrLen nEnd ) : pFldRest( 0 ), bTab1( sal_False ),
+ bTab2( sal_False ), bDouble( sal_False ), bRuby( sal_False ),
+ bBidi( sal_False ), bFormatted( sal_False ), bFollowFld( sal_False ),
+ nDirection( 0 ), bFlyInCntnt( sal_False )
+ { SetWhichPor( POR_MULTI ); SetLen( nEnd ); }
+ inline void SetDouble() { bDouble = sal_True; }
+ inline void SetRuby() { bRuby = sal_True; }
+ inline void SetBidi() { bBidi = sal_True; }
+ inline void SetTop( sal_Bool bNew ) { bTop = bNew; }
+ inline void SetTab1( sal_Bool bNew ) { bTab1 = bNew; }
+ inline void SetTab2( sal_Bool bNew ) { bTab2 = bNew; }
+ inline void SetDirection( sal_uInt8 nNew ) { nDirection = nNew; }
+ inline sal_Bool GetTab1() const { return bTab1; }
+ inline sal_Bool GetTab2() const { return bTab2; }
+public:
+ ~SwMultiPortion();
+ const SwLineLayout& GetRoot() const { return aRoot; }
+ SwLineLayout& GetRoot() { return aRoot; }
+ SwFldPortion* GetFldRest() { return pFldRest; }
+ void SetFldRest( SwFldPortion* pNew ) { pFldRest = pNew; }
+
+ inline sal_Bool HasTabulator() const { return bTab1 || bTab2; }
+ inline sal_Bool IsFormatted() const { return bFormatted; }
+ inline void SetFormatted() { bFormatted = sal_True; }
+ inline sal_Bool IsFollowFld() const { return bFollowFld; }
+ inline void SetFollowFld() { bFollowFld = sal_True; }
+ inline sal_Bool HasFlyInCntnt() const { return bFlyInCntnt; }
+ inline void SetFlyInCntnt( sal_Bool bNew ) { bFlyInCntnt = bNew; }
+ inline sal_Bool IsDouble() const { return bDouble; }
+ inline sal_Bool IsRuby() const { return bRuby; }
+ inline sal_Bool IsBidi() const { return bBidi; }
+ inline sal_Bool OnTop() const { return bTop; }
+ void ActualizeTabulator();
+
+ virtual void Paint( const SwTxtPaintInfo &rInf ) const;
+ virtual long CalcSpacing( long nSpaceAdd, const SwTxtSizeInfo &rInf ) const;
+ virtual sal_Bool ChgSpaceAdd( SwLineLayout* pCurr, long nSpaceAdd ) const;
+
+ // Summarize the internal lines to calculate the (external) size
+ void CalcSize( SwTxtFormatter& rLine, SwTxtFormatInfo &rInf );
+
+ inline sal_Bool HasBrackets() const;
+ inline sal_Bool HasRotation() const { return 0 != (1 & nDirection); }
+ inline sal_Bool IsRevers() const { return 0 != (2 & nDirection); }
+ inline sal_uInt8 GetDirection() const { return nDirection; }
+ inline sal_uInt16 GetFontRotation() const
+ { return ( HasRotation() ? ( IsRevers() ? 2700 : 900 ) : 0 ); }
+
+ // Accessibility: pass information about this portion to the PortionHandler
+ virtual void HandlePortion( SwPortionHandler& rPH ) const;
+
+ OUTPUT_OPERATOR
+};
+
+class SwDoubleLinePortion : public SwMultiPortion
+{
+ SwBracket* pBracket; // Surrounding brackets
+ SwTwips nLineDiff; // Difference of the width of the both lines
+ xub_StrLen nBlank1; // Number of blanks in the first line
+ xub_StrLen nBlank2; // Number of blanks in the second line
+public:
+ SwDoubleLinePortion( SwDoubleLinePortion& rDouble, xub_StrLen nEnd );
+ SwDoubleLinePortion( const SwMultiCreator& rCreate, xub_StrLen nEnd );
+ ~SwDoubleLinePortion();
+
+ inline SwBracket* GetBrackets() const { return pBracket; }
+ void SetBrackets( const SwDoubleLinePortion& rDouble );
+ void PaintBracket( SwTxtPaintInfo& rInf, long nSpaceAdd, sal_Bool bOpen ) const;
+ void FormatBrackets( SwTxtFormatInfo &rInf, SwTwips& nMaxWidth );
+ inline KSHORT PreWidth() const { return pBracket->nPreWidth; };
+ inline KSHORT PostWidth() const { return pBracket->nPostWidth; }
+ inline void ClearBrackets()
+ { pBracket->nPreWidth = pBracket->nPostWidth=0; Width( 0 ); }
+ inline KSHORT BracketWidth(){ return PreWidth() + PostWidth(); }
+
+ void CalcBlanks( SwTxtFormatInfo &rInf );
+ static void ResetSpaceAdd( SwLineLayout* pCurr );
+ inline SwTwips GetLineDiff() const { return nLineDiff; }
+ inline xub_StrLen GetSpaceCnt() const
+ { return ( nLineDiff < 0 ) ? nBlank2 : nBlank1; }
+ inline xub_StrLen GetSmallerSpaceCnt() const
+ { return ( nLineDiff < 0 ) ? nBlank1 : nBlank2; }
+ inline xub_StrLen GetBlank1() const { return nBlank1; }
+ inline xub_StrLen GetBlank2() const { return nBlank2; }
+
+ virtual long CalcSpacing( long nSpaceAdd, const SwTxtSizeInfo &rInf ) const;
+ virtual sal_Bool ChgSpaceAdd( SwLineLayout* pCurr, long nSpaceAdd ) const;
+};
+
+class SwRubyPortion : public SwMultiPortion
+{
+ xub_StrLen nRubyOffset;
+ sal_uInt16 nAdjustment;
+ void _Adjust( SwTxtFormatInfo &rInf);
+public:
+ SwRubyPortion( const SwRubyPortion& rRuby, xub_StrLen nEnd );
+
+ SwRubyPortion( const SwMultiCreator& rCreate, const SwFont& rFnt,
+ const IDocumentSettingAccess& rIDocumentSettingAccess,
+ xub_StrLen nEnd, xub_StrLen nOffs,
+ const sal_Bool* pForceRubyPos );
+
+ void CalcRubyOffset();
+ inline void Adjust( SwTxtFormatInfo &rInf )
+ { if(nAdjustment && GetRoot().GetNext()) _Adjust(rInf); }
+ inline sal_uInt16 GetAdjustment() const { return nAdjustment; }
+ inline xub_StrLen GetRubyOffset() const { return nRubyOffset; }
+};
+
+class SwRotatedPortion : public SwMultiPortion
+{
+public:
+ SwRotatedPortion( xub_StrLen nEnd, sal_uInt8 nDir = 1 )
+ : SwMultiPortion( nEnd ) { SetDirection( nDir ); }
+ SwRotatedPortion( const SwMultiCreator& rCreate, xub_StrLen nEnd,
+ sal_Bool bRTL );
+};
+
+class SwBidiPortion : public SwMultiPortion
+{
+ sal_uInt8 nLevel;
+
+public:
+ SwBidiPortion( xub_StrLen nEnd, sal_uInt8 nLv );
+
+ inline sal_uInt8 GetLevel() const { return nLevel; }
+ // Get number of blanks for justified alignment
+ xub_StrLen GetSpaceCnt( const SwTxtSizeInfo &rInf ) const;
+ // Calculates extra spacing based on number of blanks
+ virtual long CalcSpacing( long nSpaceAdd, const SwTxtSizeInfo &rInf ) const;
+ // Manipulate the spacing array at pCurr
+ virtual sal_Bool ChgSpaceAdd( SwLineLayout* pCurr, long nSpaceAdd ) const;
+};
+
+// For cursor travelling in multiportions
+
+class SwTxtCursorSave
+{
+ SwTxtCursor* pTxtCrsr;
+ SwLineLayout* pCurr;
+ SwTwips nWidth;
+ xub_StrLen nStart;
+ sal_uInt8 nOldProp;
+ sal_Bool bSpaceChg;
+public:
+ SwTxtCursorSave( SwTxtCursor* pTxtCursor, SwMultiPortion* pMulti,
+ SwTwips nY, sal_uInt16& nX, xub_StrLen nCurrStart, long nSpaceAdd );
+ ~SwTxtCursorSave();
+};
+
+/*************************************************************************
+ * inline - Implementations
+ *************************************************************************/
+
+inline sal_Bool SwMultiPortion::HasBrackets() const
+{
+ return sal::static_int_cast< sal_Bool >( IsDouble() ?
+ 0 != ((SwDoubleLinePortion*)this)->GetBrackets() :
+ sal_False );
+}
+
+CLASSIO( SwMultiPortion )
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/text/porref.cxx b/sw/source/core/text/porref.cxx
new file mode 100644
index 000000000000..6b28b0a445d6
--- /dev/null
+++ b/sw/source/core/text/porref.cxx
@@ -0,0 +1,116 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+
+#include <SwPortionHandler.hxx>
+#include "viewopt.hxx" // SwViewOptions
+
+#include "porref.hxx"
+#include "inftxt.hxx" // GetTxtSize()
+
+/*************************************************************************
+ * virtual SwRefPortion::Paint()
+ *************************************************************************/
+
+void SwRefPortion::Paint( const SwTxtPaintInfo &rInf ) const
+{
+ if( Width() )
+ {
+ rInf.DrawViewOpt( *this, POR_REF );
+ SwTxtPortion::Paint( rInf );
+ }
+}
+
+/*************************************************************************
+ * class SwIsoRefPortion
+ *************************************************************************/
+
+SwLinePortion *SwIsoRefPortion::Compress() { return this; }
+
+SwIsoRefPortion::SwIsoRefPortion() : nViewWidth(0)
+{
+ SetLen(1);
+ SetWhichPor( POR_ISOREF );
+}
+
+/*************************************************************************
+ * virtual SwIsoRefPortion::GetViewWidth()
+ *************************************************************************/
+
+KSHORT SwIsoRefPortion::GetViewWidth( const SwTxtSizeInfo &rInf ) const
+{
+ // Wir stehen zwar im const, aber nViewWidth sollte erst im letzten
+ // Moment errechnet werden:
+ SwIsoRefPortion* pThis = (SwIsoRefPortion*)this;
+ if( !Width() && rInf.OnWin() && SwViewOption::IsFieldShadings() &&
+ !rInf.GetOpt().IsReadonly() && !rInf.GetOpt().IsPagePreview() )
+ {
+ if( !nViewWidth )
+ pThis->nViewWidth = rInf.GetTxtSize( ' ' ).Width();
+ }
+ else
+ pThis->nViewWidth = 0;
+ return nViewWidth;
+}
+
+/*************************************************************************
+ * virtual SwIsoRefPortion::Format()
+ *************************************************************************/
+
+sal_Bool SwIsoRefPortion::Format( SwTxtFormatInfo &rInf )
+{
+ const sal_Bool bFull = SwLinePortion::Format( rInf );
+ return bFull;
+}
+
+/*************************************************************************
+ * virtual SwIsoRefPortion::Paint()
+ *************************************************************************/
+
+void SwIsoRefPortion::Paint( const SwTxtPaintInfo &rInf ) const
+{
+ if( Width() )
+ rInf.DrawViewOpt( *this, POR_REF );
+}
+
+/*************************************************************************
+ * virtual SwIsoRefPortion::HandlePortion()
+ *************************************************************************/
+
+void SwIsoRefPortion::HandlePortion( SwPortionHandler& rPH ) const
+{
+ String aString;
+ rPH.Special( GetLen(), aString, GetWhichPor() );
+}
+
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/text/porref.hxx b/sw/source/core/text/porref.hxx
new file mode 100644
index 000000000000..67c64dad83d0
--- /dev/null
+++ b/sw/source/core/text/porref.hxx
@@ -0,0 +1,76 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+#ifndef _PORREF_HXX
+#define _PORREF_HXX
+
+#include "portxt.hxx"
+
+/*************************************************************************
+ * class SwRefPortion
+ *************************************************************************/
+
+class SwRefPortion : public SwTxtPortion
+{
+public:
+ inline SwRefPortion(){ SetWhichPor( POR_REF ); }
+ virtual void Paint( const SwTxtPaintInfo &rInf ) const;
+ OUTPUT_OPERATOR
+};
+
+/*************************************************************************
+ * class SwIsoRefPortion
+ *************************************************************************/
+
+class SwIsoRefPortion : public SwRefPortion
+{
+ KSHORT nViewWidth;
+
+public:
+ SwIsoRefPortion();
+ virtual sal_Bool Format( SwTxtFormatInfo &rInf );
+ virtual void Paint( const SwTxtPaintInfo &rInf ) const;
+ virtual SwLinePortion *Compress();
+ virtual KSHORT GetViewWidth( const SwTxtSizeInfo &rInf ) const;
+
+ // Accessibility: pass information about this portion to the PortionHandler
+ virtual void HandlePortion( SwPortionHandler& rPH ) const;
+
+ OUTPUT_OPERATOR
+};
+
+/*************************************************************************
+ * inline - Implementations
+ *************************************************************************/
+
+CLASSIO( SwRefPortion )
+CLASSIO( SwIsoRefPortion )
+
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/text/porrst.cxx b/sw/source/core/text/porrst.cxx
new file mode 100644
index 000000000000..62b158295004
--- /dev/null
+++ b/sw/source/core/text/porrst.cxx
@@ -0,0 +1,598 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+#include <hintids.hxx>
+#include <sfx2/printer.hxx>
+#include <editeng/lspcitem.hxx>
+#include <editeng/adjitem.hxx>
+#include <editeng/escpitem.hxx>
+#include <editeng/lrspitem.hxx>
+#include <editeng/pgrditem.hxx>
+#include <vcl/window.hxx>
+#include <vcl/svapp.hxx>
+#include <viewsh.hxx> // ViewShell
+#include <viewopt.hxx>
+#include <ndtxt.hxx> // SwTxtNode
+#include <pagefrm.hxx> // SwPageFrm
+#include <paratr.hxx>
+#include <SwPortionHandler.hxx>
+#include <porrst.hxx>
+#include <inftxt.hxx>
+#include <txtpaint.hxx> // ClipVout
+#include <swfntcch.hxx> // SwFontAccess
+#include <tgrditem.hxx>
+#include <pagedesc.hxx> // SwPageDesc
+#include <frmatr.hxx>
+#include <redlnitr.hxx> // SwRedlineItr
+#include <porfly.hxx> // SwFlyPortion
+#include <atrhndl.hxx>
+#include "rootfrm.hxx"
+
+#include <IDocumentRedlineAccess.hxx>
+#include <IDocumentSettingAccess.hxx>
+#include <IDocumentDeviceAccess.hxx>
+
+#include <crsrsh.hxx>
+
+/*************************************************************************
+ * class SwTmpEndPortion
+ *************************************************************************/
+
+SwTmpEndPortion::SwTmpEndPortion( const SwLinePortion &rPortion )
+{
+ Height( rPortion.Height() );
+ SetAscent( rPortion.GetAscent() );
+ SetWhichPor( POR_TMPEND );
+}
+
+/*************************************************************************
+ * virtual SwTmpEndPortion::Paint()
+ *************************************************************************/
+
+void SwTmpEndPortion::Paint( const SwTxtPaintInfo &rInf ) const
+{
+ if( rInf.OnWin() && rInf.GetOpt().IsParagraph() )
+ {
+ SwDefFontSave aSave( rInf );
+ const XubString aTmp( CH_PAR );
+ rInf.DrawText( aTmp, *this );
+ }
+}
+
+/*************************************************************************
+ * class SwBreakPortion
+ *************************************************************************/
+SwBreakPortion::SwBreakPortion( const SwLinePortion &rPortion )
+ : SwLinePortion( rPortion )
+{
+ nLineLength = 1;
+ SetWhichPor( POR_BRK );
+}
+
+xub_StrLen SwBreakPortion::GetCrsrOfst( const KSHORT ) const
+{ return 0; }
+
+KSHORT SwBreakPortion::GetViewWidth( const SwTxtSizeInfo & ) const
+{ return 0; }
+
+SwLinePortion *SwBreakPortion::Compress()
+{ return (GetPortion() && GetPortion()->InTxtGrp() ? 0 : this); }
+
+void SwBreakPortion::Paint( const SwTxtPaintInfo &rInf ) const
+{
+ if( rInf.OnWin() && rInf.GetOpt().IsLineBreak() )
+ rInf.DrawLineBreak( *this );
+}
+
+/*************************************************************************
+ * virtual SwBreakPortion::Format()
+ *************************************************************************/
+
+sal_Bool SwBreakPortion::Format( SwTxtFormatInfo &rInf )
+{
+ const SwLinePortion *pRoot = rInf.GetRoot();
+ Width( 0 );
+ Height( pRoot->Height() );
+ SetAscent( pRoot->GetAscent() );
+ if ( rInf.GetIdx()+1 == rInf.GetTxt().Len() )
+ rInf.SetNewLine( sal_True );
+ return sal_True;
+}
+
+/*************************************************************************
+ * virtual SwBreakPortion::HandlePortion()
+ *************************************************************************/
+
+void SwBreakPortion::HandlePortion( SwPortionHandler& rPH ) const
+{
+ rPH.Text( GetLen(), GetWhichPor() );
+}
+
+
+SwKernPortion::SwKernPortion( SwLinePortion &rPortion, short nKrn,
+ sal_Bool bBG, sal_Bool bGK ) :
+ nKern( nKrn ), bBackground( bBG ), bGridKern( bGK )
+{
+ Height( rPortion.Height() );
+ SetAscent( rPortion.GetAscent() );
+ nLineLength = 0;
+ SetWhichPor( POR_KERN );
+ if( nKern > 0 )
+ Width( nKern );
+ rPortion.Insert( this );
+}
+
+SwKernPortion::SwKernPortion( const SwLinePortion& rPortion ) :
+ nKern( 0 ), bBackground( sal_False ), bGridKern( sal_True )
+{
+ Height( rPortion.Height() );
+ SetAscent( rPortion.GetAscent() );
+
+ nLineLength = 0;
+ SetWhichPor( POR_KERN );
+}
+
+void SwKernPortion::Paint( const SwTxtPaintInfo &rInf ) const
+{
+ if( Width() )
+ {
+ // bBackground is set for Kerning Portions between two fields
+ if ( bBackground )
+ rInf.DrawViewOpt( *this, POR_FLD );
+
+ rInf.DrawBackBrush( *this );
+
+ // do we have to repaint a post it portion?
+ if( rInf.OnWin() && pPortion && !pPortion->Width() )
+ pPortion->PrePaint( rInf, this );
+
+ if( rInf.GetFont()->IsPaintBlank() )
+ {
+ static sal_Char const sDoubleSpace[] = " ";
+ XubString aTxtDouble( sDoubleSpace, RTL_TEXTENCODING_MS_1252 );
+ // --> FME 2006-07-12 #b6439097#
+ SwRect aClipRect;
+ rInf.CalcRect( *this, &aClipRect, 0 );
+ SwSaveClip aClip( (OutputDevice*)rInf.GetOut() );
+ aClip.ChgClip( aClipRect, 0 );
+ // <--
+ rInf.DrawText( aTxtDouble, *this, 0, 2, sal_True );
+ }
+ }
+}
+
+void SwKernPortion::FormatEOL( SwTxtFormatInfo &rInf )
+{
+ if ( bGridKern )
+ return;
+
+ if( rInf.GetLast() == this )
+ rInf.SetLast( FindPrevPortion( rInf.GetRoot() ) );
+ if( nKern < 0 )
+ Width( -nKern );
+ else
+ Width( 0 );
+ rInf.GetLast()->FormatEOL( rInf );
+}
+
+SwArrowPortion::SwArrowPortion( const SwLinePortion &rPortion ) :
+ bLeft( sal_True )
+{
+ Height( rPortion.Height() );
+ SetAscent( rPortion.GetAscent() );
+ nLineLength = 0;
+ SetWhichPor( POR_ARROW );
+}
+
+SwArrowPortion::SwArrowPortion( const SwTxtPaintInfo &rInf )
+ : bLeft( sal_False )
+{
+ Height( (sal_uInt16)(rInf.GetTxtFrm()->Prt().Height()) );
+ aPos.X() = rInf.GetTxtFrm()->Frm().Left() +
+ rInf.GetTxtFrm()->Prt().Right();
+ aPos.Y() = rInf.GetTxtFrm()->Frm().Top() +
+ rInf.GetTxtFrm()->Prt().Bottom();
+ SetWhichPor( POR_ARROW );
+}
+
+void SwArrowPortion::Paint( const SwTxtPaintInfo &rInf ) const
+{
+ ((SwArrowPortion*)this)->aPos = rInf.GetPos();
+}
+
+SwLinePortion *SwArrowPortion::Compress() { return this; }
+
+SwTwips SwTxtFrm::EmptyHeight() const
+{
+ if (IsCollapse()) {
+ ViewShell *pSh = getRootFrm()->GetCurrShell();
+ if ( pSh->IsA( TYPE(SwCrsrShell) ) ) {
+ SwCrsrShell *pCrSh=(SwCrsrShell*)pSh;
+ SwCntntFrm *pCurrFrm=pCrSh->GetCurrFrm();
+ if (pCurrFrm==(SwCntntFrm*)this) {
+ // do nothing
+ } else {
+ return 1;
+ }
+ } else {
+ return 1;
+ }
+ }
+ OSL_ENSURE( ! IsVertical() || ! IsSwapped(),"SwTxtFrm::EmptyHeight with swapped frame" );
+
+ SwFont *pFnt;
+ const SwTxtNode& rTxtNode = *GetTxtNode();
+ const IDocumentSettingAccess* pIDSA = rTxtNode.getIDocumentSettingAccess();
+ ViewShell *pSh = getRootFrm()->GetCurrShell();
+ if ( rTxtNode.HasSwAttrSet() )
+ {
+ const SwAttrSet *pAttrSet = &( rTxtNode.GetSwAttrSet() );
+ pFnt = new SwFont( pAttrSet, pIDSA );
+ }
+ else
+ {
+ SwFontAccess aFontAccess( &rTxtNode.GetAnyFmtColl(), pSh);
+ pFnt = new SwFont( *aFontAccess.Get()->GetFont() );
+ pFnt->ChkMagic( pSh, pFnt->GetActual() );
+ }
+
+ if ( IsVertical() )
+ pFnt->SetVertical( 2700 );
+
+ OutputDevice* pOut = pSh ? pSh->GetOut() : 0;
+ if ( !pOut || !pSh->GetViewOptions()->getBrowseMode() ||
+ pSh->GetViewOptions()->IsPrtFormat() )
+ {
+ pOut = rTxtNode.getIDocumentDeviceAccess()->getReferenceDevice(true);
+ }
+
+ const IDocumentRedlineAccess* pIDRA = rTxtNode.getIDocumentRedlineAccess();
+ if( IDocumentRedlineAccess::IsShowChanges( pIDRA->GetRedlineMode() ) )
+ {
+ MSHORT nRedlPos = pIDRA->GetRedlinePos( rTxtNode, USHRT_MAX );
+ if( MSHRT_MAX != nRedlPos )
+ {
+ SwAttrHandler aAttrHandler;
+ aAttrHandler.Init( GetTxtNode()->GetSwAttrSet(),
+ *GetTxtNode()->getIDocumentSettingAccess(), NULL );
+ SwRedlineItr aRedln( rTxtNode, *pFnt, aAttrHandler,
+ nRedlPos, sal_True );
+ }
+ }
+
+ SwTwips nRet;
+ if( !pOut )
+ nRet = IsVertical() ?
+ Prt().SSize().Width() + 1 :
+ Prt().SSize().Height() + 1;
+ else
+ {
+ pFnt->SetFntChg( sal_True );
+ pFnt->ChgPhysFnt( pSh, *pOut );
+ nRet = pFnt->GetHeight( pSh, *pOut );
+ }
+ delete pFnt;
+ return nRet;
+}
+
+/*************************************************************************
+ * SwTxtFrm::FormatEmpty()
+ *************************************************************************/
+
+sal_Bool SwTxtFrm::FormatEmpty()
+{
+ OSL_ENSURE( ! IsVertical() || ! IsSwapped(),"SwTxtFrm::FormatEmpty with swapped frame" );
+
+ if ( HasFollow() || GetTxtNode()->GetpSwpHints() ||
+ 0 != GetTxtNode()->GetNumRule() ||
+ GetTxtNode()->HasHiddenCharAttribute( true ) ||
+ IsInFtn() || ( HasPara() && GetPara()->IsPrepMustFit() ) )
+ return sal_False;
+ const SwAttrSet& aSet = GetTxtNode()->GetSwAttrSet();
+ const SvxAdjust nAdjust = aSet.GetAdjust().GetAdjust();
+ if( ( ( ! IsRightToLeft() && ( SVX_ADJUST_LEFT != nAdjust ) ) ||
+ ( IsRightToLeft() && ( SVX_ADJUST_RIGHT != nAdjust ) ) ) ||
+ aSet.GetRegister().GetValue() )
+ return sal_False;
+ const SvxLineSpacingItem &rSpacing = aSet.GetLineSpacing();
+ if( SVX_LINE_SPACE_MIN == rSpacing.GetLineSpaceRule() ||
+ SVX_LINE_SPACE_FIX == rSpacing.GetLineSpaceRule() ||
+ aSet.GetLRSpace().IsAutoFirst() )
+ return sal_False;
+ else
+ {
+ SwTxtFly aTxtFly( this );
+ SwRect aRect;
+ sal_Bool bFirstFlyCheck = 0 != Prt().Height();
+ if ( bFirstFlyCheck &&
+ aTxtFly.IsOn() && aTxtFly.IsAnyObj( aRect ) )
+ return sal_False;
+ else
+ {
+ SwTwips nHeight = EmptyHeight();
+
+ if ( GetTxtNode()->GetSwAttrSet().GetParaGrid().GetValue() &&
+ IsInDocBody() )
+ {
+ GETGRID( FindPageFrm() )
+ if ( pGrid )
+ nHeight = pGrid->GetBaseHeight() + pGrid->GetRubyHeight();
+ }
+
+ SWRECTFN( this )
+ const SwTwips nChg = nHeight - (Prt().*fnRect->fnGetHeight)();
+
+ if( !nChg )
+ SetUndersized( sal_False );
+ AdjustFrm( nChg );
+
+ if( HasBlinkPor() )
+ {
+ ClearPara();
+ ResetBlinkPor();
+ }
+ SetCacheIdx( MSHRT_MAX );
+ if( !IsEmpty() )
+ {
+ SetEmpty( sal_True );
+ SetCompletePaint();
+ }
+ if( !bFirstFlyCheck &&
+ aTxtFly.IsOn() && aTxtFly.IsAnyObj( aRect ) )
+ return sal_False;
+
+ // --> OD 2004-11-17 #i35635# - call method <HideAndShowObjects()>
+ // to assure that objects anchored at the empty paragraph are
+ // correctly visible resp. invisible.
+ HideAndShowObjects();
+ // <--
+ return sal_True;
+ }
+ }
+}
+
+sal_Bool SwTxtFrm::FillRegister( SwTwips& rRegStart, KSHORT& rRegDiff )
+{
+ const SwFrm *pFrm = this;
+ rRegDiff = 0;
+ while( !( ( FRM_BODY | FRM_FLY )
+ & pFrm->GetType() ) && pFrm->GetUpper() )
+ pFrm = pFrm->GetUpper();
+ if( ( FRM_BODY| FRM_FLY ) & pFrm->GetType() )
+ {
+ SWRECTFN( pFrm )
+ rRegStart = (pFrm->*fnRect->fnGetPrtTop)();
+ pFrm = pFrm->FindPageFrm();
+ if( pFrm->IsPageFrm() )
+ {
+ SwPageDesc* pDesc = ((SwPageFrm*)pFrm)->FindPageDesc();
+ if( pDesc )
+ {
+ rRegDiff = pDesc->GetRegHeight();
+ if( !rRegDiff )
+ {
+ const SwTxtFmtColl *pFmt = pDesc->GetRegisterFmtColl();
+ if( pFmt )
+ {
+ const SvxLineSpacingItem &rSpace = pFmt->GetLineSpacing();
+ if( SVX_LINE_SPACE_FIX == rSpace.GetLineSpaceRule() )
+ {
+ rRegDiff = rSpace.GetLineHeight();
+ pDesc->SetRegHeight( rRegDiff );
+ pDesc->SetRegAscent( ( 4 * rRegDiff ) / 5 );
+ }
+ else
+ {
+ ViewShell *pSh = getRootFrm()->GetCurrShell();
+ SwFontAccess aFontAccess( pFmt, pSh );
+ SwFont aFnt( *aFontAccess.Get()->GetFont() );
+
+ OutputDevice *pOut = 0;
+ if( !pSh || !pSh->GetViewOptions()->getBrowseMode() ||
+ pSh->GetViewOptions()->IsPrtFormat() )
+ pOut = GetTxtNode()->getIDocumentDeviceAccess()->getReferenceDevice( true );
+
+ if( pSh && !pOut )
+ pOut = pSh->GetWin();
+
+ if( !pOut )
+ pOut = GetpApp()->GetDefaultDevice();
+
+ MapMode aOldMap( pOut->GetMapMode() );
+ pOut->SetMapMode( MapMode( MAP_TWIP ) );
+
+ aFnt.ChgFnt( pSh, *pOut );
+ rRegDiff = aFnt.GetHeight( pSh, *pOut );
+ KSHORT nNettoHeight = rRegDiff;
+
+ switch( rSpace.GetLineSpaceRule() )
+ {
+ case SVX_LINE_SPACE_AUTO:
+ break;
+ case SVX_LINE_SPACE_MIN:
+ {
+ if( rRegDiff < KSHORT( rSpace.GetLineHeight() ) )
+ rRegDiff = rSpace.GetLineHeight();
+ break;
+ }
+ default:
+ OSL_FAIL( ": unknown LineSpaceRule" );
+ }
+ switch( rSpace.GetInterLineSpaceRule() )
+ {
+ case SVX_INTER_LINE_SPACE_OFF:
+ break;
+ case SVX_INTER_LINE_SPACE_PROP:
+ {
+ long nTmp = rSpace.GetPropLineSpace();
+ if( nTmp < 50 )
+ nTmp = nTmp ? 50 : 100;
+ nTmp *= rRegDiff;
+ nTmp /= 100;
+ if( !nTmp )
+ ++nTmp;
+ rRegDiff = (KSHORT)nTmp;
+ nNettoHeight = rRegDiff;
+ break;
+ }
+ case SVX_INTER_LINE_SPACE_FIX:
+ {
+ rRegDiff = rRegDiff + rSpace.GetInterLineSpace();
+ nNettoHeight = rRegDiff;
+ break;
+ }
+ default: OSL_FAIL( ": unknown InterLineSpaceRule" );
+ }
+ pDesc->SetRegHeight( rRegDiff );
+ pDesc->SetRegAscent( rRegDiff - nNettoHeight +
+ aFnt.GetAscent( pSh, *pOut ) );
+ pOut->SetMapMode( aOldMap );
+ }
+ }
+ }
+ const long nTmpDiff = pDesc->GetRegAscent() - rRegDiff;
+ if ( bVert )
+ rRegStart -= nTmpDiff;
+ else
+ rRegStart += nTmpDiff;
+ }
+ }
+ }
+ return ( 0 != rRegDiff );
+}
+
+/*************************************************************************
+ * virtual SwHiddenTextPortion::Paint()
+ *************************************************************************/
+
+void SwHiddenTextPortion::Paint( const SwTxtPaintInfo & rInf) const
+{
+ (void)rInf;
+#if OSL_DEBUG_LEVEL > 1
+ OutputDevice* pOut = (OutputDevice*)rInf.GetOut();
+ Color aCol( SwViewOption::GetFieldShadingsColor() );
+ Color aOldColor( pOut->GetFillColor() );
+ pOut->SetFillColor( aCol );
+ Point aPos( rInf.GetPos() );
+ aPos.Y() -= 150;
+ aPos.X() -= 25;
+ SwRect aRect( aPos, Size( 100, 200 ) );
+ ((OutputDevice*)pOut)->DrawRect( aRect.SVRect() );
+ pOut->SetFillColor( aOldColor );
+#endif
+}
+
+/*************************************************************************
+ * virtual SwHiddenTextPortion::Format()
+ *************************************************************************/
+
+sal_Bool SwHiddenTextPortion::Format( SwTxtFormatInfo &rInf )
+{
+ Width( 0 );
+ rInf.GetTxtFrm()->HideFootnotes( rInf.GetIdx(), rInf.GetIdx() + GetLen() );
+
+ return sal_False;
+};
+
+/*************************************************************************
+ * virtual SwControlCharPortion::Paint()
+ *************************************************************************/
+
+void SwControlCharPortion::Paint( const SwTxtPaintInfo &rInf ) const
+{
+ if ( Width() ) // is only set during prepaint mode
+ {
+ rInf.DrawViewOpt( *this, POR_CONTROLCHAR );
+
+ if ( !rInf.GetOpt().IsPagePreview() &&
+ !rInf.GetOpt().IsReadonly() &&
+ SwViewOption::IsFieldShadings() &&
+ CHAR_ZWNBSP != mcChar )
+ {
+ SwFont aTmpFont( *rInf.GetFont() );
+ aTmpFont.SetEscapement( CHAR_ZWSP == mcChar ? DFLT_ESC_AUTO_SUB : -25 );
+ const sal_uInt16 nProp = 40;
+ aTmpFont.SetProportion( nProp ); // a smaller font
+ SwFontSave aFontSave( rInf, &aTmpFont );
+
+ String aOutString;
+
+ switch ( mcChar )
+ {
+ case CHAR_ZWSP :
+ aOutString = '/'; break;
+// case CHAR_LRM :
+// rTxt = sal_Unicode(0x2514); break;
+// case CHAR_RLM :
+// rTxt = sal_Unicode(0x2518); break;
+ }
+
+ if ( !mnHalfCharWidth )
+ mnHalfCharWidth = rInf.GetTxtSize( aOutString ).Width() / 2;
+
+ Point aOldPos = rInf.GetPos();
+ Point aNewPos( aOldPos );
+ aNewPos.X() = aNewPos.X() + ( Width() / 2 ) - mnHalfCharWidth;
+ const_cast< SwTxtPaintInfo& >( rInf ).SetPos( aNewPos );
+
+ rInf.DrawText( aOutString, *this );
+
+ const_cast< SwTxtPaintInfo& >( rInf ).SetPos( aOldPos );
+ }
+ }
+}
+
+/*************************************************************************
+ * virtual SwControlCharPortion::Format()
+ *************************************************************************/
+
+sal_Bool SwControlCharPortion::Format( SwTxtFormatInfo &rInf )
+{
+ const SwLinePortion* pRoot = rInf.GetRoot();
+ Width( 0 );
+ Height( pRoot->Height() );
+ SetAscent( pRoot->GetAscent() );
+
+ return sal_False;
+}
+
+/*************************************************************************
+ * virtual SwControlCharPortion::GetViewWidth()
+ *************************************************************************/
+
+KSHORT SwControlCharPortion::GetViewWidth( const SwTxtSizeInfo& rInf ) const
+{
+ if( !mnViewWidth )
+ mnViewWidth = rInf.GetTxtSize( ' ' ).Width();
+
+ return mnViewWidth;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/text/porrst.hxx b/sw/source/core/text/porrst.hxx
new file mode 100644
index 000000000000..1c1d2dd48893
--- /dev/null
+++ b/sw/source/core/text/porrst.hxx
@@ -0,0 +1,190 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+#ifndef _PORRST_HXX
+#define _PORRST_HXX
+#include "porlay.hxx"
+#include "porexp.hxx"
+
+#define LINE_BREAK_WIDTH 150
+#define SPECIAL_FONT_HEIGHT 200
+
+class SwTxtFormatInfo;
+
+/*************************************************************************
+ * class SwTmpEndPortion
+ *************************************************************************/
+
+class SwTmpEndPortion : public SwLinePortion
+{
+public:
+ SwTmpEndPortion( const SwLinePortion &rPortion );
+ virtual void Paint( const SwTxtPaintInfo &rInf ) const;
+ OUTPUT_OPERATOR
+};
+
+/*************************************************************************
+ * class SwBreakPortion
+ *************************************************************************/
+
+class SwBreakPortion : public SwLinePortion
+{
+public:
+ SwBreakPortion( const SwLinePortion &rPortion );
+ // liefert 0 zurueck, wenn keine Nutzdaten enthalten sind.
+ virtual SwLinePortion *Compress();
+ virtual void Paint( const SwTxtPaintInfo &rInf ) const;
+ virtual sal_Bool Format( SwTxtFormatInfo &rInf );
+ virtual KSHORT GetViewWidth( const SwTxtSizeInfo &rInf ) const;
+ virtual xub_StrLen GetCrsrOfst( const MSHORT nOfst ) const;
+
+ // Accessibility: pass information about this portion to the PortionHandler
+ virtual void HandlePortion( SwPortionHandler& rPH ) const;
+
+ OUTPUT_OPERATOR
+};
+
+/*************************************************************************
+ * class SwKernPortion
+ *************************************************************************/
+
+class SwKernPortion : public SwLinePortion
+{
+ short nKern;
+ sal_Bool bBackground;
+ sal_Bool bGridKern;
+
+public:
+
+ // This constructor automatically appends the portion to rPortion
+ // bBG indicates, that the background of the kerning portion has to
+ // be painted, e.g., if the portion if positioned between to fields.
+ // bGridKern indicates, that the kerning portion is used to provide
+ // additional space in grid mode.
+ SwKernPortion( SwLinePortion &rPortion, short nKrn,
+ sal_Bool bBG = sal_False, sal_Bool bGridKern = sal_False );
+
+ // This constructor only sets the height and ascent to the values
+ // of rPortion. It is only used for kerning portions for grid mode
+ SwKernPortion( const SwLinePortion &rPortion );
+
+ virtual void FormatEOL( SwTxtFormatInfo &rInf );
+ virtual void Paint( const SwTxtPaintInfo &rInf ) const;
+
+ OUTPUT_OPERATOR
+};
+
+/*************************************************************************
+ * class SwArrowPortion
+ *************************************************************************/
+
+class SwArrowPortion : public SwLinePortion
+{
+ Point aPos;
+ sal_Bool bLeft;
+public:
+ SwArrowPortion( const SwLinePortion &rPortion );
+ SwArrowPortion( const SwTxtPaintInfo &rInf );
+ virtual void Paint( const SwTxtPaintInfo &rInf ) const;
+ virtual SwLinePortion *Compress();
+ inline sal_Bool IsLeft() const { return bLeft; }
+ inline const Point& GetPos() const { return aPos; }
+ OUTPUT_OPERATOR
+};
+
+/*************************************************************************
+ * class SwHangingPortion
+ * The characters which are forbidden at the start of a line like the dot and
+ * other punctuation marks are allowed to display in the margin of the page
+ * by a user option.
+ * The SwHangingPortion is the corresponding textportion to do that.
+ *************************************************************************/
+
+class SwHangingPortion : public SwTxtPortion
+{
+ KSHORT nInnerWidth;
+public:
+ inline SwHangingPortion( SwPosSize aSize ) : nInnerWidth( aSize.Width() )
+ { SetWhichPor( POR_HNG ); SetLen( 1 ); Height( aSize.Height() ); }
+
+ inline KSHORT GetInnerWidth() const { return nInnerWidth; }
+};
+
+/*************************************************************************
+ * class SwHiddenTextPortion
+ * Is used to hide text
+ *************************************************************************/
+
+class SwHiddenTextPortion : public SwLinePortion
+{
+public:
+ inline SwHiddenTextPortion( xub_StrLen nLen )
+ { SetWhichPor( POR_HIDDEN_TXT ); SetLen( nLen ); }
+
+ virtual void Paint( const SwTxtPaintInfo &rInf ) const;
+ virtual sal_Bool Format( SwTxtFormatInfo &rInf );
+};
+
+/*************************************************************************
+ * class SwControlCharPortion
+ *************************************************************************/
+
+class SwControlCharPortion : public SwLinePortion
+{
+
+private:
+ mutable sal_uInt16 mnViewWidth; // used to cache a calculated value
+ mutable sal_uInt16 mnHalfCharWidth; // used to cache a calculated value
+ sal_Unicode mcChar;
+
+public:
+
+ inline SwControlCharPortion( sal_Unicode cChar )
+ : mnViewWidth( 0 ), mnHalfCharWidth( 0 ), mcChar( cChar )
+ {
+ SetWhichPor( POR_CONTROLCHAR ); SetLen( 1 );
+ }
+
+ virtual void Paint( const SwTxtPaintInfo &rInf ) const;
+ virtual sal_Bool Format( SwTxtFormatInfo &rInf );
+ virtual KSHORT GetViewWidth( const SwTxtSizeInfo& rInf ) const;
+};
+
+
+
+/*************************************************************************
+ * inline - Implementations
+ *************************************************************************/
+
+CLASSIO( SwBreakPortion )
+CLASSIO( SwEndPortion )
+CLASSIO( SwKernPortion )
+CLASSIO( SwArrowPortion )
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/text/portab.hxx b/sw/source/core/text/portab.hxx
new file mode 100644
index 000000000000..3cda7b9d1f96
--- /dev/null
+++ b/sw/source/core/text/portab.hxx
@@ -0,0 +1,160 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+#ifndef _PORTAB_HXX
+#define _PORTAB_HXX
+
+#include "porglue.hxx"
+
+/*************************************************************************
+ * class SwTabPortion
+ *************************************************************************/
+
+class SwTabPortion : public SwFixPortion
+{
+ const KSHORT nTabPos;
+ const xub_Unicode cFill;
+
+ // Das Format() verzweigt entweder in Pre- oder PostFormat()
+ sal_Bool PreFormat( SwTxtFormatInfo &rInf );
+public:
+ SwTabPortion( const KSHORT nTabPos, const xub_Unicode cFill = '\0' );
+ virtual void Paint( const SwTxtPaintInfo &rInf ) const;
+ virtual sal_Bool Format( SwTxtFormatInfo &rInf );
+ virtual void FormatEOL( SwTxtFormatInfo &rInf );
+ sal_Bool PostFormat( SwTxtFormatInfo &rInf );
+ inline sal_Bool IsFilled() const { return 0 != cFill; }
+ inline KSHORT GetTabPos() const { return nTabPos; }
+
+ // Accessibility: pass information about this portion to the PortionHandler
+ virtual void HandlePortion( SwPortionHandler& rPH ) const;
+
+ OUTPUT_OPERATOR
+};
+
+/*************************************************************************
+ * class SwTabLeftPortion
+ *************************************************************************/
+
+class SwTabLeftPortion : public SwTabPortion
+{
+public:
+ inline SwTabLeftPortion( const KSHORT nTabPosVal, const xub_Unicode cFillChar='\0' )
+ : SwTabPortion( nTabPosVal, cFillChar )
+ { SetWhichPor( POR_TABLEFT ); }
+ OUTPUT_OPERATOR
+};
+
+/*************************************************************************
+ * class SwTabRightPortion
+ *************************************************************************/
+
+class SwTabRightPortion : public SwTabPortion
+{
+public:
+ inline SwTabRightPortion( const KSHORT nTabPosVal, const xub_Unicode cFillChar='\0' )
+ : SwTabPortion( nTabPosVal, cFillChar )
+ { SetWhichPor( POR_TABRIGHT ); }
+ OUTPUT_OPERATOR
+};
+
+/*************************************************************************
+ * class SwTabCenterPortion
+ *************************************************************************/
+
+class SwTabCenterPortion : public SwTabPortion
+{
+public:
+ inline SwTabCenterPortion( const KSHORT nTabPosVal, const xub_Unicode cFillChar='\0' )
+ : SwTabPortion( nTabPosVal, cFillChar )
+ { SetWhichPor( POR_TABCENTER ); }
+ OUTPUT_OPERATOR
+};
+
+/*************************************************************************
+ * class SwTabDecimalPortion
+ *************************************************************************/
+
+class SwTabDecimalPortion : public SwTabPortion
+{
+ const xub_Unicode mcTab;
+
+ /*
+ * During text formatting, we already store the width of the portions
+ * following the tab stop up to the decimal position. This value is
+ * evaluated during pLastTab->FormatEOL. FME 2006-01-06 #127428#.
+ */
+ sal_uInt16 mnWidthOfPortionsUpTpDecimalPosition;
+
+public:
+ inline SwTabDecimalPortion( const KSHORT nTabPosVal, const xub_Unicode cTab,
+ const xub_Unicode cFillChar = '\0' )
+ : SwTabPortion( nTabPosVal, cFillChar ),
+ mcTab(cTab),
+ mnWidthOfPortionsUpTpDecimalPosition( USHRT_MAX )
+ { SetWhichPor( POR_TABDECIMAL ); }
+
+ inline xub_Unicode GetTabDecimal() const { return mcTab; }
+
+ inline void SetWidthOfPortionsUpToDecimalPosition( sal_uInt16 nNew )
+ {
+ mnWidthOfPortionsUpTpDecimalPosition = nNew;
+ }
+ inline sal_uInt16 GetWidthOfPortionsUpToDecimalPosition() const
+ {
+ return mnWidthOfPortionsUpTpDecimalPosition;
+ }
+
+ OUTPUT_OPERATOR
+};
+
+
+/*************************************************************************
+ * class SwAutoTabDecimalPortion
+ *************************************************************************/
+
+class SwAutoTabDecimalPortion : public SwTabDecimalPortion
+{
+public:
+ inline SwAutoTabDecimalPortion( const KSHORT nTabPosVal, const xub_Unicode cTab,
+ const xub_Unicode cFillChar = '\0' )
+ : SwTabDecimalPortion( nTabPosVal, cTab, cFillChar )
+ { SetLen( 0 ); }
+ virtual void Paint( const SwTxtPaintInfo &rInf ) const;
+};
+
+
+CLASSIO( SwTabPortion )
+CLASSIO( SwTabLeftPortion )
+CLASSIO( SwTabRightPortion )
+CLASSIO( SwTabCenterPortion )
+CLASSIO( SwTabDecimalPortion )
+
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/text/portox.cxx b/sw/source/core/text/portox.cxx
new file mode 100644
index 000000000000..39dab8101301
--- /dev/null
+++ b/sw/source/core/text/portox.cxx
@@ -0,0 +1,116 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+
+#include <SwPortionHandler.hxx>
+#include "viewopt.hxx" // SwViewOptions
+
+#include "portox.hxx"
+#include "inftxt.hxx" // GetTxtSize()
+
+/*************************************************************************
+ * virtual SwToxPortion::Paint()
+ *************************************************************************/
+
+void SwToxPortion::Paint( const SwTxtPaintInfo &rInf ) const
+{
+ if( Width() )
+ {
+ rInf.DrawViewOpt( *this, POR_TOX );
+ SwTxtPortion::Paint( rInf );
+ }
+}
+
+/*************************************************************************
+ * class SwIsoToxPortion
+ *************************************************************************/
+
+SwLinePortion *SwIsoToxPortion::Compress() { return this; }
+
+SwIsoToxPortion::SwIsoToxPortion() : nViewWidth(0)
+{
+ SetLen(1);
+ SetWhichPor( POR_ISOTOX );
+}
+
+/*************************************************************************
+ * virtual SwIsoToxPortion::GetViewWidth()
+ *************************************************************************/
+
+KSHORT SwIsoToxPortion::GetViewWidth( const SwTxtSizeInfo &rInf ) const
+{
+ // Wir stehen zwar im const, aber nViewWidth sollte erst im letzten
+ // Moment errechnet werden:
+ SwIsoToxPortion* pThis = (SwIsoToxPortion*)this;
+ // nViewWidth muss errechnet werden.
+ if( !Width() && rInf.OnWin() &&
+ !rInf.GetOpt().IsPagePreview() &&
+ !rInf.GetOpt().IsReadonly() && SwViewOption::IsFieldShadings() )
+ {
+ if( !nViewWidth )
+ pThis->nViewWidth = rInf.GetTxtSize( ' ' ).Width();
+ }
+ else
+ pThis->nViewWidth = 0;
+ return nViewWidth;
+}
+
+/*************************************************************************
+ * virtual SwIsoToxPortion::Format()
+ *************************************************************************/
+
+sal_Bool SwIsoToxPortion::Format( SwTxtFormatInfo &rInf )
+{
+ const sal_Bool bFull = SwLinePortion::Format( rInf );
+ return bFull;
+}
+
+/*************************************************************************
+ * virtual SwIsoToxPortion::Paint()
+ *************************************************************************/
+
+void SwIsoToxPortion::Paint( const SwTxtPaintInfo &rInf ) const
+{
+ if( Width() )
+ rInf.DrawViewOpt( *this, POR_TOX );
+}
+
+/*************************************************************************
+ * virtual SwIsoToxPortion::HandlePortion()
+ *************************************************************************/
+
+void SwIsoToxPortion::HandlePortion( SwPortionHandler& rPH ) const
+{
+ String aString;
+ rPH.Special( GetLen(), aString, GetWhichPor() );
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/text/portox.hxx b/sw/source/core/text/portox.hxx
new file mode 100644
index 000000000000..9c867701d7cc
--- /dev/null
+++ b/sw/source/core/text/portox.hxx
@@ -0,0 +1,77 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef _PORTOX_HXX
+#define _PORTOX_HXX
+
+#include "portxt.hxx"
+
+/*************************************************************************
+ * class SwToxPortion
+ *************************************************************************/
+
+class SwToxPortion : public SwTxtPortion
+{
+public:
+ inline SwToxPortion(){ SetWhichPor( POR_TOX ); }
+ virtual void Paint( const SwTxtPaintInfo &rInf ) const;
+ OUTPUT_OPERATOR
+};
+
+/*************************************************************************
+ * class SwIsoToxPortion
+ *************************************************************************/
+
+class SwIsoToxPortion : public SwToxPortion
+{
+ KSHORT nViewWidth;
+
+public:
+ SwIsoToxPortion();
+ virtual sal_Bool Format( SwTxtFormatInfo &rInf );
+ virtual void Paint( const SwTxtPaintInfo &rInf ) const;
+ virtual SwLinePortion *Compress();
+ virtual KSHORT GetViewWidth( const SwTxtSizeInfo &rInf ) const;
+
+ // Accessibility: pass information about this portion to the PortionHandler
+ virtual void HandlePortion( SwPortionHandler& rPH ) const;
+
+ OUTPUT_OPERATOR
+};
+
+/*************************************************************************
+ * inline - Implementations
+ *************************************************************************/
+
+CLASSIO( SwToxPortion )
+CLASSIO( SwIsoToxPortion )
+
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/text/portxt.cxx b/sw/source/core/text/portxt.cxx
new file mode 100644
index 000000000000..a84ccb6b52de
--- /dev/null
+++ b/sw/source/core/text/portxt.cxx
@@ -0,0 +1,876 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+
+#include <ctype.h>
+
+#include <com/sun/star/i18n/ScriptType.hdl>
+#include <hintids.hxx> // CH_TXTATR
+#include <SwPortionHandler.hxx>
+#include <porlay.hxx>
+#include <inftxt.hxx>
+#include <guess.hxx> // SwTxtGuess, Zeilenumbruch
+#include <porglue.hxx>
+#include <portab.hxx> // pLastTab->
+#include <porfld.hxx> // SwFldPortion
+#include <wrong.hxx>
+#include <viewsh.hxx>
+#include <IDocumentSettingAccess.hxx>
+#include <viewopt.hxx> // SwViewOptions
+
+#include <IMark.hxx>
+#include <pam.hxx>
+#include <doc.hxx>
+#include <xmloff/odffields.hxx>
+
+using namespace ::sw::mark;
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::i18n::ScriptType;
+
+/*************************************************************************
+ * lcl_AddSpace
+ * Returns for how many characters an extra space has to be added
+ * (for justified alignment).
+ *************************************************************************/
+
+sal_uInt16 lcl_AddSpace( const SwTxtSizeInfo &rInf, const XubString* pStr,
+ const SwLinePortion& rPor )
+{
+ xub_StrLen nPos, nEnd;
+ const SwScriptInfo* pSI = 0;
+
+ if ( pStr )
+ {
+ // passing a string means we are inside a field
+ nPos = 0;
+ nEnd = pStr->Len();
+ }
+ else
+ {
+ nPos = rInf.GetIdx();
+ nEnd = rInf.GetIdx() + rPor.GetLen();
+ pStr = &rInf.GetTxt();
+ pSI = &((SwParaPortion*)rInf.GetParaPortion())->GetScriptInfo();
+ }
+
+ sal_uInt16 nCnt = 0;
+ sal_uInt8 nScript = 0;
+
+ // If portion consists of Asian characters and language is not
+ // Korean, we add extra space to each character.
+ // first we get the script type
+ if ( pSI )
+ nScript = pSI->ScriptType( nPos );
+ else if ( pBreakIt->GetBreakIter().is() )
+ nScript = (sal_uInt8)pBreakIt->GetBreakIter()->getScriptType( *pStr, nPos );
+
+ // Note: rInf.GetIdx() can differ from nPos,
+ // e.g., when rPor is a field portion. nPos referes to the string passed
+ // to the function, rInf.GetIdx() referes to the original string.
+
+ // We try to find out which justification mode is required. This is done by
+ // evaluating the script type and the language attribute set for this portion
+
+ // Asian Justification: Each character get some extra space
+ if ( nEnd > nPos && ASIAN == nScript )
+ {
+ LanguageType aLang =
+ rInf.GetTxtFrm()->GetTxtNode()->GetLang( rInf.GetIdx(), 1, nScript );
+
+ if ( LANGUAGE_KOREAN != aLang && LANGUAGE_KOREAN_JOHAB != aLang )
+ {
+ const SwLinePortion* pPor = rPor.GetPortion();
+ if ( pPor && ( pPor->IsKernPortion() ||
+ pPor->IsControlCharPortion() ||
+ pPor->IsPostItsPortion() ) )
+ pPor = pPor->GetPortion();
+
+ nCnt += nEnd - nPos;
+
+ if ( !pPor || pPor->IsHolePortion() || pPor->InFixMargGrp() ||
+ pPor->IsBreakPortion() )
+ --nCnt;
+
+ return nCnt;
+ }
+ }
+
+ // Kashida Justification: Insert Kashidas
+ if ( nEnd > nPos && pSI && COMPLEX == nScript )
+ {
+ if ( SwScriptInfo::IsArabicText( *pStr, nPos, nEnd - nPos ) && pSI->CountKashida() )
+ {
+ const sal_uInt16 nKashRes = pSI->KashidaJustify( 0, 0, nPos, nEnd - nPos );
+ // i60591: need to check result of KashidaJustify
+ // determine if kashida justification is applicable
+ if( nKashRes != STRING_LEN )
+ return nKashRes;
+ }
+ }
+
+ // Thai Justification: Each character cell gets some extra space
+ if ( nEnd > nPos && COMPLEX == nScript )
+ {
+ LanguageType aLang =
+ rInf.GetTxtFrm()->GetTxtNode()->GetLang( rInf.GetIdx(), 1, nScript );
+
+ if ( LANGUAGE_THAI == aLang )
+ {
+ nCnt = SwScriptInfo::ThaiJustify( *pStr, 0, 0, nPos, nEnd - nPos );
+
+ const SwLinePortion* pPor = rPor.GetPortion();
+ if ( pPor && ( pPor->IsKernPortion() ||
+ pPor->IsControlCharPortion() ||
+ pPor->IsPostItsPortion() ) )
+ pPor = pPor->GetPortion();
+
+ if ( nCnt && ( ! pPor || pPor->IsHolePortion() || pPor->InFixMargGrp() ) )
+ --nCnt;
+
+ return nCnt;
+ }
+ }
+
+ // Here starts the good old "Look for blanks and add space to them" part.
+ // Note: We do not want to add space to an isolated latin blank in front
+ // of some complex characters in RTL environment
+ const sal_Bool bDoNotAddSpace =
+ LATIN == nScript && ( nEnd == nPos + 1 ) && pSI &&
+ ( i18n::ScriptType::COMPLEX ==
+ pSI->ScriptType( nPos + 1 ) ) &&
+ rInf.GetTxtFrm() && rInf.GetTxtFrm()->IsRightToLeft();
+
+ if ( bDoNotAddSpace )
+ return nCnt;
+
+ for ( ; nPos < nEnd; ++nPos )
+ {
+ if( CH_BLANK == pStr->GetChar( nPos ) )
+ ++nCnt;
+ }
+
+ // We still have to examine the next character:
+ // If the next character is ASIAN and not KOREAN we have
+ // to add an extra space
+ // nPos referes to the original string, even if a field string has
+ // been passed to this function
+ nPos = rInf.GetIdx() + rPor.GetLen();
+ if ( nPos < rInf.GetTxt().Len() )
+ {
+ sal_uInt8 nNextScript = 0;
+ const SwLinePortion* pPor = rPor.GetPortion();
+ if ( pPor && pPor->IsKernPortion() )
+ pPor = pPor->GetPortion();
+
+ if ( ! pBreakIt->GetBreakIter().is() || ! pPor || pPor->InFixMargGrp() )
+ return nCnt;
+
+ // next character is inside a field?
+ if ( CH_TXTATR_BREAKWORD == rInf.GetChar( nPos ) && pPor->InExpGrp() )
+ {
+ sal_Bool bOldOnWin = rInf.OnWin();
+ ((SwTxtSizeInfo &)rInf).SetOnWin( sal_False );
+
+ XubString aStr( aEmptyStr );
+ pPor->GetExpTxt( rInf, aStr );
+ ((SwTxtSizeInfo &)rInf).SetOnWin( bOldOnWin );
+
+ nNextScript = (sal_uInt8)pBreakIt->GetBreakIter()->getScriptType( aStr, 0 );
+ }
+ else
+ nNextScript = (sal_uInt8)pBreakIt->GetBreakIter()->getScriptType( rInf.GetTxt(), nPos );
+
+ if( ASIAN == nNextScript )
+ {
+ LanguageType aLang =
+ rInf.GetTxtFrm()->GetTxtNode()->GetLang( nPos, 1, nNextScript );
+
+ if ( LANGUAGE_KOREAN != aLang && LANGUAGE_KOREAN_JOHAB != aLang )
+ ++nCnt;
+ }
+ }
+
+ return nCnt;
+}
+
+/*************************************************************************
+ * class SwTxtPortion
+ *************************************************************************/
+
+SwTxtPortion::SwTxtPortion( const SwLinePortion &rPortion )
+ : SwLinePortion( rPortion )
+{
+ SetWhichPor( POR_TXT );
+}
+
+/*************************************************************************
+ * SwTxtPortion::BreakCut()
+ *************************************************************************/
+
+void SwTxtPortion::BreakCut( SwTxtFormatInfo &rInf, const SwTxtGuess &rGuess )
+{
+ // Das Wort/Zeichen ist groesser als die Zeile
+ // Sonderfall Nr.1: Das Wort ist groesser als die Zeile
+ // Wir kappen...
+ const KSHORT nLineWidth = (KSHORT)(rInf.Width() - rInf.X());
+ xub_StrLen nLen = rGuess.CutPos() - rInf.GetIdx();
+ if( nLen )
+ {
+ // special case: guess does not always provide the correct
+ // width, only in common cases.
+ if ( !rGuess.BreakWidth() )
+ {
+ rInf.SetLen( nLen );
+ SetLen( nLen );
+ CalcTxtSize( rInf );
+
+ // changing these values requires also changing them in
+ // guess.cxx
+ KSHORT nItalic = 0;
+ if( ITALIC_NONE != rInf.GetFont()->GetItalic() && !rInf.NotEOL() )
+ {
+ nItalic = Height() / 12;
+ }
+ Width( Width() + nItalic );
+ }
+ else
+ {
+ Width( rGuess.BreakWidth() );
+ SetLen( nLen );
+ }
+ }
+ // special case: first character does not fit to line
+ else if ( rGuess.CutPos() == rInf.GetLineStart() )
+ {
+ SetLen( 1 );
+ Width( nLineWidth );
+ }
+ else
+ {
+ SetLen( 0 );
+ Width( 0 );
+ }
+}
+
+/*************************************************************************
+ * SwTxtPortion::BreakUnderflow()
+ *************************************************************************/
+
+void SwTxtPortion::BreakUnderflow( SwTxtFormatInfo &rInf )
+{
+ Truncate();
+ Height( 0 );
+ Width( 0 );
+ SetLen( 0 );
+ SetAscent( 0 );
+ rInf.SetUnderFlow( this );
+}
+
+ /*************************************************************************
+ * SwTxtPortion::_Format()
+ *************************************************************************/
+
+sal_Bool lcl_HasContent( const SwFldPortion& rFld, SwTxtFormatInfo &rInf )
+{
+ String aTxt;
+ return rFld.GetExpTxt( rInf, aTxt ) && aTxt.Len();
+}
+
+sal_Bool SwTxtPortion::_Format( SwTxtFormatInfo &rInf )
+{
+ // 5744: wenn nur der Trennstrich nicht mehr passt,
+ // muss trotzdem das Wort umgebrochen werden, ansonsten return sal_True!
+ if( rInf.IsUnderFlow() && rInf.GetSoftHyphPos() )
+ {
+ // soft hyphen portion has triggered an underflow event because
+ // of an alternative spelling position
+ sal_Bool bFull = sal_False;
+ const sal_Bool bHyph = rInf.ChgHyph( sal_True );
+ if( rInf.IsHyphenate() )
+ {
+ SwTxtGuess aGuess;
+ // check for alternative spelling left from the soft hyphen
+ // this should usually be true but
+ aGuess.AlternativeSpelling( rInf, rInf.GetSoftHyphPos() - 1 );
+ bFull = CreateHyphen( rInf, aGuess );
+ OSL_ENSURE( bFull, "Problem with hyphenation!!!" );
+ }
+ rInf.ChgHyph( bHyph );
+ rInf.SetSoftHyphPos( 0 );
+ return bFull;
+ }
+
+ SwTxtGuess aGuess;
+ const sal_Bool bFull = !aGuess.Guess( *this, rInf, Height() );
+
+ // these are the possible cases:
+ // A Portion fits to current line
+ // B Portion does not fit to current line but a possible line break
+ // within the portion has been found by the break iterator, 2 subcases
+ // B1 break is hyphen
+ // B2 break is word end
+ // C Portion does not fit to current line and no possible line break
+ // has been found by break iterator, 2 subcases:
+ // C1 break iterator found a possible line break in portion before us
+ // ==> this break is used (underflow)
+ // C2 break iterator does not found a possible line break at all:
+ // ==> line break
+
+ // case A: line not yet full
+ if ( !bFull )
+ {
+ Width( aGuess.BreakWidth() );
+ // Vorsicht !
+ if( !InExpGrp() || InFldGrp() )
+ SetLen( rInf.GetLen() );
+
+ short nKern = rInf.GetFont()->CheckKerning();
+ if( nKern > 0 && rInf.Width() < rInf.X() + Width() + nKern )
+ {
+ nKern = (short)(rInf.Width() - rInf.X() - Width() - 1);
+ if( nKern < 0 )
+ nKern = 0;
+ }
+ if( nKern )
+ new SwKernPortion( *this, nKern );
+ }
+ // special case: hanging portion
+ else if( bFull && aGuess.GetHangingPortion() )
+ {
+ Width( aGuess.BreakWidth() );
+ SetLen( aGuess.BreakPos() - rInf.GetIdx() );
+ Insert( aGuess.GetHangingPortion() );
+ aGuess.GetHangingPortion()->SetAscent( GetAscent() );
+ aGuess.ClearHangingPortion();
+ }
+ // breakPos >= index
+ else if ( aGuess.BreakPos() >= rInf.GetIdx() && aGuess.BreakPos() != STRING_LEN )
+ {
+ // case B1
+ if( aGuess.HyphWord().is() && aGuess.BreakPos() > rInf.GetLineStart()
+ && ( aGuess.BreakPos() > rInf.GetIdx() ||
+ ( rInf.GetLast() && ! rInf.GetLast()->IsFlyPortion() ) ) )
+ {
+ CreateHyphen( rInf, aGuess );
+ if ( rInf.GetFly() )
+ rInf.GetRoot()->SetMidHyph( sal_True );
+ else
+ rInf.GetRoot()->SetEndHyph( sal_True );
+ }
+ // case C1
+ // - Footnote portions with fake line start (i.e., not at beginning of line)
+ // should keep together with the text portion. (Note: no keep together
+ // with only footnote portions.
+ // - TabPortions not at beginning of line should keep together with the
+ // text portion, if they are not followed by a blank
+ // (work around different definition of tab stop character - breaking or
+ // non breaking character - in compatibility mode)
+ else if ( ( IsFtnPortion() && rInf.IsFakeLineStart() &&
+ // --> OD 2010-01-29 #b6921213#
+ rInf.IsOtherThanFtnInside() ) ||
+ // <--
+ ( rInf.GetLast() &&
+ rInf.GetTxtFrm()->GetTxtNode()->getIDocumentSettingAccess()->get(IDocumentSettingAccess::TAB_COMPAT) &&
+ rInf.GetLast()->InTabGrp() &&
+ rInf.GetLineStart() + rInf.GetLast()->GetLen() < rInf.GetIdx() &&
+ aGuess.BreakPos() == rInf.GetIdx() &&
+ CH_BLANK != rInf.GetChar( rInf.GetIdx() ) &&
+ 0x3000 != rInf.GetChar( rInf.GetIdx() ) ) )
+ BreakUnderflow( rInf );
+ // case B2
+ else if( rInf.GetIdx() > rInf.GetLineStart() ||
+ aGuess.BreakPos() > rInf.GetIdx() ||
+ // this is weird: during formatting the follow of a field
+ // the values rInf.GetIdx and rInf.GetLineStart are replaced
+ // IsFakeLineStart indicates GetIdx > GetLineStart
+ rInf.IsFakeLineStart() ||
+ rInf.GetFly() ||
+ rInf.IsFirstMulti() ||
+ ( rInf.GetLast() &&
+ ( rInf.GetLast()->IsFlyPortion() ||
+ ( rInf.GetLast()->InFldGrp() &&
+ ! rInf.GetLast()->InNumberGrp() &&
+ ! rInf.GetLast()->IsErgoSumPortion() &&
+ lcl_HasContent(*((SwFldPortion*)rInf.GetLast()),rInf ) ) ) ) )
+ {
+ if ( rInf.X() + aGuess.BreakWidth() <= rInf.Width() )
+ Width( aGuess.BreakWidth() );
+ else
+ // this actually should not happen
+ Width( KSHORT(rInf.Width() - rInf.X()) );
+
+ SetLen( aGuess.BreakPos() - rInf.GetIdx() );
+
+ OSL_ENSURE( aGuess.BreakStart() >= aGuess.FieldDiff(),
+ "Trouble with expanded field portions during line break" );
+ const xub_StrLen nRealStart = aGuess.BreakStart() - aGuess.FieldDiff();
+ if( aGuess.BreakPos() < nRealStart && !InExpGrp() )
+ {
+ SwHolePortion *pNew = new SwHolePortion( *this );
+ pNew->SetLen( nRealStart - aGuess.BreakPos() );
+ Insert( pNew );
+ }
+ }
+ else // case C2, last exit
+ BreakCut( rInf, aGuess );
+ }
+ // breakPos < index or no breakpos at all
+ else
+ {
+ sal_Bool bFirstPor = rInf.GetLineStart() == rInf.GetIdx();
+ if( aGuess.BreakPos() != STRING_LEN &&
+ aGuess.BreakPos() != rInf.GetLineStart() &&
+ ( !bFirstPor || rInf.GetFly() || rInf.GetLast()->IsFlyPortion() ||
+ rInf.IsFirstMulti() ) &&
+ ( !rInf.GetLast()->IsBlankPortion() || ((SwBlankPortion*)
+ rInf.GetLast())->MayUnderFlow( rInf, rInf.GetIdx()-1, sal_True )))
+ { // case C1 (former BreakUnderflow())
+ BreakUnderflow( rInf );
+ }
+ else
+ // case C2, last exit
+ BreakCut( rInf, aGuess );
+ }
+
+ return bFull;
+}
+
+/*************************************************************************
+ * virtual SwTxtPortion::Format()
+ *************************************************************************/
+
+
+
+sal_Bool SwTxtPortion::Format( SwTxtFormatInfo &rInf )
+{
+#if OSL_DEBUG_LEVEL > 1
+ const XubString aDbgTxt( rInf.GetTxt().Copy( rInf.GetIdx(), rInf.GetLen() ) );
+#endif
+
+ if( rInf.X() > rInf.Width() || (!GetLen() && !InExpGrp()) )
+ {
+ Height( 0 );
+ Width( 0 );
+ SetLen( 0 );
+ SetAscent( 0 );
+ SetPortion( NULL ); // ????
+ return sal_True;
+ }
+
+ OSL_ENSURE( rInf.RealWidth() || (rInf.X() == rInf.Width()),
+ "SwTxtPortion::Format: missing real width" );
+ OSL_ENSURE( Height(), "SwTxtPortion::Format: missing height" );
+
+ return _Format( rInf );
+}
+
+/*************************************************************************
+ * virtual SwTxtPortion::FormatEOL()
+ *************************************************************************/
+
+// Format end of line
+// 5083: Es kann schon manchmal unguenstige Faelle geben...
+// "vom {Nikolaus}", Nikolaus bricht um "vom " wird im Blocksatz
+// zu "vom" und " ", wobei der Glue expandiert wird, statt in die
+// MarginPortion aufzugehen.
+// rInf.nIdx steht auf dem naechsten Wort, nIdx-1 ist der letzte
+// Buchstabe der Portion.
+
+
+
+void SwTxtPortion::FormatEOL( SwTxtFormatInfo &rInf )
+{
+ if( ( !GetPortion() || ( GetPortion()->IsKernPortion() &&
+ !GetPortion()->GetPortion() ) ) && GetLen() &&
+ rInf.GetIdx() < rInf.GetTxt().Len() &&
+ 1 < rInf.GetIdx() && ' ' == rInf.GetChar( rInf.GetIdx() - 1 )
+ && !rInf.GetLast()->IsHolePortion() )
+ {
+ // calculate number of blanks
+ xub_StrLen nX = rInf.GetIdx() - 1;
+ sal_uInt16 nHoleLen = 1;
+ while( nX && nHoleLen < GetLen() && CH_BLANK == rInf.GetChar( --nX ) )
+ nHoleLen++;
+
+ // Erst uns einstellen und dann Inserten, weil wir ja auch ein
+ // SwLineLayout sein koennten.
+ KSHORT nBlankSize;
+ if( nHoleLen == GetLen() )
+ nBlankSize = Width();
+ else
+ nBlankSize = nHoleLen * rInf.GetTxtSize( ' ' ).Width();
+ Width( Width() - nBlankSize );
+ rInf.X( rInf.X() - nBlankSize );
+ SetLen( GetLen() - nHoleLen );
+ SwLinePortion *pHole = new SwHolePortion( *this );
+ ( (SwHolePortion *)pHole )->SetBlankWidth( nBlankSize );
+ ( (SwHolePortion *)pHole )->SetLen( nHoleLen );
+ Insert( pHole );
+ }
+}
+
+/*************************************************************************
+ * virtual SwTxtPortion::GetCrsrOfst()
+ *************************************************************************/
+
+
+
+xub_StrLen SwTxtPortion::GetCrsrOfst( const KSHORT nOfst ) const
+{
+ OSL_ENSURE( !this, "SwTxtPortion::GetCrsrOfst: don't use this method!" );
+ return SwLinePortion::GetCrsrOfst( nOfst );
+}
+
+/*************************************************************************
+ * virtual SwTxtPortion::GetTxtSize()
+ *************************************************************************/
+// Das GetTxtSize() geht davon aus, dass die eigene Laenge korrekt ist
+
+SwPosSize SwTxtPortion::GetTxtSize( const SwTxtSizeInfo &rInf ) const
+{
+ return rInf.GetTxtSize();
+}
+
+/*************************************************************************
+ * virtual SwTxtPortion::Paint()
+ *************************************************************************/
+
+
+
+void SwTxtPortion::Paint( const SwTxtPaintInfo &rInf ) const
+{
+ if (rInf.OnWin() && 1==rInf.GetLen() && CH_TXT_ATR_FIELDEND==rInf.GetTxt().GetChar(rInf.GetIdx()))
+ {
+ rInf.DrawBackBrush( *this );
+ const XubString aTxt = XubString::CreateFromAscii(CH_TXT_ATR_SUBST_FIELDEND);
+ rInf.DrawText( aTxt, *this, 0, aTxt.Len(), false );
+ }
+ else if (rInf.OnWin() && 1==rInf.GetLen() && CH_TXT_ATR_FIELDSTART==rInf.GetTxt().GetChar(rInf.GetIdx()))
+ {
+ rInf.DrawBackBrush( *this );
+ const XubString aTxt = XubString::CreateFromAscii(CH_TXT_ATR_SUBST_FIELDSTART);
+ rInf.DrawText( aTxt, *this, 0, aTxt.Len(), false );
+ }
+ else if( GetLen() )
+ {
+ rInf.DrawBackBrush( *this );
+
+ // do we have to repaint a post it portion?
+ if( rInf.OnWin() && pPortion && !pPortion->Width() )
+ pPortion->PrePaint( rInf, this );
+
+ const SwWrongList *pWrongList = rInf.GetpWrongList();
+ const SwWrongList *pGrammarCheckList = rInf.GetGrammarCheckList();
+ // SMARTTAGS
+ const SwWrongList *pSmarttags = rInf.GetSmartTags();
+
+ const bool bWrong = 0 != pWrongList;
+ const bool bGrammarCheck = 0 != pGrammarCheckList;
+ const bool bSmartTags = 0 != pSmarttags;
+
+ if ( bWrong || bSmartTags || bGrammarCheck )
+ rInf.DrawMarkedText( *this, rInf.GetLen(), sal_False, bWrong, bSmartTags, bGrammarCheck );
+ else
+ rInf.DrawText( *this, rInf.GetLen(), sal_False );
+ }
+}
+
+/*************************************************************************
+ * virtual SwTxtPortion::GetExpTxt()
+ *************************************************************************/
+
+
+
+sal_Bool SwTxtPortion::GetExpTxt( const SwTxtSizeInfo &, XubString & ) const
+{
+ return sal_False;
+}
+
+/*************************************************************************
+ * xub_StrLen SwTxtPortion::GetSpaceCnt()
+ * long SwTxtPortion::CalcSpacing()
+ * sind fuer den Blocksatz zustaendig und ermitteln die Anzahl der Blanks
+ * und den daraus resultierenden zusaetzlichen Zwischenraum
+ *************************************************************************/
+
+xub_StrLen SwTxtPortion::GetSpaceCnt( const SwTxtSizeInfo &rInf,
+ xub_StrLen& rCharCnt ) const
+{
+ xub_StrLen nCnt = 0;
+ xub_StrLen nPos = 0;
+ if ( InExpGrp() )
+ {
+ if( !IsBlankPortion() && !InNumberGrp() && !IsCombinedPortion() )
+ {
+ // Bei OnWin() wird anstatt eines Leerstrings gern mal ein Blank
+ // zurueckgeliefert, das koennen wir hier aber gar nicht gebrauchen
+ sal_Bool bOldOnWin = rInf.OnWin();
+ ((SwTxtSizeInfo &)rInf).SetOnWin( sal_False );
+
+ XubString aStr( aEmptyStr );
+ GetExpTxt( rInf, aStr );
+ ((SwTxtSizeInfo &)rInf).SetOnWin( bOldOnWin );
+
+ nCnt = nCnt + lcl_AddSpace( rInf, &aStr, *this );
+ nPos = aStr.Len();
+ }
+ }
+ else if( !IsDropPortion() )
+ {
+ nCnt = nCnt + lcl_AddSpace( rInf, 0, *this );
+ nPos = GetLen();
+ }
+ rCharCnt = rCharCnt + nPos;
+ return nCnt;
+}
+
+long SwTxtPortion::CalcSpacing( long nSpaceAdd, const SwTxtSizeInfo &rInf ) const
+{
+ xub_StrLen nCnt = 0;
+
+ if ( InExpGrp() )
+ {
+ if( !IsBlankPortion() && !InNumberGrp() && !IsCombinedPortion() )
+ {
+ // Bei OnWin() wird anstatt eines Leerstrings gern mal ein Blank
+ // zurueckgeliefert, das koennen wir hier aber gar nicht gebrauchen
+ sal_Bool bOldOnWin = rInf.OnWin();
+ ((SwTxtSizeInfo &)rInf).SetOnWin( sal_False );
+
+ XubString aStr( aEmptyStr );
+ GetExpTxt( rInf, aStr );
+ ((SwTxtSizeInfo &)rInf).SetOnWin( bOldOnWin );
+ if( nSpaceAdd > 0 )
+ nCnt = nCnt + lcl_AddSpace( rInf, &aStr, *this );
+ else
+ {
+ nSpaceAdd = -nSpaceAdd;
+ nCnt = aStr.Len();
+ }
+ }
+ }
+ else if( !IsDropPortion() )
+ {
+ if( nSpaceAdd > 0 )
+ nCnt = nCnt + lcl_AddSpace( rInf, 0, *this );
+ else
+ {
+ nSpaceAdd = -nSpaceAdd;
+ nCnt = GetLen();
+ SwLinePortion* pPor = GetPortion();
+
+ // we do not want an extra space in front of margin portions
+ if ( nCnt )
+ {
+ while ( pPor && !pPor->Width() && ! pPor->IsHolePortion() )
+ pPor = pPor->GetPortion();
+
+ if ( !pPor || pPor->InFixMargGrp() || pPor->IsHolePortion() )
+ --nCnt;
+ }
+ }
+ }
+
+ return nCnt * nSpaceAdd / SPACING_PRECISION_FACTOR;
+}
+
+/*************************************************************************
+ * virtual SwTxtPortion::HandlePortion()
+ *************************************************************************/
+
+void SwTxtPortion::HandlePortion( SwPortionHandler& rPH ) const
+{
+ rPH.Text( GetLen(), GetWhichPor() );
+}
+
+/*************************************************************************
+ * class SwHolePortion
+ *************************************************************************/
+
+
+
+SwHolePortion::SwHolePortion( const SwTxtPortion &rPor )
+ : nBlankWidth( 0 )
+{
+ SetLen( 1 );
+ Height( rPor.Height() );
+ SetAscent( rPor.GetAscent() );
+ SetWhichPor( POR_HOLE );
+}
+
+SwLinePortion *SwHolePortion::Compress() { return this; }
+
+/*************************************************************************
+ * virtual SwHolePortion::Paint()
+ *************************************************************************/
+
+
+
+void SwHolePortion::Paint( const SwTxtPaintInfo &rInf ) const
+{
+ // --> FME 2004-06-24 #i16816# tagged pdf support
+ if( rInf.GetVsh() && rInf.GetVsh()->GetViewOptions()->IsPDFExport() )
+ {
+ const XubString aTxt( ' ' );
+ rInf.DrawText( aTxt, *this, 0, 1, false );
+ }
+ // <--
+}
+
+/*************************************************************************
+ * virtual SwHolePortion::Format()
+ *************************************************************************/
+
+
+
+sal_Bool SwHolePortion::Format( SwTxtFormatInfo &rInf )
+{
+ return rInf.IsFull() || rInf.X() >= rInf.Width();
+}
+
+/*************************************************************************
+ * virtual SwHolePortion::HandlePortion()
+ *************************************************************************/
+
+void SwHolePortion::HandlePortion( SwPortionHandler& rPH ) const
+{
+ rPH.Text( GetLen(), GetWhichPor() );
+}
+
+void SwFieldMarkPortion::Paint( const SwTxtPaintInfo & /*rInf*/) const
+{
+ // These shouldn't be painted!
+ // SwTxtPortion::Paint(rInf);
+}
+
+sal_Bool SwFieldMarkPortion::Format( SwTxtFormatInfo & )
+{
+ sal_Bool ret=0;
+ Width(0);
+ return ret;
+}
+
+namespace {
+ static sal_Int32 getCurrentListIndex( IFieldmark* pBM,
+ ::rtl::OUString* io_pCurrentText = NULL )
+ {
+ const IFieldmark::parameter_map_t* const pParameters = pBM->GetParameters();
+ sal_Int32 nCurrentIdx = 0;
+ const IFieldmark::parameter_map_t::const_iterator pResult = pParameters->find(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(ODF_FORMDROPDOWN_RESULT)));
+ if(pResult != pParameters->end())
+ pResult->second >>= nCurrentIdx;
+ if(io_pCurrentText)
+ {
+ const IFieldmark::parameter_map_t::const_iterator pListEntries = pParameters->find(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(ODF_FORMDROPDOWN_LISTENTRY)));
+ if(pListEntries != pParameters->end())
+ {
+ uno::Sequence< ::rtl::OUString > vListEntries;
+ pListEntries->second >>= vListEntries;
+ if(nCurrentIdx < vListEntries.getLength())
+ *io_pCurrentText = vListEntries[nCurrentIdx];
+ }
+ }
+ return nCurrentIdx;
+ }
+}
+
+//FIXME Fieldbk
+void SwFieldFormPortion::Paint( const SwTxtPaintInfo& rInf ) const
+{
+ SwTxtNode* pNd = const_cast<SwTxtNode*>(rInf.GetTxtFrm()->GetTxtNode());
+ const SwDoc *doc=pNd->GetDoc();
+ SwIndex aIndex( pNd, rInf.GetIdx() );
+ SwPosition aPosition(*pNd, aIndex);
+
+ IFieldmark* pBM = doc->getIDocumentMarkAccess( )->getFieldmarkFor( aPosition );
+
+ OSL_ENSURE( pBM,
+ "SwFieldFormPortion::Paint(..)"
+ " - Where is my form field bookmark???");
+
+ if ( pBM != NULL )
+ {
+ if ( pBM->GetFieldname( ).equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( ODF_FORMCHECKBOX ) ) )
+ { // a checkbox...
+ ICheckboxFieldmark* pCheckboxFm = reinterpret_cast< ICheckboxFieldmark* >(pBM);
+ bool checked = pCheckboxFm->IsChecked();
+ rInf.DrawCheckBox(*this, checked);
+ }
+ else if ( pBM->GetFieldname( ).equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( ODF_FORMDROPDOWN ) ) )
+ { // a list...
+ rtl::OUString aTxt;
+ getCurrentListIndex( pBM, &aTxt );
+ rInf.DrawViewOpt( *this, POR_FLD );
+ rInf.DrawText( aTxt, *this, 0, aTxt.getLength(), false );
+ }
+ else
+ {
+ assert(0); // unknown type...
+ }
+ }
+}
+
+sal_Bool SwFieldFormPortion::Format( SwTxtFormatInfo & rInf )
+{
+ sal_Bool ret = 0;
+ SwTxtNode *pNd = const_cast < SwTxtNode * >( rInf.GetTxtFrm( )->GetTxtNode( ) );
+ const SwDoc *doc = pNd->GetDoc( );
+ SwIndex aIndex( pNd, rInf.GetIdx( ) );
+ SwPosition aPosition( *pNd, aIndex );
+ IFieldmark *pBM = doc->getIDocumentMarkAccess( )->getFieldmarkFor( aPosition );
+ OSL_ENSURE( pBM != NULL, "Where is my form field bookmark???" );
+ if ( pBM != NULL )
+ {
+ if ( pBM->GetFieldname( ).equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( ODF_FORMCHECKBOX ) ) )
+ {
+ Width( rInf.GetTxtHeight( ) );
+ Height( rInf.GetTxtHeight( ) );
+ SetAscent( rInf.GetAscent( ) );
+ }
+ else if ( pBM->GetFieldname( ).equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( ODF_FORMDROPDOWN ) ) )
+ {
+ ::rtl::OUString aTxt;
+ getCurrentListIndex( pBM, &aTxt );
+ SwPosSize aPosSize = rInf.GetTxtSize( aTxt );
+ Width( aPosSize.Width( ) );
+ Height( aPosSize.Height( ) );
+ SetAscent( rInf.GetAscent( ) );
+ }
+ else
+ {
+ assert( 0 ); // unknown type...
+ }
+ }
+ return ret;
+}
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/text/portxt.hxx b/sw/source/core/text/portxt.hxx
new file mode 100644
index 000000000000..8a201cf1f87e
--- /dev/null
+++ b/sw/source/core/text/portxt.hxx
@@ -0,0 +1,124 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+#ifndef _PORTXT_HXX
+#define _PORTXT_HXX
+#ifdef GCC
+#include <sys/types.h>
+#else
+#include <new.h> //fuer size_t, FIXEDMEM aus tools
+#endif
+#include <tools/mempool.hxx>
+
+#include "porlin.hxx"
+
+class SwTxtGuess;
+
+/*************************************************************************
+ * class SwTxtPortion
+ *************************************************************************/
+
+class SwTxtPortion : public SwLinePortion
+{
+ void BreakCut( SwTxtFormatInfo &rInf, const SwTxtGuess &rGuess );
+ void BreakUnderflow( SwTxtFormatInfo &rInf );
+ sal_Bool _Format( SwTxtFormatInfo &rInf );
+
+public:
+ inline SwTxtPortion(){ SetWhichPor( POR_TXT ); }
+ SwTxtPortion( const SwLinePortion &rPortion );
+ virtual void Paint( const SwTxtPaintInfo &rInf ) const;
+ virtual sal_Bool Format( SwTxtFormatInfo &rInf );
+ virtual void FormatEOL( SwTxtFormatInfo &rInf );
+ virtual xub_StrLen GetCrsrOfst( const KSHORT nOfst ) const;
+ virtual SwPosSize GetTxtSize( const SwTxtSizeInfo &rInfo ) const;
+ virtual sal_Bool GetExpTxt( const SwTxtSizeInfo &rInf, XubString &rTxt ) const;
+ virtual long CalcSpacing( long nSpaceAdd, const SwTxtSizeInfo &rInf ) const;
+
+ // zaehlt die Spaces fuer Blocksatz
+ xub_StrLen GetSpaceCnt( const SwTxtSizeInfo &rInf, xub_StrLen& rCnt ) const;
+
+ sal_Bool CreateHyphen( SwTxtFormatInfo &rInf, SwTxtGuess &rGuess );
+
+ // Accessibility: pass information about this portion to the PortionHandler
+ virtual void HandlePortion( SwPortionHandler& rPH ) const;
+
+#if OSL_DEBUG_LEVEL > 1
+ void dumpPortionAsXml(sal_uInt16 ofs, String& aText, xmlTextWriter* writer);
+#endif
+
+ OUTPUT_OPERATOR
+ DECL_FIXEDMEMPOOL_NEWDEL(SwTxtPortion)
+};
+
+/*************************************************************************
+ * class SwHolePortion
+ *************************************************************************/
+
+class SwHolePortion : public SwLinePortion
+{
+ KSHORT nBlankWidth;
+public:
+ SwHolePortion( const SwTxtPortion &rPor );
+ inline KSHORT GetBlankWidth( ) const { return nBlankWidth; }
+ inline void SetBlankWidth( const KSHORT nNew ) { nBlankWidth = nNew; }
+ virtual SwLinePortion *Compress();
+ virtual sal_Bool Format( SwTxtFormatInfo &rInf );
+ virtual void Paint( const SwTxtPaintInfo &rInf ) const;
+
+ // Accessibility: pass information about this portion to the PortionHandler
+ virtual void HandlePortion( SwPortionHandler& rPH ) const;
+
+ OUTPUT_OPERATOR
+ DECL_FIXEDMEMPOOL_NEWDEL(SwHolePortion)
+};
+
+class SwFieldMarkPortion : public SwTxtPortion
+{
+ public:
+ inline SwFieldMarkPortion() : SwTxtPortion()
+ { }
+ virtual void Paint( const SwTxtPaintInfo &rInf ) const;
+ virtual sal_Bool Format( SwTxtFormatInfo &rInf );
+};
+
+class SwFieldFormPortion : public SwTxtPortion
+{
+ public:
+ inline SwFieldFormPortion() : SwTxtPortion()
+ { }
+ virtual void Paint( const SwTxtPaintInfo &rInf ) const;
+ virtual sal_Bool Format( SwTxtFormatInfo &rInf );
+};
+
+
+CLASSIO( SwTxtPortion )
+CLASSIO( SwHolePortion )
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/text/possiz.hxx b/sw/source/core/text/possiz.hxx
new file mode 100644
index 000000000000..c97d122da2ff
--- /dev/null
+++ b/sw/source/core/text/possiz.hxx
@@ -0,0 +1,86 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+#ifndef _POSSIZ_HXX
+#define _POSSIZ_HXX
+
+
+#include <tools/gen.hxx>
+#include "txttypes.hxx"
+
+// Im Gegensazt zu den SV-Sizes ist die SwPosSize immer positiv
+class SwPosSize
+{
+ KSHORT nWidth;
+ KSHORT nHeight;
+public:
+ inline SwPosSize( const KSHORT nW = 0, const KSHORT nH = 0 )
+ : nWidth(nW), nHeight(nH) { }
+ inline SwPosSize( const Size &rSize )
+ : nWidth(KSHORT(rSize.Width())), nHeight(KSHORT(rSize.Height())){ }
+ inline KSHORT Height() const { return nHeight; }
+ inline void Height( const KSHORT nNew ) { nHeight = nNew; }
+ inline KSHORT Width() const { return nWidth; }
+ inline void Width( const KSHORT nNew ) { nWidth = nNew; }
+
+ inline Size SvLSize() const { return Size( nWidth, nHeight ); }
+ inline void SvLSize( const Size &rSize );
+ inline void SvXSize( const Size &rSize );
+ inline SwPosSize &operator=( const SwPosSize &rSize );
+ inline SwPosSize &operator=( const Size &rSize );
+};
+
+inline SwPosSize &SwPosSize::operator=(const SwPosSize &rSize )
+{
+ nWidth = rSize.Width();
+ nHeight = rSize.Height();
+ return *this;
+}
+
+inline void SwPosSize::SvLSize( const Size &rSize )
+{
+ nWidth = KSHORT(rSize.Width());
+ nHeight = KSHORT(rSize.Height());
+}
+
+inline void SwPosSize::SvXSize( const Size &rSize )
+{
+ nHeight = KSHORT(rSize.Width());
+ nWidth = KSHORT(rSize.Height());
+}
+
+inline SwPosSize &SwPosSize::operator=( const Size &rSize )
+{
+ nWidth = KSHORT(rSize.Width());
+ nHeight = KSHORT(rSize.Height());
+ return *this;
+}
+
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/text/redlnitr.cxx b/sw/source/core/text/redlnitr.cxx
new file mode 100644
index 000000000000..441077728afe
--- /dev/null
+++ b/sw/source/core/text/redlnitr.cxx
@@ -0,0 +1,504 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+
+#include "hintids.hxx"
+#include <svl/whiter.hxx>
+#include <tools/shl.hxx>
+#include <com/sun/star/i18n/ScriptType.hdl>
+#include <swmodule.hxx>
+#include <redline.hxx> // SwRedline
+#include <txtatr.hxx> // SwTxt ...
+#include <docary.hxx> // SwRedlineTbl
+#include <itratr.hxx> // SwAttrIter
+#include <ndtxt.hxx> // SwTxtNode
+#include <doc.hxx> // SwDoc
+#include <rootfrm.hxx>
+#include <breakit.hxx>
+#include <vcl/keycodes.hxx>
+#include <vcl/cmdevt.hxx>
+#include <vcl/settings.hxx>
+#include <txtfrm.hxx> // SwTxtFrm
+#include <vcl/svapp.hxx>
+#include <redlnitr.hxx>
+#include <extinput.hxx>
+#include <sfx2/printer.hxx>
+#include <vcl/window.hxx>
+
+using namespace ::com::sun::star;
+
+/*************************************************************************
+ * SwAttrIter::CtorInitAttrIter()
+ *************************************************************************/
+void SwAttrIter::CtorInitAttrIter( SwTxtNode& rTxtNode, SwScriptInfo& rScrInf, SwTxtFrm* pFrm )
+{
+ // Beim HTML-Import kann es vorkommen, dass kein Layout existiert.
+ SwRootFrm* pRootFrm = rTxtNode.getIDocumentLayoutAccess()->GetCurrentLayout();
+ pShell = pRootFrm ? pRootFrm->GetCurrShell() : 0; //swmod 080218
+
+ pScriptInfo = &rScrInf;
+
+ // attributes set at the whole paragraph
+ pAttrSet = rTxtNode.GetpSwAttrSet();
+ // attribute array
+ pHints = rTxtNode.GetpSwpHints();
+
+ // Build a font matching the default paragraph style:
+ SwFontAccess aFontAccess( &rTxtNode.GetAnyFmtColl(), pShell );
+ delete pFnt;
+ pFnt = new SwFont( *aFontAccess.Get()->GetFont() );
+
+ // set font to vertical if frame layout is vertical
+ sal_Bool bVertLayout = sal_False;
+ sal_Bool bRTL = sal_False;
+ if ( pFrm )
+ {
+ if ( pFrm->IsVertical() )
+ {
+ bVertLayout = sal_True;
+ pFnt->SetVertical( pFnt->GetOrientation(), sal_True );
+ }
+ bRTL = pFrm->IsRightToLeft();
+ }
+
+ // Initialize the default attribute of the attribute handler
+ // based on the attribute array cached together with the font.
+ // If any further attributes for the paragraph are given in pAttrSet
+ // consider them during construction of the default array, and apply
+ // them to the font
+ aAttrHandler.Init( aFontAccess.Get()->GetDefault(), pAttrSet,
+ *rTxtNode.getIDocumentSettingAccess(), pShell, *pFnt, bVertLayout );
+
+ aMagicNo[SW_LATIN] = aMagicNo[SW_CJK] = aMagicNo[SW_CTL] = NULL;
+
+ // determine script changes if not already done for current paragraph
+ OSL_ENSURE( pScriptInfo, "No script info available");
+ if ( pScriptInfo->GetInvalidity() != STRING_LEN )
+ pScriptInfo->InitScriptInfo( rTxtNode, bRTL );
+
+ if ( pBreakIt->GetBreakIter().is() )
+ {
+ pFnt->SetActual( SwScriptInfo::WhichFont( 0, 0, pScriptInfo ) );
+
+ xub_StrLen nChg = 0;
+ sal_uInt16 nCnt = 0;
+
+ do
+ {
+ nChg = pScriptInfo->GetScriptChg( nCnt );
+ sal_uInt16 nScript = pScriptInfo->GetScriptType( nCnt++ );
+ sal_uInt8 nTmp = 4;
+ switch ( nScript ) {
+ case i18n::ScriptType::ASIAN :
+ if( !aMagicNo[SW_CJK] ) nTmp = SW_CJK; break;
+ case i18n::ScriptType::COMPLEX :
+ if( !aMagicNo[SW_CTL] ) nTmp = SW_CTL; break;
+ default:
+ if( !aMagicNo[SW_LATIN ] ) nTmp = SW_LATIN;
+ }
+ if( nTmp < 4 )
+ {
+ pFnt->ChkMagic( pShell, nTmp );
+ pFnt->GetMagic( aMagicNo[ nTmp ], aFntIdx[ nTmp ], nTmp );
+ }
+ } while( nChg < rTxtNode.GetTxt().Len() );
+ }
+ else
+ {
+ pFnt->ChkMagic( pShell, SW_LATIN );
+ pFnt->GetMagic( aMagicNo[ SW_LATIN ], aFntIdx[ SW_LATIN ], SW_LATIN );
+ }
+
+ nStartIndex = nEndIndex = nPos = nChgCnt = 0;
+ nPropFont = 0;
+ SwDoc* pDoc = rTxtNode.GetDoc();
+ const IDocumentRedlineAccess* pIDRA = rTxtNode.getIDocumentRedlineAccess();
+
+ const SwExtTextInput* pExtInp = pDoc->GetExtTextInput( rTxtNode );
+ const bool bShow = IDocumentRedlineAccess::IsShowChanges( pIDRA->GetRedlineMode() );
+ if( pExtInp || bShow )
+ {
+ MSHORT nRedlPos = pIDRA->GetRedlinePos( rTxtNode, USHRT_MAX );
+ if( pExtInp || MSHRT_MAX != nRedlPos )
+ {
+ const SvUShorts* pArr = 0;
+ xub_StrLen nInputStt = 0;
+ if( pExtInp )
+ {
+ pArr = &pExtInp->GetAttrs();
+ nInputStt = pExtInp->Start()->nContent.GetIndex();
+ Seek( 0 );
+ }
+
+ pRedln = new SwRedlineItr( rTxtNode, *pFnt, aAttrHandler, nRedlPos,
+ bShow, pArr, nInputStt );
+
+ if( pRedln->IsOn() )
+ ++nChgCnt;
+ }
+ }
+}
+
+/*************************************************************************
+ * SwRedlineItr - Der Redline-Iterator
+ *
+ * Folgende Informationen/Zustaende gibt es im RedlineIterator:
+ *
+ * nFirst ist der erste Index der RedlineTbl, der mit dem Absatz ueberlappt.
+ *
+ * nAct ist der zur Zeit aktive ( wenn bOn gesetzt ist ) oder der naechste
+ * in Frage kommende Index.
+ * nStart und nEnd geben die Grenzen des Objekts innerhalb des Absatzes an.
+ *
+ * Wenn bOn gesetzt ist, ist der Font entsprechend manipuliert worden.
+ *
+ * Wenn nAct auf MSHRT_MAX gesetzt wurde ( durch Reset() ), so ist zur Zeit
+ * kein Redline aktiv, nStart und nEnd sind invalid.
+ *************************************************************************/
+
+SwRedlineItr::SwRedlineItr( const SwTxtNode& rTxtNd, SwFont& rFnt,
+ SwAttrHandler& rAH, MSHORT nRed, sal_Bool bShw, const SvUShorts *pArr,
+ xub_StrLen nExtStart )
+ : rDoc( *rTxtNd.GetDoc() ), rNd( rTxtNd ), rAttrHandler( rAH ), pSet( 0 ),
+ nNdIdx( rTxtNd.GetIndex() ), nFirst( nRed ),
+ nAct( MSHRT_MAX ), bOn( sal_False ), bShow( bShw )
+{
+ if( pArr )
+ pExt = new SwExtend( *pArr, nExtStart );
+ else
+ pExt = NULL;
+ Seek( rFnt, 0, STRING_LEN );
+}
+
+SwRedlineItr::~SwRedlineItr()
+{
+ Clear( NULL );
+ delete pSet;
+ delete pExt;
+}
+
+// Der Return-Wert von SwRedlineItr::Seek gibt an, ob der aktuelle Font
+// veraendert wurde durch Verlassen (-1) oder Betreten eines Bereichs (+1)
+
+short SwRedlineItr::_Seek( SwFont& rFnt, xub_StrLen nNew, xub_StrLen nOld )
+{
+ short nRet = 0;
+ if( ExtOn() )
+ return 0; // Abkuerzung: wenn wir innerhalb eines ExtendTextInputs sind
+ // kann es keine anderen Attributwechsel (auch nicht durch Redlining) geben
+ if( bShow )
+ {
+ if( bOn )
+ {
+ if( nNew >= nEnd )
+ {
+ --nRet;
+ _Clear( &rFnt ); // Wir gehen hinter den aktuellen Bereich
+ ++nAct; // und pruefen gleich den naechsten
+ }
+ else if( nNew < nStart )
+ {
+ --nRet;
+ _Clear( &rFnt ); // Wir gehen vor den aktuellen Bereich
+ if( nAct > nFirst )
+ nAct = nFirst; // Die Pruefung muss von vorne beginnen
+ else
+ return nRet + EnterExtend( rFnt, nNew ); // Es gibt keinen vor uns.
+ }
+ else
+ return nRet + EnterExtend( rFnt, nNew ); // Wir sind im gleichen Bereich geblieben.
+ }
+ if( MSHRT_MAX == nAct || nOld > nNew )
+ nAct = nFirst;
+
+ nStart = STRING_LEN;
+ nEnd = STRING_LEN;
+
+ for( ; nAct < rDoc.GetRedlineTbl().Count() ; ++nAct )
+ {
+ rDoc.GetRedlineTbl()[ nAct ]->CalcStartEnd( nNdIdx, nStart, nEnd );
+
+ if( nNew < nEnd )
+ {
+ if( nNew >= nStart ) // der einzig moegliche Kandidat
+ {
+ bOn = sal_True;
+ const SwRedline *pRed = rDoc.GetRedlineTbl()[ nAct ];
+
+ if (pSet)
+ pSet->ClearItem();
+ else
+ {
+ SwAttrPool& rPool =
+ const_cast<SwDoc&>(rDoc).GetAttrPool();
+ pSet = new SfxItemSet(rPool, RES_CHRATR_BEGIN, RES_CHRATR_END-1);
+ }
+
+ if( 1 < pRed->GetStackCount() )
+ FillHints( pRed->GetAuthor( 1 ), pRed->GetType( 1 ) );
+ FillHints( pRed->GetAuthor(), pRed->GetType() );
+
+ SfxWhichIter aIter( *pSet );
+ MSHORT nWhich = aIter.FirstWhich();
+ while( nWhich )
+ {
+ const SfxPoolItem* pItem;
+ if( ( nWhich < RES_CHRATR_END ) &&
+ ( SFX_ITEM_SET == pSet->GetItemState( nWhich, sal_True, &pItem ) ) )
+ {
+ SwTxtAttr* pAttr = MakeRedlineTxtAttr(
+ const_cast<SwDoc&>(rDoc),
+ *const_cast<SfxPoolItem*>(pItem) );
+ pAttr->SetPriorityAttr( sal_True );
+ aHints.C40_INSERT( SwTxtAttr, pAttr, aHints.Count());
+ rAttrHandler.PushAndChg( *pAttr, rFnt );
+ if( RES_CHRATR_COLOR == nWhich )
+ rFnt.SetNoCol( sal_True );
+ }
+ nWhich = aIter.NextWhich();
+ }
+
+ ++nRet;
+ }
+ break;
+ }
+ nStart = STRING_LEN;
+ nEnd = STRING_LEN;
+ }
+ }
+ return nRet + EnterExtend( rFnt, nNew );
+}
+
+void SwRedlineItr::FillHints( MSHORT nAuthor, RedlineType_t eType )
+{
+ switch ( eType )
+ {
+ case nsRedlineType_t::REDLINE_INSERT:
+ SW_MOD()->GetInsertAuthorAttr(nAuthor, *pSet);
+ break;
+ case nsRedlineType_t::REDLINE_DELETE:
+ SW_MOD()->GetDeletedAuthorAttr(nAuthor, *pSet);
+ break;
+ case nsRedlineType_t::REDLINE_FORMAT:
+ case nsRedlineType_t::REDLINE_FMTCOLL:
+ SW_MOD()->GetFormatAuthorAttr(nAuthor, *pSet);
+ break;
+ default:
+ break;
+ }
+}
+
+void SwRedlineItr::ChangeTxtAttr( SwFont* pFnt, SwTxtAttr &rHt, sal_Bool bChg )
+{
+ OSL_ENSURE( IsOn(), "SwRedlineItr::ChangeTxtAttr: Off?" );
+
+ if( !bShow && !pExt )
+ return;
+
+ if( bChg )
+ {
+ if ( pExt && pExt->IsOn() )
+ rAttrHandler.PushAndChg( rHt, *pExt->GetFont() );
+ else
+ rAttrHandler.PushAndChg( rHt, *pFnt );
+ }
+ else
+ {
+ OSL_ENSURE( ! pExt || ! pExt->IsOn(), "Pop of attribute during opened extension" );
+ rAttrHandler.PopAndChg( rHt, *pFnt );
+ }
+}
+
+void SwRedlineItr::_Clear( SwFont* pFnt )
+{
+ OSL_ENSURE( bOn, "SwRedlineItr::Clear: Off?" );
+ bOn = sal_False;
+ while( aHints.Count() )
+ {
+ SwTxtAttr *pPos = aHints[ 0 ];
+ aHints.Remove(0);
+ if( pFnt )
+ rAttrHandler.PopAndChg( *pPos, *pFnt );
+ else
+ rAttrHandler.Pop( *pPos );
+ SwTxtAttr::Destroy(pPos, const_cast<SwDoc&>(rDoc).GetAttrPool() );
+ }
+ if( pFnt )
+ pFnt->SetNoCol( sal_False );
+}
+
+xub_StrLen SwRedlineItr::_GetNextRedln( xub_StrLen nNext )
+{
+ nNext = NextExtend( nNext );
+ if( !bShow || MSHRT_MAX == nFirst )
+ return nNext;
+ if( MSHRT_MAX == nAct )
+ {
+ nAct = nFirst;
+ rDoc.GetRedlineTbl()[ nAct ]->CalcStartEnd( nNdIdx, nStart, nEnd );
+ }
+ if( bOn || !nStart )
+ {
+ if( nEnd < nNext )
+ nNext = nEnd;
+ }
+ else if( nStart < nNext )
+ nNext = nStart;
+ return nNext;
+}
+
+sal_Bool SwRedlineItr::_ChkSpecialUnderline() const
+{
+ // Wenn die Unterstreichung oder das Escapement vom Redling kommt,
+ // wenden wir immer das SpecialUnderlining, d.h. die Unterstreichung
+ // unter der Grundlinie an.
+ for( MSHORT i = 0; i < aHints.Count(); ++i )
+ {
+ MSHORT nWhich = aHints[i]->Which();
+ if( RES_CHRATR_UNDERLINE == nWhich ||
+ RES_CHRATR_ESCAPEMENT == nWhich )
+ return sal_True;
+ }
+ return sal_False;
+}
+
+sal_Bool SwRedlineItr::CheckLine( xub_StrLen nChkStart, xub_StrLen nChkEnd )
+{
+ if( nFirst == MSHRT_MAX )
+ return sal_False;
+ if( nChkEnd == nChkStart ) // Leerzeilen gucken ein Zeichen weiter.
+ ++nChkEnd;
+ xub_StrLen nOldStart = nStart;
+ xub_StrLen nOldEnd = nEnd;
+ xub_StrLen nOldAct = nAct;
+ sal_Bool bRet = sal_False;
+
+ for( nAct = nFirst; nAct < rDoc.GetRedlineTbl().Count() ; ++nAct )
+ {
+ rDoc.GetRedlineTbl()[ nAct ]->CalcStartEnd( nNdIdx, nStart, nEnd );
+ if( nChkEnd < nStart )
+ break;
+ if( nChkStart <= nEnd && ( nChkEnd > nStart || STRING_LEN == nEnd ) )
+ {
+ bRet = sal_True;
+ break;
+ }
+ }
+
+ nStart = nOldStart;
+ nEnd = nOldEnd;
+ nAct = nOldAct;
+ return bRet;
+}
+
+void SwExtend::ActualizeFont( SwFont &rFnt, MSHORT nAttr )
+{
+ if ( nAttr & EXTTEXTINPUT_ATTR_UNDERLINE )
+ rFnt.SetUnderline( UNDERLINE_SINGLE );
+ else if ( nAttr & EXTTEXTINPUT_ATTR_BOLDUNDERLINE )
+ rFnt.SetUnderline( UNDERLINE_BOLD );
+ else if ( nAttr & EXTTEXTINPUT_ATTR_DOTTEDUNDERLINE )
+ rFnt.SetUnderline( UNDERLINE_DOTTED );
+ else if ( nAttr & EXTTEXTINPUT_ATTR_DASHDOTUNDERLINE )
+ rFnt.SetUnderline( UNDERLINE_DOTTED );
+
+ if ( nAttr & EXTTEXTINPUT_ATTR_REDTEXT )
+ rFnt.SetColor( Color( COL_RED ) );
+
+ if ( nAttr & EXTTEXTINPUT_ATTR_HIGHLIGHT )
+ {
+ const StyleSettings& rStyleSettings = GetpApp()->GetSettings().GetStyleSettings();
+ rFnt.SetColor( rStyleSettings.GetHighlightTextColor() );
+ rFnt.SetBackColor( new Color( rStyleSettings.GetHighlightColor() ) );
+ }
+ if ( nAttr & EXTTEXTINPUT_ATTR_GRAYWAVELINE )
+ rFnt.SetGreyWave( sal_True );
+}
+
+short SwExtend::Enter( SwFont& rFnt, xub_StrLen nNew )
+{
+ OSL_ENSURE( !Inside(), "SwExtend: Enter without Leave" );
+ OSL_ENSURE( !pFnt, "SwExtend: Enter with Font" );
+ nPos = nNew;
+ if( Inside() )
+ {
+ pFnt = new SwFont( rFnt );
+ ActualizeFont( rFnt, rArr[ nPos - nStart ] );
+ return 1;
+ }
+ return 0;
+}
+
+sal_Bool SwExtend::_Leave( SwFont& rFnt, xub_StrLen nNew )
+{
+ OSL_ENSURE( Inside(), "SwExtend: Leave without Enter" );
+ MSHORT nOldAttr = rArr[ nPos - nStart ];
+ nPos = nNew;
+ if( Inside() )
+ { // Wir sind innerhalb des ExtendText-Bereichs geblieben
+ MSHORT nAttr = rArr[ nPos - nStart ];
+ if( nOldAttr != nAttr ) // Gibt es einen (inneren) Attributwechsel?
+ {
+ rFnt = *pFnt;
+ ActualizeFont( rFnt, nAttr );
+ }
+ }
+ else
+ {
+ rFnt = *pFnt;
+ delete pFnt;
+ pFnt = NULL;
+ return sal_True;
+ }
+ return sal_False;
+}
+
+xub_StrLen SwExtend::Next( xub_StrLen nNext )
+{
+ if( nPos < nStart )
+ {
+ if( nNext > nStart )
+ nNext = nStart;
+ }
+ else if( nPos < nEnd )
+ {
+ MSHORT nIdx = nPos - nStart;
+ MSHORT nAttr = rArr[ nIdx ];
+ while( ++nIdx < rArr.Count() && nAttr == rArr[ nIdx ] )
+ ; //nothing
+ nIdx = nIdx + nStart;
+ if( nNext > nIdx )
+ nNext = nIdx;
+ }
+ return nNext;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/text/redlnitr.hxx b/sw/source/core/text/redlnitr.hxx
new file mode 100644
index 000000000000..0fd14acd302f
--- /dev/null
+++ b/sw/source/core/text/redlnitr.hxx
@@ -0,0 +1,123 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+#ifndef _REDLNITR_HXX
+#define _REDLNITR_HXX
+
+#include "ndhints.hxx"
+
+#include <IDocumentRedlineAccess.hxx>
+
+#include "swfont.hxx"
+#ifndef _SVSTDARR_USHORTS
+#define _SVSTDARR_USHORTS
+#include <svl/svstdarr.hxx>
+#endif
+
+class SwTxtNode;
+class SwDoc;
+class SfxItemSet;
+class SwAttrHandler;
+
+class SwExtend
+{
+ SwFont *pFnt;
+ const SvUShorts &rArr; // XAMA: Array of xub_StrLen
+ xub_StrLen nStart;
+ xub_StrLen nPos;
+ xub_StrLen nEnd;
+ sal_Bool _Leave( SwFont& rFnt, xub_StrLen nNew );
+ sal_Bool Inside() const { return ( nPos >= nStart && nPos < nEnd ); }
+ void ActualizeFont( SwFont &rFnt, xub_StrLen nAttr );
+public:
+ SwExtend( const SvUShorts &rA, xub_StrLen nSt ) : pFnt(0), rArr( rA ),
+ nStart( nSt ), nPos( STRING_LEN ), nEnd( nStart + rA.Count() ) {}
+ ~SwExtend() { delete pFnt; }
+ sal_Bool IsOn() const { return pFnt != 0; }
+ void Reset() { if( pFnt ) { delete pFnt; pFnt = NULL; } nPos = STRING_LEN; }
+ sal_Bool Leave( SwFont& rFnt, xub_StrLen nNew )
+ { if( pFnt ) return _Leave( rFnt, nNew ); return sal_False; }
+ short Enter( SwFont& rFnt, xub_StrLen nNew );
+ xub_StrLen Next( xub_StrLen nNext );
+ SwFont* GetFont() { return pFnt; }
+ void UpdateFont( SwFont &rFnt ) { ActualizeFont( rFnt, rArr[ nPos - nStart ] ); }
+};
+
+class SwRedlineItr
+{
+ SwpHtStart_SAR aHints;
+ const SwDoc& rDoc;
+ const SwTxtNode& rNd;
+ SwAttrHandler& rAttrHandler;
+ SfxItemSet *pSet;
+ SwExtend *pExt;
+ sal_uLong nNdIdx;
+ xub_StrLen nFirst;
+ xub_StrLen nAct;
+ xub_StrLen nStart;
+ xub_StrLen nEnd;
+ sal_Bool bOn;
+ sal_Bool bShow;
+
+ void _Clear( SwFont* pFnt );
+ sal_Bool _ChkSpecialUnderline() const;
+ void FillHints( MSHORT nAuthor, RedlineType_t eType );
+ short _Seek( SwFont& rFnt, xub_StrLen nNew, xub_StrLen nOld );
+ xub_StrLen _GetNextRedln( xub_StrLen nNext );
+ inline short EnterExtend( SwFont& rFnt, xub_StrLen nNew )
+ { if( pExt ) return pExt->Enter( rFnt, nNew ); return 0; }
+ inline xub_StrLen NextExtend( xub_StrLen nNext )
+ { if( pExt ) return pExt->Next( nNext ); return nNext; }
+public:
+ SwRedlineItr( const SwTxtNode& rTxtNd, SwFont& rFnt, SwAttrHandler& rAH,
+ xub_StrLen nRedlPos, sal_Bool bShw, const SvUShorts *pArr = 0,
+ xub_StrLen nStart = STRING_LEN );
+ ~SwRedlineItr();
+ inline sal_Bool IsOn() const { return bOn || ( pExt && pExt->IsOn() ); }
+ inline void Clear( SwFont* pFnt ) { if( bOn ) _Clear( pFnt ); }
+ void ChangeTxtAttr( SwFont* pFnt, SwTxtAttr &rHt, sal_Bool bChg );
+ inline short Seek( SwFont& rFnt, xub_StrLen nNew, xub_StrLen nOld )
+ { if( bShow || pExt ) return _Seek( rFnt, nNew, nOld ); return 0; }
+ inline void Reset() { if( nAct != nFirst ) nAct = STRING_LEN;
+ if( pExt ) pExt->Reset(); }
+ inline xub_StrLen GetNextRedln( xub_StrLen nNext )
+ { if( bShow || pExt ) return _GetNextRedln( nNext ); return nNext; }
+ inline sal_Bool ChkSpecialUnderline() const
+ { if ( IsOn() ) return _ChkSpecialUnderline(); return sal_False; }
+ sal_Bool CheckLine( xub_StrLen nChkStart, xub_StrLen nChkEnd );
+ inline sal_Bool LeaveExtend( SwFont& rFnt, xub_StrLen nNew )
+ { return pExt->Leave(rFnt, nNew ); }
+ inline sal_Bool ExtOn() { if( pExt ) return pExt->IsOn(); return sal_False; }
+ inline void UpdateExtFont( SwFont &rFnt ) {
+ OSL_ENSURE( ExtOn(), "UpdateExtFont without ExtOn" );
+ pExt->UpdateFont( rFnt ); }
+};
+
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/text/txtcache.cxx b/sw/source/core/text/txtcache.cxx
new file mode 100644
index 000000000000..24a975c258e3
--- /dev/null
+++ b/sw/source/core/text/txtcache.cxx
@@ -0,0 +1,215 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+
+
+
+#include "txtcache.hxx"
+#include "txtfrm.hxx"
+#include "porlay.hxx"
+
+/*************************************************************************
+|*
+|* SwTxtLine::SwTxtLine(), ~SwTxtLine()
+|*
+|*************************************************************************/
+
+SwTxtLine::SwTxtLine( SwTxtFrm *pFrm, SwParaPortion *pNew ) :
+ SwCacheObj( (void*)pFrm ),
+ pLine( pNew )
+{
+}
+
+SwTxtLine::~SwTxtLine()
+{
+ delete pLine;
+}
+
+/*************************************************************************
+|*
+|* SwTxtLineAccess::NewObj()
+|*
+|*************************************************************************/
+
+SwCacheObj *SwTxtLineAccess::NewObj()
+{
+ return new SwTxtLine( (SwTxtFrm*)pOwner );
+}
+
+/*************************************************************************
+|*
+|* SwTxtLineAccess::GetPara()
+|*
+|*************************************************************************/
+
+SwParaPortion *SwTxtLineAccess::GetPara()
+{
+ SwTxtLine *pRet;
+ if ( pObj )
+ pRet = (SwTxtLine*)pObj;
+ else
+ {
+ pRet = (SwTxtLine*)Get();
+ ((SwTxtFrm*)pOwner)->SetCacheIdx( pRet->GetCachePos() );
+ }
+ if ( !pRet->GetPara() )
+ pRet->SetPara( new SwParaPortion );
+ return pRet->GetPara();
+}
+
+
+/*************************************************************************
+|*
+|* SwTxtLineAccess::SwTxtLineAccess()
+|*
+|*************************************************************************/
+
+SwTxtLineAccess::SwTxtLineAccess( const SwTxtFrm *pOwn ) :
+ SwCacheAccess( *SwTxtFrm::GetTxtCache(), pOwn, pOwn->GetCacheIdx() )
+{
+}
+
+/*************************************************************************
+|*
+|* SwTxtLineAccess::IsAvailable
+|*
+|*************************************************************************/
+
+sal_Bool SwTxtLineAccess::IsAvailable() const
+{
+ if ( pObj )
+ return ((SwTxtLine*)pObj)->GetPara() != 0;
+ return sal_False;
+}
+
+/*************************************************************************
+|*
+|* SwTxtFrm::HasPara()
+|*
+|*************************************************************************/
+
+sal_Bool SwTxtFrm::_HasPara() const
+{
+ SwTxtLine *pTxtLine = (SwTxtLine*)SwTxtFrm::GetTxtCache()->
+ Get( this, GetCacheIdx(), sal_False );
+ if ( pTxtLine )
+ {
+ if ( pTxtLine->GetPara() )
+ return sal_True;
+ }
+ else
+ ((SwTxtFrm*)this)->nCacheIdx = MSHRT_MAX;
+
+ return sal_False;
+}
+
+/*************************************************************************
+|*
+|* SwTxtFrm::GetPara()
+|*
+|*************************************************************************/
+
+SwParaPortion *SwTxtFrm::GetPara()
+{
+ if ( GetCacheIdx() != MSHRT_MAX )
+ { SwTxtLine *pLine = (SwTxtLine*)SwTxtFrm::GetTxtCache()->
+ Get( this, GetCacheIdx(), sal_False );
+ if ( pLine )
+ return pLine->GetPara();
+ else
+ nCacheIdx = MSHRT_MAX;
+ }
+ return 0;
+}
+
+
+/*************************************************************************
+|*
+|* SwTxtFrm::ClearPara()
+|*
+|*************************************************************************/
+
+void SwTxtFrm::ClearPara()
+{
+ OSL_ENSURE( !IsLocked(), "+SwTxtFrm::ClearPara: this is locked." );
+ if ( !IsLocked() && GetCacheIdx() != MSHRT_MAX )
+ {
+ SwTxtLine *pTxtLine = (SwTxtLine*)SwTxtFrm::GetTxtCache()->
+ Get( this, GetCacheIdx(), sal_False );
+ if ( pTxtLine )
+ {
+ delete pTxtLine->GetPara();
+ pTxtLine->SetPara( 0 );
+ }
+ else
+ nCacheIdx = MSHRT_MAX;
+ }
+}
+
+/*************************************************************************
+|*
+|* SwTxtFrm::SetPara()
+|*
+|*************************************************************************/
+
+void SwTxtFrm::SetPara( SwParaPortion *pNew, sal_Bool bDelete )
+{
+ if ( GetCacheIdx() != MSHRT_MAX )
+ {
+ //Nur die Information Auswechseln, das CacheObj bleibt stehen.
+ SwTxtLine *pTxtLine = (SwTxtLine*)SwTxtFrm::GetTxtCache()->
+ Get( this, GetCacheIdx(), sal_False );
+ if ( pTxtLine )
+ {
+ if( bDelete )
+ delete pTxtLine->GetPara();
+ pTxtLine->SetPara( pNew );
+ }
+ else
+ {
+ OSL_ENSURE( !pNew, "+SetPara: Losing SwParaPortion" );
+ nCacheIdx = MSHRT_MAX;
+ }
+ }
+ else if ( pNew )
+ { //Einen neuen einfuegen.
+ SwTxtLine *pTxtLine = new SwTxtLine( this, pNew );
+ if ( SwTxtFrm::GetTxtCache()->Insert( pTxtLine ) )
+ nCacheIdx = pTxtLine->GetCachePos();
+ else
+ {
+ OSL_FAIL( "+SetPara: InsertCache failed." );
+ }
+ }
+}
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/text/txtcache.hxx b/sw/source/core/text/txtcache.hxx
new file mode 100644
index 000000000000..46276d5d9700
--- /dev/null
+++ b/sw/source/core/text/txtcache.hxx
@@ -0,0 +1,79 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+#ifndef _TXTCACHE_HXX
+#define _TXTCACHE_HXX
+
+#include <sal/types.h>
+#include <tools/mempool.hxx>
+#include "swcache.hxx"
+
+class SwParaPortion;
+class SwTxtFrm;
+
+class SwTxtLine : public SwCacheObj
+{
+ SwParaPortion *pLine;
+
+public:
+ DECL_FIXEDMEMPOOL_NEWDEL(SwTxtLine)
+
+ SwTxtLine( SwTxtFrm *pFrm, SwParaPortion *pNew = 0 );
+ virtual ~SwTxtLine();
+
+ inline SwParaPortion *GetPara() { return pLine; }
+ inline const SwParaPortion *GetPara() const { return pLine; }
+
+ inline void SetPara( SwParaPortion *pNew ) { pLine = pNew; }
+};
+
+
+class SwTxtLineAccess : public SwCacheAccess
+{
+
+protected:
+ virtual SwCacheObj *NewObj();
+
+public:
+ SwTxtLineAccess( const SwTxtFrm *pOwner );
+
+ SwParaPortion *GetPara();
+
+ inline SwTxtLine &GetTxtLine();
+
+ virtual sal_Bool IsAvailable() const;
+};
+
+
+inline SwTxtLine &SwTxtLineAccess::GetTxtLine()
+{
+ return *((SwTxtLine*)Get());
+}
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/text/txtdrop.cxx b/sw/source/core/text/txtdrop.cxx
new file mode 100644
index 000000000000..298a3e91e3bd
--- /dev/null
+++ b/sw/source/core/text/txtdrop.cxx
@@ -0,0 +1,1092 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+
+#include <hintids.hxx>
+#include <vcl/metric.hxx>
+#include <vcl/window.hxx>
+#include <vcl/svapp.hxx>
+#include <paratr.hxx>
+#include <txtfrm.hxx> // Format()
+#include <charfmt.hxx>
+#include <viewopt.hxx> // SwViewOption
+#include <viewsh.hxx> // ViewShell
+#include <pordrop.hxx>
+#include <itrform2.hxx>
+#include <txtpaint.hxx> // SwSaveClip
+#include <blink.hxx> // pBlink
+#include <breakit.hxx>
+#include <com/sun/star/i18n/ScriptType.hdl>
+#include <com/sun/star/i18n/WordType.hpp>
+#include <editeng/langitem.hxx>
+#include <charatr.hxx>
+#include <editeng/fhgtitem.hxx>
+#include <switerator.hxx>
+
+using namespace ::com::sun::star::i18n;
+using namespace ::com::sun::star;
+
+/*************************************************************************
+ * lcl_IsDropFlyInter
+ *
+ * Calculates if a drop caps portion intersects with a fly
+ * The width and height of the drop caps portion are passed as arguments,
+ * the position is calculated from the values in rInf
+ *************************************************************************/
+
+sal_Bool lcl_IsDropFlyInter( const SwTxtFormatInfo &rInf,
+ sal_uInt16 nWidth, sal_uInt16 nHeight )
+{
+ const SwTxtFly *pTxtFly = rInf.GetTxtFly();
+ if( pTxtFly && pTxtFly->IsOn() )
+ {
+ SwRect aRect( rInf.GetTxtFrm()->Frm().Pos(), Size( nWidth, nHeight) );
+ aRect.Pos() += rInf.GetTxtFrm()->Prt().Pos();
+ aRect.Pos().X() += rInf.X();
+ aRect.Pos().Y() = rInf.Y();
+ aRect = pTxtFly->GetFrm( aRect );
+ return aRect.HasArea();
+ }
+
+ return sal_False;
+}
+
+/*************************************************************************
+ * class SwDropSave
+ *************************************************************************/
+
+class SwDropSave
+{
+ SwTxtPaintInfo* pInf;
+ xub_StrLen nIdx;
+ xub_StrLen nLen;
+ long nX;
+ long nY;
+
+public:
+ SwDropSave( const SwTxtPaintInfo &rInf );
+ ~SwDropSave();
+};
+
+SwDropSave::SwDropSave( const SwTxtPaintInfo &rInf ) :
+ pInf( ((SwTxtPaintInfo*)&rInf) ), nIdx( rInf.GetIdx() ),
+ nLen( rInf.GetLen() ), nX( rInf.X() ), nY( rInf.Y() )
+{
+}
+
+SwDropSave::~SwDropSave()
+{
+ pInf->SetIdx( nIdx );
+ pInf->SetLen( nLen );
+ pInf->X( nX );
+ pInf->Y( nY );
+}
+
+/*************************************************************************
+ * SwDropPortionPart DTor
+ *************************************************************************/
+
+SwDropPortionPart::~SwDropPortionPart()
+{
+ if ( pFollow )
+ delete pFollow;
+ delete pFnt;
+}
+
+/*************************************************************************
+ * SwDropPortion CTor, DTor
+ *************************************************************************/
+
+SwDropPortion::SwDropPortion( const MSHORT nLineCnt,
+ const KSHORT nDrpHeight,
+ const KSHORT nDrpDescent,
+ const KSHORT nDist )
+ : pPart( 0 ),
+ nLines( nLineCnt ),
+ nDropHeight(nDrpHeight),
+ nDropDescent(nDrpDescent),
+ nDistance(nDist),
+ nFix(0),
+ nX(0)
+{
+ SetWhichPor( POR_DROP );
+}
+
+SwDropPortion::~SwDropPortion()
+{
+ delete pPart;
+ if( pBlink )
+ pBlink->Delete( this );
+}
+
+sal_Bool SwTxtSizeInfo::_HasHint( const SwTxtNode* pTxtNode, xub_StrLen nPos )
+{
+ return 0 != pTxtNode->GetTxtAttrForCharAt(nPos);
+}
+
+/*************************************************************************
+ * SwTxtNode::GetDropLen()
+ *
+ * nWishLen = 0 indicates that we want a whole word
+ *************************************************************************/
+
+MSHORT SwTxtNode::GetDropLen( MSHORT nWishLen ) const
+{
+ xub_StrLen nEnd = GetTxt().Len();
+ if( nWishLen && nWishLen < nEnd )
+ nEnd = nWishLen;
+
+ if ( ! nWishLen && pBreakIt->GetBreakIter().is() )
+ {
+ // find first word
+ const SwAttrSet& rAttrSet = GetSwAttrSet();
+ const sal_uInt16 nTxtScript = pBreakIt->GetRealScriptOfText( GetTxt(), 0 );
+
+ LanguageType eLanguage;
+
+ switch ( nTxtScript )
+ {
+ case i18n::ScriptType::ASIAN :
+ eLanguage = rAttrSet.GetCJKLanguage().GetLanguage();
+ break;
+ case i18n::ScriptType::COMPLEX :
+ eLanguage = rAttrSet.GetCTLLanguage().GetLanguage();
+ break;
+ default :
+ eLanguage = rAttrSet.GetLanguage().GetLanguage();
+ break;
+ }
+
+ Boundary aBound =
+ pBreakIt->GetBreakIter()->getWordBoundary( GetTxt(), 0,
+ pBreakIt->GetLocale( eLanguage ), WordType::DICTIONARY_WORD, sal_True );
+
+ nEnd = (xub_StrLen)aBound.endPos;
+ }
+
+ xub_StrLen i = 0;
+ for( ; i < nEnd; ++i )
+ {
+ xub_Unicode cChar = GetTxt().GetChar( i );
+ if( CH_TAB == cChar || CH_BREAK == cChar ||
+ (( CH_TXTATR_BREAKWORD == cChar || CH_TXTATR_INWORD == cChar )
+ && SwTxtSizeInfo::_HasHint( this, i ) ) )
+ break;
+ }
+ return i;
+}
+
+/*************************************************************************
+ * SwTxtNode::GetDropSize()
+ *
+ * If a dropcap is found the return value is true otherwise false. The
+ * drop cap sizes passed back by reference are font height, drop height
+ * and drop descent.
+ *************************************************************************/
+bool SwTxtNode::GetDropSize(int& rFontHeight, int& rDropHeight, int& rDropDescent) const
+{
+ rFontHeight = 0;
+ rDropHeight = 0;
+ rDropDescent =0;
+
+ const SwAttrSet& rSet = GetSwAttrSet();
+ const SwFmtDrop& rDrop = rSet.GetDrop();
+
+ // Return (0,0) if there is no drop cap at this paragraph
+ if( 1 >= rDrop.GetLines() ||
+ ( !rDrop.GetChars() && !rDrop.GetWholeWord() ) )
+ {
+ return false;
+ }
+
+ // get text frame
+ SwIterator<SwTxtFrm,SwTxtNode> aIter( *this );
+ for( SwTxtFrm* pLastFrm = aIter.First(); pLastFrm; pLastFrm = aIter.Next() )
+ {
+ // Only (master-) text frames can have a drop cap.
+ if ( !pLastFrm->IsFollow() )
+ {
+
+ if( !pLastFrm->HasPara() )
+ pLastFrm->GetFormatted();
+
+ if ( !pLastFrm->IsEmpty() )
+ {
+ const SwParaPortion* pPara = pLastFrm->GetPara();
+ OSL_ENSURE( pPara, "GetDropSize could not find the ParaPortion, I'll guess the drop cap size" );
+
+ if ( pPara )
+ {
+ const SwLinePortion* pFirstPor = pPara->GetFirstPortion();
+ if (pFirstPor && pFirstPor->IsDropPortion())
+ {
+ const SwDropPortion* pDrop = (const SwDropPortion*)pFirstPor;
+ rDropHeight = pDrop->GetDropHeight();
+ rDropDescent = pDrop->GetDropDescent();
+ if (const SwFont *pFont = pDrop->GetFnt())
+ rFontHeight = pFont->GetSize(pFont->GetActual()).Height();
+ else
+ {
+ const SvxFontHeightItem& rItem = (SvxFontHeightItem&)rSet.Get(RES_CHRATR_FONTSIZE);
+ rFontHeight = rItem.GetHeight();
+ }
+ }
+ }
+ }
+ break;
+ }
+ }
+
+ if (rFontHeight==0 && rDropHeight==0 && rDropDescent==0)
+ {
+ const sal_uInt16 nLines = rDrop.GetLines();
+
+ const SvxFontHeightItem& rItem = (SvxFontHeightItem&)rSet.Get( RES_CHRATR_FONTSIZE );
+ rFontHeight = rItem.GetHeight();
+ rDropHeight = nLines * rFontHeight;
+ rDropDescent = rFontHeight / 5;
+ return false;
+ }
+
+ return true;
+}
+
+/*************************************************************************
+ * SwDropPortion::PaintTxt()
+ *************************************************************************/
+
+// Die Breite manipulieren, sonst werden die Buchstaben gestretcht
+
+void SwDropPortion::PaintTxt( const SwTxtPaintInfo &rInf ) const
+{
+ if ( rInf.OnWin() &&
+ !rInf.GetOpt().IsPagePreview() && !rInf.GetOpt().IsReadonly() && SwViewOption::IsFieldShadings() )
+ rInf.DrawBackground( *this );
+
+ OSL_ENSURE( nDropHeight && pPart && nLines != 1, "Drop Portion painted twice" );
+
+ const SwDropPortionPart* pCurrPart = GetPart();
+ const xub_StrLen nOldLen = GetLen();
+
+ const SwTwips nBasePosY = rInf.Y();
+ ((SwTxtPaintInfo&)rInf).Y( nBasePosY + nY );
+ SwDropSave aSave( rInf );
+ // for text inside drop portions we let vcl handle the text directions
+ SwLayoutModeModifier aLayoutModeModifier( *rInf.GetOut() );
+ aLayoutModeModifier.SetAuto();
+
+ while ( pCurrPart )
+ {
+ ((SwDropPortion*)this)->SetLen( pCurrPart->GetLen() );
+ ((SwTxtPaintInfo&)rInf).SetLen( pCurrPart->GetLen() );
+ SwFontSave aFontSave( rInf, &pCurrPart->GetFont() );
+
+ SwTxtPortion::Paint( rInf );
+
+ ((SwTxtPaintInfo&)rInf).SetIdx( rInf.GetIdx() + pCurrPart->GetLen() );
+ ((SwTxtPaintInfo&)rInf).X( rInf.X() + pCurrPart->GetWidth() );
+ pCurrPart = pCurrPart->GetFollow();
+ }
+
+ ((SwTxtPaintInfo&)rInf).Y( nBasePosY );
+ ((SwDropPortion*)this)->SetLen( nOldLen );
+}
+
+/*************************************************************************
+ * SwDropPortion::Paint()
+ *************************************************************************/
+
+void SwDropPortion::PaintDrop( const SwTxtPaintInfo &rInf ) const
+{
+ // ganz normale Ausgabe wird w?hrend des normalen Paints erledigt
+ if( ! nDropHeight || ! pPart || nLines == 1 )
+ return;
+
+ // Luegenwerte einstellen!
+ const KSHORT nOldHeight = Height();
+ const KSHORT nOldWidth = Width();
+ const KSHORT nOldAscent = GetAscent();
+ const SwTwips nOldPosY = rInf.Y();
+ const KSHORT nOldPosX = (KSHORT)rInf.X();
+ const SwParaPortion *pPara = rInf.GetParaPortion();
+ const Point aOutPos( nOldPosX + nX, nOldPosY - pPara->GetAscent()
+ - pPara->GetRealHeight() + pPara->Height() );
+ // Retusche nachholen.
+
+ // Set baseline
+ ((SwTxtPaintInfo&)rInf).Y( aOutPos.Y() + nDropHeight );
+
+ // for background
+ ((SwDropPortion*)this)->Height( nDropHeight + nDropDescent );
+ ((SwDropPortion*)this)->Width( Width() - nX );
+ ((SwDropPortion*)this)->SetAscent( nDropHeight );
+
+ // Clipregion auf uns einstellen!
+ // Und zwar immer, und nie mit dem bestehenden ClipRect
+ // verrechnen, weil dies auf die Zeile eingestellt sein koennte.
+
+ SwRect aClipRect;
+ if ( rInf.OnWin() )
+ {
+ aClipRect = SwRect( aOutPos, SvLSize() );
+ aClipRect.Intersection( rInf.GetPaintRect() );
+ }
+ SwSaveClip aClip( (OutputDevice*)rInf.GetOut() );
+ aClip.ChgClip( aClipRect, rInf.GetTxtFrm() );
+ // Das machen, was man sonst nur macht ...
+ PaintTxt( rInf );
+
+ // Alte Werte sichern
+ ((SwDropPortion*)this)->Height( nOldHeight );
+ ((SwDropPortion*)this)->Width( nOldWidth );
+ ((SwDropPortion*)this)->SetAscent( nOldAscent );
+ ((SwTxtPaintInfo&)rInf).Y( nOldPosY );
+}
+
+/*************************************************************************
+ * virtual SwDropPortion::Paint()
+ *************************************************************************/
+
+void SwDropPortion::Paint( const SwTxtPaintInfo &rInf ) const
+{
+ // ganz normale Ausgabe wird hier erledigt.
+ if( ! nDropHeight || ! pPart || 1 == nLines )
+ {
+ if ( rInf.OnWin() &&
+ !rInf.GetOpt().IsPagePreview() && !rInf.GetOpt().IsReadonly() && SwViewOption::IsFieldShadings() )
+ rInf.DrawBackground( *this );
+
+ // make sure that font is not rotated
+ SwFont* pTmpFont = 0;
+ if ( rInf.GetFont()->GetOrientation( rInf.GetTxtFrm()->IsVertical() ) )
+ {
+ pTmpFont = new SwFont( *rInf.GetFont() );
+ pTmpFont->SetVertical( 0, rInf.GetTxtFrm()->IsVertical() );
+ }
+
+ SwFontSave aFontSave( rInf, pTmpFont );
+ // for text inside drop portions we let vcl handle the text directions
+ SwLayoutModeModifier aLayoutModeModifier( *rInf.GetOut() );
+ aLayoutModeModifier.SetAuto();
+
+ SwTxtPortion::Paint( rInf );
+ delete pTmpFont;
+ }
+}
+
+/*************************************************************************
+ * virtual Format()
+ *************************************************************************/
+
+
+sal_Bool SwDropPortion::FormatTxt( SwTxtFormatInfo &rInf )
+{
+ const xub_StrLen nOldLen = GetLen();
+ const xub_StrLen nOldInfLen = rInf.GetLen();
+ const sal_Bool bFull = SwTxtPortion::Format( rInf );
+ if( bFull )
+ {
+ // sieht zwar Scheisse aus, aber was soll man schon machen?
+ rInf.SetUnderFlow( 0 );
+ Truncate();
+ SetLen( nOldLen );
+ rInf.SetLen( nOldInfLen );
+ }
+ return bFull;
+}
+
+/*************************************************************************
+ * virtual GetTxtSize()
+ *************************************************************************/
+
+
+SwPosSize SwDropPortion::GetTxtSize( const SwTxtSizeInfo &rInf ) const
+{
+ sal_uInt16 nMyX = 0;
+ xub_StrLen nIdx = 0;
+
+ const SwDropPortionPart* pCurrPart = GetPart();
+
+ // skip parts
+ while ( pCurrPart && nIdx + pCurrPart->GetLen() < rInf.GetLen() )
+ {
+ nMyX = nMyX + pCurrPart->GetWidth();
+ nIdx = nIdx + pCurrPart->GetLen();
+ pCurrPart = pCurrPart->GetFollow();
+ }
+
+ xub_StrLen nOldIdx = rInf.GetIdx();
+ xub_StrLen nOldLen = rInf.GetLen();
+
+ ((SwTxtSizeInfo&)rInf).SetIdx( nIdx );
+ ((SwTxtSizeInfo&)rInf).SetLen( rInf.GetLen() - nIdx );
+
+ // robust
+ SwFontSave aFontSave( rInf, pCurrPart ? &pCurrPart->GetFont() : 0 );
+ SwPosSize aPosSize( SwTxtPortion::GetTxtSize( rInf ) );
+ aPosSize.Width( aPosSize.Width() + nMyX );
+
+ ((SwTxtSizeInfo&)rInf).SetIdx( nOldIdx );
+ ((SwTxtSizeInfo&)rInf).SetLen( nOldLen );
+
+ return aPosSize;
+}
+
+/*************************************************************************
+ * virtual GetCrsrOfst()
+ *************************************************************************/
+
+xub_StrLen SwDropPortion::GetCrsrOfst( const KSHORT ) const
+{
+ return 0;
+}
+
+/*************************************************************************
+ * SwTxtFormatter::CalcDropHeight()
+ *************************************************************************/
+
+void SwTxtFormatter::CalcDropHeight( const MSHORT nLines )
+{
+ const SwLinePortion *const pOldCurr = GetCurr();
+ KSHORT nDropHght = 0;
+ KSHORT nAscent = 0;
+ KSHORT nHeight = 0;
+ KSHORT nDropLns = 0;
+ sal_Bool bRegisterOld = IsRegisterOn();
+ bRegisterOn = sal_False;
+
+ Top();
+
+ while( GetCurr()->IsDummy() )
+ {
+ if ( !Next() )
+ break;
+ }
+
+ // Wenn wir nur eine Zeile haben returnen wir 0
+ if( GetNext() || GetDropLines() == 1 )
+ {
+ for( ; nDropLns < nLines; nDropLns++ )
+ {
+ if ( GetCurr()->IsDummy() )
+ break;
+ else
+ {
+ CalcAscentAndHeight( nAscent, nHeight );
+ nDropHght = nDropHght + nHeight;
+ bRegisterOn = bRegisterOld;
+ }
+ if ( !Next() )
+ {
+ nDropLns++; // Fix: 11356
+ break;
+ }
+ }
+
+ // In der letzten Zeile plumpsen wir auf den Zeilenascent!
+ nDropHght = nDropHght - nHeight;
+ nDropHght = nDropHght + nAscent;
+ Top();
+ }
+ bRegisterOn = bRegisterOld;
+ SetDropDescent( nHeight - nAscent );
+ SetDropHeight( nDropHght );
+ SetDropLines( nDropLns );
+ // Alte Stelle wiederfinden!
+ while( pOldCurr != GetCurr() )
+ {
+ if( !Next() )
+ {
+ OSL_ENSURE( !this, "SwTxtFormatter::_CalcDropHeight: left Toulouse" );
+ break;
+ }
+ }
+}
+
+/*************************************************************************
+ * SwTxtFormatter::GuessDropHeight()
+ *
+ * Wir schaetzen mal, dass die Fonthoehe sich nicht aendert und dass
+ * erst mindestens soviele Zeilen gibt, wie die DropCap-Einstellung angibt.
+ *
+ *************************************************************************/
+
+
+
+void SwTxtFormatter::GuessDropHeight( const MSHORT nLines )
+{
+ OSL_ENSURE( nLines, "GuessDropHeight: Give me more Lines!" );
+ KSHORT nAscent = 0;
+ KSHORT nHeight = 0;
+ SetDropLines( nLines );
+ if ( GetDropLines() > 1 )
+ {
+ CalcRealHeight();
+ CalcAscentAndHeight( nAscent, nHeight );
+ }
+ SetDropDescent( nHeight - nAscent );
+ SetDropHeight( nHeight * nLines - GetDropDescent() );
+}
+
+/*************************************************************************
+ * SwTxtFormatter::NewDropPortion
+ *************************************************************************/
+
+SwDropPortion *SwTxtFormatter::NewDropPortion( SwTxtFormatInfo &rInf )
+{
+ if( !pDropFmt )
+ return 0;
+
+ xub_StrLen nPorLen = pDropFmt->GetWholeWord() ? 0 : pDropFmt->GetChars();
+ nPorLen = pFrm->GetTxtNode()->GetDropLen( nPorLen );
+ if( !nPorLen )
+ {
+ ((SwTxtFormatter*)this)->ClearDropFmt();
+ return 0;
+ }
+
+ SwDropPortion *pDropPor = 0;
+
+ // erste oder zweite Runde?
+ if ( !( GetDropHeight() || IsOnceMore() ) )
+ {
+ if ( GetNext() )
+ CalcDropHeight( pDropFmt->GetLines() );
+ else
+ GuessDropHeight( pDropFmt->GetLines() );
+ }
+
+ // the DropPortion
+ if( GetDropHeight() )
+ pDropPor = new SwDropPortion( GetDropLines(), GetDropHeight(),
+ GetDropDescent(), pDropFmt->GetDistance() );
+ else
+ pDropPor = new SwDropPortion( 0,0,0,pDropFmt->GetDistance() );
+
+ pDropPor->SetLen( nPorLen );
+
+ // If it was not possible to create a proper drop cap portion
+ // due to avoiding endless loops. We return a drop cap portion
+ // with an empty SwDropCapPart. For these portions the current
+ // font is used.
+ if ( GetDropLines() < 2 )
+ {
+ ((SwTxtFormatter*)this)->SetPaintDrop( sal_True );
+ return pDropPor;
+ }
+
+ // build DropPortionParts:
+ OSL_ENSURE( ! rInf.GetIdx(), "Drop Portion not at 0 position!" );
+ xub_StrLen nNextChg = 0;
+ const SwCharFmt* pFmt = pDropFmt->GetCharFmt();
+ SwDropPortionPart* pCurrPart = 0;
+
+ while ( nNextChg < nPorLen )
+ {
+ // check for attribute changes and if the portion has to split:
+ Seek( nNextChg );
+
+ // the font is deleted in the destructor of the drop portion part
+ SwFont* pTmpFnt = new SwFont( *rInf.GetFont() );
+ if ( pFmt )
+ {
+ const SwAttrSet& rSet = pFmt->GetAttrSet();
+ pTmpFnt->SetDiffFnt( &rSet, pFrm->GetTxtNode()->getIDocumentSettingAccess() );
+ }
+
+ // we do not allow a vertical font for the drop portion
+ pTmpFnt->SetVertical( 0, rInf.GetTxtFrm()->IsVertical() );
+
+ // find next attribute change / script change
+ const xub_StrLen nTmpIdx = nNextChg;
+ xub_StrLen nNextAttr = Min( GetNextAttr(), rInf.GetTxt().Len() );
+ nNextChg = pScriptInfo->NextScriptChg( nTmpIdx );
+ if( nNextChg > nNextAttr )
+ nNextChg = nNextAttr;
+ if ( nNextChg > nPorLen )
+ nNextChg = nPorLen;
+
+ SwDropPortionPart* pPart =
+ new SwDropPortionPart( *pTmpFnt, nNextChg - nTmpIdx );
+
+ if ( ! pCurrPart )
+ pDropPor->SetPart( pPart );
+ else
+ pCurrPart->SetFollow( pPart );
+
+ pCurrPart = pPart;
+ }
+
+ ((SwTxtFormatter*)this)->SetPaintDrop( sal_True );
+ return pDropPor;
+}
+
+/*************************************************************************
+ * SwTxtPainter::PaintDropPortion()
+ *************************************************************************/
+
+
+
+void SwTxtPainter::PaintDropPortion()
+{
+ const SwDropPortion *pDrop = GetInfo().GetParaPortion()->FindDropPortion();
+ OSL_ENSURE( pDrop, "DrapCop-Portion not available." );
+ if( !pDrop )
+ return;
+
+ const SwTwips nOldY = GetInfo().Y();
+
+ Top();
+
+ GetInfo().SetpSpaceAdd( pCurr->GetpLLSpaceAdd() );
+ GetInfo().ResetSpaceIdx();
+ GetInfo().SetKanaComp( pCurr->GetpKanaComp() );
+ GetInfo().ResetKanaIdx();
+
+ // 8047: Drops und Dummies
+ while( !pCurr->GetLen() && Next() )
+ ;
+
+ // MarginPortion und Adjustment!
+ const SwLinePortion *pPor = pCurr->GetFirstPortion();
+ KSHORT nX = 0;
+ while( pPor && !pPor->IsDropPortion() )
+ {
+ nX = nX + pPor->Width();
+ pPor = pPor->GetPortion();
+ }
+ Point aLineOrigin( GetTopLeft() );
+
+ aLineOrigin.X() += nX;
+ KSHORT nTmpAscent, nTmpHeight;
+ CalcAscentAndHeight( nTmpAscent, nTmpHeight );
+ aLineOrigin.Y() += nTmpAscent;
+ GetInfo().SetIdx( GetStart() );
+ GetInfo().SetPos( aLineOrigin );
+ GetInfo().SetLen( pDrop->GetLen() );
+
+ pDrop->PaintDrop( GetInfo() );
+
+ GetInfo().Y( nOldY );
+}
+
+/*************************************************************************
+ * clas SwDropCapCache
+ *
+ * Da die Berechnung der Fontgroesse der Initialen ein teures Geschaeft ist,
+ * wird dies durch einen DropCapCache geschleust.
+ *************************************************************************/
+
+#define DROP_CACHE_SIZE 10
+
+class SwDropCapCache
+{
+ long aMagicNo[ DROP_CACHE_SIZE ];
+ XubString aTxt[ DROP_CACHE_SIZE ];
+ sal_uInt16 aFactor[ DROP_CACHE_SIZE ];
+ KSHORT aWishedHeight[ DROP_CACHE_SIZE ];
+ short aDescent[ DROP_CACHE_SIZE ];
+ MSHORT nIndex;
+public:
+ SwDropCapCache();
+ ~SwDropCapCache(){}
+ void CalcFontSize( SwDropPortion* pDrop, SwTxtFormatInfo &rInf );
+};
+
+/*************************************************************************
+ * SwDropCapCache Ctor / Dtor
+ *************************************************************************/
+
+SwDropCapCache::SwDropCapCache() : nIndex( 0 )
+{
+ memset( &aMagicNo, 0, sizeof(aMagicNo) );
+ memset( &aWishedHeight, 0, sizeof(aWishedHeight) );
+}
+
+void SwDropPortion::DeleteDropCapCache()
+{
+ delete pDropCapCache;
+}
+
+/*************************************************************************
+ * SwDropCapCache::CalcFontSize
+ *************************************************************************/
+
+void SwDropCapCache::CalcFontSize( SwDropPortion* pDrop, SwTxtFormatInfo &rInf )
+{
+ const void* pFntNo = 0;
+ MSHORT nTmpIdx = 0;
+
+ OSL_ENSURE( pDrop->GetPart(),"DropPortion without part during font calculation");
+
+ SwDropPortionPart* pCurrPart = pDrop->GetPart();
+ const sal_Bool bUseCache = ! pCurrPart->GetFollow();
+ xub_StrLen nIdx = rInf.GetIdx();
+ XubString aStr( rInf.GetTxt(), nIdx, pCurrPart->GetLen() );
+
+ long nAscent = 0;
+ long nDescent = 0;
+ long nFactor = -1;
+
+ if ( bUseCache )
+ {
+ SwFont& rFnt = pCurrPart->GetFont();
+ rFnt.ChkMagic( rInf.GetVsh(), rFnt.GetActual() );
+ rFnt.GetMagic( pFntNo, nTmpIdx, rFnt.GetActual() );
+
+ nTmpIdx = 0;
+
+ while( nTmpIdx < DROP_CACHE_SIZE &&
+ ( aTxt[ nTmpIdx ] != aStr || aMagicNo[ nTmpIdx ] != long(pFntNo) ||
+ aWishedHeight[ nTmpIdx ] != pDrop->GetDropHeight() ) )
+ ++nTmpIdx;
+ }
+
+ // we have to calculate a new font scaling factor if
+ // 1. we did not find a scaling factor in the cache or
+ // 2. we are not allowed to use the cache because the drop portion
+ // consists of more than one part
+ if( nTmpIdx >= DROP_CACHE_SIZE || ! bUseCache )
+ {
+ ++nIndex;
+ nIndex %= DROP_CACHE_SIZE;
+ nTmpIdx = nIndex;
+
+ long nWishedHeight = pDrop->GetDropHeight();
+
+ // find out biggest font size for initial scaling factor
+ long nMaxFontHeight = 0;
+ while ( pCurrPart )
+ {
+ const SwFont& rFnt = pCurrPart->GetFont();
+ const long nCurrHeight = rFnt.GetHeight( rFnt.GetActual() );
+ if ( nCurrHeight > nMaxFontHeight )
+ nMaxFontHeight = nCurrHeight;
+
+ pCurrPart = pCurrPart->GetFollow();
+ }
+
+ nFactor = ( 1000 * nWishedHeight ) / nMaxFontHeight;
+
+ if ( bUseCache )
+ {
+ // save keys for cache
+ aMagicNo[ nTmpIdx ] = long(pFntNo);
+ aTxt[ nTmpIdx ] = aStr;
+ aWishedHeight[ nTmpIdx ] = KSHORT(nWishedHeight);
+ // save initial scaling factor
+ aFactor[ nTmpIdx ] = (sal_uInt16)nFactor;
+ }
+
+ sal_Bool bGrow = ( pDrop->GetLen() != 0 );
+
+ // for growing controll
+ long nMax = KSHRT_MAX;
+ long nMin = nFactor / 2;
+#if OSL_DEBUG_LEVEL > 1
+ long nGrow = 0;
+#endif
+
+ sal_Bool bWinUsed = sal_False;
+ Font aOldFnt;
+ MapMode aOldMap( MAP_TWIP );
+ OutputDevice* pOut = rInf.GetOut();
+ OutputDevice* pWin;
+ if( rInf.GetVsh() && rInf.GetVsh()->GetWin() )
+ pWin = rInf.GetVsh()->GetWin();
+ else
+ pWin = GetpApp()->GetDefaultDevice();
+
+ while( bGrow )
+ {
+ // reset pCurrPart to first part
+ pCurrPart = pDrop->GetPart();
+ sal_Bool bFirstGlyphRect = sal_True;
+ sal_Bool bHaveGlyphRect = sal_False;
+ Rectangle aCommonRect, aRect;
+
+ while ( pCurrPart )
+ {
+ // current font
+ SwFont& rFnt = pCurrPart->GetFont();
+
+ // Get height including proportion
+ const sal_uInt16 nCurrHeight =
+ (sal_uInt16)rFnt.GetHeight( rFnt.GetActual() );
+
+ // Get without proportion
+ const sal_uInt8 nOldProp = rFnt.GetPropr();
+ rFnt.SetProportion( 100 );
+ Size aOldSize = Size( 0, rFnt.GetHeight( rFnt.GetActual() ) );
+
+ Size aNewSize( 0, ( nFactor * nCurrHeight ) / 1000 );
+ rFnt.SetSize( aNewSize, rFnt.GetActual() );
+ rFnt.ChgPhysFnt( rInf.GetVsh(), *pOut );
+
+ nAscent = rFnt.GetAscent( rInf.GetVsh(), *pOut );
+
+ // Wir besorgen uns das alle Buchstaben umfassende Rechteck:
+ bHaveGlyphRect = pOut->GetTextBoundRect( aRect, rInf.GetTxt(), 0,
+ nIdx, pCurrPart->GetLen() ) &&
+ ! aRect.IsEmpty();
+
+ if ( ! bHaveGlyphRect )
+ {
+ // getting glyph boundaries failed for some reason,
+ // we take the window for calculating sizes
+ if ( pWin )
+ {
+ if ( ! bWinUsed )
+ {
+ bWinUsed = sal_True;
+ aOldMap = pWin->GetMapMode( );
+ pWin->SetMapMode( MapMode( MAP_TWIP ) );
+ aOldFnt = pWin->GetFont();
+ }
+ pWin->SetFont( rFnt.GetActualFont() );
+
+ bHaveGlyphRect = pWin->GetTextBoundRect( aRect, rInf.GetTxt(), 0,
+ nIdx, pCurrPart->GetLen() ) &&
+ ! aRect.IsEmpty();
+ }
+ if ( bHaveGlyphRect )
+ {
+ FontMetric aWinMet( pWin->GetFontMetric() );
+ nAscent = (KSHORT) aWinMet.GetAscent();
+ }
+ else
+ // We do not have a window or our window could not
+ // give us glyph boundaries.
+ aRect = Rectangle( Point( 0, 0 ), Size( 0, nAscent ) );
+ }
+
+ // Now we (hopefully) have a bounding rectangle for the
+ // glyphs of the current portion and the ascent of the current
+ // font
+
+ // reset font size and proportion
+ rFnt.SetSize( aOldSize, rFnt.GetActual() );
+ rFnt.SetProportion( nOldProp );
+
+ if ( bFirstGlyphRect )
+ {
+ aCommonRect = aRect;
+ bFirstGlyphRect = sal_False;
+ }
+ else
+ aCommonRect.Union( aRect );
+
+ nIdx = nIdx + pCurrPart->GetLen();
+ pCurrPart = pCurrPart->GetFollow();
+ }
+
+ // now we have a union ( aCommonRect ) of all glyphs with
+ // respect to a common baseline : 0
+
+ // get descent and ascent from union
+ if ( rInf.GetTxtFrm()->IsVertical() )
+ {
+ nDescent = aCommonRect.Left();
+ nAscent = aCommonRect.Right();
+
+ if ( nDescent < 0 )
+ nDescent = -nDescent;
+ }
+ else
+ {
+ nDescent = aCommonRect.Bottom();
+ nAscent = aCommonRect.Top();
+ }
+ if ( nAscent < 0 )
+ nAscent = -nAscent;
+
+ const long nHght = nAscent + nDescent;
+ if ( nHght )
+ {
+ if ( nHght > nWishedHeight )
+ nMax = nFactor;
+ else
+ {
+ if ( bUseCache )
+ aFactor[ nTmpIdx ] = (sal_uInt16)nFactor;
+ nMin = nFactor;
+ }
+
+ nFactor = ( nFactor * nWishedHeight ) / nHght;
+ bGrow = ( nFactor > nMin ) && ( nFactor < nMax );
+#if OSL_DEBUG_LEVEL > 1
+ if ( bGrow )
+ nGrow++;
+#endif
+ nIdx = rInf.GetIdx();
+ }
+ else
+ bGrow = sal_False;
+ }
+
+ if ( bWinUsed )
+ {
+ // reset window if it has been used
+ pWin->SetMapMode( aOldMap );
+ pWin->SetFont( aOldFnt );
+ }
+
+ if ( bUseCache )
+ aDescent[ nTmpIdx ] = -short( nDescent );
+ }
+
+ pCurrPart = pDrop->GetPart();
+
+ // did made any new calculations or did we use the cache?
+ if ( -1 == nFactor )
+ {
+ nFactor = aFactor[ nTmpIdx ];
+ nDescent = aDescent[ nTmpIdx ];
+ }
+ else
+ nDescent = -nDescent;
+
+ while ( pCurrPart )
+ {
+ // scale current font
+ SwFont& rFnt = pCurrPart->GetFont();
+ Size aNewSize( 0, ( nFactor * rFnt.GetHeight( rFnt.GetActual() ) ) / 1000 );
+
+ const sal_uInt8 nOldProp = rFnt.GetPropr();
+ rFnt.SetProportion( 100 );
+ rFnt.SetSize( aNewSize, rFnt.GetActual() );
+ rFnt.SetProportion( nOldProp );
+
+ pCurrPart = pCurrPart->GetFollow();
+ }
+ pDrop->SetY( (short)nDescent );
+}
+
+/*************************************************************************
+ * virtual Format()
+ *************************************************************************/
+
+sal_Bool SwDropPortion::Format( SwTxtFormatInfo &rInf )
+{
+ sal_Bool bFull = sal_False;
+ Fix( (sal_uInt16)rInf.X() );
+
+ SwLayoutModeModifier aLayoutModeModifier( *rInf.GetOut() );
+ aLayoutModeModifier.SetAuto();
+
+ if( nDropHeight && pPart && nLines!=1 )
+ {
+ if( !pDropCapCache )
+ pDropCapCache = new SwDropCapCache();
+
+ // adjust font sizes to fit into the rectangle
+ pDropCapCache->CalcFontSize( this, rInf );
+
+ const long nOldX = rInf.X();
+ {
+ SwDropSave aSave( rInf );
+ SwDropPortionPart* pCurrPart = pPart;
+
+ while ( pCurrPart )
+ {
+ rInf.SetLen( pCurrPart->GetLen() );
+ SwFont& rFnt = pCurrPart->GetFont();
+ {
+ SwFontSave aFontSave( rInf, &rFnt );
+ bFull = FormatTxt( rInf );
+
+ if ( bFull )
+ break;
+ }
+
+ const SwTwips nTmpWidth =
+ ( InSpaceGrp() && rInf.GetSpaceAdd() ) ?
+ Width() + CalcSpacing( rInf.GetSpaceAdd(), rInf ) :
+ Width();
+
+ // set values
+ pCurrPart->SetWidth( (sal_uInt16)nTmpWidth );
+
+ // Move
+ rInf.SetIdx( rInf.GetIdx() + pCurrPart->GetLen() );
+ rInf.X( rInf.X() + nTmpWidth );
+ pCurrPart = pCurrPart->GetFollow();
+ }
+
+ Width( (sal_uInt16)(rInf.X() - nOldX) );
+ }
+
+ // reset my length
+ SetLen( rInf.GetLen() );
+
+ // 7631, 7633: bei Ueberlappungen mit Flys ist Schluss.
+ if( ! bFull )
+ bFull = lcl_IsDropFlyInter( rInf, Width(), nDropHeight );
+
+ if( bFull )
+ {
+ // Durch FormatTxt kann nHeight auf 0 gesetzt worden sein
+ if ( !Height() )
+ Height( rInf.GetTxtHeight() );
+
+ // Jetzt noch einmal der ganze Spass
+ nDropHeight = nLines = 0;
+ delete pPart;
+ pPart = NULL;
+
+ // meanwhile use normal formatting
+ bFull = SwTxtPortion::Format( rInf );
+ }
+ else
+ rInf.SetDropInit( sal_True );
+
+ Height( rInf.GetTxtHeight() );
+ SetAscent( rInf.GetAscent() );
+ }
+ else
+ bFull = SwTxtPortion::Format( rInf );
+
+ if( bFull )
+ nDistance = 0;
+ else
+ {
+ const KSHORT nWant = Width() + GetDistance();
+ const KSHORT nRest = (sal_uInt16)(rInf.Width() - rInf.X());
+ if( ( nWant > nRest ) ||
+ lcl_IsDropFlyInter( rInf, Width() + GetDistance(), nDropHeight ) )
+ nDistance = 0;
+
+ Width( Width() + nDistance );
+ }
+ return bFull;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/text/txtfld.cxx b/sw/source/core/text/txtfld.cxx
new file mode 100644
index 000000000000..de1526462065
--- /dev/null
+++ b/sw/source/core/text/txtfld.cxx
@@ -0,0 +1,569 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+
+#include "hintids.hxx"
+#include <fmtfld.hxx>
+#include <txtfld.hxx>
+#include <charfmt.hxx>
+
+#include "viewsh.hxx" // NewFldPortion, GetDoc()
+#include "doc.hxx" // NewFldPortion, GetSysFldType()
+#include "rootfrm.hxx" // Info ueber virt. PageNumber
+#include "pagefrm.hxx" // NewFldPortion, GetVirtPageNum()
+#include "ndtxt.hxx" // NewNumberPortion, pHints->GetNum()
+#include "fldbas.hxx" // SwField
+#include "viewopt.hxx" // SwViewOptions
+#include "flyfrm.hxx" //IsInBody()
+#include "viewimp.hxx"
+#include "txtatr.hxx" // SwTxtFld
+#include "swfont.hxx" // NewFldPortion, new SwFont
+#include "fntcache.hxx" // NewFldPortion, SwFntAccess
+#include "porfld.hxx"
+#include "porftn.hxx" // NewExtraPortion
+#include "porref.hxx" // NewExtraPortion
+#include "portox.hxx" // NewExtraPortion
+#include "porhyph.hxx" // NewExtraPortion
+#include "porfly.hxx" // NewExtraPortion
+#include "itrform2.hxx" // SwTxtFormatter
+#include "chpfld.hxx"
+#include "dbfld.hxx"
+#include "expfld.hxx"
+#include "docufld.hxx"
+#include "pagedesc.hxx" // NewFldPortion, GetNum()
+#include <pormulti.hxx> // SwMultiPortion
+#include "fmtmeta.hxx" // lcl_NewMetaPortion
+
+
+/*************************************************************************
+ * SwTxtFormatter::NewFldPortion()
+ *************************************************************************/
+
+
+sal_Bool lcl_IsInBody( SwFrm *pFrm )
+{
+ if ( pFrm->IsInDocBody() )
+ return sal_True;
+ else
+ {
+ const SwFrm *pTmp = pFrm;
+ const SwFlyFrm *pFly;
+ while ( 0 != (pFly = pTmp->FindFlyFrm()) )
+ pTmp = pFly->GetAnchorFrm();
+ return pTmp->IsInDocBody();
+ }
+}
+
+
+SwExpandPortion *SwTxtFormatter::NewFldPortion( SwTxtFormatInfo &rInf,
+ const SwTxtAttr *pHint ) const
+{
+ SwExpandPortion *pRet = 0;
+ SwFrm *pFrame = (SwFrm*)pFrm;
+ SwField *pFld = (SwField*)pHint->GetFld().GetFld();
+ const sal_Bool bName = rInf.GetOpt().IsFldName();
+
+ SwCharFmt* pChFmt = 0;
+ sal_Bool bNewFlyPor = sal_False,
+ bINet = sal_False;
+
+ // set language
+ ((SwTxtFormatter*)this)->SeekAndChg( rInf );
+ if (pFld->GetLanguage() != GetFnt()->GetLanguage())
+ {
+ pFld->SetLanguage( GetFnt()->GetLanguage() );
+ // let the visual note know about its new language
+ if (pFld->GetTyp()->Which()==RES_POSTITFLD)
+ const_cast<SwFmtFld*> (&pHint->GetFld())->Broadcast( SwFmtFldHint( &pHint->GetFld(), SWFMTFLD_LANGUAGE ) );
+ }
+
+ ViewShell *pSh = rInf.GetVsh();
+ SwDoc *const pDoc( (pSh) ? pSh->GetDoc() : 0 );
+ bool const bInClipboard( (pDoc) ? pDoc->IsClipBoard() : true );
+ sal_Bool bPlaceHolder = sal_False;
+
+ switch( pFld->GetTyp()->Which() )
+ {
+ case RES_SCRIPTFLD:
+ case RES_POSTITFLD:
+ pRet = new SwPostItsPortion( RES_SCRIPTFLD == pFld->GetTyp()->Which() );
+ break;
+
+ case RES_COMBINED_CHARS:
+ {
+ if( bName )
+ {
+ String const sName( pFld->GetFieldName() );
+ pRet = new SwFldPortion(sName);
+ }
+ else
+ {
+ String const sContent( pFld->ExpandField(bInClipboard) );
+ pRet = new SwCombinedPortion(sContent);
+ }
+ }
+ break;
+
+ case RES_HIDDENTXTFLD:
+ {
+ String const str( (bName)
+ ? pFld->GetFieldName()
+ : pFld->ExpandField(bInClipboard) );
+ pRet = new SwHiddenPortion(str);
+ }
+ break;
+
+ case RES_CHAPTERFLD:
+ if( !bName && pSh && !pSh->Imp()->IsUpdateExpFlds() )
+ {
+ ((SwChapterField*)pFld)->ChangeExpansion( pFrame,
+ &((SwTxtFld*)pHint)->GetTxtNode() );
+ }
+ {
+ String const str( (bName)
+ ? pFld->GetFieldName()
+ : pFld->ExpandField(bInClipboard) );
+ pRet = new SwFldPortion( str );
+ }
+ break;
+
+ case RES_DOCSTATFLD:
+ if( !bName && pSh && !pSh->Imp()->IsUpdateExpFlds() )
+ {
+ ((SwDocStatField*)pFld)->ChangeExpansion( pFrame );
+ }
+ {
+ String const str( (bName)
+ ? pFld->GetFieldName()
+ : pFld->ExpandField(bInClipboard) );
+ pRet = new SwFldPortion( str );
+ }
+ break;
+
+ case RES_PAGENUMBERFLD:
+ {
+ if( !bName && pSh && pSh->GetLayout() && !pSh->Imp()->IsUpdateExpFlds() )//swmod 080122
+ {
+ SwPageNumberFieldType *pPageNr = (SwPageNumberFieldType *)pFld->GetTyp();
+
+ const SwRootFrm* pTmpRootFrm = pSh->GetLayout();
+ const sal_Bool bVirt = pTmpRootFrm->IsVirtPageNum();
+
+ MSHORT nVirtNum = pFrame->GetVirtPageNum();
+ MSHORT nNumPages = pTmpRootFrm->GetPageNum();
+ sal_Int16 nNumFmt = -1;
+ if(SVX_NUM_PAGEDESC == pFld->GetFormat())
+ nNumFmt = pFrame->FindPageFrm()->GetPageDesc()->GetNumType().GetNumberingType();
+
+ pPageNr->ChangeExpansion( pDoc, nVirtNum, nNumPages,
+ bVirt, nNumFmt > -1 ? &nNumFmt : 0);
+ }
+ {
+ String const str( (bName)
+ ? pFld->GetFieldName()
+ : pFld->ExpandField(bInClipboard) );
+ pRet = new SwFldPortion( str );
+ }
+ break;
+ }
+ case RES_GETEXPFLD:
+ {
+ if( !bName && pSh && !pSh->Imp()->IsUpdateExpFlds() )
+ {
+ SwGetExpField* pExpFld = (SwGetExpField*)pFld;
+ if( !::lcl_IsInBody( pFrame ) )
+ {
+ pExpFld->ChgBodyTxtFlag( sal_False );
+ pExpFld->ChangeExpansion( *pFrame, *((SwTxtFld*)pHint) );
+ }
+ else if( !pExpFld->IsInBodyTxt() )
+ {
+ // war vorher anders, also erst expandieren, dann umsetzen!!
+ pExpFld->ChangeExpansion( *pFrame, *((SwTxtFld*)pHint) );
+ pExpFld->ChgBodyTxtFlag( sal_True );
+ }
+ }
+ {
+ String const str( (bName)
+ ? pFld->GetFieldName()
+ : pFld->ExpandField(bInClipboard) );
+ pRet = new SwFldPortion( str );
+ }
+ break;
+ }
+ case RES_DBFLD:
+ {
+ if( !bName )
+ {
+ SwDBField* pDBFld = (SwDBField*)pFld;
+ pDBFld->ChgBodyTxtFlag( ::lcl_IsInBody( pFrame ) );
+ }
+ {
+ String const str( (bName)
+ ? pFld->GetFieldName()
+ : pFld->ExpandField(bInClipboard) );
+ pRet = new SwFldPortion(str);
+ }
+ break;
+ }
+ case RES_REFPAGEGETFLD:
+ if( !bName && pSh && !pSh->Imp()->IsUpdateExpFlds() )
+ {
+ ((SwRefPageGetField*)pFld)->ChangeExpansion( pFrame, (SwTxtFld*)pHint );
+ }
+ {
+ String const str( (bName)
+ ? pFld->GetFieldName()
+ : pFld->ExpandField(bInClipboard) );
+ pRet = new SwFldPortion(str);
+ }
+ break;
+
+ case RES_JUMPEDITFLD:
+ if( !bName )
+ pChFmt = ((SwJumpEditField*)pFld)->GetCharFmt();
+ bNewFlyPor = sal_True;
+ bPlaceHolder = sal_True;
+ break;
+
+ default:
+ {
+ String const str( (bName)
+ ? pFld->GetFieldName()
+ : pFld->ExpandField(bInClipboard) );
+ pRet = new SwFldPortion(str);
+ }
+ }
+
+ if( bNewFlyPor )
+ {
+ SwFont *pTmpFnt = 0;
+ if( !bName )
+ {
+ pTmpFnt = new SwFont( *pFnt );
+ if( bINet )
+ {
+ SwAttrPool* pPool = pChFmt->GetAttrSet().GetPool();
+ SfxItemSet aSet( *pPool, RES_CHRATR_BEGIN, RES_CHRATR_END );
+ SfxItemSet aTmpSet( aSet );
+ pFrm->GetTxtNode()->GetAttr(aSet,rInf.GetIdx(),rInf.GetIdx()+1);
+ aTmpSet.Set( pChFmt->GetAttrSet() );
+ aTmpSet.Differentiate( aSet );
+ if( aTmpSet.Count() )
+ pTmpFnt->SetDiffFnt( &aTmpSet, pFrm->GetTxtNode()->getIDocumentSettingAccess() );
+ }
+ else
+ pTmpFnt->SetDiffFnt( &pChFmt->GetAttrSet(), pFrm->GetTxtNode()->getIDocumentSettingAccess() );
+ }
+ {
+ String const str( (bName)
+ ? pFld->GetFieldName()
+ : pFld->ExpandField(bInClipboard) );
+ pRet = new SwFldPortion(str, pTmpFnt, bPlaceHolder);
+ }
+ }
+
+ return pRet;
+}
+
+/*************************************************************************
+ * SwTxtFormatter::TryNewNoLengthPortion()
+ *************************************************************************/
+
+SwFldPortion * lcl_NewMetaPortion(SwTxtAttr & rHint, const bool bPrefix)
+{
+ ::sw::Meta *const pMeta(
+ static_cast<SwFmtMeta &>(rHint.GetAttr()).GetMeta() );
+ ::rtl::OUString fix;
+ ::sw::MetaField *const pField( dynamic_cast< ::sw::MetaField * >(pMeta) );
+ OSL_ENSURE(pField, "lcl_NewMetaPortion: no meta field?");
+ if (pField)
+ {
+ pField->GetPrefixAndSuffix((bPrefix) ? &fix : 0, (bPrefix) ? 0 : &fix);
+ }
+ return new SwFldPortion( fix );
+}
+
+/** Try to create a new portion with zero length, for an end of a hint
+ (where there is no CH_TXTATR). Because there may be multiple hint ends at a
+ given index, m_nHintEndIndex is used to keep track of the already created
+ portions. But the portions created here may actually be deleted again,
+ due to UnderFlow. In that case, m_nHintEndIndex must be decremented,
+ so the portion will be created again on the next line.
+ */
+SwExpandPortion *
+SwTxtFormatter::TryNewNoLengthPortion(SwTxtFormatInfo & rInfo)
+{
+ if (pHints)
+ {
+ const xub_StrLen nIdx(rInfo.GetIdx());
+ while (m_nHintEndIndex < pHints->GetEndCount())
+ {
+ SwTxtAttr & rHint( *pHints->GetEnd(m_nHintEndIndex) );
+ xub_StrLen const nEnd( *rHint.GetAnyEnd() );
+ if (nEnd > nIdx)
+ {
+ break;
+ }
+ ++m_nHintEndIndex;
+ if (nEnd == nIdx)
+ {
+ if (RES_TXTATR_METAFIELD == rHint.Which())
+ {
+ SwFldPortion *const pPortion(
+ lcl_NewMetaPortion(rHint, false));
+ pPortion->SetNoLength(); // no CH_TXTATR at hint end!
+ return pPortion;
+ }
+ }
+ }
+ }
+ return 0;
+}
+
+/*************************************************************************
+ * SwTxtFormatter::NewExtraPortion()
+ *************************************************************************/
+
+SwLinePortion *SwTxtFormatter::NewExtraPortion( SwTxtFormatInfo &rInf )
+{
+ SwTxtAttr *pHint = GetAttr( rInf.GetIdx() );
+ SwLinePortion *pRet = 0;
+ if( !pHint )
+ {
+ pRet = new SwTxtPortion;
+ pRet->SetLen( 1 );
+ rInf.SetLen( 1 );
+ return pRet;
+ }
+
+ switch( pHint->Which() )
+ {
+ case RES_TXTATR_FLYCNT :
+ {
+ pRet = NewFlyCntPortion( rInf, pHint );
+ break;
+ }
+ case RES_TXTATR_FTN :
+ {
+ pRet = NewFtnPortion( rInf, pHint );
+ break;
+ }
+ case RES_TXTATR_FIELD :
+ {
+ pRet = NewFldPortion( rInf, pHint );
+ break;
+ }
+ case RES_TXTATR_REFMARK :
+ {
+ pRet = new SwIsoRefPortion;
+ break;
+ }
+ case RES_TXTATR_TOXMARK :
+ {
+ pRet = new SwIsoToxPortion;
+ break;
+ }
+ case RES_TXTATR_METAFIELD:
+ {
+ pRet = lcl_NewMetaPortion( *pHint, true );
+ break;
+ }
+ default: ;
+ }
+ if( !pRet )
+ {
+ const XubString aNothing;
+ pRet = new SwFldPortion( aNothing );
+ rInf.SetLen( 1 );
+ }
+ return pRet;
+}
+
+/*************************************************************************
+ * SwTxtFormatter::NewNumberPortion()
+ *************************************************************************/
+
+
+SwNumberPortion *SwTxtFormatter::NewNumberPortion( SwTxtFormatInfo &rInf ) const
+{
+ if( rInf.IsNumDone() || rInf.GetTxtStart() != nStart
+ || rInf.GetTxtStart() != rInf.GetIdx() )
+ return 0;
+
+ SwNumberPortion *pRet = 0;
+ const SwTxtNode* pTxtNd = GetTxtFrm()->GetTxtNode();
+ const SwNumRule* pNumRule = pTxtNd->GetNumRule();
+
+ // hat ein "gueltige" Nummer ?
+ if( pTxtNd->IsNumbered() && pTxtNd->IsCountedInList())
+ {
+ const SwNumFmt &rNumFmt = pNumRule->Get( static_cast<sal_uInt16>(pTxtNd->GetActualListLevel()) );
+ const sal_Bool bLeft = SVX_ADJUST_LEFT == rNumFmt.GetNumAdjust();
+ const sal_Bool bCenter = SVX_ADJUST_CENTER == rNumFmt.GetNumAdjust();
+ const bool bLabelAlignmentPosAndSpaceModeActive(
+ rNumFmt.GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_ALIGNMENT );
+ const KSHORT nMinDist = bLabelAlignmentPosAndSpaceModeActive
+ ? 0 : rNumFmt.GetCharTextDistance();
+
+ if( SVX_NUM_BITMAP == rNumFmt.GetNumberingType() )
+ {
+ pRet = new SwGrfNumPortion( (SwFrm*)GetTxtFrm(),
+ pTxtNd->GetLabelFollowedBy(),
+ rNumFmt.GetBrush(),
+ rNumFmt.GetGraphicOrientation(),
+ rNumFmt.GetGraphicSize(),
+ bLeft, bCenter, nMinDist,
+ bLabelAlignmentPosAndSpaceModeActive );
+ long nTmpA = rInf.GetLast()->GetAscent();
+ long nTmpD = rInf.GetLast()->Height() - nTmpA;
+ if( !rInf.IsTest() )
+ ((SwGrfNumPortion*)pRet)->SetBase( nTmpA, nTmpD, nTmpA, nTmpD );
+ }
+ else
+ {
+ // Der SwFont wird dynamisch angelegt und im CTOR uebergeben,
+ // weil das CharFmt nur einen SV-Font zurueckliefert.
+ // Im Dtor vom SwNumberPortion wird der SwFont deletet.
+ SwFont *pNumFnt = 0;
+ const SwAttrSet* pFmt = rNumFmt.GetCharFmt() ?
+ &rNumFmt.GetCharFmt()->GetAttrSet() :
+ NULL;
+ const IDocumentSettingAccess* pIDSA = pTxtNd->getIDocumentSettingAccess();
+
+ if( SVX_NUM_CHAR_SPECIAL == rNumFmt.GetNumberingType() )
+ {
+ const Font *pFmtFnt = rNumFmt.GetBulletFont();
+
+ //
+ // Build a new bullet font basing on the current paragraph font:
+ //
+ pNumFnt = new SwFont( &rInf.GetCharAttr(), pIDSA );
+
+ // --> FME 2005-08-11 #i53199#
+ if ( !pIDSA->get(IDocumentSettingAccess::DO_NOT_RESET_PARA_ATTRS_FOR_NUM_FONT) )
+ {
+ // i18463:
+ // Underline style of paragraph font should not be considered
+ // Overline style of paragraph font should not be considered
+ // Weight style of paragraph font should not be considered
+ // Posture style of paragraph font should not be considered
+ pNumFnt->SetUnderline( UNDERLINE_NONE );
+ pNumFnt->SetOverline( UNDERLINE_NONE );
+ pNumFnt->SetItalic( ITALIC_NONE, SW_LATIN );
+ pNumFnt->SetItalic( ITALIC_NONE, SW_CJK );
+ pNumFnt->SetItalic( ITALIC_NONE, SW_CTL );
+ pNumFnt->SetWeight( WEIGHT_NORMAL, SW_LATIN );
+ pNumFnt->SetWeight( WEIGHT_NORMAL, SW_CJK );
+ pNumFnt->SetWeight( WEIGHT_NORMAL, SW_CTL );
+ }
+
+ //
+ // Apply the explicit attributes from the character style
+ // associated with the numering to the new bullet font.
+ //
+ if( pFmt )
+ pNumFnt->SetDiffFnt( pFmt, pIDSA );
+
+ if ( pFmtFnt )
+ {
+ const sal_uInt8 nAct = pNumFnt->GetActual();
+ pNumFnt->SetFamily( pFmtFnt->GetFamily(), nAct );
+ pNumFnt->SetName( pFmtFnt->GetName(), nAct );
+ pNumFnt->SetStyleName( pFmtFnt->GetStyleName(), nAct );
+ pNumFnt->SetCharSet( pFmtFnt->GetCharSet(), nAct );
+ pNumFnt->SetPitch( pFmtFnt->GetPitch(), nAct );
+ }
+
+ // we do not allow a vertical font
+ pNumFnt->SetVertical( pNumFnt->GetOrientation(),
+ pFrm->IsVertical() );
+
+ // --> OD 2008-01-23 #newlistelevelattrs#
+ pRet = new SwBulletPortion( rNumFmt.GetBulletChar(),
+ pTxtNd->GetLabelFollowedBy(),
+ pNumFnt,
+ bLeft, bCenter, nMinDist,
+ bLabelAlignmentPosAndSpaceModeActive );
+ // <--
+ }
+ else
+ {
+ XubString aTxt( pTxtNd->GetNumString() );
+ if ( aTxt.Len() > 0 )
+ {
+ aTxt.Insert( pTxtNd->GetLabelFollowedBy() );
+ }
+
+ // 7974: Nicht nur eine Optimierung...
+ // Eine Numberportion ohne Text wird die Breite von 0
+ // erhalten. Die nachfolgende Textportion wird im BreakLine
+ // in das BreakCut laufen, obwohl rInf.GetLast()->GetFlyPortion()
+ // vorliegt!
+ if( aTxt.Len() )
+ {
+ //
+ // Build a new numbering font basing on the current paragraph font:
+ //
+ pNumFnt = new SwFont( &rInf.GetCharAttr(), pIDSA );
+
+ // --> FME 2005-08-11 #i53199#
+ if ( !pIDSA->get(IDocumentSettingAccess::DO_NOT_RESET_PARA_ATTRS_FOR_NUM_FONT) )
+ {
+ // i18463:
+ // Underline style of paragraph font should not be considered
+ pNumFnt->SetUnderline( UNDERLINE_NONE );
+ // Overline style of paragraph font should not be considered
+ pNumFnt->SetOverline( UNDERLINE_NONE );
+ }
+
+
+ //
+ // Apply the explicit attributes from the character style
+ // associated with the numering to the new bullet font.
+ //
+ if( pFmt )
+ pNumFnt->SetDiffFnt( pFmt, pIDSA );
+
+ // we do not allow a vertical font
+ pNumFnt->SetVertical( pNumFnt->GetOrientation(), pFrm->IsVertical() );
+
+ pRet = new SwNumberPortion( aTxt, pNumFnt,
+ bLeft, bCenter, nMinDist,
+ bLabelAlignmentPosAndSpaceModeActive );
+ }
+ }
+ }
+ }
+ return pRet;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/text/txtfly.cxx b/sw/source/core/text/txtfly.cxx
new file mode 100644
index 000000000000..0443b23d7cf6
--- /dev/null
+++ b/sw/source/core/text/txtfly.cxx
@@ -0,0 +1,2424 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+#include <vcl/outdev.hxx>
+#include <vcl/virdev.hxx>
+
+#include "viewsh.hxx"
+#include "pagefrm.hxx"
+#include "rootfrm.hxx"
+#include "viewimp.hxx" // SwViewImp
+#include "pam.hxx" // SwPosition
+#include "swregion.hxx" // SwRegionRects
+#include "dcontact.hxx" // SwContact
+#include "dflyobj.hxx" // SdrObject
+#include "flyfrm.hxx" // SwFlyFrm
+#include "frmtool.hxx" // ::DrawGraphic
+#include "porfld.hxx" // SwGrfNumPortion
+#include "txtfrm.hxx" // SwTxtFrm
+#include "itrform2.hxx" // SwTxtFormatter
+#include "porfly.hxx" // NewFlyCntPortion
+#include "porfld.hxx" // SwGrfNumPortion
+#include "txtfly.hxx" // SwTxtFly
+#include "txtpaint.hxx" // SwSaveClip
+#include "txtatr.hxx" // SwTxtFlyCnt
+#include "notxtfrm.hxx"
+#include "flyfrms.hxx"
+#include "fmtcnct.hxx" // SwFmtChain
+#include <pormulti.hxx> // SwMultiPortion
+#include <svx/obj3d.hxx>
+#include <editeng/txtrange.hxx>
+#include <editeng/lrspitem.hxx>
+#include <editeng/ulspitem.hxx>
+// --> OD 2004-06-16 #i28701#
+#include <editeng/lspcitem.hxx>
+// <--
+#include <txtflcnt.hxx>
+#include <fmtsrnd.hxx>
+#include <fmtanchr.hxx>
+#include <fmtflcnt.hxx>
+#include <frmfmt.hxx>
+#include <pagedesc.hxx> // SwPageDesc
+#include <tgrditem.hxx>
+#include <sortedobjs.hxx>
+#include <layouter.hxx>
+#include <IDocumentDrawModelAccess.hxx>
+#include <IDocumentLayoutAccess.hxx>
+#include <IDocumentSettingAccess.hxx>
+#include <svx/svdoedge.hxx>
+#include "doc.hxx"
+
+#if OSL_DEBUG_LEVEL > 1
+#include "viewopt.hxx" // SwViewOptions, nur zum Testen (Test2)
+#include "doc.hxx"
+#endif
+
+
+using namespace ::com::sun::star;
+
+/*****************************************************************************
+ * Beschreibung:
+ * Die Klasse SwTxtFly soll die Universalschnittstelle zwischen der
+ * Formatierung/Textausgabe und den u.U. ueberlappenden freifliegenden
+ * Frames sein.
+ * Waehrend der Formatierung erkundigt sich der Formatierer beim SwTxtFly,
+ * ob ein bestimmter Bereich durch die Attribute eines ueberlappenden
+ * Frames vorliegt. Solche Bereiche werden in Form von Dummy-Portions
+ * abgebildet.
+ * Die gesamte Textausgabe und Retusche wird ebenfalls an ein SwTxtFly
+ * weitergeleitet. Dieser entscheidet, ob Textteile geclippt werden muessen
+ * und zerteilt z.B. die Bereiche bei einem DrawRect.
+ * Zu beachten ist, dass alle freifliegenden Frames in einem nach TopLeft
+ * sortiertem PtrArray an der Seite zu finden sind. Intern wird immer nur
+ * in dokumentglobalen Werten gerechnet. Die IN- und OUT-Parameter sind
+ * jedoch in den meisten Faellen an die Beduerfnisse des LineIters
+ * zugeschnitten, d.h. sie werden in frame- oder windowlokalen Koordinaten
+ * konvertiert.
+ * Wenn mehrere Frames mit Umlaufattributen in einer Zeile liegen,
+ * ergeben sich unterschiedliche Auswirkungen fuer den Textfluss:
+ *
+ * L/R P L R K
+ * P -P-P- -P-L -P R- -P K
+ * L -L P- -L L -L R- -L K
+ * R R-P- R-L R R- R K
+ * K K P- K L K R- K K
+ *
+ * (P=parallel, L=links, R=rechts, K=kein Umlauf)
+ *
+ * Das Verhalten so beschreiben:
+ * Jeder Rahmen kann Text verdraengen, wobei der Einfluss allerdings nur
+ * bis zum naechsten Rahmen reicht.
+ *****************************************************************************/
+
+void SwTxtFormatter::CalcUnclipped( SwTwips& rTop, SwTwips& rBottom )
+{
+ OSL_ENSURE( ! pFrm->IsVertical() || pFrm->IsSwapped(),
+ "SwTxtFormatter::CalcUnclipped with unswapped frame" );
+
+ long nFlyAsc, nFlyDesc;
+ // OD 08.01.2004 #i11859# - use new method <SwLineLayout::MaxAscentDescent(..)>
+ //lcl_MaxAscDescent( pCurr, rTop, rBottom, nFlyAsc, nFlyDesc );
+ pCurr->MaxAscentDescent( rTop, rBottom, nFlyAsc, nFlyDesc );
+ rTop = Y() + GetCurr()->GetAscent();
+ rBottom = rTop + nFlyDesc;
+ rTop -= nFlyAsc;
+}
+
+/*************************************************************************
+ * SwTxtFormatter::UpdatePos() aktualisiert die Referenzpunkte der zeichengeb.
+ * Objekte, z. B. nach Adjustierung ( rechtsbuendig, Blocksatz etc. )
+ * ( hauptsaechlich Korrrektur der X-Position )
+ *************************************************************************/
+
+void SwTxtFormatter::UpdatePos( SwLineLayout *pCurrent, Point aStart,
+ xub_StrLen nStartIdx, sal_Bool bAllWays ) const
+{
+ OSL_ENSURE( ! pFrm->IsVertical() || pFrm->IsSwapped(),
+ "SwTxtFormatter::UpdatePos with unswapped frame" );
+
+ if( GetInfo().IsTest() )
+ return;
+ SwLinePortion *pFirst = pCurrent->GetFirstPortion();
+ SwLinePortion *pPos = pFirst;
+ SwTxtPaintInfo aTmpInf( GetInfo() );
+ aTmpInf.SetpSpaceAdd( pCurrent->GetpLLSpaceAdd() );
+ aTmpInf.ResetSpaceIdx();
+ aTmpInf.SetKanaComp( pCurrent->GetpKanaComp() );
+ aTmpInf.ResetKanaIdx();
+
+ // Die Groesse des Frames
+ aTmpInf.SetIdx( nStartIdx );
+ aTmpInf.SetPos( aStart );
+
+ long nTmpAscent, nTmpDescent, nFlyAsc, nFlyDesc;
+ // OD 08.01.2004 #i11859# - use new method <SwLineLayout::MaxAscentDescent(..)>
+ //lcl_MaxAscDescent( pPos, nTmpAscent, nTmpDescent, nFlyAsc, nFlyDesc );
+ pCurrent->MaxAscentDescent( nTmpAscent, nTmpDescent, nFlyAsc, nFlyDesc );
+
+ KSHORT nTmpHeight = pCurrent->GetRealHeight();
+ KSHORT nAscent = pCurrent->GetAscent() + nTmpHeight - pCurrent->Height();
+ objectpositioning::AsCharFlags nFlags = AS_CHAR_ULSPACE;
+ if( GetMulti() )
+ {
+ aTmpInf.SetDirection( GetMulti()->GetDirection() );
+ if( GetMulti()->HasRotation() )
+ {
+ nFlags |= AS_CHAR_ROTATE;
+ if( GetMulti()->IsRevers() )
+ {
+ nFlags |= AS_CHAR_REVERSE;
+ aTmpInf.X( aTmpInf.X() - nAscent );
+ }
+ else
+ aTmpInf.X( aTmpInf.X() + nAscent );
+ }
+ else
+ {
+ if ( GetMulti()->IsBidi() )
+ nFlags |= AS_CHAR_BIDI;
+ aTmpInf.Y( aTmpInf.Y() + nAscent );
+ }
+ }
+ else
+ aTmpInf.Y( aTmpInf.Y() + nAscent );
+
+ while( pPos )
+ {
+ // bislang ist mir nur ein Fall bekannt, wo die Positionsaenderung
+ // (verursacht durch das Adjustment) fuer eine Portion wichtig
+ // sein koennte: Bei FlyCntPortions muss ein SetRefPoint erfolgen.
+ if( ( pPos->IsFlyCntPortion() || pPos->IsGrfNumPortion() )
+ && ( bAllWays || !IsQuick() ) )
+ {
+ // OD 08.01.2004 #i11859# - use new method <SwLineLayout::MaxAscentDescent(..)>
+ //lcl_MaxAscDescent( pFirst, nTmpAscent, nTmpDescent,
+ // nFlyAsc, nFlyDesc, pPos );
+ pCurrent->MaxAscentDescent( nTmpAscent, nTmpDescent, nFlyAsc, nFlyDesc, pPos );
+
+ if( pPos->IsGrfNumPortion() )
+ {
+ if( !nFlyAsc && !nFlyDesc )
+ {
+ nTmpAscent = nAscent;
+ nFlyAsc = nAscent;
+ nTmpDescent = nTmpHeight - nAscent;
+ nFlyDesc = nTmpDescent;
+ }
+ ((SwGrfNumPortion*)pPos)->SetBase( nTmpAscent, nTmpDescent,
+ nFlyAsc, nFlyDesc );
+ }
+ else
+ {
+ Point aBase( aTmpInf.GetPos() );
+ if ( GetInfo().GetTxtFrm()->IsVertical() )
+ GetInfo().GetTxtFrm()->SwitchHorizontalToVertical( aBase );
+
+ ((SwFlyCntPortion*)pPos)->SetBase( *aTmpInf.GetTxtFrm(),
+ aBase, nTmpAscent, nTmpDescent, nFlyAsc,
+ nFlyDesc, nFlags );
+ }
+ }
+ if( pPos->IsMultiPortion() && ((SwMultiPortion*)pPos)->HasFlyInCntnt() )
+ {
+ OSL_ENSURE( !GetMulti(), "Too much multi" );
+ ((SwTxtFormatter*)this)->pMulti = (SwMultiPortion*)pPos;
+ SwLineLayout *pLay = &GetMulti()->GetRoot();
+ Point aSt( aTmpInf.X(), aStart.Y() );
+
+ if ( GetMulti()->HasBrackets() )
+ {
+ OSL_ENSURE( GetMulti()->IsDouble(), "Brackets only for doubles");
+ aSt.X() += ((SwDoubleLinePortion*)GetMulti())->PreWidth();
+ }
+ else if( GetMulti()->HasRotation() )
+ {
+ aSt.Y() += pCurrent->GetAscent() - GetMulti()->GetAscent();
+ if( GetMulti()->IsRevers() )
+ aSt.X() += GetMulti()->Width();
+ else
+ aSt.Y() += GetMulti()->Height();
+ }
+ else if ( GetMulti()->IsBidi() )
+ // jump to end of the bidi portion
+ aSt.X() += pLay->Width();
+
+ xub_StrLen nStIdx = aTmpInf.GetIdx();
+ do
+ {
+ UpdatePos( pLay, aSt, nStIdx, bAllWays );
+ nStIdx = nStIdx + pLay->GetLen();
+ aSt.Y() += pLay->Height();
+ pLay = pLay->GetNext();
+ } while ( pLay );
+ ((SwTxtFormatter*)this)->pMulti = NULL;
+ }
+ pPos->Move( aTmpInf );
+ pPos = pPos->GetPortion();
+ }
+}
+
+/*************************************************************************
+ * SwTxtFormatter::AlignFlyInCntBase()
+ * richtet die zeichengeb. Objekte in Y-Richtung ggf. neu aus.
+ *************************************************************************/
+
+void SwTxtFormatter::AlignFlyInCntBase( long nBaseLine ) const
+{
+ OSL_ENSURE( ! pFrm->IsVertical() || pFrm->IsSwapped(),
+ "SwTxtFormatter::AlignFlyInCntBase with unswapped frame" );
+
+ if( GetInfo().IsTest() )
+ return;
+ SwLinePortion *pFirst = pCurr->GetFirstPortion();
+ SwLinePortion *pPos = pFirst;
+ objectpositioning::AsCharFlags nFlags = AS_CHAR_NOFLAG;
+ if( GetMulti() && GetMulti()->HasRotation() )
+ {
+ nFlags |= AS_CHAR_ROTATE;
+ if( GetMulti()->IsRevers() )
+ nFlags |= AS_CHAR_REVERSE;
+ }
+
+ long nTmpAscent, nTmpDescent, nFlyAsc, nFlyDesc;
+
+ while( pPos )
+ {
+ if( pPos->IsFlyCntPortion() || pPos->IsGrfNumPortion() )
+ {
+ // OD 08.01.2004 #i11859# - use new method <SwLineLayout::MaxAscentDescent(..)>
+ //lcl_MaxAscDescent( pFirst, nTmpAscent, nTmpDescent,
+ // nFlyAsc, nFlyDesc, pPos );
+ pCurr->MaxAscentDescent( nTmpAscent, nTmpDescent, nFlyAsc, nFlyDesc, pPos );
+
+ if( pPos->IsGrfNumPortion() )
+ ((SwGrfNumPortion*)pPos)->SetBase( nTmpAscent, nTmpDescent,
+ nFlyAsc, nFlyDesc );
+ else
+ {
+ Point aBase;
+ if ( GetInfo().GetTxtFrm()->IsVertical() )
+ {
+ nBaseLine = GetInfo().GetTxtFrm()->SwitchHorizontalToVertical( nBaseLine );
+ aBase = Point( nBaseLine, ((SwFlyCntPortion*)pPos)->GetRefPoint().Y() );
+ }
+ else
+ aBase = Point( ((SwFlyCntPortion*)pPos)->GetRefPoint().X(), nBaseLine );
+
+ ((SwFlyCntPortion*)pPos)->SetBase( *GetInfo().GetTxtFrm(), aBase, nTmpAscent, nTmpDescent,
+ nFlyAsc, nFlyDesc, nFlags );
+ }
+ }
+ pPos = pPos->GetPortion();
+ }
+}
+
+/*************************************************************************
+ * SwTxtFly::ChkFlyUnderflow()
+ * This is called after the real height of the line has been calculated
+ * Therefore it is possible, that more flys from below intersect with the
+ * line, or that flys from above do not intersect with the line anymore
+ * We check this and return true if so, meaning that the line has to be
+ * formatted again
+ *************************************************************************/
+
+sal_Bool SwTxtFormatter::ChkFlyUnderflow( SwTxtFormatInfo &rInf ) const
+{
+ OSL_ENSURE( rInf.GetTxtFly()->IsOn(), "SwTxtFormatter::ChkFlyUnderflow: why?" );
+ if( GetCurr() )
+ {
+ // Erst pruefen wir, ob ueberhaupt ein Fly mit der Zeile ueberlappt.
+ // = GetLineHeight()
+ const long nHeight = GetCurr()->GetRealHeight();
+ SwRect aLine( GetLeftMargin(), Y(), rInf.RealWidth(), nHeight );
+
+ SwRect aLineVert( aLine );
+ if ( pFrm->IsVertical() )
+ pFrm->SwitchHorizontalToVertical( aLineVert );
+ SwRect aInter( rInf.GetTxtFly()->GetFrm( aLineVert ) );
+ if ( pFrm->IsVertical() )
+ pFrm->SwitchVerticalToHorizontal( aInter );
+
+ if( !aInter.HasArea() )
+ return sal_False;
+
+ // Nun ueberpruefen wir jede Portion, die sich haette senken koennen,
+ // ob sie mit dem Fly ueberlappt.
+ const SwLinePortion *pPos = GetCurr()->GetFirstPortion();
+ aLine.Pos().Y() = Y() + GetCurr()->GetRealHeight() - GetCurr()->Height();
+ aLine.Height( GetCurr()->Height() );
+
+ while( pPos )
+ {
+ aLine.Width( pPos->Width() );
+
+ aLineVert = aLine;
+ if ( pFrm->IsVertical() )
+ pFrm->SwitchHorizontalToVertical( aLineVert );
+ aInter = rInf.GetTxtFly()->GetFrm( aLineVert );
+ if ( pFrm->IsVertical() )
+ pFrm->SwitchVerticalToHorizontal( aInter );
+
+ // new flys from below?
+ if( !pPos->IsFlyPortion() )
+ {
+ if( aInter.IsOver( aLine ) )
+ {
+ aInter._Intersection( aLine );
+ if( aInter.HasArea() )
+ {
+ // to be evaluated during reformat of this line:
+ // RealHeight including spacing
+ rInf.SetLineHeight( KSHORT(nHeight) );
+ // Height without extra spacing
+ rInf.SetLineNettoHeight( KSHORT( pCurr->Height() ) );
+ return sal_True;
+ }
+ }
+ }
+ else
+ {
+ // the fly portion is not anylonger intersected by a fly
+ if ( ! aInter.IsOver( aLine ) )
+ {
+ rInf.SetLineHeight( KSHORT(nHeight) );
+ rInf.SetLineNettoHeight( KSHORT( pCurr->Height() ) );
+ return sal_True;
+ }
+ else
+ {
+ aInter._Intersection( aLine );
+
+ // no area means a fly has become invalid because of
+ // lowering the line => reformat the line
+ // we also have to reformat the line, if the fly size
+ // differs from the intersection intervals size
+ if( ! aInter.HasArea() ||
+ ((SwFlyPortion*)pPos)->GetFixWidth() != aInter.Width() )
+ {
+ rInf.SetLineHeight( KSHORT(nHeight) );
+ rInf.SetLineNettoHeight( KSHORT( pCurr->Height() ) );
+ return sal_True;
+ }
+ }
+ }
+
+ aLine.Left( aLine.Left() + pPos->Width() );
+ pPos = pPos->GetPortion();
+ }
+ }
+ return sal_False;
+}
+
+/*************************************************************************
+ * SwTxtFormatter::CalcFlyWidth()
+ * ermittelt das naechste Objekt, das in die restliche Zeile ragt und
+ * konstruiert die zugehoerige FlyPortion.
+ * Dazu wird SwTxtFly.GetFrm(..) benutzt.
+ *************************************************************************/
+
+// Durch Flys kann sich der rechte Rand verkuerzen.
+
+void SwTxtFormatter::CalcFlyWidth( SwTxtFormatInfo &rInf )
+{
+ if( GetMulti() || rInf.GetFly() )
+ return;
+
+ SwTxtFly *pTxtFly = rInf.GetTxtFly();
+ if( !pTxtFly->IsOn() || rInf.IsIgnoreFly() )
+ return;
+
+ const SwLinePortion *pLast = rInf.GetLast();
+
+ long nAscent;
+ long nTop = Y();
+ long nHeight;
+
+ if( rInf.GetLineHeight() )
+ {
+ // real line height has already been calculated, we only have to
+ // search for intersections in the lower part of the strip
+ nAscent = pCurr->GetAscent();
+ nHeight = rInf.GetLineNettoHeight();
+ nTop += rInf.GetLineHeight() - nHeight;
+ }
+ else
+ {
+ nAscent = pLast->GetAscent();
+ nHeight = pLast->Height();
+
+ // we make a first guess for the lines real height
+ if ( ! pCurr->GetRealHeight() )
+ CalcRealHeight();
+
+ if ( pCurr->GetRealHeight() > nHeight )
+ nTop += pCurr->GetRealHeight() - nHeight;
+ else
+ // important for fixed space between lines
+ nHeight = pCurr->GetRealHeight();
+ }
+
+ const long nLeftMar = GetLeftMargin();
+ const long nLeftMin = (rInf.X() || GetDropLeft()) ? nLeftMar : GetLeftMin();
+
+ SwRect aLine( rInf.X() + nLeftMin, nTop, rInf.RealWidth() - rInf.X()
+ + nLeftMar - nLeftMin , nHeight );
+
+ SwRect aLineVert( aLine );
+ if ( pFrm->IsRightToLeft() )
+ pFrm->SwitchLTRtoRTL( aLineVert );
+
+ if ( pFrm->IsVertical() )
+ pFrm->SwitchHorizontalToVertical( aLineVert );
+ SwRect aInter( pTxtFly->GetFrm( aLineVert ) );
+
+ if ( pFrm->IsRightToLeft() )
+ pFrm->SwitchRTLtoLTR( aInter );
+
+ if ( pFrm->IsVertical() )
+ pFrm->SwitchVerticalToHorizontal( aInter );
+
+ if( aInter.IsOver( aLine ) )
+ {
+ aLine.Left( rInf.X() + nLeftMar );
+ sal_Bool bForced = sal_False;
+ if( aInter.Left() <= nLeftMin )
+ {
+ SwTwips nFrmLeft = GetTxtFrm()->Frm().Left();
+ if( GetTxtFrm()->Prt().Left() < 0 )
+ nFrmLeft += GetTxtFrm()->Prt().Left();
+ if( aInter.Left() < nFrmLeft )
+ aInter.Left( nFrmLeft );
+
+ long nAddMar = 0;
+ if ( pFrm->IsRightToLeft() )
+ {
+ nAddMar = pFrm->Frm().Right() - Right();
+ if ( nAddMar < 0 )
+ nAddMar = 0;
+ }
+ else
+ nAddMar = nLeftMar - nFrmLeft;
+
+ aInter.Width( aInter.Width() + nAddMar );
+ // Bei negativem Erstzeileneinzug setzen wir das Flag,
+ // um anzuzeigen, dass der Einzug/Rand verschoben wurde
+ // Dies muss beim DefaultTab an der Nullposition beruecksichtigt
+ // werden.
+ if( IsFirstTxtLine() && HasNegFirst() )
+ bForced = sal_True;
+ }
+ aInter.Intersection( aLine );
+ if( !aInter.HasArea() )
+ return;
+
+ const sal_Bool bFullLine = aLine.Left() == aInter.Left() &&
+ aLine.Right() == aInter.Right();
+
+ // Obwohl kein Text mehr da ist, muss eine weitere Zeile
+ // formatiert werden, weil auch leere Zeilen einem Fly
+ // ohne Umlauf ausweichen muessen.
+ if( bFullLine && rInf.GetIdx() == rInf.GetTxt().Len() )
+ {
+ rInf.SetNewLine( sal_True );
+ // 8221: Dummies erkennt man an Ascent == Height
+ pCurr->SetDummy(sal_True);
+ }
+
+ // aInter wird framelokal
+ aInter.Pos().X() -= nLeftMar;
+ SwFlyPortion *pFly = new SwFlyPortion( aInter );
+ if( bForced )
+ {
+ pCurr->SetForcedLeftMargin( sal_True );
+ rInf.ForcedLeftMargin( (sal_uInt16)aInter.Width() );
+ }
+
+ if( bFullLine )
+ {
+ // 8110: wir muessen um Einheiten von Zeilenhoehen anwachsen,
+ // um nebeneinanderliegende Flys mit unterschiedlichen
+ // Umlaufattributen angemessen zu umfliessen.
+ // Die letzte ausweichende Zeile, sollte in der Hoehe angepasst
+ // sein, damit nicht der Eindruck von "Rahmenabstaenden" aufkommt.
+ // 8221: Wichtig ist, dass Ascent == Height ist, weil die FlyPortionWerte
+ // im CalcLine in pCurr uebertragen werden und IsDummy() darauf
+ // angewiesen ist.
+ // Es gibt meines Wissens nur zwei Stellen, in denen DummyLines
+ // entstehen koennen: hier und in MakeFlyDummies.
+ // Ausgewertet wird IsDummy() in IsFirstTxtLine() und
+ // beim Zeilenwandern und im Zusammenhang mit DropCaps.
+ pFly->Height( KSHORT(aInter.Height()) );
+
+ // In nNextTop steckt jetzt die Unterkante des Rahmens, dem wir
+ // ausweichen oder die Oberkante des naechsten Rahmens, den wir
+ // beachten muessen. Wir koennen also jetzt getrost bis zu diesem
+ // Wert anwachsen, so sparen wir einige Leerzeilen.
+ long nNextTop = pTxtFly->GetNextTop();
+ if ( pFrm->IsVertical() )
+ nNextTop = pFrm->SwitchVerticalToHorizontal( nNextTop );
+ if( nNextTop > aInter.Bottom() )
+ {
+ SwTwips nH = nNextTop - aInter.Top();
+ if( nH < KSHRT_MAX )
+ pFly->Height( KSHORT( nH ) );
+ }
+ if( nAscent < pFly->Height() )
+ pFly->SetAscent( KSHORT(nAscent) );
+ else
+ pFly->SetAscent( pFly->Height() );
+ }
+ else
+ {
+ if( rInf.GetIdx() == rInf.GetTxt().Len() )
+ {
+ // Nicht nHeight nehmen, sonst haben wir einen Riesendescent
+ pFly->Height( pLast->Height() );
+ pFly->SetAscent( pLast->GetAscent() );
+ }
+ else
+ {
+ pFly->Height( KSHORT(aInter.Height()) );
+ if( nAscent < pFly->Height() )
+ pFly->SetAscent( KSHORT(nAscent) );
+ else
+ pFly->SetAscent( pFly->Height() );
+ }
+ }
+
+ rInf.SetFly( pFly );
+
+ if( pFly->Fix() < rInf.Width() )
+ rInf.Width( pFly->Fix() );
+
+ GETGRID( pFrm->FindPageFrm() )
+ if ( pGrid )
+ {
+ const SwPageFrm* pPageFrm = pFrm->FindPageFrm();
+ const SwLayoutFrm* pBody = pPageFrm->FindBodyCont();
+
+ SWRECTFN( pPageFrm )
+
+ const long nGridOrigin = pBody ?
+ (pBody->*fnRect->fnGetPrtLeft)() :
+ (pPageFrm->*fnRect->fnGetPrtLeft)();
+
+ const SwDoc *pDoc = rInf.GetTxtFrm()->GetNode()->GetDoc();
+ const sal_uInt16 nGridWidth = GETGRIDWIDTH( pGrid, pDoc); //for textgrid refactor
+
+ SwTwips nStartX = GetLeftMargin();
+ if ( bVert )
+ {
+ Point aPoint( nStartX, 0 );
+ pFrm->SwitchHorizontalToVertical( aPoint );
+ nStartX = aPoint.Y();
+ }
+
+ const SwTwips nOfst = nStartX - nGridOrigin;
+ const SwTwips nTmpWidth = rInf.Width() + nOfst;
+
+ const sal_uLong i = nTmpWidth / nGridWidth + 1;
+
+ const long nNewWidth = ( i - 1 ) * nGridWidth - nOfst;
+ if ( nNewWidth > 0 )
+ rInf.Width( (sal_uInt16)nNewWidth );
+ else
+ rInf.Width( 0 );
+ }
+ }
+}
+
+/*****************************************************************************
+ * SwTxtFormatter::NewFlyCntPortion
+ * legt eine neue Portion fuer ein zeichengebundenes Objekt an.
+ *****************************************************************************/
+
+SwFlyCntPortion *SwTxtFormatter::NewFlyCntPortion( SwTxtFormatInfo &rInf,
+ SwTxtAttr *pHint ) const
+{
+ SwFlyCntPortion *pRet = 0;
+ const SwFrm *pFrame = (SwFrm*)pFrm;
+
+ SwFlyInCntFrm *pFly;
+ SwFrmFmt* pFrmFmt = ((SwTxtFlyCnt*)pHint)->GetFlyCnt().GetFrmFmt();
+ if( RES_FLYFRMFMT == pFrmFmt->Which() )
+ pFly = ((SwTxtFlyCnt*)pHint)->GetFlyFrm(pFrame);
+ else
+ pFly = NULL;
+ // aBase bezeichnet die dokumentglobale Position,
+ // ab der die neue Extraportion plaziert wird.
+ // aBase.X() = Offset in der Zeile,
+ // hinter der aktuellen Portion
+ // aBase.Y() = LineIter.Y() + Ascent der aktuellen Portion
+
+ long nTmpAscent, nTmpDescent, nFlyAsc, nFlyDesc;
+ // OD 08.01.2004 #i11859# - use new method <SwLineLayout::MaxAscentDescent(..)>
+ //SwLinePortion *pPos = pCurr->GetFirstPortion();
+ //lcl_MaxAscDescent( pPos, nTmpAscent, nTmpDescent, nFlyAsc, nFlyDesc );
+ pCurr->MaxAscentDescent( nTmpAscent, nTmpDescent, nFlyAsc, nFlyDesc );
+
+ // Wenn der Ascent des Rahmens groesser als der Ascent der akt. Portion
+ // ist, wird dieser bei der Base-Berechnung verwendet, sonst wuerde
+ // der Rahmen zunaechst zu weit nach oben gesetzt, um dann doch wieder
+ // nach unten zu rutschen und dabei ein Repaint in einem Bereich ausloesen,
+ // indem er niemals wirklich war.
+ KSHORT nAscent = 0;
+
+ const bool bTxtFrmVertical = GetInfo().GetTxtFrm()->IsVertical();
+
+ const bool bUseFlyAscent = pFly && pFly->GetValidPosFlag() &&
+ 0 != ( bTxtFrmVertical ?
+ pFly->GetRefPoint().X() :
+ pFly->GetRefPoint().Y() );
+
+ if ( bUseFlyAscent )
+ nAscent = static_cast<sal_uInt16>( Abs( int( bTxtFrmVertical ?
+ pFly->GetRelPos().X() :
+ pFly->GetRelPos().Y() ) ) );
+
+ // check if be prefer to use the ascent of the last portion:
+ if ( IsQuick() ||
+ !bUseFlyAscent ||
+ nAscent < rInf.GetLast()->GetAscent() )
+ {
+ nAscent = rInf.GetLast()->GetAscent();
+ }
+ else if( nAscent > nFlyAsc )
+ nFlyAsc = nAscent;
+
+ Point aBase( GetLeftMargin() + rInf.X(), Y() + nAscent );
+ objectpositioning::AsCharFlags nMode = IsQuick() ? AS_CHAR_QUICK : 0;
+ if( GetMulti() && GetMulti()->HasRotation() )
+ {
+ nMode |= AS_CHAR_ROTATE;
+ if( GetMulti()->IsRevers() )
+ nMode |= AS_CHAR_REVERSE;
+ }
+
+ Point aTmpBase( aBase );
+ if ( GetInfo().GetTxtFrm()->IsVertical() )
+ GetInfo().GetTxtFrm()->SwitchHorizontalToVertical( aTmpBase );
+
+ if( pFly )
+ {
+ pRet = new SwFlyCntPortion( *GetInfo().GetTxtFrm(), pFly, aTmpBase,
+ nTmpAscent, nTmpDescent, nFlyAsc, nFlyDesc, nMode );
+ // Wir muessen sicherstellen, dass unser Font wieder im OutputDevice
+ // steht. Es koennte sein, dass der FlyInCnt frisch eingefuegt wurde,
+ // dann hat GetFlyFrm dazu gefuehrt, dass er neu angelegt wird.
+ // Dessen Frames werden sofort formatiert, die verstellen den Font
+ // und schon haben wir den Salat (3322).
+ rInf.SelectFont();
+ if( pRet->GetAscent() > nAscent )
+ {
+ aBase.Y() = Y() + pRet->GetAscent();
+ nMode |= AS_CHAR_ULSPACE;
+ if( !rInf.IsTest() )
+ aTmpBase = aBase;
+ if ( GetInfo().GetTxtFrm()->IsVertical() )
+ GetInfo().GetTxtFrm()->SwitchHorizontalToVertical( aTmpBase );
+
+ pRet->SetBase( *rInf.GetTxtFrm(), aTmpBase, nTmpAscent,
+ nTmpDescent, nFlyAsc, nFlyDesc, nMode );
+ }
+ }
+ else
+ {
+ pRet = new SwFlyCntPortion( *rInf.GetTxtFrm(), (SwDrawContact*)pFrmFmt->FindContactObj(),
+ aTmpBase, nTmpAscent, nTmpDescent, nFlyAsc, nFlyDesc, nMode );
+ }
+ return pRet;
+}
+
+
+
+/*************************************************************************
+ * SwTxtFly::SwTxtFly()
+ *************************************************************************/
+
+SwTxtFly::SwTxtFly( const SwTxtFly& rTxtFly )
+{
+ pPage = rTxtFly.pPage;
+ mpCurrAnchoredObj = rTxtFly.mpCurrAnchoredObj;
+ pCurrFrm = rTxtFly.pCurrFrm;
+ pMaster = rTxtFly.pMaster;
+ if( rTxtFly.mpAnchoredObjList )
+ {
+ mpAnchoredObjList = new SwAnchoredObjList( *(rTxtFly.mpAnchoredObjList) );
+ }
+ else
+ {
+ mpAnchoredObjList = NULL;
+ }
+
+ bOn = rTxtFly.bOn;
+ bLeftSide = rTxtFly.bLeftSide;
+ bTopRule = rTxtFly.bTopRule;
+ nMinBottom = rTxtFly.nMinBottom;
+ nNextTop = rTxtFly.nNextTop;
+ nIndex = rTxtFly.nIndex;
+ mbIgnoreCurrentFrame = rTxtFly.mbIgnoreCurrentFrame;
+ mbIgnoreContour = rTxtFly.mbIgnoreContour;
+ mbIgnoreObjsInHeaderFooter = rTxtFly.mbIgnoreObjsInHeaderFooter;
+}
+
+void SwTxtFly::CtorInitTxtFly( const SwTxtFrm *pFrm )
+{
+ mbIgnoreCurrentFrame = sal_False;
+ mbIgnoreContour = sal_False;
+ // --> OD 2004-12-17 #118809#
+ mbIgnoreObjsInHeaderFooter = sal_False;
+ // <--
+ pPage = pFrm->FindPageFrm();
+ const SwFlyFrm* pTmp = pFrm->FindFlyFrm();
+ // --> OD 2006-08-15 #i68520#
+ mpCurrAnchoredObj = pTmp;
+ // <--
+ pCurrFrm = pFrm;
+ pMaster = pCurrFrm->IsFollow() ? NULL : pCurrFrm;
+ // --> OD 2006-08-15 #i68520#
+ mpAnchoredObjList = NULL;
+ // <--
+ // Wenn wir nicht von einem Frame ueberlappt werden, oder wenn
+ // es gar keine FlyCollection gibt, dann schaltet wir uns fuer immer ab.
+ // Aber es koennte sein, dass waehrend der Formatierung eine Zeile
+ // hinzukommt, die in einen Frame hineinragt. Deswegen keine Optimierung
+ // per bOn = pSortedFlys && IsAnyFrm();
+ bOn = pPage->GetSortedObjs() != 0;
+ bTopRule = sal_True;
+ bLeftSide = sal_False;
+ nMinBottom = 0;
+ nIndex = ULONG_MAX;
+}
+
+/*************************************************************************
+ * SwTxtFly::_GetFrm()
+ *
+ * IN: dokumentglobal (rRect)
+ * OUT: framelokal (return-Wert)
+ * Diese Methode wird waehrend der Formatierung vom LineIter gerufen.
+ * 1. um die naechste FlyPortion vorzubereiten
+ * 2. um nach Aenderung der Zeilenhoehe neue Ueberlappungen festzustellen
+ *************************************************************************/
+
+SwRect SwTxtFly::_GetFrm( const SwRect &rRect, sal_Bool bTop ) const
+{
+ SwRect aRet;
+ if( ForEach( rRect, &aRet, sal_True ) )
+ {
+ SWRECTFN( pCurrFrm )
+ if( bTop )
+ (aRet.*fnRect->fnSetTop)( (rRect.*fnRect->fnGetTop)() );
+
+ // 8110: Bottom nicht immer anpassen.
+ const SwTwips nRetBottom = (aRet.*fnRect->fnGetBottom)();
+ const SwTwips nRectBottom = (rRect.*fnRect->fnGetBottom)();
+ if ( (*fnRect->fnYDiff)( nRetBottom, nRectBottom ) > 0 ||
+ (aRet.*fnRect->fnGetHeight)() < 0 )
+ (aRet.*fnRect->fnSetBottom)( nRectBottom );
+ }
+ return aRet;
+}
+
+/*************************************************************************
+ * SwTxtFly::IsAnyFrm()
+ *
+ * IN: dokumentglobal
+ * fuer die Printarea des aktuellen Frame
+ *
+ * dient zum Abschalten des SwTxtFly, wenn keine Objekte ueberlappen (Relax)
+ *
+ *************************************************************************/
+
+sal_Bool SwTxtFly::IsAnyFrm() const
+{
+ SWAP_IF_SWAPPED( pCurrFrm )
+
+ OSL_ENSURE( bOn, "IsAnyFrm: Why?" );
+ SwRect aRect( pCurrFrm->Frm().Pos() + pCurrFrm->Prt().Pos(),
+ pCurrFrm->Prt().SSize() );
+
+ const sal_Bool bRet = ForEach( aRect, NULL, sal_False );
+ UNDO_SWAP( pCurrFrm )
+ return bRet;
+}
+
+/*************************************************************************
+ * SwTxtFly::IsAnyObj()
+ *
+ * IN: dokumentglobal
+ * OUT: sal_True Wenn ein Rahmen oder DrawObj beruecksichtigt werden muss
+ * Nur wenn IsAnyObj sal_False liefert, koennen Optimierungen benutzt werden
+ * wie Paint/FormatEmpty fuer leere Absaetze
+ * und auch das virtuelle Outputdevice.
+ *************************************************************************/
+
+sal_Bool SwTxtFly::IsAnyObj( const SwRect &rRect ) const
+{
+ OSL_ENSURE( bOn, "SwTxtFly::IsAnyObj: Who's knocking?" );
+
+ SwRect aRect( rRect );
+ if ( aRect.IsEmpty() )
+ aRect = SwRect( pCurrFrm->Frm().Pos() + pCurrFrm->Prt().Pos(),
+ pCurrFrm->Prt().SSize() );
+
+ const SwSortedObjs *pSorted = pPage->GetSortedObjs();
+ if( pSorted ) // Eigentlich ist durch bOn sichergestellt, dass es an der
+ // Seite Objekte gibt, aber wer weiss, wer inzwischen etwas geloescht hat.
+ {
+ for ( MSHORT i = 0; i < pSorted->Count(); ++i )
+ {
+ const SwAnchoredObject* pObj = (*pSorted)[i];
+
+ const SwRect aBound( pObj->GetObjRectWithSpaces() );
+
+ // Optimierung
+ if( pObj->GetObjRect().Left() > aRect.Right() )
+ continue;
+
+ // --> OD 2006-08-15 #i68520#
+ if( mpCurrAnchoredObj != pObj && aBound.IsOver( aRect ) )
+ // <--
+ return sal_True;
+ }
+ }
+ return sal_False;
+}
+
+const SwCntntFrm* SwTxtFly::_GetMaster()
+{
+ pMaster = pCurrFrm;
+ while( pMaster->IsFollow() )
+ pMaster = (SwCntntFrm*)pMaster->FindMaster();
+ return pMaster;
+}
+
+/*************************************************************************
+ * SwTxtFly::DrawTextOpaque()
+ *
+ * IN: dokumentglobal
+ * DrawTextOpaque() wird von DrawText() gerufen.
+ * Die Clipregions werden so gesetzt, dass nur die Teile ausgegeben werden,
+ * die nicht in den Bereichen von FlyFrms liegen, die undurchsichtig und
+ * ueber dem aktuellen Frame liegen.
+ * Die On-Optimierung uebernimmt DrawText()!
+ *************************************************************************/
+
+sal_Bool SwTxtFly::DrawTextOpaque( SwDrawTextInfo &rInf )
+{
+ SwSaveClip aClipSave( rInf.GetpOut() );
+ SwRect aRect( rInf.GetPos(), rInf.GetSize() );
+ if( rInf.GetSpace() )
+ {
+ xub_StrLen nTmpLen = STRING_LEN == rInf.GetLen() ? rInf.GetText().Len() :
+ rInf.GetLen();
+ if( rInf.GetSpace() > 0 )
+ {
+ xub_StrLen nSpaceCnt = 0;
+ const xub_StrLen nEndPos = rInf.GetIdx() + nTmpLen;
+ for( xub_StrLen nPos = rInf.GetIdx(); nPos < nEndPos; ++nPos )
+ {
+ if( CH_BLANK == rInf.GetText().GetChar( nPos ) )
+ ++nSpaceCnt;
+ }
+ if( nSpaceCnt )
+ aRect.Width( aRect.Width() + nSpaceCnt * rInf.GetSpace() );
+ }
+ else
+ aRect.Width( aRect.Width() - nTmpLen * rInf.GetSpace() );
+ }
+
+ if( aClipSave.IsOn() && rInf.GetOut().IsClipRegion() )
+ {
+ SwRect aClipRect( rInf.GetOut().GetClipRegion().GetBoundRect() );
+ aRect.Intersection( aClipRect );
+ }
+
+ SwRegionRects aRegion( aRect );
+
+ sal_Bool bOpaque = sal_False;
+ // --> OD 2006-08-15 #i68520#
+ const sal_uInt32 nCurrOrd = mpCurrAnchoredObj
+ ? mpCurrAnchoredObj->GetDrawObj()->GetOrdNum()
+ : SAL_MAX_UINT32;
+ // <--
+ OSL_ENSURE( !bTopRule, "DrawTextOpaque: Wrong TopRule" );
+
+ // --> OD 2006-08-15 #i68520#
+ SwAnchoredObjList::size_type nCount( bOn ? GetAnchoredObjList()->size() : 0 );
+ if ( bOn && nCount > 0 )
+ // <--
+ {
+ MSHORT nHellId = pPage->getRootFrm()->GetCurrShell()->getIDocumentDrawModelAccess()->GetHellId();
+ for( MSHORT i = 0; i < nCount; ++i )
+ {
+ // --> OD 2006-08-15 #i68520#
+ const SwAnchoredObject* pTmpAnchoredObj = (*mpAnchoredObjList)[i];
+ if( dynamic_cast<const SwFlyFrm*>(pTmpAnchoredObj) &&
+ mpCurrAnchoredObj != pTmpAnchoredObj )
+ // <--
+ {
+ // --> OD 2006-08-15 #i68520#
+ const SwFlyFrm* pFly = dynamic_cast<const SwFlyFrm*>(pTmpAnchoredObj);
+ // <--
+ if( aRegion.GetOrigin().IsOver( pFly->Frm() ) )
+ {
+ const SwFrmFmt *pFmt = pFly->GetFmt();
+ const SwFmtSurround &rSur = pFmt->GetSurround();
+ const SwFmtAnchor& rAnchor = pFmt->GetAnchor();
+ //Nur undurchsichtige und weiter oben liegende.
+ /// OD 08.10.2002 #103898# - add condition
+ /// <!(pFly->IsBackgroundTransparent() || pFly->IsShadowTransparent())>
+ if( !( pFly->IsBackgroundTransparent()
+ || pFly->IsShadowTransparent() ) &&
+ SURROUND_THROUGHT == rSur.GetSurround() &&
+ ( !rSur.IsAnchorOnly() ||
+ // --> OD 2006-08-15 #i68520#
+ GetMaster() == pFly->GetAnchorFrm() ||
+ // <--
+ ((FLY_AT_PARA != rAnchor.GetAnchorId()) &&
+ (FLY_AT_CHAR != rAnchor.GetAnchorId())
+ )
+ ) &&
+ // --> OD 2006-08-15 #i68520#
+ pTmpAnchoredObj->GetDrawObj()->GetLayer() != nHellId &&
+ nCurrOrd < pTmpAnchoredObj->GetDrawObj()->GetOrdNum()
+ // <--
+ )
+ {
+ //Ausser der Inhalt ist Transparent
+ const SwNoTxtFrm *pNoTxt =
+ pFly->Lower() && pFly->Lower()->IsNoTxtFrm()
+ ? (SwNoTxtFrm*)pFly->Lower()
+ : 0;
+ if ( !pNoTxt ||
+ (!pNoTxt->IsTransparent() && !rSur.IsContour()) )
+ {
+ bOpaque = sal_True;
+ aRegion -= pFly->Frm();
+ }
+ }
+ }
+ }
+ }
+ }
+
+ Point aPos( rInf.GetPos().X(), rInf.GetPos().Y() + rInf.GetAscent() );
+ const Point &rOld = rInf.GetPos();
+ rInf.SetPos( aPos );
+
+ if( !bOpaque )
+ {
+ if( rInf.GetKern() )
+ rInf.GetFont()->_DrawStretchText( rInf );
+ else
+ rInf.GetFont()->_DrawText( rInf );
+ rInf.SetPos( rOld );
+ return sal_False;
+ }
+ else if( aRegion.Count() )
+ {
+ // Was fuer ein Aufwand ...
+ SwSaveClip aClipVout( rInf.GetpOut() );
+ for( MSHORT i = 0; i < aRegion.Count(); ++i )
+ {
+ SwRect &rRect = aRegion[i];
+ if( rRect != aRegion.GetOrigin() )
+ aClipVout.ChgClip( rRect );
+ if( rInf.GetKern() )
+ rInf.GetFont()->_DrawStretchText( rInf );
+ else
+ rInf.GetFont()->_DrawText( rInf );
+ }
+ }
+ rInf.SetPos( rOld );
+ return sal_True;
+}
+
+/*************************************************************************
+ * SwTxtFly::DrawFlyRect()
+ *
+ * IN: windowlokal
+ * Zwei Feinheiten gilt es zu beachten:
+ * 1) DrawRect() oberhalb des ClipRects sind erlaubt !
+ * 2) FlyToRect() liefert groessere Werte als die Framedaten !
+ *************************************************************************/
+
+void SwTxtFly::DrawFlyRect( OutputDevice* pOut, const SwRect &rRect,
+ const SwTxtPaintInfo &rInf, sal_Bool bNoGraphic )
+{
+ SwRegionRects aRegion( rRect );
+ OSL_ENSURE( !bTopRule, "DrawFlyRect: Wrong TopRule" );
+ // --> OD 2006-08-15 #i68520#
+ SwAnchoredObjList::size_type nCount( bOn ? GetAnchoredObjList()->size() : 0 );
+ if ( bOn && nCount > 0 )
+ // <--
+ {
+ MSHORT nHellId = pPage->getRootFrm()->GetCurrShell()->getIDocumentDrawModelAccess()->GetHellId();
+ for( MSHORT i = 0; i < nCount; ++i )
+ {
+ // --> OD 2006-08-15 #i68520#
+ const SwAnchoredObject* pAnchoredObjTmp = (*mpAnchoredObjList)[i];
+ if( mpCurrAnchoredObj != pAnchoredObjTmp &&
+ dynamic_cast<const SwFlyFrm*>(pAnchoredObjTmp) )
+ // <--
+ {
+ // --> OD 2006-08-15 #i68520#
+ const SwFmtSurround& rSur = pAnchoredObjTmp->GetFrmFmt().GetSurround();
+ // <--
+
+ // OD 24.01.2003 #106593# - correct clipping of fly frame area.
+ // Consider that fly frame background/shadow can be transparent
+ // and <SwAlignRect(..)> fly frame area
+ // --> OD 2006-08-15 #i68520#
+ const SwFlyFrm* pFly = dynamic_cast<const SwFlyFrm*>(pAnchoredObjTmp);
+ // <--
+ // --> OD 2005-06-08 #i47804# - consider transparent graphics
+ // and OLE objects.
+ bool bClipFlyArea =
+ ( ( SURROUND_THROUGHT == rSur.GetSurround() )
+ // --> OD 2006-08-15 #i68520#
+ ? (pAnchoredObjTmp->GetDrawObj()->GetLayer() != nHellId)
+ // <--
+ : !rSur.IsContour() ) &&
+ !pFly->IsBackgroundTransparent() &&
+ !pFly->IsShadowTransparent() &&
+ ( !pFly->Lower() ||
+ !pFly->Lower()->IsNoTxtFrm() ||
+ !static_cast<const SwNoTxtFrm*>(pFly->Lower())->IsTransparent() );
+ // <--
+ if ( bClipFlyArea )
+ {
+ // --> OD 2006-08-15 #i68520#
+ SwRect aFly( pAnchoredObjTmp->GetObjRect() );
+ // <--
+ // OD 24.01.2003 #106593#
+ ::SwAlignRect( aFly, pPage->getRootFrm()->GetCurrShell() );
+ if( aFly.Width() > 0 && aFly.Height() > 0 )
+ aRegion -= aFly;
+ }
+ }
+ }
+ }
+
+ for( MSHORT i = 0; i < aRegion.Count(); ++i )
+ {
+ if ( bNoGraphic )
+ pOut->DrawRect( aRegion[i].SVRect() );
+ else
+ {
+ OSL_ENSURE( ((SvxBrushItem*)-1) != rInf.GetBrushItem(),
+ "DrawRect: Uninitialized BrushItem!" );
+ ::DrawGraphic( rInf.GetBrushItem(), pOut, rInf.GetBrushRect(),
+ aRegion[i] );
+ }
+ }
+}
+
+// --> OD 2004-10-06 #i26945# - change first parameter:
+// Now it's the <SwAnchoredObject> instance of the floating screen object
+sal_Bool SwTxtFly::GetTop( const SwAnchoredObject* _pAnchoredObj,
+ const sal_Bool bInFtn,
+ const sal_Bool bInFooterOrHeader )
+// <--
+{
+ // --> OD 2006-08-15 #i68520#
+ // <mpCurrAnchoredObj> is set, if <pCurrFrm> is inside a fly frame
+ if( _pAnchoredObj != mpCurrAnchoredObj )
+ // <--
+ {
+ // --> OD 2004-10-06 #i26945#
+ const SdrObject* pNew = _pAnchoredObj->GetDrawObj();
+ // <--
+ // #102344# Ignore connectors which have one or more connections
+ if(pNew && pNew->ISA(SdrEdgeObj))
+ {
+ if(((SdrEdgeObj*)pNew)->GetConnectedNode(sal_True)
+ || ((SdrEdgeObj*)pNew)->GetConnectedNode(sal_False))
+ {
+ return sal_False;
+ }
+ }
+
+ if( ( bInFtn || bInFooterOrHeader ) && bTopRule )
+ {
+ // --> OD 2004-10-06 #i26945#
+ const SwFrmFmt& rFrmFmt = _pAnchoredObj->GetFrmFmt();
+ const SwFmtAnchor& rNewA = rFrmFmt.GetAnchor();
+ // <--
+ if (FLY_AT_PAGE == rNewA.GetAnchorId())
+ {
+ if ( bInFtn )
+ return sal_False;
+
+ if ( bInFooterOrHeader )
+ {
+ SwFmtVertOrient aVert( rFrmFmt.GetVertOrient() );
+ sal_Bool bVertPrt = aVert.GetRelationOrient() == text::RelOrientation::PRINT_AREA ||
+ aVert.GetRelationOrient() == text::RelOrientation::PAGE_PRINT_AREA;
+ if( bVertPrt )
+ return sal_False;
+ }
+ }
+ }
+
+ // --> OD 2006-08-15 #i68520#
+ // bEvade: consider pNew, if we are not inside a fly
+ // consider pNew, if pNew is lower of <mpCurrAnchoredObj>
+ sal_Bool bEvade = !mpCurrAnchoredObj ||
+ Is_Lower_Of( dynamic_cast<const SwFlyFrm*>(mpCurrAnchoredObj), pNew);
+
+ if ( !bEvade )
+ {
+ // We are currently inside a fly frame and pNew is not
+ // inside this fly frame. We can do some more checks if
+ // we have to consider pNew.
+
+ // If bTopRule is not set, we ignore the frame types.
+ // We directly check the z-order
+ if ( !bTopRule )
+ bEvade = sal_True;
+ else
+ {
+ // innerhalb von verketteten Flys wird nur Lowern ausgewichen
+ // --> OD 2006-08-15 #i68520#
+ const SwFmtChain &rChain = mpCurrAnchoredObj->GetFrmFmt().GetChain();
+ // <--
+ if ( !rChain.GetPrev() && !rChain.GetNext() )
+ {
+ // --> OD 2004-10-06 #i26945#
+ const SwFmtAnchor& rNewA = _pAnchoredObj->GetFrmFmt().GetAnchor();
+ // <--
+ // --> OD 2006-08-15 #i68520#
+ const SwFmtAnchor& rCurrA = mpCurrAnchoredObj->GetFrmFmt().GetAnchor();
+ // <--
+
+ // If <mpCurrAnchoredObj> is anchored as character, its content
+ // does not wrap around pNew
+ if (FLY_AS_CHAR == rCurrA.GetAnchorId())
+ return sal_False;
+
+ // If pNew is anchored to page and <mpCurrAnchoredObj is not anchored
+ // to page, the content of <mpCurrAnchoredObj> does not wrap around pNew
+ // If both pNew and <mpCurrAnchoredObj> are anchored to page, we can do
+ // some more checks
+ if (FLY_AT_PAGE == rNewA.GetAnchorId())
+ {
+ if (FLY_AT_PAGE == rCurrA.GetAnchorId())
+ {
+ bEvade = sal_True;
+ }
+ else
+ return sal_False;
+ }
+ else if (FLY_AT_PAGE == rCurrA.GetAnchorId())
+ return sal_False; // Seitengebundene weichen nur seitengeb. aus
+ else if (FLY_AT_FLY == rNewA.GetAnchorId())
+ bEvade = sal_True; // Nicht seitengeb. weichen Rahmengeb. aus
+ else if( FLY_AT_FLY == rCurrA.GetAnchorId() )
+ return sal_False; // Rahmengebundene weichen abs.geb. nicht aus
+ // --> OD 2006-01-30 #i57062#
+ // In order to avoid loop situation, it's decided to adjust
+ // the wrapping behaviour of content of at-paragraph/at-character
+ // anchored objects to one in the page header/footer and
+ // the document body --> content of at-paragraph/at-character
+ // anchored objects doesn't wrap around each other.
+// else if( bInFooterOrHeader )
+// return sal_False; // In header or footer no wrapping
+// // if both bounded at paragraph
+// else // Zwei Flies mit (auto-)absatzgebunder Verankerung ...
+// // ... entscheiden nach der Reihenfolge ihrer Anker im Dok.
+// bEvade = rNewA.GetCntntAnchor()->nNode.GetIndex() <=
+// rCurrA.GetCntntAnchor()->nNode.GetIndex();
+ else
+ return sal_False;
+ // <--
+ }
+ }
+
+ // aber: es wird niemals einem hierarchisch untergeordnetem
+ // ausgewichen und ausserdem braucht nur bei Ueberlappung
+ // ausgewichen werden.
+ // --> OD 2006-08-15 #i68520#
+ bEvade &= ( mpCurrAnchoredObj->GetDrawObj()->GetOrdNum() < pNew->GetOrdNum() );
+ // <--
+ if( bEvade )
+ {
+ // --> OD 2006-08-15 #i68520#
+ SwRect aTmp( _pAnchoredObj->GetObjRectWithSpaces() );
+ if ( !aTmp.IsOver( mpCurrAnchoredObj->GetObjRectWithSpaces() ) )
+ bEvade = sal_False;
+ // <--
+ }
+ }
+
+ if ( bEvade )
+ {
+ // --> OD 2004-10-06 #i26945#
+ const SwFmtAnchor& rNewA = _pAnchoredObj->GetFrmFmt().GetAnchor();
+ // <--
+ OSL_ENSURE( FLY_AS_CHAR != rNewA.GetAnchorId(),
+ "Don't call GetTop with a FlyInCntFrm" );
+ if (FLY_AT_PAGE == rNewA.GetAnchorId())
+ return sal_True; // Seitengebundenen wird immer ausgewichen.
+
+ // Wenn absatzgebundene Flys in einem FlyCnt gefangen sind, so
+ // endet deren Einflussbereich an den Grenzen des FlyCnt!
+ // Wenn wir aber gerade den Text des FlyCnt formatieren, dann
+ // muss er natuerlich dem absatzgebundenen Frm ausweichen!
+ // pCurrFrm ist der Anker von pNew?
+ // --> OD 2004-10-06 #i26945#
+ const SwFrm* pTmp = _pAnchoredObj->GetAnchorFrm();
+ // <--
+ if( pTmp == pCurrFrm )
+ return sal_True;
+ if( pTmp->IsTxtFrm() && ( pTmp->IsInFly() || pTmp->IsInFtn() ) )
+ {
+ // --> OD 2004-10-06 #i26945#
+ Point aPos = _pAnchoredObj->GetObjRect().Pos();
+ // <--
+ pTmp = GetVirtualUpper( pTmp, aPos );
+ }
+ // --> OD 2004-10-06 #i26945#
+ // --> OD 2004-11-29 #115759#
+ // If <pTmp> is a text frame inside a table, take the upper
+ // of the anchor frame, which contains the anchor position.
+ else if ( pTmp->IsTxtFrm() && pTmp->IsInTab() )
+ {
+ pTmp = const_cast<SwAnchoredObject*>(_pAnchoredObj)
+ ->GetAnchorFrmContainingAnchPos()->GetUpper();
+ }
+ // <--
+ // --> OD 2004-05-13 #i28701# - consider all objects in same context,
+ // if wrapping style is considered on object positioning.
+ // Thus, text will wrap around negative positioned objects.
+ // --> OD 2004-08-25 #i3317# - remove condition on checking,
+ // if wrappings style is considered on object postioning.
+ // Thus, text is wrapping around negative positioned objects.
+ // --> OD 2004-10-20 #i35640# - no consideration of negative
+ // positioned objects, if wrapping style isn't considered on
+ // object position and former text wrapping is applied.
+ // This condition is typically for documents imported from the
+ // OpenOffice.org file format.
+ const IDocumentSettingAccess* pIDSA = pCurrFrm->GetTxtNode()->getIDocumentSettingAccess();
+ if ( ( pIDSA->get(IDocumentSettingAccess::CONSIDER_WRAP_ON_OBJECT_POSITION) ||
+ !pIDSA->get(IDocumentSettingAccess::USE_FORMER_TEXT_WRAPPING) ) &&
+ ::FindKontext( pTmp, 0 ) == ::FindKontext( pCurrFrm, 0 ) )
+ {
+ return sal_True;
+ }
+ // <--
+
+ const SwFrm* pHeader = 0;
+ if ( pCurrFrm->GetNext() != pTmp &&
+ ( IsFrmInSameKontext( pTmp, pCurrFrm ) ||
+ // --> #i13832#, #i24135# wrap around objects in page header
+ ( !pIDSA->get(IDocumentSettingAccess::USE_FORMER_TEXT_WRAPPING) &&
+ 0 != ( pHeader = pTmp->FindFooterOrHeader() ) &&
+ !pHeader->IsFooterFrm() &&
+ pCurrFrm->IsInDocBody() ) ) )
+ // <--
+ {
+ if( pHeader || FLY_AT_FLY == rNewA.GetAnchorId() )
+ return sal_True;
+
+ // Compare indices:
+ // Den Index des anderen erhalten wir immer ueber das Ankerattr.
+ sal_uLong nTmpIndex = rNewA.GetCntntAnchor()->nNode.GetIndex();
+ // Jetzt wird noch ueberprueft, ob der aktuelle Absatz vor dem
+ // Anker des verdraengenden Objekts im Text steht, dann wird
+ // nicht ausgewichen.
+ // Der Index wird moeglichst ueber einen SwFmtAnchor ermittelt,
+ // da sonst recht teuer.
+ if( ULONG_MAX == nIndex )
+ nIndex = pCurrFrm->GetNode()->GetIndex();
+
+ if( nIndex >= nTmpIndex )
+ return sal_True;
+ }
+ }
+ }
+ return sal_False;
+}
+// --> OD 2006-08-15 #i68520#
+struct AnchoredObjOrder
+{
+ sal_Bool mbR2L;
+ SwRectFn mfnRect;
+
+ AnchoredObjOrder( const sal_Bool bR2L,
+ SwRectFn fnRect )
+ : mbR2L( bR2L ),
+ mfnRect( fnRect )
+ {}
+
+ bool operator()( const SwAnchoredObject* pListedAnchoredObj,
+ const SwAnchoredObject* pNewAnchoredObj )
+ {
+ const SwRect aBoundRectOfListedObj( pListedAnchoredObj->GetObjRectWithSpaces() );
+ const SwRect aBoundRectOfNewObj( pNewAnchoredObj->GetObjRectWithSpaces() );
+ if ( ( mbR2L &&
+ ( (aBoundRectOfListedObj.*mfnRect->fnGetRight)() ==
+ (aBoundRectOfNewObj.*mfnRect->fnGetRight)() ) ) ||
+ ( !mbR2L &&
+ ( (aBoundRectOfListedObj.*mfnRect->fnGetLeft)() ==
+ (aBoundRectOfNewObj.*mfnRect->fnGetLeft)() ) ) )
+ {
+ SwTwips nTopDiff =
+ (*mfnRect->fnYDiff)( (aBoundRectOfNewObj.*mfnRect->fnGetTop)(),
+ (aBoundRectOfListedObj.*mfnRect->fnGetTop)() );
+ if ( nTopDiff == 0 &&
+ ( ( mbR2L &&
+ ( (aBoundRectOfNewObj.*mfnRect->fnGetLeft)() >
+ (aBoundRectOfListedObj.*mfnRect->fnGetLeft)() ) ) ||
+ ( !mbR2L &&
+ ( (aBoundRectOfNewObj.*mfnRect->fnGetRight)() <
+ (aBoundRectOfListedObj.*mfnRect->fnGetRight)() ) ) ) )
+ {
+ return true;
+ }
+ else if ( nTopDiff > 0 )
+ {
+ return true;
+ }
+ }
+ else if ( ( mbR2L &&
+ ( (aBoundRectOfListedObj.*mfnRect->fnGetRight)() >
+ (aBoundRectOfNewObj.*mfnRect->fnGetRight)() ) ) ||
+ ( !mbR2L &&
+ ( (aBoundRectOfListedObj.*mfnRect->fnGetLeft)() <
+ (aBoundRectOfNewObj.*mfnRect->fnGetLeft)() ) ) )
+ {
+ return true;
+ }
+
+ return false;
+ }
+};
+
+// --> OD 2006-08-15 #i68520#
+SwAnchoredObjList* SwTxtFly::InitAnchoredObjList()
+{
+ OSL_ENSURE( pCurrFrm, "InitFlyList: No Frame, no FlyList" );
+ // --> OD 2006-08-15 #i68520#
+ OSL_ENSURE( !mpAnchoredObjList, "InitFlyList: FlyList already initialized" );
+ // <--
+
+ SWAP_IF_SWAPPED( pCurrFrm )
+
+ const SwSortedObjs *pSorted = pPage->GetSortedObjs();
+ const sal_uInt32 nCount = pSorted ? pSorted->Count() : 0;
+ // --> #108724# Page header/footer content doesn't have to wrap around
+ // floating screen objects
+ const bool bFooterHeader = 0 != pCurrFrm->FindFooterOrHeader();
+ const IDocumentSettingAccess* pIDSA = pCurrFrm->GetTxtNode()->getIDocumentSettingAccess();
+ // --> OD 2005-01-12 #i40155# - check, if frame is marked not to wrap
+ const sal_Bool bWrapAllowed = ( pIDSA->get(IDocumentSettingAccess::USE_FORMER_TEXT_WRAPPING) ||
+ ( !pCurrFrm->IsInFtn() && !bFooterHeader ) ) &&
+ !SwLayouter::FrmNotToWrap( *pCurrFrm->GetTxtNode()->getIDocumentLayoutAccess(), *pCurrFrm );
+ // <--
+
+ bOn = sal_False;
+
+ if( nCount && bWrapAllowed )
+ {
+ // --> OD 2006-08-15 #i68520#
+ mpAnchoredObjList = new SwAnchoredObjList();
+ // <--
+
+ // --> OD 2004-06-18 #i28701# - consider complete frame area for new
+ // text wrapping
+ SwRect aRect;
+ if ( pIDSA->get(IDocumentSettingAccess::USE_FORMER_TEXT_WRAPPING) )
+ {
+ aRect = pCurrFrm->Prt();
+ aRect += pCurrFrm->Frm().Pos();
+ }
+ else
+ {
+ aRect = pCurrFrm->Frm();
+ }
+ // Wir machen uns etwas kleiner als wir sind,
+ // damit Ein-Twip-Ueberlappungen ignoriert werden. (#49532)
+ SWRECTFN( pCurrFrm )
+ const long nRight = (aRect.*fnRect->fnGetRight)() - 1;
+ const long nLeft = (aRect.*fnRect->fnGetLeft)() + 1;
+ const sal_Bool bR2L = pCurrFrm->IsRightToLeft();
+
+ const IDocumentDrawModelAccess* pIDDMA = pCurrFrm->GetTxtNode()->getIDocumentDrawModelAccess();
+
+ for( sal_uInt32 i = 0; i < nCount; i++ )
+ {
+ // --> OD 2006-08-15 #i68520#
+// SwAnchoredObject* pAnchoredObj = (*pSorted)[ i ];
+// const SwRect aBound( pAnchoredObj->GetObjRectWithSpaces() );
+
+// // OD 2004-01-15 #110582# - do not consider hidden objects
+// // OD 2004-05-13 #i28701# - check, if object has to be considered
+// // for text wrap.
+// if ( !pDoc->IsVisibleLayerId( pAnchoredObj->GetDrawObj()->GetLayer() ) ||
+// !pAnchoredObj->ConsiderForTextWrap() ||
+// nRight < (aBound.*fnRect->fnGetLeft)() ||
+// (*fnRect->fnYDiff)( (aRect.*fnRect->fnGetTop)(),
+// (aBound.*fnRect->fnGetBottom)() ) > 0 ||
+// nLeft > (aBound.*fnRect->fnGetRight)() ||
+// // --> OD 2004-12-17 #118809# - If requested, do not consider
+// // objects in page header|footer for text frames not in page
+// // header|footer. This is requested for the calculation of
+// // the base offset for objects <SwTxtFrm::CalcBaseOfstForFly()>
+// ( mbIgnoreObjsInHeaderFooter && !bFooterHeader &&
+// pAnchoredObj->GetAnchorFrm()->FindFooterOrHeader() ) ||
+// // <--
+// // --> FME 2004-07-14 #i20505# Do not consider oversized objects
+// (aBound.*fnRect->fnGetHeight)() >
+// 2 * (pPage->Frm().*fnRect->fnGetHeight)() )
+// // <--
+// {
+// continue;
+// }
+ SwAnchoredObject* pAnchoredObj = (*pSorted)[ i ];
+ if ( !pIDDMA->IsVisibleLayerId( pAnchoredObj->GetDrawObj()->GetLayer() ) ||
+ !pAnchoredObj->ConsiderForTextWrap() ||
+ ( mbIgnoreObjsInHeaderFooter && !bFooterHeader &&
+ pAnchoredObj->GetAnchorFrm()->FindFooterOrHeader() ) )
+ {
+ continue;
+ }
+
+ const SwRect aBound( pAnchoredObj->GetObjRectWithSpaces() );
+ if ( nRight < (aBound.*fnRect->fnGetLeft)() ||
+ (*fnRect->fnYDiff)( (aRect.*fnRect->fnGetTop)(),
+ (aBound.*fnRect->fnGetBottom)() ) > 0 ||
+ nLeft > (aBound.*fnRect->fnGetRight)() ||
+ (aBound.*fnRect->fnGetHeight)() >
+ 2 * (pPage->Frm().*fnRect->fnGetHeight)() )
+ {
+ continue;
+ }
+ // <--
+
+ // --> OD 2004-10-06 #i26945# - pass <pAnchoredObj> to method
+ // <GetTop(..)> instead of only the <SdrObject> instance of the
+ // anchored object
+ if ( GetTop( pAnchoredObj, pCurrFrm->IsInFtn(), bFooterHeader ) )
+ // <--
+ {
+ // OD 11.03.2003 #107862# - adjust insert position:
+ // overlapping objects should be sorted from left to right and
+ // inside left to right sorting from top to bottom.
+ // If objects on the same position are found, they are sorted
+ // on its width.
+ // --> OD 2006-08-15 #i68520#
+// sal_uInt16 nPos = pFlyList->Count();
+// while ( nPos )
+// {
+// SdrObject* pTmpObj = (*pFlyList)[ --nPos ];
+// const SwRect aBoundRectOfTmpObj( GetBoundRect( pTmpObj ) );
+// if ( ( bR2L &&
+// ( (aBoundRectOfTmpObj.*fnRect->fnGetRight)() ==
+// (aBound.*fnRect->fnGetRight)() ) ) ||
+// ( !bR2L &&
+// ( (aBoundRectOfTmpObj.*fnRect->fnGetLeft)() ==
+// (aBound.*fnRect->fnGetLeft)() ) ) )
+// {
+// SwTwips nTopDiff =
+// (*fnRect->fnYDiff)( (aBound.*fnRect->fnGetTop)(),
+// (aBoundRectOfTmpObj.*fnRect->fnGetTop)() );
+// if ( nTopDiff == 0 &&
+// ( ( bR2L &&
+// ( (aBound.*fnRect->fnGetLeft)() >
+// (aBoundRectOfTmpObj.*fnRect->fnGetLeft)() ) ) ||
+// ( !bR2L &&
+// ( (aBound.*fnRect->fnGetRight)() <
+// (aBoundRectOfTmpObj.*fnRect->fnGetRight)() ) ) ) )
+// {
+// ++nPos;
+// break;
+// }
+// else if ( nTopDiff > 0 )
+// {
+// ++nPos;
+// break;
+// }
+// }
+// else if ( ( bR2L &&
+// ( (aBoundRectOfTmpObj.*fnRect->fnGetRight)() >
+// (aBound.*fnRect->fnGetRight)() ) ) ||
+// ( !bR2L &&
+// ( (aBoundRectOfTmpObj.*fnRect->fnGetLeft)() <
+// (aBound.*fnRect->fnGetLeft)() ) ) )
+// {
+// ++nPos;
+// break;
+// }
+// }
+// SdrObject* pSdrObj = pAnchoredObj->DrawObj();
+// pFlyList->C40_INSERT( SdrObject, pSdrObj, nPos );
+ {
+ SwAnchoredObjList::iterator aInsPosIter =
+ std::lower_bound( mpAnchoredObjList->begin(),
+ mpAnchoredObjList->end(),
+ pAnchoredObj,
+ AnchoredObjOrder( bR2L, fnRect ) );
+
+ mpAnchoredObjList->insert( aInsPosIter, pAnchoredObj );
+ }
+ // <--
+
+ const SwFmtSurround &rFlyFmt = pAnchoredObj->GetFrmFmt().GetSurround();
+ // --> OD 2006-08-15 #i68520#
+ if ( rFlyFmt.IsAnchorOnly() &&
+ pAnchoredObj->GetAnchorFrm() == GetMaster() )
+ // <--
+ {
+ const SwFmtVertOrient &rTmpFmt =
+ pAnchoredObj->GetFrmFmt().GetVertOrient();
+ if( text::VertOrientation::BOTTOM != rTmpFmt.GetVertOrient() )
+ nMinBottom = ( bVert && nMinBottom ) ?
+ Min( nMinBottom, aBound.Left() ) :
+ Max( nMinBottom, (aBound.*fnRect->fnGetBottom)() );
+ }
+
+ bOn = sal_True;
+ }
+ }
+ if( nMinBottom )
+ {
+ SwTwips nMax = (pCurrFrm->GetUpper()->*fnRect->fnGetPrtBottom)();
+ if( (*fnRect->fnYDiff)( nMinBottom, nMax ) > 0 )
+ nMinBottom = nMax;
+ }
+ }
+ else
+ {
+ // --> OD 2006-08-15 #i68520#
+ mpAnchoredObjList = new SwAnchoredObjList();
+ // <--
+ }
+
+ UNDO_SWAP( pCurrFrm )
+
+ // --> OD 2006-08-15 #i68520#
+ return mpAnchoredObjList;
+ // <--
+}
+// <--
+
+SwTwips SwTxtFly::CalcMinBottom() const
+{
+ SwTwips nRet = 0;
+ const SwSortedObjs *pDrawObj = GetMaster()->GetDrawObjs();
+ const sal_uInt32 nCount = pDrawObj ? pDrawObj->Count() : 0;
+ if( nCount )
+ {
+ SwTwips nEndOfFrm = pCurrFrm->Frm().Bottom();
+ for( sal_uInt32 i = 0; i < nCount; i++ )
+ {
+ SwAnchoredObject* pAnchoredObj = (*pDrawObj)[ i ];
+ const SwFmtSurround &rFlyFmt = pAnchoredObj->GetFrmFmt().GetSurround();
+ if( rFlyFmt.IsAnchorOnly() )
+ {
+ const SwFmtVertOrient &rTmpFmt =
+ pAnchoredObj->GetFrmFmt().GetVertOrient();
+ if( text::VertOrientation::BOTTOM != rTmpFmt.GetVertOrient() )
+ {
+ const SwRect aBound( pAnchoredObj->GetObjRectWithSpaces() );
+ if( aBound.Top() < nEndOfFrm )
+ nRet = Max( nRet, aBound.Bottom() );
+ }
+ }
+ }
+ SwTwips nMax = pCurrFrm->GetUpper()->Frm().Top() +
+ pCurrFrm->GetUpper()->Prt().Bottom();
+ if( nRet > nMax )
+ nRet = nMax;
+ }
+ return nRet;
+}
+
+/*************************************************************************
+ * Hier erfolgt die Berechnung der Kontur ...
+ * CalcBoundRect(..) und andere
+ *************************************************************************/
+
+/*************************************************************************
+ * class SwContourCache
+ *************************************************************************/
+
+SwContourCache::SwContourCache() :
+ nPntCnt( 0 ), nObjCnt( 0 )
+{
+ memset( (SdrObject**)pSdrObj, 0, sizeof(pSdrObj) );
+ memset( pTextRanger, 0, sizeof(pTextRanger) );
+}
+
+SwContourCache::~SwContourCache()
+{
+ for( MSHORT i = 0; i < nObjCnt; delete pTextRanger[ i++ ] )
+ ;
+}
+
+void SwContourCache::ClrObject( MSHORT nPos )
+{
+ OSL_ENSURE( pTextRanger[ nPos ], "ClrObject: Allready cleared. Good Bye!" );
+ nPntCnt -= pTextRanger[ nPos ]->GetPointCount();
+ delete pTextRanger[ nPos ];
+ --nObjCnt;
+ memmove( (SdrObject**)pSdrObj + nPos, pSdrObj + nPos + 1,
+ ( nObjCnt - nPos ) * sizeof( SdrObject* ) );
+ memmove( pTextRanger + nPos, pTextRanger + nPos + 1,
+ ( nObjCnt - nPos ) * sizeof( TextRanger* ) );
+}
+
+void ClrContourCache( const SdrObject *pObj )
+{
+ if( pContourCache && pObj )
+ for( MSHORT i = 0; i < pContourCache->GetCount(); ++i )
+ if( pObj == pContourCache->GetObject( i ) )
+ {
+ pContourCache->ClrObject( i );
+ break;
+ }
+}
+
+void ClrContourCache()
+{
+ if( pContourCache )
+ {
+ for( MSHORT i = 0; i < pContourCache->GetCount();
+ delete pContourCache->pTextRanger[ i++ ] )
+ ;
+ pContourCache->nObjCnt = 0;
+ pContourCache->nPntCnt = 0;
+ }
+}
+
+/*************************************************************************
+ * SwContourCache::CalcBoundRect
+ * berechnet das Rechteck, welches vom Objekt in der angegebenen Zeile
+ * ueberdeckt wird.
+ * Bei _nicht_ konturumflossenen Objekten ist dies einfach die Ueber-
+ * lappung von BoundRect (inkl. Abstand!) und Zeile,
+ * bei Konturumfluss wird das Polypolygon des Objekts abgeklappert
+ *************************************************************************/
+// --> OD 2006-08-15 #i68520#
+const SwRect SwContourCache::CalcBoundRect( const SwAnchoredObject* pAnchoredObj,
+ const SwRect &rLine,
+ const SwTxtFrm* pFrm,
+ const long nXPos,
+ const sal_Bool bRight )
+{
+ SwRect aRet;
+ const SwFrmFmt* pFmt = &(pAnchoredObj->GetFrmFmt());
+ if( pFmt->GetSurround().IsContour() &&
+ ( !pAnchoredObj->ISA(SwFlyFrm) ||
+ ( static_cast<const SwFlyFrm*>(pAnchoredObj)->Lower() &&
+ static_cast<const SwFlyFrm*>(pAnchoredObj)->Lower()->IsNoTxtFrm() ) ) )
+ {
+ aRet = pAnchoredObj->GetObjRectWithSpaces();
+ if( aRet.IsOver( rLine ) )
+ {
+ if( !pContourCache )
+ pContourCache = new SwContourCache;
+
+ aRet = pContourCache->ContourRect(
+ pFmt, pAnchoredObj->GetDrawObj(), pFrm, rLine, nXPos, bRight );
+ }
+ else
+ aRet.Width( 0 );
+ }
+ else
+ {
+ aRet = pAnchoredObj->GetObjRectWithSpaces();
+ }
+
+ return aRet;
+}
+// <--
+
+const SwRect SwContourCache::ContourRect( const SwFmt* pFmt,
+ const SdrObject* pObj, const SwTxtFrm* pFrm, const SwRect &rLine,
+ const long nXPos, const sal_Bool bRight )
+{
+ SwRect aRet;
+ MSHORT nPos = 0; // Suche im Cache ...
+ while( nPos < GetCount() && pObj != pSdrObj[ nPos ] )
+ ++nPos;
+ if( GetCount() == nPos ) // nicht gefunden
+ {
+ if( nObjCnt == POLY_CNT )
+ {
+ nPntCnt -= pTextRanger[ --nObjCnt ]->GetPointCount();
+ delete pTextRanger[ nObjCnt ];
+ }
+ ::basegfx::B2DPolyPolygon aPolyPolygon;
+ ::basegfx::B2DPolyPolygon* pPolyPolygon = 0L;
+
+ if ( pObj->ISA(SwVirtFlyDrawObj) )
+ {
+ // Vorsicht #37347: Das GetContour() fuehrt zum Laden der Grafik,
+ // diese aendert dadurch ggf. ihre Groesse, ruft deshalb ein
+ // ClrObject() auf.
+ PolyPolygon aPoly;
+ if( !((SwVirtFlyDrawObj*)pObj)->GetFlyFrm()->GetContour( aPoly ) )
+ aPoly = PolyPolygon( ((SwVirtFlyDrawObj*)pObj)->
+ GetFlyFrm()->Frm().SVRect() );
+ aPolyPolygon.clear();
+ aPolyPolygon.append(aPoly.getB2DPolyPolygon());
+ }
+ else
+ {
+ if( !pObj->ISA( E3dObject ) )
+ {
+ aPolyPolygon = pObj->TakeXorPoly();
+ }
+
+ ::basegfx::B2DPolyPolygon aContourPoly(pObj->TakeContour());
+ pPolyPolygon = new ::basegfx::B2DPolyPolygon(aContourPoly);
+ }
+ const SvxLRSpaceItem &rLRSpace = pFmt->GetLRSpace();
+ const SvxULSpaceItem &rULSpace = pFmt->GetULSpace();
+ memmove( pTextRanger + 1, pTextRanger, nObjCnt * sizeof( TextRanger* ) );
+ memmove( (SdrObject**)pSdrObj + 1, pSdrObj, nObjCnt++ * sizeof( SdrObject* ) );
+ pSdrObj[ 0 ] = pObj; // Wg. #37347 darf das Object erst nach dem
+ // GetContour() eingetragen werden.
+ pTextRanger[ 0 ] = new TextRanger( aPolyPolygon, pPolyPolygon, 20,
+ (sal_uInt16)rLRSpace.GetLeft(), (sal_uInt16)rLRSpace.GetRight(),
+ pFmt->GetSurround().IsOutside(), sal_False, pFrm->IsVertical() );
+ pTextRanger[ 0 ]->SetUpper( rULSpace.GetUpper() );
+ pTextRanger[ 0 ]->SetLower( rULSpace.GetLower() );
+
+ delete pPolyPolygon;
+ // UPPER_LOWER_TEST
+#if OSL_DEBUG_LEVEL > 1
+ const ViewShell* pTmpViewShell = pFmt->GetDoc()->GetCurrentViewShell();
+ if( pTmpViewShell )
+ {
+ sal_Bool bT2 = pTmpViewShell->GetViewOptions()->IsTest2();
+ sal_Bool bT6 = pTmpViewShell->GetViewOptions()->IsTest6();
+ if( bT2 || bT6 )
+ {
+ if( bT2 )
+ pTextRanger[ 0 ]->SetFlag7( sal_True );
+ else
+ pTextRanger[ 0 ]->SetFlag6( sal_True );
+ }
+ }
+#endif
+ nPntCnt += pTextRanger[ 0 ]->GetPointCount();
+ while( nPntCnt > POLY_MAX && nObjCnt > POLY_MIN )
+ {
+ nPntCnt -= pTextRanger[ --nObjCnt ]->GetPointCount();
+ delete pTextRanger[ nObjCnt ];
+ }
+ }
+ else if( nPos )
+ {
+ const SdrObject* pTmpObj = pSdrObj[ nPos ];
+ TextRanger* pTmpRanger = pTextRanger[ nPos ];
+ memmove( (SdrObject**)pSdrObj + 1, pSdrObj, nPos * sizeof( SdrObject* ) );
+ memmove( pTextRanger + 1, pTextRanger, nPos * sizeof( TextRanger* ) );
+ pSdrObj[ 0 ] = pTmpObj;
+ pTextRanger[ 0 ] = pTmpRanger;
+ }
+ SWRECTFN( pFrm )
+ long nTmpTop = (rLine.*fnRect->fnGetTop)();
+ // fnGetBottom is top + height
+ long nTmpBottom = (rLine.*fnRect->fnGetBottom)();
+
+ Range aRange( Min( nTmpTop, nTmpBottom ), Max( nTmpTop, nTmpBottom ) );
+
+ LongDqPtr pTmp = pTextRanger[ 0 ]->GetTextRanges( aRange );
+
+ MSHORT nCount;
+ if( 0 != ( nCount = pTmp->size() ) )
+ {
+ MSHORT nIdx = 0;
+ while( nIdx < nCount && (*pTmp)[ nIdx ] < nXPos )
+ ++nIdx;
+ sal_Bool bOdd = nIdx % 2 ? sal_True : sal_False;
+ sal_Bool bSet = sal_True;
+ if( bOdd )
+ --nIdx; // innerhalb eines Intervalls
+ else if( ! bRight && ( nIdx >= nCount || (*pTmp)[ nIdx ] != nXPos ) )
+ {
+ if( nIdx )
+ nIdx -= 2; // ein Intervall nach links gehen
+ else
+ bSet = sal_False; // vor dem erstem Intervall
+ }
+
+ if( bSet && nIdx < nCount )
+ {
+ (aRet.*fnRect->fnSetTopAndHeight)( (rLine.*fnRect->fnGetTop)(),
+ (rLine.*fnRect->fnGetHeight)() );
+ (aRet.*fnRect->fnSetLeft)( (*pTmp)[ nIdx ] );
+ (aRet.*fnRect->fnSetRight)( (*pTmp)[ nIdx + 1 ] + 1 );
+ }
+ }
+ return aRet;
+}
+
+/*************************************************************************
+ * SwContourCache::ShowContour()
+ * zeichnet die PolyPolygone des Caches zu Debugzwecken.
+ *************************************************************************/
+#if OSL_DEBUG_LEVEL > 1
+
+void SwContourCache::ShowContour( OutputDevice* pOut, const SdrObject* pObj,
+ const Color& rClosedColor, const Color& rOpenColor )
+{
+ MSHORT nPos = 0; // Suche im Cache ...
+ while( nPos < POLY_CNT && pObj != pSdrObj[ nPos ] )
+ ++nPos;
+ if( POLY_CNT != nPos )
+ {
+ const PolyPolygon* pPol = pTextRanger[ nPos ]->GetLinePolygon();
+ if( !pPol )
+ pPol = &(pTextRanger[ nPos ]->GetPolyPolygon());
+ for( MSHORT i = 0; i < pPol->Count(); ++i )
+ {
+ pOut->SetLineColor( rOpenColor );
+ const Polygon& rPol = (*pPol)[ i ];
+ MSHORT nCount = rPol.GetSize();
+ if( nCount > 1 && rPol[ 0 ] == rPol[ nCount - 1 ] )
+ pOut->SetLineColor( rClosedColor );
+ pOut->DrawPolygon( rPol );
+ }
+ static KSHORT nRadius = 0;
+ if( nRadius )
+ {
+ KSHORT nHalf = nRadius / 2;
+ Size aSz( nRadius, nRadius );
+ for( MSHORT i = 0; i < pPol->Count(); ++i )
+ {
+ const Polygon& rPol = (*pPol)[ i ];
+ MSHORT nCount = rPol.GetSize();
+ for( MSHORT k = 0; k < nCount; ++k )
+ {
+ Point aPt( rPol[ k ] );
+ aPt.X() -= nHalf;
+ aPt.Y() -= nHalf;
+ Rectangle aTmp( aPt, aSz );
+ pOut->DrawEllipse( aTmp );
+ }
+ }
+ }
+ }
+}
+#endif
+
+/*************************************************************************
+ * SwTxtFly::ShowContour()
+ * zeichnet die PolyPolygone des Caches zu Debugzwecken.
+ *************************************************************************/
+#if OSL_DEBUG_LEVEL > 1
+
+void SwTxtFly::ShowContour( OutputDevice* pOut )
+{
+ MSHORT nFlyCount;
+ if( bOn && ( 0 != ( nFlyCount = static_cast<sal_uInt16>(GetAnchoredObjList()->size() ) ) ) )
+ {
+ Color aRedColor( COL_LIGHTRED );
+ Color aGreenColor( COL_LIGHTGREEN );
+ Color aSaveColor( pOut->GetLineColor() );
+ for( MSHORT j = 0; j < nFlyCount; ++j )
+ {
+ const SwAnchoredObject* pObj = (*mpAnchoredObjList)[ j ];
+ if( !pObj->GetFrmFmt().GetSurround().IsContour() )
+ {
+ Rectangle aRect = pObj->GetObjRectWithSpaces().SVRect();
+ pOut->DrawRect( aRect );
+ continue;
+ }
+ pContourCache->ShowContour( pOut, pObj->GetDrawObj(), aRedColor, aGreenColor );
+ }
+ pOut->SetLineColor( aSaveColor );
+ }
+}
+#endif
+
+/*************************************************************************
+ * SwTxtFly::ForEach()
+ *
+ * sucht nach dem ersten Objekt, welches mit dem Rechteck ueberlappt
+ *
+ *************************************************************************/
+
+sal_Bool SwTxtFly::ForEach( const SwRect &rRect, SwRect* pRect, sal_Bool bAvoid ) const
+{
+ SWAP_IF_SWAPPED( pCurrFrm )
+
+ sal_Bool bRet = sal_False;
+ // --> OD 2006-08-15 #i68520#
+ SwAnchoredObjList::size_type nCount( bOn ? GetAnchoredObjList()->size() : 0 );
+ if ( bOn && nCount > 0 )
+ // <--
+ {
+ for( SwAnchoredObjList::size_type i = 0; i < nCount; ++i )
+ {
+ // --> OD 2006-08-15 #i68520#
+ const SwAnchoredObject* pAnchoredObj = (*mpAnchoredObjList)[i];
+
+ SwRect aRect( pAnchoredObj->GetObjRectWithSpaces() );
+ // <--
+
+ // Optimierung
+ SWRECTFN( pCurrFrm )
+ if( (aRect.*fnRect->fnGetLeft)() > (rRect.*fnRect->fnGetRight)() )
+ break;
+ // --> OD 2006-08-15 #i68520#
+ if ( mpCurrAnchoredObj != pAnchoredObj && aRect.IsOver( rRect ) )
+ // <--
+ {
+ // --> OD 2006-08-15 #i68520#
+ const SwFmt* pFmt( &(pAnchoredObj->GetFrmFmt()) );
+ const SwFmtSurround &rSur = pFmt->GetSurround();
+ // <--
+ if( bAvoid )
+ {
+ // Wenn der Text drunter durchlaeuft, bleibt die
+ // Formatierung unbeeinflusst. Im LineIter::DrawText()
+ // muessen "nur" geschickt die ClippingRegions gesetzt werden ...
+ const SwFmtAnchor& rAnchor = pFmt->GetAnchor();
+ if( ( SURROUND_THROUGHT == rSur.GetSurround() &&
+ ( !rSur.IsAnchorOnly() ||
+ // --> OD 2006-08-15 #i68520#
+ GetMaster() == pAnchoredObj->GetAnchorFrm() ||
+ // <--
+ ((FLY_AT_PARA != rAnchor.GetAnchorId()) &&
+ (FLY_AT_CHAR != rAnchor.GetAnchorId())) ) )
+ || aRect.Top() == WEIT_WECH )
+ continue;
+ }
+
+ // --> OD 2006-01-20 #i58642#
+ // Compare <GetMaster()> instead of <pCurrFrm> with the anchor
+ // frame of the anchored object, because a follow frame have
+ // to ignore the anchored objects of its master frame.
+ // Note: Anchored objects are always registered at the master
+ // frame, exception are as-character anchored objects,
+ // but these aren't handled here.
+ // --> OD 2006-08-15 #i68520#
+ if ( mbIgnoreCurrentFrame &&
+ GetMaster() == pAnchoredObj->GetAnchorFrm() )
+ continue;
+ // <--
+
+ if( pRect )
+ {
+ // --> OD 2006-08-15 #i68520#
+ SwRect aFly = AnchoredObjToRect( pAnchoredObj, rRect );
+ // <--
+ if( aFly.IsEmpty() || !aFly.IsOver( rRect ) )
+ continue;
+ if( !bRet || (
+ ( !pCurrFrm->IsRightToLeft() &&
+ ( (aFly.*fnRect->fnGetLeft)() <
+ (pRect->*fnRect->fnGetLeft)() ) ) ||
+ ( pCurrFrm->IsRightToLeft() &&
+ ( (aFly.*fnRect->fnGetRight)() >
+ (pRect->*fnRect->fnGetRight)() ) ) ) )
+ *pRect = aFly;
+ if( rSur.IsContour() )
+ {
+ bRet = sal_True;
+ continue;
+ }
+ }
+ bRet = sal_True;
+ break;
+ }
+ }
+ }
+
+ UNDO_SWAP( pCurrFrm )
+
+ return bRet;
+}
+
+/*************************************************************************
+ * SwTxtFly::GetPos()
+ *
+ * liefert die Position im sorted Array zurueck
+ *************************************************************************/
+
+// --> OD 2006-08-15 #i68520#
+SwAnchoredObjList::size_type SwTxtFly::GetPos( const SwAnchoredObject* pAnchoredObj ) const
+{
+ SwAnchoredObjList::size_type nCount = GetAnchoredObjList()->size();
+ SwAnchoredObjList::size_type nRet = 0;
+ while ( nRet < nCount && pAnchoredObj != (*mpAnchoredObjList)[ nRet ] )
+ ++nRet;
+ return nRet;
+}
+// <--
+
+/*************************************************************************
+ * SwTxtFly::CalcRightMargin()
+ *
+ * pObj ist das Object, der uns gerade ueberlappt.
+ * pCurrFrm ist der aktuelle Textframe, der ueberlappt wird.
+ * Der rechte Rand ist der rechte Rand oder
+ * er wird durch das naechste Object, welches in die Zeile ragt, bestimmt.
+ *************************************************************************/
+// --> OD 2006-08-15 #i68520#
+void SwTxtFly::CalcRightMargin( SwRect &rFly,
+ SwAnchoredObjList::size_type nFlyPos,
+ const SwRect &rLine ) const
+{
+ // Normalerweise ist der rechte Rand der rechte Rand der Printarea.
+ OSL_ENSURE( ! pCurrFrm->IsVertical() || ! pCurrFrm->IsSwapped(),
+ "SwTxtFly::CalcRightMargin with swapped frame" );
+ SWRECTFN( pCurrFrm )
+ // --> OD 2004-12-14 #118796# - correct determination of right of printing area
+ SwTwips nRight = (pCurrFrm->*fnRect->fnGetPrtRight)();
+ // <--
+ SwTwips nFlyRight = (rFly.*fnRect->fnGetRight)();
+ SwRect aLine( rLine );
+ (aLine.*fnRect->fnSetRight)( nRight );
+ (aLine.*fnRect->fnSetLeft)( (rFly.*fnRect->fnGetLeft)() );
+
+ // Es koennte aber sein, dass in die gleiche Zeile noch ein anderes
+ // Object hineinragt, welches _ueber_ uns liegt.
+ // Wunder der Technik: Flys mit Durchlauf sind fuer die darunterliegenden
+ // unsichtbar, das heisst, dass sie bei der Berechnung der Raender
+ // anderer Flys ebenfalls nicht auffallen.
+ // 3301: pNext->Frm().IsOver( rLine ) ist noetig
+ // --> OD 2006-08-15 #i68520#
+ SwSurround eSurroundForTextWrap;
+ // <--
+
+ sal_Bool bStop = sal_False;
+ // --> OD 2006-08-15 #i68520#
+ SwAnchoredObjList::size_type nPos = 0;
+ // <--
+
+ // --> OD 2006-08-15 #i68520#
+ while( nPos < mpAnchoredObjList->size() && !bStop )
+ // <--
+ {
+ if( nPos == nFlyPos )
+ {
+ ++nPos;
+ continue;
+ }
+ // --> OD 2006-08-15 #i68520#
+ const SwAnchoredObject* pNext = (*mpAnchoredObjList)[ nPos++ ];
+ if ( pNext == mpCurrAnchoredObj )
+ continue;
+ eSurroundForTextWrap = _GetSurroundForTextWrap( pNext );
+ if( SURROUND_THROUGHT == eSurroundForTextWrap )
+ continue;
+ // <--
+
+ const SwRect aTmp( SwContourCache::CalcBoundRect
+ ( pNext, aLine, pCurrFrm, nFlyRight, sal_True ) );
+ SwTwips nTmpRight = (aTmp.*fnRect->fnGetRight)();
+
+ // Optimierung:
+ // In nNextTop wird notiert, an welcher Y-Positon mit Aenderung der
+ // Rahmenverhaeltnisse gerechnet werden muss. Dies dient dazu, dass,
+ // obwohl nur die Rahmen in der aktuellen Zeilenhoehe betrachtet werden,
+ // bei Rahmen ohne Umlauf die Zeilenhoehe so erhoeht wird, dass mit einer
+ // einzigen Zeile die Unterkante das Rahmens oder ggf. die Oberkante des
+ // naechsten Rahmen erreicht wird.
+ // Insbesondere bei HTML-Dokumenten kommen oft (Dummy-)Absaetze in einer
+ // 2-Pt.-Schrift vor, bis diese einem groesseren Rahmen ausgewichen sind,
+ // erforderte es frueher Unmengen von Leerzeilen.
+ const long nTmpTop = (aTmp.*fnRect->fnGetTop)();
+ if( (*fnRect->fnYDiff)( nTmpTop, (aLine.*fnRect->fnGetTop)() ) > 0 )
+ {
+ if( (*fnRect->fnYDiff)( nNextTop, nTmpTop ) > 0 )
+ SetNextTop( nTmpTop ); // Die Oberkante des "naechsten" Rahmens
+ }
+ else if( ! (aTmp.*fnRect->fnGetWidth)() ) // Typisch fuer Objekte mit Konturumlauf
+ { // Bei Objekten mit Konturumlauf, die vor der aktuellen Zeile beginnen
+ // und hinter ihr enden, trotzdem aber nicht mit ihr ueberlappen,
+ // muss die Optimierung ausgeschaltet werden, denn bereits in der
+ // naechsten Zeile kann sich dies aendern.
+ if( ! (aTmp.*fnRect->fnGetHeight)() ||
+ (*fnRect->fnYDiff)( (aTmp.*fnRect->fnGetBottom)(),
+ (aLine.*fnRect->fnGetTop)() ) > 0 )
+ SetNextTop( 0 );
+ }
+ if( aTmp.IsOver( aLine ) && nTmpRight > nFlyRight )
+ {
+ nFlyRight = nTmpRight;
+ if( SURROUND_RIGHT == eSurroundForTextWrap ||
+ SURROUND_PARALLEL == eSurroundForTextWrap )
+ {
+ // der FlyFrm wird ueberstimmt.
+ if( nRight > nFlyRight )
+ nRight = nFlyRight;
+ bStop = sal_True;
+ }
+ }
+ }
+ (rFly.*fnRect->fnSetRight)( nRight );
+}
+// <--
+
+/*************************************************************************
+ * SwTxtFly::CalcLeftMargin()
+ *
+ * pFly ist der FlyFrm, der uns gerade ueberlappt.
+ * pCurrFrm ist der aktuelle Textframe, der ueberlappt wird.
+ * Der linke Rand ist der linke Rand der aktuellen PrintArea oder
+ * er wird durch den vorigen FlyFrm, der in die Zeile ragt, bestimmt.
+ *************************************************************************/
+// --> OD 2006-08-15 #i68520#
+void SwTxtFly::CalcLeftMargin( SwRect &rFly,
+ SwAnchoredObjList::size_type nFlyPos,
+ const SwRect &rLine ) const
+{
+ OSL_ENSURE( ! pCurrFrm->IsVertical() || ! pCurrFrm->IsSwapped(),
+ "SwTxtFly::CalcLeftMargin with swapped frame" );
+ SWRECTFN( pCurrFrm )
+ // --> OD 2004-12-14 #118796# - correct determination of left of printing area
+ SwTwips nLeft = (pCurrFrm->*fnRect->fnGetPrtLeft)();
+ // <--
+ const SwTwips nFlyLeft = (rFly.*fnRect->fnGetLeft)();
+
+ if( nLeft > nFlyLeft )
+ nLeft = rFly.Left();
+
+ SwRect aLine( rLine );
+ (aLine.*fnRect->fnSetLeft)( nLeft );
+
+ // Es koennte aber sein, dass in die gleiche Zeile noch ein anderes
+ // Object hineinragt, welches _ueber_ uns liegt.
+ // Wunder der Technik: Flys mit Durchlauf sind fuer die darunterliegenden
+ // unsichtbar, das heisst, dass sie bei der Berechnung der Raender
+ // anderer Flys ebenfalls nicht auffallen.
+ // 3301: pNext->Frm().IsOver( rLine ) ist noetig
+
+ // --> OD 2006-08-15 #i68520#
+ SwAnchoredObjList::size_type nMyPos = nFlyPos;
+ while( ++nFlyPos < mpAnchoredObjList->size() )
+ // <--
+ {
+ // --> OD 2006-08-15 #i68520#
+ const SwAnchoredObject* pNext = (*mpAnchoredObjList)[ nFlyPos ];
+ const SwRect aTmp( pNext->GetObjRectWithSpaces() );
+ // <--
+ if( (aTmp.*fnRect->fnGetLeft)() >= nFlyLeft )
+ break;
+ }
+
+ while( nFlyPos )
+ {
+ if( --nFlyPos == nMyPos )
+ continue;
+ // --> OD 2006-08-15 #i68520#
+ const SwAnchoredObject* pNext = (*mpAnchoredObjList)[ nFlyPos ];
+ if( pNext == mpCurrAnchoredObj )
+ continue;
+ SwSurround eSurroundForTextWrap = _GetSurroundForTextWrap( pNext );
+ if( SURROUND_THROUGHT == eSurroundForTextWrap )
+ continue;
+ // <--
+
+ const SwRect aTmp( SwContourCache::CalcBoundRect
+ ( pNext, aLine, pCurrFrm, nFlyLeft, sal_False ) );
+
+ if( (aTmp.*fnRect->fnGetLeft)() < nFlyLeft && aTmp.IsOver( aLine ) )
+ {
+ // --> OD 2004-12-14 #118796# - no '+1', because <..fnGetRight>
+ // returns the correct value.
+ SwTwips nTmpRight = (aTmp.*fnRect->fnGetRight)();
+ if ( nLeft <= nTmpRight )
+ nLeft = nTmpRight;
+ // <--
+
+ break;
+ }
+ }
+ (rFly.*fnRect->fnSetLeft)( nLeft );
+}
+// <--
+
+/*************************************************************************
+ * SwTxtFly::FlyToRect()
+ *
+ * IN: dokumentglobal (rRect)
+ * OUT: dokumentglobal (return-Wert)
+ * Liefert zu einem SwFlyFrm das von ihm in Anspruch genommene Rechteck
+ * unter Beruecksichtigung der eingestellten Attribute fuer den Abstand
+ * zum Text zurueck.
+ *************************************************************************/
+// --> OD 2006-08-15 #i68520#
+SwRect SwTxtFly::AnchoredObjToRect( const SwAnchoredObject* pAnchoredObj,
+ const SwRect &rLine ) const
+{
+ SWRECTFN( pCurrFrm )
+
+ const long nXPos = pCurrFrm->IsRightToLeft() ?
+ rLine.Right() :
+ (rLine.*fnRect->fnGetLeft)();
+
+ SwRect aFly = mbIgnoreContour ?
+ pAnchoredObj->GetObjRectWithSpaces() :
+ SwContourCache::CalcBoundRect( pAnchoredObj, rLine, pCurrFrm,
+ nXPos, ! pCurrFrm->IsRightToLeft() );
+
+ if( !aFly.Width() )
+ return aFly;
+
+ SetNextTop( (aFly.*fnRect->fnGetBottom)() ); // Damit die Zeile ggf. bis zur Unterkante
+ // des Rahmens waechst.
+ SwAnchoredObjList::size_type nFlyPos = GetPos( pAnchoredObj );
+
+ // Bei LEFT und RIGHT vergroessern wir das Rechteck.
+ // Hier gibt es einige Probleme, wenn mehrere Frames zu sehen sind.
+ // Zur Zeit wird nur der einfachste Fall angenommen:
+ // LEFT bedeutet, dass der Text links vom Frame fliessen soll,
+ // d.h. der Frame blaeht sich bis zum rechten Rand der Printarea
+ // oder bis zum naechsten Frame auf.
+ // Bei RIGHT ist es umgekehrt.
+ // Ansonsten wird immer der eingestellte Abstand zwischen Text
+ // und Frame aufaddiert.
+ switch( _GetSurroundForTextWrap( pAnchoredObj ) )
+ {
+ case SURROUND_LEFT :
+ {
+ CalcRightMargin( aFly, nFlyPos, rLine );
+ break;
+ }
+ case SURROUND_RIGHT :
+ {
+ CalcLeftMargin( aFly, nFlyPos, rLine );
+ break;
+ }
+ case SURROUND_NONE :
+ {
+ CalcRightMargin( aFly, nFlyPos, rLine );
+ CalcLeftMargin( aFly, nFlyPos, rLine );
+ break;
+ }
+ default:
+ break;
+ }
+ return aFly;
+}
+
+// --> OD 2006-08-15 #i68520#
+// new method <_GetSurroundForTextWrap(..)> replaces methods
+// <CalcSmart(..)> and <GetOrder(..)>
+/*************************************************************************
+ * SwTxtFly::CalcSmart()
+ *
+ * CalcSmart() liefert die Umlaufform zurueck.
+ *
+ * Auf beiden Seiten ist weniger als 2 cm Platz fuer den Text
+ * => kein Umlauf ( SURROUND_NONE )
+ * Auf genau einer Seite ist mehr als 2 cm Platz
+ * => Umlauf auf dieser Seite ( SURROUND_LEFT / SURROUND_RIGHT )
+ * Auf beiden Seiten ist mehr als 2 cm Platz, das Objekt ist breiter als 1,5 cm
+ * => Umlauf auf der breiteren Seite ( SURROUND_LEFT / SURROUND_RIGHT )
+ * Auf beiden Seiten ist mehr als 2 cm Platz, das Objekt ist schmaler als 1,5 cm
+ * => beidseitiger Umlauf ( SURROUND_PARALLEL )
+ *
+ *************************************************************************/
+
+// Umfluss nur auf Seiten mit mindestens 2 cm Platz fuer den Text
+#define TEXT_MIN 1134
+// Beidseitiger Umfluss bis zu einer Rahmenbreite von maximal 1,5 cm
+#define FRAME_MAX 850
+
+SwSurround SwTxtFly::_GetSurroundForTextWrap( const SwAnchoredObject* pAnchoredObj ) const
+{
+ const SwFrmFmt* pFmt = &(pAnchoredObj->GetFrmFmt());
+ const SwFmtSurround &rFlyFmt = pFmt->GetSurround();
+ SwSurround eSurroundForTextWrap = rFlyFmt.GetSurround();
+
+ if( rFlyFmt.IsAnchorOnly() && pAnchoredObj->GetAnchorFrm() != GetMaster() )
+ {
+ const SwFmtAnchor& rAnchor = pFmt->GetAnchor();
+ if ((FLY_AT_PARA == rAnchor.GetAnchorId()) ||
+ (FLY_AT_CHAR == rAnchor.GetAnchorId()))
+ {
+ return SURROUND_NONE;
+ }
+ }
+
+ // Beim Durchlauf und Nowrap wird smart ignoriert.
+ if( SURROUND_THROUGHT == eSurroundForTextWrap ||
+ SURROUND_NONE == eSurroundForTextWrap )
+ return eSurroundForTextWrap;
+
+ // left is left and right is right
+ if ( pCurrFrm->IsRightToLeft() )
+ {
+ if ( SURROUND_LEFT == eSurroundForTextWrap )
+ eSurroundForTextWrap = SURROUND_RIGHT;
+ else if ( SURROUND_RIGHT == eSurroundForTextWrap )
+ eSurroundForTextWrap = SURROUND_LEFT;
+ }
+
+ // "idealer Seitenumlauf":
+ if ( SURROUND_IDEAL == eSurroundForTextWrap )
+ {
+ SWRECTFN( pCurrFrm )
+ const long nCurrLeft = (pCurrFrm->*fnRect->fnGetPrtLeft)();
+ const long nCurrRight = (pCurrFrm->*fnRect->fnGetPrtRight)();
+ const SwRect aRect( pAnchoredObj->GetObjRectWithSpaces() );
+ long nFlyLeft = (aRect.*fnRect->fnGetLeft)();
+ long nFlyRight = (aRect.*fnRect->fnGetRight)();
+
+ if ( nFlyRight < nCurrLeft || nFlyLeft > nCurrRight )
+ eSurroundForTextWrap = SURROUND_PARALLEL;
+ else
+ {
+ long nLeft = nFlyLeft - nCurrLeft;
+ long nRight = nCurrRight - nFlyRight;
+ if( nFlyRight - nFlyLeft > FRAME_MAX )
+ {
+ if( nLeft < nRight )
+ nLeft = 0;
+ else
+ nRight = 0;
+ }
+ if( nLeft < TEXT_MIN )
+ nLeft = 0;
+ if( nRight < TEXT_MIN )
+ nRight = 0;
+ if( nLeft )
+ eSurroundForTextWrap = nRight ? SURROUND_PARALLEL : SURROUND_LEFT;
+ else
+ eSurroundForTextWrap = nRight ? SURROUND_RIGHT: SURROUND_NONE;
+ }
+ }
+
+ return eSurroundForTextWrap;
+}
+
+/*************************************************************************
+ * SwTxtFly::IsAnyFrm( SwRect )
+ *
+ * IN: dokumentglobal
+ *
+ * dient zum Abschalten des SwTxtFly, wenn keine Objekte ueberlappen (Relax)
+ *
+ *************************************************************************/
+
+sal_Bool SwTxtFly::IsAnyFrm( const SwRect &rLine ) const
+{
+
+ SWAP_IF_SWAPPED( pCurrFrm )
+
+ OSL_ENSURE( bOn, "IsAnyFrm: Why?" );
+
+ const sal_Bool bRet = ForEach( rLine, NULL, sal_False );
+ UNDO_SWAP( pCurrFrm )
+ return bRet;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/text/txtfly.hxx b/sw/source/core/text/txtfly.hxx
new file mode 100644
index 000000000000..1b0120e10a24
--- /dev/null
+++ b/sw/source/core/text/txtfly.hxx
@@ -0,0 +1,219 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+#ifndef _TXTFLY_HXX
+#define _TXTFLY_HXX
+
+#include "swtypes.hxx"
+#include "swrect.hxx"
+
+class OutputDevice;
+class SwCntntFrm;
+class SwPageFrm;
+class SwTxtFly;
+class SdrObject;
+class SwTxtPaintInfo;
+class SwFmt;
+class TextRanger;
+class Color;
+class SwAnchoredObject;
+
+#include <fmtsrndenum.hxx>
+
+#include <vector>
+typedef std::vector< SwAnchoredObject* > SwAnchoredObjList;
+
+/*************************************************************************
+ * class SwFlyIter
+ *************************************************************************/
+enum PAGESIDE { LEFT_SIDE, RIGHT_SIDE, DONTKNOW_SIDE };
+
+/*************************************************************************
+ * class SwContourCache
+ *************************************************************************/
+
+class SwDrawTextInfo;
+// Contour-Cache, globale Variable, in txtinit.cxx initialisiert/zerstoert
+// und in txtfly.cxx benutzt bei Konturumfluss
+class SwContourCache;
+extern SwContourCache *pContourCache;
+class SwTxtFrm;
+
+#define POLY_CNT 20
+#define POLY_MIN 5
+#define POLY_MAX 4000
+
+class SwContourCache
+{
+ friend void ClrContourCache();
+ const SdrObject *pSdrObj[ POLY_CNT ];
+ TextRanger *pTextRanger[ POLY_CNT ];
+ long nPntCnt;
+ MSHORT nObjCnt;
+ const SwRect ContourRect( const SwFmt* pFmt, const SdrObject* pObj,
+ const SwTxtFrm* pFrm, const SwRect &rLine, const long nXPos,
+ const sal_Bool bRight );
+
+public:
+ SwContourCache();
+ ~SwContourCache();
+ const SdrObject* GetObject( MSHORT nPos ) const{ return pSdrObj[ nPos ]; }
+ MSHORT GetCount() const { return nObjCnt; }
+ void ClrObject( MSHORT nPos );
+ static const SwRect CalcBoundRect( const SwAnchoredObject* pAnchoredObj,
+ const SwRect &rLine,
+ const SwTxtFrm* pFrm,
+ const long nXPos,
+ const sal_Bool bRight );
+#if OSL_DEBUG_LEVEL > 1
+ void ShowContour( OutputDevice* pOut, const SdrObject* pObj,
+ const Color& rClosedColor, const Color& rOpenColor );
+#endif
+};
+
+/*************************************************************************
+ * class SwTxtFly
+ *************************************************************************/
+
+class SwTxtFly
+{
+ const SwPageFrm *pPage;
+ const SwAnchoredObject* mpCurrAnchoredObj;
+ const SwTxtFrm *pCurrFrm;
+ const SwCntntFrm *pMaster;
+ SwAnchoredObjList* mpAnchoredObjList;
+ long nMinBottom;
+ long nNextTop; // Hier wird die Oberkante des "naechsten" Rahmens gespeichert
+ sal_uLong nIndex;
+ sal_Bool bOn : 1;
+ sal_Bool bLeftSide : 1;
+ sal_Bool bTopRule: 1;
+ sal_Bool mbIgnoreCurrentFrame: 1;
+ sal_Bool mbIgnoreContour: 1;
+ // boolean, indicating if objects in page header|footer are considered for
+ // text frames not in page header|footer.
+ sal_Bool mbIgnoreObjsInHeaderFooter: 1;
+ SwRect _GetFrm( const SwRect &rPortion, sal_Bool bTop ) const;
+ SwAnchoredObjList* InitAnchoredObjList();
+ inline SwAnchoredObjList* GetAnchoredObjList() const
+ {
+ return mpAnchoredObjList
+ ? mpAnchoredObjList
+ : const_cast<SwTxtFly*>(this)->InitAnchoredObjList();
+ }
+ // iterates over the anchored object list <mpAnchoredObjList>
+ sal_Bool ForEach( const SwRect &rRect, SwRect* pRect, sal_Bool bAvoid ) const;
+ SwSurround _GetSurroundForTextWrap( const SwAnchoredObject* pAnchoredObj ) const;
+ void CalcRightMargin( SwRect &rFly,
+ SwAnchoredObjList::size_type nPos,
+ const SwRect &rLine ) const;
+ void CalcLeftMargin( SwRect &rFly,
+ SwAnchoredObjList::size_type nPos,
+ const SwRect &rLine ) const;
+ SwAnchoredObjList::size_type GetPos( const SwAnchoredObject* pAnchoredObj ) const;
+ sal_Bool GetTop( const SwAnchoredObject* _pAnchoredObj,
+ const sal_Bool bInFtn,
+ const sal_Bool bInFooterOrHeader );
+ SwTwips CalcMinBottom() const;
+ const SwCntntFrm* _GetMaster();
+
+public:
+ inline SwTxtFly() : pPage(0), mpCurrAnchoredObj(0), pCurrFrm(0), pMaster(0), mpAnchoredObjList(0), nMinBottom(0), nNextTop(0),
+ nIndex(0) {}
+ inline SwTxtFly( const SwTxtFrm *pFrm )
+ { CtorInitTxtFly( pFrm ); }
+
+ SwTxtFly( const SwTxtFly& rTxtFly );
+ inline ~SwTxtFly() { delete mpAnchoredObjList; }
+ void CtorInitTxtFly( const SwTxtFrm *pFrm );
+ void SetTopRule(){ bTopRule = sal_False; }
+
+ inline SwRect GetFrm( const SwRect &rPortion, sal_Bool bTop = sal_True ) const;
+ inline sal_Bool IsOn() const { return bOn; }
+ inline sal_Bool Relax( const SwRect &rRect );
+ inline sal_Bool Relax();
+ inline SwTwips GetMinBottom() const
+ { return mpAnchoredObjList ? nMinBottom : CalcMinBottom(); }
+ inline const SwCntntFrm* GetMaster() const
+ { return pMaster ? pMaster : ((SwTxtFly*)this)->_GetMaster(); }
+ inline long GetNextTop() const { return nNextTop; }
+ // Diese temporaere Variable darf auch in const-Methoden manipuliert werden
+ inline void SetNextTop( long nNew ) const
+ { ((SwTxtFly*)this)->nNextTop = nNew; }
+
+ // determines the demanded rectangle for an anchored object,
+ // considering its surround for text wrapping.
+ SwRect AnchoredObjToRect( const SwAnchoredObject* pAnchoredObj,
+ const SwRect& rRect ) const;
+
+ // Die Drawmethoden stellen sicher, dass ueberlappende Frames
+ // (ausser bei transparenten Frames) nicht uebergepinselt werden.
+ sal_Bool DrawTextOpaque( SwDrawTextInfo &rInf );
+
+ void DrawFlyRect( OutputDevice* pOut, const SwRect &rRect,
+ const SwTxtPaintInfo &rInf, sal_Bool bNoGraphic = sal_False );
+
+ // Liefert zurueck, ob die Zeile von einem Frame ueberlappt wird.
+ sal_Bool IsAnyFrm( const SwRect &rLine ) const;
+ sal_Bool IsAnyFrm() const;
+ //Das Rechteck kann leer sein, es gilt dann der Frm.
+ sal_Bool IsAnyObj( const SwRect& ) const;
+
+ void SetIgnoreCurrentFrame( sal_Bool bNew ) { mbIgnoreCurrentFrame = bNew; }
+ void SetIgnoreContour( sal_Bool bNew ) { mbIgnoreContour = bNew; }
+ inline void SetIgnoreObjsInHeaderFooter( const sal_Bool _bNew )
+ {
+ mbIgnoreObjsInHeaderFooter = _bNew;
+ }
+
+#if OSL_DEBUG_LEVEL > 1
+ void ShowContour( OutputDevice* pOut );
+#endif
+};
+
+// Wenn in das rRect (meist die aktuelle Zeile) kein freifliegender
+// Frame ragt, dann schalten wir uns ab.
+// rRect ist dokumentglobal !
+inline sal_Bool SwTxtFly::Relax( const SwRect &rRect )
+{
+ return 0 != (bOn = bOn && IsAnyFrm( rRect ));
+}
+
+inline sal_Bool SwTxtFly::Relax()
+{
+ return 0 != (bOn = bOn && IsAnyFrm());
+}
+
+inline SwRect SwTxtFly::GetFrm( const SwRect &rRect, sal_Bool bTop ) const
+{
+ return bOn ? _GetFrm( rRect, bTop ) : SwRect();
+}
+
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/text/txtfrm.cxx b/sw/source/core/text/txtfrm.cxx
new file mode 100644
index 000000000000..8e1114ba5853
--- /dev/null
+++ b/sw/source/core/text/txtfrm.cxx
@@ -0,0 +1,2813 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+#include <hintids.hxx>
+#include <hints.hxx>
+#include <svl/ctloptions.hxx>
+#include <sfx2/printer.hxx>
+#include <sfx2/sfxuno.hxx>
+#include <editeng/langitem.hxx>
+#include <editeng/lspcitem.hxx>
+#include <editeng/lrspitem.hxx>
+#include <editeng/ulspitem.hxx>
+#include <editeng/brshitem.hxx>
+#include <editeng/pgrditem.hxx>
+#include <swmodule.hxx>
+#include <SwSmartTagMgr.hxx>
+#include <doc.hxx> // GetDoc()
+#include "rootfrm.hxx"
+#include <pagefrm.hxx> // InvalidateSpelling
+#include <rootfrm.hxx>
+#include <viewsh.hxx> // ViewShell
+#include <pam.hxx> // SwPosition
+#include <ndtxt.hxx> // SwTxtNode
+#include <txtatr.hxx>
+#include <paratr.hxx>
+#include <viewopt.hxx>
+#include <dflyobj.hxx>
+#include <flyfrm.hxx>
+#include <tabfrm.hxx>
+#include <frmtool.hxx>
+#include <pagedesc.hxx> // SwPageDesc
+#include <tgrditem.hxx>
+#include <dbg_lay.hxx>
+#include <fmtfld.hxx>
+#include <fmtftn.hxx>
+#include <txtfld.hxx>
+#include <txtftn.hxx>
+#include <charatr.hxx>
+#include <ftninfo.hxx>
+#include <fmtline.hxx>
+#include <txtfrm.hxx> // SwTxtFrm
+#include <sectfrm.hxx> // SwSectFrm
+#include <itrform2.hxx> // Iteratoren
+#include <widorp.hxx> // SwFrmBreak
+#include <txtcache.hxx>
+#include <fntcache.hxx> // GetLineSpace benutzt pLastFont
+#include <SwGrammarMarkUp.hxx>
+#include <lineinfo.hxx>
+#include <SwPortionHandler.hxx>
+#include <dcontact.hxx>
+#include <sortedobjs.hxx>
+#include <txtflcnt.hxx> // SwTxtFlyCnt
+#include <fmtflcnt.hxx> // SwFmtFlyCnt
+#include <fmtcntnt.hxx> // SwFmtCntnt
+#include <numrule.hxx>
+#include <swtable.hxx>
+#include <fldupde.hxx>
+#include <IGrammarContact.hxx>
+#include <switerator.hxx>
+
+#if OSL_DEBUG_LEVEL > 1
+#include <txtpaint.hxx> // DbgRect
+extern const sal_Char *GetPrepName( const enum PrepareHint ePrep );
+#endif
+
+
+TYPEINIT1( SwTxtFrm, SwCntntFrm );
+
+// Switches width and height of the text frame
+void SwTxtFrm::SwapWidthAndHeight()
+{
+ if ( ! bIsSwapped )
+ {
+ const long nPrtOfstX = Prt().Pos().X();
+ Prt().Pos().X() = Prt().Pos().Y();
+ //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin
+ if( IsVertLR() )
+ Prt().Pos().Y() = nPrtOfstX;
+ else
+ Prt().Pos().Y() = Frm().Width() - ( nPrtOfstX + Prt().Width() );
+
+ }
+ else
+ {
+ const long nPrtOfstY = Prt().Pos().Y();
+ Prt().Pos().Y() = Prt().Pos().X();
+ //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin
+ if( IsVertLR() )
+ Prt().Pos().X() = nPrtOfstY;
+ else
+ Prt().Pos().X() = Frm().Height() - ( nPrtOfstY + Prt().Height() );
+ }
+
+ const long nFrmWidth = Frm().Width();
+ Frm().Width( Frm().Height() );
+ Frm().Height( nFrmWidth );
+ const long nPrtWidth = Prt().Width();
+ Prt().Width( Prt().Height() );
+ Prt().Height( nPrtWidth );
+
+ bIsSwapped = ! bIsSwapped;
+}
+
+// Calculates the coordinates of a rectangle when switching from
+// horizontal to vertical layout.
+void SwTxtFrm::SwitchHorizontalToVertical( SwRect& rRect ) const
+{
+ // calc offset inside frame
+ //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin
+ long nOfstX, nOfstY;
+ if ( IsVertLR() )
+ {
+ nOfstX = rRect.Left() - Frm().Left();
+ nOfstY = rRect.Top() - Frm().Top();
+ }
+ else
+ {
+ nOfstX = rRect.Left() - Frm().Left();
+ nOfstY = rRect.Top() + rRect.Height() - Frm().Top();
+ }
+
+ const long nWidth = rRect.Width();
+ const long nHeight = rRect.Height();
+
+ //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin
+ if ( IsVertLR() )
+ rRect.Left(Frm().Left() + nOfstY);
+ else
+ {
+ if ( bIsSwapped )
+ rRect.Left( Frm().Left() + Frm().Height() - nOfstY );
+ else
+ // frame is rotated
+ rRect.Left( Frm().Left() + Frm().Width() - nOfstY );
+ }
+
+ rRect.Top( Frm().Top() + nOfstX );
+ rRect.Width( nHeight );
+ rRect.Height( nWidth );
+}
+
+// Calculates the coordinates of a point when switching from
+// horizontal to vertical layout.
+void SwTxtFrm::SwitchHorizontalToVertical( Point& rPoint ) const
+{
+ // calc offset inside frame
+ const long nOfstX = rPoint.X() - Frm().Left();
+ const long nOfstY = rPoint.Y() - Frm().Top();
+ //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin
+ if ( IsVertLR() )
+ rPoint.X() = Frm().Left() + nOfstY;
+ else
+ {
+ if ( bIsSwapped )
+ rPoint.X() = Frm().Left() + Frm().Height() - nOfstY;
+ else
+ // calc rotated coords
+ rPoint.X() = Frm().Left() + Frm().Width() - nOfstY;
+ }
+
+ rPoint.Y() = Frm().Top() + nOfstX;
+}
+
+// Calculates the a limit value when switching from
+// horizontal to vertical layout.
+long SwTxtFrm::SwitchHorizontalToVertical( long nLimit ) const
+{
+ Point aTmp( 0, nLimit );
+ SwitchHorizontalToVertical( aTmp );
+ return aTmp.X();
+}
+
+// Calculates the coordinates of a rectangle when switching from
+// vertical to horizontal layout.
+void SwTxtFrm::SwitchVerticalToHorizontal( SwRect& rRect ) const
+{
+ long nOfstX;
+
+ // calc offset inside frame
+
+ //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin
+ if ( IsVertLR() )
+ nOfstX = rRect.Left() - Frm().Left();
+ else
+ {
+ if ( bIsSwapped )
+ nOfstX = Frm().Left() + Frm().Height() - ( rRect.Left() + rRect.Width() );
+ else
+ nOfstX = Frm().Left() + Frm().Width() - ( rRect.Left() + rRect.Width() );
+ }
+
+ const long nOfstY = rRect.Top() - Frm().Top();
+ const long nWidth = rRect.Height();
+ const long nHeight = rRect.Width();
+
+ // calc rotated coords
+ rRect.Left( Frm().Left() + nOfstY );
+ rRect.Top( Frm().Top() + nOfstX );
+ rRect.Width( nWidth );
+ rRect.Height( nHeight );
+}
+
+// Calculates the coordinates of a point when switching from
+// vertical to horizontal layout.
+void SwTxtFrm::SwitchVerticalToHorizontal( Point& rPoint ) const
+{
+ long nOfstX;
+
+ // calc offset inside frame
+
+ //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin
+ if ( IsVertLR() )
+ nOfstX = rPoint.X() - Frm().Left();
+ else
+ {
+ if ( bIsSwapped )
+ nOfstX = Frm().Left() + Frm().Height() - rPoint.X();
+ else
+ nOfstX = Frm().Left() + Frm().Width() - rPoint.X();
+ }
+
+ const long nOfstY = rPoint.Y() - Frm().Top();
+
+ // calc rotated coords
+ rPoint.X() = Frm().Left() + nOfstY;
+ rPoint.Y() = Frm().Top() + nOfstX;
+}
+
+// Calculates the a limit value when switching from
+// vertical to horizontal layout.
+long SwTxtFrm::SwitchVerticalToHorizontal( long nLimit ) const
+{
+ Point aTmp( nLimit, 0 );
+ SwitchVerticalToHorizontal( aTmp );
+ return aTmp.Y();
+}
+
+SwFrmSwapper::SwFrmSwapper( const SwTxtFrm* pTxtFrm, sal_Bool bSwapIfNotSwapped )
+ : pFrm( pTxtFrm ), bUndo( sal_False )
+{
+ if ( pFrm->IsVertical() &&
+ ( ( bSwapIfNotSwapped && ! pFrm->IsSwapped() ) ||
+ ( ! bSwapIfNotSwapped && pFrm->IsSwapped() ) ) )
+ {
+ bUndo = sal_True;
+ ((SwTxtFrm*)pFrm)->SwapWidthAndHeight();
+ }
+}
+
+SwFrmSwapper::~SwFrmSwapper()
+{
+ if ( bUndo )
+ ((SwTxtFrm*)pFrm)->SwapWidthAndHeight();
+}
+
+void SwTxtFrm::SwitchLTRtoRTL( SwRect& rRect ) const
+{
+ SWAP_IF_NOT_SWAPPED( this )
+
+ long nWidth = rRect.Width();
+ rRect.Left( 2 * ( Frm().Left() + Prt().Left() ) +
+ Prt().Width() - rRect.Right() - 1 );
+
+ rRect.Width( nWidth );
+
+ UNDO_SWAP( this )
+}
+
+void SwTxtFrm::SwitchLTRtoRTL( Point& rPoint ) const
+{
+ SWAP_IF_NOT_SWAPPED( this )
+
+ rPoint.X() = 2 * ( Frm().Left() + Prt().Left() ) + Prt().Width() - rPoint.X() - 1;
+
+ UNDO_SWAP( this )
+}
+
+SwLayoutModeModifier::SwLayoutModeModifier( const OutputDevice& rOutp ) :
+ rOut( rOutp ), nOldLayoutMode( rOutp.GetLayoutMode() )
+{
+}
+
+SwLayoutModeModifier::~SwLayoutModeModifier()
+{
+ ((OutputDevice&)rOut).SetLayoutMode( nOldLayoutMode );
+}
+
+void SwLayoutModeModifier::Modify( sal_Bool bChgToRTL )
+{
+ ((OutputDevice&)rOut).SetLayoutMode( bChgToRTL ?
+ TEXT_LAYOUT_BIDI_STRONG | TEXT_LAYOUT_BIDI_RTL :
+ TEXT_LAYOUT_BIDI_STRONG );
+}
+
+void SwLayoutModeModifier::SetAuto()
+{
+ const sal_uLong nNewLayoutMode = nOldLayoutMode & ~TEXT_LAYOUT_BIDI_STRONG;
+ ((OutputDevice&)rOut).SetLayoutMode( nNewLayoutMode );
+}
+
+SwDigitModeModifier::SwDigitModeModifier( const OutputDevice& rOutp, LanguageType eCurLang ) :
+ rOut( rOutp ), nOldLanguageType( rOutp.GetDigitLanguage() )
+{
+ LanguageType eLang = eCurLang;
+ const SvtCTLOptions::TextNumerals nTextNumerals = SW_MOD()->GetCTLOptions().GetCTLTextNumerals();
+
+ if ( SvtCTLOptions::NUMERALS_HINDI == nTextNumerals )
+ eLang = LANGUAGE_ARABIC_SAUDI_ARABIA;
+ else if ( SvtCTLOptions::NUMERALS_ARABIC == nTextNumerals )
+ eLang = LANGUAGE_ENGLISH;
+ else if ( SvtCTLOptions::NUMERALS_SYSTEM == nTextNumerals )
+ eLang = (LanguageType)::GetAppLanguage();
+
+ ((OutputDevice&)rOut).SetDigitLanguage( eLang );
+}
+
+SwDigitModeModifier::~SwDigitModeModifier()
+{
+ ((OutputDevice&)rOut).SetDigitLanguage( nOldLanguageType );
+}
+
+/*************************************************************************
+ * SwTxtFrm::Init()
+ *************************************************************************/
+
+void SwTxtFrm::Init()
+{
+ OSL_ENSURE( !IsLocked(), "+SwTxtFrm::Init: this ist locked." );
+ if( !IsLocked() )
+ {
+ ClearPara();
+ ResetBlinkPor();
+ //Die Flags direkt setzen um ResetPreps und damit ein unnuetzes GetPara
+ //einzusparen.
+ // Nicht bOrphan, bLocked oder bWait auf sal_False setzen !
+ // bOrphan = bFlag7 = bFlag8 = sal_False;
+ }
+}
+
+/*************************************************************************
+|* SwTxtFrm::CTORen/DTOR
+|*************************************************************************/
+
+void SwTxtFrm::InitCtor()
+{
+ nCacheIdx = MSHRT_MAX;
+ nOfst = 0;
+ nAllLines = 0;
+ nThisLines = 0;
+ mnFlyAnchorOfst = 0;
+ mnFlyAnchorOfstNoWrap = 0;
+ mnFtnLine = 0;
+ // OD 2004-03-17 #i11860#
+ mnHeightOfLastLine = 0;
+ mnAdditionalFirstLineOffset = 0;
+
+ nType = FRMC_TXT;
+ bLocked = bFormatted = bWidow = bUndersized = bJustWidow =
+ bEmpty = bInFtnConnect = bFtn = bRepaint = bBlinkPor =
+ bFieldFollow = bHasAnimation = bIsSwapped = sal_False;
+ // OD 14.03.2003 #i11760#
+ mbFollowFormatAllowed = sal_True;
+}
+
+/*************************************************************************
+ * SwTxtFrm::SwTxtFrm()
+ *************************************************************************/
+SwTxtFrm::SwTxtFrm(SwTxtNode * const pNode, SwFrm* pSib )
+ : SwCntntFrm( pNode, pSib )
+{
+ InitCtor();
+}
+
+/*************************************************************************
+ * SwTxtFrm::~SwTxtFrm()
+ *************************************************************************/
+SwTxtFrm::~SwTxtFrm()
+{
+ // Remove associated SwParaPortion from pTxtCache
+ ClearPara();
+}
+
+const XubString& SwTxtFrm::GetTxt() const
+{
+ return GetTxtNode()->GetTxt();
+}
+
+void SwTxtFrm::ResetPreps()
+{
+ if ( GetCacheIdx() != MSHRT_MAX )
+ {
+ SwParaPortion *pPara;
+ if( 0 != (pPara = GetPara()) )
+ pPara->ResetPreps();
+ }
+}
+
+/*************************************************************************
+ * SwTxtFrm::IsHiddenNow()
+ *************************************************************************/
+sal_Bool SwTxtFrm::IsHiddenNow() const
+{
+ SwFrmSwapper aSwapper( this, sal_True );
+
+ if( !Frm().Width() && IsValid() && GetUpper()->IsValid() )
+ //bei Stackueberlauf (StackHack) invalid!
+ {
+// OSL_FAIL( "SwTxtFrm::IsHiddenNow: thin frame" );
+ return sal_True;
+ }
+
+ const bool bHiddenCharsHidePara = GetTxtNode()->HasHiddenCharAttribute( true );
+ const bool bHiddenParaField = GetTxtNode()->HasHiddenParaField();
+ const ViewShell* pVsh = getRootFrm()->GetCurrShell();
+
+ if ( pVsh && ( bHiddenCharsHidePara || bHiddenParaField ) )
+ {
+ if (
+ ( bHiddenParaField &&
+ ( !pVsh->GetViewOptions()->IsShowHiddenPara() &&
+ !pVsh->GetViewOptions()->IsFldName() ) ) ||
+ ( bHiddenCharsHidePara &&
+ !pVsh->GetViewOptions()->IsShowHiddenChar() ) )
+ {
+ return sal_True;
+ }
+ }
+
+ return sal_False;
+}
+
+
+/*************************************************************************
+ * SwTxtFrm::HideHidden()
+ *************************************************************************/
+// Entfernt die Anhaengsel des Textfrms wenn dieser hidden ist
+
+void SwTxtFrm::HideHidden()
+{
+ OSL_ENSURE( !GetFollow() && IsHiddenNow(),
+ "HideHidden on visible frame of hidden frame has follow" );
+
+ const xub_StrLen nEnd = STRING_LEN;
+ HideFootnotes( GetOfst(), nEnd );
+ // OD 2004-01-15 #110582#
+ HideAndShowObjects();
+
+ //Die Formatinfos sind jetzt obsolete
+ ClearPara();
+}
+
+/*************************************************************************
+ * SwTxtFrm::HideFootnotes()
+ *************************************************************************/
+void SwTxtFrm::HideFootnotes( xub_StrLen nStart, xub_StrLen nEnd )
+{
+ const SwpHints *pHints = GetTxtNode()->GetpSwpHints();
+ if( pHints )
+ {
+ const sal_uInt16 nSize = pHints->Count();
+ SwPageFrm *pPage = 0;
+ for ( sal_uInt16 i = 0; i < nSize; ++i )
+ {
+ const SwTxtAttr *pHt = (*pHints)[i];
+ if ( pHt->Which() == RES_TXTATR_FTN )
+ {
+ const xub_StrLen nIdx = *pHt->GetStart();
+ if ( nEnd < nIdx )
+ break;
+ if( nStart <= nIdx )
+ {
+ if( !pPage )
+ pPage = FindPageFrm();
+ pPage->RemoveFtn( this, (SwTxtFtn*)pHt );
+ }
+ }
+ }
+ }
+}
+
+// --> OD 2005-03-30 #120729# - hotfix: WW8 documents contain at its end hidden,
+// as-character anchored graphics, which are used for a graphic bullet list.
+// As long as these graphic bullet list aren't imported, do not hide a
+// at-character anchored object, if
+// (a) the document is an imported WW8 document -
+// checked by checking certain compatibility options -,
+// (b) the paragraph is the last content in the document and
+// (c) the anchor character is an as-character anchored graphic.
+bool lcl_HideObj( const SwTxtFrm& _rFrm,
+ const RndStdIds _eAnchorType,
+ const xub_StrLen _nObjAnchorPos,
+ SwAnchoredObject* _pAnchoredObj )
+{
+ bool bRet( true );
+
+ if (_eAnchorType == FLY_AT_CHAR)
+ {
+ const IDocumentSettingAccess* pIDSA = _rFrm.GetTxtNode()->getIDocumentSettingAccess();
+ if ( !pIDSA->get(IDocumentSettingAccess::USE_FORMER_TEXT_WRAPPING) &&
+ !pIDSA->get(IDocumentSettingAccess::OLD_LINE_SPACING) &&
+ !pIDSA->get(IDocumentSettingAccess::USE_FORMER_OBJECT_POS) &&
+ pIDSA->get(IDocumentSettingAccess::CONSIDER_WRAP_ON_OBJECT_POSITION) &&
+ _rFrm.IsInDocBody() && !_rFrm.FindNextCnt() )
+ {
+ const xub_Unicode cAnchorChar =
+ _rFrm.GetTxtNode()->GetTxt().GetChar( _nObjAnchorPos );
+ if ( cAnchorChar == CH_TXTATR_BREAKWORD )
+ {
+ const SwTxtAttr* const pHint(
+ _rFrm.GetTxtNode()->GetTxtAttrForCharAt(_nObjAnchorPos,
+ RES_TXTATR_FLYCNT) );
+ if ( pHint )
+ {
+ const SwFrmFmt* pFrmFmt =
+ static_cast<const SwTxtFlyCnt*>(pHint)->GetFlyCnt().GetFrmFmt();
+ if ( pFrmFmt->Which() == RES_FLYFRMFMT )
+ {
+ SwNodeIndex nCntntIndex = *(pFrmFmt->GetCntnt().GetCntntIdx());
+ nCntntIndex++;
+ if ( nCntntIndex.GetNode().IsNoTxtNode() )
+ {
+ bRet = false;
+ // set needed data structure values for object positioning
+ SWRECTFN( (&_rFrm) );
+ SwRect aLastCharRect( _rFrm.Frm() );
+ (aLastCharRect.*fnRect->fnSetWidth)( 1 );
+ _pAnchoredObj->maLastCharRect = aLastCharRect;
+ _pAnchoredObj->mnLastTopOfLine = (aLastCharRect.*fnRect->fnGetTop)();
+ }
+ }
+ }
+ }
+ }
+ }
+
+ return bRet;
+}
+// <--
+/*************************************************************************
+ * SwTxtFrm::HideAndShowObjects()
+ *************************************************************************/
+/** method to hide/show objects
+
+ OD 2004-01-15 #110582#
+ method hides respectively shows objects, which are anchored at paragraph,
+ at/as a character of the paragraph, corresponding to the paragraph and
+ paragraph portion visibility.
+
+ - is called from HideHidden() - should hide objects in hidden paragraphs and
+ - from _Format() - should hide/show objects in partly visible paragraphs
+
+ @author OD
+*/
+void SwTxtFrm::HideAndShowObjects()
+{
+ if ( GetDrawObjs() )
+ {
+ if ( IsHiddenNow() )
+ {
+ // complete paragraph is hidden. Thus, hide all objects
+ for ( sal_uInt32 i = 0; i < GetDrawObjs()->Count(); ++i )
+ {
+ SdrObject* pObj = (*GetDrawObjs())[i]->DrawObj();
+ SwContact* pContact = static_cast<SwContact*>(pObj->GetUserCall());
+ // --> OD 2005-03-30 #120729# - hotfix: do not hide object
+ // under certain conditions
+ const RndStdIds eAnchorType( pContact->GetAnchorId() );
+ const xub_StrLen nObjAnchorPos = pContact->GetCntntAnchorIndex().GetIndex();
+ if ((eAnchorType != FLY_AT_CHAR) ||
+ lcl_HideObj( *this, eAnchorType, nObjAnchorPos,
+ (*GetDrawObjs())[i] ))
+ {
+ pContact->MoveObjToInvisibleLayer( pObj );
+ }
+ // <--
+ }
+ }
+ else
+ {
+ // paragraph is visible, but can contain hidden text portion.
+ // first we check if objects are allowed to be hidden:
+ const SwTxtNode& rNode = *GetTxtNode();
+ const ViewShell* pVsh = getRootFrm()->GetCurrShell();
+ const bool bShouldBeHidden = !pVsh || !pVsh->GetWin() ||
+ !pVsh->GetViewOptions()->IsShowHiddenChar();
+
+ // Thus, show all objects, which are anchored at paragraph and
+ // hide/show objects, which are anchored at/as character, according
+ // to the visibility of the anchor character.
+ for ( sal_uInt32 i = 0; i < GetDrawObjs()->Count(); ++i )
+ {
+ SdrObject* pObj = (*GetDrawObjs())[i]->DrawObj();
+ SwContact* pContact = static_cast<SwContact*>(pObj->GetUserCall());
+ // --> OD 2005-03-30 #120729# - determine anchor type only once
+ const RndStdIds eAnchorType( pContact->GetAnchorId() );
+ // <--
+
+ if (eAnchorType == FLY_AT_PARA)
+ {
+ pContact->MoveObjToVisibleLayer( pObj );
+ }
+ else if ((eAnchorType == FLY_AT_CHAR) ||
+ (eAnchorType == FLY_AS_CHAR))
+ {
+ xub_StrLen nHiddenStart;
+ xub_StrLen nHiddenEnd;
+ xub_StrLen nObjAnchorPos = pContact->GetCntntAnchorIndex().GetIndex();
+ SwScriptInfo::GetBoundsOfHiddenRange( rNode, nObjAnchorPos, nHiddenStart, nHiddenEnd, 0 );
+ // --> OD 2005-03-30 #120729# - hotfix: do not hide object
+ // under certain conditions
+ if ( nHiddenStart != STRING_LEN && bShouldBeHidden &&
+ lcl_HideObj( *this, eAnchorType, nObjAnchorPos, (*GetDrawObjs())[i] ) )
+ // <--
+ pContact->MoveObjToInvisibleLayer( pObj );
+ else
+ pContact->MoveObjToVisibleLayer( pObj );
+ }
+ else
+ {
+ OSL_FAIL( "<SwTxtFrm::HideAndShowObjects()> - object not anchored at/inside paragraph!?" );
+ }
+ }
+ }
+ }
+
+ if ( IsFollow() )
+ {
+ FindMaster()->HideAndShowObjects();
+ }
+}
+
+/*************************************************************************
+ * SwTxtFrm::FindBrk()
+ *
+ * Liefert die erste Trennmoeglichkeit in der aktuellen Zeile zurueck.
+ * Die Methode wird in SwTxtFrm::Format() benutzt, um festzustellen, ob
+ * die Vorgaengerzeile mitformatiert werden muss.
+ * nFound ist <= nEndLine.
+ *************************************************************************/
+
+xub_StrLen SwTxtFrm::FindBrk( const XubString &rTxt,
+ const xub_StrLen nStart,
+ const xub_StrLen nEnd ) const
+{
+ // --> OD 2009-12-28 #i104291# - applying patch to avoid overflow.
+ unsigned long nFound = nStart;
+ const xub_StrLen nEndLine = Min( nEnd, rTxt.Len() );
+
+ // Wir ueberlesen erst alle Blanks am Anfang der Zeile (vgl. Bug 2235).
+ while( nFound <= nEndLine &&
+ ' ' == rTxt.GetChar( static_cast<xub_StrLen>(nFound) ) )
+ {
+ nFound++;
+ }
+
+ // Eine knifflige Sache mit den TxtAttr-Dummy-Zeichen (hier "$"):
+ // "Dr.$Meyer" am Anfang der zweiten Zeile. Dahinter ein Blank eingegeben
+ // und das Wort rutscht nicht in die erste Zeile, obwohl es ginge.
+ // Aus diesem Grund nehmen wir das Dummy-Zeichen noch mit.
+ while( nFound <= nEndLine &&
+ ' ' != rTxt.GetChar( static_cast<xub_StrLen>(nFound) ) )
+ {
+ nFound++;
+ }
+
+ return nFound <= STRING_LEN
+ ? static_cast<xub_StrLen>(nFound)
+ : STRING_LEN;
+ // <--
+}
+
+/*************************************************************************
+ * SwTxtFrm::IsIdxInside()
+ *************************************************************************/
+
+sal_Bool SwTxtFrm::IsIdxInside( const xub_StrLen nPos, const xub_StrLen nLen ) const
+{
+ if( GetOfst() > nPos + nLen ) // d.h., der Bereich liegt komplett vor uns.
+ return sal_False;
+
+ if( !GetFollow() ) // der Bereich liegt nicht komplett vor uns,
+ return sal_True; // nach uns kommt niemand mehr.
+
+ const xub_StrLen nMax = GetFollow()->GetOfst();
+
+ // der Bereich liegt nicht komplett hinter uns bzw.
+ // unser Text ist geloescht worden.
+ if( nMax > nPos || nMax > GetTxt().Len() )
+ return sal_True;
+
+ // changes made in the first line of a follow can modify the master
+ const SwParaPortion* pPara = GetFollow()->GetPara();
+ return pPara && ( nPos <= nMax + pPara->GetLen() );
+}
+
+/*************************************************************************
+ * SwTxtFrm::InvalidateRange()
+ *************************************************************************/
+inline void SwTxtFrm::InvalidateRange(const SwCharRange &aRange, const long nD)
+{
+ if ( IsIdxInside( aRange.Start(), aRange.Len() ) )
+ _InvalidateRange( aRange, nD );
+}
+
+/*************************************************************************
+ * SwTxtFrm::_InvalidateRange()
+ *************************************************************************/
+
+void SwTxtFrm::_InvalidateRange( const SwCharRange &aRange, const long nD)
+{
+ if ( !HasPara() )
+ { InvalidateSize();
+ return;
+ }
+
+ SetWidow( sal_False );
+ SwParaPortion *pPara = GetPara();
+
+ sal_Bool bInv = sal_False;
+ if( 0 != nD )
+ {
+ //Auf nDelta werden die Differenzen zwischen alter und
+ //neuer Zeilenlaenge aufaddiert, deshalb ist es negativ,
+ //wenn Zeichen eingefuegt wurden, positiv, wenn Zeichen
+ //geloescht wurden.
+ *(pPara->GetDelta()) += nD;
+ bInv = sal_True;
+ }
+ SwCharRange &rReformat = *(pPara->GetReformat());
+ if(aRange != rReformat) {
+ if( STRING_LEN == rReformat.Len() )
+ rReformat = aRange;
+ else
+ rReformat += aRange;
+ bInv = sal_True;
+ }
+ if(bInv)
+ {
+// 90365: nD is passed to a follow two times
+// if( GetFollow() )
+// ((SwTxtFrm*)GetFollow())->InvalidateRange( aRange, nD );
+ InvalidateSize();
+ }
+}
+
+/*************************************************************************
+ * SwTxtFrm::CalcLineSpace()
+ *************************************************************************/
+
+void SwTxtFrm::CalcLineSpace()
+{
+ OSL_ENSURE( ! IsVertical() || ! IsSwapped(),
+ "SwTxtFrm::CalcLineSpace with swapped frame!" );
+
+ if( IsLocked() || !HasPara() )
+ return;
+
+ SwParaPortion *pPara;
+ if( GetDrawObjs() ||
+ GetTxtNode()->GetSwAttrSet().GetLRSpace().IsAutoFirst() ||
+ ( pPara = GetPara() )->IsFixLineHeight() )
+ {
+ Init();
+ return;
+ }
+
+ Size aNewSize( Prt().SSize() );
+
+ SwTxtFormatInfo aInf( this );
+ SwTxtFormatter aLine( this, &aInf );
+ if( aLine.GetDropLines() )
+ {
+ Init();
+ return;
+ }
+
+ aLine.Top();
+ aLine.RecalcRealHeight();
+
+ aNewSize.Height() = (aLine.Y() - Frm().Top()) + aLine.GetLineHeight();
+
+ SwTwips nDelta = aNewSize.Height() - Prt().Height();
+ // 4291: Unterlauf bei Flys
+ if( aInf.GetTxtFly()->IsOn() )
+ {
+ SwRect aTmpFrm( Frm() );
+ if( nDelta < 0 )
+ aTmpFrm.Height( Prt().Height() );
+ else
+ aTmpFrm.Height( aNewSize.Height() );
+ if( aInf.GetTxtFly()->Relax( aTmpFrm ) )
+ {
+ Init();
+ return;
+ }
+ }
+
+ if( nDelta )
+ {
+ SwTxtFrmBreak aBreak( this );
+ if( GetFollow() || aBreak.IsBreakNow( aLine ) )
+ {
+ // Wenn es einen Follow() gibt, oder wenn wir an dieser
+ // Stelle aufbrechen muessen, so wird neu formatiert.
+ Init();
+ }
+ else
+ {
+ // Alles nimmt seinen gewohnten Gang ...
+ pPara->SetPrepAdjust();
+ pPara->SetPrep();
+ }
+ }
+}
+
+//
+// SET_WRONG( nPos, nCnt, bMove )
+//
+#define SET_WRONG( nPos, nCnt, bMove ) \
+{ \
+ lcl_SetWrong( *this, nPos, nCnt, bMove ); \
+}
+
+void lcl_SetWrong( SwTxtFrm& rFrm, xub_StrLen nPos, long nCnt, bool bMove )
+{
+ if ( !rFrm.IsFollow() )
+ {
+ SwTxtNode* pTxtNode = rFrm.GetTxtNode();
+ IGrammarContact* pGrammarContact = getGrammarContact( *pTxtNode );
+ SwGrammarMarkUp* pWrongGrammar = pGrammarContact ?
+ pGrammarContact->getGrammarCheck( *pTxtNode, false ) :
+ pTxtNode->GetGrammarCheck();
+ bool bGrammarProxy = pWrongGrammar != pTxtNode->GetGrammarCheck();
+ if( bMove )
+ {
+ if( pTxtNode->GetWrong() )
+ pTxtNode->GetWrong()->Move( nPos, nCnt );
+ if( pWrongGrammar )
+ pWrongGrammar->MoveGrammar( nPos, nCnt );
+ if( bGrammarProxy && pTxtNode->GetGrammarCheck() )
+ pTxtNode->GetGrammarCheck()->MoveGrammar( nPos, nCnt );
+ if( pTxtNode->GetSmartTags() )
+ pTxtNode->GetSmartTags()->Move( nPos, nCnt );
+ }
+ else
+ {
+ xub_StrLen nLen = (xub_StrLen)nCnt;
+ if( pTxtNode->GetWrong() )
+ pTxtNode->GetWrong()->Invalidate( nPos, nLen );
+ if( pWrongGrammar )
+ pWrongGrammar->Invalidate( nPos, nLen );
+ if( pTxtNode->GetSmartTags() )
+ pTxtNode->GetSmartTags()->Invalidate( nPos, nLen );
+ }
+ if ( !pTxtNode->GetWrong() && !pTxtNode->IsWrongDirty() )
+ {
+ pTxtNode->SetWrong( new SwWrongList( WRONGLIST_SPELL ) );
+ pTxtNode->GetWrong()->SetInvalid( nPos, nPos + (sal_uInt16)( nCnt > 0 ? nCnt : 1 ) );
+ }
+ if ( !pTxtNode->GetSmartTags() && !pTxtNode->IsSmartTagDirty() )
+ {
+ // SMARTTAGS
+ pTxtNode->SetSmartTags( new SwWrongList( WRONGLIST_SMARTTAG ) );
+ pTxtNode->GetSmartTags()->SetInvalid( nPos, nPos + (sal_uInt16)( nCnt > 0 ? nCnt : 1 ) );
+ }
+ pTxtNode->SetWrongDirty( true );
+ pTxtNode->SetGrammarCheckDirty( true );
+ pTxtNode->SetWordCountDirty( true );
+ pTxtNode->SetAutoCompleteWordDirty( true );
+ // SMARTTAGS
+ pTxtNode->SetSmartTagDirty( true );
+ }
+
+ SwRootFrm *pRootFrm = rFrm.getRootFrm();
+ if (pRootFrm)
+ {
+ pRootFrm->SetNeedGrammarCheck( sal_True );
+ }
+
+ SwPageFrm *pPage = rFrm.FindPageFrm();
+ if( pPage )
+ {
+ pPage->InvalidateSpelling();
+ pPage->InvalidateAutoCompleteWords();
+ pPage->InvalidateWordCount();
+ pPage->InvalidateSmartTags();
+ }
+}
+
+//
+// SET_SCRIPT_INVAL( nPos )
+//
+
+#define SET_SCRIPT_INVAL( nPos )\
+ lcl_SetScriptInval( *this, nPos );
+
+void lcl_SetScriptInval( SwTxtFrm& rFrm, xub_StrLen nPos )
+{
+ if( rFrm.GetPara() )
+ rFrm.GetPara()->GetScriptInfo().SetInvalidity( nPos );
+}
+
+void lcl_ModifyOfst( SwTxtFrm* pFrm, xub_StrLen nPos, xub_StrLen nLen )
+{
+ while( pFrm && pFrm->GetOfst() <= nPos )
+ pFrm = pFrm->GetFollow();
+ while( pFrm )
+ {
+ pFrm->ManipOfst( pFrm->GetOfst() + nLen );
+ pFrm = pFrm->GetFollow();
+ }
+}
+
+/*************************************************************************
+ * SwTxtFrm::Modify()
+ *************************************************************************/
+
+void SwTxtFrm::Modify( const SfxPoolItem* pOld, const SfxPoolItem *pNew )
+{
+ const MSHORT nWhich = pOld ? pOld->Which() : pNew ? pNew->Which() : 0;
+
+ //Wuensche die FrmAttribute betreffen werden von der Basisklasse
+ //verarbeitet.
+ if( IsInRange( aFrmFmtSetRange, nWhich ) || RES_FMT_CHG == nWhich )
+ {
+ SwCntntFrm::Modify( pOld, pNew );
+ if( nWhich == RES_FMT_CHG && getRootFrm()->GetCurrShell() )
+ {
+ // Collection hat sich geaendert
+ Prepare( PREP_CLEAR );
+ _InvalidatePrt();
+ SET_WRONG( 0, STRING_LEN, false );
+ SetDerivedR2L( sal_False );
+ CheckDirChange();
+ // OD 09.12.2002 #105576# - Force complete paint due to existing
+ // indents.
+ SetCompletePaint();
+ InvalidateLineNum();
+ }
+ return;
+ }
+
+ // Im gelockten Zustand werden keine Bestellungen angenommen.
+ if( IsLocked() )
+ return;
+
+ // Dies spart Stack, man muss nur aufpassen,
+ // dass sie Variablen gesetzt werden.
+ xub_StrLen nPos, nLen;
+ sal_Bool bSetFldsDirty = sal_False;
+ sal_Bool bRecalcFtnFlag = sal_False;
+
+ switch( nWhich )
+ {
+ case RES_LINENUMBER:
+ {
+ InvalidateLineNum();
+ }
+ break;
+ case RES_INS_TXT:
+ {
+ nPos = ((SwInsTxt*)pNew)->nPos;
+ nLen = ((SwInsTxt*)pNew)->nLen;
+ if( IsIdxInside( nPos, nLen ) )
+ {
+ if( !nLen )
+ {
+ // 6969: Aktualisierung der NumPortions auch bei leeren Zeilen!
+ if( nPos )
+ InvalidateSize();
+ else
+ Prepare( PREP_CLEAR );
+ }
+ else
+ _InvalidateRange( SwCharRange( nPos, nLen ), nLen );
+ }
+ SET_WRONG( nPos, nLen, true )
+ SET_SCRIPT_INVAL( nPos )
+ bSetFldsDirty = sal_True;
+ if( HasFollow() )
+ lcl_ModifyOfst( this, nPos, nLen );
+ }
+ break;
+ case RES_DEL_CHR:
+ {
+ nPos = ((SwDelChr*)pNew)->nPos;
+ InvalidateRange( SwCharRange( nPos, 1 ), -1 );
+ SET_WRONG( nPos, -1, true )
+ SET_SCRIPT_INVAL( nPos )
+ bSetFldsDirty = bRecalcFtnFlag = sal_True;
+ if( HasFollow() )
+ lcl_ModifyOfst( this, nPos, STRING_LEN );
+ }
+ break;
+ case RES_DEL_TXT:
+ {
+ nPos = ((SwDelTxt*)pNew)->nStart;
+ nLen = ((SwDelTxt*)pNew)->nLen;
+ long m = nLen;
+ m *= -1;
+ if( IsIdxInside( nPos, nLen ) )
+ {
+ if( !nLen )
+ InvalidateSize();
+ else
+ InvalidateRange( SwCharRange( nPos, 1 ), m );
+ }
+ SET_WRONG( nPos, m, true )
+ SET_SCRIPT_INVAL( nPos )
+ bSetFldsDirty = bRecalcFtnFlag = sal_True;
+ if( HasFollow() )
+ lcl_ModifyOfst( this, nPos, nLen );
+ }
+ break;
+ case RES_UPDATE_ATTR:
+ {
+ nPos = ((SwUpdateAttr*)pNew)->nStart;
+ nLen = ((SwUpdateAttr*)pNew)->nEnd - nPos;
+ if( IsIdxInside( nPos, nLen ) )
+ {
+ // Es muss in jedem Fall neu formatiert werden,
+ // auch wenn der invalidierte Bereich null ist.
+ // Beispiel: leere Zeile, 14Pt einstellen !
+ // if( !nLen ) nLen = 1;
+
+ // 6680: FtnNummern muessen formatiert werden.
+ if( !nLen )
+ nLen = 1;
+
+ _InvalidateRange( SwCharRange( nPos, nLen) );
+ MSHORT nTmp = ((SwUpdateAttr*)pNew)->nWhichAttr;
+
+ if( ! nTmp || RES_TXTATR_CHARFMT == nTmp || RES_TXTATR_AUTOFMT == nTmp ||
+ RES_FMT_CHG == nTmp || RES_ATTRSET_CHG == nTmp )
+ {
+ SET_WRONG( nPos, nPos + nLen, false )
+ SET_SCRIPT_INVAL( nPos )
+ }
+ }
+
+ // --> OD 2010-02-16 #i104008#
+ ViewShell* pViewSh = getRootFrm() ? getRootFrm()->GetCurrShell() : 0;
+ if ( pViewSh )
+ {
+ pViewSh->InvalidateAccessibleParaAttrs( *this );
+ }
+ // <--
+ }
+ break;
+ case RES_OBJECTDYING:
+ break;
+
+ case RES_PARATR_LINESPACING:
+ {
+ CalcLineSpace();
+ InvalidateSize();
+ _InvalidatePrt();
+ if( IsInSct() && !GetPrev() )
+ {
+ SwSectionFrm *pSect = FindSctFrm();
+ if( pSect->ContainsAny() == this )
+ pSect->InvalidatePrt();
+ }
+
+ // OD 09.01.2004 #i11859# - correction:
+ // (1) Also invalidate next frame on next page/column.
+ // (2) Skip empty sections and hidden paragraphs
+ // Thus, use method <InvalidateNextPrtArea()>
+ InvalidateNextPrtArea();
+
+ SetCompletePaint();
+ }
+ break;
+ case RES_TXTATR_FIELD:
+ {
+ nPos = *((SwFmtFld*)pNew)->GetTxtFld()->GetStart();
+ if( IsIdxInside( nPos, 1 ) )
+ {
+ if( pNew == pOld )
+ {
+ // Nur repainten
+ // opt: invalidate aufs Window ?
+ InvalidatePage();
+ SetCompletePaint();
+ }
+ else
+ _InvalidateRange( SwCharRange( nPos, 1 ) );
+ }
+ bSetFldsDirty = sal_True;
+ // ST2
+ if ( SwSmartTagMgr::Get().IsSmartTagsEnabled() )
+ SET_WRONG( nPos, nPos + 1, false )
+ }
+ break;
+ case RES_TXTATR_FTN :
+ {
+ nPos = *((SwFmtFtn*)pNew)->GetTxtFtn()->GetStart();
+ if( IsInFtn() || IsIdxInside( nPos, 1 ) )
+ Prepare( PREP_FTN, ((SwFmtFtn*)pNew)->GetTxtFtn() );
+ break;
+ }
+
+ case RES_ATTRSET_CHG:
+ {
+ InvalidateLineNum();
+
+ SwAttrSet& rNewSet = *((SwAttrSetChg*)pNew)->GetChgSet();
+ const SfxPoolItem* pItem;
+ int nClear = 0;
+ MSHORT nCount = rNewSet.Count();
+
+ if( SFX_ITEM_SET == rNewSet.GetItemState( RES_TXTATR_FTN,
+ sal_False, &pItem ))
+ {
+ nPos = *((SwFmtFtn*)pItem)->GetTxtFtn()->GetStart();
+ if( IsIdxInside( nPos, 1 ) )
+ Prepare( PREP_FTN, pNew );
+ nClear = 0x01;
+ --nCount;
+ }
+
+ if( SFX_ITEM_SET == rNewSet.GetItemState( RES_TXTATR_FIELD,
+ sal_False, &pItem ))
+ {
+ nPos = *((SwFmtFld*)pItem)->GetTxtFld()->GetStart();
+ if( IsIdxInside( nPos, 1 ) )
+ {
+ const SfxPoolItem& rOldItem = ((SwAttrSetChg*)pOld)->
+ GetChgSet()->Get( RES_TXTATR_FIELD );
+ if( pItem == &rOldItem )
+ {
+ // Nur repainten
+ // opt: invalidate aufs Window ?
+ InvalidatePage();
+ SetCompletePaint();
+ }
+ else
+ _InvalidateRange( SwCharRange( nPos, 1 ) );
+ }
+ nClear |= 0x02;
+ --nCount;
+ }
+ sal_Bool bLineSpace = SFX_ITEM_SET == rNewSet.GetItemState(
+ RES_PARATR_LINESPACING, sal_False ),
+ bRegister = SFX_ITEM_SET == rNewSet.GetItemState(
+ RES_PARATR_REGISTER, sal_False );
+ if ( bLineSpace || bRegister )
+ {
+ Prepare( bRegister ? PREP_REGISTER : PREP_ADJUST_FRM );
+ CalcLineSpace();
+ InvalidateSize();
+ _InvalidatePrt();
+
+ // OD 09.01.2004 #i11859# - correction:
+ // (1) Also invalidate next frame on next page/column.
+ // (2) Skip empty sections and hidden paragraphs
+ // Thus, use method <InvalidateNextPrtArea()>
+ InvalidateNextPrtArea();
+
+ SetCompletePaint();
+ nClear |= 0x04;
+ if ( bLineSpace )
+ {
+ --nCount;
+ if( IsInSct() && !GetPrev() )
+ {
+ SwSectionFrm *pSect = FindSctFrm();
+ if( pSect->ContainsAny() == this )
+ pSect->InvalidatePrt();
+ }
+ }
+ if ( bRegister )
+ --nCount;
+ }
+ if ( SFX_ITEM_SET == rNewSet.GetItemState( RES_PARATR_SPLIT,
+ sal_False ))
+ {
+ if ( GetPrev() )
+ CheckKeep();
+ Prepare( PREP_CLEAR );
+ InvalidateSize();
+ nClear |= 0x08;
+ --nCount;
+ }
+
+ if( SFX_ITEM_SET == rNewSet.GetItemState( RES_BACKGROUND, sal_False)
+ && !IsFollow() && GetDrawObjs() )
+ {
+ SwSortedObjs *pObjs = GetDrawObjs();
+ for ( int i = 0; GetDrawObjs() && i < int(pObjs->Count()); ++i )
+ {
+ SwAnchoredObject* pAnchoredObj = (*pObjs)[MSHORT(i)];
+ if ( pAnchoredObj->ISA(SwFlyFrm) )
+ {
+ SwFlyFrm *pFly = static_cast<SwFlyFrm*>(pAnchoredObj);
+ if( !pFly->IsFlyInCntFrm() )
+ {
+ const SvxBrushItem &rBack =
+ pFly->GetAttrSet()->GetBackground();
+ // OD 20.08.2002 #99657# #GetTransChg#
+ // following condition determines, if the fly frame
+ // "inherites" the background color of text frame.
+ // This is the case, if fly frame background
+ // color is "no fill"/"auto fill" and if the fly frame
+ // has no background graphic.
+ // Thus, check complete fly frame background
+ // color and *not* only its transparency value
+ if ( (rBack.GetColor() == COL_TRANSPARENT) &&
+ //if( rBack.GetColor().GetTransparency() &&
+ rBack.GetGraphicPos() == GPOS_NONE )
+ {
+ pFly->SetCompletePaint();
+ pFly->InvalidatePage();
+ }
+ }
+ }
+ }
+ }
+
+ if ( SFX_ITEM_SET ==
+ rNewSet.GetItemState( RES_TXTATR_CHARFMT, sal_False ) )
+ {
+ SET_WRONG( 0, STRING_LEN, false )
+ SET_SCRIPT_INVAL( 0 )
+ }
+ else if ( SFX_ITEM_SET ==
+ rNewSet.GetItemState( RES_CHRATR_LANGUAGE, sal_False ) ||
+ SFX_ITEM_SET ==
+ rNewSet.GetItemState( RES_CHRATR_CJK_LANGUAGE, sal_False ) ||
+ SFX_ITEM_SET ==
+ rNewSet.GetItemState( RES_CHRATR_CTL_LANGUAGE, sal_False ) )
+ SET_WRONG( 0, STRING_LEN, false )
+ else if ( SFX_ITEM_SET ==
+ rNewSet.GetItemState( RES_CHRATR_FONT, sal_False ) ||
+ SFX_ITEM_SET ==
+ rNewSet.GetItemState( RES_CHRATR_CJK_FONT, sal_False ) ||
+ SFX_ITEM_SET ==
+ rNewSet.GetItemState( RES_CHRATR_CTL_FONT, sal_False ) )
+ SET_SCRIPT_INVAL( 0 )
+ else if ( SFX_ITEM_SET ==
+ rNewSet.GetItemState( RES_FRAMEDIR, sal_False ) )
+ {
+ SetDerivedR2L( sal_False );
+ CheckDirChange();
+ // OD 09.12.2002 #105576# - Force complete paint due to existing
+ // indents.
+ SetCompletePaint();
+ }
+
+
+ if( nCount )
+ {
+ if( getRootFrm()->GetCurrShell() )
+ {
+ Prepare( PREP_CLEAR );
+ _InvalidatePrt();
+ }
+
+ if( nClear )
+ {
+ SwAttrSetChg aOldSet( *(SwAttrSetChg*)pOld );
+ SwAttrSetChg aNewSet( *(SwAttrSetChg*)pNew );
+
+ if( 0x01 & nClear )
+ {
+ aOldSet.ClearItem( RES_TXTATR_FTN );
+ aNewSet.ClearItem( RES_TXTATR_FTN );
+ }
+ if( 0x02 & nClear )
+ {
+ aOldSet.ClearItem( RES_TXTATR_FIELD );
+ aNewSet.ClearItem( RES_TXTATR_FIELD );
+ }
+ if ( 0x04 & nClear )
+ {
+ if ( bLineSpace )
+ {
+ aOldSet.ClearItem( RES_PARATR_LINESPACING );
+ aNewSet.ClearItem( RES_PARATR_LINESPACING );
+ }
+ if ( bRegister )
+ {
+ aOldSet.ClearItem( RES_PARATR_REGISTER );
+ aNewSet.ClearItem( RES_PARATR_REGISTER );
+ }
+ }
+ if ( 0x08 & nClear )
+ {
+ aOldSet.ClearItem( RES_PARATR_SPLIT );
+ aNewSet.ClearItem( RES_PARATR_SPLIT );
+ }
+ SwCntntFrm::Modify( &aOldSet, &aNewSet );
+ }
+ else
+ SwCntntFrm::Modify( pOld, pNew );
+ }
+
+ // --> OD 2009-01-06 #i88069#
+ ViewShell* pViewSh = getRootFrm() ? getRootFrm()->GetCurrShell() : 0;
+ if ( pViewSh )
+ {
+ pViewSh->InvalidateAccessibleParaAttrs( *this );
+ }
+ // <--
+ }
+ break;
+
+/* Seit dem neuen Blocksatz muessen wir immer neu formatieren:
+ case RES_PARATR_ADJUST:
+ {
+ if( GetShell() )
+ {
+ Prepare( PREP_CLEAR );
+ }
+ break;
+ }
+*/
+ // 6870: SwDocPosUpdate auswerten.
+ case RES_DOCPOS_UPDATE:
+ {
+ if( pOld && pNew )
+ {
+ const SwDocPosUpdate *pDocPos = (const SwDocPosUpdate*)pOld;
+ if( pDocPos->nDocPos <= aFrm.Top() )
+ {
+ const SwFmtFld *pFld = (const SwFmtFld *)pNew;
+ InvalidateRange(
+ SwCharRange( *pFld->GetTxtFld()->GetStart(), 1 ) );
+ }
+ }
+ break;
+ }
+ case RES_PARATR_SPLIT:
+ if ( GetPrev() )
+ CheckKeep();
+ Prepare( PREP_CLEAR );
+ bSetFldsDirty = sal_True;
+ break;
+ case RES_FRAMEDIR :
+ SetDerivedR2L( sal_False );
+ CheckDirChange();
+ break;
+ default:
+ {
+ Prepare( PREP_CLEAR );
+ _InvalidatePrt();
+ if ( !nWhich )
+ {
+ //Wird z.B. bei HiddenPara mit 0 gerufen.
+ SwFrm *pNxt;
+ if ( 0 != (pNxt = FindNext()) )
+ pNxt->InvalidatePrt();
+ }
+ }
+ } // switch
+
+ if( bSetFldsDirty )
+ GetNode()->getIDocumentFieldsAccess()->SetFieldsDirty( sal_True, GetNode(), 1 );
+
+ if ( bRecalcFtnFlag )
+ CalcFtnFlag();
+}
+
+sal_Bool SwTxtFrm::GetInfo( SfxPoolItem &rHnt ) const
+{
+ if ( RES_VIRTPAGENUM_INFO == rHnt.Which() && IsInDocBody() && ! IsFollow() )
+ {
+ SwVirtPageNumInfo &rInfo = (SwVirtPageNumInfo&)rHnt;
+ const SwPageFrm *pPage = FindPageFrm();
+ if ( pPage )
+ {
+ if ( pPage == rInfo.GetOrigPage() && !GetPrev() )
+ {
+ //Das sollte er sein (kann allenfalls temporaer anders sein,
+ // sollte uns das beunruhigen?)
+ rInfo.SetInfo( pPage, this );
+ return sal_False;
+ }
+ if ( pPage->GetPhyPageNum() < rInfo.GetOrigPage()->GetPhyPageNum() &&
+ (!rInfo.GetPage() || pPage->GetPhyPageNum() > rInfo.GetPage()->GetPhyPageNum()))
+ {
+ //Das koennte er sein.
+ rInfo.SetInfo( pPage, this );
+ }
+ }
+ }
+ return sal_True;
+}
+
+/*************************************************************************
+ * SwTxtFrm::PrepWidows()
+ *************************************************************************/
+
+void SwTxtFrm::PrepWidows( const MSHORT nNeed, sal_Bool bNotify )
+{
+ OSL_ENSURE(GetFollow() && nNeed, "+SwTxtFrm::Prepare: lost all friends");
+
+ SwParaPortion *pPara = GetPara();
+ if ( !pPara )
+ return;
+ pPara->SetPrepWidows( sal_True );
+
+ // These two lines of code have been deleted for #102340#.
+ // Obviously the widow control does not work if we have a
+ // pMaster->pFollow->pFollow situation:
+
+ // returnen oder nicht ist hier die Frage.
+ // Ohne IsLocked() ist 5156 gefaehrlich,
+ // ohne IsFollow() werden die Orphans unterdrueckt: 6968.
+ // Abfrage auf IsLocked erst hier, weil das Flag gesetzt werden soll.
+// if( IsLocked() && IsFollow() )
+// return;
+
+ MSHORT nHave = nNeed;
+
+ // Wir geben ein paar Zeilen ab und schrumpfen im CalcPreps()
+ SWAP_IF_NOT_SWAPPED( this )
+
+ SwTxtSizeInfo aInf( this );
+ SwTxtMargin aLine( this, &aInf );
+ aLine.Bottom();
+ xub_StrLen nTmpLen = aLine.GetCurr()->GetLen();
+ while( nHave && aLine.PrevLine() )
+ {
+ if( nTmpLen )
+ --nHave;
+ nTmpLen = aLine.GetCurr()->GetLen();
+ }
+ // In dieser Ecke tummelten sich einige Bugs: 7513, 7606.
+ // Wenn feststeht, dass Zeilen abgegeben werden koennen,
+ // muss der Master darueber hinaus die Widow-Regel ueberpruefen.
+ if( !nHave )
+ {
+ sal_Bool bSplit;
+ if( !IsFollow() ) //Nur ein Master entscheidet ueber Orphans
+ {
+ const WidowsAndOrphans aWidOrp( this );
+ bSplit = ( aLine.GetLineNr() >= aWidOrp.GetOrphansLines() &&
+ aLine.GetLineNr() >= aLine.GetDropLines() );
+ }
+ else
+ bSplit = sal_True;
+
+ if( bSplit )
+ {
+ GetFollow()->SetOfst( aLine.GetEnd() );
+ aLine.TruncLines( sal_True );
+ if( pPara->IsFollowField() )
+ GetFollow()->SetFieldFollow( sal_True );
+ }
+ }
+ if ( bNotify )
+ {
+ _InvalidateSize();
+ InvalidatePage();
+ }
+
+ UNDO_SWAP( this )
+}
+
+/*************************************************************************
+ * SwTxtFrm::Prepare
+ *************************************************************************/
+
+sal_Bool lcl_ErgoVadis( SwTxtFrm* pFrm, xub_StrLen &rPos, const PrepareHint ePrep )
+{
+ const SwFtnInfo &rFtnInfo = pFrm->GetNode()->GetDoc()->GetFtnInfo();
+ if( ePrep == PREP_ERGOSUM )
+ {
+ if( !rFtnInfo.aErgoSum.Len() )
+ return sal_False;;
+ rPos = pFrm->GetOfst();
+ }
+ else
+ {
+ if( !rFtnInfo.aQuoVadis.Len() )
+ return sal_False;
+ if( pFrm->HasFollow() )
+ rPos = pFrm->GetFollow()->GetOfst();
+ else
+ rPos = pFrm->GetTxt().Len();
+ if( rPos )
+ --rPos; // unser letztes Zeichen
+ }
+ return sal_True;
+}
+
+void SwTxtFrm::Prepare( const PrepareHint ePrep, const void* pVoid,
+ sal_Bool bNotify )
+{
+ SwFrmSwapper aSwapper( this, sal_False );
+
+#if OSL_DEBUG_LEVEL > 1
+ const SwTwips nDbgY = Frm().Top();
+ (void)nDbgY;
+#endif
+
+ if ( IsEmpty() )
+ {
+ switch ( ePrep )
+ {
+ case PREP_BOSS_CHGD:
+ SetInvalidVert( sal_True ); // Test
+ case PREP_WIDOWS_ORPHANS:
+ case PREP_WIDOWS:
+ case PREP_FTN_GONE : return;
+
+ case PREP_POS_CHGD :
+ {
+ // Auch in (spaltigen) Bereichen ist ein InvalidateSize notwendig,
+ // damit formatiert wird und ggf. das bUndersized gesetzt wird.
+ if( IsInFly() || IsInSct() )
+ {
+ SwTwips nTmpBottom = GetUpper()->Frm().Top() +
+ GetUpper()->Prt().Bottom();
+ if( nTmpBottom < Frm().Bottom() )
+ break;
+ }
+ // Gibt es ueberhaupt Flys auf der Seite ?
+ SwTxtFly aTxtFly( this );
+ if( aTxtFly.IsOn() )
+ {
+ // Ueberlappt irgendein Fly ?
+ aTxtFly.Relax();
+ if ( aTxtFly.IsOn() || IsUndersized() )
+ break;
+ }
+ if( GetTxtNode()->GetSwAttrSet().GetRegister().GetValue())
+ break;
+
+ GETGRID( FindPageFrm() )
+ if ( pGrid && GetTxtNode()->GetSwAttrSet().GetParaGrid().GetValue() )
+ break;
+
+ // --> OD 2004-07-16 #i28701# - consider anchored objects
+ if ( GetDrawObjs() )
+ break;
+ // <--
+
+ return;
+ }
+ default:
+ break;
+ }
+ }
+
+ if( !HasPara() && PREP_MUST_FIT != ePrep )
+ {
+ SetInvalidVert( sal_True ); // Test
+ OSL_ENSURE( !IsLocked(), "SwTxtFrm::Prepare: three of a perfect pair" );
+ if ( bNotify )
+ InvalidateSize();
+ else
+ _InvalidateSize();
+ return;
+ }
+
+ //Objekt mit Locking aus dem Cache holen.
+ SwTxtLineAccess aAccess( this );
+ SwParaPortion *pPara = aAccess.GetPara();
+
+ switch( ePrep )
+ {
+ case PREP_MOVEFTN : Frm().Height(0);
+ Prt().Height(0);
+ _InvalidatePrt();
+ _InvalidateSize();
+ // KEIN break
+ case PREP_ADJUST_FRM : pPara->SetPrepAdjust( sal_True );
+ if( IsFtnNumFrm() != pPara->IsFtnNum() ||
+ IsUndersized() )
+ {
+ InvalidateRange( SwCharRange( 0, 1 ), 1);
+ if( GetOfst() && !IsFollow() )
+ _SetOfst( 0 );
+ }
+ break;
+ case PREP_MUST_FIT : pPara->SetPrepMustFit( sal_True );
+ /* no break here */
+ case PREP_WIDOWS_ORPHANS : pPara->SetPrepAdjust( sal_True );
+ break;
+
+ case PREP_WIDOWS :
+ // MustFit ist staerker als alles anderes
+ if( pPara->IsPrepMustFit() )
+ return;
+ // Siehe Kommentar in WidowsAndOrphans::FindOrphans und CalcPreps()
+ PrepWidows( *(const MSHORT *)pVoid, bNotify );
+ break;
+
+ case PREP_FTN :
+ {
+ SwTxtFtn *pFtn = (SwTxtFtn *)pVoid;
+ if( IsInFtn() )
+ {
+ // Bin ich der erste TxtFrm einer Fussnote ?
+ if( !GetPrev() )
+ // Wir sind also ein TxtFrm der Fussnote, die
+ // die Fussnotenzahl zur Anzeige bringen muss.
+ // Oder den ErgoSum-Text...
+ InvalidateRange( SwCharRange( 0, 1 ), 1);
+
+ if( !GetNext() )
+ {
+ // Wir sind der letzte Ftn, jetzt muessten die
+ // QuoVadis-Texte geupdated werden.
+ const SwFtnInfo &rFtnInfo = GetNode()->GetDoc()->GetFtnInfo();
+ if( !pPara->UpdateQuoVadis( rFtnInfo.aQuoVadis ) )
+ {
+ xub_StrLen nPos = pPara->GetParLen();
+ if( nPos )
+ --nPos;
+ InvalidateRange( SwCharRange( nPos, 1 ), 1);
+ }
+ }
+ }
+ else
+ {
+ // Wir sind also der TxtFrm _mit_ der Fussnote
+ const xub_StrLen nPos = *pFtn->GetStart();
+ InvalidateRange( SwCharRange( nPos, 1 ), 1);
+ }
+ break;
+ }
+ case PREP_BOSS_CHGD :
+ {
+ // Test
+ {
+ SetInvalidVert( sal_False );
+ sal_Bool bOld = IsVertical();
+ SetInvalidVert( sal_True );
+ if( bOld != IsVertical() )
+ InvalidateRange( SwCharRange( GetOfst(), STRING_LEN ) );
+ }
+
+ if( HasFollow() )
+ {
+ xub_StrLen nNxtOfst = GetFollow()->GetOfst();
+ if( nNxtOfst )
+ --nNxtOfst;
+ InvalidateRange( SwCharRange( nNxtOfst, 1 ), 1);
+ }
+ if( IsInFtn() )
+ {
+ xub_StrLen nPos;
+ if( lcl_ErgoVadis( this, nPos, PREP_QUOVADIS ) )
+ InvalidateRange( SwCharRange( nPos, 1 ), 0 );
+ if( lcl_ErgoVadis( this, nPos, PREP_ERGOSUM ) )
+ InvalidateRange( SwCharRange( nPos, 1 ), 0 );
+ }
+ // 4739: Wenn wir ein Seitennummernfeld besitzen, muessen wir
+ // die Stellen invalidieren.
+ SwpHints *pHints = GetTxtNode()->GetpSwpHints();
+ if( pHints )
+ {
+ const sal_uInt16 nSize = pHints->Count();
+ const xub_StrLen nEnd = GetFollow() ?
+ GetFollow()->GetOfst() : STRING_LEN;
+ for ( sal_uInt16 i = 0; i < nSize; ++i )
+ {
+ const SwTxtAttr *pHt = (*pHints)[i];
+ const xub_StrLen nStart = *pHt->GetStart();
+ if( nStart >= GetOfst() )
+ {
+ if( nStart >= nEnd )
+ i = nSize; // fuehrt das Ende herbei
+ else
+ {
+ // 4029: wenn wir zurueckfliessen und eine Ftn besitzen, so
+ // fliesst die Ftn in jedem Fall auch mit. Damit sie nicht im
+ // Weg steht, schicken wir uns ein ADJUST_FRM.
+ // pVoid != 0 bedeutet MoveBwd()
+ const MSHORT nWhich = pHt->Which();
+ if( RES_TXTATR_FIELD == nWhich ||
+ (HasFtn() && pVoid && RES_TXTATR_FTN == nWhich))
+ InvalidateRange( SwCharRange( nStart, 1 ), 1 );
+ }
+ }
+ }
+ }
+ // A new boss, a new chance for growing
+ if( IsUndersized() )
+ {
+ _InvalidateSize();
+ InvalidateRange( SwCharRange( GetOfst(), 1 ), 1);
+ }
+ break;
+ }
+
+ case PREP_POS_CHGD :
+ {
+ if ( GetValidPrtAreaFlag() )
+ {
+ GETGRID( FindPageFrm() )
+ if ( pGrid && GetTxtNode()->GetSwAttrSet().GetParaGrid().GetValue() )
+ InvalidatePrt();
+ }
+
+ // Falls wir mit niemandem ueberlappen:
+ // Ueberlappte irgendein Fly _vor_ der Positionsaenderung ?
+ sal_Bool bFormat = pPara->HasFly();
+ if( !bFormat )
+ {
+ if( IsInFly() )
+ {
+ SwTwips nTmpBottom = GetUpper()->Frm().Top() +
+ GetUpper()->Prt().Bottom();
+ if( nTmpBottom < Frm().Bottom() )
+ bFormat = sal_True;
+ }
+ if( !bFormat )
+ {
+ if ( GetDrawObjs() )
+ {
+ const sal_uInt32 nCnt = GetDrawObjs()->Count();
+ for ( MSHORT i = 0; i < nCnt; ++i )
+ {
+ SwAnchoredObject* pAnchoredObj = (*GetDrawObjs())[i];
+ // --> OD 2004-07-16 #i28701# - consider all
+ // to-character anchored objects
+ if ( pAnchoredObj->GetFrmFmt().GetAnchor().GetAnchorId()
+ == FLY_AT_CHAR )
+ {
+ bFormat = sal_True;
+ break;
+ }
+ }
+ }
+ if( !bFormat )
+ {
+ // Gibt es ueberhaupt Flys auf der Seite ?
+ SwTxtFly aTxtFly( this );
+ if( aTxtFly.IsOn() )
+ {
+ // Ueberlappt irgendein Fly ?
+ aTxtFly.Relax();
+ bFormat = aTxtFly.IsOn() || IsUndersized();
+ }
+ }
+ }
+ }
+
+ if( bFormat )
+ {
+ if( !IsLocked() )
+ {
+ if( pPara->GetRepaint()->HasArea() )
+ SetCompletePaint();
+ Init();
+ pPara = 0;
+ _InvalidateSize();
+ }
+ }
+ else
+ {
+ if( GetTxtNode()->GetSwAttrSet().GetRegister().GetValue() )
+ Prepare( PREP_REGISTER, 0, bNotify );
+ // Durch Positionsverschiebungen mit Ftns muessen die
+ // Frames neu adjustiert werden.
+ else if( HasFtn() )
+ {
+ Prepare( PREP_ADJUST_FRM, 0, bNotify );
+ _InvalidateSize();
+ }
+ else
+ return; // damit kein SetPrep() erfolgt.
+ }
+ break;
+ }
+ case PREP_REGISTER:
+ if( GetTxtNode()->GetSwAttrSet().GetRegister().GetValue() )
+ {
+ pPara->SetPrepAdjust( sal_True );
+ CalcLineSpace();
+ InvalidateSize();
+ _InvalidatePrt();
+ SwFrm* pNxt;
+ if ( 0 != ( pNxt = GetIndNext() ) )
+ {
+ pNxt->_InvalidatePrt();
+ if ( pNxt->IsLayoutFrm() )
+ pNxt->InvalidatePage();
+ }
+ SetCompletePaint();
+ }
+ break;
+ case PREP_FTN_GONE :
+ {
+ // Wenn ein Follow uns ruft, weil eine Fussnote geloescht wird, muss unsere
+ // letzte Zeile formatiert werden, damit ggf. die erste Zeile des Follows
+ // hochrutschen kann, die extra auf die naechste Seite gerutscht war, um mit
+ // der Fussnote zusammen zu sein, insbesondere bei spaltigen Bereichen.
+ OSL_ENSURE( GetFollow(), "PREP_FTN_GONE darf nur vom Follow gerufen werden" );
+ xub_StrLen nPos = GetFollow()->GetOfst();
+ if( IsFollow() && GetOfst() == nPos ) // falls wir gar keine Textmasse besitzen,
+ FindMaster()->Prepare( PREP_FTN_GONE ); // rufen wir das Prepare unseres Masters
+ if( nPos )
+ --nPos; // das Zeichen vor unserem Follow
+ InvalidateRange( SwCharRange( nPos, 1 ), 0 );
+ return;
+ }
+ case PREP_ERGOSUM:
+ case PREP_QUOVADIS:
+ {
+ xub_StrLen nPos;
+ if( lcl_ErgoVadis( this, nPos, ePrep ) )
+ InvalidateRange( SwCharRange( nPos, 1 ), 0 );
+ }
+ break;
+ case PREP_FLY_ATTR_CHG:
+ {
+ if( pVoid )
+ {
+ xub_StrLen nWhere = CalcFlyPos( (SwFrmFmt*)pVoid );
+ OSL_ENSURE( STRING_LEN != nWhere, "Prepare: Why me?" );
+ InvalidateRange( SwCharRange( nWhere, 1 ) );
+ return;
+ }
+ // else ... Laufe in den Default-Switch
+ }
+ case PREP_CLEAR:
+ default:
+ {
+ if( IsLocked() )
+ {
+ if( PREP_FLY_ARRIVE == ePrep || PREP_FLY_LEAVE == ePrep )
+ {
+ xub_StrLen nLen = ( GetFollow() ? GetFollow()->GetOfst() :
+ STRING_LEN ) - GetOfst();
+ InvalidateRange( SwCharRange( GetOfst(), nLen ), 0 );
+ }
+ }
+ else
+ {
+ if( pPara->GetRepaint()->HasArea() )
+ SetCompletePaint();
+ Init();
+ pPara = 0;
+ if( GetOfst() && !IsFollow() )
+ _SetOfst( 0 );
+ if ( bNotify )
+ InvalidateSize();
+ else
+ _InvalidateSize();
+ }
+ return; // damit kein SetPrep() erfolgt.
+ }
+ }
+ if( pPara )
+ pPara->SetPrep( sal_True );
+}
+
+/* --------------------------------------------------
+ * Kleine Hilfsklasse mit folgender Funktion:
+ * Sie soll eine Probeformatierung vorbereiten.
+ * Der Frame wird in Groesse und Position angepasst, sein SwParaPortion zur Seite
+ * gestellt und eine neue erzeugt, dazu wird formatiert mit gesetztem bTestFormat.
+ * Im Dtor wird der TxtFrm wieder in seinen alten Zustand zurueckversetzt.
+ *
+ * --------------------------------------------------*/
+
+class SwTestFormat
+{
+ SwTxtFrm *pFrm;
+ SwParaPortion *pOldPara;
+ SwRect aOldFrm, aOldPrt;
+public:
+ SwTestFormat( SwTxtFrm* pTxtFrm, const SwFrm* pPrv, SwTwips nMaxHeight );
+ ~SwTestFormat();
+};
+
+SwTestFormat::SwTestFormat( SwTxtFrm* pTxtFrm, const SwFrm* pPre, SwTwips nMaxHeight )
+ : pFrm( pTxtFrm )
+{
+ aOldFrm = pFrm->Frm();
+ aOldPrt = pFrm->Prt();
+
+ SWRECTFN( pFrm )
+ SwTwips nLower = (pFrm->*fnRect->fnGetBottomMargin)();
+
+ pFrm->Frm() = pFrm->GetUpper()->Prt();
+ pFrm->Frm() += pFrm->GetUpper()->Frm().Pos();
+
+ (pFrm->Frm().*fnRect->fnSetHeight)( nMaxHeight );
+ if( pFrm->GetPrev() )
+ (pFrm->Frm().*fnRect->fnSetPosY)(
+ (pFrm->GetPrev()->Frm().*fnRect->fnGetBottom)() -
+ ( bVert ? nMaxHeight + 1 : 0 ) );
+
+ SwBorderAttrAccess aAccess( SwFrm::GetCache(), pFrm );
+ const SwBorderAttrs &rAttrs = *aAccess.Get();
+ (pFrm->Prt().*fnRect->fnSetPosX)( rAttrs.CalcLeft( pFrm ) );
+
+ if( pPre )
+ {
+ SwTwips nUpper = pFrm->CalcUpperSpace( &rAttrs, pPre );
+ (pFrm->Prt().*fnRect->fnSetPosY)( nUpper );
+ }
+ (pFrm->Prt().*fnRect->fnSetHeight)(
+ Max( 0L , (pFrm->Frm().*fnRect->fnGetHeight)() -
+ (pFrm->Prt().*fnRect->fnGetTop)() - nLower ) );
+ (pFrm->Prt().*fnRect->fnSetWidth)(
+ (pFrm->Frm().*fnRect->fnGetWidth)() -
+ // OD 23.01.2003 #106895# - add 1st param to <SwBorderAttrs::CalcRight(..)>
+ ( rAttrs.CalcLeft( pFrm ) + rAttrs.CalcRight( pFrm ) ) );
+ pOldPara = pFrm->HasPara() ? pFrm->GetPara() : NULL;
+ pFrm->SetPara( new SwParaPortion(), sal_False );
+
+ OSL_ENSURE( ! pFrm->IsSwapped(), "A frame is swapped before _Format" );
+
+ if ( pFrm->IsVertical() )
+ pFrm->SwapWidthAndHeight();
+
+ SwTxtFormatInfo aInf( pFrm, sal_False, sal_True, sal_True );
+ SwTxtFormatter aLine( pFrm, &aInf );
+
+ pFrm->_Format( aLine, aInf );
+
+ if ( pFrm->IsVertical() )
+ pFrm->SwapWidthAndHeight();
+
+ OSL_ENSURE( ! pFrm->IsSwapped(), "A frame is swapped after _Format" );
+}
+
+SwTestFormat::~SwTestFormat()
+{
+ pFrm->Frm() = aOldFrm;
+ pFrm->Prt() = aOldPrt;
+ pFrm->SetPara( pOldPara );
+}
+
+sal_Bool SwTxtFrm::TestFormat( const SwFrm* pPrv, SwTwips &rMaxHeight, sal_Bool &bSplit )
+{
+ PROTOCOL_ENTER( this, PROT_TESTFORMAT, 0, 0 )
+
+ if( IsLocked() && GetUpper()->Prt().Width() <= 0 )
+ return sal_False;
+
+ SwTestFormat aSave( this, pPrv, rMaxHeight );
+
+ return SwTxtFrm::WouldFit( rMaxHeight, bSplit, sal_True );
+}
+
+
+/*************************************************************************
+ * SwTxtFrm::WouldFit()
+ *************************************************************************/
+
+/* SwTxtFrm::WouldFit()
+ * sal_True: wenn ich aufspalten kann.
+ * Es soll und braucht nicht neu formatiert werden.
+ * Wir gehen davon aus, dass bereits formatiert wurde und dass
+ * die Formatierungsdaten noch aktuell sind.
+ * Wir gehen davon aus, dass die Framebreiten des evtl. Masters und
+ * Follows gleich sind. Deswegen wird kein FindBreak() mit FindOrphans()
+ * gerufen.
+ * Die benoetigte Hoehe wird von nMaxHeight abgezogen!
+ */
+
+sal_Bool SwTxtFrm::WouldFit( SwTwips &rMaxHeight, sal_Bool &bSplit, sal_Bool bTst )
+{
+ OSL_ENSURE( ! IsVertical() || ! IsSwapped(),
+ "SwTxtFrm::WouldFit with swapped frame" );
+ SWRECTFN( this );
+
+ if( IsLocked() )
+ return sal_False;
+
+ //Kann gut sein, dass mir der IdleCollector mir die gecachten
+ //Informationen entzogen hat.
+ if( !IsEmpty() )
+ GetFormatted();
+
+ // OD 2004-05-24 #i27801# - correction: 'short cut' for empty paragraph
+ // can *not* be applied, if test format is in progress. The test format doesn't
+ // adjust the frame and the printing area - see method <SwTxtFrm::_Format(..)>,
+ // which is called in <SwTxtFrm::TestFormat(..)>
+ if ( IsEmpty() && !bTst )
+ {
+ bSplit = sal_False;
+ SwTwips nHeight = bVert ? Prt().SSize().Width() : Prt().SSize().Height();
+ if( rMaxHeight < nHeight )
+ return sal_False;
+ else
+ {
+ rMaxHeight -= nHeight;
+ return sal_True;
+ }
+ }
+
+ // In sehr unguenstigen Faellen kann GetPara immer noch 0 sein.
+ // Dann returnen wir sal_True, um auf der neuen Seite noch einmal
+ // anformatiert zu werden.
+ OSL_ENSURE( HasPara() || IsHiddenNow(), "WouldFit: GetFormatted() and then !HasPara()" );
+ if( !HasPara() || ( !(Frm().*fnRect->fnGetHeight)() && IsHiddenNow() ) )
+ return sal_True;
+
+ // Da das Orphan-Flag nur sehr fluechtig existiert, wird als zweite
+ // Bedingung ueberprueft, ob die Rahmengroesse durch CalcPreps
+ // auf riesengross gesetzt wird, um ein MoveFwd zu erzwingen.
+ if( IsWidow() || ( bVert ?
+ ( 0 == Frm().Left() ) :
+ ( LONG_MAX - 20000 < Frm().Bottom() ) ) )
+ {
+ SetWidow(sal_False);
+ if ( GetFollow() )
+ {
+ // Wenn wir hier durch eine Widow-Anforderung unseres Follows gelandet
+ // sind, wird ueberprueft, ob es ueberhaupt einen Follow mit einer
+ // echten Hoehe gibt, andernfalls (z.B. in neu angelegten SctFrms)
+ // ignorieren wir das IsWidow() und pruefen doch noch, ob wir
+ // genung Platz finden.
+ if( ( ( ! bVert && LONG_MAX - 20000 >= Frm().Bottom() ) ||
+ ( bVert && 0 < Frm().Left() ) ) &&
+ ( GetFollow()->IsVertical() ?
+ !GetFollow()->Frm().Width() :
+ !GetFollow()->Frm().Height() ) )
+ {
+ SwTxtFrm* pFoll = GetFollow()->GetFollow();
+ while( pFoll &&
+ ( pFoll->IsVertical() ?
+ !pFoll->Frm().Width() :
+ !pFoll->Frm().Height() ) )
+ pFoll = pFoll->GetFollow();
+ if( pFoll )
+ return sal_False;
+ }
+ else
+ return sal_False;
+ }
+ }
+
+ SWAP_IF_NOT_SWAPPED( this );
+
+ SwTxtSizeInfo aInf( this );
+ SwTxtMargin aLine( this, &aInf );
+
+ WidowsAndOrphans aFrmBreak( this, rMaxHeight, bSplit );
+
+ sal_Bool bRet = sal_True;
+
+ aLine.Bottom();
+ // Ist Aufspalten ueberhaupt notwendig?
+ if ( 0 != ( bSplit = !aFrmBreak.IsInside( aLine ) ) )
+ bRet = !aFrmBreak.IsKeepAlways() && aFrmBreak.WouldFit( aLine, rMaxHeight, bTst );
+ else
+ {
+ //Wir brauchen die Gesamthoehe inklusive der aktuellen Zeile
+ aLine.Top();
+ do
+ {
+ rMaxHeight -= aLine.GetLineHeight();
+ } while ( aLine.Next() );
+ }
+
+ UNDO_SWAP( this )
+
+ return bRet;
+}
+
+
+/*************************************************************************
+ * SwTxtFrm::GetParHeight()
+ *************************************************************************/
+
+KSHORT SwTxtFrm::GetParHeight() const
+{
+ OSL_ENSURE( ! IsVertical() || ! IsSwapped(),
+ "SwTxtFrm::GetParHeight with swapped frame" );
+
+ if( !HasPara() )
+ { // Fuer nichtleere Absaetze ist dies ein Sonderfall, da koennen wir
+ // bei UnderSized ruhig nur 1 Twip mehr anfordern.
+ KSHORT nRet = (KSHORT)Prt().SSize().Height();
+ if( IsUndersized() )
+ {
+ if( IsEmpty() )
+ nRet = (KSHORT)EmptyHeight();
+ else
+ ++nRet;
+ }
+ return nRet;
+ }
+
+ // FME, OD 08.01.2004 #i11859# - refactoring and improve code
+ const SwLineLayout* pLineLayout = GetPara();
+ KSHORT nHeight = pLineLayout->GetRealHeight();
+ if( GetOfst() && !IsFollow() ) // Ist dieser Absatz gescrollt? Dann ist unsere
+ nHeight *= 2; // bisherige Hoehe mind. eine Zeilenhoehe zu gering
+ // OD 2004-03-04 #115793#
+ while ( pLineLayout && pLineLayout->GetNext() )
+ {
+ pLineLayout = pLineLayout->GetNext();
+ nHeight = nHeight + pLineLayout->GetRealHeight();
+ }
+
+ return nHeight;
+}
+
+
+/*************************************************************************
+ * SwTxtFrm::GetFormatted()
+ *************************************************************************/
+
+// returnt this _immer_ im formatierten Zustand!
+SwTxtFrm* SwTxtFrm::GetFormatted( bool bForceQuickFormat )
+{
+ SWAP_IF_SWAPPED( this )
+
+ //Kann gut sein, dass mir der IdleCollector mir die gecachten
+ //Informationen entzogen hat. Calc() ruft unser Format.
+ //Nicht bei leeren Absaetzen!
+ if( !HasPara() && !(IsValid() && IsEmpty()) )
+ {
+ // Calc() muss gerufen werden, weil unsere Frameposition
+ // nicht stimmen muss.
+ const sal_Bool bFormat = GetValidSizeFlag();
+ Calc();
+ // Es kann durchaus sein, dass Calc() das Format()
+ // nicht anstiess (weil wir einst vom Idle-Zerstoerer
+ // aufgefordert wurden unsere Formatinformationen wegzuschmeissen).
+ // 6995: Optimierung mit FormatQuick()
+ if( bFormat && !FormatQuick( bForceQuickFormat ) )
+ Format();
+ }
+
+ UNDO_SWAP( this )
+
+ return this;
+}
+
+/*************************************************************************
+ * SwTxtFrm::CalcFitToContent()
+ *************************************************************************/
+
+SwTwips SwTxtFrm::CalcFitToContent()
+{
+ // --> FME 2004-07-16 #i31490#
+ // If we are currently locked, we better return with a
+ // fairly reasonable value:
+ if ( IsLocked() )
+ return Prt().Width();
+ // <--
+
+ SwParaPortion* pOldPara = GetPara();
+ SwParaPortion *pDummy = new SwParaPortion();
+ SetPara( pDummy, false );
+ const SwPageFrm* pPage = FindPageFrm();
+
+ const Point aOldFrmPos = Frm().Pos();
+ const SwTwips nOldFrmWidth = Frm().Width();
+ const SwTwips nOldPrtWidth = Prt().Width();
+ const SwTwips nPageWidth = GetUpper()->IsVertical() ?
+ pPage->Prt().Height() :
+ pPage->Prt().Width();
+
+ Frm().Width( nPageWidth );
+ Prt().Width( nPageWidth );
+
+ // --> FME 2004-07-19 #i25422# objects anchored as character in RTL
+ if ( IsRightToLeft() )
+ Frm().Pos().X() += nOldFrmWidth - nPageWidth;
+
+ // --> FME 2004-07-16 #i31490#
+ SwTxtFrmLocker aLock( this );
+ // <--
+
+ SwTxtFormatInfo aInf( this, sal_False, sal_True, sal_True );
+ aInf.SetIgnoreFly( sal_True );
+ SwTxtFormatter aLine( this, &aInf );
+ SwHookOut aHook( aInf );
+
+ // --> OD 2005-09-06 #i54031# - assure mininum of MINLAY twips.
+ const SwTwips nMax = Max( (SwTwips)MINLAY,
+ aLine._CalcFitToContent() + 1 );
+ // <--
+
+ Frm().Width( nOldFrmWidth );
+ Prt().Width( nOldPrtWidth );
+
+ // --> FME 2004-07-19 #i25422# objects anchored as character in RTL
+ if ( IsRightToLeft() )
+ Frm().Pos() = aOldFrmPos;
+
+
+ SetPara( pOldPara );
+
+ return nMax;
+}
+
+/** simulate format for a list item paragraph, whose list level attributes
+ are in LABEL_ALIGNMENT mode, in order to determine additional first
+ line offset for the real text formatting due to the value of label
+ adjustment attribute of the list level.
+
+ @author OD
+*/
+void SwTxtFrm::CalcAdditionalFirstLineOffset()
+{
+ if ( IsLocked() )
+ return;
+
+ // reset additional first line offset
+ mnAdditionalFirstLineOffset = 0;
+
+ const SwTxtNode* pTxtNode( GetTxtNode() );
+ if ( pTxtNode && pTxtNode->IsNumbered() && pTxtNode->IsCountedInList() &&
+ pTxtNode->GetNumRule() )
+ {
+ const SwNumFmt& rNumFmt =
+ pTxtNode->GetNumRule()->Get( static_cast<sal_uInt16>(pTxtNode->GetActualListLevel()) );
+ if ( rNumFmt.GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_ALIGNMENT )
+ {
+ // keep current paragraph portion and apply dummy paragraph portion
+ SwParaPortion* pOldPara = GetPara();
+ SwParaPortion *pDummy = new SwParaPortion();
+ SetPara( pDummy, false );
+
+ // lock paragraph
+ SwTxtFrmLocker aLock( this );
+
+ // simulate text formatting
+ SwTxtFormatInfo aInf( this, sal_False, sal_True, sal_True );
+ aInf.SetIgnoreFly( sal_True );
+ SwTxtFormatter aLine( this, &aInf );
+ SwHookOut aHook( aInf );
+ aLine._CalcFitToContent();
+
+ // determine additional first line offset
+ const SwLinePortion* pFirstPortion = aLine.GetCurr()->GetFirstPortion();
+ if ( pFirstPortion->InNumberGrp() && !pFirstPortion->IsFtnNumPortion() )
+ {
+ SwTwips nNumberPortionWidth( pFirstPortion->Width() );
+
+ const SwLinePortion* pPortion = pFirstPortion->GetPortion();
+ while ( pPortion &&
+ pPortion->InNumberGrp() && !pPortion->IsFtnNumPortion())
+ {
+ nNumberPortionWidth += pPortion->Width();
+ pPortion = pPortion->GetPortion();
+ }
+
+ if ( ( IsRightToLeft() &&
+ rNumFmt.GetNumAdjust() == SVX_ADJUST_LEFT ) ||
+ ( !IsRightToLeft() &&
+ rNumFmt.GetNumAdjust() == SVX_ADJUST_RIGHT ) )
+ {
+ mnAdditionalFirstLineOffset = -nNumberPortionWidth;
+ }
+ else if ( rNumFmt.GetNumAdjust() == SVX_ADJUST_CENTER )
+ {
+ mnAdditionalFirstLineOffset = -(nNumberPortionWidth/2);
+ }
+ }
+
+ // restore paragraph portion
+ SetPara( pOldPara );
+ }
+ }
+}
+
+/** determine height of last line for the calculation of the proportional line
+ spacing
+
+ OD 08.01.2004 #i11859#
+ OD 2004-03-17 #i11860# - method <GetHeightOfLastLineForPropLineSpacing()>
+ replace by method <_CalcHeightOfLastLine()>. Height of last line will be
+ stored in new member <mnHeightOfLastLine> and can be accessed via method
+ <GetHeightOfLastLine()>
+ OD 2005-05-20 #i47162# - introduce new optional parameter <_bUseFont>
+ in order to force the usage of the former algorithm to determine the
+ height of the last line, which uses the font.
+
+ @author OD
+*/
+void SwTxtFrm::_CalcHeightOfLastLine( const bool _bUseFont )
+{
+ // --> OD 2006-11-13 #i71281#
+ // invalidate printing area, if height of last line changes
+ const SwTwips mnOldHeightOfLastLine( mnHeightOfLastLine );
+ // <--
+ // determine output device
+ ViewShell* pVsh = getRootFrm()->GetCurrShell();
+ OSL_ENSURE( pVsh, "<SwTxtFrm::_GetHeightOfLastLineForPropLineSpacing()> - no ViewShell" );
+ // --> OD 2007-07-02 #i78921# - make code robust, according to provided patch
+ // There could be no <ViewShell> instance in the case of loading a binary
+ // StarOffice file format containing an embedded Writer document.
+ if ( !pVsh )
+ {
+ return;
+ }
+ OutputDevice* pOut = pVsh->GetOut();
+ const IDocumentSettingAccess* pIDSA = GetTxtNode()->getIDocumentSettingAccess();
+ if ( !pVsh->GetViewOptions()->getBrowseMode() ||
+ pVsh->GetViewOptions()->IsPrtFormat() )
+ {
+ pOut = GetTxtNode()->getIDocumentDeviceAccess()->getReferenceDevice( true );
+ }
+ OSL_ENSURE( pOut, "<SwTxtFrm::_GetHeightOfLastLineForPropLineSpacing()> - no OutputDevice" );
+ // --> OD 2007-07-02 #i78921# - make code robust, according to provided patch
+ if ( !pOut )
+ {
+ return;
+ }
+ // <--
+
+ // determine height of last line
+
+ if ( _bUseFont || pIDSA->get(IDocumentSettingAccess::OLD_LINE_SPACING ) )
+ {
+ // former determination of last line height for proprotional line
+ // spacing - take height of font set at the paragraph
+ SwFont aFont( GetAttrSet(), pIDSA );
+
+ // Wir muessen dafuer sorgen, dass am OutputDevice der Font
+ // korrekt restauriert wird, sonst droht ein Last!=Owner.
+ if ( pLastFont )
+ {
+ SwFntObj *pOldFont = pLastFont;
+ pLastFont = NULL;
+ aFont.SetFntChg( sal_True );
+ aFont.ChgPhysFnt( pVsh, *pOut );
+ mnHeightOfLastLine = aFont.GetHeight( pVsh, *pOut );
+ pLastFont->Unlock();
+ pLastFont = pOldFont;
+ pLastFont->SetDevFont( pVsh, *pOut );
+ }
+ else
+ {
+ Font aOldFont = pOut->GetFont();
+ aFont.SetFntChg( sal_True );
+ aFont.ChgPhysFnt( pVsh, *pOut );
+ mnHeightOfLastLine = aFont.GetHeight( pVsh, *pOut );
+ pLastFont->Unlock();
+ pLastFont = NULL;
+ pOut->SetFont( aOldFont );
+ }
+ }
+ else
+ {
+ // new determination of last line height - take actually height of last line
+ // --> OD 2008-05-06 #i89000#
+ // assure same results, if paragraph is undersized
+ if ( IsUndersized() )
+ {
+ mnHeightOfLastLine = 0;
+ }
+ else
+ {
+ bool bCalcHeightOfLastLine = true;
+ if ( !HasPara() )
+ {
+ if ( IsEmpty() )
+ {
+ mnHeightOfLastLine = EmptyHeight();
+ bCalcHeightOfLastLine = false;
+ }
+ }
+
+ if ( bCalcHeightOfLastLine )
+ {
+ OSL_ENSURE( HasPara(),
+ "<SwTxtFrm::_CalcHeightOfLastLine()> - missing paragraph portions." );
+ const SwLineLayout* pLineLayout = GetPara();
+ while ( pLineLayout && pLineLayout->GetNext() )
+ {
+ // iteration to last line
+ pLineLayout = pLineLayout->GetNext();
+ }
+ if ( pLineLayout )
+ {
+ SwTwips nAscent, nDescent, nDummy1, nDummy2;
+ // --> OD 2005-05-20 #i47162# - suppress consideration of
+ // fly content portions and the line portion.
+ pLineLayout->MaxAscentDescent( nAscent, nDescent,
+ nDummy1, nDummy2,
+ 0, true );
+ // <--
+ // --> OD 2006-11-22 #i71281#
+ // Suppress wrong invalidation of printing area, if method is
+ // called recursive.
+ // Thus, member <mnHeightOfLastLine> is only set directly, if
+ // no recursive call is needed.
+ // mnHeightOfLastLine = nAscent + nDescent;
+ const SwTwips nNewHeightOfLastLine = nAscent + nDescent;
+ // --> OD 2005-05-20 #i47162# - if last line only contains
+ // fly content portions, <mnHeightOfLastLine> is zero.
+ // In this case determine height of last line by the font
+ if ( nNewHeightOfLastLine == 0 )
+ {
+ _CalcHeightOfLastLine( true );
+ }
+ else
+ {
+ mnHeightOfLastLine = nNewHeightOfLastLine;
+ }
+ // <--
+ // <--
+ }
+ }
+ }
+ // <--
+ }
+ // --> OD 2006-11-13 #i71281#
+ // invalidate printing area, if height of last line changes
+ if ( mnHeightOfLastLine != mnOldHeightOfLastLine )
+ {
+ InvalidatePrt();
+ }
+ // <--
+}
+
+/*************************************************************************
+ * SwTxtFrm::GetLineSpace()
+ *************************************************************************/
+// OD 07.01.2004 #i11859# - change return data type
+// add default parameter <_bNoPropLineSpacing> to control, if the
+// value of a proportional line spacing is returned or not
+// OD 07.01.2004 - trying to describe purpose of method:
+// Method returns the value of the inter line spacing for a text frame.
+// Such a value exists for proportional line spacings ("1,5 Lines",
+// "Double", "Proportional" and for leading line spacing ("Leading").
+// By parameter <_bNoPropLineSpace> (default value false) it can be
+// controlled, if the value of a proportional line spacing is returned.
+long SwTxtFrm::GetLineSpace( const bool _bNoPropLineSpace ) const
+{
+ long nRet = 0;
+
+ const SwAttrSet* pSet = GetAttrSet();
+ const SvxLineSpacingItem &rSpace = pSet->GetLineSpacing();
+
+ switch( rSpace.GetInterLineSpaceRule() )
+ {
+ case SVX_INTER_LINE_SPACE_PROP:
+ {
+ // OD 07.01.2004 #i11859#
+ if ( _bNoPropLineSpace )
+ {
+ break;
+ }
+
+ // OD 2004-03-17 #i11860# - use method <GetHeightOfLastLine()>
+ nRet = GetHeightOfLastLine();
+
+ long nTmp = nRet;
+ nTmp *= rSpace.GetPropLineSpace();
+ nTmp /= 100;
+ nTmp -= nRet;
+ if ( nTmp > 0 )
+ nRet = nTmp;
+ else
+ nRet = 0;
+ }
+ break;
+ case SVX_INTER_LINE_SPACE_FIX:
+ {
+ if ( rSpace.GetInterLineSpace() > 0 )
+ nRet = rSpace.GetInterLineSpace();
+ }
+ break;
+ default:
+ break;
+ }
+ return nRet;
+}
+
+/*************************************************************************
+ * SwTxtFrm::FirstLineHeight()
+ *************************************************************************/
+
+KSHORT SwTxtFrm::FirstLineHeight() const
+{
+ if ( !HasPara() )
+ {
+ if( IsEmpty() && IsValid() )
+ return IsVertical() ? (KSHORT)Prt().Width() : (KSHORT)Prt().Height();
+ return KSHRT_MAX;
+ }
+ const SwParaPortion *pPara = GetPara();
+ if ( !pPara )
+ return KSHRT_MAX;
+
+ return pPara->Height();
+}
+
+MSHORT SwTxtFrm::GetLineCount( xub_StrLen nPos )
+{
+ MSHORT nRet = 0;
+ SwTxtFrm *pFrm = this;
+ do
+ {
+ pFrm->GetFormatted();
+ if( !pFrm->HasPara() )
+ break;
+ SwTxtSizeInfo aInf( pFrm );
+ SwTxtMargin aLine( pFrm, &aInf );
+ if( STRING_LEN == nPos )
+ aLine.Bottom();
+ else
+ aLine.CharToLine( nPos );
+ nRet = nRet + aLine.GetLineNr();
+ pFrm = pFrm->GetFollow();
+ } while ( pFrm && pFrm->GetOfst() <= nPos );
+ return nRet;
+}
+
+void SwTxtFrm::ChgThisLines()
+{
+ //not necassary to format here (GerFormatted etc.), because we have to come from there!
+
+ sal_uLong nNew = 0;
+ const SwLineNumberInfo &rInf = GetNode()->getIDocumentLineNumberAccess()->GetLineNumberInfo();
+ if ( GetTxt().Len() && HasPara() )
+ {
+ SwTxtSizeInfo aInf( this );
+ SwTxtMargin aLine( this, &aInf );
+ if ( rInf.IsCountBlankLines() )
+ {
+ aLine.Bottom();
+ nNew = (sal_uLong)aLine.GetLineNr();
+ }
+ else
+ {
+ do
+ {
+ if( aLine.GetCurr()->HasCntnt() )
+ ++nNew;
+ } while ( aLine.NextLine() );
+ }
+ }
+ else if ( rInf.IsCountBlankLines() )
+ nNew = 1;
+
+ if ( nNew != nThisLines )
+ {
+ if ( !IsInTab() && GetAttrSet()->GetLineNumber().IsCount() )
+ {
+ nAllLines -= nThisLines;
+ nThisLines = nNew;
+ nAllLines += nThisLines;
+ SwFrm *pNxt = GetNextCntntFrm();
+ while( pNxt && pNxt->IsInTab() )
+ {
+ if( 0 != (pNxt = pNxt->FindTabFrm()) )
+ pNxt = pNxt->FindNextCnt();
+ }
+ if( pNxt )
+ pNxt->InvalidateLineNum();
+
+ //Extend repaint to the bottom.
+ if ( HasPara() )
+ {
+ SwRepaint *pRepaint = GetPara()->GetRepaint();
+ pRepaint->Bottom( Max( pRepaint->Bottom(),
+ Frm().Top()+Prt().Bottom()));
+ }
+ }
+ else //Paragraphs which are not counted should not manipulate the AllLines.
+ nThisLines = nNew;
+ }
+
+ //mba: invalidating is not necessary; if mongolian script has a problem, it should be fixed at the ritgh place
+ //with invalidating we probably get too much flickering
+ //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin
+ //Ugly. How can we hack if better?
+ //InvalidatePage();
+}
+
+
+void SwTxtFrm::RecalcAllLines()
+{
+ ValidateLineNum();
+
+ const SwAttrSet *pAttrSet = GetAttrSet();
+
+ if ( !IsInTab() )
+ {
+ const sal_uLong nOld = GetAllLines();
+ const SwFmtLineNumber &rLineNum = pAttrSet->GetLineNumber();
+ sal_uLong nNewNum;
+ const bool bRestart = GetTxtNode()->getIDocumentLineNumberAccess()->GetLineNumberInfo().IsRestartEachPage();
+
+ if ( !IsFollow() && rLineNum.GetStartValue() && rLineNum.IsCount() )
+ nNewNum = rLineNum.GetStartValue() - 1;
+ //If it is a follow or not has not be considered if it is a restart at each page; the
+ //restart should also take affekt at follows.
+ else if ( bRestart && FindPageFrm()->FindFirstBodyCntnt() == this )
+ {
+ nNewNum = 0;
+ }
+ else
+ {
+ SwCntntFrm *pPrv = GetPrevCntntFrm();
+ while ( pPrv &&
+ (pPrv->IsInTab() || pPrv->IsInDocBody() != IsInDocBody()) )
+ pPrv = pPrv->GetPrevCntntFrm();
+
+ // --> FME 2007-06-22 #i78254# Restart line numbering at page change:
+ // First body content may be in table!
+ if ( bRestart && pPrv && pPrv->FindPageFrm() != FindPageFrm() )
+ pPrv = 0;
+ // <--
+
+ nNewNum = pPrv ? ((SwTxtFrm*)pPrv)->GetAllLines() : 0;
+ }
+ if ( rLineNum.IsCount() )
+ nNewNum += GetThisLines();
+
+ if ( nOld != nNewNum )
+ {
+ nAllLines = nNewNum;
+ SwCntntFrm *pNxt = GetNextCntntFrm();
+ while ( pNxt &&
+ (pNxt->IsInTab() || pNxt->IsInDocBody() != IsInDocBody()) )
+ pNxt = pNxt->GetNextCntntFrm();
+ if ( pNxt )
+ {
+ if ( pNxt->GetUpper() != GetUpper() )
+ pNxt->InvalidateLineNum();
+ else
+ pNxt->_InvalidateLineNum();
+ }
+ }
+ }
+}
+
+void SwTxtFrm::VisitPortions( SwPortionHandler& rPH ) const
+{
+ const SwParaPortion* pPara = GetPara();
+
+ if( pPara )
+ {
+ if ( IsFollow() )
+ rPH.Skip( GetOfst() );
+
+ const SwLineLayout* pLine = pPara;
+ while ( pLine )
+ {
+ const SwLinePortion* pPor = pLine->GetFirstPortion();
+ while ( pPor )
+ {
+ pPor->HandlePortion( rPH );
+ pPor = pPor->GetPortion();
+ }
+
+ rPH.LineBreak();
+ pLine = pLine->GetNext();
+ }
+ }
+
+ rPH.Finish();
+}
+
+
+/*************************************************************************
+ * SwTxtFrm::GetScriptInfo()
+ *************************************************************************/
+
+const SwScriptInfo* SwTxtFrm::GetScriptInfo() const
+{
+ const SwParaPortion* pPara = GetPara();
+ return pPara ? &pPara->GetScriptInfo() : 0;
+}
+
+/*************************************************************************
+ * lcl_CalcFlyBasePos()
+ * Helper function for SwTxtFrm::CalcBasePosForFly()
+ *************************************************************************/
+
+SwTwips lcl_CalcFlyBasePos( const SwTxtFrm& rFrm, SwRect aFlyRect,
+ SwTxtFly& rTxtFly )
+{
+ SWRECTFN( (&rFrm) )
+ SwTwips nRet = rFrm.IsRightToLeft() ?
+ (rFrm.Frm().*fnRect->fnGetRight)() :
+ (rFrm.Frm().*fnRect->fnGetLeft)();
+
+ do
+ {
+ SwRect aRect = rTxtFly.GetFrm( aFlyRect );
+ if ( 0 != (aRect.*fnRect->fnGetWidth)() )
+ {
+ if ( rFrm.IsRightToLeft() )
+ {
+ if ( (aRect.*fnRect->fnGetRight)() -
+ (aFlyRect.*fnRect->fnGetRight)() >= 0 )
+ {
+ (aFlyRect.*fnRect->fnSetRight)(
+ (aRect.*fnRect->fnGetLeft)() );
+ nRet = (aRect.*fnRect->fnGetLeft)();
+ }
+ else
+ break;
+ }
+ else
+ {
+ if ( (aFlyRect.*fnRect->fnGetLeft)() -
+ (aRect.*fnRect->fnGetLeft)() >= 0 )
+ {
+ (aFlyRect.*fnRect->fnSetLeft)(
+ (aRect.*fnRect->fnGetRight)() + 1 );
+ nRet = (aRect.*fnRect->fnGetRight)();
+ }
+ else
+ break;
+ }
+ }
+ else
+ break;
+ }
+ while ( (aFlyRect.*fnRect->fnGetWidth)() > 0 );
+
+ return nRet;
+}
+
+/*************************************************************************
+ * SwTxtFrm::CalcBasePosForFly()
+ *************************************************************************/
+
+void SwTxtFrm::CalcBaseOfstForFly()
+{
+ OSL_ENSURE( !IsVertical() || !IsSwapped(),
+ "SwTxtFrm::CalcBasePosForFly with swapped frame!" );
+
+ const SwNode* pNode = GetTxtNode();
+ if ( !pNode->getIDocumentSettingAccess()->get(IDocumentSettingAccess::ADD_FLY_OFFSETS) )
+ return;
+
+ SWRECTFN( this )
+
+ SwRect aFlyRect( Frm().Pos() + Prt().Pos(), Prt().SSize() );
+
+ // Get first 'real' line and adjust position and height of line rectangle
+ // OD 08.09.2003 #110978#, #108749#, #110354# - correct behaviour,
+ // if no 'real' line exists (empty paragraph with and without a dummy portion)
+ {
+ SwTwips nTop = (aFlyRect.*fnRect->fnGetTop)();
+ const SwLineLayout* pLay = GetPara();
+ SwTwips nLineHeight = 200;
+ while( pLay && pLay->IsDummy() && pLay->GetNext() )
+ {
+ nTop += pLay->Height();
+ pLay = pLay->GetNext();
+ }
+ if ( pLay )
+ {
+ nLineHeight = pLay->Height();
+ }
+ (aFlyRect.*fnRect->fnSetTopAndHeight)( nTop, nLineHeight );
+ }
+
+ SwTxtFly aTxtFly( this );
+ aTxtFly.SetIgnoreCurrentFrame( sal_True );
+ aTxtFly.SetIgnoreContour( sal_True );
+ // --> OD 2004-12-17 #118809# - ignore objects in page header|footer for
+ // text frames not in page header|footer
+ aTxtFly.SetIgnoreObjsInHeaderFooter( sal_True );
+ // <--
+ SwTwips nRet1 = lcl_CalcFlyBasePos( *this, aFlyRect, aTxtFly );
+ aTxtFly.SetIgnoreCurrentFrame( sal_False );
+ SwTwips nRet2 = lcl_CalcFlyBasePos( *this, aFlyRect, aTxtFly );
+
+ // make values relative to frame start position
+ SwTwips nLeft = IsRightToLeft() ?
+ (Frm().*fnRect->fnGetRight)() :
+ (Frm().*fnRect->fnGetLeft)();
+
+ mnFlyAnchorOfst = nRet1 - nLeft;
+ mnFlyAnchorOfstNoWrap = nRet2 - nLeft;
+}
+
+/* repaint all text frames of the given text node */
+void SwTxtFrm::repaintTextFrames( const SwTxtNode& rNode )
+{
+ SwIterator<SwTxtFrm,SwTxtNode> aIter( rNode );
+ for( const SwTxtFrm *pFrm = aIter.First(); pFrm; pFrm = aIter.Next() )
+ {
+ SwRect aRec( pFrm->PaintArea() );
+ const SwRootFrm *pRootFrm = pFrm->getRootFrm();
+ ViewShell *pCurShell = pRootFrm ? pRootFrm->GetCurrShell() : NULL;
+ if( pCurShell )
+ pCurShell->InvalidateWindows( aRec );
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ \ No newline at end of file
diff --git a/sw/source/core/text/txtftn.cxx b/sw/source/core/text/txtftn.cxx
new file mode 100644
index 000000000000..8ad815c94612
--- /dev/null
+++ b/sw/source/core/text/txtftn.cxx
@@ -0,0 +1,1697 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+#include "viewsh.hxx"
+#include "doc.hxx"
+#include "pagefrm.hxx"
+#include "rootfrm.hxx"
+#include "ndtxt.hxx"
+#include "txtatr.hxx"
+#include <SwPortionHandler.hxx>
+#include <txtftn.hxx>
+#include <flyfrm.hxx>
+#include <fmtftn.hxx>
+#include <ftninfo.hxx>
+#include <charfmt.hxx>
+#include <dflyobj.hxx>
+#include <rowfrm.hxx>
+#include <editeng/brshitem.hxx>
+#include <editeng/charrotateitem.hxx>
+#include <breakit.hxx>
+#include <com/sun/star/i18n/ScriptType.hdl>
+#include <tabfrm.hxx>
+// OD 2004-05-24 #i28701#
+#include <sortedobjs.hxx>
+
+#include "swfont.hxx" // new SwFont
+#include "porftn.hxx"
+#include "porfly.hxx"
+#include "porlay.hxx"
+#include "txtfrm.hxx"
+#include "itrform2.hxx"
+#include "ftnfrm.hxx" // FindQuoVadisFrm(),
+#include "pagedesc.hxx"
+#include "redlnitr.hxx" // SwRedlnItr
+#include "sectfrm.hxx" // SwSectionFrm
+#include "layouter.hxx" // Endnote-Collection
+#include "frmtool.hxx"
+#include "ndindex.hxx"
+
+using namespace ::com::sun::star;
+
+/*************************************************************************
+ * _IsFtnNumFrm()
+ *************************************************************************/
+
+sal_Bool SwTxtFrm::_IsFtnNumFrm() const
+{
+ const SwFtnFrm* pFtn = FindFtnFrm()->GetMaster();
+ while( pFtn && !pFtn->ContainsCntnt() )
+ pFtn = pFtn->GetMaster();
+ return !pFtn;
+}
+
+/*************************************************************************
+ * FindFtn()
+ *************************************************************************/
+
+// Sucht innerhalb einer Master-Follow-Kette den richtigen TxtFrm zum SwTxtFtn
+
+SwTxtFrm *SwTxtFrm::FindFtnRef( const SwTxtFtn *pFtn )
+{
+ SwTxtFrm *pFrm = this;
+ const sal_Bool bFwd = *pFtn->GetStart() >= GetOfst();
+ while( pFrm )
+ {
+ if( SwFtnBossFrm::FindFtn( pFrm, pFtn ) )
+ return pFrm;
+ pFrm = bFwd ? pFrm->GetFollow() :
+ pFrm->IsFollow() ? pFrm->FindMaster() : 0;
+ }
+ return pFrm;
+}
+
+/*************************************************************************
+ * CalcFtnFlag()
+ *************************************************************************/
+
+#if OSL_DEBUG_LEVEL > 1
+void SwTxtFrm::CalcFtnFlag( xub_StrLen nStop )//For testing the SplitFrm
+#else
+void SwTxtFrm::CalcFtnFlag()
+#endif
+{
+ bFtn = sal_False;
+
+ const SwpHints *pHints = GetTxtNode()->GetpSwpHints();
+ if( !pHints )
+ return;
+
+ const sal_uInt16 nSize = pHints->Count();
+
+#if OSL_DEBUG_LEVEL > 1
+ const xub_StrLen nEnd = nStop != STRING_LEN ? nStop
+ : GetFollow() ? GetFollow()->GetOfst() : STRING_LEN;
+#else
+ const xub_StrLen nEnd = GetFollow() ? GetFollow()->GetOfst() : STRING_LEN;
+#endif
+
+ for ( sal_uInt16 i = 0; i < nSize; ++i )
+ {
+ const SwTxtAttr *pHt = (*pHints)[i];
+ if ( pHt->Which() == RES_TXTATR_FTN )
+ {
+ const xub_StrLen nIdx = *pHt->GetStart();
+ if ( nEnd < nIdx )
+ break;
+ if( GetOfst() <= nIdx )
+ {
+ bFtn = sal_True;
+ break;
+ }
+ }
+ }
+}
+
+/*************************************************************************
+ * CalcPrepFtnAdjust()
+ *************************************************************************/
+
+sal_Bool SwTxtFrm::CalcPrepFtnAdjust()
+{
+ OSL_ENSURE( HasFtn(), "Wer ruft mich da?" );
+ SwFtnBossFrm *pBoss = FindFtnBossFrm( sal_True );
+ const SwFtnFrm *pFtn = pBoss->FindFirstFtn( this );
+ if( pFtn && FTNPOS_CHAPTER != GetNode()->GetDoc()->GetFtnInfo().ePos &&
+ ( !pBoss->GetUpper()->IsSctFrm() ||
+ !((SwSectionFrm*)pBoss->GetUpper())->IsFtnAtEnd() ) )
+ {
+ const SwFtnContFrm *pCont = pBoss->FindFtnCont();
+ sal_Bool bReArrange = sal_True;
+
+ SWRECTFN( this )
+ if ( pCont && (*fnRect->fnYDiff)( (pCont->Frm().*fnRect->fnGetTop)(),
+ (Frm().*fnRect->fnGetBottom)() ) > 0 )
+ {
+ pBoss->RearrangeFtns( (Frm().*fnRect->fnGetBottom)(), sal_False,
+ pFtn->GetAttr() );
+ ValidateBodyFrm();
+ ValidateFrm();
+ pFtn = pBoss->FindFirstFtn( this );
+ }
+ else
+ bReArrange = sal_False;
+ if( !pCont || !pFtn || bReArrange != (pFtn->FindFtnBossFrm() == pBoss) )
+ {
+ SwTxtFormatInfo aInf( this );
+ SwTxtFormatter aLine( this, &aInf );
+ aLine.TruncLines();
+ SetPara( 0 ); //Wird ggf. geloescht!
+ ResetPreps();
+ return sal_False;
+ }
+ }
+ return sal_True;
+}
+
+
+/*************************************************************************
+ * lcl_GetFtnLower()
+ *
+ * Local helper function. Checks if nLower should be taken as the boundary
+ * for the footnote.
+ *************************************************************************/
+
+SwTwips lcl_GetFtnLower( const SwTxtFrm* pFrm, SwTwips nLower )
+{
+ // nLower is an absolute value. It denotes the bottom of the line
+ // containing the footnote.
+ SWRECTFN( pFrm )
+
+ OSL_ENSURE( !pFrm->IsVertical() || !pFrm->IsSwapped(),
+ "lcl_GetFtnLower with swapped frame" );
+
+ SwTwips nAdd;
+ SwTwips nRet = nLower;
+
+ //
+ // Check if text is inside a table.
+ //
+ if ( pFrm->IsInTab() )
+ {
+ //
+ // If pFrm is inside a table, we have to check if
+ // a) The table is not allowed to split or
+ // b) The table row is not allowed to split
+ //
+ // Inside a table, there are no footnotes,
+ // see SwFrm::FindFtnBossFrm. So we don't have to check
+ // the case that pFrm is inside a (footnote collecting) section
+ // within the table.
+ //
+ const SwFrm* pRow = pFrm;
+ while( !pRow->IsRowFrm() || !pRow->GetUpper()->IsTabFrm() )
+ pRow = pRow->GetUpper();
+ const SwTabFrm* pTabFrm = (SwTabFrm*)pRow->GetUpper();
+
+ OSL_ENSURE( pTabFrm && pRow &&
+ pRow->GetUpper()->IsTabFrm(), "Upper of row should be tab" );
+
+ const sal_Bool bDontSplit = !pTabFrm->IsFollow() &&
+ !pTabFrm->IsLayoutSplitAllowed();
+
+ SwTwips nMin = 0;
+ if ( bDontSplit )
+ nMin = (pTabFrm->Frm().*fnRect->fnGetBottom)();
+ else if ( !((SwRowFrm*)pRow)->IsRowSplitAllowed() )
+ nMin = (pRow->Frm().*fnRect->fnGetBottom)();
+
+ if ( nMin && (*fnRect->fnYDiff)( nMin, nLower ) > 0 )
+ nRet = nMin;
+
+ nAdd = (pRow->GetUpper()->*fnRect->fnGetBottomMargin)();
+ }
+ else
+ nAdd = (pFrm->*fnRect->fnGetBottomMargin)();
+
+ if( nAdd > 0 )
+ {
+ if ( bVert )
+ nRet -= nAdd;
+ else
+ nRet += nAdd;
+ }
+
+ // #i10770#: If there are fly frames anchored at previous paragraphs,
+ // the deadline should consider their lower borders.
+ const SwFrm* pStartFrm = pFrm->GetUpper()->GetLower();
+ OSL_ENSURE( pStartFrm, "Upper has no lower" );
+ SwTwips nFlyLower = bVert ? LONG_MAX : 0;
+ while ( pStartFrm != pFrm )
+ {
+ OSL_ENSURE( pStartFrm, "Frame chain is broken" );
+ if ( pStartFrm->GetDrawObjs() )
+ {
+ const SwSortedObjs &rObjs = *pStartFrm->GetDrawObjs();
+ for ( sal_uInt16 i = 0; i < rObjs.Count(); ++i )
+ {
+ SwAnchoredObject* pAnchoredObj = rObjs[i];
+ SwRect aRect( pAnchoredObj->GetObjRect() );
+
+ if ( !pAnchoredObj->ISA(SwFlyFrm) ||
+ static_cast<SwFlyFrm*>(pAnchoredObj)->IsValid() )
+ {
+ const SwTwips nBottom = (aRect.*fnRect->fnGetBottom)();
+ if ( (*fnRect->fnYDiff)( nBottom, nFlyLower ) > 0 )
+ nFlyLower = nBottom;
+ }
+ }
+ }
+
+ pStartFrm = pStartFrm->GetNext();
+ }
+
+ if ( bVert )
+ nRet = Min( nRet, nFlyLower );
+ else
+ nRet = Max( nRet, nFlyLower );
+
+ return nRet;
+}
+
+
+/*************************************************************************
+ * SwTxtFrm::GetFtnLine()
+ *************************************************************************/
+
+SwTwips SwTxtFrm::GetFtnLine( const SwTxtFtn *pFtn ) const
+{
+ OSL_ENSURE( ! IsVertical() || ! IsSwapped(),
+ "SwTxtFrm::GetFtnLine with swapped frame" );
+
+ SwTxtFrm *pThis = (SwTxtFrm*)this;
+
+ if( !HasPara() )
+ {
+ // #109071# GetFormatted() does not work here, bacause most probably
+ // the frame is currently locked. We return the previous value.
+ return pThis->mnFtnLine > 0 ?
+ pThis->mnFtnLine :
+ IsVertical() ? Frm().Left() : Frm().Bottom();
+ }
+
+ SWAP_IF_NOT_SWAPPED( this )
+
+ SwTxtInfo aInf( pThis );
+ SwTxtIter aLine( pThis, &aInf );
+ const xub_StrLen nPos = *pFtn->GetStart();
+ aLine.CharToLine( nPos );
+
+ SwTwips nRet = aLine.Y() + SwTwips(aLine.GetLineHeight());
+ if( IsVertical() )
+ nRet = SwitchHorizontalToVertical( nRet );
+
+ UNDO_SWAP( this )
+
+ nRet = lcl_GetFtnLower( pThis, nRet );
+
+ pThis->mnFtnLine = nRet;
+ return nRet;
+}
+
+/*************************************************************************
+ * SwTxtFrm::GetFtnRstHeight()
+ *************************************************************************/
+
+// Ermittelt die max. erreichbare Hoehe des TxtFrm im Ftn-Bereich.
+// Sie wird eingeschraenkt durch den unteren Rand der Zeile mit
+// der Ftn-Referenz.
+
+SwTwips SwTxtFrm::_GetFtnFrmHeight() const
+{
+ OSL_ENSURE( !IsFollow() && IsInFtn(), "SwTxtFrm::SetFtnLine: moon walk" );
+
+ const SwFtnFrm *pFtnFrm = FindFtnFrm();
+ const SwTxtFrm *pRef = (const SwTxtFrm *)pFtnFrm->GetRef();
+ const SwFtnBossFrm *pBoss = FindFtnBossFrm();
+ if( pBoss != pRef->FindFtnBossFrm( !pFtnFrm->GetAttr()->
+ GetFtn().IsEndNote() ) )
+ return 0;
+
+ SWAP_IF_SWAPPED( this )
+
+ SwTwips nHeight = pRef->IsInFtnConnect() ?
+ 1 : pRef->GetFtnLine( pFtnFrm->GetAttr() );
+ if( nHeight )
+ {
+ // So komisch es aussehen mag: Die erste Ftn auf der Seite darf sich
+ // nicht mit der Ftn-Referenz beruehren, wenn wir im Ftn-Bereich Text
+ // eingeben.
+ const SwFrm *pCont = pFtnFrm->GetUpper();
+ //Hoehe innerhalb des Cont, die ich mir 'eh noch genehmigen darf.
+ SWRECTFN( pCont )
+ SwTwips nTmp = (*fnRect->fnYDiff)( (pCont->*fnRect->fnGetPrtBottom)(),
+ (Frm().*fnRect->fnGetTop)() );
+
+#if OSL_DEBUG_LEVEL > 1
+ if( nTmp < 0 )
+ {
+ sal_Bool bInvalidPos = sal_False;
+ const SwLayoutFrm* pTmp = GetUpper();
+ while( !bInvalidPos && pTmp )
+ {
+ bInvalidPos = !pTmp->GetValidPosFlag() ||
+ !pTmp->Lower()->GetValidPosFlag();
+ if( pTmp == pCont )
+ break;
+ pTmp = pTmp->GetUpper();
+ }
+ OSL_ENSURE( bInvalidPos, "Hanging below FtnCont" );
+ }
+#endif
+
+ if ( (*fnRect->fnYDiff)( (pCont->Frm().*fnRect->fnGetTop)(), nHeight) > 0 )
+ {
+ //Wachstumspotential den Containers.
+ if ( !pRef->IsInFtnConnect() )
+ {
+ SwSaveFtnHeight aSave( (SwFtnBossFrm*)pBoss, nHeight );
+ nHeight = ((SwFtnContFrm*)pCont)->Grow( LONG_MAX, sal_True );
+ }
+ else
+ nHeight = ((SwFtnContFrm*)pCont)->Grow( LONG_MAX, sal_True );
+
+ nHeight += nTmp;
+ if( nHeight < 0 )
+ nHeight = 0;
+ }
+ else
+ { // The container has to shrink
+ nTmp += (*fnRect->fnYDiff)( (pCont->Frm().*fnRect->fnGetTop)(), nHeight);
+ if( nTmp > 0 )
+ nHeight = nTmp;
+ else
+ nHeight = 0;
+ }
+ }
+
+ UNDO_SWAP( this )
+
+ return nHeight;
+}
+
+/*************************************************************************
+ * SwTxtFrm::FindQuoVadisFrm()
+ *************************************************************************/
+
+SwTxtFrm *SwTxtFrm::FindQuoVadisFrm()
+{
+ // Erstmal feststellen, ob wir in einem FtnFrm stehen:
+ if( GetIndPrev() || !IsInFtn() )
+ return 0;
+
+ // Zum Vorgaenger-FtnFrm
+ SwFtnFrm *pFtnFrm = FindFtnFrm()->GetMaster();
+ if( !pFtnFrm )
+ return 0;
+
+ // Nun den letzten Cntnt:
+ const SwCntntFrm *pCnt = pFtnFrm->ContainsCntnt();
+ if( !pCnt )
+ return NULL;
+ const SwCntntFrm *pLast;
+ do
+ { pLast = pCnt;
+ pCnt = pCnt->GetNextCntntFrm();
+ } while( pCnt && pFtnFrm->IsAnLower( pCnt ) );
+ return (SwTxtFrm*)pLast;
+}
+
+/*************************************************************************
+ * SwTxtFrm::RemoveFtn()
+ *************************************************************************/
+
+void SwTxtFrm::RemoveFtn( const xub_StrLen nStart, const xub_StrLen nLen )
+{
+ if ( !IsFtnAllowed() )
+ return;
+
+ SwpHints *pHints = GetTxtNode()->GetpSwpHints();
+ if( !pHints )
+ return;
+
+ sal_Bool bRollBack = nLen != STRING_LEN;
+ sal_uInt16 nSize = pHints->Count();
+ xub_StrLen nEnd;
+ SwTxtFrm* pSource;
+ if( bRollBack )
+ {
+ nEnd = nStart + nLen;
+ pSource = GetFollow();
+ if( !pSource )
+ return;
+ }
+ else
+ {
+ nEnd = STRING_LEN;
+ pSource = this;
+ }
+
+ if( nSize )
+ {
+ SwPageFrm* pUpdate = NULL;
+ sal_Bool bRemove = sal_False;
+ SwFtnBossFrm *pFtnBoss = 0;
+ SwFtnBossFrm *pEndBoss = 0;
+ sal_Bool bFtnEndDoc
+ = FTNPOS_CHAPTER == GetNode()->GetDoc()->GetFtnInfo().ePos;
+ for ( sal_uInt16 i = nSize; i; )
+ {
+ SwTxtAttr *pHt = pHints->GetTextHint(--i);
+ if ( RES_TXTATR_FTN != pHt->Which() )
+ continue;
+
+ const xub_StrLen nIdx = *pHt->GetStart();
+ if( nStart > nIdx )
+ break;
+
+ if( nEnd >= nIdx )
+ {
+ SwTxtFtn *pFtn = (SwTxtFtn*)pHt;
+ sal_Bool bEndn = pFtn->GetFtn().IsEndNote();
+
+ if( bEndn )
+ {
+ if( !pEndBoss )
+ pEndBoss = pSource->FindFtnBossFrm();
+ }
+ else
+ {
+ if( !pFtnBoss )
+ {
+ pFtnBoss = pSource->FindFtnBossFrm( sal_True );
+ if( pFtnBoss->GetUpper()->IsSctFrm() )
+ {
+ SwSectionFrm* pSect = (SwSectionFrm*)
+ pFtnBoss->GetUpper();
+ if( pSect->IsFtnAtEnd() )
+ bFtnEndDoc = sal_False;
+ }
+ }
+ }
+
+ // Wir loeschen nicht, sondern wollen die Ftn verschieben.
+ // Drei Faelle koennen auftreten:
+ // 1) Es gibt weder Follow noch PrevFollow
+ // -> RemoveFtn() (vielleicht sogar ein OSL_ENSURE(wert)
+ // 2) nStart > GetOfst, ich habe einen Follow
+ // -> Ftn wandert in den Follow
+ // 3) nStart < GetOfst, ich bin ein Follow
+ // -> Ftn wandert in den PrevFollow
+ // beide muessen auf einer Seite/in einer Spalte stehen.
+
+ SwFtnFrm *pFtnFrm = bEndn ? pEndBoss->FindFtn( pSource, pFtn ) :
+ pFtnBoss->FindFtn( pSource, pFtn );
+
+ if( pFtnFrm )
+ {
+ const sal_Bool bEndDoc = bEndn ? sal_True : bFtnEndDoc;
+ if( bRollBack )
+ {
+ while ( pFtnFrm )
+ {
+ pFtnFrm->SetRef( this );
+ pFtnFrm = pFtnFrm->GetFollow();
+ SetFtn( sal_True );
+ }
+ }
+ else if( GetFollow() )
+ {
+ SwCntntFrm *pDest = GetFollow();
+ while( pDest->GetFollow() && ((SwTxtFrm*)pDest->
+ GetFollow())->GetOfst() <= nIdx )
+ pDest = pDest->GetFollow();
+ OSL_ENSURE( !pDest->FindFtnBossFrm( !bEndn )->FindFtn(
+ pDest,pFtn),"SwTxtFrm::RemoveFtn: footnote exists");
+
+ //Nicht ummelden sondern immer Moven.
+ // OD 08.11.2002 #104840# - use <SwlayoutFrm::IsBefore(::)>
+ if ( bEndDoc ||
+ !pFtnFrm->FindFtnBossFrm()->IsBefore( pDest->FindFtnBossFrm( !bEndn ) )
+ )
+ {
+ SwPageFrm* pTmp = pFtnFrm->FindPageFrm();
+ if( pUpdate && pUpdate != pTmp )
+ pUpdate->UpdateFtnNum();
+ pUpdate = pTmp;
+ while ( pFtnFrm )
+ {
+ pFtnFrm->SetRef( pDest );
+ pFtnFrm = pFtnFrm->GetFollow();
+ }
+ }
+ else
+ {
+ if( bEndn )
+ pEndBoss->MoveFtns( this, pDest, pFtn );
+ else
+ pFtnBoss->MoveFtns( this, pDest, pFtn );
+ bRemove = sal_True;
+ }
+ ((SwTxtFrm*)pDest)->SetFtn( sal_True );
+
+ OSL_ENSURE( pDest->FindFtnBossFrm( !bEndn )->FindFtn( pDest,
+ pFtn),"SwTxtFrm::RemoveFtn: footnote ChgRef failed");
+ }
+ else
+ {
+ if( !bEndDoc || ( bEndn && pEndBoss->IsInSct() &&
+ !SwLayouter::Collecting( GetNode()->GetDoc(),
+ pEndBoss->FindSctFrm(), NULL ) ) )
+ {
+ if( bEndn )
+ pEndBoss->RemoveFtn( this, pFtn );
+ else
+ pFtnBoss->RemoveFtn( this, pFtn );
+ bRemove = bRemove || !bEndDoc;
+ OSL_ENSURE( bEndn ? !pEndBoss->FindFtn( this, pFtn ) :
+ !pFtnBoss->FindFtn( this, pFtn ),
+ "SwTxtFrm::RemoveFtn: can't get off that footnote" );
+ }
+ }
+ }
+ }
+ }
+ if( pUpdate )
+ pUpdate->UpdateFtnNum();
+ // Wir bringen die Oszillation zum stehen:
+ if( bRemove && !bFtnEndDoc && HasPara() )
+ {
+ ValidateBodyFrm();
+ ValidateFrm();
+ }
+ }
+ // Folgendes Problem: Aus dem FindBreak heraus wird das RemoveFtn aufgerufen,
+ // weil die letzte Zeile an den Follow abgegeben werden soll. Der Offset
+ // des Follows ist aber veraltet, er wird demnaechst gesetzt. CalcFntFlag ist
+ // auf einen richtigen Follow-Offset angewiesen. Deshalb wird hier kurzfristig
+ // der Follow-Offset manipuliert.
+ xub_StrLen nOldOfst = STRING_LEN;
+ if( HasFollow() && nStart > GetOfst() )
+ {
+ nOldOfst = GetFollow()->GetOfst();
+ GetFollow()->ManipOfst( nStart + ( bRollBack ? nLen : 0 ) );
+ }
+ pSource->CalcFtnFlag();
+ if( nOldOfst < STRING_LEN )
+ GetFollow()->ManipOfst( nOldOfst );
+}
+
+/*************************************************************************
+ * SwTxtFormatter::ConnectFtn()
+ *************************************************************************/
+// sal_False, wenn irgendetwas schief gegangen ist.
+// Es gibt eigentlich nur zwei Moeglichkeiten:
+// a) Die Ftn ist bereits vorhanden
+// => dann wird sie gemoved, wenn ein anderer pSrcFrm gefunden wurde
+// b) Die Ftn ist nicht vorhanden
+// => dann wird sie fuer uns angelegt.
+// Ob die Ftn schliesslich auf unserer Spalte/Seite landet oder nicht,
+// spielt in diesem Zusammenhang keine Rolle.
+// Optimierungen bei Endnoten.
+// Noch ein Problem: wenn die Deadline im Ftn-Bereich liegt, muss die
+// Ftn verschoben werden.
+
+void SwTxtFrm::ConnectFtn( SwTxtFtn *pFtn, const SwTwips nDeadLine )
+{
+ OSL_ENSURE( !IsVertical() || !IsSwapped(),
+ "SwTxtFrm::ConnectFtn with swapped frame" );
+
+ bFtn = sal_True;
+ bInFtnConnect = sal_True; //Bloss zuruecksetzen!
+ sal_Bool bEnd = pFtn->GetFtn().IsEndNote();
+
+ //
+ // We want to store this value, because it is needed as a fallback
+ // in GetFtnLine(), if there is no paragraph information available
+ //
+ mnFtnLine = nDeadLine;
+
+ // Wir brauchen immer einen Boss (Spalte/Seite)
+ SwSectionFrm *pSect;
+ SwCntntFrm *pCntnt = this;
+ if( bEnd && IsInSct() )
+ {
+ pSect = FindSctFrm();
+ if( pSect->IsEndnAtEnd() )
+ pCntnt = pSect->FindLastCntnt( FINDMODE_ENDNOTE );
+ if( !pCntnt )
+ pCntnt = this;
+ }
+
+ SwFtnBossFrm *pBoss = pCntnt->FindFtnBossFrm( !bEnd );
+
+#if OSL_DEBUG_LEVEL > 1
+ SwTwips nRstHeight = GetRstHeight();
+#endif
+
+ pSect = pBoss->FindSctFrm();
+ sal_Bool bDocEnd = bEnd ? !( pSect && pSect->IsEndnAtEnd() ) :
+ ( !( pSect && pSect->IsFtnAtEnd() ) &&
+ FTNPOS_CHAPTER == GetNode()->GetDoc()->GetFtnInfo().ePos );
+ //Ftn kann beim Follow angemeldet sein.
+ SwCntntFrm *pSrcFrm = FindFtnRef( pFtn );
+
+ if( bDocEnd )
+ {
+ if( pSect && pSrcFrm )
+ {
+ SwFtnFrm *pFtnFrm = pBoss->FindFtn( pSrcFrm, pFtn );
+ if( pFtnFrm && pFtnFrm->IsInSct() )
+ {
+ pBoss->RemoveFtn( pSrcFrm, pFtn );
+ pSrcFrm = 0;
+ }
+ }
+ }
+ else if( bEnd && pSect )
+ {
+ SwFtnFrm *pFtnFrm = pSrcFrm ? pBoss->FindFtn( pSrcFrm, pFtn ) : NULL;
+ if( pFtnFrm && !pFtnFrm->GetUpper() )
+ pFtnFrm = NULL;
+ SwDoc *pDoc = GetNode()->GetDoc();
+ if( SwLayouter::Collecting( pDoc, pSect, pFtnFrm ) )
+ {
+ if( !pSrcFrm )
+ {
+ SwFtnFrm *pNew = new SwFtnFrm(pDoc->GetDfltFrmFmt(),this,this,pFtn);
+ SwNodeIndex aIdx( *pFtn->GetStartNode(), 1 );
+ ::_InsertCnt( pNew, pDoc, aIdx.GetIndex() );
+ GetNode()->getIDocumentLayoutAccess()->GetLayouter()->CollectEndnote( pNew );
+ }
+ else if( pSrcFrm != this )
+ pBoss->ChangeFtnRef( pSrcFrm, pFtn, this );
+ bInFtnConnect = sal_False;
+ return;
+ }
+ else if( pSrcFrm )
+ {
+ SwFtnBossFrm *pFtnBoss = pFtnFrm->FindFtnBossFrm();
+ if( !pFtnBoss->IsInSct() ||
+ pFtnBoss->ImplFindSctFrm()->GetSection()!=pSect->GetSection() )
+ {
+ pBoss->RemoveFtn( pSrcFrm, pFtn );
+ pSrcFrm = 0;
+ }
+ }
+ }
+
+ if( bDocEnd || bEnd )
+ {
+ if( !pSrcFrm )
+ pBoss->AppendFtn( this, pFtn );
+ else if( pSrcFrm != this )
+ pBoss->ChangeFtnRef( pSrcFrm, pFtn, this );
+ bInFtnConnect = sal_False;
+ return;
+ }
+
+ SwSaveFtnHeight aHeight( pBoss, nDeadLine );
+
+ if( !pSrcFrm ) // Es wurde ueberhaupt keine Ftn gefunden.
+ pBoss->AppendFtn( this, pFtn );
+ else
+ {
+ SwFtnFrm *pFtnFrm = pBoss->FindFtn( pSrcFrm, pFtn );
+ SwFtnBossFrm *pFtnBoss = pFtnFrm->FindFtnBossFrm();
+
+ sal_Bool bBrutal = sal_False;
+
+ if( pFtnBoss == pBoss ) // Ref und Ftn sind auf der selben Seite/Spalte.
+ {
+ SwFrm *pCont = pFtnFrm->GetUpper();
+
+ SWRECTFN ( pCont )
+ long nDiff = (*fnRect->fnYDiff)( (pCont->Frm().*fnRect->fnGetTop)(),
+ nDeadLine );
+
+ if( nDiff >= 0 )
+ {
+ //Wenn die Fussnote bei einem Follow angemeldet ist, so ist
+ //es jetzt an der Zeit sie umzumelden.
+ if ( pSrcFrm != this )
+ pBoss->ChangeFtnRef( pSrcFrm, pFtn, this );
+ //Es steht Platz zur Verfuegung, also kann die Fussnote evtl.
+ //wachsen.
+ if ( pFtnFrm->GetFollow() && nDiff > 0 )
+ {
+ SwTwips nHeight = (pCont->Frm().*fnRect->fnGetHeight)();
+ pBoss->RearrangeFtns( nDeadLine, sal_False, pFtn );
+ ValidateBodyFrm();
+ ValidateFrm();
+ ViewShell *pSh = getRootFrm()->GetCurrShell();
+ if ( pSh && nHeight == (pCont->Frm().*fnRect->fnGetHeight)() )
+ //Damit uns nix durch die Lappen geht.
+ pSh->InvalidateWindows( pCont->Frm() );
+ }
+ bInFtnConnect = sal_False;
+ return;
+ }
+ else
+ bBrutal = sal_True;
+ }
+ else
+ {
+ // Ref und Ftn sind nicht auf einer Seite, Move-Versuch ist noetig.
+ SwFrm* pTmp = this;
+ while( pTmp->GetNext() && pSrcFrm != pTmp )
+ pTmp = pTmp->GetNext();
+ if( pSrcFrm == pTmp )
+ bBrutal = sal_True;
+ else
+ { // Wenn unser Boss in einem spaltigen Bereich sitzt, es aber auf
+ // der Seite schon einen FtnContainer gibt, hilft nur die brutale
+ // Methode
+ if( pSect && pSect->FindFtnBossFrm( !bEnd )->FindFtnCont() )
+ bBrutal = sal_True;
+ // OD 08.11.2002 #104840# - use <SwLayoutFrm::IsBefore(..)>
+ else if ( !pFtnFrm->GetPrev() ||
+ pFtnBoss->IsBefore( pBoss )
+ )
+ {
+ SwFtnBossFrm *pSrcBoss = pSrcFrm->FindFtnBossFrm( !bEnd );
+ pSrcBoss->MoveFtns( pSrcFrm, this, pFtn );
+ }
+ else
+ pBoss->ChangeFtnRef( pSrcFrm, pFtn, this );
+ }
+ }
+
+ // Die brutale Loesung: Fussnote entfernen und appenden.
+ // Es muss SetFtnDeadLine() gerufen werden, weil nach
+ // RemoveFtn die nMaxFtnHeight evtl. besser auf unsere Wuensche
+ // eingestellt werden kann.
+ if( bBrutal )
+ {
+ pBoss->RemoveFtn( pSrcFrm, pFtn, sal_False );
+ SwSaveFtnHeight *pHeight = bEnd ? NULL :
+ new SwSaveFtnHeight( pBoss, nDeadLine );
+ pBoss->AppendFtn( this, pFtn );
+ delete pHeight;
+ }
+ }
+
+ // In spaltigen Bereichen, die noch nicht bis zum Seitenrand gehen,
+ // ist kein RearrangeFtns sinnvoll, da der Fussnotencontainer noch
+ // nicht kalkuliert worden ist.
+ if( !pSect || !pSect->Growable() )
+ {
+ // Umgebung validieren, um Oszillationen zu verhindern.
+ SwSaveFtnHeight aNochmal( pBoss, nDeadLine );
+ ValidateBodyFrm();
+ pBoss->RearrangeFtns( nDeadLine, sal_True );
+ ValidateFrm();
+ }
+ else if( pSect->IsFtnAtEnd() )
+ {
+ ValidateBodyFrm();
+ ValidateFrm();
+ }
+
+#if OSL_DEBUG_LEVEL > 1
+ // pFtnFrm kann sich durch Calc veraendert haben ...
+ SwFtnFrm *pFtnFrm = pBoss->FindFtn( this, pFtn );
+ if( pFtnFrm && pBoss != pFtnFrm->FindFtnBossFrm( !bEnd ) )
+ {
+ int bla = 5;
+ (void)bla;
+ }
+ nRstHeight = GetRstHeight();
+#endif
+ bInFtnConnect = sal_False;
+ return;
+}
+
+
+
+/*************************************************************************
+ * SwTxtFormatter::NewFtnPortion()
+ *************************************************************************/
+
+// Die Portion fuer die Ftn-Referenz im Text
+SwFtnPortion *SwTxtFormatter::NewFtnPortion( SwTxtFormatInfo &rInf,
+ SwTxtAttr *pHint )
+{
+ OSL_ENSURE( ! pFrm->IsVertical() || pFrm->IsSwapped(),
+ "NewFtnPortion with unswapped frame" );
+
+ if( !pFrm->IsFtnAllowed() )
+ return 0;
+
+ SwTxtFtn *pFtn = (SwTxtFtn*)pHint;
+ SwFmtFtn& rFtn = (SwFmtFtn&)pFtn->GetFtn();
+ SwDoc *pDoc = pFrm->GetNode()->GetDoc();
+
+ if( rInf.IsTest() )
+ return new SwFtnPortion( rFtn.GetViewNumStr( *pDoc ), pFrm, pFtn );
+
+ SWAP_IF_SWAPPED( pFrm )
+
+ KSHORT nReal;
+ {
+ KSHORT nOldReal = pCurr->GetRealHeight();
+ KSHORT nOldAscent = pCurr->GetAscent();
+ KSHORT nOldHeight = pCurr->Height();
+ ((SwTxtFormatter*)this)->CalcRealHeight();
+ nReal = pCurr->GetRealHeight();
+ if( nReal < nOldReal )
+ nReal = nOldReal;
+ pCurr->SetRealHeight( nOldReal );
+ pCurr->Height( nOldHeight );
+ pCurr->SetAscent( nOldAscent );
+ }
+
+ SwTwips nLower = Y() + nReal;
+
+ const bool bVertical = pFrm->IsVertical();
+ if( bVertical )
+ nLower = pFrm->SwitchHorizontalToVertical( nLower );
+
+ nLower = lcl_GetFtnLower( pFrm, nLower );
+
+ //6995: Wir frischen nur auf. Das Connect tut fuer diesen Fall nix
+ //Brauchbares, sondern wuerde stattdessen fuer diesen Fall meist die
+ //Ftn wegwerfen und neu erzeugen.
+
+ if( !rInf.IsQuick() )
+ pFrm->ConnectFtn( pFtn, nLower );
+
+ SwTxtFrm *pScrFrm = pFrm->FindFtnRef( pFtn );
+ SwFtnBossFrm *pBoss = pFrm->FindFtnBossFrm( !rFtn.IsEndNote() );
+ SwFtnFrm *pFtnFrm = NULL;
+ if( pScrFrm )
+ pFtnFrm = pBoss->FindFtn( pScrFrm, pFtn );
+
+ // Wir erkundigen uns, ob durch unser Append irgendeine
+ // Fussnote noch auf der Seite/Spalte steht. Wenn nicht verschwindet
+ // auch unsere Zeile. Dies fuehrt zu folgendem erwuenschten
+ // Verhalten: Ftn1 pass noch auf die Seite/Spalte, Ftn2 nicht mehr.
+ // Also bleibt die Ftn2-Referenz auf der Seite/Spalte stehen. Die
+ // Fussnote selbst folgt aber erst auf der naechsten Seite/Spalte.
+ // Ausnahme: Wenn keine weitere Zeile auf diese Seite/Spalte passt,
+ // so sollte die Ftn2-Referenz auch auf die naechste wandern.
+ if( !rFtn.IsEndNote() )
+ {
+ SwSectionFrm *pSct = pBoss->FindSctFrm();
+ sal_Bool bAtSctEnd = pSct && pSct->IsFtnAtEnd();
+ if( FTNPOS_CHAPTER != pDoc->GetFtnInfo().ePos || bAtSctEnd )
+ {
+ SwFrm* pFtnCont = pBoss->FindFtnCont();
+ // Wenn der Boss in einem Bereich liegt, kann es sich nur um eine
+ // Spalte dieses Bereichs handeln. Wenn dies nicht die erste Spalte
+ // ist, duerfen wir ausweichen
+ if( !pFrm->IsInTab() && ( GetLineNr() > 1 || pFrm->GetPrev() ||
+ ( !bAtSctEnd && pFrm->GetIndPrev() ) ||
+ ( pSct && pBoss->GetPrev() ) ) )
+ {
+ if( !pFtnCont )
+ {
+ rInf.SetStop( sal_True );
+ UNDO_SWAP( pFrm )
+ return 0;
+ }
+ else
+ {
+ // Es darf keine Fussnotencontainer in spaltigen Bereichen und
+ // gleichzeitig auf der Seite/Seitenspalte geben
+ if( pSct && !bAtSctEnd ) // liegt unser Container in einem (spaltigen) Bereich?
+ {
+ SwFtnBossFrm* pTmp = pBoss->FindSctFrm()->FindFtnBossFrm( sal_True );
+ SwFtnContFrm* pFtnC = pTmp->FindFtnCont();
+ if( pFtnC )
+ {
+ SwFtnFrm* pTmpFrm = (SwFtnFrm*)pFtnC->Lower();
+ if( pTmpFrm && *pTmpFrm < pFtn )
+ {
+ rInf.SetStop( sal_True );
+ UNDO_SWAP( pFrm )
+ return 0;
+ }
+ }
+ }
+ // Ist dies die letzte passende Zeile?
+ SwTwips nTmpBot = Y() + nReal * 2;
+
+ if( bVertical )
+ nTmpBot = pFrm->SwitchHorizontalToVertical( nTmpBot );
+
+ SWRECTFN( pFtnCont )
+
+ const long nDiff = (*fnRect->fnYDiff)(
+ (pFtnCont->Frm().*fnRect->fnGetTop)(),
+ nTmpBot );
+
+ if( pScrFrm && nDiff < 0 )
+ {
+ if( pFtnFrm )
+ {
+ SwFtnBossFrm *pFtnBoss = pFtnFrm->FindFtnBossFrm();
+ if( pFtnBoss != pBoss )
+ {
+ // Wir sind in der letzte Zeile und die Fussnote
+ // ist auf eine andere Seite gewandert, dann wollen
+ // wir mit ...
+ rInf.SetStop( sal_True );
+ UNDO_SWAP( pFrm )
+ return 0;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ // Endlich: FtnPortion anlegen und raus hier...
+ SwFtnPortion *pRet = new SwFtnPortion( rFtn.GetViewNumStr( *pDoc ),
+ pFrm, pFtn, nReal );
+ rInf.SetFtnInside( sal_True );
+
+ UNDO_SWAP( pFrm )
+
+ return pRet;
+ }
+
+/*************************************************************************
+ * SwTxtFormatter::NewFtnNumPortion()
+ *************************************************************************/
+
+// Die Portion fuer die Ftn-Nummerierung im Ftn-Bereich
+
+SwNumberPortion *SwTxtFormatter::NewFtnNumPortion( SwTxtFormatInfo &rInf ) const
+{
+ OSL_ENSURE( pFrm->IsInFtn() && !pFrm->GetIndPrev() && !rInf.IsFtnDone(),
+ "This is the wrong place for a ftnnumber" );
+ if( rInf.GetTxtStart() != nStart ||
+ rInf.GetTxtStart() != rInf.GetIdx() )
+ return 0;
+
+ const SwFtnFrm* pFtnFrm = pFrm->FindFtnFrm();
+ const SwTxtFtn* pFtn = pFtnFrm->GetAttr();
+
+ // Aha, wir sind also im Fussnotenbereich
+ SwFmtFtn& rFtn = (SwFmtFtn&)pFtn->GetFtn();
+
+ SwDoc *pDoc = pFrm->GetNode()->GetDoc();
+ XubString aFtnTxt( rFtn.GetViewNumStr( *pDoc, sal_True ));
+
+ const SwEndNoteInfo* pInfo;
+ if( rFtn.IsEndNote() )
+ pInfo = &pDoc->GetEndNoteInfo();
+ else
+ pInfo = &pDoc->GetFtnInfo();
+ const SwAttrSet& rSet = pInfo->GetCharFmt(*pDoc)->GetAttrSet();
+
+ const SwAttrSet* pParSet = &rInf.GetCharAttr();
+ const IDocumentSettingAccess* pIDSA = pFrm->GetTxtNode()->getIDocumentSettingAccess();
+ SwFont *pNumFnt = new SwFont( pParSet, pIDSA );
+
+ // --> FME 2005-02-17 #i37142#
+ // Underline style of paragraph font should not be considered
+ // Overline style of paragraph font should not be considered
+ // Weight style of paragraph font should not be considered
+ // Posture style of paragraph font should not be considered
+ // See also #i18463# and SwTxtFormatter::NewNumberPortion()
+ pNumFnt->SetUnderline( UNDERLINE_NONE );
+ pNumFnt->SetOverline( UNDERLINE_NONE );
+ pNumFnt->SetItalic( ITALIC_NONE, SW_LATIN );
+ pNumFnt->SetItalic( ITALIC_NONE, SW_CJK );
+ pNumFnt->SetItalic( ITALIC_NONE, SW_CTL );
+ pNumFnt->SetWeight( WEIGHT_NORMAL, SW_LATIN );
+ pNumFnt->SetWeight( WEIGHT_NORMAL, SW_CJK );
+ pNumFnt->SetWeight( WEIGHT_NORMAL, SW_CTL );
+ // <--
+
+ pNumFnt->SetDiffFnt(&rSet, pIDSA );
+ pNumFnt->SetVertical( pNumFnt->GetOrientation(), pFrm->IsVertical() );
+
+ SwFtnNumPortion* pNewPor = new SwFtnNumPortion( aFtnTxt, pNumFnt );
+ pNewPor->SetLeft( !pFrm->IsRightToLeft() );
+ return pNewPor;
+}
+
+/*************************************************************************
+ * SwTxtFormatter::NewErgoSumPortion()
+ *************************************************************************/
+
+XubString lcl_GetPageNumber( const SwPageFrm* pPage )
+{
+ OSL_ENSURE( pPage, "GetPageNumber: Homeless TxtFrm" );
+ MSHORT nVirtNum = pPage->GetVirtPageNum();
+ const SvxNumberType& rNum = pPage->GetPageDesc()->GetNumType();
+ return rNum.GetNumStr( nVirtNum );
+}
+
+SwErgoSumPortion *SwTxtFormatter::NewErgoSumPortion( SwTxtFormatInfo &rInf ) const
+{
+ // Wir koennen nicht davon ausgehen, dass wir ein Follow sind
+ // 7983: GetIdx() nicht nStart
+ if( !pFrm->IsInFtn() || pFrm->GetPrev() ||
+ rInf.IsErgoDone() || rInf.GetIdx() != pFrm->GetOfst() ||
+ pFrm->ImplFindFtnFrm()->GetAttr()->GetFtn().IsEndNote() )
+ return 0;
+
+ // Aha, wir sind also im Fussnotenbereich
+ const SwFtnInfo &rFtnInfo = pFrm->GetNode()->GetDoc()->GetFtnInfo();
+ SwTxtFrm *pQuoFrm = pFrm->FindQuoVadisFrm();
+ if( !pQuoFrm )
+ return 0;
+ const SwPageFrm* pPage = pFrm->FindPageFrm();
+ const SwPageFrm* pQuoPage = pQuoFrm->FindPageFrm();
+ if( pPage == pQuoFrm->FindPageFrm() )
+ return 0; // Wenn der QuoVadis auf der selben (spaltigen) Seite steht
+ const XubString aPage = lcl_GetPageNumber( pPage );
+ SwParaPortion *pPara = pQuoFrm->GetPara();
+ if( pPara )
+ pPara->SetErgoSumNum( aPage );
+ if( !rFtnInfo.aErgoSum.Len() )
+ return 0;
+ SwErgoSumPortion *pErgo = new SwErgoSumPortion( rFtnInfo.aErgoSum,
+ lcl_GetPageNumber( pQuoPage ) );
+ return pErgo;
+}
+
+/*************************************************************************
+ * SwTxtFormatter::FormatQuoVadis()
+ *************************************************************************/
+
+xub_StrLen SwTxtFormatter::FormatQuoVadis( const xub_StrLen nOffset )
+{
+ OSL_ENSURE( ! pFrm->IsVertical() || ! pFrm->IsSwapped(),
+ "SwTxtFormatter::FormatQuoVadis with swapped frame" );
+
+ if( !pFrm->IsInFtn() || pFrm->ImplFindFtnFrm()->GetAttr()->GetFtn().IsEndNote() )
+ return nOffset;
+
+ const SwFrm* pErgoFrm = pFrm->FindFtnFrm()->GetFollow();
+ if( !pErgoFrm && pFrm->HasFollow() )
+ pErgoFrm = pFrm->GetFollow();
+ if( !pErgoFrm )
+ return nOffset;
+
+ if( pErgoFrm == pFrm->GetNext() )
+ {
+ SwFrm *pCol = pFrm->FindColFrm();
+ while( pCol && !pCol->GetNext() )
+ pCol = pCol->GetUpper()->FindColFrm();
+ if( pCol )
+ return nOffset;
+ }
+ else
+ {
+ const SwPageFrm* pPage = pFrm->FindPageFrm();
+ const SwPageFrm* pErgoPage = pErgoFrm->FindPageFrm();
+ if( pPage == pErgoPage )
+ return nOffset; // Wenn der ErgoSum auf der selben Seite steht
+ }
+
+ SwTxtFormatInfo &rInf = GetInfo();
+ const SwFtnInfo &rFtnInfo = pFrm->GetNode()->GetDoc()->GetFtnInfo();
+ if( !rFtnInfo.aQuoVadis.Len() )
+ return nOffset;
+
+ // Ein Wort zu QuoVadis/ErgoSum:
+ // Fuer diese Texte wird der am Absatz eingestellte Font verwendet.
+ // Wir initialisieren uns also:
+// ResetFont();
+ FeedInf( rInf );
+ SeekStartAndChg( rInf, sal_True );
+ if( GetRedln() && pCurr->HasRedline() )
+ GetRedln()->Seek( *pFnt, nOffset, 0 );
+
+ // Ein fieser Sonderfall: Flyfrms reichen in die Zeile und stehen
+ // natuerlich da, wo wir unseren Quovadis Text reinsetzen wollen.
+ // Erst mal sehen, ob es so schlimm ist:
+ SwLinePortion *pPor = pCurr->GetFirstPortion();
+ KSHORT nLastLeft = 0;
+ while( pPor )
+ {
+ if ( pPor->IsFlyPortion() )
+ nLastLeft = ( (SwFlyPortion*) pPor)->Fix() +
+ ( (SwFlyPortion*) pPor)->Width();
+ pPor = pPor->GetPortion();
+ }
+ // Das alte Spiel: wir wollen, dass die Zeile an einer bestimmten
+ // Stelle umbricht, also beeinflussen wir die Width.
+ // nLastLeft ist jetzt quasi der rechte Rand.
+ const KSHORT nOldRealWidth = rInf.RealWidth();
+ rInf.RealWidth( nOldRealWidth - nLastLeft );
+
+ XubString aErgo = lcl_GetPageNumber( pErgoFrm->FindPageFrm() );
+ SwQuoVadisPortion *pQuo = new SwQuoVadisPortion(rFtnInfo.aQuoVadis, aErgo );
+ pQuo->SetAscent( rInf.GetAscent() );
+ pQuo->Height( rInf.GetTxtHeight() );
+ pQuo->Format( rInf );
+ sal_uInt16 nQuoWidth = pQuo->Width();
+ SwLinePortion* pCurrPor = pQuo;
+
+ while ( rInf.GetRest() )
+ {
+ SwLinePortion* pFollow = rInf.GetRest();
+ rInf.SetRest( 0 );
+ pCurrPor->Move( rInf );
+
+ OSL_ENSURE( pFollow->IsQuoVadisPortion(),
+ "Quo Vadis, rest of QuoVadisPortion" );
+
+ // format the rest and append it to the other QuoVadis parts
+ pFollow->Format( rInf );
+ nQuoWidth = nQuoWidth + pFollow->Width();
+
+ pCurrPor->Append( pFollow );
+ pCurrPor = pFollow;
+ }
+
+ nLastLeft = nOldRealWidth - nQuoWidth;
+ Right( Right() - nQuoWidth );
+
+ SWAP_IF_NOT_SWAPPED( pFrm )
+
+ const xub_StrLen nRet = FormatLine( nStart );
+
+ UNDO_SWAP( pFrm )
+
+ Right( rInf.Left() + nOldRealWidth - 1 );
+
+ nLastLeft = nOldRealWidth - pCurr->Width();
+ FeedInf( rInf );
+
+ // Es kann durchaus sein, dass am Ende eine Marginportion steht,
+ // die beim erneuten Aufspannen nur Aerger bereiten wuerde.
+ pPor = pCurr->FindLastPortion();
+ SwGluePortion *pGlue = pPor->IsMarginPortion() ?
+ (SwMarginPortion*) pPor : 0;
+ if( pGlue )
+ {
+ pGlue->Height( 0 );
+ pGlue->Width( 0 );
+ pGlue->SetLen( 0 );
+ pGlue->SetAscent( 0 );
+ pGlue->SetPortion( NULL );
+ pGlue->SetFixWidth(0);
+ }
+
+ // Luxus: Wir sorgen durch das Aufspannen von Glues dafuer,
+ // dass der QuoVadis-Text rechts erscheint:
+ nLastLeft = nLastLeft - nQuoWidth;
+ if( nLastLeft )
+ {
+ if( nLastLeft > pQuo->GetAscent() ) // Mindestabstand
+ {
+ switch( GetAdjust() )
+ {
+ case SVX_ADJUST_BLOCK:
+ {
+ if( !pCurr->GetLen() ||
+ CH_BREAK != GetInfo().GetChar(nStart+pCurr->GetLen()-1))
+ nLastLeft = pQuo->GetAscent();
+ nQuoWidth = nQuoWidth + nLastLeft;
+ break;
+ }
+ case SVX_ADJUST_RIGHT:
+ {
+ nLastLeft = pQuo->GetAscent();
+ nQuoWidth = nQuoWidth + nLastLeft;
+ break;
+ }
+ case SVX_ADJUST_CENTER:
+ {
+ nQuoWidth = nQuoWidth + pQuo->GetAscent();
+ long nDiff = nLastLeft - nQuoWidth;
+ if( nDiff < 0 )
+ {
+ nLastLeft = pQuo->GetAscent();
+ nQuoWidth = (sal_uInt16)(-nDiff + nLastLeft);
+ }
+ else
+ {
+ nQuoWidth = 0;
+ nLastLeft = sal_uInt16(( pQuo->GetAscent() + nDiff ) / 2);
+ }
+ break;
+ }
+ default:
+ nQuoWidth = nQuoWidth + nLastLeft;
+ }
+ }
+ else
+ nQuoWidth = nQuoWidth + nLastLeft;
+ if( nLastLeft )
+ {
+ pGlue = new SwGluePortion(0);
+ pGlue->Width( nLastLeft );
+ pPor->Append( pGlue );
+ pPor = pPor->GetPortion();
+ }
+ }
+
+ // Jetzt aber: die QuoVadis-Portion wird angedockt:
+ pCurrPor = pQuo;
+ while ( pCurrPor )
+ {
+ // pPor->Append deletes the pPortoin pointer of pPor. Therefore
+ // we have to keep a pointer to the next portion
+ pQuo = (SwQuoVadisPortion*)pCurrPor->GetPortion();
+ pPor->Append( pCurrPor );
+ pPor = pPor->GetPortion();
+ pCurrPor = pQuo;
+ }
+
+ pCurr->Width( pCurr->Width() + KSHORT( nQuoWidth ) );
+
+ // Und noch einmal adjustieren wegen des Adjustment und nicht zu Letzt
+ // wegen folgendem Sonderfall: In der Zeile hat der DummUser durchgaengig
+ // einen kleineren Font eingestellt als der vom QuoVadis-Text ...
+ CalcAdjustLine( pCurr );
+
+#if OSL_DEBUG_LEVEL > 1
+ if( OPTDBG( rInf ) )
+ {
+// aDbstream << "FormatQuoVadis:" << endl;
+// pCurr->DebugPortions( aDbstream, rInf.GetTxt(), nStart );
+ }
+#endif
+
+ // Uff...
+ return nRet;
+}
+
+
+/*************************************************************************
+ * SwTxtFormatter::MakeDummyLine()
+ *************************************************************************/
+
+// MakeDummyLine() erzeugt eine Line, die bis zum unteren Seitenrand
+// reicht. DummyLines bzw. DummyPortions sorgen dafuer, dass Oszillationen
+// zum stehen kommen, weil Rueckflussmoeglichkeiten genommen werden.
+// Sie werden bei absatzgebundenen Frames in Fussnoten und bei Ftn-
+// Oszillationen verwendet.
+
+void SwTxtFormatter::MakeDummyLine()
+{
+ KSHORT nRstHeight = GetFrmRstHeight();
+ if( pCurr && nRstHeight > pCurr->Height() )
+ {
+ SwLineLayout *pLay = new SwLineLayout;
+ nRstHeight = nRstHeight - pCurr->Height();
+ pLay->Height( nRstHeight );
+ pLay->SetAscent( nRstHeight );
+ Insert( pLay );
+ Next();
+ }
+}
+
+/*************************************************************************
+ * class SwFtnSave
+ *************************************************************************/
+class SwFtnSave
+{
+ SwTxtSizeInfo *pInf;
+ SwFont *pFnt;
+ SwFont *pOld;
+public:
+ SwFtnSave( const SwTxtSizeInfo &rInf,
+ const SwTxtFtn *pTxtFtn,
+ const bool bApplyGivenScriptType,
+ const sal_uInt8 nGivenScriptType );
+ ~SwFtnSave();
+};
+
+/*************************************************************************
+ * SwFtnSave::SwFtnSave()
+ *************************************************************************/
+
+SwFtnSave::SwFtnSave( const SwTxtSizeInfo &rInf,
+ const SwTxtFtn* pTxtFtn,
+ const bool bApplyGivenScriptType,
+ const sal_uInt8 nGivenScriptType )
+ : pInf( &((SwTxtSizeInfo&)rInf) )
+ , pFnt( 0 )
+ , pOld( 0 )
+{
+ if( pTxtFtn && rInf.GetTxtFrm() )
+ {
+ pFnt = ((SwTxtSizeInfo&)rInf).GetFont();
+ pOld = new SwFont( *pFnt );
+ pOld->GetTox() = pFnt->GetTox();
+ pFnt->GetTox() = 0;
+ SwFmtFtn& rFtn = (SwFmtFtn&)pTxtFtn->GetFtn();
+ const SwDoc *pDoc = rInf.GetTxtFrm()->GetNode()->GetDoc();
+
+ // --> OD 2009-01-29 #i98418#
+ if ( bApplyGivenScriptType )
+ {
+ pFnt->SetActual( nGivenScriptType );
+ }
+ else
+ {
+ // examine text and set script
+ String aTmpStr( rFtn.GetViewNumStr( *pDoc ) );
+ pFnt->SetActual( SwScriptInfo::WhichFont( 0, &aTmpStr, 0 ) );
+ }
+ // <--
+
+ const SwEndNoteInfo* pInfo;
+ if( rFtn.IsEndNote() )
+ pInfo = &pDoc->GetEndNoteInfo();
+ else
+ pInfo = &pDoc->GetFtnInfo();
+ const SwAttrSet& rSet = pInfo->GetAnchorCharFmt((SwDoc&)*pDoc)->GetAttrSet();
+ pFnt->SetDiffFnt( &rSet, rInf.GetTxtFrm()->GetNode()->getIDocumentSettingAccess() );
+
+ // we reduce footnote size, if we are inside a double line portion
+ if ( ! pOld->GetEscapement() && 50 == pOld->GetPropr() )
+ {
+ Size aSize = pFnt->GetSize( pFnt->GetActual() );
+ pFnt->SetSize( Size( (long)aSize.Width() / 2,
+ (long)aSize.Height() / 2 ),
+ pFnt->GetActual() );
+ }
+
+ // set the correct rotation at the footnote font
+ const SfxPoolItem* pItem;
+ if( SFX_ITEM_SET == rSet.GetItemState( RES_CHRATR_ROTATE,
+ sal_True, &pItem ))
+ pFnt->SetVertical( ((SvxCharRotateItem*)pItem)->GetValue(),
+ rInf.GetTxtFrm()->IsVertical() );
+
+ pFnt->ChgPhysFnt( pInf->GetVsh(), *pInf->GetOut() );
+
+ if( SFX_ITEM_SET == rSet.GetItemState( RES_CHRATR_BACKGROUND,
+ sal_True, &pItem ))
+ pFnt->SetBackColor( new Color( ((SvxBrushItem*)pItem)->GetColor() ) );
+ }
+ else
+ pFnt = NULL;
+}
+
+/*************************************************************************
+ * SwFtnSave::~SwFtnSave()
+ *************************************************************************/
+
+SwFtnSave::~SwFtnSave()
+{
+ if( pFnt )
+ {
+ // SwFont zurueckstellen
+ *pFnt = *pOld;
+ pFnt->GetTox() = pOld->GetTox();
+ pFnt->ChgPhysFnt( pInf->GetVsh(), *pInf->GetOut() );
+ delete pOld;
+ }
+}
+
+/*************************************************************************
+ * SwFtnPortion::SwFtnPortion()
+ *************************************************************************/
+
+SwFtnPortion::SwFtnPortion( const XubString &rExpand, SwTxtFrm *pFrame,
+ SwTxtFtn *pFootn, KSHORT nReal )
+ : SwFldPortion( rExpand, 0 )
+ , pFrm(pFrame)
+ , pFtn(pFootn)
+ , nOrigHeight( nReal )
+ // --> OD 2009-01-29 #i98418#
+ , mbPreferredScriptTypeSet( false )
+ , mnPreferredScriptType( SW_LATIN )
+ // <--
+{
+ SetLen(1);
+ SetWhichPor( POR_FTN );
+}
+
+/*************************************************************************
+ * SwFtnPortion::GetExpTxt()
+ *************************************************************************/
+
+sal_Bool SwFtnPortion::GetExpTxt( const SwTxtSizeInfo &, XubString &rTxt ) const
+{
+ rTxt = aExpand;
+ return sal_True;
+}
+
+/*************************************************************************
+ * virtual SwFtnPortion::Format()
+ *************************************************************************/
+
+sal_Bool SwFtnPortion::Format( SwTxtFormatInfo &rInf )
+{
+ // --> OD 2009-01-29 #i98418#
+// SwFtnSave aFtnSave( rInf, pFtn );
+ SwFtnSave aFtnSave( rInf, pFtn, mbPreferredScriptTypeSet, mnPreferredScriptType );
+ // <--
+ // the idx is manipulated in SwExpandPortion::Format
+ // this flag indicates, that a footnote is allowed to trigger
+ // an underflow during SwTxtGuess::Guess
+ rInf.SetFakeLineStart( rInf.GetIdx() > rInf.GetLineStart() );
+ sal_Bool bFull = SwFldPortion::Format( rInf );
+ rInf.SetFakeLineStart( sal_False );
+ SetAscent( rInf.GetAscent() );
+ Height( rInf.GetTxtHeight() );
+ rInf.SetFtnDone( !bFull );
+ if( !bFull )
+ rInf.SetParaFtn();
+ return bFull;
+}
+
+/*************************************************************************
+ * virtual SwFtnPortion::Paint()
+ *************************************************************************/
+
+void SwFtnPortion::Paint( const SwTxtPaintInfo &rInf ) const
+{
+ // --> OD 2009-01-29 #i98418#
+// SwFtnSave aFtnSave( rInf, pFtn );
+ SwFtnSave aFtnSave( rInf, pFtn, mbPreferredScriptTypeSet, mnPreferredScriptType );
+ // <--
+ rInf.DrawViewOpt( *this, POR_FTN );
+ SwExpandPortion::Paint( rInf );
+}
+
+/*************************************************************************
+ * virtual SwFtnPortion::GetTxtSize()
+ *************************************************************************/
+
+SwPosSize SwFtnPortion::GetTxtSize( const SwTxtSizeInfo &rInfo ) const
+{
+ // --> OD 2009-01-29 #i98418#
+// SwFtnSave aFtnSave( rInfo, pFtn );
+ SwFtnSave aFtnSave( rInfo, pFtn, mbPreferredScriptTypeSet, mnPreferredScriptType );
+ // <--
+ return SwExpandPortion::GetTxtSize( rInfo );
+}
+
+// --> OD 2009-01-29 #i98418#
+void SwFtnPortion::SetPreferredScriptType( sal_uInt8 nPreferredScriptType )
+{
+ mbPreferredScriptTypeSet = true;
+ mnPreferredScriptType = nPreferredScriptType;
+}
+// <--
+
+/*************************************************************************
+ * class SwQuoVadisPortion
+ *************************************************************************/
+
+SwFldPortion *SwQuoVadisPortion::Clone( const XubString &rExpand ) const
+{ return new SwQuoVadisPortion( rExpand, aErgo ); }
+
+SwQuoVadisPortion::SwQuoVadisPortion( const XubString &rExp, const XubString& rStr )
+ : SwFldPortion( rExp ), aErgo(rStr)
+{
+ SetLen(0);
+ SetWhichPor( POR_QUOVADIS );
+}
+
+/*************************************************************************
+ * virtual SwQuoVadisPortion::Format()
+ *************************************************************************/
+
+sal_Bool SwQuoVadisPortion::Format( SwTxtFormatInfo &rInf )
+{
+ // erster Versuch, vielleicht passt der Text
+ CheckScript( rInf );
+ sal_Bool bFull = SwFldPortion::Format( rInf );
+ SetLen( 0 );
+
+ if( bFull )
+ {
+ // zweiter Versuch, wir kuerzen den String:
+ aExpand = XubString( "...", RTL_TEXTENCODING_MS_1252 );
+ bFull = SwFldPortion::Format( rInf );
+ SetLen( 0 );
+ if( bFull )
+ // dritter Versuch, es langt: jetzt wird gestaucht:
+ Width( sal_uInt16(rInf.Width() - rInf.X()) );
+
+ // 8317: keine mehrzeiligen Felder bei QuoVadis und ErgoSum
+ if( rInf.GetRest() )
+ {
+ delete rInf.GetRest();
+ rInf.SetRest( 0 );
+ }
+ }
+ return bFull;
+}
+
+/*************************************************************************
+ * virtual SwQuoVadisPortion::GetExpTxt()
+ *************************************************************************/
+
+sal_Bool SwQuoVadisPortion::GetExpTxt( const SwTxtSizeInfo &, XubString &rTxt ) const
+{
+ rTxt = aExpand;
+ // if this QuoVadisPortion has a follow, the follow is responsible for
+ // the ergo text.
+ if ( ! HasFollow() )
+ rTxt += aErgo;
+ return sal_True;
+}
+
+/*************************************************************************
+ * virtual SwQuoVadisPortion::HandlePortion()
+ *************************************************************************/
+
+void SwQuoVadisPortion::HandlePortion( SwPortionHandler& rPH ) const
+{
+ String aString( aExpand );
+ aString += aErgo;
+ rPH.Special( GetLen(), aString, GetWhichPor() );
+}
+
+/*************************************************************************
+ * virtual SwQuoVadisPortion::Paint()
+ *************************************************************************/
+
+void SwQuoVadisPortion::Paint( const SwTxtPaintInfo &rInf ) const
+{
+ // Wir wollen _immer_ per DrawStretchText ausgeben,
+ // weil nErgo schnell mal wechseln kann.
+ if( PrtWidth() )
+ {
+ rInf.DrawViewOpt( *this, POR_QUOVADIS );
+ SwTxtSlot aDiffTxt( &rInf, this, true, false );
+ SwFontSave aSave( rInf, pFnt );
+ rInf.DrawText( *this, rInf.GetLen(), sal_True );
+ }
+}
+
+/*************************************************************************
+ * class SwErgoSumPortion
+ *************************************************************************/
+
+SwFldPortion *SwErgoSumPortion::Clone( const XubString &rExpand ) const
+{
+ UniString aTmp; // = UniString::CreateFromInt32( 0 );
+ return new SwErgoSumPortion( rExpand, aTmp );
+}
+
+SwErgoSumPortion::SwErgoSumPortion( const XubString &rExp, const XubString& rStr )
+ : SwFldPortion( rExp )
+{
+ SetLen(0);
+ aExpand += rStr;
+
+ // 7773: sinnvolle Massnahme: ein Blank Abstand zum Text
+ aExpand += ' ';
+ SetWhichPor( POR_ERGOSUM );
+}
+
+xub_StrLen SwErgoSumPortion::GetCrsrOfst( const KSHORT ) const
+{
+ return 0;
+}
+
+/*************************************************************************
+ * virtual SwErgoSumPortion::Format()
+ *************************************************************************/
+
+sal_Bool SwErgoSumPortion::Format( SwTxtFormatInfo &rInf )
+{
+ sal_Bool bFull = SwFldPortion::Format( rInf );
+ SetLen( 0 );
+ rInf.SetErgoDone( sal_True );
+
+ // 8317: keine mehrzeiligen Felder bei QuoVadis und ErgoSum
+ if( bFull && rInf.GetRest() )
+ {
+ delete rInf.GetRest();
+ rInf.SetRest( 0 );
+ }
+
+ // We return false in order to get some text into the current line,
+ // even if it's full (better than looping)
+ return sal_False;
+}
+
+
+/*************************************************************************
+ * SwParaPortion::SetErgoSumNum()
+ *************************************************************************/
+
+void SwParaPortion::SetErgoSumNum( const XubString& rErgo )
+{
+ SwLineLayout *pLay = this;
+ while( pLay->GetNext() )
+ {
+ pLay = pLay->GetNext();
+ }
+ SwLinePortion *pPor = pLay;
+ SwQuoVadisPortion *pQuo = 0;
+ while( pPor && !pQuo )
+ {
+ if ( pPor->IsQuoVadisPortion() )
+ pQuo = (SwQuoVadisPortion*)pPor;
+ pPor = pPor->GetPortion();
+ }
+ if( pQuo )
+ pQuo->SetNumber( rErgo );
+}
+
+/*************************************************************************
+ * SwParaPortion::UpdateQuoVadis()
+ *
+ * Wird im SwTxtFrm::Prepare() gerufen
+ *************************************************************************/
+
+sal_Bool SwParaPortion::UpdateQuoVadis( const XubString &rQuo )
+{
+ SwLineLayout *pLay = this;
+ while( pLay->GetNext() )
+ {
+ pLay = pLay->GetNext();
+ }
+ SwLinePortion *pPor = pLay;
+ SwQuoVadisPortion *pQuo = 0;
+ while( pPor && !pQuo )
+ {
+ if ( pPor->IsQuoVadisPortion() )
+ pQuo = (SwQuoVadisPortion*)pPor;
+ pPor = pPor->GetPortion();
+ }
+
+ if( !pQuo )
+ return sal_False;
+
+ return pQuo->GetQuoTxt() == rQuo;
+}
+
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/text/txthyph.cxx b/sw/source/core/text/txthyph.cxx
new file mode 100644
index 000000000000..d4edea3cc0e7
--- /dev/null
+++ b/sw/source/core/text/txthyph.cxx
@@ -0,0 +1,662 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+
+#include <hintids.hxx>
+#include <editeng/unolingu.hxx>
+#include <com/sun/star/i18n/WordType.hpp>
+#include <EnhancedPDFExportHelper.hxx>
+#include <viewopt.hxx> // SwViewOptions
+#include <viewsh.hxx>
+#include <SwPortionHandler.hxx>
+#include <porhyph.hxx> //
+#include <inftxt.hxx>
+#include <itrform2.hxx> //
+#include <guess.hxx> //
+#include <splargs.hxx> // SwInterHyphInfo
+
+using ::rtl::OUString;
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::beans;
+using namespace ::com::sun::star::linguistic2;
+using namespace ::com::sun::star::i18n;
+
+/*************************************************************************
+ * SwTxtFormatInfo::HyphWord()
+ *************************************************************************/
+
+Reference< XHyphenatedWord > SwTxtFormatInfo::HyphWord(
+ const XubString &rTxt, const MSHORT nMinTrail )
+{
+ if( rTxt.Len() < 4 || pFnt->IsSymbol(pVsh) )
+ return 0;
+ Reference< XHyphenator > xHyph = ::GetHyphenator();
+ Reference< XHyphenatedWord > xHyphWord;
+
+ if( xHyph.is() )
+ xHyphWord = xHyph->hyphenate( OUString(rTxt),
+ pBreakIt->GetLocale( pFnt->GetLanguage() ),
+ rTxt.Len() - nMinTrail, GetHyphValues() );
+ return xHyphWord;
+
+}
+
+/*************************************************************************
+ * SwTxtFrm::Hyphenate
+ *
+ * Wir formatieren eine Zeile fuer die interaktive Trennung
+ *************************************************************************/
+
+sal_Bool SwTxtFrm::Hyphenate( SwInterHyphInfo &rHyphInf )
+{
+ OSL_ENSURE( ! IsVertical() || ! IsSwapped(),"swapped frame at SwTxtFrm::Hyphenate" );
+
+ if( !pBreakIt->GetBreakIter().is() )
+ return sal_False;;
+ // Wir machen den Laden erstmal dicht:
+ OSL_ENSURE( !IsLocked(), "SwTxtFrm::Hyphenate: this is locked" );
+ // 4935: Der frame::Frame muss eine gueltige SSize haben!
+ Calc();
+ GetFormatted();
+
+ sal_Bool bRet = sal_False;
+ if( !IsEmpty() )
+ {
+ // Wir muessen die Trennung immer einschalten.
+ // Keine Angst, der SwTxtIter sichert im Hyphenate die alte Zeile.
+ SwTxtFrmLocker aLock( this );
+
+ if ( IsVertical() )
+ SwapWidthAndHeight();
+
+ SwTxtFormatInfo aInf( this, sal_True ); // sal_True fuer interactive hyph!
+ SwTxtFormatter aLine( this, &aInf );
+ aLine.CharToLine( rHyphInf.nStart );
+ // Wenn wir innerhalb des ersten Wortes einer Zeile stehen, so koennte
+ // dieses in der vorherigen getrennt werden, deshalb gehen wir ein Zeile
+ // zurueck.
+ if( aLine.Prev() )
+ {
+ SwLinePortion *pPor = aLine.GetCurr()->GetFirstPortion();
+ while( pPor->GetPortion() )
+ pPor = pPor->GetPortion();
+ if( pPor->GetWhichPor() == POR_SOFTHYPH ||
+ pPor->GetWhichPor() == POR_SOFTHYPHSTR )
+ aLine.Next();
+ }
+
+ const xub_StrLen nEnd = rHyphInf.GetEnd();
+ while( !bRet && aLine.GetStart() < nEnd )
+ {
+ bRet = aLine.Hyphenate( rHyphInf );
+ if( !aLine.Next() )
+ break;
+ }
+
+ if ( IsVertical() )
+ SwapWidthAndHeight();
+ }
+ return bRet;
+}
+
+/*************************************************************************
+ * SwTxtFormatter::Hyphenate
+ *
+ * Wir formatieren eine Zeile fuer die interaktive Trennung
+ *************************************************************************/
+// Wir koennen davon ausgehen, dass bereits formatiert wurde.
+// Fuer die CeBIT'93 gehen wir den einfachen, sicheren Weg:
+// Die Zeile wird einfach neu formatiert, der Hyphenator wird dann
+// so vorbereitet, wie ihn die UI erwartet.
+// Hier stehen natuerlich enorme Optimierungsmoeglichkeiten offen.
+
+void SetParaPortion( SwTxtInfo *pInf, SwParaPortion *pRoot )
+{
+ OSL_ENSURE( pRoot, "SetParaPortion: no root anymore" );
+ pInf->pPara = pRoot;
+}
+
+sal_Bool SwTxtFormatter::Hyphenate( SwInterHyphInfo &rHyphInf )
+{
+ SwTxtFormatInfo &rInf = GetInfo();
+ sal_Bool bRet = sal_False;
+
+ // In der letzten Zeile gibt es nie etwas zu trennen.
+ // Es sei denn, es befindet sich eine FlyPortion darin,
+ // oder es ist die letzte Zeile des Masters
+ if( !GetNext() && !rInf.GetTxtFly()->IsOn() && !pFrm->GetFollow() )
+ return bRet;
+
+ xub_StrLen nWrdStart = nStart;
+
+ // Wir muessen die alte Zeile erhalten. Ein Beispiel:
+ // Das Attribut fuer Trennung wurde nicht gesetzt,
+ // in SwTxtFrm::Hyphenate wird es jedoch immer gesetzt,
+ // weil wir Trennpositionen im Hyphenator einstellen wollen.
+ SwLineLayout *pOldCurr = pCurr;
+
+ InitCntHyph();
+
+ // 5298: IsParaLine() (ex.IsFirstLine) fragt auf GetParaPortion() ab.
+ // wir muessen gleiche Bedingungen schaffen: in der ersten
+ // Zeile formatieren wir SwParaPortions...
+ if( pOldCurr->IsParaPortion() )
+ {
+ SwParaPortion *pPara = new SwParaPortion();
+ SetParaPortion( &rInf, pPara );
+ pCurr = pPara;
+ OSL_ENSURE( IsParaLine(), "SwTxtFormatter::Hyphenate: not the first" );
+ }
+ else
+ pCurr = new SwLineLayout();
+
+ nWrdStart = FormatLine( nWrdStart );
+
+ // Man muss immer im Hinterkopf behalten, dass es z.B.
+ // Felder gibt, die aufgetrennt werden koennen ...
+ if( pCurr->PrtWidth() && pCurr->GetLen() )
+ {
+ // Wir muessen uns darauf einstellen, dass in der Zeile
+ // FlyFrms haengen, an denen auch umgebrochen werden darf.
+ // Wir suchen also die erste HyphPortion in dem angegebenen
+ // Bereich.
+
+ SwLinePortion *pPos = pCurr->GetPortion();
+ const xub_StrLen nPamStart = rHyphInf.nStart;
+ nWrdStart = nStart;
+ const xub_StrLen nEnd = rHyphInf.GetEnd();
+ while( pPos )
+ {
+ // Entweder wir liegen drueber oder wir laufen gerade auf eine
+ // Hyphportion die am Ende der Zeile oder vor einem Flys steht.
+ if( nWrdStart >= nEnd )
+ {
+ nWrdStart = 0;
+ break;
+ }
+
+ if( nWrdStart >= nPamStart && pPos->InHyphGrp()
+ && ( !pPos->IsSoftHyphPortion()
+ || ((SwSoftHyphPortion*)pPos)->IsExpand() ) )
+ {
+ nWrdStart = nWrdStart + pPos->GetLen();
+ break;
+ }
+
+ nWrdStart = nWrdStart + pPos->GetLen();
+ pPos = pPos->GetPortion();
+ }
+ // Wenn pPos 0 ist, wurde keine Trennstelle ermittelt.
+ if( !pPos )
+ nWrdStart = 0;
+ }
+
+ // Das alte LineLayout wird wieder eingestellt ...
+ delete pCurr;
+ pCurr = pOldCurr;
+
+ if( pOldCurr->IsParaPortion() )
+ {
+ SetParaPortion( &rInf, (SwParaPortion*)pOldCurr );
+ OSL_ENSURE( IsParaLine(), "SwTxtFormatter::Hyphenate: even not the first" );
+ }
+
+ if( nWrdStart )
+ {
+ // nWrdStart bezeichnet nun die Position im String, der
+ // fuer eine Trennung zur Debatte steht.
+ // Start() hangelt sich zum End()
+ rHyphInf.nWordStart = nWrdStart;
+
+ xub_StrLen nLen = 0;
+ const xub_StrLen nEnd = nWrdStart;
+
+ // Wir suchen vorwaerts
+ Reference< XHyphenatedWord > xHyphWord;
+
+ Boundary aBound =
+ pBreakIt->GetBreakIter()->getWordBoundary( rInf.GetTxt(), nWrdStart,
+ pBreakIt->GetLocale( rInf.GetFont()->GetLanguage() ), WordType::DICTIONARY_WORD, sal_True );
+ nWrdStart = static_cast<xub_StrLen>(aBound.startPos);
+ nLen = static_cast<xub_StrLen>(aBound.endPos - nWrdStart);
+ bRet = 0 != nLen;
+ if( bRet )
+ {
+ XubString aSelTxt( rInf.GetTxt().Copy(nWrdStart, nLen) );
+
+ {
+ MSHORT nMinTrail = 0;
+ if( nWrdStart + nLen > nEnd )
+ nMinTrail = nWrdStart + nLen - nEnd - 1;
+
+ //!! rHyphInf.SetHyphWord( ... ) mu??? hier geschehen
+ xHyphWord = rInf.HyphWord( aSelTxt, nMinTrail );
+ bRet = xHyphWord.is();
+ if ( !rHyphInf.IsCheck() && sal_False == bRet )
+ rHyphInf.SetNoLang( sal_True );
+ }
+
+ if( bRet )
+ {
+ rHyphInf.SetHyphWord( xHyphWord );
+ rHyphInf.nWordStart = nWrdStart;
+ rHyphInf.nWordLen = nLen;
+ rHyphInf.SetNoLang( sal_False );
+ rHyphInf.SetCheck( sal_True );
+ }
+ }
+ }
+ return bRet;
+}
+
+/*************************************************************************
+ * SwTxtPortion::CreateHyphen()
+ *************************************************************************/
+
+sal_Bool SwTxtPortion::CreateHyphen( SwTxtFormatInfo &rInf, SwTxtGuess &rGuess )
+{
+ Reference< XHyphenatedWord > xHyphWord = rGuess.HyphWord();
+
+ OSL_ENSURE( !pPortion, "SwTxtPortion::CreateHyphen(): another portion, another planet..." );
+ OSL_ENSURE( xHyphWord.is(), "SwTxtPortion::CreateHyphen(): You are lucky! The code is robust here." );
+
+ if( rInf.IsHyphForbud() ||
+ pPortion || // robust
+ !xHyphWord.is() || // more robust
+ // Mehrzeilige Felder duerfen nicht interaktiv getrennt werden.
+ ( rInf.IsInterHyph() && InFldGrp() ) )
+ return sal_False;
+
+ SwHyphPortion *pHyphPor;
+ xub_StrLen nPorEnd;
+ SwTxtSizeInfo aInf( rInf );
+
+ // first case: hyphenated word has alternative spelling
+ if ( xHyphWord->isAlternativeSpelling() )
+ {
+ SvxAlternativeSpelling aAltSpell;
+ aAltSpell = SvxGetAltSpelling( xHyphWord );
+ OSL_ENSURE( aAltSpell.bIsAltSpelling, "no alternatve spelling" );
+
+ XubString aAltTxt = aAltSpell.aReplacement;
+ nPorEnd = aAltSpell.nChangedPos + rGuess.BreakStart() - rGuess.FieldDiff();
+ xub_StrLen nTmpLen = 0;
+
+ // soft hyphen at alternative spelling position?
+ if( rInf.GetTxt().GetChar( rInf.GetSoftHyphPos() ) == CHAR_SOFTHYPHEN )
+ {
+ pHyphPor = new SwSoftHyphStrPortion( aAltTxt );
+ nTmpLen = 1;
+ }
+ else {
+ pHyphPor = new SwHyphStrPortion( aAltTxt );
+ }
+
+ // length of pHyphPor is adjusted
+ pHyphPor->SetLen( aAltTxt.Len() + 1 );
+ (SwPosSize&)(*pHyphPor) = pHyphPor->GetTxtSize( rInf );
+ pHyphPor->SetLen( aAltSpell.nChangedLength + nTmpLen );
+ }
+ else
+ {
+ // second case: no alternative spelling
+ SwHyphPortion aHyphPor;
+ aHyphPor.SetLen( 1 );
+
+ static const void* pLastMagicNo = 0;
+ static KSHORT aMiniCacheH = 0, aMiniCacheW = 0;
+ const void* pTmpMagic;
+ MSHORT nFntIdx;
+ rInf.GetFont()->GetMagic( pTmpMagic, nFntIdx, rInf.GetFont()->GetActual() );
+ if( !pLastMagicNo || pLastMagicNo != pTmpMagic ) {
+ pLastMagicNo = pTmpMagic;
+ (SwPosSize&)aHyphPor = aHyphPor.GetTxtSize( rInf );
+ aMiniCacheH = aHyphPor.Height(), aMiniCacheW = aHyphPor.Width();
+ } else {
+ aHyphPor.Height( aMiniCacheH ), aHyphPor.Width( aMiniCacheW );
+ }
+ aHyphPor.SetLen( 0 );
+ pHyphPor = new SwHyphPortion( aHyphPor );
+
+ pHyphPor->SetWhichPor( POR_HYPH );
+
+ // values required for this
+ nPorEnd = xHyphWord->getHyphenPos() + 1 + rGuess.BreakStart()
+ - rGuess.FieldDiff();
+ }
+
+ // portion end must be in front of us
+ // we do not put hyphens at start of line
+ if ( nPorEnd > rInf.GetIdx() ||
+ ( nPorEnd == rInf.GetIdx() && rInf.GetLineStart() != rInf.GetIdx() ) )
+ {
+ aInf.SetLen( nPorEnd - rInf.GetIdx() );
+ pHyphPor->SetAscent( GetAscent() );
+ SetLen( aInf.GetLen() );
+ CalcTxtSize( aInf );
+
+ Insert( pHyphPor );
+
+ short nKern = rInf.GetFont()->CheckKerning();
+ if( nKern )
+ new SwKernPortion( *this, nKern );
+
+ return sal_True;
+ }
+
+ // last exit for the lost
+ delete pHyphPor;
+ BreakCut( rInf, rGuess );
+ return sal_False;
+}
+
+
+/*************************************************************************
+ * virtual SwHyphPortion::GetExpTxt()
+ *************************************************************************/
+
+sal_Bool SwHyphPortion::GetExpTxt( const SwTxtSizeInfo &rInf, XubString &rTxt ) const
+{
+ // --> FME 2004-06-24 #i16816# tagged pdf support
+ const sal_Unicode cChar = rInf.GetVsh() &&
+ rInf.GetVsh()->GetViewOptions()->IsPDFExport() &&
+ SwTaggedPDFHelper::IsExportTaggedPDF( *rInf.GetOut() ) ?
+ 0xad :
+ '-';
+ // <--
+
+ rTxt = cChar;
+ return sal_True;
+}
+
+/*************************************************************************
+ * virtual SwHyphPortion::HandlePortion()
+ *************************************************************************/
+
+void SwHyphPortion::HandlePortion( SwPortionHandler& rPH ) const
+{
+ String aString( '-' );
+ rPH.Special( GetLen(), aString, GetWhichPor() );
+}
+
+/*************************************************************************
+ * virtual SwHyphPortion::Format()
+ *************************************************************************/
+
+sal_Bool SwHyphPortion::Format( SwTxtFormatInfo &rInf )
+{
+ const SwLinePortion *pLast = rInf.GetLast();
+ Height( pLast->Height() );
+ SetAscent( pLast->GetAscent() );
+ XubString aTxt;
+
+ if( !GetExpTxt( rInf, aTxt ) )
+ return sal_False;
+
+ PrtWidth( rInf.GetTxtSize( aTxt ).Width() );
+ const sal_Bool bFull = rInf.Width() <= rInf.X() + PrtWidth();
+ if( bFull && !rInf.IsUnderFlow() ) {
+ Truncate();
+ rInf.SetUnderFlow( this );
+ }
+
+ return bFull;
+}
+
+/*************************************************************************
+ * virtual SwHyphStrPortion::GetExpTxt()
+ *************************************************************************/
+
+sal_Bool SwHyphStrPortion::GetExpTxt( const SwTxtSizeInfo &, XubString &rTxt ) const
+{
+ rTxt = aExpand;
+ return sal_True;
+}
+
+/*************************************************************************
+ * virtual SwHyphStrPortion::HandlePortion()
+ *************************************************************************/
+
+void SwHyphStrPortion::HandlePortion( SwPortionHandler& rPH ) const
+{
+ rPH.Special( GetLen(), aExpand, GetWhichPor() );
+}
+
+/*************************************************************************
+ * class SwSoftHyphPortion
+ *************************************************************************/
+
+SwLinePortion *SwSoftHyphPortion::Compress() { return this; }
+
+SwSoftHyphPortion::SwSoftHyphPortion() :
+ bExpand(sal_False), nViewWidth(0), nHyphWidth(0)
+{
+ SetLen(1);
+ SetWhichPor( POR_SOFTHYPH );
+}
+
+KSHORT SwSoftHyphPortion::GetViewWidth( const SwTxtSizeInfo &rInf ) const
+{
+ // Wir stehen zwar im const, aber nViewWidth sollte erst im letzten
+ // Moment errechnet werden:
+ if( !Width() && rInf.OnWin() && rInf.GetOpt().IsSoftHyph() && !IsExpand() )
+ {
+ if( !nViewWidth )
+ ((SwSoftHyphPortion*)this)->nViewWidth
+ = rInf.GetTxtSize( '-' ).Width();
+ }
+ else
+ ((SwSoftHyphPortion*)this)->nViewWidth = 0;
+ return nViewWidth;
+}
+
+/* Faelle:
+ * 1) SoftHyph steht in der Zeile, ViewOpt aus.
+ * -> unsichtbar, Nachbarn unveraendert
+ * 2) SoftHyph steht in der Zeile, ViewOpt an.
+ * -> sichtbar, Nachbarn veraendert
+ * 3) SoftHyph steht am Zeilenende, ViewOpt aus/an.
+ * -> immer sichtbar, Nachbarn unveraendert
+ */
+
+void SwSoftHyphPortion::Paint( const SwTxtPaintInfo &rInf ) const
+{
+ if( Width() )
+ {
+ rInf.DrawViewOpt( *this, POR_SOFTHYPH );
+ SwExpandPortion::Paint( rInf );
+ }
+}
+
+/*************************************************************************
+ * virtual SwSoftHyphPortion::Format()
+ *************************************************************************/
+
+/* Die endgueltige Breite erhalten wir im FormatEOL().
+ * In der Underflow-Phase stellen wir fest, ob ueberhaupt ein
+ * alternatives Spelling vorliegt. Wenn ja ...
+ *
+ * Fall 1: "Au-to"
+ * 1) {Au}{-}{to}, {to} passt nicht mehr => Underflow
+ * 2) {-} ruft Hyphenate => keine Alternative
+ * 3) FormatEOL() und bFull = sal_True
+ *
+ * Fall 2: "Zuc-ker"
+ * 1) {Zuc}{-}{ker}, {ker} passt nicht mehr => Underflow
+ * 2) {-} ruft Hyphenate => Alternative!
+ * 3) Underflow() und bFull = sal_True
+ * 4) {Zuc} ruft Hyphenate => {Zuk}{-}{ker}
+ */
+
+sal_Bool SwSoftHyphPortion::Format( SwTxtFormatInfo &rInf )
+{
+ sal_Bool bFull = sal_True;
+
+ // special case for old german spelling
+ if( rInf.IsUnderFlow() )
+ {
+ if( rInf.GetSoftHyphPos() )
+ return sal_True;
+
+ const sal_Bool bHyph = rInf.ChgHyph( sal_True );
+ if( rInf.IsHyphenate() )
+ {
+ rInf.SetSoftHyphPos( rInf.GetIdx() );
+ Width(0);
+ // if the soft hyphend word has an alternative spelling
+ // when hyphenated (old german spelling), the soft hyphen
+ // portion has to trigger an underflow
+ SwTxtGuess aGuess;
+ bFull = rInf.IsInterHyph() ||
+ !aGuess.AlternativeSpelling( rInf, rInf.GetIdx() - 1 );
+ }
+ rInf.ChgHyph( bHyph );
+
+ if( bFull && !rInf.IsHyphForbud() )
+ {
+ rInf.SetSoftHyphPos(0);
+ FormatEOL( rInf );
+ if ( rInf.GetFly() )
+ rInf.GetRoot()->SetMidHyph( sal_True );
+ else
+ rInf.GetRoot()->SetEndHyph( sal_True );
+ }
+ else
+ {
+ rInf.SetSoftHyphPos( rInf.GetIdx() );
+ Truncate();
+ rInf.SetUnderFlow( this );
+ }
+ return sal_True;
+ }
+
+ rInf.SetSoftHyphPos(0);
+ SetExpand( sal_True );
+ bFull = SwHyphPortion::Format( rInf );
+ SetExpand( sal_False );
+ if( !bFull )
+ {
+ // default-maessig besitzen wir keine Breite, aber eine Hoehe
+ nHyphWidth = Width();
+ Width(0);
+ }
+ return bFull;
+}
+
+/*************************************************************************
+ * virtual SwSoftHyphPortion::FormatEOL()
+ *************************************************************************/
+// Format end of Line
+
+void SwSoftHyphPortion::FormatEOL( SwTxtFormatInfo &rInf )
+{
+ if( !IsExpand() )
+ {
+ SetExpand( sal_True );
+ if( rInf.GetLast() == this )
+ rInf.SetLast( FindPrevPortion( rInf.GetRoot() ) );
+
+ // 5964: alte Werte muessen wieder zurueckgesetzt werden.
+ const SwTwips nOldX = rInf.X();
+ const xub_StrLen nOldIdx = rInf.GetIdx();
+ rInf.X( rInf.X() - PrtWidth() );
+ rInf.SetIdx( rInf.GetIdx() - GetLen() );
+ const sal_Bool bFull = SwHyphPortion::Format( rInf );
+ nHyphWidth = Width();
+
+ // 6976: Eine truebe Sache: Wir werden erlaubterweise breiter,
+ // aber gleich wird noch ein Fly verarbeitet, der eine korrekte
+ // X-Position braucht.
+ if( bFull || !rInf.GetFly() )
+ rInf.X( nOldX );
+ else
+ rInf.X( nOldX + Width() );
+ rInf.SetIdx( nOldIdx );
+ }
+}
+
+/*************************************************************************
+ * virtual SwSoftHyphPortion::GetExpTxt()
+ *
+ * Wir expandieren:
+ * - wenn die Sonderzeichen sichtbar sein sollen
+ * - wenn wir am Ende der Zeile stehen.
+ * - wenn wir vor einem (echten/emuliertem) Zeilenumbruch stehen
+ *************************************************************************/
+
+sal_Bool SwSoftHyphPortion::GetExpTxt( const SwTxtSizeInfo &rInf, XubString &rTxt ) const
+{
+ if( IsExpand() || ( rInf.OnWin() && rInf.GetOpt().IsSoftHyph() ) ||
+ ( GetPortion() && ( GetPortion()->InFixGrp() ||
+ GetPortion()->IsDropPortion() || GetPortion()->IsLayPortion() ||
+ GetPortion()->IsParaPortion() || GetPortion()->IsBreakPortion() ) ) )
+ {
+ return SwHyphPortion::GetExpTxt( rInf, rTxt );
+ }
+ return sal_False;
+}
+
+/*************************************************************************
+ * virtual SwSoftHyphPortion::HandlePortion()
+ *************************************************************************/
+
+void SwSoftHyphPortion::HandlePortion( SwPortionHandler& rPH ) const
+{
+ const String aString( '-' );
+ const sal_uInt16 nWhich = ! Width() ?
+ POR_SOFTHYPH_COMP :
+ GetWhichPor();
+ rPH.Special( GetLen(), aString, nWhich );
+}
+
+/*************************************************************************
+ * SwSoftHyphStrPortion::Paint
+ *************************************************************************/
+
+void SwSoftHyphStrPortion::Paint( const SwTxtPaintInfo &rInf ) const
+{
+ // Bug oder feature?:
+ // {Zu}{k-}{ker}, {k-} wird grau statt {-}
+ rInf.DrawViewOpt( *this, POR_SOFTHYPH );
+ SwHyphStrPortion::Paint( rInf );
+}
+
+SwSoftHyphStrPortion::SwSoftHyphStrPortion( const XubString &rStr )
+ : SwHyphStrPortion( rStr )
+{
+ SetLen( 1 );
+ SetWhichPor( POR_SOFTHYPHSTR );
+}
+
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/text/txtinit.cxx b/sw/source/core/text/txtinit.cxx
new file mode 100644
index 000000000000..79799512a998
--- /dev/null
+++ b/sw/source/core/text/txtinit.cxx
@@ -0,0 +1,99 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+#include "swcache.hxx"
+#include "fntcache.hxx" // pFntCache ( SwFont/ScrFont-PrtFont Cache )
+#include "swfntcch.hxx" // pSwFontCache ( SwAttrSet/SwFont Cache )
+#include "txtfrm.hxx"
+#include "txtcache.hxx"
+#include "porlay.hxx"
+#include "porglue.hxx"
+#include "porexp.hxx"
+#include "porrst.hxx"
+#include "portab.hxx"
+#include "porfly.hxx"
+#include "portox.hxx"
+#include "porref.hxx"
+#include "porftn.hxx"
+#include "porhyph.hxx"
+#include "pordrop.hxx"
+#include "blink.hxx" // Blink-Manager
+#include "init.hxx" // Deklarationen fuer _TextInit() und _TextFinit()
+#include "txtfly.hxx" // SwContourCache
+#include "dbg_lay.hxx" // Layout Debug Fileausgabe
+
+SwCache *SwTxtFrm::pTxtCache = 0;
+long SwTxtFrm::nMinPrtLine = 0;
+SwContourCache *pContourCache = 0;
+SwDropCapCache *pDropCapCache = 0;
+
+IMPL_FIXEDMEMPOOL_NEWDEL( SwTxtLine, 50, 50 )
+IMPL_FIXEDMEMPOOL_NEWDEL( SwParaPortion, 50, 50 ) //Absaetze
+IMPL_FIXEDMEMPOOL_NEWDEL( SwLineLayout, 150, 150 ) //Zeilen
+IMPL_FIXEDMEMPOOL_NEWDEL( SwHolePortion, 150, 150 ) //z.B. Blanks am Zeilenende
+IMPL_FIXEDMEMPOOL_NEWDEL( SwTxtPortion, 200, 100 ) //Attributwechsel
+
+/*************************************************************************
+ * _TextInit(), _TextFinit()
+ *************************************************************************/
+
+// Werden _nur_ in init.cxx verwendet, dort stehen extern void _TextFinit()
+// und extern void _TextInit(...)
+
+void _TextInit()
+{
+ pFntCache = new SwFntCache; // Cache for SwSubFont -> SwFntObj = { Font aFont, Font* pScrFont, Font* pPrtFont, OutputDevice* pPrinter, ... }
+ pSwFontCache = new SwFontCache; // Cache for SwTxtFmtColl -> SwFontObj = { SwFont aSwFont, SfxPoolItem* pDefaultArray }
+ SwCache *pTxtCache = new SwCache( 250, 100 // Cache for SwTxtFrm -> SwTxtLine = { SwParaPortion* pLine }
+#if OSL_DEBUG_LEVEL > 1
+ , "static SwTxtFrm::pTxtCache"
+#endif
+ );
+ SwTxtFrm::SetTxtCache( pTxtCache );
+ pWaveCol = new Color( COL_GRAY );
+ PROTOCOL_INIT
+}
+
+void _TextFinit()
+{
+ PROTOCOL_STOP
+ delete SwTxtFrm::GetTxtCache();
+ delete pSwFontCache;
+ delete pFntCache;
+ delete pBlink;
+ delete pWaveCol;
+ delete pContourCache;
+ SwDropPortion::DeleteDropCapCache();
+}
+
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/text/txtio.cxx b/sw/source/core/text/txtio.cxx
new file mode 100644
index 000000000000..d2be2ed2f7a9
--- /dev/null
+++ b/sw/source/core/text/txtio.cxx
@@ -0,0 +1,723 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+#if OSL_DEBUG_LEVEL > 1
+
+#include "viewsh.hxx" // IsDbg()
+#include "viewopt.hxx" // IsDbg()
+#include "txtatr.hxx"
+#include "txtfrm.hxx" // IsDbg()
+#include "rootfrm.hxx"
+#include "flyfrms.hxx"
+#include "inftxt.hxx"
+#include "porexp.hxx"
+#include "porfld.hxx"
+#include "porfly.hxx"
+#include "porftn.hxx"
+#include "porglue.hxx"
+#include "porhyph.hxx"
+#include "porlay.hxx"
+#include "porlin.hxx"
+#include "porref.hxx"
+#include "porrst.hxx"
+#include "portab.hxx"
+#include "portox.hxx"
+#include "portxt.hxx"
+#include "pordrop.hxx"
+#include "pormulti.hxx"
+#include "ndhints.hxx"
+
+#define CONSTCHAR( name, string ) static const sal_Char name[] = string
+
+SvStream &operator<<( SvStream &rOs, const SwpHints & ) //$ ostream
+{
+ rOs << " {HINTS:";
+ rOs << '}';
+ return rOs;
+}
+
+/*************************************************************************
+ * IsDbg()
+ *************************************************************************/
+
+sal_Bool IsDbg( const SwTxtFrm *pFrm )
+{
+ if( pFrm && pFrm->getRootFrm()->GetCurrShell() )
+ return pFrm->getRootFrm()->GetCurrShell()->GetViewOptions()->IsTest4();
+ else
+ return sal_False;
+}
+
+#if OSL_DEBUG_LEVEL < 2
+
+static void Error()
+{
+ // wegen PM und BCC
+ sal_Bool bFalse = sal_False;
+ OSL_ENSURE( bFalse, "txtio: No debug version" );
+}
+
+#define IMPL_OUTOP(class) \
+ SvStream &class::operator<<( SvStream &rOs ) const /*$ostream*/\
+ { \
+ Error(); \
+ return rOs; \
+ }
+
+IMPL_OUTOP( SwTxtPortion )
+IMPL_OUTOP( SwLinePortion )
+IMPL_OUTOP( SwBreakPortion )
+IMPL_OUTOP( SwGluePortion )
+IMPL_OUTOP( SwFldPortion )
+IMPL_OUTOP( SwHiddenPortion )
+IMPL_OUTOP( SwHyphPortion )
+IMPL_OUTOP( SwFixPortion )
+IMPL_OUTOP( SwFlyPortion )
+IMPL_OUTOP( SwFlyCntPortion )
+IMPL_OUTOP( SwMarginPortion )
+IMPL_OUTOP( SwNumberPortion )
+IMPL_OUTOP( SwBulletPortion )
+IMPL_OUTOP( SwGrfNumPortion )
+IMPL_OUTOP( SwLineLayout )
+IMPL_OUTOP( SwParaPortion )
+IMPL_OUTOP( SwFtnPortion )
+IMPL_OUTOP( SwFtnNumPortion )
+IMPL_OUTOP( SwTmpEndPortion )
+IMPL_OUTOP( SwHyphStrPortion )
+IMPL_OUTOP( SwExpandPortion )
+IMPL_OUTOP( SwBlankPortion )
+IMPL_OUTOP( SwToxPortion )
+IMPL_OUTOP( SwRefPortion )
+IMPL_OUTOP( SwIsoToxPortion )
+IMPL_OUTOP( SwIsoRefPortion )
+IMPL_OUTOP( SwSoftHyphPortion )
+IMPL_OUTOP( SwSoftHyphStrPortion )
+IMPL_OUTOP( SwTabPortion )
+IMPL_OUTOP( SwTabLeftPortion )
+IMPL_OUTOP( SwTabRightPortion )
+IMPL_OUTOP( SwTabCenterPortion )
+IMPL_OUTOP( SwTabDecimalPortion )
+IMPL_OUTOP( SwPostItsPortion )
+IMPL_OUTOP( SwQuoVadisPortion )
+IMPL_OUTOP( SwErgoSumPortion )
+IMPL_OUTOP( SwHolePortion )
+IMPL_OUTOP( SwDropPortion )
+IMPL_OUTOP( SwKernPortion )
+IMPL_OUTOP( SwArrowPortion )
+IMPL_OUTOP( SwMultiPortion )
+IMPL_OUTOP( SwCombinedPortion )
+
+const char *GetPortionName( const MSHORT )
+{
+ return 0;
+}
+
+const char *GetPrepName( const PrepareHint )
+{
+ return 0;
+}
+
+void SwLineLayout::DebugPortions( SvStream &, const XubString &, //$ ostream
+ const xub_StrLen )
+{
+}
+
+#else
+#include <limits.h>
+#include <stdlib.h>
+#include "swtypes.hxx" // ZTCCONST
+#include "swfont.hxx" // SwDropPortion
+
+CONSTCHAR( pClose, "} " );
+
+/*************************************************************************
+ * GetPortionName()
+ *************************************************************************/
+
+CONSTCHAR( pPOR_LIN, "LIN" );
+CONSTCHAR( pPOR_TXT, "TXT" );
+CONSTCHAR( pPOR_SHADOW, "SHADOW" );
+CONSTCHAR( pPOR_TAB, "TAB" );
+CONSTCHAR( pPOR_TABLEFT, "TABLEFT" );
+CONSTCHAR( pPOR_TABRIGHT, "TABRIGHT" );
+CONSTCHAR( pPOR_TABCENTER, "TABCENTER" );
+CONSTCHAR( pPOR_TABDECIMAL, "TABDECIMAL" );
+CONSTCHAR( pPOR_EXP, "EXP" );
+CONSTCHAR( pPOR_HYPH, "HYPH" );
+CONSTCHAR( pPOR_HYPHSTR, "HYPHSTR" );
+CONSTCHAR( pPOR_FLD, "FLD" );
+CONSTCHAR( pPOR_FIX, "FIX" );
+CONSTCHAR( pPOR_FLY, "FLY" );
+CONSTCHAR( pPOR_FLYCNT, "FLYCNT" );
+CONSTCHAR( pPOR_MARGIN, "MARGIN" );
+CONSTCHAR( pPOR_GLUE, "GLUE" );
+CONSTCHAR( pPOR_HOLE, "HOLE" );
+CONSTCHAR( pPOR_END, "END" );
+CONSTCHAR( pPOR_BRK, "BRK" );
+CONSTCHAR( pPOR_LAY, "LAY" );
+CONSTCHAR( pPOR_BLANK, "BLANK" );
+CONSTCHAR( pPOR_FTN, "FTN" );
+CONSTCHAR( pPOR_FTNNUM, "FTNNUM" );
+CONSTCHAR( pPOR_POSTITS, "POSTITS" );
+CONSTCHAR( pPOR_SOFTHYPH, "SOFTHYPH" );
+CONSTCHAR( pPOR_SOFTHYPHSTR, "SOFTHYPHSTR" );
+CONSTCHAR( pPOR_TOX, "TOX" );
+CONSTCHAR( pPOR_REF, "REF" );
+
+CONSTCHAR( pPOR_ISOTOX, "ISOTOX" );
+CONSTCHAR( pPOR_ISOREF, "ISOREF" );
+CONSTCHAR( pPOR_HIDDEN, "Hidden" );
+CONSTCHAR( pPOR_QUOVADIS, "QuoVadis" );
+CONSTCHAR( pPOR_ERGOSUM, "ErgoSum" );
+CONSTCHAR( pPOR_NUMBER, "NUMBER" );
+CONSTCHAR( pPOR_BULLET, "BULLET" );
+CONSTCHAR( pPOR_UNKW, "UNKW" );
+CONSTCHAR( pPOR_PAR, "PAR" );
+
+const char *GetPortionName( const MSHORT /*nType*/ )
+{
+ return 0;
+}
+
+CONSTCHAR( pPREP_CLEAR, "CLEAR" );
+CONSTCHAR( pPREP_WIDOWS_ORPHANS, "WIDOWS_ORPHANS" );
+CONSTCHAR( pPREP_FIXSIZE_CHG, "FIXSIZE_CHG" );
+CONSTCHAR( pPREP_FOLLOW_FOLLOWS, "FOLLOW_FOLLOWS" );
+CONSTCHAR( pPREP_ADJUST_FRM, "ADJUST_FRM" );
+CONSTCHAR( pPREP_FREE_SPACE, "FREE_SPACE" );
+CONSTCHAR( pPREP_FLY_CHGD, "FLY_CHGD" );
+CONSTCHAR( pPREP_FLY_ATTR_CHG, "FLY_ATTR_CHG" );
+CONSTCHAR( pPREP_FLY_ARRIVE, "FLY_ARRIVE" );
+CONSTCHAR( pPREP_FLY_LEAVE, "FLY_LEAVE" );
+CONSTCHAR( pPREP_VIEWOPT, "VIEWOPT" );
+CONSTCHAR( pPREP_FTN, "FTN" );
+CONSTCHAR( pPREP_POS_CHGD, "POS" );
+CONSTCHAR( pPREP_UL_SPACE, "UL_SPACE" );
+CONSTCHAR( pPREP_MUST_FIT, "MUST_FIT" );
+CONSTCHAR( pPREP_WIDOWS, "ORPHANS" );
+CONSTCHAR( pPREP_QUOVADIS, "QUOVADIS" );
+CONSTCHAR( pPREP_PAGE, "PAGE" );
+
+const char *GetPrepName( const PrepareHint ePrep )
+{
+ // Kurz und schmerzlos:
+ const char *ppNameArr[PREP_END] =
+ {
+ pPREP_CLEAR, pPREP_WIDOWS_ORPHANS, pPREP_FIXSIZE_CHG,
+ pPREP_FOLLOW_FOLLOWS, pPREP_ADJUST_FRM, pPREP_FREE_SPACE,
+ pPREP_FLY_CHGD, pPREP_FLY_ATTR_CHG, pPREP_FLY_ARRIVE,
+ pPREP_FLY_LEAVE, pPREP_VIEWOPT, pPREP_FTN, pPREP_POS_CHGD,
+ pPREP_UL_SPACE, pPREP_MUST_FIT, pPREP_WIDOWS, pPREP_QUOVADIS,
+ pPREP_PAGE
+ };
+ OSL_ENSURE( ePrep < PREP_END, "GetPrepName: unknown PrepareHint" );
+ return( ppNameArr[ePrep] );
+}
+
+/*************************************************************************
+ * SwLineLayout::DebugPortions()
+ *
+ * DebugPortion() iteriert ueber alle Portions einer Zeile und deckt die
+ * internen Strukturen auf.
+ * Im Gegensatz zum Ausgabe-Operator werden auch die Textteile ausgegeben.
+ *************************************************************************/
+
+void SwLineLayout::DebugPortions( SvStream &rOs, const XubString &/*rTxt*/, //$ ostream
+ const xub_StrLen /*nStart*/ )
+{
+ SwLinePortion *pPortion2 = GetPortion();
+
+ xub_StrLen nPos = 0;
+ MSHORT nNr = 0;
+ KSHORT nPrtWidth, nLastPrt;
+ nPrtWidth = nLastPrt = 0;
+
+ SwLinePortion::operator<<( rOs );
+ rOs << '\"' << endl;
+
+ while( pPortion2 )
+ {
+ SwTxtPortion *pTxtPor = pPortion2->InTxtGrp() ?
+ (SwTxtPortion *)pPortion2 : NULL ;
+ (void)pTxtPor;
+ ++nNr;
+ nLastPrt = nPrtWidth;
+ nPrtWidth = nPrtWidth + pPortion2->PrtWidth();
+ rOs << "\tNr:" << nNr
+ << " Pos:" << nPos
+ << " Org:" << nLastPrt
+ << endl;
+
+ rOs << "\t";
+ pPortion2->operator<<( rOs );
+ rOs << endl;
+ nPos = nPos + pPortion2->GetLen();
+ pPortion2 = pPortion2->GetPortion();
+ }
+}
+
+SvStream &SwLinePortion::operator<<( SvStream &rOs ) const //$ ostream
+{
+ rOs << " {";
+ rOs << "L:" << nLineLength;
+ rOs << " H:" << Height();
+ rOs << " W:" << PrtWidth();
+ rOs << " A:" << nAscent;
+ rOs << pClose;
+ return rOs;
+}
+
+SvStream &SwTxtPortion::operator<<( SvStream &rOs ) const //$ ostream
+{
+ CONSTCHAR( pTxt, " {TXT:" );
+ rOs << pTxt;
+ SwLinePortion::operator<<( rOs );
+ rOs << pClose;
+ return rOs;
+}
+
+SvStream &SwTmpEndPortion::operator<<( SvStream &rOs ) const //$ ostream
+{
+ CONSTCHAR( pTxt, " {END:" );
+ rOs << pTxt;
+ SwLinePortion::operator<<( rOs );
+ if( PrtWidth() )
+ rOs << "(view)";
+ rOs << pClose;
+ return rOs;
+}
+
+SvStream &SwBreakPortion::operator<<( SvStream &rOs ) const //$ ostream
+{
+ CONSTCHAR( pTxt, " {BREAK:" );
+ rOs << pTxt;
+ SwLinePortion::operator<<( rOs );
+ rOs << pClose;
+ return rOs;
+}
+
+SvStream &SwKernPortion::operator<<( SvStream &rOs ) const //$ ostream
+{
+ CONSTCHAR( pTxt, " {KERN:" );
+ rOs << pTxt;
+ SwLinePortion::operator<<( rOs );
+ rOs << pClose;
+ return rOs;
+}
+
+SvStream &SwArrowPortion::operator<<( SvStream &rOs ) const //$ ostream
+{
+ CONSTCHAR( pTxt, " {ARROW:" );
+ rOs << pTxt;
+ SwLinePortion::operator<<( rOs );
+ rOs << pClose;
+ return rOs;
+}
+
+SvStream &SwMultiPortion::operator<<( SvStream &rOs ) const //$ ostream
+{
+ CONSTCHAR( pTxt, " {MULTI:" );
+ rOs << pTxt;
+ SwLinePortion::operator<<( rOs );
+ rOs << pClose;
+ return rOs;
+}
+
+SvStream &SwCombinedPortion::operator<<( SvStream &rOs ) const //$ ostream
+{
+ CONSTCHAR( pTxt, " {COMBINED:" );
+ rOs << pTxt;
+ SwLinePortion::operator<<( rOs );
+ rOs << pClose;
+ return rOs;
+}
+
+SvStream &SwLineLayout::operator<<( SvStream &rOs ) const //$ ostream
+{
+ CONSTCHAR( pTxt, " {LINE:" );
+ rOs << pTxt;
+ SwLinePortion::operator<<( rOs );
+ SwLinePortion *pPos = GetPortion();
+ while( pPos )
+ {
+ rOs << "\t";
+ pPos->operator<<( rOs );
+ pPos = pPos->GetPortion();
+ }
+ rOs << pClose;
+ return rOs;
+}
+
+SvStream &SwGluePortion::operator<<( SvStream &rOs ) const //$ ostream
+{
+ CONSTCHAR( pTxt, " {GLUE:" );
+ rOs << pTxt;
+ SwLinePortion::operator<<( rOs );
+ rOs << " F:" << GetFixWidth();
+ rOs << " G:" << GetPrtGlue();
+ rOs << pClose;
+ return rOs;
+}
+
+SvStream &SwFixPortion::operator<<( SvStream &rOs ) const //$ ostream
+{
+ CONSTCHAR( pTxt, " {FIX:" );
+ rOs << pTxt;
+ SwGluePortion::operator<<( rOs );
+ rOs << " Fix:" << nFix;
+ rOs << pClose;
+ return rOs;
+}
+
+SvStream &SwFlyPortion::operator<<( SvStream &rOs ) const //$ ostream
+{
+ CONSTCHAR( pTxt, " {FLY:" );
+ rOs << pTxt;
+ SwFixPortion::operator<<( rOs );
+ rOs << pClose;
+ return rOs;
+}
+
+SvStream &SwMarginPortion::operator<<( SvStream &rOs ) const //$ ostream
+{
+ CONSTCHAR( pTxt, " {MAR:" );
+ rOs << pTxt;
+ SwGluePortion::operator<<( rOs );
+ rOs << pClose;
+ return rOs;
+}
+
+SvStream &SwFlyCntPortion::operator<<( SvStream &rOs ) const //$ ostream
+{
+ CONSTCHAR( pTxt, " {FLYCNT:" );
+ rOs << pTxt;
+ SwLinePortion::operator<<( rOs );
+ if( bDraw )
+ {
+ CONSTCHAR( pTxt2, " {DRAWINCNT" );
+ rOs << pTxt2;
+ rOs << pClose;
+ }
+ else
+ {
+ CONSTCHAR( pTxt2, " {FRM:" );
+ rOs << pTxt2;
+ rOs << " {FRM:" << GetFlyFrm()->Frm() << pClose;
+ rOs << " {PRT:" << GetFlyFrm()->Prt() << pClose;
+ rOs << pClose;
+ }
+ rOs << pClose;
+ return rOs;
+}
+
+SvStream &SwExpandPortion::operator<<( SvStream &rOs ) const //$ ostream
+{
+ CONSTCHAR( pTxt, " {EXP:" );
+ rOs << pTxt;
+ SwLinePortion::operator<<( rOs );
+ rOs << pClose;
+ return rOs;
+}
+
+SvStream &SwFtnPortion::operator<<( SvStream &rOs ) const //$ ostream
+{
+ CONSTCHAR( pTxt, " {FTN:" );
+ rOs << pTxt;
+ SwExpandPortion::operator<<( rOs );
+ rOs << pClose;
+ return rOs;
+}
+
+SvStream &SwFtnNumPortion::operator<<( SvStream &rOs ) const //$ ostream
+{
+ CONSTCHAR( pTxt, " {FTNNUM:" );
+ rOs << pTxt;
+ SwNumberPortion::operator<<( rOs );
+ rOs << pClose;
+ return rOs;
+}
+
+SvStream &SwNumberPortion::operator<<( SvStream &rOs ) const //$ ostream
+{
+ CONSTCHAR( pTxt, " {NUMBER:" );
+ rOs << pTxt;
+ SwExpandPortion::operator<<( rOs );
+ rOs << " Exp:\"" << '\"';
+ rOs << pClose;
+ return rOs;
+}
+
+SvStream &SwBulletPortion::operator<<( SvStream &rOs ) const //$ ostream
+{
+ CONSTCHAR( pTxt, " {BULLET:" );
+ rOs << pTxt;
+ SwNumberPortion::operator<<( rOs );
+ rOs << pClose;
+ return rOs;
+}
+
+SvStream &SwGrfNumPortion::operator<<( SvStream &rOs ) const //$ ostream
+{
+ CONSTCHAR( pTxt, " {GRFNUM:" );
+ rOs << pTxt;
+ SwNumberPortion::operator<<( rOs );
+ rOs << pClose;
+ return rOs;
+}
+
+SvStream &SwHiddenPortion::operator<<( SvStream &rOs ) const //$ ostream
+{
+ CONSTCHAR( pTxt, " {Hidden:" );
+ rOs << pTxt;
+ SwFldPortion::operator<<( rOs );
+ rOs << pClose;
+ return rOs;
+}
+
+SvStream &SwToxPortion::operator<<( SvStream &rOs ) const //$ ostream
+{
+ CONSTCHAR( pTxt, " {TOX:" );
+ rOs << pTxt;
+ SwTxtPortion::operator<<( rOs );
+ rOs << pClose;
+ return rOs;
+}
+
+SvStream &SwRefPortion::operator<<( SvStream &rOs ) const //$ ostream
+{
+ CONSTCHAR( pTxt, " {Ref:" );
+ rOs << pTxt;
+ SwTxtPortion::operator<<( rOs );
+ rOs << pClose;
+ return rOs;
+}
+
+SvStream &SwIsoToxPortion::operator<<( SvStream &rOs ) const //$ ostream
+{
+ CONSTCHAR( pTxt, " {ISOTOX:" );
+ rOs << pTxt;
+ SwToxPortion::operator<<( rOs );
+ rOs << pClose;
+ return rOs;
+}
+
+SvStream &SwIsoRefPortion::operator<<( SvStream &rOs ) const //$ ostream
+{
+ CONSTCHAR( pTxt, " {ISOREF:" );
+ rOs << pTxt;
+ SwRefPortion::operator<<( rOs );
+ rOs << pClose;
+ return rOs;
+}
+
+SvStream &SwHyphPortion::operator<<( SvStream &rOs ) const //$ ostream
+{
+ CONSTCHAR( pTxt, " {HYPH:" );
+ rOs << pTxt;
+ SwExpandPortion::operator<<( rOs );
+ rOs << pClose;
+ return rOs;
+}
+
+SvStream &SwHyphStrPortion::operator<<( SvStream &rOs ) const //$ ostream
+{
+ CONSTCHAR( pTxt, " {HYPHSTR:" );
+ rOs << pTxt;
+ SwExpandPortion::operator<<( rOs );
+ rOs << pClose;
+ return rOs;
+}
+
+SvStream &SwSoftHyphPortion::operator<<( SvStream &rOs ) const //$ ostream
+{
+ CONSTCHAR( pTxt, " {SOFTHYPH:" );
+ rOs << pTxt;
+ SwHyphPortion::operator<<( rOs );
+ rOs << (IsExpand() ? " on" : " off");
+ rOs << pClose;
+ return rOs;
+}
+
+SvStream &SwSoftHyphStrPortion::operator<<( SvStream &rOs ) const //$ ostream
+{
+ CONSTCHAR( pTxt, " {SOFTHYPHSTR:" );
+ rOs << pTxt;
+ SwHyphStrPortion::operator<<( rOs );
+ rOs << pClose;
+ return rOs;
+}
+
+SvStream &SwBlankPortion::operator<<( SvStream &rOs ) const //$ ostream
+{
+ CONSTCHAR( pTxt, " {BLANK:" );
+ rOs << pTxt;
+ SwExpandPortion::operator<<( rOs );
+ rOs << pClose;
+ return rOs;
+}
+
+SvStream &SwFldPortion::operator<<( SvStream &rOs ) const //$ ostream
+{
+ CONSTCHAR( pTxt, " {FLD:" );
+ rOs << pTxt;
+ SwLinePortion::operator<<( rOs );
+ if( IsFollow() )
+ rOs << " F!";
+ rOs << pClose;
+ return rOs;
+}
+
+SvStream &SwPostItsPortion::operator<<( SvStream &rOs ) const //$ ostream
+{
+ CONSTCHAR( pTxt, " {POSTITS" );
+ rOs << pTxt;
+ SwLinePortion::operator<<( rOs );
+ rOs << pClose;
+ return rOs;
+}
+
+SvStream &SwTabPortion::operator<<( SvStream &rOs ) const //$ ostream
+{
+ CONSTCHAR( pTxt, " {TAB" );
+ rOs << pTxt;
+ SwFixPortion::operator<<( rOs );
+ rOs << " T:" << nTabPos;
+ if( IsFilled() )
+ rOs << " \"" << cFill << '\"';
+ rOs << pClose;
+ return rOs;
+}
+
+SvStream &SwTabLeftPortion::operator<<( SvStream &rOs ) const //$ ostream
+{
+ CONSTCHAR( pTxt, " {TABLEFT" );
+ rOs << pTxt;
+ SwTabPortion::operator<<( rOs );
+ rOs << pClose;
+ return rOs;
+}
+
+SvStream &SwTabRightPortion::operator<<( SvStream &rOs ) const //$ ostream
+{
+ CONSTCHAR( pTxt, " {TABRIGHT" );
+ rOs << pTxt;
+ SwTabPortion::operator<<( rOs );
+ rOs << pClose;
+ return rOs;
+}
+
+SvStream &SwTabCenterPortion::operator<<( SvStream &rOs ) const //$ ostream
+{
+ CONSTCHAR( pTxt, " {TABCENTER" );
+ rOs << pTxt;
+ SwTabPortion::operator<<( rOs );
+ rOs << pClose;
+ return rOs;
+}
+
+SvStream &SwTabDecimalPortion::operator<<( SvStream &rOs ) const //$ ostream
+{
+ CONSTCHAR( pTxt, " {TABDECIMAL" );
+ rOs << pTxt;
+ SwTabPortion::operator<<( rOs );
+ rOs << pClose;
+ return rOs;
+}
+
+SvStream &SwParaPortion::operator<<( SvStream &rOs ) const //$ ostream
+{
+ CONSTCHAR( pTxt, " {PAR" );
+ rOs << pTxt;
+ SwLineLayout::operator<<( rOs );
+ rOs << pClose;
+ return rOs;
+}
+
+SvStream &SwHolePortion::operator<<( SvStream &rOs ) const //$ ostream
+{
+ CONSTCHAR( pTxt, " {HOLE" );
+ rOs << pTxt;
+ SwLinePortion::operator<<( rOs );
+ rOs << pClose;
+ return rOs;
+}
+
+SvStream &SwQuoVadisPortion::operator<<( SvStream &rOs ) const //$ ostream
+{
+ CONSTCHAR( pTxt, " {QUOVADIS" );
+ rOs << pTxt;
+ SwFldPortion::operator<<( rOs );
+ rOs << pClose;
+ return rOs;
+}
+
+SvStream &SwErgoSumPortion::operator<<( SvStream &rOs ) const //$ ostream
+{
+ CONSTCHAR( pTxt, " {ERGOSUM" );
+ rOs << pTxt;
+ SwFldPortion::operator<<( rOs );
+ rOs << pClose;
+ return rOs;
+}
+
+SvStream &operator<<( SvStream &rOs, const SwTxtSizeInfo &rInf ) //$ ostream
+{
+ CONSTCHAR( pTxt, " {SIZEINFO:" );
+ rOs << pTxt;
+ rOs << ' ' << (rInf.OnWin() ? "WIN:" : "PRT:" );
+ rOs << " Idx:" << rInf.GetIdx();
+ rOs << " Len:" << rInf.GetLen();
+ rOs << pClose;
+ return rOs;
+}
+
+SvStream &SwDropPortion::operator<<( SvStream &rOs ) const //$ ostream
+{
+ CONSTCHAR( pTxt, " {DROP:" );
+ rOs << pTxt;
+ SwTxtPortion::operator<<( rOs );
+ if( pPart && nDropHeight )
+ {
+ rOs << " H:" << nDropHeight;
+ rOs << " L:" << nLines;
+ rOs <<" Fnt:" << pPart->GetFont().GetHeight();
+ if( nX || nY )
+ rOs << " [" << nX << '/' << nY << ']';
+ }
+ rOs << pClose;
+ return rOs;
+}
+
+#endif
+
+#endif /* OSL_DEBUG_LEVEL */
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/text/txtpaint.cxx b/sw/source/core/text/txtpaint.cxx
new file mode 100644
index 000000000000..2d4e5fec170f
--- /dev/null
+++ b/sw/source/core/text/txtpaint.cxx
@@ -0,0 +1,135 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+#include "txtpaint.hxx"
+#include "swrect.hxx"
+#include "rootfrm.hxx"
+
+/*************************************************************************
+ * SwSaveClip::Reset()
+ *************************************************************************/
+
+void SwSaveClip::Reset()
+{
+ // Der alte Zustand wird wieder hergestellt.
+ if( pOut && bChg )
+ {
+ if ( pOut->GetConnectMetaFile() )
+ pOut->Pop();
+ else
+ {
+ if( bOn )
+ pOut->SetClipRegion( aClip );
+ else
+ pOut->SetClipRegion();
+ }
+ bChg = sal_False;
+ }
+}
+
+/*************************************************************************
+ * SwSaveClip::_ChgClip()
+ *************************************************************************/
+
+void SwSaveClip::_ChgClip( const SwRect &rRect, const SwTxtFrm* pFrm,
+ sal_Bool bEnlargeRect )
+{
+ SwRect aOldRect( rRect );
+ const sal_Bool bVertical = pFrm && pFrm->IsVertical();
+
+ if ( pFrm && pFrm->IsRightToLeft() )
+ pFrm->SwitchLTRtoRTL( (SwRect&)rRect );
+
+ if ( bVertical )
+ pFrm->SwitchHorizontalToVertical( (SwRect&)rRect );
+
+ if ( !pOut || (!rRect.HasArea() && !pOut->IsClipRegion()) )
+ {
+ (SwRect&)rRect = aOldRect;
+ return;
+ }
+
+ if ( !bChg )
+ {
+ if ( pOut->GetConnectMetaFile() )
+ pOut->Push();
+ else if ( bOn )
+ aClip = pOut->GetClipRegion();
+ }
+
+ if ( !rRect.HasArea() )
+ pOut->SetClipRegion();
+ else
+ {
+ Rectangle aRect( rRect.SVRect() );
+
+ // Having underscores in our line, we enlarged the repaint area
+ // (see frmform.cxx) because for some fonts it could be too small.
+ // Consequently, we have to enlarge the clipping rectangle as well.
+ if ( bEnlargeRect && ! bVertical )
+ aRect.Bottom() += 40;
+
+ // Wenn das ClipRect identisch ist, passiert nix.
+ if( pOut->IsClipRegion() ) // kein && wg Mac
+ {
+ if ( aRect == pOut->GetClipRegion().GetBoundRect() )
+ {
+ (SwRect&)rRect = aOldRect;
+ return;
+ }
+ }
+
+ if( SwRootFrm::HasSameRect( rRect ) )
+ pOut->SetClipRegion();
+ else
+ {
+ const Region aClipRegion( aRect );
+ pOut->SetClipRegion( aClipRegion );
+#if OSL_DEBUG_LEVEL > 1
+ Rectangle aDbgRect = pOut->GetClipRegion().GetBoundRect();
+#endif
+ }
+#if OSL_DEBUG_LEVEL > 1
+ static sal_Bool bDbg = sal_False;
+ if( bDbg )
+ {
+ DbgBackColor aDbg( pOut, bDbg, COL_RED );
+ pOut->DrawRect( aRect );
+ }
+#endif
+ }
+ bChg = sal_True;
+
+ (SwRect&)rRect = aOldRect;
+}
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/text/txtpaint.hxx b/sw/source/core/text/txtpaint.hxx
new file mode 100644
index 000000000000..0a7a36beda48
--- /dev/null
+++ b/sw/source/core/text/txtpaint.hxx
@@ -0,0 +1,194 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+#ifndef _TXTPAINT_HXX
+#define _TXTPAINT_HXX
+#include <vcl/outdev.hxx>
+
+class SwRect; // SwSaveClip
+#include <txtfrm.hxx>
+
+/*************************************************************************
+ * class SwSaveClip
+ *************************************************************************/
+
+class SwSaveClip
+{
+ Region aClip;
+ const sal_Bool bOn;
+ sal_Bool bChg;
+protected:
+ OutputDevice* pOut;
+ void _ChgClip( const SwRect &rRect, const SwTxtFrm* pFrm,
+ sal_Bool bEnlargeRect );
+public:
+ inline SwSaveClip( OutputDevice* pOut );
+ inline ~SwSaveClip();
+ inline void ChgClip( const SwRect &rRect, const SwTxtFrm* pFrm = 0,
+ sal_Bool bEnlargeRect = sal_False)
+ { if( pOut ) _ChgClip( rRect, pFrm, bEnlargeRect ); }
+ void Reset();
+ inline sal_Bool IsOn() const { return bOn; }
+ inline sal_Bool IsChg() const { return bChg; }
+ inline sal_Bool IsOut() const { return 0 != pOut; }
+ inline OutputDevice *GetOut() { return pOut; }
+};
+
+inline SwSaveClip::SwSaveClip( OutputDevice* pOutDev ) :
+ bOn( pOutDev && pOutDev->IsClipRegion() ),
+ bChg( sal_False ),
+ pOut(pOutDev)
+{}
+
+inline SwSaveClip::~SwSaveClip()
+{
+ Reset();
+}
+
+#if OSL_DEBUG_LEVEL > 1
+
+/*************************************************************************
+ * class SwDbgOut
+ *************************************************************************/
+
+class SwDbgOut
+{
+protected:
+ OutputDevice* pOut;
+public:
+ inline SwDbgOut( OutputDevice* pOutDev, const sal_Bool bOn = sal_True );
+};
+
+/*************************************************************************
+ * class DbgColor
+ *************************************************************************/
+
+class DbgColor
+{
+ Font *pFnt;
+ Color aColor;
+public:
+ inline DbgColor( Font *pFont, const sal_Bool bOn = sal_True,
+ const ColorData eColor = COL_BLUE );
+ inline ~DbgColor();
+};
+
+/*************************************************************************
+ * class DbgBrush
+ *************************************************************************/
+
+class DbgBackColor : public SwDbgOut
+{
+ Color aOldFillColor;
+public:
+ DbgBackColor( OutputDevice* pOut, const sal_Bool bOn = sal_True,
+ ColorData nColor = COL_YELLOW );
+ ~DbgBackColor();
+};
+
+/*************************************************************************
+ * class DbgRect
+ *************************************************************************/
+
+class DbgRect : public SwDbgOut
+{
+public:
+ DbgRect( OutputDevice* pOut, const Rectangle &rRect,
+ const sal_Bool bOn = sal_True,
+ ColorData eColor = COL_LIGHTBLUE );
+};
+
+/*************************************************************************
+ * Inline-Implementierung
+ *************************************************************************/
+
+inline SwDbgOut::SwDbgOut( OutputDevice* pOutDev, const sal_Bool bOn )
+ :pOut( bOn ? pOutDev : 0 )
+{ }
+
+
+inline DbgColor::DbgColor( Font *pFont, const sal_Bool bOn,
+ const ColorData eColor )
+ :pFnt( bOn ? pFont : 0 )
+{
+ if( pFnt )
+ {
+ aColor = pFnt->GetColor();
+ pFnt->SetColor( Color( eColor ) );
+ }
+}
+
+inline DbgColor::~DbgColor()
+{
+ if( pFnt )
+ pFnt->SetColor( aColor );
+}
+
+inline DbgBackColor::DbgBackColor( OutputDevice* pOutDev, const sal_Bool bOn,
+ ColorData eColor )
+ :SwDbgOut( pOutDev, bOn )
+{
+ if( pOut )
+ {
+ aOldFillColor = pOut->GetFillColor();
+ pOut->SetFillColor( Color(eColor) );
+ }
+}
+
+inline DbgBackColor::~DbgBackColor()
+{
+ if( pOut )
+ {
+ pOut->SetFillColor( aOldFillColor );
+ }
+}
+
+inline DbgRect::DbgRect( OutputDevice* pOutDev, const Rectangle &rRect,
+ const sal_Bool bOn,
+ ColorData eColor )
+ : SwDbgOut( pOutDev, bOn )
+{
+ if( pOut )
+ {
+ const Color aColor( eColor );
+ Color aLineColor = pOut->GetLineColor();
+ pOut->SetLineColor( aColor );
+ Color aFillColor = pOut->GetFillColor();
+ pOut->SetFillColor( Color(COL_TRANSPARENT) );
+ pOut->DrawRect( rRect );
+ pOut->SetLineColor( aLineColor );
+ pOut->SetFillColor( aFillColor );
+ }
+}
+
+#endif
+
+
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/text/txttab.cxx b/sw/source/core/text/txttab.cxx
new file mode 100644
index 000000000000..6d74f36eeaa6
--- /dev/null
+++ b/sw/source/core/text/txttab.cxx
@@ -0,0 +1,679 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+#include "hintids.hxx"
+#include <editeng/lrspitem.hxx>
+#include <editeng/tstpitem.hxx>
+#include <IDocumentSettingAccess.hxx>
+#include <frmatr.hxx>
+#include <SwPortionHandler.hxx>
+
+#include "viewopt.hxx" // SwViewOptions
+#include "portab.hxx"
+#include "inftxt.hxx"
+#include "itrform2.hxx"
+#include "txtfrm.hxx"
+#include <numrule.hxx>
+// --> OD 2008-06-05 #i89179#
+#include <porfld.hxx>
+// <--
+
+
+/*************************************************************************
+ * SwLineInfo::GetTabStop()
+ *************************************************************************/
+
+//#i24363# tab stops relative to indent
+/* Return the first tab stop that is > nSearchPos.
+ * If the tab stop is outside the print area, we
+ * return 0 if it is not the first tab stop.*/
+const SvxTabStop *SwLineInfo::GetTabStop( const SwTwips nSearchPos,
+ const SwTwips nRight ) const
+{
+ for( MSHORT i = 0; i < pRuler->Count(); ++i )
+ {
+ const SvxTabStop &rTabStop = pRuler->operator[](i);
+ if( rTabStop.GetTabPos() > SwTwips(nRight) )
+ return i ? 0 : &rTabStop;
+
+ if( rTabStop.GetTabPos() > nSearchPos )
+ return &rTabStop;
+ }
+ return 0;
+}
+
+/*************************************************************************
+ * SwLineInfo::NumberOfTabStops()
+ *************************************************************************/
+
+sal_uInt16 SwLineInfo::NumberOfTabStops() const
+{
+ return pRuler->Count();
+}
+
+/*************************************************************************
+ * SwTxtFormatter::NewTabPortion()
+ *************************************************************************/
+SwTabPortion *SwTxtFormatter::NewTabPortion( SwTxtFormatInfo &rInf, bool bAuto ) const
+{
+ SwTabPortion *pTabPor = 0;
+ SwTabPortion *pLastTab = rInf.GetLastTab();
+ if( pLastTab && ( pLastTab->IsTabCntPortion() || pLastTab->IsTabDecimalPortion() ) )
+ if( pLastTab->PostFormat( rInf ) )
+ return 0;
+
+ xub_Unicode cFill = 0;
+ xub_Unicode cDec = 0;
+ SvxTabAdjust eAdj;
+
+ KSHORT nNewTabPos;
+ {
+ const bool bRTL = pFrm->IsRightToLeft();
+ // #i24363# tab stops relative to indent
+ // nTabLeft: The absolute value, the tab stops are relative to: Tabs origin.
+ //
+ // --> OD 2008-07-01 #i91133#
+ const bool bTabsRelativeToIndent =
+ pFrm->GetTxtNode()->getIDocumentSettingAccess()->get(IDocumentSettingAccess::TABS_RELATIVE_TO_INDENT);
+ const SwTwips nTabLeft = bRTL
+ ? pFrm->Frm().Right() -
+ ( bTabsRelativeToIndent ? GetTabLeft() : 0 )
+ : pFrm->Frm().Left() +
+ ( bTabsRelativeToIndent ? GetTabLeft() : 0 );
+ // <--
+
+ //
+ // nLinePos: The absolute position, where we started the line formatting.
+ //
+ SwTwips nLinePos = GetLeftMargin();
+ if ( bRTL )
+ {
+ Point aPoint( nLinePos, 0 );
+ pFrm->SwitchLTRtoRTL( aPoint );
+ nLinePos = aPoint.X();
+ }
+
+ //
+ // nTabPos: The current position, relative to the line start.
+ //
+ SwTwips nTabPos = rInf.GetLastTab() ? rInf.GetLastTab()->GetTabPos() : 0;
+ if( nTabPos < rInf.X() )
+ {
+ nTabPos = rInf.X();
+ }
+
+ //
+ // nCurrentAbsPos: The current position in absolute coordinates.
+ //
+ const SwTwips nCurrentAbsPos = bRTL ?
+ nLinePos - nTabPos :
+ nLinePos + nTabPos;
+
+ //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin
+ SwTwips nMyRight;
+ if ( pFrm->IsVertLR() )
+ nMyRight = Left();
+ else
+ nMyRight = Right();
+
+ if ( pFrm->IsVertical() )
+ {
+ Point aRightTop( nMyRight, pFrm->Frm().Top() );
+ pFrm->SwitchHorizontalToVertical( aRightTop );
+ nMyRight = aRightTop.Y();
+ }
+
+ SwTwips nNextPos;
+
+ // #i24363# tab stops relative to indent
+ // nSearchPos: The current position relative to the tabs origin.
+ //
+ const SwTwips nSearchPos = bRTL ?
+ nTabLeft - nCurrentAbsPos :
+ nCurrentAbsPos - nTabLeft;
+
+ //
+ // First, we examine the tab stops set at the paragraph style or
+ // any hard set tab stops:
+ // Note: If there are no user defined tab stops, there is always a
+ // default tab stop.
+ //
+ const SvxTabStop* pTabStop =
+ aLineInf.GetTabStop( nSearchPos, nMyRight );
+ if( pTabStop )
+ {
+ cFill = ' ' != pTabStop->GetFill() ? pTabStop->GetFill() : 0;
+ cDec = pTabStop->GetDecimal();
+ eAdj = pTabStop->GetAdjustment();
+ nNextPos = pTabStop->GetTabPos();
+ if(!bTabsRelativeToIndent && eAdj == SVX_TAB_ADJUST_DEFAULT && nSearchPos < 0)
+ {
+ //calculate default tab position of default tabs in negative indent
+ nNextPos = ( nSearchPos / nNextPos ) * nNextPos;
+ }
+ }
+ else
+ {
+ KSHORT nDefTabDist = aLineInf.GetDefTabStop();
+ if( KSHRT_MAX == nDefTabDist )
+ {
+ const SvxTabStopItem& rTab =
+ (const SvxTabStopItem &)pFrm->GetAttrSet()->
+ GetPool()->GetDefaultItem( RES_PARATR_TABSTOP );
+ if( rTab.Count() )
+ nDefTabDist = (KSHORT)rTab.GetStart()->GetTabPos();
+ else
+ nDefTabDist = SVX_TAB_DEFDIST;
+ aLineInf.SetDefTabStop( nDefTabDist );
+ }
+ SwTwips nCount = nSearchPos;
+
+ //Minimum tab stop width is 1
+ if (nDefTabDist <= 0)
+ nDefTabDist = 1;
+
+ nCount /= nDefTabDist;
+ nNextPos = nCount < 0 || (!nCount && nSearchPos <= 0)? nCount * nDefTabDist :( nCount + 1 ) * nDefTabDist ;
+ // --> FME 2004-09-21 #117919 Minimum tab stop width is 1 or 51 twips:
+ const SwTwips nMinimumTabWidth = pFrm->GetTxtNode()->getIDocumentSettingAccess()->get(IDocumentSettingAccess::TAB_COMPAT) ? 0 : 50;
+ // <--
+ if( ( bRTL && nTabLeft - nNextPos >= nCurrentAbsPos - nMinimumTabWidth ) ||
+ ( !bRTL && nNextPos + nTabLeft <= nCurrentAbsPos + nMinimumTabWidth ) )
+ {
+ nNextPos += nDefTabDist;
+ }
+ cFill = 0;
+ eAdj = SVX_TAB_ADJUST_LEFT;
+ }
+
+ // #i115705# - correction and refactoring:
+ // overrule determined next tab stop position in order to apply
+ // a tab stop at the left margin under the following conditions:
+ // - the new tab portion is inside the hanging indent
+ // - a tab stop at the left margin is allowed
+ // - the determined next tab stop is a default tab stop position OR
+ // the determined next tab stop is beyond the left margin
+ {
+ long nLeftMarginTabPos = 0;
+ {
+ if ( !bTabsRelativeToIndent )
+ {
+ if ( bRTL )
+ {
+ Point aPoint( Left(), 0 );
+ pFrm->SwitchLTRtoRTL( aPoint );
+ nLeftMarginTabPos = pFrm->Frm().Right() - aPoint.X();
+ }
+ else
+ {
+ nLeftMarginTabPos = Left() - pFrm->Frm().Left();
+ }
+ }
+ if( pCurr->HasForcedLeftMargin() )
+ {
+ SwLinePortion* pPor = pCurr->GetPortion();
+ while( pPor && !pPor->IsFlyPortion() )
+ {
+ pPor = pPor->GetPortion();
+ }
+ if ( pPor )
+ {
+ nLeftMarginTabPos += pPor->Width();
+ }
+ }
+ }
+ const bool bNewTabPortionInsideHangingIndent =
+ bRTL ? nCurrentAbsPos > nTabLeft - nLeftMarginTabPos
+ : nCurrentAbsPos < nTabLeft + nLeftMarginTabPos;
+ if ( bNewTabPortionInsideHangingIndent )
+ {
+ // If the paragraph is not inside a list having a list tab stop following
+ // the list label or no further tab stop found in such a paragraph or
+ // the next tab stop position does not equal the list tab stop,
+ // a tab stop at the left margin can be applied. If this condition is
+ // not hold, it is overruled by compatibility option TAB_AT_LEFT_INDENT_FOR_PARA_IN_LIST.
+ const bool bTabAtLeftMarginAllowed =
+ ( !aLineInf.IsListTabStopIncluded() ||
+ !pTabStop ||
+ nNextPos != aLineInf.GetListTabStopPosition() ) ||
+ // compatibility option TAB_AT_LEFT_INDENT_FOR_PARA_IN_LIST:
+ pFrm->GetTxtNode()->getIDocumentSettingAccess()->
+ get(IDocumentSettingAccess::TAB_AT_LEFT_INDENT_FOR_PARA_IN_LIST);
+ if ( bTabAtLeftMarginAllowed )
+ {
+ if ( !pTabStop || eAdj == SVX_TAB_ADJUST_DEFAULT ||
+ ( nNextPos > nLeftMarginTabPos ) )
+ {
+ eAdj = SVX_TAB_ADJUST_DEFAULT;
+ cFill = 0;
+ nNextPos = nLeftMarginTabPos;
+ }
+ }
+ }
+ }
+
+ nNextPos += bRTL ? nLinePos - nTabLeft : nTabLeft - nLinePos;
+ OSL_ENSURE( nNextPos >= 0, "GetTabStop: Don't go back!" );
+ nNewTabPos = KSHORT(nNextPos);
+ }
+
+ if ( bAuto )
+ {
+ if ( SVX_TAB_ADJUST_DECIMAL == eAdj &&
+ // --> FME 2005-12-19 #127428#
+ 1 == aLineInf.NumberOfTabStops() )
+ // <--
+ pTabPor = new SwAutoTabDecimalPortion( nNewTabPos, cDec, cFill );
+ }
+ else
+ {
+ switch( eAdj )
+ {
+ case SVX_TAB_ADJUST_RIGHT :
+ {
+ pTabPor = new SwTabRightPortion( nNewTabPos, cFill );
+ break;
+ }
+ case SVX_TAB_ADJUST_CENTER :
+ {
+ pTabPor = new SwTabCenterPortion( nNewTabPos, cFill );
+ break;
+ }
+ case SVX_TAB_ADJUST_DECIMAL :
+ {
+ pTabPor = new SwTabDecimalPortion( nNewTabPos, cDec, cFill );
+ break;
+ }
+ default:
+ {
+ OSL_ENSURE( SVX_TAB_ADJUST_LEFT == eAdj || SVX_TAB_ADJUST_DEFAULT == eAdj,
+ "+SwTxtFormatter::NewTabPortion: unknown adjustment" );
+ pTabPor = new SwTabLeftPortion( nNewTabPos, cFill );
+ break;
+ }
+ }
+ }
+
+ // Vorhandensein von Tabulatoren anzeigen ... ist nicht mehr noetig
+ // pCurr->SetTabulation();
+ // Aus Sicherheitsgruenden lassen wir uns die Daten errechnen
+ // pTabPor->Height( pLast->Height() );
+ // pTabPor->SetAscent( pLast->GetAscent() );
+ return pTabPor;
+}
+
+/*************************************************************************
+ * SwTabPortion::SwTabPortion()
+ *************************************************************************/
+
+// Die Basisklasse wird erstmal ohne alles initialisiert.
+
+
+SwTabPortion::SwTabPortion( const KSHORT nTabPosition, const xub_Unicode cFillChar )
+ : SwFixPortion( 0, 0 ), nTabPos(nTabPosition), cFill(cFillChar)
+{
+ nLineLength = 1;
+#if OSL_DEBUG_LEVEL > 1
+ if( IsFilled() )
+ {
+ OSL_ENSURE( ' ' != cFill, "SwTabPortion::CTOR: blanks ?!" );
+ }
+#endif
+ SetWhichPor( POR_TAB );
+}
+
+/*************************************************************************
+ * virtual SwTabPortion::Format()
+ *************************************************************************/
+
+
+
+sal_Bool SwTabPortion::Format( SwTxtFormatInfo &rInf )
+{
+ SwTabPortion *pLastTab = rInf.GetLastTab();
+ if( pLastTab == this )
+ return PostFormat( rInf );
+ if( pLastTab )
+ pLastTab->PostFormat( rInf );
+ return PreFormat( rInf );
+}
+
+/*************************************************************************
+ * virtual SwTabPortion::FormatEOL()
+ *************************************************************************/
+
+
+
+void SwTabPortion::FormatEOL( SwTxtFormatInfo &rInf )
+{
+ if( rInf.GetLastTab() == this && !IsTabLeftPortion() )
+ PostFormat( rInf );
+}
+
+/*************************************************************************
+ * SwTabPortion::PreFormat()
+ *************************************************************************/
+
+
+
+sal_Bool SwTabPortion::PreFormat( SwTxtFormatInfo &rInf )
+{
+ OSL_ENSURE( rInf.X() <= GetTabPos(), "SwTabPortion::PreFormat: rush hour" );
+
+ // Hier lassen wir uns nieder...
+ Fix( static_cast<sal_uInt16>(rInf.X()) );
+
+ const bool bTabCompat = rInf.GetTxtFrm()->GetTxtNode()->getIDocumentSettingAccess()->get(IDocumentSettingAccess::TAB_COMPAT);
+
+ // Die Mindestbreite eines Tabs ist immer mindestens ein Blank
+ // --> FME 2004-11-25 #i37686# In compatibility mode, the minimum width
+ // should be 1, even for non-left tab stops.
+ sal_uInt16 nMinimumTabWidth = 1;
+ // <--
+ if ( !bTabCompat )
+ {
+ // --> OD 2008-06-05 #i89179#
+ // tab portion representing the list tab of a list label gets the
+ // same font as the corresponding number portion
+ std::auto_ptr< SwFontSave > pSave( 0 );
+ if ( GetLen() == 0 &&
+ rInf.GetLast() && rInf.GetLast()->InNumberGrp() &&
+ static_cast<SwNumberPortion*>(rInf.GetLast())->HasFont() )
+ {
+ const SwFont* pNumberPortionFont =
+ static_cast<SwNumberPortion*>(rInf.GetLast())->GetFont();
+ pSave.reset( new SwFontSave( rInf, const_cast<SwFont*>(pNumberPortionFont) ) );
+ }
+ // <--
+ XubString aTmp( ' ' );
+ SwTxtSizeInfo aInf( rInf, aTmp );
+ nMinimumTabWidth = aInf.GetTxtSize().Width();
+ }
+ PrtWidth( nMinimumTabWidth );
+
+ // Break tab stop to next line if:
+ // 1. Minmal width does not fit to line anymore.
+ // 2. An underflow event was called for the tab portion.
+ sal_Bool bFull = ( bTabCompat && rInf.IsUnderFlow() ) ||
+ rInf.Width() <= rInf.X() + PrtWidth();
+
+ // #95477# Rotated tab stops get the width of one blank
+ const sal_uInt16 nDir = rInf.GetFont()->GetOrientation( rInf.GetTxtFrm()->IsVertical() );
+
+ if( ! bFull && 0 == nDir )
+ {
+ const MSHORT nWhich = GetWhichPor();
+ switch( nWhich )
+ {
+ case POR_TABRIGHT:
+ case POR_TABDECIMAL:
+ case POR_TABCENTER:
+ {
+ if( POR_TABDECIMAL == nWhich )
+ rInf.SetTabDecimal(
+ ((SwTabDecimalPortion*)this)->GetTabDecimal());
+ rInf.SetLastTab( this );
+ break;
+ }
+ case POR_TABLEFT:
+ {
+ PrtWidth( static_cast<sal_uInt16>(GetTabPos() - rInf.X()) );
+ bFull = rInf.Width() <= rInf.X() + PrtWidth();
+
+ // In tabulator compatibility mode, we reset the bFull flag
+ // if the tabulator is at the end of the paragraph and the
+ // tab stop position is outside the frame:
+ if ( bFull && bTabCompat &&
+ rInf.GetIdx() + GetLen() == rInf.GetTxt().Len() &&
+ GetTabPos() >= rInf.GetTxtFrm()->Frm().Width() )
+ bFull = sal_False;
+
+ break;
+ }
+ default: OSL_ENSURE( !this, "SwTabPortion::PreFormat: unknown adjustment" );
+ }
+ }
+
+ if( bFull )
+ {
+ // Wir muessen aufpassen, dass wir nicht endlos schleifen,
+ // wenn die Breite kleiner ist, als ein Blank ...
+ if( rInf.GetIdx() == rInf.GetLineStart() &&
+ // --> FME 2005-01-19 #119175# TabStop should be forced to current
+ // line if there is a fly reducing the line width:
+ !rInf.GetFly() )
+ // <--
+ {
+ PrtWidth( static_cast<sal_uInt16>(rInf.Width() - rInf.X()) );
+ SetFixWidth( PrtWidth() );
+ }
+ else
+ {
+ Height( 0 );
+ Width( 0 );
+ SetLen( 0 );
+ SetAscent( 0 );
+ SetPortion( NULL ); //?????
+ }
+ return sal_True;
+ }
+ else
+ {
+ // Ein Kunstgriff mit Effekt: Die neuen Tabportions verhalten sich nun
+ // so, wie FlyFrms, die in der Zeile stehen - inklusive Adjustment !
+ SetFixWidth( PrtWidth() );
+ return sal_False;
+ }
+}
+
+/*************************************************************************
+ * SwTabPortion::PostFormat()
+ *************************************************************************/
+
+
+
+sal_Bool SwTabPortion::PostFormat( SwTxtFormatInfo &rInf )
+{
+ const KSHORT nRight = Min( GetTabPos(), rInf.Width() );
+ const SwLinePortion *pPor = GetPortion();
+
+ KSHORT nPorWidth = 0;
+ while( pPor )
+ {
+ nPorWidth = nPorWidth + pPor->Width();
+ pPor = pPor->GetPortion();
+ }
+
+ const MSHORT nWhich = GetWhichPor();
+ OSL_ENSURE( POR_TABLEFT != nWhich, "SwTabPortion::PostFormat: already formatted" );
+ const bool bTabCompat = rInf.GetTxtFrm()->GetTxtNode()->getIDocumentSettingAccess()->get(IDocumentSettingAccess::TAB_COMPAT);
+
+ // --> FME 2005-12-19 #127428# Abandon dec. tab position if line is full:
+ if ( bTabCompat && POR_TABDECIMAL == nWhich )
+ {
+ KSHORT nPrePorWidth = static_cast<const SwTabDecimalPortion*>(this)->GetWidthOfPortionsUpToDecimalPosition();
+
+ // no value was set => no decimal character was found
+ if ( USHRT_MAX != nPrePorWidth )
+ {
+ if ( nPrePorWidth && nPorWidth - nPrePorWidth > rInf.Width() - nRight )
+ {
+ nPrePorWidth += nPorWidth - nPrePorWidth - ( rInf.Width() - nRight );
+ }
+
+ nPorWidth = nPrePorWidth - 1;
+ }
+ }
+ // <--
+
+ if( POR_TABCENTER == nWhich )
+ {
+ // zentrierte Tabs bereiten Probleme:
+ // Wir muessen den Anteil herausfinden, der noch auf die Zeile passt.
+ KSHORT nNewWidth = nPorWidth /2;
+ if( nNewWidth > rInf.Width() - nRight )
+ nNewWidth = nPorWidth - (rInf.Width() - nRight);
+ nPorWidth = nNewWidth;
+ }
+
+ const KSHORT nDiffWidth = nRight - Fix();
+
+ if( nDiffWidth > nPorWidth )
+ {
+ const KSHORT nOldWidth = GetFixWidth();
+ const KSHORT nAdjDiff = nDiffWidth - nPorWidth;
+ if( nAdjDiff > GetFixWidth() )
+ PrtWidth( nAdjDiff );
+ // Nicht erschrecken: wir muessen rInf weiterschieben.
+ // Immerhin waren wir als Rechtstab bislang nur ein Blank breit.
+ // Da wir uns jetzt aufgespannt haben, muss der Differenzbetrag
+ // auf rInf.X() addiert werden !
+ rInf.X( rInf.X() + PrtWidth() - nOldWidth );
+ }
+ SetFixWidth( PrtWidth() );
+ // letzte Werte zuruecksetzen
+ rInf.SetLastTab(0);
+ if( POR_TABDECIMAL == nWhich )
+ rInf.SetTabDecimal(0);
+
+ return rInf.Width() <= rInf.X();
+}
+
+/*************************************************************************
+ * virtual SwTabPortion::Paint()
+ *
+ * Ex: LineIter::DrawTab()
+ *************************************************************************/
+
+void SwTabPortion::Paint( const SwTxtPaintInfo &rInf ) const
+{
+#if OSL_DEBUG_LEVEL > 1
+ // Wir wollen uns die Fixbreite anzeigen
+ if( rInf.OnWin() && OPTDBG( rInf ) &&
+ !rInf.GetOpt().IsPagePreview() && \
+ !rInf.GetOpt().IsReadonly() && \
+ SwViewOption::IsFieldShadings() )
+ {
+ const KSHORT nTmpWidth = PrtWidth();
+ ((SwTabPortion*)this)->PrtWidth( GetFixWidth() );
+ rInf.DrawViewOpt( *this, POR_TAB );
+ ((SwTabPortion*)this)->PrtWidth( nTmpWidth );
+ }
+#endif
+
+ // --> OD 2008-06-05 #i89179#
+ // tab portion representing the list tab of a list label gets the
+ // same font as the corresponding number portion
+ std::auto_ptr< SwFontSave > pSave( 0 );
+ if ( GetLen() == 0 )
+ {
+ const SwLinePortion* pPrevPortion =
+ const_cast<SwTabPortion*>(this)->FindPrevPortion( rInf.GetParaPortion() );
+ if ( pPrevPortion &&
+ pPrevPortion->InNumberGrp() &&
+ static_cast<const SwNumberPortion*>(pPrevPortion)->HasFont() )
+ {
+ const SwFont* pNumberPortionFont =
+ static_cast<const SwNumberPortion*>(pPrevPortion)->GetFont();
+ pSave.reset( new SwFontSave( rInf, const_cast<SwFont*>(pNumberPortionFont) ) );
+ }
+ }
+ // <--
+ rInf.DrawBackBrush( *this );
+
+ // do we have to repaint a post it portion?
+ if( rInf.OnWin() && pPortion && !pPortion->Width() )
+ pPortion->PrePaint( rInf, this );
+
+ // Darstellung von Sonderzeichen
+ if( rInf.OnWin() && rInf.GetOpt().IsTab() )
+ {
+ // gefuellte Tabs werden grau hinterlegt.
+ if( IsFilled() )
+ rInf.DrawViewOpt( *this, POR_TAB );
+ else
+ rInf.DrawTab( *this );
+ }
+
+ // 6842: Tabs sollen auf einmal wieder unterstrichen werden.
+ if( rInf.GetFont()->IsPaintBlank() )
+ {
+ // Tabs mit Fuellung
+ XubString aTxt( ' ' );
+ const KSHORT nCharWidth = rInf.GetTxtSize( aTxt ).Width();
+ // robust:
+ if( nCharWidth )
+ {
+ // 6864: immer mit Kerning, auch auf dem Drucker!
+ KSHORT nChar = Width() / nCharWidth;
+ rInf.DrawText( aTxt.Fill( nChar, ' ' ), *this, 0, nChar, sal_True );
+ }
+ }
+
+ // Ausgabe von Fuellzeichen
+ if( IsFilled() )
+ {
+ // Tabs mit Fuellung
+ XubString aTxt( cFill );
+ const KSHORT nCharWidth = rInf.GetTxtSize( aTxt ).Width();
+#if OSL_DEBUG_LEVEL > 1
+ OSL_ENSURE( nCharWidth, "!SwTabPortion::Paint: sophisticated tabchar" );
+#endif
+ // robust:
+ if( nCharWidth )
+ {
+ // 6864: immer mit Kerning, auch auf dem Drucker!
+ KSHORT nChar = Width() / nCharWidth;
+ if ( cFill == '_' )
+ ++nChar; // damit keine Luecken entstehen (Bug 13430)
+ rInf.DrawText( aTxt.Fill( nChar, cFill ), *this, 0, nChar, sal_True );
+ }
+ }
+}
+
+/*************************************************************************
+ * virtual SwAutoTabDecimalPortion::Paint()
+ *************************************************************************/
+
+void SwAutoTabDecimalPortion::Paint( const SwTxtPaintInfo & ) const
+{
+}
+
+/*************************************************************************
+ * virtual SwTabPortion::HandlePortion()
+ *************************************************************************/
+
+void SwTabPortion::HandlePortion( SwPortionHandler& rPH ) const
+{
+ rPH.Text( GetLen(), GetWhichPor() );
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/text/widorp.cxx b/sw/source/core/text/widorp.cxx
new file mode 100644
index 000000000000..55ec68509498
--- /dev/null
+++ b/sw/source/core/text/widorp.cxx
@@ -0,0 +1,574 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+
+#include "hintids.hxx"
+
+#include "layfrm.hxx"
+#include "ftnboss.hxx"
+#include "ndtxt.hxx"
+#include "paratr.hxx"
+#include <editeng/orphitem.hxx>
+#include <editeng/widwitem.hxx>
+#include <editeng/keepitem.hxx>
+#include <editeng/spltitem.hxx>
+#include <frmatr.hxx>
+#include <txtftn.hxx>
+#include <fmtftn.hxx>
+#include <rowfrm.hxx>
+
+#include "widorp.hxx"
+#include "txtfrm.hxx"
+#include "itrtxt.hxx"
+#include "sectfrm.hxx" //SwSectionFrm
+#include "ftnfrm.hxx"
+
+#undef WIDOWTWIPS
+
+
+/*************************************************************************
+ * inline IsNastyFollow()
+ *************************************************************************/
+// Ein Follow, der auf der selben Seite steht, wie sein Master ist nasty.
+inline sal_Bool IsNastyFollow( const SwTxtFrm *pFrm )
+{
+ OSL_ENSURE( !pFrm->IsFollow() || !pFrm->GetPrev() ||
+ ((const SwTxtFrm*)pFrm->GetPrev())->GetFollow() == pFrm,
+ "IsNastyFollow: Was ist denn hier los?" );
+ return pFrm->IsFollow() && pFrm->GetPrev();
+}
+
+/*************************************************************************
+ * SwTxtFrmBreak::SwTxtFrmBreak()
+ *************************************************************************/
+
+SwTxtFrmBreak::SwTxtFrmBreak( SwTxtFrm *pNewFrm, const SwTwips nRst )
+ : nRstHeight(nRst), pFrm(pNewFrm)
+{
+ SWAP_IF_SWAPPED( pFrm )
+ SWRECTFN( pFrm )
+ nOrigin = (pFrm->*fnRect->fnGetPrtTop)();
+ SwSectionFrm* pSct;
+ bKeep = !pFrm->IsMoveable() || IsNastyFollow( pFrm ) ||
+ ( pFrm->IsInSct() && (pSct=pFrm->FindSctFrm())->Lower()->IsColumnFrm()
+ && !pSct->MoveAllowed( pFrm ) ) ||
+ !pFrm->GetTxtNode()->GetSwAttrSet().GetSplit().GetValue() ||
+ pFrm->GetTxtNode()->GetSwAttrSet().GetKeep().GetValue();
+ bBreak = sal_False;
+
+ if( !nRstHeight && !pFrm->IsFollow() && pFrm->IsInFtn() && pFrm->HasPara() )
+ {
+ nRstHeight = pFrm->GetFtnFrmHeight();
+ nRstHeight += (pFrm->Prt().*fnRect->fnGetHeight)() -
+ (pFrm->Frm().*fnRect->fnGetHeight)();
+ if( nRstHeight < 0 )
+ nRstHeight = 0;
+ }
+
+ UNDO_SWAP( pFrm )
+}
+
+/* BP 18.6.93: Widows.
+ * Im Gegensatz zur ersten Implementierung werden die Widows nicht
+ * mehr vorausschauend berechnet, sondern erst beim Formatieren des
+ * gesplitteten Follows festgestellt. Im Master faellt die Widows-
+ * Berechnung also generell weg (nWidows wird manipuliert).
+ * Wenn der Follow feststellt, dass die Widowsregel zutrifft,
+ * verschickt er an seinen Vorgaenger ein Prepare.
+ * Ein besonderes Problem ergibt sich, wenn die Widows zuschlagen,
+ * aber im Master noch ein paar Zeilen zur Verfuegung stehen.
+ *
+ */
+
+/*************************************************************************
+ * SwTxtFrmBreak::IsInside()
+ *************************************************************************/
+
+/* BP(22.07.92): Berechnung von Witwen und Waisen.
+ * Die Methode liefert sal_True zurueck, wenn eine dieser Regelung zutrifft.
+ *
+ * Eine Schwierigkeit gibt es im Zusammenhang mit Widows und
+ * unterschiedlichen Formaten zwischen Master- und Folgeframes:
+ * Beispiel: Wenn die erste Spalte 3cm und die zweite 4cm breit ist
+ * und Widows auf sagen wir 3 gesetzt ist, so ist erst bei der Formatierung
+ * des Follows entscheidbar, ob die Widowsbedingung einhaltbar ist oder
+ * nicht. Leider ist davon abhaengig, ob der Absatz als Ganzes auf die
+ * naechste Seite rutscht.
+ */
+
+sal_Bool SwTxtFrmBreak::IsInside( SwTxtMargin &rLine ) const
+{
+ sal_Bool bFit = sal_False;
+
+ SWAP_IF_SWAPPED( pFrm )
+ SWRECTFN( pFrm )
+ // nOrigin is an absolut value, rLine referes to the swapped situation.
+
+ SwTwips nTmpY;
+ if ( pFrm->IsVertical() )
+ nTmpY = pFrm->SwitchHorizontalToVertical( rLine.Y() + rLine.GetLineHeight() );
+ else
+ nTmpY = rLine.Y() + rLine.GetLineHeight();
+
+ SwTwips nLineHeight = (*fnRect->fnYDiff)( nTmpY , nOrigin );
+
+ // 7455 und 6114: Raum fuer die Umrandung unten einkalkulieren.
+ nLineHeight += (pFrm->*fnRect->fnGetBottomMargin)();
+
+ if( nRstHeight )
+ bFit = nRstHeight >= nLineHeight;
+ else
+ {
+ // Der Frm besitzt eine Hoehe, mit der er auf die Seite passt.
+ SwTwips nHeight =
+ (*fnRect->fnYDiff)( (pFrm->GetUpper()->*fnRect->fnGetPrtBottom)(), nOrigin );
+
+ // Wenn sich alles innerhalb des bestehenden Frames abspielt,
+ // ist das Ergebnis sal_True;
+ bFit = nHeight >= nLineHeight;
+ if( !bFit )
+ {
+ // Die LineHeight sprengt die aktuelle Frm-Hoehe.
+ // Nun rufen wir ein Probe-Grow, um zu ermitteln, ob der
+ // Frame um den gewuenschten Bereich wachsen wuerde.
+ nHeight += pFrm->GrowTst( LONG_MAX );
+
+ // Das Grow() returnt die Hoehe, um die der Upper des TxtFrm
+ // den TxtFrm wachsen lassen wuerde.
+ // Der TxtFrm selbst darf wachsen wie er will.
+ bFit = nHeight >= nLineHeight;
+ }
+ }
+
+ UNDO_SWAP( pFrm );
+
+ return bFit;
+}
+
+/*************************************************************************
+ * SwTxtFrmBreak::IsBreakNow()
+ *************************************************************************/
+
+sal_Bool SwTxtFrmBreak::IsBreakNow( SwTxtMargin &rLine )
+{
+ SWAP_IF_SWAPPED( pFrm )
+
+ // bKeep ist staerker als IsBreakNow()
+ // Ist noch genug Platz ?
+ if( bKeep || IsInside( rLine ) )
+ bBreak = sal_False;
+ else
+ {
+ /* Diese Klasse geht davon aus, dass der SwTxtMargin von Top nach Bottom
+ * durchgearbeitet wird. Aus Performancegruenden wird in folgenden
+ * Faellen der Laden fuer das weitere Aufspalten dicht gemacht:
+ * Wenn eine einzige Zeile nicht mehr passt.
+ * Sonderfall: bei DummyPortions ist LineNr == 1, obwohl wir splitten
+ * wollen.
+ */
+ // 6010: DropLines mit einbeziehen
+
+ sal_Bool bFirstLine = 1 == rLine.GetLineNr() && !rLine.GetPrev();
+ bBreak = sal_True;
+ if( ( bFirstLine && pFrm->GetIndPrev() )
+ || ( rLine.GetLineNr() <= rLine.GetDropLines() ) )
+ {
+ bKeep = sal_True;
+ bBreak = sal_False;
+ }
+ else if(bFirstLine && pFrm->IsInFtn() && !pFrm->FindFtnFrm()->GetPrev())
+ {
+ SwLayoutFrm* pTmp = pFrm->FindFtnBossFrm()->FindBodyCont();
+ if( !pTmp || !pTmp->Lower() )
+ bBreak = sal_False;
+ }
+ }
+
+ UNDO_SWAP( pFrm )
+
+ return bBreak;
+}
+
+// OD 2004-02-27 #106629# - no longer inline
+void SwTxtFrmBreak::SetRstHeight( const SwTxtMargin &rLine )
+{
+ // OD, FME 2004-02-27 #106629# - consider bottom margin
+ SWRECTFN( pFrm )
+
+ nRstHeight = (pFrm->*fnRect->fnGetBottomMargin)();
+
+ if ( bVert )
+ //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin
+ {
+ if ( pFrm->IsVertLR() )
+ nRstHeight = (*fnRect->fnYDiff)( pFrm->SwitchHorizontalToVertical( rLine.Y() ) , nOrigin );
+ else
+ nRstHeight += nOrigin - pFrm->SwitchHorizontalToVertical( rLine.Y() );
+ }
+ else
+ nRstHeight += rLine.Y() - nOrigin;
+}
+
+/*************************************************************************
+ * WidowsAndOrphans::WidowsAndOrphans()
+ *************************************************************************/
+
+WidowsAndOrphans::WidowsAndOrphans( SwTxtFrm *pNewFrm, const SwTwips nRst,
+ sal_Bool bChkKeep )
+ : SwTxtFrmBreak( pNewFrm, nRst ), nWidLines( 0 ), nOrphLines( 0 )
+{
+ SWAP_IF_SWAPPED( pFrm )
+
+ if( bKeep )
+ {
+ // 5652: bei Absaetzen, die zusammengehalten werden sollen und
+ // groesser sind als die Seite wird bKeep aufgehoben.
+ if( bChkKeep && !pFrm->GetPrev() && !pFrm->IsInFtn() &&
+ pFrm->IsMoveable() &&
+ ( !pFrm->IsInSct() || pFrm->FindSctFrm()->MoveAllowed(pFrm) ) )
+ bKeep = sal_False;
+ //Auch bei gesetztem Keep muessen Orphans beachtet werden,
+ //z.B. bei verketteten Rahmen erhaelt ein Follow im letzten Rahmen ein Keep,
+ //da er nicht (vorwaerts) Moveable ist,
+ //er darf aber trotzdem vom Master Zeilen anfordern wg. der Orphanregel.
+ if( pFrm->IsFollow() )
+ nWidLines = pFrm->GetTxtNode()->GetSwAttrSet().GetWidows().GetValue();
+ }
+ else
+ {
+ const SwAttrSet& rSet = pFrm->GetTxtNode()->GetSwAttrSet();
+ const SvxOrphansItem &rOrph = rSet.GetOrphans();
+ if ( rOrph.GetValue() > 1 )
+ nOrphLines = rOrph.GetValue();
+ if ( pFrm->IsFollow() )
+ nWidLines = rSet.GetWidows().GetValue();
+
+ }
+
+ if ( bKeep || nWidLines || nOrphLines )
+ {
+ bool bResetFlags = false;
+
+ if ( pFrm->IsInTab() )
+ {
+ // For compatibility reasons, we disable Keep/Widows/Orphans
+ // inside splittable row frames:
+ if ( pFrm->GetNextCellLeaf( MAKEPAGE_NONE ) || pFrm->IsInFollowFlowRow() )
+ {
+ const SwFrm* pTmpFrm = pFrm->GetUpper();
+ while ( !pTmpFrm->IsRowFrm() )
+ pTmpFrm = pTmpFrm->GetUpper();
+ if ( static_cast<const SwRowFrm*>(pTmpFrm)->IsRowSplitAllowed() )
+ bResetFlags = true;
+ }
+ }
+
+ if( pFrm->IsInFtn() && !pFrm->GetIndPrev() )
+ {
+ // Innerhalb von Fussnoten gibt es gute Gruende, das Keep-Attribut und
+ // die Widows/Orphans abzuschalten.
+ SwFtnFrm *pFtn = pFrm->FindFtnFrm();
+ sal_Bool bFt = !pFtn->GetAttr()->GetFtn().IsEndNote();
+ if( !pFtn->GetPrev() &&
+ pFtn->FindFtnBossFrm( bFt ) != pFtn->GetRef()->FindFtnBossFrm( bFt )
+ && ( !pFrm->IsInSct() || pFrm->FindSctFrm()->MoveAllowed(pFrm) ) )
+ {
+ bResetFlags = true;
+ }
+ }
+
+ if ( bResetFlags )
+ {
+ bKeep = sal_False;
+ nOrphLines = 0;
+ nWidLines = 0;
+ }
+ }
+
+ UNDO_SWAP( pFrm )
+}
+
+/*************************************************************************
+ * WidowsAndOrphans::FindBreak()
+ *************************************************************************/
+
+/* Die Find*-Methoden suchen nicht nur, sondern stellen den SwTxtMargin auf
+ * die Zeile ein, wo der Absatz gebrochen werden soll und kuerzen ihn dort.
+ * FindBreak()
+ */
+
+sal_Bool WidowsAndOrphans::FindBreak( SwTxtFrm *pFrame, SwTxtMargin &rLine,
+ sal_Bool bHasToFit )
+{
+ // OD 2004-02-25 #i16128# - Why member <pFrm> _*and*_ parameter <pFrame>??
+ // Thus, assertion on situation, that these are different to figure out why.
+ OSL_ENSURE( pFrm == pFrame, "<WidowsAndOrphans::FindBreak> - pFrm != pFrame" );
+
+ SWAP_IF_SWAPPED( pFrm )
+
+ sal_Bool bRet = sal_True;
+ MSHORT nOldOrphans = nOrphLines;
+ if( bHasToFit )
+ nOrphLines = 0;
+ rLine.Bottom();
+ // OD 2004-02-25 #i16128# - method renamed
+ if( !IsBreakNowWidAndOrp( rLine ) )
+ bRet = sal_False;
+ if( !FindWidows( pFrame, rLine ) )
+ {
+ sal_Bool bBack = sal_False;
+ // OD 2004-02-25 #i16128# - method renamed
+ while( IsBreakNowWidAndOrp( rLine ) )
+ {
+ if( rLine.PrevLine() )
+ bBack = sal_True;
+ else
+ break;
+ }
+ // Eigentlich werden bei HasToFit Schusterjungen (Orphans) nicht
+ // beruecksichtigt, wenn allerdings Dummy-Lines im Spiel sind und
+ // die Orphansregel verletzt wird, machen wir mal eine Ausnahme:
+ // Wir lassen einfach eine Dummyline zurueck und wandern mit dem Text
+ // komplett auf die naechste Seite/Spalte.
+ if( rLine.GetLineNr() <= nOldOrphans &&
+ rLine.GetInfo().GetParaPortion()->IsDummy() &&
+ ( ( bHasToFit && bRet ) || IsBreakNow( rLine ) ) )
+ rLine.Top();
+
+ rLine.TruncLines( sal_True );
+ bRet = bBack;
+ }
+ nOrphLines = nOldOrphans;
+
+ UNDO_SWAP( pFrm )
+
+ return bRet;
+}
+
+/*************************************************************************
+ * WidowsAndOrphans::FindWidows()
+ *************************************************************************/
+
+/* FindWidows positioniert den SwTxtMargin des Masters auf die umzubrechende
+ * Zeile, indem der Follow formatiert und untersucht wird.
+ * Liefert sal_True zurueck, wenn die Widows-Regelung in Kraft tritt,
+ * d.h. der Absatz _zusammengehalten_ werden soll !
+ */
+
+sal_Bool WidowsAndOrphans::FindWidows( SwTxtFrm *pFrame, SwTxtMargin &rLine )
+{
+ OSL_ENSURE( ! pFrame->IsVertical() || ! pFrame->IsSwapped(),
+ "WidowsAndOrphans::FindWidows with swapped frame" );
+
+ if( !nWidLines || !pFrame->IsFollow() )
+ return sal_False;
+
+ rLine.Bottom();
+
+ // Wir koennen noch was abzwacken
+ SwTxtFrm *pMaster = pFrame->FindMaster();
+ OSL_ENSURE(pMaster, "+WidowsAndOrphans::FindWidows: Widows in a master?");
+ if( !pMaster )
+ return sal_False;
+
+ // 5156: Wenn die erste Zeile des Follows nicht passt, wird der Master
+ // wohl voll mit Dummies sein. In diesem Fall waere ein PREP_WIDOWS fatal.
+ if( pMaster->GetOfst() == pFrame->GetOfst() )
+ return sal_False;
+
+ // Resthoehe des Masters
+ SWRECTFN( pFrame )
+
+ const SwTwips nDocPrtTop = (pFrame->*fnRect->fnGetPrtTop)();
+ SwTwips nOldHeight;
+ SwTwips nTmpY = rLine.Y() + rLine.GetLineHeight();
+
+ if ( bVert )
+ {
+ nTmpY = pFrame->SwitchHorizontalToVertical( nTmpY );
+ nOldHeight = -(pFrame->Prt().*fnRect->fnGetHeight)();
+ }
+ else
+ nOldHeight = (pFrame->Prt().*fnRect->fnGetHeight)();
+
+ const SwTwips nChg = (*fnRect->fnYDiff)( nTmpY, nDocPrtTop + nOldHeight );
+
+ // Unterhalb der Widows-Schwelle...
+ if( rLine.GetLineNr() >= nWidLines )
+ {
+ // 8575: Follow to Master I
+ // Wenn der Follow *waechst*, so besteht fuer den Master die Chance,
+ // Zeilen entgegenzunehmen, die er vor Kurzem gezwungen war an den
+ // Follow abzugeben: Prepare(Need); diese Abfrage unterhalb von nChg!
+ // (0W, 2O, 2M, 2F) + 1F = 3M, 2F
+ if( rLine.GetLineNr() > nWidLines && pFrame->IsJustWidow() )
+ {
+ // Wenn der Master gelockt ist, so hat er vermutlich gerade erst
+ // eine Zeile an uns abgegeben, diese geben nicht zurueck, nur
+ // weil bei uns daraus mehrere geworden sind (z.B. durch Rahmen).
+ if( !pMaster->IsLocked() && pMaster->GetUpper() )
+ {
+ const SwTwips nTmpRstHeight = (pMaster->Frm().*fnRect->fnBottomDist)
+ ( (pMaster->GetUpper()->*fnRect->fnGetPrtBottom)() );
+ if ( nTmpRstHeight >=
+ SwTwips(rLine.GetInfo().GetParaPortion()->Height() ) )
+ {
+ pMaster->Prepare( PREP_ADJUST_FRM );
+ pMaster->_InvalidateSize();
+ pMaster->InvalidatePage();
+ }
+ }
+
+ pFrame->SetJustWidow( sal_False );
+ }
+ return sal_False;
+ }
+
+ // 8575: Follow to Master II
+ // Wenn der Follow *schrumpft*, so besteht fuer den Master die Chance,
+ // den kompletten Orphan zu inhalieren.
+ // (0W, 2O, 2M, 1F) - 1F = 3M, 0F -> PREP_ADJUST_FRM
+ // (0W, 2O, 3M, 2F) - 1F = 2M, 2F -> PREP_WIDOWS
+
+ if( 0 > nChg && !pMaster->IsLocked() && pMaster->GetUpper() )
+ {
+ SwTwips nTmpRstHeight = (pMaster->Frm().*fnRect->fnBottomDist)
+ ( (pMaster->GetUpper()->*fnRect->fnGetPrtBottom)() );
+ if( nTmpRstHeight >= SwTwips(rLine.GetInfo().GetParaPortion()->Height() ) )
+ {
+ pMaster->Prepare( PREP_ADJUST_FRM );
+ pMaster->_InvalidateSize();
+ pMaster->InvalidatePage();
+ pFrame->SetJustWidow( sal_False );
+ return sal_False;
+ }
+ }
+
+ // Master to Follow
+ // Wenn der Follow nach seiner Formatierung weniger Zeilen enthaelt
+ // als Widows, so besteht noch die Chance, einige Zeilen des Masters
+ // abzuzwacken. Wenn dadurch die Orphans-Regel des Masters in Kraft
+ // tritt muss im CalcPrep() des Master-Frame der Frame so vergroessert
+ // werden, dass er nicht mehr auf seine urspruengliche Seite passt.
+ // Wenn er noch ein paar Zeilen entbehren kann, dann muss im CalcPrep()
+ // ein Shrink() erfolgen, der Follow mit dem Widows rutscht dann auf
+ // die Seite des Masters, haelt sich aber zusammen, so dass er (endlich)
+ // auf die naechste Seite rutscht. - So die Theorie!
+
+
+ // Wir fordern nur noch ein Zeile zur Zeit an, weil eine Zeile des Masters
+ // bei uns durchaus mehrere Zeilen ergeben koennten.
+ // Dafuer behaelt CalcFollow solange die Kontrolle, bis der Follow alle
+ // notwendigen Zeilen bekommen hat.
+ MSHORT nNeed = 1; // frueher: nWidLines - rLine.GetLineNr();
+
+ // Special case: Master cannot give lines to follow
+ // --> FME 2008-09-16 #i91421#
+ if ( !pMaster->GetIndPrev() )
+ {
+ sal_uLong nLines = pMaster->GetThisLines();
+ if(nLines == 0 && pMaster->HasPara())
+ {
+ const SwParaPortion *pMasterPara = pMaster->GetPara();
+ if(pMasterPara && pMasterPara->GetNext())
+ nLines = 2;
+ }
+ if( nLines <= nNeed )
+ return sal_False;
+ }
+
+ pMaster->Prepare( PREP_WIDOWS, (void*)&nNeed );
+ return sal_True;
+}
+
+/*************************************************************************
+ * WidowsAndOrphans::WouldFit()
+ *************************************************************************/
+
+sal_Bool WidowsAndOrphans::WouldFit( SwTxtMargin &rLine, SwTwips &rMaxHeight, sal_Bool bTst )
+{
+ // Here it does not matter, if pFrm is swapped or not.
+ // IsInside() takes care for itself
+
+ // Wir erwarten, dass rLine auf der letzten Zeile steht!!
+ OSL_ENSURE( !rLine.GetNext(), "WouldFit: aLine::Bottom missed!" );
+ MSHORT nLineCnt = rLine.GetLineNr();
+
+ // Erstmal die Orphansregel und den Initialenwunsch erfuellen ...
+ const MSHORT nMinLines = Max( GetOrphansLines(), rLine.GetDropLines() );
+ if ( nLineCnt < nMinLines )
+ return sal_False;
+
+ rLine.Top();
+ SwTwips nLineSum = rLine.GetLineHeight();
+
+ while( nMinLines > rLine.GetLineNr() )
+ {
+ if( !rLine.NextLine() )
+ return sal_False;
+ nLineSum += rLine.GetLineHeight();
+ }
+
+ // Wenn wir jetzt schon nicht mehr passen ...
+ if( !IsInside( rLine ) )
+ return sal_False;
+
+ // Jetzt noch die Widows-Regel ueberpruefen
+ if( !nWidLines && !pFrm->IsFollow() )
+ {
+ // I.A. brauchen Widows nur ueberprueft werden, wenn wir ein Follow
+ // sind. Bei WouldFit muss aber auch fuer den Master die Regel ueber-
+ // prueft werden, weil wir ja gerade erst die Trennstelle ermitteln.
+ // Im Ctor von WidowsAndOrphans wurde nWidLines aber nur fuer Follows
+ // aus dem AttrSet ermittelt, deshalb holen wir es hier nach:
+ const SwAttrSet& rSet = pFrm->GetTxtNode()->GetSwAttrSet();
+ nWidLines = rSet.GetWidows().GetValue();
+ }
+
+ // Sind nach Orphans/Initialen noch genug Zeilen fuer die Widows uebrig?
+ // #111937#: If we are currently doing a test formatting, we may not
+ // consider the widows rule for two reasons:
+ // 1. The columns may have different widths.
+ // Widow lines would have wrong width.
+ // 2. Test formatting is only done up to the given space.
+ // we do not have any lines for widows at all.
+ if( bTst || nLineCnt - nMinLines >= GetWidowsLines() )
+ {
+ if( rMaxHeight >= nLineSum )
+ {
+ rMaxHeight -= nLineSum;
+ return sal_True;
+ }
+ }
+ return sal_False;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/text/widorp.hxx b/sw/source/core/text/widorp.hxx
new file mode 100644
index 000000000000..a0730d1b171e
--- /dev/null
+++ b/sw/source/core/text/widorp.hxx
@@ -0,0 +1,98 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+#ifndef _WIDORP_HXX
+#define _WIDORP_HXX
+class SwTxtFrm;
+
+#include "swtypes.hxx"
+#include "itrtxt.hxx"
+
+class SwTxtFrmBreak
+{
+private:
+ SwTwips nRstHeight;
+ SwTwips nOrigin;
+protected:
+ SwTxtFrm *pFrm;
+ sal_Bool bBreak;
+ sal_Bool bKeep;
+public:
+ SwTxtFrmBreak( SwTxtFrm *pFrm, const SwTwips nRst = 0 );
+ sal_Bool IsBreakNow( SwTxtMargin &rLine );
+
+ sal_Bool IsBroken() const { return bBreak; }
+ sal_Bool IsKeepAlways() const { return bKeep; }
+ void Keep() { bKeep = sal_True; }
+ void Break() { bKeep = sal_False; bBreak = sal_True; }
+
+ inline sal_Bool GetKeep() const { return bKeep; }
+ inline void SetKeep( const sal_Bool bNew ) { bKeep = bNew; }
+
+ sal_Bool IsInside( SwTxtMargin &rLine ) const;
+
+ // Um Sonderfaelle mit Ftn behandeln zu koennen.
+ // Mit SetRstHeight wird dem SwTxtFrmBreak die Resthoehe eingestellt,
+ // Um TruncLines() rufen zu koennen, ohne dass IsBreakNow() einen
+ // anderen Wert zurueckliefert.
+ // Es wird dabei davon ausgegangen, dass rLine auf der letzten Zeile
+ // steht, die nicht mehr passt.
+
+ // OD 2004-02-27 #106629# - no longer inline
+ void SetRstHeight( const SwTxtMargin &rLine );
+ SwTwips GetRstHeight() const { return nRstHeight; }
+};
+
+class WidowsAndOrphans : public SwTxtFrmBreak
+{
+private:
+ MSHORT nWidLines, nOrphLines;
+
+public:
+ WidowsAndOrphans( SwTxtFrm *pFrm, const SwTwips nRst = 0,
+ sal_Bool bCheckKeep = sal_True );
+ sal_Bool FindWidows( SwTxtFrm *pFrm, SwTxtMargin &rLine );
+ MSHORT GetWidowsLines() const
+ { return nWidLines; }
+ MSHORT GetOrphansLines() const
+ { return nOrphLines; }
+ void ClrOrphLines(){ nOrphLines = 0; }
+
+ sal_Bool FindBreak( SwTxtFrm *pFrm, SwTxtMargin &rLine, sal_Bool bHasToFit );
+ sal_Bool WouldFit( SwTxtMargin &rLine, SwTwips &rMaxHeight, sal_Bool bTest );
+ // OD 2004-02-25 #i16128# - rename method to avoid confusion with base class
+ // method <SwTxtFrmBreak::IsBreakNow>, which isn't virtual.
+ sal_Bool IsBreakNowWidAndOrp( SwTxtMargin &rLine )
+ {
+ return ( rLine.GetLineNr() > nOrphLines ) && IsBreakNow( rLine );
+ }
+};
+
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/text/wrong.cxx b/sw/source/core/text/wrong.cxx
new file mode 100644
index 000000000000..873ab995b0af
--- /dev/null
+++ b/sw/source/core/text/wrong.cxx
@@ -0,0 +1,646 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+
+#include <tools/string.hxx>
+#include <tools/debug.hxx>
+#include "swtypes.hxx"
+#include "txttypes.hxx"
+
+#include "SwGrammarMarkUp.hxx"
+
+
+/*************************************************************************
+ * SwWrongList::SwWrongList()
+ *************************************************************************/
+SwWrongList::SwWrongList( WrongListType eType ) :
+ meType (eType),
+ nBeginInvalid(STRING_LEN), // everything correct... (the invalid area starts beyond the string)
+ nEndInvalid (STRING_LEN)
+{
+ maList.reserve( 5 );
+}
+
+SwWrongList::~SwWrongList()
+{
+ ClearList();
+}
+
+/*************************************************************************
+ * SwWrongList* SwWrongList::Clone()
+ *************************************************************************/
+
+SwWrongList* SwWrongList::Clone()
+{
+ SwWrongList* pClone = new SwWrongList( meType );
+ pClone->CopyFrom( *this );
+ return pClone;
+}
+
+/*************************************************************************
+ * void SwWrongList::CopyFrom( const SwWrongList& rCopy )
+ *************************************************************************/
+
+void SwWrongList::CopyFrom( const SwWrongList& rCopy )
+{
+ maList = rCopy.maList;
+ meType = rCopy.meType;
+ nBeginInvalid = rCopy.nBeginInvalid;
+ nEndInvalid = rCopy.nEndInvalid;
+ for( size_t i = 0; i < maList.size(); ++i )
+ {
+ if( maList[i].mpSubList )
+ maList[i].mpSubList = maList[i].mpSubList->Clone();
+ }
+}
+
+/*************************************************************************
+ * SwWrongList::ClearList()
+ *************************************************************************/
+void SwWrongList::ClearList()
+{
+ for ( size_t i = 0; i < maList.size(); ++i)
+ {
+ if (maList[i].mpSubList)
+ delete maList[i].mpSubList;
+ maList[i].mpSubList = NULL;
+ }
+ maList.clear();
+}
+
+/*************************************************************************
+ * sal_Bool SwWrongList::InWrongWord() gibt den Anfang und die Laenge des
+ * Wortes zurueck, wenn es als falsch markiert ist.
+ *************************************************************************/
+sal_Bool SwWrongList::InWrongWord( xub_StrLen &rChk, xub_StrLen &rLn ) const
+{
+ MSHORT nPos = GetWrongPos( rChk );
+ xub_StrLen nWrPos;
+ if( nPos < Count() && ( nWrPos = Pos( nPos ) ) <= rChk )
+ {
+ rLn = Len( nPos );
+ if( nWrPos + rLn <= rChk )
+ return sal_False;
+ rChk = nWrPos;
+ return sal_True;
+ }
+ return sal_False;
+}
+
+/*************************************************************************
+ * sal_Bool SwWrongList::Check() liefert den ersten falschen Bereich
+ *************************************************************************/
+sal_Bool SwWrongList::Check( xub_StrLen &rChk, xub_StrLen &rLn ) const
+{
+ MSHORT nPos = GetWrongPos( rChk );
+ rLn = rLn + rChk;
+ xub_StrLen nWrPos;
+
+ if( nPos == Count() )
+ return sal_False;
+
+ xub_StrLen nEnd = Len( nPos );
+ nEnd = nEnd + ( nWrPos = Pos( nPos ) );
+ if( nEnd == rChk )
+ {
+ ++nPos;
+ if( nPos == Count() )
+ return sal_False;
+ else
+ {
+ nEnd = Len( nPos );
+ nEnd = nEnd + ( nWrPos = Pos( nPos ) );
+ }
+ }
+ if( nEnd > rChk && nWrPos < rLn )
+ {
+ if( nWrPos > rChk )
+ rChk = nWrPos;
+ if( nEnd < rLn )
+ rLn = nEnd;
+ rLn = rLn - rChk;
+ return 0 != rLn;
+ }
+ return sal_False;
+}
+
+/*************************************************************************
+ * xub_StrLen SwWrongList::NextWrong() liefert die naechste Fehlerposition
+ *************************************************************************/
+
+xub_StrLen SwWrongList::NextWrong( xub_StrLen nChk ) const
+{
+ xub_StrLen nRet;
+ xub_StrLen nPos = GetWrongPos( nChk );
+ if( nPos < Count() )
+ {
+ nRet = Pos( nPos );
+ if( nRet < nChk && nRet + Len( nPos ) <= nChk )
+ {
+ if( ++nPos < Count() )
+ nRet = Pos( nPos );
+ else
+ nRet = STRING_LEN;
+ }
+ }
+ else
+ nRet = STRING_LEN;
+ if( nRet > GetBeginInv() && nChk < GetEndInv() )
+ nRet = nChk > GetBeginInv() ? nChk : GetBeginInv();
+ return nRet;
+}
+
+/*************************************************************************
+ * MSHORT SwWrongList::GetWrongPos( xub_StrLen nValue )
+ * sucht die erste Position im Array, die groessergleich nValue ist,
+ * dies kann natuerlich auch hinter dem letzten Element sein!
+ *************************************************************************/
+
+MSHORT SwWrongList::GetWrongPos( xub_StrLen nValue ) const
+{
+ MSHORT nOben = Count(), nUnten = 0;
+
+ if( nOben > 0 )
+ {
+ // For smart tag lists, we may not use a binary search. We return the
+ // position of the first smart tag which coveres nValue
+ if ( 0 != maList[0].maType.getLength() || maList[0].mpSubList )
+ {
+ std::vector<SwWrongArea>::const_iterator aIter = maList.begin();
+ while ( aIter != maList.end() )
+ {
+ const xub_StrLen nSTPos = (*aIter).mnPos;
+ const xub_StrLen nSTLen = (*aIter).mnLen;
+ if ( nSTPos <= nValue && nValue < nSTPos + nSTLen )
+ break;
+ else if ( nSTPos > nValue )
+ break;
+
+ ++aIter;
+ ++nUnten;
+ }
+ return nUnten;
+ }
+
+ --nOben;
+ MSHORT nMitte = 0;
+ while( nUnten <= nOben )
+ {
+ nMitte = nUnten + ( nOben - nUnten ) / 2;
+ xub_StrLen nTmp = Pos( nMitte );
+ if( nTmp == nValue )
+ {
+ nUnten = nMitte;
+ break;
+ }
+ else if( nTmp < nValue )
+ {
+ if( nTmp + Len( nMitte ) >= nValue )
+ {
+ nUnten = nMitte;
+ break;
+ }
+ nUnten = nMitte + 1;
+ }
+ else if( nMitte == 0 )
+ {
+ break;
+ }
+ else
+ nOben = nMitte - 1;
+ }
+ }
+
+ // nUnten now points to an index i into the wrong list which
+ // 1. nValue is inside [ Area[i].pos, Area[i].pos + Area[i].len ] (inkl!!!)
+ // 2. nValue < Area[i].pos
+
+ return nUnten;
+}
+
+/*************************************************************************
+ * void SwWrongList::_Invalidate()
+ *************************************************************************/
+
+void SwWrongList::_Invalidate( xub_StrLen nBegin, xub_StrLen nEnd )
+{
+ if ( nBegin < GetBeginInv() )
+ nBeginInvalid = nBegin;
+ if ( nEnd > GetEndInv() )
+ nEndInvalid = nEnd;
+}
+
+void SwWrongList::SetInvalid( xub_StrLen nBegin, xub_StrLen nEnd )
+{
+ nBeginInvalid = nBegin;
+ nEndInvalid = nEnd;
+}
+
+
+/*************************************************************************
+ * SwWrongList::Move( xub_StrLen nPos, long nDiff )
+ * veraendert alle Positionen ab nPos um den angegebenen Wert,
+ * wird nach Einfuegen oder Loeschen von Buchstaben benoetigt.
+ *************************************************************************/
+
+void SwWrongList::Move( xub_StrLen nPos, long nDiff )
+{
+ MSHORT i = GetWrongPos( nPos );
+ if( nDiff < 0 )
+ {
+ xub_StrLen nEnd = nPos + xub_StrLen( -nDiff );
+ MSHORT nLst = i;
+ xub_StrLen nWrPos;
+ xub_StrLen nWrLen;
+ sal_Bool bJump = sal_False;
+ while( nLst < Count() && Pos( nLst ) < nEnd )
+ ++nLst;
+ if( nLst > i && ( nWrPos = Pos( nLst - 1 ) ) <= nPos )
+ {
+ nWrLen = Len( nLst - 1 );
+ // calculate new length of word
+ nWrLen = ( nEnd > nWrPos + nWrLen ) ?
+ nPos - nWrPos :
+ static_cast<xub_StrLen>(nWrLen + nDiff);
+ if( nWrLen )
+ {
+ maList[--nLst].mnLen = nWrLen;
+ bJump = sal_True;
+ }
+ }
+ Remove( i, nLst - i );
+
+ if ( bJump )
+ ++i;
+ if( STRING_LEN == GetBeginInv() )
+ SetInvalid( nPos ? nPos - 1 : nPos, nPos + 1 );
+ else
+ {
+ ShiftLeft( nBeginInvalid, nPos, nEnd );
+ ShiftLeft( nEndInvalid, nPos, nEnd );
+ _Invalidate( nPos ? nPos - 1 : nPos, nPos + 1 );
+ }
+ }
+ else
+ {
+ xub_StrLen nWrPos;
+ xub_StrLen nEnd = nPos + xub_StrLen( nDiff );
+ if( STRING_LEN != GetBeginInv() )
+ {
+ if( nBeginInvalid > nPos )
+ nBeginInvalid = nBeginInvalid + xub_StrLen( nDiff );
+ if( nEndInvalid >= nPos )
+ nEndInvalid = nEndInvalid + xub_StrLen( nDiff );
+ }
+ // Wenn wir mitten in einem falschen Wort stehen, muss vom Wortanfang
+ // invalidiert werden.
+ if( i < Count() && nPos >= ( nWrPos = Pos( i ) ) )
+ {
+ Invalidate( nWrPos, nEnd );
+ xub_StrLen nWrLen = Len( i ) + xub_StrLen( nDiff );
+ maList[i++].mnLen = nWrLen;
+ nWrLen = nWrLen + nWrPos;
+ Invalidate( nWrPos, nWrLen );
+ }
+ else
+ Invalidate( nPos, nEnd );
+ }
+ while( i < Count() )
+ {
+ const xub_StrLen nTmp = static_cast<xub_StrLen>(nDiff + maList[i].mnPos);
+ maList[i++].mnPos = nTmp;
+ }
+}
+
+/*************************************************************************
+ * SwWrongList::Fresh
+ *
+ * For a given range [nPos, nPos + nLen[ and an index nIndex, this function
+ * basically counts the number of SwWrongArea entries starting with nIndex
+ * up to nPos + nLen. All these entries are removed.
+ *************************************************************************/
+sal_Bool SwWrongList::Fresh( xub_StrLen &rStart, xub_StrLen &rEnd, xub_StrLen nPos,
+ xub_StrLen nLen, MSHORT nIndex, xub_StrLen nCursorPos )
+{
+ // length of word must be greater than 0 and cursor position must be outside the word
+ sal_Bool bRet = nLen && ( nCursorPos > nPos + nLen || nCursorPos < nPos );
+
+ xub_StrLen nWrPos = 0;
+ xub_StrLen nWrEnd = rEnd;
+ MSHORT nCnt = nIndex;
+ if( nCnt < Count() && ( nWrPos = Pos( nIndex ) ) < nPos )
+ {
+ if( rStart > nWrPos )
+ rStart = nWrPos;
+ }
+
+ while( nCnt < Count() && ( nWrPos = Pos( nCnt ) ) < nPos )
+ nWrEnd = nWrPos + Len( nCnt++ );
+
+ if( nCnt < Count() && nWrPos == nPos && Len( nCnt ) == nLen )
+ {
+ ++nCnt;
+ bRet = sal_True;
+ }
+ else
+ {
+ if( bRet )
+ {
+ if( rStart > nPos )
+ rStart = nPos;
+ nWrEnd = nPos + nLen;
+ }
+ }
+
+ nPos = nPos + nLen;
+
+ if( nCnt < Count() && ( nWrPos = Pos( nCnt ) ) < nPos )
+ {
+ if( rStart > nWrPos )
+ rStart = nWrPos;
+ }
+
+ while( nCnt < Count() && ( nWrPos = Pos( nCnt ) ) < nPos )
+ nWrEnd = nWrPos + Len( nCnt++ );
+
+ if( rEnd < nWrEnd )
+ rEnd = nWrEnd;
+
+ Remove( nIndex, nCnt - nIndex );
+
+ return bRet;
+}
+
+void SwWrongList::Invalidate( xub_StrLen nBegin, xub_StrLen nEnd )
+{
+ if (STRING_LEN == GetBeginInv())
+ SetInvalid( nBegin, nEnd );
+ else
+ _Invalidate( nBegin, nEnd );
+}
+
+sal_Bool SwWrongList::InvalidateWrong( )
+{
+ if( Count() )
+ {
+ xub_StrLen nFirst = Pos( 0 );
+ xub_StrLen nLast = Pos( Count() - 1 ) + Len( Count() - 1 );
+ Invalidate( nFirst, nLast );
+ return sal_True;
+ }
+ else
+ return sal_False;
+}
+
+SwWrongList* SwWrongList::SplitList( xub_StrLen nSplitPos )
+{
+ SwWrongList *pRet = NULL;
+ MSHORT nLst = 0;
+ xub_StrLen nWrPos;
+ xub_StrLen nWrLen;
+ while( nLst < Count() && Pos( nLst ) < nSplitPos )
+ ++nLst;
+ if( nLst && ( nWrPos = Pos( nLst - 1 ) )
+ + ( nWrLen = Len( nLst - 1 ) ) > nSplitPos )
+ {
+ nWrLen += nWrPos - nSplitPos;
+ maList[--nLst].mnPos = nSplitPos;
+ maList[nLst].mnLen = nWrLen;
+ }
+ if( nLst )
+ {
+ if( WRONGLIST_GRAMMAR == GetWrongListType() )
+ pRet = new SwGrammarMarkUp();
+ else
+ pRet = new SwWrongList( GetWrongListType() );
+ pRet->Insert(0, maList.begin(), ( nLst >= maList.size() ? maList.end() : maList.begin() + nLst ) );
+ pRet->SetInvalid( GetBeginInv(), GetEndInv() );
+ pRet->_Invalidate( nSplitPos ? nSplitPos - 1 : nSplitPos, nSplitPos );
+ Remove( 0, nLst );
+ }
+ if( STRING_LEN == GetBeginInv() )
+ SetInvalid( 0, 1 );
+ else
+ {
+ ShiftLeft( nBeginInvalid, 0, nSplitPos );
+ ShiftLeft( nEndInvalid, 0, nSplitPos );
+ _Invalidate( 0, 1 );
+ }
+ nLst = 0;
+ while( nLst < Count() )
+ {
+ nWrPos = maList[nLst].mnPos - nSplitPos;
+ maList[nLst++].mnPos = nWrPos;
+ }
+ return pRet;
+}
+
+void SwWrongList::JoinList( SwWrongList* pNext, xub_StrLen nInsertPos )
+{
+ if (pNext)
+ {
+ DBG_ASSERT( GetWrongListType() == pNext->GetWrongListType(), "type mismatch with next list" );
+ }
+ if( pNext )
+ {
+ sal_uInt16 nCnt = Count();
+ pNext->Move( 0, nInsertPos );
+ Insert(nCnt, pNext->maList.begin(), pNext->maList.end());
+
+ Invalidate( pNext->GetBeginInv(), pNext->GetEndInv() );
+ if( nCnt && Count() > nCnt )
+ {
+ xub_StrLen nWrPos = Pos( nCnt );
+ xub_StrLen nWrLen = Len( nCnt );
+ if( !nWrPos )
+ {
+ nWrPos = nWrPos + nInsertPos;
+ nWrLen = nWrLen - nInsertPos;
+ maList[nCnt].mnPos = nWrPos;
+ maList[nCnt].mnLen = nWrLen;
+ }
+ if( nWrPos == Pos( nCnt - 1 ) + Len( nCnt - 1 ) )
+ {
+ nWrLen = nWrLen + Len( nCnt - 1 );
+ maList[nCnt - 1].mnLen = nWrLen;
+ Remove( nCnt, 1 );
+ }
+ }
+ }
+ Invalidate( nInsertPos ? nInsertPos - 1 : nInsertPos, nInsertPos + 1 );
+}
+
+
+void SwWrongList::InsertSubList( xub_StrLen nNewPos, xub_StrLen nNewLen, sal_uInt16 nWhere, SwWrongList* pSubList )
+{
+ if (pSubList)
+ {
+ DBG_ASSERT( GetWrongListType() == pSubList->GetWrongListType(), "type mismatch with sub list" );
+ }
+ std::vector<SwWrongArea>::iterator i = maList.begin();
+ if ( nWhere >= maList.size() )
+ i = maList.end(); // robust
+ else
+ i += nWhere;
+ maList.insert(i, SwWrongArea( rtl::OUString(), 0, nNewPos, nNewLen, pSubList ) );
+}
+
+
+// New functions: Necessary because SwWrongList has been changed to use std::vector
+void SwWrongList::Insert(sal_uInt16 nWhere, std::vector<SwWrongArea>::iterator startPos, std::vector<SwWrongArea>::iterator endPos)
+{
+ std::vector<SwWrongArea>::iterator i = maList.begin();
+ if ( nWhere >= maList.size() )
+ i = maList.end(); // robust
+ else
+ i += nWhere;
+ maList.insert(i, startPos, endPos); // insert [startPos, endPos[ before i
+
+ // ownership of the sublist is passed to maList, therefore we have to set the
+ // pSubList-Pointers to 0
+ while ( startPos != endPos )
+ {
+ (*startPos).mpSubList = 0;
+ ++startPos;
+ }
+}
+
+void SwWrongList::Remove(sal_uInt16 nIdx, sal_uInt16 nLen )
+{
+ if ( nIdx >= maList.size() ) return;
+ std::vector<SwWrongArea>::iterator i1 = maList.begin();
+ i1 += nIdx;
+
+ std::vector<SwWrongArea>::iterator i2 = i1;
+ if ( nIdx + nLen >= static_cast<sal_uInt16>(maList.size()) )
+ i2 = maList.end(); // robust
+ else
+ i2 += nLen;
+
+ std::vector<SwWrongArea>::iterator iLoop = i1;
+ while ( iLoop != i2 )
+ {
+ if ( (*iLoop).mpSubList )
+ delete (*iLoop).mpSubList;
+ ++iLoop;
+ }
+
+#if OSL_DEBUG_LEVEL > 1
+ const int nOldSize = Count();
+ (void) nOldSize;
+#endif
+
+ maList.erase(i1, i2);
+
+#if OSL_DEBUG_LEVEL > 1
+ OSL_ENSURE( Count() + nLen == nOldSize, "SwWrongList::Remove() trouble" );
+#endif
+}
+
+void SwWrongList::RemoveEntry( xub_StrLen nBegin, xub_StrLen nEnd ) {
+ sal_uInt16 nDelPos = 0;
+ sal_uInt16 nDel = 0;
+ std::vector<SwWrongArea>::iterator aIter = maList.begin();
+ while( aIter != maList.end() && (*aIter).mnPos < nBegin )
+ {
+ ++aIter;
+ ++nDelPos;
+ }
+ if( WRONGLIST_GRAMMAR == GetWrongListType() )
+ {
+ while( aIter != maList.end() && nBegin < nEnd && nEnd > (*aIter).mnPos )
+ {
+ ++aIter;
+ ++nDel;
+ }
+ }
+ else
+ {
+ while( aIter != maList.end() && nBegin == (*aIter).mnPos && nEnd == (*aIter).mnPos +(*aIter).mnLen )
+ {
+ ++aIter;
+ ++nDel;
+ }
+ }
+ if( nDel )
+ Remove( nDelPos, nDel );
+}
+
+bool SwWrongList::LookForEntry( xub_StrLen nBegin, xub_StrLen nEnd ) {
+ std::vector<SwWrongArea>::iterator aIter = maList.begin();
+ while( aIter != maList.end() && (*aIter).mnPos < nBegin )
+ ++aIter;
+ if( aIter != maList.end() && nBegin == (*aIter).mnPos && nEnd == (*aIter).mnPos +(*aIter).mnLen )
+ return true;
+ return false;
+}
+
+void SwWrongList::Insert( const rtl::OUString& rType,
+ com::sun::star::uno::Reference< com::sun::star::container::XStringKeyMap > xPropertyBag,
+ xub_StrLen nNewPos, xub_StrLen nNewLen )
+{
+ std::vector<SwWrongArea>::iterator aIter = maList.begin();
+
+ while ( aIter != maList.end() )
+ {
+ const xub_StrLen nSTPos = (*aIter).mnPos;
+
+ if ( nNewPos < nSTPos )
+ {
+ // insert at current position
+ break;
+ }
+ else if ( nNewPos == nSTPos )
+ {
+ while ( aIter != maList.end() && (*aIter).mnPos == nSTPos )
+ {
+ const xub_StrLen nSTLen = (*aIter).mnLen;
+
+ if ( nNewLen < nSTLen )
+ {
+ // insert at current position
+ break;
+ }
+
+ ++aIter;
+ }
+
+ break;
+ }
+
+ ++aIter;
+ }
+
+ maList.insert(aIter, SwWrongArea( rType, xPropertyBag, nNewPos, nNewLen, 0 ) );
+}
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/text/xmldump.cxx b/sw/source/core/text/xmldump.cxx
new file mode 100644
index 000000000000..3209fbadac52
--- /dev/null
+++ b/sw/source/core/text/xmldump.cxx
@@ -0,0 +1,318 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * Version: MPL 1.1 / GPLv3+ / LGPLv3+
+ *
+ * The contents of this file are subject to the Mozilla Public 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.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Initial Developer of the Original Code is
+ * Novell Inc.
+ * Portions created by the Initial Developer are Copyright (C) 2010 the
+ * Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s): Florian Reuter <freuter@novell.com>
+ * Cedric Bosdonnat <cbosdonnat@novell.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 3 or later (the "GPLv3+"), or
+ * the GNU Lesser General Public License Version 3 or later (the "LGPLv3+"),
+ * in which case the provisions of the GPLv3+ or the LGPLv3+ are applicable
+ * instead of those above.
+ */
+#include "precompiled_sw.hxx"
+
+#include "frame.hxx"
+#include "txtfrm.hxx"
+#include "porlin.hxx"
+#include "porlay.hxx"
+#include "portxt.hxx"
+#include <libxml/xmlwriter.h>
+#include <SwPortionHandler.hxx>
+
+class XmlPortionDumper:public SwPortionHandler
+{
+ private:
+ xmlTextWriterPtr writer;
+ sal_uInt16 ofs;
+ public:
+
+ XmlPortionDumper( xmlTextWriterPtr some_writer ):writer( some_writer ), ofs( 0 )
+ {
+ }
+
+ virtual ~ XmlPortionDumper( )
+ {
+ }
+
+ /**
+ @param nLength
+ length of this portion in the model string
+ @param rText
+ text which is painted on-screen
+ */
+ virtual void Text( sal_uInt16 nLength,
+ sal_uInt16 nType )
+ {
+ ofs += nLength;
+ xmlTextWriterStartElement( writer, BAD_CAST( "Text" ) );
+ xmlTextWriterWriteFormatAttribute( writer,
+ BAD_CAST( "nLength" ),
+ "%i", ( int ) nLength );
+ xmlTextWriterWriteFormatAttribute( writer,
+ BAD_CAST( "nType" ),
+ "%i", ( int ) nType );
+ xmlTextWriterEndElement( writer );
+ }
+
+ /**
+ @param nLength
+ length of this portion in the model string
+ @param rText
+ text which is painted on-screen
+ @param nType
+ type of this portion
+ */
+ virtual void Special( sal_uInt16 nLength,
+ const String & rText,
+ sal_uInt16 nType )
+ {
+ xmlTextWriterStartElement( writer, BAD_CAST( "Special" ) );
+ xmlTextWriterWriteFormatAttribute( writer,
+ BAD_CAST( "nLength" ),
+ "%i", ( int ) nLength );
+ xmlTextWriterWriteFormatAttribute( writer,
+ BAD_CAST( "nType" ),
+ "%i", ( int ) nType );
+ rtl::OUString sText( rText );
+ rtl::OString sText8 =::rtl::OUStringToOString( sText,
+ RTL_TEXTENCODING_UTF8 );
+ xmlTextWriterWriteFormatAttribute( writer, BAD_CAST( "rText" ),
+ "%s", sText8.getStr( ) );
+
+ xmlTextWriterEndElement( writer );
+ ofs += nLength;
+ }
+
+ virtual void LineBreak( )
+ {
+ xmlTextWriterStartElement( writer, BAD_CAST( "LineBreak" ) );
+ xmlTextWriterEndElement( writer );
+ }
+
+ /**
+ * @param nLength
+ * number of 'model string' characters to be skipped
+ */
+ virtual void Skip( sal_uInt16 nLength )
+ {
+ xmlTextWriterStartElement( writer, BAD_CAST( "Skip" ) );
+ xmlTextWriterWriteFormatAttribute( writer,
+ BAD_CAST( "nLength" ),
+ "%i", ( int ) nLength );
+ xmlTextWriterEndElement( writer );
+ ofs += nLength;
+ }
+
+ virtual void Finish( )
+ {
+ xmlTextWriterStartElement( writer, BAD_CAST( "Finish" ) );
+ xmlTextWriterEndElement( writer );
+ }
+
+};
+
+#if OSL_DEBUG_LEVEL > 1
+
+void SwTxtPortion::dumpPortionAsXml( xub_StrLen ofs, XubString & /*aText */,
+ xmlTextWriterPtr writer )
+{
+ xmlTextWriterStartElement( writer, BAD_CAST( "SwTxtPortion" ) );
+ xmlTextWriterWriteFormatAttribute( writer, BAD_CAST( "ofs" ), "%i", ofs );
+ xmlTextWriterWriteFormatAttribute( writer, BAD_CAST( "len" ), "%i",
+ ( int ) this->GetLen( ) );
+
+ xmlTextWriterEndElement( writer );
+}
+
+void SwLinePortion::dumpPortionAsXml( xub_StrLen ofs, XubString & /*aText */,
+ xmlTextWriterPtr writer )
+{
+ xmlTextWriterStartElement( writer, BAD_CAST( "SwLinePortion" ) );
+ xmlTextWriterWriteFormatAttribute( writer,
+ BAD_CAST( "nWhichPor" ),
+ "%04X",
+ ( int ) this->GetWhichPor( ) );
+ xmlTextWriterWriteFormatAttribute( writer, BAD_CAST( "ofs" ), "%i", ofs );
+ xmlTextWriterWriteFormatAttribute( writer, BAD_CAST( "len" ), "%i",
+ ( int ) this->GetLen( ) );
+ xmlTextWriterEndElement( writer );
+}
+
+void SwLineLayout::dumpLineAsXml( xmlTextWriterPtr writer,
+ xub_StrLen & ofs, XubString & aText )
+{ // not used any longer...
+ xmlTextWriterStartElement( writer, BAD_CAST( "SwLineLayout" ) );
+ SwLinePortion *portion = this;
+ while ( portion != NULL )
+ {
+ portion->dumpPortionAsXml( ofs, aText, writer );
+ ofs += portion->GetLen( );
+ portion = portion->GetPortion( );
+ }
+ xmlTextWriterEndElement( writer );
+}
+
+
+void SwParaPortion::dumpAsXml( xmlTextWriterPtr writer, SwTxtFrm * pTxtFrm )
+{
+ xmlTextWriterStartElement( writer, BAD_CAST( "SwParaPortion" ) );
+ SwParaPortion *pPara = this;
+
+ if ( pPara && pTxtFrm )
+ {
+ xub_StrLen ofs = 0;
+ XubString & aText = ( String & ) pTxtFrm->GetTxt( );
+ if ( pTxtFrm->IsFollow( ) )
+ ofs += pTxtFrm->GetOfst( );
+
+ SwLineLayout *pLine = pPara;
+ while ( pLine )
+ {
+ xmlTextWriterStartElement( writer, BAD_CAST( "line" ) );
+ SwLinePortion *pPor = pLine->GetFirstPortion( );
+ while ( pPor )
+ {
+ pPor->dumpPortionAsXml( ofs, aText, writer );
+ ofs += pPor->GetLen( );
+ pPor = pPor->GetPortion( );
+ }
+
+ xmlTextWriterEndElement( writer ); // line
+ pLine = pLine->GetNext( );
+ }
+ }
+ xmlTextWriterEndElement( writer );
+}
+
+
+void SwFrm::dumpAsXml( xmlTextWriterPtr writer )
+{
+ const char *name = NULL;
+
+ switch ( GetType( ) )
+ {
+ case FRM_ROOT:
+ name = "root";
+ break;
+ case FRM_PAGE:
+ name = "page";
+ break;
+ case FRM_COLUMN:
+ name = "column";
+ break;
+ case FRM_HEADER:
+ name = "header";
+ break;
+ case FRM_FOOTER:
+ name = "footer";
+ break;
+ case FRM_FTNCONT:
+ name = "ftncont";
+ break;
+ case FRM_FTN:
+ name = "ftn";
+ break;
+ case FRM_BODY:
+ name = "body";
+ break;
+ case FRM_FLY:
+ name = "fly";
+ break;
+ case FRM_SECTION:
+ name = "section";
+ break;
+ case FRM_UNUSED:
+ name = "unused";
+ break;
+ case FRM_TAB:
+ name = "tab";
+ break;
+ case FRM_ROW:
+ name = "row";
+ break;
+ case FRM_CELL:
+ name = "cell";
+ break;
+ case FRM_TXT:
+ name = "txt";
+ break;
+ case FRM_NOTXT:
+ name = "txt";
+ break;
+ };
+
+ if ( name != NULL )
+ {
+ xmlTextWriterStartElement( writer, ( const xmlChar * ) name );
+
+ dumpAsXmlAttributes( writer );
+
+ if ( IsTxtFrm( ) )
+ {
+ SwTxtFrm *pTxtFrm = ( SwTxtFrm * ) this;
+ rtl::OUString aTxt = pTxtFrm->GetTxt( );
+ for ( int i = 0; i < 32; i++ )
+ {
+ aTxt = aTxt.replace( i, '*' );
+ }
+ rtl::OString aTxt8 =::rtl::OUStringToOString( aTxt,
+ RTL_TEXTENCODING_UTF8 );
+ xmlTextWriterWriteString( writer,
+ ( const xmlChar * ) aTxt8.getStr( ) );
+ XmlPortionDumper pdumper( writer );
+ pTxtFrm->VisitPortions( pdumper );
+
+ }
+ else
+ {
+ dumpChildrenAsXml( writer );
+ }
+ xmlTextWriterEndElement( writer );
+ }
+}
+
+void SwFrm::dumpAsXmlAttributes( xmlTextWriterPtr writer )
+{
+ xmlTextWriterWriteFormatAttribute( writer, BAD_CAST( "ptr" ), "%p", this );
+ xmlTextWriterWriteFormatAttribute( writer, BAD_CAST( "next" ), "%p", GetNext() );
+ xmlTextWriterWriteFormatAttribute( writer, BAD_CAST( "prev" ), "%p", GetPrev() );
+ xmlTextWriterWriteFormatAttribute( writer, BAD_CAST( "upper" ), "%p", this->GetUpper() );
+ xmlTextWriterWriteFormatAttribute( writer, BAD_CAST( "lower" ), "%p", this->GetLower() );
+}
+
+void SwFrm::dumpChildrenAsXml( xmlTextWriterPtr writer )
+{
+ SwFrm *pFrm = GetLower( );
+ for ( ; pFrm != NULL; pFrm = pFrm->GetNext( ) )
+ {
+ pFrm->dumpAsXml( writer );
+ }
+}
+
+void SwTxtFrm::dumpAsXmlAttributes( xmlTextWriterPtr writer )
+{
+ SwFrm::dumpAsXmlAttributes( writer );
+ if ( HasFollow() )
+ xmlTextWriterWriteFormatAttribute( writer, BAD_CAST( "follow" ), "%p", GetFollow() );
+}
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/tox/tox.cxx b/sw/source/core/tox/tox.cxx
new file mode 100644
index 000000000000..3ae878c5a2c2
--- /dev/null
+++ b/sw/source/core/tox/tox.cxx
@@ -0,0 +1,935 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+#include <tools/resid.hxx>
+#include <hintids.hxx>
+#include <swtypes.hxx>
+#include <txtatr.hxx>
+#include <ndtxt.hxx>
+#include <txttxmrk.hxx>
+#include <tox.hxx>
+#include <poolfmt.hrc>
+#include <doc.hxx>
+#include <docary.hxx>
+#include <paratr.hxx>
+#include <editeng/tstpitem.hxx>
+#include <SwStyleNameMapper.hxx>
+#include <hints.hxx> // SwPtrMsgPoolItem
+#include <algorithm>
+#include <functional>
+#include <switerator.hxx>
+
+using namespace std;
+
+const sal_Char* SwForm::aFormEntry = "<E>";
+const sal_Char* SwForm::aFormTab = "<T>";
+const sal_Char* SwForm::aFormPageNums = "<#>";
+const sal_Char* SwForm::aFormLinkStt = "<LS>";
+const sal_Char* SwForm::aFormLinkEnd = "<LE>";
+const sal_Char* SwForm::aFormEntryNum = "<E#>";
+const sal_Char* SwForm::aFormEntryTxt = "<ET>";
+const sal_Char* SwForm::aFormChapterMark= "<C>";
+const sal_Char* SwForm::aFormText = "<X>";
+const sal_Char* SwForm::aFormAuth = "<A>";
+sal_uInt8 SwForm::nFormTabLen = 3;
+sal_uInt8 SwForm::nFormEntryLen = 3;
+sal_uInt8 SwForm::nFormPageNumsLen = 3;
+sal_uInt8 SwForm::nFormLinkSttLen = 4;
+sal_uInt8 SwForm::nFormLinkEndLen = 4;
+sal_uInt8 SwForm::nFormEntryNumLen = 4;
+sal_uInt8 SwForm::nFormEntryTxtLen = 4;
+sal_uInt8 SwForm::nFormChapterMarkLen = 3;
+sal_uInt8 SwForm::nFormTextLen = 3;
+sal_uInt8 SwForm::nFormAuthLen = 5;
+
+SV_IMPL_PTRARR(SwTOXMarks, SwTOXMark*)
+
+TYPEINIT2( SwTOXMark, SfxPoolItem, SwClient ); // fuers rtti
+
+struct PatternIni
+{
+ sal_uInt16 n1;
+ sal_uInt16 n2;
+ sal_uInt16 n3;
+ sal_uInt16 n4;
+ sal_uInt16 n5;
+};
+const PatternIni aPatternIni[] =
+{
+ {USHRT_MAX, USHRT_MAX, USHRT_MAX, USHRT_MAX, USHRT_MAX}, //Header - no pattern
+ {AUTH_FIELD_AUTHOR, AUTH_FIELD_TITLE, AUTH_FIELD_YEAR, USHRT_MAX, USHRT_MAX}, //AUTH_TYPE_ARTICLE,
+ {AUTH_FIELD_AUTHOR, AUTH_FIELD_TITLE, AUTH_FIELD_YEAR, USHRT_MAX, USHRT_MAX}, //AUTH_TYPE_BOOK,
+ {AUTH_FIELD_AUTHOR, AUTH_FIELD_TITLE, AUTH_FIELD_YEAR, USHRT_MAX, USHRT_MAX}, //AUTH_TYPE_BOOKLET,
+ {AUTH_FIELD_AUTHOR, AUTH_FIELD_TITLE, AUTH_FIELD_YEAR, USHRT_MAX, USHRT_MAX}, //AUTH_TYPE_CONFERENCE,
+ {AUTH_FIELD_AUTHOR, AUTH_FIELD_TITLE, AUTH_FIELD_YEAR, USHRT_MAX, USHRT_MAX}, //AUTH_TYPE_INBOOK,
+ {AUTH_FIELD_AUTHOR, AUTH_FIELD_TITLE, AUTH_FIELD_YEAR, USHRT_MAX, USHRT_MAX}, //AUTH_TYPE_INCOLLECTION,
+ {AUTH_FIELD_AUTHOR, AUTH_FIELD_TITLE, AUTH_FIELD_YEAR, USHRT_MAX, USHRT_MAX}, //AUTH_TYPE_INPROCEEDINGS,
+ {AUTH_FIELD_AUTHOR, AUTH_FIELD_TITLE, AUTH_FIELD_YEAR, USHRT_MAX, USHRT_MAX}, //AUTH_TYPE_JOURNAL,
+ {AUTH_FIELD_AUTHOR, AUTH_FIELD_TITLE, AUTH_FIELD_YEAR, USHRT_MAX, USHRT_MAX}, //AUTH_TYPE_MANUAL,
+ {AUTH_FIELD_AUTHOR, AUTH_FIELD_TITLE, AUTH_FIELD_YEAR, USHRT_MAX, USHRT_MAX}, //AUTH_TYPE_MASTERSTHESIS,
+ {AUTH_FIELD_AUTHOR, AUTH_FIELD_TITLE, AUTH_FIELD_YEAR, USHRT_MAX, USHRT_MAX}, //AUTH_TYPE_MISC,
+ {AUTH_FIELD_AUTHOR, AUTH_FIELD_TITLE, AUTH_FIELD_YEAR, USHRT_MAX, USHRT_MAX}, //AUTH_TYPE_PHDTHESIS,
+ {AUTH_FIELD_AUTHOR, AUTH_FIELD_TITLE, AUTH_FIELD_YEAR, USHRT_MAX, USHRT_MAX}, //AUTH_TYPE_PROCEEDINGS,
+ {AUTH_FIELD_AUTHOR, AUTH_FIELD_TITLE, AUTH_FIELD_YEAR, USHRT_MAX, USHRT_MAX}, //AUTH_TYPE_TECHREPORT,
+ {AUTH_FIELD_AUTHOR, AUTH_FIELD_TITLE, AUTH_FIELD_YEAR, USHRT_MAX, USHRT_MAX}, //AUTH_TYPE_UNPUBLISHED,
+ {AUTH_FIELD_AUTHOR, AUTH_FIELD_TITLE, AUTH_FIELD_YEAR, USHRT_MAX, USHRT_MAX}, //AUTH_TYPE_EMAIL,
+ {AUTH_FIELD_AUTHOR, AUTH_FIELD_TITLE, AUTH_FIELD_YEAR, AUTH_FIELD_URL, USHRT_MAX},//AUTH_TYPE_WWW,
+ {AUTH_FIELD_AUTHOR, AUTH_FIELD_TITLE, AUTH_FIELD_YEAR, USHRT_MAX, USHRT_MAX}, //AUTH_TYPE_CUSTOM1,
+ {AUTH_FIELD_AUTHOR, AUTH_FIELD_TITLE, AUTH_FIELD_YEAR, USHRT_MAX, USHRT_MAX}, //AUTH_TYPE_CUSTOM2,
+ {AUTH_FIELD_AUTHOR, AUTH_FIELD_TITLE, AUTH_FIELD_YEAR, USHRT_MAX, USHRT_MAX}, //AUTH_TYPE_CUSTOM3,
+ {AUTH_FIELD_AUTHOR, AUTH_FIELD_TITLE, AUTH_FIELD_YEAR, USHRT_MAX, USHRT_MAX}, //AUTH_TYPE_CUSTOM4,
+ {AUTH_FIELD_AUTHOR, AUTH_FIELD_TITLE, AUTH_FIELD_YEAR, USHRT_MAX, USHRT_MAX}, //AUTH_TYPE_CUSTOM5,
+ {AUTH_FIELD_AUTHOR, AUTH_FIELD_TITLE, AUTH_FIELD_YEAR, USHRT_MAX, USHRT_MAX}, //AUTH_FIELD_YEAR,
+ {AUTH_FIELD_AUTHOR, AUTH_FIELD_TITLE, AUTH_FIELD_YEAR, USHRT_MAX, USHRT_MAX}, //AUTH_FIELD_URL,
+ {AUTH_FIELD_AUTHOR, AUTH_FIELD_TITLE, AUTH_FIELD_YEAR, USHRT_MAX, USHRT_MAX}, //AUTH_FIELD_CUSTOM1,
+ {AUTH_FIELD_AUTHOR, AUTH_FIELD_TITLE, AUTH_FIELD_YEAR, USHRT_MAX, USHRT_MAX}, //AUTH_FIELD_CUSTOM2,
+ {AUTH_FIELD_AUTHOR, AUTH_FIELD_TITLE, AUTH_FIELD_YEAR, USHRT_MAX, USHRT_MAX}, //AUTH_FIELD_CUSTOM3,
+ {AUTH_FIELD_AUTHOR, AUTH_FIELD_TITLE, AUTH_FIELD_YEAR, USHRT_MAX, USHRT_MAX}, //AUTH_FIELD_CUSTOM4,
+ {AUTH_FIELD_AUTHOR, AUTH_FIELD_TITLE, AUTH_FIELD_YEAR, USHRT_MAX, USHRT_MAX}, //AUTH_FIELD_CUSTOM5,
+ {USHRT_MAX, USHRT_MAX, USHRT_MAX, USHRT_MAX, USHRT_MAX}
+};
+
+SwFormTokens lcl_GetAuthPattern(sal_uInt16 nTypeId)
+{
+ SwFormTokens aRet;
+
+ PatternIni aIni = aPatternIni[nTypeId];
+ sal_uInt16 nVals[5];
+ nVals[0] = aIni.n1;
+ nVals[1] = aIni.n2;
+ nVals[2] = aIni.n3;
+ nVals[3] = aIni.n4;
+ nVals[4] = aIni.n5;
+
+ SwFormToken aStartToken( TOKEN_AUTHORITY );
+ aStartToken.nAuthorityField = AUTH_FIELD_IDENTIFIER;
+ aRet.push_back( aStartToken );
+ SwFormToken aSeparatorToken( TOKEN_TEXT );
+ aSeparatorToken.sText = String::CreateFromAscii( ": " );
+ aRet.push_back( aSeparatorToken );
+ SwFormToken aTextToken( TOKEN_TEXT );
+ aTextToken.sText = String::CreateFromAscii( ", " );
+
+ for(sal_uInt16 i = 0; i < 5 ; i++)
+ {
+ if(nVals[i] == USHRT_MAX)
+ break;
+ if( i > 0 )
+ aRet.push_back( aTextToken );
+
+ // -> #i21237#
+ SwFormToken aToken(TOKEN_AUTHORITY);
+
+ aToken.nAuthorityField = nVals[i];
+ aRet.push_back(aToken);
+ // <- #i21237#
+ }
+
+ return aRet;
+}
+/*--------------------------------------------------------------------
+ Beschreibung: Verzeichnis-Markierungen D/Ctor
+ --------------------------------------------------------------------*/
+
+
+/// pool default constructor
+SwTOXMark::SwTOXMark()
+ : SfxPoolItem( RES_TXTATR_TOXMARK )
+ , SwModify( 0 )
+ ,
+ pTxtAttr( 0 ),
+ bAutoGenerated(sal_False),
+ bMainEntry(sal_False)
+{
+}
+
+
+SwTOXMark::SwTOXMark( const SwTOXType* pTyp )
+ : SfxPoolItem( RES_TXTATR_TOXMARK )
+ , SwModify( const_cast<SwTOXType*>(pTyp) )
+ ,
+ pTxtAttr( 0 ), nLevel( 0 ),
+ bAutoGenerated(sal_False),
+ bMainEntry(sal_False)
+{
+}
+
+
+SwTOXMark::SwTOXMark( const SwTOXMark& rCopy )
+ : SfxPoolItem( RES_TXTATR_TOXMARK )
+ , SwModify(rCopy.GetRegisteredInNonConst())
+ ,
+ aPrimaryKey( rCopy.aPrimaryKey ), aSecondaryKey( rCopy.aSecondaryKey ),
+ aTextReading( rCopy.aTextReading ),
+ aPrimaryKeyReading( rCopy.aPrimaryKeyReading ),
+ aSecondaryKeyReading( rCopy.aSecondaryKeyReading ),
+ pTxtAttr( 0 ), nLevel( rCopy.nLevel ),
+ bAutoGenerated( rCopy.bAutoGenerated),
+ bMainEntry(rCopy.bMainEntry)
+{
+ // AlternativString kopieren
+ aAltText = rCopy.aAltText;
+}
+
+
+SwTOXMark::~SwTOXMark()
+{
+}
+
+
+void SwTOXMark::RegisterToTOXType( SwTOXType& rMark )
+{
+ rMark.Add(this);
+}
+
+int SwTOXMark::operator==( const SfxPoolItem& rAttr ) const
+{
+ OSL_ENSURE( SfxPoolItem::operator==( rAttr ), "keine gleichen Attribute" );
+ return GetRegisteredIn() == ((SwTOXMark&)rAttr).GetRegisteredIn();
+}
+
+
+SfxPoolItem* SwTOXMark::Clone( SfxItemPool* ) const
+{
+ return new SwTOXMark( *this );
+}
+
+void SwTOXMark::Modify( const SfxPoolItem* pOld, const SfxPoolItem* pNew)
+{
+ NotifyClients(pOld, pNew);
+ if (pOld && (RES_REMOVE_UNO_OBJECT == pOld->Which()))
+ { // invalidate cached uno object
+ SetXTOXMark(::com::sun::star::uno::Reference<
+ ::com::sun::star::text::XDocumentIndexMark>(0));
+ }
+}
+
+void SwTOXMark::InvalidateTOXMark()
+{
+ SwPtrMsgPoolItem aMsgHint( RES_REMOVE_UNO_OBJECT,
+ &static_cast<SwModify&>(*this) ); // cast to base class!
+ NotifyClients(&aMsgHint, &aMsgHint);
+}
+
+String SwTOXMark::GetText() const
+{
+ String aStr;
+ if( aAltText.Len() )
+ aStr = aAltText;
+ else if( pTxtAttr && pTxtAttr->GetpTxtNd() )
+ {
+ xub_StrLen* pEndIdx = pTxtAttr->GetEnd();
+ OSL_ENSURE( pEndIdx, "TOXMark ohne Mark!!");
+ if( pEndIdx )
+ {
+ const xub_StrLen nStt = *pTxtAttr->GetStart();
+ aStr = pTxtAttr->GetpTxtNd()->GetExpandTxt( nStt, *pEndIdx-nStt );
+ }
+ }
+ return aStr;
+}
+
+void SwTOXMark::InsertTOXMarks( SwTOXMarks& aMarks, const SwTOXType& rType )
+{
+ SwIterator<SwTOXMark,SwTOXType> aIter(rType);
+ SwTOXMark* pMark = aIter.First();
+ while( pMark )
+ {
+ if(pMark->GetTxtTOXMark())
+ aMarks.C40_INSERT(SwTOXMark, pMark, aMarks.Count());
+ pMark = aIter.Next();
+ }
+}
+
+/*--------------------------------------------------------------------
+ Beschreibung: Typen von Verzeichnissen verwalten
+ --------------------------------------------------------------------*/
+
+SwTOXType::SwTOXType( TOXTypes eTyp, const String& rName )
+ : SwModify(0),
+ aName(rName),
+ eType(eTyp)
+{
+}
+
+
+SwTOXType::SwTOXType(const SwTOXType& rCopy)
+ : SwModify( (SwModify*)rCopy.GetRegisteredIn() ),
+ aName(rCopy.aName),
+ eType(rCopy.eType)
+{
+}
+
+/*--------------------------------------------------------------------
+ Beschreibung: Formen bearbeiten
+ --------------------------------------------------------------------*/
+
+SwForm::SwForm( TOXTypes eTyp ) // #i21237#
+ : eType( eTyp ), nFormMaxLevel( SwForm::GetFormMaxLevel( eTyp )),
+// nFirstTabPos( lNumIndent ),
+ bCommaSeparated(sal_False)
+{
+ //bHasFirstTabPos =
+ bGenerateTabPos = sal_False;
+ bIsRelTabPos = sal_True;
+
+ // Inhaltsverzeichnis hat entsprechend Anzahl Headlines + Ueberschrift
+ // Benutzer hat 10 Ebenen + Ueberschrift
+ // Stichwort hat 3 Ebenen + Ueberschrift + Trenner
+ // indexes of tables, objects illustrations and authorities consist of a heading and one level
+
+ sal_uInt16 nPoolId;
+ switch( eType )
+ {
+ case TOX_INDEX: nPoolId = STR_POOLCOLL_TOX_IDXH; break;
+ case TOX_USER: nPoolId = STR_POOLCOLL_TOX_USERH; break;
+ case TOX_CONTENT: nPoolId = STR_POOLCOLL_TOX_CNTNTH; break;
+ case TOX_ILLUSTRATIONS: nPoolId = STR_POOLCOLL_TOX_ILLUSH; break;
+ case TOX_OBJECTS : nPoolId = STR_POOLCOLL_TOX_OBJECTH; break;
+ case TOX_TABLES : nPoolId = STR_POOLCOLL_TOX_TABLESH; break;
+ case TOX_AUTHORITIES : nPoolId = STR_POOLCOLL_TOX_AUTHORITIESH; break;
+ default:
+ OSL_ENSURE( !this, "ungueltiger TOXTyp");
+ return ;
+ }
+
+ SwFormTokens aTokens;
+ if (TOX_CONTENT == eType)
+ {
+ aTokens.push_back(SwFormToken(TOKEN_ENTRY_NO));
+ aTokens.push_back(SwFormToken(TOKEN_ENTRY_TEXT));
+ }
+ else
+ aTokens.push_back(SwFormToken(TOKEN_ENTRY));
+
+ if (TOX_AUTHORITIES != eType)
+ {
+ SwFormToken aToken(TOKEN_TAB_STOP);
+ aToken.nTabStopPosition = 0;
+
+ // --> FME 2004-12-10 #i36870# right aligned tab for all
+ aToken.cTabFillChar = '.';
+ aToken.eTabAlign = SVX_TAB_ADJUST_END;
+ // <--
+
+ aTokens.push_back(aToken);
+ aTokens.push_back(SwFormToken(TOKEN_PAGE_NUMS));
+ }
+
+ SetTemplate( 0, SW_RESSTR( nPoolId++ ));
+
+ if(TOX_INDEX == eType)
+ {
+ for( sal_uInt16 i = 1; i < 5; ++i )
+ {
+ if(1 == i)
+ {
+ SwFormTokens aTmpTokens;
+ SwFormToken aTmpToken(TOKEN_ENTRY);
+ aTmpTokens.push_back(aTmpToken);
+
+ SetPattern( i, aTmpTokens );
+ SetTemplate( i, SW_RESSTR( STR_POOLCOLL_TOX_IDXBREAK ));
+ }
+ else
+ {
+ SetPattern( i, aTokens );
+ SetTemplate( i, SW_RESSTR( STR_POOLCOLL_TOX_IDX1 + i - 2 ));
+ }
+ }
+ }
+ else
+ for( sal_uInt16 i = 1; i < GetFormMax(); ++i, ++nPoolId ) // Nr 0 ist der Titel
+ {
+ if(TOX_AUTHORITIES == eType)
+ SetPattern(i, lcl_GetAuthPattern(i));
+ else
+ SetPattern( i, aTokens );
+
+ if( TOX_CONTENT == eType && 6 == i )
+ nPoolId = STR_POOLCOLL_TOX_CNTNT6;
+ else if( TOX_USER == eType && 6 == i )
+ nPoolId = STR_POOLCOLL_TOX_USER6;
+ else if( TOX_AUTHORITIES == eType )
+ nPoolId = STR_POOLCOLL_TOX_AUTHORITIES1;
+ SetTemplate( i, SW_RESSTR( nPoolId ) );
+ }
+}
+
+
+SwForm::SwForm(const SwForm& rForm)
+ : eType( rForm.eType )
+{
+ *this = rForm;
+}
+
+
+SwForm& SwForm::operator=(const SwForm& rForm)
+{
+ eType = rForm.eType;
+ nFormMaxLevel = rForm.nFormMaxLevel;
+// nFirstTabPos = rForm.nFirstTabPos;
+// bHasFirstTabPos = rForm.bHasFirstTabPos;
+ bGenerateTabPos = rForm.bGenerateTabPos;
+ bIsRelTabPos = rForm.bIsRelTabPos;
+ bCommaSeparated = rForm.bCommaSeparated;
+ for(sal_uInt16 i=0; i < nFormMaxLevel; ++i)
+ {
+ aPattern[i] = rForm.aPattern[i];
+ aTemplate[i] = rForm.aTemplate[i];
+ }
+ return *this;
+}
+
+sal_uInt16 SwForm::GetFormMaxLevel( TOXTypes eTOXType )
+{
+ sal_uInt16 nRet = 0;
+ switch( eTOXType )
+ {
+ case TOX_INDEX: nRet = 5; break;
+ case TOX_USER: nRet = MAXLEVEL+1; break;
+ case TOX_CONTENT: nRet = MAXLEVEL+1; break;
+ case TOX_ILLUSTRATIONS:
+ case TOX_OBJECTS :
+ case TOX_TABLES : nRet = 2; break;
+ case TOX_AUTHORITIES : nRet = AUTH_TYPE_END + 1; break;
+ }
+ return nRet;
+}
+
+// #i21237#
+bool operator == (const SwFormToken & rToken, FormTokenType eType)
+{
+ return rToken.eTokenType == eType;
+}
+
+//-----------------------------------------------------------------------------
+void SwForm::AdjustTabStops(SwDoc& rDoc, sal_Bool bInsertNewTapStops) // #i21237#
+{
+ for(sal_uInt16 nLevel = 1; nLevel < GetFormMax(); nLevel++)
+ {
+ const String& sTemplateName = GetTemplate(nLevel);
+
+ SwTxtFmtColl* pColl = rDoc.FindTxtFmtCollByName( sTemplateName );
+ if( !pColl )
+ {
+ sal_uInt16 nId = SwStyleNameMapper::GetPoolIdFromUIName
+ ( sTemplateName, nsSwGetPoolIdFromName::GET_POOLID_TXTCOLL ); // #i21237#
+ if( USHRT_MAX != nId )
+ pColl = rDoc.GetTxtCollFromPool( nId );
+ }
+
+ const SvxTabStopItem* pTabStops = 0;
+ sal_uInt16 nTabCount = 0;
+ if( pColl &&
+ 0 != ( pTabStops = &pColl->GetTabStops(sal_False) ) &&
+ 0 != ( nTabCount = pTabStops->Count() ) )
+ {
+ // #i21237#
+ SwFormTokens aCurrentPattern = GetPattern(nLevel);
+ SwFormTokens::iterator aIt = aCurrentPattern.begin();
+
+ sal_Bool bChanged = sal_False;
+
+ for(sal_uInt16 nTab = 0; nTab < nTabCount; ++nTab)
+ {
+ const SvxTabStop& rTab = (*pTabStops)[nTab];
+
+ // --> FME 2004-12-16 #i29178#
+ // For Word import, we do not want to replace exising tokens,
+ // we insert new tabstop tokens without a tabstop character:
+ if ( bInsertNewTapStops )
+ {
+ if ( SVX_TAB_ADJUST_DEFAULT != rTab.GetAdjustment() )
+ {
+ bChanged = sal_True;
+ SwFormToken aToken(TOKEN_TAB_STOP);
+ aToken.bWithTab = sal_False;
+ aToken.nTabStopPosition = rTab.GetTabPos();
+ aToken.eTabAlign = rTab.GetAdjustment();
+ aToken.cTabFillChar = rTab.GetFill();
+ aCurrentPattern.push_back(aToken);
+ }
+ }
+ // <--
+ else
+ {
+ aIt = find_if(aIt, aCurrentPattern.end(),
+ SwFormTokenEqualToFormTokenType
+ (TOKEN_TAB_STOP));
+ if ( aIt != aCurrentPattern.end() )
+ {
+ bChanged = sal_True;
+ aIt->nTabStopPosition = rTab.GetTabPos();
+ aIt->eTabAlign = nTab == nTabCount - 1 &&
+ SVX_TAB_ADJUST_RIGHT == rTab.GetAdjustment() ?
+ SVX_TAB_ADJUST_END :
+ rTab.GetAdjustment();
+ aIt->cTabFillChar = rTab.GetFill();
+ ++aIt;
+ }
+ else
+ break; // no more tokens to replace
+ }
+ }
+ // <--
+
+ if(bChanged)
+ SetPattern(nLevel, aCurrentPattern); // #i21237#
+ }
+ }
+}
+/*--------------------------------------------------------------------
+ Beschreibung: Ctor TOXBase
+ --------------------------------------------------------------------*/
+
+
+SwTOXBase::SwTOXBase(const SwTOXType* pTyp, const SwForm& rForm,
+ sal_uInt16 nCreaType, const String& rTitle )
+ : SwClient((SwModify*)pTyp),
+ aForm(rForm),
+ aTitle(rTitle),
+ eLanguage((LanguageType)::GetAppLanguage()),
+ nCreateType(nCreaType),
+ nOLEOptions(0),
+ eCaptionDisplay(CAPTION_COMPLETE),
+ bProtected( sal_True ),
+ bFromChapter(sal_False),
+ bFromObjectNames(sal_False),
+ bLevelFromChapter(sal_False)
+{
+ aData.nOptions = 0;
+}
+
+
+SwTOXBase::SwTOXBase( const SwTOXBase& rSource, SwDoc* pDoc )
+ : SwClient( rSource.GetRegisteredInNonConst() )
+{
+ CopyTOXBase( pDoc, rSource );
+}
+
+void SwTOXBase::RegisterToTOXType( SwTOXType& rType )
+{
+ rType.Add( this );
+}
+
+SwTOXBase& SwTOXBase::CopyTOXBase( SwDoc* pDoc, const SwTOXBase& rSource )
+{
+ SwTOXType* pType = (SwTOXType*)rSource.GetTOXType();
+ if( pDoc && USHRT_MAX == pDoc->GetTOXTypes().GetPos( pType ))
+ {
+ // type not in pDoc, so create it now
+ const SwTOXTypes& rTypes = pDoc->GetTOXTypes();
+ sal_Bool bFound = sal_False;
+ for( sal_uInt16 n = rTypes.Count(); n; )
+ {
+ const SwTOXType* pCmp = rTypes[ --n ];
+ if( pCmp->GetType() == pType->GetType() &&
+ pCmp->GetTypeName() == pType->GetTypeName() )
+ {
+ pType = (SwTOXType*)pCmp;
+ bFound = sal_True;
+ break;
+ }
+ }
+
+ if( !bFound )
+ pType = (SwTOXType*)pDoc->InsertTOXType( *pType );
+ }
+ pType->Add( this );
+
+ nCreateType = rSource.nCreateType;
+ aTitle = rSource.aTitle;
+ aForm = rSource.aForm;
+ bProtected = rSource.bProtected;
+ bFromChapter = rSource.bFromChapter;
+ bFromObjectNames = rSource.bFromObjectNames;
+ sMainEntryCharStyle = rSource.sMainEntryCharStyle;
+ sSequenceName = rSource.sSequenceName;
+ eCaptionDisplay = rSource.eCaptionDisplay;
+ nOLEOptions = rSource.nOLEOptions;
+ eLanguage = rSource.eLanguage;
+ sSortAlgorithm = rSource.sSortAlgorithm;
+
+ for( sal_uInt16 i = 0; i < MAXLEVEL; ++i )
+ aStyleNames[i] = rSource.aStyleNames[i];
+
+ // its the same data type!
+ aData.nOptions = rSource.aData.nOptions;
+
+ if( !pDoc || pDoc->IsCopyIsMove() )
+ aName = rSource.GetTOXName();
+ else
+ aName = pDoc->GetUniqueTOXBaseName( *pType, &rSource.GetTOXName() );
+
+ return *this;
+}
+
+/*--------------------------------------------------------------------
+ Beschreibung: Verzeichnisspezifische Funktionen
+ --------------------------------------------------------------------*/
+
+SwTOXBase::~SwTOXBase()
+{
+// if( GetTOXType()->GetType() == TOX_USER )
+// delete aData.pTemplateName;
+}
+
+void SwTOXBase::SetTitle(const String& rTitle)
+ { aTitle = rTitle; }
+
+
+SwTOXBase & SwTOXBase::operator = (const SwTOXBase & rSource)
+{
+ ByteString aTmpStr(aTitle, RTL_TEXTENCODING_ASCII_US);
+ ByteString aTmpStr1(rSource.aTitle, RTL_TEXTENCODING_ASCII_US);
+
+ aForm = rSource.aForm;
+ aName = rSource.aName;
+ aTitle = rSource.aTitle;
+ sMainEntryCharStyle = rSource.sMainEntryCharStyle;
+ for(sal_uInt16 nLevel = 0; nLevel < MAXLEVEL; nLevel++)
+ aStyleNames[nLevel] = rSource.aStyleNames[nLevel];
+ sSequenceName = rSource.sSequenceName;
+ eLanguage = rSource.eLanguage;
+ sSortAlgorithm = rSource.sSortAlgorithm;
+ aData = rSource.aData;
+ nCreateType = rSource.nCreateType;
+ nOLEOptions = rSource.nOLEOptions;
+ eCaptionDisplay = rSource.eCaptionDisplay;
+ bProtected = rSource.bProtected;
+ bFromChapter = rSource.bFromChapter;
+ bFromObjectNames = rSource.bFromObjectNames;
+ bLevelFromChapter = rSource.bLevelFromChapter;
+
+ if (rSource.GetAttrSet())
+ SetAttrSet(*rSource.GetAttrSet());
+
+ return *this;
+}
+
+String SwFormToken::GetString() const
+{
+ String sRet;
+
+ sal_Bool bAppend = sal_True;
+ switch( eTokenType )
+ {
+ case TOKEN_ENTRY_NO:
+ sRet.AssignAscii( SwForm::aFormEntryNum );
+ break;
+ case TOKEN_ENTRY_TEXT:
+ sRet.AssignAscii( SwForm::aFormEntryTxt );
+ break;
+ case TOKEN_ENTRY:
+ sRet.AssignAscii( SwForm::aFormEntry );
+ break;
+ case TOKEN_TAB_STOP:
+ sRet.AssignAscii( SwForm::aFormTab );
+ break;
+ case TOKEN_TEXT:
+ sRet.AssignAscii( SwForm::aFormText );
+ break;
+ case TOKEN_PAGE_NUMS:
+ sRet.AssignAscii( SwForm::aFormPageNums );
+ break;
+ case TOKEN_CHAPTER_INFO:
+ sRet.AssignAscii( SwForm::aFormChapterMark );
+ break;
+ case TOKEN_LINK_START:
+ sRet.AssignAscii( SwForm::aFormLinkStt );
+ break;
+ case TOKEN_LINK_END:
+ sRet.AssignAscii( SwForm::aFormLinkEnd );
+ break;
+ case TOKEN_AUTHORITY:
+ {
+ sRet.AssignAscii( SwForm::aFormAuth );
+ String sTmp( String::CreateFromInt32( nAuthorityField ));
+ if( sTmp.Len() < 2 )
+ sTmp.Insert('0', 0);
+ sRet.Insert( sTmp, 2 );
+ }
+ break;
+ case TOKEN_END:
+ break;
+ }
+ sRet.Erase( sRet.Len() - 1 );
+ sRet += ' ';
+ sRet += sCharStyleName;
+ sRet += ',';
+ sRet += String::CreateFromInt32( nPoolId );
+ sRet += ',';
+
+ // TabStopPosition and TabAlign or ChapterInfoFormat
+ if(TOKEN_TAB_STOP == eTokenType)
+ {
+ sRet += String::CreateFromInt32( nTabStopPosition );
+ sRet += ',';
+ sRet += String::CreateFromInt32( static_cast< sal_Int32 >(eTabAlign) );
+ sRet += ',';
+ sRet += cTabFillChar;
+ sRet += ',';
+ sRet += String::CreateFromInt32( bWithTab );
+ }
+ else if(TOKEN_CHAPTER_INFO == eTokenType)
+ {
+ sRet += String::CreateFromInt32( nChapterFormat );
+//add maximum permetted level
+ sRet += ',';
+ sRet += String::CreateFromInt32( nOutlineLevel );
+ }
+ else if(TOKEN_TEXT == eTokenType)
+ {
+ //append Text if Len() > 0 only!
+ if( sText.Len() )
+ {
+ sRet += TOX_STYLE_DELIMITER;
+ String sTmp( sText );
+ sTmp.EraseAllChars( TOX_STYLE_DELIMITER );
+ sRet += sTmp;
+ sRet += TOX_STYLE_DELIMITER;
+ }
+ else
+ bAppend = sal_False;
+ }
+ else if(TOKEN_ENTRY_NO == eTokenType)
+ {
+ sRet += String::CreateFromInt32( nChapterFormat );
+//add maximum permitted level
+ sRet += ',';
+ sRet += String::CreateFromInt32( nOutlineLevel );
+ }
+
+ if(bAppend)
+ {
+ sRet += '>';
+ }
+ else
+ {
+ // don't append empty text tokens
+ sRet.Erase();
+ }
+
+ return sRet;
+}
+
+// -> #i21237#
+SwFormTokensHelper::SwFormTokensHelper(const String & rPattern)
+{
+ xub_StrLen nCurPatternPos = 0;
+ xub_StrLen nCurPatternLen = 0;
+
+ while (nCurPatternPos < rPattern.Len())
+ {
+ nCurPatternPos = nCurPatternPos + nCurPatternLen;
+
+ SwFormToken aToken = BuildToken(rPattern, nCurPatternPos);
+ aTokens.push_back(aToken);
+ }
+}
+
+SwFormToken SwFormTokensHelper::BuildToken( const String & sPattern,
+ xub_StrLen & nCurPatternPos ) const
+{
+ String sToken( SearchNextToken(sPattern, nCurPatternPos) );
+ nCurPatternPos = nCurPatternPos + sToken.Len();
+ xub_StrLen nTokenLen;
+ FormTokenType eTokenType = GetTokenType(sToken, &nTokenLen);
+
+ // at this point sPattern contains the
+ // character style name, the PoolId, tab stop position, tab stop alignment, chapter info format
+ // the form is: CharStyleName, PoolId[, TabStopPosition|ChapterInfoFormat[, TabStopAlignment[, TabFillChar]]]
+ // in text tokens the form differs from the others: CharStyleName, PoolId[,\0xffinserted text\0xff]
+ SwFormToken eRet( eTokenType );
+ String sAuthFieldEnum = sToken.Copy( 2, 2 );
+ sToken = sToken.Copy( nTokenLen, sToken.Len() - nTokenLen - 1);
+
+ eRet.sCharStyleName = sToken.GetToken( 0, ',');
+ String sTmp( sToken.GetToken( 1, ',' ));
+ if( sTmp.Len() )
+ eRet.nPoolId = static_cast<sal_uInt16>(sTmp.ToInt32());
+
+ switch( eTokenType )
+ {
+//i53420
+ case TOKEN_ENTRY_NO:
+ if( (sTmp = sToken.GetToken( 2, ',' ) ).Len() )
+ eRet.nChapterFormat = static_cast<sal_uInt16>(sTmp.ToInt32());
+ if( (sTmp = sToken.GetToken( 3, ',' ) ).Len() )
+ eRet.nOutlineLevel = static_cast<sal_uInt16>(sTmp.ToInt32()); //the maximum outline level to examine
+ break;
+
+ case TOKEN_TEXT:
+ {
+ xub_StrLen nStartText = sToken.Search( TOX_STYLE_DELIMITER );
+ if( STRING_NOTFOUND != nStartText )
+ {
+ xub_StrLen nEndText = sToken.Search( TOX_STYLE_DELIMITER,
+ nStartText + 1);
+ if( STRING_NOTFOUND != nEndText )
+ {
+ eRet.sText = sToken.Copy( nStartText + 1,
+ nEndText - nStartText - 1);
+ }
+ }
+ }
+ break;
+
+ case TOKEN_TAB_STOP:
+ if( (sTmp = sToken.GetToken( 2, ',' ) ).Len() )
+ eRet.nTabStopPosition = sTmp.ToInt32();
+
+ if( (sTmp = sToken.GetToken( 3, ',' ) ).Len() )
+ eRet.eTabAlign = static_cast<SvxTabAdjust>(sTmp.ToInt32());
+
+ if( (sTmp = sToken.GetToken( 4, ',' ) ).Len() )
+ eRet.cTabFillChar = sTmp.GetChar(0);
+
+ if( (sTmp = sToken.GetToken( 5, ',' ) ).Len() )
+ eRet.bWithTab = 0 != sTmp.ToInt32();
+ break;
+
+ case TOKEN_CHAPTER_INFO:
+ if( (sTmp = sToken.GetToken( 2, ',' ) ).Len() )
+ eRet.nChapterFormat = static_cast<sal_uInt16>(sTmp.ToInt32()); //SwChapterFormat;
+ //i53420
+ if( (sTmp = sToken.GetToken( 3, ',' ) ).Len() )
+ eRet.nOutlineLevel = static_cast<sal_uInt16>(sTmp.ToInt32()); //the maximum outline level to examine
+
+ break;
+
+ case TOKEN_AUTHORITY:
+ eRet.nAuthorityField = static_cast<sal_uInt16>(sAuthFieldEnum.ToInt32());
+ break;
+ default: break;
+ }
+ return eRet;
+}
+
+String SwFormTokensHelper::SearchNextToken( const String & sPattern,
+ xub_StrLen nStt ) const
+{
+ //it's not so easy - it doesn't work if the text part contains a '>'
+ //sal_uInt16 nTokenEnd = sPattern.Search('>');
+
+ String aResult;
+
+ xub_StrLen nEnd = sPattern.Search( '>', nStt );
+ if( STRING_NOTFOUND == nEnd )
+ {
+ nEnd = sPattern.Len();
+ }
+ else
+ {
+ xub_StrLen nTextSeparatorFirst = sPattern.Search( TOX_STYLE_DELIMITER, nStt );
+ if( STRING_NOTFOUND != nTextSeparatorFirst )
+ {
+ xub_StrLen nTextSeparatorSecond = sPattern.Search( TOX_STYLE_DELIMITER,
+ nTextSeparatorFirst + 1 );
+ if( STRING_NOTFOUND != nTextSeparatorSecond &&
+ nEnd > nTextSeparatorFirst )
+ nEnd = sPattern.Search( '>', nTextSeparatorSecond );
+ }
+
+ ++nEnd;
+
+ aResult = sPattern.Copy( nStt, nEnd - nStt );
+ }
+
+ return aResult;
+}
+
+FormTokenType SwFormTokensHelper::GetTokenType(const String & sToken,
+ xub_StrLen * pTokenLen) const
+{
+ static struct
+ {
+ const sal_Char* pNm;
+ sal_uInt16 nLen;
+ sal_uInt16 nOffset;
+ FormTokenType eToken;
+ } const aTokenArr[] = {
+ { SwForm::aFormTab, SwForm::nFormEntryLen, 1, TOKEN_TAB_STOP },
+ { SwForm::aFormPageNums, SwForm::nFormPageNumsLen, 1, TOKEN_PAGE_NUMS },
+ { SwForm::aFormLinkStt, SwForm::nFormLinkSttLen, 1, TOKEN_LINK_START },
+ { SwForm::aFormLinkEnd, SwForm::nFormLinkEndLen, 1, TOKEN_LINK_END },
+ { SwForm::aFormEntryNum, SwForm::nFormEntryNumLen, 1, TOKEN_ENTRY_NO },
+ { SwForm::aFormEntryTxt, SwForm::nFormEntryTxtLen, 1, TOKEN_ENTRY_TEXT },
+ { SwForm::aFormChapterMark,SwForm::nFormChapterMarkLen,1,TOKEN_CHAPTER_INFO },
+ { SwForm::aFormText, SwForm::nFormTextLen, 1, TOKEN_TEXT },
+ { SwForm::aFormEntry, SwForm::nFormEntryLen, 1, TOKEN_ENTRY },
+ { SwForm::aFormAuth, SwForm::nFormAuthLen, 3, TOKEN_AUTHORITY },
+ { 0, 0, 0, TOKEN_END }
+ };
+
+ FormTokenType eTokenType = TOKEN_TEXT;
+ xub_StrLen nTokenLen = 0;
+ const sal_Char* pNm;
+ for( int i = 0; 0 != ( pNm = aTokenArr[ i ].pNm ); ++i )
+ if( COMPARE_EQUAL == sToken.CompareToAscii( pNm,
+ aTokenArr[ i ].nLen - aTokenArr[ i ].nOffset ))
+ {
+ eTokenType = aTokenArr[ i ].eToken;
+ nTokenLen = aTokenArr[ i ].nLen;
+ break;
+ }
+
+ OSL_ENSURE( pNm, "wrong token" );
+ if (pTokenLen)
+ *pTokenLen = nTokenLen;
+
+ return eTokenType;
+}
+
+// <- #i21237#
+
+void SwForm::SetPattern(sal_uInt16 nLevel, const SwFormTokens& rTokens)
+{
+ OSL_ENSURE(nLevel < GetFormMax(), "Index >= FORM_MAX");
+ aPattern[nLevel] = rTokens;
+}
+
+void SwForm::SetPattern(sal_uInt16 nLevel, const String & rStr)
+{
+ OSL_ENSURE(nLevel < GetFormMax(), "Index >= FORM_MAX");
+
+ SwFormTokensHelper aHelper(rStr);
+ aPattern[nLevel] = aHelper.GetTokens();
+}
+
+const SwFormTokens& SwForm::GetPattern(sal_uInt16 nLevel) const
+{
+ OSL_ENSURE(nLevel < GetFormMax(), "Index >= FORM_MAX");
+ return aPattern[nLevel];
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/tox/toxhlp.cxx b/sw/source/core/tox/toxhlp.cxx
new file mode 100644
index 000000000000..02364b36cf8a
--- /dev/null
+++ b/sw/source/core/tox/toxhlp.cxx
@@ -0,0 +1,194 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+
+#include <com/sun/star/lang/XMultiServiceFactory.hpp>
+#include <comphelper/processfactory.hxx>
+#include <com/sun/star/i18n/XExtendedIndexEntrySupplier.hpp>
+#include <tools/string.hxx>
+#include <tools/debug.hxx>
+#include <toxwrap.hxx>
+
+using namespace ::com::sun::star;
+
+
+IndexEntrySupplierWrapper::IndexEntrySupplierWrapper()
+{
+ uno::Reference<
+ lang::XMultiServiceFactory > rxMSF =
+ ::comphelper::getProcessServiceFactory();
+
+ try {
+ STAR_REFERENCE( uno::XInterface ) xI =
+ rxMSF->createInstance( ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
+ "com.sun.star.i18n.IndexEntrySupplier")) );
+ if( xI.is() )
+ {
+ UNO_NMSPC::Any x = xI->queryInterface( ::getCppuType(
+ (const uno::Reference< i18n::XExtendedIndexEntrySupplier>*)0) );
+ x >>= xIES;
+ }
+ }
+ catch ( UNO_NMSPC::Exception&
+#if OSL_DEBUG_LEVEL > 1
+ e
+#endif
+ )
+ {
+#if OSL_DEBUG_LEVEL > 1
+ ByteString aMsg( "IndexEntrySupplierWrapper: Exception caught\n" );
+ aMsg += ByteString( String( e.Message ), RTL_TEXTENCODING_UTF8 );
+ DBG_ERRORFILE( aMsg.GetBuffer() );
+#endif
+ }
+}
+
+IndexEntrySupplierWrapper::~IndexEntrySupplierWrapper()
+{
+}
+
+String IndexEntrySupplierWrapper::GetIndexKey( const String& rTxt,
+ const String& rTxtReading,
+ const STAR_NMSPC::lang::Locale& rLocale ) const
+{
+ String sRet;
+ try {
+ sRet = xIES->getIndexKey( rTxt, rTxtReading, rLocale );
+ }
+ catch ( UNO_NMSPC::Exception&
+#if OSL_DEBUG_LEVEL > 1
+ e
+#endif
+ )
+ {
+#if OSL_DEBUG_LEVEL > 1
+ ByteString aMsg( "getIndexKey: Exception caught\n" );
+ aMsg += ByteString( String( e.Message ), RTL_TEXTENCODING_UTF8 );
+ DBG_ERRORFILE( aMsg.GetBuffer() );
+#endif
+ }
+ return sRet;
+}
+
+String IndexEntrySupplierWrapper::GetFollowingText( sal_Bool bMorePages ) const
+{
+ String sRet;
+ try {
+ sRet = xIES->getIndexFollowPageWord( bMorePages, aLcl );
+ }
+ catch ( UNO_NMSPC::Exception&
+#if OSL_DEBUG_LEVEL > 1
+ e
+#endif
+ )
+ {
+#if OSL_DEBUG_LEVEL > 1
+ ByteString aMsg( "getIndexFollowPageWord: Exception caught\n" );
+ aMsg += ByteString( String( e.Message ), RTL_TEXTENCODING_UTF8 );
+ DBG_ERRORFILE( aMsg.GetBuffer() );
+#endif
+ }
+ return sRet;
+}
+
+STAR_NMSPC::uno::Sequence< ::rtl::OUString >
+IndexEntrySupplierWrapper::GetAlgorithmList( const STAR_NMSPC::lang::Locale& rLcl ) const
+{
+ uno::Sequence< ::rtl::OUString > sRet;
+
+ try {
+ sRet = xIES->getAlgorithmList( rLcl );
+ }
+ catch ( UNO_NMSPC::Exception&
+#if OSL_DEBUG_LEVEL > 1
+ e
+#endif
+ )
+ {
+#if OSL_DEBUG_LEVEL > 1
+ ByteString aMsg( "getAlgorithmList: Exception caught\n" );
+ aMsg += ByteString( String( e.Message ), RTL_TEXTENCODING_UTF8 );
+ DBG_ERRORFILE( aMsg.GetBuffer() );
+#endif
+ }
+ return sRet;
+}
+
+sal_Bool IndexEntrySupplierWrapper::LoadAlgorithm(
+ const STAR_NMSPC::lang::Locale& rLcl,
+ const String& sSortAlgorithm, long nOptions ) const
+{
+ sal_Bool bRet = sal_False;
+ try {
+ bRet = xIES->loadAlgorithm( rLcl, sSortAlgorithm, nOptions );
+ }
+ catch ( UNO_NMSPC::Exception&
+#if OSL_DEBUG_LEVEL > 1
+ e
+#endif
+ )
+ {
+#if OSL_DEBUG_LEVEL > 1
+ ByteString aMsg( "loadAlgorithm: Exception caught\n" );
+ aMsg += ByteString( String( e.Message ), RTL_TEXTENCODING_UTF8 );
+ DBG_ERRORFILE( aMsg.GetBuffer() );
+#endif
+ }
+ return bRet;
+}
+
+sal_Int16 IndexEntrySupplierWrapper::CompareIndexEntry(
+ const String& rTxt1, const String& rTxtReading1,
+ const STAR_NMSPC::lang::Locale& rLocale1,
+ const String& rTxt2, const String& rTxtReading2,
+ const STAR_NMSPC::lang::Locale& rLocale2 ) const
+{
+ sal_Int16 nRet = 0;
+ try {
+ nRet = xIES->compareIndexEntry( rTxt1, rTxtReading1, rLocale1,
+ rTxt2, rTxtReading2, rLocale2 );
+ }
+ catch ( UNO_NMSPC::Exception&
+#if OSL_DEBUG_LEVEL > 1
+ e
+#endif
+ )
+ {
+#if OSL_DEBUG_LEVEL > 1
+ ByteString aMsg( "compareIndexEntry: Exception caught\n" );
+ aMsg += ByteString( String( e.Message ), RTL_TEXTENCODING_UTF8 );
+ DBG_ERRORFILE( aMsg.GetBuffer() );
+#endif
+ }
+ return nRet;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/tox/txmsrt.cxx b/sw/source/core/tox/txmsrt.cxx
new file mode 100644
index 000000000000..ee3d247db41f
--- /dev/null
+++ b/sw/source/core/tox/txmsrt.cxx
@@ -0,0 +1,883 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+#include <tools/resid.hxx>
+#include <unotools/charclass.hxx>
+#include <com/sun/star/i18n/CollatorOptions.hpp>
+#include <editeng/unolingu.hxx>
+#include <txtfld.hxx>
+#include <doc.hxx>
+#include <docary.hxx>
+#include <cntfrm.hxx>
+#include <node.hxx>
+#include <frmatr.hxx>
+#include <pam.hxx>
+#include <txttxmrk.hxx>
+#include <frmfmt.hxx>
+#include <fmtfld.hxx>
+#include <txmsrt.hxx>
+#include <ndtxt.hxx>
+#include <txtatr.hxx>
+#include <swtable.hxx>
+#include <expfld.hxx>
+#include <authfld.hxx>
+#include <toxwrap.hxx>
+
+#include <comcore.hrc>
+#include <numrule.hxx>
+
+extern sal_Bool IsFrameBehind( const SwTxtNode& rMyNd, xub_StrLen nMySttPos,
+ const SwTxtNode& rBehindNd, xub_StrLen nSttPos );
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::uno;
+using ::rtl::OUString;
+/*--------------------------------------------------------------------
+ Beschreibung: Strings initialisieren
+ --------------------------------------------------------------------*/
+
+sal_uInt16 SwTOXSortTabBase::nOpt = 0;
+
+SV_IMPL_VARARR( SwTOXSources, SwTOXSource )
+
+
+SwTOXInternational::SwTOXInternational( LanguageType nLang, sal_uInt16 nOpt,
+ const String& rSortAlgorithm ) :
+ eLang( nLang ),
+ sSortAlgorithm(rSortAlgorithm),
+ nOptions( nOpt )
+{
+ Init();
+}
+
+SwTOXInternational::SwTOXInternational( const SwTOXInternational& rIntl ) :
+ eLang( rIntl.eLang ),
+ sSortAlgorithm(rIntl.sSortAlgorithm),
+ nOptions( rIntl.nOptions )
+{
+ Init();
+}
+
+void SwTOXInternational::Init()
+{
+ pIndexWrapper = new IndexEntrySupplierWrapper();
+
+ const lang::Locale aLcl( SvxCreateLocale( eLang ) );
+ pIndexWrapper->SetLocale( aLcl );
+
+ if(!sSortAlgorithm.Len())
+ {
+ Sequence < OUString > aSeq( pIndexWrapper->GetAlgorithmList( aLcl ));
+ if(aSeq.getLength())
+ sSortAlgorithm = aSeq.getConstArray()[0];
+ }
+
+ if ( nOptions & nsSwTOIOptions::TOI_CASE_SENSITIVE )
+ pIndexWrapper->LoadAlgorithm( aLcl, sSortAlgorithm, 0 );
+ else
+ pIndexWrapper->LoadAlgorithm( aLcl, sSortAlgorithm, SW_COLLATOR_IGNORES );
+
+ pCharClass = new CharClass( aLcl );
+
+}
+
+SwTOXInternational::~SwTOXInternational()
+{
+ delete pCharClass;
+ delete pIndexWrapper;
+}
+
+String SwTOXInternational::ToUpper( const String& rStr, xub_StrLen nPos ) const
+{
+ return pCharClass->toUpper( rStr, nPos, 1 );
+}
+inline sal_Bool SwTOXInternational::IsNumeric( const String& rStr ) const
+{
+ return pCharClass->isNumeric( rStr );
+}
+
+sal_Int32 SwTOXInternational::Compare( const String& rTxt1, const String& rTxtReading1,
+ const lang::Locale& rLocale1,
+ const String& rTxt2, const String& rTxtReading2,
+ const lang::Locale& rLocale2 ) const
+{
+ return pIndexWrapper->CompareIndexEntry( rTxt1, rTxtReading1, rLocale1,
+ rTxt2, rTxtReading2, rLocale2 );
+}
+
+String SwTOXInternational::GetIndexKey( const String& rTxt, const String& rTxtReading,
+ const lang::Locale& rLocale ) const
+{
+ return pIndexWrapper->GetIndexKey( rTxt, rTxtReading, rLocale );
+}
+
+String SwTOXInternational::GetFollowingText( sal_Bool bMorePages ) const
+{
+ return pIndexWrapper->GetFollowingText( bMorePages );
+}
+
+/*--------------------------------------------------------------------
+ Beschreibung: SortierElement fuer Verzeichniseintraege
+ --------------------------------------------------------------------*/
+
+
+SwTOXSortTabBase::SwTOXSortTabBase( TOXSortType nTyp, const SwCntntNode* pNd,
+ const SwTxtTOXMark* pMark,
+ const SwTOXInternational* pInter,
+ const lang::Locale* pLocale )
+ : pTOXNd( 0 ), pTxtMark( pMark ), pTOXIntl( pInter ),
+ nPos( 0 ), nCntPos( 0 ), nType( static_cast<sal_uInt16>(nTyp) ), bValidTxt( sal_False )
+{
+ if ( pLocale )
+ aLocale = *pLocale;
+
+ if( pNd )
+ {
+ xub_StrLen n = 0;
+ if( pTxtMark )
+ n = *pTxtMark->GetStart();
+ SwTOXSource aTmp( pNd, n,
+ pTxtMark ? pTxtMark->GetTOXMark().IsMainEntry() : sal_False );
+ aTOXSources.Insert( aTmp, aTOXSources.Count() );
+
+ nPos = pNd->GetIndex();
+
+ switch( nTyp )
+ {
+ case TOX_SORT_CONTENT:
+ case TOX_SORT_PARA:
+ case TOX_SORT_TABLE:
+ // falls sie in Sonderbereichen stehen, sollte man die
+ // Position im Body besorgen
+ if( nPos < pNd->GetNodes().GetEndOfExtras().GetIndex() )
+ {
+ // dann die "Anker" (Body) Position holen.
+ Point aPt;
+ const SwCntntFrm* pFrm = pNd->getLayoutFrm( pNd->GetDoc()->GetCurrentLayout(), &aPt, 0, sal_False );
+ if( pFrm )
+ {
+ SwPosition aPos( *pNd );
+ const SwDoc& rDoc = *pNd->GetDoc();
+#if OSL_DEBUG_LEVEL > 1
+ OSL_ENSURE( GetBodyTxtNode( rDoc, aPos, *pFrm ),
+ "wo steht der Absatz" );
+#else
+ GetBodyTxtNode( rDoc, aPos, *pFrm );
+#endif
+ nPos = aPos.nNode.GetIndex();
+ nCntPos = aPos.nContent.GetIndex();
+ }
+ }
+ else
+ nCntPos = n;
+ break;
+ default: break;
+ }
+ }
+}
+
+
+String SwTOXSortTabBase::GetURL() const
+{
+ return aEmptyStr;
+}
+
+void SwTOXSortTabBase::FillText( SwTxtNode& rNd, const SwIndex& rInsPos,
+ sal_uInt16 ) const
+{
+ String sMyTxt;
+ String sMyTxtReading;
+
+ GetTxt( sMyTxt, sMyTxtReading );
+
+ rNd.InsertText( sMyTxt, rInsPos );
+}
+
+sal_Bool SwTOXSortTabBase::operator==( const SwTOXSortTabBase& rCmp )
+{
+ sal_Bool bRet = nPos == rCmp.nPos && nCntPos == rCmp.nCntPos &&
+ (!aTOXSources[0].pNd || !rCmp.aTOXSources[0].pNd ||
+ aTOXSources[0].pNd == rCmp.aTOXSources[0].pNd );
+
+ if( TOX_SORT_CONTENT == nType )
+ {
+ bRet = bRet && pTxtMark && rCmp.pTxtMark &&
+ *pTxtMark->GetStart() == *rCmp.pTxtMark->GetStart();
+
+ if( bRet )
+ {
+ // beide Pointer vorhanden -> vergleiche Text
+ // beide Pointer nicht vorhanden -> vergleiche AlternativText
+ const xub_StrLen *pEnd = pTxtMark->GetEnd(),
+ *pEndCmp = rCmp.pTxtMark->GetEnd();
+
+ String sMyTxt;
+ String sMyTxtReading;
+ GetTxt( sMyTxt, sMyTxtReading );
+
+ String sOtherTxt;
+ String sOtherTxtReading;
+ rCmp.GetTxt( sOtherTxt, sOtherTxtReading );
+
+ bRet = ( ( pEnd && pEndCmp ) || ( !pEnd && !pEndCmp ) ) &&
+ pTOXIntl->IsEqual( sMyTxt, sMyTxtReading, GetLocale(),
+ sOtherTxt, sOtherTxtReading, rCmp.GetLocale() );
+ }
+ }
+ return bRet;
+}
+
+sal_Bool SwTOXSortTabBase::operator<( const SwTOXSortTabBase& rCmp )
+{
+ if( nPos < rCmp.nPos )
+ return sal_True;
+
+ if( nPos == rCmp.nPos )
+ {
+ if( nCntPos < rCmp.nCntPos )
+ return sal_True;
+
+ if( nCntPos == rCmp.nCntPos )
+ {
+ const SwNode* pFirst = aTOXSources[0].pNd;
+ const SwNode* pNext = rCmp.aTOXSources[0].pNd;
+
+ if( pFirst && pFirst == pNext )
+ {
+ if( TOX_SORT_CONTENT == nType && pTxtMark && rCmp.pTxtMark )
+ {
+ if( *pTxtMark->GetStart() < *rCmp.pTxtMark->GetStart() )
+ return sal_True;
+
+ if( *pTxtMark->GetStart() == *rCmp.pTxtMark->GetStart() )
+ {
+ const xub_StrLen *pEnd = pTxtMark->GetEnd(),
+ *pEndCmp = rCmp.pTxtMark->GetEnd();
+
+ String sMyTxt;
+ String sMyTxtReading;
+ GetTxt( sMyTxt, sMyTxtReading );
+
+ String sOtherTxt;
+ String sOtherTxtReading;
+ rCmp.GetTxt( sOtherTxt, sOtherTxtReading );
+
+ // beide Pointer vorhanden -> vergleiche Text
+ // beide Pointer nicht vorhanden -> vergleiche AlternativText
+ if( ( pEnd && pEndCmp ) || ( !pEnd && !pEndCmp ) )
+ pTOXIntl->IsEqual( sMyTxt, sMyTxtReading, GetLocale(),
+ sOtherTxt, sOtherTxtReading, rCmp.GetLocale() );
+
+ if( pEnd && !pEndCmp )
+ return sal_True;
+ }
+ }
+ }
+ else if( pFirst && pFirst->IsTxtNode() &&
+ pNext && pNext->IsTxtNode() )
+ return ::IsFrameBehind( *(SwTxtNode*)pNext, nCntPos,
+ *(SwTxtNode*)pFirst, nCntPos );
+ }
+ }
+ return sal_False;
+}
+
+/*--------------------------------------------------------------------
+ Beschreibung: sortierter Stichworteintrag
+ --------------------------------------------------------------------*/
+
+
+SwTOXIndex::SwTOXIndex( const SwTxtNode& rNd,
+ const SwTxtTOXMark* pMark, sal_uInt16 nOptions,
+ sal_uInt8 nKyLevel,
+ const SwTOXInternational& rIntl,
+ const lang::Locale& rLocale )
+ : SwTOXSortTabBase( TOX_SORT_INDEX, &rNd, pMark, &rIntl, &rLocale ),
+ nKeyLevel(nKyLevel)
+{
+ nPos = rNd.GetIndex();
+ nOpt = nOptions;
+}
+
+//
+// Stichworte vergleichen. Bezieht sich nur auf den Text
+//
+
+
+sal_Bool SwTOXIndex::operator==( const SwTOXSortTabBase& rCmpBase )
+{
+ SwTOXIndex& rCmp = (SwTOXIndex&)rCmpBase;
+
+ // In Abhaengigkeit von den Optionen Grosskleinschreibung beachten
+ if(GetLevel() != rCmp.GetLevel() || nKeyLevel != rCmp.nKeyLevel)
+ return sal_False;
+
+ OSL_ENSURE(pTxtMark, "pTxtMark == 0, Kein Stichwort");
+
+ String sMyTxt;
+ String sMyTxtReading;
+ GetTxt( sMyTxt, sMyTxtReading );
+
+ String sOtherTxt;
+ String sOtherTxtReading;
+ rCmp.GetTxt( sOtherTxt, sOtherTxtReading );
+
+ sal_Bool bRet = pTOXIntl->IsEqual( sMyTxt, sMyTxtReading, GetLocale(),
+ sOtherTxt, sOtherTxtReading, rCmp.GetLocale() );
+
+ // Wenn nicht zusammengefasst wird muss die Pos aus gewertet werden
+ if(bRet && !(GetOptions() & nsSwTOIOptions::TOI_SAME_ENTRY))
+ bRet = nPos == rCmp.nPos;
+
+ return bRet;
+}
+
+//
+// kleiner haengt nur vom Text ab
+
+sal_Bool SwTOXIndex::operator<( const SwTOXSortTabBase& rCmpBase )
+{
+ SwTOXIndex& rCmp = (SwTOXIndex&)rCmpBase;
+
+ OSL_ENSURE(pTxtMark, "pTxtMark == 0, Kein Stichwort");
+
+ String sMyTxt;
+ String sMyTxtReading;
+ GetTxt( sMyTxt, sMyTxtReading );
+
+ String sOtherTxt;
+ String sOtherTxtReading;
+ rCmp.GetTxt( sOtherTxt, sOtherTxtReading );
+
+ sal_Bool bRet = GetLevel() == rCmp.GetLevel() &&
+ pTOXIntl->IsLess( sMyTxt, sMyTxtReading, GetLocale(),
+ sOtherTxt, sOtherTxtReading, rCmp.GetLocale() );
+
+ // Wenn nicht zusammengefasst wird muss die Pos aus gewertet werden
+ if( !bRet && !(GetOptions() & nsSwTOIOptions::TOI_SAME_ENTRY) )
+ {
+ bRet = pTOXIntl->IsEqual( sMyTxt, sMyTxtReading, GetLocale(),
+ sOtherTxt, sOtherTxtReading, rCmp.GetLocale() ) &&
+ nPos < rCmp.nPos;
+ }
+
+ return bRet;
+}
+
+//
+// Das Stichwort selbst
+
+void SwTOXIndex::GetText_Impl( String& rTxt, String& rTxtReading ) const
+{
+ OSL_ENSURE(pTxtMark, "pTxtMark == 0, Kein Stichwort");
+ const SwTOXMark& rTOXMark = pTxtMark->GetTOXMark();
+ switch(nKeyLevel)
+ {
+ case FORM_PRIMARY_KEY :
+ {
+ rTxt = rTOXMark.GetPrimaryKey();
+ rTxtReading = rTOXMark.GetPrimaryKeyReading();
+ }
+ break;
+ case FORM_SECONDARY_KEY :
+ {
+ rTxt = rTOXMark.GetSecondaryKey();
+ rTxtReading = rTOXMark.GetSecondaryKeyReading();
+ }
+ break;
+ case FORM_ENTRY :
+ {
+ rTxt = rTOXMark.GetText();
+ rTxtReading = rTOXMark.GetTextReading();
+ }
+ break;
+ }
+ // if TOI_INITIAL_CAPS is set, first character is to be capitalized
+ if( nsSwTOIOptions::TOI_INITIAL_CAPS & nOpt && pTOXIntl )
+ {
+ String sUpper( pTOXIntl->ToUpper( rTxt, 0 ));
+ rTxt.Erase( 0, 1 ).Insert( sUpper, 0 );
+ }
+}
+
+void SwTOXIndex::FillText( SwTxtNode& rNd, const SwIndex& rInsPos, sal_uInt16 ) const
+{
+ const xub_StrLen* pEnd = pTxtMark->GetEnd();
+ String sTmp;
+ String sTmpReading;
+ if( pEnd && !pTxtMark->GetTOXMark().IsAlternativeText() &&
+ 0 == (GetOptions() & nsSwTOIOptions::TOI_KEY_AS_ENTRY))
+ {
+ sTmp = ((SwTxtNode*)aTOXSources[0].pNd)->GetExpandTxt(
+ *pTxtMark->GetStart(),
+ *pEnd - *pTxtMark->GetStart());
+ if(nsSwTOIOptions::TOI_INITIAL_CAPS&nOpt && pTOXIntl)
+ {
+ String sUpper( pTOXIntl->ToUpper( sTmp, 0 ));
+ sTmp.Erase( 0, 1 ).Insert( sUpper, 0 );
+ }
+ }
+ else
+ GetTxt( sTmp, sTmpReading );
+
+ rNd.InsertText( sTmp, rInsPos );
+}
+
+
+
+sal_uInt16 SwTOXIndex::GetLevel() const
+{
+ OSL_ENSURE(pTxtMark, "pTxtMark == 0, Kein Stichwort");
+
+ sal_uInt16 nForm = FORM_PRIMARY_KEY;
+
+ if( 0 == (GetOptions() & nsSwTOIOptions::TOI_KEY_AS_ENTRY)&&
+ pTxtMark->GetTOXMark().GetPrimaryKey().Len() )
+ {
+ nForm = FORM_SECONDARY_KEY;
+ if( pTxtMark->GetTOXMark().GetSecondaryKey().Len() )
+ nForm = FORM_ENTRY;
+ }
+ return nForm;
+}
+
+/*--------------------------------------------------------------------
+ Beschreibung: Schluessel und Trennzeichen
+ --------------------------------------------------------------------*/
+
+
+SwTOXCustom::SwTOXCustom(const String& rStr, const String& rReading,
+ sal_uInt16 nLevel,
+ const SwTOXInternational& rIntl,
+ const lang::Locale& rLocale )
+ : SwTOXSortTabBase( TOX_SORT_CUSTOM, 0, 0, &rIntl, &rLocale ),
+ aKey(rStr), sReading(rReading), nLev(nLevel)
+{
+}
+
+
+sal_Bool SwTOXCustom::operator==(const SwTOXSortTabBase& rCmpBase)
+{
+ String sMyTxt;
+ String sMyTxtReading;
+ GetTxt( sMyTxt, sMyTxtReading );
+
+ String sOtherTxt;
+ String sOtherTxtReading;
+ rCmpBase.GetTxt( sOtherTxt, sOtherTxtReading );
+
+ return GetLevel() == rCmpBase.GetLevel() &&
+ pTOXIntl->IsEqual( sMyTxt, sMyTxtReading, GetLocale(),
+ sOtherTxt, sOtherTxtReading, rCmpBase.GetLocale() );
+}
+
+
+sal_Bool SwTOXCustom::operator < (const SwTOXSortTabBase& rCmpBase)
+{
+ String sMyTxt;
+ String sMyTxtReading;
+ GetTxt( sMyTxt, sMyTxtReading );
+
+ String sOtherTxt;
+ String sOtherTxtReading;
+ rCmpBase.GetTxt( sOtherTxt, sOtherTxtReading );
+
+ return GetLevel() <= rCmpBase.GetLevel() &&
+ pTOXIntl->IsLess( sMyTxt, sMyTxtReading, GetLocale(),
+ sOtherTxt, sOtherTxtReading, rCmpBase.GetLocale() );
+}
+
+
+sal_uInt16 SwTOXCustom::GetLevel() const
+{
+ return nLev;
+}
+
+
+void SwTOXCustom::GetText_Impl( String& rTxt, String &rTxtReading ) const
+{
+ rTxt = aKey;
+ rTxtReading = sReading;
+}
+
+
+/*--------------------------------------------------------------------
+ Beschreibung: sortierter Inhaltsverz. Eintrag
+ --------------------------------------------------------------------*/
+
+
+SwTOXContent::SwTOXContent( const SwTxtNode& rNd, const SwTxtTOXMark* pMark,
+ const SwTOXInternational& rIntl)
+ : SwTOXSortTabBase( TOX_SORT_CONTENT, &rNd, pMark, &rIntl )
+{
+}
+
+
+// Der Text des Inhalts
+//
+
+void SwTOXContent::GetText_Impl( String& rTxt, String& rTxtReading ) const
+{
+ const xub_StrLen* pEnd = pTxtMark->GetEnd();
+ if( pEnd && !pTxtMark->GetTOXMark().IsAlternativeText() )
+ {
+ rTxt = ((SwTxtNode*)aTOXSources[0].pNd)->GetExpandTxt(
+ *pTxtMark->GetStart(),
+ *pEnd - *pTxtMark->GetStart() );
+
+ rTxtReading = pTxtMark->GetTOXMark().GetTextReading();
+ }
+ else
+ rTxt = pTxtMark->GetTOXMark().GetAlternativeText();
+}
+
+void SwTOXContent::FillText( SwTxtNode& rNd, const SwIndex& rInsPos, sal_uInt16 ) const
+{
+ const xub_StrLen* pEnd = pTxtMark->GetEnd();
+ if( pEnd && !pTxtMark->GetTOXMark().IsAlternativeText() )
+ ((SwTxtNode*)aTOXSources[0].pNd)->GetExpandTxt( rNd, &rInsPos,
+ *pTxtMark->GetStart(),
+ *pEnd - *pTxtMark->GetStart() );
+ else
+ {
+ String sTmp, sTmpReading;
+ GetTxt( sTmp, sTmpReading );
+ rNd.InsertText( sTmp, rInsPos );
+ }
+}
+
+//
+// Die Ebene fuer Anzeige
+//
+
+
+sal_uInt16 SwTOXContent::GetLevel() const
+{
+ return pTxtMark->GetTOXMark().GetLevel();
+}
+
+/*--------------------------------------------------------------------
+ Beschreibung: Verzeichnis aus Absaetzen zusammengesammelt
+ --------------------------------------------------------------------*/
+
+// bei Sortierung von OLE/Grafiken aufpassen !!!
+// Die Position darf nicht die im Dokument,
+// sondern muss die vom "Henkel" sein !!
+
+
+SwTOXPara::SwTOXPara( const SwCntntNode& rNd, SwTOXElement eT, sal_uInt16 nLevel )
+ : SwTOXSortTabBase( TOX_SORT_PARA, &rNd, 0, 0 ),
+ eType( eT ),
+ m_nLevel(nLevel),
+ nStartIndex(0),
+ nEndIndex(STRING_LEN)
+{
+}
+
+
+void SwTOXPara::GetText_Impl( String& rTxt, String& ) const
+{
+ const SwCntntNode* pNd = aTOXSources[0].pNd;
+ switch( eType )
+ {
+ case nsSwTOXElement::TOX_SEQUENCE:
+ case nsSwTOXElement::TOX_TEMPLATE:
+ case nsSwTOXElement::TOX_OUTLINELEVEL:
+ {
+ xub_StrLen nStt = nStartIndex;
+ rTxt = ((SwTxtNode*)pNd)->GetExpandTxt(
+ nStt,
+ STRING_NOTFOUND == nEndIndex ? STRING_LEN : nEndIndex - nStt);
+ }
+ break;
+
+ case nsSwTOXElement::TOX_OLE:
+ case nsSwTOXElement::TOX_GRAPHIC:
+ case nsSwTOXElement::TOX_FRAME:
+ {
+ // suche das FlyFormat, dort steht der Object/Grafik-Name
+ SwFrmFmt* pFly = pNd->GetFlyFmt();
+ if( pFly )
+ rTxt = pFly->GetName();
+ else
+ {
+ OSL_ENSURE( !this, "Grafik/Object ohne Namen" );
+ sal_uInt16 nId = nsSwTOXElement::TOX_OLE == eType
+ ? STR_OBJECT_DEFNAME
+ : nsSwTOXElement::TOX_GRAPHIC == eType
+ ? STR_GRAPHIC_DEFNAME
+ : STR_FRAME_DEFNAME;
+ rTxt = SW_RESSTR( nId );
+ }
+ }
+ break;
+ default: break;
+ }
+}
+
+void SwTOXPara::FillText( SwTxtNode& rNd, const SwIndex& rInsPos, sal_uInt16 ) const
+{
+ if( nsSwTOXElement::TOX_TEMPLATE == eType || nsSwTOXElement::TOX_SEQUENCE == eType || nsSwTOXElement::TOX_OUTLINELEVEL == eType)
+ {
+ SwTxtNode* pSrc = (SwTxtNode*)aTOXSources[0].pNd;
+ xub_StrLen nStt = nStartIndex;
+ pSrc->GetExpandTxt( rNd, &rInsPos, nStt,
+ nEndIndex == STRING_LEN ? STRING_LEN : nEndIndex - nStt,
+ sal_False, sal_False, sal_True );
+ }
+ else
+ {
+ String sTmp, sTmpReading;
+ GetTxt( sTmp, sTmpReading );
+ sTmp.SearchAndReplaceAll('\t', ' ');
+ rNd.InsertText( sTmp, rInsPos );
+ }
+}
+
+
+sal_uInt16 SwTOXPara::GetLevel() const
+{
+ sal_uInt16 nRet = m_nLevel;
+ const SwCntntNode* pNd = aTOXSources[0].pNd;
+
+ if( nsSwTOXElement::TOX_OUTLINELEVEL == eType && pNd->GetTxtNode() )
+ {
+ const int nTmp = ((SwTxtNode*)pNd)->GetAttrOutlineLevel();//#outline level,zhaojianwei????
+ if(nTmp != 0 )
+ nRet = static_cast<sal_uInt16>(nTmp);
+ }
+ return nRet;
+}
+
+
+String SwTOXPara::GetURL() const
+{
+ String aTxt;
+ const SwCntntNode* pNd = aTOXSources[0].pNd;
+ switch( eType )
+ {
+ case nsSwTOXElement::TOX_TEMPLATE:
+ case nsSwTOXElement::TOX_OUTLINELEVEL:
+ {
+ const SwTxtNode * pTxtNd = static_cast<const SwTxtNode *>(pNd);
+
+ SwDoc* pDoc = const_cast<SwDoc*>( pTxtNd->GetDoc() );
+ ::sw::mark::IMark const * const pMark = pDoc->getIDocumentMarkAccess()->getMarkForTxtNode(
+ *(pTxtNd),
+ IDocumentMarkAccess::CROSSREF_HEADING_BOOKMARK);
+ aTxt = '#';
+ const String aMarkName( pMark->GetName() );
+ aTxt += aMarkName;
+ }
+ break;
+
+ case nsSwTOXElement::TOX_OLE:
+ case nsSwTOXElement::TOX_GRAPHIC:
+ case nsSwTOXElement::TOX_FRAME:
+ {
+ // suche das FlyFormat, dort steht der Object/Grafik-Name
+ SwFrmFmt* pFly = pNd->GetFlyFmt();
+ if( pFly )
+ {
+ (( aTxt = '#' ) += pFly->GetName() ) += cMarkSeperator;
+ const sal_Char* pStr;
+ switch( eType )
+ {
+ case nsSwTOXElement::TOX_OLE: pStr = pMarkToOLE; break;
+ case nsSwTOXElement::TOX_GRAPHIC: pStr = pMarkToGraphic; break;
+ case nsSwTOXElement::TOX_FRAME: pStr = pMarkToFrame; break;
+ default: pStr = 0;
+ }
+ if( pStr )
+ aTxt.AppendAscii( pStr );
+ }
+ }
+ break;
+ default: break;
+ }
+ return aTxt;
+}
+
+
+/*--------------------------------------------------------------------
+ Beschreibung: Tabelle
+ --------------------------------------------------------------------*/
+
+
+SwTOXTable::SwTOXTable( const SwCntntNode& rNd )
+ : SwTOXSortTabBase( TOX_SORT_TABLE, &rNd, 0, 0 ),
+ nLevel(FORM_ALPHA_DELIMITTER)
+{
+}
+
+
+void SwTOXTable::GetText_Impl( String& rTxt, String& ) const
+{
+ const SwNode* pNd = aTOXSources[0].pNd;
+ if( pNd && 0 != ( pNd = pNd->FindTableNode() ) )
+ {
+ rTxt = ((SwTableNode*)pNd)->GetTable().GetFrmFmt()->GetName();
+ }
+ else
+ {
+ OSL_ENSURE( !this, "Wo ist meine Tabelle geblieben?" );
+ rTxt = SW_RESSTR( STR_TABLE_DEFNAME );
+ }
+}
+
+sal_uInt16 SwTOXTable::GetLevel() const
+{
+ return nLevel;
+}
+
+
+String SwTOXTable::GetURL() const
+{
+ String aTxt;
+ const SwNode* pNd = aTOXSources[0].pNd;
+ if( pNd && 0 != ( pNd = pNd->FindTableNode() ) )
+ {
+ aTxt = ((SwTableNode*)pNd)->GetTable().GetFrmFmt()->GetName();
+ if( aTxt.Len() )
+ {
+ ( aTxt.Insert( '#', 0 ) += cMarkSeperator ).
+ AppendAscii( pMarkToTable );
+ }
+ }
+ return aTxt;
+}
+
+SwTOXAuthority::SwTOXAuthority( const SwCntntNode& rNd,
+ SwFmtFld& rField, const SwTOXInternational& rIntl ) :
+ SwTOXSortTabBase( TOX_SORT_AUTHORITY, &rNd, 0, &rIntl ),
+ m_rField(rField)
+{
+ if(rField.GetTxtFld())
+ nCntPos = *rField.GetTxtFld()->GetStart();
+}
+
+sal_uInt16 SwTOXAuthority::GetLevel() const
+{
+ String sText(((SwAuthorityField*)m_rField.GetFld())->
+ GetFieldText(AUTH_FIELD_AUTHORITY_TYPE));
+ //#i18655# the level '0' is the heading level therefor the values are incremented here
+ sal_uInt16 nRet = 1;
+ if( pTOXIntl->IsNumeric( sText ) )
+ {
+ nRet = (sal_uInt16)sText.ToInt32();
+ nRet++;
+ }
+ //illegal values are also set to 'ARTICLE' as non-numeric values are
+ if(nRet > AUTH_TYPE_END)
+ nRet = 1;
+ return nRet;
+}
+
+static String lcl_GetText(SwFmtFld const& rField)
+{
+ return rField.GetFld()->ExpandField(true);
+}
+
+void SwTOXAuthority::GetText_Impl( String& rTxt, String& ) const
+{
+ rTxt = lcl_GetText(m_rField);
+}
+
+void SwTOXAuthority::FillText( SwTxtNode& rNd,
+ const SwIndex& rInsPos, sal_uInt16 nAuthField ) const
+{
+ SwAuthorityField* pField = (SwAuthorityField*)m_rField.GetFld();
+ String sText;
+ if(AUTH_FIELD_IDENTIFIER == nAuthField)
+ {
+ sText = lcl_GetText(m_rField);
+ const SwAuthorityFieldType* pType = (const SwAuthorityFieldType*)pField->GetTyp();
+ sal_Unicode cChar = pType->GetPrefix();
+ if(cChar && cChar != ' ')
+ sText.Erase(0, 1);
+ cChar = pType->GetSuffix();
+ if(cChar && cChar != ' ')
+ sText.Erase(sText.Len() - 1, 1);
+ }
+ else if(AUTH_FIELD_AUTHORITY_TYPE == nAuthField)
+ {
+ sal_uInt16 nLevel = GetLevel();
+ if(nLevel)
+ sText = SwAuthorityFieldType::GetAuthTypeName((ToxAuthorityType) --nLevel);
+ }
+ else
+ sText = (pField->GetFieldText((ToxAuthorityField) nAuthField));
+ rNd.InsertText( sText, rInsPos );
+}
+
+sal_Bool SwTOXAuthority::operator==( const SwTOXSortTabBase& rCmp)
+{
+ return nType == rCmp.nType &&
+ ((SwAuthorityField*)m_rField.GetFld())->GetHandle() ==
+ ((SwAuthorityField*)((SwTOXAuthority&)rCmp).m_rField.GetFld())->GetHandle();
+}
+
+sal_Bool SwTOXAuthority::operator<( const SwTOXSortTabBase& rBase)
+{
+ sal_Bool bRet = sal_False;
+ SwAuthorityField* pField = (SwAuthorityField*)m_rField.GetFld();
+ SwAuthorityFieldType* pType = (SwAuthorityFieldType*)
+ pField->GetTyp();
+ if(pType->IsSortByDocument())
+ bRet = SwTOXSortTabBase::operator<(rBase);
+ else
+ {
+ SwAuthorityField* pCmpField = (SwAuthorityField*)
+ ((SwTOXAuthority&)rBase).m_rField.GetFld();
+
+
+ for(sal_uInt16 i = 0; i < pType->GetSortKeyCount(); i++)
+ {
+ const SwTOXSortKey* pKey = pType->GetSortKey(i);
+ String sMyTxt = pField->GetFieldText(pKey->eField);
+ String sMyTxtReading;
+ String sOtherTxt = pCmpField->GetFieldText(pKey->eField);
+ String sOtherTxtReading;
+
+ sal_Int32 nComp = pTOXIntl->Compare( sMyTxt, sMyTxtReading, GetLocale(),
+ sOtherTxt, sOtherTxtReading, rBase.GetLocale() );
+
+ if( nComp )
+ {
+ bRet = (-1 == nComp) == pKey->bSortAscending;
+ break;
+ }
+ }
+ }
+ return bRet;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/txtnode/SwGrammarContact.cxx b/sw/source/core/txtnode/SwGrammarContact.cxx
new file mode 100644
index 000000000000..14ff4233246f
--- /dev/null
+++ b/sw/source/core/txtnode/SwGrammarContact.cxx
@@ -0,0 +1,205 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+#include <vcl/timer.hxx>
+#include <hints.hxx>
+#include <IGrammarContact.hxx>
+#include <pam.hxx>
+#include <ndtxt.hxx>
+#include <SwGrammarMarkUp.hxx>
+#include <txtfrm.hxx>
+#include <rootfrm.hxx>
+#include <viewsh.hxx>
+
+/* SwGrammarContact
+ This class is responsible for the delayed display of grammar checks when a paragraph is edited
+ It's a client of the paragraph the cursor points to.
+ If the cursor position changes, updateCursorPosition has to be called
+ If the grammar checker wants to set a grammar marker at a paragraph, he has to request
+ the grammar list from this class. If the requested paragraph is not edited, it returns
+ the normal grammar list. But if the paragraph is the active one, a proxy list will be returned and
+ all changes are set in this proxy list. If the cursor leaves the paragraph the proxy list
+ will replace the old list. If the grammar checker has completed the paragraph ('setChecked')
+ then a timer is setup which replaces the old list as well.
+*/
+
+class SwGrammarContact : public IGrammarContact, public SwClient
+{
+ Timer aTimer;
+ SwGrammarMarkUp *mpProxyList;
+ bool mbFinished;
+ SwTxtNode* getMyTxtNode() { return (SwTxtNode*)GetRegisteredIn(); }
+ DECL_LINK( TimerRepaint, Timer * );
+
+public:
+ SwGrammarContact();
+ ~SwGrammarContact() { aTimer.Stop(); delete mpProxyList; }
+
+ // (pure) virtual functions of IGrammarContact
+ virtual void updateCursorPosition( const SwPosition& rNewPos );
+ virtual SwGrammarMarkUp* getGrammarCheck( SwTxtNode& rTxtNode, bool bCreate );
+ virtual void finishGrammarCheck( SwTxtNode& rTxtNode );
+protected:
+ // virtual function of SwClient
+ virtual void Modify( const SfxPoolItem* pOld, const SfxPoolItem *pNew);
+};
+
+SwGrammarContact::SwGrammarContact() : mpProxyList(0), mbFinished( false )
+{
+ aTimer.SetTimeout( 2000 ); // Repaint of grammar check after 'setChecked'
+ aTimer.SetTimeoutHdl( LINK(this, SwGrammarContact, TimerRepaint) );
+}
+
+IMPL_LINK( SwGrammarContact, TimerRepaint, Timer *, pTimer )
+{
+ if( pTimer )
+ {
+ pTimer->Stop();
+ if( GetRegisteredIn() )
+ { //Replace the old wrong list by the proxy list and repaint all frames
+ getMyTxtNode()->SetGrammarCheck( mpProxyList, true );
+ mpProxyList = 0;
+ SwTxtFrm::repaintTextFrames( *getMyTxtNode() );
+ }
+ }
+ return 0;
+}
+
+/* I'm always a client of the current paragraph */
+void SwGrammarContact::updateCursorPosition( const SwPosition& rNewPos )
+{
+ SwTxtNode* pTxtNode = rNewPos.nNode.GetNode().GetTxtNode();
+ if( pTxtNode != GetRegisteredIn() ) // paragraph has been changed
+ {
+ aTimer.Stop();
+ if( GetRegisteredIn() ) // My last paragraph has been left
+ {
+ if( mpProxyList )
+ { // replace old list by the proxy list and repaint
+ getMyTxtNode()->SetGrammarCheck( mpProxyList, true );
+ SwTxtFrm::repaintTextFrames( *getMyTxtNode() );
+ }
+ GetRegisteredInNonConst()->Remove( this ); // good bye old paragraph
+ mpProxyList = 0;
+ }
+ if( pTxtNode )
+ pTxtNode->Add( this ); // welcome new paragraph
+ }
+}
+
+/* deliver a grammar check list for the given text node */
+SwGrammarMarkUp* SwGrammarContact::getGrammarCheck( SwTxtNode& rTxtNode, bool bCreate )
+{
+ SwGrammarMarkUp *pRet = 0;
+ if( GetRegisteredIn() == &rTxtNode ) // hey, that's my current paragraph!
+ { // so you will get a proxy list...
+ if( bCreate )
+ {
+ if( mbFinished )
+ {
+ delete mpProxyList;
+ mpProxyList = 0;
+ }
+ if( !mpProxyList )
+ {
+ if( rTxtNode.GetGrammarCheck() )
+ mpProxyList = (SwGrammarMarkUp*)rTxtNode.GetGrammarCheck()->Clone();
+ else
+ {
+ mpProxyList = new SwGrammarMarkUp();
+ mpProxyList->SetInvalid( 0, STRING_LEN );
+ }
+ }
+ mbFinished = false;
+ }
+ pRet = mpProxyList;
+ }
+ else
+ {
+ pRet = rTxtNode.GetGrammarCheck(); // do you have already a list?
+ if( bCreate && !pRet ) // do you want to create a list?
+ {
+ pRet = new SwGrammarMarkUp();
+ pRet->SetInvalid( 0, STRING_LEN );
+ rTxtNode.SetGrammarCheck( pRet );
+ rTxtNode.SetGrammarCheckDirty( true );
+ }
+ }
+ return pRet;
+}
+
+void SwGrammarContact::Modify( const SfxPoolItem* pOld, const SfxPoolItem * )
+{
+ if( !pOld || pOld->Which() != RES_OBJECTDYING )
+ return;
+
+ SwPtrMsgPoolItem *pDead = (SwPtrMsgPoolItem *)pOld;
+ if( pDead->pObject == GetRegisteredIn() )
+ { // if my current paragraph dies, I throw the proxy list away
+ aTimer.Stop();
+ GetRegisteredInNonConst()->Remove( this );
+ delete mpProxyList;
+ mpProxyList = 0;
+ }
+}
+
+void SwGrammarContact::finishGrammarCheck( SwTxtNode& rTxtNode )
+{
+ if( &rTxtNode != GetRegisteredIn() ) // not my paragraph
+ SwTxtFrm::repaintTextFrames( rTxtNode ); // can be repainted directly
+ else
+ {
+ if( mpProxyList )
+ {
+ mbFinished = true;
+ aTimer.Start(); // will replace old list and repaint with delay
+ }
+ else if( getMyTxtNode()->GetGrammarCheck() )
+ { // all grammar problems seems to be gone, no delay needed
+ getMyTxtNode()->SetGrammarCheck( 0, true );
+ SwTxtFrm::repaintTextFrames( *getMyTxtNode() );
+ }
+ }
+}
+
+IGrammarContact* createGrammarContact()
+{
+ return new SwGrammarContact();
+}
+
+void finishGrammarCheck( SwTxtNode& rTxtNode )
+{
+ IGrammarContact* pGrammarContact = getGrammarContact( rTxtNode );
+ if( pGrammarContact )
+ pGrammarContact->finishGrammarCheck( rTxtNode );
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/txtnode/atrfld.cxx b/sw/source/core/txtnode/atrfld.cxx
new file mode 100644
index 000000000000..4f6488e570ea
--- /dev/null
+++ b/sw/source/core/txtnode/atrfld.cxx
@@ -0,0 +1,424 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+#include "fldbas.hxx" // fuer FieldType
+#include <fmtfld.hxx>
+#include <txtfld.hxx>
+#include <docufld.hxx>
+#include <doc.hxx>
+
+#include "reffld.hxx"
+#include "ddefld.hxx"
+#include "usrfld.hxx"
+#include "expfld.hxx"
+#include "swfont.hxx" // fuer GetFldsColor
+#include "ndtxt.hxx" // SwTxtNode
+#include "calc.hxx" // Update fuer UserFields
+#include "hints.hxx"
+#include <IDocumentFieldsAccess.hxx>
+#include <fieldhint.hxx>
+#include <svl/smplhint.hxx>
+
+TYPEINIT3( SwFmtFld, SfxPoolItem, SwClient,SfxBroadcaster)
+TYPEINIT1(SwFmtFldHint, SfxHint);
+
+/****************************************************************************
+ *
+ * class SwFmtFld
+ *
+ ****************************************************************************/
+
+ // Konstruktor fuers Default vom Attribut-Pool
+SwFmtFld::SwFmtFld()
+ : SfxPoolItem( RES_TXTATR_FIELD ),
+ SwClient( 0 ),
+ pField( 0 ),
+ pTxtAttr( 0 )
+{
+}
+
+SwFmtFld::SwFmtFld( const SwField &rFld )
+ : SfxPoolItem( RES_TXTATR_FIELD ),
+ SwClient( rFld.GetTyp() ),
+ pTxtAttr( 0 )
+{
+ pField = rFld.CopyField();
+}
+
+// #i24434#
+// Since Items are used in ItemPool and in default constructed ItemSets with
+// full pool range, all items need to be clonable. Thus, this one needed to be
+// corrected
+SwFmtFld::SwFmtFld( const SwFmtFld& rAttr )
+ : SfxPoolItem( RES_TXTATR_FIELD ), SwClient(), SfxBroadcaster(),
+ pField( 0 ),
+ pTxtAttr( 0 )
+{
+ if(rAttr.GetFld())
+ {
+ rAttr.GetFld()->GetTyp()->Add(this);
+ pField = rAttr.GetFld()->CopyField();
+ }
+}
+
+SwFmtFld::~SwFmtFld()
+{
+ SwFieldType* pType = pField ? pField->GetTyp() : 0;
+
+ if (pType && pType->Which() == RES_DBFLD)
+ pType = 0; // DB-Feldtypen zerstoeren sich selbst
+
+ Broadcast( SwFmtFldHint( this, SWFMTFLD_REMOVED ) );
+ delete pField;
+
+ // bei einige FeldTypen muessen wir den FeldTypen noch loeschen
+ if( pType && pType->IsLastDepend() )
+ {
+ sal_Bool bDel = sal_False;
+ switch( pType->Which() )
+ {
+ case RES_USERFLD:
+ bDel = ((SwUserFieldType*)pType)->IsDeleted();
+ break;
+
+ case RES_SETEXPFLD:
+ bDel = ((SwSetExpFieldType*)pType)->IsDeleted();
+ break;
+
+ case RES_DDEFLD:
+ bDel = ((SwDDEFieldType*)pType)->IsDeleted();
+ break;
+ }
+
+ if( bDel )
+ {
+ // vorm loeschen erstmal austragen
+ pType->Remove( this );
+ delete pType;
+ }
+ }
+}
+
+void SwFmtFld::RegisterToFieldType( SwFieldType& rType )
+{
+ rType.Add(this);
+}
+
+
+// #111840#
+void SwFmtFld::SetFld(SwField * _pField)
+{
+ if (NULL != pField)
+ delete pField;
+
+ pField = _pField;
+ Broadcast( SwFmtFldHint( this, SWFMTFLD_CHANGED ) );
+}
+
+int SwFmtFld::operator==( const SfxPoolItem& rAttr ) const
+{
+ OSL_ENSURE( SfxPoolItem::operator==( rAttr ), "keine gleichen Attribute" );
+ // OD 2004-05-14 #i29146# - correction: check, if <pField> and
+ // <((SwFmtFld&)rAttr).GetFld()> are set.
+ // OD 2004-05-14 #i29146# - items are equal, if both fields aren't set.
+ return ( pField && ((SwFmtFld&)rAttr).GetFld() &&
+ pField->GetTyp() == ((SwFmtFld&)rAttr).GetFld()->GetTyp() &&
+ pField->GetFormat() == ((SwFmtFld&)rAttr).GetFld()->GetFormat() ) ||
+ ( !pField && !((SwFmtFld&)rAttr).GetFld() );
+}
+
+SfxPoolItem* SwFmtFld::Clone( SfxItemPool* ) const
+{
+ return new SwFmtFld( *this );
+}
+
+void SwFmtFld::SwClientNotify( const SwModify&, const SfxHint& rHint )
+{
+ if( !pTxtAttr )
+ return;
+
+ const SwFieldHint* pHint = dynamic_cast<const SwFieldHint*>( &rHint );
+ if ( pHint )
+ {
+ // replace field content by text
+ SwPaM* pPaM = pHint->GetPaM();
+ SwDoc* pDoc = pPaM->GetDoc();
+ const SwTxtNode& rTxtNode = pTxtAttr->GetTxtNode();
+ pPaM->GetPoint()->nNode = rTxtNode;
+ pPaM->GetPoint()->nContent.Assign( (SwTxtNode*)&rTxtNode, *pTxtAttr->GetStart() );
+
+ String const aEntry( GetFld()->ExpandField( pDoc->IsClipBoard() ) );
+ pPaM->SetMark();
+ pPaM->Move( fnMoveForward );
+ pDoc->DeleteRange( *pPaM );
+ pDoc->InsertString( *pPaM, aEntry );
+ }
+}
+
+void SwFmtFld::Modify( const SfxPoolItem* pOld, const SfxPoolItem* pNew )
+{
+ if( !pTxtAttr )
+ return;
+
+ // don't do anything, especially not expand!
+ if( pNew && pNew->Which() == RES_OBJECTDYING )
+ return;
+
+ SwTxtNode* pTxtNd = (SwTxtNode*)&pTxtAttr->GetTxtNode();
+ OSL_ENSURE( pTxtNd, "wo ist denn mein Node?" );
+ if( pNew )
+ {
+ switch( pNew->Which() )
+ {
+ case RES_TXTATR_FLDCHG:
+ // "Farbe hat sich geaendert !"
+ // this, this fuer "nur Painten"
+ pTxtNd->ModifyNotification( this, this );
+ return;
+ case RES_REFMARKFLD_UPDATE:
+ // GetReferenz-Felder aktualisieren
+ if( RES_GETREFFLD == GetFld()->GetTyp()->Which() )
+ {
+ // --> OD 2007-09-06 #i81002#
+// ((SwGetRefField*)GetFld())->UpdateField();
+ dynamic_cast<SwGetRefField*>(GetFld())->UpdateField( pTxtAttr );
+ // <--
+ }
+ break;
+ case RES_DOCPOS_UPDATE:
+ // Je nach DocPos aktualisieren (SwTxtFrm::Modify())
+ pTxtNd->ModifyNotification( pNew, this );
+ return;
+
+ case RES_ATTRSET_CHG:
+ case RES_FMT_CHG:
+ pTxtNd->ModifyNotification( pOld, pNew );
+ return;
+ default:
+ break;
+ }
+ }
+
+ switch (GetFld()->GetTyp()->Which())
+ {
+ case RES_HIDDENPARAFLD:
+ if( !pOld || RES_HIDDENPARA_PRINT != pOld->Which() )
+ break;
+ case RES_DBSETNUMBERFLD:
+ case RES_DBNUMSETFLD:
+ case RES_DBNEXTSETFLD:
+ case RES_DBNAMEFLD:
+ pTxtNd->ModifyNotification( 0, pNew);
+ return;
+ }
+
+ if( RES_USERFLD == GetFld()->GetTyp()->Which() )
+ {
+ SwUserFieldType* pType = (SwUserFieldType*)GetFld()->GetTyp();
+ if(!pType->IsValid())
+ {
+ SwCalc aCalc( *pTxtNd->GetDoc() );
+ pType->GetValue( aCalc );
+ }
+ }
+ pTxtAttr->Expand();
+}
+
+sal_Bool SwFmtFld::GetInfo( SfxPoolItem& rInfo ) const
+{
+ const SwTxtNode* pTxtNd;
+ if( RES_AUTOFMT_DOCNODE != rInfo.Which() ||
+ !pTxtAttr || 0 == ( pTxtNd = pTxtAttr->GetpTxtNode() ) ||
+ &pTxtNd->GetNodes() != ((SwAutoFmtGetDocNode&)rInfo).pNodes )
+ return sal_True;
+
+ ((SwAutoFmtGetDocNode&)rInfo).pCntntNode = pTxtNd;
+ return sal_False;
+}
+
+
+sal_Bool SwFmtFld::IsFldInDoc() const
+{
+ const SwTxtNode* pTxtNd;
+ return pTxtAttr && 0 != ( pTxtNd = pTxtAttr->GetpTxtNode() ) &&
+ pTxtNd->GetNodes().IsDocNodes();
+}
+
+sal_Bool SwFmtFld::IsProtect() const
+{
+ const SwTxtNode* pTxtNd;
+ return pTxtAttr && 0 != ( pTxtNd = pTxtAttr->GetpTxtNode() ) &&
+ pTxtNd->IsProtect();
+}
+
+/*************************************************************************
+|*
+|* SwTxtFld::SwTxtFld()
+|*
+|* Beschreibung Attribut fuer automatischen Text, Ctor
+|*
+*************************************************************************/
+
+SwTxtFld::SwTxtFld(SwFmtFld & rAttr, xub_StrLen const nStartPos)
+ : SwTxtAttr( rAttr, nStartPos )
+ , m_aExpand( rAttr.GetFld()->ExpandField(true) )
+ , m_pTxtNode( 0 )
+{
+ rAttr.pTxtAttr = this;
+ SetHasDummyChar(true);
+}
+
+SwTxtFld::~SwTxtFld( )
+{
+ SwFmtFld & rFmtFld( static_cast<SwFmtFld &>(GetAttr()) );
+ if (this == rFmtFld.pTxtAttr)
+ {
+ rFmtFld.pTxtAttr = 0; // #i110140# invalidate!
+ }
+}
+
+/*************************************************************************
+|*
+|* SwTxtFld::Expand()
+|*
+|* Beschreibung exandiert das Feld und tauscht den Text im Node
+|*
+*************************************************************************/
+
+void SwTxtFld::Expand() const
+{
+ // Wenn das expandierte Feld sich nicht veraendert hat, wird returnt
+ OSL_ENSURE( m_pTxtNode, "SwTxtFld: where is my TxtNode?" );
+
+ const SwField* pFld = GetFld().GetFld();
+ XubString aNewExpand(
+ pFld->ExpandField(m_pTxtNode->GetDoc()->IsClipBoard()) );
+
+ if( aNewExpand == m_aExpand )
+ {
+ // Bei Seitennummernfeldern
+ const sal_uInt16 nWhich = pFld->GetTyp()->Which();
+ if( RES_CHAPTERFLD != nWhich && RES_PAGENUMBERFLD != nWhich &&
+ RES_REFPAGEGETFLD != nWhich &&
+ // --> FME 2005-05-23 #122919# Page count fields to not use aExpand
+ // during formatting, therefore an invalidation of the text frame
+ // has to be triggered even if aNewExpand == aExpand:
+ ( RES_DOCSTATFLD != nWhich || DS_PAGE != static_cast<const SwDocStatField*>(pFld)->GetSubType() ) &&
+ // <--
+ ( RES_GETEXPFLD != nWhich || ((SwGetExpField*)pFld)->IsInBodyTxt() ) )
+ {
+ // BP: das muesste man noch optimieren!
+ //JP 12.06.97: stimmt, man sollte auf jedenfall eine Status-
+ // aenderung an die Frames posten
+ if( m_pTxtNode->CalcHiddenParaField() )
+ {
+ m_pTxtNode->ModifyNotification( 0, 0 );
+ }
+ return;
+ }
+ }
+
+ m_aExpand = aNewExpand;
+
+ // 0, this for formatting
+ m_pTxtNode->ModifyNotification( 0, const_cast<SwFmtFld*>( &GetFld() ) );
+}
+
+/*************************************************************************
+ * SwTxtFld::CopyFld()
+ *************************************************************************/
+
+void SwTxtFld::CopyFld( SwTxtFld *pDest ) const
+{
+ OSL_ENSURE( m_pTxtNode, "SwTxtFld: where is my TxtNode?" );
+ OSL_ENSURE( pDest->m_pTxtNode, "SwTxtFld: where is pDest's TxtNode?" );
+
+ IDocumentFieldsAccess* pIDFA = m_pTxtNode->getIDocumentFieldsAccess();
+ IDocumentFieldsAccess* pDestIDFA = pDest->m_pTxtNode->getIDocumentFieldsAccess();
+
+ SwFmtFld& rFmtFld = (SwFmtFld&)pDest->GetFld();
+ const sal_uInt16 nFldWhich = rFmtFld.GetFld()->GetTyp()->Which();
+
+ if( pIDFA != pDestIDFA )
+ {
+ // Die Hints stehen in unterschiedlichen Dokumenten,
+ // der Feldtyp muss im neuen Dokument angemeldet werden.
+ // Z.B: Kopieren ins ClipBoard.
+ SwFieldType* pFldType;
+ if( nFldWhich != RES_DBFLD && nFldWhich != RES_USERFLD &&
+ nFldWhich != RES_SETEXPFLD && nFldWhich != RES_DDEFLD &&
+ RES_AUTHORITY != nFldWhich )
+ pFldType = pDestIDFA->GetSysFldType( nFldWhich );
+ else
+ pFldType = pDestIDFA->InsertFldType( *rFmtFld.GetFld()->GetTyp() );
+
+ // Sonderbehandlung fuer DDE-Felder
+ if( RES_DDEFLD == nFldWhich )
+ {
+ if( rFmtFld.GetTxtFld() )
+ ((SwDDEFieldType*)rFmtFld.GetFld()->GetTyp())->DecRefCnt();
+ ((SwDDEFieldType*)pFldType)->IncRefCnt();
+ }
+
+ OSL_ENSURE( pFldType, "unbekannter FieldType" );
+ pFldType->Add( &rFmtFld ); // ummelden
+ rFmtFld.GetFld()->ChgTyp( pFldType );
+ }
+
+ // Expressionfelder Updaten
+ if( nFldWhich == RES_SETEXPFLD || nFldWhich == RES_GETEXPFLD ||
+ nFldWhich == RES_HIDDENTXTFLD )
+ {
+ SwTxtFld* pFld = (SwTxtFld*)this;
+ pDestIDFA->UpdateExpFlds( pFld, true );
+ }
+ // Tabellenfelder auf externe Darstellung
+ else if( RES_TABLEFLD == nFldWhich &&
+ ((SwTblField*)rFmtFld.GetFld())->IsIntrnlName() )
+ {
+ // erzeuge aus der internen (fuer CORE) die externe (fuer UI) Formel
+ const SwTableNode* pTblNd = m_pTxtNode->FindTableNode();
+ if( pTblNd ) // steht in einer Tabelle
+ ((SwTblField*)rFmtFld.GetFld())->PtrToBoxNm( &pTblNd->GetTable() );
+ }
+}
+
+void SwTxtFld::NotifyContentChange(SwFmtFld& rFmtFld)
+{
+ //if not in undo section notify the change
+ if (m_pTxtNode && m_pTxtNode->GetNodes().IsDocNodes())
+ {
+ m_pTxtNode->ModifyNotification(0, &rFmtFld);
+ }
+}
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/txtnode/atrflyin.cxx b/sw/source/core/txtnode/atrflyin.cxx
new file mode 100644
index 000000000000..4a7319993d0a
--- /dev/null
+++ b/sw/source/core/txtnode/atrflyin.cxx
@@ -0,0 +1,286 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+#include "hintids.hxx"
+#include "cntfrm.hxx" // _GetFly
+#include "doc.hxx"
+#include <IDocumentUndoRedo.hxx>
+#include "pam.hxx" // fuer SwTxtFlyCnt
+#include "flyfrm.hxx" // fuer SwTxtFlyCnt
+#include "ndtxt.hxx" // SwFlyFrmFmt
+#include "frmfmt.hxx" // SwFlyFrmFmt
+#include <fmtflcnt.hxx>
+#include <txtflcnt.hxx>
+#include <fmtanchr.hxx>
+#include "swfont.hxx"
+#include "txtfrm.hxx"
+#include "flyfrms.hxx"
+#include <objectformatter.hxx>
+#include <switerator.hxx>
+
+SwFmtFlyCnt::SwFmtFlyCnt( SwFrmFmt *pFrmFmt )
+ : SfxPoolItem( RES_TXTATR_FLYCNT ),
+ pTxtAttr( 0 ),
+ pFmt( pFrmFmt )
+{
+}
+
+int SwFmtFlyCnt::operator==( const SfxPoolItem& rAttr ) const
+{
+ OSL_ENSURE( SfxPoolItem::operator==( rAttr ), "keine gleichen Attribute" );
+ return( pTxtAttr && ((SwFmtFlyCnt&)rAttr).pTxtAttr &&
+ *pTxtAttr->GetStart() == *((SwFmtFlyCnt&)rAttr).pTxtAttr->GetStart() &&
+ pFmt == ((SwFmtFlyCnt&)rAttr).GetFrmFmt() );
+}
+
+SfxPoolItem* SwFmtFlyCnt::Clone( SfxItemPool* ) const
+{
+ return new SwFmtFlyCnt( pFmt );
+}
+
+SwTxtFlyCnt::SwTxtFlyCnt( SwFmtFlyCnt& rAttr, xub_StrLen nStartPos )
+ : SwTxtAttr( rAttr, nStartPos )
+{
+ rAttr.pTxtAttr = this;
+ SetHasDummyChar(true);
+}
+
+
+
+/*************************************************************************
+ * SwTxtFlyCnt::MakeTxtHint()
+ *
+ * An dieser Stelle soll einmal der Gesamtzusammenhang bei der Erzeugung
+ * eines neuen SwTxtFlyCnt erlaeutert werden.
+ * Das MakeTxtHint() wird z.B. im SwTxtNode::Copy() gerufen.
+ * Fuer die komplette Verdopplung sind folgende Schritte notwendig:
+ * 1) Duplizieren des pFmt incl. Inhalt, Attributen etc.
+ * 2) Setzen des Ankers
+ * 3) Benachrichtigung
+ * Da fuer die Bewaeltigung der Aufgaben nicht immer alle Informationen
+ * bereitstehen und darueber hinaus bestimmte Methoden erst zu einem
+ * spaeteren Zeitpunkt gerufen werden duerfen (weil nocht nicht alle
+ * Nodeinformationen vorliegen), verteilt sich der Ablauf.
+ * ad 1) MakeTxtHint() wird durch den Aufruf von SwDoc::CopyLayout()
+ * der das neue FlyFrmFmt erzeugt und mit dem duplizierten Inhalt des
+ * FlyFrm verbunden.
+ * ad 2) SetAnchor() wird von SwTxtNode::Insert() gerufen und sorgt fuer das
+ * setzen des Ankers (die SwPosition des Dummy-Zeichens wird dem FlyFrmFmt
+ * per SetAttr bekannt gegeben). Dies kann nicht im MakeTxtHint erledigt
+ * werden, da der Zielnode unbestimmt ist.
+ * ad 3) _GetFlyFrm() wird im Formatierungsprozess vom LineIter gerufen
+ * und sucht den FlyFrm zum Dummyzeichen des aktuellen CntntFrm. Wird keiner
+ * gefunden, so wird ein neuer FlyFrm angelegt.
+ * Kritisch an diesem Vorgehen ist, dass das pCntnt->AppendFly() eine
+ * sofortige Neuformatierung von pCntnt anstoesst. Die Rekursion kommt
+ * allerdings durch den Lockmechanismus in SwTxtFrm::Format() nicht
+ * zu stande.
+ * Attraktiv ist der Umstand, dass niemand ueber die vom Node abhaengigen
+ * CntntFrms iterieren braucht, um die FlyInCntFrm anzulegen. Dies geschieht
+ * bei der Arbeit.
+ *************************************************************************/
+
+void SwTxtFlyCnt::CopyFlyFmt( SwDoc* pDoc )
+{
+ SwFrmFmt* pFmt = GetFlyCnt().GetFrmFmt();
+ OSL_ENSURE( pFmt, "von welchem Format soll ich eine Kopie erzeugen?" );
+ // Das FlyFrmFmt muss dupliziert werden.
+ // In CopyLayoutFmt (siehe doclay.cxx) wird das FlyFrmFmt erzeugt
+ // und der Inhalt dupliziert.
+
+ // disable undo while copying attribute
+ ::sw::UndoGuard const undoGuard(pDoc->GetIDocumentUndoRedo());
+ SwFmtAnchor aAnchor( pFmt->GetAnchor() );
+ if ((FLY_AT_PAGE != aAnchor.GetAnchorId()) &&
+ (pDoc != pFmt->GetDoc())) // different documents?
+ {
+ // JP 03.06.96: dann sorge dafuer, das der koperierte Anker auf
+ // gueltigen Content zeigt! Die Umsetzung auf die
+ // richtige Position erfolgt spaeter.
+ SwNodeIndex aIdx( pDoc->GetNodes().GetEndOfExtras(), +2 );
+ SwCntntNode* pCNd = aIdx.GetNode().GetCntntNode();
+ if( !pCNd )
+ pCNd = pDoc->GetNodes().GoNext( &aIdx );
+
+ SwPosition* pPos = (SwPosition*)aAnchor.GetCntntAnchor();
+ pPos->nNode = aIdx;
+ if (FLY_AS_CHAR == aAnchor.GetAnchorId())
+ {
+ pPos->nContent.Assign( pCNd, 0 );
+ }
+ else
+ {
+ pPos->nContent.Assign( 0, 0 );
+ OSL_ENSURE( !this, "CopyFlyFmt: Was fuer ein Anker?" );
+ }
+ }
+
+ SwFrmFmt* pNew = pDoc->CopyLayoutFmt( *pFmt, aAnchor, false, false );
+ ((SwFmtFlyCnt&)GetFlyCnt()).SetFlyFmt( pNew );
+}
+
+/*************************************************************************
+ * SwTxtFlyCnt::SetAnchor()
+ *
+ * SetAnchor() wird von SwTxtNode::Insert() gerufen und sorgt fuer das
+ * setzen des Ankers (die SwPosition des Dummy-Zeichens wird dem FlyFrmFmt
+ * per SetAttr bekannt gegeben). Dies kann nicht im MakeTxtHint erledigt
+ * werden, da der Zielnode unbestimmt ist.
+ * (siehe Kommentar in SwTxtFlyCnt::MakeTxtHint)
+ *************************************************************************/
+
+void SwTxtFlyCnt::SetAnchor( const SwTxtNode *pNode )
+{
+ // fuers Undo muss der neue Anker schon bekannt sein !
+
+ // Wir ermitteln den Index im Nodesarray zum Node
+
+ SwDoc* pDoc = (SwDoc*)pNode->GetDoc();
+
+ SwIndex aIdx( (SwTxtNode*)pNode, *GetStart() );
+ SwPosition aPos( *pNode->StartOfSectionNode(), aIdx );
+ SwFrmFmt* pFmt = GetFlyCnt().GetFrmFmt();
+ SwFmtAnchor aAnchor( pFmt->GetAnchor() );
+
+ if( !aAnchor.GetCntntAnchor() ||
+ !aAnchor.GetCntntAnchor()->nNode.GetNode().GetNodes().IsDocNodes() ||
+ &aAnchor.GetCntntAnchor()->nNode.GetNode() != (SwNode*)pNode )
+ aPos.nNode = *pNode;
+ else
+ aPos.nNode = aAnchor.GetCntntAnchor()->nNode;
+
+ aAnchor.SetType( FLY_AS_CHAR ); // default!
+ aAnchor.SetAnchor( &aPos );
+
+ // beim Ankerwechsel werden immer alle FlyFrms vom Attribut geloescht
+ // JP 25.04.95: wird innerhalb des SplitNodes die Frames verschoben
+ // koennen die Frames erhalten bleiben.
+ if( ( !pNode->GetpSwpHints() || !pNode->GetpSwpHints()->IsInSplitNode() )
+ && RES_DRAWFRMFMT != pFmt->Which() )
+ pFmt->DelFrms();
+
+ // stehen wir noch im falschen Dokument ?
+ if( pDoc != pFmt->GetDoc() )
+ {
+ // disable undo while copying attribute
+ ::sw::UndoGuard const undoGuard(pDoc->GetIDocumentUndoRedo());
+ SwFrmFmt* pNew = pDoc->CopyLayoutFmt( *pFmt, aAnchor, false, false );
+
+ ::sw::UndoGuard const undoGuardFmt(
+ pFmt->GetDoc()->GetIDocumentUndoRedo());
+ pFmt->GetDoc()->DelLayoutFmt( pFmt );
+ ((SwFmtFlyCnt&)GetFlyCnt()).SetFlyFmt( pNew );
+ }
+ else if( pNode->GetpSwpHints() &&
+ pNode->GetpSwpHints()->IsInSplitNode() &&
+ RES_DRAWFRMFMT != pFmt->Which() )
+ {
+ pFmt->LockModify();
+ pFmt->SetFmtAttr( aAnchor ); // nur den Anker neu setzen
+ pFmt->UnlockModify();
+ }
+ else
+ pFmt->SetFmtAttr( aAnchor ); // nur den Anker neu setzen
+
+ // Am Node haengen u.a. abhaengige CntFrms.
+ // Fuer jeden CntFrm wird ein SwFlyInCntFrm angelegt.
+}
+
+/*************************************************************************
+ * SwTxtFlyCnt::_GetFlyFrm()
+ *
+ * _GetFlyFrm() wird im Formatierungsprozess vom LineIter gerufen
+ * und sucht den FlyFrm zum Dummyzeichen des aktuellen CntntFrm. Wird keiner
+ * gefunden, so wird ein neuer FlyFrm angelegt.
+ * (siehe Kommentar ind SwTxtFlyCnt::MakeTxtHint)
+ *************************************************************************/
+
+SwFlyInCntFrm *SwTxtFlyCnt::_GetFlyFrm( const SwFrm *pCurrFrm )
+{
+ SwFrmFmt* pFrmFmt = GetFlyCnt().GetFrmFmt();
+ if( RES_DRAWFRMFMT == pFrmFmt->Which() )
+ {
+ OSL_ENSURE( !this, "SwTxtFlyCnt::_GetFlyFrm: DrawInCnt-Baustelle!" );
+ return NULL;
+ }
+
+ SwIterator<SwFlyFrm,SwFmt> aIter( *GetFlyCnt().pFmt );
+ OSL_ENSURE( pCurrFrm->IsTxtFrm(), "SwTxtFlyCnt::_GetFlyFrm for TxtFrms only." );
+ SwFrm* pFrm = aIter.First();
+ if ( pFrm )
+ {
+ SwTxtFrm *pFirst = (SwTxtFrm*)pCurrFrm;
+ while ( pFirst->IsFollow() )
+ pFirst = pFirst->FindMaster();
+ do
+ {
+ SwTxtFrm *pTmp = pFirst;
+ do
+ { if( ( (SwFlyFrm*)pFrm )->GetAnchorFrm() == (SwFrm*) pTmp )
+ {
+ if ( pTmp != pCurrFrm )
+ {
+ pTmp->RemoveFly( (SwFlyFrm*)pFrm );
+ ((SwTxtFrm*)pCurrFrm)->AppendFly( (SwFlyFrm*)pFrm );
+ }
+ return (SwFlyInCntFrm*)pFrm;
+ }
+ pTmp = pTmp->GetFollow();
+ } while ( pTmp );
+
+ pFrm = aIter.Next();
+
+ } while( pFrm );
+ }
+
+ // Wir haben keinen passenden FlyFrm gefunden, deswegen wird ein
+ // neuer angelegt.
+ // Dabei wird eine sofortige Neuformatierung von pCurrFrm angestossen.
+ // Die Rekursion wird durch den Lockmechanismus in SwTxtFrm::Format()
+ // abgewuergt.
+ SwFrm* pCurrFrame = const_cast< SwFrm* >(pCurrFrm);
+ SwFlyInCntFrm *pFly = new SwFlyInCntFrm( (SwFlyFrmFmt*)pFrmFmt, pCurrFrame, pCurrFrame );
+ pCurrFrame->AppendFly( pFly );
+ pFly->RegistFlys();
+
+ // 7922: Wir muessen dafuer sorgen, dass der Inhalt des FlyInCnt
+ // nach seiner Konstruktion stramm durchformatiert wird.
+ // --> OD 2004-11-09 #i26945# - Use new object formatter to format Writer
+ // fly frame and its content.
+ SwObjectFormatter::FormatObj( *pFly, const_cast<SwFrm*>(pCurrFrm),
+ pCurrFrm->FindPageFrm() );
+ // <--
+
+ return pFly;
+}
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/txtnode/atrftn.cxx b/sw/source/core/txtnode/atrftn.cxx
new file mode 100644
index 000000000000..fdea3387ae6a
--- /dev/null
+++ b/sw/source/core/txtnode/atrftn.cxx
@@ -0,0 +1,545 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+
+
+#define _SVSTDARR_USHORTS
+#define _SVSTDARR_USHORTSSORT
+#include <svl/svstdarr.hxx>
+#include <doc.hxx>
+#include <cntfrm.hxx> // OSL_ENSURE(in ~SwTxtFtn()
+#include <pagefrm.hxx> // RemoveFtn()
+#include <fmtftn.hxx>
+#include <txtftn.hxx>
+#include <ftnidx.hxx>
+#include <ftninfo.hxx>
+#include <swfont.hxx>
+#include <ndtxt.hxx>
+#include <poolfmt.hxx>
+#include <ftnfrm.hxx>
+#include <ndindex.hxx>
+#include <fmtftntx.hxx>
+#include <section.hxx>
+#include <switerator.hxx>
+
+/*************************************************************************
+|*
+|* class SwFmtFtn
+|*
+*************************************************************************/
+
+
+SwFmtFtn::SwFmtFtn( bool bEndNote )
+ : SfxPoolItem( RES_TXTATR_FTN ),
+ pTxtAttr( 0 ),
+ nNumber( 0 ),
+ m_bEndNote( bEndNote )
+{
+}
+
+
+int SwFmtFtn::operator==( const SfxPoolItem& rAttr ) const
+{
+ OSL_ENSURE( SfxPoolItem::operator==( rAttr ), "keine gleichen Attribute" );
+ return nNumber == ((SwFmtFtn&)rAttr).nNumber &&
+ aNumber == ((SwFmtFtn&)rAttr).aNumber &&
+ m_bEndNote == ((SwFmtFtn&)rAttr).m_bEndNote;
+}
+
+
+SfxPoolItem* SwFmtFtn::Clone( SfxItemPool* ) const
+{
+ SwFmtFtn* pNew = new SwFmtFtn;
+ pNew->aNumber = aNumber;
+ pNew->nNumber = nNumber;
+ pNew->m_bEndNote = m_bEndNote;
+ return pNew;
+}
+
+void SwFmtFtn::SetEndNote( bool b )
+{
+ if ( b != m_bEndNote )
+ {
+ if ( GetTxtFtn() )
+ {
+ GetTxtFtn()->DelFrms(0);
+ }
+ m_bEndNote = b;
+ }
+}
+
+SwFmtFtn::~SwFmtFtn()
+{
+}
+
+
+void SwFmtFtn::GetFtnText( XubString& rStr ) const
+{
+ if( pTxtAttr->GetStartNode() )
+ {
+ SwNodeIndex aIdx( *pTxtAttr->GetStartNode(), 1 );
+ SwCntntNode* pCNd = aIdx.GetNode().GetTxtNode();
+ if( !pCNd )
+ pCNd = aIdx.GetNodes().GoNext( &aIdx );
+
+ if( pCNd->IsTxtNode() )
+ rStr = ((SwTxtNode*)pCNd)->GetExpandTxt();
+ }
+}
+
+ // returnt den anzuzeigenden String der Fuss-/Endnote
+XubString SwFmtFtn::GetViewNumStr( const SwDoc& rDoc, sal_Bool bInclStrings ) const
+{
+ XubString sRet( GetNumStr() );
+ if( !sRet.Len() )
+ {
+ // dann ist die Nummer von Interesse, also ueber die Info diese
+ // besorgen.
+ sal_Bool bMakeNum = sal_True;
+ const SwSectionNode* pSectNd = pTxtAttr
+ ? SwUpdFtnEndNtAtEnd::FindSectNdWithEndAttr( *pTxtAttr )
+ : 0;
+
+ if( pSectNd )
+ {
+ const SwFmtFtnEndAtTxtEnd& rFtnEnd = (SwFmtFtnEndAtTxtEnd&)
+ pSectNd->GetSection().GetFmt()->GetFmtAttr(
+ IsEndNote() ?
+ static_cast<sal_uInt16>(RES_END_AT_TXTEND) :
+ static_cast<sal_uInt16>(RES_FTN_AT_TXTEND) );
+
+ if( FTNEND_ATTXTEND_OWNNUMANDFMT == rFtnEnd.GetValue() )
+ {
+ bMakeNum = sal_False;
+ sRet = rFtnEnd.GetSwNumType().GetNumStr( GetNumber() );
+ if( bInclStrings )
+ {
+ sRet.Insert( rFtnEnd.GetPrefix(), 0 );
+ sRet += rFtnEnd.GetSuffix();
+ }
+ }
+ }
+
+ if( bMakeNum )
+ {
+ const SwEndNoteInfo* pInfo;
+ if( IsEndNote() )
+ pInfo = &rDoc.GetEndNoteInfo();
+ else
+ pInfo = &rDoc.GetFtnInfo();
+ sRet = pInfo->aFmt.GetNumStr( GetNumber() );
+ if( bInclStrings )
+ {
+ sRet.Insert( pInfo->GetPrefix(), 0 );
+ sRet += pInfo->GetSuffix();
+ }
+ }
+ }
+ return sRet;
+}
+
+/*************************************************************************
+ * class SwTxt/FmtFnt
+ *************************************************************************/
+
+SwTxtFtn::SwTxtFtn( SwFmtFtn& rAttr, xub_StrLen nStartPos )
+ : SwTxtAttr( rAttr, nStartPos )
+ , m_pStartNode( 0 )
+ , m_pTxtNode( 0 )
+ , m_nSeqNo( USHRT_MAX )
+{
+ rAttr.pTxtAttr = this;
+ SetHasDummyChar(true);
+}
+
+
+SwTxtFtn::~SwTxtFtn()
+{
+ SetStartNode( 0 );
+}
+
+
+
+void SwTxtFtn::SetStartNode( const SwNodeIndex *pNewNode, sal_Bool bDelNode )
+{
+ if( pNewNode )
+ {
+ if ( !m_pStartNode )
+ {
+ m_pStartNode = new SwNodeIndex( *pNewNode );
+ }
+ else
+ {
+ *m_pStartNode = *pNewNode;
+ }
+ }
+ else if ( m_pStartNode )
+ {
+ // Zwei Dinge muessen erledigt werden:
+ // 1) Die Fussnoten muessen bei ihren Seiten abgemeldet werden
+ // 2) Die Fussnoten-Sektion in den Inserts muss geloescht werden.
+ SwDoc* pDoc;
+ if ( m_pTxtNode )
+ {
+ pDoc = m_pTxtNode->GetDoc();
+ }
+ else
+ {
+ //JP 27.01.97: der sw3-Reader setzt einen StartNode aber das
+ // Attribut ist noch nicht im TextNode verankert.
+ // Wird es geloescht (z.B. bei Datei einfuegen mit
+ // Ftn in einen Rahmen), muss auch der Inhalt
+ // geloescht werden
+ pDoc = m_pStartNode->GetNodes().GetDoc();
+ }
+
+ // Wir duerfen die Fussnotennodes nicht loeschen
+ // und brauchen die Fussnotenframes nicht loeschen, wenn
+ // wir im ~SwDoc() stehen.
+ if( !pDoc->IsInDtor() )
+ {
+ if( bDelNode )
+ {
+ // 1) Die Section fuer die Fussnote wird beseitigt
+ // Es kann sein, dass die Inserts schon geloescht wurden.
+ pDoc->DeleteSection( &m_pStartNode->GetNode() );
+ }
+ else
+ // Werden die Nodes nicht geloescht mussen sie bei den Seiten
+ // abmeldet (Frms loeschen) werden, denn sonst bleiben sie
+ // stehen (Undo loescht sie nicht!)
+ DelFrms( 0 );
+ }
+ DELETEZ( m_pStartNode );
+
+ // loesche die Fussnote noch aus dem Array am Dokument
+ for( sal_uInt16 n = 0; n < pDoc->GetFtnIdxs().Count(); ++n )
+ if( this == pDoc->GetFtnIdxs()[n] )
+ {
+ pDoc->GetFtnIdxs().Remove( n );
+ // gibt noch weitere Fussnoten
+ if( !pDoc->IsInDtor() && n < pDoc->GetFtnIdxs().Count() )
+ {
+ SwNodeIndex aTmp( pDoc->GetFtnIdxs()[n]->GetTxtNode() );
+ pDoc->GetFtnIdxs().UpdateFtn( aTmp );
+ }
+ break;
+ }
+ }
+}
+
+
+void SwTxtFtn::SetNumber( const sal_uInt16 nNewNum, const XubString* pStr )
+{
+ SwFmtFtn& rFtn = (SwFmtFtn&)GetFtn();
+ if( pStr && pStr->Len() )
+ rFtn.aNumber = *pStr;
+ else
+ {
+ rFtn.nNumber = nNewNum;
+ rFtn.aNumber = aEmptyStr;
+ }
+
+ OSL_ENSURE( m_pTxtNode, "SwTxtFtn: where is my TxtNode?" );
+ SwNodes &rNodes = m_pTxtNode->GetDoc()->GetNodes();
+ m_pTxtNode->ModifyNotification( 0, &rFtn );
+ if ( m_pStartNode )
+ {
+ // must iterate over all TxtNodes because of footnotes on other pages
+ SwNode* pNd;
+ sal_uLong nSttIdx = m_pStartNode->GetIndex() + 1;
+ sal_uLong nEndIdx = m_pStartNode->GetNode().EndOfSectionIndex();
+ for( ; nSttIdx < nEndIdx; ++nSttIdx )
+ {
+ // Es koennen ja auch Grafiken in der Fussnote stehen ...
+ if( ( pNd = rNodes[ nSttIdx ] )->IsTxtNode() )
+ ((SwTxtNode*)pNd)->ModifyNotification( 0, &rFtn );
+ }
+ }
+}
+
+// Die Fussnoten duplizieren
+void SwTxtFtn::CopyFtn(SwTxtFtn & rDest, SwTxtNode & rDestNode) const
+{
+ if (m_pStartNode && !rDest.GetStartNode())
+ {
+ // dest missing node section? create it here!
+ // (happens in SwTxtNode::CopyText if pDest == this)
+ rDest.MakeNewTextSection( rDestNode.GetNodes() );
+ }
+ if (m_pStartNode && rDest.GetStartNode())
+ {
+ // footnotes not necessarily in same document!
+ SwDoc *const pDstDoc = rDestNode.GetDoc();
+ SwNodes &rDstNodes = pDstDoc->GetNodes();
+
+ // copy only the content of the section
+ SwNodeRange aRg( *m_pStartNode, 1,
+ *m_pStartNode->GetNode().EndOfSectionNode() );
+
+ // insert at the end of rDest, i.e., the nodes are appended.
+ // nDestLen contains number of CntntNodes in rDest _before_ copy.
+ SwNodeIndex aStart( *(rDest.GetStartNode()) );
+ SwNodeIndex aEnd( *aStart.GetNode().EndOfSectionNode() );
+ sal_uLong nDestLen = aEnd.GetIndex() - aStart.GetIndex() - 1;
+
+ m_pTxtNode->GetDoc()->CopyWithFlyInFly( aRg, 0, aEnd, sal_True );
+
+ // in case the destination section was not empty, delete the old nodes
+ // before: Src: SxxxE, Dst: SnE
+ // now: Src: SxxxE, Dst: SnxxxE
+ // after: Src: SxxxE, Dst: SxxxE
+ aStart++;
+ rDstNodes.Delete( aStart, nDestLen );
+ }
+
+ // also copy user defined number string
+ if( GetFtn().aNumber.Len() )
+ {
+ const_cast<SwFmtFtn &>(rDest.GetFtn()).aNumber = GetFtn().aNumber;
+ }
+}
+
+
+ // lege eine neue leere TextSection fuer diese Fussnote an
+void SwTxtFtn::MakeNewTextSection( SwNodes& rNodes )
+{
+ if ( m_pStartNode )
+ return;
+
+ // Nun verpassen wir dem TxtNode noch die Fussnotenvorlage.
+ SwTxtFmtColl *pFmtColl;
+ const SwEndNoteInfo* pInfo;
+ sal_uInt16 nPoolId;
+
+ if( GetFtn().IsEndNote() )
+ {
+ pInfo = &rNodes.GetDoc()->GetEndNoteInfo();
+ nPoolId = RES_POOLCOLL_ENDNOTE;
+ }
+ else
+ {
+ pInfo = &rNodes.GetDoc()->GetFtnInfo();
+ nPoolId = RES_POOLCOLL_FOOTNOTE;
+ }
+
+ if( 0 == (pFmtColl = pInfo->GetFtnTxtColl() ) )
+ pFmtColl = rNodes.GetDoc()->GetTxtCollFromPool( nPoolId );
+
+ SwStartNode* pSttNd = rNodes.MakeTextSection( SwNodeIndex( rNodes.GetEndOfInserts() ),
+ SwFootnoteStartNode, pFmtColl );
+ m_pStartNode = new SwNodeIndex( *pSttNd );
+}
+
+
+void SwTxtFtn::DelFrms( const SwFrm* pSib )
+{
+ // delete the FtnFrames from the pages
+ OSL_ENSURE( m_pTxtNode, "SwTxtFtn: where is my TxtNode?" );
+ if ( !m_pTxtNode )
+ return;
+
+ const SwRootFrm* pRoot = pSib ? pSib->getRootFrm() : 0;
+ sal_Bool bFrmFnd = sal_False;
+ {
+ SwIterator<SwCntntFrm,SwTxtNode> aIter( *m_pTxtNode );
+ for( SwCntntFrm* pFnd = aIter.First(); pFnd; pFnd = aIter.Next() )
+ {
+ if( pRoot != pFnd->getRootFrm() && pRoot )
+ continue;
+ SwPageFrm* pPage = pFnd->FindPageFrm();
+ if( pPage )
+ {
+ pPage->RemoveFtn( pFnd, this );
+ bFrmFnd = sal_True;
+ }
+ }
+ }
+ //JP 13.05.97: falls das Layout vorm loeschen der Fussnoten entfernt
+ // wird, sollte man das ueber die Fussnote selbst tun
+ if ( !bFrmFnd && m_pStartNode )
+ {
+ SwNodeIndex aIdx( *m_pStartNode );
+ SwCntntNode* pCNd = m_pTxtNode->GetNodes().GoNext( &aIdx );
+ if( pCNd )
+ {
+ SwIterator<SwCntntFrm,SwCntntNode> aIter( *pCNd );
+ for( SwCntntFrm* pFnd = aIter.First(); pFnd; pFnd = aIter.Next() )
+ {
+ if( pRoot != pFnd->getRootFrm() && pRoot )
+ continue;
+ SwPageFrm* pPage = pFnd->FindPageFrm();
+
+ SwFrm *pFrm = pFnd->GetUpper();
+ while ( pFrm && !pFrm->IsFtnFrm() )
+ pFrm = pFrm->GetUpper();
+
+ SwFtnFrm *pFtn = (SwFtnFrm*)pFrm;
+ while ( pFtn && pFtn->GetMaster() )
+ pFtn = pFtn->GetMaster();
+ OSL_ENSURE( pFtn->GetAttr() == this, "Ftn mismatch error." );
+
+ while ( pFtn )
+ {
+ SwFtnFrm *pFoll = pFtn->GetFollow();
+ pFtn->Cut();
+ delete pFtn;
+ pFtn = pFoll;
+ }
+
+ // #i20556# During hiding of a section, the connection
+ // to the layout is already lost. pPage may be 0:
+ if ( pPage )
+ pPage->UpdateFtnNum();
+ }
+ }
+ }
+}
+
+
+sal_uInt16 SwTxtFtn::SetSeqRefNo()
+{
+ if( !m_pTxtNode )
+ return USHRT_MAX;
+
+ SwDoc* pDoc = m_pTxtNode->GetDoc();
+ if( pDoc->IsInReading() )
+ return USHRT_MAX;
+
+ sal_uInt16 n, nFtnCnt = pDoc->GetFtnIdxs().Count();
+
+ const sal_uInt8 nTmp = 255 < nFtnCnt ? 255 : static_cast<sal_uInt8>(nFtnCnt);
+ SvUShortsSort aArr( nTmp, nTmp );
+
+ // dann testmal, ob die Nummer schon vergeben ist oder ob eine neue
+ // bestimmt werden muss.
+ SwTxtFtn* pTxtFtn;
+ for( n = 0; n < nFtnCnt; ++n )
+ {
+ pTxtFtn = pDoc->GetFtnIdxs()[ n ];
+ if ( pTxtFtn != this )
+ {
+ aArr.Insert( pTxtFtn->m_nSeqNo );
+ }
+ }
+
+ // test if number is already in use
+ if ( USHRT_MAX != m_nSeqNo )
+ {
+ for( n = 0; n < aArr.Count(); ++n )
+ {
+ if ( aArr[ n ] > m_nSeqNo )
+ {
+ return m_nSeqNo; // free -> use
+ }
+ else if ( aArr[ n ] == m_nSeqNo )
+ {
+ break; // used -> create new one
+ }
+ }
+
+ if ( n == aArr.Count() )
+ {
+ return m_nSeqNo; // free -> use
+ }
+ }
+
+ // alle Nummern entsprechend geflag, also bestimme die richtige Nummer
+ for( n = 0; n < aArr.Count(); ++n )
+ if( n != aArr[ n ] )
+ break;
+
+ return m_nSeqNo = n;
+}
+
+void SwTxtFtn::SetUniqueSeqRefNo( SwDoc& rDoc )
+{
+ sal_uInt16 n, nStt = 0, nFtnCnt = rDoc.GetFtnIdxs().Count();
+
+ const sal_uInt8 nTmp = 255 < nFtnCnt ? 255 : static_cast<sal_uInt8>(nFtnCnt);
+ SvUShortsSort aArr( nTmp, nTmp );
+
+ // dann alle Nummern zusammensammeln die schon existieren
+ SwTxtFtn* pTxtFtn;
+ for( n = 0; n < nFtnCnt; ++n )
+ {
+ pTxtFtn = rDoc.GetFtnIdxs()[ n ];
+ if ( USHRT_MAX != pTxtFtn->m_nSeqNo )
+ {
+ aArr.Insert( pTxtFtn->m_nSeqNo );
+ }
+ }
+
+
+ for( n = 0; n < nFtnCnt; ++n )
+ {
+ pTxtFtn = rDoc.GetFtnIdxs()[ n ];
+ if ( USHRT_MAX == pTxtFtn->m_nSeqNo )
+ {
+ for( ; nStt < aArr.Count(); ++nStt )
+ {
+ if ( nStt != aArr[ nStt ] )
+ {
+ pTxtFtn->m_nSeqNo = nStt;
+ break;
+ }
+ }
+
+ if ( USHRT_MAX == pTxtFtn->m_nSeqNo )
+ {
+ break; // found nothing
+ }
+ }
+ }
+
+ // alle Nummern schon vergeben, also mit nStt++ weitermachen
+ for( ; n < nFtnCnt; ++n )
+ {
+ pTxtFtn = rDoc.GetFtnIdxs()[ n ];
+ if ( USHRT_MAX == pTxtFtn->m_nSeqNo )
+ {
+ pTxtFtn->m_nSeqNo = nStt++;
+ }
+ }
+}
+
+void SwTxtFtn::CheckCondColl()
+{
+//FEATURE::CONDCOLL
+ if( GetStartNode() )
+ ((SwStartNode&)GetStartNode()->GetNode()).CheckSectionCondColl();
+//FEATURE::CONDCOLL
+}
+
+
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/txtnode/atrref.cxx b/sw/source/core/txtnode/atrref.cxx
new file mode 100644
index 000000000000..7adfc3ff591f
--- /dev/null
+++ b/sw/source/core/txtnode/atrref.cxx
@@ -0,0 +1,105 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+
+#include <hintids.hxx>
+#include <txtrfmrk.hxx>
+#include <fmtrfmrk.hxx>
+#include <swfont.hxx>
+
+
+/****************************************************************************
+ *
+ * class SwFmtRefMark
+ *
+ ****************************************************************************/
+
+SwFmtRefMark::~SwFmtRefMark( )
+{
+}
+
+SwFmtRefMark::SwFmtRefMark( const XubString& rName )
+ : SfxPoolItem( RES_TXTATR_REFMARK ),
+ pTxtAttr( 0 ),
+ aRefName( rName )
+{
+}
+
+SwFmtRefMark::SwFmtRefMark( const SwFmtRefMark& rAttr )
+ : SfxPoolItem( RES_TXTATR_REFMARK ),
+ pTxtAttr( 0 ),
+ aRefName( rAttr.aRefName )
+{
+}
+
+int SwFmtRefMark::operator==( const SfxPoolItem& rAttr ) const
+{
+ OSL_ENSURE( SfxPoolItem::operator==( rAttr ), "keine gleichen Attribute" );
+ return aRefName == ((SwFmtRefMark&)rAttr).aRefName;
+}
+
+SfxPoolItem* SwFmtRefMark::Clone( SfxItemPool* ) const
+{
+ return new SwFmtRefMark( *this );
+}
+
+/*************************************************************************
+ * class SwTxtRefMark
+ *************************************************************************/
+
+// Attribut fuer Inhalts-/Positions-Referenzen im Text
+
+SwTxtRefMark::SwTxtRefMark( SwFmtRefMark& rAttr,
+ xub_StrLen const nStartPos, xub_StrLen const*const pEnd)
+ : SwTxtAttrEnd( rAttr, nStartPos, nStartPos )
+ , m_pTxtNode( 0 )
+ , m_pEnd( 0 )
+{
+ rAttr.pTxtAttr = this;
+ if ( pEnd )
+ {
+ m_nEnd = *pEnd;
+ m_pEnd = & m_nEnd;
+ }
+ else
+ {
+ SetHasDummyChar(true);
+ }
+ SetDontMoveAttr( true );
+ SetOverlapAllowedAttr( true );
+}
+
+xub_StrLen* SwTxtRefMark::GetEnd()
+{
+ return m_pEnd;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/txtnode/atrtox.cxx b/sw/source/core/txtnode/atrtox.cxx
new file mode 100644
index 000000000000..1b3c989e23db
--- /dev/null
+++ b/sw/source/core/txtnode/atrtox.cxx
@@ -0,0 +1,99 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+
+#include <doc.hxx>
+#include <txttxmrk.hxx>
+#include <swfont.hxx>
+#include <tox.hxx>
+#include <ndtxt.hxx>
+
+SwTxtTOXMark::SwTxtTOXMark( SwTOXMark& rAttr,
+ xub_StrLen const nStartPos, xub_StrLen const*const pEnd)
+ : SwTxtAttrEnd( rAttr, nStartPos, nStartPos )
+ , m_pTxtNode( 0 )
+ , m_pEnd( 0 )
+{
+ rAttr.pTxtAttr = this;
+ if ( !rAttr.GetAlternativeText().Len() )
+ {
+ m_nEnd = *pEnd;
+ m_pEnd = & m_nEnd;
+ }
+ else
+ {
+ SetHasDummyChar(true);
+ }
+ SetDontMoveAttr( true );
+ SetOverlapAllowedAttr( true );
+}
+
+SwTxtTOXMark::~SwTxtTOXMark()
+{
+}
+
+xub_StrLen* SwTxtTOXMark::GetEnd()
+{
+ return m_pEnd;
+}
+
+void SwTxtTOXMark::CopyTOXMark( SwDoc* pDoc )
+{
+ SwTOXMark& rTOX = (SwTOXMark&)GetTOXMark();
+ TOXTypes eType = rTOX.GetTOXType()->GetType();
+ sal_uInt16 nCount = pDoc->GetTOXTypeCount( eType );
+ const SwTOXType* pType = 0;
+ const XubString& rNm = rTOX.GetTOXType()->GetTypeName();
+
+ // kein entsprechender Verzeichnistyp vorhanden -> anlegen
+ // sonst verwenden
+ for(sal_uInt16 i=0; i < nCount; ++i)
+ {
+ const SwTOXType* pSrcType = pDoc->GetTOXType(eType, i);
+ if(pSrcType->GetTypeName() == rNm )
+ {
+ pType = pSrcType;
+ break;
+ }
+ }
+ // kein entsprechender Typ vorhanden -> neu erzeugen
+ //
+ if(!pType)
+ {
+ pDoc->InsertTOXType( SwTOXType( eType, rNm ) );
+ pType = pDoc->GetTOXType(eType, 0);
+ }
+ // Verzeichnistyp umhaengen
+ //
+ ((SwTOXType*)pType)->Add( &rTOX );
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/txtnode/chrfmt.cxx b/sw/source/core/txtnode/chrfmt.cxx
new file mode 100644
index 000000000000..71d7e48f6d74
--- /dev/null
+++ b/sw/source/core/txtnode/chrfmt.cxx
@@ -0,0 +1,40 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+
+#include <charfmt.hxx>
+
+
+TYPEINIT1( SwCharFmt, SwFmt ); //rtti fuer SwCharFmt
+
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/txtnode/fmtatr2.cxx b/sw/source/core/txtnode/fmtatr2.cxx
new file mode 100644
index 000000000000..ed7ab96e35e2
--- /dev/null
+++ b/sw/source/core/txtnode/fmtatr2.cxx
@@ -0,0 +1,905 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+#include "hintids.hxx"
+#include "unomid.h"
+
+#include <basic/sbxvar.hxx>
+#include <svl/macitem.hxx>
+#include <svl/stritem.hxx>
+#include <svl/stylepool.hxx>
+#include <fmtautofmt.hxx>
+#include <fchrfmt.hxx>
+#include <fmtinfmt.hxx>
+#include <txtatr.hxx>
+#include <fmtruby.hxx>
+#include <charfmt.hxx>
+#include <hints.hxx> // SwUpdateAttr
+#include <unostyle.hxx>
+#include <unoevent.hxx> // SwHyperlinkEventDescriptor
+#include <com/sun/star/text/RubyAdjust.hdl>
+
+#include <cmdid.h>
+#include <com/sun/star/uno/Any.h>
+#include <SwStyleNameMapper.hxx>
+
+#include <fmtmeta.hxx>
+#include <ndtxt.hxx> // for meta
+#include <doc.hxx> // for meta
+#include <unometa.hxx>
+#include <docsh.hxx>
+#include <svl/zforlist.hxx> // GetNumberFormat
+
+#include <boost/bind.hpp>
+#include <algorithm>
+
+
+using namespace ::com::sun::star;
+using ::rtl::OUString;
+
+TYPEINIT1_AUTOFACTORY(SwFmtINetFmt, SfxPoolItem);
+TYPEINIT1_AUTOFACTORY(SwFmtAutoFmt, SfxPoolItem);
+
+/*************************************************************************
+|*
+|* class SwFmtCharFmt
+|*
+*************************************************************************/
+
+SwFmtCharFmt::SwFmtCharFmt( SwCharFmt *pFmt )
+ : SfxPoolItem( RES_TXTATR_CHARFMT ),
+ SwClient(pFmt),
+ pTxtAttr( 0 )
+{
+}
+
+
+
+SwFmtCharFmt::SwFmtCharFmt( const SwFmtCharFmt& rAttr )
+ : SfxPoolItem( RES_TXTATR_CHARFMT ),
+ SwClient( rAttr.GetCharFmt() ),
+ pTxtAttr( 0 )
+{
+}
+
+
+
+SwFmtCharFmt::~SwFmtCharFmt() {}
+
+
+
+int SwFmtCharFmt::operator==( const SfxPoolItem& rAttr ) const
+{
+ OSL_ENSURE( SfxPoolItem::operator==( rAttr ), "keine gleichen Attribute" );
+ return GetCharFmt() == ((SwFmtCharFmt&)rAttr).GetCharFmt();
+}
+
+
+
+SfxPoolItem* SwFmtCharFmt::Clone( SfxItemPool* ) const
+{
+ return new SwFmtCharFmt( *this );
+}
+
+
+
+// weiterleiten an das TextAttribut
+void SwFmtCharFmt::Modify( const SfxPoolItem* pOld, const SfxPoolItem* pNew )
+{
+ if( pTxtAttr )
+ pTxtAttr->ModifyNotification( pOld, pNew );
+}
+
+
+
+// weiterleiten an das TextAttribut
+sal_Bool SwFmtCharFmt::GetInfo( SfxPoolItem& rInfo ) const
+{
+ return pTxtAttr ? pTxtAttr->GetInfo( rInfo ) : sal_False;
+}
+bool SwFmtCharFmt::QueryValue( uno::Any& rVal, sal_uInt8 ) const
+{
+ String sCharFmtName;
+ if(GetCharFmt())
+ SwStyleNameMapper::FillProgName(GetCharFmt()->GetName(), sCharFmtName, nsSwGetPoolIdFromName::GET_POOLID_CHRFMT, sal_True );
+ rVal <<= OUString( sCharFmtName );
+ return true;
+}
+bool SwFmtCharFmt::PutValue( const uno::Any& , sal_uInt8 )
+{
+ OSL_FAIL("Zeichenvorlage kann mit PutValue nicht gesetzt werden!");
+ return false;
+}
+
+/*************************************************************************
+|*
+|* class SwFmtAutoFmt
+|*
+*************************************************************************/
+
+SwFmtAutoFmt::SwFmtAutoFmt( sal_uInt16 nInitWhich )
+ : SfxPoolItem( nInitWhich )
+{
+}
+
+SwFmtAutoFmt::SwFmtAutoFmt( const SwFmtAutoFmt& rAttr )
+ : SfxPoolItem( rAttr.Which() ), mpHandle( rAttr.mpHandle )
+{
+}
+
+SwFmtAutoFmt::~SwFmtAutoFmt()
+{
+}
+
+int SwFmtAutoFmt::operator==( const SfxPoolItem& rAttr ) const
+{
+ OSL_ENSURE( SfxPoolItem::operator==( rAttr ), "different attributes" );
+ return mpHandle == ((SwFmtAutoFmt&)rAttr).mpHandle;
+}
+
+SfxPoolItem* SwFmtAutoFmt::Clone( SfxItemPool* ) const
+{
+ return new SwFmtAutoFmt( *this );
+}
+
+bool SwFmtAutoFmt::QueryValue( uno::Any& rVal, sal_uInt8 ) const
+{
+ String sCharFmtName = StylePool::nameOf( mpHandle );
+ rVal <<= OUString( sCharFmtName );
+ return true;
+}
+
+bool SwFmtAutoFmt::PutValue( const uno::Any& , sal_uInt8 )
+{
+ //the format is not renameable via API
+ return false;
+}
+
+/*************************************************************************
+|*
+|* class SwFmtINetFmt
+|*
+*************************************************************************/
+
+SwFmtINetFmt::SwFmtINetFmt()
+ : SfxPoolItem( RES_TXTATR_INETFMT ),
+ pMacroTbl( 0 ),
+ pTxtAttr( 0 ),
+ nINetId( 0 ),
+ nVisitedId( 0 )
+{}
+
+SwFmtINetFmt::SwFmtINetFmt( const XubString& rURL, const XubString& rTarget )
+ : SfxPoolItem( RES_TXTATR_INETFMT ),
+ aURL( rURL ),
+ aTargetFrame( rTarget ),
+ pMacroTbl( 0 ),
+ pTxtAttr( 0 ),
+ nINetId( 0 ),
+ nVisitedId( 0 )
+{
+}
+
+SwFmtINetFmt::SwFmtINetFmt( const SwFmtINetFmt& rAttr )
+ : SfxPoolItem( RES_TXTATR_INETFMT ),
+ aURL( rAttr.GetValue() ),
+ aTargetFrame( rAttr.aTargetFrame ),
+ aINetFmt( rAttr.aINetFmt ),
+ aVisitedFmt( rAttr.aVisitedFmt ),
+ aName( rAttr.aName ),
+ pMacroTbl( 0 ),
+ pTxtAttr( 0 ),
+ nINetId( rAttr.nINetId ),
+ nVisitedId( rAttr.nVisitedId )
+{
+ if( rAttr.GetMacroTbl() )
+ pMacroTbl = new SvxMacroTableDtor( *rAttr.GetMacroTbl() );
+}
+
+SwFmtINetFmt::~SwFmtINetFmt()
+{
+ delete pMacroTbl;
+}
+
+
+
+int SwFmtINetFmt::operator==( const SfxPoolItem& rAttr ) const
+{
+ OSL_ENSURE( SfxPoolItem::operator==( rAttr ), "keine gleichen Attribute" );
+ sal_Bool bRet = SfxPoolItem::operator==( (SfxPoolItem&) rAttr )
+ && aURL == ((SwFmtINetFmt&)rAttr).aURL
+ && aName == ((SwFmtINetFmt&)rAttr).aName
+ && aTargetFrame == ((SwFmtINetFmt&)rAttr).aTargetFrame
+ && aINetFmt == ((SwFmtINetFmt&)rAttr).aINetFmt
+ && aVisitedFmt == ((SwFmtINetFmt&)rAttr).aVisitedFmt
+ && nINetId == ((SwFmtINetFmt&)rAttr).nINetId
+ && nVisitedId == ((SwFmtINetFmt&)rAttr).nVisitedId;
+
+ if( !bRet )
+ return sal_False;
+
+ const SvxMacroTableDtor* pOther = ((SwFmtINetFmt&)rAttr).pMacroTbl;
+ if( !pMacroTbl )
+ return ( !pOther || !pOther->Count() );
+ if( !pOther )
+ return 0 == pMacroTbl->Count();
+
+ const SvxMacroTableDtor& rOwn = *pMacroTbl;
+ const SvxMacroTableDtor& rOther = *pOther;
+
+ // Anzahl unterschiedlich => auf jeden Fall ungleich
+ if( rOwn.Count() != rOther.Count() )
+ return sal_False;
+
+ // einzeln vergleichen; wegen Performance ist die Reihenfolge wichtig
+ for( sal_uInt16 nNo = 0; nNo < rOwn.Count(); ++nNo )
+ {
+ const SvxMacro *pOwnMac = rOwn.GetObject(nNo);
+ const SvxMacro *pOtherMac = rOther.GetObject(nNo);
+ if ( rOwn.GetKey(pOwnMac) != rOther.GetKey(pOtherMac) ||
+ pOwnMac->GetLibName() != pOtherMac->GetLibName() ||
+ pOwnMac->GetMacName() != pOtherMac->GetMacName() )
+ return sal_False;
+ }
+ return sal_True;
+}
+
+
+
+SfxPoolItem* SwFmtINetFmt::Clone( SfxItemPool* ) const
+{
+ return new SwFmtINetFmt( *this );
+}
+
+
+
+void SwFmtINetFmt::SetMacroTbl( const SvxMacroTableDtor* pNewTbl )
+{
+ if( pNewTbl )
+ {
+ if( pMacroTbl )
+ *pMacroTbl = *pNewTbl;
+ else
+ pMacroTbl = new SvxMacroTableDtor( *pNewTbl );
+ }
+ else if( pMacroTbl )
+ delete pMacroTbl, pMacroTbl = 0;
+}
+
+
+
+void SwFmtINetFmt::SetMacro( sal_uInt16 nEvent, const SvxMacro& rMacro )
+{
+ if( !pMacroTbl )
+ pMacroTbl = new SvxMacroTableDtor;
+
+ SvxMacro *pOldMacro;
+ if( 0 != ( pOldMacro = pMacroTbl->Get( nEvent )) )
+ {
+ delete pOldMacro;
+ pMacroTbl->Replace( nEvent, new SvxMacro( rMacro ) );
+ }
+ else
+ pMacroTbl->Insert( nEvent, new SvxMacro( rMacro ) );
+}
+
+
+
+const SvxMacro* SwFmtINetFmt::GetMacro( sal_uInt16 nEvent ) const
+{
+ const SvxMacro* pRet = 0;
+ if( pMacroTbl && pMacroTbl->IsKeyValid( nEvent ) )
+ pRet = pMacroTbl->Get( nEvent );
+ return pRet;
+}
+
+
+
+bool SwFmtINetFmt::QueryValue( uno::Any& rVal, sal_uInt8 nMemberId ) const
+{
+ bool bRet = true;
+ XubString sVal;
+ nMemberId &= ~CONVERT_TWIPS;
+ switch(nMemberId)
+ {
+ case MID_URL_URL:
+ sVal = aURL;
+ break;
+ case MID_URL_TARGET:
+ sVal = aTargetFrame;
+ break;
+ case MID_URL_HYPERLINKNAME:
+ sVal = aName;
+ break;
+ case MID_URL_VISITED_FMT:
+ sVal = aVisitedFmt;
+ if( !sVal.Len() && nVisitedId != 0 )
+ SwStyleNameMapper::FillUIName( nVisitedId, sVal );
+ if( sVal.Len() )
+ SwStyleNameMapper::FillProgName( sVal, sVal, nsSwGetPoolIdFromName::GET_POOLID_CHRFMT, sal_True );
+ break;
+ case MID_URL_UNVISITED_FMT:
+ sVal = aINetFmt;
+ if( !sVal.Len() && nINetId != 0 )
+ SwStyleNameMapper::FillUIName( nINetId, sVal );
+ if( sVal.Len() )
+ SwStyleNameMapper::FillProgName( sVal, sVal, nsSwGetPoolIdFromName::GET_POOLID_CHRFMT, sal_True );
+ break;
+ case MID_URL_HYPERLINKEVENTS:
+ {
+ // create (and return) event descriptor
+ SwHyperlinkEventDescriptor* pEvents =
+ new SwHyperlinkEventDescriptor();
+ pEvents->copyMacrosFromINetFmt(*this);
+ uno::Reference<container::XNameReplace> xNameReplace(pEvents);
+
+ // all others return a string; so we just set rVal here and exit
+ rVal <<= xNameReplace;
+ return bRet;
+ }
+ default:
+ break;
+ }
+ rVal <<= OUString(sVal);
+ return bRet;
+}
+bool SwFmtINetFmt::PutValue( const uno::Any& rVal, sal_uInt8 nMemberId )
+{
+ bool bRet = true;
+ nMemberId &= ~CONVERT_TWIPS;
+
+ // all properties except HyperlinkEvents are of type string, hence
+ // we treat HyperlinkEvents specially
+ if (MID_URL_HYPERLINKEVENTS == nMemberId)
+ {
+ uno::Reference<container::XNameReplace> xReplace;
+ rVal >>= xReplace;
+ if (xReplace.is())
+ {
+ // Create hyperlink event descriptor. Then copy events
+ // from argument into descriptor. Then copy events from
+ // the descriptor into the format.
+ SwHyperlinkEventDescriptor* pEvents = new SwHyperlinkEventDescriptor();
+ uno::Reference< lang::XServiceInfo> xHold = pEvents;
+ pEvents->copyMacrosFromNameReplace(xReplace);
+ pEvents->copyMacrosIntoINetFmt(*this);
+ }
+ else
+ {
+ // wrong type!
+ bRet = false;
+ }
+ }
+ else
+ {
+ // all string properties:
+ if(rVal.getValueType() != ::getCppuType((rtl::OUString*)0))
+ return false;
+ XubString sVal = *(rtl::OUString*)rVal.getValue();
+ switch(nMemberId)
+ {
+ case MID_URL_URL:
+ aURL = sVal;
+ break;
+ case MID_URL_TARGET:
+ aTargetFrame = sVal;
+ break;
+ case MID_URL_HYPERLINKNAME:
+ aName = sVal;
+ break;
+ case MID_URL_VISITED_FMT:
+ {
+ String aString;
+ SwStyleNameMapper::FillUIName( sVal, aString, nsSwGetPoolIdFromName::GET_POOLID_CHRFMT, sal_True );
+ aVisitedFmt = OUString ( aString );
+ nVisitedId = SwStyleNameMapper::GetPoolIdFromUIName( aVisitedFmt,
+ nsSwGetPoolIdFromName::GET_POOLID_CHRFMT );
+ }
+ break;
+ case MID_URL_UNVISITED_FMT:
+ {
+ String aString;
+ SwStyleNameMapper::FillUIName( sVal, aString, nsSwGetPoolIdFromName::GET_POOLID_CHRFMT, sal_True );
+ aINetFmt = OUString ( aString );
+ nINetId = SwStyleNameMapper::GetPoolIdFromUIName( aINetFmt, nsSwGetPoolIdFromName::GET_POOLID_CHRFMT );
+ }
+ break;
+ default:
+ bRet = false;
+ }
+ }
+ return bRet;
+}
+
+
+/*************************************************************************
+|* class SwFmtRuby
+*************************************************************************/
+
+SwFmtRuby::SwFmtRuby( const String& rRubyTxt )
+ : SfxPoolItem( RES_TXTATR_CJK_RUBY ),
+ sRubyTxt( rRubyTxt ),
+ pTxtAttr( 0 ),
+ nCharFmtId( 0 ),
+ nPosition( 0 ),
+ nAdjustment( 0 )
+{
+}
+
+SwFmtRuby::SwFmtRuby( const SwFmtRuby& rAttr )
+ : SfxPoolItem( RES_TXTATR_CJK_RUBY ),
+ sRubyTxt( rAttr.sRubyTxt ),
+ sCharFmtName( rAttr.sCharFmtName ),
+ pTxtAttr( 0 ),
+ nCharFmtId( rAttr.nCharFmtId),
+ nPosition( rAttr.nPosition ),
+ nAdjustment( rAttr.nAdjustment )
+{
+}
+
+SwFmtRuby::~SwFmtRuby()
+{
+}
+
+SwFmtRuby& SwFmtRuby::operator=( const SwFmtRuby& rAttr )
+{
+ sRubyTxt = rAttr.sRubyTxt;
+ sCharFmtName = rAttr.sCharFmtName;
+ nCharFmtId = rAttr.nCharFmtId;
+ nPosition = rAttr.nPosition;
+ nAdjustment = rAttr.nAdjustment;
+ pTxtAttr = 0;
+ return *this;
+}
+
+int SwFmtRuby::operator==( const SfxPoolItem& rAttr ) const
+{
+ OSL_ENSURE( SfxPoolItem::operator==( rAttr ), "keine gleichen Attribute" );
+ return sRubyTxt == ((SwFmtRuby&)rAttr).sRubyTxt &&
+ sCharFmtName == ((SwFmtRuby&)rAttr).sCharFmtName &&
+ nCharFmtId == ((SwFmtRuby&)rAttr).nCharFmtId &&
+ nPosition == ((SwFmtRuby&)rAttr).nPosition &&
+ nAdjustment == ((SwFmtRuby&)rAttr).nAdjustment;
+}
+
+SfxPoolItem* SwFmtRuby::Clone( SfxItemPool* ) const
+{
+ return new SwFmtRuby( *this );
+}
+
+bool SwFmtRuby::QueryValue( uno::Any& rVal,
+ sal_uInt8 nMemberId ) const
+{
+ bool bRet = true;
+ nMemberId &= ~CONVERT_TWIPS;
+ switch( nMemberId )
+ {
+ case MID_RUBY_TEXT: rVal <<= (OUString)sRubyTxt; break;
+ case MID_RUBY_ADJUST: rVal <<= (sal_Int16)nAdjustment; break;
+ case MID_RUBY_CHARSTYLE:
+ {
+ String aString;
+ SwStyleNameMapper::FillProgName(sCharFmtName, aString, nsSwGetPoolIdFromName::GET_POOLID_CHRFMT, sal_True );
+ rVal <<= OUString ( aString );
+ }
+ break;
+ case MID_RUBY_ABOVE:
+ {
+ sal_Bool bAbove = !nPosition;
+ rVal.setValue(&bAbove, ::getBooleanCppuType());
+ }
+ break;
+ default:
+ bRet = false;
+ }
+ return bRet;
+}
+bool SwFmtRuby::PutValue( const uno::Any& rVal,
+ sal_uInt8 nMemberId )
+{
+ bool bRet = true;
+ nMemberId &= ~CONVERT_TWIPS;
+ switch( nMemberId )
+ {
+ case MID_RUBY_TEXT:
+ {
+ OUString sTmp;
+ bRet = rVal >>= sTmp;
+ sRubyTxt = sTmp;
+ }
+ break;
+ case MID_RUBY_ADJUST:
+ {
+ sal_Int16 nSet = 0;
+ rVal >>= nSet;
+ if(nSet >= 0 && nSet <= text::RubyAdjust_INDENT_BLOCK)
+ nAdjustment = nSet;
+ else
+ bRet = false;
+ }
+ break;
+ case MID_RUBY_ABOVE:
+ {
+ const uno::Type& rType = ::getBooleanCppuType();
+ if(rVal.hasValue() && rVal.getValueType() == rType)
+ {
+ sal_Bool bAbove = *(sal_Bool*)rVal.getValue();
+ nPosition = bAbove ? 0 : 1;
+ }
+ }
+ break;
+ case MID_RUBY_CHARSTYLE:
+ {
+ OUString sTmp;
+ bRet = rVal >>= sTmp;
+ if(bRet)
+ sCharFmtName = SwStyleNameMapper::GetUIName(sTmp, nsSwGetPoolIdFromName::GET_POOLID_CHRFMT );
+ }
+ break;
+ default:
+ bRet = false;
+ }
+ return bRet;
+}
+
+
+/*************************************************************************
+ class SwFmtMeta
+ ************************************************************************/
+
+SwFmtMeta * SwFmtMeta::CreatePoolDefault(const sal_uInt16 i_nWhich)
+{
+ return new SwFmtMeta(i_nWhich);
+}
+
+SwFmtMeta::SwFmtMeta(const sal_uInt16 i_nWhich)
+ : SfxPoolItem( i_nWhich )
+ , m_pMeta()
+ , m_pTxtAttr( 0 )
+{
+ OSL_ENSURE((RES_TXTATR_META == i_nWhich) || (RES_TXTATR_METAFIELD == i_nWhich),
+ "ERROR: SwFmtMeta: invalid which id!");
+}
+
+SwFmtMeta::SwFmtMeta( ::boost::shared_ptr< ::sw::Meta > const & i_pMeta,
+ const sal_uInt16 i_nWhich )
+ : SfxPoolItem( i_nWhich )
+ , m_pMeta( i_pMeta )
+ , m_pTxtAttr( 0 )
+{
+ OSL_ENSURE((RES_TXTATR_META == i_nWhich) || (RES_TXTATR_METAFIELD == i_nWhich),
+ "ERROR: SwFmtMeta: invalid which id!");
+ OSL_ENSURE(m_pMeta, "SwFmtMeta: no Meta ?");
+ // DO NOT call m_pMeta->SetFmtMeta(this) here; only from SetTxtAttr!
+}
+
+SwFmtMeta::~SwFmtMeta()
+{
+ if (m_pMeta && (m_pMeta->GetFmtMeta() == this))
+ {
+ NotifyChangeTxtNode(0);
+ m_pMeta->SetFmtMeta(0);
+ }
+}
+
+int SwFmtMeta::operator==( const SfxPoolItem & i_rOther ) const
+{
+ OSL_ENSURE( SfxPoolItem::operator==( i_rOther ), "i just copied this assert" );
+ return SfxPoolItem::operator==( i_rOther )
+ && (m_pMeta == static_cast<SwFmtMeta const &>( i_rOther ).m_pMeta);
+}
+
+SfxPoolItem * SwFmtMeta::Clone( SfxItemPool * /*pPool*/ ) const
+{
+ // if this is indeed a copy, then DoCopy must be called later!
+ return (m_pMeta) // #i105148# pool default may be cloned also!
+ ? new SwFmtMeta( m_pMeta, Which() ) : new SwFmtMeta( Which() );
+}
+
+void SwFmtMeta::SetTxtAttr(SwTxtMeta * const i_pTxtAttr)
+{
+ OSL_ENSURE(!(m_pTxtAttr && i_pTxtAttr),
+ "SwFmtMeta::SetTxtAttr: already has text attribute?");
+ OSL_ENSURE( m_pTxtAttr || i_pTxtAttr ,
+ "SwFmtMeta::SetTxtAttr: no attribute to remove?");
+ m_pTxtAttr = i_pTxtAttr;
+ OSL_ENSURE(m_pMeta, "inserted SwFmtMeta has no sw::Meta?");
+ // the sw::Meta must be able to find the current text attribute!
+ if (m_pMeta)
+ {
+ if (i_pTxtAttr)
+ {
+ m_pMeta->SetFmtMeta(this);
+ }
+ else if (m_pMeta->GetFmtMeta() == this)
+ { // text attribute gone => de-register from text node!
+ NotifyChangeTxtNode(0);
+ m_pMeta->SetFmtMeta(0);
+ }
+ }
+}
+
+void SwFmtMeta::NotifyChangeTxtNode(SwTxtNode *const pTxtNode)
+{
+ // N.B.: do not reset m_pTxtAttr here: see call in nodes.cxx,
+ // where the hint is not deleted!
+ OSL_ENSURE(m_pMeta, "SwFmtMeta::NotifyChangeTxtNode: no Meta?");
+ if (m_pMeta && (m_pMeta->GetFmtMeta() == this))
+ { // do not call Modify, that would call SwXMeta::Modify!
+ m_pMeta->NotifyChangeTxtNode(pTxtNode);
+ }
+}
+
+// this SwFmtMeta has been cloned and points at the same sw::Meta as the source
+// this method copies the sw::Meta
+void SwFmtMeta::DoCopy(::sw::MetaFieldManager & i_rTargetDocManager,
+ SwTxtNode & i_rTargetTxtNode)
+{
+ OSL_ENSURE(m_pMeta, "DoCopy called for SwFmtMeta with no sw::Meta?");
+ if (m_pMeta)
+ {
+ const ::boost::shared_ptr< ::sw::Meta> pOriginal( m_pMeta );
+ if (RES_TXTATR_META == Which())
+ {
+ m_pMeta.reset( new ::sw::Meta(this) );
+ }
+ else
+ {
+ ::sw::MetaField *const pMetaField(
+ static_cast< ::sw::MetaField* >(pOriginal.get()));
+ m_pMeta = i_rTargetDocManager.makeMetaField( this,
+ pMetaField->m_nNumberFormat, pMetaField->IsFixedLanguage() );
+ }
+ // Meta must have a text node before calling RegisterAsCopyOf
+ m_pMeta->NotifyChangeTxtNode(& i_rTargetTxtNode);
+ // this cannot be done in Clone: a Clone is not necessarily a copy!
+ m_pMeta->RegisterAsCopyOf(*pOriginal);
+ }
+}
+
+
+namespace sw {
+
+/*************************************************************************
+ class sw::Meta
+ ************************************************************************/
+
+Meta::Meta(SwFmtMeta * const i_pFmt)
+ : ::sfx2::Metadatable()
+ , SwModify()
+ , m_pFmt( i_pFmt )
+{
+}
+
+Meta::~Meta()
+{
+}
+
+SwTxtMeta * Meta::GetTxtAttr() const
+{
+ return (m_pFmt) ? m_pFmt->GetTxtAttr() : 0;
+}
+
+SwTxtNode * Meta::GetTxtNode() const
+{
+ return m_pTxtNode;
+}
+
+void Meta::NotifyChangeTxtNodeImpl()
+{
+ if (m_pTxtNode && (GetRegisteredIn() != m_pTxtNode))
+ {
+ m_pTxtNode->Add(this);
+ }
+ else if (!m_pTxtNode && GetRegisteredIn())
+ {
+ GetRegisteredInNonConst()->Remove(this);
+ }
+}
+
+void Meta::NotifyChangeTxtNode(SwTxtNode *const pTxtNode)
+{
+ m_pTxtNode = pTxtNode;
+ NotifyChangeTxtNodeImpl();
+ if (!pTxtNode) // text node gone? invalidate UNO object!
+ {
+ SwPtrMsgPoolItem aMsgHint( RES_REMOVE_UNO_OBJECT,
+ &static_cast<SwModify&>(*this) ); // cast to base class!
+ this->Modify(&aMsgHint, &aMsgHint);
+ }
+}
+
+// SwClient
+void Meta::Modify( const SfxPoolItem *pOld, const SfxPoolItem *pNew )
+{
+ NotifyClients(pOld, pNew);
+ if (pOld && (RES_REMOVE_UNO_OBJECT == pOld->Which()))
+ { // invalidate cached uno object
+ SetXMeta(uno::Reference<rdf::XMetadatable>(0));
+ }
+}
+
+// sfx2::Metadatable
+::sfx2::IXmlIdRegistry& Meta::GetRegistry()
+{
+ SwTxtNode * const pTxtNode( GetTxtNode() );
+ // GetRegistry may only be called on a meta that is actually in the
+ // document, which means it has a pointer to its text node
+ OSL_ENSURE(pTxtNode, "ERROR: GetRegistry: no text node?");
+ if (!pTxtNode)
+ throw uno::RuntimeException();
+ return pTxtNode->GetRegistry();
+}
+
+bool Meta::IsInClipboard() const
+{
+ const SwTxtNode * const pTxtNode( GetTxtNode() );
+// no text node: in UNDO OSL_ENSURE(pTxtNode, "IsInClipboard: no text node?");
+ return (pTxtNode) ? pTxtNode->IsInClipboard() : false;
+}
+
+bool Meta::IsInUndo() const
+{
+ const SwTxtNode * const pTxtNode( GetTxtNode() );
+// no text node: in UNDO OSL_ENSURE(pTxtNode, "IsInUndo: no text node?");
+ return (pTxtNode) ? pTxtNode->IsInUndo() : true;
+}
+
+bool Meta::IsInContent() const
+{
+ const SwTxtNode * const pTxtNode( GetTxtNode() );
+ OSL_ENSURE(pTxtNode, "IsInContent: no text node?");
+ return (pTxtNode) ? pTxtNode->IsInContent() : true;
+}
+
+::com::sun::star::uno::Reference< ::com::sun::star::rdf::XMetadatable >
+Meta::MakeUnoObject()
+{
+ return SwXMeta::CreateXMeta(*this);
+}
+
+/*************************************************************************
+ class sw::MetaField
+ ************************************************************************/
+
+MetaField::MetaField(SwFmtMeta * const i_pFmt,
+ const sal_uInt32 nNumberFormat, const bool bIsFixedLanguage)
+ : Meta(i_pFmt)
+ , m_nNumberFormat( nNumberFormat )
+ , m_bIsFixedLanguage( bIsFixedLanguage )
+{
+}
+
+void MetaField::GetPrefixAndSuffix(
+ ::rtl::OUString *const o_pPrefix, ::rtl::OUString *const o_pSuffix)
+{
+ try
+ {
+ const uno::Reference<rdf::XMetadatable> xMetaField( MakeUnoObject() );
+ OSL_ENSURE(dynamic_cast<SwXMetaField*>(xMetaField.get()),
+ "GetPrefixAndSuffix: no SwXMetaField?");
+ if (xMetaField.is())
+ {
+ SwTxtNode * const pTxtNode( GetTxtNode() );
+ SwDocShell const * const pShell(pTxtNode->GetDoc()->GetDocShell());
+ const uno::Reference<frame::XModel> xModel(
+ (pShell) ? pShell->GetModel() : 0, uno::UNO_SET_THROW);
+ getPrefixAndSuffix(xModel, xMetaField, o_pPrefix, o_pSuffix);
+ }
+ } catch (uno::Exception) {
+ OSL_FAIL("exception?");
+ }
+}
+
+sal_uInt32 MetaField::GetNumberFormat(::rtl::OUString const & rContent) const
+{
+ //TODO: this probably lacks treatment for some special cases
+ sal_uInt32 nNumberFormat( m_nNumberFormat );
+ SwTxtNode * const pTxtNode( GetTxtNode() );
+ if (pTxtNode)
+ {
+ SvNumberFormatter *const pNumberFormatter(
+ pTxtNode->GetDoc()->GetNumberFormatter() );
+ double number;
+ (void) pNumberFormatter->IsNumberFormat(
+ rContent, nNumberFormat, number );
+ }
+ return nNumberFormat;
+}
+
+void MetaField::SetNumberFormat(sal_uInt32 nNumberFormat)
+{
+ // effectively, the member is only a default:
+ // GetNumberFormat checks if the text actually conforms
+ m_nNumberFormat = nNumberFormat;
+}
+
+
+/*************************************************************************
+ class sw::MetaFieldManager
+ ************************************************************************/
+
+
+MetaFieldManager::MetaFieldManager()
+{
+}
+
+::boost::shared_ptr<MetaField>
+MetaFieldManager::makeMetaField(SwFmtMeta * const i_pFmt,
+ const sal_uInt32 nNumberFormat, const bool bIsFixedLanguage)
+{
+ const ::boost::shared_ptr<MetaField> pMetaField(
+ new MetaField(i_pFmt, nNumberFormat, bIsFixedLanguage) );
+ m_MetaFields.push_back(pMetaField);
+ return pMetaField;
+}
+
+struct IsInUndo
+{
+ bool operator()(::boost::weak_ptr<MetaField> const & pMetaField) {
+ return pMetaField.lock()->IsInUndo();
+ }
+};
+
+struct MakeUnoObject
+{
+ uno::Reference<text::XTextField>
+ operator()(::boost::weak_ptr<MetaField> const & pMetaField) {
+ return uno::Reference<text::XTextField>(
+ pMetaField.lock()->MakeUnoObject(), uno::UNO_QUERY);
+ }
+};
+
+::std::vector< uno::Reference<text::XTextField> >
+MetaFieldManager::getMetaFields()
+{
+ // erase deleted fields
+ const MetaFieldList_t::iterator iter(
+ ::std::remove_if(m_MetaFields.begin(), m_MetaFields.end(),
+ ::boost::bind(&::boost::weak_ptr<MetaField>::expired, _1)));
+ m_MetaFields.erase(iter, m_MetaFields.end());
+ // filter out fields in UNDO
+ MetaFieldList_t filtered(m_MetaFields.size());
+ const MetaFieldList_t::iterator iter2(
+ ::std::remove_copy_if(m_MetaFields.begin(), m_MetaFields.end(),
+ filtered.begin(), IsInUndo()));
+ filtered.erase(iter2, filtered.end());
+ // create uno objects
+ ::std::vector< uno::Reference<text::XTextField> > ret(filtered.size());
+ ::std::transform(filtered.begin(), filtered.end(), ret.begin(),
+ MakeUnoObject());
+ return ret;
+}
+
+} // namespace sw
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/txtnode/fntcache.cxx b/sw/source/core/txtnode/fntcache.cxx
new file mode 100644
index 000000000000..b866f3b4973e
--- /dev/null
+++ b/sw/source/core/txtnode/fntcache.cxx
@@ -0,0 +1,2651 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+
+#include <vcl/outdev.hxx>
+#include <vcl/print.hxx>
+#include <vcl/lineinfo.hxx>
+#include <vcl/metric.hxx>
+#include <vcl/window.hxx>
+#include <vcl/svapp.hxx>
+#include <com/sun/star/i18n/CharacterIteratorMode.hdl>
+#include <com/sun/star/i18n/WordType.hdl>
+#include <breakit.hxx>
+#include <viewsh.hxx> // Bildschirmabgleich
+#include <viewopt.hxx> // Bildschirmabgleich abschalten, ViewOption
+#include <fntcache.hxx>
+#include <IDocumentSettingAccess.hxx>
+#include <swfont.hxx> // CH_BLANK + CH_BULLET
+#include <wrong.hxx>
+#include "dbg_lay.hxx"
+#include <txtfrm.hxx> // SwTxtFrm
+#include <pagefrm.hxx>
+#include <pagedesc.hxx> // SwPageDesc
+#include <tgrditem.hxx>
+#include <scriptinfo.hxx>
+#include <editeng/brshitem.hxx>
+#include <tools/shl.hxx>
+#include <swmodule.hxx>
+#include <accessibilityoptions.hxx>
+#include <svtools/accessibilityoptions.hxx>
+#include <doc.hxx>
+#include <editeng/fhgtitem.hxx>
+#include <docsh.hxx>
+#include <poolfmt.hrc>
+
+using namespace ::com::sun::star;
+
+// globale Variablen, werden in FntCache.Hxx bekanntgegeben
+// Der FontCache wird in TxtInit.Cxx _TXTINIT erzeugt und in _TXTEXIT geloescht
+SwFntCache *pFntCache = NULL;
+// Letzter Font, der durch ChgFntCache eingestellt wurde.
+SwFntObj *pLastFont = NULL;
+// Die "MagicNumber", die den Fonts zur Identifizierung verpasst wird
+sal_uInt8* pMagicNo = NULL;
+
+Color *pWaveCol = 0;
+
+long SwFntObj::nPixWidth;
+MapMode* SwFntObj::pPixMap = NULL;
+OutputDevice* SwFntObj::pPixOut = NULL;
+
+extern sal_uInt16 UnMapDirection( sal_uInt16 nDir, const sal_Bool bVertFormat );
+sal_uInt16 GetDefaultFontHeight( SwDrawTextInfo &rInf )
+{
+ SwDocShell* pDocShell = rInf.GetShell()->GetDoc()->GetDocShell();
+ SfxStyleSheetBasePool* pBasePool = pDocShell->GetStyleSheetPool();
+
+ String aString(SW_RES(STR_POOLCOLL_STANDARD));
+
+ SfxStyleSheetBase* pStyle = pBasePool->Find( aString, (SfxStyleFamily)SFX_STYLE_FAMILY_PARA );
+ SfxItemSet& aTmpSet = pStyle->GetItemSet();
+ SvxFontHeightItem &aDefaultFontItem = (SvxFontHeightItem&)aTmpSet.Get(RES_CHRATR_CJK_FONTSIZE);
+ return (sal_uInt16)aDefaultFontItem.GetHeight();
+}
+
+
+
+/*************************************************************************
+|*
+|* SwFntCache::Flush()
+|*
+|*************************************************************************/
+
+void SwFntCache::Flush( )
+{
+ if ( pLastFont )
+ {
+ pLastFont->Unlock();
+ pLastFont = NULL;
+ }
+ SwCache::Flush( );
+}
+
+/*************************************************************************
+|*
+|* SwFntObj::SwFntObj(), ~SwFntObj()
+|*
+|*************************************************************************/
+
+SwFntObj::SwFntObj( const SwSubFont &rFont, const void *pOwn, ViewShell *pSh ) :
+ SwCacheObj( (void*)pOwn ),
+ aFont( rFont ),
+ pScrFont( NULL ),
+ pPrtFont( &aFont ),
+ pPrinter( NULL ),
+ nPropWidth( rFont.GetPropWidth() )
+{
+ nZoom = pSh ? pSh->GetViewOptions()->GetZoom() : USHRT_MAX;
+ nGuessedLeading = USHRT_MAX;
+ nExtLeading = USHRT_MAX;
+ nPrtAscent = USHRT_MAX;
+ nPrtHeight = USHRT_MAX;
+ bPaintBlank = ( UNDERLINE_NONE != aFont.GetUnderline()
+ || UNDERLINE_NONE != aFont.GetOverline()
+ || STRIKEOUT_NONE != aFont.GetStrikeout() )
+ && !aFont.IsWordLineMode();
+ aFont.SetLanguage(rFont.GetLanguage());
+}
+
+SwFntObj::~SwFntObj()
+{
+ if ( pScrFont != pPrtFont )
+ delete pScrFont;
+ if ( pPrtFont != &aFont )
+ delete pPrtFont;
+}
+
+void SwFntObj::CreatePrtFont( const OutputDevice& rPrt )
+{
+ if ( nPropWidth != 100 && pPrinter != &rPrt )
+ {
+ if( pScrFont != pPrtFont )
+ delete pScrFont;
+ if( pPrtFont != &aFont )
+ delete pPrtFont;
+
+ const Font aOldFnt( rPrt.GetFont() );
+ ((OutputDevice&)rPrt).SetFont( aFont );
+ const FontMetric aWinMet( rPrt.GetFontMetric() );
+ ((OutputDevice&)rPrt).SetFont( aOldFnt );
+ long nWidth = ( aWinMet.GetSize().Width() * nPropWidth ) / 100;
+
+ if( !nWidth )
+ ++nWidth;
+ pPrtFont = new Font( aFont );
+ pPrtFont->SetSize( Size( nWidth, aFont.GetSize().Height() ) );
+ pScrFont = NULL;
+ }
+}
+
+/*************************************************************************
+ *
+ * bool lcl_IsFontAdjustNecessary( rOutDev, rRefDev )
+ *
+ * returns whether we have to adjust the output font to resemble
+ * the formatting font
+ *
+ * _Not_ necessary if
+ *
+ * 1. RefDef == OutDev (text formatting, online layout...)
+ * 2. PDF export from online layout
+ * 3. Prospect/PagePreview pringing
+ *
+ *************************************************************************/
+
+bool lcl_IsFontAdjustNecessary( const OutputDevice& rOutDev,
+ const OutputDevice& rRefDev )
+{
+ return &rRefDev != &rOutDev &&
+ OUTDEV_WINDOW != rRefDev.GetOutDevType() &&
+ ( OUTDEV_PRINTER != rRefDev.GetOutDevType() ||
+ OUTDEV_PRINTER != rOutDev.GetOutDevType() );
+}
+
+struct CalcLinePosData
+{
+ SwDrawTextInfo& rInf;
+ Font& rFont;
+ xub_StrLen nCnt;
+ const sal_Bool bSwitchH2V;
+ const sal_Bool bSwitchL2R;
+ long nHalfSpace;
+ sal_Int32* pKernArray;
+ const sal_Bool bBidiPor;
+
+ CalcLinePosData( SwDrawTextInfo& _rInf, Font& _rFont,
+ xub_StrLen _nCnt, const sal_Bool _bSwitchH2V, const sal_Bool _bSwitchL2R,
+ long _nHalfSpace, sal_Int32* _pKernArray, const sal_Bool _bBidiPor) :
+ rInf( _rInf ),
+ rFont( _rFont ),
+ nCnt( _nCnt ),
+ bSwitchH2V( _bSwitchH2V ),
+ bSwitchL2R( _bSwitchL2R ),
+ nHalfSpace( _nHalfSpace ),
+ pKernArray( _pKernArray ),
+ bBidiPor( _bBidiPor )
+ {
+ }
+};
+
+/** Function: lcl_calcLinePos
+
+ Computes the start and end position of an underline. This function is called
+ from the DrawText-method (for underlining misspelled words or smarttag terms).
+*/
+
+void lcl_calcLinePos( const CalcLinePosData &rData,
+ Point &rStart, Point &rEnd, xub_StrLen nStart, xub_StrLen nWrLen )
+{
+ long nBlank = 0;
+ const xub_StrLen nEnd = nStart + nWrLen;
+ const long nTmpSpaceAdd = rData.rInf.GetSpace() / SPACING_PRECISION_FACTOR;
+
+ if ( nEnd < rData.nCnt
+ && CH_BLANK == rData.rInf.GetText().GetChar( rData.rInf.GetIdx() + nEnd ) )
+ {
+ if( nEnd + 1 == rData.nCnt )
+ nBlank -= nTmpSpaceAdd;
+ else
+ nBlank -= rData.nHalfSpace;
+ }
+
+ // determine start, end and length of wave line
+ sal_Int32 nKernStart = nStart ? rData.pKernArray[ sal_uInt16( nStart - 1 ) ] : 0;
+ sal_Int32 nKernEnd = rData.pKernArray[ sal_uInt16( nEnd - 1 ) ];
+
+ sal_uInt16 nDir = rData.bBidiPor ? 1800 :
+ UnMapDirection( rData.rFont.GetOrientation(), rData.bSwitchH2V );
+
+ switch ( nDir )
+ {
+ case 0 :
+ rStart.X() += nKernStart;
+ rEnd.X() = nBlank + rData.rInf.GetPos().X() + nKernEnd;
+ rEnd.Y() = rData.rInf.GetPos().Y();
+ break;
+ case 900 :
+ rStart.Y() -= nKernStart;
+ rEnd.X() = rData.rInf.GetPos().X();
+ rEnd.Y() = nBlank + rData.rInf.GetPos().Y() - nKernEnd;
+ break;
+ case 1800 :
+ rStart.X() -= nKernStart;
+ rEnd.X() = rData.rInf.GetPos().X() - nKernEnd - nBlank;
+ rEnd.Y() = rData.rInf.GetPos().Y();
+ break;
+ case 2700 :
+ rStart.Y() += nKernStart;
+ rEnd.X() = rData.rInf.GetPos().X();
+ rEnd.Y() = nBlank + rData.rInf.GetPos().Y() + nKernEnd;
+ break;
+ }
+
+ if ( rData.bSwitchL2R )
+ {
+ rData.rInf.GetFrm()->SwitchLTRtoRTL( rStart );
+ rData.rInf.GetFrm()->SwitchLTRtoRTL( rEnd );
+ }
+
+ if ( rData.bSwitchH2V )
+ {
+ rData.rInf.GetFrm()->SwitchHorizontalToVertical( rStart );
+ rData.rInf.GetFrm()->SwitchHorizontalToVertical( rEnd );
+ }
+}
+
+/*************************************************************************
+ *
+ * sal_uInt16 SwFntObj::GetFontAscent( const OutputDevice& rOut )
+ *
+ * Beschreibung: liefern den Ascent des Fonts auf dem
+ * gewuenschten Outputdevice zurueck, ggf. muss der Bildschirmfont erst
+ * erzeugt werden.
+ *************************************************************************/
+
+sal_uInt16 SwFntObj::GetFontAscent( const ViewShell *pSh, const OutputDevice& rOut )
+{
+ sal_uInt16 nRet = 0;
+ const OutputDevice& rRefDev = pSh ? pSh->GetRefDev() : rOut;
+
+ if ( pSh && lcl_IsFontAdjustNecessary( rOut, rRefDev ) )
+ {
+ CreateScrFont( *pSh, rOut );
+ OSL_ENSURE( USHRT_MAX != nScrAscent, "nScrAscent is going berzerk" );
+ nRet = nScrAscent;
+ }
+ else
+ {
+ if ( nPrtAscent == USHRT_MAX ) // DruckerAscent noch nicht bekannt?
+ {
+ CreatePrtFont( rOut );
+ const Font aOldFnt( rRefDev.GetFont() );
+ ((OutputDevice&)rRefDev).SetFont( *pPrtFont );
+ const FontMetric aOutMet( rRefDev.GetFontMetric() );
+ nPrtAscent = (sal_uInt16) aOutMet.GetAscent();
+ ( (OutputDevice&)rRefDev).SetFont( aOldFnt );
+ }
+
+ nRet = nPrtAscent;
+ }
+
+#if !defined(MACOSX) // #i89844# extleading is below the line for Mac
+ // TODO: move extleading below the line for all platforms too
+ nRet += GetFontLeading( pSh, rRefDev );
+#endif
+
+ OSL_ENSURE( USHRT_MAX != nRet, "GetFontAscent returned USHRT_MAX" );
+ return nRet;
+}
+
+/*************************************************************************
+ *
+ * sal_uInt16 SwFntObj::GetFontHeight( const OutputDevice* pOut )
+ *
+ * Beschreibung: liefern die H?he des Fonts auf dem
+ * gewuenschten Outputdevice zurueck, ggf. muss der Bildschirmfont erst
+ * erzeugt werden.
+ *************************************************************************/
+
+sal_uInt16 SwFntObj::GetFontHeight( const ViewShell* pSh, const OutputDevice& rOut )
+{
+ sal_uInt16 nRet = 0;
+ const OutputDevice& rRefDev = pSh ? pSh->GetRefDev() : rOut;
+
+ if ( pSh && lcl_IsFontAdjustNecessary( rOut, rRefDev ) )
+ {
+ CreateScrFont( *pSh, rOut );
+ OSL_ENSURE( USHRT_MAX != nScrHeight, "nScrHeight is going berzerk" );
+ nRet = nScrHeight + GetFontLeading( pSh, rRefDev );
+ }
+ else
+ {
+ if ( nPrtHeight == USHRT_MAX ) // PrinterHeight noch nicht bekannt?
+ {
+ CreatePrtFont( rOut );
+ const Font aOldFnt( rRefDev.GetFont() );
+ ((OutputDevice&)rRefDev).SetFont( *pPrtFont );
+ nPrtHeight = static_cast<sal_uInt16>(rRefDev.GetTextHeight());
+
+#if OSL_DEBUG_LEVEL > 1
+ // Check if vcl did not change the meading of GetTextHeight
+ const FontMetric aOutMet( rRefDev.GetFontMetric() );
+ long nTmpPrtHeight = (sal_uInt16)aOutMet.GetAscent() + aOutMet.GetDescent();
+ (void) nTmpPrtHeight;
+ // #i106098#: do not compare with == here due to rounding error
+ OSL_ENSURE( abs(nTmpPrtHeight - nPrtHeight) < 3,
+ "GetTextHeight != Ascent + Descent" );
+#endif
+
+ ((OutputDevice&)rRefDev).SetFont( aOldFnt );
+ }
+
+ nRet = nPrtHeight + GetFontLeading( pSh, rRefDev );
+ }
+
+ OSL_ENSURE( USHRT_MAX != nRet, "GetFontHeight returned USHRT_MAX" );
+ return nRet;
+}
+
+sal_uInt16 SwFntObj::GetFontLeading( const ViewShell *pSh, const OutputDevice& rOut )
+{
+ sal_uInt16 nRet = 0;
+
+ if ( pSh )
+ {
+ if ( USHRT_MAX == nGuessedLeading || USHRT_MAX == nExtLeading )
+ {
+ const Font aOldFnt( rOut.GetFont() );
+ ((OutputDevice&)rOut).SetFont( *pPrtFont );
+ const FontMetric aMet( rOut.GetFontMetric() );
+ ((OutputDevice&)rOut).SetFont( aOldFnt );
+ bSymbol = RTL_TEXTENCODING_SYMBOL == aMet.GetCharSet();
+ GuessLeading( *pSh, aMet );
+ nExtLeading = static_cast<sal_uInt16>(aMet.GetExtLeading());
+ }
+
+ const IDocumentSettingAccess& rIDSA = *pSh->getIDocumentSettingAccess();
+ const bool bBrowse = ( pSh->GetWin() &&
+ pSh->GetViewOptions()->getBrowseMode() &&
+ !pSh->GetViewOptions()->IsPrtFormat() );
+
+ if ( !bBrowse && rIDSA.get(IDocumentSettingAccess::ADD_EXT_LEADING) )
+ nRet = nExtLeading;
+ else
+ nRet = nGuessedLeading;
+ }
+
+ OSL_ENSURE( USHRT_MAX != nRet, "GetFontLeading returned USHRT_MAX" );
+ return nRet;
+}
+
+
+/*************************************************************************
+ *
+ * SwFntObj::CreateScrFont( const ViewShell& rSh, const OutputDevice& rOut )
+ *
+ * pOut is the output device, not the reference device
+ *
+ *************************************************************************/
+
+void SwFntObj::CreateScrFont( const ViewShell& rSh, const OutputDevice& rOut )
+{
+ if ( pScrFont )
+ return;
+
+ // any changes to the output device are reset at the end of the function
+ OutputDevice* pOut = (OutputDevice*)&rOut;
+
+ // Save old font
+ Font aOldOutFont( pOut->GetFont() );
+
+ nScrHeight = USHRT_MAX;
+
+ // Condition for output font / refdev font adjustment
+ OutputDevice* pPrt = &rSh.GetRefDev();
+
+ if( !rSh.GetWin() ||
+ !rSh.GetViewOptions()->getBrowseMode() ||
+ rSh.GetViewOptions()->IsPrtFormat() )
+ {
+ // After CreatePrtFont pPrtFont is the font which is actually used
+ // by the reference device
+ CreatePrtFont( *pPrt );
+ pPrinter = pPrt;
+
+ // save old reference device font
+ Font aOldPrtFnt( pPrt->GetFont() );
+
+ // set the font used at the reference device at the reference device
+ // and the output device
+ pPrt->SetFont( *pPrtFont );
+ pOut->SetFont( *pPrtFont );
+
+ // This should be the default for pScrFont.
+ pScrFont = pPrtFont;
+
+ FontMetric aMet = pPrt->GetFontMetric( );
+ //Don't loose "faked" properties of the logical font that don't truly
+ //exist in the physical font metrics which vcl which fake up for us
+ aMet.SetWeight(pScrFont->GetWeight());
+ aMet.SetItalic(pScrFont->GetItalic());
+
+ bSymbol = RTL_TEXTENCODING_SYMBOL == aMet.GetCharSet();
+
+ if ( USHRT_MAX == nGuessedLeading )
+ GuessLeading( rSh, aMet );
+
+ if ( USHRT_MAX == nExtLeading )
+ nExtLeading = static_cast<sal_uInt16>(aMet.GetExtLeading());
+
+ // reset the original reference device font
+ pPrt->SetFont( aOldPrtFnt );
+ }
+ else
+ {
+ bSymbol = RTL_TEXTENCODING_SYMBOL == aFont.GetCharSet();
+ if ( nGuessedLeading == USHRT_MAX )
+ nGuessedLeading = 0;
+
+ // no external leading in browse mode
+ if ( nExtLeading == USHRT_MAX )
+ nExtLeading = 0;
+
+ pScrFont = pPrtFont;
+ }
+
+ // Zoomfaktor ueberpruefen, z.B. wg. PrtOle2 beim Speichern
+ {
+ // Sollte der Zoomfaktor des OutputDevices nicht mit dem der View-
+ // Options uebereinstimmen, so darf dieser Font nicht gecacht
+ // werden, deshalb wird der Zoomfaktor auf einen "ungueltigen" Wert
+ // gesetzt.
+ long nTmp;
+ if( pOut->GetMapMode().GetScaleX().IsValid() &&
+ pOut->GetMapMode().GetScaleY().IsValid() &&
+ pOut->GetMapMode().GetScaleX() == pOut->GetMapMode().GetScaleY() )
+ {
+ nTmp = ( 100 * pOut->GetMapMode().GetScaleX().GetNumerator() ) /
+ pOut->GetMapMode().GetScaleX().GetDenominator();
+ }
+ else
+ nTmp = 0;
+ if( nTmp != nZoom )
+ nZoom = USHRT_MAX - 1;
+ }
+
+ nScrAscent = (sal_uInt16)pOut->GetFontMetric().GetAscent();
+ if ( USHRT_MAX == nScrHeight )
+ nScrHeight = (sal_uInt16)pOut->GetTextHeight();
+
+ // reset original output device font
+ pOut->SetFont( aOldOutFont );
+}
+
+
+void SwFntObj::GuessLeading( const ViewShell&
+#if defined(WNT) || defined(PM2)
+ rSh
+#endif
+ , const FontMetric& rMet )
+{
+ // If leading >= 5, this seems to be enough leading.
+ // Nothing has to be done.
+ if ( rMet.GetIntLeading() >= 5 )
+ {
+ nGuessedLeading = 0;
+ return;
+ }
+
+#if defined(WNT) || defined(PM2)
+ OutputDevice *pWin = rSh.GetWin() ?
+ rSh.GetWin() :
+ GetpApp()->GetDefaultDevice();
+ if ( pWin )
+ {
+ MapMode aTmpMap( MAP_TWIP );
+ MapMode aOldMap = pWin->GetMapMode( );
+ pWin->SetMapMode( aTmpMap );
+ const Font aOldFnt( pWin->GetFont() );
+ pWin->SetFont( *pPrtFont );
+ const FontMetric aWinMet( pWin->GetFontMetric() );
+ const sal_uInt16 nWinHeight = sal_uInt16( aWinMet.GetSize().Height() );
+ if( pPrtFont->GetName().Search( aWinMet.GetName() ) < USHRT_MAX )
+ {
+ // Wenn das Leading auf dem Window auch 0 ist, dann
+ // muss es auch so bleiben (vgl. StarMath!).
+ long nTmpLeading = (long)aWinMet.GetIntLeading();
+ // einen Versuch haben wir noch wg. 31003:
+ if( nTmpLeading <= 0 )
+ {
+ pWin->SetFont( rMet );
+ nTmpLeading = (long)pWin->GetFontMetric().GetIntLeading();
+ if( nTmpLeading < 0 )
+ nGuessedLeading = 0;
+ else
+ nGuessedLeading = sal_uInt16(nTmpLeading);
+ }
+ else
+ {
+ nGuessedLeading = sal_uInt16(nTmpLeading);
+ // Manta-Hack #50153#:
+ // Wer beim Leading luegt, luegt moeglicherweise auch beim
+ // Ascent/Descent, deshalb wird hier ggf. der Font ein wenig
+ // tiefergelegt, ohne dabei seine Hoehe zu aendern.
+ long nDiff = Min( rMet.GetDescent() - aWinMet.GetDescent(),
+ aWinMet.GetAscent() - rMet.GetAscent() - nTmpLeading );
+ if( nDiff > 0 )
+ {
+ OSL_ENSURE( nPrtAscent < USHRT_MAX, "GuessLeading: PrtAscent-Fault" );
+ if ( nPrtAscent < USHRT_MAX )
+ nPrtAscent = nPrtAscent + (sal_uInt16)(( 2 * nDiff ) / 5);
+ }
+ }
+ }
+ else
+ {
+ // Wenn alle Stricke reissen, nehmen wir 15% der
+ // Hoehe, ein von CL empirisch ermittelter Wert.
+ nGuessedLeading = (nWinHeight * 15) / 100;
+ }
+ pWin->SetFont( aOldFnt );
+ pWin->SetMapMode( aOldMap );
+ }
+ else
+#endif
+ nGuessedLeading = 0;
+}
+
+/*************************************************************************
+ *
+ * void SwFntObj::SetDeviceFont( const OutputDevice *pOut ),
+ *
+ * Beschreibung: stellt den Font am gewuenschten OutputDevice ein,
+ * am Bildschirm muss eventuell erst den Abgleich durchgefuehrt werden.
+ *
+ *************************************************************************/
+
+void SwFntObj::SetDevFont( const ViewShell *pSh, OutputDevice& rOut )
+{
+ const OutputDevice& rRefDev = pSh ? pSh->GetRefDev() : rOut;
+
+ if ( pSh && lcl_IsFontAdjustNecessary( rOut, rRefDev ) )
+ {
+ CreateScrFont( *pSh, rOut );
+ if( !GetScrFont()->IsSameInstance( rOut.GetFont() ) )
+ rOut.SetFont( *pScrFont );
+ if( pPrinter && ( !pPrtFont->IsSameInstance( pPrinter->GetFont() ) ) )
+ pPrinter->SetFont( *pPrtFont );
+ }
+ else
+ {
+ CreatePrtFont( rOut );
+ if( !pPrtFont->IsSameInstance( rOut.GetFont() ) )
+ rOut.SetFont( *pPrtFont );
+ }
+
+ // Here, we actually do not need the leading values, but by calling
+ // GetFontLeading() we assure that the values are calculated for later use.
+ GetFontLeading( pSh, rRefDev );
+}
+
+#define WRONG_SHOW_MIN 5
+#define WRONG_SHOW_SMALL 11
+#define WRONG_SHOW_MEDIUM 15
+
+/*************************************************************************
+ *
+ * void SwFntObj::DrawText( ... )
+ *
+ * Beschreibung: Textausgabe
+ * auf dem Bildschirm => DrawTextArray
+ * auf dem Drucker, !Kerning => DrawText
+ * auf dem Drucker + Kerning => DrawStretchText
+ *
+ *************************************************************************/
+
+sal_uInt8 lcl_WhichPunctuation( xub_Unicode cChar )
+{
+ if ( ( cChar < 0x3001 || cChar > 0x3002 ) &&
+ ( cChar < 0x3008 || cChar > 0x3011 ) &&
+ ( cChar < 0x3014 || cChar > 0x301F ) &&
+ 0xFF62 != cChar && 0xFF63 != cChar )
+ // no punctuation
+ return SwScriptInfo::NONE;
+ else if ( 0x3001 == cChar || 0x3002 == cChar ||
+ 0x3009 == cChar || 0x300B == cChar ||
+ 0x300D == cChar || 0x300F == cChar ||
+ 0x3011 == cChar || 0x3015 == cChar ||
+ 0x3017 == cChar || 0x3019 == cChar ||
+ 0x301B == cChar || 0x301E == cChar ||
+ 0x301F == cChar || 0xFF63 == cChar )
+ // right punctuation
+ return SwScriptInfo::SPECIAL_RIGHT;
+
+ return SwScriptInfo::SPECIAL_LEFT;
+}
+
+static sal_Bool lcl_IsMonoSpaceFont( const OutputDevice& rOut )
+{
+ const String aStr1( xub_Unicode( 0x3008 ) );
+ const String aStr2( xub_Unicode( 0x307C ) );
+ const long nWidth1 = rOut.GetTextWidth( aStr1 );
+ const long nWidth2 = rOut.GetTextWidth( aStr2 );
+ return nWidth1 == nWidth2;
+}
+
+// ER 09.07.95 20:34
+// mit -Ox Optimierung stuerzt's unter win95 ab
+// JP 12.07.95: unter WNT auch (i386); Alpha ??
+// global optimization off
+#ifdef _MSC_VER
+#pragma optimize("g",off)
+#endif
+
+/* This helper structure (SwForbidden) contains the already marked parts of the string
+ to avoid double lines (e.g grammar + spell check error) */
+
+typedef std::vector< std::pair< xub_StrLen, xub_StrLen > > SwForbidden;
+
+static void lcl_DrawLineForWrongListData(
+ SwForbidden &rForbidden,
+ const SwDrawTextInfo &rInf,
+ const SwWrongList *pWList,
+ const CalcLinePosData &rCalcLinePosData,
+ const Size &rPrtFontSize )
+{
+ if (!pWList)
+ return;
+
+ xub_StrLen nStart = rInf.GetIdx();
+ xub_StrLen nWrLen = rInf.GetLen();
+
+ // check if respective data is available in the current text range
+ if (pWList->Check( nStart, nWrLen ))
+ {
+ // get line color to use...
+ Color aLineColor;
+ if (pWList == rInf.GetWrong()) // ... for spell checking
+ aLineColor = SwViewOption::GetSpellColor();
+ else if (pWList == rInf.GetGrammarCheck()) // ... for grammar checking
+ // currently there is no specific color for grammar check errors available in the configuration
+ aLineColor = Color( COL_LIGHTBLUE );
+ else if (pWList == rInf.GetSmartTags()) // ... for smart tags
+ aLineColor = SwViewOption::GetSmarttagColor();
+
+ long nHght = rInf.GetOut().LogicToPixel( rPrtFontSize ).Height();
+
+ // Draw wavy lines for spell and grammar errors only if font is large enough.
+ // Lines for smart tags will always be drawn.
+ if (pWList == rInf.GetSmartTags() || WRONG_SHOW_MIN < nHght)
+ {
+ SwForbidden::iterator pIter = rForbidden.begin();
+ if (rInf.GetOut().GetConnectMetaFile())
+ rInf.GetOut().Push();
+
+ const Color aCol( rInf.GetOut().GetLineColor() );
+ const sal_Bool bColSave = aCol != aLineColor;
+ if (bColSave)
+ rInf.GetOut().SetLineColor( aLineColor );
+
+ // iterate over all ranges stored in the respective SwWrongList
+ do
+ {
+ nStart = nStart - rInf.GetIdx();
+
+ const xub_StrLen nEnd = nStart + nWrLen;
+ xub_StrLen nNext = nStart;
+ while( nNext < nEnd )
+ {
+ while( pIter != rForbidden.end() && pIter->second <= nNext )
+ ++pIter;
+ xub_StrLen nNextStart = nNext;
+ xub_StrLen nNextEnd = nEnd;
+ if( pIter == rForbidden.end() || nNextEnd <= pIter->first )
+ {
+ // No overlapping mark up found
+ std::pair< xub_StrLen, xub_StrLen > aNew;
+ aNew.first = nNextStart;
+ aNew.second = nNextEnd;
+ rForbidden.insert( pIter, aNew );
+ pIter = rForbidden.begin();
+ nNext = nEnd;
+ }
+ else
+ {
+ nNext = pIter->second;
+ if( nNextStart < pIter->first )
+ {
+ nNextEnd = pIter->first;
+ pIter->first = nNextStart;
+ }
+ else
+ continue;
+ }
+ // determine line pos
+ Point aStart( rInf.GetPos() );
+ Point aEnd;
+ lcl_calcLinePos( rCalcLinePosData, aStart, aEnd, nNextStart, nNextEnd - nNextStart );
+
+ // draw line for smart tags?
+ if (pWList == rInf.GetSmartTags())
+ {
+ aStart.Y() +=30;
+ aEnd.Y() +=30;
+
+ LineInfo aLineInfo( LINE_DASH );
+ aLineInfo.SetDistance( 40 );
+ aLineInfo.SetDashLen( 1 );
+ aLineInfo.SetDashCount(1);
+
+ rInf.GetOut().DrawLine( aStart, aEnd, aLineInfo );
+ }
+ else // draw wavy lines for spell or grammar errors
+ {
+ // get wavy line type to use
+ sal_uInt16 nWave =
+ WRONG_SHOW_MEDIUM < nHght ? WAVE_NORMAL :
+ ( WRONG_SHOW_SMALL < nHght ? WAVE_SMALL : WAVE_FLAT );
+
+ rInf.GetOut().DrawWaveLine( aStart, aEnd, nWave );
+ }
+ }
+
+ nStart = nEnd + rInf.GetIdx();
+ nWrLen = rInf.GetIdx() + rInf.GetLen() - nStart;
+ }
+ while (nWrLen && pWList->Check( nStart, nWrLen ));
+
+ if (bColSave)
+ rInf.GetOut().SetLineColor( aCol );
+
+ if (rInf.GetOut().GetConnectMetaFile())
+ rInf.GetOut().Pop();
+ }
+ }
+}
+
+
+void SwFntObj::DrawText( SwDrawTextInfo &rInf )
+{
+ OSL_ENSURE( rInf.GetShell(), "SwFntObj::DrawText without shell" );
+
+ OutputDevice& rRefDev = rInf.GetShell()->GetRefDev();
+ OutputDevice* pWin = rInf.GetShell()->GetWin();
+
+ // true if pOut is the printer and the printer has been used for formatting
+ const sal_Bool bPrt = OUTDEV_PRINTER == rInf.GetOut().GetOutDevType() &&
+ OUTDEV_PRINTER == rRefDev.GetOutDevType();
+ const sal_Bool bBrowse = ( pWin &&
+ rInf.GetShell()->GetViewOptions()->getBrowseMode() &&
+ !rInf.GetShell()->GetViewOptions()->IsPrtFormat() &&
+ !rInf.GetBullet() &&
+ ( rInf.GetSpace() || !rInf.GetKern() ) &&
+ !rInf.GetWrong() &&
+ !rInf.GetGrammarCheck() &&
+ !rInf.GetSmartTags() &&
+ !rInf.GetGreyWave() );
+
+ // bDirectPrint indicates that we can enter the branch which calls
+ // the DrawText functions instead of calling the DrawTextArray functions
+ const sal_Bool bDirectPrint = bPrt || bBrowse;
+
+ // Condition for output font / refdev font adjustment
+ const sal_Bool bUseScrFont =
+ lcl_IsFontAdjustNecessary( rInf.GetOut(), rRefDev );
+
+ Font* pTmpFont = bUseScrFont ? pScrFont : pPrtFont;
+
+ //
+ // bDirectPrint and bUseScrFont should have these values:
+ //
+ // Outdev / RefDef | Printer | VirtPrinter | Window
+ // ----------------------------------------------------
+ // Printer | 1 - 0 | 0 - 1 | -
+ // ----------------------------------------------------
+ // VirtPrinter/PDF | 0 - 1 | 0 - 1 | -
+ // ----------------------------------------------------
+ // Window/VirtWindow| 0 - 1 | 0 - 1 | 1 - 0
+ //
+ // Exception: During painting of a Writer OLE object, we do not have
+ // a window. Therefore bUseSrcFont is always 0 in this case.
+ //
+
+#if OSL_DEBUG_LEVEL > 1
+
+ const sal_Bool bNoAdjust = bPrt ||
+ ( pWin &&
+ rInf.GetShell()->GetViewOptions()->getBrowseMode() &&
+ !rInf.GetShell()->GetViewOptions()->IsPrtFormat() );
+
+ if ( OUTDEV_PRINTER == rInf.GetOut().GetOutDevType() )
+ {
+ // Printer output
+ if ( OUTDEV_PRINTER == rRefDev.GetOutDevType() )
+ {
+ OSL_ENSURE( bNoAdjust == 1 && bUseScrFont == 0, "Outdev Check failed" );
+ }
+ else if ( OUTDEV_VIRDEV == rRefDev.GetOutDevType() )
+ {
+ OSL_ENSURE( bNoAdjust == 0 && bUseScrFont == 1, "Outdev Check failed" );
+ }
+ else
+ {
+ OSL_FAIL( "Outdev Check failed" );
+ }
+ }
+ else if ( OUTDEV_VIRDEV == rInf.GetOut().GetOutDevType() && ! pWin )
+ {
+ // PDF export
+ if ( OUTDEV_PRINTER == rRefDev.GetOutDevType() )
+ {
+ OSL_ENSURE( bNoAdjust == 0 && bUseScrFont == 1, "Outdev Check failed" );
+ }
+ else if ( OUTDEV_VIRDEV == rRefDev.GetOutDevType() )
+ {
+ OSL_ENSURE( bNoAdjust == 0 && bUseScrFont == 1, "Outdev Check failed" );
+ }
+ else
+ {
+ OSL_FAIL( "Outdev Check failed" );
+ }
+ }
+ else if ( OUTDEV_WINDOW == rInf.GetOut().GetOutDevType() ||
+ ( OUTDEV_VIRDEV == rInf.GetOut().GetOutDevType() && pWin ) )
+ {
+ // Window or virtual window
+ if ( OUTDEV_PRINTER == rRefDev.GetOutDevType() )
+ {
+ OSL_ENSURE( bNoAdjust == 0 && bUseScrFont == 1, "Outdev Check failed" );
+ }
+ else if ( OUTDEV_VIRDEV == rRefDev.GetOutDevType() )
+ {
+ OSL_ENSURE( bNoAdjust == 0 && bUseScrFont == 1, "Outdev Check failed" );
+ }
+ else if ( OUTDEV_WINDOW == rRefDev.GetOutDevType() )
+ {
+ OSL_ENSURE( bNoAdjust == 1 && bUseScrFont == 0, "Outdev Check failed" );
+ }
+ else
+ {
+ OSL_FAIL( "Outdev Check failed" );
+ }
+ }
+ else
+ {
+ OSL_FAIL( "Outdev Check failed" );
+ }
+
+#endif
+
+ // robust: better use the printer font instead of using no font at all
+ OSL_ENSURE( pTmpFont, "No screen or printer font?" );
+ if ( ! pTmpFont )
+ pTmpFont = pPrtFont;
+
+ // HACK: UNDERLINE_WAVE darf nicht mehr missbraucht werden, daher
+ // wird die graue Wellenlinie des ExtendedAttributSets zunaechst
+ // in der Fontfarbe erscheinen.
+
+ const sal_Bool bSwitchH2V = rInf.GetFrm() && rInf.GetFrm()->IsVertical();
+ const sal_Bool bSwitchL2R = rInf.GetFrm() && rInf.GetFrm()->IsRightToLeft() &&
+ ! rInf.IsIgnoreFrmRTL();
+ const sal_uLong nMode = rInf.GetOut().GetLayoutMode();
+ const sal_Bool bBidiPor = ( bSwitchL2R !=
+ ( 0 != ( TEXT_LAYOUT_BIDI_RTL & nMode ) ) );
+
+ // be sure to have the correct layout mode at the printer
+ if ( pPrinter )
+ {
+ pPrinter->SetLayoutMode( rInf.GetOut().GetLayoutMode() );
+ pPrinter->SetDigitLanguage( rInf.GetOut().GetDigitLanguage() );
+ }
+
+ Point aPos( rInf.GetPos() );
+ if( !bPrt )
+ {
+ if( rInf.GetpOut() != pPixOut || rInf.GetOut().GetMapMode() != *pPixMap )
+ {
+ *pPixMap = rInf.GetOut().GetMapMode();
+ pPixOut = rInf.GetpOut();
+ Size aTmp( 1, 1 );
+ nPixWidth = rInf.GetOut().PixelToLogic( aTmp ).Width();
+ }
+
+ aPos.X() += rInf.GetFrm()->IsRightToLeft() ? 0 : nPixWidth;
+ }
+
+ Color aOldColor( pTmpFont->GetColor() );
+ sal_Bool bChgColor = rInf.ApplyAutoColor( pTmpFont );
+ if( !pTmpFont->IsSameInstance( rInf.GetOut().GetFont() ) )
+ rInf.GetOut().SetFont( *pTmpFont );
+ if ( bChgColor )
+ pTmpFont->SetColor( aOldColor );
+
+ if ( STRING_LEN == rInf.GetLen() )
+ rInf.SetLen( rInf.GetText().Len() );
+
+
+ //
+ // ASIAN LINE AND CHARACTER GRID MODE START: snap to characters
+ //
+
+ if ( rInf.GetFrm() && rInf.SnapToGrid() && rInf.GetFont() &&
+ SW_CJK == rInf.GetFont()->GetActual() )
+ {
+ GETGRID( rInf.GetFrm()->FindPageFrm() )
+ if ( pGrid && GRID_LINES_CHARS == pGrid->GetGridType() && pGrid->IsSnapToChars())
+ {
+ //for textgrid refactor
+ //const sal_uInt16 nGridWidth = pGrid->GetBaseHeight();
+ const SwDoc* pDoc = rInf.GetShell()->GetDoc();
+ const sal_uInt16 nGridWidth = GETGRIDWIDTH(pGrid, pDoc);
+ sal_Int32* pKernArray = new sal_Int32[rInf.GetLen()];
+
+ if ( pPrinter )
+ pPrinter->GetTextArray( rInf.GetText(), pKernArray,
+ rInf.GetIdx(), rInf.GetLen() );
+ else
+ rInf.GetOut().GetTextArray( rInf.GetText(), pKernArray,
+ rInf.GetIdx(), rInf.GetLen() );
+
+ long nWidthPerChar = pKernArray[ rInf.GetLen() - 1 ] / rInf.GetLen();
+
+ const sal_uLong i = nWidthPerChar ?
+ ( nWidthPerChar - 1 ) / nGridWidth + 1:
+ 1;
+
+ nWidthPerChar = i * nGridWidth;
+
+ // position of first character, we take the printer position
+ long nCharWidth = pKernArray[ 0 ];
+ sal_uLong nHalfWidth = nWidthPerChar / 2;
+
+ long nNextFix;
+
+ // punctuation characters are not centered
+ xub_Unicode cChar = rInf.GetText().GetChar( rInf.GetIdx() );
+ sal_uInt8 nType = lcl_WhichPunctuation( cChar );
+ switch ( nType )
+ {
+ case SwScriptInfo::NONE :
+ aPos.X() += ( nWidthPerChar - nCharWidth ) / 2;
+ nNextFix = nCharWidth / 2;
+ break;
+ case SwScriptInfo::SPECIAL_RIGHT :
+ nNextFix = nHalfWidth;
+ break;
+ default:
+ aPos.X() += nWidthPerChar - nCharWidth;
+ nNextFix = nCharWidth - nHalfWidth;
+ }
+
+ // calculate offsets
+ for ( xub_StrLen j = 1; j < rInf.GetLen(); ++j )
+ {
+ long nScr = pKernArray[ j ] - pKernArray[ j - 1 ];
+ nNextFix += nWidthPerChar;
+
+ // punctuation characters are not centered
+ cChar = rInf.GetText().GetChar( rInf.GetIdx() + j );
+ nType = lcl_WhichPunctuation( cChar );
+ switch ( nType )
+ {
+ case SwScriptInfo::NONE :
+ pKernArray[ j - 1 ] = nNextFix - ( nScr / 2 );
+ break;
+ case SwScriptInfo::SPECIAL_RIGHT :
+ pKernArray[ j - 1 ] = nNextFix - nHalfWidth;
+ break;
+ default:
+ pKernArray[ j - 1 ] = nNextFix + nHalfWidth - nScr;
+ }
+ }
+
+ // the layout engine requires the total width of the output
+ pKernArray[ rInf.GetLen() - 1 ] = rInf.GetWidth() -
+ aPos.X() + rInf.GetPos().X() ;
+
+ if ( bSwitchH2V )
+ rInf.GetFrm()->SwitchHorizontalToVertical( aPos );
+
+ rInf.GetOut().DrawTextArray( aPos, rInf.GetText(),
+ pKernArray, rInf.GetIdx(), rInf.GetLen() );
+
+ delete[] pKernArray;
+ return;
+ }
+ }
+
+ // For text grid refactor
+ // ASIAN LINE AND CHARACTER GRID MODE START: not snap to characters
+ //
+ if ( rInf.GetFrm() && rInf.SnapToGrid() && rInf.GetFont() &&
+ SW_CJK == rInf.GetFont()->GetActual() )
+ {
+ GETGRID( rInf.GetFrm()->FindPageFrm() )
+
+ if ( pGrid && GRID_LINES_CHARS == pGrid->GetGridType() && !pGrid->IsSnapToChars() )
+ {
+ const sal_uInt16 nDefaultFontHeight = GetDefaultFontHeight( rInf );
+
+ const SwDoc* pDoc = rInf.GetShell()->GetDoc();
+ long nGridWidthAdd = GETGRIDWIDTH(pGrid, pDoc);
+ if( SW_LATIN == rInf.GetFont()->GetActual() )
+ nGridWidthAdd = ( nGridWidthAdd - nDefaultFontHeight ) / 2;
+ else
+ nGridWidthAdd = nGridWidthAdd - nDefaultFontHeight;
+
+ sal_Int32* pKernArray = new sal_Int32[rInf.GetLen()];
+
+ if ( pPrinter )
+ pPrinter->GetTextArray( rInf.GetText(), pKernArray,
+ rInf.GetIdx(), rInf.GetLen() );
+ else
+ rInf.GetOut().GetTextArray( rInf.GetText(), pKernArray,
+ rInf.GetIdx(), rInf.GetLen() );
+ if ( bSwitchH2V )
+ rInf.GetFrm()->SwitchHorizontalToVertical( aPos );
+ if ( rInf.GetSpace() || rInf.GetKanaComp())
+ {
+ long nSpaceAdd = rInf.GetSpace() / SPACING_PRECISION_FACTOR;
+ sal_Bool bSpecialJust = sal_False;
+ if ( rInf.GetFont() && rInf.GetLen() )
+ {
+ const SwScriptInfo* pSI = rInf.GetScriptInfo();
+ const sal_uInt8 nActual = rInf.GetFont()->GetActual();
+ ///Kana Compression
+ if( SW_CJK == nActual && rInf.GetKanaComp() &&
+ pSI && pSI->CountCompChg() &&
+ lcl_IsMonoSpaceFont( *(rInf.GetpOut()) ) )
+ {
+ pSI->Compress( pKernArray,rInf.GetIdx(), rInf.GetLen(),
+ rInf.GetKanaComp(), (sal_uInt16)aFont.GetSize().Height(),&aPos );
+ bSpecialJust = sal_True;
+ }
+ ///Asian Justification
+ if ( ( SW_CJK == nActual || SW_LATIN == nActual ) && nSpaceAdd )
+ {
+ LanguageType aLang = rInf.GetFont()->GetLanguage( SW_CJK );
+ if ( LANGUAGE_KOREAN != aLang && LANGUAGE_KOREAN_JOHAB != aLang)
+ {
+ long nSpaceSum = nSpaceAdd;
+ for ( sal_uInt16 nI = 0; nI < rInf.GetLen(); ++nI )
+ {
+ pKernArray[ nI ] += nSpaceSum;
+ nSpaceSum += nSpaceAdd;
+ }
+ bSpecialJust = sal_True;
+ nSpaceAdd = 0;
+ }
+ }
+ long nGridAddSum = nGridWidthAdd;
+ for(xub_StrLen i = 0; i < rInf.GetLen(); i++,nGridAddSum += nGridWidthAdd )
+ {
+ pKernArray[i] += nGridAddSum;
+ }
+ long nKernSum = rInf.GetKern();
+ if ( bSpecialJust || rInf.GetKern() )
+ {
+ for( xub_StrLen i = 0; i < rInf.GetLen(); i++, nKernSum += rInf.GetKern() )
+ {
+ if ( CH_BLANK == rInf.GetText().GetChar(rInf.GetIdx()+i) )
+ nKernSum += nSpaceAdd;
+ pKernArray[i] += nKernSum;
+ }
+ ///With through/uderstr. Grouped style requires a blank at the end
+ ///of a text edition special measures:
+ if( bPaintBlank && rInf.GetLen() && (CH_BLANK ==
+ rInf.GetText().GetChar( rInf.GetIdx() + rInf.GetLen() - 1) ) )
+ {
+ ///If it concerns a singular, underlined space acts,
+ ///we must spend two:
+ if( 1 == rInf.GetLen() )
+ {
+ pKernArray[0] = rInf.GetWidth() + nSpaceAdd;
+ rInf.GetOut().DrawTextArray( aPos, rInf.GetText(),
+ pKernArray, rInf.GetIdx(), 1 );
+ }
+ else
+ {
+ pKernArray[ rInf.GetLen() - 2] += nSpaceAdd;
+ rInf.GetOut().DrawTextArray( aPos, rInf.GetText(),
+ pKernArray, rInf.GetIdx(), rInf.GetLen() );
+ }
+ }
+ else
+ {
+ rInf.GetOut().DrawTextArray( aPos, rInf.GetText(),
+ pKernArray, rInf.GetIdx(), rInf.GetLen() );
+ }
+ }
+ else
+ {
+ Point aTmpPos( aPos );
+ xub_StrLen i;
+ xub_StrLen j = 0;
+ long nSpaceSum = 0;
+ for( i = 0; i < rInf.GetLen(); i++ )
+ {
+ if( CH_BLANK == rInf.GetText().GetChar( rInf.GetIdx() + i) )
+ {
+ nSpaceSum += nSpaceAdd;
+ if( j < i)
+ rInf.GetOut().DrawText( aTmpPos, rInf.GetText(),
+ rInf.GetIdx() + j, i - j );
+ j = i + 1;
+ pKernArray[i] = pKernArray[i] + nSpaceSum;
+ aTmpPos.X() = aPos.X() + pKernArray[ i ] + nKernSum;
+ }
+ }
+ if( j < i )
+ rInf.GetOut().DrawText( aTmpPos, rInf.GetText(),
+ rInf.GetIdx() +j , i - j );
+ }
+ }
+ }
+ else
+ {
+ //long nKernAdd = rInf.GetKern();
+ long nKernAdd = 0;
+ long nGridAddSum = nGridWidthAdd + nKernAdd;
+ for(xub_StrLen i = 0; i < rInf.GetLen(); i++,nGridAddSum += nGridWidthAdd + nKernAdd )
+ {
+ pKernArray[i] += nGridAddSum;
+ }
+ rInf.GetOut().DrawTextArray( aPos, rInf.GetText(),
+ pKernArray, rInf.GetIdx(), rInf.GetLen() );
+ }
+ delete[] pKernArray;
+ return;
+ }
+ }
+
+ //
+ // DIRECT PAINTING WITHOUT SCREEN ADJUSTMENT
+ //
+
+ if ( bDirectPrint )
+ {
+ const Fraction aTmp( 1, 1 );
+ sal_Bool bStretch = rInf.GetWidth() && ( rInf.GetLen() > 1 ) && bPrt
+ && ( aTmp != rInf.GetOut().GetMapMode().GetScaleX() );
+
+ if ( bSwitchL2R )
+ rInf.GetFrm()->SwitchLTRtoRTL( aPos );
+
+ if ( bSwitchH2V )
+ rInf.GetFrm()->SwitchHorizontalToVertical( aPos );
+
+ // In the good old days we used to have a simple DrawText if the
+ // output device is the printer. Now we need a DrawTextArray if
+ // 1. KanaCompression is enabled
+ // 2. Justified alignment
+ // Simple kerning is handled by DrawStretchText
+ if( rInf.GetSpace() || rInf.GetKanaComp() )
+ {
+ sal_Int32 *pKernArray = new sal_Int32[ rInf.GetLen() ];
+ rInf.GetOut().GetTextArray( rInf.GetText(), pKernArray,
+ rInf.GetIdx(), rInf.GetLen() );
+
+ if( bStretch )
+ {
+ xub_StrLen nZwi = rInf.GetLen() - 1;
+ long nDiff = rInf.GetWidth() - pKernArray[ nZwi ]
+ - rInf.GetLen() * rInf.GetKern();
+ long nRest = nDiff % nZwi;
+ long nAdd;
+ if( nRest < 0 )
+ {
+ nAdd = -1;
+ nRest += nZwi;
+ }
+ else
+ {
+ nAdd = +1;
+ nRest = nZwi - nRest;
+ }
+ nDiff /= nZwi;
+ long nSum = nDiff;
+ for( xub_StrLen i = 0; i < nZwi; )
+ {
+ pKernArray[ i ] += nSum;
+ if( ++i == nRest )
+ nDiff += nAdd;
+ nSum += nDiff;
+ }
+ }
+
+ //
+ // Modify Array for special justifications
+ //
+ long nSpaceAdd = rInf.GetSpace() / SPACING_PRECISION_FACTOR;
+ sal_Bool bSpecialJust = sal_False;
+
+ if ( rInf.GetFont() && rInf.GetLen() )
+ {
+ const SwScriptInfo* pSI = rInf.GetScriptInfo();
+ const sal_uInt8 nActual = rInf.GetFont()->GetActual();
+
+ // Kana Compression
+ if ( SW_CJK == nActual && rInf.GetKanaComp() &&
+ pSI && pSI->CountCompChg() &&
+ lcl_IsMonoSpaceFont( rInf.GetOut() ) )
+ {
+ pSI->Compress( pKernArray, rInf.GetIdx(), rInf.GetLen(),
+ rInf.GetKanaComp(),
+ (sal_uInt16)aFont.GetSize().Height(), &aPos );
+ bSpecialJust = sal_True;
+ }
+
+ // Asian Justification
+ if ( SW_CJK == nActual && nSpaceAdd )
+ {
+ LanguageType aLang = rInf.GetFont()->GetLanguage( SW_CJK );
+
+ if ( LANGUAGE_KOREAN != aLang && LANGUAGE_KOREAN_JOHAB != aLang )
+ {
+ long nSpaceSum = nSpaceAdd;
+ for ( sal_uInt16 nI = 0; nI < rInf.GetLen(); ++nI )
+ {
+ pKernArray[ nI ] += nSpaceSum;
+ nSpaceSum += nSpaceAdd;
+ }
+
+ bSpecialJust = sal_True;
+ nSpaceAdd = 0;
+ }
+ }
+
+ // Kashida Justification
+ if ( SW_CTL == nActual && nSpaceAdd )
+ {
+ if ( SwScriptInfo::IsArabicText( rInf.GetText(), rInf.GetIdx(), rInf.GetLen() ) )
+ {
+ if ( pSI && pSI->CountKashida() &&
+ pSI->KashidaJustify( pKernArray, 0, rInf.GetIdx(),
+ rInf.GetLen(), nSpaceAdd ) != STRING_LEN )
+ {
+ bSpecialJust = sal_True;
+ nSpaceAdd = 0;
+ }
+ }
+ }
+
+ // Thai Justification
+ if ( SW_CTL == nActual && nSpaceAdd )
+ {
+ LanguageType aLang = rInf.GetFont()->GetLanguage( SW_CTL );
+
+ if ( LANGUAGE_THAI == aLang )
+ {
+ // Use rInf.GetSpace() because it has more precision than
+ // nSpaceAdd:
+ SwScriptInfo::ThaiJustify( rInf.GetText(), pKernArray, 0,
+ rInf.GetIdx(), rInf.GetLen(),
+ rInf.GetNumberOfBlanks(),
+ rInf.GetSpace() );
+
+ // adding space to blanks is already done
+ bSpecialJust = sal_True;
+ nSpaceAdd = 0;
+ }
+ }
+ }
+
+ long nKernSum = rInf.GetKern();
+
+ if ( bStretch || bPaintBlank || rInf.GetKern() || bSpecialJust )
+ {
+ for( xub_StrLen i = 0; i < rInf.GetLen(); i++,
+ nKernSum += rInf.GetKern() )
+ {
+ if ( CH_BLANK == rInf.GetText().GetChar(rInf.GetIdx()+i) )
+ nKernSum += nSpaceAdd;
+ pKernArray[i] += nKernSum;
+ }
+
+ // Bei durch/unterstr. Blocksatz erfordert ein Blank am Ende
+ // einer Textausgabe besondere Massnahmen:
+ if( bPaintBlank && rInf.GetLen() && ( CH_BLANK ==
+ rInf.GetText().GetChar( rInf.GetIdx()+rInf.GetLen()-1 ) ) )
+ {
+ // Wenn es sich um ein singulaeres, unterstrichenes Space
+ // handelt, muessen wir zwei ausgeben:
+ if( 1 == rInf.GetLen() )
+ {
+ pKernArray[0] = rInf.GetWidth() + nSpaceAdd;
+
+ rInf.GetOut().DrawTextArray( aPos, rInf.GetText(),
+ pKernArray, rInf.GetIdx(), 1 );
+ }
+ else
+ {
+ pKernArray[ rInf.GetLen() - 2 ] += nSpaceAdd;
+ rInf.GetOut().DrawTextArray( aPos, rInf.GetText(),
+ pKernArray, rInf.GetIdx(), rInf.GetLen() );
+ }
+ }
+ else
+ rInf.GetOut().DrawTextArray( aPos, rInf.GetText(),
+ pKernArray, rInf.GetIdx(), rInf.GetLen() );
+ }
+ else
+ {
+ Point aTmpPos( aPos );
+ xub_StrLen j = 0;
+ xub_StrLen i;
+ for( i = 0; i < rInf.GetLen(); i++ )
+ {
+ if( CH_BLANK == rInf.GetText().GetChar( rInf.GetIdx()+i ) )
+ {
+ nKernSum += nSpaceAdd;
+ if( j < i )
+ rInf.GetOut().DrawText( aTmpPos, rInf.GetText(),
+ rInf.GetIdx() + j, i - j );
+ j = i + 1;
+ SwTwips nAdd = pKernArray[ i ] + nKernSum;
+ if ( ( TEXT_LAYOUT_BIDI_STRONG | TEXT_LAYOUT_BIDI_RTL ) == nMode )
+ nAdd *= -1;
+ aTmpPos.X() = aPos.X() + nAdd;
+ }
+ }
+ if( j < i )
+ rInf.GetOut().DrawText( aTmpPos, rInf.GetText(),
+ rInf.GetIdx() + j, i - j );
+ }
+ delete[] pKernArray;
+ }
+ else if( bStretch )
+ {
+ long nTmpWidth = rInf.GetWidth();
+ if( rInf.GetKern() && rInf.GetLen() && nTmpWidth > rInf.GetKern() )
+ nTmpWidth -= rInf.GetKern();
+ rInf.GetOut().DrawStretchText( aPos, nTmpWidth,
+ rInf.GetText(), rInf.GetIdx(), rInf.GetLen() );
+ }
+ else if( rInf.GetKern() )
+ {
+ const long nTmpWidth = GetTextSize( rInf ).Width();
+
+ const Color aSaveColor( pTmpFont->GetColor() );
+ const sal_Bool bColorChanged = rInf.ApplyAutoColor( pTmpFont );
+
+ if( bColorChanged )
+ {
+ if( !pTmpFont->IsSameInstance( rInf.GetOut().GetFont() ) )
+ rInf.GetOut().SetFont( *pTmpFont );
+ pTmpFont->SetColor( aSaveColor );
+ }
+
+ rInf.GetOut().DrawStretchText( aPos, (sal_uInt16)nTmpWidth,
+ rInf.GetText(), rInf.GetIdx(), rInf.GetLen() );
+ }
+ else
+ rInf.GetOut().DrawText( aPos, rInf.GetText(),
+ rInf.GetIdx(), rInf.GetLen() );
+ }
+
+ //
+ // PAINTING WITH FORMATTING DEVICE/SCREEN ADJUSTMENT
+ //
+
+ else
+ {
+ const String* pStr = &rInf.GetText();
+ String aStr( aEmptyStr );
+ sal_Bool bBullet = rInf.GetBullet();
+ if( bSymbol )
+ bBullet = sal_False;
+ sal_Int32 *pKernArray = new sal_Int32[ rInf.GetLen() ];
+ CreateScrFont( *rInf.GetShell(), rInf.GetOut() );
+ long nScrPos;
+
+ // get screen array
+ sal_Int32* pScrArray = new sal_Int32[ rInf.GetLen() ];
+ rInf.GetOut().GetTextArray( rInf.GetText(), pScrArray,
+ rInf.GetIdx(), rInf.GetLen() );
+
+ // OLE: no printer available
+ // OSL_ENSURE( pPrinter, "DrawText needs pPrinter" )
+ if ( pPrinter )
+ {
+ // pTmpFont has already been set as current font for rInf.GetOut()
+ if ( pPrinter != rInf.GetpOut() || pTmpFont != pPrtFont )
+ {
+ if( !pPrtFont->IsSameInstance( pPrinter->GetFont() ) )
+ pPrinter->SetFont( *pPrtFont );
+ }
+ pPrinter->GetTextArray( rInf.GetText(), pKernArray, rInf.GetIdx(),
+ rInf.GetLen() );
+ }
+ else
+ {
+ rInf.GetOut().GetTextArray( rInf.GetText(), pKernArray,
+ rInf.GetIdx(), rInf.GetLen() );
+ }
+
+ //
+ // Modify Printer and ScreenArrays for special justifications
+ //
+ long nSpaceAdd = rInf.GetSpace() / SPACING_PRECISION_FACTOR;
+ bool bNoHalfSpace = false;
+
+ if ( rInf.GetFont() && rInf.GetLen() )
+ {
+ const sal_uInt8 nActual = rInf.GetFont()->GetActual();
+ const SwScriptInfo* pSI = rInf.GetScriptInfo();
+
+ // Kana Compression
+ if ( SW_CJK == nActual && rInf.GetKanaComp() &&
+ pSI && pSI->CountCompChg() &&
+ lcl_IsMonoSpaceFont( rInf.GetOut() ) )
+ {
+ Point aTmpPos( aPos );
+ pSI->Compress( pScrArray, rInf.GetIdx(), rInf.GetLen(),
+ rInf.GetKanaComp(),
+ (sal_uInt16)aFont.GetSize().Height(), &aTmpPos );
+ pSI->Compress( pKernArray, rInf.GetIdx(), rInf.GetLen(),
+ rInf.GetKanaComp(),
+ (sal_uInt16)aFont.GetSize().Height(), &aPos );
+ }
+
+ // Asian Justification
+ if ( SW_CJK == nActual && nSpaceAdd )
+ {
+ LanguageType aLang = rInf.GetFont()->GetLanguage( SW_CJK );
+
+ if ( LANGUAGE_KOREAN != aLang && LANGUAGE_KOREAN_JOHAB != aLang )
+ {
+ long nSpaceSum = nSpaceAdd;
+ for ( sal_uInt16 nI = 0; nI < rInf.GetLen(); ++nI )
+ {
+ pKernArray[ nI ] += nSpaceSum;
+ pScrArray[ nI ] += nSpaceSum;
+ nSpaceSum += nSpaceAdd;
+ }
+
+ nSpaceAdd = 0;
+ }
+ }
+
+ // Kashida Justification
+ if ( SW_CTL == nActual && nSpaceAdd )
+ {
+ if ( SwScriptInfo::IsArabicText( rInf.GetText(), rInf.GetIdx(), rInf.GetLen() ) )
+ {
+ if ( pSI && pSI->CountKashida() &&
+ pSI->KashidaJustify( pKernArray, pScrArray, rInf.GetIdx(),
+ rInf.GetLen(), nSpaceAdd ) != STRING_LEN )
+ nSpaceAdd = 0;
+ else
+ bNoHalfSpace = true;
+ }
+ }
+
+ // Thai Justification
+ if ( SW_CTL == nActual && nSpaceAdd )
+ {
+ LanguageType aLang = rInf.GetFont()->GetLanguage( SW_CTL );
+
+ if ( LANGUAGE_THAI == aLang )
+ {
+ SwScriptInfo::ThaiJustify( rInf.GetText(), pKernArray,
+ pScrArray, rInf.GetIdx(),
+ rInf.GetLen(),
+ rInf.GetNumberOfBlanks(),
+ rInf.GetSpace() );
+
+ // adding space to blanks is already done
+ nSpaceAdd = 0;
+ }
+ }
+ }
+
+ nScrPos = pScrArray[ 0 ];
+
+ if( bBullet )
+ {
+ // !!! HACK !!!
+ // The Arabic layout engine requires some context of the string
+ // which should be painted.
+ xub_StrLen nCopyStart = rInf.GetIdx();
+ if ( nCopyStart )
+ --nCopyStart;
+
+ xub_StrLen nCopyLen = rInf.GetLen();
+ if ( nCopyStart + nCopyLen < rInf.GetText().Len() )
+ ++nCopyLen;
+
+ aStr = rInf.GetText().Copy( nCopyStart, nCopyLen );
+ pStr = &aStr;
+
+ for( xub_StrLen i = 0; i < aStr.Len(); ++i )
+ if( CH_BLANK == aStr.GetChar( i ) )
+ aStr.SetChar( i, CH_BULLET );
+ }
+
+ xub_StrLen nCnt = rInf.GetText().Len();
+ if ( nCnt < rInf.GetIdx() )
+ nCnt = 0;
+ else
+ nCnt = nCnt - rInf.GetIdx();
+ nCnt = Min( nCnt, rInf.GetLen() );
+ long nKernSum = rInf.GetKern();
+ xub_Unicode cChPrev = rInf.GetText().GetChar( rInf.GetIdx() );
+
+ // Wenn es sich um ein singulaeres, unterstrichenes Space
+ // im Blocksatz handelt, muessen wir zwei ausgeben:
+ if ( ( nCnt == 1 ) && rInf.GetSpace() && ( cChPrev == CH_BLANK ) )
+ {
+ pKernArray[0] = rInf.GetWidth() +
+ rInf.GetKern() +
+ ( rInf.GetSpace() / SPACING_PRECISION_FACTOR );
+
+ if ( bSwitchL2R )
+ rInf.GetFrm()->SwitchLTRtoRTL( aPos );
+
+ if ( bSwitchH2V )
+ rInf.GetFrm()->SwitchHorizontalToVertical( aPos );
+
+ rInf.GetOut().DrawTextArray( aPos, rInf.GetText(),
+ pKernArray, rInf.GetIdx(), 1 );
+ if( bBullet )
+ rInf.GetOut().DrawTextArray( aPos, *pStr, pKernArray,
+ rInf.GetIdx() ? 1 : 0, 1 );
+ }
+ else
+ {
+ xub_Unicode nCh;
+
+ // Bei Pairkerning waechst der Printereinfluss auf die Positionierung
+ sal_uInt16 nMul = 3;
+
+ if ( pPrtFont->GetKerning() )
+ nMul = 1;
+
+ const sal_uInt16 nDiv = nMul+1;
+
+ // In nSpaceSum wird der durch Blocksatz auf die Spaces verteilte
+ // Zwischenraum aufsummiert.
+ // Die Spaces selbst werden im Normalfall in der Mitte des
+ // Zwischenraums positioniert, deshalb die nSpace/2-Mimik.
+ // Bei wortweiser Unterstreichung muessen sie am Anfang des
+ // Zwischenraums stehen, damit dieser nicht unterstrichen wird.
+ // Ein Space am Anfang oder am Ende des Textes muss allerdings
+ // vor bzw. hinter den kompletten Zwischenraum gesetzt werden,
+ // sonst wuerde das Durch-/Unterstreichen Luecken aufweisen.
+ long nSpaceSum = 0;
+ // in word line mode and for Arabic, we disable the half space trick:
+ const long nHalfSpace = pPrtFont->IsWordLineMode() || bNoHalfSpace ? 0 : nSpaceAdd / 2;
+ const long nOtherHalf = nSpaceAdd - nHalfSpace;
+ if ( nSpaceAdd && ( cChPrev == CH_BLANK ) )
+ nSpaceSum = nHalfSpace;
+ for ( xub_StrLen i=1; i<nCnt; ++i,nKernSum += rInf.GetKern() )
+ {
+ nCh = rInf.GetText().GetChar( rInf.GetIdx() + i );
+
+ OSL_ENSURE( pScrArray, "Where is the screen array?" );
+ long nScr;
+ nScr = pScrArray[ i ] - pScrArray[ i - 1 ];
+
+ // Wenn vor uns ein (Ex-)SPACE ist, positionieren wir uns optimal,
+ // d.h. unseren rechten Rand auf die 100% Druckerposition,
+ // sind wir sogar selbst ein Ex-SPACE, so positionieren wir uns
+ // linksbuendig zur Druckerposition.
+ if ( nCh == CH_BLANK )
+ {
+ nScrPos = pKernArray[i-1] + nScr;
+
+ if ( cChPrev == CH_BLANK )
+ nSpaceSum += nOtherHalf;
+ if ( i + 1 == nCnt )
+ nSpaceSum += nSpaceAdd;
+ else
+ nSpaceSum += nHalfSpace;
+ }
+ else
+ {
+ if ( cChPrev == CH_BLANK )
+ {
+ nScrPos = pKernArray[i-1] + nScr;
+
+ // kein Pixel geht verloren:
+ nSpaceSum += nOtherHalf;
+ }
+ else if ( cChPrev == '-' )
+ nScrPos = pKernArray[i-1] + nScr;
+ else
+ {
+ nScrPos += nScr;
+ nScrPos = ( nMul * nScrPos + pKernArray[i] ) / nDiv;
+ }
+ }
+ cChPrev = nCh;
+ pKernArray[i-1] = nScrPos - nScr + nKernSum + nSpaceSum;
+ // In word line mode and for Arabic, we disabled the half space trick. If a portion
+ // ends with a blank, the full nSpaceAdd value has been added to the character in
+ // front of the blank. This leads to painting artifacts, therefore we remove the
+ // nSpaceAdd value again:
+ if ( (bNoHalfSpace || pPrtFont->IsWordLineMode()) && i+1 == nCnt && nCh == CH_BLANK )
+ pKernArray[i-1] = pKernArray[i-1] - nSpaceAdd;
+ }
+
+ // the layout engine requires the total width of the output
+ pKernArray[ rInf.GetLen() - 1 ] += nKernSum + nSpaceSum;
+
+ if( rInf.GetGreyWave() )
+ {
+ if( rInf.GetLen() )
+ {
+ long nHght = rInf.GetOut().LogicToPixel(
+ pPrtFont->GetSize() ).Height();
+ if( WRONG_SHOW_MIN < nHght )
+ {
+ if ( rInf.GetOut().GetConnectMetaFile() )
+ rInf.GetOut().Push();
+
+ sal_uInt16 nWave =
+ WRONG_SHOW_MEDIUM < nHght ? WAVE_NORMAL :
+ ( WRONG_SHOW_SMALL < nHght ? WAVE_SMALL :
+ WAVE_FLAT );
+ Color aCol( rInf.GetOut().GetLineColor() );
+ sal_Bool bColSave = aCol != *pWaveCol;
+ if ( bColSave )
+ rInf.GetOut().SetLineColor( *pWaveCol );
+
+ Point aEnd;
+ long nKernVal = pKernArray[ sal_uInt16( rInf.GetLen() - 1 ) ];
+
+ sal_uInt16 nDir = bBidiPor ?
+ 1800 :
+ UnMapDirection(
+ GetFont()->GetOrientation(),
+ bSwitchH2V );
+
+ switch ( nDir )
+ {
+ case 0 :
+ aEnd.X() = rInf.GetPos().X() + nKernVal;
+ aEnd.Y() = rInf.GetPos().Y();
+ break;
+ case 900 :
+ aEnd.X() = rInf.GetPos().X();
+ aEnd.Y() = rInf.GetPos().Y() - nKernVal;
+ break;
+ case 1800 :
+ aEnd.X() = rInf.GetPos().X() - nKernVal;
+ aEnd.Y() = rInf.GetPos().Y();
+ break;
+ case 2700 :
+ aEnd.X() = rInf.GetPos().X();
+ aEnd.Y() = rInf.GetPos().Y() + nKernVal;
+ break;
+ }
+
+ Point aCurrPos( rInf.GetPos() );
+
+ if ( bSwitchL2R )
+ {
+ rInf.GetFrm()->SwitchLTRtoRTL( aCurrPos );
+ rInf.GetFrm()->SwitchLTRtoRTL( aEnd );
+ }
+
+ if ( bSwitchH2V )
+ {
+ rInf.GetFrm()->SwitchHorizontalToVertical( aCurrPos );
+ rInf.GetFrm()->SwitchHorizontalToVertical( aEnd );
+ }
+ rInf.GetOut().DrawWaveLine( aCurrPos, aEnd, nWave );
+
+ if ( bColSave )
+ rInf.GetOut().SetLineColor( aCol );
+
+ if ( rInf.GetOut().GetConnectMetaFile() )
+ rInf.GetOut().Pop();
+ }
+ }
+ }
+ else if( !bSymbol && rInf.GetLen() )
+ {
+ // anything to do?
+ if (rInf.GetWrong() || rInf.GetGrammarCheck() || rInf.GetSmartTags())
+ {
+ CalcLinePosData aCalcLinePosData(rInf, *GetFont(),
+ nCnt, bSwitchH2V, bSwitchL2R,
+ nHalfSpace, pKernArray, bBidiPor);
+
+ SwForbidden aForbidden;
+ // draw line for smart tag data
+ lcl_DrawLineForWrongListData( aForbidden, rInf, rInf.GetSmartTags(), aCalcLinePosData, Size() );
+ // draw wave line for spell check errors
+ // draw them BEFORE the grammar check lines to 'override' the latter in case of conflict.
+ // reason: some grammar errors can only be found if spelling errors are fixed,
+ // therefore we don't want the user to miss a spelling error.
+ lcl_DrawLineForWrongListData( aForbidden, rInf, rInf.GetWrong(), aCalcLinePosData, pPrtFont->GetSize() );
+ // draw wave line for grammar check errors
+ lcl_DrawLineForWrongListData( aForbidden, rInf, rInf.GetGrammarCheck(), aCalcLinePosData, pPrtFont->GetSize() );
+ }
+ }
+
+ xub_StrLen nOffs = 0;
+ xub_StrLen nLen = rInf.GetLen();
+
+ if( nOffs < nLen )
+ {
+ // If we paint bullets instead of spaces, we use a copy of
+ // the paragraph string. For the layout engine, the copy
+ // of the string has to be an environment of the range which
+ // is painted
+ xub_StrLen nTmpIdx = bBullet ?
+ ( rInf.GetIdx() ? 1 : 0 ) :
+ rInf.GetIdx();
+
+ if ( bSwitchL2R )
+ rInf.GetFrm()->SwitchLTRtoRTL( aPos );
+
+ if ( bSwitchH2V )
+ rInf.GetFrm()->SwitchHorizontalToVertical( aPos );
+
+ rInf.GetOut().DrawTextArray( aPos, *pStr, pKernArray + nOffs,
+ nTmpIdx + nOffs , nLen - nOffs );
+ }
+ }
+ delete[] pScrArray;
+ delete[] pKernArray;
+ }
+}
+
+
+// Optimierung war fuer DrawText() ausgeschaltet
+#ifdef _MSC_VER
+#pragma optimize("",on)
+#endif
+
+
+/*************************************************************************
+ *
+ * Size SwFntObj::GetTextSize( const OutputDevice *pOut, const String &rTxt,
+ * const sal_uInt16 nIdx, const sal_uInt16 nLen, const short nKern = 0 );
+ *
+ * Beschreibung: ermittelt die TextSize (des Druckers)
+ *
+ *************************************************************************/
+
+Size SwFntObj::GetTextSize( SwDrawTextInfo& rInf )
+{
+ Size aTxtSize;
+ const xub_StrLen nLn = ( STRING_LEN != rInf.GetLen() ) ? rInf.GetLen() :
+ rInf.GetText().Len();
+
+ // be sure to have the correct layout mode at the printer
+ if ( pPrinter )
+ {
+ pPrinter->SetLayoutMode( rInf.GetOut().GetLayoutMode() );
+ pPrinter->SetDigitLanguage( rInf.GetOut().GetDigitLanguage() );
+ }
+
+ if ( rInf.GetFrm() && nLn && rInf.SnapToGrid() && rInf.GetFont() &&
+ SW_CJK == rInf.GetFont()->GetActual() )
+ {
+ GETGRID( rInf.GetFrm()->FindPageFrm() )
+ if ( pGrid && GRID_LINES_CHARS == pGrid->GetGridType() && pGrid->IsSnapToChars() )
+ {
+ const SwDoc* pDoc = rInf.GetShell()->GetDoc();
+ const sal_uInt16 nGridWidth = GETGRIDWIDTH(pGrid, pDoc);
+
+ OutputDevice* pOutDev;
+
+ if ( pPrinter )
+ {
+ if( !pPrtFont->IsSameInstance( pPrinter->GetFont() ) )
+ pPrinter->SetFont(*pPrtFont);
+ pOutDev = pPrinter;
+ }
+ else
+ pOutDev = rInf.GetpOut();
+
+ aTxtSize.Width() =
+ pOutDev->GetTextWidth( rInf.GetText(), rInf.GetIdx(), nLn );
+
+ OSL_ENSURE( !rInf.GetShell() ||
+ ( USHRT_MAX != GetGuessedLeading() && USHRT_MAX != GetExtLeading() ),
+ "Leading values should be already calculated" );
+ aTxtSize.Height() = pOutDev->GetTextHeight() +
+ GetFontLeading( rInf.GetShell(), rInf.GetOut() );
+
+ long nWidthPerChar = aTxtSize.Width() / nLn;
+
+ const sal_uLong i = nWidthPerChar ?
+ ( nWidthPerChar - 1 ) / nGridWidth + 1:
+ 1;
+
+ aTxtSize.Width() = i * nGridWidth * nLn;
+ rInf.SetKanaDiff( 0 );
+ return aTxtSize;
+ }
+ }
+
+ //for textgrid refactor
+ if ( rInf.GetFrm() && nLn && rInf.SnapToGrid() && rInf.GetFont() &&
+ SW_CJK == rInf.GetFont()->GetActual() )
+ {
+ GETGRID( rInf.GetFrm()->FindPageFrm() )
+ if ( pGrid && GRID_LINES_CHARS == pGrid->GetGridType() && !pGrid->IsSnapToChars() )
+ {
+ const sal_uInt16 nDefaultFontHeight = GetDefaultFontHeight( rInf );
+
+ const SwDoc* pDoc = rInf.GetShell()->GetDoc();
+ long nGridWidthAdd = GETGRIDWIDTH(pGrid, pDoc);
+ if( SW_LATIN == rInf.GetFont()->GetActual() )
+ nGridWidthAdd = ( nGridWidthAdd - nDefaultFontHeight ) / 2;
+ else
+ nGridWidthAdd = nGridWidthAdd - nDefaultFontHeight;
+ OutputDevice* pOutDev;
+ if ( pPrinter )
+ {
+ if( !pPrtFont->IsSameInstance( pPrinter->GetFont() ) )
+ pPrinter->SetFont(*pPrtFont);
+ pOutDev = pPrinter;
+ }
+ else
+ pOutDev = rInf.GetpOut();
+ aTxtSize.Width() = pOutDev->GetTextWidth( rInf.GetText(), rInf.GetIdx(), nLn );
+ aTxtSize.Height() = pOutDev->GetTextHeight() +
+ GetFontLeading( rInf.GetShell(), rInf.GetOut() );
+ aTxtSize.Width() += (nLn) * long( nGridWidthAdd );
+ //if ( rInf.GetKern() && nLn )
+ // aTxtSize.Width() += ( nLn ) * long( rInf.GetKern() );
+
+ rInf.SetKanaDiff( 0 );
+ return aTxtSize;
+ }
+ }
+
+ const sal_Bool bCompress = rInf.GetKanaComp() && nLn &&
+ rInf.GetFont() &&
+ SW_CJK == rInf.GetFont()->GetActual() &&
+ rInf.GetScriptInfo() &&
+ rInf.GetScriptInfo()->CountCompChg() &&
+ lcl_IsMonoSpaceFont( rInf.GetOut() );
+
+ OSL_ENSURE( !bCompress || ( rInf.GetScriptInfo() && rInf.GetScriptInfo()->
+ CountCompChg()), "Compression without info" );
+
+ // This is the part used e.g., for cursor travelling
+ // See condition for DrawText or DrawTextArray (bDirectPrint)
+ if ( pPrinter && pPrinter != rInf.GetpOut() )
+ {
+ if( !pPrtFont->IsSameInstance( pPrinter->GetFont() ) )
+ pPrinter->SetFont(*pPrtFont);
+ aTxtSize.Width() = pPrinter->GetTextWidth( rInf.GetText(),
+ rInf.GetIdx(), nLn );
+ aTxtSize.Height() = pPrinter->GetTextHeight();
+ sal_Int32 *pKernArray = new sal_Int32[nLn];
+ CreateScrFont( *rInf.GetShell(), rInf.GetOut() );
+ if( !GetScrFont()->IsSameInstance( rInf.GetOut().GetFont() ) )
+ rInf.GetOut().SetFont( *pScrFont );
+ long nScrPos;
+
+ pPrinter->GetTextArray( rInf.GetText(), pKernArray, rInf.GetIdx(),nLn );
+ if( bCompress )
+ rInf.SetKanaDiff( rInf.GetScriptInfo()->Compress( pKernArray,
+ rInf.GetIdx(), nLn, rInf.GetKanaComp(),
+ (sal_uInt16)aFont.GetSize().Height() ) );
+ else
+ rInf.SetKanaDiff( 0 );
+
+ if ( rInf.GetKanaDiff() )
+ nScrPos = pKernArray[ nLn - 1 ];
+ else
+ {
+ sal_Int32* pScrArray = new sal_Int32[ rInf.GetLen() ];
+ rInf.GetOut().GetTextArray( rInf.GetText(), pScrArray,
+ rInf.GetIdx(), rInf.GetLen() );
+ nScrPos = pScrArray[ 0 ];
+ xub_StrLen nCnt = rInf.GetText().Len();
+ if ( nCnt < rInf.GetIdx() )
+ nCnt=0;
+ else
+ nCnt = nCnt - rInf.GetIdx();
+ nCnt = Min (nCnt, nLn);
+ xub_Unicode nChPrev = rInf.GetText().GetChar( rInf.GetIdx() );
+
+ xub_Unicode nCh;
+
+ // Bei Pairkerning waechst der Printereinfluss auf die Positionierung
+ sal_uInt16 nMul = 3;
+ if ( pPrtFont->GetKerning() )
+ nMul = 1;
+ const sal_uInt16 nDiv = nMul+1;
+ for( xub_StrLen i=1; i<nCnt; i++ )
+ {
+ nCh = rInf.GetText().GetChar( rInf.GetIdx() + i );
+ long nScr;
+ nScr = pScrArray[ i ] - pScrArray[ i - 1 ];
+ if ( nCh == CH_BLANK )
+ nScrPos = pKernArray[i-1]+nScr;
+ else
+ {
+ if ( nChPrev == CH_BLANK || nChPrev == '-' )
+ nScrPos = pKernArray[i-1]+nScr;
+ else
+ {
+ nScrPos += nScr;
+ nScrPos = ( nMul * nScrPos + pKernArray[i] ) / nDiv;
+ }
+ }
+ nChPrev = nCh;
+ pKernArray[i-1] = nScrPos - nScr;
+ }
+ delete[] pScrArray;
+ }
+
+ delete[] pKernArray;
+ aTxtSize.Width() = nScrPos;
+ }
+ else
+ {
+ if( !pPrtFont->IsSameInstance( rInf.GetOut().GetFont() ) )
+ rInf.GetOut().SetFont( *pPrtFont );
+ if( bCompress )
+ {
+ sal_Int32 *pKernArray = new sal_Int32[nLn];
+ rInf.GetOut().GetTextArray( rInf.GetText(), pKernArray,
+ rInf.GetIdx(), nLn );
+ rInf.SetKanaDiff( rInf.GetScriptInfo()->Compress( pKernArray,
+ rInf.GetIdx(), nLn, rInf.GetKanaComp(),
+ (sal_uInt16) aFont.GetSize().Height() ) );
+ aTxtSize.Width() = pKernArray[ nLn - 1 ];
+ delete[] pKernArray;
+ }
+ else
+ {
+ aTxtSize.Width() = rInf.GetOut().GetTextWidth( rInf.GetText(),
+ rInf.GetIdx(), nLn );
+ rInf.SetKanaDiff( 0 );
+ }
+
+ aTxtSize.Height() = rInf.GetOut().GetTextHeight();
+ }
+
+ if ( rInf.GetKern() && nLn )
+ aTxtSize.Width() += ( nLn - 1 ) * long( rInf.GetKern() );
+
+ OSL_ENSURE( !rInf.GetShell() ||
+ ( USHRT_MAX != GetGuessedLeading() && USHRT_MAX != GetExtLeading() ),
+ "Leading values should be already calculated" );
+ aTxtSize.Height() += GetFontLeading( rInf.GetShell(), rInf.GetOut() );
+ return aTxtSize;
+}
+
+
+xub_StrLen SwFntObj::GetCrsrOfst( SwDrawTextInfo &rInf )
+{
+ long nSpaceAdd = rInf.GetSpace() / SPACING_PRECISION_FACTOR;
+ const long nSperren = -rInf.GetSperren() / SPACING_PRECISION_FACTOR;
+ long nKern = rInf.GetKern();
+
+ if( 0 != nSperren )
+ nKern -= nSperren;
+
+ sal_Int32 *pKernArray = new sal_Int32[ rInf.GetLen() ];
+
+ // be sure to have the correct layout mode at the printer
+ if ( pPrinter )
+ {
+ pPrinter->SetLayoutMode( rInf.GetOut().GetLayoutMode() );
+ pPrinter->SetDigitLanguage( rInf.GetOut().GetDigitLanguage() );
+ pPrinter->GetTextArray( rInf.GetText(), pKernArray,
+ rInf.GetIdx(), rInf.GetLen() );
+ }
+ else
+ rInf.GetOut().GetTextArray( rInf.GetText(), pKernArray,
+ rInf.GetIdx(), rInf.GetLen() );
+
+ const SwScriptInfo* pSI = rInf.GetScriptInfo();
+ if ( rInf.GetFont() && rInf.GetLen() )
+ {
+ const sal_uInt8 nActual = rInf.GetFont()->GetActual();
+
+ // Kana Compression
+ if ( SW_CJK == nActual && rInf.GetKanaComp() &&
+ pSI && pSI->CountCompChg() &&
+ lcl_IsMonoSpaceFont( rInf.GetOut() ) )
+ {
+ pSI->Compress( pKernArray, rInf.GetIdx(), rInf.GetLen(),
+ rInf.GetKanaComp(),
+ (sal_uInt16) aFont.GetSize().Height() );
+ }
+
+ // Asian Justification
+ if ( SW_CJK == rInf.GetFont()->GetActual() )
+ {
+ LanguageType aLang = rInf.GetFont()->GetLanguage( SW_CJK );
+
+ if ( LANGUAGE_KOREAN != aLang && LANGUAGE_KOREAN_JOHAB != aLang )
+ {
+ long nSpaceSum = nSpaceAdd;
+ for ( sal_uInt16 nI = 0; nI < rInf.GetLen(); ++nI )
+ {
+ pKernArray[ nI ] += nSpaceSum;
+ nSpaceSum += nSpaceAdd;
+ }
+
+ nSpaceAdd = 0;
+ }
+
+ }
+
+ // Kashida Justification
+ if ( SW_CTL == nActual && rInf.GetSpace() )
+ {
+ if ( SwScriptInfo::IsArabicText( rInf.GetText(), rInf.GetIdx(), rInf.GetLen() ) )
+ {
+ if ( pSI && pSI->CountKashida() &&
+ pSI->KashidaJustify( pKernArray, 0, rInf.GetIdx(), rInf.GetLen(),
+ nSpaceAdd ) != STRING_LEN )
+ nSpaceAdd = 0;
+ }
+ }
+
+ // Thai Justification
+ if ( SW_CTL == nActual && nSpaceAdd )
+ {
+ LanguageType aLang = rInf.GetFont()->GetLanguage( SW_CTL );
+
+ if ( LANGUAGE_THAI == aLang )
+ {
+ SwScriptInfo::ThaiJustify( rInf.GetText(), pKernArray, 0,
+ rInf.GetIdx(), rInf.GetLen(),
+ rInf.GetNumberOfBlanks(),
+ rInf.GetSpace() );
+
+ // adding space to blanks is already done
+ nSpaceAdd = 0;
+ }
+ }
+ }
+
+ long nLeft = 0;
+ long nRight = 0;
+ xub_StrLen nCnt = 0;
+ long nSpaceSum = 0;
+ long nKernSum = 0;
+
+ if ( rInf.GetFrm() && rInf.GetLen() && rInf.SnapToGrid() &&
+ rInf.GetFont() && SW_CJK == rInf.GetFont()->GetActual() )
+ {
+ GETGRID( rInf.GetFrm()->FindPageFrm() )
+ if ( pGrid && GRID_LINES_CHARS == pGrid->GetGridType() && pGrid->IsSnapToChars() )
+ {
+ const SwDoc* pDoc = rInf.GetShell()->GetDoc();
+ const sal_uInt16 nGridWidth = GETGRIDWIDTH(pGrid, pDoc);
+
+ long nWidthPerChar = pKernArray[ rInf.GetLen() - 1 ] / rInf.GetLen();
+
+ sal_uLong i = nWidthPerChar ?
+ ( nWidthPerChar - 1 ) / nGridWidth + 1:
+ 1;
+
+ nWidthPerChar = i * nGridWidth;
+
+ nCnt = (sal_uInt16)(rInf.GetOfst() / nWidthPerChar);
+ if ( 2 * ( rInf.GetOfst() - nCnt * nWidthPerChar ) > nWidthPerChar )
+ ++nCnt;
+
+ delete[] pKernArray;
+ return nCnt;
+ }
+ }
+
+ //for textgrid refactor
+ if ( rInf.GetFrm() && rInf.GetLen() && rInf.SnapToGrid() &&
+ rInf.GetFont() && SW_CJK == rInf.GetFont()->GetActual() )
+ {
+ GETGRID( rInf.GetFrm()->FindPageFrm() )
+ if ( pGrid && GRID_LINES_CHARS == pGrid->GetGridType() && !pGrid->IsSnapToChars() )
+ {
+
+ const sal_uInt16 nDefaultFontHeight = GetDefaultFontHeight( rInf );
+
+ const SwDoc* pDoc = rInf.GetShell()->GetDoc();
+ long nGridWidthAdd = GETGRIDWIDTH(pGrid, pDoc);
+ if( SW_LATIN == rInf.GetFont()->GetActual() )
+ nGridWidthAdd = ( nGridWidthAdd - nDefaultFontHeight ) / 2;
+ else
+ nGridWidthAdd = nGridWidthAdd - nDefaultFontHeight;
+
+ for(xub_StrLen j = 0; j < rInf.GetLen(); j++)
+ {
+ long nScr = pKernArray[ j ] + ( nSpaceAdd + nGridWidthAdd ) * ( j + 1 );
+ if( nScr >= rInf.GetOfst())
+ {
+ nCnt = j;
+ break;
+ }
+ }
+ delete[] pKernArray;
+ return nCnt;
+ }
+ }
+
+ sal_uInt16 nItrMode = i18n::CharacterIteratorMode::SKIPCELL;
+ sal_Int32 nDone = 0;
+ LanguageType aLang = LANGUAGE_NONE;
+ bool bSkipCharacterCells = false;
+ xub_StrLen nIdx = rInf.GetIdx();
+ xub_StrLen nLastIdx = nIdx;
+ const xub_StrLen nEnd = rInf.GetIdx() + rInf.GetLen();
+
+ // --> OD 2009-12-29 #i105901#
+ // skip character cells for all script types
+ if ( pBreakIt->GetBreakIter().is() )
+ // <--
+ {
+ aLang = rInf.GetFont()->GetLanguage();
+ bSkipCharacterCells = true;
+ }
+
+ while ( ( nRight < long( rInf.GetOfst() ) ) && ( nIdx < nEnd ) )
+ {
+ if ( nSpaceAdd && CH_BLANK == rInf.GetText().GetChar( nIdx ) )
+ nSpaceSum += nSpaceAdd;
+
+ // go to next character (cell).
+ nLastIdx = nIdx;
+
+ if ( bSkipCharacterCells )
+ {
+ nIdx = (xub_StrLen)pBreakIt->GetBreakIter()->nextCharacters( rInf.GetText(),
+ nIdx, pBreakIt->GetLocale( aLang ), nItrMode, 1, nDone );
+ if ( nIdx <= nLastIdx )
+ break;
+ }
+ else
+ ++nIdx;
+
+ nLeft = nRight;
+ nRight = pKernArray[ nIdx - rInf.GetIdx() - 1 ] + nKernSum + nSpaceSum;
+
+ nKernSum += nKern;
+ }
+
+ // step back if position is before the middle of the character
+ // or if we do not want to go to the next character
+ if ( nIdx > rInf.GetIdx() &&
+ ( rInf.IsPosMatchesBounds() ||
+ ( ( nRight > long( rInf.GetOfst() ) ) &&
+ ( nRight - rInf.GetOfst() > rInf.GetOfst() - nLeft ) ) ) )
+ nCnt = nLastIdx - rInf.GetIdx(); // first half
+ else
+ nCnt = nIdx - rInf.GetIdx(); // second half
+
+ if ( pSI )
+ rInf.SetCursorBidiLevel( pSI->DirType( nLastIdx ) );
+
+ delete[] pKernArray;
+ return nCnt;
+}
+
+
+/*************************************************************************
+|*
+|* SwFntAccess::SwFntAccess()
+|*
+|*************************************************************************/
+
+SwFntAccess::SwFntAccess( const void* &rMagic,
+ sal_uInt16 &rIndex, const void *pOwn, ViewShell *pSh,
+ sal_Bool bCheck ) :
+ SwCacheAccess( *pFntCache, rMagic, rIndex ),
+ pShell( pSh )
+{
+ // Der benutzte CTor von SwCacheAccess sucht anhand rMagic+rIndex im Cache
+ if ( IsAvail() )
+ {
+ // Der schnellste Fall: ein bekannter Font ( rMagic ),
+ // bei dem Drucker und Zoom nicht ueberprueft werden brauchen.
+ if ( !bCheck )
+ return;
+
+ // Hier ist zwar der Font bekannt, muss aber noch ueberprueft werden.
+
+ }
+ else
+ // Hier ist der Font nicht bekannt, muss also gesucht werden.
+ bCheck = sal_False;
+
+
+ {
+ OutputDevice* pOut = 0;
+ sal_uInt16 nZoom = USHRT_MAX;
+
+ // Get the reference device
+ if ( pSh )
+ {
+ pOut = &pSh->GetRefDev();
+ nZoom = pSh->GetViewOptions()->GetZoom();
+ }
+
+ SwFntObj *pFntObj;
+ if ( bCheck )
+ {
+ pFntObj = Get();
+ if ( ( pFntObj->GetZoom( ) == nZoom ) &&
+ ( pFntObj->pPrinter == pOut ) &&
+ pFntObj->GetPropWidth() ==
+ ((SwSubFont*)pOwn)->GetPropWidth() )
+ return; // Die Ueberpruefung ergab: Drucker+Zoom okay.
+ pFntObj->Unlock( ); // Vergiss dies Objekt, es wurde leider
+ pObj = NULL; // eine Drucker/Zoomaenderung festgestellt.
+ }
+
+ // Search by font comparison, quite expensive!
+ // Look for same font and same printer
+ pFntObj = pFntCache->First();
+ while ( pFntObj && !( pFntObj->aFont == *(Font *)pOwn &&
+ pFntObj->GetZoom() == nZoom &&
+ pFntObj->GetPropWidth() ==
+ ((SwSubFont*)pOwn)->GetPropWidth() &&
+ ( !pFntObj->pPrinter || pFntObj->pPrinter == pOut ) ) )
+ pFntObj = pFntCache->Next( pFntObj );
+
+ if( pFntObj && pFntObj->pPrinter != pOut )
+ {
+ // Wir haben zwar einen ohne Drucker gefunden, mal sehen, ob es
+ // auch noch einen mit identischem Drucker gibt.
+ SwFntObj *pTmpObj = pFntObj;
+ while( pTmpObj && !( pTmpObj->aFont == *(Font *)pOwn &&
+ pTmpObj->GetZoom()==nZoom && pTmpObj->pPrinter==pOut &&
+ pTmpObj->GetPropWidth() ==
+ ((SwSubFont*)pOwn)->GetPropWidth() ) )
+ pTmpObj = pFntCache->Next( pTmpObj );
+ if( pTmpObj )
+ pFntObj = pTmpObj;
+ }
+
+ if ( !pFntObj ) // Font has not been found, create one
+ {
+ // Das Objekt muss neu angelegt werden, deshalb muss der Owner ein
+ // SwFont sein, spaeter wird als Owner die "MagicNumber" gehalten.
+ SwCacheAccess::pOwner = pOwn;
+ pFntObj = Get(); // hier wird via NewObj() angelegt und gelockt.
+ OSL_ENSURE(pFntObj, "No Font, no Fun.");
+ }
+ else // Font has been found, so we lock it.
+ {
+ pFntObj->Lock();
+ if( pFntObj->pPrinter != pOut ) // Falls bis dato kein Drucker bekannt
+ {
+ OSL_ENSURE( !pFntObj->pPrinter, "SwFntAccess: Printer Changed" );
+ pFntObj->CreatePrtFont( *pOut );
+ pFntObj->pPrinter = pOut;
+ pFntObj->pScrFont = NULL;
+ pFntObj->nGuessedLeading = USHRT_MAX;
+ pFntObj->nExtLeading = USHRT_MAX;
+ pFntObj->nPrtAscent = USHRT_MAX;
+ pFntObj->nPrtHeight = USHRT_MAX;
+ }
+ pObj = pFntObj;
+ }
+
+ // egal, ob neu oder gefunden, ab jetzt ist der Owner vom Objekt eine
+ // MagicNumber und wird auch dem aufrufenden SwFont bekanntgegeben,
+ // ebenso der Index fuer spaetere direkte Zugriffe
+ rMagic = pFntObj->GetOwner();
+ SwCacheAccess::pOwner = rMagic;
+ rIndex = pFntObj->GetCachePos();
+ }
+}
+
+SwCacheObj *SwFntAccess::NewObj( )
+{
+ // Ein neuer Font, eine neue "MagicNumber".
+ return new SwFntObj( *(SwSubFont *)pOwner, ++pMagicNo, pShell );
+}
+
+extern xub_StrLen lcl_CalcCaseMap( const SwFont& rFnt,
+ const XubString& rOrigString,
+ xub_StrLen nOfst,
+ xub_StrLen nLen,
+ xub_StrLen nIdx );
+
+xub_StrLen SwFont::GetTxtBreak( SwDrawTextInfo& rInf, long nTextWidth )
+{
+ ChgFnt( rInf.GetShell(), rInf.GetOut() );
+
+ const sal_Bool bCompress = rInf.GetKanaComp() && rInf.GetLen() &&
+ SW_CJK == GetActual() &&
+ rInf.GetScriptInfo() &&
+ rInf.GetScriptInfo()->CountCompChg() &&
+ lcl_IsMonoSpaceFont( rInf.GetOut() );
+
+ OSL_ENSURE( !bCompress || ( rInf.GetScriptInfo() && rInf.GetScriptInfo()->
+ CountCompChg()), "Compression without info" );
+
+ sal_uInt16 nTxtBreak = 0;
+ long nKern = 0;
+
+ sal_uInt16 nLn = ( rInf.GetLen() == STRING_LEN ? rInf.GetText().Len()
+ : rInf.GetLen() );
+
+ if ( rInf.GetFrm() && nLn && rInf.SnapToGrid() &&
+ rInf.GetFont() && SW_CJK == rInf.GetFont()->GetActual() )
+ {
+ GETGRID( rInf.GetFrm()->FindPageFrm() )
+ if ( pGrid && GRID_LINES_CHARS == pGrid->GetGridType() && pGrid->IsSnapToChars() )
+ {
+ const SwDoc* pDoc = rInf.GetShell()->GetDoc();
+ const sal_uInt16 nGridWidth = GETGRIDWIDTH(pGrid, pDoc);
+
+ sal_Int32* pKernArray = new sal_Int32[rInf.GetLen()];
+ rInf.GetOut().GetTextArray( rInf.GetText(), pKernArray,
+ rInf.GetIdx(), rInf.GetLen() );
+
+ long nWidthPerChar = pKernArray[ rInf.GetLen() - 1 ] / rInf.GetLen();
+
+ const sal_uLong i = nWidthPerChar ?
+ ( nWidthPerChar - 1 ) / nGridWidth + 1:
+ 1;
+
+ nWidthPerChar = i * nGridWidth;
+ long nCurrPos = nWidthPerChar;
+
+ while( nTxtBreak < rInf.GetLen() && nTextWidth >= nCurrPos )
+ {
+ nCurrPos += nWidthPerChar;
+ ++nTxtBreak;
+ }
+
+ delete[] pKernArray;
+ return nTxtBreak + rInf.GetIdx();
+ }
+ }
+
+ //for text grid enhancement
+ if ( rInf.GetFrm() && nLn && rInf.SnapToGrid() && rInf.GetFont() &&
+ SW_CJK == rInf.GetFont()->GetActual() )
+ {
+ GETGRID( rInf.GetFrm()->FindPageFrm() )
+ if ( pGrid && GRID_LINES_CHARS == pGrid->GetGridType() && !pGrid->IsSnapToChars() )
+ {
+ const sal_uInt16 nDefaultFontHeight = GetDefaultFontHeight( rInf );
+
+ const SwDoc* pDoc = rInf.GetShell()->GetDoc();
+ long nGridWidthAdd = GETGRIDWIDTH(pGrid, pDoc);
+ if( SW_LATIN == rInf.GetFont()->GetActual() )
+ nGridWidthAdd = ( nGridWidthAdd - nDefaultFontHeight ) / 2 ;
+ else
+ nGridWidthAdd = nGridWidthAdd - nDefaultFontHeight;
+
+ sal_Int32* pKernArray = new sal_Int32[rInf.GetLen()];
+ rInf.GetOut().GetTextArray( rInf.GetText(), pKernArray,
+ rInf.GetIdx(), rInf.GetLen() );
+ long nCurrPos = pKernArray[nTxtBreak] + nGridWidthAdd;
+ while( nTxtBreak < rInf.GetLen() && nTextWidth >= nCurrPos)
+ {
+ nTxtBreak++;
+ nCurrPos = pKernArray[nTxtBreak] + nGridWidthAdd * ( nTxtBreak + 1 );
+ }
+ delete[] pKernArray;
+ return nTxtBreak + rInf.GetIdx();
+ }
+ }
+
+ if( aSub[nActual].IsCapital() && nLn )
+ nTxtBreak = GetCapitalBreak( rInf.GetShell(), rInf.GetpOut(),
+ rInf.GetScriptInfo(), rInf.GetText(), nTextWidth,0, rInf.GetIdx(),nLn );
+ else
+ {
+ nKern = CheckKerning();
+
+ const XubString* pTmpText;
+ XubString aTmpText;
+ xub_StrLen nTmpIdx;
+ xub_StrLen nTmpLen;
+ bool bTextReplaced = false;
+
+ if ( !aSub[nActual].IsCaseMap() )
+ {
+ pTmpText = &rInf.GetText();
+ nTmpIdx = rInf.GetIdx();
+ nTmpLen = nLn;
+ }
+ else
+ {
+ const XubString aSnippet( rInf.GetText(), rInf.GetIdx(), nLn );
+ aTmpText = aSub[nActual].CalcCaseMap( aSnippet );
+ const bool bTitle = SVX_CASEMAP_TITEL == aSub[nActual].GetCaseMap() &&
+ pBreakIt->GetBreakIter().is();
+
+ // Uaaaaahhhh!!! In title case mode, we would get wrong results
+ if ( bTitle && nLn )
+ {
+ // check if rInf.GetIdx() is begin of word
+ if ( !pBreakIt->GetBreakIter()->isBeginWord(
+ rInf.GetText(), rInf.GetIdx(),
+ pBreakIt->GetLocale( aSub[nActual].GetLanguage() ),
+ i18n::WordType::ANYWORD_IGNOREWHITESPACES ) )
+ {
+ // In this case, the beginning of aTmpText is wrong.
+ XubString aSnippetTmp( aSnippet, 0, 1 );
+ aSnippetTmp = aSub[nActual].CalcCaseMap( aSnippetTmp );
+ aTmpText.Erase( 0, aSnippetTmp.Len() );
+ aTmpText.Insert( aSnippet.GetChar( 0 ), 0 );
+ }
+ }
+
+ pTmpText = &aTmpText;
+ nTmpIdx = 0;
+ nTmpLen = aTmpText.Len();
+ bTextReplaced = true;
+ }
+
+ if( rInf.GetHyphPos() )
+ nTxtBreak = rInf.GetOut().GetTextBreak( *pTmpText, nTextWidth,
+ '-', *rInf.GetHyphPos(),
+ nTmpIdx, nTmpLen, nKern );
+ else
+ nTxtBreak = rInf.GetOut().GetTextBreak( *pTmpText, nTextWidth,
+ nTmpIdx, nTmpLen, nKern );
+
+ if ( bTextReplaced && STRING_LEN != nTxtBreak )
+ {
+ if ( nTmpLen != nLn )
+ nTxtBreak = lcl_CalcCaseMap( *this, rInf.GetText(),
+ rInf.GetIdx(), nLn, nTxtBreak );
+ else
+ nTxtBreak = nTxtBreak + rInf.GetIdx();
+ }
+ }
+
+ if ( ! bCompress )
+ return nTxtBreak;
+
+ nTxtBreak = nTxtBreak - rInf.GetIdx();
+
+ if( nTxtBreak < nLn )
+ {
+ if( !nTxtBreak && nLn )
+ nLn = 1;
+ else if( nLn > 2 * nTxtBreak )
+ nLn = 2 * nTxtBreak;
+ sal_Int32 *pKernArray = new sal_Int32[ nLn ];
+ rInf.GetOut().GetTextArray( rInf.GetText(), pKernArray,
+ rInf.GetIdx(), nLn );
+ if( rInf.GetScriptInfo()->Compress( pKernArray, rInf.GetIdx(), nLn,
+ rInf.GetKanaComp(), (sal_uInt16)GetHeight( nActual ) ) )
+ {
+ long nKernAdd = nKern;
+ xub_StrLen nTmpBreak = nTxtBreak;
+ if( nKern && nTxtBreak )
+ nKern *= nTxtBreak - 1;
+ while( nTxtBreak<nLn && nTextWidth >= pKernArray[nTxtBreak] +nKern )
+ {
+ nKern += nKernAdd;
+ ++nTxtBreak;
+ }
+ if( rInf.GetHyphPos() )
+ *rInf.GetHyphPos() += nTxtBreak - nTmpBreak; // It's not perfect
+ }
+ delete[] pKernArray;
+ }
+ nTxtBreak = nTxtBreak + rInf.GetIdx();
+
+ return nTxtBreak;
+}
+
+extern Color aGlobalRetoucheColor;
+
+sal_Bool SwDrawTextInfo::ApplyAutoColor( Font* pFont )
+{
+ const Font& rFnt = pFont ? *pFont : GetOut().GetFont();
+ sal_Bool bPrt = GetShell() && ! GetShell()->GetWin();
+ ColorData nNewColor = COL_BLACK;
+ sal_Bool bChgFntColor = sal_False;
+ sal_Bool bChgLineColor = sal_False;
+
+ if( bPrt && GetShell() && GetShell()->GetViewOptions()->IsBlackFont() )
+ {
+ if ( COL_BLACK != rFnt.GetColor().GetColor() )
+ bChgFntColor = sal_True;
+
+ if ( (COL_BLACK != GetOut().GetLineColor().GetColor()) ||
+ (COL_BLACK != GetOut().GetOverlineColor().GetColor()) )
+ bChgLineColor = sal_True;
+ }
+ else
+ {
+ // FontColor has to be changed if:
+ // 1. FontColor = AUTO or 2. IsAlwaysAutoColor is set
+ // LineColor has to be changed if:
+ // 1. IsAlwaysAutoColor is set
+
+ bChgLineColor = ! bPrt && GetShell() &&
+ GetShell()->GetAccessibilityOptions()->IsAlwaysAutoColor();
+
+ bChgFntColor = COL_AUTO == rFnt.GetColor().GetColor() || bChgLineColor;
+
+ if ( bChgFntColor )
+ {
+ // check if current background has a user defined setting
+ const Color* pCol = GetFont() ? GetFont()->GetBackColor() : NULL;
+ if( ! pCol || COL_TRANSPARENT == pCol->GetColor() )
+ {
+ const SvxBrushItem* pItem;
+ SwRect aOrigBackRect;
+
+ /// OD 21.08.2002
+ /// consider, that [GetBackgroundBrush(...)] can set <pCol>
+ /// - see implementation in /core/layout/paintfrm.cxx
+ /// OD 21.08.2002 #99657#
+ /// There is a user defined setting for the background, if there
+ /// is a background brush and its color is *not* "no fill"/"auto fill".
+ if( GetFrm()->GetBackgroundBrush( pItem, pCol, aOrigBackRect, sal_False ) )
+ {
+ if ( !pCol )
+ {
+ pCol = &pItem->GetColor();
+ }
+
+ /// OD 30.08.2002 #99657#
+ /// determined color <pCol> can be <COL_TRANSPARENT>. Thus, check it.
+ if ( pCol->GetColor() == COL_TRANSPARENT)
+ pCol = NULL;
+ }
+ else
+ pCol = NULL;
+ }
+
+ // no user defined color at paragraph or font background
+ if ( ! pCol )
+ pCol = &aGlobalRetoucheColor;
+
+ if( GetShell() && GetShell()->GetWin() )
+ {
+ // here we determine the prefered window text color for painting
+ const SwViewOption* pViewOption = GetShell()->GetViewOptions();
+ if(pViewOption->IsPagePreview() &&
+ !SW_MOD()->GetAccessibilityOptions().GetIsForPagePreviews())
+ nNewColor = COL_BLACK;
+ else
+ // we take the font color from the appearence page
+ nNewColor = SwViewOption::GetFontColor().GetColor();
+ }
+
+ // change painting color depending of dark/bright background
+ Color aTmpColor( nNewColor );
+ if ( pCol->IsDark() && aTmpColor.IsDark() )
+ nNewColor = COL_WHITE;
+ else if ( pCol->IsBright() && aTmpColor.IsBright() )
+ nNewColor = COL_BLACK;
+ }
+ }
+
+ if ( bChgFntColor || bChgLineColor )
+ {
+ Color aNewColor( nNewColor );
+
+ if ( bChgFntColor )
+ {
+ if ( pFont && aNewColor != pFont->GetColor() )
+ {
+ // only set the new color at the font passed as argument
+ pFont->SetColor( aNewColor );
+ }
+ else if ( aNewColor != GetOut().GetFont().GetColor() )
+ {
+ // set new font with new color at output device
+ Font aFont( rFnt );
+ aFont.SetColor( aNewColor );
+ GetOut().SetFont( aFont );
+ }
+ }
+
+ // the underline and overline colors have to be set separately
+ if ( bChgLineColor )
+ {
+ // get current font color or color set at output device
+ aNewColor = pFont ? pFont->GetColor() : GetOut().GetFont().GetColor();
+ if ( aNewColor != GetOut().GetLineColor() )
+ GetOut().SetLineColor( aNewColor );
+ if ( aNewColor != GetOut().GetOverlineColor() )
+ GetOut().SetOverlineColor( aNewColor );
+ }
+
+ return sal_True;
+ }
+
+ return sal_False;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/txtnode/fntcap.cxx b/sw/source/core/txtnode/fntcap.cxx
new file mode 100644
index 000000000000..8a40614a3d93
--- /dev/null
+++ b/sw/source/core/txtnode/fntcap.cxx
@@ -0,0 +1,846 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+
+#include <hintids.hxx>
+#include <editeng/cmapitem.hxx>
+#include <editeng/svxfont.hxx>
+
+#include <vcl/outdev.hxx>
+#include <com/sun/star/i18n/CharType.hdl>
+#include <com/sun/star/i18n/WordType.hdl>
+
+#include <vcl/print.hxx>
+#include <fntcache.hxx>
+#include <swfont.hxx>
+#include <breakit.hxx>
+#include <txtfrm.hxx> // SwTxtFrm
+#include <scriptinfo.hxx>
+
+using namespace ::com::sun::star::i18n;
+
+/*************************************************************************
+ * class SwCapitalInfo
+ *
+ * The information encapsulated in SwCapitalInfo is required
+ * by the ::Do functions. They contain the information about
+ * the original string, whereas rDo.GetInf() contains information
+ * about the display string.
+ *************************************************************************/
+
+class SwCapitalInfo
+{
+public:
+ explicit SwCapitalInfo( const XubString& rOrigText ) :
+ rString( rOrigText ), nIdx( 0 ), nLen( 0 ) {};
+ const XubString& rString;
+ xub_StrLen nIdx;
+ xub_StrLen nLen;
+};
+
+/*************************************************************************
+ * xub_StrLen lcl_CalcCaseMap()
+ *
+ * rFnt: required for CalcCaseMap
+ * rOrigString: The original string
+ * nOfst: Position of the substring in rOrigString
+ * nLen: Length if the substring in rOrigString
+ * nIdx: Referes to a position in the display string and should be mapped
+ * to a position in rOrigString
+ *************************************************************************/
+
+xub_StrLen lcl_CalcCaseMap( const SwFont& rFnt,
+ const XubString& rOrigString,
+ xub_StrLen nOfst,
+ xub_StrLen nLen,
+ xub_StrLen nIdx )
+{
+ int j = 0;
+ const xub_StrLen nEnd = nOfst + nLen;
+ OSL_ENSURE( nEnd <= rOrigString.Len(), "lcl_CalcCaseMap: Wrong parameters" );
+
+ // special case for title case:
+ const bool bTitle = SVX_CASEMAP_TITEL == rFnt.GetCaseMap() &&
+ pBreakIt->GetBreakIter().is();
+ for ( xub_StrLen i = nOfst; i < nEnd; ++i )
+ {
+ XubString aTmp( rOrigString, i, 1 );
+
+ if ( !bTitle ||
+ pBreakIt->GetBreakIter()->isBeginWord(
+ rOrigString, i,
+ pBreakIt->GetLocale( rFnt.GetLanguage() ),
+ WordType::ANYWORD_IGNOREWHITESPACES ) )
+ aTmp = rFnt.GetActualFont().CalcCaseMap( aTmp );
+
+ j += aTmp.Len();
+
+ if ( j > nIdx )
+ return i;
+ }
+
+ return nOfst + nLen;
+}
+
+/*************************************************************************
+ * class SwDoCapitals
+ *************************************************************************/
+
+class SwDoCapitals
+{
+protected:
+ SwDrawTextInfo &rInf;
+ SwCapitalInfo* pCapInf; // referes to additional information
+ // required by the ::Do function
+public:
+ SwDoCapitals ( SwDrawTextInfo &rInfo ) : rInf( rInfo ), pCapInf( 0 ) { }
+ virtual void Init( SwFntObj *pUpperFont, SwFntObj *pLowerFont ) = 0;
+ virtual void Do() = 0;
+ inline OutputDevice& GetOut() { return rInf.GetOut(); }
+ inline SwDrawTextInfo& GetInf() { return rInf; }
+ inline SwCapitalInfo* GetCapInf() const { return pCapInf; }
+ inline void SetCapInf( SwCapitalInfo& rNew ) { pCapInf = &rNew; }
+};
+
+/*************************************************************************
+ * class SwDoGetCapitalSize
+ *************************************************************************/
+
+class SwDoGetCapitalSize : public SwDoCapitals
+{
+protected:
+ Size aTxtSize;
+public:
+ SwDoGetCapitalSize( SwDrawTextInfo &rInfo ) : SwDoCapitals ( rInfo ) { }
+ virtual void Init( SwFntObj *pUpperFont, SwFntObj *pLowerFont );
+ virtual void Do();
+ const Size &GetSize() const { return aTxtSize; }
+};
+
+void SwDoGetCapitalSize::Init( SwFntObj *, SwFntObj * )
+{
+ aTxtSize.Height() = 0;
+ aTxtSize.Width() = 0;
+}
+
+void SwDoGetCapitalSize::Do()
+{
+ aTxtSize.Width() += rInf.GetSize().Width();
+ if( rInf.GetUpper() )
+ aTxtSize.Height() = rInf.GetSize().Height();
+}
+
+/*************************************************************************
+ * SwSubFont::GetCapitalSize()
+ *************************************************************************/
+
+Size SwSubFont::GetCapitalSize( SwDrawTextInfo& rInf )
+{
+ // Start:
+ const long nOldKern = rInf.GetKern();
+ rInf.SetKern( CheckKerning() );
+ Point aPos;
+ rInf.SetPos( aPos );
+ rInf.SetSpace( 0 );
+ rInf.SetDrawSpace( sal_False );
+ SwDoGetCapitalSize aDo( rInf );
+ DoOnCapitals( aDo );
+ Size aTxtSize( aDo.GetSize() );
+
+ // End:
+ if( !aTxtSize.Height() )
+ {
+ SV_STAT( nGetTextSize );
+ aTxtSize.Height() = short ( rInf.GetpOut()->GetTextHeight() );
+ }
+ rInf.SetKern( nOldKern );
+ return aTxtSize;
+}
+
+/*************************************************************************
+ * class SwDoGetCapitalBreak
+ *************************************************************************/
+
+class SwDoGetCapitalBreak : public SwDoCapitals
+{
+protected:
+ xub_StrLen *pExtraPos;
+ long nTxtWidth;
+ xub_StrLen nBreak;
+public:
+ SwDoGetCapitalBreak( SwDrawTextInfo &rInfo, long nWidth, xub_StrLen *pExtra)
+ : SwDoCapitals ( rInfo ), pExtraPos( pExtra ), nTxtWidth( nWidth ),
+ nBreak( STRING_LEN )
+ { }
+ virtual void Init( SwFntObj *pUpperFont, SwFntObj *pLowerFont );
+ virtual void Do();
+ xub_StrLen GetBreak() const { return nBreak; }
+};
+
+void SwDoGetCapitalBreak::Init( SwFntObj *, SwFntObj * )
+{
+}
+
+void SwDoGetCapitalBreak::Do()
+{
+ if ( nTxtWidth )
+ {
+ if ( rInf.GetSize().Width() < nTxtWidth )
+ nTxtWidth -= rInf.GetSize().Width();
+ else
+ {
+ xub_StrLen nEnd = rInf.GetEnd();
+ if( pExtraPos )
+ {
+ nBreak = GetOut().GetTextBreak( rInf.GetText(), nTxtWidth, '-',
+ *pExtraPos, rInf.GetIdx(), rInf.GetLen(), rInf.GetKern() );
+ if( *pExtraPos > nEnd )
+ *pExtraPos = nEnd;
+ }
+ else
+ nBreak = GetOut().GetTextBreak( rInf.GetText(), nTxtWidth,
+ rInf.GetIdx(), rInf.GetLen(), rInf.GetKern() );
+
+ if( nBreak > nEnd )
+ nBreak = nEnd;
+
+ // nBreak may be relative to the display string. It has to be
+ // calculated relative to the original string:
+ if ( GetCapInf() )
+ {
+ if ( GetCapInf()->nLen != rInf.GetLen() )
+ nBreak = lcl_CalcCaseMap( *rInf.GetFont(),
+ GetCapInf()->rString,
+ GetCapInf()->nIdx,
+ GetCapInf()->nLen, nBreak );
+ else
+ nBreak = nBreak + GetCapInf()->nIdx;
+ }
+
+ nTxtWidth = 0;
+ }
+ }
+}
+
+/*************************************************************************
+ * SwFont::GetCapitalBreak()
+ *************************************************************************/
+
+xub_StrLen SwFont::GetCapitalBreak( ViewShell* pSh, const OutputDevice* pOut,
+ const SwScriptInfo* pScript, const XubString& rTxt, long nTextWidth,
+ xub_StrLen *pExtra, const xub_StrLen nIdx, const xub_StrLen nLen )
+{
+ // Start:
+ Point aPos( 0, 0 );
+ SwDrawTextInfo aInfo(pSh, *(OutputDevice*)pOut, pScript, rTxt, nIdx, nLen,
+ 0, sal_False);
+ aInfo.SetPos( aPos );
+ aInfo.SetSpace( 0 );
+ aInfo.SetWrong( NULL );
+ aInfo.SetGrammarCheck( NULL );
+ aInfo.SetSmartTags( NULL ); // SMARTTAGS
+ aInfo.SetDrawSpace( sal_False );
+ aInfo.SetKern( CheckKerning() );
+ aInfo.SetKanaComp( pScript ? 0 : 100 );
+ aInfo.SetFont( this );
+
+ SwDoGetCapitalBreak aDo( aInfo, nTextWidth, pExtra );
+ DoOnCapitals( aDo );
+ return aDo.GetBreak();
+}
+
+/*************************************************************************
+ * class SwDoDrawCapital
+ *************************************************************************/
+
+class SwDoDrawCapital : public SwDoCapitals
+{
+protected:
+ SwFntObj *pUpperFnt;
+ SwFntObj *pLowerFnt;
+public:
+ SwDoDrawCapital( SwDrawTextInfo &rInfo ) :
+ SwDoCapitals( rInfo ), pUpperFnt(0), pLowerFnt(0)
+ { }
+ virtual void Init( SwFntObj *pUpperFont, SwFntObj *pLowerFont );
+ virtual void Do();
+ void DrawSpace( Point &rPos );
+};
+
+void SwDoDrawCapital::Init( SwFntObj *pUpperFont, SwFntObj *pLowerFont )
+{
+ pUpperFnt = pUpperFont;
+ pLowerFnt = pLowerFont;
+}
+
+void SwDoDrawCapital::Do()
+{
+ SV_STAT( nDrawText );
+ sal_uInt16 nOrgWidth = rInf.GetWidth();
+ rInf.SetWidth( sal_uInt16(rInf.GetSize().Width()) );
+ if ( rInf.GetUpper() )
+ pUpperFnt->DrawText( rInf );
+ else
+ {
+ sal_Bool bOldBullet = rInf.GetBullet();
+ rInf.SetBullet( sal_False );
+ pLowerFnt->DrawText( rInf );
+ rInf.SetBullet( bOldBullet );
+ }
+
+ OSL_ENSURE( pUpperFnt, "No upper font, dying soon!");
+ rInf.Shift( pUpperFnt->GetFont()->GetOrientation() );
+ rInf.SetWidth( nOrgWidth );
+}
+
+/*************************************************************************
+ * SwDoDrawCapital::DrawSpace()
+ *************************************************************************/
+
+void SwDoDrawCapital::DrawSpace( Point &rPos )
+{
+ static sal_Char const sDoubleSpace[] = " ";
+
+ long nDiff = rInf.GetPos().X() - rPos.X();
+
+ Point aPos( rPos );
+ const sal_Bool bSwitchL2R = rInf.GetFrm()->IsRightToLeft() &&
+ ! rInf.IsIgnoreFrmRTL();
+
+
+ if ( bSwitchL2R )
+ rInf.GetFrm()->SwitchLTRtoRTL( aPos );
+
+ const sal_uLong nMode = rInf.GetpOut()->GetLayoutMode();
+ const sal_Bool bBidiPor = ( bSwitchL2R !=
+ ( 0 != ( TEXT_LAYOUT_BIDI_RTL & nMode ) ) );
+
+ if ( bBidiPor )
+ nDiff = -nDiff;
+
+ if ( rInf.GetFrm()->IsVertical() )
+ rInf.GetFrm()->SwitchHorizontalToVertical( aPos );
+
+ if ( nDiff )
+ {
+ rInf.ApplyAutoColor();
+ GetOut().DrawStretchText( aPos, nDiff,
+ XubString( sDoubleSpace, RTL_TEXTENCODING_MS_1252 ), 0, 2 );
+ }
+ rPos.X() = rInf.GetPos().X() + rInf.GetWidth();
+}
+
+/*************************************************************************
+ * SwSubFont::DrawCapital()
+ *************************************************************************/
+
+void SwSubFont::DrawCapital( SwDrawTextInfo &rInf )
+{
+ // Es wird vorausgesetzt, dass rPos bereits kalkuliert ist!
+ // hochgezogen in SwFont: const Point aPos( CalcPos(rPos) );
+ rInf.SetDrawSpace( GetUnderline() != UNDERLINE_NONE ||
+ GetOverline() != UNDERLINE_NONE ||
+ GetStrikeout() != STRIKEOUT_NONE );
+ SwDoDrawCapital aDo( rInf );
+ DoOnCapitals( aDo );
+}
+
+/*************************************************************************
+ * class SwDoDrawCapital
+ *************************************************************************/
+
+class SwDoCapitalCrsrOfst : public SwDoCapitals
+{
+protected:
+ SwFntObj *pUpperFnt;
+ SwFntObj *pLowerFnt;
+ xub_StrLen nCrsr;
+ sal_uInt16 nOfst;
+public:
+ SwDoCapitalCrsrOfst( SwDrawTextInfo &rInfo, const sal_uInt16 nOfs ) :
+ SwDoCapitals( rInfo ), pUpperFnt(0), pLowerFnt(0), nCrsr( 0 ), nOfst( nOfs )
+ { }
+ virtual void Init( SwFntObj *pUpperFont, SwFntObj *pLowerFont );
+ virtual void Do();
+
+ void DrawSpace( const Point &rPos );
+ inline xub_StrLen GetCrsr(){ return nCrsr; }
+};
+
+void SwDoCapitalCrsrOfst::Init( SwFntObj *pUpperFont, SwFntObj *pLowerFont )
+{
+ pUpperFnt = pUpperFont;
+ pLowerFnt = pLowerFont;
+}
+
+void SwDoCapitalCrsrOfst::Do()
+{
+ if ( nOfst )
+ {
+ if ( nOfst > rInf.GetSize().Width() )
+ {
+ nOfst = nOfst - sal_uInt16(rInf.GetSize().Width());
+ nCrsr = nCrsr + rInf.GetLen();
+ }
+ else
+ {
+ SwDrawTextInfo aDrawInf( rInf.GetShell(), *rInf.GetpOut(),
+ rInf.GetScriptInfo(),
+ rInf.GetText(),
+ rInf.GetIdx(),
+ rInf.GetLen(), 0, sal_False );
+ aDrawInf.SetOfst( nOfst );
+ aDrawInf.SetKern( rInf.GetKern() );
+ aDrawInf.SetKanaComp( rInf.GetKanaComp() );
+ aDrawInf.SetFrm( rInf.GetFrm() );
+ aDrawInf.SetFont( rInf.GetFont() );
+
+ if ( rInf.GetUpper() )
+ {
+ aDrawInf.SetSpace( 0 );
+ nCrsr = nCrsr + pUpperFnt->GetCrsrOfst( aDrawInf );
+ }
+ else
+ {
+ aDrawInf.SetSpace( rInf.GetSpace() );
+ nCrsr = nCrsr + pLowerFnt->GetCrsrOfst( aDrawInf );
+ }
+ nOfst = 0;
+ }
+ }
+}
+
+/*************************************************************************
+ * SwSubFont::GetCapitalCrsrOfst()
+ *************************************************************************/
+
+xub_StrLen SwSubFont::GetCapitalCrsrOfst( SwDrawTextInfo& rInf )
+{
+ const long nOldKern = rInf.GetKern();
+ rInf.SetKern( CheckKerning() );
+ SwDoCapitalCrsrOfst aDo( rInf, rInf.GetOfst() );
+ Point aPos;
+ rInf.SetPos( aPos );
+ rInf.SetDrawSpace( sal_False );
+ DoOnCapitals( aDo );
+ rInf.SetKern( nOldKern );
+ return aDo.GetCrsr();
+}
+
+/*************************************************************************
+ * class SwDoDrawStretchCapital
+ *************************************************************************/
+
+class SwDoDrawStretchCapital : public SwDoDrawCapital
+{
+ const xub_StrLen nStrLen;
+ const sal_uInt16 nCapWidth;
+ const sal_uInt16 nOrgWidth;
+public:
+ virtual void Do();
+
+ SwDoDrawStretchCapital( SwDrawTextInfo &rInfo, const sal_uInt16 nCapitalWidth )
+ : SwDoDrawCapital( rInfo ),
+ nStrLen( rInfo.GetLen() ),
+ nCapWidth( nCapitalWidth ),
+ nOrgWidth( rInfo.GetWidth() )
+ { }
+};
+
+/*************************************************************************
+ * SwDoDrawStretchCapital
+ *************************************************************************/
+
+void SwDoDrawStretchCapital::Do()
+{
+ SV_STAT( nDrawStretchText );
+ sal_uInt16 nPartWidth = sal_uInt16(rInf.GetSize().Width());
+
+ if( rInf.GetLen() )
+ {
+ // 4023: Kapitaelchen und Kerning.
+ long nDiff = long(nOrgWidth) - long(nCapWidth);
+ if( nDiff )
+ {
+ nDiff *= rInf.GetLen();
+ nDiff /= (long) nStrLen;
+ nDiff += nPartWidth;
+ if( 0 < nDiff )
+ nPartWidth = sal_uInt16(nDiff);
+ }
+
+ rInf.ApplyAutoColor();
+
+ Point aPos( rInf.GetPos() );
+ const sal_Bool bSwitchL2R = rInf.GetFrm()->IsRightToLeft() &&
+ ! rInf.IsIgnoreFrmRTL();
+
+ if ( bSwitchL2R )
+ rInf.GetFrm()->SwitchLTRtoRTL( aPos );
+
+ if ( rInf.GetFrm()->IsVertical() )
+ rInf.GetFrm()->SwitchHorizontalToVertical( aPos );
+
+ // Optimierung:
+ if( 1 >= rInf.GetLen() )
+ GetOut().DrawText( aPos, rInf.GetText(), rInf.GetIdx(),
+ rInf.GetLen() );
+ else
+ GetOut().DrawStretchText( aPos, nPartWidth,
+ rInf.GetText(), rInf.GetIdx(), rInf.GetLen() );
+ }
+ ((Point&)rInf.GetPos()).X() += nPartWidth;
+}
+
+/*************************************************************************
+ * SwSubFont::DrawStretchCapital()
+ *************************************************************************/
+
+void SwSubFont::DrawStretchCapital( SwDrawTextInfo &rInf )
+{
+ // Es wird vorausgesetzt, dass rPos bereits kalkuliert ist!
+ // hochgezogen in SwFont: const Point aPos( CalcPos(rPos) );
+
+ if( rInf.GetLen() == STRING_LEN )
+ rInf.SetLen( rInf.GetText().Len() );
+
+ const Point& rOldPos = rInf.GetPos();
+ const sal_uInt16 nCapWidth = (sal_uInt16)( GetCapitalSize( rInf ).Width() );
+ rInf.SetPos( rOldPos );
+
+ rInf.SetDrawSpace( GetUnderline() != UNDERLINE_NONE ||
+ GetOverline() != UNDERLINE_NONE ||
+ GetStrikeout() != STRIKEOUT_NONE );
+ SwDoDrawStretchCapital aDo( rInf, nCapWidth );
+ DoOnCapitals( aDo );
+}
+
+/*************************************************************************
+ * SwSubFont::DoOnCapitals() const
+ *************************************************************************/
+
+// JP 22.8.2001 - global optimization off - Bug 91245 / 91223
+#ifdef _MSC_VER
+#pragma optimize("g",off)
+#endif
+
+void SwSubFont::DoOnCapitals( SwDoCapitals &rDo )
+{
+ OSL_ENSURE( pLastFont, "SwFont::DoOnCapitals: No LastFont?!" );
+
+ Size aPartSize;
+ long nKana = 0;
+ const XubString aTxt( CalcCaseMap( rDo.GetInf().GetText() ) );
+ xub_StrLen nMaxPos = Min( sal_uInt16(rDo.GetInf().GetText().Len()
+ - rDo.GetInf().GetIdx()), rDo.GetInf().GetLen() );
+ rDo.GetInf().SetLen( nMaxPos );
+
+ const XubString& rOldText = rDo.GetInf().GetText();
+ rDo.GetInf().SetText( aTxt );
+ rDo.GetInf().SetSize( aPartSize );
+ xub_StrLen nPos = rDo.GetInf().GetIdx();
+ xub_StrLen nOldPos = nPos;
+ nMaxPos = nMaxPos + nPos;
+
+ // #107816#
+ // Look if the length of the original text and the ToUpper-converted
+ // text is different. If yes, do special handling.
+ XubString aNewText;
+ SwCapitalInfo aCapInf( rOldText );
+ sal_Bool bCaseMapLengthDiffers( aTxt.Len() != rOldText.Len() );
+ if ( bCaseMapLengthDiffers )
+ rDo.SetCapInf( aCapInf );
+
+ SwFntObj *pOldLast = pLastFont;
+ SwFntAccess *pBigFontAccess = NULL;
+ SwFntObj *pBigFont;
+ SwFntAccess *pSpaceFontAccess = NULL;
+ SwFntObj *pSpaceFont = NULL;
+
+ const void *pMagic2 = NULL;
+ sal_uInt16 nIndex2 = 0;
+ SwSubFont aFont( *this );
+ Point aStartPos( rDo.GetInf().GetPos() );
+
+ const sal_Bool bTextLines = aFont.GetUnderline() != UNDERLINE_NONE
+ || aFont.GetOverline() != UNDERLINE_NONE
+ || aFont.GetStrikeout() != STRIKEOUT_NONE;
+ const sal_Bool bWordWise = bTextLines && aFont.IsWordLineMode() &&
+ rDo.GetInf().GetDrawSpace();
+ const long nTmpKern = rDo.GetInf().GetKern();
+
+ if ( bTextLines )
+ {
+ if ( bWordWise )
+ {
+ aFont.SetWordLineMode( sal_False );
+ pSpaceFontAccess = new SwFntAccess( pMagic2, nIndex2, &aFont,
+ rDo.GetInf().GetShell() );
+ pSpaceFont = pSpaceFontAccess->Get();
+ }
+ else
+ pSpaceFont = pLastFont;
+
+ // Wir basteln uns einen Font fuer die Grossbuchstaben:
+ aFont.SetUnderline( UNDERLINE_NONE );
+ aFont.SetOverline( UNDERLINE_NONE );
+ aFont.SetStrikeout( STRIKEOUT_NONE );
+ pMagic2 = NULL;
+ nIndex2 = 0;
+ pBigFontAccess = new SwFntAccess( pMagic2, nIndex2, &aFont,
+ rDo.GetInf().GetShell() );
+ pBigFont = pBigFontAccess->Get();
+ }
+ else
+ pBigFont = pLastFont;
+
+ // Hier entsteht der Kleinbuchstabenfont:
+ aFont.SetProportion( sal_uInt8 (aFont.GetPropr() * SMALL_CAPS_PERCENTAGE ) / 100L);
+ pMagic2 = NULL;
+ nIndex2 = 0;
+ SwFntAccess *pSmallFontAccess = new SwFntAccess( pMagic2, nIndex2, &aFont,
+ rDo.GetInf().GetShell() );
+ SwFntObj *pSmallFont = pSmallFontAccess->Get();
+
+ rDo.Init( pBigFont, pSmallFont );
+ OutputDevice* pOutSize = pSmallFont->GetPrt();
+ if( !pOutSize )
+ pOutSize = &rDo.GetOut();
+ OutputDevice* pOldOut = &rDo.GetOut();
+
+ const LanguageType eLng = LANGUAGE_DONTKNOW == GetLanguage()
+ ? LANGUAGE_SYSTEM : GetLanguage();
+
+ if( nPos < nMaxPos )
+ {
+ nPos = (xub_StrLen)pBreakIt->GetBreakIter()->endOfCharBlock( rOldText, nPos,
+ pBreakIt->GetLocale( eLng ), CharType::LOWERCASE_LETTER);
+ if( nPos == STRING_LEN )
+ nPos = nOldPos;
+ else if( nPos > nMaxPos )
+ nPos = nMaxPos;
+ }
+
+ while( nOldPos < nMaxPos )
+ {
+
+ // The lower ones...
+ if( nOldPos != nPos )
+ {
+ SV_STAT( nGetTextSize );
+ pLastFont = pSmallFont;
+ pLastFont->SetDevFont( rDo.GetInf().GetShell(), rDo.GetOut() );
+
+ // #107816#, #i14820#
+ if( bCaseMapLengthDiffers )
+ {
+ // Build an own 'changed' string for the given part of the
+ // source string and use it. That new string may differ in length
+ // from the source string.
+ const XubString aSnippet( rOldText, nOldPos, nPos - nOldPos);
+ aNewText = CalcCaseMap( aSnippet );
+ aCapInf.nIdx = nOldPos;
+ aCapInf.nLen = nPos - nOldPos;
+ rDo.GetInf().SetIdx( 0 );
+ rDo.GetInf().SetLen( aNewText.Len() );
+ rDo.GetInf().SetText( aNewText );
+ }
+ else
+ {
+ rDo.GetInf().SetIdx( nOldPos );
+ rDo.GetInf().SetLen( nPos - nOldPos );
+ }
+
+ rDo.GetInf().SetUpper( sal_False );
+ rDo.GetInf().SetOut( *pOutSize );
+ aPartSize = pSmallFont->GetTextSize( rDo.GetInf() );
+ nKana += rDo.GetInf().GetKanaDiff();
+ rDo.GetInf().SetOut( *pOldOut );
+ if( nTmpKern && nPos < nMaxPos )
+ aPartSize.Width() += nTmpKern;
+ rDo.Do();
+ nOldPos = nPos;
+ }
+ nPos = (xub_StrLen)pBreakIt->GetBreakIter()->nextCharBlock( rOldText, nPos,
+ pBreakIt->GetLocale( eLng ), CharType::LOWERCASE_LETTER);
+ if( nPos == STRING_LEN || nPos > nMaxPos )
+ nPos = nMaxPos;
+ OSL_ENSURE( nPos, "nextCharBlock not implemented?" );
+#if OSL_DEBUG_LEVEL > 1
+ if( !nPos )
+ nPos = nMaxPos;
+#endif
+ // The upper ones...
+ if( nOldPos != nPos )
+ {
+ const long nSpaceAdd = rDo.GetInf().GetSpace() / SPACING_PRECISION_FACTOR;
+
+ do
+ {
+ rDo.GetInf().SetUpper( sal_True );
+ pLastFont = pBigFont;
+ pLastFont->SetDevFont( rDo.GetInf().GetShell(), rDo.GetOut() );
+ xub_StrLen nTmp;
+ if( bWordWise )
+ {
+ nTmp = nOldPos;
+ while( nTmp < nPos && CH_BLANK == rOldText.GetChar( nTmp ) )
+ ++nTmp;
+ if( nOldPos < nTmp )
+ {
+ pLastFont = pSpaceFont;
+ pLastFont->SetDevFont( rDo.GetInf().GetShell(),
+ rDo.GetOut() );
+ ((SwDoDrawCapital&)rDo).DrawSpace( aStartPos );
+ pLastFont = pBigFont;
+ pLastFont->SetDevFont( rDo.GetInf().GetShell(),
+ rDo.GetOut() );
+
+ // #107816#, #i14820#
+ if( bCaseMapLengthDiffers )
+ {
+ // Build an own 'changed' string for the given part of the
+ // source string and use it. That new string may differ in length
+ // from the source string.
+ const XubString aSnippet( rOldText, nOldPos, nTmp - nOldPos);
+ aNewText = CalcCaseMap( aSnippet );
+ aCapInf.nIdx = nOldPos;
+ aCapInf.nLen = nTmp - nOldPos;
+ rDo.GetInf().SetIdx( 0 );
+ rDo.GetInf().SetLen( aNewText.Len() );
+ rDo.GetInf().SetText( aNewText );
+ }
+ else
+ {
+ rDo.GetInf().SetIdx( nOldPos );
+ rDo.GetInf().SetLen( nTmp - nOldPos );
+ }
+
+ rDo.GetInf().SetOut( *pOutSize );
+ aPartSize = pBigFont->GetTextSize( rDo.GetInf() );
+ nKana += rDo.GetInf().GetKanaDiff();
+ rDo.GetInf().SetOut( *pOldOut );
+ if( nSpaceAdd )
+ aPartSize.Width() += nSpaceAdd * ( nTmp - nOldPos );
+ if( nTmpKern && nPos < nMaxPos )
+ aPartSize.Width() += nTmpKern;
+ rDo.Do();
+ aStartPos = rDo.GetInf().GetPos();
+ nOldPos = nTmp;
+ }
+
+ while( nTmp < nPos && CH_BLANK != rOldText.GetChar( nTmp ) )
+ ++nTmp;
+ }
+ else
+ nTmp = nPos;
+ if( nTmp > nOldPos )
+ {
+ // #107816#, #i14820#
+ if( bCaseMapLengthDiffers )
+ {
+ // Build an own 'changed' string for the given part of the
+ // source string and use it. That new string may differ in length
+ // from the source string.
+ const XubString aSnippet( rOldText, nOldPos, nTmp - nOldPos);
+ aNewText = CalcCaseMap( aSnippet );
+ aCapInf.nIdx = nOldPos;
+ aCapInf.nLen = nTmp - nOldPos;
+ rDo.GetInf().SetIdx( 0 );
+ rDo.GetInf().SetLen( aNewText.Len() );
+ rDo.GetInf().SetText( aNewText );
+ }
+ else
+ {
+ rDo.GetInf().SetIdx( nOldPos );
+ rDo.GetInf().SetLen( nTmp - nOldPos );
+ }
+
+ rDo.GetInf().SetOut( *pOutSize );
+ aPartSize = pBigFont->GetTextSize( rDo.GetInf() );
+ nKana += rDo.GetInf().GetKanaDiff();
+ rDo.GetInf().SetOut( *pOldOut );
+ if( !bWordWise && rDo.GetInf().GetSpace() )
+ {
+ for( xub_StrLen nI = nOldPos; nI < nPos; ++nI )
+ {
+ if( CH_BLANK == rOldText.GetChar( nI ) )
+ aPartSize.Width() += nSpaceAdd;
+ }
+ }
+ if( nTmpKern && nPos < nMaxPos )
+ aPartSize.Width() += nTmpKern;
+ rDo.Do();
+ nOldPos = nTmp;
+ }
+ } while( nOldPos != nPos );
+ }
+ nPos = (xub_StrLen)pBreakIt->GetBreakIter()->endOfCharBlock( rOldText, nPos,
+ pBreakIt->GetLocale( eLng ), CharType::LOWERCASE_LETTER);
+ if( nPos == STRING_LEN || nPos > nMaxPos )
+ nPos = nMaxPos;
+ OSL_ENSURE( nPos, "endOfCharBlock not implemented?" );
+#if OSL_DEBUG_LEVEL > 1
+ if( !nPos )
+ nPos = nMaxPos;
+#endif
+ }
+
+ // Aufraeumen:
+ if( pBigFont != pOldLast )
+ delete pBigFontAccess;
+
+ if( bTextLines )
+ {
+ if( rDo.GetInf().GetDrawSpace() )
+ {
+ pLastFont = pSpaceFont;
+ pLastFont->SetDevFont( rDo.GetInf().GetShell(), rDo.GetOut() );
+ ( (SwDoDrawCapital&) rDo ).DrawSpace( aStartPos );
+ }
+ if ( bWordWise )
+ delete pSpaceFontAccess;
+ }
+ pLastFont = pOldLast;
+ pLastFont->SetDevFont( rDo.GetInf().GetShell(), rDo.GetOut() );
+
+ delete pSmallFontAccess;
+ rDo.GetInf().SetText( rOldText );
+ rDo.GetInf().SetKanaDiff( nKana );
+}
+
+// JP 22.8.2001 - global optimization off - Bug 91245 / 91223
+#ifdef _MSC_VER
+#pragma optimize("g",on)
+#endif
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/txtnode/modeltoviewhelper.cxx b/sw/source/core/txtnode/modeltoviewhelper.cxx
new file mode 100644
index 000000000000..8d4940b1ec67
--- /dev/null
+++ b/sw/source/core/txtnode/modeltoviewhelper.cxx
@@ -0,0 +1,123 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+#include <modeltoviewhelper.hxx>
+
+namespace ModelToViewHelper
+{
+
+/** Converts a model position into a view position
+*/
+sal_uInt32 ConvertToViewPosition( const ConversionMap* pMap, sal_uInt32 nModelPos )
+{
+ sal_uInt32 nRet = nModelPos;
+
+ if ( !pMap )
+ return nRet;
+
+ // Search for entry behind nPos:
+ ConversionMap::const_iterator aIter;
+ for ( aIter = pMap->begin(); aIter != pMap->end(); ++aIter )
+ {
+ if ( (*aIter).first >= nModelPos )
+ {
+ const sal_uInt32 nPosModel = (*aIter).first;
+ const sal_uInt32 nPosExpand = (*aIter).second;
+
+ const sal_uInt32 nDistToNextModel = nPosModel - nModelPos;
+ nRet = nPosExpand - nDistToNextModel;
+ break;
+ }
+ }
+
+ return nRet;
+}
+
+
+/** Converts a view position into a model position
+*/
+ModelPosition ConvertToModelPosition( const ConversionMap* pMap, sal_uInt32 nViewPos )
+{
+ ModelPosition aRet;
+ aRet.mnPos = nViewPos;
+
+ if ( !pMap )
+ return aRet;
+
+ // Search for entry behind nPos:
+ ConversionMap::const_iterator aIter;
+ for ( aIter = pMap->begin(); aIter != pMap->end(); ++aIter )
+ {
+ if ( (*aIter).second > nViewPos )
+ {
+ const sal_uInt32 nPosModel = (*aIter).first;
+ const sal_uInt32 nPosExpand = (*aIter).second;
+
+ // If nViewPos is in front of first field, we are finished.
+ if ( aIter == pMap->begin() )
+ break;
+
+ --aIter;
+
+ // nPrevPosModel is the field position
+ const sal_uInt32 nPrevPosModel = (*aIter).first;
+ const sal_uInt32 nPrevPosExpand = (*aIter).second;
+
+ const sal_uInt32 nLengthModel = nPosModel - nPrevPosModel;
+ const sal_uInt32 nLengthExpand = nPosExpand - nPrevPosExpand;
+
+ const sal_uInt32 nFieldLengthExpand = nLengthExpand - nLengthModel + 1;
+ const sal_uInt32 nFieldEndExpand = nPrevPosExpand + nFieldLengthExpand;
+
+ // Check if nPos is outside of field:
+ if ( nFieldEndExpand <= nViewPos )
+ {
+ // nPos is outside of field:
+ const sal_uInt32 nDistToField = nViewPos - nFieldEndExpand + 1;
+ aRet.mnPos = nPrevPosModel + nDistToField;
+ }
+ else
+ {
+ // nViewPos is inside a field:
+ aRet.mnPos = nPrevPosModel;
+ aRet.mnSubPos = nViewPos - nPrevPosExpand;
+ aRet.mbIsField = true;
+ }
+
+ break;
+ }
+ }
+
+ return aRet;
+}
+
+} // namespace ModelToViewStringConverter end
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/txtnode/ndhints.cxx b/sw/source/core/txtnode/ndhints.cxx
new file mode 100644
index 000000000000..d0e0974f2ed0
--- /dev/null
+++ b/sw/source/core/txtnode/ndhints.cxx
@@ -0,0 +1,431 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+#include "txatbase.hxx"
+#include "ndhints.hxx"
+#include <txtatr.hxx>
+
+#if OSL_DEBUG_LEVEL > 1
+#include <pam.hxx>
+#endif
+
+
+_SV_IMPL_SORTAR_ALG( SwpHtStart, SwTxtAttr* )
+_SV_IMPL_SORTAR_ALG( SwpHtEnd, SwTxtAttr* )
+
+inline void DumpHints(const SwpHtStart &, const SwpHtEnd &) { }
+
+/*************************************************************************
+ * inline IsEqual()
+ *************************************************************************/
+
+inline sal_Bool IsEqual( const SwTxtAttr &rHt1, const SwTxtAttr &rHt2 )
+{
+ return (long)(&rHt1) == (long)(&rHt2);
+}
+
+/*************************************************************************
+ * IsLessStart()
+ *************************************************************************/
+
+// SV_IMPL_OP_PTRARR_SORT( SwpHtStart, SwTxtAttr* )
+// kein SV_IMPL_PTRARR_SORT( name,ArrElement )
+// unser SEEK_PTR_TO_OBJECT_NOTL( name,ArrElement )
+
+// Sortierreihenfolge: Start, Ende (umgekehrt!), Which-Wert (umgekehrt!),
+// als letztes die Adresse selbst
+
+static sal_Bool lcl_IsLessStart( const SwTxtAttr &rHt1, const SwTxtAttr &rHt2 )
+{
+ if ( *rHt1.GetStart() == *rHt2.GetStart() )
+ {
+ const xub_StrLen nHt1 = *rHt1.GetAnyEnd();
+ const xub_StrLen nHt2 = *rHt2.GetAnyEnd();
+ if ( nHt1 == nHt2 )
+ {
+ const sal_uInt16 nWhich1 = rHt1.Which();
+ const sal_uInt16 nWhich2 = rHt2.Which();
+ if ( nWhich1 == nWhich2 )
+ {
+ if ( RES_TXTATR_CHARFMT == nWhich1 )
+ {
+ const sal_uInt16 nS1 = static_cast<const SwTxtCharFmt&>(rHt1).GetSortNumber();
+ const sal_uInt16 nS2 = static_cast<const SwTxtCharFmt&>(rHt2).GetSortNumber();
+ OSL_ENSURE( nS1 != nS2, "AUTOSTYLES: lcl_IsLessStart trouble" );
+ if ( nS1 != nS2 ) // robust
+ return nS1 < nS2;
+ }
+
+ return (long)&rHt1 < (long)&rHt2;
+ }
+ // order is important! for requirements see hintids.hxx
+ return ( nWhich1 > nWhich2 );
+ }
+ return ( nHt1 > nHt2 );
+ }
+ return ( *rHt1.GetStart() < *rHt2.GetStart() );
+}
+
+/*************************************************************************
+ * inline IsLessEnd()
+ *************************************************************************/
+
+// Zuerst nach Ende danach nach Ptr
+static sal_Bool lcl_IsLessEnd( const SwTxtAttr &rHt1, const SwTxtAttr &rHt2 )
+{
+ const xub_StrLen nHt1 = *rHt1.GetAnyEnd();
+ const xub_StrLen nHt2 = *rHt2.GetAnyEnd();
+ if ( nHt1 == nHt2 )
+ {
+ if ( *rHt1.GetStart() == *rHt2.GetStart() )
+ {
+ const sal_uInt16 nWhich1 = rHt1.Which();
+ const sal_uInt16 nWhich2 = rHt2.Which();
+ if ( nWhich1 == nWhich2 )
+ {
+ if ( RES_TXTATR_CHARFMT == nWhich1 )
+ {
+ const sal_uInt16 nS1 = static_cast<const SwTxtCharFmt&>(rHt1).GetSortNumber();
+ const sal_uInt16 nS2 = static_cast<const SwTxtCharFmt&>(rHt2).GetSortNumber();
+ OSL_ENSURE( nS1 != nS2, "AUTOSTYLES: lcl_IsLessEnd trouble" );
+ if ( nS1 != nS2 ) // robust
+ return nS1 > nS2;
+ }
+
+ return (long)&rHt1 > (long)&rHt2;
+ }
+ // order is important! for requirements see hintids.hxx
+ return ( nWhich1 < nWhich2 );
+ }
+ else
+ return ( *rHt1.GetStart() > *rHt2.GetStart() );
+ }
+ return ( nHt1 < nHt2 );
+}
+
+/*************************************************************************
+ * SwpHtStart::Seek_Entry()
+ *************************************************************************/
+
+sal_Bool SwpHtStart::Seek_Entry( const SwTxtAttr *pElement, sal_uInt16 *pPos ) const
+{
+ sal_uInt16 nOben = Count(), nMitte, nUnten = 0;
+ if( nOben > 0 )
+ {
+ nOben--;
+ while( nUnten <= nOben )
+ {
+ nMitte = nUnten + ( nOben - nUnten ) / 2;
+ const SwTxtAttr *pMitte = (*this)[nMitte];
+ if( IsEqual( *pMitte, *pElement ) )
+ {
+ *pPos = nMitte;
+ return sal_True;
+ }
+ else
+ if( lcl_IsLessStart( *pMitte, *pElement ) )
+ nUnten = nMitte + 1;
+ else
+ if( nMitte == 0 )
+ {
+ *pPos = nUnten;
+ return sal_False;
+ }
+ else
+ nOben = nMitte - 1;
+ }
+ }
+ *pPos = nUnten;
+ return sal_False;
+}
+
+/*************************************************************************
+ * SwpHtEnd::Seek_Entry()
+ *************************************************************************/
+
+sal_Bool SwpHtEnd::Seek_Entry( const SwTxtAttr *pElement, sal_uInt16 *pPos ) const
+{
+ sal_uInt16 nOben = Count(), nMitte, nUnten = 0;
+ if( nOben > 0 )
+ {
+ nOben--;
+ while( nUnten <= nOben )
+ {
+ nMitte = nUnten + ( nOben - nUnten ) / 2;
+ const SwTxtAttr *pMitte = (*this)[nMitte];
+ if( IsEqual( *pMitte, *pElement ) )
+ {
+ *pPos = nMitte;
+ return sal_True;
+ }
+ else
+ if( lcl_IsLessEnd( *pMitte, *pElement ) )
+ nUnten = nMitte + 1;
+ else
+ if( nMitte == 0 )
+ {
+ *pPos = nUnten;
+ return sal_False;
+ }
+ else
+ nOben = nMitte - 1;
+ }
+ }
+ *pPos = nUnten;
+ return sal_False;
+}
+
+/*************************************************************************
+ * class SwpHintsArr
+ *************************************************************************/
+
+void SwpHintsArray::Insert( const SwTxtAttr *pHt )
+{
+ Resort();
+#if OSL_DEBUG_LEVEL > 1
+ sal_uInt16 nPos;
+ OSL_ENSURE(!m_HintStarts.Seek_Entry( pHt, &nPos ),
+ "Insert: hint already in HtStart");
+ OSL_ENSURE(!m_HintEnds.Seek_Entry( pHt, &nPos ),
+ "Insert: hint already in HtEnd");
+#endif
+ m_HintStarts.Insert( pHt );
+ m_HintEnds.Insert( pHt );
+}
+
+void SwpHintsArray::DeleteAtPos( const sal_uInt16 nPos )
+{
+ // optimization: nPos is the position in the Starts array
+ const SwTxtAttr *pHt = m_HintStarts[ nPos ];
+ m_HintStarts.Remove( nPos );
+
+ Resort();
+
+ sal_uInt16 nEndPos;
+ m_HintEnds.Seek_Entry( pHt, &nEndPos );
+ m_HintEnds.Remove( nEndPos );
+}
+
+#if OSL_DEBUG_LEVEL > 1
+
+/*************************************************************************
+ * SwpHintsArray::Check()
+ *************************************************************************/
+
+
+#define CHECK_ERR(cond, text) \
+ if(!(cond)) \
+ { \
+ OSL_ENSURE(!this, text); \
+ DumpHints(m_HintStarts, m_HintEnds); \
+ return !(const_cast<SwpHintsArray*>(this))->Resort(); \
+ }
+
+bool SwpHintsArray::Check() const
+{
+ // 1) gleiche Anzahl in beiden Arrays
+ CHECK_ERR( m_HintStarts.Count() == m_HintEnds.Count(),
+ "HintsCheck: wrong sizes" );
+ xub_StrLen nLastStart = 0;
+ xub_StrLen nLastEnd = 0;
+
+ const SwTxtAttr *pLastStart = 0;
+ const SwTxtAttr *pLastEnd = 0;
+
+ for( sal_uInt16 i = 0; i < Count(); ++i )
+ {
+ // --- Start-Kontrolle ---
+
+ // 2a) gueltiger Pointer? vgl. DELETEFF
+ const SwTxtAttr *pHt = m_HintStarts[i];
+ CHECK_ERR( 0xFF != *(unsigned char*)pHt, "HintsCheck: start ptr was deleted" );
+
+ // 3a) Stimmt die Start-Sortierung?
+ xub_StrLen nIdx = *pHt->GetStart();
+ CHECK_ERR( nIdx >= nLastStart, "HintsCheck: starts are unsorted" );
+
+ // 4a) IsLessStart-Konsistenz
+ if( pLastStart )
+ CHECK_ERR( lcl_IsLessStart( *pLastStart, *pHt ), "HintsCheck: IsLastStart" );
+
+ nLastStart = nIdx;
+ pLastStart = pHt;
+
+ // --- End-Kontrolle ---
+
+ // 2b) gueltiger Pointer? vgl. DELETEFF
+ const SwTxtAttr *pHtEnd = m_HintEnds[i];
+ CHECK_ERR( 0xFF != *(unsigned char*)pHtEnd, "HintsCheck: end ptr was deleted" );
+
+ // 3b) Stimmt die End-Sortierung?
+ nIdx = *pHtEnd->GetAnyEnd();
+ CHECK_ERR( nIdx >= nLastEnd, "HintsCheck: ends are unsorted" );
+ nLastEnd = nIdx;
+
+ // 4b) IsLessEnd-Konsistenz
+ if( pLastEnd )
+ CHECK_ERR( lcl_IsLessEnd( *pLastEnd, *pHtEnd ), "HintsCheck: IsLastEnd" );
+
+ nLastEnd = nIdx;
+ pLastEnd = pHtEnd;
+
+ // --- Ueberkreuzungen ---
+
+ // 5) gleiche Pointer in beiden Arrays
+ if( !m_HintStarts.Seek_Entry( pHt, &nIdx ) )
+ nIdx = STRING_LEN;
+
+ CHECK_ERR( STRING_LEN != nIdx, "HintsCheck: no GetStartOf" );
+
+ // 6) gleiche Pointer in beiden Arrays
+ if( !m_HintEnds.Seek_Entry( pHt, &nIdx ) )
+ nIdx = STRING_LEN;
+
+ CHECK_ERR( STRING_LEN != nIdx, "HintsCheck: no GetEndOf" );
+
+ // 7a) character attributes in array?
+ sal_uInt16 nWhich = pHt->Which();
+ CHECK_ERR( !isCHRATR(nWhich),
+ "HintsCheck: Character attribute in start array" );
+
+ // 7b) character attributes in array?
+ nWhich = pHtEnd->Which();
+ CHECK_ERR( !isCHRATR(nWhich),
+ "HintsCheck: Character attribute in end array" );
+
+ // 8) style portion check
+ const SwTxtAttr* pHtThis = m_HintStarts[i];
+ const SwTxtAttr* pHtLast = i > 0 ? m_HintStarts[i-1] : 0;
+ CHECK_ERR( 0 == i ||
+ ( RES_TXTATR_CHARFMT != pHtLast->Which() && RES_TXTATR_AUTOFMT != pHtLast->Which() ) ||
+ ( RES_TXTATR_CHARFMT != pHtThis->Which() && RES_TXTATR_AUTOFMT != pHtThis->Which() ) ||
+ ( *pHtThis->GetStart() >= *pHtLast->GetEnd() ) ||
+ ( ( ( (*pHtThis->GetStart() == *pHtLast->GetStart())
+ && (*pHtThis->GetEnd() == *pHtLast->GetEnd())
+ ) // same range
+ || (*pHtThis->GetStart() == *pHtThis->GetEnd())
+ )
+ && ( (pHtThis->Which() != RES_TXTATR_AUTOFMT)
+ || (pHtLast->Which() != RES_TXTATR_AUTOFMT)
+ ) // never two AUTOFMT on same range
+ ),
+ "HintsCheck: Portion inconsistency. "
+ "This can be temporarily ok during undo operations" );
+
+ // 9) nesting portion check
+ if (pHtThis->IsNesting())
+ {
+ for ( sal_uInt16 j = 0; j < Count(); ++j )
+ {
+ SwTxtAttr const * const pOther( m_HintStarts[j] );
+ if ( pOther->IsNesting() && (i != j) )
+ {
+ SwComparePosition cmp = ComparePosition(
+ *pHtThis->GetStart(), *pHtThis->GetEnd(),
+ *pOther->GetStart(), *pOther->GetEnd());
+ CHECK_ERR( (POS_OVERLAP_BEFORE != cmp) &&
+ (POS_OVERLAP_BEHIND != cmp),
+ "HintsCheck: overlapping nesting hints!!!" );
+ }
+ }
+ }
+
+ // 10) dummy char check (unfortunately cannot check SwTxtNode::m_Text)
+ if (pHtThis->HasDummyChar())
+ {
+ for ( sal_uInt16 j = 0; j < i; ++j )
+ {
+ SwTxtAttr const * const pOther( m_HintStarts[j] );
+ if (pOther->HasDummyChar())
+ {
+ CHECK_ERR( (*pOther->GetStart() != *pHtThis->GetStart()),
+ "HintsCheck: multiple hints claim same CH_TXTATR!");
+ }
+ }
+ }
+ }
+ return true;
+}
+
+#endif /* PRODUCT */
+
+/*************************************************************************
+ * SwpHintsArray::Resort()
+ *************************************************************************/
+
+// Resort() wird vor jedem Insert und Delete gerufen.
+// Wenn Textmasse geloescht wird, so werden die Indizes in
+// ndtxt.cxx angepasst. Leider erfolgt noch keine Neusortierung
+// auf gleichen Positionen.
+
+bool SwpHintsArray::Resort()
+{
+ bool bResort = false;
+ const SwTxtAttr *pLast = 0;
+ sal_uInt16 i;
+
+ for ( i = 0; i < m_HintStarts.Count(); ++i )
+ {
+ const SwTxtAttr *pHt = m_HintStarts[i];
+ if( pLast && !lcl_IsLessStart( *pLast, *pHt ) )
+ {
+ m_HintStarts.Remove( i );
+ m_HintStarts.Insert( pHt );
+ pHt = m_HintStarts[i];
+ if ( pHt != pLast )
+ --i;
+ bResort = true;
+ }
+ pLast = pHt;
+ }
+
+ pLast = 0;
+ for ( i = 0; i < m_HintEnds.Count(); ++i )
+ {
+ const SwTxtAttr *pHt = m_HintEnds[i];
+ if( pLast && !lcl_IsLessEnd( *pLast, *pHt ) )
+ {
+ m_HintEnds.Remove( i );
+ m_HintEnds.Insert( pHt );
+ pHt = m_HintEnds[i]; // normalerweise == pLast
+ // Wenn die Unordnung etwas groesser ist (24200),
+ // muessen wir Position i erneut vergleichen.
+ if ( pLast != pHt )
+ --i;
+ bResort = true;
+ }
+ pLast = pHt;
+ }
+ return bResort;
+}
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/txtnode/ndtxt.cxx b/sw/source/core/txtnode/ndtxt.cxx
new file mode 100644
index 000000000000..52e99ff519e8
--- /dev/null
+++ b/sw/source/core/txtnode/ndtxt.cxx
@@ -0,0 +1,4829 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+#include <hintids.hxx>
+#include <hints.hxx>
+
+#include <editeng/fontitem.hxx>
+#include <editeng/brkitem.hxx>
+#include <editeng/escpitem.hxx>
+#include <editeng/lrspitem.hxx>
+#include <editeng/tstpitem.hxx>
+#include <svl/urihelper.hxx>
+#ifndef _SVSTDARR_HXX
+#define _SVSTDARR_ULONGS
+#include <svl/svstdarr.hxx>
+#endif
+#include <svl/ctloptions.hxx>
+#include <swmodule.hxx>
+#include <txtfld.hxx>
+#include <txtinet.hxx>
+#include <fmtinfmt.hxx>
+#include <fmtpdsc.hxx>
+#include <txtatr.hxx>
+#include <fmtrfmrk.hxx>
+#include <txttxmrk.hxx>
+#include <fchrfmt.hxx>
+#include <txtftn.hxx>
+#include <fmtflcnt.hxx>
+#include <fmtfld.hxx>
+#include <frmatr.hxx>
+#include <charatr.hxx>
+#include <ftnidx.hxx>
+#include <ftninfo.hxx>
+#include <fmtftn.hxx>
+#include <fmtmeta.hxx>
+#include <charfmt.hxx>
+#include <ndtxt.hxx>
+#include <doc.hxx>
+#include <IDocumentUndoRedo.hxx>
+#include <docary.hxx>
+#include <pam.hxx> // fuer SwPosition
+#include <fldbas.hxx>
+#include <paratr.hxx>
+#include <txtfrm.hxx>
+#include <ftnfrm.hxx>
+#include <ftnboss.hxx>
+#include <rootfrm.hxx>
+#include <pagedesc.hxx> // fuer SwPageDesc
+#include <expfld.hxx> // fuer SwTblField
+#include <section.hxx> // fuer SwSection
+#include <mvsave.hxx>
+#include <swcache.hxx>
+#include <SwGrammarMarkUp.hxx>
+#include <dcontact.hxx>
+#include <redline.hxx>
+#include <doctxm.hxx>
+#include <IMark.hxx>
+#include <scriptinfo.hxx>
+#include <istyleaccess.hxx>
+#include <SwStyleNameMapper.hxx>
+#include <numrule.hxx>
+#include <swtable.hxx>
+#include <docsh.hxx>
+#include <SwNodeNum.hxx>
+#include <svl/intitem.hxx>
+#include <list.hxx>
+#include <switerator.hxx>
+#include <attrhint.hxx>
+
+
+using namespace ::com::sun::star;
+
+
+SV_DECL_PTRARR( TmpHints, SwTxtAttr*, 0, 4 )
+
+TYPEINIT1( SwTxtNode, SwCntntNode )
+
+SV_DECL_PTRARR(SwpHts,SwTxtAttr*,1,1)
+
+// Leider ist das SwpHints nicht ganz wasserdicht:
+// Jeder darf an den Hints rumfummeln, ohne die Sortierreihenfolge
+// und Verkettung sicherstellen zu muessen.
+#if OSL_DEBUG_LEVEL > 1
+#define CHECK_SWPHINTS(pNd) { if( pNd->GetpSwpHints() && \
+ !pNd->GetDoc()->IsInReading() ) \
+ pNd->GetpSwpHints()->Check(); }
+#else
+#define CHECK_SWPHINTS(pNd)
+#endif
+
+SwTxtNode *SwNodes::MakeTxtNode( const SwNodeIndex & rWhere,
+ SwTxtFmtColl *pColl,
+ SwAttrSet* pAutoAttr )
+{
+ OSL_ENSURE( pColl, "Collectionpointer ist 0." );
+
+ SwTxtNode *pNode = new SwTxtNode( rWhere, pColl, pAutoAttr );
+
+ SwNodeIndex aIdx( *pNode );
+
+ // #125329#
+ // call method <UpdateOutlineNode(..)> only for the document nodes array
+ if ( IsDocNodes() )
+ UpdateOutlineNode(*pNode);
+
+ //Wenn es noch kein Layout gibt oder in einer versteckten Section
+ // stehen, brauchen wir uns um das MakeFrms nicht bemuehen.
+ const SwSectionNode* pSectNd;
+ if( !GetDoc()->GetCurrentViewShell() || //swmod 071108//swmod 071225
+ ( 0 != (pSectNd = pNode->FindSectionNode()) &&
+ pSectNd->GetSection().IsHiddenFlag() ))
+ return pNode;
+
+ SwNodeIndex aTmp( rWhere );
+ do {
+ // max. 2 Durchlaeufe:
+ // 1. den Nachfolger nehmen
+ // 2. den Vorgaenger
+
+ SwNode * pNd = & aTmp.GetNode();
+ switch (pNd->GetNodeType())
+ {
+ case ND_TABLENODE:
+ ((SwTableNode*)pNd)->MakeFrms( aIdx );
+ return pNode;
+
+ case ND_SECTIONNODE:
+ if( ((SwSectionNode*)pNd)->GetSection().IsHidden() ||
+ ((SwSectionNode*)pNd)->IsCntntHidden() )
+ {
+ SwNodeIndex aTmpIdx( *pNode );
+ pNd = FindPrvNxtFrmNode( aTmpIdx, pNode );
+ if( !pNd )
+ return pNode;
+ aTmp = *pNd;
+ break;
+ }
+ ((SwSectionNode*)pNd)->MakeFrms( aIdx );
+ return pNode;
+
+ case ND_TEXTNODE:
+ case ND_GRFNODE:
+ case ND_OLENODE:
+ ((SwCntntNode*)pNd)->MakeFrms( *pNode );
+ return pNode;
+
+ case ND_ENDNODE:
+ if( pNd->StartOfSectionNode()->IsSectionNode() &&
+ aTmp.GetIndex() < rWhere.GetIndex() )
+ {
+ if( pNd->StartOfSectionNode()->GetSectionNode()->GetSection().IsHiddenFlag())
+ {
+ if( !GoPrevSection( &aTmp, sal_True, sal_False ) ||
+ aTmp.GetNode().FindTableNode() !=
+ pNode->FindTableNode() )
+ return pNode; // schade, das wars
+ }
+ else
+ aTmp = *pNd->StartOfSectionNode();
+ break;
+ }
+ else if( pNd->StartOfSectionNode()->IsTableNode() &&
+ aTmp.GetIndex() < rWhere.GetIndex() )
+ {
+ // wir stehen hinter einem TabellenNode
+ aTmp = *pNd->StartOfSectionNode();
+ break;
+ }
+ // kein break !!!
+ default:
+ if( rWhere == aTmp )
+ aTmp -= 2;
+ else
+ return pNode;
+ break;
+ }
+ } while( sal_True );
+}
+
+// --------------------
+// SwTxtNode
+// --------------------
+
+SwTxtNode::SwTxtNode( const SwNodeIndex &rWhere,
+ SwTxtFmtColl *pTxtColl,
+ const SfxItemSet* pAutoAttr )
+ : SwCntntNode( rWhere, ND_TEXTNODE, pTxtColl ),
+ m_pSwpHints( 0 ),
+ mpNodeNum( 0 ),
+ m_bLastOutlineState( false ),
+ m_bNotifiable( false ),
+ // #i70748#
+ mbEmptyListStyleSetDueToSetOutlineLevelAttr( false ),
+ mbInSetOrResetAttr( false ),
+ mpList( 0 )
+{
+ InitSwParaStatistics( true );
+
+ // soll eine Harte-Attributierung gesetzt werden?
+ if( pAutoAttr )
+ SetAttr( *pAutoAttr );
+
+ if ( !IsInList() && GetNumRule() && GetListId().Len() > 0 )
+ {
+ // #i101516#
+ // apply paragraph style's assigned outline style list level as
+ // list level of the paragraph, if it has none set already.
+ if ( !HasAttrListLevel() &&
+ pTxtColl && pTxtColl->IsAssignedToListLevelOfOutlineStyle() )
+ {
+ SetAttrListLevel( pTxtColl->GetAssignedOutlineStyleLevel() );
+ }
+ AddToList();
+ }
+ GetNodes().UpdateOutlineNode(*this);
+
+ m_bNotifiable = true;
+
+ m_bContainsHiddenChars = m_bHiddenCharsHidePara = false;
+ m_bRecalcHiddenCharFlags = true;
+}
+
+SwTxtNode::~SwTxtNode()
+{
+ // delete loescht nur die Pointer, nicht die Arrayelemente!
+ if ( m_pSwpHints )
+ {
+ // damit Attribute die ihren Inhalt entfernen nicht doppelt
+ // geloescht werden.
+ SwpHints* pTmpHints = m_pSwpHints;
+ m_pSwpHints = 0;
+
+ for( sal_uInt16 j = pTmpHints->Count(); j; )
+ // erst muss das Attribut aus dem Array entfernt werden,
+ // denn sonst wuerde es sich selbst loeschen (Felder) !!!!
+ DestroyAttr( pTmpHints->GetTextHint( --j ) );
+
+ delete pTmpHints;
+ }
+
+ RemoveFromList();
+
+ InitSwParaStatistics( false );
+}
+
+SwCntntFrm *SwTxtNode::MakeFrm( SwFrm* pSib )
+{
+ SwCntntFrm *pFrm = new SwTxtFrm( this, pSib );
+ return pFrm;
+}
+
+xub_StrLen SwTxtNode::Len() const
+{
+ return m_Text.Len();
+}
+
+/*---------------------------------------------------------------------------
+ * lcl_ChangeFtnRef
+ * After a split node, it's necessary to actualize the ref-pointer of the
+ * ftnfrms.
+ * --------------------------------------------------------------------------*/
+
+void lcl_ChangeFtnRef( SwTxtNode &rNode )
+{
+ SwpHints *pSwpHints = rNode.GetpSwpHints();
+ if( pSwpHints && rNode.GetDoc()->GetCurrentViewShell() ) //swmod 071108//swmod 071225
+ {
+ SwTxtAttr* pHt;
+ SwCntntFrm* pFrm = NULL;
+ // OD 07.11.2002 #104840# - local variable to remember first footnote
+ // of node <rNode> in order to invalidate position of its first content.
+ // Thus, in its <MakeAll()> it will checked its position relative to its reference.
+ SwFtnFrm* pFirstFtnOfNode = 0;
+ for( sal_uInt16 j = pSwpHints->Count(); j; )
+ {
+ pHt = pSwpHints->GetTextHint(--j);
+ if (RES_TXTATR_FTN == pHt->Which())
+ {
+ if( !pFrm )
+ {
+ pFrm = SwIterator<SwCntntFrm,SwTxtNode>::FirstElement( rNode );
+ if( !pFrm )
+ return;
+ }
+ SwTxtFtn *pAttr = (SwTxtFtn*)pHt;
+ OSL_ENSURE( pAttr->GetStartNode(), "FtnAtr ohne StartNode." );
+ SwNodeIndex aIdx( *pAttr->GetStartNode(), 1 );
+ SwCntntNode *pNd = aIdx.GetNode().GetCntntNode();
+ if ( !pNd )
+ pNd = pFrm->GetAttrSet()->GetDoc()->
+ GetNodes().GoNextSection( &aIdx, sal_True, sal_False );
+ if ( !pNd )
+ continue;
+
+ SwIterator<SwCntntFrm,SwCntntNode> aIter( *pNd );
+ SwCntntFrm* pCntnt = aIter.First();
+ if( pCntnt )
+ {
+ OSL_ENSURE( pCntnt->getRootFrm() == pFrm->getRootFrm(),
+ "lcl_ChangeFtnRef: Layout double?" );
+ SwFtnFrm *pFtn = pCntnt->FindFtnFrm();
+ if( pFtn && pFtn->GetAttr() == pAttr )
+ {
+ while( pFtn->GetMaster() )
+ pFtn = pFtn->GetMaster();
+ // #104840# - remember footnote frame
+ pFirstFtnOfNode = pFtn;
+ while ( pFtn )
+ {
+ pFtn->SetRef( pFrm );
+ pFtn = pFtn->GetFollow();
+ ((SwTxtFrm*)pFrm)->SetFtn( sal_True );
+ }
+ }
+#if OSL_DEBUG_LEVEL > 1
+ while( 0 != (pCntnt = aIter.Next()) )
+ {
+ SwFtnFrm *pDbgFtn = pCntnt->FindFtnFrm();
+ OSL_ENSURE( !pDbgFtn || pDbgFtn->GetRef() == pFrm,
+ "lcl_ChangeFtnRef: Who's that guy?" );
+ }
+#endif
+ }
+ }
+ } // end of for-loop on <SwpHints>
+ // #104840# - invalidate
+ if ( pFirstFtnOfNode )
+ {
+ SwCntntFrm* pCntnt = pFirstFtnOfNode->ContainsCntnt();
+ if ( pCntnt )
+ {
+ pCntnt->_InvalidatePos();
+ }
+ }
+ }
+}
+
+SwCntntNode *SwTxtNode::SplitCntntNode( const SwPosition &rPos )
+{
+ bool parentIsOutline = IsOutline();
+
+ // lege den Node "vor" mir an
+ const xub_StrLen nSplitPos = rPos.nContent.GetIndex();
+ const xub_StrLen nTxtLen = m_Text.Len();
+ SwTxtNode* const pNode =
+ _MakeNewTxtNode( rPos.nNode, sal_False, nSplitPos==nTxtLen );
+
+ // the first paragraph gets the XmlId,
+ // _except_ if it is empty and the second is not empty
+ if (nSplitPos != 0) {
+ pNode->RegisterAsCopyOf(*this, true);
+ if (nSplitPos == nTxtLen)
+ {
+ this->RemoveMetadataReference();
+ // NB: SwUndoSplitNode will call pNode->JoinNext,
+ // which is sufficient even in this case!
+ }
+ }
+
+ ResetAttr( RES_PARATR_LIST_ISRESTART );
+ ResetAttr( RES_PARATR_LIST_RESTARTVALUE );
+ ResetAttr( RES_PARATR_LIST_ISCOUNTED );
+ if ( GetNumRule() == 0 || (parentIsOutline && !IsOutline()) )
+ {
+ ResetAttr( RES_PARATR_LIST_ID );
+ ResetAttr( RES_PARATR_LIST_LEVEL );
+ }
+
+ if ( GetDepends() && m_Text.Len() && (nTxtLen / 2) < nSplitPos )
+ {
+// JP 25.04.95: Optimierung fuer SplitNode:
+// Wird am Ende vom Node gesplittet, dann verschiebe die
+// Frames vom akt. auf den neuen und erzeuge fuer den akt.
+// neue. Dadurch entfaellt das neu aufbauen vom Layout.
+
+ LockModify(); // Benachrichtigungen abschalten
+
+ // werden FlyFrames mit verschoben, so muessen diese nicht ihre
+ // Frames zerstoeren. Im SwTxtFly::SetAnchor wird es abgefragt!
+ if ( HasHints() )
+ {
+ pNode->GetOrCreateSwpHints().SetInSplitNode(true);
+ }
+
+ //Ersten Teil des Inhalts in den neuen Node uebertragen und
+ //im alten Node loeschen.
+ SwIndex aIdx( this );
+ CutText( pNode, aIdx, nSplitPos );
+
+ if( GetWrong() )
+ {
+ pNode->SetWrong( GetWrong()->SplitList( nSplitPos ) );
+ }
+ SetWrongDirty( true );
+
+ if( GetGrammarCheck() )
+ {
+ pNode->SetGrammarCheck( GetGrammarCheck()->SplitGrammarList( nSplitPos ) );
+ }
+ SetGrammarCheckDirty( true );
+
+ SetWordCountDirty( true );
+
+ // SMARTTAGS
+ if( GetSmartTags() )
+ {
+ pNode->SetSmartTags( GetSmartTags()->SplitList( nSplitPos ) );
+ }
+ SetSmartTagDirty( true );
+
+ if ( pNode->HasHints() )
+ {
+ if ( pNode->m_pSwpHints->CanBeDeleted() )
+ {
+ delete pNode->m_pSwpHints;
+ pNode->m_pSwpHints = 0;
+ }
+ else
+ {
+ pNode->m_pSwpHints->SetInSplitNode(false);
+ }
+
+ // alle zeichengebundenen Rahmen, die im neuen Absatz laden
+ // muessen aus den alten Frame entfernt werden:
+ // JP 01.10.96: alle leeren und nicht zu expandierenden
+ // Attribute loeschen
+ if ( HasHints() )
+ {
+ for ( sal_uInt16 j = m_pSwpHints->Count(); j; )
+ {
+ SwTxtAttr* const pHt = m_pSwpHints->GetTextHint( --j );
+ if ( RES_TXTATR_FLYCNT == pHt ->Which() )
+ {
+ pHt->GetFlyCnt().GetFrmFmt()->DelFrms();
+ }
+ else if ( pHt->DontExpand() )
+ {
+ const xub_StrLen* const pEnd = pHt->GetEnd();
+ if (pEnd && *pHt->GetStart() == *pEnd )
+ {
+ // delete it!
+ m_pSwpHints->DeleteAtPos( j );
+ DestroyAttr( pHt );
+ }
+ }
+ }
+ }
+
+ }
+
+ SwIterator<SwCntntFrm,SwTxtNode> aIter( *this );
+ for( SwCntntFrm* pFrm = aIter.First(); pFrm; pFrm = aIter.Next() )
+ {
+ pFrm->RegisterToNode( *pNode );
+ if( pFrm->IsTxtFrm() && !pFrm->IsFollow() && ((SwTxtFrm*)pFrm)->GetOfst() )
+ ((SwTxtFrm*)pFrm)->SetOfst( 0 );
+ }
+
+ if ( IsInCache() )
+ {
+ SwFrm::GetCache().Delete( this );
+ SetInCache( sal_False );
+ }
+
+ UnlockModify(); // Benachrichtigungen wieder freischalten
+
+ // If there is an accessible layout we must call modify even
+ // with length zero, because we have to notify about the changed
+ // text node.
+ const SwRootFrm *pRootFrm;
+ if ( (nTxtLen != nSplitPos) ||
+ ( (pRootFrm = pNode->GetDoc()->GetCurrentLayout()) != 0 &&
+ pRootFrm->IsAnyShellAccessible() ) ) //swmod 080218
+ {
+ // dann sage den Frames noch, das am Ende etwas "geloescht" wurde
+ if( 1 == nTxtLen - nSplitPos )
+ {
+ SwDelChr aHint( nSplitPos );
+ pNode->NotifyClients( 0, &aHint );
+ }
+ else
+ {
+ SwDelTxt aHint( nSplitPos, nTxtLen - nSplitPos );
+ pNode->NotifyClients( 0, &aHint );
+ }
+ }
+ if ( HasHints() )
+ {
+ MoveTxtAttr_To_AttrSet();
+ }
+ pNode->MakeFrms( *this ); // neue Frames anlegen.
+ lcl_ChangeFtnRef( *this );
+ }
+ else
+ {
+ SwWrongList *pList = GetWrong();
+ SetWrong( 0, false );
+ SetWrongDirty( true );
+
+ SwGrammarMarkUp *pList3 = GetGrammarCheck();
+ SetGrammarCheck( 0, false );
+ SetGrammarCheckDirty( true );
+
+ SetWordCountDirty( true );
+
+ // SMARTTAGS
+ SwWrongList *pList2 = GetSmartTags();
+ SetSmartTags( 0, false );
+ SetSmartTagDirty( true );
+
+ SwIndex aIdx( this );
+ CutText( pNode, aIdx, nSplitPos );
+
+ // JP 01.10.96: alle leeren und nicht zu expandierenden
+ // Attribute loeschen
+ if ( HasHints() )
+ {
+ for ( sal_uInt16 j = m_pSwpHints->Count(); j; )
+ {
+ SwTxtAttr* const pHt = m_pSwpHints->GetTextHint( --j );
+ const xub_StrLen* const pEnd = pHt->GetEnd();
+ if ( pHt->DontExpand() && pEnd && (*pHt->GetStart() == *pEnd) )
+ {
+ // delete it!
+ m_pSwpHints->DeleteAtPos( j );
+ DestroyAttr( pHt );
+ }
+ }
+ MoveTxtAttr_To_AttrSet();
+ }
+
+ if( pList )
+ {
+ pNode->SetWrong( pList->SplitList( nSplitPos ) );
+ SetWrong( pList, false );
+ }
+
+ if( pList3 )
+ {
+ pNode->SetGrammarCheck( pList3->SplitGrammarList( nSplitPos ) );
+ SetGrammarCheck( pList3, false );
+ }
+
+ // SMARTTAGS
+ if( pList2 )
+ {
+ pNode->SetSmartTags( pList2->SplitList( nSplitPos ) );
+ SetSmartTags( pList2, false );
+ }
+
+ if ( GetDepends() )
+ {
+ MakeFrms( *pNode ); // neue Frames anlegen.
+ }
+ lcl_ChangeFtnRef( *pNode );
+ }
+
+ {
+ //Hint fuer Pagedesc versenden. Das mueste eigntlich das Layout im
+ //Paste der Frames selbst erledigen, aber das fuehrt dann wiederum
+ //zu weiteren Folgefehlern, die mit Laufzeitkosten geloest werden
+ //muesten. #56977# #55001# #56135#
+ const SfxPoolItem *pItem;
+ if( GetDepends() && SFX_ITEM_SET == pNode->GetSwAttrSet().
+ GetItemState( RES_PAGEDESC, sal_True, &pItem ) )
+ {
+ pNode->ModifyNotification( (SfxPoolItem*)pItem, (SfxPoolItem*)pItem );
+ }
+ }
+ return pNode;
+}
+
+void SwTxtNode::MoveTxtAttr_To_AttrSet()
+{
+ OSL_ENSURE( m_pSwpHints, "MoveTxtAttr_To_AttrSet without SwpHints?" );
+ for ( sal_uInt16 i = 0; m_pSwpHints && i < m_pSwpHints->Count(); ++i )
+ {
+ SwTxtAttr *pHt = m_pSwpHints->GetTextHint(i);
+
+ if( *pHt->GetStart() )
+ break;
+
+ const xub_StrLen* pHtEndIdx = pHt->GetEnd();
+
+ if( !pHtEndIdx )
+ continue;
+
+ if ( *pHtEndIdx < m_Text.Len() || pHt->IsCharFmtAttr() )
+ break;
+
+ if( !pHt->IsDontMoveAttr() &&
+ SetAttr( pHt->GetAttr() ) )
+ {
+ m_pSwpHints->DeleteAtPos(i);
+ DestroyAttr( pHt );
+ --i;
+ }
+ }
+
+}
+
+SwCntntNode *SwTxtNode::JoinNext()
+{
+ SwNodes& rNds = GetNodes();
+ SwNodeIndex aIdx( *this );
+ if( SwCntntNode::CanJoinNext( &aIdx ) )
+ {
+ SwDoc* pDoc = rNds.GetDoc();
+ SvULongs aBkmkArr( 15, 15 );
+ _SaveCntntIdx( pDoc, aIdx.GetIndex(), USHRT_MAX, aBkmkArr, SAVEFLY );
+ SwTxtNode *pTxtNode = aIdx.GetNode().GetTxtNode();
+ xub_StrLen nOldLen = m_Text.Len();
+
+ // METADATA: merge
+ this->JoinMetadatable(*pTxtNode, !this->Len(), !pTxtNode->Len());
+
+ SwWrongList *pList = GetWrong();
+ if( pList )
+ {
+ pList->JoinList( pTxtNode->GetWrong(), nOldLen );
+ SetWrongDirty( true );
+ SetWrong( 0, false );
+ }
+ else
+ {
+ pList = pTxtNode->GetWrong();
+ if( pList )
+ {
+ pList->Move( 0, nOldLen );
+ SetWrongDirty( true );
+ pTxtNode->SetWrong( 0, false );
+ }
+ }
+
+ SwGrammarMarkUp *pList3 = GetGrammarCheck();
+ if( pList3 )
+ {
+ pList3->JoinGrammarList( pTxtNode->GetGrammarCheck(), nOldLen );
+ SetGrammarCheckDirty( true );
+ SetGrammarCheck( 0, false );
+ }
+ else
+ {
+ pList3 = pTxtNode->GetGrammarCheck();
+ if( pList3 )
+ {
+ pList3->MoveGrammar( 0, nOldLen );
+ SetGrammarCheckDirty( true );
+ pTxtNode->SetGrammarCheck( 0, false );
+ }
+ }
+
+ // SMARTTAGS
+ SwWrongList *pList2 = GetSmartTags();
+ if( pList2 )
+ {
+ pList2->JoinList( pTxtNode->GetSmartTags(), nOldLen );
+ SetSmartTagDirty( true );
+ SetSmartTags( 0, false );
+ }
+ else
+ {
+ pList2 = pTxtNode->GetSmartTags();
+ if( pList2 )
+ {
+ pList2->Move( 0, nOldLen );
+ SetSmartTagDirty( true );
+ pTxtNode->SetSmartTags( 0, false );
+ }
+ }
+
+ { // wg. SwIndex
+ pTxtNode->CutText( this, SwIndex(pTxtNode), pTxtNode->Len() );
+ }
+ // verschiebe noch alle Bookmarks/TOXMarks
+ if( aBkmkArr.Count() )
+ _RestoreCntntIdx( pDoc, aBkmkArr, GetIndex(), nOldLen );
+
+ if( pTxtNode->HasAnyIndex() )
+ {
+ // alle Crsr/StkCrsr/UnoCrsr aus dem Loeschbereich verschieben
+ pDoc->CorrAbs( aIdx, SwPosition( *this ), nOldLen, sal_True );
+ }
+ rNds.Delete(aIdx);
+ SetWrong( pList, false );
+ SetGrammarCheck( pList3, false );
+ SetSmartTags( pList2, false ); // SMARTTAGS
+ InvalidateNumRule();
+ }
+ else {
+ OSL_FAIL( "kein TxtNode." );
+ }
+
+ return this;
+}
+
+SwCntntNode *SwTxtNode::JoinPrev()
+{
+ SwNodes& rNds = GetNodes();
+ SwNodeIndex aIdx( *this );
+ if( SwCntntNode::CanJoinPrev( &aIdx ) )
+ {
+ SwDoc* pDoc = rNds.GetDoc();
+ SvULongs aBkmkArr( 15, 15 );
+ _SaveCntntIdx( pDoc, aIdx.GetIndex(), USHRT_MAX, aBkmkArr, SAVEFLY );
+ SwTxtNode *pTxtNode = aIdx.GetNode().GetTxtNode();
+ xub_StrLen nLen = pTxtNode->Len();
+
+ SwWrongList *pList = pTxtNode->GetWrong();
+ if( pList )
+ {
+ pList->JoinList( GetWrong(), Len() );
+ SetWrongDirty( true );
+ pTxtNode->SetWrong( 0, false );
+ SetWrong( NULL );
+ }
+ else
+ {
+ pList = GetWrong();
+ if( pList )
+ {
+ pList->Move( 0, nLen );
+ SetWrongDirty( true );
+ SetWrong( 0, false );
+ }
+ }
+
+ SwGrammarMarkUp *pList3 = pTxtNode->GetGrammarCheck();
+ if( pList3 )
+ {
+ pList3->JoinGrammarList( GetGrammarCheck(), Len() );
+ SetGrammarCheckDirty( true );
+ pTxtNode->SetGrammarCheck( 0, false );
+ SetGrammarCheck( NULL );
+ }
+ else
+ {
+ pList3 = GetGrammarCheck();
+ if( pList3 )
+ {
+ pList3->MoveGrammar( 0, nLen );
+ SetGrammarCheckDirty( true );
+ SetGrammarCheck( 0, false );
+ }
+ }
+
+ // SMARTTAGS
+ SwWrongList *pList2 = pTxtNode->GetSmartTags();
+ if( pList2 )
+ {
+ pList2->JoinList( GetSmartTags(), Len() );
+ SetSmartTagDirty( true );
+ pTxtNode->SetSmartTags( 0, false );
+ SetSmartTags( NULL );
+ }
+ else
+ {
+ pList2 = GetSmartTags();
+ if( pList2 )
+ {
+ pList2->Move( 0, nLen );
+ SetSmartTagDirty( true );
+ SetSmartTags( 0, false );
+ }
+ }
+
+ { // wg. SwIndex
+ pTxtNode->CutText( this, SwIndex(this), SwIndex(pTxtNode), nLen );
+ }
+ // verschiebe noch alle Bookmarks/TOXMarks
+ if( aBkmkArr.Count() )
+ _RestoreCntntIdx( pDoc, aBkmkArr, GetIndex() );
+
+ if( pTxtNode->HasAnyIndex() )
+ {
+ // alle Crsr/StkCrsr/UnoCrsr aus dem Loeschbereich verschieben
+ pDoc->CorrAbs( aIdx, SwPosition( *this ), nLen, sal_True );
+ }
+ rNds.Delete(aIdx);
+ SetWrong( pList, false );
+ SetGrammarCheck( pList3, false );
+ SetSmartTags( pList2, false );
+ InvalidateNumRule();
+ }
+ else {
+ OSL_FAIL( "kein TxtNode." );
+ }
+
+ return this;
+}
+
+// erzeugt einen AttrSet mit Bereichen fuer Frame-/Para/Char-Attributen
+void SwTxtNode::NewAttrSet( SwAttrPool& rPool )
+{
+ OSL_ENSURE( !mpAttrSet.get(), "AttrSet ist doch gesetzt" );
+ SwAttrSet aNewAttrSet( rPool, aTxtNodeSetRange );
+
+ // put names of parent style and conditional style:
+ const SwFmtColl* pAnyFmtColl = &GetAnyFmtColl();
+ const SwFmtColl* pFmtColl = GetFmtColl();
+ String sVal;
+ SwStyleNameMapper::FillProgName( pAnyFmtColl->GetName(), sVal, nsSwGetPoolIdFromName::GET_POOLID_TXTCOLL, sal_True );
+ SfxStringItem aAnyFmtColl( RES_FRMATR_STYLE_NAME, sVal );
+ if ( pFmtColl != pAnyFmtColl )
+ SwStyleNameMapper::FillProgName( pFmtColl->GetName(), sVal, nsSwGetPoolIdFromName::GET_POOLID_TXTCOLL, sal_True );
+ SfxStringItem aFmtColl( RES_FRMATR_CONDITIONAL_STYLE_NAME, sVal );
+ aNewAttrSet.Put( aAnyFmtColl );
+ aNewAttrSet.Put( aFmtColl );
+
+ aNewAttrSet.SetParent( &pAnyFmtColl->GetAttrSet() );
+ mpAttrSet = GetDoc()->GetIStyleAccess().getAutomaticStyle( aNewAttrSet, IStyleAccess::AUTO_STYLE_PARA );
+}
+
+
+// override SwIndexReg::Update => text hints do not need SwIndex for start/end!
+void SwTxtNode::Update( SwIndex const & rPos, const xub_StrLen nChangeLen,
+ const bool bNegative, const bool bDelete )
+{
+ SetAutoCompleteWordDirty( sal_True );
+
+ ::std::auto_ptr<TmpHints> pCollector;
+ const xub_StrLen nChangePos = rPos.GetIndex();
+
+ if ( HasHints() )
+ {
+ if ( bNegative )
+ {
+ const xub_StrLen nChangeEnd = nChangePos + nChangeLen;
+ for ( sal_uInt16 n = 0; n < m_pSwpHints->Count(); ++n )
+ {
+ SwTxtAttr * const pHint = m_pSwpHints->GetTextHint(n);
+ xub_StrLen * const pStart = pHint->GetStart();
+ if ( *pStart > nChangePos )
+ {
+ if ( *pStart > nChangeEnd )
+ {
+ *pStart = *pStart - nChangeLen;
+ }
+ else
+ {
+ *pStart = nChangePos;
+ }
+ }
+
+ xub_StrLen * const pEnd = pHint->GetEnd();
+ if (pEnd)
+ {
+ if ( *pEnd > nChangePos )
+ {
+ if( *pEnd > nChangeEnd )
+ {
+ *pEnd = *pEnd - nChangeLen;
+ }
+ else
+ {
+ *pEnd = nChangePos;
+ }
+ }
+ }
+ }
+
+ m_pSwpHints->MergePortions( *this );
+ }
+ else
+ {
+ bool bNoExp = false;
+ bool bResort = false;
+ const sal_uInt16 coArrSz = static_cast<sal_uInt16>(RES_TXTATR_WITHEND_END) -
+ static_cast<sal_uInt16>(RES_CHRATR_BEGIN);
+
+ sal_Bool aDontExp[ coArrSz ];
+ memset( &aDontExp, 0, coArrSz * sizeof(sal_Bool) );
+
+ for ( sal_uInt16 n = 0; n < m_pSwpHints->Count(); ++n )
+ {
+ SwTxtAttr * const pHint = m_pSwpHints->GetTextHint(n);
+ xub_StrLen * const pStart = pHint->GetStart();
+ xub_StrLen * const pEnd = pHint->GetEnd();
+ if ( *pStart >= nChangePos )
+ {
+ *pStart = *pStart + nChangeLen;
+ if ( pEnd )
+ {
+ *pEnd = *pEnd + nChangeLen;
+ }
+ }
+ else if ( pEnd && (*pEnd >= nChangePos) )
+ {
+ if ( (*pEnd > nChangePos) || IsIgnoreDontExpand() )
+ {
+ *pEnd = *pEnd + nChangeLen;
+ }
+ else // *pEnd == nChangePos
+ {
+ sal_uInt16 nWhPos;
+ const sal_uInt16 nWhich = pHint->Which();
+
+ OSL_ENSURE(!isCHRATR(nWhich), "Update: char attr hint?");
+ if (isCHRATR(nWhich) || isTXTATR_WITHEND(nWhich))
+ {
+ nWhPos = static_cast<sal_uInt16>(nWhich -
+ RES_CHRATR_BEGIN);
+ }
+ else
+ continue;
+
+ if( aDontExp[ nWhPos ] )
+ continue;
+
+ if ( pHint->DontExpand() )
+ {
+ pHint->SetDontExpand( false );
+ bResort = true;
+ if ( pHint->IsCharFmtAttr() )
+ {
+ bNoExp = true;
+ aDontExp[ static_cast<sal_uInt16>(RES_TXTATR_CHARFMT) - static_cast<sal_uInt16>(RES_CHRATR_BEGIN) ]
+ = sal_True;
+ aDontExp[ static_cast<sal_uInt16>(RES_TXTATR_INETFMT) - static_cast<sal_uInt16>(RES_CHRATR_BEGIN) ]
+ = sal_True;
+ }
+ else
+ aDontExp[ nWhPos ] = sal_True;
+ }
+ else if( bNoExp )
+ {
+ if ( !pCollector.get() )
+ {
+ pCollector.reset( new TmpHints );
+ }
+ sal_uInt16 nCollCnt = pCollector->Count();
+ for( sal_uInt16 i = 0; i < nCollCnt; ++i )
+ {
+ SwTxtAttr *pTmp = (*pCollector)[ i ];
+ if( nWhich == pTmp->Which() )
+ {
+ pCollector->Remove( i );
+ SwTxtAttr::Destroy( pTmp,
+ GetDoc()->GetAttrPool() );
+ break;
+ }
+ }
+ SwTxtAttr * const pTmp = MakeTxtAttr( *GetDoc(),
+ pHint->GetAttr(),
+ nChangePos, nChangePos + nChangeLen);
+ pCollector->C40_INSERT( SwTxtAttr, pTmp, pCollector->Count() );
+ }
+ else
+ {
+ *pEnd = *pEnd + nChangeLen;
+ }
+ }
+ }
+ }
+ if ( bResort )
+ {
+ m_pSwpHints->Resort();
+ }
+ }
+ }
+
+ SwIndexReg aTmpIdxReg;
+ if ( !bNegative && !bDelete )
+ {
+ const SwRedlineTbl& rTbl = GetDoc()->GetRedlineTbl();
+ for ( sal_uInt16 i = 0; i < rTbl.Count(); ++i )
+ {
+ SwRedline *const pRedl = rTbl[ i ];
+ if ( pRedl->HasMark() )
+ {
+ SwPosition* const pEnd = pRedl->End();
+ if ( this == &pEnd->nNode.GetNode() &&
+ *pRedl->GetPoint() != *pRedl->GetMark() )
+ {
+ SwIndex & rIdx = pEnd->nContent;
+ if (nChangePos == rIdx.GetIndex())
+ {
+ rIdx.Assign( &aTmpIdxReg, rIdx.GetIndex() );
+ }
+ }
+ }
+ else if ( this == &pRedl->GetPoint()->nNode.GetNode() )
+ {
+ SwIndex & rIdx = pRedl->GetPoint()->nContent;
+ if (nChangePos == rIdx.GetIndex())
+ {
+ rIdx.Assign( &aTmpIdxReg, rIdx.GetIndex() );
+ // mst: FIXME: why does this adjust the unused position???
+ SwIndex * pIdx;
+ if ( &pRedl->GetBound( true ) == pRedl->GetPoint() )
+ {
+ pRedl->GetBound( false ) = pRedl->GetBound( true );
+ pIdx = &pRedl->GetBound( false ).nContent;
+ }
+ else
+ {
+ pRedl->GetBound( true ) = pRedl->GetBound( false );
+ pIdx = &pRedl->GetBound( true ).nContent;
+ }
+ pIdx->Assign( &aTmpIdxReg, pIdx->GetIndex() );
+ }
+ }
+ }
+
+ const IDocumentMarkAccess* const pMarkAccess = getIDocumentMarkAccess();
+ for(IDocumentMarkAccess::const_iterator_t ppMark =
+ pMarkAccess->getMarksBegin();
+ ppMark != pMarkAccess->getMarksEnd();
+ ppMark++)
+ {
+ // Bookmarks must never grow to either side, when
+ // editing (directly) to the left or right (#i29942#)!
+ // And a bookmark with same start and end must remain
+ // to the left of the inserted text (used in XML import).
+ const ::sw::mark::IMark* const pMark = ppMark->get();
+ const SwPosition* pEnd = &pMark->GetMarkEnd();
+ SwIndex & rIdx = const_cast<SwIndex&>(pEnd->nContent);
+ if( this == &pEnd->nNode.GetNode() &&
+ rPos.GetIndex() == rIdx.GetIndex() )
+ {
+ rIdx.Assign( &aTmpIdxReg, rIdx.GetIndex() );
+ }
+ }
+ }
+
+ // base class
+ SwIndexReg::Update( rPos, nChangeLen, bNegative, bDelete );
+
+ if ( pCollector.get() )
+ {
+ const sal_uInt16 nCount = pCollector->Count();
+ for ( sal_uInt16 i = 0; i < nCount; ++i )
+ {
+ m_pSwpHints->TryInsertHint( (*pCollector)[ i ], *this );
+ }
+ }
+
+ aTmpIdxReg.MoveTo( *this );
+}
+
+void SwTxtNode::_ChgTxtCollUpdateNum( const SwTxtFmtColl *pOldColl,
+ const SwTxtFmtColl *pNewColl)
+{
+ SwDoc* pDoc = GetDoc();
+ OSL_ENSURE( pDoc, "Kein Doc?" );
+ // erfrage die OutlineLevel und update gegebenenfalls das Nodes-Array,
+ // falls sich die Level geaendert haben !
+ const int nOldLevel = pOldColl && pOldColl->IsAssignedToListLevelOfOutlineStyle() ?
+ pOldColl->GetAssignedOutlineStyleLevel() : MAXLEVEL;
+ const int nNewLevel = pNewColl && pNewColl->IsAssignedToListLevelOfOutlineStyle() ?
+ pNewColl->GetAssignedOutlineStyleLevel() : MAXLEVEL;
+
+ if ( MAXLEVEL != nNewLevel )
+ {
+ SetAttrListLevel(nNewLevel);
+ }
+
+ {
+ if (pDoc)
+ pDoc->GetNodes().UpdateOutlineNode(*this);
+ }
+
+
+ SwNodes& rNds = GetNodes();
+ // Update beim Level 0 noch die Fussnoten !!
+ if( ( !nNewLevel || !nOldLevel) && pDoc->GetFtnIdxs().Count() &&
+ FTNNUM_CHAPTER == pDoc->GetFtnInfo().eNum &&
+ rNds.IsDocNodes() )
+ {
+ SwNodeIndex aTmpIndex( rNds, GetIndex());
+
+ pDoc->GetFtnIdxs().UpdateFtn( aTmpIndex);
+ }
+
+ if( RES_CONDTXTFMTCOLL == pNewColl->Which() )
+ {
+ // Erfrage die akt. Condition des TextNodes:
+ ChkCondColl();
+ }
+}
+
+// Wenn man sich genau am Ende einer Text- bzw. INetvorlage befindet,
+// bekommt diese das DontExpand-Flag verpasst
+
+sal_Bool SwTxtNode::DontExpandFmt( const SwIndex& rIdx, bool bFlag,
+ sal_Bool bFmtToTxtAttributes )
+{
+ const xub_StrLen nIdx = rIdx.GetIndex();
+ if ( bFmtToTxtAttributes && nIdx == m_Text.Len() )
+ {
+ FmtToTxtAttr( this );
+ }
+
+ sal_Bool bRet = sal_False;
+ if ( HasHints() )
+ {
+ const sal_uInt16 nEndCnt = m_pSwpHints->GetEndCount();
+ sal_uInt16 nPos = nEndCnt;
+ while( nPos )
+ {
+ SwTxtAttr *pTmp = m_pSwpHints->GetEnd( --nPos );
+ xub_StrLen *pEnd = pTmp->GetEnd();
+ if( !pEnd || *pEnd > nIdx )
+ continue;
+ if( nIdx != *pEnd )
+ nPos = 0;
+ else if( bFlag != pTmp->DontExpand() && !pTmp->IsLockExpandFlag()
+ && *pEnd > *pTmp->GetStart())
+ {
+ bRet = sal_True;
+ m_pSwpHints->NoteInHistory( pTmp );
+ pTmp->SetDontExpand( bFlag );
+ }
+ }
+ }
+ return bRet;
+}
+
+static bool lcl_GetTxtAttrDefault(xub_StrLen const nIndex,
+ xub_StrLen const nHintStart, xub_StrLen const nHintEnd)
+{
+ return ((nHintStart <= nIndex) && (nIndex < nHintEnd));
+}
+static bool lcl_GetTxtAttrExpand(xub_StrLen const nIndex,
+ xub_StrLen const nHintStart, xub_StrLen const nHintEnd)
+{
+ return ((nHintStart < nIndex) && (nIndex <= nHintEnd));
+}
+static bool lcl_GetTxtAttrParent(xub_StrLen const nIndex,
+ xub_StrLen const nHintStart, xub_StrLen const nHintEnd)
+{
+ return ((nHintStart < nIndex) && (nIndex < nHintEnd));
+}
+
+static void
+lcl_GetTxtAttrs(
+ ::std::vector<SwTxtAttr *> *const pVector, SwTxtAttr **const ppTxtAttr,
+ SwpHints *const pSwpHints,
+ xub_StrLen const nIndex, RES_TXTATR const nWhich,
+ enum SwTxtNode::GetTxtAttrMode const eMode)
+{
+ sal_uInt16 const nSize = (pSwpHints) ? pSwpHints->Count() : 0;
+ xub_StrLen nPreviousIndex(0); // index of last hint with nWhich
+ bool (*pMatchFunc)(xub_StrLen const, xub_StrLen const, xub_StrLen const)=0;
+ switch (eMode)
+ {
+ case SwTxtNode::DEFAULT: pMatchFunc = &lcl_GetTxtAttrDefault; break;
+ case SwTxtNode::EXPAND: pMatchFunc = &lcl_GetTxtAttrExpand; break;
+ case SwTxtNode::PARENT: pMatchFunc = &lcl_GetTxtAttrParent; break;
+ default: OSL_ASSERT(false);
+ }
+
+ for( sal_uInt16 i = 0; i < nSize; ++i )
+ {
+ SwTxtAttr *const pHint = pSwpHints->GetTextHint(i);
+ xub_StrLen const nHintStart( *(pHint->GetStart()) );
+ if (nIndex < nHintStart)
+ {
+ return; // hints are sorted by start, so we are done...
+ }
+
+ if (pHint->Which() != nWhich)
+ {
+ continue;
+ }
+
+ xub_StrLen const*const pEndIdx = pHint->GetEnd();
+ OSL_ENSURE(pEndIdx || pHint->HasDummyChar(),
+ "hint with no end and no dummy char?");
+ // Wenn bExpand gesetzt ist, wird das Verhalten bei Eingabe
+ // simuliert, d.h. der Start wuede verschoben, das Ende expandiert,
+ bool const bContained( (pEndIdx)
+ ? (*pMatchFunc)(nIndex, nHintStart, *pEndIdx)
+ : (nHintStart == nIndex) );
+ if (bContained)
+ {
+ if (pVector)
+ {
+ if (nPreviousIndex < nHintStart)
+ {
+ pVector->clear(); // clear hints that are outside pHint
+ nPreviousIndex = nHintStart;
+ }
+ pVector->push_back(pHint);
+ }
+ else
+ {
+ *ppTxtAttr = pHint; // and possibly overwrite outer hint
+ }
+ if (!pEndIdx)
+ {
+ break;
+ }
+ }
+ }
+}
+
+::std::vector<SwTxtAttr *>
+SwTxtNode::GetTxtAttrsAt(xub_StrLen const nIndex, RES_TXTATR const nWhich,
+ enum GetTxtAttrMode const eMode) const
+{
+ ::std::vector<SwTxtAttr *> ret;
+ lcl_GetTxtAttrs(& ret, 0, m_pSwpHints, nIndex, nWhich, eMode);
+ return ret;
+}
+
+SwTxtAttr *
+SwTxtNode::GetTxtAttrAt(xub_StrLen const nIndex, RES_TXTATR const nWhich,
+ enum GetTxtAttrMode const eMode) const
+{
+ OSL_ENSURE( (nWhich == RES_TXTATR_META)
+ || (nWhich == RES_TXTATR_METAFIELD)
+ || (nWhich == RES_TXTATR_AUTOFMT)
+ || (nWhich == RES_TXTATR_INETFMT)
+ || (nWhich == RES_TXTATR_CJK_RUBY)
+ || (nWhich == RES_TXTATR_UNKNOWN_CONTAINER),
+ "GetTxtAttrAt() will give wrong result for this hint!");
+
+ SwTxtAttr * pRet(0);
+ lcl_GetTxtAttrs(0, & pRet, m_pSwpHints, nIndex, nWhich, eMode);
+ return pRet;
+}
+
+/*************************************************************************
+ * CopyHint()
+ *************************************************************************/
+
+SwCharFmt* lcl_FindCharFmt( const SwCharFmts* pCharFmts, const XubString& rName )
+{
+ if( rName.Len() )
+ {
+ SwCharFmt* pFmt;
+ sal_uInt16 nArrLen = pCharFmts->Count();
+ for( sal_uInt16 i = 1; i < nArrLen; i++ )
+ {
+ pFmt = (*pCharFmts)[ i ];
+ if( pFmt->GetName().CompareTo( rName ) == COMPARE_EQUAL )
+ return pFmt;
+ }
+ }
+ return NULL;
+}
+
+void lcl_CopyHint( const sal_uInt16 nWhich, const SwTxtAttr * const pHt,
+ SwTxtAttr *const pNewHt, SwDoc *const pOtherDoc, SwTxtNode *const pDest )
+{
+ OSL_ENSURE( nWhich == pHt->Which(), "Falsche Hint-Id" );
+ switch( nWhich )
+ {
+ // copy nodesarray section with footnote content
+ case RES_TXTATR_FTN :
+ OSL_ENSURE(pDest, "lcl_CopyHint: no destination text node?");
+ static_cast<const SwTxtFtn*>(pHt)->CopyFtn(
+ *static_cast<SwTxtFtn*>(pNewHt), *pDest);
+ break;
+
+ // Beim Kopieren von Feldern in andere Dokumente
+ // muessen die Felder bei ihren neuen Feldtypen angemeldet werden.
+
+ // TabellenFormel muessen relativ kopiert werden.
+ case RES_TXTATR_FIELD :
+ {
+ const SwFmtFld& rFld = pHt->GetFld();
+ if( pOtherDoc )
+ {
+ static_cast<const SwTxtFld*>(pHt)->CopyFld(
+ static_cast<SwTxtFld*>(pNewHt) );
+ }
+
+ // Tabellenformel ??
+ if( RES_TABLEFLD == rFld.GetFld()->GetTyp()->Which()
+ && static_cast<const SwTblField*>(rFld.GetFld())->IsIntrnlName())
+ {
+ // wandel die interne in eine externe Formel um
+ const SwTableNode* const pDstTblNd =
+ static_cast<const SwTxtFld*>(pHt)->
+ GetTxtNode().FindTableNode();
+ if( pDstTblNd )
+ {
+ SwTblField* const pTblFld = const_cast<SwTblField*>(
+ static_cast<const SwTblField*>(
+ pNewHt->GetFld().GetFld()));
+ pTblFld->PtrToBoxNm( &pDstTblNd->GetTable() );
+ }
+ }
+ }
+ break;
+
+ case RES_TXTATR_TOXMARK :
+ if( pOtherDoc && pDest && pDest->GetpSwpHints()
+ && USHRT_MAX != pDest->GetpSwpHints()->GetPos( pNewHt ) )
+ {
+ // Beim Kopieren von TOXMarks(Client) in andere Dokumente
+ // muss der Verzeichnis (Modify) ausgetauscht werden
+ static_cast<SwTxtTOXMark*>(pNewHt)->CopyTOXMark( pOtherDoc );
+ }
+ break;
+
+ case RES_TXTATR_CHARFMT :
+ // Wenn wir es mit einer Zeichenvorlage zu tun haben,
+ // muessen wir natuerlich auch die Formate kopieren.
+ if( pDest && pDest->GetpSwpHints()
+ && USHRT_MAX != pDest->GetpSwpHints()->GetPos( pNewHt ) )
+ {
+ SwCharFmt* pFmt =
+ static_cast<SwCharFmt*>(pHt->GetCharFmt().GetCharFmt());
+
+ if( pFmt && pOtherDoc )
+ {
+ pFmt = pOtherDoc->CopyCharFmt( *pFmt );
+ }
+ const_cast<SwFmtCharFmt&>( static_cast<const SwFmtCharFmt&>(
+ pNewHt->GetCharFmt() ) ).SetCharFmt( pFmt );
+ }
+ break;
+ case RES_TXTATR_INETFMT :
+ {
+ // Wenn wir es mit benutzerdefinierten INet-Zeichenvorlagen
+ // zu tun haben, muessen wir natuerlich auch die Formate kopieren.
+ if( pOtherDoc && pDest && pDest->GetpSwpHints()
+ && USHRT_MAX != pDest->GetpSwpHints()->GetPos( pNewHt ) )
+ {
+ const SwDoc* const pDoc = static_cast<const SwTxtINetFmt*>(pHt)
+ ->GetTxtNode().GetDoc();
+ if ( pDoc )
+ {
+ const SwCharFmts* pCharFmts = pDoc->GetCharFmts();
+ const SwFmtINetFmt& rFmt = pHt->GetINetFmt();
+ SwCharFmt* pFmt;
+ pFmt = lcl_FindCharFmt( pCharFmts, rFmt.GetINetFmt() );
+ if( pFmt )
+ pOtherDoc->CopyCharFmt( *pFmt );
+ pFmt = lcl_FindCharFmt( pCharFmts, rFmt.GetVisitedFmt() );
+ if( pFmt )
+ pOtherDoc->CopyCharFmt( *pFmt );
+ }
+ }
+ //JP 24.04.98: Bug 49753 - ein TextNode muss am Attribut
+ // gesetzt sein, damit die Vorlagen erzeugt
+ // werden koenne
+ SwTxtINetFmt* const pINetHt = static_cast<SwTxtINetFmt*>(pNewHt);
+ if ( !pINetHt->GetpTxtNode() )
+ {
+ pINetHt->ChgTxtNode( pDest );
+ }
+
+ //JP 22.10.97: Bug 44875 - Verbindung zum Format herstellen
+ pINetHt->GetCharFmt();
+ break;
+ }
+ case RES_TXTATR_META:
+ case RES_TXTATR_METAFIELD:
+ OSL_ENSURE(pNewHt, "copying Meta should not fail!");
+ OSL_ENSURE(pDest && (CH_TXTATR_INWORD ==
+ pDest->GetTxt().GetChar(*pNewHt->GetStart())),
+ "missing CH_TXTATR?");
+ break;
+ }
+}
+
+/*************************************************************************
+|* SwTxtNode::CopyAttr()
+|* Beschreibung kopiert Attribute an der Position nStart in pDest.
+|* BP 7.6.93: Es werden mit Absicht nur die Attribute _mit_ EndIdx
+|* kopiert! CopyAttr wird vornehmlich dann gerufen,
+|* wenn Attribute fuer einen Node mit leerem String
+|* gesetzt werden sollen.
+*************************************************************************/
+
+void SwTxtNode::CopyAttr( SwTxtNode *pDest, const xub_StrLen nTxtStartIdx,
+ const xub_StrLen nOldPos )
+{
+ if ( HasHints() ) // keine Attribute, keine Kekse
+ {
+ SwDoc* const pOtherDoc = (pDest->GetDoc() != GetDoc()) ?
+ pDest->GetDoc() : 0;
+
+ for ( sal_uInt16 i = 0; i < m_pSwpHints->Count(); i++ )
+ {
+ SwTxtAttr *const pHt = m_pSwpHints->GetTextHint(i);
+ xub_StrLen const nAttrStartIdx = *pHt->GetStart();
+ if ( nTxtStartIdx < nAttrStartIdx )
+ break; // ueber das Textende, da nLen == 0
+
+ const xub_StrLen *const pEndIdx = pHt->GetEnd();
+ if ( pEndIdx && !pHt->HasDummyChar() )
+ {
+ if( ( *pEndIdx > nTxtStartIdx ||
+ ( *pEndIdx == nTxtStartIdx &&
+ nAttrStartIdx == nTxtStartIdx ) ) )
+ {
+ sal_uInt16 const nWhich = pHt->Which();
+ if ( RES_TXTATR_REFMARK != nWhich )
+ {
+ // attribute in the area => copy
+ SwTxtAttr *const pNewHt = pDest->InsertItem(
+ pHt->GetAttr(), nOldPos, nOldPos,
+ nsSetAttrMode::SETATTR_IS_COPY);
+ if ( pNewHt )
+ {
+ lcl_CopyHint( nWhich, pHt, pNewHt,
+ pOtherDoc, pDest );
+ }
+ }
+ else if( !pOtherDoc ? GetDoc()->IsCopyIsMove()
+ : 0 == pOtherDoc->GetRefMark(
+ pHt->GetRefMark().GetRefName() ) )
+ {
+ pDest->InsertItem( pHt->GetAttr(), nOldPos, nOldPos,
+ nsSetAttrMode::SETATTR_IS_COPY);
+ }
+ }
+ }
+ }
+ }
+
+ if( this != pDest )
+ {
+ // Frames benachrichtigen, sonst verschwinden die Ftn-Nummern
+ SwUpdateAttr aHint( nOldPos, nOldPos, 0 );
+ pDest->ModifyNotification( 0, &aHint );
+ }
+}
+
+/*************************************************************************
+|* SwTxtNode::Copy()
+|* Beschreibung kopiert Zeichen und Attibute in pDest,
+|* wird angehaengt
+*************************************************************************/
+
+// --> OD 2008-11-18 #i96213#
+// introduction of new optional parameter to control, if all attributes have to be copied.
+void SwTxtNode::CopyText( SwTxtNode *const pDest,
+ const SwIndex &rStart,
+ const xub_StrLen nLen,
+ const bool bForceCopyOfAllAttrs )
+{
+ SwIndex aIdx( pDest, pDest->m_Text.Len() );
+ CopyText( pDest, aIdx, rStart, nLen, bForceCopyOfAllAttrs );
+}
+
+// --> OD 2008-11-18 #i96213#
+// introduction of new optional parameter to control, if all attributes have to be copied.
+void SwTxtNode::CopyText( SwTxtNode *const pDest,
+ const SwIndex &rDestStart,
+ const SwIndex &rStart,
+ xub_StrLen nLen,
+ const bool bForceCopyOfAllAttrs )
+{
+ xub_StrLen nTxtStartIdx = rStart.GetIndex();
+ xub_StrLen nDestStart = rDestStart.GetIndex(); // alte Pos merken
+
+ if (pDest->GetDoc()->IsClipBoard() && this->GetNum())
+ {
+ // #i111677# cache expansion of source (for clipboard)
+ pDest->m_pNumStringCache.reset(
+ new ::rtl::OUString(this->GetNumString()));
+ }
+
+ if( !nLen )
+ {
+ // wurde keine Laenge angegeben, dann Kopiere die Attribute
+ // an der Position rStart.
+ CopyAttr( pDest, nTxtStartIdx, nDestStart );
+
+ // harte Absatz umspannende Attribute kopieren
+ if( HasSwAttrSet() )
+ {
+ // alle, oder nur die CharAttribute ?
+ // --> OD 2008-11-18 #i96213#
+ if ( !bForceCopyOfAllAttrs &&
+ ( nDestStart ||
+ pDest->HasSwAttrSet() ||
+ nLen != pDest->GetTxt().Len() ) )
+ // <--
+ {
+ SfxItemSet aCharSet( pDest->GetDoc()->GetAttrPool(),
+ RES_CHRATR_BEGIN, RES_CHRATR_END-1,
+ RES_TXTATR_INETFMT, RES_TXTATR_INETFMT,
+ RES_TXTATR_CHARFMT, RES_TXTATR_CHARFMT,
+ RES_UNKNOWNATR_BEGIN, RES_UNKNOWNATR_END-1,
+ 0 );
+ aCharSet.Put( *GetpSwAttrSet() );
+ if( aCharSet.Count() )
+ {
+ pDest->SetAttr( aCharSet, nDestStart, nDestStart );
+ }
+ }
+ else
+ {
+ GetpSwAttrSet()->CopyToModify( *pDest );
+ }
+ }
+ return;
+ }
+
+ // 1. Text kopieren
+ const xub_StrLen oldLen = pDest->m_Text.Len();
+ //JP 15.02.96: Bug 25537 - Attributbehandlung am Ende fehlt! Darum
+ // ueber die InsertMethode den Text einfuegen und nicht
+ // selbst direkt
+ pDest->InsertText( m_Text.Copy( nTxtStartIdx, nLen ), rDestStart,
+ IDocumentContentOperations::INS_EMPTYEXPAND );
+
+ // um reale Groesse Updaten !
+ nLen = pDest->m_Text.Len() - oldLen;
+ if ( !nLen ) // string not longer?
+ return;
+
+ SwDoc* const pOtherDoc = (pDest->GetDoc() != GetDoc()) ?
+ pDest->GetDoc() : 0;
+
+ // harte Absatz umspannende Attribute kopieren
+ if( HasSwAttrSet() )
+ {
+ // alle, oder nur die CharAttribute ?
+ // --> OD 2008-11-18 #i96213#
+ if ( !bForceCopyOfAllAttrs &&
+ ( nDestStart ||
+ pDest->HasSwAttrSet() ||
+ nLen != pDest->GetTxt().Len() ) )
+ // <--
+ {
+ SfxItemSet aCharSet( pDest->GetDoc()->GetAttrPool(),
+ RES_CHRATR_BEGIN, RES_CHRATR_END-1,
+ RES_TXTATR_INETFMT, RES_TXTATR_INETFMT,
+ RES_TXTATR_CHARFMT, RES_TXTATR_CHARFMT,
+ RES_UNKNOWNATR_BEGIN, RES_UNKNOWNATR_END-1,
+ 0 );
+ aCharSet.Put( *GetpSwAttrSet() );
+ if( aCharSet.Count() )
+ {
+ pDest->SetAttr( aCharSet, nDestStart, nDestStart + nLen );
+ }
+ }
+ else
+ {
+ GetpSwAttrSet()->CopyToModify( *pDest );
+ }
+ }
+
+ bool const bUndoNodes = !pOtherDoc
+ && GetDoc()->GetIDocumentUndoRedo().IsUndoNodes(GetNodes());
+
+ // Ende erst jetzt holen, weil beim Kopieren in sich selbst der
+ // Start-Index und alle Attribute vorher aktualisiert werden.
+ nTxtStartIdx = rStart.GetIndex();
+ const xub_StrLen nEnd = nTxtStartIdx + nLen;
+
+ // 2. Attribute kopieren
+ // durch das Attribute-Array, bis der Anfang des Geltungsbereiches
+ // des Attributs hinter dem zu kopierenden Bereich liegt
+ const sal_uInt16 nSize = m_pSwpHints ? m_pSwpHints->Count() : 0;
+
+ // wird in sich selbst kopiert, dann kann beim Einfuegen ein
+ // Attribut geloescht werden. Darum erst ins Tmp-Array kopieren und
+ // dann erst ins eigene uebertragen.
+ SwpHts aArr( 5 );
+
+ // Del-Array fuer alle RefMarks ohne Ausdehnung
+ SwpHts aRefMrkArr;
+
+ sal_uInt16 nDeletedDummyChars(0);
+ //Achtung: kann ungueltig sein!!
+ for (sal_uInt16 n = 0; ( n < nSize ); ++n)
+ {
+ const xub_StrLen nAttrStartIdx = *(*m_pSwpHints)[n]->GetStart();
+ if (!( nAttrStartIdx < nEnd))
+ break;
+
+ SwTxtAttr * const pHt = m_pSwpHints->GetTextHint(n);
+ const xub_StrLen * const pEndIdx = pHt->GetEnd();
+ const sal_uInt16 nWhich = pHt->Which();
+
+ // JP 26.04.94: REFMARK's werden nie kopiert. Hat das Refmark aber
+ // keinen Bereich umspannt, so steht im Text ein 255
+ // dieses muss entfernt werden. Trick: erst kopieren,
+ // erkennen und sammeln, nach dem kopieren Loeschen.
+ // Nimmt sein Zeichen mit ins Grab !!
+ // JP 14.08.95: Duerfen RefMarks gemovt werden?
+ int bCopyRefMark = RES_TXTATR_REFMARK == nWhich && ( bUndoNodes ||
+ (!pOtherDoc ? GetDoc()->IsCopyIsMove()
+ : 0 == pOtherDoc->GetRefMark(
+ pHt->GetRefMark().GetRefName() )));
+
+ if( pEndIdx && RES_TXTATR_REFMARK == nWhich && !bCopyRefMark )
+ {
+ continue;
+ }
+
+ xub_StrLen nAttrStt;
+ xub_StrLen nAttrEnd;
+
+ if( nAttrStartIdx < nTxtStartIdx )
+ {
+ // start is before selection
+ // copy hints with end and CH_TXTATR only if dummy char is copied
+ if ( pEndIdx && (*pEndIdx > nTxtStartIdx) && !pHt->HasDummyChar() )
+ {
+ // attribute with extent and the end is in the selection
+ nAttrStt = nDestStart;
+ nAttrEnd = (*pEndIdx > nEnd)
+ ? rDestStart.GetIndex()
+ : nDestStart + (*pEndIdx) - nTxtStartIdx;
+ }
+ else
+ {
+ continue;
+ }
+ }
+ else
+ {
+ // start is in the selection
+ nAttrStt = nDestStart + ( nAttrStartIdx - nTxtStartIdx );
+ if( pEndIdx )
+ {
+ nAttrEnd = *pEndIdx > nEnd
+ ? rDestStart.GetIndex()
+ : nDestStart + ( *pEndIdx - nTxtStartIdx );
+ }
+ else
+ {
+ nAttrEnd = nAttrStt;
+ }
+ }
+
+ SwTxtAttr * pNewHt = 0;
+
+ if( pDest == this )
+ {
+ // copy the hint here, but insert it later
+ pNewHt = MakeTxtAttr( *GetDoc(), pHt->GetAttr(),
+ nAttrStt, nAttrEnd, COPY, pDest );
+
+ lcl_CopyHint(nWhich, pHt, pNewHt, 0, pDest);
+ aArr.C40_INSERT( SwTxtAttr, pNewHt, aArr.Count() );
+ }
+ else
+ {
+ pNewHt = pDest->InsertItem( pHt->GetAttr(), nAttrStt - nDeletedDummyChars,
+ nAttrEnd - nDeletedDummyChars,
+ nsSetAttrMode::SETATTR_NOTXTATRCHR
+ | nsSetAttrMode::SETATTR_IS_COPY);
+ if (pNewHt)
+ {
+ lcl_CopyHint( nWhich, pHt, pNewHt, pOtherDoc, pDest );
+ }
+ else if (pHt->HasDummyChar())
+ {
+ // The attribute that has failed to be copied would insert
+ // dummy char, so positions of the following attributes have
+ // to be shifted by one to compensate for that missing char.
+ ++nDeletedDummyChars;
+ }
+ }
+
+ if( RES_TXTATR_REFMARK == nWhich && !pEndIdx && !bCopyRefMark )
+ {
+ aRefMrkArr.C40_INSERT( SwTxtAttr, pNewHt, aRefMrkArr.Count() );
+ }
+ }
+
+ // nur falls im Array Attribute stehen (kann nur beim Kopieren
+ // sich selbst passieren!!)
+ for ( sal_uInt16 i = 0; i < aArr.Count(); ++i )
+ {
+ InsertHint( aArr[ i ], nsSetAttrMode::SETATTR_NOTXTATRCHR );
+ }
+
+ if( pDest->GetpSwpHints() )
+ {
+ for ( sal_uInt16 i = 0; i < aRefMrkArr.Count(); ++i )
+ {
+ SwTxtAttr * const pNewHt = aRefMrkArr[i];
+ if( pNewHt->GetEnd() )
+ {
+ pDest->GetpSwpHints()->Delete( pNewHt );
+ pDest->DestroyAttr( pNewHt );
+ }
+ else
+ {
+ const SwIndex aIdx( pDest, *pNewHt->GetStart() );
+ pDest->EraseText( aIdx, 1 );
+ }
+ }
+ }
+
+ CHECK_SWPHINTS(this);
+}
+
+
+void SwTxtNode::InsertText( const XubString & rStr, const SwIndex & rIdx,
+ const IDocumentContentOperations::InsertFlags nMode )
+{
+ OSL_ENSURE( rIdx <= m_Text.Len(), "SwTxtNode::InsertText: invalid index." );
+ OSL_ENSURE( (sal_uLong)m_Text.Len() + (sal_uLong)rStr.Len() <= STRING_LEN,
+ "SwTxtNode::InsertText: node text with insertion > STRING_LEN." );
+
+ xub_StrLen aPos = rIdx.GetIndex();
+ xub_StrLen nLen = m_Text.Len() - aPos;
+ m_Text.Insert( rStr, aPos );
+ nLen = m_Text.Len() - aPos - nLen;
+
+ if ( !nLen ) return;
+
+ sal_Bool bOldExpFlg = IsIgnoreDontExpand();
+ if (nMode & IDocumentContentOperations::INS_FORCEHINTEXPAND)
+ {
+ SetIgnoreDontExpand( sal_True );
+ }
+
+ Update( rIdx, nLen ); // text content changed!
+
+ if (nMode & IDocumentContentOperations::INS_FORCEHINTEXPAND)
+ {
+ SetIgnoreDontExpand( bOldExpFlg );
+ }
+
+ // analog zu Insert(char) in txtedt.cxx:
+ // 1) bei bHintExp leere Hints an rIdx.GetIndex suchen und aufspannen
+ // 2) bei bHintExp == sal_False mitgezogene Feldattribute zuruecksetzen
+
+ if ( HasHints() )
+ {
+ for ( sal_uInt16 i = 0; i < m_pSwpHints->Count() &&
+ rIdx >= *(*m_pSwpHints)[i]->GetStart(); ++i )
+ {
+ SwTxtAttr * const pHt = m_pSwpHints->GetTextHint( i );
+ xub_StrLen * const pEndIdx = pHt->GetEnd();
+ if( !pEndIdx )
+ continue;
+
+ if( rIdx == *pEndIdx )
+ {
+ if ( (nMode & IDocumentContentOperations::INS_NOHINTEXPAND) ||
+ (!(nMode & IDocumentContentOperations::INS_FORCEHINTEXPAND)
+ && pHt->DontExpand()) )
+ {
+ // bei leeren Attributen auch Start veraendern
+ if( rIdx == *pHt->GetStart() )
+ *pHt->GetStart() = *pHt->GetStart() - nLen;
+ *pEndIdx = *pEndIdx - nLen;
+ m_pSwpHints->DeleteAtPos(i);
+ InsertHint( pHt, nsSetAttrMode::SETATTR_NOHINTADJUST );
+ }
+ // empty hints at insert position?
+ else if ( (nMode & IDocumentContentOperations::INS_EMPTYEXPAND)
+ && (*pEndIdx == *pHt->GetStart()) )
+ {
+ *pHt->GetStart() = *pHt->GetStart() - nLen;
+ const sal_uInt16 nAktLen = m_pSwpHints->Count();
+ m_pSwpHints->DeleteAtPos(i);
+ InsertHint( pHt/* AUTOSTYLES:, nsSetAttrMode::SETATTR_NOHINTADJUST*/ );
+ if ( nAktLen > m_pSwpHints->Count() && i )
+ {
+ --i;
+ }
+ continue;
+ }
+ else
+ {
+ continue;
+ }
+ }
+ if ( !(nMode & IDocumentContentOperations::INS_NOHINTEXPAND) &&
+ rIdx == nLen && *pHt->GetStart() == rIdx.GetIndex() &&
+ !pHt->IsDontExpandStartAttr() )
+ {
+ // Kein Feld, am Absatzanfang, HintExpand
+ m_pSwpHints->DeleteAtPos(i);
+ *pHt->GetStart() = *pHt->GetStart() - nLen;
+ InsertHint( pHt, nsSetAttrMode::SETATTR_NOHINTADJUST );
+ }
+ }
+ TryDeleteSwpHints();
+ }
+
+ if ( GetDepends() )
+ {
+ SwInsTxt aHint( aPos, nLen );
+ NotifyClients( 0, &aHint );
+ }
+
+ // By inserting a character, the hidden flags
+ // at the TxtNode can become invalid:
+ SetCalcHiddenCharFlags();
+
+ CHECK_SWPHINTS(this);
+}
+
+/*************************************************************************
+|*
+|* SwTxtNode::Cut()
+|*
+|* Beschreibung text.doc
+|*
+*************************************************************************/
+
+void SwTxtNode::CutText( SwTxtNode * const pDest,
+ const SwIndex & rStart, const xub_StrLen nLen )
+{
+ if(pDest)
+ {
+ SwIndex aDestStt( pDest, pDest->GetTxt().Len() );
+ CutImpl( pDest, aDestStt, rStart, nLen, false );
+ }
+ else
+ {
+ OSL_FAIL("mst: entering dead and bitrotted code; fasten your seatbelts!");
+ EraseText( rStart, nLen );
+ }
+}
+
+
+void SwTxtNode::CutImpl( SwTxtNode * const pDest, const SwIndex & rDestStart,
+ const SwIndex & rStart, xub_StrLen nLen, const bool bUpdate )
+{
+ if(!pDest)
+ {
+ OSL_FAIL("mst: entering dead and bitrotted code; fasten your seatbelts!");
+ EraseText( rStart, nLen );
+ return;
+ }
+
+ // nicht im Dokument verschieben ?
+ if( GetDoc() != pDest->GetDoc() )
+ {
+ OSL_FAIL("mst: entering dead and bitrotted code; fasten your seatbelts!");
+ CopyText( pDest, rDestStart, rStart, nLen);
+ EraseText(rStart, nLen);
+ return;
+ }
+
+ if( !nLen )
+ {
+ // wurde keine Laenge angegeben, dann Kopiere die Attribute
+ // an der Position rStart.
+ CopyAttr( pDest, rStart.GetIndex(), rDestStart.GetIndex() );
+ return;
+ }
+
+ xub_StrLen nTxtStartIdx = rStart.GetIndex();
+ xub_StrLen nDestStart = rDestStart.GetIndex(); // alte Pos merken
+ const xub_StrLen nInitSize = pDest->m_Text.Len();
+
+ // wird in sich selbst verschoben, muss es gesondert behandelt werden !!
+ if( pDest == this )
+ {
+ OSL_FAIL("mst: entering dead and bitrotted code; fasten your seatbelts!");
+ m_Text.Insert( m_Text, nTxtStartIdx, nLen, nDestStart );
+ m_Text.Erase( nTxtStartIdx + (nDestStart<nTxtStartIdx ? nLen : 0), nLen );
+
+ const xub_StrLen nEnd = rStart.GetIndex() + nLen;
+
+ // dann suche mal alle Attribute zusammen, die im verschobenen
+ // Bereich liegen. Diese werden in das extra Array verschoben,
+ // damit sich die Indizies beim Updaten nicht veraendern !!!
+ SwpHts aArr( 5 );
+
+ // 2. Attribute verschieben
+ // durch das Attribute-Array, bis der Anfang des Geltungsbereiches
+ // des Attributs hinter dem zu verschiebenden Bereich liegt
+ sal_uInt16 nAttrCnt = 0;
+ while ( m_pSwpHints && nAttrCnt < m_pSwpHints->Count() )
+ {
+ SwTxtAttr * const pHt = m_pSwpHints->GetTextHint(nAttrCnt);
+ const xub_StrLen nAttrStartIdx = *pHt->GetStart();
+ if (!( nAttrStartIdx < nEnd ))
+ break;
+ const xub_StrLen * const pEndIdx = pHt->GetEnd();
+ const sal_uInt16 nWhich = pHt->Which();
+ SwTxtAttr *pNewHt = 0;
+
+ if(nAttrStartIdx < nTxtStartIdx)
+ {
+ // Anfang liegt vor dem Bereich
+ if ( RES_TXTATR_REFMARK != nWhich && !pHt->HasDummyChar() &&
+ pEndIdx && *pEndIdx > nTxtStartIdx )
+ {
+ // Attribut mit einem Bereich
+ // und das Ende des Attribut liegt im Bereich
+ pNewHt = MakeTxtAttr( *GetDoc(), pHt->GetAttr(), 0,
+ *pEndIdx > nEnd
+ ? nLen
+ : *pEndIdx - nTxtStartIdx );
+ }
+ }
+ else
+ {
+ // der Anfang liegt vollstaendig im Bereich
+ if( !pEndIdx || *pEndIdx < nEnd )
+ {
+ // Attribut verschieben
+ m_pSwpHints->Delete( pHt );
+ // die Start/End Indicies neu setzen
+ *pHt->GetStart() = nAttrStartIdx - nTxtStartIdx;
+ if( pEndIdx )
+ *pHt->GetEnd() = *pEndIdx - nTxtStartIdx;
+ aArr.C40_INSERT( SwTxtAttr, pHt, aArr.Count() );
+ continue; // while-Schleife weiter, ohne ++ !
+ }
+ // das Ende liegt dahinter
+ else if (RES_TXTATR_REFMARK != nWhich && !pHt->HasDummyChar())
+ {
+ pNewHt = MakeTxtAttr( *GetDoc(), pHt->GetAttr(),
+ nAttrStartIdx - nTxtStartIdx,
+ !pEndIdx ? 0
+ : ( *pEndIdx > nEnd
+ ? nLen
+ : *pEndIdx - nTxtStartIdx ));
+ }
+ }
+ if( pNewHt )
+ {
+ // die Daten kopieren
+ lcl_CopyHint( nWhich, pHt, pNewHt, 0, this );
+ aArr.C40_INSERT( SwTxtAttr, pNewHt, aArr.Count() );
+ }
+ ++nAttrCnt;
+ }
+
+ if( bUpdate )
+ {
+ // Update aller Indizies
+ Update( rDestStart, nLen, sal_False, sal_True );
+ }
+
+ CHECK_SWPHINTS(this);
+
+ Update( rStart, nLen, sal_True, sal_True );
+
+ CHECK_SWPHINTS(this);
+
+ // dann setze die kopierten/geloeschten Attribute in den Node
+ if( nDestStart <= nTxtStartIdx )
+ {
+ nTxtStartIdx = nTxtStartIdx + nLen;
+ }
+ else
+ {
+ nDestStart = nDestStart - nLen;
+ }
+
+ for ( sal_uInt16 n = 0; n < aArr.Count(); ++n )
+ {
+ SwTxtAttr *const pNewHt = aArr[n];
+ *pNewHt->GetStart() = nDestStart + *pNewHt->GetStart();
+ xub_StrLen * const pEndIdx = pNewHt->GetEnd();
+ if ( pEndIdx )
+ {
+ *pEndIdx = nDestStart + *pEndIdx;
+ }
+ InsertHint( pNewHt, nsSetAttrMode::SETATTR_NOTXTATRCHR );
+ }
+ }
+ else
+ {
+ pDest->m_Text.Insert( m_Text, nTxtStartIdx, nLen, nDestStart );
+ m_Text.Erase( nTxtStartIdx, nLen );
+ nLen = pDest->m_Text.Len() - nInitSize; // update w/ current size!
+ if( !nLen ) // String nicht gewachsen ??
+ return;
+
+ if( bUpdate )
+ {
+ // Update aller Indizies
+ pDest->Update( rDestStart, nLen, sal_False, sal_True);
+ }
+
+ CHECK_SWPHINTS(pDest);
+
+ const xub_StrLen nEnd = rStart.GetIndex() + nLen;
+ SwDoc* const pOtherDoc = (pDest->GetDoc() != GetDoc())
+ ? pDest->GetDoc() : 0;
+ bool const bUndoNodes = !pOtherDoc
+ && GetDoc()->GetIDocumentUndoRedo().IsUndoNodes(GetNodes());
+
+ OSL_ENSURE(!pOtherDoc,
+ "mst: entering dead and bitrotted code; fasten your seatbelts!");
+
+ // harte Absatz umspannende Attribute kopieren
+ if( HasSwAttrSet() )
+ {
+ // alle, oder nur die CharAttribute ?
+ if( nInitSize || pDest->HasSwAttrSet() ||
+ nLen != pDest->GetTxt().Len() )
+ {
+ SfxItemSet aCharSet( pDest->GetDoc()->GetAttrPool(),
+ RES_CHRATR_BEGIN, RES_CHRATR_END-1,
+ RES_TXTATR_INETFMT, RES_TXTATR_INETFMT,
+ RES_TXTATR_CHARFMT, RES_TXTATR_CHARFMT,
+ RES_UNKNOWNATR_BEGIN, RES_UNKNOWNATR_END-1,
+ 0 );
+ aCharSet.Put( *GetpSwAttrSet() );
+ if( aCharSet.Count() )
+ pDest->SetAttr( aCharSet, nDestStart, nDestStart + nLen );
+ }
+ else
+ {
+ GetpSwAttrSet()->CopyToModify( *pDest );
+ }
+ }
+
+ // 2. Attribute verschieben
+ // durch das Attribute-Array, bis der Anfang des Geltungsbereiches
+ // des Attributs hinter dem zu verschiebenden Bereich liegt
+ sal_uInt16 nAttrCnt = 0;
+ while ( m_pSwpHints && (nAttrCnt < m_pSwpHints->Count()) )
+ {
+ SwTxtAttr * const pHt = m_pSwpHints->GetTextHint(nAttrCnt);
+ const xub_StrLen nAttrStartIdx = *pHt->GetStart();
+ if (!( nAttrStartIdx < nEnd ))
+ break;
+ const xub_StrLen * const pEndIdx = pHt->GetEnd();
+ const sal_uInt16 nWhich = pHt->Which();
+ SwTxtAttr *pNewHt = 0;
+
+ // if the hint has a dummy character, then it must not be split!
+ if(nAttrStartIdx < nTxtStartIdx)
+ {
+ // Anfang liegt vor dem Bereich
+ if( !pHt->HasDummyChar() && ( RES_TXTATR_REFMARK != nWhich
+ || bUndoNodes ) && pEndIdx && *pEndIdx > nTxtStartIdx )
+ {
+ // Attribut mit einem Bereich
+ // und das Ende des Attribut liegt im Bereich
+ pNewHt = MakeTxtAttr( *pDest->GetDoc(), pHt->GetAttr(),
+ nDestStart,
+ nDestStart + (
+ *pEndIdx > nEnd
+ ? nLen
+ : *pEndIdx - nTxtStartIdx ) );
+ }
+ }
+ else
+ {
+ // der Anfang liegt vollstaendig im Bereich
+ if( !pEndIdx || *pEndIdx < nEnd ||
+ (!pOtherDoc && !bUndoNodes && RES_TXTATR_REFMARK == nWhich)
+ || pHt->HasDummyChar() )
+ {
+ // do not delete note and later add it -> sidebar flickering
+ if ( GetDoc()->GetDocShell() )
+ {
+ GetDoc()->GetDocShell()->Broadcast( SfxSimpleHint(SFX_HINT_USER04));
+ }
+ // Attribut verschieben
+ m_pSwpHints->Delete( pHt );
+ // die Start/End Indicies neu setzen
+ *pHt->GetStart() =
+ nDestStart + (nAttrStartIdx - nTxtStartIdx);
+ if( pEndIdx )
+ {
+ *pHt->GetEnd() = nDestStart + (
+ *pEndIdx > nEnd
+ ? nLen
+ : *pEndIdx - nTxtStartIdx );
+ }
+ pDest->InsertHint( pHt,
+ nsSetAttrMode::SETATTR_NOTXTATRCHR
+ | nsSetAttrMode::SETATTR_DONTREPLACE );
+ if ( GetDoc()->GetDocShell() )
+ {
+ GetDoc()->GetDocShell()->Broadcast( SfxSimpleHint(SFX_HINT_USER04));
+ }
+ continue; // while-Schleife weiter, ohne ++ !
+ }
+ // das Ende liegt dahinter
+ else if( RES_TXTATR_REFMARK != nWhich || bUndoNodes )
+ {
+ pNewHt = MakeTxtAttr( *GetDoc(), pHt->GetAttr(),
+ nDestStart + (nAttrStartIdx - nTxtStartIdx),
+ !pEndIdx ? 0
+ : nDestStart + ( *pEndIdx > nEnd
+ ? nLen
+ : *pEndIdx - nTxtStartIdx ));
+ }
+ }
+ if ( pNewHt )
+ {
+ const bool bSuccess( pDest->InsertHint( pNewHt,
+ nsSetAttrMode::SETATTR_NOTXTATRCHR
+ | nsSetAttrMode::SETATTR_DONTREPLACE
+ | nsSetAttrMode::SETATTR_IS_COPY) );
+ if (bSuccess)
+ {
+ lcl_CopyHint( nWhich, pHt, pNewHt, pOtherDoc, pDest );
+ }
+ }
+ ++nAttrCnt;
+ }
+ // sollten jetzt noch leere Attribute rumstehen, dann haben diese
+ // eine hoehere Praezedenz. Also herausholen und das Array updaten.
+ // Die dabei entstehenden leeren Hints werden von den gesicherten
+ // "uebergeplaettet". (Bug: 6977)
+ if( m_pSwpHints && nAttrCnt < m_pSwpHints->Count() )
+ {
+ SwpHts aArr( 5 );
+ while ( nAttrCnt < m_pSwpHints->Count() )
+ {
+ SwTxtAttr * const pHt = m_pSwpHints->GetTextHint(nAttrCnt);
+ if ( nEnd != *pHt->GetStart() )
+ break;
+ const xub_StrLen * const pEndIdx = pHt->GetEnd();
+ if ( pEndIdx && *pEndIdx == nEnd )
+ {
+ aArr.C40_INSERT( SwTxtAttr, pHt, aArr.Count() );
+ m_pSwpHints->Delete( pHt );
+ }
+ else
+ {
+ ++nAttrCnt;
+ }
+ }
+ Update( rStart, nLen, sal_True, sal_True );
+
+ for ( sal_uInt16 n = 0; n < aArr.Count(); ++n )
+ {
+ SwTxtAttr * const pHt = aArr[ n ];
+ *pHt->GetStart() = *pHt->GetEnd() = rStart.GetIndex();
+ InsertHint( pHt );
+ }
+ }
+ else
+ {
+ Update( rStart, nLen, sal_True, sal_True );
+ }
+
+ CHECK_SWPHINTS(this);
+ }
+
+ TryDeleteSwpHints();
+
+ // Frames benachrichtigen;
+ SwInsTxt aInsHint( nDestStart, nLen );
+ pDest->ModifyNotification( 0, &aInsHint );
+ SwDelTxt aDelHint( nTxtStartIdx, nLen );
+ ModifyNotification( 0, &aDelHint );
+}
+
+
+void SwTxtNode::EraseText(const SwIndex &rIdx, const xub_StrLen nCount,
+ const IDocumentContentOperations::InsertFlags nMode )
+{
+ OSL_ENSURE( rIdx <= m_Text.Len(), "SwTxtNode::EraseText: invalid index." );
+
+ const xub_StrLen nStartIdx = rIdx.GetIndex();
+ const xub_StrLen nCnt = (STRING_LEN == nCount)
+ ? m_Text.Len() - nStartIdx : nCount;
+ const xub_StrLen nEndIdx = nStartIdx + nCnt;
+ m_Text.Erase( nStartIdx, nCnt );
+
+ /* GCAttr(); alle leeren weggwerfen ist zu brutal.
+ * Es duerfen nur die wegggeworfen werden,
+ * die im Bereich liegen und nicht am Ende des Bereiches liegen
+ */
+
+ for ( sal_uInt16 i = 0; m_pSwpHints && i < m_pSwpHints->Count(); ++i )
+ {
+ SwTxtAttr *pHt = m_pSwpHints->GetTextHint(i);
+
+ const xub_StrLen nHintStart = *pHt->GetStart();
+
+ if ( nHintStart < nStartIdx )
+ continue;
+
+ if ( nHintStart > nEndIdx )
+ break; // hints are sorted by end, so break here
+
+ const xub_StrLen* pHtEndIdx = pHt->GetEnd();
+ const sal_uInt16 nWhich = pHt->Which();
+
+ if( !pHtEndIdx )
+ {
+ OSL_ENSURE(pHt->HasDummyChar(),
+ "attribute with neither end nor CH_TXTATR?");
+ if (isTXTATR(nWhich) &&
+ (nHintStart >= nStartIdx) && (nHintStart < nEndIdx))
+ {
+ m_pSwpHints->DeleteAtPos(i);
+ DestroyAttr( pHt );
+ --i;
+ }
+ continue;
+ }
+
+ OSL_ENSURE(!( (nHintStart < nEndIdx) && (*pHtEndIdx > nEndIdx)
+ && pHt->HasDummyChar() )
+ // next line: deleting exactly dummy char: DeleteAttributes
+ || ((nHintStart == nStartIdx) && (nHintStart + 1 == nEndIdx)),
+ "ERROR: deleting left-overlapped attribute with CH_TXTATR");
+
+ // Delete the hint if:
+ // 1. The hint ends before the deletion end position or
+ // 2. The hint ends at the deletion end position and
+ // we are not in empty expand mode and
+ // the hint is a [toxmark|refmark|ruby] text attribute
+ // 3. deleting exactly the dummy char of an hint with end and dummy
+ // char deletes the hint
+ if ( (*pHtEndIdx < nEndIdx)
+ || ( (*pHtEndIdx == nEndIdx) &&
+ !(IDocumentContentOperations::INS_EMPTYEXPAND & nMode) &&
+ ( (RES_TXTATR_TOXMARK == nWhich) ||
+ (RES_TXTATR_REFMARK == nWhich) ||
+ // --> FME 2006-03-03 #i62668# Ruby text attribute must be
+ // treated just like toxmark and refmarks
+ (RES_TXTATR_CJK_RUBY == nWhich) ) )
+ // <--
+ || ( (nHintStart < nEndIdx) &&
+ pHt->HasDummyChar() )
+ )
+ {
+ m_pSwpHints->DeleteAtPos(i);
+ DestroyAttr( pHt );
+ --i;
+ }
+ }
+
+ OSL_ENSURE(rIdx.GetIndex() == nStartIdx, "huh? start index has changed?");
+
+ TryDeleteSwpHints();
+
+ Update( rIdx, nCnt, sal_True );
+
+ if( 1 == nCnt )
+ {
+ SwDelChr aHint( nStartIdx );
+ NotifyClients( 0, &aHint );
+ }
+ else
+ {
+ SwDelTxt aHint( nStartIdx, nCnt );
+ NotifyClients( 0, &aHint );
+ }
+
+ OSL_ENSURE(rIdx.GetIndex() == nStartIdx, "huh? start index has changed?");
+
+ // By deleting a character, the hidden flags
+ // at the TxtNode can become invalid:
+ SetCalcHiddenCharFlags();
+
+ CHECK_SWPHINTS(this);
+}
+
+/***********************************************************************
+#* Class : SwTxtNode
+#* Methode : GCAttr
+#*
+#* Beschreibung
+#* text.doc
+#***********************************************************************/
+
+void SwTxtNode::GCAttr()
+{
+ if ( !HasHints() )
+ return;
+
+ bool bChanged = false;
+ sal_uInt16 nMin = m_Text.Len(),
+ nMax = 0;
+ sal_Bool bAll = nMin != 0; // Bei leeren Absaetzen werden nur die
+ // INet-Formate entfernt.
+
+ for ( sal_uInt16 i = 0; m_pSwpHints && i < m_pSwpHints->Count(); ++i )
+ {
+ SwTxtAttr * const pHt = m_pSwpHints->GetTextHint(i);
+
+ // wenn Ende und Start gleich sind --> loeschen
+ const xub_StrLen * const pEndIdx = pHt->GetEnd();
+ if (pEndIdx && !pHt->HasDummyChar() && (*pEndIdx == *pHt->GetStart())
+ && ( bAll || pHt->Which() == RES_TXTATR_INETFMT ) )
+ {
+ bChanged = true;
+ nMin = Min( nMin, *pHt->GetStart() );
+ nMax = Max( nMax, *pHt->GetEnd() );
+ DestroyAttr( m_pSwpHints->Cut(i) );
+ --i;
+ }
+ else
+ {
+ pHt->SetDontExpand( false );
+ }
+ }
+ TryDeleteSwpHints();
+
+ if(bChanged)
+ {
+ //TxtFrm's reagieren auf aHint, andere auf aNew
+ SwUpdateAttr aHint( nMin, nMax, 0 );
+ NotifyClients( 0, &aHint );
+ SwFmtChg aNew( GetTxtColl() );
+ NotifyClients( 0, &aNew );
+ }
+}
+
+// #i23726#
+SwNumRule* SwTxtNode::_GetNumRule(sal_Bool bInParent) const
+{
+ SwNumRule* pRet = 0;
+
+ const SfxPoolItem* pItem = GetNoCondAttr( RES_PARATR_NUMRULE, bInParent );
+ bool bNoNumRule = false;
+ if ( pItem )
+ {
+ String sNumRuleName = static_cast<const SwNumRuleItem *>(pItem)->GetValue();
+ if (sNumRuleName.Len() > 0)
+ {
+ pRet = GetDoc()->FindNumRulePtr( sNumRuleName );
+ }
+ else // numbering is turned off
+ bNoNumRule = true;
+ }
+
+ if ( !bNoNumRule )
+ {
+ if ( pRet && pRet == GetDoc()->GetOutlineNumRule() &&
+ ( !HasSwAttrSet() ||
+ SFX_ITEM_SET !=
+ GetpSwAttrSet()->GetItemState( RES_PARATR_NUMRULE, sal_False ) ) )
+ {
+ SwTxtFmtColl* pColl = GetTxtColl();
+ if ( pColl )
+ {
+ const SwNumRuleItem& rDirectItem = pColl->GetNumRule( sal_False );
+ if ( rDirectItem.GetValue().Len() == 0 )
+ {
+ pRet = 0L;
+ }
+ }
+ }
+ }
+
+ return pRet;
+}
+
+SwNumRule* SwTxtNode::GetNumRule(sal_Bool bInParent) const
+{
+ SwNumRule * pRet = _GetNumRule(bInParent);
+
+ return pRet;
+}
+
+void SwTxtNode::NumRuleChgd()
+{
+ if ( IsInList() )
+ {
+ SwNumRule* pNumRule = GetNumRule();
+ if ( pNumRule && pNumRule != GetNum()->GetNumRule() )
+ {
+ mpNodeNum->ChangeNumRule( *pNumRule );
+ }
+ }
+
+ if( IsInCache() )
+ {
+ SwFrm::GetCache().Delete( this );
+ SetInCache( sal_False );
+ }
+ SetInSwFntCache( sal_False );
+
+ // Sending "noop" modify in order to cause invalidations of registered
+ // <SwTxtFrm> instances to get the list style change respectively the change
+ // in the list tree reflected in the layout.
+ // Important note:
+ {
+ SvxLRSpaceItem& rLR = (SvxLRSpaceItem&)GetSwAttrSet().GetLRSpace();
+ NotifyClients( &rLR, &rLR );
+ }
+}
+
+// -> #i27615#
+sal_Bool SwTxtNode::IsNumbered() const
+{
+ sal_Bool bResult = sal_False;
+
+ SwNumRule* pRule = GetNum() ? GetNum()->GetNumRule() : 0L;
+ if ( pRule && IsCountedInList() )
+ bResult = sal_True;
+
+ return bResult;
+}
+
+bool SwTxtNode::HasMarkedLabel() const
+{
+ bool bResult = false;
+
+ if ( IsInList() )
+ {
+ bResult =
+ GetDoc()->getListByName( GetListId() )->IsListLevelMarked( GetActualListLevel() );
+ }
+
+ return bResult;
+}
+// <- #i27615#
+
+SwTxtNode* SwTxtNode::_MakeNewTxtNode( const SwNodeIndex& rPos, sal_Bool bNext,
+ sal_Bool bChgFollow )
+{
+ /* hartes PageBreak/PageDesc/ColumnBreak aus AUTO-Set ignorieren */
+ SwAttrSet* pNewAttrSet = 0;
+ // --> OD 2007-07-10 #i75353#
+ bool bClearHardSetNumRuleWhenFmtCollChanges( false );
+ // <--
+ if( HasSwAttrSet() )
+ {
+ pNewAttrSet = new SwAttrSet( *GetpSwAttrSet() );
+ const SfxItemSet* pTmpSet = GetpSwAttrSet();
+
+ if( bNext ) // der naechste erbt keine Breaks!
+ pTmpSet = pNewAttrSet;
+
+ // PageBreaks/PageDesc/ColBreak rausschmeissen.
+ sal_Bool bRemoveFromCache = sal_False;
+ std::vector<sal_uInt16> aClearWhichIds;
+ if ( bNext )
+ bRemoveFromCache = ( 0 != pNewAttrSet->ClearItem( RES_PAGEDESC ) );
+ else
+ aClearWhichIds.push_back( RES_PAGEDESC );
+
+ if( SFX_ITEM_SET == pTmpSet->GetItemState( RES_BREAK, sal_False ) )
+ {
+ if ( bNext )
+ pNewAttrSet->ClearItem( RES_BREAK );
+ else
+ aClearWhichIds.push_back( RES_BREAK );
+ bRemoveFromCache = sal_True;
+ }
+ if( SFX_ITEM_SET == pTmpSet->GetItemState( RES_KEEP, sal_False ) )
+ {
+ if ( bNext )
+ pNewAttrSet->ClearItem( RES_KEEP );
+ else
+ aClearWhichIds.push_back( RES_KEEP );
+ bRemoveFromCache = sal_True;
+ }
+ if( SFX_ITEM_SET == pTmpSet->GetItemState( RES_PARATR_SPLIT, sal_False ) )
+ {
+ if ( bNext )
+ pNewAttrSet->ClearItem( RES_PARATR_SPLIT );
+ else
+ aClearWhichIds.push_back( RES_PARATR_SPLIT );
+ bRemoveFromCache = sal_True;
+ }
+ if(SFX_ITEM_SET == pTmpSet->GetItemState(RES_PARATR_NUMRULE, sal_False))
+ {
+ SwNumRule * pRule = GetNumRule();
+
+ if (pRule && IsOutline())
+ {
+ if ( bNext )
+ pNewAttrSet->ClearItem(RES_PARATR_NUMRULE);
+ else
+ {
+ // --> OD 2007-07-10 #i75353#
+ // No clear of hard set numbering rule at an outline paragraph at this point.
+ // Only if the paragraph style changes - see below.
+ bClearHardSetNumRuleWhenFmtCollChanges = true;
+ // <--
+ }
+ bRemoveFromCache = sal_True;
+ }
+ }
+
+ if ( 0 != aClearWhichIds.size() )
+ bRemoveFromCache = 0 != ClearItemsFromAttrSet( aClearWhichIds );
+
+ if( !bNext && bRemoveFromCache && IsInCache() )
+ {
+ SwFrm::GetCache().Delete( this );
+ SetInCache( sal_False );
+ }
+ }
+ SwNodes& rNds = GetNodes();
+
+ SwTxtFmtColl* pColl = GetTxtColl();
+
+ SwTxtNode *pNode = new SwTxtNode( rPos, pColl, pNewAttrSet );
+
+ if( pNewAttrSet )
+ delete pNewAttrSet;
+
+ const SwNumRule* pRule = GetNumRule();
+ if( pRule && pRule == pNode->GetNumRule() && rNds.IsDocNodes() ) // #115901#
+ {
+ // --> OD 2005-10-18 #i55459#
+ // - correction: parameter <bNext> has to be checked, as it was in the
+ // previous implementation.
+ if ( !bNext && !IsCountedInList() )
+ SetCountedInList(true);
+ // <--
+ }
+
+ // jetzt kann es sein, das durch die Nummerierung dem neuen Node eine
+ // Vorlage aus dem Pool zugewiesen wurde. Dann darf diese nicht
+ // nochmal uebergeplaettet werden !!
+ if( pColl != pNode->GetTxtColl() ||
+ ( bChgFollow && pColl != GetTxtColl() ))
+ return pNode; // mehr duerfte nicht gemacht werden oder ????
+
+ pNode->_ChgTxtCollUpdateNum( 0, pColl ); // fuer Nummerierung/Gliederung
+ if( bNext || !bChgFollow )
+ return pNode;
+
+ SwTxtFmtColl *pNextColl = &pColl->GetNextTxtFmtColl();
+ // --> OD 2009-08-12 #i101870#
+ // perform action on different paragraph styles before applying the new paragraph style
+ if (pNextColl != pColl)
+ {
+ // --> OD 2007-07-10 #i75353#
+ if ( bClearHardSetNumRuleWhenFmtCollChanges )
+ {
+ std::vector<sal_uInt16> aClearWhichIds;
+ aClearWhichIds.push_back( RES_PARATR_NUMRULE );
+ if ( ClearItemsFromAttrSet( aClearWhichIds ) != 0 && IsInCache() )
+ {
+ SwFrm::GetCache().Delete( this );
+ SetInCache( sal_False );
+ }
+ }
+ // <--
+ }
+ // <--
+ ChgFmtColl( pNextColl );
+
+ return pNode;
+}
+
+SwCntntNode* SwTxtNode::AppendNode( const SwPosition & rPos )
+{
+ // Position hinter dem eingefuegt wird
+ SwNodeIndex aIdx( rPos.nNode, 1 );
+ SwTxtNode* pNew = _MakeNewTxtNode( aIdx, sal_True );
+
+ // reset list attributes at appended text node
+ pNew->ResetAttr( RES_PARATR_LIST_ISRESTART );
+ pNew->ResetAttr( RES_PARATR_LIST_RESTARTVALUE );
+ pNew->ResetAttr( RES_PARATR_LIST_ISCOUNTED );
+ if ( pNew->GetNumRule() == 0 )
+ {
+ pNew->ResetAttr( RES_PARATR_LIST_ID );
+ pNew->ResetAttr( RES_PARATR_LIST_LEVEL );
+ }
+
+ if ( !IsInList() && GetNumRule() && GetListId().Len() > 0 )
+ {
+ AddToList();
+ }
+
+ if( GetDepends() )
+ MakeFrms( *pNew );
+ return pNew;
+}
+
+/*************************************************************************
+ * SwTxtNode::GetTxtAttr
+ *************************************************************************/
+
+SwTxtAttr * SwTxtNode::GetTxtAttrForCharAt( const xub_StrLen nIndex,
+ const RES_TXTATR nWhich ) const
+{
+ if ( HasHints() )
+ {
+ for ( sal_uInt16 i = 0; i < m_pSwpHints->Count(); ++i )
+ {
+ SwTxtAttr * const pHint = m_pSwpHints->GetTextHint(i);
+ const xub_StrLen nStartPos = *pHint->GetStart();
+ if ( nIndex < nStartPos )
+ {
+ return 0;
+ }
+ if ( (nIndex == nStartPos) && pHint->HasDummyChar() )
+ {
+ return ( RES_TXTATR_END == nWhich || nWhich == pHint->Which() )
+ ? pHint : 0;
+ }
+ }
+ }
+ return 0;
+}
+
+// -> #i29560#
+sal_Bool SwTxtNode::HasNumber() const
+{
+ sal_Bool bResult = sal_False;
+
+ const SwNumRule* pRule = GetNum() ? GetNum()->GetNumRule() : 0L;
+ if ( pRule )
+ {
+ SwNumFmt aFmt(pRule->Get( static_cast<sal_uInt16>(GetActualListLevel())));
+
+ // #i40041#
+ bResult = aFmt.IsEnumeration() &&
+ SVX_NUM_NUMBER_NONE != aFmt.GetNumberingType();
+ }
+
+ return bResult;
+}
+
+sal_Bool SwTxtNode::HasBullet() const
+{
+ sal_Bool bResult = sal_False;
+
+ const SwNumRule* pRule = GetNum() ? GetNum()->GetNumRule() : 0L;
+ if ( pRule )
+ {
+ SwNumFmt aFmt(pRule->Get( static_cast<sal_uInt16>(GetActualListLevel())));
+
+ bResult = aFmt.IsItemize();
+ }
+
+ return bResult;
+}
+// <- #i29560#
+
+// --> OD 2005-11-17 #128041# - introduce parameter <_bInclPrefixAndSuffixStrings>
+//i53420 added max outline parameter
+XubString SwTxtNode::GetNumString( const bool _bInclPrefixAndSuffixStrings, const unsigned int _nRestrictToThisLevel ) const
+{
+ if (GetDoc()->IsClipBoard() && m_pNumStringCache.get())
+ {
+ // #i111677# do not expand number strings in clipboard documents
+ return *m_pNumStringCache;
+ }
+ const SwNumRule* pRule = GetNum() ? GetNum()->GetNumRule() : 0L;
+ if ( pRule &&
+ IsCountedInList() )
+ {
+ SvxNumberType const& rNumberType(
+ pRule->Get( static_cast<sal_uInt16>(GetActualListLevel()) ) );
+ if (rNumberType.IsTxtFmt() ||
+ // #b6432095#
+ (style::NumberingType::NUMBER_NONE == rNumberType.GetNumberingType()))
+ {
+ return pRule->MakeNumString( GetNum()->GetNumberVector(),
+ _bInclPrefixAndSuffixStrings ? sal_True : sal_False,
+ sal_False,
+ _nRestrictToThisLevel );
+ }
+ }
+
+ return aEmptyStr;
+}
+
+long SwTxtNode::GetLeftMarginWithNum( sal_Bool bTxtLeft ) const
+{
+ long nRet = 0;
+ const SwNumRule* pRule = GetNum() ? GetNum()->GetNumRule() : 0L;
+ if( pRule )
+ {
+ const SwNumFmt& rFmt = pRule->Get(static_cast<sal_uInt16>(GetActualListLevel()));
+
+ if ( rFmt.GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_WIDTH_AND_POSITION )
+ {
+ nRet = rFmt.GetAbsLSpace();
+
+ if( !bTxtLeft )
+ {
+ if( 0 > rFmt.GetFirstLineOffset() &&
+ nRet > -rFmt.GetFirstLineOffset() )
+ nRet = nRet + rFmt.GetFirstLineOffset();
+ else
+ nRet = 0;
+ }
+
+ if( pRule->IsAbsSpaces() )
+ nRet = nRet - GetSwAttrSet().GetLRSpace().GetLeft();
+ }
+ else if ( rFmt.GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_ALIGNMENT )
+ {
+ if ( AreListLevelIndentsApplicable() )
+ {
+ nRet = rFmt.GetIndentAt();
+ // --> OD 2008-06-06 #i90401#
+ // Only negative first line indents have consider for the left margin
+ if ( !bTxtLeft &&
+ rFmt.GetFirstLineIndent() < 0 )
+ {
+ nRet = nRet + rFmt.GetFirstLineIndent();
+ }
+ }
+ }
+ }
+
+ return nRet;
+}
+
+sal_Bool SwTxtNode::GetFirstLineOfsWithNum( short& rFLOffset ) const
+{
+ sal_Bool bRet( sal_False );
+ // --> OD 2009-09-08 #i95907#, #b6879723#
+ rFLOffset = 0;
+ // <--
+
+ // --> OD 2005-11-02 #i51089 - TUNING#
+ const SwNumRule* pRule = GetNum() ? GetNum()->GetNumRule() : 0L;
+ if ( pRule )
+ {
+ if ( IsCountedInList() )
+ {
+ const SwNumFmt& rFmt = pRule->Get(static_cast<sal_uInt16>(GetActualListLevel()));
+ if ( rFmt.GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_WIDTH_AND_POSITION )
+ {
+ rFLOffset = pRule->Get( static_cast<sal_uInt16>(GetActualListLevel() )).GetFirstLineOffset();
+
+ if (!getIDocumentSettingAccess()->get(IDocumentSettingAccess::IGNORE_FIRST_LINE_INDENT_IN_NUMBERING))
+ {
+ SvxLRSpaceItem aItem = GetSwAttrSet().GetLRSpace();
+ rFLOffset = rFLOffset + aItem.GetTxtFirstLineOfst();
+ }
+ }
+ else if ( rFmt.GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_ALIGNMENT )
+ {
+ if ( AreListLevelIndentsApplicable() )
+ {
+ rFLOffset = static_cast<sal_uInt16>(rFmt.GetFirstLineIndent());
+ }
+ else if (!getIDocumentSettingAccess()->get(IDocumentSettingAccess::IGNORE_FIRST_LINE_INDENT_IN_NUMBERING))
+ {
+ SvxLRSpaceItem aItem = GetSwAttrSet().GetLRSpace();
+ rFLOffset = aItem.GetTxtFirstLineOfst();
+ }
+ }
+ }
+
+ bRet = sal_True;
+ }
+ else
+ {
+ rFLOffset = GetSwAttrSet().GetLRSpace().GetTxtFirstLineOfst();
+ }
+
+ return bRet;
+}
+
+// --> OD 2010-01-05 #b6884103#
+SwTwips SwTxtNode::GetAdditionalIndentForStartingNewList() const
+{
+ SwTwips nAdditionalIndent = 0;
+
+ const SwNumRule* pRule = GetNum() ? GetNum()->GetNumRule() : 0L;
+ if ( pRule )
+ {
+ const SwNumFmt& rFmt = pRule->Get(static_cast<sal_uInt16>(GetActualListLevel()));
+ if ( rFmt.GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_WIDTH_AND_POSITION )
+ {
+ nAdditionalIndent = GetSwAttrSet().GetLRSpace().GetLeft();
+
+ if (getIDocumentSettingAccess()->get(IDocumentSettingAccess::IGNORE_FIRST_LINE_INDENT_IN_NUMBERING))
+ {
+ nAdditionalIndent = nAdditionalIndent -
+ GetSwAttrSet().GetLRSpace().GetTxtFirstLineOfst();
+ }
+ }
+ else if ( rFmt.GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_ALIGNMENT )
+ {
+ if ( AreListLevelIndentsApplicable() )
+ {
+ nAdditionalIndent = rFmt.GetIndentAt() + rFmt.GetFirstLineIndent();
+ }
+ else
+ {
+ nAdditionalIndent = GetSwAttrSet().GetLRSpace().GetLeft();
+ if (getIDocumentSettingAccess()->get(IDocumentSettingAccess::IGNORE_FIRST_LINE_INDENT_IN_NUMBERING))
+ {
+ nAdditionalIndent = nAdditionalIndent -
+ GetSwAttrSet().GetLRSpace().GetTxtFirstLineOfst();
+ }
+ }
+ }
+ }
+ else
+ {
+ nAdditionalIndent = GetSwAttrSet().GetLRSpace().GetLeft();
+ }
+
+ return nAdditionalIndent;
+}
+
+// --> OD 2008-12-02 #i96772#
+void SwTxtNode::ClearLRSpaceItemDueToListLevelIndents( SvxLRSpaceItem& o_rLRSpaceItem ) const
+{
+ if ( AreListLevelIndentsApplicable() )
+ {
+ const SwNumRule* pRule = GetNumRule();
+ if ( pRule && GetActualListLevel() >= 0 )
+ {
+ const SwNumFmt& rFmt = pRule->Get(static_cast<sal_uInt16>(GetActualListLevel()));
+ if ( rFmt.GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_ALIGNMENT )
+ {
+ SvxLRSpaceItem aLR( RES_LR_SPACE );
+ o_rLRSpaceItem = aLR;
+ }
+ }
+ }
+}
+
+// --> OD 2008-07-01 #i91133#
+long SwTxtNode::GetLeftMarginForTabCalculation() const
+{
+ long nLeftMarginForTabCalc = 0;
+
+ bool bLeftMarginForTabCalcSetToListLevelIndent( false );
+ const SwNumRule* pRule = GetNum() ? GetNum()->GetNumRule() : 0;
+ if( pRule )
+ {
+ const SwNumFmt& rFmt = pRule->Get(static_cast<sal_uInt16>(GetActualListLevel()));
+ if ( rFmt.GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_ALIGNMENT )
+ {
+ if ( AreListLevelIndentsApplicable() )
+ {
+ nLeftMarginForTabCalc = rFmt.GetIndentAt();
+ bLeftMarginForTabCalcSetToListLevelIndent = true;
+ }
+ }
+ }
+ if ( !bLeftMarginForTabCalcSetToListLevelIndent )
+ {
+ nLeftMarginForTabCalc = GetSwAttrSet().GetLRSpace().GetTxtLeft();
+ }
+
+ return nLeftMarginForTabCalc;
+}
+
+void SwTxtNode::Replace0xFF( XubString& rTxt, xub_StrLen& rTxtStt,
+ xub_StrLen nEndPos, sal_Bool bExpandFlds ) const
+{
+ if( GetpSwpHints() )
+ {
+ sal_Unicode cSrchChr = CH_TXTATR_BREAKWORD;
+ for( int nSrchIter = 0; 2 > nSrchIter; ++nSrchIter,
+ cSrchChr = CH_TXTATR_INWORD )
+ {
+ xub_StrLen nPos = rTxt.Search( cSrchChr );
+ while( STRING_NOTFOUND != nPos && nPos < nEndPos )
+ {
+ const SwTxtAttr* const pAttr =
+ GetTxtAttrForCharAt( rTxtStt + nPos );
+ if( pAttr )
+ {
+ switch( pAttr->Which() )
+ {
+ case RES_TXTATR_FIELD:
+ rTxt.Erase( nPos, 1 );
+ if( bExpandFlds )
+ {
+ const XubString aExpand(
+ static_cast<SwTxtFld const*>(pAttr)->GetFld()
+ .GetFld()->ExpandField(true));
+ rTxt.Insert( aExpand, nPos );
+ nPos = nPos + aExpand.Len();
+ nEndPos = nEndPos + aExpand.Len();
+ rTxtStt = rTxtStt - aExpand.Len();
+ }
+ ++rTxtStt;
+ break;
+ case RES_TXTATR_FTN:
+ rTxt.Erase( nPos, 1 );
+ if( bExpandFlds )
+ {
+ const SwFmtFtn& rFtn = pAttr->GetFtn();
+ XubString sExpand;
+ if( rFtn.GetNumStr().Len() )
+ sExpand = rFtn.GetNumStr();
+ else if( rFtn.IsEndNote() )
+ sExpand = GetDoc()->GetEndNoteInfo().aFmt.
+ GetNumStr( rFtn.GetNumber() );
+ else
+ sExpand = GetDoc()->GetFtnInfo().aFmt.
+ GetNumStr( rFtn.GetNumber() );
+ rTxt.Insert( sExpand, nPos );
+ nPos = nPos + sExpand.Len();
+ nEndPos = nEndPos + sExpand.Len();
+ rTxtStt = rTxtStt - sExpand.Len();
+ }
+ ++rTxtStt;
+ break;
+ default:
+ rTxt.Erase( nPos, 1 );
+ ++rTxtStt;
+ }
+ }
+ else
+ ++nPos, ++nEndPos;
+ nPos = rTxt.Search( cSrchChr, nPos );
+ }
+ }
+ }
+}
+
+/*************************************************************************
+ * SwTxtNode::GetExpandTxt
+ * Expand fields
+ *************************************************************************/
+// --> OD 2007-11-15 #i83479# - handling of new parameters
+XubString SwTxtNode::GetExpandTxt( const xub_StrLen nIdx,
+ const xub_StrLen nLen,
+ const bool bWithNum,
+ const bool bAddSpaceAfterListLabelStr,
+ const bool bWithSpacesForLevel ) const
+{
+ XubString aTxt( GetTxt().Copy( nIdx, nLen ) );
+ xub_StrLen nTxtStt = nIdx;
+ Replace0xFF( aTxt, nTxtStt, aTxt.Len(), sal_True );
+ if( bWithNum )
+ {
+ XubString aListLabelStr = GetNumString();
+ if ( aListLabelStr.Len() > 0 )
+ {
+ if ( bAddSpaceAfterListLabelStr )
+ {
+ const sal_Unicode aSpace = ' ';
+ aTxt.Insert( aSpace, 0 );
+ }
+ aTxt.Insert( GetNumString(), 0 );
+ }
+ }
+
+ if ( bWithSpacesForLevel && GetActualListLevel() > 0 )
+ {
+ int nLevel( GetActualListLevel() );
+ while ( nLevel > 0 )
+ {
+ const sal_Unicode aSpace = ' ';
+ aTxt.Insert( aSpace , 0 );
+ aTxt.Insert( aSpace , 0 );
+ --nLevel;
+ }
+ }
+
+ return aTxt;
+}
+
+sal_Bool SwTxtNode::GetExpandTxt( SwTxtNode& rDestNd, const SwIndex* pDestIdx,
+ xub_StrLen nIdx, xub_StrLen nLen, sal_Bool bWithNum,
+ sal_Bool bWithFtn, sal_Bool bReplaceTabsWithSpaces ) const
+{
+ if( &rDestNd == this )
+ return sal_False;
+
+ SwIndex aDestIdx( &rDestNd, rDestNd.GetTxt().Len() );
+ if( pDestIdx )
+ aDestIdx = *pDestIdx;
+ xub_StrLen nDestStt = aDestIdx.GetIndex();
+
+ // Text einfuegen
+ String sTmpText = GetTxt();
+ if( bReplaceTabsWithSpaces )
+ sTmpText.SearchAndReplaceAll('\t', ' ');
+
+ // mask hidden characters
+ const xub_Unicode cChar = CH_TXTATR_BREAKWORD;
+ sal_uInt16 nHiddenChrs =
+ SwScriptInfo::MaskHiddenRanges( *this, sTmpText, 0, sTmpText.Len(), cChar );
+
+ sTmpText = sTmpText.Copy( nIdx, nLen );
+ rDestNd.InsertText( sTmpText, aDestIdx );
+ nLen = aDestIdx.GetIndex() - nDestStt;
+
+ // alle FontAttribute mit CHARSET Symbol in dem Bereich setzen
+ if ( HasHints() )
+ {
+ xub_StrLen nInsPos = nDestStt - nIdx;
+ for ( sal_uInt16 i = 0; i < m_pSwpHints->Count(); i++ )
+ {
+ const SwTxtAttr* pHt = (*m_pSwpHints)[i];
+ const xub_StrLen nAttrStartIdx = *pHt->GetStart();
+ const sal_uInt16 nWhich = pHt->Which();
+ if (nIdx + nLen <= nAttrStartIdx)
+ break; // ueber das Textende
+
+ const xub_StrLen *pEndIdx = pHt->GetEnd();
+ if( pEndIdx && *pEndIdx > nIdx &&
+ ( RES_CHRATR_FONT == nWhich ||
+ RES_TXTATR_CHARFMT == nWhich ||
+ RES_TXTATR_AUTOFMT == nWhich ))
+ {
+ const SvxFontItem* const pFont =
+ static_cast<const SvxFontItem*>(
+ CharFmt::GetItem( *pHt, RES_CHRATR_FONT ));
+ if ( pFont && RTL_TEXTENCODING_SYMBOL == pFont->GetCharSet() )
+ {
+ // attribute in area => copy
+ rDestNd.InsertItem( *const_cast<SvxFontItem*>(pFont),
+ nInsPos + nAttrStartIdx, nInsPos + *pEndIdx );
+ }
+ }
+ else if ( pHt->HasDummyChar() && (nAttrStartIdx >= nIdx) )
+ {
+ aDestIdx = nInsPos + nAttrStartIdx;
+ switch( nWhich )
+ {
+ case RES_TXTATR_FIELD:
+ {
+ XubString const aExpand(
+ static_cast<SwTxtFld const*>(pHt)->GetFld().GetFld()
+ ->ExpandField(true));
+ if( aExpand.Len() )
+ {
+ aDestIdx++; // dahinter einfuegen;
+ rDestNd.InsertText( aExpand, aDestIdx );
+ aDestIdx = nInsPos + nAttrStartIdx;
+ nInsPos = nInsPos + aExpand.Len();
+ }
+ rDestNd.EraseText( aDestIdx, 1 );
+ --nInsPos;
+ }
+ break;
+
+ case RES_TXTATR_FTN:
+ {
+ if ( bWithFtn )
+ {
+ const SwFmtFtn& rFtn = pHt->GetFtn();
+ XubString sExpand;
+ if( rFtn.GetNumStr().Len() )
+ sExpand = rFtn.GetNumStr();
+ else if( rFtn.IsEndNote() )
+ sExpand = GetDoc()->GetEndNoteInfo().aFmt.
+ GetNumStr( rFtn.GetNumber() );
+ else
+ sExpand = GetDoc()->GetFtnInfo().aFmt.
+ GetNumStr( rFtn.GetNumber() );
+ if( sExpand.Len() )
+ {
+ aDestIdx++; // insert behind
+ SvxEscapementItem aItem(
+ SVX_ESCAPEMENT_SUPERSCRIPT );
+ rDestNd.InsertItem(aItem,
+ aDestIdx.GetIndex(),
+ aDestIdx.GetIndex() );
+ rDestNd.InsertText( sExpand, aDestIdx,
+ IDocumentContentOperations::INS_EMPTYEXPAND);
+ aDestIdx = nInsPos + nAttrStartIdx;
+ nInsPos = nInsPos + sExpand.Len();
+ }
+ }
+ rDestNd.EraseText( aDestIdx, 1 );
+ --nInsPos;
+ }
+ break;
+
+ default:
+ rDestNd.EraseText( aDestIdx, 1 );
+ --nInsPos;
+ }
+ }
+ }
+ }
+
+ if( bWithNum )
+ {
+ aDestIdx = nDestStt;
+ rDestNd.InsertText( GetNumString(), aDestIdx );
+ }
+
+ if ( nHiddenChrs > 0 )
+ {
+ aDestIdx = 0;
+ while ( aDestIdx < rDestNd.GetTxt().Len() )
+ {
+ if ( cChar == rDestNd.GetTxt().GetChar( aDestIdx.GetIndex() ) )
+ {
+ xub_StrLen nIndex = aDestIdx.GetIndex();
+ while ( nIndex < rDestNd.GetTxt().Len() &&
+ cChar == rDestNd.GetTxt().GetChar( ++nIndex ) )
+ ;
+ rDestNd.EraseText( aDestIdx, nIndex - aDestIdx.GetIndex() );
+ }
+ else
+ ++aDestIdx;
+ }
+ }
+
+ return sal_True;
+}
+
+const ModelToViewHelper::ConversionMap*
+ SwTxtNode::BuildConversionMap( rtl::OUString& rRetText ) const
+{
+ const rtl::OUString& rNodeText = GetTxt();
+ rRetText = rNodeText;
+ ModelToViewHelper::ConversionMap* pConversionMap = 0;
+
+ const SwpHints* pSwpHints2 = GetpSwpHints();
+ xub_StrLen nPos = 0;
+
+ for ( sal_uInt16 i = 0; pSwpHints2 && i < pSwpHints2->Count(); ++i )
+ {
+ const SwTxtAttr* pAttr = (*pSwpHints2)[i];
+ if ( RES_TXTATR_FIELD == pAttr->Which() )
+ {
+ const XubString aExpand(
+ static_cast<SwTxtFld const*>(pAttr)->GetFld().GetFld()
+ ->ExpandField(true));
+ if ( aExpand.Len() > 0 )
+ {
+ const xub_StrLen nFieldPos = *pAttr->GetStart();
+ rRetText = rRetText.replaceAt( nPos + nFieldPos, 1, aExpand );
+ if ( !pConversionMap )
+ pConversionMap = new ModelToViewHelper::ConversionMap;
+ pConversionMap->push_back(
+ ModelToViewHelper::ConversionMapEntry(
+ nFieldPos, nPos + nFieldPos ) );
+ nPos += ( aExpand.Len() - 1 );
+ }
+ }
+ }
+
+ if ( pConversionMap && pConversionMap->size() )
+ pConversionMap->push_back(
+ ModelToViewHelper::ConversionMapEntry(
+ rNodeText.getLength()+1, rRetText.getLength()+1 ) );
+
+ return pConversionMap;
+}
+
+XubString SwTxtNode::GetRedlineTxt( xub_StrLen nIdx, xub_StrLen nLen,
+ sal_Bool bExpandFlds, sal_Bool bWithNum ) const
+{
+ SvUShorts aRedlArr;
+ const SwDoc* pDoc = GetDoc();
+ sal_uInt16 nRedlPos = pDoc->GetRedlinePos( *this, nsRedlineType_t::REDLINE_DELETE );
+ if( USHRT_MAX != nRedlPos )
+ {
+ // es existiert fuer den Node irgendein Redline-Delete-Object
+ const sal_uLong nNdIdx = GetIndex();
+ for( ; nRedlPos < pDoc->GetRedlineTbl().Count() ; ++nRedlPos )
+ {
+ const SwRedline* pTmp = pDoc->GetRedlineTbl()[ nRedlPos ];
+ if( nsRedlineType_t::REDLINE_DELETE == pTmp->GetType() )
+ {
+ const SwPosition *pRStt = pTmp->Start(), *pREnd = pTmp->End();
+ if( pRStt->nNode < nNdIdx )
+ {
+ if( pREnd->nNode > nNdIdx )
+ // Absatz ist komplett geloescht
+ return aEmptyStr;
+ else if( pREnd->nNode == nNdIdx )
+ {
+ // von 0 bis nContent ist alles geloescht
+ aRedlArr.Insert( xub_StrLen(0), aRedlArr.Count() );
+ aRedlArr.Insert( pREnd->nContent.GetIndex(), aRedlArr.Count() );
+ }
+ }
+ else if( pRStt->nNode == nNdIdx )
+ {
+ aRedlArr.Insert( pRStt->nContent.GetIndex(), aRedlArr.Count() );
+ if( pREnd->nNode == nNdIdx )
+ aRedlArr.Insert( pREnd->nContent.GetIndex(), aRedlArr.Count() );
+ else
+ {
+ aRedlArr.Insert( GetTxt().Len(), aRedlArr.Count() );
+ break; // mehr kann nicht kommen
+ }
+ }
+ else
+ break; // mehr kann nicht kommen
+ }
+ }
+ }
+
+ XubString aTxt( GetTxt().Copy( nIdx, nLen ) );
+
+ xub_StrLen nTxtStt = nIdx, nIdxEnd = nIdx + aTxt.Len();
+ for( sal_uInt16 n = 0; n < aRedlArr.Count(); n += 2 )
+ {
+ xub_StrLen nStt = aRedlArr[ n ], nEnd = aRedlArr[ n+1 ];
+ if( ( nIdx <= nStt && nStt <= nIdxEnd ) ||
+ ( nIdx <= nEnd && nEnd <= nIdxEnd ))
+ {
+ if( nStt < nIdx ) nStt = nIdx;
+ if( nIdxEnd < nEnd ) nEnd = nIdxEnd;
+ xub_StrLen nDelCnt = nEnd - nStt;
+ aTxt.Erase( nStt - nTxtStt, nDelCnt );
+ Replace0xFF( aTxt, nTxtStt, nStt - nTxtStt, bExpandFlds );
+ nTxtStt = nTxtStt + nDelCnt;
+ }
+ else if( nStt >= nIdxEnd )
+ break;
+ }
+ Replace0xFF( aTxt, nTxtStt, aTxt.Len(), bExpandFlds );
+
+ if( bWithNum )
+ aTxt.Insert( GetNumString(), 0 );
+ return aTxt;
+}
+
+/*************************************************************************
+ * SwTxtNode::ReplaceText
+ *************************************************************************/
+
+void SwTxtNode::ReplaceText( const SwIndex& rStart, const xub_StrLen nDelLen,
+ const XubString& rText )
+{
+ OSL_ENSURE( rStart.GetIndex() < m_Text.Len() &&
+ rStart.GetIndex() + nDelLen <= m_Text.Len(),
+ "SwTxtNode::ReplaceText: index out of bounds" );
+ const xub_StrLen nStartPos = rStart.GetIndex();
+ xub_StrLen nEndPos = nStartPos + nDelLen;
+ xub_StrLen nLen = nDelLen;
+ for ( xub_StrLen nPos = nStartPos; nPos < nEndPos; ++nPos )
+ {
+ if ( ( CH_TXTATR_BREAKWORD == m_Text.GetChar( nPos ) ) ||
+ ( CH_TXTATR_INWORD == m_Text.GetChar( nPos ) ) )
+ {
+ SwTxtAttr *const pHint = GetTxtAttrForCharAt( nPos );
+ if (pHint)
+ {
+ OSL_ENSURE(!( pHint->GetEnd() && pHint->HasDummyChar()
+ && (*pHint->GetStart() < nEndPos)
+ && (*pHint->GetEnd() > nEndPos) ),
+ "ReplaceText: ERROR: "
+ "deleting left-overlapped attribute with CH_TXTATR");
+ DeleteAttribute( pHint );
+ --nEndPos;
+ --nLen;
+ }
+ }
+ }
+
+ sal_Bool bOldExpFlg = IsIgnoreDontExpand();
+ SetIgnoreDontExpand( sal_True );
+
+ if( nLen && rText.Len() )
+ {
+ // dann das 1. Zeichen ersetzen den Rest loschen und einfuegen
+ // Dadurch wird die Attributierung des 1. Zeichen expandiert!
+ m_Text.SetChar( nStartPos, rText.GetChar( 0 ) );
+
+ ((SwIndex&)rStart)++;
+ m_Text.Erase( rStart.GetIndex(), nLen - 1 );
+ Update( rStart, nLen - 1, true );
+
+ XubString aTmpTxt( rText ); aTmpTxt.Erase( 0, 1 );
+ m_Text.Insert( aTmpTxt, rStart.GetIndex() );
+ Update( rStart, aTmpTxt.Len(), false );
+ }
+ else
+ {
+ m_Text.Erase( nStartPos, nLen );
+ Update( rStart, nLen, true );
+
+ m_Text.Insert( rText, nStartPos );
+ Update( rStart, rText.Len(), false );
+ }
+
+ SetIgnoreDontExpand( bOldExpFlg );
+ SwDelTxt aDelHint( nStartPos, nDelLen );
+ NotifyClients( 0, &aDelHint );
+
+ SwInsTxt aHint( nStartPos, rText.Len() );
+ NotifyClients( 0, &aHint );
+}
+
+namespace {
+ // Helper method for special handling of modified attributes at text node.
+ // The following is handled:
+ // (1) on changing the paragraph style - RES_FMT_CHG:
+ // Check, if list style of the text node is changed. If yes, add respectively
+ // remove the text node to the corresponding list.
+ // (2) on changing the attributes - RES_ATTRSET_CHG:
+ // Same as (1).
+ // (3) on changing the list style - RES_PARATR_NUMRULE:
+ // Same as (1).
+ void HandleModifyAtTxtNode( SwTxtNode& rTxtNode,
+ const SfxPoolItem* pOldValue,
+ const SfxPoolItem* pNewValue )
+ {
+ const sal_uInt16 nWhich = pOldValue ? pOldValue->Which() :
+ pNewValue ? pNewValue->Which() : 0 ;
+ bool bNumRuleSet = false;
+ bool bParagraphStyleChanged = false;
+ String sNumRule;
+ String sOldNumRule;
+ switch ( nWhich )
+ {
+ case RES_FMT_CHG:
+ {
+ bParagraphStyleChanged = true;
+ if( rTxtNode.GetNodes().IsDocNodes() )
+ {
+ // #i70748#
+ const SwNumRule* pFormerNumRuleAtTxtNode =
+ rTxtNode.GetNum() ? rTxtNode.GetNum()->GetNumRule() : 0;
+ if ( pFormerNumRuleAtTxtNode )
+ {
+ sOldNumRule = pFormerNumRuleAtTxtNode->GetName();
+ }
+ // #i70748#
+ if ( rTxtNode.IsEmptyListStyleDueToSetOutlineLevelAttr() )
+ {
+ const SwNumRuleItem& rNumRuleItem = rTxtNode.GetTxtColl()->GetNumRule();
+ if ( rNumRuleItem.GetValue().Len() > 0 )
+ {
+ rTxtNode.ResetEmptyListStyleDueToResetOutlineLevelAttr();
+ }
+ }
+
+ const SwNumRule* pNumRuleAtTxtNode = rTxtNode.GetNumRule();
+ if ( pNumRuleAtTxtNode )
+ {
+ bNumRuleSet = true;
+ sNumRule = pNumRuleAtTxtNode->GetName();
+ }
+ }
+ break;
+ }
+ case RES_ATTRSET_CHG:
+ {
+ const SfxPoolItem* pItem = 0;
+ // #i70748#
+ const SwNumRule* pFormerNumRuleAtTxtNode =
+ rTxtNode.GetNum() ? rTxtNode.GetNum()->GetNumRule() : 0;
+ if ( pFormerNumRuleAtTxtNode )
+ {
+ sOldNumRule = pFormerNumRuleAtTxtNode->GetName();
+ }
+
+ if ( dynamic_cast<const SwAttrSetChg*>(pNewValue)->GetChgSet()->GetItemState( RES_PARATR_NUMRULE, sal_False, &pItem ) ==
+ SFX_ITEM_SET )
+ {
+ // #i70748#
+ rTxtNode.ResetEmptyListStyleDueToResetOutlineLevelAttr();
+ bNumRuleSet = true;
+ }
+ // #i70748#
+ // The new list style set at the paragraph.
+ const SwNumRule* pNumRuleAtTxtNode = rTxtNode.GetNumRule();
+ if ( pNumRuleAtTxtNode )
+ {
+ sNumRule = pNumRuleAtTxtNode->GetName();
+ }
+ break;
+ }
+ case RES_PARATR_NUMRULE:
+ {
+ if ( rTxtNode.GetNodes().IsDocNodes() )
+ {
+ const SwNumRule* pFormerNumRuleAtTxtNode =
+ rTxtNode.GetNum() ? rTxtNode.GetNum()->GetNumRule() : 0;
+ if ( pFormerNumRuleAtTxtNode )
+ {
+ sOldNumRule = pFormerNumRuleAtTxtNode->GetName();
+ }
+
+ if ( pNewValue )
+ {
+ // #i70748#
+ rTxtNode.ResetEmptyListStyleDueToResetOutlineLevelAttr();
+ bNumRuleSet = true;
+ }
+ // --> OD 2008-12-17 #i70748#
+ // The new list style set at the paragraph.
+ const SwNumRule* pNumRuleAtTxtNode = rTxtNode.GetNumRule();
+ if ( pNumRuleAtTxtNode )
+ {
+ sNumRule = pNumRuleAtTxtNode->GetName();
+ }
+ }
+ break;
+ }
+ }
+ if ( sNumRule != sOldNumRule )
+ {
+ if ( bNumRuleSet )
+ {
+ if ( sNumRule.Len() == 0 )
+ {
+ rTxtNode.RemoveFromList();
+ if ( bParagraphStyleChanged )
+ {
+ SvUShortsSort aResetAttrsArray;
+ aResetAttrsArray.Insert( RES_PARATR_LIST_ID );
+ aResetAttrsArray.Insert( RES_PARATR_LIST_LEVEL );
+ aResetAttrsArray.Insert( RES_PARATR_LIST_ISRESTART );
+ aResetAttrsArray.Insert( RES_PARATR_LIST_RESTARTVALUE );
+ aResetAttrsArray.Insert( RES_PARATR_LIST_ISCOUNTED );
+ SwPaM aPam( rTxtNode );
+ // --> OD 2008-11-28 #i96644#
+ // suppress side effect "send data changed events"
+ rTxtNode.GetDoc()->ResetAttrs( aPam, sal_False,
+ &aResetAttrsArray,
+ false );
+ }
+ }
+ else
+ {
+ rTxtNode.RemoveFromList();
+ // If new list style is the outline style, apply outline
+ // level as the list level.
+ if ( sNumRule ==
+ String::CreateFromAscii( SwNumRule::GetOutlineRuleName() ) )
+ {
+ // --> OD 2008-09-10 #i70748#
+ OSL_ENSURE( rTxtNode.GetTxtColl()->IsAssignedToListLevelOfOutlineStyle(),
+ "<HandleModifyAtTxtNode()> - text node with outline style, but its paragraph style is not assigned to outline style." );
+ int nNewListLevel =
+ rTxtNode.GetTxtColl()->GetAssignedOutlineStyleLevel();
+ if ( 0 <= nNewListLevel && nNewListLevel < MAXLEVEL )
+ {
+ rTxtNode.SetAttrListLevel( nNewListLevel );
+ }
+ }
+ rTxtNode.AddToList();
+ }
+ }
+ else // <sNumRule.Len() == 0 && sOldNumRule.Len() != 0>
+ {
+ rTxtNode.RemoveFromList();
+ if ( bParagraphStyleChanged )
+ {
+ SvUShortsSort aResetAttrsArray;
+ aResetAttrsArray.Insert( RES_PARATR_LIST_ID );
+ aResetAttrsArray.Insert( RES_PARATR_LIST_LEVEL );
+ aResetAttrsArray.Insert( RES_PARATR_LIST_ISRESTART );
+ aResetAttrsArray.Insert( RES_PARATR_LIST_RESTARTVALUE );
+ aResetAttrsArray.Insert( RES_PARATR_LIST_ISCOUNTED );
+ SwPaM aPam( rTxtNode );
+ // --> OD 2008-11-28 #i96644#
+ // suppress side effect "send data changed events"
+ rTxtNode.GetDoc()->ResetAttrs( aPam, sal_False,
+ &aResetAttrsArray,
+ false );
+ // <--
+ // --> OD 2008-11-19 #i70748#
+ if ( dynamic_cast<const SfxUInt16Item &>(rTxtNode.GetAttr( RES_PARATR_OUTLINELEVEL, sal_False )).GetValue() > 0 )
+ {
+ rTxtNode.SetEmptyListStyleDueToSetOutlineLevelAttr();
+ }
+ // <--
+ }
+ }
+ }
+ else if ( sNumRule.Len() > 0 && !rTxtNode.IsInList() )
+ {
+ rTxtNode.AddToList();
+ }
+ }
+ // End of method <HandleModifyAtTxtNode>
+}
+
+void SwTxtNode::Modify( const SfxPoolItem* pOldValue, const SfxPoolItem* pNewValue )
+{
+ bool bWasNotifiable = m_bNotifiable;
+ m_bNotifiable = false;
+
+ // Bug 24616/24617:
+ // Modify ueberladen, damit beim Loeschen von Vorlagen diese
+ // wieder richtig verwaltet werden (Outline-Numerierung!!)
+ // Bug25481:
+ // bei Nodes im Undo nie _ChgTxtCollUpdateNum rufen.
+ if( pOldValue && pNewValue && RES_FMT_CHG == pOldValue->Which() &&
+ GetRegisteredIn() == ((SwFmtChg*)pNewValue)->pChangedFmt &&
+ GetNodes().IsDocNodes() )
+ {
+ _ChgTxtCollUpdateNum(
+ (SwTxtFmtColl*)((SwFmtChg*)pOldValue)->pChangedFmt,
+ (SwTxtFmtColl*)((SwFmtChg*)pNewValue)->pChangedFmt );
+ }
+
+ if ( !mbInSetOrResetAttr )
+ {
+ HandleModifyAtTxtNode( *this, pOldValue, pNewValue );
+ }
+
+ SwCntntNode::Modify( pOldValue, pNewValue );
+
+ SwDoc * pDoc = GetDoc();
+ // --> OD 2005-11-02 #125329# - assure that text node is in document nodes array
+ if ( pDoc && !pDoc->IsInDtor() && &pDoc->GetNodes() == &GetNodes() )
+ // <--
+ {
+ pDoc->GetNodes().UpdateOutlineNode(*this);
+ }
+
+ m_bNotifiable = bWasNotifiable;
+
+ if (pOldValue && (RES_REMOVE_UNO_OBJECT == pOldValue->Which()))
+ { // invalidate cached uno object
+ SetXParagraph(::com::sun::star::uno::Reference<
+ ::com::sun::star::text::XTextContent>(0));
+ }
+}
+
+SwFmtColl* SwTxtNode::ChgFmtColl( SwFmtColl *pNewColl )
+{
+ OSL_ENSURE( pNewColl,"ChgFmtColl: Collectionpointer ist 0." );
+ OSL_ENSURE( HAS_BASE( SwTxtFmtColl, pNewColl ),
+ "ChgFmtColl: ist kein Text-Collectionpointer." );
+
+ SwTxtFmtColl *pOldColl = GetTxtColl();
+ if( pNewColl != pOldColl )
+ {
+ SetCalcHiddenCharFlags();
+ SwCntntNode::ChgFmtColl( pNewColl );
+#if OSL_DEBUG_LEVEL > 1
+ OSL_ENSURE( !mbInSetOrResetAttr,
+ "DEBUG OSL_ENSURE(ON - <SwTxtNode::ChgFmtColl(..)> called during <Set/ResetAttr(..)>" );
+#endif
+ if ( !mbInSetOrResetAttr )
+ {
+ SwFmtChg aTmp1( pOldColl );
+ SwFmtChg aTmp2( pNewColl );
+ HandleModifyAtTxtNode( *this, &aTmp1, &aTmp2 );
+ }
+ }
+
+ // nur wenn im normalen Nodes-Array
+ if( GetNodes().IsDocNodes() )
+ {
+ _ChgTxtCollUpdateNum( pOldColl, static_cast<SwTxtFmtColl *>(pNewColl) );
+ }
+
+ GetNodes().UpdateOutlineNode(*this);
+
+ return pOldColl;
+}
+
+SwNodeNum* SwTxtNode::CreateNum() const
+{
+ if ( !mpNodeNum )
+ {
+ mpNodeNum = new SwNodeNum( const_cast<SwTxtNode*>(this) );
+ }
+ return mpNodeNum;
+}
+
+SwNumberTree::tNumberVector SwTxtNode::GetNumberVector() const
+{
+ if ( GetNum() )
+ {
+ return GetNum()->GetNumberVector();
+ }
+ else
+ {
+ SwNumberTree::tNumberVector aResult;
+ return aResult;
+ }
+}
+
+bool SwTxtNode::IsOutline() const
+{
+ bool bResult = false;
+
+ if ( GetAttrOutlineLevel() > 0 )
+ {
+ bResult = !IsInRedlines();
+ }
+ else
+ {
+ const SwNumRule* pRule( GetNum() ? GetNum()->GetNumRule() : 0L );
+ if ( pRule && pRule->IsOutlineRule() )
+ {
+ bResult = !IsInRedlines();
+ }
+ }
+
+ return bResult;
+}
+
+bool SwTxtNode::IsOutlineStateChanged() const
+{
+ return IsOutline() != m_bLastOutlineState;
+}
+
+void SwTxtNode::UpdateOutlineState()
+{
+ m_bLastOutlineState = IsOutline();
+}
+
+//#outline level, zhaojianwei
+int SwTxtNode::GetAttrOutlineLevel() const
+{
+ return ((const SfxUInt16Item &)GetAttr(RES_PARATR_OUTLINELEVEL)).GetValue();
+}
+void SwTxtNode::SetAttrOutlineLevel(int nLevel)
+{
+ OSL_ENSURE( 0 <= nLevel && nLevel <= MAXLEVEL ,"SwTxtNode: Level Out Of Range" );//#outline level,zhaojianwei
+ if ( 0 <= nLevel && nLevel <= MAXLEVEL )
+ {
+ SetAttr( SfxUInt16Item( RES_PARATR_OUTLINELEVEL,
+ static_cast<sal_uInt16>(nLevel) ) );
+ }
+}
+//<-end
+
+// --> OD 2008-11-19 #i70748#
+bool SwTxtNode::IsEmptyListStyleDueToSetOutlineLevelAttr()
+{
+ return mbEmptyListStyleSetDueToSetOutlineLevelAttr;
+}
+
+void SwTxtNode::SetEmptyListStyleDueToSetOutlineLevelAttr()
+{
+ if ( !mbEmptyListStyleSetDueToSetOutlineLevelAttr )
+ {
+ SetAttr( SwNumRuleItem() );
+ mbEmptyListStyleSetDueToSetOutlineLevelAttr = true;
+ }
+}
+
+void SwTxtNode::ResetEmptyListStyleDueToResetOutlineLevelAttr()
+{
+ if ( mbEmptyListStyleSetDueToSetOutlineLevelAttr )
+ {
+ ResetAttr( RES_PARATR_NUMRULE );
+ mbEmptyListStyleSetDueToSetOutlineLevelAttr = false;
+ }
+}
+// <--
+
+
+void SwTxtNode::SetAttrListLevel( int nLevel )
+{
+ if ( nLevel < 0 || nLevel >= MAXLEVEL )
+ {
+ OSL_FAIL( "<SwTxtNode::SetAttrListLevel()> - value of parameter <nLevel> is out of valid range" );
+ return;
+ }
+
+ SfxInt16Item aNewListLevelItem( RES_PARATR_LIST_LEVEL,
+ static_cast<sal_Int16>(nLevel) );
+ SetAttr( aNewListLevelItem );
+}
+
+bool SwTxtNode::HasAttrListLevel() const
+{
+ return GetpSwAttrSet() &&
+ GetpSwAttrSet()->GetItemState( RES_PARATR_LIST_LEVEL, sal_False ) == SFX_ITEM_SET;
+}
+
+int SwTxtNode::GetAttrListLevel() const
+{
+ int nAttrListLevel = 0;
+
+ const SfxInt16Item& aListLevelItem =
+ dynamic_cast<const SfxInt16Item&>(GetAttr( RES_PARATR_LIST_LEVEL ));
+ nAttrListLevel = static_cast<int>(aListLevelItem.GetValue());
+
+ return nAttrListLevel;
+}
+
+int SwTxtNode::GetActualListLevel() const
+{
+ return GetNum() ? GetNum()->GetLevelInListTree() : -1;
+}
+
+void SwTxtNode::SetListRestart( bool bRestart )
+{
+// CreateNum()->SetRestart(bRestart);
+ if ( !bRestart )
+ {
+ // attribute not contained in paragraph style's attribute set. Thus,
+ // it can be reset to the attribute pool default by resetting the attribute.
+ ResetAttr( RES_PARATR_LIST_ISRESTART );
+ }
+ else
+ {
+ SfxBoolItem aNewIsRestartItem( RES_PARATR_LIST_ISRESTART,
+ sal_True );
+ SetAttr( aNewIsRestartItem );
+ }
+}
+
+bool SwTxtNode::IsListRestart() const
+{
+// return GetNum() ? GetNum()->IsRestart() : false;
+ const SfxBoolItem& aIsRestartItem =
+ dynamic_cast<const SfxBoolItem&>(GetAttr( RES_PARATR_LIST_ISRESTART ));
+
+ return aIsRestartItem.GetValue() ? true : false;
+}
+
+/** Returns if the paragraph has a visible numbering or bullet.
+ This includes all kinds of numbering/bullet/outlines.
+ The concrete list label string has to be checked, too.
+ */
+bool SwTxtNode::HasVisibleNumberingOrBullet() const
+{
+ bool bRet = false;
+
+ const SwNumRule* pRule = GetNum() ? GetNum()->GetNumRule() : 0L;
+ if ( pRule && IsCountedInList())
+ {
+ // --> OD 2008-03-19 #i87154#
+ // Correction of #newlistlevelattrs#:
+ // The numbering type has to be checked for bullet lists.
+ const SwNumFmt& rFmt = pRule->Get( static_cast<sal_uInt16>(GetActualListLevel() ));
+ if ( SVX_NUM_NUMBER_NONE != rFmt.GetNumberingType() ||
+ pRule->MakeNumString( *(GetNum()) ).Len() > 0 )
+ {
+ bRet = true;
+ }
+ // <--
+ }
+
+ return bRet;
+}
+
+void SwTxtNode::SetAttrListRestartValue( SwNumberTree::tSwNumTreeNumber nNumber )
+{
+// CreateNum()->SetStart(nNumber);
+ const bool bChanged( HasAttrListRestartValue()
+ ? GetAttrListRestartValue() != nNumber
+ : nNumber != USHRT_MAX );
+
+ if ( bChanged || !HasAttrListRestartValue() )
+ {
+ if ( nNumber == USHRT_MAX )
+ {
+ ResetAttr( RES_PARATR_LIST_RESTARTVALUE );
+ }
+ else
+ {
+ SfxInt16Item aNewListRestartValueItem( RES_PARATR_LIST_RESTARTVALUE,
+ static_cast<sal_Int16>(nNumber) );
+ SetAttr( aNewListRestartValueItem );
+ }
+ }
+}
+
+bool SwTxtNode::HasAttrListRestartValue() const
+{
+ return GetpSwAttrSet() &&
+ GetpSwAttrSet()->GetItemState( RES_PARATR_LIST_RESTARTVALUE, sal_False ) == SFX_ITEM_SET;
+}
+SwNumberTree::tSwNumTreeNumber SwTxtNode::GetAttrListRestartValue() const
+{
+ OSL_ENSURE( HasAttrListRestartValue(),
+ "<SwTxtNode::GetAttrListRestartValue()> - only ask for list restart value, if attribute is set at text node." );
+
+ const SfxInt16Item& aListRestartValueItem =
+ dynamic_cast<const SfxInt16Item&>(GetAttr( RES_PARATR_LIST_RESTARTVALUE ));
+ return static_cast<SwNumberTree::tSwNumTreeNumber>(aListRestartValueItem.GetValue());
+}
+
+SwNumberTree::tSwNumTreeNumber SwTxtNode::GetActualListStartValue() const
+{
+// return GetNum() ? GetNum()->GetStart() : 1;
+ SwNumberTree::tSwNumTreeNumber nListRestartValue = 1;
+
+ if ( IsListRestart() && HasAttrListRestartValue() )
+ {
+ nListRestartValue = GetAttrListRestartValue();
+ }
+ else
+ {
+ SwNumRule* pRule = GetNumRule();
+ if ( pRule )
+ {
+ const SwNumFmt* pFmt =
+ pRule->GetNumFmt( static_cast<sal_uInt16>(GetAttrListLevel()) );
+ if ( pFmt )
+ {
+ nListRestartValue = pFmt->GetStart();
+ }
+ }
+ }
+
+ return nListRestartValue;
+}
+
+bool SwTxtNode::IsNotifiable() const
+{
+ return m_bNotifiable && IsNotificationEnabled();
+}
+
+bool SwTxtNode::IsNotificationEnabled() const
+{
+ bool bResult = false;
+ const SwDoc * pDoc = GetDoc();
+ if( pDoc )
+ {
+ bResult = pDoc->IsInReading() || pDoc->IsInDtor() ? false : true;
+ }
+ return bResult;
+}
+
+void SwTxtNode::SetCountedInList( bool bCounted )
+{
+ if ( bCounted )
+ {
+ // attribute not contained in paragraph style's attribute set. Thus,
+ // it can be reset to the attribute pool default by resetting the attribute.
+ ResetAttr( RES_PARATR_LIST_ISCOUNTED );
+ }
+ else
+ {
+ SfxBoolItem aIsCountedInListItem( RES_PARATR_LIST_ISCOUNTED, sal_False );
+ SetAttr( aIsCountedInListItem );
+ }
+}
+
+bool SwTxtNode::IsCountedInList() const
+{
+ const SfxBoolItem& aIsCountedInListItem =
+ dynamic_cast<const SfxBoolItem&>(GetAttr( RES_PARATR_LIST_ISCOUNTED ));
+
+ return aIsCountedInListItem.GetValue() ? true : false;
+}
+
+void SwTxtNode::AddToList()
+{
+ if ( IsInList() )
+ {
+ OSL_FAIL( "<SwTxtNode::AddToList()> - the text node is already added to a list. Serious defect -> please inform OD" );
+ return;
+ }
+
+ const String sListId = GetListId();
+ if ( sListId.Len() > 0 )
+ {
+ SwList* pList = GetDoc()->getListByName( sListId );
+ if ( pList == 0 )
+ {
+ // Create corresponding list.
+ SwNumRule* pNumRule = GetNumRule();
+ if ( pNumRule )
+ {
+ pList = GetDoc()->createList( sListId, GetNumRule()->GetName() );
+ }
+ }
+ OSL_ENSURE( pList != 0,
+ "<SwTxtNode::AddToList()> - no list for given list id. Serious defect -> please inform OD" );
+ if ( pList )
+ {
+ pList->InsertListItem( *CreateNum(), GetAttrListLevel() );
+ mpList = pList;
+ }
+ }
+}
+
+void SwTxtNode::RemoveFromList()
+{
+ if ( IsInList() )
+ {
+ mpList->RemoveListItem( *mpNodeNum );
+ mpList = 0;
+ delete mpNodeNum;
+ mpNodeNum = 0L;
+ }
+}
+
+bool SwTxtNode::IsInList() const
+{
+ return GetNum() != 0 && GetNum()->GetParent() != 0;
+}
+
+bool SwTxtNode::IsFirstOfNumRule() const
+{
+ bool bResult = false;
+
+ if ( GetNum() && GetNum()->GetNumRule())
+ bResult = GetNum()->IsFirst();
+
+ return bResult;
+}
+
+void SwTxtNode::SetListId( const String sListId )
+{
+ const SfxStringItem& rListIdItem =
+ dynamic_cast<const SfxStringItem&>(GetAttr( RES_PARATR_LIST_ID ));
+ if ( rListIdItem.GetValue() != sListId )
+ {
+ if ( sListId.Len() == 0 )
+ {
+ ResetAttr( RES_PARATR_LIST_ID );
+ }
+ else
+ {
+ SfxStringItem aNewListIdItem( RES_PARATR_LIST_ID, sListId );
+ SetAttr( aNewListIdItem );
+ }
+ }
+}
+
+String SwTxtNode::GetListId() const
+{
+ String sListId;
+
+ const SfxStringItem& rListIdItem =
+ dynamic_cast<const SfxStringItem&>(GetAttr( RES_PARATR_LIST_ID ));
+ sListId = rListIdItem.GetValue();
+
+ // As long as no explicit list id attribute is set, use the list id of
+ // the list, which has been created for the applied list style.
+ if ( sListId.Len() == 0 )
+ {
+ SwNumRule* pRule = GetNumRule();
+ if ( pRule )
+ {
+ sListId = pRule->GetDefaultListId();
+ }
+ }
+
+ return sListId;
+}
+
+/** Determines, if the list level indent attributes can be applied to the
+ paragraph.
+
+ The list level indents can be applied to the paragraph under the one
+ of following conditions:
+ - the list style is directly applied to the paragraph and the paragraph
+ has no own indent attributes.
+ - the list style is applied to the paragraph through one of its paragraph
+ styles, the paragraph has no own indent attributes and on the paragraph
+ style hierarchy from the paragraph to the paragraph style with the
+ list style no indent attributes are found.
+
+ @author OD
+
+ @return boolean
+*/
+bool SwTxtNode::AreListLevelIndentsApplicable() const
+{
+ bool bAreListLevelIndentsApplicable( true );
+
+ if ( !GetNum() || !GetNum()->GetNumRule() )
+ {
+ // no list style applied to paragraph
+ bAreListLevelIndentsApplicable = false;
+ }
+ else if ( HasSwAttrSet() &&
+ GetpSwAttrSet()->GetItemState( RES_LR_SPACE, sal_False ) == SFX_ITEM_SET )
+ {
+ // paragraph has hard-set indent attributes
+ bAreListLevelIndentsApplicable = false;
+ }
+ else if ( HasSwAttrSet() &&
+ GetpSwAttrSet()->GetItemState( RES_PARATR_NUMRULE, sal_False ) == SFX_ITEM_SET )
+ {
+ // list style is directly applied to paragraph and paragraph has no
+ // hard-set indent attributes
+ bAreListLevelIndentsApplicable = true;
+ }
+ else
+ {
+ // list style is applied through one of the paragraph styles and
+ // paragraph has no hard-set indent attributes
+
+ // check, paragraph's
+ const SwTxtFmtColl* pColl = GetTxtColl();
+ while ( pColl )
+ {
+ if ( pColl->GetAttrSet().GetItemState( RES_LR_SPACE, sal_False ) == SFX_ITEM_SET )
+ {
+ // indent attributes found in the paragraph style hierarchy.
+ bAreListLevelIndentsApplicable = false;
+ break;
+ }
+
+ if ( pColl->GetAttrSet().GetItemState( RES_PARATR_NUMRULE, sal_False ) == SFX_ITEM_SET )
+ {
+ // paragraph style with the list style found and until now no
+ // indent attributes are found in the paragraph style hierarchy.
+ bAreListLevelIndentsApplicable = true;
+ break;
+ }
+
+ pColl = dynamic_cast<const SwTxtFmtColl*>(pColl->DerivedFrom());
+ OSL_ENSURE( pColl,
+ "<SwTxtNode::AreListLevelIndentsApplicable()> - something wrong in paragraph's style hierarchy. The applied list style is not found." );
+ }
+ }
+
+ return bAreListLevelIndentsApplicable;
+}
+
+/** Retrieves the list tab stop position, if the paragraph's list level defines
+ one and this list tab stop has to merged into the tap stops of the paragraph
+
+ @author OD
+
+ @param nListTabStopPosition
+ output parameter - containing the list tab stop position
+
+ @return boolean - indicating, if a list tab stop position is provided
+*/
+bool SwTxtNode::GetListTabStopPosition( long& nListTabStopPosition ) const
+{
+ bool bListTanStopPositionProvided( false );
+
+ const SwNumRule* pNumRule = GetNum() ? GetNum()->GetNumRule() : 0;
+ if ( pNumRule && HasVisibleNumberingOrBullet() && GetActualListLevel() >= 0 )
+ {
+ const SwNumFmt& rFmt = pNumRule->Get( static_cast<sal_uInt16>(GetActualListLevel()) );
+ if ( rFmt.GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_ALIGNMENT &&
+ rFmt.GetLabelFollowedBy() == SvxNumberFormat::LISTTAB )
+ {
+ bListTanStopPositionProvided = true;
+ nListTabStopPosition = rFmt.GetListtabPos();
+
+ if ( getIDocumentSettingAccess()->get(IDocumentSettingAccess::TABS_RELATIVE_TO_INDENT) )
+ {
+ // tab stop position are treated to be relative to the "before text"
+ // indent value of the paragraph. Thus, adjust <nListTabStopPos>.
+ if ( AreListLevelIndentsApplicable() )
+ {
+ nListTabStopPosition -= rFmt.GetIndentAt();
+ }
+ else if (!getIDocumentSettingAccess()->get(IDocumentSettingAccess::IGNORE_FIRST_LINE_INDENT_IN_NUMBERING))
+ {
+ SvxLRSpaceItem aItem = GetSwAttrSet().GetLRSpace();
+ nListTabStopPosition -= aItem.GetTxtLeft();
+ }
+ }
+ }
+ }
+
+ return bListTanStopPositionProvided;
+}
+
+/** Retrieves the character following the list label, if the paragraph's
+ list level defines one.
+
+ @author OD
+
+ @return XubString - the list tab stop position
+*/
+XubString SwTxtNode::GetLabelFollowedBy() const
+{
+ XubString aLabelFollowedBy;
+
+ const SwNumRule* pNumRule = GetNum() ? GetNum()->GetNumRule() : 0;
+ if ( pNumRule && HasVisibleNumberingOrBullet() && GetActualListLevel() >= 0 )
+ {
+ const SwNumFmt& rFmt = pNumRule->Get( static_cast<sal_uInt16>(GetActualListLevel()) );
+ if ( rFmt.GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_ALIGNMENT )
+ {
+ switch ( rFmt.GetLabelFollowedBy() )
+ {
+ case SvxNumberFormat::LISTTAB:
+ {
+ const sal_Unicode aTab = '\t';
+ aLabelFollowedBy.Insert( aTab, 0 );
+ }
+ break;
+ case SvxNumberFormat::SPACE:
+ {
+ const sal_Unicode aSpace = ' ';
+ aLabelFollowedBy.Insert( aSpace, 0 );
+ }
+ break;
+ case SvxNumberFormat::NOTHING:
+ {
+ // intentionally left blank.
+ }
+ break;
+ default:
+ {
+ OSL_FAIL( "<SwTxtNode::GetLabelFollowedBy()> - unknown SvxNumberFormat::GetLabelFollowedBy() return value" );
+ }
+ }
+ }
+ }
+
+ return aLabelFollowedBy;
+}
+
+void SwTxtNode::CalcHiddenCharFlags() const
+{
+ xub_StrLen nStartPos;
+ xub_StrLen nEndPos;
+ // Update of the flags is done inside GetBoundsOfHiddenRange()
+ SwScriptInfo::GetBoundsOfHiddenRange( *this, 0, nStartPos, nEndPos );
+}
+
+// --> FME 2004-06-08 #i12836# enhanced pdf export
+bool SwTxtNode::IsHidden() const
+{
+ if ( HasHiddenParaField() || HasHiddenCharAttribute( true ) )
+ return true;
+
+ const SwSectionNode* pSectNd = FindSectionNode();
+ if ( pSectNd && pSectNd->GetSection().IsHiddenFlag() )
+ return true;
+
+ return false;
+}
+// <--
+
+namespace {
+ // Helper class for special handling of setting attributes at text node:
+ // In constructor an instance of the helper class recognize whose attributes
+ // are set and perform corresponding actions before the intrinsic set of
+ // attributes has been taken place.
+ // In the destructor - after the attributes have been set at the text
+ // node - corresponding actions are performed.
+ // The following is handled:
+ // (1) When the list style attribute - RES_PARATR_NUMRULE - is set,
+ // (A) list style attribute is empty -> the text node is removed from
+ // its list.
+ // (B) list style attribute is not empty
+ // (a) text node has no list style -> add text node to its list after
+ // the attributes have been set.
+ // (b) text node has list style -> change of list style is notified
+ // after the attributes have been set.
+ // (2) When the list id attribute - RES_PARATR_LIST_ID - is set and changed,
+ // the text node is removed from its current list before the attributes
+ // are set and added to its new list after the attributes have been set.
+ // (3) Notify list tree, if list level - RES_PARATR_LIST_LEVEL - is set
+ // and changed after the attributes have been set
+ // (4) Notify list tree, if list restart - RES_PARATR_LIST_ISRESTART - is set
+ // and changed after the attributes have been set
+ // (5) Notify list tree, if list restart value - RES_PARATR_LIST_RESTARTVALUE -
+ // is set and changed after the attributes have been set
+ // (6) Notify list tree, if count in list - RES_PARATR_LIST_ISCOUNTED - is set
+ // and changed after the attributes have been set
+ // (7) Set or Reset emtpy list style due to changed outline level - RES_PARATR_OUTLINELEVEL.
+ class HandleSetAttrAtTxtNode
+ {
+ public:
+ HandleSetAttrAtTxtNode( SwTxtNode& rTxtNode,
+ const SfxPoolItem& pItem );
+ HandleSetAttrAtTxtNode( SwTxtNode& rTxtNode,
+ const SfxItemSet& rItemSet );
+ ~HandleSetAttrAtTxtNode();
+
+ private:
+ SwTxtNode& mrTxtNode;
+ bool mbAddTxtNodeToList;
+ bool mbUpdateListLevel;
+ bool mbUpdateListRestart;
+ bool mbUpdateListCount;
+ // --> OD 2008-11-19 #i70748#
+ bool mbOutlineLevelSet;
+ // <--
+ };
+
+ HandleSetAttrAtTxtNode::HandleSetAttrAtTxtNode( SwTxtNode& rTxtNode,
+ const SfxPoolItem& pItem )
+ : mrTxtNode( rTxtNode ),
+ mbAddTxtNodeToList( false ),
+ mbUpdateListLevel( false ),
+ mbUpdateListRestart( false ),
+ mbUpdateListCount( false ),
+ // --> OD 2008-11-19 #i70748#
+ mbOutlineLevelSet( false )
+ // <--
+ {
+ switch ( pItem.Which() )
+ {
+ // handle RES_PARATR_NUMRULE
+ case RES_PARATR_NUMRULE:
+ {
+ mrTxtNode.RemoveFromList();
+
+ const SwNumRuleItem& pNumRuleItem =
+ dynamic_cast<const SwNumRuleItem&>(pItem);
+ if ( pNumRuleItem.GetValue().Len() > 0 )
+ {
+ mbAddTxtNodeToList = true;
+ // --> OD 2010-05-12 #i105562#
+ //
+ mrTxtNode.ResetEmptyListStyleDueToResetOutlineLevelAttr();
+ // <--
+ }
+ }
+ break;
+
+ // handle RES_PARATR_LIST_ID
+ case RES_PARATR_LIST_ID:
+ {
+ const SfxStringItem& pListIdItem =
+ dynamic_cast<const SfxStringItem&>(pItem);
+ OSL_ENSURE( pListIdItem.GetValue().Len() > 0,
+ "<HandleSetAttrAtTxtNode(..)> - empty list id attribute not excepted. Serious defect -> please inform OD." );
+ const String sListIdOfTxtNode = rTxtNode.GetListId();
+ if ( pListIdItem.GetValue() != sListIdOfTxtNode )
+ {
+ mbAddTxtNodeToList = true;
+ if ( mrTxtNode.IsInList() )
+ {
+ mrTxtNode.RemoveFromList();
+ }
+ }
+ }
+ break;
+
+ // handle RES_PARATR_LIST_LEVEL
+ case RES_PARATR_LIST_LEVEL:
+ {
+ const SfxInt16Item& aListLevelItem =
+ dynamic_cast<const SfxInt16Item&>(pItem);
+ if ( aListLevelItem.GetValue() != mrTxtNode.GetAttrListLevel() )
+ {
+ mbUpdateListLevel = true;
+ }
+ }
+ break;
+
+ // handle RES_PARATR_LIST_ISRESTART
+ case RES_PARATR_LIST_ISRESTART:
+ {
+ const SfxBoolItem& aListIsRestartItem =
+ dynamic_cast<const SfxBoolItem&>(pItem);
+ if ( aListIsRestartItem.GetValue() !=
+ (mrTxtNode.IsListRestart() ? sal_True : sal_False) )
+ {
+ mbUpdateListRestart = true;
+ }
+ }
+ break;
+
+ // handle RES_PARATR_LIST_RESTARTVALUE
+ case RES_PARATR_LIST_RESTARTVALUE:
+ {
+ const SfxInt16Item& aListRestartValueItem =
+ dynamic_cast<const SfxInt16Item&>(pItem);
+ if ( !mrTxtNode.HasAttrListRestartValue() ||
+ aListRestartValueItem.GetValue() != mrTxtNode.GetAttrListRestartValue() )
+ {
+ mbUpdateListRestart = true;
+ }
+ }
+ break;
+
+ // handle RES_PARATR_LIST_ISCOUNTED
+ case RES_PARATR_LIST_ISCOUNTED:
+ {
+ const SfxBoolItem& aIsCountedInListItem =
+ dynamic_cast<const SfxBoolItem&>(pItem);
+ if ( aIsCountedInListItem.GetValue() !=
+ (mrTxtNode.IsCountedInList() ? sal_True : sal_False) )
+ {
+ mbUpdateListCount = true;
+ }
+ }
+ break;
+
+ // --> OD 2008-11-19 #i70748#
+ // handle RES_PARATR_OUTLINELEVEL
+ case RES_PARATR_OUTLINELEVEL:
+ {
+ const SfxUInt16Item& aOutlineLevelItem =
+ dynamic_cast<const SfxUInt16Item&>(pItem);
+ if ( aOutlineLevelItem.GetValue() != mrTxtNode.GetAttrOutlineLevel() )
+ {
+ mbOutlineLevelSet = true;
+ }
+ }
+ break;
+ // <--
+ }
+
+ }
+
+ HandleSetAttrAtTxtNode::HandleSetAttrAtTxtNode( SwTxtNode& rTxtNode,
+ const SfxItemSet& rItemSet )
+ : mrTxtNode( rTxtNode ),
+ mbAddTxtNodeToList( false ),
+ mbUpdateListLevel( false ),
+ mbUpdateListRestart( false ),
+ mbUpdateListCount( false ),
+ // --> OD 2008-11-19 #i70748#
+ mbOutlineLevelSet( false )
+ // <--
+ {
+ const SfxPoolItem* pItem = 0;
+ // handle RES_PARATR_NUMRULE
+ if ( rItemSet.GetItemState( RES_PARATR_NUMRULE, sal_False, &pItem ) == SFX_ITEM_SET )
+ {
+ mrTxtNode.RemoveFromList();
+
+ const SwNumRuleItem* pNumRuleItem =
+ dynamic_cast<const SwNumRuleItem*>(pItem);
+ if ( pNumRuleItem->GetValue().Len() > 0 )
+ {
+ mbAddTxtNodeToList = true;
+ // --> OD 2008-11-19 #i70748#
+ mrTxtNode.ResetEmptyListStyleDueToResetOutlineLevelAttr();
+ // <--
+ }
+ }
+
+ // handle RES_PARATR_LIST_ID
+ if ( rItemSet.GetItemState( RES_PARATR_LIST_ID, sal_False, &pItem ) == SFX_ITEM_SET )
+ {
+ const SfxStringItem* pListIdItem =
+ dynamic_cast<const SfxStringItem*>(pItem);
+ const String sListIdOfTxtNode = mrTxtNode.GetListId();
+ if ( pListIdItem &&
+ pListIdItem->GetValue() != sListIdOfTxtNode )
+ {
+ mbAddTxtNodeToList = true;
+ if ( mrTxtNode.IsInList() )
+ {
+ mrTxtNode.RemoveFromList();
+ }
+ }
+ }
+
+ // handle RES_PARATR_LIST_LEVEL
+ if ( rItemSet.GetItemState( RES_PARATR_LIST_LEVEL, sal_False, &pItem ) == SFX_ITEM_SET )
+ {
+ const SfxInt16Item* pListLevelItem =
+ dynamic_cast<const SfxInt16Item*>(pItem);
+ if ( pListLevelItem->GetValue() != mrTxtNode.GetAttrListLevel() )
+ {
+ mbUpdateListLevel = true;
+ }
+ }
+
+ // handle RES_PARATR_LIST_ISRESTART
+ if ( rItemSet.GetItemState( RES_PARATR_LIST_ISRESTART, sal_False, &pItem ) == SFX_ITEM_SET )
+ {
+ const SfxBoolItem* pListIsRestartItem =
+ dynamic_cast<const SfxBoolItem*>(pItem);
+ if ( pListIsRestartItem->GetValue() !=
+ (mrTxtNode.IsListRestart() ? sal_True : sal_False) )
+ {
+ mbUpdateListRestart = true;
+ }
+ }
+
+ // handle RES_PARATR_LIST_RESTARTVALUE
+ if ( rItemSet.GetItemState( RES_PARATR_LIST_RESTARTVALUE, sal_False, &pItem ) == SFX_ITEM_SET )
+ {
+ const SfxInt16Item* pListRestartValueItem =
+ dynamic_cast<const SfxInt16Item*>(pItem);
+ if ( !mrTxtNode.HasAttrListRestartValue() ||
+ pListRestartValueItem->GetValue() != mrTxtNode.GetAttrListRestartValue() )
+ {
+ mbUpdateListRestart = true;
+ }
+ }
+
+ // handle RES_PARATR_LIST_ISCOUNTED
+ if ( rItemSet.GetItemState( RES_PARATR_LIST_ISCOUNTED, sal_False, &pItem ) == SFX_ITEM_SET )
+ {
+ const SfxBoolItem* pIsCountedInListItem =
+ dynamic_cast<const SfxBoolItem*>(pItem);
+ if ( pIsCountedInListItem->GetValue() !=
+ (mrTxtNode.IsCountedInList() ? sal_True : sal_False) )
+ {
+ mbUpdateListCount = true;
+ }
+ }
+
+ // --> OD 2008-11-19 #i70748#
+ // handle RES_PARATR_OUTLINELEVEL
+ if ( rItemSet.GetItemState( RES_PARATR_OUTLINELEVEL, sal_False, &pItem ) == SFX_ITEM_SET )
+ {
+ const SfxUInt16Item* pOutlineLevelItem =
+ dynamic_cast<const SfxUInt16Item*>(pItem);
+ if ( pOutlineLevelItem->GetValue() != mrTxtNode.GetAttrOutlineLevel() )
+ {
+ mbOutlineLevelSet = true;
+ }
+ }
+ // <--
+ }
+
+ HandleSetAttrAtTxtNode::~HandleSetAttrAtTxtNode()
+ {
+ if ( mbAddTxtNodeToList )
+ {
+ SwNumRule* pNumRuleAtTxtNode = mrTxtNode.GetNumRule();
+ if ( pNumRuleAtTxtNode )
+ {
+ mrTxtNode.AddToList();
+ }
+ }
+ else
+ {
+ if ( mbUpdateListLevel && mrTxtNode.IsInList() )
+ {
+ const_cast<SwNodeNum*>(mrTxtNode.GetNum())->SetLevelInListTree(
+ mrTxtNode.GetAttrListLevel() );
+ }
+
+ if ( mbUpdateListRestart && mrTxtNode.IsInList() )
+ {
+ SwNodeNum* pNodeNum = const_cast<SwNodeNum*>(mrTxtNode.GetNum());
+ pNodeNum->InvalidateMe();
+ pNodeNum->NotifyInvalidSiblings();
+ }
+
+ if ( mbUpdateListCount && mrTxtNode.IsInList() )
+ {
+ const_cast<SwNodeNum*>(mrTxtNode.GetNum())->InvalidateAndNotifyTree();
+ }
+ }
+
+ // --> OD 2008-11-19 #i70748#
+ if ( mbOutlineLevelSet )
+ {
+ if ( mrTxtNode.GetAttrOutlineLevel() == 0 )
+ {
+ mrTxtNode.ResetEmptyListStyleDueToResetOutlineLevelAttr();
+ }
+ else
+ {
+ const SfxPoolItem* pItem = 0;
+ if ( mrTxtNode.GetSwAttrSet().GetItemState( RES_PARATR_NUMRULE,
+ sal_True, &pItem )
+ != SFX_ITEM_SET )
+ {
+ mrTxtNode.SetEmptyListStyleDueToSetOutlineLevelAttr();
+ }
+ }
+ }
+ // <--
+ }
+ // End of class <HandleSetAttrAtTxtNode>
+}
+
+sal_Bool SwTxtNode::SetAttr( const SfxPoolItem& pItem )
+{
+ const bool bOldIsSetOrResetAttr( mbInSetOrResetAttr );
+ mbInSetOrResetAttr = true;
+
+ HandleSetAttrAtTxtNode aHandleSetAttr( *this, pItem );
+
+ sal_Bool bRet = SwCntntNode::SetAttr( pItem );
+
+ mbInSetOrResetAttr = bOldIsSetOrResetAttr;
+
+ return bRet;
+}
+
+sal_Bool SwTxtNode::SetAttr( const SfxItemSet& rSet )
+{
+ const bool bOldIsSetOrResetAttr( mbInSetOrResetAttr );
+ mbInSetOrResetAttr = true;
+
+ HandleSetAttrAtTxtNode aHandleSetAttr( *this, rSet );
+
+ sal_Bool bRet = SwCntntNode::SetAttr( rSet );
+
+ mbInSetOrResetAttr = bOldIsSetOrResetAttr;
+
+ return bRet;
+}
+
+namespace {
+ // Helper class for special handling of resetting attributes at text node:
+ // In constructor an instance of the helper class recognize whose attributes
+ // are reset and perform corresponding actions before the intrinsic reset of
+ // attributes has been taken place.
+ // In the destructor - after the attributes have been reset at the text
+ // node - corresponding actions are performed.
+ // The following is handled:
+ // (1) When the list style attribute - RES_PARATR_NUMRULE - is reset,
+ // the text is removed from its list before the attributes have been reset.
+ // (2) When the list id attribute - RES_PARATR_LIST_ID - is reset,
+ // the text is removed from its list before the attributes have been reset.
+ // (3) Notify list tree, if list level - RES_PARATR_LIST_LEVEL - is reset.
+ // (4) Notify list tree, if list restart - RES_PARATR_LIST_ISRESTART - is reset.
+ // (5) Notify list tree, if list restart value - RES_PARATR_LIST_RESTARTVALUE - is reset.
+ // (6) Notify list tree, if count in list - RES_PARATR_LIST_ISCOUNTED - is reset.
+ // (7) Reset empty list style, if outline level attribute - RES_PARATR_OUTLINELEVEL - is reset.
+ class HandleResetAttrAtTxtNode
+ {
+ public:
+ HandleResetAttrAtTxtNode( SwTxtNode& rTxtNode,
+ const sal_uInt16 nWhich1,
+ const sal_uInt16 nWhich2 );
+ HandleResetAttrAtTxtNode( SwTxtNode& rTxtNode,
+ const SvUShorts& rWhichArr );
+ HandleResetAttrAtTxtNode( SwTxtNode& rTxtNode );
+
+ ~HandleResetAttrAtTxtNode();
+
+ private:
+ SwTxtNode& mrTxtNode;
+ bool mbListStyleOrIdReset;
+ bool mbUpdateListLevel;
+ bool mbUpdateListRestart;
+ bool mbUpdateListCount;
+ };
+
+ HandleResetAttrAtTxtNode::HandleResetAttrAtTxtNode( SwTxtNode& rTxtNode,
+ const sal_uInt16 nWhich1,
+ const sal_uInt16 nWhich2 )
+ : mrTxtNode( rTxtNode ),
+ mbListStyleOrIdReset( false ),
+ mbUpdateListLevel( false ),
+ mbUpdateListRestart( false ),
+ mbUpdateListCount( false )
+ {
+ bool bRemoveFromList( false );
+ if ( nWhich2 != 0 && nWhich2 > nWhich1 )
+ {
+ // RES_PARATR_NUMRULE and RES_PARATR_LIST_ID
+ if ( nWhich1 <= RES_PARATR_NUMRULE && RES_PARATR_NUMRULE <= nWhich2 )
+ {
+ bRemoveFromList = mrTxtNode.GetNumRule() != 0;
+ mbListStyleOrIdReset = true;
+ }
+ else if ( nWhich1 <= RES_PARATR_LIST_ID && RES_PARATR_LIST_ID <= nWhich2 )
+ {
+ bRemoveFromList = mrTxtNode.GetpSwAttrSet() &&
+ mrTxtNode.GetpSwAttrSet()->GetItemState( RES_PARATR_LIST_ID, sal_False ) == SFX_ITEM_SET;
+ // --> OD 2008-10-20 #i92898#
+ mbListStyleOrIdReset = true;
+ // <--
+ }
+
+ if ( !bRemoveFromList )
+ {
+ // RES_PARATR_LIST_LEVEL
+ mbUpdateListLevel = ( nWhich1 <= RES_PARATR_LIST_LEVEL &&
+ RES_PARATR_LIST_LEVEL <= nWhich2 &&
+ mrTxtNode.HasAttrListLevel() );
+
+ // RES_PARATR_LIST_ISRESTART and RES_PARATR_LIST_RESTARTVALUE
+ mbUpdateListRestart =
+ ( nWhich1 <= RES_PARATR_LIST_ISRESTART && RES_PARATR_LIST_ISRESTART <= nWhich2 &&
+ mrTxtNode.IsListRestart() ) ||
+ ( nWhich1 <= RES_PARATR_LIST_RESTARTVALUE && RES_PARATR_LIST_RESTARTVALUE <= nWhich2 &&
+ mrTxtNode.HasAttrListRestartValue() );
+
+ // RES_PARATR_LIST_ISCOUNTED
+ mbUpdateListCount =
+ ( nWhich1 <= RES_PARATR_LIST_ISCOUNTED && RES_PARATR_LIST_ISCOUNTED <= nWhich2 &&
+ !mrTxtNode.IsCountedInList() );
+ }
+
+ // --> OD 2008-11-19 #i70748#
+ // RES_PARATR_OUTLINELEVEL
+ if ( nWhich1 <= RES_PARATR_OUTLINELEVEL && RES_PARATR_OUTLINELEVEL <= nWhich2 )
+ {
+ mrTxtNode.ResetEmptyListStyleDueToResetOutlineLevelAttr();
+ }
+ // <--
+ }
+ else
+ {
+ // RES_PARATR_NUMRULE and RES_PARATR_LIST_ID
+ if ( nWhich1 == RES_PARATR_NUMRULE )
+ {
+ bRemoveFromList = mrTxtNode.GetNumRule() != 0;
+ mbListStyleOrIdReset = true;
+ }
+ else if ( nWhich1 == RES_PARATR_LIST_ID )
+ {
+ bRemoveFromList = mrTxtNode.GetpSwAttrSet() &&
+ mrTxtNode.GetpSwAttrSet()->GetItemState( RES_PARATR_LIST_ID, sal_False ) == SFX_ITEM_SET;
+ // --> OD 2008-10-20 #i92898#
+ mbListStyleOrIdReset = true;
+ // <--
+ }
+ // --> OD 2008-11-19 #i70748#
+ // RES_PARATR_OUTLINELEVEL
+ else if ( nWhich1 == RES_PARATR_OUTLINELEVEL )
+ {
+ mrTxtNode.ResetEmptyListStyleDueToResetOutlineLevelAttr();
+ }
+ // <--
+
+ if ( !bRemoveFromList )
+ {
+ // RES_PARATR_LIST_LEVEL
+ mbUpdateListLevel = nWhich1 == RES_PARATR_LIST_LEVEL &&
+ mrTxtNode.HasAttrListLevel();
+
+ // RES_PARATR_LIST_ISRESTART and RES_PARATR_LIST_RESTARTVALUE
+ mbUpdateListRestart = ( nWhich1 == RES_PARATR_LIST_ISRESTART &&
+ mrTxtNode.IsListRestart() ) ||
+ ( nWhich1 == RES_PARATR_LIST_RESTARTVALUE &&
+ mrTxtNode.HasAttrListRestartValue() );
+
+ // RES_PARATR_LIST_ISCOUNTED
+ mbUpdateListCount = nWhich1 == RES_PARATR_LIST_ISCOUNTED &&
+ !mrTxtNode.IsCountedInList();
+ }
+ }
+
+ if ( bRemoveFromList && mrTxtNode.IsInList() )
+ {
+ mrTxtNode.RemoveFromList();
+ }
+ }
+
+ HandleResetAttrAtTxtNode::HandleResetAttrAtTxtNode( SwTxtNode& rTxtNode,
+ const SvUShorts& rWhichArr )
+ : mrTxtNode( rTxtNode ),
+ mbListStyleOrIdReset( false ),
+ mbUpdateListLevel( false ),
+ mbUpdateListRestart( false ),
+ mbUpdateListCount( false )
+ {
+ bool bRemoveFromList( false );
+ {
+ const sal_uInt16 nEnd = rWhichArr.Count();
+ for ( sal_uInt16 n = 0; n < nEnd; ++n )
+ {
+ // RES_PARATR_NUMRULE and RES_PARATR_LIST_ID
+ if ( rWhichArr[ n ] == RES_PARATR_NUMRULE )
+ {
+ bRemoveFromList = bRemoveFromList ||
+ mrTxtNode.GetNumRule() != 0;
+ mbListStyleOrIdReset = true;
+ }
+ else if ( rWhichArr[ n ] == RES_PARATR_LIST_ID )
+ {
+ bRemoveFromList = bRemoveFromList ||
+ ( mrTxtNode.GetpSwAttrSet() &&
+ mrTxtNode.GetpSwAttrSet()->GetItemState( RES_PARATR_LIST_ID, sal_False ) == SFX_ITEM_SET );
+ // --> OD 2008-10-20 #i92898#
+ mbListStyleOrIdReset = true;
+ // <--
+ }
+ // --> OD 2008-11-19 #i70748#
+ // RES_PARATR_OUTLINELEVEL
+ else if ( rWhichArr[ n ] == RES_PARATR_OUTLINELEVEL )
+ {
+ mrTxtNode.ResetEmptyListStyleDueToResetOutlineLevelAttr();
+ }
+ // <--
+
+ if ( !bRemoveFromList )
+ {
+ // RES_PARATR_LIST_LEVEL
+ mbUpdateListLevel = mbUpdateListLevel ||
+ ( rWhichArr[ n ] == RES_PARATR_LIST_LEVEL &&
+ mrTxtNode.HasAttrListLevel() );
+
+ // RES_PARATR_LIST_ISRESTART and RES_PARATR_LIST_RESTARTVALUE
+ mbUpdateListRestart = mbUpdateListRestart ||
+ ( rWhichArr[ n ] == RES_PARATR_LIST_ISRESTART &&
+ mrTxtNode.IsListRestart() ) ||
+ ( rWhichArr[ n ] == RES_PARATR_LIST_RESTARTVALUE &&
+ mrTxtNode.HasAttrListRestartValue() );
+
+ // RES_PARATR_LIST_ISCOUNTED
+ mbUpdateListCount = mbUpdateListCount ||
+ ( rWhichArr[ n ] == RES_PARATR_LIST_ISCOUNTED &&
+ !mrTxtNode.IsCountedInList() );
+ }
+ }
+ }
+
+ if ( bRemoveFromList && mrTxtNode.IsInList() )
+ {
+ mrTxtNode.RemoveFromList();
+ }
+ }
+
+ HandleResetAttrAtTxtNode::HandleResetAttrAtTxtNode( SwTxtNode& rTxtNode )
+ : mrTxtNode( rTxtNode ),
+ mbListStyleOrIdReset( false ),
+ mbUpdateListLevel( false ),
+ mbUpdateListRestart( false ),
+ mbUpdateListCount( false )
+ {
+ mbListStyleOrIdReset = true;
+ if ( rTxtNode.IsInList() )
+ {
+ rTxtNode.RemoveFromList();
+ }
+ // --> OD 2008-11-19 #i70748#
+ mrTxtNode.ResetEmptyListStyleDueToResetOutlineLevelAttr();
+ // <--
+ }
+
+ HandleResetAttrAtTxtNode::~HandleResetAttrAtTxtNode()
+ {
+ if ( mbListStyleOrIdReset && !mrTxtNode.IsInList() )
+ {
+ // check, if in spite of the reset of the list style or the list id
+ // the paragraph still has to be added to a list.
+ if ( mrTxtNode.GetNumRule() &&
+ mrTxtNode.GetListId().Len() > 0 )
+ {
+ // --> OD 2009-01-14 #i96062#
+ // If paragraph has no list level attribute set and list style
+ // is the outline style, apply outline level as the list level.
+ if ( !mrTxtNode.HasAttrListLevel() &&
+ mrTxtNode.GetNumRule()->GetName() ==
+ String::CreateFromAscii( SwNumRule::GetOutlineRuleName() ) &&
+ mrTxtNode.GetTxtColl()->IsAssignedToListLevelOfOutlineStyle() )
+ {
+ int nNewListLevel = mrTxtNode.GetTxtColl()->GetAssignedOutlineStyleLevel();
+ if ( 0 <= nNewListLevel && nNewListLevel < MAXLEVEL )
+ {
+ mrTxtNode.SetAttrListLevel( nNewListLevel );
+ }
+ }
+ // <--
+ mrTxtNode.AddToList();
+ }
+ // --> OD 2008-11-19 #i70748#
+ // --> OD 2010-05-12 #i105562#
+ else if ( mrTxtNode.GetpSwAttrSet() &&
+ dynamic_cast<const SfxUInt16Item &>(mrTxtNode.GetAttr( RES_PARATR_OUTLINELEVEL, sal_False )).GetValue() > 0 )
+ {
+ mrTxtNode.SetEmptyListStyleDueToSetOutlineLevelAttr();
+ }
+ // <--
+ }
+
+ if ( mrTxtNode.IsInList() )
+ {
+ if ( mbUpdateListLevel )
+ {
+ SwNodeNum* pNodeNum = const_cast<SwNodeNum*>(mrTxtNode.GetNum());
+ pNodeNum->SetLevelInListTree( mrTxtNode.GetAttrListLevel() );
+ }
+
+ if ( mbUpdateListRestart )
+ {
+ SwNodeNum* pNodeNum = const_cast<SwNodeNum*>(mrTxtNode.GetNum());
+ pNodeNum->InvalidateMe();
+ pNodeNum->NotifyInvalidSiblings();
+ }
+
+ if ( mbUpdateListCount )
+ {
+ SwNodeNum* pNodeNum = const_cast<SwNodeNum*>(mrTxtNode.GetNum());
+ pNodeNum->InvalidateAndNotifyTree();
+ }
+ }
+ }
+ // End of class <HandleResetAttrAtTxtNode>
+}
+
+sal_Bool SwTxtNode::ResetAttr( sal_uInt16 nWhich1, sal_uInt16 nWhich2 )
+{
+ const bool bOldIsSetOrResetAttr( mbInSetOrResetAttr );
+ mbInSetOrResetAttr = true;
+
+ HandleResetAttrAtTxtNode aHandleResetAttr( *this, nWhich1, nWhich2 );
+
+ sal_Bool bRet = SwCntntNode::ResetAttr( nWhich1, nWhich2 );
+
+ mbInSetOrResetAttr = bOldIsSetOrResetAttr;
+
+ return bRet;
+}
+
+sal_Bool SwTxtNode::ResetAttr( const SvUShorts& rWhichArr )
+{
+ const bool bOldIsSetOrResetAttr( mbInSetOrResetAttr );
+ mbInSetOrResetAttr = true;
+
+ HandleResetAttrAtTxtNode aHandleResetAttr( *this, rWhichArr );
+
+ sal_Bool bRet = SwCntntNode::ResetAttr( rWhichArr );
+
+ mbInSetOrResetAttr = bOldIsSetOrResetAttr;
+
+ return bRet;
+}
+
+sal_uInt16 SwTxtNode::ResetAllAttr()
+{
+ const bool bOldIsSetOrResetAttr( mbInSetOrResetAttr );
+ mbInSetOrResetAttr = true;
+
+ HandleResetAttrAtTxtNode aHandleResetAttr( *this );
+
+ sal_uInt16 nRet = SwCntntNode::ResetAllAttr();
+
+ mbInSetOrResetAttr = bOldIsSetOrResetAttr;
+
+ return nRet;
+}
+// <--
+
+// sw::Metadatable
+::sfx2::IXmlIdRegistry& SwTxtNode::GetRegistry()
+{
+ return GetDoc()->GetXmlIdRegistry();
+}
+
+bool SwTxtNode::IsInClipboard() const
+{
+ return GetDoc()->IsClipBoard();
+}
+
+bool SwTxtNode::IsInUndo() const
+{
+ return GetDoc()->GetIDocumentUndoRedo().IsUndoNodes(GetNodes());
+}
+
+bool SwTxtNode::IsInContent() const
+{
+ return !GetDoc()->IsInHeaderFooter( SwNodeIndex(*this) );
+}
+
+void SwTxtNode::SwClientNotify( const SwModify& rModify, const SfxHint& rHint )
+{
+ const SwAttrHint* pHint = dynamic_cast<const SwAttrHint*>(&rHint);
+ if ( pHint && pHint->GetId() == RES_CONDTXTFMTCOLL && &rModify == GetRegisteredIn() )
+ ChkCondColl();
+}
+
+#include <unoparagraph.hxx>
+
+uno::Reference< rdf::XMetadatable >
+SwTxtNode::MakeUnoObject()
+{
+ const uno::Reference<rdf::XMetadatable> xMeta(
+ SwXParagraph::CreateXParagraph(*GetDoc(), *this), uno::UNO_QUERY);
+ return xMeta;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/txtnode/swfntcch.cxx b/sw/source/core/txtnode/swfntcch.cxx
new file mode 100644
index 000000000000..8a421ba1ff79
--- /dev/null
+++ b/sw/source/core/txtnode/swfntcch.cxx
@@ -0,0 +1,90 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+
+#include <viewsh.hxx>
+#include "swfntcch.hxx"
+#include "fmtcol.hxx"
+#include "swfont.hxx"
+
+// aus atrstck.cxx
+extern const sal_uInt8 StackPos[];
+
+// globale Variablen, werden in SwFntCch.Hxx bekanntgegeben
+// Der FontCache wird in TxtInit.Cxx _TXTINIT erzeugt und in _TXTEXIT geloescht
+SwFontCache *pSwFontCache = NULL;
+
+/*************************************************************************
+|*
+|* SwFontObj::SwFontObj(), ~SwFontObj()
+|*
+|*************************************************************************/
+
+SwFontObj::SwFontObj( const void *pOwn, ViewShell *pSh ) :
+ SwCacheObj( (void*)pOwn ),
+ aSwFont( &((SwTxtFmtColl *)pOwn)->GetAttrSet(), pSh ? pSh->getIDocumentSettingAccess() : 0 )
+{
+ aSwFont.GoMagic( pSh, aSwFont.GetActual() );
+ const SwAttrSet& rAttrSet = ((SwTxtFmtColl *)pOwn)->GetAttrSet();
+ for (sal_uInt16 i = RES_CHRATR_BEGIN; i < RES_CHRATR_END; i++)
+ pDefaultArray[ StackPos[ i ] ] = &rAttrSet.Get( i, sal_True );
+}
+
+SwFontObj::~SwFontObj()
+{
+}
+
+/*************************************************************************
+|*
+|* SwFontAccess::SwFontAccess()
+|*
+|*************************************************************************/
+
+SwFontAccess::SwFontAccess( const void *pOwn, ViewShell *pSh ) :
+ SwCacheAccess( *pSwFontCache, pOwn,
+ ((SwTxtFmtColl*)pOwn)->IsInSwFntCache() ),
+ pShell( pSh )
+{
+}
+
+SwFontObj *SwFontAccess::Get( )
+{
+ return (SwFontObj *) SwCacheAccess::Get( );
+}
+
+SwCacheObj *SwFontAccess::NewObj( )
+{
+ ((SwTxtFmtColl*)pOwner)->SetInSwFntCache( sal_True );
+ return new SwFontObj( pOwner, pShell );
+}
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/txtnode/swfont.cxx b/sw/source/core/txtnode/swfont.cxx
new file mode 100644
index 000000000000..cfa8036ecdce
--- /dev/null
+++ b/sw/source/core/txtnode/swfont.cxx
@@ -0,0 +1,1243 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+
+#include <hintids.hxx>
+
+#include <com/sun/star/i18n/ScriptType.hdl>
+#include <vcl/outdev.hxx>
+#include <unotools/localedatawrapper.hxx>
+#include <editeng/unolingu.hxx>
+#include <editeng/brshitem.hxx>
+#include <editeng/wrlmitem.hxx>
+#include <editeng/blnkitem.hxx>
+#include <editeng/nhypitem.hxx>
+#include <editeng/kernitem.hxx>
+#include <editeng/cmapitem.hxx>
+#include <editeng/langitem.hxx>
+#include <editeng/escpitem.hxx>
+#include <editeng/akrnitem.hxx>
+#include <editeng/shdditem.hxx>
+#include <editeng/charreliefitem.hxx>
+#include <editeng/cntritem.hxx>
+#include <editeng/colritem.hxx>
+#include <editeng/cscoitem.hxx>
+#include <editeng/crsditem.hxx>
+#include <editeng/udlnitem.hxx>
+#include <editeng/wghtitem.hxx>
+#include <editeng/postitem.hxx>
+#include <editeng/fhgtitem.hxx>
+#include <editeng/fontitem.hxx>
+#include <editeng/emphitem.hxx>
+#include <editeng/charscaleitem.hxx>
+#include <editeng/charrotateitem.hxx>
+#include <editeng/twolinesitem.hxx>
+#include <editeng/charhiddenitem.hxx>
+#include <IDocumentSettingAccess.hxx>
+#include <vcl/window.hxx>
+#include <charatr.hxx>
+#include <viewsh.hxx> // Bildschirmabgleich
+#include <swfont.hxx>
+#include <fntcache.hxx> // FontCache
+#include <txtfrm.hxx> // SwTxtFrm
+#include <scriptinfo.hxx>
+
+#if defined(WNT) || defined(PM2)
+#define FNT_LEADING_HACK
+#endif
+
+#if defined(WNT)
+#define FNT_ATM_HACK
+#endif
+
+#if OSL_DEBUG_LEVEL > 1
+// globale Variable
+SvStatistics aSvStat;
+#endif
+
+using namespace ::com::sun::star;
+
+/************************************************************************
+ * Hintergrundbrush setzen, z.B. bei Zeichenvorlagen
+ ***********************************************************************/
+
+void SwFont::SetBackColor( Color* pNewColor )
+{
+ delete pBackColor;
+ pBackColor = pNewColor;
+ bFntChg = sal_True;
+ aSub[SW_LATIN].pMagic = aSub[SW_CJK].pMagic = aSub[SW_CTL].pMagic = 0;
+}
+
+// maps directions for vertical layout
+sal_uInt16 MapDirection( sal_uInt16 nDir, const sal_Bool bVertFormat )
+{
+ if ( bVertFormat )
+ {
+ switch ( nDir )
+ {
+ case 0 :
+ nDir = 2700;
+ break;
+ case 900 :
+ nDir = 0;
+ break;
+ case 2700 :
+ nDir = 1800;
+ break;
+#if OSL_DEBUG_LEVEL > 1
+ default :
+ OSL_FAIL( "Unsupported direction" );
+ break;
+#endif
+ }
+ }
+ return nDir;
+}
+
+// maps the absolute direction set at the font to its logical conterpart
+// in the rotated environment
+sal_uInt16 UnMapDirection( sal_uInt16 nDir, const sal_Bool bVertFormat )
+{
+ if ( bVertFormat )
+ {
+ switch ( nDir )
+ {
+ case 0 :
+ nDir = 900;
+ break;
+ case 1800 :
+ nDir = 2700;
+ break;
+ case 2700 :
+ nDir = 0;
+ break;
+#if OSL_DEBUG_LEVEL > 1
+ default :
+ OSL_FAIL( "Unsupported direction" );
+ break;
+#endif
+ }
+ }
+ return nDir;
+}
+
+sal_uInt16 SwFont::GetOrientation( const sal_Bool bVertFormat ) const
+{
+ return UnMapDirection( aSub[nActual].GetOrientation(), bVertFormat );
+}
+
+void SwFont::SetVertical( sal_uInt16 nDir, const sal_Bool bVertFormat )
+{
+ // map direction if frame has vertical layout
+ nDir = MapDirection( nDir, bVertFormat );
+
+ if( nDir != aSub[0].GetOrientation() )
+ {
+ bFntChg = sal_True;
+ aSub[0].SetVertical( nDir, bVertFormat );
+ aSub[1].SetVertical( nDir, bVertFormat || nDir > 1000 );
+ aSub[2].SetVertical( nDir, bVertFormat );
+ }
+}
+
+/*************************************************************************
+ Escapement:
+ frEsc: Fraction, Grad des Escapements
+ Esc = resultierendes Escapement
+ A1 = Original-Ascent (nOrgAscent)
+ A2 = verkleinerter Ascent (nEscAscent)
+ Ax = resultierender Ascent (GetAscent())
+ H1 = Original-Hoehe (nOrgHeight)
+ H2 = verkleinerter Hoehe (nEscHeight)
+ Hx = resultierender Hoehe (GetHeight())
+ Bx = resultierende Baseline fuer die Textausgabe (CalcPos())
+ (Vorsicht: Y - A1!)
+
+ Escapement:
+ Esc = H1 * frEsc;
+
+ Hochstellung:
+ Ax = A2 + Esc;
+ Hx = H2 + Esc;
+ Bx = A1 - Esc;
+
+ Tiefstellung:
+ Ax = A1;
+ Hx = A1 + Esc + (H2 - A2);
+ Bx = A1 + Esc;
+
+*************************************************************************/
+
+/*************************************************************************
+ * SwSubFont::CalcEscAscent( const sal_uInt16 nOldAscent )
+ *************************************************************************/
+
+// nEsc ist der Prozentwert
+sal_uInt16 SwSubFont::CalcEscAscent( const sal_uInt16 nOldAscent ) const
+{
+ if( DFLT_ESC_AUTO_SUPER != GetEscapement() &&
+ DFLT_ESC_AUTO_SUB != GetEscapement() )
+ {
+ const long nAscent = nOldAscent +
+ ( (long) nOrgHeight * GetEscapement() ) / 100L;
+ if ( nAscent>0 )
+ return ( Max( sal_uInt16 (nAscent), nOrgAscent ));
+ }
+ return nOrgAscent;
+}
+
+/*************************************************************************
+ * SwFont::SetDiffFnt()
+ *************************************************************************/
+
+void SwFont::SetDiffFnt( const SfxItemSet *pAttrSet,
+ const IDocumentSettingAccess *pIDocumentSettingAccess )
+{
+ delete pBackColor;
+ pBackColor = NULL;
+
+ if( pAttrSet )
+ {
+ const SfxPoolItem* pItem;
+ if( SFX_ITEM_SET == pAttrSet->GetItemState( RES_CHRATR_FONT,
+ sal_True, &pItem ))
+ {
+ const SvxFontItem *pFont = (const SvxFontItem *)pItem;
+ aSub[SW_LATIN].SetFamily( pFont->GetFamily() );
+ aSub[SW_LATIN].Font::SetName( pFont->GetFamilyName() );
+ aSub[SW_LATIN].Font::SetStyleName( pFont->GetStyleName() );
+ aSub[SW_LATIN].Font::SetPitch( pFont->GetPitch() );
+ aSub[SW_LATIN].Font::SetCharSet( pFont->GetCharSet() );
+ }
+ if( SFX_ITEM_SET == pAttrSet->GetItemState( RES_CHRATR_FONTSIZE,
+ sal_True, &pItem ))
+ {
+ const SvxFontHeightItem *pHeight = (const SvxFontHeightItem *)pItem;
+ aSub[SW_LATIN].SvxFont::SetPropr( 100 );
+ aSub[SW_LATIN].aSize = aSub[SW_LATIN].Font::GetSize();
+ Size aTmpSize = aSub[SW_LATIN].aSize;
+ aTmpSize.Height() = pHeight->GetHeight();
+ aSub[SW_LATIN].SetSize( aTmpSize );
+ }
+ if( SFX_ITEM_SET == pAttrSet->GetItemState( RES_CHRATR_POSTURE,
+ sal_True, &pItem ))
+ aSub[SW_LATIN].Font::SetItalic( ((SvxPostureItem*)pItem)->GetPosture() );
+ if( SFX_ITEM_SET == pAttrSet->GetItemState( RES_CHRATR_WEIGHT,
+ sal_True, &pItem ))
+ aSub[SW_LATIN].Font::SetWeight( ((SvxWeightItem*)pItem)->GetWeight() );
+ if( SFX_ITEM_SET == pAttrSet->GetItemState( RES_CHRATR_LANGUAGE,
+ sal_True, &pItem ))
+ aSub[SW_LATIN].SetLanguage( ((SvxLanguageItem*)pItem)->GetLanguage() );
+
+ if( SFX_ITEM_SET == pAttrSet->GetItemState( RES_CHRATR_CJK_FONT,
+ sal_True, &pItem ))
+ {
+ const SvxFontItem *pFont = (const SvxFontItem *)pItem;
+ aSub[SW_CJK].SetFamily( pFont->GetFamily() );
+ aSub[SW_CJK].Font::SetName( pFont->GetFamilyName() );
+ aSub[SW_CJK].Font::SetStyleName( pFont->GetStyleName() );
+ aSub[SW_CJK].Font::SetPitch( pFont->GetPitch() );
+ aSub[SW_CJK].Font::SetCharSet( pFont->GetCharSet() );
+ }
+ if( SFX_ITEM_SET == pAttrSet->GetItemState( RES_CHRATR_CJK_FONTSIZE,
+ sal_True, &pItem ))
+ {
+ const SvxFontHeightItem *pHeight = (const SvxFontHeightItem *)pItem;
+ aSub[SW_CJK].SvxFont::SetPropr( 100 );
+ aSub[SW_CJK].aSize = aSub[SW_CJK].Font::GetSize();
+ Size aTmpSize = aSub[SW_CJK].aSize;
+ aTmpSize.Height() = pHeight->GetHeight();
+ aSub[SW_CJK].SetSize( aTmpSize );
+ }
+ if( SFX_ITEM_SET == pAttrSet->GetItemState( RES_CHRATR_CJK_POSTURE,
+ sal_True, &pItem ))
+ aSub[SW_CJK].Font::SetItalic( ((SvxPostureItem*)pItem)->GetPosture() );
+ if( SFX_ITEM_SET == pAttrSet->GetItemState( RES_CHRATR_CJK_WEIGHT,
+ sal_True, &pItem ))
+ aSub[SW_CJK].Font::SetWeight( ((SvxWeightItem*)pItem)->GetWeight() );
+ if( SFX_ITEM_SET == pAttrSet->GetItemState( RES_CHRATR_CJK_LANGUAGE,
+ sal_True, &pItem ))
+ {
+ LanguageType eNewLang = ((SvxLanguageItem*)pItem)->GetLanguage();
+ aSub[SW_CJK].SetLanguage( eNewLang );
+ aSub[SW_LATIN].SetCJKContextLanguage( eNewLang );
+ aSub[SW_CJK].SetCJKContextLanguage( eNewLang );
+ aSub[SW_CTL].SetCJKContextLanguage( eNewLang );
+ }
+
+ if( SFX_ITEM_SET == pAttrSet->GetItemState( RES_CHRATR_CTL_FONT,
+ sal_True, &pItem ))
+ {
+ const SvxFontItem *pFont = (const SvxFontItem *)pItem;
+ aSub[SW_CTL].SetFamily( pFont->GetFamily() );
+ aSub[SW_CTL].Font::SetName( pFont->GetFamilyName() );
+ aSub[SW_CTL].Font::SetStyleName( pFont->GetStyleName() );
+ aSub[SW_CTL].Font::SetPitch( pFont->GetPitch() );
+ aSub[SW_CTL].Font::SetCharSet( pFont->GetCharSet() );
+ }
+ if( SFX_ITEM_SET == pAttrSet->GetItemState( RES_CHRATR_CTL_FONTSIZE,
+ sal_True, &pItem ))
+ {
+ const SvxFontHeightItem *pHeight = (const SvxFontHeightItem *)pItem;
+ aSub[SW_CTL].SvxFont::SetPropr( 100 );
+ aSub[SW_CTL].aSize = aSub[SW_CTL].Font::GetSize();
+ Size aTmpSize = aSub[SW_CTL].aSize;
+ aTmpSize.Height() = pHeight->GetHeight();
+ aSub[SW_CTL].SetSize( aTmpSize );
+ }
+ if( SFX_ITEM_SET == pAttrSet->GetItemState( RES_CHRATR_CTL_POSTURE,
+ sal_True, &pItem ))
+ aSub[SW_CTL].Font::SetItalic( ((SvxPostureItem*)pItem)->GetPosture() );
+ if( SFX_ITEM_SET == pAttrSet->GetItemState( RES_CHRATR_CTL_WEIGHT,
+ sal_True, &pItem ))
+ aSub[SW_CTL].Font::SetWeight( ((SvxWeightItem*)pItem)->GetWeight() );
+ if( SFX_ITEM_SET == pAttrSet->GetItemState( RES_CHRATR_CTL_LANGUAGE,
+ sal_True, &pItem ))
+ aSub[SW_CTL].SetLanguage( ((SvxLanguageItem*)pItem)->GetLanguage() );
+
+ if( SFX_ITEM_SET == pAttrSet->GetItemState( RES_CHRATR_UNDERLINE,
+ sal_True, &pItem ))
+ {
+ SetUnderline( ((SvxUnderlineItem*)pItem)->GetLineStyle() );
+ SetUnderColor( ((SvxUnderlineItem*)pItem)->GetColor() );
+ }
+ if( SFX_ITEM_SET == pAttrSet->GetItemState( RES_CHRATR_OVERLINE,
+ sal_True, &pItem ))
+ {
+ SetOverline( ((SvxOverlineItem*)pItem)->GetLineStyle() );
+ SetOverColor( ((SvxOverlineItem*)pItem)->GetColor() );
+ }
+ if( SFX_ITEM_SET == pAttrSet->GetItemState( RES_CHRATR_CROSSEDOUT,
+ sal_True, &pItem ))
+ SetStrikeout( ((SvxCrossedOutItem*)pItem)->GetStrikeout() );
+ if( SFX_ITEM_SET == pAttrSet->GetItemState( RES_CHRATR_COLOR,
+ sal_True, &pItem ))
+ SetColor( ((SvxColorItem*)pItem)->GetValue() );
+ if( SFX_ITEM_SET == pAttrSet->GetItemState( RES_CHRATR_EMPHASIS_MARK,
+ sal_True, &pItem ))
+ SetEmphasisMark( ((SvxEmphasisMarkItem*)pItem)->GetEmphasisMark() );
+
+ SetTransparent( sal_True );
+ SetAlign( ALIGN_BASELINE );
+ if( SFX_ITEM_SET == pAttrSet->GetItemState( RES_CHRATR_CONTOUR,
+ sal_True, &pItem ))
+ SetOutline( ((SvxContourItem*)pItem)->GetValue() );
+ if( SFX_ITEM_SET == pAttrSet->GetItemState( RES_CHRATR_SHADOWED,
+ sal_True, &pItem ))
+ SetShadow( ((SvxShadowedItem*)pItem)->GetValue() );
+ if( SFX_ITEM_SET == pAttrSet->GetItemState( RES_CHRATR_RELIEF,
+ sal_True, &pItem ))
+ SetRelief( (FontRelief)((SvxCharReliefItem*)pItem)->GetValue() );
+ if( SFX_ITEM_SET == pAttrSet->GetItemState( RES_CHRATR_SHADOWED,
+ sal_True, &pItem ))
+ SetPropWidth(((SvxShadowedItem*)pItem)->GetValue() ? 50 : 100 );
+ if( SFX_ITEM_SET == pAttrSet->GetItemState( RES_CHRATR_AUTOKERN,
+ sal_True, &pItem ))
+ {
+ if( ((SvxAutoKernItem*)pItem)->GetValue() )
+ {
+ SetAutoKern( ( !pIDocumentSettingAccess ||
+ !pIDocumentSettingAccess->get(IDocumentSettingAccess::KERN_ASIAN_PUNCTUATION) ) ?
+ KERNING_FONTSPECIFIC :
+ KERNING_ASIAN );
+ }
+ else
+ SetAutoKern( 0 );
+ }
+ if( SFX_ITEM_SET == pAttrSet->GetItemState( RES_CHRATR_WORDLINEMODE,
+ sal_True, &pItem ))
+ SetWordLineMode( ((SvxWordLineModeItem*)pItem)->GetValue() );
+
+ if( SFX_ITEM_SET == pAttrSet->GetItemState( RES_CHRATR_ESCAPEMENT,
+ sal_True, &pItem ))
+ {
+ const SvxEscapementItem *pEsc = (const SvxEscapementItem *)pItem;
+ SetEscapement( pEsc->GetEsc() );
+ if( aSub[SW_LATIN].IsEsc() )
+ SetProportion( pEsc->GetProp() );
+ }
+ if( SFX_ITEM_SET == pAttrSet->GetItemState( RES_CHRATR_CASEMAP,
+ sal_True, &pItem ))
+ SetCaseMap( ((SvxCaseMapItem*)pItem)->GetCaseMap() );
+ if( SFX_ITEM_SET == pAttrSet->GetItemState( RES_CHRATR_KERNING,
+ sal_True, &pItem ))
+ SetFixKerning( ((SvxKerningItem*)pItem)->GetValue() );
+ if( SFX_ITEM_SET == pAttrSet->GetItemState( RES_CHRATR_NOHYPHEN,
+ sal_True, &pItem ))
+ SetNoHyph( ((SvxNoHyphenItem*)pItem)->GetValue() );
+ if( SFX_ITEM_SET == pAttrSet->GetItemState( RES_CHRATR_BLINK,
+ sal_True, &pItem ))
+ SetBlink( ((SvxBlinkItem*)pItem)->GetValue() );
+ if( SFX_ITEM_SET == pAttrSet->GetItemState( RES_CHRATR_ROTATE,
+ sal_True, &pItem ))
+ SetVertical( ((SvxCharRotateItem*)pItem)->GetValue() );
+ if( SFX_ITEM_SET == pAttrSet->GetItemState( RES_CHRATR_BACKGROUND,
+ sal_True, &pItem ))
+ pBackColor = new Color( ((SvxBrushItem*)pItem)->GetColor() );
+ else
+ pBackColor = NULL;
+ const SfxPoolItem* pTwoLinesItem = 0;
+ if( SFX_ITEM_SET ==
+ pAttrSet->GetItemState( RES_CHRATR_TWO_LINES, sal_True, &pTwoLinesItem ))
+ if ( ((SvxTwoLinesItem*)pTwoLinesItem)->GetValue() )
+ SetVertical( 0 );
+ }
+ else
+ {
+ Invalidate();
+ bNoHyph = sal_False;
+ bBlink = sal_False;
+ }
+ bPaintBlank = sal_False;
+ bPaintWrong = sal_False;
+ OSL_ENSURE( aSub[SW_LATIN].IsTransparent(), "SwFont: Transparent revolution" );
+}
+
+/*************************************************************************
+ * class SwFont
+ *************************************************************************/
+
+SwFont::SwFont( const SwFont &rFont )
+{
+ aSub[SW_LATIN] = rFont.aSub[SW_LATIN];
+ aSub[SW_CJK] = rFont.aSub[SW_CJK];
+ aSub[SW_CTL] = rFont.aSub[SW_CTL];
+ nActual = rFont.nActual;
+ pBackColor = rFont.pBackColor ? new Color( *rFont.pBackColor ) : NULL;
+ aUnderColor = rFont.GetUnderColor();
+ aOverColor = rFont.GetOverColor();
+ nToxCnt = 0;
+ nRefCnt = 0;
+ m_nMetaCount = 0;
+ bFntChg = rFont.bFntChg;
+ bOrgChg = rFont.bOrgChg;
+ bPaintBlank = rFont.bPaintBlank;
+ bPaintWrong = sal_False;
+ bURL = rFont.bURL;
+ bGreyWave = rFont.bGreyWave;
+ bNoColReplace = rFont.bNoColReplace;
+ bNoHyph = rFont.bNoHyph;
+ bBlink = rFont.bBlink;
+}
+
+SwFont::SwFont( const SwAttrSet* pAttrSet,
+ const IDocumentSettingAccess* pIDocumentSettingAccess )
+{
+ nActual = SW_LATIN;
+ nToxCnt = 0;
+ nRefCnt = 0;
+ m_nMetaCount = 0;
+ bPaintBlank = sal_False;
+ bPaintWrong = sal_False;
+ bURL = sal_False;
+ bGreyWave = sal_False;
+ bNoColReplace = sal_False;
+ bNoHyph = pAttrSet->GetNoHyphenHere().GetValue();
+ bBlink = pAttrSet->GetBlink().GetValue();
+ bOrgChg = sal_True;
+ {
+ const SvxFontItem& rFont = pAttrSet->GetFont();
+ aSub[SW_LATIN].SetFamily( rFont.GetFamily() );
+ aSub[SW_LATIN].SetName( rFont.GetFamilyName() );
+ aSub[SW_LATIN].SetStyleName( rFont.GetStyleName() );
+ aSub[SW_LATIN].SetPitch( rFont.GetPitch() );
+ aSub[SW_LATIN].SetCharSet( rFont.GetCharSet() );
+ aSub[SW_LATIN].SvxFont::SetPropr( 100 ); // 100% der FontSize
+ Size aTmpSize = aSub[SW_LATIN].aSize;
+ aTmpSize.Height() = pAttrSet->GetSize().GetHeight();
+ aSub[SW_LATIN].SetSize( aTmpSize );
+ aSub[SW_LATIN].SetItalic( pAttrSet->GetPosture().GetPosture() );
+ aSub[SW_LATIN].SetWeight( pAttrSet->GetWeight().GetWeight() );
+ aSub[SW_LATIN].SetLanguage( pAttrSet->GetLanguage().GetLanguage() );
+ }
+
+ {
+ const SvxFontItem& rFont = pAttrSet->GetCJKFont();
+ aSub[SW_CJK].SetFamily( rFont.GetFamily() );
+ aSub[SW_CJK].SetName( rFont.GetFamilyName() );
+ aSub[SW_CJK].SetStyleName( rFont.GetStyleName() );
+ aSub[SW_CJK].SetPitch( rFont.GetPitch() );
+ aSub[SW_CJK].SetCharSet( rFont.GetCharSet() );
+ aSub[SW_CJK].SvxFont::SetPropr( 100 ); // 100% der FontSize
+ Size aTmpSize = aSub[SW_CJK].aSize;
+ aTmpSize.Height() = pAttrSet->GetCJKSize().GetHeight();
+ aSub[SW_CJK].SetSize( aTmpSize );
+ aSub[SW_CJK].SetItalic( pAttrSet->GetCJKPosture().GetPosture() );
+ aSub[SW_CJK].SetWeight( pAttrSet->GetCJKWeight().GetWeight() );
+ LanguageType eNewLang = pAttrSet->GetCJKLanguage().GetLanguage();
+ aSub[SW_CJK].SetLanguage( eNewLang );
+ aSub[SW_LATIN].SetCJKContextLanguage( eNewLang );
+ aSub[SW_CJK].SetCJKContextLanguage( eNewLang );
+ aSub[SW_CTL].SetCJKContextLanguage( eNewLang );
+ }
+
+ {
+ const SvxFontItem& rFont = pAttrSet->GetCTLFont();
+ aSub[SW_CTL].SetFamily( rFont.GetFamily() );
+ aSub[SW_CTL].SetName( rFont.GetFamilyName() );
+ aSub[SW_CTL].SetStyleName( rFont.GetStyleName() );
+ aSub[SW_CTL].SetPitch( rFont.GetPitch() );
+ aSub[SW_CTL].SetCharSet( rFont.GetCharSet() );
+ aSub[SW_CTL].SvxFont::SetPropr( 100 ); // 100% der FontSize
+ Size aTmpSize = aSub[SW_CTL].aSize;
+ aTmpSize.Height() = pAttrSet->GetCTLSize().GetHeight();
+ aSub[SW_CTL].SetSize( aTmpSize );
+ aSub[SW_CTL].SetItalic( pAttrSet->GetCTLPosture().GetPosture() );
+ aSub[SW_CTL].SetWeight( pAttrSet->GetCTLWeight().GetWeight() );
+ aSub[SW_CTL].SetLanguage( pAttrSet->GetCTLLanguage().GetLanguage() );
+ }
+
+ const FontUnderline eUnderline = pAttrSet->GetUnderline().GetLineStyle();
+ if ( pAttrSet->GetCharHidden().GetValue() )
+ SetUnderline( UNDERLINE_DOTTED );
+ else
+ SetUnderline( eUnderline );
+ SetUnderColor( pAttrSet->GetUnderline().GetColor() );
+ SetOverline( pAttrSet->GetOverline().GetLineStyle() );
+ SetOverColor( pAttrSet->GetOverline().GetColor() );
+ SetEmphasisMark( pAttrSet->GetEmphasisMark().GetEmphasisMark() );
+ SetStrikeout( pAttrSet->GetCrossedOut().GetStrikeout() );
+ SetColor( pAttrSet->GetColor().GetValue() );
+ SetTransparent( sal_True );
+ SetAlign( ALIGN_BASELINE );
+ SetOutline( pAttrSet->GetContour().GetValue() );
+ SetShadow( pAttrSet->GetShadowed().GetValue() );
+ SetPropWidth( pAttrSet->GetCharScaleW().GetValue() );
+ SetRelief( (FontRelief)pAttrSet->GetCharRelief().GetValue() );
+ if( pAttrSet->GetAutoKern().GetValue() )
+ {
+ SetAutoKern( ( !pIDocumentSettingAccess ||
+ !pIDocumentSettingAccess->get(IDocumentSettingAccess::KERN_ASIAN_PUNCTUATION) ) ?
+ KERNING_FONTSPECIFIC :
+ KERNING_ASIAN );
+ }
+ else
+ SetAutoKern( 0 );
+ SetWordLineMode( pAttrSet->GetWordLineMode().GetValue() );
+ const SvxEscapementItem &rEsc = pAttrSet->GetEscapement();
+ SetEscapement( rEsc.GetEsc() );
+ if( aSub[SW_LATIN].IsEsc() )
+ SetProportion( rEsc.GetProp() );
+ SetCaseMap( pAttrSet->GetCaseMap().GetCaseMap() );
+ SetFixKerning( pAttrSet->GetKerning().GetValue() );
+ const SfxPoolItem* pItem;
+ if( SFX_ITEM_SET == pAttrSet->GetItemState( RES_CHRATR_BACKGROUND,
+ sal_True, &pItem ))
+ pBackColor = new Color( ((SvxBrushItem*)pItem)->GetColor() );
+ else
+ pBackColor = NULL;
+ const SvxTwoLinesItem& rTwoLinesItem = pAttrSet->Get2Lines();
+ if ( ! rTwoLinesItem.GetValue() )
+ SetVertical( pAttrSet->GetCharRotate().GetValue() );
+ else
+ SetVertical( 0 );
+}
+
+SwSubFont& SwSubFont::operator=( const SwSubFont &rFont )
+{
+ SvxFont::operator=( rFont );
+ pMagic = rFont.pMagic;
+ nFntIndex = rFont.nFntIndex;
+ nOrgHeight = rFont.nOrgHeight;
+ nOrgAscent = rFont.nOrgAscent;
+ nPropWidth = rFont.nPropWidth;
+ aSize = rFont.aSize;
+ return *this;
+}
+
+SwFont& SwFont::operator=( const SwFont &rFont )
+{
+ aSub[SW_LATIN] = rFont.aSub[SW_LATIN];
+ aSub[SW_CJK] = rFont.aSub[SW_CJK];
+ aSub[SW_CTL] = rFont.aSub[SW_CTL];
+ nActual = rFont.nActual;
+ delete pBackColor;
+ pBackColor = rFont.pBackColor ? new Color( *rFont.pBackColor ) : NULL;
+ aUnderColor = rFont.GetUnderColor();
+ aOverColor = rFont.GetOverColor();
+ nToxCnt = 0;
+ nRefCnt = 0;
+ m_nMetaCount = 0;
+ bFntChg = rFont.bFntChg;
+ bOrgChg = rFont.bOrgChg;
+ bPaintBlank = rFont.bPaintBlank;
+ bPaintWrong = sal_False;
+ bURL = rFont.bURL;
+ bGreyWave = rFont.bGreyWave;
+ bNoColReplace = rFont.bNoColReplace;
+ bNoHyph = rFont.bNoHyph;
+ bBlink = rFont.bBlink;
+ return *this;
+}
+
+/*************************************************************************
+ * SwFont::GoMagic()
+ *************************************************************************/
+
+void SwFont::GoMagic( ViewShell *pSh, sal_uInt8 nWhich )
+{
+ SwFntAccess aFntAccess( aSub[nWhich].pMagic, aSub[nWhich].nFntIndex,
+ &aSub[nWhich], pSh, sal_True );
+}
+
+/*************************************************************************
+ * SwSubFont::IsSymbol()
+ *************************************************************************/
+
+sal_Bool SwSubFont::IsSymbol( ViewShell *pSh )
+{
+ SwFntAccess aFntAccess( pMagic, nFntIndex, this, pSh, sal_False );
+ return aFntAccess.Get()->IsSymbol();
+}
+
+/*************************************************************************
+ * SwSubFont::ChgFnt()
+ *************************************************************************/
+
+sal_Bool SwSubFont::ChgFnt( ViewShell *pSh, OutputDevice& rOut )
+{
+ if ( pLastFont )
+ pLastFont->Unlock();
+ SwFntAccess aFntAccess( pMagic, nFntIndex, this, pSh, sal_True );
+ SV_STAT( nChangeFont );
+
+ pLastFont = aFntAccess.Get();
+
+ pLastFont->SetDevFont( pSh, rOut );
+
+ pLastFont->Lock();
+ return UNDERLINE_NONE != GetUnderline() ||
+ UNDERLINE_NONE != GetOverline() ||
+ STRIKEOUT_NONE != GetStrikeout();
+}
+
+/*************************************************************************
+ * SwFont::ChgPhysFnt()
+ *************************************************************************/
+
+void SwFont::ChgPhysFnt( ViewShell *pSh, OutputDevice& rOut )
+{
+ if( bOrgChg && aSub[nActual].IsEsc() )
+ {
+ const sal_uInt8 nOldProp = aSub[nActual].GetPropr();
+ SetProportion( 100 );
+ ChgFnt( pSh, rOut );
+ SwFntAccess aFntAccess( aSub[nActual].pMagic, aSub[nActual].nFntIndex,
+ &aSub[nActual], pSh );
+ aSub[nActual].nOrgHeight = aFntAccess.Get()->GetFontHeight( pSh, rOut );
+ aSub[nActual].nOrgAscent = aFntAccess.Get()->GetFontAscent( pSh, rOut );
+ SetProportion( nOldProp );
+ bOrgChg = sal_False;
+ }
+
+ if( bFntChg )
+ {
+ ChgFnt( pSh, rOut );
+ bFntChg = bOrgChg;
+ }
+ if( rOut.GetTextLineColor() != aUnderColor )
+ rOut.SetTextLineColor( aUnderColor );
+ if( rOut.GetOverlineColor() != aOverColor )
+ rOut.SetOverlineColor( aOverColor );
+}
+
+/*************************************************************************
+ * SwFont::CalcEscHeight()
+ * Height = MaxAscent + MaxDescent
+ * MaxAscent = Max (T1_ascent, T2_ascent + (Esc * T1_height) );
+ * MaxDescent = Max (T1_height-T1_ascent,
+ * T2_height-T2_ascent - (Esc * T1_height)
+ *************************************************************************/
+
+sal_uInt16 SwSubFont::CalcEscHeight( const sal_uInt16 nOldHeight,
+ const sal_uInt16 nOldAscent ) const
+{
+ if( DFLT_ESC_AUTO_SUPER != GetEscapement() &&
+ DFLT_ESC_AUTO_SUB != GetEscapement() )
+ {
+ long nDescent = nOldHeight - nOldAscent -
+ ( (long) nOrgHeight * GetEscapement() ) / 100L;
+ const sal_uInt16 nDesc = ( nDescent>0 ) ? Max ( sal_uInt16(nDescent),
+ sal_uInt16(nOrgHeight - nOrgAscent) ) : nOrgHeight - nOrgAscent;
+ return ( nDesc + CalcEscAscent( nOldAscent ) );
+ }
+ return nOrgHeight;
+}
+
+short SwSubFont::_CheckKerning( )
+{
+ short nKernx = - short( Font::GetSize().Height() / 6 );
+
+ if ( nKernx < GetFixKerning() )
+ return GetFixKerning();
+ return nKernx;
+}
+
+/*************************************************************************
+ * SwSubFont::GetAscent()
+ *************************************************************************/
+
+sal_uInt16 SwSubFont::GetAscent( ViewShell *pSh, const OutputDevice& rOut )
+{
+ sal_uInt16 nAscent;
+ SwFntAccess aFntAccess( pMagic, nFntIndex, this, pSh );
+ nAscent = aFntAccess.Get()->GetFontAscent( pSh, rOut );
+ if( GetEscapement() )
+ nAscent = CalcEscAscent( nAscent );
+ return nAscent;
+}
+
+/*************************************************************************
+ * SwSubFont::GetHeight()
+ *************************************************************************/
+
+sal_uInt16 SwSubFont::GetHeight( ViewShell *pSh, const OutputDevice& rOut )
+{
+ SV_STAT( nGetTextSize );
+ SwFntAccess aFntAccess( pMagic, nFntIndex, this, pSh );
+ const sal_uInt16 nHeight = aFntAccess.Get()->GetFontHeight( pSh, rOut );
+ if ( GetEscapement() )
+ {
+ const sal_uInt16 nAscent = aFntAccess.Get()->GetFontAscent( pSh, rOut );
+ return CalcEscHeight( nHeight, nAscent ); // + nLeading;
+ }
+ return nHeight; // + nLeading;
+}
+
+/*************************************************************************
+ * SwSubFont::_GetTxtSize()
+ *************************************************************************/
+Size SwSubFont::_GetTxtSize( SwDrawTextInfo& rInf )
+{
+ // Robust: Eigentlich sollte der Font bereits eingestellt sein, aber
+ // sicher ist sicher ...
+ if ( !pLastFont || pLastFont->GetOwner()!=pMagic ||
+ !IsSameInstance( rInf.GetpOut()->GetFont() ) )
+ ChgFnt( rInf.GetShell(), rInf.GetOut() );
+
+ SwDigitModeModifier aDigitModeModifier( rInf.GetOut(), rInf.GetFont()->GetLanguage() );
+
+ Size aTxtSize;
+ xub_StrLen nLn = ( rInf.GetLen() == STRING_LEN ? rInf.GetText().Len()
+ : rInf.GetLen() );
+ rInf.SetLen( nLn );
+ if( IsCapital() && nLn )
+ aTxtSize = GetCapitalSize( rInf );
+ else
+ {
+ SV_STAT( nGetTextSize );
+ long nOldKern = rInf.GetKern();
+ const XubString &rOldTxt = rInf.GetText();
+ rInf.SetKern( CheckKerning() );
+ if ( !IsCaseMap() )
+ aTxtSize = pLastFont->GetTextSize( rInf );
+ else
+ {
+ String aTmp = CalcCaseMap( rInf.GetText() );
+ const XubString &rOldStr = rInf.GetText();
+ sal_Bool bCaseMapLengthDiffers(aTmp.Len() != rOldStr.Len());
+
+ if(bCaseMapLengthDiffers && rInf.GetLen())
+ {
+ // #108203#
+ // If the length of the original string and the CaseMapped one
+ // are different, it is necessary to handle the given text part as
+ // a single snippet since it�s size may differ, too.
+ xub_StrLen nOldIdx(rInf.GetIdx());
+ xub_StrLen nOldLen(rInf.GetLen());
+ const XubString aSnippet(rOldStr, nOldIdx, nOldLen);
+ XubString aNewText(CalcCaseMap(aSnippet));
+
+ rInf.SetText( aNewText );
+ rInf.SetIdx( 0 );
+ rInf.SetLen( aNewText.Len() );
+
+ aTxtSize = pLastFont->GetTextSize( rInf );
+
+ rInf.SetIdx( nOldIdx );
+ rInf.SetLen( nOldLen );
+ }
+ else
+ {
+ rInf.SetText( aTmp );
+ aTxtSize = pLastFont->GetTextSize( rInf );
+ }
+
+ rInf.SetText( rOldStr );
+ }
+ rInf.SetKern( nOldKern );
+ rInf.SetText( rOldTxt );
+ // 15142: Ein Wort laenger als eine Zeile, beim Zeilenumbruch
+ // hochgestellt, muss seine effektive Hoehe melden.
+ if( GetEscapement() )
+ {
+ const sal_uInt16 nAscent = pLastFont->GetFontAscent( rInf.GetShell(),
+ rInf.GetOut() );
+ aTxtSize.Height() =
+ (long)CalcEscHeight( (sal_uInt16)aTxtSize.Height(), nAscent);
+ }
+ }
+
+ if (1==rInf.GetLen() && CH_TXT_ATR_FIELDSTART==rInf.GetText().GetChar(rInf.GetIdx()))
+ {
+ xub_StrLen nOldIdx(rInf.GetIdx());
+ xub_StrLen nOldLen(rInf.GetLen());
+ String aNewText=String::CreateFromAscii(CH_TXT_ATR_SUBST_FIELDSTART);
+ rInf.SetText( aNewText );
+ rInf.SetIdx( 0 );
+ rInf.SetLen( aNewText.Len() );
+ aTxtSize = pLastFont->GetTextSize( rInf );
+ rInf.SetIdx( nOldIdx );
+ rInf.SetLen( nOldLen );
+ }
+ else if (1==rInf.GetLen() && CH_TXT_ATR_FIELDEND==rInf.GetText().GetChar(rInf.GetIdx()))
+ {
+ xub_StrLen nOldIdx(rInf.GetIdx());
+ xub_StrLen nOldLen(rInf.GetLen());
+ String aNewText=String::CreateFromAscii(CH_TXT_ATR_SUBST_FIELDEND);
+ rInf.SetText( aNewText );
+ rInf.SetIdx( 0 );
+ rInf.SetLen( aNewText.Len() );
+ aTxtSize = pLastFont->GetTextSize( rInf );
+ rInf.SetIdx( nOldIdx );
+ rInf.SetLen( nOldLen );
+ }
+
+ return aTxtSize;
+}
+
+/*************************************************************************
+ * SwSubFont::_DrawText()
+ *************************************************************************/
+
+void SwSubFont::_DrawText( SwDrawTextInfo &rInf, const sal_Bool bGrey )
+{
+ rInf.SetGreyWave( bGrey );
+ xub_StrLen nLn = rInf.GetText().Len();
+ if( !rInf.GetLen() || !nLn )
+ return;
+ if( STRING_LEN == rInf.GetLen() )
+ rInf.SetLen( nLn );
+
+ FontUnderline nOldUnder = UNDERLINE_NONE;
+ SwUnderlineFont* pUnderFnt = 0;
+
+ if( rInf.GetUnderFnt() )
+ {
+ nOldUnder = GetUnderline();
+ SetUnderline( UNDERLINE_NONE );
+ pUnderFnt = rInf.GetUnderFnt();
+ }
+
+ if( !pLastFont || pLastFont->GetOwner()!=pMagic )
+ ChgFnt( rInf.GetShell(), rInf.GetOut() );
+
+ SwDigitModeModifier aDigitModeModifier( rInf.GetOut(), rInf.GetFont()->GetLanguage() );
+
+ Point aPos( rInf.GetPos() );
+ const Point &rOld = rInf.GetPos();
+ rInf.SetPos( aPos );
+
+ if( GetEscapement() )
+ CalcEsc( rInf, aPos );
+
+ rInf.SetKern( CheckKerning() + rInf.GetSperren() / SPACING_PRECISION_FACTOR );
+
+ if( IsCapital() )
+ DrawCapital( rInf );
+ else
+ {
+ SV_STAT( nDrawText );
+ if ( !IsCaseMap() )
+ pLastFont->DrawText( rInf );
+ else
+ {
+ const XubString &rOldStr = rInf.GetText();
+ XubString aString( CalcCaseMap( rOldStr ) );
+ sal_Bool bCaseMapLengthDiffers(aString.Len() != rOldStr.Len());
+
+ if(bCaseMapLengthDiffers && rInf.GetLen())
+ {
+ // #108203#
+ // If the length of the original string and the CaseMapped one
+ // are different, it is necessary to handle the given text part as
+ // a single snippet since it�s size may differ, too.
+ xub_StrLen nOldIdx(rInf.GetIdx());
+ xub_StrLen nOldLen(rInf.GetLen());
+ const XubString aSnippet(rOldStr, nOldIdx, nOldLen);
+ XubString aNewText = CalcCaseMap(aSnippet);
+
+ rInf.SetText( aNewText );
+ rInf.SetIdx( 0 );
+ rInf.SetLen( aNewText.Len() );
+
+ pLastFont->DrawText( rInf );
+
+ rInf.SetIdx( nOldIdx );
+ rInf.SetLen( nOldLen );
+ }
+ else
+ {
+ rInf.SetText( aString );
+ pLastFont->DrawText( rInf );
+ }
+
+ rInf.SetText( rOldStr );
+ }
+ }
+
+ if( pUnderFnt && nOldUnder != UNDERLINE_NONE )
+ {
+static sal_Char const sDoubleSpace[] = " ";
+ Size aFontSize = _GetTxtSize( rInf );
+ const XubString &rOldStr = rInf.GetText();
+ XubString aStr( sDoubleSpace, RTL_TEXTENCODING_MS_1252 );
+
+ xub_StrLen nOldIdx = rInf.GetIdx();
+ xub_StrLen nOldLen = rInf.GetLen();
+ long nSpace = 0;
+ if( rInf.GetSpace() )
+ {
+ xub_StrLen nTmpEnd = nOldIdx + nOldLen;
+ if( nTmpEnd > rOldStr.Len() )
+ nTmpEnd = rOldStr.Len();
+
+ const SwScriptInfo* pSI = rInf.GetScriptInfo();
+
+ const sal_Bool bAsianFont =
+ ( rInf.GetFont() && SW_CJK == rInf.GetFont()->GetActual() );
+ for( xub_StrLen nTmp = nOldIdx; nTmp < nTmpEnd; ++nTmp )
+ {
+ if( CH_BLANK == rOldStr.GetChar( nTmp ) || bAsianFont ||
+ ( nTmp + 1 < rOldStr.Len() && pSI &&
+ i18n::ScriptType::ASIAN == pSI->ScriptType( nTmp + 1 ) ) )
+ ++nSpace;
+ }
+
+ // if next portion if a hole portion we do not consider any
+ // extra space added because the last character was ASIAN
+ if ( nSpace && rInf.IsSpaceStop() && bAsianFont )
+ --nSpace;
+
+ nSpace *= rInf.GetSpace() / SPACING_PRECISION_FACTOR;
+ }
+
+ rInf.SetWidth( sal_uInt16(aFontSize.Width() + nSpace) );
+ rInf.SetText( aStr );
+ rInf.SetIdx( 0 );
+ rInf.SetLen( 2 );
+ SetUnderline( nOldUnder );
+ rInf.SetUnderFnt( 0 );
+
+ // set position for underline font
+ rInf.SetPos( pUnderFnt->GetPos() );
+
+ pUnderFnt->GetFont()._DrawStretchText( rInf );
+
+ rInf.SetUnderFnt( pUnderFnt );
+ rInf.SetText( rOldStr );
+ rInf.SetIdx( nOldIdx );
+ rInf.SetLen( nOldLen );
+ }
+
+ rInf.SetPos( rOld );
+}
+
+void SwSubFont::_DrawStretchText( SwDrawTextInfo &rInf )
+{
+ if( !rInf.GetLen() || !rInf.GetText().Len() )
+ return;
+
+ FontUnderline nOldUnder = UNDERLINE_NONE;
+ SwUnderlineFont* pUnderFnt = 0;
+
+ if( rInf.GetUnderFnt() )
+ {
+ nOldUnder = GetUnderline();
+ SetUnderline( UNDERLINE_NONE );
+ pUnderFnt = rInf.GetUnderFnt();
+ }
+
+ if ( !pLastFont || pLastFont->GetOwner() != pMagic )
+ ChgFnt( rInf.GetShell(), rInf.GetOut() );
+
+ SwDigitModeModifier aDigitModeModifier( rInf.GetOut(), rInf.GetFont()->GetLanguage() );
+
+ rInf.ApplyAutoColor();
+
+ Point aPos( rInf.GetPos() );
+
+ if( GetEscapement() )
+ CalcEsc( rInf, aPos );
+
+ rInf.SetKern( CheckKerning() + rInf.GetSperren() / SPACING_PRECISION_FACTOR );
+ const Point &rOld = rInf.GetPos();
+ rInf.SetPos( aPos );
+
+ if( IsCapital() )
+ DrawStretchCapital( rInf );
+ else
+ {
+ SV_STAT( nDrawStretchText );
+
+ if ( rInf.GetFrm() )
+ {
+ if ( rInf.GetFrm()->IsRightToLeft() )
+ rInf.GetFrm()->SwitchLTRtoRTL( aPos );
+
+ if ( rInf.GetFrm()->IsVertical() )
+ rInf.GetFrm()->SwitchHorizontalToVertical( aPos );
+ }
+
+ if ( !IsCaseMap() )
+ rInf.GetOut().DrawStretchText( aPos, rInf.GetWidth(),
+ rInf.GetText(), rInf.GetIdx(), rInf.GetLen() );
+ else
+ rInf.GetOut().DrawStretchText( aPos, rInf.GetWidth(), CalcCaseMap(
+ rInf.GetText() ), rInf.GetIdx(), rInf.GetLen() );
+ }
+
+ if( pUnderFnt && nOldUnder != UNDERLINE_NONE )
+ {
+static sal_Char const sDoubleSpace[] = " ";
+ const XubString &rOldStr = rInf.GetText();
+ XubString aStr( sDoubleSpace, RTL_TEXTENCODING_MS_1252 );
+ xub_StrLen nOldIdx = rInf.GetIdx();
+ xub_StrLen nOldLen = rInf.GetLen();
+ rInf.SetText( aStr );
+ rInf.SetIdx( 0 );
+ rInf.SetLen( 2 );
+ SetUnderline( nOldUnder );
+ rInf.SetUnderFnt( 0 );
+
+ // set position for underline font
+ rInf.SetPos( pUnderFnt->GetPos() );
+
+ pUnderFnt->GetFont()._DrawStretchText( rInf );
+
+ rInf.SetUnderFnt( pUnderFnt );
+ rInf.SetText( rOldStr );
+ rInf.SetIdx( nOldIdx );
+ rInf.SetLen( nOldLen );
+ }
+
+ rInf.SetPos( rOld );
+}
+
+/*************************************************************************
+ * SwSubFont::_GetCrsrOfst()
+ *************************************************************************/
+
+xub_StrLen SwSubFont::_GetCrsrOfst( SwDrawTextInfo& rInf )
+{
+ if ( !pLastFont || pLastFont->GetOwner()!=pMagic )
+ ChgFnt( rInf.GetShell(), rInf.GetOut() );
+
+ SwDigitModeModifier aDigitModeModifier( rInf.GetOut(), rInf.GetFont()->GetLanguage() );
+
+ xub_StrLen nLn = rInf.GetLen() == STRING_LEN ? rInf.GetText().Len()
+ : rInf.GetLen();
+ rInf.SetLen( nLn );
+ xub_StrLen nCrsr = 0;
+ if( IsCapital() && nLn )
+ nCrsr = GetCapitalCrsrOfst( rInf );
+ else
+ {
+ const XubString &rOldTxt = rInf.GetText();
+ long nOldKern = rInf.GetKern();
+ rInf.SetKern( CheckKerning() );
+ SV_STAT( nGetTextSize );
+ if ( !IsCaseMap() )
+ nCrsr = pLastFont->GetCrsrOfst( rInf );
+ else
+ {
+ String aTmp = CalcCaseMap( rInf.GetText() );
+ rInf.SetText( aTmp );
+ nCrsr = pLastFont->GetCrsrOfst( rInf );
+ }
+ rInf.SetKern( nOldKern );
+ rInf.SetText( rOldTxt );
+ }
+ return nCrsr;
+}
+
+/*************************************************************************
+ * SwSubFont::CalcEsc()
+ *************************************************************************/
+
+void SwSubFont::CalcEsc( SwDrawTextInfo& rInf, Point& rPos )
+{
+ long nOfst;
+
+ sal_uInt16 nDir = UnMapDirection(
+ GetOrientation(), rInf.GetFrm() && rInf.GetFrm()->IsVertical() );
+
+ switch ( GetEscapement() )
+ {
+ case DFLT_ESC_AUTO_SUB :
+ nOfst = nOrgHeight - nOrgAscent -
+ pLastFont->GetFontHeight( rInf.GetShell(), rInf.GetOut() ) +
+ pLastFont->GetFontAscent( rInf.GetShell(), rInf.GetOut() );
+
+ switch ( nDir )
+ {
+ case 0 :
+ rPos.Y() += nOfst;
+ break;
+ case 900 :
+ rPos.X() += nOfst;
+ break;
+ case 2700 :
+ rPos.X() -= nOfst;
+ break;
+ }
+
+ break;
+ case DFLT_ESC_AUTO_SUPER :
+ nOfst = pLastFont->GetFontAscent( rInf.GetShell(), rInf.GetOut() ) -
+ nOrgAscent;
+
+
+ switch ( nDir )
+ {
+ case 0 :
+ rPos.Y() += nOfst;
+ break;
+ case 900 :
+ rPos.X() += nOfst;
+ break;
+ case 2700 :
+ rPos.X() -= nOfst;
+ break;
+ }
+
+ break;
+ default :
+ nOfst = ((long)nOrgHeight * GetEscapement()) / 100L;
+
+ switch ( nDir )
+ {
+ case 0 :
+ rPos.Y() -= nOfst;
+ break;
+ case 900 :
+ rPos.X() -= nOfst;
+ break;
+ case 2700 :
+ rPos.X() += nOfst;
+ break;
+ }
+ }
+}
+
+// used during painting of small capitals
+void SwDrawTextInfo::Shift( sal_uInt16 nDir )
+{
+#if OSL_DEBUG_LEVEL > 1
+ OSL_ENSURE( bPos, "DrawTextInfo: Undefined Position" );
+ OSL_ENSURE( bSize, "DrawTextInfo: Undefined Width" );
+#endif
+
+ const sal_Bool bBidiPor = ( GetFrm() && GetFrm()->IsRightToLeft() ) !=
+ ( 0 != ( TEXT_LAYOUT_BIDI_RTL & GetpOut()->GetLayoutMode() ) );
+
+ nDir = bBidiPor ?
+ 1800 :
+ UnMapDirection( nDir, GetFrm() && GetFrm()->IsVertical() );
+
+ switch ( nDir )
+ {
+ case 0 :
+ ((Point*)pPos)->X() += GetSize().Width();
+ break;
+ case 900 :
+ OSL_ENSURE( ((Point*)pPos)->Y() >= GetSize().Width(), "Going underground" );
+ ((Point*)pPos)->Y() -= GetSize().Width();
+ break;
+ case 1800 :
+ ((Point*)pPos)->X() -= GetSize().Width();
+ break;
+ case 2700 :
+ ((Point*)pPos)->Y() += GetSize().Width();
+ break;
+ }
+}
+
+/*************************************************************************
+ * SwUnderlineFont::~SwUnderlineFont
+ *
+ * Used for the "continuous underline" feature.
+ *************************************************************************/
+
+SwUnderlineFont::SwUnderlineFont( SwFont& rFnt, const Point& rPoint )
+ : aPos( rPoint ), pFnt( &rFnt )
+{
+};
+
+SwUnderlineFont::~SwUnderlineFont()
+{
+ delete pFnt;
+}
+
+//Helper for filters to find true lineheight of a font
+long AttrSetToLineHeight( const IDocumentSettingAccess& rIDocumentSettingAccess,
+ const SwAttrSet &rSet,
+ const OutputDevice &rOut, sal_Int16 nScript)
+{
+ SwFont aFont(&rSet, &rIDocumentSettingAccess);
+ sal_uInt8 nActual;
+ switch (nScript)
+ {
+ default:
+ case i18n::ScriptType::LATIN:
+ nActual = SW_LATIN;
+ break;
+ case i18n::ScriptType::ASIAN:
+ nActual = SW_CJK;
+ break;
+ case i18n::ScriptType::COMPLEX:
+ nActual = SW_CTL;
+ break;
+ }
+ aFont.SetActual(nActual);
+
+ OutputDevice &rMutableOut = const_cast<OutputDevice &>(rOut);
+ const Font aOldFont(rMutableOut.GetFont());
+
+ rMutableOut.SetFont(aFont.GetActualFont());
+ long nHeight = rMutableOut.GetTextHeight();
+
+ rMutableOut.SetFont(aOldFont);
+ return nHeight;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/txtnode/thints.cxx b/sw/source/core/txtnode/thints.cxx
new file mode 100644
index 000000000000..3ca7d01e1981
--- /dev/null
+++ b/sw/source/core/txtnode/thints.cxx
@@ -0,0 +1,3063 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+
+#include <hintids.hxx>
+#include <sot/factory.hxx>
+#include <editeng/xmlcnitm.hxx>
+#include <svl/whiter.hxx>
+#include <svl/itemiter.hxx>
+#include <svl/stylepool.hxx>
+#include <editeng/fontitem.hxx>
+#include <editeng/langitem.hxx>
+#include <editeng/emphitem.hxx>
+#include <editeng/charscaleitem.hxx>
+#include <editeng/charrotateitem.hxx>
+#include <editeng/lrspitem.hxx>
+#include <txtinet.hxx>
+#include <txtflcnt.hxx>
+#include <fmtfld.hxx>
+#include <fmtanchr.hxx>
+#include <fmtinfmt.hxx>
+#include <txtatr.hxx>
+#include <fchrfmt.hxx>
+#include <fmtautofmt.hxx>
+#include <fmtflcnt.hxx>
+#include <fmtftn.hxx>
+#include <txttxmrk.hxx>
+#include <txtrfmrk.hxx>
+#include <txtftn.hxx>
+#include <txtfld.hxx>
+#include <charatr.hxx>
+#include <charfmt.hxx>
+#include <frmfmt.hxx>
+#include <ftnidx.hxx>
+#include <fmtruby.hxx>
+#include <fmtmeta.hxx>
+#include <breakit.hxx>
+#include <doc.hxx>
+#include <IDocumentUndoRedo.hxx>
+#include <fldbas.hxx>
+#include <pam.hxx>
+#include <ndtxt.hxx>
+#include <txtfrm.hxx>
+#include <rolbck.hxx> // fuer SwRegHistory
+#include <ddefld.hxx>
+#include <docufld.hxx>
+#include <expfld.hxx>
+#include <usrfld.hxx>
+#include <poolfmt.hxx>
+#include <swfont.hxx>
+#include <istyleaccess.hxx>
+// OD 26.06.2003 #108784#
+#include <dcontact.hxx>
+#include <docsh.hxx>
+#include <svl/smplhint.hxx>
+#include <algorithm>
+#include <map>
+
+#if OSL_DEBUG_LEVEL > 1
+#define CHECK Check();
+#else
+#define CHECK
+#endif
+
+using namespace ::com::sun::star::i18n;
+
+
+SwpHints::SwpHints()
+ : m_pHistory(0)
+ , m_bFontChange(true)
+ , m_bInSplitNode(false)
+ , m_bCalcHiddenParaField(false)
+ , m_bHasHiddenParaField(false)
+ , m_bFootnote(false)
+ , m_bDDEFields(false)
+{
+}
+
+struct TxtAttrDeleter
+{
+ SwAttrPool & m_rPool;
+ TxtAttrDeleter( SwDoc & rDoc ) : m_rPool( rDoc.GetAttrPool() ) { }
+ void operator() (SwTxtAttr * const pAttr)
+ {
+ if (RES_TXTATR_META == pAttr->Which() ||
+ RES_TXTATR_METAFIELD == pAttr->Which())
+ {
+ static_cast<SwTxtMeta *>(pAttr)->ChgTxtNode(0); // prevents ASSERT
+ }
+ SwTxtAttr::Destroy( pAttr, m_rPool );
+ }
+};
+
+struct TxtAttrContains
+{
+ xub_StrLen m_nPos;
+ TxtAttrContains( const xub_StrLen nPos ) : m_nPos( nPos ) { }
+ bool operator() (SwTxtAttrEnd * const pAttr)
+ {
+ return (*pAttr->GetStart() < m_nPos) && (m_nPos < *pAttr->GetEnd());
+ }
+};
+
+// a: |-----|
+// b:
+// |---| => valid: b before a
+// |-----| => valid: start == end; b before a
+// |---------| => invalid: overlap (1)
+// |-----------| => valid: same end; b around a
+// |-----------------| => valid: b around a
+// |---| => valid; same start; b within a
+// |-----| => valid; same start and end; b around or within a?
+// |-----------| => valid: same start: b around a
+// |-| => valid: b within a
+// |---| => valid: same end; b within a
+// |---------| => invalid: overlap (2)
+// |-----| => valid: end == start; b after a
+// |---| => valid: b after a
+// ===> 2 invalid overlap cases
+static
+bool isOverlap(const xub_StrLen nStart1, const xub_StrLen nEnd1,
+ const xub_StrLen nStart2, const xub_StrLen nEnd2)
+{
+ return
+ ((nStart1 > nStart2) && (nStart1 < nEnd2) && (nEnd1 > nEnd2)) // (1)
+ || ((nStart1 < nStart2) && (nStart2 < nEnd1) && (nEnd1 < nEnd2)); // (2)
+}
+
+/// #i106930#: now asymmetric: empty hint1 is _not_ nested, but empty hint2 is
+static
+bool isNestedAny(const xub_StrLen nStart1, const xub_StrLen nEnd1,
+ const xub_StrLen nStart2, const xub_StrLen nEnd2)
+{
+ return ((nStart1 == nStart2) || (nEnd1 == nEnd2))
+ // same start/end: nested except if hint1 empty and hint2 not empty
+ ? (nStart1 != nEnd1) || (nStart2 == nEnd2)
+ : ((nStart1 < nStart2) ? (nEnd1 >= nEnd2) : (nEnd1 <= nEnd2));
+}
+
+static
+bool isSelfNestable(const sal_uInt16 nWhich)
+{
+ if ((RES_TXTATR_INETFMT == nWhich) ||
+ (RES_TXTATR_CJK_RUBY == nWhich))
+ return false;
+ OSL_ENSURE((RES_TXTATR_META == nWhich) ||
+ (RES_TXTATR_METAFIELD == nWhich), "???");
+ return true;
+}
+
+static
+bool isSplittable(const sal_uInt16 nWhich)
+{
+ if ((RES_TXTATR_INETFMT == nWhich) ||
+ (RES_TXTATR_CJK_RUBY == nWhich))
+ return true;
+ OSL_ENSURE((RES_TXTATR_META == nWhich) ||
+ (RES_TXTATR_METAFIELD == nWhich), "???");
+ return false;
+}
+
+enum Split_t { FAIL, SPLIT_NEW, SPLIT_OTHER };
+/**
+ Calculate splitting policy for overlapping hints, based on what kind of
+ hint is inserted, and what kind of existing hint overlaps.
+ */
+static Split_t
+splitPolicy(const sal_uInt16 nWhichNew, const sal_uInt16 nWhichOther)
+{
+ if (!isSplittable(nWhichOther))
+ {
+ if (!isSplittable(nWhichNew))
+ return FAIL;
+ else
+ return SPLIT_NEW;
+ }
+ else
+ {
+ if ((RES_TXTATR_INETFMT == nWhichNew) &&
+ (RES_TXTATR_CJK_RUBY == nWhichOther))
+ return SPLIT_NEW;
+ else
+ return SPLIT_OTHER;
+ }
+}
+
+void SwTxtINetFmt::InitINetFmt(SwTxtNode & rNode)
+{
+ ChgTxtNode(&rNode);
+ SwCharFmt * const pFmt(
+ rNode.GetDoc()->GetCharFmtFromPool(RES_POOLCHR_INET_NORMAL) );
+ pFmt->Add( this );
+}
+
+void SwTxtRuby::InitRuby(SwTxtNode & rNode)
+{
+ ChgTxtNode(&rNode);
+ SwCharFmt * const pFmt(
+ rNode.GetDoc()->GetCharFmtFromPool(RES_POOLCHR_RUBYTEXT) );
+ pFmt->Add( this );
+}
+
+/**
+ Create a new nesting text hint.
+ */
+static SwTxtAttrNesting *
+MakeTxtAttrNesting(SwTxtNode & rNode, SwTxtAttrNesting & rNesting,
+ const xub_StrLen nStart, const xub_StrLen nEnd)
+{
+ SwTxtAttr * const pNew( MakeTxtAttr(
+ *rNode.GetDoc(), rNesting.GetAttr(), nStart, nEnd ) );
+ switch (pNew->Which())
+ {
+ case RES_TXTATR_INETFMT:
+ {
+ static_cast<SwTxtINetFmt*>(pNew)->InitINetFmt(rNode);
+ break;
+ }
+ case RES_TXTATR_CJK_RUBY:
+ {
+ static_cast<SwTxtRuby*>(pNew)->InitRuby(rNode);
+ break;
+ }
+ default:
+ OSL_FAIL("MakeTxtAttrNesting: what the hell is that?");
+ break;
+ }
+ return static_cast<SwTxtAttrNesting*>(pNew);
+}
+
+typedef ::std::vector<SwTxtAttrNesting *> NestList_t;
+
+static void
+lcl_DoSplitNew(NestList_t & rSplits, SwTxtNode & rNode,
+ const xub_StrLen nNewStart,
+ const xub_StrLen nOtherStart, const xub_StrLen nOtherEnd, bool bOtherDummy)
+{
+ const bool bSplitAtStart(nNewStart < nOtherStart);
+ const xub_StrLen nSplitPos( (bSplitAtStart) ? nOtherStart : nOtherEnd );
+ // first find the portion that is split (not necessarily the last one!)
+ NestList_t::iterator const iter(
+ ::std::find_if( rSplits.begin(), rSplits.end(),
+ TxtAttrContains(nSplitPos) ) );
+ if (iter != rSplits.end()) // already split here?
+ {
+ const xub_StrLen nStartPos( // skip other's dummy character!
+ (bSplitAtStart && bOtherDummy) ? nSplitPos + 1 : nSplitPos );
+ SwTxtAttrNesting * const pNew( MakeTxtAttrNesting(
+ rNode, **iter, nStartPos, *(*iter)->GetEnd() ) );
+ *(*iter)->GetEnd() = nSplitPos;
+ rSplits.insert(iter + 1, pNew);
+ }
+}
+
+/**
+ Insert nesting hint into the hints array. Also calls NoteInHistory.
+ @param rNewHint the hint to be inserted (must not overlap existing!)
+ */
+void SwpHints::InsertNesting(SwTxtAttrNesting & rNewHint)
+{
+ SwpHintsArray::Insert(& rNewHint);
+ NoteInHistory( & rNewHint, true );
+}
+
+/**
+
+The following hints correspond to well-formed XML elements in ODF:
+RES_TXTATR_INETFMT, RES_TXTATR_CJK_RUBY, RES_TXTATR_META, RES_TXTATR_METAFIELD
+
+The writer core must ensure that these do not overlap; if they did,
+the document would not be storable as ODF.
+
+Also, a Hyperlink must not be nested within another Hyperlink,
+and a Ruby must not be nested within another Ruby.
+
+The ODF export in xmloff will only put a hyperlink into a ruby, never a ruby
+into a hyperlink.
+
+Unfortunately the UNO API for Hyperlink and Ruby consists of the properties
+Hyperlink* and Ruby* of the css.text.CharacterProperties service. In other
+words, they are treated as formatting attributes, not as content entites.
+Furthermore, for API users it is not possible to easily test whether a certain
+range would be overlapping with other nested attributes, and most importantly,
+<em>which ones</em>, so we can hardly refuse to insert these in cases of
+overlap.
+
+It is possible to split Hyperlink and Ruby into multiple portions, such that
+the result is properly nested.
+
+meta and meta-field must not be split, because they have xml:id.
+
+These constraints result in the following design:
+
+RES_TXTATR_INETFMT:
+ always succeeds
+ inserts n attributes split at RES_TXTATR_CJK_RUBY, RES_TXTATR_META,
+ RES_TXTATR_METAFIELD
+ may replace existing RES_TXTATR_INETFMT at overlap
+RES_TXTATR_CJK_RUBY:
+ always succeeds
+ inserts n attributes split at RES_TXTATR_META, RES_TXTATR_METAFIELD
+ may replace existing RES_TXTATR_CJK_RUBY at overlap
+ may split existing overlapping RES_TXTATR_INETFMT
+RES_TXTATR_META:
+ may fail if overlapping existing RES_TXTATR_META/RES_TXTATR_METAFIELD
+ may split existing overlapping RES_TXTATR_INETFMT or RES_TXTATR_CJK_RUBY
+ inserts 1 attribute
+RES_TXTATR_METAFIELD:
+ may fail if overlapping existing RES_TXTATR_META/RES_TXTATR_METAFIELD
+ may split existing overlapping RES_TXTATR_INETFMT or RES_TXTATR_CJK_RUBY
+ inserts 1 attribute
+
+The nesting is expressed by the position of the hints.
+RES_TXTATR_META and RES_TXTATR_METAFIELD have a CH_TXTATR, and there can
+only be one such hint starting and ending at a given position.
+Only RES_TXTATR_INETFMT and RES_TXTATR_CJK_RUBY lack a CH_TXTATR.
+The interpretation given is that RES_TXTATR_CJK_RUBY is always around
+a RES_TXTATR_INETFMT at the same start and end position (which corresponds
+with the UNO API).
+Both of these are always around a nesting hint with CH_TXTATR at the same
+start and end position (if they should be inside, then the start should be
+after the CH_TXTATR).
+It would probably be a bad idea to add another nesting hint without
+CH_TXTATR; on the other hand, it would be difficult adding a CH_TXTATR to
+RES_TXTATR_INETFMT and RES_TXTATR_CJK_RUBY, due to the overwriting and
+splitting of exising hints that is necessary for backward compatibility.
+
+ @param rNode the text node
+ @param rHint the hint to be inserted
+ @returns true iff hint was successfully inserted
+*/
+bool
+SwpHints::TryInsertNesting( SwTxtNode & rNode, SwTxtAttrNesting & rNewHint )
+{
+// INVARIANT: the nestable hints in the array are properly nested
+ const sal_uInt16 nNewWhich( rNewHint.Which() );
+ const xub_StrLen nNewStart( *rNewHint.GetStart() );
+ const xub_StrLen nNewEnd ( *rNewHint.GetEnd() );
+//??? const bool bNoLengthAttribute( nNewStart == nNewEnd );
+ const bool bNewSelfNestable( isSelfNestable(nNewWhich) );
+
+ OSL_ENSURE( (RES_TXTATR_INETFMT == nNewWhich) ||
+ (RES_TXTATR_CJK_RUBY == nNewWhich) ||
+ (RES_TXTATR_META == nNewWhich) ||
+ (RES_TXTATR_METAFIELD == nNewWhich),
+ "TryInsertNesting: Expecting INETFMT or RUBY or META or METAFIELD" );
+
+ NestList_t OverlappingExisting; // existing hints to be split
+ NestList_t OverwrittenExisting; // existing hints to be replaced
+ NestList_t SplitNew; // new hints to be inserted
+
+ SplitNew.push_back(& rNewHint);
+
+ // pass 1: split the inserted hint into fragments if necessary
+ for ( sal_uInt16 i = 0; i < GetEndCount(); ++i )
+ {
+ SwTxtAttr * const pOther = GetEnd(i);
+
+ if (pOther->IsNesting())
+ {
+ const sal_uInt16 nOtherWhich( pOther->Which() );
+ const xub_StrLen nOtherStart( *(pOther)->GetStart() );
+ const xub_StrLen nOtherEnd ( *(pOther)->GetEnd() );
+ if (isOverlap(nNewStart, nNewEnd, nOtherStart, nOtherEnd ))
+ {
+ switch (splitPolicy(nNewWhich, nOtherWhich))
+ {
+ case FAIL:
+ OSL_TRACE("cannot insert hint: overlap detected");
+ ::std::for_each(SplitNew.begin(), SplitNew.end(),
+ TxtAttrDeleter(*rNode.GetDoc()));
+ return false;
+ case SPLIT_NEW:
+ lcl_DoSplitNew(SplitNew, rNode, nNewStart,
+ nOtherStart, nOtherEnd, pOther->HasDummyChar());
+ break;
+ case SPLIT_OTHER:
+ OverlappingExisting.push_back(
+ static_cast<SwTxtAttrNesting*>(pOther));
+ break;
+ default:
+ OSL_FAIL("bad code monkey");
+ break;
+ }
+ }
+ else if (isNestedAny(nNewStart, nNewEnd, nOtherStart, nOtherEnd))
+ {
+ if (!bNewSelfNestable && (nNewWhich == nOtherWhich))
+ {
+ // ruby and hyperlink: if there is nesting, _overwrite_
+ OverwrittenExisting.push_back(
+ static_cast<SwTxtAttrNesting*>(pOther));
+ }
+ else if ((nNewStart == nOtherStart) && pOther->HasDummyChar())
+ {
+ if (rNewHint.HasDummyChar())
+ {
+ OSL_FAIL("ERROR: inserting duplicate CH_TXTATR hint");
+ return false;
+ } else if (nNewEnd < nOtherEnd) {
+ // other has dummy char, new is inside other, but
+ // new contains the other's dummy char?
+ // should be corrected because it may lead to problems
+ // in SwXMeta::createEnumeration
+ // SplitNew is sorted, so this is the first split
+ xub_StrLen *const pStart(SplitNew.front()->GetStart());
+ OSL_ENSURE(*pStart == nNewStart, "how did that happen?");
+ *pStart = nNewStart + 1;
+ }
+ }
+ }
+ }
+ }
+
+ OSL_ENSURE(isSplittable(nNewWhich) || SplitNew.size() == 1,
+ "splitting the unsplittable ???");
+
+ // pass 2: split existing hints that overlap/nest with new hint
+ // do not iterate over hints array, but over remembered set of overlapping
+ // hints, to keep things simple w.r.t. insertion/removal
+ // N.B: if there is a hint that splits the inserted hint, then
+ // that hint would also have already split any hint in OverlappingExisting
+ // so any hint in OverlappingExisting can be split at most by one hint
+ // in SplitNew, or even not at all (this is not true for existing hints
+ // that go _around_ new hint, which is the raison d'^etre for pass 4)
+ for (NestList_t::iterator itOther = OverlappingExisting.begin();
+ itOther != OverlappingExisting.end(); ++itOther)
+ {
+ const xub_StrLen nOtherStart( *(*itOther)->GetStart() );
+ const xub_StrLen nOtherEnd ( *(*itOther)->GetEnd() );
+
+ for (NestList_t::iterator itNew = SplitNew.begin();
+ itNew != SplitNew.end(); ++itNew)
+ {
+ const xub_StrLen nSplitNewStart( *(*itNew)->GetStart() );
+ const xub_StrLen nSplitNewEnd ( *(*itNew)->GetEnd() );
+ // 4 cases: within, around, overlap l, overlap r, (OTHER: no action)
+ const bool bRemoveOverlap(
+ !bNewSelfNestable && (nNewWhich == (*itOther)->Which()) );
+
+ switch (ComparePosition(nSplitNewStart, nSplitNewEnd,
+ nOtherStart, nOtherEnd))
+ {
+ case POS_INSIDE:
+ {
+ OSL_ENSURE(!bRemoveOverlap,
+ "this one should be in OverwrittenExisting?");
+ }
+ break;
+ case POS_OUTSIDE:
+ case POS_EQUAL:
+ {
+ OSL_FAIL("existing hint inside new hint: why?");
+ }
+ break;
+ case POS_OVERLAP_BEFORE:
+ {
+ Delete( *itOther ); // this also does NoteInHistory!
+ *(*itOther)->GetStart() = nSplitNewEnd;
+ InsertNesting( **itOther );
+ if (!bRemoveOverlap)
+ {
+ if ( USHRT_MAX == Count() )
+ {
+ OSL_FAIL("hints array full :-(");
+ return false;
+ }
+ SwTxtAttrNesting * const pOtherLeft(
+ MakeTxtAttrNesting( rNode, **itOther,
+ nOtherStart, nSplitNewEnd ) );
+ InsertNesting( *pOtherLeft );
+ }
+ }
+ break;
+ case POS_OVERLAP_BEHIND:
+ {
+ Delete( *itOther ); // this also does NoteInHistory!
+ *(*itOther)->GetEnd() = nSplitNewStart;
+ InsertNesting( **itOther );
+ if (!bRemoveOverlap)
+ {
+ if ( USHRT_MAX == Count() )
+ {
+ OSL_FAIL("hints array full :-(");
+ return false;
+ }
+ SwTxtAttrNesting * const pOtherRight(
+ MakeTxtAttrNesting( rNode, **itOther,
+ nSplitNewStart, nOtherEnd ) );
+ InsertNesting( *pOtherRight );
+ }
+ }
+ break;
+ default:
+ break; // overlap resolved by splitting new: nothing to do
+ }
+ }
+ }
+
+ if ( USHRT_MAX - SplitNew.size() <= Count() )
+ {
+ OSL_FAIL("hints array full :-(");
+ return false;
+ }
+
+ // pass 3: insert new hints
+ for (NestList_t::iterator iter = SplitNew.begin();
+ iter != SplitNew.end(); ++iter)
+ {
+ InsertNesting(**iter);
+ }
+
+ // pass 4: handle overwritten hints
+ // RES_TXTATR_INETFMT and RES_TXTATR_CJK_RUBY should displace attributes
+ // of the same kind.
+ for (NestList_t::iterator itOther = OverwrittenExisting.begin();
+ itOther != OverwrittenExisting.end(); ++itOther)
+ {
+ const xub_StrLen nOtherStart( *(*itOther)->GetStart() );
+ const xub_StrLen nOtherEnd ( *(*itOther)->GetEnd() );
+
+ // overwritten portion is given by start/end of inserted hint
+ if ((nNewStart <= nOtherStart) && (nOtherEnd <= nNewEnd))
+ {
+ Delete(*itOther);
+ rNode.DestroyAttr( *itOther );
+ }
+ else
+ {
+ OSL_ENSURE((nOtherStart < nNewStart) && (nNewEnd < nOtherEnd), "huh?");
+ // scenario: there is a RUBY, and contained within that a META;
+ // now a RUBY is inserted within the META => the exising RUBY is split:
+ // here it is not possible to simply insert the left/right fragment
+ // of the existing RUBY because they <em>overlap</em> with the META!
+ Delete( *itOther ); // this also does NoteInHistory!
+ *(*itOther)->GetEnd() = nNewStart;
+ bool bSuccess( TryInsertNesting(rNode, **itOther) );
+ OSL_ENSURE(bSuccess, "recursive call 1 failed?");
+ SwTxtAttrNesting * const pOtherRight(
+ MakeTxtAttrNesting(
+ rNode, **itOther, nNewEnd, nOtherEnd ) );
+ bSuccess = TryInsertNesting(rNode, *pOtherRight);
+ OSL_ENSURE(bSuccess, "recursive call 2 failed?");
+ (void)bSuccess;
+ }
+
+ }
+
+ return true;
+}
+
+
+// This function takes care for the following text attribute:
+// RES_TXTATR_CHARFMT, RES_TXTATR_AUTOFMT
+// These attributes have to be handled in a special way (Portion building).
+//
+// The new attribute will be split by any existing RES_TXTATR_AUTOFMT or
+// RES_TXTATR_CHARFMT. The new attribute itself will
+// split any existing RES_TXTATR_AUTOFMT or RES_TXTATR_CHARFMT.
+
+void SwpHints::BuildPortions( SwTxtNode& rNode, SwTxtAttr& rNewHint,
+ const SetAttrMode nMode )
+{
+ const sal_uInt16 nWhich = rNewHint.Which();
+
+ const xub_StrLen nThisStart = *rNewHint.GetStart();
+ const xub_StrLen nThisEnd = *rNewHint.GetEnd();
+ const bool bNoLengthAttribute = nThisStart == nThisEnd;
+
+ std::vector<SwTxtAttr*> aInsDelHints;
+ std::vector<SwTxtAttr*>::iterator aIter;
+
+ OSL_ENSURE( RES_TXTATR_CHARFMT == rNewHint.Which() ||
+ RES_TXTATR_AUTOFMT == rNewHint.Which(),
+ "Expecting CHARFMT or AUTOFMT" );
+
+ //
+ // 2. Find the hints which cover the start and end position
+ // of the new hint. These hints have to be split into two portions:
+ //
+ if ( !bNoLengthAttribute ) // nothing to do for no length attributes
+ {
+ for ( sal_uInt16 i = 0; i < Count(); ++i )
+ {
+ SwTxtAttr* pOther = GetTextHint(i);
+
+ if ( RES_TXTATR_CHARFMT != pOther->Which() &&
+ RES_TXTATR_AUTOFMT != pOther->Which() )
+ continue;
+
+ xub_StrLen nOtherStart = *pOther->GetStart();
+ const xub_StrLen nOtherEnd = *pOther->GetEnd();
+
+ // Check if start of new attribute overlaps with pOther:
+ // Split pOther if necessary:
+ if ( nOtherStart < nThisStart && nThisStart < nOtherEnd )
+ {
+ SwTxtAttr* pNewAttr = MakeTxtAttr( *rNode.GetDoc(),
+ pOther->GetAttr(), nOtherStart, nThisStart );
+ if ( RES_TXTATR_CHARFMT == pOther->Which() )
+ static_cast<SwTxtCharFmt*>(pNewAttr)->SetSortNumber( static_cast<SwTxtCharFmt*>(pOther)->GetSortNumber() );
+ aInsDelHints.push_back( pNewAttr );
+
+ NoteInHistory( pOther );
+ *pOther->GetStart() = nThisStart;
+ NoteInHistory( pOther, true );
+
+ nOtherStart = nThisStart;
+ }
+
+ // Check if end of new attribute overlaps with pOther:
+ // Split pOther if necessary:
+ if ( nOtherStart < nThisEnd && nThisEnd < nOtherEnd )
+ {
+ SwTxtAttr* pNewAttr = MakeTxtAttr( *rNode.GetDoc(),
+ pOther->GetAttr(), nOtherStart, nThisEnd );
+ if ( RES_TXTATR_CHARFMT == pOther->Which() )
+ static_cast<SwTxtCharFmt*>(pNewAttr)->SetSortNumber( static_cast<SwTxtCharFmt*>(pOther)->GetSortNumber() );
+ aInsDelHints.push_back( pNewAttr );
+
+ NoteInHistory( pOther );
+ *pOther->GetStart() = nThisEnd;
+ NoteInHistory( pOther, true );
+ }
+ }
+
+ // Insert the newly created attributes:
+ for ( aIter = aInsDelHints.begin(); aIter != aInsDelHints.end(); ++aIter )
+ {
+ SwpHintsArray::Insert( *aIter );
+ NoteInHistory( *aIter, true );
+ }
+ }
+
+#if OSL_DEBUG_LEVEL > 1
+ if( !rNode.GetDoc()->IsInReading() )
+ CHECK;
+#endif
+
+ //
+ // 4. Split rNewHint into 1 ... n new hints:
+ //
+ std::set<xub_StrLen> aBounds;
+ aBounds.insert( nThisStart );
+ aBounds.insert( nThisEnd );
+
+ if ( !bNoLengthAttribute ) // nothing to do for no length attributes
+ {
+ for ( sal_uInt16 i = 0; i < Count(); ++i )
+ {
+ const SwTxtAttr* pOther = GetTextHint(i);
+
+ if ( RES_TXTATR_CHARFMT != pOther->Which() &&
+ RES_TXTATR_AUTOFMT != pOther->Which() )
+ continue;
+
+ const xub_StrLen nOtherStart = *pOther->GetStart();
+ const xub_StrLen nOtherEnd = *pOther->GetEnd();
+
+ aBounds.insert( nOtherStart );
+ aBounds.insert( nOtherEnd );
+ }
+ }
+
+ std::set<xub_StrLen>::iterator aStartIter = aBounds.lower_bound( nThisStart );
+ std::set<xub_StrLen>::iterator aEndIter = aBounds.upper_bound( nThisEnd );
+ xub_StrLen nPorStart = *aStartIter;
+ ++aStartIter;
+ bool bDestroyHint = true;
+
+ //
+ // Insert the 1...n new parts of the new attribute:
+ //
+ while ( aStartIter != aEndIter || bNoLengthAttribute )
+ {
+ OSL_ENSURE( bNoLengthAttribute || nPorStart < *aStartIter, "AUTOSTYLES: BuildPortion trouble" );
+
+ const xub_StrLen nPorEnd = bNoLengthAttribute ? nPorStart : *aStartIter;
+ aInsDelHints.clear();
+
+ // Get all hints that are in [nPorStart, nPorEnd[:
+ for ( sal_uInt16 i = 0; i < Count(); ++i )
+ {
+ SwTxtAttr *pOther = GetTextHint(i);
+
+ if ( RES_TXTATR_CHARFMT != pOther->Which() &&
+ RES_TXTATR_AUTOFMT != pOther->Which() )
+ continue;
+
+ const xub_StrLen nOtherStart = *pOther->GetStart();
+
+ if ( nOtherStart > nPorStart )
+ break;
+
+ if ( pOther->GetEnd() && *pOther->GetEnd() == nPorEnd && nOtherStart == nPorStart )
+ {
+ OSL_ENSURE( *pOther->GetEnd() == nPorEnd, "AUTOSTYLES: BuildPortion trouble" );
+ aInsDelHints.push_back( pOther );
+ }
+ }
+
+ SwTxtAttr* pNewAttr = 0;
+ if ( RES_TXTATR_CHARFMT == nWhich )
+ {
+ // pNewHint can be inserted after calculating the sort value.
+ // This should ensure, that pNewHint comes behind the already present
+ // character style
+ sal_uInt16 nCharStyleCount = 0;
+ aIter = aInsDelHints.begin();
+ while ( aIter != aInsDelHints.end() )
+ {
+ if ( RES_TXTATR_CHARFMT == (*aIter)->Which() )
+ {
+ // --> FME 2007-02-16 #i74589#
+ const SwFmtCharFmt& rOtherCharFmt = (*aIter)->GetCharFmt();
+ const SwFmtCharFmt& rThisCharFmt = rNewHint.GetCharFmt();
+ const bool bSameCharFmt = rOtherCharFmt.GetCharFmt() == rThisCharFmt.GetCharFmt();
+ // <--
+
+ // --> OD 2009-03-24 #i90311#
+ // Do not remove existing character format hint during XML import
+ if ( !rNode.GetDoc()->IsInXMLImport() &&
+ ( !( nsSetAttrMode::SETATTR_DONTREPLACE & nMode ) ||
+ bNoLengthAttribute ||
+ bSameCharFmt ) )
+ // <--
+ {
+ // Remove old hint
+ Delete( *aIter );
+ rNode.DestroyAttr( *aIter );
+ }
+ else
+ ++nCharStyleCount;
+ }
+ else
+ {
+ // remove all attributes from auto styles, which are explicitely set in
+ // the new character format:
+ OSL_ENSURE( RES_TXTATR_AUTOFMT == (*aIter)->Which(), "AUTOSTYLES - Misc trouble" );
+ SwTxtAttr* pOther = *aIter;
+ boost::shared_ptr<SfxItemSet> pOldStyle = static_cast<const SwFmtAutoFmt&>(pOther->GetAttr()).GetStyleHandle();
+
+ // For each attribute in the automatic style check if it
+ // is also set the the new character style:
+ SfxItemSet aNewSet( *pOldStyle->GetPool(),
+ aCharAutoFmtSetRange);
+ SfxItemIter aItemIter( *pOldStyle );
+ const SfxPoolItem* pItem = aItemIter.GetCurItem();
+ while( sal_True )
+ {
+ if ( !CharFmt::IsItemIncluded( pItem->Which(), &rNewHint ) )
+ {
+ aNewSet.Put( *pItem );
+ }
+
+ if( aItemIter.IsAtEnd() )
+ break;
+
+ pItem = aItemIter.NextItem();
+ }
+
+ // Remove old hint
+ Delete( pOther );
+ rNode.DestroyAttr( pOther );
+
+ // Create new AutoStyle
+ if ( aNewSet.Count() )
+ {
+ pNewAttr = MakeTxtAttr( *rNode.GetDoc(),
+ aNewSet, nPorStart, nPorEnd );
+ SwpHintsArray::Insert( pNewAttr );
+ NoteInHistory( pNewAttr, true );
+ }
+ }
+ ++aIter;
+ }
+
+ // If there is no current hint and start and end of rNewHint
+ // is ok, we do not need to create a new txtattr.
+ if ( nPorStart == nThisStart &&
+ nPorEnd == nThisEnd &&
+ !nCharStyleCount )
+ {
+ pNewAttr = &rNewHint;
+ bDestroyHint = false;
+ }
+ else
+ {
+ pNewAttr = MakeTxtAttr( *rNode.GetDoc(), rNewHint.GetAttr(),
+ nPorStart, nPorEnd );
+ static_cast<SwTxtCharFmt*>(pNewAttr)->SetSortNumber( nCharStyleCount );
+ }
+ }
+ else
+ {
+ // Find the current autostyle. Mix attributes if necessary.
+ SwTxtAttr* pCurrentAutoStyle = 0;
+ SwTxtAttr* pCurrentCharFmt = 0;
+ aIter = aInsDelHints.begin();
+ while ( aIter != aInsDelHints.end() )
+ {
+ if ( RES_TXTATR_AUTOFMT == (*aIter)->Which() )
+ pCurrentAutoStyle = *aIter;
+ else if ( RES_TXTATR_CHARFMT == (*aIter)->Which() )
+ pCurrentCharFmt = *aIter;
+ ++aIter;
+ }
+
+ boost::shared_ptr<SfxItemSet> pNewStyle = static_cast<const SwFmtAutoFmt&>(rNewHint.GetAttr()).GetStyleHandle();
+ if ( pCurrentAutoStyle )
+ {
+ boost::shared_ptr<SfxItemSet> pCurrentStyle = static_cast<const SwFmtAutoFmt&>(pCurrentAutoStyle->GetAttr()).GetStyleHandle();
+
+ // Merge attributes
+ SfxItemSet aNewSet( *pCurrentStyle );
+ aNewSet.Put( *pNewStyle );
+
+ // --> FME 2007-4-11 #i75750# Remove attributes already set at whole paragraph
+ // --> FME 2007-09-24 #i81764# This should not be applied for no length attributes!!! <--
+ if ( !bNoLengthAttribute && rNode.HasSwAttrSet() && aNewSet.Count() )
+ {
+ SfxItemIter aIter2( aNewSet );
+ const SfxPoolItem* pItem = aIter2.GetCurItem();
+ const SfxItemSet& rWholeParaAttrSet = rNode.GetSwAttrSet();
+
+ do
+ {
+ const SfxPoolItem* pTmpItem = 0;
+ if ( SFX_ITEM_SET == rWholeParaAttrSet.GetItemState( pItem->Which(), sal_False, &pTmpItem ) &&
+ pTmpItem == pItem )
+ {
+ // Do not clear item if the attribute is set in a character format:
+ if ( !pCurrentCharFmt || 0 == CharFmt::GetItem( *pCurrentCharFmt, pItem->Which() ) )
+ aNewSet.ClearItem( pItem->Which() );
+ }
+ }
+ while (!aIter2.IsAtEnd() && 0 != (pItem = aIter2.NextItem()));
+ }
+ // <--
+
+ // Remove old hint
+ Delete( pCurrentAutoStyle );
+ rNode.DestroyAttr( pCurrentAutoStyle );
+
+ // Create new AutoStyle
+ if ( aNewSet.Count() )
+ pNewAttr = MakeTxtAttr( *rNode.GetDoc(), aNewSet,
+ nPorStart, nPorEnd );
+ }
+ else
+ {
+ // Remove any attributes which are already set at the whole paragraph:
+ bool bOptimizeAllowed = true;
+
+ SfxItemSet* pNewSet = 0;
+ // --> FME 2007-4-11 #i75750# Remove attributes already set at whole paragraph
+ // --> FME 2007-09-24 #i81764# This should not be applied for no length attributes!!! <--
+ if ( !bNoLengthAttribute && rNode.HasSwAttrSet() && pNewStyle->Count() )
+ {
+ SfxItemIter aIter2( *pNewStyle );
+ const SfxPoolItem* pItem = aIter2.GetCurItem();
+ const SfxItemSet& rWholeParaAttrSet = rNode.GetSwAttrSet();
+
+ do
+ {
+ const SfxPoolItem* pTmpItem = 0;
+ if ( SFX_ITEM_SET == rWholeParaAttrSet.GetItemState( pItem->Which(), sal_False, &pTmpItem ) &&
+ pTmpItem == pItem )
+ {
+ // Do not clear item if the attribute is set in a character format:
+ if ( !pCurrentCharFmt || 0 == CharFmt::GetItem( *pCurrentCharFmt, pItem->Which() ) )
+ {
+ if ( !pNewSet )
+ pNewSet = pNewStyle->Clone( sal_True );
+ pNewSet->ClearItem( pItem->Which() );
+ }
+ }
+ }
+ while (!aIter2.IsAtEnd() && 0 != (pItem = aIter2.NextItem()));
+
+ if ( pNewSet )
+ {
+ bOptimizeAllowed = false;
+ if ( pNewSet->Count() )
+ pNewStyle = rNode.getIDocumentStyleAccess().getAutomaticStyle( *pNewSet, IStyleAccess::AUTO_STYLE_CHAR );
+ else
+ pNewStyle.reset();
+
+ delete pNewSet;
+ }
+ }
+ // <--
+
+ // Create new AutoStyle
+ // If there is no current hint and start and end of rNewHint
+ // is ok, we do not need to create a new txtattr.
+ if ( bOptimizeAllowed &&
+ nPorStart == nThisStart &&
+ nPorEnd == nThisEnd )
+ {
+ pNewAttr = &rNewHint;
+ bDestroyHint = false;
+ }
+ else if ( pNewStyle.get() )
+ {
+ pNewAttr = MakeTxtAttr( *rNode.GetDoc(), *pNewStyle,
+ nPorStart, nPorEnd );
+ }
+ }
+ }
+
+ if ( pNewAttr )
+ {
+ SwpHintsArray::Insert( pNewAttr );
+// if ( bDestroyHint )
+ NoteInHistory( pNewAttr, true );
+ }
+
+ if ( !bNoLengthAttribute )
+ {
+ nPorStart = *aStartIter;
+ ++aStartIter;
+ }
+ else
+ break;
+ }
+
+ if ( bDestroyHint )
+ rNode.DestroyAttr( &rNewHint );
+}
+
+/*************************************************************************
+ * SwTxtNode::MakeTxtAttr()
+ *************************************************************************/
+
+SwTxtAttr* MakeRedlineTxtAttr( SwDoc & rDoc, SfxPoolItem & rAttr )
+{
+ // this is intended _only_ for special-purpose redline attributes!
+ switch (rAttr.Which())
+ {
+ case RES_CHRATR_COLOR:
+ case RES_CHRATR_WEIGHT:
+ case RES_CHRATR_CJK_WEIGHT:
+ case RES_CHRATR_CTL_WEIGHT:
+ case RES_CHRATR_POSTURE:
+ case RES_CHRATR_CJK_POSTURE:
+ case RES_CHRATR_CTL_POSTURE:
+ case RES_CHRATR_UNDERLINE:
+ case RES_CHRATR_CROSSEDOUT:
+ case RES_CHRATR_CASEMAP:
+ case RES_CHRATR_BACKGROUND:
+ break;
+ default:
+ OSL_FAIL("unsupported redline attribute");
+ break;
+ }
+
+ // Put new attribute into pool
+ // FIXME: this const_cast is evil!
+ SfxPoolItem& rNew =
+ const_cast<SfxPoolItem&>( rDoc.GetAttrPool().Put( rAttr ) );
+ return new SwTxtAttrEnd( rNew, 0, 0 );
+}
+
+// create new text attribute
+SwTxtAttr* MakeTxtAttr( SwDoc & rDoc, SfxPoolItem& rAttr,
+ xub_StrLen const nStt, xub_StrLen const nEnd,
+ CopyOrNew_t const bIsCopy, SwTxtNode *const pTxtNode)
+{
+ if ( isCHRATR(rAttr.Which()) )
+ {
+ // Somebody wants to build a SwTxtAttr for a character attribute.
+ // Sorry, this is not allowed any longer.
+ // You'll get a brand new autostyle attribute:
+ SfxItemSet aItemSet( rDoc.GetAttrPool(),
+ RES_CHRATR_BEGIN, RES_CHRATR_END );
+ aItemSet.Put( rAttr );
+ return MakeTxtAttr( rDoc, aItemSet, nStt, nEnd );
+ }
+ else if ( RES_TXTATR_AUTOFMT == rAttr.Which() &&
+ static_cast<const SwFmtAutoFmt&>(rAttr).GetStyleHandle()->
+ GetPool() != &rDoc.GetAttrPool() )
+ {
+ // If the attribute is an auto-style which refers to a pool that is
+ // different from rDoc's pool, we have to correct this:
+ const StylePool::SfxItemSet_Pointer_t pAutoStyle = static_cast<const SwFmtAutoFmt&>(rAttr).GetStyleHandle();
+ ::std::auto_ptr<const SfxItemSet> pNewSet(
+ pAutoStyle->SfxItemSet::Clone( sal_True, &rDoc.GetAttrPool() ));
+ SwTxtAttr* pNew = MakeTxtAttr( rDoc, *pNewSet, nStt, nEnd );
+ return pNew;
+ }
+
+ // Put new attribute into pool
+ // FIXME: this const_cast is evil!
+ SfxPoolItem& rNew =
+ const_cast<SfxPoolItem&>( rDoc.GetAttrPool().Put( rAttr ) );
+
+ SwTxtAttr* pNew = 0;
+ switch( rNew.Which() )
+ {
+ case RES_TXTATR_CHARFMT:
+ {
+ SwFmtCharFmt &rFmtCharFmt = (SwFmtCharFmt&) rNew;
+ if( !rFmtCharFmt.GetCharFmt() )
+ {
+ rFmtCharFmt.SetCharFmt( rDoc.GetDfltCharFmt() );
+ }
+
+ pNew = new SwTxtCharFmt( rFmtCharFmt, nStt, nEnd );
+ }
+ break;
+ case RES_TXTATR_INETFMT:
+ pNew = new SwTxtINetFmt( (SwFmtINetFmt&)rNew, nStt, nEnd );
+ break;
+ case RES_TXTATR_FIELD:
+ pNew = new SwTxtFld( static_cast<SwFmtFld &>(rNew), nStt );
+ break;
+ case RES_TXTATR_FLYCNT:
+ {
+ // erst hier wird das Frame-Format kopiert (mit Inhalt) !!
+ pNew = new SwTxtFlyCnt( (SwFmtFlyCnt&)rNew, nStt );
+ // Kopie von einem Text-Attribut
+ if ( static_cast<const SwFmtFlyCnt &>(rAttr).GetTxtFlyCnt() )
+ {
+ // then the format must be copied
+ static_cast<SwTxtFlyCnt *>(pNew)->CopyFlyFmt( &rDoc );
+ }
+ }
+ break;
+ case RES_TXTATR_FTN:
+ pNew = new SwTxtFtn( (SwFmtFtn&)rNew, nStt );
+ // ggfs. SeqNo kopieren
+ if( ((SwFmtFtn&)rAttr).GetTxtFtn() )
+ ((SwTxtFtn*)pNew)->SetSeqNo( ((SwFmtFtn&)rAttr).GetTxtFtn()->GetSeqRefNo() );
+ break;
+ case RES_TXTATR_REFMARK:
+ pNew = nStt == nEnd
+ ? new SwTxtRefMark( (SwFmtRefMark&)rNew, nStt )
+ : new SwTxtRefMark( (SwFmtRefMark&)rNew, nStt, &nEnd );
+ break;
+ case RES_TXTATR_TOXMARK:
+ pNew = new SwTxtTOXMark( (SwTOXMark&)rNew, nStt, &nEnd );
+ break;
+ case RES_TXTATR_CJK_RUBY:
+ pNew = new SwTxtRuby( (SwFmtRuby&)rNew, nStt, nEnd );
+ break;
+ case RES_TXTATR_META:
+ case RES_TXTATR_METAFIELD:
+ pNew = SwTxtMeta::CreateTxtMeta( rDoc.GetMetaFieldManager(), pTxtNode,
+ static_cast<SwFmtMeta&>(rNew), nStt, nEnd, bIsCopy );
+ break;
+ default:
+ OSL_ENSURE(RES_TXTATR_AUTOFMT == rNew.Which(), "unknown attribute");
+ pNew = new SwTxtAttrEnd( rNew, nStt, nEnd );
+ break;
+ }
+
+ return pNew;
+}
+
+SwTxtAttr* MakeTxtAttr( SwDoc & rDoc, const SfxItemSet& rSet,
+ xub_StrLen nStt, xub_StrLen nEnd )
+{
+ IStyleAccess& rStyleAccess = rDoc.GetIStyleAccess();
+ const StylePool::SfxItemSet_Pointer_t pAutoStyle = rStyleAccess.getAutomaticStyle( rSet, IStyleAccess::AUTO_STYLE_CHAR );
+ SwFmtAutoFmt aNewAutoFmt;
+ aNewAutoFmt.SetStyleHandle( pAutoStyle );
+ SwTxtAttr* pNew = MakeTxtAttr( rDoc, aNewAutoFmt, nStt, nEnd );
+ return pNew;
+}
+
+
+// loesche das Text-Attribut (muss beim Pool abgemeldet werden!)
+void SwTxtNode::DestroyAttr( SwTxtAttr* pAttr )
+{
+ if( pAttr )
+ {
+ // einige Sachen muessen vorm Loeschen der "Format-Attribute" erfolgen
+ SwDoc* pDoc = GetDoc();
+ sal_uInt16 nDelMsg = 0;
+ switch( pAttr->Which() )
+ {
+ case RES_TXTATR_FLYCNT:
+ {
+ // siehe auch die Anmerkung "Loeschen von Formaten
+ // zeichengebundener Frames" in fesh.cxx, SwFEShell::DelFmt()
+ SwFrmFmt* pFmt = pAttr->GetFlyCnt().GetFrmFmt();
+ if( pFmt ) // vom Undo auf 0 gesetzt ??
+ pDoc->DelLayoutFmt( (SwFlyFrmFmt*)pFmt );
+ }
+ break;
+
+ case RES_CHRATR_HIDDEN:
+ SetCalcHiddenCharFlags();
+ break;
+
+ case RES_TXTATR_FTN:
+ ((SwTxtFtn*)pAttr)->SetStartNode( 0 );
+ nDelMsg = RES_FOOTNOTE_DELETED;
+ break;
+
+ case RES_TXTATR_FIELD:
+ if( !pDoc->IsInDtor() )
+ {
+ // Wenn wir ein HiddenParaField sind, dann muessen wir
+ // ggf. fuer eine Neuberechnung des Visible-Flags sorgen.
+ const SwField* pFld = pAttr->GetFld().GetFld();
+
+ //JP 06-08-95: DDE-Felder bilden eine Ausnahme
+ OSL_ENSURE( RES_DDEFLD == pFld->GetTyp()->Which() ||
+ this == ((SwTxtFld*)pAttr)->GetpTxtNode(),
+ "Wo steht denn dieses Feld?" );
+
+ // bestimmte Felder mussen am Doc das Calculations-Flag updaten
+ switch( pFld->GetTyp()->Which() )
+ {
+ case RES_HIDDENPARAFLD:
+ SetCalcHiddenParaField();
+ // kein break !
+ case RES_DBSETNUMBERFLD:
+ case RES_GETEXPFLD:
+ case RES_DBFLD:
+ case RES_SETEXPFLD:
+ case RES_HIDDENTXTFLD:
+ case RES_DBNUMSETFLD:
+ case RES_DBNEXTSETFLD:
+ if( !pDoc->IsNewFldLst() && GetNodes().IsDocNodes() )
+ pDoc->InsDelFldInFldLst( sal_False, *(SwTxtFld*)pAttr );
+ break;
+ case RES_DDEFLD:
+ if( GetNodes().IsDocNodes() &&
+ ((SwTxtFld*)pAttr)->GetpTxtNode() )
+ ((SwDDEFieldType*)pFld->GetTyp())->DecRefCnt();
+ break;
+ case RES_POSTITFLD:
+ {
+ const_cast<SwFmtFld&>(pAttr->GetFld()).Broadcast( SwFmtFldHint( &((SwTxtFld*)pAttr)->GetFld(), SWFMTFLD_REMOVED ) );
+ break;
+ }
+ }
+ }
+ nDelMsg = RES_FIELD_DELETED;
+ break;
+
+ case RES_TXTATR_TOXMARK:
+ static_cast<SwTOXMark&>(pAttr->GetAttr()).InvalidateTOXMark();
+ break;
+
+ case RES_TXTATR_REFMARK:
+ nDelMsg = RES_REFMARK_DELETED;
+ break;
+
+ case RES_TXTATR_META:
+ case RES_TXTATR_METAFIELD:
+ static_cast<SwTxtMeta*>(pAttr)->ChgTxtNode(0);
+ break;
+
+ default:
+ break;
+ }
+
+ if( nDelMsg && !pDoc->IsInDtor() && GetNodes().IsDocNodes() )
+ {
+ SwPtrMsgPoolItem aMsgHint( nDelMsg, (void*)&pAttr->GetAttr() );
+ pDoc->GetUnoCallBack()->ModifyNotification( &aMsgHint, &aMsgHint );
+ }
+
+ SwTxtAttr::Destroy( pAttr, pDoc->GetAttrPool() );
+ }
+}
+
+/*************************************************************************
+ * SwTxtNode::Insert()
+ *************************************************************************/
+
+SwTxtAttr*
+SwTxtNode::InsertItem( SfxPoolItem& rAttr,
+ const xub_StrLen nStart, const xub_StrLen nEnd, const SetAttrMode nMode )
+{
+ // character attributes will be inserted as automatic styles:
+ OSL_ENSURE( !isCHRATR(rAttr.Which()), "AUTOSTYLES - "
+ "SwTxtNode::InsertItem should not be called with character attributes");
+
+ SwTxtAttr *const pNew = MakeTxtAttr( *GetDoc(), rAttr, nStart, nEnd,
+ (nMode & nsSetAttrMode::SETATTR_IS_COPY) ? COPY : NEW, this );
+
+ if ( pNew )
+ {
+ const bool bSuccess( InsertHint( pNew, nMode ) );
+ // N.B.: also check that the hint is actually in the hints array,
+ // because hints of certain types may be merged after succesful
+ // insertion, and thus destroyed!
+ if (!bSuccess || ( USHRT_MAX == m_pSwpHints->GetPos( pNew ) ))
+ {
+ return 0;
+ }
+ }
+
+ return pNew;
+}
+
+// take ownership of pAttr; if insertion fails, delete pAttr
+bool SwTxtNode::InsertHint( SwTxtAttr * const pAttr, const SetAttrMode nMode )
+{
+ sal_Bool bHiddenPara = sal_False;
+
+ OSL_ENSURE( pAttr && *pAttr->GetStart() <= Len(), "StartIdx out of bounds!" );
+ OSL_ENSURE( !pAttr->GetEnd() || (*pAttr->GetEnd() <= Len()),
+ "EndIdx out of bounds!" );
+
+ // translate from SetAttrMode to InsertMode (for hints with CH_TXTATR)
+ const enum IDocumentContentOperations::InsertFlags nInsertFlags =
+ (nMode & nsSetAttrMode::SETATTR_FORCEHINTEXPAND)
+ ? static_cast<IDocumentContentOperations::InsertFlags>(
+ IDocumentContentOperations::INS_FORCEHINTEXPAND |
+ IDocumentContentOperations::INS_EMPTYEXPAND)
+ : IDocumentContentOperations::INS_EMPTYEXPAND;
+
+ // need this after TryInsertHint, when pAttr may be deleted
+ const xub_StrLen nStart( *pAttr->GetStart() );
+ const bool bDummyChar( pAttr->HasDummyChar() );
+ if (bDummyChar)
+ {
+ sal_uInt16 nInsMode = nMode;
+ switch( pAttr->Which() )
+ {
+ case RES_TXTATR_FLYCNT:
+ {
+ SwTxtFlyCnt *pFly = (SwTxtFlyCnt *)pAttr;
+ SwFrmFmt* pFmt = pAttr->GetFlyCnt().GetFrmFmt();
+ if( !(nsSetAttrMode::SETATTR_NOTXTATRCHR & nInsMode) )
+ {
+ // Wir muessen zuerst einfuegen, da in SetAnchor()
+ // dem FlyFrm GetStart() uebermittelt wird.
+ //JP 11.05.98: falls das Anker-Attribut schon richtig
+ // gesetzt ist, dann korrigiere dieses nach dem Einfuegen
+ // des Zeichens. Sonst muesste das immer ausserhalb
+ // erfolgen (Fehleranfaellig !)
+ const SwFmtAnchor* pAnchor = 0;
+ pFmt->GetItemState( RES_ANCHOR, sal_False,
+ (const SfxPoolItem**)&pAnchor );
+
+ SwIndex aIdx( this, *pAttr->GetStart() );
+ const sal_Unicode c = GetCharOfTxtAttr(*pAttr);
+ InsertText( c, aIdx, nInsertFlags );
+ nInsMode |= nsSetAttrMode::SETATTR_NOTXTATRCHR;
+
+ if (pAnchor &&
+ (FLY_AS_CHAR == pAnchor->GetAnchorId()) &&
+ pAnchor->GetCntntAnchor() &&
+ pAnchor->GetCntntAnchor()->nNode == *this &&
+ pAnchor->GetCntntAnchor()->nContent == aIdx )
+ {
+ const_cast<SwIndex&>(
+ pAnchor->GetCntntAnchor()->nContent)--;
+ }
+ }
+ pFly->SetAnchor( this );
+
+ // Format-Pointer kann sich im SetAnchor geaendert haben!
+ // (Kopieren in andere Docs!)
+ pFmt = pAttr->GetFlyCnt().GetFrmFmt();
+ SwDoc *pDoc = pFmt->GetDoc();
+
+ // OD 26.06.2003 #108784# - allow drawing objects in header/footer.
+ // But don't allow control objects in header/footer
+ if( RES_DRAWFRMFMT == pFmt->Which() &&
+ pDoc->IsInHeaderFooter( pFmt->GetAnchor().GetCntntAnchor()->nNode ) )
+ {
+ SwDrawContact* pDrawContact =
+ static_cast<SwDrawContact*>(pFmt->FindContactObj());
+ if ( pDrawContact &&
+ pDrawContact->GetMaster() &&
+ ::CheckControlLayer( pDrawContact->GetMaster() ) )
+ {
+ // das soll nicht meoglich sein; hier verhindern
+ // Der Dtor des TxtHints loescht nicht das Zeichen.
+ // Wenn ein CH_TXTATR_.. vorliegt, dann muss man
+ // dieses explizit loeschen
+ if( nsSetAttrMode::SETATTR_NOTXTATRCHR & nInsMode )
+ {
+ // loesche das Zeichen aus dem String !
+ OSL_ENSURE( ( CH_TXTATR_BREAKWORD ==
+ m_Text.GetChar(*pAttr->GetStart() ) ||
+ CH_TXTATR_INWORD ==
+ m_Text.GetChar(*pAttr->GetStart())),
+ "where is my attribute character?" );
+ m_Text.Erase( *pAttr->GetStart(), 1 );
+ // Indizies Updaten
+ SwIndex aTmpIdx( this, *pAttr->GetStart() );
+ Update( aTmpIdx, 1, sal_True );
+ }
+ // do not record deletion of Format!
+ ::sw::UndoGuard const ug(pDoc->GetIDocumentUndoRedo());
+ DestroyAttr( pAttr );
+ return false;
+ }
+ }
+ break;
+ }
+
+ case RES_TXTATR_FTN :
+ {
+ // Fussnoten, man kommt an alles irgendwie heran.
+ // CntntNode erzeugen und in die Inserts-Section stellen
+ SwDoc *pDoc = GetDoc();
+ SwNodes &rNodes = pDoc->GetNodes();
+
+ // FussNote in nicht Content-/Redline-Bereich einfuegen ??
+ if( StartOfSectionIndex() < rNodes.GetEndOfAutotext().GetIndex() )
+ {
+ // das soll nicht meoglich sein; hier verhindern
+ // Der Dtor des TxtHints loescht nicht das Zeichen.
+ // Wenn ein CH_TXTATR_.. vorliegt, dann muss man
+ // dieses explizit loeschen
+ if( nsSetAttrMode::SETATTR_NOTXTATRCHR & nInsMode )
+ {
+ // loesche das Zeichen aus dem String !
+ OSL_ENSURE( ( CH_TXTATR_BREAKWORD ==
+ m_Text.GetChar(*pAttr->GetStart() ) ||
+ CH_TXTATR_INWORD ==
+ m_Text.GetChar(*pAttr->GetStart())),
+ "where is my attribute character?" );
+ m_Text.Erase( *pAttr->GetStart(), 1 );
+ // Indizies Updaten
+ SwIndex aTmpIdx( this, *pAttr->GetStart() );
+ Update( aTmpIdx, 1, sal_True );
+ }
+ DestroyAttr( pAttr );
+ return false;
+ }
+
+ // wird eine neue Fussnote eingefuegt ??
+ sal_Bool bNewFtn = 0 == ((SwTxtFtn*)pAttr)->GetStartNode();
+ if( bNewFtn )
+ {
+ ((SwTxtFtn*)pAttr)->MakeNewTextSection( GetNodes() );
+ SwRegHistory* pHist = GetpSwpHints()
+ ? GetpSwpHints()->GetHistory() : 0;
+ if( pHist )
+ pHist->ChangeNodeIndex( GetIndex() );
+ }
+ else if ( !GetpSwpHints() || !GetpSwpHints()->IsInSplitNode() )
+ {
+ // loesche alle Frames der Section, auf die der StartNode zeigt
+ sal_uLong nSttIdx =
+ ((SwTxtFtn*)pAttr)->GetStartNode()->GetIndex();
+ sal_uLong nEndIdx = rNodes[ nSttIdx++ ]->EndOfSectionIndex();
+ SwCntntNode* pCNd;
+ for( ; nSttIdx < nEndIdx; ++nSttIdx )
+ if( 0 != ( pCNd = rNodes[ nSttIdx ]->GetCntntNode() ))
+ pCNd->DelFrms();
+ }
+
+ if( !(nsSetAttrMode::SETATTR_NOTXTATRCHR & nInsMode) )
+ {
+ // Wir muessen zuerst einfuegen, da sonst gleiche Indizes
+ // entstehen koennen und das Attribut im _SortArr_ am
+ // Dokument nicht eingetrage wird.
+ SwIndex aNdIdx( this, *pAttr->GetStart() );
+ const sal_Unicode c = GetCharOfTxtAttr(*pAttr);
+ InsertText( c, aNdIdx, nInsertFlags );
+ nInsMode |= nsSetAttrMode::SETATTR_NOTXTATRCHR;
+ }
+
+ // Wir tragen uns am FtnIdx-Array des Docs ein ...
+ SwTxtFtn* pTxtFtn = 0;
+ if( !bNewFtn )
+ {
+ // eine alte Ftn wird umgehaengt (z.B. SplitNode)
+ for( sal_uInt16 n = 0; n < pDoc->GetFtnIdxs().Count(); ++n )
+ if( pAttr == pDoc->GetFtnIdxs()[n] )
+ {
+ // neuen Index zuweisen, dafuer aus dem SortArray
+ // loeschen und neu eintragen
+ pTxtFtn = pDoc->GetFtnIdxs()[n];
+ pDoc->GetFtnIdxs().Remove( n );
+ break;
+ }
+ // wenn ueber Undo der StartNode gesetzt wurde, kann
+ // der Index noch gar nicht in der Verwaltung stehen !!
+ }
+ if( !pTxtFtn )
+ pTxtFtn = (SwTxtFtn*)pAttr;
+
+ // fuers Update der Nummern und zum Sortieren
+ // muss der Node gesetzt sein.
+ ((SwTxtFtn*)pAttr)->ChgTxtNode( this );
+
+ // FussNote im Redline-Bereich NICHT ins FtnArray einfuegen!
+ if( StartOfSectionIndex() > rNodes.GetEndOfRedlines().GetIndex() )
+ {
+#if OSL_DEBUG_LEVEL > 1
+ const sal_Bool bSuccess =
+#endif
+ pDoc->GetFtnIdxs().Insert( pTxtFtn );
+#if OSL_DEBUG_LEVEL > 1
+ OSL_ENSURE( bSuccess, "FtnIdx nicht eingetragen." );
+#endif
+ }
+ SwNodeIndex aTmpIndex( *this );
+ pDoc->GetFtnIdxs().UpdateFtn( aTmpIndex);
+ ((SwTxtFtn*)pAttr)->SetSeqRefNo();
+ }
+ break;
+
+ case RES_TXTATR_FIELD:
+ {
+ // fuer HiddenParaFields Benachrichtigungsmechanismus
+ // anwerfen
+ if( RES_HIDDENPARAFLD ==
+ pAttr->GetFld().GetFld()->GetTyp()->Which() )
+ bHiddenPara = sal_True;
+ }
+ break;
+
+ }
+ // Fuer SwTxtHints ohne Endindex werden CH_TXTATR_..
+ // eingefuegt, aStart muss danach um einen zurueckgesetzt werden.
+ // Wenn wir im SwTxtNode::Copy stehen, so wurde das Zeichen bereits
+ // mitkopiert. In solchem Fall ist SETATTR_NOTXTATRCHR angegeben worden.
+ if( !(nsSetAttrMode::SETATTR_NOTXTATRCHR & nInsMode) )
+ {
+ SwIndex aIdx( this, *pAttr->GetStart() );
+ InsertText( GetCharOfTxtAttr(*pAttr), aIdx, nInsertFlags );
+
+ // adjust end of hint to account for inserted CH_TXTATR
+ xub_StrLen * const pEnd(pAttr->GetEnd());
+ if (pEnd)
+ {
+ *pEnd = *pEnd + 1;
+ }
+ }
+ }
+
+ GetOrCreateSwpHints();
+
+ // 4263: AttrInsert durch TextInsert => kein Adjust
+ const bool bRet = m_pSwpHints->TryInsertHint( pAttr, *this, nMode );
+
+ if (!bRet && bDummyChar)
+ {
+ // undo insertion of dummy character
+ // N.B. cannot insert the dummy character after inserting the hint,
+ // because if the hint has no extent it will be moved in InsertText,
+ // resulting in infinite recursion
+ if ( !(nsSetAttrMode::SETATTR_NOTXTATRCHR & nMode) )
+ {
+ OSL_ENSURE( ( CH_TXTATR_BREAKWORD == m_Text.GetChar(nStart) ||
+ CH_TXTATR_INWORD == m_Text.GetChar(nStart) ),
+ "where is my attribute character?" );
+ SwIndex aIdx( this, nStart );
+ EraseText( aIdx, 1 );
+ }
+ }
+
+ if ( bHiddenPara )
+ {
+ SetCalcHiddenParaField();
+ }
+
+ return bRet;
+}
+
+
+/*************************************************************************
+ * SwTxtNode::DeleteAttribute()
+ *************************************************************************/
+
+void SwTxtNode::DeleteAttribute( SwTxtAttr * const pAttr )
+{
+ if ( !HasHints() )
+ {
+ OSL_FAIL("DeleteAttribute called, but text node without hints?");
+ return;
+ }
+
+ if ( pAttr->HasDummyChar() )
+ {
+ // Unbedingt Copy-konstruieren!
+ const SwIndex aIdx( this, *pAttr->GetStart() );
+ // erase the CH_TXTATR, which will also delete pAttr
+ EraseText( aIdx, 1 );
+ }
+ else
+ {
+ // create MsgHint before start/end become invalid
+ SwUpdateAttr aHint(
+ *pAttr->GetStart(), *pAttr->GetEnd(), pAttr->Which() );
+ m_pSwpHints->Delete( pAttr );
+ SwTxtAttr::Destroy( pAttr, GetDoc()->GetAttrPool() );
+ NotifyClients( 0, &aHint );
+
+ TryDeleteSwpHints();
+ }
+}
+
+/*************************************************************************
+ * SwTxtNode::DeleteAttributes()
+ *************************************************************************/
+
+//FIXME: this does NOT respect SORT NUMBER (for CHARFMT)!
+void SwTxtNode::DeleteAttributes( const sal_uInt16 nWhich,
+ const xub_StrLen nStart, const xub_StrLen nEnd )
+{
+ if ( !HasHints() )
+ return;
+
+ for ( sal_uInt16 nPos = 0; m_pSwpHints && nPos < m_pSwpHints->Count(); nPos++ )
+ {
+ SwTxtAttr * const pTxtHt = m_pSwpHints->GetTextHint( nPos );
+ const xub_StrLen nHintStart = *(pTxtHt->GetStart());
+ if (nStart < nHintStart)
+ {
+ break; // sorted by start
+ }
+ else if ( (nStart == nHintStart) && (nWhich == pTxtHt->Which()) )
+ {
+ if ( nWhich == RES_CHRATR_HIDDEN )
+ {
+ OSL_FAIL("hey, that's a CHRATR! how did that get in?");
+ SetCalcHiddenCharFlags();
+ }
+ else if ( nWhich == RES_TXTATR_CHARFMT )
+ {
+ // Check if character format contains hidden attribute:
+ const SwCharFmt* pFmt = pTxtHt->GetCharFmt().GetCharFmt();
+ const SfxPoolItem* pItem;
+ if ( SFX_ITEM_SET == pFmt->GetItemState( RES_CHRATR_HIDDEN, sal_True, &pItem ) )
+ SetCalcHiddenCharFlags();
+ }
+ // --> FME 2007-03-16 #i75430# Recalc hidden flags if necessary
+ else if ( nWhich == RES_TXTATR_AUTOFMT )
+ {
+ // Check if auto style contains hidden attribute:
+ const SfxPoolItem* pHiddenItem = CharFmt::GetItem( *pTxtHt, RES_CHRATR_HIDDEN );
+ if ( pHiddenItem )
+ SetCalcHiddenCharFlags();
+ }
+ // <--
+
+ xub_StrLen const * const pEndIdx = pTxtHt->GetEnd();
+
+ if ( pTxtHt->HasDummyChar() )
+ {
+ // Unbedingt Copy-konstruieren!
+ const SwIndex aIdx( this, nStart );
+ // erase the CH_TXTATR, which will also delete pTxtHt
+ EraseText( aIdx, 1 );
+ }
+ else if( *pEndIdx == nEnd )
+ {
+ // den MsgHint jetzt fuettern, weil gleich sind
+ // Start und End weg.
+ // Das CalcVisibleFlag bei HiddenParaFields entfaellt,
+ // da dies das Feld im Dtor selbst erledigt.
+ SwUpdateAttr aHint( nStart, *pEndIdx, nWhich );
+ m_pSwpHints->DeleteAtPos( nPos ); // gefunden, loeschen,
+ SwTxtAttr::Destroy( pTxtHt, GetDoc()->GetAttrPool() );
+ NotifyClients( 0, &aHint );
+ }
+ }
+ }
+ TryDeleteSwpHints();
+}
+
+/*************************************************************************
+ * SwTxtNode::DelSoftHyph()
+ *************************************************************************/
+
+void SwTxtNode::DelSoftHyph( const xub_StrLen nStt, const xub_StrLen nEnd )
+{
+ xub_StrLen nFndPos = nStt, nEndPos = nEnd;
+ while( STRING_NOTFOUND !=
+ ( nFndPos = m_Text.Search( CHAR_SOFTHYPHEN, nFndPos )) &&
+ nFndPos < nEndPos )
+ {
+ const SwIndex aIdx( this, nFndPos );
+ EraseText( aIdx, 1 );
+ --nEndPos;
+ }
+}
+
+// setze diese Attribute am TextNode. Wird der gesamte Bereich umspannt,
+// dann setze sie nur im AutoAttrSet (SwCntntNode:: SetAttr)
+sal_Bool SwTxtNode::SetAttr( const SfxItemSet& rSet, xub_StrLen nStt,
+ xub_StrLen nEnd, const SetAttrMode nMode )
+{
+ if( !rSet.Count() )
+ return sal_False;
+
+ // teil die Sets auf (fuer Selektion in Nodes)
+ const SfxItemSet* pSet = &rSet;
+ SfxItemSet aTxtSet( *rSet.GetPool(), RES_TXTATR_BEGIN, RES_TXTATR_END-1 );
+
+ // gesamter Bereich
+ if ( !nStt && (nEnd == m_Text.Len()) &&
+ !(nMode & nsSetAttrMode::SETATTR_NOFORMATATTR ) )
+ {
+ // sind am Node schon Zeichenvorlagen gesetzt, muss man diese Attribute
+ // (rSet) immer als TextAttribute setzen, damit sie angezeigt werden.
+ int bHasCharFmts = sal_False;
+ if ( HasHints() )
+ {
+ for ( sal_uInt16 n = 0; n < m_pSwpHints->Count(); ++n )
+ {
+ if ( (*m_pSwpHints)[ n ]->IsCharFmtAttr() )
+ {
+ bHasCharFmts = sal_True;
+ break;
+ }
+ }
+ }
+
+ if( !bHasCharFmts )
+ {
+ aTxtSet.Put( rSet );
+ // If there are any character attributes in rSet,
+ // we want to set them at the paragraph:
+ if( aTxtSet.Count() != rSet.Count() )
+ {
+ sal_Bool bRet = SetAttr( rSet );
+ if( !aTxtSet.Count() )
+ return bRet;
+ }
+
+ // check for auto style:
+ const SfxPoolItem* pItem;
+ const bool bAutoStyle = SFX_ITEM_SET == aTxtSet.GetItemState( RES_TXTATR_AUTOFMT, sal_False, &pItem );
+ if ( bAutoStyle )
+ {
+ boost::shared_ptr<SfxItemSet> pAutoStyleSet = static_cast<const SwFmtAutoFmt*>(pItem)->GetStyleHandle();
+ sal_Bool bRet = SetAttr( *pAutoStyleSet );
+ if( 1 == aTxtSet.Count() )
+ return bRet;
+ }
+
+ // Continue with the text attributes:
+ pSet = &aTxtSet;
+ }
+ }
+
+ GetOrCreateSwpHints();
+
+ SfxItemSet aCharSet( *rSet.GetPool(), aCharAutoFmtSetRange );
+
+ sal_uInt16 nCount = 0;
+ SfxItemIter aIter( *pSet );
+ const SfxPoolItem* pItem = aIter.GetCurItem();
+
+ do
+ {
+ if ( pItem && (reinterpret_cast<SfxPoolItem*>(-1) != pItem))
+ {
+ const sal_uInt16 nWhich = pItem->Which();
+ OSL_ENSURE( isCHRATR(nWhich) || isTXTATR(nWhich),
+ "SwTxtNode::SetAttr(): unknown attribute" );
+ if ( isCHRATR(nWhich) || isTXTATR(nWhich) )
+ {
+ if ((RES_TXTATR_CHARFMT == nWhich) &&
+ (GetDoc()->GetDfltCharFmt() ==
+ static_cast<const SwFmtCharFmt*>(pItem)->GetCharFmt()))
+ {
+ SwIndex aIndex( this, nStt );
+ RstAttr( aIndex, nEnd - nStt, RES_TXTATR_CHARFMT, 0 );
+ DontExpandFmt( aIndex );
+ }
+ else
+ {
+ if (isCHRATR(nWhich) ||
+ (RES_TXTATR_UNKNOWN_CONTAINER == nWhich))
+ {
+ aCharSet.Put( *pItem );
+ }
+ else
+ {
+
+ SwTxtAttr *const pNew = MakeTxtAttr( *GetDoc(),
+ const_cast<SfxPoolItem&>(*pItem), nStt, nEnd );
+ if ( pNew )
+ {
+ if ( nEnd != nStt && !pNew->GetEnd() )
+ {
+ OSL_FAIL("Attribut without end, but area marked");
+ DestroyAttr( pNew ); // do not insert
+ }
+ else if ( InsertHint( pNew, nMode ) )
+ {
+ ++nCount;
+ }
+ }
+ }
+ }
+ }
+ }
+ if ( aIter.IsAtEnd() )
+ break;
+ pItem = aIter.NextItem();
+ } while( true );
+
+ if ( aCharSet.Count() )
+ {
+ SwTxtAttr* pTmpNew = MakeTxtAttr( *GetDoc(), aCharSet, nStt, nEnd );
+ if ( InsertHint( pTmpNew, nMode ) )
+ {
+ ++nCount;
+ }
+ }
+
+ TryDeleteSwpHints();
+
+ return nCount ? sal_True : sal_False;
+}
+
+void lcl_MergeAttr( SfxItemSet& rSet, const SfxPoolItem& rAttr )
+{
+ if ( RES_TXTATR_AUTOFMT == rAttr.Which() )
+ {
+ const SfxItemSet* pCFSet = CharFmt::GetItemSet( rAttr );
+ if ( !pCFSet )
+ return;
+ SfxWhichIter aIter( *pCFSet );
+ sal_uInt16 nWhich = aIter.FirstWhich();
+ while( nWhich )
+ {
+ if( ( nWhich < RES_CHRATR_END ||
+ RES_TXTATR_UNKNOWN_CONTAINER == nWhich ) &&
+ ( SFX_ITEM_SET == pCFSet->GetItemState( nWhich, sal_True ) ) )
+ rSet.Put( pCFSet->Get( nWhich ) );
+ nWhich = aIter.NextWhich();
+ }
+ }
+ else
+ rSet.Put( rAttr );
+}
+
+void lcl_MergeAttr_ExpandChrFmt( SfxItemSet& rSet, const SfxPoolItem& rAttr )
+{
+ if( RES_TXTATR_CHARFMT == rAttr.Which() ||
+ RES_TXTATR_INETFMT == rAttr.Which() ||
+ RES_TXTATR_AUTOFMT == rAttr.Which() )
+ {
+ const SfxItemSet* pCFSet = CharFmt::GetItemSet( rAttr );
+
+ if ( pCFSet )
+ {
+ SfxWhichIter aIter( *pCFSet );
+ sal_uInt16 nWhich = aIter.FirstWhich();
+ while( nWhich )
+ {
+ if( ( nWhich < RES_CHRATR_END ||
+ ( RES_TXTATR_AUTOFMT == rAttr.Which() && RES_TXTATR_UNKNOWN_CONTAINER == nWhich ) ) &&
+ ( SFX_ITEM_SET == pCFSet->GetItemState( nWhich, sal_True ) ) )
+ rSet.Put( pCFSet->Get( nWhich ) );
+ nWhich = aIter.NextWhich();
+ }
+ }
+ }
+
+ // aufnehmen als MergeWert (falls noch nicht gesetzt neu setzen!)
+
+/* wenn mehrere Attribute ueberlappen gewinnt der letze !!
+ z.B
+ 1234567890123456789
+ |------------| Font1
+ |------| Font2
+ ^ ^
+ |--| Abfragebereich: -> Gueltig ist Font2
+*/
+ rSet.Put( rAttr );
+}
+
+struct SwPoolItemEndPair
+{
+public:
+ const SfxPoolItem* mpItem;
+ xub_StrLen mnEndPos;
+
+ SwPoolItemEndPair() : mpItem( 0 ), mnEndPos( 0 ) {};
+};
+
+void lcl_MergeListLevelIndentAsLRSpaceItem( const SwTxtNode& rTxtNode,
+ SfxItemSet& rSet )
+{
+ if ( rTxtNode.AreListLevelIndentsApplicable() )
+ {
+ const SwNumRule* pRule = rTxtNode.GetNumRule();
+ if ( pRule && rTxtNode.GetActualListLevel() >= 0 )
+ {
+ const SwNumFmt& rFmt = pRule->Get(static_cast<sal_uInt16>(rTxtNode.GetActualListLevel()));
+ if ( rFmt.GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_ALIGNMENT )
+ {
+ SvxLRSpaceItem aLR( RES_LR_SPACE );
+ aLR.SetTxtLeft( rFmt.GetIndentAt() );
+ aLR.SetTxtFirstLineOfst( static_cast<short>(rFmt.GetFirstLineIndent()) );
+ rSet.Put( aLR );
+ }
+ }
+ }
+}
+
+// erfrage die Attribute vom TextNode ueber den Bereich
+sal_Bool SwTxtNode::GetAttr( SfxItemSet& rSet, xub_StrLen nStt, xub_StrLen nEnd,
+ sal_Bool bOnlyTxtAttr, sal_Bool bGetFromChrFmt,
+ const bool bMergeIndentValuesOfNumRule ) const
+{
+ if( HasHints() )
+ {
+ /* stelle erstmal fest, welche Text-Attribut in dem Bereich gueltig
+ * sind. Dabei gibt es folgende Faelle:
+ * UnEindeutig wenn: (wenn != Format-Attribut)
+ * - das Attribut liegt vollstaendig im Bereich
+ * - das Attributende liegt im Bereich
+ * - der Attributanfang liegt im Bereich:
+ * Eindeutig (im Set mergen):
+ * - das Attrib umfasst den Bereich
+ * nichts tun:
+ * das Attribut liegt ausserhalb des Bereiches
+ */
+
+ void (*fnMergeAttr)( SfxItemSet&, const SfxPoolItem& )
+ = bGetFromChrFmt ? &lcl_MergeAttr_ExpandChrFmt
+ : &lcl_MergeAttr;
+
+ // dann besorge mal die Auto-(Fmt)Attribute
+ SfxItemSet aFmtSet( *rSet.GetPool(), rSet.GetRanges() );
+ if( !bOnlyTxtAttr )
+ {
+ SwCntntNode::GetAttr( aFmtSet );
+ if ( bMergeIndentValuesOfNumRule )
+ {
+ lcl_MergeListLevelIndentAsLRSpaceItem( *this, aFmtSet );
+ }
+ }
+
+ const sal_uInt16 nSize = m_pSwpHints->Count();
+
+ if( nStt == nEnd ) // kein Bereich:
+ {
+ for (sal_uInt16 n = 0; n < nSize; ++n)
+ {
+ const SwTxtAttr* pHt = (*m_pSwpHints)[n];
+ const xub_StrLen nAttrStart = *pHt->GetStart();
+ if( nAttrStart > nEnd ) // ueber den Bereich hinaus
+ break;
+
+ const xub_StrLen* pAttrEnd = pHt->GetEnd();
+ if ( ! pAttrEnd ) // no attributes without end
+ continue;
+
+ if( ( nAttrStart < nStt &&
+ ( pHt->DontExpand() ? nStt < *pAttrEnd
+ : nStt <= *pAttrEnd )) ||
+ ( nStt == nAttrStart &&
+ ( nAttrStart == *pAttrEnd || !nStt )))
+ (*fnMergeAttr)( rSet, pHt->GetAttr() );
+ }
+ }
+ else // es ist ein Bereich definiert
+ {
+ // --> FME 2007-03-13 #i75299#
+ ::std::auto_ptr< std::vector< SwPoolItemEndPair > > pAttrArr;
+ // <--
+
+ const sal_uInt16 coArrSz = static_cast<sal_uInt16>(RES_TXTATR_WITHEND_END) -
+ static_cast<sal_uInt16>(RES_CHRATR_BEGIN);
+
+ for (sal_uInt16 n = 0; n < nSize; ++n)
+ {
+ const SwTxtAttr* pHt = (*m_pSwpHints)[n];
+ const xub_StrLen nAttrStart = *pHt->GetStart();
+ if( nAttrStart > nEnd ) // ueber den Bereich hinaus
+ break;
+
+ const xub_StrLen* pAttrEnd = pHt->GetEnd();
+ if ( ! pAttrEnd ) // no attributes without end
+ continue;
+
+ sal_Bool bChkInvalid = sal_False;
+ if( nAttrStart <= nStt ) // vor oder genau Start
+ {
+ if( *pAttrEnd <= nStt ) // liegt davor
+ continue;
+
+ if( nEnd <= *pAttrEnd ) // hinter oder genau Ende
+ (*fnMergeAttr)( aFmtSet, pHt->GetAttr() );
+ else
+// else if( pHt->GetAttr() != aFmtSet.Get( pHt->Which() ) )
+ // uneindeutig
+ bChkInvalid = sal_True;
+ }
+ else if( nAttrStart < nEnd // reicht in den Bereich
+)// && pHt->GetAttr() != aFmtSet.Get( pHt->Which() ) )
+ bChkInvalid = sal_True;
+
+ if( bChkInvalid )
+ {
+ // uneindeutig ?
+ ::std::auto_ptr< SfxItemIter > pItemIter;
+ const SfxPoolItem* pItem = 0;
+
+ if ( RES_TXTATR_AUTOFMT == pHt->Which() )
+ {
+ const SfxItemSet* pAutoSet = CharFmt::GetItemSet( pHt->GetAttr() );
+ if ( pAutoSet )
+ {
+ pItemIter.reset( new SfxItemIter( *pAutoSet ) );
+ pItem = pItemIter->GetCurItem();
+ }
+ }
+ else
+ pItem = &pHt->GetAttr();
+
+ const sal_uInt16 nHintEnd = *pAttrEnd;
+
+ while ( pItem )
+ {
+ const sal_uInt16 nHintWhich = pItem->Which();
+ OSL_ENSURE(!isUNKNOWNATR(nHintWhich),
+ "SwTxtNode::GetAttr(): unknown attribute?");
+
+ if ( !pAttrArr.get() )
+ {
+ pAttrArr.reset(
+ new std::vector< SwPoolItemEndPair >(coArrSz));
+ }
+
+ std::vector< SwPoolItemEndPair >::iterator pPrev = pAttrArr->begin();
+ if (isCHRATR(nHintWhich) ||
+ isTXTATR_WITHEND(nHintWhich))
+ {
+ pPrev += nHintWhich - RES_CHRATR_BEGIN;
+ }
+ else
+ {
+ pPrev = pAttrArr->end();
+ }
+
+#if OSL_DEBUG_LEVEL > 1
+ SwPoolItemEndPair aTmp = *pPrev;
+#endif
+
+ if( pPrev != pAttrArr->end() )
+ {
+ if( !pPrev->mpItem )
+ {
+ if ( bOnlyTxtAttr || *pItem != aFmtSet.Get( nHintWhich ) )
+ {
+ if( nAttrStart > nStt )
+ {
+ rSet.InvalidateItem( nHintWhich );
+ pPrev->mpItem = (SfxPoolItem*)-1;
+ }
+ else
+ {
+ pPrev->mpItem = pItem;
+ pPrev->mnEndPos = nHintEnd;
+ }
+ }
+ }
+ else if( (SfxPoolItem*)-1 != pPrev->mpItem )
+ {
+ if( pPrev->mnEndPos == nAttrStart &&
+ *pPrev->mpItem == *pItem )
+ {
+ pPrev->mpItem = pItem;
+ pPrev->mnEndPos = nHintEnd;
+ }
+ else
+ {
+ rSet.InvalidateItem( nHintWhich );
+ pPrev->mpItem = (SfxPoolItem*)-1;
+ }
+ }
+ }
+
+ pItem = ( pItemIter.get() && !pItemIter->IsAtEnd() )
+ ? pItemIter->NextItem() : 0;
+ } // end while
+ }
+ }
+
+ if ( pAttrArr.get() )
+ {
+ for (sal_uInt16 n = 0; n < coArrSz; ++n)
+ {
+ const SwPoolItemEndPair& rItemPair = (*pAttrArr)[ n ];
+ if( (0 != rItemPair.mpItem) && ((SfxPoolItem*)-1 != rItemPair.mpItem) )
+ {
+ const sal_uInt16 nWh =
+ static_cast<sal_uInt16>(n + RES_CHRATR_BEGIN);
+
+ if( nEnd <= rItemPair.mnEndPos ) // hinter oder genau Ende
+ {
+ if( *rItemPair.mpItem != aFmtSet.Get( nWh ) )
+ (*fnMergeAttr)( rSet, *rItemPair.mpItem );
+ }
+ else
+ // uneindeutig
+ rSet.InvalidateItem( nWh );
+ }
+ }
+ }
+ }
+ if( aFmtSet.Count() )
+ {
+ // aus dem Format-Set alle entfernen, die im TextSet auch gesetzt sind
+ aFmtSet.Differentiate( rSet );
+ // jetzt alle zusammen "mergen"
+ rSet.Put( aFmtSet );
+ }
+ }
+ else if( !bOnlyTxtAttr )
+ {
+ // dann besorge mal die Auto-(Fmt)Attribute
+ SwCntntNode::GetAttr( rSet );
+ if ( bMergeIndentValuesOfNumRule )
+ {
+ lcl_MergeListLevelIndentAsLRSpaceItem( *this, rSet );
+ }
+ }
+
+ return rSet.Count() ? sal_True : sal_False;
+}
+
+
+namespace
+{
+
+typedef std::pair<sal_uInt16, sal_uInt16> AttrSpan_t;
+typedef std::multimap<AttrSpan_t, const SwTxtAttr*> AttrSpanMap_t;
+
+
+struct IsAutoStyle
+{
+ bool
+ operator()(const AttrSpanMap_t::value_type& i_rAttrSpan)
+ const
+ {
+ return i_rAttrSpan.second && i_rAttrSpan.second->Which() == RES_TXTATR_AUTOFMT;
+ }
+};
+
+
+/** Removes from io_rAttrSet all items that are set by style on the
+ given span.
+ */
+struct RemovePresentAttrs
+{
+ RemovePresentAttrs(SfxItemSet& io_rAttrSet)
+ : m_rAttrSet(io_rAttrSet)
+ {
+ }
+
+ void
+ operator()(const AttrSpanMap_t::value_type& i_rAttrSpan)
+ const
+ {
+ if (!i_rAttrSpan.second)
+ {
+ return;
+ }
+
+ const SwTxtAttr* const pAutoStyle(i_rAttrSpan.second);
+ SfxItemIter aIter(m_rAttrSet);
+ const SfxPoolItem* pItem(aIter.GetCurItem());
+ while (pItem)
+ {
+ const sal_uInt16 nWhich(pItem->Which());
+ if (CharFmt::IsItemIncluded(nWhich, pAutoStyle))
+ {
+ m_rAttrSet.ClearItem(nWhich);
+ }
+
+ if (aIter.IsAtEnd())
+ {
+ break;
+ }
+ pItem = aIter.NextItem();
+ }
+ }
+
+private:
+ SfxItemSet& m_rAttrSet;
+};
+
+
+/** Collects all style-covered spans from i_rHints to o_rSpanMap. In
+ addition inserts dummy spans with pointer to format equal to 0 for
+ all gaps (i.e. spans not covered by any style). This simplifies
+ creation of autostyles for all needed spans, but it means all code
+ that tries to access the pointer has to check if it's non-null!
+ */
+void
+lcl_CollectHintSpans(const SwpHints& i_rHints, const sal_uInt16 nLength,
+ AttrSpanMap_t& o_rSpanMap)
+{
+ sal_uInt16 nLastEnd(0);
+
+ for (sal_uInt16 i(0); i != i_rHints.Count(); ++i)
+ {
+ const SwTxtAttr* const pHint(i_rHints[i]);
+ const sal_uInt16 nWhich(pHint->Which());
+ if (nWhich == RES_TXTATR_CHARFMT || nWhich == RES_TXTATR_AUTOFMT)
+ {
+ const AttrSpan_t aSpan(*pHint->GetStart(), *pHint->GetEnd());
+ o_rSpanMap.insert(AttrSpanMap_t::value_type(aSpan, pHint));
+
+ if (aSpan.first != nLastEnd)
+ {
+ // insert dummy span covering the gap
+ o_rSpanMap.insert(AttrSpanMap_t::value_type(
+ AttrSpan_t(nLastEnd, aSpan.first), 0));
+ }
+
+ nLastEnd = aSpan.second;
+ }
+ }
+
+ // no hints at the end (special case: no hints at all in i_rHints)
+ if (nLastEnd != nLength && nLength != 0)
+ {
+ o_rSpanMap.insert(
+ AttrSpanMap_t::value_type(AttrSpan_t(nLastEnd, nLength), 0));
+ }
+}
+
+
+void
+lcl_FillWhichIds(const SfxItemSet& i_rAttrSet, std::vector<sal_uInt16>& o_rClearIds)
+{
+ o_rClearIds.reserve(i_rAttrSet.Count());
+ SfxItemIter aIter(i_rAttrSet);
+ const SfxPoolItem* pItem(aIter.GetCurItem());
+ while (pItem)
+ {
+ o_rClearIds.push_back(pItem->Which());
+
+ if (aIter.IsAtEnd())
+ {
+ break;
+ }
+ pItem = aIter.NextItem();
+ }
+}
+
+struct SfxItemSetClearer
+{
+ SfxItemSet & m_rItemSet;
+ SfxItemSetClearer(SfxItemSet & rItemSet) : m_rItemSet(rItemSet) { }
+ void operator()(sal_uInt16 const nWhich) { m_rItemSet.ClearItem(nWhich); }
+};
+
+}
+
+
+/** Does the hard work of SwTxtNode::FmtToTxtAttr: the real conversion
+ of items to automatic styles.
+ */
+void
+SwTxtNode::impl_FmtToTxtAttr(const SfxItemSet& i_rAttrSet)
+{
+ typedef AttrSpanMap_t::iterator AttrSpanMap_iterator_t;
+ AttrSpanMap_t aAttrSpanMap;
+
+ if (i_rAttrSet.Count() == 0)
+ {
+ return;
+ }
+
+ // 1. Identify all spans in hints' array
+
+ lcl_CollectHintSpans(*m_pSwpHints, m_Text.Len(), aAttrSpanMap);
+
+ // 2. Go through all spans and insert new attrs
+
+ AttrSpanMap_iterator_t aCurRange(aAttrSpanMap.begin());
+ const AttrSpanMap_iterator_t aEnd(aAttrSpanMap.end());
+ while (aCurRange != aEnd)
+ {
+ typedef std::pair<AttrSpanMap_iterator_t, AttrSpanMap_iterator_t>
+ AttrSpanMapRange_t;
+ AttrSpanMapRange_t aRange(aAttrSpanMap.equal_range(aCurRange->first));
+
+ // 2a. Collect attributes to insert
+
+ SfxItemSet aCurSet(i_rAttrSet);
+ std::for_each(aRange.first, aRange.second, RemovePresentAttrs(aCurSet));
+
+ // 2b. Insert automatic style containing the collected attributes
+
+ if (aCurSet.Count() != 0)
+ {
+ AttrSpanMap_iterator_t aAutoStyleIt(
+ std::find_if(aRange.first, aRange.second, IsAutoStyle()));
+ if (aAutoStyleIt != aRange.second)
+ {
+ // there already is an automatic style on that span:
+ // create new one and remove the original one
+ SwTxtAttr* const pAutoStyle(const_cast<SwTxtAttr*>(aAutoStyleIt->second));
+ const boost::shared_ptr<SfxItemSet> pOldStyle(
+ static_cast<const SwFmtAutoFmt&>(
+ pAutoStyle->GetAttr()).GetStyleHandle());
+ aCurSet.Put(*pOldStyle);
+
+ // remove the old hint
+ m_pSwpHints->Delete(pAutoStyle);
+ DestroyAttr(pAutoStyle);
+ }
+ m_pSwpHints->Insert(
+ MakeTxtAttr(*GetDoc(), aCurSet,
+ aCurRange->first.first, aCurRange->first.second));
+ }
+
+ aCurRange = aRange.second;
+ }
+
+ // 3. Clear items from the node
+ std::vector<sal_uInt16> aClearedIds;
+ lcl_FillWhichIds(i_rAttrSet, aClearedIds);
+ ClearItemsFromAttrSet(aClearedIds);
+}
+
+void SwTxtNode::FmtToTxtAttr( SwTxtNode* pNd )
+{
+ SfxItemSet aThisSet( GetDoc()->GetAttrPool(), aCharFmtSetRange );
+ if( HasSwAttrSet() && GetpSwAttrSet()->Count() )
+ aThisSet.Put( *GetpSwAttrSet() );
+
+ GetOrCreateSwpHints();
+
+ if( pNd == this )
+ {
+ impl_FmtToTxtAttr(aThisSet);
+ }
+ else
+ {
+ // There are five possible combinations of items from this and
+ // pNd (pNd is the 'main' node):
+ //
+ // case pNd this action
+ // ----------------------------------------------------
+ // 1 - - do nothing
+ // 2 - a convert item to attr of this
+ // 3 a - convert item to attr of pNd
+ // 4 a a clear item in this
+ // 5 a b convert item to attr of this
+
+ SfxItemSet aNdSet( pNd->GetDoc()->GetAttrPool(), aCharFmtSetRange );
+ if( pNd->HasSwAttrSet() && pNd->GetpSwAttrSet()->Count() )
+ aNdSet.Put( *pNd->GetpSwAttrSet() );
+
+ pNd->GetOrCreateSwpHints();
+
+ std::vector<sal_uInt16> aProcessedIds;
+
+ if( aThisSet.Count() )
+ {
+ SfxItemIter aIter( aThisSet );
+ const SfxPoolItem* pItem = aIter.GetCurItem(), *pNdItem = 0;
+ SfxItemSet aConvertSet( GetDoc()->GetAttrPool(), aCharFmtSetRange );
+ std::vector<sal_uInt16> aClearWhichIds;
+
+ while( true )
+ {
+ if( SFX_ITEM_SET == aNdSet.GetItemState( pItem->Which(), sal_False, &pNdItem ) )
+ {
+ if (*pItem == *pNdItem) // 4
+ {
+ aClearWhichIds.push_back( pItem->Which() );
+ }
+ else // 5
+ {
+ aConvertSet.Put(*pItem);
+ }
+ aProcessedIds.push_back(pItem->Which());
+ }
+ else // 2
+ {
+ aConvertSet.Put(*pItem);
+ }
+
+ if( aIter.IsAtEnd() )
+ break;
+ pItem = aIter.NextItem();
+ }
+
+ // 4/ clear items of this that are set with the same value on pNd
+ ClearItemsFromAttrSet( aClearWhichIds );
+
+ // 2, 5/ convert all other items to attrs
+ impl_FmtToTxtAttr(aConvertSet);
+ }
+
+ {
+ std::for_each(aProcessedIds.begin(), aProcessedIds.end(),
+ SfxItemSetClearer(aNdSet));
+
+ // 3/ convert items to attrs
+ pNd->impl_FmtToTxtAttr(aNdSet);
+
+ if( aNdSet.Count() )
+ {
+ SwFmtChg aTmp1( pNd->GetFmtColl() );
+ pNd->NotifyClients( &aTmp1, &aTmp1 );
+ }
+ }
+ }
+
+ SetCalcHiddenCharFlags();
+
+ pNd->TryDeleteSwpHints();
+}
+
+/*************************************************************************
+ * SwpHints::CalcFlags()
+ *************************************************************************/
+
+void SwpHints::CalcFlags()
+{
+ m_bDDEFields = m_bFootnote = false;
+ const sal_uInt16 nSize = Count();
+ const SwTxtAttr* pAttr;
+ for( sal_uInt16 nPos = 0; nPos < nSize; ++nPos )
+ {
+ switch( ( pAttr = (*this)[ nPos ])->Which() )
+ {
+ case RES_TXTATR_FTN:
+ m_bFootnote = true;
+ if ( m_bDDEFields )
+ return;
+ break;
+ case RES_TXTATR_FIELD:
+ {
+ const SwField* pFld = pAttr->GetFld().GetFld();
+ if( RES_DDEFLD == pFld->GetTyp()->Which() )
+ {
+ m_bDDEFields = true;
+ if ( m_bFootnote )
+ return;
+ }
+ }
+ break;
+ }
+ }
+}
+
+/*************************************************************************
+ * SwpHints::CalcVisibleFlag()
+ *************************************************************************/
+
+bool SwpHints::CalcHiddenParaField()
+{
+ m_bCalcHiddenParaField = false;
+ bool bOldHasHiddenParaField = m_bHasHiddenParaField;
+ bool bNewHasHiddenParaField = false;
+ const sal_uInt16 nSize = Count();
+ const SwTxtAttr *pTxtHt;
+
+ for( sal_uInt16 nPos = 0; nPos < nSize; ++nPos )
+ {
+ pTxtHt = (*this)[ nPos ];
+ const sal_uInt16 nWhich = pTxtHt->Which();
+
+ if( RES_TXTATR_FIELD == nWhich )
+ {
+ const SwFmtFld& rFld = pTxtHt->GetFld();
+ if( RES_HIDDENPARAFLD == rFld.GetFld()->GetTyp()->Which() )
+ {
+ if( !((SwHiddenParaField*)rFld.GetFld())->IsHidden() )
+ {
+ SetHiddenParaField(false);
+ return bOldHasHiddenParaField != bNewHasHiddenParaField;
+ }
+ else
+ {
+ bNewHasHiddenParaField = true;
+ }
+ }
+ }
+ }
+ SetHiddenParaField( bNewHasHiddenParaField );
+ return bOldHasHiddenParaField != bNewHasHiddenParaField;
+}
+
+
+/*************************************************************************
+ * SwpHints::NoteInHistory()
+ *************************************************************************/
+
+void SwpHints::NoteInHistory( SwTxtAttr *pAttr, const bool bNew )
+{
+ if ( m_pHistory ) { m_pHistory->AddHint( pAttr, bNew ); }
+}
+
+/*************************************************************************
+ * SwpHints::MergePortions( )
+ *************************************************************************/
+
+bool SwpHints::MergePortions( SwTxtNode& rNode )
+{
+ if ( !Count() )
+ return false;
+
+ // sort before merging
+ SwpHintsArray::Resort();
+
+ bool bRet = false;
+ typedef std::multimap< int, SwTxtAttr* > PortionMap;
+ PortionMap aPortionMap;
+ xub_StrLen nLastPorStart = STRING_LEN;
+ sal_uInt16 i = 0;
+ int nKey = 0;
+
+ // get portions by start position:
+ for ( i = 0; i < Count(); ++i )
+ {
+ SwTxtAttr *pHt = GetTextHint( i );
+ if ( RES_TXTATR_CHARFMT != pHt->Which() &&
+ RES_TXTATR_AUTOFMT != pHt->Which() )
+ //&&
+ //RES_TXTATR_INETFMT != pHt->Which() )
+ continue;
+
+ const xub_StrLen nPorStart = *pHt->GetStart();
+ if ( nPorStart != nLastPorStart && nLastPorStart != STRING_LEN )
+ ++nKey;
+ nLastPorStart = nPorStart;
+ aPortionMap.insert( std::pair< const int, SwTxtAttr* >( nKey, pHt ) );
+ }
+
+ // check if portion i can be merged with portion i+1:
+ i = 0;
+ int j = i + 1;
+ while ( i <= nKey )
+ {
+ std::pair< PortionMap::iterator, PortionMap::iterator > aRange1 = aPortionMap.equal_range( i );
+ std::pair< PortionMap::iterator, PortionMap::iterator > aRange2 = aPortionMap.equal_range( j );
+ PortionMap::iterator aIter1 = aRange1.first;
+ PortionMap::iterator aIter2 = aRange2.first;
+
+ bool bMerge = true;
+ const sal_uInt16 nAttributesInPor1 = static_cast<sal_uInt16>(std::distance( aRange1.first, aRange1.second ));
+ const sal_uInt16 nAttributesInPor2 = static_cast<sal_uInt16>(std::distance( aRange2.first, aRange2.second ));
+
+ if ( nAttributesInPor1 == nAttributesInPor2 && nAttributesInPor1 != 0 )
+ {
+ while ( aIter1 != aRange1.second )
+ {
+ const SwTxtAttr* p1 = (*aIter1).second;
+ const SwTxtAttr* p2 = (*aIter2).second;
+ if ( *p1->GetEnd() < *p2->GetStart() || p1->Which() != p2->Which() || !(*p1 == *p2) )
+ {
+ bMerge = false;
+ break;
+ }
+ ++aIter1;
+ ++aIter2;
+ }
+ }
+ else
+ {
+ bMerge = false;
+ }
+
+ if ( bMerge )
+ {
+ // erase all elements with key i + 1
+ xub_StrLen nNewPortionEnd = 0;
+ for ( aIter2 = aRange2.first; aIter2 != aRange2.second; ++aIter2 )
+ {
+ SwTxtAttr* p2 = (*aIter2).second;
+ nNewPortionEnd = *p2->GetEnd();
+
+ const sal_uInt16 nCountBeforeDelete = Count();
+ Delete( p2 );
+
+ // robust: check if deletion actually took place before destroying attribute:
+ if ( Count() < nCountBeforeDelete )
+ rNode.DestroyAttr( p2 );
+ }
+ aPortionMap.erase( aRange2.first, aRange2.second );
+ ++j;
+
+ // change all attributes with key i
+ aRange1 = aPortionMap.equal_range( i );
+ for ( aIter1 = aRange1.first; aIter1 != aRange1.second; ++aIter1 )
+ {
+ SwTxtAttr* p1 = (*aIter1).second;
+ NoteInHistory( p1 );
+ *p1->GetEnd() = nNewPortionEnd;
+ NoteInHistory( p1, true );
+ bRet = true;
+ }
+ }
+ else
+ {
+ ++i;
+ j = i + 1;
+ }
+ }
+
+ if ( bRet )
+ {
+ SwpHintsArray::Resort();
+ }
+
+ return bRet;
+}
+
+// check if there is already a character format and adjust the sort numbers
+void lcl_CheckSortNumber( const SwpHints& rHints, SwTxtCharFmt& rNewCharFmt )
+{
+ const xub_StrLen nHtStart = *rNewCharFmt.GetStart();
+ const xub_StrLen nHtEnd = *rNewCharFmt.GetEnd();
+ sal_uInt16 nSortNumber = 0;
+
+ for ( sal_uInt16 i = 0; i < rHints.Count(); ++i )
+ {
+ const SwTxtAttr* pOtherHt = rHints[i];
+
+ const xub_StrLen nOtherStart = *pOtherHt->GetStart();
+
+ if ( nOtherStart > nHtStart )
+ break;
+
+ if ( RES_TXTATR_CHARFMT == pOtherHt->Which() )
+ {
+ const xub_StrLen nOtherEnd = *pOtherHt->GetEnd();
+
+ if ( nOtherStart == nHtStart && nOtherEnd == nHtEnd )
+ {
+ const sal_uInt16 nOtherSortNum = static_cast<const SwTxtCharFmt*>(pOtherHt)->GetSortNumber();
+ nSortNumber = nOtherSortNum + 1;
+ }
+ }
+ }
+
+ if ( nSortNumber > 0 )
+ rNewCharFmt.SetSortNumber( nSortNumber );
+}
+
+/*************************************************************************
+ * SwpHints::Insert()
+ *************************************************************************/
+
+/*
+ * Try to insert the new hint.
+ * Depending on the type of the hint, this either always succeeds, or may fail.
+ * Depending on the type of the hint, other hints may be deleted or
+ * overwritten.
+ * The return value indicates successful insertion.
+ */
+bool SwpHints::TryInsertHint( SwTxtAttr* const pHint, SwTxtNode &rNode,
+ const SetAttrMode nMode )
+{
+ if ( USHRT_MAX == Count() ) // we're sorry, this flight is overbooked...
+ {
+ OSL_FAIL("hints array full :-(");
+ return false;
+ }
+
+ // Felder bilden eine Ausnahme:
+ // 1) Sie koennen nie ueberlappen
+ // 2) Wenn zwei Felder genau aneinander liegen,
+ // sollen sie nicht zu einem verschmolzen werden.
+ // Wir koennen also auf die while-Schleife verzichten
+
+ xub_StrLen *pHtEnd = pHint->GetEnd();
+ sal_uInt16 nWhich = pHint->Which();
+
+ switch( nWhich )
+ {
+ case RES_TXTATR_CHARFMT:
+ {
+ // Check if character format contains hidden attribute:
+ const SwCharFmt* pFmt = pHint->GetCharFmt().GetCharFmt();
+ const SfxPoolItem* pItem;
+ if ( SFX_ITEM_SET == pFmt->GetItemState( RES_CHRATR_HIDDEN, sal_True, &pItem ) )
+ rNode.SetCalcHiddenCharFlags();
+
+ ((SwTxtCharFmt*)pHint)->ChgTxtNode( &rNode );
+ break;
+ }
+ // --> FME 2007-03-16 #i75430# Recalc hidden flags if necessary
+ case RES_TXTATR_AUTOFMT:
+ {
+ // Check if auto style contains hidden attribute:
+ const SfxPoolItem* pHiddenItem = CharFmt::GetItem( *pHint, RES_CHRATR_HIDDEN );
+ if ( pHiddenItem )
+ rNode.SetCalcHiddenCharFlags();
+ break;
+ }
+ // <--
+ case RES_TXTATR_INETFMT:
+ static_cast<SwTxtINetFmt*>(pHint)->InitINetFmt(rNode);
+ break;
+ case RES_TXTATR_FIELD:
+ {
+ sal_Bool bDelFirst = 0 != ((SwTxtFld*)pHint)->GetpTxtNode();
+ ((SwTxtFld*)pHint)->ChgTxtNode( &rNode );
+ SwDoc* pDoc = rNode.GetDoc();
+ const SwField* pFld = ((SwTxtFld*)pHint)->GetFld().GetFld();
+
+ if( !pDoc->IsNewFldLst() )
+ {
+ // was fuer ein Feld ist es denn ??
+ // bestimmte Felder mussen am Doc das Calculations-Flag updaten
+ switch( pFld->GetTyp()->Which() )
+ {
+ case RES_DBFLD:
+ case RES_SETEXPFLD:
+ case RES_HIDDENPARAFLD:
+ case RES_HIDDENTXTFLD:
+ case RES_DBNUMSETFLD:
+ case RES_DBNEXTSETFLD:
+ {
+ if( bDelFirst )
+ pDoc->InsDelFldInFldLst( sal_False, *(SwTxtFld*)pHint );
+ if( rNode.GetNodes().IsDocNodes() )
+ pDoc->InsDelFldInFldLst( sal_True, *(SwTxtFld*)pHint );
+ }
+ break;
+ case RES_DDEFLD:
+ if( rNode.GetNodes().IsDocNodes() )
+ ((SwDDEFieldType*)pFld->GetTyp())->IncRefCnt();
+ break;
+ }
+ }
+
+ // gehts ins normale Nodes-Array?
+ if( rNode.GetNodes().IsDocNodes() )
+ {
+ sal_Bool bInsFldType = sal_False;
+ switch( pFld->GetTyp()->Which() )
+ {
+ case RES_SETEXPFLD:
+ bInsFldType = ((SwSetExpFieldType*)pFld->GetTyp())->IsDeleted();
+ if( nsSwGetSetExpType::GSE_SEQ & ((SwSetExpFieldType*)pFld->GetTyp())->GetType() )
+ {
+ // bevor die ReferenzNummer gesetzt wird, sollte
+ // das Feld am richtigen FeldTypen haengen!
+ SwSetExpFieldType* pFldType = (SwSetExpFieldType*)
+ pDoc->InsertFldType( *pFld->GetTyp() );
+ if( pFldType != pFld->GetTyp() )
+ {
+ SwFmtFld* pFmtFld = (SwFmtFld*)&((SwTxtFld*)pHint)
+ ->GetFld();
+ pFmtFld->RegisterToFieldType( *pFldType );
+ pFmtFld->GetFld()->ChgTyp( pFldType );
+ }
+ pFldType->SetSeqRefNo( *(SwSetExpField*)pFld );
+ }
+ break;
+ case RES_USERFLD:
+ bInsFldType = ((SwUserFieldType*)pFld->GetTyp())->IsDeleted();
+ break;
+
+ case RES_DDEFLD:
+ if( pDoc->IsNewFldLst() )
+ ((SwDDEFieldType*)pFld->GetTyp())->IncRefCnt();
+ bInsFldType = ((SwDDEFieldType*)pFld->GetTyp())->IsDeleted();
+ break;
+
+ case RES_POSTITFLD:
+ if ( pDoc->GetDocShell() )
+ pDoc->GetDocShell()->Broadcast( SwFmtFldHint( &((SwTxtFld*)pHint)->GetFld(), SWFMTFLD_INSERTED ) );
+ break;
+ }
+ if( bInsFldType )
+ pDoc->InsDeletedFldType( *pFld->GetTyp() );
+ }
+ }
+ break;
+ case RES_TXTATR_FTN :
+ ((SwTxtFtn*)pHint)->ChgTxtNode( &rNode );
+ break;
+ case RES_TXTATR_REFMARK:
+ ((SwTxtRefMark*)pHint)->ChgTxtNode( &rNode );
+ if( rNode.GetNodes().IsDocNodes() )
+ {
+ // search for a reference with the same name
+ SwTxtAttr* pTmpHt;
+ xub_StrLen *pTmpHtEnd, *pTmpHintEnd;
+ for( sal_uInt16 n = 0, nEnd = Count(); n < nEnd; ++n )
+ {
+ if (RES_TXTATR_REFMARK == (pTmpHt = GetTextHint(n))->Which() &&
+ pHint->GetAttr() == pTmpHt->GetAttr() &&
+ 0 != ( pTmpHtEnd = pTmpHt->GetEnd() ) &&
+ 0 != ( pTmpHintEnd = pHint->GetEnd() ) )
+ {
+ SwComparePosition eCmp = ::ComparePosition(
+ *pTmpHt->GetStart(), *pTmpHtEnd,
+ *pHint->GetStart(), *pTmpHintEnd );
+ sal_Bool bDelOld = sal_True, bChgStart = sal_False, bChgEnd = sal_False;
+ switch( eCmp )
+ {
+ case POS_BEFORE:
+ case POS_BEHIND: bDelOld = sal_False; break;
+
+ case POS_OUTSIDE: bChgStart = bChgEnd = sal_True; break;
+
+ case POS_COLLIDE_END:
+ case POS_OVERLAP_BEFORE: bChgStart = sal_True; break;
+ case POS_COLLIDE_START:
+ case POS_OVERLAP_BEHIND: bChgEnd = sal_True; break;
+ default: break;
+ }
+
+ if( bChgStart )
+ *pHint->GetStart() = *pTmpHt->GetStart();
+ if( bChgEnd )
+ *pTmpHintEnd = *pTmpHtEnd;
+
+ if( bDelOld )
+ {
+ NoteInHistory( pTmpHt );
+ rNode.DestroyAttr( Cut( n-- ) );
+ --nEnd;
+ }
+ }
+ }
+ }
+ break;
+ case RES_TXTATR_TOXMARK:
+ ((SwTxtTOXMark*)pHint)->ChgTxtNode( &rNode );
+ break;
+
+ case RES_TXTATR_CJK_RUBY:
+ static_cast<SwTxtRuby*>(pHint)->InitRuby(rNode);
+ break;
+
+ case RES_TXTATR_META:
+ case RES_TXTATR_METAFIELD:
+ static_cast<SwTxtMeta *>(pHint)->ChgTxtNode( &rNode );
+ break;
+
+ case RES_CHRATR_HIDDEN:
+ rNode.SetCalcHiddenCharFlags();
+ break;
+ }
+
+ if( nsSetAttrMode::SETATTR_DONTEXPAND & nMode )
+ pHint->SetDontExpand( sal_True );
+
+ // SwTxtAttrs ohne Ende werden sonderbehandelt:
+ // Sie werden natuerlich in das Array insertet, aber sie werden nicht
+ // in die pPrev/Next/On/Off-Verkettung aufgenommen.
+ // Der Formatierer erkennt diese TxtHints an dem CH_TXTATR_.. im Text !
+ xub_StrLen nHtStart = *pHint->GetStart();
+ if( !pHtEnd )
+ {
+ SwpHintsArray::Insert( pHint );
+ CalcFlags();
+#if OSL_DEBUG_LEVEL > 1
+ if( !rNode.GetDoc()->IsInReading() )
+ CHECK;
+#endif
+ // ... und die Abhaengigen benachrichtigen
+ if ( rNode.GetDepends() )
+ {
+ SwUpdateAttr aHint( nHtStart, nHtStart, nWhich );
+ rNode.ModifyNotification( 0, &aHint );
+ }
+ return true;
+ }
+
+ // ----------------------------------------------------------------
+ // Ab hier gibt es nur noch pHint mit einem EndIdx !!!
+
+ if( *pHtEnd < nHtStart )
+ {
+ OSL_ENSURE( *pHtEnd >= nHtStart,
+ "+SwpHints::Insert: invalid hint, end < start" );
+
+ // Wir drehen den Quatsch einfach um:
+ *pHint->GetStart() = *pHtEnd;
+ *pHtEnd = nHtStart;
+ nHtStart = *pHint->GetStart();
+ }
+
+ // I need this value later on for notification but the pointer may become invalid
+ const xub_StrLen nHintEnd = *pHtEnd;
+ const bool bNoHintAdjustMode = (nsSetAttrMode::SETATTR_NOHINTADJUST & nMode);
+
+ // handle nesting attributes: inserting may fail due to overlap!
+ if (pHint->IsNesting())
+ {
+ const bool bRet(
+ TryInsertNesting(rNode, *static_cast<SwTxtAttrNesting*>(pHint)));
+ if (!bRet) return false;
+ }
+ // Currently REFMARK and TOXMARK have OverlapAllowed set to true.
+ // These attributes may be inserted directly.
+ // Also attributes without length may be inserted directly.
+ // SETATTR_NOHINTADJUST is set e.g., during undo.
+ // Portion building in not necessary during XML import.
+ else
+ if ( !bNoHintAdjustMode &&
+ !pHint->IsOverlapAllowedAttr() &&
+ !rNode.GetDoc()->IsInXMLImport() &&
+ ( RES_TXTATR_AUTOFMT == nWhich ||
+ RES_TXTATR_CHARFMT == nWhich ) )
+ {
+ OSL_ENSURE( nWhich != RES_TXTATR_AUTOFMT ||
+ static_cast<const SwFmtAutoFmt&>(pHint->GetAttr()).GetStyleHandle()->GetPool() ==
+ &rNode.GetDoc()->GetAttrPool(),
+ "AUTOSTYLES - Pool mismatch" );
+
+ BuildPortions( rNode, *pHint, nMode );
+
+ if ( nHtStart < nHintEnd ) // skip merging for 0-length attributes
+ MergePortions( rNode );
+ }
+ else
+ {
+ // There may be more than one character style at the current position.
+ // Take care of the sort number.
+ // Special case ruby portion: During import, the ruby attribute is set
+ // multiple times
+ // Special case hyperlink: During import, the ruby attribute is set
+ // multiple times
+ // FME 2007-11-08 #i82989# in NOHINTADJUST mode, we want to insert
+ // character attributes directly
+ if ( ( RES_TXTATR_CHARFMT == nWhich && !bNoHintAdjustMode ) )
+ {
+ BuildPortions( rNode, *pHint, nMode );
+ }
+ else
+ {
+ // --> FME 2007-11-08 #i82989# Check sort numbers in NoHintAdjustMode
+ if ( RES_TXTATR_CHARFMT == nWhich )
+ lcl_CheckSortNumber( *this, *static_cast<SwTxtCharFmt*>(pHint) );
+ // <--
+
+ SwpHintsArray::Insert( pHint );
+ NoteInHistory( pHint, true );
+ }
+ }
+
+ // ... und die Abhaengigen benachrichtigen
+ if ( rNode.GetDepends() )
+ {
+ SwUpdateAttr aHint( nHtStart, nHtStart == nHintEnd ? nHintEnd + 1 : nHintEnd, nWhich );
+ rNode.ModifyNotification( 0, &aHint );
+ }
+
+#if OSL_DEBUG_LEVEL > 1
+ if( !bNoHintAdjustMode && !rNode.GetDoc()->IsInReading() )
+ CHECK;
+#endif
+
+ return true;
+}
+
+/*************************************************************************
+ * SwpHints::DeleteAtPos()
+ *************************************************************************/
+
+void SwpHints::DeleteAtPos( const sal_uInt16 nPos )
+{
+ SwTxtAttr *pHint = GetTextHint(nPos);
+ // ChainDelete( pHint );
+ NoteInHistory( pHint );
+ SwpHintsArray::DeleteAtPos( nPos );
+
+ if( RES_TXTATR_FIELD == pHint->Which() )
+ {
+ SwFieldType* pFldTyp = ((SwTxtFld*)pHint)->GetFld().GetFld()->GetTyp();
+ if( RES_DDEFLD == pFldTyp->Which() )
+ {
+ const SwTxtNode* pNd = ((SwTxtFld*)pHint)->GetpTxtNode();
+ if( pNd && pNd->GetNodes().IsDocNodes() )
+ ((SwDDEFieldType*)pFldTyp)->DecRefCnt();
+ ((SwTxtFld*)pHint)->ChgTxtNode( 0 );
+ }
+ else if( RES_POSTITFLD == pFldTyp->Which() )
+ {
+ const_cast<SwFmtFld&>(((SwTxtFld*)pHint)->GetFld()).Broadcast( SwFmtFldHint( &((SwTxtFld*)pHint)->GetFld(), SWFMTFLD_REMOVED ) );
+ }
+ else if ( m_bHasHiddenParaField &&
+ RES_HIDDENPARAFLD == pFldTyp->Which() )
+ {
+ m_bCalcHiddenParaField = true;
+ }
+ }
+
+ CalcFlags();
+ CHECK;
+}
+
+// Ist der Hint schon bekannt, dann suche die Position und loesche ihn.
+// Ist er nicht im Array, so gibt es ein OSL_ENSURE(!!
+
+void SwpHints::Delete( SwTxtAttr* pTxtHt )
+{
+ // Attr 2.0: SwpHintsArr::Delete( pTxtHt );
+ const sal_uInt16 nPos = GetStartOf( pTxtHt );
+ OSL_ENSURE( USHRT_MAX != nPos, "Attribut nicht im Attribut-Array!" );
+ if( USHRT_MAX != nPos )
+ DeleteAtPos( nPos );
+}
+
+void SwTxtNode::ClearSwpHintsArr( bool bDelFields )
+{
+ if ( HasHints() )
+ {
+ sal_uInt16 nPos = 0;
+ while ( nPos < m_pSwpHints->Count() )
+ {
+ SwTxtAttr* pDel = m_pSwpHints->GetTextHint( nPos );
+ bool bDel = false;
+
+ switch( pDel->Which() )
+ {
+ case RES_TXTATR_FLYCNT:
+ case RES_TXTATR_FTN:
+ break;
+
+ case RES_TXTATR_FIELD:
+ if( bDelFields )
+ bDel = true;
+ break;
+ default:
+ bDel = true; break;
+ }
+
+ if( bDel )
+ {
+ m_pSwpHints->SwpHintsArray::DeleteAtPos( nPos );
+ DestroyAttr( pDel );
+ }
+ else
+ ++nPos;
+ }
+ }
+}
+
+sal_uInt16 SwTxtNode::GetLang( const xub_StrLen nBegin, const xub_StrLen nLen,
+ sal_uInt16 nScript ) const
+{
+ sal_uInt16 nRet = LANGUAGE_DONTKNOW;
+
+ if ( ! nScript )
+ {
+ nScript = pBreakIt->GetRealScriptOfText( m_Text, nBegin );
+ }
+
+ // --> FME 2008-09-29 #i91465# hennerdrewes: Consider nScript if pSwpHints == 0
+ const sal_uInt16 nWhichId = GetWhichOfScript( RES_CHRATR_LANGUAGE, nScript );
+ // <--
+
+ if ( HasHints() )
+ {
+ const xub_StrLen nEnd = nBegin + nLen;
+ for ( sal_uInt16 i = 0, nSize = m_pSwpHints->Count(); i < nSize; ++i )
+ {
+ // ist der Attribut-Anfang schon groesser als der Idx ?
+ const SwTxtAttr *pHt = m_pSwpHints->operator[](i);
+ const xub_StrLen nAttrStart = *pHt->GetStart();
+ if( nEnd < nAttrStart )
+ break;
+
+ const sal_uInt16 nWhich = pHt->Which();
+
+ if( nWhichId == nWhich ||
+ ( ( pHt->IsCharFmtAttr() || RES_TXTATR_AUTOFMT == nWhich ) && CharFmt::IsItemIncluded( nWhichId, pHt ) ) )
+ {
+ const xub_StrLen *pEndIdx = pHt->GetEnd();
+ // Ueberlappt das Attribut den Bereich?
+
+ if( pEndIdx &&
+ nLen ? ( nAttrStart < nEnd && nBegin < *pEndIdx )
+ : (( nAttrStart < nBegin &&
+ ( pHt->DontExpand() ? nBegin < *pEndIdx
+ : nBegin <= *pEndIdx )) ||
+ ( nBegin == nAttrStart &&
+ ( nAttrStart == *pEndIdx || !nBegin ))) )
+ {
+ const SfxPoolItem* pItem = CharFmt::GetItem( *pHt, nWhichId );
+ sal_uInt16 nLng = ((SvxLanguageItem*)pItem)->GetLanguage();
+
+ // Umfasst das Attribut den Bereich komplett?
+ if( nAttrStart <= nBegin && nEnd <= *pEndIdx )
+ nRet = nLng;
+ else if( LANGUAGE_DONTKNOW == nRet )
+ nRet = nLng; // partielle Ueberlappung, der 1. gewinnt
+ }
+ }
+ }
+ }
+ if( LANGUAGE_DONTKNOW == nRet )
+ {
+ nRet = ((SvxLanguageItem&)GetSwAttrSet().Get( nWhichId )).GetLanguage();
+ if( LANGUAGE_DONTKNOW == nRet )
+ nRet = static_cast<sal_uInt16>(GetAppLanguage());
+ }
+ return nRet;
+}
+
+
+sal_Unicode GetCharOfTxtAttr( const SwTxtAttr& rAttr )
+{
+ sal_Unicode cRet = CH_TXTATR_BREAKWORD;
+ switch ( rAttr.Which() )
+ {
+ case RES_TXTATR_FTN:
+ case RES_TXTATR_REFMARK:
+ case RES_TXTATR_TOXMARK:
+ case RES_TXTATR_META:
+ case RES_TXTATR_METAFIELD:
+ cRet = CH_TXTATR_INWORD;
+ break;
+
+ case RES_TXTATR_FIELD:
+ case RES_TXTATR_FLYCNT:
+ {
+ cRet = CH_TXTATR_BREAKWORD;
+
+ // #i78149: PostIt fields should not break words for spell and grammar checking
+ if (rAttr.Which() == RES_TXTATR_FIELD &&
+ RES_POSTITFLD == rAttr.GetFld().GetFld()->GetTyp()->Which())
+ cRet = CH_TXTATR_INWORD;
+ }
+ break;
+
+ default:
+ OSL_FAIL("GetCharOfTxtAttr: unknown attr");
+ break;
+ }
+ return cRet;
+}
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/txtnode/txatbase.cxx b/sw/source/core/txtnode/txatbase.cxx
new file mode 100644
index 000000000000..ae370d5afe42
--- /dev/null
+++ b/sw/source/core/txtnode/txatbase.cxx
@@ -0,0 +1,86 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+
+#include <svl/itempool.hxx>
+#include <txatbase.hxx>
+#include <fmtfld.hxx>
+#include <docufld.hxx>
+
+SwTxtAttr::SwTxtAttr( SfxPoolItem& rAttr, xub_StrLen nStart )
+ : m_pAttr( &rAttr )
+ , m_nStart( nStart )
+ , m_bDontExpand( false )
+ , m_bLockExpandFlag( false )
+ , m_bDontMoveAttr( false )
+ , m_bCharFmtAttr( false )
+ , m_bOverlapAllowedAttr( false )
+ , m_bPriorityAttr( false )
+ , m_bDontExpandStart( false )
+ , m_bNesting( false )
+ , m_bHasDummyChar( false )
+{
+}
+
+SwTxtAttr::~SwTxtAttr( )
+{
+}
+
+xub_StrLen* SwTxtAttr::GetEnd()
+{
+ return 0;
+}
+
+void SwTxtAttr::Destroy( SwTxtAttr * pToDestroy, SfxItemPool& rPool )
+{
+ if (!pToDestroy) return;
+ SfxPoolItem * const pAttr = pToDestroy->m_pAttr;
+ delete pToDestroy;
+ rPool.Remove( *pAttr );
+}
+
+int SwTxtAttr::operator==( const SwTxtAttr& rAttr ) const
+{
+ return GetAttr() == rAttr.GetAttr();
+}
+
+SwTxtAttrEnd::SwTxtAttrEnd( SfxPoolItem& rAttr,
+ xub_StrLen nStart, xub_StrLen nEnd ) :
+ SwTxtAttr( rAttr, nStart ), m_nEnd( nEnd )
+{
+}
+
+xub_StrLen* SwTxtAttrEnd::GetEnd()
+{
+ return & m_nEnd;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/txtnode/txatritr.cxx b/sw/source/core/txtnode/txatritr.cxx
new file mode 100644
index 000000000000..5bbab28687ce
--- /dev/null
+++ b/sw/source/core/txtnode/txatritr.cxx
@@ -0,0 +1,246 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+
+#include <hintids.hxx>
+
+#include <com/sun/star/i18n/ScriptType.hdl>
+#include <tools/string.hxx>
+#include <editeng/langitem.hxx>
+#include <txatritr.hxx>
+#include <fchrfmt.hxx>
+#include <charfmt.hxx>
+#include <breakit.hxx>
+#include <ndtxt.hxx>
+#include <txatbase.hxx>
+
+using namespace ::com::sun::star::i18n;
+
+
+SwScriptIterator::SwScriptIterator( const String& rStr, xub_StrLen nStt, sal_Bool bFrwrd )
+ : rText( rStr ),
+ nChgPos( rStr.Len() ),
+ nCurScript( ScriptType::WEAK ),
+ bForward( bFrwrd )
+{
+ if( pBreakIt->GetBreakIter().is() )
+ {
+ if ( ! bFrwrd && nStt )
+ --nStt;
+
+ xub_StrLen nPos = nStt;
+ nCurScript = pBreakIt->GetBreakIter()->getScriptType( rText, nPos );
+ if( ScriptType::WEAK == nCurScript )
+ {
+ if( nPos )
+ {
+ nPos = (xub_StrLen)pBreakIt->GetBreakIter()->beginOfScript(
+ rText, nPos, nCurScript );
+ if( nPos && nPos < rText.Len() )
+ {
+ nStt = --nPos;
+ nCurScript = pBreakIt->GetBreakIter()->getScriptType( rText,nPos);
+ }
+ }
+ }
+
+ nChgPos = bForward ?
+ (xub_StrLen)pBreakIt->GetBreakIter()->endOfScript( rText, nStt, nCurScript ) :
+ (xub_StrLen)pBreakIt->GetBreakIter()->beginOfScript( rText, nStt, nCurScript );
+ }
+}
+
+sal_Bool SwScriptIterator::Next()
+{
+ sal_Bool bRet = sal_False;
+ if( pBreakIt->GetBreakIter().is() )
+ {
+ if ( bForward && nChgPos < rText.Len() )
+ {
+ nCurScript = pBreakIt->GetBreakIter()->getScriptType( rText, nChgPos );
+ nChgPos = (xub_StrLen)pBreakIt->GetBreakIter()->endOfScript(
+ rText, nChgPos, nCurScript );
+ bRet = sal_True;
+ }
+ else if ( ! bForward && nChgPos )
+ {
+ --nChgPos;
+ nCurScript = pBreakIt->GetBreakIter()->getScriptType( rText, nChgPos );
+ nChgPos = (xub_StrLen)pBreakIt->GetBreakIter()->beginOfScript(
+ rText, nChgPos, nCurScript );
+ bRet = sal_True;
+ }
+ }
+ else
+ nChgPos = rText.Len();
+ return bRet;
+}
+
+// --------------------------------------------------------------------
+
+SwTxtAttrIterator::SwTxtAttrIterator( const SwTxtNode& rTNd, sal_uInt16 nWhchId,
+ xub_StrLen nStt,
+ sal_Bool bUseGetWhichOfScript )
+ : aSIter( rTNd.GetTxt(), nStt ), rTxtNd( rTNd ),
+ pParaItem( 0 ), nChgPos( nStt ), nAttrPos( 0 ), nWhichId( nWhchId ),
+ bIsUseGetWhichOfScript( bUseGetWhichOfScript )
+{
+ SearchNextChg();
+}
+
+sal_Bool SwTxtAttrIterator::Next()
+{
+ sal_Bool bRet = sal_False;
+ if( nChgPos < aSIter.GetText().Len() )
+ {
+ bRet = sal_True;
+ if( aStack.Count() )
+ {
+ do {
+ const SwTxtAttr* pHt = (SwTxtAttr*)aStack[ 0 ];
+ sal_uInt16 nEndPos = *pHt->GetEnd();
+ if( nChgPos >= nEndPos )
+ aStack.Remove( 0 );
+ else
+ break;
+ } while( aStack.Count() );
+ }
+
+ if( aStack.Count() )
+ {
+ sal_uInt16 nSavePos = nAttrPos;
+ SearchNextChg();
+ if( aStack.Count() )
+ {
+ const SwTxtAttr* pHt = (SwTxtAttr*)aStack[ 0 ];
+ sal_uInt16 nEndPos = *pHt->GetEnd();
+ if( nChgPos >= nEndPos )
+ {
+ nChgPos = nEndPos;
+ nAttrPos = nSavePos;
+
+ if( RES_TXTATR_CHARFMT == pHt->Which() )
+ {
+ sal_uInt16 nWId = bIsUseGetWhichOfScript ?
+ GetWhichOfScript( nWhichId,
+ aSIter.GetCurrScript() ) : nWhichId;
+ pCurItem = &pHt->GetCharFmt().GetCharFmt()->GetFmtAttr(nWId);
+ }
+ else
+ pCurItem = &pHt->GetAttr();
+
+ aStack.Remove( 0 );
+ }
+ }
+ }
+ else
+ SearchNextChg();
+ }
+ return bRet;
+}
+
+void SwTxtAttrIterator::AddToStack( const SwTxtAttr& rAttr )
+{
+ void* pAdd = (void*)&rAttr;
+ sal_uInt16 nIns = 0, nEndPos = *rAttr.GetEnd();
+ for( ; nIns < aStack.Count(); ++nIns )
+ if( *((SwTxtAttr*)aStack[ nIns ] )->GetEnd() > nEndPos )
+ break;
+
+ aStack.Insert( pAdd, nIns );
+}
+
+void SwTxtAttrIterator::SearchNextChg()
+{
+ sal_uInt16 nWh = 0;
+ if( nChgPos == aSIter.GetScriptChgPos() )
+ {
+ aSIter.Next();
+ pParaItem = 0;
+ nAttrPos = 0; // must be restart at the beginning, because
+ // some attributes can start before or inside
+ // the current scripttype!
+ aStack.Remove( 0, aStack.Count() );
+ }
+ if( !pParaItem )
+ {
+ nWh = bIsUseGetWhichOfScript ?
+ GetWhichOfScript( nWhichId,
+ aSIter.GetCurrScript() ) : nWhichId;
+ pParaItem = &rTxtNd.GetSwAttrSet().Get( nWh );
+ }
+
+ xub_StrLen nStt = nChgPos;
+ nChgPos = aSIter.GetScriptChgPos();
+ pCurItem = pParaItem;
+
+ const SwpHints* pHts = rTxtNd.GetpSwpHints();
+ if( pHts )
+ {
+ if( !nWh )
+ {
+ nWh = bIsUseGetWhichOfScript ?
+ GetWhichOfScript( nWhichId,
+ aSIter.GetCurrScript() ) : nWhichId;
+ }
+
+ const SfxPoolItem* pItem = 0;
+ for( ; nAttrPos < pHts->Count(); ++nAttrPos )
+ {
+ const SwTxtAttr* pHt = (*pHts)[ nAttrPos ];
+ const sal_uInt16* pEnd = pHt->GetEnd();
+ const sal_uInt16 nHtStt = *pHt->GetStart();
+ if( nHtStt < nStt && ( !pEnd || *pEnd <= nStt ))
+ continue;
+
+ if( nHtStt >= nChgPos )
+ break;
+
+ pItem = CharFmt::GetItem( *pHt, nWh );
+ if ( pItem )
+ {
+ if( nHtStt > nStt )
+ {
+ if( nChgPos > nHtStt )
+ nChgPos = nHtStt;
+ break;
+ }
+ AddToStack( *pHt );
+ pCurItem = pItem;
+ if( *pEnd < nChgPos )
+ nChgPos = *pEnd;
+ }
+ }
+ }
+}
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/txtnode/txtatr2.cxx b/sw/source/core/txtnode/txtatr2.cxx
new file mode 100644
index 000000000000..5db0ab4b6f4a
--- /dev/null
+++ b/sw/source/core/txtnode/txtatr2.cxx
@@ -0,0 +1,353 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+#include <hintids.hxx>
+#include <hints.hxx>
+#include <sfx2/objsh.hxx>
+#include <editeng/xmlcnitm.hxx>
+#include <editeng/twolinesitem.hxx>
+#include <txtinet.hxx>
+#include <txtatr.hxx>
+#include <fchrfmt.hxx>
+#include <fmtinfmt.hxx>
+#include <charfmt.hxx>
+#include <ndtxt.hxx> // SwCharFmt, SwTxtNode
+#include <poolfmt.hxx> // RES_POOLCHR_INET_...
+#include <doc.hxx> // SwDoc
+#include <fmtruby.hxx>
+#include <fmtmeta.hxx>
+
+
+TYPEINIT1(SwTxtINetFmt,SwClient);
+TYPEINIT1(SwTxtRuby,SwClient);
+
+
+/*************************************************************************
+ * class SwTxtCharFmt
+ *************************************************************************/
+
+SwTxtCharFmt::SwTxtCharFmt( SwFmtCharFmt& rAttr,
+ xub_StrLen nStt, xub_StrLen nEnde )
+ : SwTxtAttrEnd( rAttr, nStt, nEnde )
+ , m_pTxtNode( 0 )
+ , m_nSortNumber( 0 )
+{
+ rAttr.pTxtAttr = this;
+ SetCharFmtAttr( sal_True );
+}
+
+SwTxtCharFmt::~SwTxtCharFmt( )
+{
+}
+
+void SwTxtCharFmt::ModifyNotification( const SfxPoolItem* pOld, const SfxPoolItem* pNew )
+{
+ sal_uInt16 nWhich = pOld ? pOld->Which() : pNew ? pNew->Which() : 0;
+ OSL_ENSURE( isCHRATR(nWhich) || (RES_OBJECTDYING == nWhich)
+ || (RES_ATTRSET_CHG == nWhich) || (RES_FMT_CHG == nWhich),
+ "SwTxtCharFmt::Modify(): unknown Modify");
+
+ if ( m_pTxtNode )
+ {
+ SwUpdateAttr aUpdateAttr( *GetStart(), *GetEnd(), nWhich );
+ m_pTxtNode->ModifyNotification( &aUpdateAttr, &aUpdateAttr );
+ }
+}
+
+bool SwTxtCharFmt::GetInfo( SfxPoolItem& rInfo ) const
+{
+ if ( RES_AUTOFMT_DOCNODE != rInfo.Which() || !m_pTxtNode ||
+ &m_pTxtNode->GetNodes() != static_cast<SwAutoFmtGetDocNode&>(rInfo).pNodes )
+ {
+ return true;
+ }
+
+ static_cast<SwAutoFmtGetDocNode&>(rInfo).pCntntNode = m_pTxtNode;
+ return false;
+}
+
+
+/*************************************************************************
+ * class SwTxtAttrNesting
+ *************************************************************************/
+
+SwTxtAttrNesting::SwTxtAttrNesting( SfxPoolItem & i_rAttr,
+ const xub_StrLen i_nStart, const xub_StrLen i_nEnd )
+ : SwTxtAttrEnd( i_rAttr, i_nStart, i_nEnd )
+{
+ SetDontExpand( true ); // never expand this attribute
+ // lock the expand flag: simple guarantee that nesting will not be
+ // invalidated by expand operations
+ SetLockExpandFlag( true );
+ SetDontExpandStartAttr( true );
+ SetNesting( true );
+}
+
+SwTxtAttrNesting::~SwTxtAttrNesting()
+{
+}
+
+
+/*************************************************************************
+ * class SwTxtINetFmt
+ *************************************************************************/
+
+SwTxtINetFmt::SwTxtINetFmt( SwFmtINetFmt& rAttr,
+ xub_StrLen nStart, xub_StrLen nEnd )
+ : SwTxtAttrNesting( rAttr, nStart, nEnd )
+ , SwClient( 0 )
+ , m_pTxtNode( 0 )
+ , m_bVisited( false )
+ , m_bVisitedValid( false )
+{
+ rAttr.pTxtAttr = this;
+ SetCharFmtAttr( true );
+}
+
+SwTxtINetFmt::~SwTxtINetFmt( )
+{
+}
+
+SwCharFmt* SwTxtINetFmt::GetCharFmt()
+{
+ const SwFmtINetFmt& rFmt = SwTxtAttrEnd::GetINetFmt();
+ SwCharFmt* pRet = NULL;
+
+ if( rFmt.GetValue().Len() )
+ {
+ const SwDoc* pDoc = GetTxtNode().GetDoc();
+ if( !IsVisitedValid() )
+ {
+ SetVisited( pDoc->IsVisitedURL( rFmt.GetValue() ) );
+ SetVisitedValid( true );
+ }
+ sal_uInt16 nId;
+ const String& rStr = IsVisited() ? rFmt.GetVisitedFmt()
+ : rFmt.GetINetFmt();
+ if( rStr.Len() )
+ nId = IsVisited() ? rFmt.GetVisitedFmtId() : rFmt.GetINetFmtId();
+ else
+ nId = static_cast<sal_uInt16>(IsVisited() ? RES_POOLCHR_INET_VISIT : RES_POOLCHR_INET_NORMAL);
+
+ // JP 10.02.2000, Bug 72806: dont modify the doc for getting the
+ // correct charstyle.
+ sal_Bool bResetMod = !pDoc->IsModified();
+ Link aOle2Lnk;
+ if( bResetMod )
+ {
+ aOle2Lnk = pDoc->GetOle2Link();
+ ((SwDoc*)pDoc)->SetOle2Link( Link() );
+ }
+
+ pRet = IsPoolUserFmt( nId )
+ ? ((SwDoc*)pDoc)->FindCharFmtByName( rStr )
+ : ((SwDoc*)pDoc)->GetCharFmtFromPool( nId );
+
+ if( bResetMod )
+ {
+ ((SwDoc*)pDoc)->ResetModified();
+ ((SwDoc*)pDoc)->SetOle2Link( aOle2Lnk );
+ }
+ }
+
+ if( pRet )
+ pRet->Add( this );
+ else if( GetRegisteredIn() )
+ GetRegisteredInNonConst()->Remove( this );
+
+ return pRet;
+}
+
+void SwTxtINetFmt::Modify( const SfxPoolItem* pOld, const SfxPoolItem* pNew )
+{
+ sal_uInt16 nWhich = pOld ? pOld->Which() : pNew ? pNew->Which() : 0;
+ OSL_ENSURE( isCHRATR(nWhich) || (RES_OBJECTDYING == nWhich)
+ || (RES_ATTRSET_CHG == nWhich) || (RES_FMT_CHG == nWhich),
+ "SwTxtINetFmt::Modify(): unknown Modify");
+
+ if ( m_pTxtNode )
+ {
+ SwUpdateAttr aUpdateAttr( *GetStart(), *GetEnd(), nWhich );
+ m_pTxtNode->ModifyNotification( &aUpdateAttr, &aUpdateAttr );
+ }
+}
+
+ // erfrage vom Modify Informationen
+sal_Bool SwTxtINetFmt::GetInfo( SfxPoolItem& rInfo ) const
+{
+ if ( RES_AUTOFMT_DOCNODE != rInfo.Which() || !m_pTxtNode ||
+ &m_pTxtNode->GetNodes() != static_cast<SwAutoFmtGetDocNode&>(rInfo).pNodes )
+ {
+ return sal_True;
+ }
+
+ static_cast<SwAutoFmtGetDocNode&>(rInfo).pCntntNode = m_pTxtNode;
+ return sal_False;
+}
+
+sal_Bool SwTxtINetFmt::IsProtect( ) const
+{
+ return m_pTxtNode && m_pTxtNode->IsProtect();
+}
+
+/*************************************************************************
+ * class SwTxtRuby
+ *************************************************************************/
+
+SwTxtRuby::SwTxtRuby( SwFmtRuby& rAttr,
+ xub_StrLen nStart, xub_StrLen nEnd )
+ : SwTxtAttrNesting( rAttr, nStart, nEnd )
+ , SwClient( 0 )
+ , m_pTxtNode( 0 )
+{
+ rAttr.pTxtAttr = this;
+}
+
+SwTxtRuby::~SwTxtRuby()
+{
+}
+
+void SwTxtRuby::Modify( const SfxPoolItem* pOld, const SfxPoolItem *pNew )
+{
+ sal_uInt16 nWhich = pOld ? pOld->Which() : pNew ? pNew->Which() : 0;
+ OSL_ENSURE( isCHRATR(nWhich) || (RES_OBJECTDYING == nWhich)
+ || (RES_ATTRSET_CHG == nWhich) || (RES_FMT_CHG == nWhich),
+ "SwTxtRuby::Modify(): unknown Modify");
+
+ if ( m_pTxtNode )
+ {
+ SwUpdateAttr aUpdateAttr( *GetStart(), *GetEnd(), nWhich );
+ m_pTxtNode->ModifyNotification( &aUpdateAttr, &aUpdateAttr );
+ }
+}
+
+sal_Bool SwTxtRuby::GetInfo( SfxPoolItem& rInfo ) const
+{
+ if( RES_AUTOFMT_DOCNODE != rInfo.Which() || !m_pTxtNode ||
+ &m_pTxtNode->GetNodes() != static_cast<SwAutoFmtGetDocNode&>(rInfo).pNodes )
+ {
+ return sal_True;
+ }
+
+ static_cast<SwAutoFmtGetDocNode&>(rInfo).pCntntNode = m_pTxtNode;
+ return sal_False;
+}
+
+SwCharFmt* SwTxtRuby::GetCharFmt()
+{
+ const SwFmtRuby& rFmt = SwTxtAttrEnd::GetRuby();
+ SwCharFmt* pRet = 0;
+
+ if( rFmt.GetText().Len() )
+ {
+ const SwDoc* pDoc = GetTxtNode().GetDoc();
+ const String& rStr = rFmt.GetCharFmtName();
+ sal_uInt16 nId = RES_POOLCHR_RUBYTEXT;
+ if ( rStr.Len() )
+ nId = rFmt.GetCharFmtId();
+
+ // JP 10.02.2000, Bug 72806: dont modify the doc for getting the
+ // correct charstyle.
+ sal_Bool bResetMod = !pDoc->IsModified();
+ Link aOle2Lnk;
+ if( bResetMod )
+ {
+ aOle2Lnk = pDoc->GetOle2Link();
+ ((SwDoc*)pDoc)->SetOle2Link( Link() );
+ }
+
+ pRet = IsPoolUserFmt( nId )
+ ? ((SwDoc*)pDoc)->FindCharFmtByName( rStr )
+ : ((SwDoc*)pDoc)->GetCharFmtFromPool( nId );
+
+ if( bResetMod )
+ {
+ ((SwDoc*)pDoc)->ResetModified();
+ ((SwDoc*)pDoc)->SetOle2Link( aOle2Lnk );
+ }
+ }
+
+ if( pRet )
+ pRet->Add( this );
+ else if( GetRegisteredIn() )
+ GetRegisteredInNonConst()->Remove( this );
+
+ return pRet;
+}
+
+
+/*************************************************************************
+ * class SwTxtMeta
+ *************************************************************************/
+
+SwTxtMeta *
+SwTxtMeta::CreateTxtMeta(
+ ::sw::MetaFieldManager & i_rTargetDocManager,
+ SwTxtNode *const i_pTargetTxtNode,
+ SwFmtMeta & i_rAttr,
+ xub_StrLen const i_nStart, xub_StrLen const i_nEnd, bool const i_bIsCopy)
+{
+ if (COPY == i_bIsCopy)
+ { // i_rAttr is already cloned, now call DoCopy to copy the sw::Meta
+ OSL_ENSURE(i_pTargetTxtNode, "cannot copy Meta without target node");
+ i_rAttr.DoCopy(i_rTargetDocManager, *i_pTargetTxtNode);
+ }
+ SwTxtMeta *const pTxtMeta(new SwTxtMeta(i_rAttr, i_nStart, i_nEnd));
+ return pTxtMeta;
+}
+
+SwTxtMeta::SwTxtMeta( SwFmtMeta & i_rAttr,
+ const xub_StrLen i_nStart, const xub_StrLen i_nEnd )
+ : SwTxtAttrNesting( i_rAttr, i_nStart, i_nEnd )
+{
+ i_rAttr.SetTxtAttr( this );
+ SetHasDummyChar(true);
+}
+
+SwTxtMeta::~SwTxtMeta()
+{
+ SwFmtMeta & rFmtMeta( static_cast<SwFmtMeta &>(GetAttr()) );
+ if (rFmtMeta.GetTxtAttr() == this)
+ {
+ rFmtMeta.SetTxtAttr(0);
+ }
+}
+
+void SwTxtMeta::ChgTxtNode(SwTxtNode * const pNode)
+{
+ SwFmtMeta & rFmtMeta( static_cast<SwFmtMeta &>(GetAttr()) );
+ if (rFmtMeta.GetTxtAttr() == this)
+ {
+ rFmtMeta.NotifyChangeTxtNode(pNode);
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/txtnode/txtedt.cxx b/sw/source/core/txtnode/txtedt.cxx
new file mode 100644
index 000000000000..917ae6c83068
--- /dev/null
+++ b/sw/source/core/txtnode/txtedt.cxx
@@ -0,0 +1,2123 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+#include <hintids.hxx>
+#include <vcl/svapp.hxx>
+#include <svl/itemiter.hxx>
+#include <editeng/splwrap.hxx>
+#include <editeng/langitem.hxx>
+#include <editeng/fontitem.hxx>
+#include <editeng/scripttypeitem.hxx>
+#include <editeng/hangulhanja.hxx>
+#include <SwSmartTagMgr.hxx>
+#include <linguistic/lngprops.hxx>
+#include <unotools/transliterationwrapper.hxx>
+#include <unotools/charclass.hxx>
+#include <dlelstnr.hxx>
+#include <swmodule.hxx>
+#include <splargs.hxx>
+#include <viewopt.hxx>
+#include <acmplwrd.hxx>
+#include <doc.hxx> // GetDoc()
+#include <docsh.hxx>
+#include <txtfld.hxx>
+#include <fmtfld.hxx>
+#include <txatbase.hxx>
+#include <charatr.hxx>
+#include <fldbas.hxx>
+#include <pam.hxx>
+#include <hints.hxx>
+#include <ndtxt.hxx>
+#include <txtfrm.hxx>
+#include <SwGrammarMarkUp.hxx>
+
+#include <txttypes.hxx>
+#include <breakit.hxx>
+#include <crstate.hxx>
+#include <UndoOverwrite.hxx>
+#include <txatritr.hxx>
+#include <redline.hxx> // SwRedline
+#include <docary.hxx> // SwRedlineTbl
+#include <scriptinfo.hxx>
+#include <docstat.hxx>
+#include <editsh.hxx>
+#include <unotextmarkup.hxx>
+#include <txtatr.hxx>
+#include <fmtautofmt.hxx>
+#include <istyleaccess.hxx>
+
+#include <unomid.h>
+
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/i18n/WordType.hdl>
+#include <com/sun/star/i18n/ScriptType.hdl>
+#include <com/sun/star/i18n/TransliterationModules.hpp>
+#include <com/sun/star/i18n/TransliterationModulesExtra.hpp>
+
+#include <vector>
+
+using rtl::OUString;
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::frame;
+using namespace ::com::sun::star::i18n;
+using namespace ::com::sun::star::beans;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::linguistic2;
+using namespace ::com::sun::star::smarttags;
+
+// Wir ersparen uns in Hyphenate ein GetFrm()
+// Achtung: in edlingu.cxx stehen die Variablen!
+extern const SwTxtNode *pLinguNode;
+extern SwTxtFrm *pLinguFrm;
+
+bool lcl_IsSkippableWhiteSpace( xub_Unicode cCh )
+{
+ return 0x3000 == cCh ||
+ ' ' == cCh ||
+ '\t' == cCh ||
+ 0x0a == cCh;
+}
+
+/*
+ * This has basically the same function as SwScriptInfo::MaskHiddenRanges,
+ * only for deleted redlines
+ */
+
+sal_uInt16 lcl_MaskRedlines( const SwTxtNode& rNode, XubString& rText,
+ const xub_StrLen nStt, const xub_StrLen nEnd,
+ const xub_Unicode cChar )
+{
+ sal_uInt16 nNumOfMaskedRedlines = 0;
+
+ const SwDoc& rDoc = *rNode.GetDoc();
+ sal_uInt16 nAct = rDoc.GetRedlinePos( rNode, USHRT_MAX );
+
+ for ( ; nAct < rDoc.GetRedlineTbl().Count(); nAct++ )
+ {
+ const SwRedline* pRed = rDoc.GetRedlineTbl()[ nAct ];
+
+ if ( pRed->Start()->nNode > rNode.GetIndex() )
+ break;
+
+ if( nsRedlineType_t::REDLINE_DELETE == pRed->GetType() )
+ {
+ xub_StrLen nRedlineEnd;
+ xub_StrLen nRedlineStart;
+
+ pRed->CalcStartEnd( rNode.GetIndex(), nRedlineStart, nRedlineEnd );
+
+ if ( nRedlineEnd < nStt || nRedlineStart > nEnd )
+ continue;
+
+ while ( nRedlineStart < nRedlineEnd && nRedlineStart < nEnd )
+ {
+ if ( nRedlineStart >= nStt && nRedlineStart < nEnd )
+ {
+ rText.SetChar( nRedlineStart, cChar );
+ ++nNumOfMaskedRedlines;
+ }
+ ++nRedlineStart;
+ }
+ }
+ }
+
+ return nNumOfMaskedRedlines;
+}
+
+/*
+ * Used for spell checking. Deleted redlines and hidden characters are masked
+ */
+
+sal_uInt16 lcl_MaskRedlinesAndHiddenText( const SwTxtNode& rNode, XubString& rText,
+ const xub_StrLen nStt, const xub_StrLen nEnd,
+ const xub_Unicode cChar = CH_TXTATR_INWORD,
+ bool bCheckShowHiddenChar = true )
+{
+ sal_uInt16 nRedlinesMasked = 0;
+ sal_uInt16 nHiddenCharsMasked = 0;
+
+ const SwDoc& rDoc = *rNode.GetDoc();
+ const bool bShowChg = 0 != IDocumentRedlineAccess::IsShowChanges( rDoc.GetRedlineMode() );
+
+ // If called from word count or from spell checking, deleted redlines
+ // should be masked:
+ if ( bShowChg )
+ {
+ nRedlinesMasked = lcl_MaskRedlines( rNode, rText, nStt, nEnd, cChar );
+ }
+
+ const bool bHideHidden = !SW_MOD()->GetViewOption(rDoc.get(IDocumentSettingAccess::HTML_MODE))->IsShowHiddenChar();
+
+ // If called from word count, we want to mask the hidden ranges even
+ // if they are visible:
+ if ( !bCheckShowHiddenChar || bHideHidden )
+ {
+ nHiddenCharsMasked =
+ SwScriptInfo::MaskHiddenRanges( rNode, rText, nStt, nEnd, cChar );
+ }
+
+ return nRedlinesMasked + nHiddenCharsMasked;
+}
+
+/*
+ * Used for spell checking. Calculates a rectangle for repaint.
+ */
+
+static SwRect lcl_CalculateRepaintRect( SwTxtFrm& rTxtFrm, xub_StrLen nChgStart, xub_StrLen nChgEnd )
+{
+ SwRect aRect;
+
+ SwTxtNode *pNode = rTxtFrm.GetTxtNode();
+
+ SwNodeIndex aNdIdx( *pNode );
+ SwPosition aPos( aNdIdx, SwIndex( pNode, nChgEnd ) );
+ SwCrsrMoveState aTmpState( MV_NONE );
+ aTmpState.b2Lines = sal_True;
+ rTxtFrm.GetCharRect( aRect, aPos, &aTmpState );
+ // information about end of repaint area
+ Sw2LinesPos* pEnd2Pos = aTmpState.p2Lines;
+
+ const SwTxtFrm *pEndFrm = &rTxtFrm;
+
+ while( pEndFrm->HasFollow() &&
+ nChgEnd >= pEndFrm->GetFollow()->GetOfst() )
+ pEndFrm = pEndFrm->GetFollow();
+
+ if ( pEnd2Pos )
+ {
+ // we are inside a special portion, take left border
+ SWRECTFN( pEndFrm )
+ (aRect.*fnRect->fnSetTop)( (pEnd2Pos->aLine.*fnRect->fnGetTop)() );
+ if ( pEndFrm->IsRightToLeft() )
+ (aRect.*fnRect->fnSetLeft)( (pEnd2Pos->aPortion.*fnRect->fnGetLeft)() );
+ else
+ (aRect.*fnRect->fnSetLeft)( (pEnd2Pos->aPortion.*fnRect->fnGetRight)() );
+ (aRect.*fnRect->fnSetWidth)( 1 );
+ (aRect.*fnRect->fnSetHeight)( (pEnd2Pos->aLine.*fnRect->fnGetHeight)() );
+ delete pEnd2Pos;
+ }
+
+ aTmpState.p2Lines = NULL;
+ SwRect aTmp;
+ aPos = SwPosition( aNdIdx, SwIndex( pNode, nChgStart ) );
+ rTxtFrm.GetCharRect( aTmp, aPos, &aTmpState );
+
+ // i63141: GetCharRect(..) could cause a formatting,
+ // during the formatting SwTxtFrms could be joined, deleted, created...
+ // => we have to reinit pStartFrm and pEndFrm after the formatting
+ const SwTxtFrm* pStartFrm = &rTxtFrm;
+ while( pStartFrm->HasFollow() &&
+ nChgStart >= pStartFrm->GetFollow()->GetOfst() )
+ pStartFrm = pStartFrm->GetFollow();
+ pEndFrm = pStartFrm;
+ while( pEndFrm->HasFollow() &&
+ nChgEnd >= pEndFrm->GetFollow()->GetOfst() )
+ pEndFrm = pEndFrm->GetFollow();
+
+ // information about start of repaint area
+ Sw2LinesPos* pSt2Pos = aTmpState.p2Lines;
+ if ( pSt2Pos )
+ {
+ // we are inside a special portion, take right border
+ SWRECTFN( pStartFrm )
+ (aTmp.*fnRect->fnSetTop)( (pSt2Pos->aLine.*fnRect->fnGetTop)() );
+ if ( pStartFrm->IsRightToLeft() )
+ (aTmp.*fnRect->fnSetLeft)( (pSt2Pos->aPortion.*fnRect->fnGetRight)() );
+ else
+ (aTmp.*fnRect->fnSetLeft)( (pSt2Pos->aPortion.*fnRect->fnGetLeft)() );
+ (aTmp.*fnRect->fnSetWidth)( 1 );
+ (aTmp.*fnRect->fnSetHeight)( (pSt2Pos->aLine.*fnRect->fnGetHeight)() );
+ delete pSt2Pos;
+ }
+
+ sal_Bool bSameFrame = sal_True;
+
+ if( rTxtFrm.HasFollow() )
+ {
+ if( pEndFrm != pStartFrm )
+ {
+ bSameFrame = sal_False;
+ SwRect aStFrm( pStartFrm->PaintArea() );
+ {
+ SWRECTFN( pStartFrm )
+ (aTmp.*fnRect->fnSetLeft)( (aStFrm.*fnRect->fnGetLeft)() );
+ (aTmp.*fnRect->fnSetRight)( (aStFrm.*fnRect->fnGetRight)() );
+ (aTmp.*fnRect->fnSetBottom)( (aStFrm.*fnRect->fnGetBottom)() );
+ }
+ aStFrm = pEndFrm->PaintArea();
+ {
+ SWRECTFN( pEndFrm )
+ (aRect.*fnRect->fnSetTop)( (aStFrm.*fnRect->fnGetTop)() );
+ (aRect.*fnRect->fnSetLeft)( (aStFrm.*fnRect->fnGetLeft)() );
+ (aRect.*fnRect->fnSetRight)( (aStFrm.*fnRect->fnGetRight)() );
+ }
+ aRect.Union( aTmp );
+ while( sal_True )
+ {
+ pStartFrm = pStartFrm->GetFollow();
+ if( pStartFrm == pEndFrm )
+ break;
+ aRect.Union( pStartFrm->PaintArea() );
+ }
+ }
+ }
+ if( bSameFrame )
+ {
+ SWRECTFN( pStartFrm )
+ if( (aTmp.*fnRect->fnGetTop)() == (aRect.*fnRect->fnGetTop)() )
+ (aRect.*fnRect->fnSetLeft)( (aTmp.*fnRect->fnGetLeft)() );
+ else
+ {
+ SwRect aStFrm( pStartFrm->PaintArea() );
+ (aRect.*fnRect->fnSetLeft)( (aStFrm.*fnRect->fnGetLeft)() );
+ (aRect.*fnRect->fnSetRight)( (aStFrm.*fnRect->fnGetRight)() );
+ (aRect.*fnRect->fnSetTop)( (aTmp.*fnRect->fnGetTop)() );
+ }
+
+ if( aTmp.Height() > aRect.Height() )
+ aRect.Height( aTmp.Height() );
+ }
+
+ return aRect;
+}
+
+/*
+ * Used for automatic styles. Used during RstAttr.
+ */
+
+static bool lcl_HaveCommonAttributes( IStyleAccess& rStyleAccess,
+ const SfxItemSet* pSet1,
+ sal_uInt16 nWhichId,
+ const SfxItemSet& rSet2,
+ boost::shared_ptr<SfxItemSet>& pStyleHandle )
+{
+ bool bRet = false;
+
+ SfxItemSet* pNewSet = 0;
+
+ if ( !pSet1 )
+ {
+ OSL_ENSURE( nWhichId, "lcl_HaveCommonAttributes not used correctly" );
+ if ( SFX_ITEM_SET == rSet2.GetItemState( nWhichId, sal_False ) )
+ {
+ pNewSet = rSet2.Clone( sal_True );
+ pNewSet->ClearItem( nWhichId );
+ }
+ }
+ else if ( pSet1->Count() )
+ {
+ SfxItemIter aIter( *pSet1 );
+ const SfxPoolItem* pItem = aIter.GetCurItem();
+ while( sal_True )
+ {
+ if ( SFX_ITEM_SET == rSet2.GetItemState( pItem->Which(), sal_False ) )
+ {
+ if ( !pNewSet )
+ pNewSet = rSet2.Clone( sal_True );
+ pNewSet->ClearItem( pItem->Which() );
+ }
+
+ if( aIter.IsAtEnd() )
+ break;
+
+ pItem = aIter.NextItem();
+ }
+ }
+
+ if ( pNewSet )
+ {
+ if ( pNewSet->Count() )
+ pStyleHandle = rStyleAccess.getAutomaticStyle( *pNewSet, IStyleAccess::AUTO_STYLE_CHAR );
+ delete pNewSet;
+ bRet = true;
+ }
+
+ return bRet;
+}
+
+inline sal_Bool InRange(xub_StrLen nIdx, xub_StrLen nStart, xub_StrLen nEnd) {
+ return ((nIdx >=nStart) && (nIdx <= nEnd));
+}
+
+/*
+ * void SwTxtNode::RstAttr(const SwIndex &rIdx, sal_uInt16 nLen)
+ *
+ * Deletes all attributes, starting at position rIdx, for length nLen.
+ */
+
+/* 5 cases:
+ * 1) The attribute is completely in the deletion range:
+ * -> delete it
+ * 2) The end of the attribute is in the deletion range:
+ * -> delete it, then re-insert it with new end
+ * 3) The start of the attribute is in the deletion range:
+ * -> delete it, then re-insert it with new start
+ * 4) The attribute contains the deletion range:
+ * Split, i.e.,
+ * -> Delete, re-insert from old start to start of deletion range
+ * -> insert new attribute from end of deletion range to old end
+ * 5) The attribute is outside the deletion range
+ * -> nothing to do
+ */
+
+void SwTxtNode::RstAttr(const SwIndex &rIdx, xub_StrLen nLen, sal_uInt16 nWhich,
+ const SfxItemSet* pSet, sal_Bool bInclRefToxMark )
+{
+ // Attribute?
+ if ( !GetpSwpHints() )
+ return;
+
+ sal_uInt16 i = 0;
+ xub_StrLen nStt = rIdx.GetIndex();
+ xub_StrLen nEnd = nStt + nLen;
+ xub_StrLen nAttrStart;
+ SwTxtAttr *pHt;
+
+ sal_Bool bChanged = sal_False;
+
+ // nMin and nMax initialized to maximum / minimum (inverse)
+ xub_StrLen nMin = m_Text.Len();
+ xub_StrLen nMax = nStt;
+
+ const sal_Bool bNoLen = !nMin;
+
+ // We have to remember the "new" attributes, which have
+ // been introduced by splitting surrounding attributes (case 4).
+ // They may not be forgotten inside the "Forget" function
+ //std::vector< const SwTxtAttr* > aNewAttributes;
+
+ // iterate over attribute array until start of attribute is behind
+ // deletion range
+ while ((i < m_pSwpHints->Count()) &&
+ ((( nAttrStart = *(*m_pSwpHints)[i]->GetStart()) < nEnd ) || nLen==0) )
+ {
+ pHt = m_pSwpHints->GetTextHint(i);
+
+ // attributes without end stay in!
+ xub_StrLen * const pAttrEnd = pHt->GetEnd();
+ if ( !pAttrEnd /*|| pHt->HasDummyChar()*/ ) // see bInclRefToxMark
+ {
+ i++;
+ continue;
+ }
+
+ // Default behavior is to process all attributes:
+ bool bSkipAttr = false;;
+ boost::shared_ptr<SfxItemSet> pStyleHandle;
+
+ // 1. case: We want to reset only the attributes listed in pSet:
+ if ( pSet )
+ {
+ bSkipAttr = SFX_ITEM_SET != pSet->GetItemState( pHt->Which(), sal_False );
+ if ( bSkipAttr && RES_TXTATR_AUTOFMT == pHt->Which() )
+ {
+ // if the current attribute is an autostyle, we have to check if the autostyle
+ // and pSet have any attributes in common. If so, pStyleHandle will contain
+ // a handle to AutoStyle / pSet:
+ bSkipAttr = !lcl_HaveCommonAttributes( getIDocumentStyleAccess(), pSet, 0, *static_cast<const SwFmtAutoFmt&>(pHt->GetAttr()).GetStyleHandle(), pStyleHandle );
+ }
+ }
+ else if ( nWhich )
+ {
+ // 2. case: We want to reset only the attributes with WhichId nWhich:
+ bSkipAttr = nWhich != pHt->Which();
+ if ( bSkipAttr && RES_TXTATR_AUTOFMT == pHt->Which() )
+ {
+ bSkipAttr = !lcl_HaveCommonAttributes( getIDocumentStyleAccess(), 0, nWhich, *static_cast<const SwFmtAutoFmt&>(pHt->GetAttr()).GetStyleHandle(), pStyleHandle );
+ }
+ }
+ else if ( !bInclRefToxMark )
+ {
+ // 3. case: Reset all attributes except from ref/toxmarks:
+ // skip hints with CH_TXTATR here
+ // (deleting those is ONLY allowed for UNDO!)
+ bSkipAttr = RES_TXTATR_REFMARK == pHt->Which()
+ || RES_TXTATR_TOXMARK == pHt->Which()
+ || RES_TXTATR_META == pHt->Which()
+ || RES_TXTATR_METAFIELD == pHt->Which();
+ }
+
+ if ( bSkipAttr )
+ {
+ i++;
+ continue;
+ }
+
+ if( nStt <= nAttrStart ) // Faelle: 1,3,5
+ {
+ if( nEnd > nAttrStart
+ || ( nEnd == *pAttrEnd && nEnd==nAttrStart ) )
+ {
+ // Faelle: 1,3
+ if ( nMin > nAttrStart )
+ nMin = nAttrStart;
+ if ( nMax < *pAttrEnd )
+ nMax = *pAttrEnd;
+ // Falls wir nur ein nichtaufgespanntes Attribut entfernen,
+ // tun wir mal so, als ob sich nichts geaendert hat.
+ bChanged = bChanged || nEnd > nAttrStart || bNoLen;
+ if( *pAttrEnd <= nEnd ) // Fall: 1
+ {
+ const xub_StrLen nAttrEnd = *pAttrEnd;
+
+ m_pSwpHints->DeleteAtPos(i);
+ DestroyAttr( pHt );
+
+ if ( pStyleHandle.get() )
+ {
+ SwTxtAttr* pNew = MakeTxtAttr( *GetDoc(),
+ *pStyleHandle, nAttrStart, nAttrEnd );
+ InsertHint( pNew, nsSetAttrMode::SETATTR_NOHINTADJUST );
+ }
+
+ // if the last attribute is a Field, the HintsArray is
+ // deleted!
+ if ( !m_pSwpHints )
+ break;
+
+ //JP 26.11.96:
+ // beim DeleteAtPos wird ein Resort ausgefuehrt!!
+ // darum muessen wir wieder bei 0 anfangen!!!
+ // ueber den Fall 3 koennen Attribute nach hinten
+ // verschoben worden sein; damit stimmt jetzt das i
+ // nicht mehr!!!
+ i = 0;
+
+ continue;
+ }
+ else // Fall: 3
+ {
+ m_pSwpHints->NoteInHistory( pHt );
+ *pHt->GetStart() = nEnd;
+ m_pSwpHints->NoteInHistory( pHt, sal_True );
+
+ if ( pStyleHandle.get() && nAttrStart < nEnd )
+ {
+ SwTxtAttr* pNew = MakeTxtAttr( *GetDoc(),
+ *pStyleHandle, nAttrStart, nEnd );
+ InsertHint( pNew, nsSetAttrMode::SETATTR_NOHINTADJUST );
+ }
+
+ bChanged = sal_True;
+ }
+ }
+ }
+ else // Faelle: 2,4,5
+ if( *pAttrEnd > nStt ) // Faelle: 2,4
+ {
+ if( *pAttrEnd < nEnd ) // Fall: 2
+ {
+ if ( nMin > nAttrStart )
+ nMin = nAttrStart;
+ if ( nMax < *pAttrEnd )
+ nMax = *pAttrEnd;
+ bChanged = sal_True;
+
+ const xub_StrLen nAttrEnd = *pAttrEnd;
+
+ m_pSwpHints->NoteInHistory( pHt );
+ *pAttrEnd = nStt;
+ m_pSwpHints->NoteInHistory( pHt, sal_True );
+
+ if ( pStyleHandle.get() )
+ {
+ SwTxtAttr* pNew = MakeTxtAttr( *GetDoc(),
+ *pStyleHandle, nStt, nAttrEnd );
+ InsertHint( pNew, nsSetAttrMode::SETATTR_NOHINTADJUST );
+ }
+ }
+ else if( nLen ) // Fall: 4
+ { // bei Lange 0 werden beide Hints vom Insert(Ht)
+ // wieder zu einem zusammengezogen !!!!
+ if ( nMin > nAttrStart )
+ nMin = nAttrStart;
+ if ( nMax < *pAttrEnd )
+ nMax = *pAttrEnd;
+ bChanged = sal_True;
+ xub_StrLen nTmpEnd = *pAttrEnd;
+ m_pSwpHints->NoteInHistory( pHt );
+ *pAttrEnd = nStt;
+ m_pSwpHints->NoteInHistory( pHt, sal_True );
+
+ if ( pStyleHandle.get() && nStt < nEnd )
+ {
+ SwTxtAttr* pNew = MakeTxtAttr( *GetDoc(),
+ *pStyleHandle, nStt, nEnd );
+ InsertHint( pNew, nsSetAttrMode::SETATTR_NOHINTADJUST );
+ }
+
+ if( nEnd < nTmpEnd )
+ {
+ SwTxtAttr* pNew = MakeTxtAttr( *GetDoc(),
+ pHt->GetAttr(), nEnd, nTmpEnd );
+ if ( pNew )
+ {
+ SwTxtCharFmt* pCharFmt = dynamic_cast<SwTxtCharFmt*>(pHt);
+ if ( pCharFmt )
+ static_cast<SwTxtCharFmt*>(pNew)->SetSortNumber( pCharFmt->GetSortNumber() );
+
+ InsertHint( pNew,
+ nsSetAttrMode::SETATTR_NOHINTADJUST );
+ }
+
+ // jetzt kein i+1, weil das eingefuegte Attribut
+ // ein anderes auf die Position geschoben hat !
+ continue;
+ }
+ }
+ }
+ ++i;
+ }
+
+ TryDeleteSwpHints();
+ if (bChanged)
+ {
+ if ( HasHints() )
+ {
+ m_pSwpHints->Resort();
+ }
+ //TxtFrm's reagieren auf aHint, andere auf aNew
+ SwUpdateAttr aHint( nMin, nMax, 0 );
+ NotifyClients( 0, &aHint );
+ SwFmtChg aNew( GetFmtColl() );
+ NotifyClients( 0, &aNew );
+ }
+}
+
+/*************************************************************************
+ * SwTxtNode::GetCurWord()
+ *
+ * Aktuelles Wort zurueckliefern:
+ * Wir suchen immer von links nach rechts, es wird also das Wort
+ * vor nPos gesucht. Es sei denn, wir befinden uns am Anfang des
+ * Absatzes, dann wird das erste Wort zurueckgeliefert.
+ * Wenn dieses erste Wort nur aus Whitespaces besteht, returnen wir
+ * einen leeren String.
+ *************************************************************************/
+
+XubString SwTxtNode::GetCurWord( xub_StrLen nPos ) const
+{
+ OSL_ENSURE( nPos <= m_Text.Len(), "SwTxtNode::GetCurWord: invalid index." );
+
+ if (!m_Text.Len())
+ return m_Text;
+
+ Boundary aBndry;
+ const uno::Reference< XBreakIterator > &rxBreak = pBreakIt->GetBreakIter();
+ if (rxBreak.is())
+ {
+ sal_Int16 nWordType = WordType::DICTIONARY_WORD;
+ lang::Locale aLocale( pBreakIt->GetLocale( GetLang( nPos ) ) );
+#ifdef DEBUG
+ sal_Bool bBegin = rxBreak->isBeginWord( m_Text, nPos, aLocale, nWordType );
+ sal_Bool bEnd = rxBreak->isEndWord ( m_Text, nPos, aLocale, nWordType );
+ (void)bBegin;
+ (void)bEnd;
+#endif
+ aBndry =
+ rxBreak->getWordBoundary( m_Text, nPos, aLocale, nWordType, sal_True );
+
+ // if no word was found use previous word (if any)
+ if (aBndry.startPos == aBndry.endPos)
+ {
+ aBndry = rxBreak->previousWord( m_Text, nPos, aLocale, nWordType );
+ }
+ }
+
+ // check if word was found and if it uses a symbol font, if so
+ // enforce returning an empty string
+ if (aBndry.endPos != aBndry.startPos && IsSymbol( (xub_StrLen)aBndry.startPos ))
+ aBndry.endPos = aBndry.startPos;
+
+ return m_Text.Copy( static_cast<xub_StrLen>(aBndry.startPos),
+ static_cast<xub_StrLen>(aBndry.endPos - aBndry.startPos) );
+}
+
+SwScanner::SwScanner( const SwTxtNode& rNd, const String& rTxt, const LanguageType* pLang,
+ const ModelToViewHelper::ConversionMap* pConvMap,
+ sal_uInt16 nType, xub_StrLen nStart, xub_StrLen nEnde, sal_Bool bClp )
+ : rNode( rNd ), rText( rTxt), pLanguage( pLang ), pConversionMap( pConvMap ), nLen( 0 ), nWordType( nType ), bClip( bClp )
+{
+ OSL_ENSURE( rText.Len(), "SwScanner: EmptyString" );
+ nStartPos = nBegin = nStart;
+ nEndPos = nEnde;
+
+ if ( pLanguage )
+ {
+ aCurrLang = *pLanguage;
+ }
+ else
+ {
+ ModelToViewHelper::ModelPosition aModelBeginPos = ModelToViewHelper::ConvertToModelPosition( pConversionMap, nBegin );
+ const xub_StrLen nModelBeginPos = (xub_StrLen)aModelBeginPos.mnPos;
+ aCurrLang = rNd.GetLang( nModelBeginPos );
+ }
+}
+
+sal_Bool SwScanner::NextWord()
+{
+ nBegin = nBegin + nLen;
+ Boundary aBound;
+
+ CharClass& rCC = GetAppCharClass();
+ lang::Locale aOldLocale = rCC.getLocale();
+
+ while ( true )
+ {
+ // skip non-letter characters:
+ while ( nBegin < rText.Len() )
+ {
+ if ( !lcl_IsSkippableWhiteSpace( rText.GetChar( nBegin ) ) )
+ {
+ if ( !pLanguage )
+ {
+ const sal_uInt16 nNextScriptType = pBreakIt->GetBreakIter()->getScriptType( rText, nBegin );
+ ModelToViewHelper::ModelPosition aModelBeginPos = ModelToViewHelper::ConvertToModelPosition( pConversionMap, nBegin );
+ const xub_StrLen nBeginModelPos = (xub_StrLen)aModelBeginPos.mnPos;
+ aCurrLang = rNode.GetLang( nBeginModelPos, 1, nNextScriptType );
+ }
+
+ if ( nWordType != i18n::WordType::WORD_COUNT )
+ {
+ rCC.setLocale( pBreakIt->GetLocale( aCurrLang ) );
+ if ( rCC.isLetterNumeric( rText.GetChar( nBegin ) ) )
+ break;
+ }
+ else
+ break;
+ }
+ ++nBegin;
+ }
+
+ if ( nBegin >= rText.Len() || nBegin >= nEndPos )
+ return sal_False;
+
+ // get the word boundaries
+ aBound = pBreakIt->GetBreakIter()->getWordBoundary( rText, nBegin,
+ pBreakIt->GetLocale( aCurrLang ), nWordType, sal_True );
+ OSL_ENSURE( aBound.endPos >= aBound.startPos, "broken aBound result" );
+
+ //no word boundaries could be found
+ if(aBound.endPos == aBound.startPos)
+ return sal_False;
+
+ //if a word before is found it has to be searched for the next
+ if(aBound.endPos == nBegin)
+ ++nBegin;
+ else
+ break;
+ } // end while( true )
+
+ rCC.setLocale( aOldLocale );
+
+ // #i89042, as discussed with HDU: don't evaluate script changes for word count. Use whole word.
+ if ( nWordType == i18n::WordType::WORD_COUNT )
+ {
+ nBegin = Max( static_cast< xub_StrLen >(aBound.startPos), nBegin );
+ nLen = 0;
+ if (static_cast< xub_StrLen >(aBound.endPos) > nBegin)
+ nLen = static_cast< xub_StrLen >(aBound.endPos) - nBegin;
+ }
+ else
+ {
+ // we have to differenciate between these cases:
+ if ( aBound.startPos <= nBegin )
+ {
+ OSL_ENSURE( aBound.endPos >= nBegin, "Unexpected aBound result" );
+
+ // restrict boundaries to script boundaries and nEndPos
+ const sal_uInt16 nCurrScript = pBreakIt->GetBreakIter()->getScriptType( rText, nBegin );
+ XubString aTmpWord = rText.Copy( nBegin, static_cast<xub_StrLen>(aBound.endPos - nBegin) );
+ const sal_Int32 nScriptEnd = nBegin +
+ pBreakIt->GetBreakIter()->endOfScript( aTmpWord, 0, nCurrScript );
+ const sal_Int32 nEnd = Min( aBound.endPos, nScriptEnd );
+
+ // restrict word start to last script change position
+ sal_Int32 nScriptBegin = 0;
+ if ( aBound.startPos < nBegin )
+ {
+ // search from nBegin backwards until the next script change
+ aTmpWord = rText.Copy( static_cast<xub_StrLen>(aBound.startPos),
+ static_cast<xub_StrLen>(nBegin - aBound.startPos + 1) );
+ nScriptBegin = aBound.startPos +
+ pBreakIt->GetBreakIter()->beginOfScript( aTmpWord, nBegin - aBound.startPos,
+ nCurrScript );
+ }
+
+ nBegin = (xub_StrLen)Max( aBound.startPos, nScriptBegin );
+ nLen = (xub_StrLen)(nEnd - nBegin);
+ }
+ else
+ {
+ const sal_uInt16 nCurrScript = pBreakIt->GetBreakIter()->getScriptType( rText, aBound.startPos );
+ XubString aTmpWord = rText.Copy( static_cast<xub_StrLen>(aBound.startPos),
+ static_cast<xub_StrLen>(aBound.endPos - aBound.startPos) );
+ const sal_Int32 nScriptEnd = aBound.startPos +
+ pBreakIt->GetBreakIter()->endOfScript( aTmpWord, 0, nCurrScript );
+ const sal_Int32 nEnd = Min( aBound.endPos, nScriptEnd );
+ nBegin = (xub_StrLen)aBound.startPos;
+ nLen = (xub_StrLen)(nEnd - nBegin);
+ }
+ }
+
+ // optionally clip the result of getWordBoundaries:
+ if ( bClip )
+ {
+ aBound.startPos = Max( (xub_StrLen)aBound.startPos, nStartPos );
+ aBound.endPos = Min( (xub_StrLen)aBound.endPos, nEndPos );
+ nBegin = (xub_StrLen)aBound.startPos;
+ nLen = (xub_StrLen)(aBound.endPos - nBegin);
+ }
+
+ if( ! nLen )
+ return sal_False;
+
+ aWord = rText.Copy( nBegin, nLen );
+
+ return sal_True;
+}
+
+sal_uInt16 SwTxtNode::Spell(SwSpellArgs* pArgs)
+{
+ // Die Aehnlichkeiten zu SwTxtFrm::_AutoSpell sind beabsichtigt ...
+ // ACHTUNG: Ev. Bugs in beiden Routinen fixen!
+
+ uno::Reference<beans::XPropertySet> xProp( GetLinguPropertySet() );
+
+ xub_StrLen nBegin, nEnd;
+
+ // modify string according to redline information and hidden text
+ const XubString aOldTxt( m_Text );
+ const bool bRestoreString =
+ lcl_MaskRedlinesAndHiddenText( *this, m_Text, 0, m_Text.Len() ) > 0;
+
+ if ( pArgs->pStartNode != this )
+ nBegin = 0;
+ else
+ nBegin = pArgs->pStartIdx->GetIndex();
+
+ nEnd = ( pArgs->pEndNode != this )
+ ? m_Text.Len()
+ : pArgs->pEndIdx->GetIndex();
+
+ pArgs->xSpellAlt = NULL;
+
+ // 4 cases:
+ //
+ // 1. IsWrongDirty = 0 and GetWrong = 0
+ // Everything is checked and correct
+ // 2. IsWrongDirty = 0 and GetWrong = 1
+ // Everything is checked and errors are identified in the wrong list
+ // 3. IsWrongDirty = 1 and GetWrong = 0
+ // Nothing has been checked
+ // 4. IsWrongDirty = 1 and GetWrong = 1
+ // Text has been checked but there is an invalid range in the wrong list
+ //
+ // Nothing has to be done for case 1.
+ if ( ( IsWrongDirty() || GetWrong() ) && m_Text.Len() )
+ {
+ if ( nBegin > m_Text.Len() )
+ {
+ nBegin = m_Text.Len();
+ }
+ if ( nEnd > m_Text.Len() )
+ {
+ nEnd = m_Text.Len();
+ }
+ //
+ if(!IsWrongDirty())
+ {
+ xub_StrLen nTemp = GetWrong()->NextWrong( nBegin );
+ if(nTemp > nEnd)
+ {
+ // reset original text
+ if ( bRestoreString )
+ {
+ m_Text = aOldTxt;
+ }
+ return 0;
+ }
+ if(nTemp > nBegin)
+ nBegin = nTemp;
+
+ }
+
+ // In case 2. we pass the wrong list to the scanned, because only
+ // the words in the wrong list have to be checked
+ SwScanner aScanner( *this, m_Text, 0, 0,
+ WordType::DICTIONARY_WORD,
+ nBegin, nEnd );
+ while( !pArgs->xSpellAlt.is() && aScanner.NextWord() )
+ {
+ const XubString& rWord = aScanner.GetWord();
+
+ // get next language for next word, consider language attributes
+ // within the word
+ LanguageType eActLang = aScanner.GetCurrentLanguage();
+
+ if( rWord.Len() > 0 && LANGUAGE_NONE != eActLang )
+ {
+ if (pArgs->xSpeller.is())
+ {
+ SvxSpellWrapper::CheckSpellLang( pArgs->xSpeller, eActLang );
+ pArgs->xSpellAlt = pArgs->xSpeller->spell( rWord, eActLang,
+ Sequence< PropertyValue >() );
+ }
+ if( (pArgs->xSpellAlt).is() )
+ {
+ if( IsSymbol( aScanner.GetBegin() ) )
+ {
+ pArgs->xSpellAlt = NULL;
+ }
+ else
+ {
+ // make sure the selection build later from the
+ // data below does not include footnotes and other
+ // "in word" character to the left and right in order
+ // to preserve those. Therefore count those "in words"
+ // in order to modify the selection accordingly.
+ const sal_Unicode* pChar = rWord.GetBuffer();
+ xub_StrLen nLeft = 0;
+ while (pChar && *pChar++ == CH_TXTATR_INWORD)
+ ++nLeft;
+ pChar = rWord.Len() ? rWord.GetBuffer() + rWord.Len() - 1 : 0;
+ xub_StrLen nRight = 0;
+ while (pChar && *pChar-- == CH_TXTATR_INWORD)
+ ++nRight;
+
+ pArgs->pStartNode = this;
+ pArgs->pEndNode = this;
+ pArgs->pStartIdx->Assign(this, aScanner.GetEnd() - nRight );
+ pArgs->pEndIdx->Assign(this, aScanner.GetBegin() + nLeft );
+ }
+ }
+ }
+ }
+ }
+
+ // reset original text
+ if ( bRestoreString )
+ {
+ m_Text = aOldTxt;
+ }
+
+ return pArgs->xSpellAlt.is() ? 1 : 0;
+}
+
+void SwTxtNode::SetLanguageAndFont( const SwPaM &rPaM,
+ LanguageType nLang, sal_uInt16 nLangWhichId,
+ const Font *pFont, sal_uInt16 nFontWhichId )
+{
+ sal_uInt16 aRanges[] = {
+ nLangWhichId, nLangWhichId,
+ nFontWhichId, nFontWhichId,
+ 0, 0, 0 };
+ if (!pFont)
+ aRanges[2] = aRanges[3] = 0; // clear entries with font WhichId
+
+ SwEditShell *pEditShell = GetDoc()->GetEditShell();
+ SfxItemSet aSet( pEditShell->GetAttrPool(), aRanges );
+ aSet.Put( SvxLanguageItem( nLang, nLangWhichId ) );
+
+ DBG_ASSERT( pFont, "target font missing?" );
+ if (pFont)
+ {
+ SvxFontItem aFontItem = (SvxFontItem&) aSet.Get( nFontWhichId );
+ aFontItem.SetFamilyName( pFont->GetName());
+ aFontItem.SetFamily( pFont->GetFamily());
+ aFontItem.SetStyleName( pFont->GetStyleName());
+ aFontItem.SetPitch( pFont->GetPitch());
+ aFontItem.SetCharSet( pFont->GetCharSet() );
+ aSet.Put( aFontItem );
+ }
+
+ GetDoc()->InsertItemSet( rPaM, aSet, 0 );
+ // SetAttr( aSet ); <- Does not set language attribute of empty paragraphs correctly,
+ // <- because since there is no selection the flag to garbage
+ // <- collect all attributes is set, and therefore attributes spanned
+ // <- over empty selection are removed.
+
+}
+
+sal_uInt16 SwTxtNode::Convert( SwConversionArgs &rArgs )
+{
+ // get range of text within node to be converted
+ // (either all the text or the the text within the selection
+ // when the conversion was started)
+ xub_StrLen nTextBegin, nTextEnd;
+ //
+ if ( rArgs.pStartNode != this )
+ {
+ nTextBegin = 0;
+ }
+ else
+ nTextBegin = rArgs.pStartIdx->GetIndex();
+ if (nTextBegin > m_Text.Len())
+ {
+ nTextBegin = m_Text.Len();
+ }
+
+ nTextEnd = ( rArgs.pEndNode != this )
+ ? m_Text.Len()
+ : ::std::min( rArgs.pEndIdx->GetIndex(), m_Text.Len() );
+
+ rArgs.aConvText = rtl::OUString();
+
+ // modify string according to redline information and hidden text
+ const XubString aOldTxt( m_Text );
+ const bool bRestoreString =
+ lcl_MaskRedlinesAndHiddenText( *this, m_Text, 0, m_Text.Len() ) > 0;
+
+ sal_Bool bFound = sal_False;
+ xub_StrLen nBegin = nTextBegin;
+ xub_StrLen nLen = 0;
+ LanguageType nLangFound = LANGUAGE_NONE;
+ if (!m_Text.Len())
+ {
+ if (rArgs.bAllowImplicitChangesForNotConvertibleText)
+ {
+ // create SwPaM with mark & point spanning empty paragraph
+ //SwPaM aCurPaM( *this, *this, nBegin, nBegin + nLen ); <-- wrong c-tor, does sth different
+ SwPaM aCurPaM( *this, 0 );
+
+ SetLanguageAndFont( aCurPaM,
+ rArgs.nConvTargetLang, RES_CHRATR_CJK_LANGUAGE,
+ rArgs.pTargetFont, RES_CHRATR_CJK_FONT );
+ }
+ }
+ else
+ {
+ SwLanguageIterator aIter( *this, nBegin );
+
+ // find non zero length text portion of appropriate language
+ do {
+ nLangFound = aIter.GetLanguage();
+ sal_Bool bLangOk = (nLangFound == rArgs.nConvSrcLang) ||
+ (editeng::HangulHanjaConversion::IsChinese( nLangFound ) &&
+ editeng::HangulHanjaConversion::IsChinese( rArgs.nConvSrcLang ));
+
+ xub_StrLen nChPos = aIter.GetChgPos();
+ // the position at the end of the paragraph returns -1
+ // which becomes 65535 when converted to xub_StrLen,
+ // and thus must be cut to the end of the actual string.
+ if (nChPos == (xub_StrLen) -1)
+ {
+ nChPos = m_Text.Len();
+ }
+
+ nLen = nChPos - nBegin;
+ bFound = bLangOk && nLen > 0;
+ if (!bFound)
+ {
+ // create SwPaM with mark & point spanning the attributed text
+ //SwPaM aCurPaM( *this, *this, nBegin, nBegin + nLen ); <-- wrong c-tor, does sth different
+ SwPaM aCurPaM( *this, nBegin );
+ aCurPaM.SetMark();
+ aCurPaM.GetPoint()->nContent = nBegin + nLen;
+
+ // check script type of selected text
+ SwEditShell *pEditShell = GetDoc()->GetEditShell();
+ pEditShell->Push(); // save current cursor on stack
+ pEditShell->SetSelection( aCurPaM );
+ sal_Bool bIsAsianScript = (SCRIPTTYPE_ASIAN == pEditShell->GetScriptType());
+ pEditShell->Pop( sal_False ); // restore cursor from stack
+
+ if (!bIsAsianScript && rArgs.bAllowImplicitChangesForNotConvertibleText)
+ {
+ SetLanguageAndFont( aCurPaM,
+ rArgs.nConvTargetLang, RES_CHRATR_CJK_LANGUAGE,
+ rArgs.pTargetFont, RES_CHRATR_CJK_FONT );
+ }
+ nBegin = nChPos; // start of next language portion
+ }
+ } while (!bFound && aIter.Next()); /* loop while nothing was found and still sth is left to be searched */
+ }
+
+ // keep resulting text within selection / range of text to be converted
+ if (nBegin < nTextBegin)
+ nBegin = nTextBegin;
+ if (nBegin + nLen > nTextEnd)
+ nLen = nTextEnd - nBegin;
+ sal_Bool bInSelection = nBegin < nTextEnd;
+
+ if (bFound && bInSelection) // convertible text found within selection/range?
+ {
+ const XubString aTxtPortion = m_Text.Copy( nBegin, nLen );
+ DBG_ASSERT( m_Text.Len() > 0, "convertible text portion missing!" );
+ rArgs.aConvText = m_Text.Copy( nBegin, nLen );
+ rArgs.nConvTextLang = nLangFound;
+
+ // position where to start looking in next iteration (after current ends)
+ rArgs.pStartNode = this;
+ rArgs.pStartIdx->Assign(this, nBegin + nLen );
+ // end position (when we have travelled over the whole document)
+ rArgs.pEndNode = this;
+ rArgs.pEndIdx->Assign(this, nBegin );
+ }
+
+ // restore original text
+ if ( bRestoreString )
+ {
+ m_Text = aOldTxt;
+ }
+
+ return rArgs.aConvText.getLength() ? 1 : 0;
+}
+
+// Die Aehnlichkeiten zu SwTxtNode::Spell sind beabsichtigt ...
+// ACHTUNG: Ev. Bugs in beiden Routinen fixen!
+SwRect SwTxtFrm::_AutoSpell( const SwCntntNode* pActNode, const SwViewOption& rViewOpt, xub_StrLen nActPos )
+{
+ SwRect aRect;
+#if OSL_DEBUG_LEVEL > 1
+ static sal_Bool bStop = sal_False;
+ if ( bStop )
+ return aRect;
+#endif
+ // Die Aehnlichkeiten zu SwTxtNode::Spell sind beabsichtigt ...
+ // ACHTUNG: Ev. Bugs in beiden Routinen fixen!
+ SwTxtNode *pNode = GetTxtNode();
+ if( pNode != pActNode || !nActPos )
+ nActPos = STRING_LEN;
+
+ SwAutoCompleteWord& rACW = SwDoc::GetAutoCompleteWords();
+
+ // modify string according to redline information and hidden text
+ const XubString aOldTxt( pNode->GetTxt() );
+ const bool bRestoreString =
+ lcl_MaskRedlinesAndHiddenText( *pNode, pNode->m_Text,
+ 0, pNode->GetTxt().Len() ) > 0;
+
+ // a change of data indicates that at least one word has been modified
+ const sal_Bool bRedlineChg =
+ ( pNode->GetTxt().GetBuffer() != aOldTxt.GetBuffer() );
+
+ xub_StrLen nBegin = 0;
+ xub_StrLen nEnd = pNode->GetTxt().Len();
+ xub_StrLen nInsertPos = 0;
+ xub_StrLen nChgStart = STRING_LEN;
+ xub_StrLen nChgEnd = 0;
+ xub_StrLen nInvStart = STRING_LEN;
+ xub_StrLen nInvEnd = 0;
+
+ const sal_Bool bAddAutoCmpl = pNode->IsAutoCompleteWordDirty() &&
+ rViewOpt.IsAutoCompleteWords();
+
+ if( pNode->GetWrong() )
+ {
+ nBegin = pNode->GetWrong()->GetBeginInv();
+ if( STRING_LEN != nBegin )
+ {
+ nEnd = pNode->GetWrong()->GetEndInv();
+ if ( nEnd > pNode->GetTxt().Len() )
+ {
+ nEnd = pNode->GetTxt().Len();
+ }
+ }
+
+ // get word around nBegin, we start at nBegin - 1
+ if ( STRING_LEN != nBegin )
+ {
+ if ( nBegin )
+ --nBegin;
+
+ LanguageType eActLang = pNode->GetLang( nBegin );
+ Boundary aBound =
+ pBreakIt->GetBreakIter()->getWordBoundary( pNode->GetTxt(), nBegin,
+ pBreakIt->GetLocale( eActLang ),
+ WordType::DICTIONARY_WORD, sal_True );
+ nBegin = xub_StrLen(aBound.startPos);
+ }
+
+ // get the position in the wrong list
+ nInsertPos = pNode->GetWrong()->GetWrongPos( nBegin );
+
+ // sometimes we have to skip one entry
+ if( nInsertPos < pNode->GetWrong()->Count() &&
+ nBegin == pNode->GetWrong()->Pos( nInsertPos ) +
+ pNode->GetWrong()->Len( nInsertPos ) )
+ nInsertPos++;
+ }
+
+ sal_Bool bFresh = nBegin < nEnd;
+
+ if( nBegin < nEnd )
+ {
+ //! register listener to LinguServiceEvents now in order to get
+ //! notified about relevant changes in the future
+ SwModule *pModule = SW_MOD();
+ if (!pModule->GetLngSvcEvtListener().is())
+ pModule->CreateLngSvcEvtListener();
+
+ uno::Reference< XSpellChecker1 > xSpell( ::GetSpellChecker() );
+ SwDoc* pDoc = pNode->GetDoc();
+
+ SwScanner aScanner( *pNode, pNode->GetTxt(), 0, 0,
+ WordType::DICTIONARY_WORD, nBegin, nEnd);
+
+ while( aScanner.NextWord() )
+ {
+ const XubString& rWord = aScanner.GetWord();
+ nBegin = aScanner.GetBegin();
+ xub_StrLen nLen = aScanner.GetLen();
+
+ // get next language for next word, consider language attributes
+ // within the word
+ LanguageType eActLang = aScanner.GetCurrentLanguage();
+
+ sal_Bool bSpell = sal_True;
+ bSpell = xSpell.is() ? xSpell->hasLanguage( eActLang ) : sal_False;
+ if( bSpell && rWord.Len() > 0 )
+ {
+ // check for: bAlter => xHyphWord.is()
+ DBG_ASSERT(!bSpell || xSpell.is(), "NULL pointer");
+
+ if( !xSpell->isValid( rWord, eActLang, Sequence< PropertyValue >() ) )
+ {
+ xub_StrLen nSmartTagStt = nBegin;
+ xub_StrLen nDummy = 1;
+ if ( !pNode->GetSmartTags() || !pNode->GetSmartTags()->InWrongWord( nSmartTagStt, nDummy ) )
+ {
+ if( !pNode->GetWrong() )
+ {
+ pNode->SetWrong( new SwWrongList( WRONGLIST_SPELL ) );
+ pNode->GetWrong()->SetInvalid( 0, nEnd );
+ }
+ if( pNode->GetWrong()->Fresh( nChgStart, nChgEnd,
+ nBegin, nLen, nInsertPos, nActPos ) )
+ pNode->GetWrong()->Insert( rtl::OUString(), 0, nBegin, nLen, nInsertPos++ );
+ else
+ {
+ nInvStart = nBegin;
+ nInvEnd = nBegin + nLen;
+ }
+ }
+ }
+ else if( bAddAutoCmpl && rACW.GetMinWordLen() <= rWord.Len() )
+ {
+ if ( bRedlineChg )
+ {
+ XubString rNewWord( rWord );
+ rACW.InsertWord( rNewWord, *pDoc );
+ }
+ else
+ rACW.InsertWord( rWord, *pDoc );
+ }
+ }
+ }
+ }
+
+ // reset original text
+ // i63141 before calling GetCharRect(..) with formatting!
+ if ( bRestoreString )
+ {
+ pNode->m_Text = aOldTxt;
+ }
+ if( pNode->GetWrong() )
+ {
+ if( bFresh )
+ pNode->GetWrong()->Fresh( nChgStart, nChgEnd,
+ nEnd, 0, nInsertPos, nActPos );
+
+ //
+ // Calculate repaint area:
+ //
+ if( nChgStart < nChgEnd )
+ {
+ aRect = lcl_CalculateRepaintRect( *this, nChgStart, nChgEnd );
+ }
+
+ pNode->GetWrong()->SetInvalid( nInvStart, nInvEnd );
+ pNode->SetWrongDirty( STRING_LEN != pNode->GetWrong()->GetBeginInv() );
+ if( !pNode->GetWrong()->Count() && ! pNode->IsWrongDirty() )
+ pNode->SetWrong( NULL );
+ }
+ else
+ pNode->SetWrongDirty( false );
+
+ if( bAddAutoCmpl )
+ pNode->SetAutoCompleteWordDirty( false );
+
+ return aRect;
+}
+
+/** Function: SmartTagScan
+
+ Function scans words in current text and checks them in the
+ smarttag libraries. If the check returns true to bounds of the
+ recognized words are stored into a list which is used later for drawing
+ the underline.
+
+ @param SwCntntNode* pActNode
+
+ @param xub_StrLen nActPos
+
+ @return SwRect: Repaint area
+*/
+SwRect SwTxtFrm::SmartTagScan( SwCntntNode* /*pActNode*/, xub_StrLen /*nActPos*/ )
+{
+ SwRect aRet;
+ SwTxtNode *pNode = GetTxtNode();
+ const rtl::OUString& rText = pNode->GetTxt();
+
+ // Iterate over language portions
+ SmartTagMgr& rSmartTagMgr = SwSmartTagMgr::Get();
+
+ SwWrongList* pSmartTagList = pNode->GetSmartTags();
+
+ xub_StrLen nBegin = 0;
+ xub_StrLen nEnd = static_cast< xub_StrLen >(rText.getLength());
+
+ if ( pSmartTagList )
+ {
+ if ( pSmartTagList->GetBeginInv() != STRING_LEN )
+ {
+ nBegin = pSmartTagList->GetBeginInv();
+ nEnd = Min( pSmartTagList->GetEndInv(), (xub_StrLen)rText.getLength() );
+
+ if ( nBegin < nEnd )
+ {
+ const LanguageType aCurrLang = pNode->GetLang( nBegin );
+ const com::sun::star::lang::Locale aCurrLocale = pBreakIt->GetLocale( aCurrLang );
+ nBegin = static_cast< xub_StrLen >(pBreakIt->GetBreakIter()->beginOfSentence( rText, nBegin, aCurrLocale ));
+ nEnd = static_cast< xub_StrLen >(Min( rText.getLength(), pBreakIt->GetBreakIter()->endOfSentence( rText, nEnd, aCurrLocale ) ));
+ }
+ }
+ }
+
+ const sal_uInt16 nNumberOfEntries = pSmartTagList ? pSmartTagList->Count() : 0;
+ sal_uInt16 nNumberOfRemovedEntries = 0;
+ sal_uInt16 nNumberOfInsertedEntries = 0;
+
+ // clear smart tag list between nBegin and nEnd:
+ if ( 0 != nNumberOfEntries )
+ {
+ xub_StrLen nChgStart = STRING_LEN;
+ xub_StrLen nChgEnd = 0;
+ const sal_uInt16 nCurrentIndex = pSmartTagList->GetWrongPos( nBegin );
+ pSmartTagList->Fresh( nChgStart, nChgEnd, nBegin, nEnd - nBegin, nCurrentIndex, STRING_LEN );
+ nNumberOfRemovedEntries = nNumberOfEntries - pSmartTagList->Count();
+ }
+
+ if ( nBegin < nEnd )
+ {
+ // Expand the string:
+ rtl::OUString aExpandText;
+ const ModelToViewHelper::ConversionMap* pConversionMap =
+ pNode->BuildConversionMap( aExpandText );
+
+ // Ownership ov ConversionMap is passed to SwXTextMarkup object!
+ Reference< com::sun::star::text::XTextMarkup > xTextMarkup =
+ new SwXTextMarkup( *pNode, pConversionMap );
+
+ Reference< ::com::sun::star::frame::XController > xController = pNode->GetDoc()->GetDocShell()->GetController();
+
+ xub_StrLen nLangBegin = nBegin;
+ xub_StrLen nLangEnd = nEnd;
+
+ // smart tag recognization has to be done for each language portion:
+ SwLanguageIterator aIter( *pNode, nLangBegin );
+
+ do
+ {
+ const LanguageType nLang = aIter.GetLanguage();
+ const com::sun::star::lang::Locale aLocale = pBreakIt->GetLocale( nLang );
+ nLangEnd = Min( nEnd, aIter.GetChgPos() );
+
+ const sal_uInt32 nExpandBegin = ModelToViewHelper::ConvertToViewPosition( pConversionMap, nLangBegin );
+ const sal_uInt32 nExpandEnd = ModelToViewHelper::ConvertToViewPosition( pConversionMap, nLangEnd );
+
+ rSmartTagMgr.Recognize( aExpandText, xTextMarkup, xController, aLocale, nExpandBegin, nExpandEnd - nExpandBegin );
+
+ nLangBegin = nLangEnd;
+ }
+ while ( aIter.Next() && nLangEnd < nEnd );
+
+ pSmartTagList = pNode->GetSmartTags();
+
+ const sal_uInt16 nNumberOfEntriesAfterRecognize = pSmartTagList ? pSmartTagList->Count() : 0;
+ nNumberOfInsertedEntries = nNumberOfEntriesAfterRecognize - ( nNumberOfEntries - nNumberOfRemovedEntries );
+ }
+
+ if( pSmartTagList )
+ {
+ //
+ // Update WrongList stuff
+ //
+ pSmartTagList->SetInvalid( STRING_LEN, 0 );
+ pNode->SetSmartTagDirty( STRING_LEN != pSmartTagList->GetBeginInv() );
+
+ if( !pSmartTagList->Count() && !pNode->IsSmartTagDirty() )
+ pNode->SetSmartTags( NULL );
+
+ //
+ // Calculate repaint area:
+ //
+#if OSL_DEBUG_LEVEL > 1
+ const sal_uInt16 nNumberOfEntriesAfterRecognize2 = pSmartTagList->Count();
+ (void) nNumberOfEntriesAfterRecognize2;
+#endif
+ if ( nBegin < nEnd && ( 0 != nNumberOfRemovedEntries ||
+ 0 != nNumberOfInsertedEntries ) )
+ {
+ aRet = lcl_CalculateRepaintRect( *this, nBegin, nEnd );
+ }
+ }
+ else
+ pNode->SetSmartTagDirty( false );
+
+ return aRet;
+}
+
+// Wird vom CollectAutoCmplWords gerufen
+void SwTxtFrm::CollectAutoCmplWrds( SwCntntNode* pActNode, xub_StrLen nActPos )
+{
+ SwTxtNode *pNode = GetTxtNode();
+ if( pNode != pActNode || !nActPos )
+ nActPos = STRING_LEN;
+
+ SwDoc* pDoc = pNode->GetDoc();
+ SwAutoCompleteWord& rACW = SwDoc::GetAutoCompleteWords();
+
+ xub_StrLen nBegin = 0;
+ xub_StrLen nEnd = pNode->GetTxt().Len();
+ xub_StrLen nLen;
+ sal_Bool bACWDirty = sal_False, bAnyWrd = sal_False;
+
+ if( nBegin < nEnd )
+ {
+ sal_uInt16 nCnt = 200;
+ SwScanner aScanner( *pNode, pNode->GetTxt(), 0, 0,
+ WordType::DICTIONARY_WORD, nBegin, nEnd );
+ while( aScanner.NextWord() )
+ {
+ nBegin = aScanner.GetBegin();
+ nLen = aScanner.GetLen();
+ if( rACW.GetMinWordLen() <= nLen )
+ {
+ const XubString& rWord = aScanner.GetWord();
+
+ if( nActPos < nBegin || ( nBegin + nLen ) < nActPos )
+ {
+ if( rACW.GetMinWordLen() <= rWord.Len() )
+ rACW.InsertWord( rWord, *pDoc );
+ bAnyWrd = sal_True;
+ }
+ else
+ bACWDirty = sal_True;
+ }
+ if( !--nCnt )
+ {
+ if ( Application::AnyInput( INPUT_ANY ) )
+ return;
+ nCnt = 100;
+ }
+ }
+ }
+
+ if( bAnyWrd && !bACWDirty )
+ pNode->SetAutoCompleteWordDirty( sal_False );
+}
+
+/*************************************************************************
+ * SwTxtNode::Hyphenate
+ *************************************************************************/
+// Findet den TxtFrm und sucht dessen CalcHyph
+
+sal_Bool SwTxtNode::Hyphenate( SwInterHyphInfo &rHyphInf )
+{
+ // Abkuerzung: am Absatz ist keine Sprache eingestellt:
+ if ( LANGUAGE_NONE == sal_uInt16( GetSwAttrSet().GetLanguage().GetLanguage() )
+ && USHRT_MAX == GetLang( 0, m_Text.Len() ) )
+ {
+ if( !rHyphInf.IsCheck() )
+ rHyphInf.SetNoLang( sal_True );
+ return sal_False;
+ }
+
+ if( pLinguNode != this )
+ {
+ pLinguNode = this;
+ pLinguFrm = (SwTxtFrm*)getLayoutFrm( GetDoc()->GetCurrentLayout(), (Point*)(rHyphInf.GetCrsrPos()) );
+ }
+ SwTxtFrm *pFrm = pLinguFrm;
+ if( pFrm )
+ pFrm = &(pFrm->GetFrmAtOfst( rHyphInf.nStart ));
+ else
+ {
+ // 4935: Seit der Trennung ueber Sonderbereiche sind Faelle
+ // moeglich, in denen kein Frame zum Node vorliegt.
+ // Also keinOSL_ENSURE
+#if OSL_DEBUG_LEVEL > 1
+ OSL_ENSURE( pFrm, "!SwTxtNode::Hyphenate: can't find any frame" );
+#endif
+ return sal_False;
+ }
+
+ while( pFrm )
+ {
+ if( pFrm->Hyphenate( rHyphInf ) )
+ {
+ // Das Layout ist nicht robust gegen "Direktformatierung"
+ // (7821, 7662, 7408); vgl. layact.cxx,
+ // SwLayAction::_TurboAction(), if( !pCnt->IsValid() ...
+ pFrm->SetCompletePaint();
+ return sal_True;
+ }
+ pFrm = (SwTxtFrm*)(pFrm->GetFollow());
+ if( pFrm )
+ {
+ rHyphInf.nLen = rHyphInf.nLen - (pFrm->GetOfst() - rHyphInf.nStart);
+ rHyphInf.nStart = pFrm->GetOfst();
+ }
+ }
+ return sal_False;
+}
+
+struct TransliterationChgData
+{
+ xub_StrLen nStart;
+ xub_StrLen nLen;
+ String sChanged;
+ Sequence< sal_Int32 > aOffsets;
+};
+
+// change text to Upper/Lower/Hiragana/Katagana/...
+void SwTxtNode::TransliterateText(
+ utl::TransliterationWrapper& rTrans,
+ xub_StrLen nStt, xub_StrLen nEnd,
+ SwUndoTransliterate* pUndo )
+{
+ if (nStt < nEnd && pBreakIt->GetBreakIter().is())
+ {
+ // since we don't use Hiragana/Katakana or half-width/full-width transliterations here
+ // it is fine to use ANYWORD_IGNOREWHITESPACES. (ANY_WORD btw is broken and will
+ // occasionaly miss words in consecutive sentences). Also with ANYWORD_IGNOREWHITESPACES
+ // text like 'just-in-time' will be converted to 'Just-In-Time' which seems to be the
+ // proper thing to do.
+ const sal_Int16 nWordType = WordType::ANYWORD_IGNOREWHITESPACES;
+
+ //! In order to have less trouble with changing text size, e.g. because
+ //! of ligatures or � (German small sz) being resolved, we need to process
+ //! the text replacements from end to start.
+ //! This way the offsets for the yet to be changed words will be
+ //! left unchanged by the already replaced text.
+ //! For this we temporarily save the changes to be done in this vector
+ std::vector< TransliterationChgData > aChanges;
+ TransliterationChgData aChgData;
+
+ if (rTrans.getType() == (sal_uInt32)TransliterationModulesExtra::TITLE_CASE)
+ {
+ // for 'capitalize every word' we need to iterate over each word
+
+ Boundary aSttBndry;
+ Boundary aEndBndry;
+ aSttBndry = pBreakIt->GetBreakIter()->getWordBoundary(
+ GetTxt(), nStt,
+ pBreakIt->GetLocale( GetLang( nStt ) ),
+ nWordType,
+ sal_True /*prefer forward direction*/);
+ aEndBndry = pBreakIt->GetBreakIter()->getWordBoundary(
+ GetTxt(), nEnd,
+ pBreakIt->GetLocale( GetLang( nEnd ) ),
+ nWordType,
+ sal_False /*prefer backward direction*/);
+
+ // prevent backtracking to the previous word if selection is at word boundary
+ if (aSttBndry.endPos <= nStt)
+ {
+ aSttBndry = pBreakIt->GetBreakIter()->nextWord(
+ GetTxt(), aSttBndry.endPos,
+ pBreakIt->GetLocale( GetLang( aSttBndry.endPos ) ),
+ nWordType);
+ }
+ // prevent advancing to the next word if selection is at word boundary
+ if (aEndBndry.startPos >= nEnd)
+ {
+ aEndBndry = pBreakIt->GetBreakIter()->previousWord(
+ GetTxt(), aEndBndry.startPos,
+ pBreakIt->GetLocale( GetLang( aEndBndry.startPos ) ),
+ nWordType);
+ }
+
+ Boundary aCurWordBndry( aSttBndry );
+ while (aCurWordBndry.startPos <= aEndBndry.startPos)
+ {
+ nStt = (xub_StrLen)aCurWordBndry.startPos;
+ nEnd = (xub_StrLen)aCurWordBndry.endPos;
+ sal_Int32 nLen = nEnd - nStt;
+ DBG_ASSERT( nLen > 0, "invalid word length of 0" );
+#if OSL_DEBUG_LEVEL > 1
+ String aText( GetTxt().Copy( nStt, nLen ) );
+#endif
+
+ Sequence <sal_Int32> aOffsets;
+ String sChgd( rTrans.transliterate( GetTxt(), GetLang( nStt ), nStt, nLen, &aOffsets ));
+
+ if (!m_Text.Equals( sChgd, nStt, nLen ))
+ {
+ aChgData.nStart = nStt;
+ aChgData.nLen = nLen;
+ aChgData.sChanged = sChgd;
+ aChgData.aOffsets = aOffsets;
+ aChanges.push_back( aChgData );
+ }
+
+ aCurWordBndry = pBreakIt->GetBreakIter()->nextWord(
+ GetTxt(), nEnd,
+ pBreakIt->GetLocale( GetLang( nEnd ) ),
+ nWordType);
+ }
+ }
+ else if (rTrans.getType() == (sal_uInt32)TransliterationModulesExtra::SENTENCE_CASE)
+ {
+ // for 'sentence case' we need to iterate sentence by sentence
+
+ sal_Int32 nLastStart = pBreakIt->GetBreakIter()->beginOfSentence(
+ GetTxt(), nEnd,
+ pBreakIt->GetLocale( GetLang( nEnd ) ) );
+ sal_Int32 nLastEnd = pBreakIt->GetBreakIter()->endOfSentence(
+ GetTxt(), nLastStart,
+ pBreakIt->GetLocale( GetLang( nLastStart ) ) );
+
+ // extend nStt, nEnd to the current sentence boundaries
+ sal_Int32 nCurrentStart = pBreakIt->GetBreakIter()->beginOfSentence(
+ GetTxt(), nStt,
+ pBreakIt->GetLocale( GetLang( nStt ) ) );
+ sal_Int32 nCurrentEnd = pBreakIt->GetBreakIter()->endOfSentence(
+ GetTxt(), nCurrentStart,
+ pBreakIt->GetLocale( GetLang( nCurrentStart ) ) );
+
+ // prevent backtracking to the previous sentence if selection starts at end of a sentence
+ if (nCurrentEnd <= nStt)
+ {
+ // now nCurrentStart is probably located on a non-letter word. (unless we
+ // are in Asian text with no spaces...)
+ // Thus to get the real sentence start we should locate the next real word,
+ // that is one found by DICTIONARY_WORD
+ i18n::Boundary aBndry = pBreakIt->GetBreakIter()->nextWord(
+ GetTxt(), nCurrentEnd,
+ pBreakIt->GetLocale( GetLang( nCurrentEnd ) ),
+ i18n::WordType::DICTIONARY_WORD);
+
+ // now get new current sentence boundaries
+ nCurrentStart = pBreakIt->GetBreakIter()->beginOfSentence(
+ GetTxt(), aBndry.startPos,
+ pBreakIt->GetLocale( GetLang( aBndry.startPos) ) );
+ nCurrentEnd = pBreakIt->GetBreakIter()->endOfSentence(
+ GetTxt(), nCurrentStart,
+ pBreakIt->GetLocale( GetLang( nCurrentStart) ) );
+ }
+ // prevent advancing to the next sentence if selection ends at start of a sentence
+ if (nLastStart >= nEnd)
+ {
+ // now nCurrentStart is probably located on a non-letter word. (unless we
+ // are in Asian text with no spaces...)
+ // Thus to get the real sentence start we should locate the previous real word,
+ // that is one found by DICTIONARY_WORD
+ i18n::Boundary aBndry = pBreakIt->GetBreakIter()->previousWord(
+ GetTxt(), nLastStart,
+ pBreakIt->GetLocale( GetLang( nLastStart) ),
+ i18n::WordType::DICTIONARY_WORD);
+ nLastEnd = pBreakIt->GetBreakIter()->endOfSentence(
+ GetTxt(), aBndry.startPos,
+ pBreakIt->GetLocale( GetLang( aBndry.startPos) ) );
+ if (nCurrentEnd > nLastEnd)
+ nCurrentEnd = nLastEnd;
+ }
+
+ while (nCurrentStart < nLastEnd)
+ {
+ sal_Int32 nLen = nCurrentEnd - nCurrentStart;
+ DBG_ASSERT( nLen > 0, "invalid word length of 0" );
+#if OSL_DEBUG_LEVEL > 1
+ String aText( GetTxt().Copy( nCurrentStart, nLen ) );
+#endif
+
+ Sequence <sal_Int32> aOffsets;
+ String sChgd( rTrans.transliterate( GetTxt(),
+ GetLang( nCurrentStart ), nCurrentStart, nLen, &aOffsets ));
+
+ if (!m_Text.Equals( sChgd, nStt, nLen ))
+ {
+ aChgData.nStart = nCurrentStart;
+ aChgData.nLen = nLen;
+ aChgData.sChanged = sChgd;
+ aChgData.aOffsets = aOffsets;
+ aChanges.push_back( aChgData );
+ }
+
+ Boundary aFirstWordBndry;
+ aFirstWordBndry = pBreakIt->GetBreakIter()->nextWord(
+ GetTxt(), nCurrentEnd,
+ pBreakIt->GetLocale( GetLang( nCurrentEnd ) ),
+ nWordType);
+ nCurrentStart = aFirstWordBndry.startPos;
+ nCurrentEnd = pBreakIt->GetBreakIter()->endOfSentence(
+ GetTxt(), nCurrentStart,
+ pBreakIt->GetLocale( GetLang( nCurrentStart ) ) );
+ }
+ }
+ else
+ {
+ // here we may transliterate over complete language portions...
+
+ SwLanguageIterator* pIter;
+ if( rTrans.needLanguageForTheMode() )
+ pIter = new SwLanguageIterator( *this, nStt );
+ else
+ pIter = 0;
+
+ xub_StrLen nEndPos;
+ sal_uInt16 nLang;
+ do {
+ if( pIter )
+ {
+ nLang = pIter->GetLanguage();
+ nEndPos = pIter->GetChgPos();
+ if( nEndPos > nEnd )
+ nEndPos = nEnd;
+ }
+ else
+ {
+ nLang = LANGUAGE_SYSTEM;
+ nEndPos = nEnd;
+ }
+ xub_StrLen nLen = nEndPos - nStt;
+
+ Sequence <sal_Int32> aOffsets;
+ String sChgd( rTrans.transliterate( m_Text, nLang, nStt, nLen, &aOffsets ));
+
+ if (!m_Text.Equals( sChgd, nStt, nLen ))
+ {
+ aChgData.nStart = nStt;
+ aChgData.nLen = nLen;
+ aChgData.sChanged = sChgd;
+ aChgData.aOffsets = aOffsets;
+ aChanges.push_back( aChgData );
+ }
+
+ nStt = nEndPos;
+ } while( nEndPos < nEnd && pIter && pIter->Next() );
+ delete pIter;
+ }
+
+ if (aChanges.size() > 0)
+ {
+ // now apply the changes from end to start to leave the offsets of the
+ // yet unchanged text parts remain the same.
+ for (size_t i = 0; i < aChanges.size(); ++i)
+ {
+ TransliterationChgData &rData = aChanges[ aChanges.size() - 1 - i ];
+ if (pUndo)
+ pUndo->AddChanges( *this, rData.nStart, rData.nLen, rData.aOffsets );
+ ReplaceTextOnly( rData.nStart, rData.nLen, rData.sChanged, rData.aOffsets );
+ }
+ }
+ }
+}
+
+void SwTxtNode::ReplaceTextOnly( xub_StrLen nPos, xub_StrLen nLen,
+ const XubString& rText,
+ const Sequence<sal_Int32>& rOffsets )
+{
+ m_Text.Replace( nPos, nLen, rText );
+
+ xub_StrLen nTLen = rText.Len();
+ const sal_Int32* pOffsets = rOffsets.getConstArray();
+ // now look for no 1-1 mapping -> move the indizies!
+ xub_StrLen nI, nMyOff;
+ for( nI = 0, nMyOff = nPos; nI < nTLen; ++nI, ++nMyOff )
+ {
+ xub_StrLen nOff = (xub_StrLen)pOffsets[ nI ];
+ if( nOff < nMyOff )
+ {
+ // something is inserted
+ xub_StrLen nCnt = 1;
+ while( nI + nCnt < nTLen && nOff == pOffsets[ nI + nCnt ] )
+ ++nCnt;
+
+ Update( SwIndex( this, nMyOff ), nCnt, sal_False );
+ nMyOff = nOff;
+ //nMyOff -= nCnt;
+ nI += nCnt - 1;
+ }
+ else if( nOff > nMyOff )
+ {
+ // something is deleted
+ Update( SwIndex( this, nMyOff+1 ), nOff - nMyOff, sal_True );
+ nMyOff = nOff;
+ }
+ }
+ if( nMyOff < nLen )
+ // something is deleted at the end
+ Update( SwIndex( this, nMyOff ), nLen - nMyOff, sal_True );
+
+ // notify the layout!
+ SwDelTxt aDelHint( nPos, nTLen );
+ NotifyClients( 0, &aDelHint );
+
+ SwInsTxt aHint( nPos, nTLen );
+ NotifyClients( 0, &aHint );
+}
+
+void SwTxtNode::CountWords( SwDocStat& rStat,
+ xub_StrLen nStt, xub_StrLen nEnd ) const
+{
+ sal_Bool isCountAll = ( (0 == nStt) && (GetTxt().Len() == nEnd) );
+
+ ++rStat.nAllPara; // #i93174#: count _all_ paragraphs
+ if( nStt >= nEnd )
+ { // empty node or empty selection or bad call
+ return;
+ }
+ if ( IsHidden() )
+ { // not counting hidden paras
+ return;
+ }
+ // Shortcut when counting whole paragraph and current count is clean
+ if ( isCountAll && !IsWordCountDirty() )
+ {
+ // accumulate into DocStat record to return the values
+ rStat.nWord += GetParaNumberOfWords();
+ rStat.nChar += GetParaNumberOfChars();
+ rStat.nCharExcludingSpaces += GetParaNumberOfCharsExcludingSpaces();
+ return;
+ }
+
+ // make a copy of the text
+ String& rTextCopy = const_cast<String&>(m_Text);
+
+ // mask out the redlined and hidden text with ' '
+ const xub_Unicode cChar(' ');
+ const sal_uInt16 nNumOfMaskedChars = lcl_MaskRedlinesAndHiddenText( *this, rTextCopy, nStt, nEnd, cChar, false );
+
+ // expand text into pConversionMap for scanner
+ rtl::OUString aExpandText;
+ const ModelToViewHelper::ConversionMap* pConversionMap = BuildConversionMap( aExpandText );
+
+ // map start and end points onto the ConversionMap
+ const sal_uInt32 nExpandBegin = ModelToViewHelper::ConvertToViewPosition( pConversionMap, nStt );
+ const sal_uInt32 nExpandEnd = ModelToViewHelper::ConvertToViewPosition( pConversionMap, nEnd );
+
+ if ( aExpandText.getLength() <= 0 )
+ {
+ OSL_ENSURE(aExpandText.getLength() >= 0, "Node text expansion error: length < 0." );
+ return;
+ }
+
+ //do the count
+ // all counts exclude hidden paras and hidden+redlined within para
+ // definition of space/white chars in SwScanner (and BreakIter!)
+ // uses both lcl_IsSkippableWhiteSpace and BreakIter getWordBoundary in SwScanner
+ sal_uInt32 nTmpWords = 0; // count of all contiguous blocks of non-white chars
+ sal_uInt32 nTmpChars = 0; // count of all chars
+ sal_uInt32 nTmpCharsExcludingSpaces = 0; // all non-white chars
+
+ ++rStat.nPara; // count of non-empty paras
+
+ // count words in masked and expanded text:
+ if( pBreakIt->GetBreakIter().is() )
+ {
+ const String aScannerText( aExpandText );
+ // zero is NULL for pLanguage -----------v last param = true for clipping
+ SwScanner aScanner( *this, aScannerText, 0, pConversionMap, i18n::WordType::WORD_COUNT,
+ (xub_StrLen)nExpandBegin, (xub_StrLen)nExpandEnd, true );
+
+ // used to filter out scanner returning almost empty strings (len=1; unichar=0x0001)
+ const rtl::OUString aBreakWord( CH_TXTATR_BREAKWORD );
+
+ while ( aScanner.NextWord() )
+ {
+ // 1 is len(CH_TXTATR_BREAKWORD) : match returns length of match
+ if( 1 != aExpandText.match(aBreakWord, aScanner.GetBegin() ))
+ {
+ ++nTmpWords;
+ nTmpCharsExcludingSpaces += aScanner.GetLen();
+ }
+ }
+ }
+
+ nTmpChars = nExpandEnd - nExpandBegin - nNumOfMaskedChars;
+
+ // no nTmpCharsExcludingSpaces adjust needed neither for blanked out MaskedChars
+ // nor for mid-word selection - set scanner bClip = true at creation
+
+ // count words in numbering string if started at beginning of para:
+ if ( nStt == 0 )
+ {
+ // count outline number label - ? no expansion into map
+ // always counts all of number-ish label
+ const String aNumString = GetNumString();
+ const xub_StrLen nNumStringLen = aNumString.Len();
+ if ( nNumStringLen > 0 )
+ {
+ LanguageType aLanguage = GetLang( 0 );
+
+ SwScanner aScanner( *this, aNumString, &aLanguage, 0,
+ i18n::WordType::WORD_COUNT, 0, nNumStringLen, true );
+
+ while ( aScanner.NextWord() )
+ {
+ ++nTmpWords;
+ nTmpCharsExcludingSpaces += aScanner.GetLen();
+ }
+
+ nTmpChars += nNumStringLen;
+ }
+ else if ( HasBullet() )
+ {
+ ++nTmpWords;
+ ++nTmpChars;
+ ++nTmpCharsExcludingSpaces;
+ }
+ }
+
+ delete pConversionMap;
+
+ // If counting the whole para then update cached values and mark clean
+ if ( isCountAll )
+ {
+ SetParaNumberOfWords( nTmpWords );
+ SetParaNumberOfChars( nTmpChars );
+ SetParaNumberOfCharsExcludingSpaces( nTmpCharsExcludingSpaces );
+ SetWordCountDirty( false );
+ }
+ // accumulate into DocStat record to return the values
+ rStat.nWord += nTmpWords;
+ rStat.nChar += nTmpChars;
+ rStat.nCharExcludingSpaces += nTmpCharsExcludingSpaces;
+}
+
+//
+// Paragraph statistics start
+//
+struct SwParaIdleData_Impl
+{
+ SwWrongList* pWrong; // for spell checking
+ SwGrammarMarkUp* pGrammarCheck; // for grammar checking / proof reading
+ SwWrongList* pSmartTags;
+ sal_uLong nNumberOfWords;
+ sal_uLong nNumberOfChars;
+ sal_uLong nNumberOfCharsExcludingSpaces;
+ bool bWordCountDirty;
+ bool bWrongDirty; // Ist das Wrong-Feld auf invalid?
+ bool bGrammarCheckDirty;
+ bool bSmartTagDirty;
+ bool bAutoComplDirty; // die ACompl-Liste muss angepasst werden
+
+ SwParaIdleData_Impl() :
+ pWrong ( 0 ),
+ pGrammarCheck ( 0 ),
+ pSmartTags ( 0 ),
+ nNumberOfWords ( 0 ),
+ nNumberOfChars ( 0 ),
+ nNumberOfCharsExcludingSpaces ( 0 ),
+ bWordCountDirty ( true ),
+ bWrongDirty ( true ),
+ bGrammarCheckDirty ( true ),
+ bSmartTagDirty ( true ),
+ bAutoComplDirty ( true ) {};
+};
+
+void SwTxtNode::InitSwParaStatistics( bool bNew )
+{
+ if ( bNew )
+ {
+ m_pParaIdleData_Impl = new SwParaIdleData_Impl;
+ }
+ else if ( m_pParaIdleData_Impl )
+ {
+ delete m_pParaIdleData_Impl->pWrong;
+ delete m_pParaIdleData_Impl->pGrammarCheck;
+ delete m_pParaIdleData_Impl->pSmartTags;
+ delete m_pParaIdleData_Impl;
+ m_pParaIdleData_Impl = 0;
+ }
+}
+
+void SwTxtNode::SetWrong( SwWrongList* pNew, bool bDelete )
+{
+ if ( m_pParaIdleData_Impl )
+ {
+ if ( bDelete )
+ {
+ delete m_pParaIdleData_Impl->pWrong;
+ }
+ m_pParaIdleData_Impl->pWrong = pNew;
+ }
+}
+
+SwWrongList* SwTxtNode::GetWrong()
+{
+ return m_pParaIdleData_Impl ? m_pParaIdleData_Impl->pWrong : 0;
+}
+
+// --> OD 2008-05-27 #i71360#
+const SwWrongList* SwTxtNode::GetWrong() const
+{
+ return m_pParaIdleData_Impl ? m_pParaIdleData_Impl->pWrong : 0;
+}
+// <--
+
+void SwTxtNode::SetGrammarCheck( SwGrammarMarkUp* pNew, bool bDelete )
+{
+ if ( m_pParaIdleData_Impl )
+ {
+ if ( bDelete )
+ {
+ delete m_pParaIdleData_Impl->pGrammarCheck;
+ }
+ m_pParaIdleData_Impl->pGrammarCheck = pNew;
+ }
+}
+
+SwGrammarMarkUp* SwTxtNode::GetGrammarCheck()
+{
+ return m_pParaIdleData_Impl ? m_pParaIdleData_Impl->pGrammarCheck : 0;
+}
+
+void SwTxtNode::SetSmartTags( SwWrongList* pNew, bool bDelete )
+{
+ OSL_ENSURE( !pNew || SwSmartTagMgr::Get().IsSmartTagsEnabled(),
+ "Weird - we have a smart tag list without any recognizers?" );
+
+ if ( m_pParaIdleData_Impl )
+ {
+ if ( bDelete )
+ {
+ delete m_pParaIdleData_Impl->pSmartTags;
+ }
+ m_pParaIdleData_Impl->pSmartTags = pNew;
+ }
+}
+
+SwWrongList* SwTxtNode::GetSmartTags()
+{
+ return m_pParaIdleData_Impl ? m_pParaIdleData_Impl->pSmartTags : 0;
+}
+
+void SwTxtNode::SetParaNumberOfWords( sal_uLong nNew ) const
+{
+ if ( m_pParaIdleData_Impl )
+ {
+ m_pParaIdleData_Impl->nNumberOfWords = nNew;
+ }
+}
+sal_uLong SwTxtNode::GetParaNumberOfWords() const
+{
+ return m_pParaIdleData_Impl ? m_pParaIdleData_Impl->nNumberOfWords : 0;
+}
+void SwTxtNode::SetParaNumberOfChars( sal_uLong nNew ) const
+{
+ if ( m_pParaIdleData_Impl )
+ {
+ m_pParaIdleData_Impl->nNumberOfChars = nNew;
+ }
+}
+sal_uLong SwTxtNode::GetParaNumberOfChars() const
+{
+ return m_pParaIdleData_Impl ? m_pParaIdleData_Impl->nNumberOfChars : 0;
+}
+void SwTxtNode::SetWordCountDirty( bool bNew ) const
+{
+ if ( m_pParaIdleData_Impl )
+ {
+ m_pParaIdleData_Impl->bWordCountDirty = bNew;
+ }
+}
+
+sal_uLong SwTxtNode::GetParaNumberOfCharsExcludingSpaces() const
+{
+ return m_pParaIdleData_Impl ? m_pParaIdleData_Impl->nNumberOfCharsExcludingSpaces : 0;
+}
+
+void SwTxtNode::SetParaNumberOfCharsExcludingSpaces( sal_uLong nNew ) const
+{
+ if ( m_pParaIdleData_Impl )
+ {
+ m_pParaIdleData_Impl->nNumberOfCharsExcludingSpaces = nNew;
+ }
+}
+
+bool SwTxtNode::IsWordCountDirty() const
+{
+ return m_pParaIdleData_Impl ? m_pParaIdleData_Impl->bWordCountDirty : 0;
+}
+void SwTxtNode::SetWrongDirty( bool bNew ) const
+{
+ if ( m_pParaIdleData_Impl )
+ {
+ m_pParaIdleData_Impl->bWrongDirty = bNew;
+ }
+}
+bool SwTxtNode::IsWrongDirty() const
+{
+ return m_pParaIdleData_Impl ? m_pParaIdleData_Impl->bWrongDirty : 0;
+}
+void SwTxtNode::SetGrammarCheckDirty( bool bNew ) const
+{
+ if ( m_pParaIdleData_Impl )
+ {
+ m_pParaIdleData_Impl->bGrammarCheckDirty = bNew;
+ }
+}
+bool SwTxtNode::IsGrammarCheckDirty() const
+{
+ return m_pParaIdleData_Impl ? m_pParaIdleData_Impl->bGrammarCheckDirty : 0;
+}
+void SwTxtNode::SetSmartTagDirty( bool bNew ) const
+{
+ if ( m_pParaIdleData_Impl )
+ {
+ m_pParaIdleData_Impl->bSmartTagDirty = bNew;
+ }
+}
+bool SwTxtNode::IsSmartTagDirty() const
+{
+ return m_pParaIdleData_Impl ? m_pParaIdleData_Impl->bSmartTagDirty : 0;
+}
+void SwTxtNode::SetAutoCompleteWordDirty( bool bNew ) const
+{
+ if ( m_pParaIdleData_Impl )
+ {
+ m_pParaIdleData_Impl->bAutoComplDirty = bNew;
+ }
+}
+bool SwTxtNode::IsAutoCompleteWordDirty() const
+{
+ return m_pParaIdleData_Impl ? m_pParaIdleData_Impl->bAutoComplDirty : 0;
+}
+//
+// Paragraph statistics end
+//
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/undo/SwRewriter.cxx b/sw/source/core/undo/SwRewriter.cxx
new file mode 100644
index 000000000000..afde2760904d
--- /dev/null
+++ b/sw/source/core/undo/SwRewriter.cxx
@@ -0,0 +1,80 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+#include <algorithm>
+#include <SwRewriter.hxx>
+
+using namespace std;
+
+bool operator == (const SwRewriteRule & a, const SwRewriteRule & b)
+{
+ return a.first == b.first;
+}
+
+SwRewriter::SwRewriter()
+{
+}
+
+SwRewriter::SwRewriter(const SwRewriter & rSrc)
+ : mRules(rSrc.mRules)
+{
+}
+
+SwRewriter::~SwRewriter()
+{
+}
+
+void SwRewriter::AddRule(const String & rWhat, const String & rWith)
+{
+ SwRewriteRule aRule(rWhat, rWith);
+
+ vector<SwRewriteRule>::iterator aIt;
+
+ aIt = find(mRules.begin(), mRules.end(), aRule);
+
+ if (aIt != mRules.end())
+ *aIt = aRule;
+ else
+ mRules.push_back(aRule);
+}
+
+String SwRewriter::Apply(const String & rStr) const
+{
+ String aResult = rStr;
+ vector<SwRewriteRule>::const_iterator aIt;
+
+ for (aIt = mRules.begin(); aIt != mRules.end(); ++aIt)
+ aResult.SearchAndReplaceAll(aIt->first, aIt->second);
+
+ return aResult;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/undo/SwUndoField.cxx b/sw/source/core/undo/SwUndoField.cxx
new file mode 100644
index 000000000000..b89f38dc23c4
--- /dev/null
+++ b/sw/source/core/undo/SwUndoField.cxx
@@ -0,0 +1,165 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+#include <tools/rtti.hxx>
+
+#include <SwUndoField.hxx>
+#include <swundo.hxx>
+#include <doc.hxx>
+#include <IDocumentUndoRedo.hxx>
+#include <txtfld.hxx>
+#include <fldbas.hxx>
+#include <ndtxt.hxx>
+#include <fmtfld.hxx>
+#include <dbfld.hxx>
+#include <docsh.hxx>
+
+using namespace ::com::sun::star::uno;
+
+SwUndoField::SwUndoField(const SwPosition & rPos, SwUndoId _nId )
+ : SwUndo(_nId)
+{
+ nNodeIndex = rPos.nNode.GetIndex();
+ nOffset = rPos.nContent.GetIndex();
+ pDoc = rPos.GetDoc();
+}
+
+SwUndoField::~SwUndoField()
+{
+}
+
+SwPosition SwUndoField::GetPosition()
+{
+ SwNode * pNode = pDoc->GetNodes()[nNodeIndex];
+ SwNodeIndex aNodeIndex(*pNode);
+ SwIndex aIndex(pNode->GetCntntNode(), nOffset);
+ SwPosition aResult(aNodeIndex, aIndex);
+
+ return aResult;
+}
+
+SwUndoFieldFromDoc::SwUndoFieldFromDoc(const SwPosition & rPos,
+ const SwField & rOldField,
+ const SwField & rNewField,
+ SwMsgPoolItem * _pHnt, sal_Bool _bUpdate, SwUndoId _nId)
+ : SwUndoField(rPos,_nId)
+ , pOldField(rOldField.CopyField())
+ , pNewField(rNewField.CopyField())
+ , pHnt(_pHnt)
+ , bUpdate(_bUpdate)
+{
+ OSL_ENSURE(pOldField, "No old field!");
+ OSL_ENSURE(pNewField, "No new field!");
+ OSL_ENSURE(pDoc, "No document!");
+}
+
+SwUndoFieldFromDoc::~SwUndoFieldFromDoc()
+{
+ delete pOldField;
+ delete pNewField;
+}
+
+void SwUndoFieldFromDoc::UndoImpl(::sw::UndoRedoContext &)
+{
+ SwTxtFld * pTxtFld = SwDoc::GetTxtFld(GetPosition());
+
+ const SwField * pField = pTxtFld ? pTxtFld->GetFld().GetFld() : NULL;
+
+ if (pField)
+ {
+ pDoc->UpdateFld(pTxtFld, *pOldField, pHnt, bUpdate);
+ }
+}
+
+void SwUndoFieldFromDoc::DoImpl()
+{
+ SwTxtFld * pTxtFld = SwDoc::GetTxtFld(GetPosition());
+ const SwField * pField = pTxtFld ? pTxtFld->GetFld().GetFld() : NULL;
+
+ if (pField)
+ {
+ pDoc->UpdateFld(pTxtFld, *pNewField, pHnt, bUpdate);
+ SwFmtFld* pDstFmtFld = (SwFmtFld*)&pTxtFld->GetFld();
+
+ if ( pDoc->GetFldType(RES_POSTITFLD, aEmptyStr,false) == pDstFmtFld->GetFld()->GetTyp() )
+ pDoc->GetDocShell()->Broadcast( SwFmtFldHint( pDstFmtFld, SWFMTFLD_INSERTED ) );
+ }
+}
+
+void SwUndoFieldFromDoc::RedoImpl(::sw::UndoRedoContext &)
+{
+ DoImpl();
+}
+
+void SwUndoFieldFromDoc::RepeatImpl(::sw::RepeatContext &)
+{
+ ::sw::UndoGuard const undoGuard(pDoc->GetIDocumentUndoRedo());
+ DoImpl();
+}
+
+SwUndoFieldFromAPI::SwUndoFieldFromAPI(const SwPosition & rPos,
+ const Any & rOldVal, const Any & rNewVal,
+ sal_uInt16 _nWhich)
+ : SwUndoField(rPos), aOldVal(rOldVal), aNewVal(rNewVal), nWhich(_nWhich)
+{
+}
+
+SwUndoFieldFromAPI::~SwUndoFieldFromAPI()
+{
+}
+
+void SwUndoFieldFromAPI::UndoImpl(::sw::UndoRedoContext &)
+{
+ SwField * pField = SwDoc::GetField(GetPosition());
+
+ if (pField)
+ pField->PutValue(aOldVal, nWhich);
+}
+
+void SwUndoFieldFromAPI::DoImpl()
+{
+ SwField * pField = SwDoc::GetField(GetPosition());
+
+ if (pField)
+ pField->PutValue(aNewVal, nWhich);
+}
+
+void SwUndoFieldFromAPI::RedoImpl(::sw::UndoRedoContext &)
+{
+ DoImpl();
+}
+
+void SwUndoFieldFromAPI::RepeatImpl(::sw::RepeatContext &)
+{
+ DoImpl();
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/undo/SwUndoFmt.cxx b/sw/source/core/undo/SwUndoFmt.cxx
new file mode 100644
index 000000000000..a63b09519bc3
--- /dev/null
+++ b/sw/source/core/undo/SwUndoFmt.cxx
@@ -0,0 +1,462 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+#include <tools/resid.hxx>
+#include <tools/string.hxx>
+
+#include <poolfmt.hxx>
+#include <charfmt.hxx>
+#include <frmfmt.hxx>
+#include <SwUndoFmt.hxx>
+#include <SwRewriter.hxx>
+#include <swundo.hxx>
+#include <undobj.hxx>
+#include <fmtcol.hxx>
+#include <doc.hxx>
+#include <IDocumentUndoRedo.hxx>
+#include <comcore.hrc>
+
+SwUndoFmtCreate::SwUndoFmtCreate
+(SwUndoId nUndoId, SwFmt * _pNew, SwFmt * _pDerivedFrom, SwDoc * _pDoc)
+ : SwUndo(nUndoId), pNew(_pNew),
+ pDoc(_pDoc), pNewSet(NULL), nId(0), bAuto(sal_False)
+{
+ if (_pDerivedFrom)
+ sDerivedFrom = _pDerivedFrom->GetName();
+}
+
+SwUndoFmtCreate::~SwUndoFmtCreate()
+{
+}
+
+void SwUndoFmtCreate::UndoImpl(::sw::UndoRedoContext &)
+{
+ if (pNew)
+ {
+ if (sNewName.Len() == 0 && pNew)
+ sNewName = pNew->GetName();
+
+ if (sNewName.Len() > 0)
+ pNew = Find(sNewName);
+
+ if (pNew)
+ {
+ pNewSet = new SfxItemSet(pNew->GetAttrSet());
+ nId = pNew->GetPoolFmtId() & COLL_GET_RANGE_BITS;
+ bAuto = pNew->IsAuto();
+
+ Delete();
+ }
+ }
+}
+
+void SwUndoFmtCreate::RedoImpl(::sw::UndoRedoContext &)
+{
+ SwFmt * pDerivedFrom = Find(sDerivedFrom);
+ SwFmt * pFmt = Create(pDerivedFrom);
+
+ if (pFmt && pNewSet)
+ {
+ pFmt->SetAuto(bAuto);
+ pDoc->ChgFmt(*pFmt, *pNewSet);
+ pFmt->SetPoolFmtId((pFmt->GetPoolFmtId()
+ & ~COLL_GET_RANGE_BITS)
+ | nId);
+
+ pNew = pFmt;
+ }
+ else
+ pNew = NULL;
+}
+
+SwRewriter SwUndoFmtCreate::GetRewriter() const
+{
+ if (sNewName.Len() == 0 && pNew)
+ sNewName = pNew->GetName();
+
+ SwRewriter aRewriter;
+
+ aRewriter.AddRule(UNDO_ARG1, sNewName);
+
+ return aRewriter;
+}
+
+SwUndoFmtDelete::SwUndoFmtDelete
+(SwUndoId nUndoId, SwFmt * _pOld, SwDoc * _pDoc)
+ : SwUndo(nUndoId),
+ pDoc(_pDoc), sOldName(_pOld->GetName()),
+ aOldSet(_pOld->GetAttrSet())
+{
+ sDerivedFrom = _pOld->DerivedFrom()->GetName();
+ nId = _pOld->GetPoolFmtId() & COLL_GET_RANGE_BITS;
+ bAuto = _pOld->IsAuto();
+}
+
+SwUndoFmtDelete::~SwUndoFmtDelete()
+{
+}
+
+void SwUndoFmtDelete::UndoImpl(::sw::UndoRedoContext &)
+{
+ SwFmt * pDerivedFrom = Find(sDerivedFrom);
+
+ SwFmt * pFmt = Create(pDerivedFrom);
+
+ if (pFmt)
+ {
+ pDoc->ChgFmt(*pFmt, aOldSet);
+ pFmt->SetAuto(bAuto);
+ pFmt->SetPoolFmtId((pFmt->GetPoolFmtId() &
+ ~COLL_GET_RANGE_BITS)
+ | nId);
+ }
+}
+
+void SwUndoFmtDelete::RedoImpl(::sw::UndoRedoContext &)
+{
+ SwFmt * pOld = Find(sOldName);
+
+ if (pOld)
+ {
+ Delete(pOld);
+ }
+}
+
+SwRewriter SwUndoFmtDelete::GetRewriter() const
+{
+ SwRewriter aRewriter;
+
+ aRewriter.AddRule(UNDO_ARG1, sOldName);
+
+ return aRewriter;
+}
+
+SwUndoRenameFmt::SwUndoRenameFmt(SwUndoId nUndoId,
+ const String & _sOldName,
+ const String & _sNewName,
+ SwDoc * _pDoc)
+ : SwUndo(nUndoId), sOldName(_sOldName),
+ sNewName(_sNewName), pDoc(_pDoc)
+{
+}
+
+
+SwUndoRenameFmt::~SwUndoRenameFmt()
+{
+}
+
+void SwUndoRenameFmt::UndoImpl(::sw::UndoRedoContext &)
+{
+ SwFmt * pFmt = Find(sNewName);
+
+ if (pFmt)
+ {
+ pDoc->RenameFmt(*pFmt, sOldName, sal_True);
+ }
+}
+
+void SwUndoRenameFmt::RedoImpl(::sw::UndoRedoContext &)
+{
+ SwFmt * pFmt = Find(sOldName);
+
+ if (pFmt)
+ {
+ pDoc->RenameFmt(*pFmt, sNewName, sal_True);
+ }
+}
+
+SwRewriter SwUndoRenameFmt::GetRewriter() const
+{
+ SwRewriter aRewriter;
+
+ aRewriter.AddRule(UNDO_ARG1, sOldName);
+ aRewriter.AddRule(UNDO_ARG2, SW_RES(STR_YIELDS));
+ aRewriter.AddRule(UNDO_ARG3, sNewName);
+
+ return aRewriter;
+}
+
+SwUndoTxtFmtCollCreate::SwUndoTxtFmtCollCreate
+(SwTxtFmtColl * _pNew, SwTxtFmtColl * _pDerivedFrom, SwDoc * _pDoc)
+ : SwUndoFmtCreate(UNDO_TXTFMTCOL_CREATE, _pNew, _pDerivedFrom, _pDoc)
+{
+}
+
+SwFmt * SwUndoTxtFmtCollCreate::Create(SwFmt * pDerivedFrom)
+{
+ return pDoc->MakeTxtFmtColl(sNewName, (SwTxtFmtColl *)pDerivedFrom, sal_True);
+}
+
+void SwUndoTxtFmtCollCreate::Delete()
+{
+ pDoc->DelTxtFmtColl((SwTxtFmtColl *) pNew, sal_True);
+}
+
+SwFmt * SwUndoTxtFmtCollCreate::Find(const String & rName) const
+{
+ return pDoc->FindTxtFmtCollByName(rName);
+}
+
+SwUndoTxtFmtCollDelete::SwUndoTxtFmtCollDelete(SwTxtFmtColl * _pOld,
+ SwDoc * _pDoc)
+ : SwUndoFmtDelete(UNDO_TXTFMTCOL_DELETE, _pOld, _pDoc)
+{
+}
+
+SwFmt * SwUndoTxtFmtCollDelete::Create(SwFmt * pDerivedFrom)
+{
+ return pDoc->MakeTxtFmtColl(sOldName, (SwTxtFmtColl *) pDerivedFrom, sal_True);
+}
+
+void SwUndoTxtFmtCollDelete::Delete(SwFmt * pOld)
+{
+ pDoc->DelTxtFmtColl((SwTxtFmtColl *) pOld, sal_True);
+}
+
+SwFmt * SwUndoTxtFmtCollDelete::Find(const String & rName) const
+{
+ return pDoc->FindTxtFmtCollByName(rName);
+}
+
+SwUndoRenameFmtColl::SwUndoRenameFmtColl(const String & sInitOldName,
+ const String & sInitNewName,
+ SwDoc * _pDoc)
+ : SwUndoRenameFmt(UNDO_TXTFMTCOL_RENAME, sInitOldName, sInitNewName, _pDoc)
+{
+}
+
+SwFmt * SwUndoRenameFmtColl::Find(const String & rName) const
+{
+ return pDoc->FindTxtFmtCollByName(rName);
+}
+
+SwUndoCharFmtCreate::SwUndoCharFmtCreate(SwCharFmt * pNewFmt,
+ SwCharFmt * pDerivedFrom,
+ SwDoc * pDocument)
+ : SwUndoFmtCreate(UNDO_CHARFMT_CREATE, pNewFmt, pDerivedFrom, pDocument)
+{
+}
+
+SwFmt * SwUndoCharFmtCreate::Create(SwFmt * pDerivedFrom)
+{
+ return pDoc->MakeCharFmt(sNewName, (SwCharFmt *) pDerivedFrom, sal_True);
+}
+
+void SwUndoCharFmtCreate::Delete()
+{
+ pDoc->DelCharFmt((SwCharFmt *) pNew, sal_True);
+}
+
+SwFmt * SwUndoCharFmtCreate::Find(const String & rName) const
+{
+ return pDoc->FindCharFmtByName(rName);
+}
+
+SwUndoCharFmtDelete::SwUndoCharFmtDelete(SwCharFmt * pOld, SwDoc * pDocument)
+ : SwUndoFmtDelete(UNDO_CHARFMT_DELETE, pOld, pDocument)
+{
+}
+
+SwFmt * SwUndoCharFmtDelete::Create(SwFmt * pDerivedFrom)
+{
+ return pDoc->MakeCharFmt(sOldName, (SwCharFmt *) pDerivedFrom, sal_True);
+}
+
+void SwUndoCharFmtDelete::Delete(SwFmt * pFmt)
+{
+ pDoc->DelCharFmt((SwCharFmt *) pFmt, sal_True);
+}
+
+SwFmt * SwUndoCharFmtDelete::Find(const String & rName) const
+{
+ return pDoc->FindCharFmtByName(rName);
+}
+
+SwUndoRenameCharFmt::SwUndoRenameCharFmt(const String & sInitOldName,
+ const String & sInitNewName,
+ SwDoc * pDocument)
+ : SwUndoRenameFmt(UNDO_CHARFMT_RENAME, sInitOldName, sInitNewName, pDocument)
+{
+}
+
+SwFmt * SwUndoRenameCharFmt::Find(const String & rName) const
+{
+ return pDoc->FindCharFmtByName(rName);
+}
+
+SwUndoFrmFmtCreate::SwUndoFrmFmtCreate(SwFrmFmt * pNewFmt,
+ SwFrmFmt * pDerivedFrom,
+ SwDoc * pDocument)
+ : SwUndoFmtCreate(UNDO_FRMFMT_CREATE, pNewFmt, pDerivedFrom, pDocument),
+ bAuto(pNewFmt->IsAuto())
+{
+}
+
+SwFmt * SwUndoFrmFmtCreate::Create(SwFmt * pDerivedFrom)
+{
+ return pDoc->MakeFrmFmt(sNewName, (SwFrmFmt *) pDerivedFrom, sal_True, bAuto);
+}
+
+void SwUndoFrmFmtCreate::Delete()
+{
+ pDoc->DelFrmFmt((SwFrmFmt *) pNew, sal_True);
+}
+
+SwFmt * SwUndoFrmFmtCreate::Find(const String & rName) const
+{
+ return pDoc->FindFrmFmtByName(rName);
+}
+
+SwUndoFrmFmtDelete::SwUndoFrmFmtDelete(SwFrmFmt * pOld, SwDoc * pDocument)
+ : SwUndoFmtDelete(UNDO_FRMFMT_DELETE, pOld, pDocument)
+{
+}
+
+SwFmt * SwUndoFrmFmtDelete::Create(SwFmt * pDerivedFrom)
+{
+ return pDoc->MakeFrmFmt(sOldName, (SwFrmFmt *) pDerivedFrom, sal_True);
+}
+
+void SwUndoFrmFmtDelete::Delete(SwFmt * pFmt)
+{
+ pDoc->DelFrmFmt((SwFrmFmt *) pFmt, sal_True);
+}
+
+SwFmt * SwUndoFrmFmtDelete::Find(const String & rName) const
+{
+ return pDoc->FindFrmFmtByName(rName);
+}
+
+SwUndoRenameFrmFmt::SwUndoRenameFrmFmt(const String & sInitOldName,
+ const String & sInitNewName,
+ SwDoc * pDocument)
+ : SwUndoRenameFmt(UNDO_FRMFMT_RENAME, sInitOldName, sInitNewName, pDocument)
+{
+}
+
+SwFmt * SwUndoRenameFrmFmt::Find(const String & rName) const
+{
+ return pDoc->FindFrmFmtByName(rName);
+}
+
+SwUndoNumruleCreate::SwUndoNumruleCreate(const SwNumRule * _pNew,
+ SwDoc * _pDoc)
+ : SwUndo(UNDO_NUMRULE_CREATE), pNew(_pNew), aNew(*_pNew), pDoc(_pDoc),
+ bInitialized(false)
+{
+}
+
+void SwUndoNumruleCreate::UndoImpl(::sw::UndoRedoContext &)
+{
+ if (! bInitialized)
+ {
+ aNew = *pNew;
+ bInitialized = true;
+ }
+
+ pDoc->DelNumRule(aNew.GetName(), sal_True);
+}
+
+void SwUndoNumruleCreate::RedoImpl(::sw::UndoRedoContext &)
+{
+ pDoc->MakeNumRule(aNew.GetName(), &aNew, sal_True);
+}
+
+SwRewriter SwUndoNumruleCreate::GetRewriter() const
+{
+ SwRewriter aResult;
+
+ if (! bInitialized)
+ {
+ aNew = *pNew;
+ bInitialized = true;
+ }
+
+ aResult.AddRule(UNDO_ARG1, aNew.GetName());
+
+ return aResult;
+}
+
+SwUndoNumruleDelete::SwUndoNumruleDelete(const SwNumRule & rRule,
+ SwDoc * _pDoc)
+ : SwUndo(UNDO_NUMRULE_DELETE), aOld(rRule), pDoc(_pDoc)
+{
+}
+
+void SwUndoNumruleDelete::UndoImpl(::sw::UndoRedoContext &)
+{
+ pDoc->MakeNumRule(aOld.GetName(), &aOld, sal_True);
+}
+
+void SwUndoNumruleDelete::RedoImpl(::sw::UndoRedoContext &)
+{
+ pDoc->DelNumRule(aOld.GetName(), sal_True);
+}
+
+SwRewriter SwUndoNumruleDelete::GetRewriter() const
+{
+ SwRewriter aResult;
+
+ aResult.AddRule(UNDO_ARG1, aOld.GetName());
+
+ return aResult;
+}
+
+SwUndoNumruleRename::SwUndoNumruleRename(const String & _aOldName,
+ const String & _aNewName,
+ SwDoc * _pDoc)
+ : SwUndo(UNDO_NUMRULE_RENAME), aOldName(_aOldName), aNewName(_aNewName),
+ pDoc(_pDoc)
+{
+}
+
+void SwUndoNumruleRename::UndoImpl(::sw::UndoRedoContext &)
+{
+ pDoc->RenameNumRule(aNewName, aOldName, sal_True);
+}
+
+void SwUndoNumruleRename::RedoImpl(::sw::UndoRedoContext &)
+{
+ pDoc->RenameNumRule(aOldName, aNewName, sal_True);
+}
+
+SwRewriter SwUndoNumruleRename::GetRewriter() const
+{
+ SwRewriter aRewriter;
+
+ aRewriter.AddRule(UNDO_ARG1, aOldName);
+ aRewriter.AddRule(UNDO_ARG2, SW_RES(STR_YIELDS));
+ aRewriter.AddRule(UNDO_ARG3, aNewName);
+
+ return aRewriter;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/undo/SwUndoPageDesc.cxx b/sw/source/core/undo/SwUndoPageDesc.cxx
new file mode 100644
index 000000000000..2b6494003109
--- /dev/null
+++ b/sw/source/core/undo/SwUndoPageDesc.cxx
@@ -0,0 +1,435 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+#include <tools/resid.hxx>
+#include <doc.hxx>
+#include <IDocumentUndoRedo.hxx>
+#include <swundo.hxx>
+#include <pagedesc.hxx>
+#include <SwUndoPageDesc.hxx>
+#include <SwRewriter.hxx>
+#include <undobj.hxx>
+#include <comcore.hrc>
+#include <fmtcntnt.hxx>
+#include <fmthdft.hxx>
+
+#ifdef DEBUG
+#include <ndindex.hxx>
+#endif
+
+
+#ifdef DEBUG
+// Pure debug help function to have a quick look at the header/footer attributes.
+void DebugHeaderFooterContent( const SwPageDesc& rPageDesc )
+{
+ sal_uLong nHeaderMaster = ULONG_MAX;
+ sal_uLong nHeaderLeft = ULONG_MAX;
+ sal_uLong nFooterMaster = ULONG_MAX;
+ sal_uLong nFooterLeft = ULONG_MAX;
+
+ SwFmtHeader& rHead = (SwFmtHeader&)rPageDesc.GetMaster().GetHeader();
+ SwFmtFooter& rFoot = (SwFmtFooter&)rPageDesc.GetMaster().GetFooter();
+ SwFmtHeader& rLeftHead = (SwFmtHeader&)rPageDesc.GetLeft().GetHeader();
+ SwFmtFooter& rLeftFoot = (SwFmtFooter&)rPageDesc.GetLeft().GetFooter();
+ if( rHead.IsActive() )
+ {
+ SwFrmFmt* pHeaderFmt = rHead.GetHeaderFmt();
+ if( pHeaderFmt )
+ {
+ nHeaderCount = pHeaderFmt->GetClientCount();
+ {
+ int nHeaderCount = 0;
+ }
+ const SwFmtCntnt* pCntnt = &pHeaderFmt->GetCntnt();
+ if( pCntnt->GetCntntIdx() )
+ nHeaderMaster = pCntnt->GetCntntIdx()->GetIndex();
+ else
+ nHeaderMaster = 0;
+ }
+ SwFrmFmt* pLeftHeaderFmt = rLeftHead.GetHeaderFmt();
+ if( pLeftHeaderFmt )
+ {
+ nLeftHeaderCount = pLeftHeaderFmt->GetClientCount();
+ {
+ int nLeftHeaderCount = 0;
+ }
+ const SwFmtCntnt* pLeftCntnt = &pLeftHeaderFmt->GetCntnt();
+ if( pLeftCntnt->GetCntntIdx() )
+ nHeaderLeft = pLeftCntnt->GetCntntIdx()->GetIndex();
+ else
+ nHeaderLeft = 0;
+ }
+ }
+ if( rFoot.IsActive() )
+ {
+ SwFrmFmt* pFooterFmt = rFoot.GetFooterFmt();
+ if( pFooterFmt )
+ {
+ nFooterCount = pFooterFmt->GetClientCount();
+ {
+ int nFooterCount = 0;
+ }
+ const SwFmtCntnt* pCntnt = &pFooterFmt->GetCntnt();
+ if( pCntnt->GetCntntIdx() )
+ nFooterMaster = pCntnt->GetCntntIdx()->GetIndex();
+ else
+ nFooterMaster = 0;
+ }
+ SwFrmFmt* pLeftFooterFmt = rLeftFoot.GetFooterFmt();
+ if( pLeftFooterFmt )
+ {
+ nLeftFooterCount = pLeftFooterFmt->GetClientCount();
+ {
+ int nLeftFooterCount = 0;
+ }
+ const SwFmtCntnt* pLeftCntnt = &pLeftFooterFmt->GetCntnt();
+ if( pLeftCntnt->GetCntntIdx() )
+ nFooterLeft = pLeftCntnt->GetCntntIdx()->GetIndex();
+ else
+ nFooterLeft = 0;
+ }
+ }
+ int i = 0;
+ ++i; // To set a breakpoint
+}
+#endif
+
+SwUndoPageDesc::SwUndoPageDesc(const SwPageDesc & _aOld,
+ const SwPageDesc & _aNew,
+ SwDoc * _pDoc)
+ : SwUndo( _aOld.GetName() != _aNew.GetName() ?
+ UNDO_RENAME_PAGEDESC :
+ UNDO_CHANGE_PAGEDESC ),
+ aOld(_aOld, _pDoc), aNew(_aNew, _pDoc), pDoc(_pDoc), bExchange( false )
+{
+ OSL_ENSURE(0 != pDoc, "no document?");
+
+#ifdef DEBUG
+ DebugHeaderFooterContent( (SwPageDesc&)aOld );
+ DebugHeaderFooterContent( (SwPageDesc&)aNew );
+#endif
+
+ /*
+ The page description changes.
+ If there are no header/footer content changes like header on/off or change from shared content
+ to unshared etc., there is no reason to duplicate the content nodes (Crash i55547)
+ But this happens, this Undo Ctor will destroy the unnecessary duplicate and manipulate the
+ content pointer of the both page descriptions.
+ */
+ SwPageDesc &rOldDesc = (SwPageDesc&)aOld;
+ SwPageDesc &rNewDesc = (SwPageDesc&)aNew;
+ const SwFmtHeader& rOldHead = rOldDesc.GetMaster().GetHeader();
+ const SwFmtHeader& rNewHead = rNewDesc.GetMaster().GetHeader();
+ const SwFmtFooter& rOldFoot = rOldDesc.GetMaster().GetFooter();
+ const SwFmtFooter& rNewFoot = rNewDesc.GetMaster().GetFooter();
+ /* bExchange must not be set, if the old page descriptor will stay active.
+ Two known situations:
+ #i67735#: renaming a page descriptor
+ #i67334#: changing the follow style
+ If header/footer will be activated or deactivated, this undo will not work.
+ */
+ bExchange = ( aOld.GetName() == aNew.GetName() ) &&
+ ( _aOld.GetFollow() == _aNew.GetFollow() ) &&
+ ( rOldHead.IsActive() == rNewHead.IsActive() ) &&
+ ( rOldFoot.IsActive() == rNewFoot.IsActive() );
+ if( rOldHead.IsActive() && ( rOldDesc.IsHeaderShared() != rNewDesc.IsHeaderShared() ) )
+ bExchange = false;
+ if( rOldFoot.IsActive() && ( rOldDesc.IsFooterShared() != rNewDesc.IsFooterShared() ) )
+ bExchange = false;
+ if( bExchange )
+ {
+ if( rNewHead.IsActive() )
+ {
+ SwFrmFmt* pFormat = new SwFrmFmt( *rNewHead.GetHeaderFmt() );
+ // The Ctor of this object will remove the duplicate!
+ SwFmtHeader aFmtHeader( pFormat );
+ if( !rNewDesc.IsHeaderShared() )
+ {
+ pFormat = new SwFrmFmt( *rNewDesc.GetLeft().GetHeader().GetHeaderFmt() );
+ // The Ctor of this object will remove the duplicate!
+ SwFmtHeader aFormatHeader( pFormat );
+ }
+ }
+ // Same procedure for footers...
+ if( rNewFoot.IsActive() )
+ {
+ SwFrmFmt* pFormat = new SwFrmFmt( *rNewFoot.GetFooterFmt() );
+ // The Ctor of this object will remove the duplicate!
+ SwFmtFooter aFmtFooter( pFormat );
+ if( !rNewDesc.IsFooterShared() )
+ {
+ pFormat = new SwFrmFmt( *rNewDesc.GetLeft().GetFooter().GetFooterFmt() );
+ // The Ctor of this object will remove the duplicate!
+ SwFmtFooter aFormatFooter( pFormat );
+ }
+ }
+
+ // After this exchange method the old page description will point to zero,
+ // the new one will point to the node position of the original content nodes.
+ ExchangeContentNodes( (SwPageDesc&)aOld, (SwPageDesc&)aNew );
+#ifdef DEBUG
+ DebugHeaderFooterContent( (SwPageDesc&)aOld );
+ DebugHeaderFooterContent( (SwPageDesc&)aNew );
+#endif
+ }
+}
+
+SwUndoPageDesc::~SwUndoPageDesc()
+{
+}
+
+
+void SwUndoPageDesc::ExchangeContentNodes( SwPageDesc& rSource, SwPageDesc &rDest )
+{
+ OSL_ENSURE( bExchange, "You shouldn't do that." );
+ const SwFmtHeader& rDestHead = rDest.GetMaster().GetHeader();
+ const SwFmtHeader& rSourceHead = rSource.GetMaster().GetHeader();
+ if( rDestHead.IsActive() )
+ {
+ // Let the destination page descrition point to the source node position,
+ // from now on this descriptor is responsible for the content nodes!
+ const SfxPoolItem* pItem;
+ rDest.GetMaster().GetAttrSet().GetItemState( RES_HEADER, sal_False, &pItem );
+ SfxPoolItem *pNewItem = pItem->Clone();
+ SwFrmFmt* pNewFmt = ((SwFmtHeader*)pNewItem)->GetHeaderFmt();
+#ifdef DEBUG
+ const SwFmtCntnt& rSourceCntnt = rSourceHead.GetHeaderFmt()->GetCntnt();
+ (void)rSourceCntnt;
+ const SwFmtCntnt& rDestCntnt = rDestHead.GetHeaderFmt()->GetCntnt();
+ (void)rDestCntnt;
+#endif
+ pNewFmt->SetFmtAttr( rSourceHead.GetHeaderFmt()->GetCntnt() );
+ delete pNewItem;
+
+ // Let the source page description point to zero node position,
+ // it loses the responsible and can be destroyed without removing the content nodes.
+ rSource.GetMaster().GetAttrSet().GetItemState( RES_HEADER, sal_False, &pItem );
+ pNewItem = pItem->Clone();
+ pNewFmt = ((SwFmtHeader*)pNewItem)->GetHeaderFmt();
+ pNewFmt->SetFmtAttr( SwFmtCntnt() );
+ delete pNewItem;
+
+ if( !rDest.IsHeaderShared() )
+ {
+ // Same procedure for unshared header..
+ const SwFmtHeader& rSourceLeftHead = rSource.GetLeft().GetHeader();
+ rDest.GetLeft().GetAttrSet().GetItemState( RES_HEADER, sal_False, &pItem );
+ pNewItem = pItem->Clone();
+ pNewFmt = ((SwFmtHeader*)pNewItem)->GetHeaderFmt();
+#ifdef DEBUG
+ const SwFmtCntnt& rSourceCntnt1 = rSourceLeftHead.GetHeaderFmt()->GetCntnt();
+ (void)rSourceCntnt1;
+ const SwFmtCntnt& rDestCntnt1 = rDest.GetLeft().GetHeader().GetHeaderFmt()->GetCntnt();
+ (void)rDestCntnt1;
+#endif
+ pNewFmt->SetFmtAttr( rSourceLeftHead.GetHeaderFmt()->GetCntnt() );
+ delete pNewItem;
+ rSource.GetLeft().GetAttrSet().GetItemState( RES_HEADER, sal_False, &pItem );
+ pNewItem = pItem->Clone();
+ pNewFmt = ((SwFmtHeader*)pNewItem)->GetHeaderFmt();
+ pNewFmt->SetFmtAttr( SwFmtCntnt() );
+ delete pNewItem;
+ }
+ }
+ // Same procedure for footers...
+ const SwFmtFooter& rDestFoot = rDest.GetMaster().GetFooter();
+ const SwFmtFooter& rSourceFoot = rSource.GetMaster().GetFooter();
+ if( rDestFoot.IsActive() )
+ {
+ const SfxPoolItem* pItem;
+ rDest.GetMaster().GetAttrSet().GetItemState( RES_FOOTER, sal_False, &pItem );
+ SfxPoolItem *pNewItem = pItem->Clone();
+ SwFrmFmt *pNewFmt = ((SwFmtFooter*)pNewItem)->GetFooterFmt();
+ pNewFmt->SetFmtAttr( rSourceFoot.GetFooterFmt()->GetCntnt() );
+ delete pNewItem;
+
+#ifdef DEBUG
+ const SwFmtCntnt& rFooterSourceCntnt = rSourceFoot.GetFooterFmt()->GetCntnt();
+ (void)rFooterSourceCntnt;
+ const SwFmtCntnt& rFooterDestCntnt = rDestFoot.GetFooterFmt()->GetCntnt();
+ (void)rFooterDestCntnt;
+#endif
+ rSource.GetMaster().GetAttrSet().GetItemState( RES_FOOTER, sal_False, &pItem );
+ pNewItem = pItem->Clone();
+ pNewFmt = ((SwFmtFooter*)pNewItem)->GetFooterFmt();
+ pNewFmt->SetFmtAttr( SwFmtCntnt() );
+ delete pNewItem;
+
+ if( !rDest.IsFooterShared() )
+ {
+ const SwFmtFooter& rSourceLeftFoot = rSource.GetLeft().GetFooter();
+#ifdef DEBUG
+ const SwFmtCntnt& rFooterSourceCntnt2 = rSourceLeftFoot.GetFooterFmt()->GetCntnt();
+ const SwFmtCntnt& rFooterDestCntnt2 =
+ rDest.GetLeft().GetFooter().GetFooterFmt()->GetCntnt();
+ (void)rFooterSourceCntnt2;
+ (void)rFooterDestCntnt2;
+#endif
+ rDest.GetLeft().GetAttrSet().GetItemState( RES_FOOTER, sal_False, &pItem );
+ pNewItem = pItem->Clone();
+ pNewFmt = ((SwFmtFooter*)pNewItem)->GetFooterFmt();
+ pNewFmt->SetFmtAttr( rSourceLeftFoot.GetFooterFmt()->GetCntnt() );
+ delete pNewItem;
+ rSource.GetLeft().GetAttrSet().GetItemState( RES_FOOTER, sal_False, &pItem );
+ pNewItem = pItem->Clone();
+ pNewFmt = ((SwFmtFooter*)pNewItem)->GetFooterFmt();
+ pNewFmt->SetFmtAttr( SwFmtCntnt() );
+ delete pNewItem;
+ }
+ }
+}
+
+void SwUndoPageDesc::UndoImpl(::sw::UndoRedoContext &)
+{
+ // Move (header/footer)content node responsibility from new page descriptor to old one again.
+ if( bExchange )
+ ExchangeContentNodes( (SwPageDesc&)aNew, (SwPageDesc&)aOld );
+ pDoc->ChgPageDesc(aOld.GetName(), aOld);
+}
+
+void SwUndoPageDesc::RedoImpl(::sw::UndoRedoContext &)
+{
+ // Move (header/footer)content node responsibility from old page descriptor to new one again.
+ if( bExchange )
+ ExchangeContentNodes( (SwPageDesc&)aOld, (SwPageDesc&)aNew );
+ pDoc->ChgPageDesc(aNew.GetName(), aNew);
+}
+
+SwRewriter SwUndoPageDesc::GetRewriter() const
+{
+ SwRewriter aResult;
+
+ aResult.AddRule(UNDO_ARG1, aOld.GetName());
+ aResult.AddRule(UNDO_ARG2, SW_RES(STR_YIELDS));
+ aResult.AddRule(UNDO_ARG3, aNew.GetName());
+
+ return aResult;
+}
+
+// #116530#
+SwUndoPageDescCreate::SwUndoPageDescCreate(const SwPageDesc * pNew,
+ SwDoc * _pDoc)
+ : SwUndo(UNDO_CREATE_PAGEDESC), pDesc(pNew), aNew(*pNew, _pDoc),
+ pDoc(_pDoc)
+{
+ OSL_ENSURE(0 != pDoc, "no document?");
+}
+
+SwUndoPageDescCreate::~SwUndoPageDescCreate()
+{
+}
+
+void SwUndoPageDescCreate::UndoImpl(::sw::UndoRedoContext &)
+{
+ // -> #116530#
+ if (pDesc)
+ {
+ aNew = *pDesc;
+ pDesc = NULL;
+ }
+ // <- #116530#
+
+ pDoc->DelPageDesc(aNew.GetName(), sal_True);
+}
+
+void SwUndoPageDescCreate::DoImpl()
+{
+ SwPageDesc aPageDesc = aNew;
+ pDoc->MakePageDesc(aNew.GetName(), &aPageDesc, sal_False, sal_True); // #116530#
+}
+
+void SwUndoPageDescCreate::RedoImpl(::sw::UndoRedoContext &)
+{
+ DoImpl();
+}
+
+void SwUndoPageDescCreate::RepeatImpl(::sw::RepeatContext &)
+{
+ ::sw::UndoGuard const undoGuard(pDoc->GetIDocumentUndoRedo());
+ DoImpl();
+}
+
+SwRewriter SwUndoPageDescCreate::GetRewriter() const
+{
+ SwRewriter aResult;
+
+ if (pDesc)
+ aResult.AddRule(UNDO_ARG1, pDesc->GetName());
+ else
+ aResult.AddRule(UNDO_ARG1, aNew.GetName());
+
+
+ return aResult;
+}
+
+SwUndoPageDescDelete::SwUndoPageDescDelete(const SwPageDesc & _aOld,
+ SwDoc * _pDoc)
+ : SwUndo(UNDO_DELETE_PAGEDESC), aOld(_aOld, _pDoc), pDoc(_pDoc)
+{
+ OSL_ENSURE(0 != pDoc, "no document?");
+}
+
+SwUndoPageDescDelete::~SwUndoPageDescDelete()
+{
+}
+
+void SwUndoPageDescDelete::UndoImpl(::sw::UndoRedoContext &)
+{
+ SwPageDesc aPageDesc = aOld;
+ pDoc->MakePageDesc(aOld.GetName(), &aPageDesc, sal_False, sal_True); // #116530#
+}
+
+void SwUndoPageDescDelete::DoImpl()
+{
+ pDoc->DelPageDesc(aOld.GetName(), sal_True); // #116530#
+}
+
+void SwUndoPageDescDelete::RedoImpl(::sw::UndoRedoContext &)
+{
+ DoImpl();
+}
+
+void SwUndoPageDescDelete::RepeatImpl(::sw::RepeatContext &)
+{
+ ::sw::UndoGuard const undoGuard(pDoc->GetIDocumentUndoRedo());
+ DoImpl();
+}
+
+SwRewriter SwUndoPageDescDelete::GetRewriter() const
+{
+ SwRewriter aResult;
+
+ aResult.AddRule(UNDO_ARG1, aOld.GetName());
+
+ return aResult;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/undo/SwUndoTOXChange.cxx b/sw/source/core/undo/SwUndoTOXChange.cxx
new file mode 100644
index 000000000000..8b5b8c254090
--- /dev/null
+++ b/sw/source/core/undo/SwUndoTOXChange.cxx
@@ -0,0 +1,79 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+#include <SwUndoTOXChange.hxx>
+#include <swundo.hxx>
+#include <doctxm.hxx>
+
+SwUndoTOXChange::SwUndoTOXChange(SwTOXBase * _pTOX, const SwTOXBase & rNew)
+ : SwUndo(UNDO_TOXCHANGE), pTOX(_pTOX), aOld(*_pTOX), aNew(rNew)
+{
+}
+
+SwUndoTOXChange::~SwUndoTOXChange()
+{
+}
+
+void SwUndoTOXChange::UpdateTOXBaseSection()
+{
+ if (pTOX->ISA(SwTOXBaseSection))
+ {
+ SwTOXBaseSection * pTOXBase = static_cast<SwTOXBaseSection *>(pTOX);
+ pTOXBase->Update();
+ pTOXBase->UpdatePageNum();
+ }
+}
+
+void SwUndoTOXChange::UndoImpl(::sw::UndoRedoContext &)
+{
+ *pTOX = aOld;
+
+ UpdateTOXBaseSection();
+}
+
+void SwUndoTOXChange::DoImpl()
+{
+ *pTOX = aNew;
+
+ UpdateTOXBaseSection();
+}
+
+void SwUndoTOXChange::RedoImpl(::sw::UndoRedoContext &)
+{
+ DoImpl();
+}
+
+void SwUndoTOXChange::RepeatImpl(::sw::RepeatContext &)
+{
+ DoImpl();
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/undo/docundo.cxx b/sw/source/core/undo/docundo.cxx
new file mode 100644
index 000000000000..441bf84096a4
--- /dev/null
+++ b/sw/source/core/undo/docundo.cxx
@@ -0,0 +1,581 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+#include <UndoManager.hxx>
+
+#include <unotools/undoopt.hxx>
+
+#include <vcl/wrkwin.hxx>
+
+#include <svx/svdmodel.hxx>
+
+#include <swmodule.hxx>
+#include <doc.hxx>
+#include <ndarr.hxx>
+#include <pam.hxx>
+#include <ndtxt.hxx>
+#include <swundo.hxx>
+#include <UndoCore.hxx>
+#include <rolbck.hxx>
+#include <undo.hrc>
+#include <editsh.hxx>
+#include <unobaseclass.hxx>
+
+#include <limits>
+
+using namespace ::com::sun::star;
+
+
+// the undo array should never grow beyond this limit:
+#define UNDO_ACTION_LIMIT (USHRT_MAX - 1000)
+
+
+// UndoManager ///////////////////////////////////////////////////////////
+
+namespace sw {
+
+UndoManager::UndoManager(::std::auto_ptr<SwNodes> pUndoNodes,
+ IDocumentDrawModelAccess & rDrawModelAccess,
+ IDocumentRedlineAccess & rRedlineAccess,
+ IDocumentState & rState)
+ : m_rDrawModelAccess(rDrawModelAccess)
+ , m_rRedlineAccess(rRedlineAccess)
+ , m_rState(rState)
+ , m_pUndoNodes(pUndoNodes)
+ , m_bGroupUndo(true)
+ , m_bDrawUndo(true)
+ , m_bLockUndoNoModifiedPosition(false)
+ , m_UndoSaveMark(MARK_INVALID)
+{
+ OSL_ASSERT(m_pUndoNodes.get());
+ // writer expects it to be disabled initially
+ // Undo is enabled by SwEditShell constructor
+ SfxUndoManager::EnableUndo(false);
+}
+
+SwNodes const& UndoManager::GetUndoNodes() const
+{
+ return *m_pUndoNodes;
+}
+
+SwNodes & UndoManager::GetUndoNodes()
+{
+ return *m_pUndoNodes;
+}
+
+bool UndoManager::IsUndoNodes(SwNodes const& rNodes) const
+{
+ return & rNodes == m_pUndoNodes.get();
+}
+
+void UndoManager::DoUndo(bool const bDoUndo)
+{
+ EnableUndo(bDoUndo);
+
+ SdrModel *const pSdrModel = m_rDrawModelAccess.GetDrawModel();
+ if( pSdrModel )
+ {
+ pSdrModel->EnableUndo(bDoUndo);
+ }
+}
+
+bool UndoManager::DoesUndo() const
+{
+ return IsUndoEnabled();
+}
+
+void UndoManager::DoGroupUndo(bool const bDoUndo)
+{
+ m_bGroupUndo = bDoUndo;
+}
+
+bool UndoManager::DoesGroupUndo() const
+{
+ return m_bGroupUndo;
+}
+
+void UndoManager::DoDrawUndo(bool const bDoUndo)
+{
+ m_bDrawUndo = bDoUndo;
+}
+
+bool UndoManager::DoesDrawUndo() const
+{
+ return m_bDrawUndo;
+}
+
+
+bool UndoManager::IsUndoNoResetModified() const
+{
+ return MARK_INVALID == m_UndoSaveMark;
+}
+
+void UndoManager::SetUndoNoResetModified()
+{
+ if (MARK_INVALID != m_UndoSaveMark)
+ {
+ RemoveMark(m_UndoSaveMark);
+ m_UndoSaveMark = MARK_INVALID;
+ }
+}
+
+void UndoManager::SetUndoNoModifiedPosition()
+{
+ if (!m_bLockUndoNoModifiedPosition)
+ {
+ m_UndoSaveMark = MarkTopUndoAction();
+ }
+}
+
+void UndoManager::LockUndoNoModifiedPosition()
+{
+ m_bLockUndoNoModifiedPosition = true;
+}
+
+void UndoManager::UnLockUndoNoModifiedPosition()
+{
+ m_bLockUndoNoModifiedPosition = false;
+}
+
+
+SwUndo* UndoManager::GetLastUndo()
+{
+ if (!SfxUndoManager::GetUndoActionCount(CurrentLevel))
+ {
+ return 0;
+ }
+ SfxUndoAction *const pAction( SfxUndoManager::GetUndoAction(0) );
+ return dynamic_cast<SwUndo*>(pAction);
+}
+
+void UndoManager::AppendUndo(SwUndo *const pUndo)
+{
+ AddUndoAction(pUndo);
+}
+
+void UndoManager::ClearRedo()
+{
+ return SfxUndoManager::ImplClearRedo_NoLock(TopLevel);
+}
+
+void UndoManager::DelAllUndoObj()
+{
+ ::sw::UndoGuard const undoGuard(*this);
+
+ SfxUndoManager::ClearAllLevels();
+
+ m_UndoSaveMark = MARK_INVALID;
+}
+
+
+/**************** UNDO ******************/
+
+SwUndoId
+UndoManager::StartUndo(SwUndoId const i_eUndoId,
+ SwRewriter const*const pRewriter)
+{
+ if (!IsUndoEnabled())
+ {
+ return UNDO_EMPTY;
+ }
+
+ SwUndoId const eUndoId( (0 == i_eUndoId) ? UNDO_START : i_eUndoId );
+
+ OSL_ASSERT(UNDO_END != eUndoId);
+ String comment( (UNDO_START == eUndoId)
+ ? String("??", RTL_TEXTENCODING_ASCII_US)
+ : String(SW_RES(UNDO_BASE + eUndoId)) );
+ if (pRewriter)
+ {
+ OSL_ASSERT(UNDO_START != eUndoId);
+ comment = pRewriter->Apply(comment);
+ }
+
+ SfxUndoManager::EnterListAction(comment, comment, eUndoId);
+
+ return eUndoId;
+}
+
+
+SwUndoId
+UndoManager::EndUndo(SwUndoId const i_eUndoId, SwRewriter const*const pRewriter)
+{
+ if (!IsUndoEnabled())
+ {
+ return UNDO_EMPTY;
+ }
+
+ SwUndoId const eUndoId( ((0 == i_eUndoId) || (UNDO_START == i_eUndoId))
+ ? UNDO_END : i_eUndoId );
+ OSL_ENSURE(!((UNDO_END == eUndoId) && pRewriter),
+ "EndUndo(): no Undo ID, but rewriter given?");
+
+ SfxUndoAction *const pLastUndo(
+ (0 == SfxUndoManager::GetUndoActionCount(CurrentLevel))
+ ? 0 : SfxUndoManager::GetUndoAction(0) );
+
+ int const nCount = LeaveListAction();
+
+ if (nCount) // otherwise: empty list action not inserted!
+ {
+ OSL_ASSERT(pLastUndo);
+ OSL_ASSERT(UNDO_START != eUndoId);
+ SfxUndoAction *const pUndoAction(SfxUndoManager::GetUndoAction(0));
+ SfxListUndoAction *const pListAction(
+ dynamic_cast<SfxListUndoAction*>(pUndoAction));
+ OSL_ASSERT(pListAction);
+ if (pListAction)
+ {
+ if (UNDO_END != eUndoId)
+ {
+ OSL_ENSURE(pListAction->GetId() == eUndoId,
+ "EndUndo(): given ID different from StartUndo()");
+ // comment set by caller of EndUndo
+ String comment = String(SW_RES(UNDO_BASE + eUndoId));
+ if (pRewriter)
+ {
+ comment = pRewriter->Apply(comment);
+ }
+ pListAction->SetComment(comment);
+ }
+ else if ((UNDO_START != pListAction->GetId()))
+ {
+ // comment set by caller of StartUndo: nothing to do here
+ }
+ else if (pLastUndo)
+ {
+ // comment was not set at StartUndo or EndUndo:
+ // take comment of last contained action
+ // (note that this works recursively, i.e. the last contained
+ // action may be a list action created by StartUndo/EndUndo)
+ String const comment(pLastUndo->GetComment());
+ pListAction->SetComment(comment);
+ }
+ else
+ {
+ OSL_ENSURE(false, "EndUndo(): no comment?");
+ }
+ }
+ }
+
+ return eUndoId;
+}
+
+bool
+UndoManager::GetLastUndoInfo(
+ ::rtl::OUString *const o_pStr, SwUndoId *const o_pId) const
+{
+ // this is actually expected to work on the current level,
+ // but that was really not obvious from the previous implementation...
+ if (!SfxUndoManager::GetUndoActionCount(CurrentLevel))
+ {
+ return false;
+ }
+
+ SfxUndoAction *const pAction( SfxUndoManager::GetUndoAction(0) );
+ if (o_pStr)
+ {
+ *o_pStr = pAction->GetComment();
+ }
+ if (o_pId)
+ {
+ sal_uInt16 const nId(pAction->GetId());
+ *o_pId = static_cast<SwUndoId>(nId);
+ }
+
+ return true;
+}
+
+SwUndoComments_t UndoManager::GetUndoComments() const
+{
+ OSL_ENSURE(!SfxUndoManager::IsInListAction(),
+ "GetUndoComments() called while in list action?");
+
+ SwUndoComments_t ret;
+ sal_uInt16 const nUndoCount(SfxUndoManager::GetUndoActionCount(TopLevel));
+ for (sal_uInt16 n = 0; n < nUndoCount; ++n)
+ {
+ ::rtl::OUString const comment(
+ SfxUndoManager::GetUndoActionComment(n, TopLevel));
+ ret.push_back(comment);
+ }
+
+ return ret;
+}
+
+
+/**************** REDO ******************/
+bool UndoManager::GetFirstRedoInfo(::rtl::OUString *const o_pStr) const
+{
+ if (!SfxUndoManager::GetRedoActionCount(CurrentLevel))
+ {
+ return false;
+ }
+
+ if (o_pStr)
+ {
+ *o_pStr = SfxUndoManager::GetRedoActionComment(0, CurrentLevel);
+ }
+
+ return true;
+}
+
+
+SwUndoComments_t UndoManager::GetRedoComments() const
+{
+ OSL_ENSURE(!SfxUndoManager::IsInListAction(),
+ "GetRedoComments() called while in list action?");
+
+ SwUndoComments_t ret;
+ sal_uInt16 const nRedoCount(SfxUndoManager::GetRedoActionCount(TopLevel));
+ for (sal_uInt16 n = 0; n < nRedoCount; ++n)
+ {
+ ::rtl::OUString const comment(
+ SfxUndoManager::GetRedoActionComment(n, TopLevel));
+ ret.push_back(comment);
+ }
+
+ return ret;
+}
+
+/**************** REPEAT ******************/
+
+SwUndoId UndoManager::GetRepeatInfo(::rtl::OUString *const o_pStr) const
+{
+ SwUndoId nRepeatId(UNDO_EMPTY);
+ GetLastUndoInfo(o_pStr, & nRepeatId);
+ if( REPEAT_START <= nRepeatId && REPEAT_END > nRepeatId )
+ {
+ return nRepeatId;
+ }
+ if (o_pStr) // not repeatable -> clear comment
+ {
+ *o_pStr = String();
+ }
+ return UNDO_EMPTY;
+}
+
+SwUndo * UndoManager::RemoveLastUndo()
+{
+ if (SfxUndoManager::GetRedoActionCount(CurrentLevel) ||
+ SfxUndoManager::GetRedoActionCount(TopLevel))
+ {
+ OSL_ENSURE(false, "RemoveLastUndoAction(): there are Redo actions?");
+ return 0;
+ }
+ if (!SfxUndoManager::GetUndoActionCount(CurrentLevel))
+ {
+ OSL_ENSURE(false, "RemoveLastUndoAction(): no Undo actions");
+ return 0;
+ }
+ SfxUndoAction *const pLastUndo(GetUndoAction(0));
+ SfxUndoManager::RemoveLastUndoAction();
+ return dynamic_cast<SwUndo *>(pLastUndo);
+}
+
+// svl::IUndoManager /////////////////////////////////////////////////////
+
+void UndoManager::EnableUndo(bool bEnable)
+{
+ // UGLY: SfxUndoManager has a counter to match enable/disable calls
+ // but the writer code expects that a single call switches
+ while (IsUndoEnabled() != bEnable)
+ {
+ SfxUndoManager::EnableUndo(bEnable);
+ }
+}
+
+void UndoManager::AddUndoAction(SfxUndoAction *pAction, sal_Bool bTryMerge)
+{
+ SwUndo *const pUndo( dynamic_cast<SwUndo *>(pAction) );
+ if (pUndo)
+ {
+ if (nsRedlineMode_t::REDLINE_NONE == pUndo->GetRedlineMode())
+ {
+ pUndo->SetRedlineMode( m_rRedlineAccess.GetRedlineMode() );
+ }
+ }
+ SfxUndoManager::AddUndoAction(pAction, bTryMerge);
+ // if the undo nodes array is too large, delete some actions
+ while (UNDO_ACTION_LIMIT < GetUndoNodes().Count())
+ {
+ RemoveOldestUndoActions(1);
+ }
+}
+
+class CursorGuard
+{
+public:
+ CursorGuard(SwEditShell & rShell, bool const bSave)
+ : m_rShell(rShell)
+ , m_bSaveCursor(bSave)
+ {
+ if (m_bSaveCursor)
+ {
+ m_rShell.Push(); // prevent modification of current cursor
+ }
+ }
+ ~CursorGuard()
+ {
+ if (m_bSaveCursor)
+ {
+ m_rShell.Pop();
+ }
+ }
+private:
+ SwEditShell & m_rShell;
+ bool const m_bSaveCursor;
+};
+
+bool UndoManager::impl_DoUndoRedo(UndoOrRedo_t const undoOrRedo)
+{
+ SwDoc & rDoc(*GetUndoNodes().GetDoc());
+
+ UnoActionContext c(& rDoc); // exception-safe StartAllAction/EndAllAction
+
+ SwEditShell *const pEditShell( rDoc.GetEditShell() );
+
+ OSL_ENSURE(pEditShell, "sw::UndoManager needs a SwEditShell!");
+ if (!pEditShell)
+ {
+ throw uno::RuntimeException();
+ }
+
+ // in case the model has controllers locked, the Undo should not
+ // change the view cursors!
+ bool const bSaveCursors(pEditShell->CursorsLocked());
+ CursorGuard(*pEditShell, bSaveCursors);
+ if (!bSaveCursors)
+ {
+ // (in case Undo was called via API) clear the cursors:
+ pEditShell->KillPams();
+ pEditShell->SetMark();
+ pEditShell->ClearMark();
+ }
+
+ bool bRet(false);
+
+ ::sw::UndoRedoContext context(rDoc, *pEditShell);
+
+ // N.B. these may throw!
+ if (UNDO == undoOrRedo)
+ {
+ bRet = SfxUndoManager::UndoWithContext(context);
+ }
+ else
+ {
+ bRet = SfxUndoManager::RedoWithContext(context);
+ }
+
+ if (bRet)
+ {
+ // if we are at the "last save" position, the document is not modified
+ if (SfxUndoManager::HasTopUndoActionMark(m_UndoSaveMark))
+ {
+ m_rState.ResetModified();
+ }
+ else
+ {
+ m_rState.SetModified();
+ }
+ }
+
+ pEditShell->HandleUndoRedoContext(context);
+
+ return bRet;
+}
+
+sal_Bool UndoManager::Undo()
+{
+ bool const bRet = impl_DoUndoRedo(UNDO);
+ return bRet;
+}
+
+sal_Bool UndoManager::Redo()
+{
+ bool const bRet = impl_DoUndoRedo(REDO);
+ return bRet;
+}
+
+/** N.B.: this does _not_ call SfxUndoManager::Repeat because it is not
+ possible to wrap a list action around it:
+ calling EnterListAction here will cause SfxUndoManager::Repeat
+ to repeat the list action!
+ */
+bool
+UndoManager::Repeat(::sw::RepeatContext & rContext,
+ sal_uInt16 const nRepeatCount)
+{
+ if (SfxUndoManager::IsInListAction())
+ {
+ OSL_ENSURE(false, "repeat in open list action???");
+ return false;
+ }
+ if (!SfxUndoManager::GetUndoActionCount(TopLevel))
+ {
+ return false;
+ }
+ SfxUndoAction *const pRepeatAction(GetUndoAction(0));
+ OSL_ASSERT(pRepeatAction);
+ if (!pRepeatAction || !pRepeatAction->CanRepeat(rContext))
+ {
+ return false;
+ }
+
+ ::rtl::OUString const comment(pRepeatAction->GetComment());
+ ::rtl::OUString const rcomment(pRepeatAction->GetRepeatComment(rContext));
+ sal_uInt16 const nId(pRepeatAction->GetId());
+ if (DoesUndo())
+ {
+ EnterListAction(comment, rcomment, nId);
+ }
+
+ SwPaM *const pFirstCursor(& rContext.GetRepeatPaM());
+ do { // iterate over ring
+ for (sal_uInt16 nRptCnt = nRepeatCount; nRptCnt > 0; --nRptCnt)
+ {
+ pRepeatAction->Repeat(rContext);
+ }
+ rContext.m_bDeleteRepeated = false; // reset for next PaM
+ rContext.m_pCurrentPaM =
+ static_cast<SwPaM*>(rContext.m_pCurrentPaM->GetNext());
+ } while (pFirstCursor != & rContext.GetRepeatPaM());
+
+ if (DoesUndo())
+ {
+ LeaveListAction();
+ }
+ return true;
+}
+
+} // namespace sw
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/undo/rolbck.cxx b/sw/source/core/undo/rolbck.cxx
new file mode 100644
index 000000000000..970403d5cd1f
--- /dev/null
+++ b/sw/source/core/undo/rolbck.cxx
@@ -0,0 +1,1516 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+#include <rolbck.hxx>
+
+#include <tools/resid.hxx>
+
+#include <svl/itemiter.hxx>
+
+#include <editeng/brkitem.hxx>
+
+#include <hints.hxx>
+#include <hintids.hxx>
+#include <fmtftn.hxx>
+#include <fchrfmt.hxx>
+#include <fmtflcnt.hxx>
+#include <fmtrfmrk.hxx>
+#include <fmtfld.hxx>
+#include <fmtpdsc.hxx>
+#include <txtfld.hxx>
+#include <txtrfmrk.hxx>
+#include <txttxmrk.hxx>
+#include <txtftn.hxx>
+#include <txtflcnt.hxx>
+#include <fmtanchr.hxx>
+#include <fmtcnct.hxx>
+#include <frmfmt.hxx>
+#include <ftnidx.hxx>
+#include <doc.hxx> // SwDoc.GetNodes()
+#include <IDocumentUndoRedo.hxx>
+#include <docary.hxx>
+#include <ndtxt.hxx> // SwTxtNode
+#include <paratr.hxx> //
+#include <cellatr.hxx> //
+#include <fldbas.hxx> // fuer Felder
+#include <pam.hxx> // fuer SwPaM
+#include <swtable.hxx>
+#include <ndgrf.hxx> // SwGrfNode
+#include <UndoCore.hxx>
+#include <IMark.hxx> // fuer SwBookmark
+#include <charfmt.hxx> // #i27615#
+#include <comcore.hrc>
+#include <undo.hrc>
+#include <bookmrk.hxx>
+
+SV_IMPL_PTRARR( SwpHstry, SwHistoryHintPtr)
+
+String SwHistoryHint::GetDescription() const
+{
+ return String();
+}
+
+
+SwHistorySetFmt::SwHistorySetFmt( const SfxPoolItem* pFmtHt, sal_uLong nNd )
+ : SwHistoryHint( HSTRY_SETFMTHNT )
+ , m_pAttr( pFmtHt->Clone() )
+ , m_nNodeIndex( nNd )
+{
+ switch ( m_pAttr->Which() )
+ {
+ case RES_PAGEDESC:
+ static_cast<SwFmtPageDesc&>(*m_pAttr).ChgDefinedIn( 0 );
+ break;
+ case RES_PARATR_DROP:
+ static_cast<SwFmtDrop&>(*m_pAttr).ChgDefinedIn( 0 );
+ break;
+ case RES_BOXATR_FORMULA:
+ {
+ //JP 30.07.98: Bug 54295 - Formeln immer im Klartext speichern
+ SwTblBoxFormula& rNew = static_cast<SwTblBoxFormula&>(*m_pAttr);
+ if ( rNew.IsIntrnlName() )
+ {
+ const SwTblBoxFormula& rOld =
+ *static_cast<const SwTblBoxFormula*>(pFmtHt);
+ const SwNode* pNd = rOld.GetNodeOfFormula();
+ if ( pNd )
+ {
+ const SwTableNode* pTableNode = pNd->FindTableNode();
+ if (pTableNode)
+ {
+ SwTableFmlUpdate aMsgHnt( &pTableNode->GetTable() );
+ aMsgHnt.eFlags = TBL_BOXNAME;
+ rNew.ChgDefinedIn( rOld.GetDefinedIn() );
+ rNew.ChangeState( &aMsgHnt );
+ }
+ }
+ }
+ rNew.ChgDefinedIn( 0 );
+ }
+ break;
+ }
+}
+
+String SwHistorySetFmt::GetDescription() const
+{
+ String aResult ;
+
+ sal_uInt16 nWhich = m_pAttr->Which();
+ switch (nWhich)
+ {
+ case RES_BREAK:
+ switch ((static_cast<SvxFmtBreakItem &>(*m_pAttr)).GetBreak())
+ {
+ case SVX_BREAK_PAGE_BEFORE:
+ case SVX_BREAK_PAGE_AFTER:
+ case SVX_BREAK_PAGE_BOTH:
+ aResult = SW_RES(STR_UNDO_PAGEBREAKS);
+
+ break;
+ case SVX_BREAK_COLUMN_BEFORE:
+ case SVX_BREAK_COLUMN_AFTER:
+ case SVX_BREAK_COLUMN_BOTH:
+ aResult = SW_RES(STR_UNDO_COLBRKS);
+
+ break;
+ default:
+ break;
+ }
+ break;
+ default:
+ break;
+ }
+
+ return aResult;
+}
+
+void SwHistorySetFmt::SetInDoc( SwDoc* pDoc, bool bTmpSet )
+{
+ SwNode * pNode = pDoc->GetNodes()[ m_nNodeIndex ];
+ if ( pNode->IsCntntNode() )
+ {
+ static_cast<SwCntntNode*>(pNode)->SetAttr( *m_pAttr );
+ }
+ else if ( pNode->IsTableNode() )
+ {
+ static_cast<SwTableNode*>(pNode)->GetTable().GetFrmFmt()->SetFmtAttr(
+ *m_pAttr );
+ }
+ else if ( pNode->IsStartNode() && (SwTableBoxStartNode ==
+ static_cast<SwStartNode*>(pNode)->GetStartNodeType()) )
+ {
+ SwTableNode* pTNd = pNode->FindTableNode();
+ if ( pTNd )
+ {
+ SwTableBox* pBox = pTNd->GetTable().GetTblBox( m_nNodeIndex );
+ if (pBox)
+ {
+ pBox->ClaimFrmFmt()->SetFmtAttr( *m_pAttr );
+ }
+ }
+ }
+
+ if ( !bTmpSet )
+ {
+ m_pAttr.reset();
+ }
+}
+
+SwHistorySetFmt::~SwHistorySetFmt()
+{
+}
+
+
+SwHistoryResetFmt::SwHistoryResetFmt(const SfxPoolItem* pFmtHt, sal_uLong nNodeIdx)
+ : SwHistoryHint( HSTRY_RESETFMTHNT )
+ , m_nNodeIndex( nNodeIdx )
+ , m_nWhich( pFmtHt->Which() )
+{
+}
+
+
+void SwHistoryResetFmt::SetInDoc( SwDoc* pDoc, bool )
+{
+ SwNode * pNode = pDoc->GetNodes()[ m_nNodeIndex ];
+ if ( pNode->IsCntntNode() )
+ {
+ static_cast<SwCntntNode*>(pNode)->ResetAttr( m_nWhich );
+ }
+ else if ( pNode->IsTableNode() )
+ {
+ static_cast<SwTableNode*>(pNode)->GetTable().GetFrmFmt()->
+ ResetFmtAttr( m_nWhich );
+ }
+}
+
+
+SwHistorySetTxt::SwHistorySetTxt( SwTxtAttr* pTxtHt, sal_uLong nNodePos )
+ : SwHistoryHint( HSTRY_SETTXTHNT )
+ , m_nNodeIndex( nNodePos )
+ , m_nStart( *pTxtHt->GetStart() )
+ , m_nEnd( *pTxtHt->GetAnyEnd() )
+{
+ // !! Achtung: folgende Attribute erzeugen keine FormatAttribute:
+ // - NoLineBreak, NoHypen, Inserted, Deleted
+ // Dafuer muessen Sonderbehandlungen gemacht werden !!!
+
+ // ein bisschen kompliziert, aber ist Ok so: erst vom default
+ // eine Kopie und dann die Werte aus dem Text Attribut zuweisen
+ sal_uInt16 nWhich = pTxtHt->Which();
+ if ( RES_TXTATR_CHARFMT == nWhich )
+ {
+ m_pAttr.reset( new SwFmtCharFmt( pTxtHt->GetCharFmt().GetCharFmt() ) );
+ }
+ else
+ {
+ m_pAttr.reset( pTxtHt->GetAttr().Clone() );
+ }
+}
+
+
+SwHistorySetTxt::~SwHistorySetTxt()
+{
+}
+
+
+void SwHistorySetTxt::SetInDoc( SwDoc* pDoc, bool )
+{
+ if ( !m_pAttr.get() )
+ return;
+
+ if ( RES_TXTATR_CHARFMT == m_pAttr->Which() )
+ {
+ // ask the Doc if the CharFmt still exists
+ if ( USHRT_MAX == pDoc->GetCharFmts()->GetPos(
+ (static_cast<SwFmtCharFmt&>(*m_pAttr)).GetCharFmt() ) )
+ return; // do not set, format does not exist
+ }
+
+ SwTxtNode * pTxtNd = pDoc->GetNodes()[ m_nNodeIndex ]->GetTxtNode();
+ OSL_ENSURE( pTxtNd, "SwHistorySetTxt::SetInDoc: not a TextNode" );
+
+ if ( pTxtNd )
+ {
+ pTxtNd->InsertItem( *m_pAttr, m_nStart, m_nEnd,
+ nsSetAttrMode::SETATTR_NOTXTATRCHR |
+ nsSetAttrMode::SETATTR_NOHINTADJUST );
+ }
+}
+
+
+SwHistorySetTxtFld::SwHistorySetTxtFld( SwTxtFld* pTxtFld, sal_uLong nNodePos )
+ : SwHistoryHint( HSTRY_SETTXTFLDHNT )
+ , m_pFldType( 0 )
+ , m_pFld( new SwFmtFld( *pTxtFld->GetFld().GetFld() ) )
+{
+ // only copy if not Sys-FieldType
+ SwDoc* pDoc = pTxtFld->GetTxtNode().GetDoc();
+
+ m_nFldWhich = m_pFld->GetFld()->GetTyp()->Which();
+ if (m_nFldWhich == RES_DBFLD ||
+ m_nFldWhich == RES_USERFLD ||
+ m_nFldWhich == RES_SETEXPFLD ||
+ m_nFldWhich == RES_DDEFLD ||
+ !pDoc->GetSysFldType( m_nFldWhich ))
+ {
+ m_pFldType.reset( m_pFld->GetFld()->GetTyp()->Copy() );
+ m_pFld->GetFld()->ChgTyp( m_pFldType.get() ); // change field type
+ }
+ m_nNodeIndex = nNodePos;
+ m_nPos = *pTxtFld->GetStart();
+}
+
+String SwHistorySetTxtFld::GetDescription() const
+{
+ return m_pFld->GetFld()->GetDescription();;
+}
+
+SwHistorySetTxtFld::~SwHistorySetTxtFld()
+{
+}
+
+
+void SwHistorySetTxtFld::SetInDoc( SwDoc* pDoc, bool )
+{
+ if ( !m_pFld.get() )
+ return;
+
+ SwFieldType* pNewFldType = m_pFldType.get();
+ if ( !pNewFldType )
+ {
+ pNewFldType = pDoc->GetSysFldType( m_nFldWhich );
+ }
+ else
+ {
+ // register type with the document
+ pNewFldType = pDoc->InsertFldType( *m_pFldType );
+ }
+
+ m_pFld->GetFld()->ChgTyp( pNewFldType ); // change field type
+
+ SwTxtNode * pTxtNd = pDoc->GetNodes()[ m_nNodeIndex ]->GetTxtNode();
+ OSL_ENSURE( pTxtNd, "SwHistorySetTxtFld: no TextNode" );
+
+ if ( pTxtNd )
+ {
+ pTxtNd->InsertItem( *m_pFld, m_nPos, m_nPos,
+ nsSetAttrMode::SETATTR_NOTXTATRCHR );
+ }
+}
+
+
+
+SwHistorySetRefMark::SwHistorySetRefMark( SwTxtRefMark* pTxtHt, sal_uLong nNodePos )
+ : SwHistoryHint( HSTRY_SETREFMARKHNT )
+ , m_RefName( pTxtHt->GetRefMark().GetRefName() )
+ , m_nNodeIndex( nNodePos )
+ , m_nStart( *pTxtHt->GetStart() )
+ , m_nEnd( *pTxtHt->GetAnyEnd() )
+{
+}
+
+
+void SwHistorySetRefMark::SetInDoc( SwDoc* pDoc, bool )
+{
+ SwTxtNode * pTxtNd = pDoc->GetNodes()[ m_nNodeIndex ]->GetTxtNode();
+ OSL_ENSURE( pTxtNd, "SwHistorySetRefMark: no TextNode" );
+ if ( !pTxtNd )
+ return;
+
+ SwFmtRefMark aRefMark( m_RefName );
+
+ // if a reference mark without an end already exists here: must not insert!
+ if ( m_nStart != m_nEnd ||
+ !pTxtNd->GetTxtAttrForCharAt( m_nStart, RES_TXTATR_REFMARK ) )
+ {
+ pTxtNd->InsertItem( aRefMark, m_nStart, m_nEnd,
+ nsSetAttrMode::SETATTR_NOTXTATRCHR );
+ }
+}
+
+
+SwHistorySetTOXMark::SwHistorySetTOXMark( SwTxtTOXMark* pTxtHt, sal_uLong nNodePos )
+ : SwHistoryHint( HSTRY_SETTOXMARKHNT )
+ , m_TOXMark( pTxtHt->GetTOXMark() )
+ , m_TOXName( m_TOXMark.GetTOXType()->GetTypeName() )
+ , m_eTOXTypes( m_TOXMark.GetTOXType()->GetType() )
+ , m_nNodeIndex( nNodePos )
+ , m_nStart( *pTxtHt->GetStart() )
+ , m_nEnd( *pTxtHt->GetAnyEnd() )
+{
+ m_TOXMark.DeRegister();
+}
+
+
+void SwHistorySetTOXMark::SetInDoc( SwDoc* pDoc, bool )
+{
+ SwTxtNode * pTxtNd = pDoc->GetNodes()[ m_nNodeIndex ]->GetTxtNode();
+ OSL_ENSURE( pTxtNd, "SwHistorySetTOXMark: no TextNode" );
+ if ( !pTxtNd )
+ return;
+
+ // search for respective TOX type
+ sal_uInt16 nCnt = pDoc->GetTOXTypeCount( m_eTOXTypes );
+ SwTOXType* pToxType = 0;
+ for ( sal_uInt16 n = 0; n < nCnt; ++n )
+ {
+ pToxType = const_cast<SwTOXType*>(pDoc->GetTOXType( m_eTOXTypes, n ));
+ if ( pToxType->GetTypeName() == m_TOXName )
+ break;
+ pToxType = 0;
+ }
+
+ if ( !pToxType ) // TOX type not found, create new
+ {
+ pToxType = const_cast<SwTOXType*>(
+ pDoc->InsertTOXType( SwTOXType( m_eTOXTypes, m_TOXName )));
+ }
+
+ SwTOXMark aNew( m_TOXMark );
+ aNew.RegisterToTOXType( *pToxType );
+
+ pTxtNd->InsertItem( aNew, m_nStart, m_nEnd,
+ nsSetAttrMode::SETATTR_NOTXTATRCHR );
+}
+
+
+int SwHistorySetTOXMark::IsEqual( const SwTOXMark& rCmp ) const
+{
+ return m_TOXName == rCmp.GetTOXType()->GetTypeName() &&
+ m_eTOXTypes == rCmp.GetTOXType()->GetType() &&
+ m_TOXMark.GetAlternativeText() == rCmp.GetAlternativeText() &&
+ ( (TOX_INDEX == m_eTOXTypes)
+ ? ( m_TOXMark.GetPrimaryKey() == rCmp.GetPrimaryKey() &&
+ m_TOXMark.GetSecondaryKey() == rCmp.GetSecondaryKey() )
+ : m_TOXMark.GetLevel() == rCmp.GetLevel()
+ );
+}
+
+
+SwHistoryResetTxt::SwHistoryResetTxt( sal_uInt16 nWhich,
+ xub_StrLen nAttrStart, xub_StrLen nAttrEnd, sal_uLong nNodePos )
+ : SwHistoryHint( HSTRY_RESETTXTHNT )
+ , m_nNodeIndex( nNodePos ), m_nStart( nAttrStart ), m_nEnd( nAttrEnd )
+ , m_nAttr( nWhich )
+{
+}
+
+
+void SwHistoryResetTxt::SetInDoc( SwDoc* pDoc, bool )
+{
+ SwTxtNode * pTxtNd = pDoc->GetNodes()[ m_nNodeIndex ]->GetTxtNode();
+ OSL_ENSURE( pTxtNd, "SwHistoryResetTxt: no TextNode" );
+ if ( pTxtNd )
+ {
+ pTxtNd->DeleteAttributes( m_nAttr, m_nStart, m_nEnd );
+ }
+}
+
+
+SwHistorySetFootnote::SwHistorySetFootnote( SwTxtFtn* pTxtFtn, sal_uLong nNodePos )
+ : SwHistoryHint( HSTRY_SETFTNHNT )
+ , m_pUndo( new SwUndoSaveSection )
+ , m_FootnoteNumber( pTxtFtn->GetFtn().GetNumStr() )
+ , m_nNodeIndex( nNodePos )
+ , m_nStart( *pTxtFtn->GetStart() )
+ , m_bEndNote( pTxtFtn->GetFtn().IsEndNote() )
+{
+ OSL_ENSURE( pTxtFtn->GetStartNode(),
+ "SwHistorySetFootnote: Footnote without Section" );
+
+ // merke die alte NodePos, denn wer weiss was alles in der SaveSection
+ // gespeichert (geloescht) wird
+ SwDoc* pDoc = const_cast<SwDoc*>(pTxtFtn->GetTxtNode().GetDoc());
+ SwNode* pSaveNd = pDoc->GetNodes()[ m_nNodeIndex ];
+
+ //Pointer auf StartNode der FtnSection merken und erstmal den Pointer im
+ //Attribut zuruecksetzen -> Damit werden automatisch die Frms vernichtet.
+ SwNodeIndex aSttIdx( *pTxtFtn->GetStartNode() );
+ pTxtFtn->SetStartNode( 0, sal_False );
+
+ m_pUndo->SaveSection( pDoc, aSttIdx );
+ m_nNodeIndex = pSaveNd->GetIndex();
+}
+
+SwHistorySetFootnote::SwHistorySetFootnote( const SwTxtFtn &rTxtFtn )
+ : SwHistoryHint( HSTRY_SETFTNHNT )
+ , m_pUndo( 0 )
+ , m_FootnoteNumber( rTxtFtn.GetFtn().GetNumStr() )
+ , m_nNodeIndex( _SwTxtFtn_GetIndex( (&rTxtFtn) ) )
+ , m_nStart( *rTxtFtn.GetStart() )
+ , m_bEndNote( rTxtFtn.GetFtn().IsEndNote() )
+{
+ OSL_ENSURE( rTxtFtn.GetStartNode(),
+ "SwHistorySetFootnote: Footnote without Section" );
+}
+
+String SwHistorySetFootnote::GetDescription() const
+{
+ return SW_RES(STR_FOOTNOTE);
+}
+
+SwHistorySetFootnote::~SwHistorySetFootnote()
+{
+}
+
+
+void SwHistorySetFootnote::SetInDoc( SwDoc* pDoc, bool )
+{
+ SwTxtNode * pTxtNd = pDoc->GetNodes()[ m_nNodeIndex ]->GetTxtNode();
+ OSL_ENSURE( pTxtNd, "SwHistorySetFootnote: no TextNode" );
+ if ( !pTxtNd )
+ return;
+
+ if ( m_pUndo.get() )
+ {
+ // set the footnote in the TextNode
+ SwFmtFtn aTemp( m_bEndNote );
+ SwFmtFtn& rNew = const_cast<SwFmtFtn&>(
+ static_cast<const SwFmtFtn&>(pDoc->GetAttrPool().Put(aTemp)) );
+ if ( m_FootnoteNumber.Len() )
+ {
+ rNew.SetNumStr( m_FootnoteNumber );
+ }
+ SwTxtFtn* pTxtFtn = new SwTxtFtn( rNew, m_nStart );
+
+ // create the section of the Footnote
+ SwNodeIndex aIdx( *pTxtNd );
+ m_pUndo->RestoreSection( pDoc, &aIdx, SwFootnoteStartNode );
+ pTxtFtn->SetStartNode( &aIdx );
+ if ( m_pUndo->GetHistory() )
+ {
+ // create frames only now
+ m_pUndo->GetHistory()->Rollback( pDoc );
+ }
+
+ pTxtNd->InsertHint( pTxtFtn );
+ }
+ else
+ {
+ SwTxtFtn * const pFtn =
+ const_cast<SwTxtFtn*>( static_cast<const SwTxtFtn*>(
+ pTxtNd->GetTxtAttrForCharAt( m_nStart )));
+ SwFmtFtn &rFtn = const_cast<SwFmtFtn&>(pFtn->GetFtn());
+ rFtn.SetNumStr( m_FootnoteNumber );
+ if ( rFtn.IsEndNote() != m_bEndNote )
+ {
+ rFtn.SetEndNote( m_bEndNote );
+ pFtn->CheckCondColl();
+ }
+ }
+}
+
+
+SwHistoryChangeFmtColl::SwHistoryChangeFmtColl( SwFmtColl* pFmtColl, sal_uLong nNd,
+ sal_uInt8 nNodeWhich )
+ : SwHistoryHint( HSTRY_CHGFMTCOLL )
+ , m_pColl( pFmtColl )
+ , m_nNodeIndex( nNd )
+ , m_nNodeType( nNodeWhich )
+{
+}
+
+void SwHistoryChangeFmtColl::SetInDoc( SwDoc* pDoc, bool )
+{
+ SwCntntNode * pCntntNd = pDoc->GetNodes()[ m_nNodeIndex ]->GetCntntNode();
+ OSL_ENSURE( pCntntNd, "SwHistoryChangeFmtColl: no ContentNode" );
+
+ // before setting the format, check if it is still available in the
+ // document. if it has been deleted, there is no undo!
+ if ( pCntntNd && m_nNodeType == pCntntNd->GetNodeType() )
+ {
+ if ( ND_TEXTNODE == m_nNodeType )
+ {
+ if ( USHRT_MAX != pDoc->GetTxtFmtColls()->GetPos(
+ static_cast<SwTxtFmtColl * const>(m_pColl) ))
+ {
+ pCntntNd->ChgFmtColl( m_pColl );
+ }
+ }
+ else if ( USHRT_MAX != pDoc->GetGrfFmtColls()->GetPos(
+ static_cast<SwGrfFmtColl * const>(m_pColl) ))
+ {
+ pCntntNd->ChgFmtColl( m_pColl );
+ }
+ }
+}
+
+
+SwHistoryTxtFlyCnt::SwHistoryTxtFlyCnt( SwFrmFmt* const pFlyFmt )
+ : SwHistoryHint( HSTRY_FLYCNT )
+ , m_pUndo( new SwUndoDelLayFmt( pFlyFmt ) )
+{
+ OSL_ENSURE( pFlyFmt, "SwHistoryTxtFlyCnt: no Format" );
+ m_pUndo->ChgShowSel( sal_False );
+}
+
+
+SwHistoryTxtFlyCnt::~SwHistoryTxtFlyCnt()
+{
+}
+
+
+void SwHistoryTxtFlyCnt::SetInDoc( SwDoc* pDoc, bool )
+{
+ ::sw::IShellCursorSupplier *const pISCS(pDoc->GetIShellCursorSupplier());
+ OSL_ASSERT(pISCS);
+ ::sw::UndoRedoContext context(*pDoc, *pISCS);
+ m_pUndo->UndoImpl(context);
+}
+
+
+
+SwHistoryBookmark::SwHistoryBookmark(
+ const ::sw::mark::IMark& rBkmk,
+ bool bSavePos,
+ bool bSaveOtherPos)
+ : SwHistoryHint(HSTRY_BOOKMARK)
+ , m_aName(rBkmk.GetName())
+ , m_aShortName()
+ , m_aKeycode()
+ , m_nNode(bSavePos ?
+ rBkmk.GetMarkPos().nNode.GetIndex() : 0)
+ , m_nOtherNode(bSaveOtherPos ?
+ rBkmk.GetOtherMarkPos().nNode.GetIndex() : 0)
+ , m_nCntnt(bSavePos ?
+ rBkmk.GetMarkPos().nContent.GetIndex() : 0)
+ , m_nOtherCntnt(bSaveOtherPos ?
+ rBkmk.GetOtherMarkPos().nContent.GetIndex() :0)
+ , m_bSavePos(bSavePos)
+ , m_bSaveOtherPos(bSaveOtherPos)
+ , m_bHadOtherPos(rBkmk.IsExpanded())
+ , m_eBkmkType(IDocumentMarkAccess::GetType(rBkmk))
+{
+ const ::sw::mark::IBookmark* const pBookmark = dynamic_cast< const ::sw::mark::IBookmark* >(&rBkmk);
+ if(pBookmark)
+ {
+ m_aKeycode = pBookmark->GetKeyCode();
+ m_aShortName = pBookmark->GetShortName();
+
+ ::sfx2::Metadatable const*const pMetadatable(
+ dynamic_cast< ::sfx2::Metadatable const* >(pBookmark));
+ if (pMetadatable)
+ {
+ m_pMetadataUndo = pMetadatable->CreateUndo();
+ }
+ }
+}
+
+
+void SwHistoryBookmark::SetInDoc( SwDoc* pDoc, bool )
+{
+ ::sw::UndoGuard const undoGuard(pDoc->GetIDocumentUndoRedo());
+
+ SwNodes& rNds = pDoc->GetNodes();
+ IDocumentMarkAccess* pMarkAccess = pDoc->getIDocumentMarkAccess();
+ ::std::auto_ptr<SwPaM> pPam;
+ ::sw::mark::IMark* pMark = NULL;
+
+ if(m_bSavePos)
+ {
+ SwCntntNode* const pCntntNd = rNds[m_nNode]->GetCntntNode();
+ OSL_ENSURE(pCntntNd,
+ "<SwHistoryBookmark::SetInDoc(..)>"
+ " - wrong node for a mark");
+
+ // #111660# don't crash when nNode1 doesn't point to content node.
+ if(pCntntNd)
+ pPam = ::std::auto_ptr<SwPaM>(new SwPaM(*pCntntNd, m_nCntnt));
+ }
+ else
+ {
+ pMark = pMarkAccess->findMark(m_aName)->get();
+ pPam = ::std::auto_ptr<SwPaM>(new SwPaM(pMark->GetMarkPos()));
+ }
+
+ if(m_bSaveOtherPos)
+ {
+ SwCntntNode* const pCntntNd = rNds[m_nOtherNode]->GetCntntNode();
+ OSL_ENSURE(pCntntNd,
+ "<SwHistoryBookmark::SetInDoc(..)>"
+ " - wrong node for a mark");
+
+ if(pPam.get() != NULL && pCntntNd)
+ {
+ pPam->SetMark();
+ pPam->GetMark()->nNode = m_nOtherNode;
+ pPam->GetMark()->nContent.Assign(pCntntNd, m_nOtherCntnt);
+ }
+ }
+ else if(m_bHadOtherPos)
+ {
+ if(!pMark)
+ pMark = pMarkAccess->findMark(m_aName)->get();
+ OSL_ENSURE(pMark->IsExpanded(),
+ "<SwHistoryBookmark::SetInDoc(..)>"
+ " - missing pos on old mark");
+ pPam->SetMark();
+ *pPam->GetMark() = pMark->GetOtherMarkPos();
+ }
+
+ if(pPam.get())
+ {
+ if(pMark)
+ pMarkAccess->deleteMark(pMark);
+ ::sw::mark::IBookmark* const pBookmark = dynamic_cast< ::sw::mark::IBookmark* >(
+ pMarkAccess->makeMark(*pPam, m_aName, m_eBkmkType));
+ if(pBookmark)
+ {
+ pBookmark->SetKeyCode(m_aKeycode);
+ pBookmark->SetShortName(m_aShortName);
+ if (m_pMetadataUndo)
+ {
+ ::sfx2::Metadatable * const pMeta(
+ dynamic_cast< ::sfx2::Metadatable* >(pBookmark));
+ OSL_ENSURE(pMeta, "metadata undo, but not metadatable?");
+ if (pMeta)
+ {
+ pMeta->RestoreMetadata(m_pMetadataUndo);
+ }
+ }
+ }
+ }
+}
+
+
+bool SwHistoryBookmark::IsEqualBookmark(const ::sw::mark::IMark& rBkmk)
+{
+ return m_nNode == rBkmk.GetMarkPos().nNode.GetIndex()
+ && m_nCntnt == rBkmk.GetMarkPos().nContent.GetIndex()
+ && m_aName == rBkmk.GetName();
+}
+
+const ::rtl::OUString& SwHistoryBookmark::GetName() const
+{
+ return m_aName;
+}
+
+/*************************************************************************/
+
+
+SwHistorySetAttrSet::SwHistorySetAttrSet( const SfxItemSet& rSet,
+ sal_uLong nNodePos, const SvUShortsSort& rSetArr )
+ : SwHistoryHint( HSTRY_SETATTRSET )
+ , m_OldSet( rSet )
+ , m_ResetArray( 0, 4 )
+ , m_nNodeIndex( nNodePos )
+{
+ SfxItemIter aIter( m_OldSet ), aOrigIter( rSet );
+ const SfxPoolItem* pItem = aIter.FirstItem(),
+ * pOrigItem = aOrigIter.FirstItem();
+ do {
+ if( !rSetArr.Seek_Entry( pOrigItem->Which() ))
+ {
+ m_ResetArray.Insert( pOrigItem->Which(), m_ResetArray.Count() );
+ m_OldSet.ClearItem( pOrigItem->Which() );
+ }
+ else
+ {
+ switch ( pItem->Which() )
+ {
+ case RES_PAGEDESC:
+ static_cast<SwFmtPageDesc*>(
+ const_cast<SfxPoolItem*>(pItem))->ChgDefinedIn( 0 );
+ break;
+
+ case RES_PARATR_DROP:
+ static_cast<SwFmtDrop*>(
+ const_cast<SfxPoolItem*>(pItem))->ChgDefinedIn( 0 );
+ break;
+
+ case RES_BOXATR_FORMULA:
+ {
+ //JP 20.04.98: Bug 49502 - wenn eine Formel gesetzt ist, nie den
+ // Value mit sichern. Der muss gegebenfalls neu
+ // errechnet werden!
+ //JP 30.07.98: Bug 54295 - Formeln immer im Klartext speichern
+ m_OldSet.ClearItem( RES_BOXATR_VALUE );
+
+ SwTblBoxFormula& rNew =
+ *static_cast<SwTblBoxFormula*>(
+ const_cast<SfxPoolItem*>(pItem));
+ if ( rNew.IsIntrnlName() )
+ {
+ const SwTblBoxFormula& rOld =
+ static_cast<const SwTblBoxFormula&>(
+ rSet.Get( RES_BOXATR_FORMULA ));
+ const SwNode* pNd = rOld.GetNodeOfFormula();
+ if ( pNd )
+ {
+ const SwTableNode* pTableNode
+ = pNd->FindTableNode();
+ if (pTableNode)
+ {
+ SwTableFmlUpdate aMsgHnt(
+ &pTableNode->GetTable() );
+ aMsgHnt.eFlags = TBL_BOXNAME;
+ rNew.ChgDefinedIn( rOld.GetDefinedIn() );
+ rNew.ChangeState( &aMsgHnt );
+ }
+ }
+ }
+ rNew.ChgDefinedIn( 0 );
+ }
+ break;
+ }
+ }
+
+ if( aIter.IsAtEnd() )
+ break;
+ pItem = aIter.NextItem();
+ pOrigItem = aOrigIter.NextItem();
+ } while( sal_True );
+}
+
+void SwHistorySetAttrSet::SetInDoc( SwDoc* pDoc, bool )
+{
+ ::sw::UndoGuard const undoGuard(pDoc->GetIDocumentUndoRedo());
+
+ SwNode * pNode = pDoc->GetNodes()[ m_nNodeIndex ];
+ if ( pNode->IsCntntNode() )
+ {
+ static_cast<SwCntntNode*>(pNode)->SetAttr( m_OldSet );
+ if ( m_ResetArray.Count() )
+ {
+ static_cast<SwCntntNode*>(pNode)->ResetAttr( m_ResetArray );
+ }
+ }
+ else if ( pNode->IsTableNode() )
+ {
+ SwFmt& rFmt =
+ *static_cast<SwTableNode*>(pNode)->GetTable().GetFrmFmt();
+ rFmt.SetFmtAttr( m_OldSet );
+ if ( m_ResetArray.Count() )
+ {
+ rFmt.ResetFmtAttr( *m_ResetArray.GetData() );
+ }
+ }
+}
+
+/*************************************************************************/
+
+
+SwHistoryResetAttrSet::SwHistoryResetAttrSet( const SfxItemSet& rSet,
+ sal_uLong nNodePos, xub_StrLen nAttrStt, xub_StrLen nAttrEnd )
+ : SwHistoryHint( HSTRY_RESETATTRSET )
+ , m_nNodeIndex( nNodePos ), m_nStart( nAttrStt ), m_nEnd( nAttrEnd )
+ , m_Array( (sal_uInt8)rSet.Count() )
+{
+ SfxItemIter aIter( rSet );
+ bool bAutoStyle = false;
+
+ while( sal_True )
+ {
+ const sal_uInt16 nWhich = aIter.GetCurItem()->Which();
+
+#ifndef PRODUCT
+ switch (nWhich)
+ {
+ case RES_TXTATR_REFMARK:
+ case RES_TXTATR_TOXMARK:
+ if (m_nStart != m_nEnd) break; // else: fall through!
+ case RES_TXTATR_FIELD:
+ case RES_TXTATR_FLYCNT:
+ case RES_TXTATR_FTN:
+ case RES_TXTATR_META:
+ case RES_TXTATR_METAFIELD:
+ OSL_ENSURE(rSet.Count() == 1,
+ "text attribute with CH_TXTATR, but not the only one:"
+ "\nnot such a good idea");
+ break;
+ }
+#endif
+
+ // Character attribute cannot be inserted into the hints array
+ // anymore. Therefore we have to treat them as one RES_TXTATR_AUTOFMT:
+ if (isCHRATR(nWhich))
+ {
+ bAutoStyle = true;
+ }
+ else
+ {
+ m_Array.Insert( aIter.GetCurItem()->Which(), m_Array.Count() );
+ }
+
+ if( aIter.IsAtEnd() )
+ break;
+
+ aIter.NextItem();
+ }
+
+ if ( bAutoStyle )
+ {
+ m_Array.Insert( RES_TXTATR_AUTOFMT, m_Array.Count() );
+ }
+}
+
+
+void SwHistoryResetAttrSet::SetInDoc( SwDoc* pDoc, bool )
+{
+ ::sw::UndoGuard const undoGuard(pDoc->GetIDocumentUndoRedo());
+
+ SwCntntNode * pCntntNd = pDoc->GetNodes()[ m_nNodeIndex ]->GetCntntNode();
+ OSL_ENSURE( pCntntNd, "SwHistoryResetAttrSet: no CntntNode" );
+
+ if (pCntntNd)
+ {
+ const sal_uInt16* pArr = m_Array.GetData();
+ if ( USHRT_MAX == m_nEnd && USHRT_MAX == m_nStart )
+ {
+ // no area: use ContentNode
+ for ( sal_uInt16 n = m_Array.Count(); n; --n, ++pArr )
+ {
+ pCntntNd->ResetAttr( *pArr );
+ }
+ }
+ else
+ {
+ // area: use TextNode
+ for ( sal_uInt16 n = m_Array.Count(); n; --n, ++pArr )
+ {
+ static_cast<SwTxtNode*>(pCntntNd)->
+ DeleteAttributes( *pArr, m_nStart, m_nEnd );
+ }
+ }
+ }
+}
+
+
+/*************************************************************************/
+
+
+SwHistoryChangeFlyAnchor::SwHistoryChangeFlyAnchor( SwFrmFmt& rFmt )
+ : SwHistoryHint( HSTRY_CHGFLYANCHOR )
+ , m_rFmt( rFmt )
+ , m_nOldNodeIndex( rFmt.GetAnchor().GetCntntAnchor()->nNode.GetIndex() )
+ , m_nOldContentIndex( (FLY_AT_CHAR == rFmt.GetAnchor().GetAnchorId())
+ ? rFmt.GetAnchor().GetCntntAnchor()->nContent.GetIndex()
+ : STRING_MAXLEN )
+{
+}
+
+
+void SwHistoryChangeFlyAnchor::SetInDoc( SwDoc* pDoc, bool )
+{
+ ::sw::UndoGuard const undoGuard(pDoc->GetIDocumentUndoRedo());
+
+ sal_uInt16 nPos = pDoc->GetSpzFrmFmts()->GetPos( &m_rFmt );
+ if ( USHRT_MAX != nPos ) // Format does still exist
+ {
+ SwFmtAnchor aTmp( m_rFmt.GetAnchor() );
+
+ SwNode* pNd = pDoc->GetNodes()[ m_nOldNodeIndex ];
+ SwCntntNode* pCNd = pNd->GetCntntNode();
+ SwPosition aPos( *pNd );
+ if ( STRING_MAXLEN != m_nOldContentIndex )
+ {
+ OSL_ENSURE(pCNd, "SwHistoryChangeFlyAnchor: no ContentNode");
+ if (pCNd)
+ {
+ aPos.nContent.Assign( pCNd, m_nOldContentIndex );
+ }
+ }
+ aTmp.SetAnchor( &aPos );
+
+ // so the Layout does not get confused
+ if ( !pCNd || !pCNd->getLayoutFrm( pDoc->GetCurrentLayout(), 0, 0, sal_False ) )
+ {
+ m_rFmt.DelFrms();
+ }
+
+ m_rFmt.SetFmtAttr( aTmp );
+ }
+}
+
+
+/*************************************************************************/
+
+SwHistoryChangeFlyChain::SwHistoryChangeFlyChain( SwFlyFrmFmt& rFmt,
+ const SwFmtChain& rAttr )
+ : SwHistoryHint( HSTRY_CHGFLYCHAIN )
+ , m_pPrevFmt( rAttr.GetPrev() )
+ , m_pNextFmt( rAttr.GetNext() )
+ , m_pFlyFmt( &rFmt )
+{
+}
+
+
+void SwHistoryChangeFlyChain::SetInDoc( SwDoc* pDoc, bool )
+{
+ if ( USHRT_MAX != pDoc->GetSpzFrmFmts()->GetPos( m_pFlyFmt ) )
+ {
+ SwFmtChain aChain;
+
+ if ( m_pPrevFmt &&
+ USHRT_MAX != pDoc->GetSpzFrmFmts()->GetPos( m_pPrevFmt ) )
+ {
+ aChain.SetPrev( m_pPrevFmt );
+ SwFmtChain aTmp( m_pPrevFmt->GetChain() );
+ aTmp.SetNext( m_pFlyFmt );
+ m_pPrevFmt->SetFmtAttr( aTmp );
+ }
+
+ if ( m_pNextFmt &&
+ USHRT_MAX != pDoc->GetSpzFrmFmts()->GetPos( m_pNextFmt ) )
+ {
+ aChain.SetNext( m_pNextFmt );
+ SwFmtChain aTmp( m_pNextFmt->GetChain() );
+ aTmp.SetPrev( m_pFlyFmt );
+ m_pNextFmt->SetFmtAttr( aTmp );
+ }
+
+ if ( aChain.GetNext() || aChain.GetPrev() )
+ {
+ m_pFlyFmt->SetFmtAttr( aChain );
+ }
+ }
+}
+
+
+// -> #i27615#
+SwHistoryChangeCharFmt::SwHistoryChangeCharFmt(const SfxItemSet & rSet,
+ const String & sFmt)
+ : SwHistoryHint(HSTRY_CHGCHARFMT)
+ , m_OldSet(rSet), m_Fmt(sFmt)
+{
+}
+
+void SwHistoryChangeCharFmt::SetInDoc(SwDoc * pDoc, bool )
+{
+ SwCharFmt * pCharFmt = pDoc->FindCharFmtByName(m_Fmt);
+
+ if (pCharFmt)
+ {
+ pCharFmt->SetFmtAttr(m_OldSet);
+ }
+}
+// <- #i27615#
+
+/* */
+
+
+SwHistory::SwHistory( sal_uInt16 nInitSz, sal_uInt16 nGrowSz )
+ : m_SwpHstry( (sal_uInt8)nInitSz, (sal_uInt8)nGrowSz )
+ , m_nEndDiff( 0 )
+{}
+
+
+SwHistory::~SwHistory()
+{
+ Delete( 0 );
+}
+
+
+/*************************************************************************
+|*
+|* void SwHistory::Add()
+|*
+|* Beschreibung Dokument 1.0
+|*
+*************************************************************************/
+
+void SwHistory::Add( const SfxPoolItem* pOldValue, const SfxPoolItem* pNewValue,
+ sal_uLong nNodeIdx )
+{
+ OSL_ENSURE( !m_nEndDiff, "History was not deleted after REDO" );
+
+ sal_uInt16 nWhich = pNewValue->Which();
+ if( (nWhich >= POOLATTR_END) || (nWhich == RES_TXTATR_FIELD) )
+ return;
+
+ // no default Attribute?
+ SwHistoryHint * pHt;
+ if ( pOldValue && pOldValue != GetDfltAttr( pOldValue->Which() ) )
+ {
+ pHt = new SwHistorySetFmt( pOldValue, nNodeIdx );
+ }
+ else
+ {
+ pHt = new SwHistoryResetFmt( pNewValue, nNodeIdx );
+ }
+ m_SwpHstry.Insert( pHt, Count() );
+}
+
+
+void SwHistory::Add( SwTxtAttr* pHint, sal_uLong nNodeIdx, bool bNewAttr )
+{
+ OSL_ENSURE( !m_nEndDiff, "History was not deleted after REDO" );
+
+ SwHistoryHint * pHt;
+ sal_uInt16 nAttrWhich = pHint->Which();
+
+ if( !bNewAttr )
+ {
+ switch ( nAttrWhich )
+ {
+ case RES_TXTATR_FTN:
+ pHt = new SwHistorySetFootnote(
+ static_cast<SwTxtFtn*>(pHint), nNodeIdx );
+ break;
+ case RES_TXTATR_FLYCNT:
+ pHt = new SwHistoryTxtFlyCnt( static_cast<SwTxtFlyCnt*>(pHint)
+ ->GetFlyCnt().GetFrmFmt() );
+ break;
+ case RES_TXTATR_FIELD:
+ pHt = new SwHistorySetTxtFld(
+ static_cast<SwTxtFld*>(pHint), nNodeIdx );
+ break;
+ case RES_TXTATR_TOXMARK:
+ pHt = new SwHistorySetTOXMark(
+ static_cast<SwTxtTOXMark*>(pHint), nNodeIdx );
+ break;
+ case RES_TXTATR_REFMARK:
+ pHt = new SwHistorySetRefMark(
+ static_cast<SwTxtRefMark*>(pHint), nNodeIdx );
+ break;
+ default:
+ pHt = new SwHistorySetTxt(
+ static_cast<SwTxtAttr*>(pHint), nNodeIdx );
+ }
+ }
+ else
+ {
+ pHt = new SwHistoryResetTxt( pHint->Which(), *pHint->GetStart(),
+ *pHint->GetAnyEnd(), nNodeIdx );
+ }
+ m_SwpHstry.Insert( pHt, Count() );
+}
+
+
+void SwHistory::Add( SwFmtColl* pColl, sal_uLong nNodeIdx, sal_uInt8 nWhichNd )
+{
+ OSL_ENSURE( !m_nEndDiff, "History was not deleted after REDO" );
+
+ SwHistoryHint * pHt =
+ new SwHistoryChangeFmtColl( pColl, nNodeIdx, nWhichNd );
+ m_SwpHstry.Insert( pHt, Count() );
+}
+
+
+void SwHistory::Add(const ::sw::mark::IMark& rBkmk, bool bSavePos, bool bSaveOtherPos)
+{
+ OSL_ENSURE( !m_nEndDiff, "History was not deleted after REDO" );
+
+ SwHistoryHint * pHt = new SwHistoryBookmark(rBkmk, bSavePos, bSaveOtherPos);
+ m_SwpHstry.Insert( pHt, Count() );
+}
+
+
+void SwHistory::Add( SwFrmFmt& rFmt )
+{
+ SwHistoryHint * pHt = new SwHistoryChangeFlyAnchor( rFmt );
+ m_SwpHstry.Insert( pHt, Count() );
+}
+
+void SwHistory::Add( SwFlyFrmFmt& rFmt, sal_uInt16& rSetPos )
+{
+ OSL_ENSURE( !m_nEndDiff, "History was not deleted after REDO" );
+
+ SwHistoryHint * pHint;
+ const sal_uInt16 nWh = rFmt.Which();
+ if( RES_FLYFRMFMT == nWh || RES_DRAWFRMFMT == nWh )
+ {
+ pHint = new SwHistoryTxtFlyCnt( &rFmt );
+ m_SwpHstry.Insert( pHint, Count() );
+
+ const SwFmtChain* pChainItem;
+ if( SFX_ITEM_SET == rFmt.GetItemState( RES_CHAIN, sal_False,
+ (const SfxPoolItem**)&pChainItem ))
+ {
+ if( pChainItem->GetNext() || pChainItem->GetPrev() )
+ {
+ SwHistoryHint * pHt =
+ new SwHistoryChangeFlyChain( rFmt, *pChainItem );
+ m_SwpHstry.Insert( pHt, rSetPos++ );
+ if ( pChainItem->GetNext() )
+ {
+ SwFmtChain aTmp( pChainItem->GetNext()->GetChain() );
+ aTmp.SetPrev( 0 );
+ pChainItem->GetNext()->SetFmtAttr( aTmp );
+ }
+ if ( pChainItem->GetPrev() )
+ {
+ SwFmtChain aTmp( pChainItem->GetPrev()->GetChain() );
+ aTmp.SetNext( 0 );
+ pChainItem->GetPrev()->SetFmtAttr( aTmp );
+ }
+ }
+ rFmt.ResetFmtAttr( RES_CHAIN );
+ }
+ }
+}
+
+void SwHistory::Add( const SwTxtFtn& rFtn )
+{
+ SwHistoryHint *pHt = new SwHistorySetFootnote( rFtn );
+ m_SwpHstry.Insert( pHt, Count() );
+}
+
+// #i27615#
+void SwHistory::Add(const SfxItemSet & rSet, const SwCharFmt & rFmt)
+{
+ SwHistoryHint * pHt = new SwHistoryChangeCharFmt(rSet, rFmt.GetName());
+ m_SwpHstry.Insert(pHt, Count());
+}
+
+/*************************************************************************
+|*
+|* sal_Bool SwHistory::Rollback()
+|*
+|* Beschreibung Dokument 1.0
+|*
+*************************************************************************/
+
+
+bool SwHistory::Rollback( SwDoc* pDoc, sal_uInt16 nStart )
+{
+ if ( !Count() )
+ return false;
+
+ SwHistoryHint * pHHt;
+ sal_uInt16 i;
+ for ( i = Count(); i > nStart ; )
+ {
+ pHHt = m_SwpHstry[ --i ];
+ pHHt->SetInDoc( pDoc, false );
+ delete pHHt;
+ }
+ m_SwpHstry.Remove( nStart, Count() - nStart );
+ m_nEndDiff = 0;
+ return true;
+}
+
+
+
+bool SwHistory::TmpRollback( SwDoc* pDoc, sal_uInt16 nStart, bool bToFirst )
+{
+ sal_uInt16 nEnd = Count() - m_nEndDiff;
+ if ( !Count() || !nEnd || nStart >= nEnd )
+ return false;
+
+ SwHistoryHint * pHHt;
+ if ( bToFirst )
+ {
+ for ( ; nEnd > nStart; ++m_nEndDiff )
+ {
+ pHHt = m_SwpHstry[ --nEnd ];
+ pHHt->SetInDoc( pDoc, true );
+ }
+ }
+ else
+ {
+ for ( ; nStart < nEnd; ++m_nEndDiff, ++nStart )
+ {
+ pHHt = m_SwpHstry[ nStart ];
+ pHHt->SetInDoc( pDoc, true );
+ }
+ }
+ return true;
+}
+
+
+void SwHistory::Delete( sal_uInt16 nStart )
+{
+ for ( sal_uInt16 n = Count(); n > nStart; )
+ {
+ m_SwpHstry.DeleteAndDestroy( --n, 1 );
+ }
+ m_nEndDiff = 0;
+}
+
+
+sal_uInt16 SwHistory::SetTmpEnd( sal_uInt16 nNewTmpEnd )
+{
+ OSL_ENSURE( nNewTmpEnd <= Count(), "SwHistory::SetTmpEnd: out of bounds" );
+
+ sal_uInt16 nOld = Count() - m_nEndDiff;
+ m_nEndDiff = Count() - nNewTmpEnd;
+
+ // for every SwHistoryFlyCnt, call the Redo of its UndoObject.
+ // this saves the formats of the flys!
+ for ( sal_uInt16 n = nOld; n < nNewTmpEnd; n++ )
+ {
+ if ( HSTRY_FLYCNT == (*this)[ n ]->Which() )
+ {
+ static_cast<SwHistoryTxtFlyCnt*>((*this)[ n ])
+ ->GetUDelLFmt()->RedoForRollback();
+ }
+ }
+
+ return nOld;
+}
+
+void SwHistory::CopyFmtAttr( const SfxItemSet& rSet, sal_uLong nNodeIdx )
+{
+ if( rSet.Count() )
+ {
+ SfxItemIter aIter( rSet );
+ do {
+ if( (SfxPoolItem*)-1 != aIter.GetCurItem() )
+ {
+ const SfxPoolItem* pNew = aIter.GetCurItem();
+ Add( pNew, pNew, nNodeIdx );
+ }
+ if( aIter.IsAtEnd() )
+ break;
+ aIter.NextItem();
+ } while( sal_True );
+ }
+}
+
+void SwHistory::CopyAttr( SwpHints* pHts, sal_uLong nNodeIdx,
+ xub_StrLen nStart, xub_StrLen nEnd, bool bFields )
+{
+ if( !pHts )
+ return;
+
+ // copy all attributes of the TextNode in the area from nStart to nEnd
+ SwTxtAttr* pHt;
+ xub_StrLen nAttrStt;
+ const xub_StrLen * pEndIdx;
+ for( sal_uInt16 n = 0; n < pHts->Count(); n++ )
+ {
+ // BP: nAttrStt muss auch bei !pEndIdx gesetzt werden
+ pHt = pHts->GetTextHint(n);
+ nAttrStt = *pHt->GetStart();
+// JP: ???? wieso nAttrStt >= nEnd
+// if( 0 != ( pEndIdx = pHt->GetEnd() ) && nAttrStt >= nEnd )
+ if( 0 != ( pEndIdx = pHt->GetEnd() ) && nAttrStt > nEnd )
+ break;
+
+ // Flys und Ftn nie kopieren !!
+ sal_Bool bNextAttr = sal_False;
+ switch( pHt->Which() )
+ {
+ case RES_TXTATR_FIELD:
+ // keine Felder, .. kopieren ??
+ if( !bFields )
+ bNextAttr = sal_True;
+ break;
+ case RES_TXTATR_FLYCNT:
+ case RES_TXTATR_FTN:
+ bNextAttr = sal_True;
+ break;
+ }
+
+ if( bNextAttr )
+ continue;
+
+ // save all attributes that are somehow in this area
+ if ( nStart <= nAttrStt )
+ {
+ if ( nEnd > nAttrStt
+// JP: ???? wieso nAttrStt >= nEnd
+// || (nEnd == nAttrStt && (!pEndIdx || nEnd == pEndIdx->GetIndex()))
+ )
+ {
+ Add( pHt, nNodeIdx, false );
+ }
+ }
+ else if ( pEndIdx && nStart < *pEndIdx )
+ {
+ Add( pHt, nNodeIdx, false );
+ }
+ }
+}
+
+
+/*************************************************************************/
+
+// Klasse zum Registrieren der History am Node, Format, HintsArray, ...
+
+SwRegHistory::SwRegHistory( SwHistory* pHst )
+ : SwClient( 0 )
+ , m_pHistory( pHst )
+ , m_nNodeIndex( ULONG_MAX )
+{
+ _MakeSetWhichIds();
+}
+
+SwRegHistory::SwRegHistory( SwModify* pRegIn, const SwNode& rNd,
+ SwHistory* pHst )
+ : SwClient( pRegIn )
+ , m_pHistory( pHst )
+ , m_nNodeIndex( rNd.GetIndex() )
+{
+ _MakeSetWhichIds();
+}
+
+SwRegHistory::SwRegHistory( const SwNode& rNd, SwHistory* pHst )
+ : SwClient( 0 )
+ , m_pHistory( pHst )
+ , m_nNodeIndex( rNd.GetIndex() )
+{
+ _MakeSetWhichIds();
+}
+
+void SwRegHistory::Modify( const SfxPoolItem* pOld, const SfxPoolItem* pNew )
+{
+ // --> OD 2010-10-05 #i114861#
+ // Do not handle a "noop" modify
+ // - e.g. <SwTxtNode::NumRuleChgd()> uses such a "noop" modify
+// if ( m_pHistory && ( pOld || pNew ) )
+ if ( m_pHistory && ( pOld || pNew ) &&
+ pOld != pNew )
+ // <--
+ {
+ if ( pNew->Which() < POOLATTR_END )
+ {
+ m_pHistory->Add( pOld, pNew, m_nNodeIndex );
+ }
+ else if ( RES_ATTRSET_CHG == pNew->Which() )
+ {
+ SwHistoryHint* pNewHstr;
+ const SfxItemSet& rSet =
+ *static_cast<const SwAttrSetChg*>(pOld)->GetChgSet();
+ if ( 1 < rSet.Count() )
+ {
+ pNewHstr =
+ new SwHistorySetAttrSet( rSet, m_nNodeIndex, m_WhichIdSet );
+ }
+ else
+ {
+ const SfxPoolItem* pItem = SfxItemIter( rSet ).FirstItem();
+ if ( m_WhichIdSet.Seek_Entry( pItem->Which() ) )
+ {
+ pNewHstr = new SwHistorySetFmt( pItem, m_nNodeIndex );
+ }
+ else
+ {
+ pNewHstr = new SwHistoryResetFmt( pItem, m_nNodeIndex );
+ }
+ }
+ m_pHistory->m_SwpHstry.Insert( pNewHstr, m_pHistory->Count() );
+ }
+ }
+}
+
+
+
+void SwRegHistory::AddHint( SwTxtAttr* pHt, const bool bNew )
+{
+ m_pHistory->Add( pHt, m_nNodeIndex, bNew );
+}
+
+
+bool SwRegHistory::InsertItems( const SfxItemSet& rSet,
+ xub_StrLen const nStart, xub_StrLen const nEnd, SetAttrMode const nFlags )
+{
+ if( !rSet.Count() )
+ return false;
+
+ SwTxtNode * const pTxtNode =
+ dynamic_cast<SwTxtNode *>(const_cast<SwModify *>(GetRegisteredIn()));
+
+ OSL_ENSURE(pTxtNode, "SwRegHistory not registered at text node?");
+ if (!pTxtNode)
+ return false;
+
+ if ( pTxtNode->GetpSwpHints() && m_pHistory )
+ {
+ pTxtNode->GetpSwpHints()->Register( this );
+ }
+
+ const bool bInserted = pTxtNode->SetAttr( rSet, nStart, nEnd, nFlags );
+
+ // Achtung: Durch das Einfuegen eines Attributs kann das Array
+ // geloescht werden!!! Wenn das einzufuegende zunaechst ein vorhandenes
+ // loescht, selbst aber nicht eingefuegt werden braucht, weil die
+ // Absatzattribute identisch sind( -> bForgetAttr in SwpHints::Insert )
+ if ( pTxtNode->GetpSwpHints() && m_pHistory )
+ {
+ pTxtNode->GetpSwpHints()->DeRegister();
+ }
+
+ if ( m_pHistory && bInserted )
+ {
+ SwHistoryHint* pNewHstr = new SwHistoryResetAttrSet( rSet,
+ pTxtNode->GetIndex(), nStart, nEnd );
+ // der NodeIndex kann verschoben sein !!
+
+ m_pHistory->m_SwpHstry.Insert( pNewHstr, m_pHistory->Count() );
+ }
+
+ return bInserted;
+}
+
+void SwRegHistory::RegisterInModify( SwModify* pRegIn, const SwNode& rNd )
+{
+ if ( m_pHistory && pRegIn )
+ {
+ pRegIn->Add( this );
+ m_nNodeIndex = rNd.GetIndex();
+ _MakeSetWhichIds();
+ }
+ else if ( m_WhichIdSet.Count() )
+ {
+ m_WhichIdSet.Remove( 0, m_WhichIdSet.Count() );
+ }
+}
+
+void SwRegHistory::_MakeSetWhichIds()
+{
+ if (!m_pHistory) return;
+
+ if ( m_WhichIdSet.Count() )
+ {
+ m_WhichIdSet.Remove( 0, m_WhichIdSet.Count() );
+ }
+
+ if( GetRegisteredIn() )
+ {
+ const SfxItemSet* pSet = 0;
+ if( GetRegisteredIn()->ISA( SwCntntNode ) )
+ {
+ pSet = static_cast<SwCntntNode*>(
+ const_cast<SwModify*>(GetRegisteredIn()))->GetpSwAttrSet();
+ }
+ else if ( GetRegisteredIn()->ISA( SwFmt ) )
+ {
+ pSet = &static_cast<SwFmt*>(
+ const_cast<SwModify*>(GetRegisteredIn()))->GetAttrSet();
+ }
+ if( pSet && pSet->Count() )
+ {
+ SfxItemIter aIter( *pSet );
+ sal_uInt16 nW = aIter.FirstItem()->Which();
+ while( sal_True )
+ {
+ m_WhichIdSet.Insert( nW );
+ if( aIter.IsAtEnd() )
+ break;
+ nW = aIter.NextItem()->Which();
+ }
+ }
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/undo/unattr.cxx b/sw/source/core/undo/unattr.cxx
new file mode 100644
index 000000000000..0d585f42aa0e
--- /dev/null
+++ b/sw/source/core/undo/unattr.cxx
@@ -0,0 +1,1259 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+#define _SVSTDARR_USHORTS
+#define _SVSTDARR_USHORTSSORT
+#include <UndoAttribute.hxx>
+
+#include <svl/itemiter.hxx>
+
+#include <editeng/tstpitem.hxx>
+
+#include <svx/svdmodel.hxx>
+#include <svx/svdpage.hxx>
+
+#include <hintids.hxx>
+#include <fmtflcnt.hxx>
+#include <txtftn.hxx>
+#include <fmtornt.hxx>
+#include <fmtanchr.hxx>
+#include <fmtfsize.hxx>
+#include <frmfmt.hxx>
+#include <fmtcntnt.hxx>
+#include <ftnidx.hxx>
+#include <doc.hxx>
+#include <IDocumentUndoRedo.hxx>
+#include <IShellCursorSupplier.hxx>
+#include <docary.hxx>
+#include <swundo.hxx> // fuer die UndoIds
+#include <pam.hxx>
+#include <ndtxt.hxx>
+#include <swtable.hxx>
+#include <swtblfmt.hxx>
+#include <UndoCore.hxx>
+#include <hints.hxx>
+#include <rolbck.hxx>
+#include <ndnotxt.hxx>
+#include <dcontact.hxx>
+#include <ftninfo.hxx>
+#include <redline.hxx>
+#include <section.hxx>
+#include <charfmt.hxx>
+#include <switerator.hxx>
+
+
+// -----------------------------------------------------
+
+SwUndoFmtAttrHelper::SwUndoFmtAttrHelper( SwFmt& rFmt, bool bSvDrwPt )
+ : SwClient( &rFmt )
+ , m_pUndo( 0 )
+ , m_bSaveDrawPt( bSvDrwPt )
+{
+}
+
+void SwUndoFmtAttrHelper::Modify( const SfxPoolItem* pOld, const SfxPoolItem* pNew )
+{
+ if( pOld )
+ {
+ if ( pOld->Which() == RES_OBJECTDYING )
+ {
+ CheckRegistration( pOld, pNew );
+ }
+ else if ( pNew )
+ {
+ if( POOLATTR_END >= pOld->Which() )
+ {
+ if ( GetUndo() )
+ {
+ m_pUndo->PutAttr( *pOld );
+ }
+ else
+ {
+ m_pUndo.reset( new SwUndoFmtAttr( *pOld,
+ *static_cast<SwFmt*>(GetRegisteredInNonConst()), m_bSaveDrawPt ) );
+ }
+ }
+ else if ( RES_ATTRSET_CHG == pOld->Which() )
+ {
+ if ( GetUndo() )
+ {
+ SfxItemIter aIter(
+ *(static_cast<const SwAttrSetChg*>(pOld))->GetChgSet() );
+ const SfxPoolItem* pItem = aIter.GetCurItem();
+ while ( pItem )
+ {
+ m_pUndo->PutAttr( *pItem );
+ if( aIter.IsAtEnd() )
+ break;
+ pItem = aIter.NextItem();
+ }
+ }
+ else
+ {
+ m_pUndo.reset( new SwUndoFmtAttr(
+ *static_cast<const SwAttrSetChg*>(pOld)->GetChgSet(),
+ *static_cast<SwFmt*>(GetRegisteredInNonConst()), m_bSaveDrawPt ) );
+ }
+ }
+ }
+ }
+}
+
+// -----------------------------------------------------
+
+SwUndoFmtAttr::SwUndoFmtAttr( const SfxItemSet& rOldSet,
+ SwFmt& rChgFmt,
+ bool bSaveDrawPt )
+ : SwUndo( UNDO_INSFMTATTR )
+ , m_pFmt( &rChgFmt )
+ // --> OD 2007-07-11 #i56253#
+ , m_pOldSet( new SfxItemSet( rOldSet ) )
+ // <--
+ , m_nNodeIndex( 0 )
+ , m_nFmtWhich( rChgFmt.Which() )
+ , m_bSaveDrawPt( bSaveDrawPt )
+{
+ Init();
+}
+
+SwUndoFmtAttr::SwUndoFmtAttr( const SfxPoolItem& rItem, SwFmt& rChgFmt,
+ bool bSaveDrawPt )
+ : SwUndo( UNDO_INSFMTATTR )
+ , m_pFmt( &rChgFmt )
+ , m_pOldSet( m_pFmt->GetAttrSet().Clone( sal_False ) )
+ , m_nNodeIndex( 0 )
+ , m_nFmtWhich( rChgFmt.Which() )
+ , m_bSaveDrawPt( bSaveDrawPt )
+{
+ m_pOldSet->Put( rItem );
+ Init();
+}
+
+void SwUndoFmtAttr::Init()
+{
+ // treat change of anchor specially
+ if ( SFX_ITEM_SET == m_pOldSet->GetItemState( RES_ANCHOR, sal_False ))
+ {
+ SaveFlyAnchor( m_bSaveDrawPt );
+ }
+ else if ( RES_FRMFMT == m_nFmtWhich )
+ {
+ SwDoc* pDoc = m_pFmt->GetDoc();
+ if (USHRT_MAX != pDoc->GetTblFrmFmts()->GetPos(
+ static_cast<const SwFrmFmtPtr>(m_pFmt)))
+ {
+ // Table Format: save table position, table formats are volatile!
+ SwTable * pTbl = SwIterator<SwTable,SwFmt>::FirstElement( *m_pFmt );
+ if ( pTbl )
+ {
+ m_nNodeIndex = pTbl->GetTabSortBoxes()[ 0 ]->GetSttNd()
+ ->FindTableNode()->GetIndex();
+ }
+ }
+ else if (USHRT_MAX != pDoc->GetSections().GetPos(
+ static_cast<const SwSectionFmtPtr>(m_pFmt)))
+ {
+ m_nNodeIndex = m_pFmt->GetCntnt().GetCntntIdx()->GetIndex();
+ }
+ else if ( 0 != dynamic_cast< SwTableBoxFmt* >( m_pFmt ) )
+ {
+ SwTableBox * pTblBox = SwIterator<SwTableBox,SwFmt>::FirstElement( *m_pFmt );
+ if ( pTblBox )
+ {
+ m_nNodeIndex = pTblBox->GetSttIdx();
+ }
+ }
+ }
+}
+
+SwUndoFmtAttr::~SwUndoFmtAttr()
+{
+}
+
+void SwUndoFmtAttr::UndoImpl(::sw::UndoRedoContext & rContext)
+{
+ // OD 2004-10-26 #i35443#
+ // Important note: <Undo(..)> also called by <ReDo(..)>
+
+ if ( !m_pOldSet.get() || !m_pFmt || !IsFmtInDoc( &rContext.GetDoc() ))
+ return;
+
+ // --> OD 2004-10-26 #i35443# - If anchor attribute has been successfull
+ // restored, all other attributes are also restored.
+ // Thus, keep track of its restoration
+ bool bAnchorAttrRestored( false );
+ if ( SFX_ITEM_SET == m_pOldSet->GetItemState( RES_ANCHOR, sal_False ))
+ {
+ bAnchorAttrRestored = RestoreFlyAnchor(rContext);
+ if ( bAnchorAttrRestored )
+ {
+ // Anchor attribute successfull restored.
+ // Thus, keep anchor position for redo
+ SaveFlyAnchor();
+ }
+ else
+ {
+ // Anchor attribute not restored due to invalid anchor position.
+ // Thus, delete anchor attribute.
+ m_pOldSet->ClearItem( RES_ANCHOR );
+ }
+ }
+
+ if ( !bAnchorAttrRestored )
+ // <--
+ {
+ SwUndoFmtAttrHelper aTmp( *m_pFmt, m_bSaveDrawPt );
+ m_pFmt->SetFmtAttr( *m_pOldSet );
+ if ( aTmp.GetUndo() )
+ {
+ // transfer ownership of helper object's old set
+ m_pOldSet = aTmp.GetUndo()->m_pOldSet;
+ }
+ else
+ {
+ m_pOldSet->ClearItem();
+ }
+
+ if ( RES_FLYFRMFMT == m_nFmtWhich || RES_DRAWFRMFMT == m_nFmtWhich )
+ {
+ rContext.SetSelections(static_cast<SwFrmFmt*>(m_pFmt), 0);
+ }
+ }
+}
+
+bool SwUndoFmtAttr::IsFmtInDoc( SwDoc* pDoc )
+{
+ // search for the Format in the Document; if it does not exist any more,
+ // the attribute is not restored!
+ sal_uInt16 nPos = USHRT_MAX;
+ switch ( m_nFmtWhich )
+ {
+ case RES_TXTFMTCOLL:
+ nPos = pDoc->GetTxtFmtColls()->GetPos(
+ static_cast<const SwTxtFmtCollPtr>(m_pFmt) );
+ break;
+
+ case RES_GRFFMTCOLL:
+ nPos = pDoc->GetGrfFmtColls()->GetPos(
+ static_cast<const SwGrfFmtCollPtr>(m_pFmt) );
+ break;
+
+ case RES_CHRFMT:
+ nPos = pDoc->GetCharFmts()->GetPos(
+ static_cast<SwCharFmtPtr>(m_pFmt) );
+ break;
+
+ case RES_FRMFMT:
+ if ( m_nNodeIndex && (m_nNodeIndex < pDoc->GetNodes().Count()) )
+ {
+ SwNode* pNd = pDoc->GetNodes()[ m_nNodeIndex ];
+ if ( pNd->IsTableNode() )
+ {
+ m_pFmt =
+ static_cast<SwTableNode*>(pNd)->GetTable().GetFrmFmt();
+ nPos = 0;
+ break;
+ }
+ else if ( pNd->IsSectionNode() )
+ {
+ m_pFmt =
+ static_cast<SwSectionNode*>(pNd)->GetSection().GetFmt();
+ nPos = 0;
+ break;
+ }
+ else if ( pNd->IsStartNode() && (SwTableBoxStartNode ==
+ static_cast< SwStartNode* >(pNd)->GetStartNodeType()) )
+ {
+ SwTableNode* pTblNode = pNd->FindTableNode();
+ if ( pTblNode )
+ {
+ SwTableBox* pBox =
+ pTblNode->GetTable().GetTblBox( m_nNodeIndex );
+ if ( pBox )
+ {
+ m_pFmt = pBox->GetFrmFmt();
+ nPos = 0;
+ break;
+ }
+ }
+ }
+ }
+ // no break!
+ case RES_DRAWFRMFMT:
+ case RES_FLYFRMFMT:
+ nPos = pDoc->GetSpzFrmFmts()->GetPos(
+ static_cast<const SwFrmFmtPtr>(m_pFmt) );
+ if ( USHRT_MAX == nPos )
+ {
+ nPos = pDoc->GetFrmFmts()->GetPos(
+ static_cast<const SwFrmFmtPtr>(m_pFmt) );
+ }
+ break;
+ }
+
+ if ( USHRT_MAX == nPos )
+ {
+ // Format does not exist; reset
+ m_pFmt = 0;
+ }
+
+ return 0 != m_pFmt;
+}
+
+// prueft, ob es noch im Doc ist!
+SwFmt* SwUndoFmtAttr::GetFmt( SwDoc& rDoc )
+{
+ return m_pFmt && IsFmtInDoc( &rDoc ) ? m_pFmt : 0;
+}
+
+void SwUndoFmtAttr::RedoImpl(::sw::UndoRedoContext & rContext)
+{
+ // --> OD 2004-10-26 #i35443# - Because the undo stores the attributes for
+ // redo, the same code as for <Undo(..)> can be applied for <Redo(..)>
+ UndoImpl(rContext);
+ // <--
+}
+
+void SwUndoFmtAttr::RepeatImpl(::sw::RepeatContext & rContext)
+{
+ if ( !m_pOldSet.get() )
+ return;
+
+ SwDoc & rDoc(rContext.GetDoc());
+
+ switch ( m_nFmtWhich )
+ {
+ case RES_GRFFMTCOLL:
+ {
+ SwNoTxtNode *const pNd =
+ rContext.GetRepeatPaM().GetNode()->GetNoTxtNode();
+ if( pNd )
+ {
+ rDoc.SetAttr( m_pFmt->GetAttrSet(), *pNd->GetFmtColl() );
+ }
+ }
+ break;
+
+ case RES_TXTFMTCOLL:
+ {
+ SwTxtNode *const pNd =
+ rContext.GetRepeatPaM().GetNode()->GetTxtNode();
+ if( pNd )
+ {
+ rDoc.SetAttr( m_pFmt->GetAttrSet(), *pNd->GetFmtColl() );
+ }
+ }
+ break;
+
+// case RES_CHRFMT:
+// case RES_FRMFMT:
+
+ case RES_FLYFRMFMT:
+ {
+ // erstal pruefen, ob der Cursor ueberhaupt in einem fliegenden
+ // Rahmen steht. Der Weg ist: suche in allen FlyFrmFormaten
+ // nach dem FlyCntnt-Attribut und teste ob der Cursor in der
+ // entsprechenden Section liegt.
+ SwFrmFmt *const pFly =
+ rContext.GetRepeatPaM().GetNode()->GetFlyFmt();
+ if( pFly )
+ {
+ // Bug 43672: es duerfen nicht alle Attribute gesetzt werden!
+ if (SFX_ITEM_SET ==
+ m_pFmt->GetAttrSet().GetItemState( RES_CNTNT ))
+ {
+ SfxItemSet aTmpSet( m_pFmt->GetAttrSet() );
+ aTmpSet.ClearItem( RES_CNTNT );
+ if( aTmpSet.Count() )
+ {
+ rDoc.SetAttr( aTmpSet, *pFly );
+ }
+ }
+ else
+ {
+ rDoc.SetAttr( m_pFmt->GetAttrSet(), *pFly );
+ }
+ }
+ break;
+ }
+ }
+}
+
+SwRewriter SwUndoFmtAttr::GetRewriter() const
+{
+ SwRewriter aRewriter;
+
+ if (m_pFmt)
+ {
+ aRewriter.AddRule(UNDO_ARG1, m_pFmt->GetName());
+ }
+
+ return aRewriter;
+}
+
+void SwUndoFmtAttr::PutAttr( const SfxPoolItem& rItem )
+{
+ m_pOldSet->Put( rItem );
+ if ( RES_ANCHOR == rItem.Which() )
+ {
+ SaveFlyAnchor( m_bSaveDrawPt );
+ }
+}
+
+void SwUndoFmtAttr::SaveFlyAnchor( bool bSvDrwPt )
+{
+ // das Format ist gueltig, sonst wuerde man gar bis hier kommen
+ if( bSvDrwPt )
+ {
+ if ( RES_DRAWFRMFMT == m_pFmt->Which() )
+ {
+ Point aPt( static_cast<SwFrmFmt*>(m_pFmt)->FindSdrObject()
+ ->GetRelativePos() );
+ // store old value as attribute, to keep SwUndoFmtAttr small
+ m_pOldSet->Put( SwFmtFrmSize( ATT_VAR_SIZE, aPt.X(), aPt.Y() ) );
+ }
+/* else
+ {
+ pOldSet->Put( pFmt->GetVertOrient() );
+ pOldSet->Put( pFmt->GetHoriOrient() );
+ }
+*/ }
+
+ const SwFmtAnchor& rAnchor =
+ static_cast<const SwFmtAnchor&>( m_pOldSet->Get( RES_ANCHOR, sal_False ) );
+ if( !rAnchor.GetCntntAnchor() )
+ return;
+
+ xub_StrLen nCntnt = 0;
+ switch( rAnchor.GetAnchorId() )
+ {
+ case FLY_AS_CHAR:
+ case FLY_AT_CHAR:
+ nCntnt = rAnchor.GetCntntAnchor()->nContent.GetIndex();
+ case FLY_AT_PARA:
+ case FLY_AT_FLY:
+ m_nNodeIndex = rAnchor.GetCntntAnchor()->nNode.GetIndex();
+ break;
+ default:
+ return;
+ }
+
+ SwFmtAnchor aAnchor( rAnchor.GetAnchorId(), nCntnt );
+ m_pOldSet->Put( aAnchor );
+}
+
+// --> OD 2004-10-26 #i35443# - Add return value, type <bool>.
+// Return value indicates, if anchor attribute is restored.
+// Note: If anchor attribute is restored, all other existing attributes
+// are also restored.
+bool SwUndoFmtAttr::RestoreFlyAnchor(::sw::UndoRedoContext & rContext)
+{
+ SwDoc *const pDoc = & rContext.GetDoc();
+ SwFlyFrmFmt* pFrmFmt = static_cast<SwFlyFrmFmt*>(m_pFmt);
+ const SwFmtAnchor& rAnchor =
+ static_cast<const SwFmtAnchor&>( m_pOldSet->Get( RES_ANCHOR, sal_False ) );
+
+ SwFmtAnchor aNewAnchor( rAnchor.GetAnchorId() );
+ if (FLY_AT_PAGE != rAnchor.GetAnchorId())
+ {
+ SwNode* pNd = pDoc->GetNodes()[ m_nNodeIndex ];
+
+ if ( (FLY_AT_FLY == rAnchor.GetAnchorId())
+ ? ( !pNd->IsStartNode() || (SwFlyStartNode !=
+ static_cast<SwStartNode*>(pNd)->GetStartNodeType()) )
+ : !pNd->IsTxtNode() )
+ {
+ // --> OD 2004-10-26 #i35443# - invalid position.
+ // Thus, anchor attribute not restored
+ return false;
+ // <--
+ }
+
+ SwPosition aPos( *pNd );
+ if ((FLY_AS_CHAR == rAnchor.GetAnchorId()) ||
+ (FLY_AT_CHAR == rAnchor.GetAnchorId()))
+ {
+ aPos.nContent.Assign( (SwTxtNode*)pNd, rAnchor.GetPageNum() );
+ if ( aPos.nContent.GetIndex() >
+ static_cast<SwTxtNode*>(pNd)->GetTxt().Len() )
+ {
+ // --> OD 2004-10-26 #i35443# - invalid position.
+ // Thus, anchor attribute not restored
+ return false;
+ // <--
+ }
+ }
+ aNewAnchor.SetAnchor( &aPos );
+ }
+ else
+ aNewAnchor.SetPageNum( rAnchor.GetPageNum() );
+
+ Point aDrawSavePt, aDrawOldPt;
+ if( pDoc->GetCurrentViewShell() ) //swmod 071108//swmod 071225
+ {
+ if( RES_DRAWFRMFMT == pFrmFmt->Which() )
+ {
+ // den alten zwischengespeicherten Wert herausholen.
+ const SwFmtFrmSize& rOldSize = static_cast<const SwFmtFrmSize&>(
+ m_pOldSet->Get( RES_FRM_SIZE ) );
+ aDrawSavePt.X() = rOldSize.GetWidth();
+ aDrawSavePt.Y() = rOldSize.GetHeight();
+ m_pOldSet->ClearItem( RES_FRM_SIZE );
+
+ // den akt. wieder zwischenspeichern
+ aDrawOldPt = pFrmFmt->FindSdrObject()->GetRelativePos();
+//JP 08.10.97: ist laut AMA/MA nicht mehr noetig
+// pCont->DisconnectFromLayout();
+ }
+ else
+ {
+ pFrmFmt->DelFrms(); // delete Frms
+ }
+ }
+
+ const SwFmtAnchor &rOldAnch = pFrmFmt->GetAnchor();
+ // --> OD 2006-03-13 #i54336#
+ // Consider case, that as-character anchored object has moved its anchor position.
+ if (FLY_AS_CHAR == rOldAnch.GetAnchorId())
+ // <--
+ {
+ //Bei InCntnt's wird es spannend: Das TxtAttribut muss vernichtet
+ //werden. Leider reisst dies neben den Frms auch noch das Format mit
+ //in sein Grab. Um dass zu unterbinden loesen wir vorher die
+ //Verbindung zwischen Attribut und Format.
+ const SwPosition *pPos = rOldAnch.GetCntntAnchor();
+ SwTxtNode *pTxtNode = (SwTxtNode*)&pPos->nNode.GetNode();
+ OSL_ENSURE( pTxtNode->HasHints(), "Missing FlyInCnt-Hint." );
+ const xub_StrLen nIdx = pPos->nContent.GetIndex();
+ SwTxtAttr * const pHnt =
+ pTxtNode->GetTxtAttrForCharAt( nIdx, RES_TXTATR_FLYCNT );
+ OSL_ENSURE( pHnt && pHnt->Which() == RES_TXTATR_FLYCNT,
+ "Missing FlyInCnt-Hint." );
+ OSL_ENSURE( pHnt && pHnt->GetFlyCnt().GetFrmFmt() == pFrmFmt,
+ "Wrong TxtFlyCnt-Hint." );
+ const_cast<SwFmtFlyCnt&>(pHnt->GetFlyCnt()).SetFlyFmt();
+
+ //Die Verbindung ist geloest, jetzt muss noch das Attribut vernichtet
+ //werden.
+ pTxtNode->DeleteAttributes( RES_TXTATR_FLYCNT, nIdx, nIdx );
+ }
+
+ {
+ m_pOldSet->Put( aNewAnchor );
+ SwUndoFmtAttrHelper aTmp( *m_pFmt, m_bSaveDrawPt );
+ m_pFmt->SetFmtAttr( *m_pOldSet );
+ if ( aTmp.GetUndo() )
+ {
+ m_nNodeIndex = aTmp.GetUndo()->m_nNodeIndex;
+ // transfer ownership of helper object's old set
+ m_pOldSet = aTmp.GetUndo()->m_pOldSet;
+ }
+ else
+ {
+ m_pOldSet->ClearItem();
+ }
+ }
+
+ if ( RES_DRAWFRMFMT == pFrmFmt->Which() )
+ {
+ SwDrawContact *pCont =
+ static_cast<SwDrawContact*>(pFrmFmt->FindContactObj());
+ // das Draw-Model hat auch noch ein Undo-Object fuer die
+ // richtige Position vorbereitet; dieses ist aber relativ.
+ // Darum verhinder hier, das durch setzen des Ankers das
+ // Contact-Object seine Position aendert.
+//JP 08.10.97: ist laut AMA/MA nicht mehr noetig
+// pCont->ConnectToLayout();
+ SdrObject* pObj = pCont->GetMaster();
+
+ if( pCont->GetAnchorFrm() && !pObj->IsInserted() )
+ {
+ OSL_ENSURE( pDoc->GetDrawModel(), "RestoreFlyAnchor without DrawModel" );
+ pDoc->GetDrawModel()->GetPage( 0 )->InsertObject( pObj );
+ }
+ pObj->SetRelativePos( aDrawSavePt );
+
+ // den alten Wert wieder zwischenspeichern.
+ m_pOldSet->Put(
+ SwFmtFrmSize( ATT_VAR_SIZE, aDrawOldPt.X(), aDrawOldPt.Y() ) );
+ }
+
+ if (FLY_AS_CHAR == aNewAnchor.GetAnchorId())
+ {
+ const SwPosition* pPos = aNewAnchor.GetCntntAnchor();
+ SwTxtNode* pTxtNd = pPos->nNode.GetNode().GetTxtNode();
+ OSL_ENSURE( pTxtNd, "no Text Node at position." );
+ SwFmtFlyCnt aFmt( pFrmFmt );
+ pTxtNd->InsertItem( aFmt, pPos->nContent.GetIndex(), 0 );
+ }
+
+
+ if( RES_DRAWFRMFMT != pFrmFmt->Which() )
+ pFrmFmt->MakeFrms();
+
+ rContext.SetSelections(pFrmFmt, 0);
+
+ // --> OD 2004-10-26 #i35443# - anchor attribute restored.
+ return true;
+ // <--
+}
+
+// -----------------------------------------------------
+SwUndoFmtResetAttr::SwUndoFmtResetAttr( SwFmt& rChangedFormat,
+ const sal_uInt16 nWhichId )
+ : SwUndo( UNDO_RESETATTR )
+ , m_pChangedFormat( &rChangedFormat )
+ , m_nWhichId( nWhichId )
+ , m_pOldItem( 0 )
+{
+ const SfxPoolItem* pItem = 0;
+ if (rChangedFormat.GetItemState( nWhichId, sal_False, &pItem ) == SFX_ITEM_SET)
+ {
+ m_pOldItem.reset( pItem->Clone() );
+ }
+}
+
+SwUndoFmtResetAttr::~SwUndoFmtResetAttr()
+{
+}
+
+void SwUndoFmtResetAttr::UndoImpl(::sw::UndoRedoContext &)
+{
+ if ( m_pOldItem.get() )
+ {
+ m_pChangedFormat->SetFmtAttr( *m_pOldItem );
+ }
+}
+
+void SwUndoFmtResetAttr::RedoImpl(::sw::UndoRedoContext &)
+{
+ if ( m_pOldItem.get() )
+ {
+ m_pChangedFormat->ResetFmtAttr( m_nWhichId );
+ }
+}
+// <--
+
+// -----------------------------------------------------
+
+SwUndoResetAttr::SwUndoResetAttr( const SwPaM& rRange, sal_uInt16 nFmtId )
+ : SwUndo( UNDO_RESETATTR ), SwUndRng( rRange )
+ , m_pHistory( new SwHistory )
+ , m_nFormatId( nFmtId )
+{
+}
+
+SwUndoResetAttr::SwUndoResetAttr( const SwPosition& rPos, sal_uInt16 nFmtId )
+ : SwUndo( UNDO_RESETATTR )
+ , m_pHistory( new SwHistory )
+ , m_nFormatId( nFmtId )
+{
+ nSttNode = nEndNode = rPos.nNode.GetIndex();
+ nSttCntnt = nEndCntnt = rPos.nContent.GetIndex();
+}
+
+SwUndoResetAttr::~SwUndoResetAttr()
+{
+}
+
+void SwUndoResetAttr::UndoImpl(::sw::UndoRedoContext & rContext)
+{
+ // reset old values
+ SwDoc & rDoc = rContext.GetDoc();
+ m_pHistory->TmpRollback( &rDoc, 0 );
+ m_pHistory->SetTmpEnd( m_pHistory->Count() );
+
+ if ((RES_CONDTXTFMTCOLL == m_nFormatId) &&
+ (nSttNode == nEndNode) && (nSttCntnt == nEndCntnt))
+ {
+ SwTxtNode* pTNd = rDoc.GetNodes()[ nSttNode ]->GetTxtNode();
+ if( pTNd )
+ {
+ SwIndex aIdx( pTNd, nSttCntnt );
+ pTNd->DontExpandFmt( aIdx, sal_False );
+ }
+ }
+
+ AddUndoRedoPaM(rContext);
+}
+
+void SwUndoResetAttr::RedoImpl(::sw::UndoRedoContext & rContext)
+{
+ SwDoc & rDoc = rContext.GetDoc();
+ SwPaM & rPam = AddUndoRedoPaM(rContext);
+ SvUShortsSort* pIdArr = m_Ids.Count() ? &m_Ids : 0;
+
+ switch ( m_nFormatId )
+ {
+ case RES_CHRFMT:
+ rDoc.RstTxtAttrs(rPam);
+ break;
+ case RES_TXTFMTCOLL:
+ rDoc.ResetAttrs(rPam, sal_False, pIdArr );
+ break;
+ case RES_CONDTXTFMTCOLL:
+ rDoc.ResetAttrs(rPam, sal_True, pIdArr );
+
+ break;
+ case RES_TXTATR_TOXMARK:
+ // special treatment for TOXMarks
+ {
+ SwTOXMarks aArr;
+ SwNodeIndex aIdx( rDoc.GetNodes(), nSttNode );
+ SwPosition aPos( aIdx, SwIndex( aIdx.GetNode().GetCntntNode(),
+ nSttCntnt ));
+
+ sal_uInt16 nCnt = rDoc.GetCurTOXMark( aPos, aArr );
+ if( nCnt )
+ {
+ if( 1 < nCnt )
+ {
+ // search for the right one
+ SwHistoryHint* pHHint = (GetHistory())[ 0 ];
+ if( pHHint && HSTRY_SETTOXMARKHNT == pHHint->Which() )
+ {
+ while( nCnt )
+ {
+ if ( static_cast<SwHistorySetTOXMark*>(pHHint)
+ ->IsEqual( *aArr[ --nCnt ] ) )
+ {
+ ++nCnt;
+ break;
+ }
+ }
+ }
+ else
+ nCnt = 0;
+ }
+ // gefunden, also loeschen
+ if( nCnt-- )
+ {
+ rDoc.DeleteTOXMark( aArr[ nCnt ] );
+ }
+ }
+ }
+ break;
+ }
+}
+
+void SwUndoResetAttr::RepeatImpl(::sw::RepeatContext & rContext)
+{
+ if (m_nFormatId < RES_FMT_BEGIN)
+ {
+ return;
+ }
+
+ SvUShortsSort* pIdArr = m_Ids.Count() ? &m_Ids : 0;
+ switch ( m_nFormatId )
+ {
+ case RES_CHRFMT:
+ rContext.GetDoc().RstTxtAttrs(rContext.GetRepeatPaM());
+ break;
+ case RES_TXTFMTCOLL:
+ rContext.GetDoc().ResetAttrs(rContext.GetRepeatPaM(), false, pIdArr);
+ break;
+ case RES_CONDTXTFMTCOLL:
+ rContext.GetDoc().ResetAttrs(rContext.GetRepeatPaM(), true, pIdArr);
+ break;
+ }
+}
+
+
+void SwUndoResetAttr::SetAttrs( const SvUShortsSort& rArr )
+{
+ if ( m_Ids.Count() )
+ {
+ m_Ids.Remove( 0, m_Ids.Count() );
+ }
+ m_Ids.Insert( &rArr );
+}
+
+// -----------------------------------------------------
+
+
+SwUndoAttr::SwUndoAttr( const SwPaM& rRange, const SfxPoolItem& rAttr,
+ const SetAttrMode nFlags )
+ : SwUndo( UNDO_INSATTR ), SwUndRng( rRange )
+ , m_AttrSet( rRange.GetDoc()->GetAttrPool(), rAttr.Which(), rAttr.Which() )
+ , m_pHistory( new SwHistory )
+ , m_pRedlineData( 0 )
+ , m_pRedlineSaveData( 0 )
+ , m_nNodeIndex( ULONG_MAX )
+ , m_nInsertFlags( nFlags )
+{
+ m_AttrSet.Put( rAttr );
+}
+
+SwUndoAttr::SwUndoAttr( const SwPaM& rRange, const SfxItemSet& rSet,
+ const SetAttrMode nFlags )
+ : SwUndo( UNDO_INSATTR ), SwUndRng( rRange )
+ , m_AttrSet( rSet )
+ , m_pHistory( new SwHistory )
+ , m_pRedlineData( 0 )
+ , m_pRedlineSaveData( 0 )
+ , m_nNodeIndex( ULONG_MAX )
+ , m_nInsertFlags( nFlags )
+{
+}
+
+SwUndoAttr::~SwUndoAttr()
+{
+}
+
+void SwUndoAttr::SaveRedlineData( const SwPaM& rPam, sal_Bool bIsCntnt )
+{
+ SwDoc* pDoc = rPam.GetDoc();
+ if ( pDoc->IsRedlineOn() )
+ {
+ m_pRedlineData.reset( new SwRedlineData( bIsCntnt
+ ? nsRedlineType_t::REDLINE_INSERT
+ : nsRedlineType_t::REDLINE_FORMAT,
+ pDoc->GetRedlineAuthor() ) );
+ }
+
+ m_pRedlineSaveData.reset( new SwRedlineSaveDatas );
+ if ( !FillSaveDataForFmt( rPam, *m_pRedlineSaveData ))
+ {
+ m_pRedlineSaveData.reset(0);
+ }
+
+ SetRedlineMode( pDoc->GetRedlineMode() );
+ if ( bIsCntnt )
+ {
+ m_nNodeIndex = rPam.GetPoint()->nNode.GetIndex();
+ }
+}
+
+void SwUndoAttr::UndoImpl(::sw::UndoRedoContext & rContext)
+{
+ SwDoc *const pDoc = & rContext.GetDoc();
+
+ RemoveIdx( *pDoc );
+
+ if( IDocumentRedlineAccess::IsRedlineOn( GetRedlineMode() ) )
+ {
+ SwPaM aPam(pDoc->GetNodes().GetEndOfContent());
+ if ( ULONG_MAX != m_nNodeIndex )
+ {
+ aPam.DeleteMark();
+ aPam.GetPoint()->nNode = m_nNodeIndex;
+ aPam.GetPoint()->nContent.Assign( aPam.GetCntntNode(), nSttCntnt );
+ aPam.SetMark();
+ aPam.GetPoint()->nContent++;
+ pDoc->DeleteRedline(aPam, false, USHRT_MAX);
+ }
+ else
+ {
+ // alle Format-Redlines entfernen, werden ggfs. neu gesetzt
+ SetPaM(aPam);
+ pDoc->DeleteRedline(aPam, false, nsRedlineType_t::REDLINE_FORMAT);
+ if ( m_pRedlineSaveData.get() )
+ {
+ SetSaveData( *pDoc, *m_pRedlineSaveData );
+ }
+ }
+ }
+
+ const bool bToLast = (1 == m_AttrSet.Count())
+ && (RES_TXTATR_FIELD <= *m_AttrSet.GetRanges())
+ && (*m_AttrSet.GetRanges() <= RES_TXTATR_FTN);
+
+ // restore old values
+ m_pHistory->TmpRollback( pDoc, 0, !bToLast );
+ m_pHistory->SetTmpEnd( m_pHistory->Count() );
+
+ // set cursor onto Undo area
+ AddUndoRedoPaM(rContext);
+}
+
+void SwUndoAttr::RepeatImpl(::sw::RepeatContext & rContext)
+{
+ // RefMarks are not repeat capable
+ if ( SFX_ITEM_SET != m_AttrSet.GetItemState( RES_TXTATR_REFMARK, sal_False ) )
+ {
+ rContext.GetDoc().InsertItemSet( rContext.GetRepeatPaM(),
+ m_AttrSet, m_nInsertFlags );
+ }
+ else if ( 1 < m_AttrSet.Count() )
+ {
+ SfxItemSet aTmpSet( m_AttrSet );
+ aTmpSet.ClearItem( RES_TXTATR_REFMARK );
+ rContext.GetDoc().InsertItemSet( rContext.GetRepeatPaM(),
+ aTmpSet, m_nInsertFlags );
+ }
+}
+
+void SwUndoAttr::RedoImpl(::sw::UndoRedoContext & rContext)
+{
+ SwDoc & rDoc = rContext.GetDoc();
+ SwPaM & rPam = AddUndoRedoPaM(rContext);
+
+ if ( m_pRedlineData.get() &&
+ IDocumentRedlineAccess::IsRedlineOn( GetRedlineMode() ) )
+ {
+ RedlineMode_t eOld = rDoc.GetRedlineMode();
+ rDoc.SetRedlineMode_intern(static_cast<RedlineMode_t>(
+ eOld & ~nsRedlineMode_t::REDLINE_IGNORE));
+ rDoc.InsertItemSet( rPam, m_AttrSet, m_nInsertFlags );
+
+ if ( ULONG_MAX != m_nNodeIndex )
+ {
+ rPam.SetMark();
+ if ( rPam.Move( fnMoveBackward ) )
+ {
+ rDoc.AppendRedline( new SwRedline( *m_pRedlineData, rPam ),
+ true);
+ }
+ rPam.DeleteMark();
+ }
+ else
+ {
+ rDoc.AppendRedline( new SwRedline( *m_pRedlineData, rPam ), true);
+ }
+
+ rDoc.SetRedlineMode_intern( eOld );
+ }
+ else
+ {
+ rDoc.InsertItemSet( rPam, m_AttrSet, m_nInsertFlags );
+ }
+}
+
+
+void SwUndoAttr::RemoveIdx( SwDoc& rDoc )
+{
+ if ( SFX_ITEM_SET != m_AttrSet.GetItemState( RES_TXTATR_FTN, sal_False ))
+ return ;
+
+ SwHistoryHint* pHstHnt;
+ SwNodes& rNds = rDoc.GetNodes();
+ for ( sal_uInt16 n = 0; n < m_pHistory->Count(); ++n )
+ {
+ xub_StrLen nCntnt = 0;
+ sal_uLong nNode = 0;
+ pHstHnt = (*m_pHistory)[ n ];
+ switch ( pHstHnt->Which() )
+ {
+ case HSTRY_RESETTXTHNT:
+ {
+ SwHistoryResetTxt * pHistoryHint
+ = static_cast<SwHistoryResetTxt*>(pHstHnt);
+ if ( RES_TXTATR_FTN == pHistoryHint->GetWhich() )
+ {
+ nNode = pHistoryHint->GetNode();
+ nCntnt = pHistoryHint->GetCntnt();
+ }
+ }
+ break;
+
+ case HSTRY_RESETATTRSET:
+ {
+ SwHistoryResetAttrSet * pHistoryHint
+ = static_cast<SwHistoryResetAttrSet*>(pHstHnt);
+ nCntnt = pHistoryHint->GetCntnt();
+ if ( STRING_MAXLEN != nCntnt )
+ {
+ const SvUShorts& rArr = pHistoryHint->GetArr();
+ for ( sal_uInt16 i = rArr.Count(); i; )
+ {
+ if ( RES_TXTATR_FTN == rArr[ --i ] )
+ {
+ nNode = pHistoryHint->GetNode();
+ break;
+ }
+ }
+ }
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ if( nNode )
+ {
+ SwTxtNode* pTxtNd = rNds[ nNode ]->GetTxtNode();
+ if( pTxtNd )
+ {
+ SwTxtAttr *const pTxtHt =
+ pTxtNd->GetTxtAttrForCharAt(nCntnt, RES_TXTATR_FTN);
+ if( pTxtHt )
+ {
+ // ok, dann hole mal die Werte
+ SwTxtFtn* pFtn = static_cast<SwTxtFtn*>(pTxtHt);
+ RemoveIdxFromSection( rDoc, pFtn->GetStartNode()->GetIndex() );
+ return ;
+ }
+ }
+ }
+ }
+}
+
+// -----------------------------------------------------
+
+SwUndoDefaultAttr::SwUndoDefaultAttr( const SfxItemSet& rSet )
+ : SwUndo( UNDO_SETDEFTATTR )
+ , m_pOldSet( 0 )
+ , m_pTabStop( 0 )
+{
+ const SfxPoolItem* pItem;
+ if( SFX_ITEM_SET == rSet.GetItemState( RES_PARATR_TABSTOP, sal_False, &pItem ) )
+ {
+ // store separately, because it may change!
+ m_pTabStop.reset( static_cast<SvxTabStopItem*>(pItem->Clone()) );
+ if ( 1 != rSet.Count() ) // are there more attributes?
+ {
+ m_pOldSet.reset( new SfxItemSet( rSet ) );
+ }
+ }
+ else
+ {
+ m_pOldSet.reset( new SfxItemSet( rSet ) );
+ }
+}
+
+SwUndoDefaultAttr::~SwUndoDefaultAttr()
+{
+}
+
+void SwUndoDefaultAttr::UndoImpl(::sw::UndoRedoContext & rContext)
+{
+ SwDoc & rDoc = rContext.GetDoc();
+ if ( m_pOldSet.get() )
+ {
+ SwUndoFmtAttrHelper aTmp(
+ *const_cast<SwTxtFmtColl*>(rDoc.GetDfltTxtFmtColl()) );
+ rDoc.SetDefault( *m_pOldSet );
+ m_pOldSet.reset( 0 );
+ if ( aTmp.GetUndo() )
+ {
+ // transfer ownership of helper object's old set
+ m_pOldSet = aTmp.GetUndo()->m_pOldSet;
+ }
+ }
+ if ( m_pTabStop.get() )
+ {
+ SvxTabStopItem* pOld = static_cast<SvxTabStopItem*>(
+ rDoc.GetDefault( RES_PARATR_TABSTOP ).Clone() );
+ rDoc.SetDefault( *m_pTabStop );
+ m_pTabStop.reset( pOld );
+ }
+}
+
+void SwUndoDefaultAttr::RedoImpl(::sw::UndoRedoContext & rContext)
+{
+ UndoImpl(rContext);
+}
+
+// -----------------------------------------------------
+
+SwUndoMoveLeftMargin::SwUndoMoveLeftMargin(
+ const SwPaM& rPam, sal_Bool bFlag, sal_Bool bMod )
+ : SwUndo( bFlag ? UNDO_INC_LEFTMARGIN : UNDO_DEC_LEFTMARGIN )
+ , SwUndRng( rPam )
+ , m_pHistory( new SwHistory )
+ , m_bModulus( bMod )
+{
+}
+
+SwUndoMoveLeftMargin::~SwUndoMoveLeftMargin()
+{
+}
+
+void SwUndoMoveLeftMargin::UndoImpl(::sw::UndoRedoContext & rContext)
+{
+ SwDoc & rDoc = rContext.GetDoc();
+
+ // restore old values
+ m_pHistory->TmpRollback( & rDoc, 0 );
+ m_pHistory->SetTmpEnd( m_pHistory->Count() );
+
+ AddUndoRedoPaM(rContext);
+}
+
+void SwUndoMoveLeftMargin::RedoImpl(::sw::UndoRedoContext & rContext)
+{
+ SwDoc & rDoc = rContext.GetDoc();
+ SwPaM & rPam = AddUndoRedoPaM(rContext);
+
+ rDoc.MoveLeftMargin( rPam,
+ GetId() == UNDO_INC_LEFTMARGIN, m_bModulus );
+}
+
+void SwUndoMoveLeftMargin::RepeatImpl(::sw::RepeatContext & rContext)
+{
+ SwDoc & rDoc = rContext.GetDoc();
+ rDoc.MoveLeftMargin(rContext.GetRepeatPaM(), GetId() == UNDO_INC_LEFTMARGIN,
+ m_bModulus );
+}
+
+// -----------------------------------------------------
+
+SwUndoChangeFootNote::SwUndoChangeFootNote(
+ const SwPaM& rRange, const String& rTxt,
+ sal_uInt16 nNum, bool bIsEndNote )
+ : SwUndo( UNDO_CHGFTN ), SwUndRng( rRange )
+ , m_pHistory( new SwHistory() )
+ , m_Text( rTxt )
+ , m_nNumber( nNum )
+ , m_bEndNote( bIsEndNote )
+{
+}
+
+SwUndoChangeFootNote::~SwUndoChangeFootNote()
+{
+}
+
+void SwUndoChangeFootNote::UndoImpl(::sw::UndoRedoContext & rContext)
+{
+ SwDoc & rDoc = rContext.GetDoc();
+
+ m_pHistory->TmpRollback( &rDoc, 0 );
+ m_pHistory->SetTmpEnd( m_pHistory->Count() );
+
+ rDoc.GetFtnIdxs().UpdateAllFtn();
+
+ AddUndoRedoPaM(rContext);
+}
+
+void SwUndoChangeFootNote::RedoImpl(::sw::UndoRedoContext & rContext)
+{
+ SwDoc & rDoc( rContext.GetDoc() );
+ SwPaM & rPaM = AddUndoRedoPaM(rContext);
+ rDoc.SetCurFtn(rPaM, m_Text, m_nNumber, m_bEndNote);
+ SetPaM(rPaM);
+}
+
+void SwUndoChangeFootNote::RepeatImpl(::sw::RepeatContext & rContext)
+{
+ SwDoc & rDoc = rContext.GetDoc();
+ rDoc.SetCurFtn( rContext.GetRepeatPaM(), m_Text, m_nNumber, m_bEndNote );
+}
+
+
+// -----------------------------------------------------
+
+
+SwUndoFootNoteInfo::SwUndoFootNoteInfo( const SwFtnInfo &rInfo )
+ : SwUndo( UNDO_FTNINFO )
+ , m_pFootNoteInfo( new SwFtnInfo( rInfo ) )
+{
+}
+
+SwUndoFootNoteInfo::~SwUndoFootNoteInfo()
+{
+}
+
+void SwUndoFootNoteInfo::UndoImpl(::sw::UndoRedoContext & rContext)
+{
+ SwDoc & rDoc = rContext.GetDoc();
+ SwFtnInfo *pInf = new SwFtnInfo( rDoc.GetFtnInfo() );
+ rDoc.SetFtnInfo( *m_pFootNoteInfo );
+ m_pFootNoteInfo.reset( pInf );
+}
+
+void SwUndoFootNoteInfo::RedoImpl(::sw::UndoRedoContext & rContext)
+{
+ SwDoc & rDoc = rContext.GetDoc();
+ SwFtnInfo *pInf = new SwFtnInfo( rDoc.GetFtnInfo() );
+ rDoc.SetFtnInfo( *m_pFootNoteInfo );
+ m_pFootNoteInfo.reset( pInf );
+}
+
+
+// -----------------------------------------------------
+
+SwUndoEndNoteInfo::SwUndoEndNoteInfo( const SwEndNoteInfo &rInfo )
+ : SwUndo( UNDO_FTNINFO )
+ , m_pEndNoteInfo( new SwEndNoteInfo( rInfo ) )
+{
+}
+
+SwUndoEndNoteInfo::~SwUndoEndNoteInfo()
+{
+}
+
+void SwUndoEndNoteInfo::UndoImpl(::sw::UndoRedoContext & rContext)
+{
+ SwDoc & rDoc = rContext.GetDoc();
+ SwEndNoteInfo *pInf = new SwEndNoteInfo( rDoc.GetEndNoteInfo() );
+ rDoc.SetEndNoteInfo( *m_pEndNoteInfo );
+ m_pEndNoteInfo.reset( pInf );
+}
+
+void SwUndoEndNoteInfo::RedoImpl(::sw::UndoRedoContext & rContext)
+{
+ SwDoc & rDoc = rContext.GetDoc();
+ SwEndNoteInfo *pInf = new SwEndNoteInfo( rDoc.GetEndNoteInfo() );
+ rDoc.SetEndNoteInfo( *m_pEndNoteInfo );
+ m_pEndNoteInfo.reset( pInf );
+}
+
+// -----------------------------------------------------
+
+SwUndoDontExpandFmt::SwUndoDontExpandFmt( const SwPosition& rPos )
+ : SwUndo( UNDO_DONTEXPAND )
+ , m_nNodeIndex( rPos.nNode.GetIndex() )
+ , m_nContentIndex( rPos.nContent.GetIndex() )
+{
+}
+
+void SwUndoDontExpandFmt::UndoImpl(::sw::UndoRedoContext & rContext)
+{
+ SwPaM *const pPam(& rContext.GetCursorSupplier().CreateNewShellCursor());
+ SwDoc *const pDoc = & rContext.GetDoc();
+
+ SwPosition& rPos = *pPam->GetPoint();
+ rPos.nNode = m_nNodeIndex;
+ rPos.nContent.Assign( rPos.nNode.GetNode().GetCntntNode(), m_nContentIndex);
+ pDoc->DontExpandFmt( rPos, sal_False );
+}
+
+
+void SwUndoDontExpandFmt::RedoImpl(::sw::UndoRedoContext & rContext)
+{
+ SwPaM *const pPam(& rContext.GetCursorSupplier().CreateNewShellCursor());
+ SwDoc *const pDoc = & rContext.GetDoc();
+
+ SwPosition& rPos = *pPam->GetPoint();
+ rPos.nNode = m_nNodeIndex;
+ rPos.nContent.Assign( rPos.nNode.GetNode().GetCntntNode(), m_nContentIndex);
+ pDoc->DontExpandFmt( rPos );
+}
+
+void SwUndoDontExpandFmt::RepeatImpl(::sw::RepeatContext & rContext)
+{
+ SwPaM & rPam = rContext.GetRepeatPaM();
+ SwDoc & rDoc = rContext.GetDoc();
+ rDoc.DontExpandFmt( *rPam.GetPoint() );
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/undo/unbkmk.cxx b/sw/source/core/undo/unbkmk.cxx
new file mode 100644
index 000000000000..26dfc0b1c256
--- /dev/null
+++ b/sw/source/core/undo/unbkmk.cxx
@@ -0,0 +1,107 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+#include <UndoBookmark.hxx>
+
+#include "doc.hxx"
+#include "docary.hxx"
+#include "swundo.hxx" // fuer die UndoIds
+#include "pam.hxx"
+
+#include <UndoCore.hxx>
+#include "IMark.hxx"
+#include "rolbck.hxx"
+
+#include "SwRewriter.hxx"
+
+
+SwUndoBookmark::SwUndoBookmark( SwUndoId nUndoId,
+ const ::sw::mark::IMark& rBkmk )
+ : SwUndo( nUndoId )
+ , m_pHistoryBookmark(new SwHistoryBookmark(rBkmk, true, rBkmk.IsExpanded()))
+{
+}
+
+SwUndoBookmark::~SwUndoBookmark()
+{
+}
+
+void SwUndoBookmark::SetInDoc( SwDoc* pDoc )
+{
+ m_pHistoryBookmark->SetInDoc( pDoc, false );
+}
+
+void SwUndoBookmark::ResetInDoc( SwDoc* pDoc )
+{
+ IDocumentMarkAccess* const pMarkAccess = pDoc->getIDocumentMarkAccess();
+ for (IDocumentMarkAccess::const_iterator_t ppBkmk =
+ pMarkAccess->getMarksBegin();
+ ppBkmk != pMarkAccess->getMarksEnd();
+ ++ppBkmk)
+ {
+ if ( m_pHistoryBookmark->IsEqualBookmark( **ppBkmk ) )
+ {
+ pMarkAccess->deleteMark( ppBkmk );
+ break;
+ }
+ }
+}
+
+SwRewriter SwUndoBookmark::GetRewriter() const
+{
+ SwRewriter aResult;
+
+ aResult.AddRule(UNDO_ARG1, m_pHistoryBookmark->GetName());
+
+ return aResult;
+}
+
+//----------------------------------------------------------------------
+
+
+SwUndoInsBookmark::SwUndoInsBookmark( const ::sw::mark::IMark& rBkmk )
+ : SwUndoBookmark( UNDO_INSBOOKMARK, rBkmk )
+{
+}
+
+
+void SwUndoInsBookmark::UndoImpl(::sw::UndoRedoContext & rContext)
+{
+ ResetInDoc( &rContext.GetDoc() );
+}
+
+void SwUndoInsBookmark::RedoImpl(::sw::UndoRedoContext & rContext)
+{
+ SetInDoc( &rContext.GetDoc() );
+}
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ \ No newline at end of file
diff --git a/sw/source/core/undo/undel.cxx b/sw/source/core/undo/undel.cxx
new file mode 100644
index 000000000000..6c296013e966
--- /dev/null
+++ b/sw/source/core/undo/undel.cxx
@@ -0,0 +1,991 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+#include <UndoDelete.hxx>
+#include <hintids.hxx>
+#include <unotools/charclass.hxx>
+#include <editeng/brkitem.hxx>
+#include <fmtpdsc.hxx>
+#include <frmfmt.hxx>
+#include <fmtanchr.hxx>
+#include <doc.hxx>
+#include <UndoManager.hxx>
+#include <swtable.hxx>
+#include <swundo.hxx> // fuer die UndoIds
+#include <pam.hxx>
+#include <ndtxt.hxx>
+#include <UndoCore.hxx>
+#include <rolbck.hxx>
+#include <poolfmt.hxx>
+#include <mvsave.hxx>
+#include <redline.hxx>
+#include <docary.hxx>
+#include <sfx2/app.hxx>
+
+#include <fldbas.hxx>
+#include <fmtfld.hxx>
+#include <comcore.hrc> // #111827#
+#include <undo.hrc>
+
+
+// DELETE
+/* lcl_MakeAutoFrms has to call MakeFrms for objects bounded "AtChar" ( == AUTO ),
+ if the anchor frame has be moved via _MoveNodes(..) and DelFrms(..)
+*/
+
+void lcl_MakeAutoFrms( const SwSpzFrmFmts& rSpzArr, sal_uLong nMovedIndex )
+{
+ if( rSpzArr.Count() )
+ {
+ SwFlyFrmFmt* pFmt;
+ const SwFmtAnchor* pAnchor;
+ for( sal_uInt16 n = 0; n < rSpzArr.Count(); ++n )
+ {
+ pFmt = (SwFlyFrmFmt*)rSpzArr[n];
+ pAnchor = &pFmt->GetAnchor();
+ if (pAnchor->GetAnchorId() == FLY_AT_CHAR)
+ {
+ const SwPosition* pAPos = pAnchor->GetCntntAnchor();
+ if( pAPos && nMovedIndex == pAPos->nNode.GetIndex() )
+ pFmt->MakeFrms();
+ }
+ }
+ }
+}
+
+/*
+SwUndoDelete has to perform a deletion and to record anything that is needed to restore the
+situation before the deletion. Unfortunately a part of the deletion will be done after calling
+this Ctor, this has to be kept in mind! In this Ctor only the complete paragraphs will be deleted,
+the joining of the first and last paragraph of the selection will be handled outside this function.
+Here are the main steps of the function:
+1. Deletion/recording of content indizes of the selection: footnotes, fly frames and bookmarks
+Step 1 could shift all nodes by deletion of footnotes => nNdDiff will be set.
+2. If the paragraph where the selection ends, is the last content of a section so that this
+section becomes empty when the paragraphs will be joined we have to do some smart actions ;-)
+The paragraph will be moved outside the section and replaced by a dummy text node, the complete
+section will be deleted in step 3. The difference between replacement dummy and original is
+nReplacementDummy.
+3. Moving complete selected nodes into the UndoArray. Before this happens the selection has to be
+extended if there are sections which would become empty otherwise. BTW: sections will be moved into
+the UndoArray if they are complete part of the selection. Sections starting or ending outside of the
+selection will not be removed from the DocNodeArray even they got a "dummy"-copy in the UndoArray.
+4. We have to anticipate the joining of the two paragraphs if the start paragraph is inside a
+section and the end paragraph not. Then we have to move the paragraph into this section and to
+record this in nSectDiff.
+*/
+
+SwUndoDelete::SwUndoDelete( SwPaM& rPam, sal_Bool bFullPara, sal_Bool bCalledByTblCpy )
+ : SwUndo(UNDO_DELETE), SwUndRng( rPam ),
+ pMvStt( 0 ), pSttStr(0), pEndStr(0), pRedlData(0), pRedlSaveData(0),
+ nNode(0), nNdDiff(0), nSectDiff(0), nReplaceDummy(0), nSetPos(0),
+ bGroup( sal_False ), bBackSp( sal_False ), bJoinNext( sal_False ), bTblDelLastNd( sal_False ),
+ bDelFullPara( bFullPara ), bResetPgDesc( sal_False ), bResetPgBrk( sal_False ),
+ bFromTableCopy( bCalledByTblCpy )
+{
+ bDelFullPara = bFullPara; // This is set e.g. if an empty paragraph before a table is deleted
+
+ bCacheComment = false;
+
+ SwDoc * pDoc = rPam.GetDoc();
+
+ if( !pDoc->IsIgnoreRedline() && pDoc->GetRedlineTbl().Count() )
+ {
+ pRedlSaveData = new SwRedlineSaveDatas;
+ if( !FillSaveData( rPam, *pRedlSaveData ))
+ delete pRedlSaveData, pRedlSaveData = 0;
+ }
+
+ if( !pHistory )
+ pHistory = new SwHistory;
+
+ // loesche erstmal alle Fussnoten
+ const SwPosition *pStt = rPam.Start(),
+ *pEnd = rPam.GetPoint() == pStt
+ ? rPam.GetMark()
+ : rPam.GetPoint();
+
+ // Step 1. deletion/record of content indizes
+ if( bDelFullPara )
+ {
+ OSL_ENSURE( rPam.HasMark(), "PaM ohne Mark" );
+ DelCntntIndex( *rPam.GetMark(), *rPam.GetPoint(),
+ DelCntntType(nsDelCntntType::DELCNT_ALL | nsDelCntntType::DELCNT_CHKNOCNTNT) );
+
+ ::sw::UndoGuard const undoGuard(pDoc->GetIDocumentUndoRedo());
+ _DelBookmarks(pStt->nNode, pEnd->nNode);
+ }
+ else
+ DelCntntIndex( *rPam.GetMark(), *rPam.GetPoint() );
+
+ nSetPos = pHistory ? pHistory->Count() : 0;
+
+ // wurde schon was geloescht ??
+ nNdDiff = nSttNode - pStt->nNode.GetIndex();
+
+ bJoinNext = !bFullPara && pEnd == rPam.GetPoint();
+ bBackSp = !bFullPara && !bJoinNext;
+
+ SwTxtNode *pSttTxtNd = 0, *pEndTxtNd = 0;
+ if( !bFullPara )
+ {
+ pSttTxtNd = pStt->nNode.GetNode().GetTxtNode();
+ pEndTxtNd = nSttNode == nEndNode
+ ? pSttTxtNd
+ : pEnd->nNode.GetNode().GetTxtNode();
+ }
+
+ sal_Bool bMoveNds = *pStt == *pEnd // noch ein Bereich vorhanden ??
+ ? sal_False
+ : ( SaveCntnt( pStt, pEnd, pSttTxtNd, pEndTxtNd ) || bFromTableCopy );
+
+ if( pSttTxtNd && pEndTxtNd && pSttTxtNd != pEndTxtNd )
+ {
+ // zwei unterschiedliche TextNodes, also speicher noch die
+ // TextFormatCollection fuers
+ pHistory->Add( pSttTxtNd->GetTxtColl(),pStt->nNode.GetIndex(), ND_TEXTNODE );
+ pHistory->Add( pEndTxtNd->GetTxtColl(),pEnd->nNode.GetIndex(), ND_TEXTNODE );
+
+ if( !bJoinNext ) // Selection von Unten nach Oben
+ {
+ // Beim JoinPrev() werden die AUTO-PageBreak's richtig
+ // kopiert. Um diese beim Undo wieder herzustellen, muss das
+ // Auto-PageBreak aus dem EndNode zurueckgesetzt werden.
+ // - fuer die PageDesc, ColBreak dito !
+ if( pEndTxtNd->HasSwAttrSet() )
+ {
+ SwRegHistory aRegHist( *pEndTxtNd, pHistory );
+ if( SFX_ITEM_SET == pEndTxtNd->GetpSwAttrSet()->GetItemState(
+ RES_BREAK, sal_False ) )
+ pEndTxtNd->ResetAttr( RES_BREAK );
+ if( pEndTxtNd->HasSwAttrSet() &&
+ SFX_ITEM_SET == pEndTxtNd->GetpSwAttrSet()->GetItemState(
+ RES_PAGEDESC, sal_False ) )
+ pEndTxtNd->ResetAttr( RES_PAGEDESC );
+ }
+ }
+ }
+
+
+ // verschiebe jetzt noch den PaM !!!
+ // der SPoint steht am Anfang der SSelection
+ if( pEnd == rPam.GetPoint() && ( !bFullPara || pSttTxtNd || pEndTxtNd ) )
+ rPam.Exchange();
+
+ if( !pSttTxtNd && !pEndTxtNd )
+ rPam.GetPoint()->nNode--;
+ rPam.DeleteMark(); // der SPoint ist aus dem Bereich
+
+ if( !pEndTxtNd )
+ nEndCntnt = 0;
+ if( !pSttTxtNd )
+ nSttCntnt = 0;
+
+ if( bMoveNds ) // sind noch Nodes zu verschieben ?
+ {
+ SwNodes& rNds = pDoc->GetUndoManager().GetUndoNodes();
+ SwNodes& rDocNds = pDoc->GetNodes();
+ SwNodeRange aRg( rDocNds, nSttNode - nNdDiff,
+ rDocNds, nEndNode - nNdDiff );
+ if( !bFullPara && !pEndTxtNd &&
+ &aRg.aEnd.GetNode() != &pDoc->GetNodes().GetEndOfContent() )
+ {
+ SwNode* pNode = aRg.aEnd.GetNode().StartOfSectionNode();
+ if( pNode->GetIndex() >= nSttNode - nNdDiff )
+ aRg.aEnd++; // Deletion of a complete table
+ }
+ SwNode* pTmpNd;
+ // Step 2: Expand selection if necessary
+ if( bJoinNext || bFullPara )
+ {
+ // If all content of a section will be moved into Undo,
+ // the section itself should be moved complete.
+ while( aRg.aEnd.GetIndex() + 2 < rDocNds.Count() &&
+ ( (pTmpNd = rDocNds[ aRg.aEnd.GetIndex()+1 ])->IsEndNode() &&
+ pTmpNd->StartOfSectionNode()->IsSectionNode() &&
+ pTmpNd->StartOfSectionNode()->GetIndex() >= aRg.aStart.GetIndex() ) )
+ aRg.aEnd++;
+ nReplaceDummy = aRg.aEnd.GetIndex() + nNdDiff - nEndNode;
+ if( nReplaceDummy )
+ { // The selection has been expanded, because
+ aRg.aEnd++;
+ if( pEndTxtNd )
+ {
+ // The end text node has to leave the (expanded) selection
+ // The dummy is needed because _MoveNodes deletes empty sections
+ ++nReplaceDummy;
+ SwNodeRange aMvRg( *pEndTxtNd, 0, *pEndTxtNd, 1 );
+ SwPosition aSplitPos( *pEndTxtNd );
+ ::sw::UndoGuard const ug(pDoc->GetIDocumentUndoRedo());
+ pDoc->SplitNode( aSplitPos, false );
+ rDocNds._MoveNodes( aMvRg, rDocNds, aRg.aEnd, sal_True );
+ aRg.aEnd--;
+ }
+ else
+ nReplaceDummy = 0;
+ }
+ }
+ if( bBackSp || bFullPara )
+ {
+ //See above, the selection has to expanded if there are "nearly empty" sections
+ // and a replacement dummy has to be set if needed.
+ while( 1 < aRg.aStart.GetIndex() &&
+ ( (pTmpNd = rDocNds[ aRg.aStart.GetIndex()-1 ])->IsSectionNode() &&
+ pTmpNd->EndOfSectionIndex() < aRg.aEnd.GetIndex() ) )
+ aRg.aStart--;
+ if( pSttTxtNd )
+ {
+ nReplaceDummy = nSttNode - nNdDiff - aRg.aStart.GetIndex();
+ if( nReplaceDummy )
+ {
+ SwNodeRange aMvRg( *pSttTxtNd, 0, *pSttTxtNd, 1 );
+ SwPosition aSplitPos( *pSttTxtNd );
+ ::sw::UndoGuard const ug(pDoc->GetIDocumentUndoRedo());
+ pDoc->SplitNode( aSplitPos, false );
+ rDocNds._MoveNodes( aMvRg, rDocNds, aRg.aStart, sal_True );
+ aRg.aStart--;
+ }
+ }
+ }
+
+ if( bFromTableCopy )
+ {
+ if( !pEndTxtNd )
+ {
+ if( pSttTxtNd )
+ aRg.aStart++;
+ else if( !bFullPara && !aRg.aEnd.GetNode().IsCntntNode() )
+ aRg.aEnd--;
+ }
+ }
+ else if( pSttTxtNd && ( pEndTxtNd || pSttTxtNd->GetTxt().Len() ) )
+ aRg.aStart++;
+
+ // Step 3: Moving into UndoArray...
+ nNode = rNds.GetEndOfContent().GetIndex();
+ rDocNds._MoveNodes( aRg, rNds, SwNodeIndex( rNds.GetEndOfContent() ));
+ pMvStt = new SwNodeIndex( rNds, nNode );
+ nNode = rNds.GetEndOfContent().GetIndex() - nNode; // Differenz merken !
+ if( pSttTxtNd && pEndTxtNd )
+ {
+ //Step 4: Moving around sections
+ nSectDiff = aRg.aEnd.GetIndex() - aRg.aStart.GetIndex();
+ // nSect is the number of sections which starts(ends) between start and end node of the
+ // selection. The "loser" paragraph has to be moved into the section(s) of the
+ // "winner" paragraph
+ if( nSectDiff )
+ {
+ if( bJoinNext )
+ {
+ SwNodeRange aMvRg( *pEndTxtNd, 0, *pEndTxtNd, 1 );
+ rDocNds._MoveNodes( aMvRg, rDocNds, aRg.aStart, sal_True );
+ }
+ else
+ {
+ SwNodeRange aMvRg( *pSttTxtNd, 0, *pSttTxtNd, 1 );
+ rDocNds._MoveNodes( aMvRg, rDocNds, aRg.aEnd, sal_True );
+ }
+ }
+ }
+ if( nSectDiff || nReplaceDummy )
+ lcl_MakeAutoFrms( *pDoc->GetSpzFrmFmts(),
+ bJoinNext ? pEndTxtNd->GetIndex() : pSttTxtNd->GetIndex() );
+ }
+ else
+ nNode = 0; // kein Node verschoben -> keine Differenz zum Ende
+
+ // wurden davor noch Nodes geloescht ?? (FootNotes haben ContentNodes!)
+ if( !pSttTxtNd && !pEndTxtNd )
+ {
+ nNdDiff = nSttNode - rPam.GetPoint()->nNode.GetIndex() - (bFullPara ? 0 : 1);
+ rPam.Move( fnMoveForward, fnGoNode );
+ }
+ else
+ {
+ nNdDiff = nSttNode;
+ if( nSectDiff && bBackSp )
+ nNdDiff += nSectDiff;
+ nNdDiff -= rPam.GetPoint()->nNode.GetIndex();
+ }
+
+ if( !rPam.GetNode()->IsCntntNode() )
+ rPam.GetPoint()->nContent.Assign( 0, 0 );
+
+ // wird die History ueberhaupt benoetigt ??
+ if( pHistory && !pHistory->Count() )
+ DELETEZ( pHistory );
+}
+
+sal_Bool SwUndoDelete::SaveCntnt( const SwPosition* pStt, const SwPosition* pEnd,
+ SwTxtNode* pSttTxtNd, SwTxtNode* pEndTxtNd )
+{
+ sal_uLong nNdIdx = pStt->nNode.GetIndex();
+ // 1 - kopiere den Anfang in den Start-String
+ if( pSttTxtNd )
+ {
+ sal_Bool bOneNode = nSttNode == nEndNode;
+ xub_StrLen nLen = bOneNode ? nEndCntnt - nSttCntnt
+ : pSttTxtNd->GetTxt().Len() - nSttCntnt;
+ SwRegHistory aRHst( *pSttTxtNd, pHistory );
+ // always save all text atttibutes because of possibly overlapping
+ // areas of on/off
+ pHistory->CopyAttr( pSttTxtNd->GetpSwpHints(), nNdIdx,
+ 0, pSttTxtNd->GetTxt().Len(), true );
+ if( !bOneNode && pSttTxtNd->HasSwAttrSet() )
+ pHistory->CopyFmtAttr( *pSttTxtNd->GetpSwAttrSet(), nNdIdx );
+
+ // die Laenge kann sich veraendert haben (!!Felder!!)
+ nLen = ( bOneNode ? pEnd->nContent.GetIndex() : pSttTxtNd->GetTxt().Len() )
+ - pStt->nContent.GetIndex();
+
+
+ // loesche jetzt noch den Text (alle Attribut-Aenderungen kommen in
+ // die Undo-History
+ pSttStr = (String*)new String( pSttTxtNd->GetTxt().Copy( nSttCntnt, nLen ));
+ pSttTxtNd->EraseText( pStt->nContent, nLen );
+ if( pSttTxtNd->GetpSwpHints() )
+ pSttTxtNd->GetpSwpHints()->DeRegister();
+
+ // METADATA: store
+ bool emptied( pSttStr->Len() && !pSttTxtNd->Len() );
+ if (!bOneNode || emptied) // merging may overwrite xmlids...
+ {
+ m_pMetadataUndoStart = (emptied)
+ ? pSttTxtNd->CreateUndoForDelete()
+ : pSttTxtNd->CreateUndo();
+ }
+
+ if( bOneNode )
+ return sal_False; // keine Nodes mehr verschieben
+ }
+
+
+ // 2 - kopiere das Ende in den End-String
+ if( pEndTxtNd )
+ {
+ SwIndex aEndIdx( pEndTxtNd );
+ nNdIdx = pEnd->nNode.GetIndex();
+ SwRegHistory aRHst( *pEndTxtNd, pHistory );
+
+ // always save all text atttibutes because of possibly overlapping
+ // areas of on/off
+ pHistory->CopyAttr( pEndTxtNd->GetpSwpHints(), nNdIdx, 0,
+ pEndTxtNd->GetTxt().Len(), true );
+
+ if( pEndTxtNd->HasSwAttrSet() )
+ pHistory->CopyFmtAttr( *pEndTxtNd->GetpSwAttrSet(), nNdIdx );
+
+
+ // loesche jetzt noch den Text (alle Attribut-Aenderungen kommen in
+ // die Undo-History
+ pEndStr = (String*)new String( pEndTxtNd->GetTxt().Copy( 0,
+ pEnd->nContent.GetIndex() ));
+ pEndTxtNd->EraseText( aEndIdx, pEnd->nContent.GetIndex() );
+ if( pEndTxtNd->GetpSwpHints() )
+ pEndTxtNd->GetpSwpHints()->DeRegister();
+
+ // METADATA: store
+ bool emptied( pEndStr->Len() && !pEndTxtNd->Len() );
+
+ m_pMetadataUndoEnd = (emptied)
+ ? pEndTxtNd->CreateUndoForDelete()
+ : pEndTxtNd->CreateUndo();
+ }
+
+ // sind es nur zwei Nodes, dann ist schon alles erledigt.
+ if( ( pSttTxtNd || pEndTxtNd ) && nSttNode + 1 == nEndNode )
+ return sal_False; // keine Nodes mehr verschieben
+
+ return sal_True; // verschiebe die dazwischen liegenden Nodes
+}
+
+
+sal_Bool SwUndoDelete::CanGrouping( SwDoc* pDoc, const SwPaM& rDelPam )
+{
+ // ist das Undo groesser als 1 Node ? (sprich: Start und EndString)
+ if( pSttStr ? !pSttStr->Len() || pEndStr : sal_True )
+ return sal_False;
+
+ // es kann nur das Loeschen von einzelnen char's zusammengefasst werden
+ if( nSttNode != nEndNode || ( !bGroup && nSttCntnt+1 != nEndCntnt ))
+ return sal_False;
+
+ const SwPosition *pStt = rDelPam.Start(),
+ *pEnd = rDelPam.GetPoint() == pStt
+ ? rDelPam.GetMark()
+ : rDelPam.GetPoint();
+
+ if( pStt->nNode != pEnd->nNode ||
+ pStt->nContent.GetIndex()+1 != pEnd->nContent.GetIndex() ||
+ pEnd->nNode != nSttNode )
+ return sal_False;
+
+ // untercheide zwischen BackSpace und Delete. Es muss dann das
+ // Undo-Array unterschiedlich aufgebaut werden !!
+ if( pEnd->nContent == nSttCntnt )
+ {
+ if( bGroup && !bBackSp ) return sal_False;
+ bBackSp = sal_True;
+ }
+ else if( pStt->nContent == nSttCntnt )
+ {
+ if( bGroup && bBackSp ) return sal_False;
+ bBackSp = sal_False;
+ }
+ else
+ return sal_False;
+
+ // sind die beiden Nodes (Nodes-/Undo-Array) ueberhaupt TextNodes?
+ SwTxtNode * pDelTxtNd = pStt->nNode.GetNode().GetTxtNode();
+ if( !pDelTxtNd ) return sal_False;
+
+ xub_StrLen nUChrPos = bBackSp ? 0 : pSttStr->Len()-1;
+ sal_Unicode cDelChar = pDelTxtNd->GetTxt().GetChar( pStt->nContent.GetIndex() );
+ CharClass& rCC = GetAppCharClass();
+ if( ( CH_TXTATR_BREAKWORD == cDelChar || CH_TXTATR_INWORD == cDelChar ) ||
+ rCC.isLetterNumeric( String( cDelChar ), 0 ) !=
+ rCC.isLetterNumeric( *pSttStr, nUChrPos ) )
+ return sal_False;
+
+ {
+ SwRedlineSaveDatas* pTmpSav = new SwRedlineSaveDatas;
+ if( !FillSaveData( rDelPam, *pTmpSav, sal_False ))
+ delete pTmpSav, pTmpSav = 0;
+
+ sal_Bool bOk = ( !pRedlSaveData && !pTmpSav ) ||
+ ( pRedlSaveData && pTmpSav &&
+ SwUndo::CanRedlineGroup( *pRedlSaveData, *pTmpSav, bBackSp ));
+ delete pTmpSav;
+ if( !bOk )
+ return sal_False;
+
+ pDoc->DeleteRedline( rDelPam, false, USHRT_MAX );
+ }
+
+ // Ok, die beiden 'Deletes' koennen zusammen gefasst werden, also
+ // 'verschiebe' das enstprechende Zeichen
+ if( bBackSp )
+ nSttCntnt--; // BackSpace: Zeichen in Array einfuegen !!
+ else
+ {
+ nEndCntnt++; // Delete: Zeichen am Ende anhaengen
+ nUChrPos++;
+ }
+ pSttStr->Insert( cDelChar, nUChrPos );
+ pDelTxtNd->EraseText( pStt->nContent, 1 );
+
+ bGroup = sal_True;
+ return sal_True;
+}
+
+
+
+SwUndoDelete::~SwUndoDelete()
+{
+ delete pSttStr;
+ delete pEndStr;
+ if( pMvStt ) // loesche noch den Bereich aus dem UndoNodes Array
+ {
+ // Insert speichert den Inhalt in der IconSection
+ pMvStt->GetNode().GetNodes().Delete( *pMvStt, nNode );
+ delete pMvStt;
+ }
+ delete pRedlData;
+ delete pRedlSaveData;
+}
+
+static SwRewriter lcl_RewriterFromHistory(SwHistory & rHistory)
+{
+ SwRewriter aRewriter;
+
+ bool bDone = false;
+
+ for ( sal_uInt16 n = 0; n < rHistory.Count(); n++)
+ {
+ String aDescr = rHistory[n]->GetDescription();
+
+ if (aDescr.Len() > 0)
+ {
+ aRewriter.AddRule(UNDO_ARG2, aDescr);
+
+ bDone = true;
+ break;
+ }
+ }
+
+ if (! bDone)
+ {
+ aRewriter.AddRule(UNDO_ARG2, SW_RES(STR_FIELD));
+ }
+
+ return aRewriter;
+}
+
+SwRewriter SwUndoDelete::GetRewriter() const
+{
+ SwRewriter aResult;
+ String * pStr = NULL;
+
+ if (nNode != 0)
+ {
+ if (sTableName.Len() > 0)
+ {
+
+ SwRewriter aRewriter;
+ aRewriter.AddRule(UNDO_ARG1, SW_RES(STR_START_QUOTE));
+ aRewriter.AddRule(UNDO_ARG2, sTableName);
+ aRewriter.AddRule(UNDO_ARG3, SW_RES(STR_END_QUOTE));
+
+ String sTmp = aRewriter.Apply(SW_RES(STR_TABLE_NAME));
+ aResult.AddRule(UNDO_ARG1, sTmp);
+ }
+ else
+ aResult.AddRule(UNDO_ARG1, String(SW_RES(STR_PARAGRAPHS)));
+ }
+ else
+ {
+ String aStr;
+
+ if (pSttStr != NULL && pEndStr != NULL && pSttStr->Len() == 0 &&
+ pEndStr->Len() == 0)
+ {
+ aStr = SW_RES(STR_PARAGRAPH_UNDO);
+ }
+ else
+ {
+ if (pSttStr != NULL)
+ pStr = pSttStr;
+ else if (pEndStr != NULL)
+ pStr = pEndStr;
+
+ if (pStr != NULL)
+ {
+ aStr = DenoteSpecialCharacters(*pStr);
+ }
+ else
+ {
+ aStr = UNDO_ARG2;
+ }
+ }
+
+ aStr = ShortenString(aStr, nUndoStringLength, String(SW_RES(STR_LDOTS)));
+ if (pHistory)
+ {
+ SwRewriter aRewriter = lcl_RewriterFromHistory(*pHistory);
+ aStr = aRewriter.Apply(aStr);
+ }
+
+ aResult.AddRule(UNDO_ARG1, aStr);
+ }
+
+ return aResult;
+}
+
+// Every object, anchored "AtCntnt" will be reanchored at rPos
+void lcl_ReAnchorAtCntntFlyFrames( const SwSpzFrmFmts& rSpzArr, SwPosition &rPos, sal_uLong nOldIdx )
+{
+ if( rSpzArr.Count() )
+ {
+ SwFlyFrmFmt* pFmt;
+ const SwFmtAnchor* pAnchor;
+ const SwPosition* pAPos;
+ for( sal_uInt16 n = 0; n < rSpzArr.Count(); ++n )
+ {
+ pFmt = (SwFlyFrmFmt*)rSpzArr[n];
+ pAnchor = &pFmt->GetAnchor();
+ if (pAnchor->GetAnchorId() == FLY_AT_PARA)
+ {
+ pAPos = pAnchor->GetCntntAnchor();
+ if( pAPos && nOldIdx == pAPos->nNode.GetIndex() )
+ {
+ SwFmtAnchor aAnch( *pAnchor );
+ aAnch.SetAnchor( &rPos );
+ pFmt->SetFmtAttr( aAnch );
+ }
+ }
+ }
+ }
+}
+
+void SwUndoDelete::UndoImpl(::sw::UndoRedoContext & rContext)
+{
+ SwDoc *const pDoc = & rContext.GetDoc();
+
+ sal_uLong nCalcStt = nSttNode - nNdDiff;
+
+ if( nSectDiff && bBackSp )
+ nCalcStt += nSectDiff;
+
+ SwNodeIndex aIdx( pDoc->GetNodes(), nCalcStt );
+ SwNode* pInsNd = &aIdx.GetNode();
+
+ { // Block, damit der SwPosition beim loeschen vom Node
+ // abgemeldet ist
+ SwPosition aPos( aIdx );
+ if( !bDelFullPara )
+ {
+ if( pInsNd->IsTableNode() )
+ {
+ pInsNd = pDoc->GetNodes().MakeTxtNode( aIdx,
+ (SwTxtFmtColl*)pDoc->GetDfltTxtFmtColl() );
+ aIdx--;
+ aPos.nNode = aIdx;
+ aPos.nContent.Assign( pInsNd->GetCntntNode(), nSttCntnt );
+ }
+ else
+ {
+ if( pInsNd->IsCntntNode() )
+ aPos.nContent.Assign( (SwCntntNode*)pInsNd, nSttCntnt );
+ if( !bTblDelLastNd )
+ pInsNd = 0; // Node nicht loeschen !!
+ }
+ }
+ else
+ pInsNd = 0; // Node nicht loeschen !!
+
+ sal_Bool bNodeMove = 0 != nNode;
+
+ if( pEndStr )
+ {
+ // alle Attribute verwerfen, wurden alle gespeichert!
+ SwTxtNode* pTxtNd = aPos.nNode.GetNode().GetTxtNode();
+
+ if( pTxtNd && pTxtNd->HasSwAttrSet() )
+ pTxtNd->ResetAllAttr();
+
+ if( pTxtNd && pTxtNd->GetpSwpHints() )
+ pTxtNd->ClearSwpHintsArr( true );
+
+ if( pSttStr && !bFromTableCopy )
+ {
+ sal_uLong nOldIdx = aPos.nNode.GetIndex();
+ pDoc->SplitNode( aPos, false );
+ // After the split all objects are anchored at the first paragraph,
+ // but the pHistory of the fly frame formats relies on anchoring at
+ // the start of the selection => selection backwards needs a correction.
+ if( bBackSp )
+ lcl_ReAnchorAtCntntFlyFrames( *pDoc->GetSpzFrmFmts(), aPos, nOldIdx );
+ pTxtNd = aPos.nNode.GetNode().GetTxtNode();
+ }
+ if( pTxtNd )
+ {
+ pTxtNd->InsertText( *pEndStr, aPos.nContent,
+ IDocumentContentOperations::INS_NOHINTEXPAND );
+ // METADATA: restore
+ pTxtNd->RestoreMetadata(m_pMetadataUndoEnd);
+ }
+ }
+ else if( pSttStr && bNodeMove )
+ {
+ SwTxtNode * pNd = aPos.nNode.GetNode().GetTxtNode();
+ if( pNd )
+ {
+ if( nSttCntnt < pNd->GetTxt().Len() )
+ {
+ sal_uLong nOldIdx = aPos.nNode.GetIndex();
+ pDoc->SplitNode( aPos, false );
+ if( bBackSp )
+ lcl_ReAnchorAtCntntFlyFrames( *pDoc->GetSpzFrmFmts(), aPos, nOldIdx );
+ }
+ else
+ aPos.nNode++;
+ }
+ }
+ SwNode* pMovedNode = NULL;
+ if( nSectDiff )
+ {
+ sal_uLong nMoveIndex = aPos.nNode.GetIndex();
+ int nDiff = 0;
+ if( bJoinNext )
+ {
+ nMoveIndex += nSectDiff + 1;
+ pMovedNode = &aPos.nNode.GetNode();
+ }
+ else
+ {
+ nMoveIndex -= nSectDiff + 1;
+ ++nDiff;
+ }
+ SwNodeIndex aMvIdx( pDoc->GetNodes(), nMoveIndex );
+ SwNodeRange aRg( aPos.nNode, 0 - nDiff, aPos.nNode, 1 - nDiff );
+ aPos.nNode--;
+ if( !bJoinNext )
+ pMovedNode = &aPos.nNode.GetNode();
+ pDoc->GetNodes()._MoveNodes( aRg, pDoc->GetNodes(), aMvIdx, sal_True );
+ aPos.nNode++;
+ }
+
+ if( bNodeMove )
+ {
+ SwNodeRange aRange( *pMvStt, 0, *pMvStt, nNode );
+ SwNodeIndex aCopyIndex( aPos.nNode, -1 );
+ pDoc->GetUndoManager().GetUndoNodes()._Copy( aRange, aPos.nNode );
+
+ if( nReplaceDummy )
+ {
+ sal_uLong nMoveIndex;
+ if( bJoinNext )
+ {
+ nMoveIndex = nEndNode - nNdDiff;
+ aPos.nNode = nMoveIndex + nReplaceDummy;
+ }
+ else
+ {
+ aPos = SwPosition( aCopyIndex );
+ nMoveIndex = aPos.nNode.GetIndex() + nReplaceDummy + 1;
+ }
+ SwNodeIndex aMvIdx( pDoc->GetNodes(), nMoveIndex );
+ SwNodeRange aRg( aPos.nNode, 0, aPos.nNode, 1 );
+ pMovedNode = &aPos.nNode.GetNode();
+ pDoc->GetNodes()._MoveNodes( aRg, pDoc->GetNodes(), aMvIdx, sal_True );
+ pDoc->GetNodes().Delete( aMvIdx, 1 );
+ }
+ }
+
+ if( pMovedNode )
+ lcl_MakeAutoFrms( *pDoc->GetSpzFrmFmts(), pMovedNode->GetIndex() );
+
+ if( pSttStr )
+ {
+ aPos.nNode = nSttNode - nNdDiff + ( bJoinNext ? 0 : nReplaceDummy );
+ SwTxtNode * pTxtNd = aPos.nNode.GetNode().GetTxtNode();
+ // wenn mehr als ein Node geloescht wurde, dann wurden auch
+ // alle "Node"-Attribute gespeichert
+
+ if (pTxtNd != NULL)
+ {
+ if( pTxtNd->HasSwAttrSet() && bNodeMove && !pEndStr )
+ pTxtNd->ResetAllAttr();
+
+ if( pTxtNd->GetpSwpHints() )
+ pTxtNd->ClearSwpHintsArr( true );
+
+ // SectionNode-Modus und von oben nach unten selektiert:
+ // -> im StartNode steht noch der Rest vom Join => loeschen
+ aPos.nContent.Assign( pTxtNd, nSttCntnt );
+ pTxtNd->InsertText( *pSttStr, aPos.nContent,
+ IDocumentContentOperations::INS_NOHINTEXPAND );
+ // METADATA: restore
+ pTxtNd->RestoreMetadata(m_pMetadataUndoStart);
+ }
+ }
+
+ if( pHistory )
+ {
+ pHistory->TmpRollback( pDoc, nSetPos, false );
+ if( nSetPos ) // es gab Fussnoten/FlyFrames
+ {
+ // gibts ausser diesen noch andere ?
+ if( nSetPos < pHistory->Count() )
+ {
+ // dann sicher die Attribute anderen Attribute
+ SwHistory aHstr;
+ aHstr.Move( 0, pHistory, nSetPos );
+ pHistory->Rollback( pDoc );
+ pHistory->Move( 0, &aHstr );
+ }
+ else
+ {
+ pHistory->Rollback( pDoc );
+ DELETEZ( pHistory );
+ }
+ }
+ }
+
+ if( bResetPgDesc || bResetPgBrk )
+ {
+ sal_uInt16 nStt = static_cast<sal_uInt16>( bResetPgDesc ? RES_PAGEDESC : RES_BREAK );
+ sal_uInt16 nEnd = static_cast<sal_uInt16>( bResetPgBrk ? RES_BREAK : RES_PAGEDESC );
+
+ SwNode* pNode = pDoc->GetNodes()[ nEndNode + 1 ];
+ if( pNode->IsCntntNode() )
+ ((SwCntntNode*)pNode)->ResetAttr( nStt, nEnd );
+ else if( pNode->IsTableNode() )
+ ((SwTableNode*)pNode)->GetTable().GetFrmFmt()->ResetFmtAttr( nStt, nEnd );
+ }
+ }
+ // den temp. eingefuegten Node noch loeschen !!
+ if( pInsNd )
+ pDoc->GetNodes().Delete( aIdx, 1 );
+ if( pRedlSaveData )
+ SetSaveData( *pDoc, *pRedlSaveData );
+
+ AddUndoRedoPaM(rContext, true);
+}
+
+void SwUndoDelete::RedoImpl(::sw::UndoRedoContext & rContext)
+{
+ SwPaM & rPam = AddUndoRedoPaM(rContext);
+ SwDoc& rDoc = *rPam.GetDoc();
+
+ if( pRedlSaveData )
+ {
+ bool bSuccess = FillSaveData(rPam, *pRedlSaveData, sal_True);
+ OSL_ENSURE(bSuccess,
+ "SwUndoDelete::Redo: used to have redline data, but now none?");
+ if (!bSuccess)
+ {
+ delete pRedlSaveData, pRedlSaveData = 0;
+ }
+ }
+
+ if( !bDelFullPara )
+ {
+ SwUndRng aTmpRng( rPam );
+ RemoveIdxFromRange( rPam, sal_False );
+ aTmpRng.SetPaM( rPam );
+
+ if( !bJoinNext ) // Dann Selektion von unten nach oben
+ rPam.Exchange(); // wieder herstellen!
+ }
+
+ if( pHistory ) // wurden Attribute gesichert ?
+ {
+ pHistory->SetTmpEnd( pHistory->Count() );
+ SwHistory aHstr;
+ aHstr.Move( 0, pHistory );
+
+ if( bDelFullPara )
+ {
+ OSL_ENSURE( rPam.HasMark(), "PaM ohne Mark" );
+ DelCntntIndex( *rPam.GetMark(), *rPam.GetPoint(),
+ DelCntntType(nsDelCntntType::DELCNT_ALL | nsDelCntntType::DELCNT_CHKNOCNTNT) );
+
+ _DelBookmarks(rPam.GetMark()->nNode, rPam.GetPoint()->nNode);
+ }
+ else
+ DelCntntIndex( *rPam.GetMark(), *rPam.GetPoint() );
+ nSetPos = pHistory ? pHistory->Count() : 0;
+
+ pHistory->Move( nSetPos, &aHstr );
+ }
+ else
+ {
+ if( bDelFullPara )
+ {
+ OSL_ENSURE( rPam.HasMark(), "PaM ohne Mark" );
+ DelCntntIndex( *rPam.GetMark(), *rPam.GetPoint(),
+ DelCntntType(nsDelCntntType::DELCNT_ALL | nsDelCntntType::DELCNT_CHKNOCNTNT) );
+
+ _DelBookmarks( rPam.GetMark()->nNode, rPam.GetPoint()->nNode );
+ }
+ else
+ DelCntntIndex( *rPam.GetMark(), *rPam.GetPoint() );
+ nSetPos = pHistory ? pHistory->Count() : 0;
+ }
+
+ if( !pSttStr && !pEndStr )
+ {
+ SwNodeIndex aSttIdx = ( bDelFullPara || bJoinNext )
+ ? rPam.GetMark()->nNode
+ : rPam.GetPoint()->nNode;
+ SwTableNode* pTblNd = aSttIdx.GetNode().GetTableNode();
+ if( pTblNd )
+ {
+ if( bTblDelLastNd )
+ {
+ // dann am Ende wieder einen Node einfuegen
+ const SwNodeIndex aTmpIdx( *pTblNd->EndOfSectionNode(), 1 );
+ rDoc.GetNodes().MakeTxtNode( aTmpIdx,
+ rDoc.GetTxtCollFromPool( RES_POOLCOLL_STANDARD ) );
+ }
+
+ SwCntntNode* pNextNd = rDoc.GetNodes()[
+ pTblNd->EndOfSectionIndex()+1 ]->GetCntntNode();
+ if( pNextNd )
+ {
+ SwFrmFmt* pTableFmt = pTblNd->GetTable().GetFrmFmt();
+
+ const SfxPoolItem *pItem;
+ if( SFX_ITEM_SET == pTableFmt->GetItemState( RES_PAGEDESC,
+ sal_False, &pItem ) )
+ pNextNd->SetAttr( *pItem );
+
+ if( SFX_ITEM_SET == pTableFmt->GetItemState( RES_BREAK,
+ sal_False, &pItem ) )
+ pNextNd->SetAttr( *pItem );
+ }
+ pTblNd->DelFrms();
+ }
+
+ rPam.SetMark();
+ rPam.DeleteMark();
+
+ rDoc.GetNodes().Delete( aSttIdx, nEndNode - nSttNode );
+
+ // setze den Cursor immer in einen ContentNode !!
+ if( !rPam.Move( fnMoveBackward, fnGoCntnt ) &&
+ !rPam.Move( fnMoveForward, fnGoCntnt ) )
+ rPam.GetPoint()->nContent.Assign( rPam.GetCntntNode(), 0 );
+ }
+ else if( bDelFullPara )
+ {
+ // der Pam wurde am Point( == Ende) um eins erhoeht, um einen
+ // Bereich fuers Undo zu haben. Der muss jetzt aber wieder entfernt
+ // werden!!!
+ rPam.End()->nNode--;
+ if( rPam.GetPoint()->nNode == rPam.GetMark()->nNode )
+ *rPam.GetMark() = *rPam.GetPoint();
+ rDoc.DelFullPara( rPam );
+ }
+ else
+ rDoc.DeleteAndJoin( rPam );
+}
+
+void SwUndoDelete::RepeatImpl(::sw::RepeatContext & rContext)
+{
+ // this action does not seem idempotent,
+ // so make sure it is only executed once on repeat
+ if (rContext.m_bDeleteRepeated)
+ return;
+
+ SwPaM & rPam = rContext.GetRepeatPaM();
+ SwDoc& rDoc = *rPam.GetDoc();
+ ::sw::GroupUndoGuard const undoGuard(rDoc.GetIDocumentUndoRedo());
+ if( !rPam.HasMark() )
+ {
+ rPam.SetMark();
+ rPam.Move( fnMoveForward, fnGoCntnt );
+ }
+ if( bDelFullPara )
+ rDoc.DelFullPara( rPam );
+ else
+ rDoc.DeleteAndJoin( rPam );
+ rContext.m_bDeleteRepeated = true;
+}
+
+
+void SwUndoDelete::SetTableName(const String & rName)
+{
+ sTableName = rName;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/undo/undo.hrc b/sw/source/core/undo/undo.hrc
new file mode 100644
index 000000000000..8edccd344adf
--- /dev/null
+++ b/sw/source/core/undo/undo.hrc
@@ -0,0 +1,185 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#include <rcid.hrc>
+// Undo
+#define UNDO_BASE (RC_WRTSH_BEGIN + 8)
+#define STR_CANT_UNDO (UNDO_BASE + 0)
+
+// im enun folgen hier START & END fuer die Klammerungen,
+
+// Id's fuer die Undo/Redo/Repeat faehigen "Funktionen"
+#define STR_DELETE_UNDO (UNDO_BASE + 3)
+#define STR_INSERT_UNDO (UNDO_BASE + 4)
+#define STR_OVR_UNDO (UNDO_BASE + 5)
+#define STR_SPLITNODE_UNDO (UNDO_BASE + 6)
+#define STR_INSATTR_UNDO (UNDO_BASE + 7)
+#define STR_SETFMTCOLL_UNDO (UNDO_BASE + 8)
+#define STR_RESET_ATTR_UNDO (UNDO_BASE + 9)
+#define STR_INSFMT_ATTR_UNDO (UNDO_BASE +10)
+#define STR_INSERT_DOC_UNDO (UNDO_BASE +11)
+#define STR_COPY_UNDO (UNDO_BASE +12)
+#define STR_INSTABLE_UNDO (UNDO_BASE +13)
+#define STR_TABLETOTEXT_UNDO (UNDO_BASE +14)
+#define STR_TEXTTOTABLE_UNDO (UNDO_BASE +15)
+#define STR_SORT_TXT (UNDO_BASE +16)
+#define STR_INSERTFLY (UNDO_BASE +17)
+#define STR_TABLEHEADLINE (UNDO_BASE +18)
+#define STR_INSERTSECTION (UNDO_BASE +19)
+#define STR_OUTLINE_LR (UNDO_BASE +20)
+#define STR_OUTLINE_UD (UNDO_BASE +21)
+#define STR_INSNUM (UNDO_BASE +22)
+#define STR_NUMUP (UNDO_BASE +23)
+#define STR_MOVENUM (UNDO_BASE +24)
+#define STR_INSERTDRAW (UNDO_BASE +25)
+#define STR_NUMORNONUM (UNDO_BASE +26)
+#define STR_INC_LEFTMARGIN (UNDO_BASE +27)
+#define STR_DEC_LEFTMARGIN (UNDO_BASE +28)
+#define STR_INSERTLABEL (UNDO_BASE +29)
+#define STR_SETNUMRULESTART (UNDO_BASE +30)
+#define STR_CHANGEFTN (UNDO_BASE +31)
+#define STR_REDLINE (UNDO_BASE +32)
+#define STR_ACCEPT_REDLINE (UNDO_BASE +33)
+#define STR_REJECT_REDLINE (UNDO_BASE +34)
+#define STR_SPLIT_TABLE (UNDO_BASE +35)
+#define STR_DONTEXPAND (UNDO_BASE +36)
+#define STR_AUTOCORRECT (UNDO_BASE +37)
+#define STR_MERGE_TABLE (UNDO_BASE +38)
+#define STR_TRANSLITERATE (UNDO_BASE +39)
+#define STR_PASTE_CLIPBOARD_UNDO (UNDO_BASE +40)
+#define STR_TYPING_UNDO (UNDO_BASE +41)
+
+#define STR_REPEAT_DUMMY_6 (UNDO_BASE +42)
+#define STR_REPEAT_DUMMY_7 (UNDO_BASE +43)
+#define STR_REPEAT_DUMMY_8 (UNDO_BASE +44)
+#define STR_REPEAT_DUMMY_9 (UNDO_BASE +45)
+// !!!!!! umsetzen !!!!!!!!!!! umsetzen !!!!!!!!!!! umsetzen !!!!
+#define CORE_REPEAT_END STR_REPEAT_DUMMY_9// !!!! umsetzen !!!
+
+
+// Id's nur fuer die Undo/Redo faehigen "Funktionen"
+#define STR_MOVE_UNDO (CORE_REPEAT_END + 1)
+#define STR_INSERT_GLOSSARY (CORE_REPEAT_END + 2)
+#define STR_DELBOOKMARK (CORE_REPEAT_END + 3)
+#define STR_INSBOOKMARK (CORE_REPEAT_END + 4)
+#define STR_SORT_TBL (CORE_REPEAT_END + 5)
+#define STR_DELETEFLY (CORE_REPEAT_END + 6)
+#define STR_AUTOFORMAT (CORE_REPEAT_END + 7)
+#define STR_REPLACE (CORE_REPEAT_END + 8)
+#define STR_DELETESECTION (CORE_REPEAT_END + 9)
+#define STR_CHANGESECTION (CORE_REPEAT_END +10)
+#define STR_CHANGESECTPASSWD (CORE_REPEAT_END +11)
+#define STR_CHANGEDEFATTR (CORE_REPEAT_END +12)
+#define STR_DELNUM (CORE_REPEAT_END +13)
+#define STR_DRAWUNDO (CORE_REPEAT_END +14)
+#define STR_DRAWGROUP (CORE_REPEAT_END +15)
+#define STR_DRAWUNGROUP (CORE_REPEAT_END +16)
+#define STR_DRAWDELETE (CORE_REPEAT_END +17)
+#define STR_REREAD (CORE_REPEAT_END +18)
+#define STR_DELGRF (CORE_REPEAT_END +19)
+#define STR_DELOLE (CORE_REPEAT_END +20)
+#define STR_TABLE_ATTR (CORE_REPEAT_END +21)
+#define STR_TABLE_AUTOFMT (CORE_REPEAT_END +22)
+#define STR_TABLE_INSCOL (CORE_REPEAT_END +23)
+#define STR_TABLE_INSROW (CORE_REPEAT_END +24)
+#define STR_TABLE_DELBOX (CORE_REPEAT_END +25)
+#define STR_TABLE_SPLIT (CORE_REPEAT_END +26)
+#define STR_TABLE_MERGE (CORE_REPEAT_END +27)
+#define STR_TABLE_NUMFORMAT (CORE_REPEAT_END +28)
+#define STR_INSERT_TOX (CORE_REPEAT_END +29)
+#define STR_CLEAR_TOX_RANGE (CORE_REPEAT_END +30)
+#define STR_TABLE_TBLCPYTBL (CORE_REPEAT_END +31)
+#define STR_TABLE_CPYTBL (CORE_REPEAT_END +32)
+#define STR_INS_FROM_SHADOWCRSR (CORE_REPEAT_END +33)
+#define STR_UNDO_CHAIN (CORE_REPEAT_END +34)
+#define STR_UNDO_UNCHAIN (CORE_REPEAT_END +35)
+#define STR_UNDO_FTNINFO (CORE_REPEAT_END +36)
+#define STR_UNDO_ENDNOTEINFO (CORE_REPEAT_END +37)
+#define STR_UNDO_COMPAREDOC (CORE_REPEAT_END +38)
+#define STR_UNDO_SETFLYFRMFMT (CORE_REPEAT_END +39)
+#define STR_UNDO_SETRUBYATTR (CORE_REPEAT_END +40)
+// #102505#
+#define STR_UNDO_TMPAUTOCORR (CORE_REPEAT_END +41)
+
+#define STR_TOXCHANGE (CORE_REPEAT_END +42)
+#define STR_UNDO_PAGEDESC_CREATE (CORE_REPEAT_END +43)
+#define STR_UNDO_PAGEDESC (CORE_REPEAT_END +44)
+#define STR_UNDO_PAGEDESC_DELETE (CORE_REPEAT_END +45)
+#define STR_UNDO_HEADER_FOOTER (CORE_REPEAT_END +46) // #i7983#
+#define STR_UNDO_FIELD (CORE_REPEAT_END +47) // #111840#
+#define STR_UNDO_TXTFMTCOL_CREATE (CORE_REPEAT_END +48)
+#define STR_UNDO_TXTFMTCOL_DELETE (CORE_REPEAT_END +49)
+#define STR_UNDO_TXTFMTCOL_RENAME (CORE_REPEAT_END +50)
+#define STR_UNDO_CHARFMT_CREATE (CORE_REPEAT_END +51)
+#define STR_UNDO_CHARFMT_DELETE (CORE_REPEAT_END +52)
+#define STR_UNDO_CHARFMT_RENAME (CORE_REPEAT_END +53)
+#define STR_UNDO_FRMFMT_CREATE (CORE_REPEAT_END +54)
+#define STR_UNDO_FRMFMT_DELETE (CORE_REPEAT_END +55)
+#define STR_UNDO_FRMFMT_RENAME (CORE_REPEAT_END +56)
+#define STR_UNDO_NUMRULE_CREATE (CORE_REPEAT_END +57)
+#define STR_UNDO_NUMRULE_DELETE (CORE_REPEAT_END +58)
+#define STR_UNDO_NUMRULE_RENAME (CORE_REPEAT_END +59)
+#define STR_UNDO_BOOKMARK_RENAME (CORE_REPEAT_END +60)
+#define STR_UNDO_INDEX_ENTRY_INSERT (CORE_REPEAT_END +61)
+#define STR_UNDO_INDEX_ENTRY_DELETE (CORE_REPEAT_END +62)
+#define STR_UNDO_COL_DELETE (CORE_REPEAT_END +63)
+#define STR_UNDO_ROW_DELETE (CORE_REPEAT_END +64)
+#define STR_UNDO_PAGEDESC_RENAME (CORE_REPEAT_END +65)
+#define STR_NUMDOWN (CORE_REPEAT_END +66)
+#define STR_UNDO_FLYFRMFMT_TITLE (CORE_REPEAT_END +67)
+#define STR_UNDO_FLYFRMFMT_DESCRITPTION (CORE_REPEAT_END +68)
+
+// !!!!!! umsetzen !!!!!!!!!!! umsetzen !!!!!!!!!!! umsetzen !!!!
+#define CORE_UNDO_END STR_UNDO_FLYFRMFMT_DESCRITPTION// !!!! umsetzen !!!
+
+// UI-Undo Klammerungen
+#define UI_UNDO_BEGIN (CORE_UNDO_END + 1)
+#define STR_REPLACE_UNDO (UI_UNDO_BEGIN)
+#define STR_INSERT_PAGE_BREAK_UNDO (UI_UNDO_BEGIN + 1)
+#define STR_INSERT_COLUMN_BREAK_UNDO (UI_UNDO_BEGIN + 2)
+#define STR_PLAY_MACRO_UNDO (UI_UNDO_BEGIN + 3)
+#define STR_INSERT_ENV_UNDO (UI_UNDO_BEGIN + 4)
+#define STR_DRAG_AND_COPY (UI_UNDO_BEGIN + 5)
+#define STR_DRAG_AND_MOVE (UI_UNDO_BEGIN + 6)
+#define STR_INSERT_RULER (UI_UNDO_BEGIN + 7)
+#define STR_INSERT_CHART (UI_UNDO_BEGIN + 8)
+#define STR_INSERT_FOOTNOTE (UI_UNDO_BEGIN + 9)
+#define STR_INSERT_URLBTN (UI_UNDO_BEGIN + 10)
+#define STR_INSERT_URLTXT (UI_UNDO_BEGIN + 11)
+#define STR_DELETE_INVISIBLECNTNT (UI_UNDO_BEGIN + 12)
+#define STR_REPLACE_STYLE (UI_UNDO_BEGIN + 13)
+#define UI_UNDO_END STR_REPLACE_STYLE
+
+#define UNDO_MORE_STRINGS_BEGIN (UI_UNDO_END + 1)
+#define STR_OCCURRENCES_OF (UNDO_MORE_STRINGS_BEGIN)
+#define STR_UNDO_TABS (UNDO_MORE_STRINGS_BEGIN + 1)
+#define STR_UNDO_NLS (UNDO_MORE_STRINGS_BEGIN + 2)
+#define STR_UNDO_PAGEBREAKS (UNDO_MORE_STRINGS_BEGIN + 3)
+#define STR_UNDO_COLBRKS (UNDO_MORE_STRINGS_BEGIN + 4)
+#define STR_UNDO_SPECIALCHAR (UNDO_MORE_STRINGS_BEGIN + 5)
+
+#define UNDO_ACT_END STR_UNDO_TABLE_NAME
diff --git a/sw/source/core/undo/undo.src b/sw/source/core/undo/undo.src
new file mode 100644
index 000000000000..c394da3e8e87
--- /dev/null
+++ b/sw/source/core/undo/undo.src
@@ -0,0 +1,657 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#include <comcore.hrc>
+#include <undo.hrc>
+
+ // Undo
+String STR_CANT_UNDO
+{
+ Text [ en-US ] = "not possible" ;
+};
+String STR_DELETE_UNDO
+{
+ Text [ en-US ] = "Delete $1" ;
+};
+String STR_INSERT_UNDO
+{
+ Text [ en-US ] = "Insert $1" ;
+};
+String STR_OVR_UNDO
+{
+ Text [ en-US ] = "Overwrite: $1" ;
+};
+String STR_SPLITNODE_UNDO
+{
+ Text [ en-US ] = "New Paragraph" ;
+};
+String STR_MOVE_UNDO
+{
+ Text [ en-US ] = "Move" ;
+};
+String STR_INSATTR_UNDO
+{
+ Text [ en-US ] = "Apply attributes" ;
+};
+String STR_SETFMTCOLL_UNDO
+{
+ Text [ en-US ] = "Apply Styles: $1" ;
+};
+String STR_RESET_ATTR_UNDO
+{
+ Text [ en-US ] = "Reset attributes" ;
+};
+String STR_INSFMT_ATTR_UNDO
+{
+ Text [ en-US ] = "Change style: $1" ;
+};
+String STR_INSERT_DOC_UNDO
+{
+ Text [ en-US ] = "Insert file" ;
+};
+String STR_INSERT_GLOSSARY
+{
+ Text [ en-US ] = "Insert AutoText" ;
+};
+String STR_DELBOOKMARK
+{
+ Text [ en-US ] = "Delete bookmark: $1" ;
+};
+String STR_INSBOOKMARK
+{
+ Text [ en-US ] = "Insert bookmark: $1" ;
+};
+String STR_SORT_TBL
+{
+ Text [ en-US ] = "Sort table" ;
+};
+String STR_SORT_TXT
+{
+ Text [ en-US ] = "Sort text" ;
+};
+String STR_INSTABLE_UNDO
+{
+ Text [ en-US ] = "Insert table: $1$2$3" ;
+};
+String STR_TEXTTOTABLE_UNDO
+{
+ Text [ en-US ] = "Convert text -> table" ;
+};
+String STR_TABLETOTEXT_UNDO
+{
+ Text [ en-US ] = "Convert table -> text" ;
+};
+String STR_COPY_UNDO
+{
+ Text [ en-US ] = "Copy: $1" ;
+};
+String STR_REPLACE_UNDO
+{
+ Text [ en-US ] = "Replace $1 $2 $3" ;
+};
+String STR_INSERT_PAGE_BREAK_UNDO
+{
+ Text [ en-US ] = "Insert page break" ;
+};
+String STR_INSERT_COLUMN_BREAK_UNDO
+{
+ Text [ en-US ] = "Insert column break" ;
+};
+String STR_PLAY_MACRO_UNDO
+{
+ Text [ en-US ] = "Run macro" ;
+};
+String STR_INSERT_ENV_UNDO
+{
+ Text [ en-US ] = "Insert Envelope" ;
+};
+String STR_DRAG_AND_COPY
+{
+ Text [ en-US ] = "Copy: $1" ;
+};
+String STR_DRAG_AND_MOVE
+{
+ Text [ en-US ] = "Move: $1" ;
+};
+String STR_INSERT_RULER
+{
+ Text [ en-US ] = "Insert horizontal ruler" ;
+};
+String STR_INSERT_CHART
+{
+ Text [ en-US ] = "Insert %PRODUCTNAME Chart" ;
+};
+String STR_INSERTFLY
+{
+ Text [ en-US ] = "Insert frame" ;
+};
+String STR_DELETEFLY
+{
+ Text [ en-US ] = "Delete frame" ;
+};
+String STR_AUTOFORMAT
+{
+ Text [ en-US ] = "AutoFormat" ;
+};
+String STR_TABLEHEADLINE
+{
+ Text [ en-US ] = "Table heading" ;
+};
+String STR_REPLACE
+{
+ Text [ en-US ] = "Replace: $1 $2 $3" ;
+};
+String STR_INSERTSECTION
+{
+ Text [ en-US ] = "Insert section" ;
+};
+String STR_DELETESECTION
+{
+ Text [ en-US ] = "Delete section" ;
+};
+String STR_CHANGESECTION
+{
+ Text [ en-US ] = "Modify section" ;
+};
+String STR_CHANGESECTPASSWD
+{
+ Text [ en-US ] = "Change password protection" ;
+};
+String STR_CHANGEDEFATTR
+{
+ Text [ en-US ] = "Modify default values" ;
+};
+String STR_REPLACE_STYLE
+{
+ Text [ en-US ] = "Replace style: $1 $2 $3" ;
+};
+String STR_OUTLINE_LR
+{
+ Text [ en-US ] = "Promote/demote outline" ;
+};
+String STR_OUTLINE_UD
+{
+ Text [ en-US ] = "Move outline" ;
+};
+String STR_INSNUM
+{
+ Text [ en-US ] = "Insert numbering" ;
+};
+String STR_NUMUP
+{
+ Text [ en-US ] = "Promote level" ;
+};
+String STR_NUMDOWN
+{
+ Text [ en-US ] = "Demote level" ;
+};
+String STR_MOVENUM
+{
+ Text [ en-US ] = "Move paragraphs" ;
+};
+String STR_INSERTDRAW
+{
+ Text [ en-US ] = "Insert drawing object: $1" ;
+};
+String STR_NUMORNONUM
+{
+ Text [ en-US ] = "Number On/Off" ;
+};
+String STR_INC_LEFTMARGIN
+{
+ Text [ en-US ] = "Increase Indent" ;
+};
+String STR_DEC_LEFTMARGIN
+{
+ Text [ en-US ] = "Decrease indent" ;
+};
+String STR_INSERTLABEL
+{
+ Text [ en-US ] = "Insert caption: $1" ;
+};
+String STR_SETNUMRULESTART
+{
+ Text [ en-US ] = "Restart numbering" ;
+};
+String STR_CHANGEFTN
+{
+ Text [ en-US ] = "Modify footnote" ;
+};
+String STR_REDLINE
+{
+ /* !! sollte NIE gebraucht/uebersetzt werden !! */
+};
+String STR_ACCEPT_REDLINE
+{
+ Text [ en-US ] = "Accept change: $1" ;
+};
+String STR_REJECT_REDLINE
+{
+ Text [ en-US ] = "Reject change: $1" ;
+};
+String STR_SPLIT_TABLE
+{
+ Text [ en-US ] = "Split Table" ;
+};
+String STR_DONTEXPAND
+{
+ Text [ en-US ] = "Stop attribute" ;
+};
+String STR_AUTOCORRECT
+{
+ Text [ en-US ] = "AutoCorrect" ;
+};
+String STR_MERGE_TABLE
+{
+ Text [ en-US ] = "Merge table";
+};
+
+String STR_TRANSLITERATE
+{
+ Text [ en-US ] = "Case/Characters";
+};
+
+String STR_DELNUM
+{
+ Text [ en-US ] = "Delete numbering" ;
+};
+String STR_DRAWUNDO
+{
+ Text [ en-US ] = "Drawing objects: $1" ;
+};
+String STR_DRAWGROUP
+{
+ Text [ en-US ] = "Group draw objects" ;
+};
+String STR_DRAWUNGROUP
+{
+ Text [ en-US ] = "Ungroup drawing objects" ;
+};
+String STR_DRAWDELETE
+{
+ Text [ en-US ] = "Delete drawing objects" ;
+};
+String STR_REREAD
+{
+ Text [ en-US ] = "Replace graphics" ;
+};
+String STR_DELGRF
+{
+ Text [ en-US ] = "Delete graphics" ;
+};
+String STR_DELOLE
+{
+ Text [ en-US ] = "Delete object" ;
+};
+String STR_TABLE_ATTR
+{
+ Text [ en-US ] = "Apply table attributes" ;
+};
+String STR_TABLE_AUTOFMT
+{
+ Text [ en-US ] = "AutoFormat Table" ;
+};
+String STR_TABLE_INSCOL
+{
+ Text [ en-US ] = "Insert Column" ;
+};
+String STR_TABLE_INSROW
+{
+ Text [ en-US ] = "Insert Row" ;
+};
+String STR_TABLE_DELBOX
+{
+ Text [ en-US ] = "Delete row/column" ;
+};
+String STR_UNDO_COL_DELETE
+{
+ Text [ en-US ] = "Delete column" ;
+};
+String STR_UNDO_ROW_DELETE
+{
+ Text [ en-US ] = "Delete row" ;
+};
+String STR_TABLE_SPLIT
+{
+ Text [ en-US ] = "Split Cells" ;
+};
+String STR_TABLE_MERGE
+{
+ Text [ en-US ] = "Merge Cells" ;
+};
+String STR_TABLE_NUMFORMAT
+{
+ Text [ en-US ] = "Format cell" ;
+};
+String STR_INSERT_TOX
+{
+ Text [ en-US ] = "Insert index/table" ;
+};
+String STR_CLEAR_TOX_RANGE
+{
+ Text [ en-US ] = "Remove index/table" ;
+};
+String STR_TABLE_TBLCPYTBL{
+ Text [ en-US ] = "Copy table" ;
+};
+String STR_TABLE_CPYTBL
+{
+ Text [ en-US ] = "Copy table" ;
+};
+String STR_INS_FROM_SHADOWCRSR
+{
+ Text [ en-US ] = "Set cursor" ;
+};
+String STR_UNDO_CHAIN
+{
+ Text [ en-US ] = "Link text frames" ;
+};
+String STR_UNDO_UNCHAIN
+{
+ Text [ en-US ] = "Unlink text frames" ;
+};
+String STR_UNDO_FTNINFO
+{
+ Text [ en-US ] = "Modify footnote options" ;
+};
+String STR_UNDO_ENDNOTEINFO
+{
+ Text [ en-US ] = "Modify endnote settings" ;
+};
+String STR_UNDO_COMPAREDOC
+{
+ Text [ en-US ] = "Compare Document" ;
+};
+String STR_UNDO_SETFLYFRMFMT
+{
+ Text [ en-US ] = "Apply frame style: $1" ;
+};
+String STR_UNDO_SETRUBYATTR
+{
+ Text [ en-US ] = "Ruby Setting";
+};
+// #102505#
+String STR_UNDO_TMPAUTOCORR
+{
+ Text [ en-US ] = "AutoCorrect" ;
+};
+String STR_INSERT_FOOTNOTE
+{
+ Text [ en-US ] = "Insert footnote" ;
+};
+String STR_INSERT_URLBTN
+{
+ Text [ en-US ] = "insert URL button";
+};
+String STR_INSERT_URLTXT
+{
+ Text [ en-US ] = "Insert Hyperlink";
+};
+String STR_DELETE_INVISIBLECNTNT
+{
+ Text [ en-US ] = "remove invisible content";
+};
+String STR_TOXCHANGE
+{
+ Text [ en-US ] = "Table/index changed";
+};
+String STR_START_QUOTE
+{
+ Text [ en-US ] = "'";
+};
+String STR_END_QUOTE
+{
+ Text [ en-US ] = "'";
+};
+String STR_LDOTS
+{
+ Text [ en-US ] = "...";
+};
+String STR_CLIPBOARD
+{
+ Text [ en-US ] = "clipboard";
+};
+String STR_MULTISEL
+{
+ Text [ en-US ] = "multiple selection";
+};
+String STR_TYPING_UNDO
+{
+ Text [ en-US ] = "Typing: $1";
+};
+String STR_PASTE_CLIPBOARD_UNDO
+{
+ Text [ en-US ] = "Paste clipboard";
+};
+String STR_YIELDS
+{
+ Text [ en-US ] = "->";
+};
+String STR_OCCURRENCES_OF
+{
+ Text [ en-US ] = "occurrences of";
+};
+String STR_UNDO_TABS
+{
+ Text [ en-US ] = "$1 tab(s)";
+};
+String STR_UNDO_NLS
+{
+ Text[ en-US ] = "$1 line break(s)";
+};
+String STR_UNDO_PAGEBREAKS
+{
+ Text[ en-US ] = "page break";
+};
+String STR_UNDO_COLBRKS
+{
+ Text[ en-US ] = "column break";
+};
+String STR_REDLINE_INSERT
+{
+ Text [ en-US ] = "Insert $1";
+};
+String STR_REDLINE_DELETE
+{
+ Text [ en-US ] = "Delete $1";
+};
+String STR_REDLINE_FORMAT
+{
+ Text [ en-US ] = "Attributes changed";
+};
+String STR_REDLINE_TABLE
+{
+ Text [ en-US ] = "Table changed";
+};
+String STR_REDLINE_FMTCOLL
+{
+ Text [ en-US ] = "Style changed";
+};
+String STR_REDLINE_MULTIPLE
+{
+ Text [ en-US ] = "multiple changes";
+};
+String STR_N_REDLINES
+{
+ Text [ en-US ] = "$1 changes";
+};
+String STR_UNDO_PAGEDESC
+{
+ Text [ en-US ] = "Change page style: $1";
+};
+String STR_UNDO_PAGEDESC_CREATE
+{
+ Text [ en-US ] = "Create page style: $1";
+};
+String STR_UNDO_PAGEDESC_DELETE
+{
+ Text [ en-US ] = "Delete page style: $1";
+};
+String STR_UNDO_PAGEDESC_RENAME
+{
+ Text [ en-US ] = "Rename page style: $1 $2 $3";
+};
+String STR_UNDO_HEADER_FOOTER
+{
+ Text [ en-US ] = "Header/footer changed";
+};
+String STR_UNDO_FIELD
+{
+ Text [ en-US ] = "Field changed";
+};
+String STR_UNDO_TXTFMTCOL_CREATE
+{
+ Text [ en-US ] = "Create paragraph style: $1";
+};
+String STR_UNDO_TXTFMTCOL_DELETE
+{
+ Text [ en-US ] = "Delete paragraph style: $1";
+};
+String STR_UNDO_TXTFMTCOL_RENAME
+{
+ Text [ en-US ] = "Rename paragraph style: $1 $2 $3";
+};
+String STR_UNDO_CHARFMT_CREATE
+{
+ Text [ en-US ] = "Create character style: $1";
+};
+String STR_UNDO_CHARFMT_DELETE
+{
+ Text [ en-US ] = "Delete character style: $1";
+};
+String STR_UNDO_CHARFMT_RENAME
+{
+ Text [ en-US ] = "Rename character style: $1 $2 $3";
+};
+String STR_UNDO_FRMFMT_CREATE
+{
+ Text [ en-US ] = "Create frame style: $1";
+};
+String STR_UNDO_FRMFMT_DELETE
+{
+ Text [ en-US ] = "Delete frame style: $1";
+};
+String STR_UNDO_FRMFMT_RENAME
+{
+ Text [ en-US ] = "Rename frame style: $1 $2 $3";
+};
+String STR_UNDO_NUMRULE_CREATE
+{
+ Text [ en-US ] = "Create numbering style: $1";
+};
+String STR_UNDO_NUMRULE_DELETE
+{
+ Text [ en-US ] = "Delete numbering style: $1";
+};
+String STR_UNDO_NUMRULE_RENAME
+{
+ Text [ en-US ] = "Rename numbering style: $1 $2 $3";
+};
+String STR_UNDO_BOOKMARK_RENAME
+{
+ Text[ en-US ] = "Rename bookmark: $1 $2 $3";
+};
+String STR_UNDO_INDEX_ENTRY_INSERT
+{
+ Text[ en-US ] = "Insert index entry";
+};
+String STR_UNDO_INDEX_ENTRY_DELETE
+{
+ Text[ en-US ] = "Delete index entry";
+};
+String STR_FIELD
+{
+ Text [ en-US ] = "field";
+};
+String STR_PARAGRAPHS
+{
+ Text [ en-US ] = "Paragraphs" ;
+};
+String STR_FRAME
+{
+ Text [ en-US ] = "frame";
+};
+String STR_OLE
+{
+ Text [ en-US ] = "OLE-object";
+};
+String STR_MATH_FORMULA
+{
+ Text [ en-US ] = "formula";
+};
+String STR_CHART
+{
+ Text [ en-US ] = "chart";
+};
+String STR_NOTE
+{
+ Text [ en-US ] = "comment";
+};
+String STR_REFERENCE
+{
+ Text [ en-US ] = "cross-reference";
+};
+String STR_SCRIPT
+{
+ Text [ en-US ] = "script";
+};
+String STR_AUTHORITY_ENTRY
+{
+ Text[ en-US ] = "bibliography entry";
+};
+String STR_SPECIALCHAR
+{
+ Text[ en-US ] = "special character";
+};
+String STR_FOOTNOTE
+{
+ Text[ en-US ] = "footnote";
+};
+String STR_GRAPHIC
+{
+ Text[ en-US ] = "picture";
+};
+String STR_DRAWING_OBJECTS
+{
+ Text[ en-US ] = "drawing object(s)";
+};
+String STR_TABLE_NAME
+{
+ Text[ en-US ] = "table: $1$2$3";
+};
+String STR_PARAGRAPH_UNDO
+{
+ Text[ en-US ] = "paragraph";
+};
+String STR_UNDO_FLYFRMFMT_TITLE
+{
+ Text[ en-US ] = "Change object title of $1";
+};
+String STR_UNDO_FLYFRMFMT_DESCRITPTION
+{
+ Text[ en-US ] = "Change object description of $1";
+};
diff --git a/sw/source/core/undo/undobj.cxx b/sw/source/core/undo/undobj.cxx
new file mode 100644
index 000000000000..4d17b8fa51a1
--- /dev/null
+++ b/sw/source/core/undo/undobj.cxx
@@ -0,0 +1,1347 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+
+#include <IShellCursorSupplier.hxx>
+#include <txtftn.hxx>
+#include <fmtanchr.hxx>
+#include <ftnidx.hxx>
+#include <frmfmt.hxx>
+#include <doc.hxx>
+#include <UndoManager.hxx>
+#include <docary.hxx>
+#include <swundo.hxx> // fuer die UndoIds
+#include <pam.hxx>
+#include <ndtxt.hxx>
+#include <UndoCore.hxx>
+#include <rolbck.hxx>
+#include <ndnotxt.hxx>
+#include <IMark.hxx>
+#include <mvsave.hxx>
+#include <redline.hxx>
+#include <crossrefbookmark.hxx>
+#include <undo.hrc>
+#include <comcore.hrc>
+#include <docsh.hxx>
+
+class SwRedlineSaveData : public SwUndRng, public SwRedlineData,
+ private SwUndoSaveSection
+{
+public:
+ SwRedlineSaveData( SwComparePosition eCmpPos,
+ const SwPosition& rSttPos, const SwPosition& rEndPos,
+ SwRedline& rRedl, sal_Bool bCopyNext );
+ ~SwRedlineSaveData();
+ void RedlineToDoc( SwPaM& rPam );
+ SwNodeIndex* GetMvSttIdx() const
+ { return SwUndoSaveSection::GetMvSttIdx(); }
+
+#if OSL_DEBUG_LEVEL > 1
+ sal_uInt16 nRedlineCount;
+#endif
+};
+
+SV_IMPL_PTRARR( SwRedlineSaveDatas, SwRedlineSaveDataPtr )
+
+
+//------------------------------------------------------------
+
+// Diese Klasse speichert den Pam als sal_uInt16's und kann diese wieder zu
+
+// einem PaM zusammensetzen
+SwUndRng::SwUndRng()
+ : nSttNode( 0 ), nEndNode( 0 ), nSttCntnt( 0 ), nEndCntnt( 0 )
+{
+}
+
+SwUndRng::SwUndRng( const SwPaM& rPam )
+{
+ SetValues( rPam );
+}
+
+void SwUndRng::SetValues( const SwPaM& rPam )
+{
+ const SwPosition *pStt = rPam.Start();
+ if( rPam.HasMark() )
+ {
+ const SwPosition *pEnd = rPam.GetPoint() == pStt
+ ? rPam.GetMark()
+ : rPam.GetPoint();
+ nEndNode = pEnd->nNode.GetIndex();
+ nEndCntnt = pEnd->nContent.GetIndex();
+ }
+ else
+ // keine Selektion !!
+ nEndNode = 0, nEndCntnt = STRING_MAXLEN;
+
+ nSttNode = pStt->nNode.GetIndex();
+ nSttCntnt = pStt->nContent.GetIndex();
+}
+
+void SwUndRng::SetPaM( SwPaM & rPam, sal_Bool bCorrToCntnt ) const
+{
+ rPam.DeleteMark();
+ rPam.GetPoint()->nNode = nSttNode;
+ SwNode* pNd = rPam.GetNode();
+ if( pNd->IsCntntNode() )
+ rPam.GetPoint()->nContent.Assign( pNd->GetCntntNode(), nSttCntnt );
+ else if( bCorrToCntnt )
+ rPam.Move( fnMoveForward, fnGoCntnt );
+ else
+ rPam.GetPoint()->nContent.Assign( 0, 0 );
+
+ if( !nEndNode && STRING_MAXLEN == nEndCntnt ) // keine Selection
+ return ;
+
+ rPam.SetMark();
+ if( nSttNode == nEndNode && nSttCntnt == nEndCntnt )
+ return; // nichts mehr zu tun
+
+ rPam.GetPoint()->nNode = nEndNode;
+ if( (pNd = rPam.GetNode())->IsCntntNode() )
+ rPam.GetPoint()->nContent.Assign( pNd->GetCntntNode(), nEndCntnt );
+ else if( bCorrToCntnt )
+ rPam.Move( fnMoveBackward, fnGoCntnt );
+ else
+ rPam.GetPoint()->nContent.Assign( 0, 0 );
+}
+
+SwPaM & SwUndRng::AddUndoRedoPaM(
+ ::sw::UndoRedoContext & rContext, bool bCorrToCntnt) const
+{
+ SwPaM & rPaM( rContext.GetCursorSupplier().CreateNewShellCursor() );
+ SetPaM( rPaM, bCorrToCntnt );
+ return rPaM;
+}
+
+
+//------------------------------------------------------------
+
+
+void SwUndo::RemoveIdxFromSection( SwDoc& rDoc, sal_uLong nSttIdx,
+ sal_uLong* pEndIdx )
+{
+ SwNodeIndex aIdx( rDoc.GetNodes(), nSttIdx );
+ SwNodeIndex aEndIdx( rDoc.GetNodes(), pEndIdx ? *pEndIdx
+ : aIdx.GetNode().EndOfSectionIndex() );
+ SwPosition aPos( rDoc.GetNodes().GetEndOfPostIts() );
+ rDoc.CorrAbs( aIdx, aEndIdx, aPos, sal_True );
+}
+
+void SwUndo::RemoveIdxFromRange( SwPaM& rPam, sal_Bool bMoveNext )
+{
+ const SwPosition* pEnd = rPam.End();
+ if( bMoveNext )
+ {
+ if( pEnd != rPam.GetPoint() )
+ rPam.Exchange();
+
+ SwNodeIndex aStt( rPam.GetMark()->nNode );
+ SwNodeIndex aEnd( rPam.GetPoint()->nNode );
+
+ if( !rPam.Move( fnMoveForward ) )
+ {
+ rPam.Exchange();
+ if( !rPam.Move( fnMoveBackward ) )
+ {
+ rPam.GetPoint()->nNode = rPam.GetDoc()->GetNodes().GetEndOfPostIts();
+ rPam.GetPoint()->nContent.Assign( 0, 0 );
+ }
+ }
+
+ rPam.GetDoc()->CorrAbs( aStt, aEnd, *rPam.GetPoint(), sal_True );
+ }
+ else
+ rPam.GetDoc()->CorrAbs( rPam, *pEnd, sal_True );
+}
+
+void SwUndo::RemoveIdxRel( sal_uLong nIdx, const SwPosition& rPos )
+{
+ // nur die Crsr verschieben; die Bookmarks/TOXMarks/.. werden vom
+ // entsp. JoinNext/JoinPrev erledigt!
+ SwNodeIndex aIdx( rPos.nNode.GetNode().GetNodes(), nIdx );
+ ::PaMCorrRel( aIdx, rPos );
+}
+
+SwUndo::SwUndo(SwUndoId const nId)
+ : m_nId(nId), nOrigRedlineMode(nsRedlineMode_t::REDLINE_NONE),
+ bCacheComment(true), pComment(NULL)
+{
+}
+
+bool SwUndo::IsDelBox() const
+{
+ return GetId() == UNDO_COL_DELETE || GetId() == UNDO_ROW_DELETE ||
+ GetId() == UNDO_TABLE_DELBOX;
+}
+
+SwUndo::~SwUndo()
+{
+ delete pComment;
+}
+
+
+class UndoRedoRedlineGuard
+{
+public:
+ UndoRedoRedlineGuard(::sw::UndoRedoContext & rContext, SwUndo & rUndo)
+ : m_rRedlineAccess(rContext.GetDoc())
+ , m_eMode(m_rRedlineAccess.GetRedlineMode())
+ {
+ RedlineMode_t const eTmpMode =
+ static_cast<RedlineMode_t>(rUndo.GetRedlineMode());
+ if ((nsRedlineMode_t::REDLINE_SHOW_MASK & eTmpMode) !=
+ (nsRedlineMode_t::REDLINE_SHOW_MASK & m_eMode))
+ {
+ m_rRedlineAccess.SetRedlineMode( eTmpMode );
+ }
+ m_rRedlineAccess.SetRedlineMode_intern( static_cast<RedlineMode_t>(
+ eTmpMode | nsRedlineMode_t::REDLINE_IGNORE) );
+ }
+ ~UndoRedoRedlineGuard()
+ {
+ m_rRedlineAccess.SetRedlineMode(m_eMode);
+ }
+private:
+ IDocumentRedlineAccess & m_rRedlineAccess;
+ RedlineMode_t const m_eMode;
+};
+
+void SwUndo::Undo()
+{
+ OSL_ENSURE(false, "SwUndo::Undo(): ERROR: must call Undo(context) instead");
+}
+
+void SwUndo::Redo()
+{
+ OSL_ENSURE(false, "SwUndo::Redo(): ERROR: must call Redo(context) instead");
+}
+
+void SwUndo::UndoWithContext(SfxUndoContext & rContext)
+{
+ ::sw::UndoRedoContext *const pContext(
+ dynamic_cast< ::sw::UndoRedoContext * >(& rContext));
+ OSL_ASSERT(pContext);
+ if (!pContext) { return; }
+ UndoRedoRedlineGuard(*pContext, *this);
+ UndoImpl(*pContext);
+}
+
+void SwUndo::RedoWithContext(SfxUndoContext & rContext)
+{
+ ::sw::UndoRedoContext *const pContext(
+ dynamic_cast< ::sw::UndoRedoContext * >(& rContext));
+ OSL_ASSERT(pContext);
+ if (!pContext) { return; }
+ UndoRedoRedlineGuard(*pContext, *this);
+ RedoImpl(*pContext);
+}
+
+void SwUndo::Repeat(SfxRepeatTarget & rContext)
+{
+ ::sw::RepeatContext *const pRepeatContext(
+ dynamic_cast< ::sw::RepeatContext * >(& rContext));
+ OSL_ASSERT(pRepeatContext);
+ if (!pRepeatContext) { return; }
+ RepeatImpl(*pRepeatContext);
+}
+
+sal_Bool SwUndo::CanRepeat(SfxRepeatTarget & rContext) const
+{
+ ::sw::RepeatContext *const pRepeatContext(
+ dynamic_cast< ::sw::RepeatContext * >(& rContext));
+ OSL_ASSERT(pRepeatContext);
+ if (!pRepeatContext) { return false; }
+ return CanRepeatImpl(*pRepeatContext);
+}
+
+void SwUndo::RepeatImpl( ::sw::RepeatContext & )
+{
+}
+
+bool SwUndo::CanRepeatImpl( ::sw::RepeatContext & ) const
+{
+// return false;
+ return ((REPEAT_START <= GetId()) && (GetId() < REPEAT_END));
+}
+
+String SwUndo::GetComment() const
+{
+ String aResult;
+
+ if (bCacheComment)
+ {
+ if (! pComment)
+ {
+ pComment = new String(SW_RES(UNDO_BASE + GetId()));
+
+ SwRewriter aRewriter = GetRewriter();
+
+ *pComment = aRewriter.Apply(*pComment);
+ }
+
+ aResult = *pComment;
+ }
+ else
+ {
+ aResult = String(SW_RES(UNDO_BASE + GetId()));
+
+ SwRewriter aRewriter = GetRewriter();
+
+ aResult = aRewriter.Apply(aResult);
+ }
+
+ return aResult;
+}
+
+SwRewriter SwUndo::GetRewriter() const
+{
+ SwRewriter aResult;
+
+ return aResult;
+}
+
+
+//------------------------------------------------------------
+
+SwUndoSaveCntnt::SwUndoSaveCntnt()
+ : pHistory( 0 )
+{}
+
+SwUndoSaveCntnt::~SwUndoSaveCntnt()
+{
+ delete pHistory;
+}
+
+ // wird fuer das Loeschen von Inhalt benoetigt. Fuer das ReDo werden
+ // Inhalte in das UndoNodesArray verschoben. Diese Methoden fuegen
+ // am Ende eines TextNodes fuer die Attribute einen Trenner ein.
+ // Dadurch werden die Attribute nicht expandiert.
+ // MoveTo.. verschiebt aus dem NodesArray in das UndoNodesArray
+ // MoveFrom.. verschiebt aus dem UndoNodesArray in das NodesArray
+
+ // 2.8.93: ist pEndNdIdx angebenen, wird vom Undo/Redo -Ins/DelFly
+ // aufgerufen. Dann soll die gesamte Section verschoben werden.
+
+void SwUndoSaveCntnt::MoveToUndoNds( SwPaM& rPaM, SwNodeIndex* pNodeIdx,
+ SwIndex* pCntIdx, sal_uLong* pEndNdIdx, xub_StrLen* pEndCntIdx )
+{
+ SwDoc& rDoc = *rPaM.GetDoc();
+ ::sw::UndoGuard const undoGuard(rDoc.GetIDocumentUndoRedo());
+
+ SwNoTxtNode* pCpyNd = rPaM.GetNode()->GetNoTxtNode();
+
+ // jetzt kommt das eigentliche Loeschen(Verschieben)
+ SwNodes & rNds = rDoc.GetUndoManager().GetUndoNodes();
+ SwPosition aPos( pEndNdIdx ? rNds.GetEndOfPostIts()
+ : rNds.GetEndOfExtras() );
+ aPos.nNode--;
+
+ const SwPosition* pStt = rPaM.Start(), *pEnd = rPaM.End();
+
+ if( pCpyNd || pEndNdIdx || !aPos.nNode.GetNode().GetCntntNode() ||
+ (!pStt->nContent.GetIndex() && (pStt->nNode != pEnd->nNode ||
+ (!pStt->nNode.GetNode().GetCntntNode() ||
+ pStt->nNode.GetNode().GetCntntNode()->Len() ==
+ pEnd->nContent.GetIndex() ) ) ) )
+ {
+ aPos.nNode++;
+ aPos.nContent = 0;
+ }
+ else
+ aPos.nNode.GetNode().GetCntntNode()->MakeEndIndex( &aPos.nContent );
+
+ // als sal_uInt16 merken; die Indizies verschieben sich !!
+ sal_uLong nTmpMvNode = aPos.nNode.GetIndex();
+ xub_StrLen nTmpMvCntnt = aPos.nContent.GetIndex();
+
+ if( pCpyNd || pEndNdIdx )
+ {
+ SwNodeRange aRg( pStt->nNode, 0, pEnd->nNode, 1 );
+ rDoc.GetNodes()._MoveNodes( aRg, rNds, aPos.nNode, sal_False );
+ aPos.nContent = 0;
+ aPos.nNode--;
+ }
+ else
+ {
+ rDoc.GetNodes().MoveRange( rPaM, aPos, rNds );
+
+ SwTxtNode* pTxtNd = aPos.nNode.GetNode().GetTxtNode();
+ if( pTxtNd ) // fuege einen Trenner fuer die Attribute ein !
+ {
+ // weil aber beim Insert die Attribute angefasst/sprich
+ // aus dem Array geloescht und wieder eingefuegt werden, koennen
+ // dadurch Attribute verschwinden (z.B "Fett aus" von 10-20,
+ // "Fett an" von 12-15, dann wird durchs Insert/Delete das
+ // "Fett an" geloescht !! Ist hier aber nicht erwuenscht !!)
+ // DARUM: nicht die Hints anfassen, direct den String manipulieren
+
+ String& rStr = (String&)pTxtNd->GetTxt();
+ // Zur Sicherheit lieber nur wenn wirklich am Ende steht
+ if( rStr.Len() == aPos.nContent.GetIndex() )
+ {
+ rStr.Insert( ' ' );
+ ++aPos.nContent;
+ }
+ else
+ {
+ pTxtNd->InsertText( sal_Unicode(' '), aPos.nContent,
+ IDocumentContentOperations::INS_NOHINTEXPAND );
+ }
+ }
+ }
+ if( pEndNdIdx )
+ *pEndNdIdx = aPos.nNode.GetIndex();
+ if( pEndCntIdx )
+ *pEndCntIdx = aPos.nContent.GetIndex();
+
+ // alte Position
+ aPos.nNode = nTmpMvNode;
+ if( pNodeIdx )
+ *pNodeIdx = aPos.nNode;
+
+ if( pCntIdx )
+ {
+ SwCntntNode* pCNd = aPos.nNode.GetNode().GetCntntNode();
+ if( pCNd )
+ pCntIdx->Assign( pCNd, nTmpMvCntnt );
+ else
+ pCntIdx->Assign( 0, 0 );
+ }
+}
+
+void SwUndoSaveCntnt::MoveFromUndoNds( SwDoc& rDoc, sal_uLong nNodeIdx,
+ xub_StrLen nCntIdx, SwPosition& rInsPos,
+ sal_uLong* pEndNdIdx, xub_StrLen* pEndCntIdx )
+{
+ // jetzt kommt das wiederherstellen
+ SwNodes & rNds = rDoc.GetUndoManager().GetUndoNodes();
+ if( nNodeIdx == rNds.GetEndOfPostIts().GetIndex() )
+ return; // nichts gespeichert
+
+ ::sw::UndoGuard const undoGuard(rDoc.GetIDocumentUndoRedo());
+
+ SwPaM aPaM( rInsPos );
+ if( pEndNdIdx ) // dann hole aus diesem den Bereich
+ aPaM.GetPoint()->nNode.Assign( rNds, *pEndNdIdx );
+ else
+ {
+ aPaM.GetPoint()->nNode = rNds.GetEndOfExtras();
+ GoInCntnt( aPaM, fnMoveBackward );
+ }
+
+ SwTxtNode* pTxtNd = aPaM.GetNode()->GetTxtNode();
+ if( !pEndNdIdx && pTxtNd ) // loesche den Trenner wieder
+ {
+ if( pEndCntIdx )
+ aPaM.GetPoint()->nContent.Assign( pTxtNd, *pEndCntIdx );
+ if( pTxtNd->GetTxt().Len() )
+ {
+ GoInCntnt( aPaM, fnMoveBackward );
+ pTxtNd->EraseText( aPaM.GetPoint()->nContent, 1 );
+ }
+
+ aPaM.SetMark();
+ aPaM.GetPoint()->nNode = nNodeIdx;
+ aPaM.GetPoint()->nContent.Assign( aPaM.GetCntntNode(), nCntIdx );
+
+ _SaveRedlEndPosForRestore aRedlRest( rInsPos.nNode, rInsPos.nContent.GetIndex() );
+
+ rNds.MoveRange( aPaM, rInsPos, rDoc.GetNodes() );
+
+ // noch den letzen Node loeschen.
+ if( !aPaM.GetPoint()->nContent.GetIndex() ||
+ ( aPaM.GetPoint()->nNode++ && // noch leere Nodes am Ende ??
+ &rNds.GetEndOfExtras() != &aPaM.GetPoint()->nNode.GetNode() ))
+ {
+ aPaM.GetPoint()->nContent.Assign( 0, 0 );
+ aPaM.SetMark();
+ rNds.Delete( aPaM.GetPoint()->nNode,
+ rNds.GetEndOfExtras().GetIndex() -
+ aPaM.GetPoint()->nNode.GetIndex() );
+ }
+
+ aRedlRest.Restore();
+ }
+ else if( pEndNdIdx || !pTxtNd )
+ {
+ SwNodeRange aRg( rNds, nNodeIdx, rNds, (pEndNdIdx
+ ? ((*pEndNdIdx) + 1)
+ : rNds.GetEndOfExtras().GetIndex() ) );
+ rNds._MoveNodes( aRg, rDoc.GetNodes(), rInsPos.nNode, 0 == pEndNdIdx );
+
+ }
+ else {
+ OSL_FAIL( "was ist es denn nun?" );
+ }
+}
+
+// diese beiden Methoden bewegen den Point vom Pam zurueck/vor. Damit
+// kann fuer ein Undo/Redo ein Bereich aufgespannt werden. (Der
+// Point liegt dann vor dem manipuliertem Bereich !!)
+// Das Flag gibt an, ob noch vorm Point Inhalt steht.
+
+sal_Bool SwUndoSaveCntnt::MovePtBackward( SwPaM& rPam )
+{
+ rPam.SetMark();
+ if( rPam.Move( fnMoveBackward ))
+ return sal_True;
+
+ // gibt es nach vorne keinen Inhalt mehr, so setze den Point einfach
+ // auf die vorherige Position (Node und Content, damit der Content
+ // abgemeldet wird !!)
+ rPam.GetPoint()->nNode--;
+ rPam.GetPoint()->nContent.Assign( 0, 0 );
+ return sal_False;
+}
+
+void SwUndoSaveCntnt::MovePtForward( SwPaM& rPam, sal_Bool bMvBkwrd )
+{
+ // gab es noch Inhalt vor der Position ?
+ if( bMvBkwrd )
+ rPam.Move( fnMoveForward );
+ else
+ { // setzen Point auf die naechste Position
+ rPam.GetPoint()->nNode++;
+ SwCntntNode* pCNd = rPam.GetCntntNode();
+ if( pCNd )
+ pCNd->MakeStartIndex( &rPam.GetPoint()->nContent );
+ else
+ rPam.Move( fnMoveForward );
+ }
+}
+
+
+/*
+ JP 21.03.94: loesche alle Objecte, die ContentIndizies auf den ang.
+ Bereich besitzen.
+ Zur Zeit gibts folgende Objecte
+ - Fussnoten
+ - Flys
+ - Bookmarks
+ - Verzeichnisse
+*/
+// --> OD 2007-10-17 #i81002# - extending method:
+// delete certain (not all) cross-reference bookmarks at text node of <rMark>
+// and at text node of <rPoint>, if these text nodes aren't the same.
+void SwUndoSaveCntnt::DelCntntIndex( const SwPosition& rMark,
+ const SwPosition& rPoint,
+ DelCntntType nDelCntntType )
+{
+ const SwPosition *pStt = rMark < rPoint ? &rMark : &rPoint,
+ *pEnd = &rMark == pStt ? &rPoint : &rMark;
+
+ SwDoc* pDoc = rMark.nNode.GetNode().GetDoc();
+
+ ::sw::UndoGuard const undoGuard(pDoc->GetIDocumentUndoRedo());
+
+ // 1. Fussnoten
+ if( nsDelCntntType::DELCNT_FTN & nDelCntntType )
+ {
+ SwFtnIdxs& rFtnArr = pDoc->GetFtnIdxs();
+ if( rFtnArr.Count() )
+ {
+ const SwNode* pFtnNd;
+ sal_uInt16 nPos;
+ rFtnArr.SeekEntry( pStt->nNode, &nPos );
+ SwTxtFtn* pSrch;
+
+ // loesche erstmal alle, die dahinter stehen
+ while( nPos < rFtnArr.Count() && ( pFtnNd =
+ &( pSrch = rFtnArr[ nPos ] )->GetTxtNode())->GetIndex()
+ <= pEnd->nNode.GetIndex() )
+ {
+ xub_StrLen nFtnSttIdx = *pSrch->GetStart();
+ if( (nsDelCntntType::DELCNT_CHKNOCNTNT & nDelCntntType )
+ ? (&pEnd->nNode.GetNode() == pFtnNd )
+ : (( &pStt->nNode.GetNode() == pFtnNd &&
+ pStt->nContent.GetIndex() > nFtnSttIdx) ||
+ ( &pEnd->nNode.GetNode() == pFtnNd &&
+ nFtnSttIdx >= pEnd->nContent.GetIndex() )) )
+ {
+ ++nPos; // weiter suchen
+ continue;
+ }
+
+ // es muss leider ein Index angelegt werden. Sonst knallts im
+ // TextNode, weil im DTOR der SwFtn dieser geloescht wird !!
+ SwTxtNode* pTxtNd = (SwTxtNode*)pFtnNd;
+ if( !pHistory )
+ pHistory = new SwHistory;
+ SwTxtAttr* const pFtnHnt =
+ pTxtNd->GetTxtAttrForCharAt( nFtnSttIdx );
+ OSL_ENSURE( pFtnHnt, "kein FtnAttribut" );
+ SwIndex aIdx( pTxtNd, nFtnSttIdx );
+ pHistory->Add( pFtnHnt, pTxtNd->GetIndex(), false );
+ pTxtNd->EraseText( aIdx, 1 );
+ }
+
+ while( nPos-- && ( pFtnNd = &( pSrch = rFtnArr[ nPos ] )->
+ GetTxtNode())->GetIndex() >= pStt->nNode.GetIndex() )
+ {
+ xub_StrLen nFtnSttIdx = *pSrch->GetStart();
+ if( !(nsDelCntntType::DELCNT_CHKNOCNTNT & nDelCntntType) && (
+ ( &pStt->nNode.GetNode() == pFtnNd &&
+ pStt->nContent.GetIndex() > nFtnSttIdx ) ||
+ ( &pEnd->nNode.GetNode() == pFtnNd &&
+ nFtnSttIdx >= pEnd->nContent.GetIndex() )))
+ continue; // weiter suchen
+
+ // es muss leider ein Index angelegt werden. Sonst knallts im
+ // TextNode, weil im DTOR der SwFtn dieser geloescht wird !!
+ SwTxtNode* pTxtNd = (SwTxtNode*)pFtnNd;
+ if( !pHistory )
+ pHistory = new SwHistory;
+ SwTxtAttr* const pFtnHnt =
+ pTxtNd->GetTxtAttrForCharAt( nFtnSttIdx );
+ OSL_ENSURE( pFtnHnt, "kein FtnAttribut" );
+ SwIndex aIdx( pTxtNd, nFtnSttIdx );
+ pHistory->Add( pFtnHnt, pTxtNd->GetIndex(), false );
+ pTxtNd->EraseText( aIdx, 1 );
+ }
+ }
+ }
+
+ // 2. Flys
+ if( nsDelCntntType::DELCNT_FLY & nDelCntntType )
+ {
+ sal_uInt16 nChainInsPos = pHistory ? pHistory->Count() : 0;
+ const SwSpzFrmFmts& rSpzArr = *pDoc->GetSpzFrmFmts();
+ if( rSpzArr.Count() )
+ {
+ const sal_Bool bDelFwrd = rMark.nNode.GetIndex() <= rPoint.nNode.GetIndex();
+ SwFlyFrmFmt* pFmt;
+ const SwFmtAnchor* pAnchor;
+ sal_uInt16 n = rSpzArr.Count();
+ const SwPosition* pAPos;
+
+ while( n && rSpzArr.Count() )
+ {
+ pFmt = (SwFlyFrmFmt*)rSpzArr[--n];
+ pAnchor = &pFmt->GetAnchor();
+ switch( pAnchor->GetAnchorId() )
+ {
+ case FLY_AS_CHAR:
+ if( 0 != (pAPos = pAnchor->GetCntntAnchor() ) &&
+ (( nsDelCntntType::DELCNT_CHKNOCNTNT & nDelCntntType )
+ ? ( pStt->nNode <= pAPos->nNode &&
+ pAPos->nNode < pEnd->nNode )
+ : ( *pStt <= *pAPos && *pAPos < *pEnd )) )
+ {
+ if( !pHistory )
+ pHistory = new SwHistory;
+ SwTxtNode *const pTxtNd =
+ pAPos->nNode.GetNode().GetTxtNode();
+ SwTxtAttr* const pFlyHnt = pTxtNd->GetTxtAttrForCharAt(
+ pAPos->nContent.GetIndex());
+ OSL_ENSURE( pFlyHnt, "kein FlyAttribut" );
+ pHistory->Add( pFlyHnt, 0, false );
+ // n wieder zurueck, damit nicht ein Format uebesprungen wird !
+ n = n >= rSpzArr.Count() ? rSpzArr.Count() : n+1;
+ }
+ break;
+ case FLY_AT_PARA:
+ {
+ pAPos = pAnchor->GetCntntAnchor();
+ if( pAPos )
+ {
+ bool bTmp;
+ if( nsDelCntntType::DELCNT_CHKNOCNTNT & nDelCntntType )
+ bTmp = pStt->nNode <= pAPos->nNode && pAPos->nNode < pEnd->nNode;
+ else
+ {
+ if (bDelFwrd)
+ bTmp = rMark.nNode < pAPos->nNode &&
+ pAPos->nNode <= rPoint.nNode;
+ else
+ bTmp = rPoint.nNode <= pAPos->nNode &&
+ pAPos->nNode < rMark.nNode;
+ }
+
+ if (bTmp)
+ {
+ if( !pHistory )
+ pHistory = new SwHistory;
+
+ // Moving the anchor?
+ if( !( nsDelCntntType::DELCNT_CHKNOCNTNT & nDelCntntType ) &&
+ ( rPoint.nNode.GetIndex() == pAPos->nNode.GetIndex() ) )
+ {
+ // Do not try to move the anchor to a table!
+ if( rMark.nNode.GetNode().GetTxtNode() )
+ {
+ pHistory->Add( *pFmt );
+ SwFmtAnchor aAnch( *pAnchor );
+ SwPosition aPos( rMark.nNode );
+ aAnch.SetAnchor( &aPos );
+ pFmt->SetFmtAttr( aAnch );
+ }
+ }
+ else
+ {
+ pHistory->Add( *pFmt, nChainInsPos );
+ // n wieder zurueck, damit nicht ein
+ // Format uebesprungen wird !
+ n = n >= rSpzArr.Count() ?
+ rSpzArr.Count() : n+1;
+ }
+ }
+ }
+ }
+ break;
+ case FLY_AT_CHAR:
+ if( 0 != (pAPos = pAnchor->GetCntntAnchor() ) &&
+ ( pStt->nNode <= pAPos->nNode && pAPos->nNode <= pEnd->nNode ) )
+ {
+ if( !pHistory )
+ pHistory = new SwHistory;
+ if (IsDestroyFrameAnchoredAtChar(
+ *pAPos, *pStt, *pEnd, nDelCntntType))
+ {
+ pHistory->Add( *pFmt, nChainInsPos );
+ n = n >= rSpzArr.Count() ? rSpzArr.Count() : n+1;
+ }
+ else if( !( nsDelCntntType::DELCNT_CHKNOCNTNT & nDelCntntType ) )
+ {
+ if( *pStt <= *pAPos && *pAPos < *pEnd )
+ {
+ // These are the objects anchored
+ // between section start and end position
+ // Do not try to move the anchor to a table!
+ if( rMark.nNode.GetNode().GetTxtNode() )
+ {
+ pHistory->Add( *pFmt );
+ SwFmtAnchor aAnch( *pAnchor );
+ aAnch.SetAnchor( &rMark );
+ pFmt->SetFmtAttr( aAnch );
+ }
+ }
+ }
+ }
+ break;
+ case FLY_AT_FLY:
+
+ if( 0 != (pAPos = pAnchor->GetCntntAnchor() ) &&
+ pStt->nNode == pAPos->nNode )
+ {
+ if( !pHistory )
+ pHistory = new SwHistory;
+
+ pHistory->Add( *pFmt, nChainInsPos );
+
+ // n wieder zurueck, damit nicht ein Format uebesprungen wird !
+ n = n >= rSpzArr.Count() ? rSpzArr.Count() : n+1;
+ }
+ break;
+ default: break;
+ }
+ }
+ }
+ }
+
+ // 3. Bookmarks
+ if( nsDelCntntType::DELCNT_BKM & nDelCntntType )
+ {
+ IDocumentMarkAccess* const pMarkAccess = pDoc->getIDocumentMarkAccess();
+ if( pMarkAccess->getMarksCount() )
+ {
+
+ for( sal_uInt16 n = 0; n < pMarkAccess->getMarksCount(); ++n )
+ {
+ // --> OD 2007-10-17 #i81002#
+ bool bSavePos = false;
+ bool bSaveOtherPos = false;
+ const ::sw::mark::IMark* pBkmk = (pMarkAccess->getMarksBegin() + n)->get();
+ if( nsDelCntntType::DELCNT_CHKNOCNTNT & nDelCntntType )
+ {
+ if( pStt->nNode <= pBkmk->GetMarkPos().nNode &&
+ pBkmk->GetMarkPos().nNode < pEnd->nNode )
+ bSavePos = true;
+ if( pBkmk->IsExpanded() &&
+ pStt->nNode <= pBkmk->GetOtherMarkPos().nNode &&
+ pBkmk->GetOtherMarkPos().nNode < pEnd->nNode )
+ bSaveOtherPos = true;
+ }
+ else
+ {
+ // --> OD 2009-08-06 #i92125#
+ bool bKeepCrossRefBkmk( false );
+ {
+ if ( rMark.nNode == rPoint.nNode &&
+ ( IDocumentMarkAccess::GetType(*pBkmk) ==
+ IDocumentMarkAccess::CROSSREF_HEADING_BOOKMARK ||
+ IDocumentMarkAccess::GetType(*pBkmk) ==
+ IDocumentMarkAccess::CROSSREF_NUMITEM_BOOKMARK ) )
+ {
+ bKeepCrossRefBkmk = true;
+ }
+ }
+ if ( !bKeepCrossRefBkmk )
+ {
+ bool bMaybe = false;
+ if ( *pStt <= pBkmk->GetMarkPos() && pBkmk->GetMarkPos() <= *pEnd )
+ {
+ if( pBkmk->GetMarkPos() == *pEnd ||
+ ( *pStt == pBkmk->GetMarkPos() && pBkmk->IsExpanded() ) )
+ bMaybe = true;
+ else
+ bSavePos = true;
+ }
+ if( pBkmk->IsExpanded() &&
+ *pStt <= pBkmk->GetOtherMarkPos() && pBkmk->GetOtherMarkPos() <= *pEnd )
+ {
+ if( bSavePos || bSaveOtherPos ||
+ ( pBkmk->GetOtherMarkPos() < *pEnd && pBkmk->GetOtherMarkPos() > *pStt ) )
+ {
+ if( bMaybe )
+ bSavePos = true;
+ bSaveOtherPos = true;
+ }
+ }
+ }
+ // <--
+
+ // --> OD 2007-10-17 #i81002#
+ const bool bDifferentTxtNodesAtMarkAndPoint(
+ rMark.nNode != rPoint.nNode &&
+ rMark.nNode.GetNode().GetTxtNode() &&
+ rPoint.nNode.GetNode().GetTxtNode() );
+ // <--
+ if( !bSavePos && !bSaveOtherPos && bDifferentTxtNodesAtMarkAndPoint &&
+ dynamic_cast< const ::sw::mark::CrossRefBookmark* >(pBkmk))
+ {
+ // delete cross-reference bookmark at <pStt>, if only part of
+ // <pEnd> text node content is deleted.
+ if( pStt->nNode == pBkmk->GetMarkPos().nNode &&
+ pEnd->nContent.GetIndex() !=
+ pEnd->nNode.GetNode().GetTxtNode()->Len() )
+ {
+ bSavePos = true;
+ bSaveOtherPos = false;
+ }
+ // delete cross-reference bookmark at <pEnd>, if only part of
+ // <pStt> text node content is deleted.
+ else if( pEnd->nNode == pBkmk->GetMarkPos().nNode &&
+ pStt->nContent.GetIndex() != 0 )
+ {
+ bSavePos = true;
+ bSaveOtherPos = false;
+ }
+ }
+ }
+ if( bSavePos || bSaveOtherPos )
+ {
+ if( !pHistory )
+ pHistory = new SwHistory;
+
+ pHistory->Add( *pBkmk, bSavePos, bSaveOtherPos );
+ if(bSavePos &&
+ (bSaveOtherPos || !pBkmk->IsExpanded()))
+ {
+ pMarkAccess->deleteMark(pMarkAccess->getMarksBegin()+n);
+ n--;
+ }
+ }
+ }
+ }
+ }
+}
+
+
+// sicher eine vollstaendige Section im Undo-Nodes-Array
+
+SwUndoSaveSection::SwUndoSaveSection()
+ : pMvStt( 0 ), pRedlSaveData( 0 ), nMvLen( 0 ), nStartPos( ULONG_MAX )
+{
+}
+
+SwUndoSaveSection::~SwUndoSaveSection()
+{
+ if( pMvStt ) // loesche noch den Bereich aus dem UndoNodes Array
+ {
+ // SaveSection speichert den Inhalt in der PostIt-Section
+ SwNodes& rUNds = pMvStt->GetNode().GetNodes();
+ rUNds.Delete( *pMvStt, nMvLen );
+
+ delete pMvStt;
+ }
+ delete pRedlSaveData;
+}
+
+void SwUndoSaveSection::SaveSection( SwDoc* pDoc, const SwNodeIndex& rSttIdx )
+{
+ SwNodeRange aRg( rSttIdx.GetNode(), *rSttIdx.GetNode().EndOfSectionNode() );
+ SaveSection( pDoc, aRg );
+}
+
+
+void SwUndoSaveSection::SaveSection( SwDoc* , const SwNodeRange& rRange )
+{
+ SwPaM aPam( rRange.aStart, rRange.aEnd );
+
+ // loesche alle Fussnoten / FlyFrames / Bookmarks / Verzeichnisse
+ DelCntntIndex( *aPam.GetMark(), *aPam.GetPoint() );
+
+ pRedlSaveData = new SwRedlineSaveDatas;
+ if( !SwUndo::FillSaveData( aPam, *pRedlSaveData, sal_True, sal_True ))
+ delete pRedlSaveData, pRedlSaveData = 0;
+
+ nStartPos = rRange.aStart.GetIndex();
+
+ aPam.GetPoint()->nNode--;
+ aPam.GetMark()->nNode++;
+
+ SwCntntNode* pCNd = aPam.GetCntntNode( sal_False );
+ if( pCNd )
+ aPam.GetMark()->nContent.Assign( pCNd, 0 );
+ if( 0 != ( pCNd = aPam.GetCntntNode( sal_True )) )
+ aPam.GetPoint()->nContent.Assign( pCNd, pCNd->Len() );
+
+ // Positionen als SwIndex merken, damit im DTOR dieser Bereich
+ // entfernt werden kann !!
+ sal_uLong nEnd;
+ pMvStt = new SwNodeIndex( rRange.aStart );
+ MoveToUndoNds( aPam, pMvStt, 0, &nEnd, 0 );
+ nMvLen = nEnd - pMvStt->GetIndex() + 1;
+}
+
+void SwUndoSaveSection::RestoreSection( SwDoc* pDoc, SwNodeIndex* pIdx,
+ sal_uInt16 nSectType )
+{
+ if( ULONG_MAX != nStartPos ) // gab es ueberhaupt Inhalt ?
+ {
+ // ueberpruefe, ob der Inhalt an der alten Position steht
+ SwNodeIndex aSttIdx( pDoc->GetNodes(), nStartPos );
+// OSL_ENSURE( !pDoc->GetNodes()[ aSttIdx ]->GetCntntNode(),
+// "RestoreSection(): Position on content node");
+
+ // move den Inhalt aus dem UndoNodes-Array in den Fly
+ SwStartNode* pSttNd = pDoc->GetNodes().MakeEmptySection( aSttIdx,
+ (SwStartNodeType)nSectType );
+
+ RestoreSection( pDoc, SwNodeIndex( *pSttNd->EndOfSectionNode() ));
+
+ if( pIdx )
+ *pIdx = *pSttNd;
+ }
+}
+
+void SwUndoSaveSection::RestoreSection( SwDoc* pDoc, const SwNodeIndex& rInsPos )
+{
+ if( ULONG_MAX != nStartPos ) // gab es ueberhaupt Inhalt ?
+ {
+ SwPosition aInsPos( rInsPos );
+ sal_uLong nEnd = pMvStt->GetIndex() + nMvLen - 1;
+ MoveFromUndoNds( *pDoc, pMvStt->GetIndex(), 0, aInsPos, &nEnd, 0 );
+
+ // Indizies wieder zerstoren, Inhalt ist aus dem UndoNodes-Array
+ // entfernt worden.
+ DELETEZ( pMvStt );
+ nMvLen = 0;
+
+ if( pRedlSaveData )
+ {
+ SwUndo::SetSaveData( *pDoc, *pRedlSaveData );
+ delete pRedlSaveData, pRedlSaveData = 0;
+ }
+ }
+}
+
+ // sicher und setze die RedlineDaten
+
+SwRedlineSaveData::SwRedlineSaveData( SwComparePosition eCmpPos,
+ const SwPosition& rSttPos,
+ const SwPosition& rEndPos,
+ SwRedline& rRedl,
+ sal_Bool bCopyNext )
+ : SwUndRng( rRedl ),
+ SwRedlineData( rRedl.GetRedlineData(), bCopyNext )
+{
+ OSL_ENSURE( POS_OUTSIDE == eCmpPos ||
+ !rRedl.GetContentIdx(), "Redline mit Content" );
+
+ switch( eCmpPos )
+ {
+ case POS_OVERLAP_BEFORE: // Pos1 ueberlappt Pos2 am Anfang
+ nEndNode = rEndPos.nNode.GetIndex();
+ nEndCntnt = rEndPos.nContent.GetIndex();
+ break;
+ case POS_OVERLAP_BEHIND: // Pos1 ueberlappt Pos2 am Ende
+ nSttNode = rSttPos.nNode.GetIndex();
+ nSttCntnt = rSttPos.nContent.GetIndex();
+ break;
+
+ case POS_INSIDE: // Pos1 liegt vollstaendig in Pos2
+ nSttNode = rSttPos.nNode.GetIndex();
+ nSttCntnt = rSttPos.nContent.GetIndex();
+ nEndNode = rEndPos.nNode.GetIndex();
+ nEndCntnt = rEndPos.nContent.GetIndex();
+ break;
+
+ case POS_OUTSIDE: // Pos2 liegt vollstaendig in Pos1
+ if( rRedl.GetContentIdx() )
+ {
+ // dann den Bereich ins UndoArray verschieben und merken
+ SaveSection( rRedl.GetDoc(), *rRedl.GetContentIdx() );
+ rRedl.SetContentIdx( 0 );
+ }
+ break;
+
+ case POS_EQUAL: // Pos1 ist genauso gross wie Pos2
+ break;
+
+ default:
+ OSL_ENSURE( !this, "keine gueltigen Daten!" );
+ }
+
+#if OSL_DEBUG_LEVEL > 1
+ nRedlineCount = rSttPos.nNode.GetNode().GetDoc()->GetRedlineTbl().Count();
+#endif
+}
+
+SwRedlineSaveData::~SwRedlineSaveData()
+{
+}
+
+void SwRedlineSaveData::RedlineToDoc( SwPaM& rPam )
+{
+ SwDoc& rDoc = *rPam.GetDoc();
+ SwRedline* pRedl = new SwRedline( *this, rPam );
+
+ if( GetMvSttIdx() )
+ {
+ SwNodeIndex aIdx( rDoc.GetNodes() );
+ RestoreSection( &rDoc, &aIdx, SwNormalStartNode );
+ if( GetHistory() )
+ GetHistory()->Rollback( &rDoc );
+ pRedl->SetContentIdx( &aIdx );
+ }
+ SetPaM( *pRedl );
+ // erstmal die "alten" entfernen, damit im Append keine unerwarteten
+ // Dinge passieren, wie z.B. eine Delete in eigenen Insert. Dann wird
+ // naehmlich das gerade restaurierte wieder geloescht - nicht das gewollte
+ rDoc.DeleteRedline( *pRedl, false, USHRT_MAX );
+
+ RedlineMode_t eOld = rDoc.GetRedlineMode();
+ rDoc.SetRedlineMode_intern((RedlineMode_t)(eOld | nsRedlineMode_t::REDLINE_DONTCOMBINE_REDLINES));
+ //#i92154# let UI know about a new redline with comment
+ if (rDoc.GetDocShell() && (pRedl->GetComment() != String()) )
+ rDoc.GetDocShell()->Broadcast(SwRedlineHint(pRedl,SWREDLINE_INSERTED));
+ //
+#if OSL_DEBUG_LEVEL > 0
+ bool const bSuccess =
+#endif
+ rDoc.AppendRedline( pRedl, true );
+ OSL_ENSURE(bSuccess,
+ "SwRedlineSaveData::RedlineToDoc: insert redline failed");
+ rDoc.SetRedlineMode_intern( eOld );
+}
+
+sal_Bool SwUndo::FillSaveData( const SwPaM& rRange, SwRedlineSaveDatas& rSData,
+ sal_Bool bDelRange, sal_Bool bCopyNext )
+{
+ if( rSData.Count() )
+ rSData.DeleteAndDestroy( 0, rSData.Count() );
+
+ SwRedlineSaveData* pNewData;
+ const SwPosition *pStt = rRange.Start(), *pEnd = rRange.End();
+ const SwRedlineTbl& rTbl = rRange.GetDoc()->GetRedlineTbl();
+ sal_uInt16 n = 0;
+ rRange.GetDoc()->GetRedline( *pStt, &n );
+ for( ; n < rTbl.Count(); ++n )
+ {
+ SwRedline* pRedl = rTbl[ n ];
+ const SwPosition *pRStt = pRedl->Start(), *pREnd = pRedl->End();
+
+ SwComparePosition eCmpPos = ComparePosition( *pStt, *pEnd, *pRStt, *pREnd );
+ if( POS_BEFORE != eCmpPos && POS_BEHIND != eCmpPos &&
+ POS_COLLIDE_END != eCmpPos && POS_COLLIDE_START != eCmpPos )
+ {
+ pNewData = new SwRedlineSaveData( eCmpPos, *pStt, *pEnd,
+ *pRedl, bCopyNext );
+ rSData.Insert( pNewData, rSData.Count() );
+ }
+ }
+ if( rSData.Count() && bDelRange )
+ rRange.GetDoc()->DeleteRedline( rRange, false, USHRT_MAX );
+ return 0 != rSData.Count();
+}
+
+sal_Bool SwUndo::FillSaveDataForFmt( const SwPaM& rRange, SwRedlineSaveDatas& rSData )
+{
+ if( rSData.Count() )
+ rSData.DeleteAndDestroy( 0, rSData.Count() );
+
+ SwRedlineSaveData* pNewData;
+ const SwPosition *pStt = rRange.Start(), *pEnd = rRange.End();
+ const SwRedlineTbl& rTbl = rRange.GetDoc()->GetRedlineTbl();
+ sal_uInt16 n = 0;
+ rRange.GetDoc()->GetRedline( *pStt, &n );
+ for( ; n < rTbl.Count(); ++n )
+ {
+ SwRedline* pRedl = rTbl[ n ];
+ if( nsRedlineType_t::REDLINE_FORMAT == pRedl->GetType() )
+ {
+ const SwPosition *pRStt = pRedl->Start(), *pREnd = pRedl->End();
+
+ SwComparePosition eCmpPos = ComparePosition( *pStt, *pEnd, *pRStt, *pREnd );
+ if( POS_BEFORE != eCmpPos && POS_BEHIND != eCmpPos &&
+ POS_COLLIDE_END != eCmpPos && POS_COLLIDE_START != eCmpPos )
+ {
+ pNewData = new SwRedlineSaveData( eCmpPos, *pStt, *pEnd,
+ *pRedl, sal_True );
+ rSData.Insert( pNewData, rSData.Count() );
+ }
+
+
+ }
+ }
+ return 0 != rSData.Count();
+}
+
+void SwUndo::SetSaveData( SwDoc& rDoc, const SwRedlineSaveDatas& rSData )
+{
+ RedlineMode_t eOld = rDoc.GetRedlineMode();
+ rDoc.SetRedlineMode_intern( (RedlineMode_t)(( eOld & ~nsRedlineMode_t::REDLINE_IGNORE) | nsRedlineMode_t::REDLINE_ON ));
+ SwPaM aPam( rDoc.GetNodes().GetEndOfContent() );
+
+ for( sal_uInt16 n = rSData.Count(); n; )
+ rSData[ --n ]->RedlineToDoc( aPam );
+
+#if OSL_DEBUG_LEVEL > 1
+ // check redline count against count saved in RedlineSaveData object
+ OSL_ENSURE( (rSData.Count() == 0) ||
+ (rSData[0]->nRedlineCount == rDoc.GetRedlineTbl().Count()),
+ "redline count not restored properly" );
+#endif
+
+ rDoc.SetRedlineMode_intern( eOld );
+}
+
+sal_Bool SwUndo::HasHiddenRedlines( const SwRedlineSaveDatas& rSData )
+{
+ for( sal_uInt16 n = rSData.Count(); n; )
+ if( rSData[ --n ]->GetMvSttIdx() )
+ return sal_True;
+ return sal_False;
+}
+
+sal_Bool SwUndo::CanRedlineGroup( SwRedlineSaveDatas& rCurr,
+ const SwRedlineSaveDatas& rCheck, sal_Bool bCurrIsEnd )
+{
+ sal_Bool bRet = sal_False;
+ sal_uInt16 n;
+
+ if( rCurr.Count() == rCheck.Count() )
+ {
+ bRet = sal_True;
+ for( n = 0; n < rCurr.Count(); ++n )
+ {
+ const SwRedlineSaveData& rSet = *rCurr[ n ];
+ const SwRedlineSaveData& rGet = *rCheck[ n ];
+ if( rSet.nSttNode != rGet.nSttNode ||
+ rSet.GetMvSttIdx() || rGet.GetMvSttIdx() ||
+ ( bCurrIsEnd ? rSet.nSttCntnt != rGet.nEndCntnt
+ : rSet.nEndCntnt != rGet.nSttCntnt ) ||
+ !rGet.CanCombine( rSet ) )
+ {
+ bRet = sal_False;
+ break;
+ }
+ }
+
+ if( bRet )
+ for( n = 0; n < rCurr.Count(); ++n )
+ {
+ SwRedlineSaveData& rSet = *rCurr[ n ];
+ const SwRedlineSaveData& rGet = *rCheck[ n ];
+ if( bCurrIsEnd )
+ rSet.nSttCntnt = rGet.nSttCntnt;
+ else
+ rSet.nEndCntnt = rGet.nEndCntnt;
+ }
+ }
+ return bRet;
+}
+
+// #111827#
+String ShortenString(const String & rStr, xub_StrLen nLength, const String & rFillStr)
+{
+ OSL_ENSURE( nLength - rFillStr.Len() >= 2, "improper arguments");
+
+ String aResult;
+
+ if (rStr.Len() <= nLength)
+ aResult = rStr;
+ else
+ {
+ long nTmpLength = nLength - rFillStr.Len();
+ if ( nTmpLength < 2 )
+ nTmpLength = 2;
+
+ nLength = static_cast<xub_StrLen>(nTmpLength);
+
+ const xub_StrLen nFrontLen = nLength - nLength / 2;
+ const xub_StrLen nBackLen = nLength - nFrontLen;
+
+ aResult += rStr.Copy(0, nFrontLen);
+ aResult += rFillStr;
+ aResult += rStr.Copy(rStr.Len() - nBackLen, nBackLen);
+ }
+
+ return aResult;
+}
+
+static bool lcl_IsSpecialCharacter(sal_Unicode nChar)
+{
+ switch (nChar)
+ {
+ case CH_TXTATR_BREAKWORD:
+ case CH_TXTATR_INWORD:
+ case CH_TXTATR_TAB:
+ case CH_TXTATR_NEWLINE:
+ return true;
+
+ default:
+ break;
+ }
+
+ return false;
+}
+
+static String lcl_DenotedPortion(String rStr, xub_StrLen nStart,
+ xub_StrLen nEnd)
+{
+ String aResult;
+
+ if (nEnd - nStart > 0)
+ {
+ sal_Unicode cLast = rStr.GetChar(nEnd - 1);
+ if (lcl_IsSpecialCharacter(cLast))
+ {
+ switch(cLast)
+ {
+ case CH_TXTATR_TAB:
+ aResult += String(SW_RES(STR_UNDO_TABS));
+
+ break;
+ case CH_TXTATR_NEWLINE:
+ aResult += String(SW_RES(STR_UNDO_NLS));
+
+ break;
+
+ case CH_TXTATR_INWORD:
+ case CH_TXTATR_BREAKWORD:
+ aResult += UNDO_ARG2;
+
+ break;
+
+ }
+ SwRewriter aRewriter;
+ aRewriter.AddRule(UNDO_ARG1,
+ String::CreateFromInt32(nEnd - nStart));
+ aResult = aRewriter.Apply(aResult);
+ }
+ else
+ {
+ aResult = String(SW_RES(STR_START_QUOTE));
+ aResult += rStr.Copy(nStart, nEnd - nStart);
+ aResult += String(SW_RES(STR_END_QUOTE));
+ }
+ }
+
+ return aResult;
+}
+
+String DenoteSpecialCharacters(const String & rStr)
+{
+ String aResult;
+
+ if (rStr.Len() > 0)
+ {
+ bool bStart = false;
+ xub_StrLen nStart = 0;
+ sal_Unicode cLast = 0;
+
+ for (xub_StrLen i = 0; i < rStr.Len(); i++)
+ {
+ if (lcl_IsSpecialCharacter(rStr.GetChar(i)))
+ {
+ if (cLast != rStr.GetChar(i))
+ bStart = true;
+
+ }
+ else
+ {
+ if (lcl_IsSpecialCharacter(cLast))
+ bStart = true;
+ }
+
+ if (bStart)
+ {
+ aResult += lcl_DenotedPortion(rStr, nStart, i);
+
+ nStart = i;
+ bStart = false;
+ }
+
+ cLast = rStr.GetChar(i);
+ }
+
+ aResult += lcl_DenotedPortion(rStr, nStart, rStr.Len());
+ }
+ else
+ aResult = UNDO_ARG2;
+
+ return aResult;
+}
+
+bool IsDestroyFrameAnchoredAtChar(SwPosition const & rAnchorPos,
+ SwPosition const & rStart, SwPosition const & rEnd,
+ DelCntntType const nDelCntntType)
+{
+
+ // Here we identified the objects to destroy:
+ // - anchored between start and end of the selection
+ // - anchored in start of the selection with "CheckNoContent"
+ // - anchored in start of sel. and the selection start at pos 0
+ return (rAnchorPos.nNode < rEnd.nNode)
+ && ( (nsDelCntntType::DELCNT_CHKNOCNTNT & nDelCntntType)
+ || (rStart.nNode < rAnchorPos.nNode)
+ || !rStart.nContent.GetIndex()
+ );
+}
+
+const String UNDO_ARG1("$1", RTL_TEXTENCODING_ASCII_US);
+const String UNDO_ARG2("$2", RTL_TEXTENCODING_ASCII_US);
+const String UNDO_ARG3("$3", RTL_TEXTENCODING_ASCII_US);
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/undo/undobj1.cxx b/sw/source/core/undo/undobj1.cxx
new file mode 100644
index 000000000000..49471cf4501f
--- /dev/null
+++ b/sw/source/core/undo/undobj1.cxx
@@ -0,0 +1,729 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+#include <svl/itemiter.hxx>
+
+#include <hintids.hxx>
+#include <hints.hxx>
+#include <fmtflcnt.hxx>
+#include <fmtanchr.hxx>
+#include <fmtcntnt.hxx>
+#include <txtflcnt.hxx>
+#include <frmfmt.hxx>
+#include <flyfrm.hxx>
+#include <UndoCore.hxx>
+#include <UndoDraw.hxx>
+#include <rolbck.hxx> // fuer die Attribut History
+#include <doc.hxx>
+#include <docary.hxx>
+#include <rootfrm.hxx>
+#include <swundo.hxx> // fuer die UndoIds
+#include <pam.hxx>
+#include <ndtxt.hxx>
+// OD 26.06.2003 #108784#
+#include <dcontact.hxx>
+#include <ndole.hxx>
+
+
+//---------------------------------------------------------------------
+// SwUndoLayBase /////////////////////////////////////////////////////////
+
+SwUndoFlyBase::SwUndoFlyBase( SwFrmFmt* pFormat, SwUndoId nUndoId )
+ : SwUndo( nUndoId ), pFrmFmt( pFormat )
+{
+}
+
+SwUndoFlyBase::~SwUndoFlyBase()
+{
+ if( bDelFmt ) // loeschen waehrend eines Undo's ??
+ delete pFrmFmt;
+}
+
+void SwUndoFlyBase::InsFly(::sw::UndoRedoContext & rContext, bool bShowSelFrm)
+{
+ SwDoc *const pDoc = & rContext.GetDoc();
+
+ // ins Array wieder eintragen
+ SwSpzFrmFmts& rFlyFmts = *(SwSpzFrmFmts*)pDoc->GetSpzFrmFmts();
+ rFlyFmts.Insert( pFrmFmt, rFlyFmts.Count() );
+
+ // OD 26.06.2003 #108784# - insert 'master' drawing object into drawing page
+ if ( RES_DRAWFRMFMT == pFrmFmt->Which() )
+ {
+ SwDrawContact* pDrawContact =
+ static_cast<SwDrawContact*>(pFrmFmt->FindContactObj());
+ if ( pDrawContact )
+ {
+ pDrawContact->InsertMasterIntoDrawPage();
+ // --> OD 2005-01-31 #i40845# - follow-up of #i35635#
+ // move object to visible layer
+ pDrawContact->MoveObjToVisibleLayer( pDrawContact->GetMaster() );
+ // <--
+ }
+ }
+
+ SwFmtAnchor aAnchor( (RndStdIds)nRndId );
+
+ if (FLY_AT_PAGE == nRndId)
+ {
+ aAnchor.SetPageNum( (sal_uInt16)nNdPgPos );
+ }
+ else
+ {
+ SwPosition aNewPos(pDoc->GetNodes().GetEndOfContent());
+ aNewPos.nNode = nNdPgPos;
+ if ((FLY_AS_CHAR == nRndId) || (FLY_AT_CHAR == nRndId))
+ {
+ aNewPos.nContent.Assign( aNewPos.nNode.GetNode().GetCntntNode(),
+ nCntPos );
+ }
+ aAnchor.SetAnchor( &aNewPos );
+ }
+
+ pFrmFmt->SetFmtAttr( aAnchor ); // Anker neu setzen
+
+ if( RES_DRAWFRMFMT != pFrmFmt->Which() )
+ {
+ // Content holen und -Attribut neu setzen
+ SwNodeIndex aIdx( pDoc->GetNodes() );
+ RestoreSection( pDoc, &aIdx, SwFlyStartNode );
+ pFrmFmt->SetFmtAttr( SwFmtCntnt( aIdx.GetNode().GetStartNode() ));
+ }
+
+ //JP 18.12.98: Bug 60505 - InCntntAttribut erst setzen, wenn der Inhalt
+ // vorhanden ist! Sonst wuerde das Layout den Fly vorher
+ // formatieren, aber keine Inhalt finden; so geschene bei
+ // Grafiken aus dem Internet
+ if (FLY_AS_CHAR == nRndId)
+ {
+ // es muss mindestens das Attribut im TextNode stehen
+ SwCntntNode* pCNd = aAnchor.GetCntntAnchor()->nNode.GetNode().GetCntntNode();
+ OSL_ENSURE( pCNd->IsTxtNode(), "no Text Node at position." );
+ SwFmtFlyCnt aFmt( pFrmFmt );
+ static_cast<SwTxtNode*>(pCNd)->InsertItem( aFmt, nCntPos, nCntPos );
+ }
+
+ pFrmFmt->MakeFrms();
+
+ if( bShowSelFrm )
+ {
+ rContext.SetSelections(pFrmFmt, 0);
+ }
+
+ if( GetHistory() )
+ GetHistory()->Rollback( pDoc );
+
+ switch( nRndId )
+ {
+ case FLY_AS_CHAR:
+ case FLY_AT_CHAR:
+ {
+ const SwFmtAnchor& rAnchor = pFrmFmt->GetAnchor();
+ nNdPgPos = rAnchor.GetCntntAnchor()->nNode.GetIndex();
+ nCntPos = rAnchor.GetCntntAnchor()->nContent.GetIndex();
+ }
+ break;
+ case FLY_AT_PARA:
+ case FLY_AT_FLY:
+ {
+ const SwFmtAnchor& rAnchor = pFrmFmt->GetAnchor();
+ nNdPgPos = rAnchor.GetCntntAnchor()->nNode.GetIndex();
+ }
+ break;
+ case FLY_AT_PAGE:
+ break;
+ }
+ bDelFmt = sal_False;
+}
+
+void SwUndoFlyBase::DelFly( SwDoc* pDoc )
+{
+ bDelFmt = sal_True; // im DTOR das Format loeschen
+ pFrmFmt->DelFrms(); // Frms vernichten.
+
+ // alle Uno-Objecte sollten sich jetzt abmelden
+ {
+ SwPtrMsgPoolItem aMsgHint( RES_REMOVE_UNO_OBJECT, pFrmFmt );
+ pFrmFmt->ModifyNotification( &aMsgHint, &aMsgHint );
+ }
+
+ if ( RES_DRAWFRMFMT != pFrmFmt->Which() )
+ {
+ // gibt es ueberhaupt Inhalt, dann sicher diesen
+ const SwFmtCntnt& rCntnt = pFrmFmt->GetCntnt();
+ OSL_ENSURE( rCntnt.GetCntntIdx(), "Fly ohne Inhalt" );
+
+ SaveSection( pDoc, *rCntnt.GetCntntIdx() );
+ ((SwFmtCntnt&)rCntnt).SetNewCntntIdx( (const SwNodeIndex*)0 );
+ }
+ // OD 02.07.2003 #108784# - remove 'master' drawing object from drawing page
+ else if ( RES_DRAWFRMFMT == pFrmFmt->Which() )
+ {
+ SwDrawContact* pDrawContact =
+ static_cast<SwDrawContact*>(pFrmFmt->FindContactObj());
+ if ( pDrawContact )
+ {
+ pDrawContact->RemoveMasterFromDrawPage();
+ }
+ }
+
+ const SwFmtAnchor& rAnchor = pFrmFmt->GetAnchor();
+ const SwPosition* pPos = rAnchor.GetCntntAnchor();
+ // die Positionen im Nodes-Array haben sich verschoben
+ nRndId = static_cast<sal_uInt16>(rAnchor.GetAnchorId());
+ if (FLY_AS_CHAR == nRndId)
+ {
+ nNdPgPos = pPos->nNode.GetIndex();
+ nCntPos = pPos->nContent.GetIndex();
+ SwTxtNode *const pTxtNd = pPos->nNode.GetNode().GetTxtNode();
+ OSL_ENSURE( pTxtNd, "Kein Textnode gefunden" );
+ SwTxtFlyCnt* const pAttr = static_cast<SwTxtFlyCnt*>(
+ pTxtNd->GetTxtAttrForCharAt( nCntPos, RES_TXTATR_FLYCNT ) );
+ // Attribut steht noch im TextNode, loeschen
+ if( pAttr && pAttr->GetFlyCnt().GetFrmFmt() == pFrmFmt )
+ {
+ // Pointer auf 0, nicht loeschen
+ ((SwFmtFlyCnt&)pAttr->GetFlyCnt()).SetFlyFmt();
+ SwIndex aIdx( pPos->nContent );
+ pTxtNd->EraseText( aIdx, 1 );
+ }
+ }
+ else if (FLY_AT_CHAR == nRndId)
+ {
+ nNdPgPos = pPos->nNode.GetIndex();
+ nCntPos = pPos->nContent.GetIndex();
+ }
+ else if ((FLY_AT_PARA == nRndId) || (FLY_AT_FLY == nRndId))
+ {
+ nNdPgPos = pPos->nNode.GetIndex();
+ }
+ else
+ {
+ nNdPgPos = rAnchor.GetPageNum();
+ }
+
+ pFrmFmt->ResetFmtAttr( RES_ANCHOR ); // Anchor loeschen
+
+
+ // aus dem Array austragen
+ SwSpzFrmFmts& rFlyFmts = *(SwSpzFrmFmts*)pDoc->GetSpzFrmFmts();
+ rFlyFmts.Remove( rFlyFmts.GetPos( pFrmFmt ));
+}
+
+// SwUndoInsLayFmt ///////////////////////////////////////////////////////
+
+SwUndoInsLayFmt::SwUndoInsLayFmt( SwFrmFmt* pFormat, sal_uLong nNodeIdx, xub_StrLen nCntIdx )
+ : SwUndoFlyBase( pFormat, RES_DRAWFRMFMT == pFormat->Which() ?
+ UNDO_INSDRAWFMT : UNDO_INSLAYFMT ),
+ mnCrsrSaveIndexPara( nNodeIdx ), mnCrsrSaveIndexPos( nCntIdx )
+{
+ const SwFmtAnchor& rAnchor = pFrmFmt->GetAnchor();
+ nRndId = static_cast<sal_uInt16>(rAnchor.GetAnchorId());
+ bDelFmt = sal_False;
+ switch( nRndId )
+ {
+ case FLY_AT_PAGE:
+ nNdPgPos = rAnchor.GetPageNum();
+ break;
+ case FLY_AT_PARA:
+ case FLY_AT_FLY:
+ nNdPgPos = rAnchor.GetCntntAnchor()->nNode.GetIndex();
+ break;
+ case FLY_AS_CHAR:
+ case FLY_AT_CHAR:
+ {
+ const SwPosition* pPos = rAnchor.GetCntntAnchor();
+ nCntPos = pPos->nContent.GetIndex();
+ nNdPgPos = pPos->nNode.GetIndex();
+ }
+ break;
+ default:
+ OSL_FAIL( "Was denn fuer ein FlyFrame?" );
+ }
+}
+
+SwUndoInsLayFmt::~SwUndoInsLayFmt()
+{
+}
+
+void SwUndoInsLayFmt::UndoImpl(::sw::UndoRedoContext & rContext)
+{
+ SwDoc & rDoc(rContext.GetDoc());
+ const SwFmtCntnt& rCntnt = pFrmFmt->GetCntnt();
+ if( rCntnt.GetCntntIdx() ) // kein Inhalt
+ {
+ bool bRemoveIdx = true;
+ if( mnCrsrSaveIndexPara > 0 )
+ {
+ SwTxtNode *const pNode =
+ rDoc.GetNodes()[mnCrsrSaveIndexPara]->GetTxtNode();
+ if( pNode )
+ {
+ SwNodeIndex aIdx( rDoc.GetNodes(),
+ rCntnt.GetCntntIdx()->GetIndex() );
+ SwNodeIndex aEndIdx( rDoc.GetNodes(),
+ aIdx.GetNode().EndOfSectionIndex() );
+ SwIndex aIndex( pNode, mnCrsrSaveIndexPos );
+ SwPosition aPos( *pNode, aIndex );
+ rDoc.CorrAbs( aIdx, aEndIdx, aPos, sal_True );
+ bRemoveIdx = false;
+ }
+ }
+ if( bRemoveIdx )
+ {
+ RemoveIdxFromSection( rDoc, rCntnt.GetCntntIdx()->GetIndex() );
+ }
+ }
+ DelFly(& rDoc);
+}
+
+void SwUndoInsLayFmt::RedoImpl(::sw::UndoRedoContext & rContext)
+{
+ InsFly(rContext);
+}
+
+void SwUndoInsLayFmt::RepeatImpl(::sw::RepeatContext & rContext)
+{
+ SwDoc *const pDoc = & rContext.GetDoc();
+ // erfrage und setze den Anker neu
+ SwFmtAnchor aAnchor( pFrmFmt->GetAnchor() );
+ if ((FLY_AT_PARA == aAnchor.GetAnchorId()) ||
+ (FLY_AT_CHAR == aAnchor.GetAnchorId()) ||
+ (FLY_AS_CHAR == aAnchor.GetAnchorId()))
+ {
+ SwPosition aPos( *rContext.GetRepeatPaM().GetPoint() );
+ if (FLY_AT_PARA == aAnchor.GetAnchorId())
+ {
+ aPos.nContent.Assign( 0, 0 );
+ }
+ aAnchor.SetAnchor( &aPos );
+ }
+ else if( FLY_AT_FLY == aAnchor.GetAnchorId() )
+ {
+ SwStartNode const*const pSttNd =
+ rContext.GetRepeatPaM().GetNode()->FindFlyStartNode();
+ if( pSttNd )
+ {
+ SwPosition aPos( *pSttNd );
+ aAnchor.SetAnchor( &aPos );
+ }
+ else
+ {
+ return ;
+ }
+ }
+ else if (FLY_AT_PAGE == aAnchor.GetAnchorId())
+ {
+ aAnchor.SetPageNum( pDoc->GetCurrentLayout()->GetCurrPage( &rContext.GetRepeatPaM() ));
+ }
+ else {
+ OSL_FAIL( "was fuer ein Anker ist es denn nun?" );
+ }
+
+ SwFrmFmt* pFlyFmt = pDoc->CopyLayoutFmt( *pFrmFmt, aAnchor, true, true );
+ (void) pFlyFmt;
+//FIXME nobody ever did anything with this selection:
+// rContext.SetSelections(pFlyFmt, 0);
+}
+
+// #111827#
+String SwUndoInsLayFmt::GetComment() const
+{
+ String aResult;
+
+ // HACK: disable caching:
+ // the SfxUndoManager calls GetComment() too early: the pFrmFmt does not
+ // have a SwDrawContact yet, so it will fall back to SwUndo::GetComment(),
+ // which sets pComment to a wrong value.
+// if (! pComment)
+ if (true)
+ {
+ /*
+ If frame format is present and has an SdrObject use the undo
+ comment of the SdrObject. Otherwise use the default comment.
+ */
+
+ bool bDone = false;
+ if (pFrmFmt)
+ {
+ const SdrObject * pSdrObj = pFrmFmt->FindSdrObject();
+ if ( pSdrObj )
+ {
+ aResult = SdrUndoNewObj::GetComment( *pSdrObj );
+ bDone = true;
+ }
+ }
+
+ if (! bDone)
+ aResult = SwUndo::GetComment();
+ }
+ else
+ aResult = *pComment;
+
+ return aResult;
+}
+
+// SwUndoDelLayFmt ///////////////////////////////////////////////////////
+
+static SwUndoId
+lcl_GetSwUndoId(SwFrmFmt *const pFrmFmt)
+{
+ if (RES_DRAWFRMFMT != pFrmFmt->Which())
+ {
+ const SwFmtCntnt& rCntnt = pFrmFmt->GetCntnt();
+ OSL_ENSURE( rCntnt.GetCntntIdx(), "Fly without content" );
+
+ SwNodeIndex firstNode(*rCntnt.GetCntntIdx(), 1);
+ SwNoTxtNode *const pNoTxtNode(firstNode.GetNode().GetNoTxtNode());
+ if (pNoTxtNode && pNoTxtNode->IsGrfNode())
+ {
+ return UNDO_DELGRF;
+ }
+ else if (pNoTxtNode && pNoTxtNode->IsOLENode())
+ {
+ // surprisingly not UNDO_DELOLE, which does not seem to work
+ return UNDO_DELETE;
+ }
+ }
+ return UNDO_DELLAYFMT;
+}
+
+SwUndoDelLayFmt::SwUndoDelLayFmt( SwFrmFmt* pFormat )
+ : SwUndoFlyBase( pFormat, lcl_GetSwUndoId(pFormat) )
+ , bShowSelFrm( sal_True )
+{
+ SwDoc* pDoc = pFormat->GetDoc();
+ DelFly( pDoc );
+}
+
+SwRewriter SwUndoDelLayFmt::GetRewriter() const
+{
+ SwRewriter aRewriter;
+
+ SwDoc * pDoc = pFrmFmt->GetDoc();
+
+ if (pDoc)
+ {
+ SwNodeIndex* pIdx = GetMvSttIdx();
+ if( 1 == GetMvNodeCnt() && pIdx)
+ {
+ SwNode *const pNd = & pIdx->GetNode();
+
+ if ( pNd->IsNoTxtNode() && pNd->IsOLENode())
+ {
+ SwOLENode * pOLENd = pNd->GetOLENode();
+
+ aRewriter.AddRule(UNDO_ARG1, pOLENd->GetDescription());
+ }
+ }
+ }
+
+ return aRewriter;
+}
+
+void SwUndoDelLayFmt::UndoImpl(::sw::UndoRedoContext & rContext)
+{
+ InsFly( rContext, bShowSelFrm );
+}
+
+void SwUndoDelLayFmt::RedoImpl(::sw::UndoRedoContext & rContext)
+{
+ SwDoc & rDoc(rContext.GetDoc());
+ const SwFmtCntnt& rCntnt = pFrmFmt->GetCntnt();
+ if( rCntnt.GetCntntIdx() ) // kein Inhalt
+ {
+ RemoveIdxFromSection(rDoc, rCntnt.GetCntntIdx()->GetIndex());
+ }
+
+ DelFly(& rDoc);
+}
+
+void SwUndoDelLayFmt::RedoForRollback()
+{
+ const SwFmtCntnt& rCntnt = pFrmFmt->GetCntnt();
+ if( rCntnt.GetCntntIdx() ) // kein Inhalt
+ RemoveIdxFromSection( *pFrmFmt->GetDoc(),
+ rCntnt.GetCntntIdx()->GetIndex() );
+
+ DelFly( pFrmFmt->GetDoc() );
+}
+
+// SwUndoSetFlyFmt ///////////////////////////////////////////////////////
+
+SwUndoSetFlyFmt::SwUndoSetFlyFmt( SwFrmFmt& rFlyFmt, SwFrmFmt& rNewFrmFmt )
+ : SwUndo( UNDO_SETFLYFRMFMT ), SwClient( &rFlyFmt ), pFrmFmt( &rFlyFmt ),
+ pOldFmt( (SwFrmFmt*)rFlyFmt.DerivedFrom() ), pNewFmt( &rNewFrmFmt ),
+ pItemSet( new SfxItemSet( *rFlyFmt.GetAttrSet().GetPool(),
+ rFlyFmt.GetAttrSet().GetRanges() )),
+ nOldNode( 0 ), nNewNode( 0 ),
+ nOldCntnt( 0 ), nNewCntnt( 0 ),
+ nOldAnchorTyp( 0 ), nNewAnchorTyp( 0 ), bAnchorChgd( sal_False )
+{
+}
+
+SwRewriter SwUndoSetFlyFmt::GetRewriter() const
+{
+ SwRewriter aRewriter;
+
+ if (pNewFmt)
+ aRewriter.AddRule(UNDO_ARG1, pNewFmt->GetName());
+
+ return aRewriter;
+}
+
+
+SwUndoSetFlyFmt::~SwUndoSetFlyFmt()
+{
+ delete pItemSet;
+}
+
+void SwUndoSetFlyFmt::DeRegisterFromFormat( SwFmt& rFmt )
+{
+ rFmt.Remove(this);
+}
+
+void SwUndoSetFlyFmt::GetAnchor( SwFmtAnchor& rAnchor,
+ sal_uLong nNode, xub_StrLen nCntnt )
+{
+ RndStdIds nAnchorTyp = rAnchor.GetAnchorId();
+ if (FLY_AT_PAGE != nAnchorTyp)
+ {
+ SwNode* pNd = pFrmFmt->GetDoc()->GetNodes()[ nNode ];
+
+ if( FLY_AT_FLY == nAnchorTyp
+ ? ( !pNd->IsStartNode() || SwFlyStartNode !=
+ ((SwStartNode*)pNd)->GetStartNodeType() )
+ : !pNd->IsTxtNode() )
+ {
+ pNd = 0; // invalid position
+ }
+ else
+ {
+ SwPosition aPos( *pNd );
+ if ((FLY_AS_CHAR == nAnchorTyp) ||
+ (FLY_AT_CHAR == nAnchorTyp))
+ {
+ if ( nCntnt > static_cast<SwTxtNode*>(pNd)->GetTxt().Len() )
+ {
+ pNd = 0; // invalid position
+ }
+ else
+ {
+ aPos.nContent.Assign(static_cast<SwTxtNode*>(pNd), nCntnt);
+ }
+ }
+ if ( pNd )
+ {
+ rAnchor.SetAnchor( &aPos );
+ }
+ }
+
+ if( !pNd )
+ {
+ // ungueltige Position - setze auf 1. Seite
+ rAnchor.SetType( FLY_AT_PAGE );
+ rAnchor.SetPageNum( 1 );
+ }
+ }
+ else
+ rAnchor.SetPageNum( nCntnt );
+}
+
+void SwUndoSetFlyFmt::UndoImpl(::sw::UndoRedoContext & rContext)
+{
+ SwDoc & rDoc = rContext.GetDoc();
+
+ // ist das neue Format noch vorhanden ??
+ if( USHRT_MAX != rDoc.GetFrmFmts()->GetPos( (const SwFrmFmtPtr)pOldFmt ) )
+ {
+ if( bAnchorChgd )
+ pFrmFmt->DelFrms();
+
+ if( pFrmFmt->DerivedFrom() != pOldFmt )
+ pFrmFmt->SetDerivedFrom( pOldFmt );
+
+ SfxItemIter aIter( *pItemSet );
+ const SfxPoolItem* pItem = aIter.GetCurItem();
+ while( pItem )
+ {
+ if( IsInvalidItem( pItem ))
+ pFrmFmt->ResetFmtAttr( pItemSet->GetWhichByPos(
+ aIter.GetCurPos() ));
+ else
+ pFrmFmt->SetFmtAttr( *pItem );
+
+ if( aIter.IsAtEnd() )
+ break;
+ pItem = aIter.NextItem();
+ }
+
+ if( bAnchorChgd )
+ {
+ const SwFmtAnchor& rOldAnch = pFrmFmt->GetAnchor();
+ if (FLY_AS_CHAR == rOldAnch.GetAnchorId())
+ {
+ // Bei InCntnt's wird es spannend: Das TxtAttribut muss
+ // vernichtet werden. Leider reisst dies neben den Frms
+ // auch noch das Format mit in sein Grab. Um dass zu
+ // unterbinden loesen wir vorher die Verbindung zwischen
+ // Attribut und Format.
+ const SwPosition *pPos = rOldAnch.GetCntntAnchor();
+ SwTxtNode *pTxtNode = pPos->nNode.GetNode().GetTxtNode();
+ OSL_ENSURE( pTxtNode->HasHints(), "Missing FlyInCnt-Hint." );
+ const xub_StrLen nIdx = pPos->nContent.GetIndex();
+ SwTxtAttr * pHnt = pTxtNode->GetTxtAttrForCharAt(
+ nIdx, RES_TXTATR_FLYCNT );
+ OSL_ENSURE( pHnt && pHnt->Which() == RES_TXTATR_FLYCNT,
+ "Missing FlyInCnt-Hint." );
+ OSL_ENSURE( pHnt && pHnt->GetFlyCnt().GetFrmFmt() == pFrmFmt,
+ "Wrong TxtFlyCnt-Hint." );
+ const_cast<SwFmtFlyCnt&>(pHnt->GetFlyCnt()).SetFlyFmt();
+
+ // Die Verbindung ist geloest, jetzt muss noch das Attribut
+ // vernichtet werden.
+ pTxtNode->DeleteAttributes( RES_TXTATR_FLYCNT, nIdx, nIdx );
+ }
+
+ // Anker umsetzen
+ SwFmtAnchor aNewAnchor( (RndStdIds) nOldAnchorTyp );
+ GetAnchor( aNewAnchor, nOldNode, nOldCntnt );
+ pFrmFmt->SetFmtAttr( aNewAnchor );
+
+ if (FLY_AS_CHAR == aNewAnchor.GetAnchorId())
+ {
+ SwPosition* pPos = (SwPosition*)aNewAnchor.GetCntntAnchor();
+ SwFmtFlyCnt aFmt( pFrmFmt );
+ pPos->nNode.GetNode().GetTxtNode()->InsertItem( aFmt,
+ nOldCntnt, 0 );
+ }
+
+ pFrmFmt->MakeFrms();
+ }
+ rContext.SetSelections(pFrmFmt, 0);
+ }
+}
+
+void SwUndoSetFlyFmt::RedoImpl(::sw::UndoRedoContext & rContext)
+{
+ SwDoc & rDoc = rContext.GetDoc();
+
+ // ist das neue Format noch vorhanden ??
+ if( USHRT_MAX != rDoc.GetFrmFmts()->GetPos( (const SwFrmFmtPtr)pNewFmt ) )
+ {
+
+ if( bAnchorChgd )
+ {
+ SwFmtAnchor aNewAnchor( (RndStdIds) nNewAnchorTyp );
+ GetAnchor( aNewAnchor, nNewNode, nNewCntnt );
+ SfxItemSet aSet( rDoc.GetAttrPool(), aFrmFmtSetRange );
+ aSet.Put( aNewAnchor );
+ rDoc.SetFrmFmtToFly( *pFrmFmt, *pNewFmt, &aSet );
+ }
+ else
+ rDoc.SetFrmFmtToFly( *pFrmFmt, *pNewFmt, 0 );
+
+ rContext.SetSelections(pFrmFmt, 0);
+ }
+}
+
+void SwUndoSetFlyFmt::PutAttr( sal_uInt16 nWhich, const SfxPoolItem* pItem )
+{
+ if( pItem && pItem != GetDfltAttr( nWhich ) )
+ {
+ // Sonderbehandlung fuer den Anchor
+ if( RES_ANCHOR == nWhich )
+ {
+ // nur den 1. Ankerwechsel vermerken
+ OSL_ENSURE( !bAnchorChgd, "mehrfacher Ankerwechsel nicht erlaubt!" );
+
+ bAnchorChgd = sal_True;
+
+ const SwFmtAnchor* pAnchor = (SwFmtAnchor*)pItem;
+ switch( nOldAnchorTyp = static_cast<sal_uInt16>(pAnchor->GetAnchorId()) )
+ {
+ case FLY_AS_CHAR:
+ case FLY_AT_CHAR:
+ nOldCntnt = pAnchor->GetCntntAnchor()->nContent.GetIndex();
+ case FLY_AT_PARA:
+ case FLY_AT_FLY:
+ nOldNode = pAnchor->GetCntntAnchor()->nNode.GetIndex();
+ break;
+
+ default:
+ nOldCntnt = pAnchor->GetPageNum();
+ }
+
+ pAnchor = (SwFmtAnchor*)&pFrmFmt->GetAnchor();
+ switch( nNewAnchorTyp = static_cast<sal_uInt16>(pAnchor->GetAnchorId()) )
+ {
+ case FLY_AS_CHAR:
+ case FLY_AT_CHAR:
+ nNewCntnt = pAnchor->GetCntntAnchor()->nContent.GetIndex();
+ case FLY_AT_PARA:
+ case FLY_AT_FLY:
+ nNewNode = pAnchor->GetCntntAnchor()->nNode.GetIndex();
+ break;
+
+ default:
+ nNewCntnt = pAnchor->GetPageNum();
+ }
+ }
+ else
+ pItemSet->Put( *pItem );
+ }
+ else
+ pItemSet->InvalidateItem( nWhich );
+}
+
+void SwUndoSetFlyFmt::Modify( const SfxPoolItem* pOld, const SfxPoolItem* )
+{
+ if( pOld )
+ {
+ sal_uInt16 nWhich = pOld->Which();
+
+ if( nWhich < POOLATTR_END )
+ PutAttr( nWhich, pOld );
+ else if( RES_ATTRSET_CHG == nWhich )
+ {
+ SfxItemIter aIter( *((SwAttrSetChg*)pOld)->GetChgSet() );
+ const SfxPoolItem* pItem = aIter.GetCurItem();
+ while( pItem )
+ {
+ PutAttr( pItem->Which(), pItem );
+ if( aIter.IsAtEnd() )
+ break;
+ pItem = aIter.NextItem();
+ }
+ }
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/undo/undoflystrattr.cxx b/sw/source/core/undo/undoflystrattr.cxx
new file mode 100644
index 000000000000..8358603fbed4
--- /dev/null
+++ b/sw/source/core/undo/undoflystrattr.cxx
@@ -0,0 +1,102 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+#include <undoflystrattr.hxx>
+#include <frmfmt.hxx>
+
+SwUndoFlyStrAttr::SwUndoFlyStrAttr( SwFlyFrmFmt& rFlyFrmFmt,
+ const SwUndoId eUndoId,
+ const String& sOldStr,
+ const String& sNewStr )
+ : SwUndo( eUndoId ),
+ mrFlyFrmFmt( rFlyFrmFmt ),
+ msOldStr( sOldStr ),
+ msNewStr( sNewStr )
+{
+ OSL_ENSURE( eUndoId == UNDO_FLYFRMFMT_TITLE ||
+ eUndoId == UNDO_FLYFRMFMT_DESCRIPTION,
+ "<SwUndoFlyStrAttr::SwUndoFlyStrAttr(..)> - unexpected undo id --> Undo will not work" );
+}
+
+SwUndoFlyStrAttr::~SwUndoFlyStrAttr()
+{
+}
+
+void SwUndoFlyStrAttr::UndoImpl(::sw::UndoRedoContext &)
+{
+ switch ( GetId() )
+ {
+ case UNDO_FLYFRMFMT_TITLE:
+ {
+ mrFlyFrmFmt.SetObjTitle( msOldStr, true );
+ }
+ break;
+ case UNDO_FLYFRMFMT_DESCRIPTION:
+ {
+ mrFlyFrmFmt.SetObjDescription( msOldStr, true );
+ }
+ break;
+ default:
+ {
+ }
+ }
+}
+
+void SwUndoFlyStrAttr::RedoImpl(::sw::UndoRedoContext &)
+{
+ switch ( GetId() )
+ {
+ case UNDO_FLYFRMFMT_TITLE:
+ {
+ mrFlyFrmFmt.SetObjTitle( msNewStr, true );
+ }
+ break;
+ case UNDO_FLYFRMFMT_DESCRIPTION:
+ {
+ mrFlyFrmFmt.SetObjDescription( msNewStr, true );
+ }
+ break;
+ default:
+ {
+ }
+ }
+}
+
+SwRewriter SwUndoFlyStrAttr::GetRewriter() const
+{
+ SwRewriter aResult;
+
+ aResult.AddRule( UNDO_ARG1, mrFlyFrmFmt.GetName() );
+
+ return aResult;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/undo/undraw.cxx b/sw/source/core/undo/undraw.cxx
new file mode 100644
index 000000000000..b92ce4f488a9
--- /dev/null
+++ b/sw/source/core/undo/undraw.cxx
@@ -0,0 +1,608 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+#include <UndoDraw.hxx>
+
+#include <rtl/string.h>
+#include <rtl/memory.h>
+
+#include <rtl/string.h>
+#include <svx/svdogrp.hxx>
+#include <svx/svdundo.hxx>
+#include <svx/svdpage.hxx>
+#include <svx/svdmark.hxx>
+
+#include <hintids.hxx>
+#include <hints.hxx>
+#include <fmtanchr.hxx>
+#include <fmtflcnt.hxx>
+#include <txtflcnt.hxx>
+#include <frmfmt.hxx>
+#include <doc.hxx>
+#include <IDocumentUndoRedo.hxx>
+#include <docary.hxx>
+#include <frame.hxx>
+#include <swundo.hxx> // fuer die UndoIds
+#include <pam.hxx>
+#include <ndtxt.hxx>
+#include <UndoCore.hxx>
+#include <dcontact.hxx>
+#include <dview.hxx>
+#include <rootfrm.hxx>
+#include <viewsh.hxx>
+
+
+struct SwUndoGroupObjImpl
+{
+ SwDrawFrmFmt* pFmt;
+ SdrObject* pObj;
+ sal_uLong nNodeIdx;
+};
+
+
+// Draw-Objecte
+
+IMPL_LINK( SwDoc, AddDrawUndo, SdrUndoAction *, pUndo )
+{
+#if OSL_DEBUG_LEVEL > 1
+ sal_uInt16 nId = pUndo->GetId();
+ (void)nId;
+ String sComment( pUndo->GetComment() );
+#endif
+
+ if (GetIDocumentUndoRedo().DoesUndo() &&
+ GetIDocumentUndoRedo().DoesDrawUndo())
+ {
+ const SdrMarkList* pMarkList = 0;
+ ViewShell* pSh = GetCurrentViewShell();
+ if( pSh && pSh->HasDrawView() )
+ pMarkList = &pSh->GetDrawView()->GetMarkedObjectList();
+
+ GetIDocumentUndoRedo().AppendUndo( new SwSdrUndo(pUndo, pMarkList) );
+ }
+ else
+ delete pUndo;
+ return 0;
+}
+
+SwSdrUndo::SwSdrUndo( SdrUndoAction* pUndo, const SdrMarkList* pMrkLst )
+ : SwUndo( UNDO_DRAWUNDO ), pSdrUndo( pUndo )
+{
+ if( pMrkLst && pMrkLst->GetMarkCount() )
+ pMarkList = new SdrMarkList( *pMrkLst );
+ else
+ pMarkList = 0;
+}
+
+SwSdrUndo::~SwSdrUndo()
+{
+ delete pSdrUndo;
+ delete pMarkList;
+}
+
+void SwSdrUndo::UndoImpl(::sw::UndoRedoContext & rContext)
+{
+ pSdrUndo->Undo();
+ rContext.SetSelections(0, pMarkList);
+}
+
+void SwSdrUndo::RedoImpl(::sw::UndoRedoContext & rContext)
+{
+ pSdrUndo->Redo();
+ rContext.SetSelections(0, pMarkList);
+}
+
+String SwSdrUndo::GetComment() const
+{
+ return pSdrUndo->GetComment();
+}
+
+//--------------------------------------------
+
+void lcl_SendRemoveToUno( SwFmt& rFmt )
+{
+ SwPtrMsgPoolItem aMsgHint( RES_REMOVE_UNO_OBJECT, &rFmt );
+ rFmt.ModifyNotification( &aMsgHint, &aMsgHint );
+}
+
+void lcl_SaveAnchor( SwFrmFmt* pFmt, sal_uLong& rNodePos )
+{
+ const SwFmtAnchor& rAnchor = pFmt->GetAnchor();
+ if ((FLY_AT_PARA == rAnchor.GetAnchorId()) ||
+ (FLY_AT_CHAR == rAnchor.GetAnchorId()) ||
+ (FLY_AT_FLY == rAnchor.GetAnchorId()) ||
+ (FLY_AS_CHAR == rAnchor.GetAnchorId()))
+ {
+ rNodePos = rAnchor.GetCntntAnchor()->nNode.GetIndex();
+ xub_StrLen nCntntPos = 0;
+
+ if (FLY_AS_CHAR == rAnchor.GetAnchorId())
+ {
+ nCntntPos = rAnchor.GetCntntAnchor()->nContent.GetIndex();
+
+ // destroy TextAttribute
+ SwTxtNode *pTxtNd = pFmt->GetDoc()->GetNodes()[ rNodePos ]->GetTxtNode();
+ OSL_ENSURE( pTxtNd, "No text node found!" );
+ SwTxtFlyCnt* pAttr = static_cast<SwTxtFlyCnt*>(
+ pTxtNd->GetTxtAttrForCharAt( nCntntPos, RES_TXTATR_FLYCNT ));
+ // attribute still in text node, delete
+ if( pAttr && pAttr->GetFlyCnt().GetFrmFmt() == pFmt )
+ {
+ // just set pointer to 0, don't delete
+ ((SwFmtFlyCnt&)pAttr->GetFlyCnt()).SetFlyFmt();
+ SwIndex aIdx( pTxtNd, nCntntPos );
+ pTxtNd->EraseText( aIdx, 1 );
+ }
+ }
+ else if (FLY_AT_CHAR == rAnchor.GetAnchorId())
+ {
+ nCntntPos = rAnchor.GetCntntAnchor()->nContent.GetIndex();
+ }
+
+ pFmt->SetFmtAttr( SwFmtAnchor( rAnchor.GetAnchorId(), nCntntPos ) );
+ }
+}
+
+void lcl_RestoreAnchor( SwFrmFmt* pFmt, sal_uLong& rNodePos )
+{
+ const SwFmtAnchor& rAnchor = pFmt->GetAnchor();
+ if ((FLY_AT_PARA == rAnchor.GetAnchorId()) ||
+ (FLY_AT_CHAR == rAnchor.GetAnchorId()) ||
+ (FLY_AT_FLY == rAnchor.GetAnchorId()) ||
+ (FLY_AS_CHAR == rAnchor.GetAnchorId()))
+ {
+ xub_StrLen nCntntPos = rAnchor.GetPageNum();
+ SwNodes& rNds = pFmt->GetDoc()->GetNodes();
+
+ SwNodeIndex aIdx( rNds, rNodePos );
+ SwPosition aPos( aIdx );
+
+ SwFmtAnchor aTmp( rAnchor.GetAnchorId() );
+ if ((FLY_AS_CHAR == rAnchor.GetAnchorId()) ||
+ (FLY_AT_CHAR == rAnchor.GetAnchorId()))
+ {
+ aPos.nContent.Assign( aIdx.GetNode().GetCntntNode(), nCntntPos );
+ }
+ aTmp.SetAnchor( &aPos );
+ pFmt->SetFmtAttr( aTmp );
+
+ if (FLY_AS_CHAR == rAnchor.GetAnchorId())
+ {
+ SwTxtNode *pTxtNd = aIdx.GetNode().GetTxtNode();
+ OSL_ENSURE( pTxtNd, "no Text Node" );
+ SwFmtFlyCnt aFmt( pFmt );
+ pTxtNd->InsertItem( aFmt, nCntntPos, nCntntPos );
+ }
+ }
+}
+
+SwUndoDrawGroup::SwUndoDrawGroup( sal_uInt16 nCnt )
+ : SwUndo( UNDO_DRAWGROUP ), nSize( nCnt + 1 ), bDelFmt( sal_True )
+{
+ pObjArr = new SwUndoGroupObjImpl[ nSize ];
+}
+
+SwUndoDrawGroup::~SwUndoDrawGroup()
+{
+ if( bDelFmt )
+ {
+ SwUndoGroupObjImpl* pTmp = pObjArr + 1;
+ for( sal_uInt16 n = 1; n < nSize; ++n, ++pTmp )
+ delete pTmp->pFmt;
+ }
+ else
+ delete pObjArr->pFmt;
+
+ delete [] pObjArr;
+}
+
+void SwUndoDrawGroup::UndoImpl(::sw::UndoRedoContext &)
+{
+ bDelFmt = sal_False;
+
+ // save group object
+ SwDrawFrmFmt* pFmt = pObjArr->pFmt;
+ SwDrawContact* pDrawContact = (SwDrawContact*)pFmt->FindContactObj();
+ SdrObject* pObj = pDrawContact->GetMaster();
+ pObjArr->pObj = pObj;
+
+ // object will destroy itself
+ pDrawContact->Changed( *pObj, SDRUSERCALL_DELETE, pObj->GetLastBoundRect() );
+ pObj->SetUserCall( 0 );
+
+ ::lcl_SaveAnchor( pFmt, pObjArr->nNodeIdx );
+
+ // notify UNO objects to decouple
+ ::lcl_SendRemoveToUno( *pFmt );
+
+ // remove from array
+ SwDoc* pDoc = pFmt->GetDoc();
+ SwSpzFrmFmts& rFlyFmts = *(SwSpzFrmFmts*)pDoc->GetSpzFrmFmts();
+ rFlyFmts.Remove( rFlyFmts.GetPos( pFmt ));
+
+ for( sal_uInt16 n = 1; n < nSize; ++n )
+ {
+ SwUndoGroupObjImpl& rSave = *( pObjArr + n );
+
+ ::lcl_RestoreAnchor( rSave.pFmt, rSave.nNodeIdx );
+ rFlyFmts.Insert( rSave.pFmt, rFlyFmts.Count() );
+
+ pObj = rSave.pObj;
+
+ SwDrawContact *pContact = new SwDrawContact( rSave.pFmt, pObj );
+ pContact->ConnectToLayout();
+ // #i45718# - follow-up of #i35635# move object to visible layer
+ pContact->MoveObjToVisibleLayer( pObj );
+ // #i45952# - notify that position attributes are already set
+ OSL_ENSURE( rSave.pFmt->ISA(SwDrawFrmFmt),
+ "<SwUndoDrawGroup::Undo(..)> - wrong type of frame format for drawing object" );
+ if ( rSave.pFmt->ISA(SwDrawFrmFmt) )
+ {
+ static_cast<SwDrawFrmFmt*>(rSave.pFmt)->PosAttrSet();
+ }
+ }
+}
+
+void SwUndoDrawGroup::RedoImpl(::sw::UndoRedoContext &)
+{
+ bDelFmt = sal_True;
+
+ // remove from array
+ SwDoc* pDoc = pObjArr->pFmt->GetDoc();
+ SwSpzFrmFmts& rFlyFmts = *(SwSpzFrmFmts*)pDoc->GetSpzFrmFmts();
+ SdrObject* pObj;
+
+ for( sal_uInt16 n = 1; n < nSize; ++n )
+ {
+ SwUndoGroupObjImpl& rSave = *( pObjArr + n );
+
+ pObj = rSave.pObj;
+
+ SwDrawContact *pContact = (SwDrawContact*)GetUserCall(pObj);
+
+ // object will destroy itself
+ pContact->Changed( *pObj, SDRUSERCALL_DELETE, pObj->GetLastBoundRect() );
+ pObj->SetUserCall( 0 );
+
+ ::lcl_SaveAnchor( rSave.pFmt, rSave.nNodeIdx );
+
+ // notify UNO objects to decouple
+ ::lcl_SendRemoveToUno( *rSave.pFmt );
+
+ rFlyFmts.Remove( rFlyFmts.GetPos( rSave.pFmt ));
+ }
+
+ // re-insert group object
+ ::lcl_RestoreAnchor( pObjArr->pFmt, pObjArr->nNodeIdx );
+ rFlyFmts.Insert( pObjArr->pFmt, rFlyFmts.Count() );
+
+ SwDrawContact *pContact = new SwDrawContact( pObjArr->pFmt, pObjArr->pObj );
+ // #i26791# - correction: connect object to layout
+ pContact->ConnectToLayout();
+ // #i45718# - follow-up of #i35635# move object to visible layer
+ pContact->MoveObjToVisibleLayer( pObjArr->pObj );
+ // #i45952# - notify that position attributes are already set
+ OSL_ENSURE( pObjArr->pFmt->ISA(SwDrawFrmFmt),
+ "<SwUndoDrawGroup::Undo(..)> - wrong type of frame format for drawing object" );
+ if ( pObjArr->pFmt->ISA(SwDrawFrmFmt) )
+ {
+ static_cast<SwDrawFrmFmt*>(pObjArr->pFmt)->PosAttrSet();
+ }
+}
+
+void SwUndoDrawGroup::AddObj( sal_uInt16 nPos, SwDrawFrmFmt* pFmt, SdrObject* pObj )
+{
+ SwUndoGroupObjImpl& rSave = *( pObjArr + nPos + 1 );
+ rSave.pObj = pObj;
+ rSave.pFmt = pFmt;
+ ::lcl_SaveAnchor( pFmt, rSave.nNodeIdx );
+
+ // notify UNO objects to decouple
+ ::lcl_SendRemoveToUno( *pFmt );
+
+ // remove from array
+ SwSpzFrmFmts& rFlyFmts = *(SwSpzFrmFmts*)pFmt->GetDoc()->GetSpzFrmFmts();
+ rFlyFmts.Remove( rFlyFmts.GetPos( pFmt ));
+}
+
+void SwUndoDrawGroup::SetGroupFmt( SwDrawFrmFmt* pFmt )
+{
+ pObjArr->pObj = 0;
+ pObjArr->pFmt = pFmt;
+}
+
+
+// ------------------------------
+
+SwUndoDrawUnGroup::SwUndoDrawUnGroup( SdrObjGroup* pObj )
+ : SwUndo( UNDO_DRAWUNGROUP ), bDelFmt( sal_False )
+{
+ nSize = (sal_uInt16)pObj->GetSubList()->GetObjCount() + 1;
+ pObjArr = new SwUndoGroupObjImpl[ nSize ];
+
+ SwDrawContact *pContact = (SwDrawContact*)GetUserCall(pObj);
+ SwDrawFrmFmt* pFmt = (SwDrawFrmFmt*)pContact->GetFmt();
+
+ pObjArr->pObj = pObj;
+ pObjArr->pFmt = pFmt;
+
+ // object will destroy itself
+ pContact->Changed( *pObj, SDRUSERCALL_DELETE, pObj->GetLastBoundRect() );
+ pObj->SetUserCall( 0 );
+
+ ::lcl_SaveAnchor( pFmt, pObjArr->nNodeIdx );
+
+ // notify UNO objects to decouple
+ ::lcl_SendRemoveToUno( *pFmt );
+
+ // remove from array
+ SwSpzFrmFmts& rFlyFmts = *(SwSpzFrmFmts*)pFmt->GetDoc()->GetSpzFrmFmts();
+ rFlyFmts.Remove( rFlyFmts.GetPos( pFmt ));
+}
+
+SwUndoDrawUnGroup::~SwUndoDrawUnGroup()
+{
+ if( bDelFmt )
+ {
+ SwUndoGroupObjImpl* pTmp = pObjArr + 1;
+ for( sal_uInt16 n = 1; n < nSize; ++n, ++pTmp )
+ delete pTmp->pFmt;
+ }
+ else
+ delete pObjArr->pFmt;
+
+ delete [] pObjArr;
+}
+
+void SwUndoDrawUnGroup::UndoImpl(::sw::UndoRedoContext & rContext)
+{
+ bDelFmt = sal_True;
+
+ SwDoc *const pDoc = & rContext.GetDoc();
+ SwSpzFrmFmts& rFlyFmts = *(SwSpzFrmFmts*)pDoc->GetSpzFrmFmts();
+
+ // remove from array
+ for( sal_uInt16 n = 1; n < nSize; ++n )
+ {
+ SwUndoGroupObjImpl& rSave = *( pObjArr + n );
+
+ ::lcl_SaveAnchor( rSave.pFmt, rSave.nNodeIdx );
+
+ // notify UNO objects to decouple
+ ::lcl_SendRemoveToUno( *rSave.pFmt );
+
+ rFlyFmts.Remove( rFlyFmts.GetPos( rSave.pFmt ));
+ }
+
+ // re-insert group object
+ ::lcl_RestoreAnchor( pObjArr->pFmt, pObjArr->nNodeIdx );
+ rFlyFmts.Insert( pObjArr->pFmt, rFlyFmts.Count() );
+
+ SwDrawContact *pContact = new SwDrawContact( pObjArr->pFmt, pObjArr->pObj );
+ pContact->ConnectToLayout();
+ // #i45718# - follow-up of #i35635# move object to visible layer
+ pContact->MoveObjToVisibleLayer( pObjArr->pObj );
+ // #i45952# - notify that position attributes are already set
+ OSL_ENSURE( pObjArr->pFmt->ISA(SwDrawFrmFmt),
+ "<SwUndoDrawGroup::Undo(..)> - wrong type of frame format for drawing object" );
+ if ( pObjArr->pFmt->ISA(SwDrawFrmFmt) )
+ {
+ static_cast<SwDrawFrmFmt*>(pObjArr->pFmt)->PosAttrSet();
+ }
+}
+
+void SwUndoDrawUnGroup::RedoImpl(::sw::UndoRedoContext &)
+{
+ bDelFmt = sal_False;
+
+ // save group object
+ SwDrawFrmFmt* pFmt = pObjArr->pFmt;
+ SwDrawContact* pContact = (SwDrawContact*)pFmt->FindContactObj();
+
+ // object will destroy itself
+ pContact->Changed( *pObjArr->pObj, SDRUSERCALL_DELETE,
+ pObjArr->pObj->GetLastBoundRect() );
+ pObjArr->pObj->SetUserCall( 0 );
+
+ ::lcl_SaveAnchor( pFmt, pObjArr->nNodeIdx );
+
+ // notify UNO objects to decouple
+ ::lcl_SendRemoveToUno( *pFmt );
+
+ // remove from array
+ SwDoc* pDoc = pFmt->GetDoc();
+ SwSpzFrmFmts& rFlyFmts = *(SwSpzFrmFmts*)pDoc->GetSpzFrmFmts();
+ rFlyFmts.Remove( rFlyFmts.GetPos( pFmt ));
+
+ for( sal_uInt16 n = 1; n < nSize; ++n )
+ {
+ SwUndoGroupObjImpl& rSave = *( pObjArr + n );
+
+ ::lcl_RestoreAnchor( rSave.pFmt, rSave.nNodeIdx );
+ rFlyFmts.Insert( rSave.pFmt, rFlyFmts.Count() );
+
+ // #i45952# - notify that position attributes are already set
+ OSL_ENSURE( rSave.pFmt->ISA(SwDrawFrmFmt),
+ "<SwUndoDrawGroup::Undo(..)> - wrong type of frame format for drawing object" );
+ if ( rSave.pFmt->ISA(SwDrawFrmFmt) )
+ {
+ static_cast<SwDrawFrmFmt*>(rSave.pFmt)->PosAttrSet();
+ }
+ }
+}
+
+void SwUndoDrawUnGroup::AddObj( sal_uInt16 nPos, SwDrawFrmFmt* pFmt )
+{
+ SwUndoGroupObjImpl& rSave = *( pObjArr + nPos + 1 );
+ rSave.pFmt = pFmt;
+ rSave.pObj = 0;
+}
+
+SwUndoDrawUnGroupConnectToLayout::SwUndoDrawUnGroupConnectToLayout()
+ : SwUndo( UNDO_DRAWUNGROUP )
+{
+}
+
+SwUndoDrawUnGroupConnectToLayout::~SwUndoDrawUnGroupConnectToLayout()
+{
+}
+
+void
+SwUndoDrawUnGroupConnectToLayout::UndoImpl(::sw::UndoRedoContext &)
+{
+ for ( std::vector< SdrObject >::size_type i = 0;
+ i < aDrawFmtsAndObjs.size(); ++i )
+ {
+ SdrObject* pObj( aDrawFmtsAndObjs[i].second );
+ SwDrawContact* pDrawContact( dynamic_cast<SwDrawContact*>(pObj->GetUserCall()) );
+ OSL_ENSURE( pDrawContact,
+ "<SwUndoDrawUnGroupConnectToLayout::Undo(..)> -- missing SwDrawContact instance" );
+ if ( pDrawContact )
+ {
+ // deletion of instance <pDrawContact> and thus disconnection from
+ // the Writer layout.
+ pDrawContact->Changed( *pObj, SDRUSERCALL_DELETE, pObj->GetLastBoundRect() );
+ pObj->SetUserCall( 0 );
+ }
+ }
+}
+
+void
+SwUndoDrawUnGroupConnectToLayout::RedoImpl(::sw::UndoRedoContext &)
+{
+ for ( std::vector< std::pair< SwDrawFrmFmt*, SdrObject* > >::size_type i = 0;
+ i < aDrawFmtsAndObjs.size(); ++i )
+ {
+ SwDrawFrmFmt* pFmt( aDrawFmtsAndObjs[i].first );
+ SdrObject* pObj( aDrawFmtsAndObjs[i].second );
+ SwDrawContact *pContact = new SwDrawContact( pFmt, pObj );
+ pContact->ConnectToLayout();
+ pContact->MoveObjToVisibleLayer( pObj );
+ }
+}
+
+void SwUndoDrawUnGroupConnectToLayout::AddFmtAndObj( SwDrawFrmFmt* pDrawFrmFmt,
+ SdrObject* pDrawObject )
+{
+ aDrawFmtsAndObjs.push_back(
+ std::pair< SwDrawFrmFmt*, SdrObject* >( pDrawFrmFmt, pDrawObject ) );
+}
+
+//-------------------------------------
+
+SwUndoDrawDelete::SwUndoDrawDelete( sal_uInt16 nCnt )
+ : SwUndo( UNDO_DRAWDELETE ), nSize( nCnt ), bDelFmt( sal_True )
+{
+ pObjArr = new SwUndoGroupObjImpl[ nSize ];
+ pMarkLst = new SdrMarkList();
+}
+
+SwUndoDrawDelete::~SwUndoDrawDelete()
+{
+ if( bDelFmt )
+ {
+ SwUndoGroupObjImpl* pTmp = pObjArr;
+ for( sal_uInt16 n = 0; n < pMarkLst->GetMarkCount(); ++n, ++pTmp )
+ delete pTmp->pFmt;
+ }
+ delete [] pObjArr;
+ delete pMarkLst;
+}
+
+void SwUndoDrawDelete::UndoImpl(::sw::UndoRedoContext & rContext)
+{
+ bDelFmt = sal_False;
+ SwSpzFrmFmts & rFlyFmts = *rContext.GetDoc().GetSpzFrmFmts();
+ for( sal_uInt16 n = 0; n < pMarkLst->GetMarkCount(); ++n )
+ {
+ SwUndoGroupObjImpl& rSave = *( pObjArr + n );
+ ::lcl_RestoreAnchor( rSave.pFmt, rSave.nNodeIdx );
+ rFlyFmts.Insert( rSave.pFmt, rFlyFmts.Count() );
+ SdrObject *pObj = rSave.pObj;
+ SwDrawContact *pContact = new SwDrawContact( rSave.pFmt, pObj );
+ pContact->_Changed( *pObj, SDRUSERCALL_INSERTED, NULL );
+ // #i45718# - follow-up of #i35635# move object to visible layer
+ pContact->MoveObjToVisibleLayer( pObj );
+ // #i45952# - notify that position attributes are already set
+ OSL_ENSURE( rSave.pFmt->ISA(SwDrawFrmFmt),
+ "<SwUndoDrawGroup::Undo(..)> - wrong type of frame format for drawing object" );
+ if ( rSave.pFmt->ISA(SwDrawFrmFmt) )
+ {
+ static_cast<SwDrawFrmFmt*>(rSave.pFmt)->PosAttrSet();
+ }
+ // <--
+ }
+ rContext.SetSelections(0, pMarkLst);
+}
+
+void SwUndoDrawDelete::RedoImpl(::sw::UndoRedoContext & rContext)
+{
+ bDelFmt = sal_True;
+ SwSpzFrmFmts & rFlyFmts = *rContext.GetDoc().GetSpzFrmFmts();
+ for( sal_uInt16 n = 0; n < pMarkLst->GetMarkCount(); ++n )
+ {
+ SwUndoGroupObjImpl& rSave = *( pObjArr + n );
+ SdrObject *pObj = rSave.pObj;
+ SwDrawContact *pContact = (SwDrawContact*)GetUserCall(pObj);
+ SwDrawFrmFmt *pFmt = (SwDrawFrmFmt*)pContact->GetFmt();
+
+ // object will destroy itself
+ pContact->Changed( *pObj, SDRUSERCALL_DELETE, pObj->GetLastBoundRect() );
+ pObj->SetUserCall( 0 );
+
+ // notify UNO objects to decouple
+ ::lcl_SendRemoveToUno( *pFmt );
+
+ rFlyFmts.Remove( rFlyFmts.GetPos( pFmt ));
+ ::lcl_SaveAnchor( pFmt, rSave.nNodeIdx );
+ }
+}
+
+void SwUndoDrawDelete::AddObj( sal_uInt16 , SwDrawFrmFmt* pFmt,
+ const SdrMark& rMark )
+{
+ SwUndoGroupObjImpl& rSave = *( pObjArr + pMarkLst->GetMarkCount() );
+ rSave.pObj = rMark.GetMarkedSdrObj();
+ rSave.pFmt = pFmt;
+ ::lcl_SaveAnchor( pFmt, rSave.nNodeIdx );
+
+ // notify UNO objects to decouple
+ ::lcl_SendRemoveToUno( *pFmt );
+
+ // remove from array
+ SwDoc* pDoc = pFmt->GetDoc();
+ SwSpzFrmFmts& rFlyFmts = *(SwSpzFrmFmts*)pDoc->GetSpzFrmFmts();
+ rFlyFmts.Remove( rFlyFmts.GetPos( pFmt ));
+
+ pMarkLst->InsertEntry( rMark );
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/undo/unfmco.cxx b/sw/source/core/undo/unfmco.cxx
new file mode 100644
index 000000000000..4ba736443dba
--- /dev/null
+++ b/sw/source/core/undo/unfmco.cxx
@@ -0,0 +1,122 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+
+
+#include "doc.hxx"
+#include "swundo.hxx" // fuer die UndoIds
+#include "pam.hxx"
+#include "ndtxt.hxx"
+
+#include <UndoCore.hxx>
+#include "rolbck.hxx"
+
+
+//--------------------------------------------------
+
+
+SwUndoFmtColl::SwUndoFmtColl( const SwPaM& rRange,
+ SwFmtColl* pColl,
+ const bool bReset,
+ const bool bResetListAttrs )
+ : SwUndo( UNDO_SETFMTCOLL ),
+ SwUndRng( rRange ),
+ pHistory( new SwHistory ),
+ pFmtColl( pColl ),
+ mbReset( bReset ),
+ mbResetListAttrs( bResetListAttrs )
+{
+ // --> FME 2004-08-06 #i31191#
+ if ( pColl )
+ aFmtName = pColl->GetName();
+ // <--
+}
+
+
+SwUndoFmtColl::~SwUndoFmtColl()
+{
+ delete pHistory;
+}
+
+
+void SwUndoFmtColl::UndoImpl(::sw::UndoRedoContext & rContext)
+{
+ // restore old values
+ pHistory->TmpRollback(& rContext.GetDoc(), 0);
+ pHistory->SetTmpEnd( pHistory->Count() );
+
+ // create cursor for undo range
+ AddUndoRedoPaM(rContext);
+}
+
+
+void SwUndoFmtColl::RedoImpl(::sw::UndoRedoContext & rContext)
+{
+ SwPaM & rPam = AddUndoRedoPaM(rContext);
+
+ DoSetFmtColl(rContext.GetDoc(), rPam);
+}
+
+void SwUndoFmtColl::RepeatImpl(::sw::RepeatContext & rContext)
+{
+ DoSetFmtColl(rContext.GetDoc(), rContext.GetRepeatPaM());
+}
+
+void SwUndoFmtColl::DoSetFmtColl(SwDoc & rDoc, SwPaM & rPaM)
+{
+ // es kann nur eine TextFmtColl auf einen Bereich angewendet werden,
+ // also erfrage auch nur in dem Array
+ sal_uInt16 const nPos = rDoc.GetTxtFmtColls()->GetPos(
+ (SwTxtFmtColl*)pFmtColl );
+ // does the format still exist?
+ if( USHRT_MAX != nPos )
+ {
+ rDoc.SetTxtFmtColl(rPaM,
+ (SwTxtFmtColl*)pFmtColl,
+ mbReset,
+ mbResetListAttrs );
+ }
+}
+
+SwRewriter SwUndoFmtColl::GetRewriter() const
+{
+ SwRewriter aResult;
+
+ // --> FME 2004-08-06 #i31191# Use stored format name instead of
+ // pFmtColl->GetName(), because pFmtColl does not have to be available
+ // anymore.
+ aResult.AddRule(UNDO_ARG1, aFmtName );
+ // <--
+
+ return aResult;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/undo/unins.cxx b/sw/source/core/undo/unins.cxx
new file mode 100644
index 000000000000..4cb2b0e94b63
--- /dev/null
+++ b/sw/source/core/undo/unins.cxx
@@ -0,0 +1,1068 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+#include <UndoInsert.hxx>
+
+#include <hintids.hxx>
+#include <unotools/charclass.hxx>
+#include <sot/storage.hxx>
+#include <editeng/keepitem.hxx>
+#include <svx/svdobj.hxx>
+
+#include <docsh.hxx>
+#include <fmtcntnt.hxx>
+#include <fmtanchr.hxx>
+#include <frmfmt.hxx>
+#include <doc.hxx>
+#include <IDocumentUndoRedo.hxx>
+#include <swundo.hxx> // fuer die UndoIds
+#include <pam.hxx>
+#include <ndtxt.hxx>
+#include <UndoCore.hxx>
+#include <UndoDelete.hxx>
+#include <UndoAttribute.hxx>
+#include <rolbck.hxx>
+#include <ndgrf.hxx>
+#include <ndole.hxx>
+#include <grfatr.hxx>
+#include <cntfrm.hxx>
+#include <flyfrm.hxx>
+#include <fesh.hxx>
+#include <swtable.hxx>
+#include <redline.hxx>
+#include <docary.hxx>
+#include <acorrect.hxx>
+#include <dcontact.hxx>
+
+#include <comcore.hrc> // #111827#
+#include <undo.hrc>
+
+using namespace ::com::sun::star;
+
+
+//------------------------------------------------------------
+
+// INSERT
+
+String * SwUndoInsert::GetTxtFromDoc() const
+{
+ String * pResult = NULL;
+
+ SwNodeIndex aNd( pDoc->GetNodes(), nNode);
+ SwCntntNode* pCNd = aNd.GetNode().GetCntntNode();
+ SwPaM aPaM( *pCNd, nCntnt );
+
+ aPaM.SetMark();
+
+ if( pCNd->IsTxtNode() )
+ {
+ pResult = new String( ((SwTxtNode*)pCNd)->GetTxt().Copy(nCntnt-nLen,
+ nLen ) );
+
+ }
+
+ return pResult;
+}
+
+void SwUndoInsert::Init(const SwNodeIndex & rNd)
+{
+ // Redline beachten
+ pDoc = rNd.GetNode().GetDoc();
+ if( pDoc->IsRedlineOn() )
+ {
+ pRedlData = new SwRedlineData( nsRedlineType_t::REDLINE_INSERT,
+ pDoc->GetRedlineAuthor() );
+ SetRedlineMode( pDoc->GetRedlineMode() );
+ }
+
+ pUndoTxt = GetTxtFromDoc();
+
+ bCacheComment = false;
+}
+
+// #111827#
+SwUndoInsert::SwUndoInsert( const SwNodeIndex& rNd, xub_StrLen nCnt,
+ xub_StrLen nL,
+ const IDocumentContentOperations::InsertFlags nInsertFlags,
+ sal_Bool bWDelim )
+ : SwUndo(UNDO_TYPING), pPos( 0 ), pTxt( 0 ), pRedlData( 0 ),
+ nNode( rNd.GetIndex() ), nCntnt(nCnt), nLen(nL),
+ bIsWordDelim( bWDelim ), bIsAppend( sal_False )
+ , m_nInsertFlags(nInsertFlags)
+{
+ Init(rNd);
+}
+
+// #111827#
+SwUndoInsert::SwUndoInsert( const SwNodeIndex& rNd )
+ : SwUndo(UNDO_SPLITNODE), pPos( 0 ), pTxt( 0 ),
+ pRedlData( 0 ), nNode( rNd.GetIndex() ), nCntnt(0), nLen(1),
+ bIsWordDelim( sal_False ), bIsAppend( sal_True )
+ , m_nInsertFlags(IDocumentContentOperations::INS_EMPTYEXPAND)
+{
+ Init(rNd);
+}
+
+// stelle fest, ob das naechste Insert mit dem aktuellen zusammengefasst
+// werden kann. Wenn ja, dann aender die Laenge und die InsPos.
+// Dann wird von SwDoc::Insert kein neues Object in die Undoliste gestellt.
+
+sal_Bool SwUndoInsert::CanGrouping( sal_Unicode cIns )
+{
+ if( !bIsAppend && bIsWordDelim ==
+ !GetAppCharClass().isLetterNumeric( String( cIns )) )
+ {
+ nLen++;
+ nCntnt++;
+
+ if (pUndoTxt)
+ pUndoTxt->Insert(cIns);
+
+ return sal_True;
+ }
+ return sal_False;
+}
+
+sal_Bool SwUndoInsert::CanGrouping( const SwPosition& rPos )
+{
+ sal_Bool bRet = sal_False;
+ if( nNode == rPos.nNode.GetIndex() &&
+ nCntnt == rPos.nContent.GetIndex() )
+ {
+ // Redline beachten
+ SwDoc& rDoc = *rPos.nNode.GetNode().GetDoc();
+ if( ( ~nsRedlineMode_t::REDLINE_SHOW_MASK & rDoc.GetRedlineMode() ) ==
+ ( ~nsRedlineMode_t::REDLINE_SHOW_MASK & GetRedlineMode() ) )
+ {
+ bRet = sal_True;
+
+ // dann war oder ist noch Redline an:
+ // pruefe, ob an der InsPosition ein anderer Redline
+ // rumsteht. Wenn der gleiche nur einmalig vorhanden ist,
+ // kann zusammen gefasst werden.
+ const SwRedlineTbl& rTbl = rDoc.GetRedlineTbl();
+ if( rTbl.Count() )
+ {
+ SwRedlineData aRData( nsRedlineType_t::REDLINE_INSERT, rDoc.GetRedlineAuthor() );
+ const SwIndexReg* pIReg = rPos.nContent.GetIdxReg();
+ SwIndex* pIdx;
+ for( sal_uInt16 i = 0; i < rTbl.Count(); ++i )
+ {
+ SwRedline* pRedl = rTbl[ i ];
+ if( pIReg == (pIdx = &pRedl->End()->nContent)->GetIdxReg() &&
+ nCntnt == pIdx->GetIndex() )
+ {
+ if( !pRedl->HasMark() || !pRedlData ||
+ *pRedl != *pRedlData || *pRedl != aRData )
+ {
+ bRet = sal_False;
+ break;
+ }
+ }
+ }
+ }
+ }
+ }
+ return bRet;
+}
+
+SwUndoInsert::~SwUndoInsert()
+{
+ if( pPos ) // loesche noch den Bereich aus dem UndoNodes Array
+ {
+ // Insert speichert den Inhalt in der IconSection
+ SwNodes& rUNds = pPos->nNode.GetNode().GetNodes();
+ if( pPos->nContent.GetIndex() ) // nicht den gesamten Node loeschen
+ {
+ SwTxtNode* pTxtNd = pPos->nNode.GetNode().GetTxtNode();
+ OSL_ENSURE( pTxtNd, "kein TextNode, aus dem geloescht werden soll" );
+ pTxtNd->EraseText( pPos->nContent );
+ pPos->nNode++;
+ }
+ pPos->nContent.Assign( 0, 0 );
+ rUNds.Delete( pPos->nNode, rUNds.GetEndOfExtras().GetIndex() -
+ pPos->nNode.GetIndex() );
+ delete pPos;
+ }
+ else if( pTxt ) // der eingefuegte Text
+ delete pTxt;
+ delete pRedlData;
+}
+
+
+
+void SwUndoInsert::UndoImpl(::sw::UndoRedoContext & rContext)
+{
+ SwDoc *const pTmpDoc = & rContext.GetDoc();
+ SwPaM *const pPam(& rContext.GetCursorSupplier().CreateNewShellCursor());
+
+ if( bIsAppend )
+ {
+ pPam->GetPoint()->nNode = nNode;
+
+ if( IDocumentRedlineAccess::IsRedlineOn( GetRedlineMode() ))
+ {
+ pPam->GetPoint()->nContent.Assign( pPam->GetCntntNode(), 0 );
+ pPam->SetMark();
+ pPam->Move( fnMoveBackward );
+ pPam->Exchange();
+ pTmpDoc->DeleteRedline( *pPam, true, USHRT_MAX );
+ }
+ pPam->DeleteMark();
+ pTmpDoc->DelFullPara( *pPam );
+ pPam->GetPoint()->nContent.Assign( pPam->GetCntntNode(), 0 );
+ }
+ else
+ {
+ sal_uLong nNd = nNode;
+ xub_StrLen nCnt = nCntnt;
+ if( nLen )
+ {
+ SwNodeIndex aNd( pTmpDoc->GetNodes(), nNode);
+ SwCntntNode* pCNd = aNd.GetNode().GetCntntNode();
+ SwPaM aPaM( *pCNd, nCntnt );
+
+ aPaM.SetMark();
+
+ SwTxtNode * const pTxtNode( pCNd->GetTxtNode() );
+ if ( pTxtNode )
+ {
+ aPaM.GetPoint()->nContent -= nLen;
+ if( IDocumentRedlineAccess::IsRedlineOn( GetRedlineMode() ))
+ pTmpDoc->DeleteRedline( aPaM, true, USHRT_MAX );
+ RemoveIdxFromRange( aPaM, sal_False );
+ pTxt = new String( pTxtNode->GetTxt().Copy(nCntnt-nLen, nLen) );
+ pTxtNode->EraseText( aPaM.GetPoint()->nContent, nLen );
+ }
+ else // ansonsten Grafik/OLE/Text/...
+ {
+ aPaM.Move(fnMoveBackward);
+ if( IDocumentRedlineAccess::IsRedlineOn( GetRedlineMode() ))
+ pTmpDoc->DeleteRedline( aPaM, true, USHRT_MAX );
+ RemoveIdxFromRange( aPaM, sal_False );
+ }
+
+ nNd = aPaM.GetPoint()->nNode.GetIndex();
+ nCnt = aPaM.GetPoint()->nContent.GetIndex();
+
+ if( !pTxt )
+ {
+ pPos = new SwPosition( *aPaM.GetPoint() );
+ MoveToUndoNds( aPaM, &pPos->nNode, &pPos->nContent );
+ }
+ nNode = aPaM.GetPoint()->nNode.GetIndex();
+ nCntnt = aPaM.GetPoint()->nContent.GetIndex();
+ }
+
+ // set cursor to Undo range
+ pPam->DeleteMark();
+
+ pPam->GetPoint()->nNode = nNd;
+ pPam->GetPoint()->nContent.Assign(
+ pPam->GetPoint()->nNode.GetNode().GetCntntNode(), nCnt );
+ }
+
+ DELETEZ(pUndoTxt);
+}
+
+
+void SwUndoInsert::RedoImpl(::sw::UndoRedoContext & rContext)
+{
+ SwDoc *const pTmpDoc = & rContext.GetDoc();
+ SwPaM *const pPam(& rContext.GetCursorSupplier().CreateNewShellCursor());
+ pPam->DeleteMark();
+
+ if( bIsAppend )
+ {
+ pPam->GetPoint()->nNode = nNode - 1;
+ pTmpDoc->AppendTxtNode( *pPam->GetPoint() );
+
+ pPam->SetMark();
+ pPam->Move( fnMoveBackward );
+ pPam->Exchange();
+
+ if( pRedlData && IDocumentRedlineAccess::IsRedlineOn( GetRedlineMode() ))
+ {
+ RedlineMode_t eOld = pTmpDoc->GetRedlineMode();
+ pTmpDoc->SetRedlineMode_intern((RedlineMode_t)(eOld & ~nsRedlineMode_t::REDLINE_IGNORE));
+ pTmpDoc->AppendRedline( new SwRedline( *pRedlData, *pPam ), true);
+ pTmpDoc->SetRedlineMode_intern( eOld );
+ }
+ else if( !( nsRedlineMode_t::REDLINE_IGNORE & GetRedlineMode() ) &&
+ pTmpDoc->GetRedlineTbl().Count() )
+ pTmpDoc->SplitRedline( *pPam );
+
+ pPam->DeleteMark();
+ }
+ else
+ {
+ pPam->GetPoint()->nNode = nNode;
+ SwCntntNode *const pCNd =
+ pPam->GetPoint()->nNode.GetNode().GetCntntNode();
+ pPam->GetPoint()->nContent.Assign( pCNd, nCntnt );
+
+ if( nLen )
+ {
+ sal_Bool bMvBkwrd = MovePtBackward( *pPam );
+
+ if( pTxt )
+ {
+ SwTxtNode *const pTxtNode = pCNd->GetTxtNode();
+ OSL_ENSURE( pTxtNode, "where is my textnode ?" );
+ pTxtNode->InsertText( *pTxt, pPam->GetMark()->nContent,
+ m_nInsertFlags );
+ DELETEZ( pTxt );
+ }
+ else
+ {
+ // Inhalt wieder einfuegen. (erst pPos abmelden !!)
+ sal_uLong nMvNd = pPos->nNode.GetIndex();
+ xub_StrLen nMvCnt = pPos->nContent.GetIndex();
+ DELETEZ( pPos );
+ MoveFromUndoNds( *pTmpDoc, nMvNd, nMvCnt, *pPam->GetMark() );
+ }
+ nNode = pPam->GetMark()->nNode.GetIndex();
+ nCntnt = pPam->GetMark()->nContent.GetIndex();
+
+ MovePtForward( *pPam, bMvBkwrd );
+ pPam->Exchange();
+ if( pRedlData && IDocumentRedlineAccess::IsRedlineOn( GetRedlineMode() ))
+ {
+ RedlineMode_t eOld = pTmpDoc->GetRedlineMode();
+ pTmpDoc->SetRedlineMode_intern((RedlineMode_t)(eOld & ~nsRedlineMode_t::REDLINE_IGNORE));
+ pTmpDoc->AppendRedline( new SwRedline( *pRedlData,
+ *pPam ), true);
+ pTmpDoc->SetRedlineMode_intern( eOld );
+ }
+ else if( !( nsRedlineMode_t::REDLINE_IGNORE & GetRedlineMode() ) &&
+ pTmpDoc->GetRedlineTbl().Count() )
+ pTmpDoc->SplitRedline(*pPam);
+ }
+ }
+
+ pUndoTxt = GetTxtFromDoc();
+}
+
+
+void SwUndoInsert::RepeatImpl(::sw::RepeatContext & rContext)
+{
+ if( !nLen )
+ return;
+
+ SwDoc & rDoc = rContext.GetDoc();
+ SwNodeIndex aNd( rDoc.GetNodes(), nNode );
+ SwCntntNode* pCNd = aNd.GetNode().GetCntntNode();;
+
+ if( !bIsAppend && 1 == nLen ) // >1 dann immer nur Text, ansonsten Grafik/OLE/Text/...
+ {
+ SwPaM aPaM( *pCNd, nCntnt );
+ aPaM.SetMark();
+ aPaM.Move(fnMoveBackward);
+ pCNd = aPaM.GetCntntNode();
+ }
+
+// Was passiert mit dem evt. selektierten Bereich ???
+
+ switch( pCNd->GetNodeType() )
+ {
+ case ND_TEXTNODE:
+ if( bIsAppend )
+ {
+ rDoc.AppendTxtNode( *rContext.GetRepeatPaM().GetPoint() );
+ }
+ else
+ {
+ String aTxt( ((SwTxtNode*)pCNd)->GetTxt() );
+ ::sw::GroupUndoGuard const undoGuard(rDoc.GetIDocumentUndoRedo());
+ rDoc.InsertString( rContext.GetRepeatPaM(),
+ aTxt.Copy( nCntnt - nLen, nLen ) );
+ }
+ break;
+ case ND_GRFNODE:
+ {
+ SwGrfNode* pGrfNd = (SwGrfNode*)pCNd;
+ String sFile, sFilter;
+ if( pGrfNd->IsGrfLink() )
+ pGrfNd->GetFileFilterNms( &sFile, &sFilter );
+
+ rDoc.Insert( rContext.GetRepeatPaM(), sFile, sFilter,
+ &pGrfNd->GetGrf(),
+ 0/* Grafik-Collection*/, NULL, NULL );
+ }
+ break;
+
+ case ND_OLENODE:
+ {
+ // StarView bietet noch nicht die Moeglichkeit ein StarOBJ zu kopieren
+ SvStorageRef aRef = new SvStorage( aEmptyStr );
+ SwOLEObj& rSwOLE = (SwOLEObj&)((SwOLENode*)pCNd)->GetOLEObj();
+
+ // temporary storage until object is inserted
+ // TODO/MBA: seems that here a physical copy is done - not as in drawing layer! Testing!
+ // TODO/LATER: Copying through the container would copy the replacement image as well
+ comphelper::EmbeddedObjectContainer aCnt;
+ ::rtl::OUString aName = aCnt.CreateUniqueObjectName();
+ if ( aCnt.StoreEmbeddedObject( rSwOLE.GetOleRef(), aName, sal_True ) )
+ {
+ uno::Reference < embed::XEmbeddedObject > aNew = aCnt.GetEmbeddedObject( aName );
+ rDoc.Insert( rContext.GetRepeatPaM(),
+ svt::EmbeddedObjectRef( aNew,
+ static_cast<SwOLENode*>(pCNd)->GetAspect() ),
+ NULL, NULL, NULL );
+ }
+
+ break;
+ }
+ }
+}
+
+// #111827#
+SwRewriter SwUndoInsert::GetRewriter() const
+{
+ SwRewriter aResult;
+ String * pStr = NULL;
+ bool bDone = false;
+
+ if (pTxt)
+ pStr = pTxt;
+ else if (pUndoTxt)
+ pStr = pUndoTxt;
+
+ if (pStr)
+ {
+ String aString = ShortenString(DenoteSpecialCharacters(*pStr),
+ nUndoStringLength,
+ String(SW_RES(STR_LDOTS)));
+
+ aResult.AddRule(UNDO_ARG1, aString);
+
+ bDone = true;
+ }
+
+ if ( ! bDone )
+ {
+ aResult.AddRule(UNDO_ARG1, String("??", RTL_TEXTENCODING_ASCII_US));
+ }
+
+ return aResult;
+}
+
+
+// SwUndoReplace /////////////////////////////////////////////////////////
+
+
+class SwUndoReplace::Impl
+ : private SwUndoSaveCntnt
+{
+ ::rtl::OUString m_sOld;
+ ::rtl::OUString m_sIns;
+ sal_uLong m_nSttNd, m_nEndNd, m_nOffset;
+ xub_StrLen m_nSttCnt, m_nEndCnt, m_nSetPos, m_nSelEnd;
+ bool m_bSplitNext : 1;
+ bool m_bRegExp : 1;
+ // metadata references for paragraph and following para (if m_bSplitNext)
+ ::boost::shared_ptr< ::sfx2::MetadatableUndo > m_pMetadataUndoStart;
+ ::boost::shared_ptr< ::sfx2::MetadatableUndo > m_pMetadataUndoEnd;
+
+public:
+ Impl(SwPaM const& rPam, ::rtl::OUString const& rIns, bool const bRegExp);
+ virtual ~Impl()
+ {
+ }
+
+ virtual void UndoImpl( ::sw::UndoRedoContext & );
+ virtual void RedoImpl( ::sw::UndoRedoContext & );
+
+ void SetEnd(SwPaM const& rPam);
+
+ ::rtl::OUString const& GetOld() const { return m_sOld; }
+ ::rtl::OUString const& GetIns() const { return m_sIns; }
+};
+
+
+SwUndoReplace::SwUndoReplace(SwPaM const& rPam,
+ ::rtl::OUString const& rIns, bool const bRegExp)
+ : SwUndo( UNDO_REPLACE )
+ , m_pImpl(new Impl(rPam, rIns, bRegExp))
+{
+}
+
+SwUndoReplace::~SwUndoReplace()
+{
+}
+
+void SwUndoReplace::UndoImpl(::sw::UndoRedoContext & rContext)
+{
+ m_pImpl->UndoImpl(rContext);
+}
+
+void SwUndoReplace::RedoImpl(::sw::UndoRedoContext & rContext)
+{
+ m_pImpl->RedoImpl(rContext);
+}
+
+SwRewriter
+MakeUndoReplaceRewriter(sal_uLong const occurrences,
+ ::rtl::OUString const& sOld, ::rtl::OUString const& sNew)
+{
+ SwRewriter aResult;
+
+ if (1 < occurrences)
+ {
+ aResult.AddRule(UNDO_ARG1, String::CreateFromInt32(occurrences));
+ aResult.AddRule(UNDO_ARG2, String(SW_RES(STR_OCCURRENCES_OF)));
+
+ String aTmpStr;
+ aTmpStr += String(SW_RES(STR_START_QUOTE));
+ aTmpStr += ShortenString(sOld, nUndoStringLength,
+ SW_RES(STR_LDOTS));
+ aTmpStr += String(SW_RES(STR_END_QUOTE));
+ aResult.AddRule(UNDO_ARG3, aTmpStr);
+ }
+ else if (1 == occurrences)
+ {
+ {
+ String aTmpStr;
+
+ aTmpStr += String(SW_RES(STR_START_QUOTE));
+ // #i33488 #
+ aTmpStr += ShortenString(sOld, nUndoStringLength,
+ SW_RES(STR_LDOTS));
+ aTmpStr += String(SW_RES(STR_END_QUOTE));
+ aResult.AddRule(UNDO_ARG1, aTmpStr);
+ }
+
+ aResult.AddRule(UNDO_ARG2, String(SW_RES(STR_YIELDS)));
+
+ {
+ String aTmpStr;
+
+ aTmpStr += String(SW_RES(STR_START_QUOTE));
+ // #i33488 #
+ aTmpStr += ShortenString(sNew, nUndoStringLength,
+ SW_RES(STR_LDOTS));
+ aTmpStr += String(SW_RES(STR_END_QUOTE));
+ aResult.AddRule(UNDO_ARG3, aTmpStr);
+ }
+ }
+
+ return aResult;
+}
+
+// #111827#
+SwRewriter SwUndoReplace::GetRewriter() const
+{
+ return MakeUndoReplaceRewriter(1, m_pImpl->GetOld(), m_pImpl->GetIns());
+}
+
+void SwUndoReplace::SetEnd(SwPaM const& rPam)
+{
+ m_pImpl->SetEnd(rPam);
+}
+
+SwUndoReplace::Impl::Impl(
+ SwPaM const& rPam, ::rtl::OUString const& rIns, bool const bRegExp)
+ : m_sIns( rIns )
+ , m_nOffset( 0 )
+ , m_bRegExp(bRegExp)
+{
+
+ const SwPosition * pStt( rPam.Start() );
+ const SwPosition * pEnd( rPam.End() );
+
+ m_nSttNd = m_nEndNd = pStt->nNode.GetIndex();
+ m_nSttCnt = pStt->nContent.GetIndex();
+ m_nSelEnd = m_nEndCnt = pEnd->nContent.GetIndex();
+
+ m_bSplitNext = m_nSttNd != pEnd->nNode.GetIndex();
+
+ SwTxtNode* pNd = pStt->nNode.GetNode().GetTxtNode();
+ OSL_ENSURE( pNd, "wo ist der TextNode" );
+
+ pHistory = new SwHistory;
+ DelCntntIndex( *rPam.GetMark(), *rPam.GetPoint() );
+
+ m_nSetPos = pHistory->Count();
+
+ sal_uLong nNewPos = pStt->nNode.GetIndex();
+ m_nOffset = m_nSttNd - nNewPos;
+
+ if ( pNd->GetpSwpHints() )
+ {
+ pHistory->CopyAttr( pNd->GetpSwpHints(), nNewPos, 0,
+ pNd->GetTxt().Len(), true );
+ }
+
+ if ( m_bSplitNext )
+ {
+ if( pNd->HasSwAttrSet() )
+ pHistory->CopyFmtAttr( *pNd->GetpSwAttrSet(), nNewPos );
+ pHistory->Add( pNd->GetTxtColl(), nNewPos, ND_TEXTNODE );
+
+ SwTxtNode* pNext = pEnd->nNode.GetNode().GetTxtNode();
+ sal_uLong nTmp = pNext->GetIndex();
+ pHistory->CopyAttr( pNext->GetpSwpHints(), nTmp, 0,
+ pNext->GetTxt().Len(), true );
+ if( pNext->HasSwAttrSet() )
+ pHistory->CopyFmtAttr( *pNext->GetpSwAttrSet(), nTmp );
+ pHistory->Add( pNext->GetTxtColl(),nTmp, ND_TEXTNODE );
+ // METADATA: store
+ m_pMetadataUndoStart = pNd ->CreateUndo();
+ m_pMetadataUndoEnd = pNext->CreateUndo();
+ }
+
+ if( !pHistory->Count() )
+ delete pHistory, pHistory = 0;
+
+ xub_StrLen nECnt = m_bSplitNext ? pNd->GetTxt().Len()
+ : pEnd->nContent.GetIndex();
+ m_sOld = pNd->GetTxt().Copy( m_nSttCnt, nECnt - m_nSttCnt );
+}
+
+void SwUndoReplace::Impl::UndoImpl(::sw::UndoRedoContext & rContext)
+{
+ SwDoc *const pDoc = & rContext.GetDoc();
+ SwPaM & rPam(rContext.GetCursorSupplier().CreateNewShellCursor());
+ rPam.DeleteMark();
+
+ SwTxtNode* pNd = pDoc->GetNodes()[ m_nSttNd - m_nOffset ]->GetTxtNode();
+ OSL_ENSURE( pNd, "Wo ist der TextNode geblieben?" );
+
+ SwAutoCorrExceptWord* pACEWord = pDoc->GetAutoCorrExceptWord();
+ if( pACEWord )
+ {
+ if ((1 == m_sIns.getLength()) && (1 == m_sOld.getLength()))
+ {
+ SwPosition aPos( *pNd ); aPos.nContent.Assign( pNd, m_nSttCnt );
+ pACEWord->CheckChar( aPos, m_sOld[ 0 ] );
+ }
+ pDoc->SetAutoCorrExceptWord( 0 );
+ }
+
+ SwIndex aIdx( pNd, sal_uInt16( m_nSttCnt ) );
+ if( m_nSttNd == m_nEndNd )
+ {
+ pNd->EraseText( aIdx, sal_uInt16( m_sIns.getLength() ) );
+ }
+ else
+ {
+ rPam.GetPoint()->nNode = *pNd;
+ rPam.GetPoint()->nContent.Assign( pNd, m_nSttCnt );
+ rPam.SetMark();
+ rPam.GetPoint()->nNode = m_nEndNd - m_nOffset;
+ rPam.GetPoint()->nContent.Assign( rPam.GetCntntNode(), m_nEndCnt );
+
+ pDoc->DeleteAndJoin( rPam );
+ rPam.DeleteMark();
+ pNd = rPam.GetNode()->GetTxtNode();
+ OSL_ENSURE( pNd, "Wo ist der TextNode geblieben?" );
+ aIdx.Assign( pNd, m_nSttCnt );
+ }
+
+ if( m_bSplitNext )
+ {
+ SwPosition aPos( *pNd, aIdx );
+ pDoc->SplitNode( aPos, false );
+ pNd->RestoreMetadata(m_pMetadataUndoEnd);
+ pNd = pDoc->GetNodes()[ m_nSttNd - m_nOffset ]->GetTxtNode();
+ aIdx.Assign( pNd, m_nSttCnt );
+ // METADATA: restore
+ pNd->RestoreMetadata(m_pMetadataUndoStart);
+ }
+
+ if (m_sOld.getLength())
+ {
+ pNd->InsertText( m_sOld, aIdx );
+ }
+
+ if( pHistory )
+ {
+ if( pNd->GetpSwpHints() )
+ pNd->ClearSwpHintsArr( true );
+
+ pHistory->TmpRollback( pDoc, m_nSetPos, false );
+ if ( m_nSetPos ) // there were footnotes/FlyFrames
+ {
+ // gibts ausser diesen noch andere ?
+ if( m_nSetPos < pHistory->Count() )
+ {
+ // dann sicher die Attribute anderen Attribute
+ SwHistory aHstr;
+ aHstr.Move( 0, pHistory, m_nSetPos );
+ pHistory->Rollback( pDoc );
+ pHistory->Move( 0, &aHstr );
+ }
+ else
+ {
+ pHistory->Rollback( pDoc );
+ DELETEZ( pHistory );
+ }
+ }
+ }
+
+ rPam.GetPoint()->nNode = m_nSttNd;
+ rPam.GetPoint()->nContent = aIdx;
+}
+
+void SwUndoReplace::Impl::RedoImpl(::sw::UndoRedoContext & rContext)
+{
+ SwDoc & rDoc = rContext.GetDoc();
+ SwPaM & rPam(rContext.GetCursorSupplier().CreateNewShellCursor());
+ rPam.DeleteMark();
+ rPam.GetPoint()->nNode = m_nSttNd;
+
+ SwTxtNode* pNd = rPam.GetPoint()->nNode.GetNode().GetTxtNode();
+ OSL_ENSURE( pNd, "Wo ist der TextNode geblieben?" );
+ rPam.GetPoint()->nContent.Assign( pNd, m_nSttCnt );
+ rPam.SetMark();
+ if( m_bSplitNext )
+ {
+ rPam.GetPoint()->nNode = m_nSttNd + 1;
+ pNd = rPam.GetPoint()->nNode.GetNode().GetTxtNode();
+ }
+ rPam.GetPoint()->nContent.Assign( pNd, m_nSelEnd );
+
+ if( pHistory )
+ {
+ SwHistory* pSave = pHistory;
+ SwHistory aHst;
+ pHistory = &aHst;
+ DelCntntIndex( *rPam.GetMark(), *rPam.GetPoint() );
+ m_nSetPos = pHistory->Count();
+
+ pHistory = pSave;
+ pHistory->Move( 0, &aHst );
+ }
+ else
+ {
+ pHistory = new SwHistory;
+ DelCntntIndex( *rPam.GetMark(), *rPam.GetPoint() );
+ m_nSetPos = pHistory->Count();
+ if( !m_nSetPos )
+ delete pHistory, pHistory = 0;
+ }
+
+ rDoc.ReplaceRange( rPam, m_sIns, m_bRegExp );
+ rPam.DeleteMark();
+}
+
+void SwUndoReplace::Impl::SetEnd(SwPaM const& rPam)
+{
+ if( rPam.GetPoint()->nNode != rPam.GetMark()->nNode )
+ {
+ // multiple paragraphs were inserted
+ const SwPosition* pEnd = rPam.End();
+ m_nEndNd = m_nOffset + pEnd->nNode.GetIndex();
+ m_nEndCnt = pEnd->nContent.GetIndex();
+ }
+}
+
+
+// SwUndoReRead //////////////////////////////////////////////////////////
+
+
+SwUndoReRead::SwUndoReRead( const SwPaM& rPam, const SwGrfNode& rGrfNd )
+ : SwUndo( UNDO_REREAD ), nPos( rPam.GetPoint()->nNode.GetIndex() )
+{
+ SaveGraphicData( rGrfNd );
+}
+
+
+SwUndoReRead::~SwUndoReRead()
+{
+ delete pGrf;
+ delete pNm;
+ delete pFltr;
+}
+
+
+void SwUndoReRead::SetAndSave(::sw::UndoRedoContext & rContext)
+{
+ SwDoc & rDoc = rContext.GetDoc();
+ SwGrfNode* pGrfNd = rDoc.GetNodes()[ nPos ]->GetGrfNode();
+
+ if( !pGrfNd )
+ return ;
+
+ // die alten Werte zwischen speichern
+ Graphic* pOldGrf = pGrf;
+ String* pOldNm = pNm;
+ String* pOldFltr = pFltr;
+ sal_uInt16 nOldMirr = nMirr;
+
+ SaveGraphicData( *pGrfNd );
+ if( pOldNm )
+ {
+ pGrfNd->ReRead( *pOldNm, pFltr ? *pFltr : aEmptyStr, 0, 0, sal_True );
+ delete pOldNm;
+ delete pOldFltr;
+ }
+ else
+ {
+ pGrfNd->ReRead( aEmptyStr, aEmptyStr, pOldGrf, 0, sal_True );
+ delete pOldGrf;
+ }
+
+ if( RES_MIRROR_GRAPH_DONT != nOldMirr )
+ pGrfNd->SetAttr( SwMirrorGrf() );
+
+ rContext.SetSelections(pGrfNd->GetFlyFmt(), 0);
+}
+
+
+void SwUndoReRead::UndoImpl(::sw::UndoRedoContext & rContext)
+{
+ SetAndSave(rContext);
+}
+
+
+void SwUndoReRead::RedoImpl(::sw::UndoRedoContext & rContext)
+{
+ SetAndSave(rContext);
+}
+
+
+void SwUndoReRead::SaveGraphicData( const SwGrfNode& rGrfNd )
+{
+ if( rGrfNd.IsGrfLink() )
+ {
+ pNm = new String;
+ pFltr = new String;
+ rGrfNd.GetFileFilterNms( pNm, pFltr );
+ pGrf = 0;
+ }
+ else
+ {
+ ((SwGrfNode&)rGrfNd).SwapIn( sal_True );
+ pGrf = new Graphic( rGrfNd.GetGrf() );
+ pNm = pFltr = 0;
+ }
+ nMirr = rGrfNd.GetSwAttrSet().GetMirrorGrf().GetValue();
+}
+
+/* */
+
+SwUndoInsertLabel::SwUndoInsertLabel( const SwLabelType eTyp,
+ const String &rTxt,
+ const String& rSeparator,
+ const String& rNumberSeparator,
+ const sal_Bool bBef,
+ const sal_uInt16 nInitId,
+ const String& rCharacterStyle,
+ const sal_Bool bCpyBorder )
+ : SwUndo( UNDO_INSERTLABEL ),
+ sText( rTxt ),
+ sSeparator( rSeparator ),
+ sNumberSeparator( rNumberSeparator ),//#i61007# order of captions
+ sCharacterStyle( rCharacterStyle ),
+ nFldId( nInitId ),
+ eType( eTyp ),
+ nLayerId( 0 ),
+ bBefore( bBef ),
+ bCpyBrd( bCpyBorder )
+{
+ bUndoKeep = sal_False;
+ OBJECT.pUndoFly = 0;
+ OBJECT.pUndoAttr = 0;
+}
+
+SwUndoInsertLabel::~SwUndoInsertLabel()
+{
+ if( LTYPE_OBJECT == eType || LTYPE_DRAW == eType )
+ {
+ delete OBJECT.pUndoFly;
+ delete OBJECT.pUndoAttr;
+ }
+ else
+ delete NODE.pUndoInsNd;
+}
+
+void SwUndoInsertLabel::UndoImpl(::sw::UndoRedoContext & rContext)
+{
+ SwDoc & rDoc = rContext.GetDoc();
+
+ if( LTYPE_OBJECT == eType || LTYPE_DRAW == eType )
+ {
+ OSL_ENSURE( OBJECT.pUndoAttr && OBJECT.pUndoFly, "Pointer nicht initialisiert" );
+ SwFrmFmt* pFmt;
+ SdrObject *pSdrObj = 0;
+ if( OBJECT.pUndoAttr &&
+ 0 != (pFmt = (SwFrmFmt*)OBJECT.pUndoAttr->GetFmt( rDoc )) &&
+ ( LTYPE_DRAW != eType ||
+ 0 != (pSdrObj = pFmt->FindSdrObject()) ) )
+ {
+ OBJECT.pUndoAttr->UndoImpl(rContext);
+ OBJECT.pUndoFly->UndoImpl(rContext);
+ if( LTYPE_DRAW == eType )
+ {
+ pSdrObj->SetLayer( nLayerId );
+ }
+ }
+ }
+ else if( NODE.nNode )
+ {
+ if ( eType == LTYPE_TABLE && bUndoKeep )
+ {
+ SwTableNode *pNd = rDoc.GetNodes()[
+ rDoc.GetNodes()[NODE.nNode-1]->StartOfSectionIndex()]->GetTableNode();
+ if ( pNd )
+ pNd->GetTable().GetFrmFmt()->ResetFmtAttr( RES_KEEP );
+ }
+ SwPaM aPam( rDoc.GetNodes().GetEndOfContent() );
+ aPam.GetPoint()->nNode = NODE.nNode;
+ aPam.SetMark();
+ aPam.GetPoint()->nNode = NODE.nNode + 1;
+ NODE.pUndoInsNd = new SwUndoDelete( aPam, sal_True );
+ }
+}
+
+
+void SwUndoInsertLabel::RedoImpl(::sw::UndoRedoContext & rContext)
+{
+ SwDoc & rDoc = rContext.GetDoc();
+
+ if( LTYPE_OBJECT == eType || LTYPE_DRAW == eType )
+ {
+ OSL_ENSURE( OBJECT.pUndoAttr && OBJECT.pUndoFly, "Pointer nicht initialisiert" );
+ SwFrmFmt* pFmt;
+ SdrObject *pSdrObj = 0;
+ if( OBJECT.pUndoAttr &&
+ 0 != (pFmt = (SwFrmFmt*)OBJECT.pUndoAttr->GetFmt( rDoc )) &&
+ ( LTYPE_DRAW != eType ||
+ 0 != (pSdrObj = pFmt->FindSdrObject()) ) )
+ {
+ OBJECT.pUndoFly->RedoImpl(rContext);
+ OBJECT.pUndoAttr->RedoImpl(rContext);
+ if( LTYPE_DRAW == eType )
+ {
+ pSdrObj->SetLayer( nLayerId );
+ if( pSdrObj->GetLayer() == rDoc.GetHellId() )
+ pSdrObj->SetLayer( rDoc.GetHeavenId() );
+ // OD 02.07.2003 #108784#
+ else if( pSdrObj->GetLayer() == rDoc.GetInvisibleHellId() )
+ pSdrObj->SetLayer( rDoc.GetInvisibleHeavenId() );
+ }
+ }
+ }
+ else if( NODE.pUndoInsNd )
+ {
+ if ( eType == LTYPE_TABLE && bUndoKeep )
+ {
+ SwTableNode *pNd = rDoc.GetNodes()[
+ rDoc.GetNodes()[NODE.nNode-1]->StartOfSectionIndex()]->GetTableNode();
+ if ( pNd )
+ pNd->GetTable().GetFrmFmt()->SetFmtAttr( SvxFmtKeepItem(sal_True, RES_KEEP) );
+ }
+ NODE.pUndoInsNd->UndoImpl(rContext);
+ delete NODE.pUndoInsNd, NODE.pUndoInsNd = 0;
+ }
+}
+
+void SwUndoInsertLabel::RepeatImpl(::sw::RepeatContext & rContext)
+{
+ SwDoc & rDoc = rContext.GetDoc();
+ const SwPosition& rPos = *rContext.GetRepeatPaM().GetPoint();
+
+ sal_uLong nIdx = 0;
+
+ SwCntntNode* pCNd = rPos.nNode.GetNode().GetCntntNode();
+ if( pCNd )
+ switch( eType )
+ {
+ case LTYPE_TABLE:
+ {
+ const SwTableNode* pTNd = pCNd->FindTableNode();
+ if( pTNd )
+ nIdx = pTNd->GetIndex();
+ }
+ break;
+
+ case LTYPE_FLY:
+ case LTYPE_OBJECT:
+ {
+ SwFlyFrm* pFly;
+ SwCntntFrm *pCnt = pCNd->getLayoutFrm( rDoc.GetCurrentLayout() );
+ if( pCnt && 0 != ( pFly = pCnt->FindFlyFrm() ) )
+ nIdx = pFly->GetFmt()->GetCntnt().GetCntntIdx()->GetIndex();
+ }
+ break;
+ case LTYPE_DRAW:
+ break;
+ }
+
+ if( nIdx )
+ {
+ rDoc.InsertLabel( eType, sText, sSeparator, sNumberSeparator, bBefore,
+ nFldId, nIdx, sCharacterStyle, bCpyBrd );
+ }
+}
+
+// #111827#
+SwRewriter SwUndoInsertLabel::GetRewriter() const
+{
+ SwRewriter aRewriter;
+
+ String aTmpStr;
+
+ aTmpStr += String(SW_RES(STR_START_QUOTE));
+ aTmpStr += ShortenString(sText, nUndoStringLength,
+ String(SW_RES(STR_LDOTS)));
+ aTmpStr += String(SW_RES(STR_END_QUOTE));
+
+ aRewriter.AddRule(UNDO_ARG1, aTmpStr);
+
+ return aRewriter;
+}
+
+void SwUndoInsertLabel::SetFlys( SwFrmFmt& rOldFly, SfxItemSet& rChgSet,
+ SwFrmFmt& rNewFly )
+{
+ if( LTYPE_OBJECT == eType || LTYPE_DRAW == eType )
+ {
+ SwUndoFmtAttrHelper aTmp( rOldFly, false );
+ rOldFly.SetFmtAttr( rChgSet );
+ if ( aTmp.GetUndo() )
+ {
+ OBJECT.pUndoAttr = aTmp.ReleaseUndo();
+ }
+ OBJECT.pUndoFly = new SwUndoInsLayFmt( &rNewFly,0,0 );
+ }
+}
+
+void SwUndoInsertLabel::SetDrawObj( sal_uInt8 nLId )
+{
+ if( LTYPE_DRAW == eType )
+ {
+ nLayerId = nLId;
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/undo/unmove.cxx b/sw/source/core/undo/unmove.cxx
new file mode 100644
index 000000000000..f7b01da4caa2
--- /dev/null
+++ b/sw/source/core/undo/unmove.cxx
@@ -0,0 +1,357 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+#include <UndoSplitMove.hxx>
+
+#include <doc.hxx>
+#include <IDocumentUndoRedo.hxx>
+#include <pam.hxx>
+#include <swundo.hxx> // fuer die UndoIds
+#include <ndtxt.hxx>
+#include <UndoCore.hxx>
+#include <rolbck.hxx>
+
+
+// MOVE
+
+SwUndoMove::SwUndoMove( const SwPaM& rRange, const SwPosition& rMvPos )
+ : SwUndo( UNDO_MOVE ), SwUndRng( rRange ),
+ nMvDestNode( rMvPos.nNode.GetIndex() ),
+ nMvDestCntnt( rMvPos.nContent.GetIndex() ),
+ bMoveRedlines( false )
+{
+ bMoveRange = bJoinNext = bJoinPrev = sal_False;
+
+ // StartNode vorm loeschen von Fussnoten besorgen!
+ SwDoc* pDoc = rRange.GetDoc();
+ SwTxtNode* pTxtNd = pDoc->GetNodes()[ nSttNode ]->GetTxtNode();
+ SwTxtNode* pEndTxtNd = pDoc->GetNodes()[ nEndNode ]->GetTxtNode();
+
+ pHistory = new SwHistory;
+
+ if( pTxtNd )
+ {
+ pHistory->Add( pTxtNd->GetTxtColl(), nSttNode, ND_TEXTNODE );
+ if ( pTxtNd->GetpSwpHints() )
+ {
+ pHistory->CopyAttr( pTxtNd->GetpSwpHints(), nSttNode,
+ 0, pTxtNd->GetTxt().Len(), false );
+ }
+ if( pTxtNd->HasSwAttrSet() )
+ pHistory->CopyFmtAttr( *pTxtNd->GetpSwAttrSet(), nSttNode );
+ }
+ if( pEndTxtNd && pEndTxtNd != pTxtNd )
+ {
+ pHistory->Add( pEndTxtNd->GetTxtColl(), nEndNode, ND_TEXTNODE );
+ if ( pEndTxtNd->GetpSwpHints() )
+ {
+ pHistory->CopyAttr( pEndTxtNd->GetpSwpHints(), nEndNode,
+ 0, pEndTxtNd->GetTxt().Len(), false );
+ }
+ if( pEndTxtNd->HasSwAttrSet() )
+ pHistory->CopyFmtAttr( *pEndTxtNd->GetpSwAttrSet(), nEndNode );
+ }
+
+ pTxtNd = rMvPos.nNode.GetNode().GetTxtNode();
+ if (0 != pTxtNd)
+ {
+ pHistory->Add( pTxtNd->GetTxtColl(), nMvDestNode, ND_TEXTNODE );
+ if ( pTxtNd->GetpSwpHints() )
+ {
+ pHistory->CopyAttr( pTxtNd->GetpSwpHints(), nMvDestNode,
+ 0, pTxtNd->GetTxt().Len(), false );
+ }
+ if( pTxtNd->HasSwAttrSet() )
+ pHistory->CopyFmtAttr( *pTxtNd->GetpSwAttrSet(), nMvDestNode );
+ }
+
+
+ nFtnStt = pHistory->Count();
+ DelFtn( rRange );
+
+ if( pHistory && !pHistory->Count() )
+ DELETEZ( pHistory );
+}
+
+
+SwUndoMove::SwUndoMove( SwDoc* pDoc, const SwNodeRange& rRg,
+ const SwNodeIndex& rMvPos )
+ : SwUndo( UNDO_MOVE ),
+ nMvDestNode( rMvPos.GetIndex() ),
+ bMoveRedlines( false )
+{
+ bMoveRange = sal_True;
+ bJoinNext = bJoinPrev = sal_False;
+
+ nSttCntnt = nEndCntnt = nMvDestCntnt = STRING_MAXLEN;
+
+ nSttNode = rRg.aStart.GetIndex();
+ nEndNode = rRg.aEnd.GetIndex();
+
+// DelFtn( rRange );
+
+ // wird aus dem CntntBereich in den Sonderbereich verschoben ?
+ sal_uLong nCntntStt = pDoc->GetNodes().GetEndOfAutotext().GetIndex();
+ if( nMvDestNode < nCntntStt && rRg.aStart.GetIndex() > nCntntStt )
+ {
+ // loesche alle Fussnoten. Diese sind dort nicht erwuenscht.
+ SwPosition aPtPos( rRg.aEnd );
+ SwCntntNode* pCNd = rRg.aEnd.GetNode().GetCntntNode();
+ if( pCNd )
+ aPtPos.nContent.Assign( pCNd, pCNd->Len() );
+ SwPosition aMkPos( rRg.aStart );
+ if( 0 != ( pCNd = aMkPos.nNode.GetNode().GetCntntNode() ))
+ aMkPos.nContent.Assign( pCNd, 0 );
+
+ DelCntntIndex( aMkPos, aPtPos, nsDelCntntType::DELCNT_FTN );
+
+ if( pHistory && !pHistory->Count() )
+ DELETEZ( pHistory );
+ }
+
+ nFtnStt = 0;
+}
+
+
+
+void SwUndoMove::SetDestRange( const SwPaM& rRange,
+ const SwPosition& rInsPos,
+ sal_Bool bJoin, sal_Bool bCorrPam )
+{
+ const SwPosition *pStt = rRange.Start(),
+ *pEnd = rRange.GetPoint() == pStt
+ ? rRange.GetMark()
+ : rRange.GetPoint();
+
+ nDestSttNode = pStt->nNode.GetIndex();
+ nDestSttCntnt = pStt->nContent.GetIndex();
+ nDestEndNode = pEnd->nNode.GetIndex();
+ nDestEndCntnt = pEnd->nContent.GetIndex();
+
+ nInsPosNode = rInsPos.nNode.GetIndex();
+ nInsPosCntnt = rInsPos.nContent.GetIndex();
+
+ if( bCorrPam )
+ {
+ nDestSttNode--;
+ nDestEndNode--;
+ }
+
+ bJoinNext = nDestSttNode != nDestEndNode &&
+ pStt->nNode.GetNode().GetTxtNode() &&
+ pEnd->nNode.GetNode().GetTxtNode();
+ bJoinPrev = bJoin;
+}
+
+
+void SwUndoMove::SetDestRange( const SwNodeIndex& rStt,
+ const SwNodeIndex& rEnd,
+ const SwNodeIndex& rInsPos )
+{
+ nDestSttNode = rStt.GetIndex();
+ nDestEndNode = rEnd.GetIndex();
+ if( nDestSttNode > nDestEndNode )
+ {
+ nDestSttNode = nDestEndNode;
+ nDestEndNode = rStt.GetIndex();
+ }
+ nInsPosNode = rInsPos.GetIndex();
+
+ nDestSttCntnt = nDestEndCntnt = nInsPosCntnt = STRING_MAXLEN;
+}
+
+
+void SwUndoMove::UndoImpl(::sw::UndoRedoContext & rContext)
+{
+ SwDoc *const pDoc = & rContext.GetDoc();
+
+ // Block, damit aus diesem gesprungen werden kann
+ do {
+ // erzeuge aus den Werten die Insert-Position und den Bereich
+ SwNodeIndex aIdx( pDoc->GetNodes(), nDestSttNode );
+
+ if( bMoveRange )
+ {
+ // nur ein Move mit SwRange
+ SwNodeRange aRg( aIdx, aIdx );
+ aRg.aEnd = nDestEndNode;
+ aIdx = nInsPosNode;
+ bool bSuccess = pDoc->MoveNodeRange( aRg, aIdx,
+ IDocumentContentOperations::DOC_MOVEDEFAULT );
+ if (!bSuccess)
+ break;
+ }
+ else
+ {
+ SwPaM aPam( aIdx.GetNode(), nDestSttCntnt,
+ *pDoc->GetNodes()[ nDestEndNode ], nDestEndCntnt );
+
+ // #i17764# if redlines are to be moved, we may not remove them before
+ // pDoc->Move gets a chance to handle them
+ if( ! bMoveRedlines )
+ RemoveIdxFromRange( aPam, sal_False );
+
+ SwPosition aPos( *pDoc->GetNodes()[ nInsPosNode] );
+ SwCntntNode* pCNd = aPos.nNode.GetNode().GetCntntNode();
+ aPos.nContent.Assign( pCNd, nInsPosCntnt );
+
+ if( pCNd->HasSwAttrSet() )
+ pCNd->ResetAllAttr();
+
+ if( pCNd->IsTxtNode() && ((SwTxtNode*)pCNd)->GetpSwpHints() )
+ ((SwTxtNode*)pCNd)->ClearSwpHintsArr( false );
+
+ // an der InsertPos erstmal alle Attribute entfernen,
+ const bool bSuccess = pDoc->MoveRange( aPam, aPos, (bMoveRedlines)
+ ? IDocumentContentOperations::DOC_MOVEREDLINES
+ : IDocumentContentOperations::DOC_MOVEDEFAULT );
+ if (!bSuccess)
+ break;
+
+ aPam.Exchange();
+ aPam.DeleteMark();
+// pDoc->ResetAttr( aPam, sal_False );
+ if( aPam.GetNode()->IsCntntNode() )
+ aPam.GetNode()->GetCntntNode()->ResetAllAttr();
+ // der Pam wird jetzt aufgegeben.
+ }
+
+ SwTxtNode* pTxtNd = aIdx.GetNode().GetTxtNode();
+ if( bJoinNext )
+ {
+ {
+ RemoveIdxRel( aIdx.GetIndex() + 1, SwPosition( aIdx,
+ SwIndex( pTxtNd, pTxtNd->GetTxt().Len() ) ) );
+ }
+ // sind keine Pams mehr im naechsten TextNode
+ pTxtNd->JoinNext();
+ }
+
+ if( bJoinPrev && pTxtNd->CanJoinPrev( &aIdx ) )
+ {
+ // ?? sind keine Pams mehr im naechsten TextNode ??
+ pTxtNd = aIdx.GetNode().GetTxtNode();
+ {
+ RemoveIdxRel( aIdx.GetIndex() + 1, SwPosition( aIdx,
+ SwIndex( pTxtNd, pTxtNd->GetTxt().Len() ) ) );
+ }
+ pTxtNd->JoinNext();
+ }
+
+ } while( sal_False );
+
+ if( pHistory )
+ {
+ if( nFtnStt != pHistory->Count() )
+ pHistory->Rollback( pDoc, nFtnStt );
+ pHistory->TmpRollback( pDoc, 0 );
+ pHistory->SetTmpEnd( pHistory->Count() );
+ }
+
+ // setze noch den Cursor auf den Undo-Bereich
+ if( !bMoveRange )
+ {
+ AddUndoRedoPaM(rContext);
+ }
+}
+
+
+void SwUndoMove::RedoImpl(::sw::UndoRedoContext & rContext)
+{
+ SwPaM *const pPam = & AddUndoRedoPaM(rContext);
+ SwDoc & rDoc = rContext.GetDoc();
+
+ SwNodes& rNds = rDoc.GetNodes();
+ SwNodeIndex aIdx( rNds, nMvDestNode );
+
+ if( bMoveRange )
+ {
+ // nur ein Move mit SwRange
+ SwNodeRange aRg( rNds, nSttNode, rNds, nEndNode );
+ rDoc.MoveNodeRange( aRg, aIdx, (bMoveRedlines)
+ ? IDocumentContentOperations::DOC_MOVEREDLINES
+ : IDocumentContentOperations::DOC_MOVEDEFAULT );
+ }
+ else
+ {
+ SwPaM aPam( *pPam->GetPoint() );
+ SetPaM( aPam );
+ SwPosition aMvPos( aIdx, SwIndex( aIdx.GetNode().GetCntntNode(),
+ nMvDestCntnt ));
+
+ DelFtn( aPam );
+ RemoveIdxFromRange( aPam, sal_False );
+
+ aIdx = aPam.Start()->nNode;
+ sal_Bool bJoinTxt = aIdx.GetNode().IsTxtNode();
+
+ aIdx--;
+ rDoc.MoveRange( aPam, aMvPos,
+ IDocumentContentOperations::DOC_MOVEDEFAULT );
+
+ if( nSttNode != nEndNode && bJoinTxt )
+ {
+ aIdx++;
+ SwTxtNode * pTxtNd = aIdx.GetNode().GetTxtNode();
+ if( pTxtNd && pTxtNd->CanJoinNext() )
+ {
+ {
+ RemoveIdxRel( aIdx.GetIndex() + 1, SwPosition( aIdx,
+ SwIndex( pTxtNd, pTxtNd->GetTxt().Len() ) ) );
+ }
+ pTxtNd->JoinNext();
+ }
+ }
+ *pPam->GetPoint() = *aPam.GetPoint();
+ pPam->SetMark();
+ *pPam->GetMark() = *aPam.GetMark();
+ }
+}
+
+
+void SwUndoMove::DelFtn( const SwPaM& rRange )
+{
+ // wird aus dem CntntBereich in den Sonderbereich verschoben ?
+ SwDoc* pDoc = rRange.GetDoc();
+ sal_uLong nCntntStt = pDoc->GetNodes().GetEndOfAutotext().GetIndex();
+ if( nMvDestNode < nCntntStt &&
+ rRange.GetPoint()->nNode.GetIndex() >= nCntntStt )
+ {
+ // loesche alle Fussnoten. Diese sind dort nicht erwuenscht.
+ DelCntntIndex( *rRange.GetMark(), *rRange.GetPoint(),
+ nsDelCntntType::DELCNT_FTN );
+
+ if( pHistory && !pHistory->Count() )
+ delete pHistory, pHistory = 0;
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/undo/unnum.cxx b/sw/source/core/undo/unnum.cxx
new file mode 100644
index 000000000000..c775da164d01
--- /dev/null
+++ b/sw/source/core/undo/unnum.cxx
@@ -0,0 +1,454 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+#include <UndoNumbering.hxx>
+
+#include <hintids.hxx>
+#include <editeng/lrspitem.hxx>
+#include <doc.hxx>
+#include <IDocumentUndoRedo.hxx>
+#include <swundo.hxx> // fuer die UndoIds
+#include <pam.hxx>
+#include <ndtxt.hxx>
+#include <UndoCore.hxx>
+#include <rolbck.hxx>
+
+
+SV_DECL_PTRARR_DEL( _SfxPoolItems, SfxPoolItem*, 16, 16 )
+SV_IMPL_PTRARR( _SfxPoolItems, SfxPoolItem* );
+
+
+SwUndoInsNum::SwUndoInsNum( const SwNumRule& rOldRule,
+ const SwNumRule& rNewRule,
+ SwUndoId nUndoId )
+ : SwUndo( nUndoId ),
+ aNumRule( rNewRule ), pHistory( 0 ), nSttSet( ULONG_MAX ),
+ pOldNumRule( new SwNumRule( rOldRule )), nLRSavePos( 0 )
+{
+}
+
+SwUndoInsNum::SwUndoInsNum( const SwPaM& rPam, const SwNumRule& rRule )
+ : SwUndo( UNDO_INSNUM ), SwUndRng( rPam ),
+ aNumRule( rRule ), pHistory( 0 ),
+ nSttSet( ULONG_MAX ), pOldNumRule( 0 ), nLRSavePos( 0 )
+{
+}
+
+SwUndoInsNum::SwUndoInsNum( const SwPosition& rPos, const SwNumRule& rRule,
+ const String& rReplaceRule )
+ : SwUndo( UNDO_INSNUM ),
+ aNumRule( rRule ), pHistory( 0 ),
+ nSttSet( ULONG_MAX ), pOldNumRule( 0 ),
+ sReplaceRule( rReplaceRule ), nLRSavePos( 0 )
+{
+ // keine Selektion !!
+ nEndNode = 0, nEndCntnt = USHRT_MAX;
+ nSttNode = rPos.nNode.GetIndex();
+ nSttCntnt = rPos.nContent.GetIndex();
+}
+
+SwUndoInsNum::~SwUndoInsNum()
+{
+ delete pHistory;
+ delete pOldNumRule;
+}
+
+SwRewriter SwUndoInsNum::GetRewriter() const
+{
+ SwRewriter aResult;
+ if( UNDO_INSFMTATTR == GetId() )
+ aResult.AddRule(UNDO_ARG1, aNumRule.GetName());
+ return aResult;
+}
+
+void SwUndoInsNum::UndoImpl(::sw::UndoRedoContext & rContext)
+{
+ SwDoc & rDoc = rContext.GetDoc();
+
+ if( pOldNumRule )
+ rDoc.ChgNumRuleFmts( *pOldNumRule );
+
+ if( pHistory )
+ {
+ SwTxtNode* pNd;
+ if( ULONG_MAX != nSttSet &&
+ 0 != ( pNd = rDoc.GetNodes()[ nSttSet ]->GetTxtNode() ))
+ pNd->SetListRestart( sal_True );
+ else
+ pNd = 0;
+
+
+ if( nLRSavePos )
+ {
+ // sofort Updaten, damit eventuell "alte" LRSpaces wieder
+ // gueltig werden.
+ // !!! Dafuer suche aber erstmal den richtigen NumRule - Namen!
+ if( !pNd && nSttNode )
+ pNd = rDoc.GetNodes()[ nSttNode ]->GetTxtNode();
+
+ pHistory->TmpRollback( &rDoc, nLRSavePos );
+
+ }
+ pHistory->TmpRollback( &rDoc, 0 );
+ pHistory->SetTmpEnd( pHistory->Count() );
+ }
+
+ if (nSttNode)
+ {
+ AddUndoRedoPaM(rContext);
+ }
+}
+
+void SwUndoInsNum::RedoImpl(::sw::UndoRedoContext & rContext)
+{
+ SwDoc & rDoc = rContext.GetDoc();
+
+ if( pOldNumRule )
+ rDoc.ChgNumRuleFmts( aNumRule );
+ else if( pHistory )
+ {
+ SwPaM & rPam( AddUndoRedoPaM(rContext) );
+ if( sReplaceRule.Len() )
+ {
+ rDoc.ReplaceNumRule(*rPam.GetPoint(),
+ sReplaceRule, aNumRule.GetName() );
+ }
+ else
+ {
+ // --> OD 2005-02-25 #i42921# - adapt to changed signature
+ rDoc.SetNumRule(rPam, aNumRule, false);
+ // <--
+ }
+ }
+}
+
+void SwUndoInsNum::SetLRSpaceEndPos()
+{
+ if( pHistory )
+ nLRSavePos = pHistory->Count();
+}
+
+void SwUndoInsNum::RepeatImpl(::sw::RepeatContext & rContext)
+{
+ SwDoc & rDoc(rContext.GetDoc());
+ if( nSttNode )
+ {
+ if( !sReplaceRule.Len() )
+ {
+ // --> OD 2005-02-25 #i42921# - adapt to changed signature
+ rDoc.SetNumRule(rContext.GetRepeatPaM(), aNumRule, false);
+ // <--
+ }
+ }
+ else
+ {
+ rDoc.ChgNumRuleFmts( aNumRule );
+ }
+}
+
+SwHistory* SwUndoInsNum::GetHistory()
+{
+ if( !pHistory )
+ pHistory = new SwHistory;
+ return pHistory;
+}
+
+void SwUndoInsNum::SaveOldNumRule( const SwNumRule& rOld )
+{
+ if( !pOldNumRule )
+ pOldNumRule = new SwNumRule( rOld );
+}
+
+/* */
+
+
+SwUndoDelNum::SwUndoDelNum( const SwPaM& rPam )
+ : SwUndo( UNDO_DELNUM ), SwUndRng( rPam )
+{
+ aNodes.reserve( nEndNode - nSttNode > 255 ? 255 : nEndNode - nSttNode );
+ pHistory = new SwHistory;
+}
+
+SwUndoDelNum::~SwUndoDelNum()
+{
+ delete pHistory;
+}
+
+void SwUndoDelNum::UndoImpl(::sw::UndoRedoContext & rContext)
+{
+ SwDoc & rDoc = rContext.GetDoc();
+
+ pHistory->TmpRollback( &rDoc, 0 );
+ pHistory->SetTmpEnd( pHistory->Count() );
+
+ for( std::vector<NodeLevel>::const_iterator i = aNodes.begin(); i != aNodes.end(); ++i )
+ {
+ SwTxtNode* pNd = rDoc.GetNodes()[ i->index ]->GetTxtNode();
+ OSL_ENSURE( pNd, "Where has the TextNode gone?" );
+ pNd->SetAttrListLevel( i->level );
+
+ if( pNd->GetCondFmtColl() )
+ pNd->ChkCondColl();
+ }
+
+ AddUndoRedoPaM(rContext);
+}
+
+void SwUndoDelNum::RedoImpl(::sw::UndoRedoContext & rContext)
+{
+ SwPaM & rPam( AddUndoRedoPaM(rContext) );
+ rContext.GetDoc().DelNumRules(rPam);
+}
+
+void SwUndoDelNum::RepeatImpl(::sw::RepeatContext & rContext)
+{
+ rContext.GetDoc().DelNumRules(rContext.GetRepeatPaM());
+}
+
+void SwUndoDelNum::AddNode( const SwTxtNode& rNd, sal_Bool )
+{
+ if( rNd.GetNumRule() )
+ {
+ aNodes.push_back( NodeLevel( rNd.GetIndex(), rNd.GetActualListLevel() ) );
+ }
+}
+
+
+/* */
+
+
+SwUndoMoveNum::SwUndoMoveNum( const SwPaM& rPam, long nOff, sal_Bool bIsOutlMv )
+ : SwUndo( bIsOutlMv ? UNDO_OUTLINE_UD : UNDO_MOVENUM ),
+ SwUndRng( rPam ),
+ nNewStt( 0 ), nOffset( nOff )
+{
+ // nOffset: nach unten => 1
+ // nach oben => -1
+}
+
+void SwUndoMoveNum::UndoImpl(::sw::UndoRedoContext & rContext)
+{
+ sal_uLong nTmpStt = nSttNode, nTmpEnd = nEndNode;
+
+ if( nEndNode || USHRT_MAX != nEndCntnt ) // Bereich ?
+ {
+ if( nNewStt < nSttNode ) // nach vorne verschoben
+ nEndNode = nEndNode - ( nSttNode - nNewStt );
+ else
+ nEndNode = nEndNode + ( nNewStt - nSttNode );
+ }
+ nSttNode = nNewStt;
+
+//JP 22.06.95: wird wollen die Bookmarks/Verzeichnisse behalten, oder?
+// SetPaM( rUndoIter );
+// RemoveIdxFromRange( *rUndoIter.pAktPam, sal_True );
+
+ SwPaM & rPam( AddUndoRedoPaM(rContext) );
+ rContext.GetDoc().MoveParagraph( rPam, -nOffset,
+ UNDO_OUTLINE_UD == GetId() );
+ nSttNode = nTmpStt;
+ nEndNode = nTmpEnd;
+}
+
+void SwUndoMoveNum::RedoImpl(::sw::UndoRedoContext & rContext)
+{
+//JP 22.06.95: wird wollen die Bookmarks/Verzeichnisse behalten, oder?
+// SetPaM( rUndoIter );
+// RemoveIdxFromRange( *rUndoIter.pAktPam, sal_True );
+
+ SwPaM & rPam( AddUndoRedoPaM(rContext) );
+ rContext.GetDoc().MoveParagraph(rPam, nOffset, UNDO_OUTLINE_UD == GetId());
+}
+
+void SwUndoMoveNum::RepeatImpl(::sw::RepeatContext & rContext)
+{
+ SwDoc & rDoc = rContext.GetDoc();
+ if( UNDO_OUTLINE_UD == GetId() )
+ {
+ rDoc.MoveOutlinePara(rContext.GetRepeatPaM(),
+ 0 < nOffset ? 1 : -1 );
+ }
+ else
+ {
+ rDoc.MoveParagraph(rContext.GetRepeatPaM(), nOffset, sal_False);
+ }
+}
+
+/* */
+
+
+SwUndoNumUpDown::SwUndoNumUpDown( const SwPaM& rPam, short nOff )
+ : SwUndo( nOff > 0 ? UNDO_NUMUP : UNDO_NUMDOWN ), SwUndRng( rPam ),
+ nOffset( nOff )
+{
+ // nOffset: Down => 1
+ // Up => -1
+}
+
+void SwUndoNumUpDown::UndoImpl(::sw::UndoRedoContext & rContext)
+{
+ SwPaM & rPam( AddUndoRedoPaM(rContext) );
+ rContext.GetDoc().NumUpDown(rPam, 1 != nOffset );
+}
+
+void SwUndoNumUpDown::RedoImpl(::sw::UndoRedoContext & rContext)
+{
+ SwPaM & rPam( AddUndoRedoPaM(rContext) );
+ rContext.GetDoc().NumUpDown(rPam, 1 == nOffset);
+}
+
+void SwUndoNumUpDown::RepeatImpl(::sw::RepeatContext & rContext)
+{
+ rContext.GetDoc().NumUpDown(rContext.GetRepeatPaM(), 1 == nOffset);
+}
+
+/* */
+
+// #115901#
+SwUndoNumOrNoNum::SwUndoNumOrNoNum( const SwNodeIndex& rIdx, sal_Bool bOldNum,
+ sal_Bool bNewNum)
+ : SwUndo( UNDO_NUMORNONUM ), nIdx( rIdx.GetIndex() ), mbNewNum(bNewNum),
+ mbOldNum(bOldNum)
+{
+}
+
+// #115901#, #i40034#
+void SwUndoNumOrNoNum::UndoImpl(::sw::UndoRedoContext & rContext)
+{
+ SwNodeIndex aIdx( rContext.GetDoc().GetNodes(), nIdx );
+ SwTxtNode * pTxtNd = aIdx.GetNode().GetTxtNode();
+
+ if (NULL != pTxtNd)
+ {
+ pTxtNd->SetCountedInList(mbOldNum);
+ }
+}
+
+// #115901#, #i40034#
+void SwUndoNumOrNoNum::RedoImpl(::sw::UndoRedoContext & rContext)
+{
+ SwNodeIndex aIdx( rContext.GetDoc().GetNodes(), nIdx );
+ SwTxtNode * pTxtNd = aIdx.GetNode().GetTxtNode();
+
+ if (NULL != pTxtNd)
+ {
+ pTxtNd->SetCountedInList(mbNewNum);
+ }
+}
+
+// #115901#
+void SwUndoNumOrNoNum::RepeatImpl(::sw::RepeatContext & rContext)
+{
+ SwDoc & rDoc = rContext.GetDoc();
+ if (mbOldNum && ! mbNewNum)
+ {
+ rDoc.NumOrNoNum(rContext.GetRepeatPaM().GetPoint()->nNode, sal_False);
+ }
+ else if ( ! mbOldNum && mbNewNum )
+ {
+ rDoc.NumOrNoNum(rContext.GetRepeatPaM().GetPoint()->nNode, sal_True);
+ }
+}
+
+/* */
+
+SwUndoNumRuleStart::SwUndoNumRuleStart( const SwPosition& rPos, sal_Bool bFlg )
+ : SwUndo( UNDO_SETNUMRULESTART ),
+ nIdx( rPos.nNode.GetIndex() ), nOldStt( USHRT_MAX ),
+ nNewStt( USHRT_MAX ), bSetSttValue( sal_False ), bFlag( bFlg )
+{
+}
+
+SwUndoNumRuleStart::SwUndoNumRuleStart( const SwPosition& rPos, sal_uInt16 nStt )
+ : SwUndo( UNDO_SETNUMRULESTART ),
+ nIdx( rPos.nNode.GetIndex() ),
+ nOldStt( USHRT_MAX ), nNewStt( nStt ), bSetSttValue( sal_True )
+{
+ SwTxtNode* pTxtNd = rPos.nNode.GetNode().GetTxtNode();
+ if ( pTxtNd )
+ {
+ if ( pTxtNd->HasAttrListRestartValue() )
+ {
+ nOldStt = static_cast<sal_uInt16>(pTxtNd->GetAttrListRestartValue());
+ }
+ else
+ {
+ nOldStt = USHRT_MAX; // indicating, that the list restart value is not set
+ }
+ }
+}
+
+
+void SwUndoNumRuleStart::UndoImpl(::sw::UndoRedoContext & rContext)
+{
+ SwDoc & rDoc = rContext.GetDoc();
+ SwPosition const aPos( *rDoc.GetNodes()[ nIdx ] );
+ if( bSetSttValue )
+ {
+ rDoc.SetNodeNumStart( aPos, nOldStt );
+ }
+ else
+ {
+ rDoc.SetNumRuleStart( aPos, !bFlag );
+ }
+}
+
+
+void SwUndoNumRuleStart::RedoImpl(::sw::UndoRedoContext & rContext)
+{
+ SwDoc & rDoc = rContext.GetDoc();
+ SwPosition const aPos( *rDoc.GetNodes()[ nIdx ] );
+ if( bSetSttValue )
+ {
+ rDoc.SetNodeNumStart( aPos, nNewStt );
+ }
+ else
+ {
+ rDoc.SetNumRuleStart( aPos, bFlag );
+ }
+}
+
+
+void SwUndoNumRuleStart::RepeatImpl(::sw::RepeatContext & rContext)
+{
+ SwDoc & rDoc = rContext.GetDoc();
+ if( bSetSttValue )
+ {
+ rDoc.SetNodeNumStart(*rContext.GetRepeatPaM().GetPoint(), nNewStt);
+ }
+ else
+ {
+ rDoc.SetNumRuleStart(*rContext.GetRepeatPaM().GetPoint(), bFlag);
+ }
+}
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/undo/unoutl.cxx b/sw/source/core/undo/unoutl.cxx
new file mode 100644
index 000000000000..109387765fc6
--- /dev/null
+++ b/sw/source/core/undo/unoutl.cxx
@@ -0,0 +1,64 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+#include "doc.hxx"
+#include "swundo.hxx" // fuer die UndoIds
+#include "pam.hxx"
+#include "ndtxt.hxx"
+
+#include <UndoCore.hxx>
+
+
+SwUndoOutlineLeftRight::SwUndoOutlineLeftRight( const SwPaM& rPam,
+ short nOff )
+ : SwUndo( UNDO_OUTLINE_LR ), SwUndRng( rPam ), nOffset( nOff )
+{
+}
+
+void SwUndoOutlineLeftRight::UndoImpl(::sw::UndoRedoContext & rContext)
+{
+ SwPaM & rPaM( AddUndoRedoPaM(rContext) );
+ rContext.GetDoc().OutlineUpDown(rPaM, -nOffset);
+}
+
+void SwUndoOutlineLeftRight::RedoImpl(::sw::UndoRedoContext & rContext)
+{
+ SwPaM & rPaM( AddUndoRedoPaM(rContext) );
+ rContext.GetDoc().OutlineUpDown(rPaM, nOffset);
+}
+
+void SwUndoOutlineLeftRight::RepeatImpl(::sw::RepeatContext & rContext)
+{
+ rContext.GetDoc().OutlineUpDown(rContext.GetRepeatPaM(), nOffset);
+}
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ \ No newline at end of file
diff --git a/sw/source/core/undo/unovwr.cxx b/sw/source/core/undo/unovwr.cxx
new file mode 100644
index 000000000000..f2f83a06fd42
--- /dev/null
+++ b/sw/source/core/undo/unovwr.cxx
@@ -0,0 +1,504 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+#include <UndoOverwrite.hxx>
+
+#include <tools/resid.hxx>
+
+#include <unotools/charclass.hxx>
+#include <unotools/transliterationwrapper.hxx>
+
+#include <comphelper/processfactory.hxx>
+
+#include <doc.hxx>
+#include <IDocumentUndoRedo.hxx>
+#include <IShellCursorSupplier.hxx>
+#include <swundo.hxx> // fuer die UndoIds
+#include <pam.hxx>
+#include <ndtxt.hxx>
+#include <UndoCore.hxx>
+#include <rolbck.hxx>
+#include <acorrect.hxx>
+#include <docary.hxx>
+
+#include <comcore.hrc> // #111827#
+#include <undo.hrc>
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::i18n;
+using namespace ::com::sun::star::uno;
+
+
+//------------------------------------------------------------
+
+// OVERWRITE
+
+
+SwUndoOverwrite::SwUndoOverwrite( SwDoc* pDoc, SwPosition& rPos,
+ sal_Unicode cIns )
+ : SwUndo(UNDO_OVERWRITE),
+ pRedlSaveData( 0 ), bGroup( sal_False )
+{
+ if( !pDoc->IsIgnoreRedline() && pDoc->GetRedlineTbl().Count() )
+ {
+ SwPaM aPam( rPos.nNode, rPos.nContent.GetIndex(),
+ rPos.nNode, rPos.nContent.GetIndex()+1 );
+ pRedlSaveData = new SwRedlineSaveDatas;
+ if( !FillSaveData( aPam, *pRedlSaveData, sal_False ))
+ delete pRedlSaveData, pRedlSaveData = 0;
+ }
+
+ nSttNode = rPos.nNode.GetIndex();
+ nSttCntnt = rPos.nContent.GetIndex();
+
+ SwTxtNode* pTxtNd = rPos.nNode.GetNode().GetTxtNode();
+ OSL_ENSURE( pTxtNd, "Overwrite nicht im TextNode?" );
+
+ bInsChar = sal_True;
+ xub_StrLen nTxtNdLen = pTxtNd->GetTxt().Len();
+ if( nSttCntnt < nTxtNdLen ) // kein reines Einfuegen ?
+ {
+ aDelStr.Insert( pTxtNd->GetTxt().GetChar( nSttCntnt ) );
+ if( !pHistory )
+ pHistory = new SwHistory;
+ SwRegHistory aRHst( *pTxtNd, pHistory );
+ pHistory->CopyAttr( pTxtNd->GetpSwpHints(), nSttNode, 0,
+ nTxtNdLen, false );
+ rPos.nContent++;
+ bInsChar = sal_False;
+ }
+
+ sal_Bool bOldExpFlg = pTxtNd->IsIgnoreDontExpand();
+ pTxtNd->SetIgnoreDontExpand( sal_True );
+
+ pTxtNd->InsertText( cIns, rPos.nContent,
+ IDocumentContentOperations::INS_EMPTYEXPAND );
+ aInsStr.Insert( cIns );
+
+ if( !bInsChar )
+ {
+ const SwIndex aTmpIndex( rPos.nContent, -2 );
+ pTxtNd->EraseText( aTmpIndex, 1 );
+ }
+ pTxtNd->SetIgnoreDontExpand( bOldExpFlg );
+
+ bCacheComment = false;
+}
+
+SwUndoOverwrite::~SwUndoOverwrite()
+{
+ delete pRedlSaveData;
+}
+
+sal_Bool SwUndoOverwrite::CanGrouping( SwDoc* pDoc, SwPosition& rPos,
+ sal_Unicode cIns )
+{
+/// ?? was ist mit nur eingefuegten Charaktern ???
+
+ // es kann nur das Loeschen von einzelnen char's zusammengefasst werden
+ if( rPos.nNode != nSttNode || !aInsStr.Len() ||
+ ( !bGroup && aInsStr.Len() != 1 ))
+ return sal_False;
+
+ // ist der Node ueberhaupt ein TextNode?
+ SwTxtNode * pDelTxtNd = rPos.nNode.GetNode().GetTxtNode();
+ if( !pDelTxtNd ||
+ ( pDelTxtNd->GetTxt().Len() != rPos.nContent.GetIndex() &&
+ rPos.nContent.GetIndex() != ( nSttCntnt + aInsStr.Len() )))
+ return sal_False;
+
+ CharClass& rCC = GetAppCharClass();
+
+ // befrage das einzufuegende Charakter
+ if (( CH_TXTATR_BREAKWORD == cIns || CH_TXTATR_INWORD == cIns ) ||
+ rCC.isLetterNumeric( String( cIns ), 0 ) !=
+ rCC.isLetterNumeric( aInsStr, aInsStr.Len()-1 ) )
+ return sal_False;
+
+ {
+ SwRedlineSaveDatas* pTmpSav = new SwRedlineSaveDatas;
+ SwPaM aPam( rPos.nNode, rPos.nContent.GetIndex(),
+ rPos.nNode, rPos.nContent.GetIndex()+1 );
+
+ if( !FillSaveData( aPam, *pTmpSav, sal_False ))
+ delete pTmpSav, pTmpSav = 0;
+
+ sal_Bool bOk = ( !pRedlSaveData && !pTmpSav ) ||
+ ( pRedlSaveData && pTmpSav &&
+ SwUndo::CanRedlineGroup( *pRedlSaveData, *pTmpSav,
+ nSttCntnt > rPos.nContent.GetIndex() ));
+ delete pTmpSav;
+ if( !bOk )
+ return sal_False;
+
+ pDoc->DeleteRedline( aPam, false, USHRT_MAX );
+ }
+
+ // Ok, die beiden 'Overwrites' koennen zusammen gefasst werden, also
+ // 'verschiebe' das enstprechende Zeichen
+ if( !bInsChar )
+ {
+ if( rPos.nContent.GetIndex() < pDelTxtNd->GetTxt().Len() )
+ {
+ aDelStr.Insert( pDelTxtNd->GetTxt().GetChar(rPos.nContent.GetIndex()) );
+ rPos.nContent++;
+ }
+ else
+ bInsChar = sal_True;
+ }
+
+ sal_Bool bOldExpFlg = pDelTxtNd->IsIgnoreDontExpand();
+ pDelTxtNd->SetIgnoreDontExpand( sal_True );
+
+ pDelTxtNd->InsertText( cIns, rPos.nContent,
+ IDocumentContentOperations::INS_EMPTYEXPAND );
+ aInsStr.Insert( cIns );
+
+ if( !bInsChar )
+ {
+ const SwIndex aTmpIndex( rPos.nContent, -2 );
+ pDelTxtNd->EraseText( aTmpIndex, 1 );
+ }
+ pDelTxtNd->SetIgnoreDontExpand( bOldExpFlg );
+
+ bGroup = sal_True;
+ return sal_True;
+}
+
+
+
+
+
+void SwUndoOverwrite::UndoImpl(::sw::UndoRedoContext & rContext)
+{
+ SwDoc *const pDoc = & rContext.GetDoc();
+ SwPaM *const pAktPam(& rContext.GetCursorSupplier().CreateNewShellCursor());
+
+ pAktPam->DeleteMark();
+ pAktPam->GetPoint()->nNode = nSttNode;
+ SwTxtNode* pTxtNd = pAktPam->GetNode()->GetTxtNode();
+ OSL_ENSURE( pTxtNd, "Overwrite nicht im TextNode?" );
+ SwIndex& rIdx = pAktPam->GetPoint()->nContent;
+ rIdx.Assign( pTxtNd, nSttCntnt );
+
+ SwAutoCorrExceptWord* pACEWord = pDoc->GetAutoCorrExceptWord();
+ if( pACEWord )
+ {
+ if( 1 == aInsStr.Len() && 1 == aDelStr.Len() )
+ pACEWord->CheckChar( *pAktPam->GetPoint(), aDelStr.GetChar( 0 ) );
+ pDoc->SetAutoCorrExceptWord( 0 );
+ }
+
+ // wurde nicht nur ueberschieben sondern auch geinsertet, so loesche
+ // den Ueberhang
+ if( aInsStr.Len() > aDelStr.Len() )
+ {
+ rIdx += aDelStr.Len();
+ pTxtNd->EraseText( rIdx, aInsStr.Len() - aDelStr.Len() );
+ rIdx = nSttCntnt;
+ }
+
+ if( aDelStr.Len() )
+ {
+ String aTmpStr( '1' );
+ sal_Unicode* pTmpStr = aTmpStr.GetBufferAccess();
+
+ sal_Bool bOldExpFlg = pTxtNd->IsIgnoreDontExpand();
+ pTxtNd->SetIgnoreDontExpand( sal_True );
+
+ rIdx++;
+ for( xub_StrLen n = 0; n < aDelStr.Len(); n++ )
+ {
+ // einzeln, damit die Attribute stehen bleiben !!!
+ *pTmpStr = aDelStr.GetChar( n );
+ pTxtNd->InsertText( aTmpStr, rIdx /*???, SETATTR_NOTXTATRCHR*/ );
+ rIdx -= 2;
+ pTxtNd->EraseText( rIdx, 1 );
+ rIdx += 2;
+ }
+ pTxtNd->SetIgnoreDontExpand( bOldExpFlg );
+ rIdx--;
+ }
+ if( pHistory )
+ {
+ if( pTxtNd->GetpSwpHints() )
+ pTxtNd->ClearSwpHintsArr( false );
+ pHistory->TmpRollback( pDoc, 0, false );
+ }
+
+ if( pAktPam->GetMark()->nContent.GetIndex() != nSttCntnt )
+ {
+ pAktPam->SetMark();
+ pAktPam->GetMark()->nContent = nSttCntnt;
+ }
+
+ if( pRedlSaveData )
+ SetSaveData( *pDoc, *pRedlSaveData );
+}
+
+void SwUndoOverwrite::RepeatImpl(::sw::RepeatContext & rContext)
+{
+ SwPaM *const pAktPam = & rContext.GetRepeatPaM();
+ if( !aInsStr.Len() || pAktPam->HasMark() )
+ return;
+
+ SwDoc & rDoc = rContext.GetDoc();
+
+ {
+ ::sw::GroupUndoGuard const undoGuard(rDoc.GetIDocumentUndoRedo());
+ rDoc.Overwrite(*pAktPam, aInsStr.GetChar(0));
+ }
+ for( xub_StrLen n = 1; n < aInsStr.Len(); ++n )
+ rDoc.Overwrite( *pAktPam, aInsStr.GetChar( n ) );
+}
+
+void SwUndoOverwrite::RedoImpl(::sw::UndoRedoContext & rContext)
+{
+ SwDoc *const pDoc = & rContext.GetDoc();
+ SwPaM *const pAktPam(& rContext.GetCursorSupplier().CreateNewShellCursor());
+
+ pAktPam->DeleteMark();
+ pAktPam->GetPoint()->nNode = nSttNode;
+ SwTxtNode* pTxtNd = pAktPam->GetNode()->GetTxtNode();
+ OSL_ENSURE( pTxtNd, "Overwrite nicht im TextNode?" );
+ SwIndex& rIdx = pAktPam->GetPoint()->nContent;
+
+ if( pRedlSaveData )
+ {
+ rIdx.Assign( pTxtNd, nSttCntnt );
+ pAktPam->SetMark();
+ pAktPam->GetMark()->nContent += aInsStr.Len();
+ pDoc->DeleteRedline( *pAktPam, false, USHRT_MAX );
+ pAktPam->DeleteMark();
+ }
+ rIdx.Assign( pTxtNd, aDelStr.Len() ? nSttCntnt+1 : nSttCntnt );
+
+ sal_Bool bOldExpFlg = pTxtNd->IsIgnoreDontExpand();
+ pTxtNd->SetIgnoreDontExpand( sal_True );
+
+ for( xub_StrLen n = 0; n < aInsStr.Len(); n++ )
+ {
+ // einzeln, damit die Attribute stehen bleiben !!!
+ pTxtNd->InsertText( aInsStr.GetChar( n ), rIdx,
+ IDocumentContentOperations::INS_EMPTYEXPAND );
+ if( n < aDelStr.Len() )
+ {
+ rIdx -= 2;
+ pTxtNd->EraseText( rIdx, 1 );
+ rIdx += n+1 < aDelStr.Len() ? 2 : 1;
+ }
+ }
+ pTxtNd->SetIgnoreDontExpand( bOldExpFlg );
+
+ // alte Anfangs-Position vom UndoNodes-Array zurueckholen
+ if( pHistory )
+ pHistory->SetTmpEnd( pHistory->Count() );
+ if( pAktPam->GetMark()->nContent.GetIndex() != nSttCntnt )
+ {
+ pAktPam->SetMark();
+ pAktPam->GetMark()->nContent = nSttCntnt;
+ }
+}
+
+SwRewriter SwUndoOverwrite::GetRewriter() const
+{
+ SwRewriter aResult;
+
+ String aString;
+
+ aString += String(SW_RES(STR_START_QUOTE));
+ aString += ShortenString(aInsStr, nUndoStringLength,
+ String(SW_RES(STR_LDOTS)));
+ aString += String(SW_RES(STR_END_QUOTE));
+
+ aResult.AddRule(UNDO_ARG1, aString);
+
+ return aResult;
+}
+
+//------------------------------------------------------------
+
+struct _UndoTransliterate_Data
+{
+ String sText;
+ SwHistory* pHistory;
+ Sequence< sal_Int32 >* pOffsets;
+ sal_uLong nNdIdx;
+ xub_StrLen nStart, nLen;
+
+ _UndoTransliterate_Data( sal_uLong nNd, xub_StrLen nStt, xub_StrLen nStrLen, const String& rTxt )
+ : sText( rTxt ), pHistory( 0 ), pOffsets( 0 ),
+ nNdIdx( nNd ), nStart( nStt ), nLen( nStrLen )
+ {}
+ ~_UndoTransliterate_Data() { delete pOffsets; delete pHistory; }
+
+ void SetChangeAtNode( SwDoc& rDoc );
+};
+
+SwUndoTransliterate::SwUndoTransliterate(
+ const SwPaM& rPam,
+ const utl::TransliterationWrapper& rTrans )
+ : SwUndo( UNDO_TRANSLITERATE ), SwUndRng( rPam ), nType( rTrans.getType() )
+{
+}
+
+SwUndoTransliterate::~SwUndoTransliterate()
+{
+ for (size_t i = 0; i < aChanges.size(); ++i)
+ delete aChanges[i];
+}
+
+void SwUndoTransliterate::UndoImpl(::sw::UndoRedoContext & rContext)
+{
+ SwDoc & rDoc = rContext.GetDoc();
+
+ // since the changes were added to the vector from the end of the string/node towards
+ // the start, we need to revert them from the start towards the end now to keep the
+ // offset information of the undo data in sync with the changing text.
+ // Thus we need to iterate from the end of the vector to the start
+ for (sal_Int32 i = aChanges.size() - 1; i >= 0; --i)
+ aChanges[i]->SetChangeAtNode( rDoc );
+
+ AddUndoRedoPaM(rContext, true);
+}
+
+void SwUndoTransliterate::RedoImpl(::sw::UndoRedoContext & rContext)
+{
+ SwPaM & rPam( AddUndoRedoPaM(rContext) );
+ DoTransliterate(rContext.GetDoc(), rPam);
+}
+
+void SwUndoTransliterate::RepeatImpl(::sw::RepeatContext & rContext)
+{
+ DoTransliterate(rContext.GetDoc(), rContext.GetRepeatPaM());
+}
+
+void SwUndoTransliterate::DoTransliterate(SwDoc & rDoc, SwPaM & rPam)
+{
+ utl::TransliterationWrapper aTrans( ::comphelper::getProcessServiceFactory(), nType );
+ rDoc.TransliterateText( rPam, aTrans );
+}
+
+void SwUndoTransliterate::AddChanges( SwTxtNode& rTNd,
+ xub_StrLen nStart, xub_StrLen nLen,
+ uno::Sequence <sal_Int32>& rOffsets )
+{
+ long nOffsLen = rOffsets.getLength();
+ _UndoTransliterate_Data* pNew = new _UndoTransliterate_Data(
+ rTNd.GetIndex(), nStart, (xub_StrLen)nOffsLen,
+ rTNd.GetTxt().Copy( nStart, nLen ));
+
+ aChanges.push_back( pNew );
+
+ const sal_Int32* pOffsets = rOffsets.getConstArray();
+ // where did we need less memory ?
+ const sal_Int32* p = pOffsets;
+ for( long n = 0; n < nOffsLen; ++n, ++p )
+ if( *p != ( nStart + n ))
+ {
+ // create the Offset array
+ pNew->pOffsets = new Sequence <sal_Int32> ( nLen );
+ sal_Int32* pIdx = pNew->pOffsets->getArray();
+ p = pOffsets;
+ long nMyOff, nNewVal = nStart;
+ for( n = 0, nMyOff = nStart; n < nOffsLen; ++p, ++n, ++nMyOff )
+ {
+ if( *p < nMyOff )
+ {
+ // something is deleted
+ nMyOff = *p;
+ *(pIdx-1) = nNewVal++;
+ }
+ else if( *p > nMyOff )
+ {
+ for( ; *p > nMyOff; ++nMyOff )
+ *pIdx++ = nNewVal;
+ --nMyOff;
+ --n;
+ --p;
+ }
+ else
+ *pIdx++ = nNewVal++;
+ }
+
+ // and then we need to save the attributes/bookmarks
+ // but this data must moved every time to the last in the chain!
+ for (size_t i = 0; i + 1 < aChanges.size(); ++i) // check all changes but not the current one
+ {
+ _UndoTransliterate_Data* pD = aChanges[i];
+ if( pD->nNdIdx == pNew->nNdIdx && pD->pHistory )
+ {
+ // same node and have a history?
+ pNew->pHistory = pD->pHistory;
+ pD->pHistory = 0;
+ break; // more can't exist
+ }
+ }
+
+ if( !pNew->pHistory )
+ {
+ pNew->pHistory = new SwHistory;
+ SwRegHistory aRHst( rTNd, pNew->pHistory );
+ pNew->pHistory->CopyAttr( rTNd.GetpSwpHints(),
+ pNew->nNdIdx, 0, rTNd.GetTxt().Len(), false );
+ }
+ break;
+ }
+}
+
+void _UndoTransliterate_Data::SetChangeAtNode( SwDoc& rDoc )
+{
+ SwTxtNode* pTNd = rDoc.GetNodes()[ nNdIdx ]->GetTxtNode();
+ if( pTNd )
+ {
+ Sequence <sal_Int32> aOffsets( pOffsets ? pOffsets->getLength() : nLen );
+ if( pOffsets )
+ aOffsets = *pOffsets;
+ else
+ {
+ sal_Int32* p = aOffsets.getArray();
+ for( xub_StrLen n = 0; n < nLen; ++n, ++p )
+ *p = n + nStart;
+ }
+ pTNd->ReplaceTextOnly( nStart, nLen, sText, aOffsets );
+
+ if( pHistory )
+ {
+ if( pTNd->GetpSwpHints() )
+ pTNd->ClearSwpHintsArr( false );
+ pHistory->TmpRollback( &rDoc, 0, false );
+ pHistory->SetTmpEnd( pHistory->Count() );
+ }
+ }
+}
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/undo/unredln.cxx b/sw/source/core/undo/unredln.cxx
new file mode 100644
index 000000000000..90d8d261e604
--- /dev/null
+++ b/sw/source/core/undo/unredln.cxx
@@ -0,0 +1,541 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+#include <UndoRedline.hxx>
+
+#include <hintids.hxx>
+#include <unotools/charclass.hxx>
+#include <doc.hxx>
+#include <swundo.hxx> // fuer die UndoIds
+#include <pam.hxx>
+#include <ndtxt.hxx>
+#include <UndoCore.hxx>
+#include <UndoDelete.hxx>
+#include <rolbck.hxx>
+#include <redline.hxx>
+#include <docary.hxx>
+#include <sortopt.hxx>
+
+extern void lcl_JoinText( SwPaM& rPam, sal_Bool bJoinPrev );
+extern void lcl_GetJoinFlags( SwPaM& rPam, sal_Bool& rJoinTxt, sal_Bool& rJoinPrev );
+
+//------------------------------------------------------------------
+
+SwUndoRedline::SwUndoRedline( SwUndoId nUsrId, const SwPaM& rRange )
+ : SwUndo( UNDO_REDLINE ), SwUndRng( rRange ),
+ pRedlData( 0 ), pRedlSaveData( 0 ), nUserId( nUsrId ),
+ bHiddenRedlines( sal_False )
+{
+ // Redline beachten
+ SwDoc& rDoc = *rRange.GetDoc();
+ if( rDoc.IsRedlineOn() )
+ {
+ switch( nUserId )
+ {
+ case UNDO_DELETE:
+ case UNDO_REPLACE:
+ pRedlData = new SwRedlineData( nsRedlineType_t::REDLINE_DELETE, rDoc.GetRedlineAuthor() );
+ break;
+ default:
+ ;
+ }
+ SetRedlineMode( rDoc.GetRedlineMode() );
+ }
+
+ sal_uLong nEndExtra = rDoc.GetNodes().GetEndOfExtras().GetIndex();
+
+ pRedlSaveData = new SwRedlineSaveDatas;
+ if( !FillSaveData( rRange, *pRedlSaveData, sal_False,
+ UNDO_REJECT_REDLINE != nUserId ))
+ delete pRedlSaveData, pRedlSaveData = 0;
+ else
+ {
+ bHiddenRedlines = HasHiddenRedlines( *pRedlSaveData );
+ if( bHiddenRedlines ) // dann muessen die NodeIndizies
+ { // vom SwUndRng korrigiert werden
+ nEndExtra -= rDoc.GetNodes().GetEndOfExtras().GetIndex();
+ nSttNode -= nEndExtra;
+ nEndNode -= nEndExtra;
+ }
+ }
+}
+
+SwUndoRedline::~SwUndoRedline()
+{
+ delete pRedlData;
+ delete pRedlSaveData;
+}
+
+sal_uInt16 SwUndoRedline::GetRedlSaveCount() const
+{
+ return pRedlSaveData ? pRedlSaveData->Count() : 0;
+}
+
+
+void SwUndoRedline::UndoImpl(::sw::UndoRedoContext & rContext)
+{
+ SwDoc *const pDoc = & rContext.GetDoc();
+ SwPaM & rPam( AddUndoRedoPaM(rContext) );
+
+ UndoRedlineImpl(*pDoc, rPam);
+
+ if( pRedlSaveData )
+ {
+ sal_uLong nEndExtra = pDoc->GetNodes().GetEndOfExtras().GetIndex();
+ SetSaveData( *pDoc, *pRedlSaveData );
+ if( bHiddenRedlines )
+ {
+ pRedlSaveData->DeleteAndDestroy( 0, pRedlSaveData->Count() );
+
+ nEndExtra = pDoc->GetNodes().GetEndOfExtras().GetIndex() - nEndExtra;
+ nSttNode += nEndExtra;
+ nEndNode += nEndExtra;
+ }
+ SetPaM(rPam, true);
+ }
+}
+
+
+void SwUndoRedline::RedoImpl(::sw::UndoRedoContext & rContext)
+{
+ SwDoc *const pDoc = & rContext.GetDoc();
+ RedlineMode_t eOld = pDoc->GetRedlineMode();
+ pDoc->SetRedlineMode_intern((RedlineMode_t)(( eOld & ~nsRedlineMode_t::REDLINE_IGNORE) | nsRedlineMode_t::REDLINE_ON ));
+
+ SwPaM & rPam( AddUndoRedoPaM(rContext) );
+ if( pRedlSaveData && bHiddenRedlines )
+ {
+ sal_uLong nEndExtra = pDoc->GetNodes().GetEndOfExtras().GetIndex();
+ FillSaveData(rPam, *pRedlSaveData, sal_False,
+ UNDO_REJECT_REDLINE != nUserId );
+
+ nEndExtra -= pDoc->GetNodes().GetEndOfExtras().GetIndex();
+ nSttNode -= nEndExtra;
+ nEndNode -= nEndExtra;
+ }
+
+ RedoRedlineImpl(*pDoc, rPam);
+
+ SetPaM(rPam, true);
+ pDoc->SetRedlineMode_intern( eOld );
+}
+
+void SwUndoRedline::UndoRedlineImpl(SwDoc &, SwPaM &)
+{
+}
+
+// default: remove redlines
+void SwUndoRedline::RedoRedlineImpl(SwDoc & rDoc, SwPaM & rPam)
+{
+ rDoc.DeleteRedline(rPam, true, USHRT_MAX);
+}
+
+
+// SwUndoRedlineDelete ///////////////////////////////////////////////////
+
+SwUndoRedlineDelete::SwUndoRedlineDelete( const SwPaM& rRange, SwUndoId nUsrId )
+ : SwUndoRedline( nUsrId = (nUsrId ? nUsrId : UNDO_DELETE), rRange ),
+ bCanGroup( sal_False ), bIsDelim( sal_False ), bIsBackspace( sal_False )
+{
+ const SwTxtNode* pTNd;
+ if( UNDO_DELETE == nUserId &&
+ nSttNode == nEndNode && nSttCntnt + 1 == nEndCntnt &&
+ 0 != (pTNd = rRange.GetNode()->GetTxtNode()) )
+ {
+ sal_Unicode cCh = pTNd->GetTxt().GetChar( nSttCntnt );
+ if( CH_TXTATR_BREAKWORD != cCh && CH_TXTATR_INWORD != cCh )
+ {
+ bCanGroup = sal_True;
+ bIsDelim = !GetAppCharClass().isLetterNumeric( pTNd->GetTxt(),
+ nSttCntnt );
+ bIsBackspace = nSttCntnt == rRange.GetPoint()->nContent.GetIndex();
+ }
+ }
+
+ bCacheComment = false;
+}
+
+void SwUndoRedlineDelete::UndoRedlineImpl(SwDoc & rDoc, SwPaM & rPam)
+{
+ rDoc.DeleteRedline(rPam, true, USHRT_MAX);
+}
+
+void SwUndoRedlineDelete::RedoRedlineImpl(SwDoc & rDoc, SwPaM & rPam)
+{
+ if (rPam.GetPoint() != rPam.GetMark())
+ {
+ rDoc.AppendRedline( new SwRedline(*pRedlData, rPam), sal_False );
+ }
+}
+
+sal_Bool SwUndoRedlineDelete::CanGrouping( const SwUndoRedlineDelete& rNext )
+{
+ sal_Bool bRet = sal_False;
+ if( UNDO_DELETE == nUserId && nUserId == rNext.nUserId &&
+ bCanGroup == rNext.bCanGroup &&
+ bIsDelim == rNext.bIsDelim &&
+ bIsBackspace == rNext.bIsBackspace &&
+ nSttNode == nEndNode &&
+ rNext.nSttNode == nSttNode &&
+ rNext.nEndNode == nEndNode )
+ {
+ int bIsEnd = 0;
+ if( rNext.nSttCntnt == nEndCntnt )
+ bIsEnd = 1;
+ else if( rNext.nEndCntnt == nSttCntnt )
+ bIsEnd = -1;
+
+ if( bIsEnd &&
+ (( !pRedlSaveData && !rNext.pRedlSaveData ) ||
+ ( pRedlSaveData && rNext.pRedlSaveData &&
+ SwUndo::CanRedlineGroup( *pRedlSaveData,
+ *rNext.pRedlSaveData, 1 != bIsEnd )
+ )))
+ {
+ if( 1 == bIsEnd )
+ nEndCntnt = rNext.nEndCntnt;
+ else
+ nSttCntnt = rNext.nSttCntnt;
+ bRet = sal_True;
+ }
+ }
+ return bRet;
+}
+
+/* */
+
+SwUndoRedlineSort::SwUndoRedlineSort( const SwPaM& rRange,
+ const SwSortOptions& rOpt )
+ : SwUndoRedline( UNDO_SORT_TXT, rRange ),
+ pOpt( new SwSortOptions( rOpt ) ),
+ nSaveEndNode( nEndNode ), nOffset( 0 ), nSaveEndCntnt( nEndCntnt )
+{
+}
+
+SwUndoRedlineSort::~SwUndoRedlineSort()
+{
+ delete pOpt;
+}
+
+void SwUndoRedlineSort::UndoRedlineImpl(SwDoc & rDoc, SwPaM & rPam)
+{
+ // rPam contains the sorted range
+ // aSaveRange contains copied (i.e. original) range
+
+ SwPosition *const pStart = rPam.Start();
+ SwPosition *const pEnd = rPam.End();
+
+ SwNodeIndex aPrevIdx( pStart->nNode, -1 );
+ sal_uLong nOffsetTemp = pEnd->nNode.GetIndex() - pStart->nNode.GetIndex();
+
+ if( 0 == ( nsRedlineMode_t::REDLINE_SHOW_DELETE & rDoc.GetRedlineMode()) )
+ {
+ // die beiden Redline Objecte suchen und diese dann anzeigen lassen,
+ // damit die Nodes wieder uebereinstimmen!
+ // das Geloeschte ist versteckt, also suche das INSERT
+ // Redline Object. Dahinter steht das Geloeschte
+ sal_uInt16 nFnd = rDoc.GetRedlinePos(
+ *rDoc.GetNodes()[ nSttNode + 1 ],
+ nsRedlineType_t::REDLINE_INSERT );
+ OSL_ENSURE( USHRT_MAX != nFnd && nFnd+1 < rDoc.GetRedlineTbl().Count(),
+ "kein Insert Object gefunden" );
+ ++nFnd;
+ rDoc.GetRedlineTbl()[nFnd]->Show( 1 );
+ }
+
+ {
+ SwPaM aTmp( *rPam.GetMark() );
+ aTmp.GetMark()->nContent = 0;
+ aTmp.SetMark();
+ aTmp.GetPoint()->nNode = nSaveEndNode;
+ aTmp.GetPoint()->nContent.Assign( aTmp.GetCntntNode(), nSaveEndCntnt );
+ rDoc.DeleteRedline( aTmp, true, USHRT_MAX );
+ }
+
+ rDoc.DelFullPara(rPam);
+
+ SwPaM *const pPam = & rPam;
+ pPam->DeleteMark();
+ pPam->GetPoint()->nNode.Assign( aPrevIdx.GetNode(), +1 );
+ SwCntntNode* pCNd = pPam->GetCntntNode();
+ pPam->GetPoint()->nContent.Assign(pCNd, 0 );
+ pPam->SetMark();
+
+ pPam->GetPoint()->nNode += nOffsetTemp;
+ pCNd = pPam->GetCntntNode();
+ pPam->GetPoint()->nContent.Assign( pCNd, pCNd->Len() );
+
+ SetValues( *pPam );
+
+ SetPaM(rPam);
+}
+
+void SwUndoRedlineSort::RedoRedlineImpl(SwDoc & rDoc, SwPaM & rPam)
+{
+ SwPaM* pPam = &rPam;
+ SwPosition* pStart = pPam->Start();
+ SwPosition* pEnd = pPam->End();
+
+ SwNodeIndex aPrevIdx( pStart->nNode, -1 );
+ sal_uLong nOffsetTemp = pEnd->nNode.GetIndex() - pStart->nNode.GetIndex();
+ xub_StrLen nCntStt = pStart->nContent.GetIndex();
+
+ rDoc.SortText(rPam, *pOpt);
+
+ pPam->DeleteMark();
+ pPam->GetPoint()->nNode.Assign( aPrevIdx.GetNode(), +1 );
+ SwCntntNode* pCNd = pPam->GetCntntNode();
+ xub_StrLen nLen = pCNd->Len();
+ if( nLen > nCntStt )
+ nLen = nCntStt;
+ pPam->GetPoint()->nContent.Assign(pCNd, nLen );
+ pPam->SetMark();
+
+ pPam->GetPoint()->nNode += nOffsetTemp;
+ pCNd = pPam->GetCntntNode();
+ pPam->GetPoint()->nContent.Assign( pCNd, pCNd->Len() );
+
+ SetValues( rPam );
+
+ SetPaM( rPam );
+ rPam.GetPoint()->nNode = nSaveEndNode;
+ rPam.GetPoint()->nContent.Assign( rPam.GetCntntNode(), nSaveEndCntnt );
+}
+
+void SwUndoRedlineSort::RepeatImpl(::sw::RepeatContext & rContext)
+{
+ rContext.GetDoc().SortText( rContext.GetRepeatPaM(), *pOpt );
+}
+
+void SwUndoRedlineSort::SetSaveRange( const SwPaM& rRange )
+{
+ const SwPosition& rPos = *rRange.End();
+ nSaveEndNode = rPos.nNode.GetIndex();
+ nSaveEndCntnt = rPos.nContent.GetIndex();
+}
+
+void SwUndoRedlineSort::SetOffset( const SwNodeIndex& rIdx )
+{
+ nOffset = rIdx.GetIndex() - nSttNode;
+}
+
+// SwUndoAcceptRedline ///////////////////////////////////////////////////
+
+SwUndoAcceptRedline::SwUndoAcceptRedline( const SwPaM& rRange )
+ : SwUndoRedline( UNDO_ACCEPT_REDLINE, rRange )
+{
+}
+
+void SwUndoAcceptRedline::RedoRedlineImpl(SwDoc & rDoc, SwPaM & rPam)
+{
+ rDoc.AcceptRedline(rPam, false);
+}
+
+void SwUndoAcceptRedline::RepeatImpl(::sw::RepeatContext & rContext)
+{
+ rContext.GetDoc().AcceptRedline(rContext.GetRepeatPaM(), true);
+}
+
+SwUndoRejectRedline::SwUndoRejectRedline( const SwPaM& rRange )
+ : SwUndoRedline( UNDO_REJECT_REDLINE, rRange )
+{
+}
+
+void SwUndoRejectRedline::RedoRedlineImpl(SwDoc & rDoc, SwPaM & rPam)
+{
+ rDoc.RejectRedline(rPam, false);
+}
+
+void SwUndoRejectRedline::RepeatImpl(::sw::RepeatContext & rContext)
+{
+ rContext.GetDoc().RejectRedline(rContext.GetRepeatPaM(), true);
+}
+
+// SwUndoCompDoc /////////////////////////////////////////////////////////
+
+SwUndoCompDoc::SwUndoCompDoc( const SwPaM& rRg, sal_Bool bIns )
+ : SwUndo( UNDO_COMPAREDOC ), SwUndRng( rRg ), pRedlData( 0 ),
+ pUnDel( 0 ), pUnDel2( 0 ), pRedlSaveData( 0 ), bInsert( bIns )
+{
+ SwDoc* pDoc = (SwDoc*)rRg.GetDoc();
+ if( pDoc->IsRedlineOn() )
+ {
+ RedlineType_t eTyp = bInsert ? nsRedlineType_t::REDLINE_INSERT : nsRedlineType_t::REDLINE_DELETE;
+ pRedlData = new SwRedlineData( eTyp, pDoc->GetRedlineAuthor() );
+ SetRedlineMode( pDoc->GetRedlineMode() );
+ }
+}
+
+SwUndoCompDoc::SwUndoCompDoc( const SwRedline& rRedl )
+ : SwUndo( UNDO_COMPAREDOC ), SwUndRng( rRedl ), pRedlData( 0 ),
+ pUnDel( 0 ), pUnDel2( 0 ), pRedlSaveData( 0 ),
+ // fuers MergeDoc wird aber der jeweils umgekehrte Zweig benoetigt!
+ bInsert( nsRedlineType_t::REDLINE_DELETE == rRedl.GetType() )
+{
+ SwDoc* pDoc = (SwDoc*)rRedl.GetDoc();
+ if( pDoc->IsRedlineOn() )
+ {
+ pRedlData = new SwRedlineData( rRedl.GetRedlineData() );
+ SetRedlineMode( pDoc->GetRedlineMode() );
+ }
+
+ pRedlSaveData = new SwRedlineSaveDatas;
+ if( !FillSaveData( rRedl, *pRedlSaveData, sal_False, sal_True ))
+ delete pRedlSaveData, pRedlSaveData = 0;
+}
+
+SwUndoCompDoc::~SwUndoCompDoc()
+{
+ delete pRedlData;
+ delete pUnDel;
+ delete pUnDel2;
+ delete pRedlSaveData;
+}
+
+void SwUndoCompDoc::UndoImpl(::sw::UndoRedoContext & rContext)
+{
+ SwDoc *const pDoc = & rContext.GetDoc();
+ SwPaM *const pPam( & AddUndoRedoPaM(rContext) );
+
+ if( !bInsert )
+ {
+ // die Redlines loeschen
+ RedlineMode_t eOld = pDoc->GetRedlineMode();
+ pDoc->SetRedlineMode_intern((RedlineMode_t)(( eOld & ~nsRedlineMode_t::REDLINE_IGNORE) | nsRedlineMode_t::REDLINE_ON));
+
+ pDoc->DeleteRedline( *pPam, true, USHRT_MAX );
+
+ pDoc->SetRedlineMode_intern( eOld );
+
+ //per definition Point is end (in SwUndRng!)
+ SwCntntNode* pCSttNd = pPam->GetCntntNode( sal_False );
+ SwCntntNode* pCEndNd = pPam->GetCntntNode( sal_True );
+
+ // if start- and end-content is zero, then the doc-compare moves
+ // complete nodes into the current doc. And then the selection
+ // must be from end to start, so the delete join into the right
+ // direction.
+ if( !nSttCntnt && !nEndCntnt )
+ pPam->Exchange();
+
+ sal_Bool bJoinTxt, bJoinPrev;
+ ::lcl_GetJoinFlags( *pPam, bJoinTxt, bJoinPrev );
+
+ pUnDel = new SwUndoDelete( *pPam, sal_False );
+
+ if( bJoinTxt )
+ ::lcl_JoinText( *pPam, bJoinPrev );
+
+ if( pCSttNd && !pCEndNd)
+ {
+ // #112139# Do not step behind the end of content.
+ SwNode * pTmp = pPam->GetNode(sal_True);
+ if (pTmp)
+ {
+ SwNode * pEnd = pDoc->GetNodes().DocumentSectionEndNode(pTmp);
+
+ if (pTmp != pEnd)
+ {
+ pPam->SetMark();
+ pPam->GetPoint()->nNode++;
+ pPam->GetBound( sal_True ).nContent.Assign( 0, 0 );
+ pPam->GetBound( sal_False ).nContent.Assign( 0, 0 );
+ pUnDel2 = new SwUndoDelete( *pPam, sal_True );
+ }
+ }
+ }
+ pPam->DeleteMark();
+ }
+ else
+ {
+ if( IDocumentRedlineAccess::IsRedlineOn( GetRedlineMode() ))
+ {
+ pDoc->DeleteRedline( *pPam, true, USHRT_MAX );
+
+ if( pRedlSaveData )
+ SetSaveData( *pDoc, *pRedlSaveData );
+ }
+ SetPaM(*pPam, true);
+ }
+}
+
+void SwUndoCompDoc::RedoImpl(::sw::UndoRedoContext & rContext)
+{
+ SwDoc *const pDoc = & rContext.GetDoc();
+ SwPaM *const pPam( & AddUndoRedoPaM(rContext) );
+
+ if( bInsert )
+ {
+ if( pRedlData && IDocumentRedlineAccess::IsRedlineOn( GetRedlineMode() ))
+ {
+ SwRedline* pTmp = new SwRedline( *pRedlData, *pPam );
+ ((SwRedlineTbl&)pDoc->GetRedlineTbl()).Insert( pTmp );
+ pTmp->InvalidateRange();
+
+/*
+ SwRedlineMode eOld = pDoc->GetRedlineMode();
+ pDoc->SetRedlineMode_intern( eOld & ~REDLINE_IGNORE );
+ pDoc->AppendRedline( new SwRedline( *pRedlData, *pPam ));
+ pDoc->SetRedlineMode_intern( eOld );
+*/
+ }
+ else if( !( nsRedlineMode_t::REDLINE_IGNORE & GetRedlineMode() ) &&
+ pDoc->GetRedlineTbl().Count() )
+ pDoc->SplitRedline( *pPam );
+ }
+ else
+ {
+// SwRedlineMode eOld = pDoc->GetRedlineMode();
+// pDoc->SetRedlineMode_intern( ( eOld & ~REDLINE_IGNORE) | REDLINE_ON );
+
+ if( pUnDel2 )
+ {
+ pUnDel2->UndoImpl(rContext);
+ delete pUnDel2, pUnDel2 = 0;
+ }
+ pUnDel->UndoImpl(rContext);
+ delete pUnDel, pUnDel = 0;
+
+ SetPaM( *pPam );
+
+ SwRedline* pTmp = new SwRedline( *pRedlData, *pPam );
+ ((SwRedlineTbl&)pDoc->GetRedlineTbl()).Insert( pTmp );
+ if (pTmp) // #i19649#
+ pTmp->InvalidateRange();
+
+// pDoc->SetRedlineMode_intern( eOld );
+ }
+
+ SetPaM(*pPam, true);
+}
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ \ No newline at end of file
diff --git a/sw/source/core/undo/unsect.cxx b/sw/source/core/undo/unsect.cxx
new file mode 100644
index 000000000000..dd9a6ce93c62
--- /dev/null
+++ b/sw/source/core/undo/unsect.cxx
@@ -0,0 +1,501 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+#include <UndoSection.hxx>
+
+#include <sfx2/linkmgr.hxx>
+#include <fmtcntnt.hxx>
+#include <doc.hxx>
+#include <docary.hxx>
+#include <swundo.hxx> // fuer die UndoIds
+#include <pam.hxx>
+#include <ndtxt.hxx>
+#include <UndoCore.hxx>
+#include <section.hxx>
+#include <rolbck.hxx>
+#include <redline.hxx>
+#include <doctxm.hxx>
+#include <ftnidx.hxx>
+#include <editsh.hxx>
+/// OD 04.10.2002 #102894#
+/// class Calc needed for calculation of the hidden condition of a section.
+#include <calc.hxx>
+
+
+SfxItemSet* lcl_GetAttrSet( const SwSection& rSect )
+{
+ // Attribute des Formate sichern (Spalten, Farbe, ... )
+ // Cntnt- und Protect- Items interessieren nicht (stehen schon in der
+ // Section), muessen also entfernen werden
+ SfxItemSet* pAttr = 0;
+ if( rSect.GetFmt() )
+ {
+ sal_uInt16 nCnt = 1;
+ if( rSect.IsProtect() )
+ ++nCnt;
+
+ if( nCnt < rSect.GetFmt()->GetAttrSet().Count() )
+ {
+ pAttr = new SfxItemSet( rSect.GetFmt()->GetAttrSet() );
+ pAttr->ClearItem( RES_PROTECT );
+ pAttr->ClearItem( RES_CNTNT );
+ if( !pAttr->Count() )
+ delete pAttr, pAttr = 0;
+ }
+ }
+ return pAttr;
+}
+
+
+////////////////////////////////////////////////////////////////////////////
+
+SwUndoInsSection::SwUndoInsSection(
+ SwPaM const& rPam, SwSectionData const& rNewData,
+ SfxItemSet const*const pSet, SwTOXBase const*const pTOXBase)
+ : SwUndo( UNDO_INSSECTION ), SwUndRng( rPam )
+ , m_pSectionData(new SwSectionData(rNewData))
+ , m_pTOXBase( (pTOXBase) ? new SwTOXBase(*pTOXBase) : 0 )
+ , m_pAttrSet( (pSet && pSet->Count()) ? new SfxItemSet( *pSet ) : 0 )
+ , m_pHistory(0)
+ , m_pRedlData(0)
+ , m_nSectionNodePos(0)
+ , m_bSplitAtStart(false)
+ , m_bSplitAtEnd(false)
+ , m_bUpdateFtn(false)
+{
+ SwDoc& rDoc = *(SwDoc*)rPam.GetDoc();
+ if( rDoc.IsRedlineOn() )
+ {
+ m_pRedlData.reset(new SwRedlineData( nsRedlineType_t::REDLINE_INSERT,
+ rDoc.GetRedlineAuthor() ));
+ SetRedlineMode( rDoc.GetRedlineMode() );
+ }
+
+
+ if( !rPam.HasMark() )
+ {
+ const SwCntntNode* pCNd = rPam.GetPoint()->nNode.GetNode().GetCntntNode();
+ if( pCNd && pCNd->HasSwAttrSet() && (
+ !rPam.GetPoint()->nContent.GetIndex() ||
+ rPam.GetPoint()->nContent.GetIndex() == pCNd->Len() ))
+ {
+ SfxItemSet aBrkSet( rDoc.GetAttrPool(), aBreakSetRange );
+ aBrkSet.Put( *pCNd->GetpSwAttrSet() );
+ if( aBrkSet.Count() )
+ {
+ m_pHistory.reset( new SwHistory );
+ m_pHistory->CopyFmtAttr( aBrkSet, pCNd->GetIndex() );
+ }
+ }
+ }
+}
+
+SwUndoInsSection::~SwUndoInsSection()
+{
+}
+
+void SwUndoInsSection::UndoImpl(::sw::UndoRedoContext & rContext)
+{
+ SwDoc & rDoc = rContext.GetDoc();
+
+ RemoveIdxFromSection( rDoc, m_nSectionNodePos );
+
+ SwSectionNode *const pNd =
+ rDoc.GetNodes()[ m_nSectionNodePos ]->GetSectionNode();
+ OSL_ENSURE( pNd, "wo ist mein SectionNode?" );
+
+ if( IDocumentRedlineAccess::IsRedlineOn( GetRedlineMode() ))
+ rDoc.DeleteRedline( *pNd, true, USHRT_MAX );
+
+ // lag keine Selektion vor ??
+ SwNodeIndex aIdx( *pNd );
+ if( ( !nEndNode && STRING_MAXLEN == nEndCntnt ) ||
+ ( nSttNode == nEndNode && nSttCntnt == nEndCntnt ))
+ // loesche einfach alle Nodes
+ rDoc.GetNodes().Delete( aIdx, pNd->EndOfSectionIndex() -
+ aIdx.GetIndex() );
+ else
+ // einfach das Format loeschen, der Rest erfolgt automatisch
+ rDoc.DelSectionFmt( pNd->GetSection().GetFmt() );
+
+ // muessen wir noch zusammenfassen ?
+ if (m_bSplitAtStart)
+ {
+ Join( rDoc, nSttNode );
+ }
+
+ if (m_bSplitAtEnd)
+ {
+ Join( rDoc, nEndNode );
+ }
+
+ if (m_pHistory.get())
+ {
+ m_pHistory->TmpRollback( &rDoc, 0, false );
+ }
+
+ if (m_bUpdateFtn)
+ {
+ rDoc.GetFtnIdxs().UpdateFtn( aIdx );
+ }
+
+ AddUndoRedoPaM(rContext);
+}
+
+void SwUndoInsSection::RedoImpl(::sw::UndoRedoContext & rContext)
+{
+ SwDoc & rDoc = rContext.GetDoc();
+ SwPaM & rPam( AddUndoRedoPaM(rContext) );
+
+ const SwTOXBaseSection* pUpdateTOX = 0;
+ if (m_pTOXBase.get())
+ {
+ pUpdateTOX = rDoc.InsertTableOf( *rPam.GetPoint(),
+ *m_pTOXBase, m_pAttrSet.get(), true);
+ }
+ else
+ {
+ rDoc.InsertSwSection(rPam, *m_pSectionData, 0, m_pAttrSet.get(), true);
+ }
+
+ if (m_pHistory.get())
+ {
+ m_pHistory->SetTmpEnd( m_pHistory->Count() );
+ }
+
+ SwSectionNode *const pSectNd =
+ rDoc.GetNodes()[ m_nSectionNodePos ]->GetSectionNode();
+ if (m_pRedlData.get() &&
+ IDocumentRedlineAccess::IsRedlineOn( GetRedlineMode()))
+ {
+ RedlineMode_t eOld = rDoc.GetRedlineMode();
+ rDoc.SetRedlineMode_intern((RedlineMode_t)(eOld & ~nsRedlineMode_t::REDLINE_IGNORE));
+
+ SwPaM aPam( *pSectNd->EndOfSectionNode(), *pSectNd, 1 );
+ rDoc.AppendRedline( new SwRedline( *m_pRedlData, aPam ), true);
+ rDoc.SetRedlineMode_intern( eOld );
+ }
+ else if( !( nsRedlineMode_t::REDLINE_IGNORE & GetRedlineMode() ) &&
+ rDoc.GetRedlineTbl().Count() )
+ {
+ SwPaM aPam( *pSectNd->EndOfSectionNode(), *pSectNd, 1 );
+ rDoc.SplitRedline( aPam );
+ }
+
+ if( pUpdateTOX )
+ {
+ // Formatierung anstossen
+ SwEditShell* pESh = rDoc.GetEditShell();
+ if( pESh )
+ pESh->CalcLayout();
+
+ // Seitennummern eintragen
+ ((SwTOXBaseSection*)pUpdateTOX)->UpdatePageNum();
+ }
+}
+
+void SwUndoInsSection::RepeatImpl(::sw::RepeatContext & rContext)
+{
+ SwDoc & rDoc = rContext.GetDoc();
+ if (m_pTOXBase.get())
+ {
+ rDoc.InsertTableOf(*rContext.GetRepeatPaM().GetPoint(),
+ *m_pTOXBase, m_pAttrSet.get(), true);
+ }
+ else
+ {
+ rDoc.InsertSwSection(rContext.GetRepeatPaM(),
+ *m_pSectionData, 0, m_pAttrSet.get());
+ }
+}
+
+void SwUndoInsSection::Join( SwDoc& rDoc, sal_uLong nNode )
+{
+ SwNodeIndex aIdx( rDoc.GetNodes(), nNode );
+ SwTxtNode* pTxtNd = aIdx.GetNode().GetTxtNode();
+ OSL_ENSURE( pTxtNd, "wo ist mein TextNode?" );
+
+ {
+ RemoveIdxRel( nNode + 1, SwPosition( aIdx,
+ SwIndex( pTxtNd, pTxtNd->GetTxt().Len() )));
+ }
+ pTxtNd->JoinNext();
+
+ if (m_pHistory.get())
+ {
+ SwIndex aCntIdx( pTxtNd, 0 );
+ pTxtNd->RstAttr( aCntIdx, pTxtNd->Len(), 0, 0, true );
+ }
+}
+
+
+void
+SwUndoInsSection::SaveSplitNode(SwTxtNode *const pTxtNd, bool const bAtStart)
+{
+ if( pTxtNd->GetpSwpHints() )
+ {
+ if (!m_pHistory.get())
+ {
+ m_pHistory.reset( new SwHistory );
+ }
+ m_pHistory->CopyAttr( pTxtNd->GetpSwpHints(), pTxtNd->GetIndex(), 0,
+ pTxtNd->GetTxt().Len(), false );
+ }
+
+ if (bAtStart)
+ {
+ m_bSplitAtStart = true;
+ }
+ else
+ {
+ m_bSplitAtEnd = true;
+ }
+}
+
+
+////////////////////////////////////////////////////////////////////////////
+
+class SwUndoDelSection
+ : public SwUndo
+{
+private:
+ ::std::auto_ptr<SwSectionData> const m_pSectionData; /// section not TOX
+ ::std::auto_ptr<SwTOXBase> const m_pTOXBase; /// set iff section is TOX
+ ::std::auto_ptr<SfxItemSet> const m_pAttrSet;
+ ::boost::shared_ptr< ::sfx2::MetadatableUndo > const m_pMetadataUndo;
+ sal_uLong const m_nStartNode;
+ sal_uLong const m_nEndNode;
+
+public:
+ SwUndoDelSection(
+ SwSectionFmt const&, SwSection const&, SwNodeIndex const*const);
+
+ virtual ~SwUndoDelSection();
+
+ virtual void UndoImpl( ::sw::UndoRedoContext & );
+ virtual void RedoImpl( ::sw::UndoRedoContext & );
+};
+
+SW_DLLPRIVATE SwUndo * MakeUndoDelSection(SwSectionFmt const& rFormat)
+{
+ return new SwUndoDelSection(rFormat, *rFormat.GetSection(),
+ rFormat.GetCntnt().GetCntntIdx());
+}
+
+SwUndoDelSection::SwUndoDelSection(
+ SwSectionFmt const& rSectionFmt, SwSection const& rSection,
+ SwNodeIndex const*const pIndex)
+ : SwUndo( UNDO_DELSECTION )
+ , m_pSectionData( new SwSectionData(rSection) )
+ , m_pTOXBase( rSection.ISA( SwTOXBaseSection )
+ ? new SwTOXBase(static_cast<SwTOXBaseSection const&>(rSection))
+ : 0 )
+ , m_pAttrSet( ::lcl_GetAttrSet(rSection) )
+ , m_pMetadataUndo( rSectionFmt.CreateUndo() )
+ , m_nStartNode( pIndex->GetIndex() )
+ , m_nEndNode( pIndex->GetNode().EndOfSectionIndex() )
+{
+}
+
+SwUndoDelSection::~SwUndoDelSection()
+{
+}
+
+void SwUndoDelSection::UndoImpl(::sw::UndoRedoContext & rContext)
+{
+ SwDoc & rDoc = rContext.GetDoc();
+
+ if (m_pTOXBase.get())
+ {
+ rDoc.InsertTableOf(m_nStartNode, m_nEndNode-2, *m_pTOXBase,
+ m_pAttrSet.get());
+ }
+ else
+ {
+ SwNodeIndex aStt( rDoc.GetNodes(), m_nStartNode );
+ SwNodeIndex aEnd( rDoc.GetNodes(), m_nEndNode-2 );
+ SwSectionFmt* pFmt = rDoc.MakeSectionFmt( 0 );
+ if (m_pAttrSet.get())
+ {
+ pFmt->SetFmtAttr( *m_pAttrSet );
+ }
+
+ /// OD 04.10.2002 #102894#
+ /// remember inserted section node for further calculations
+ SwSectionNode* pInsertedSectNd = rDoc.GetNodes().InsertTextSection(
+ aStt, *pFmt, *m_pSectionData, 0, & aEnd);
+
+ if( SFX_ITEM_SET == pFmt->GetItemState( RES_FTN_AT_TXTEND ) ||
+ SFX_ITEM_SET == pFmt->GetItemState( RES_END_AT_TXTEND ))
+ {
+ rDoc.GetFtnIdxs().UpdateFtn( aStt );
+ }
+
+ /// OD 04.10.2002 #102894#
+ /// consider that section is hidden by condition.
+ /// If section is hidden by condition,
+ /// recalculate condition and update hidden condition flag.
+ /// Recalculation is necessary, because fields, on which the hide
+ /// condition depends, can be changed - fields changes aren't undoable.
+ /// NOTE: setting hidden condition flag also creates/deletes corresponding
+ /// frames, if the hidden condition flag changes.
+ SwSection& aInsertedSect = pInsertedSectNd->GetSection();
+ if ( aInsertedSect.IsHidden() &&
+ aInsertedSect.GetCondition().Len() > 0 )
+ {
+ SwCalc aCalc( rDoc );
+ rDoc.FldsToCalc(aCalc, pInsertedSectNd->GetIndex(), USHRT_MAX);
+ bool bRecalcCondHidden =
+ aCalc.Calculate( aInsertedSect.GetCondition() ).GetBool() ? true : false;
+ aInsertedSect.SetCondHidden( bRecalcCondHidden );
+ }
+
+ pFmt->RestoreMetadata(m_pMetadataUndo);
+ }
+}
+
+void SwUndoDelSection::RedoImpl(::sw::UndoRedoContext & rContext)
+{
+ SwDoc & rDoc = rContext.GetDoc();
+
+ SwSectionNode *const pNd =
+ rDoc.GetNodes()[ m_nStartNode ]->GetSectionNode();
+ OSL_ENSURE( pNd, "wo ist mein SectionNode?" );
+ // einfach das Format loeschen, der Rest erfolgt automatisch
+ rDoc.DelSectionFmt( pNd->GetSection().GetFmt() );
+}
+
+
+////////////////////////////////////////////////////////////////////////////
+
+class SwUndoUpdateSection
+ : public SwUndo
+{
+private:
+ ::std::auto_ptr<SwSectionData> m_pSectionData;
+ ::std::auto_ptr<SfxItemSet> m_pAttrSet;
+ sal_uLong const m_nStartNode;
+ bool const m_bOnlyAttrChanged;
+
+public:
+ SwUndoUpdateSection(
+ SwSection const&, SwNodeIndex const*const, bool const bOnlyAttr);
+
+ virtual ~SwUndoUpdateSection();
+
+ virtual void UndoImpl( ::sw::UndoRedoContext & );
+ virtual void RedoImpl( ::sw::UndoRedoContext & );
+};
+
+SW_DLLPRIVATE SwUndo *
+MakeUndoUpdateSection(SwSectionFmt const& rFormat, bool const bOnlyAttr)
+{
+ return new SwUndoUpdateSection(*rFormat.GetSection(),
+ rFormat.GetCntnt().GetCntntIdx(), bOnlyAttr);
+}
+
+SwUndoUpdateSection::SwUndoUpdateSection(
+ SwSection const& rSection, SwNodeIndex const*const pIndex,
+ bool const bOnlyAttr)
+ : SwUndo( UNDO_CHGSECTION )
+ , m_pSectionData( new SwSectionData(rSection) )
+ , m_pAttrSet( ::lcl_GetAttrSet(rSection) )
+ , m_nStartNode( pIndex->GetIndex() )
+ , m_bOnlyAttrChanged( bOnlyAttr )
+{
+}
+
+SwUndoUpdateSection::~SwUndoUpdateSection()
+{
+}
+
+void SwUndoUpdateSection::UndoImpl(::sw::UndoRedoContext & rContext)
+{
+ SwDoc & rDoc = rContext.GetDoc();
+ SwSectionNode *const pSectNd =
+ rDoc.GetNodes()[ m_nStartNode ]->GetSectionNode();
+ OSL_ENSURE( pSectNd, "wo ist mein SectionNode?" );
+
+ SwSection& rNdSect = pSectNd->GetSection();
+ SwFmt* pFmt = rNdSect.GetFmt();
+
+ SfxItemSet* pCur = ::lcl_GetAttrSet( rNdSect );
+ if (m_pAttrSet.get())
+ {
+ // das Content- und Protect-Item muss bestehen bleiben
+ const SfxPoolItem* pItem;
+ m_pAttrSet->Put( pFmt->GetFmtAttr( RES_CNTNT ));
+ if( SFX_ITEM_SET == pFmt->GetItemState( RES_PROTECT, sal_True, &pItem ))
+ {
+ m_pAttrSet->Put( *pItem );
+ }
+ pFmt->DelDiffs( *m_pAttrSet );
+ m_pAttrSet->ClearItem( RES_CNTNT );
+ pFmt->SetFmtAttr( *m_pAttrSet );
+ }
+ else
+ {
+ // dann muessen die alten entfernt werden
+ pFmt->ResetFmtAttr( RES_FRMATR_BEGIN, RES_BREAK );
+ pFmt->ResetFmtAttr( RES_HEADER, RES_OPAQUE );
+ pFmt->ResetFmtAttr( RES_SURROUND, RES_FRMATR_END-1 );
+ }
+ m_pAttrSet.reset(pCur);
+
+ if (!m_bOnlyAttrChanged)
+ {
+ const bool bUpdate =
+ (!rNdSect.IsLinkType() && m_pSectionData->IsLinkType())
+ || ( m_pSectionData->GetLinkFileName().Len()
+ && (m_pSectionData->GetLinkFileName() !=
+ rNdSect.GetLinkFileName()));
+
+ // swap stored section data with live section data
+ SwSectionData *const pOld( new SwSectionData(rNdSect) );
+ rNdSect.SetSectionData(*m_pSectionData);
+ m_pSectionData.reset(pOld);
+
+ if( bUpdate )
+ rNdSect.CreateLink( CREATE_UPDATE );
+ else if( CONTENT_SECTION == rNdSect.GetType() && rNdSect.IsConnected() )
+ {
+ rNdSect.Disconnect();
+ rDoc.GetLinkManager().Remove( &rNdSect.GetBaseLink() );
+ }
+ }
+}
+
+void SwUndoUpdateSection::RedoImpl(::sw::UndoRedoContext & rContext)
+{
+ UndoImpl(rContext);
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/undo/unsort.cxx b/sw/source/core/undo/unsort.cxx
new file mode 100644
index 000000000000..1b72dba58572
--- /dev/null
+++ b/sw/source/core/undo/unsort.cxx
@@ -0,0 +1,282 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+#include <UndoSort.hxx>
+
+#include <doc.hxx>
+#include <swundo.hxx> // fuer die UndoIds
+#include <pam.hxx>
+#include <swtable.hxx>
+#include <ndtxt.hxx>
+#include <UndoCore.hxx>
+#include <UndoTable.hxx>
+#include <sortopt.hxx>
+#include <docsort.hxx>
+#include <redline.hxx>
+#include <node2lay.hxx>
+
+
+/*--------------------------------------------------------------------
+ Beschreibung: Undo fuers Sorting
+ --------------------------------------------------------------------*/
+
+
+SV_IMPL_PTRARR(SwSortList, SwSortUndoElement*)
+SV_IMPL_PTRARR(SwUndoSortList, SwNodeIndex*)
+
+
+SwSortUndoElement::~SwSortUndoElement()
+{
+ // sind String Pointer gespeichert ??
+ if( 0xffffffff != SORT_TXT_TBL.TXT.nKenn )
+ {
+ delete SORT_TXT_TBL.TBL.pSource;
+ delete SORT_TXT_TBL.TBL.pTarget;
+ }
+}
+
+
+SwUndoSort::SwUndoSort(const SwPaM& rRg, const SwSortOptions& rOpt)
+ : SwUndo(UNDO_SORT_TXT), SwUndRng(rRg), pUndoTblAttr( 0 ),
+ pRedlData( 0 )
+{
+ pSortOpt = new SwSortOptions(rOpt);
+}
+
+SwUndoSort::SwUndoSort( sal_uLong nStt, sal_uLong nEnd, const SwTableNode& rTblNd,
+ const SwSortOptions& rOpt, sal_Bool bSaveTable )
+ : SwUndo(UNDO_SORT_TBL), pUndoTblAttr( 0 ), pRedlData( 0 )
+{
+ nSttNode = nStt;
+ nEndNode = nEnd;
+ nTblNd = rTblNd.GetIndex();
+
+ pSortOpt = new SwSortOptions(rOpt);
+ if( bSaveTable )
+ pUndoTblAttr = new SwUndoAttrTbl( rTblNd );
+}
+
+SwUndoSort::~SwUndoSort()
+{
+ delete pSortOpt;
+ delete pUndoTblAttr;
+ delete pRedlData;
+}
+
+void SwUndoSort::UndoImpl(::sw::UndoRedoContext & rContext)
+{
+ SwDoc & rDoc = rContext.GetDoc();
+ if(pSortOpt->bTable)
+ {
+ // Undo Tabelle
+ RemoveIdxFromSection( rDoc, nSttNode, &nEndNode );
+
+ if( pUndoTblAttr )
+ {
+ pUndoTblAttr->UndoImpl(rContext);
+ }
+
+ SwTableNode* pTblNd = rDoc.GetNodes()[ nTblNd ]->GetTableNode();
+
+ // --> FME 2004-11-26 #i37739# A simple 'MakeFrms' after the node sorting
+ // does not work if the table is inside a frame and has no prev/next.
+ SwNode2Layout aNode2Layout( *pTblNd );
+ // <--
+
+ pTblNd->DelFrms();
+ const SwTable& rTbl = pTblNd->GetTable();
+
+ SwMovedBoxes aMovedList;
+ for( sal_uInt16 i=0; i < aSortList.Count(); i++)
+ {
+ const SwTableBox* pSource = rTbl.GetTblBox(
+ *aSortList[i]->SORT_TXT_TBL.TBL.pSource );
+ const SwTableBox* pTarget = rTbl.GetTblBox(
+ *aSortList[i]->SORT_TXT_TBL.TBL.pTarget );
+
+ // zurueckverschieben
+ MoveCell(&rDoc, pTarget, pSource,
+ USHRT_MAX != aMovedList.GetPos(pSource) );
+
+ // schon Verschobenen in der Liste merken
+ aMovedList.Insert(pTarget, aMovedList.Count() );
+ }
+
+ // Restore table frames:
+ // --> FME 2004-11-26 #i37739# A simple 'MakeFrms' after the node sorting
+ // does not work if the table is inside a frame and has no prev/next.
+ const sal_uLong nIdx = pTblNd->GetIndex();
+ aNode2Layout.RestoreUpperFrms( rDoc.GetNodes(), nIdx, nIdx + 1 );
+ // <--
+ }
+ else
+ {
+ // Undo Text
+ SwPaM & rPam( AddUndoRedoPaM(rContext) );
+ RemoveIdxFromRange(rPam, true);
+
+ // fuer die sorted Positions einen Index anlegen.
+ // JP 25.11.97: Die IndexList muss aber nach SourcePosition
+ // aufsteigend sortiert aufgebaut werden
+ SwUndoSortList aIdxList( (sal_uInt8)aSortList.Count() );
+ sal_uInt16 i;
+
+ for( i = 0; i < aSortList.Count(); ++i)
+ for( sal_uInt16 ii=0; ii < aSortList.Count(); ++ii )
+ if( aSortList[ii]->SORT_TXT_TBL.TXT.nSource == nSttNode + i )
+ {
+ SwNodeIndex* pIdx = new SwNodeIndex( rDoc.GetNodes(),
+ aSortList[ii]->SORT_TXT_TBL.TXT.nTarget );
+ aIdxList.C40_INSERT(SwNodeIndex, pIdx, i );
+ break;
+ }
+
+ for(i=0; i < aSortList.Count(); ++i)
+ {
+ SwNodeIndex aIdx( rDoc.GetNodes(), nSttNode + i );
+ SwNodeRange aRg( *aIdxList[i], 0, *aIdxList[i], 1 );
+ rDoc.MoveNodeRange(aRg, aIdx,
+ IDocumentContentOperations::DOC_MOVEDEFAULT);
+ }
+ // Indixes loeschen
+ aIdxList.DeleteAndDestroy(0, aIdxList.Count());
+ SetPaM(rPam, true);
+ }
+}
+
+void SwUndoSort::RedoImpl(::sw::UndoRedoContext & rContext)
+{
+ SwDoc & rDoc = rContext.GetDoc();
+
+ if(pSortOpt->bTable)
+ {
+ // Redo bei Tabelle
+ RemoveIdxFromSection( rDoc, nSttNode, &nEndNode );
+
+ SwTableNode* pTblNd = rDoc.GetNodes()[ nTblNd ]->GetTableNode();
+
+ // --> FME 2004-11-26 #i37739# A simple 'MakeFrms' after the node sorting
+ // does not work if the table is inside a frame and has no prev/next.
+ SwNode2Layout aNode2Layout( *pTblNd );
+ // <--
+
+ pTblNd->DelFrms();
+ const SwTable& rTbl = pTblNd->GetTable();
+
+ SwMovedBoxes aMovedList;
+ for(sal_uInt16 i=0; i < aSortList.Count(); ++i)
+ {
+ const SwTableBox* pSource = rTbl.GetTblBox(
+ (const String&) *aSortList[i]->SORT_TXT_TBL.TBL.pSource );
+ const SwTableBox* pTarget = rTbl.GetTblBox(
+ (const String&) *aSortList[i]->SORT_TXT_TBL.TBL.pTarget );
+
+ // zurueckverschieben
+ MoveCell(&rDoc, pSource, pTarget,
+ USHRT_MAX != aMovedList.GetPos( pTarget ) );
+ // schon Verschobenen in der Liste merken
+ aMovedList.Insert( pSource, aMovedList.Count() );
+ }
+
+ if( pUndoTblAttr )
+ {
+ pUndoTblAttr->RedoImpl(rContext);
+ }
+
+ // Restore table frames:
+ // --> FME 2004-11-26 #i37739# A simple 'MakeFrms' after the node sorting
+ // does not work if the table is inside a frame and has no prev/next.
+ const sal_uLong nIdx = pTblNd->GetIndex();
+ aNode2Layout.RestoreUpperFrms( rDoc.GetNodes(), nIdx, nIdx + 1 );
+ // <--
+ }
+ else
+ {
+ // Redo for Text
+ SwPaM & rPam( AddUndoRedoPaM(rContext) );
+ SetPaM(rPam);
+ RemoveIdxFromRange(rPam, true);
+
+ SwUndoSortList aIdxList( (sal_uInt8)aSortList.Count() );
+ sal_uInt16 i;
+
+ for( i = 0; i < aSortList.Count(); ++i)
+ { // aktuelle Pos ist die Ausgangslage
+ SwNodeIndex* pIdx = new SwNodeIndex( rDoc.GetNodes(),
+ aSortList[i]->SORT_TXT_TBL.TXT.nSource);
+ aIdxList.C40_INSERT( SwNodeIndex, pIdx, i );
+ }
+
+ for(i=0; i < aSortList.Count(); ++i)
+ {
+ SwNodeIndex aIdx( rDoc.GetNodes(), nSttNode + i);
+ SwNodeRange aRg( *aIdxList[i], 0, *aIdxList[i], 1 );
+ rDoc.MoveNodeRange(aRg, aIdx,
+ IDocumentContentOperations::DOC_MOVEDEFAULT);
+ }
+ // Indixes loeschen
+ aIdxList.DeleteAndDestroy(0, aIdxList.Count());
+ SetPaM(rPam, true);
+ SwTxtNode const*const pTNd = rPam.GetNode()->GetTxtNode();
+ if( pTNd )
+ {
+ rPam.GetPoint()->nContent = pTNd->GetTxt().Len();
+ }
+ }
+}
+
+void SwUndoSort::RepeatImpl(::sw::RepeatContext & rContext)
+{
+ // table not repeat capable
+ if(!pSortOpt->bTable)
+ {
+ SwPaM *const pPam = & rContext.GetRepeatPaM();
+ SwDoc& rDoc = *pPam->GetDoc();
+
+ if( !rDoc.IsIdxInTbl( pPam->Start()->nNode ) )
+ rDoc.SortText(*pPam, *pSortOpt);
+ }
+}
+
+void SwUndoSort::Insert( const String& rOrgPos, const String& rNewPos)
+{
+ SwSortUndoElement* pEle = new SwSortUndoElement(rOrgPos, rNewPos);
+ aSortList.C40_INSERT( SwSortUndoElement, pEle, aSortList.Count() );
+}
+
+void SwUndoSort::Insert( sal_uLong nOrgPos, sal_uLong nNewPos)
+{
+ SwSortUndoElement* pEle = new SwSortUndoElement(nOrgPos, nNewPos);
+ aSortList.C40_INSERT( SwSortUndoElement, pEle, aSortList.Count() );
+}
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ \ No newline at end of file
diff --git a/sw/source/core/undo/unspnd.cxx b/sw/source/core/undo/unspnd.cxx
new file mode 100644
index 000000000000..317d1baa4652
--- /dev/null
+++ b/sw/source/core/undo/unspnd.cxx
@@ -0,0 +1,206 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+#include <UndoSplitMove.hxx>
+
+#include "doc.hxx"
+#include "pam.hxx"
+#include "swtable.hxx"
+#include "ndtxt.hxx"
+#include "swundo.hxx" // fuer die UndoIds
+#include <editeng/brkitem.hxx>
+#include <fmtpdsc.hxx>
+#include <frmfmt.hxx>
+#include <UndoCore.hxx>
+#include "rolbck.hxx"
+#include "redline.hxx"
+#include "docary.hxx"
+#include <IShellCursorSupplier.hxx>
+
+
+//------------------------------------------------------------------
+
+// SPLITNODE
+
+
+SwUndoSplitNode::SwUndoSplitNode( SwDoc* pDoc, const SwPosition& rPos,
+ sal_Bool bChkTable )
+ : SwUndo( UNDO_SPLITNODE ), pHistory( 0 ), pRedlData( 0 ), nNode( rPos.nNode.GetIndex() ),
+ nCntnt( rPos.nContent.GetIndex() ),
+ bTblFlag( sal_False ), bChkTblStt( bChkTable )
+{
+ SwTxtNode *const pTxtNd = rPos.nNode.GetNode().GetTxtNode();
+ OSL_ENSURE( pTxtNd, "nur beim TextNode rufen!" );
+ if( pTxtNd->GetpSwpHints() )
+ {
+ pHistory = new SwHistory;
+ pHistory->CopyAttr( pTxtNd->GetpSwpHints(), nNode, 0,
+ pTxtNd->GetTxt().Len(), false );
+ if( !pHistory->Count() )
+ DELETEZ( pHistory );
+ }
+ // Redline beachten
+ if( pDoc->IsRedlineOn() )
+ {
+ pRedlData = new SwRedlineData( nsRedlineType_t::REDLINE_INSERT, pDoc->GetRedlineAuthor() );
+ SetRedlineMode( pDoc->GetRedlineMode() );
+ }
+}
+
+SwUndoSplitNode::~SwUndoSplitNode()
+{
+ delete pHistory;
+ delete pRedlData;
+}
+
+void SwUndoSplitNode::UndoImpl(::sw::UndoRedoContext & rContext)
+{
+ SwDoc *const pDoc = & rContext.GetDoc();
+ SwPaM & rPam( rContext.GetCursorSupplier().CreateNewShellCursor() );
+ rPam.DeleteMark();
+ if( bTblFlag )
+ {
+ // dann wurde direkt vor der akt. Tabelle ein TextNode eingefuegt.
+ SwNodeIndex& rIdx = rPam.GetPoint()->nNode;
+ rIdx = nNode;
+ SwTxtNode* pTNd;
+ SwNode* pCurrNd = pDoc->GetNodes()[ nNode + 1 ];
+ SwTableNode* pTblNd = pCurrNd->FindTableNode();
+ if( pCurrNd->IsCntntNode() && pTblNd &&
+ 0 != ( pTNd = pDoc->GetNodes()[ pTblNd->GetIndex()-1 ]->GetTxtNode() ))
+ {
+ // verschiebe die BreakAttribute noch
+ SwFrmFmt* pTableFmt = pTblNd->GetTable().GetFrmFmt();
+ const SfxItemSet* pNdSet = pTNd->GetpSwAttrSet();
+ if( pNdSet )
+ {
+ const SfxPoolItem *pItem;
+ if( SFX_ITEM_SET == pNdSet->GetItemState( RES_PAGEDESC, sal_False,
+ &pItem ) )
+ pTableFmt->SetFmtAttr( *pItem );
+
+ if( SFX_ITEM_SET == pNdSet->GetItemState( RES_BREAK, sal_False,
+ &pItem ) )
+ pTableFmt->SetFmtAttr( *pItem );
+ }
+
+ // dann loesche den wieder
+ SwNodeIndex aDelNd( *pTblNd, -1 );
+ rPam.GetPoint()->nContent.Assign( (SwCntntNode*)pCurrNd, 0 );
+ RemoveIdxRel( aDelNd.GetIndex(), *rPam.GetPoint() );
+ pDoc->GetNodes().Delete( aDelNd );
+ }
+ }
+ else
+ {
+ SwTxtNode * pTNd = pDoc->GetNodes()[ nNode ]->GetTxtNode();
+ if( pTNd )
+ {
+ rPam.GetPoint()->nNode = *pTNd;
+ rPam.GetPoint()->nContent.Assign( pTNd, pTNd->GetTxt().Len() );
+
+ if( IDocumentRedlineAccess::IsRedlineOn( GetRedlineMode() ))
+ {
+ rPam.SetMark();
+ rPam.GetMark()->nNode++;
+ rPam.GetMark()->nContent.Assign( rPam.GetMark()->
+ nNode.GetNode().GetCntntNode(), 0 );
+ pDoc->DeleteRedline( rPam, true, USHRT_MAX );
+ rPam.DeleteMark();
+ }
+
+ RemoveIdxRel( nNode+1, *rPam.GetPoint() );
+
+ pTNd->JoinNext();
+ if( pHistory )
+ {
+ rPam.GetPoint()->nContent = 0;
+ rPam.SetMark();
+ rPam.GetPoint()->nContent = pTNd->GetTxt().Len();
+
+ pDoc->RstTxtAttrs( rPam, sal_True );
+ pHistory->TmpRollback( pDoc, 0, false );
+ }
+ }
+ }
+
+ // setze noch den Cursor auf den Undo-Bereich
+ rPam.DeleteMark();
+ rPam.GetPoint()->nNode = nNode;
+ rPam.GetPoint()->nContent.Assign( rPam.GetCntntNode(), nCntnt );
+}
+
+void SwUndoSplitNode::RedoImpl(::sw::UndoRedoContext & rContext)
+{
+ SwPaM & rPam( rContext.GetCursorSupplier().CreateNewShellCursor() );
+ rPam.GetPoint()->nNode = nNode;
+ SwTxtNode * pTNd = rPam.GetNode()->GetTxtNode();
+ OSL_ENSURE(pTNd, "SwUndoSplitNode::RedoImpl(): SwTxtNode expected");
+ if (pTNd)
+ {
+ rPam.GetPoint()->nContent.Assign( pTNd, nCntnt );
+
+ SwDoc* pDoc = rPam.GetDoc();
+ pDoc->SplitNode( *rPam.GetPoint(), bChkTblStt );
+
+ if( pHistory )
+ pHistory->SetTmpEnd( pHistory->Count() );
+
+ if( ( pRedlData && IDocumentRedlineAccess::IsRedlineOn( GetRedlineMode() )) ||
+ ( !( nsRedlineMode_t::REDLINE_IGNORE & GetRedlineMode() ) &&
+ pDoc->GetRedlineTbl().Count() ))
+ {
+ rPam.SetMark();
+ if( rPam.Move( fnMoveBackward ))
+ {
+ if( pRedlData && IDocumentRedlineAccess::IsRedlineOn( GetRedlineMode() ))
+ {
+ RedlineMode_t eOld = pDoc->GetRedlineMode();
+ pDoc->SetRedlineMode_intern((RedlineMode_t)(eOld & ~nsRedlineMode_t::REDLINE_IGNORE));
+ pDoc->AppendRedline( new SwRedline( *pRedlData, rPam ), true);
+ pDoc->SetRedlineMode_intern( eOld );
+ }
+ else
+ pDoc->SplitRedline( rPam );
+ rPam.Exchange();
+ }
+ rPam.DeleteMark();
+ }
+ }
+}
+
+void SwUndoSplitNode::RepeatImpl(::sw::RepeatContext & rContext)
+{
+ rContext.GetDoc().SplitNode(
+ *rContext.GetRepeatPaM().GetPoint(), bChkTblStt );
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/undo/untbl.cxx b/sw/source/core/undo/untbl.cxx
new file mode 100644
index 000000000000..ee16891ab5e1
--- /dev/null
+++ b/sw/source/core/undo/untbl.cxx
@@ -0,0 +1,3269 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+#include <UndoTable.hxx>
+
+#include <UndoRedline.hxx>
+#include <UndoDelete.hxx>
+#include <UndoSplitMove.hxx>
+#include <UndoCore.hxx>
+#include <hintids.hxx>
+#include <hints.hxx>
+#include <editeng/brkitem.hxx>
+#include <fmtornt.hxx>
+#include <fmtpdsc.hxx>
+#include <doc.hxx>
+#include <IDocumentUndoRedo.hxx>
+#include <editsh.hxx>
+#include <docary.hxx>
+#include <ndtxt.hxx>
+#include <swtable.hxx>
+#include <pam.hxx>
+#include <cntfrm.hxx>
+#include <tblsel.hxx>
+#include <swundo.hxx> // fuer die UndoIds
+#include <rolbck.hxx>
+#include <ddefld.hxx>
+#include <tabcol.hxx>
+#include <tabfrm.hxx>
+#include <rowfrm.hxx>
+#include <cellfrm.hxx>
+#include <swcache.hxx>
+#include <tblafmt.hxx>
+#include <poolfmt.hxx>
+#include <mvsave.hxx>
+#include <cellatr.hxx>
+#include <swtblfmt.hxx>
+#include <swddetbl.hxx>
+#include <redline.hxx>
+#include <node2lay.hxx>
+#include <tblrwcl.hxx>
+#include <fmtanchr.hxx>
+#include <comcore.hrc>
+#include <unochart.hxx>
+#include <switerator.hxx>
+
+#if OSL_DEBUG_LEVEL > 1
+#define CHECK_TABLE(t) (t).CheckConsistency();
+#else
+#define CHECK_TABLE(t)
+#endif
+
+#if OSL_DEBUG_LEVEL > 1
+ void lcl_DebugRedline( const SwDoc* pDoc );
+ #define _DEBUG_REDLINE( pDoc ) lcl_DebugRedline( pDoc );
+#else
+ #define _DEBUG_REDLINE( pDoc )
+#endif
+
+extern void ClearFEShellTabCols();
+
+typedef SfxItemSet* SfxItemSetPtr;
+SV_DECL_PTRARR_DEL( SfxItemSets, SfxItemSetPtr, 10, 5 )
+
+typedef SwUndoSaveSection* SwUndoSaveSectionPtr;
+SV_DECL_PTRARR_DEL( SwUndoSaveSections, SwUndoSaveSectionPtr, 0, 10 )
+
+typedef SwUndoMove* SwUndoMovePtr;
+SV_DECL_PTRARR_DEL( SwUndoMoves, SwUndoMovePtr, 0, 10 )
+
+struct SwTblToTxtSave;
+typedef SwTblToTxtSave* SwTblToTxtSavePtr;
+SV_DECL_PTRARR_DEL( SwTblToTxtSaves, SwTblToTxtSavePtr, 0, 10 )
+
+struct _UndoTblCpyTbl_Entry
+{
+ sal_uLong nBoxIdx, nOffset;
+ SfxItemSet* pBoxNumAttr;
+ SwUndo* pUndo;
+
+ // Was the last paragraph of the new and the first paragraph of the old content joined?
+ bool bJoin; // For redlining only
+
+ _UndoTblCpyTbl_Entry( const SwTableBox& rBox );
+ ~_UndoTblCpyTbl_Entry();
+};
+typedef _UndoTblCpyTbl_Entry* _UndoTblCpyTbl_EntryPtr;
+SV_DECL_PTRARR_DEL( _UndoTblCpyTbl_Entries, _UndoTblCpyTbl_EntryPtr, 0, 10 )
+
+class _SaveBox;
+class _SaveLine;
+
+class _SaveTable
+{
+ friend class _SaveBox;
+ friend class _SaveLine;
+ SfxItemSet aTblSet;
+ _SaveLine* pLine;
+ const SwTable* pSwTable;
+ SfxItemSets aSets;
+ SwFrmFmts aFrmFmts;
+ sal_uInt16 nLineCount;
+ sal_Bool bModifyBox : 1;
+ sal_Bool bSaveFormula : 1;
+ sal_Bool bNewModel : 1;
+
+public:
+ _SaveTable( const SwTable& rTbl, sal_uInt16 nLnCnt = USHRT_MAX,
+ sal_Bool bSaveFml = sal_True );
+ ~_SaveTable();
+
+ sal_uInt16 AddFmt( SwFrmFmt* pFmt, bool bIsLine );
+ void NewFrmFmt( const SwTableLine* , const SwTableBox*, sal_uInt16 nFmtPos,
+ SwFrmFmt* pOldFmt );
+
+ void RestoreAttr( SwTable& rTbl, sal_Bool bModifyBox = sal_False );
+ void SaveCntntAttrs( SwDoc* pDoc );
+ void CreateNew( SwTable& rTbl, sal_Bool bCreateFrms = sal_True,
+ sal_Bool bRestoreChart = sal_True );
+ sal_Bool IsNewModel() const { return bNewModel; }
+};
+
+class _SaveLine
+{
+ friend class _SaveTable;
+ friend class _SaveBox;
+
+ _SaveLine* pNext;
+ _SaveBox* pBox;
+ sal_uInt16 nItemSet;
+
+public:
+
+ _SaveLine( _SaveLine* pPrev, const SwTableLine& rLine, _SaveTable& rSTbl );
+ ~_SaveLine();
+
+ void RestoreAttr( SwTableLine& rLine, _SaveTable& rSTbl );
+ void SaveCntntAttrs( SwDoc* pDoc );
+
+ void CreateNew( SwTable& rTbl, SwTableBox& rParent, _SaveTable& rSTbl );
+};
+
+class _SaveBox
+{
+ friend class _SaveLine;
+
+ _SaveBox* pNext;
+ sal_uLong nSttNode;
+ long nRowSpan;
+ sal_uInt16 nItemSet;
+ union
+ {
+ SfxItemSets* pCntntAttrs;
+ _SaveLine* pLine;
+ } Ptrs;
+
+public:
+ _SaveBox( _SaveBox* pPrev, const SwTableBox& rBox, _SaveTable& rSTbl );
+ ~_SaveBox();
+
+ void RestoreAttr( SwTableBox& rBox, _SaveTable& rSTbl );
+ void SaveCntntAttrs( SwDoc* pDoc );
+
+ void CreateNew( SwTable& rTbl, SwTableLine& rParent, _SaveTable& rSTbl );
+};
+
+void InsertSort( SvUShorts& rArr, sal_uInt16 nIdx, sal_uInt16* pInsPos = 0 );
+void InsertSort( SvULongs& rArr, sal_uLong nIdx, sal_uInt16* pInsPos = 0 );
+
+#if OSL_DEBUG_LEVEL > 1
+#include "shellio.hxx"
+void CheckTable( const SwTable& );
+#define CHECKTABLE(t) CheckTable( t );
+#else
+#define CHECKTABLE(t)
+#endif
+
+/* #130880: Crash in undo of table to text when the table has (freshly) merged cells
+The order of cell content nodes in the nodes array is not given by the recursive table structure.
+The algorithmn must not rely on this even it holds for a fresh loaded table in odt file format.
+So we need to remember not only the start node position but the end node position as well.
+*/
+
+struct SwTblToTxtSave
+{
+ sal_uLong m_nSttNd;
+ sal_uLong m_nEndNd;
+ xub_StrLen m_nCntnt;
+ SwHistory* m_pHstry;
+ // metadata references for first and last paragraph in cell
+ ::boost::shared_ptr< ::sfx2::MetadatableUndo > m_pMetadataUndoStart;
+ ::boost::shared_ptr< ::sfx2::MetadatableUndo > m_pMetadataUndoEnd;
+
+ SwTblToTxtSave( SwDoc& rDoc, sal_uLong nNd, sal_uLong nEndIdx, xub_StrLen nCntnt );
+ ~SwTblToTxtSave() { delete m_pHstry; }
+};
+
+SV_IMPL_PTRARR( SfxItemSets, SfxItemSetPtr )
+SV_IMPL_PTRARR( SwUndoSaveSections, SwUndoSaveSectionPtr )
+SV_IMPL_PTRARR( SwUndoMoves, SwUndoMovePtr )
+SV_IMPL_PTRARR( SwTblToTxtSaves, SwTblToTxtSavePtr )
+SV_IMPL_PTRARR( _UndoTblCpyTbl_Entries, _UndoTblCpyTbl_EntryPtr )
+
+sal_uInt16 aSave_BoxCntntSet[] = {
+ RES_CHRATR_COLOR, RES_CHRATR_CROSSEDOUT,
+ RES_CHRATR_FONT, RES_CHRATR_FONTSIZE,
+ RES_CHRATR_POSTURE, RES_CHRATR_POSTURE,
+ RES_CHRATR_SHADOWED, RES_CHRATR_WEIGHT,
+ RES_PARATR_ADJUST, RES_PARATR_ADJUST,
+ 0 };
+
+
+
+SwUndoInsTbl::SwUndoInsTbl( const SwPosition& rPos, sal_uInt16 nCl, sal_uInt16 nRw,
+ sal_uInt16 nAdj, const SwInsertTableOptions& rInsTblOpts,
+ const SwTableAutoFmt* pTAFmt,
+ const SvUShorts* pColArr,
+ const String & rName)
+ : SwUndo( UNDO_INSTABLE ),
+ aInsTblOpts( rInsTblOpts ), pDDEFldType( 0 ), pColWidth( 0 ), pRedlData( 0 ), pAutoFmt( 0 ),
+ nSttNode( rPos.nNode.GetIndex() ), nRows( nRw ), nCols( nCl ), nAdjust( nAdj )
+{
+ if( pColArr )
+ {
+ pColWidth = new SvUShorts( 0, 1 );
+ pColWidth->Insert( pColArr, 0 );
+ }
+ if( pTAFmt )
+ pAutoFmt = new SwTableAutoFmt( *pTAFmt );
+
+ // Redline beachten
+ SwDoc& rDoc = *rPos.nNode.GetNode().GetDoc();
+ if( rDoc.IsRedlineOn() )
+ {
+ pRedlData = new SwRedlineData( nsRedlineType_t::REDLINE_INSERT, rDoc.GetRedlineAuthor() );
+ SetRedlineMode( rDoc.GetRedlineMode() );
+ }
+
+ sTblNm = rName;
+}
+
+
+SwUndoInsTbl::~SwUndoInsTbl()
+{
+ delete pDDEFldType;
+ delete pColWidth;
+ delete pRedlData;
+ delete pAutoFmt;
+}
+
+void SwUndoInsTbl::UndoImpl(::sw::UndoRedoContext & rContext)
+{
+ SwDoc & rDoc = rContext.GetDoc();
+ SwNodeIndex aIdx( rDoc.GetNodes(), nSttNode );
+
+ SwTableNode* pTblNd = aIdx.GetNode().GetTableNode();
+ OSL_ENSURE( pTblNd, "kein TabellenNode" );
+ pTblNd->DelFrms();
+
+ if( IDocumentRedlineAccess::IsRedlineOn( GetRedlineMode() ))
+ rDoc.DeleteRedline( *pTblNd, true, USHRT_MAX );
+ RemoveIdxFromSection( rDoc, nSttNode );
+
+ // harte SeitenUmbrueche am nachfolgenden Node verschieben
+ SwCntntNode* pNextNd = rDoc.GetNodes()[ pTblNd->EndOfSectionIndex()+1 ]->GetCntntNode();
+ if( pNextNd )
+ {
+ SwFrmFmt* pTableFmt = pTblNd->GetTable().GetFrmFmt();
+ const SfxPoolItem *pItem;
+
+ if( SFX_ITEM_SET == pTableFmt->GetItemState( RES_PAGEDESC,
+ sal_False, &pItem ) )
+ pNextNd->SetAttr( *pItem );
+
+ if( SFX_ITEM_SET == pTableFmt->GetItemState( RES_BREAK,
+ sal_False, &pItem ) )
+ pNextNd->SetAttr( *pItem );
+ }
+
+
+ sTblNm = pTblNd->GetTable().GetFrmFmt()->GetName();
+ if( pTblNd->GetTable().IsA( TYPE( SwDDETable )) )
+ pDDEFldType = (SwDDEFieldType*)((SwDDETable&)pTblNd->GetTable()).
+ GetDDEFldType()->Copy();
+
+ rDoc.GetNodes().Delete( aIdx, pTblNd->EndOfSectionIndex() -
+ aIdx.GetIndex() + 1 );
+
+ SwPaM & rPam( rContext.GetCursorSupplier().CreateNewShellCursor() );
+ rPam.DeleteMark();
+ rPam.GetPoint()->nNode = aIdx;
+ rPam.GetPoint()->nContent.Assign( rPam.GetCntntNode(), 0 );
+}
+
+
+void SwUndoInsTbl::RedoImpl(::sw::UndoRedoContext & rContext)
+{
+ SwDoc & rDoc = rContext.GetDoc();
+
+ SwPosition const aPos(SwNodeIndex(rDoc.GetNodes(), nSttNode));
+ const SwTable* pTbl = rDoc.InsertTable( aInsTblOpts, aPos, nRows, nCols,
+ nAdjust,
+ pAutoFmt, pColWidth );
+ ((SwFrmFmt*)pTbl->GetFrmFmt())->SetName( sTblNm );
+ SwTableNode* pTblNode = (SwTableNode*)rDoc.GetNodes()[nSttNode]->GetTableNode();
+
+ if( pDDEFldType )
+ {
+ SwDDEFieldType* pNewType = (SwDDEFieldType*)rDoc.InsertFldType(
+ *pDDEFldType);
+ SwDDETable* pDDETbl = new SwDDETable( pTblNode->GetTable(), pNewType );
+ pTblNode->SetNewTable( pDDETbl ); // setze die DDE-Tabelle
+ delete pDDEFldType, pDDEFldType = 0;
+ }
+
+ if( (pRedlData && IDocumentRedlineAccess::IsRedlineOn( GetRedlineMode() )) ||
+ ( !( nsRedlineMode_t::REDLINE_IGNORE & GetRedlineMode() ) &&
+ rDoc.GetRedlineTbl().Count() ))
+ {
+ SwPaM aPam( *pTblNode->EndOfSectionNode(), *pTblNode, 1 );
+ SwCntntNode* pCNd = aPam.GetCntntNode( sal_False );
+ if( pCNd )
+ aPam.GetMark()->nContent.Assign( pCNd, 0 );
+
+ if( pRedlData && IDocumentRedlineAccess::IsRedlineOn( GetRedlineMode() ) )
+ {
+ RedlineMode_t eOld = rDoc.GetRedlineMode();
+ rDoc.SetRedlineMode_intern((RedlineMode_t)(eOld & ~nsRedlineMode_t::REDLINE_IGNORE));
+
+ rDoc.AppendRedline( new SwRedline( *pRedlData, aPam ), true);
+ rDoc.SetRedlineMode_intern( eOld );
+ }
+ else
+ rDoc.SplitRedline( aPam );
+ }
+}
+
+
+void SwUndoInsTbl::RepeatImpl(::sw::RepeatContext & rContext)
+{
+ rContext.GetDoc().InsertTable(
+ aInsTblOpts, *rContext.GetRepeatPaM().GetPoint(),
+ nRows, nCols, nAdjust, pAutoFmt, pColWidth );
+}
+
+SwRewriter SwUndoInsTbl::GetRewriter() const
+{
+ SwRewriter aRewriter;
+
+ aRewriter.AddRule(UNDO_ARG1, SW_RES(STR_START_QUOTE));
+ aRewriter.AddRule(UNDO_ARG2, sTblNm);
+ aRewriter.AddRule(UNDO_ARG3, SW_RES(STR_END_QUOTE));
+
+ return aRewriter;
+}
+
+// -----------------------------------------------------
+
+SwTblToTxtSave::SwTblToTxtSave( SwDoc& rDoc, sal_uLong nNd, sal_uLong nEndIdx, xub_StrLen nCnt )
+ : m_nSttNd( nNd ), m_nEndNd( nEndIdx), m_nCntnt( nCnt ), m_pHstry( 0 )
+{
+ // Attributierung des gejointen Node merken.
+ SwTxtNode* pNd = rDoc.GetNodes()[ nNd ]->GetTxtNode();
+ if( pNd )
+ {
+ m_pHstry = new SwHistory;
+
+ m_pHstry->Add( pNd->GetTxtColl(), nNd, ND_TEXTNODE );
+ if ( pNd->GetpSwpHints() )
+ {
+ m_pHstry->CopyAttr( pNd->GetpSwpHints(), nNd, 0,
+ pNd->GetTxt().Len(), false );
+ }
+ if( pNd->HasSwAttrSet() )
+ m_pHstry->CopyFmtAttr( *pNd->GetpSwAttrSet(), nNd );
+
+ if( !m_pHstry->Count() )
+ delete m_pHstry, m_pHstry = 0;
+
+ // METADATA: store
+ m_pMetadataUndoStart = pNd->CreateUndo();
+ }
+
+ // we also need to store the metadata reference of the _last_ paragraph
+ // we subtract 1 to account for the removed cell start/end node pair
+ // (after SectionUp, the end of the range points to the node after the cell)
+ if ( nEndIdx - 1 > nNd )
+ {
+ SwTxtNode* pLastNode( rDoc.GetNodes()[ nEndIdx - 1 ]->GetTxtNode() );
+ if( pLastNode )
+ {
+ // METADATA: store
+ m_pMetadataUndoEnd = pLastNode->CreateUndo();
+ }
+ }
+}
+
+SwUndoTblToTxt::SwUndoTblToTxt( const SwTable& rTbl, sal_Unicode cCh )
+ : SwUndo( UNDO_TABLETOTEXT ),
+ sTblNm( rTbl.GetFrmFmt()->GetName() ), pDDEFldType( 0 ), pHistory( 0 ),
+ nSttNd( 0 ), nEndNd( 0 ),
+ nAdjust( static_cast<sal_uInt16>(rTbl.GetFrmFmt()->GetHoriOrient().GetHoriOrient()) ),
+ cTrenner( cCh ), nHdlnRpt( rTbl.GetRowsToRepeat() )
+{
+ pTblSave = new _SaveTable( rTbl );
+ pBoxSaves = new SwTblToTxtSaves( (sal_uInt8)rTbl.GetTabSortBoxes().Count() );
+
+ if( rTbl.IsA( TYPE( SwDDETable ) ) )
+ pDDEFldType = (SwDDEFieldType*)((SwDDETable&)rTbl).GetDDEFldType()->Copy();
+
+ bCheckNumFmt = rTbl.GetFrmFmt()->GetDoc()->IsInsTblFormatNum();
+
+ pHistory = new SwHistory;
+ const SwTableNode* pTblNd = rTbl.GetTableNode();
+ sal_uLong nTblStt = pTblNd->GetIndex(), nTblEnd = pTblNd->EndOfSectionIndex();
+
+ const SwSpzFrmFmts& rFrmFmtTbl = *pTblNd->GetDoc()->GetSpzFrmFmts();
+ for( sal_uInt16 n = 0; n < rFrmFmtTbl.Count(); ++n )
+ {
+ SwFrmFmt* pFmt = rFrmFmtTbl[ n ];
+ SwFmtAnchor const*const pAnchor = &pFmt->GetAnchor();
+ SwPosition const*const pAPos = pAnchor->GetCntntAnchor();
+ if (pAPos &&
+ ((FLY_AT_CHAR == pAnchor->GetAnchorId()) ||
+ (FLY_AT_PARA == pAnchor->GetAnchorId())) &&
+ nTblStt <= pAPos->nNode.GetIndex() &&
+ pAPos->nNode.GetIndex() < nTblEnd )
+ {
+ pHistory->Add( *pFmt );
+ }
+ }
+
+ if( !pHistory->Count() )
+ delete pHistory, pHistory = 0;
+}
+
+
+SwUndoTblToTxt::~SwUndoTblToTxt()
+{
+ delete pDDEFldType;
+ delete pTblSave;
+ delete pBoxSaves;
+ delete pHistory;
+}
+
+
+
+void SwUndoTblToTxt::UndoImpl(::sw::UndoRedoContext & rContext)
+{
+ SwDoc & rDoc = rContext.GetDoc();
+ SwPaM *const pPam(& rContext.GetCursorSupplier().CreateNewShellCursor());
+
+ SwNodeIndex aFrmIdx( rDoc.GetNodes(), nSttNd );
+ SwNodeIndex aEndIdx( rDoc.GetNodes(), nEndNd );
+
+ pPam->GetPoint()->nNode = aFrmIdx;
+ pPam->SetMark();
+ pPam->GetPoint()->nNode = aEndIdx;
+ rDoc.DelNumRules( *pPam );
+ pPam->DeleteMark();
+
+ // dann sammel mal alle Uppers ein
+ SwNode2Layout aNode2Layout( aFrmIdx.GetNode() );
+
+ // erzeuge die TabelleNode Structur
+ SwTableNode* pTblNd = rDoc.GetNodes().UndoTableToText( nSttNd, nEndNd, *pBoxSaves );
+ pTblNd->GetTable().SetTableModel( pTblSave->IsNewModel() );
+ SwTableFmt* pTableFmt = rDoc.MakeTblFrmFmt( sTblNm, rDoc.GetDfltFrmFmt() );
+ pTblNd->GetTable().RegisterToFormat( *pTableFmt );
+ pTblNd->GetTable().SetRowsToRepeat( nHdlnRpt );
+
+ // erzeuge die alte Tabellen Struktur
+ pTblSave->CreateNew( pTblNd->GetTable() );
+
+ if( pDDEFldType )
+ {
+ SwDDEFieldType* pNewType = (SwDDEFieldType*)rDoc.InsertFldType(
+ *pDDEFldType);
+ SwDDETable* pDDETbl = new SwDDETable( pTblNd->GetTable(), pNewType );
+ pTblNd->SetNewTable( pDDETbl, sal_False ); // setze die DDE-Tabelle
+ delete pDDEFldType, pDDEFldType = 0;
+ }
+
+ if( bCheckNumFmt )
+ {
+ SwTableSortBoxes& rBxs = pTblNd->GetTable().GetTabSortBoxes();
+ for( sal_uInt16 nBoxes = rBxs.Count(); nBoxes; )
+ rDoc.ChkBoxNumFmt( *rBxs[ --nBoxes ], sal_False );
+ }
+
+ if( pHistory )
+ {
+ sal_uInt16 nTmpEnd = pHistory->GetTmpEnd();
+ pHistory->TmpRollback( &rDoc, 0 );
+ pHistory->SetTmpEnd( nTmpEnd );
+ }
+
+ aNode2Layout.RestoreUpperFrms( rDoc.GetNodes(),
+ pTblNd->GetIndex(), pTblNd->GetIndex()+1 );
+
+ // will man eine TabellenSelektion ??
+ pPam->DeleteMark();
+ pPam->GetPoint()->nNode = *pTblNd->EndOfSectionNode();
+ pPam->SetMark();
+ pPam->GetPoint()->nNode = *pPam->GetNode()->StartOfSectionNode();
+ pPam->Move( fnMoveForward, fnGoCntnt );
+ pPam->Exchange();
+ pPam->Move( fnMoveBackward, fnGoCntnt );
+
+ ClearFEShellTabCols();
+}
+
+ // steht im untbl.cxx und darf nur vom Undoobject gerufen werden
+SwTableNode* SwNodes::UndoTableToText( sal_uLong nSttNd, sal_uLong nEndNd,
+ const SwTblToTxtSaves& rSavedData )
+{
+ SwNodeIndex aSttIdx( *this, nSttNd );
+ SwNodeIndex aEndIdx( *this, nEndNd+1 );
+
+ SwTableNode * pTblNd = new SwTableNode( aSttIdx );
+ SwEndNode* pEndNd = new SwEndNode( aEndIdx, *pTblNd );
+
+ aEndIdx = *pEndNd;
+
+ /* Set pTblNd as start of section for all nodes in [nSttNd, nEndNd].
+ Delete all Frames attached to the nodes in that range. */
+ SwNode* pNd;
+ {
+ sal_uLong n, nTmpEnd = aEndIdx.GetIndex();
+ for( n = pTblNd->GetIndex() + 1; n < nTmpEnd; ++n )
+ {
+ if( ( pNd = (*this)[ n ] )->IsCntntNode() )
+ ((SwCntntNode*)pNd)->DelFrms();
+ pNd->pStartOfSection = pTblNd;
+ }
+ }
+
+ // dann die Tabellen Struktur teilweise aufbauen. Erstmal eine Line
+ // in der alle Boxen stehen! Die korrekte Struktur kommt dann aus der
+ // SaveStruct
+ SwTableBoxFmt* pBoxFmt = GetDoc()->MakeTableBoxFmt();
+ SwTableLineFmt* pLineFmt = GetDoc()->MakeTableLineFmt();
+ SwTableLine* pLine = new SwTableLine( pLineFmt, rSavedData.Count(), 0 );
+ pTblNd->GetTable().GetTabLines().C40_INSERT( SwTableLine, pLine, 0 );
+
+ SvULongs aBkmkArr( 0, 4 );
+ for( sal_uInt16 n = rSavedData.Count(); n; )
+ {
+ SwTblToTxtSave* pSave = rSavedData[ --n ];
+ // if the start node was merged with last from prev. cell,
+ // subtract 1 from index to get the merged paragraph, and split that
+ aSttIdx = pSave->m_nSttNd - ( ( USHRT_MAX != pSave->m_nCntnt ) ? 1 : 0);
+ SwTxtNode* pTxtNd = aSttIdx.GetNode().GetTxtNode();
+
+ if( USHRT_MAX != pSave->m_nCntnt )
+ {
+ // an der ContentPosition splitten, das vorherige Zeichen
+ // loeschen (ist der Trenner!)
+ OSL_ENSURE( pTxtNd, "Wo ist der TextNode geblieben?" );
+ SwIndex aCntPos( pTxtNd, pSave->m_nCntnt - 1 );
+
+ pTxtNd->EraseText( aCntPos, 1 );
+ SwCntntNode* pNewNd = pTxtNd->SplitCntntNode(
+ SwPosition( aSttIdx, aCntPos ));
+ if( aBkmkArr.Count() )
+ _RestoreCntntIdx( aBkmkArr, *pNewNd, pSave->m_nCntnt,
+ pSave->m_nCntnt + 1 );
+ }
+ else
+ {
+ if( aBkmkArr.Count() )
+ aBkmkArr.Remove( 0, aBkmkArr.Count() );
+ if( pTxtNd )
+ _SaveCntntIdx( GetDoc(), aSttIdx.GetIndex(),
+ pTxtNd->GetTxt().Len(), aBkmkArr );
+ }
+
+ if( pTxtNd )
+ {
+ // METADATA: restore
+ pTxtNd->GetTxtNode()->RestoreMetadata(pSave->m_pMetadataUndoStart);
+ if( pTxtNd->HasSwAttrSet() )
+ pTxtNd->ResetAllAttr();
+
+ if( pTxtNd->GetpSwpHints() )
+ pTxtNd->ClearSwpHintsArr( false );
+ }
+
+ if( pSave->m_pHstry )
+ {
+ sal_uInt16 nTmpEnd = pSave->m_pHstry->GetTmpEnd();
+ pSave->m_pHstry->TmpRollback( GetDoc(), 0 );
+ pSave->m_pHstry->SetTmpEnd( nTmpEnd );
+ }
+
+ // METADATA: restore
+ // end points to node after cell
+ if ( pSave->m_nEndNd - 1 > pSave->m_nSttNd )
+ {
+ SwTxtNode* pLastNode = (*this)[ pSave->m_nEndNd - 1 ]->GetTxtNode();
+ if (pLastNode)
+ {
+ pLastNode->RestoreMetadata(pSave->m_pMetadataUndoEnd);
+ }
+ }
+
+ aEndIdx = pSave->m_nEndNd;
+ SwStartNode* pSttNd = new SwStartNode( aSttIdx, ND_STARTNODE,
+ SwTableBoxStartNode );
+ pSttNd->pStartOfSection = pTblNd;
+ new SwEndNode( aEndIdx, *pSttNd );
+
+ for( sal_uLong i = aSttIdx.GetIndex(); i < aEndIdx.GetIndex()-1; ++i )
+ {
+ pNd = (*this)[ i ];
+ pNd->pStartOfSection = pSttNd;
+ if( pNd->IsStartNode() )
+ i = pNd->EndOfSectionIndex();
+ }
+
+ SwTableBox* pBox = new SwTableBox( pBoxFmt, *pSttNd, pLine );
+ pLine->GetTabBoxes().C40_INSERT( SwTableBox, pBox, 0 );
+ }
+ return pTblNd;
+}
+
+
+void SwUndoTblToTxt::RedoImpl(::sw::UndoRedoContext & rContext)
+{
+ SwDoc & rDoc = rContext.GetDoc();
+ SwPaM *const pPam(& rContext.GetCursorSupplier().CreateNewShellCursor());
+
+ pPam->GetPoint()->nNode = nSttNd;
+ pPam->GetPoint()->nContent.Assign( 0, 0 );
+ SwNodeIndex aSaveIdx( pPam->GetPoint()->nNode, -1 );
+
+ pPam->SetMark(); // alle Indizies abmelden
+ pPam->DeleteMark();
+
+ SwTableNode* pTblNd = pPam->GetNode()->GetTableNode();
+ OSL_ENSURE( pTblNd, "keinen TableNode gefunden" );
+
+ if( pTblNd->GetTable().IsA( TYPE( SwDDETable )) )
+ pDDEFldType = (SwDDEFieldType*)((SwDDETable&)pTblNd->GetTable()).
+ GetDDEFldType()->Copy();
+
+ rDoc.TableToText( pTblNd, cTrenner );
+
+ aSaveIdx++;
+ SwCntntNode* pCNd = aSaveIdx.GetNode().GetCntntNode();
+ if( !pCNd && 0 == ( pCNd = rDoc.GetNodes().GoNext( &aSaveIdx ) ) &&
+ 0 == ( pCNd = rDoc.GetNodes().GoPrevious( &aSaveIdx )) )
+ {
+ OSL_FAIL( "wo steht denn nun der TextNode" );
+ }
+
+ pPam->GetPoint()->nNode = aSaveIdx;
+ pPam->GetPoint()->nContent.Assign( pCNd, 0 );
+
+ pPam->SetMark(); // alle Indizies abmelden
+ pPam->DeleteMark();
+}
+
+
+void SwUndoTblToTxt::RepeatImpl(::sw::RepeatContext & rContext)
+{
+ SwPaM *const pPam = & rContext.GetRepeatPaM();
+ SwTableNode *const pTblNd = pPam->GetNode()->FindTableNode();
+ if( pTblNd )
+ {
+ // move cursor out of table
+ pPam->GetPoint()->nNode = *pTblNd->EndOfSectionNode();
+ pPam->Move( fnMoveForward, fnGoCntnt );
+ pPam->SetMark();
+ pPam->DeleteMark();
+
+ rContext.GetDoc().TableToText( pTblNd, cTrenner );
+ }
+}
+
+void SwUndoTblToTxt::SetRange( const SwNodeRange& rRg )
+{
+ nSttNd = rRg.aStart.GetIndex();
+ nEndNd = rRg.aEnd.GetIndex();
+}
+
+void SwUndoTblToTxt::AddBoxPos( SwDoc& rDoc, sal_uLong nNdIdx, sal_uLong nEndIdx, xub_StrLen nCntntIdx )
+{
+ SwTblToTxtSave* pNew = new SwTblToTxtSave( rDoc, nNdIdx, nEndIdx, nCntntIdx );
+ pBoxSaves->Insert( pNew, pBoxSaves->Count() );
+}
+
+// -----------------------------------------------------
+
+SwUndoTxtToTbl::SwUndoTxtToTbl( const SwPaM& rRg,
+ const SwInsertTableOptions& rInsTblOpts,
+ sal_Unicode cCh, sal_uInt16 nAdj,
+ const SwTableAutoFmt* pAFmt )
+ : SwUndo( UNDO_TEXTTOTABLE ), SwUndRng( rRg ), aInsTblOpts( rInsTblOpts ),
+ pDelBoxes( 0 ), pAutoFmt( 0 ),
+ pHistory( 0 ), cTrenner( cCh ), nAdjust( nAdj )
+{
+ if( pAFmt )
+ pAutoFmt = new SwTableAutoFmt( *pAFmt );
+
+ const SwPosition* pEnd = rRg.End();
+ SwNodes& rNds = rRg.GetDoc()->GetNodes();
+ bSplitEnd = pEnd->nContent.GetIndex() && ( pEnd->nContent.GetIndex()
+ != pEnd->nNode.GetNode().GetCntntNode()->Len() ||
+ pEnd->nNode.GetIndex() >= rNds.GetEndOfContent().GetIndex()-1 );
+}
+
+SwUndoTxtToTbl::~SwUndoTxtToTbl()
+{
+ delete pDelBoxes;
+ delete pAutoFmt;
+}
+
+void SwUndoTxtToTbl::UndoImpl(::sw::UndoRedoContext & rContext)
+{
+ SwDoc & rDoc = rContext.GetDoc();
+
+ sal_uLong nTblNd = nSttNode;
+ if( nSttCntnt )
+ ++nTblNd; // Node wurde vorher gesplittet
+ SwNodeIndex aIdx( rDoc.GetNodes(), nTblNd );
+ SwTableNode *const pTNd = aIdx.GetNode().GetTableNode();
+ OSL_ENSURE( pTNd, "keinen Tabellen-Node gefunden" );
+
+ RemoveIdxFromSection( rDoc, nTblNd );
+
+ sTblNm = pTNd->GetTable().GetFrmFmt()->GetName();
+
+ if( pHistory )
+ {
+ pHistory->TmpRollback( &rDoc, 0 );
+ pHistory->SetTmpEnd( pHistory->Count() );
+ }
+
+ if( pDelBoxes )
+ {
+ SwTable& rTbl = pTNd->GetTable();
+ for( sal_uInt16 n = pDelBoxes->Count(); n; )
+ {
+ SwTableBox* pBox = rTbl.GetTblBox( (*pDelBoxes)[ --n ] );
+ if( pBox )
+ ::_DeleteBox( rTbl, pBox, 0, sal_False, sal_False );
+ else {
+ OSL_ENSURE( !this, "Wo ist die Box geblieben?" );
+ }
+ }
+ }
+
+ SwNodeIndex aEndIdx( *pTNd->EndOfSectionNode() );
+ rDoc.TableToText( pTNd, 0x0b == cTrenner ? 0x09 : cTrenner );
+
+ // join again at start?
+ SwPaM aPam(rDoc.GetNodes().GetEndOfContent());
+ SwPosition *const pPos = aPam.GetPoint();
+ if( nSttCntnt )
+ {
+ pPos->nNode = nTblNd;
+ pPos->nContent.Assign(pPos->nNode.GetNode().GetCntntNode(), 0);
+ if (aPam.Move(fnMoveBackward, fnGoCntnt))
+ {
+ SwNodeIndex & rIdx = aPam.GetPoint()->nNode;
+
+ // dann die Crsr/etc. nochmal relativ verschieben
+ RemoveIdxRel( rIdx.GetIndex()+1, *pPos );
+
+ rIdx.GetNode().GetCntntNode()->JoinNext();
+ }
+ }
+
+ // join again at end?
+ if( bSplitEnd )
+ {
+ SwNodeIndex& rIdx = pPos->nNode;
+ rIdx = nEndNode;
+ SwTxtNode* pTxtNd = rIdx.GetNode().GetTxtNode();
+ if( pTxtNd && pTxtNd->CanJoinNext() )
+ {
+ aPam.GetMark()->nContent.Assign( 0, 0 );
+ aPam.GetPoint()->nContent.Assign( 0, 0 );
+
+ // dann die Crsr/etc. nochmal relativ verschieben
+ pPos->nContent.Assign( pTxtNd, pTxtNd->GetTxt().Len() );
+ RemoveIdxRel( nEndNode + 1, *pPos );
+
+ pTxtNd->JoinNext();
+ }
+ }
+
+ AddUndoRedoPaM(rContext);
+}
+
+
+void SwUndoTxtToTbl::RedoImpl(::sw::UndoRedoContext & rContext)
+{
+ SwPaM & rPam( AddUndoRedoPaM(rContext) );
+ RemoveIdxFromRange(rPam, false);
+ SetPaM(rPam);
+
+ SwTable const*const pTable = rContext.GetDoc().TextToTable(
+ aInsTblOpts, rPam, cTrenner, nAdjust, pAutoFmt );
+ ((SwFrmFmt*)pTable->GetFrmFmt())->SetName( sTblNm );
+}
+
+
+void SwUndoTxtToTbl::RepeatImpl(::sw::RepeatContext & rContext)
+{
+ // no Table In Table
+ if (!rContext.GetRepeatPaM().GetNode()->FindTableNode())
+ {
+ rContext.GetDoc().TextToTable( aInsTblOpts, rContext.GetRepeatPaM(),
+ cTrenner, nAdjust,
+ pAutoFmt );
+ }
+}
+
+void SwUndoTxtToTbl::AddFillBox( const SwTableBox& rBox )
+{
+ if( !pDelBoxes )
+ pDelBoxes = new SvULongs;
+ pDelBoxes->Insert( rBox.GetSttIdx(), pDelBoxes->Count() );
+}
+
+SwHistory& SwUndoTxtToTbl::GetHistory()
+{
+ if( !pHistory )
+ pHistory = new SwHistory;
+ return *pHistory;
+}
+
+// -----------------------------------------------------
+
+SwUndoTblHeadline::SwUndoTblHeadline( const SwTable& rTbl, sal_uInt16 nOldHdl,
+ sal_uInt16 nNewHdl )
+ : SwUndo( UNDO_TABLEHEADLINE ),
+ nOldHeadline( nOldHdl ),
+ nNewHeadline( nNewHdl )
+{
+ OSL_ENSURE( rTbl.GetTabSortBoxes().Count(), "Tabelle ohne Inhalt" );
+ const SwStartNode *pSttNd = rTbl.GetTabSortBoxes()[ 0 ]->GetSttNd();
+ OSL_ENSURE( pSttNd, "Box ohne Inhalt" );
+
+ nTblNd = pSttNd->StartOfSectionIndex();
+}
+
+void SwUndoTblHeadline::UndoImpl(::sw::UndoRedoContext & rContext)
+{
+ SwDoc & rDoc = rContext.GetDoc();
+ SwTableNode* pTNd = rDoc.GetNodes()[ nTblNd ]->GetTableNode();
+ OSL_ENSURE( pTNd, "keinen Tabellen-Node gefunden" );
+
+ rDoc.SetRowsToRepeat( pTNd->GetTable(), nOldHeadline );
+}
+
+void SwUndoTblHeadline::RedoImpl(::sw::UndoRedoContext & rContext)
+{
+ SwDoc & rDoc = rContext.GetDoc();
+
+ SwTableNode* pTNd = rDoc.GetNodes()[ nTblNd ]->GetTableNode();
+ OSL_ENSURE( pTNd, "keinen Tabellen-Node gefunden" );
+
+ rDoc.SetRowsToRepeat( pTNd->GetTable(), nNewHeadline );
+}
+
+void SwUndoTblHeadline::RepeatImpl(::sw::RepeatContext & rContext)
+{
+ SwTableNode *const pTblNd =
+ rContext.GetRepeatPaM().GetNode()->FindTableNode();
+ if( pTblNd )
+ {
+ rContext.GetDoc().SetRowsToRepeat( pTblNd->GetTable(), nNewHeadline );
+ }
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+
+
+_SaveTable::_SaveTable( const SwTable& rTbl, sal_uInt16 nLnCnt, sal_Bool bSaveFml )
+ : aTblSet( *rTbl.GetFrmFmt()->GetAttrSet().GetPool(), aTableSetRange ),
+ pSwTable( &rTbl ), nLineCount( nLnCnt ), bSaveFormula( bSaveFml )
+{
+ bModifyBox = sal_False;
+ bNewModel = rTbl.IsNewModel();
+ aTblSet.Put( rTbl.GetFrmFmt()->GetAttrSet() );
+ pLine = new _SaveLine( 0, *rTbl.GetTabLines()[ 0 ], *this );
+
+ _SaveLine* pLn = pLine;
+ if( USHRT_MAX == nLnCnt )
+ nLnCnt = rTbl.GetTabLines().Count();
+ for( sal_uInt16 n = 1; n < nLnCnt; ++n )
+ pLn = new _SaveLine( pLn, *rTbl.GetTabLines()[ n ], *this );
+
+ aFrmFmts.Remove( 0, aFrmFmts.Count() );
+ pSwTable = 0;
+}
+
+
+_SaveTable::~_SaveTable()
+{
+ delete pLine;
+}
+
+
+sal_uInt16 _SaveTable::AddFmt( SwFrmFmt* pFmt, bool bIsLine )
+{
+ sal_uInt16 nRet = aFrmFmts.GetPos( pFmt );
+ if( USHRT_MAX == nRet )
+ {
+ // Kopie vom ItemSet anlegen
+ SfxItemSet* pSet = new SfxItemSet( *pFmt->GetAttrSet().GetPool(),
+ bIsLine ? aTableLineSetRange : aTableBoxSetRange );
+ pSet->Put( pFmt->GetAttrSet() );
+ //JP 20.04.98: Bug 49502 - wenn eine Formel gesetzt ist, nie den
+ // Value mit sichern. Der muss gegebenfalls neu
+ // errechnet werden!
+ //JP 30.07.98: Bug 54295 - Formeln immer im Klartext speichern
+ const SfxPoolItem* pItem;
+ if( SFX_ITEM_SET == pSet->GetItemState( RES_BOXATR_FORMULA, sal_True, &pItem ))
+ {
+ pSet->ClearItem( RES_BOXATR_VALUE );
+ if( pSwTable && bSaveFormula )
+ {
+ SwTableFmlUpdate aMsgHnt( pSwTable );
+ aMsgHnt.eFlags = TBL_BOXNAME;
+ ((SwTblBoxFormula*)pItem)->ChgDefinedIn( pFmt );
+ ((SwTblBoxFormula*)pItem)->ChangeState( &aMsgHnt );
+ ((SwTblBoxFormula*)pItem)->ChgDefinedIn( 0 );
+ }
+ }
+ aSets.Insert( pSet, (nRet = aSets.Count() ) );
+ aFrmFmts.Insert( pFmt, nRet );
+ }
+ return nRet;
+}
+
+
+void _SaveTable::RestoreAttr( SwTable& rTbl, sal_Bool bMdfyBox )
+{
+ sal_uInt16 n;
+
+ bModifyBox = bMdfyBox;
+
+ // zuerst die Attribute des TabellenFrmFormates zurueck holen
+ SwFrmFmt* pFmt = rTbl.GetFrmFmt();
+ SfxItemSet& rFmtSet = (SfxItemSet&)pFmt->GetAttrSet();
+ rFmtSet.ClearItem();
+ rFmtSet.Put( aTblSet );
+
+ if( pFmt->IsInCache() )
+ {
+ SwFrm::GetCache().Delete( pFmt );
+ pFmt->SetInCache( sal_False );
+ }
+
+ // zur Sicherheit alle Tableframes invalidieren
+ SwIterator<SwTabFrm,SwFmt> aIter( *pFmt );
+ for( SwTabFrm* pLast = aIter.First(); pLast; pLast = aIter.Next() )
+ if( pLast->GetTable() == &rTbl )
+ {
+ pLast->InvalidateAll();
+ pLast->SetCompletePaint();
+ }
+
+ // FrmFmts mit Defaults (0) fuellen
+ pFmt = 0;
+ for( n = aSets.Count(); n; --n )
+ aFrmFmts.Insert( pFmt, aFrmFmts.Count() );
+
+ sal_uInt16 nLnCnt = nLineCount;
+ if( USHRT_MAX == nLnCnt )
+ nLnCnt = rTbl.GetTabLines().Count();
+
+ _SaveLine* pLn = pLine;
+ for( n = 0; n < nLnCnt; ++n, pLn = pLn->pNext )
+ {
+ if( !pLn )
+ {
+ OSL_ENSURE( !this, "Anzahl der Lines hat sich veraendert" );
+ break;
+ }
+
+ pLn->RestoreAttr( *rTbl.GetTabLines()[ n ], *this );
+ }
+
+ aFrmFmts.Remove( 0, aFrmFmts.Count() );
+ bModifyBox = sal_False;
+}
+
+
+void _SaveTable::SaveCntntAttrs( SwDoc* pDoc )
+{
+ pLine->SaveCntntAttrs( pDoc );
+}
+
+
+void _SaveTable::CreateNew( SwTable& rTbl, sal_Bool bCreateFrms,
+ sal_Bool bRestoreChart )
+{
+ sal_uInt16 n;
+
+ _FndBox aTmpBox( 0, 0 );
+ //if( bRestoreChart )
+ // // ? TL_CHART2: notification or locking of controller required ?
+ aTmpBox.DelFrms( rTbl );
+
+ // zuerst die Attribute des TabellenFrmFormates zurueck holen
+ SwFrmFmt* pFmt = rTbl.GetFrmFmt();
+ SfxItemSet& rFmtSet = (SfxItemSet&)pFmt->GetAttrSet();
+ rFmtSet.ClearItem();
+ rFmtSet.Put( aTblSet );
+
+ if( pFmt->IsInCache() )
+ {
+ SwFrm::GetCache().Delete( pFmt );
+ pFmt->SetInCache( sal_False );
+ }
+
+ // SwTableBox muss ein Format haben!!
+ SwTableBox aParent( (SwTableBoxFmt*)pFmt, rTbl.GetTabLines().Count(), 0 );
+
+ // FrmFmts mit Defaults (0) fuellen
+ pFmt = 0;
+ for( n = aSets.Count(); n; --n )
+ aFrmFmts.Insert( pFmt, aFrmFmts.Count() );
+
+ pLine->CreateNew( rTbl, aParent, *this );
+ aFrmFmts.Remove( 0, aFrmFmts.Count() );
+
+ // die neuen Lines eintragen, die alten loeschen
+ sal_uInt16 nOldLines = nLineCount;
+ if( USHRT_MAX == nLineCount )
+ nOldLines = rTbl.GetTabLines().Count();
+
+ SwDoc *pDoc = rTbl.GetFrmFmt()->GetDoc();
+ SwChartDataProvider *pPCD = pDoc->GetChartDataProvider();
+ for( n = 0; n < aParent.GetTabLines().Count(); ++n )
+ {
+ SwTableLine* pLn = aParent.GetTabLines()[ n ];
+ pLn->SetUpper( 0 );
+ if( n < nOldLines )
+ {
+ SwTableLine* pOld = rTbl.GetTabLines()[ n ];
+
+ // TL_CHART2: notify chart about boxes to be removed
+ const SwTableBoxes &rBoxes = pOld->GetTabBoxes();
+ sal_uInt16 nBoxes = rBoxes.Count();
+ for (sal_uInt16 k = 0; k < nBoxes; ++k)
+ {
+ SwTableBox *pBox = rBoxes[k];
+ if (pPCD)
+ pPCD->DeleteBox( &rTbl, *pBox );
+ }
+
+ rTbl.GetTabLines().C40_REPLACE( SwTableLine, pLn, n );
+ delete pOld;
+ }
+ else
+ rTbl.GetTabLines().C40_INSERT( SwTableLine, pLn, n );
+ }
+
+ if( n < nOldLines )
+ {
+ // remove remaining lines...
+
+ for (sal_uInt16 k1 = 0; k1 < nOldLines - n; ++k1)
+ {
+ const SwTableBoxes &rBoxes = rTbl.GetTabLines()[n + k1]->GetTabBoxes();
+ sal_uInt16 nBoxes = rBoxes.Count();
+ for (sal_uInt16 k2 = 0; k2 < nBoxes; ++k2)
+ {
+ SwTableBox *pBox = rBoxes[k2];
+ // TL_CHART2: notify chart about boxes to be removed
+ if (pPCD)
+ pPCD->DeleteBox( &rTbl, *pBox );
+ }
+ }
+
+ rTbl.GetTabLines().DeleteAndDestroy( n, nOldLines - n );
+ }
+
+ aParent.GetTabLines().Remove( 0, n );
+
+ if( bCreateFrms )
+ aTmpBox.MakeFrms( rTbl );
+ if( bRestoreChart )
+ {
+ // TL_CHART2: need to inform chart of probably changed cell names
+ pDoc->UpdateCharts( rTbl.GetFrmFmt()->GetName() );
+ }
+}
+
+
+void _SaveTable::NewFrmFmt( const SwTableLine* pTblLn, const SwTableBox* pTblBx,
+ sal_uInt16 nFmtPos, SwFrmFmt* pOldFmt )
+{
+ SwDoc* pDoc = pOldFmt->GetDoc();
+
+ SwFrmFmt* pFmt = aFrmFmts[ nFmtPos ];
+ if( !pFmt )
+ {
+ if( pTblLn )
+ pFmt = pDoc->MakeTableLineFmt();
+ else
+ pFmt = pDoc->MakeTableBoxFmt();
+ pFmt->SetFmtAttr( *aSets[ nFmtPos ] );
+ aFrmFmts.Replace( pFmt, nFmtPos );
+ }
+
+ //Erstmal die Frms ummelden.
+ SwIterator<SwTabFrm,SwFmt> aIter( *pOldFmt );
+ for( SwFrm* pLast = aIter.First(); pLast; pLast = aIter.Next() )
+ {
+ if( pTblLn ? ((SwRowFrm*)pLast)->GetTabLine() == pTblLn
+ : ((SwCellFrm*)pLast)->GetTabBox() == pTblBx )
+ {
+ pLast->RegisterToFormat(*pFmt);
+ pLast->InvalidateAll();
+ pLast->ReinitializeFrmSizeAttrFlags();
+ if ( !pTblLn )
+ {
+ ((SwCellFrm*)pLast)->SetDerivedVert( sal_False );
+ ((SwCellFrm*)pLast)->CheckDirChange();
+ }
+ }
+ }
+
+ //Jetzt noch mich selbst ummelden.
+ if ( pTblLn )
+ const_cast<SwTableLine*>(pTblLn)->RegisterToFormat( *pFmt );
+ else if ( pTblBx )
+ const_cast<SwTableBox*>(pTblBx)->RegisterToFormat( *pFmt );
+
+ if( bModifyBox && !pTblLn )
+ {
+ const SfxPoolItem& rOld = pOldFmt->GetFmtAttr( RES_BOXATR_FORMAT ),
+ & rNew = pFmt->GetFmtAttr( RES_BOXATR_FORMAT );
+ if( rOld != rNew )
+ pFmt->ModifyNotification( (SfxPoolItem*)&rOld, (SfxPoolItem*)&rNew );
+ }
+
+ if( !pOldFmt->GetDepends() )
+ delete pOldFmt;
+
+}
+
+
+_SaveLine::_SaveLine( _SaveLine* pPrev, const SwTableLine& rLine, _SaveTable& rSTbl )
+ : pNext( 0 )
+{
+ if( pPrev )
+ pPrev->pNext = this;
+
+ nItemSet = rSTbl.AddFmt( rLine.GetFrmFmt(), true );
+
+ pBox = new _SaveBox( 0, *rLine.GetTabBoxes()[ 0 ], rSTbl );
+ _SaveBox* pBx = pBox;
+ for( sal_uInt16 n = 1; n < rLine.GetTabBoxes().Count(); ++n )
+ pBx = new _SaveBox( pBx, *rLine.GetTabBoxes()[ n ], rSTbl );
+}
+
+
+_SaveLine::~_SaveLine()
+{
+ delete pBox;
+ delete pNext;
+}
+
+
+void _SaveLine::RestoreAttr( SwTableLine& rLine, _SaveTable& rSTbl )
+{
+ rSTbl.NewFrmFmt( &rLine, 0, nItemSet, rLine.GetFrmFmt() );
+
+ _SaveBox* pBx = pBox;
+ for( sal_uInt16 n = 0; n < rLine.GetTabBoxes().Count(); ++n, pBx = pBx->pNext )
+ {
+ if( !pBx )
+ {
+ OSL_ENSURE( !this, "Anzahl der Boxen hat sich veraendert" );
+ break;
+ }
+ pBx->RestoreAttr( *rLine.GetTabBoxes()[ n ], rSTbl );
+ }
+}
+
+
+void _SaveLine::SaveCntntAttrs( SwDoc* pDoc )
+{
+ pBox->SaveCntntAttrs( pDoc );
+ if( pNext )
+ pNext->SaveCntntAttrs( pDoc );
+}
+
+
+void _SaveLine::CreateNew( SwTable& rTbl, SwTableBox& rParent, _SaveTable& rSTbl )
+{
+ SwTableLineFmt* pFmt = (SwTableLineFmt*)rSTbl.aFrmFmts[ nItemSet ];
+ if( !pFmt )
+ {
+ SwDoc* pDoc = rTbl.GetFrmFmt()->GetDoc();
+ pFmt = pDoc->MakeTableLineFmt();
+ pFmt->SetFmtAttr( *rSTbl.aSets[ nItemSet ] );
+ rSTbl.aFrmFmts.Replace( pFmt, nItemSet );
+ }
+ SwTableLine* pNew = new SwTableLine( pFmt, 1, &rParent );
+
+ rParent.GetTabLines().C40_INSERT( SwTableLine, pNew, rParent.GetTabLines().Count() );
+
+ // HB, #127868# robustness: in some cases - which I
+ // cannot reproduce nor see from the code - pNew seems
+ // to be set to NULL in C40_INSERT.
+ OSL_ENSURE(pNew, "Table line just created set to NULL in C40_INSERT");
+
+ if (pNew)
+ {
+ pBox->CreateNew( rTbl, *pNew, rSTbl );
+ }
+
+ if( pNext )
+ pNext->CreateNew( rTbl, rParent, rSTbl );
+}
+
+
+_SaveBox::_SaveBox( _SaveBox* pPrev, const SwTableBox& rBox, _SaveTable& rSTbl )
+ : pNext( 0 ), nSttNode( ULONG_MAX ), nRowSpan(0)
+{
+ Ptrs.pLine = 0;
+
+ if( pPrev )
+ pPrev->pNext = this;
+
+ nItemSet = rSTbl.AddFmt( rBox.GetFrmFmt(), false );
+
+ if( rBox.GetSttNd() )
+ {
+ nSttNode = rBox.GetSttIdx();
+ nRowSpan = rBox.getRowSpan();
+ }
+ else
+ {
+ Ptrs.pLine = new _SaveLine( 0, *rBox.GetTabLines()[ 0 ], rSTbl );
+
+ _SaveLine* pLn = Ptrs.pLine;
+ for( sal_uInt16 n = 1; n < rBox.GetTabLines().Count(); ++n )
+ pLn = new _SaveLine( pLn, *rBox.GetTabLines()[ n ], rSTbl );
+ }
+}
+
+
+_SaveBox::~_SaveBox()
+{
+ if( ULONG_MAX == nSttNode ) // keine EndBox
+ delete Ptrs.pLine;
+ else
+ delete Ptrs.pCntntAttrs;
+ delete pNext;
+}
+
+
+void _SaveBox::RestoreAttr( SwTableBox& rBox, _SaveTable& rSTbl )
+{
+ rSTbl.NewFrmFmt( 0, &rBox, nItemSet, rBox.GetFrmFmt() );
+
+ if( ULONG_MAX == nSttNode ) // keine EndBox
+ {
+ if( !rBox.GetTabLines().Count() )
+ {
+ OSL_ENSURE( !this, "Anzahl der Lines hat sich veraendert" );
+ }
+ else
+ {
+ _SaveLine* pLn = Ptrs.pLine;
+ for( sal_uInt16 n = 0; n < rBox.GetTabLines().Count(); ++n, pLn = pLn->pNext )
+ {
+ if( !pLn )
+ {
+ OSL_ENSURE( !this, "Anzahl der Lines hat sich veraendert" );
+ break;
+ }
+
+ pLn->RestoreAttr( *rBox.GetTabLines()[ n ], rSTbl );
+ }
+ }
+ }
+ else if( rBox.GetSttNd() && rBox.GetSttIdx() == nSttNode )
+ {
+ if( Ptrs.pCntntAttrs )
+ {
+ SwNodes& rNds = rBox.GetFrmFmt()->GetDoc()->GetNodes();
+ sal_uInt16 nSet = 0;
+ sal_uLong nEnd = rBox.GetSttNd()->EndOfSectionIndex();
+ for( sal_uLong n = nSttNode + 1; n < nEnd; ++n )
+ {
+ SwCntntNode* pCNd = rNds[ n ]->GetCntntNode();
+ if( pCNd )
+ {
+ SfxItemSet* pSet = (*Ptrs.pCntntAttrs)[ nSet++ ];
+ if( pSet )
+ {
+ sal_uInt16 *pRstAttr = aSave_BoxCntntSet;
+ while( *pRstAttr )
+ {
+ pCNd->ResetAttr( *pRstAttr, *(pRstAttr+1) );
+ pRstAttr += 2;
+ }
+ pCNd->SetAttr( *pSet );
+ }
+ else
+ pCNd->ResetAllAttr();
+ }
+ }
+ }
+ }
+ else
+ {
+ OSL_ENSURE( !this, "Box nicht mehr am gleichen Node" );
+ }
+}
+
+
+void _SaveBox::SaveCntntAttrs( SwDoc* pDoc )
+{
+ if( ULONG_MAX == nSttNode ) // keine EndBox
+ {
+ // weiter in der Line
+ Ptrs.pLine->SaveCntntAttrs( pDoc );
+ }
+ else
+ {
+ sal_uLong nEnd = pDoc->GetNodes()[ nSttNode ]->EndOfSectionIndex();
+ Ptrs.pCntntAttrs = new SfxItemSets( (sal_uInt8)(nEnd - nSttNode - 1 ), 5 );
+ for( sal_uLong n = nSttNode + 1; n < nEnd; ++n )
+ {
+ SwCntntNode* pCNd = pDoc->GetNodes()[ n ]->GetCntntNode();
+ if( pCNd )
+ {
+ SfxItemSet* pSet = 0;
+ if( pCNd->HasSwAttrSet() )
+ {
+ pSet = new SfxItemSet( pDoc->GetAttrPool(),
+ aSave_BoxCntntSet );
+ pSet->Put( *pCNd->GetpSwAttrSet() );
+ }
+
+ Ptrs.pCntntAttrs->Insert( pSet, Ptrs.pCntntAttrs->Count() );
+ }
+ }
+ }
+ if( pNext )
+ pNext->SaveCntntAttrs( pDoc );
+}
+
+
+void _SaveBox::CreateNew( SwTable& rTbl, SwTableLine& rParent, _SaveTable& rSTbl )
+{
+ SwTableBoxFmt* pFmt = (SwTableBoxFmt*)rSTbl.aFrmFmts[ nItemSet ];
+ if( !pFmt )
+ {
+ SwDoc* pDoc = rTbl.GetFrmFmt()->GetDoc();
+ pFmt = pDoc->MakeTableBoxFmt();
+ pFmt->SetFmtAttr( *rSTbl.aSets[ nItemSet ] );
+ rSTbl.aFrmFmts.Replace( pFmt, nItemSet );
+ }
+
+ if( ULONG_MAX == nSttNode ) // keine EndBox
+ {
+ SwTableBox* pNew = new SwTableBox( pFmt, 1, &rParent );
+ rParent.GetTabBoxes().C40_INSERT( SwTableBox, pNew, rParent.GetTabBoxes().Count() );
+
+ Ptrs.pLine->CreateNew( rTbl, *pNew, rSTbl );
+ }
+ else
+ {
+ // Box zum StartNode in der alten Tabelle suchen
+ SwTableBox* pBox = rTbl.GetTblBox( nSttNode );
+ OSL_ENSURE( pBox, "Wo ist meine TabellenBox geblieben?" );
+
+ SwFrmFmt* pOld = pBox->GetFrmFmt();
+ pBox->RegisterToFormat( *pFmt );
+ if( !pOld->GetDepends() )
+ delete pOld;
+
+ pBox->setRowSpan( nRowSpan );
+
+ SwTableBoxes* pTBoxes = &pBox->GetUpper()->GetTabBoxes();
+ pTBoxes->Remove( pTBoxes->C40_GETPOS( SwTableBox, pBox ) );
+
+ pBox->SetUpper( &rParent );
+ pTBoxes = &rParent.GetTabBoxes();
+ pTBoxes->C40_INSERT( SwTableBox, pBox, pTBoxes->Count() );
+ }
+
+ if( pNext )
+ pNext->CreateNew( rTbl, rParent, rSTbl );
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+
+// UndoObject fuer Attribut Aenderung an der Tabelle
+
+
+SwUndoAttrTbl::SwUndoAttrTbl( const SwTableNode& rTblNd, sal_Bool bClearTabCols )
+ : SwUndo( UNDO_TABLE_ATTR ),
+ nSttNode( rTblNd.GetIndex() )
+{
+ bClearTabCol = bClearTabCols;
+ pSaveTbl = new _SaveTable( rTblNd.GetTable() );
+}
+
+SwUndoAttrTbl::~SwUndoAttrTbl()
+{
+ delete pSaveTbl;
+}
+
+void SwUndoAttrTbl::UndoImpl(::sw::UndoRedoContext & rContext)
+{
+ SwDoc & rDoc = rContext.GetDoc();
+ SwTableNode* pTblNd = rDoc.GetNodes()[ nSttNode ]->GetTableNode();
+ OSL_ENSURE( pTblNd, "kein TabellenNode" );
+
+ if (pTblNd)
+ {
+ _SaveTable* pOrig = new _SaveTable( pTblNd->GetTable() );
+ pSaveTbl->RestoreAttr( pTblNd->GetTable() );
+ delete pSaveTbl;
+ pSaveTbl = pOrig;
+ }
+
+ if( bClearTabCol )
+ ClearFEShellTabCols();
+}
+
+void SwUndoAttrTbl::RedoImpl(::sw::UndoRedoContext & rContext)
+{
+ UndoImpl(rContext);
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+
+// UndoObject fuer AutoFormat an der Tabelle
+
+
+SwUndoTblAutoFmt::SwUndoTblAutoFmt( const SwTableNode& rTblNd,
+ const SwTableAutoFmt& rAFmt )
+ : SwUndo( UNDO_TABLE_AUTOFMT ),
+ nSttNode( rTblNd.GetIndex() ),
+ bSaveCntntAttr( sal_False )
+{
+ pSaveTbl = new _SaveTable( rTblNd.GetTable() );
+
+ if( rAFmt.IsFont() || rAFmt.IsJustify() )
+ {
+ // dann auch noch ueber die ContentNodes der EndBoxen und
+ // und alle Absatz-Attribute zusammen sammeln
+ pSaveTbl->SaveCntntAttrs( (SwDoc*)rTblNd.GetDoc() );
+ bSaveCntntAttr = sal_True;
+ }
+}
+
+SwUndoTblAutoFmt::~SwUndoTblAutoFmt()
+{
+ delete pSaveTbl;
+}
+
+void SwUndoTblAutoFmt::SaveBoxCntnt( const SwTableBox& rBox )
+{
+ ::boost::shared_ptr<SwUndoTblNumFmt> const p(new SwUndoTblNumFmt(rBox));
+ m_Undos.push_back(p);
+}
+
+
+void
+SwUndoTblAutoFmt::UndoRedo(bool const bUndo, ::sw::UndoRedoContext & rContext)
+{
+ SwDoc & rDoc = rContext.GetDoc();
+ SwTableNode* pTblNd = rDoc.GetNodes()[ nSttNode ]->GetTableNode();
+ OSL_ENSURE( pTblNd, "kein TabellenNode" );
+
+ _SaveTable* pOrig = new _SaveTable( pTblNd->GetTable() );
+ // dann auch noch ueber die ContentNodes der EndBoxen und
+ // und alle Absatz-Attribute zusammen sammeln
+ if( bSaveCntntAttr )
+ pOrig->SaveCntntAttrs( &rDoc );
+
+ if (bUndo)
+ {
+ for (size_t n = m_Undos.size(); 0 < n; --n)
+ {
+ m_Undos.at(n-1)->UndoImpl(rContext);
+ }
+ }
+
+ pSaveTbl->RestoreAttr( pTblNd->GetTable(), !bUndo );
+ delete pSaveTbl;
+ pSaveTbl = pOrig;
+}
+
+void SwUndoTblAutoFmt::UndoImpl(::sw::UndoRedoContext & rContext)
+{
+ UndoRedo(true, rContext);
+}
+
+void SwUndoTblAutoFmt::RedoImpl(::sw::UndoRedoContext & rContext)
+{
+ UndoRedo(false, rContext);
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+
+SwUndoTblNdsChg::SwUndoTblNdsChg( SwUndoId nAction,
+ const SwSelBoxes& rBoxes,
+ const SwTableNode& rTblNd,
+ long nMn, long nMx,
+ sal_uInt16 nCnt, sal_Bool bFlg, sal_Bool bSmHght )
+ : SwUndo( nAction ),
+ aBoxes( rBoxes.Count() < 255 ? (sal_uInt8)rBoxes.Count() : 255, 10 ),
+ nMin( nMn ), nMax( nMx ),
+ nSttNode( rTblNd.GetIndex() ), nCurrBox( 0 ),
+ nCount( nCnt ), nRelDiff( 0 ), nAbsDiff( 0 ),
+ nSetColType( USHRT_MAX ),
+ bFlag( bFlg ),
+ bSameHeight( bSmHght )
+{
+ Ptrs.pNewSttNds = 0;
+
+ const SwTable& rTbl = rTblNd.GetTable();
+ pSaveTbl = new _SaveTable( rTbl );
+
+ // und die Selektion merken
+ for( sal_uInt16 n = 0; n < rBoxes.Count(); ++n )
+ aBoxes.Insert( rBoxes[n]->GetSttIdx(), n );
+}
+
+
+SwUndoTblNdsChg::SwUndoTblNdsChg( SwUndoId nAction,
+ const SwSelBoxes& rBoxes,
+ const SwTableNode& rTblNd )
+ : SwUndo( nAction ),
+ aBoxes( rBoxes.Count() < 255 ? (sal_uInt8)rBoxes.Count() : 255, 10 ),
+ nMin( 0 ), nMax( 0 ),
+ nSttNode( rTblNd.GetIndex() ), nCurrBox( 0 ),
+ nCount( 0 ), nRelDiff( 0 ), nAbsDiff( 0 ),
+ nSetColType( USHRT_MAX ),
+ bFlag( sal_False ),
+ bSameHeight( sal_False )
+{
+ Ptrs.pNewSttNds = 0;
+
+ const SwTable& rTbl = rTblNd.GetTable();
+ pSaveTbl = new _SaveTable( rTbl );
+
+ // und die Selektion merken
+ for( sal_uInt16 n = 0; n < rBoxes.Count(); ++n )
+ aBoxes.Insert( rBoxes[n]->GetSttIdx(), n );
+}
+
+void SwUndoTblNdsChg::ReNewBoxes( const SwSelBoxes& rBoxes )
+{
+ if( rBoxes.Count() != aBoxes.Count() )
+ {
+ aBoxes.Remove( 0, aBoxes.Count() );
+ for( sal_uInt16 n = 0; n < rBoxes.Count(); ++n )
+ aBoxes.Insert( rBoxes[n]->GetSttIdx(), n );
+ }
+}
+
+SwUndoTblNdsChg::~SwUndoTblNdsChg()
+{
+ delete pSaveTbl;
+
+ if( IsDelBox() )
+ delete Ptrs.pDelSects;
+ else
+ delete Ptrs.pNewSttNds;
+}
+
+void SwUndoTblNdsChg::SaveNewBoxes( const SwTableNode& rTblNd,
+ const SwTableSortBoxes& rOld )
+{
+ const SwTable& rTbl = rTblNd.GetTable();
+ const SwTableSortBoxes& rTblBoxes = rTbl.GetTabSortBoxes();
+ sal_uInt16 n;
+ sal_uInt16 i;
+
+ OSL_ENSURE( ! IsDelBox(), "falsche Action" );
+ Ptrs.pNewSttNds = new SvULongs( (sal_uInt8)(rTblBoxes.Count() - rOld.Count()), 5 );
+
+ for( n = 0, i = 0; n < rOld.Count(); ++i )
+ {
+ if( rOld[ n ] == rTblBoxes[ i ] )
+ ++n;
+ else
+ // neue Box: sortiert einfuegen!!
+ InsertSort( *Ptrs.pNewSttNds, rTblBoxes[ i ]->GetSttIdx() );
+ }
+
+ for( ; i < rTblBoxes.Count(); ++i )
+ // neue Box: sortiert einfuegen!!
+ InsertSort( *Ptrs.pNewSttNds, rTblBoxes[ i ]->GetSttIdx() );
+}
+
+
+SwTableLine* lcl_FindTableLine( const SwTable& rTable,
+ const SwTableBox& rBox )
+{
+ SwTableLine* pRet = NULL;
+ // i63949: For nested cells we have to take nLineNo - 1, too, not 0!
+ const SwTableLines &rTableLines = ( rBox.GetUpper()->GetUpper() != NULL ) ?
+ rBox.GetUpper()->GetUpper()->GetTabLines()
+ : rTable.GetTabLines();
+ const SwTableLine* pLine = rBox.GetUpper();
+ sal_uInt16 nLineNo = rTableLines.C40_GETPOS( SwTableLine, pLine );
+ pRet = rTableLines[nLineNo - 1];
+
+ return pRet;
+}
+
+const SwTableLines& lcl_FindParentLines( const SwTable& rTable,
+ const SwTableBox& rBox )
+{
+ const SwTableLines& rRet =
+ ( rBox.GetUpper()->GetUpper() != NULL ) ?
+ rBox.GetUpper()->GetUpper()->GetTabLines() :
+ rTable.GetTabLines();
+
+ return rRet;
+}
+
+
+void SwUndoTblNdsChg::SaveNewBoxes( const SwTableNode& rTblNd,
+ const SwTableSortBoxes& rOld,
+ const SwSelBoxes& rBoxes,
+ const SvULongs& rNodeCnts )
+{
+ const SwTable& rTbl = rTblNd.GetTable();
+ const SwTableSortBoxes& rTblBoxes = rTbl.GetTabSortBoxes();
+
+ OSL_ENSURE( ! IsDelBox(), "falsche Action" );
+ Ptrs.pNewSttNds = new SvULongs( (sal_uInt8)(rTblBoxes.Count() - rOld.Count()), 5 );
+
+ OSL_ENSURE( rTbl.IsNewModel() || rOld.Count() + nCount * rBoxes.Count() == rTblBoxes.Count(),
+ "unexpected boxes" );
+ OSL_ENSURE( rOld.Count() <= rTblBoxes.Count(), "more unexpected boxes" );
+ for( sal_uInt16 n = 0, i = 0; i < rTblBoxes.Count(); ++i )
+ {
+ if( ( n < rOld.Count() ) &&
+ ( rOld[ n ] == rTblBoxes[ i ] ) )
+ {
+ // box already known? Then nothing to be done.
+ ++n;
+ }
+ else
+ {
+ // new box found: insert (obey sort order)
+ sal_uInt16 nInsPos;
+ const SwTableBox* pBox = rTblBoxes[ i ];
+ InsertSort( *Ptrs.pNewSttNds, pBox->GetSttIdx(), &nInsPos );
+
+ // find the source box. It must be one in rBoxes.
+ // We found the right one if it's in the same column as pBox.
+ // No, if more than one selected cell in the same column has been splitted,
+ // we have to look for the nearest one (i65201)!
+ const SwTableBox* pSourceBox = NULL;
+ const SwTableBox* pCheckBox = NULL;
+ const SwTableLine* pBoxLine = pBox->GetUpper();
+ sal_uInt16 nLineDiff = lcl_FindParentLines(rTbl,*pBox).C40_GETPOS(SwTableLine,pBoxLine);
+ sal_uInt16 nLineNo = 0;
+ for( sal_uInt16 j = 0; j < rBoxes.Count(); ++j )
+ {
+ pCheckBox = rBoxes[j];
+ if( pCheckBox->GetUpper()->GetUpper() == pBox->GetUpper()->GetUpper() )
+ {
+ const SwTableLine* pCheckLine = pCheckBox->GetUpper();
+ sal_uInt16 nCheckLine = lcl_FindParentLines( rTbl, *pCheckBox ).
+ C40_GETPOS( SwTableLine, pCheckLine );
+ if( ( !pSourceBox || nCheckLine > nLineNo ) && nCheckLine < nLineDiff )
+ {
+ nLineNo = nCheckLine;
+ pSourceBox = pCheckBox;
+ }
+ }
+ }
+
+ // find the line number difference
+ // (to help determine bNodesMoved flag below)
+ nLineDiff = nLineDiff - nLineNo;
+ OSL_ENSURE( pSourceBox, "Splitted source box not found!" );
+ // find out how many nodes the source box used to have
+ // (to help determine bNodesMoved flag below)
+ sal_uInt16 nNdsPos = 0;
+ while( rBoxes[ nNdsPos ] != pSourceBox )
+ ++nNdsPos;
+ sal_uLong nNodes = rNodeCnts[ nNdsPos ];
+
+ // When a new table cell is created, it either gets a new
+ // node, or it gets node(s) from elsewhere. The undo must
+ // know, of course, and thus we must determine here just
+ // where pBox's nodes are from:
+ // If 1) the source box has lost nodes, and
+ // 2) we're in the node range that got nodes
+ // then pBox received nodes from elsewhere.
+ // If bNodesMoved is set for pBox the undo must move the
+ // boxes back, otherwise it must delete them.
+ // The bNodesMoved flag is stored in a seperate array
+ // which mirrors Ptrs.pNewSttNds, i.e. Ptrs.pNewSttNds[i]
+ // and aMvBoxes[i] belong together.
+ sal_Bool bNodesMoved =
+ ( nNodes != ( pSourceBox->GetSttNd()->EndOfSectionIndex() -
+ pSourceBox->GetSttIdx() ) )
+ && ( nNodes - 1 > nLineDiff );
+ aMvBoxes.insert( aMvBoxes.begin() + nInsPos, bNodesMoved );
+ }
+ }
+}
+
+
+void SwUndoTblNdsChg::SaveSection( SwStartNode* pSttNd )
+{
+ OSL_ENSURE( IsDelBox(), "falsche Action" );
+ if( !Ptrs.pDelSects )
+ Ptrs.pDelSects = new SwUndoSaveSections( 10, 5 );
+
+ SwTableNode* pTblNd = pSttNd->FindTableNode();
+ SwUndoSaveSection* pSave = new SwUndoSaveSection;
+ pSave->SaveSection( pSttNd->GetDoc(), SwNodeIndex( *pSttNd ));
+
+ Ptrs.pDelSects->Insert( pSave, Ptrs.pDelSects->Count() );
+ nSttNode = pTblNd->GetIndex();
+}
+
+
+void SwUndoTblNdsChg::UndoImpl(::sw::UndoRedoContext & rContext)
+{
+ SwDoc & rDoc = rContext.GetDoc();
+ SwNodeIndex aIdx( rDoc.GetNodes(), nSttNode );
+
+ SwTableNode *const pTblNd = aIdx.GetNode().GetTableNode();
+ OSL_ENSURE( pTblNd, "kein TabellenNode" );
+
+ SwTableFmlUpdate aMsgHnt( &pTblNd->GetTable() );
+ aMsgHnt.eFlags = TBL_BOXPTR;
+ rDoc.UpdateTblFlds( &aMsgHnt );
+
+ CHECK_TABLE( pTblNd->GetTable() )
+
+ _FndBox aTmpBox( 0, 0 );
+ // ? TL_CHART2: notification or locking of controller required ?
+
+ SwChartDataProvider *pPCD = rDoc.GetChartDataProvider();
+ std::vector< SwTableBox* > aDelBoxes;
+ if( IsDelBox() )
+ {
+ // Trick: die fehlenden Boxen in irgendeine Line einfuegen, beim
+ // CreateNew werden sie korrekt verbunden.
+ SwTableBox* pCpyBox = pTblNd->GetTable().GetTabSortBoxes()[0];
+ SwTableBoxes& rLnBoxes = pCpyBox->GetUpper()->GetTabBoxes();
+
+ // die Sections wieder herstellen
+ for( sal_uInt16 n = Ptrs.pDelSects->Count(); n; )
+ {
+ SwUndoSaveSection* pSave = (*Ptrs.pDelSects)[ --n ];
+ pSave->RestoreSection( &rDoc, &aIdx, SwTableBoxStartNode );
+ if( pSave->GetHistory() )
+ pSave->GetHistory()->Rollback( &rDoc );
+ SwTableBox* pBox = new SwTableBox( (SwTableBoxFmt*)pCpyBox->GetFrmFmt(), aIdx,
+ pCpyBox->GetUpper() );
+ rLnBoxes.C40_INSERT( SwTableBox, pBox, rLnBoxes.Count() );
+ }
+ Ptrs.pDelSects->DeleteAndDestroy( 0, Ptrs.pDelSects->Count() );
+ }
+ else if( !aMvBoxes.empty() )
+ {
+ // dann muessen Nodes verschoben und nicht geloescht werden!
+ // Dafuer brauchen wir aber ein temp Array
+ SvULongs aTmp( 0, 5);
+ aTmp.Insert( Ptrs.pNewSttNds, 0 );
+
+ // von hinten anfangen
+ for( sal_uInt16 n = aTmp.Count(); n; )
+ {
+ // Box aus der Tabellen-Struktur entfernen
+ sal_uLong nIdx = aTmp[ --n ];
+ SwTableBox* pBox = pTblNd->GetTable().GetTblBox( nIdx );
+ OSL_ENSURE( pBox, "Wo ist meine TabellenBox geblieben?" );
+
+ // TL_CHART2: notify chart about box to be removed
+ if (pPCD)
+ pPCD->DeleteBox( &pTblNd->GetTable(), *pBox );
+
+ if( aMvBoxes[ n ] )
+ {
+ SwNodeRange aRg( *pBox->GetSttNd(), 1,
+ *pBox->GetSttNd()->EndOfSectionNode() );
+
+ SwTableLine* pLine = lcl_FindTableLine( pTblNd->GetTable(), *pBox );
+ SwNodeIndex aInsPos( *(pLine->GetTabBoxes()[0]->GetSttNd()), 2 );
+
+ // alle StartNode Indizies anpassen
+ sal_uInt16 i = n;
+ sal_uLong nSttIdx = aInsPos.GetIndex() - 2,
+ nNdCnt = aRg.aEnd.GetIndex() - aRg.aStart.GetIndex();
+ while( i && aTmp[ --i ] > nSttIdx )
+ aTmp[ i ] += nNdCnt;
+
+ // erst die Box loeschen
+ delete pBox;
+ // dann die Nodes verschieben,
+ rDoc.GetNodes()._MoveNodes( aRg, rDoc.GetNodes(), aInsPos, sal_False );
+ }
+ else
+ rDoc.DeleteSection( rDoc.GetNodes()[ nIdx ] );
+ aDelBoxes.insert( aDelBoxes.end(), pBox );
+ }
+ }
+ else
+ {
+ // Remove nodes from nodes array (backwards!)
+ for( sal_uInt16 n = Ptrs.pNewSttNds->Count(); n; )
+ {
+ sal_uLong nIdx = (*Ptrs.pNewSttNds)[ --n ];
+ SwTableBox* pBox = pTblNd->GetTable().GetTblBox( nIdx );
+ OSL_ENSURE( pBox, "Where's my table box?" );
+ // TL_CHART2: notify chart about box to be removed
+ if (pPCD)
+ pPCD->DeleteBox( &pTblNd->GetTable(), *pBox );
+ aDelBoxes.insert( aDelBoxes.end(), pBox );
+ rDoc.DeleteSection( rDoc.GetNodes()[ nIdx ] );
+ }
+ }
+ // Remove boxes from table structure
+ for( sal_uInt16 n = 0; n < aDelBoxes.size(); ++n )
+ {
+ SwTableBox* pCurrBox = aDelBoxes[n];
+ SwTableBoxes* pTBoxes = &pCurrBox->GetUpper()->GetTabBoxes();
+ pTBoxes->Remove( pTBoxes->C40_GETPOS( SwTableBox, pCurrBox ) );
+ delete pCurrBox;
+ }
+
+ pSaveTbl->CreateNew( pTblNd->GetTable(), sal_True, sal_False );
+
+ // TL_CHART2: need to inform chart of probably changed cell names
+ rDoc.UpdateCharts( pTblNd->GetTable().GetFrmFmt()->GetName() );
+
+ if( IsDelBox() )
+ nSttNode = pTblNd->GetIndex();
+ ClearFEShellTabCols();
+ CHECK_TABLE( pTblNd->GetTable() )
+}
+
+
+void SwUndoTblNdsChg::RedoImpl(::sw::UndoRedoContext & rContext)
+{
+ SwDoc & rDoc = rContext.GetDoc();
+
+ SwTableNode* pTblNd = rDoc.GetNodes()[ nSttNode ]->GetTableNode();
+ OSL_ENSURE( pTblNd, "kein TabellenNode" );
+ CHECK_TABLE( pTblNd->GetTable() )
+
+ SwSelBoxes aSelBoxes;
+ for( sal_uInt16 n = 0; n < aBoxes.Count(); ++n )
+ {
+ SwTableBox* pBox = pTblNd->GetTable().GetTblBox( aBoxes[ n ] );
+ aSelBoxes.Insert( pBox );
+ }
+
+ // SelBoxes erzeugen und InsertCell/-Row/SplitTbl aufrufen
+ switch( GetId() )
+ {
+ case UNDO_TABLE_INSCOL:
+ if( USHRT_MAX == nSetColType )
+ rDoc.InsertCol( aSelBoxes, nCount, bFlag );
+ else
+ {
+ SwTableBox* pBox = pTblNd->GetTable().GetTblBox( nCurrBox );
+ rDoc.SetColRowWidthHeight( *pBox, nSetColType, nAbsDiff,
+ nRelDiff );
+ }
+ break;
+
+ case UNDO_TABLE_INSROW:
+ if( USHRT_MAX == nSetColType )
+ rDoc.InsertRow( aSelBoxes, nCount, bFlag );
+ else
+ {
+ SwTable& rTbl = pTblNd->GetTable();
+ SwTableBox* pBox = rTbl.GetTblBox( nCurrBox );
+ TblChgMode eOldMode = rTbl.GetTblChgMode();
+ rTbl.SetTblChgMode( (TblChgMode)nCount );
+ rDoc.SetColRowWidthHeight( *pBox, nSetColType, nAbsDiff, nRelDiff );
+ rTbl.SetTblChgMode( eOldMode );
+ }
+ break;
+
+ case UNDO_TABLE_SPLIT:
+ rDoc.SplitTbl( aSelBoxes, bFlag, nCount, bSameHeight );
+ break;
+ case UNDO_TABLE_DELBOX:
+ case UNDO_ROW_DELETE:
+ case UNDO_COL_DELETE:
+ if( USHRT_MAX == nSetColType )
+ {
+ SwTableFmlUpdate aMsgHnt( &pTblNd->GetTable() );
+ aMsgHnt.eFlags = TBL_BOXPTR;
+ rDoc.UpdateTblFlds( &aMsgHnt );
+ SwTable &rTable = pTblNd->GetTable();
+ if( nMax > nMin && rTable.IsNewModel() )
+ rTable.PrepareDeleteCol( nMin, nMax );
+ rTable.DeleteSel( &rDoc, aSelBoxes, 0, this, sal_True, sal_True );
+ }
+ else
+ {
+ SwTable& rTbl = pTblNd->GetTable();
+
+ SwTableFmlUpdate aMsgHnt( &rTbl );
+ aMsgHnt.eFlags = TBL_BOXPTR;
+ rDoc.UpdateTblFlds( &aMsgHnt );
+
+ SwTableBox* pBox = rTbl.GetTblBox( nCurrBox );
+ TblChgMode eOldMode = rTbl.GetTblChgMode();
+ rTbl.SetTblChgMode( (TblChgMode)nCount );
+
+ // need the SaveSections!
+ rDoc.GetIDocumentUndoRedo().DoUndo( true );
+ SwUndoTblNdsChg* pUndo = 0;
+
+ switch( nSetColType & 0xff )
+ {
+ case nsTblChgWidthHeightType::WH_COL_LEFT:
+ case nsTblChgWidthHeightType::WH_COL_RIGHT:
+ case nsTblChgWidthHeightType::WH_CELL_LEFT:
+ case nsTblChgWidthHeightType::WH_CELL_RIGHT:
+ rTbl.SetColWidth( *pBox, nSetColType, nAbsDiff,
+ nRelDiff, (SwUndo**)&pUndo );
+ break;
+ case nsTblChgWidthHeightType::WH_ROW_TOP:
+ case nsTblChgWidthHeightType::WH_ROW_BOTTOM:
+ case nsTblChgWidthHeightType::WH_CELL_TOP:
+ case nsTblChgWidthHeightType::WH_CELL_BOTTOM:
+ rTbl.SetRowHeight( *pBox, nSetColType, nAbsDiff,
+ nRelDiff, (SwUndo**)&pUndo );
+ break;
+ }
+
+ if( pUndo )
+ {
+ Ptrs.pDelSects->Insert( pUndo->Ptrs.pDelSects, 0 );
+ pUndo->Ptrs.pDelSects->Remove( 0, pUndo->Ptrs.pDelSects->Count() );
+
+ delete pUndo;
+ }
+ rDoc.GetIDocumentUndoRedo().DoUndo( false );
+
+ rTbl.SetTblChgMode( eOldMode );
+ }
+ nSttNode = pTblNd->GetIndex();
+ break;
+ default:
+ ;
+ }
+ ClearFEShellTabCols();
+ CHECK_TABLE( pTblNd->GetTable() )
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+
+SwUndoTblMerge::SwUndoTblMerge( const SwPaM& rTblSel )
+ : SwUndo( UNDO_TABLE_MERGE ), SwUndRng( rTblSel ), pHistory( 0 )
+{
+ const SwTableNode* pTblNd = rTblSel.GetNode()->FindTableNode();
+ OSL_ENSURE( pTblNd, "Wo ist TabllenNode" );
+ pSaveTbl = new _SaveTable( pTblNd->GetTable() );
+ pMoves = new SwUndoMoves;
+ nTblNode = pTblNd->GetIndex();
+}
+
+SwUndoTblMerge::~SwUndoTblMerge()
+{
+ delete pSaveTbl;
+ delete pMoves;
+ delete pHistory;
+}
+
+void SwUndoTblMerge::UndoImpl(::sw::UndoRedoContext & rContext)
+{
+ SwDoc & rDoc = rContext.GetDoc();
+ SwNodeIndex aIdx( rDoc.GetNodes(), nTblNode );
+
+ SwTableNode *const pTblNd = aIdx.GetNode().GetTableNode();
+ OSL_ENSURE( pTblNd, "kein TabellenNode" );
+
+ SwTableFmlUpdate aMsgHnt( &pTblNd->GetTable() );
+ aMsgHnt.eFlags = TBL_BOXPTR;
+ rDoc.UpdateTblFlds( &aMsgHnt );
+
+ _FndBox aTmpBox( 0, 0 );
+ // ? TL_CHART2: notification or locking of controller required ?
+
+
+ // 1. die geloeschten Boxen wiederherstellen:
+
+ // Trick: die fehlenden Boxen in irgendeine Line einfuegen, beim
+ // CreateNew werden sie korrekt verbunden.
+ SwTableBox *pBox, *pCpyBox = pTblNd->GetTable().GetTabSortBoxes()[0];
+ SwTableBoxes& rLnBoxes = pCpyBox->GetUpper()->GetTabBoxes();
+
+CHECKTABLE(pTblNd->GetTable())
+
+ SwSelBoxes aSelBoxes;
+ SwTxtFmtColl* pColl = rDoc.GetTxtCollFromPool( RES_POOLCOLL_STANDARD );
+ sal_uInt16 n;
+
+ for( n = 0; n < aBoxes.Count(); ++n )
+ {
+ aIdx = aBoxes[ n ];
+ SwStartNode* pSttNd = rDoc.GetNodes().MakeTextSection( aIdx,
+ SwTableBoxStartNode, pColl );
+ pBox = new SwTableBox( (SwTableBoxFmt*)pCpyBox->GetFrmFmt(), *pSttNd,
+ pCpyBox->GetUpper() );
+ rLnBoxes.C40_INSERT( SwTableBox, pBox, rLnBoxes.Count() );
+
+ aSelBoxes.Insert( pBox );
+ }
+
+CHECKTABLE(pTblNd->GetTable())
+
+ SwChartDataProvider *pPCD = rDoc.GetChartDataProvider();
+ // 2. die eingefuegten Boxen loeschen
+ // die Nodes loeschen (von Hinten!!)
+ for( n = aNewSttNds.Count(); n; )
+ {
+ // Box aus der Tabellen-Struktur entfernen
+ sal_uLong nIdx = aNewSttNds[ --n ];
+
+ if( !nIdx && n )
+ {
+ nIdx = aNewSttNds[ --n ];
+ pBox = pTblNd->GetTable().GetTblBox( nIdx );
+ OSL_ENSURE( pBox, "Wo ist meine TabellenBox geblieben?" );
+
+ if( !pSaveTbl->IsNewModel() )
+ rDoc.GetNodes().MakeTxtNode( SwNodeIndex(
+ *pBox->GetSttNd()->EndOfSectionNode() ), pColl );
+
+ // das war der Trenner, -> die verschobenen herstellen
+ for( sal_uInt16 i = pMoves->Count(); i; )
+ {
+ SwTxtNode* pTxtNd = 0;
+ sal_uInt16 nDelPos = 0;
+ SwUndoMove* pUndo = (*pMoves)[ --i ];
+ if( !pUndo->IsMoveRange() )
+ {
+ pTxtNd = rDoc.GetNodes()[ pUndo->GetDestSttNode() ]->GetTxtNode();
+ nDelPos = pUndo->GetDestSttCntnt() - 1;
+ }
+ pUndo->UndoImpl(rContext);
+ if( pUndo->IsMoveRange() )
+ {
+ // den ueberfluessigen Node loeschen
+ aIdx = pUndo->GetEndNode();
+ SwCntntNode *pCNd = aIdx.GetNode().GetCntntNode();
+ if( pCNd )
+ {
+ SwNodeIndex aTmp( aIdx, -1 );
+ SwCntntNode *pMove = aTmp.GetNode().GetCntntNode();
+ if( pMove )
+ pCNd->MoveTo( *pMove );
+ }
+ rDoc.GetNodes().Delete( aIdx, 1 );
+ }
+ else if( pTxtNd )
+ {
+ // evt. noch ueberflussige Attribute loeschen
+ SwIndex aTmpIdx( pTxtNd, nDelPos );
+ if( pTxtNd->GetpSwpHints() && pTxtNd->GetpSwpHints()->Count() )
+ pTxtNd->RstAttr( aTmpIdx, pTxtNd->GetTxt().Len() -
+ nDelPos + 1 );
+ // das Trennzeichen loeschen
+ pTxtNd->EraseText( aTmpIdx, 1 );
+ }
+ }
+ nIdx = pBox->GetSttIdx();
+ }
+ else
+ pBox = pTblNd->GetTable().GetTblBox( nIdx );
+
+ if( !pSaveTbl->IsNewModel() )
+ {
+ // TL_CHART2: notify chart about box to be removed
+ if (pPCD)
+ pPCD->DeleteBox( &pTblNd->GetTable(), *pBox );
+
+ SwTableBoxes* pTBoxes = &pBox->GetUpper()->GetTabBoxes();
+ pTBoxes->Remove( pTBoxes->C40_GETPOS( SwTableBox, pBox ) );
+
+
+ // Indizies aus dem Bereich loeschen
+ {
+ SwNodeIndex aTmpIdx( *pBox->GetSttNd() );
+ rDoc.CorrAbs( SwNodeIndex( aTmpIdx, 1 ),
+ SwNodeIndex( *aTmpIdx.GetNode().EndOfSectionNode() ),
+ SwPosition( aTmpIdx, SwIndex( 0, 0 )), sal_True );
+ }
+
+ delete pBox;
+ rDoc.DeleteSection( rDoc.GetNodes()[ nIdx ] );
+ }
+ }
+CHECKTABLE(pTblNd->GetTable())
+
+
+ pSaveTbl->CreateNew( pTblNd->GetTable(), sal_True, sal_False );
+
+ // TL_CHART2: need to inform chart of probably changed cell names
+ rDoc.UpdateCharts( pTblNd->GetTable().GetFrmFmt()->GetName() );
+
+ if( pHistory )
+ {
+ pHistory->TmpRollback( &rDoc, 0 );
+ pHistory->SetTmpEnd( pHistory->Count() );
+ }
+// nTblNode = pTblNd->GetIndex();
+
+ SwPaM *const pPam(& rContext.GetCursorSupplier().CreateNewShellCursor());
+ pPam->DeleteMark();
+ pPam->GetPoint()->nNode = nSttNode;
+ pPam->GetPoint()->nContent.Assign( pPam->GetCntntNode(), nSttCntnt );
+ pPam->SetMark();
+ pPam->DeleteMark();
+
+CHECKTABLE(pTblNd->GetTable())
+ ClearFEShellTabCols();
+}
+
+void SwUndoTblMerge::RedoImpl(::sw::UndoRedoContext & rContext)
+{
+ SwDoc & rDoc = rContext.GetDoc();
+ SwPaM & rPam( AddUndoRedoPaM(rContext) );
+ rDoc.MergeTbl(rPam);
+}
+
+void SwUndoTblMerge::MoveBoxCntnt( SwDoc* pDoc, SwNodeRange& rRg, SwNodeIndex& rPos )
+{
+ SwNodeIndex aTmp( rRg.aStart, -1 ), aTmp2( rPos, -1 );
+ SwUndoMove* pUndo = new SwUndoMove( pDoc, rRg, rPos );
+ ::sw::UndoGuard const undoGuard(pDoc->GetIDocumentUndoRedo());
+ pDoc->MoveNodeRange( rRg, rPos, (pSaveTbl->IsNewModel()) ?
+ IDocumentContentOperations::DOC_NO_DELFRMS :
+ IDocumentContentOperations::DOC_MOVEDEFAULT );
+ aTmp++;
+ aTmp2++;
+ pUndo->SetDestRange( aTmp2, rPos, aTmp );
+
+ pMoves->Insert( pUndo, pMoves->Count() );
+}
+
+void SwUndoTblMerge::SetSelBoxes( const SwSelBoxes& rBoxes )
+{
+ // die Selektion merken
+ for( sal_uInt16 n = 0; n < rBoxes.Count(); ++n )
+ InsertSort( aBoxes, rBoxes[n]->GetSttIdx() );
+
+ // als Trennung fuers einfuegen neuer Boxen nach dem Verschieben!
+ aNewSttNds.Insert( (sal_uLong)0, aNewSttNds.Count() );
+
+ // The new table model does not delete overlapped cells (by row span),
+ // so the rBoxes array might be empty even some cells have been merged.
+ if( rBoxes.Count() )
+ nTblNode = rBoxes[ 0 ]->GetSttNd()->FindTableNode()->GetIndex();
+}
+
+void SwUndoTblMerge::SaveCollection( const SwTableBox& rBox )
+{
+ if( !pHistory )
+ pHistory = new SwHistory;
+
+ SwNodeIndex aIdx( *rBox.GetSttNd(), 1 );
+ SwCntntNode* pCNd = aIdx.GetNode().GetCntntNode();
+ if( !pCNd )
+ pCNd = aIdx.GetNodes().GoNext( &aIdx );
+
+ pHistory->Add( pCNd->GetFmtColl(), aIdx.GetIndex(), pCNd->GetNodeType());
+ if( pCNd->HasSwAttrSet() )
+ pHistory->CopyFmtAttr( *pCNd->GetpSwAttrSet(), aIdx.GetIndex() );
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+
+SwUndoTblNumFmt::SwUndoTblNumFmt( const SwTableBox& rBox,
+ const SfxItemSet* pNewSet )
+ : SwUndo( UNDO_TBLNUMFMT ),
+ pBoxSet( 0 ), pHistory( 0 ), nFmtIdx( NUMBERFORMAT_TEXT )
+{
+ bNewFmt = bNewFml = bNewValue = sal_False;
+ nNode = rBox.GetSttIdx();
+
+ nNdPos = rBox.IsValidNumTxtNd( 0 == pNewSet );
+ SwDoc* pDoc = rBox.GetFrmFmt()->GetDoc();
+
+ if( ULONG_MAX != nNdPos )
+ {
+ SwTxtNode* pTNd = pDoc->GetNodes()[ nNdPos ]->GetTxtNode();
+
+ pHistory = new SwHistory;
+ SwRegHistory aRHst( *rBox.GetSttNd(), pHistory );
+ // always save all text atttibutes because of possibly overlapping
+ // areas of on/off
+ pHistory->CopyAttr( pTNd->GetpSwpHints(), nNdPos, 0,
+ pTNd->GetTxt().Len(), true );
+
+ if( pTNd->HasSwAttrSet() )
+ pHistory->CopyFmtAttr( *pTNd->GetpSwAttrSet(), nNdPos );
+
+ aStr = pTNd->GetTxt();
+ if( pTNd->GetpSwpHints() )
+ pTNd->GetpSwpHints()->DeRegister();
+ }
+
+ pBoxSet = new SfxItemSet( pDoc->GetAttrPool(), aTableBoxSetRange );
+ pBoxSet->Put( rBox.GetFrmFmt()->GetAttrSet() );
+
+ if( pNewSet )
+ {
+ const SfxPoolItem* pItem;
+ if( SFX_ITEM_SET == pNewSet->GetItemState( RES_BOXATR_FORMAT,
+ sal_False, &pItem ))
+ {
+ bNewFmt = sal_True;
+ nNewFmtIdx = ((SwTblBoxNumFormat*)pItem)->GetValue();
+ }
+ if( SFX_ITEM_SET == pNewSet->GetItemState( RES_BOXATR_FORMULA,
+ sal_False, &pItem ))
+ {
+ bNewFml = sal_True;
+ aNewFml = ((SwTblBoxFormula*)pItem)->GetFormula();
+ }
+ if( SFX_ITEM_SET == pNewSet->GetItemState( RES_BOXATR_VALUE,
+ sal_False, &pItem ))
+ {
+ bNewValue = sal_True;
+ fNewNum = ((SwTblBoxValue*)pItem)->GetValue();
+ }
+ }
+
+ // wird die History ueberhaupt benoetigt ??
+ if( pHistory && !pHistory->Count() )
+ DELETEZ( pHistory );
+}
+
+SwUndoTblNumFmt::~SwUndoTblNumFmt()
+{
+ delete pHistory;
+ delete pBoxSet;
+}
+
+void SwUndoTblNumFmt::UndoImpl(::sw::UndoRedoContext & rContext)
+{
+ OSL_ENSURE( pBoxSet, "Where's the stored item set?" );
+
+ SwDoc & rDoc = rContext.GetDoc();
+ SwStartNode* pSttNd = rDoc.GetNodes()[ nNode ]->
+ FindSttNodeByType( SwTableBoxStartNode );
+ OSL_ENSURE( pSttNd, "ohne StartNode kein TabellenBox" );
+ SwTableBox* pBox = pSttNd->FindTableNode()->GetTable().GetTblBox(
+ pSttNd->GetIndex() );
+ OSL_ENSURE( pBox, "keine TabellenBox gefunden" );
+
+ SwTableBoxFmt* pFmt = rDoc.MakeTableBoxFmt();
+ pFmt->SetFmtAttr( *pBoxSet );
+ pBox->ChgFrmFmt( pFmt );
+
+ if( ULONG_MAX == nNdPos )
+ return;
+
+ SwTxtNode* pTxtNd = rDoc.GetNodes()[ nNdPos ]->GetTxtNode();
+ // wenn mehr als ein Node geloescht wurde, dann wurden auch
+ // alle "Node"-Attribute gespeichert
+ if( pTxtNd->HasSwAttrSet() )
+ pTxtNd->ResetAllAttr();
+
+ if( pTxtNd->GetpSwpHints() && aStr.Len() )
+ pTxtNd->ClearSwpHintsArr( true );
+
+ // ChgTextToNum(..) only acts when the strings are different. We
+ // need to do the same here.
+ if( pTxtNd->GetTxt() != aStr )
+ {
+ rDoc.DeleteRedline( *( pBox->GetSttNd() ), false, USHRT_MAX );
+
+ SwIndex aIdx( pTxtNd, 0 );
+ if( aStr.Len() )
+ {
+ pTxtNd->EraseText( aIdx );
+ pTxtNd->InsertText( aStr, aIdx,
+ IDocumentContentOperations::INS_NOHINTEXPAND );
+ }
+ }
+
+ if( pHistory )
+ {
+ sal_uInt16 nTmpEnd = pHistory->GetTmpEnd();
+ pHistory->TmpRollback( &rDoc, 0 );
+ pHistory->SetTmpEnd( nTmpEnd );
+ }
+
+ SwPaM *const pPam(& rContext.GetCursorSupplier().CreateNewShellCursor());
+ pPam->DeleteMark();
+ pPam->GetPoint()->nNode = nNode + 1;
+ pPam->GetPoint()->nContent.Assign( pTxtNd, 0 );
+}
+
+/** switch the RedlineMode on the given document, using
+ * SetRedlineMode_intern. This class set the mode in the constructor,
+ * and changes it back in the destructor, i.e. it uses the
+ * initialization-is-resource-acquisition idiom.
+ */
+class RedlineModeInternGuard
+{
+ SwDoc& mrDoc;
+ RedlineMode_t meOldRedlineMode;
+
+public:
+ RedlineModeInternGuard(
+ SwDoc& rDoc, /// change mode of this document
+ RedlineMode_t eNewRedlineMode, /// new redline mode
+ RedlineMode_t eRedlineModeMask = (RedlineMode_t)(nsRedlineMode_t::REDLINE_ON | nsRedlineMode_t::REDLINE_IGNORE /*change only bits set in this mask*/));
+
+ ~RedlineModeInternGuard();
+};
+
+RedlineModeInternGuard::RedlineModeInternGuard(
+ SwDoc& rDoc,
+ RedlineMode_t eNewRedlineMode,
+ RedlineMode_t eRedlineModeMask )
+ : mrDoc( rDoc ),
+ meOldRedlineMode( rDoc.GetRedlineMode() )
+{
+ mrDoc.SetRedlineMode_intern((RedlineMode_t)( ( meOldRedlineMode & ~eRedlineModeMask ) |
+ ( eNewRedlineMode & eRedlineModeMask ) ));
+}
+
+RedlineModeInternGuard::~RedlineModeInternGuard()
+{
+ mrDoc.SetRedlineMode_intern( meOldRedlineMode );
+}
+
+
+
+void SwUndoTblNumFmt::RedoImpl(::sw::UndoRedoContext & rContext)
+{
+ // konnte die Box veraendert werden ?
+ if( !pBoxSet )
+ return ;
+
+ SwDoc & rDoc = rContext.GetDoc();
+ SwPaM *const pPam(& rContext.GetCursorSupplier().CreateNewShellCursor());
+
+ pPam->DeleteMark();
+ pPam->GetPoint()->nNode = nNode;
+
+ SwNode * pNd = & pPam->GetPoint()->nNode.GetNode();
+ SwStartNode* pSttNd = pNd->FindSttNodeByType( SwTableBoxStartNode );
+ OSL_ENSURE( pSttNd, "ohne StartNode kein TabellenBox" );
+ SwTableBox* pBox = pSttNd->FindTableNode()->GetTable().GetTblBox(
+ pSttNd->GetIndex() );
+ OSL_ENSURE( pBox, "keine TabellenBox gefunden" );
+
+ SwFrmFmt* pBoxFmt = pBox->ClaimFrmFmt();
+ if( bNewFmt || bNewFml || bNewValue )
+ {
+ SfxItemSet aBoxSet( rDoc.GetAttrPool(),
+ RES_BOXATR_FORMAT, RES_BOXATR_VALUE );
+
+ // JP 15.01.99: Nur Attribute zuruecksetzen reicht nicht.
+ // Sorge dafuer, das der Text auch entsprechend
+ // formatiert wird!
+ pBoxFmt->LockModify();
+
+ if( bNewFml )
+ aBoxSet.Put( SwTblBoxFormula( aNewFml ));
+ else
+ pBoxFmt->ResetFmtAttr( RES_BOXATR_FORMULA );
+ if( bNewFmt )
+ aBoxSet.Put( SwTblBoxNumFormat( nNewFmtIdx ));
+ else
+ pBoxFmt->ResetFmtAttr( RES_BOXATR_FORMAT );
+ if( bNewValue )
+ aBoxSet.Put( SwTblBoxValue( fNewNum ));
+ else
+ pBoxFmt->ResetFmtAttr( RES_BOXATR_VALUE );
+ pBoxFmt->UnlockModify();
+
+ // dvo: When redlining is (was) enabled, setting the attribute
+ // will also change the cell content. To allow this, the
+ // REDLINE_IGNORE flag must be removed during Redo. #108450#
+ RedlineModeInternGuard aGuard( rDoc, nsRedlineMode_t::REDLINE_NONE, nsRedlineMode_t::REDLINE_IGNORE );
+ pBoxFmt->SetFmtAttr( aBoxSet );
+ }
+ else if( NUMBERFORMAT_TEXT != nFmtIdx )
+ {
+ SfxItemSet aBoxSet( rDoc.GetAttrPool(),
+ RES_BOXATR_FORMAT, RES_BOXATR_VALUE );
+
+ aBoxSet.Put( SwTblBoxNumFormat( nFmtIdx ));
+ aBoxSet.Put( SwTblBoxValue( fNum ));
+
+ // JP 15.01.99: Nur Attribute zuruecksetzen reicht nicht.
+ // Sorge dafuer, das der Text auch entsprechend
+ // formatiert wird!
+ pBoxFmt->LockModify();
+ pBoxFmt->ResetFmtAttr( RES_BOXATR_FORMULA );
+ pBoxFmt->UnlockModify();
+
+ // dvo: When redlining is (was) enabled, setting the attribute
+ // will also change the cell content. To allow this, the
+ // REDLINE_IGNORE flag must be removed during Redo. #108450#
+ RedlineModeInternGuard aGuard( rDoc, nsRedlineMode_t::REDLINE_NONE, nsRedlineMode_t::REDLINE_IGNORE );
+ pBoxFmt->SetFmtAttr( aBoxSet );
+ }
+ else
+ {
+ // es ist keine Zahl
+
+ // JP 15.01.99: Nur Attribute zuruecksetzen reicht nicht.
+ // Sorge dafuer, das der Text auch entsprechend
+ // formatiert wird!
+ pBoxFmt->SetFmtAttr( *GetDfltAttr( RES_BOXATR_FORMAT ));
+
+ pBoxFmt->ResetFmtAttr( RES_BOXATR_FORMAT, RES_BOXATR_VALUE );
+ }
+
+ if( bNewFml )
+ {
+ // egal was gesetzt wurde, ein Update der Tabelle macht sich immer gut
+ SwTableFmlUpdate aTblUpdate( &pSttNd->FindTableNode()->GetTable() );
+ rDoc.UpdateTblFlds( &aTblUpdate );
+ }
+
+ if( !pNd->IsCntntNode() )
+ pNd = rDoc.GetNodes().GoNext( &pPam->GetPoint()->nNode );
+ pPam->GetPoint()->nContent.Assign( (SwCntntNode*)pNd, 0 );
+}
+
+void SwUndoTblNumFmt::SetBox( const SwTableBox& rBox )
+{
+ nNode = rBox.GetSttIdx();
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+
+_UndoTblCpyTbl_Entry::_UndoTblCpyTbl_Entry( const SwTableBox& rBox )
+ : nBoxIdx( rBox.GetSttIdx() ), nOffset( 0 ),
+ pBoxNumAttr( 0 ), pUndo( 0 ), bJoin( false )
+{
+}
+
+_UndoTblCpyTbl_Entry::~_UndoTblCpyTbl_Entry()
+{
+ delete pUndo;
+ delete pBoxNumAttr;
+}
+
+
+SwUndoTblCpyTbl::SwUndoTblCpyTbl()
+ : SwUndo( UNDO_TBLCPYTBL ), pInsRowUndo( 0 )
+{
+ pArr = new _UndoTblCpyTbl_Entries;
+}
+
+SwUndoTblCpyTbl::~SwUndoTblCpyTbl()
+{
+ delete pArr;
+ delete pInsRowUndo;
+}
+
+void SwUndoTblCpyTbl::UndoImpl(::sw::UndoRedoContext & rContext)
+{
+ SwDoc & rDoc = rContext.GetDoc();
+ _DEBUG_REDLINE( &rDoc )
+
+ SwTableNode* pTblNd = 0;
+ for( sal_uInt16 n = pArr->Count(); n; )
+ {
+ _UndoTblCpyTbl_Entry* pEntry = (*pArr)[ --n ];
+ sal_uLong nSttPos = pEntry->nBoxIdx + pEntry->nOffset;
+ SwStartNode* pSNd = rDoc.GetNodes()[ nSttPos ]->StartOfSectionNode();
+ if( !pTblNd )
+ pTblNd = pSNd->FindTableNode();
+
+ SwTableBox& rBox = *pTblNd->GetTable().GetTblBox( nSttPos );
+
+ SwNodeIndex aInsIdx( *rBox.GetSttNd(), 1 );
+ rDoc.GetNodes().MakeTxtNode( aInsIdx, (SwTxtFmtColl*)rDoc.GetDfltTxtFmtColl() );
+
+ // b62341295: Redline for copying tables
+ const SwNode *pEndNode = rBox.GetSttNd()->EndOfSectionNode();
+ SwPaM aPam( aInsIdx.GetNode(), *pEndNode );
+ SwUndoDelete* pUndo = 0;
+
+ if( IDocumentRedlineAccess::IsRedlineOn( GetRedlineMode() ) )
+ {
+ bool bDeleteCompleteParagraph = false;
+ bool bShiftPam = false;
+ // There are a couple of different situations to consider during redlining
+ if( pEntry->pUndo )
+ {
+ SwUndoDelete *const pUndoDelete =
+ dynamic_cast<SwUndoDelete*>(pEntry->pUndo);
+ SwUndoRedlineDelete *const pUndoRedlineDelete =
+ dynamic_cast<SwUndoRedlineDelete*>(pEntry->pUndo);
+ OSL_ASSERT(pUndoDelete || pUndoRedlineDelete);
+ if (pUndoRedlineDelete)
+ {
+ // The old content was not empty or he has been merged with the new content
+ bDeleteCompleteParagraph = !pEntry->bJoin; // bJoin is set when merged
+ // Set aTmpIdx to the beginning fo the old content
+ SwNodeIndex aTmpIdx( *pEndNode,
+ pUndoRedlineDelete->NodeDiff()-1 );
+ SwTxtNode *pTxt = aTmpIdx.GetNode().GetTxtNode();
+ if( pTxt )
+ {
+ aPam.GetPoint()->nNode = *pTxt;
+ aPam.GetPoint()->nContent.Assign( pTxt,
+ pUndoRedlineDelete->ContentStart() );
+ }
+ else
+ *aPam.GetPoint() = SwPosition( aTmpIdx );
+ }
+ else if (pUndoDelete && pUndoDelete->IsDelFullPara())
+ {
+ // When the old content was an empty paragraph, but could not be joined
+ // with the new content (e.g. because of a section or table)
+ // We "save" the aPam.Point, we go one step backwards (because later on the
+ // empty paragraph will be inserted by the undo) and set the "ShiftPam-flag
+ // for step forward later on.
+ bDeleteCompleteParagraph = true;
+ bShiftPam = true;
+ SwNodeIndex aTmpIdx( *pEndNode, -1 );
+ SwTxtNode *pTxt = aTmpIdx.GetNode().GetTxtNode();
+ if( pTxt )
+ {
+ aPam.GetPoint()->nNode = *pTxt;
+ aPam.GetPoint()->nContent.Assign( pTxt, 0 );
+ }
+ else
+ *aPam.GetPoint() = SwPosition( aTmpIdx );
+ }
+ }
+ rDoc.DeleteRedline( aPam, true, USHRT_MAX );
+
+ if( pEntry->pUndo )
+ {
+ pEntry->pUndo->UndoImpl(rContext);
+ delete pEntry->pUndo;
+ pEntry->pUndo = 0;
+ }
+ if( bShiftPam )
+ {
+ // The aPam.Point is at the moment at the last position of the new content and has to be
+ // moved to the first postion of the old content for the SwUndoDelete operation
+ SwNodeIndex aTmpIdx( aPam.GetPoint()->nNode, 1 );
+ SwTxtNode *pTxt = aTmpIdx.GetNode().GetTxtNode();
+ if( pTxt )
+ {
+ aPam.GetPoint()->nNode = *pTxt;
+ aPam.GetPoint()->nContent.Assign( pTxt, 0 );
+ }
+ else
+ *aPam.GetPoint() = SwPosition( aTmpIdx );
+ }
+ pUndo = new SwUndoDelete( aPam, bDeleteCompleteParagraph, sal_True );
+ }
+ else
+ {
+ pUndo = new SwUndoDelete( aPam, true );
+ if( pEntry->pUndo )
+ {
+ pEntry->pUndo->UndoImpl(rContext);
+ delete pEntry->pUndo;
+ pEntry->pUndo = 0;
+ }
+ }
+ pEntry->pUndo = pUndo;
+
+ aInsIdx = rBox.GetSttIdx() + 1;
+ rDoc.GetNodes().Delete( aInsIdx, 1 );
+
+ SfxItemSet aTmpSet( rDoc.GetAttrPool(), RES_BOXATR_FORMAT, RES_BOXATR_VALUE,
+ RES_VERT_ORIENT, RES_VERT_ORIENT, 0 );
+ aTmpSet.Put( rBox.GetFrmFmt()->GetAttrSet() );
+ if( aTmpSet.Count() )
+ {
+ SwFrmFmt* pBoxFmt = rBox.ClaimFrmFmt();
+ pBoxFmt->ResetFmtAttr( RES_BOXATR_FORMAT, RES_BOXATR_VALUE );
+ pBoxFmt->ResetFmtAttr( RES_VERT_ORIENT );
+ }
+
+ if( pEntry->pBoxNumAttr )
+ {
+ rBox.ClaimFrmFmt()->SetFmtAttr( *pEntry->pBoxNumAttr );
+ delete pEntry->pBoxNumAttr, pEntry->pBoxNumAttr = 0;
+ }
+
+ if( aTmpSet.Count() )
+ {
+ pEntry->pBoxNumAttr = new SfxItemSet( rDoc.GetAttrPool(),
+ RES_BOXATR_FORMAT, RES_BOXATR_VALUE,
+ RES_VERT_ORIENT, RES_VERT_ORIENT, 0 );
+ pEntry->pBoxNumAttr->Put( aTmpSet );
+ }
+
+ pEntry->nOffset = rBox.GetSttIdx() - pEntry->nBoxIdx;
+ }
+
+ if( pInsRowUndo )
+ {
+ pInsRowUndo->UndoImpl(rContext);
+ }
+ _DEBUG_REDLINE( &rDoc )
+}
+
+void SwUndoTblCpyTbl::RedoImpl(::sw::UndoRedoContext & rContext)
+{
+ SwDoc & rDoc = rContext.GetDoc();
+ _DEBUG_REDLINE( &rDoc )
+
+ if( pInsRowUndo )
+ {
+ pInsRowUndo->RedoImpl(rContext);
+ }
+
+ SwTableNode* pTblNd = 0;
+ for( sal_uInt16 n = 0; n < pArr->Count(); ++n )
+ {
+ _UndoTblCpyTbl_Entry* pEntry = (*pArr)[ n ];
+ sal_uLong nSttPos = pEntry->nBoxIdx + pEntry->nOffset;
+ SwStartNode* pSNd = rDoc.GetNodes()[ nSttPos ]->StartOfSectionNode();
+ if( !pTblNd )
+ pTblNd = pSNd->FindTableNode();
+
+ SwTableBox& rBox = *pTblNd->GetTable().GetTblBox( nSttPos );
+
+ SwNodeIndex aInsIdx( *rBox.GetSttNd(), 1 );
+
+ // b62341295: Redline for copying tables - Start.
+ rDoc.GetNodes().MakeTxtNode( aInsIdx, (SwTxtFmtColl*)rDoc.GetDfltTxtFmtColl() );
+ SwPaM aPam( aInsIdx.GetNode(), *rBox.GetSttNd()->EndOfSectionNode());
+ SwUndo* pUndo = IDocumentRedlineAccess::IsRedlineOn( GetRedlineMode() ) ? 0 : new SwUndoDelete( aPam, sal_True );
+ if( pEntry->pUndo )
+ {
+ pEntry->pUndo->UndoImpl(rContext);
+ if( IDocumentRedlineAccess::IsRedlineOn( GetRedlineMode() ) )
+ {
+ // PrepareRedline has to be called with the beginning of the old content
+ // When new and old content has been joined, the rIter.pAktPam has been set
+ // by the Undo operation to this point.
+ // Otherwise aInsIdx has been moved during the Undo operation
+ if( pEntry->bJoin )
+ {
+ SwPaM const& rLastPam =
+ rContext.GetCursorSupplier().GetCurrentShellCursor();
+ pUndo = PrepareRedline( &rDoc, rBox, *rLastPam.GetPoint(),
+ pEntry->bJoin, true );
+ }
+ else
+ {
+ SwPosition aTmpPos( aInsIdx );
+ pUndo = PrepareRedline( &rDoc, rBox, aTmpPos, pEntry->bJoin, true );
+ }
+ }
+ delete pEntry->pUndo;
+ pEntry->pUndo = 0;
+ }
+ pEntry->pUndo = pUndo;
+ // b62341295: Redline for copying tables - End.
+
+ aInsIdx = rBox.GetSttIdx() + 1;
+ rDoc.GetNodes().Delete( aInsIdx, 1 );
+
+ SfxItemSet aTmpSet( rDoc.GetAttrPool(), RES_BOXATR_FORMAT, RES_BOXATR_VALUE,
+ RES_VERT_ORIENT, RES_VERT_ORIENT, 0 );
+ aTmpSet.Put( rBox.GetFrmFmt()->GetAttrSet() );
+ if( aTmpSet.Count() )
+ {
+ SwFrmFmt* pBoxFmt = rBox.ClaimFrmFmt();
+ pBoxFmt->ResetFmtAttr( RES_BOXATR_FORMAT, RES_BOXATR_VALUE );
+ pBoxFmt->ResetFmtAttr( RES_VERT_ORIENT );
+ }
+ if( pEntry->pBoxNumAttr )
+ {
+ rBox.ClaimFrmFmt()->SetFmtAttr( *pEntry->pBoxNumAttr );
+ delete pEntry->pBoxNumAttr, pEntry->pBoxNumAttr = 0;
+ }
+
+ if( aTmpSet.Count() )
+ {
+ pEntry->pBoxNumAttr = new SfxItemSet( rDoc.GetAttrPool(),
+ RES_BOXATR_FORMAT, RES_BOXATR_VALUE,
+ RES_VERT_ORIENT, RES_VERT_ORIENT, 0 );
+ pEntry->pBoxNumAttr->Put( aTmpSet );
+ }
+
+ pEntry->nOffset = rBox.GetSttIdx() - pEntry->nBoxIdx;
+ }
+ _DEBUG_REDLINE( &rDoc )
+}
+
+void SwUndoTblCpyTbl::AddBoxBefore( const SwTableBox& rBox, sal_Bool bDelCntnt )
+{
+ if( pArr->Count() && !bDelCntnt )
+ return;
+
+ _UndoTblCpyTbl_Entry* pEntry = new _UndoTblCpyTbl_Entry( rBox );
+ pArr->Insert( pEntry, pArr->Count() );
+
+ SwDoc* pDoc = rBox.GetFrmFmt()->GetDoc();
+ _DEBUG_REDLINE( pDoc )
+ if( bDelCntnt )
+ {
+ SwNodeIndex aInsIdx( *rBox.GetSttNd(), 1 );
+ pDoc->GetNodes().MakeTxtNode( aInsIdx, (SwTxtFmtColl*)pDoc->GetDfltTxtFmtColl() );
+ SwPaM aPam( aInsIdx.GetNode(), *rBox.GetSttNd()->EndOfSectionNode() );
+
+ if( !pDoc->IsRedlineOn() )
+ pEntry->pUndo = new SwUndoDelete( aPam, sal_True );
+ }
+
+ pEntry->pBoxNumAttr = new SfxItemSet( pDoc->GetAttrPool(),
+ RES_BOXATR_FORMAT, RES_BOXATR_VALUE,
+ RES_VERT_ORIENT, RES_VERT_ORIENT, 0 );
+ pEntry->pBoxNumAttr->Put( rBox.GetFrmFmt()->GetAttrSet() );
+ if( !pEntry->pBoxNumAttr->Count() )
+ delete pEntry->pBoxNumAttr, pEntry->pBoxNumAttr = 0;
+ _DEBUG_REDLINE( pDoc )
+}
+
+void SwUndoTblCpyTbl::AddBoxAfter( const SwTableBox& rBox, const SwNodeIndex& rIdx, sal_Bool bDelCntnt )
+{
+ _UndoTblCpyTbl_Entry* pEntry = (*pArr)[ pArr->Count() - 1 ];
+
+ // wurde der Inhalt geloescht, so loesche jetzt auch noch den temp.
+ // erzeugten Node
+ if( bDelCntnt )
+ {
+ SwDoc* pDoc = rBox.GetFrmFmt()->GetDoc();
+ _DEBUG_REDLINE( pDoc )
+
+ if( pDoc->IsRedlineOn() )
+ {
+ SwPosition aTmpPos( rIdx );
+ pEntry->pUndo = PrepareRedline( pDoc, rBox, aTmpPos, pEntry->bJoin, false );
+ }
+ SwNodeIndex aDelIdx( *rBox.GetSttNd(), 1 );
+ rBox.GetFrmFmt()->GetDoc()->GetNodes().Delete( aDelIdx, 1 );
+ _DEBUG_REDLINE( pDoc )
+ }
+
+ pEntry->nOffset = rBox.GetSttIdx() - pEntry->nBoxIdx;
+}
+
+// PrepareRedline is called from AddBoxAfter() and from Redo() in slightly different situations.
+// bRedo is set by calling from Redo()
+// rJoin is false by calling from AddBoxAfter() and will be set if the old and new content has
+// been merged.
+// rJoin is true if Redo() is calling and the content has already been merged
+
+SwUndo* SwUndoTblCpyTbl::PrepareRedline( SwDoc* pDoc, const SwTableBox& rBox,
+ const SwPosition& rPos, bool& rJoin, bool bRedo )
+{
+ SwUndo *pUndo = 0;
+ // b62341295: Redline for copying tables
+ // What's to do?
+ // Mark the cell content before rIdx as insertion,
+ // mark the cell content behind rIdx as deletion
+ // merge text nodes at rIdx if possible
+ RedlineMode_t eOld = pDoc->GetRedlineMode();
+ pDoc->SetRedlineMode_intern((RedlineMode_t)( ( eOld | nsRedlineMode_t::REDLINE_DONTCOMBINE_REDLINES ) &
+ ~nsRedlineMode_t::REDLINE_IGNORE ));
+ SwPosition aInsertEnd( rPos );
+ SwTxtNode* pTxt;
+ if( !rJoin )
+ {
+ // If the content is not merged, the end of the insertion is at the end of the node
+ // _before_ the given position rPos
+ --aInsertEnd.nNode;
+ pTxt = aInsertEnd.nNode.GetNode().GetTxtNode();
+ if( pTxt )
+ {
+ aInsertEnd.nContent.Assign( pTxt, pTxt->GetTxt().Len() );
+ if( !bRedo && rPos.nNode.GetNode().GetTxtNode() )
+ { // Try to merge, if not called by Redo()
+ rJoin = true;
+ pTxt->JoinNext();
+ }
+ }
+ else
+ aInsertEnd.nContent = SwIndex( 0 );
+ }
+ // For joined (merged) contents the start of deletionm and end of insertion are identical
+ // otherwise adjacent nodes.
+ SwPosition aDeleteStart( rJoin ? aInsertEnd : rPos );
+ if( !rJoin )
+ {
+ pTxt = aDeleteStart.nNode.GetNode().GetTxtNode();
+ if( pTxt )
+ aDeleteStart.nContent.Assign( pTxt, 0 );
+ }
+ SwPosition aCellEnd( SwNodeIndex( *rBox.GetSttNd()->EndOfSectionNode(), -1 ) );
+ pTxt = aCellEnd.nNode.GetNode().GetTxtNode();
+ if( pTxt )
+ aCellEnd.nContent.Assign( pTxt, pTxt->GetTxt().Len() );
+ if( aDeleteStart != aCellEnd )
+ { // If the old (deleted) part is not empty, here we are...
+ SwPaM aDeletePam( aDeleteStart, aCellEnd );
+ pUndo = new SwUndoRedlineDelete( aDeletePam, UNDO_DELETE );
+ pDoc->AppendRedline( new SwRedline( nsRedlineType_t::REDLINE_DELETE, aDeletePam ), true );
+ }
+ else if( !rJoin ) // If the old part is empty and joined, we are finished
+ { // if it is not joined, we have to delete this empty paragraph
+ aCellEnd = SwPosition(
+ SwNodeIndex( *rBox.GetSttNd()->EndOfSectionNode() ));
+ SwPaM aTmpPam( aDeleteStart, aCellEnd );
+ pUndo = new SwUndoDelete( aTmpPam, sal_True );
+ }
+ SwPosition aCellStart( SwNodeIndex( *rBox.GetSttNd(), 2 ) );
+ pTxt = aCellStart.nNode.GetNode().GetTxtNode();
+ if( pTxt )
+ aCellStart.nContent.Assign( pTxt, 0 );
+ if( aCellStart != aInsertEnd ) // An empty insertion will not been marked
+ {
+ SwPaM aTmpPam( aCellStart, aInsertEnd );
+ pDoc->AppendRedline( new SwRedline( nsRedlineType_t::REDLINE_INSERT, aTmpPam ), true );
+ }
+
+ pDoc->SetRedlineMode_intern( eOld );
+ return pUndo;
+}
+
+
+sal_Bool SwUndoTblCpyTbl::InsertRow( SwTable& rTbl, const SwSelBoxes& rBoxes,
+ sal_uInt16 nCnt )
+{
+ SwTableNode* pTblNd = (SwTableNode*)rTbl.GetTabSortBoxes()[0]->
+ GetSttNd()->FindTableNode();
+
+ SwTableSortBoxes aTmpLst( 0, 5 );
+ pInsRowUndo = new SwUndoTblNdsChg( UNDO_TABLE_INSROW, rBoxes, *pTblNd,
+ 0, 0, nCnt, sal_True, sal_False );
+ aTmpLst.Insert( &rTbl.GetTabSortBoxes(), 0, rTbl.GetTabSortBoxes().Count() );
+
+ sal_Bool bRet = rTbl.InsertRow( rTbl.GetFrmFmt()->GetDoc(), rBoxes, nCnt, sal_True );
+ if( bRet )
+ pInsRowUndo->SaveNewBoxes( *pTblNd, aTmpLst );
+ else
+ delete pInsRowUndo, pInsRowUndo = 0;
+ return bRet;
+}
+
+sal_Bool SwUndoTblCpyTbl::IsEmpty() const
+{
+ return !pInsRowUndo && !pArr->Count();
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+
+SwUndoCpyTbl::SwUndoCpyTbl()
+ : SwUndo( UNDO_CPYTBL ), pDel( 0 ), nTblNode( 0 )
+{
+}
+
+SwUndoCpyTbl::~SwUndoCpyTbl()
+{
+ delete pDel;
+}
+
+void SwUndoCpyTbl::UndoImpl(::sw::UndoRedoContext & rContext)
+{
+ SwDoc & rDoc = rContext.GetDoc();
+ SwTableNode* pTNd = rDoc.GetNodes()[ nTblNode ]->GetTableNode();
+
+ // harte SeitenUmbrueche am nachfolgenden Node verschieben
+ SwCntntNode* pNextNd = rDoc.GetNodes()[ pTNd->EndOfSectionIndex()+1 ]->GetCntntNode();
+ if( pNextNd )
+ {
+ SwFrmFmt* pTableFmt = pTNd->GetTable().GetFrmFmt();
+ const SfxPoolItem *pItem;
+
+ if( SFX_ITEM_SET == pTableFmt->GetItemState( RES_PAGEDESC,
+ sal_False, &pItem ) )
+ pNextNd->SetAttr( *pItem );
+
+ if( SFX_ITEM_SET == pTableFmt->GetItemState( RES_BREAK,
+ sal_False, &pItem ) )
+ pNextNd->SetAttr( *pItem );
+ }
+
+ SwPaM aPam( *pTNd, *pTNd->EndOfSectionNode(), 0 , 1 );
+ pDel = new SwUndoDelete( aPam, sal_True );
+}
+
+void SwUndoCpyTbl::RedoImpl(::sw::UndoRedoContext & rContext)
+{
+ pDel->UndoImpl(rContext);
+ delete pDel, pDel = 0;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+
+SwUndoSplitTbl::SwUndoSplitTbl( const SwTableNode& rTblNd,
+ SwSaveRowSpan* pRowSp, sal_uInt16 eMode, sal_Bool bNewSize )
+ : SwUndo( UNDO_SPLIT_TABLE ),
+ nTblNode( rTblNd.GetIndex() ), nOffset( 0 ), mpSaveRowSpan( pRowSp ), pSavTbl( 0 ),
+ pHistory( 0 ), nMode( eMode ), nFmlEnd( 0 ), bCalcNewSize( bNewSize )
+{
+ switch( nMode )
+ {
+ case HEADLINE_BOXATRCOLLCOPY:
+ pHistory = new SwHistory;
+ // kein break;
+ case HEADLINE_BORDERCOPY:
+ case HEADLINE_BOXATTRCOPY:
+ pSavTbl = new _SaveTable( rTblNd.GetTable(), 1, sal_False );
+ break;
+ }
+}
+
+SwUndoSplitTbl::~SwUndoSplitTbl()
+{
+ delete pSavTbl;
+ delete pHistory;
+ delete mpSaveRowSpan;
+}
+
+void SwUndoSplitTbl::UndoImpl(::sw::UndoRedoContext & rContext)
+{
+ SwDoc *const pDoc = & rContext.GetDoc();
+ SwPaM *const pPam(& rContext.GetCursorSupplier().CreateNewShellCursor());
+
+ pPam->DeleteMark();
+ SwNodeIndex& rIdx = pPam->GetPoint()->nNode;
+ rIdx = nTblNode + nOffset;
+
+ //Den implizit erzeugten Absatz wieder entfernen.
+ pDoc->GetNodes().Delete( rIdx, 1 );
+
+ rIdx = nTblNode + nOffset;
+ SwTableNode* pTblNd = rIdx.GetNode().GetTableNode();
+ SwTable& rTbl = pTblNd->GetTable();
+
+ SwTableFmlUpdate aMsgHnt( &rTbl );
+ aMsgHnt.eFlags = TBL_BOXPTR;
+ pDoc->UpdateTblFlds( &aMsgHnt );
+
+ switch( nMode )
+ {
+ case HEADLINE_BOXATRCOLLCOPY:
+ if( pHistory )
+ pHistory->TmpRollback( pDoc, nFmlEnd );
+
+ // kein break
+ case HEADLINE_BOXATTRCOPY:
+ case HEADLINE_BORDERCOPY:
+ {
+ pSavTbl->CreateNew( rTbl, sal_False );
+ pSavTbl->RestoreAttr( rTbl );
+ }
+ break;
+
+ case HEADLINE_CNTNTCOPY:
+ // die erzeugte 1. Line muss wieder entfernt werden
+ {
+ SwSelBoxes aSelBoxes;
+ SwTableBox* pBox = rTbl.GetTblBox( nTblNode + nOffset + 1 );
+ rTbl.SelLineFromBox( pBox, aSelBoxes, sal_True );
+ _FndBox aTmpBox( 0, 0 );
+ aTmpBox.SetTableLines( aSelBoxes, rTbl );
+ aTmpBox.DelFrms( rTbl );
+ rTbl.DeleteSel( pDoc, aSelBoxes, 0, 0, sal_False, sal_False );
+ }
+ break;
+ }
+
+ pDoc->GetNodes().MergeTable( rIdx );
+
+ if( pHistory )
+ {
+ pHistory->TmpRollback( pDoc, 0 );
+ pHistory->SetTmpEnd( pHistory->Count() );
+ }
+ if( mpSaveRowSpan )
+ {
+ pTblNd = rIdx.GetNode().FindTableNode();
+ if( pTblNd )
+ pTblNd->GetTable().RestoreRowSpan( *mpSaveRowSpan );
+ }
+ ClearFEShellTabCols();
+}
+
+void SwUndoSplitTbl::RedoImpl(::sw::UndoRedoContext & rContext)
+{
+ SwDoc *const pDoc = & rContext.GetDoc();
+ SwPaM *const pPam(& rContext.GetCursorSupplier().CreateNewShellCursor());
+
+ pPam->DeleteMark();
+ pPam->GetPoint()->nNode = nTblNode;
+ pDoc->SplitTable( *pPam->GetPoint(), nMode, bCalcNewSize );
+
+ ClearFEShellTabCols();
+}
+
+void SwUndoSplitTbl::RepeatImpl(::sw::RepeatContext & rContext)
+{
+ SwPaM *const pPam = & rContext.GetRepeatPaM();
+ SwDoc *const pDoc = & rContext.GetDoc();
+
+ pDoc->SplitTable( *pPam->GetPoint(), nMode, bCalcNewSize );
+ ClearFEShellTabCols();
+}
+
+void SwUndoSplitTbl::SaveFormula( SwHistory& rHistory )
+{
+ if( !pHistory )
+ pHistory = new SwHistory;
+
+ nFmlEnd = rHistory.Count();
+ pHistory->Move( 0, &rHistory );
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+
+SwUndoMergeTbl::SwUndoMergeTbl( const SwTableNode& rTblNd,
+ const SwTableNode& rDelTblNd,
+ sal_Bool bWithPrv, sal_uInt16 nMd )
+ : SwUndo( UNDO_MERGE_TABLE ), pSavTbl( 0 ),
+ pHistory( 0 ), nMode( nMd ), bWithPrev( bWithPrv )
+{
+ // Endnode der letzen Tabellenzelle merken, die auf der Position verbleibt
+ if( bWithPrev )
+ nTblNode = rDelTblNd.EndOfSectionIndex() - 1;
+ else
+ nTblNode = rTblNd.EndOfSectionIndex() - 1;
+
+ aName = rDelTblNd.GetTable().GetFrmFmt()->GetName();
+ pSavTbl = new _SaveTable( rDelTblNd.GetTable() );
+
+ pSavHdl = bWithPrev ? new _SaveTable( rTblNd.GetTable(), 1 ) : 0;
+}
+
+SwUndoMergeTbl::~SwUndoMergeTbl()
+{
+ delete pSavTbl;
+ delete pSavHdl;
+ delete pHistory;
+}
+
+void SwUndoMergeTbl::UndoImpl(::sw::UndoRedoContext & rContext)
+{
+ SwDoc *const pDoc = & rContext.GetDoc();
+ SwPaM *const pPam(& rContext.GetCursorSupplier().CreateNewShellCursor());
+
+ pPam->DeleteMark();
+ SwNodeIndex& rIdx = pPam->GetPoint()->nNode;
+ rIdx = nTblNode;
+
+ SwTableNode* pTblNd = rIdx.GetNode().FindTableNode();
+ SwTable* pTbl = &pTblNd->GetTable();
+
+ SwTableFmlUpdate aMsgHnt( pTbl );
+ aMsgHnt.eFlags = TBL_BOXPTR;
+ pDoc->UpdateTblFlds( &aMsgHnt );
+
+ //Lines fuer das Layout-Update herausuchen.
+ _FndBox aFndBox( 0, 0 );
+ aFndBox.SetTableLines( *pTbl );
+ aFndBox.DelFrms( *pTbl );
+ // ? TL_CHART2: notification or locking of controller required ?
+
+ SwTableNode* pNew = pDoc->GetNodes().SplitTable( rIdx, sal_True, sal_False );
+
+ //Layout updaten
+ aFndBox.MakeFrms( *pTbl );
+ // ? TL_CHART2: notification or locking of controller required ?
+
+ if( bWithPrev )
+ {
+ // den Namen umsetzen
+ pNew->GetTable().GetFrmFmt()->SetName( pTbl->GetFrmFmt()->GetName() );
+ pSavHdl->RestoreAttr( pNew->GetTable() );
+ }
+ else
+ pTbl = &pNew->GetTable();
+ pTbl->GetFrmFmt()->SetName( aName );
+
+// pSavTbl->CreateNew( *pTbl, sal_False );
+ pSavTbl->RestoreAttr( *pTbl );
+
+
+ if( pHistory )
+ {
+ pHistory->TmpRollback( pDoc, 0 );
+ pHistory->SetTmpEnd( pHistory->Count() );
+ }
+
+ // fuer die neue Tabelle die Frames anlegen
+ SwNodeIndex aTmpIdx( *pNew );
+ pNew->MakeFrms( &aTmpIdx );
+
+ // Cursor irgendwo in den Content stellen
+ SwCntntNode* pCNd = pDoc->GetNodes().GoNext( &rIdx );
+ pPam->GetPoint()->nContent.Assign( pCNd, 0 );
+
+ ClearFEShellTabCols();
+
+ // TL_CHART2: need to inform chart of probably changed cell names
+ SwChartDataProvider *pPCD = pDoc->GetChartDataProvider();
+ if (pPCD)
+ {
+ pDoc->UpdateCharts( pTbl->GetFrmFmt()->GetName() );
+ pDoc->UpdateCharts( pNew->GetTable().GetFrmFmt()->GetName() );
+ }
+}
+
+void SwUndoMergeTbl::RedoImpl(::sw::UndoRedoContext & rContext)
+{
+ SwDoc *const pDoc = & rContext.GetDoc();
+ SwPaM *const pPam(& rContext.GetCursorSupplier().CreateNewShellCursor());
+
+ pPam->DeleteMark();
+ pPam->GetPoint()->nNode = nTblNode;
+ if( bWithPrev )
+ pPam->GetPoint()->nNode = nTblNode + 3;
+ else
+ pPam->GetPoint()->nNode = nTblNode;
+
+ pDoc->MergeTable( *pPam->GetPoint(), bWithPrev, nMode );
+
+ ClearFEShellTabCols();
+}
+
+void SwUndoMergeTbl::RepeatImpl(::sw::RepeatContext & rContext)
+{
+ SwDoc *const pDoc = & rContext.GetDoc();
+ SwPaM *const pPam = & rContext.GetRepeatPaM();
+
+ pDoc->MergeTable( *pPam->GetPoint(), bWithPrev, nMode );
+ ClearFEShellTabCols();
+}
+
+void SwUndoMergeTbl::SaveFormula( SwHistory& rHistory )
+{
+ if( !pHistory )
+ pHistory = new SwHistory;
+ pHistory->Move( 0, &rHistory );
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+
+void InsertSort( SvUShorts& rArr, sal_uInt16 nIdx, sal_uInt16* pInsPos )
+{
+ sal_uInt16 nO = rArr.Count(), nM, nU = 0;
+ if( nO > 0 )
+ {
+ nO--;
+ while( nU <= nO )
+ {
+ nM = nU + ( nO - nU ) / 2;
+ if( *(rArr.GetData() + nM) == nIdx )
+ {
+ OSL_FAIL( "Index already exists. This should never happen." );
+ return;
+ }
+ if( *(rArr.GetData() + nM) < nIdx )
+ nU = nM + 1;
+ else if( nM == 0 )
+ break;
+ else
+ nO = nM - 1;
+ }
+ }
+ rArr.Insert( nIdx, nU );
+ if( pInsPos )
+ *pInsPos = nU;
+}
+
+void InsertSort( SvULongs& rArr, sal_uLong nIdx, sal_uInt16* pInsPos )
+{
+ sal_uInt16 nO = rArr.Count(), nM, nU = 0;
+ if( nO > 0 )
+ {
+ nO--;
+ while( nU <= nO )
+ {
+ nM = nU + ( nO - nU ) / 2;
+ if( *(rArr.GetData() + nM) == nIdx )
+ {
+ OSL_FAIL( "Index ist schon vorhanden, darf nie sein!" );
+ return;
+ }
+ if( *(rArr.GetData() + nM) < nIdx )
+ nU = nM + 1;
+ else if( nM == 0 )
+ break;
+ else
+ nO = nM - 1;
+ }
+ }
+ rArr.Insert( nIdx, nU );
+ if( pInsPos )
+ *pInsPos = nU;
+}
+
+#if OSL_DEBUG_LEVEL > 1
+
+
+void CheckTable( const SwTable& rTbl )
+{
+ const SwNodes& rNds = rTbl.GetFrmFmt()->GetDoc()->GetNodes();
+ const SwTableSortBoxes& rSrtArr = rTbl.GetTabSortBoxes();
+ for( sal_uInt16 n = 0; n < rSrtArr.Count(); ++n )
+ {
+ const SwTableBox* pBox = rSrtArr[ n ];
+ const SwNode* pNd = pBox->GetSttNd();
+ OSL_ENSURE( rNds[ pBox->GetSttIdx() ] == pNd, "Box mit falchem StartNode" );
+ }
+}
+#endif
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/undo/untblk.cxx b/sw/source/core/undo/untblk.cxx
new file mode 100644
index 000000000000..ca6f3359ab53
--- /dev/null
+++ b/sw/source/core/undo/untblk.cxx
@@ -0,0 +1,357 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+#include <hintids.hxx>
+#include <fmtanchr.hxx>
+#include <frmfmt.hxx>
+#include <doc.hxx>
+#include <IDocumentUndoRedo.hxx>
+#include <docary.hxx>
+#include <swundo.hxx> // fuer die UndoIds
+#include <pam.hxx>
+#include <ndtxt.hxx>
+#include <UndoCore.hxx>
+#include <rolbck.hxx>
+#include <redline.hxx>
+
+
+
+SwUndoInserts::SwUndoInserts( SwUndoId nUndoId, const SwPaM& rPam )
+ : SwUndo( nUndoId ), SwUndRng( rPam ),
+ pTxtFmtColl( 0 ), pLastNdColl(0), pFrmFmts( 0 ), pRedlData( 0 ),
+ bSttWasTxtNd( sal_True ), nNdDiff( 0 ), pPos( 0 ), nSetPos( 0 )
+{
+ pHistory = new SwHistory;
+ SwDoc* pDoc = (SwDoc*)rPam.GetDoc();
+
+ SwTxtNode* pTxtNd = rPam.GetPoint()->nNode.GetNode().GetTxtNode();
+ if( pTxtNd )
+ {
+ pTxtFmtColl = pTxtNd->GetTxtColl();
+ pHistory->CopyAttr( pTxtNd->GetpSwpHints(), nSttNode,
+ 0, pTxtNd->GetTxt().Len(), false );
+ if( pTxtNd->HasSwAttrSet() )
+ pHistory->CopyFmtAttr( *pTxtNd->GetpSwAttrSet(), nSttNode );
+
+ if( !nSttCntnt ) // dann werden Flys mitgenommen !!
+ {
+ sal_uInt16 nArrLen = pDoc->GetSpzFrmFmts()->Count();
+ for( sal_uInt16 n = 0; n < nArrLen; ++n )
+ {
+ SwFrmFmt* pFmt = (*pDoc->GetSpzFrmFmts())[n];
+ SwFmtAnchor const*const pAnchor = &pFmt->GetAnchor();
+ const SwPosition* pAPos = pAnchor->GetCntntAnchor();
+ if (pAPos &&
+ (pAnchor->GetAnchorId() == FLY_AT_PARA) &&
+ nSttNode == pAPos->nNode.GetIndex() )
+ {
+ if( !pFrmFmts )
+ pFrmFmts = new SvPtrarr;
+ pFrmFmts->Insert( pFmt, pFrmFmts->Count() );
+ }
+ }
+ }
+ }
+ // Redline beachten
+ if( pDoc->IsRedlineOn() )
+ {
+ pRedlData = new SwRedlineData( nsRedlineType_t::REDLINE_INSERT, pDoc->GetRedlineAuthor() );
+ SetRedlineMode( pDoc->GetRedlineMode() );
+ }
+}
+
+// setze den Destination-Bereich nach dem Einlesen.
+
+void SwUndoInserts::SetInsertRange( const SwPaM& rPam, sal_Bool bScanFlys,
+ sal_Bool bSttIsTxtNd )
+{
+ const SwPosition* pTmpPos = rPam.End();
+ nEndNode = pTmpPos->nNode.GetIndex();
+ nEndCntnt = pTmpPos->nContent.GetIndex();
+ if( rPam.HasMark() )
+ {
+ if( pTmpPos == rPam.GetPoint() )
+ pTmpPos = rPam.GetMark();
+ else
+ pTmpPos = rPam.GetPoint();
+
+ nSttNode = pTmpPos->nNode.GetIndex();
+ nSttCntnt = pTmpPos->nContent.GetIndex();
+
+ if( !bSttIsTxtNd ) // wird eine Tabellenselektion eingefuegt,
+ {
+ ++nSttNode; // dann stimmt der CopyPam nicht ganz
+ bSttWasTxtNd = sal_False;
+ }
+ }
+
+ if( bScanFlys && !nSttCntnt )
+ {
+ // dann alle neuen Flys zusammen sammeln !!
+ SwDoc* pDoc = (SwDoc*)rPam.GetDoc();
+ sal_uInt16 nFndPos, nArrLen = pDoc->GetSpzFrmFmts()->Count();
+ for( sal_uInt16 n = 0; n < nArrLen; ++n )
+ {
+ SwFrmFmt* pFmt = (*pDoc->GetSpzFrmFmts())[n];
+ SwFmtAnchor const*const pAnchor = &pFmt->GetAnchor();
+ SwPosition const*const pAPos = pAnchor->GetCntntAnchor();
+ if (pAPos &&
+ (pAnchor->GetAnchorId() == FLY_AT_PARA) &&
+ nSttNode == pAPos->nNode.GetIndex() )
+ {
+ if( !pFrmFmts ||
+ USHRT_MAX == ( nFndPos = pFrmFmts->GetPos( pFmt ) ) )
+ {
+ ::boost::shared_ptr<SwUndoInsLayFmt> const pFlyUndo(
+ new SwUndoInsLayFmt(pFmt, 0, 0));
+ m_FlyUndos.push_back(pFlyUndo);
+ }
+ else
+ pFrmFmts->Remove( nFndPos );
+ }
+ }
+ delete pFrmFmts, pFrmFmts = 0;
+ }
+}
+
+
+SwUndoInserts::~SwUndoInserts()
+{
+ if( pPos ) // loesche noch den Bereich aus dem UndoNodes Array
+ {
+ // Insert speichert den Inhalt in der IconSection
+ SwNodes& rUNds = pPos->nNode.GetNodes();
+ if( pPos->nContent.GetIndex() ) // nicht den gesamten Node loeschen
+ {
+ SwTxtNode* pTxtNd = pPos->nNode.GetNode().GetTxtNode();
+ OSL_ENSURE( pTxtNd, "kein TextNode, aus dem geloescht werden soll" );
+ if( pTxtNd ) // Robust
+ {
+ pTxtNd->EraseText( pPos->nContent );
+ }
+ pPos->nNode++;
+ }
+ pPos->nContent.Assign( 0, 0 );
+ rUNds.Delete( pPos->nNode, rUNds.GetEndOfExtras().GetIndex() -
+ pPos->nNode.GetIndex() );
+ delete pPos;
+ }
+ delete pFrmFmts;
+ delete pRedlData;
+}
+
+
+void SwUndoInserts::UndoImpl(::sw::UndoRedoContext & rContext)
+{
+ SwDoc *const pDoc = & rContext.GetDoc();
+ SwPaM *const pPam = & AddUndoRedoPaM(rContext);
+
+ if( IDocumentRedlineAccess::IsRedlineOn( GetRedlineMode() ))
+ pDoc->DeleteRedline( *pPam, true, USHRT_MAX );
+
+ // sind an Point/Mark 2 unterschiedliche TextNodes, dann muss ein
+ // JoinNext ausgefuehrt werden.
+ sal_Bool bJoinNext = nSttNode != nEndNode &&
+ pPam->GetMark()->nNode.GetNode().GetTxtNode() &&
+ pPam->GetPoint()->nNode.GetNode().GetTxtNode();
+
+
+ // gibts ueberhaupt Inhalt ? (laden von Zeichenvorlagen hat kein Inhalt!)
+ if( nSttNode != nEndNode || nSttCntnt != nEndCntnt )
+ {
+ if( nSttNode != nEndNode )
+ {
+ SwTxtNode* pTxtNd = pDoc->GetNodes()[ nEndNode ]->GetTxtNode();
+ if( pTxtNd && pTxtNd->GetTxt().Len() == nEndCntnt )
+ pLastNdColl = pTxtNd->GetTxtColl();
+ }
+
+ RemoveIdxFromRange( *pPam, sal_False );
+ SetPaM(*pPam);
+
+ // sind Fussnoten oder CntntFlyFrames im Text ??
+ nSetPos = pHistory->Count();
+ nNdDiff = pPam->GetMark()->nNode.GetIndex();
+ DelCntntIndex( *pPam->GetMark(), *pPam->GetPoint() );
+ nNdDiff -= pPam->GetMark()->nNode.GetIndex();
+
+ if( *pPam->GetPoint() != *pPam->GetMark() )
+ {
+ pPos = new SwPosition( *pPam->GetPoint() );
+ MoveToUndoNds( *pPam, &pPos->nNode, &pPos->nContent );
+
+ if( !bSttWasTxtNd )
+ pPam->Move( fnMoveBackward, fnGoCntnt );
+ }
+ }
+
+ if (m_FlyUndos.size())
+ {
+ sal_uLong nTmp = pPam->GetPoint()->nNode.GetIndex();
+ for (size_t n = m_FlyUndos.size(); 0 < n; --n)
+ {
+ m_FlyUndos[ n-1 ]->UndoImpl(rContext);
+ }
+ nNdDiff += nTmp - pPam->GetPoint()->nNode.GetIndex();
+ }
+
+ SwNodeIndex& rIdx = pPam->GetPoint()->nNode;
+ SwTxtNode* pTxtNode = rIdx.GetNode().GetTxtNode();
+ if( pTxtNode )
+ {
+ if( !pTxtFmtColl ) // falls 0, dann war hier auch kein TextNode,
+ { // dann muss dieser geloescht werden,
+ SwNodeIndex aDelIdx( rIdx );
+ rIdx++;
+ SwCntntNode* pCNd = rIdx.GetNode().GetCntntNode();
+ xub_StrLen nCnt = 0; if( pCNd ) nCnt = pCNd->Len();
+ pPam->GetPoint()->nContent.Assign( pCNd, nCnt );
+ pPam->SetMark();
+ pPam->DeleteMark();
+
+ RemoveIdxRel( aDelIdx.GetIndex(), *pPam->GetPoint() );
+
+ pDoc->GetNodes().Delete( aDelIdx, 1 );
+ }
+ else
+ {
+ if( bJoinNext && pTxtNode->CanJoinNext())
+ {
+ {
+ RemoveIdxRel( rIdx.GetIndex()+1, SwPosition( rIdx,
+ SwIndex( pTxtNode, pTxtNode->GetTxt().Len() )));
+ }
+ pTxtNode->JoinNext();
+ }
+ // reset all text attributes in the paragraph!
+ pTxtNode->RstAttr( SwIndex(pTxtNode, 0), pTxtNode->Len(),
+ 0, 0, true );
+
+ // setze alle Attribute im Node zurueck
+ pTxtNode->ResetAllAttr();
+
+ if( USHRT_MAX != pDoc->GetTxtFmtColls()->GetPos( pTxtFmtColl ))
+ pTxtFmtColl = (SwTxtFmtColl*)pTxtNode->ChgFmtColl( pTxtFmtColl );
+
+ pHistory->SetTmpEnd( nSetPos );
+ pHistory->TmpRollback( pDoc, 0, false );
+ }
+ }
+}
+
+void SwUndoInserts::RedoImpl(::sw::UndoRedoContext & rContext)
+{
+ // setze noch den Cursor auf den Redo-Bereich
+ SwPaM *const pPam = & AddUndoRedoPaM(rContext);
+ SwDoc* pDoc = pPam->GetDoc();
+ pPam->DeleteMark();
+ pPam->GetPoint()->nNode = nSttNode - nNdDiff;
+ SwCntntNode* pCNd = pPam->GetCntntNode();
+ pPam->GetPoint()->nContent.Assign( pCNd, nSttCntnt );
+
+ SwTxtFmtColl* pSavTxtFmtColl = pTxtFmtColl;
+ if( pTxtFmtColl && pCNd && pCNd->IsTxtNode() )
+ pSavTxtFmtColl = ((SwTxtNode*)pCNd)->GetTxtColl();
+
+ pHistory->SetTmpEnd( nSetPos );
+
+ // alte Anfangs-Position fuers Rollback zurueckholen
+ if( ( nSttNode != nEndNode || nSttCntnt != nEndCntnt ) && pPos )
+ {
+ sal_Bool bMvBkwrd = MovePtBackward( *pPam );
+
+ // Inhalt wieder einfuegen. (erst pPos abmelden !!)
+ sal_uLong nMvNd = pPos->nNode.GetIndex();
+ xub_StrLen nMvCnt = pPos->nContent.GetIndex();
+ DELETEZ( pPos );
+ MoveFromUndoNds( *pDoc, nMvNd, nMvCnt, *pPam->GetMark() );
+ if( bSttWasTxtNd )
+ MovePtForward( *pPam, bMvBkwrd );
+ pPam->Exchange();
+ }
+
+ if( USHRT_MAX != pDoc->GetTxtFmtColls()->GetPos( pTxtFmtColl ))
+ {
+ SwTxtNode* pTxtNd = pPam->GetMark()->nNode.GetNode().GetTxtNode();
+ if( pTxtNd )
+ pTxtNd->ChgFmtColl( pTxtFmtColl );
+ }
+ pTxtFmtColl = pSavTxtFmtColl;
+
+ if( pLastNdColl && USHRT_MAX != pDoc->GetTxtFmtColls()->GetPos( pLastNdColl ) &&
+ pPam->GetPoint()->nNode != pPam->GetMark()->nNode )
+ {
+ SwTxtNode* pTxtNd = pPam->GetPoint()->nNode.GetNode().GetTxtNode();
+ if( pTxtNd )
+ pTxtNd->ChgFmtColl( pLastNdColl );
+ }
+
+ for (size_t n = m_FlyUndos.size(); 0 < n; --n)
+ {
+ m_FlyUndos[ n-1 ]->RedoImpl(rContext);
+ }
+
+ pHistory->Rollback( pDoc, nSetPos );
+
+ if( pRedlData && IDocumentRedlineAccess::IsRedlineOn( GetRedlineMode() ))
+ {
+ RedlineMode_t eOld = pDoc->GetRedlineMode();
+ pDoc->SetRedlineMode_intern((RedlineMode_t)( eOld & ~nsRedlineMode_t::REDLINE_IGNORE ));
+ pDoc->AppendRedline( new SwRedline( *pRedlData, *pPam ), true);
+ pDoc->SetRedlineMode_intern( eOld );
+ }
+ else if( !( nsRedlineMode_t::REDLINE_IGNORE & GetRedlineMode() ) &&
+ pDoc->GetRedlineTbl().Count() )
+ pDoc->SplitRedline( *pPam );
+}
+
+void SwUndoInserts::RepeatImpl(::sw::RepeatContext & rContext)
+{
+ SwPaM aPam( rContext.GetDoc().GetNodes().GetEndOfContent() );
+ SetPaM( aPam );
+ SwPaM & rRepeatPaM( rContext.GetRepeatPaM() );
+ aPam.GetDoc()->CopyRange( aPam, *rRepeatPaM.GetPoint(), false );
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+
+SwUndoInsDoc::SwUndoInsDoc( const SwPaM& rPam )
+ : SwUndoInserts( UNDO_INSDOKUMENT, rPam )
+{
+}
+
+SwUndoCpyDoc::SwUndoCpyDoc( const SwPaM& rPam )
+ : SwUndoInserts( UNDO_COPY, rPam )
+{
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/unocore/SwXTextDefaults.cxx b/sw/source/core/unocore/SwXTextDefaults.cxx
new file mode 100644
index 000000000000..ba0d8a4699ab
--- /dev/null
+++ b/sw/source/core/unocore/SwXTextDefaults.cxx
@@ -0,0 +1,291 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+#include <com/sun/star/beans/PropertyAttribute.hpp>
+
+#include <osl/mutex.hxx>
+#include <vcl/svapp.hxx>
+
+#include <SwXTextDefaults.hxx>
+#include <SwStyleNameMapper.hxx>
+#include <fchrfmt.hxx>
+#include <charfmt.hxx>
+#include <docstyle.hxx>
+#include <doc.hxx>
+#include <docsh.hxx>
+#include <unomap.hxx>
+#include <unomid.h>
+#include <paratr.hxx>
+#include <unoprnms.hxx>
+#include <unocrsrhelper.hxx>
+#include <hintids.hxx>
+
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::beans;
+using namespace ::com::sun::star::lang;
+using rtl::OUString;
+
+
+SwXTextDefaults::SwXTextDefaults ( SwDoc * pNewDoc ) :
+ m_pPropSet( aSwMapProvider.GetPropertySet( PROPERTY_MAP_TEXT_DEFAULT ) ),
+ m_pDoc ( pNewDoc )
+{
+}
+
+
+SwXTextDefaults::~SwXTextDefaults ()
+{
+}
+
+
+uno::Reference< XPropertySetInfo > SAL_CALL SwXTextDefaults::getPropertySetInfo( )
+ throw(RuntimeException)
+{
+ static uno::Reference < XPropertySetInfo > xRef = m_pPropSet->getPropertySetInfo();
+ return xRef;
+}
+
+
+void SAL_CALL SwXTextDefaults::setPropertyValue( const OUString& rPropertyName, const Any& aValue )
+ throw(UnknownPropertyException, PropertyVetoException, IllegalArgumentException, WrappedTargetException, RuntimeException)
+{
+ SolarMutexGuard aGuard;
+ if (!m_pDoc)
+ throw RuntimeException();
+ const SfxItemPropertySimpleEntry *pMap = m_pPropSet->getPropertyMap()->getByName( rPropertyName );
+ if (!pMap)
+ throw UnknownPropertyException(OUString ( RTL_CONSTASCII_USTRINGPARAM ( "Unknown property: " ) ) + rPropertyName, static_cast < cppu::OWeakObject * > ( this ) );
+ if ( pMap->nFlags & PropertyAttribute::READONLY)
+ throw PropertyVetoException ( OUString ( RTL_CONSTASCII_USTRINGPARAM ( "Property is read-only: " ) ) + rPropertyName, static_cast < cppu::OWeakObject * > ( this ) );
+
+ const SfxPoolItem& rItem = m_pDoc->GetDefault(pMap->nWID);
+ if (RES_PAGEDESC == pMap->nWID && MID_PAGEDESC_PAGEDESCNAME == pMap->nMemberId)
+ {
+ SfxItemSet aSet( m_pDoc->GetAttrPool(), RES_PAGEDESC, RES_PAGEDESC );
+ aSet.Put(rItem);
+ SwUnoCursorHelper::SetPageDesc( aValue, *m_pDoc, aSet );
+ m_pDoc->SetDefault(aSet.Get(RES_PAGEDESC));
+ }
+ else if ((RES_PARATR_DROP == pMap->nWID && MID_DROPCAP_CHAR_STYLE_NAME == pMap->nMemberId) ||
+ (RES_TXTATR_CHARFMT == pMap->nWID))
+ {
+ OUString uStyle;
+ if(aValue >>= uStyle)
+ {
+ String sStyle;
+ SwStyleNameMapper::FillUIName(uStyle, sStyle, nsSwGetPoolIdFromName::GET_POOLID_CHRFMT, sal_True );
+ SwDocStyleSheet* pStyle =
+ (SwDocStyleSheet*)m_pDoc->GetDocShell()->GetStyleSheetPool()->Find(sStyle, SFX_STYLE_FAMILY_CHAR);
+ SwFmtDrop* pDrop = 0;
+ SwFmtCharFmt *pCharFmt = 0;
+ if(pStyle)
+ {
+ rtl::Reference< SwDocStyleSheet > xStyle( new SwDocStyleSheet( *(SwDocStyleSheet*)pStyle ) );
+ if (RES_PARATR_DROP == pMap->nWID)
+ {
+ pDrop = (SwFmtDrop*)rItem.Clone(); // because rItem ist const...
+ pDrop->SetCharFmt(xStyle->GetCharFmt());
+ m_pDoc->SetDefault(*pDrop);
+ }
+ else // RES_TXTATR_CHARFMT == pMap->nWID
+ {
+ pCharFmt = (SwFmtCharFmt*)rItem.Clone(); // because rItem ist const...
+ pCharFmt->SetCharFmt(xStyle->GetCharFmt());
+ m_pDoc->SetDefault(*pCharFmt);
+ }
+ }
+ else
+ throw lang::IllegalArgumentException();
+ delete pDrop;
+ delete pCharFmt;
+ }
+ else
+ throw lang::IllegalArgumentException();
+ }
+ else
+ {
+ SfxPoolItem * pNewItem = rItem.Clone();
+ pNewItem->PutValue( aValue, pMap->nMemberId);
+ m_pDoc->SetDefault(*pNewItem);
+ delete pNewItem;
+ }
+}
+
+
+Any SAL_CALL SwXTextDefaults::getPropertyValue( const OUString& rPropertyName )
+ throw(UnknownPropertyException, WrappedTargetException, RuntimeException)
+{
+ SolarMutexGuard aGuard;
+ if (!m_pDoc)
+ throw RuntimeException();
+ const SfxItemPropertySimpleEntry *pMap = m_pPropSet->getPropertyMap()->getByName( rPropertyName );
+ if (!pMap)
+ throw UnknownPropertyException(OUString ( RTL_CONSTASCII_USTRINGPARAM ( "Unknown property: " ) ) + rPropertyName, static_cast < cppu::OWeakObject * > ( this ) );
+ Any aRet;
+ const SfxPoolItem& rItem = m_pDoc->GetDefault(pMap->nWID);
+ rItem.QueryValue( aRet, pMap->nMemberId );
+ return aRet;
+}
+
+
+void SAL_CALL SwXTextDefaults::addPropertyChangeListener( const OUString& /*rPropertyName*/, const uno::Reference< XPropertyChangeListener >& /*xListener*/ )
+ throw(UnknownPropertyException, WrappedTargetException, RuntimeException)
+{
+ DBG_WARNING ( "not implemented" );
+}
+
+
+void SAL_CALL SwXTextDefaults::removePropertyChangeListener( const OUString& /*rPropertyName*/, const uno::Reference< XPropertyChangeListener >& /*xListener*/ )
+ throw(UnknownPropertyException, WrappedTargetException, RuntimeException)
+{
+ DBG_WARNING ( "not implemented" );
+}
+
+
+void SAL_CALL SwXTextDefaults::addVetoableChangeListener( const OUString& /*rPropertyName*/, const uno::Reference< XVetoableChangeListener >& /*xListener*/ )
+ throw(UnknownPropertyException, WrappedTargetException, RuntimeException)
+{
+ DBG_WARNING ( "not implemented" );
+}
+
+
+void SAL_CALL SwXTextDefaults::removeVetoableChangeListener( const OUString& /*rPropertyName*/, const uno::Reference< XVetoableChangeListener >& /*xListener*/ )
+ throw(UnknownPropertyException, WrappedTargetException, RuntimeException)
+{
+ DBG_WARNING ( "not implemented" );
+}
+
+
+// XPropertyState
+PropertyState SAL_CALL SwXTextDefaults::getPropertyState( const OUString& rPropertyName )
+ throw(UnknownPropertyException, RuntimeException)
+{
+ SolarMutexGuard aGuard;
+ PropertyState eRet = PropertyState_DIRECT_VALUE;
+ if (!m_pDoc)
+ throw RuntimeException();
+ const SfxItemPropertySimpleEntry *pMap = m_pPropSet->getPropertyMap()->getByName( rPropertyName );
+ if (!pMap)
+ throw UnknownPropertyException(OUString ( RTL_CONSTASCII_USTRINGPARAM ( "Unknown property: " ) ) + rPropertyName, static_cast < cppu::OWeakObject * > ( this ) );
+
+ const SfxPoolItem& rItem = m_pDoc->GetDefault(pMap->nWID);
+ if (IsStaticDefaultItem ( &rItem ) )
+ eRet = PropertyState_DEFAULT_VALUE;
+ return eRet;
+}
+
+
+Sequence< PropertyState > SAL_CALL SwXTextDefaults::getPropertyStates( const Sequence< OUString >& rPropertyNames )
+ throw(UnknownPropertyException, RuntimeException)
+{
+ const sal_Int32 nCount = rPropertyNames.getLength();
+ const OUString * pNames = rPropertyNames.getConstArray();
+ Sequence < PropertyState > aRet ( nCount );
+ PropertyState *pState = aRet.getArray();
+
+ for ( sal_Int32 nIndex = 0; nIndex < nCount; nIndex++)
+ pState[nIndex] = getPropertyState( pNames[nIndex] );
+
+ return aRet;
+}
+
+
+void SAL_CALL SwXTextDefaults::setPropertyToDefault( const OUString& rPropertyName )
+ throw(UnknownPropertyException, RuntimeException)
+{
+ if (!m_pDoc)
+ throw RuntimeException();
+ const SfxItemPropertySimpleEntry *pMap = m_pPropSet->getPropertyMap()->getByName( rPropertyName );
+ if (!pMap)
+ throw UnknownPropertyException(OUString ( RTL_CONSTASCII_USTRINGPARAM ( "Unknown property: " ) ) + rPropertyName, static_cast < cppu::OWeakObject * > ( this ) );
+ if ( pMap->nFlags & PropertyAttribute::READONLY)
+ throw RuntimeException( OUString ( RTL_CONSTASCII_USTRINGPARAM ( "setPropertyToDefault: property is read-only: " ) ) + rPropertyName, static_cast < cppu::OWeakObject * > ( this ) );
+ SfxItemPool& rSet (m_pDoc->GetAttrPool());
+ rSet.ResetPoolDefaultItem ( pMap->nWID );
+}
+
+
+Any SAL_CALL SwXTextDefaults::getPropertyDefault( const OUString& rPropertyName )
+ throw(UnknownPropertyException, WrappedTargetException, RuntimeException)
+{
+ if (!m_pDoc)
+ throw RuntimeException();
+ const SfxItemPropertySimpleEntry *pMap = m_pPropSet->getPropertyMap()->getByName( rPropertyName );
+ if (!pMap)
+ throw UnknownPropertyException(OUString ( RTL_CONSTASCII_USTRINGPARAM ( "Unknown property: " ) ) + rPropertyName, static_cast < cppu::OWeakObject * > ( this ) );
+ Any aRet;
+ SfxItemPool& rSet (m_pDoc->GetAttrPool());
+ const SfxPoolItem *pItem = rSet.GetPoolDefaultItem ( pMap->nWID );
+ pItem->QueryValue( aRet, pMap->nMemberId );
+ return aRet;
+}
+
+
+rtl::OUString SAL_CALL SwXTextDefaults::getImplementationName( )
+ throw (RuntimeException)
+{
+ return C2U("SwXTextDefaults");
+}
+
+
+sal_Bool SAL_CALL SwXTextDefaults::supportsService( const ::rtl::OUString& rServiceName )
+ throw (RuntimeException)
+{
+ return rServiceName == C2U("com.sun.star.text.Defaults") ||
+ rServiceName == C2U("com.sun.star.style.CharacterProperties") ||
+ rServiceName == C2U("com.sun.star.style.CharacterPropertiesAsian") ||
+ rServiceName == C2U("com.sun.star.style.CharacterPropertiesComplex") ||
+ rServiceName == C2U("com.sun.star.style.ParagraphProperties") ||
+ rServiceName == C2U("com.sun.star.style.ParagraphPropertiesAsian") ||
+ rServiceName == C2U("com.sun.star.style.ParagraphPropertiesComplex");
+}
+
+
+uno::Sequence< ::rtl::OUString > SAL_CALL SwXTextDefaults::getSupportedServiceNames( )
+ throw (RuntimeException)
+{
+ uno::Sequence< OUString > aRet(7);
+ OUString* pArr = aRet.getArray();
+ *pArr++ = C2U("com.sun.star.text.Defaults");
+ *pArr++ = C2U("com.sun.star.style.CharacterProperties");
+ *pArr++ = C2U("com.sun.star.style.CharacterPropertiesAsian");
+ *pArr++ = C2U("com.sun.star.style.CharacterPropertiesComplex");
+ *pArr++ = C2U("com.sun.star.style.ParagraphProperties");
+ *pArr++ = C2U("com.sun.star.style.ParagraphPropertiesAsian");
+ *pArr++ = C2U("com.sun.star.style.ParagraphPropertiesComplex");
+ return aRet;
+}
+
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/unocore/TextCursorHelper.cxx b/sw/source/core/unocore/TextCursorHelper.cxx
new file mode 100644
index 000000000000..e72abba9c992
--- /dev/null
+++ b/sw/source/core/unocore/TextCursorHelper.cxx
@@ -0,0 +1,58 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+#include "TextCursorHelper.hxx"
+#include "unobaseclass.hxx"
+
+
+using namespace ::com::sun::star;
+
+const uno::Sequence< sal_Int8 > & OTextCursorHelper::getUnoTunnelId()
+{
+ static uno::Sequence< sal_Int8 > aSeq = ::CreateUnoTunnelId();
+ return aSeq;
+}
+
+//XUnoTunnel
+sal_Int64 SAL_CALL OTextCursorHelper::getSomething(
+ const uno::Sequence< sal_Int8 >& rId )
+ throw(uno::RuntimeException)
+{
+ if( rId.getLength() == 16
+ && 0 == rtl_compareMemory( getUnoTunnelId().getConstArray(),
+ rId.getConstArray(), 16 ) )
+ {
+ return sal::static_int_cast< sal_Int64 >( reinterpret_cast< sal_IntPtr >(this) );
+ }
+ return 0;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/unocore/XMLRangeHelper.cxx b/sw/source/core/unocore/XMLRangeHelper.cxx
new file mode 100644
index 000000000000..66684613c7e5
--- /dev/null
+++ b/sw/source/core/unocore/XMLRangeHelper.cxx
@@ -0,0 +1,415 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+#include "XMLRangeHelper.hxx"
+#include <unotools/charclass.hxx>
+#include <rtl/ustrbuf.hxx>
+
+#include <algorithm>
+#include <functional>
+
+using ::rtl::OUString;
+using ::rtl::OUStringBuffer;
+
+// ================================================================================
+
+namespace
+{
+/** unary function that escapes backslashes and single quotes in a sal_Unicode
+ array (which you can get from an OUString with getStr()) and puts the result
+ into the OUStringBuffer given in the CTOR
+ */
+class lcl_Escape : public ::std::unary_function< sal_Unicode, void >
+{
+public:
+ lcl_Escape( ::rtl::OUStringBuffer & aResultBuffer ) : m_aResultBuffer( aResultBuffer ) {}
+ void operator() ( sal_Unicode aChar )
+ {
+ static const sal_Unicode m_aQuote( '\'' );
+ static const sal_Unicode m_aBackslash( '\\' );
+
+ if( aChar == m_aQuote ||
+ aChar == m_aBackslash )
+ m_aResultBuffer.append( m_aBackslash );
+ m_aResultBuffer.append( aChar );
+ }
+
+private:
+ ::rtl::OUStringBuffer & m_aResultBuffer;
+};
+
+// ----------------------------------------
+
+/** unary function that removes backslash escapes in a sal_Unicode array (which
+ you can get from an OUString with getStr()) and puts the result into the
+ OUStringBuffer given in the CTOR
+ */
+class lcl_UnEscape : public ::std::unary_function< sal_Unicode, void >
+{
+public:
+ lcl_UnEscape( ::rtl::OUStringBuffer & aResultBuffer ) : m_aResultBuffer( aResultBuffer ) {}
+ void operator() ( sal_Unicode aChar )
+ {
+ static const sal_Unicode m_aBackslash( '\\' );
+
+ if( aChar != m_aBackslash )
+ m_aResultBuffer.append( aChar );
+ }
+
+private:
+ ::rtl::OUStringBuffer & m_aResultBuffer;
+};
+
+// ----------------------------------------
+
+OUStringBuffer lcl_getXMLStringForCell( const /*::chart::*/XMLRangeHelper::Cell & rCell )
+{
+ ::rtl::OUStringBuffer aBuffer;
+ if( rCell.empty())
+ return aBuffer;
+
+ sal_Int32 nCol = rCell.nColumn;
+ aBuffer.append( (sal_Unicode)'.' );
+ if( ! rCell.bRelativeColumn )
+ aBuffer.append( (sal_Unicode)'$' );
+
+ // get A, B, C, ..., AA, AB, ... representation of column number
+ if( nCol < 26 )
+ aBuffer.append( (sal_Unicode)('A' + nCol) );
+ else if( nCol < 702 )
+ {
+ aBuffer.append( (sal_Unicode)('A' + nCol / 26 - 1 ));
+ aBuffer.append( (sal_Unicode)('A' + nCol % 26) );
+ }
+ else // works for nCol <= 18,278
+ {
+ aBuffer.append( (sal_Unicode)('A' + nCol / 702 - 1 ));
+ aBuffer.append( (sal_Unicode)('A' + (nCol % 702) / 26 ));
+ aBuffer.append( (sal_Unicode)('A' + nCol % 26) );
+ }
+
+ // write row number as number
+ if( ! rCell.bRelativeRow )
+ aBuffer.append( (sal_Unicode)'$' );
+ aBuffer.append( rCell.nRow + (sal_Int32)1 );
+
+ return aBuffer;
+}
+
+void lcl_getSingleCellAddressFromXMLString(
+ const ::rtl::OUString& rXMLString,
+ sal_Int32 nStartPos, sal_Int32 nEndPos,
+ /*::chart::*/XMLRangeHelper::Cell & rOutCell )
+{
+ // expect "\$?[a-zA-Z]+\$?[1-9][0-9]*"
+ static const sal_Unicode aDollar( '$' );
+ static const sal_Unicode aLetterA( 'A' );
+
+ ::rtl::OUString aCellStr = rXMLString.copy( nStartPos, nEndPos - nStartPos + 1 ).toAsciiUpperCase();
+ const sal_Unicode* pStrArray = aCellStr.getStr();
+ sal_Int32 nLength = aCellStr.getLength();
+ sal_Int32 i = nLength - 1, nColumn = 0;
+
+ // parse number for row
+ while( CharClass::isAsciiDigit( pStrArray[ i ] ) && i >= 0 )
+ i--;
+ rOutCell.nRow = (aCellStr.copy( i + 1 )).toInt32() - 1;
+ // a dollar in XML means absolute (whereas in UI it means relative)
+ if( pStrArray[ i ] == aDollar )
+ {
+ i--;
+ rOutCell.bRelativeRow = false;
+ }
+ else
+ rOutCell.bRelativeRow = true;
+
+ // parse rest for column
+ sal_Int32 nPower = 1;
+ while( CharClass::isAsciiAlpha( pStrArray[ i ] ))
+ {
+ nColumn += (pStrArray[ i ] - aLetterA + 1) * nPower;
+ i--;
+ nPower *= 26;
+ }
+ rOutCell.nColumn = nColumn - 1;
+
+ rOutCell.bRelativeColumn = true;
+ if( i >= 0 &&
+ pStrArray[ i ] == aDollar )
+ rOutCell.bRelativeColumn = false;
+ rOutCell.bIsEmpty = false;
+}
+
+bool lcl_getCellAddressFromXMLString(
+ const ::rtl::OUString& rXMLString,
+ sal_Int32 nStartPos, sal_Int32 nEndPos,
+ /*::chart::*/XMLRangeHelper::Cell & rOutCell,
+ ::rtl::OUString& rOutTableName )
+{
+ static const sal_Unicode aDot( '.' );
+ static const sal_Unicode aQuote( '\'' );
+ static const sal_Unicode aBackslash( '\\' );
+
+ sal_Int32 nNextDelimiterPos = nStartPos;
+
+ sal_Int32 nDelimiterPos = nStartPos;
+ bool bInQuotation = false;
+ // parse table name
+ while( nDelimiterPos < nEndPos &&
+ ( bInQuotation || rXMLString[ nDelimiterPos ] != aDot ))
+ {
+ // skip escaped characters (with backslash)
+ if( rXMLString[ nDelimiterPos ] == aBackslash )
+ ++nDelimiterPos;
+ // toggle quotation mode when finding single quotes
+ else if( rXMLString[ nDelimiterPos ] == aQuote )
+ bInQuotation = ! bInQuotation;
+
+ ++nDelimiterPos;
+ }
+
+ if( nDelimiterPos == -1 ||
+ nDelimiterPos >= nEndPos )
+ {
+ return false;
+ }
+ if( nDelimiterPos > nStartPos )
+ {
+ // there is a table name before the address
+
+ ::rtl::OUStringBuffer aTableNameBuffer;
+ const sal_Unicode * pTableName = rXMLString.getStr();
+
+ // remove escapes from table name
+ ::std::for_each( pTableName + nStartPos,
+ pTableName + nDelimiterPos,
+ lcl_UnEscape( aTableNameBuffer ));
+
+ // unquote quoted table name
+ const sal_Unicode * pBuf = aTableNameBuffer.getStr();
+ if( pBuf[ 0 ] == aQuote &&
+ pBuf[ aTableNameBuffer.getLength() - 1 ] == aQuote )
+ {
+ ::rtl::OUString aName = aTableNameBuffer.makeStringAndClear();
+ rOutTableName = aName.copy( 1, aName.getLength() - 2 );
+ }
+ else
+ rOutTableName = aTableNameBuffer.makeStringAndClear();
+ }
+
+ for( sal_Int32 i = 0;
+ nNextDelimiterPos < nEndPos;
+ nDelimiterPos = nNextDelimiterPos, i++ )
+ {
+ nNextDelimiterPos = rXMLString.indexOf( aDot, nDelimiterPos + 1 );
+ if( nNextDelimiterPos == -1 ||
+ nNextDelimiterPos > nEndPos )
+ nNextDelimiterPos = nEndPos + 1;
+
+ if( i==0 )
+ // only take first cell
+ lcl_getSingleCellAddressFromXMLString(
+ rXMLString, nDelimiterPos + 1, nNextDelimiterPos - 1, rOutCell );
+ }
+
+ return true;
+}
+
+bool lcl_getCellRangeAddressFromXMLString(
+ const ::rtl::OUString& rXMLString,
+ sal_Int32 nStartPos, sal_Int32 nEndPos,
+ /*::chart::*/XMLRangeHelper::CellRange & rOutRange )
+{
+ bool bResult = true;
+ static const sal_Unicode aColon( ':' );
+ static const sal_Unicode aQuote( '\'' );
+ static const sal_Unicode aBackslash( '\\' );
+
+ sal_Int32 nDelimiterPos = nStartPos;
+ bool bInQuotation = false;
+ // parse table name
+ while( nDelimiterPos < nEndPos &&
+ ( bInQuotation || rXMLString[ nDelimiterPos ] != aColon ))
+ {
+ // skip escaped characters (with backslash)
+ if( rXMLString[ nDelimiterPos ] == aBackslash )
+ ++nDelimiterPos;
+ // toggle quotation mode when finding single quotes
+ else if( rXMLString[ nDelimiterPos ] == aQuote )
+ bInQuotation = ! bInQuotation;
+
+ ++nDelimiterPos;
+ }
+
+ if( nDelimiterPos == nEndPos )
+ {
+ // only one cell
+ bResult = lcl_getCellAddressFromXMLString( rXMLString, nStartPos, nEndPos,
+ rOutRange.aUpperLeft,
+ rOutRange.aTableName );
+ }
+ else
+ {
+ // range (separated by a colon)
+ bResult = lcl_getCellAddressFromXMLString( rXMLString, nStartPos, nDelimiterPos - 1,
+ rOutRange.aUpperLeft,
+ rOutRange.aTableName );
+ ::rtl::OUString sTableSecondName;
+ if( bResult )
+ {
+ bResult = lcl_getCellAddressFromXMLString( rXMLString, nDelimiterPos + 1, nEndPos,
+ rOutRange.aLowerRight,
+ sTableSecondName );
+ }
+ if( bResult &&
+ sTableSecondName.getLength() &&
+ ! sTableSecondName.equals( rOutRange.aTableName ))
+ bResult = false;
+ }
+
+ return bResult;
+}
+
+} // anonymous namespace
+
+// ================================================================================
+
+//namespace chart
+//{
+namespace XMLRangeHelper
+{
+
+CellRange getCellRangeFromXMLString( const OUString & rXMLString )
+{
+ static const sal_Unicode aSpace( ' ' );
+ static const sal_Unicode aQuote( '\'' );
+ static const sal_Unicode aDollar( '$' );
+ static const sal_Unicode aBackslash( '\\' );
+
+ sal_Int32 nStartPos = 0;
+ sal_Int32 nEndPos = nStartPos;
+ const sal_Int32 nLength = rXMLString.getLength();
+
+ // reset
+ CellRange aResult;
+
+ // iterate over different ranges
+ for( sal_Int32 i = 0;
+ nEndPos < nLength;
+ nStartPos = ++nEndPos, i++ )
+ {
+ // find start point of next range
+
+ // ignore leading '$'
+ if( rXMLString[ nEndPos ] == aDollar)
+ nEndPos++;
+
+ bool bInQuotation = false;
+ // parse range
+ while( nEndPos < nLength &&
+ ( bInQuotation || rXMLString[ nEndPos ] != aSpace ))
+ {
+ // skip escaped characters (with backslash)
+ if( rXMLString[ nEndPos ] == aBackslash )
+ ++nEndPos;
+ // toggle quotation mode when finding single quotes
+ else if( rXMLString[ nEndPos ] == aQuote )
+ bInQuotation = ! bInQuotation;
+
+ ++nEndPos;
+ }
+
+ if( ! lcl_getCellRangeAddressFromXMLString(
+ rXMLString,
+ nStartPos, nEndPos - 1,
+ aResult ))
+ {
+ // if an error occurred, bail out
+ return CellRange();
+ }
+ }
+
+ return aResult;
+}
+
+OUString getXMLStringFromCellRange( const CellRange & rRange )
+{
+ static const sal_Unicode aSpace( ' ' );
+ static const sal_Unicode aQuote( '\'' );
+
+ ::rtl::OUStringBuffer aBuffer;
+
+ if( (rRange.aTableName).getLength())
+ {
+ bool bNeedsEscaping = ( rRange.aTableName.indexOf( aQuote ) > -1 );
+ bool bNeedsQuoting = bNeedsEscaping || ( rRange.aTableName.indexOf( aSpace ) > -1 );
+
+ // quote table name if it contains spaces or quotes
+ if( bNeedsQuoting )
+ {
+ // leading quote
+ aBuffer.append( aQuote );
+
+ // escape existing quotes
+ if( bNeedsEscaping )
+ {
+ const sal_Unicode * pTableNameBeg = rRange.aTableName.getStr();
+
+ // append the quoted string at the buffer
+ ::std::for_each( pTableNameBeg,
+ pTableNameBeg + rRange.aTableName.getLength(),
+ lcl_Escape( aBuffer ) );
+ }
+ else
+ aBuffer.append( rRange.aTableName );
+
+ // final quote
+ aBuffer.append( aQuote );
+ }
+ else
+ aBuffer.append( rRange.aTableName );
+ }
+ aBuffer.append( lcl_getXMLStringForCell( rRange.aUpperLeft ));
+
+ if( ! rRange.aLowerRight.empty())
+ {
+ // we have a range (not a single cell)
+ aBuffer.append( sal_Unicode( ':' ));
+ aBuffer.append( lcl_getXMLStringForCell( rRange.aLowerRight ));
+ }
+
+ return aBuffer.makeStringAndClear();
+}
+
+} // namespace XMLRangeHelper
+//} // namespace chart
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/unocore/XMLRangeHelper.hxx b/sw/source/core/unocore/XMLRangeHelper.hxx
new file mode 100644
index 000000000000..0b4b34e57153
--- /dev/null
+++ b/sw/source/core/unocore/XMLRangeHelper.hxx
@@ -0,0 +1,81 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+//!!
+//!! This file is an exact copy of the same file in chart2 project
+//!!
+
+#ifndef XMLRANGEHELPER_HXX
+#define XMLRANGEHELPER_HXX
+
+#include <sal/types.h>
+#include <rtl/ustring.hxx>
+
+//namespace chart
+//{
+namespace XMLRangeHelper
+{
+
+struct Cell
+{
+ sal_Int32 nColumn;
+ sal_Int32 nRow;
+ bool bRelativeColumn;
+ bool bRelativeRow;
+ bool bIsEmpty;
+
+ Cell() :
+ nColumn(0),
+ nRow(0),
+ bRelativeColumn(false),
+ bRelativeRow(false),
+ bIsEmpty(true)
+ {}
+
+ inline bool empty() const { return bIsEmpty; }
+};
+
+struct CellRange
+{
+ Cell aUpperLeft;
+ Cell aLowerRight;
+ ::rtl::OUString aTableName;
+};
+
+CellRange getCellRangeFromXMLString( const ::rtl::OUString & rXMLString );
+
+::rtl::OUString getXMLStringFromCellRange( const CellRange & rRange );
+
+
+} // namespace XMLRangeHelper
+//} // namespace chart
+
+// XMLRANGEHELPER_HXX
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/unocore/swunohelper.cxx b/sw/source/core/unocore/swunohelper.cxx
new file mode 100644
index 000000000000..add5f34a56b5
--- /dev/null
+++ b/sw/source/core/unocore/swunohelper.cxx
@@ -0,0 +1,291 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+#define _SVSTDARR_STRINGS
+#include <com/sun/star/uno/Sequence.h>
+#include <com/sun/star/uno/Exception.hpp>
+#include <com/sun/star/ucb/XContentIdentifier.hpp>
+#include <com/sun/star/ucb/XContentProvider.hpp>
+#include <com/sun/star/ucb/XCommandEnvironment.hpp>
+#include <com/sun/star/ucb/TransferInfo.hpp>
+#include <com/sun/star/ucb/NameClash.hdl>
+#include <com/sun/star/sdbc/XResultSet.hpp>
+#include <com/sun/star/sdbc/XRow.hpp>
+#include <com/sun/star/lang/XMultiServiceFactory.hpp>
+#include <comphelper/processfactory.hxx>
+#include <comphelper/types.hxx>
+#include <tools/urlobj.hxx>
+#include <tools/datetime.hxx>
+#include <tools/debug.hxx>
+#include <ucbhelper/contentidentifier.hxx>
+#include <ucbhelper/contentbroker.hxx>
+#include <ucbhelper/content.hxx>
+#include <svl/svstdarr.hxx>
+#include <swunohelper.hxx>
+#include <swunodef.hxx>
+
+namespace SWUnoHelper {
+
+sal_Int32 GetEnumAsInt32( const UNO_NMSPC::Any& rVal )
+{
+ sal_Int32 eVal;
+ try
+ {
+ eVal = comphelper::getEnumAsINT32( rVal );
+ }
+ catch( UNO_NMSPC::Exception & )
+ {
+ eVal = 0;
+ OSL_FAIL( "can't get EnumAsInt32" );
+ }
+ return eVal;
+}
+
+
+// methods for UCB actions
+sal_Bool UCB_DeleteFile( const String& rURL )
+{
+ sal_Bool bRemoved;
+ try
+ {
+ ucbhelper::Content aTempContent( rURL,
+ STAR_REFERENCE( ucb::XCommandEnvironment )());
+ aTempContent.executeCommand(
+ rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("delete")),
+ UNO_NMSPC::makeAny( sal_Bool( sal_True ) ) );
+ bRemoved = sal_True;
+ }
+ catch( UNO_NMSPC::Exception& )
+ {
+ bRemoved = sal_False;
+ OSL_FAIL( "Exeception from executeCommand( delete )" );
+ }
+ return bRemoved;
+}
+
+sal_Bool UCB_CopyFile( const String& rURL, const String& rNewURL, sal_Bool bCopyIsMove )
+{
+ sal_Bool bCopyCompleted = sal_True;
+ try
+ {
+ INetURLObject aURL( rNewURL );
+ String sName( aURL.GetName() );
+ aURL.removeSegment();
+ String sMainURL( aURL.GetMainURL(INetURLObject::NO_DECODE) );
+
+ ucbhelper::Content aTempContent( sMainURL,
+ STAR_REFERENCE( ucb::XCommandEnvironment )());
+
+ UNO_NMSPC::Any aAny;
+ STAR_NMSPC::ucb::TransferInfo aInfo;
+ aInfo.NameClash = STAR_NMSPC::ucb::NameClash::ERROR;
+ aInfo.NewTitle = sName;
+ aInfo.SourceURL = rURL;
+ aInfo.MoveData = bCopyIsMove;
+ aAny <<= aInfo;
+ aTempContent.executeCommand(
+ rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("transfer")),
+ aAny );
+ }
+ catch( UNO_NMSPC::Exception& )
+ {
+ OSL_FAIL( "Exeception from executeCommand( transfer )" );
+ bCopyCompleted = sal_False;
+ }
+ return bCopyCompleted;
+}
+
+sal_Bool UCB_IsCaseSensitiveFileName( const String& rURL )
+{
+ sal_Bool bCaseSensitive;
+ try
+ {
+ STAR_REFERENCE( lang::XMultiServiceFactory ) xMSF =
+ comphelper::getProcessServiceFactory();
+
+ INetURLObject aTempObj( rURL );
+ aTempObj.SetBase( aTempObj.GetBase().toAsciiLowerCase() );
+ STAR_REFERENCE( ucb::XContentIdentifier ) xRef1 = new
+ ucbhelper::ContentIdentifier( xMSF,
+ aTempObj.GetMainURL( INetURLObject::NO_DECODE ));
+
+ aTempObj.SetBase(aTempObj.GetBase().toAsciiUpperCase());
+ STAR_REFERENCE( ucb::XContentIdentifier ) xRef2 = new
+ ucbhelper::ContentIdentifier( xMSF,
+ aTempObj.GetMainURL( INetURLObject::NO_DECODE ));
+
+ STAR_REFERENCE( ucb::XContentProvider ) xProv =
+ ucbhelper::ContentBroker::get()->getContentProviderInterface();
+
+ sal_Int32 nCompare = xProv->compareContentIds( xRef1, xRef2 );
+ bCaseSensitive = 0 != nCompare;
+ }
+ catch( UNO_NMSPC::Exception& )
+ {
+ bCaseSensitive = sal_False;
+ OSL_FAIL( "Exeception from compareContentIds()" );
+ }
+ return bCaseSensitive;
+}
+
+sal_Bool UCB_IsReadOnlyFileName( const String& rURL )
+{
+ sal_Bool bIsReadOnly = sal_False;
+ try
+ {
+ ucbhelper::Content aCnt( rURL, STAR_REFERENCE( ucb::XCommandEnvironment )());
+ UNO_NMSPC::Any aAny = aCnt.getPropertyValue(
+ rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("IsReadOnly")));
+ if(aAny.hasValue())
+ bIsReadOnly = *(sal_Bool*)aAny.getValue();
+ }
+ catch( UNO_NMSPC::Exception& )
+ {
+ bIsReadOnly = sal_False;
+ }
+ return bIsReadOnly;
+}
+
+sal_Bool UCB_IsFile( const String& rURL )
+{
+ sal_Bool bExists = sal_False;
+ try
+ {
+ ::ucbhelper::Content aContent( rURL, STAR_REFERENCE( ucb::XCommandEnvironment )() );
+ bExists = aContent.isDocument();
+ }
+ catch (UNO_NMSPC::Exception &)
+ {
+ }
+ return bExists;
+}
+
+sal_Bool UCB_IsDirectory( const String& rURL )
+{
+ sal_Bool bExists = sal_False;
+ try
+ {
+ ::ucbhelper::Content aContent( rURL, STAR_REFERENCE( ucb::XCommandEnvironment )() );
+ bExists = aContent.isFolder();
+ }
+ catch (UNO_NMSPC::Exception &)
+ {
+ }
+ return bExists;
+}
+
+ // get a list of files from the folder of the URL
+ // options: pExtension = 0 -> all, else this specific extension
+ // pDateTime != 0 -> returns also the modified date/time of
+ // the files in a SvPtrarr -->
+ // !! objects must be deleted from the caller!!
+sal_Bool UCB_GetFileListOfFolder( const String& rURL, SvStrings& rList,
+ const String* pExtension,
+ SvPtrarr* pDateTimeList )
+{
+ sal_Bool bOk = sal_False;
+ try
+ {
+ ucbhelper::Content aCnt( rURL, STAR_REFERENCE( ucb::XCommandEnvironment )());
+ STAR_REFERENCE( sdbc::XResultSet ) xResultSet;
+
+ sal_uInt16 nSeqSize = pDateTimeList ? 2 : 1;
+ UNO_NMSPC::Sequence < rtl::OUString > aProps( nSeqSize );
+ rtl::OUString* pProps = aProps.getArray();
+ pProps[ 0 ] = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Title"));
+ if( pDateTimeList )
+ pProps[ 1 ] = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("DateModified"));
+
+ try
+ {
+ xResultSet = aCnt.createCursor( aProps, ::ucbhelper::INCLUDE_DOCUMENTS_ONLY );
+ }
+ catch( UNO_NMSPC::Exception& )
+ {
+ DBG_ERRORFILE( "create cursor failed!" );
+ }
+
+ if( xResultSet.is() )
+ {
+ STAR_REFERENCE( sdbc::XRow ) xRow( xResultSet, UNO_NMSPC::UNO_QUERY );
+ xub_StrLen nExtLen = pExtension ? pExtension->Len() : 0;
+ try
+ {
+ if( xResultSet->first() )
+ {
+ do {
+ String sTitle( xRow->getString( 1 ) );
+ if( !nExtLen ||
+ ( sTitle.Len() > nExtLen &&
+ sTitle.Equals( *pExtension,
+ sTitle.Len() - nExtLen, nExtLen )) )
+ {
+ String* pStr = new String( sTitle );
+ rList.Insert( pStr, rList.Count() );
+
+ if( pDateTimeList )
+ {
+ STAR_NMSPC::util::DateTime aStamp = xRow->getTimestamp(2);
+ ::DateTime* pDateTime = new ::DateTime(
+ ::Date( aStamp.Day,
+ aStamp.Month,
+ aStamp.Year ),
+ ::Time( aStamp.Hours,
+ aStamp.Minutes,
+ aStamp.Seconds,
+ aStamp.HundredthSeconds ));
+ void* p = pDateTime;
+ pDateTimeList->Insert( p,
+ pDateTimeList->Count() );
+ }
+ }
+
+ } while( xResultSet->next() );
+ }
+ bOk = sal_True;
+ }
+ catch( UNO_NMSPC::Exception& )
+ {
+ DBG_ERRORFILE( "Exception caught!" );
+ }
+ }
+ }
+ catch( UNO_NMSPC::Exception& )
+ {
+ DBG_ERRORFILE( "Exception caught!" );
+ bOk = sal_False;
+ }
+ return bOk;
+}
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/unocore/unobkm.cxx b/sw/source/core/unocore/unobkm.cxx
new file mode 100644
index 000000000000..d2fc151e5e5c
--- /dev/null
+++ b/sw/source/core/unocore/unobkm.cxx
@@ -0,0 +1,734 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+#include <unobookmark.hxx>
+#include <osl/mutex.hxx>
+#include <vcl/svapp.hxx>
+
+#include <TextCursorHelper.hxx>
+#include <unotextrange.hxx>
+#include <unomap.hxx>
+#include <unoprnms.hxx>
+#include <unoevtlstnr.hxx>
+#include <IMark.hxx>
+#include <crossrefbookmark.hxx>
+#include <doc.hxx>
+#include <IDocumentUndoRedo.hxx>
+#include <docary.hxx>
+#include <swundo.hxx>
+#include <comcore.hrc>
+#include <SwRewriter.hxx>
+#include <docsh.hxx>
+#include <xmloff/odffields.hxx>
+
+using namespace ::sw::mark;
+using namespace ::com::sun::star;
+using ::rtl::OUString;
+
+
+namespace
+{
+ static OUString lcl_QuoteName(const OUString& rName)
+ {
+ static const OUString sStart = OUString(String(SW_RES(STR_START_QUOTE)));
+ static const OUString sEnd = OUString(String(SW_RES(STR_END_QUOTE)));
+ ::rtl::OUStringBuffer sBuf(64);
+ return sBuf.append(sStart).append(rName).append(sEnd).makeStringAndClear();
+ }
+}
+
+/******************************************************************
+ * SwXBookmark
+ ******************************************************************/
+
+class SwXBookmark::Impl
+ : public SwClient
+{
+
+public:
+ SwEventListenerContainer m_ListenerContainer;
+ SwDoc * m_pDoc;
+ ::sw::mark::IMark * m_pRegisteredBookmark;
+ ::rtl::OUString m_sMarkName;
+
+
+ Impl( SwXBookmark & rThis,
+ SwDoc *const pDoc, ::sw::mark::IMark *const /*pBookmark*/)
+ : SwClient()
+ , m_ListenerContainer(static_cast< ::cppu::OWeakObject* >(&rThis))
+ , m_pDoc(pDoc)
+ , m_pRegisteredBookmark(0)
+ {
+ // DO NOT regiserInMark here! (because SetXBookmark would delete rThis)
+ }
+
+ void registerInMark(SwXBookmark & rThis, ::sw::mark::IMark *const pBkmk);
+protected:
+ // SwClient
+ virtual void Modify( const SfxPoolItem *pOld, const SfxPoolItem *pNew);
+
+};
+
+void SwXBookmark::Impl::Modify(const SfxPoolItem *pOld, const SfxPoolItem *pNew)
+{
+ ClientModify(this, pOld, pNew);
+ if (!GetRegisteredIn())
+ {
+ m_pRegisteredBookmark = NULL;
+ m_pDoc = NULL;
+ m_ListenerContainer.Disposing();
+ }
+}
+
+void SwXBookmark::Impl::registerInMark(SwXBookmark & rThis,
+ ::sw::mark::IMark *const pBkmk)
+{
+ if (pBkmk)
+ {
+ pBkmk->Add(this);
+ ::sw::mark::MarkBase *const pMarkBase(
+ dynamic_cast< ::sw::mark::MarkBase * >(pBkmk));
+ OSL_ENSURE(pMarkBase, "registerInMark: no MarkBase?");
+ if (pMarkBase)
+ {
+ const uno::Reference<text::XTextContent> xBookmark(& rThis);
+ pMarkBase->SetXBookmark(xBookmark);
+ }
+ }
+ else if (m_pRegisteredBookmark)
+ {
+ m_sMarkName = m_pRegisteredBookmark->GetName();
+ m_pRegisteredBookmark->Remove(this);
+ }
+ m_pRegisteredBookmark = pBkmk;
+}
+
+void SwXBookmark::registerInMark(SwXBookmark & rThis,
+ ::sw::mark::IMark *const pBkmk)
+{
+ m_pImpl->registerInMark( rThis, pBkmk );
+}
+
+const ::sw::mark::IMark* SwXBookmark::GetBookmark() const
+{
+ return m_pImpl->m_pRegisteredBookmark;
+}
+
+SwXBookmark::SwXBookmark(::sw::mark::IMark *const pBkmk, SwDoc *const pDoc)
+ : m_pImpl( new SwXBookmark::Impl(*this, pDoc, pBkmk) )
+{
+}
+
+SwXBookmark::SwXBookmark()
+ : m_pImpl( new SwXBookmark::Impl(*this, 0, 0) )
+{
+}
+
+SwXBookmark::~SwXBookmark()
+{
+}
+
+uno::Reference<text::XTextContent>
+SwXBookmark::CreateXBookmark(SwDoc & rDoc, ::sw::mark::IMark & rBookmark)
+{
+ // #i105557#: do not iterate over the registered clients: race condition
+ ::sw::mark::MarkBase *const pMarkBase(
+ dynamic_cast< ::sw::mark::MarkBase * >(&rBookmark));
+ OSL_ENSURE(pMarkBase, "CreateXBookmark: no MarkBase?");
+ if (!pMarkBase) { return 0; }
+ uno::Reference<text::XTextContent> xBookmark(pMarkBase->GetXBookmark());
+ if (!xBookmark.is())
+ {
+ // FIXME: These belong in XTextFieldsSupplier
+ //if (dynamic_cast< ::sw::mark::TextFieldmark* >(&rBkmk))
+ // pXBkmk = new SwXFieldmark(false, &rBkmk, pDoc);
+ //else if (dynamic_cast< ::sw::mark::CheckboxFieldmark* >(&rBkmk))
+ // pXBkmk = new SwXFieldmark(true, &rBkmk, pDoc);
+ //else
+ OSL_ENSURE(
+ dynamic_cast< ::sw::mark::IBookmark* >(&rBookmark),
+ "<SwXBookmark::GetObject(..)>"
+ "SwXBookmark requested for non-bookmark mark.");
+ SwXBookmark *const pXBookmark = new SwXBookmark(&rBookmark, &rDoc);
+ xBookmark.set(pXBookmark);
+ pXBookmark->m_pImpl->registerInMark(*pXBookmark, pMarkBase);
+ }
+ return xBookmark;
+}
+
+::sw::mark::IMark const* SwXBookmark::GetBookmarkInDoc(SwDoc const*const pDoc,
+ const uno::Reference< lang::XUnoTunnel> & xUT)
+{
+ SwXBookmark *const pXBkm(
+ ::sw::UnoTunnelGetImplementation<SwXBookmark>(xUT));
+ if (pXBkm && (pDoc == pXBkm->m_pImpl->m_pDoc))
+ {
+ return pXBkm->m_pImpl->m_pRegisteredBookmark;
+ }
+ return 0;
+}
+
+const uno::Sequence< sal_Int8 > & SwXBookmark::getUnoTunnelId()
+{
+ static uno::Sequence< sal_Int8 > aSeq = ::CreateUnoTunnelId();
+ return aSeq;
+}
+
+sal_Int64 SAL_CALL
+SwXBookmark::getSomething(const uno::Sequence< sal_Int8 >& rId)
+throw (uno::RuntimeException)
+{
+ return ::sw::UnoTunnelImpl<SwXBookmark>(rId, this);
+}
+
+void SwXBookmark::attachToRangeEx(
+ const uno::Reference< text::XTextRange > & xTextRange,
+ IDocumentMarkAccess::MarkType eType)
+throw (lang::IllegalArgumentException, uno::RuntimeException)
+{
+ if (m_pImpl->m_pRegisteredBookmark)
+ {
+ throw uno::RuntimeException();
+ }
+
+ const uno::Reference<lang::XUnoTunnel> xRangeTunnel(
+ xTextRange, uno::UNO_QUERY);
+ SwXTextRange* pRange = 0;
+ OTextCursorHelper* pCursor = 0;
+ if(xRangeTunnel.is())
+ {
+ pRange = ::sw::UnoTunnelGetImplementation<SwXTextRange>(xRangeTunnel);
+ pCursor =
+ ::sw::UnoTunnelGetImplementation<OTextCursorHelper>(xRangeTunnel);
+ }
+
+ SwDoc *const pDoc =
+ (pRange) ? pRange->GetDoc() : ((pCursor) ? pCursor->GetDoc() : 0);
+ if (!pDoc)
+ {
+ throw lang::IllegalArgumentException();
+ }
+
+ m_pImpl->m_pDoc = pDoc;
+ SwUnoInternalPaM aPam(*m_pImpl->m_pDoc);
+ ::sw::XTextRangeToSwPaM(aPam, xTextRange);
+ UnoActionContext aCont(m_pImpl->m_pDoc);
+ if (!m_pImpl->m_sMarkName.getLength())
+ {
+ m_pImpl->m_sMarkName = OUString(RTL_CONSTASCII_USTRINGPARAM("Bookmark"));
+ }
+ if ((eType == IDocumentMarkAccess::BOOKMARK) &&
+ ::sw::mark::CrossRefNumItemBookmark::IsLegalName(m_pImpl->m_sMarkName))
+ {
+ eType = IDocumentMarkAccess::CROSSREF_NUMITEM_BOOKMARK;
+ }
+ else if ((eType == IDocumentMarkAccess::BOOKMARK) &&
+ ::sw::mark::CrossRefHeadingBookmark::IsLegalName(m_pImpl->m_sMarkName))
+ {
+ eType = IDocumentMarkAccess::CROSSREF_HEADING_BOOKMARK;
+ }
+ m_pImpl->registerInMark(*this,
+ m_pImpl->m_pDoc->getIDocumentMarkAccess()->makeMark(
+ aPam, m_pImpl->m_sMarkName, eType));
+ // --> OD 2007-10-23 #i81002#
+ // Check, if bookmark has been created.
+ // E.g., the creation of a cross-reference bookmark is suppress,
+ // if the PaM isn't a valid one for cross-reference bookmarks.
+ if (!m_pImpl->m_pRegisteredBookmark)
+ {
+ OSL_FAIL("<SwXBookmark::attachToRange(..)>"
+ " - could not create Mark.");
+ throw lang::IllegalArgumentException();
+ }
+ // <--
+}
+
+void SwXBookmark::attachToRange(
+ const uno::Reference< text::XTextRange > & xTextRange)
+throw (lang::IllegalArgumentException, uno::RuntimeException)
+{
+ attachToRangeEx(xTextRange, IDocumentMarkAccess::BOOKMARK);
+}
+
+void SAL_CALL
+SwXBookmark::attach(const uno::Reference< text::XTextRange > & xTextRange)
+throw (lang::IllegalArgumentException, uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+ attachToRange( xTextRange );
+}
+
+uno::Reference< text::XTextRange > SAL_CALL
+SwXBookmark::getAnchor() throw (uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+
+ if (!m_pImpl->m_pRegisteredBookmark)
+ {
+ throw uno::RuntimeException();
+ }
+ return SwXTextRange::CreateXTextRange(
+ *m_pImpl->m_pDoc,
+ m_pImpl->m_pRegisteredBookmark->GetMarkPos(),
+ (m_pImpl->m_pRegisteredBookmark->IsExpanded())
+ ? &m_pImpl->m_pRegisteredBookmark->GetOtherMarkPos() : NULL);
+}
+
+void SAL_CALL SwXBookmark::dispose() throw (uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+ if (m_pImpl->m_pRegisteredBookmark)
+ {
+ m_pImpl->m_pDoc->getIDocumentMarkAccess()->deleteMark(
+ m_pImpl->m_pRegisteredBookmark);
+ }
+}
+
+void SAL_CALL SwXBookmark::addEventListener(
+ const uno::Reference< lang::XEventListener > & xListener)
+throw (uno::RuntimeException)
+{
+ SolarMutexGuard g;
+
+ if (!m_pImpl->m_pRegisteredBookmark)
+ {
+ throw uno::RuntimeException();
+ }
+ m_pImpl->m_ListenerContainer.AddListener(xListener);
+}
+
+void SAL_CALL SwXBookmark::removeEventListener(
+ const uno::Reference< lang::XEventListener > & xListener)
+throw (uno::RuntimeException)
+{
+ SolarMutexGuard g;
+
+ if (!m_pImpl->m_pRegisteredBookmark ||
+ !m_pImpl->m_ListenerContainer.RemoveListener(xListener))
+ {
+ throw uno::RuntimeException();
+ }
+}
+
+OUString SAL_CALL SwXBookmark::getName()
+throw (uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+
+ return (m_pImpl->m_pRegisteredBookmark)
+ ? m_pImpl->m_pRegisteredBookmark->GetName()
+ : m_pImpl->m_sMarkName;
+}
+
+void SAL_CALL SwXBookmark::setName(const OUString& rName)
+throw (uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+
+ if (!m_pImpl->m_pRegisteredBookmark)
+ {
+ m_pImpl->m_sMarkName = rName;
+ }
+ if (!m_pImpl->m_pRegisteredBookmark || (getName() == rName))
+ {
+ return;
+ }
+ IDocumentMarkAccess *const pMarkAccess =
+ m_pImpl->m_pDoc->getIDocumentMarkAccess();
+ if(pMarkAccess->findMark(rName) != pMarkAccess->getMarksEnd())
+ {
+ throw uno::RuntimeException();
+ }
+
+ SwPaM aPam(m_pImpl->m_pRegisteredBookmark->GetMarkPos());
+ if (m_pImpl->m_pRegisteredBookmark->IsExpanded())
+ {
+ aPam.SetMark();
+ *aPam.GetMark() = m_pImpl->m_pRegisteredBookmark->GetOtherMarkPos();
+ }
+
+ SwRewriter aRewriter;
+ aRewriter.AddRule(UNDO_ARG1, lcl_QuoteName(getName()));
+ aRewriter.AddRule(UNDO_ARG2, SW_RES(STR_YIELDS));
+ aRewriter.AddRule(UNDO_ARG3, lcl_QuoteName(rName));
+
+ m_pImpl->m_pDoc->GetIDocumentUndoRedo().StartUndo(
+ UNDO_BOOKMARK_RENAME, &aRewriter);
+ pMarkAccess->renameMark(m_pImpl->m_pRegisteredBookmark, rName);
+ m_pImpl->m_pDoc->GetIDocumentUndoRedo().EndUndo(
+ UNDO_BOOKMARK_RENAME, &aRewriter);
+}
+
+OUString SAL_CALL
+SwXBookmark::getImplementationName() throw (uno::RuntimeException)
+{
+ return OUString(RTL_CONSTASCII_USTRINGPARAM("SwXBookmark"));
+}
+
+static char const*const g_ServicesBookmark[] =
+{
+ "com.sun.star.text.TextContent",
+ "com.sun.star.text.Bookmark",
+ "com.sun.star.document.LinkTarget",
+};
+static const size_t g_nServicesBookmark(
+ SAL_N_ELEMENTS(g_ServicesBookmark));
+
+sal_Bool SAL_CALL SwXBookmark::supportsService(const OUString& rServiceName)
+throw (uno::RuntimeException)
+{
+ return ::sw::SupportsServiceImpl(
+ g_nServicesBookmark, g_ServicesBookmark, rServiceName);
+}
+
+uno::Sequence< OUString > SAL_CALL
+SwXBookmark::getSupportedServiceNames() throw (uno::RuntimeException)
+{
+ return ::sw::GetSupportedServiceNamesImpl(
+ g_nServicesBookmark, g_ServicesBookmark);
+}
+
+// MetadatableMixin
+::sfx2::Metadatable* SwXBookmark::GetCoreObject()
+{
+ return dynamic_cast< ::sfx2::Metadatable* >(m_pImpl->m_pRegisteredBookmark);
+}
+
+uno::Reference<frame::XModel> SwXBookmark::GetModel()
+{
+ if (m_pImpl->m_pDoc)
+ {
+ SwDocShell const * const pShell( m_pImpl->m_pDoc->GetDocShell() );
+ return (pShell) ? pShell->GetModel() : 0;
+ }
+ return 0;
+}
+
+
+uno::Reference< beans::XPropertySetInfo > SAL_CALL
+SwXBookmark::getPropertySetInfo() throw (uno::RuntimeException)
+{
+ SolarMutexGuard g;
+
+ static uno::Reference< beans::XPropertySetInfo > xRef(
+ aSwMapProvider.GetPropertySet(PROPERTY_MAP_BOOKMARK)
+ ->getPropertySetInfo() );
+ return xRef;
+}
+
+void SAL_CALL
+SwXBookmark::setPropertyValue(const OUString& PropertyName,
+ const uno::Any& /*rValue*/)
+throw (beans::UnknownPropertyException, beans::PropertyVetoException,
+ lang::IllegalArgumentException, lang::WrappedTargetException,
+ uno::RuntimeException)
+{
+ // nothing to set here
+ throw lang::IllegalArgumentException( ::rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM("Property is read-only: "))
+ + PropertyName, static_cast< cppu::OWeakObject * >(this), 0 );
+}
+
+uno::Any SAL_CALL SwXBookmark::getPropertyValue(const OUString& rPropertyName)
+throw (beans::UnknownPropertyException, lang::WrappedTargetException,
+ uno::RuntimeException)
+{
+ SolarMutexGuard g;
+
+ uno::Any aRet;
+ if (! ::sw::GetDefaultTextContentValue(aRet, rPropertyName))
+ {
+ if(rPropertyName.equalsAsciiL( SW_PROP_NAME(UNO_LINK_DISPLAY_NAME)))
+ {
+ aRet <<= getName();
+ }
+ }
+ return aRet;
+}
+
+void SAL_CALL
+SwXBookmark::addPropertyChangeListener(
+ const ::rtl::OUString& /*rPropertyName*/,
+ const uno::Reference< beans::XPropertyChangeListener >& /*xListener*/)
+throw (beans::UnknownPropertyException, lang::WrappedTargetException,
+ uno::RuntimeException)
+{
+ OSL_FAIL("SwXBookmark::addPropertyChangeListener(): not implemented");
+}
+
+void SAL_CALL
+SwXBookmark::removePropertyChangeListener(
+ const ::rtl::OUString& /*rPropertyName*/,
+ const uno::Reference< beans::XPropertyChangeListener >& /*xListener*/)
+throw (beans::UnknownPropertyException, lang::WrappedTargetException,
+ uno::RuntimeException)
+{
+ OSL_FAIL("SwXBookmark::removePropertyChangeListener(): not implemented");
+}
+
+void SAL_CALL
+SwXBookmark::addVetoableChangeListener(
+ const ::rtl::OUString& /*rPropertyName*/,
+ const uno::Reference< beans::XVetoableChangeListener >& /*xListener*/)
+throw (beans::UnknownPropertyException, lang::WrappedTargetException,
+ uno::RuntimeException)
+{
+ OSL_FAIL("SwXBookmark::addVetoableChangeListener(): not implemented");
+}
+
+void SAL_CALL
+SwXBookmark::removeVetoableChangeListener(
+ const ::rtl::OUString& /*rPropertyName*/,
+ const uno::Reference< beans::XVetoableChangeListener >& /*xListener*/)
+throw (beans::UnknownPropertyException, lang::WrappedTargetException,
+ uno::RuntimeException)
+{
+ OSL_FAIL("SwXBookmark::removeVetoableChangeListener(): not implemented");
+}
+
+/******************************************************************
+ * SwXFieldmark
+ ******************************************************************/
+
+SwXFieldmark::SwXFieldmark(bool _isReplacementObject, ::sw::mark::IMark* pBkm, SwDoc* pDc)
+ : SwXFieldmark_Base(pBkm, pDc)
+ , isReplacementObject(_isReplacementObject)
+{ }
+
+void SwXFieldmarkParameters::insertByName(const OUString& aName, const uno::Any& aElement)
+ throw (lang::IllegalArgumentException, container::ElementExistException, lang::WrappedTargetException, uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+ IFieldmark::parameter_map_t* pParameters = getCoreParameters();
+ if(pParameters->find(aName) != pParameters->end())
+ throw container::ElementExistException();
+ (*pParameters)[aName] = aElement;
+}
+
+void SwXFieldmarkParameters::removeByName(const OUString& aName)
+ throw (container::NoSuchElementException, lang::WrappedTargetException, uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+ if(!getCoreParameters()->erase(aName))
+ throw container::NoSuchElementException();
+}
+
+void SwXFieldmarkParameters::replaceByName(const OUString& aName, const uno::Any& aElement)
+ throw (lang::IllegalArgumentException, container::NoSuchElementException, lang::WrappedTargetException, uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+ IFieldmark::parameter_map_t* pParameters = getCoreParameters();
+ IFieldmark::parameter_map_t::iterator pEntry = pParameters->find(aName);
+ if(pEntry == pParameters->end())
+ throw container::NoSuchElementException();
+ pEntry->second = aElement;
+}
+
+uno::Any SwXFieldmarkParameters::getByName(const OUString& aName)
+ throw (container::NoSuchElementException, lang::WrappedTargetException, uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+ IFieldmark::parameter_map_t* pParameters = getCoreParameters();
+ IFieldmark::parameter_map_t::iterator pEntry = pParameters->find(aName);
+ if(pEntry == pParameters->end())
+ throw container::NoSuchElementException();
+ return pEntry->second;
+}
+
+uno::Sequence<OUString> SwXFieldmarkParameters::getElementNames()
+ throw (uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+ IFieldmark::parameter_map_t* pParameters = getCoreParameters();
+ uno::Sequence<OUString> vResult(pParameters->size());
+ OUString* pOutEntry = vResult.getArray();
+ for(IFieldmark::parameter_map_t::iterator pEntry = pParameters->begin(); pEntry!=pParameters->end(); ++pEntry, ++pOutEntry)
+ *pOutEntry = pEntry->first;
+ return vResult;
+}
+
+::sal_Bool SwXFieldmarkParameters::hasByName(const OUString& aName)
+ throw (uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+ IFieldmark::parameter_map_t* pParameters = getCoreParameters();
+ return (pParameters->find(aName) != pParameters->end());
+}
+
+uno::Type SwXFieldmarkParameters::getElementType()
+ throw (uno::RuntimeException)
+{
+ return ::cppu::UnoType< ::cppu::UnoVoidType>::get();
+}
+
+::sal_Bool SwXFieldmarkParameters::hasElements()
+ throw (uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+ return !getCoreParameters()->empty();
+}
+
+void SwXFieldmarkParameters::Modify(const SfxPoolItem *pOld, const SfxPoolItem *pNew)
+{
+ ClientModify(this, pOld, pNew);
+}
+
+
+IFieldmark::parameter_map_t* SwXFieldmarkParameters::getCoreParameters()
+ throw (uno::RuntimeException)
+{
+ const IFieldmark* pFieldmark = dynamic_cast< const IFieldmark* >(GetRegisteredIn());
+ if(!pFieldmark)
+ throw uno::RuntimeException();
+ return const_cast< IFieldmark* >(pFieldmark)->GetParameters();
+}
+
+
+void SwXFieldmark::attachToRange( const uno::Reference < text::XTextRange >& xTextRange )
+ throw(lang::IllegalArgumentException, uno::RuntimeException)
+{
+
+ attachToRangeEx( xTextRange,
+ ( isReplacementObject ? IDocumentMarkAccess::CHECKBOX_FIELDMARK : IDocumentMarkAccess::TEXT_FIELDMARK ) );
+}
+
+::rtl::OUString SwXFieldmark::getFieldType(void)
+ throw(uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+ const IFieldmark *pBkm = dynamic_cast<const IFieldmark*>(GetBookmark());
+ if(!pBkm)
+ throw uno::RuntimeException();
+ return pBkm->GetFieldname();
+}
+
+void SwXFieldmark::setFieldType(const::rtl::OUString & fieldType)
+ throw(uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+ IFieldmark *pBkm = const_cast<IFieldmark*>(
+ dynamic_cast<const IFieldmark*>(GetBookmark()));
+ if(!pBkm)
+ throw uno::RuntimeException();
+ pBkm->SetFieldname(fieldType);
+}
+
+uno::Reference<container::XNameContainer> SwXFieldmark::getParameters()
+ throw (uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+ IFieldmark *pBkm = const_cast<IFieldmark*>(
+ dynamic_cast<const IFieldmark*>(GetBookmark()));
+ if(!pBkm)
+ throw uno::RuntimeException();
+ return uno::Reference<container::XNameContainer>(new SwXFieldmarkParameters(pBkm));
+}
+
+uno::Reference<text::XTextContent>
+SwXFieldmark::CreateXFieldmark(SwDoc & rDoc, ::sw::mark::IMark & rMark)
+{
+ // #i105557#: do not iterate over the registered clients: race condition
+ ::sw::mark::MarkBase *const pMarkBase(
+ dynamic_cast< ::sw::mark::MarkBase * >(&rMark));
+ OSL_ENSURE(pMarkBase, "CreateXBookmark: no MarkBase?");
+ if (!pMarkBase) { return 0; }
+ uno::Reference<text::XTextContent> xMark(pMarkBase->GetXBookmark());
+ if (!xMark.is())
+ {
+ // FIXME: These belong in XTextFieldsSupplier
+ SwXFieldmark* pXBkmk = NULL;
+ if (dynamic_cast< ::sw::mark::TextFieldmark* >(&rMark))
+ pXBkmk = new SwXFieldmark(false, &rMark, &rDoc);
+ else if (dynamic_cast< ::sw::mark::CheckboxFieldmark* >(&rMark))
+ pXBkmk = new SwXFieldmark(true, &rMark, &rDoc);
+
+ xMark.set(pXBkmk);
+ pXBkmk->registerInMark(*pXBkmk, pMarkBase);
+ }
+ return xMark;
+}
+
+::sw::mark::ICheckboxFieldmark*
+SwXFieldmark::getCheckboxFieldmark()
+{
+ ::sw::mark::ICheckboxFieldmark* pCheckboxFm = NULL;
+ if ( getFieldType() == rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(ODF_FORMCHECKBOX) ) )
+ // evil #TODO #FIXME casting away the const-ness
+ pCheckboxFm = const_cast<sw::mark::ICheckboxFieldmark*>(reinterpret_cast< const ::sw::mark::ICheckboxFieldmark* >( GetBookmark()));
+ return pCheckboxFm;
+
+}
+
+// support 'hidden' "Checked" property ( note: this property is just for convenience to support
+// docx import filter thus not published via PropertySet info )
+
+void SAL_CALL
+SwXFieldmark::setPropertyValue(const OUString& PropertyName,
+ const uno::Any& rValue)
+throw (beans::UnknownPropertyException, beans::PropertyVetoException,
+ lang::IllegalArgumentException, lang::WrappedTargetException,
+ uno::RuntimeException)
+{
+ SolarMutexGuard g;
+ if ( PropertyName.equals( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("Checked") ) ) )
+ {
+ ::sw::mark::ICheckboxFieldmark* pCheckboxFm = getCheckboxFieldmark();
+ sal_Bool bChecked( sal_False );
+ if ( pCheckboxFm && ( rValue >>= bChecked ) )
+ pCheckboxFm->SetChecked( bChecked );
+ else
+ throw uno::RuntimeException();
+
+ }
+ else
+ SwXFieldmark_Base::setPropertyValue( PropertyName, rValue );
+}
+
+// support 'hidden' "Checked" property ( note: this property is just for convenience to support
+// docx import filter thus not published via PropertySet info )
+
+uno::Any SAL_CALL SwXFieldmark::getPropertyValue(const OUString& rPropertyName)
+throw (beans::UnknownPropertyException, lang::WrappedTargetException,
+ uno::RuntimeException)
+{
+ SolarMutexGuard g;
+ if ( rPropertyName.equals( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("Checked") ) ) )
+ {
+ ::sw::mark::ICheckboxFieldmark* pCheckboxFm = getCheckboxFieldmark();
+ if ( pCheckboxFm )
+ return uno::makeAny( pCheckboxFm->IsChecked() );
+ else
+ throw uno::RuntimeException();
+ }
+ return SwXFieldmark_Base::getPropertyValue( rPropertyName );
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/unocore/unochart.cxx b/sw/source/core/unocore/unochart.cxx
new file mode 100644
index 000000000000..d653e5f782dc
--- /dev/null
+++ b/sw/source/core/unocore/unochart.cxx
@@ -0,0 +1,2956 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+#include <memory>
+#include <algorithm>
+
+#include <com/sun/star/chart/ChartDataRowSource.hpp>
+#include <com/sun/star/chart2/data/LabelOrigin.hpp>
+#include <cppuhelper/interfacecontainer.hxx>
+#include <osl/mutex.hxx>
+#include <vcl/svapp.hxx>
+#include <svl/zforlist.hxx> // SvNumberFormatter
+#include <svtools/chartprettypainter.hxx>
+
+#include <tools/link.hxx>
+
+#include <XMLRangeHelper.hxx>
+#include <unochart.hxx>
+#include <swtable.hxx>
+#include <unoprnms.hxx>
+#include <unomap.hxx>
+#include <unomid.h>
+#include <unocrsr.hxx>
+#include <unotbl.hxx>
+#include <doc.hxx>
+#include <frmfmt.hxx>
+#include <docsh.hxx>
+#include <ndole.hxx>
+#include <swtypes.hxx>
+#include <unocore.hrc>
+
+#include <docary.hxx>
+
+#define SN_DATA_PROVIDER "com.sun.star.chart2.data.DataProvider"
+#define SN_DATA_SOURCE "com.sun.star.chart2.data.DataSource"
+#define SN_DATA_SEQUENCE "com.sun.star.chart2.data.DataSequence"
+#define SN_LABELED_DATA_SEQUENCE "com.sun.star.chart2.data.LabeledDataSequence"
+
+#define DIRECTION_DONT_KNOW -1
+#define DIRECTION_HAS_ERROR -2
+#define DIRECTION_COLS 0
+#define DIRECTION_ROWS 1
+
+using namespace ::com::sun::star;
+using ::rtl::OUString;
+
+// from unotbl.cxx
+extern void lcl_GetCellPosition( const String &rCellName, sal_Int32 &rColumn, sal_Int32 &rRow);
+extern String lcl_GetCellName( sal_Int32 nColumn, sal_Int32 nRow );
+extern int lcl_CompareCellsByColFirst( const String &rCellName1, const String &rCellName2 );
+extern int lcl_CompareCellsByRowFirst( const String &rCellName1, const String &rCellName2 );
+extern int lcl_CompareCellRanges(
+ const String &rRange1StartCell, const String &rRange1EndCell,
+ const String &rRange2StartCell, const String &rRange2EndCell,
+ sal_Bool bCmpColsFirst );
+extern void lcl_NormalizeRange( String &rCell1, String &rCell2 );
+
+//static
+void SwChartHelper::DoUpdateAllCharts( SwDoc* pDoc )
+{
+ if (!pDoc)
+ return;
+
+ uno::Reference< frame::XModel > xRes;
+
+ SwOLENode *pONd;
+ SwStartNode *pStNd;
+ SwNodeIndex aIdx( *pDoc->GetNodes().GetEndOfAutotext().StartOfSectionNode(), 1 );
+ while( 0 != (pStNd = aIdx.GetNode().GetStartNode()) )
+ {
+ aIdx++;
+ if (0 != ( pONd = aIdx.GetNode().GetOLENode() ) &&
+ ChartPrettyPainter::IsChart( pONd->GetOLEObj().GetObject() ) )
+ {
+ // Load the object and set modified
+
+ uno::Reference < embed::XEmbeddedObject > xIP = pONd->GetOLEObj().GetOleRef();
+ if ( svt::EmbeddedObjectRef::TryRunningState( xIP ) )
+ {
+ try
+ {
+ uno::Reference< util::XModifiable > xModif( xIP->getComponent(), uno::UNO_QUERY_THROW );
+ xModif->setModified( sal_True );
+ }
+ catch ( uno::Exception& )
+ {
+ }
+
+ }
+ }
+ aIdx.Assign( *pStNd->EndOfSectionNode(), + 1 );
+ }
+}
+
+SwChartLockController_Helper::SwChartLockController_Helper( SwDoc *pDocument ) :
+ pDoc( pDocument )
+{
+ aUnlockTimer.SetTimeout( 1500 );
+ aUnlockTimer.SetTimeoutHdl( LINK( this, SwChartLockController_Helper, DoUnlockAllCharts ));
+}
+
+SwChartLockController_Helper::~SwChartLockController_Helper()
+{
+ if (pDoc) // still connected?
+ Disconnect();
+}
+
+void SwChartLockController_Helper::StartOrContinueLocking()
+{
+ if (!bIsLocked)
+ LockAllCharts();
+ aUnlockTimer.Start(); // start or continue time of locking
+}
+
+void SwChartLockController_Helper::Disconnect()
+{
+ aUnlockTimer.Stop();
+ UnlockAllCharts();
+ pDoc = 0;
+}
+
+void SwChartLockController_Helper::LockUnlockAllCharts( sal_Bool bLock )
+{
+ if (!pDoc)
+ return;
+
+ const SwFrmFmts& rTblFmts = *pDoc->GetTblFrmFmts();
+ for( sal_uInt16 n = 0; n < rTblFmts.Count(); ++n )
+ {
+ SwTable* pTmpTbl;
+ const SwTableNode* pTblNd;
+ SwFrmFmt* pFmt = rTblFmts[ n ];
+
+ if( 0 != ( pTmpTbl = SwTable::FindTable( pFmt ) ) &&
+ 0 != ( pTblNd = pTmpTbl->GetTableNode() ) &&
+ pTblNd->GetNodes().IsDocNodes() )
+ {
+ uno::Reference< frame::XModel > xRes;
+
+ String aName( pTmpTbl->GetFrmFmt()->GetName() );
+ SwOLENode *pONd;
+ SwStartNode *pStNd;
+ SwNodeIndex aIdx( *pDoc->GetNodes().GetEndOfAutotext().StartOfSectionNode(), 1 );
+ while( 0 != (pStNd = aIdx.GetNode().GetStartNode()) )
+ {
+ aIdx++;
+ if (0 != ( pONd = aIdx.GetNode().GetOLENode() ) &&
+ pONd->GetChartTblName().Len() > 0 /* is chart object? */)
+ {
+ uno::Reference < embed::XEmbeddedObject > xIP = pONd->GetOLEObj().GetOleRef();
+ if ( svt::EmbeddedObjectRef::TryRunningState( xIP ) )
+ {
+ xRes = uno::Reference < frame::XModel >( xIP->getComponent(), uno::UNO_QUERY );
+ if (xRes.is())
+ {
+ if (bLock)
+ xRes->lockControllers();
+ else
+ xRes->unlockControllers();
+ }
+ }
+ }
+ aIdx.Assign( *pStNd->EndOfSectionNode(), + 1 );
+ }
+ }
+ }
+
+ bIsLocked = bLock;
+}
+
+IMPL_LINK( SwChartLockController_Helper, DoUnlockAllCharts, Timer *, /*pTimer*/ )
+{
+ UnlockAllCharts();
+ return 0;
+}
+
+static osl::Mutex & GetChartMutex()
+{
+ static osl::Mutex aMutex;
+ return aMutex;
+}
+
+static void LaunchModifiedEvent(
+ ::cppu::OInterfaceContainerHelper &rICH,
+ const uno::Reference< uno::XInterface > &rxI )
+{
+ lang::EventObject aEvtObj( rxI );
+ cppu::OInterfaceIteratorHelper aIt( rICH );
+ while (aIt.hasMoreElements())
+ {
+ uno::Reference< util::XModifyListener > xRef( aIt.next(), uno::UNO_QUERY );
+ if (xRef.is())
+ xRef->modified( aEvtObj );
+ }
+}
+
+// rCellRangeName needs to be of one of the following formats:
+// - e.g. "A2:E5" or
+// - e.g. "Table1.A2:E5"
+sal_Bool FillRangeDescriptor(
+ SwRangeDescriptor &rDesc,
+ const String &rCellRangeName )
+{
+ xub_StrLen nToken = STRING_NOTFOUND == rCellRangeName.Search('.') ? 0 : 1;
+ String aCellRangeNoTableName( rCellRangeName.GetToken( nToken, '.' ) );
+ String aTLName( aCellRangeNoTableName.GetToken(0, ':') ); // name of top left cell
+ String aBRName( aCellRangeNoTableName.GetToken(1, ':') ); // name of bottom right cell
+ if(!aTLName.Len() || !aBRName.Len())
+ return sal_False;
+
+ rDesc.nTop = rDesc.nLeft = rDesc.nBottom = rDesc.nRight = -1;
+ lcl_GetCellPosition( aTLName, rDesc.nLeft, rDesc.nTop );
+ lcl_GetCellPosition( aBRName, rDesc.nRight, rDesc.nBottom );
+ rDesc.Normalize();
+ DBG_ASSERT( rDesc.nTop != -1 &&
+ rDesc.nLeft != -1 &&
+ rDesc.nBottom != -1 &&
+ rDesc.nRight != -1,
+ "failed to get range descriptor" );
+ DBG_ASSERT( rDesc.nTop <= rDesc.nBottom && rDesc.nLeft <= rDesc.nRight,
+ "invalid range descriptor");
+ return sal_True;
+}
+
+static String GetCellRangeName( SwFrmFmt &rTblFmt, SwUnoCrsr &rTblCrsr )
+{
+ String aRes;
+
+ //!! see also SwXTextTableCursor::getRangeName
+
+ SwUnoTableCrsr* pUnoTblCrsr = dynamic_cast<SwUnoTableCrsr*>(&rTblCrsr);
+ if (!pUnoTblCrsr)
+ return String();
+ pUnoTblCrsr->MakeBoxSels();
+
+ const SwStartNode* pStart;
+ const SwTableBox* pStartBox = 0;
+ const SwTableBox* pEndBox = 0;
+
+ pStart = pUnoTblCrsr->GetPoint()->nNode.GetNode().FindTableBoxStartNode();
+ if (pStart)
+ {
+ const SwTable* pTable = SwTable::FindTable( &rTblFmt );
+ pEndBox = pTable->GetTblBox( pStart->GetIndex());
+ aRes = pEndBox->GetName();
+
+ if(pUnoTblCrsr->HasMark())
+ {
+ pStart = pUnoTblCrsr->GetMark()->nNode.GetNode().FindTableBoxStartNode();
+ pStartBox = pTable->GetTblBox( pStart->GetIndex());
+ }
+ DBG_ASSERT( pStartBox, "start box not found" );
+ DBG_ASSERT( pEndBox, "end box not found" );
+ // need to switch start and end?
+ if (*pUnoTblCrsr->GetPoint() < *pUnoTblCrsr->GetMark())
+ {
+ const SwTableBox* pTmpBox = pStartBox;
+ pStartBox = pEndBox;
+ pEndBox = pTmpBox;
+ }
+
+ aRes = pStartBox->GetName();
+ aRes += (sal_Unicode)':';
+ if (pEndBox)
+ aRes += pEndBox->GetName();
+ else
+ aRes += pStartBox->GetName();
+ }
+
+ return aRes;
+}
+
+static String GetRangeRepFromTableAndCells( const String &rTableName,
+ const String &rStartCell, const String &rEndCell,
+ sal_Bool bForceEndCellName )
+{
+ DBG_ASSERT( rTableName.Len(), "table name missing" );
+ DBG_ASSERT( rStartCell.Len(), "cell name missing" );
+ String aRes( rTableName );
+ aRes += (sal_Unicode) '.';
+ aRes += rStartCell;
+
+ if (rEndCell.Len())
+ {
+ aRes += (sal_Unicode) ':';
+ aRes += rEndCell;
+ }
+ else if (bForceEndCellName)
+ {
+ aRes += (sal_Unicode) ':';
+ aRes += rStartCell;
+ }
+
+ return aRes;
+}
+
+static sal_Bool GetTableAndCellsFromRangeRep(
+ const OUString &rRangeRepresentation,
+ String &rTblName,
+ String &rStartCell,
+ String &rEndCell,
+ sal_Bool bSortStartEndCells = sal_True )
+{
+ // parse range representation for table name and cell/range names
+ // accepted format sth like: "Table1.A2:C5" , "Table2.A2.1:B3.2"
+ String aTblName; // table name
+ OUString aRange; // cell range
+ String aStartCell; // name of top left cell
+ String aEndCell; // name of bottom right cell
+ sal_Int32 nIdx = rRangeRepresentation.indexOf( '.' );
+ if (nIdx >= 0)
+ {
+ aTblName = rRangeRepresentation.copy( 0, nIdx );
+ aRange = rRangeRepresentation.copy( nIdx + 1 );
+ sal_Int32 nPos = aRange.indexOf( ':' );
+ if (nPos >= 0) // a cell-range like "Table1.A2:D4"
+ {
+ aStartCell = aRange.copy( 0, nPos );
+ aEndCell = aRange.copy( nPos + 1 );
+
+ // need to switch start and end cell ?
+ // (does not check for normalization here)
+ if (bSortStartEndCells && 1 == lcl_CompareCellsByColFirst( aStartCell, aEndCell ))
+ {
+ String aTmp( aStartCell );
+ aStartCell = aEndCell;
+ aEndCell = aTmp;
+ }
+ }
+ else // a single cell like in "Table1.B3"
+ {
+ aStartCell = aEndCell = aRange;
+ }
+ }
+
+ sal_Bool bSuccess = aTblName.Len() != 0 &&
+ aStartCell.Len() != 0 && aEndCell.Len() != 0;
+ if (bSuccess)
+ {
+ rTblName = aTblName;
+ rStartCell = aStartCell;
+ rEndCell = aEndCell;
+ }
+ return bSuccess;
+}
+
+static void GetTableByName( const SwDoc &rDoc, const String &rTableName,
+ SwFrmFmt **ppTblFmt, SwTable **ppTable)
+{
+ SwFrmFmt *pTblFmt = NULL;
+
+ // find frame format of table
+ //! see SwXTextTables::getByName
+ sal_uInt16 nCount = rDoc.GetTblFrmFmtCount(sal_True);
+ for (sal_uInt16 i = 0; i < nCount && !pTblFmt; ++i)
+ {
+ SwFrmFmt& rTblFmt = rDoc.GetTblFrmFmt(i, sal_True);
+ if(rTableName == rTblFmt.GetName())
+ pTblFmt = &rTblFmt;
+ }
+
+ if (ppTblFmt)
+ *ppTblFmt = pTblFmt;
+
+ if (ppTable)
+ *ppTable = pTblFmt ? SwTable::FindTable( pTblFmt ) : 0;
+}
+
+static void GetFormatAndCreateCursorFromRangeRep(
+ const SwDoc *pDoc,
+ const OUString &rRangeRepresentation, // must be a single range (i.e. so called sub-range)
+ SwFrmFmt **ppTblFmt, // will be set to the table format of the table used in the range representation
+ SwUnoCrsr **ppUnoCrsr ) // will be set to cursor spanning the cell range
+ // (cursor will be created!)
+{
+ String aTblName; // table name
+ String aStartCell; // name of top left cell
+ String aEndCell; // name of bottom right cell
+ sal_Bool bNamesFound = GetTableAndCellsFromRangeRep( rRangeRepresentation,
+ aTblName, aStartCell, aEndCell );
+
+ if (!bNamesFound)
+ {
+ if (ppTblFmt)
+ *ppTblFmt = NULL;
+ if (ppUnoCrsr)
+ *ppUnoCrsr = NULL;
+ }
+ else
+ {
+ SwFrmFmt *pTblFmt = NULL;
+
+ // is the correct table format already provided?
+ if (*ppTblFmt != NULL && (*ppTblFmt)->GetName() == aTblName)
+ pTblFmt = *ppTblFmt;
+ else if (ppTblFmt)
+ GetTableByName( *pDoc, aTblName, &pTblFmt, NULL );
+
+ if (ppTblFmt)
+ *ppTblFmt = pTblFmt;
+
+ if (ppUnoCrsr != NULL)
+ {
+ *ppUnoCrsr = NULL; // default result in case of failure
+
+ SwTable *pTable = pTblFmt ? SwTable::FindTable( pTblFmt ) : 0;
+ // create new SwUnoCrsr spanning the specified range
+ //! see also SwXTextTable::GetRangeByName
+ // --> OD 2007-08-03 #i80314#
+ // perform validation check. Thus, pass <true> as 2nd parameter to <SwTable::GetTblBox(..)>
+ const SwTableBox* pTLBox =
+ pTable ? pTable->GetTblBox( aStartCell, true ) : 0;
+ // <--
+ if(pTLBox)
+ {
+ // hier muessen die Actions aufgehoben werden
+ UnoActionRemoveContext aRemoveContext(pTblFmt->GetDoc());
+ const SwStartNode* pSttNd = pTLBox->GetSttNd();
+ SwPosition aPos(*pSttNd);
+ // set cursor to top left box of range
+ SwUnoCrsr* pUnoCrsr = pTblFmt->GetDoc()->CreateUnoCrsr(aPos, sal_True);
+ pUnoCrsr->Move( fnMoveForward, fnGoNode );
+ pUnoCrsr->SetRemainInSection( sal_False );
+ // --> OD 2007-08-03 #i80314#
+ // perform validation check. Thus, pass <true> as 2nd parameter to <SwTable::GetTblBox(..)>
+ const SwTableBox* pBRBox = pTable->GetTblBox( aEndCell, true );
+ // <--
+ if(pBRBox)
+ {
+ pUnoCrsr->SetMark();
+ pUnoCrsr->GetPoint()->nNode = *pBRBox->GetSttNd();
+ pUnoCrsr->Move( fnMoveForward, fnGoNode );
+ SwUnoTableCrsr* pCrsr =
+ dynamic_cast<SwUnoTableCrsr*>(pUnoCrsr);
+ pCrsr->MakeBoxSels();
+
+ if (ppUnoCrsr)
+ *ppUnoCrsr = pCrsr;
+ }
+ else
+ {
+ delete pUnoCrsr;
+ }
+ }
+ }
+ }
+}
+
+static sal_Bool GetSubranges( const OUString &rRangeRepresentation,
+ uno::Sequence< OUString > &rSubRanges, sal_Bool bNormalize )
+{
+ sal_Bool bRes = sal_True;
+ String aRangesStr( rRangeRepresentation );
+ xub_StrLen nLen = aRangesStr.GetTokenCount( ';' );
+ uno::Sequence< OUString > aRanges( nLen );
+
+ sal_Int32 nCnt = 0;
+ if (nLen != 0)
+ {
+ OUString *pRanges = aRanges.getArray();
+ String aFirstTable;
+ for ( xub_StrLen i = 0; i < nLen && bRes; ++i)
+ {
+ String aRange( aRangesStr.GetToken( i, ';' ) );
+ if (aRange.Len())
+ {
+ pRanges[nCnt] = aRange;
+
+ String aTableName, aStartCell, aEndCell;
+ bRes &= GetTableAndCellsFromRangeRep( aRange,
+ aTableName, aStartCell, aEndCell );
+
+ if (bNormalize)
+ {
+ lcl_NormalizeRange( aStartCell, aEndCell );
+ pRanges[nCnt] = GetRangeRepFromTableAndCells( aTableName,
+ aStartCell, aEndCell, sal_True );
+ }
+
+ // make sure to use only a single table
+ if (nCnt == 0)
+ aFirstTable = aTableName;
+ else
+ bRes &= aFirstTable == aTableName;
+
+ ++nCnt;
+ }
+ }
+ }
+ aRanges.realloc( nCnt );
+
+ rSubRanges = aRanges;
+ return bRes;
+}
+
+static void SortSubranges( uno::Sequence< OUString > &rSubRanges, sal_Bool bCmpByColumn )
+{
+ sal_Int32 nLen = rSubRanges.getLength();
+ OUString *pSubRanges = rSubRanges.getArray();
+
+ String aSmallestTblName;
+ String aSmallestStartCell;
+ String aSmallestEndCell;
+
+ for (sal_Int32 i = 0; i < nLen; ++i)
+ {
+ sal_Int32 nIdxOfSmallest = i;
+ GetTableAndCellsFromRangeRep( pSubRanges[nIdxOfSmallest],
+ aSmallestTblName, aSmallestStartCell, aSmallestEndCell );
+ if (aSmallestEndCell.Len() == 0)
+ aSmallestEndCell = aSmallestStartCell;
+
+ for (sal_Int32 k = i+1; k < nLen; ++k)
+ {
+ // get cell names for sub range
+ String aTblName;
+ String aStartCell;
+ String aEndCell;
+ GetTableAndCellsFromRangeRep( pSubRanges[k],
+ aTblName, aStartCell, aEndCell );
+ if (aEndCell.Len() == 0)
+ aEndCell = aStartCell;
+
+ // compare cell ranges ( is the new one smaller? )
+ if (-1 == lcl_CompareCellRanges( aStartCell, aEndCell,
+ aSmallestStartCell, aSmallestEndCell, bCmpByColumn ))
+ {
+ nIdxOfSmallest = k;
+ aSmallestTblName = aTblName;
+ aSmallestStartCell = aStartCell;
+ aSmallestEndCell = aEndCell;
+ }
+ }
+
+ // move smallest element to the start of the not sorted area
+ OUString aTmp( pSubRanges[ nIdxOfSmallest ] );
+ pSubRanges[ nIdxOfSmallest ] = pSubRanges[ i ];
+ pSubRanges[ i ] = aTmp;
+ }
+}
+
+SwChartDataProvider::SwChartDataProvider( const SwDoc* pSwDoc ) :
+ aEvtListeners( GetChartMutex() ),
+ pDoc( pSwDoc )
+{
+ bDisposed = sal_False;
+}
+
+SwChartDataProvider::~SwChartDataProvider()
+{
+}
+
+uno::Reference< chart2::data::XDataSource > SwChartDataProvider::Impl_createDataSource(
+ const uno::Sequence< beans::PropertyValue >& rArguments, sal_Bool bTestOnly )
+ throw (lang::IllegalArgumentException, uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+ if (bDisposed)
+ throw lang::DisposedException();
+
+ uno::Reference< chart2::data::XDataSource > xRes;
+
+ if (!pDoc)
+ throw uno::RuntimeException();
+
+ // get arguments
+ OUString aRangeRepresentation;
+ uno::Sequence< sal_Int32 > aSequenceMapping;
+ sal_Bool bFirstIsLabel = sal_False;
+ sal_Bool bDtaSrcIsColumns = sal_True; // true : DataSource will be sequence of columns
+ // false: DataSource will be sequence of rows
+ OUString aChartOleObjectName;//work around wrong writer ranges ( see Issue 58464 )
+ sal_Int32 nArgs = rArguments.getLength();
+ DBG_ASSERT( nArgs != 0, "no properties provided" );
+ if (nArgs == 0)
+ return xRes;
+ const beans::PropertyValue *pArg = rArguments.getConstArray();
+ for (sal_Int32 i = 0; i < nArgs; ++i)
+ {
+ if (pArg[i].Name.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("DataRowSource")))
+ {
+ chart::ChartDataRowSource eSource;
+ if (!(pArg[i].Value >>= eSource))
+ {
+ sal_Int32 nTmp = 0;
+ if (!(pArg[i].Value >>= nTmp))
+ throw lang::IllegalArgumentException();
+ eSource = static_cast< chart::ChartDataRowSource >( nTmp );
+ }
+ bDtaSrcIsColumns = eSource == chart::ChartDataRowSource_COLUMNS;
+ }
+ else if (pArg[i].Name.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("FirstCellAsLabel")))
+ {
+ if (!(pArg[i].Value >>= bFirstIsLabel))
+ throw lang::IllegalArgumentException();
+ }
+ else if (pArg[i].Name.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("CellRangeRepresentation")))
+ {
+ if (!(pArg[i].Value >>= aRangeRepresentation))
+ throw lang::IllegalArgumentException();
+ }
+ else if (pArg[i].Name.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("SequenceMapping")))
+ {
+ if (!(pArg[i].Value >>= aSequenceMapping))
+ throw lang::IllegalArgumentException();
+ }
+ else if (pArg[i].Name.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("ChartOleObjectName")))
+ {
+ if (!(pArg[i].Value >>= aChartOleObjectName))
+ throw lang::IllegalArgumentException();
+ }
+ }
+
+ uno::Sequence< OUString > aSubRanges;
+ // get sub-ranges and check that they all are from the very same table
+ sal_Bool bOk = GetSubranges( aRangeRepresentation, aSubRanges, sal_True );
+
+ if (!bOk && pDoc && aChartOleObjectName.getLength() )
+ {
+ //try to correct the range here
+ //work around wrong writer ranges ( see Issue 58464 )
+ String aChartTableName;
+
+ const SwNodes& rNodes = pDoc->GetNodes();
+ for( sal_uLong nN = rNodes.Count(); nN--; )
+ {
+ SwNodePtr pNode = rNodes[nN];
+ if( !pNode )
+ continue;
+ const SwOLENode* pOleNode = pNode->GetOLENode();
+ if( !pOleNode )
+ continue;
+ const SwOLEObj& rOObj = pOleNode->GetOLEObj();
+ if( aChartOleObjectName.equals( rOObj.GetCurrentPersistName() ) )
+ {
+ aChartTableName = pOleNode->GetChartTblName();
+ break;
+ }
+ }
+
+ if( aChartTableName.Len() )
+ {
+ //the wrong range is still shifted one row down
+ //thus the first row is missing and an invalid row at the end is added.
+ //Therefore we need to shift the range one row up
+ SwRangeDescriptor aDesc;
+ if (aRangeRepresentation.getLength() == 0)
+ return xRes; // we cant handle this thus returning an empty references
+ aRangeRepresentation = aRangeRepresentation.copy( 1 ); // get rid of '.' to have only the cell range left
+ FillRangeDescriptor( aDesc, aRangeRepresentation );
+ aDesc.Normalize();
+ if (aDesc.nTop <= 0) // no chance to shift the range one row up?
+ return xRes; // we cant handle this thus returning an empty references
+ aDesc.nTop -= 1;
+ aDesc.nBottom -= 1;
+
+ String aNewStartCell( lcl_GetCellName( aDesc.nLeft, aDesc.nTop ) );
+ String aNewEndCell( lcl_GetCellName( aDesc.nRight, aDesc.nBottom ) );
+ aRangeRepresentation = GetRangeRepFromTableAndCells(
+ aChartTableName, aNewStartCell, aNewEndCell, sal_True );
+ bOk = GetSubranges( aRangeRepresentation, aSubRanges, sal_True );
+ }
+ }
+ if (!bOk) // different tables used, or incorrect range specifiers
+ throw lang::IllegalArgumentException();
+
+ SortSubranges( aSubRanges, bDtaSrcIsColumns );
+ const OUString *pSubRanges = aSubRanges.getConstArray();
+#if OSL_DEBUG_LEVEL > 1
+ {
+ sal_Int32 nSR = aSubRanges.getLength();
+ OUString *pSR = aSubRanges.getArray();
+ OUString aRg;
+ for (sal_Int32 i = 0; i < nSR; ++i)
+ {
+ aRg = pSR[i];
+ }
+ }
+#endif
+
+ // get table format for that single table from above
+ SwFrmFmt *pTblFmt = 0; // pointer to table format
+ SwUnoCrsr *pUnoCrsr = 0; // here required to check if the cells in the range do actually exist
+ std::auto_ptr< SwUnoCrsr > pAuto( pUnoCrsr ); // to end lifetime of object pointed to by pUnoCrsr
+ if (aSubRanges.getLength() > 0)
+ GetFormatAndCreateCursorFromRangeRep( pDoc, pSubRanges[0], &pTblFmt, &pUnoCrsr );
+ if (!pTblFmt || !pUnoCrsr)
+ throw lang::IllegalArgumentException();
+
+ if(pTblFmt)
+ {
+ SwTable* pTable = SwTable::FindTable( pTblFmt );
+ if(pTable->IsTblComplex())
+ return xRes; // we cant handle this thus returning an empty references
+ else
+ {
+ // get a character map in the size of the table to mark
+ // all the ranges to use in
+ sal_Int32 nRows = pTable->GetTabLines().Count();
+ sal_Int32 nCols = pTable->GetTabLines().GetObject(0)->GetTabBoxes().Count();
+ std::vector< std::vector< sal_Char > > aMap( nRows );
+ for (sal_Int32 i = 0; i < nRows; ++i)
+ aMap[i].resize( nCols );
+
+ // iterate over subranges and mark used cells in above map
+ //!! by proceeding this way we automatically get rid of
+ //!! multiple listed or overlapping cell ranges which should
+ //!! just be ignored silently
+ sal_Int32 nSubRanges = aSubRanges.getLength();
+ for (sal_Int32 i = 0; i < nSubRanges; ++i)
+ {
+ String aTblName, aStartCell, aEndCell;
+ sal_Bool bOk2 = GetTableAndCellsFromRangeRep(
+ pSubRanges[i], aTblName, aStartCell, aEndCell );
+ (void) bOk2;
+ DBG_ASSERT( bOk2, "failed to get table and start/end cells" );
+
+ sal_Int32 nStartRow, nStartCol, nEndRow, nEndCol;
+ lcl_GetCellPosition( aStartCell, nStartCol, nStartRow );
+ lcl_GetCellPosition( aEndCell, nEndCol, nEndRow );
+ DBG_ASSERT( nStartRow <= nEndRow && nStartCol <= nEndCol,
+ "cell range not normalized");
+
+ // test if the ranges span more than the available cells
+ if( nStartRow < 0 || nEndRow >= nRows ||
+ nStartCol < 0 || nEndCol >= nCols )
+ {
+ throw lang::IllegalArgumentException();
+ }
+ for (sal_Int32 k1 = nStartRow; k1 <= nEndRow; ++k1)
+ {
+ for (sal_Int32 k2 = nStartCol; k2 <= nEndCol; ++k2)
+ aMap[k1][k2] = 'x';
+ }
+ }
+
+ //
+ // find label and data sequences to use
+ //
+ sal_Int32 oi; // outer index (slower changing index)
+ sal_Int32 ii; // inner index (faster changing index)
+ sal_Int32 oiEnd = bDtaSrcIsColumns ? nCols : nRows;
+ sal_Int32 iiEnd = bDtaSrcIsColumns ? nRows : nCols;
+ std::vector< sal_Int32 > aLabelIdx( oiEnd );
+ std::vector< sal_Int32 > aDataStartIdx( oiEnd );
+ std::vector< sal_Int32 > aDataLen( oiEnd );
+ for (oi = 0; oi < oiEnd; ++oi)
+ {
+ aLabelIdx[oi] = -1;
+ aDataStartIdx[oi] = -1;
+ aDataLen[oi] = 0;
+ }
+ //
+ for (oi = 0; oi < oiEnd; ++oi)
+ {
+ ii = 0;
+ while (ii < iiEnd)
+ {
+ sal_Char &rChar = bDtaSrcIsColumns ? aMap[ii][oi] : aMap[oi][ii];
+
+ // label should be used but is not yet found?
+ if (rChar == 'x' && bFirstIsLabel && aLabelIdx[oi] == -1)
+ {
+ aLabelIdx[oi] = ii;
+ rChar = 'L'; // setting a different char for labels here
+ // makes the test for the data sequence below
+ // easier
+ }
+
+ // find data sequence
+ if (rChar == 'x' && aDataStartIdx[oi] == -1)
+ {
+ aDataStartIdx[oi] = ii;
+
+ // get length of data sequence
+ sal_Int32 nL = 0;
+ sal_Char c;
+ while (ii< iiEnd && 'x' == (c = bDtaSrcIsColumns ? aMap[ii][oi] : aMap[oi][ii]))
+ {
+ ++nL; ++ii;
+ }
+ aDataLen[oi] = nL;
+
+ // check that there is no other seperate sequence of data
+ // to be found because that is not supported
+ while (ii < iiEnd)
+ {
+ if ('x' == (c = bDtaSrcIsColumns ? aMap[ii][oi] : aMap[oi][ii]))
+ throw lang::IllegalArgumentException();
+ ++ii;
+ }
+ }
+ else
+ ++ii;
+ }
+ }
+
+ // make some other consistency checks while calculating
+ // the number of XLabeledDataSequence to build:
+ // - labels should always be used or not at all
+ // - the data sequences should have equal non-zero length
+ sal_Int32 nNumLDS = 0;
+ if (oiEnd > 0)
+ {
+ sal_Int32 nFirstSeqLen = 0;
+ sal_Int32 nFirstSeqLabelIdx = -1;
+ for (oi = 0; oi < oiEnd; ++oi)
+ {
+ sal_Bool bFirstFound = sal_False;
+ // row/col used at all?
+ if (aDataStartIdx[oi] != -1 &&
+ (!bFirstIsLabel || aLabelIdx[oi] != -1))
+ {
+ ++nNumLDS;
+ if (!bFirstFound)
+ {
+ nFirstSeqLen = aDataLen[oi];
+ nFirstSeqLabelIdx = aLabelIdx[oi];
+ bFirstFound = sal_True;
+ }
+ else
+ {
+ if (nFirstSeqLen != aDataLen[oi] ||
+ nFirstSeqLabelIdx != aLabelIdx[oi])
+ throw lang::IllegalArgumentException();
+ }
+ }
+ }
+ }
+ if (nNumLDS == 0)
+ throw lang::IllegalArgumentException();
+
+ // now we should have all necessary data to build a proper DataSource
+ // thus if we came this far there should be no further problem
+ if (bTestOnly)
+ return xRes; // have createDataSourcePossible return true
+
+ // create data source from found label and data sequences
+ uno::Sequence< uno::Reference< chart2::data::XDataSequence > > aLabelSeqs( nNumLDS );
+ uno::Reference< chart2::data::XDataSequence > *pLabelSeqs = aLabelSeqs.getArray();
+ uno::Sequence< uno::Reference< chart2::data::XDataSequence > > aDataSeqs( nNumLDS );
+ uno::Reference< chart2::data::XDataSequence > *pDataSeqs = aDataSeqs.getArray();
+ sal_Int32 nSeqsIdx = 0;
+ for (oi = 0; oi < oiEnd; ++oi)
+ {
+ // row/col not used? (see if-statement above where nNumLDS was counted)
+ if (!(aDataStartIdx[oi] != -1 &&
+ (!bFirstIsLabel || aLabelIdx[oi] != -1)))
+ continue;
+
+ // get cell ranges for label and data
+ //
+ SwRangeDescriptor aLabelDesc;
+ SwRangeDescriptor aDataDesc;
+ if (bDtaSrcIsColumns) // use columns
+ {
+ aLabelDesc.nTop = aLabelIdx[oi];
+ aLabelDesc.nLeft = oi;
+ aLabelDesc.nBottom = aLabelDesc.nTop;
+ aLabelDesc.nRight = oi;
+
+ aDataDesc.nTop = aDataStartIdx[oi];
+ aDataDesc.nLeft = oi;
+ aDataDesc.nBottom = aDataDesc.nTop + aDataLen[oi] - 1;
+ aDataDesc.nRight = oi;
+ }
+ else // use rows
+ {
+ aLabelDesc.nTop = oi;
+ aLabelDesc.nLeft = aLabelIdx[oi];
+ aLabelDesc.nBottom = oi;
+ aLabelDesc.nRight = aLabelDesc.nLeft;
+
+ aDataDesc.nTop = oi;
+ aDataDesc.nLeft = aDataStartIdx[oi];
+ aDataDesc.nBottom = oi;
+ aDataDesc.nRight = aDataDesc.nLeft + aDataLen[oi] - 1;
+ }
+ String aBaseName( pTblFmt->GetName() );
+ aBaseName += '.';
+ //
+ String aLabelRange;
+ if (aLabelIdx[oi] != -1)
+ {
+ aLabelRange += aBaseName;
+ aLabelRange += lcl_GetCellName( aLabelDesc.nLeft, aLabelDesc.nTop );
+ aLabelRange += ':';
+ aLabelRange += lcl_GetCellName( aLabelDesc.nRight, aLabelDesc.nBottom );
+ }
+ //
+ String aDataRange;
+ if (aDataStartIdx[oi] != -1)
+ {
+ aDataRange += aBaseName;
+ aDataRange += lcl_GetCellName( aDataDesc.nLeft, aDataDesc.nTop );
+ aDataRange += ':';
+ aDataRange += lcl_GetCellName( aDataDesc.nRight, aDataDesc.nBottom );
+ }
+
+ // get cursors spanning the cell ranges for label and data
+ SwUnoCrsr *pLabelUnoCrsr = 0;
+ SwUnoCrsr *pDataUnoCrsr = 0;
+ GetFormatAndCreateCursorFromRangeRep( pDoc, aLabelRange, &pTblFmt, &pLabelUnoCrsr);
+ GetFormatAndCreateCursorFromRangeRep( pDoc, aDataRange, &pTblFmt, &pDataUnoCrsr);
+
+ // create XDataSequence's from cursors
+ if (pLabelUnoCrsr)
+ pLabelSeqs[ nSeqsIdx ] = new SwChartDataSequence( *this, *pTblFmt, pLabelUnoCrsr );
+ DBG_ASSERT( pDataUnoCrsr, "pointer to data sequence missing" );
+ if (pDataUnoCrsr)
+ pDataSeqs [ nSeqsIdx ] = new SwChartDataSequence( *this, *pTblFmt, pDataUnoCrsr );
+ if (pLabelUnoCrsr || pDataUnoCrsr)
+ ++nSeqsIdx;
+ }
+ DBG_ASSERT( nSeqsIdx == nNumLDS,
+ "mismatch between sequence size and num,ber of entries" );
+
+ // build data source from data and label sequences
+ uno::Sequence< uno::Reference< chart2::data::XLabeledDataSequence > > aLDS( nNumLDS );
+ uno::Reference< chart2::data::XLabeledDataSequence > *pLDS = aLDS.getArray();
+ for (sal_Int32 i = 0; i < nNumLDS; ++i)
+ {
+ SwChartLabeledDataSequence *pLabeledDtaSeq = new SwChartLabeledDataSequence;
+ pLabeledDtaSeq->setLabel( pLabelSeqs[i] );
+ pLabeledDtaSeq->setValues( pDataSeqs[i] );
+ pLDS[i] = pLabeledDtaSeq;
+ }
+
+ // apply 'SequenceMapping' if it was provided
+ sal_Int32 nSequenceMappingLen = aSequenceMapping.getLength();
+ if (nSequenceMappingLen)
+ {
+ sal_Int32 *pSequenceMapping = aSequenceMapping.getArray();
+ uno::Sequence< uno::Reference< chart2::data::XLabeledDataSequence > > aOld_LDS( aLDS );
+ uno::Reference< chart2::data::XLabeledDataSequence > *pOld_LDS = aOld_LDS.getArray();
+
+ sal_Int32 nNewCnt = 0;
+ for (sal_Int32 i = 0; i < nSequenceMappingLen; ++i)
+ {
+ // check that index to be used is valid
+ // and has not yet been used
+ sal_Int32 nIdx = pSequenceMapping[i];
+ if (0 <= nIdx && nIdx < nNumLDS && pOld_LDS[nIdx].is())
+ {
+ pLDS[nNewCnt++] = pOld_LDS[nIdx];
+
+ // mark index as being used already (avoids duplicate entries)
+ pOld_LDS[nIdx].clear();
+ }
+ }
+ // add not yet used 'old' sequences to new one
+ for (sal_Int32 i = 0; i < nNumLDS; ++i)
+ {
+#if OSL_DEBUG_LEVEL > 1
+ if (!pOld_LDS[i].is())
+ i = i;
+#endif
+ if (pOld_LDS[i].is())
+ pLDS[nNewCnt++] = pOld_LDS[i];
+ }
+ DBG_ASSERT( nNewCnt == nNumLDS, "unexpected size of resulting sequence" );
+ }
+
+ xRes = new SwChartDataSource( aLDS );
+ }
+ }
+
+ return xRes;
+}
+
+sal_Bool SAL_CALL SwChartDataProvider::createDataSourcePossible(
+ const uno::Sequence< beans::PropertyValue >& rArguments )
+ throw (uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+
+ sal_Bool bPossible = sal_True;
+ try
+ {
+ Impl_createDataSource( rArguments, sal_True );
+ }
+ catch (lang::IllegalArgumentException &)
+ {
+ bPossible = sal_False;
+ }
+
+ return bPossible;
+}
+
+uno::Reference< chart2::data::XDataSource > SAL_CALL SwChartDataProvider::createDataSource(
+ const uno::Sequence< beans::PropertyValue >& rArguments )
+ throw (lang::IllegalArgumentException, uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+ return Impl_createDataSource( rArguments );
+}
+
+////////////////////////////////////////////////////////////
+// SwChartDataProvider::GetBrokenCellRangeForExport
+//
+// fix for #i79009
+// we need to return a property that has the same value as the property
+// 'CellRangeRepresentation' but for all rows which are increased by one.
+// E.g. Table1:A1:D5 -> Table1:A2:D6
+// Since the problem is only for old charts which did not support multiple
+// we do not need to provide that property/string if the 'CellRangeRepresentation'
+// contains multiple ranges.
+OUString SwChartDataProvider::GetBrokenCellRangeForExport(
+ const OUString &rCellRangeRepresentation )
+{
+ OUString aRes;
+
+ // check that we do not have multiple ranges
+ if (-1 == rCellRangeRepresentation.indexOf( ';' ))
+ {
+ // get current cell and table names
+ String aTblName, aStartCell, aEndCell;
+ GetTableAndCellsFromRangeRep( rCellRangeRepresentation,
+ aTblName, aStartCell, aEndCell, sal_False );
+ sal_Int32 nStartCol = -1, nStartRow = -1, nEndCol = -1, nEndRow = -1;
+ lcl_GetCellPosition( aStartCell, nStartCol, nStartRow );
+ lcl_GetCellPosition( aEndCell, nEndCol, nEndRow );
+
+ // get new cell names
+ ++nStartRow;
+ ++nEndRow;
+ aStartCell = lcl_GetCellName( nStartCol, nStartRow );
+ aEndCell = lcl_GetCellName( nEndCol, nEndRow );
+
+ aRes = GetRangeRepFromTableAndCells( aTblName,
+ aStartCell, aEndCell, sal_False );
+ }
+
+ return aRes;
+}
+
+uno::Sequence< beans::PropertyValue > SAL_CALL SwChartDataProvider::detectArguments(
+ const uno::Reference< chart2::data::XDataSource >& xDataSource )
+ throw (uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+ if (bDisposed)
+ throw lang::DisposedException();
+
+ uno::Sequence< beans::PropertyValue > aResult;
+ if (!xDataSource.is())
+ return aResult;
+
+ const uno::Sequence< uno::Reference< chart2::data::XLabeledDataSequence > > aDS_LDS( xDataSource->getDataSequences() );
+ const uno::Reference< chart2::data::XLabeledDataSequence > *pDS_LDS = aDS_LDS.getConstArray();
+ sal_Int32 nNumDS_LDS = aDS_LDS.getLength();
+
+ if (nNumDS_LDS == 0)
+ {
+ DBG_WARNING( "XLabeledDataSequence in data source contains 0 entries" );
+ return aResult;
+ }
+
+ SwFrmFmt *pTableFmt = 0;
+ SwTable *pTable = 0;
+ String aTableName;
+ sal_Int32 nTableRows = 0;
+ sal_Int32 nTableCols = 0;
+
+ // data used to build 'CellRangeRepresentation' from later on
+ std::vector< std::vector< sal_Char > > aMap;
+
+ uno::Sequence< sal_Int32 > aSequenceMapping( nNumDS_LDS );
+ sal_Int32 *pSequenceMapping = aSequenceMapping.getArray();
+
+ String aCellRanges;
+ sal_Int16 nDtaSrcIsColumns = -1;// -1: don't know yet, 0: false, 1: true -2: neither
+ sal_Int32 nLabelSeqLen = -1; // used to see if labels are always used or not and have
+ // the expected size of 1 (i.e. if FirstCellAsLabel can
+ // be determined)
+ // -1: don't know yet, 0: not used, 1: always a single labe cell, ...
+ // -2: neither/failed
+ for (sal_Int32 nDS1 = 0; nDS1 < nNumDS_LDS; ++nDS1)
+ {
+ uno::Reference< chart2::data::XLabeledDataSequence > xLabeledDataSequence( pDS_LDS[nDS1] );
+ if( !xLabeledDataSequence.is() )
+ {
+ OSL_FAIL("got NULL for XLabeledDataSequence from Data source");
+ continue;
+ }
+ const uno::Reference< chart2::data::XDataSequence > xCurLabel( xLabeledDataSequence->getLabel(), uno::UNO_QUERY );
+ const uno::Reference< chart2::data::XDataSequence > xCurValues( xLabeledDataSequence->getValues(), uno::UNO_QUERY );
+
+ // get sequence lengths for label and values.
+ // (0 length is Ok)
+ sal_Int32 nCurLabelSeqLen = -1;
+ sal_Int32 nCurValuesSeqLen = -1;
+ if (xCurLabel.is())
+ nCurLabelSeqLen = xCurLabel->getData().getLength();
+ if (xCurValues.is())
+ nCurValuesSeqLen = xCurValues->getData().getLength();
+
+ // check for consistent use of 'first cell as label'
+ if (nLabelSeqLen == -1) // set initial value to compare with below further on
+ nLabelSeqLen = nCurLabelSeqLen;
+ if (nLabelSeqLen != nCurLabelSeqLen)
+ nLabelSeqLen = -2; // failed / no consistent use of label cells
+
+ // get table and cell names for label and values data sequences
+ // (start and end cell will be sorted, i.e. start cell <= end cell)
+ String aLabelTblName, aLabelStartCell, aLabelEndCell;
+ String aValuesTblName, aValuesStartCell, aValuesEndCell;
+ String aLabelRange, aValuesRange;
+ if (xCurLabel.is())
+ aLabelRange = xCurLabel->getSourceRangeRepresentation();
+ if (xCurValues.is())
+ aValuesRange = xCurValues->getSourceRangeRepresentation();
+ if ((aLabelRange.Len() && !GetTableAndCellsFromRangeRep( aLabelRange,
+ aLabelTblName, aLabelStartCell, aLabelEndCell )) ||
+ !GetTableAndCellsFromRangeRep( aValuesRange,
+ aValuesTblName, aValuesStartCell, aValuesEndCell ))
+ {
+ return aResult; // failed -> return empty property sequence
+ }
+
+ // make sure all sequences use the same table
+ if (!aTableName.Len())
+ aTableName = aValuesTblName; // get initial value to compare with
+ if (!aTableName.Len() ||
+ aTableName != aValuesTblName ||
+ (aLabelTblName.Len() && aTableName != aLabelTblName))
+ {
+ return aResult; // failed -> return empty property sequence
+ }
+
+
+ // try to get 'DataRowSource' value (ROWS or COLUMNS) from inspecting
+ // first and last cell used in both sequences
+ //
+ sal_Int32 nFirstCol = -1, nFirstRow = -1, nLastCol = -1, nLastRow = -1;
+ String aCell( aLabelStartCell.Len() ? aLabelStartCell : aValuesStartCell );
+ DBG_ASSERT( aCell.Len() , "start cell missing?" );
+ lcl_GetCellPosition( aCell, nFirstCol, nFirstRow);
+ lcl_GetCellPosition( aValuesEndCell, nLastCol, nLastRow);
+ //
+ sal_Int16 nDirection = -1; // -1: not yet set, 0: columns, 1: rows, -2: failed
+ if (nFirstCol == nLastCol && nFirstRow == nLastRow) // a single cell...
+ {
+ DBG_ASSERT( nCurLabelSeqLen == 0 && nCurValuesSeqLen == 1,
+ "trying to determine 'DataRowSource': something's fishy... should have been a single cell");
+ (void)nCurValuesSeqLen;
+ nDirection = 0; // default direction for a single cell should be 'columns'
+ }
+ else // more than one cell is availabale (in values and label together!)
+ {
+ if (nFirstCol == nLastCol && nFirstRow != nLastRow)
+ nDirection = 1;
+ else if (nFirstCol != nLastCol && nFirstRow == nLastRow)
+ nDirection = 0;
+ else
+ {
+ OSL_FAIL( "trying to determine 'DataRowSource': unexpected case found" );
+ nDirection = -2;
+ }
+ }
+ // check for consistent direction of data source
+ if (nDtaSrcIsColumns == -1) // set initial value to compare with below
+ nDtaSrcIsColumns = nDirection;
+ if (nDtaSrcIsColumns != nDirection)
+ {
+ nDtaSrcIsColumns = -2; // failed
+ }
+
+
+ if (nDtaSrcIsColumns == 0 || nDtaSrcIsColumns == 1)
+ {
+ // build data to obtain 'SequenceMapping' later on
+ //
+ DBG_ASSERT( nDtaSrcIsColumns == 0 || /* rows */
+ nDtaSrcIsColumns == 1, /* columns */
+ "unexpected value for 'nDtaSrcIsColumns'" );
+ pSequenceMapping[nDS1] = nDtaSrcIsColumns ? nFirstCol : nFirstRow;
+
+
+ // build data used to determine 'CellRangeRepresentation' later on
+ //
+ GetTableByName( *pDoc, aTableName, &pTableFmt, &pTable );
+ if (!pTable || pTable->IsTblComplex())
+ return aResult; // failed -> return empty property sequence
+ nTableRows = pTable->GetTabLines().Count();
+ nTableCols = pTable->GetTabLines().GetObject(0)->GetTabBoxes().Count();
+ aMap.resize( nTableRows );
+ for (sal_Int32 i = 0; i < nTableRows; ++i)
+ aMap[i].resize( nTableCols );
+ //
+ if (aLabelStartCell.Len() && aLabelEndCell.Len())
+ {
+ sal_Int32 nStartCol = -1, nStartRow = -1, nEndCol = -1, nEndRow = -1;
+ lcl_GetCellPosition( aLabelStartCell, nStartCol, nStartRow );
+ lcl_GetCellPosition( aLabelEndCell, nEndCol, nEndRow );
+ if (nStartRow < 0 || nEndRow >= nTableRows ||
+ nStartCol < 0 || nEndCol >= nTableCols)
+ {
+ return aResult; // failed -> return empty property sequence
+ }
+ for (sal_Int32 i = nStartRow; i <= nEndRow; ++i)
+ {
+ for (sal_Int32 k = nStartCol; k <= nEndCol; ++k)
+ {
+ sal_Char &rChar = aMap[i][k];
+ if (rChar == '\0') // check for overlapping values and/or labels
+ rChar = 'L';
+ else
+ return aResult; // failed -> return empty property sequence
+ }
+ }
+ }
+ if (aValuesStartCell.Len() && aValuesEndCell.Len())
+ {
+ sal_Int32 nStartCol = -1, nStartRow = -1, nEndCol = -1, nEndRow = -1;
+ lcl_GetCellPosition( aValuesStartCell, nStartCol, nStartRow );
+ lcl_GetCellPosition( aValuesEndCell, nEndCol, nEndRow );
+ if (nStartRow < 0 || nEndRow >= nTableRows ||
+ nStartCol < 0 || nEndCol >= nTableCols)
+ {
+ return aResult; // failed -> return empty property sequence
+ }
+ for (sal_Int32 i = nStartRow; i <= nEndRow; ++i)
+ {
+ for (sal_Int32 k = nStartCol; k <= nEndCol; ++k)
+ {
+ sal_Char &rChar = aMap[i][k];
+ if (rChar == '\0') // check for overlapping values and/or labels
+ rChar = 'x';
+ else
+ return aResult; // failed -> return empty property sequence
+ }
+ }
+ }
+ }
+
+#if OSL_DEBUG_LEVEL > 1
+ // do some extra sanity checking that the length of the sequences
+ // matches their range representation
+ {
+ sal_Int32 nStartRow = -1, nStartCol = -1, nEndRow = -1, nEndCol = -1;
+ if (xCurLabel.is())
+ {
+ lcl_GetCellPosition( aLabelStartCell, nStartCol, nStartRow);
+ lcl_GetCellPosition( aLabelEndCell, nEndCol, nEndRow);
+ DBG_ASSERT( (nStartCol == nEndCol && (nEndRow - nStartRow + 1) == xCurLabel->getData().getLength()) ||
+ (nStartRow == nEndRow && (nEndCol - nStartCol + 1) == xCurLabel->getData().getLength()),
+ "label sequence length does not match range representation!" );
+ }
+ if (xCurValues.is())
+ {
+ lcl_GetCellPosition( aValuesStartCell, nStartCol, nStartRow);
+ lcl_GetCellPosition( aValuesEndCell, nEndCol, nEndRow);
+ DBG_ASSERT( (nStartCol == nEndCol && (nEndRow - nStartRow + 1) == xCurValues->getData().getLength()) ||
+ (nStartRow == nEndRow && (nEndCol - nStartCol + 1) == xCurValues->getData().getLength()),
+ "value sequence length does not match range representation!" );
+ }
+ }
+#endif
+ } // for
+
+
+ // build value for 'CellRangeRepresentation'
+ //
+ String aCellRangeBase( aTableName );
+ aCellRangeBase += '.';
+ String aCurRange;
+ for (sal_Int32 i = 0; i < nTableRows; ++i)
+ {
+ for (sal_Int32 k = 0; k < nTableCols; ++k)
+ {
+ if (aMap[i][k] != '\0') // top-left cell of a sub-range found
+ {
+ // find rectangular sub-range to use
+ sal_Int32 nRowIndex1 = i; // row index
+ sal_Int32 nColIndex1 = k; // column index
+ sal_Int32 nRowSubLen = 0;
+ sal_Int32 nColSubLen = 0;
+ while (nRowIndex1 < nTableRows && aMap[nRowIndex1++][k] != '\0')
+ ++nRowSubLen;
+ // be aware of shifted sequences!
+ // (according to the checks done prior the length should be ok)
+ while (nColIndex1 < nTableCols && aMap[i][nColIndex1] != '\0'
+ && aMap[i + nRowSubLen-1][nColIndex1] != '\0')
+ {
+ ++nColIndex1;
+ ++nColSubLen;
+ }
+ String aStartCell( lcl_GetCellName( k, i ) );
+ String aEndCell( lcl_GetCellName( k + nColSubLen - 1, i + nRowSubLen - 1) );
+ aCurRange = aCellRangeBase;
+ aCurRange += aStartCell;
+ aCurRange += ':';
+ aCurRange += aEndCell;
+ if (aCellRanges.Len())
+ aCellRanges += ';';
+ aCellRanges += aCurRange;
+
+ // clear already found sub-range from map
+ for (sal_Int32 nRowIndex2 = 0; nRowIndex2 < nRowSubLen; ++nRowIndex2)
+ for (sal_Int32 nColumnIndex2 = 0; nColumnIndex2 < nColSubLen; ++nColumnIndex2)
+ aMap[i + nRowIndex2][k + nColumnIndex2] = '\0';
+ }
+ }
+ }
+ // to be nice to the user we now sort the cell ranges according to
+ // rows or columns depending on the direction used in the data source
+ uno::Sequence< OUString > aSortedRanges;
+ GetSubranges( aCellRanges, aSortedRanges, sal_False /*sub ranges should already be normalized*/ );
+ SortSubranges( aSortedRanges, (nDtaSrcIsColumns == 1) );
+ sal_Int32 nSortedRanges = aSortedRanges.getLength();
+ const OUString *pSortedRanges = aSortedRanges.getConstArray();
+ OUString aSortedCellRanges;
+ for (sal_Int32 i = 0; i < nSortedRanges; ++i)
+ {
+ if (aSortedCellRanges.getLength())
+ aSortedCellRanges += OUString::valueOf( (sal_Unicode) ';');
+ aSortedCellRanges += pSortedRanges[i];
+ }
+
+
+ // build value for 'SequenceMapping'
+ //
+ uno::Sequence< sal_Int32 > aSortedMapping( aSequenceMapping );
+ sal_Int32 *pSortedMapping = aSortedMapping.getArray();
+ std::sort( pSortedMapping, pSortedMapping + aSortedMapping.getLength() );
+ DBG_ASSERT( aSortedMapping.getLength() == nNumDS_LDS, "unexpected size of sequence" );
+ sal_Bool bNeedSequenceMapping = sal_False;
+ for (sal_Int32 i = 0; i < nNumDS_LDS; ++i)
+ {
+ sal_Int32 *pIt = std::find( pSortedMapping, pSortedMapping + nNumDS_LDS,
+ pSequenceMapping[i] );
+ DBG_ASSERT( pIt, "index not found" );
+ if (!pIt)
+ return aResult; // failed -> return empty property sequence
+ pSequenceMapping[i] = pIt - pSortedMapping;
+
+ if (i != pSequenceMapping[i])
+ bNeedSequenceMapping = sal_True;
+ }
+
+ // check if 'SequenceMapping' is actually not required...
+ // (don't write unnecessary properties to the XML file)
+ if (!bNeedSequenceMapping)
+ aSequenceMapping.realloc(0);
+
+ //
+ // build resulting properties
+ //
+ DBG_ASSERT(nLabelSeqLen >= 0 || nLabelSeqLen == -2 /*not used*/,
+ "unexpected value for 'nLabelSeqLen'" );
+ sal_Bool bFirstCellIsLabel = sal_False; // default value if 'nLabelSeqLen' could not properly determined
+ if (nLabelSeqLen > 0) // == 0 means no label sequence in use
+ bFirstCellIsLabel = sal_True;
+ //
+ DBG_ASSERT( aSortedCellRanges.getLength(), "CellRangeRepresentation missing" );
+ OUString aBrokenCellRangeForExport( GetBrokenCellRangeForExport( aSortedCellRanges ) );
+ //
+ aResult.realloc(5);
+ sal_Int32 nProps = 0;
+ aResult[nProps ].Name = C2U("FirstCellAsLabel");
+ aResult[nProps++].Value <<= bFirstCellIsLabel;
+ aResult[nProps ].Name = C2U("CellRangeRepresentation");
+ aResult[nProps++].Value <<= aSortedCellRanges;
+ if (0 != aBrokenCellRangeForExport.getLength())
+ {
+ aResult[nProps ].Name = C2U("BrokenCellRangeForExport");
+ aResult[nProps++].Value <<= aBrokenCellRangeForExport;
+ }
+ if (nDtaSrcIsColumns == 0 || nDtaSrcIsColumns == 1)
+ {
+ chart::ChartDataRowSource eDataRowSource = (nDtaSrcIsColumns == 1) ?
+ chart::ChartDataRowSource_COLUMNS : chart::ChartDataRowSource_ROWS;
+ aResult[nProps ].Name = C2U("DataRowSource");
+ aResult[nProps++].Value <<= eDataRowSource;
+
+ if (aSequenceMapping.getLength() != 0)
+ {
+ aResult[nProps ].Name = C2U("SequenceMapping");
+ aResult[nProps++].Value <<= aSequenceMapping;
+ }
+ }
+ aResult.realloc( nProps );
+
+ return aResult;
+}
+
+uno::Reference< chart2::data::XDataSequence > SwChartDataProvider::Impl_createDataSequenceByRangeRepresentation(
+ const OUString& rRangeRepresentation, sal_Bool bTestOnly )
+ throw (lang::IllegalArgumentException, uno::RuntimeException)
+{
+ if (bDisposed)
+ throw lang::DisposedException();
+
+ SwFrmFmt *pTblFmt = 0; // pointer to table format
+ SwUnoCrsr *pUnoCrsr = 0; // pointer to new created cursor spanning the cell range
+ GetFormatAndCreateCursorFromRangeRep( pDoc, rRangeRepresentation,
+ &pTblFmt, &pUnoCrsr );
+ if (!pTblFmt || !pUnoCrsr)
+ throw lang::IllegalArgumentException();
+
+ // check that cursors point and mark are in a single row or column.
+ String aCellRange( GetCellRangeName( *pTblFmt, *pUnoCrsr ) );
+ SwRangeDescriptor aDesc;
+ FillRangeDescriptor( aDesc, aCellRange );
+ if (aDesc.nTop != aDesc.nBottom && aDesc.nLeft != aDesc.nRight)
+ throw lang::IllegalArgumentException();
+
+ DBG_ASSERT( pTblFmt && pUnoCrsr, "table format or cursor missing" );
+ uno::Reference< chart2::data::XDataSequence > xDataSeq;
+ if (!bTestOnly)
+ xDataSeq = new SwChartDataSequence( *this, *pTblFmt, pUnoCrsr );
+
+ return xDataSeq;
+}
+
+sal_Bool SAL_CALL SwChartDataProvider::createDataSequenceByRangeRepresentationPossible(
+ const OUString& rRangeRepresentation )
+ throw (uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+
+ sal_Bool bPossible = sal_True;
+ try
+ {
+ Impl_createDataSequenceByRangeRepresentation( rRangeRepresentation, sal_True );
+ }
+ catch (lang::IllegalArgumentException &)
+ {
+ bPossible = sal_False;
+ }
+
+ return bPossible;
+}
+
+uno::Reference< chart2::data::XDataSequence > SAL_CALL SwChartDataProvider::createDataSequenceByRangeRepresentation(
+ const OUString& rRangeRepresentation )
+ throw (lang::IllegalArgumentException, uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+ return Impl_createDataSequenceByRangeRepresentation( rRangeRepresentation );
+}
+
+uno::Reference< sheet::XRangeSelection > SAL_CALL SwChartDataProvider::getRangeSelection( )
+ throw (uno::RuntimeException)
+{
+ // note: it is no error to return nothing here
+ return uno::Reference< sheet::XRangeSelection >();
+}
+
+void SAL_CALL SwChartDataProvider::dispose( )
+ throw (uno::RuntimeException)
+{
+ sal_Bool bMustDispose( sal_False );
+ {
+ osl::MutexGuard aGuard( GetChartMutex() );
+ bMustDispose = !bDisposed;
+ if (!bDisposed)
+ bDisposed = sal_True;
+ }
+ if (bMustDispose)
+ {
+ // dispose all data-sequences
+ Map_Set_DataSequenceRef_t::iterator aIt( aDataSequences.begin() );
+ while (aIt != aDataSequences.end())
+ {
+ DisposeAllDataSequences( (*aIt).first );
+ ++aIt;
+ }
+ // release all references to data-sequences
+ aDataSequences.clear();
+
+ // require listeners to release references to this object
+ lang::EventObject aEvtObj( dynamic_cast< chart2::data::XDataSequence * >(this) );
+ aEvtListeners.disposeAndClear( aEvtObj );
+ }
+}
+
+void SAL_CALL SwChartDataProvider::addEventListener(
+ const uno::Reference< lang::XEventListener >& rxListener )
+ throw (uno::RuntimeException)
+{
+ osl::MutexGuard aGuard( GetChartMutex() );
+ if (!bDisposed && rxListener.is())
+ aEvtListeners.addInterface( rxListener );
+}
+
+void SAL_CALL SwChartDataProvider::removeEventListener(
+ const uno::Reference< lang::XEventListener >& rxListener )
+ throw (uno::RuntimeException)
+{
+ osl::MutexGuard aGuard( GetChartMutex() );
+ if (!bDisposed && rxListener.is())
+ aEvtListeners.removeInterface( rxListener );
+}
+
+OUString SAL_CALL SwChartDataProvider::getImplementationName( )
+ throw (uno::RuntimeException)
+{
+ return C2U("SwChartDataProvider");
+}
+
+sal_Bool SAL_CALL SwChartDataProvider::supportsService(
+ const OUString& rServiceName )
+ throw (uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+ return rServiceName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( SN_DATA_PROVIDER ) );
+}
+
+uno::Sequence< OUString > SAL_CALL SwChartDataProvider::getSupportedServiceNames( )
+ throw (uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+ uno::Sequence< OUString > aRes(1);
+ aRes.getArray()[0] = C2U( SN_DATA_PROVIDER );
+ return aRes;
+}
+
+void SwChartDataProvider::Modify( const SfxPoolItem* pOld, const SfxPoolItem *pNew)
+{
+ // actually this function should be superfluous (need to check later)
+ ClientModify(this, pOld, pNew );
+}
+
+void SwChartDataProvider::AddDataSequence( const SwTable &rTable, uno::Reference< chart2::data::XDataSequence > &rxDataSequence )
+{
+ aDataSequences[ &rTable ].insert( rxDataSequence );
+}
+
+void SwChartDataProvider::RemoveDataSequence( const SwTable &rTable, uno::Reference< chart2::data::XDataSequence > &rxDataSequence )
+{
+ aDataSequences[ &rTable ].erase( rxDataSequence );
+}
+
+void SwChartDataProvider::InvalidateTable( const SwTable *pTable )
+{
+ DBG_ASSERT( pTable, "table pointer is NULL" );
+ if (pTable)
+ {
+ if (!bDisposed)
+ pTable->GetFrmFmt()->GetDoc()->GetChartControllerHelper().StartOrContinueLocking();
+
+ const Set_DataSequenceRef_t &rSet = aDataSequences[ pTable ];
+ Set_DataSequenceRef_t::const_iterator aIt( rSet.begin() );
+ while (aIt != rSet.end())
+ {
+ uno::Reference< chart2::data::XDataSequence > xTemp(*aIt); // temporary needed for g++ 3.3.5
+ uno::Reference< util::XModifiable > xRef( xTemp, uno::UNO_QUERY );
+ if (xRef.is())
+ {
+ // mark the sequence as 'dirty' and notify listeners
+ xRef->setModified( sal_True );
+ }
+ ++aIt;
+ }
+ }
+}
+
+sal_Bool SwChartDataProvider::DeleteBox( const SwTable *pTable, const SwTableBox &rBox )
+{
+ sal_Bool bRes = sal_False;
+ DBG_ASSERT( pTable, "table pointer is NULL" );
+ if (pTable)
+ {
+ if (!bDisposed)
+ pTable->GetFrmFmt()->GetDoc()->GetChartControllerHelper().StartOrContinueLocking();
+
+ Set_DataSequenceRef_t &rSet = aDataSequences[ pTable ];
+
+ // iterate over all data-sequences for that table...
+ Set_DataSequenceRef_t::iterator aIt( rSet.begin() );
+ Set_DataSequenceRef_t::iterator aEndIt( rSet.end() );
+ Set_DataSequenceRef_t::iterator aDelIt; // iterator used for deletion when appropriate
+ while (aIt != aEndIt)
+ {
+ SwChartDataSequence *pDataSeq = 0;
+ sal_Bool bNowEmpty = sal_False;
+
+ // check if weak reference is still valid...
+ uno::Reference< chart2::data::XDataSequence > xTemp(*aIt); // temporary needed for g++ 3.3.5
+ uno::Reference< chart2::data::XDataSequence > xRef( xTemp, uno::UNO_QUERY );
+ if (xRef.is())
+ {
+ // then delete that table box (check if implementation cursor needs to be adjusted)
+ pDataSeq = static_cast< SwChartDataSequence * >( xRef.get() );
+ if (pDataSeq)
+ {
+#if OSL_DEBUG_LEVEL > 1
+ OUString aRangeStr( pDataSeq->getSourceRangeRepresentation() );
+#endif
+ bNowEmpty = pDataSeq->DeleteBox( rBox );
+ if (bNowEmpty)
+ aDelIt = aIt;
+ }
+ }
+ ++aIt;
+
+ if (bNowEmpty)
+ {
+ rSet.erase( aDelIt );
+ if (pDataSeq)
+ pDataSeq->dispose(); // the current way to tell chart that sth. got removed
+ }
+ }
+ }
+ return bRes;
+}
+
+void SwChartDataProvider::DisposeAllDataSequences( const SwTable *pTable )
+{
+ DBG_ASSERT( pTable, "table pointer is NULL" );
+ if (pTable)
+ {
+ if (!bDisposed)
+ pTable->GetFrmFmt()->GetDoc()->GetChartControllerHelper().StartOrContinueLocking();
+
+ //! make a copy of the STL container!
+ //! This is necessary since calling 'dispose' will implicitly remove an element
+ //! of the original container, and thus any iterator in the original container
+ //! would become invalid.
+ const Set_DataSequenceRef_t aSet( aDataSequences[ pTable ] );
+
+ Set_DataSequenceRef_t::const_iterator aIt( aSet.begin() );
+ Set_DataSequenceRef_t::const_iterator aEndIt( aSet.end() );
+ while (aIt != aEndIt)
+ {
+ uno::Reference< chart2::data::XDataSequence > xTemp(*aIt); // temporary needed for g++ 3.3.5
+ uno::Reference< lang::XComponent > xRef( xTemp, uno::UNO_QUERY );
+ if (xRef.is())
+ {
+ xRef->dispose();
+ }
+ ++aIt;
+ }
+ }
+}
+
+////////////////////////////////////////
+// SwChartDataProvider::AddRowCols tries to notify charts of added columns
+// or rows and extends the value sequence respectively (if possible).
+// If those can be added to the end of existing value data-sequences those
+// sequences get mofdified accordingly and will send a modification
+// notification (calling 'setModified').
+//
+// Since this function is a work-around for non existent Writer core functionality
+// (no arbitrary multi-selection in tables that can be used to define a
+// data-sequence) this function will be somewhat unreliable.
+// For example we will only try to adapt value sequences. For this we assume
+// that a sequence of length 1 is a label sequence and those with length >= 2
+// we presume to be value sequences. Also new cells can only be added in the
+// direction the value sequence is already pointing (rows / cols) and at the
+// start or end of the values data-sequence.
+// Nothing needs to be done if the new cells are in between the table cursors
+// point and mark since data-sequence are considered to consist of all cells
+// between those.
+// New rows/cols need to be added already to the table before calling
+// this function.
+//
+void SwChartDataProvider::AddRowCols(
+ const SwTable &rTable,
+ const SwSelBoxes& rBoxes,
+ sal_uInt16 nLines, sal_Bool bBehind )
+{
+ if (rTable.IsTblComplex())
+ return;
+
+ const sal_uInt16 nBoxes = rBoxes.Count();
+ if (nBoxes < 1 || nLines < 1)
+ return;
+
+ SwTableBox* pFirstBox = *( rBoxes.GetData() + 0 );
+ SwTableBox* pLastBox = *( rBoxes.GetData() + nBoxes - 1 );
+
+ if (pFirstBox && pLastBox)
+ {
+ sal_Int32 nFirstCol = -1, nFirstRow = -1, nLastCol = -1, nLastRow = -1;
+ lcl_GetCellPosition( pFirstBox->GetName(), nFirstCol, nFirstRow );
+ lcl_GetCellPosition( pLastBox->GetName(), nLastCol, nLastRow );
+
+ bool bAddCols = false; // default; also to be used if nBoxes == 1 :-/
+ if (nFirstCol == nLastCol && nFirstRow != nLastRow)
+ bAddCols = true;
+ if (nFirstCol == nLastCol || nFirstRow == nLastRow)
+ {
+ //get range of indices in col/rows for new cells
+ sal_Int32 nFirstNewCol = nFirstCol;
+ sal_Int32 nFirstNewRow = bBehind ? nFirstRow + 1 : nFirstRow - nLines;
+ if (bAddCols)
+ {
+ DBG_ASSERT( nFirstCol == nLastCol, "column indices seem broken" );
+ nFirstNewCol = bBehind ? nFirstCol + 1 : nFirstCol - nLines;
+ nFirstNewRow = nFirstRow;
+ }
+
+ // iterate over all data-sequences for the table
+ const Set_DataSequenceRef_t &rSet = aDataSequences[ &rTable ];
+ Set_DataSequenceRef_t::const_iterator aIt( rSet.begin() );
+ while (aIt != rSet.end())
+ {
+ uno::Reference< chart2::data::XDataSequence > xTemp(*aIt); // temporary needed for g++ 3.3.5
+ uno::Reference< chart2::data::XTextualDataSequence > xRef( xTemp, uno::UNO_QUERY );
+ if (xRef.is())
+ {
+ const sal_Int32 nLen = xRef->getTextualData().getLength();
+ if (nLen > 1) // value data-sequence ?
+ {
+ SwChartDataSequence *pDataSeq = 0;
+ uno::Reference< lang::XUnoTunnel > xTunnel( xRef, uno::UNO_QUERY );
+ if(xTunnel.is())
+ {
+ pDataSeq = reinterpret_cast< SwChartDataSequence * >(
+ sal::static_int_cast< sal_IntPtr >( xTunnel->getSomething( SwChartDataSequence::getUnoTunnelId() )));
+
+ if (pDataSeq)
+ {
+ SwRangeDescriptor aDesc;
+ pDataSeq->FillRangeDesc( aDesc );
+
+ chart::ChartDataRowSource eDRSource = chart::ChartDataRowSource_COLUMNS;
+ if (aDesc.nTop == aDesc.nBottom && aDesc.nLeft != aDesc.nRight)
+ eDRSource = chart::ChartDataRowSource_ROWS;
+
+ if (!bAddCols && eDRSource == chart::ChartDataRowSource_COLUMNS)
+ {
+ // add rows: extend affected columns by newly added row cells
+ pDataSeq->ExtendTo( true, nFirstNewRow, nLines );
+ }
+ else if (bAddCols && eDRSource == chart::ChartDataRowSource_ROWS)
+ {
+ // add cols: extend affected rows by newly added column cells
+ pDataSeq->ExtendTo( false, nFirstNewCol, nLines );
+ }
+ }
+ }
+ }
+ }
+ ++aIt;
+ }
+
+ }
+ }
+}
+
+// XRangeXMLConversion ---------------------------------------------------
+rtl::OUString SAL_CALL SwChartDataProvider::convertRangeToXML( const rtl::OUString& rRangeRepresentation )
+ throw ( uno::RuntimeException, lang::IllegalArgumentException )
+{
+ SolarMutexGuard aGuard;
+ if (bDisposed)
+ throw lang::DisposedException();
+
+ String aRes;
+ String aRangeRepresentation( rRangeRepresentation );
+
+ // multiple ranges are delimeted by a ';' like in
+ // "Table1.A1:A4;Table1.C2:C5" the same table must be used in all ranges!
+ xub_StrLen nNumRanges = aRangeRepresentation.GetTokenCount( ';' );
+ SwTable* pFirstFoundTable = 0; // to check that only one table will be used
+ for (sal_uInt16 i = 0; i < nNumRanges; ++i)
+ {
+ String aRange( aRangeRepresentation.GetToken(i, ';') );
+ SwFrmFmt *pTblFmt = 0; // pointer to table format
+ GetFormatAndCreateCursorFromRangeRep( pDoc, aRange, &pTblFmt, NULL );
+ if (!pTblFmt)
+ throw lang::IllegalArgumentException();
+ SwTable* pTable = SwTable::FindTable( pTblFmt );
+ if (pTable->IsTblComplex())
+ throw uno::RuntimeException();
+
+ // check that there is only one table used in all ranges
+ if (!pFirstFoundTable)
+ pFirstFoundTable = pTable;
+ if (pTable != pFirstFoundTable)
+ throw lang::IllegalArgumentException();
+
+ String aTblName;
+ String aStartCell;
+ String aEndCell;
+ if (!GetTableAndCellsFromRangeRep( aRange, aTblName, aStartCell, aEndCell ))
+ throw lang::IllegalArgumentException();
+
+ sal_Int32 nCol, nRow;
+ lcl_GetCellPosition( aStartCell, nCol, nRow );
+ if (nCol < 0 || nRow < 0)
+ throw uno::RuntimeException();
+
+ //!! following objects/functions are implemented in XMLRangeHelper.?xx
+ //!! which is a copy of the respective file from chart2 !!
+ XMLRangeHelper::CellRange aCellRange;
+ aCellRange.aTableName = aTblName;
+ aCellRange.aUpperLeft.nColumn = nCol;
+ aCellRange.aUpperLeft.nRow = nRow;
+ aCellRange.aUpperLeft.bIsEmpty = false;
+ if (aStartCell != aEndCell && aEndCell.Len() != 0)
+ {
+ lcl_GetCellPosition( aEndCell, nCol, nRow );
+ if (nCol < 0 || nRow < 0)
+ throw uno::RuntimeException();
+
+ aCellRange.aLowerRight.nColumn = nCol;
+ aCellRange.aLowerRight.nRow = nRow;
+ aCellRange.aLowerRight.bIsEmpty = false;
+ }
+ String aTmp( XMLRangeHelper::getXMLStringFromCellRange( aCellRange ) );
+ if (aRes.Len()) // in case of multiple ranges add delimeter
+ aRes.AppendAscii( " " );
+ aRes += aTmp;
+ }
+
+ return aRes;
+}
+
+rtl::OUString SAL_CALL SwChartDataProvider::convertRangeFromXML( const rtl::OUString& rXMLRange )
+ throw ( uno::RuntimeException, lang::IllegalArgumentException )
+{
+ SolarMutexGuard aGuard;
+ if (bDisposed)
+ throw lang::DisposedException();
+
+ String aRes;
+ String aXMLRange( rXMLRange );
+
+ // multiple ranges are delimeted by a ' ' like in
+ // "Table1.$A$1:.$A$4 Table1.$C$2:.$C$5" the same table must be used in all ranges!
+ xub_StrLen nNumRanges = aXMLRange.GetTokenCount( ' ' );
+ rtl::OUString aFirstFoundTable; // to check that only one table will be used
+ for (sal_uInt16 i = 0; i < nNumRanges; ++i)
+ {
+ String aRange( aXMLRange.GetToken(i, ' ') );
+
+ //!! following objects and function are implemented in XMLRangeHelper.?xx
+ //!! which is a copy of the respective file from chart2 !!
+ XMLRangeHelper::CellRange aCellRange( XMLRangeHelper::getCellRangeFromXMLString( aRange ));
+
+ // check that there is only one table used in all ranges
+ if (aFirstFoundTable.getLength() == 0)
+ aFirstFoundTable = aCellRange.aTableName;
+ if (aCellRange.aTableName != aFirstFoundTable)
+ throw lang::IllegalArgumentException();
+
+ OUString aTmp( aCellRange.aTableName );
+ aTmp += OUString::valueOf((sal_Unicode) '.');
+ aTmp += lcl_GetCellName( aCellRange.aUpperLeft.nColumn,
+ aCellRange.aUpperLeft.nRow );
+ // does cell range consist of more than a single cell?
+ if (!aCellRange.aLowerRight.bIsEmpty)
+ {
+ aTmp += OUString::valueOf((sal_Unicode) ':');
+ aTmp += lcl_GetCellName( aCellRange.aLowerRight.nColumn,
+ aCellRange.aLowerRight.nRow );
+ }
+
+ if (aRes.Len()) // in case of multiple ranges add delimeter
+ aRes.AppendAscii( ";" );
+ aRes += String(aTmp);
+ }
+
+ return aRes;
+}
+
+SwChartDataSource::SwChartDataSource(
+ const uno::Sequence< uno::Reference< chart2::data::XLabeledDataSequence > > &rLDS ) :
+ aLDS( rLDS )
+{
+}
+
+SwChartDataSource::~SwChartDataSource()
+{
+}
+
+uno::Sequence< uno::Reference< chart2::data::XLabeledDataSequence > > SAL_CALL SwChartDataSource::getDataSequences( )
+ throw (uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+ return aLDS;
+}
+
+OUString SAL_CALL SwChartDataSource::getImplementationName( )
+ throw (uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+ return C2U("SwChartDataSource");
+}
+
+sal_Bool SAL_CALL SwChartDataSource::supportsService(
+ const OUString& rServiceName )
+ throw (uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+ return rServiceName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( SN_DATA_SOURCE ) );
+}
+
+uno::Sequence< OUString > SAL_CALL SwChartDataSource::getSupportedServiceNames( )
+ throw (uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+ uno::Sequence< OUString > aRes(1);
+ aRes.getArray()[0] = C2U( SN_DATA_SOURCE );
+ return aRes;
+}
+
+SwChartDataSequence::SwChartDataSequence(
+ SwChartDataProvider &rProvider,
+ SwFrmFmt &rTblFmt,
+ SwUnoCrsr *pTableCursor ) :
+ SwClient( &rTblFmt ),
+ aEvtListeners( GetChartMutex() ),
+ aModifyListeners( GetChartMutex() ),
+ aRowLabelText( SW_RES( STR_CHART2_ROW_LABEL_TEXT ) ),
+ aColLabelText( SW_RES( STR_CHART2_COL_LABEL_TEXT ) ),
+ xDataProvider( &rProvider ),
+ pDataProvider( &rProvider ),
+ pTblCrsr( pTableCursor ),
+ aCursorDepend( this, pTableCursor ),
+ _pPropSet( aSwMapProvider.GetPropertySet( PROPERTY_MAP_CHART2_DATA_SEQUENCE ) )
+{
+ bDisposed = sal_False;
+
+ acquire();
+ try
+ {
+ const SwTable* pTable = SwTable::FindTable( &rTblFmt );
+ if (pTable)
+ {
+ uno::Reference< chart2::data::XDataSequence > xRef( dynamic_cast< chart2::data::XDataSequence * >(this), uno::UNO_QUERY );
+ pDataProvider->AddDataSequence( *pTable, xRef );
+ pDataProvider->addEventListener( dynamic_cast< lang::XEventListener * >(this) );
+ }
+ else {
+ OSL_FAIL( "table missing" );
+ }
+ }
+ catch (uno::RuntimeException &)
+ {
+ throw;
+ }
+ catch (uno::Exception &)
+ {
+ }
+ release();
+
+#if OSL_DEBUG_LEVEL > 1
+ OUString aRangeStr( getSourceRangeRepresentation() );
+
+ // check if it can properly convert into a SwUnoTableCrsr
+ // which is required for some functions
+ SwUnoTableCrsr* pUnoTblCrsr = dynamic_cast<SwUnoTableCrsr*>(pTblCrsr);
+ DBG_ASSERT(pUnoTblCrsr, "SwChartDataSequence: cursor not SwUnoTableCrsr");
+ (void) pUnoTblCrsr;
+#endif
+}
+
+SwChartDataSequence::SwChartDataSequence( const SwChartDataSequence &rObj ) :
+ SwChartDataSequenceBaseClass(),
+ SwClient( rObj.GetFrmFmt() ),
+ aEvtListeners( GetChartMutex() ),
+ aModifyListeners( GetChartMutex() ),
+ aRole( rObj.aRole ),
+ aRowLabelText( SW_RES(STR_CHART2_ROW_LABEL_TEXT) ),
+ aColLabelText( SW_RES(STR_CHART2_COL_LABEL_TEXT) ),
+ xDataProvider( rObj.pDataProvider ),
+ pDataProvider( rObj.pDataProvider ),
+ pTblCrsr( rObj.pTblCrsr->Clone() ),
+ aCursorDepend( this, pTblCrsr ),
+ _pPropSet( rObj._pPropSet )
+{
+ bDisposed = sal_False;
+
+ acquire();
+ try
+ {
+ const SwTable* pTable = SwTable::FindTable( GetFrmFmt() );
+ if (pTable)
+ {
+ uno::Reference< chart2::data::XDataSequence > xRef( dynamic_cast< chart2::data::XDataSequence * >(this), uno::UNO_QUERY );
+ pDataProvider->AddDataSequence( *pTable, xRef );
+ pDataProvider->addEventListener( dynamic_cast< lang::XEventListener * >(this) );
+ }
+ else {
+ OSL_FAIL( "table missing" );
+ }
+ }
+ catch (uno::RuntimeException &)
+ {
+ throw;
+ }
+ catch (uno::Exception &)
+ {
+ }
+ release();
+
+#if OSL_DEBUG_LEVEL > 1
+ OUString aRangeStr( getSourceRangeRepresentation() );
+
+ // check if it can properly convert into a SwUnoTableCrsr
+ // which is required for some functions
+ SwUnoTableCrsr* pUnoTblCrsr = dynamic_cast<SwUnoTableCrsr*>(pTblCrsr);
+ DBG_ASSERT(pUnoTblCrsr, "SwChartDataSequence: cursor not SwUnoTableCrsr");
+ (void) pUnoTblCrsr;
+#endif
+}
+
+SwChartDataSequence::~SwChartDataSequence()
+{
+ // since the data-provider holds only weak references to the data-sequence
+ // there should be no need here to release them explicitly...
+
+ delete pTblCrsr;
+}
+
+const uno::Sequence< sal_Int8 > & SwChartDataSequence::getUnoTunnelId()
+{
+ static uno::Sequence< sal_Int8 > aSeq = ::CreateUnoTunnelId();
+ return aSeq;
+}
+
+sal_Int64 SAL_CALL SwChartDataSequence::getSomething( const uno::Sequence< sal_Int8 > &rId )
+ throw(uno::RuntimeException)
+{
+ if( rId.getLength() == 16
+ && 0 == rtl_compareMemory( getUnoTunnelId().getConstArray(),
+ rId.getConstArray(), 16 ) )
+ {
+ return sal::static_int_cast< sal_Int64 >( reinterpret_cast< sal_IntPtr >(this) );
+ }
+ return 0;
+}
+
+uno::Sequence< uno::Any > SAL_CALL SwChartDataSequence::getData( )
+ throw (uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+ if (bDisposed)
+ throw lang::DisposedException();
+
+ uno::Sequence< uno::Any > aRes;
+ SwFrmFmt* pTblFmt = GetFrmFmt();
+ if(pTblFmt)
+ {
+ SwTable* pTable = SwTable::FindTable( pTblFmt );
+ if(!pTable->IsTblComplex())
+ {
+ SwRangeDescriptor aDesc;
+ if (FillRangeDescriptor( aDesc, GetCellRangeName( *pTblFmt, *pTblCrsr ) ))
+ {
+ //!! make copy of pTblCrsr (SwUnoCrsr )
+ // keep original cursor and make copy of it that gets handed
+ // over to the SwXCellRange object which takes ownership and
+ // thus will destroy the copy later.
+ SwXCellRange aRange( pTblCrsr->Clone(), *pTblFmt, aDesc );
+ aRange.GetDataSequence( &aRes, 0, 0 );
+ }
+ }
+ }
+ return aRes;
+}
+
+OUString SAL_CALL SwChartDataSequence::getSourceRangeRepresentation( )
+ throw (uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+ if (bDisposed)
+ throw lang::DisposedException();
+
+ String aRes;
+ SwFrmFmt* pTblFmt = GetFrmFmt();
+ if (pTblFmt)
+ {
+ aRes = pTblFmt->GetName();
+ String aCellRange( GetCellRangeName( *pTblFmt, *pTblCrsr ) );
+ DBG_ASSERT( aCellRange.Len() != 0, "failed to get cell range" );
+ aRes += (sal_Unicode) '.';
+ aRes += aCellRange;
+ }
+ return aRes;
+}
+
+uno::Sequence< OUString > SAL_CALL SwChartDataSequence::generateLabel(
+ chart2::data::LabelOrigin eLabelOrigin )
+ throw (uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+ if (bDisposed)
+ throw lang::DisposedException();
+
+ uno::Sequence< OUString > aLabels;
+
+ {
+ SwRangeDescriptor aDesc;
+ sal_Bool bOk sal_False;
+ SwFrmFmt* pTblFmt = GetFrmFmt();
+ SwTable* pTable = pTblFmt ? SwTable::FindTable( pTblFmt ) : 0;
+ if (!pTblFmt || !pTable || pTable->IsTblComplex())
+ throw uno::RuntimeException();
+ else
+ {
+ String aCellRange( GetCellRangeName( *pTblFmt, *pTblCrsr ) );
+ DBG_ASSERT( aCellRange.Len() != 0, "failed to get cell range" );
+ bOk = FillRangeDescriptor( aDesc, aCellRange );
+ DBG_ASSERT( bOk, "falied to get SwRangeDescriptor" );
+ }
+ if (bOk)
+ {
+ aDesc.Normalize();
+ sal_Int32 nColSpan = aDesc.nRight - aDesc.nLeft + 1;
+ sal_Int32 nRowSpan = aDesc.nBottom - aDesc.nTop + 1;
+ DBG_ASSERT( nColSpan == 1 || nRowSpan == 1,
+ "unexpected range of selected cells" );
+
+ String aTxt; // label text to be returned
+ sal_Bool bReturnEmptyTxt = sal_False;
+ sal_Bool bUseCol = sal_True;
+ if (eLabelOrigin == chart2::data::LabelOrigin_COLUMN)
+ bUseCol = sal_True;
+ else if (eLabelOrigin == chart2::data::LabelOrigin_ROW)
+ bUseCol = sal_False;
+ else if (eLabelOrigin == chart2::data::LabelOrigin_SHORT_SIDE)
+ {
+ bUseCol = nColSpan < nRowSpan;
+ bReturnEmptyTxt = nColSpan == nRowSpan;
+ }
+ else if (eLabelOrigin == chart2::data::LabelOrigin_LONG_SIDE)
+ {
+ bUseCol = nColSpan > nRowSpan;
+ bReturnEmptyTxt = nColSpan == nRowSpan;
+ }
+ else {
+ OSL_FAIL( "unexpected case" );
+ }
+
+ // build label sequence
+ //
+ sal_Int32 nSeqLen = bUseCol ? nColSpan : nRowSpan;
+ aLabels.realloc( nSeqLen );
+ OUString *pLabels = aLabels.getArray();
+ for (sal_Int32 i = 0; i < nSeqLen; ++i)
+ {
+ if (!bReturnEmptyTxt)
+ {
+ aTxt = bUseCol ? aColLabelText : aRowLabelText;
+ sal_Int32 nCol = aDesc.nLeft;
+ sal_Int32 nRow = aDesc.nTop;
+ if (bUseCol)
+ nCol = nCol + i;
+ else
+ nRow = nRow + i;
+ String aCellName( lcl_GetCellName( nCol, nRow ) );
+
+ xub_StrLen nLen = aCellName.Len();
+ if (nLen)
+ {
+ const sal_Unicode *pBuf = aCellName.GetBuffer();
+ const sal_Unicode *pEnd = pBuf + nLen;
+ while (pBuf < pEnd && !('0' <= *pBuf && *pBuf <= '9'))
+ ++pBuf;
+ // start of number found?
+ if (pBuf < pEnd && ('0' <= *pBuf && *pBuf <= '9'))
+ {
+ String aRplc;
+ String aNew;
+ if (bUseCol)
+ {
+ aRplc = String::CreateFromAscii( "%COLUMNLETTER" );
+ aNew = String( aCellName.GetBuffer(), static_cast<xub_StrLen>(pBuf - aCellName.GetBuffer()) );
+ }
+ else
+ {
+ aRplc = String::CreateFromAscii( "%ROWNUMBER" );
+ aNew = String( pBuf, static_cast<xub_StrLen>((aCellName.GetBuffer() + nLen) - pBuf) );
+ }
+ xub_StrLen nPos = aTxt.Search( aRplc );
+ if (nPos != STRING_NOTFOUND)
+ aTxt = aTxt.Replace( nPos, aRplc.Len(), aNew );
+ }
+ }
+ }
+ pLabels[i] = aTxt;
+ }
+ }
+ }
+
+ return aLabels;
+}
+
+::sal_Int32 SAL_CALL SwChartDataSequence::getNumberFormatKeyByIndex(
+ ::sal_Int32 /*nIndex*/ )
+ throw (lang::IndexOutOfBoundsException,
+ uno::RuntimeException)
+{
+ return 0;
+}
+
+uno::Sequence< OUString > SAL_CALL SwChartDataSequence::getTextualData( )
+ throw (uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+ if (bDisposed)
+ throw lang::DisposedException();
+
+ uno::Sequence< OUString > aRes;
+ SwFrmFmt* pTblFmt = GetFrmFmt();
+ if(pTblFmt)
+ {
+ SwTable* pTable = SwTable::FindTable( pTblFmt );
+ if(!pTable->IsTblComplex())
+ {
+ SwRangeDescriptor aDesc;
+ if (FillRangeDescriptor( aDesc, GetCellRangeName( *pTblFmt, *pTblCrsr ) ))
+ {
+ //!! make copy of pTblCrsr (SwUnoCrsr )
+ // keep original cursor and make copy of it that gets handed
+ // over to the SwXCellRange object which takes ownership and
+ // thus will destroy the copy later.
+ SwXCellRange aRange( pTblCrsr->Clone(), *pTblFmt, aDesc );
+ aRange.GetDataSequence( 0, &aRes, 0 );
+ }
+ }
+ }
+ return aRes;
+}
+
+uno::Sequence< double > SAL_CALL SwChartDataSequence::getNumericalData( )
+ throw (uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+ if (bDisposed)
+ throw lang::DisposedException();
+
+ uno::Sequence< double > aRes;
+ SwFrmFmt* pTblFmt = GetFrmFmt();
+ if(pTblFmt)
+ {
+ SwTable* pTable = SwTable::FindTable( pTblFmt );
+ if(!pTable->IsTblComplex())
+ {
+ SwRangeDescriptor aDesc;
+ if (FillRangeDescriptor( aDesc, GetCellRangeName( *pTblFmt, *pTblCrsr ) ))
+ {
+ //!! make copy of pTblCrsr (SwUnoCrsr )
+ // keep original cursor and make copy of it that gets handed
+ // over to the SwXCellRange object which takes ownership and
+ // thus will destroy the copy later.
+ SwXCellRange aRange( pTblCrsr->Clone(), *pTblFmt, aDesc );
+
+ // get numerical values and make an effort to return the
+ // numerical value for text formatted cells
+ aRange.GetDataSequence( 0, 0, &aRes, sal_True );
+ }
+ }
+ }
+ return aRes;
+}
+
+uno::Reference< util::XCloneable > SAL_CALL SwChartDataSequence::createClone( )
+ throw (uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+ if (bDisposed)
+ throw lang::DisposedException();
+ return new SwChartDataSequence( *this );
+}
+
+uno::Reference< beans::XPropertySetInfo > SAL_CALL SwChartDataSequence::getPropertySetInfo( )
+ throw (uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+ if (bDisposed)
+ throw lang::DisposedException();
+
+ static uno::Reference< beans::XPropertySetInfo > xRes = _pPropSet->getPropertySetInfo();
+ return xRes;
+}
+
+void SAL_CALL SwChartDataSequence::setPropertyValue(
+ const OUString& rPropertyName,
+ const uno::Any& rValue )
+ throw (beans::UnknownPropertyException, beans::PropertyVetoException, lang::IllegalArgumentException, lang::WrappedTargetException, uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+ if (bDisposed)
+ throw lang::DisposedException();
+
+ if (rPropertyName.equalsAscii( SW_PROP_NAME_STR( UNO_NAME_ROLE )))
+ {
+ if ( !(rValue >>= aRole) )
+ throw lang::IllegalArgumentException();
+ }
+ else
+ throw beans::UnknownPropertyException();
+}
+
+uno::Any SAL_CALL SwChartDataSequence::getPropertyValue(
+ const OUString& rPropertyName )
+ throw (beans::UnknownPropertyException, lang::WrappedTargetException, uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+ if (bDisposed)
+ throw lang::DisposedException();
+
+ uno::Any aRes;
+ if (rPropertyName.equalsAscii( SW_PROP_NAME_STR( UNO_NAME_ROLE )))
+ aRes <<= aRole;
+ else
+ throw beans::UnknownPropertyException();
+
+ return aRes;
+}
+
+void SAL_CALL SwChartDataSequence::addPropertyChangeListener(
+ const OUString& /*rPropertyName*/,
+ const uno::Reference< beans::XPropertyChangeListener >& /*xListener*/ )
+ throw (beans::UnknownPropertyException, lang::WrappedTargetException, uno::RuntimeException)
+{
+ OSL_FAIL( "not implemented" );
+}
+
+void SAL_CALL SwChartDataSequence::removePropertyChangeListener(
+ const OUString& /*rPropertyName*/,
+ const uno::Reference< beans::XPropertyChangeListener >& /*xListener*/ )
+ throw (beans::UnknownPropertyException, lang::WrappedTargetException, uno::RuntimeException)
+{
+ OSL_FAIL( "not implemented" );
+}
+
+void SAL_CALL SwChartDataSequence::addVetoableChangeListener(
+ const OUString& /*rPropertyName*/,
+ const uno::Reference< beans::XVetoableChangeListener >& /*xListener*/ )
+ throw (beans::UnknownPropertyException, lang::WrappedTargetException, uno::RuntimeException)
+{
+ OSL_FAIL( "not implemented" );
+}
+
+void SAL_CALL SwChartDataSequence::removeVetoableChangeListener(
+ const OUString& /*rPropertyName*/,
+ const uno::Reference< beans::XVetoableChangeListener >& /*xListener*/ )
+ throw (beans::UnknownPropertyException, lang::WrappedTargetException, uno::RuntimeException)
+{
+ OSL_FAIL( "not implemented" );
+}
+
+OUString SAL_CALL SwChartDataSequence::getImplementationName( )
+ throw (uno::RuntimeException)
+{
+ return C2U("SwChartDataSequence");
+}
+
+sal_Bool SAL_CALL SwChartDataSequence::supportsService(
+ const OUString& rServiceName )
+ throw (uno::RuntimeException)
+{
+ return rServiceName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( SN_DATA_SEQUENCE ) );
+}
+
+uno::Sequence< OUString > SAL_CALL SwChartDataSequence::getSupportedServiceNames( )
+ throw (uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+ uno::Sequence< OUString > aRes(1);
+ aRes.getArray()[0] = C2U( SN_DATA_SEQUENCE );
+ return aRes;
+}
+
+void SwChartDataSequence::Modify( const SfxPoolItem* pOld, const SfxPoolItem *pNew)
+{
+ ClientModify(this, pOld, pNew );
+
+ // table was deleted or cursor was deleted
+ if(!GetRegisteredIn() || !aCursorDepend.GetRegisteredIn())
+ {
+ pTblCrsr = 0;
+ dispose();
+ }
+ else
+ {
+ setModified( sal_True );
+ }
+}
+
+sal_Bool SAL_CALL SwChartDataSequence::isModified( )
+ throw (uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+ if (bDisposed)
+ throw lang::DisposedException();
+
+ return sal_True;
+}
+
+void SAL_CALL SwChartDataSequence::setModified(
+ ::sal_Bool bModified )
+ throw (beans::PropertyVetoException, uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+ if (bDisposed)
+ throw lang::DisposedException();
+
+ if (bModified)
+ LaunchModifiedEvent( aModifyListeners, dynamic_cast< XModifyBroadcaster * >(this) );
+}
+
+void SAL_CALL SwChartDataSequence::addModifyListener(
+ const uno::Reference< util::XModifyListener >& rxListener )
+ throw (uno::RuntimeException)
+{
+ osl::MutexGuard aGuard( GetChartMutex() );
+ if (!bDisposed && rxListener.is())
+ aModifyListeners.addInterface( rxListener );
+}
+
+void SAL_CALL SwChartDataSequence::removeModifyListener(
+ const uno::Reference< util::XModifyListener >& rxListener )
+ throw (uno::RuntimeException)
+{
+ osl::MutexGuard aGuard( GetChartMutex() );
+ if (!bDisposed && rxListener.is())
+ aModifyListeners.removeInterface( rxListener );
+}
+
+void SAL_CALL SwChartDataSequence::disposing( const lang::EventObject& rSource )
+ throw (uno::RuntimeException)
+{
+ if (bDisposed)
+ throw lang::DisposedException();
+ if (rSource.Source == xDataProvider)
+ {
+ pDataProvider = 0;
+ xDataProvider.clear();
+ }
+}
+
+void SAL_CALL SwChartDataSequence::dispose( )
+ throw (uno::RuntimeException)
+{
+ sal_Bool bMustDispose( sal_False );
+ {
+ osl::MutexGuard aGuard( GetChartMutex() );
+ bMustDispose = !bDisposed;
+ if (!bDisposed)
+ bDisposed = sal_True;
+ }
+ if (bMustDispose)
+ {
+ bDisposed = sal_True;
+ if (pDataProvider)
+ {
+ const SwTable* pTable = SwTable::FindTable( GetFrmFmt() );
+ if (pTable)
+ {
+ uno::Reference< chart2::data::XDataSequence > xRef( dynamic_cast< chart2::data::XDataSequence * >(this), uno::UNO_QUERY );
+ pDataProvider->RemoveDataSequence( *pTable, xRef );
+ }
+ else {
+ OSL_FAIL( "table missing" );
+ }
+ }
+
+ // require listeners to release references to this object
+ lang::EventObject aEvtObj( dynamic_cast< chart2::data::XDataSequence * >(this) );
+ aModifyListeners.disposeAndClear( aEvtObj );
+ aEvtListeners.disposeAndClear( aEvtObj );
+ }
+}
+
+void SAL_CALL SwChartDataSequence::addEventListener(
+ const uno::Reference< lang::XEventListener >& rxListener )
+ throw (uno::RuntimeException)
+{
+ osl::MutexGuard aGuard( GetChartMutex() );
+ if (!bDisposed && rxListener.is())
+ aEvtListeners.addInterface( rxListener );
+}
+
+void SAL_CALL SwChartDataSequence::removeEventListener(
+ const uno::Reference< lang::XEventListener >& rxListener )
+ throw (uno::RuntimeException)
+{
+ osl::MutexGuard aGuard( GetChartMutex() );
+ if (!bDisposed && rxListener.is())
+ aEvtListeners.removeInterface( rxListener );
+}
+
+sal_Bool SwChartDataSequence::DeleteBox( const SwTableBox &rBox )
+{
+#if OSL_DEBUG_LEVEL > 1
+ String aBoxName( rBox.GetName() );
+#endif
+
+ // to be set if the last box of the data-sequence was removed here
+ sal_Bool bNowEmpty = sal_False;
+
+ // if the implementation cursor gets affected (i.e. thew box where it is located
+ // in gets removed) we need to move it before that... (otherwise it does not need to change)
+ //
+ const SwStartNode* pPointStartNode = pTblCrsr->GetPoint()->nNode.GetNode().FindTableBoxStartNode();
+ const SwStartNode* pMarkStartNode = pTblCrsr->GetMark()->nNode.GetNode().FindTableBoxStartNode();
+ //
+ if (!pTblCrsr->HasMark() || (pPointStartNode == rBox.GetSttNd() && pMarkStartNode == rBox.GetSttNd()))
+ {
+ bNowEmpty = sal_True;
+ }
+ else if (pPointStartNode == rBox.GetSttNd() || pMarkStartNode == rBox.GetSttNd())
+ {
+ sal_Int32 nPointRow = -1, nPointCol = -1;
+ sal_Int32 nMarkRow = -1, nMarkCol = -1;
+ const SwTable* pTable = SwTable::FindTable( GetFrmFmt() );
+ String aPointCellName( pTable->GetTblBox( pPointStartNode->GetIndex() )->GetName() );
+ String aMarkCellName( pTable->GetTblBox( pMarkStartNode->GetIndex() )->GetName() );
+
+ lcl_GetCellPosition( aPointCellName, nPointCol, nPointRow );
+ lcl_GetCellPosition( aMarkCellName, nMarkCol, nMarkRow );
+ DBG_ASSERT( nPointRow >= 0 && nPointCol >= 0, "invalid row and col" );
+ DBG_ASSERT( nMarkRow >= 0 && nMarkCol >= 0, "invalid row and col" );
+
+ // move vertical or horizontal?
+ DBG_ASSERT( nPointRow == nMarkRow || nPointCol == nMarkCol,
+ "row/col indices not matching" );
+ DBG_ASSERT( nPointRow != nMarkRow || nPointCol != nMarkCol,
+ "point and mark are identical" );
+ sal_Bool bMoveVertical = (nPointCol == nMarkCol);
+ sal_Bool bMoveHorizontal = (nPointRow == nMarkRow);
+
+ // get movement direction
+ sal_Bool bMoveLeft = sal_False; // move left or right?
+ sal_Bool bMoveUp = sal_False; // move up or down?
+ if (bMoveVertical)
+ {
+ if (pPointStartNode == rBox.GetSttNd()) // move point?
+ bMoveUp = nPointRow > nMarkRow;
+ else // move mark
+ bMoveUp = nMarkRow > nPointRow;
+ }
+ else if (bMoveHorizontal)
+ {
+ if (pPointStartNode == rBox.GetSttNd()) // move point?
+ bMoveLeft = nPointCol > nMarkCol;
+ else // move mark
+ bMoveLeft = nMarkCol > nPointCol;
+ }
+ else {
+ OSL_FAIL( "neither vertical nor horizontal movement" );
+ }
+
+ // get new box (position) to use...
+ sal_Int32 nRow = (pPointStartNode == rBox.GetSttNd()) ? nPointRow : nMarkRow;
+ sal_Int32 nCol = (pPointStartNode == rBox.GetSttNd()) ? nPointCol : nMarkCol;
+ if (bMoveVertical)
+ nRow += bMoveUp ? -1 : +1;
+ if (bMoveHorizontal)
+ nCol += bMoveLeft ? -1 : +1;
+ String aNewCellName = lcl_GetCellName( nCol, nRow );
+ SwTableBox* pNewBox = (SwTableBox*) pTable->GetTblBox( aNewCellName );
+
+ if (pNewBox) // set new position (cell range) to use
+ {
+ // So erh lt man den ersten Inhaltsnode in einer gegebenen Zelle:
+ // Zun chst einen SwNodeIndex auf den Node hinter dem SwStartNode der Box...
+ SwNodeIndex aIdx( *pNewBox->GetSttNd(), +1 );
+ // Dies kann ein SwCntntNode sein, kann aber auch ein Tabellen oder Sectionnode sein,
+ // deshalb das GoNext;
+ SwCntntNode *pCNd = aIdx.GetNode().GetCntntNode();
+ if (!pCNd)
+ pCNd = GetFrmFmt()->GetDoc()->GetNodes().GoNext( &aIdx );
+ //und damit kann man z.B. eine SwPosition erzeugen:
+ SwPosition aNewPos( *pCNd ); // new position to beused with cursor
+
+ // if the mark is to be changed make sure there is one...
+ if (pMarkStartNode == rBox.GetSttNd() && !pTblCrsr->HasMark())
+ pTblCrsr->SetMark();
+
+ // set cursor to new position...
+ SwPosition *pPos = (pPointStartNode == rBox.GetSttNd()) ?
+ pTblCrsr->GetPoint() : pTblCrsr->GetMark();
+ if (pPos)
+ {
+ pPos->nNode = aNewPos.nNode;
+ pPos->nContent = aNewPos.nContent;
+ }
+ else {
+ OSL_FAIL( "neither point nor mark available for change" );
+ }
+ }
+ else {
+ OSL_FAIL( "failed to get position" );
+ }
+ }
+
+ return bNowEmpty;
+}
+
+void SwChartDataSequence::FillRangeDesc( SwRangeDescriptor &rRangeDesc ) const
+{
+ SwFrmFmt* pTblFmt = GetFrmFmt();
+ if(pTblFmt)
+ {
+ SwTable* pTable = SwTable::FindTable( pTblFmt );
+ if(!pTable->IsTblComplex())
+ {
+ FillRangeDescriptor( rRangeDesc, GetCellRangeName( *pTblFmt, *pTblCrsr ) );
+ }
+ }
+}
+
+/**
+SwChartDataSequence::ExtendTo
+
+extends the data-sequence by new cells added at the end of the direction
+the data-sequence points to.
+If the cells are already within the range of the sequence nothing needs
+to be done.
+If the cells are beyond the end of the sequence (are not adjacent to the
+current last cell) nothing can be done. Only if the cells are adjacent to
+the last cell they can be added.
+
+@returns true if the data-sequence was changed.
+@param bExtendCols
+ specifies if columns or rows are to be extended
+@param nFirstNew
+ index of first new row/col to be included in data-sequence
+@param nLastNew
+ index of last new row/col to be included in data-sequence
+*/
+bool SwChartDataSequence::ExtendTo( bool bExtendCol,
+ sal_Int32 nFirstNew, sal_Int32 nCount )
+{
+ bool bChanged = false;
+
+ SwUnoTableCrsr* pUnoTblCrsr = dynamic_cast<SwUnoTableCrsr*>(pTblCrsr);
+ //pUnoTblCrsr->MakeBoxSels();
+
+ const SwStartNode *pStartNd = 0;
+ const SwTableBox *pStartBox = 0;
+ const SwTableBox *pEndBox = 0;
+
+ const SwTable* pTable = SwTable::FindTable( GetFrmFmt() );
+ DBG_ASSERT( !pTable->IsTblComplex(), "table too complex" );
+ if (nCount < 1 || nFirstNew < 0 || pTable->IsTblComplex())
+ return false;
+
+ //
+ // get range descriptor (cell range) for current data-sequence
+ //
+ pStartNd = pUnoTblCrsr->GetPoint()->nNode.GetNode().FindTableBoxStartNode();
+ pEndBox = pTable->GetTblBox( pStartNd->GetIndex() );
+ const String aEndBox( pEndBox->GetName() );
+ //
+ pStartNd = pUnoTblCrsr->GetMark()->nNode.GetNode().FindTableBoxStartNode();
+ pStartBox = pTable->GetTblBox( pStartNd->GetIndex() );
+ const String aStartBox( pStartBox->GetName() );
+ //
+ String aCellRange( aStartBox ); // note that cell range here takes the newly added rows/cols already into account
+ aCellRange.AppendAscii( ":" );
+ aCellRange += aEndBox;
+ SwRangeDescriptor aDesc;
+ FillRangeDescriptor( aDesc, aCellRange );
+
+ String aNewStartCell;
+ String aNewEndCell;
+ if (bExtendCol && aDesc.nBottom + 1 == nFirstNew)
+ {
+ // new column cells adjacent to the bottom of the
+ // current data-sequence to be added...
+ DBG_ASSERT( aDesc.nLeft == aDesc.nRight, "data-sequence is not a column" );
+ aNewStartCell = lcl_GetCellName(aDesc.nLeft, aDesc.nTop);
+ aNewEndCell = lcl_GetCellName(aDesc.nRight, aDesc.nBottom + nCount);
+ bChanged = true;
+ }
+ else if (bExtendCol && aDesc.nTop - nCount == nFirstNew)
+ {
+ // new column cells adjacent to the top of the
+ // current data-sequence to be added...
+ DBG_ASSERT( aDesc.nLeft == aDesc.nRight, "data-sequence is not a column" );
+ aNewStartCell = lcl_GetCellName(aDesc.nLeft, aDesc.nTop - nCount);
+ aNewEndCell = lcl_GetCellName(aDesc.nRight, aDesc.nBottom);
+ bChanged = true;
+ }
+ else if (!bExtendCol && aDesc.nRight + 1 == nFirstNew)
+ {
+ // new row cells adjacent to the right of the
+ // current data-sequence to be added...
+ DBG_ASSERT( aDesc.nTop == aDesc.nBottom, "data-sequence is not a row" );
+ aNewStartCell = lcl_GetCellName(aDesc.nLeft, aDesc.nTop);
+ aNewEndCell = lcl_GetCellName(aDesc.nRight + nCount, aDesc.nBottom);
+ bChanged = true;
+ }
+ else if (!bExtendCol && aDesc.nLeft - nCount == nFirstNew)
+ {
+ // new row cells adjacent to the left of the
+ // current data-sequence to be added...
+ DBG_ASSERT( aDesc.nTop == aDesc.nBottom, "data-sequence is not a row" );
+ aNewStartCell = lcl_GetCellName(aDesc.nLeft - nCount, aDesc.nTop);
+ aNewEndCell = lcl_GetCellName(aDesc.nRight, aDesc.nBottom);
+ bChanged = true;
+ }
+
+ if (bChanged)
+ {
+ // move table cursor to new start and end of data-sequence
+ const SwTableBox *pNewStartBox = pTable->GetTblBox( aNewStartCell );
+ const SwTableBox *pNewEndBox = pTable->GetTblBox( aNewEndCell );
+ pUnoTblCrsr->SetMark();
+ pUnoTblCrsr->GetPoint()->nNode = *pNewEndBox->GetSttNd();
+ pUnoTblCrsr->GetMark()->nNode = *pNewStartBox->GetSttNd();
+ pUnoTblCrsr->Move( fnMoveForward, fnGoNode );
+ pUnoTblCrsr->MakeBoxSels();
+ }
+
+ return bChanged;
+}
+
+SwChartLabeledDataSequence::SwChartLabeledDataSequence() :
+ aEvtListeners( GetChartMutex() ),
+ aModifyListeners( GetChartMutex() )
+{
+ bDisposed = sal_False;
+}
+
+SwChartLabeledDataSequence::~SwChartLabeledDataSequence()
+{
+}
+
+uno::Reference< chart2::data::XDataSequence > SAL_CALL SwChartLabeledDataSequence::getValues( )
+ throw (uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+ if (bDisposed)
+ throw lang::DisposedException();
+ return xData;
+}
+
+void SwChartLabeledDataSequence::SetDataSequence(
+ uno::Reference< chart2::data::XDataSequence >& rxDest,
+ const uno::Reference< chart2::data::XDataSequence >& rxSource)
+{
+ uno::Reference< util::XModifyListener > xML( dynamic_cast< util::XModifyListener* >(this), uno::UNO_QUERY );
+ uno::Reference< lang::XEventListener > xEL( dynamic_cast< lang::XEventListener* >(this), uno::UNO_QUERY );
+
+ // stop listening to old data-sequence
+ uno::Reference< util::XModifyBroadcaster > xMB( rxDest, uno::UNO_QUERY );
+ if (xMB.is())
+ xMB->removeModifyListener( xML );
+ uno::Reference< lang::XComponent > xC( rxDest, uno::UNO_QUERY );
+ if (xC.is())
+ xC->removeEventListener( xEL );
+
+ rxDest = rxSource;
+
+ // start listening to new data-sequence
+ xC = uno::Reference< lang::XComponent >( rxDest, uno::UNO_QUERY );
+ if (xC.is())
+ xC->addEventListener( xEL );
+ xMB = uno::Reference< util::XModifyBroadcaster >( rxDest, uno::UNO_QUERY );
+ if (xMB.is())
+ xMB->addModifyListener( xML );
+}
+
+void SAL_CALL SwChartLabeledDataSequence::setValues(
+ const uno::Reference< chart2::data::XDataSequence >& rxSequence )
+ throw (uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+ if (bDisposed)
+ throw lang::DisposedException();
+
+ if (xData != rxSequence)
+ {
+ SetDataSequence( xData, rxSequence );
+ // inform listeners of changes
+ LaunchModifiedEvent( aModifyListeners, dynamic_cast< XModifyBroadcaster * >(this) );
+ }
+}
+
+uno::Reference< chart2::data::XDataSequence > SAL_CALL SwChartLabeledDataSequence::getLabel( )
+ throw (uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+ if (bDisposed)
+ throw lang::DisposedException();
+ return xLabels;
+}
+
+void SAL_CALL SwChartLabeledDataSequence::setLabel(
+ const uno::Reference< chart2::data::XDataSequence >& rxSequence )
+ throw (uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+ if (bDisposed)
+ throw lang::DisposedException();
+
+ if (xLabels != rxSequence)
+ {
+ SetDataSequence( xLabels, rxSequence );
+ // inform listeners of changes
+ LaunchModifiedEvent( aModifyListeners, dynamic_cast< XModifyBroadcaster * >(this) );
+ }
+}
+
+uno::Reference< util::XCloneable > SAL_CALL SwChartLabeledDataSequence::createClone( )
+ throw (uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+ if (bDisposed)
+ throw lang::DisposedException();
+
+ uno::Reference< util::XCloneable > xRes;
+
+ uno::Reference< util::XCloneable > xDataCloneable( xData, uno::UNO_QUERY );
+ uno::Reference< util::XCloneable > xLabelsCloneable( xLabels, uno::UNO_QUERY );
+ SwChartLabeledDataSequence *pRes = new SwChartLabeledDataSequence();
+ if (xDataCloneable.is())
+ {
+ uno::Reference< chart2::data::XDataSequence > xDataClone( xDataCloneable->createClone(), uno::UNO_QUERY );
+ pRes->setValues( xDataClone );
+ }
+
+ if (xLabelsCloneable.is())
+ {
+ uno::Reference< chart2::data::XDataSequence > xLabelsClone( xLabelsCloneable->createClone(), uno::UNO_QUERY );
+ pRes->setLabel( xLabelsClone );
+ }
+ xRes = pRes;
+ return xRes;
+}
+
+OUString SAL_CALL SwChartLabeledDataSequence::getImplementationName( )
+ throw (uno::RuntimeException)
+{
+ return C2U("SwChartLabeledDataSequence");
+}
+
+sal_Bool SAL_CALL SwChartLabeledDataSequence::supportsService(
+ const OUString& rServiceName )
+ throw (uno::RuntimeException)
+{
+ return rServiceName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( SN_LABELED_DATA_SEQUENCE ) );
+}
+
+uno::Sequence< OUString > SAL_CALL SwChartLabeledDataSequence::getSupportedServiceNames( )
+ throw (uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+ uno::Sequence< OUString > aRes(1);
+ aRes.getArray()[0] = C2U( SN_LABELED_DATA_SEQUENCE );
+ return aRes;
+}
+
+void SAL_CALL SwChartLabeledDataSequence::disposing(
+ const lang::EventObject& rSource )
+ throw (uno::RuntimeException)
+{
+ osl::MutexGuard aGuard( GetChartMutex() );
+ uno::Reference< uno::XInterface > xRef( rSource.Source );
+ if (xRef == xData)
+ xData.clear();
+ if (xRef == xLabels)
+ xLabels.clear();
+ if (!xData.is() && !xLabels.is())
+ dispose();
+}
+
+void SAL_CALL SwChartLabeledDataSequence::modified(
+ const lang::EventObject& rEvent )
+ throw (uno::RuntimeException)
+{
+ if (rEvent.Source == xData || rEvent.Source == xLabels)
+ {
+ LaunchModifiedEvent( aModifyListeners, dynamic_cast< XModifyBroadcaster * >(this) );
+ }
+}
+
+void SAL_CALL SwChartLabeledDataSequence::addModifyListener(
+ const uno::Reference< util::XModifyListener >& rxListener )
+ throw (uno::RuntimeException)
+{
+ osl::MutexGuard aGuard( GetChartMutex() );
+ if (!bDisposed && rxListener.is())
+ aModifyListeners.addInterface( rxListener );
+}
+
+void SAL_CALL SwChartLabeledDataSequence::removeModifyListener(
+ const uno::Reference< util::XModifyListener >& rxListener )
+ throw (uno::RuntimeException)
+{
+ osl::MutexGuard aGuard( GetChartMutex() );
+ if (!bDisposed && rxListener.is())
+ aModifyListeners.removeInterface( rxListener );
+}
+
+void SAL_CALL SwChartLabeledDataSequence::dispose( )
+ throw (uno::RuntimeException)
+{
+ sal_Bool bMustDispose( sal_False );
+ {
+ osl::MutexGuard aGuard( GetChartMutex() );
+ bMustDispose = !bDisposed;
+ if (!bDisposed)
+ bDisposed = sal_True;
+ }
+ if (bMustDispose)
+ {
+ bDisposed = sal_True;
+
+ // require listeners to release references to this object
+ lang::EventObject aEvtObj( dynamic_cast< chart2::data::XLabeledDataSequence * >(this) );
+ aModifyListeners.disposeAndClear( aEvtObj );
+ aEvtListeners.disposeAndClear( aEvtObj );
+ }
+}
+
+void SAL_CALL SwChartLabeledDataSequence::addEventListener(
+ const uno::Reference< lang::XEventListener >& rxListener )
+ throw (uno::RuntimeException)
+{
+ osl::MutexGuard aGuard( GetChartMutex() );
+ if (!bDisposed && rxListener.is())
+ aEvtListeners.addInterface( rxListener );
+}
+
+void SAL_CALL SwChartLabeledDataSequence::removeEventListener(
+ const uno::Reference< lang::XEventListener >& rxListener )
+ throw (uno::RuntimeException)
+{
+ osl::MutexGuard aGuard( GetChartMutex() );
+ if (!bDisposed && rxListener.is())
+ aEvtListeners.removeInterface( rxListener );
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/unocore/unocoll.cxx b/sw/source/core/unocore/unocoll.cxx
new file mode 100644
index 000000000000..e5db9e65f472
--- /dev/null
+++ b/sw/source/core/unocore/unocoll.cxx
@@ -0,0 +1,1996 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+#include <swtypes.hxx>
+#include <cmdid.h>
+#include <hintids.hxx>
+#include <svx/svxids.hrc>
+#include <doc.hxx>
+#include <docary.hxx>
+#include <fmtcol.hxx>
+#include <poolfmt.hxx>
+#include <unocoll.hxx>
+#include <unosett.hxx>
+#include <fmtanchr.hxx>
+#include <ndtxt.hxx>
+#include <section.hxx>
+#include <IMark.hxx>
+#include <ftnidx.hxx>
+#include <fmtftn.hxx>
+#include <txtftn.hxx>
+#include <fmtpdsc.hxx>
+#include <pagedesc.hxx>
+#include <osl/mutex.hxx>
+#include <com/sun/star/text/XTextTableCursor.hpp>
+#include <com/sun/star/text/XTextTablesSupplier.hpp>
+#include <com/sun/star/text/TableColumnSeparator.hpp>
+#include <com/sun/star/text/XTextTable.hpp>
+#include <svl/PasswordHelper.hxx>
+#include <svtools/unoimap.hxx>
+#include <svtools/unoevent.hxx>
+#include <unotbl.hxx>
+#include <unostyle.hxx>
+#include <unofield.hxx>
+#include <unoidx.hxx>
+#include <unoframe.hxx>
+#include <unofootnote.hxx>
+#include <vcl/svapp.hxx>
+#include <fmtcntnt.hxx>
+#include <authfld.hxx>
+#include <SwXTextDefaults.hxx>
+#include <unochart.hxx>
+#include <comphelper/makesequence.hxx>
+#include <comphelper/sequence.hxx>
+#include <list>
+#include <iterator>
+#include <unosection.hxx>
+#include <unoparagraph.hxx>
+#include <unobookmark.hxx>
+#include <unorefmark.hxx>
+#include <unometa.hxx>
+#include "docsh.hxx"
+#include <switerator.hxx>
+#include <com/sun/star/document/XCodeNameQuery.hpp>
+#include <com/sun/star/drawing/XDrawPageSupplier.hpp>
+#include <com/sun/star/form/XFormsSupplier.hpp>
+#include <com/sun/star/script/ModuleInfo.hpp>
+#include <com/sun/star/script/ModuleType.hpp>
+#include <com/sun/star/script/ScriptEventDescriptor.hpp>
+#include <com/sun/star/script/vba/XVBAModuleInfo.hpp>
+#include <vbahelper/vbaaccesshelper.hxx>
+#include <basic/basmgr.hxx>
+#include <comphelper/processfactory.hxx>
+
+using ::rtl::OUString;
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::document;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::text;
+using namespace ::com::sun::star::container;
+using namespace ::com::sun::star::lang;
+
+using rtl::OUString;
+
+class SwVbaCodeNameProvider : public ::cppu::WeakImplHelper1< document::XCodeNameQuery >
+{
+ SwDocShell* mpDocShell;
+ rtl::OUString msThisDocumentCodeName;
+public:
+ SwVbaCodeNameProvider( SwDocShell* pDocShell ) : mpDocShell( pDocShell ) {}
+ // XCodeNameQuery
+ rtl::OUString SAL_CALL getCodeNameForObject( const uno::Reference< uno::XInterface >& xIf ) throw( uno::RuntimeException )
+ {
+ // Initialise the code name
+ if ( msThisDocumentCodeName.getLength() == 0 )
+ {
+ try
+ {
+ uno::Reference< beans::XPropertySet > xProps( mpDocShell->GetModel(), uno::UNO_QUERY_THROW );
+ uno::Reference< container::XNameAccess > xLibContainer( xProps->getPropertyValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("BasicLibraries") ) ), uno::UNO_QUERY_THROW );
+ rtl::OUString sProjectName( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("Standard") ) );
+ if ( mpDocShell->GetBasicManager()->GetName().Len() )
+ sProjectName = mpDocShell->GetBasicManager()->GetName();
+
+ uno::Reference< container::XNameAccess > xLib( xLibContainer->getByName( sProjectName ), uno::UNO_QUERY_THROW );
+ uno::Sequence< rtl::OUString > sModuleNames = xLib->getElementNames();
+ uno::Reference< script::vba::XVBAModuleInfo > xVBAModuleInfo( xLib, uno::UNO_QUERY );
+
+ for ( sal_Int32 i=0; i < sModuleNames.getLength(); ++i )
+ {
+ script::ModuleInfo mInfo;
+
+ if ( xVBAModuleInfo->hasModuleInfo( sModuleNames[ i ] ) && xVBAModuleInfo->getModuleInfo( sModuleNames[ i ] ).ModuleType == script::ModuleType::DOCUMENT )
+ {
+ msThisDocumentCodeName = sModuleNames[ i ];
+ break;
+ }
+ }
+ }
+ catch( uno::Exception& )
+ {
+ }
+ }
+ rtl::OUString sCodeName;
+ if ( mpDocShell )
+ {
+ OSL_TRACE( "*** In ScVbaCodeNameProvider::getCodeNameForObject");
+ // need to find the page ( and index ) for this control
+ uno::Reference< drawing::XDrawPageSupplier > xSupplier( mpDocShell->GetModel(), uno::UNO_QUERY_THROW );
+ uno::Reference< container::XIndexAccess > xIndex( xSupplier->getDrawPage(), uno::UNO_QUERY_THROW );
+
+ bool bMatched = false;
+ uno::Sequence< script::ScriptEventDescriptor > aFakeEvents;
+ try
+ {
+ uno::Reference< form::XFormsSupplier > xFormSupplier( xIndex, uno::UNO_QUERY_THROW );
+ uno::Reference< container::XIndexAccess > xFormIndex( xFormSupplier->getForms(), uno::UNO_QUERY_THROW );
+ // get the www-standard container
+ uno::Reference< container::XIndexAccess > xFormControls( xFormIndex->getByIndex(0), uno::UNO_QUERY_THROW );
+ sal_Int32 nCntrls = xFormControls->getCount();
+ for( sal_Int32 cIndex = 0; cIndex < nCntrls; ++cIndex )
+ {
+ uno::Reference< uno::XInterface > xControl( xFormControls->getByIndex( cIndex ), uno::UNO_QUERY_THROW );
+ bMatched = ( xControl == xIf );
+ if ( bMatched )
+ {
+ sCodeName = msThisDocumentCodeName;
+ break;
+ }
+ }
+ }
+ catch( uno::Exception& ) {}
+ }
+ // Probably should throw here ( if !bMatched )
+ return sCodeName;
+ }
+};
+
+typedef boost::unordered_map< rtl::OUString, rtl::OUString, rtl::OUStringHash > StringHashMap;
+class SwVbaProjectNameProvider : public ::cppu::WeakImplHelper1< container::XNameContainer >
+{
+ SwDocShell* mpDocShell;
+ StringHashMap mTemplateToProject;
+public:
+ SwVbaProjectNameProvider( SwDocShell* pDocShell ) : mpDocShell( pDocShell )
+ {
+ }
+ virtual ::sal_Bool SAL_CALL hasByName( const ::rtl::OUString& aName ) throw (::com::sun::star::uno::RuntimeException )
+ {
+ return ( mTemplateToProject.find( aName ) != mTemplateToProject.end() );
+ }
+ virtual ::com::sun::star::uno::Any SAL_CALL getByName( const ::rtl::OUString& aName ) throw (::com::sun::star::container::NoSuchElementException, ::com::sun::star::lang::WrappedTargetException, ::com::sun::star::uno::RuntimeException)
+ {
+ if ( !hasByName( aName ) )
+ throw container::NoSuchElementException();
+ return uno::makeAny( mTemplateToProject.find( aName )->second );
+ }
+ virtual ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL getElementNames( ) throw (::com::sun::star::uno::RuntimeException)
+ {
+ uno::Sequence< rtl::OUString > aElements( mTemplateToProject.size() );
+ StringHashMap::iterator it_end = mTemplateToProject.end();
+ sal_Int32 index = 0;
+ for ( StringHashMap::iterator it = mTemplateToProject.begin(); it != it_end; ++it, ++index )
+ aElements[ index ] = it->first;
+ return aElements;
+ }
+
+ virtual void SAL_CALL insertByName( const rtl::OUString& aName, const uno::Any& aElement ) throw ( com::sun::star::lang::IllegalArgumentException, com::sun::star::container::ElementExistException, com::sun::star::lang::WrappedTargetException )
+ {
+
+ rtl::OUString sProjectName;
+ aElement >>= sProjectName;
+ OSL_TRACE("** Template cache inserting template name %s with project %s"
+ , rtl::OUStringToOString( aName, RTL_TEXTENCODING_UTF8 ).getStr()
+ , rtl::OUStringToOString( sProjectName, RTL_TEXTENCODING_UTF8 ).getStr() );
+ mTemplateToProject[ aName ] = sProjectName;
+ }
+
+ virtual void SAL_CALL removeByName( const rtl::OUString& Name ) throw ( com::sun::star::container::NoSuchElementException, com::sun::star::lang::WrappedTargetException )
+ {
+ if ( !hasByName( Name ) )
+ throw container::NoSuchElementException();
+ mTemplateToProject.erase( Name );
+ }
+ virtual void SAL_CALL replaceByName( const rtl::OUString& aName, const uno::Any& aElement ) throw ( com::sun::star::lang::IllegalArgumentException, com::sun::star::container::NoSuchElementException, com::sun::star::lang::WrappedTargetException )
+ {
+ if ( !hasByName( aName ) )
+ throw container::NoSuchElementException();
+ insertByName( aName, aElement ); // insert will overwrite
+ }
+ // XElemenAccess
+ virtual ::com::sun::star::uno::Type SAL_CALL getElementType( ) throw (::com::sun::star::uno::RuntimeException)
+ {
+ return ::getCppuType((const rtl::OUString*)0);
+ }
+ virtual ::sal_Bool SAL_CALL hasElements( ) throw (::com::sun::star::uno::RuntimeException )
+ {
+
+ return ( mTemplateToProject.size() > 0 );
+ }
+
+};
+
+class SwVbaObjectForCodeNameProvider : public ::cppu::WeakImplHelper1< container::XNameAccess >
+{
+ SwDocShell* mpDocShell;
+public:
+ SwVbaObjectForCodeNameProvider( SwDocShell* pDocShell ) : mpDocShell( pDocShell )
+ {
+ // #FIXME #TODO is the code name for ThisDocument read anywhere?
+ }
+
+ virtual ::sal_Bool SAL_CALL hasByName( const ::rtl::OUString& aName ) throw (::com::sun::star::uno::RuntimeException )
+ {
+ // #FIXME #TODO we really need to be checking against the codename for
+ // ThisDocument
+ if ( aName.equals( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("ThisDocument" ) ) ) )
+ return sal_True;
+ return sal_False;
+ }
+ ::com::sun::star::uno::Any SAL_CALL getByName( const ::rtl::OUString& aName ) throw (::com::sun::star::container::NoSuchElementException, ::com::sun::star::lang::WrappedTargetException, ::com::sun::star::uno::RuntimeException)
+ {
+ if ( !hasByName( aName ) )
+ throw container::NoSuchElementException();
+ uno::Sequence< uno::Any > aArgs( 2 );
+ aArgs[0] = uno::Any( uno::Reference< uno::XInterface >() );
+ aArgs[1] = uno::Any( mpDocShell->GetModel() );
+ uno::Reference< uno::XInterface > xDocObj = ooo::vba::createVBAUnoAPIServiceWithArgs( mpDocShell, "ooo.vba.word.Document" , aArgs );
+ OSL_TRACE("Creating Object ( ooo.vba.word.Document ) 0x%x", xDocObj.get() );
+ return uno::makeAny( xDocObj );
+ }
+ virtual ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL getElementNames( ) throw (::com::sun::star::uno::RuntimeException)
+ {
+ uno::Sequence< rtl::OUString > aNames;
+ return aNames;
+ }
+ // XElemenAccess
+ virtual ::com::sun::star::uno::Type SAL_CALL getElementType( ) throw (::com::sun::star::uno::RuntimeException){ return uno::Type(); }
+ virtual ::sal_Bool SAL_CALL hasElements( ) throw (::com::sun::star::uno::RuntimeException ) { return sal_True; }
+
+};
+
+struct ProvNamesId_Type
+{
+ const char * pName;
+ sal_uInt16 nType;
+};
+
+// note: this thing is indexed as an array, so do not insert/remove entries!
+const ProvNamesId_Type aProvNamesId[] =
+{
+ { "com.sun.star.text.TextTable", SW_SERVICE_TYPE_TEXTTABLE },
+ { "com.sun.star.text.TextFrame", SW_SERVICE_TYPE_TEXTFRAME },
+ { "com.sun.star.text.GraphicObject", SW_SERVICE_TYPE_GRAPHIC },
+ { "com.sun.star.text.TextEmbeddedObject", SW_SERVICE_TYPE_OLE },
+ { "com.sun.star.text.Bookmark", SW_SERVICE_TYPE_BOOKMARK },
+ { "com.sun.star.text.Footnote", SW_SERVICE_TYPE_FOOTNOTE },
+ { "com.sun.star.text.Endnote", SW_SERVICE_TYPE_ENDNOTE },
+ { "com.sun.star.text.DocumentIndexMark", SW_SERVICE_TYPE_INDEXMARK },
+ { "com.sun.star.text.DocumentIndex", SW_SERVICE_TYPE_INDEX },
+ { "com.sun.star.text.ReferenceMark", SW_SERVICE_REFERENCE_MARK },
+ { "com.sun.star.style.CharacterStyle", SW_SERVICE_STYLE_CHARACTER_STYLE },
+ { "com.sun.star.style.ParagraphStyle", SW_SERVICE_STYLE_PARAGRAPH_STYLE },
+ { "com.sun.star.style.FrameStyle", SW_SERVICE_STYLE_FRAME_STYLE },
+ { "com.sun.star.style.PageStyle", SW_SERVICE_STYLE_PAGE_STYLE },
+ { "com.sun.star.style.NumberingStyle", SW_SERVICE_STYLE_NUMBERING_STYLE },
+ { "com.sun.star.text.ContentIndexMark", SW_SERVICE_CONTENT_INDEX_MARK },
+ { "com.sun.star.text.ContentIndex", SW_SERVICE_CONTENT_INDEX },
+ { "com.sun.star.text.UserIndexMark", SW_SERVICE_USER_INDEX_MARK },
+ { "com.sun.star.text.UserIndex", SW_SERVICE_USER_INDEX },
+ { "com.sun.star.text.TextSection", SW_SERVICE_TEXT_SECTION },
+ { "com.sun.star.text.TextField.DateTime", SW_SERVICE_FIELDTYPE_DATETIME },
+ { "com.sun.star.text.TextField.User", SW_SERVICE_FIELDTYPE_USER },
+ { "com.sun.star.text.TextField.SetExpression", SW_SERVICE_FIELDTYPE_SET_EXP },
+ { "com.sun.star.text.TextField.GetExpression", SW_SERVICE_FIELDTYPE_GET_EXP },
+ { "com.sun.star.text.TextField.FileName", SW_SERVICE_FIELDTYPE_FILE_NAME },
+ { "com.sun.star.text.TextField.PageNumber", SW_SERVICE_FIELDTYPE_PAGE_NUM },
+ { "com.sun.star.text.TextField.Author", SW_SERVICE_FIELDTYPE_AUTHOR },
+ { "com.sun.star.text.TextField.Chapter", SW_SERVICE_FIELDTYPE_CHAPTER },
+ { "", SW_SERVICE_FIELDTYPE_DUMMY_0 },
+ { "com.sun.star.text.TextField.GetReference", SW_SERVICE_FIELDTYPE_GET_REFERENCE },
+ { "com.sun.star.text.TextField.ConditionalText", SW_SERVICE_FIELDTYPE_CONDITIONED_TEXT },
+ { "com.sun.star.text.TextField.Annotation", SW_SERVICE_FIELDTYPE_ANNOTATION },
+ { "com.sun.star.text.TextField.Input", SW_SERVICE_FIELDTYPE_INPUT },
+ { "com.sun.star.text.TextField.Macro", SW_SERVICE_FIELDTYPE_MACRO },
+ { "com.sun.star.text.TextField.DDE", SW_SERVICE_FIELDTYPE_DDE },
+ { "com.sun.star.text.TextField.HiddenParagraph", SW_SERVICE_FIELDTYPE_HIDDEN_PARA },
+ { "" /*com.sun.star.text.TextField.DocumentInfo"*/, SW_SERVICE_FIELDTYPE_DOC_INFO },
+ { "com.sun.star.text.TextField.TemplateName", SW_SERVICE_FIELDTYPE_TEMPLATE_NAME },
+ { "com.sun.star.text.TextField.ExtendedUser", SW_SERVICE_FIELDTYPE_USER_EXT },
+ { "com.sun.star.text.TextField.ReferencePageSet", SW_SERVICE_FIELDTYPE_REF_PAGE_SET },
+ { "com.sun.star.text.TextField.ReferencePageGet", SW_SERVICE_FIELDTYPE_REF_PAGE_GET },
+ { "com.sun.star.text.TextField.JumpEdit", SW_SERVICE_FIELDTYPE_JUMP_EDIT },
+ { "com.sun.star.text.TextField.Script", SW_SERVICE_FIELDTYPE_SCRIPT },
+ { "com.sun.star.text.TextField.DatabaseNextSet", SW_SERVICE_FIELDTYPE_DATABASE_NEXT_SET },
+ { "com.sun.star.text.TextField.DatabaseNumberOfSet", SW_SERVICE_FIELDTYPE_DATABASE_NUM_SET },
+ { "com.sun.star.text.TextField.DatabaseSetNumber", SW_SERVICE_FIELDTYPE_DATABASE_SET_NUM },
+ { "com.sun.star.text.TextField.Database", SW_SERVICE_FIELDTYPE_DATABASE },
+ { "com.sun.star.text.TextField.DatabaseName", SW_SERVICE_FIELDTYPE_DATABASE_NAME },
+ { "com.sun.star.text.TextField.TableFormula", SW_SERVICE_FIELDTYPE_TABLE_FORMULA },
+ { "com.sun.star.text.TextField.PageCount", SW_SERVICE_FIELDTYPE_PAGE_COUNT },
+ { "com.sun.star.text.TextField.ParagraphCount", SW_SERVICE_FIELDTYPE_PARAGRAPH_COUNT },
+ { "com.sun.star.text.TextField.WordCount", SW_SERVICE_FIELDTYPE_WORD_COUNT },
+ { "com.sun.star.text.TextField.CharacterCount", SW_SERVICE_FIELDTYPE_CHARACTER_COUNT },
+ { "com.sun.star.text.TextField.TableCount", SW_SERVICE_FIELDTYPE_TABLE_COUNT },
+ { "com.sun.star.text.TextField.GraphicObjectCount", SW_SERVICE_FIELDTYPE_GRAPHIC_OBJECT_COUNT },
+ { "com.sun.star.text.TextField.EmbeddedObjectCount", SW_SERVICE_FIELDTYPE_EMBEDDED_OBJECT_COUNT },
+ { "com.sun.star.text.TextField.DocInfo.ChangeAuthor", SW_SERVICE_FIELDTYPE_DOCINFO_CHANGE_AUTHOR },
+ { "com.sun.star.text.TextField.DocInfo.ChangeDateTime", SW_SERVICE_FIELDTYPE_DOCINFO_CHANGE_DATE_TIME },
+ { "com.sun.star.text.TextField.DocInfo.EditTime", SW_SERVICE_FIELDTYPE_DOCINFO_EDIT_TIME },
+ { "com.sun.star.text.TextField.DocInfo.Description", SW_SERVICE_FIELDTYPE_DOCINFO_DESCRIPTION },
+ { "com.sun.star.text.TextField.DocInfo.CreateAuthor", SW_SERVICE_FIELDTYPE_DOCINFO_CREATE_AUTHOR },
+ { "com.sun.star.text.TextField.DocInfo.CreateDateTime", SW_SERVICE_FIELDTYPE_DOCINFO_CREATE_DATE_TIME },
+ { "", SW_SERVICE_FIELDTYPE_DUMMY_0 },
+ { "", SW_SERVICE_FIELDTYPE_DUMMY_1 },
+ { "", SW_SERVICE_FIELDTYPE_DUMMY_2 },
+ { "", SW_SERVICE_FIELDTYPE_DUMMY_3 },
+ { "com.sun.star.text.TextField.DocInfo.Custom", SW_SERVICE_FIELDTYPE_DOCINFO_CUSTOM },
+ { "com.sun.star.text.TextField.DocInfo.PrintAuthor", SW_SERVICE_FIELDTYPE_DOCINFO_PRINT_AUTHOR },
+ { "com.sun.star.text.TextField.DocInfo.PrintDateTime", SW_SERVICE_FIELDTYPE_DOCINFO_PRINT_DATE_TIME },
+ { "com.sun.star.text.TextField.DocInfo.KeyWords", SW_SERVICE_FIELDTYPE_DOCINFO_KEY_WORDS },
+ { "com.sun.star.text.TextField.DocInfo.Subject", SW_SERVICE_FIELDTYPE_DOCINFO_SUBJECT },
+ { "com.sun.star.text.TextField.DocInfo.Title", SW_SERVICE_FIELDTYPE_DOCINFO_TITLE },
+ { "com.sun.star.text.TextField.DocInfo.Revision", SW_SERVICE_FIELDTYPE_DOCINFO_REVISION },
+ { "com.sun.star.text.TextField.Bibliography", SW_SERVICE_FIELDTYPE_BIBLIOGRAPHY },
+ { "com.sun.star.text.TextField.CombinedCharacters", SW_SERVICE_FIELDTYPE_COMBINED_CHARACTERS },
+ { "com.sun.star.text.TextField.DropDown", SW_SERVICE_FIELDTYPE_DROPDOWN },
+ { "com.sun.star.text.textfield.MetadataField", SW_SERVICE_FIELDTYPE_METAFIELD },
+ { "", SW_SERVICE_FIELDTYPE_DUMMY_4 },
+ { "", SW_SERVICE_FIELDTYPE_DUMMY_5 },
+ { "", SW_SERVICE_FIELDTYPE_DUMMY_6 },
+ { "", SW_SERVICE_FIELDTYPE_DUMMY_7 },
+ { "com.sun.star.text.FieldMaster.User", SW_SERVICE_FIELDMASTER_USER },
+ { "com.sun.star.text.FieldMaster.DDE", SW_SERVICE_FIELDMASTER_DDE },
+ { "com.sun.star.text.FieldMaster.SetExpression", SW_SERVICE_FIELDMASTER_SET_EXP },
+ { "com.sun.star.text.FieldMaster.Database", SW_SERVICE_FIELDMASTER_DATABASE },
+ { "com.sun.star.text.FieldMaster.Bibliography", SW_SERVICE_FIELDMASTER_BIBLIOGRAPHY },
+ { "", SW_SERVICE_FIELDMASTER_DUMMY2 },
+ { "", SW_SERVICE_FIELDMASTER_DUMMY3 },
+ { "", SW_SERVICE_FIELDMASTER_DUMMY4 },
+ { "", SW_SERVICE_FIELDMASTER_DUMMY5 },
+ { "com.sun.star.text.IllustrationsIndex", SW_SERVICE_INDEX_ILLUSTRATIONS },
+ { "com.sun.star.text.ObjectIndex", SW_SERVICE_INDEX_OBJECTS },
+ { "com.sun.star.text.TableIndex", SW_SERVICE_INDEX_TABLES },
+ { "com.sun.star.text.Bibliography", SW_SERVICE_INDEX_BIBLIOGRAPHY },
+ { "com.sun.star.text.Paragraph", SW_SERVICE_PARAGRAPH },
+ { "com.sun.star.text.TextField.InputUser", SW_SERVICE_FIELDTYPE_INPUT_USER },
+ { "com.sun.star.text.TextField.HiddenText", SW_SERVICE_FIELDTYPE_HIDDEN_TEXT },
+ { "com.sun.star.style.ConditionalParagraphStyle", SW_SERVICE_STYLE_CONDITIONAL_PARAGRAPH_STYLE },
+ { "com.sun.star.text.NumberingRules", SW_SERVICE_NUMBERING_RULES },
+ { "com.sun.star.text.TextColumns", SW_SERVICE_TEXT_COLUMNS },
+ { "com.sun.star.text.IndexHeaderSection", SW_SERVICE_INDEX_HEADER_SECTION },
+ { "com.sun.star.text.Defaults", SW_SERVICE_DEFAULTS },
+ { "com.sun.star.image.ImageMapRectangleObject", SW_SERVICE_IMAP_RECTANGLE },
+ { "com.sun.star.image.ImageMapCircleObject", SW_SERVICE_IMAP_CIRCLE },
+ { "com.sun.star.image.ImageMapPolygonObject", SW_SERVICE_IMAP_POLYGON },
+ { "com.sun.star.text.TextGraphicObject", SW_SERVICE_TYPE_TEXT_GRAPHIC },
+ { "com.sun.star.chart2.data.DataProvider", SW_SERVICE_CHART2_DATA_PROVIDER },
+ { "com.sun.star.text.Fieldmark", SW_SERVICE_TYPE_FIELDMARK },
+ { "com.sun.star.text.FormFieldmark", SW_SERVICE_TYPE_FORMFIELDMARK },
+ { "com.sun.star.text.InContentMetadata", SW_SERVICE_TYPE_META },
+ { "ooo.vba.VBAObjectModuleObjectProvider", SW_SERVICE_VBAOBJECTPROVIDER },
+ { "ooo.vba.VBACodeNameProvider", SW_SERVICE_VBACODENAMEPROVIDER },
+ { "ooo.vba.VBAProjectNameProvider", SW_SERVICE_VBAPROJECTNAMEPROVIDER },
+ { "ooo.vba.VBAGlobals", SW_SERVICE_VBAGLOBALS },
+
+ // case-correct versions of the service names (see #i67811)
+ { CSS_TEXT_TEXTFIELD_DATE_TIME, SW_SERVICE_FIELDTYPE_DATETIME },
+ { CSS_TEXT_TEXTFIELD_USER, SW_SERVICE_FIELDTYPE_USER },
+ { CSS_TEXT_TEXTFIELD_SET_EXPRESSION, SW_SERVICE_FIELDTYPE_SET_EXP },
+ { CSS_TEXT_TEXTFIELD_GET_EXPRESSION, SW_SERVICE_FIELDTYPE_GET_EXP },
+ { CSS_TEXT_TEXTFIELD_FILE_NAME, SW_SERVICE_FIELDTYPE_FILE_NAME },
+ { CSS_TEXT_TEXTFIELD_PAGE_NUMBER, SW_SERVICE_FIELDTYPE_PAGE_NUM },
+ { CSS_TEXT_TEXTFIELD_AUTHOR, SW_SERVICE_FIELDTYPE_AUTHOR },
+ { CSS_TEXT_TEXTFIELD_CHAPTER, SW_SERVICE_FIELDTYPE_CHAPTER },
+ { CSS_TEXT_TEXTFIELD_GET_REFERENCE, SW_SERVICE_FIELDTYPE_GET_REFERENCE },
+ { CSS_TEXT_TEXTFIELD_CONDITIONAL_TEXT, SW_SERVICE_FIELDTYPE_CONDITIONED_TEXT },
+ { CSS_TEXT_TEXTFIELD_ANNOTATION, SW_SERVICE_FIELDTYPE_ANNOTATION },
+ { CSS_TEXT_TEXTFIELD_INPUT, SW_SERVICE_FIELDTYPE_INPUT },
+ { CSS_TEXT_TEXTFIELD_MACRO, SW_SERVICE_FIELDTYPE_MACRO },
+ { CSS_TEXT_TEXTFIELD_DDE, SW_SERVICE_FIELDTYPE_DDE },
+ { CSS_TEXT_TEXTFIELD_HIDDEN_PARAGRAPH, SW_SERVICE_FIELDTYPE_HIDDEN_PARA },
+ { CSS_TEXT_TEXTFIELD_TEMPLATE_NAME, SW_SERVICE_FIELDTYPE_TEMPLATE_NAME },
+ { CSS_TEXT_TEXTFIELD_EXTENDED_USER, SW_SERVICE_FIELDTYPE_USER_EXT },
+ { CSS_TEXT_TEXTFIELD_REFERENCE_PAGE_SET, SW_SERVICE_FIELDTYPE_REF_PAGE_SET },
+ { CSS_TEXT_TEXTFIELD_REFERENCE_PAGE_GET, SW_SERVICE_FIELDTYPE_REF_PAGE_GET },
+ { CSS_TEXT_TEXTFIELD_JUMP_EDIT, SW_SERVICE_FIELDTYPE_JUMP_EDIT },
+ { CSS_TEXT_TEXTFIELD_SCRIPT, SW_SERVICE_FIELDTYPE_SCRIPT },
+ { CSS_TEXT_TEXTFIELD_DATABASE_NEXT_SET, SW_SERVICE_FIELDTYPE_DATABASE_NEXT_SET },
+ { CSS_TEXT_TEXTFIELD_DATABASE_NUMBER_OF_SET, SW_SERVICE_FIELDTYPE_DATABASE_NUM_SET },
+ { CSS_TEXT_TEXTFIELD_DATABASE_SET_NUMBER, SW_SERVICE_FIELDTYPE_DATABASE_SET_NUM },
+ { CSS_TEXT_TEXTFIELD_DATABASE, SW_SERVICE_FIELDTYPE_DATABASE },
+ { CSS_TEXT_TEXTFIELD_DATABASE_NAME, SW_SERVICE_FIELDTYPE_DATABASE_NAME },
+ { CSS_TEXT_TEXTFIELD_TABLE_FORMULA, SW_SERVICE_FIELDTYPE_TABLE_FORMULA },
+ { CSS_TEXT_TEXTFIELD_PAGE_COUNT, SW_SERVICE_FIELDTYPE_PAGE_COUNT },
+ { CSS_TEXT_TEXTFIELD_PARAGRAPH_COUNT, SW_SERVICE_FIELDTYPE_PARAGRAPH_COUNT },
+ { CSS_TEXT_TEXTFIELD_WORD_COUNT, SW_SERVICE_FIELDTYPE_WORD_COUNT },
+ { CSS_TEXT_TEXTFIELD_CHARACTER_COUNT, SW_SERVICE_FIELDTYPE_CHARACTER_COUNT },
+ { CSS_TEXT_TEXTFIELD_TABLE_COUNT, SW_SERVICE_FIELDTYPE_TABLE_COUNT },
+ { CSS_TEXT_TEXTFIELD_GRAPHIC_OBJECT_COUNT, SW_SERVICE_FIELDTYPE_GRAPHIC_OBJECT_COUNT },
+ { CSS_TEXT_TEXTFIELD_EMBEDDED_OBJECT_COUNT, SW_SERVICE_FIELDTYPE_EMBEDDED_OBJECT_COUNT },
+ { CSS_TEXT_TEXTFIELD_DOCINFO_CHANGE_AUTHOR, SW_SERVICE_FIELDTYPE_DOCINFO_CHANGE_AUTHOR },
+ { CSS_TEXT_TEXTFIELD_DOCINFO_CHANGE_DATE_TIME, SW_SERVICE_FIELDTYPE_DOCINFO_CHANGE_DATE_TIME },
+ { CSS_TEXT_TEXTFIELD_DOCINFO_EDIT_TIME, SW_SERVICE_FIELDTYPE_DOCINFO_EDIT_TIME },
+ { CSS_TEXT_TEXTFIELD_DOCINFO_DESCRIPTION, SW_SERVICE_FIELDTYPE_DOCINFO_DESCRIPTION },
+ { CSS_TEXT_TEXTFIELD_DOCINFO_CREATE_AUTHOR, SW_SERVICE_FIELDTYPE_DOCINFO_CREATE_AUTHOR },
+ { CSS_TEXT_TEXTFIELD_DOCINFO_CREATE_DATE_TIME, SW_SERVICE_FIELDTYPE_DOCINFO_CREATE_DATE_TIME },
+ { CSS_TEXT_TEXTFIELD_DOCINFO_PRINT_AUTHOR, SW_SERVICE_FIELDTYPE_DOCINFO_PRINT_AUTHOR },
+ { CSS_TEXT_TEXTFIELD_DOCINFO_PRINT_DATE_TIME, SW_SERVICE_FIELDTYPE_DOCINFO_PRINT_DATE_TIME },
+ { CSS_TEXT_TEXTFIELD_DOCINFO_KEY_WORDS, SW_SERVICE_FIELDTYPE_DOCINFO_KEY_WORDS },
+ { CSS_TEXT_TEXTFIELD_DOCINFO_SUBJECT, SW_SERVICE_FIELDTYPE_DOCINFO_SUBJECT },
+ { CSS_TEXT_TEXTFIELD_DOCINFO_TITLE, SW_SERVICE_FIELDTYPE_DOCINFO_TITLE },
+ { CSS_TEXT_TEXTFIELD_DOCINFO_REVISION, SW_SERVICE_FIELDTYPE_DOCINFO_REVISION },
+ { CSS_TEXT_TEXTFIELD_DOCINFO_CUSTOM, SW_SERVICE_FIELDTYPE_DOCINFO_CUSTOM },
+ { CSS_TEXT_TEXTFIELD_BIBLIOGRAPHY, SW_SERVICE_FIELDTYPE_BIBLIOGRAPHY },
+ { CSS_TEXT_TEXTFIELD_COMBINED_CHARACTERS, SW_SERVICE_FIELDTYPE_COMBINED_CHARACTERS },
+ { CSS_TEXT_TEXTFIELD_DROP_DOWN, SW_SERVICE_FIELDTYPE_DROPDOWN },
+ { CSS_TEXT_TEXTFIELD_INPUT_USER, SW_SERVICE_FIELDTYPE_INPUT_USER },
+ { CSS_TEXT_TEXTFIELD_HIDDEN_TEXT, SW_SERVICE_FIELDTYPE_HIDDEN_TEXT },
+ { CSS_TEXT_FIELDMASTER_USER, SW_SERVICE_FIELDMASTER_USER },
+ { CSS_TEXT_FIELDMASTER_DDE, SW_SERVICE_FIELDMASTER_DDE },
+ { CSS_TEXT_FIELDMASTER_SET_EXPRESSION, SW_SERVICE_FIELDMASTER_SET_EXP },
+ { CSS_TEXT_FIELDMASTER_DATABASE, SW_SERVICE_FIELDMASTER_DATABASE },
+ { CSS_TEXT_FIELDMASTER_BIBLIOGRAPHY, SW_SERVICE_FIELDMASTER_BIBLIOGRAPHY }
+};
+
+const SvEventDescription* lcl_GetSupportedMacroItems()
+{
+ static const SvEventDescription aMacroDescriptionsImpl[] =
+ {
+ { SFX_EVENT_MOUSEOVER_OBJECT, "OnMouseOver" },
+ { SFX_EVENT_MOUSEOUT_OBJECT, "OnMouseOut" },
+ { 0, NULL }
+ };
+
+ return aMacroDescriptionsImpl;
+}
+
+/******************************************************************
+ * SwXServiceProvider
+ ******************************************************************/
+OUString SwXServiceProvider::GetProviderName(sal_uInt16 nObjectType)
+{
+ SolarMutexGuard aGuard;
+ OUString sRet;
+ sal_uInt16 nEntries = SAL_N_ELEMENTS(aProvNamesId);
+ if(nObjectType < nEntries)
+ sRet = rtl::OUString::createFromAscii(aProvNamesId[nObjectType].pName);
+ return sRet;
+}
+
+uno::Sequence<OUString> SwXServiceProvider::GetAllServiceNames()
+{
+ sal_uInt16 nEntries = SAL_N_ELEMENTS(aProvNamesId);
+ uno::Sequence<OUString> aRet(nEntries);
+ OUString* pArray = aRet.getArray();
+ sal_uInt16 n = 0;
+ for(sal_uInt16 i = 0; i < nEntries; i++)
+ {
+ String sProv(rtl::OUString::createFromAscii(aProvNamesId[i].pName));
+ if(sProv.Len())
+ {
+ pArray[n] = sProv;
+ n++;
+ }
+ }
+ aRet.realloc(n);
+ return aRet;
+
+}
+
+sal_uInt16 SwXServiceProvider::GetProviderType(const OUString& rServiceName)
+{
+ sal_uInt16 nEntries = SAL_N_ELEMENTS(aProvNamesId);
+ for(sal_uInt16 i = 0; i < nEntries; i++ )
+ {
+ if( COMPARE_EQUAL == rServiceName.compareToAscii(aProvNamesId[i].pName))
+ return aProvNamesId[i].nType;
+ }
+ return SW_SERVICE_INVALID;
+}
+
+uno::Reference< uno::XInterface > SwXServiceProvider::MakeInstance(sal_uInt16 nObjectType, SwDoc* pDoc)
+{
+ SolarMutexGuard aGuard;
+ uno::Reference< uno::XInterface > xRet;
+ switch(nObjectType)
+ {
+ case SW_SERVICE_TYPE_TEXTTABLE:
+ {
+ SwXTextTable* pTextTable = new SwXTextTable();
+ xRet = (cppu::OWeakObject*)pTextTable;
+ }
+ break;
+ case SW_SERVICE_TYPE_TEXTFRAME:
+ {
+ SwXTextFrame* pTextFrame = new SwXTextFrame( pDoc );
+ xRet = (cppu::OWeakObject*)(SwXFrame*)pTextFrame;
+ }
+ break;
+ case SW_SERVICE_TYPE_GRAPHIC :
+ case SW_SERVICE_TYPE_TEXT_GRAPHIC /* #i47503# */ :
+ {
+ SwXTextGraphicObject* pGraphic = new SwXTextGraphicObject( pDoc );
+ xRet = (cppu::OWeakObject*)(SwXFrame*)pGraphic;
+
+ }
+ break;
+ case SW_SERVICE_TYPE_OLE :
+ {
+ SwXTextEmbeddedObject* pOle = new SwXTextEmbeddedObject( pDoc );
+ xRet = (cppu::OWeakObject*)(SwXFrame*)pOle;
+ }
+ break;
+ case SW_SERVICE_TYPE_BOOKMARK :
+ {
+ SwXBookmark* pBookmark = new SwXBookmark;
+ xRet = (cppu::OWeakObject*)pBookmark;
+ }
+ break;
+ case SW_SERVICE_TYPE_FIELDMARK :
+ {
+ SwXFieldmark* pFieldmark = new SwXFieldmark(false);
+ xRet = (cppu::OWeakObject*)pFieldmark;
+ }
+ break;
+ case SW_SERVICE_TYPE_FORMFIELDMARK :
+ {
+ SwXFieldmark* pFieldmark = new SwXFieldmark(true);
+ xRet = (cppu::OWeakObject*)pFieldmark;
+ }
+ break;
+ case SW_SERVICE_VBAOBJECTPROVIDER :
+ {
+ SwVbaObjectForCodeNameProvider* pObjProv = new SwVbaObjectForCodeNameProvider( pDoc->GetDocShell() );
+ xRet = (cppu::OWeakObject*)pObjProv;
+ }
+ break;
+ case SW_SERVICE_VBACODENAMEPROVIDER :
+ {
+ if ( pDoc->GetDocShell() && ooo::vba::isAlienWordDoc( *pDoc->GetDocShell() ) )
+ {
+ SwVbaCodeNameProvider* pObjProv = new SwVbaCodeNameProvider( pDoc->GetDocShell() );
+ xRet = (cppu::OWeakObject*)pObjProv;
+ }
+ }
+ break;
+ case SW_SERVICE_VBAPROJECTNAMEPROVIDER :
+ {
+ uno::Reference< container::XNameContainer > xProjProv = pDoc->GetVBATemplateToProjectCache();
+ if ( !xProjProv.is() && pDoc->GetDocShell() && ooo::vba::isAlienWordDoc( *pDoc->GetDocShell() ) )
+ {
+ xProjProv = new SwVbaProjectNameProvider( pDoc->GetDocShell() );
+ pDoc->SetVBATemplateToProjectCache( xProjProv );
+ }
+ //xRet = (cppu::OWeakObject*)xProjProv;
+ xRet = xProjProv;
+ }
+ break;
+ case SW_SERVICE_VBAGLOBALS :
+ {
+ if ( pDoc )
+ {
+ uno::Any aGlobs;
+ if ( !pDoc->GetDocShell()->GetBasicManager()->GetGlobalUNOConstant( "VBAGlobals", aGlobs ) )
+ {
+ uno::Sequence< uno::Any > aArgs(1);
+ aArgs[ 0 ] <<= pDoc->GetDocShell()->GetModel();
+ aGlobs <<= ::comphelper::getProcessServiceFactory()->createInstanceWithArguments( ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("ooo.vba.word.Globals")), aArgs );
+ pDoc->GetDocShell()->GetBasicManager()->SetGlobalUNOConstant( "VBAGlobals", aGlobs );
+ }
+ aGlobs >>= xRet;
+ }
+ }
+ break;
+
+ case SW_SERVICE_TYPE_FOOTNOTE :
+ xRet = (cppu::OWeakObject*)new SwXFootnote(sal_False);
+ break;
+ case SW_SERVICE_TYPE_ENDNOTE :
+ xRet = (cppu::OWeakObject*)new SwXFootnote(sal_True);
+ break;
+ case SW_SERVICE_CONTENT_INDEX_MARK :
+ case SW_SERVICE_USER_INDEX_MARK :
+ case SW_SERVICE_TYPE_INDEXMARK:
+ {
+ TOXTypes eType = TOX_INDEX;
+ if(SW_SERVICE_CONTENT_INDEX_MARK== nObjectType)
+ eType = TOX_CONTENT;
+ else if(SW_SERVICE_USER_INDEX_MARK == nObjectType)
+ eType = TOX_USER;
+ xRet = (cppu::OWeakObject*)new SwXDocumentIndexMark(eType);
+ }
+ break;
+ case SW_SERVICE_CONTENT_INDEX :
+ case SW_SERVICE_USER_INDEX :
+ case SW_SERVICE_TYPE_INDEX :
+ case SW_SERVICE_INDEX_ILLUSTRATIONS:
+ case SW_SERVICE_INDEX_OBJECTS :
+ case SW_SERVICE_INDEX_TABLES:
+ case SW_SERVICE_INDEX_BIBLIOGRAPHY :
+ {
+ TOXTypes eType = TOX_INDEX;
+ if(SW_SERVICE_CONTENT_INDEX == nObjectType)
+ eType = TOX_CONTENT;
+ else if(SW_SERVICE_USER_INDEX == nObjectType)
+ eType = TOX_USER;
+ else if(SW_SERVICE_INDEX_ILLUSTRATIONS == nObjectType)
+ {
+ eType = TOX_ILLUSTRATIONS;
+ }
+ else if(SW_SERVICE_INDEX_OBJECTS == nObjectType)
+ {
+ eType = TOX_OBJECTS;
+ }
+ else if(SW_SERVICE_INDEX_BIBLIOGRAPHY == nObjectType)
+ {
+ eType = TOX_AUTHORITIES;
+ }
+ else if(SW_SERVICE_INDEX_TABLES == nObjectType)
+ {
+ eType = TOX_TABLES;
+ }
+ xRet = (cppu::OWeakObject*)new SwXDocumentIndex(eType, *pDoc);
+ }
+ break;
+ case SW_SERVICE_INDEX_HEADER_SECTION :
+ case SW_SERVICE_TEXT_SECTION :
+ xRet = SwXTextSection::CreateXTextSection(0,
+ (SW_SERVICE_INDEX_HEADER_SECTION == nObjectType));
+
+ break;
+ case SW_SERVICE_REFERENCE_MARK :
+ xRet = (cppu::OWeakObject*)new SwXReferenceMark(0, 0);
+ break;
+ case SW_SERVICE_STYLE_CHARACTER_STYLE:
+ case SW_SERVICE_STYLE_PARAGRAPH_STYLE:
+ case SW_SERVICE_STYLE_CONDITIONAL_PARAGRAPH_STYLE:
+ case SW_SERVICE_STYLE_FRAME_STYLE:
+ case SW_SERVICE_STYLE_PAGE_STYLE:
+ case SW_SERVICE_STYLE_NUMBERING_STYLE:
+ {
+ SfxStyleFamily eFamily = SFX_STYLE_FAMILY_CHAR;
+ switch(nObjectType)
+ {
+ case SW_SERVICE_STYLE_PARAGRAPH_STYLE:
+ case SW_SERVICE_STYLE_CONDITIONAL_PARAGRAPH_STYLE:
+ eFamily = SFX_STYLE_FAMILY_PARA;
+ break;
+ case SW_SERVICE_STYLE_FRAME_STYLE:
+ eFamily = SFX_STYLE_FAMILY_FRAME;
+ break;
+ case SW_SERVICE_STYLE_PAGE_STYLE:
+ eFamily = SFX_STYLE_FAMILY_PAGE;
+ break;
+ case SW_SERVICE_STYLE_NUMBERING_STYLE:
+ eFamily = SFX_STYLE_FAMILY_PSEUDO;
+ break;
+ }
+ SwXStyle* pNewStyle = SFX_STYLE_FAMILY_PAGE == eFamily ?
+ new SwXPageStyle(pDoc->GetDocShell()) :
+ eFamily == SFX_STYLE_FAMILY_FRAME ?
+ new SwXFrameStyle ( pDoc ):
+ new SwXStyle( pDoc, eFamily, nObjectType == SW_SERVICE_STYLE_CONDITIONAL_PARAGRAPH_STYLE);
+ xRet = (cppu::OWeakObject*)pNewStyle;
+ }
+ break;
+// SW_SERVICE_DUMMY_5
+// SW_SERVICE_DUMMY_6
+// SW_SERVICE_DUMMY_7
+// SW_SERVICE_DUMMY_8
+// SW_SERVICE_DUMMY_9
+ case SW_SERVICE_FIELDTYPE_DATETIME:
+ case SW_SERVICE_FIELDTYPE_USER:
+ case SW_SERVICE_FIELDTYPE_SET_EXP:
+ case SW_SERVICE_FIELDTYPE_GET_EXP:
+ case SW_SERVICE_FIELDTYPE_FILE_NAME:
+ case SW_SERVICE_FIELDTYPE_PAGE_NUM:
+ case SW_SERVICE_FIELDTYPE_AUTHOR:
+ case SW_SERVICE_FIELDTYPE_CHAPTER:
+ case SW_SERVICE_FIELDTYPE_GET_REFERENCE:
+ case SW_SERVICE_FIELDTYPE_CONDITIONED_TEXT:
+ case SW_SERVICE_FIELDTYPE_INPUT:
+ case SW_SERVICE_FIELDTYPE_MACRO:
+ case SW_SERVICE_FIELDTYPE_DDE:
+ case SW_SERVICE_FIELDTYPE_HIDDEN_PARA:
+ case SW_SERVICE_FIELDTYPE_DOC_INFO:
+ case SW_SERVICE_FIELDTYPE_TEMPLATE_NAME:
+ case SW_SERVICE_FIELDTYPE_USER_EXT:
+ case SW_SERVICE_FIELDTYPE_REF_PAGE_SET:
+ case SW_SERVICE_FIELDTYPE_REF_PAGE_GET:
+ case SW_SERVICE_FIELDTYPE_JUMP_EDIT:
+ case SW_SERVICE_FIELDTYPE_SCRIPT:
+ case SW_SERVICE_FIELDTYPE_DATABASE_NEXT_SET:
+ case SW_SERVICE_FIELDTYPE_DATABASE_NUM_SET:
+ case SW_SERVICE_FIELDTYPE_DATABASE_SET_NUM:
+ case SW_SERVICE_FIELDTYPE_DATABASE:
+ case SW_SERVICE_FIELDTYPE_DATABASE_NAME:
+ case SW_SERVICE_FIELDTYPE_PAGE_COUNT :
+ case SW_SERVICE_FIELDTYPE_PARAGRAPH_COUNT :
+ case SW_SERVICE_FIELDTYPE_WORD_COUNT :
+ case SW_SERVICE_FIELDTYPE_CHARACTER_COUNT :
+ case SW_SERVICE_FIELDTYPE_TABLE_COUNT :
+ case SW_SERVICE_FIELDTYPE_GRAPHIC_OBJECT_COUNT :
+ case SW_SERVICE_FIELDTYPE_EMBEDDED_OBJECT_COUNT :
+ case SW_SERVICE_FIELDTYPE_DOCINFO_CHANGE_AUTHOR :
+ case SW_SERVICE_FIELDTYPE_DOCINFO_CHANGE_DATE_TIME :
+ case SW_SERVICE_FIELDTYPE_DOCINFO_EDIT_TIME :
+ case SW_SERVICE_FIELDTYPE_DOCINFO_DESCRIPTION :
+ case SW_SERVICE_FIELDTYPE_DOCINFO_CREATE_AUTHOR :
+ case SW_SERVICE_FIELDTYPE_DOCINFO_CREATE_DATE_TIME :
+ case SW_SERVICE_FIELDTYPE_DOCINFO_CUSTOM :
+ case SW_SERVICE_FIELDTYPE_DOCINFO_PRINT_AUTHOR :
+ case SW_SERVICE_FIELDTYPE_DOCINFO_PRINT_DATE_TIME :
+ case SW_SERVICE_FIELDTYPE_DOCINFO_KEY_WORDS :
+ case SW_SERVICE_FIELDTYPE_DOCINFO_SUBJECT :
+ case SW_SERVICE_FIELDTYPE_DOCINFO_TITLE :
+ case SW_SERVICE_FIELDTYPE_DOCINFO_REVISION :
+ case SW_SERVICE_FIELDTYPE_BIBLIOGRAPHY:
+ case SW_SERVICE_FIELDTYPE_INPUT_USER :
+ case SW_SERVICE_FIELDTYPE_HIDDEN_TEXT :
+ case SW_SERVICE_FIELDTYPE_COMBINED_CHARACTERS :
+ case SW_SERVICE_FIELDTYPE_DROPDOWN :
+ case SW_SERVICE_FIELDTYPE_TABLE_FORMULA:
+ xRet = (cppu::OWeakObject*)new SwXTextField(nObjectType);
+ break;
+ case SW_SERVICE_FIELDTYPE_ANNOTATION:
+ xRet = (cppu::OWeakObject*)new SwXTextField(nObjectType, pDoc);
+ break;
+ case SW_SERVICE_FIELDMASTER_USER:
+ case SW_SERVICE_FIELDMASTER_DDE:
+ case SW_SERVICE_FIELDMASTER_SET_EXP :
+ case SW_SERVICE_FIELDMASTER_DATABASE:
+ {
+ sal_uInt16 nResId = USHRT_MAX;
+ switch(nObjectType)
+ {
+ case SW_SERVICE_FIELDMASTER_USER: nResId = RES_USERFLD; break;
+ case SW_SERVICE_FIELDMASTER_DDE: nResId = RES_DDEFLD; break;
+ case SW_SERVICE_FIELDMASTER_SET_EXP : nResId = RES_SETEXPFLD; break;
+ case SW_SERVICE_FIELDMASTER_DATABASE: nResId = RES_DBFLD; break;
+ }
+ xRet = (cppu::OWeakObject*)new SwXFieldMaster(pDoc, nResId);
+ }
+ break;
+ case SW_SERVICE_FIELDMASTER_BIBLIOGRAPHY:
+ {
+ SwFieldType* pType = pDoc->GetFldType(RES_AUTHORITY, aEmptyStr, sal_True);
+ if(!pType)
+ {
+ SwAuthorityFieldType aType(pDoc);
+ pType = pDoc->InsertFldType(aType);
+ }
+ else
+ {
+ SwXFieldMaster* pMaster = SwIterator<SwXFieldMaster,SwFieldType>::FirstElement( *pType );
+ if(pMaster)
+ xRet = (cppu::OWeakObject*)pMaster;
+ }
+ if(!xRet.is())
+ xRet = (cppu::OWeakObject*)new SwXFieldMaster(*pType, pDoc);
+ }
+ break;
+ case SW_SERVICE_PARAGRAPH :
+ xRet = (cppu::OWeakObject*)new SwXParagraph();
+ break;
+ case SW_SERVICE_NUMBERING_RULES :
+ xRet = (cppu::OWeakObject*)new SwXNumberingRules(*pDoc);
+ break;
+ case SW_SERVICE_TEXT_COLUMNS :
+ xRet = (cppu::OWeakObject*)new SwXTextColumns(0);
+ break;
+ case SW_SERVICE_DEFAULTS:
+ xRet = (cppu::OWeakObject*)new SwXTextDefaults( pDoc );
+ break;
+ case SW_SERVICE_IMAP_RECTANGLE :
+ xRet = SvUnoImageMapRectangleObject_createInstance( lcl_GetSupportedMacroItems() );
+ break;
+ case SW_SERVICE_IMAP_CIRCLE :
+ xRet = SvUnoImageMapCircleObject_createInstance( lcl_GetSupportedMacroItems() );
+ break;
+ case SW_SERVICE_IMAP_POLYGON :
+ xRet = SvUnoImageMapPolygonObject_createInstance( lcl_GetSupportedMacroItems() );
+ break;
+ case SW_SERVICE_CHART2_DATA_PROVIDER :
+ // #i64497# If a chart is in a temporary document during clipoard
+ // paste, there should be no data provider, so that own data is used
+ // This should not happen during copy/paste, as this will unlink
+ // charts using table data.
+ OSL_ASSERT( pDoc->GetDocShell()->GetCreateMode() != SFX_CREATE_MODE_EMBEDDED );
+ if( pDoc->GetDocShell()->GetCreateMode() != SFX_CREATE_MODE_EMBEDDED )
+ xRet = (cppu::OWeakObject*) pDoc->GetChartDataProvider( true /* create - if not yet available */ );
+ break;
+ case SW_SERVICE_TYPE_META:
+ xRet = static_cast< ::cppu::OWeakObject* >( new SwXMeta(pDoc) );
+ break;
+ case SW_SERVICE_FIELDTYPE_METAFIELD:
+ xRet = static_cast< ::cppu::OWeakObject* >(new SwXMetaField(pDoc));
+ break;
+ default:
+ throw uno::RuntimeException();
+ }
+ return xRet;
+}
+
+/******************************************************************
+ * SwXTextTables
+ ******************************************************************/
+//SMART_UNO_IMPLEMENTATION( SwXTextTables, UsrObject );
+SwXTextTables::SwXTextTables(SwDoc* pDc) :
+ SwUnoCollection(pDc)
+{
+
+}
+
+SwXTextTables::~SwXTextTables()
+{
+
+}
+
+sal_Int32 SwXTextTables::getCount(void) throw( uno::RuntimeException )
+{
+ SolarMutexGuard aGuard;
+ sal_Int32 nRet = 0;
+ if(IsValid())
+ nRet = GetDoc()->GetTblFrmFmtCount(sal_True);
+ return nRet;
+}
+
+uno::Any SAL_CALL SwXTextTables::getByIndex(sal_Int32 nIndex)
+ throw( IndexOutOfBoundsException, WrappedTargetException, uno::RuntimeException )
+{
+ SolarMutexGuard aGuard;
+ uno::Any aRet;
+ if(IsValid())
+ {
+ if(0 <= nIndex && GetDoc()->GetTblFrmFmtCount(sal_True) > nIndex)
+ {
+ SwFrmFmt& rFmt = GetDoc()->GetTblFrmFmt( static_cast< xub_StrLen >(nIndex), sal_True);
+ uno::Reference< XTextTable > xTbl = SwXTextTables::GetObject(rFmt);
+ aRet.setValue( &xTbl,
+ ::getCppuType((uno::Reference< XTextTable>*)0));
+ }
+ else
+ throw IndexOutOfBoundsException();
+ }
+ else
+ throw uno::RuntimeException();
+ return aRet;
+}
+
+uno::Any SwXTextTables::getByName(const OUString& rItemName)
+ throw( NoSuchElementException, WrappedTargetException, uno::RuntimeException )
+{
+ SolarMutexGuard aGuard;
+ uno::Any aRet;
+ if(IsValid())
+ {
+ sal_uInt16 nCount = GetDoc()->GetTblFrmFmtCount(sal_True);
+ uno::Reference< XTextTable > xTbl;
+ for( sal_uInt16 i = 0; i < nCount; i++)
+ {
+ String aName(rItemName);
+ SwFrmFmt& rFmt = GetDoc()->GetTblFrmFmt(i, sal_True);
+ if(aName == rFmt.GetName())
+ {
+ xTbl = SwXTextTables::GetObject(rFmt);
+ aRet.setValue(&xTbl,
+ ::getCppuType(( uno::Reference< XTextTable >*)0));
+ break;
+ }
+ }
+ if(!xTbl.is())
+ throw NoSuchElementException();
+ }
+ else
+ throw uno::RuntimeException();
+ return aRet;
+}
+
+uno::Sequence< OUString > SwXTextTables::getElementNames(void)
+ throw( uno::RuntimeException )
+{
+ SolarMutexGuard aGuard;
+ if(!IsValid())
+ throw uno::RuntimeException();
+ sal_uInt16 nCount = GetDoc()->GetTblFrmFmtCount(sal_True);
+ uno::Sequence<OUString> aSeq(nCount);
+ if(nCount)
+ {
+ OUString* pArray = aSeq.getArray();
+ for( sal_uInt16 i = 0; i < nCount; i++)
+ {
+ SwFrmFmt& rFmt = GetDoc()->GetTblFrmFmt(i, sal_True);
+
+ pArray[i] = OUString(rFmt.GetName());
+ }
+ }
+ return aSeq;
+}
+
+sal_Bool SwXTextTables::hasByName(const OUString& rName)
+ throw( uno::RuntimeException )
+{
+ SolarMutexGuard aGuard;
+ sal_Bool bRet= sal_False;
+ if(IsValid())
+ {
+ sal_uInt16 nCount = GetDoc()->GetTblFrmFmtCount(sal_True);
+ for( sal_uInt16 i = 0; i < nCount; i++)
+ {
+ String aName(rName);
+ SwFrmFmt& rFmt = GetDoc()->GetTblFrmFmt(i, sal_True);
+ if(aName == rFmt.GetName())
+ {
+ bRet = sal_True;
+ break;
+ }
+ }
+ }
+ else
+ throw uno::RuntimeException();
+ return bRet;
+}
+
+uno::Type SAL_CALL
+ SwXTextTables::getElementType( )
+ throw(uno::RuntimeException)
+{
+ return ::getCppuType((uno::Reference<XTextTable>*)0);
+}
+
+sal_Bool SwXTextTables::hasElements(void) throw( uno::RuntimeException )
+{
+ SolarMutexGuard aGuard;
+ if(!IsValid())
+ throw uno::RuntimeException();
+ return 0 != GetDoc()->GetTblFrmFmtCount(sal_True);
+}
+
+OUString SwXTextTables::getImplementationName(void) throw( uno::RuntimeException )
+{
+ return C2U("SwXTextTables");
+}
+
+sal_Bool SwXTextTables::supportsService(const OUString& rServiceName) throw( uno::RuntimeException )
+{
+ return rServiceName == C2U("com.sun.star.text.TextTables");
+}
+
+uno::Sequence< OUString > SwXTextTables::getSupportedServiceNames(void) throw( uno::RuntimeException )
+{
+ uno::Sequence< OUString > aRet(1);
+ OUString* pArr = aRet.getArray();
+ pArr[0] = C2U("com.sun.star.text.TextTables");
+ return aRet;
+}
+
+XTextTable* SwXTextTables::GetObject( SwFrmFmt& rFmt )
+{
+ SolarMutexGuard aGuard;
+ SwXTextTable* pTbl = SwIterator<SwXTextTable,SwFmt>::FirstElement( rFmt );
+ if( !pTbl )
+ pTbl = new SwXTextTable(rFmt);
+ return pTbl ;
+}
+
+/******************************************************************
+ * SwXFrameEnumeration
+ ******************************************************************/
+namespace
+{
+ template<FlyCntType T> struct UnoFrameWrap_traits {};
+
+ template<>
+ struct UnoFrameWrap_traits<FLYCNTTYPE_FRM>
+ {
+ typedef SwXTextFrame core_frame_t;
+ typedef XTextFrame uno_frame_t;
+ static inline bool filter(const SwNode* const pNode) { return !pNode->IsNoTxtNode(); };
+ };
+
+ template<>
+ struct UnoFrameWrap_traits<FLYCNTTYPE_GRF>
+ {
+ typedef SwXTextGraphicObject core_frame_t;
+ typedef XTextContent uno_frame_t;
+ static inline bool filter(const SwNode* const pNode) { return pNode->IsGrfNode(); };
+ };
+
+ template<>
+ struct UnoFrameWrap_traits<FLYCNTTYPE_OLE>
+ {
+ typedef SwXTextEmbeddedObject core_frame_t;
+ typedef XEmbeddedObjectSupplier uno_frame_t;
+ static inline bool filter(const SwNode* const pNode) { return pNode->IsOLENode(); };
+ };
+
+ template<FlyCntType T>
+ static uno::Any lcl_UnoWrapFrame(SwFrmFmt* pFmt)
+ {
+ SwXFrame* pFrm = SwIterator<SwXFrame,SwFmt>::FirstElement( *pFmt );
+ if(!pFrm)
+ pFrm = new typename UnoFrameWrap_traits<T>::core_frame_t(*pFmt);
+ Reference< typename UnoFrameWrap_traits<T>::uno_frame_t > xFrm =
+ static_cast< typename UnoFrameWrap_traits<T>::core_frame_t* >(pFrm);
+ return uno::makeAny(xFrm);
+ }
+
+ // runtime adapter for lcl_UnoWrapFrame
+ static uno::Any lcl_UnoWrapFrame(SwFrmFmt* pFmt, FlyCntType eType) throw(uno::RuntimeException())
+ {
+ switch(eType)
+ {
+ case FLYCNTTYPE_FRM:
+ return lcl_UnoWrapFrame<FLYCNTTYPE_FRM>(pFmt);
+ case FLYCNTTYPE_GRF:
+ return lcl_UnoWrapFrame<FLYCNTTYPE_GRF>(pFmt);
+ case FLYCNTTYPE_OLE:
+ return lcl_UnoWrapFrame<FLYCNTTYPE_OLE>(pFmt);
+ default:
+ throw uno::RuntimeException();
+ }
+ }
+
+ template<FlyCntType T>
+ class SwXFrameEnumeration
+ : public SwSimpleEnumeration_Base
+ {
+ private:
+ typedef ::std::list< Any > frmcontainer_t;
+ frmcontainer_t m_aFrames;
+ protected:
+ virtual ~SwXFrameEnumeration() {};
+ public:
+ SwXFrameEnumeration(const SwDoc* const pDoc);
+
+ //XEnumeration
+ virtual sal_Bool SAL_CALL hasMoreElements(void) throw( RuntimeException );
+ virtual Any SAL_CALL nextElement(void) throw( NoSuchElementException, WrappedTargetException, RuntimeException );
+
+ //XServiceInfo
+ virtual OUString SAL_CALL getImplementationName(void) throw( RuntimeException );
+ virtual sal_Bool SAL_CALL supportsService(const OUString& ServiceName) throw( RuntimeException );
+ virtual Sequence< OUString > SAL_CALL getSupportedServiceNames(void) throw( RuntimeException );
+ };
+}
+
+template<FlyCntType T>
+SwXFrameEnumeration<T>::SwXFrameEnumeration(const SwDoc* const pDoc)
+ : m_aFrames()
+{
+ SolarMutexGuard aGuard;
+ const SwSpzFrmFmts* const pFmts = pDoc->GetSpzFrmFmts();
+ if(!pFmts->Count())
+ return;
+ // --> OD 2009-09-10 #i104937#
+// const SwFrmFmt* const pFmtsEnd = (*pFmts)[pFmts->Count()];
+ const sal_uInt16 nSize = pFmts->Count();
+ // <--
+ ::std::insert_iterator<frmcontainer_t> pInserter = ::std::insert_iterator<frmcontainer_t>(m_aFrames, m_aFrames.begin());
+ // --> OD 2009-09-10 #i104937#
+ SwFrmFmt* pFmt( 0 );
+ for( sal_uInt16 i = 0; i < nSize; ++i )
+// for(SwFrmFmt* pFmt = (*pFmts)[0]; pFmt < pFmtsEnd; ++pFmt)
+ // <--
+ {
+ // --> OD 2009-09-10 #i104937#
+ pFmt = (*pFmts)[i];
+ // <--
+ if(pFmt->Which() != RES_FLYFRMFMT)
+ continue;
+ const SwNodeIndex* pIdx = pFmt->GetCntnt().GetCntntIdx();
+ if(!pIdx || !pIdx->GetNodes().IsDocNodes())
+ continue;
+ const SwNode* pNd = pDoc->GetNodes()[ pIdx->GetIndex() + 1 ];
+ if(UnoFrameWrap_traits<T>::filter(pNd))
+ *pInserter++ = lcl_UnoWrapFrame<T>(pFmt);
+ }
+}
+
+template<FlyCntType T>
+sal_Bool SwXFrameEnumeration<T>::hasMoreElements(void) throw( RuntimeException )
+{
+ SolarMutexGuard aGuard;
+ return !m_aFrames.empty();
+}
+
+template<FlyCntType T>
+Any SwXFrameEnumeration<T>::nextElement(void) throw( NoSuchElementException, WrappedTargetException, RuntimeException )
+{
+ SolarMutexGuard aGuard;
+ if(m_aFrames.empty())
+ throw NoSuchElementException();
+ Any aResult = *m_aFrames.begin();
+ m_aFrames.pop_front();
+ return aResult;
+}
+
+template<FlyCntType T>
+OUString SwXFrameEnumeration<T>::getImplementationName(void) throw( RuntimeException )
+{
+ return C2U("SwXFrameEnumeration");
+}
+
+template<FlyCntType T>
+sal_Bool SwXFrameEnumeration<T>::supportsService(const OUString& ServiceName) throw( RuntimeException )
+{
+ return C2U("com.sun.star.container.XEnumeration") == ServiceName;
+}
+
+template<FlyCntType T>
+Sequence< OUString > SwXFrameEnumeration<T>::getSupportedServiceNames(void) throw( RuntimeException )
+{
+ return ::comphelper::makeSequence(C2U("com.sun.star.container.XEnumeration"));
+}
+
+/******************************************************************
+ * SwXFrames
+ ******************************************************************/
+OUString SwXFrames::getImplementationName(void) throw( RuntimeException )
+{
+ return C2U("SwXFrames");
+}
+
+sal_Bool SwXFrames::supportsService(const OUString& rServiceName) throw( RuntimeException )
+{
+ return C2U("com.sun.star.text.TextFrames") == rServiceName;
+}
+
+Sequence<OUString> SwXFrames::getSupportedServiceNames(void) throw( RuntimeException )
+{
+ return ::comphelper::makeSequence(C2U("com.sun.star.text.TextFrames"));
+}
+
+SwXFrames::SwXFrames(SwDoc* _pDoc, FlyCntType eSet) :
+ SwUnoCollection(_pDoc),
+ eType(eSet)
+{}
+
+SwXFrames::~SwXFrames()
+{}
+
+uno::Reference<container::XEnumeration> SwXFrames::createEnumeration(void) throw(uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+ if(!IsValid())
+ throw uno::RuntimeException();
+ switch(eType)
+ {
+ case FLYCNTTYPE_FRM:
+ return uno::Reference< container::XEnumeration >(
+ new SwXFrameEnumeration<FLYCNTTYPE_FRM>(GetDoc()));
+ case FLYCNTTYPE_GRF:
+ return uno::Reference< container::XEnumeration >(
+ new SwXFrameEnumeration<FLYCNTTYPE_GRF>(GetDoc()));
+ case FLYCNTTYPE_OLE:
+ return uno::Reference< container::XEnumeration >(
+ new SwXFrameEnumeration<FLYCNTTYPE_OLE>(GetDoc()));
+ default:
+ throw uno::RuntimeException();
+ }
+}
+
+sal_Int32 SwXFrames::getCount(void) throw(uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+ if(!IsValid())
+ throw uno::RuntimeException();
+ return GetDoc()->GetFlyCount(eType);
+}
+
+uno::Any SwXFrames::getByIndex(sal_Int32 nIndex)
+ throw(IndexOutOfBoundsException, WrappedTargetException, uno::RuntimeException )
+{
+ SolarMutexGuard aGuard;
+ if(!IsValid())
+ throw uno::RuntimeException();
+ if(nIndex < 0 || nIndex >= USHRT_MAX)
+ throw IndexOutOfBoundsException();
+ SwFrmFmt* pFmt = GetDoc()->GetFlyNum(static_cast<sal_uInt16>(nIndex), eType);
+ if(!pFmt)
+ throw IndexOutOfBoundsException();
+ return lcl_UnoWrapFrame(pFmt, eType);
+}
+
+uno::Any SwXFrames::getByName(const OUString& rName)
+ throw(NoSuchElementException, WrappedTargetException, uno::RuntimeException )
+{
+ SolarMutexGuard aGuard;
+ if(!IsValid())
+ throw uno::RuntimeException();
+ const SwFrmFmt* pFmt;
+ switch(eType)
+ {
+ case FLYCNTTYPE_GRF:
+ pFmt = GetDoc()->FindFlyByName(rName, ND_GRFNODE);
+ break;
+ case FLYCNTTYPE_OLE:
+ pFmt = GetDoc()->FindFlyByName(rName, ND_OLENODE);
+ break;
+ default:
+ pFmt = GetDoc()->FindFlyByName(rName, ND_TEXTNODE);
+ break;
+ }
+ if(!pFmt)
+ throw NoSuchElementException();
+ return lcl_UnoWrapFrame(const_cast<SwFrmFmt*>(pFmt), eType);
+}
+
+uno::Sequence<OUString> SwXFrames::getElementNames(void) throw( uno::RuntimeException )
+{
+ SolarMutexGuard aGuard;
+ if(!IsValid())
+ throw uno::RuntimeException();
+ const Reference<XEnumeration> xEnum = createEnumeration();
+ ::std::vector<OUString> vNames;
+ while(xEnum->hasMoreElements())
+ {
+ Reference<container::XNamed> xNamed;
+ xEnum->nextElement() >>= xNamed;
+ if(xNamed.is())
+ vNames.push_back(xNamed->getName());
+ }
+ return ::comphelper::containerToSequence(vNames);
+}
+
+sal_Bool SwXFrames::hasByName(const OUString& rName) throw( uno::RuntimeException )
+{
+ SolarMutexGuard aGuard;
+ if(!IsValid())
+ throw uno::RuntimeException();
+ switch(eType)
+ {
+ case FLYCNTTYPE_GRF:
+ return GetDoc()->FindFlyByName(rName, ND_GRFNODE) != NULL;
+ case FLYCNTTYPE_OLE:
+ return GetDoc()->FindFlyByName(rName, ND_OLENODE) != NULL;
+ default:
+ return GetDoc()->FindFlyByName(rName, ND_TEXTNODE) != NULL;
+ }
+}
+
+uno::Type SAL_CALL SwXFrames::getElementType() throw(uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+ switch(eType)
+ {
+ case FLYCNTTYPE_FRM:
+ return ::getCppuType((uno::Reference<XTextFrame>*)0);
+ case FLYCNTTYPE_GRF:
+ return ::getCppuType((uno::Reference<XTextContent>*)0);
+ case FLYCNTTYPE_OLE:
+ return ::getCppuType((uno::Reference<XEmbeddedObjectSupplier>*)0);
+ default:
+ return uno::Type();
+ }
+}
+
+sal_Bool SwXFrames::hasElements(void) throw(uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+ if(!IsValid())
+ throw uno::RuntimeException();
+ return GetDoc()->GetFlyCount(eType) > 0;
+}
+
+SwXFrame* SwXFrames::GetObject(SwFrmFmt& rFmt, FlyCntType eType)
+{
+ SwXFrame* pFrm = SwIterator<SwXFrame,SwFmt>::FirstElement( rFmt );
+ if(pFrm) return pFrm;
+ switch(eType)
+ {
+ case FLYCNTTYPE_FRM:
+ return new SwXTextFrame(rFmt);
+ case FLYCNTTYPE_GRF:
+ return new SwXTextGraphicObject(rFmt);
+ case FLYCNTTYPE_OLE:
+ return new SwXTextEmbeddedObject(rFmt);
+ default:
+ return NULL;
+ }
+}
+
+/******************************************************************
+ * SwXTextFrames
+ ******************************************************************/
+OUString SwXTextFrames::getImplementationName(void) throw( RuntimeException )
+{
+ return C2U("SwXTextFrames");
+}
+
+sal_Bool SwXTextFrames::supportsService(const OUString& rServiceName) throw( RuntimeException )
+{
+ return C2U("com.sun.star.text.TextFrames") == rServiceName;
+}
+
+Sequence< OUString > SwXTextFrames::getSupportedServiceNames(void) throw( RuntimeException )
+{
+ Sequence< OUString > aRet(1);
+ OUString* pArray = aRet.getArray();
+ pArray[0] = C2U("com.sun.star.text.TextFrames");
+ return aRet;
+}
+
+SwXTextFrames::SwXTextFrames(SwDoc* _pDoc) :
+ SwXFrames(_pDoc, FLYCNTTYPE_FRM)
+{
+}
+
+SwXTextFrames::~SwXTextFrames()
+{
+}
+
+/******************************************************************
+ * SwXTextGraphicObjects
+ ******************************************************************/
+OUString SwXTextGraphicObjects::getImplementationName(void) throw( RuntimeException )
+{
+ return C2U("SwXTextGraphicObjects");
+}
+
+sal_Bool SwXTextGraphicObjects::supportsService(const OUString& rServiceName) throw( RuntimeException )
+{
+ return C2U("com.sun.star.text.TextGraphicObjects") == rServiceName;
+}
+
+Sequence< OUString > SwXTextGraphicObjects::getSupportedServiceNames(void) throw( RuntimeException )
+{
+ Sequence< OUString > aRet(1);
+ OUString* pArray = aRet.getArray();
+ pArray[0] = C2U("com.sun.star.text.TextGraphicObjects");
+ return aRet;
+}
+
+SwXTextGraphicObjects::SwXTextGraphicObjects(SwDoc* _pDoc) :
+ SwXFrames(_pDoc, FLYCNTTYPE_GRF)
+{
+}
+
+SwXTextGraphicObjects::~SwXTextGraphicObjects()
+{
+}
+
+/******************************************************************
+ * SwXTextEmbeddedObjects
+ ******************************************************************/
+OUString SwXTextEmbeddedObjects::getImplementationName(void) throw( RuntimeException )
+{
+ return C2U("SwXTextEmbeddedObjects");
+}
+
+sal_Bool SwXTextEmbeddedObjects::supportsService(const OUString& rServiceName) throw( RuntimeException )
+{
+ return C2U("com.sun.star.text.TextEmbeddedObjects") == rServiceName;
+}
+
+Sequence< OUString > SwXTextEmbeddedObjects::getSupportedServiceNames(void) throw( RuntimeException )
+{
+ Sequence< OUString > aRet(1);
+ OUString* pArray = aRet.getArray();
+ pArray[0] = C2U("com.sun.star.text.TextEmbeddedObjects");
+ return aRet;
+}
+
+SwXTextEmbeddedObjects::SwXTextEmbeddedObjects(SwDoc* _pDoc) :
+ SwXFrames(_pDoc, FLYCNTTYPE_OLE)
+{
+}
+
+SwXTextEmbeddedObjects::~SwXTextEmbeddedObjects()
+{
+}
+
+#define PASSWORD_STD_TIMEOUT 1000
+OUString SwXTextSections::getImplementationName(void) throw( RuntimeException )
+{
+ return C2U("SwXTextSections");
+}
+
+sal_Bool SwXTextSections::supportsService(const OUString& rServiceName) throw( RuntimeException )
+{
+ return C2U("com.sun.star.text.TextSections") == rServiceName;
+}
+
+Sequence< OUString > SwXTextSections::getSupportedServiceNames(void) throw( RuntimeException )
+{
+ Sequence< OUString > aRet(1);
+ OUString* pArray = aRet.getArray();
+ pArray[0] = C2U("com.sun.star.text.TextSections");
+ return aRet;
+}
+
+SwXTextSections::SwXTextSections(SwDoc* _pDoc) :
+ SwUnoCollection(_pDoc)
+{
+}
+
+SwXTextSections::~SwXTextSections()
+{
+}
+
+sal_Int32 SwXTextSections::getCount(void) throw( uno::RuntimeException )
+{
+ SolarMutexGuard aGuard;
+ if(!IsValid())
+ throw uno::RuntimeException();
+ const SwSectionFmts& rSectFmts = GetDoc()->GetSections();
+ sal_uInt16 nCount = rSectFmts.Count();
+ for(sal_uInt16 i = nCount; i; i--)
+ {
+ if( !rSectFmts[i - 1]->IsInNodesArr())
+ nCount--;
+ }
+ return nCount;
+}
+
+uno::Any SwXTextSections::getByIndex(sal_Int32 nIndex)
+ throw( IndexOutOfBoundsException, WrappedTargetException, uno::RuntimeException )
+{
+ SolarMutexGuard aGuard;
+ uno::Reference< XTextSection > xRet;
+ if(IsValid())
+ {
+ SwSectionFmts& rFmts = GetDoc()->GetSections();
+
+ const SwSectionFmts& rSectFmts = GetDoc()->GetSections();
+ sal_uInt16 nCount = rSectFmts.Count();
+ for(sal_uInt16 i = 0; i < nCount; i++)
+ {
+ if( !rSectFmts[i]->IsInNodesArr())
+ nIndex ++;
+ else if(nIndex == i)
+ break;
+ if(nIndex == i)
+ break;
+ }
+ if(nIndex >= 0 && nIndex < rFmts.Count())
+ {
+ SwSectionFmt* pFmt = rFmts[(sal_uInt16)nIndex];
+ xRet = GetObject(*pFmt);
+ }
+ else
+ throw IndexOutOfBoundsException();
+ }
+ else
+ throw uno::RuntimeException();
+ return makeAny(xRet);
+}
+
+uno::Any SwXTextSections::getByName(const OUString& Name)
+ throw( NoSuchElementException, WrappedTargetException, uno::RuntimeException )
+{
+ SolarMutexGuard aGuard;
+ uno::Any aRet;
+ if(IsValid())
+ {
+ String aName(Name);
+ SwSectionFmts& rFmts = GetDoc()->GetSections();
+ uno::Reference< XTextSection > xSect;
+ for(sal_uInt16 i = 0; i < rFmts.Count(); i++)
+ {
+ SwSectionFmt* pFmt = rFmts[i];
+ if (pFmt->IsInNodesArr()
+ && (aName == pFmt->GetSection()->GetSectionName()))
+ {
+ xSect = GetObject(*pFmt);
+ aRet.setValue(&xSect, ::getCppuType((uno::Reference<XTextSection>*)0));
+ break;
+ }
+ }
+ if(!xSect.is())
+ throw NoSuchElementException();
+ }
+ else
+ throw uno::RuntimeException();
+ return aRet;
+}
+
+uno::Sequence< OUString > SwXTextSections::getElementNames(void)
+ throw( uno::RuntimeException )
+{
+ SolarMutexGuard aGuard;
+ if(!IsValid())
+ throw uno::RuntimeException();
+ sal_uInt16 nCount = GetDoc()->GetSections().Count();
+ SwSectionFmts& rSectFmts = GetDoc()->GetSections();
+ for(sal_uInt16 i = nCount; i; i--)
+ {
+ if( !rSectFmts[i - 1]->IsInNodesArr())
+ nCount--;
+ }
+
+ uno::Sequence<OUString> aSeq(nCount);
+ if(nCount)
+ {
+ SwSectionFmts& rFmts = GetDoc()->GetSections();
+ OUString* pArray = aSeq.getArray();
+ sal_uInt16 nIndex = 0;
+ for( sal_uInt16 i = 0; i < nCount; i++, nIndex++)
+ {
+ const SwSectionFmt* pFmt = rFmts[nIndex];
+ while(!pFmt->IsInNodesArr())
+ {
+ pFmt = rFmts[++nIndex];
+ }
+ pArray[i] = pFmt->GetSection()->GetSectionName();
+ }
+ }
+ return aSeq;
+}
+
+sal_Bool SwXTextSections::hasByName(const OUString& Name)
+ throw( uno::RuntimeException )
+{
+ SolarMutexGuard aGuard;
+ sal_Bool bRet = sal_False;
+ String aName(Name);
+ if(IsValid())
+ {
+ SwSectionFmts& rFmts = GetDoc()->GetSections();
+ for(sal_uInt16 i = 0; i < rFmts.Count(); i++)
+ {
+ const SwSectionFmt* pFmt = rFmts[i];
+ if (aName == pFmt->GetSection()->GetSectionName())
+ {
+ bRet = sal_True;
+ break;
+ }
+ }
+ }
+ else
+ {
+ //Sonderbehandlung der dbg_ - Methoden
+ if( COMPARE_EQUAL != aName.CompareToAscii("dbg_", 4))
+ throw uno::RuntimeException();
+ }
+ return bRet;
+}
+
+uno::Type SAL_CALL SwXTextSections::getElementType() throw(uno::RuntimeException)
+{
+ return ::getCppuType((uno::Reference<XTextSection>*)0);
+}
+
+sal_Bool SwXTextSections::hasElements(void) throw( uno::RuntimeException )
+{
+ SolarMutexGuard aGuard;
+ sal_uInt16 nCount = 0;
+ if(IsValid())
+ {
+ SwSectionFmts& rFmts = GetDoc()->GetSections();
+ nCount = rFmts.Count();
+ }
+ else
+ throw uno::RuntimeException();
+ return nCount > 0;
+}
+
+uno::Reference< XTextSection > SwXTextSections::GetObject( SwSectionFmt& rFmt )
+{
+ return SwXTextSection::CreateXTextSection(&rFmt);
+}
+
+OUString SwXBookmarks::getImplementationName(void) throw( RuntimeException )
+{
+ return OUString(RTL_CONSTASCII_USTRINGPARAM("SwXBookmarks"));
+}
+
+sal_Bool SwXBookmarks::supportsService(const OUString& rServiceName) throw( RuntimeException )
+{
+ return OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.text.Bookmarks")) == rServiceName;
+}
+
+Sequence< OUString > SwXBookmarks::getSupportedServiceNames(void) throw( RuntimeException )
+{
+ Sequence< OUString > aRet(1);
+ aRet[0] = OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.text.Bookmarks"));
+ return aRet;
+}
+
+SwXBookmarks::SwXBookmarks(SwDoc* _pDoc) :
+ SwUnoCollection(_pDoc)
+{ }
+
+SwXBookmarks::~SwXBookmarks()
+{ }
+
+sal_Int32 SwXBookmarks::getCount(void)
+ throw( uno::RuntimeException )
+{
+ SolarMutexGuard aGuard;
+ if(!IsValid())
+ throw uno::RuntimeException();
+ return GetDoc()->getIDocumentMarkAccess()->getMarksCount();
+}
+
+uno::Any SwXBookmarks::getByIndex(sal_Int32 nIndex)
+ throw( IndexOutOfBoundsException, WrappedTargetException, uno::RuntimeException )
+{
+ SolarMutexGuard aGuard;
+ if(!IsValid())
+ throw uno::RuntimeException();
+ IDocumentMarkAccess* const pMarkAccess = GetDoc()->getIDocumentMarkAccess();
+ if(nIndex < 0 || nIndex >= pMarkAccess->getMarksCount())
+ throw IndexOutOfBoundsException();
+
+ uno::Any aRet;
+ ::sw::mark::IMark* pBkmk = pMarkAccess->getMarksBegin()[nIndex].get();
+ const uno::Reference< text::XTextContent > xRef =
+ SwXBookmark::CreateXBookmark(*GetDoc(), *pBkmk);
+ aRet <<= xRef;
+ return aRet;
+}
+
+uno::Any SwXBookmarks::getByName(const rtl::OUString& rName)
+ throw( NoSuchElementException, WrappedTargetException, uno::RuntimeException )
+{
+ SolarMutexGuard aGuard;
+ if(!IsValid())
+ throw uno::RuntimeException();
+
+ IDocumentMarkAccess* const pMarkAccess = GetDoc()->getIDocumentMarkAccess();
+ IDocumentMarkAccess::const_iterator_t ppBkmk = pMarkAccess->findMark(rName);
+ if(ppBkmk == pMarkAccess->getMarksEnd())
+ throw NoSuchElementException();
+
+ uno::Any aRet;
+ const uno::Reference< text::XTextContent > xRef =
+ SwXBookmark::CreateXBookmark(*GetDoc(), *(ppBkmk->get()));
+ aRet <<= xRef;
+ return aRet;
+}
+
+uno::Sequence< OUString > SwXBookmarks::getElementNames(void)
+ throw( uno::RuntimeException )
+{
+ SolarMutexGuard aGuard;
+ if(!IsValid())
+ throw uno::RuntimeException();
+
+ IDocumentMarkAccess* const pMarkAccess = GetDoc()->getIDocumentMarkAccess();
+ uno::Sequence<OUString> aSeq(pMarkAccess->getMarksCount());
+ sal_Int32 nCnt = 0;
+ for(IDocumentMarkAccess::const_iterator_t ppMark = pMarkAccess->getMarksBegin();
+ ppMark != pMarkAccess->getMarksEnd();)
+ aSeq[nCnt++] = (*ppMark++)->GetName();
+ return aSeq;
+}
+
+sal_Bool SwXBookmarks::hasByName(const OUString& rName)
+ throw( uno::RuntimeException )
+{
+ SolarMutexGuard aGuard;
+ if(!IsValid())
+ throw uno::RuntimeException();
+
+ IDocumentMarkAccess* const pMarkAccess = GetDoc()->getIDocumentMarkAccess();
+ return pMarkAccess->findMark(rName) != pMarkAccess->getMarksEnd();
+}
+
+uno::Type SAL_CALL SwXBookmarks::getElementType()
+ throw(uno::RuntimeException)
+{
+ return ::getCppuType((uno::Reference<XTextContent>*)0);
+}
+
+sal_Bool SwXBookmarks::hasElements(void)
+ throw( uno::RuntimeException )
+{
+ SolarMutexGuard aGuard;
+ if(!IsValid())
+ throw uno::RuntimeException();
+ return GetDoc()->getIDocumentMarkAccess()->getBookmarksCount() != 0;
+}
+
+SwXNumberingRulesCollection::SwXNumberingRulesCollection( SwDoc* _pDoc ) :
+ SwUnoCollection(_pDoc)
+{
+}
+
+SwXNumberingRulesCollection::~SwXNumberingRulesCollection()
+{
+}
+
+sal_Int32 SwXNumberingRulesCollection::getCount(void) throw( uno::RuntimeException )
+{
+ SolarMutexGuard aGuard;
+ if(!IsValid())
+ throw uno::RuntimeException();
+ return GetDoc()->GetNumRuleTbl().Count();
+}
+
+uno::Any SwXNumberingRulesCollection::getByIndex(sal_Int32 nIndex)
+ throw( IndexOutOfBoundsException, WrappedTargetException, uno::RuntimeException )
+{
+ SolarMutexGuard aGuard;
+ uno::Any aRet;
+ if(IsValid())
+ {
+ uno::Reference< XIndexReplace > xRef;
+ if ( nIndex < GetDoc()->GetNumRuleTbl().Count() )
+ {
+ xRef = new SwXNumberingRules( *GetDoc()->GetNumRuleTbl()[ static_cast< sal_uInt16 >(nIndex) ] );
+ aRet.setValue(&xRef, ::getCppuType((uno::Reference<XIndexReplace>*)0));
+ }
+
+ if(!xRef.is())
+ throw IndexOutOfBoundsException();
+ }
+ else
+ throw uno::RuntimeException();
+ return aRet;
+}
+
+uno::Type SAL_CALL SwXNumberingRulesCollection::getElementType() throw(uno::RuntimeException)
+{
+ return ::getCppuType((uno::Reference<XIndexReplace>*)0);
+}
+
+sal_Bool SwXNumberingRulesCollection::hasElements(void) throw( uno::RuntimeException )
+{
+ SolarMutexGuard aGuard;
+ if(!IsValid())
+ throw uno::RuntimeException();
+ return GetDoc()->GetNumRuleTbl().Count() > 0;
+}
+
+OUString SwXFootnotes::getImplementationName(void) throw( RuntimeException )
+{
+ return C2U("SwXFootnotes");
+}
+
+sal_Bool SwXFootnotes::supportsService(const OUString& rServiceName) throw( RuntimeException )
+{
+ return C2U("com.sun.star.text.Footnotes") == rServiceName;
+}
+
+Sequence< OUString > SwXFootnotes::getSupportedServiceNames(void) throw( RuntimeException )
+{
+ Sequence< OUString > aRet(1);
+ OUString* pArray = aRet.getArray();
+ pArray[0] = C2U("com.sun.star.text.Footnotes");
+ return aRet;
+}
+
+SwXFootnotes::SwXFootnotes(sal_Bool bEnd, SwDoc* _pDoc)
+ : SwUnoCollection(_pDoc)
+ , m_bEndnote(bEnd)
+{
+}
+
+SwXFootnotes::~SwXFootnotes()
+{
+}
+
+sal_Int32 SwXFootnotes::getCount(void) throw( uno::RuntimeException )
+{
+ SolarMutexGuard aGuard;
+ if(!IsValid())
+ throw uno::RuntimeException();
+ sal_Int32 nCount = 0;
+ sal_uInt16 n, nFtnCnt = GetDoc()->GetFtnIdxs().Count();
+ SwTxtFtn* pTxtFtn;
+ for( n = 0; n < nFtnCnt; ++n )
+ {
+ pTxtFtn = GetDoc()->GetFtnIdxs()[ n ];
+ const SwFmtFtn& rFtn = pTxtFtn->GetFtn();
+ if ( rFtn.IsEndNote() != m_bEndnote )
+ continue;
+ nCount++;
+ }
+ return nCount;
+}
+
+uno::Any SwXFootnotes::getByIndex(sal_Int32 nIndex)
+ throw( IndexOutOfBoundsException, WrappedTargetException, uno::RuntimeException )
+{
+ SolarMutexGuard aGuard;
+ uno::Any aRet;
+ if(IsValid())
+ {
+ sal_uInt16 n, nFtnCnt = GetDoc()->GetFtnIdxs().Count();
+ SwTxtFtn* pTxtFtn;
+ uno::Reference< XFootnote > xRef;
+ sal_Int32 nCount = 0;
+ for( n = 0; n < nFtnCnt; ++n )
+ {
+ pTxtFtn = GetDoc()->GetFtnIdxs()[ n ];
+ const SwFmtFtn& rFtn = pTxtFtn->GetFtn();
+ if ( rFtn.IsEndNote() != m_bEndnote )
+ continue;
+
+ if(nCount == nIndex)
+ {
+ xRef = SwXFootnote::CreateXFootnote(*GetDoc(), rFtn);
+ aRet <<= xRef;
+ break;
+ }
+ nCount++;
+ }
+ if(!xRef.is())
+ throw IndexOutOfBoundsException();
+ }
+ else
+ throw uno::RuntimeException();
+ return aRet;
+}
+
+uno::Type SAL_CALL SwXFootnotes::getElementType() throw(uno::RuntimeException)
+{
+ return ::getCppuType((uno::Reference<XFootnote>*)0);
+}
+
+sal_Bool SwXFootnotes::hasElements(void) throw( uno::RuntimeException )
+{
+ SolarMutexGuard aGuard;
+ if(!IsValid())
+ throw uno::RuntimeException();
+ return GetDoc()->GetFtnIdxs().Count() > 0;
+}
+
+Reference<XFootnote> SwXFootnotes::GetObject( SwDoc& rDoc, const SwFmtFtn& rFmt )
+{
+ return SwXFootnote::CreateXFootnote(rDoc, rFmt);
+}
+
+OUString SwXReferenceMarks::getImplementationName(void) throw( RuntimeException )
+{
+ return C2U("SwXReferenceMarks");
+}
+
+sal_Bool SwXReferenceMarks::supportsService(const OUString& rServiceName) throw( RuntimeException )
+{
+ return C2U("com.sun.star.text.ReferenceMarks") == rServiceName;
+}
+
+Sequence< OUString > SwXReferenceMarks::getSupportedServiceNames(void) throw( RuntimeException )
+{
+ Sequence< OUString > aRet(1);
+ OUString* pArray = aRet.getArray();
+ pArray[0] = C2U("com.sun.star.text.ReferenceMarks");
+ return aRet;
+}
+
+SwXReferenceMarks::SwXReferenceMarks(SwDoc* _pDoc) :
+ SwUnoCollection(_pDoc)
+{
+}
+
+SwXReferenceMarks::~SwXReferenceMarks()
+{
+}
+
+sal_Int32 SwXReferenceMarks::getCount(void) throw( uno::RuntimeException )
+{
+ SolarMutexGuard aGuard;
+ if(!IsValid())
+ throw uno::RuntimeException();
+ return GetDoc()->GetRefMarks();
+}
+
+uno::Any SwXReferenceMarks::getByIndex(sal_Int32 nIndex)
+ throw( IndexOutOfBoundsException, WrappedTargetException, uno::RuntimeException )
+{
+ SolarMutexGuard aGuard;
+ uno::Any aRet;
+ if(!IsValid())
+ throw uno::RuntimeException();
+ uno::Reference< XTextContent > xRef;
+ if(0 <= nIndex && nIndex < USHRT_MAX)
+ {
+ const SwFmtRefMark* pMark = GetDoc()->GetRefMark( (sal_uInt16) nIndex );
+ if(pMark)
+ {
+ xRef = SwXReferenceMarks::GetObject( GetDoc(), pMark );
+ aRet.setValue(&xRef, ::getCppuType((uno::Reference<XTextContent>*)0));
+ }
+ }
+ if(!xRef.is())
+ throw IndexOutOfBoundsException();
+ return aRet;
+}
+
+uno::Any SwXReferenceMarks::getByName(const OUString& rName)
+ throw( NoSuchElementException, WrappedTargetException, uno::RuntimeException )
+{
+ SolarMutexGuard aGuard;
+ uno::Any aRet;
+ if(IsValid())
+ {
+ const SwFmtRefMark* pMark = GetDoc()->GetRefMark(rName);
+ if(pMark)
+ {
+ uno::Reference< XTextContent > xRef = SwXReferenceMarks::GetObject( GetDoc(), pMark );
+ aRet.setValue(&xRef, ::getCppuType((uno::Reference<XTextContent>*)0));
+ }
+ else
+ throw NoSuchElementException();
+ }
+ else
+ throw uno::RuntimeException();
+ return aRet;
+}
+
+uno::Sequence< OUString > SwXReferenceMarks::getElementNames(void) throw( uno::RuntimeException )
+{
+ SolarMutexGuard aGuard;
+ uno::Sequence<OUString> aRet;
+ if(IsValid())
+ {
+ SvStringsDtor aStrings;
+ sal_uInt16 nCount = GetDoc()->GetRefMarks( &aStrings );
+ aRet.realloc(nCount);
+ OUString* pNames = aRet.getArray();
+ for(sal_uInt16 i = 0; i < nCount; i++)
+ pNames[i] = *aStrings.GetObject(i);
+ }
+ else
+ throw uno::RuntimeException();
+ return aRet;
+}
+
+sal_Bool SwXReferenceMarks::hasByName(const OUString& rName) throw( uno::RuntimeException )
+{
+ SolarMutexGuard aGuard;
+ if(!IsValid())
+ throw uno::RuntimeException();
+ return 0 != GetDoc()->GetRefMark( rName);
+}
+
+uno::Type SAL_CALL SwXReferenceMarks::getElementType() throw(uno::RuntimeException)
+{
+ return ::getCppuType((uno::Reference<XTextContent>*)0);
+}
+
+sal_Bool SwXReferenceMarks::hasElements(void) throw( uno::RuntimeException )
+{
+ SolarMutexGuard aGuard;
+ if(!IsValid())
+ throw uno::RuntimeException();
+ return 0 != GetDoc()->GetRefMarks();
+}
+
+SwXReferenceMark* SwXReferenceMarks::GetObject( SwDoc* pDoc, const SwFmtRefMark* pMark )
+{
+ SolarMutexGuard aGuard;
+
+ return SwXReferenceMark::CreateXReferenceMark(*pDoc, *pMark);
+}
+
+
+void SwUnoCollection::Invalidate()
+{
+ bObjectValid = sal_False;
+ pDoc = 0;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/unocore/unocore.src b/sw/source/core/unocore/unocore.src
new file mode 100644
index 000000000000..4bab91813490
--- /dev/null
+++ b/sw/source/core/unocore/unocore.src
@@ -0,0 +1,64 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#include <unocore.hrc>
+
+String STR_CHART2_ROW_LABEL_TEXT
+{
+ Text [ en-US ] = "Row %ROWNUMBER" ;
+};
+
+String STR_CHART2_COL_LABEL_TEXT
+{
+ Text [ en-US ] = "Column %COLUMNLETTER" ;
+};
+
+String STR_STYLE_FAMILY_CHARACTER
+{
+ Text [ en-US ] = "Character" ;
+};
+
+String STR_STYLE_FAMILY_PARAGRAPH
+{
+ Text [ en-US ] = "Paragraph" ;
+};
+
+String STR_STYLE_FAMILY_FRAME
+{
+ Text [ en-US ] = "Frame" ;
+};
+
+String STR_STYLE_FAMILY_PAGE
+{
+ Text [ en-US ] = "Pages" ;
+};
+
+String STR_STYLE_FAMILY_NUMBERING
+{
+ Text [ en-US ] = "Numbering" ;
+};
+
diff --git a/sw/source/core/unocore/unocrsrhelper.cxx b/sw/source/core/unocore/unocrsrhelper.cxx
new file mode 100644
index 000000000000..c542798bdc8e
--- /dev/null
+++ b/sw/source/core/unocore/unocrsrhelper.cxx
@@ -0,0 +1,1079 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+#include <svx/svxids.hrc>
+#include <map>
+#include <com/sun/star/text/XTextSection.hpp>
+#include <cmdid.h>
+#include <unocrsrhelper.hxx>
+#include <unofootnote.hxx>
+#include <unorefmark.hxx>
+#include <unostyle.hxx>
+#include <unoidx.hxx>
+#include <unofield.hxx>
+#include <unotbl.hxx>
+#include <unosett.hxx>
+#include <unoframe.hxx>
+#include <unocrsr.hxx>
+#include <doc.hxx>
+#include <IDocumentUndoRedo.hxx>
+#include <IDocumentRedlineAccess.hxx>
+#include <fmtftn.hxx>
+#include <fmtpdsc.hxx>
+#include <charfmt.hxx>
+#include <pagedesc.hxx>
+#include <docstyle.hxx>
+#include <ndtxt.hxx>
+#include <txtrfmrk.hxx>
+#include <fmtfld.hxx>
+#include <docsh.hxx>
+#include <section.hxx>
+#include <shellio.hxx>
+#include <edimp.hxx>
+#include <swundo.hxx>
+#include <cntfrm.hxx>
+#include <pagefrm.hxx>
+#include <svl/eitem.hxx>
+#include <tools/urlobj.hxx>
+#include <docary.hxx>
+#include <swtable.hxx>
+#include <tox.hxx>
+#include <doctxm.hxx>
+#include <fchrfmt.hxx>
+#include <editeng/flstitem.hxx>
+#include <vcl/metric.hxx>
+#include <svtools/ctrltool.hxx>
+#define _SVSTDARR_USHORTS
+#define _SVSTDARR_USHORTSSORT
+#include <svl/svstdarr.hxx>
+#include <sfx2/docfilt.hxx>
+#include <sfx2/docfile.hxx>
+#include <sfx2/fcontnr.hxx>
+#include <svl/stritem.hxx>
+#include <com/sun/star/beans/PropertyState.hpp>
+#include <SwStyleNameMapper.hxx>
+#include <redline.hxx>
+#include <numrule.hxx>
+#include <comphelper/storagehelper.hxx>
+#include <comphelper/mediadescriptor.hxx>
+#include <comphelper/sequenceashashmap.hxx>
+#include <com/sun/star/embed/ElementModes.hpp>
+#include <com/sun/star/embed/XStorage.hpp>
+#include <SwNodeNum.hxx>
+#include <fmtmeta.hxx>
+
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::beans;
+using namespace ::com::sun::star::text;
+using namespace ::com::sun::star::table;
+using namespace ::com::sun::star::container;
+using namespace ::com::sun::star::lang;
+using ::rtl::OUString;
+
+namespace SwUnoCursorHelper
+{
+
+uno::Reference<text::XTextContent>
+GetNestedTextContent(SwTxtNode & rTextNode, xub_StrLen const nIndex,
+ bool const bParent)
+{
+ // these should be unambiguous because of the dummy character
+ SwTxtNode::GetTxtAttrMode const eMode( (bParent)
+ ? SwTxtNode::PARENT : SwTxtNode::EXPAND );
+ SwTxtAttr *const pMetaTxtAttr =
+ rTextNode.GetTxtAttrAt(nIndex, RES_TXTATR_META, eMode);
+ SwTxtAttr *const pMetaFieldTxtAttr =
+ rTextNode.GetTxtAttrAt(nIndex, RES_TXTATR_METAFIELD, eMode);
+ // which is innermost?
+ SwTxtAttr *const pTxtAttr = (pMetaTxtAttr)
+ ? ((pMetaFieldTxtAttr)
+ ? ((*pMetaFieldTxtAttr->GetStart() >
+ *pMetaTxtAttr->GetStart())
+ ? pMetaFieldTxtAttr : pMetaTxtAttr)
+ : pMetaTxtAttr)
+ : pMetaFieldTxtAttr;
+ uno::Reference<XTextContent> xRet;
+ if (pTxtAttr)
+ {
+ ::sw::Meta *const pMeta(
+ static_cast<SwFmtMeta &>(pTxtAttr->GetAttr()).GetMeta());
+ OSL_ASSERT(pMeta);
+ xRet.set(pMeta->MakeUnoObject(), uno::UNO_QUERY);
+ }
+ return xRet;
+}
+
+/* --------------------------------------------------
+ * Read the special properties of the cursor
+ * --------------------------------------------------*/
+sal_Bool getCrsrPropertyValue(const SfxItemPropertySimpleEntry& rEntry
+ , SwPaM& rPam
+ , Any *pAny
+ , PropertyState& eState
+ , const SwTxtNode* pNode )
+{
+ PropertyState eNewState = PropertyState_DIRECT_VALUE;
+// PropertyState_DEFAULT_VALUE
+// PropertyState_AMBIGUOUS_VALUE
+ sal_Bool bDone = sal_True;
+ switch(rEntry.nWID)
+ {
+ case FN_UNO_PARA_CONT_PREV_SUBTREE:
+ if (pAny)
+ {
+ const SwTxtNode * pTmpNode = pNode;
+
+ if (!pTmpNode)
+ pTmpNode = rPam.GetNode()->GetTxtNode();
+
+ bool bRet = false;
+
+ if ( pTmpNode &&
+ pTmpNode->GetNum() &&
+ pTmpNode->GetNum()->IsContinueingPreviousSubTree() )
+ {
+ bRet = true;
+ }
+
+ *pAny <<= bRet;
+ }
+ break;
+ case FN_UNO_PARA_NUM_STRING:
+ if (pAny)
+ {
+ const SwTxtNode * pTmpNode = pNode;
+
+ if (!pTmpNode)
+ pTmpNode = rPam.GetNode()->GetTxtNode();
+
+ String sRet;
+ if ( pTmpNode && pTmpNode->GetNum() )
+ {
+ sRet = pTmpNode->GetNumString();
+ }
+
+ *pAny <<= OUString(sRet);
+ }
+ break;
+ case RES_PARATR_OUTLINELEVEL:
+ if (pAny)
+ {
+ const SwTxtNode * pTmpNode = pNode;
+
+ if (!pTmpNode)
+ pTmpNode = rPam.GetNode()->GetTxtNode();
+
+ sal_Int16 nRet = -1;
+ if ( pTmpNode )
+ nRet = sal::static_int_cast< sal_Int16 >( pTmpNode->GetAttrOutlineLevel() );
+
+ *pAny <<= nRet;
+ }
+ break;
+ case FN_UNO_PARA_CONDITIONAL_STYLE_NAME:
+ case FN_UNO_PARA_STYLE :
+ {
+ SwFmtColl* pFmt = 0;
+ if(pNode)
+ pFmt = FN_UNO_PARA_CONDITIONAL_STYLE_NAME == rEntry.nWID
+ ? pNode->GetFmtColl() : &pNode->GetAnyFmtColl();
+ else
+ {
+ pFmt = SwUnoCursorHelper::GetCurTxtFmtColl(rPam,
+ FN_UNO_PARA_CONDITIONAL_STYLE_NAME == rEntry.nWID);
+ }
+ if(pFmt)
+ {
+ if( pAny )
+ {
+ String sVal;
+ SwStyleNameMapper::FillProgName(pFmt->GetName(), sVal, nsSwGetPoolIdFromName::GET_POOLID_TXTCOLL, sal_True );
+ *pAny <<= OUString(sVal);
+ }
+ }
+ else
+ eNewState = PropertyState_AMBIGUOUS_VALUE;
+ }
+ break;
+ case FN_UNO_PAGE_STYLE :
+ {
+ String sVal;
+ GetCurPageStyle(rPam, sVal);
+ if( pAny )
+ *pAny <<= OUString(sVal);
+ if(!sVal.Len())
+ eNewState = PropertyState_AMBIGUOUS_VALUE;
+ }
+ break;
+ case FN_UNO_NUM_START_VALUE :
+ if( pAny )
+ {
+ sal_Int16 nValue = IsNodeNumStart(rPam, eNewState);
+ *pAny <<= nValue;
+ }
+ break;
+ case FN_UNO_NUM_LEVEL :
+ case FN_UNO_IS_NUMBER :
+ // #i91601#
+ case FN_UNO_LIST_ID:
+ case FN_NUMBER_NEWSTART:
+ {
+ // a multi selection is not considered
+ const SwTxtNode* pTxtNd = rPam.GetNode()->GetTxtNode();
+ if ( pTxtNd && pTxtNd->IsInList() )
+ {
+ if( pAny )
+ {
+ if(rEntry.nWID == FN_UNO_NUM_LEVEL)
+ *pAny <<= (sal_Int16)(pTxtNd->GetActualListLevel());
+ else if(rEntry.nWID == FN_UNO_IS_NUMBER)
+ {
+ sal_Bool bIsNumber = pTxtNd->IsCountedInList();
+ pAny->setValue(&bIsNumber, ::getBooleanCppuType());
+ }
+ // #i91601#
+ else if ( rEntry.nWID == FN_UNO_LIST_ID )
+ {
+ const String sListId = pTxtNd->GetListId();
+ *pAny <<= OUString(sListId);
+ }
+ else /*if(rEntry.nWID == UNO_NAME_PARA_IS_NUMBERING_RESTART)*/
+ {
+ sal_Bool bIsRestart = pTxtNd->IsListRestart();
+ pAny->setValue(&bIsRestart, ::getBooleanCppuType());
+ }
+ }
+ }
+ else
+ {
+ eNewState = PropertyState_DEFAULT_VALUE;
+
+ if( pAny )
+ {
+ // #i30838# set default values for default properties
+ if(rEntry.nWID == FN_UNO_NUM_LEVEL)
+ *pAny <<= static_cast<sal_Int16>( 0 );
+ else if(rEntry.nWID == FN_UNO_IS_NUMBER)
+ *pAny <<= false;
+ // #i91601#
+ else if ( rEntry.nWID == FN_UNO_LIST_ID )
+ {
+ *pAny <<= OUString();
+ }
+ // <--
+ else /*if(rEntry.nWID == UNO_NAME_PARA_IS_NUMBERING_RESTART)*/
+ *pAny <<= false;
+ }
+ }
+ //PROPERTY_MAYBEVOID!
+ }
+ break;
+ case FN_UNO_NUM_RULES :
+ if( pAny )
+ getNumberingProperty(rPam, eNewState, pAny);
+ else
+ {
+ if( !rPam.GetDoc()->GetCurrNumRule( *rPam.GetPoint() ) )
+ eNewState = PropertyState_DEFAULT_VALUE;
+ }
+ break;
+ case FN_UNO_DOCUMENT_INDEX_MARK:
+ {
+ ::std::vector<SwTxtAttr *> const marks(
+ rPam.GetNode()->GetTxtNode()->GetTxtAttrsAt(
+ rPam.GetPoint()->nContent.GetIndex(), RES_TXTATR_TOXMARK));
+ if (marks.size())
+ {
+ if( pAny )
+ { // hmm... can only return 1 here
+ SwTOXMark & rMark =
+ static_cast<SwTOXMark &>((*marks.begin())->GetAttr());
+ const uno::Reference< text::XDocumentIndexMark > xRef =
+ SwXDocumentIndexMark::CreateXDocumentIndexMark(
+ *rPam.GetDoc(),
+ *const_cast<SwTOXType*>(rMark.GetTOXType()), rMark);
+ (*pAny) <<= xRef;
+ }
+ }
+ else
+ //also here - indistinguishable
+ eNewState = PropertyState_DEFAULT_VALUE;
+ }
+ break;
+ case FN_UNO_DOCUMENT_INDEX:
+ {
+ const SwTOXBase* pBase = rPam.GetDoc()->GetCurTOX(
+ *rPam.Start() );
+ if( pBase )
+ {
+ if( pAny )
+ {
+ const uno::Reference< text::XDocumentIndex > xRef =
+ SwXDocumentIndex::CreateXDocumentIndex(*rPam.GetDoc(),
+ *static_cast<SwTOXBaseSection const*>(pBase));
+ (*pAny) <<= xRef;
+ }
+ }
+ else
+ eNewState = PropertyState_DEFAULT_VALUE;
+ }
+ break;
+ case FN_UNO_TEXT_FIELD:
+ {
+ const SwPosition *pPos = rPam.Start();
+ const SwTxtNode *pTxtNd =
+ rPam.GetDoc()->GetNodes()[pPos->nNode.GetIndex()]->GetTxtNode();
+ SwTxtAttr *const pTxtAttr = (pTxtNd)
+ ? pTxtNd->GetTxtAttrForCharAt(
+ pPos->nContent.GetIndex(), RES_TXTATR_FIELD)
+ : 0;
+ if(pTxtAttr)
+ {
+ if( pAny )
+ {
+ SwXTextField* pField = SwXTextField::CreateSwXTextField(*rPam.GetDoc(),
+ pTxtAttr->GetFld());
+ *pAny <<= uno::Reference< XTextField >( pField );
+ }
+ }
+ else
+ eNewState = PropertyState_DEFAULT_VALUE;
+ }
+ break;
+ case FN_UNO_TEXT_TABLE:
+ case FN_UNO_CELL:
+ {
+ SwStartNode* pSttNode = rPam.GetNode()->StartOfSectionNode();
+ SwStartNodeType eType = pSttNode->GetStartNodeType();
+ if(SwTableBoxStartNode == eType)
+ {
+ if( pAny )
+ {
+ const SwTableNode* pTblNode = pSttNode->FindTableNode();
+ SwFrmFmt* pTableFmt = (SwFrmFmt*)pTblNode->GetTable().GetFrmFmt();
+ //SwTable& rTable = ((SwTableNode*)pSttNode)->GetTable();
+ if(FN_UNO_TEXT_TABLE == rEntry.nWID)
+ {
+ uno::Reference< XTextTable > xTable = SwXTextTables::GetObject(*pTableFmt);
+ pAny->setValue(&xTable, ::getCppuType((uno::Reference<XTextTable>*)0));
+ }
+ else
+ {
+ SwTableBox* pBox = pSttNode->GetTblBox();
+ uno::Reference< XCell > xCell = SwXCell::CreateXCell(pTableFmt, pBox);
+ pAny->setValue(&xCell, ::getCppuType((uno::Reference<XCell>*)0));
+ }
+ }
+ }
+ else
+ eNewState = PropertyState_DEFAULT_VALUE;
+ }
+ break;
+ case FN_UNO_TEXT_FRAME:
+ {
+ SwStartNode* pSttNode = rPam.GetNode()->StartOfSectionNode();
+ SwStartNodeType eType = pSttNode->GetStartNodeType();
+
+ SwFrmFmt* pFmt;
+ if(eType == SwFlyStartNode && 0 != (pFmt = pSttNode->GetFlyFmt()))
+ {
+ if( pAny )
+ {
+ uno::Reference< XTextFrame > xFrm = (SwXTextFrame*) SwXFrames::GetObject(*pFmt, FLYCNTTYPE_FRM);
+ pAny->setValue(&xFrm, ::getCppuType((uno::Reference<XTextFrame>*)0));
+ }
+ }
+ else
+ eNewState = PropertyState_DEFAULT_VALUE;
+ }
+ break;
+ case FN_UNO_TEXT_SECTION:
+ {
+ SwSection* pSect = rPam.GetDoc()->GetCurrSection(*rPam.GetPoint());
+ if(pSect)
+ {
+ if( pAny )
+ {
+ uno::Reference< XTextSection > xSect = SwXTextSections::GetObject( *pSect->GetFmt() );
+ pAny->setValue(&xSect, ::getCppuType((uno::Reference<XTextSection>*)0) );
+ }
+ }
+ else
+ eNewState = PropertyState_DEFAULT_VALUE;
+ }
+ break;
+ case FN_UNO_ENDNOTE:
+ case FN_UNO_FOOTNOTE:
+ {
+ SwTxtAttr *const pTxtAttr =
+ rPam.GetNode()->GetTxtNode()->GetTxtAttrForCharAt(
+ rPam.GetPoint()->nContent.GetIndex(), RES_TXTATR_FTN);
+ if(pTxtAttr)
+ {
+ const SwFmtFtn& rFtn = pTxtAttr->GetFtn();
+ if(rFtn.IsEndNote() == (FN_UNO_ENDNOTE == rEntry.nWID))
+ {
+ if( pAny )
+ {
+ const uno::Reference< text::XFootnote > xFootnote =
+ SwXFootnote::CreateXFootnote(*rPam.GetDoc(), rFtn);
+ *pAny <<= xFootnote;
+ }
+ }
+ else
+ eNewState = PropertyState_DEFAULT_VALUE;
+ }
+ else
+ eNewState = PropertyState_DEFAULT_VALUE;
+ }
+ break;
+ case FN_UNO_REFERENCE_MARK:
+ {
+ ::std::vector<SwTxtAttr *> const marks(
+ rPam.GetNode()->GetTxtNode()->GetTxtAttrsAt(
+ rPam.GetPoint()->nContent.GetIndex(), RES_TXTATR_REFMARK));
+ if (marks.size())
+ {
+ if( pAny )
+ { // hmm... can only return 1 here
+ const SwFmtRefMark& rRef = (*marks.begin())->GetRefMark();
+ uno::Reference< XTextContent > xRef = SwXReferenceMarks::GetObject( rPam.GetDoc(), &rRef );
+ pAny->setValue(&xRef, ::getCppuType((uno::Reference<XTextContent>*)0));
+ }
+ }
+ else
+ eNewState = PropertyState_DEFAULT_VALUE;
+ }
+ break;
+ case FN_UNO_NESTED_TEXT_CONTENT:
+ {
+ uno::Reference<XTextContent> const xRet(
+ GetNestedTextContent(*rPam.GetNode()->GetTxtNode(),
+ rPam.GetPoint()->nContent.GetIndex(), false));
+ if (xRet.is())
+ {
+ if (pAny)
+ {
+ (*pAny) <<= xRet;
+ }
+ }
+ else
+ {
+ eNewState = PropertyState_DEFAULT_VALUE;
+ }
+ }
+ break;
+ case FN_UNO_CHARFMT_SEQUENCE:
+ {
+
+ SwTxtNode* pTxtNode;
+ if((pTxtNode = (SwTxtNode*)rPam.GetNode( sal_True )) == rPam.GetNode(sal_False) &&
+ pTxtNode->GetpSwpHints())
+ {
+ sal_uInt16 nPaMStart = rPam.GetPoint()->nContent.GetIndex();
+ sal_uInt16 nPaMEnd = rPam.GetMark() ? rPam.GetMark()->nContent.GetIndex() : nPaMStart;
+ if(nPaMStart > nPaMEnd)
+ {
+ sal_uInt16 nTmp = nPaMStart;
+ nPaMStart = nPaMEnd;
+ nPaMEnd = nTmp;
+ }
+ Sequence< ::rtl::OUString> aCharStyles;
+ SwpHints* pHints = pTxtNode->GetpSwpHints();
+ for(sal_uInt16 nAttr = 0; nAttr < pHints->GetStartCount(); nAttr++ )
+ {
+ SwTxtAttr* pAttr = pHints->GetStart( nAttr );
+ if(pAttr->Which() != RES_TXTATR_CHARFMT)
+ continue;
+ sal_uInt16 nAttrStart = *pAttr->GetStart();
+ sal_uInt16 nAttrEnd = *pAttr->GetEnd();
+ //check if the attribute touches the selection
+ if( ( nAttrEnd > nPaMStart && nAttrStart < nPaMEnd ) ||
+ ( !nAttrStart && !nAttrEnd && !nPaMStart && !nPaMEnd ) )
+ {
+ //check for overlapping
+ if(nAttrStart > nPaMStart ||
+ nAttrEnd < nPaMEnd)
+ {
+ aCharStyles.realloc(0);
+ eNewState = PropertyState_AMBIGUOUS_VALUE;
+ break;
+ }
+ else
+ {
+ //now the attribute should start before or at the selection
+ //and it should end at the end of the selection or behind
+ DBG_ASSERT(nAttrStart <= nPaMStart && nAttrEnd >=nPaMEnd,
+ "attribute overlaps or is outside");
+ //now the name of the style has to be added to the sequence
+ aCharStyles.realloc(aCharStyles.getLength() + 1);
+ DBG_ASSERT(pAttr->GetCharFmt().GetCharFmt(), "no character format set");
+ aCharStyles.getArray()[aCharStyles.getLength() - 1] =
+ SwStyleNameMapper::GetProgName(
+ pAttr->GetCharFmt().GetCharFmt()->GetName(), nsSwGetPoolIdFromName::GET_POOLID_CHRFMT);
+ }
+ }
+
+ }
+ eNewState =
+ aCharStyles.getLength() ?
+ PropertyState_DIRECT_VALUE : PropertyState_DEFAULT_VALUE;;
+ if(pAny)
+ (*pAny) <<= aCharStyles;
+ }
+ else
+ eNewState = PropertyState_DEFAULT_VALUE;
+ }
+ break;
+ case RES_TXTATR_CHARFMT:
+ // no break here!
+ default: bDone = sal_False;
+ }
+ if( bDone )
+ eState = eNewState;
+ return bDone;
+};
+
+sal_Int16 IsNodeNumStart(SwPaM& rPam, PropertyState& eState)
+{
+ const SwTxtNode* pTxtNd = rPam.GetNode()->GetTxtNode();
+ // correction: check, if restart value is set at the text node and use
+ // new method <SwTxtNode::GetAttrListRestartValue()> to retrieve the value
+ if ( pTxtNd && pTxtNd->GetNumRule() && pTxtNd->IsListRestart() &&
+ pTxtNd->HasAttrListRestartValue() )
+ {
+ eState = PropertyState_DIRECT_VALUE;
+ sal_Int16 nTmp = sal::static_int_cast< sal_Int16 >(pTxtNd->GetAttrListRestartValue());
+ return nTmp;
+ }
+ eState = PropertyState_DEFAULT_VALUE;
+ return -1;
+}
+
+void setNumberingProperty(const Any& rValue, SwPaM& rPam)
+{
+ uno::Reference<XIndexReplace> xIndexReplace;
+ if(rValue >>= xIndexReplace)
+ {
+ SwXNumberingRules* pSwNum = 0;
+
+ uno::Reference<XUnoTunnel> xNumTunnel(xIndexReplace, UNO_QUERY);
+ if(xNumTunnel.is())
+ {
+ pSwNum = reinterpret_cast< SwXNumberingRules * >(
+ sal::static_int_cast< sal_IntPtr >( xNumTunnel->getSomething( SwXNumberingRules::getUnoTunnelId() )));
+ }
+
+ if(pSwNum)
+ {
+ SwDoc* pDoc = rPam.GetDoc();
+ if(pSwNum->GetNumRule())
+ {
+ SwNumRule aRule(*pSwNum->GetNumRule());
+ const String* pNewCharStyles = pSwNum->GetNewCharStyleNames();
+ const String* pBulletFontNames = pSwNum->GetBulletFontNames();
+ for(sal_uInt16 i = 0; i < MAXLEVEL; i++)
+ {
+ SwNumFmt aFmt(aRule.Get( i ));
+ if( pNewCharStyles[i].Len() &&
+ pNewCharStyles[i] != SwXNumberingRules::GetInvalidStyle() &&
+ (!aFmt.GetCharFmt() || pNewCharStyles[i] != aFmt.GetCharFmt()->GetName()))
+ {
+ if(!pNewCharStyles[i].Len())
+ aFmt.SetCharFmt(0);
+ else
+ {
+
+ // get CharStyle and set the rule
+ sal_uInt16 nChCount = pDoc->GetCharFmts()->Count();
+ SwCharFmt* pCharFmt = 0;
+ for(sal_uInt16 nCharFmt = 0; nCharFmt < nChCount; nCharFmt++)
+ {
+ SwCharFmt& rChFmt = *((*(pDoc->GetCharFmts()))[nCharFmt]);;
+ if(rChFmt.GetName() == pNewCharStyles[i])
+ {
+ pCharFmt = &rChFmt;
+ break;
+ }
+ }
+
+ if(!pCharFmt)
+ {
+ SfxStyleSheetBasePool* pPool = pDoc->GetDocShell()->GetStyleSheetPool();
+ SfxStyleSheetBase* pBase;
+ pBase = pPool->Find(pNewCharStyles[i], SFX_STYLE_FAMILY_CHAR);
+ // shall it really be created?
+ if(!pBase)
+ pBase = &pPool->Make(pNewCharStyles[i], SFX_STYLE_FAMILY_PAGE);
+ pCharFmt = ((SwDocStyleSheet*)pBase)->GetCharFmt();
+ }
+ if(pCharFmt)
+ aFmt.SetCharFmt(pCharFmt);
+ }
+ }
+ //Now again for fonts
+ if(
+ pBulletFontNames[i] != SwXNumberingRules::GetInvalidStyle() &&
+ (
+ (pBulletFontNames[i].Len() && !aFmt.GetBulletFont()) ||
+ (pBulletFontNames[i].Len() &&
+ aFmt.GetBulletFont()->GetName() != pBulletFontNames[i])
+ )
+ )
+ {
+ const SvxFontListItem* pFontListItem =
+ (const SvxFontListItem* )pDoc->GetDocShell()
+ ->GetItem( SID_ATTR_CHAR_FONTLIST );
+ const FontList* pList = pFontListItem->GetFontList();
+
+ FontInfo aInfo = pList->Get(
+ pBulletFontNames[i],WEIGHT_NORMAL, ITALIC_NONE);
+ Font aFont(aInfo);
+ aFmt.SetBulletFont(&aFont);
+ }
+ aRule.Set( i, aFmt );
+ }
+ UnoActionContext aAction(pDoc);
+
+ if( rPam.GetNext() != &rPam ) // Multiple selection?
+ {
+ pDoc->GetIDocumentUndoRedo().StartUndo( UNDO_START, NULL );
+ SwPamRanges aRangeArr( rPam );
+ SwPaM aPam( *rPam.GetPoint() );
+ for( sal_uInt16 n = 0; n < aRangeArr.Count(); ++n )
+ {
+ // no start of a new list
+ pDoc->SetNumRule( aRangeArr.SetPam( n, aPam ), aRule, false );
+ }
+ pDoc->GetIDocumentUndoRedo().EndUndo( UNDO_END, NULL );
+ }
+ else
+ {
+ // no start of a new list
+ pDoc->SetNumRule( rPam, aRule, false );
+ }
+
+
+ }
+ else if(pSwNum->GetCreatedNumRuleName().Len())
+ {
+ UnoActionContext aAction(pDoc);
+ SwNumRule* pRule = pDoc->FindNumRulePtr( pSwNum->GetCreatedNumRuleName() );
+ if(!pRule)
+ throw RuntimeException();
+ // no start of a new list
+ pDoc->SetNumRule( rPam, *pRule, false );
+ }
+ // #i103817#
+ // outline numbering
+ else
+ {
+ UnoActionContext aAction(pDoc);
+ SwNumRule* pRule = pDoc->GetOutlineNumRule();
+ if(!pRule)
+ throw RuntimeException();
+ pDoc->SetNumRule( rPam, *pRule, false );
+ }
+ }
+ }
+ else if(rValue.getValueType() == ::getVoidCppuType())
+ {
+ rPam.GetDoc()->DelNumRules(rPam);
+ }
+}
+
+void getNumberingProperty(SwPaM& rPam, PropertyState& eState, Any * pAny )
+{
+ const SwNumRule* pNumRule = rPam.GetDoc()->GetCurrNumRule( *rPam.GetPoint() );
+ if(pNumRule)
+ {
+ uno::Reference< XIndexReplace > xNum = new SwXNumberingRules(*pNumRule);
+ if ( pAny )
+ pAny->setValue(&xNum, ::getCppuType((const uno::Reference<XIndexReplace>*)0));
+ eState = PropertyState_DIRECT_VALUE;
+ }
+ else
+ eState = PropertyState_DEFAULT_VALUE;
+}
+
+void GetCurPageStyle(SwPaM& rPaM, String &rString)
+{
+ const SwPageFrm* pPage = rPaM.GetCntntNode()->getLayoutFrm(rPaM.GetDoc()->GetCurrentLayout())->FindPageFrm();
+ if(pPage)
+ SwStyleNameMapper::FillProgName( pPage->GetPageDesc()->GetName(), rString, nsSwGetPoolIdFromName::GET_POOLID_PAGEDESC, sal_True );
+}
+
+/* --------------------------------------------------
+ * reset special properties of the cursor
+ * --------------------------------------------------*/
+void resetCrsrPropertyValue(const SfxItemPropertySimpleEntry& rEntry, SwPaM& rPam)
+{
+ SwDoc* pDoc = rPam.GetDoc();
+ switch(rEntry.nWID)
+ {
+ case FN_UNO_PARA_STYLE :
+// lcl_SetTxtFmtColl(aValue, pUnoCrsr);
+ break;
+ case FN_UNO_PAGE_STYLE :
+ break;
+ case FN_UNO_NUM_START_VALUE :
+ {
+ UnoActionContext aAction(pDoc);
+
+ if( rPam.GetNext() != &rPam ) // Multiple selection?
+ {
+ pDoc->GetIDocumentUndoRedo().StartUndo( UNDO_START, NULL );
+ SwPamRanges aRangeArr( rPam );
+ SwPaM aPam( *rPam.GetPoint() );
+ for( sal_uInt16 n = 0; n < aRangeArr.Count(); ++n )
+ pDoc->SetNodeNumStart( *aRangeArr.SetPam( n, aPam ).GetPoint(), 1 );
+ pDoc->GetIDocumentUndoRedo().EndUndo( UNDO_END, NULL );
+ }
+ else
+ pDoc->SetNodeNumStart( *rPam.GetPoint(), 0 );
+ }
+
+ break;
+ case FN_UNO_NUM_LEVEL :
+ break;
+ case FN_UNO_NUM_RULES:
+// lcl_setNumberingProperty(aValue, pUnoCrsr);
+ break;
+ case FN_UNO_CHARFMT_SEQUENCE:
+ {
+ SvUShortsSort aWhichIds;
+ aWhichIds.Insert(RES_TXTATR_CHARFMT);
+ pDoc->ResetAttrs(rPam, sal_True, &aWhichIds);
+ }
+ break;
+ }
+}
+
+void InsertFile(SwUnoCrsr* pUnoCrsr,
+ const String& rURL,
+ const uno::Sequence< beans::PropertyValue >& rOptions
+ ) throw( lang::IllegalArgumentException, io::IOException, uno::RuntimeException )
+{
+ SfxMedium* pMed = 0;
+ SwDoc* pDoc = pUnoCrsr->GetDoc();
+ SwDocShell* pDocSh = pDoc->GetDocShell();
+ comphelper::MediaDescriptor aMediaDescriptor( rOptions );
+ ::rtl::OUString sFileName = rURL;
+ ::rtl::OUString sFilterName, sFilterOptions, sPassword, sBaseURL;
+ uno::Reference < io::XStream > xStream;
+ uno::Reference < io::XInputStream > xInputStream;
+
+ if( !sFileName.getLength() )
+ aMediaDescriptor[comphelper::MediaDescriptor::PROP_URL()] >>= sFileName;
+ if( !sFileName.getLength() )
+ aMediaDescriptor[comphelper::MediaDescriptor::PROP_FILENAME()] >>= sFileName;
+ aMediaDescriptor[comphelper::MediaDescriptor::PROP_INPUTSTREAM()] >>= xInputStream;
+ aMediaDescriptor[comphelper::MediaDescriptor::PROP_STREAM()] >>= xStream;
+ aMediaDescriptor[comphelper::MediaDescriptor::PROP_INPUTSTREAM()] >>= xInputStream;
+ aMediaDescriptor[comphelper::MediaDescriptor::PROP_FILTERNAME()] >>= sFilterName;
+ aMediaDescriptor[comphelper::MediaDescriptor::PROP_FILTEROPTIONS()] >>= sFilterOptions;
+ aMediaDescriptor[comphelper::MediaDescriptor::PROP_PASSWORD()] >>= sPassword;
+ aMediaDescriptor[comphelper::MediaDescriptor::PROP_DOCUMENTBASEURL() ] >>= sBaseURL;
+ if ( !xInputStream.is() && xStream.is() )
+ xInputStream = xStream->getInputStream();
+
+ if(!pDocSh || (!sFileName.getLength() && !xInputStream.is()))
+ return;
+
+ SfxObjectFactory& rFact = pDocSh->GetFactory();
+ const SfxFilter* pFilter = rFact.GetFilterContainer()->GetFilter4FilterName( sFilterName );
+ uno::Reference < embed::XStorage > xReadStorage;
+ if( xInputStream.is() )
+ {
+ uno::Sequence< uno::Any > aArgs( 2 );
+ aArgs[0] <<= xInputStream;
+ aArgs[1] <<= embed::ElementModes::READ;
+ try
+ {
+ xReadStorage = uno::Reference< embed::XStorage >(
+ ::comphelper::OStorageHelper::GetStorageFactory()->createInstanceWithArguments( aArgs ),
+ uno::UNO_QUERY );
+ }
+ catch( const io::IOException& rEx)
+ {
+ (void)rEx;
+ }
+ }
+ if ( !pFilter )
+ {
+ if( xInputStream.is() && !xReadStorage.is())
+ {
+ pMed = new SfxMedium;
+ pMed->setStreamToLoadFrom(xInputStream, sal_True );
+ }
+ else
+ pMed = xReadStorage.is() ?
+ new SfxMedium(xReadStorage, sBaseURL, 0 ) :
+ new SfxMedium(sFileName, STREAM_READ, sal_True, 0, 0 );
+ if( sBaseURL.getLength() )
+ pMed->GetItemSet()->Put( SfxStringItem( SID_DOC_BASEURL, sBaseURL ) );
+
+ SfxFilterMatcher aMatcher( rFact.GetFilterContainer()->GetName() );
+ ErrCode nErr = aMatcher.GuessFilter( *pMed, &pFilter, sal_False );
+ if ( nErr || !pFilter)
+ DELETEZ(pMed);
+ else
+ pMed->SetFilter( pFilter );
+ }
+ else
+ {
+ if(!pMed)
+ {
+ if( xInputStream.is() && !xReadStorage.is())
+ {
+ pMed = new SfxMedium;
+ pMed->setStreamToLoadFrom(xInputStream, sal_True );
+ pMed->SetFilter( pFilter );
+ }
+ else
+ {
+ if( xReadStorage.is() )
+ {
+ pMed = new SfxMedium(xReadStorage, sBaseURL, 0 );
+ pMed->SetFilter( pFilter );
+ }
+ else
+ pMed = new SfxMedium(sFileName, STREAM_READ, sal_True, pFilter, 0);
+ }
+ }
+ if(sFilterOptions.getLength())
+ pMed->GetItemSet()->Put( SfxStringItem( SID_FILE_FILTEROPTIONS, sFilterOptions ) );
+ if( sBaseURL.getLength())
+ pMed->GetItemSet()->Put( SfxStringItem( SID_DOC_BASEURL, sBaseURL ) );
+ }
+
+ if( !pMed )
+ return;
+
+ // this sourcecode is not responsible for the lifetime of the shell, SfxObjectShellLock should not be used
+ SfxObjectShellRef aRef( pDocSh );
+
+ pDocSh->RegisterTransfer( *pMed );
+ pMed->DownLoad(); // if necessary: start the download
+ if( aRef.Is() && 1 < aRef->GetRefCount() ) // Ref still valid?
+ {
+ SwReader* pRdr;
+ SfxItemSet* pSet = pMed->GetItemSet();
+ pSet->Put(SfxBoolItem(FN_API_CALL, sal_True));
+ if(sPassword.getLength())
+ pSet->Put(SfxStringItem(SID_PASSWORD, sPassword));
+ Reader *pRead = pDocSh->StartConvertFrom( *pMed, &pRdr, 0, pUnoCrsr);
+ if( pRead )
+ {
+
+ UnoActionContext aContext(pDoc);
+
+ if(pUnoCrsr->HasMark())
+ pDoc->DeleteAndJoin(*pUnoCrsr);
+
+ SwNodeIndex aSave( pUnoCrsr->GetPoint()->nNode, -1 );
+ xub_StrLen nCntnt = pUnoCrsr->GetPoint()->nContent.GetIndex();
+
+ sal_uInt32 nErrno = pRdr->Read( *pRead ); // and paste the document
+
+ if(!nErrno)
+ {
+ aSave++;
+ pUnoCrsr->SetMark();
+ pUnoCrsr->GetMark()->nNode = aSave;
+
+ SwCntntNode* pCntNode = aSave.GetNode().GetCntntNode();
+ if( !pCntNode )
+ nCntnt = 0;
+ pUnoCrsr->GetMark()->nContent.Assign( pCntNode, nCntnt );
+ }
+
+ delete pRdr;
+
+
+ }
+ }
+ delete pMed;
+}
+
+// insert text and scan for CR characters in order to insert
+// paragraph breaks at those positions by calling SplitNode
+sal_Bool DocInsertStringSplitCR(
+ SwDoc &rDoc,
+ const SwPaM &rNewCursor, const String &rText,
+ const bool bForceExpandHints )
+{
+ sal_Bool bOK = sal_True;
+
+ const enum IDocumentContentOperations::InsertFlags nInsertFlags =
+ (bForceExpandHints)
+ ? static_cast<IDocumentContentOperations::InsertFlags>(
+ IDocumentContentOperations::INS_FORCEHINTEXPAND |
+ IDocumentContentOperations::INS_EMPTYEXPAND)
+ : IDocumentContentOperations::INS_EMPTYEXPAND;
+
+ // grouping done in InsertString is intended for typing, not API calls
+ ::sw::GroupUndoGuard const undoGuard(rDoc.GetIDocumentUndoRedo());
+ OUString aTxt;
+ xub_StrLen nStartIdx = 0;
+ SwTxtNode* const pTxtNd =
+ rNewCursor.GetPoint()->nNode.GetNode().GetTxtNode();
+ const xub_StrLen nMaxLength = ( pTxtNd )
+ ? STRING_LEN - pTxtNd->GetTxt().Len()
+ : STRING_LEN;
+ xub_StrLen nIdx = rText.Search( '\r', nStartIdx );
+ if( ( nIdx == STRING_NOTFOUND && nMaxLength < rText.Len() ) ||
+ ( nIdx != STRING_NOTFOUND && nMaxLength < nIdx ) )
+ {
+ nIdx = nMaxLength;
+ }
+ while (nIdx != STRING_NOTFOUND )
+ {
+ DBG_ASSERT( nIdx - nStartIdx >= 0, "index negative!" );
+ aTxt = rText.Copy( nStartIdx, nIdx - nStartIdx );
+ if (aTxt.getLength() &&
+ !rDoc.InsertString( rNewCursor, aTxt, nInsertFlags ))
+ {
+ OSL_FAIL( "Doc->Insert(Str) failed." );
+ bOK = sal_False;
+ }
+ if (!rDoc.SplitNode( *rNewCursor.GetPoint(), false ) )
+ {
+ OSL_FAIL( "SplitNode failed" );
+ bOK = sal_False;
+ }
+ nStartIdx = nIdx + 1;
+ nIdx = rText.Search( '\r', nStartIdx );
+ }
+ aTxt = rText.Copy( nStartIdx );
+ if (aTxt.getLength() &&
+ !rDoc.InsertString( rNewCursor, aTxt, nInsertFlags ))
+ {
+ OSL_FAIL( "Doc->Insert(Str) failed." );
+ bOK = sal_False;
+ }
+
+ return bOK;
+}
+
+void makeRedline( SwPaM& rPaM,
+ const ::rtl::OUString& rRedlineType,
+ const uno::Sequence< beans::PropertyValue >& rRedlineProperties )
+ throw (lang::IllegalArgumentException, uno::RuntimeException)
+{
+ IDocumentRedlineAccess* pRedlineAccess = rPaM.GetDoc();
+
+ RedlineType_t eType = nsRedlineType_t::REDLINE_INSERT;
+ if( rRedlineType.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM ( "Delete" ) ))
+ eType = nsRedlineType_t::REDLINE_DELETE;
+ else if( rRedlineType.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM ( "Format" ) ))
+ eType = nsRedlineType_t::REDLINE_FORMAT;
+ else if( rRedlineType.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM ( "TextTable" ) ))
+ eType = nsRedlineType_t::REDLINE_TABLE;
+ else if( !rRedlineType.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM ( "Insert" ) ))
+ throw lang::IllegalArgumentException();
+
+ //todo: what about REDLINE_FMTCOLL?
+ comphelper::SequenceAsHashMap aPropMap( rRedlineProperties );
+ uno::Any aAuthorValue;
+ aAuthorValue = aPropMap.getUnpackedValueOrDefault( ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("RedlineAuthor")), aAuthorValue);
+ sal_uInt16 nAuthor = 0;
+ ::rtl::OUString sAuthor;
+ if( aAuthorValue >>= sAuthor )
+ nAuthor = pRedlineAccess->InsertRedlineAuthor(sAuthor);
+
+ ::rtl::OUString sComment;
+ uno::Any aCommentValue;
+ aCommentValue = aPropMap.getUnpackedValueOrDefault( ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("RedlineComment")), aCommentValue);
+
+ SwRedlineData aRedlineData( eType, nAuthor );
+ if( aCommentValue >>= sComment )
+ aRedlineData.SetComment( sComment );
+
+ ::util::DateTime aStamp;
+ uno::Any aDateTimeValue;
+ aDateTimeValue = aPropMap.getUnpackedValueOrDefault( ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("RedlineDateTime")), aDateTimeValue);
+ if( aDateTimeValue >>= aStamp )
+ {
+ aRedlineData.SetTimeStamp(
+ DateTime( Date( aStamp.Day, aStamp.Month, aStamp.Year ), Time( aStamp.Hours, aStamp.Minutes, aStamp.Seconds ) ) );
+ }
+
+ SwRedline* pRedline = new SwRedline( aRedlineData, rPaM );
+ RedlineMode_t nPrevMode = pRedlineAccess->GetRedlineMode( );
+
+ pRedlineAccess->SetRedlineMode_intern(nsRedlineMode_t::REDLINE_ON);
+ bool bRet = pRedlineAccess->AppendRedline( pRedline, false );
+ pRedlineAccess->SetRedlineMode_intern( nPrevMode );
+ if( !bRet )
+ throw lang::IllegalArgumentException();
+}
+
+SwAnyMapHelper::~SwAnyMapHelper()
+{
+ AnyMapHelper_t::iterator aIt = begin();
+ while( aIt != end() )
+ {
+ delete ( aIt->second );
+ ++aIt;
+ }
+}
+
+void SwAnyMapHelper::SetValue( sal_uInt16 nWhichId, sal_uInt16 nMemberId, const uno::Any& rAny )
+{
+ sal_uInt32 nKey = (nWhichId << 16) + nMemberId;
+ AnyMapHelper_t::iterator aIt = find( nKey );
+ if( aIt != end() )
+ {
+ *(aIt->second) = rAny;
+ }
+ else
+ insert( value_type(nKey, new uno::Any( rAny )) );
+}
+
+bool SwAnyMapHelper::FillValue( sal_uInt16 nWhichId, sal_uInt16 nMemberId, const uno::Any*& pAny )
+{
+ bool bRet = false;
+ sal_uInt32 nKey = (nWhichId << 16) + nMemberId;
+ AnyMapHelper_t::iterator aIt = find( nKey );
+ if( aIt != end() )
+ {
+ pAny = aIt->second;
+ bRet = true;
+ }
+ return bRet;
+}
+
+}//namespace SwUnoCursorHelper
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/unocore/unodraw.cxx b/sw/source/core/unocore/unodraw.cxx
new file mode 100644
index 000000000000..d709de046f76
--- /dev/null
+++ b/sw/source/core/unocore/unodraw.cxx
@@ -0,0 +1,2850 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+#include <swtypes.hxx>
+#include <cmdid.h>
+
+#include <unomid.h>
+#include <unodraw.hxx>
+#include <unocoll.hxx>
+#include <unoframe.hxx>
+#include <unoparagraph.hxx>
+#include <unotextrange.hxx>
+#include <unoprnms.hxx>
+#include <editeng/unoprnms.hxx>
+#include <svx/svditer.hxx>
+#include <swunohelper.hxx>
+#include <doc.hxx>
+#include <IDocumentUndoRedo.hxx>
+#include <fmtcntnt.hxx>
+#include <fmtflcnt.hxx>
+#include <txtatr.hxx>
+#include <docsh.hxx>
+#include <unomap.hxx>
+#include <unoport.hxx>
+#include <unocrsr.hxx>
+#include <TextCursorHelper.hxx>
+#include <swundo.hxx>
+#include <dflyobj.hxx>
+#include <ndtxt.hxx>
+#include <svx/svdview.hxx>
+#include <svx/unoshape.hxx>
+#include <dcontact.hxx>
+#include <svx/fmglob.hxx>
+#include <fmtornt.hxx>
+#include <fmtanchr.hxx>
+#include <fmtsrnd.hxx>
+#include <fmtfollowtextflow.hxx>
+#include <rootfrm.hxx>
+#include <editeng/lrspitem.hxx>
+#include <editeng/ulspitem.hxx>
+#include <svx/shapepropertynotifier.hxx>
+#include <crstate.hxx>
+#include <osl/mutex.hxx>
+#include <comphelper/extract.hxx>
+#include <comphelper/stl_types.hxx>
+#include <comphelper/makesequence.hxx>
+#include <svx/scene3d.hxx>
+#include <com/sun/star/beans/PropertyAttribute.hpp>
+#include <com/sun/star/drawing/XDrawPageSupplier.hpp>
+#include <com/sun/star/text/HoriOrientation.hpp>
+#include <com/sun/star/text/VertOrientation.hpp>
+#include <basegfx/numeric/ftools.hxx>
+#include <algorithm>
+#include <fmtwrapinfluenceonobjpos.hxx>
+#include <com/sun/star/text/TextContentAnchorType.hpp>
+#include <basegfx/matrix/b2dhommatrix.hxx>
+#include <basegfx/matrix/b2dhommatrixtools.hxx>
+#include <com/sun/star/drawing/PointSequence.hpp>
+#include <vcl/svapp.hxx>
+#include <list>
+#include <iterator>
+#include <switerator.hxx>
+
+using ::rtl::OUString;
+using namespace ::com::sun::star;
+
+DECLARE_STL_USTRINGACCESS_MAP( uno::Sequence< sal_Int8 > *, SwShapeImplementationIdMap );
+
+static SwShapeImplementationIdMap aImplementationIdMap;
+
+class SwShapeDescriptor_Impl
+{
+ SwFmtHoriOrient* pHOrient;
+ SwFmtVertOrient* pVOrient;
+ SwFmtAnchor* pAnchor;
+ SwFmtSurround* pSurround;
+ SvxULSpaceItem* pULSpace;
+ SvxLRSpaceItem* pLRSpace;
+ sal_Bool bOpaque;
+ uno::Reference< text::XTextRange > xTextRange;
+ // #i26791#
+ SwFmtFollowTextFlow* mpFollowTextFlow;
+ // #i28701#
+ SwFmtWrapInfluenceOnObjPos* pWrapInfluenceOnObjPos;
+ // #i28749#
+ sal_Int16 mnPositionLayoutDir;
+
+public:
+ bool bInitializedPropertyNotifier;
+
+public:
+ SwShapeDescriptor_Impl() :
+ // #i32349# - no defaults, in order to determine on
+ // adding a shape, if positioning attributes are set or not.
+ pHOrient( 0L ),
+ pVOrient( 0L ),
+ pAnchor(0),
+ pSurround(0),
+ pULSpace(0),
+ pLRSpace(0),
+ bOpaque(sal_False),
+ // #i26791#
+ mpFollowTextFlow( new SwFmtFollowTextFlow( sal_False ) ),
+ // #i28701# #i35017#
+ pWrapInfluenceOnObjPos( new SwFmtWrapInfluenceOnObjPos(
+ text::WrapInfluenceOnPosition::ONCE_CONCURRENT ) ),
+ // #i28749#
+ mnPositionLayoutDir( text::PositionLayoutDir::PositionInLayoutDirOfAnchor ),
+ bInitializedPropertyNotifier(false)
+ {}
+
+ ~SwShapeDescriptor_Impl()
+ {
+ delete pHOrient;
+ delete pVOrient;
+ delete pAnchor;
+ delete pSurround;
+ delete pULSpace;
+ delete pLRSpace;
+ // #i26791#
+ delete mpFollowTextFlow;
+ // #i28701#
+ delete pWrapInfluenceOnObjPos;
+ }
+ SwFmtAnchor* GetAnchor(sal_Bool bCreate = sal_False)
+ {
+ if(bCreate && !pAnchor)
+ {
+ pAnchor = new SwFmtAnchor(FLY_AS_CHAR);
+ }
+ return pAnchor;
+ }
+ SwFmtHoriOrient* GetHOrient(sal_Bool bCreate = sal_False)
+ {
+ if (bCreate && !pHOrient)
+ {
+ // #i26791#
+ pHOrient = new SwFmtHoriOrient( 0, text::HoriOrientation::NONE, text::RelOrientation::FRAME );
+ }
+ return pHOrient;
+ }
+ SwFmtVertOrient* GetVOrient(sal_Bool bCreate = sal_False)
+ {
+ if(bCreate && !pVOrient)
+ {
+ // #i26791#
+ pVOrient = new SwFmtVertOrient( 0, text::VertOrientation::NONE, text::RelOrientation::FRAME );
+ }
+ return pVOrient;
+ }
+
+ SwFmtSurround* GetSurround(sal_Bool bCreate = sal_False)
+ {
+ if(bCreate && !pSurround)
+ pSurround = new SwFmtSurround();
+ return pSurround;
+ }
+ SvxLRSpaceItem* GetLRSpace(sal_Bool bCreate = sal_False)
+ {
+ if(bCreate && !pLRSpace)
+ pLRSpace = new SvxLRSpaceItem(RES_LR_SPACE);
+ return pLRSpace;
+ }
+ SvxULSpaceItem* GetULSpace(sal_Bool bCreate = sal_False)
+ {
+ if(bCreate && !pULSpace)
+ pULSpace = new SvxULSpaceItem(RES_UL_SPACE);
+ return pULSpace;
+ }
+ uno::Reference< text::XTextRange > & GetTextRange()
+ {
+ return xTextRange;
+ }
+ sal_Bool IsOpaque() const
+ {
+ return bOpaque;
+ }
+ const sal_Bool& GetOpaque() const
+ {
+ return bOpaque;
+ }
+ void RemoveHOrient(){DELETEZ(pHOrient);}
+ void RemoveVOrient(){DELETEZ(pVOrient);}
+ void RemoveAnchor(){DELETEZ(pAnchor);}
+ void RemoveSurround(){DELETEZ(pSurround);}
+ void RemoveULSpace(){DELETEZ(pULSpace);}
+ void RemoveLRSpace(){DELETEZ(pLRSpace);}
+ void SetOpaque(sal_Bool bSet){bOpaque = bSet;}
+
+ // #i26791#
+ SwFmtFollowTextFlow* GetFollowTextFlow( sal_Bool _bCreate = sal_False )
+ {
+ if ( _bCreate && !mpFollowTextFlow )
+ mpFollowTextFlow = new SwFmtFollowTextFlow( sal_False );
+ return mpFollowTextFlow;
+ }
+ void RemoveFollowTextFlow()
+ {
+ DELETEZ(mpFollowTextFlow);
+ }
+
+ // #i28749#
+ sal_Int16 GetPositionLayoutDir() const
+ {
+ return mnPositionLayoutDir;
+ }
+ void SetPositionLayoutDir( sal_Int16 _nPositionLayoutDir )
+ {
+ switch ( _nPositionLayoutDir )
+ {
+ case text::PositionLayoutDir::PositionInHoriL2R:
+ case text::PositionLayoutDir::PositionInLayoutDirOfAnchor:
+ {
+ mnPositionLayoutDir = _nPositionLayoutDir;
+ }
+ break;
+ default:
+ {
+ OSL_FAIL( "<SwShapeDescriptor_Impl::SetPositionLayoutDir(..)> - invalid attribute value." );
+ }
+ }
+ }
+ void RemovePositionLayoutDir()
+ {
+ mnPositionLayoutDir = text::PositionLayoutDir::PositionInLayoutDirOfAnchor;
+ }
+
+ // #i28701#
+ inline SwFmtWrapInfluenceOnObjPos* GetWrapInfluenceOnObjPos(
+ const sal_Bool _bCreate = sal_False )
+ {
+ if ( _bCreate && !pWrapInfluenceOnObjPos )
+ {
+ pWrapInfluenceOnObjPos = new SwFmtWrapInfluenceOnObjPos(
+ // #i35017#
+ text::WrapInfluenceOnPosition::ONCE_CONCURRENT );
+ }
+ return pWrapInfluenceOnObjPos;
+ }
+ inline void RemoveWrapInfluenceOnObjPos()
+ {
+ DELETEZ(pWrapInfluenceOnObjPos);
+ }
+};
+
+/****************************************************************************
+ class SwFmDrawPage
+****************************************************************************/
+SwFmDrawPage::SwFmDrawPage( SdrPage* pPage ) :
+ SvxFmDrawPage( pPage ), pPageView(0)
+{
+}
+
+SwFmDrawPage::~SwFmDrawPage() throw ()
+{
+ RemovePageView();
+}
+
+const SdrMarkList& SwFmDrawPage::PreGroup(const uno::Reference< drawing::XShapes > & xShapes)
+{
+ _SelectObjectsInView( xShapes, GetPageView() );
+ const SdrMarkList& rMarkList = mpView->GetMarkedObjectList();
+ return rMarkList;
+}
+
+void SwFmDrawPage::PreUnGroup(const uno::Reference< drawing::XShapeGroup > xShapeGroup)
+{
+ uno::Reference< drawing::XShape > xShape( xShapeGroup, uno::UNO_QUERY);
+ _SelectObjectInView( xShape, GetPageView() );
+}
+
+SdrPageView* SwFmDrawPage::GetPageView()
+{
+ if(!pPageView)
+ pPageView = mpView->ShowSdrPage( mpPage );
+ return pPageView;
+}
+
+void SwFmDrawPage::RemovePageView()
+{
+ if(pPageView && mpView)
+ mpView->HideSdrPage();
+ pPageView = 0;
+}
+
+uno::Reference< uno::XInterface > SwFmDrawPage::GetInterface( SdrObject* pObj )
+{
+ uno::Reference< XInterface > xShape;
+ if( pObj )
+ {
+ SwFrmFmt* pFmt = ::FindFrmFmt( pObj );
+ SwXShape* pxShape = SwIterator<SwXShape,SwFmt>::FirstElement( *pFmt );
+ if(pxShape)
+ {
+ xShape = *(cppu::OWeakObject*)pxShape;
+ }
+ else
+ xShape = pObj->getUnoShape();
+ }
+ return xShape;
+}
+
+SdrObject* SwFmDrawPage::_CreateSdrObject( const uno::Reference< drawing::XShape > & xShape ) throw ()
+{
+ //TODO: stimmt das so - kann die Methode weg?
+ return SvxFmDrawPage::_CreateSdrObject( xShape );
+}
+
+uno::Reference< drawing::XShape > SwFmDrawPage::_CreateShape( SdrObject *pObj ) const throw ()
+{
+ uno::Reference< drawing::XShape > xRet;
+ if(pObj->ISA(SwVirtFlyDrawObj) || pObj->GetObjInventor() == SWGInventor)
+ {
+ SwFlyDrawContact* pFlyContact = (SwFlyDrawContact*)pObj->GetUserCall();
+ if(pFlyContact)
+ {
+ FlyCntType eType = FLYCNTTYPE_ALL;
+ SwFrmFmt* pFlyFmt = pFlyContact->GetFmt();
+ SwDoc* pDoc = pFlyFmt->GetDoc();
+ const SwNodeIndex* pIdx;
+ if( RES_FLYFRMFMT == pFlyFmt->Which()
+ && 0 != ( pIdx = pFlyFmt->GetCntnt().GetCntntIdx() )
+ && pIdx->GetNodes().IsDocNodes()
+ )
+ {
+ const SwNode* pNd = pDoc->GetNodes()[ pIdx->GetIndex() + 1 ];
+ if(!pNd->IsNoTxtNode())
+ eType = FLYCNTTYPE_FRM;
+ else if( pNd->IsGrfNode() )
+ eType = FLYCNTTYPE_GRF;
+ else if( pNd->IsOLENode() )
+ eType = FLYCNTTYPE_OLE;
+ }
+ else
+ {
+ OSL_FAIL( "<SwFmDrawPage::_CreateShape(..)> - could not retrieve type. Thus, no shape created." );
+ return xRet;
+ }
+ DBG_ASSERT( eType != FLYCNTTYPE_ALL, "unexpected FlyCntType value for eType" );
+ xRet = SwXFrames::GetObject( *pFlyFmt, eType );
+ }
+ }
+ else
+ {
+ // own block - temporary object has to be destroyed before
+ // the delegator is set #81670#
+ {
+ xRet = SvxFmDrawPage::_CreateShape( pObj );
+ }
+ uno::Reference< XUnoTunnel > xShapeTunnel(xRet, uno::UNO_QUERY);
+ //don't create an SwXShape if it already exists
+ SwXShape* pShape = 0;
+ if(xShapeTunnel.is())
+ pShape = reinterpret_cast< SwXShape * >(
+ sal::static_int_cast< sal_IntPtr >( xShapeTunnel->getSomething(SwXShape::getUnoTunnelId()) ));
+ if(!pShape)
+ {
+ xShapeTunnel = 0;
+ uno::Reference< uno::XInterface > xCreate(xRet, uno::UNO_QUERY);
+ xRet = 0;
+ uno::Reference< beans::XPropertySet > xPrSet;
+ if ( pObj->IsGroupObject() && (!pObj->Is3DObj() || ( PTR_CAST(E3dScene,pObj ) != NULL ) ) )
+ xPrSet = new SwXGroupShape( xCreate );
+ else
+ xPrSet = new SwXShape( xCreate );
+ xRet = uno::Reference< drawing::XShape >(xPrSet, uno::UNO_QUERY);
+ }
+ }
+ return xRet;
+}
+
+/****************************************************************************
+ class SwXShapesEnumeration
+****************************************************************************/
+namespace
+{
+ class SwXShapesEnumeration
+ : public SwSimpleEnumeration_Base
+ {
+ private:
+ typedef ::std::list< ::com::sun::star::uno::Any > shapescontainer_t;
+ shapescontainer_t m_aShapes;
+ protected:
+ virtual ~SwXShapesEnumeration() {};
+ public:
+ SwXShapesEnumeration(SwXDrawPage* const pDrawPage);
+
+ //XEnumeration
+ virtual sal_Bool SAL_CALL hasMoreElements(void) throw(uno::RuntimeException);
+ virtual uno::Any SAL_CALL nextElement(void) throw(container::NoSuchElementException, lang::WrappedTargetException, uno::RuntimeException);
+
+ //XServiceInfo
+ virtual OUString SAL_CALL getImplementationName(void) throw(uno::RuntimeException);
+ virtual sal_Bool SAL_CALL supportsService(const OUString& ServiceName) throw(uno::RuntimeException);
+ virtual uno::Sequence<OUString> SAL_CALL getSupportedServiceNames(void) throw(uno::RuntimeException);
+ };
+}
+
+SwXShapesEnumeration::SwXShapesEnumeration(SwXDrawPage* const pDrawPage)
+ : m_aShapes()
+{
+ SolarMutexGuard aGuard;
+ ::std::insert_iterator<shapescontainer_t> pInserter = ::std::insert_iterator<shapescontainer_t>(m_aShapes, m_aShapes.begin());
+ sal_Int32 nCount = pDrawPage->getCount();
+ for(sal_Int32 nIdx = 0; nIdx < nCount; nIdx++)
+ {
+ uno::Reference<drawing::XShape> xShape = uno::Reference<drawing::XShape>(pDrawPage->getByIndex(nIdx), uno::UNO_QUERY);
+ *pInserter++ = uno::makeAny(xShape);
+ }
+}
+
+sal_Bool SwXShapesEnumeration::hasMoreElements(void) throw(uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+ return !m_aShapes.empty();
+}
+
+uno::Any SwXShapesEnumeration::nextElement(void) throw(container::NoSuchElementException, lang::WrappedTargetException, uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+ if(m_aShapes.empty())
+ throw container::NoSuchElementException();
+ uno::Any aResult = *m_aShapes.begin();
+ m_aShapes.pop_front();
+ return aResult;
+}
+
+OUString SwXShapesEnumeration::getImplementationName(void) throw(uno::RuntimeException)
+{
+ return C2U("SwXShapeEnumeration");
+}
+
+sal_Bool SwXShapesEnumeration::supportsService(const OUString& ServiceName) throw(uno::RuntimeException)
+{
+ return C2U("com.sun.star.container.XEnumeration") == ServiceName;
+}
+
+uno::Sequence< OUString > SwXShapesEnumeration::getSupportedServiceNames(void) throw(uno::RuntimeException)
+{
+ return ::comphelper::makeSequence(C2U("com.sun.star.container.XEnumeration"));
+}
+
+/****************************************************************************
+ class SwXDrawPage
+****************************************************************************/
+uno::Reference< container::XEnumeration > SwXDrawPage::createEnumeration(void) throw( uno::RuntimeException )
+{
+ SolarMutexGuard aGuard;
+ return uno::Reference< container::XEnumeration >(
+ new SwXShapesEnumeration(this));
+}
+
+rtl::OUString SwXDrawPage::getImplementationName(void) throw( uno::RuntimeException )
+{
+ return C2U("SwXDrawPage");
+}
+
+sal_Bool SwXDrawPage::supportsService(const rtl::OUString& rServiceName) throw( uno::RuntimeException )
+{
+ return C2U("com.sun.star.drawing.GenericDrawPage") == rServiceName;
+}
+
+uno::Sequence< rtl::OUString > SwXDrawPage::getSupportedServiceNames(void) throw( uno::RuntimeException )
+{
+ uno::Sequence< rtl::OUString > aRet(1);
+ rtl::OUString* pArray = aRet.getArray();
+ pArray[0] = C2U("com.sun.star.drawing.GenericDrawPage");
+ return aRet;
+}
+
+SwXDrawPage::SwXDrawPage(SwDoc* pDc) :
+ pDoc(pDc),
+ pDrawPage(0)
+{
+}
+
+SwXDrawPage::~SwXDrawPage()
+{
+ if(xPageAgg.is())
+ {
+ uno::Reference< uno::XInterface > xInt;
+ xPageAgg->setDelegator(xInt);
+ }
+}
+
+uno::Any SwXDrawPage::queryInterface( const uno::Type& aType )
+ throw( uno::RuntimeException )
+{
+ uno::Any aRet = SwXDrawPageBaseClass::queryInterface(aType);
+ if(!aRet.hasValue())
+ {
+ // secure with checking if page exists. This may not be the case
+ // either for new SW docs with no yet graphics usage or when
+ // the doc is closed and someone else still holds a UNO reference
+ // to the XDrawPage (in that case, pDoc is set to 0)
+ SwFmDrawPage* pPage = GetSvxPage();
+
+ if(pPage)
+ {
+ aRet = pPage->queryAggregation(aType);
+ }
+ }
+ return aRet;
+}
+
+uno::Sequence< uno::Type > SwXDrawPage::getTypes() throw( uno::RuntimeException )
+{
+ uno::Sequence< uno::Type > aPageTypes = SwXDrawPageBaseClass::getTypes();
+ uno::Sequence< uno::Type > aSvxTypes = GetSvxPage()->getTypes();
+
+ long nIndex = aPageTypes.getLength();
+ aPageTypes.realloc(aPageTypes.getLength() + aSvxTypes.getLength() + 1);
+
+ uno::Type* pPageTypes = aPageTypes.getArray();
+ const uno::Type* pSvxTypes = aSvxTypes.getConstArray();
+ long nPos;
+ for(nPos = 0; nPos < aSvxTypes.getLength(); nPos++)
+ {
+ pPageTypes[nIndex++] = pSvxTypes[nPos];
+ }
+ pPageTypes[nIndex] = ::getCppuType((uno::Reference<form::XFormsSupplier2>*)0);
+ return aPageTypes;
+}
+
+sal_Int32 SwXDrawPage::getCount(void) throw( uno::RuntimeException )
+{
+ SolarMutexGuard aGuard;
+ if(!pDoc)
+ throw uno::RuntimeException();
+ if(!pDoc->GetDrawModel())
+ return 0;
+ else
+ {
+ ((SwXDrawPage*)this)->GetSvxPage();
+ return pDrawPage->getCount();
+ }
+}
+
+uno::Any SwXDrawPage::getByIndex(sal_Int32 nIndex)
+ throw( lang::IndexOutOfBoundsException, lang::WrappedTargetException,
+ uno::RuntimeException )
+{
+ SolarMutexGuard aGuard;
+ if(!pDoc)
+ throw uno::RuntimeException();
+ if(!pDoc->GetDrawModel())
+ throw lang::IndexOutOfBoundsException();
+
+ ((SwXDrawPage*)this)->GetSvxPage();
+ return pDrawPage->getByIndex( nIndex );
+}
+
+uno::Type SwXDrawPage::getElementType(void) throw( uno::RuntimeException )
+{
+ return ::getCppuType((const uno::Reference<drawing::XShape>*)0);
+}
+
+sal_Bool SwXDrawPage::hasElements(void) throw( uno::RuntimeException )
+{
+ SolarMutexGuard aGuard;
+ if(!pDoc)
+ throw uno::RuntimeException();
+ if(!pDoc->GetDrawModel())
+ return sal_False;
+ else
+ return ((SwXDrawPage*)this)->GetSvxPage()->hasElements();
+}
+
+void SwXDrawPage::add(const uno::Reference< drawing::XShape > & xShape)
+ throw( uno::RuntimeException )
+{
+ SolarMutexGuard aGuard;
+ if(!pDoc)
+ throw uno::RuntimeException();
+ uno::Reference< lang::XUnoTunnel > xShapeTunnel(xShape, uno::UNO_QUERY);
+ SwXShape* pShape = 0;
+ SvxShape* pSvxShape = 0;
+ if(xShapeTunnel.is())
+ {
+ pShape = reinterpret_cast< SwXShape * >(
+ sal::static_int_cast< sal_IntPtr >( xShapeTunnel->getSomething(SwXShape::getUnoTunnelId()) ));
+ pSvxShape = reinterpret_cast< SvxShape * >(
+ sal::static_int_cast< sal_IntPtr >( xShapeTunnel->getSomething(SvxShape::getUnoTunnelId()) ));
+ }
+
+ if(!pShape || pShape->GetRegisteredIn() || !pShape->m_bDescriptor )
+ {
+ uno::RuntimeException aExcept;
+ if(pShape)
+ aExcept.Message = C2U("object already inserted");
+ else
+ aExcept.Message = C2U("illegal object");
+ throw aExcept;
+ }
+
+ if ( pSvxShape->GetSdrObject() )
+ {
+ if ( pSvxShape->GetSdrObject()->IsInserted() )
+ {
+ return;
+ }
+ }
+ GetSvxPage()->add(xShape);
+
+ uno::Reference< uno::XAggregation > xAgg = pShape->GetAggregationInterface();
+
+ DBG_ASSERT(pSvxShape, "warum gibt es hier kein SvxShape?");
+ //diese Position ist auf jeden Fall in 1/100 mm
+ awt::Point aMM100Pos(pSvxShape->getPosition());
+
+ //jetzt noch die Properties aus dem SwShapeDescriptor_Impl auswerten
+ SwShapeDescriptor_Impl* pDesc = pShape->GetDescImpl();
+
+ SfxItemSet aSet( pDoc->GetAttrPool(), RES_FRMATR_BEGIN,
+ RES_FRMATR_END-1 );
+ SwFmtAnchor aAnchor( FLY_AS_CHAR );
+ sal_Bool bOpaque = sal_False;
+ if( pDesc )
+ {
+ if(pDesc->GetSurround())
+ aSet.Put( *pDesc->GetSurround());
+ //die Items sind schon in Twip gesetzt
+ if(pDesc->GetLRSpace())
+ {
+ aSet.Put(*pDesc->GetLRSpace());
+ }
+ if(pDesc->GetULSpace())
+ {
+ aSet.Put(*pDesc->GetULSpace());
+ }
+ if(pDesc->GetAnchor())
+ aAnchor = *pDesc->GetAnchor();
+
+ // #i32349# - if no horizontal position exists, create one
+ if ( !pDesc->GetHOrient() )
+ {
+ SwFmtHoriOrient* pHori = pDesc->GetHOrient( sal_True );
+ SwTwips nHoriPos = MM100_TO_TWIP(aMM100Pos.X);
+ pHori->SetPos( nHoriPos );
+ }
+ {
+ if(pDesc->GetHOrient()->GetHoriOrient() == text::HoriOrientation::NONE)
+ aMM100Pos.X = TWIP_TO_MM100(pDesc->GetHOrient()->GetPos());
+ aSet.Put( *pDesc->GetHOrient() );
+ }
+ // #i32349# - if no vertical position exists, create one
+ if ( !pDesc->GetVOrient() )
+ {
+ SwFmtVertOrient* pVert = pDesc->GetVOrient( sal_True );
+ SwTwips nVertPos = MM100_TO_TWIP(aMM100Pos.Y);
+ pVert->SetPos( nVertPos );
+ }
+ {
+ if(pDesc->GetVOrient()->GetVertOrient() == text::VertOrientation::NONE)
+ aMM100Pos.Y = TWIP_TO_MM100(pDesc->GetVOrient()->GetPos());
+ aSet.Put( *pDesc->GetVOrient() );
+ }
+
+ if(pDesc->GetSurround())
+ aSet.Put( *pDesc->GetSurround());
+ bOpaque = pDesc->IsOpaque();
+
+ // #i26791#
+ if ( pDesc->GetFollowTextFlow() )
+ {
+ aSet.Put( *pDesc->GetFollowTextFlow() );
+ }
+
+ // #i28701#
+ if ( pDesc->GetWrapInfluenceOnObjPos() )
+ {
+ aSet.Put( *pDesc->GetWrapInfluenceOnObjPos() );
+ }
+ }
+
+ pSvxShape->setPosition(aMM100Pos);
+ SdrObject* pObj = pSvxShape->GetSdrObject();
+ // #108784# - set layer of new drawing object to corresponding
+ // invisible layer.
+ if(FmFormInventor != pObj->GetObjInventor())
+ pObj->SetLayer( bOpaque ? pDoc->GetInvisibleHeavenId() : pDoc->GetInvisibleHellId() );
+ else
+ pObj->SetLayer(pDoc->GetInvisibleControlsId());
+
+ SwPaM* pPam = new SwPaM(pDoc->GetNodes().GetEndOfContent());
+ SwUnoInternalPaM* pInternalPam = 0;
+ uno::Reference< text::XTextRange > xRg;
+ if( pDesc && (xRg = pDesc->GetTextRange()).is() )
+ {
+ pInternalPam = new SwUnoInternalPaM(*pDoc);
+ if (::sw::XTextRangeToSwPaM(*pInternalPam, xRg))
+ {
+ if(FLY_AT_FLY == aAnchor.GetAnchorId() &&
+ !pInternalPam->GetNode()->FindFlyStartNode())
+ {
+ aAnchor.SetType(FLY_AS_CHAR);
+ }
+ else if (FLY_AT_PAGE == aAnchor.GetAnchorId())
+ {
+ aAnchor.SetAnchor(pInternalPam->Start());
+ }
+ }
+ else
+ throw uno::RuntimeException();
+ }
+ else if ((aAnchor.GetAnchorId() != FLY_AT_PAGE) && pDoc->GetCurrentLayout())
+ {
+ SwCrsrMoveState aState( MV_SETONLYTEXT );
+ Point aTmp(MM100_TO_TWIP(aMM100Pos.X), MM100_TO_TWIP(aMM100Pos.Y));
+ pDoc->GetCurrentLayout()->GetCrsrOfst( pPam->GetPoint(), aTmp, &aState ); //swmod 080218
+ aAnchor.SetAnchor( pPam->GetPoint() );
+
+ // #i32349# - adjustment of vertical positioning
+ // attributes no longer needed, because its already got a default.
+ }
+ else
+ {
+ aAnchor.SetType(FLY_AT_PAGE);
+
+ // #i32349# - adjustment of vertical positioning
+ // attributes no longer needed, because its already got a default.
+ }
+ aSet.Put(aAnchor);
+ SwPaM* pTemp = pInternalPam;
+ if ( !pTemp )
+ pTemp = pPam;
+ UnoActionContext aAction(pDoc);
+ pDoc->Insert( *pTemp, *pObj, &aSet, NULL );
+ SwFrmFmt* pFmt = ::FindFrmFmt( pObj );
+ if(pFmt)
+ pFmt->Add(pShape);
+ pShape->m_bDescriptor = sal_False;
+
+ delete pPam;
+ delete pInternalPam;
+}
+
+void SwXDrawPage::remove(const uno::Reference< drawing::XShape > & xShape) throw( uno::RuntimeException )
+{
+ SolarMutexGuard aGuard;
+ if(!pDoc)
+ throw uno::RuntimeException();
+ uno::Reference<lang::XComponent> xComp(xShape, uno::UNO_QUERY);
+ xComp->dispose();
+}
+
+uno::Reference< drawing::XShapeGroup > SwXDrawPage::group(const uno::Reference< drawing::XShapes > & xShapes) throw( uno::RuntimeException )
+{
+ SolarMutexGuard aGuard;
+ if(!pDoc || !xShapes.is())
+ throw uno::RuntimeException();
+ uno::Reference< drawing::XShapeGroup > xRet;
+ if(xPageAgg.is())
+ {
+
+ SwFmDrawPage* pPage = GetSvxPage();
+ if(pPage)//kann das auch Null sein?
+ {
+ //markieren und MarkList zurueckgeben
+ const SdrMarkList& rMarkList = pPage->PreGroup(xShapes);
+ if ( rMarkList.GetMarkCount() > 1 )
+ {
+ sal_Bool bFlyInCnt = sal_False;
+ for ( sal_uInt16 i = 0; !bFlyInCnt && i < rMarkList.GetMarkCount(); ++i )
+ {
+ const SdrObject *pObj = rMarkList.GetMark( i )->GetMarkedSdrObj();
+ if (FLY_AS_CHAR == ::FindFrmFmt(const_cast<SdrObject*>(
+ pObj))->GetAnchor().GetAnchorId())
+ {
+ bFlyInCnt = sal_True;
+ }
+ }
+ if( bFlyInCnt )
+ throw uno::RuntimeException();
+ if( !bFlyInCnt )
+ {
+ UnoActionContext aContext(pDoc);
+ pDoc->GetIDocumentUndoRedo().StartUndo( UNDO_START, NULL );
+
+ SwDrawContact* pContact = pDoc->GroupSelection( *pPage->GetDrawView() );
+ pDoc->ChgAnchor(
+ pPage->GetDrawView()->GetMarkedObjectList(),
+ FLY_AT_PARA/*int eAnchorId*/,
+ sal_True, sal_False );
+
+ pPage->GetDrawView()->UnmarkAll();
+ if(pContact)
+ {
+ uno::Reference< uno::XInterface > xInt = pPage->GetInterface( pContact->GetMaster() );
+ xRet = uno::Reference< drawing::XShapeGroup >(xInt, uno::UNO_QUERY);
+ }
+ pDoc->GetIDocumentUndoRedo().EndUndo( UNDO_END, NULL );
+ }
+ }
+ pPage->RemovePageView();
+ }
+ }
+ return xRet;
+}
+
+void SwXDrawPage::ungroup(const uno::Reference< drawing::XShapeGroup > & xShapeGroup) throw( uno::RuntimeException )
+{
+ SolarMutexGuard aGuard;
+ if(!pDoc)
+ throw uno::RuntimeException();
+ if(xPageAgg.is())
+ {
+ SwFmDrawPage* pPage = GetSvxPage();
+ if(pPage)//kann das auch Null sein?
+ {
+ pPage->PreUnGroup(xShapeGroup);
+ UnoActionContext aContext(pDoc);
+ pDoc->GetIDocumentUndoRedo().StartUndo( UNDO_START, NULL );
+
+ pDoc->UnGroupSelection( *pPage->GetDrawView() );
+ pDoc->ChgAnchor( pPage->GetDrawView()->GetMarkedObjectList(),
+ FLY_AT_PARA/*int eAnchorId*/,
+ sal_True, sal_False );
+ pDoc->GetIDocumentUndoRedo().EndUndo( UNDO_END, NULL );
+ }
+ pPage->RemovePageView();
+ }
+}
+
+SwFmDrawPage* SwXDrawPage::GetSvxPage()
+{
+ if(!xPageAgg.is() && pDoc)
+ {
+ SolarMutexGuard aGuard;
+ // #i52858#
+ SdrModel* pModel = pDoc->GetOrCreateDrawModel();
+ SdrPage* pPage = pModel->GetPage( 0 );
+
+ {
+ // waehrend des queryInterface braucht man ein Ref auf das
+ // Objekt, sonst wird es geloescht.
+ pDrawPage = new SwFmDrawPage(pPage);
+ uno::Reference< drawing::XDrawPage > xPage = pDrawPage;
+ uno::Any aAgg = xPage->queryInterface(::getCppuType((uno::Reference< uno::XAggregation >*)0));
+ if(aAgg.getValueType() == ::getCppuType((uno::Reference< uno::XAggregation >*)0))
+ xPageAgg = *(uno::Reference< uno::XAggregation >*)aAgg.getValue();
+ }
+ if( xPageAgg.is() )
+ xPageAgg->setDelegator( (cppu::OWeakObject*)this );
+ }
+ return pDrawPage;
+}
+
+// renamed and outlined to detect where it's called
+void SwXDrawPage::InvalidateSwDoc()
+{
+ pDoc = 0;
+}
+
+TYPEINIT1(SwXShape, SwClient);
+
+const uno::Sequence< sal_Int8 > & SwXShape::getUnoTunnelId()
+{
+ static uno::Sequence< sal_Int8 > aSeq = ::CreateUnoTunnelId();
+ return aSeq;
+}
+
+sal_Int64 SAL_CALL SwXShape::getSomething( const uno::Sequence< sal_Int8 >& rId )
+ throw(uno::RuntimeException)
+{
+ if( rId.getLength() == 16
+ && 0 == rtl_compareMemory( getUnoTunnelId().getConstArray(),
+ rId.getConstArray(), 16 ) )
+ {
+ return sal::static_int_cast< sal_Int64 >( reinterpret_cast< sal_IntPtr >(this) );
+ }
+
+ if( xShapeAgg.is() )
+ {
+ const uno::Type& rTunnelType = ::getCppuType((uno::Reference<lang::XUnoTunnel>*)0 );
+ uno::Any aAgg = xShapeAgg->queryAggregation( rTunnelType );
+ if(aAgg.getValueType() == rTunnelType)
+ {
+ uno::Reference<lang::XUnoTunnel> xAggTunnel =
+ *(uno::Reference<lang::XUnoTunnel>*)aAgg.getValue();
+ if(xAggTunnel.is())
+ return xAggTunnel->getSomething(rId);
+ }
+ }
+ return 0;
+}
+namespace
+{
+ static void lcl_addShapePropertyEventFactories( SdrObject& _rObj, SwXShape& _rShape )
+ {
+ ::svx::PPropertyValueProvider pProvider( new ::svx::PropertyValueProvider( _rShape, "AnchorType" ) );
+ _rObj.getShapePropertyChangeNotifier().registerProvider( ::svx::eTextShapeAnchorType, pProvider );
+ }
+}
+
+
+SwXShape::SwXShape(uno::Reference< uno::XInterface > & xShape) :
+ m_pPropSet(aSwMapProvider.GetPropertySet(PROPERTY_MAP_TEXT_SHAPE)),
+ m_pPropertyMapEntries(aSwMapProvider.GetPropertyMapEntries(PROPERTY_MAP_TEXT_SHAPE)),
+ pImplementationId(0),
+ pImpl(new SwShapeDescriptor_Impl()),
+ m_bDescriptor(sal_True)
+{
+ if(xShape.is()) // default Ctor
+ {
+ const uno::Type& rAggType = ::getCppuType((const uno::Reference< uno::XAggregation >*)0);
+ //aAgg contains a reference of the SvxShape!
+ {
+ uno::Any aAgg = xShape->queryInterface(rAggType);
+ if(aAgg.getValueType() == rAggType)
+ xShapeAgg = *(uno::Reference< uno::XAggregation >*)aAgg.getValue();
+ // #i31698#
+ if ( xShapeAgg.is() )
+ {
+ xShapeAgg->queryAggregation( ::getCppuType((uno::Reference< drawing::XShape >*)0) ) >>= mxShape;
+ OSL_ENSURE( mxShape.is(),
+ "<SwXShape::SwXShape(..)> - no XShape found at <xShapeAgg>" );
+ }
+ // <--
+ }
+ xShape = 0;
+ m_refCount++;
+ if( xShapeAgg.is() )
+ xShapeAgg->setDelegator( (cppu::OWeakObject*)this );
+ m_refCount--;
+
+ uno::Reference< lang::XUnoTunnel > xShapeTunnel(xShapeAgg, uno::UNO_QUERY);
+ SvxShape* pShape = 0;
+ if(xShapeTunnel.is())
+ pShape = reinterpret_cast< SvxShape * >(
+ sal::static_int_cast< sal_IntPtr >( xShapeTunnel->getSomething(SvxShape::getUnoTunnelId()) ));
+
+ SdrObject* pObj = pShape ? pShape->GetSdrObject() : 0;
+ if(pObj)
+ {
+ SwFrmFmt* pFmt = ::FindFrmFmt( pObj );
+ if(pFmt)
+ pFmt->Add(this);
+
+ lcl_addShapePropertyEventFactories( *pObj, *this );
+ pImpl->bInitializedPropertyNotifier = true;
+ }
+ }
+}
+
+void SwXShape::AddExistingShapeToFmt( SdrObject& _rObj )
+{
+ SdrObjListIter aIter( _rObj, IM_DEEPNOGROUPS );
+ while ( aIter.IsMore() )
+ {
+ SdrObject* pCurrent = aIter.Next();
+ OSL_ENSURE( pCurrent, "SwXShape::AddExistingShapeToFmt: invalid object list element!" );
+ if ( !pCurrent )
+ continue;
+
+ SwXShape* pSwShape = NULL;
+ uno::Reference< lang::XUnoTunnel > xShapeTunnel( pCurrent->getWeakUnoShape(), uno::UNO_QUERY );
+ if ( xShapeTunnel.is() )
+ pSwShape = reinterpret_cast< SwXShape * >(
+ sal::static_int_cast< sal_IntPtr >( xShapeTunnel->getSomething( SwXShape::getUnoTunnelId() ) ) );
+ if ( pSwShape )
+ {
+ if ( pSwShape->m_bDescriptor )
+ {
+ SwFrmFmt* pFmt = ::FindFrmFmt( const_cast< SdrObject* >( pCurrent ) );
+ if ( pFmt )
+ pFmt->Add( pSwShape );
+ pSwShape->m_bDescriptor = sal_False;
+ }
+
+ if ( !pSwShape->pImpl->bInitializedPropertyNotifier )
+ {
+ lcl_addShapePropertyEventFactories( *pCurrent, *pSwShape );
+ pSwShape->pImpl->bInitializedPropertyNotifier = true;
+ }
+ }
+ }
+}
+
+SwXShape::~SwXShape()
+{
+ if (xShapeAgg.is())
+ {
+ uno::Reference< uno::XInterface > xRef;
+ xShapeAgg->setDelegator(xRef);
+ }
+ delete pImpl;
+}
+
+uno::Any SwXShape::queryInterface( const uno::Type& aType ) throw( uno::RuntimeException )
+{
+ uno::Any aRet = SwXShapeBaseClass::queryInterface(aType);
+ // #i53320# - follow-up of #i31698#
+ // interface drawing::XShape is overloaded. Thus, provide
+ // correct object instance.
+ if(!aRet.hasValue() && xShapeAgg.is())
+ {
+ if(aType == ::getCppuType((uno::Reference<XShape>*)0))
+ aRet <<= uno::Reference<XShape>(this);
+ else
+ aRet = xShapeAgg->queryAggregation(aType);
+ }
+ return aRet;
+}
+
+uno::Sequence< uno::Type > SwXShape::getTypes( ) throw(uno::RuntimeException)
+{
+ uno::Sequence< uno::Type > aRet = SwXShapeBaseClass::getTypes();
+ if(xShapeAgg.is())
+ {
+ uno::Any aProv = xShapeAgg->queryAggregation(::getCppuType((uno::Reference< XTypeProvider >*)0));
+ if(aProv.hasValue())
+ {
+ uno::Reference< XTypeProvider > xAggProv;
+ aProv >>= xAggProv;
+ uno::Sequence< uno::Type > aAggTypes = xAggProv->getTypes();
+ const uno::Type* pAggTypes = aAggTypes.getConstArray();
+ long nIndex = aRet.getLength();
+
+ aRet.realloc(nIndex + aAggTypes.getLength());
+ uno::Type* pBaseTypes = aRet.getArray();
+
+ for(long i = 0; i < aAggTypes.getLength(); i++)
+ pBaseTypes[nIndex++] = pAggTypes[i];
+ }
+ }
+ return aRet;
+}
+
+uno::Sequence< sal_Int8 > SwXShape::getImplementationId( ) throw(uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+ // do we need to compute the implementation id for this instance?
+ if( !pImplementationId && xShapeAgg.is())
+ {
+ uno::Reference< XShape > xAggShape;
+ xShapeAgg->queryAggregation( ::getCppuType((uno::Reference< XShape >*)0) ) >>= xAggShape;
+
+ if( xAggShape.is() )
+ {
+ const rtl::OUString aShapeType( xAggShape->getShapeType() );
+ // did we already compute an implementation id for the agregated shape type?
+ SwShapeImplementationIdMap::iterator aIter( aImplementationIdMap.find(aShapeType ) );
+ if( aIter == aImplementationIdMap.end() )
+ {
+ // we need to create a new implementation id for this
+ // note: this memory is not free'd until application exists
+ // but since we have a fixed set of shapetypes and the
+ // memory will be reused this is ok.
+ pImplementationId = new uno::Sequence< sal_Int8 >( 16 );
+ rtl_createUuid( (sal_uInt8 *) pImplementationId->getArray(), 0, sal_True );
+ aImplementationIdMap[ aShapeType ] = pImplementationId;
+ }
+ else
+ {
+ // use the already computed implementation id
+ pImplementationId = (*aIter).second;
+ }
+ }
+ }
+ if( NULL == pImplementationId )
+ {
+ OSL_FAIL( "Could not create an implementation id for a SwXShape!" );
+ return uno::Sequence< sal_Int8 > ();
+ }
+ else
+ {
+ return *pImplementationId;
+ }
+}
+
+uno::Reference< beans::XPropertySetInfo > SwXShape::getPropertySetInfo(void) throw( uno::RuntimeException )
+{
+ SolarMutexGuard aGuard;
+ uno::Reference< beans::XPropertySetInfo > aRet;
+ if(xShapeAgg.is())
+ {
+ const uno::Type& rPropSetType = ::getCppuType((const uno::Reference< beans::XPropertySet >*)0);
+ uno::Any aPSet = xShapeAgg->queryAggregation( rPropSetType );
+ if(aPSet.getValueType() == rPropSetType && aPSet.getValue())
+ {
+ uno::Reference< beans::XPropertySet > xPrSet =
+ *(uno::Reference< beans::XPropertySet >*)aPSet.getValue();
+ uno::Reference< beans::XPropertySetInfo > xInfo = xPrSet->getPropertySetInfo();
+ // PropertySetInfo verlaengern!
+ const uno::Sequence<beans::Property> aPropSeq = xInfo->getProperties();
+ aRet = new SfxExtItemPropertySetInfo( m_pPropertyMapEntries, aPropSeq );
+ }
+ }
+ if(!aRet.is())
+ aRet = m_pPropSet->getPropertySetInfo();
+ return aRet;
+}
+
+void SwXShape::setPropertyValue(const rtl::OUString& rPropertyName, const uno::Any& aValue)
+ throw( beans::UnknownPropertyException, beans::PropertyVetoException,
+ lang::IllegalArgumentException, lang::WrappedTargetException,
+ uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+ SwFrmFmt* pFmt = GetFrmFmt();
+ const SfxItemPropertySimpleEntry* pEntry = m_pPropSet->getPropertyMap()->getByName( rPropertyName );
+ if(xShapeAgg.is())
+ {
+ if(pEntry)
+ {
+ if ( pEntry->nFlags & beans::PropertyAttribute::READONLY)
+ throw beans::PropertyVetoException ( rtl::OUString ( RTL_CONSTASCII_USTRINGPARAM ( "Property is read-only: " ) ) + rPropertyName, static_cast < cppu::OWeakObject * > ( this ) );
+ //mit Layout kann der Anker umgesetzt werden, ohne dass sich die Position aendert
+ if(pFmt)
+ {
+ SwAttrSet aSet(pFmt->GetAttrSet());
+ SwDoc* pDoc = pFmt->GetDoc();
+ if(RES_ANCHOR == pEntry->nWID && MID_ANCHOR_ANCHORFRAME == pEntry->nMemberId)
+ {
+ sal_Bool bDone = sal_True;
+ uno::Reference<text::XTextFrame> xFrame;
+ if(aValue >>= xFrame)
+ {
+ uno::Reference<lang::XUnoTunnel> xTunnel(xFrame, uno::UNO_QUERY);
+ SwXFrame* pFrame = xTunnel.is() ?
+ reinterpret_cast< SwXFrame * >(
+ sal::static_int_cast< sal_IntPtr >( xTunnel->getSomething(SwXFrame::getUnoTunnelId()) ))
+ : 0;
+ if(pFrame && pFrame->GetFrmFmt() &&
+ pFrame->GetFrmFmt()->GetDoc() == pDoc)
+ {
+ UnoActionContext aCtx(pDoc);
+ SfxItemSet aItemSet( pDoc->GetAttrPool(),
+ RES_FRMATR_BEGIN, RES_FRMATR_END - 1 );
+ aItemSet.SetParent(&pFmt->GetAttrSet());
+ SwFmtAnchor aAnchor = (const SwFmtAnchor&)aItemSet.Get(pEntry->nWID);
+ SwPosition aPos(*pFrame->GetFrmFmt()->GetCntnt().GetCntntIdx());
+ aAnchor.SetAnchor(&aPos);
+ aAnchor.SetType(FLY_AT_FLY);
+ aItemSet.Put(aAnchor);
+ pFmt->SetFmtAttr(aItemSet);
+ bDone = sal_True;
+ }
+ }
+ if(!bDone)
+ throw lang::IllegalArgumentException();
+ }
+ else if(RES_OPAQUE == pEntry->nWID)
+ {
+ SvxShape* pSvxShape = GetSvxShape();
+ DBG_ASSERT(pSvxShape, "No SvxShape found!");
+ if(pSvxShape)
+ {
+ SdrObject* pObj = pSvxShape->GetSdrObject();
+ // set layer of new drawing
+ // object to corresponding invisible layer.
+ bool bIsVisible = pDoc->IsVisibleLayerId( pObj->GetLayer() );
+ if(FmFormInventor != pObj->GetObjInventor())
+ {
+ pObj->SetLayer( *(sal_Bool*)aValue.getValue()
+ ? ( bIsVisible ? pDoc->GetHeavenId() : pDoc->GetInvisibleHeavenId() )
+ : ( bIsVisible ? pDoc->GetHellId() : pDoc->GetInvisibleHellId() ));
+ }
+ else
+ {
+ pObj->SetLayer( bIsVisible ? pDoc->GetControlsId() : pDoc->GetInvisibleControlsId());
+ }
+
+ }
+
+ }
+ // #i26791# - special handling for property FN_TEXT_RANGE
+ else if ( FN_TEXT_RANGE == pEntry->nWID )
+ {
+ SwFmtAnchor aAnchor( static_cast<const SwFmtAnchor&>(aSet.Get( RES_ANCHOR )) );
+ if (aAnchor.GetAnchorId() == FLY_AT_PAGE)
+ {
+ // set property <TextRange> not valid for to-page anchored shapes
+ throw lang::IllegalArgumentException();
+ }
+ else
+ {
+ SwUnoInternalPaM* pInternalPam =
+ new SwUnoInternalPaM( *(pFmt->GetDoc()) );
+ uno::Reference< text::XTextRange > xRg;
+ aValue >>= xRg;
+ if (::sw::XTextRangeToSwPaM(*pInternalPam, xRg) )
+ {
+ if (aAnchor.GetAnchorId() == FLY_AS_CHAR)
+ {
+ //delete old SwFmtFlyCnt
+ //With AnchorAsCharacter the current TxtAttribute has to be deleted.
+ //Tbis removes the frame format too.
+ //To prevent this the connection between format and attribute has to be broken before.
+ const SwPosition *pPos = aAnchor.GetCntntAnchor();
+ SwTxtNode *pTxtNode = pPos->nNode.GetNode().GetTxtNode();
+ OSL_ENSURE( pTxtNode->HasHints(), "Missing FlyInCnt-Hint." );
+ const xub_StrLen nIdx = pPos->nContent.GetIndex();
+ SwTxtAttr * const pHnt =
+ pTxtNode->GetTxtAttrForCharAt(
+ nIdx, RES_TXTATR_FLYCNT );
+ DBG_ASSERT( pHnt && pHnt->Which() == RES_TXTATR_FLYCNT,
+ "Missing FlyInCnt-Hint." );
+ DBG_ASSERT( pHnt && pHnt->GetFlyCnt().GetFrmFmt() == pFmt,
+ "Wrong TxtFlyCnt-Hint." );
+ const_cast<SwFmtFlyCnt&>(pHnt->GetFlyCnt())
+ .SetFlyFmt();
+
+ //The connection is removed now the attribute can be deleted.
+ pTxtNode->DeleteAttributes(
+ RES_TXTATR_FLYCNT, nIdx );
+ //create a new one
+ SwTxtNode *pNd = pInternalPam->GetNode()->GetTxtNode();
+ DBG_ASSERT( pNd, "Cursor not at TxtNode." );
+ SwFmtFlyCnt aFmt( pFmt );
+ pNd->InsertItem(aFmt, pInternalPam->GetPoint()
+ ->nContent.GetIndex(), 0 );
+ }
+ else
+ {
+ aAnchor.SetAnchor( pInternalPam->GetPoint() );
+ aSet.Put(aAnchor);
+ pFmt->SetFmtAttr(aSet);
+ }
+ }
+ else
+ {
+ throw uno::RuntimeException();
+ }
+ delete pInternalPam;
+ }
+ }
+ // #i28749#
+ else if ( FN_SHAPE_POSITION_LAYOUT_DIR == pEntry->nWID )
+ {
+ sal_Int16 nPositionLayoutDir = 0;
+ aValue >>= nPositionLayoutDir;
+ pFmt->SetPositionLayoutDir( nPositionLayoutDir );
+ }
+ else if( pDoc->GetCurrentLayout()) //swmod 080218
+ {
+ UnoActionContext aCtx(pDoc);
+ if(RES_ANCHOR == pEntry->nWID && MID_ANCHOR_ANCHORTYPE == pEntry->nMemberId)
+ {
+ SdrObject* pObj = pFmt->FindSdrObject();
+ SdrMarkList aList;
+ SdrMark aMark(pObj);
+ aList.InsertEntry(aMark);
+ sal_Int32 nAnchor = 0;
+ cppu::enum2int( nAnchor, aValue );
+ pDoc->ChgAnchor( aList, (RndStdIds)nAnchor,
+ sal_False, sal_True );
+ }
+ else
+ {
+ m_pPropSet->setPropertyValue(*pEntry, aValue, aSet);
+ pFmt->SetFmtAttr(aSet);
+ }
+ }
+ else
+ {
+ m_pPropSet->setPropertyValue( *pEntry, aValue, aSet );
+
+ if(RES_ANCHOR == pEntry->nWID && MID_ANCHOR_ANCHORTYPE == pEntry->nMemberId)
+ {
+ bool bSetAttr = true;
+ sal_Int32 eNewAnchor = SWUnoHelper::GetEnumAsInt32( aValue );
+
+ //if old anchor was in_cntnt the related text attribute has to be removed
+ const SwFmtAnchor& rOldAnchor = pFmt->GetAnchor();
+ RndStdIds eOldAnchorId = rOldAnchor.GetAnchorId();
+ SdrObject* pObj = pFmt->FindSdrObject();
+ SwFrmFmt *pFlyFmt = FindFrmFmt( pObj );
+ pFlyFmt->DelFrms();
+ if( text::TextContentAnchorType_AS_CHARACTER != eNewAnchor &&
+ (FLY_AS_CHAR == eOldAnchorId))
+ {
+ //With AnchorAsCharacter the current TxtAttribute has to be deleted.
+ //Tbis removes the frame format too.
+ //To prevent this the connection between format and attribute has to be broken before.
+ const SwPosition *pPos = rOldAnchor.GetCntntAnchor();
+ SwTxtNode *pTxtNode = pPos->nNode.GetNode().GetTxtNode();
+ OSL_ENSURE( pTxtNode->HasHints(), "Missing FlyInCnt-Hint." );
+ const xub_StrLen nIdx = pPos->nContent.GetIndex();
+ SwTxtAttr * const pHnt =
+ pTxtNode->GetTxtAttrForCharAt(
+ nIdx, RES_TXTATR_FLYCNT );
+ DBG_ASSERT( pHnt && pHnt->Which() == RES_TXTATR_FLYCNT,
+ "Missing FlyInCnt-Hint." );
+ DBG_ASSERT( pHnt && pHnt->GetFlyCnt().GetFrmFmt() == pFlyFmt,
+ "Wrong TxtFlyCnt-Hint." );
+ const_cast<SwFmtFlyCnt&>(pHnt->GetFlyCnt())
+ .SetFlyFmt();
+
+ //The connection is removed now the attribute can be deleted.
+ pTxtNode->DeleteAttributes(RES_TXTATR_FLYCNT, nIdx);
+ }
+ else if( text::TextContentAnchorType_AT_PAGE != eNewAnchor &&
+ (FLY_AT_PAGE == eOldAnchorId))
+ {
+ SwFmtAnchor aNewAnchor( dynamic_cast< const SwFmtAnchor& >( aSet.Get( RES_ANCHOR ) ) );
+ //if the fly has been anchored at page then it needs to be connected
+ //to the content position
+ SwPaM aPam(pDoc->GetNodes().GetEndOfContent());
+ if( pDoc->GetCurrentLayout() )
+ {
+ SwCrsrMoveState aState( MV_SETONLYTEXT );
+ Point aTmp( pObj->GetSnapRect().TopLeft() );
+ pDoc->GetCurrentLayout()->GetCrsrOfst( aPam.GetPoint(), aTmp, &aState );
+ }
+ else
+ {
+ //without access to the layout the last node of the body will be used as anchor position
+ aPam.Move( fnMoveBackward, fnGoDoc );
+ }
+ //anchor position has to be inserted after the text attribute has been inserted
+ aNewAnchor.SetAnchor( aPam.GetPoint() );
+ aSet.Put( aNewAnchor );
+ pFmt->SetFmtAttr(aSet);
+ bSetAttr = false;
+ if( text::TextContentAnchorType_AS_CHARACTER == eNewAnchor &&
+ (FLY_AS_CHAR != eOldAnchorId))
+ {
+ //the RES_TXTATR_FLYCNT needs to be added now
+ SwTxtNode *pNd = aPam.GetNode()->GetTxtNode();
+ DBG_ASSERT( pNd, "Crsr is not in a TxtNode." );
+ SwFmtFlyCnt aFmt( pFlyFmt );
+ pNd->InsertItem(aFmt,
+ aPam.GetPoint()->nContent.GetIndex(), 0 );
+ //aPam.GetPoint()->nContent--;
+
+ }
+ }
+ if( bSetAttr )
+ pFmt->SetFmtAttr(aSet);
+ }
+ else
+ pFmt->SetFmtAttr(aSet);
+ }
+ }
+ else
+ {
+ SfxPoolItem* pItem = 0;
+ switch(pEntry->nWID)
+ {
+ case RES_ANCHOR:
+ pItem = pImpl->GetAnchor(sal_True);
+ break;
+ case RES_HORI_ORIENT:
+ pItem = pImpl->GetHOrient(sal_True);
+ break;
+ case RES_VERT_ORIENT:
+ pItem = pImpl->GetVOrient(sal_True);
+ break;
+ case RES_LR_SPACE:
+ pItem = pImpl->GetLRSpace(sal_True);
+ break;
+ case RES_UL_SPACE:
+ pItem = pImpl->GetULSpace(sal_True);
+ break;
+ case RES_SURROUND:
+ pItem = pImpl->GetSurround(sal_True);
+ break;
+ case FN_TEXT_RANGE:
+ {
+ const uno::Type rTextRangeType =
+ ::getCppuType((uno::Reference< text::XTextRange>*)0);
+ if(aValue.getValueType() == rTextRangeType)
+ {
+ uno::Reference< text::XTextRange > & rRange = pImpl->GetTextRange();
+ rRange = *(uno::Reference< text::XTextRange > *)aValue.getValue();
+ }
+ }
+ break;
+ case RES_OPAQUE :
+ pImpl->SetOpaque(*(sal_Bool*)aValue.getValue());
+ break;
+ // #i26791#
+ case RES_FOLLOW_TEXT_FLOW:
+ {
+ pItem = pImpl->GetFollowTextFlow( sal_True );
+ }
+ break;
+ // #i28701#
+ case RES_WRAP_INFLUENCE_ON_OBJPOS:
+ {
+ pItem = pImpl->GetWrapInfluenceOnObjPos( sal_True );
+ }
+ break;
+ // #i28749#
+ case FN_SHAPE_POSITION_LAYOUT_DIR :
+ {
+ sal_Int16 nPositionLayoutDir = 0;
+ aValue >>= nPositionLayoutDir;
+ pImpl->SetPositionLayoutDir( nPositionLayoutDir );
+ }
+ break;
+ }
+ if(pItem)
+ ((SfxPoolItem*)pItem)->PutValue(aValue, pEntry->nMemberId);
+ }
+ }
+ else
+ {
+ uno::Reference< beans::XPropertySet > xPrSet;
+ const uno::Type& rPSetType =
+ ::getCppuType((const uno::Reference< beans::XPropertySet >*)0);
+ uno::Any aPSet = xShapeAgg->queryAggregation(rPSetType);
+ if(aPSet.getValueType() != rPSetType || !aPSet.getValue())
+ throw uno::RuntimeException();
+ xPrSet = *(uno::Reference< beans::XPropertySet >*)aPSet.getValue();
+ // #i31698# - setting the caption point of a
+ // caption object doesn't have to change the object position.
+ // Thus, keep the position, before the caption point is set and
+ // restore it afterwards.
+ awt::Point aKeepedPosition( 0, 0 );
+ if ( rPropertyName.equals(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("CaptionPoint"))) &&
+ getShapeType().equals(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.drawing.CaptionShape"))) )
+ {
+ aKeepedPosition = getPosition();
+ }
+ if( pFmt && pFmt->GetDoc()->GetCurrentViewShell() ) //swmod 071108//swmod 071225
+ {
+ UnoActionContext aCtx(pFmt->GetDoc());
+ xPrSet->setPropertyValue(rPropertyName, aValue);
+ }
+ else
+ xPrSet->setPropertyValue(rPropertyName, aValue);
+ // #i31698# - restore object position, if caption point is set.
+ if ( rPropertyName.equals(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("CaptionPoint"))) &&
+ getShapeType().equals(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.drawing.CaptionShape"))) )
+ {
+ setPosition( aKeepedPosition );
+ }
+ }
+ }
+}
+
+uno::Any SwXShape::getPropertyValue(const rtl::OUString& rPropertyName)
+ throw( beans::UnknownPropertyException, lang::WrappedTargetException,
+ uno::RuntimeException )
+{
+ SolarMutexGuard aGuard;
+ uno::Any aRet;
+ SwFrmFmt* pFmt = GetFrmFmt();
+ if(xShapeAgg.is())
+ {
+ const SfxItemPropertySimpleEntry* pEntry = m_pPropSet->getPropertyMap()->getByName( rPropertyName );
+ if(pEntry)
+ {
+ if(pFmt)
+ {
+ if(RES_OPAQUE == pEntry->nWID)
+ {
+ SvxShape* pSvxShape = GetSvxShape();
+ DBG_ASSERT(pSvxShape, "No SvxShape found!");
+ if(pSvxShape)
+ {
+ SdrObject* pObj = pSvxShape->GetSdrObject();
+ // consider invisible layers
+ sal_Bool bOpaque =
+ ( pObj->GetLayer() != pFmt->GetDoc()->GetHellId() &&
+ pObj->GetLayer() != pFmt->GetDoc()->GetInvisibleHellId() );
+ aRet.setValue(&bOpaque, ::getBooleanCppuType());
+ }
+ }
+ else if(FN_ANCHOR_POSITION == pEntry->nWID)
+ {
+ SvxShape* pSvxShape = GetSvxShape();
+ DBG_ASSERT(pSvxShape, "No SvxShape found!");
+ if(pSvxShape)
+ {
+ SdrObject* pObj = pSvxShape->GetSdrObject();
+ Point aPt = pObj->GetAnchorPos();
+ awt::Point aPoint( TWIP_TO_MM100( aPt.X() ),
+ TWIP_TO_MM100( aPt.Y() ) );
+ aRet.setValue(&aPoint, ::getCppuType( (awt::Point*)0 ));
+ }
+ }
+ // #i26791# - special handling for FN_TEXT_RANGE
+ else if ( FN_TEXT_RANGE == pEntry->nWID )
+ {
+ const SwFmtAnchor aAnchor = pFmt->GetAnchor();
+ if (aAnchor.GetAnchorId() == FLY_AT_PAGE)
+ {
+ // return nothing, because property <TextRange> isn't
+ // valid for to-page anchored shapes
+ uno::Any aAny;
+ aRet = aAny;
+ }
+ else
+ {
+ if ( aAnchor.GetCntntAnchor() )
+ {
+ const uno::Reference< text::XTextRange > xTextRange
+ = SwXTextRange::CreateXTextRange(
+ *pFmt->GetDoc(),
+ *aAnchor.GetCntntAnchor(),
+ 0L );
+ aRet.setValue(&xTextRange, ::getCppuType((uno::Reference<text::XTextRange>*)0));
+ }
+ else
+ {
+ // return nothing
+ uno::Any aAny;
+ aRet = aAny;
+ }
+ }
+ }
+ // #i28749#
+ else if ( FN_SHAPE_TRANSFORMATION_IN_HORI_L2R == pEntry->nWID )
+ {
+ // get property <::drawing::Shape::Transformation>
+ // without conversion to layout direction as below
+ aRet = _getPropAtAggrObj( rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Transformation")) );
+ }
+ else if ( FN_SHAPE_POSITION_LAYOUT_DIR == pEntry->nWID )
+ {
+ aRet <<= pFmt->GetPositionLayoutDir();
+ }
+ // #i36248#
+ else if ( FN_SHAPE_STARTPOSITION_IN_HORI_L2R == pEntry->nWID )
+ {
+ // get property <::drawing::Shape::StartPosition>
+ // without conversion to layout direction as below
+ aRet = _getPropAtAggrObj( rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("StartPosition")) );
+ }
+ else if ( FN_SHAPE_ENDPOSITION_IN_HORI_L2R == pEntry->nWID )
+ {
+ // get property <::drawing::Shape::EndPosition>
+ // without conversion to layout direction as below
+ aRet = _getPropAtAggrObj( rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("EndPosition")) );
+ }
+ else
+ {
+ const SwAttrSet& rSet = pFmt->GetAttrSet();
+ m_pPropSet->getPropertyValue(*pEntry, rSet, aRet);
+ }
+ }
+ else
+ {
+ SfxPoolItem* pItem = 0;
+ switch(pEntry->nWID)
+ {
+ case RES_ANCHOR:
+ pItem = pImpl->GetAnchor();
+ break;
+ case RES_HORI_ORIENT:
+ pItem = pImpl->GetHOrient();
+ break;
+ case RES_VERT_ORIENT:
+ pItem = pImpl->GetVOrient();
+ break;
+ case RES_LR_SPACE:
+ pItem = pImpl->GetLRSpace();
+ break;
+ case RES_UL_SPACE:
+ pItem = pImpl->GetULSpace();
+ break;
+ case RES_SURROUND:
+ pItem = pImpl->GetSurround();
+ break;
+ case FN_TEXT_RANGE :
+ aRet.setValue(&pImpl->GetTextRange(), ::getCppuType((uno::Reference<text::XTextRange>*)0));
+ break;
+ case RES_OPAQUE :
+ aRet.setValue(&pImpl->GetOpaque(), ::getBooleanCppuType());
+ break;
+ case FN_ANCHOR_POSITION :
+ {
+ awt::Point aPoint;
+ aRet.setValue(&aPoint, ::getCppuType( (awt::Point*)0 ));
+ }
+ break;
+ // #i26791#
+ case RES_FOLLOW_TEXT_FLOW :
+ {
+ pItem = pImpl->GetFollowTextFlow();
+ }
+ break;
+ // #i28701#
+ case RES_WRAP_INFLUENCE_ON_OBJPOS:
+ {
+ pItem = pImpl->GetWrapInfluenceOnObjPos();
+ }
+ break;
+ // #i28749#
+ case FN_SHAPE_TRANSFORMATION_IN_HORI_L2R:
+ {
+ // get property <::drawing::Shape::Transformation>
+ // without conversion to layout direction as below
+ aRet = _getPropAtAggrObj( rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Transformation")) );
+ }
+ break;
+ case FN_SHAPE_POSITION_LAYOUT_DIR:
+ {
+ aRet <<= pImpl->GetPositionLayoutDir();
+ }
+ break;
+ // #i36248#
+ case FN_SHAPE_STARTPOSITION_IN_HORI_L2R:
+ {
+ // get property <::drawing::Shape::StartPosition>
+ // without conversion to layout direction as below
+ aRet = _getPropAtAggrObj( rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("StartPosition")) );
+ }
+ break;
+ case FN_SHAPE_ENDPOSITION_IN_HORI_L2R:
+ {
+ // get property <::drawing::Shape::StartPosition>
+ // without conversion to layout direction as below
+ aRet = _getPropAtAggrObj( rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("EndPosition")) );
+ }
+ break;
+ }
+ if(pItem)
+ pItem->QueryValue(aRet, pEntry->nMemberId);
+ }
+ }
+ else
+ {
+ aRet = _getPropAtAggrObj( rPropertyName );
+
+ // #i31698# - convert the position (translation)
+ // of the drawing object in the transformation
+ if ( rPropertyName.equals(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Transformation"))) )
+ {
+ drawing::HomogenMatrix3 aMatrix;
+ aRet >>= aMatrix;
+ aRet <<= _ConvertTransformationToLayoutDir( aMatrix );
+ }
+ // #i36248#
+ else if ( rPropertyName.equals(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("StartPosition"))) )
+ {
+ awt::Point aStartPos;
+ aRet >>= aStartPos;
+ // #i59051#
+ aRet <<= _ConvertStartOrEndPosToLayoutDir( aStartPos );
+ }
+ else if ( rPropertyName.equals(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("EndPosition"))) )
+ {
+ awt::Point aEndPos;
+ aRet >>= aEndPos;
+ // #i59051#
+ aRet <<= _ConvertStartOrEndPosToLayoutDir( aEndPos );
+ }
+ // #i59051#
+ else if ( rPropertyName.equals(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("PolyPolygonBezier"))) )
+ {
+ drawing::PolyPolygonBezierCoords aPath;
+ aRet >>= aPath;
+ aRet <<= _ConvertPolyPolygonBezierToLayoutDir( aPath );
+ }
+ }
+ }
+ return aRet;
+}
+
+uno::Any SwXShape::_getPropAtAggrObj( const ::rtl::OUString& _rPropertyName )
+ throw( beans::UnknownPropertyException, lang::WrappedTargetException,
+ uno::RuntimeException )
+{
+ uno::Any aRet;
+
+ uno::Reference< beans::XPropertySet > xPrSet;
+ const uno::Type& rPSetType =
+ ::getCppuType((const uno::Reference< beans::XPropertySet >*)0);
+ uno::Any aPSet = xShapeAgg->queryAggregation(rPSetType);
+ if ( aPSet.getValueType() != rPSetType || !aPSet.getValue() )
+ {
+ throw uno::RuntimeException();
+ }
+ xPrSet = *(uno::Reference< beans::XPropertySet >*)aPSet.getValue();
+ aRet = xPrSet->getPropertyValue( _rPropertyName );
+
+ return aRet;
+}
+
+beans::PropertyState SwXShape::getPropertyState( const rtl::OUString& rPropertyName )
+ throw(beans::UnknownPropertyException, uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+ uno::Sequence< rtl::OUString > aNames(1);
+ rtl::OUString* pStrings = aNames.getArray();
+ pStrings[0] = rPropertyName;
+ uno::Sequence< beans::PropertyState > aStates = getPropertyStates(aNames);
+ return aStates.getConstArray()[0];
+}
+
+uno::Sequence< beans::PropertyState > SwXShape::getPropertyStates(
+ const uno::Sequence< rtl::OUString >& aPropertyNames )
+ throw(beans::UnknownPropertyException, uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+ SwFrmFmt* pFmt = GetFrmFmt();
+ uno::Sequence< beans::PropertyState > aRet(aPropertyNames.getLength());
+ if(xShapeAgg.is())
+ {
+ SvxShape* pSvxShape = GetSvxShape();
+ sal_Bool bGroupMember = sal_False;
+ sal_Bool bFormControl = sal_False;
+ SdrObject* pObject = pSvxShape->GetSdrObject();
+ if(pObject)
+ {
+ bGroupMember = pObject->GetUpGroup() != 0;
+ bFormControl = pObject->GetObjInventor() == FmFormInventor;
+ }
+ const rtl::OUString* pNames = aPropertyNames.getConstArray();
+ beans::PropertyState* pRet = aRet.getArray();
+ uno::Reference< XPropertyState > xShapePrState;
+ for(sal_Int32 nProperty = 0; nProperty < aPropertyNames.getLength(); nProperty++)
+ {
+ const SfxItemPropertySimpleEntry* pEntry = m_pPropSet->getPropertyMap()->getByName( pNames[nProperty] );
+ if(pEntry)
+ {
+ if(RES_OPAQUE == pEntry->nWID)
+ pRet[nProperty] = bFormControl ?
+ beans::PropertyState_DEFAULT_VALUE : beans::PropertyState_DIRECT_VALUE;
+ else if(FN_ANCHOR_POSITION == pEntry->nWID)
+ pRet[nProperty] = beans::PropertyState_DIRECT_VALUE;
+ else if(FN_TEXT_RANGE == pEntry->nWID)
+ pRet[nProperty] = beans::PropertyState_DIRECT_VALUE;
+ else if(bGroupMember)
+ pRet[nProperty] = beans::PropertyState_DEFAULT_VALUE;
+ else if(pFmt)
+ {
+ const SwAttrSet& rSet = pFmt->GetAttrSet();
+ SfxItemState eItemState = rSet.GetItemState(pEntry->nWID, sal_False);
+
+ if(SFX_ITEM_SET == eItemState)
+ pRet[nProperty] = beans::PropertyState_DIRECT_VALUE;
+ else if(SFX_ITEM_DEFAULT == eItemState)
+ pRet[nProperty] = beans::PropertyState_DEFAULT_VALUE;
+ else
+ pRet[nProperty] = beans::PropertyState_AMBIGUOUS_VALUE;
+ }
+ else
+ {
+ SfxPoolItem* pItem = 0;
+ switch(pEntry->nWID)
+ {
+ case RES_ANCHOR:
+ pItem = pImpl->GetAnchor();
+ break;
+ case RES_HORI_ORIENT:
+ pItem = pImpl->GetHOrient();
+ break;
+ case RES_VERT_ORIENT:
+ pItem = pImpl->GetVOrient();
+ break;
+ case RES_LR_SPACE:
+ pItem = pImpl->GetLRSpace();
+ break;
+ case RES_UL_SPACE:
+ pItem = pImpl->GetULSpace();
+ break;
+ case RES_SURROUND:
+ pItem = pImpl->GetSurround();
+ break;
+ // #i28701#
+ case RES_WRAP_INFLUENCE_ON_OBJPOS:
+ {
+ pItem = pImpl->GetWrapInfluenceOnObjPos();
+ }
+ break;
+ }
+ if(pItem)
+ pRet[nProperty] = beans::PropertyState_DIRECT_VALUE;
+ else
+ pRet[nProperty] = beans::PropertyState_DEFAULT_VALUE;
+ }
+ }
+ else
+ {
+ if(!xShapePrState.is())
+ {
+ const uno::Type& rPStateType = ::getCppuType((uno::Reference< XPropertyState >*)0);
+ uno::Any aPState = xShapeAgg->queryAggregation(rPStateType);
+ if(aPState.getValueType() != rPStateType || !aPState.getValue())
+ throw uno::RuntimeException();
+ xShapePrState = *(uno::Reference< XPropertyState >*)aPState.getValue();
+ }
+ pRet[nProperty] = xShapePrState->getPropertyState(pNames[nProperty]);
+ }
+ }
+ }
+ else
+ throw uno::RuntimeException();
+ return aRet;
+}
+
+void SwXShape::setPropertyToDefault( const rtl::OUString& rPropertyName )
+ throw(beans::UnknownPropertyException, uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+ SwFrmFmt* pFmt = GetFrmFmt();
+ if(xShapeAgg.is())
+ {
+ const SfxItemPropertySimpleEntry* pEntry = m_pPropSet->getPropertyMap()->getByName( rPropertyName );
+ if(pEntry)
+ {
+ if ( pEntry->nFlags & beans::PropertyAttribute::READONLY)
+ throw uno::RuntimeException( rtl::OUString ( RTL_CONSTASCII_USTRINGPARAM ( "Property is read-only: " ) ) + rPropertyName, static_cast < cppu::OWeakObject * > ( this ) );
+ if(pFmt)
+ {
+ const SfxItemSet& rSet = pFmt->GetAttrSet();
+ SfxItemSet aSet(pFmt->GetDoc()->GetAttrPool(), pEntry->nWID, pEntry->nWID);
+ aSet.SetParent(&rSet);
+ aSet.ClearItem(pEntry->nWID);
+ pFmt->GetDoc()->SetAttr(aSet, *pFmt);
+ }
+ else
+ {
+ switch(pEntry->nWID)
+ {
+ case RES_ANCHOR: pImpl->RemoveAnchor(); break;
+ case RES_HORI_ORIENT: pImpl->RemoveHOrient(); break;
+ case RES_VERT_ORIENT: pImpl->RemoveVOrient(); break;
+ case RES_LR_SPACE: pImpl->RemoveLRSpace(); break;
+ case RES_UL_SPACE: pImpl->RemoveULSpace(); break;
+ case RES_SURROUND: pImpl->RemoveSurround();break;
+ case RES_OPAQUE : pImpl->SetOpaque(sal_False); break;
+ case FN_TEXT_RANGE :
+ break;
+ // #i26791#
+ case RES_FOLLOW_TEXT_FLOW:
+ {
+ pImpl->RemoveFollowTextFlow();
+ }
+ break;
+ // #i28701#
+ case RES_WRAP_INFLUENCE_ON_OBJPOS:
+ {
+ pImpl->RemoveWrapInfluenceOnObjPos();
+ }
+ break;
+ }
+ }
+ }
+ else
+ {
+ const uno::Type& rPStateType = ::getCppuType((uno::Reference< XPropertyState >*)0);
+ uno::Any aPState = xShapeAgg->queryAggregation(rPStateType);
+ if(aPState.getValueType() != rPStateType || !aPState.getValue())
+ throw uno::RuntimeException();
+ uno::Reference< XPropertyState > xShapePrState = *(uno::Reference< XPropertyState >*)aPState.getValue();
+ xShapePrState->setPropertyToDefault( rPropertyName );
+ }
+ }
+ else
+ throw uno::RuntimeException();
+}
+
+uno::Any SwXShape::getPropertyDefault( const rtl::OUString& rPropertyName )
+ throw( beans::UnknownPropertyException, lang::WrappedTargetException,
+ uno::RuntimeException )
+{
+ SolarMutexGuard aGuard;
+ SwFrmFmt* pFmt = GetFrmFmt();
+ uno::Any aRet;
+ if(xShapeAgg.is())
+ {
+ const SfxItemPropertySimpleEntry* pEntry = m_pPropSet->getPropertyMap()->getByName( rPropertyName );
+ if(pEntry)
+ {
+ if(pEntry->nWID < RES_FRMATR_END && pFmt)
+ {
+ const SfxPoolItem& rDefItem =
+ pFmt->GetDoc()->GetAttrPool().GetDefaultItem(pEntry->nWID);
+ rDefItem.QueryValue(aRet, pEntry->nMemberId);
+ }
+ else
+ throw uno::RuntimeException();
+ }
+ else
+ {
+ const uno::Type& rPStateType = ::getCppuType((uno::Reference< XPropertyState >*)0);
+ uno::Any aPState = xShapeAgg->queryAggregation(rPStateType);
+ if(aPState.getValueType() != rPStateType || !aPState.getValue())
+ throw uno::RuntimeException();
+ uno::Reference< XPropertyState > xShapePrState = *(uno::Reference< XPropertyState >*)aPState.getValue();
+ xShapePrState->getPropertyDefault( rPropertyName );
+ }
+ }
+ else
+ throw uno::RuntimeException();
+ return aRet;
+}
+
+void SwXShape::addPropertyChangeListener(
+ const rtl::OUString& _propertyName,
+ const uno::Reference< beans::XPropertyChangeListener > & _listener )
+ throw( beans::UnknownPropertyException, lang::WrappedTargetException,
+ uno::RuntimeException )
+{
+ if ( !xShapeAgg.is() )
+ throw uno::RuntimeException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "no shape aggregate" ) ), *this );
+
+ // must be handled by the aggregate
+ uno::Reference< beans::XPropertySet > xShapeProps;
+ if ( xShapeAgg->queryAggregation( beans::XPropertySet::static_type() ) >>= xShapeProps )
+ xShapeProps->addPropertyChangeListener( _propertyName, _listener );
+}
+
+void SwXShape::removePropertyChangeListener(
+ const rtl::OUString& _propertyName,
+ const uno::Reference< beans::XPropertyChangeListener > & _listener)
+ throw( beans::UnknownPropertyException, lang::WrappedTargetException,
+ uno::RuntimeException )
+{
+ if ( !xShapeAgg.is() )
+ throw uno::RuntimeException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "no shape aggregate" ) ), *this );
+
+ // must be handled by the aggregate
+ uno::Reference< beans::XPropertySet > xShapeProps;
+ if ( xShapeAgg->queryAggregation( beans::XPropertySet::static_type() ) >>= xShapeProps )
+ xShapeProps->removePropertyChangeListener( _propertyName, _listener );
+}
+
+void SwXShape::addVetoableChangeListener(
+ const rtl::OUString& /*PropertyName*/,
+ const uno::Reference< beans::XVetoableChangeListener > & /*aListener*/ )
+ throw( beans::UnknownPropertyException, lang::WrappedTargetException,
+ uno::RuntimeException )
+{
+ DBG_WARNING("not implemented");
+}
+
+void SwXShape::removeVetoableChangeListener(
+ const rtl::OUString& /*PropertyName*/,
+ const uno::Reference< beans::XVetoableChangeListener > & /*aListener*/)
+ throw( beans::UnknownPropertyException, lang::WrappedTargetException,
+ uno::RuntimeException )
+{
+ DBG_WARNING("not implemented");
+}
+
+void SwXShape::Modify( const SfxPoolItem* pOld, const SfxPoolItem *pNew)
+{
+ ClientModify(this, pOld, pNew);
+}
+
+void SwXShape::attach(const uno::Reference< text::XTextRange > & xTextRange)
+ throw( lang::IllegalArgumentException, uno::RuntimeException )
+{
+ SolarMutexGuard aGuard;
+
+ // get access to SwDoc
+ // (see also SwXTextRange::XTextRangeToSwPaM)
+ SwDoc* pDoc = 0;
+ uno::Reference<lang::XUnoTunnel> xRangeTunnel( xTextRange, uno::UNO_QUERY);
+ if(xRangeTunnel.is())
+ {
+ SwXTextRange* pRange = 0;
+ OTextCursorHelper* pCursor = 0;
+ SwXTextPortion* pPortion = 0;
+ SwXText* pText = 0;
+ SwXParagraph* pParagraph = 0;
+
+ pRange = reinterpret_cast< SwXTextRange * >(
+ sal::static_int_cast< sal_IntPtr >( xRangeTunnel->getSomething( SwXTextRange::getUnoTunnelId()) ));
+ pText = reinterpret_cast< SwXText * >(
+ sal::static_int_cast< sal_IntPtr >( xRangeTunnel->getSomething( SwXText::getUnoTunnelId()) ));
+ pCursor = reinterpret_cast< OTextCursorHelper * >(
+ sal::static_int_cast< sal_IntPtr >( xRangeTunnel->getSomething( OTextCursorHelper::getUnoTunnelId()) ));
+ pPortion = reinterpret_cast< SwXTextPortion * >(
+ sal::static_int_cast< sal_IntPtr >( xRangeTunnel->getSomething( SwXTextPortion::getUnoTunnelId()) ));
+ pParagraph = reinterpret_cast< SwXParagraph * >(
+ sal::static_int_cast< sal_IntPtr >( xRangeTunnel->getSomething( SwXParagraph::getUnoTunnelId( ) ) ) );
+
+ if (pRange)
+ pDoc = pRange->GetDoc();
+ else if (!pDoc && pText)
+ pDoc = pText->GetDoc();
+ else if (!pDoc && pCursor)
+ pDoc = pCursor->GetDoc();
+ else if ( !pDoc && pPortion && pPortion->GetCursor() )
+ {
+ pDoc = pPortion->GetCursor()->GetDoc();
+ }
+ else if ( !pDoc && pParagraph && pParagraph->GetTxtNode( ) )
+ {
+ pDoc = const_cast<SwDoc*>(pParagraph->GetTxtNode()->GetDoc());
+ }
+
+ }
+
+ if(!pDoc)
+ throw uno::RuntimeException();
+ SwDocShell *pDocSh = pDoc->GetDocShell();
+ if (pDocSh)
+ {
+ uno::Reference< frame::XModel > xModel;
+ xModel = pDocSh->GetModel();
+ uno::Reference< drawing::XDrawPageSupplier > xDPS(xModel, uno::UNO_QUERY);
+ if (xDPS.is())
+ {
+ uno::Reference< drawing::XDrawPage > xDP( xDPS->getDrawPage() );
+ if (xDP.is())
+ {
+ uno::Any aPos;
+ aPos <<= xTextRange;
+ setPropertyValue(S2U("TextRange"), aPos);
+ uno::Reference< drawing::XShape > xTemp( (cppu::OWeakObject*) this, uno::UNO_QUERY );
+ xDP->add( xTemp );
+ }
+ }
+ }
+}
+
+uno::Reference< text::XTextRange > SwXShape::getAnchor(void) throw( uno::RuntimeException )
+{
+ SolarMutexGuard aGuard;
+ uno::Reference< text::XTextRange > aRef;
+ SwFrmFmt* pFmt = GetFrmFmt();
+ if(pFmt)
+ {
+ const SwFmtAnchor& rAnchor = pFmt->GetAnchor();
+ // return an anchor for non-page bound frames
+ // and for page bound frames that have a page no == NULL and a content position
+ if ((rAnchor.GetAnchorId() != FLY_AT_PAGE) ||
+ (rAnchor.GetCntntAnchor() && !rAnchor.GetPageNum()))
+ {
+ const SwPosition &rPos = *(pFmt->GetAnchor().GetCntntAnchor());
+ aRef = SwXTextRange::CreateXTextRange(*pFmt->GetDoc(), rPos, 0);
+ }
+ }
+ else
+ aRef = pImpl->GetTextRange();
+ return aRef;
+}
+
+void SwXShape::dispose(void) throw( uno::RuntimeException )
+{
+ SolarMutexGuard aGuard;
+ SwFrmFmt* pFmt = GetFrmFmt();
+ if(pFmt)
+ {
+ // determine correct <SdrObject>
+ SdrObject* pObj = GetSvxShape()->GetSdrObject();
+ // safety assertion:
+ // <pObj> must be the same as <pFmt->FindSdrObject()>, if <pObj> isn't
+ // a 'virtual' drawing object.
+ // correct assertion and refine it for safety reason.
+ OSL_ENSURE( !pObj ||
+ pObj->ISA(SwDrawVirtObj) ||
+ pObj->GetUpGroup() ||
+ pObj == pFmt->FindSdrObject(),
+ "<SwXShape::dispose(..) - different 'master' drawing objects!!" );
+ // perform delete of draw frame format *not*
+ // for 'virtual' drawing objects.
+ // no delete of draw format for members
+ // of a group
+ if ( pObj &&
+ !pObj->ISA(SwDrawVirtObj) &&
+ !pObj->GetUpGroup() &&
+ pObj->IsInserted() )
+ {
+ if (pFmt->GetAnchor().GetAnchorId() == FLY_AS_CHAR)
+ {
+ const SwPosition &rPos = *(pFmt->GetAnchor().GetCntntAnchor());
+ SwTxtNode *pTxtNode = rPos.nNode.GetNode().GetTxtNode();
+ const xub_StrLen nIdx = rPos.nContent.GetIndex();
+ pTxtNode->DeleteAttributes( RES_TXTATR_FLYCNT, nIdx );
+ }
+ else
+ pFmt->GetDoc()->DelLayoutFmt( pFmt );
+ }
+ }
+ if(xShapeAgg.is())
+ {
+ uno::Any aAgg(xShapeAgg->queryAggregation( ::getCppuType((uno::Reference<XComponent>*)0)));
+ uno::Reference<XComponent> xComp;
+ aAgg >>= xComp;
+ if(xComp.is())
+ xComp->dispose();
+ }
+}
+
+void SwXShape::addEventListener(
+ const uno::Reference< lang::XEventListener > & aListener)
+ throw( uno::RuntimeException )
+{
+ uno::Reference< lang::XUnoTunnel > xShapeTunnel(xShapeAgg, uno::UNO_QUERY);
+ SvxShape* pSvxShape = GetSvxShape();
+ if(pSvxShape)
+ pSvxShape->addEventListener(aListener);
+}
+
+void SwXShape::removeEventListener(
+ const uno::Reference< lang::XEventListener > & aListener)
+ throw( uno::RuntimeException )
+{
+ SvxShape* pSvxShape = GetSvxShape();
+ if(pSvxShape)
+ pSvxShape->removeEventListener(aListener);
+}
+
+rtl::OUString SwXShape::getImplementationName(void) throw( uno::RuntimeException )
+{
+ return C2U("SwXShape");
+}
+
+sal_Bool SwXShape::supportsService(const rtl::OUString& rServiceName) throw( uno::RuntimeException )
+{
+ sal_Bool bRet = sal_False;
+ if(COMPARE_EQUAL == rServiceName.compareToAscii("com.sun.star.drawing.Shape"))
+ bRet = sal_True;
+ else if(xShapeAgg.is())
+ {
+ uno::Reference< lang::XUnoTunnel > xShapeTunnel(xShapeAgg, uno::UNO_QUERY);
+ SvxShape* pSvxShape = GetSvxShape();
+ bRet = pSvxShape->supportsService(rServiceName);
+ }
+ return bRet;
+}
+
+uno::Sequence< rtl::OUString > SwXShape::getSupportedServiceNames(void) throw( uno::RuntimeException )
+{
+ uno::Sequence< rtl::OUString > aSeq;
+ if(xShapeAgg.is())
+ {
+ uno::Reference< lang::XUnoTunnel > xShapeTunnel(xShapeAgg, uno::UNO_QUERY);
+ SvxShape* pSvxShape = GetSvxShape();
+ if(pSvxShape)
+ aSeq = pSvxShape->getSupportedServiceNames();
+ }
+ else
+ {
+ aSeq.realloc(1);
+ aSeq.getArray()[0] = C2U("com.sun.star.drawing.Shape");
+ }
+ return aSeq;
+}
+
+SvxShape* SwXShape::GetSvxShape()
+{
+ SvxShape* pSvxShape = 0;
+ if(xShapeAgg.is())
+ {
+ uno::Reference< lang::XUnoTunnel > xShapeTunnel(xShapeAgg, uno::UNO_QUERY);
+ if(xShapeTunnel.is())
+ pSvxShape = reinterpret_cast< SvxShape * >(
+ sal::static_int_cast< sal_IntPtr >( xShapeTunnel->getSomething(SvxShape::getUnoTunnelId()) ));
+ }
+ return pSvxShape;
+}
+
+// #i31698#
+// implementation of virtual methods from drawing::XShape
+awt::Point SAL_CALL SwXShape::getPosition() throw ( uno::RuntimeException )
+{
+ awt::Point aPos( _GetAttrPosition() );
+
+ // handle group members
+ SvxShape* pSvxShape = GetSvxShape();
+ if ( pSvxShape )
+ {
+ SdrObject* pTopGroupObj = _GetTopGroupObj( pSvxShape );
+ if ( pTopGroupObj )
+ {
+ // #i34750# - get attribute position of top group
+ // shape and add offset between top group object and group member
+ uno::Reference< drawing::XShape > xGroupShape =
+ uno::Reference< drawing::XShape >( pTopGroupObj->getUnoShape(),
+ uno::UNO_QUERY );
+ aPos = xGroupShape->getPosition();
+ // add offset between top group object and group member
+ // to the determined attribute position
+ // #i34750#:
+ // consider the layout direction
+ const Rectangle aMemberObjRect = GetSvxShape()->GetSdrObject()->GetSnapRect();
+ const Rectangle aGroupObjRect = pTopGroupObj->GetSnapRect();
+ // #i53320# - relative position of group member and
+ // top group object is always given in horizontal left-to-right layout.
+ awt::Point aOffset( 0, 0 );
+ {
+ aOffset.X = ( aMemberObjRect.Left() - aGroupObjRect.Left() );
+ aOffset.Y = ( aMemberObjRect.Top() - aGroupObjRect.Top() );
+ }
+ aOffset.X = TWIP_TO_MM100(aOffset.X);
+ aOffset.Y = TWIP_TO_MM100(aOffset.Y);
+ aPos.X += aOffset.X;
+ aPos.Y += aOffset.Y;
+ }
+ }
+
+ return aPos;
+}
+
+void SAL_CALL SwXShape::setPosition( const awt::Point& aPosition )
+ throw ( uno::RuntimeException )
+{
+ SdrObject* pTopGroupObj = _GetTopGroupObj();
+ if ( !pTopGroupObj )
+ {
+ // #i37877# - no adjustment of position attributes,
+ // if the position also has to be applied at the drawing object and
+ // a contact object is already registered at the drawing object.
+ bool bApplyPosAtDrawObj(false);
+ bool bNoAdjustOfPosProp(false);
+ // #i35798# - apply position also to drawing object,
+ // if drawing object has no anchor position set.
+ if ( mxShape.is() )
+ {
+ SvxShape* pSvxShape = GetSvxShape();
+ if ( pSvxShape )
+ {
+ const SdrObject* pObj = pSvxShape->GetSdrObject();
+ if ( pObj &&
+ pObj->GetAnchorPos().X() == 0 &&
+ pObj->GetAnchorPos().Y() == 0 )
+ {
+ bApplyPosAtDrawObj = true;
+ if ( pObj->GetUserCall() &&
+ pObj->GetUserCall()->ISA(SwDrawContact) )
+ {
+ bNoAdjustOfPosProp = true;
+ }
+ }
+ }
+ }
+ // shape isn't a group member. Thus, set positioning attributes
+ if ( !bNoAdjustOfPosProp )
+ {
+ _AdjustPositionProperties( aPosition );
+ }
+ if ( bApplyPosAtDrawObj )
+ {
+ mxShape->setPosition( aPosition );
+ }
+ }
+ else if ( mxShape.is() )
+ {
+ // shape is a member of a group. Thus, set its position.
+ awt::Point aNewPos( aPosition );
+ // The given position is given in the according layout direction. Thus,
+ // it has to be converted to a position in horizontal left-to-right
+ // layout.
+ // convert given absolute attribute position in layout direction into
+ // position in horizontal left-to-right layout.
+ {
+ aNewPos = _ConvertPositionToHoriL2R( aNewPos, getSize() );
+ }
+ // Convert given absolute position in horizontal left-to-right
+ // layout into relative position in horizontal left-to-right layout.
+ uno::Reference< drawing::XShape > xGroupShape =
+ uno::Reference< drawing::XShape >( pTopGroupObj->getUnoShape(),
+ uno::UNO_QUERY );
+ {
+ // #i34750#
+ // use method <xGroupShape->getPosition()> to get the correct
+ // position of the top group object.
+ awt::Point aAttrPosInHoriL2R(
+ _ConvertPositionToHoriL2R( xGroupShape->getPosition(),
+ xGroupShape->getSize() ) );
+ aNewPos.X -= aAttrPosInHoriL2R.X;
+ aNewPos.Y -= aAttrPosInHoriL2R.Y;
+ }
+ // convert relative position in horizontal left-to-right layout into
+ // absolute position in horizontal left-to-right layout
+ {
+ // #i34750#
+ // use method <SvxShape->getPosition()> to get the correct
+ // 'Drawing layer' position of the top group shape.
+ uno::Reference< lang::XUnoTunnel > xGrpShapeTunnel(
+ pTopGroupObj->getUnoShape(),
+ uno::UNO_QUERY );
+ SvxShape* pSvxGroupShape = reinterpret_cast< SvxShape * >(
+ sal::static_int_cast< sal_IntPtr >( xGrpShapeTunnel->getSomething(SvxShape::getUnoTunnelId()) ));
+ const awt::Point aGroupPos = pSvxGroupShape->getPosition();
+ aNewPos.X += aGroupPos.X;
+ aNewPos.Y += aGroupPos.Y;
+ }
+ // set position
+ mxShape->setPosition( aNewPos );
+ }
+}
+
+awt::Size SAL_CALL SwXShape::getSize() throw ( uno::RuntimeException )
+{
+ awt::Size aSize;
+ if ( mxShape.is() )
+ {
+ aSize = mxShape->getSize();
+ }
+ return aSize;
+}
+
+void SAL_CALL SwXShape::setSize( const awt::Size& aSize )
+ throw ( beans::PropertyVetoException,
+ uno::RuntimeException )
+{
+ if ( mxShape.is() )
+ {
+ mxShape->setSize( aSize );
+ }
+}
+// #i31698#
+// implementation of virtual methods from drawing::XShapeDescriptor
+::rtl::OUString SAL_CALL SwXShape::getShapeType() throw ( uno::RuntimeException )
+{
+ ::rtl::OUString aType;
+ if ( mxShape.is() )
+ {
+ aType = mxShape->getShapeType();
+ }
+ return aType;
+}
+/** method to determine top group object
+ #i31698#
+*/
+SdrObject* SwXShape::_GetTopGroupObj( SvxShape* _pSvxShape )
+{
+ SdrObject* pTopGroupObj( 0L );
+
+ SvxShape* pSvxShape = _pSvxShape ? _pSvxShape : GetSvxShape();
+ if ( pSvxShape )
+ {
+ SdrObject* pSdrObj = pSvxShape->GetSdrObject();
+ if ( pSdrObj && pSdrObj->GetUpGroup() )
+ {
+ pTopGroupObj = pSdrObj->GetUpGroup();
+ while ( pTopGroupObj->GetUpGroup() )
+ {
+ pTopGroupObj = pTopGroupObj->GetUpGroup();
+ }
+ }
+ }
+
+ return pTopGroupObj;
+}
+
+/** method to determine position according to the positioning attributes
+ #i31698#
+*/
+awt::Point SwXShape::_GetAttrPosition()
+{
+ awt::Point aAttrPos;
+
+ uno::Any aHoriPos( getPropertyValue( rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("HoriOrientPosition")) ) );
+ aHoriPos >>= aAttrPos.X;
+ uno::Any aVertPos( getPropertyValue( rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("VertOrientPosition")) ) );
+ aVertPos >>= aAttrPos.Y;
+ // #i35798# - fallback, if attribute position is (0,0)
+ // and no anchor position is applied to the drawing object
+ SvxShape* pSvxShape = GetSvxShape();
+ if ( pSvxShape )
+ {
+ const SdrObject* pObj = pSvxShape->GetSdrObject();
+ if ( pObj &&
+ pObj->GetAnchorPos().X() == 0 &&
+ pObj->GetAnchorPos().Y() == 0 &&
+ aAttrPos.X == 0 && aAttrPos.Y == 0 )
+ {
+ const Rectangle aObjRect = pObj->GetSnapRect();
+ aAttrPos.X = TWIP_TO_MM100(aObjRect.Left());
+ aAttrPos.Y = TWIP_TO_MM100(aObjRect.Top());
+ }
+ }
+ // #i35007# - If drawing object is anchored as-character,
+ // it's x-position isn't sensible. Thus, return the x-position as zero in this case.
+ text::TextContentAnchorType eTextAnchorType =
+ text::TextContentAnchorType_AT_PARAGRAPH;
+ {
+ rtl::OUString sAnchorType( RTL_CONSTASCII_USTRINGPARAM( "AnchorType" ) );
+ uno::Any aAny = getPropertyValue( sAnchorType );
+ aAny >>= eTextAnchorType;
+ }
+ if ( eTextAnchorType == text::TextContentAnchorType_AS_CHARACTER )
+ {
+ aAttrPos.X = 0;
+ }
+
+ return aAttrPos;
+}
+
+/** method to convert the position (translation) of the drawing object to
+ the layout direction horizontal left-to-right.
+ #i31698#
+*/
+awt::Point SwXShape::_ConvertPositionToHoriL2R( const awt::Point _aObjPos,
+ const awt::Size _aObjSize )
+{
+ awt::Point aObjPosInHoriL2R( _aObjPos );
+
+ SwFrmFmt* pFrmFmt = GetFrmFmt();
+ if ( pFrmFmt )
+ {
+ SwFrmFmt::tLayoutDir eLayoutDir = pFrmFmt->GetLayoutDir();
+ switch ( eLayoutDir )
+ {
+ case SwFrmFmt::HORI_L2R:
+ {
+ // nothing to do
+ }
+ break;
+ case SwFrmFmt::HORI_R2L:
+ {
+ aObjPosInHoriL2R.X = -_aObjPos.X - _aObjSize.Width;
+ }
+ break;
+ case SwFrmFmt::VERT_R2L:
+ {
+ aObjPosInHoriL2R.X = -_aObjPos.Y - _aObjSize.Width;
+ aObjPosInHoriL2R.Y = _aObjPos.X;
+ }
+ break;
+ default:
+ {
+ OSL_FAIL( "<SwXShape::_ConvertPositionToHoriL2R(..)> - unsupported layout direction" );
+ }
+ }
+ }
+
+ return aObjPosInHoriL2R;
+}
+
+/** method to convert the transformation of the drawing object to the layout
+ direction, the drawing object is in
+ #i31698#
+*/
+drawing::HomogenMatrix3 SwXShape::_ConvertTransformationToLayoutDir(
+ drawing::HomogenMatrix3 _aMatrixInHoriL2R )
+{
+ drawing::HomogenMatrix3 aMatrix( _aMatrixInHoriL2R );
+
+ // #i44334#, #i44681# - direct manipulation of the
+ // tranformation structure isn't valid, if it contains rotation.
+ SvxShape* pSvxShape = GetSvxShape();
+ OSL_ENSURE( pSvxShape,
+ "<SwXShape::_ConvertTransformationToLayoutDir(..)> - no SvxShape found!");
+ if ( pSvxShape )
+ {
+ const SdrObject* pObj = pSvxShape->GetSdrObject();
+ OSL_ENSURE( pObj,
+ "<SwXShape::_ConvertTransformationToLayoutDir(..)> - no SdrObject found!");
+ if ( pObj )
+ {
+ // get position of object in Writer coordinate system.
+ awt::Point aPos( getPosition() );
+ // get position of object in Drawing layer coordinate system
+ const Point aTmpObjPos( pObj->GetSnapRect().TopLeft() );
+ const awt::Point aObjPos(
+ TWIP_TO_MM100( aTmpObjPos.X() - pObj->GetAnchorPos().X() ),
+ TWIP_TO_MM100( aTmpObjPos.Y() - pObj->GetAnchorPos().Y() ) );
+ // determine difference between these positions according to the
+ // Writer coordinate system
+ const awt::Point aTranslateDiff( aPos.X - aObjPos.X,
+ aPos.Y - aObjPos.Y );
+ // apply translation difference to transformation matrix.
+ if ( aTranslateDiff.X != 0 || aTranslateDiff.Y != 0 )
+ {
+ // #i73079# - use correct matrix type
+ ::basegfx::B2DHomMatrix aTempMatrix;
+
+ aTempMatrix.set(0, 0, aMatrix.Line1.Column1 );
+ aTempMatrix.set(0, 1, aMatrix.Line1.Column2 );
+ aTempMatrix.set(0, 2, aMatrix.Line1.Column3 );
+ aTempMatrix.set(1, 0, aMatrix.Line2.Column1 );
+ aTempMatrix.set(1, 1, aMatrix.Line2.Column2 );
+ aTempMatrix.set(1, 2, aMatrix.Line2.Column3 );
+ aTempMatrix.set(2, 0, aMatrix.Line3.Column1 );
+ aTempMatrix.set(2, 1, aMatrix.Line3.Column2 );
+ aTempMatrix.set(2, 2, aMatrix.Line3.Column3 );
+ // #i73079#
+ aTempMatrix.translate( aTranslateDiff.X, aTranslateDiff.Y );
+ aMatrix.Line1.Column1 = aTempMatrix.get(0, 0);
+ aMatrix.Line1.Column2 = aTempMatrix.get(0, 1);
+ aMatrix.Line1.Column3 = aTempMatrix.get(0, 2);
+ aMatrix.Line2.Column1 = aTempMatrix.get(1, 0);
+ aMatrix.Line2.Column2 = aTempMatrix.get(1, 1);
+ aMatrix.Line2.Column3 = aTempMatrix.get(1, 2);
+ aMatrix.Line3.Column1 = aTempMatrix.get(2, 0);
+ aMatrix.Line3.Column2 = aTempMatrix.get(2, 1);
+ aMatrix.Line3.Column3 = aTempMatrix.get(2, 2);
+ }
+ }
+ }
+
+ return aMatrix;
+}
+
+/** method to adjust the positioning properties
+ #i31698#
+*/
+void SwXShape::_AdjustPositionProperties( const awt::Point _aPosition )
+{
+ // handle x-position
+ // #i35007# - no handling of x-position, if drawing
+ // object is anchored as-character, because it doesn't make sense.
+ text::TextContentAnchorType eTextAnchorType =
+ text::TextContentAnchorType_AT_PARAGRAPH;
+ {
+ rtl::OUString sAnchorType( RTL_CONSTASCII_USTRINGPARAM( "AnchorType" ) );
+ uno::Any aAny = getPropertyValue( sAnchorType );
+ aAny >>= eTextAnchorType;
+ }
+ if ( eTextAnchorType != text::TextContentAnchorType_AS_CHARACTER )
+ {
+ // determine current x-postion
+ rtl::OUString aHoriPosPropStr( RTL_CONSTASCII_USTRINGPARAM("HoriOrientPosition") );
+ uno::Any aHoriPos( getPropertyValue( aHoriPosPropStr ) );
+ sal_Int32 dCurrX = 0;
+ aHoriPos >>= dCurrX;
+ // change x-position attribute, if needed
+ if ( dCurrX != _aPosition.X )
+ {
+ // adjust x-position orientation to text::HoriOrientation::NONE, if needed
+ // Note: has to be done before setting x-position attribute
+ rtl::OUString aHoriOrientPropStr( RTL_CONSTASCII_USTRINGPARAM("HoriOrient") );
+ uno::Any aHoriOrient( getPropertyValue( aHoriOrientPropStr ) );
+ sal_Int16 eHoriOrient;
+ if (aHoriOrient >>= eHoriOrient) // may be void
+ {
+ if ( eHoriOrient != text::HoriOrientation::NONE )
+ {
+ eHoriOrient = text::HoriOrientation::NONE;
+ aHoriOrient <<= eHoriOrient;
+ setPropertyValue( aHoriOrientPropStr, aHoriOrient );
+ }
+ }
+ // set x-position attribute
+ aHoriPos <<= _aPosition.X;
+ setPropertyValue( aHoriPosPropStr, aHoriPos );
+ }
+ }
+
+ // handle y-position
+ {
+ // determine current y-postion
+ rtl::OUString aVertPosPropStr( RTL_CONSTASCII_USTRINGPARAM("VertOrientPosition") );
+ uno::Any aVertPos( getPropertyValue( aVertPosPropStr ) );
+ sal_Int32 dCurrY = 0;
+ aVertPos >>= dCurrY;
+ // change y-position attribute, if needed
+ if ( dCurrY != _aPosition.Y )
+ {
+ // adjust y-position orientation to text::VertOrientation::NONE, if needed
+ // Note: has to be done before setting y-position attribute
+ rtl::OUString aVertOrientPropStr( RTL_CONSTASCII_USTRINGPARAM("VertOrient") );
+ uno::Any aVertOrient( getPropertyValue( aVertOrientPropStr ) );
+ sal_Int16 eVertOrient;
+ if (aVertOrient >>= eVertOrient) // may be void
+ {
+ if ( eVertOrient != text::VertOrientation::NONE )
+ {
+ eVertOrient = text::VertOrientation::NONE;
+ aVertOrient <<= eVertOrient;
+ setPropertyValue( aVertOrientPropStr, aVertOrient );
+ }
+ }
+ // set y-position attribute
+ aVertPos <<= _aPosition.Y;
+ setPropertyValue( aVertPosPropStr, aVertPos );
+ }
+ }
+}
+
+/** method to convert start or end position of the drawing object to the
+ Writer specific position, which is the attribute position in layout direction
+ #i59051#
+*/
+::com::sun::star::awt::Point SwXShape::_ConvertStartOrEndPosToLayoutDir(
+ const ::com::sun::star::awt::Point& aStartOrEndPos )
+{
+ awt::Point aConvertedPos( aStartOrEndPos );
+
+ SvxShape* pSvxShape = GetSvxShape();
+ OSL_ENSURE( pSvxShape,
+ "<SwXShape::_ConvertStartOrEndPosToLayoutDir(..)> - no SvxShape found!");
+ if ( pSvxShape )
+ {
+ const SdrObject* pObj = pSvxShape->GetSdrObject();
+ OSL_ENSURE( pObj,
+ "<SwXShape::_ConvertStartOrEndPosToLayoutDir(..)> - no SdrObject found!");
+ if ( pObj )
+ {
+ // get position of object in Writer coordinate system.
+ awt::Point aPos( getPosition() );
+ // get position of object in Drawing layer coordinate system
+ const Point aTmpObjPos( pObj->GetSnapRect().TopLeft() );
+ const awt::Point aObjPos(
+ TWIP_TO_MM100( aTmpObjPos.X() - pObj->GetAnchorPos().X() ),
+ TWIP_TO_MM100( aTmpObjPos.Y() - pObj->GetAnchorPos().Y() ) );
+ // determine difference between these positions according to the
+ // Writer coordinate system
+ const awt::Point aTranslateDiff( aPos.X - aObjPos.X,
+ aPos.Y - aObjPos.Y );
+ // apply translation difference to transformation matrix.
+ if ( aTranslateDiff.X != 0 || aTranslateDiff.Y != 0 )
+ {
+ aConvertedPos.X = aConvertedPos.X + aTranslateDiff.X;
+ aConvertedPos.Y = aConvertedPos.Y + aTranslateDiff.Y;
+ }
+ }
+ }
+
+ return aConvertedPos;
+}
+
+::com::sun::star::drawing::PolyPolygonBezierCoords SwXShape::_ConvertPolyPolygonBezierToLayoutDir(
+ const ::com::sun::star::drawing::PolyPolygonBezierCoords& aPath )
+{
+ drawing::PolyPolygonBezierCoords aConvertedPath( aPath );
+
+ SvxShape* pSvxShape = GetSvxShape();
+ OSL_ENSURE( pSvxShape,
+ "<SwXShape::_ConvertStartOrEndPosToLayoutDir(..)> - no SvxShape found!");
+ if ( pSvxShape )
+ {
+ const SdrObject* pObj = pSvxShape->GetSdrObject();
+ OSL_ENSURE( pObj,
+ "<SwXShape::_ConvertStartOrEndPosToLayoutDir(..)> - no SdrObject found!");
+ if ( pObj )
+ {
+ // get position of object in Writer coordinate system.
+ awt::Point aPos( getPosition() );
+ // get position of object in Drawing layer coordinate system
+ const Point aTmpObjPos( pObj->GetSnapRect().TopLeft() );
+ const awt::Point aObjPos(
+ TWIP_TO_MM100( aTmpObjPos.X() - pObj->GetAnchorPos().X() ),
+ TWIP_TO_MM100( aTmpObjPos.Y() - pObj->GetAnchorPos().Y() ) );
+ // determine difference between these positions according to the
+ // Writer coordinate system
+ const awt::Point aTranslateDiff( aPos.X - aObjPos.X,
+ aPos.Y - aObjPos.Y );
+ // apply translation difference to PolyPolygonBezier.
+ if ( aTranslateDiff.X != 0 || aTranslateDiff.Y != 0 )
+ {
+ const basegfx::B2DHomMatrix aMatrix(basegfx::tools::createTranslateB2DHomMatrix(
+ aTranslateDiff.X, aTranslateDiff.Y));
+
+ const sal_Int32 nOuterSequenceCount(aConvertedPath.Coordinates.getLength());
+ drawing::PointSequence* pInnerSequence = aConvertedPath.Coordinates.getArray();
+ for(sal_Int32 a(0); a < nOuterSequenceCount; a++)
+ {
+ const sal_Int32 nInnerSequenceCount(pInnerSequence->getLength());
+ awt::Point* pArray = pInnerSequence->getArray();
+
+ for(sal_Int32 b(0); b < nInnerSequenceCount; b++)
+ {
+ basegfx::B2DPoint aNewCoordinatePair(pArray->X, pArray->Y);
+ aNewCoordinatePair *= aMatrix;
+ pArray->X = basegfx::fround(aNewCoordinatePair.getX());
+ pArray->Y = basegfx::fround(aNewCoordinatePair.getY());
+ pArray++;
+ }
+ }
+ }
+ }
+ }
+
+ return aConvertedPath;
+}
+
+SwXGroupShape::SwXGroupShape(uno::Reference< XInterface > & xShape) :
+ SwXShape(xShape)
+{
+#if OSL_DEBUG_LEVEL > 1
+ uno::Reference<XShapes> xShapes(xShapeAgg, uno::UNO_QUERY);
+ DBG_ASSERT(xShapes.is(), "no SvxShape found or shape is not a group shape");
+#endif
+}
+
+SwXGroupShape::~SwXGroupShape()
+{
+}
+
+uno::Any SwXGroupShape::queryInterface( const uno::Type& rType ) throw(uno::RuntimeException)
+{
+ uno::Any aRet;
+ if(rType == ::getCppuType((uno::Reference<XShapes>*)0))
+ aRet <<= uno::Reference<XShapes>(this);
+ else
+ aRet = SwXShape::queryInterface(rType);
+ return aRet;
+}
+
+void SwXGroupShape::acquire( ) throw()
+{
+ SwXShape::acquire();
+}
+
+void SwXGroupShape::release( ) throw()
+{
+ SwXShape::release();
+}
+
+void SwXGroupShape::add( const uno::Reference< XShape >& xShape ) throw (uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+ SvxShape* pSvxShape = GetSvxShape();
+ SwFrmFmt* pFmt = GetFrmFmt();
+ if(pSvxShape && pFmt)
+ {
+ uno::Reference<XShapes> xShapes;
+ if( xShapeAgg.is() )
+ {
+ const uno::Type& rType = ::getCppuType((uno::Reference<XShapes>*)0 );
+ uno::Any aAgg = xShapeAgg->queryAggregation( rType );
+ aAgg >>= xShapes;
+ }
+ if(xShapes.is())
+ xShapes->add(xShape);
+ else
+ throw uno::RuntimeException();
+
+ uno::Reference<lang::XUnoTunnel> xTunnel(xShape, uno::UNO_QUERY);
+ SwXShape* pSwShape = 0;
+ if(xShape.is())
+ pSwShape = reinterpret_cast< SwXShape * >(
+ sal::static_int_cast< sal_IntPtr >( xTunnel->getSomething(SwXShape::getUnoTunnelId()) ));
+ if(pSwShape && pSwShape->m_bDescriptor)
+ {
+ SvxShape* pAddShape = reinterpret_cast< SvxShape * >(
+ sal::static_int_cast< sal_IntPtr >( xTunnel->getSomething(SvxShape::getUnoTunnelId()) ));
+ if(pAddShape)
+ {
+ SdrObject* pObj = pAddShape->GetSdrObject();
+ if(pObj)
+ {
+ SwDoc* pDoc = pFmt->GetDoc();
+ // set layer of new drawing
+ // object to corresponding invisible layer.
+ if( FmFormInventor != pObj->GetObjInventor())
+ {
+ pObj->SetLayer( pSwShape->pImpl->GetOpaque()
+ ? pDoc->GetInvisibleHeavenId()
+ : pDoc->GetInvisibleHellId() );
+ }
+ else
+ {
+ pObj->SetLayer(pDoc->GetInvisibleControlsId());
+ }
+ }
+ }
+ pSwShape->m_bDescriptor = sal_False;
+ //add the group member to the format of the group
+ SwFrmFmt* pShapeFmt = ::FindFrmFmt( pSvxShape->GetSdrObject() );
+ if(pShapeFmt)
+ pFmt->Add(pSwShape);
+ }
+ }
+ else
+ throw uno::RuntimeException();
+}
+
+void SwXGroupShape::remove( const uno::Reference< XShape >& xShape ) throw (uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+ uno::Reference<XShapes> xShapes;
+ if( xShapeAgg.is() )
+ {
+ const uno::Type& rType = ::getCppuType((uno::Reference<XShapes>*)0 );
+ uno::Any aAgg = xShapeAgg->queryAggregation( rType );
+ aAgg >>= xShapes;
+ }
+ if(!xShapes.is())
+ throw uno::RuntimeException();
+ xShapes->remove(xShape);
+}
+
+sal_Int32 SwXGroupShape::getCount(void) throw( uno::RuntimeException )
+{
+ SolarMutexGuard aGuard;
+ uno::Reference<XIndexAccess> xAcc;
+ if( xShapeAgg.is() )
+ {
+ const uno::Type& rType = ::getCppuType((uno::Reference<XIndexAccess>*)0 );
+ uno::Any aAgg = xShapeAgg->queryAggregation( rType );
+ aAgg >>= xAcc;
+ }
+ if(!xAcc.is())
+ throw uno::RuntimeException();
+ return xAcc->getCount();
+}
+
+uno::Any SwXGroupShape::getByIndex(sal_Int32 nIndex)
+ throw( lang::IndexOutOfBoundsException, lang::WrappedTargetException,
+ uno::RuntimeException )
+{
+ SolarMutexGuard aGuard;
+ uno::Reference<XIndexAccess> xAcc;
+ if( xShapeAgg.is() )
+ {
+ const uno::Type& rType = ::getCppuType((uno::Reference<XIndexAccess>*)0 );
+ uno::Any aAgg = xShapeAgg->queryAggregation( rType );
+ aAgg >>= xAcc;
+ }
+ if(!xAcc.is())
+ throw uno::RuntimeException();
+ return xAcc->getByIndex(nIndex);
+}
+
+uno::Type SwXGroupShape::getElementType( ) throw(uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+ uno::Reference<XIndexAccess> xAcc;
+ if( xShapeAgg.is() )
+ {
+ const uno::Type& rType = ::getCppuType((uno::Reference<XIndexAccess>*)0 );
+ uno::Any aAgg = xShapeAgg->queryAggregation( rType );
+ aAgg >>= xAcc;
+ }
+ if(!xAcc.is())
+ throw uno::RuntimeException();
+ return xAcc->getElementType();
+}
+
+sal_Bool SwXGroupShape::hasElements( ) throw(uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+ uno::Reference<XIndexAccess> xAcc;
+ if( xShapeAgg.is() )
+ {
+ const uno::Type& rType = ::getCppuType((uno::Reference<XIndexAccess>*)0 );
+ uno::Any aAgg = xShapeAgg->queryAggregation( rType );
+ aAgg >>= xAcc;
+ }
+ if(!xAcc.is())
+ throw uno::RuntimeException();
+ return xAcc->hasElements();
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/unocore/unoevent.cxx b/sw/source/core/unocore/unoevent.cxx
new file mode 100644
index 000000000000..c58728e40b68
--- /dev/null
+++ b/sw/source/core/unocore/unoevent.cxx
@@ -0,0 +1,331 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+
+// HINTIDs must be on top; it is required for the macitem.hxx header
+#include "hintids.hxx"
+#include "unoevent.hxx"
+#include "unoframe.hxx"
+#include "unostyle.hxx"
+#include "swevent.hxx"
+#include "docstyle.hxx"
+#include <svx/svxids.hrc>
+#include "fmtinfmt.hxx"
+#include <svl/macitem.hxx>
+#include <rtl/ustrbuf.hxx>
+#include <com/sun/star/beans/PropertyValue.hpp>
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::uno;
+
+using ::com::sun::star::container::NoSuchElementException;
+using ::com::sun::star::container::XNameReplace;
+using ::com::sun::star::lang::IllegalArgumentException;
+using ::com::sun::star::lang::WrappedTargetException;
+using ::com::sun::star::lang::XServiceInfo;
+using ::com::sun::star::beans::PropertyValue;
+using ::cppu::WeakImplHelper2;
+using ::rtl::OUString;
+using ::rtl::OUStringBuffer;
+
+
+const sal_Char sAPI_ServiceName[] = "com.sun.star.container.XNameReplace";
+const sal_Char sAPI_SwFrameEventDescriptor[] = "SwFrameEventDescriptor";
+const sal_Char sAPI_SwFrameStyleEventDescriptor[] =
+ "SwFrameStyleEventDescriptor";
+const sal_Char sAPI_SwDetachedEventDescriptor[] = "SwDetachedEventDescriptor";
+const sal_Char sAPI_SwHyperlinkEventDescriptor[] =
+ "SwHyperlinkEventDescriptor";
+const sal_Char sAPI_SwAutoTextEventDescriptor[] =
+ "SwAutoTextEventDescriptor";
+
+//
+// tables of allowed events for specific objects
+//
+
+const struct SvEventDescription aGraphicEvents[] =
+{
+ { SW_EVENT_OBJECT_SELECT, "OnSelect" },
+ { SFX_EVENT_MOUSEOVER_OBJECT, "OnMouseOver" },
+ { SFX_EVENT_MOUSECLICK_OBJECT, "OnClick" },
+ { SFX_EVENT_MOUSEOUT_OBJECT, "OnMouseOut" },
+ { SVX_EVENT_IMAGE_LOAD, "OnLoadDone" },
+ { SVX_EVENT_IMAGE_ABORT, "OnLoadCancel" },
+ { SVX_EVENT_IMAGE_ERROR, "OnLoadError" },
+ { 0, NULL }
+};
+
+const struct SvEventDescription aFrameEvents[] =
+{
+ { SW_EVENT_OBJECT_SELECT, "OnSelect" },
+ { SW_EVENT_FRM_KEYINPUT_ALPHA, "OnAlphaCharInput" },
+ { SW_EVENT_FRM_KEYINPUT_NOALPHA, "OnNonAlphaCharInput" },
+ { SW_EVENT_FRM_RESIZE, "OnResize" },
+ { SW_EVENT_FRM_MOVE, "OnMove" },
+ { SFX_EVENT_MOUSEOVER_OBJECT, "OnMouseOver" },
+ { SFX_EVENT_MOUSECLICK_OBJECT, "OnClick" },
+ { SFX_EVENT_MOUSEOUT_OBJECT, "OnMouseOut" },
+ { 0, NULL }
+};
+
+const struct SvEventDescription aOLEEvents[] =
+{
+ { SW_EVENT_OBJECT_SELECT, "OnSelect" },
+ { SFX_EVENT_MOUSEOVER_OBJECT, "OnMouseOver" },
+ { SFX_EVENT_MOUSECLICK_OBJECT, "OnClick" },
+ { SFX_EVENT_MOUSEOUT_OBJECT, "OnMouseOut" },
+ { 0, NULL }
+};
+
+const struct SvEventDescription aHyperlinkEvents[] =
+{
+ { SFX_EVENT_MOUSEOVER_OBJECT, "OnMouseOver" },
+ { SFX_EVENT_MOUSECLICK_OBJECT, "OnClick" },
+ { SFX_EVENT_MOUSEOUT_OBJECT, "OnMouseOut" },
+ { 0, NULL }
+};
+
+const struct SvEventDescription aAutotextEvents[] =
+{
+ { SW_EVENT_START_INS_GLOSSARY, "OnInsertStart" },
+ { SW_EVENT_END_INS_GLOSSARY, "OnInsertDone" },
+ { 0, NULL }
+};
+
+const struct SvEventDescription aFrameStyleEvents[] =
+{
+ { SW_EVENT_OBJECT_SELECT, "OnSelect" },
+ { SW_EVENT_FRM_KEYINPUT_ALPHA, "OnAlphaCharInput" },
+ { SW_EVENT_FRM_KEYINPUT_NOALPHA, "OnNonAlphaCharInput" },
+ { SW_EVENT_FRM_RESIZE, "OnResize" },
+ { SW_EVENT_FRM_MOVE, "OnMove" },
+ { SFX_EVENT_MOUSEOVER_OBJECT, "OnMouseOver" },
+ { SFX_EVENT_MOUSECLICK_OBJECT, "OnClick" },
+ { SFX_EVENT_MOUSEOUT_OBJECT, "OnMouseOut" },
+ { SVX_EVENT_IMAGE_LOAD, "OnLoadDone" },
+ { SVX_EVENT_IMAGE_ABORT, "OnLoadCancel" },
+ { SVX_EVENT_IMAGE_ERROR, "OnLoadError" },
+ { 0, NULL }
+};
+
+//
+// SwHyperlinkEventDescriptor
+//
+
+SwHyperlinkEventDescriptor::SwHyperlinkEventDescriptor() :
+ SvDetachedEventDescriptor(aHyperlinkEvents),
+ sImplName(RTL_CONSTASCII_USTRINGPARAM(sAPI_SwHyperlinkEventDescriptor))
+{
+}
+
+SwHyperlinkEventDescriptor::~SwHyperlinkEventDescriptor()
+{
+}
+
+OUString SwHyperlinkEventDescriptor::getImplementationName(void)
+ throw( RuntimeException )
+{
+ return sImplName;
+}
+
+void SwHyperlinkEventDescriptor::copyMacrosFromINetFmt(
+ const SwFmtINetFmt& aFmt)
+{
+ for(sal_Int16 i = 0; mpSupportedMacroItems[i].mnEvent != 0; i++)
+ {
+ sal_uInt16 nEvent = mpSupportedMacroItems[i].mnEvent;
+ const SvxMacro* aMacro = aFmt.GetMacro(nEvent);
+ if (NULL != aMacro)
+ replaceByName(nEvent, *aMacro);
+ }
+}
+
+void SwHyperlinkEventDescriptor::copyMacrosIntoINetFmt(
+ SwFmtINetFmt& aFmt)
+{
+ for(sal_Int16 i = 0; mpSupportedMacroItems[i].mnEvent != 0; i++)
+ {
+ sal_uInt16 nEvent = mpSupportedMacroItems[i].mnEvent;
+ if (hasByName(nEvent))
+ {
+ SvxMacro aMacro(sEmpty, sEmpty);
+ getByName(aMacro, nEvent);
+ aFmt.SetMacro(nEvent, aMacro);
+ }
+ }
+}
+
+
+void SwHyperlinkEventDescriptor::copyMacrosFromNameReplace(
+ uno::Reference<
+ container::XNameReplace> & xReplace)
+{
+ // iterate over all names (all names that *we* support)
+ Sequence<OUString> aNames = getElementNames();
+ sal_Int32 nCount = aNames.getLength();
+ for(sal_Int32 i = 0; i < nCount; i++)
+ {
+ // copy element for that name
+ const OUString& rName = aNames[i];
+ if (xReplace->hasByName(rName))
+ {
+ SvBaseEventDescriptor::replaceByName(rName,
+ xReplace->getByName(rName));
+ }
+ }
+}
+
+
+//
+// SwFrameEventDescriptor
+//
+
+// use double cast in superclass constructor to avoid ambigous cast
+SwFrameEventDescriptor::SwFrameEventDescriptor(
+ SwXTextFrame& rFrameRef ) :
+ SvEventDescriptor((text::XTextFrame&)rFrameRef, aFrameEvents),
+ sSwFrameEventDescriptor(RTL_CONSTASCII_USTRINGPARAM(
+ sAPI_SwFrameEventDescriptor)),
+ rFrame(rFrameRef)
+{
+}
+
+SwFrameEventDescriptor::SwFrameEventDescriptor(
+ SwXTextGraphicObject& rGraphicRef ) :
+ SvEventDescriptor((text::XTextContent&)rGraphicRef, aGraphicEvents),
+ rFrame((SwXFrame&)rGraphicRef)
+{
+}
+
+SwFrameEventDescriptor::SwFrameEventDescriptor(
+ SwXTextEmbeddedObject& rObjectRef ) :
+ SvEventDescriptor((text::XTextContent&)rObjectRef, aOLEEvents),
+ rFrame((SwXFrame&)rObjectRef)
+{
+}
+
+SwFrameEventDescriptor::~SwFrameEventDescriptor()
+{
+}
+
+void SwFrameEventDescriptor::setMacroItem(const SvxMacroItem& rItem)
+{
+ rFrame.GetFrmFmt()->SetFmtAttr(rItem);
+}
+
+const SvxMacroItem& SwFrameEventDescriptor::getMacroItem()
+{
+ return (const SvxMacroItem&)rFrame.GetFrmFmt()->GetFmtAttr(RES_FRMMACRO);
+}
+
+sal_uInt16 SwFrameEventDescriptor::getMacroItemWhich() const
+{
+ return RES_FRMMACRO;
+}
+
+OUString SwFrameEventDescriptor::getImplementationName()
+ throw( RuntimeException )
+{
+ return sSwFrameEventDescriptor;
+}
+
+
+//
+// SwFrameStyleEventDescriptor
+//
+
+SwFrameStyleEventDescriptor::SwFrameStyleEventDescriptor(
+ SwXFrameStyle& rStyleRef ) :
+ SvEventDescriptor((document::XEventsSupplier&)rStyleRef,
+ aFrameStyleEvents),
+ sSwFrameStyleEventDescriptor(RTL_CONSTASCII_USTRINGPARAM(
+ sAPI_SwFrameStyleEventDescriptor)),
+ rStyle(rStyleRef)
+{
+}
+
+SwFrameStyleEventDescriptor::~SwFrameStyleEventDescriptor()
+{
+}
+
+void SwFrameStyleEventDescriptor::setMacroItem(const SvxMacroItem& rItem)
+{
+ // As I was told, for some entirely unobvious reason getting an
+ // item from a style has to look as follows:
+ SfxStyleSheetBasePool* pBasePool = rStyle.GetBasePool();
+ if (pBasePool)
+ {
+ SfxStyleSheetBase* pBase = pBasePool->Find(rStyle.GetStyleName());
+ if (pBase)
+ {
+ rtl::Reference< SwDocStyleSheet > xStyle( new SwDocStyleSheet( *(SwDocStyleSheet*)pBase ) );
+ SfxItemSet& rStyleSet = xStyle->GetItemSet();
+ SfxItemSet aSet(*rStyleSet.GetPool(), RES_FRMMACRO, RES_FRMMACRO);
+ aSet.Put(rItem);
+ xStyle->SetItemSet(aSet);
+ }
+ }
+}
+
+static const SvxMacroItem aEmptyMacroItem(RES_FRMMACRO);
+
+const SvxMacroItem& SwFrameStyleEventDescriptor::getMacroItem()
+{
+ // As I was told, for some entirely unobvious reason getting an
+ // item from a style has to look as follows:
+ SfxStyleSheetBasePool* pBasePool = rStyle.GetBasePool();
+ if (pBasePool)
+ {
+ SfxStyleSheetBase* pBase = pBasePool->Find(rStyle.GetStyleName());
+ if (pBase)
+ {
+ rtl::Reference< SwDocStyleSheet > xStyle( new SwDocStyleSheet( *(SwDocStyleSheet*)pBase) );
+ return (const SvxMacroItem&)xStyle->GetItemSet().Get(RES_FRMMACRO);
+ }
+ else
+ return aEmptyMacroItem;
+ }
+ else
+ return aEmptyMacroItem;
+}
+
+OUString SwFrameStyleEventDescriptor::getImplementationName()
+ throw( RuntimeException )
+{
+ return sSwFrameStyleEventDescriptor;
+}
+
+sal_uInt16 SwFrameStyleEventDescriptor::getMacroItemWhich() const
+{
+ return RES_FRMMACRO;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/unocore/unoevtlstnr.cxx b/sw/source/core/unocore/unoevtlstnr.cxx
new file mode 100644
index 000000000000..0e20fd81af9f
--- /dev/null
+++ b/sw/source/core/unocore/unoevtlstnr.cxx
@@ -0,0 +1,105 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+
+#include <unoevtlstnr.hxx>
+#include <tools/debug.hxx>
+#include <com/sun/star/lang/EventObject.hpp>
+#include <com/sun/star/lang/XEventListener.hpp>
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star::uno;
+
+SV_IMPL_PTRARR(SwEvtLstnrArray, XEventListenerPtr);
+
+SwEventListenerContainer::SwEventListenerContainer( uno::XInterface* _pxParent) :
+ pListenerArr(0),
+ pxParent(_pxParent)
+{
+}
+
+SwEventListenerContainer::~SwEventListenerContainer()
+{
+ if(pListenerArr && pListenerArr->Count())
+ {
+ pListenerArr->DeleteAndDestroy(0, pListenerArr->Count());
+ }
+ delete pListenerArr;
+}
+
+void SwEventListenerContainer::AddListener(const uno::Reference< lang::XEventListener > & rxListener)
+{
+ if(!pListenerArr)
+ pListenerArr = new SwEvtLstnrArray;
+ uno::Reference< lang::XEventListener > * pInsert = new uno::Reference< lang::XEventListener > ;
+ *pInsert = rxListener;
+ pListenerArr->Insert(pInsert, pListenerArr->Count());
+}
+
+sal_Bool SwEventListenerContainer::RemoveListener(const uno::Reference< lang::XEventListener > & rxListener)
+{
+ if(!pListenerArr)
+ return sal_False;
+ else
+ {
+ lang::XEventListener* pLeft = rxListener.get();
+ for(sal_uInt16 i = 0; i < pListenerArr->Count(); i++)
+ {
+ XEventListenerPtr pElem = pListenerArr->GetObject(i);
+ lang::XEventListener* pRight = pElem->get();
+ if(pLeft == pRight)
+ {
+ pListenerArr->Remove(i);
+ delete pElem;
+ return sal_True;
+ }
+ }
+ }
+ return sal_False;
+}
+
+void SwEventListenerContainer::Disposing()
+{
+ if(!pListenerArr)
+ return;
+
+ lang::EventObject aObj(pxParent);
+ for(sal_uInt16 i = 0; i < pListenerArr->Count(); i++)
+ {
+ XEventListenerPtr pElem = pListenerArr->GetObject(i);
+ (*pElem)->disposing(aObj);
+ }
+ pListenerArr->DeleteAndDestroy(0, pListenerArr->Count());
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/unocore/unofield.cxx b/sw/source/core/unocore/unofield.cxx
new file mode 100644
index 000000000000..93126e71ab9d
--- /dev/null
+++ b/sw/source/core/unocore/unofield.cxx
@@ -0,0 +1,2806 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+
+#include <swtypes.hxx>
+#include <cmdid.h>
+#include <doc.hxx>
+#include <hints.hxx>
+#include <fmtfld.hxx>
+#include <txtfld.hxx>
+#include <ndtxt.hxx>
+#include <unomap.hxx>
+#include <unoprnms.hxx>
+#include <unotextrange.hxx>
+#include <unotextcursor.hxx>
+#include <unocoll.hxx>
+#include <sfx2/linkmgr.hxx>
+#include <docstat.hxx>
+#include <editsh.hxx>
+#include <viewsh.hxx>
+#include <comphelper/types.hxx>
+#include <comphelper/processfactory.hxx>
+#include <com/sun/star/util/Time.hpp>
+#include <com/sun/star/util/DateTimeRange.hpp>
+#include <com/sun/star/util/DateTime.hpp>
+#include <com/sun/star/util/Date.hpp>
+#include <com/sun/star/beans/XFastPropertySet.hpp>
+#include <com/sun/star/beans/XPropertyStateChangeListener.hpp>
+#include <com/sun/star/beans/PropertyAttribute.hpp>
+#include <com/sun/star/beans/XPropertyContainer.hpp>
+
+//undef to prevent error (from sfx2/docfile.cxx)
+#undef SEQUENCE
+#include <com/sun/star/text/SetVariableType.hpp>
+#include <com/sun/star/text/WrapTextMode.hpp>
+#include <com/sun/star/text/TextContentAnchorType.hpp>
+#include <com/sun/star/text/PageNumberType.hpp>
+#include <unofield.hxx>
+#include <unocrsr.hxx>
+#include <authfld.hxx>
+#include <flddat.hxx>
+#include <dbfld.hxx>
+#include <usrfld.hxx>
+#include <docufld.hxx>
+#include <expfld.hxx>
+#include <chpfld.hxx>
+#include <flddropdown.hxx>
+#include <poolfmt.hxx>
+#include <poolfmt.hrc>
+#include <pagedesc.hxx>
+#include <docary.hxx>
+#include <reffld.hxx>
+#include <ddefld.hxx>
+#include <SwStyleNameMapper.hxx>
+#include <swunohelper.hxx>
+#include <unofldmid.h>
+#include <scriptinfo.hxx>
+#include <tools/datetime.hxx>
+#include <tools/urlobj.hxx>
+#include <svx/dataaccessdescriptor.hxx>
+#define _SVSTDARR_STRINGS
+#include <svl/svstdarr.hxx>
+#include <osl/mutex.hxx>
+#include <vcl/svapp.hxx>
+#include <textapi.hxx>
+#include <editeng/outliner.hxx>
+#include <docsh.hxx>
+#include <fmtmeta.hxx> // MetaFieldManager
+#include <switerator.hxx>
+
+using ::rtl::OUString;
+using namespace ::com::sun::star;
+using namespace nsSwDocInfoSubType;
+
+#define COM_TEXT_FLDMASTER "com.sun.star.text.FieldMaster."
+
+// case-corrected version of the first part for the service names (see #i67811)
+#define COM_TEXT_FLDMASTER_CC "com.sun.star.text.fieldmaster."
+
+// note: this thing is indexed as an array, so do not insert/remove entries!
+static const sal_uInt16 aDocInfoSubTypeFromService[] =
+{
+ DI_CHANGE | DI_SUB_AUTHOR, //PROPERTY_MAP_FLDTYP_DOCINFO_CHANGE_AUTHOR
+ DI_CHANGE | DI_SUB_DATE, //PROPERTY_MAP_FLDTYP_DOCINFO_CHANGE_DATE_TIME
+ DI_EDIT | DI_SUB_TIME, //PROPERTY_MAP_FLDTYP_DOCINFO_EDIT_TIME
+ DI_COMMENT, //PROPERTY_MAP_FLDTYP_DOCINFO_DESCRIPTION
+ DI_CREATE | DI_SUB_AUTHOR, //PROPERTY_MAP_FLDTYP_DOCINFO_CREATE_AUTHOR
+ DI_CREATE | DI_SUB_DATE, //PROPERTY_MAP_FLDTYP_DOCINFO_CREATE_DATE_TIME
+ 0, //DUMMY
+ 0, //DUMMY
+ 0, //DUMMY
+ 0, //DUMMY
+ DI_CUSTOM, //PROPERTY_MAP_FLDTYP_DOCINFO_CUSTOM
+ DI_PRINT | DI_SUB_AUTHOR, //PROPERTY_MAP_FLDTYP_DOCINFO_PRINT_AUTHOR
+ DI_PRINT | DI_SUB_DATE, //PROPERTY_MAP_FLDTYP_DOCINFO_PRINT_DATE_TIME
+ DI_KEYS, //PROPERTY_MAP_FLDTYP_DOCINFO_KEY_WORDS
+ DI_THEMA, //PROPERTY_MAP_FLDTYP_DOCINFO_SUBJECT
+ DI_TITEL, //PROPERTY_MAP_FLDTYP_DOCINFO_TITLE
+ DI_DOCNO //PROPERTY_MAP_FLDTYP_DOCINFO_REVISION
+};
+
+struct ServiceIdResId
+{
+ sal_uInt16 nResId;
+ sal_uInt16 nServiceId;
+};
+
+static const ServiceIdResId aServiceToRes[] =
+{
+ {RES_DATETIMEFLD, SW_SERVICE_FIELDTYPE_DATETIME },
+ {RES_USERFLD, SW_SERVICE_FIELDTYPE_USER },
+ {RES_SETEXPFLD, SW_SERVICE_FIELDTYPE_SET_EXP } ,
+ {RES_GETEXPFLD, SW_SERVICE_FIELDTYPE_GET_EXP } ,
+ {RES_FILENAMEFLD, SW_SERVICE_FIELDTYPE_FILE_NAME },
+ {RES_PAGENUMBERFLD, SW_SERVICE_FIELDTYPE_PAGE_NUM } ,
+ {RES_AUTHORFLD, SW_SERVICE_FIELDTYPE_AUTHOR } ,
+ {RES_CHAPTERFLD, SW_SERVICE_FIELDTYPE_CHAPTER },
+ {RES_GETREFFLD, SW_SERVICE_FIELDTYPE_GET_REFERENCE } ,
+ {RES_HIDDENTXTFLD, SW_SERVICE_FIELDTYPE_CONDITIONED_TEXT },
+ {RES_POSTITFLD, SW_SERVICE_FIELDTYPE_ANNOTATION } ,
+ {RES_INPUTFLD, SW_SERVICE_FIELDTYPE_INPUT },
+ {RES_MACROFLD, SW_SERVICE_FIELDTYPE_MACRO },
+ {RES_DDEFLD, SW_SERVICE_FIELDTYPE_DDE },
+ {RES_HIDDENPARAFLD, SW_SERVICE_FIELDTYPE_HIDDEN_PARA } ,
+ {RES_DOCINFOFLD, SW_SERVICE_FIELDTYPE_DOC_INFO },
+ {RES_TEMPLNAMEFLD, SW_SERVICE_FIELDTYPE_TEMPLATE_NAME },
+ {RES_EXTUSERFLD, SW_SERVICE_FIELDTYPE_USER_EXT },
+ {RES_REFPAGESETFLD, SW_SERVICE_FIELDTYPE_REF_PAGE_SET } ,
+ {RES_REFPAGEGETFLD, SW_SERVICE_FIELDTYPE_REF_PAGE_GET } ,
+ {RES_JUMPEDITFLD, SW_SERVICE_FIELDTYPE_JUMP_EDIT },
+ {RES_SCRIPTFLD, SW_SERVICE_FIELDTYPE_SCRIPT } ,
+ {RES_DBNEXTSETFLD, SW_SERVICE_FIELDTYPE_DATABASE_NEXT_SET },
+ {RES_DBNUMSETFLD, SW_SERVICE_FIELDTYPE_DATABASE_NUM_SET },
+ {RES_DBSETNUMBERFLD, SW_SERVICE_FIELDTYPE_DATABASE_SET_NUM } ,
+ {RES_DBFLD, SW_SERVICE_FIELDTYPE_DATABASE } ,
+ {RES_DBNAMEFLD, SW_SERVICE_FIELDTYPE_DATABASE_NAME },
+ {RES_DOCSTATFLD, SW_SERVICE_FIELDTYPE_PAGE_COUNT },
+ {RES_DOCSTATFLD, SW_SERVICE_FIELDTYPE_PARAGRAPH_COUNT },
+ {RES_DOCSTATFLD, SW_SERVICE_FIELDTYPE_WORD_COUNT },
+ {RES_DOCSTATFLD, SW_SERVICE_FIELDTYPE_CHARACTER_COUNT },
+ {RES_DOCSTATFLD, SW_SERVICE_FIELDTYPE_TABLE_COUNT },
+ {RES_DOCSTATFLD, SW_SERVICE_FIELDTYPE_GRAPHIC_OBJECT_COUNT },
+ {RES_DOCSTATFLD, SW_SERVICE_FIELDTYPE_EMBEDDED_OBJECT_COUNT },
+ {RES_DOCINFOFLD, SW_SERVICE_FIELDTYPE_DOCINFO_CHANGE_AUTHOR },
+ {RES_DOCINFOFLD, SW_SERVICE_FIELDTYPE_DOCINFO_CHANGE_DATE_TIME},
+ {RES_DOCINFOFLD, SW_SERVICE_FIELDTYPE_DOCINFO_EDIT_TIME },
+ {RES_DOCINFOFLD, SW_SERVICE_FIELDTYPE_DOCINFO_DESCRIPTION },
+ {RES_DOCINFOFLD, SW_SERVICE_FIELDTYPE_DOCINFO_CREATE_AUTHOR },
+ {RES_DOCINFOFLD, SW_SERVICE_FIELDTYPE_DOCINFO_CREATE_DATE_TIME},
+ {RES_DOCINFOFLD, SW_SERVICE_FIELDTYPE_DOCINFO_CUSTOM },
+ {RES_DOCINFOFLD, SW_SERVICE_FIELDTYPE_DOCINFO_PRINT_AUTHOR },
+ {RES_DOCINFOFLD, SW_SERVICE_FIELDTYPE_DOCINFO_PRINT_DATE_TIME },
+ {RES_DOCINFOFLD, SW_SERVICE_FIELDTYPE_DOCINFO_KEY_WORDS },
+ {RES_DOCINFOFLD, SW_SERVICE_FIELDTYPE_DOCINFO_SUBJECT },
+ {RES_DOCINFOFLD, SW_SERVICE_FIELDTYPE_DOCINFO_TITLE },
+ {RES_INPUTFLD, SW_SERVICE_FIELDTYPE_INPUT_USER },
+ {RES_HIDDENTXTFLD, SW_SERVICE_FIELDTYPE_HIDDEN_TEXT },
+ {RES_AUTHORITY, SW_SERVICE_FIELDTYPE_BIBLIOGRAPHY },
+ {RES_COMBINED_CHARS, SW_SERVICE_FIELDTYPE_COMBINED_CHARACTERS },
+ {RES_DROPDOWN, SW_SERVICE_FIELDTYPE_DROPDOWN },
+ {RES_TABLEFLD, SW_SERVICE_FIELDTYPE_TABLE_FORMULA },
+ {USHRT_MAX, USHRT_MAX }
+};
+
+sal_uInt16 lcl_ServiceIdToResId(sal_uInt16 nServiceId)
+{
+ const ServiceIdResId* pMap = aServiceToRes;
+ while( USHRT_MAX != pMap->nServiceId && nServiceId != pMap->nServiceId )
+ ++pMap;
+#if OSL_DEBUG_LEVEL > 1
+ if( USHRT_MAX == pMap->nServiceId )
+ OSL_FAIL("service id not found");
+#endif
+ return pMap->nResId;
+}
+
+sal_uInt16 lcl_GetServiceForField( const SwField& rFld )
+{
+ sal_uInt16 nWhich = rFld.Which(), nSrvId = USHRT_MAX;
+ //special handling for some fields
+ switch( nWhich )
+ {
+ case RES_INPUTFLD:
+ if( INP_USR == (rFld.GetSubType() & 0x00ff) )
+ nSrvId = SW_SERVICE_FIELDTYPE_INPUT_USER;
+ break;
+
+ case RES_DOCINFOFLD:
+ {
+ sal_uInt16 nSubType = rFld.GetSubType();
+ switch( (nSubType & 0xff))
+ {
+ case DI_CHANGE:
+ nSrvId = ((nSubType&0x300) == DI_SUB_AUTHOR)
+ ? SW_SERVICE_FIELDTYPE_DOCINFO_CHANGE_AUTHOR
+ : SW_SERVICE_FIELDTYPE_DOCINFO_CHANGE_DATE_TIME;
+ break;
+ case DI_CREATE:
+ nSrvId = ((nSubType&0x300) == DI_SUB_AUTHOR)
+ ? SW_SERVICE_FIELDTYPE_DOCINFO_CREATE_AUTHOR
+ : SW_SERVICE_FIELDTYPE_DOCINFO_CREATE_DATE_TIME;
+ break;
+ case DI_PRINT:
+ nSrvId = ((nSubType&0x300) == DI_SUB_AUTHOR)
+ ? SW_SERVICE_FIELDTYPE_DOCINFO_PRINT_AUTHOR
+ : SW_SERVICE_FIELDTYPE_DOCINFO_PRINT_DATE_TIME;
+ break;
+ case DI_EDIT: nSrvId = SW_SERVICE_FIELDTYPE_DOCINFO_EDIT_TIME;break;
+ case DI_COMMENT:nSrvId = SW_SERVICE_FIELDTYPE_DOCINFO_DESCRIPTION;break;
+ case DI_KEYS: nSrvId = SW_SERVICE_FIELDTYPE_DOCINFO_KEY_WORDS;break;
+ case DI_THEMA: nSrvId = SW_SERVICE_FIELDTYPE_DOCINFO_SUBJECT; break;
+ case DI_TITEL: nSrvId = SW_SERVICE_FIELDTYPE_DOCINFO_TITLE; break;
+ case DI_DOCNO: nSrvId = SW_SERVICE_FIELDTYPE_DOCINFO_REVISION; break;
+ case DI_CUSTOM: nSrvId = SW_SERVICE_FIELDTYPE_DOCINFO_CUSTOM; break;
+ }
+ }
+ break;
+
+ case RES_HIDDENTXTFLD:
+ nSrvId = TYP_CONDTXTFLD == rFld.GetSubType()
+ ? SW_SERVICE_FIELDTYPE_CONDITIONED_TEXT
+ : SW_SERVICE_FIELDTYPE_HIDDEN_TEXT;
+ break;
+
+ case RES_DOCSTATFLD:
+ {
+ switch( rFld.GetSubType() )
+ {
+ case DS_PAGE: nSrvId = SW_SERVICE_FIELDTYPE_PAGE_COUNT; break;
+ case DS_PARA: nSrvId = SW_SERVICE_FIELDTYPE_PARAGRAPH_COUNT; break;
+ case DS_WORD: nSrvId = SW_SERVICE_FIELDTYPE_WORD_COUNT ; break;
+ case DS_CHAR: nSrvId = SW_SERVICE_FIELDTYPE_CHARACTER_COUNT; break;
+ case DS_TBL: nSrvId = SW_SERVICE_FIELDTYPE_TABLE_COUNT ; break;
+ case DS_GRF: nSrvId = SW_SERVICE_FIELDTYPE_GRAPHIC_OBJECT_COUNT; break;
+ case DS_OLE: nSrvId = SW_SERVICE_FIELDTYPE_EMBEDDED_OBJECT_COUNT; break;
+ }
+ }
+ break;
+ }
+ if( USHRT_MAX == nSrvId )
+ {
+ for( const ServiceIdResId* pMap = aServiceToRes;
+ USHRT_MAX != pMap->nResId; ++pMap )
+ if( nWhich == pMap->nResId )
+ {
+ nSrvId = pMap->nServiceId;
+ break;
+ }
+ }
+#if OSL_DEBUG_LEVEL > 1
+ if( USHRT_MAX == nSrvId )
+ OSL_FAIL("resid not found");
+#endif
+ return nSrvId;
+}
+
+sal_uInt16 lcl_GetPropMapIdForFieldType( sal_uInt16 nWhich )
+{
+ sal_uInt16 nId;
+ switch( nWhich )
+ {
+ case RES_USERFLD: nId = PROPERTY_MAP_FLDMSTR_USER; break;
+ case RES_DBFLD: nId = PROPERTY_MAP_FLDMSTR_DATABASE; break;
+ case RES_SETEXPFLD: nId = PROPERTY_MAP_FLDMSTR_SET_EXP; break;
+ case RES_DDEFLD: nId = PROPERTY_MAP_FLDMSTR_DDE; break;
+ case RES_AUTHORITY: nId = PROPERTY_MAP_FLDMSTR_BIBLIOGRAPHY; break;
+ default: nId = PROPERTY_MAP_FLDMSTR_DUMMY0;
+ }
+ return nId;
+}
+
+sal_uInt16 GetFieldTypeMId( const OUString& rProperty, const SwFieldType& rTyp )
+{
+ sal_uInt16 nId = lcl_GetPropMapIdForFieldType( rTyp.Which() );
+ const SfxItemPropertySet* pSet = aSwMapProvider.GetPropertySet( nId );
+ if( !pSet )
+ nId = USHRT_MAX;
+ else
+ {
+ const SfxItemPropertySimpleEntry* pEntry = pSet->getPropertyMap()->getByName(rProperty);
+ nId = pEntry ? pEntry->nWID : USHRT_MAX;
+ }
+ return nId;
+}
+
+sal_uInt16 lcl_GetPropertyMapOfService( sal_uInt16 nServiceId )
+{
+ sal_uInt16 nRet;
+ switch ( nServiceId)
+ {
+ case SW_SERVICE_FIELDTYPE_DATETIME: nRet = PROPERTY_MAP_FLDTYP_DATETIME; break;
+ case SW_SERVICE_FIELDTYPE_USER: nRet = PROPERTY_MAP_FLDTYP_USER; break;
+ case SW_SERVICE_FIELDTYPE_SET_EXP: nRet = PROPERTY_MAP_FLDTYP_SET_EXP; break;
+ case SW_SERVICE_FIELDTYPE_GET_EXP: nRet = PROPERTY_MAP_FLDTYP_GET_EXP; break;
+ case SW_SERVICE_FIELDTYPE_FILE_NAME: nRet = PROPERTY_MAP_FLDTYP_FILE_NAME; break;
+ case SW_SERVICE_FIELDTYPE_PAGE_NUM: nRet = PROPERTY_MAP_FLDTYP_PAGE_NUM; break;
+ case SW_SERVICE_FIELDTYPE_AUTHOR: nRet = PROPERTY_MAP_FLDTYP_AUTHOR; break;
+ case SW_SERVICE_FIELDTYPE_CHAPTER: nRet = PROPERTY_MAP_FLDTYP_CHAPTER; break;
+ case SW_SERVICE_FIELDTYPE_GET_REFERENCE: nRet = PROPERTY_MAP_FLDTYP_GET_REFERENCE; break;
+ case SW_SERVICE_FIELDTYPE_CONDITIONED_TEXT: nRet = PROPERTY_MAP_FLDTYP_CONDITIONED_TEXT; break;
+ case SW_SERVICE_FIELDTYPE_ANNOTATION: nRet = PROPERTY_MAP_FLDTYP_ANNOTATION; break;
+ case SW_SERVICE_FIELDTYPE_INPUT_USER:
+ case SW_SERVICE_FIELDTYPE_INPUT: nRet = PROPERTY_MAP_FLDTYP_INPUT; break;
+ case SW_SERVICE_FIELDTYPE_MACRO: nRet = PROPERTY_MAP_FLDTYP_MACRO; break;
+ case SW_SERVICE_FIELDTYPE_DDE: nRet = PROPERTY_MAP_FLDTYP_DDE; break;
+ case SW_SERVICE_FIELDTYPE_HIDDEN_PARA: nRet = PROPERTY_MAP_FLDTYP_HIDDEN_PARA; break;
+ case SW_SERVICE_FIELDTYPE_DOC_INFO: nRet = PROPERTY_MAP_FLDTYP_DOC_INFO; break;
+ case SW_SERVICE_FIELDTYPE_TEMPLATE_NAME: nRet = PROPERTY_MAP_FLDTYP_TEMPLATE_NAME; break;
+ case SW_SERVICE_FIELDTYPE_USER_EXT: nRet = PROPERTY_MAP_FLDTYP_USER_EXT; break;
+ case SW_SERVICE_FIELDTYPE_REF_PAGE_SET: nRet = PROPERTY_MAP_FLDTYP_REF_PAGE_SET; break;
+ case SW_SERVICE_FIELDTYPE_REF_PAGE_GET: nRet = PROPERTY_MAP_FLDTYP_REF_PAGE_GET; break;
+ case SW_SERVICE_FIELDTYPE_JUMP_EDIT: nRet = PROPERTY_MAP_FLDTYP_JUMP_EDIT; break;
+ case SW_SERVICE_FIELDTYPE_SCRIPT: nRet = PROPERTY_MAP_FLDTYP_SCRIPT; break;
+ case SW_SERVICE_FIELDTYPE_DATABASE_NEXT_SET: nRet = PROPERTY_MAP_FLDTYP_DATABASE_NEXT_SET; break;
+ case SW_SERVICE_FIELDTYPE_DATABASE_NUM_SET: nRet = PROPERTY_MAP_FLDTYP_DATABASE_NUM_SET; break;
+ case SW_SERVICE_FIELDTYPE_DATABASE_SET_NUM: nRet = PROPERTY_MAP_FLDTYP_DATABASE_SET_NUM; break;
+ case SW_SERVICE_FIELDTYPE_DATABASE: nRet = PROPERTY_MAP_FLDTYP_DATABASE; break;
+ case SW_SERVICE_FIELDTYPE_DATABASE_NAME: nRet = PROPERTY_MAP_FLDTYP_DATABASE_NAME; break;
+ case SW_SERVICE_FIELDTYPE_TABLE_FORMULA: nRet = PROPERTY_MAP_FLDTYP_TABLE_FORMULA; break;
+ case SW_SERVICE_FIELDTYPE_PAGE_COUNT:
+ case SW_SERVICE_FIELDTYPE_PARAGRAPH_COUNT:
+ case SW_SERVICE_FIELDTYPE_WORD_COUNT:
+ case SW_SERVICE_FIELDTYPE_CHARACTER_COUNT:
+ case SW_SERVICE_FIELDTYPE_TABLE_COUNT:
+ case SW_SERVICE_FIELDTYPE_GRAPHIC_OBJECT_COUNT:
+ case SW_SERVICE_FIELDTYPE_EMBEDDED_OBJECT_COUNT: nRet = PROPERTY_MAP_FLDTYP_DOCSTAT; break;
+ case SW_SERVICE_FIELDTYPE_DOCINFO_CHANGE_AUTHOR:
+ case SW_SERVICE_FIELDTYPE_DOCINFO_CREATE_AUTHOR:
+ case SW_SERVICE_FIELDTYPE_DOCINFO_PRINT_AUTHOR: nRet = PROPERTY_MAP_FLDTYP_DOCINFO_AUTHOR; break;
+ case SW_SERVICE_FIELDTYPE_DOCINFO_CHANGE_DATE_TIME:
+ case SW_SERVICE_FIELDTYPE_DOCINFO_CREATE_DATE_TIME:
+ case SW_SERVICE_FIELDTYPE_DOCINFO_PRINT_DATE_TIME: nRet = PROPERTY_MAP_FLDTYP_DOCINFO_DATE_TIME; break;
+ case SW_SERVICE_FIELDTYPE_DOCINFO_EDIT_TIME: nRet = PROPERTY_MAP_FLDTYP_DOCINFO_EDIT_TIME; break;
+ case SW_SERVICE_FIELDTYPE_DOCINFO_CUSTOM: nRet = PROPERTY_MAP_FLDTYP_DOCINFO_CUSTOM; break;
+ case SW_SERVICE_FIELDTYPE_DOCINFO_DESCRIPTION:
+ case SW_SERVICE_FIELDTYPE_DOCINFO_KEY_WORDS:
+ case SW_SERVICE_FIELDTYPE_DOCINFO_SUBJECT:
+ case SW_SERVICE_FIELDTYPE_DOCINFO_TITLE: nRet = PROPERTY_MAP_FLDTYP_DOCINFO_MISC; break;
+ case SW_SERVICE_FIELDTYPE_DOCINFO_REVISION: nRet = PROPERTY_MAP_FLDTYP_DOCINFO_REVISION; break;
+ case SW_SERVICE_FIELDTYPE_BIBLIOGRAPHY: nRet = PROPERTY_MAP_FLDTYP_BIBLIOGRAPHY; break;
+ case SW_SERVICE_FIELDTYPE_DUMMY_0:
+ case SW_SERVICE_FIELDTYPE_COMBINED_CHARACTERS: nRet = PROPERTY_MAP_FLDTYP_COMBINED_CHARACTERS; break;
+ case SW_SERVICE_FIELDTYPE_DROPDOWN: nRet = PROPERTY_MAP_FLDTYP_DROPDOWN; break;
+ case SW_SERVICE_FIELDTYPE_DUMMY_4:
+ case SW_SERVICE_FIELDTYPE_DUMMY_5:
+ case SW_SERVICE_FIELDTYPE_DUMMY_6:
+ case SW_SERVICE_FIELDTYPE_DUMMY_7:
+ nRet = PROPERTY_MAP_FLDTYP_DUMMY_0; break;
+ case SW_SERVICE_FIELDMASTER_USER: nRet = PROPERTY_MAP_FLDMSTR_USER; break;
+ case SW_SERVICE_FIELDMASTER_DDE: nRet = PROPERTY_MAP_FLDMSTR_DDE; break;
+ case SW_SERVICE_FIELDMASTER_SET_EXP: nRet = PROPERTY_MAP_FLDMSTR_SET_EXP; break;
+ case SW_SERVICE_FIELDMASTER_DATABASE: nRet = PROPERTY_MAP_FLDMSTR_DATABASE; break;
+ case SW_SERVICE_FIELDMASTER_BIBLIOGRAPHY: nRet = PROPERTY_MAP_FLDMSTR_BIBLIOGRAPHY; break;
+ case SW_SERVICE_FIELDMASTER_DUMMY2:
+ case SW_SERVICE_FIELDMASTER_DUMMY3:
+ case SW_SERVICE_FIELDMASTER_DUMMY4:
+ case SW_SERVICE_FIELDMASTER_DUMMY5: nRet = PROPERTY_MAP_FLDMSTR_DUMMY0; break;
+ case SW_SERVICE_FIELDTYPE_HIDDEN_TEXT: nRet = PROPERTY_MAP_FLDTYP_HIDDEN_TEXT; break;
+ default:
+ OSL_FAIL( "wrong service id" );
+ nRet = USHRT_MAX;
+ }
+ return nRet;
+}
+
+/******************************************************************
+ * SwXFieldMaster
+ ******************************************************************/
+TYPEINIT1(SwXFieldMaster, SwClient);
+
+const uno::Sequence< sal_Int8 > & SwXFieldMaster::getUnoTunnelId()
+{
+ static uno::Sequence< sal_Int8 > aSeq = ::CreateUnoTunnelId();
+ return aSeq;
+}
+
+sal_Int64 SAL_CALL SwXFieldMaster::getSomething( const uno::Sequence< sal_Int8 >& rId )
+ throw(uno::RuntimeException)
+{
+ if( rId.getLength() == 16
+ && 0 == rtl_compareMemory( getUnoTunnelId().getConstArray(),
+ rId.getConstArray(), 16 ) )
+ {
+ return sal::static_int_cast< sal_Int64 >( reinterpret_cast< sal_IntPtr >(this) );
+ }
+ return 0;
+}
+
+OUString SwXFieldMaster::getImplementationName(void) throw( uno::RuntimeException )
+{
+ return C2U("SwXFieldMaster");
+}
+
+sal_Bool SwXFieldMaster::supportsService(const OUString& rServiceName) throw( uno::RuntimeException )
+{
+ sal_Bool bRet = sal_False;
+ if(rServiceName.equalsAsciiL(
+ RTL_CONSTASCII_STRINGPARAM("com.sun.star.text.TextFieldMaster")))
+ bRet = sal_True;
+ else
+ {
+ const sal_Char* pEntry;
+ switch( nResTypeId )
+ {
+ case RES_USERFLD: pEntry = "User"; break;
+ case RES_DBFLD: pEntry = "Database"; break;
+ case RES_SETEXPFLD: pEntry = "SetExpression"; break;
+ case RES_DDEFLD: pEntry = "DDE"; break;
+ case RES_AUTHORITY: pEntry = "Bibliography"; break;
+ default: pEntry = 0;
+ }
+ if( pEntry )
+ {
+ ByteString aTmp( RTL_CONSTASCII_STRINGPARAM(
+ "com.sun.star.text.fieldmaster."));
+ aTmp.Append( pEntry );
+ bRet = rServiceName.equalsAsciiL(aTmp.GetBuffer(), aTmp.Len());
+ }
+ }
+ return bRet;
+}
+
+uno::Sequence< OUString > SwXFieldMaster::getSupportedServiceNames(void) throw( uno::RuntimeException )
+{
+ uno::Sequence< OUString > aRet(2);
+ OUString* pArray = aRet.getArray();
+ pArray[0] = C2U("com.sun.star.text.TextFieldMaster");
+
+ const sal_Char* pEntry1;
+ switch( nResTypeId )
+ {
+ case RES_USERFLD: pEntry1 = "User"; break;
+ case RES_DBFLD: pEntry1 = "Database"; break;
+ case RES_SETEXPFLD: pEntry1 = "SetExpression"; break;
+ case RES_DDEFLD: pEntry1 = "DDE"; break;
+ case RES_AUTHORITY: pEntry1 = "Bibliography"; break;
+ default: pEntry1 = 0;
+ }
+ if( pEntry1 )
+ {
+ String s;
+ s.AppendAscii( "com.sun.star.text.fieldmaster." ).AppendAscii( pEntry1 );
+ pArray[1] = s;
+ }
+ return aRet;
+}
+
+SwXFieldMaster::SwXFieldMaster(SwDoc* pDoc, sal_uInt16 nResId) :
+ aLstnrCntnr( (XPropertySet*)this),
+ nResTypeId(nResId),
+ m_pDoc(pDoc),
+ m_bIsDescriptor(sal_True),
+ fParam1(0.),
+ nParam1(-1),
+ bParam1(sal_False),
+ nParam2(0)
+{
+ pDoc->GetPageDescFromPool(RES_POOLPAGE_STANDARD)->Add(this);
+}
+
+SwXFieldMaster::SwXFieldMaster(SwFieldType& rType, SwDoc* pDoc) :
+ SwClient(&rType),
+ aLstnrCntnr( (XPropertySet*)this),
+ nResTypeId(rType.Which()),
+ m_pDoc(pDoc),
+ m_bIsDescriptor(sal_False),
+ fParam1(0.),
+ nParam1(-1),
+ bParam1(sal_False)
+{
+
+}
+
+SwXFieldMaster::~SwXFieldMaster()
+{
+
+}
+
+uno::Reference< beans::XPropertySetInfo > SwXFieldMaster::getPropertySetInfo(void)
+ throw( uno::RuntimeException )
+{
+ SolarMutexGuard aGuard;
+ uno::Reference< beans::XPropertySetInfo > aRef =
+ aSwMapProvider.GetPropertySet(
+ lcl_GetPropMapIdForFieldType( nResTypeId ) )->getPropertySetInfo();
+ return aRef;
+}
+
+void SwXFieldMaster::setPropertyValue( const OUString& rPropertyName,
+ const uno::Any& rValue)
+ throw( beans::UnknownPropertyException, beans::PropertyVetoException,
+ lang::IllegalArgumentException, lang::WrappedTargetException, uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+ SwFieldType* pType = GetFldType(sal_True);
+ if(pType)
+ {
+ sal_Bool bSetValue = sal_True;
+ if( rPropertyName.equalsAsciiL( SW_PROP_NAME(UNO_NAME_SUB_TYPE)))
+ {
+ const SvStringsDtor& rExtraArr = SwStyleNameMapper::GetExtraUINameArray();
+ String sTypeName = pType->GetName();
+ static sal_uInt16 nIds[] =
+ {
+ RES_POOLCOLL_LABEL_DRAWING - RES_POOLCOLL_EXTRA_BEGIN,
+ RES_POOLCOLL_LABEL_ABB - RES_POOLCOLL_EXTRA_BEGIN,
+ RES_POOLCOLL_LABEL_TABLE - RES_POOLCOLL_EXTRA_BEGIN,
+ RES_POOLCOLL_LABEL_FRAME- RES_POOLCOLL_EXTRA_BEGIN,
+ 0
+ };
+ for(const sal_uInt16 * pIds = nIds; *pIds; ++pIds)
+ {
+ if(sTypeName == *rExtraArr[ *pIds ] )
+ {
+ bSetValue = sal_False;
+ break;
+ }
+ }
+ }
+ if( bSetValue )
+ {
+ // nothing special to be done here for the properties
+ // UNO_NAME_DATA_BASE_NAME and UNO_NAME_DATA_BASE_URL.
+ // We just call PutValue (empty string is allowed).
+ // Thus the last property set will be used as Data Source.
+
+ sal_uInt16 nMId = GetFieldTypeMId( rPropertyName, *pType );
+ if( USHRT_MAX != nMId )
+ pType->PutValue( rValue, nMId );
+ else
+ throw beans::UnknownPropertyException(OUString ( RTL_CONSTASCII_USTRINGPARAM ( "Unknown property: " ) ) + rPropertyName, static_cast < cppu::OWeakObject * > ( this ) );
+ }
+ }
+ else if(!pType && m_pDoc &&
+ ( rPropertyName.equalsAsciiL( SW_PROP_NAME(UNO_NAME_NAME))) )
+ {
+ OUString uTmp;
+ rValue >>= uTmp;
+ String sTypeName(uTmp);
+ SwFieldType* pType2 = m_pDoc->GetFldType(nResTypeId, sTypeName, sal_False);
+
+ String sTable(SW_RES(STR_POOLCOLL_LABEL_TABLE));
+ String sDrawing(SW_RES(STR_POOLCOLL_LABEL_DRAWING));
+ String sFrame(SW_RES(STR_POOLCOLL_LABEL_FRAME));
+ String sIllustration(SW_RES(STR_POOLCOLL_LABEL_ABB));
+
+ if(pType2 ||
+ (RES_SETEXPFLD == nResTypeId &&
+ ( sTypeName == sTable || sTypeName == sDrawing ||
+ sTypeName == sFrame || sTypeName == sIllustration )))
+ {
+ throw lang::IllegalArgumentException();
+ }
+ else
+ {
+ switch(nResTypeId)
+ {
+ case RES_USERFLD :
+ {
+ SwUserFieldType aType(m_pDoc, sTypeName);
+ pType2 = m_pDoc->InsertFldType(aType);
+ ((SwUserFieldType*)pType2)->SetContent(sParam1);
+ ((SwUserFieldType*)pType2)->SetValue(fParam1);
+ ((SwUserFieldType*)pType2)->SetType(bParam1 ? nsSwGetSetExpType::GSE_EXPR : nsSwGetSetExpType::GSE_STRING);
+ }
+ break;
+ case RES_DDEFLD :
+ {
+ SwDDEFieldType aType(sTypeName, sParam1,
+ sal::static_int_cast< sal_uInt16 >(bParam1 ? sfx2::LINKUPDATE_ALWAYS : sfx2::LINKUPDATE_ONCALL));
+ pType2 = m_pDoc->InsertFldType(aType);
+ }
+ break;
+ case RES_SETEXPFLD :
+ {
+ SwSetExpFieldType aType(m_pDoc, sTypeName);
+ if(sParam1.Len())
+ aType.SetDelimiter( sParam1.GetChar(0));
+ if(nParam1 > -1 && nParam1 < MAXLEVEL)
+ aType.SetOutlineLvl(nParam1);
+ pType2 = m_pDoc->InsertFldType(aType);
+ }
+ break;
+ case RES_DBFLD :
+ {
+ ::GetString( rValue, sParam3 );
+ pType = GetFldType();
+ }
+ break;
+ }
+ if(pType2)
+ {
+ pType2->Add(this);
+ m_bIsDescriptor = sal_False;
+ }
+ else
+ throw uno::RuntimeException();
+ }
+
+ DBG_ASSERT(pType2, "kein FieldType gefunden!" );
+ }
+ else
+ {
+ switch( nResTypeId )
+ {
+ case RES_USERFLD:
+ if(rPropertyName.equalsAsciiL( SW_PROP_NAME(UNO_NAME_CONTENT)))
+ ::GetString( rValue, sParam1 );
+ else if(rPropertyName.equalsAsciiL( SW_PROP_NAME(UNO_NAME_VALUE )))
+ {
+ if(rValue.getValueType() != ::getCppuType(static_cast<const double*>(0)))
+ throw lang::IllegalArgumentException();
+ fParam1 = *(double*)rValue.getValue();
+ }
+ else if(rPropertyName.equalsAsciiL( SW_PROP_NAME(UNO_NAME_IS_EXPRESSION )))
+ {
+ if(rValue.getValueType() != ::getBooleanCppuType())
+ throw lang::IllegalArgumentException();
+ bParam1 = *(sal_Bool*)rValue.getValue();
+ }
+
+ break;
+ case RES_DBFLD:
+ if(rPropertyName.equalsAsciiL( SW_PROP_NAME(UNO_NAME_DATA_BASE_NAME)))
+ ::GetString( rValue, sParam1 );
+ else if(rPropertyName.equalsAsciiL( SW_PROP_NAME(UNO_NAME_DATA_TABLE_NAME)))
+ ::GetString( rValue, sParam2 );
+ else if(rPropertyName.equalsAsciiL( SW_PROP_NAME(UNO_NAME_DATA_COLUMN_NAME)))
+ ::GetString( rValue, sParam3 );
+ else if(rPropertyName.equalsAsciiL( SW_PROP_NAME(UNO_NAME_DATA_COMMAND_TYPE)))
+ rValue >>= nParam2;
+ if(rPropertyName.equalsAsciiL( SW_PROP_NAME(UNO_NAME_DATA_BASE_URL)))
+ ::GetString( rValue, sParam5 );
+
+ if((sParam1.Len() || sParam5.Len())
+ && sParam2.Len() && sParam3.Len())
+ GetFldType();
+ break;
+ case RES_SETEXPFLD:
+ if(rPropertyName.equalsAsciiL( SW_PROP_NAME(UNO_NAME_NUMBERING_SEPARATOR)))
+ ::GetString( rValue, sParam1 );
+ else if(rPropertyName.equalsAsciiL( SW_PROP_NAME(UNO_NAME_CHAPTER_NUMBERING_LEVEL)))
+ rValue >>= nParam1;
+ break;
+ case RES_DDEFLD:
+ {
+ sal_uInt16 nPart = rPropertyName.equalsAsciiL( SW_PROP_NAME(UNO_NAME_DDE_COMMAND_TYPE)) ? 0 :
+ rPropertyName.equalsAsciiL( SW_PROP_NAME(UNO_NAME_DDE_COMMAND_FILE)) ? 1 :
+ rPropertyName.equalsAsciiL( SW_PROP_NAME(UNO_NAME_DDE_COMMAND_ELEMENT)) ? 2 :
+ rPropertyName.equalsAsciiL( SW_PROP_NAME(UNO_NAME_IS_AUTOMATIC_UPDATE)) ? 3 : USHRT_MAX;
+ if(nPart < 3 )
+ {
+ String sTmp;
+ if(!sParam1.Len())
+ (sParam1 = sfx2::cTokenSeperator)
+ += sfx2::cTokenSeperator;
+
+ sParam1.SetToken( nPart, sfx2::cTokenSeperator,
+ ::GetString( rValue, sTmp ));
+ }
+ else if(3 == nPart)
+ bParam1 = *(sal_Bool*)rValue.getValue();
+ }
+ break;
+ default:
+ throw beans::UnknownPropertyException(OUString ( RTL_CONSTASCII_USTRINGPARAM ( "Unknown property: " ) ) + rPropertyName, static_cast < cppu::OWeakObject * > ( this ) );
+ }
+ }
+}
+
+SwFieldType* SwXFieldMaster::GetFldType(sal_Bool bDontCreate) const
+{
+ if(!bDontCreate && RES_DBFLD == nResTypeId && m_bIsDescriptor && m_pDoc)
+ {
+ SwDBData aData;
+
+ // set DataSource
+ svx::ODataAccessDescriptor aAcc;
+ if( sParam1.Len() > 0 )
+ aAcc[ svx::daDataSource ] <<= OUString(sParam1); // DataBaseName
+ else if( sParam5.Len() > 0 )
+ aAcc[ svx::daDatabaseLocation] <<= OUString(sParam5); // DataBaseURL
+ aData.sDataSource = aAcc.getDataSource();
+
+ aData.sCommand = sParam2;
+ aData.nCommandType = nParam2;
+ SwDBFieldType aType(m_pDoc, sParam3, aData);
+ SwFieldType* pType = m_pDoc->InsertFldType(aType);
+ SwXFieldMaster* pThis = ((SwXFieldMaster*)this);
+ pType->Add(pThis);
+ pThis->m_bIsDescriptor = sal_False;
+ }
+ if(m_bIsDescriptor)
+ return 0;
+ else
+ return (SwFieldType*)GetRegisteredIn();
+}
+
+typedef SwFmtFld* SwFmtFldPtr;
+SV_DECL_PTRARR(SwDependentFields, SwFmtFldPtr, 5, 5)
+SV_IMPL_PTRARR(SwDependentFields, SwFmtFldPtr)
+
+uno::Any SwXFieldMaster::getPropertyValue(const OUString& rPropertyName)
+ throw( beans::UnknownPropertyException, lang::WrappedTargetException, uno::RuntimeException )
+{
+ SolarMutexGuard aGuard;
+ uno::Any aRet;
+ SwFieldType* pType = GetFldType(sal_True);
+ if( rPropertyName.equalsAsciiL( SW_PROP_NAME(UNO_NAME_INSTANCE_NAME)) )
+ {
+ String sName;
+ if(pType)
+ SwXTextFieldMasters::getInstanceName(*pType, sName);
+ aRet <<= OUString(sName);
+ }
+ else if(pType)
+ {
+ if(rPropertyName.equalsAsciiL( SW_PROP_NAME(UNO_NAME_NAME) ))
+ {
+ aRet <<= SwXFieldMaster::GetProgrammaticName(*pType, *GetDoc());
+ }
+ else if(rPropertyName.equalsAsciiL( SW_PROP_NAME(UNO_NAME_DEPENDENT_TEXT_FIELDS)) )
+ {
+ //fill all text fields into a sequence
+ SwDependentFields aFldArr;
+ SwIterator<SwFmtFld,SwFieldType> aIter( *pType );
+ SwFmtFldPtr pFld = aIter.First();
+ while(pFld)
+ {
+ if(pFld->IsFldInDoc())
+ aFldArr.Insert(pFld, aFldArr.Count());
+ pFld = aIter.Next();
+ }
+
+ uno::Sequence<uno::Reference <text::XDependentTextField> > aRetSeq(aFldArr.Count());
+ uno::Reference<text::XDependentTextField>* pRetSeq = aRetSeq.getArray();
+ for(sal_uInt16 i = 0; i < aFldArr.Count(); i++)
+ {
+ pFld = aFldArr.GetObject(i);
+ SwXTextField * pInsert = SwXTextField::CreateSwXTextField(*GetDoc(), *pFld);
+
+ pRetSeq[i] = uno::Reference<text::XDependentTextField>(pInsert);
+ }
+ aRet <<= aRetSeq;
+ }
+ else if(pType)
+ {
+ //TODO: Properties fuer die uebrigen Feldtypen einbauen
+ sal_uInt16 nMId = GetFieldTypeMId( rPropertyName, *pType );
+ if( USHRT_MAX != nMId )
+ {
+ pType->QueryValue( aRet, nMId );
+
+ if( rPropertyName.equalsAsciiL( SW_PROP_NAME(UNO_NAME_DATA_BASE_NAME)) ||
+ rPropertyName.equalsAsciiL( SW_PROP_NAME(UNO_NAME_DATA_BASE_URL)))
+ {
+ OUString aDataSource;
+ aRet >>= aDataSource;
+ aRet <<= OUString();
+
+ OUString *pStr = 0; // only one of this properties will return
+ // a non-empty string.
+ INetURLObject aObj;
+ aObj.SetURL( aDataSource );
+ sal_Bool bIsURL = aObj.GetProtocol() != INET_PROT_NOT_VALID;
+ if (bIsURL && rPropertyName.equalsAsciiL( SW_PROP_NAME(UNO_NAME_DATA_BASE_URL)))
+ pStr = &aDataSource; // DataBaseURL
+ else if (!bIsURL && rPropertyName.equalsAsciiL( SW_PROP_NAME(UNO_NAME_DATA_BASE_NAME)))
+ pStr = &aDataSource; // DataBaseName
+
+ if (pStr)
+ aRet <<= *pStr;
+ }
+ }
+ else
+ throw beans::UnknownPropertyException(OUString ( RTL_CONSTASCII_USTRINGPARAM ( "Unknown property: " ) ) + rPropertyName, static_cast < cppu::OWeakObject * > ( this ) );
+ }
+ else
+ {
+ if(rPropertyName.equalsAsciiL( SW_PROP_NAME(UNO_NAME_DATA_COMMAND_TYPE)) )
+ aRet <<= nParam2;
+ }
+ }
+ else
+ {
+ if(rPropertyName.equalsAsciiL( SW_PROP_NAME(UNO_NAME_DATA_COMMAND_TYPE)) )
+ aRet <<= nParam2;
+ else if(rPropertyName.equalsAsciiL( SW_PROP_NAME(UNO_NAME_DEPENDENT_TEXT_FIELDS)) )
+ {
+ uno::Sequence<uno::Reference <text::XDependentTextField> > aRetSeq(0);
+ aRet <<= aRetSeq;
+ }
+ else
+ {
+ const String* pStr = 0;
+ String sStr;
+ switch ( nResTypeId )
+ {
+ case RES_USERFLD:
+ if( rPropertyName.equalsAsciiL( SW_PROP_NAME(UNO_NAME_CONTENT)) )
+ pStr = &sParam1;
+ else if(rPropertyName.equalsAsciiL( SW_PROP_NAME(UNO_NAME_VALUE )))
+ aRet <<= fParam1;
+ else if(rPropertyName.equalsAsciiL( SW_PROP_NAME(UNO_NAME_IS_EXPRESSION )))
+ aRet.setValue(&bParam1, ::getBooleanCppuType());
+ break;
+ case RES_DBFLD:
+ if(rPropertyName.equalsAsciiL( SW_PROP_NAME(UNO_NAME_DATA_BASE_NAME)) ||
+ rPropertyName.equalsAsciiL( SW_PROP_NAME(UNO_NAME_DATA_BASE_URL)))
+ {
+ pStr = 0; // only one of this properties will return
+ // a non-empty string.
+ INetURLObject aObj;
+ aObj.SetURL( sParam5 ); // SetSmartURL
+ sal_Bool bIsURL = aObj.GetProtocol() != INET_PROT_NOT_VALID;
+ if (bIsURL && rPropertyName.equalsAsciiL( SW_PROP_NAME(UNO_NAME_DATA_BASE_URL)))
+ pStr = &sParam5; // DataBaseURL
+ else if ( rPropertyName.equalsAsciiL( SW_PROP_NAME(UNO_NAME_DATA_BASE_NAME)))
+ pStr = &sParam1; // DataBaseName
+ }
+ else if(rPropertyName.equalsAsciiL( SW_PROP_NAME(UNO_NAME_DATA_TABLE_NAME)))
+ pStr = &sParam2;
+ else if(rPropertyName.equalsAsciiL( SW_PROP_NAME(UNO_NAME_DATA_COLUMN_NAME)))
+ pStr = &sParam3;
+ break;
+ case RES_SETEXPFLD:
+ if(rPropertyName.equalsAsciiL( SW_PROP_NAME(UNO_NAME_NUMBERING_SEPARATOR)))
+ pStr = &sParam1;
+ else if(rPropertyName.equalsAsciiL( SW_PROP_NAME(UNO_NAME_CHAPTER_NUMBERING_LEVEL)))
+ aRet <<= nParam1;
+ break;
+ case RES_DDEFLD:
+ {
+ sal_uInt16 nPart = rPropertyName.equalsAsciiL( SW_PROP_NAME(UNO_NAME_DDE_COMMAND_TYPE)) ? 0 :
+ rPropertyName.equalsAsciiL( SW_PROP_NAME(UNO_NAME_DDE_COMMAND_FILE)) ? 1 :
+ rPropertyName.equalsAsciiL( SW_PROP_NAME(UNO_NAME_DDE_COMMAND_ELEMENT)) ? 2 :
+ rPropertyName.equalsAsciiL( SW_PROP_NAME(UNO_NAME_IS_AUTOMATIC_UPDATE)) ? 3 : USHRT_MAX;
+ if(nPart < 3 )
+ pStr = &(sStr = sParam1.GetToken(nPart, sfx2::cTokenSeperator));
+ else if(3 == nPart)
+ aRet.setValue(&bParam1, ::getBooleanCppuType());
+ }
+ break;
+ default:
+ throw beans::UnknownPropertyException(OUString ( RTL_CONSTASCII_USTRINGPARAM ( "Unknown property: " ) ) + rPropertyName, static_cast < cppu::OWeakObject * > ( this ) );
+ }
+
+ if( pStr )
+ aRet <<= OUString( *pStr );
+ }
+ }
+ return aRet;
+}
+
+void SwXFieldMaster::addPropertyChangeListener(const OUString& /*PropertyName*/, const uno::Reference< beans::XPropertyChangeListener > & /*aListener*/) throw( beans::UnknownPropertyException, lang::WrappedTargetException, uno::RuntimeException )
+{
+ DBG_WARNING("not implemented");
+}
+
+void SwXFieldMaster::removePropertyChangeListener(const OUString& /*PropertyName*/, const uno::Reference< beans::XPropertyChangeListener > & /*aListener*/) throw( beans::UnknownPropertyException, lang::WrappedTargetException, uno::RuntimeException )
+{
+ DBG_WARNING("not implemented");
+}
+
+void SwXFieldMaster::addVetoableChangeListener(const OUString& /*PropertyName*/, const uno::Reference< beans::XVetoableChangeListener > & /*aListener*/) throw( beans::UnknownPropertyException, lang::WrappedTargetException, uno::RuntimeException )
+{
+ DBG_WARNING("not implemented");
+}
+
+void SwXFieldMaster::removeVetoableChangeListener(const OUString& /*PropertyName*/, const uno::Reference< beans::XVetoableChangeListener > & /*aListener*/) throw( beans::UnknownPropertyException, lang::WrappedTargetException, uno::RuntimeException )
+{
+ DBG_WARNING("not implemented");
+}
+
+void SwXFieldMaster::dispose(void) throw( uno::RuntimeException )
+{
+ SolarMutexGuard aGuard;
+ SwFieldType* pFldType = GetFldType(sal_True);
+ if(pFldType)
+ {
+ sal_uInt16 nTypeIdx = USHRT_MAX;
+ const SwFldTypes* pTypes = GetDoc()->GetFldTypes();
+ for( sal_uInt16 i = 0; i < pTypes->Count(); i++ )
+ {
+ if((*pTypes)[i] == pFldType)
+ nTypeIdx = i;
+ }
+
+ // zuerst alle Felder loeschen
+ SwIterator<SwFmtFld,SwFieldType> aIter( *pFldType );
+ SwFmtFld* pFld = aIter.First();
+ while(pFld)
+ {
+ // Feld im Undo?
+ SwTxtFld *pTxtFld = pFld->GetTxtFld();
+ if(pTxtFld && pTxtFld->GetTxtNode().GetNodes().IsDocNodes() )
+ {
+ SwTxtNode& rTxtNode = (SwTxtNode&)*pTxtFld->GetpTxtNode();
+ SwPaM aPam(rTxtNode, *pTxtFld->GetStart());
+ aPam.SetMark();
+ aPam.Move();
+ GetDoc()->DeleteAndJoin(aPam);
+ }
+ pFld = aIter.Next();
+ }
+ // dann den FieldType loeschen
+ GetDoc()->RemoveFldType(nTypeIdx);
+ }
+ else
+ throw uno::RuntimeException();
+}
+
+void SwXFieldMaster::addEventListener(const uno::Reference< lang::XEventListener > & aListener)
+ throw( uno::RuntimeException )
+{
+ if(!GetRegisteredIn())
+ throw uno::RuntimeException();
+ aLstnrCntnr.AddListener(aListener);
+}
+
+void SwXFieldMaster::removeEventListener(const uno::Reference< lang::XEventListener > & aListener)
+ throw( uno::RuntimeException )
+{
+ if(!GetRegisteredIn() || !aLstnrCntnr.RemoveListener(aListener))
+ throw uno::RuntimeException();
+}
+
+void SwXFieldMaster::Modify( const SfxPoolItem* pOld, const SfxPoolItem *pNew)
+{
+ ClientModify(this, pOld, pNew);
+ if(!GetRegisteredIn())
+ {
+ aLstnrCntnr.Disposing();
+ m_pDoc = 0;
+ }
+}
+OUString SwXFieldMaster::GetProgrammaticName(const SwFieldType& rType, SwDoc& rDoc)
+{
+ OUString sRet(rType.GetName());
+ if(RES_SETEXPFLD == rType.Which())
+ {
+ const SwFldTypes* pTypes = rDoc.GetFldTypes();
+ for( sal_uInt16 i = 0; i <= INIT_FLDTYPES; i++ )
+ {
+ if((*pTypes)[i] == &rType)
+ {
+ sRet = SwStyleNameMapper::GetProgName ( sRet, nsSwGetPoolIdFromName::GET_POOLID_TXTCOLL );
+ break;
+ }
+ }
+ }
+ return sRet;
+}
+
+OUString SwXFieldMaster::LocalizeFormula(
+ const SwSetExpField& rFld,
+ const OUString& rFormula,
+ sal_Bool bQuery)
+{
+ const OUString sTypeName(rFld.GetTyp()->GetName());
+ OUString sProgName = SwStyleNameMapper::GetProgName(sTypeName, nsSwGetPoolIdFromName::GET_POOLID_TXTCOLL );
+ if(sProgName != sTypeName)
+ {
+ OUString sSource = bQuery ? sTypeName : sProgName;
+ OUString sDest = bQuery ? sProgName : sTypeName;
+ if(!rFormula.compareTo(sSource, sSource.getLength()))
+ {
+ OUString sTmpFormula = sDest;
+ sTmpFormula += rFormula.copy(sSource.getLength());
+ return sTmpFormula;
+ }
+ }
+ return rFormula;
+}
+
+SwXTextField* SwXTextField::CreateSwXTextField(SwDoc & rDoc, SwFmtFld const& rFmt)
+{
+ SwIterator<SwXTextField,SwFieldType> aIter(*rFmt.GetFld()->GetTyp());
+ SwXTextField * pField = 0;
+ SwXTextField * pTemp = aIter.First();
+ while (pTemp)
+ {
+ if (pTemp->GetFldFmt() == &rFmt)
+ {
+ pField = pTemp;
+ break;
+ }
+ pTemp = aIter.Next();
+ }
+ return pField ? pField : new SwXTextField( rFmt, &rDoc );
+}
+
+struct SwFieldProperties_Impl
+{
+ String sPar1;
+ String sPar2;
+ String sPar3;
+ String sPar4;
+ String sPar5;
+ String sPar6;
+ Date aDate;
+ double fDouble;
+ uno::Sequence<beans::PropertyValue> aPropSeq;
+ uno::Sequence<OUString> aStrings;
+ util::DateTime* pDateTime;
+
+ sal_Int32 nSubType;
+ sal_Int32 nFormat;
+ sal_uInt16 nUSHORT1;
+ sal_uInt16 nUSHORT2;
+ sal_Int16 nSHORT1;
+ sal_Int8 nByte1;
+ sal_Bool bFormatIsDefault;
+ sal_Bool bBool1;
+ sal_Bool bBool2;
+ sal_Bool bBool3;
+ sal_Bool bBool4;
+
+ SwFieldProperties_Impl():
+ fDouble(0.),
+ pDateTime(0),
+ nSubType(0),
+ nFormat(0),
+ nUSHORT1(0),
+ nUSHORT2(0),
+ nSHORT1(0),
+ nByte1(0),
+ bFormatIsDefault(sal_True),
+ bBool1(sal_False),
+ bBool2(sal_False),
+ bBool3(sal_False),
+ bBool4(sal_True) //Automatic language
+ {}
+ ~SwFieldProperties_Impl()
+ {delete pDateTime;}
+
+};
+
+TYPEINIT1(SwXTextField, SwClient);
+
+const uno::Sequence< sal_Int8 > & SwXTextField::getUnoTunnelId()
+{
+ static uno::Sequence< sal_Int8 > aSeq = ::CreateUnoTunnelId();
+ return aSeq;
+}
+
+sal_Int64 SAL_CALL SwXTextField::getSomething( const uno::Sequence< sal_Int8 >& rId )
+ throw(uno::RuntimeException)
+{
+ if( rId.getLength() == 16
+ && 0 == rtl_compareMemory( getUnoTunnelId().getConstArray(),
+ rId.getConstArray(), 16 ) )
+ {
+ return sal::static_int_cast< sal_Int64 >( reinterpret_cast< sal_IntPtr >(this) );
+ }
+ return 0;
+}
+
+SwXTextField::SwXTextField(sal_uInt16 nServiceId, SwDoc* pDoc) :
+ aLstnrCntnr( (XTextContent*)this),
+ pFmtFld(0),
+ m_pDoc(pDoc),
+ m_pTextObject(0),
+ m_bIsDescriptor(nServiceId != USHRT_MAX),
+ m_bCallUpdate(sal_False),
+ m_nServiceId(nServiceId),
+ m_pProps(new SwFieldProperties_Impl)
+{
+ //Set visible as default!
+ if(SW_SERVICE_FIELDTYPE_SET_EXP == nServiceId ||
+ SW_SERVICE_FIELDTYPE_DATABASE_SET_NUM == nServiceId ||
+ SW_SERVICE_FIELDTYPE_DATABASE == nServiceId ||
+ SW_SERVICE_FIELDTYPE_DATABASE_NAME == nServiceId )
+ m_pProps->bBool2 = sal_True;
+ else if(SW_SERVICE_FIELDTYPE_TABLE_FORMULA == nServiceId)
+ m_pProps->bBool1 = sal_True;
+ if(SW_SERVICE_FIELDTYPE_SET_EXP == nServiceId)
+ m_pProps->nUSHORT2 = USHRT_MAX;
+
+}
+
+SwXTextField::SwXTextField(const SwFmtFld& rFmt, SwDoc* pDc) :
+ aLstnrCntnr( (XTextContent*)this),
+ pFmtFld(&rFmt),
+ m_pDoc(pDc),
+ m_pTextObject(0),
+ m_bIsDescriptor(sal_False),
+ m_bCallUpdate(sal_False),
+ m_nServiceId( lcl_GetServiceForField( *pFmtFld->GetFld() ) ),
+ m_pProps(0)
+{
+ pDc->GetUnoCallBack()->Add(this);
+}
+
+SwXTextField::~SwXTextField()
+{
+ if ( m_pTextObject )
+ {
+ m_pTextObject->DisposeEditSource();
+ m_pTextObject->release();
+ }
+
+ delete m_pProps;
+}
+
+void SwXTextField::attachTextFieldMaster(const uno::Reference< beans::XPropertySet > & xFieldMaster)
+ throw( lang::IllegalArgumentException, uno::RuntimeException )
+{
+ SolarMutexGuard aGuard;
+ if(!m_bIsDescriptor)
+ throw uno::RuntimeException();
+ uno::Reference< lang::XUnoTunnel > xMasterTunnel(xFieldMaster, uno::UNO_QUERY);
+ if (!xMasterTunnel.is())
+ throw lang::IllegalArgumentException();
+ SwXFieldMaster* pMaster = reinterpret_cast< SwXFieldMaster * >(
+ sal::static_int_cast< sal_IntPtr >( xMasterTunnel->getSomething( SwXFieldMaster::getUnoTunnelId()) ));
+
+ SwFieldType* pFieldType = pMaster ? pMaster->GetFldType() : 0;
+ if(pFieldType && pFieldType->Which() == lcl_ServiceIdToResId(m_nServiceId))
+ {
+ m_sTypeName = pFieldType->GetName();
+ pFieldType->Add( &m_aFieldTypeClient );
+ }
+ else
+ throw lang::IllegalArgumentException();
+
+}
+
+uno::Reference< beans::XPropertySet > SwXTextField::getTextFieldMaster(void) throw( uno::RuntimeException )
+{
+ SolarMutexGuard aGuard;
+ SwFieldType* pType = 0;
+ if( m_bIsDescriptor && m_aFieldTypeClient.GetRegisteredIn() )
+ {
+ pType = (SwFieldType*)m_aFieldTypeClient.GetRegisteredIn();
+ }
+ else
+ {
+ if(!GetRegisteredIn())
+ throw uno::RuntimeException();
+ pType = pFmtFld->GetFld()->GetTyp();
+ }
+
+ SwXFieldMaster* pMaster = SwIterator<SwXFieldMaster,SwFieldType>::FirstElement( *pType );
+ if(!pMaster)
+ pMaster = new SwXFieldMaster(*pType, GetDoc());
+
+ return pMaster;
+}
+
+OUString SwXTextField::getPresentation(sal_Bool bShowCommand) throw( uno::RuntimeException )
+{
+ SolarMutexGuard aGuard;
+
+ SwField const*const pField = GetField();
+ if (!pField)
+ {
+ throw uno::RuntimeException();
+ }
+ ::rtl::OUString const ret( (bShowCommand)
+ ? pField->GetFieldName()
+ : pField->ExpandField(true) );
+ return ret;
+}
+
+void SwXTextField::attachToRange(
+ const uno::Reference< text::XTextRange > & xTextRange)
+ throw( lang::IllegalArgumentException, uno::RuntimeException )
+{
+ SolarMutexGuard aGuard;
+ if(!m_bIsDescriptor)
+ throw uno::RuntimeException();
+ uno::Reference<lang::XUnoTunnel> xRangeTunnel( xTextRange, uno::UNO_QUERY);
+ SwXTextRange* pRange = 0;
+ OTextCursorHelper* pCursor = 0;
+ if(xRangeTunnel.is())
+ {
+ pRange = reinterpret_cast< SwXTextRange * >(
+ sal::static_int_cast< sal_IntPtr >( xRangeTunnel->getSomething( SwXTextRange::getUnoTunnelId()) ));
+ pCursor = reinterpret_cast< OTextCursorHelper * >(
+ sal::static_int_cast< sal_IntPtr >( xRangeTunnel->getSomething( OTextCursorHelper::getUnoTunnelId()) ));
+ }
+
+ SwDoc* pDoc = pRange ? (SwDoc*)pRange->GetDoc() : pCursor ? (SwDoc*)pCursor->GetDoc() : 0;
+ //wurde ein FieldMaster attached, dann ist das Dokument schon festgelegt!
+ if(pDoc && (!m_pDoc || m_pDoc == pDoc))
+ {
+ SwUnoInternalPaM aPam(*pDoc);
+ //das muss jetzt sal_True liefern
+ ::sw::XTextRangeToSwPaM(aPam, xTextRange);
+ SwField* pFld = 0;
+ switch(m_nServiceId)
+ {
+ case SW_SERVICE_FIELDTYPE_ANNOTATION:
+ {
+ SwFieldType* pFldType = pDoc->GetSysFldType(RES_POSTITFLD);
+
+ DateTime aDateTime;
+ if (m_pProps->pDateTime)
+ {
+ aDateTime.SetYear(m_pProps->pDateTime->Year);
+ aDateTime.SetMonth(m_pProps->pDateTime->Month);
+ aDateTime.SetDay(m_pProps->pDateTime->Day);
+ aDateTime.SetHour(m_pProps->pDateTime->Hours);
+ aDateTime.SetMin(m_pProps->pDateTime->Minutes);
+ aDateTime.SetSec(m_pProps->pDateTime->Seconds);
+ }
+ pFld = new SwPostItField((SwPostItFieldType*)pFldType,
+ m_pProps->sPar1, m_pProps->sPar2,aDateTime);
+ if ( m_pTextObject )
+ {
+ ((SwPostItField*)pFld)->SetTextObject( m_pTextObject->CreateText() );
+ ((SwPostItField*)pFld)->SetPar2(m_pTextObject->GetText());
+ }
+ }
+ break;
+ case SW_SERVICE_FIELDTYPE_SCRIPT:
+ {
+ SwFieldType* pFldType = pDoc->GetSysFldType(RES_SCRIPTFLD);
+ pFld = new SwScriptField((SwScriptFieldType*)pFldType,
+ m_pProps->sPar1, m_pProps->sPar2,
+ m_pProps->bBool1);
+ }
+ break;
+ case SW_SERVICE_FIELDTYPE_DATETIME:
+ {
+ sal_uInt16 nSub = 0;
+ if(m_pProps->bBool1)
+ nSub |= FIXEDFLD;
+ if(m_pProps->bBool2)
+ nSub |= DATEFLD;
+ else
+ nSub |= TIMEFLD;
+ SwFieldType* pFldType = pDoc->GetSysFldType(RES_DATETIMEFLD);
+ pFld = new SwDateTimeField((SwDateTimeFieldType*)pFldType,
+ nSub, m_pProps->nFormat);
+ if(m_pProps->fDouble > 0.)
+ ((SwDateTimeField*)pFld)->SetValue( m_pProps->fDouble );
+ if(m_pProps->pDateTime)
+ {
+ uno::Any aVal; aVal <<= *m_pProps->pDateTime;
+ pFld->PutValue( aVal, FIELD_PROP_DATE_TIME );
+ }
+ ((SwDateTimeField*)pFld)->SetOffset(m_pProps->nSubType);
+ }
+ break;
+ case SW_SERVICE_FIELDTYPE_FILE_NAME:
+ {
+ SwFieldType* pFldType = pDoc->GetSysFldType(RES_FILENAMEFLD);
+ sal_Int32 nFormat = m_pProps->nFormat;
+ if(m_pProps->bBool2)
+ nFormat |= FF_FIXED;
+ pFld = new SwFileNameField((SwFileNameFieldType*)pFldType, nFormat);
+ if(m_pProps->sPar3.Len())
+ ((SwFileNameField*)pFld)->SetExpansion(m_pProps->sPar3);
+ uno::Any aFormat(&m_pProps->nFormat, ::getCppuType(&m_pProps->nFormat));
+ pFld->PutValue( aFormat, FIELD_PROP_FORMAT );
+ }
+ break;
+ case SW_SERVICE_FIELDTYPE_TEMPLATE_NAME:
+ {
+ SwFieldType* pFldType = pDoc->GetSysFldType(RES_TEMPLNAMEFLD);
+ pFld = new SwTemplNameField((SwTemplNameFieldType*)pFldType,
+ m_pProps->nFormat);
+ uno::Any aFormat(&m_pProps->nFormat, ::getCppuType(&m_pProps->nFormat));
+ pFld->PutValue(aFormat, FIELD_PROP_FORMAT);
+ }
+ break;
+ case SW_SERVICE_FIELDTYPE_CHAPTER:
+ {
+ SwFieldType* pFldType = pDoc->GetSysFldType(RES_CHAPTERFLD);
+ pFld = new SwChapterField((SwChapterFieldType*)pFldType, m_pProps->nUSHORT1);
+ ((SwChapterField*)pFld)->SetLevel(m_pProps->nByte1);
+ uno::Any aVal; aVal <<= (sal_Int16)m_pProps->nUSHORT1;
+ pFld->PutValue(aVal, FIELD_PROP_USHORT1 );
+ }
+ break;
+ case SW_SERVICE_FIELDTYPE_AUTHOR:
+ {
+ long nFormat = m_pProps->bBool1 ? AF_NAME : AF_SHORTCUT;
+ if(m_pProps->bBool2)
+ nFormat |= AF_FIXED;
+
+ SwFieldType* pFldType = pDoc->GetSysFldType(RES_AUTHORFLD);
+ pFld = new SwAuthorField((SwAuthorFieldType*)pFldType, nFormat);
+ ((SwAuthorField*)pFld)->SetExpansion(m_pProps->sPar1);
+ }
+ break;
+ case SW_SERVICE_FIELDTYPE_CONDITIONED_TEXT:
+ case SW_SERVICE_FIELDTYPE_HIDDEN_TEXT:
+ {
+ SwFieldType* pFldType = pDoc->GetSysFldType(RES_HIDDENTXTFLD);
+ pFld = new SwHiddenTxtField(((SwHiddenTxtFieldType*)pFldType),
+ m_pProps->sPar1,
+ m_pProps->sPar2, m_pProps->sPar3,
+ static_cast< sal_uInt16 >(SW_SERVICE_FIELDTYPE_HIDDEN_TEXT == m_nServiceId ?
+ TYP_HIDDENTXTFLD : TYP_CONDTXTFLD));
+ ((SwHiddenTxtField*)pFld)->SetValue(m_pProps->bBool1);
+ uno::Any aVal; aVal <<= (OUString)m_pProps->sPar4;
+ pFld->PutValue(aVal, FIELD_PROP_PAR4 );
+ }
+ break;
+ case SW_SERVICE_FIELDTYPE_HIDDEN_PARA:
+ {
+ SwFieldType* pFldType = pDoc->GetSysFldType(RES_HIDDENPARAFLD);
+ pFld = new SwHiddenParaField((SwHiddenParaFieldType*)pFldType,
+ m_pProps->sPar1);
+ ((SwHiddenParaField*)pFld)->SetHidden(m_pProps->bBool1);
+ }
+ break;
+ case SW_SERVICE_FIELDTYPE_GET_REFERENCE:
+ {
+ SwFieldType* pFldType = pDoc->GetSysFldType(RES_GETREFFLD);
+ pFld = new SwGetRefField((SwGetRefFieldType*)pFldType,
+ m_pProps->sPar1,
+ 0,
+ 0,
+ 0);
+ if(m_pProps->sPar3.Len())
+ ((SwGetRefField*)pFld)->SetExpand(m_pProps->sPar3);
+ uno::Any aVal; aVal <<=(sal_Int16)m_pProps->nUSHORT1;
+ pFld->PutValue(aVal, FIELD_PROP_USHORT1 );
+ aVal <<=(sal_Int16)m_pProps->nUSHORT2;
+ pFld->PutValue(aVal, FIELD_PROP_USHORT2 );
+ aVal <<=(sal_Int16)m_pProps->nSHORT1;
+ pFld->PutValue(aVal, FIELD_PROP_SHORT1 );
+ }
+ break;
+ case SW_SERVICE_FIELDTYPE_JUMP_EDIT:
+ {
+ SwFieldType* pFldType = pDoc->GetSysFldType(RES_JUMPEDITFLD);
+ pFld = new SwJumpEditField((SwJumpEditFieldType*)pFldType,
+ m_pProps->nUSHORT1, m_pProps->sPar2, m_pProps->sPar1);
+ }
+ break;
+ case SW_SERVICE_FIELDTYPE_DOCINFO_CHANGE_AUTHOR :
+ case SW_SERVICE_FIELDTYPE_DOCINFO_CHANGE_DATE_TIME :
+ case SW_SERVICE_FIELDTYPE_DOCINFO_EDIT_TIME :
+ case SW_SERVICE_FIELDTYPE_DOCINFO_DESCRIPTION :
+ case SW_SERVICE_FIELDTYPE_DOCINFO_CREATE_AUTHOR :
+ case SW_SERVICE_FIELDTYPE_DOCINFO_CREATE_DATE_TIME :
+ case SW_SERVICE_FIELDTYPE_DOCINFO_CUSTOM :
+ case SW_SERVICE_FIELDTYPE_DOCINFO_PRINT_AUTHOR :
+ case SW_SERVICE_FIELDTYPE_DOCINFO_PRINT_DATE_TIME :
+ case SW_SERVICE_FIELDTYPE_DOCINFO_KEY_WORDS :
+ case SW_SERVICE_FIELDTYPE_DOCINFO_SUBJECT :
+ case SW_SERVICE_FIELDTYPE_DOCINFO_TITLE :
+ case SW_SERVICE_FIELDTYPE_DOCINFO_REVISION :
+ case SW_SERVICE_FIELDTYPE_DOC_INFO:
+ {
+ SwFieldType* pFldType = pDoc->GetSysFldType(RES_DOCINFOFLD);
+ sal_uInt16 nSubType = aDocInfoSubTypeFromService[
+ m_nServiceId - SW_SERVICE_FIELDTYPE_DOCINFO_CHANGE_AUTHOR];
+ if( SW_SERVICE_FIELDTYPE_DOCINFO_CHANGE_DATE_TIME == m_nServiceId ||
+ SW_SERVICE_FIELDTYPE_DOCINFO_CREATE_DATE_TIME == m_nServiceId ||
+ SW_SERVICE_FIELDTYPE_DOCINFO_PRINT_DATE_TIME == m_nServiceId ||
+ SW_SERVICE_FIELDTYPE_DOCINFO_EDIT_TIME == m_nServiceId )
+ {
+ if(m_pProps->bBool2) //IsDate
+ {
+ nSubType &= 0xf0ff;
+ nSubType |= DI_SUB_DATE;
+ }
+ else
+ {
+ nSubType &= 0xf0ff;
+ nSubType |= DI_SUB_TIME;
+ }
+ }
+ if(m_pProps->bBool1)
+ nSubType |= DI_SUB_FIXED;
+ pFld = new SwDocInfoField((SwDocInfoFieldType*)pFldType, nSubType, m_pProps->sPar4, m_pProps->nFormat);
+ if(m_pProps->sPar3.Len())
+ ((SwDocInfoField*)pFld)->SetExpansion(m_pProps->sPar3);
+ }
+ break;
+ case SW_SERVICE_FIELDTYPE_USER_EXT:
+ {
+ sal_Int32 nFormat = 0;
+ if(m_pProps->bBool1)
+ nFormat = AF_FIXED;
+
+ SwFieldType* pFldType = pDoc->GetSysFldType(RES_EXTUSERFLD);
+ pFld = new SwExtUserField((SwExtUserFieldType*)pFldType, m_pProps->nUSHORT1, nFormat);
+ ((SwExtUserField*)pFld)->SetExpansion(m_pProps->sPar1);
+ }
+ break;
+ case SW_SERVICE_FIELDTYPE_USER:
+ {
+ SwFieldType* pFldType = pDoc->GetFldType(RES_USERFLD, m_sTypeName, sal_True);
+ if(!pFldType)
+ throw uno::RuntimeException();
+ sal_uInt16 nUserSubType = m_pProps->bBool1 ? nsSwExtendedSubType::SUB_INVISIBLE : 0;
+ if(m_pProps->bBool2)
+ nUserSubType |= nsSwExtendedSubType::SUB_CMD;
+ if(m_pProps->bFormatIsDefault &&
+ nsSwGetSetExpType::GSE_STRING == ((SwUserFieldType*)pFldType)->GetType())
+ m_pProps->nFormat = -1;
+ pFld = new SwUserField((SwUserFieldType*)pFldType,
+ nUserSubType,
+ m_pProps->nFormat);
+ }
+ break;
+ case SW_SERVICE_FIELDTYPE_REF_PAGE_SET:
+ {
+ SwFieldType* pFldType = pDoc->GetSysFldType(RES_REFPAGESETFLD);
+ pFld = new SwRefPageSetField( (SwRefPageSetFieldType*)pFldType,
+ m_pProps->nUSHORT1,
+ m_pProps->bBool1 );
+ }
+ break;
+ case SW_SERVICE_FIELDTYPE_REF_PAGE_GET:
+ {
+ SwFieldType* pFldType = pDoc->GetSysFldType(RES_REFPAGEGETFLD);
+ pFld = new SwRefPageGetField( (SwRefPageGetFieldType*)pFldType,
+ m_pProps->nUSHORT1 );
+ ((SwRefPageGetField*)pFld)->SetText(m_pProps->sPar1);
+ }
+ break;
+ case SW_SERVICE_FIELDTYPE_PAGE_NUM:
+ {
+ SwFieldType* pFldType = pDoc->GetSysFldType(RES_PAGENUMBERFLD);
+ pFld = new SwPageNumberField((SwPageNumberFieldType*)pFldType,
+ PG_RANDOM,
+ m_pProps->nFormat,
+ m_pProps->nUSHORT1);
+ ((SwPageNumberField*)pFld)->SetUserString(m_pProps->sPar1);
+ uno::Any aVal; aVal <<= m_pProps->nSubType;
+ pFld->PutValue( aVal, FIELD_PROP_SUBTYPE );
+ }
+ break;
+ case SW_SERVICE_FIELDTYPE_DDE:
+ {
+ SwFieldType* pFldType = pDoc->GetFldType(RES_DDEFLD, m_sTypeName, sal_True);
+ if(!pFldType)
+ throw uno::RuntimeException();
+ pFld = new SwDDEField( (SwDDEFieldType*)pFldType );
+ }
+ break;
+ case SW_SERVICE_FIELDTYPE_DATABASE_NAME:
+ {
+ SwFieldType* pFldType = pDoc->GetSysFldType(RES_DBNAMEFLD);
+ SwDBData aData;
+ aData.sDataSource = m_pProps->sPar1;
+ aData.sCommand = m_pProps->sPar2;
+ aData.nCommandType = m_pProps->nSHORT1;
+ pFld = new SwDBNameField((SwDBNameFieldType*)pFldType, aData);
+ sal_uInt16 nSubType = pFld->GetSubType();
+ if(m_pProps->bBool2)
+ nSubType &= ~nsSwExtendedSubType::SUB_INVISIBLE;
+ else
+ nSubType |= nsSwExtendedSubType::SUB_INVISIBLE;
+ pFld->SetSubType(nSubType);
+ }
+ break;
+ case SW_SERVICE_FIELDTYPE_DATABASE_NEXT_SET:
+ {
+ SwDBData aData;
+ aData.sDataSource = m_pProps->sPar1;
+ aData.sCommand = m_pProps->sPar2;
+ aData.nCommandType = m_pProps->nSHORT1;
+ SwFieldType* pFldType = pDoc->GetSysFldType(RES_DBNEXTSETFLD);
+ pFld = new SwDBNextSetField((SwDBNextSetFieldType*)pFldType,
+ m_pProps->sPar3, aEmptyStr,
+ aData);
+ }
+ break;
+ case SW_SERVICE_FIELDTYPE_DATABASE_NUM_SET:
+ {
+ SwDBData aData;
+ aData.sDataSource = m_pProps->sPar1;
+ aData.sCommand = m_pProps->sPar2;
+ aData.nCommandType = m_pProps->nSHORT1;
+ pFld = new SwDBNumSetField( (SwDBNumSetFieldType*)
+ pDoc->GetSysFldType(RES_DBNUMSETFLD),
+ m_pProps->sPar3,
+ String::CreateFromInt32(m_pProps->nFormat),
+ aData );
+ }
+ break;
+ case SW_SERVICE_FIELDTYPE_DATABASE_SET_NUM:
+ {
+ SwDBData aData;
+ aData.sDataSource = m_pProps->sPar1;
+ aData.sCommand = m_pProps->sPar2;
+ aData.nCommandType = m_pProps->nSHORT1;
+ pFld = new SwDBSetNumberField((SwDBSetNumberFieldType*)
+ pDoc->GetSysFldType(RES_DBSETNUMBERFLD),
+ aData,
+ m_pProps->nUSHORT1);
+ ((SwDBSetNumberField*)pFld)->SetSetNumber(m_pProps->nFormat);
+ sal_uInt16 nSubType = pFld->GetSubType();
+ if(m_pProps->bBool2)
+ nSubType &= ~nsSwExtendedSubType::SUB_INVISIBLE;
+ else
+ nSubType |= nsSwExtendedSubType::SUB_INVISIBLE;
+ pFld->SetSubType(nSubType);
+ }
+ break;
+ case SW_SERVICE_FIELDTYPE_DATABASE:
+ {
+ SwFieldType* pFldType = pDoc->GetFldType(RES_DBFLD, m_sTypeName, sal_False);
+ if(!pFldType)
+ throw uno::RuntimeException();
+ pFld = new SwDBField((SwDBFieldType*)pFldType, m_pProps->nFormat);
+ ((SwDBField*)pFld)->InitContent(m_pProps->sPar1);
+ sal_uInt16 nSubType = pFld->GetSubType();
+ if(m_pProps->bBool2)
+ nSubType &= ~nsSwExtendedSubType::SUB_INVISIBLE;
+ else
+ nSubType |= nsSwExtendedSubType::SUB_INVISIBLE;
+ pFld->SetSubType(nSubType);
+ }
+ break;
+ case SW_SERVICE_FIELDTYPE_SET_EXP:
+ {
+ SwFieldType* pFldType = pDoc->GetFldType(RES_SETEXPFLD, m_sTypeName, sal_True);
+ if(!pFldType)
+ throw uno::RuntimeException();
+ // detect the field type's sub type and set an appropriate number format
+ if(m_pProps->bFormatIsDefault &&
+ nsSwGetSetExpType::GSE_STRING == ((SwSetExpFieldType*)pFldType)->GetType())
+ m_pProps->nFormat = -1;
+ pFld = new SwSetExpField((SwSetExpFieldType*)pFldType,
+ m_pProps->sPar2,
+ m_pProps->nUSHORT2 != USHRT_MAX ? //#i79471# the field can have a number format or a number_ing_ format
+ m_pProps->nUSHORT2 : m_pProps->nFormat);
+
+ sal_uInt16 nSubType = pFld->GetSubType();
+ if(m_pProps->bBool2)
+ nSubType &= ~nsSwExtendedSubType::SUB_INVISIBLE;
+ else
+ nSubType |= nsSwExtendedSubType::SUB_INVISIBLE;
+ if(m_pProps->bBool3)
+ nSubType |= nsSwExtendedSubType::SUB_CMD;
+ else
+ nSubType &= ~nsSwExtendedSubType::SUB_CMD;
+ pFld->SetSubType(nSubType);
+ ((SwSetExpField*)pFld)->SetSeqNumber( m_pProps->nUSHORT1 );
+ ((SwSetExpField*)pFld)->SetInputFlag(m_pProps->bBool1);
+ ((SwSetExpField*)pFld)->SetPromptText(m_pProps->sPar3);
+ if(m_pProps->sPar4.Len())
+ ((SwSetExpField*)pFld)->ChgExpStr(m_pProps->sPar4);
+
+ }
+ break;
+ case SW_SERVICE_FIELDTYPE_GET_EXP:
+ {
+ sal_uInt16 nSubType;
+ switch(m_pProps->nSubType)
+ {
+ case text::SetVariableType::STRING: nSubType = nsSwGetSetExpType::GSE_STRING; break;
+ case text::SetVariableType::VAR: nSubType = nsSwGetSetExpType::GSE_EXPR; break;
+ //case text::SetVariableType::SEQUENCE: nSubType = nsSwGetSetExpType::GSE_SEQ; break;
+ case text::SetVariableType::FORMULA: nSubType = nsSwGetSetExpType::GSE_FORMULA; break;
+ default:
+ OSL_FAIL("wrong value");
+ nSubType = nsSwGetSetExpType::GSE_EXPR;
+ }
+ //make sure the SubType matches the field type
+ SwFieldType* pSetExpFld = pDoc->GetFldType(RES_SETEXPFLD, m_pProps->sPar1, sal_False);
+ bool bSetGetExpFieldUninitialized = false;
+ if( pSetExpFld )
+ {
+ if( nSubType != nsSwGetSetExpType::GSE_STRING &&
+ static_cast< SwSetExpFieldType* >(pSetExpFld)->GetType() == nsSwGetSetExpType::GSE_STRING )
+ nSubType = nsSwGetSetExpType::GSE_STRING;
+ }
+ else
+ bSetGetExpFieldUninitialized = true; // #i82544#
+
+ if(m_pProps->bBool2)
+ nSubType |= nsSwExtendedSubType::SUB_CMD;
+ else
+ nSubType &= ~nsSwExtendedSubType::SUB_CMD;
+ pFld = new SwGetExpField((SwGetExpFieldType*)
+ pDoc->GetSysFldType(RES_GETEXPFLD),
+ m_pProps->sPar1, nSubType, m_pProps->nFormat);
+ //TODO: SubType auswerten!
+ if(m_pProps->sPar4.Len())
+ ((SwGetExpField*)pFld)->ChgExpStr(m_pProps->sPar4);
+ // #i82544#
+ if( bSetGetExpFieldUninitialized )
+ ((SwGetExpField*)pFld)->SetLateInitialization();
+ }
+ break;
+ case SW_SERVICE_FIELDTYPE_INPUT_USER:
+ case SW_SERVICE_FIELDTYPE_INPUT:
+ {
+ SwFieldType* pFldType = pDoc->GetFldType(RES_INPUTFLD, m_sTypeName, sal_True);
+ if(!pFldType)
+ throw uno::RuntimeException();
+ sal_uInt16 nInpSubType = sal::static_int_cast< sal_uInt16 >(SW_SERVICE_FIELDTYPE_INPUT_USER == m_nServiceId ? INP_USR : INP_TXT);
+ SwInputField * pTxtField =
+ new SwInputField((SwInputFieldType*)pFldType,
+ m_pProps->sPar1, m_pProps->sPar2,
+ nInpSubType);
+ pTxtField->SetHelp(m_pProps->sPar3);
+ pTxtField->SetToolTip(m_pProps->sPar4);
+
+ pFld = pTxtField;
+ }
+ break;
+ case SW_SERVICE_FIELDTYPE_MACRO:
+ {
+ SwFieldType* pFldType = pDoc->GetSysFldType(RES_MACROFLD);
+ String aName;
+
+ // support for Scripting Framework macros
+ if (m_pProps->sPar4.Len() != 0)
+ {
+ aName = m_pProps->sPar4;
+ }
+ else
+ {
+ SwMacroField::CreateMacroString(
+ aName, m_pProps->sPar1, m_pProps->sPar3 );
+ }
+ pFld = new SwMacroField((SwMacroFieldType*)pFldType, aName,
+ m_pProps->sPar2);
+ }
+ break;
+ case SW_SERVICE_FIELDTYPE_PAGE_COUNT :
+ case SW_SERVICE_FIELDTYPE_PARAGRAPH_COUNT :
+ case SW_SERVICE_FIELDTYPE_WORD_COUNT :
+ case SW_SERVICE_FIELDTYPE_CHARACTER_COUNT :
+ case SW_SERVICE_FIELDTYPE_TABLE_COUNT :
+ case SW_SERVICE_FIELDTYPE_GRAPHIC_OBJECT_COUNT :
+ case SW_SERVICE_FIELDTYPE_EMBEDDED_OBJECT_COUNT :
+ {
+ sal_uInt16 nSubType = DS_PAGE;
+ switch(m_nServiceId)
+ {
+// case SW_SERVICE_FIELDTYPE_PAGE_COUNT : break;
+ case SW_SERVICE_FIELDTYPE_PARAGRAPH_COUNT : nSubType = DS_PARA;break;
+ case SW_SERVICE_FIELDTYPE_WORD_COUNT : nSubType = DS_WORD;break;
+ case SW_SERVICE_FIELDTYPE_CHARACTER_COUNT : nSubType = DS_CHAR;break;
+ case SW_SERVICE_FIELDTYPE_TABLE_COUNT : nSubType = DS_TBL;break;
+ case SW_SERVICE_FIELDTYPE_GRAPHIC_OBJECT_COUNT : nSubType = DS_GRF;break;
+ case SW_SERVICE_FIELDTYPE_EMBEDDED_OBJECT_COUNT : nSubType = DS_OLE;break;
+ }
+ SwFieldType* pFldType = pDoc->GetSysFldType(RES_DOCSTATFLD);
+ pFld = new SwDocStatField((SwDocStatFieldType*)pFldType, nSubType, m_pProps->nUSHORT2);
+ }
+ break;
+ case SW_SERVICE_FIELDTYPE_BIBLIOGRAPHY:
+ pFld = new SwAuthorityField( (SwAuthorityFieldType*)
+ pDoc->InsertFldType(SwAuthorityFieldType(pDoc)),
+ aEmptyStr );
+ if(m_pProps->aPropSeq.getLength())
+ {
+ uno::Any aVal; aVal <<= m_pProps->aPropSeq;
+ pFld->PutValue( aVal, FIELD_PROP_PROP_SEQ );
+ }
+ break;
+ case SW_SERVICE_FIELDTYPE_COMBINED_CHARACTERS:
+ // create field
+ pFld = new SwCombinedCharField( (SwCombinedCharFieldType*)
+ pDoc->GetSysFldType(RES_COMBINED_CHARS),
+ m_pProps->sPar1);
+ break;
+ case SW_SERVICE_FIELDTYPE_DROPDOWN:
+ pFld = new SwDropDownField
+ ((SwDropDownFieldType *)
+ pDoc->GetSysFldType(RES_DROPDOWN));
+
+ ((SwDropDownField *) pFld)->SetItems(m_pProps->aStrings);
+ ((SwDropDownField *) pFld)->SetSelectedItem(m_pProps->sPar1);
+ ((SwDropDownField *) pFld)->SetName(m_pProps->sPar2);
+ ((SwDropDownField *) pFld)->SetHelp(m_pProps->sPar3);
+ ((SwDropDownField *) pFld)->SetToolTip(m_pProps->sPar4);
+ break;
+
+ case SW_SERVICE_FIELDTYPE_TABLE_FORMULA :
+ {
+
+ // create field
+ sal_uInt16 nType = nsSwGetSetExpType::GSE_FORMULA;
+ if(m_pProps->bBool1)
+ {
+ nType |= nsSwExtendedSubType::SUB_CMD;
+ if(m_pProps->bFormatIsDefault)
+ m_pProps->nFormat = -1;
+ }
+ pFld = new SwTblField( (SwTblFieldType*)
+ pDoc->GetSysFldType(RES_TABLEFLD),
+ m_pProps->sPar2,
+ nType,
+ m_pProps->nFormat);
+ ((SwTblField*)pFld)->ChgExpStr(m_pProps->sPar1);
+ }
+ break;
+ default: OSL_FAIL("was ist das fuer ein Typ?");
+ }
+ if(pFld)
+ {
+ pFld->SetAutomaticLanguage(!m_pProps->bBool4);
+ SwFmtFld aFmt( *pFld );
+
+ UnoActionContext aCont(pDoc);
+ SwTxtAttr* pTxtAttr = 0;
+ if(aPam.HasMark())
+ pDoc->DeleteAndJoin(aPam);
+
+ SwXTextCursor const*const pTextCursor(
+ dynamic_cast<SwXTextCursor*>(pCursor));
+ const bool bForceExpandHints( (pTextCursor)
+ ? pTextCursor->IsAtEndOfMeta() : false );
+ const SetAttrMode nInsertFlags = (bForceExpandHints)
+ ? nsSetAttrMode::SETATTR_FORCEHINTEXPAND
+ : nsSetAttrMode::SETATTR_DEFAULT;
+
+ pDoc->InsertPoolItem(aPam, aFmt, nInsertFlags);
+
+ pTxtAttr = aPam.GetNode()->GetTxtNode()->GetTxtAttrForCharAt(
+ aPam.GetPoint()->nContent.GetIndex()-1, RES_TXTATR_FIELD);
+
+ // was passiert mit dem Update der Felder ? (siehe fldmgr.cxx)
+ if(pTxtAttr)
+ {
+ const SwFmtFld& rFld = pTxtAttr->GetFld();
+ pFmtFld = &rFld;
+ }
+ }
+ delete pFld;
+
+ m_pDoc = pDoc;
+ m_pDoc->GetUnoCallBack()->Add(this);
+ m_bIsDescriptor = sal_False;
+ if(m_aFieldTypeClient.GetRegisteredIn())
+ const_cast<SwModify*>(m_aFieldTypeClient.GetRegisteredIn())->Remove(&m_aFieldTypeClient);
+ DELETEZ(m_pProps);
+ if(m_bCallUpdate)
+ update();
+ }
+ else
+ throw lang::IllegalArgumentException();
+}
+
+void SwXTextField::attach(const uno::Reference< text::XTextRange > & xTextRange)
+ throw( lang::IllegalArgumentException, uno::RuntimeException )
+{
+ SolarMutexGuard aGuard;
+ attachToRange( xTextRange );
+}
+
+uno::Reference< text::XTextRange > SwXTextField::getAnchor(void) throw( uno::RuntimeException )
+{
+ SolarMutexGuard aGuard;
+ uno::Reference< text::XTextRange > aRef;
+ SwField* pField = (SwField*)GetField();
+ if(pField)
+ {
+ const SwTxtFld* pTxtFld = pFmtFld->GetTxtFld();
+ if(!pTxtFld)
+ throw uno::RuntimeException();
+ const SwTxtNode& rTxtNode = pTxtFld->GetTxtNode();
+
+ SwPaM aPam(rTxtNode, *pTxtFld->GetStart() + 1, rTxtNode, *pTxtFld->GetStart());
+
+ aRef = SwXTextRange::CreateXTextRange(
+ *m_pDoc, *aPam.GetPoint(), aPam.GetMark());
+ }
+ return aRef;
+
+}
+
+void SwXTextField::dispose(void) throw( uno::RuntimeException )
+{
+ SolarMutexGuard aGuard;
+ SwField* pField = (SwField*)GetField();
+ if(pField)
+ {
+ UnoActionContext aContext(GetDoc());
+ const SwTxtFld* pTxtFld = pFmtFld->GetTxtFld();
+ SwTxtNode& rTxtNode = (SwTxtNode&)*pTxtFld->GetpTxtNode();
+ SwPaM aPam(rTxtNode, *pTxtFld->GetStart());
+ aPam.SetMark();
+ aPam.Move();
+ GetDoc()->DeleteAndJoin(aPam);
+ }
+
+ if ( m_pTextObject )
+ {
+ m_pTextObject->DisposeEditSource();
+ m_pTextObject->release();
+ m_pTextObject = 0;
+ }
+}
+
+void SwXTextField::addEventListener(const uno::Reference< lang::XEventListener > & aListener) throw( uno::RuntimeException )
+{
+ if(!GetRegisteredIn())
+ throw uno::RuntimeException();
+ aLstnrCntnr.AddListener(aListener);
+}
+
+void SwXTextField::removeEventListener(const uno::Reference< lang::XEventListener > & aListener) throw( uno::RuntimeException )
+{
+ if(!GetRegisteredIn() || !aLstnrCntnr.RemoveListener(aListener))
+ throw uno::RuntimeException();
+}
+
+uno::Reference< beans::XPropertySetInfo > SwXTextField::getPropertySetInfo(void)
+ throw( uno::RuntimeException )
+{
+ SolarMutexGuard aGuard;
+ //kein static
+ uno::Reference< beans::XPropertySetInfo > aRef;
+ if(m_nServiceId != USHRT_MAX)
+ {
+ const SfxItemPropertySet* pPropSet = aSwMapProvider.GetPropertySet(
+ lcl_GetPropertyMapOfService( m_nServiceId ));
+ uno::Reference< beans::XPropertySetInfo > xInfo = pPropSet->getPropertySetInfo();
+ // extend PropertySetInfo!
+ const uno::Sequence<beans::Property> aPropSeq = xInfo->getProperties();
+ aRef = new SfxExtItemPropertySetInfo(
+ aSwMapProvider.GetPropertyMapEntries(PROPERTY_MAP_PARAGRAPH_EXTENSIONS),
+ aPropSeq );
+ }
+ else
+ throw uno::RuntimeException();
+ return aRef;
+}
+
+void SwXTextField::setPropertyValue(const OUString& rPropertyName, const uno::Any& rValue)
+ throw( beans::UnknownPropertyException, beans::PropertyVetoException, lang::IllegalArgumentException,
+ lang::WrappedTargetException, uno::RuntimeException )
+{
+ SolarMutexGuard aGuard;
+ SwField* pField = (SwField*)GetField();
+ const SfxItemPropertySet* _pPropSet = aSwMapProvider.GetPropertySet(
+ lcl_GetPropertyMapOfService( m_nServiceId));
+ const SfxItemPropertySimpleEntry* pEntry = _pPropSet->getPropertyMap()->getByName(rPropertyName);
+
+ if (!pEntry)
+ throw beans::UnknownPropertyException(OUString ( RTL_CONSTASCII_USTRINGPARAM ( "Unknown property: " ) ) + rPropertyName, static_cast < cppu::OWeakObject * > ( this ) );
+ if ( pEntry->nFlags & beans::PropertyAttribute::READONLY)
+ throw beans::PropertyVetoException ( OUString ( RTL_CONSTASCII_USTRINGPARAM ( "Property is read-only: " ) ) + rPropertyName, static_cast < cppu::OWeakObject * > ( this ) );
+
+ if(pField)
+ {
+ // Sonderbehandlung Serienbrieffeld
+ sal_uInt16 nWhich = pField->Which();
+ if( RES_DBFLD == nWhich &&
+ (rPropertyName.equalsAsciiL( SW_PROP_NAME(UNO_NAME_DATA_BASE_NAME)) ||
+ rPropertyName.equalsAsciiL( SW_PROP_NAME(UNO_NAME_DATA_BASE_URL))||
+ rPropertyName.equalsAsciiL( SW_PROP_NAME(UNO_NAME_DATA_TABLE_NAME))||
+ rPropertyName.equalsAsciiL( SW_PROP_NAME(UNO_NAME_DATA_COLUMN_NAME))))
+ {
+ // hier muss ein neuer Feldtyp angelegt werden und
+ // das Feld an den neuen Typ umgehaengt werden
+ DBG_WARNING("not implemented");
+ }
+ else
+ {
+ SwDoc * pDoc = GetDoc();
+
+ if (NULL != pDoc)
+ {
+ const SwTxtFld* pTxtFld = pFmtFld->GetTxtFld();
+ if(!pTxtFld)
+ throw uno::RuntimeException();
+ SwPosition aPosition( pTxtFld->GetTxtNode() );
+ aPosition.nContent = *pTxtFld->GetStart();
+ pDoc->PutValueToField( aPosition, rValue, pEntry->nWID);
+ }
+ }
+ pField->PutValue( rValue, pEntry->nWID );
+
+ //#i100374# notify SwPostIt about new field content
+ if (RES_POSTITFLD== nWhich && pFmtFld)
+ {
+ const_cast<SwFmtFld*>(pFmtFld)->Broadcast(SwFmtFldHint( 0, SWFMTFLD_CHANGED ));
+ }
+
+ // changes of the expanded string have to be notified
+ //#to the SwTxtFld
+ if(RES_DBFLD == nWhich && pFmtFld->GetTxtFld())
+ {
+ pFmtFld->GetTxtFld()->Expand();
+ }
+
+ //#i100374# changing a document field should set the modify flag
+ SwDoc* pDoc = GetDoc();
+ if (pDoc)
+ pDoc->SetModified();
+
+ }
+ else if(m_pProps)
+ {
+ String* pStr = 0;
+ sal_Bool* pBool = 0;
+ switch(pEntry->nWID)
+ {
+ case FIELD_PROP_PAR1:
+ pStr = &m_pProps->sPar1;
+ break;
+ case FIELD_PROP_PAR2:
+ pStr = &m_pProps->sPar2;
+ break;
+ case FIELD_PROP_PAR3:
+ pStr = &m_pProps->sPar3;
+ break;
+ case FIELD_PROP_PAR4:
+ pStr = &m_pProps->sPar4;
+ break;
+ case FIELD_PROP_FORMAT:
+ rValue >>= m_pProps->nFormat;
+ m_pProps->bFormatIsDefault = sal_False;
+ break;
+ case FIELD_PROP_SUBTYPE:
+ m_pProps->nSubType = SWUnoHelper::GetEnumAsInt32( rValue );
+ break;
+ case FIELD_PROP_BYTE1 :
+ rValue >>= m_pProps->nByte1;
+ break;
+ case FIELD_PROP_BOOL1 :
+ pBool = &m_pProps->bBool1;
+ break;
+ case FIELD_PROP_BOOL2 :
+ pBool = &m_pProps->bBool2;
+ break;
+ case FIELD_PROP_BOOL3 :
+ pBool = &m_pProps->bBool3;
+ break;
+ case FIELD_PROP_BOOL4:
+ pBool = &m_pProps->bBool4;
+ break;
+ case FIELD_PROP_DATE :
+ {
+ if(rValue.getValueType() != ::getCppuType(static_cast<const util::Date*>(0)))
+ throw lang::IllegalArgumentException();
+
+ util::Date aTemp = *(const util::Date*)rValue.getValue();
+ m_pProps->aDate = Date(aTemp.Day, aTemp.Month, aTemp.Year);
+ }
+ break;
+ case FIELD_PROP_USHORT1:
+ case FIELD_PROP_USHORT2:
+ {
+ sal_Int16 nVal = 0;
+ rValue >>= nVal;
+ if( FIELD_PROP_USHORT1 == pEntry->nWID)
+ m_pProps->nUSHORT1 = nVal;
+ else
+ m_pProps->nUSHORT2 = nVal;
+ }
+ break;
+ case FIELD_PROP_SHORT1:
+ rValue >>= m_pProps->nSHORT1;
+ break;
+ case FIELD_PROP_DOUBLE:
+ if(rValue.getValueType() != ::getCppuType(static_cast<const double*>(0)))
+ throw lang::IllegalArgumentException();
+ m_pProps->fDouble = *(double*)rValue.getValue();
+ break;
+
+ case FIELD_PROP_DATE_TIME :
+ if(!m_pProps->pDateTime)
+ m_pProps->pDateTime = new util::DateTime;
+ rValue >>= (*m_pProps->pDateTime);
+ break;
+ case FIELD_PROP_PROP_SEQ:
+ rValue >>= m_pProps->aPropSeq;
+ break;
+ case FIELD_PROP_STRINGS:
+ rValue >>= m_pProps->aStrings;
+ break;
+ }
+ if( pStr )
+ ::GetString( rValue, *pStr );
+ else if( pBool )
+ {
+ if( rValue.getValueType() == getCppuBooleanType() )
+ *pBool = *(sal_Bool*)rValue.getValue();
+ else
+ throw lang::IllegalArgumentException();
+ }
+ }
+ else
+ throw uno::RuntimeException();
+}
+
+uno::Any SwXTextField::getPropertyValue(const OUString& rPropertyName)
+ throw( beans::UnknownPropertyException, lang::WrappedTargetException, uno::RuntimeException )
+{
+ SolarMutexGuard aGuard;
+ uno::Any aRet;
+ const SwField* pField = GetField();
+ const SfxItemPropertySet* _pPropSet = aSwMapProvider.GetPropertySet(
+ lcl_GetPropertyMapOfService( m_nServiceId));
+ const SfxItemPropertySimpleEntry* pEntry = _pPropSet->getPropertyMap()->getByName(rPropertyName);
+ if(!pEntry )
+ {
+ const SfxItemPropertySet* _pParaPropSet = aSwMapProvider.GetPropertySet(PROPERTY_MAP_PARAGRAPH_EXTENSIONS);
+ pEntry = _pParaPropSet->getPropertyMap()->getByName(rPropertyName);
+ }
+ if (!pEntry)
+ throw beans::UnknownPropertyException(OUString ( RTL_CONSTASCII_USTRINGPARAM ( "Unknown property: " ) ) + rPropertyName, static_cast < cppu::OWeakObject * > ( this ) );
+
+ switch( pEntry->nWID )
+ {
+ case FN_UNO_TEXT_WRAP:
+ aRet <<= text::WrapTextMode_NONE;
+ break;
+ case FN_UNO_ANCHOR_TYPE:
+ aRet <<= text::TextContentAnchorType_AS_CHARACTER;
+ break;
+ case FN_UNO_ANCHOR_TYPES:
+ {
+ uno::Sequence<text::TextContentAnchorType> aTypes(1);
+ text::TextContentAnchorType* pArray = aTypes.getArray();
+ pArray[0] = text::TextContentAnchorType_AS_CHARACTER;
+ aRet.setValue(&aTypes, ::getCppuType(static_cast<uno::Sequence<text::TextContentAnchorType>*>(0)));
+ }
+ break;
+
+ default:
+ if( pField )
+ {
+ if (FIELD_PROP_IS_FIELD_USED == pEntry->nWID ||
+ FIELD_PROP_IS_FIELD_DISPLAYED == pEntry->nWID)
+ {
+ sal_Bool bIsFieldUsed = sal_False;
+ sal_Bool bIsFieldDisplayed = sal_False;
+
+ // in order to have the information about fields
+ // correctly evaluated the document needs a layout
+ // (has to be already formatted)
+ SwDoc *pDoc = GetDoc();
+ ViewShell *pViewShell = 0;
+ SwEditShell *pEditShell = pDoc ? pDoc->GetEditShell( &pViewShell ) : 0;
+ if (pEditShell)
+ pEditShell->CalcLayout();
+ else if (pViewShell) // a page preview has no SwEditShell it should only have a view shell
+ pViewShell->CalcLayout();
+ else
+ throw uno::RuntimeException();
+
+ // get text node for the text field
+ const SwFmtFld *pFldFmt = GetFldFmt();
+ const SwTxtFld* pTxtFld = pFldFmt ? pFmtFld->GetTxtFld() : 0;
+ if(!pTxtFld)
+ throw uno::RuntimeException();
+ const SwTxtNode& rTxtNode = pTxtFld->GetTxtNode();
+
+ // skip fields that are currently not in the document
+ // e.g. fields in undo or redo array
+ if (rTxtNode.GetNodes().IsDocNodes())
+ {
+ sal_Bool bFrame = 0 != rTxtNode.FindLayoutRect().Width(); // oder so
+ sal_Bool bHidden = rTxtNode.IsHidden();
+ if ( !bHidden )
+ {
+ xub_StrLen nHiddenStart;
+ xub_StrLen nHiddenEnd;
+
+ SwPosition aPosition( pTxtFld->GetTxtNode() );
+ aPosition.nContent = *pTxtFld->GetStart();
+
+ bHidden = SwScriptInfo::GetBoundsOfHiddenRange( pTxtFld->GetTxtNode(),
+ *pTxtFld->GetStart(),
+ nHiddenStart, nHiddenEnd );
+ }
+
+ // !bFrame && !bHidden: aller Wahrscheinlichkeit handelt es
+ // sich um ein Feld in einem unbenutzten Seitenstyle
+ //
+ // bHidden: Feld ist versteckt
+ // FME: Problem: Verstecktes Feld in unbenutzter Seitenvorlage =>
+ // bIsFieldUsed = true
+ // bIsFieldDisplayed = false
+ bIsFieldUsed = bFrame || bHidden;
+ bIsFieldDisplayed = bIsFieldUsed && !bHidden;
+ }
+ sal_Bool bRetVal = (FIELD_PROP_IS_FIELD_USED == pEntry->nWID) ?
+ bIsFieldUsed : bIsFieldDisplayed;
+ aRet.setValue( &bRetVal, ::getCppuBooleanType() );
+ }
+ else
+ pField->QueryValue( aRet, pEntry->nWID );
+ }
+ else if( m_pProps ) // currently just a descriptor...
+ {
+ switch(pEntry->nWID)
+ {
+ case FIELD_PROP_TEXT:
+ {
+ if (!m_pTextObject)
+ {
+ SwTextAPIEditSource* pObj = new SwTextAPIEditSource( m_pDoc );
+ m_pTextObject = new SwTextAPIObject( pObj );
+ m_pTextObject->acquire();
+ }
+
+ uno::Reference < text::XText > xText( m_pTextObject );
+ aRet <<= xText;
+ break;
+ }
+ case FIELD_PROP_PAR1:
+ aRet <<= OUString(m_pProps->sPar1);
+ break;
+ case FIELD_PROP_PAR2:
+ aRet <<= OUString(m_pProps->sPar2);
+ break;
+ case FIELD_PROP_PAR3:
+ aRet <<= OUString(m_pProps->sPar3);
+ break;
+ case FIELD_PROP_PAR4:
+ aRet <<= OUString(m_pProps->sPar4);
+ break;
+ case FIELD_PROP_FORMAT:
+ aRet <<= m_pProps->nFormat;
+ break;
+ case FIELD_PROP_SUBTYPE:
+ aRet <<= m_pProps->nSubType;
+ break;
+ case FIELD_PROP_BYTE1 :
+ aRet <<= m_pProps->nByte1;
+ break;
+ case FIELD_PROP_BOOL1 :
+ aRet.setValue(&m_pProps->bBool1, ::getCppuBooleanType());
+ break;
+ case FIELD_PROP_BOOL2 :
+ aRet.setValue(&m_pProps->bBool2, ::getCppuBooleanType());
+ break;
+ case FIELD_PROP_BOOL3 :
+ aRet.setValue(&m_pProps->bBool3, ::getCppuBooleanType());
+ break;
+ case FIELD_PROP_BOOL4 :
+ aRet.setValue(&m_pProps->bBool4, ::getCppuBooleanType());
+ break;
+ case FIELD_PROP_DATE :
+ aRet.setValue(&m_pProps->aDate, ::getCppuType(static_cast<const util::Date*>(0)));
+ break;
+ case FIELD_PROP_USHORT1:
+ aRet <<= (sal_Int16)m_pProps->nUSHORT1;
+ break;
+ case FIELD_PROP_USHORT2:
+ aRet <<= (sal_Int16)m_pProps->nUSHORT2;
+ break;
+ case FIELD_PROP_SHORT1:
+ aRet <<= m_pProps->nSHORT1;
+ break;
+ case FIELD_PROP_DOUBLE:
+ aRet <<= m_pProps->fDouble;
+ break;
+ case FIELD_PROP_DATE_TIME :
+ if(m_pProps->pDateTime)
+ aRet <<= (*m_pProps->pDateTime);
+ break;
+ case FIELD_PROP_PROP_SEQ:
+ aRet <<= m_pProps->aPropSeq;
+ break;
+ case FIELD_PROP_STRINGS:
+ aRet <<= m_pProps->aStrings;
+ break;
+ case FIELD_PROP_IS_FIELD_USED:
+ case FIELD_PROP_IS_FIELD_DISPLAYED:
+ aRet.setValue( sal_False, ::getCppuBooleanType() );
+ break;
+ }
+ }
+ else
+ throw uno::RuntimeException();
+ }
+ return aRet;
+}
+
+void SwXTextField::addPropertyChangeListener(const OUString& /*PropertyName*/, const uno::Reference< beans::XPropertyChangeListener > & /*aListener*/) throw( beans::UnknownPropertyException, lang::WrappedTargetException, uno::RuntimeException )
+{
+ DBG_WARNING("not implemented");
+}
+
+void SwXTextField::removePropertyChangeListener(const OUString& /*PropertyName*/, const uno::Reference< beans::XPropertyChangeListener > & /*aListener*/) throw( beans::UnknownPropertyException, lang::WrappedTargetException, uno::RuntimeException )
+{
+ DBG_WARNING("not implemented");
+}
+
+void SwXTextField::addVetoableChangeListener(const OUString& /*PropertyName*/, const uno::Reference< beans::XVetoableChangeListener > & /*aListener*/) throw( beans::UnknownPropertyException, lang::WrappedTargetException, uno::RuntimeException )
+{
+ DBG_WARNING("not implemented");
+}
+
+void SwXTextField::removeVetoableChangeListener(const OUString& /*PropertyName*/, const uno::Reference< beans::XVetoableChangeListener > & /*aListener*/) throw( beans::UnknownPropertyException, lang::WrappedTargetException, uno::RuntimeException )
+{
+ DBG_WARNING("not implemented");
+}
+
+void SwXTextField::update( ) throw (uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+ const SwField* pFld = GetField();
+ if(pFld)
+ {
+ switch(pFld->Which())
+ {
+ case RES_DATETIMEFLD:
+ ((SwDateTimeField*)pFld)->SetDateTime( ::DateTime() );
+ break;
+
+ case RES_EXTUSERFLD:
+ {
+ SwExtUserField* pExtUserFld = (SwExtUserField*)pFld;
+ pExtUserFld->SetExpansion( ((SwExtUserFieldType*)pFld->GetTyp())->Expand(
+ pExtUserFld->GetSubType(),
+ pExtUserFld->GetFormat() ) );
+ }
+ break;
+
+ case RES_AUTHORFLD:
+ {
+ SwAuthorField* pAuthorFld = (SwAuthorField*)pFld;
+ pAuthorFld->SetExpansion( ((SwAuthorFieldType*)pFld->GetTyp())->Expand(
+ pAuthorFld->GetFormat() ) );
+ }
+ break;
+
+ case RES_FILENAMEFLD:
+ {
+ SwFileNameField* pFileNameFld = (SwFileNameField*)pFld;
+ pFileNameFld->SetExpansion( ((SwFileNameFieldType*)pFld->GetTyp())->Expand(
+ pFileNameFld->GetFormat() ) );
+ }
+ break;
+
+ case RES_DOCINFOFLD:
+ {
+ SwDocInfoField* pDocInfFld = (SwDocInfoField*)pFld;
+ pDocInfFld->SetExpansion( ((SwDocInfoFieldType*)pFld->GetTyp())->Expand(
+ pDocInfFld->GetSubType(),
+ pDocInfFld->GetFormat(),
+ pDocInfFld->GetLanguage(),
+ pDocInfFld->GetName() ) );
+ }
+ break;
+ }
+ // Text formatting has to be triggered.
+ const_cast<SwFmtFld*>(pFmtFld)->ModifyNotification( 0, 0 );
+ }
+ else
+ m_bCallUpdate = sal_True;
+}
+
+OUString SwXTextField::getImplementationName(void) throw( uno::RuntimeException )
+{
+ return C2U("SwXTextField");
+}
+
+static OUString OldNameToNewName_Impl( const OUString &rOld )
+{
+ static OUString aOldNamePart1(RTL_CONSTASCII_USTRINGPARAM(".TextField.DocInfo."));
+ static OUString aOldNamePart2(RTL_CONSTASCII_USTRINGPARAM(".TextField."));
+ static OUString aNewNamePart1(RTL_CONSTASCII_USTRINGPARAM(".textfield.docinfo."));
+ static OUString aNewNamePart2(RTL_CONSTASCII_USTRINGPARAM(".textfield."));
+ OUString sServiceNameCC( rOld );
+ sal_Int32 nIdx = sServiceNameCC.indexOf( aOldNamePart1 );
+ if (nIdx >= 0)
+ sServiceNameCC = sServiceNameCC.replaceAt( nIdx, aOldNamePart1.getLength(), aNewNamePart1 );
+ nIdx = sServiceNameCC.indexOf( aOldNamePart2 );
+ if (nIdx >= 0)
+ sServiceNameCC = sServiceNameCC.replaceAt( nIdx, aOldNamePart2.getLength(), aNewNamePart2 );
+ return sServiceNameCC;
+}
+
+sal_Bool SwXTextField::supportsService(const OUString& rServiceName) throw( uno::RuntimeException )
+{
+ OUString sServiceName = SwXServiceProvider::GetProviderName(m_nServiceId);
+
+ // case-corected version of service-name (see #i67811)
+ // (need to supply both because of compatibility to older versions)
+ OUString sServiceNameCC( OldNameToNewName_Impl( sServiceName ) );
+
+ return sServiceName == rServiceName || sServiceNameCC == rServiceName ||
+ rServiceName.equalsAsciiL(
+ RTL_CONSTASCII_STRINGPARAM("com.sun.star.text.TextContent"));
+}
+
+uno::Sequence< OUString > SwXTextField::getSupportedServiceNames(void) throw( uno::RuntimeException )
+{
+ OUString sServiceName = SwXServiceProvider::GetProviderName(m_nServiceId);
+
+ // case-corected version of service-name (see #i67811)
+ // (need to supply both because of compatibility to older versions)
+ OUString sServiceNameCC( OldNameToNewName_Impl( sServiceName ) );
+ sal_Int32 nLen = sServiceName == sServiceNameCC ? 2 : 3;
+
+ uno::Sequence< OUString > aRet( nLen );
+ OUString* pArray = aRet.getArray();
+ *pArray++ = sServiceName;
+ if (nLen == 3)
+ *pArray++ = sServiceNameCC;
+ *pArray++ = C2U("com.sun.star.text.TextContent");
+ return aRet;
+}
+
+void SwXTextField::Invalidate()
+{
+ if (GetRegisteredIn())
+ {
+ ((SwModify*)GetRegisteredIn())->Remove(this);
+ aLstnrCntnr.Disposing();
+ pFmtFld = 0;
+ m_pDoc = 0;
+ }
+}
+
+
+void SwXTextField::Modify( const SfxPoolItem* pOld, const SfxPoolItem *pNew)
+{
+ switch( pOld ? pOld->Which() : 0 )
+ {
+ case RES_REMOVE_UNO_OBJECT:
+ case RES_OBJECTDYING:
+ if( (void*)GetRegisteredIn() == ((SwPtrMsgPoolItem *)pOld)->pObject )
+ Invalidate();
+ break;
+
+ case RES_FMT_CHG:
+ // wurden wir an das neue umgehaengt und wird das alte geloscht?
+ if( ((SwFmtChg*)pNew)->pChangedFmt == GetRegisteredIn() &&
+ ((SwFmtChg*)pOld)->pChangedFmt->IsFmtInDTOR() )
+ Invalidate();
+ break;
+ case RES_FIELD_DELETED:
+ if( (void*)pFmtFld == ((SwPtrMsgPoolItem *)pOld)->pObject )
+ Invalidate();
+ break;
+ }
+}
+
+const SwField* SwXTextField::GetField() const
+{
+ if(GetRegisteredIn() && pFmtFld)
+ return pFmtFld->GetFld();
+ return 0;
+}
+
+/******************************************************************
+ * SwXTextFieldMasters
+ ******************************************************************/
+OUString SwXTextFieldMasters::getImplementationName(void) throw( uno::RuntimeException )
+{
+ return C2U("SwXTextFieldMasters");
+}
+
+sal_Bool SwXTextFieldMasters::supportsService(const OUString& rServiceName) throw( uno::RuntimeException )
+{
+ return rServiceName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM(
+ "com.sun.star.text.TextFieldMasters" ));
+}
+
+uno::Sequence< OUString > SwXTextFieldMasters::getSupportedServiceNames(void) throw( uno::RuntimeException )
+{
+ uno::Sequence< OUString > aRet(1);
+ OUString* pArray = aRet.getArray();
+ pArray[0] = C2U("com.sun.star.text.TextFieldMasters");
+ return aRet;
+}
+
+SwXTextFieldMasters::SwXTextFieldMasters(SwDoc* _pDoc) :
+ SwUnoCollection(_pDoc)
+{
+}
+
+SwXTextFieldMasters::~SwXTextFieldMasters()
+{
+
+}
+
+/*-----------------------------------------------------------------------
+ Iteration ueber nicht-Standard Feldtypen
+ USER/SETEXP/DDE/DATABASE
+ Der Name ist demnach:
+ "com.sun.star.text.fieldmaster.User" + <Feltypname>
+ "com.sun.star.text.fieldmaster.DDE" + <Feltypname>
+ "com.sun.star.text.fieldmaster.SetExpression" + <Feltypname>
+ "com.sun.star.text.fieldmaster.DataBase" + <Feltypname>
+
+ Falls wir grosszuegig werden wollen, dann koennte man com.sun.star.text
+ auch optional weglassen
+ -----------------------------------------------------------------------*/
+sal_uInt16 lcl_GetIdByName( String& rName, String& rTypeName )
+{
+ if( rName.EqualsAscii( COM_TEXT_FLDMASTER, 0, RTL_CONSTASCII_LENGTH(COM_TEXT_FLDMASTER ))
+ || rName.EqualsAscii( COM_TEXT_FLDMASTER_CC, 0, RTL_CONSTASCII_LENGTH(COM_TEXT_FLDMASTER_CC )))
+ rName.Erase(0, 30);
+
+ sal_uInt16 nResId = USHRT_MAX;
+ xub_StrLen nFound = 0;
+ rTypeName = rName.GetToken( 0, '.', nFound );
+ if(rTypeName.EqualsAscii("User"))
+ nResId = RES_USERFLD;
+ else if(rTypeName.EqualsAscii("DDE"))
+ nResId = RES_DDEFLD;
+ else if(rTypeName.EqualsAscii("SetExpression"))
+ {
+ nResId = RES_SETEXPFLD;
+
+ String sFldTypName( rName.GetToken( 1, '.' ));
+ String sUIName( SwStyleNameMapper::GetSpecialExtraUIName( sFldTypName ) );
+
+ if( sUIName != sFldTypName )
+ rName.SetToken( 1, '.', sUIName );
+ }
+ else if(rTypeName.EqualsAscii("DataBase"))
+ {
+ rName.Erase( 0, RTL_CONSTASCII_LENGTH( "DataBase." ));
+ sal_uInt16 nDotCount = rName.GetTokenCount('.');
+ if( 2 <= nDotCount )
+ {
+ // #i51815#
+ //rName.SearchAndReplace('.', DB_DELIM);
+ //rName.SetChar( rName.SearchBackward( '.' ), DB_DELIM );
+
+ rName.InsertAscii( "DataBase.", 0 );
+ nResId = RES_DBFLD;
+ }
+ }
+ else if( rTypeName.EqualsAscii("Bibliography"))
+ nResId = RES_AUTHORITY;
+ return nResId;
+}
+
+uno::Any SwXTextFieldMasters::getByName(const OUString& rName)
+ throw( container::NoSuchElementException, lang::WrappedTargetException, uno::RuntimeException )
+{
+ SolarMutexGuard aGuard;
+ if(!GetDoc())
+ throw uno::RuntimeException();
+
+ String sName(rName), sTypeName;
+ sal_uInt16 nResId = lcl_GetIdByName( sName, sTypeName );
+ if( USHRT_MAX == nResId )
+ throw container::NoSuchElementException();
+
+ sName.Erase(0, sTypeName.Len()+1);
+ SwFieldType* pType = GetDoc()->GetFldType(nResId, sName, sal_True);
+ if(!pType)
+ throw container::NoSuchElementException();
+ SwXFieldMaster* pMaster = SwIterator<SwXFieldMaster,SwFieldType>::FirstElement( *pType );
+ if(!pMaster)
+ pMaster = new SwXFieldMaster(*pType, GetDoc());
+ uno::Reference< beans::XPropertySet > aRef = pMaster;
+ uno::Any aRet(&aRef, ::getCppuType( static_cast<const uno::Reference<beans::XPropertySet>* >(0)));
+ return aRet;
+}
+
+sal_Bool SwXTextFieldMasters::getInstanceName(
+ const SwFieldType& rFldType, String& rName)
+{
+ sal_Bool bRet = sal_True;
+ switch( rFldType.Which() )
+ {
+ case RES_USERFLD:
+ rName.AppendAscii( RTL_CONSTASCII_STRINGPARAM( COM_TEXT_FLDMASTER_CC ));
+ rName.AppendAscii( RTL_CONSTASCII_STRINGPARAM( "User."));
+ rName += rFldType.GetName();
+ break;
+ case RES_DDEFLD:
+ rName.AppendAscii( RTL_CONSTASCII_STRINGPARAM( COM_TEXT_FLDMASTER_CC ));
+ rName.AppendAscii( RTL_CONSTASCII_STRINGPARAM( "DDE."));
+ rName += rFldType.GetName();
+ break;
+
+ case RES_SETEXPFLD:
+ rName.AppendAscii( RTL_CONSTASCII_STRINGPARAM( COM_TEXT_FLDMASTER_CC ));
+ rName.AppendAscii( RTL_CONSTASCII_STRINGPARAM( "SetExpression."));
+ rName += String( SwStyleNameMapper::GetSpecialExtraProgName( rFldType.GetName() ) );
+ break;
+
+ case RES_DBFLD:
+ {
+ rName.AppendAscii( RTL_CONSTASCII_STRINGPARAM( COM_TEXT_FLDMASTER_CC ));
+ rName.AppendAscii( RTL_CONSTASCII_STRINGPARAM( "DataBase."));
+ String sDBName(rFldType.GetName());
+ sDBName.SearchAndReplaceAll(DB_DELIM, '.');
+ rName += sDBName;
+ }
+ break;
+
+ case RES_AUTHORITY:
+ rName.AppendAscii( RTL_CONSTASCII_STRINGPARAM( COM_TEXT_FLDMASTER_CC ));
+ rName.AppendAscii( RTL_CONSTASCII_STRINGPARAM( "Bibliography"));
+ break;
+
+ default:
+ bRet = sal_False;
+ }
+
+ return bRet;
+}
+
+uno::Sequence< OUString > SwXTextFieldMasters::getElementNames(void)
+ throw( uno::RuntimeException )
+{
+ SolarMutexGuard aGuard;
+ if(!GetDoc())
+ throw uno::RuntimeException();
+
+ const SwFldTypes* pFldTypes = GetDoc()->GetFldTypes();
+ sal_uInt16 nCount = pFldTypes->Count();
+
+ SvStrings aFldNames;
+ String* pString = new String();
+ sal_uInt16 i;
+
+ for( i = 0; i < nCount; i++)
+ {
+ SwFieldType& rFldType = *((*pFldTypes)[i]);
+
+ if (SwXTextFieldMasters::getInstanceName(rFldType, *pString))
+ {
+ aFldNames.Insert(pString, aFldNames.Count());
+ pString = new String();
+ }
+ }
+ delete pString;
+
+ uno::Sequence< OUString > aSeq(aFldNames.Count());
+ OUString* pArray = aSeq.getArray();
+ for(i = 0; i < aFldNames.Count();i++)
+ {
+ pArray[i] = *aFldNames.GetObject(i);
+ }
+ aFldNames.DeleteAndDestroy(0, aFldNames.Count());
+
+ return aSeq;
+
+}
+
+sal_Bool SwXTextFieldMasters::hasByName(const OUString& rName) throw( uno::RuntimeException )
+{
+ SolarMutexGuard aGuard;
+ if(!GetDoc())
+ throw uno::RuntimeException();
+
+ String sName(rName), sTypeName;
+ sal_uInt16 nResId = lcl_GetIdByName( sName, sTypeName );
+ sal_Bool bRet = sal_False;
+ if( USHRT_MAX != nResId )
+ {
+ sName.Erase(0, sTypeName.Len()+1);
+ bRet = USHRT_MAX != nResId && 0 != GetDoc()->GetFldType(nResId, sName, sal_True);
+ }
+ return bRet;
+}
+
+uno::Type SwXTextFieldMasters::getElementType(void) throw( uno::RuntimeException )
+{
+ return ::getCppuType(static_cast<const uno::Reference<beans::XPropertySet>*>(0));
+
+}
+
+sal_Bool SwXTextFieldMasters::hasElements(void) throw( uno::RuntimeException )
+{
+ SolarMutexGuard aGuard;
+ if(!IsValid())
+ throw uno::RuntimeException();
+ return sal_True;
+}
+
+OUString SwXTextFieldTypes::getImplementationName(void) throw( uno::RuntimeException )
+{
+ return C2U("SwXTextFieldTypes");
+}
+
+sal_Bool SwXTextFieldTypes::supportsService(const OUString& rServiceName) throw( uno::RuntimeException )
+{
+ return rServiceName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM(
+ "com.sun.star.text.TextFields" ));
+}
+
+uno::Sequence< OUString > SwXTextFieldTypes::getSupportedServiceNames(void) throw( uno::RuntimeException )
+{
+ uno::Sequence< OUString > aRet(1);
+ OUString* pArray = aRet.getArray();
+ pArray[0] = C2U("com.sun.star.text.TextFields");
+ return aRet;
+}
+
+SwXTextFieldTypes::SwXTextFieldTypes(SwDoc* _pDoc) :
+ SwUnoCollection (_pDoc),
+ aRefreshCont ( static_cast< XEnumerationAccess * >(this) )
+{
+}
+
+SwXTextFieldTypes::~SwXTextFieldTypes()
+{
+}
+
+void SwXTextFieldTypes::Invalidate()
+{
+ SwUnoCollection::Invalidate();
+ aRefreshCont.Disposing();
+}
+
+uno::Reference< container::XEnumeration > SwXTextFieldTypes::createEnumeration(void)
+ throw( uno::RuntimeException )
+{
+ SolarMutexGuard aGuard;
+ if(!IsValid())
+ throw uno::RuntimeException();
+ return new SwXFieldEnumeration(GetDoc());
+}
+
+uno::Type SwXTextFieldTypes::getElementType(void) throw( uno::RuntimeException )
+{
+ return ::getCppuType(static_cast<const uno::Reference<text::XDependentTextField>*>(0));
+}
+
+sal_Bool SwXTextFieldTypes::hasElements(void) throw( uno::RuntimeException )
+{
+ SolarMutexGuard aGuard;
+ if(!IsValid())
+ throw uno::RuntimeException();
+ //es gibt sie immer
+ return sal_True;
+}
+
+void SwXTextFieldTypes::refresh(void) throw( uno::RuntimeException )
+{
+ SolarMutexGuard aGuard;
+ if(!IsValid())
+ throw uno::RuntimeException();
+ UnoActionContext aContext(GetDoc());
+ SwDocStat aDocStat;
+ GetDoc()->UpdateDocStat(aDocStat);
+ GetDoc()->UpdateFlds(0, sal_False);
+
+ // call refresh listeners
+ aRefreshCont.Refreshed();
+}
+
+void SwXTextFieldTypes::addRefreshListener(const uno::Reference< util::XRefreshListener > & l)
+ throw( uno::RuntimeException )
+{
+ SolarMutexGuard aGuard;
+ if ( !IsValid() )
+ throw uno::RuntimeException();
+ aRefreshCont.AddListener ( reinterpret_cast < const uno::Reference < lang::XEventListener > &> ( l ));
+}
+
+void SwXTextFieldTypes::removeRefreshListener(const uno::Reference< util::XRefreshListener > & l)
+ throw( uno::RuntimeException )
+{
+ SolarMutexGuard aGuard;
+ if ( !IsValid() || !aRefreshCont.RemoveListener ( reinterpret_cast < const uno::Reference < lang::XEventListener > &> ( l ) ) )
+ throw uno::RuntimeException();
+}
+
+/******************************************************************
+ * SwXFieldEnumeration
+ ******************************************************************/
+OUString SwXFieldEnumeration::getImplementationName(void) throw( uno::RuntimeException )
+{
+ return C2U("SwXFieldEnumeration");
+}
+
+sal_Bool SwXFieldEnumeration::supportsService(const OUString& rServiceName) throw( uno::RuntimeException )
+{
+ return rServiceName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM(
+ "com.sun.star.text.FieldEnumeration" ));
+}
+
+uno::Sequence< OUString > SwXFieldEnumeration::getSupportedServiceNames(void) throw( uno::RuntimeException )
+{
+ uno::Sequence< OUString > aRet(1);
+ OUString* pArray = aRet.getArray();
+ pArray[0] = C2U("com.sun.star.text.FieldEnumeration");
+ return aRet;
+}
+
+SwXFieldEnumeration::SwXFieldEnumeration(SwDoc* pDc) :
+ nNextIndex(0),
+ pDoc(pDc)
+{
+ pDoc->GetPageDescFromPool(RES_POOLPAGE_STANDARD)->Add(this);
+
+ // build sequence
+ sal_Int32 nSize = 32;
+ aItems.realloc( nSize );
+ uno::Reference< text::XTextField > *pItems = aItems.getArray();
+ sal_Int32 nFillPos = 0;
+ //
+ const SwFldTypes* pFldTypes = pDoc->GetFldTypes();
+ sal_uInt16 nCount = pFldTypes->Count();
+ for(sal_uInt16 nType = 0; nType < nCount; ++nType)
+ {
+ const SwFieldType *pCurType = pFldTypes->GetObject(nType);
+ SwIterator<SwFmtFld,SwFieldType> aIter( *pCurType );
+ const SwFmtFld* pCurFldFmt = aIter.First();
+ while (pCurFldFmt)
+ {
+ const SwTxtFld *pTxtFld = pCurFldFmt->GetTxtFld();
+ // skip fields that are currently not in the document
+ // e.g. fields in undo or redo array
+ sal_Bool bSkip = !pTxtFld ||
+ !pTxtFld->GetpTxtNode()->GetNodes().IsDocNodes();
+ if (!bSkip)
+ pItems[ nFillPos++ ] = new SwXTextField(*pCurFldFmt, pDoc);
+ pCurFldFmt = aIter.Next();
+
+ // enlarge sequence if necessary
+ if (aItems.getLength() == nFillPos)
+ {
+ aItems.realloc( 2 * aItems.getLength() );
+ pItems = aItems.getArray();
+ }
+ }
+ }
+ // now handle meta-fields, which are not SwFields
+ const ::std::vector< uno::Reference<text::XTextField> > MetaFields(
+ pDc->GetMetaFieldManager().getMetaFields() );
+ for (size_t i = 0; i < MetaFields.size(); ++i)
+ {
+ pItems[ nFillPos ] = MetaFields[i];
+ nFillPos++;
+
+ //FIXME UGLY
+ // enlarge sequence if necessary
+ if (aItems.getLength() == nFillPos)
+ {
+ aItems.realloc( 2 * aItems.getLength() );
+ pItems = aItems.getArray();
+ }
+ }
+ // resize sequence to actual used size
+ aItems.realloc( nFillPos );
+}
+
+SwXFieldEnumeration::~SwXFieldEnumeration()
+{
+
+}
+
+sal_Bool SwXFieldEnumeration::hasMoreElements(void)
+ throw( uno::RuntimeException )
+{
+ SolarMutexGuard aGuard;
+ return nNextIndex < aItems.getLength();
+}
+
+uno::Any SwXFieldEnumeration::nextElement(void)
+ throw( container::NoSuchElementException, lang::WrappedTargetException, uno::RuntimeException )
+{
+ SolarMutexGuard aGuard;
+
+ if (!(nNextIndex < aItems.getLength()))
+ throw container::NoSuchElementException();
+
+#if OSL_DEBUG_LEVEL > 1
+ uno::Reference< text::XTextField > *pItems = aItems.getArray();
+ (void)pItems;
+#endif
+ uno::Reference< text::XTextField > &rxFld = aItems.getArray()[ nNextIndex++ ];
+ uno::Any aRet(&rxFld, ::getCppuType(static_cast<const uno::Reference<text::XTextField>*>(0)));
+ rxFld = 0; // free memory for item that is not longer used
+ return aRet;
+}
+
+void SwXFieldEnumeration::Modify( const SfxPoolItem* pOld, const SfxPoolItem *pNew)
+{
+ ClientModify(this, pOld, pNew);
+ if(!GetRegisteredIn())
+ pDoc = 0;
+}
+
+String& GetString( const uno::Any& rAny, String& rStr )
+{
+ OUString aStr;
+ rAny >>= aStr;
+ rStr = String( aStr );
+ return rStr;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/unocore/unoflatpara.cxx b/sw/source/core/unocore/unoflatpara.cxx
new file mode 100644
index 000000000000..17538a119b35
--- /dev/null
+++ b/sw/source/core/unocore/unoflatpara.cxx
@@ -0,0 +1,533 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+#include <editeng/unolingu.hxx>
+
+#include <unobaseclass.hxx>
+#include <unoflatpara.hxx>
+
+#include <osl/mutex.hxx>
+#include <vcl/svapp.hxx>
+#include <com/sun/star/text/TextMarkupType.hpp>
+#include <unotextmarkup.hxx>
+#include <ndtxt.hxx>
+#include <doc.hxx>
+#include <docsh.hxx>
+#include <viewsh.hxx>
+#include <viewimp.hxx>
+#include <breakit.hxx>
+#include <pam.hxx>
+#include <unotextrange.hxx>
+#include <pagefrm.hxx>
+#include <cntfrm.hxx>
+#include <rootfrm.hxx>
+#include <poolfmt.hxx>
+#include <pagedesc.hxx>
+#include <IGrammarContact.hxx>
+#include <viewopt.hxx>
+
+using namespace ::com::sun::star;
+
+/******************************************************************************
+ * SwXFlatParagraph
+ ******************************************************************************/
+
+SwXFlatParagraph::SwXFlatParagraph( SwTxtNode& rTxtNode, rtl::OUString aExpandText, const ModelToViewHelper::ConversionMap* pMap ) :
+ SwXTextMarkup( rTxtNode, pMap ),
+ maExpandText( aExpandText )
+{
+}
+
+SwXFlatParagraph::~SwXFlatParagraph()
+{
+}
+
+uno::Sequence< uno::Type > SwXFlatParagraph::getTypes( ) throw(uno::RuntimeException)
+{
+ uno::Sequence< uno::Type > aTypes = SwXTextMarkup::getTypes();
+ aTypes.realloc( aTypes.getLength() + 1 );
+ aTypes[aTypes.getLength()-1] = ::getCppuType((uno::Reference< text::XFlatParagraph >*)0);
+ return aTypes;
+}
+
+uno::Sequence< sal_Int8 > SwXFlatParagraph::getImplementationId( ) throw(uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+ static uno::Sequence< sal_Int8 > aId( 16 );
+ static sal_Bool bInit = sal_False;
+ if(!bInit)
+ {
+ rtl_createUuid( (sal_uInt8 *)(aId.getArray() ), 0, sal_True );
+ bInit = sal_True;
+ }
+ return aId;
+}
+
+uno::Any SAL_CALL SwXFlatParagraph::queryInterface( const uno::Type& rType ) throw(uno::RuntimeException)
+{
+ if ( rType == ::getCppuType((uno::Reference< text::XFlatParagraph >*)0) )
+ {
+ return uno::makeAny( uno::Reference < text::XFlatParagraph >(this) );
+ }
+ else
+ return SwXTextMarkup::queryInterface( rType );
+}
+
+void SAL_CALL SwXFlatParagraph::acquire() throw()
+{
+ SwXTextMarkup::acquire();
+}
+
+void SAL_CALL SwXFlatParagraph::release() throw()
+{
+ SwXTextMarkup::release();
+}
+
+const SwTxtNode* SwXFlatParagraph::getTxtNode() const
+{
+ return mpTxtNode;
+}
+
+css::uno::Reference< css::container::XStringKeyMap > SAL_CALL SwXFlatParagraph::getMarkupInfoContainer() throw (css::uno::RuntimeException)
+{
+ return SwXTextMarkup::getMarkupInfoContainer();
+}
+
+void SAL_CALL SwXFlatParagraph::commitTextMarkup(::sal_Int32 nType, const ::rtl::OUString & rIdentifier, ::sal_Int32 nStart, ::sal_Int32 nLength, const css::uno::Reference< css::container::XStringKeyMap > & rxMarkupInfoContainer) throw (css::uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+ SwXTextMarkup::commitTextMarkup( nType, rIdentifier, nStart, nLength, rxMarkupInfoContainer );
+}
+
+// text::XFlatParagraph:
+::rtl::OUString SAL_CALL SwXFlatParagraph::getText() throw (uno::RuntimeException)
+{
+ return maExpandText;
+}
+
+// text::XFlatParagraph:
+void SAL_CALL SwXFlatParagraph::setChecked( ::sal_Int32 nType, ::sal_Bool bVal ) throw (uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+
+ if ( mpTxtNode )
+ {
+ if ( text::TextMarkupType::SPELLCHECK == nType )
+ mpTxtNode->SetWrongDirty( !bVal );
+ else if ( text::TextMarkupType::SMARTTAG == nType )
+ mpTxtNode->SetSmartTagDirty( !bVal );
+ else if( text::TextMarkupType::PROOFREADING == nType )
+ {
+ mpTxtNode->SetGrammarCheckDirty( !bVal );
+ if( bVal )
+ ::finishGrammarCheck( *mpTxtNode );
+ }
+ }
+}
+
+// text::XFlatParagraph:
+::sal_Bool SAL_CALL SwXFlatParagraph::isChecked( ::sal_Int32 nType ) throw (uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+ if ( mpTxtNode )
+ {
+ if ( text::TextMarkupType::SPELLCHECK == nType )
+ return mpTxtNode->IsWrongDirty();
+ else if ( text::TextMarkupType::PROOFREADING == nType )
+ return mpTxtNode->IsGrammarCheckDirty();
+ else if ( text::TextMarkupType::SMARTTAG == nType )
+ return mpTxtNode->IsSmartTagDirty();
+ }
+
+ return sal_False;
+}
+
+// text::XFlatParagraph:
+::sal_Bool SAL_CALL SwXFlatParagraph::isModified() throw (uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+ return 0 == mpTxtNode;
+}
+
+// text::XFlatParagraph:
+lang::Locale SAL_CALL SwXFlatParagraph::getLanguageOfText(::sal_Int32 nPos, ::sal_Int32 nLen)
+ throw (uno::RuntimeException, lang::IllegalArgumentException)
+{
+ SolarMutexGuard aGuard;
+ if (!mpTxtNode)
+ return SvxCreateLocale( LANGUAGE_NONE );
+
+ const lang::Locale aLocale( SW_BREAKITER()->GetLocale( mpTxtNode->GetLang( static_cast<sal_uInt16>(nPos), static_cast<sal_uInt16>(nLen) ) ) );
+ return aLocale;
+}
+
+// text::XFlatParagraph:
+lang::Locale SAL_CALL SwXFlatParagraph::getPrimaryLanguageOfText(::sal_Int32 nPos, ::sal_Int32 nLen)
+ throw (uno::RuntimeException, lang::IllegalArgumentException)
+{
+ SolarMutexGuard aGuard;
+
+ if (!mpTxtNode)
+ return SvxCreateLocale( LANGUAGE_NONE );
+
+ const lang::Locale aLocale( SW_BREAKITER()->GetLocale( mpTxtNode->GetLang( static_cast<sal_uInt16>(nPos), static_cast<sal_uInt16>(nLen) ) ) );
+ return aLocale;
+}
+
+// text::XFlatParagraph:
+void SAL_CALL SwXFlatParagraph::changeText(::sal_Int32 nPos, ::sal_Int32 nLen, const ::rtl::OUString & aNewText, const css::uno::Sequence< css::beans::PropertyValue > & aAttributes) throw (css::uno::RuntimeException, css::lang::IllegalArgumentException)
+{
+ SolarMutexGuard aGuard;
+
+ if ( !mpTxtNode )
+ return;
+
+ SwTxtNode* pOldTxtNode = mpTxtNode;
+
+ SwPaM aPaM( *mpTxtNode, static_cast<sal_uInt16>(nPos), *mpTxtNode, static_cast<sal_uInt16>(nPos + nLen) );
+
+ UnoActionContext aAction( mpTxtNode->GetDoc() );
+
+ const uno::Reference< text::XTextRange > xRange =
+ SwXTextRange::CreateXTextRange(
+ *mpTxtNode->GetDoc(), *aPaM.GetPoint(), aPaM.GetMark() );
+ uno::Reference< beans::XPropertySet > xPropSet( xRange, uno::UNO_QUERY );
+ if ( xPropSet.is() )
+ {
+ for ( sal_uInt16 i = 0; i < aAttributes.getLength(); ++i )
+ xPropSet->setPropertyValue( aAttributes[i].Name, aAttributes[i].Value );
+ }
+
+ mpTxtNode = pOldTxtNode; // setPropertyValue() modifies this. We restore the old state.
+
+ IDocumentContentOperations* pIDCO = mpTxtNode->getIDocumentContentOperations();
+ pIDCO->ReplaceRange( aPaM, aNewText, false );
+
+ mpTxtNode = 0;
+}
+
+// text::XFlatParagraph:
+void SAL_CALL SwXFlatParagraph::changeAttributes(::sal_Int32 nPos, ::sal_Int32 nLen, const css::uno::Sequence< css::beans::PropertyValue > & aAttributes) throw (css::uno::RuntimeException, css::lang::IllegalArgumentException)
+{
+ SolarMutexGuard aGuard;
+
+ if ( !mpTxtNode )
+ return;
+
+ SwPaM aPaM( *mpTxtNode, static_cast<sal_uInt16>(nPos), *mpTxtNode, static_cast<sal_uInt16>(nPos + nLen) );
+
+ UnoActionContext aAction( mpTxtNode->GetDoc() );
+
+ const uno::Reference< text::XTextRange > xRange =
+ SwXTextRange::CreateXTextRange(
+ *mpTxtNode->GetDoc(), *aPaM.GetPoint(), aPaM.GetMark() );
+ uno::Reference< beans::XPropertySet > xPropSet( xRange, uno::UNO_QUERY );
+ if ( xPropSet.is() )
+ {
+ for ( sal_uInt16 i = 0; i < aAttributes.getLength(); ++i )
+ xPropSet->setPropertyValue( aAttributes[i].Name, aAttributes[i].Value );
+ }
+
+ mpTxtNode = 0;
+}
+
+// text::XFlatParagraph:
+css::uno::Sequence< ::sal_Int32 > SAL_CALL SwXFlatParagraph::getLanguagePortions() throw (css::uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+ return css::uno::Sequence< ::sal_Int32>();
+}
+
+
+const uno::Sequence< sal_Int8 >&
+SwXFlatParagraph::getUnoTunnelId()
+{
+ static uno::Sequence<sal_Int8> aSeq(CreateUnoTunnelId());
+ return aSeq;
+}
+
+
+sal_Int64 SAL_CALL
+SwXFlatParagraph::getSomething(
+ const uno::Sequence< sal_Int8 >& rId)
+ throw (uno::RuntimeException)
+{
+ return sw::UnoTunnelImpl(rId, this);
+}
+
+
+/******************************************************************************
+ * SwXFlatParagraphIterator
+ ******************************************************************************/
+
+SwXFlatParagraphIterator::SwXFlatParagraphIterator( SwDoc& rDoc, sal_Int32 nType, sal_Bool bAutomatic )
+ : mpDoc( &rDoc ),
+ mnType( nType ),
+ mbAutomatic( bAutomatic ),
+ mnCurrentNode( 0 ),
+ mnStartNode( 0 ),
+ mnEndNode( rDoc.GetNodes().Count() ),
+ mbWrapped( sal_False )
+{
+ //mnStartNode = mnCurrentNode = get node from current cursor TODO!
+
+ // register as listener and get notified when document is closed
+ mpDoc->GetPageDescFromPool( RES_POOLPAGE_STANDARD )->Add(this);
+}
+
+SwXFlatParagraphIterator::~SwXFlatParagraphIterator()
+{
+}
+
+
+void SwXFlatParagraphIterator::Modify( const SfxPoolItem* pOld, const SfxPoolItem *pNew )
+{
+ ClientModify( this, pOld, pNew );
+ // check if document gets closed...
+ if(!GetRegisteredIn())
+ {
+ SolarMutexGuard aGuard;
+ mpDoc = 0;
+ }
+}
+
+
+uno::Reference< text::XFlatParagraph > SwXFlatParagraphIterator::getFirstPara()
+ throw( uno::RuntimeException )
+{
+ return getNextPara(); // TODO
+}
+
+uno::Reference< text::XFlatParagraph > SwXFlatParagraphIterator::getNextPara()
+ throw( uno::RuntimeException )
+{
+ SolarMutexGuard aGuard;
+
+ uno::Reference< text::XFlatParagraph > xRet;
+ if (!mpDoc)
+ return xRet;
+
+ SwTxtNode* pRet = 0;
+ if ( mbAutomatic )
+ {
+ ViewShell* pViewShell = 0;
+ mpDoc->GetEditShell( &pViewShell );
+
+ SwPageFrm* pCurrentPage = pViewShell ? pViewShell->Imp()->GetFirstVisPage() : 0;
+ SwPageFrm* pStartPage = pCurrentPage;
+ SwPageFrm* pStopPage = 0;
+
+ while ( pCurrentPage != pStopPage )
+ {
+ if (mnType != text::TextMarkupType::SPELLCHECK || pCurrentPage->IsInvalidSpelling() )
+ {
+ // this method is supposed to return an empty paragraph in case Online Checking is disabled
+ if ( ( mnType == text::TextMarkupType::PROOFREADING || mnType == text::TextMarkupType::SPELLCHECK )
+ && !pViewShell->GetViewOptions()->IsOnlineSpell() )
+ return xRet;
+
+ // search for invalid content:
+ SwCntntFrm* pCnt = pCurrentPage->ContainsCntnt();
+
+ while( pCnt && pCurrentPage->IsAnLower( pCnt ) )
+ {
+ SwTxtNode* pTxtNode = dynamic_cast<SwTxtNode*>( pCnt->GetNode()->GetTxtNode() );
+
+ if ( pTxtNode &&
+ ((mnType == text::TextMarkupType::SPELLCHECK &&
+ pTxtNode->IsWrongDirty()) ||
+ (mnType == text::TextMarkupType::PROOFREADING &&
+ pTxtNode->IsGrammarCheckDirty())) )
+ {
+ pRet = pTxtNode;
+ break;
+ }
+
+ pCnt = pCnt->GetNextCntntFrm();
+ }
+ }
+
+ if ( pRet )
+ break;
+
+ // if there is no invalid text node on the current page,
+ // we validate the page
+ pCurrentPage->ValidateSpelling();
+
+ // proceed with next page, wrap at end of document if required:
+ pCurrentPage = static_cast<SwPageFrm*>(pCurrentPage->GetNext());
+
+ if ( !pCurrentPage && !pStopPage )
+ {
+ pStopPage = pStartPage;
+ pCurrentPage = static_cast<SwPageFrm*>(pViewShell->GetLayout()->Lower());
+ }
+ }
+ }
+ else // non-automatic checking
+ {
+ const SwNodes& rNodes = mpDoc->GetNodes();
+ const sal_uLong nMaxNodes = rNodes.Count();
+
+ while ( mnCurrentNode < mnEndNode && mnCurrentNode < nMaxNodes )
+ {
+ SwNode* pNd = rNodes[ mnCurrentNode ];
+
+ ++mnCurrentNode;
+
+ pRet = dynamic_cast<SwTxtNode*>(pNd);
+ if ( pRet )
+ break;
+
+ if ( mnCurrentNode == mnEndNode && !mbWrapped )
+ {
+ mnCurrentNode = 0;
+ mnEndNode = mnStartNode;
+ }
+ }
+ }
+
+ if ( pRet )
+ {
+ // Expand the string:
+ rtl::OUString aExpandText;
+ const ModelToViewHelper::ConversionMap* pConversionMap =
+ pRet->BuildConversionMap( aExpandText );
+
+ xRet = new SwXFlatParagraph( *pRet, aExpandText, pConversionMap );
+ // keep hard references...
+ m_aFlatParaList.insert( xRet );
+ }
+
+ return xRet;
+}
+
+uno::Reference< text::XFlatParagraph > SwXFlatParagraphIterator::getLastPara()
+ throw( uno::RuntimeException )
+{
+ return getNextPara();
+}
+
+uno::Reference< text::XFlatParagraph > SwXFlatParagraphIterator::getParaAfter(const uno::Reference< text::XFlatParagraph > & xPara)
+ throw ( uno::RuntimeException, lang::IllegalArgumentException )
+{
+ SolarMutexGuard aGuard;
+
+ uno::Reference< text::XFlatParagraph > xRet;
+ if (!mpDoc)
+ return xRet;
+
+ const uno::Reference<lang::XUnoTunnel> xFPTunnel(xPara, uno::UNO_QUERY);
+ OSL_ASSERT(xFPTunnel.is());
+ SwXFlatParagraph* const pFlatParagraph(sw::UnoTunnelGetImplementation<SwXFlatParagraph>(xFPTunnel));
+
+ if ( !pFlatParagraph )
+ return xRet;
+
+ const SwTxtNode* pCurrentNode = pFlatParagraph->getTxtNode();
+
+ if ( !pCurrentNode )
+ return xRet;
+
+ SwTxtNode* pNextTxtNode = 0;
+ const SwNodes& rNodes = pCurrentNode->GetDoc()->GetNodes();
+
+ for( sal_uLong nCurrentNode = pCurrentNode->GetIndex() + 1; nCurrentNode < rNodes.Count(); ++nCurrentNode )
+ {
+ SwNode* pNd = rNodes[ nCurrentNode ];
+ pNextTxtNode = dynamic_cast<SwTxtNode*>(pNd);
+ if ( pNextTxtNode )
+ break;
+ }
+
+ if ( pNextTxtNode )
+ {
+ // Expand the string:
+ rtl::OUString aExpandText;
+ const ModelToViewHelper::ConversionMap* pConversionMap =
+ pNextTxtNode->BuildConversionMap( aExpandText );
+
+ xRet = new SwXFlatParagraph( *pNextTxtNode, aExpandText, pConversionMap );
+ // keep hard references...
+ m_aFlatParaList.insert( xRet );
+ }
+
+ return xRet;
+}
+
+uno::Reference< text::XFlatParagraph > SwXFlatParagraphIterator::getParaBefore(const uno::Reference< text::XFlatParagraph > & xPara )
+ throw ( uno::RuntimeException, lang::IllegalArgumentException )
+{
+ SolarMutexGuard aGuard;
+
+ uno::Reference< text::XFlatParagraph > xRet;
+ if (!mpDoc)
+ return xRet;
+
+ const uno::Reference<lang::XUnoTunnel> xFPTunnel(xPara, uno::UNO_QUERY);
+ OSL_ASSERT(xFPTunnel.is());
+ SwXFlatParagraph* const pFlatParagraph(sw::UnoTunnelGetImplementation<SwXFlatParagraph>(xFPTunnel));
+
+ if ( !pFlatParagraph )
+ return xRet;
+
+ const SwTxtNode* pCurrentNode = pFlatParagraph->getTxtNode();
+
+ if ( !pCurrentNode )
+ return xRet;
+
+ SwTxtNode* pPrevTxtNode = 0;
+ const SwNodes& rNodes = pCurrentNode->GetDoc()->GetNodes();
+
+ for( sal_uLong nCurrentNode = pCurrentNode->GetIndex() - 1; nCurrentNode > 0; --nCurrentNode )
+ {
+ SwNode* pNd = rNodes[ nCurrentNode ];
+ pPrevTxtNode = dynamic_cast<SwTxtNode*>(pNd);
+ if ( pPrevTxtNode )
+ break;
+ }
+
+ if ( pPrevTxtNode )
+ {
+ // Expand the string:
+ rtl::OUString aExpandText;
+ const ModelToViewHelper::ConversionMap* pConversionMap =
+ pPrevTxtNode->BuildConversionMap( aExpandText );
+
+ xRet = new SwXFlatParagraph( *pPrevTxtNode, aExpandText, pConversionMap );
+ // keep hard references...
+ m_aFlatParaList.insert( xRet );
+ }
+
+ return xRet;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/unocore/unoframe.cxx b/sw/source/core/unocore/unoframe.cxx
new file mode 100644
index 000000000000..e23cf3c9d4eb
--- /dev/null
+++ b/sw/source/core/unocore/unoframe.cxx
@@ -0,0 +1,3144 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+ /*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+#include <com/sun/star/embed/NoVisualAreaSizeException.hpp>
+#include <com/sun/star/container/XChild.hpp>
+#include <com/sun/star/embed/XClassifiedObject.hpp>
+#include <com/sun/star/embed/XVisualObject.hpp>
+#include <com/sun/star/embed/XComponentSupplier.hpp>
+#include <com/sun/star/embed/EmbedStates.hpp>
+#include <com/sun/star/embed/Aspects.hpp>
+#include <com/sun/star/graphic/XGraphicProvider.hpp>
+#include <svx/svxids.hrc>
+#include <editeng/memberids.hrc>
+
+#include <swtypes.hxx>
+#include <cmdid.h>
+
+#include <memory>
+#include <hints.hxx>
+#include <doc.hxx>
+#include <IDocumentUndoRedo.hxx>
+#include <docsh.hxx>
+#include <editsh.hxx>
+#include <swcli.hxx>
+#include <ndindex.hxx>
+#include <pam.hxx>
+#include <ndnotxt.hxx>
+#include <svx/unomid.hxx>
+#include <unocrsr.hxx>
+#include <unocrsrhelper.hxx>
+#include <docstyle.hxx>
+#include <dcontact.hxx>
+#include <fmtcnct.hxx>
+#include <ndole.hxx>
+#include <frmfmt.hxx>
+#include <frame.hxx>
+#include <unotextrange.hxx>
+#include <unotextcursor.hxx>
+#include <unoparagraph.hxx>
+#include <unomap.hxx>
+#include <unoprnms.hxx>
+#include <unoevent.hxx>
+#include <com/sun/star/util/XModifyBroadcaster.hpp>
+#include <com/sun/star/table/ShadowFormat.hpp>
+#include <com/sun/star/style/GraphicLocation.hpp>
+#include <com/sun/star/text/GraphicCrop.hpp>
+#include <com/sun/star/text/TextContentAnchorType.hpp>
+#include <com/sun/star/text/XTextColumns.hpp>
+#include <com/sun/star/text/WrapTextMode.hpp>
+#include <com/sun/star/beans/PropertyAttribute.hpp>
+#include <com/sun/star/drawing/PointSequenceSequence.hpp>
+#include <com/sun/star/drawing/PointSequence.hpp>
+#include <com/sun/star/drawing/ColorMode.hpp>
+#include <tools/poly.hxx>
+#include <swundo.hxx>
+#include <unostyle.hxx>
+#include <svx/svdmodel.hxx>
+#include <svx/svdpage.hxx>
+#include <editeng/brshitem.hxx>
+#include <editeng/protitem.hxx>
+#include <fmtornt.hxx>
+#include <fmturl.hxx>
+#include <editeng/lrspitem.hxx>
+#include <editeng/ulspitem.hxx>
+#include <editeng/boxitem.hxx>
+#include <editeng/opaqitem.hxx>
+#include <editeng/prntitem.hxx>
+#include <editeng/shaditem.hxx>
+#include <fmtsrnd.hxx>
+#include <fmtfsize.hxx>
+#include <grfatr.hxx>
+#include <unoframe.hxx>
+#include <fmtanchr.hxx>
+#include <fmtclds.hxx>
+#include <fmtcntnt.hxx>
+#include <frmatr.hxx>
+#include <ndtxt.hxx>
+#include <ndgrf.hxx>
+#include <osl/mutex.hxx>
+#include <vcl/svapp.hxx>
+#include <sfx2/printer.hxx>
+#include <SwStyleNameMapper.hxx>
+#include <xmloff/xmlcnitm.hxx>
+#include <poolfmt.hxx>
+#include <pagedesc.hxx>
+#include <com/sun/star/style/XStyleFamiliesSupplier.hpp>
+#include <tools/urlobj.hxx>
+#include <editeng/frmdiritem.hxx>
+#include <fmtfollowtextflow.hxx>
+#include <fmtwrapinfluenceonobjpos.hxx>
+#include <toolkit/helper/vclunohelper.hxx>
+#include <switerator.hxx>
+
+// from fefly1.cxx
+extern sal_Bool lcl_ChkAndSetNewAnchor( const SwFlyFrm& rFly, SfxItemSet& rSet );
+
+using namespace ::com::sun::star;
+using ::rtl::OUString;
+
+using ::com::sun::star::frame::XModel;
+using ::com::sun::star::container::XNameAccess;
+using ::com::sun::star::style::XStyleFamiliesSupplier;
+
+const sal_Char sPackageProtocol[] = "vnd.sun.star.Package:";
+const sal_Char sGraphicObjectProtocol[] = "vnd.sun.star.GraphicObject:";
+
+/****************************************************************************
+ Rahmenbeschreibung
+****************************************************************************/
+class BaseFrameProperties_Impl
+{
+ SwUnoCursorHelper::SwAnyMapHelper aAnyMap;
+
+public:
+ virtual ~BaseFrameProperties_Impl();
+
+ void SetProperty(sal_uInt16 nWID, sal_uInt8 nMemberId, const uno::Any& rVal);
+ bool GetProperty(sal_uInt16 nWID, sal_uInt8 nMemberId, const uno::Any*& pAny );
+ bool FillBaseProperties(SfxItemSet& rToSet, const SfxItemSet &rFromSet, bool& rSizeFound);
+
+ virtual bool AnyToItemSet( SwDoc* pDoc, SfxItemSet& rFrmSet, SfxItemSet& rSet, bool& rSizeFound) = 0;
+
+};
+
+BaseFrameProperties_Impl::~BaseFrameProperties_Impl()
+{
+}
+
+void BaseFrameProperties_Impl::SetProperty(sal_uInt16 nWID, sal_uInt8 nMemberId, const uno::Any& rVal)
+{
+ aAnyMap.SetValue( nWID, nMemberId, rVal );
+}
+
+bool BaseFrameProperties_Impl::GetProperty(sal_uInt16 nWID, sal_uInt8 nMemberId, const uno::Any*& rpAny)
+{
+ return aAnyMap.FillValue( nWID, nMemberId, rpAny );
+}
+
+bool BaseFrameProperties_Impl::FillBaseProperties(SfxItemSet& rToSet, const SfxItemSet& rFromSet, bool& rSizeFound)
+{
+ bool bRet = true;
+ //Anker kommt auf jeden Fall in den Set
+ SwFmtAnchor aAnchor ( static_cast < const SwFmtAnchor & > ( rFromSet.Get ( RES_ANCHOR ) ) );
+ {
+ const ::uno::Any* pAnchorPgNo;
+ if(GetProperty(RES_ANCHOR, MID_ANCHOR_PAGENUM, pAnchorPgNo))
+ bRet &= ((SfxPoolItem&)aAnchor).PutValue(*pAnchorPgNo, MID_ANCHOR_PAGENUM);
+ const ::uno::Any* pAnchorType;
+ if(GetProperty(RES_ANCHOR, MID_ANCHOR_ANCHORTYPE, pAnchorType))
+ bRet &= ((SfxPoolItem&)aAnchor).PutValue(*pAnchorType, MID_ANCHOR_ANCHORTYPE);
+ }
+ rToSet.Put(aAnchor);
+ {
+ const ::uno::Any* pCol = 0;
+ GetProperty(RES_BACKGROUND, MID_BACK_COLOR, pCol );
+ const ::uno::Any* pRGBCol = 0;
+ GetProperty(RES_BACKGROUND, MID_BACK_COLOR_R_G_B, pRGBCol );
+ const ::uno::Any* pColTrans = 0;
+ GetProperty(RES_BACKGROUND, MID_BACK_COLOR_TRANSPARENCY, pColTrans);
+ const ::uno::Any* pTrans = 0;
+ GetProperty(RES_BACKGROUND, MID_GRAPHIC_TRANSPARENT, pTrans );
+ const ::uno::Any* pGrLoc = 0;
+ GetProperty(RES_BACKGROUND, MID_GRAPHIC_POSITION, pGrLoc );
+ const ::uno::Any* pGrURL = 0;
+ GetProperty(RES_BACKGROUND, MID_GRAPHIC_URL, pGrURL );
+ const ::uno::Any* pGrFilter = 0;
+ GetProperty(RES_BACKGROUND, MID_GRAPHIC_FILTER, pGrFilter );
+ const ::uno::Any* pGrTranparency = 0;
+ GetProperty(RES_BACKGROUND, MID_GRAPHIC_TRANSPARENCY, pGrTranparency );
+
+ if(pCol || pTrans || pGrURL || pGrFilter || pGrLoc ||
+ pGrTranparency || pColTrans || pRGBCol)
+ {
+ SvxBrushItem aBrush ( static_cast < const :: SvxBrushItem & > ( rFromSet.Get ( RES_BACKGROUND ) ) );
+ if(pCol )
+ bRet &= ((SfxPoolItem&)aBrush).PutValue(*pCol,MID_BACK_COLOR );
+ if(pColTrans)
+ bRet &= ((SfxPoolItem&)aBrush).PutValue(*pColTrans, MID_BACK_COLOR_TRANSPARENCY);
+ if(pRGBCol)
+ bRet &= ((SfxPoolItem&)aBrush).PutValue(*pRGBCol, MID_BACK_COLOR_R_G_B);
+ if(pTrans)
+ {
+ // don't overwrite transparency with a non-transparence flag
+ if(!pColTrans || Any2Bool( *pTrans ))
+ bRet &= ((SfxPoolItem&)aBrush).PutValue(*pTrans, MID_GRAPHIC_TRANSPARENT);
+ }
+ if(pGrURL)
+ bRet &= ((SfxPoolItem&)aBrush).PutValue(*pGrURL, MID_GRAPHIC_URL);
+ if(pGrFilter)
+ bRet &= ((SfxPoolItem&)aBrush).PutValue(*pGrFilter, MID_GRAPHIC_FILTER);
+ if(pGrLoc)
+ bRet &= ((SfxPoolItem&)aBrush).PutValue(*pGrLoc, MID_GRAPHIC_POSITION);
+ if(pGrTranparency)
+ bRet &= ((SfxPoolItem&)aBrush).PutValue(*pGrTranparency, MID_GRAPHIC_TRANSPARENCY);
+
+ rToSet.Put(aBrush);
+ }
+ }
+ {
+ const ::uno::Any* pCont = 0;
+ GetProperty(RES_PROTECT, MID_PROTECT_CONTENT, pCont );
+ const ::uno::Any* pPos = 0;
+ GetProperty(RES_PROTECT,MID_PROTECT_POSITION, pPos );
+ const ::uno::Any* pName = 0;
+ GetProperty(RES_PROTECT, MID_PROTECT_SIZE, pName );
+ if(pCont||pPos||pName)
+ {
+ SvxProtectItem aProt ( static_cast < const :: SvxProtectItem & > ( rFromSet.Get ( RES_PROTECT ) ) );
+ if(pCont)
+ bRet &= ((SfxPoolItem&)aProt).PutValue(*pCont, MID_PROTECT_CONTENT);
+ if(pPos )
+ bRet &= ((SfxPoolItem&)aProt).PutValue(*pPos, MID_PROTECT_POSITION);
+ if(pName)
+ bRet &= ((SfxPoolItem&)aProt).PutValue(*pName, MID_PROTECT_SIZE);
+ rToSet.Put(aProt);
+ }
+ }
+ {
+ const ::uno::Any* pHori = 0;
+ GetProperty(RES_HORI_ORIENT, MID_HORIORIENT_ORIENT, pHori );
+ const ::uno::Any* pHoriP = 0;
+ GetProperty(RES_HORI_ORIENT, MID_HORIORIENT_POSITION|CONVERT_TWIPS, pHoriP );
+ const ::uno::Any* pHoriR = 0;
+ GetProperty(RES_HORI_ORIENT, MID_HORIORIENT_RELATION, pHoriR );
+ const ::uno::Any* pPageT = 0;
+ GetProperty(RES_HORI_ORIENT, MID_HORIORIENT_PAGETOGGLE, pPageT);
+ if(pHori||pHoriP||pHoriR||pPageT)
+ {
+ SwFmtHoriOrient aOrient ( static_cast < const :: SwFmtHoriOrient & > ( rFromSet.Get ( RES_HORI_ORIENT ) ) );
+ if(pHori )
+ bRet &= ((SfxPoolItem&)aOrient).PutValue(*pHori, MID_HORIORIENT_ORIENT);
+ if(pHoriP)
+ bRet &= ((SfxPoolItem&)aOrient).PutValue(*pHoriP, MID_HORIORIENT_POSITION|CONVERT_TWIPS);
+ if(pHoriR)
+ bRet &= ((SfxPoolItem&)aOrient).PutValue(*pHoriR, MID_HORIORIENT_RELATION);
+ if(pPageT)
+ bRet &= ((SfxPoolItem&)aOrient).PutValue(*pPageT, MID_HORIORIENT_PAGETOGGLE);
+ rToSet.Put(aOrient);
+ }
+ }
+
+ {
+ const ::uno::Any* pVert = 0;
+ GetProperty(RES_VERT_ORIENT, MID_VERTORIENT_ORIENT, pVert);
+ const ::uno::Any* pVertP = 0;
+ GetProperty(RES_VERT_ORIENT, MID_VERTORIENT_POSITION|CONVERT_TWIPS, pVertP );
+ const ::uno::Any* pVertR = 0;
+ GetProperty(RES_VERT_ORIENT, MID_VERTORIENT_RELATION, pVertR );
+ if(pVert||pVertP||pVertR)
+ {
+ SwFmtVertOrient aOrient ( static_cast < const :: SwFmtVertOrient & > ( rFromSet.Get ( RES_VERT_ORIENT ) ) );
+ if(pVert )
+ bRet &= ((SfxPoolItem&)aOrient).PutValue(*pVert, MID_VERTORIENT_ORIENT);
+ if(pVertP)
+ bRet &= ((SfxPoolItem&)aOrient).PutValue(*pVertP, MID_VERTORIENT_POSITION|CONVERT_TWIPS);
+ if(pVertR)
+ bRet &= ((SfxPoolItem&)aOrient).PutValue(*pVertR, MID_VERTORIENT_RELATION);
+ rToSet.Put(aOrient);
+ }
+ }
+ {
+ const ::uno::Any* pURL = 0;
+ GetProperty(RES_URL, MID_URL_URL, pURL );
+ const ::uno::Any* pTarget = 0;
+ GetProperty(RES_URL, MID_URL_TARGET, pTarget );
+ const ::uno::Any* pHyLNm = 0;
+ GetProperty(RES_URL, MID_URL_HYPERLINKNAME, pHyLNm );
+ const ::uno::Any* pHySMp = 0;
+ GetProperty(RES_URL, MID_URL_SERVERMAP, pHySMp );
+ if(pURL||pTarget||pHyLNm||pHySMp)
+ {
+ SwFmtURL aURL ( static_cast < const :: SwFmtURL & > ( rFromSet.Get ( RES_URL ) ) );
+ if(pURL)
+ bRet &= ((SfxPoolItem&)aURL).PutValue(*pURL, MID_URL_URL);
+ if(pTarget)
+ bRet &= ((SfxPoolItem&)aURL).PutValue(*pTarget, MID_URL_TARGET);
+ if(pHyLNm)
+ bRet &= ((SfxPoolItem&)aURL).PutValue(*pHyLNm, MID_URL_HYPERLINKNAME );
+ if(pHySMp)
+ bRet &= ((SfxPoolItem&)aURL).PutValue(*pHySMp, MID_URL_SERVERMAP);
+ rToSet.Put(aURL);
+ }
+ }
+ const ::uno::Any* pL = 0;
+ GetProperty(RES_LR_SPACE, MID_L_MARGIN|CONVERT_TWIPS, pL );
+ const ::uno::Any* pR = 0;
+ GetProperty(RES_LR_SPACE, MID_R_MARGIN|CONVERT_TWIPS, pR );
+ if(pL||pR)
+ {
+ SvxLRSpaceItem aLR ( static_cast < const :: SvxLRSpaceItem & > ( rFromSet.Get ( RES_LR_SPACE ) ) );
+ if(pL)
+ bRet &= ((SfxPoolItem&)aLR).PutValue(*pL, MID_L_MARGIN|CONVERT_TWIPS);
+ if(pR)
+ bRet &= ((SfxPoolItem&)aLR).PutValue(*pR, MID_R_MARGIN|CONVERT_TWIPS);
+ rToSet.Put(aLR);
+ }
+ const ::uno::Any* pT = 0;
+ GetProperty(RES_UL_SPACE, MID_UP_MARGIN|CONVERT_TWIPS, pT );
+ const ::uno::Any* pB = 0;
+ GetProperty(RES_UL_SPACE, MID_LO_MARGIN|CONVERT_TWIPS, pB );
+ if(pT||pB)
+ {
+ SvxULSpaceItem aTB ( static_cast < const :: SvxULSpaceItem &> ( rFromSet.Get ( RES_UL_SPACE ) ) );
+ if(pT)
+ bRet &= ((SfxPoolItem&)aTB).PutValue(*pT, MID_UP_MARGIN|CONVERT_TWIPS);
+ if(pB)
+ bRet &= ((SfxPoolItem&)aTB).PutValue(*pB, MID_LO_MARGIN|CONVERT_TWIPS);
+ rToSet.Put(aTB);
+ }
+ const ::uno::Any* pOp;
+ if(GetProperty(RES_OPAQUE, 0, pOp))
+ {
+ SvxOpaqueItem aOp ( static_cast < const :: SvxOpaqueItem& > ( rFromSet.Get ( RES_OPAQUE ) ) );
+ bRet &= ((SfxPoolItem&)aOp).PutValue(*pOp, 0);
+ rToSet.Put(aOp);
+ }
+ const ::uno::Any* pPrt;
+ if(GetProperty(RES_PRINT, 0, pPrt))
+ {
+ SvxPrintItem aPrt ( static_cast < const :: SvxPrintItem & > ( rFromSet.Get ( RES_PRINT ) ) );
+ bRet &= ((SfxPoolItem&)aPrt).PutValue(*pPrt, 0);
+ rToSet.Put(aPrt);
+ }
+ const ::uno::Any* pSh;
+ if(GetProperty(RES_SHADOW, CONVERT_TWIPS, pSh))
+ {
+ SvxShadowItem aSh ( static_cast < const :: SvxShadowItem& > ( rFromSet.Get ( RES_SHADOW ) ) );
+ bRet &= ((SfxPoolItem&)aSh).PutValue(*pSh, CONVERT_TWIPS);
+ rToSet.Put(aSh);
+ }
+ const ::uno::Any* pSur = 0;
+ GetProperty(RES_SURROUND, MID_SURROUND_SURROUNDTYPE, pSur);
+ const ::uno::Any* pSurAnch = 0;
+ GetProperty(RES_SURROUND, MID_SURROUND_ANCHORONLY, pSurAnch);
+ if(pSur || pSurAnch)
+ {
+ SwFmtSurround aSrnd ( static_cast < const :: SwFmtSurround & > ( rFromSet.Get ( RES_SURROUND ) ) );
+ if(pSur)
+ bRet &= ((SfxPoolItem&)aSrnd).PutValue(*pSur, MID_SURROUND_SURROUNDTYPE );
+ if(pSurAnch)
+ bRet &= ((SfxPoolItem&)aSrnd).PutValue(*pSurAnch, MID_SURROUND_ANCHORONLY);
+ rToSet.Put(aSrnd);
+ }
+ const ::uno::Any* pLeft = 0;
+ GetProperty(RES_BOX, LEFT_BORDER |CONVERT_TWIPS, pLeft );
+ const ::uno::Any* pRight = 0;
+ GetProperty(RES_BOX, CONVERT_TWIPS|RIGHT_BORDER , pRight );
+ const ::uno::Any* pTop = 0;
+ GetProperty(RES_BOX, CONVERT_TWIPS|TOP_BORDER , pTop );
+ const ::uno::Any* pBottom = 0;
+ GetProperty(RES_BOX, CONVERT_TWIPS|BOTTOM_BORDER, pBottom);
+ const ::uno::Any* pDistance = 0;
+ GetProperty(RES_BOX, CONVERT_TWIPS|BORDER_DISTANCE, pDistance);
+ const ::uno::Any* pLeftDistance = 0;
+ GetProperty(RES_BOX, CONVERT_TWIPS|LEFT_BORDER_DISTANCE, pLeftDistance);
+ const ::uno::Any* pRightDistance = 0;
+ GetProperty(RES_BOX, CONVERT_TWIPS|RIGHT_BORDER_DISTANCE, pRightDistance);
+ const ::uno::Any* pTopDistance = 0;
+ GetProperty(RES_BOX, CONVERT_TWIPS|TOP_BORDER_DISTANCE, pTopDistance);
+ const ::uno::Any* pBottomDistance = 0;
+ GetProperty(RES_BOX, CONVERT_TWIPS|BOTTOM_BORDER_DISTANCE, pBottomDistance);
+ if( pLeft || pRight || pTop || pBottom || pDistance ||
+ pLeftDistance || pRightDistance || pTopDistance || pBottomDistance )
+ {
+ SvxBoxItem aBox ( static_cast < const :: SvxBoxItem & > ( rFromSet.Get ( RES_BOX ) ) );
+ if( pLeft )
+ bRet &= ((SfxPoolItem&)aBox).PutValue(*pLeft, CONVERT_TWIPS|LEFT_BORDER );
+ if( pRight )
+ bRet &= ((SfxPoolItem&)aBox).PutValue(*pRight, CONVERT_TWIPS|RIGHT_BORDER );
+ if( pTop )
+ bRet &= ((SfxPoolItem&)aBox).PutValue(*pTop, CONVERT_TWIPS|TOP_BORDER);
+ if( pBottom )
+ bRet &= ((SfxPoolItem&)aBox).PutValue(*pBottom, CONVERT_TWIPS|BOTTOM_BORDER);
+ if( pDistance )
+ bRet &= ((SfxPoolItem&)aBox).PutValue(*pDistance, CONVERT_TWIPS|BORDER_DISTANCE);
+ if( pLeftDistance )
+ bRet &= ((SfxPoolItem&)aBox).PutValue(*pLeftDistance, CONVERT_TWIPS|LEFT_BORDER_DISTANCE);
+ if( pRightDistance )
+ bRet &= ((SfxPoolItem&)aBox).PutValue(*pRightDistance, CONVERT_TWIPS|RIGHT_BORDER_DISTANCE);
+ if( pTopDistance )
+ bRet &= ((SfxPoolItem&)aBox).PutValue(*pTopDistance, CONVERT_TWIPS|TOP_BORDER_DISTANCE);
+ if( pBottomDistance )
+ bRet &= ((SfxPoolItem&)aBox).PutValue(*pBottomDistance, CONVERT_TWIPS|BOTTOM_BORDER_DISTANCE);
+ rToSet.Put(aBox);
+ }
+ {
+ const ::uno::Any* pRelH = 0;
+ GetProperty(RES_FRM_SIZE, MID_FRMSIZE_REL_HEIGHT, pRelH);
+ const ::uno::Any* pRelW = 0;
+ GetProperty(RES_FRM_SIZE, MID_FRMSIZE_REL_WIDTH, pRelW);
+ const ::uno::Any* pSyncWidth = 0;
+ GetProperty(RES_FRM_SIZE, MID_FRMSIZE_IS_SYNC_WIDTH_TO_HEIGHT, pSyncWidth);
+ const ::uno::Any* pSyncHeight = 0;
+ GetProperty(RES_FRM_SIZE, MID_FRMSIZE_IS_SYNC_HEIGHT_TO_WIDTH, pSyncHeight);
+ const ::uno::Any* pWidth = 0;
+ GetProperty(RES_FRM_SIZE, MID_FRMSIZE_WIDTH|CONVERT_TWIPS, pWidth);
+ const ::uno::Any* pHeight = 0;
+ GetProperty(RES_FRM_SIZE, MID_FRMSIZE_HEIGHT|CONVERT_TWIPS, pHeight);
+ const ::uno::Any* pSize = 0;
+ GetProperty(RES_FRM_SIZE, MID_FRMSIZE_SIZE|CONVERT_TWIPS, pSize);
+ const ::uno::Any* pSizeType = 0;
+ GetProperty(RES_FRM_SIZE, MID_FRMSIZE_SIZE_TYPE, pSizeType);
+ const ::uno::Any* pWidthType = 0;
+ GetProperty(RES_FRM_SIZE, MID_FRMSIZE_WIDTH_TYPE, pWidthType);
+ if( pWidth || pHeight ||pRelH || pRelW || pSize ||pSizeType ||
+ pWidthType ||pSyncWidth || pSyncHeight )
+ {
+ rSizeFound = true;
+ SwFmtFrmSize aFrmSz ( static_cast < const :: SwFmtFrmSize& > ( rFromSet.Get ( RES_FRM_SIZE ) ) );
+ if(pWidth)
+ bRet &= ((SfxPoolItem&)aFrmSz).PutValue(*pWidth, MID_FRMSIZE_WIDTH|CONVERT_TWIPS);
+ if(pHeight)
+ bRet &= ((SfxPoolItem&)aFrmSz).PutValue(*pHeight, MID_FRMSIZE_HEIGHT|CONVERT_TWIPS);
+ if(pRelH )
+ bRet &= ((SfxPoolItem&)aFrmSz).PutValue(*pRelH, MID_FRMSIZE_REL_HEIGHT);
+ if(pRelW )
+ bRet &= ((SfxPoolItem&)aFrmSz).PutValue(*pRelW, MID_FRMSIZE_REL_WIDTH);
+ if(pSyncWidth)
+ bRet &= ((SfxPoolItem&)aFrmSz).PutValue(*pSyncWidth, MID_FRMSIZE_IS_SYNC_WIDTH_TO_HEIGHT);
+ if(pSyncHeight)
+ bRet &= ((SfxPoolItem&)aFrmSz).PutValue(*pSyncHeight, MID_FRMSIZE_IS_SYNC_HEIGHT_TO_WIDTH);
+ if(pSize)
+ bRet &= ((SfxPoolItem&)aFrmSz).PutValue(*pSize, MID_FRMSIZE_SIZE|CONVERT_TWIPS);
+ if(pSizeType)
+ bRet &= ((SfxPoolItem&)aFrmSz).PutValue(*pSizeType, MID_FRMSIZE_SIZE_TYPE);
+ if(pWidthType)
+ bRet &= ((SfxPoolItem&)aFrmSz).PutValue(*pWidthType, MID_FRMSIZE_WIDTH_TYPE);
+ if(!aFrmSz.GetWidth())
+ aFrmSz.SetWidth(MINFLY);
+ if(!aFrmSz.GetHeight())
+ aFrmSz.SetHeight(MINFLY);
+ rToSet.Put(aFrmSz);
+ }
+ else
+ {
+ rSizeFound = false;
+ SwFmtFrmSize aFrmSz;
+ awt::Size aSize;
+ aSize.Width = 2 * MM50;
+ aSize.Height = 2 * MM50;
+ ::uno::Any aSizeVal;
+ aSizeVal <<= aSize;
+ ((SfxPoolItem&)aFrmSz).PutValue(aSizeVal, MID_FRMSIZE_SIZE|CONVERT_TWIPS);
+ rToSet.Put(aFrmSz);
+ }
+ }
+ const ::uno::Any* pFrameDirection = 0;
+ GetProperty(RES_FRAMEDIR, 0, pFrameDirection);
+ if(pFrameDirection)
+ {
+ SvxFrameDirectionItem aAttr(FRMDIR_HORI_LEFT_TOP, RES_FRAMEDIR);
+ aAttr.PutValue(*pFrameDirection, 0);
+ rToSet.Put(aAttr);
+ }
+ const ::uno::Any* pUnknown = 0;
+ GetProperty(RES_UNKNOWNATR_CONTAINER, 0, pUnknown);
+ if(pUnknown)
+ {
+ SvXMLAttrContainerItem aAttr(RES_UNKNOWNATR_CONTAINER);
+ aAttr.PutValue(*pUnknown, 0);
+ rToSet.Put(aAttr);
+ }
+
+ // #i18732#
+ const ::uno::Any* pFollowTextFlow = 0;
+ GetProperty(RES_FOLLOW_TEXT_FLOW, 0, pFollowTextFlow);
+ if ( pFollowTextFlow )
+ {
+ SwFmtFollowTextFlow aFmtFollowTextFlow;
+ aFmtFollowTextFlow.PutValue(*pFollowTextFlow, 0);
+ rToSet.Put(aFmtFollowTextFlow);
+ }
+
+ // #i28701# - RES_WRAP_INFLUENCE_ON_OBJPOS
+ const ::uno::Any* pWrapInfluenceOnObjPos = 0;
+ GetProperty(RES_WRAP_INFLUENCE_ON_OBJPOS, MID_WRAP_INFLUENCE, pWrapInfluenceOnObjPos);
+ if ( pWrapInfluenceOnObjPos )
+ {
+ SwFmtWrapInfluenceOnObjPos aFmtWrapInfluenceOnObjPos;
+ aFmtWrapInfluenceOnObjPos.PutValue( *pWrapInfluenceOnObjPos, MID_WRAP_INFLUENCE );
+ rToSet.Put(aFmtWrapInfluenceOnObjPos);
+ }
+
+ return bRet;
+}
+
+class SwFrameProperties_Impl : public BaseFrameProperties_Impl
+{
+public:
+ SwFrameProperties_Impl();
+ virtual ~SwFrameProperties_Impl(){}
+
+ bool AnyToItemSet( SwDoc* pDoc, SfxItemSet& rFrmSet, SfxItemSet& rSet, bool& rSizeFound);
+};
+
+SwFrameProperties_Impl::SwFrameProperties_Impl():
+ BaseFrameProperties_Impl(/*aSwMapProvider.GetPropertyMap(PROPERTY_MAP_TEXT_FRAME)*/ )
+{
+}
+
+inline void lcl_FillCol ( SfxItemSet &rToSet, const :: SfxItemSet &rFromSet, const :: uno::Any *pAny)
+{
+ if ( pAny )
+ {
+ SwFmtCol aCol ( static_cast < const :: SwFmtCol & > ( rFromSet.Get ( RES_COL ) ) );
+ ((SfxPoolItem&)aCol).PutValue( *pAny, MID_COLUMNS);
+ rToSet.Put(aCol);
+ }
+}
+
+bool SwFrameProperties_Impl::AnyToItemSet(SwDoc *pDoc, SfxItemSet& rSet, SfxItemSet&, bool& rSizeFound)
+{
+ //Properties fuer alle Frames
+ const ::uno::Any *pStyleName;
+ SwDocStyleSheet* pStyle = NULL;
+ bool bRet;
+
+ if ( GetProperty ( FN_UNO_FRAME_STYLE_NAME, 0, pStyleName ) )
+ {
+ OUString sStyle;
+ *pStyleName >>= sStyle;
+ pStyle = (SwDocStyleSheet*)pDoc->GetDocShell()->GetStyleSheetPool()->Find(sStyle,
+ SFX_STYLE_FAMILY_FRAME);
+ }
+
+ const ::uno::Any* pColumns = NULL;
+ GetProperty (RES_COL, MID_COLUMNS, pColumns);
+ if ( pStyle )
+ {
+ rtl::Reference< SwDocStyleSheet > xStyle( new SwDocStyleSheet( *pStyle ) );
+ const :: SfxItemSet *pItemSet = &xStyle->GetItemSet();
+ bRet = FillBaseProperties( rSet, *pItemSet, rSizeFound );
+ lcl_FillCol ( rSet, *pItemSet, pColumns );
+ }
+ else
+ {
+ const :: SfxItemSet *pItemSet = &pDoc->GetFrmFmtFromPool( RES_POOLFRM_FRAME )->GetAttrSet();
+ bRet = FillBaseProperties( rSet, *pItemSet, rSizeFound );
+ lcl_FillCol ( rSet, *pItemSet, pColumns );
+ }
+ const ::uno::Any* pEdit;
+ if(GetProperty(RES_EDIT_IN_READONLY, 0, pEdit))
+ {
+ SfxBoolItem aBool(RES_EDIT_IN_READONLY);
+ ((SfxPoolItem&)aBool).PutValue(*pEdit, 0);
+ rSet.Put(aBool);
+ }
+ return bRet;
+}
+
+/****************************************************************************
+ Grafik-Descriptor
+****************************************************************************/
+class SwGraphicProperties_Impl : public BaseFrameProperties_Impl
+{
+public:
+ SwGraphicProperties_Impl();
+ virtual ~SwGraphicProperties_Impl(){}
+
+ virtual bool AnyToItemSet( SwDoc* pDoc, SfxItemSet& rFrmSet, SfxItemSet& rSet, bool& rSizeFound);
+};
+
+SwGraphicProperties_Impl::SwGraphicProperties_Impl( ) :
+ BaseFrameProperties_Impl(/*aSwMapProvider.GetPropertyMap(PROPERTY_MAP_TEXT_GRAPHIC)*/ )
+{
+}
+
+inline void lcl_FillMirror ( SfxItemSet &rToSet, const :: SfxItemSet &rFromSet, const ::uno::Any *pHEvenMirror, const ::uno::Any *pHOddMirror, const ::uno::Any *pVMirror, bool &rRet )
+{
+ if(pHEvenMirror || pHOddMirror || pVMirror )
+ {
+ SwMirrorGrf aMirror ( static_cast < const :: SwMirrorGrf& > ( rFromSet.Get ( RES_GRFATR_MIRRORGRF ) ) );
+ if(pHEvenMirror)
+ rRet &= ((SfxPoolItem&)aMirror).PutValue(*pHEvenMirror, MID_MIRROR_HORZ_EVEN_PAGES);
+ if(pHOddMirror)
+ rRet &= ((SfxPoolItem&)aMirror).PutValue(*pHOddMirror, MID_MIRROR_HORZ_ODD_PAGES);
+ if(pVMirror)
+ rRet &= ((SfxPoolItem&)aMirror).PutValue(*pVMirror, MID_MIRROR_VERT);
+ rToSet.Put(aMirror);
+ }
+}
+
+bool SwGraphicProperties_Impl::AnyToItemSet(
+ SwDoc* pDoc,
+ SfxItemSet& rFrmSet,
+ SfxItemSet& rGrSet,
+ bool& rSizeFound)
+{
+ //Properties fuer alle Frames
+ bool bRet;
+ const ::uno::Any *pStyleName;
+ SwDocStyleSheet* pStyle = NULL;
+
+ if ( GetProperty ( FN_UNO_FRAME_STYLE_NAME, 0, pStyleName ) )
+ {
+ OUString sStyle;
+ *pStyleName >>= sStyle;
+ pStyle = (SwDocStyleSheet*)pDoc->GetDocShell()->GetStyleSheetPool()->Find(sStyle,
+ SFX_STYLE_FAMILY_FRAME);
+ }
+
+ const ::uno::Any* pHEvenMirror = 0;
+ const ::uno::Any* pHOddMirror = 0;
+ const ::uno::Any* pVMirror = 0;
+ GetProperty(RES_GRFATR_MIRRORGRF, MID_MIRROR_HORZ_EVEN_PAGES, pHEvenMirror);
+ GetProperty(RES_GRFATR_MIRRORGRF, MID_MIRROR_HORZ_ODD_PAGES, pHOddMirror);
+ GetProperty(RES_GRFATR_MIRRORGRF, MID_MIRROR_VERT, pVMirror);
+
+ if ( pStyle )
+ {
+ rtl::Reference< SwDocStyleSheet > xStyle( new SwDocStyleSheet(*pStyle) );
+ const :: SfxItemSet *pItemSet = &xStyle->GetItemSet();
+ bRet = FillBaseProperties(rFrmSet, *pItemSet, rSizeFound);
+ lcl_FillMirror ( rGrSet, *pItemSet, pHEvenMirror, pHOddMirror, pVMirror, bRet );
+ }
+ else
+ {
+ const :: SfxItemSet *pItemSet = &pDoc->GetFrmFmtFromPool( RES_POOLFRM_GRAPHIC )->GetAttrSet();
+ bRet = FillBaseProperties(rFrmSet, *pItemSet, rSizeFound);
+ lcl_FillMirror ( rGrSet, *pItemSet, pHEvenMirror, pHOddMirror, pVMirror, bRet );
+ }
+
+
+ static const :: sal_uInt16 nIDs[] =
+ {
+ RES_GRFATR_CROPGRF,
+ RES_GRFATR_ROTATION,
+ RES_GRFATR_LUMINANCE,
+ RES_GRFATR_CONTRAST,
+ RES_GRFATR_CHANNELR,
+ RES_GRFATR_CHANNELG,
+ RES_GRFATR_CHANNELB,
+ RES_GRFATR_GAMMA,
+ RES_GRFATR_INVERT,
+ RES_GRFATR_TRANSPARENCY,
+ RES_GRFATR_DRAWMODE,
+ 0
+ };
+ const ::uno::Any* pAny;
+ for(sal_Int16 nIndex = 0; nIDs[nIndex]; nIndex++)
+ {
+ sal_uInt8 nMId = RES_GRFATR_CROPGRF == nIDs[nIndex] ? CONVERT_TWIPS : 0;
+ if(GetProperty(nIDs[nIndex], nMId, pAny ))
+ {
+ SfxPoolItem* pItem = ::GetDfltAttr( nIDs[nIndex] )->Clone();
+ bRet &= pItem->PutValue(*pAny, nMId );
+ rGrSet.Put(*pItem);
+ delete pItem;
+ }
+ }
+
+ return bRet;
+}
+
+class SwOLEProperties_Impl : public SwFrameProperties_Impl
+{
+public:
+ SwOLEProperties_Impl() :
+ SwFrameProperties_Impl(/*aSwMapProvider.GetPropertyMap(PROPERTY_MAP_EMBEDDED_OBJECT)*/ ){}
+ virtual ~SwOLEProperties_Impl(){}
+
+ virtual bool AnyToItemSet( SwDoc* pDoc, SfxItemSet& rFrmSet, SfxItemSet& rSet, bool& rSizeFound);
+};
+
+bool SwOLEProperties_Impl::AnyToItemSet(
+ SwDoc* pDoc, SfxItemSet& rFrmSet, SfxItemSet& rSet, bool& rSizeFound)
+{
+ const ::uno::Any* pTemp;
+ if(!GetProperty(FN_UNO_CLSID, 0, pTemp) && !GetProperty(FN_UNO_STREAM_NAME, 0, pTemp) )
+ return sal_False;
+ SwFrameProperties_Impl::AnyToItemSet( pDoc, rFrmSet, rSet, rSizeFound);
+ //
+ return sal_True;
+}
+
+/******************************************************************
+ * SwXFrame
+ ******************************************************************/
+const :: uno::Sequence< sal_Int8 > & SwXFrame::getUnoTunnelId()
+{
+ static uno::Sequence< sal_Int8 > aSeq = ::CreateUnoTunnelId();
+ return aSeq;
+}
+
+sal_Int64 SAL_CALL SwXFrame::getSomething( const :: uno::Sequence< sal_Int8 >& rId )
+ throw(uno::RuntimeException)
+{
+ if( rId.getLength() == 16
+ && 0 == rtl_compareMemory( getUnoTunnelId().getConstArray(),
+ rId.getConstArray(), 16 ) )
+ {
+ return sal::static_int_cast< sal_Int64 >( reinterpret_cast< sal_IntPtr >(this) );
+ }
+ return 0;
+}
+
+TYPEINIT1(SwXFrame, SwClient);
+
+OUString SwXFrame::getImplementationName(void) throw( uno::RuntimeException )
+{
+ return C2U("SwXFrame");
+}
+
+sal_Bool SwXFrame::supportsService(const :: OUString& rServiceName) throw( uno::RuntimeException )
+{
+ return !rServiceName.compareToAscii("com.sun.star.text.BaseFrame")||
+ !rServiceName.compareToAscii("com.sun.star.text.TextContent") ||
+ !rServiceName.compareToAscii("com.sun.star.document.LinkTarget");
+}
+
+uno::Sequence< OUString > SwXFrame::getSupportedServiceNames(void) throw( uno::RuntimeException )
+{
+ uno::Sequence< OUString > aRet(3);
+ OUString* pArray = aRet.getArray();
+ pArray[0] = C2U("com.sun.star.text.BaseFrame");
+ pArray[1] = C2U("com.sun.star.text.TextContent");
+ pArray[2] = C2U("com.sun.star.document.LinkTarget");
+ return aRet;
+}
+
+SwXFrame::SwXFrame(FlyCntType eSet, const :: SfxItemPropertySet* pSet, SwDoc *pDoc) :
+ aLstnrCntnr( (container::XNamed*)this),
+ m_pPropSet(pSet),
+ m_pDoc ( pDoc ),
+ eType(eSet),
+ bIsDescriptor(true),
+ m_pCopySource( 0 )
+{
+ // Register ourselves as a listener to the document (via the page descriptor)
+ pDoc->GetPageDescFromPool(RES_POOLPAGE_STANDARD)->Add(this);
+ // get the property set for the default style data
+ // First get the model
+ uno::Reference < XModel > xModel = pDoc->GetDocShell()->GetBaseModel();
+ // Ask the model for it's family supplier interface
+ uno::Reference < XStyleFamiliesSupplier > xFamilySupplier ( xModel, uno::UNO_QUERY );
+ // Get the style families
+ uno::Reference < XNameAccess > xFamilies = xFamilySupplier->getStyleFamilies();
+ // Get the Frame family (and keep it for later)
+ const ::uno::Any aAny = xFamilies->getByName ( OUString ( RTL_CONSTASCII_USTRINGPARAM ( "FrameStyles" ) ) );
+ aAny >>= mxStyleFamily;
+ // In the derived class, we'll ask mxStyleFamily for the relevant default style
+ // mxStyleFamily is initialised in the SwXFrame constructor
+ switch(eType)
+ {
+ case FLYCNTTYPE_FRM:
+ {
+ uno::Any aAny2 = mxStyleFamily->getByName ( OUString ( RTL_CONSTASCII_USTRINGPARAM ( "Frame" ) ) );
+ aAny2 >>= mxStyleData;
+ pProps = new SwFrameProperties_Impl( );
+ }
+ break;
+ case FLYCNTTYPE_GRF:
+ {
+ uno::Any aAny2 = mxStyleFamily->getByName ( OUString ( RTL_CONSTASCII_USTRINGPARAM ( "Graphics" ) ) );
+ aAny2 >>= mxStyleData;
+ pProps = new SwGraphicProperties_Impl( );
+ }
+ break;
+ case FLYCNTTYPE_OLE:
+ {
+ uno::Any aAny2 = mxStyleFamily->getByName ( OUString ( RTL_CONSTASCII_USTRINGPARAM ( "OLE" ) ) );
+ aAny2 >>= mxStyleData;
+ pProps = new SwOLEProperties_Impl( );
+ }
+ break;
+
+ default:
+ ;
+ }
+}
+
+SwXFrame::SwXFrame(SwFrmFmt& rFrmFmt, FlyCntType eSet, const :: SfxItemPropertySet* pSet) :
+ SwClient( &rFrmFmt ),
+ aLstnrCntnr( (container::XNamed*)this),
+ m_pPropSet(pSet),
+ m_pDoc( 0 ),
+ eType(eSet),
+ pProps(0),
+ bIsDescriptor(false),
+ m_pCopySource(0)
+{
+
+}
+
+SwXFrame::~SwXFrame()
+{
+ delete m_pCopySource;
+ delete pProps;
+}
+
+OUString SwXFrame::getName(void) throw( uno::RuntimeException )
+{
+ SolarMutexGuard aGuard;
+ String sRet;
+ SwFrmFmt* pFmt = GetFrmFmt();
+ if(pFmt)
+ sRet = pFmt->GetName();
+ else if(bIsDescriptor)
+ sRet = sName;
+ else
+ throw uno::RuntimeException();
+ return sRet;
+}
+
+void SwXFrame::setName(const :: OUString& rName) throw( uno::RuntimeException )
+{
+ SolarMutexGuard aGuard;
+ SwFrmFmt* pFmt = GetFrmFmt();
+ String sTmpName(rName);
+ if(pFmt)
+ {
+ pFmt->GetDoc()->SetFlyName((SwFlyFrmFmt&)*pFmt, sTmpName);
+ if(pFmt->GetName() != sTmpName)
+ {
+ throw uno::RuntimeException();
+ }
+ }
+ else if(bIsDescriptor)
+ sName = sTmpName;
+ else
+ throw uno::RuntimeException();
+}
+
+uno::Reference< beans::XPropertySetInfo > SwXFrame::getPropertySetInfo(void) throw( uno::RuntimeException )
+{
+ uno::Reference< beans::XPropertySetInfo > xRef;
+ static uno::Reference< beans::XPropertySetInfo > xFrmRef;
+ static uno::Reference< beans::XPropertySetInfo > xGrfRef;
+ static uno::Reference< beans::XPropertySetInfo > xOLERef;
+ switch(eType)
+ {
+ case FLYCNTTYPE_FRM:
+ if( !xFrmRef.is() )
+ xFrmRef = m_pPropSet->getPropertySetInfo();
+ xRef = xFrmRef;
+ break;
+ case FLYCNTTYPE_GRF:
+ if( !xGrfRef.is() )
+ xGrfRef = m_pPropSet->getPropertySetInfo();
+ xRef = xGrfRef;
+ break;
+ case FLYCNTTYPE_OLE:
+ if( !xOLERef.is() )
+ xOLERef = m_pPropSet->getPropertySetInfo();
+ xRef = xOLERef;
+ break;
+ default:
+ ;
+ }
+ return xRef;
+}
+
+void SwXFrame::SetSelection(SwPaM& rCopySource)
+{
+ if(m_pCopySource)
+ delete m_pCopySource;
+ m_pCopySource = new SwPaM( *rCopySource.Start() );
+ m_pCopySource->SetMark();
+ *m_pCopySource->GetMark() = *rCopySource.End();
+}
+
+SdrObject *SwXFrame::GetOrCreateSdrObject( SwFlyFrmFmt *pFmt )
+{
+ SdrObject* pObject = pFmt->FindSdrObject();
+ if( !pObject )
+ {
+ SwDoc *pDoc = pFmt->GetDoc();
+ // --> OD 2005-08-08 #i52858# - method name changed
+ SdrModel *pDrawModel = pDoc->GetOrCreateDrawModel();
+ // <--
+ SwFlyDrawContact* pContactObject
+ = new SwFlyDrawContact( pFmt, pDrawModel );
+ pObject = pContactObject->GetMaster();
+
+ const :: SwFmtSurround& rSurround = pFmt->GetSurround();
+ pObject->SetLayer(
+ ( SURROUND_THROUGHT == rSurround.GetSurround() &&
+ !pFmt->GetOpaque().GetValue() ) ? pDoc->GetHellId()
+ : pDoc->GetHeavenId() );
+
+ pDrawModel->GetPage(0)->InsertObject( pObject );
+ }
+
+ return pObject;
+}
+
+SwFrmFmt *lcl_GetFrmFmt( const :: uno::Any& rValue, SwDoc *pDoc )
+{
+ SwFrmFmt *pRet = 0;
+ SwDocShell* pDocSh = pDoc->GetDocShell();
+ if(pDocSh)
+ {
+ OUString uTemp;
+ rValue >>= uTemp;
+ String sStyle;
+ SwStyleNameMapper::FillUIName(String (uTemp), sStyle, nsSwGetPoolIdFromName::GET_POOLID_FRMFMT, true);
+ SwDocStyleSheet* pStyle =
+ (SwDocStyleSheet*)pDocSh->GetStyleSheetPool()->Find(sStyle,
+ SFX_STYLE_FAMILY_FRAME);
+ if(pStyle)
+ pRet = pStyle->GetFrmFmt();
+ }
+
+ return pRet;
+}
+
+void SwXFrame::setPropertyValue(const :: OUString& rPropertyName, const :: uno::Any& aValue)
+ throw( beans::UnknownPropertyException, beans::PropertyVetoException, lang::IllegalArgumentException, lang::WrappedTargetException, uno::RuntimeException )
+{
+ SolarMutexGuard aGuard;
+ SwFrmFmt* pFmt = GetFrmFmt();
+ const :: SfxItemPropertySimpleEntry* pEntry = m_pPropSet->getPropertyMap()->getByName(rPropertyName);
+
+ if (!pEntry)
+ throw beans::UnknownPropertyException(OUString ( RTL_CONSTASCII_USTRINGPARAM ( "Unknown property: " ) ) + rPropertyName, static_cast < cppu::OWeakObject * > ( this ) );
+
+ if(pFmt)
+ {
+ bool bNextFrame = false;
+ if ( pEntry->nFlags & beans::PropertyAttribute::READONLY)
+ throw beans::PropertyVetoException( OUString ( RTL_CONSTASCII_USTRINGPARAM ( "Property is read-only: " ) ) + rPropertyName, static_cast < cppu::OWeakObject * > ( this ) );
+
+ SwDoc* pDoc = pFmt->GetDoc();
+ if ( ((eType == FLYCNTTYPE_GRF) && isGRFATR(pEntry->nWID)) ||
+ (FN_PARAM_COUNTOUR_PP == pEntry->nWID) ||
+ (FN_UNO_IS_AUTOMATIC_CONTOUR == pEntry->nWID) ||
+ (FN_UNO_IS_PIXEL_CONTOUR == pEntry->nWID) )
+ {
+ const :: SwNodeIndex* pIdx = pFmt->GetCntnt().GetCntntIdx();
+ if(pIdx)
+ {
+ SwNodeIndex aIdx(*pIdx, 1);
+ SwNoTxtNode* pNoTxt = aIdx.GetNode().GetNoTxtNode();
+ if(pEntry->nWID == FN_PARAM_COUNTOUR_PP)
+ {
+ drawing::PointSequenceSequence aParam;
+ if(!aValue.hasValue())
+ pNoTxt->SetContour(0);
+ else if(aValue >>= aParam)
+ {
+ PolyPolygon aPoly((sal_uInt16)aParam.getLength());
+ for(sal_Int32 i = 0; i < aParam.getLength(); i++)
+ {
+ const :: drawing::PointSequence* pPointSeq = aParam.getConstArray();
+ sal_Int32 nPoints = pPointSeq[i].getLength();
+ const :: awt::Point* pPoints = pPointSeq[i].getConstArray();
+ Polygon aSet( (sal_uInt16)nPoints );
+ for(sal_Int32 j = 0; j < nPoints; j++)
+ {
+ Point aPoint(pPoints[j].X, pPoints[j].Y);
+ aSet.SetPoint(aPoint, (sal_uInt16)j);
+ }
+ // Close polygon if it isn't closed already.
+ aSet.Optimize( POLY_OPTIMIZE_CLOSE );
+ aPoly.Insert( aSet );
+ }
+ pNoTxt->SetContourAPI( &aPoly );
+ }
+ else
+ throw lang::IllegalArgumentException();
+ }
+ else if(pEntry->nWID == FN_UNO_IS_AUTOMATIC_CONTOUR )
+ {
+ pNoTxt->SetAutomaticContour( *(sal_Bool *)aValue.getValue() );
+ }
+ else if(pEntry->nWID == FN_UNO_IS_PIXEL_CONTOUR )
+ {
+ // The IsPixelContour property can only be set if there
+ // is no contour, or if the contour has been set by the
+ // API itself (or in other words, if the contour isn't
+ // used already).
+ if( !pNoTxt->_HasContour() ||
+ !pNoTxt->IsContourMapModeValid() )
+ pNoTxt->SetPixelContour( *(sal_Bool *)aValue.getValue() );
+ else
+ throw lang::IllegalArgumentException();
+ }
+ else
+ {
+ SfxItemSet aSet(pNoTxt->GetSwAttrSet());
+ m_pPropSet->setPropertyValue(*pEntry, aValue, aSet);
+ pNoTxt->SetAttr(aSet);
+ }
+ }
+ }
+ // --> OD 2009-07-13 #i73249#
+ // Attribute AlternativeText was never published.
+ // Now it has been replaced by Attribute Title - valid for all <SwXFrame> instances
+// else if( FN_UNO_ALTERNATIVE_TEXT == pEntry->nWID && eType != FLYCNTTYPE_FRM )
+// {
+// const :: SwNodeIndex* pIdx = pFmt->GetCntnt().GetCntntIdx();
+// if(pIdx)
+// {
+// SwNodeIndex aIdx(*pIdx, 1);
+// SwNoTxtNode* pNoTxt = aIdx.GetNode().GetNoTxtNode();
+// OUString uTemp;
+// aValue >>= uTemp;
+// pNoTxt->SetAlternateText(uTemp);
+// }
+// }
+ // New attribute Title
+ else if( FN_UNO_TITLE == pEntry->nWID )
+ {
+ SwFlyFrmFmt* pFlyFmt = dynamic_cast<SwFlyFrmFmt*>(pFmt);
+ OSL_ENSURE( pFmt,
+ "unexpected type of <pFmt> --> crash" );
+ OUString uTemp;
+ aValue >>= uTemp;
+ const String sTitle(uTemp);
+ // assure that <SdrObject> instance exists.
+ GetOrCreateSdrObject( pFlyFmt );
+ pFlyFmt->GetDoc()->SetFlyFrmTitle( *(pFlyFmt), sTitle );
+ }
+ // New attribute Description
+ else if( FN_UNO_DESCRIPTION == pEntry->nWID )
+ {
+ SwFlyFrmFmt* pFlyFmt = dynamic_cast<SwFlyFrmFmt*>(pFmt);
+ OSL_ENSURE( pFmt,
+ "unexpected type of <pFmt> --> crash" );
+ OUString uTemp;
+ aValue >>= uTemp;
+ const String sDescription(uTemp);
+ // assure that <SdrObject> instance exists.
+ GetOrCreateSdrObject( pFlyFmt );
+ pFlyFmt->GetDoc()->SetFlyFrmDescription( *(pFlyFmt), sDescription );
+ }
+ // <--
+ else if(FN_UNO_FRAME_STYLE_NAME == pEntry->nWID)
+ {
+ SwFrmFmt *pFrmFmt = lcl_GetFrmFmt( aValue, pFmt->GetDoc() );
+ if( pFrmFmt )
+ {
+ UnoActionContext aAction(pFmt->GetDoc());
+
+ SfxItemSet* pSet = 0;
+ // --> OD 2004-08-13 #i31771#, #i25798# - No adjustment of
+ // anchor ( no call of method <::lcl_ChkAndSetNewAnchor(..)> ),
+ // if document is currently in reading mode.
+ if ( !pFmt->GetDoc()->IsInReading() )
+ {
+ // see SwFEShell::SetFrmFmt( SwFrmFmt *pNewFmt, sal_Bool bKeepOrient, Point* pDocPos )
+ SwFlyFrm *pFly = 0;
+ {
+ const :: SwFrmFmt* pFmtXX = pFmt;
+ if (PTR_CAST(SwFlyFrmFmt, pFmtXX))
+ pFly = ((SwFlyFrmFmt*)pFmtXX)->GetFrm();
+ }
+ if ( pFly )
+ {
+ const :: SfxPoolItem* pItem;
+ if( SFX_ITEM_SET == pFrmFmt->GetItemState( RES_ANCHOR, false, &pItem ))
+ {
+ pSet = new SfxItemSet( pDoc->GetAttrPool(), aFrmFmtSetRange );
+ pSet->Put( *pItem );
+ if ( !::lcl_ChkAndSetNewAnchor( *pFly, *pSet ) )
+ delete pSet, pSet = 0;
+ }
+ }
+ }
+ // <--
+
+ pFmt->GetDoc()->SetFrmFmtToFly( *pFmt, *pFrmFmt, pSet, sal_False );
+ delete pSet;
+ }
+ else
+ throw lang::IllegalArgumentException();
+ }
+ else if( FN_UNO_GRAPHIC_U_R_L == pEntry->nWID ||
+ FN_UNO_GRAPHIC_FILTER == pEntry->nWID)
+ {
+ String sGrfName, sFltName;
+ GraphicObject *pGrfObj = 0;
+ pFmt->GetDoc()->GetGrfNms( *(SwFlyFrmFmt*)pFmt, &sGrfName, &sFltName );
+ OUString uTemp;
+ aValue >>= uTemp;
+ String sTmp(uTemp);
+ UnoActionContext aAction(pFmt->GetDoc());
+ if(FN_UNO_GRAPHIC_U_R_L == pEntry->nWID)
+ {
+ if( sTmp.EqualsAscii( sPackageProtocol,
+ 0, sizeof( sPackageProtocol )-1 ) )
+ {
+ pGrfObj = new GraphicObject;
+ pGrfObj->SetUserData( sTmp );
+ pGrfObj->SetSwapState();
+ sGrfName.Erase();
+ }
+ else if( sTmp.EqualsAscii( sGraphicObjectProtocol,
+ 0, sizeof(sGraphicObjectProtocol)-1 ) )
+ {
+ ByteString sId( sTmp.Copy(sizeof(sGraphicObjectProtocol)-1),
+ RTL_TEXTENCODING_ASCII_US );
+ pGrfObj = new GraphicObject( sId );
+ sGrfName.Erase();
+ }
+ else
+ {
+ sGrfName = sTmp;
+ }
+ }
+ else
+ {
+ sFltName = sTmp;
+ }
+
+ const :: SwNodeIndex* pIdx = pFmt->GetCntnt().GetCntntIdx();
+ if(pIdx)
+ {
+ SwNodeIndex aIdx(*pIdx, 1);
+// SwNoTxtNode* pNoTxt = aIdx.GetNode().GetNoTxtNode();
+ SwGrfNode* pGrfNode = aIdx.GetNode().GetGrfNode();
+ if(!pGrfNode)
+ {
+ delete pGrfObj;
+ throw uno::RuntimeException();
+ }
+ SwPaM aGrfPaM(*pGrfNode);
+ pFmt->GetDoc()->ReRead( aGrfPaM, sGrfName, sFltName, 0,
+ pGrfObj );
+ }
+ delete pGrfObj;
+ }
+ else if( FN_UNO_GRAPHIC == pEntry->nWID )
+ {
+ uno::Reference< graphic::XGraphic > xGraphic;
+ aValue >>= xGraphic;
+ if(xGraphic.is())
+ {
+ const :: SwNodeIndex* pIdx = pFmt->GetCntnt().GetCntntIdx();
+ if(pIdx)
+ {
+ SwNodeIndex aIdx(*pIdx, 1);
+ SwGrfNode* pGrfNode = aIdx.GetNode().GetGrfNode();
+ if(!pGrfNode)
+ {
+ throw uno::RuntimeException();
+ }
+ SwPaM aGrfPaM(*pGrfNode);
+ Graphic aGraphic( xGraphic );
+ pFmt->GetDoc()->ReRead( aGrfPaM, String(), String(), &aGraphic, 0 );
+ }
+ }
+ }
+ else if( FN_UNO_REPLACEMENT_GRAPHIC_URL == pEntry->nWID || FN_UNO_REPLACEMENT_GRAPHIC == pEntry->nWID )
+ {
+ bool bURL = FN_UNO_REPLACEMENT_GRAPHIC_URL == pEntry->nWID;
+ bool bApply = false;
+ Graphic aGraphic;
+ if( bURL )
+ {
+ GraphicObject *pGrfObj = 0;
+ OUString aGrfUrl;
+ aValue >>= aGrfUrl;
+
+ // the package URL based graphics are handled in different way currently
+ // TODO/LATER: actually this is the correct place to handle them
+ ::rtl::OUString aGraphicProtocol( RTL_CONSTASCII_USTRINGPARAM( sGraphicObjectProtocol ) );
+ if( aGrfUrl.compareTo( aGraphicProtocol, aGraphicProtocol.getLength() ) == 0 )
+ {
+ ByteString sId( aGrfUrl.copy(sizeof(sGraphicObjectProtocol)-1).getStr(), RTL_TEXTENCODING_ASCII_US );
+ pGrfObj = new GraphicObject( sId );
+ aGraphic = pGrfObj->GetGraphic();
+ bApply = true;
+ }
+ }
+ else
+ {
+ uno::Reference< graphic::XGraphic > xGraphic;
+ aValue >>= xGraphic;
+ if( xGraphic.is() )
+ {
+ aGraphic = Graphic( xGraphic );
+ bApply = true;
+ }
+ }
+
+ if ( bApply )
+ {
+ const :: SwFmtCntnt* pCnt = &pFmt->GetCntnt();
+ if ( pCnt->GetCntntIdx() && pDoc->GetNodes()[ pCnt->GetCntntIdx()->GetIndex() + 1 ] )
+ {
+ SwOLENode* pOleNode = pDoc->GetNodes()[ pCnt->GetCntntIdx()->GetIndex() + 1 ]->GetOLENode();
+
+ if ( pOleNode )
+ {
+ svt::EmbeddedObjectRef xObj = pOleNode->GetOLEObj().GetObject();
+
+ ::rtl::OUString aMediaType;
+ xObj.SetGraphic( aGraphic, aMediaType );
+ }
+ }
+ }
+ }
+ else if(0 != (bNextFrame = (rPropertyName.equalsAsciiL( SW_PROP_NAME(UNO_NAME_CHAIN_NEXT_NAME))))
+ || rPropertyName.equalsAsciiL( SW_PROP_NAME(UNO_NAME_CHAIN_PREV_NAME)))
+ {
+ OUString uTemp;
+ aValue >>= uTemp;
+ String sChainName(uTemp);
+ if(!sChainName.Len())
+ {
+ if(bNextFrame)
+ pDoc->Unchain(*pFmt);
+ else
+ {
+ SwFmtChain aChain( pFmt->GetChain() );
+ SwFrmFmt *pPrev = aChain.GetPrev();
+ if(pPrev)
+ pDoc->Unchain(*pPrev);
+ }
+ }
+ else
+ {
+ sal_uInt16 nCount = pDoc->GetFlyCount(FLYCNTTYPE_FRM);
+
+ SwFrmFmt* pChain = 0;
+ for( sal_uInt16 i = 0; i < nCount; i++)
+ {
+ SwFrmFmt* pFmt2 = pDoc->GetFlyNum(i, FLYCNTTYPE_FRM);
+ if(sChainName == pFmt2->GetName() )
+ {
+ pChain = pFmt2;
+ break;
+ }
+ }
+ if(pChain)
+ {
+ SwFrmFmt* pSource = bNextFrame ? pFmt : pChain;
+ SwFrmFmt* pDest = bNextFrame ? pChain: pFmt;
+ pDoc->Chain(*pSource, *pDest);
+ }
+ }
+ }
+ else if(FN_UNO_Z_ORDER == pEntry->nWID)
+ {
+ sal_Int32 nZOrder = - 1;
+ aValue >>= nZOrder;
+ if( nZOrder >= 0)
+ {
+ SdrObject* pObject =
+ GetOrCreateSdrObject( (SwFlyFrmFmt*)pFmt );
+ SdrModel *pDrawModel = pDoc->GetDrawModel();
+ pDrawModel->GetPage(0)->
+ SetObjectOrdNum(pObject->GetOrdNum(), nZOrder);
+ }
+ }
+ else if(RES_ANCHOR == pEntry->nWID && MID_ANCHOR_ANCHORFRAME == pEntry->nMemberId)
+ {
+ bool bDone = false;
+ uno::Reference<text::XTextFrame> xFrame;
+ if(aValue >>= xFrame)
+ {
+ uno::Reference<lang::XUnoTunnel> xTunnel(xFrame, uno::UNO_QUERY);
+ SwXFrame* pFrame = xTunnel.is() ?
+ reinterpret_cast< SwXFrame * >( sal::static_int_cast< sal_IntPtr >( xTunnel->getSomething(SwXFrame::getUnoTunnelId()) ))
+ : 0;
+ if(pFrame && this != pFrame && pFrame->GetFrmFmt() && pFrame->GetFrmFmt()->GetDoc() == pDoc)
+ {
+ SfxItemSet aSet( pDoc->GetAttrPool(),
+ RES_FRMATR_BEGIN, RES_FRMATR_END - 1 );
+ aSet.SetParent(&pFmt->GetAttrSet());
+ SwFmtAnchor aAnchor = (const :: SwFmtAnchor&)aSet.Get(pEntry->nWID);
+
+
+ SwPosition aPos(*pFrame->GetFrmFmt()->GetCntnt().GetCntntIdx());
+ aAnchor.SetAnchor(&aPos);
+ aAnchor.SetType(FLY_AT_FLY);
+ aSet.Put(aAnchor);
+ pDoc->SetFlyFrmAttr( *pFmt, aSet );
+ bDone = true;
+ }
+ }
+ if(!bDone)
+ throw lang::IllegalArgumentException();
+ }
+ else
+ {
+ SfxItemSet aSet( pDoc->GetAttrPool(),
+ RES_FRMATR_BEGIN, RES_FRMATR_END - 1,
+ RES_UNKNOWNATR_CONTAINER, RES_UNKNOWNATR_CONTAINER,
+ 0L);
+
+ aSet.SetParent(&pFmt->GetAttrSet());
+ m_pPropSet->setPropertyValue(*pEntry, aValue, aSet);
+ if(RES_ANCHOR == pEntry->nWID && MID_ANCHOR_ANCHORTYPE == pEntry->nMemberId)
+ {
+ SwFmtAnchor aAnchor = (const :: SwFmtAnchor&)aSet.Get(pEntry->nWID);
+ if(aAnchor.GetAnchorId() == FLY_AT_FLY)
+ {
+ const :: SwPosition* pPosition = aAnchor.GetCntntAnchor();
+ SwFrmFmt* pFlyFmt = pPosition ? pPosition->nNode.GetNode().GetFlyFmt() : 0;
+ if(!pFlyFmt || pFlyFmt->Which() == RES_DRAWFRMFMT)
+ {
+ lang::IllegalArgumentException aExcept;
+ aExcept.Message = C2U("Anchor to frame: no frame found");
+ throw aExcept;
+ }
+ else
+ {
+ SwPosition aPos = *pPosition;
+ aPos.nNode = *pFlyFmt->GetCntnt().GetCntntIdx();
+ aAnchor.SetAnchor(&aPos);
+ aSet.Put(aAnchor);
+ }
+ }
+ else if ((aAnchor.GetAnchorId() != FLY_AT_PAGE) &&
+ !aAnchor.GetCntntAnchor())
+ {
+ SwNode& rNode = pDoc->GetNodes().GetEndOfContent();
+ SwPaM aPam(rNode);
+ aPam.Move( fnMoveBackward, fnGoDoc );
+ aAnchor.SetAnchor( aPam.Start() );
+ aSet.Put(aAnchor);
+ }
+
+ // --> OD 2004-08-13 #i31771#, #i25798# - No adjustment of
+ // anchor ( no call of method <::lcl_ChkAndSetNewAnchor(..)> ),
+ // if document is currently in reading mode.
+ if ( !pFmt->GetDoc()->IsInReading() )
+ {
+ // see SwFEShell::SetFlyFrmAttr( SfxItemSet& rSet )
+ SwFlyFrm *pFly = 0;
+ if (PTR_CAST(SwFlyFrmFmt, pFmt))
+ pFly = ((SwFlyFrmFmt*)pFmt)->GetFrm();
+ if (pFly)
+ {
+ const :: SfxPoolItem* pItem;
+ if( SFX_ITEM_SET == aSet.GetItemState( RES_ANCHOR, false, &pItem ))
+ {
+ aSet.Put( *pItem );
+ ::lcl_ChkAndSetNewAnchor( *pFly, aSet );
+ }
+ }
+ }
+ // <--
+
+ pFmt->GetDoc()->SetFlyFrmAttr( *pFmt, aSet );
+ }
+ else if(FN_UNO_CLSID == pEntry->nWID || FN_UNO_STREAM_NAME == pEntry->nWID)
+ {
+ throw lang::IllegalArgumentException();
+ }
+ else
+ pFmt->SetFmtAttr(aSet);
+ }
+ }
+ else if(IsDescriptor())
+ {
+ pProps->SetProperty(pEntry->nWID, pEntry->nMemberId, aValue);
+ if( FN_UNO_FRAME_STYLE_NAME == pEntry->nWID )
+ {
+ OUString sStyleName;
+ aValue >>= sStyleName;
+ try
+ {
+ uno::Any aAny = mxStyleFamily->getByName ( sStyleName );
+ aAny >>= mxStyleData;
+ }
+ catch ( container::NoSuchElementException const & )
+ {
+ }
+ catch ( lang::WrappedTargetException const & )
+ {
+ }
+ catch ( uno::RuntimeException const & )
+ {
+ }
+ }
+ }
+ else
+ throw uno::RuntimeException();
+}
+
+uno::Any SwXFrame::getPropertyValue(const OUString& rPropertyName)
+ throw( beans::UnknownPropertyException, lang::WrappedTargetException, uno::RuntimeException )
+{
+ SolarMutexGuard aGuard;
+ uno::Any aAny;
+ SwFrmFmt* pFmt = GetFrmFmt();
+ const SfxItemPropertySimpleEntry* pEntry = m_pPropSet->getPropertyMap()->getByName(rPropertyName);
+ if (!pEntry)
+ throw beans::UnknownPropertyException(OUString ( RTL_CONSTASCII_USTRINGPARAM ( "Unknown property: " ) ) + rPropertyName, static_cast < cppu::OWeakObject * > ( this ) );
+
+ if(FN_UNO_ANCHOR_TYPES == pEntry->nWID)
+ {
+ uno::Sequence<text::TextContentAnchorType> aTypes(5);
+ text::TextContentAnchorType* pArray = aTypes.getArray();
+ pArray[0] = text::TextContentAnchorType_AT_PARAGRAPH;
+ pArray[1] = text::TextContentAnchorType_AS_CHARACTER;
+ pArray[2] = text::TextContentAnchorType_AT_PAGE;
+ pArray[3] = text::TextContentAnchorType_AT_FRAME;
+ pArray[4] = text::TextContentAnchorType_AT_CHARACTER;
+ aAny.setValue(&aTypes, ::getCppuType(static_cast<uno::Sequence<text::TextContentAnchorType>*>(0)));
+ }
+ else if(pFmt)
+ {
+ if( ((eType == FLYCNTTYPE_GRF) || (eType == FLYCNTTYPE_OLE)) &&
+ pEntry &&
+ (isGRFATR(pEntry->nWID) ||
+ pEntry->nWID == FN_PARAM_COUNTOUR_PP ||
+ pEntry->nWID == FN_UNO_IS_AUTOMATIC_CONTOUR ||
+ pEntry->nWID == FN_UNO_IS_PIXEL_CONTOUR ))
+ {
+ const SwNodeIndex* pIdx = pFmt->GetCntnt().GetCntntIdx();
+ if(pIdx)
+ {
+ SwNodeIndex aIdx(*pIdx, 1);
+ SwNoTxtNode* pNoTxt = aIdx.GetNode().GetNoTxtNode();
+ if(pEntry->nWID == FN_PARAM_COUNTOUR_PP)
+ {
+ PolyPolygon aContour;
+ if( pNoTxt->GetContourAPI( aContour ) )
+ {
+ drawing::PointSequenceSequence aPtSeq(aContour.Count());
+ drawing::PointSequence* pPSeq = aPtSeq.getArray();
+ for(sal_uInt16 i = 0; i < aContour.Count(); i++)
+ {
+ const Polygon& rPoly = aContour.GetObject(i);
+ pPSeq[i].realloc(rPoly.GetSize());
+ awt::Point* pPoints = pPSeq[i].getArray();
+ for(sal_uInt16 j = 0; j < rPoly.GetSize(); j++)
+ {
+ const Point& rPoint = rPoly.GetPoint(j);
+ pPoints[j].X = rPoint.X();
+ pPoints[j].Y = rPoint.Y();
+ }
+ }
+ aAny <<= aPtSeq;
+ }
+ }
+ else if(pEntry->nWID == FN_UNO_IS_AUTOMATIC_CONTOUR )
+ {
+ sal_Bool bValue = pNoTxt->HasAutomaticContour();
+ aAny.setValue( &bValue, ::getBooleanCppuType() );
+ }
+ else if(pEntry->nWID == FN_UNO_IS_PIXEL_CONTOUR )
+ {
+ sal_Bool bValue = pNoTxt->IsPixelContour();
+ aAny.setValue( &bValue, ::getBooleanCppuType() );
+ }
+ else
+ {
+ SfxItemSet aSet(pNoTxt->GetSwAttrSet());
+ m_pPropSet->getPropertyValue(*pEntry, aSet, aAny);
+ }
+ }
+ }
+ else if( FN_UNO_GRAPHIC_U_R_L == pEntry->nWID)
+ {
+ String sGrfName;
+ const SwNodeIndex* pIdx = pFmt->GetCntnt().GetCntntIdx();
+ if(pIdx)
+ {
+ SwNodeIndex aIdx(*pIdx, 1);
+// SwNoTxtNode* pNoTxt = aIdx.GetNode().GetNoTxtNode();
+ SwGrfNode* pGrfNode = aIdx.GetNode().GetGrfNode();
+ if(!pGrfNode)
+ throw uno::RuntimeException();
+ if( pGrfNode->IsGrfLink() )
+ {
+ pFmt->GetDoc()->GetGrfNms( *(SwFlyFrmFmt*)pFmt, &sGrfName, 0 );
+ }
+ else
+ {
+ String sPrefix( RTL_CONSTASCII_USTRINGPARAM(sGraphicObjectProtocol) );
+ String sId( pGrfNode->GetGrfObj().GetUniqueID(),
+ RTL_TEXTENCODING_ASCII_US );
+ (sGrfName = sPrefix) += sId;
+ }
+ }
+ aAny <<= OUString(sGrfName);
+ }
+ else if( FN_UNO_GRAPHIC_FILTER == pEntry->nWID )
+ {
+ String sFltName;
+ pFmt->GetDoc()->GetGrfNms( *(SwFlyFrmFmt*)pFmt, 0, &sFltName );
+ aAny <<= OUString(sFltName);
+ }
+ else if( FN_UNO_GRAPHIC == pEntry->nWID )
+ {
+ const SwNodeIndex* pIdx = pFmt->GetCntnt().GetCntntIdx();
+ if(pIdx)
+ {
+ SwNodeIndex aIdx(*pIdx, 1);
+ SwGrfNode* pGrfNode = aIdx.GetNode().GetGrfNode();
+ if(!pGrfNode)
+ throw uno::RuntimeException();
+ aAny <<= pGrfNode->GetGrf().GetXGraphic();
+ }
+ }
+ else if(FN_UNO_FRAME_STYLE_NAME == pEntry->nWID)
+ {
+ aAny <<= OUString(SwStyleNameMapper::GetProgName(pFmt->DerivedFrom()->GetName(), nsSwGetPoolIdFromName::GET_POOLID_FRMFMT ) );
+ }
+ // --> OD 2009-07-13 #i73249#
+ // Attribute AlternativeText was never published.
+ // Now it has been replaced by Attribute Title - valid for all <SwXFrame> instances
+// else if(eType != FLYCNTTYPE_FRM &&
+// FN_UNO_ALTERNATIVE_TEXT == pEntry->nWID)
+// {
+// const SwNodeIndex* pIdx = pFmt->GetCntnt().GetCntntIdx();
+// if(pIdx)
+// {
+// SwNodeIndex aIdx(*pIdx, 1);
+// SwNoTxtNode* pNoTxt = aIdx.GetNode().GetNoTxtNode();
+// aAny <<= OUString(pNoTxt->GetAlternateText());
+// }
+// }
+ else if( FN_UNO_TITLE == pEntry->nWID )
+ {
+ SwFlyFrmFmt* pFlyFmt = dynamic_cast<SwFlyFrmFmt*>(pFmt);
+ OSL_ENSURE( pFmt,
+ "unexpected type of <pFmt> --> crash" );
+ // assure that <SdrObject> instance exists.
+ GetOrCreateSdrObject( pFlyFmt );
+ aAny <<= OUString(pFlyFmt->GetObjTitle());
+ }
+ // New attribute Description
+ else if( FN_UNO_DESCRIPTION == pEntry->nWID )
+ {
+ SwFlyFrmFmt* pFlyFmt = dynamic_cast<SwFlyFrmFmt*>(pFmt);
+ OSL_ENSURE( pFmt,
+ "unexpected type of <pFmt> --> crash" );
+ // assure that <SdrObject> instance exists.
+ GetOrCreateSdrObject( pFlyFmt );
+ aAny <<= OUString(pFlyFmt->GetObjDescription());
+ }
+ // <--
+ else if(eType == FLYCNTTYPE_GRF &&
+ (rPropertyName.equalsAsciiL( SW_PROP_NAME(UNO_NAME_ACTUAL_SIZE))))
+ {
+ const SwNodeIndex* pIdx = pFmt->GetCntnt().GetCntntIdx();
+ if(pIdx)
+ {
+ SwNodeIndex aIdx(*pIdx, 1);
+ SwNoTxtNode* pNoTxt = aIdx.GetNode().GetNoTxtNode();
+ Size aActSize = ((SwGrfNode*)pNoTxt)->GetTwipSize();
+ awt::Size aTmp;
+ aTmp.Width = TWIP_TO_MM100(aActSize.Width());
+ aTmp.Height = TWIP_TO_MM100(aActSize.Height());
+ aAny.setValue(&aTmp, ::getCppuType(static_cast<const awt::Size*>(0)));
+ }
+ }
+ else if(FN_PARAM_LINK_DISPLAY_NAME == pEntry->nWID)
+ {
+ aAny <<= OUString(pFmt->GetName());
+ }
+ else if(FN_UNO_Z_ORDER == pEntry->nWID)
+ {
+ const SdrObject* pObj = pFmt->FindRealSdrObject();
+ if( pObj )
+ {
+ aAny <<= (sal_Int32)pObj->GetOrdNum();
+ }
+ }
+ else if(FN_UNO_CLSID == pEntry->nWID || FN_UNO_MODEL == pEntry->nWID||
+ FN_UNO_COMPONENT == pEntry->nWID ||FN_UNO_STREAM_NAME == pEntry->nWID||
+ FN_EMBEDDED_OBJECT == pEntry->nWID)
+ {
+ SwDoc* pDoc = pFmt->GetDoc();
+ const SwFmtCntnt* pCnt = &pFmt->GetCntnt();
+ DBG_ASSERT( pCnt->GetCntntIdx() &&
+ pDoc->GetNodes()[ pCnt->GetCntntIdx()->
+ GetIndex() + 1 ]->GetOLENode(), "kein OLE-Node?");
+
+ SwOLENode* pOleNode = pDoc->GetNodes()[ pCnt->GetCntntIdx()
+ ->GetIndex() + 1 ]->GetOLENode();
+ uno::Reference < embed::XEmbeddedObject > xIP = pOleNode->GetOLEObj().GetOleRef();
+ OUString aHexCLSID;
+ {
+ SvGlobalName aClassName( xIP->getClassID() );
+ aHexCLSID = aClassName.GetHexName();
+ if(FN_UNO_CLSID != pEntry->nWID)
+ {
+ if ( svt::EmbeddedObjectRef::TryRunningState( xIP ) )
+ {
+ uno::Reference < lang::XComponent > xComp( xIP->getComponent(), uno::UNO_QUERY );
+ uno::Reference < frame::XModel > xModel( xComp, uno::UNO_QUERY );
+ if ( FN_EMBEDDED_OBJECT == pEntry->nWID )
+ {
+ // ensure the
+ OSL_ENSURE( pDoc->GetDocShell(), "no doc shell => no client site" );
+ if ( pDoc->GetDocShell() )
+ pDoc->GetDocShell()->GetIPClient( svt::EmbeddedObjectRef( xIP, embed::Aspects::MSOLE_CONTENT ) );
+ aAny <<= xIP;
+ }
+ else if ( xModel.is() )
+ aAny <<= xModel;
+ else if ( FN_UNO_COMPONENT == pEntry->nWID )
+ aAny <<= xComp;
+ }
+ }
+ }
+
+ if(FN_UNO_CLSID == pEntry->nWID)
+ aAny <<= aHexCLSID;
+ else if(FN_UNO_STREAM_NAME == pEntry->nWID)
+ {
+ aAny <<= ::rtl::OUString(pOleNode->GetOLEObj().GetCurrentPersistName());
+ }
+ }
+ else if(WID_LAYOUT_SIZE == pEntry->nWID)
+ {
+ // format document completely in order to get correct value
+ pFmt->GetDoc()->GetEditShell()->CalcLayout();
+
+ SwFrm* pTmpFrm = SwIterator<SwFrm,SwFmt>::FirstElement( *pFmt );
+ if ( pTmpFrm )
+ {
+ DBG_ASSERT( pTmpFrm->IsValid(), "frame not valid" );
+ const SwRect &rRect = pTmpFrm->Frm();
+ Size aMM100Size = OutputDevice::LogicToLogic(
+ Size( rRect.Width(), rRect.Height() ),
+ MapMode( MAP_TWIP ), MapMode( MAP_100TH_MM ));
+ aAny <<= awt::Size( aMM100Size.Width(), aMM100Size.Height() );
+ }
+ }
+ else
+ {
+ const SwAttrSet& rSet = pFmt->GetAttrSet();
+ m_pPropSet->getPropertyValue(*pEntry, rSet, aAny);
+ }
+ }
+ else if(IsDescriptor())
+ {
+ if ( ! m_pDoc )
+ throw uno::RuntimeException();
+ if(WID_LAYOUT_SIZE != pEntry->nWID) // there is no LayoutSize in a descriptor
+ {
+ const uno::Any* pAny = 0;
+ if( !pProps->GetProperty( pEntry->nWID, pEntry->nMemberId, pAny ) )
+ aAny = mxStyleData->getPropertyValue( rPropertyName );
+ else if ( pAny )
+ aAny = *pAny;
+ }
+ }
+ else
+ throw uno::RuntimeException();
+ return aAny;
+}
+
+void SwXFrame::addPropertyChangeListener(const OUString& /*PropertyName*/,
+ const uno::Reference< beans::XPropertyChangeListener > & /*aListener*/)
+ throw( beans::UnknownPropertyException, lang::WrappedTargetException, uno::RuntimeException )
+{
+ DBG_WARNING("not implemented");
+}
+
+void SwXFrame::removePropertyChangeListener(const OUString& /*PropertyName*/,
+ const uno::Reference< beans::XPropertyChangeListener > & /*aListener*/)
+ throw( beans::UnknownPropertyException, lang::WrappedTargetException, uno::RuntimeException )
+{
+ DBG_WARNING("not implemented");
+}
+
+void SwXFrame::addVetoableChangeListener(const OUString& /*PropertyName*/,
+ const uno::Reference< beans::XVetoableChangeListener > & /*aListener*/)
+ throw( beans::UnknownPropertyException, lang::WrappedTargetException, uno::RuntimeException )
+{
+ DBG_WARNING("not implemented");
+}
+
+void SwXFrame::removeVetoableChangeListener(
+ const OUString& /*PropertyName*/, const uno::Reference< beans::XVetoableChangeListener > & /*aListener*/)
+ throw( beans::UnknownPropertyException, lang::WrappedTargetException, uno::RuntimeException )
+{
+ DBG_WARNING("not implemented");
+}
+
+beans::PropertyState SwXFrame::getPropertyState( const OUString& rPropertyName )
+ throw(beans::UnknownPropertyException, uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+ uno::Sequence< OUString > aPropertyNames(1);
+ OUString* pNames = aPropertyNames.getArray();
+ pNames[0] = rPropertyName;
+ uno::Sequence< beans::PropertyState > aStates = getPropertyStates(aPropertyNames);
+ return aStates.getConstArray()[0];
+}
+
+uno::Sequence< beans::PropertyState > SwXFrame::getPropertyStates(
+ const uno::Sequence< OUString >& aPropertyNames )
+ throw(beans::UnknownPropertyException, uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+ uno::Sequence< beans::PropertyState > aStates(aPropertyNames.getLength());
+ beans::PropertyState* pStates = aStates.getArray();
+ SwFrmFmt* pFmt = GetFrmFmt();
+ if(pFmt)
+ {
+ const OUString* pNames = aPropertyNames.getConstArray();
+ const SwAttrSet& rFmtSet = pFmt->GetAttrSet();
+ for(int i = 0; i < aPropertyNames.getLength(); i++)
+ {
+ const SfxItemPropertySimpleEntry* pEntry = m_pPropSet->getPropertyMap()->getByName(pNames[i]);
+ if (!pEntry)
+ throw beans::UnknownPropertyException(OUString ( RTL_CONSTASCII_USTRINGPARAM ( "Unknown property: " ) ) + pNames[i], static_cast < cppu::OWeakObject * > ( this ) );
+
+ if(pEntry->nWID == FN_UNO_ANCHOR_TYPES||
+ pEntry->nWID == FN_PARAM_LINK_DISPLAY_NAME||
+ FN_UNO_FRAME_STYLE_NAME == pEntry->nWID||
+ FN_UNO_GRAPHIC_U_R_L == pEntry->nWID||
+ FN_UNO_GRAPHIC_FILTER == pEntry->nWID||
+ FN_UNO_ACTUAL_SIZE == pEntry->nWID||
+ FN_UNO_ALTERNATIVE_TEXT == pEntry->nWID)
+ {
+ pStates[i] = beans::PropertyState_DIRECT_VALUE;
+ }
+ else
+ {
+ if ((eType == FLYCNTTYPE_GRF) &&
+ pEntry && isGRFATR(pEntry->nWID))
+ {
+ const SwNodeIndex* pIdx = pFmt->GetCntnt().GetCntntIdx();
+ if(pIdx)
+ {
+ SwNodeIndex aIdx(*pIdx, 1);
+ SwNoTxtNode* pNoTxt = aIdx.GetNode().GetNoTxtNode();
+ SfxItemSet aSet(pNoTxt->GetSwAttrSet());
+ aSet.GetItemState(pEntry->nWID);
+ if(SFX_ITEM_SET == aSet.GetItemState( pEntry->nWID, sal_False ))
+ pStates[i] = beans::PropertyState_DIRECT_VALUE;
+ }
+ }
+ else
+ {
+ if(SFX_ITEM_SET == rFmtSet.GetItemState( pEntry->nWID, sal_False ))
+ pStates[i] = beans::PropertyState_DIRECT_VALUE;
+ else
+ pStates[i] = beans::PropertyState_DEFAULT_VALUE;
+ }
+ }
+ }
+ }
+ else if(IsDescriptor())
+ {
+ for(int i = 0; i < aPropertyNames.getLength(); i++)
+ pStates[i] = beans::PropertyState_DIRECT_VALUE;
+ }
+ else
+ throw uno::RuntimeException();
+ return aStates;
+}
+
+void SwXFrame::setPropertyToDefault( const OUString& rPropertyName )
+ throw(beans::UnknownPropertyException, uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+ SwFrmFmt* pFmt = GetFrmFmt();
+ if(pFmt)
+ {
+ const SfxItemPropertySimpleEntry* pEntry = m_pPropSet->getPropertyMap()->getByName(rPropertyName);
+ if (!pEntry)
+ throw beans::UnknownPropertyException(OUString ( RTL_CONSTASCII_USTRINGPARAM ( "Unknown property: " ) ) + rPropertyName, static_cast < cppu::OWeakObject * > ( this ) );
+ if ( pEntry->nFlags & beans::PropertyAttribute::READONLY)
+ throw uno::RuntimeException( OUString ( RTL_CONSTASCII_USTRINGPARAM ( "setPropertyToDefault: property is read-only: " ) ) + rPropertyName, static_cast < cppu::OWeakObject * > ( this ) );
+
+ bool bNextFrame;
+ if( pEntry->nWID &&
+ pEntry->nWID != FN_UNO_ANCHOR_TYPES &&
+ pEntry->nWID != FN_PARAM_LINK_DISPLAY_NAME)
+ {
+ if ( (eType == FLYCNTTYPE_GRF) && isGRFATR(pEntry->nWID) )
+ {
+ const SwNodeIndex* pIdx = pFmt->GetCntnt().GetCntntIdx();
+ if(pIdx)
+ {
+ SwNodeIndex aIdx(*pIdx, 1);
+ SwNoTxtNode* pNoTxt = aIdx.GetNode().GetNoTxtNode();
+ {
+ SfxItemSet aSet(pNoTxt->GetSwAttrSet());
+ aSet.ClearItem(pEntry->nWID);
+ pNoTxt->SetAttr(aSet);
+ }
+ }
+ }
+ // --> OD 2009-07-13 #i73249#
+ // Attribute AlternativeText was never published.
+ // Now it has been replaced by Attribute Title - valid for all <SwXFrame> instances
+// else if( eType != FLYCNTTYPE_FRM && FN_UNO_ALTERNATIVE_TEXT == pEntry->nWID )
+// {
+// const SwNodeIndex* pIdx = pFmt->GetCntnt().GetCntntIdx();
+// if(pIdx)
+// {
+// SwNodeIndex aIdx(*pIdx, 1);
+// SwNoTxtNode* pNoTxt = aIdx.GetNode().GetNoTxtNode();
+// pNoTxt->SetAlternateText(aEmptyStr);
+// }
+// }
+ // New attribute Title
+ else if( FN_UNO_TITLE == pEntry->nWID )
+ {
+ SwFlyFrmFmt* pFlyFmt = dynamic_cast<SwFlyFrmFmt*>(pFmt);
+ OSL_ENSURE( pFmt,
+ "unexpected type of <pFmt> --> crash" );
+ // assure that <SdrObject> instance exists.
+ GetOrCreateSdrObject( pFlyFmt );
+ pFlyFmt->GetDoc()->SetFlyFrmTitle( *(pFlyFmt), aEmptyStr );
+ }
+ // New attribute Description
+ else if( FN_UNO_DESCRIPTION == pEntry->nWID )
+ {
+ SwFlyFrmFmt* pFlyFmt = dynamic_cast<SwFlyFrmFmt*>(pFmt);
+ OSL_ENSURE( pFmt,
+ "unexpected type of <pFmt> --> crash" );
+ // assure that <SdrObject> instance exists.
+ GetOrCreateSdrObject( pFlyFmt );
+ pFlyFmt->GetDoc()->SetFlyFrmDescription( *(pFlyFmt), aEmptyStr );
+ }
+ // <--
+ else
+ {
+ SwDoc* pDoc = pFmt->GetDoc();
+ SfxItemSet aSet( pDoc->GetAttrPool(),
+ RES_FRMATR_BEGIN, RES_FRMATR_END - 1 );
+ aSet.SetParent(&pFmt->GetAttrSet());
+ aSet.ClearItem(pEntry->nWID);
+ if(!rPropertyName.equalsAsciiL( SW_PROP_NAME(UNO_NAME_ANCHOR_TYPE)))
+ pFmt->SetFmtAttr(aSet);
+ }
+ }
+ else if(0 != (bNextFrame = (rPropertyName.equalsAsciiL( SW_PROP_NAME(UNO_NAME_CHAIN_NEXT_NAME))))
+ || rPropertyName.equalsAsciiL( SW_PROP_NAME(UNO_NAME_CHAIN_PREV_NAME)))
+ {
+ SwDoc* pDoc = pFmt->GetDoc();
+ if(bNextFrame)
+ pDoc->Unchain(*pFmt);
+ else
+ {
+ SwFmtChain aChain( pFmt->GetChain() );
+ SwFrmFmt *pPrev = aChain.GetPrev();
+ if(pPrev)
+ pDoc->Unchain(*pPrev);
+ }
+ }
+ }
+ else if(!IsDescriptor())
+ throw uno::RuntimeException();
+
+}
+
+uno::Any SwXFrame::getPropertyDefault( const OUString& rPropertyName )
+ throw(beans::UnknownPropertyException, lang::WrappedTargetException, uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+ uno::Any aRet;
+ SwFrmFmt* pFmt = GetFrmFmt();
+ if(pFmt)
+ {
+ const SfxItemPropertySimpleEntry* pEntry = m_pPropSet->getPropertyMap()->getByName(rPropertyName);
+ if(pEntry)
+ {
+ if ( pEntry->nWID < RES_FRMATR_END )
+ {
+ const SfxPoolItem& rDefItem =
+ pFmt->GetDoc()->GetAttrPool().GetDefaultItem(pEntry->nWID);
+ rDefItem.QueryValue(aRet, pEntry->nMemberId);
+ }
+ }
+ else
+ throw beans::UnknownPropertyException(OUString ( RTL_CONSTASCII_USTRINGPARAM ( "Unknown property: " ) ) + rPropertyName, static_cast < cppu::OWeakObject * > ( this ) );
+ }
+ else if(!IsDescriptor())
+ throw uno::RuntimeException();
+ return aRet;
+}
+
+void SwXFrame::addEventListener(const uno::Reference< lang::XEventListener > & aListener) throw( uno::RuntimeException )
+{
+ if(!GetRegisteredIn())
+ throw uno::RuntimeException();
+ aLstnrCntnr.AddListener(aListener);
+}
+
+void SwXFrame::removeEventListener(const uno::Reference< lang::XEventListener > & aListener) throw( uno::RuntimeException )
+{
+ if(!GetRegisteredIn() || !aLstnrCntnr.RemoveListener(aListener))
+ throw uno::RuntimeException();
+}
+
+void SwXFrame::Modify( const SfxPoolItem* pOld, const SfxPoolItem *pNew)
+{
+ ClientModify(this, pOld, pNew);
+ if(!GetRegisteredIn())
+ {
+ mxStyleData.clear();
+ mxStyleFamily.clear();
+ m_pDoc = 0;
+ aLstnrCntnr.Disposing();
+ }
+}
+
+void SwXFrame::dispose(void) throw( uno::RuntimeException )
+{
+ SolarMutexGuard aGuard;
+ SwFrmFmt* pFmt = GetFrmFmt();
+ if ( pFmt )
+ {
+ SdrObject* pObj = pFmt->FindSdrObject();
+ // OD 11.09.2003 #112039# - add condition to perform delete of
+ // format/anchor sign, not only if the object is inserted, but also
+ // if a contact object is registered, which isn't in the destruction.
+ if ( pObj &&
+ ( pObj->IsInserted() ||
+ ( pObj->GetUserCall() &&
+ !static_cast<SwContact*>(pObj->GetUserCall())->IsInDTOR() ) ) )
+ {
+ if (pFmt->GetAnchor().GetAnchorId() == FLY_AS_CHAR)
+ {
+ const SwPosition &rPos = *(pFmt->GetAnchor().GetCntntAnchor());
+ SwTxtNode *pTxtNode = rPos.nNode.GetNode().GetTxtNode();
+ const xub_StrLen nIdx = rPos.nContent.GetIndex();
+ pTxtNode->DeleteAttributes( RES_TXTATR_FLYCNT, nIdx, nIdx );
+ }
+ else
+ pFmt->GetDoc()->DelLayoutFmt(pFmt);
+ }
+ }
+
+}
+
+uno::Reference< text::XTextRange > SwXFrame::getAnchor(void) throw( uno::RuntimeException )
+{
+ SolarMutexGuard aGuard;
+ uno::Reference< text::XTextRange > aRef;
+ SwFrmFmt* pFmt = GetFrmFmt();
+ if(pFmt)
+ {
+ const SwFmtAnchor& rAnchor = pFmt->GetAnchor();
+ // return an anchor for non-page bound frames
+ // and for page bound frames that have a page no == NULL and a content position
+ if ((rAnchor.GetAnchorId() != FLY_AT_PAGE) ||
+ (rAnchor.GetCntntAnchor() && !rAnchor.GetPageNum()))
+ {
+ const SwPosition &rPos = *(rAnchor.GetCntntAnchor());
+ aRef = SwXTextRange::CreateXTextRange(*pFmt->GetDoc(), rPos, 0);
+ }
+ }
+ else
+ throw uno::RuntimeException();
+ return aRef;
+}
+
+void SwXFrame::ResetDescriptor()
+{
+ bIsDescriptor = false;
+ mxStyleData.clear();
+ mxStyleFamily.clear();
+ DELETEZ(pProps);
+}
+
+void SwXFrame::attachToRange(const uno::Reference< text::XTextRange > & xTextRange)
+ throw( lang::IllegalArgumentException, uno::RuntimeException )
+{
+ SolarMutexGuard aGuard;
+ if(!IsDescriptor())
+ throw uno::RuntimeException();
+ uno::Reference<lang::XUnoTunnel> xRangeTunnel( xTextRange, uno::UNO_QUERY);
+ SwXTextRange* pRange = 0;
+ OTextCursorHelper* pCursor = 0;
+ if(xRangeTunnel.is())
+ {
+ pRange = reinterpret_cast< SwXTextRange * >(
+ sal::static_int_cast< sal_IntPtr >( xRangeTunnel->getSomething( SwXTextRange::getUnoTunnelId()) ));
+ pCursor = reinterpret_cast< OTextCursorHelper * >(
+ sal::static_int_cast< sal_IntPtr >( xRangeTunnel->getSomething( OTextCursorHelper::getUnoTunnelId()) ));
+ }
+
+ SwDoc* pDoc = pRange ? (SwDoc*)pRange->GetDoc() : pCursor ? (SwDoc*)pCursor->GetDoc() : 0;
+ if(pDoc)
+ {
+ SwUnoInternalPaM aIntPam(*pDoc);
+ //das muss jetzt true liefern
+ ::sw::XTextRangeToSwPaM(aIntPam, xTextRange);
+
+ SwNode& rNode = pDoc->GetNodes().GetEndOfContent();
+ SwPaM aPam(rNode);
+ aPam.Move( fnMoveBackward, fnGoDoc );
+ static sal_uInt16 const aFrmAttrRange[] =
+ {
+ RES_FRMATR_BEGIN, RES_FRMATR_END-1,
+ SID_ATTR_BORDER_INNER, SID_ATTR_BORDER_INNER,
+ RES_UNKNOWNATR_CONTAINER, RES_UNKNOWNATR_CONTAINER,
+ 0
+ };
+ static sal_uInt16 const aGrAttrRange[] =
+ {
+ RES_GRFATR_BEGIN, RES_GRFATR_END-1,
+ 0
+ };
+ SfxItemSet aGrSet(pDoc->GetAttrPool(), aGrAttrRange );
+
+ SfxItemSet aFrmSet(pDoc->GetAttrPool(), aFrmAttrRange );
+ //jetzt muessen die passenden Items in den Set
+ bool bSizeFound;
+ if(!pProps->AnyToItemSet( pDoc, aFrmSet, aGrSet, bSizeFound))
+ throw lang::IllegalArgumentException();
+ //der TextRange wird einzeln behandelt
+ *aPam.GetPoint() = *aIntPam.GetPoint();
+ if(aIntPam.HasMark())
+ {
+ aPam.SetMark();
+ *aPam.GetMark() = *aIntPam.GetMark();
+ }
+
+ const SfxPoolItem* pItem;
+ RndStdIds eAnchorId = FLY_AT_PARA;
+ if(SFX_ITEM_SET == aFrmSet.GetItemState(RES_ANCHOR, false, &pItem) )
+ {
+ eAnchorId = ((const SwFmtAnchor*)pItem)->GetAnchorId();
+ if( FLY_AT_FLY == eAnchorId &&
+ !aPam.GetNode()->FindFlyStartNode())
+ {
+ //rahmengebunden geht nur dort, wo ein Rahmen ist!
+ SwFmtAnchor aAnchor(FLY_AT_PARA);
+ aFrmSet.Put(aAnchor);
+ }
+ else if ((FLY_AT_PAGE == eAnchorId) &&
+ 0 == ((const SwFmtAnchor*)pItem)->GetPageNum() )
+ {
+ SwFmtAnchor aAnchor( *((const SwFmtAnchor*)pItem) );
+ aAnchor.SetAnchor( aPam.GetPoint() );
+ aFrmSet.Put(aAnchor);
+ }
+ }
+
+ const ::uno::Any* pStyle;
+ SwFrmFmt *pParentFrmFmt = 0;
+ if(pProps->GetProperty(FN_UNO_FRAME_STYLE_NAME, 0, pStyle))
+ pParentFrmFmt = lcl_GetFrmFmt( *pStyle, pDoc );
+
+ SwFlyFrmFmt* pFmt = 0;
+ if( eType == FLYCNTTYPE_FRM)
+ {
+ UnoActionContext aCont(pDoc);
+ if(m_pCopySource)
+ {
+ SwFmtAnchor* pAnchorItem = 0;
+ // the frame is inserted bound to page
+ // to prevent conflicts if the to-be-anchored position is part of the to-be-copied text
+ if (eAnchorId != FLY_AT_PAGE)
+ {
+ pAnchorItem = static_cast<SwFmtAnchor*>(aFrmSet.Get(RES_ANCHOR).Clone());
+ aFrmSet.Put( SwFmtAnchor( FLY_AT_PAGE, 1 ));
+ }
+
+ pFmt = pDoc->MakeFlyAndMove( *m_pCopySource, aFrmSet,
+ 0,
+ pParentFrmFmt );
+ if(pAnchorItem && pFmt)
+ {
+ pFmt->DelFrms();
+ pAnchorItem->SetAnchor( m_pCopySource->Start() );
+ SfxItemSet aAnchorSet( pDoc->GetAttrPool(), RES_ANCHOR, RES_ANCHOR );
+ aAnchorSet.Put( *pAnchorItem );
+ pDoc->SetFlyFrmAttr( *pFmt, aAnchorSet );
+ delete pAnchorItem;
+ }
+ DELETEZ( m_pCopySource );
+ }
+ else
+ {
+ pFmt = pDoc->MakeFlySection( FLY_AT_PARA, aPam.GetPoint(),
+ &aFrmSet, pParentFrmFmt );
+ }
+ if(pFmt)
+ {
+ pFmt->Add(this);
+ if(sName.Len())
+ pDoc->SetFlyName((SwFlyFrmFmt&)*pFmt, sName);
+ }
+ //den SwXText wecken
+ ((SwXTextFrame*)this)->SetDoc( bIsDescriptor ? m_pDoc : GetFrmFmt()->GetDoc() );
+ }
+ else if( eType == FLYCNTTYPE_GRF)
+ {
+ UnoActionContext aCont(pDoc);
+ const ::uno::Any* pGraphicURL;
+ String sGraphicURL;
+ GraphicObject *pGrfObj = 0;
+ if(pProps->GetProperty(FN_UNO_GRAPHIC_U_R_L, 0, pGraphicURL))
+ {
+ OUString uTemp;
+ (*pGraphicURL) >>= uTemp;
+ sGraphicURL = String(uTemp);
+ if( sGraphicURL.EqualsAscii( sPackageProtocol,
+ 0, sizeof( sPackageProtocol )-1 ) )
+ {
+ pGrfObj = new GraphicObject;
+ pGrfObj->SetUserData( sGraphicURL );
+ pGrfObj->SetSwapState();
+ sGraphicURL.Erase();
+ }
+ else if( sGraphicURL.EqualsAscii( sGraphicObjectProtocol,
+ 0, sizeof(sGraphicObjectProtocol)-1 ) )
+ {
+ ByteString sId( sGraphicURL.Copy( sizeof(sGraphicObjectProtocol)-1 ),
+ RTL_TEXTENCODING_ASCII_US );
+ pGrfObj = new GraphicObject( sId );
+ sGraphicURL.Erase();
+ }
+ }
+ Graphic aGraphic;
+ const ::uno::Any* pGraphic;
+ if( pProps->GetProperty( FN_UNO_GRAPHIC, 0, pGraphic ))
+ {
+ uno::Reference< graphic::XGraphic > xGraphic;
+ (*pGraphic) >>= xGraphic;
+ aGraphic = Graphic( xGraphic );
+ }
+
+ String sFltName;
+ const ::uno::Any* pFilter;
+ if(pProps->GetProperty(FN_UNO_GRAPHIC_FILTER, 0, pFilter))
+ {
+ OUString uTemp;
+ (*pFilter) >>= uTemp;
+ sFltName = String(uTemp);
+ }
+
+ pFmt =
+ pGrfObj ? pDoc->Insert( aPam, *pGrfObj, &aFrmSet, &aGrSet,
+ pParentFrmFmt )
+ : pDoc->Insert( aPam, sGraphicURL, sFltName, &aGraphic,
+ &aFrmSet, &aGrSet, pParentFrmFmt );
+ delete pGrfObj;
+ if(pFmt)
+ {
+ SwGrfNode *pGrfNd = pDoc->GetNodes()[ pFmt->GetCntnt().GetCntntIdx()
+ ->GetIndex()+1 ]->GetGrfNode();
+ pGrfNd->SetChgTwipSize( !bSizeFound );
+ pFmt->Add(this);
+ if(sName.Len())
+ pDoc->SetFlyName((SwFlyFrmFmt&)*pFmt, sName);
+
+ }
+ const ::uno::Any* pSurroundContour;
+ if(pProps->GetProperty(RES_SURROUND, MID_SURROUND_CONTOUR, pSurroundContour))
+ setPropertyValue(rtl::OUString::createFromAscii(SW_PROP_NAME_STR(UNO_NAME_SURROUND_CONTOUR)), *pSurroundContour);
+ const ::uno::Any* pContourOutside;
+ if(pProps->GetProperty(RES_SURROUND, MID_SURROUND_CONTOUROUTSIDE, pContourOutside))
+ setPropertyValue(rtl::OUString::createFromAscii(SW_PROP_NAME_STR(UNO_NAME_CONTOUR_OUTSIDE)), *pContourOutside);
+ const ::uno::Any* pContourPoly;
+ if(pProps->GetProperty(FN_PARAM_COUNTOUR_PP, 0, pContourPoly))
+ setPropertyValue(rtl::OUString::createFromAscii(SW_PROP_NAME_STR(UNO_NAME_CONTOUR_POLY_POLYGON)), *pContourPoly);
+ const ::uno::Any* pPixelContour;
+ if(pProps->GetProperty(FN_UNO_IS_PIXEL_CONTOUR, 0, pPixelContour))
+ setPropertyValue(rtl::OUString::createFromAscii(SW_PROP_NAME_STR(UNO_NAME_IS_PIXEL_CONTOUR)), *pPixelContour);
+ const ::uno::Any* pAutoContour;
+ if(pProps->GetProperty(FN_UNO_IS_AUTOMATIC_CONTOUR, 0, pAutoContour))
+ setPropertyValue(rtl::OUString::createFromAscii(SW_PROP_NAME_STR(UNO_NAME_IS_AUTOMATIC_CONTOUR)), *pAutoContour);
+ }
+ else
+ {
+ const ::uno::Any* pCLSID = 0;
+ const ::uno::Any* pStreamName = 0;
+ if(!pProps->GetProperty(FN_UNO_CLSID, 0, pCLSID) && !pProps->GetProperty( FN_UNO_STREAM_NAME, 0, pStreamName ))
+ throw uno::RuntimeException();
+ if(pCLSID)
+ {
+ OUString aCLSID;
+ SvGlobalName aClassName;
+ uno::Reference < embed::XEmbeddedObject > xIPObj;
+ std::auto_ptr < comphelper::EmbeddedObjectContainer > pCnt;
+ if( (*pCLSID) >>= aCLSID )
+ {
+ if( !aClassName.MakeId( aCLSID ) )
+ {
+ lang::IllegalArgumentException aExcept;
+ aExcept.Message = OUString(RTL_CONSTASCII_USTRINGPARAM("CLSID invalid"));
+ throw aExcept;
+ }
+
+ pCnt.reset( new comphelper::EmbeddedObjectContainer );
+ ::rtl::OUString aName;
+ xIPObj = pCnt->CreateEmbeddedObject( aClassName.GetByteSequence(), aName );
+ }
+ if ( xIPObj.is() )
+ {
+ //TODO/LATER: MISCSTATUS_RESIZEONPRINTERCHANGE
+ //if( SVOBJ_MISCSTATUS_RESIZEONPRINTERCHANGE & xIPObj->GetMiscStatus() && pDoc->getPrinter( false ) )
+ // xIPObj->OnDocumentPrinterChanged( pDoc->getPrinter( false ) );
+
+ UnoActionContext aAction(pDoc);
+ pDoc->GetIDocumentUndoRedo().StartUndo(UNDO_INSERT, NULL);
+ if(!bSizeFound)
+ {
+ //TODO/LATER: from where do I get a ViewAspect? And how do I transport it to the OLENode?
+ sal_Int64 nAspect = embed::Aspects::MSOLE_CONTENT;
+
+ // TODO/LEAN: VisualArea still needs running state
+ svt::EmbeddedObjectRef::TryRunningState( xIPObj );
+
+ // set parent to get correct VisArea(in case of object needing parent printer)
+ uno::Reference < container::XChild > xChild( xIPObj, uno::UNO_QUERY );
+ if ( xChild.is() )
+ xChild->setParent( pDoc->GetDocShell()->GetModel() );
+
+ //The Size should be suggested by the OLE server if not manually set
+ MapUnit aRefMap = VCLUnoHelper::UnoEmbed2VCLMapUnit( xIPObj->getMapUnit( nAspect ) );
+ awt::Size aSize;
+ try
+ {
+ aSize = xIPObj->getVisualAreaSize( nAspect );
+ }
+ catch ( embed::NoVisualAreaSizeException& )
+ {
+ // the default size will be set later
+ }
+
+ Size aSz( aSize.Width, aSize.Height );
+ if ( !aSz.Width() || !aSz.Height() )
+ {
+ aSz.Width() = aSz.Height() = 5000;
+ aSz = OutputDevice::LogicToLogic
+ ( aSz, MapMode( MAP_100TH_MM ), aRefMap );
+ }
+ MapMode aMyMap( MAP_TWIP );
+ aSz = OutputDevice::LogicToLogic( aSz, aRefMap, aMyMap );
+ SwFmtFrmSize aFrmSz;
+ aFrmSz.SetSize(aSz);
+ aFrmSet.Put(aFrmSz);
+ }
+ SwFlyFrmFmt* pFmt2 = 0;
+
+ // TODO/LATER: Is it the only possible aspect here?
+ sal_Int64 nAspect = embed::Aspects::MSOLE_CONTENT;
+ ::svt::EmbeddedObjectRef xObjRef( xIPObj, nAspect );
+ pFmt2 = pDoc->Insert(aPam, xObjRef, &aFrmSet, NULL, NULL );
+ OSL_ENSURE( pFmt2, "Doc->Insert(notxt) failed." );
+
+ pDoc->GetIDocumentUndoRedo().EndUndo(UNDO_INSERT, NULL);
+ pFmt2->Add(this);
+ if(sName.Len())
+ pDoc->SetFlyName((SwFlyFrmFmt&)*pFmt2, sName);
+ }
+ }
+ else if( pStreamName )
+ {
+ ::rtl::OUString sStreamName;
+ (*pStreamName) >>= sStreamName;
+ pDoc->GetIDocumentUndoRedo().StartUndo(UNDO_INSERT, NULL);
+
+ SwFlyFrmFmt* pFrmFmt = 0;
+ pFrmFmt = pDoc->InsertOLE( aPam, sStreamName, embed::Aspects::MSOLE_CONTENT, &aFrmSet, NULL, NULL );
+ pDoc->GetIDocumentUndoRedo().EndUndo(UNDO_INSERT, NULL);
+ pFrmFmt->Add(this);
+ if(sName.Len())
+ pDoc->SetFlyName((SwFlyFrmFmt&)*pFrmFmt, sName);
+ }
+ }
+ if( pFmt && pDoc->GetDrawModel() )
+ GetOrCreateSdrObject( pFmt );
+ const ::uno::Any* pOrder;
+ if( pProps->GetProperty(FN_UNO_Z_ORDER, 0, pOrder) )
+ setPropertyValue(rtl::OUString::createFromAscii(SW_PROP_NAME_STR(UNO_NAME_Z_ORDER)), *pOrder);
+ const ::uno::Any* pReplacement;
+ if( pProps->GetProperty(FN_UNO_REPLACEMENT_GRAPHIC, 0, pReplacement) )
+ setPropertyValue(rtl::OUString::createFromAscii(SW_PROP_NAME_STR(UNO_NAME_GRAPHIC)), *pReplacement);
+ // new attribute Title
+ const ::uno::Any* pTitle;
+ if ( pProps->GetProperty(FN_UNO_TITLE, 0, pTitle) )
+ {
+ setPropertyValue(rtl::OUString::createFromAscii(SW_PROP_NAME_STR(UNO_NAME_TITLE)), *pTitle);
+ }
+ // new attribute Description
+ const ::uno::Any* pDescription;
+ if ( pProps->GetProperty(FN_UNO_DESCRIPTION, 0, pDescription) )
+ {
+ setPropertyValue(rtl::OUString::createFromAscii(SW_PROP_NAME_STR(UNO_NAME_DESCRIPTION)), *pDescription);
+ }
+ }
+ else
+ throw lang::IllegalArgumentException();
+ //setzt das Flag zurueck und loescht den Descriptor-Pointer
+ ResetDescriptor();
+}
+
+void SwXFrame::attach(const uno::Reference< text::XTextRange > & xTextRange)
+ throw( lang::IllegalArgumentException, uno::RuntimeException )
+{
+ SwFrmFmt* pFmt;
+ if(IsDescriptor())
+ attachToRange(xTextRange);
+ else if(0 != (pFmt = GetFrmFmt()))
+ {
+ uno::Reference<lang::XUnoTunnel> xRangeTunnel( xTextRange, uno::UNO_QUERY);
+ SwDoc* pDoc = pFmt->GetDoc();
+ SwUnoInternalPaM aIntPam(*pDoc);
+ if (::sw::XTextRangeToSwPaM(aIntPam, xTextRange))
+ {
+ SfxItemSet aSet( pDoc->GetAttrPool(), RES_ANCHOR, RES_ANCHOR );
+ aSet.SetParent(&pFmt->GetAttrSet());
+ SwFmtAnchor aAnchor = (const SwFmtAnchor&)aSet.Get(RES_ANCHOR);
+ aAnchor.SetAnchor( aIntPam.Start() );
+ aSet.Put(aAnchor);
+ pDoc->SetFlyFrmAttr( *pFmt, aSet );
+ }
+ else
+ throw lang::IllegalArgumentException();
+ }
+}
+
+awt::Point SwXFrame::getPosition(void) throw( uno::RuntimeException )
+{
+ SolarMutexGuard aGuard;
+ uno::RuntimeException aRuntime;
+ aRuntime.Message = C2U("position cannot be determined with this method");
+ throw aRuntime;
+}
+
+void SwXFrame::setPosition(const awt::Point& /*aPosition*/) throw( uno::RuntimeException )
+{
+ SolarMutexGuard aGuard;
+ uno::RuntimeException aRuntime;
+ aRuntime.Message = C2U("position cannot be changed with this method");
+ throw aRuntime;
+}
+
+awt::Size SwXFrame::getSize(void) throw( uno::RuntimeException )
+{
+ const ::uno::Any aVal = getPropertyValue(C2U("Size"));
+ awt::Size* pRet = (awt::Size*)aVal.getValue();
+ return *pRet;
+}
+
+void SwXFrame::setSize(const awt::Size& aSize)
+ throw( beans::PropertyVetoException, uno::RuntimeException )
+{
+ const ::uno::Any aVal(&aSize, ::getCppuType(static_cast<const awt::Size*>(0)));
+ setPropertyValue(C2U("Size"), aVal);
+}
+
+OUString SwXFrame::getShapeType(void) throw( uno::RuntimeException )
+{
+ return C2U("FrameShape");
+}
+
+/******************************************************************
+ * SwXTextFrame
+ ******************************************************************/
+SwXTextFrame::SwXTextFrame( SwDoc *_pDoc ) :
+ SwXText(0, CURSOR_FRAME),
+ SwXFrame(FLYCNTTYPE_FRM, aSwMapProvider.GetPropertySet(PROPERTY_MAP_TEXT_FRAME), _pDoc )
+{
+}
+
+SwXTextFrame::SwXTextFrame(SwFrmFmt& rFmt) :
+ SwXText(rFmt.GetDoc(), CURSOR_FRAME),
+ SwXFrame(rFmt, FLYCNTTYPE_FRM, aSwMapProvider.GetPropertySet(PROPERTY_MAP_TEXT_FRAME))
+{
+
+}
+
+SwXTextFrame::~SwXTextFrame()
+{
+}
+
+void SAL_CALL SwXTextFrame::acquire( )throw()
+{
+ SwXFrame::acquire();
+}
+
+void SAL_CALL SwXTextFrame::release( )throw()
+{
+ SwXFrame::release();
+}
+
+::uno::Any SAL_CALL SwXTextFrame::queryInterface( const uno::Type& aType )
+ throw (uno::RuntimeException)
+{
+ ::uno::Any aRet = SwXFrame::queryInterface(aType);
+ if(aRet.getValueType() == ::getCppuVoidType())
+ aRet = SwXText::queryInterface(aType);
+ if(aRet.getValueType() == ::getCppuVoidType())
+ aRet = SwXTextFrameBaseClass::queryInterface(aType);
+ return aRet;
+}
+
+uno::Sequence< uno::Type > SAL_CALL SwXTextFrame::getTypes( ) throw(uno::RuntimeException)
+{
+ uno::Sequence< uno::Type > aTextFrameTypes = SwXTextFrameBaseClass::getTypes();
+ uno::Sequence< uno::Type > aFrameTypes = SwXFrame::getTypes();
+ uno::Sequence< uno::Type > aTextTypes = SwXText::getTypes();
+
+ long nIndex = aTextFrameTypes.getLength();
+ aTextFrameTypes.realloc(
+ aTextFrameTypes.getLength() +
+ aFrameTypes.getLength() +
+ aTextTypes.getLength());
+
+ uno::Type* pTextFrameTypes = aTextFrameTypes.getArray();
+ const uno::Type* pFrameTypes = aFrameTypes.getConstArray();
+ long nPos;
+ for(nPos = 0; nPos <aFrameTypes.getLength(); nPos++)
+ pTextFrameTypes[nIndex++] = pFrameTypes[nPos];
+
+ const uno::Type* pTextTypes = aTextTypes.getConstArray();
+ for(nPos = 0; nPos <aTextTypes.getLength(); nPos++)
+ pTextFrameTypes[nIndex++] = pTextTypes[nPos];
+
+ return aTextFrameTypes;
+}
+
+uno::Sequence< sal_Int8 > SAL_CALL SwXTextFrame::getImplementationId( ) throw(uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+ static uno::Sequence< sal_Int8 > aId( 16 );
+ static bool bInit = false;
+ if(!bInit)
+ {
+ rtl_createUuid((sal_uInt8 *)(aId.getArray() ), 0, true);
+ bInit = true;
+ }
+ return aId;
+}
+
+uno::Reference< text::XText > SwXTextFrame::getText(void) throw( uno::RuntimeException )
+{
+ return this;
+}
+
+const SwStartNode *SwXTextFrame::GetStartNode() const
+{
+ const SwStartNode *pSttNd = 0;
+
+ SwFrmFmt* pFmt = GetFrmFmt();
+ if(pFmt)
+ {
+ const SwFmtCntnt& rFlyCntnt = pFmt->GetCntnt();
+ if( rFlyCntnt.GetCntntIdx() )
+ pSttNd = rFlyCntnt.GetCntntIdx()->GetNode().GetStartNode();
+ }
+
+ return pSttNd;
+}
+
+uno::Reference< text::XTextCursor >
+SwXTextFrame::CreateCursor() throw (uno::RuntimeException)
+{
+ return createTextCursor();
+}
+
+uno::Reference< text::XTextCursor > SwXTextFrame::createTextCursor(void) throw( uno::RuntimeException )
+{
+ SolarMutexGuard aGuard;
+ uno::Reference< text::XTextCursor > aRef;
+ SwFrmFmt* pFmt = GetFrmFmt();
+ if(pFmt)
+ {
+ //save current start node to be able to check if there is content after the table -
+ //otherwise the cursor would be in the body text!
+ const SwNode& rNode = pFmt->GetCntnt().GetCntntIdx()->GetNode();
+ const SwStartNode* pOwnStartNode = rNode.FindSttNodeByType(SwFlyStartNode);
+
+ SwPaM aPam(rNode);
+ aPam.Move(fnMoveForward, fnGoNode);
+ SwTableNode* pTblNode = aPam.GetNode()->FindTableNode();
+ SwCntntNode* pCont = 0;
+ while( pTblNode )
+ {
+ aPam.GetPoint()->nNode = *pTblNode->EndOfSectionNode();
+ pCont = GetDoc()->GetNodes().GoNext(&aPam.GetPoint()->nNode);
+ pTblNode = pCont->FindTableNode();
+ }
+ if(pCont)
+ aPam.GetPoint()->nContent.Assign(pCont, 0);
+
+ const SwStartNode* pNewStartNode =
+ aPam.GetNode()->FindSttNodeByType(SwFlyStartNode);
+ if(!pNewStartNode || pNewStartNode != pOwnStartNode)
+ {
+ uno::RuntimeException aExcept;
+ aExcept.Message = S2U("no text available");
+ throw aExcept;
+ }
+
+ SwXTextCursor *const pXCursor = new SwXTextCursor(
+ *pFmt->GetDoc(), this, CURSOR_FRAME, *aPam.GetPoint());
+ aRef = static_cast<text::XWordCursor*>(pXCursor);
+#if OSL_DEBUG_LEVEL > 1
+ SwUnoCrsr *const pUnoCrsr = pXCursor->GetCursor();
+ (void) pUnoCrsr;
+#endif
+ }
+ else
+ throw uno::RuntimeException();
+ return aRef;
+}
+
+uno::Reference< text::XTextCursor > SwXTextFrame::createTextCursorByRange(const uno::Reference< text::XTextRange > & aTextPosition) throw( uno::RuntimeException )
+{
+ SolarMutexGuard aGuard;
+ uno::Reference< text::XTextCursor > aRef;
+ SwFrmFmt* pFmt = GetFrmFmt();
+ SwUnoInternalPaM aPam(*GetDoc());
+ if (pFmt && ::sw::XTextRangeToSwPaM(aPam, aTextPosition))
+ {
+ SwNode& rNode = pFmt->GetCntnt().GetCntntIdx()->GetNode();
+#if OSL_DEBUG_LEVEL > 1
+ const SwStartNode* p1 = aPam.GetNode()->FindFlyStartNode();
+ const SwStartNode* p2 = rNode.FindFlyStartNode();
+ (void)p1;
+ (void)p2;
+#endif
+ if(aPam.GetNode()->FindFlyStartNode() == rNode.FindFlyStartNode())
+ {
+ aRef = static_cast<text::XWordCursor*>(
+ new SwXTextCursor(*pFmt->GetDoc(), this, CURSOR_FRAME,
+ *aPam.GetPoint(), aPam.GetMark()));
+ }
+ }
+ else
+ throw uno::RuntimeException();
+ return aRef;
+}
+
+uno::Reference< container::XEnumeration > SwXTextFrame::createEnumeration(void) throw( uno::RuntimeException )
+{
+ SolarMutexGuard aGuard;
+ uno::Reference< container::XEnumeration > aRef;
+ SwFrmFmt* pFmt = GetFrmFmt();
+ if(pFmt)
+ {
+ SwPosition aPos(pFmt->GetCntnt().GetCntntIdx()->GetNode());
+ ::std::auto_ptr<SwUnoCrsr> pUnoCursor(
+ GetDoc()->CreateUnoCrsr(aPos, false));
+ pUnoCursor->Move(fnMoveForward, fnGoNode);
+// // no Cursor in protected sections
+// SwCrsrSaveState aSave( *pUnoCrsr );
+// if(pUnoCrsr->IsInProtectTable(true) ||
+// pUnoCrsr->IsSelOvr( SELOVER_TOGGLE | SELOVER_CHANGEPOS ))
+// throw uno::RuntimeException() );
+ aRef = new SwXParagraphEnumeration(this, pUnoCursor, CURSOR_FRAME);
+ }
+ return aRef;
+}
+
+uno::Type SwXTextFrame::getElementType(void) throw( uno::RuntimeException )
+{
+ return ::getCppuType(static_cast<uno::Reference<text::XTextRange>*>(0));
+}
+
+sal_Bool SwXTextFrame::hasElements(void) throw( uno::RuntimeException )
+{
+ return sal_True;
+}
+
+void SwXTextFrame::attach(const uno::Reference< text::XTextRange > & xTextRange)
+ throw( lang::IllegalArgumentException, uno::RuntimeException )
+{
+ SwXFrame::attach(xTextRange);
+}
+
+uno::Reference< text::XTextRange > SwXTextFrame::getAnchor(void) throw( uno::RuntimeException )
+{
+ SolarMutexGuard aGuard;
+ return SwXFrame::getAnchor();
+}
+
+void SwXTextFrame::dispose(void) throw( uno::RuntimeException )
+{
+ SolarMutexGuard aGuard;
+ SwXFrame::dispose();
+}
+
+void SwXTextFrame::addEventListener(const uno::Reference< lang::XEventListener > & aListener) throw( uno::RuntimeException )
+{
+ SwXFrame::addEventListener(aListener);
+}
+
+void SwXTextFrame::removeEventListener(const uno::Reference< lang::XEventListener > & aListener) throw( uno::RuntimeException )
+{
+ SwXFrame::removeEventListener(aListener);
+}
+
+OUString SwXTextFrame::getImplementationName(void) throw( uno::RuntimeException )
+{
+ return C2U("SwXTextFrame");
+}
+
+sal_Bool SwXTextFrame::supportsService(const OUString& rServiceName) throw( uno::RuntimeException )
+{
+ return COMPARE_EQUAL == rServiceName.compareToAscii("com.sun.star.text.Text")||
+ COMPARE_EQUAL == rServiceName.compareToAscii("com.sun.star.text.TextFrame")||
+ SwXFrame::supportsService(rServiceName);
+}
+
+uno::Sequence< OUString > SwXTextFrame::getSupportedServiceNames(void) throw( uno::RuntimeException )
+{
+ uno::Sequence < OUString > aRet = SwXFrame::getSupportedServiceNames();
+ aRet.realloc(aRet.getLength() + 2);
+ OUString* pArray = aRet.getArray();
+ pArray[aRet.getLength() - 2] = C2U("com.sun.star.text.TextFrame");
+ pArray[aRet.getLength() - 1] = C2U("com.sun.star.text.Text");
+ return aRet;
+}
+
+void * SAL_CALL SwXTextFrame::operator new( size_t t) throw()
+{
+ return SwXTextFrameBaseClass::operator new( t);
+}
+
+void SAL_CALL SwXTextFrame::operator delete( void * p) throw()
+{
+ SwXTextFrameBaseClass::operator delete(p);
+}
+
+uno::Reference<container::XNameReplace > SAL_CALL SwXTextFrame::getEvents()
+ throw(uno::RuntimeException)
+{
+ return new SwFrameEventDescriptor( *this );
+}
+
+sal_Int64 SAL_CALL SwXTextFrame::getSomething( const uno::Sequence< sal_Int8 >& rId )
+ throw(uno::RuntimeException)
+{
+ sal_Int64 nRet = SwXFrame::getSomething( rId );
+ if( !nRet )
+ nRet = SwXText::getSomething( rId );
+
+ return nRet;
+}
+
+::uno::Any SwXTextFrame::getPropertyValue(const OUString& rPropertyName)
+ throw( beans::UnknownPropertyException, lang::WrappedTargetException, uno::RuntimeException )
+{
+ SolarMutexGuard aGuard;
+ ::uno::Any aRet;
+ if(rPropertyName.equalsAsciiL(SW_PROP_NAME(UNO_NAME_START_REDLINE))||
+ rPropertyName.equalsAsciiL(SW_PROP_NAME(UNO_NAME_END_REDLINE)))
+ {
+ //redline can only be returned if it's a living object
+ if(!IsDescriptor())
+ aRet = SwXText::getPropertyValue(rPropertyName);
+ }
+ else
+ aRet = SwXFrame::getPropertyValue(rPropertyName);
+ return aRet;
+}
+
+/******************************************************************
+ * SwXTextGraphicObject
+ ******************************************************************/
+SwXTextGraphicObject::SwXTextGraphicObject( SwDoc *pDoc ) :
+ SwXFrame(FLYCNTTYPE_GRF, aSwMapProvider.GetPropertySet(PROPERTY_MAP_TEXT_GRAPHIC), pDoc)
+{
+}
+
+SwXTextGraphicObject::SwXTextGraphicObject(SwFrmFmt& rFmt) :
+ SwXFrame(rFmt, FLYCNTTYPE_GRF, aSwMapProvider.GetPropertySet(PROPERTY_MAP_TEXT_GRAPHIC))
+{
+
+}
+
+SwXTextGraphicObject::~SwXTextGraphicObject()
+{
+
+}
+
+void SAL_CALL SwXTextGraphicObject::acquire( )throw()
+{
+ SwXFrame::acquire();
+}
+
+void SAL_CALL SwXTextGraphicObject::release( )throw()
+{
+ SwXFrame::release();
+}
+
+::uno::Any SAL_CALL SwXTextGraphicObject::queryInterface( const uno::Type& aType )
+ throw(uno::RuntimeException)
+{
+ ::uno::Any aRet = SwXFrame::queryInterface(aType);
+ if(aRet.getValueType() == ::getCppuVoidType())
+ aRet = SwXTextGraphicObjectBaseClass::queryInterface(aType);
+ return aRet;
+}
+
+uno::Sequence< uno::Type > SAL_CALL
+ SwXTextGraphicObject::getTypes( ) throw(uno::RuntimeException)
+{
+ uno::Sequence< uno::Type > aGraphicTypes = SwXTextGraphicObjectBaseClass::getTypes();
+ uno::Sequence< uno::Type > aFrameTypes = SwXFrame::getTypes();
+
+ long nIndex = aGraphicTypes.getLength();
+ aGraphicTypes.realloc(
+ aGraphicTypes.getLength() +
+ aFrameTypes.getLength());
+
+ uno::Type* pGraphicTypes = aGraphicTypes.getArray();
+ const uno::Type* pFrameTypes = aFrameTypes.getConstArray();
+ long nPos;
+ for(nPos = 0; nPos <aFrameTypes.getLength(); nPos++)
+ pGraphicTypes[nIndex++] = pFrameTypes[nPos];
+
+ return aGraphicTypes;
+}
+
+uno::Sequence< sal_Int8 > SAL_CALL SwXTextGraphicObject::getImplementationId( ) throw(uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+ static uno::Sequence< sal_Int8 > aId( 16 );
+ static bool bInit = false;
+ if(!bInit)
+ {
+ rtl_createUuid((sal_uInt8 *)(aId.getArray() ), 0, true);
+ bInit = true;
+ }
+ return aId;
+}
+
+void SwXTextGraphicObject::attach(const uno::Reference< text::XTextRange > & xTextRange) throw( lang::IllegalArgumentException, uno::RuntimeException )
+{
+ SwXFrame::attach(xTextRange);
+}
+
+uno::Reference< text::XTextRange > SwXTextGraphicObject::getAnchor(void) throw( uno::RuntimeException )
+{
+ SolarMutexGuard aGuard;
+ return SwXFrame::getAnchor();
+}
+
+void SwXTextGraphicObject::dispose(void) throw( uno::RuntimeException )
+{
+ SolarMutexGuard aGuard;
+ SwXFrame::dispose();
+}
+
+void SwXTextGraphicObject::addEventListener(const uno::Reference< lang::XEventListener > & aListener)
+ throw( uno::RuntimeException )
+{
+ SwXFrame::addEventListener(aListener);
+}
+
+void SwXTextGraphicObject::removeEventListener(const uno::Reference< lang::XEventListener > & aListener)
+ throw( uno::RuntimeException )
+{
+ SwXFrame::removeEventListener(aListener);
+}
+
+OUString SwXTextGraphicObject::getImplementationName(void) throw( uno::RuntimeException )
+{
+ return C2U("SwXTextGraphicObject");
+}
+
+sal_Bool SwXTextGraphicObject::supportsService(const OUString& rServiceName) throw( uno::RuntimeException )
+{
+ return COMPARE_EQUAL == rServiceName.compareToAscii("com.sun.star.text.TextGraphicObject") ||
+ SwXFrame::supportsService(rServiceName);
+}
+
+uno::Sequence< OUString > SwXTextGraphicObject::getSupportedServiceNames(void)
+ throw( uno::RuntimeException )
+{
+ uno::Sequence < OUString > aRet = SwXFrame::getSupportedServiceNames();
+ aRet.realloc(aRet.getLength() + 1);
+ OUString* pArray = aRet.getArray();
+ pArray[aRet.getLength() - 1] = C2U("com.sun.star.text.TextGraphicObject");
+ return aRet;
+}
+
+void * SAL_CALL SwXTextGraphicObject::operator new( size_t t) throw()
+{
+ return SwXTextGraphicObjectBaseClass::operator new(t);
+}
+
+void SAL_CALL SwXTextGraphicObject::operator delete( void * p) throw()
+{
+ SwXTextGraphicObjectBaseClass::operator delete(p);
+}
+
+uno::Reference<container::XNameReplace> SAL_CALL
+ SwXTextGraphicObject::getEvents()
+ throw(uno::RuntimeException)
+{
+ return new SwFrameEventDescriptor( *this );
+}
+
+SwXTextEmbeddedObject::SwXTextEmbeddedObject( SwDoc *pDoc ) :
+ SwXFrame(FLYCNTTYPE_OLE, aSwMapProvider.GetPropertySet(PROPERTY_MAP_EMBEDDED_OBJECT), pDoc)
+{
+}
+
+SwXTextEmbeddedObject::SwXTextEmbeddedObject(SwFrmFmt& rFmt) :
+ SwXFrame(rFmt, FLYCNTTYPE_OLE, aSwMapProvider.GetPropertySet(PROPERTY_MAP_EMBEDDED_OBJECT))
+{
+
+}
+
+SwXTextEmbeddedObject::~SwXTextEmbeddedObject()
+{
+
+}
+void SAL_CALL SwXTextEmbeddedObject::acquire()throw()
+{
+ SwXFrame::acquire();
+}
+
+void SAL_CALL SwXTextEmbeddedObject::release()throw()
+{
+ SwXFrame::release();
+}
+
+::uno::Any SAL_CALL SwXTextEmbeddedObject::queryInterface( const uno::Type& aType )
+ throw( uno::RuntimeException)
+{
+ ::uno::Any aRet = SwXFrame::queryInterface(aType);;
+ if(aRet.getValueType() == ::getCppuVoidType())
+ aRet = SwXTextEmbeddedObjectBaseClass::queryInterface(aType);
+ return aRet;
+}
+
+uno::Sequence< uno::Type > SAL_CALL SwXTextEmbeddedObject::getTypes( ) throw(uno::RuntimeException)
+{
+ uno::Sequence< uno::Type > aTextEmbeddedTypes = SwXTextEmbeddedObjectBaseClass::getTypes();
+ uno::Sequence< uno::Type > aFrameTypes = SwXFrame::getTypes();
+
+ long nIndex = aTextEmbeddedTypes.getLength();
+ aTextEmbeddedTypes.realloc(
+ aTextEmbeddedTypes.getLength() +
+ aFrameTypes.getLength());
+
+ uno::Type* pTextEmbeddedTypes = aTextEmbeddedTypes.getArray();
+
+ const uno::Type* pFrameTypes = aFrameTypes.getConstArray();
+ long nPos;
+ for(nPos = 0; nPos <aFrameTypes.getLength(); nPos++)
+ pTextEmbeddedTypes[nIndex++] = pFrameTypes[nPos];
+
+ return aTextEmbeddedTypes;
+}
+
+uno::Sequence< sal_Int8 > SAL_CALL SwXTextEmbeddedObject::getImplementationId( ) throw(uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+ static uno::Sequence< sal_Int8 > aId( 16 );
+ static bool bInit = false;
+ if(!bInit)
+ {
+ rtl_createUuid((sal_uInt8 *)(aId.getArray() ), 0, true);
+ bInit = true;
+ }
+ return aId;
+}
+
+void SwXTextEmbeddedObject::attach(const uno::Reference< text::XTextRange > & xTextRange) throw( lang::IllegalArgumentException, uno::RuntimeException )
+{
+ SwXFrame::attach(xTextRange);
+}
+
+uno::Reference< text::XTextRange > SwXTextEmbeddedObject::getAnchor(void) throw( uno::RuntimeException )
+{
+ SolarMutexGuard aGuard;
+ return SwXFrame::getAnchor();
+}
+
+void SwXTextEmbeddedObject::dispose(void) throw( uno::RuntimeException )
+{
+ SolarMutexGuard aGuard;
+ SwXFrame::dispose();
+}
+
+void SwXTextEmbeddedObject::addEventListener(const uno::Reference< lang::XEventListener > & aListener) throw( uno::RuntimeException )
+{
+ SwXFrame::addEventListener(aListener);
+}
+
+void SwXTextEmbeddedObject::removeEventListener(const uno::Reference< lang::XEventListener > & aListener) throw( uno::RuntimeException )
+{
+ SwXFrame::removeEventListener(aListener);
+}
+
+uno::Reference< lang::XComponent > SwXTextEmbeddedObject::getEmbeddedObject(void) throw( uno::RuntimeException )
+{
+ uno::Reference< lang::XComponent > xRet;
+ SwFrmFmt* pFmt = GetFrmFmt();
+ if(pFmt)
+ {
+ SwDoc* pDoc = pFmt->GetDoc();
+ const SwFmtCntnt* pCnt = &pFmt->GetCntnt();
+ DBG_ASSERT( pCnt->GetCntntIdx() &&
+ pDoc->GetNodes()[ pCnt->GetCntntIdx()->
+ GetIndex() + 1 ]->GetOLENode(), "kein OLE-Node?");
+
+ SwOLENode* pOleNode = pDoc->GetNodes()[ pCnt->GetCntntIdx()
+ ->GetIndex() + 1 ]->GetOLENode();
+ uno::Reference < embed::XEmbeddedObject > xIP = pOleNode->GetOLEObj().GetOleRef();
+ if ( svt::EmbeddedObjectRef::TryRunningState( xIP ) )
+ {
+ // TODO/LATER: the listener registered after client creation should be able to handle scaling, after that the client is not necessary here
+ if ( pDoc->GetDocShell() )
+ pDoc->GetDocShell()->GetIPClient( svt::EmbeddedObjectRef( xIP, embed::Aspects::MSOLE_CONTENT ) );
+
+ xRet = uno::Reference < lang::XComponent >( xIP->getComponent(), uno::UNO_QUERY );
+ uno::Reference< util::XModifyBroadcaster > xBrdcst( xRet, uno::UNO_QUERY);
+ uno::Reference< frame::XModel > xModel( xRet, uno::UNO_QUERY);
+ if( xBrdcst.is() && xModel.is() )
+ {
+ SwXOLEListener* pListener = SwIterator<SwXOLEListener,SwFmt>::FirstElement( *pFmt );
+ //create a new one if the OLE object doesn't have one already
+ if( !pListener )
+ {
+ uno::Reference< util::XModifyListener > xOLEListener = new SwXOLEListener(*pFmt, xModel);
+ xBrdcst->addModifyListener( xOLEListener );
+ }
+ }
+ }
+ }
+ return xRet;
+}
+
+uno::Reference< embed::XEmbeddedObject > SAL_CALL SwXTextEmbeddedObject::getExtendedControlOverEmbeddedObject()
+ throw( uno::RuntimeException )
+{
+ uno::Reference< embed::XEmbeddedObject > xResult;
+ SwFrmFmt* pFmt = GetFrmFmt();
+ if(pFmt)
+ {
+ SwDoc* pDoc = pFmt->GetDoc();
+ const SwFmtCntnt* pCnt = &pFmt->GetCntnt();
+ DBG_ASSERT( pCnt->GetCntntIdx() &&
+ pDoc->GetNodes()[ pCnt->GetCntntIdx()->
+ GetIndex() + 1 ]->GetOLENode(), "kein OLE-Node?");
+
+ SwOLENode* pOleNode = pDoc->GetNodes()[ pCnt->GetCntntIdx()
+ ->GetIndex() + 1 ]->GetOLENode();
+ xResult = pOleNode->GetOLEObj().GetOleRef();
+ if ( svt::EmbeddedObjectRef::TryRunningState( xResult ) )
+ {
+ // TODO/LATER: the listener registered after client creation should be able to handle scaling, after that the client is not necessary here
+ if ( pDoc->GetDocShell() )
+ pDoc->GetDocShell()->GetIPClient( svt::EmbeddedObjectRef( xResult, embed::Aspects::MSOLE_CONTENT ) );
+
+ uno::Reference < lang::XComponent > xComp( xResult->getComponent(), uno::UNO_QUERY );
+ uno::Reference< util::XModifyBroadcaster > xBrdcst( xComp, uno::UNO_QUERY);
+ uno::Reference< frame::XModel > xModel( xComp, uno::UNO_QUERY);
+ if( xBrdcst.is() && xModel.is() )
+ {
+ SwXOLEListener* pListener = SwIterator<SwXOLEListener,SwFmt>::FirstElement( *pFmt );
+ //create a new one if the OLE object doesn't have one already
+ if( !pListener )
+ {
+ uno::Reference< util::XModifyListener > xOLEListener = new SwXOLEListener(*pFmt, xModel);
+ xBrdcst->addModifyListener( xOLEListener );
+ }
+ }
+ }
+ }
+ return xResult;
+}
+
+sal_Int64 SAL_CALL SwXTextEmbeddedObject::getAspect() throw (uno::RuntimeException)
+{
+ SwFrmFmt* pFmt = GetFrmFmt();
+ if(pFmt)
+ {
+ SwDoc* pDoc = pFmt->GetDoc();
+ const SwFmtCntnt* pCnt = &pFmt->GetCntnt();
+ DBG_ASSERT( pCnt->GetCntntIdx() &&
+ pDoc->GetNodes()[ pCnt->GetCntntIdx()->
+ GetIndex() + 1 ]->GetOLENode(), "kein OLE-Node?");
+
+ return pDoc->GetNodes()[ pCnt->GetCntntIdx()->GetIndex() + 1 ]->GetOLENode()->GetAspect();
+ }
+
+ return embed::Aspects::MSOLE_CONTENT; // return the default value
+}
+
+void SAL_CALL SwXTextEmbeddedObject::setAspect( sal_Int64 nAspect ) throw (uno::RuntimeException)
+{
+ SwFrmFmt* pFmt = GetFrmFmt();
+ if(pFmt)
+ {
+ SwDoc* pDoc = pFmt->GetDoc();
+ const SwFmtCntnt* pCnt = &pFmt->GetCntnt();
+ DBG_ASSERT( pCnt->GetCntntIdx() &&
+ pDoc->GetNodes()[ pCnt->GetCntntIdx()->
+ GetIndex() + 1 ]->GetOLENode(), "kein OLE-Node?");
+
+ pDoc->GetNodes()[ pCnt->GetCntntIdx()->GetIndex() + 1 ]->GetOLENode()->SetAspect( nAspect );
+ }
+}
+
+uno::Reference< graphic::XGraphic > SAL_CALL SwXTextEmbeddedObject::getReplacementGraphic() throw (uno::RuntimeException)
+{
+ SwFrmFmt* pFmt = GetFrmFmt();
+ if(pFmt)
+ {
+ SwDoc* pDoc = pFmt->GetDoc();
+ const SwFmtCntnt* pCnt = &pFmt->GetCntnt();
+ DBG_ASSERT( pCnt->GetCntntIdx() &&
+ pDoc->GetNodes()[ pCnt->GetCntntIdx()->
+ GetIndex() + 1 ]->GetOLENode(), "kein OLE-Node?");
+
+ Graphic* pGraphic = pDoc->GetNodes()[ pCnt->GetCntntIdx()->GetIndex() + 1 ]->GetOLENode()->GetGraphic();
+ if ( pGraphic )
+ return pGraphic->GetXGraphic();
+ }
+
+ return uno::Reference< graphic::XGraphic >();
+}
+
+
+OUString SwXTextEmbeddedObject::getImplementationName(void) throw( uno::RuntimeException )
+
+{
+ return C2U("SwXTextEmbeddedObject");
+}
+
+sal_Bool SwXTextEmbeddedObject::supportsService(const OUString& rServiceName) throw( uno::RuntimeException )
+{
+ return COMPARE_EQUAL == rServiceName.compareToAscii("com.sun.star.text.TextEmbeddedObject")||
+ SwXFrame::supportsService(rServiceName);
+}
+
+uno::Sequence< OUString > SwXTextEmbeddedObject::getSupportedServiceNames(void)
+ throw( uno::RuntimeException )
+{
+ uno::Sequence < OUString > aRet = SwXFrame::getSupportedServiceNames();
+ aRet.realloc(aRet.getLength() + 1);
+ OUString* pArray = aRet.getArray();
+ pArray[aRet.getLength() - 1] = C2U("com.sun.star.text.TextEmbeddedObject");
+ return aRet;
+}
+
+void * SAL_CALL SwXTextEmbeddedObject::operator new( size_t t) throw()
+{
+ return SwXTextEmbeddedObjectBaseClass::operator new(t);
+}
+
+void SAL_CALL SwXTextEmbeddedObject::operator delete( void * p) throw()
+{
+ SwXTextEmbeddedObjectBaseClass::operator delete(p);
+}
+
+uno::Reference<container::XNameReplace> SAL_CALL
+ SwXTextEmbeddedObject::getEvents()
+ throw(uno::RuntimeException)
+{
+ return new SwFrameEventDescriptor( *this );
+}
+
+TYPEINIT1(SwXOLEListener, SwClient);
+
+SwXOLEListener::SwXOLEListener( SwFmt& rOLEFmt, uno::Reference< XModel > xOLE) :
+ SwClient(&rOLEFmt),
+ xOLEModel(xOLE)
+{
+}
+
+SwXOLEListener::~SwXOLEListener()
+{}
+
+void SwXOLEListener::modified( const lang::EventObject& /*rEvent*/ )
+ throw( uno::RuntimeException )
+{
+ SolarMutexGuard aGuard;
+
+ SwOLENode* pNd = 0;
+ SwFmt* pFmt = GetFmt();
+ if(pFmt)
+ {const SwNodeIndex* pIdx = pFmt->GetCntnt().GetCntntIdx();
+ if(pIdx)
+ {
+ SwNodeIndex aIdx(*pIdx, 1);
+ SwNoTxtNode* pNoTxt = aIdx.GetNode().GetNoTxtNode();
+ pNd = pNoTxt->GetOLENode();
+ }
+ }
+ if(!pNd)
+ throw uno::RuntimeException();
+
+ uno::Reference < embed::XEmbeddedObject > xIP = pNd->GetOLEObj().GetOleRef();
+ if ( xIP.is() )
+ {
+ sal_Int32 nState = xIP->getCurrentState();
+ if ( nState == embed::EmbedStates::INPLACE_ACTIVE || nState == embed::EmbedStates::UI_ACTIVE )
+ return;
+ }
+
+ // if the OLE-Node is UI-Active do nothing
+ pNd->SetOLESizeInvalid(true);
+ pNd->GetDoc()->SetOLEObjModified();
+}
+
+void SwXOLEListener::disposing( const lang::EventObject& rEvent )
+ throw( uno::RuntimeException )
+{
+ SolarMutexGuard aGuard;
+
+ uno::Reference< util::XModifyListener > xListener( this );
+
+
+ uno::Reference< frame::XModel > xModel( rEvent.Source, uno::UNO_QUERY );
+ uno::Reference< util::XModifyBroadcaster > xBrdcst(xModel, uno::UNO_QUERY);
+
+ try
+ {
+ if( xBrdcst.is() )
+ xBrdcst->removeModifyListener( xListener );
+ }
+ catch(uno::Exception const &)
+ {
+ OSL_FAIL("OLE Listener couldn't be removed");
+ }
+}
+
+void SwXOLEListener::Modify( const SfxPoolItem* pOld, const SfxPoolItem* pNew )
+{
+ ClientModify(this, pOld, pNew);
+ if(!GetRegisteredIn())
+ xOLEModel = 0;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/unocore/unoftn.cxx b/sw/source/core/unocore/unoftn.cxx
new file mode 100644
index 000000000000..529530932cb7
--- /dev/null
+++ b/sw/source/core/unocore/unoftn.cxx
@@ -0,0 +1,634 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+#include <rtl/uuid.h>
+
+#include <osl/mutex.hxx>
+#include <vcl/svapp.hxx>
+#include <comphelper/sequence.hxx>
+
+#include <unomid.h>
+#include <unofootnote.hxx>
+#include <unotextrange.hxx>
+#include <unotextcursor.hxx>
+#include <unoparagraph.hxx>
+#include <unomap.hxx>
+#include <unoprnms.hxx>
+#include <unoevtlstnr.hxx>
+#include <doc.hxx>
+#include <ftnidx.hxx>
+#include <fmtftn.hxx>
+#include <txtftn.hxx>
+#include <ndtxt.hxx>
+#include <unocrsr.hxx>
+#include <hints.hxx>
+
+
+using namespace ::com::sun::star;
+using ::rtl::OUString;
+
+/******************************************************************
+ * SwXFootnote
+ ******************************************************************/
+class SwXFootnote::Impl
+ : public SwClient
+{
+
+public:
+
+ SwXFootnote & m_rThis;
+ const bool m_bIsEndnote;
+ SwEventListenerContainer m_ListenerContainer;
+ bool m_bIsDescriptor;
+ const SwFmtFtn * m_pFmtFtn;
+ ::rtl::OUString m_sLabel;
+
+ Impl( SwXFootnote & rThis,
+ SwDoc *const pDoc, SwFmtFtn const*const pFootnote,
+ const bool bIsEndnote)
+ : SwClient((pDoc) ? pDoc->GetUnoCallBack() : 0)
+ , m_rThis(rThis)
+ , m_bIsEndnote(bIsEndnote)
+ , m_ListenerContainer(static_cast< ::cppu::OWeakObject* >(&rThis))
+// #i111177#: unxsols4 (Sun C++ 5.9 SunOS_sparc) generates wrong code for this
+// , m_bIsDescriptor(0 == pFootnote)
+ , m_bIsDescriptor((0 == pFootnote) ? true : false)
+ , m_pFmtFtn(pFootnote)
+ {
+ }
+
+ const SwFmtFtn* GetFootnoteFormat() const {
+ return m_rThis.GetDoc() ? m_pFmtFtn : 0;
+ }
+
+ SwFmtFtn const& GetFootnoteFormatOrThrow() {
+ SwFmtFtn const*const pFootnote( GetFootnoteFormat() );
+ if (!pFootnote) {
+ throw uno::RuntimeException(OUString(RTL_CONSTASCII_USTRINGPARAM(
+ "SwXFootnote: disposed or invalid")), 0);
+ }
+ return *pFootnote;
+ }
+
+ void Invalidate();
+protected:
+ // SwClient
+ virtual void Modify( const SfxPoolItem *pOld, const SfxPoolItem *pNew);
+
+};
+
+void SwXFootnote::Impl::Invalidate()
+{
+ if (GetRegisteredIn())
+ {
+ const_cast<SwModify*>(GetRegisteredIn())->Remove(this);
+ }
+ m_ListenerContainer.Disposing();
+ m_pFmtFtn = 0;
+ m_rThis.SetDoc(0);
+}
+
+void SwXFootnote::Impl::Modify(const SfxPoolItem *pOld, const SfxPoolItem *pNew)
+{
+ ClientModify(this, pOld, pNew);
+
+ if (!GetRegisteredIn()) // removed => dispose
+ {
+ Invalidate();
+ }
+ else if (pOld)
+ {
+ switch (pOld->Which())
+ {
+ case RES_FOOTNOTE_DELETED:
+ if (static_cast<const void*>(m_pFmtFtn) ==
+ static_cast<const SwPtrMsgPoolItem *>(pOld)->pObject)
+ {
+ Invalidate();
+ }
+ break;
+ }
+ }
+}
+
+SwXFootnote::SwXFootnote(const bool bEndnote)
+ : SwXText(0, CURSOR_FOOTNOTE)
+ , m_pImpl( new SwXFootnote::Impl(*this, 0, 0, bEndnote) )
+{
+}
+
+SwXFootnote::SwXFootnote(SwDoc & rDoc, const SwFmtFtn& rFmt)
+ : SwXText(& rDoc, CURSOR_FOOTNOTE)
+ , m_pImpl( new SwXFootnote::Impl(*this, &rDoc, &rFmt, rFmt.IsEndNote()) )
+{
+}
+
+SwXFootnote::~SwXFootnote()
+{
+}
+
+SwXFootnote *
+SwXFootnote::GetXFootnote(
+ SwModify const& /*rUnoCB*/, SwFmtFtn const& /*rFootnoteFmt*/)
+{
+ // re-use existing SwXFootnote
+ // #i105557#: do not iterate over the registered clients: race condition
+ // to do this properly requires the SwXFootnote to register at the
+ // SwFmtFtn directly, not at the unocallback
+ // also this function must return a uno Reference!
+ return 0;
+}
+
+SwXFootnote *
+SwXFootnote::CreateXFootnote(SwDoc & rDoc, SwFmtFtn const& rFootnoteFmt)
+{
+ SwXFootnote *const pXFootnote(
+ GetXFootnote(*rDoc.GetUnoCallBack(), rFootnoteFmt));
+ return (pXFootnote)
+ ? pXFootnote
+ : new SwXFootnote(rDoc, rFootnoteFmt);
+}
+
+const uno::Sequence< sal_Int8 > & SwXFootnote::getUnoTunnelId()
+{
+ static uno::Sequence< sal_Int8 > aSeq = ::CreateUnoTunnelId();
+ return aSeq;
+}
+
+sal_Int64 SAL_CALL
+SwXFootnote::getSomething(const uno::Sequence< sal_Int8 >& rId)
+throw (uno::RuntimeException)
+{
+ const sal_Int64 nRet( ::sw::UnoTunnelImpl<SwXFootnote>(rId, this) );
+ return (nRet) ? nRet : SwXText::getSomething(rId);
+}
+
+OUString SAL_CALL
+SwXFootnote::getImplementationName() throw (uno::RuntimeException)
+{
+ return C2U("SwXFootnote");
+}
+
+static char const*const g_ServicesFootnote[] =
+{
+ "com.sun.star.text.TextContent",
+ "com.sun.star.text.Footnote",
+ "com.sun.star.text.Text",
+ "com.sun.star.text.Endnote", // NB: only supported for endnotes!
+};
+
+static const size_t g_nServicesEndnote(
+ SAL_N_ELEMENTS(g_ServicesFootnote));
+
+static const size_t g_nServicesFootnote( g_nServicesEndnote - 1 ); // NB: omit!
+
+sal_Bool SAL_CALL SwXFootnote::supportsService(const OUString& rServiceName)
+throw (uno::RuntimeException)
+{
+ SolarMutexGuard g;
+ return ::sw::SupportsServiceImpl(
+ (m_pImpl->m_bIsEndnote) ? g_nServicesEndnote : g_nServicesFootnote,
+ g_ServicesFootnote, rServiceName);
+}
+
+uno::Sequence< OUString > SAL_CALL
+SwXFootnote::getSupportedServiceNames() throw (uno::RuntimeException)
+{
+ SolarMutexGuard g;
+ return ::sw::GetSupportedServiceNamesImpl(
+ (m_pImpl->m_bIsEndnote) ? g_nServicesEndnote : g_nServicesFootnote,
+ g_ServicesFootnote);
+}
+
+uno::Sequence< uno::Type > SAL_CALL
+SwXFootnote::getTypes() throw (uno::RuntimeException)
+{
+ const uno::Sequence< uno::Type > aTypes = SwXFootnote_Base::getTypes();
+ const uno::Sequence< uno::Type > aTextTypes = SwXText::getTypes();
+ return ::comphelper::concatSequences(aTypes, aTextTypes);
+}
+
+uno::Sequence< sal_Int8 > SAL_CALL
+SwXFootnote::getImplementationId() throw (uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+ static uno::Sequence< sal_Int8 > aId( 16 );
+ static sal_Bool bInit = sal_False;
+ if(!bInit)
+ {
+ rtl_createUuid( (sal_uInt8 *)(aId.getArray() ), 0, sal_True );
+ bInit = sal_True;
+ }
+ return aId;
+}
+
+uno::Any SAL_CALL
+SwXFootnote::queryInterface(const uno::Type& rType)
+throw (uno::RuntimeException)
+{
+ const uno::Any ret = SwXFootnote_Base::queryInterface(rType);
+ return (ret.getValueType() == ::getCppuVoidType())
+ ? SwXText::queryInterface(rType)
+ : ret;
+}
+
+OUString SAL_CALL SwXFootnote::getLabel() throw (uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+
+ ::rtl::OUString sRet;
+ SwFmtFtn const*const pFmt = m_pImpl->GetFootnoteFormat();
+ if(pFmt)
+ {
+ sRet = pFmt->GetNumStr();
+ }
+ else if (m_pImpl->m_bIsDescriptor)
+ {
+ sRet = m_pImpl->m_sLabel;
+ }
+ else
+ {
+ throw uno::RuntimeException();
+ }
+ return sRet;
+}
+
+void SAL_CALL
+SwXFootnote::setLabel(const OUString& aLabel) throw (uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+
+ SwFmtFtn const*const pFmt = m_pImpl->GetFootnoteFormat();
+ if(pFmt)
+ {
+ const SwTxtFtn* pTxtFtn = pFmt->GetTxtFtn();
+ DBG_ASSERT(pTxtFtn, "kein TextNode?");
+ SwTxtNode& rTxtNode = (SwTxtNode&)pTxtFtn->GetTxtNode();
+
+ SwPaM aPam(rTxtNode, *pTxtFtn->GetStart());
+ GetDoc()->SetCurFtn(aPam, aLabel, pFmt->GetNumber(), pFmt->IsEndNote());
+ }
+ else if (m_pImpl->m_bIsDescriptor)
+ {
+ m_pImpl->m_sLabel = String(aLabel);
+ }
+ else
+ {
+ throw uno::RuntimeException();
+ }
+}
+
+void SAL_CALL
+SwXFootnote::attach(const uno::Reference< text::XTextRange > & xTextRange)
+throw (lang::IllegalArgumentException, uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+
+ if (!m_pImpl->m_bIsDescriptor)
+ {
+ throw uno::RuntimeException();
+ }
+ const uno::Reference<lang::XUnoTunnel> xRangeTunnel(
+ xTextRange, uno::UNO_QUERY);
+ SwXTextRange *const pRange =
+ ::sw::UnoTunnelGetImplementation<SwXTextRange>(xRangeTunnel);
+ OTextCursorHelper *const pCursor =
+ ::sw::UnoTunnelGetImplementation<OTextCursorHelper>(xRangeTunnel);
+ SwDoc *const pNewDoc =
+ (pRange) ? pRange->GetDoc() : ((pCursor) ? pCursor->GetDoc() : 0);
+ if (!pNewDoc)
+ {
+ throw lang::IllegalArgumentException();
+ }
+
+ SwUnoInternalPaM aPam(*pNewDoc);
+ //das muss jetzt sal_True liefern
+ ::sw::XTextRangeToSwPaM(aPam, xTextRange);
+
+ UnoActionContext aCont(pNewDoc);
+ pNewDoc->DeleteAndJoin(aPam);
+ aPam.DeleteMark();
+ SwFmtFtn aFootNote(m_pImpl->m_bIsEndnote);
+ if (m_pImpl->m_sLabel.getLength())
+ {
+ aFootNote.SetNumStr(m_pImpl->m_sLabel);
+ }
+
+ SwXTextCursor const*const pTextCursor(
+ dynamic_cast<SwXTextCursor*>(pCursor));
+ const bool bForceExpandHints( (pTextCursor)
+ ? pTextCursor->IsAtEndOfMeta() : false );
+ const SetAttrMode nInsertFlags = (bForceExpandHints)
+ ? nsSetAttrMode::SETATTR_FORCEHINTEXPAND
+ : nsSetAttrMode::SETATTR_DEFAULT;
+
+ pNewDoc->InsertPoolItem(aPam, aFootNote, nInsertFlags);
+
+ SwTxtFtn *const pTxtAttr = static_cast<SwTxtFtn*>(
+ aPam.GetNode()->GetTxtNode()->GetTxtAttrForCharAt(
+ aPam.GetPoint()->nContent.GetIndex()-1, RES_TXTATR_FTN ));
+
+ if (pTxtAttr)
+ {
+ const SwFmtFtn& rFtn = pTxtAttr->GetFtn();
+ m_pImpl->m_pFmtFtn = &rFtn;
+ pNewDoc->GetUnoCallBack()->Add(m_pImpl.get());
+ // force creation of sequence id - is used for references
+ if (pNewDoc->IsInReading())
+ {
+ pTxtAttr->SetSeqNo(pNewDoc->GetFtnIdxs().Count());
+ }
+ else
+ {
+ pTxtAttr->SetSeqRefNo();
+ }
+ }
+ m_pImpl->m_bIsDescriptor = sal_False;
+ SetDoc(pNewDoc);
+}
+
+uno::Reference< text::XTextRange > SAL_CALL
+SwXFootnote::getAnchor() throw (uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+
+ SwFmtFtn const& rFmt( m_pImpl->GetFootnoteFormatOrThrow() );
+
+ SwTxtFtn const*const pTxtFtn = rFmt.GetTxtFtn();
+ SwPaM aPam( pTxtFtn->GetTxtNode(), *pTxtFtn->GetStart() );
+ SwPosition aMark( *aPam.Start() );
+ aPam.SetMark();
+ aPam.GetMark()->nContent++;
+ const uno::Reference< text::XTextRange > xRet =
+ SwXTextRange::CreateXTextRange(*GetDoc(), *aPam.Start(), aPam.End());
+ return xRet;
+}
+
+void SAL_CALL SwXFootnote::dispose() throw (uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+
+ SwFmtFtn const& rFmt( m_pImpl->GetFootnoteFormatOrThrow() );
+
+ SwTxtFtn const*const pTxtFtn = rFmt.GetTxtFtn();
+ DBG_ASSERT(pTxtFtn, "no TextNode?");
+ SwTxtNode& rTxtNode = const_cast<SwTxtNode&>(pTxtFtn->GetTxtNode());
+ const xub_StrLen nPos = *pTxtFtn->GetStart();
+ SwPaM aPam(rTxtNode, nPos, rTxtNode, nPos+1);
+ GetDoc()->DeleteAndJoin( aPam );
+}
+
+void SAL_CALL
+SwXFootnote::addEventListener(
+ const uno::Reference< lang::XEventListener > & xListener)
+throw (uno::RuntimeException)
+{
+ SolarMutexGuard g;
+
+ if (!m_pImpl->GetFootnoteFormat())
+ {
+ throw uno::RuntimeException();
+ }
+ m_pImpl->m_ListenerContainer.AddListener(xListener);
+}
+
+void SAL_CALL
+SwXFootnote::removeEventListener(
+ const uno::Reference< lang::XEventListener > & xListener)
+throw (uno::RuntimeException)
+{
+ SolarMutexGuard g;
+
+ if (!m_pImpl->GetFootnoteFormat() ||
+ !m_pImpl->m_ListenerContainer.RemoveListener(xListener))
+ {
+ throw uno::RuntimeException();
+ }
+}
+
+const SwStartNode *SwXFootnote::GetStartNode() const
+{
+ SwFmtFtn const*const pFmt = m_pImpl->GetFootnoteFormat();
+ if(pFmt)
+ {
+ const SwTxtFtn* pTxtFtn = pFmt->GetTxtFtn();
+ if( pTxtFtn )
+ {
+ return pTxtFtn->GetStartNode()->GetNode().GetStartNode();
+ }
+ }
+ return 0;
+}
+
+uno::Reference< text::XTextCursor >
+SwXFootnote::CreateCursor() throw (uno::RuntimeException)
+{
+ return createTextCursor();
+}
+
+uno::Reference< text::XTextCursor > SAL_CALL
+SwXFootnote::createTextCursor() throw (uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+
+ SwFmtFtn const& rFmt( m_pImpl->GetFootnoteFormatOrThrow() );
+
+ SwTxtFtn const*const pTxtFtn = rFmt.GetTxtFtn();
+ SwPosition aPos( *pTxtFtn->GetStartNode() );
+ SwXTextCursor *const pXCursor =
+ new SwXTextCursor(*GetDoc(), this, CURSOR_FOOTNOTE, aPos);
+ SwUnoCrsr *const pUnoCrsr = pXCursor->GetCursor();
+ pUnoCrsr->Move(fnMoveForward, fnGoNode);
+ const uno::Reference< text::XTextCursor > xRet =
+ static_cast<text::XWordCursor*>(pXCursor);
+ return xRet;
+}
+
+uno::Reference< text::XTextCursor > SAL_CALL
+SwXFootnote::createTextCursorByRange(
+ const uno::Reference< text::XTextRange > & xTextPosition)
+throw (uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+
+ SwFmtFtn const& rFmt( m_pImpl->GetFootnoteFormatOrThrow() );
+
+ SwUnoInternalPaM aPam(*GetDoc());
+ if (!::sw::XTextRangeToSwPaM(aPam, xTextPosition))
+ {
+ throw uno::RuntimeException();
+ }
+
+ SwTxtFtn const*const pTxtFtn = rFmt.GetTxtFtn();
+ SwNode const*const pFtnStartNode = &pTxtFtn->GetStartNode()->GetNode();
+
+ const SwNode* pStart = aPam.GetNode()->FindFootnoteStartNode();
+ if (pStart != pFtnStartNode)
+ {
+ throw uno::RuntimeException();
+ }
+
+ const uno::Reference< text::XTextCursor > xRet =
+ static_cast<text::XWordCursor*>(
+ new SwXTextCursor(*GetDoc(), this, CURSOR_FOOTNOTE,
+ *aPam.GetPoint(), aPam.GetMark()));
+ return xRet;
+}
+
+uno::Reference< container::XEnumeration > SAL_CALL
+SwXFootnote::createEnumeration() throw (uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+
+ SwFmtFtn const& rFmt( m_pImpl->GetFootnoteFormatOrThrow() );
+
+ SwTxtFtn const*const pTxtFtn = rFmt.GetTxtFtn();
+ SwPosition aPos( *pTxtFtn->GetStartNode() );
+ ::std::auto_ptr<SwUnoCrsr> pUnoCursor(
+ GetDoc()->CreateUnoCrsr(aPos, sal_False));
+ pUnoCursor->Move(fnMoveForward, fnGoNode);
+ const uno::Reference< container::XEnumeration > xRet =
+ new SwXParagraphEnumeration(this, pUnoCursor, CURSOR_FOOTNOTE);
+ return xRet;
+}
+
+uno::Type SAL_CALL SwXFootnote::getElementType() throw (uno::RuntimeException)
+{
+ return text::XTextRange::static_type();
+}
+
+sal_Bool SAL_CALL SwXFootnote::hasElements() throw (uno::RuntimeException)
+{
+ return sal_True;
+}
+
+uno::Reference< beans::XPropertySetInfo > SAL_CALL
+SwXFootnote::getPropertySetInfo()
+throw (uno::RuntimeException)
+{
+ SolarMutexGuard g;
+ static uno::Reference< beans::XPropertySetInfo > xRet =
+ aSwMapProvider.GetPropertySet(PROPERTY_MAP_FOOTNOTE)
+ ->getPropertySetInfo();
+ return xRet;
+}
+
+void SAL_CALL
+SwXFootnote::setPropertyValue(const ::rtl::OUString&, const uno::Any&)
+throw (beans::UnknownPropertyException, beans::PropertyVetoException,
+ lang::IllegalArgumentException, lang::WrappedTargetException,
+ uno::RuntimeException)
+{
+ //no values to be set
+ throw lang::IllegalArgumentException();
+}
+
+uno::Any SAL_CALL
+SwXFootnote::getPropertyValue(const OUString& rPropertyName)
+throw (beans::UnknownPropertyException, lang::WrappedTargetException,
+ uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+
+ uno::Any aRet;
+ if (! ::sw::GetDefaultTextContentValue(aRet, rPropertyName))
+ {
+ if (rPropertyName.equalsAsciiL(SW_PROP_NAME(UNO_NAME_START_REDLINE)) ||
+ rPropertyName.equalsAsciiL(SW_PROP_NAME(UNO_NAME_END_REDLINE)))
+ {
+ //redline can only be returned if it's a living object
+ if (!m_pImpl->m_bIsDescriptor)
+ {
+ aRet = SwXText::getPropertyValue(rPropertyName);
+ }
+ }
+ else if (rPropertyName.equalsAsciiL(
+ SW_PROP_NAME(UNO_NAME_REFERENCE_ID)))
+ {
+ SwFmtFtn const*const pFmt = m_pImpl->GetFootnoteFormat();
+ if (pFmt)
+ {
+ SwTxtFtn const*const pTxtFtn = pFmt->GetTxtFtn();
+ DBG_ASSERT(pTxtFtn, "no TextNode?");
+ aRet <<= static_cast<sal_Int16>(pTxtFtn->GetSeqRefNo());
+ }
+ }
+ else
+ {
+ beans::UnknownPropertyException aExcept;
+ aExcept.Message = rPropertyName;
+ throw aExcept;
+ }
+ }
+ return aRet;
+}
+
+void SAL_CALL
+SwXFootnote::addPropertyChangeListener(
+ const ::rtl::OUString& /*rPropertyName*/,
+ const uno::Reference< beans::XPropertyChangeListener >& /*xListener*/)
+throw (beans::UnknownPropertyException, lang::WrappedTargetException,
+ uno::RuntimeException)
+{
+ OSL_FAIL("SwXFootnote::addPropertyChangeListener(): not implemented");
+}
+
+void SAL_CALL
+SwXFootnote::removePropertyChangeListener(
+ const ::rtl::OUString& /*rPropertyName*/,
+ const uno::Reference< beans::XPropertyChangeListener >& /*xListener*/)
+throw (beans::UnknownPropertyException, lang::WrappedTargetException,
+ uno::RuntimeException)
+{
+ OSL_FAIL("SwXFootnote::removePropertyChangeListener(): not implemented");
+}
+
+void SAL_CALL
+SwXFootnote::addVetoableChangeListener(
+ const ::rtl::OUString& /*rPropertyName*/,
+ const uno::Reference< beans::XVetoableChangeListener >& /*xListener*/)
+throw (beans::UnknownPropertyException, lang::WrappedTargetException,
+ uno::RuntimeException)
+{
+ OSL_FAIL("SwXFootnote::addVetoableChangeListener(): not implemented");
+}
+
+void SAL_CALL
+SwXFootnote::removeVetoableChangeListener(
+ const ::rtl::OUString& /*rPropertyName*/,
+ const uno::Reference< beans::XVetoableChangeListener >& /*xListener*/)
+throw (beans::UnknownPropertyException, lang::WrappedTargetException,
+ uno::RuntimeException)
+{
+ OSL_FAIL("SwXFootnote::removeVetoableChangeListener(): not implemented");
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/unocore/unoidx.cxx b/sw/source/core/unocore/unoidx.cxx
new file mode 100644
index 000000000000..50524cfc788d
--- /dev/null
+++ b/sw/source/core/unocore/unoidx.cxx
@@ -0,0 +1,3223 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+#include <com/sun/star/beans/PropertyAttribute.hpp>
+#include <com/sun/star/container/XIndexReplace.hpp>
+#include <com/sun/star/frame/XModel.hpp>
+#include <com/sun/star/text/ChapterFormat.hpp>
+#include <com/sun/star/text/ReferenceFieldPart.hpp>
+#include <com/sun/star/text/BibliographyDataField.hpp>
+#include <com/sun/star/text/XTextDocument.hpp>
+
+#include <tools/debug.hxx>
+#include <osl/mutex.hxx>
+#include <vcl/svapp.hxx>
+#include <editeng/unolingu.hxx>
+#include <hints.hxx>
+#include <cmdid.h>
+#include <swtypes.hxx>
+#include <shellres.hxx>
+#include <viewsh.hxx>
+#include <doc.hxx>
+#include <docary.hxx>
+#include <poolfmt.hxx>
+#include <poolfmt.hrc>
+#include <pagedesc.hxx>
+#include <fmtcntnt.hxx>
+#include <unomap.hxx>
+#include <unotextrange.hxx>
+#include <unotextcursor.hxx>
+#include <unosection.hxx>
+#include <doctxm.hxx>
+#include <txttxmrk.hxx>
+#include <unocrsr.hxx>
+#include <unostyle.hxx>
+#include <ndtxt.hxx>
+#include <unoidx.hxx>
+#include <docsh.hxx>
+#include <chpfld.hxx>
+#include <SwStyleNameMapper.hxx>
+#include <unoevtlstnr.hxx>
+
+
+using namespace ::com::sun::star;
+using ::rtl::OUString;
+
+static OUString
+lcl_AnyToString(uno::Any const& rVal) throw (lang::IllegalArgumentException)
+{
+ OUString sRet;
+ if(!(rVal >>= sRet))
+ {
+ throw lang::IllegalArgumentException();
+ }
+ return sRet;
+}
+
+static sal_Int16
+lcl_AnyToInt16(uno::Any const& rVal) throw (lang::IllegalArgumentException)
+{
+ sal_Int16 nRet = 0;
+ if(!(rVal >>= nRet))
+ {
+ throw lang::IllegalArgumentException();
+ }
+ return nRet;
+}
+
+static sal_Bool
+lcl_AnyToBool(uno::Any const& rVal) throw (lang::IllegalArgumentException)
+{
+ sal_Bool bRet = sal_False;
+ if(!(rVal >>= bRet))
+ {
+ throw lang::IllegalArgumentException();
+ }
+ return bRet;
+}
+
+static void
+lcl_AnyToBitMask(uno::Any const& rValue,
+ sal_uInt16 & rBitMask, const sal_uInt16 nBit)
+throw (lang::IllegalArgumentException)
+{
+ rBitMask = lcl_AnyToBool(rValue)
+ ? (rBitMask | nBit)
+ : (rBitMask & ~nBit);
+}
+
+static void
+lcl_BitMaskToAny(uno::Any & o_rValue,
+ const sal_uInt16 nBitMask, const sal_uInt16 nBit)
+{
+ const sal_Bool bRet = 0 != (nBitMask & nBit);
+ o_rValue <<= bRet;
+}
+
+static void
+lcl_ReAssignTOXType(SwDoc* pDoc, SwTOXBase& rTOXBase, const OUString& rNewName)
+{
+ const sal_uInt16 nUserCount = pDoc->GetTOXTypeCount( TOX_USER );
+ const SwTOXType* pNewType = 0;
+ for(sal_uInt16 nUser = 0; nUser < nUserCount; nUser++)
+ {
+ const SwTOXType* pType = pDoc->GetTOXType( TOX_USER, nUser );
+ if(pType->GetTypeName().Equals((String)rNewName))
+ {
+ pNewType = pType;
+ break;
+ }
+ }
+ if(!pNewType)
+ {
+ SwTOXType aNewType(TOX_USER, rNewName);
+ pNewType = pDoc->InsertTOXType( aNewType );
+ }
+
+ rTOXBase.RegisterToTOXType( *((SwTOXType*)pNewType) );
+}
+
+static const char cUserDefined[] = "User-Defined";
+static const char cUserSuffix[] = " (user)";
+#define USER_LEN 12
+#define USER_AND_SUFFIXLEN 19
+
+void lcl_ConvertTOUNameToProgrammaticName(OUString& rTmp)
+{
+ ShellResource* pShellRes = ViewShell::GetShellRes();
+
+ if(rTmp.equals(pShellRes->aTOXUserName))
+ {
+ rTmp = OUString(C2U(cUserDefined));
+ }
+ // if the version is not English but the alternative index's name is
+ // "User-Defined" a " (user)" is appended
+ else if(rTmp.equalsAscii(cUserDefined))
+ {
+ rTmp += C2U(cUserSuffix);
+ }
+}
+
+static void
+lcl_ConvertTOUNameToUserName(OUString& rTmp)
+{
+ ShellResource* pShellRes = ViewShell::GetShellRes();
+ if(rTmp.equalsAscii(cUserDefined))
+ {
+ rTmp = pShellRes->aTOXUserName;
+ }
+ else if(!pShellRes->aTOXUserName.EqualsAscii(cUserDefined) &&
+ USER_AND_SUFFIXLEN == rTmp.getLength())
+ {
+ //make sure that in non-English versions the " (user)" suffix is removed
+ if (rTmp.matchAsciiL(cUserDefined, sizeof(cUserDefined)) &&
+ rTmp.matchAsciiL(cUserSuffix, sizeof(cUserSuffix), USER_LEN))
+ {
+ rTmp = C2U(cUserDefined);
+ }
+ }
+}
+
+typedef ::cppu::WeakImplHelper2
+< lang::XServiceInfo
+, container::XIndexReplace
+> SwXDocumentIndexStyleAccess_Base;
+
+class SwXDocumentIndex::StyleAccess_Impl
+ : public SwXDocumentIndexStyleAccess_Base
+{
+
+private:
+ /// can be destroyed threadsafely, so no UnoImplPtr here
+ ::rtl::Reference<SwXDocumentIndex> m_xParent;
+
+ virtual ~StyleAccess_Impl();
+
+public:
+ StyleAccess_Impl(SwXDocumentIndex& rParentIdx);
+
+ // XServiceInfo
+ virtual ::rtl::OUString SAL_CALL getImplementationName()
+ throw (uno::RuntimeException);
+ virtual sal_Bool SAL_CALL
+ supportsService(const ::rtl::OUString& rServiceName)
+ throw (uno::RuntimeException);
+ virtual uno::Sequence< ::rtl::OUString > SAL_CALL
+ getSupportedServiceNames() throw (uno::RuntimeException);
+
+ // XElementAccess
+ virtual uno::Type SAL_CALL getElementType() throw (uno::RuntimeException);
+ virtual sal_Bool SAL_CALL hasElements() throw (uno::RuntimeException);
+
+ // XIndexAccess
+ virtual sal_Int32 SAL_CALL getCount() throw (uno::RuntimeException);
+ virtual uno::Any SAL_CALL getByIndex(sal_Int32 nIndex)
+ throw (lang::IndexOutOfBoundsException, lang::WrappedTargetException,
+ uno::RuntimeException);
+
+ // XIndexReplace
+ virtual void SAL_CALL
+ replaceByIndex(sal_Int32 Index, const uno::Any& rElement)
+ throw (lang::IllegalArgumentException, lang::IndexOutOfBoundsException,
+ lang::WrappedTargetException, uno::RuntimeException);
+
+};
+
+typedef ::cppu::WeakImplHelper2
+< lang::XServiceInfo
+, container::XIndexReplace
+> SwXDocumentIndexTokenAccess_Base;
+
+class SwXDocumentIndex::TokenAccess_Impl
+ : public SwXDocumentIndexTokenAccess_Base
+{
+
+private:
+ /// can be destroyed threadsafely, so no UnoImplPtr here
+ ::rtl::Reference<SwXDocumentIndex> m_xParent;
+
+ virtual ~TokenAccess_Impl();
+
+public:
+
+ TokenAccess_Impl(SwXDocumentIndex& rParentIdx);
+
+ // XServiceInfo
+ virtual ::rtl::OUString SAL_CALL getImplementationName()
+ throw (uno::RuntimeException);
+ virtual sal_Bool SAL_CALL
+ supportsService(const ::rtl::OUString& rServiceName)
+ throw (uno::RuntimeException);
+ virtual uno::Sequence< ::rtl::OUString > SAL_CALL
+ getSupportedServiceNames() throw (uno::RuntimeException);
+
+ // XElementAccess
+ virtual uno::Type SAL_CALL getElementType() throw (uno::RuntimeException);
+ virtual sal_Bool SAL_CALL hasElements() throw (uno::RuntimeException);
+
+ // XIndexAccess
+ virtual sal_Int32 SAL_CALL getCount() throw (uno::RuntimeException);
+ virtual uno::Any SAL_CALL getByIndex(sal_Int32 nIndex)
+ throw (lang::IndexOutOfBoundsException, lang::WrappedTargetException,
+ uno::RuntimeException);
+
+ // XIndexReplace
+ virtual void SAL_CALL
+ replaceByIndex(sal_Int32 Index, const uno::Any& rElement)
+ throw (lang::IllegalArgumentException, lang::IndexOutOfBoundsException,
+ lang::WrappedTargetException, uno::RuntimeException);
+
+};
+
+/******************************************************************
+ * SwXDocumentIndex
+ ******************************************************************/
+class SwDocIndexDescriptorProperties_Impl
+{
+private:
+ ::std::auto_ptr<SwTOXBase> m_pTOXBase;
+ OUString m_sUserTOXTypeName;
+
+public:
+ SwDocIndexDescriptorProperties_Impl(SwTOXType const*const pType);
+
+ SwTOXBase & GetTOXBase() { return *m_pTOXBase; }
+ const OUString& GetTypeName() const { return m_sUserTOXTypeName; }
+ void SetTypeName(const OUString& rSet) { m_sUserTOXTypeName = rSet; }
+};
+
+SwDocIndexDescriptorProperties_Impl::SwDocIndexDescriptorProperties_Impl(
+ SwTOXType const*const pType)
+{
+ SwForm aForm(pType->GetType());
+ m_pTOXBase.reset(new SwTOXBase(pType, aForm,
+ nsSwTOXElement::TOX_MARK, pType->GetTypeName()));
+ if(pType->GetType() == TOX_CONTENT || pType->GetType() == TOX_USER)
+ {
+ m_pTOXBase->SetLevel(MAXLEVEL);
+ }
+ m_sUserTOXTypeName = pType->GetTypeName();
+}
+
+static sal_uInt16
+lcl_TypeToPropertyMap_Index(const TOXTypes eType)
+{
+ switch (eType)
+ {
+ case TOX_INDEX: return PROPERTY_MAP_INDEX_IDX;
+ case TOX_CONTENT: return PROPERTY_MAP_INDEX_CNTNT;
+ case TOX_TABLES: return PROPERTY_MAP_INDEX_TABLES;
+ case TOX_ILLUSTRATIONS: return PROPERTY_MAP_INDEX_ILLUSTRATIONS;
+ case TOX_OBJECTS: return PROPERTY_MAP_INDEX_OBJECTS;
+ case TOX_AUTHORITIES: return PROPERTY_MAP_BIBLIOGRAPHY;
+ //case TOX_USER:
+ default:
+ return PROPERTY_MAP_INDEX_USER;
+ }
+}
+
+class SwXDocumentIndex::Impl
+ : public SwClient
+{
+
+public:
+
+ SfxItemPropertySet const& m_rPropSet;
+ const TOXTypes m_eTOXType;
+ SwEventListenerContainer m_ListenerContainer;
+ bool m_bIsDescriptor;
+ SwDoc * m_pDoc;
+ ::std::auto_ptr<SwDocIndexDescriptorProperties_Impl> m_pProps;
+ uno::WeakReference<container::XIndexReplace> m_wStyleAccess;
+ uno::WeakReference<container::XIndexReplace> m_wTokenAccess;
+
+ Impl( SwXDocumentIndex & rThis,
+ SwDoc & rDoc,
+ const TOXTypes eType,
+ SwTOXBaseSection const*const pBaseSection)
+ : SwClient((pBaseSection) ? pBaseSection->GetFmt() : 0)
+ , m_rPropSet(
+ *aSwMapProvider.GetPropertySet(lcl_TypeToPropertyMap_Index(eType)))
+ , m_eTOXType(eType)
+ , m_ListenerContainer(static_cast< ::cppu::OWeakObject* >(&rThis))
+ // #i111177# unxsols4 (Sun C++ 5.9 SunOS_sparc) may generate wrong code
+ , m_bIsDescriptor((0 == pBaseSection) ? true : false)
+ , m_pDoc(&rDoc)
+ , m_pProps((m_bIsDescriptor)
+ ? new SwDocIndexDescriptorProperties_Impl(rDoc.GetTOXType(eType, 0))
+ : 0)
+ {
+ }
+
+ SwSectionFmt * GetSectionFmt() const {
+ return static_cast<SwSectionFmt *>(
+ const_cast<SwModify *>(GetRegisteredIn()));
+ }
+
+ SwTOXBase & GetTOXSectionOrThrow() const
+ {
+ SwSectionFmt *const pSectionFmt(GetSectionFmt());
+ SwTOXBase *const pTOXSection( (m_bIsDescriptor)
+ ? &m_pProps->GetTOXBase()
+ : ((pSectionFmt)
+ ? static_cast<SwTOXBaseSection*>(pSectionFmt->GetSection())
+ : 0));
+ if (!pTOXSection)
+ {
+ throw uno::RuntimeException(OUString(RTL_CONSTASCII_USTRINGPARAM(
+ "SwXDocumentIndex: disposed or invalid")), 0);
+ }
+ return *pTOXSection;
+ }
+
+ sal_Int32 GetFormMax() const
+ {
+ SwTOXBase & rSection( GetTOXSectionOrThrow() );
+ return (m_bIsDescriptor)
+ ? SwForm::GetFormMaxLevel(m_eTOXType)
+ : rSection.GetTOXForm().GetFormMax();
+ }
+protected:
+ // SwClient
+ virtual void Modify(const SfxPoolItem *pOld, const SfxPoolItem *pNew);
+
+};
+
+void SwXDocumentIndex::Impl::Modify(const SfxPoolItem *pOld, const SfxPoolItem *pNew)
+{
+ ClientModify(this, pOld, pNew);
+
+ if (!GetRegisteredIn())
+ {
+ m_ListenerContainer.Disposing();
+ }
+}
+
+SwXDocumentIndex::SwXDocumentIndex(
+ SwTOXBaseSection const& rBaseSection, SwDoc & rDoc)
+ : m_pImpl( new SwXDocumentIndex::Impl( *this,
+ rDoc, rBaseSection.SwTOXBase::GetType(), & rBaseSection) )
+{
+}
+
+SwXDocumentIndex::SwXDocumentIndex(const TOXTypes eType, SwDoc& rDoc)
+ : m_pImpl( new SwXDocumentIndex::Impl( *this, rDoc, eType, 0) )
+{
+}
+
+SwXDocumentIndex::~SwXDocumentIndex()
+{
+}
+
+uno::Reference<text::XDocumentIndex>
+SwXDocumentIndex::CreateXDocumentIndex(
+ SwDoc & rDoc, SwTOXBaseSection const& rSection)
+{
+ // re-use existing SwXDocumentIndex
+ // #i105557#: do not iterate over the registered clients: race condition
+ SwSectionFmt *const pFmt = rSection.GetFmt();
+ uno::Reference<text::XDocumentIndex> xIndex(pFmt->GetXObject(),
+ uno::UNO_QUERY);
+ if (!xIndex.is())
+ {
+ SwXDocumentIndex *const pIndex(new SwXDocumentIndex(rSection, rDoc));
+ xIndex.set(pIndex);
+ pFmt->SetXObject(uno::Reference<uno::XInterface>(xIndex));
+ }
+ return xIndex;
+}
+
+const uno::Sequence< sal_Int8 > & SwXDocumentIndex::getUnoTunnelId()
+{
+ static uno::Sequence< sal_Int8 > aSeq = ::CreateUnoTunnelId();
+ return aSeq;
+}
+
+sal_Int64 SAL_CALL
+SwXDocumentIndex::getSomething(const uno::Sequence< sal_Int8 >& rId)
+throw (uno::RuntimeException)
+{
+ return ::sw::UnoTunnelImpl<SwXDocumentIndex>(rId, this);
+}
+
+OUString SAL_CALL
+SwXDocumentIndex::getImplementationName() throw (uno::RuntimeException)
+{
+ return C2U("SwXDocumentIndex");
+}
+
+sal_Bool SAL_CALL
+SwXDocumentIndex::supportsService(const OUString& rServiceName)
+throw (uno::RuntimeException)
+{
+ SolarMutexGuard g;
+
+ return C2U("com.sun.star.text.BaseIndex") == rServiceName
+ || ((TOX_INDEX == m_pImpl->m_eTOXType) &&
+ rServiceName.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("com.sun.star.text.DocumentIndex")))
+ || ((TOX_CONTENT == m_pImpl->m_eTOXType) &&
+ rServiceName.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("com.sun.star.text.ContentIndex")))
+ || ((TOX_USER == m_pImpl->m_eTOXType) &&
+ rServiceName.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("com.sun.star.text.UserDefinedIndex")))
+ || ((TOX_ILLUSTRATIONS == m_pImpl->m_eTOXType) &&
+ rServiceName.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("com.sun.star.text.IllustrationsIndex")))
+ || ((TOX_TABLES == m_pImpl->m_eTOXType) &&
+ rServiceName.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("com.sun.star.text.TableIndex")))
+ || ((TOX_OBJECTS == m_pImpl->m_eTOXType) &&
+ rServiceName.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("com.sun.star.text.ObjectIndex")))
+ || ((TOX_AUTHORITIES == m_pImpl->m_eTOXType) &&
+ rServiceName.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("com.sun.star.text.Bibliography")));
+}
+
+uno::Sequence< OUString > SAL_CALL
+SwXDocumentIndex::getSupportedServiceNames() throw (uno::RuntimeException)
+{
+ SolarMutexGuard g;
+
+ uno::Sequence< OUString > aRet(2);
+ OUString* pArray = aRet.getArray();
+ pArray[0] = C2U("com.sun.star.text.BaseIndex");
+ switch (m_pImpl->m_eTOXType)
+ {
+ case TOX_INDEX:
+ pArray[1] = C2U("com.sun.star.text.DocumentIndex");
+ break;
+ case TOX_CONTENT:
+ pArray[1] = C2U("com.sun.star.text.ContentIndex");
+ break;
+ case TOX_TABLES:
+ pArray[1] = C2U("com.sun.star.text.TableIndex");
+ break;
+ case TOX_ILLUSTRATIONS:
+ pArray[1] = C2U("com.sun.star.text.IllustrationsIndex");
+ break;
+ case TOX_OBJECTS:
+ pArray[1] = C2U("com.sun.star.text.ObjectIndex");
+ break;
+ case TOX_AUTHORITIES:
+ pArray[1] = C2U("com.sun.star.text.Bibliography");
+ break;
+ //case TOX_USER:
+ default:
+ pArray[1] = C2U("com.sun.star.text.UserDefinedIndex");
+ }
+ return aRet;
+}
+
+OUString SAL_CALL SwXDocumentIndex::getServiceName()
+throw (uno::RuntimeException)
+{
+ SolarMutexGuard g;
+
+ sal_uInt16 nObjectType = SW_SERVICE_TYPE_INDEX;
+ switch (m_pImpl->m_eTOXType)
+ {
+// case TOX_INDEX: break;
+ case TOX_USER: nObjectType = SW_SERVICE_USER_INDEX;
+ break;
+ case TOX_CONTENT: nObjectType = SW_SERVICE_CONTENT_INDEX;
+ break;
+ case TOX_ILLUSTRATIONS: nObjectType = SW_SERVICE_INDEX_ILLUSTRATIONS;
+ break;
+ case TOX_OBJECTS: nObjectType = SW_SERVICE_INDEX_OBJECTS;
+ break;
+ case TOX_TABLES: nObjectType = SW_SERVICE_INDEX_TABLES;
+ break;
+ case TOX_AUTHORITIES: nObjectType = SW_SERVICE_INDEX_BIBLIOGRAPHY;
+ break;
+ default:
+ break;
+ }
+ return SwXServiceProvider::GetProviderName(nObjectType);
+}
+
+void SAL_CALL SwXDocumentIndex::update() throw (uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+
+ SwSectionFmt *const pFmt = m_pImpl->GetSectionFmt();
+ SwTOXBaseSection *const pTOXBase = (pFmt) ?
+ static_cast<SwTOXBaseSection*>(pFmt->GetSection()) : 0;
+ if(!pTOXBase)
+ {
+ throw uno::RuntimeException();
+ }
+ pTOXBase->Update();
+ // page numbers
+ pTOXBase->UpdatePageNum();
+}
+
+uno::Reference< beans::XPropertySetInfo > SAL_CALL
+SwXDocumentIndex::getPropertySetInfo() throw (uno::RuntimeException)
+{
+ SolarMutexGuard g;
+
+ const uno::Reference< beans::XPropertySetInfo > xRef =
+ m_pImpl->m_rPropSet.getPropertySetInfo();
+ return xRef;
+}
+
+void SAL_CALL
+SwXDocumentIndex::setPropertyValue(
+ const OUString& rPropertyName, const uno::Any& rValue)
+throw (beans::UnknownPropertyException, beans::PropertyVetoException,
+ lang::IllegalArgumentException, lang::WrappedTargetException,
+ uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+
+ SfxItemPropertySimpleEntry const*const pEntry =
+ m_pImpl->m_rPropSet.getPropertyMap()->getByName(rPropertyName);
+ if (!pEntry)
+ {
+ throw beans::UnknownPropertyException(
+ OUString(RTL_CONSTASCII_USTRINGPARAM("Unknown property: "))
+ + rPropertyName,
+ static_cast<cppu::OWeakObject *>(this));
+ }
+ if (pEntry->nFlags & beans::PropertyAttribute::READONLY)
+ {
+ throw beans::PropertyVetoException(
+ OUString(RTL_CONSTASCII_USTRINGPARAM("Property is read-only: " ))
+ + rPropertyName,
+ static_cast<cppu::OWeakObject *>(this));
+ }
+
+ SwSectionFmt *const pSectionFmt(m_pImpl->GetSectionFmt());
+ SwTOXBase & rTOXBase( m_pImpl->GetTOXSectionOrThrow() );
+
+ sal_uInt16 nCreate = rTOXBase.GetCreateType();
+ sal_uInt16 nTOIOptions = 0;
+ sal_uInt16 nOLEOptions = rTOXBase.GetOLEOptions();
+ const TOXTypes eTxBaseType = rTOXBase.GetTOXType()->GetType();
+ if (eTxBaseType == TOX_INDEX)
+ {
+ nTOIOptions = rTOXBase.GetOptions();
+ }
+ SwForm aForm(rTOXBase.GetTOXForm());
+ sal_Bool bForm = sal_False;
+ switch (pEntry->nWID)
+ {
+ case WID_IDX_TITLE:
+ {
+ OUString sNewName;
+ if (!(rValue >>= sNewName))
+ {
+ throw lang::IllegalArgumentException();
+ }
+ rTOXBase.SetTitle(sNewName);
+ }
+ break;
+ case WID_IDX_NAME:
+ {
+ OUString sNewName;
+ if (!(rValue >>= sNewName))
+ {
+ throw lang::IllegalArgumentException();
+ }
+ rTOXBase.SetTOXName(sNewName);
+ }
+ break;
+ case WID_USER_IDX_NAME:
+ {
+ OUString sNewName;
+ if (!(rValue >>= sNewName))
+ {
+ throw lang::IllegalArgumentException();
+ }
+ lcl_ConvertTOUNameToUserName(sNewName);
+ DBG_ASSERT(TOX_USER == eTxBaseType,
+ "tox type name can only be changed for user indexes");
+ if (pSectionFmt)
+ {
+ OUString sTmp = rTOXBase.GetTOXType()->GetTypeName();
+ if (sTmp != sNewName)
+ {
+ lcl_ReAssignTOXType(pSectionFmt->GetDoc(),
+ rTOXBase, sNewName);
+ }
+ }
+ else
+ {
+ m_pImpl->m_pProps->SetTypeName(sNewName);
+ }
+ }
+ break;
+ case WID_IDX_LOCALE:
+ {
+ lang::Locale aLocale;
+ if (!(rValue>>= aLocale))
+ {
+ throw lang::IllegalArgumentException();
+ }
+ rTOXBase.SetLanguage(SvxLocaleToLanguage(aLocale));
+ }
+ break;
+ case WID_IDX_SORT_ALGORITHM:
+ {
+ OUString sTmp;
+ if (!(rValue >>= sTmp))
+ {
+ throw lang::IllegalArgumentException();
+ }
+ rTOXBase.SetSortAlgorithm(sTmp);
+ }
+ break;
+ case WID_LEVEL:
+ {
+ rTOXBase.SetLevel(lcl_AnyToInt16(rValue));
+ }
+ break;
+ case WID_CREATE_FROM_MARKS:
+ lcl_AnyToBitMask(rValue, nCreate, nsSwTOXElement::TOX_MARK);
+ break;
+ case WID_CREATE_FROM_OUTLINE:
+ lcl_AnyToBitMask(rValue, nCreate, nsSwTOXElement::TOX_OUTLINELEVEL);
+ break;
+// case WID_PARAGRAPH_STYLE_NAMES :OSL_FAIL("not implemented")
+// break;
+ case WID_CREATE_FROM_CHAPTER:
+ rTOXBase.SetFromChapter(lcl_AnyToBool(rValue));
+ break;
+ case WID_CREATE_FROM_LABELS:
+ rTOXBase.SetFromObjectNames(! lcl_AnyToBool(rValue));
+ break;
+ case WID_PROTECTED:
+ {
+ sal_Bool bSet = lcl_AnyToBool(rValue);
+ rTOXBase.SetProtected(bSet);
+ if (pSectionFmt)
+ {
+ static_cast<SwTOXBaseSection &>(rTOXBase).SetProtect(bSet);
+ }
+ }
+ break;
+ case WID_USE_ALPHABETICAL_SEPARATORS:
+ lcl_AnyToBitMask(rValue, nTOIOptions,
+ nsSwTOIOptions::TOI_ALPHA_DELIMITTER);
+ break;
+ case WID_USE_KEY_AS_ENTRY:
+ lcl_AnyToBitMask(rValue, nTOIOptions,
+ nsSwTOIOptions::TOI_KEY_AS_ENTRY);
+ break;
+ case WID_USE_COMBINED_ENTRIES:
+ lcl_AnyToBitMask(rValue, nTOIOptions,
+ nsSwTOIOptions::TOI_SAME_ENTRY);
+ break;
+ case WID_IS_CASE_SENSITIVE:
+ lcl_AnyToBitMask(rValue, nTOIOptions,
+ nsSwTOIOptions::TOI_CASE_SENSITIVE);
+ break;
+ case WID_USE_P_P:
+ lcl_AnyToBitMask(rValue, nTOIOptions, nsSwTOIOptions::TOI_FF);
+ break;
+ case WID_USE_DASH:
+ lcl_AnyToBitMask(rValue, nTOIOptions, nsSwTOIOptions::TOI_DASH);
+ break;
+ case WID_USE_UPPER_CASE:
+ lcl_AnyToBitMask(rValue, nTOIOptions,
+ nsSwTOIOptions::TOI_INITIAL_CAPS);
+ break;
+ case WID_IS_COMMA_SEPARATED:
+ bForm = sal_True;
+ aForm.SetCommaSeparated(lcl_AnyToBool(rValue));
+ break;
+ case WID_LABEL_CATEGORY:
+ {
+ // convert file-format/API/external programmatic english name
+ // to internal UI name before usage
+ String aName( SwStyleNameMapper::GetSpecialExtraUIName(
+ lcl_AnyToString(rValue) ) );
+ rTOXBase.SetSequenceName( aName );
+ }
+ break;
+ case WID_LABEL_DISPLAY_TYPE:
+ {
+ const sal_Int16 nVal = lcl_AnyToInt16(rValue);
+ sal_uInt16 nSet = CAPTION_COMPLETE;
+ switch (nVal)
+ {
+ case text::ReferenceFieldPart::TEXT:
+ nSet = CAPTION_COMPLETE;
+ break;
+ case text::ReferenceFieldPart::CATEGORY_AND_NUMBER:
+ nSet = CAPTION_NUMBER;
+ break;
+ case text::ReferenceFieldPart::ONLY_CAPTION:
+ nSet = CAPTION_TEXT;
+ break;
+ default:
+ throw lang::IllegalArgumentException();
+ }
+ rTOXBase.SetCaptionDisplay(static_cast<SwCaptionDisplay>(nSet));
+ }
+ break;
+ case WID_USE_LEVEL_FROM_SOURCE:
+ rTOXBase.SetLevelFromChapter(lcl_AnyToBool(rValue));
+ break;
+ case WID_MAIN_ENTRY_CHARACTER_STYLE_NAME:
+ {
+ String aString;
+ SwStyleNameMapper::FillUIName(lcl_AnyToString(rValue),
+ aString, nsSwGetPoolIdFromName::GET_POOLID_CHRFMT, sal_True);
+ rTOXBase.SetMainEntryCharStyle( aString );
+ }
+ break;
+ case WID_CREATE_FROM_TABLES:
+ lcl_AnyToBitMask(rValue, nCreate, nsSwTOXElement::TOX_TABLE);
+ break;
+ case WID_CREATE_FROM_TEXT_FRAMES:
+ lcl_AnyToBitMask(rValue, nCreate, nsSwTOXElement::TOX_FRAME);
+ break;
+ case WID_CREATE_FROM_GRAPHIC_OBJECTS:
+ lcl_AnyToBitMask(rValue, nCreate, nsSwTOXElement::TOX_GRAPHIC);
+ break;
+ case WID_CREATE_FROM_EMBEDDED_OBJECTS:
+ lcl_AnyToBitMask(rValue, nCreate, nsSwTOXElement::TOX_OLE);
+ break;
+ case WID_CREATE_FROM_STAR_MATH:
+ lcl_AnyToBitMask(rValue, nOLEOptions, nsSwTOOElements::TOO_MATH);
+ break;
+ case WID_CREATE_FROM_STAR_CHART:
+ lcl_AnyToBitMask(rValue, nOLEOptions, nsSwTOOElements::TOO_CHART);
+ break;
+ case WID_CREATE_FROM_STAR_CALC:
+ lcl_AnyToBitMask(rValue, nOLEOptions, nsSwTOOElements::TOO_CALC);
+ break;
+ case WID_CREATE_FROM_STAR_DRAW:
+ lcl_AnyToBitMask(rValue, nOLEOptions,
+ nsSwTOOElements::TOO_DRAW_IMPRESS);
+ break;
+ case WID_CREATE_FROM_OTHER_EMBEDDED_OBJECTS:
+ lcl_AnyToBitMask(rValue, nOLEOptions, nsSwTOOElements::TOO_OTHER);
+ break;
+ case WID_PARA_HEAD:
+ {
+ String aString;
+ SwStyleNameMapper::FillUIName( lcl_AnyToString(rValue),
+ aString, nsSwGetPoolIdFromName::GET_POOLID_TXTCOLL, sal_True);
+ bForm = sal_True;
+ // Header is on Pos 0
+ aForm.SetTemplate( 0, aString );
+ }
+ break;
+ case WID_IS_RELATIVE_TABSTOPS:
+ bForm = sal_True;
+ aForm.SetRelTabPos(lcl_AnyToBool(rValue));
+ break;
+ case WID_PARA_SEP:
+ {
+ String aString;
+ bForm = sal_True;
+ SwStyleNameMapper::FillUIName( lcl_AnyToString(rValue),
+ aString, nsSwGetPoolIdFromName::GET_POOLID_TXTCOLL, sal_True);
+ aForm.SetTemplate( 1, aString );
+ }
+ break;
+ case WID_CREATE_FROM_PARAGRAPH_STYLES:
+ lcl_AnyToBitMask(rValue, nCreate, nsSwTOXElement::TOX_TEMPLATE);
+ break;
+
+ case WID_PARA_LEV1:
+ case WID_PARA_LEV2:
+ case WID_PARA_LEV3:
+ case WID_PARA_LEV4:
+ case WID_PARA_LEV5:
+ case WID_PARA_LEV6:
+ case WID_PARA_LEV7:
+ case WID_PARA_LEV8:
+ case WID_PARA_LEV9:
+ case WID_PARA_LEV10:
+ {
+ bForm = sal_True;
+ // in sdbcx::Index Label 1 begins at Pos 2 otherwise at Pos 1
+ const sal_uInt16 nLPos = rTOXBase.GetType() == TOX_INDEX ? 2 : 1;
+ String aString;
+ SwStyleNameMapper::FillUIName( lcl_AnyToString(rValue),
+ aString, nsSwGetPoolIdFromName::GET_POOLID_TXTCOLL, sal_True);
+ aForm.SetTemplate(nLPos + pEntry->nWID - WID_PARA_LEV1, aString );
+ }
+ break;
+ default:
+ //this is for items only
+ if (WID_PRIMARY_KEY > pEntry->nWID)
+ {
+ const SwAttrSet& rSet =
+ m_pImpl->m_pDoc->GetTOXBaseAttrSet(rTOXBase);
+ SfxItemSet aAttrSet(rSet);
+ m_pImpl->m_rPropSet.setPropertyValue(
+ rPropertyName, rValue, aAttrSet);
+
+ const SwSectionFmts& rSects = m_pImpl->m_pDoc->GetSections();
+ for (sal_uInt16 i = 0; i < rSects.Count(); i++)
+ {
+ const SwSectionFmt* pTmpFmt = rSects[ i ];
+ if (pTmpFmt == pSectionFmt)
+ {
+ SwSectionData tmpData(
+ static_cast<SwTOXBaseSection&>(rTOXBase));
+ m_pImpl->m_pDoc->UpdateSection(i, tmpData, & aAttrSet);
+ break;
+ }
+ }
+ }
+ }
+ rTOXBase.SetCreate(nCreate);
+ rTOXBase.SetOLEOptions(nOLEOptions);
+ if (rTOXBase.GetTOXType()->GetType() == TOX_INDEX)
+ {
+ rTOXBase.SetOptions(nTOIOptions);
+ }
+ if (bForm)
+ {
+ rTOXBase.SetTOXForm(aForm);
+ }
+}
+
+uno::Any SAL_CALL
+SwXDocumentIndex::getPropertyValue(const OUString& rPropertyName)
+throw (beans::UnknownPropertyException, lang::WrappedTargetException,
+ uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+
+ uno::Any aRet;
+ SfxItemPropertySimpleEntry const*const pEntry =
+ m_pImpl->m_rPropSet.getPropertyMap()->getByName(rPropertyName);
+ if (!pEntry)
+ {
+ throw beans::UnknownPropertyException(
+ OUString(RTL_CONSTASCII_USTRINGPARAM("Unknown property: "))
+ + rPropertyName,
+ static_cast< cppu::OWeakObject * >(this));
+ }
+
+ SwSectionFmt *const pSectionFmt( m_pImpl->GetSectionFmt() );
+ SwTOXBase* pTOXBase = 0;
+ if (pSectionFmt)
+ {
+ pTOXBase = static_cast<SwTOXBaseSection*>(pSectionFmt->GetSection());
+ }
+ else if (m_pImpl->m_bIsDescriptor)
+ {
+ pTOXBase = &m_pImpl->m_pProps->GetTOXBase();
+ }
+ if(pTOXBase)
+ {
+ const sal_uInt16 nCreate = pTOXBase->GetCreateType();
+ const sal_uInt16 nOLEOptions = pTOXBase->GetOLEOptions();
+ const sal_uInt16 nTOIOptions =
+ (pTOXBase->GetTOXType()->GetType() == TOX_INDEX)
+ ? pTOXBase->GetOptions()
+ : 0U;
+ const SwForm& rForm = pTOXBase->GetTOXForm();
+ switch(pEntry->nWID)
+ {
+ case WID_IDX_CONTENT_SECTION:
+ case WID_IDX_HEADER_SECTION :
+ if(WID_IDX_CONTENT_SECTION == pEntry->nWID)
+ {
+ const uno::Reference <text::XTextSection> xContentSect =
+ SwXTextSection::CreateXTextSection( pSectionFmt );
+ aRet <<= xContentSect;
+ }
+ else
+ {
+ SwSections aSectArr;
+ pSectionFmt->GetChildSections(aSectArr,
+ SORTSECT_NOT, sal_False);
+ for(sal_uInt16 i = 0; i < aSectArr.Count(); i++)
+ {
+ SwSection* pSect = aSectArr[i];
+ if(pSect->GetType() == TOX_HEADER_SECTION)
+ {
+ const uno::Reference <text::XTextSection> xHeader =
+ SwXTextSection::CreateXTextSection(
+ pSect->GetFmt() );
+ aRet <<= xHeader;
+ break;
+ }
+ }
+ }
+ break;
+ case WID_IDX_TITLE :
+ {
+ OUString uRet(pTOXBase->GetTitle());
+ aRet <<= uRet;
+ break;
+ }
+ case WID_IDX_NAME:
+ aRet <<= OUString(pTOXBase->GetTOXName());
+ break;
+ case WID_USER_IDX_NAME:
+ {
+ OUString sTmp;
+ if (!m_pImpl->m_bIsDescriptor)
+ {
+ sTmp = pTOXBase->GetTOXType()->GetTypeName();
+ }
+ else
+ {
+ sTmp = m_pImpl->m_pProps->GetTypeName();
+ }
+ //I18N
+ lcl_ConvertTOUNameToProgrammaticName(sTmp);
+ aRet <<= sTmp;
+ }
+ break;
+ case WID_IDX_LOCALE:
+ aRet <<= SvxCreateLocale(pTOXBase->GetLanguage());
+ break;
+ case WID_IDX_SORT_ALGORITHM:
+ aRet <<= OUString(pTOXBase->GetSortAlgorithm());
+ break;
+ case WID_LEVEL :
+ aRet <<= static_cast<sal_Int16>(pTOXBase->GetLevel());
+ break;
+ case WID_CREATE_FROM_MARKS:
+ lcl_BitMaskToAny(aRet, nCreate, nsSwTOXElement::TOX_MARK);
+ break;
+ case WID_CREATE_FROM_OUTLINE:
+ lcl_BitMaskToAny(aRet, nCreate,
+ nsSwTOXElement::TOX_OUTLINELEVEL);
+ break;
+ case WID_CREATE_FROM_CHAPTER:
+ {
+ const sal_Bool bRet = pTOXBase->IsFromChapter();
+ aRet <<= bRet;
+ }
+ break;
+ case WID_CREATE_FROM_LABELS:
+ {
+ const sal_Bool bRet = ! pTOXBase->IsFromObjectNames();
+ aRet <<= bRet;
+ }
+ break;
+ case WID_PROTECTED:
+ {
+ const sal_Bool bRet = pTOXBase->IsProtected();
+ aRet <<= bRet;
+ }
+ break;
+ case WID_USE_ALPHABETICAL_SEPARATORS:
+ lcl_BitMaskToAny(aRet, nTOIOptions,
+ nsSwTOIOptions::TOI_ALPHA_DELIMITTER);
+ break;
+ case WID_USE_KEY_AS_ENTRY:
+ lcl_BitMaskToAny(aRet, nTOIOptions,
+ nsSwTOIOptions::TOI_KEY_AS_ENTRY);
+ break;
+ case WID_USE_COMBINED_ENTRIES:
+ lcl_BitMaskToAny(aRet, nTOIOptions,
+ nsSwTOIOptions::TOI_SAME_ENTRY);
+ break;
+ case WID_IS_CASE_SENSITIVE:
+ lcl_BitMaskToAny(aRet, nTOIOptions,
+ nsSwTOIOptions::TOI_CASE_SENSITIVE);
+ break;
+ case WID_USE_P_P:
+ lcl_BitMaskToAny(aRet, nTOIOptions, nsSwTOIOptions::TOI_FF);
+ break;
+ case WID_USE_DASH:
+ lcl_BitMaskToAny(aRet, nTOIOptions, nsSwTOIOptions::TOI_DASH);
+ break;
+ case WID_USE_UPPER_CASE:
+ lcl_BitMaskToAny(aRet, nTOIOptions,
+ nsSwTOIOptions::TOI_INITIAL_CAPS);
+ break;
+ case WID_IS_COMMA_SEPARATED:
+ {
+ const sal_Bool bRet = rForm.IsCommaSeparated();
+ aRet <<= bRet;
+ }
+ break;
+ case WID_LABEL_CATEGORY:
+ {
+ // convert internal UI name to
+ // file-format/API/external programmatic english name
+ // before usage
+ String aName( SwStyleNameMapper::GetSpecialExtraProgName(
+ pTOXBase->GetSequenceName() ) );
+ aRet <<= OUString( aName );
+ }
+ break;
+ case WID_LABEL_DISPLAY_TYPE:
+ {
+ sal_Int16 nSet = text::ReferenceFieldPart::TEXT;
+ switch (pTOXBase->GetCaptionDisplay())
+ {
+ case CAPTION_COMPLETE:
+ nSet = text::ReferenceFieldPart::TEXT;
+ break;
+ case CAPTION_NUMBER:
+ nSet = text::ReferenceFieldPart::CATEGORY_AND_NUMBER;
+ break;
+ case CAPTION_TEXT:
+ nSet = text::ReferenceFieldPart::ONLY_CAPTION;
+ break;
+ }
+ aRet <<= nSet;
+ }
+ break;
+ case WID_USE_LEVEL_FROM_SOURCE:
+ {
+ const sal_Bool bRet = pTOXBase->IsLevelFromChapter();
+ aRet <<= bRet;
+ }
+ break;
+ case WID_LEVEL_FORMAT:
+ {
+ uno::Reference< container::XIndexReplace > xTokenAccess(
+ m_pImpl->m_wTokenAccess);
+ if (!xTokenAccess.is())
+ {
+ xTokenAccess = new TokenAccess_Impl(*this);
+ m_pImpl->m_wTokenAccess = xTokenAccess;
+ }
+ aRet <<= xTokenAccess;
+ }
+ break;
+ case WID_LEVEL_PARAGRAPH_STYLES:
+ {
+ uno::Reference< container::XIndexReplace > xStyleAccess(
+ m_pImpl->m_wStyleAccess);
+ if (!xStyleAccess.is())
+ {
+ xStyleAccess = new StyleAccess_Impl(*this);
+ m_pImpl->m_wStyleAccess = xStyleAccess;
+ }
+ aRet <<= xStyleAccess;
+ }
+ break;
+ case WID_MAIN_ENTRY_CHARACTER_STYLE_NAME:
+ {
+ String aString;
+ SwStyleNameMapper::FillProgName(
+ pTOXBase->GetMainEntryCharStyle(),
+ aString,
+ nsSwGetPoolIdFromName::GET_POOLID_CHRFMT,
+ sal_True);
+ aRet <<= OUString( aString );
+ }
+ break;
+ case WID_CREATE_FROM_TABLES:
+ lcl_BitMaskToAny(aRet, nCreate, nsSwTOXElement::TOX_TABLE);
+ break;
+ case WID_CREATE_FROM_TEXT_FRAMES:
+ lcl_BitMaskToAny(aRet, nCreate, nsSwTOXElement::TOX_FRAME);
+ break;
+ case WID_CREATE_FROM_GRAPHIC_OBJECTS:
+ lcl_BitMaskToAny(aRet, nCreate, nsSwTOXElement::TOX_GRAPHIC);
+ break;
+ case WID_CREATE_FROM_EMBEDDED_OBJECTS:
+ lcl_BitMaskToAny(aRet, nCreate, nsSwTOXElement::TOX_OLE);
+ break;
+ case WID_CREATE_FROM_STAR_MATH:
+ lcl_BitMaskToAny(aRet, nOLEOptions, nsSwTOOElements::TOO_MATH);
+ break;
+ case WID_CREATE_FROM_STAR_CHART:
+ lcl_BitMaskToAny(aRet, nOLEOptions, nsSwTOOElements::TOO_CHART);
+ break;
+ case WID_CREATE_FROM_STAR_CALC:
+ lcl_BitMaskToAny(aRet, nOLEOptions, nsSwTOOElements::TOO_CALC);
+ break;
+ case WID_CREATE_FROM_STAR_DRAW:
+ lcl_BitMaskToAny(aRet, nOLEOptions,
+ nsSwTOOElements::TOO_DRAW_IMPRESS);
+ break;
+ case WID_CREATE_FROM_OTHER_EMBEDDED_OBJECTS:
+ lcl_BitMaskToAny(aRet, nOLEOptions, nsSwTOOElements::TOO_OTHER);
+ break;
+ case WID_CREATE_FROM_PARAGRAPH_STYLES:
+ lcl_BitMaskToAny(aRet, nCreate, nsSwTOXElement::TOX_TEMPLATE);
+ break;
+ case WID_PARA_HEAD:
+ {
+ //Header steht an Pos 0
+ String aString;
+ SwStyleNameMapper::FillProgName(rForm.GetTemplate( 0 ), aString,
+ nsSwGetPoolIdFromName::GET_POOLID_TXTCOLL, sal_True );
+ aRet <<= OUString( aString );
+ }
+ break;
+ case WID_PARA_SEP:
+ {
+ String aString;
+ SwStyleNameMapper::FillProgName(
+ rForm.GetTemplate( 1 ),
+ aString,
+ nsSwGetPoolIdFromName::GET_POOLID_TXTCOLL,
+ sal_True);
+ aRet <<= OUString( aString );
+ }
+ break;
+ case WID_PARA_LEV1:
+ case WID_PARA_LEV2:
+ case WID_PARA_LEV3:
+ case WID_PARA_LEV4:
+ case WID_PARA_LEV5:
+ case WID_PARA_LEV6:
+ case WID_PARA_LEV7:
+ case WID_PARA_LEV8:
+ case WID_PARA_LEV9:
+ case WID_PARA_LEV10:
+ {
+ // in sdbcx::Index Label 1 begins at Pos 2 otherwise at Pos 1
+ sal_uInt16 nLPos = pTOXBase->GetType() == TOX_INDEX ? 2 : 1;
+ String aString;
+ SwStyleNameMapper::FillProgName(
+ rForm.GetTemplate(nLPos + pEntry->nWID - WID_PARA_LEV1),
+ aString,
+ nsSwGetPoolIdFromName::GET_POOLID_TXTCOLL,
+ sal_True);
+ aRet <<= OUString( aString );
+ }
+ break;
+ case WID_IS_RELATIVE_TABSTOPS:
+ {
+ const sal_Bool bRet = rForm.IsRelTabPos();
+ aRet <<= bRet;
+ }
+ break;
+ case WID_INDEX_MARKS:
+ {
+ SwTOXMarks aMarks;
+ const SwTOXType* pType = pTOXBase->GetTOXType();
+ SwTOXMark::InsertTOXMarks( aMarks, *pType );
+ uno::Sequence< uno::Reference<text::XDocumentIndexMark> > aXMarks(aMarks.Count());
+ uno::Reference<text::XDocumentIndexMark>* pxMarks = aXMarks.getArray();
+ for(sal_uInt16 i = 0; i < aMarks.Count(); i++)
+ {
+ SwTOXMark* pMark = aMarks.GetObject(i);
+ pxMarks[i] = SwXDocumentIndexMark::CreateXDocumentIndexMark(
+ *m_pImpl->m_pDoc,
+ *const_cast<SwTOXType*>(pType), *pMark);
+ }
+ aRet <<= aXMarks;
+ }
+ break;
+ default:
+ //this is for items only
+ if(WID_PRIMARY_KEY > pEntry->nWID)
+ {
+ const SwAttrSet& rSet =
+ m_pImpl->m_pDoc->GetTOXBaseAttrSet(*pTOXBase);
+ aRet = m_pImpl->m_rPropSet.getPropertyValue(
+ rPropertyName, rSet);
+ }
+ }
+ }
+ return aRet;
+}
+
+void SAL_CALL
+SwXDocumentIndex::addPropertyChangeListener(
+ const ::rtl::OUString& /*rPropertyName*/,
+ const uno::Reference< beans::XPropertyChangeListener >& /*xListener*/)
+throw (beans::UnknownPropertyException, lang::WrappedTargetException,
+ uno::RuntimeException)
+{
+ OSL_FAIL("SwXDocumentIndex::addPropertyChangeListener(): not implemented");
+}
+
+void SAL_CALL
+SwXDocumentIndex::removePropertyChangeListener(
+ const ::rtl::OUString& /*rPropertyName*/,
+ const uno::Reference< beans::XPropertyChangeListener >& /*xListener*/)
+throw (beans::UnknownPropertyException, lang::WrappedTargetException,
+ uno::RuntimeException)
+{
+ OSL_FAIL("SwXDocumentIndex::removePropertyChangeListener(): not implemented");
+}
+
+void SAL_CALL
+SwXDocumentIndex::addVetoableChangeListener(
+ const ::rtl::OUString& /*rPropertyName*/,
+ const uno::Reference< beans::XVetoableChangeListener >& /*xListener*/)
+throw (beans::UnknownPropertyException, lang::WrappedTargetException,
+ uno::RuntimeException)
+{
+ OSL_FAIL("SwXDocumentIndex::addVetoableChangeListener(): not implemented");
+}
+
+void SAL_CALL
+SwXDocumentIndex::removeVetoableChangeListener(
+ const ::rtl::OUString& /*rPropertyName*/,
+ const uno::Reference< beans::XVetoableChangeListener >& /*xListener*/)
+throw (beans::UnknownPropertyException, lang::WrappedTargetException,
+ uno::RuntimeException)
+{
+ OSL_FAIL("SwXDocumentIndex::removeVetoableChangeListener(): not implemented");
+}
+
+void SAL_CALL
+SwXDocumentIndex::attach(const uno::Reference< text::XTextRange > & xTextRange)
+throw (lang::IllegalArgumentException, uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+
+ if (!m_pImpl->m_bIsDescriptor)
+ {
+ throw uno::RuntimeException();
+ }
+ const uno::Reference<XUnoTunnel> xRangeTunnel( xTextRange, uno::UNO_QUERY);
+ SwXTextRange *const pRange =
+ ::sw::UnoTunnelGetImplementation<SwXTextRange>(xRangeTunnel);
+ OTextCursorHelper *const pCursor =
+ ::sw::UnoTunnelGetImplementation<OTextCursorHelper>(xRangeTunnel);
+
+ SwDoc *const pDoc =
+ (pRange) ? pRange->GetDoc() : ((pCursor) ? pCursor->GetDoc() : 0);
+ if (!pDoc)
+ {
+ throw lang::IllegalArgumentException();
+ }
+
+ SwUnoInternalPaM aPam(*pDoc);
+ //das muss jetzt sal_True liefern
+ ::sw::XTextRangeToSwPaM(aPam, xTextRange);
+
+ const SwTOXBase* pOld = pDoc->GetCurTOX( *aPam.Start() );
+ if (pOld)
+ {
+ throw lang::IllegalArgumentException();
+ }
+
+ UnoActionContext aAction(pDoc);
+ if (aPam.HasMark())
+ {
+ pDoc->DeleteAndJoin(aPam);
+ }
+
+ SwTOXBase & rTOXBase = m_pImpl->m_pProps->GetTOXBase();
+ SwTOXType const*const pTOXType = rTOXBase.GetTOXType();
+ if ((TOX_USER == pTOXType->GetType()) &&
+ !m_pImpl->m_pProps->GetTypeName().equals(pTOXType->GetTypeName()))
+ {
+ lcl_ReAssignTOXType(pDoc, rTOXBase, m_pImpl->m_pProps->GetTypeName());
+ }
+ //TODO: apply Section attributes (columns and background)
+ SwTOXBaseSection const*const pTOX =
+ pDoc->InsertTableOf( *aPam.GetPoint(), rTOXBase, 0, sal_False );
+
+ pDoc->SetTOXBaseName(*pTOX, m_pImpl->m_pProps->GetTOXBase().GetTOXName());
+
+ // update page numbers
+ pTOX->GetFmt()->Add(m_pImpl.get());
+ pTOX->GetFmt()->SetXObject(static_cast< ::cppu::OWeakObject*>(this));
+ const_cast<SwTOXBaseSection*>(pTOX)->UpdatePageNum();
+
+ m_pImpl->m_pProps.reset();
+ m_pImpl->m_pDoc = pDoc;
+ m_pImpl->m_bIsDescriptor = sal_False;
+}
+
+uno::Reference< text::XTextRange > SAL_CALL
+SwXDocumentIndex::getAnchor() throw (uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+
+ SwSectionFmt *const pSectionFmt( m_pImpl->GetSectionFmt() );
+ if (!pSectionFmt)
+ {
+ throw uno::RuntimeException();
+ }
+
+ uno::Reference< text::XTextRange > xRet;
+ SwNodeIndex const*const pIdx( pSectionFmt->GetCntnt().GetCntntIdx() );
+ if (pIdx && pIdx->GetNode().GetNodes().IsDocNodes())
+ {
+ SwPaM aPaM(*pIdx);
+ aPaM.Move( fnMoveForward, fnGoCntnt );
+ aPaM.SetMark();
+ aPaM.GetPoint()->nNode = *pIdx->GetNode().EndOfSectionNode();
+ aPaM.Move( fnMoveBackward, fnGoCntnt );
+ xRet = SwXTextRange::CreateXTextRange(*pSectionFmt->GetDoc(),
+ *aPaM.GetMark(), aPaM.GetPoint());
+ }
+ return xRet;
+}
+
+void lcl_RemoveChildSections(SwSectionFmt& rParentFmt)
+{
+ SwSections aTmpArr;
+ SwDoc *const pDoc = rParentFmt.GetDoc();
+ const sal_uInt16 nCnt = rParentFmt.GetChildSections(aTmpArr, SORTSECT_POS);
+ if( nCnt )
+ {
+ for( sal_uInt16 n = 0; n < nCnt; ++n )
+ {
+ if( aTmpArr[n]->GetFmt()->IsInNodesArr() )
+ {
+ SwSectionFmt* pFmt = aTmpArr[n]->GetFmt();
+ lcl_RemoveChildSections(*pFmt);
+ pDoc->DelSectionFmt( pFmt );
+ }
+ }
+ }
+}
+
+void SAL_CALL SwXDocumentIndex::dispose() throw (uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+
+ SwSectionFmt *const pSectionFmt( m_pImpl->GetSectionFmt() );
+ if (pSectionFmt)
+ {
+ pSectionFmt->GetDoc()->DeleteTOX(
+ *static_cast<SwTOXBaseSection*>(pSectionFmt->GetSection()),
+ sal_True);
+ }
+}
+
+void SAL_CALL
+SwXDocumentIndex::addEventListener(
+ const uno::Reference< lang::XEventListener > & xListener)
+throw (uno::RuntimeException)
+{
+ SolarMutexGuard g;
+
+ if (!m_pImpl->GetRegisteredIn())
+ {
+ throw uno::RuntimeException();
+ }
+ m_pImpl->m_ListenerContainer.AddListener(xListener);
+}
+
+void SAL_CALL
+SwXDocumentIndex::removeEventListener(
+ const uno::Reference< lang::XEventListener > & xListener)
+throw (uno::RuntimeException)
+{
+ SolarMutexGuard g;
+
+ if (!m_pImpl->GetRegisteredIn() ||
+ !m_pImpl->m_ListenerContainer.RemoveListener(xListener))
+ {
+ throw uno::RuntimeException();
+ }
+}
+
+OUString SAL_CALL SwXDocumentIndex::getName() throw (uno::RuntimeException)
+{
+ SolarMutexGuard g;
+
+ OUString uRet;
+ SwSectionFmt *const pSectionFmt( m_pImpl->GetSectionFmt() );
+ if (m_pImpl->m_bIsDescriptor)
+ {
+ uRet = OUString(m_pImpl->m_pProps->GetTOXBase().GetTOXName());
+ }
+ else if(pSectionFmt)
+ {
+ uRet = OUString(pSectionFmt->GetSection()->GetSectionName());
+ }
+ else
+ {
+ throw uno::RuntimeException();
+ }
+ return uRet;
+}
+
+void SAL_CALL
+SwXDocumentIndex::setName(const OUString& rName) throw (uno::RuntimeException)
+{
+ SolarMutexGuard g;
+
+ if (!rName.getLength())
+ {
+ throw uno::RuntimeException();
+ }
+
+ SwSectionFmt *const pSectionFmt( m_pImpl->GetSectionFmt() );
+ if (m_pImpl->m_bIsDescriptor)
+ {
+ m_pImpl->m_pProps->GetTOXBase().SetTOXName(rName);
+ }
+ else if (pSectionFmt)
+ {
+ const bool bSuccess = pSectionFmt->GetDoc()->SetTOXBaseName(
+ *static_cast<SwTOXBaseSection*>(pSectionFmt->GetSection()), rName);
+ if (!bSuccess)
+ {
+ throw uno::RuntimeException();
+ }
+ }
+ else
+ {
+ throw uno::RuntimeException();
+ }
+}
+
+// MetadatableMixin
+::sfx2::Metadatable* SwXDocumentIndex::GetCoreObject()
+{
+ SwSectionFmt *const pSectionFmt( m_pImpl->GetSectionFmt() );
+ return pSectionFmt;
+}
+
+uno::Reference<frame::XModel> SwXDocumentIndex::GetModel()
+{
+ SwSectionFmt *const pSectionFmt( m_pImpl->GetSectionFmt() );
+ if (pSectionFmt)
+ {
+ SwDocShell const*const pShell( pSectionFmt->GetDoc()->GetDocShell() );
+ return (pShell) ? pShell->GetModel() : 0;
+ }
+ return 0;
+}
+
+
+/******************************************************************
+ * SwXDocumentIndexMark
+ ******************************************************************/
+static sal_uInt16
+lcl_TypeToPropertyMap_Mark(const TOXTypes eType)
+{
+ switch (eType)
+ {
+ case TOX_INDEX: return PROPERTY_MAP_INDEX_MARK;
+ case TOX_CONTENT: return PROPERTY_MAP_CNTIDX_MARK;
+ //case TOX_USER:
+ default:
+ return PROPERTY_MAP_USER_MARK;
+ }
+}
+
+class SwXDocumentIndexMark::Impl
+ : public SwClient
+{
+private:
+ bool m_bInReplaceMark;
+
+public:
+
+ SfxItemPropertySet const& m_rPropSet;
+ const TOXTypes m_eTOXType;
+ SwEventListenerContainer m_ListenerContainer;
+ bool m_bIsDescriptor;
+ SwDepend m_TypeDepend;
+ const SwTOXMark * m_pTOXMark;
+ SwDoc * m_pDoc;
+
+ sal_Bool m_bMainEntry;
+ sal_uInt16 m_nLevel;
+ OUString m_sAltText;
+ OUString m_sPrimaryKey;
+ OUString m_sSecondaryKey;
+ OUString m_sTextReading;
+ OUString m_sPrimaryKeyReading;
+ OUString m_sSecondaryKeyReading;
+ OUString m_sUserIndexName;
+
+ Impl( SwXDocumentIndexMark & rThis,
+ SwDoc *const pDoc,
+ const enum TOXTypes eType,
+ SwTOXType *const pType, SwTOXMark const*const pMark)
+ : SwClient(const_cast<SwTOXMark*>(pMark))
+ , m_bInReplaceMark(false)
+ , m_rPropSet(
+ *aSwMapProvider.GetPropertySet(lcl_TypeToPropertyMap_Mark(eType)))
+ , m_eTOXType(eType)
+ , m_ListenerContainer(static_cast< ::cppu::OWeakObject* >(&rThis))
+// #i112513#: unxsols4 (Sun C++ 5.9 SunOS_sparc) generates wrong code for this
+// , m_bIsDescriptor(0 == pMark)
+ , m_bIsDescriptor((0 == pMark) ? true : false)
+ , m_TypeDepend(this, pType)
+ , m_pTOXMark(pMark)
+ , m_pDoc(pDoc)
+ , m_bMainEntry(sal_False)
+ , m_nLevel(0)
+ {
+ }
+
+ SwTOXType * GetTOXType() const {
+ return static_cast<SwTOXType*>(
+ const_cast<SwModify *>(m_TypeDepend.GetRegisteredIn()));
+ }
+
+ void DeleteTOXMark()
+ {
+ m_pDoc->DeleteTOXMark(m_pTOXMark); // calls Invalidate() via Modify!
+ m_pTOXMark = 0;
+ }
+
+ void InsertTOXMark(SwTOXType & rTOXType, SwTOXMark & rMark, SwPaM & rPam,
+ SwXTextCursor const*const pTextCursor);
+
+ void ReplaceTOXMark(SwTOXType & rTOXType, SwTOXMark & rMark, SwPaM & rPam)
+ {
+ m_bInReplaceMark = true;
+ DeleteTOXMark();
+ m_bInReplaceMark = false;
+ try {
+ InsertTOXMark(rTOXType, rMark, rPam, 0);
+ } catch (...) {
+ OSL_FAIL("ReplaceTOXMark() failed!");
+ m_ListenerContainer.Disposing();
+ throw;
+ }
+ }
+
+ void Invalidate();
+protected:
+ // SwClient
+ virtual void Modify(const SfxPoolItem *pOld, const SfxPoolItem *pNew);
+};
+
+void SwXDocumentIndexMark::Impl::Invalidate()
+{
+ if (GetRegisteredIn())
+ {
+ const_cast<SwModify*>(GetRegisteredIn())->Remove(this);
+ if (m_TypeDepend.GetRegisteredIn())
+ {
+ const_cast<SwModify*>(m_TypeDepend.GetRegisteredIn())->Remove(
+ &m_TypeDepend);
+ }
+ }
+ if (!m_bInReplaceMark) // #i109983# only dispose on delete, not on replace!
+ {
+ m_ListenerContainer.Disposing();
+ }
+ m_pDoc = 0;
+ m_pTOXMark = 0;
+}
+
+void SwXDocumentIndexMark::Impl::Modify(const SfxPoolItem *pOld, const SfxPoolItem *pNew)
+{
+ ClientModify(this, pOld, pNew);
+
+ if (!GetRegisteredIn()) // removed => dispose
+ {
+ Invalidate();
+ }
+}
+
+SwXDocumentIndexMark::SwXDocumentIndexMark(const TOXTypes eToxType)
+ : m_pImpl( new SwXDocumentIndexMark::Impl(*this, 0, eToxType, 0, 0) )
+{
+}
+
+SwXDocumentIndexMark::SwXDocumentIndexMark(SwDoc & rDoc,
+ SwTOXType & rType, SwTOXMark & rMark)
+ : m_pImpl( new SwXDocumentIndexMark::Impl(*this, &rDoc, rType.GetType(),
+ &rType, &rMark) )
+{
+}
+
+SwXDocumentIndexMark::~SwXDocumentIndexMark()
+{
+}
+
+uno::Reference<text::XDocumentIndexMark>
+SwXDocumentIndexMark::CreateXDocumentIndexMark(
+ SwDoc & rDoc, SwTOXType & rType, SwTOXMark & rMark)
+{
+ // re-use existing SwXDocumentIndexMark
+ // NB: xmloff depends on this caching to generate ID from the address!
+ // #i105557#: do not iterate over the registered clients: race condition
+ uno::Reference< text::XDocumentIndexMark > xTOXMark(rMark.GetXTOXMark());
+ if (!xTOXMark.is())
+ {
+ SwXDocumentIndexMark *const pNew =
+ new SwXDocumentIndexMark(rDoc, rType, rMark);
+ xTOXMark.set(pNew);
+ rMark.SetXTOXMark(xTOXMark);
+ }
+ return xTOXMark;
+}
+
+const uno::Sequence< sal_Int8 > & SwXDocumentIndexMark::getUnoTunnelId()
+{
+ static uno::Sequence< sal_Int8 > aSeq = ::CreateUnoTunnelId();
+ return aSeq;
+}
+
+sal_Int64 SAL_CALL
+SwXDocumentIndexMark::getSomething(const uno::Sequence< sal_Int8 >& rId)
+throw (uno::RuntimeException)
+{
+ return ::sw::UnoTunnelImpl<SwXDocumentIndexMark>(rId, this);
+}
+
+static const sal_Char cBaseMark[] = "com.sun.star.text.BaseIndexMark";
+static const sal_Char cContentMark[] = "com.sun.star.text.ContentIndexMark";
+static const sal_Char cIdxMark[] = "com.sun.star.text.DocumentIndexMark";
+static const sal_Char cIdxMarkAsian[] = "com.sun.star.text.DocumentIndexMarkAsian";
+static const sal_Char cUserMark[] = "com.sun.star.text.UserIndexMark";
+static const sal_Char cTextContent[] = "com.sun.star.text.TextContent";
+
+OUString SAL_CALL
+SwXDocumentIndexMark::getImplementationName() throw (uno::RuntimeException)
+{
+ return C2U("SwXDocumentIndexMark");
+}
+
+sal_Bool SAL_CALL
+SwXDocumentIndexMark::supportsService(const OUString& rServiceName)
+throw (uno::RuntimeException)
+{
+ SolarMutexGuard g;
+
+ return rServiceName.equalsAscii(cBaseMark)
+ || rServiceName.equalsAscii(cTextContent)
+ || ((m_pImpl->m_eTOXType == TOX_USER)
+ && rServiceName.equalsAscii(cUserMark))
+ || ((m_pImpl->m_eTOXType == TOX_CONTENT)
+ && rServiceName.equalsAscii(cContentMark))
+ || ((m_pImpl->m_eTOXType == TOX_INDEX)
+ && rServiceName.equalsAscii(cIdxMark))
+ || ((m_pImpl->m_eTOXType == TOX_INDEX)
+ && rServiceName.equalsAscii(cIdxMarkAsian));
+}
+
+uno::Sequence< OUString > SAL_CALL
+SwXDocumentIndexMark::getSupportedServiceNames() throw (uno::RuntimeException)
+{
+ SolarMutexGuard g;
+
+ const sal_Int32 nCnt = (m_pImpl->m_eTOXType == TOX_INDEX) ? 4 : 3;
+ uno::Sequence< OUString > aRet(nCnt);
+ OUString* pArray = aRet.getArray();
+ pArray[0] = C2U(cBaseMark);
+ pArray[1] = C2U(cTextContent);
+ switch (m_pImpl->m_eTOXType)
+ {
+ case TOX_USER:
+ pArray[2] = C2U(cUserMark);
+ break;
+ case TOX_CONTENT:
+ pArray[2] = C2U(cContentMark);
+ break;
+ case TOX_INDEX:
+ pArray[2] = C2U(cIdxMark);
+ pArray[3] = C2U(cIdxMarkAsian);
+ break;
+
+ default:
+ ;
+ }
+ return aRet;
+}
+
+OUString SAL_CALL
+SwXDocumentIndexMark::getMarkEntry() throw (uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+
+ OUString sRet;
+ SwTOXType *const pType = m_pImpl->GetTOXType();
+ if (pType && m_pImpl->m_pTOXMark)
+ {
+ sRet = OUString(m_pImpl->m_pTOXMark->GetAlternativeText());
+ }
+ else if (m_pImpl->m_bIsDescriptor)
+ {
+ sRet = m_pImpl->m_sAltText;
+ }
+ else
+ {
+ throw uno::RuntimeException();
+ }
+ return sRet;
+}
+
+void SAL_CALL
+SwXDocumentIndexMark::setMarkEntry(const OUString& rIndexEntry)
+throw (uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+
+ SwTOXType *const pType = m_pImpl->GetTOXType();
+ if (pType && m_pImpl->m_pTOXMark)
+ {
+ SwTOXMark aMark(*m_pImpl->m_pTOXMark);
+ aMark.SetAlternativeText(rIndexEntry);
+ SwTxtTOXMark const*const pTxtMark =
+ m_pImpl->m_pTOXMark->GetTxtTOXMark();
+ SwPaM aPam(pTxtMark->GetTxtNode(), *pTxtMark->GetStart());
+ aPam.SetMark();
+ if(pTxtMark->GetEnd())
+ {
+ aPam.GetPoint()->nContent = *pTxtMark->GetEnd();
+ }
+ else
+ aPam.GetPoint()->nContent++;
+
+ m_pImpl->ReplaceTOXMark(*pType, aMark, aPam);
+ }
+ else if (m_pImpl->m_bIsDescriptor)
+ {
+ m_pImpl->m_sAltText = rIndexEntry;
+ }
+ else
+ {
+ throw uno::RuntimeException();
+ }
+}
+
+void SAL_CALL
+SwXDocumentIndexMark::attach(
+ const uno::Reference< text::XTextRange > & xTextRange)
+throw (lang::IllegalArgumentException, uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+
+ if (!m_pImpl->m_bIsDescriptor)
+ {
+ throw uno::RuntimeException();
+ }
+
+ const uno::Reference<XUnoTunnel> xRangeTunnel(xTextRange, uno::UNO_QUERY);
+ SwXTextRange *const pRange =
+ ::sw::UnoTunnelGetImplementation<SwXTextRange>(xRangeTunnel);
+ OTextCursorHelper *const pCursor =
+ ::sw::UnoTunnelGetImplementation<OTextCursorHelper>(xRangeTunnel);
+ SwDoc *const pDoc =
+ (pRange) ? pRange->GetDoc() : ((pCursor) ? pCursor->GetDoc() : 0);
+ if (!pDoc)
+ {
+ throw lang::IllegalArgumentException();
+ }
+
+ const SwTOXType* pTOXType = 0;
+ switch (m_pImpl->m_eTOXType)
+ {
+ case TOX_INDEX:
+ case TOX_CONTENT:
+ pTOXType = pDoc->GetTOXType( m_pImpl->m_eTOXType, 0 );
+ break;
+ case TOX_USER:
+ {
+ if (!m_pImpl->m_sUserIndexName.getLength())
+ {
+ pTOXType = pDoc->GetTOXType( m_pImpl->m_eTOXType, 0 );
+ }
+ else
+ {
+ const sal_uInt16 nCount =
+ pDoc->GetTOXTypeCount(m_pImpl->m_eTOXType);
+ for (sal_uInt16 i = 0; i < nCount; i++)
+ {
+ SwTOXType const*const pTemp =
+ pDoc->GetTOXType( m_pImpl->m_eTOXType, i );
+ if (m_pImpl->m_sUserIndexName ==
+ OUString(pTemp->GetTypeName()))
+ {
+ pTOXType = pTemp;
+ break;
+ }
+ }
+ if (!pTOXType)
+ {
+ SwTOXType aUserType(TOX_USER, m_pImpl->m_sUserIndexName);
+ pTOXType = pDoc->InsertTOXType(aUserType);
+ }
+ }
+ }
+ break;
+
+ default:
+ break;
+ }
+ if (!pTOXType)
+ {
+ throw lang::IllegalArgumentException();
+ }
+
+ SwUnoInternalPaM aPam(*pDoc);
+ //which must now return sal_True
+ ::sw::XTextRangeToSwPaM(aPam, xTextRange);
+ SwTOXMark aMark (pTOXType);
+ if (m_pImpl->m_sAltText.getLength())
+ {
+ aMark.SetAlternativeText(m_pImpl->m_sAltText);
+ }
+ switch (m_pImpl->m_eTOXType)
+ {
+ case TOX_INDEX:
+ if (m_pImpl->m_sPrimaryKey.getLength())
+ {
+ aMark.SetPrimaryKey(m_pImpl->m_sPrimaryKey);
+ }
+ if (m_pImpl->m_sSecondaryKey.getLength())
+ {
+ aMark.SetSecondaryKey(m_pImpl->m_sSecondaryKey);
+ }
+ if (m_pImpl->m_sTextReading.getLength())
+ {
+ aMark.SetTextReading(m_pImpl->m_sTextReading);
+ }
+ if (m_pImpl->m_sPrimaryKeyReading.getLength())
+ {
+ aMark.SetPrimaryKeyReading(m_pImpl->m_sPrimaryKeyReading);
+ }
+ if (m_pImpl->m_sSecondaryKeyReading.getLength())
+ {
+ aMark.SetSecondaryKeyReading(m_pImpl->m_sSecondaryKeyReading);
+ }
+ aMark.SetMainEntry(m_pImpl->m_bMainEntry);
+ break;
+ case TOX_USER:
+ case TOX_CONTENT:
+ if (USHRT_MAX != m_pImpl->m_nLevel)
+ {
+ aMark.SetLevel(m_pImpl->m_nLevel+1);
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ m_pImpl->InsertTOXMark(*const_cast<SwTOXType *>(pTOXType), aMark, aPam,
+ dynamic_cast<SwXTextCursor const*>(pCursor));
+
+ m_pImpl->m_bIsDescriptor = sal_False;
+}
+
+template<typename T> struct NotContainedIn
+{
+ ::std::vector<T> const& m_rVector;
+ explicit NotContainedIn(::std::vector<T> const& rVector)
+ : m_rVector(rVector) { }
+ bool operator() (T const& rT) {
+ return ::std::find(m_rVector.begin(), m_rVector.end(), rT)
+ == m_rVector.end();
+ }
+};
+
+void SwXDocumentIndexMark::Impl::InsertTOXMark(
+ SwTOXType & rTOXType, SwTOXMark & rMark, SwPaM & rPam,
+ SwXTextCursor const*const pTextCursor)
+{
+ SwDoc *const pDoc( rPam.GetDoc() );
+ UnoActionContext aAction(pDoc);
+ bool bMark = *rPam.GetPoint() != *rPam.GetMark();
+ // n.b.: toxmarks must have either alternative text or an extent
+ if (bMark && rMark.GetAlternativeText().Len())
+ {
+ rPam.Normalize(sal_True);
+ rPam.DeleteMark();
+ bMark = false;
+ }
+ // Marks ohne Alternativtext ohne selektierten Text koennen nicht eingefuegt werden,
+ // deshalb hier ein Leerzeichen - ob das die ideale Loesung ist?
+ if (!bMark && !rMark.GetAlternativeText().Len())
+ {
+ rMark.SetAlternativeText( String(' ') );
+ }
+
+ const bool bForceExpandHints( (!bMark && pTextCursor)
+ ? pTextCursor->IsAtEndOfMeta() : false );
+ const SetAttrMode nInsertFlags = (bForceExpandHints)
+ ? ( nsSetAttrMode::SETATTR_FORCEHINTEXPAND
+ | nsSetAttrMode::SETATTR_DONTEXPAND)
+ : nsSetAttrMode::SETATTR_DONTEXPAND;
+
+ ::std::vector<SwTxtAttr *> oldMarks;
+ if (bMark)
+ {
+ oldMarks = rPam.GetNode()->GetTxtNode()->GetTxtAttrsAt(
+ rPam.GetPoint()->nContent.GetIndex(), RES_TXTATR_TOXMARK);
+ }
+
+ pDoc->InsertPoolItem(rPam, rMark, nInsertFlags);
+ if (bMark && *rPam.GetPoint() > *rPam.GetMark())
+ {
+ rPam.Exchange();
+ }
+
+ // rMark was copied into the document pool; now retrieve real format...
+ SwTxtAttr * pTxtAttr(0);
+ if (bMark)
+ {
+ // #i107672#
+ // ensure that we do not retrieve a different mark at the same position
+ ::std::vector<SwTxtAttr *> const newMarks(
+ rPam.GetNode()->GetTxtNode()->GetTxtAttrsAt(
+ rPam.GetPoint()->nContent.GetIndex(), RES_TXTATR_TOXMARK));
+ ::std::vector<SwTxtAttr *>::const_iterator const iter(
+ ::std::find_if(newMarks.begin(), newMarks.end(),
+ NotContainedIn<SwTxtAttr *>(oldMarks)));
+ OSL_ASSERT(newMarks.end() != iter);
+ if (newMarks.end() != iter)
+ {
+ pTxtAttr = *iter;
+ }
+ }
+ else
+ {
+ pTxtAttr = rPam.GetNode()->GetTxtNode()->GetTxtAttrForCharAt(
+ rPam.GetPoint()->nContent.GetIndex()-1, RES_TXTATR_TOXMARK );
+ }
+
+ if (!pTxtAttr)
+ {
+ throw uno::RuntimeException(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
+ "SwXDocumentIndexMark::InsertTOXMark(): cannot insert attribute")),
+ 0);
+ }
+
+ m_pDoc = pDoc;
+ m_pTOXMark = & pTxtAttr->GetTOXMark();
+ const_cast<SwTOXMark*>(m_pTOXMark)->Add(this);
+ const_cast<SwTOXType &>(rTOXType).Add(& m_TypeDepend);
+}
+
+uno::Reference< text::XTextRange > SAL_CALL
+SwXDocumentIndexMark::getAnchor() throw (uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+
+ SwTOXType *const pType = m_pImpl->GetTOXType();
+ if (!pType || !m_pImpl->m_pTOXMark)
+ {
+ throw uno::RuntimeException();
+ }
+ if (!m_pImpl->m_pTOXMark->GetTxtTOXMark())
+ {
+ throw uno::RuntimeException();
+ }
+ const SwTxtTOXMark* pTxtMark = m_pImpl->m_pTOXMark->GetTxtTOXMark();
+ SwPaM aPam(pTxtMark->GetTxtNode(), *pTxtMark->GetStart());
+ aPam.SetMark();
+ if(pTxtMark->GetEnd())
+ {
+ aPam.GetPoint()->nContent = *pTxtMark->GetEnd();
+ }
+ else
+ {
+ aPam.GetPoint()->nContent++;
+ }
+ const uno::Reference< frame::XModel > xModel =
+ m_pImpl->m_pDoc->GetDocShell()->GetBaseModel();
+ const uno::Reference< text::XTextDocument > xTDoc(xModel, uno::UNO_QUERY);
+ const uno::Reference< text::XTextRange > xRet =
+ new SwXTextRange(aPam, xTDoc->getText());
+
+ return xRet;
+}
+
+void SAL_CALL
+SwXDocumentIndexMark::dispose() throw (uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+
+ SwTOXType *const pType = m_pImpl->GetTOXType();
+ if (pType && m_pImpl->m_pTOXMark)
+ {
+ m_pImpl->DeleteTOXMark(); // call Invalidate() via modify!
+ }
+}
+
+void SAL_CALL
+SwXDocumentIndexMark::addEventListener(
+ const uno::Reference< lang::XEventListener > & xListener)
+throw (uno::RuntimeException)
+{
+ SolarMutexGuard g;
+
+ if (!m_pImpl->GetRegisteredIn())
+ {
+ throw uno::RuntimeException();
+ }
+ m_pImpl->m_ListenerContainer.AddListener(xListener);
+}
+
+void SAL_CALL
+SwXDocumentIndexMark::removeEventListener(
+ const uno::Reference< lang::XEventListener > & xListener)
+throw (uno::RuntimeException)
+{
+ SolarMutexGuard g;
+
+ if (!m_pImpl->GetRegisteredIn() ||
+ !m_pImpl->m_ListenerContainer.RemoveListener(xListener))
+ {
+ throw uno::RuntimeException();
+ }
+}
+
+uno::Reference< beans::XPropertySetInfo > SAL_CALL
+SwXDocumentIndexMark::getPropertySetInfo() throw (uno::RuntimeException)
+{
+ SolarMutexGuard g;
+
+ static uno::Reference< beans::XPropertySetInfo > xInfos[3];
+ int nPos = 0;
+ switch (m_pImpl->m_eTOXType)
+ {
+ case TOX_INDEX: nPos = 0; break;
+ case TOX_CONTENT: nPos = 1; break;
+ case TOX_USER: nPos = 2; break;
+ default:
+ ;
+ }
+ if(!xInfos[nPos].is())
+ {
+ const uno::Reference< beans::XPropertySetInfo > xInfo =
+ m_pImpl->m_rPropSet.getPropertySetInfo();
+ // extend PropertySetInfo!
+ const uno::Sequence<beans::Property> aPropSeq = xInfo->getProperties();
+ xInfos[nPos] = new SfxExtItemPropertySetInfo(
+ aSwMapProvider.GetPropertyMapEntries(
+ PROPERTY_MAP_PARAGRAPH_EXTENSIONS),
+ aPropSeq );
+ }
+ return xInfos[nPos];
+}
+
+void SAL_CALL
+SwXDocumentIndexMark::setPropertyValue(
+ const OUString& rPropertyName, const uno::Any& rValue)
+throw (beans::UnknownPropertyException, beans::PropertyVetoException,
+ lang::IllegalArgumentException, lang::WrappedTargetException,
+ uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+
+ SfxItemPropertySimpleEntry const*const pEntry =
+ m_pImpl->m_rPropSet.getPropertyMap()->getByName(rPropertyName);
+ if (!pEntry)
+ {
+ throw beans::UnknownPropertyException(
+ OUString(RTL_CONSTASCII_USTRINGPARAM("Unknown property: "))
+ + rPropertyName,
+ static_cast<cppu::OWeakObject *>(this));
+ }
+ if (pEntry->nFlags & beans::PropertyAttribute::READONLY)
+ {
+ throw beans::PropertyVetoException(
+ OUString(RTL_CONSTASCII_USTRINGPARAM("Property is read-only: "))
+ + rPropertyName,
+ static_cast<cppu::OWeakObject *>(this));
+ }
+
+ SwTOXType *const pType = m_pImpl->GetTOXType();
+ if (pType && m_pImpl->m_pTOXMark)
+ {
+ SwTOXMark aMark(*m_pImpl->m_pTOXMark);
+ switch(pEntry->nWID)
+ {
+ case WID_ALT_TEXT:
+ aMark.SetAlternativeText(lcl_AnyToString(rValue));
+ break;
+ case WID_LEVEL:
+ aMark.SetLevel(Min( static_cast<sal_Int8>( MAXLEVEL ),
+ static_cast<sal_Int8>(lcl_AnyToInt16(rValue)+1)));
+ break;
+ case WID_PRIMARY_KEY :
+ aMark.SetPrimaryKey(lcl_AnyToString(rValue));
+ break;
+ case WID_SECONDARY_KEY:
+ aMark.SetSecondaryKey(lcl_AnyToString(rValue));
+ break;
+ case WID_MAIN_ENTRY:
+ aMark.SetMainEntry(lcl_AnyToBool(rValue));
+ break;
+ case WID_TEXT_READING:
+ aMark.SetTextReading(lcl_AnyToString(rValue));
+ break;
+ case WID_PRIMARY_KEY_READING:
+ aMark.SetPrimaryKeyReading(lcl_AnyToString(rValue));
+ break;
+ case WID_SECONDARY_KEY_READING:
+ aMark.SetSecondaryKeyReading(lcl_AnyToString(rValue));
+ break;
+ }
+ SwTxtTOXMark const*const pTxtMark =
+ m_pImpl->m_pTOXMark->GetTxtTOXMark();
+ SwPaM aPam(pTxtMark->GetTxtNode(), *pTxtMark->GetStart());
+ aPam.SetMark();
+ if(pTxtMark->GetEnd())
+ {
+ aPam.GetPoint()->nContent = *pTxtMark->GetEnd();
+ }
+ else
+ {
+ aPam.GetPoint()->nContent++;
+ }
+
+ m_pImpl->ReplaceTOXMark(*pType, aMark, aPam);
+ }
+ else if (m_pImpl->m_bIsDescriptor)
+ {
+ switch(pEntry->nWID)
+ {
+ case WID_ALT_TEXT:
+ m_pImpl->m_sAltText = lcl_AnyToString(rValue);
+ break;
+ case WID_LEVEL:
+ {
+ const sal_Int16 nVal = lcl_AnyToInt16(rValue);
+ if(nVal >= 0 && nVal < MAXLEVEL)
+ {
+ m_pImpl->m_nLevel = nVal;
+ }
+ else
+ {
+ throw lang::IllegalArgumentException();
+ }
+ }
+ break;
+ case WID_PRIMARY_KEY:
+ m_pImpl->m_sPrimaryKey = lcl_AnyToString(rValue);
+ break;
+ case WID_SECONDARY_KEY:
+ m_pImpl->m_sSecondaryKey = lcl_AnyToString(rValue);
+ break;
+ case WID_TEXT_READING:
+ m_pImpl->m_sTextReading = lcl_AnyToString(rValue);
+ break;
+ case WID_PRIMARY_KEY_READING:
+ m_pImpl->m_sPrimaryKeyReading = lcl_AnyToString(rValue);
+ break;
+ case WID_SECONDARY_KEY_READING:
+ m_pImpl->m_sSecondaryKeyReading = lcl_AnyToString(rValue);
+ break;
+ case WID_USER_IDX_NAME:
+ {
+ OUString sTmp(lcl_AnyToString(rValue));
+ lcl_ConvertTOUNameToUserName(sTmp);
+ m_pImpl->m_sUserIndexName = sTmp;
+ }
+ break;
+ case WID_MAIN_ENTRY:
+ m_pImpl->m_bMainEntry = lcl_AnyToBool(rValue);
+ break;
+ }
+ }
+ else
+ {
+ throw uno::RuntimeException();
+ }
+}
+
+uno::Any SAL_CALL
+SwXDocumentIndexMark::getPropertyValue(const OUString& rPropertyName)
+throw (beans::UnknownPropertyException, lang::WrappedTargetException,
+ uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+
+ uno::Any aRet;
+ SfxItemPropertySimpleEntry const*const pEntry =
+ m_pImpl->m_rPropSet.getPropertyMap()->getByName(rPropertyName);
+ if (!pEntry)
+ {
+ throw beans::UnknownPropertyException(
+ OUString(RTL_CONSTASCII_USTRINGPARAM("Unknown property: "))
+ + rPropertyName,
+ static_cast<cppu::OWeakObject *>(this));
+ }
+ if (::sw::GetDefaultTextContentValue(aRet, rPropertyName, pEntry->nWID))
+ {
+ return aRet;
+ }
+
+ SwTOXType *const pType = m_pImpl->GetTOXType();
+ if (pType && m_pImpl->m_pTOXMark)
+ {
+ switch(pEntry->nWID)
+ {
+ case WID_ALT_TEXT:
+ aRet <<= OUString(m_pImpl->m_pTOXMark->GetAlternativeText());
+ break;
+ case WID_LEVEL:
+ aRet <<= static_cast<sal_Int16>(
+ m_pImpl->m_pTOXMark->GetLevel() - 1);
+ break;
+ case WID_PRIMARY_KEY :
+ aRet <<= OUString(m_pImpl->m_pTOXMark->GetPrimaryKey());
+ break;
+ case WID_SECONDARY_KEY:
+ aRet <<= OUString(m_pImpl->m_pTOXMark->GetSecondaryKey());
+ break;
+ case WID_TEXT_READING:
+ aRet <<= OUString(m_pImpl->m_pTOXMark->GetTextReading());
+ break;
+ case WID_PRIMARY_KEY_READING:
+ aRet <<= OUString(m_pImpl->m_pTOXMark->GetPrimaryKeyReading());
+ break;
+ case WID_SECONDARY_KEY_READING:
+ aRet <<= OUString(
+ m_pImpl->m_pTOXMark->GetSecondaryKeyReading());
+ break;
+ case WID_USER_IDX_NAME :
+ {
+ OUString sTmp(pType->GetTypeName());
+ lcl_ConvertTOUNameToProgrammaticName(sTmp);
+ aRet <<= sTmp;
+ }
+ break;
+ case WID_MAIN_ENTRY:
+ {
+ const sal_Bool bTemp = m_pImpl->m_pTOXMark->IsMainEntry();
+ aRet <<= bTemp;
+ }
+ break;
+ }
+ }
+ else if (m_pImpl->m_bIsDescriptor)
+ {
+ switch(pEntry->nWID)
+ {
+ case WID_ALT_TEXT:
+ aRet <<= m_pImpl->m_sAltText;
+ break;
+ case WID_LEVEL:
+ aRet <<= static_cast<sal_Int16>(m_pImpl->m_nLevel);
+ break;
+ case WID_PRIMARY_KEY:
+ aRet <<= m_pImpl->m_sPrimaryKey;
+ break;
+ case WID_SECONDARY_KEY:
+ aRet <<= m_pImpl->m_sSecondaryKey;
+ break;
+ case WID_TEXT_READING:
+ aRet <<= m_pImpl->m_sTextReading;
+ break;
+ case WID_PRIMARY_KEY_READING:
+ aRet <<= m_pImpl->m_sPrimaryKeyReading;
+ break;
+ case WID_SECONDARY_KEY_READING:
+ aRet <<= m_pImpl->m_sSecondaryKeyReading;
+ break;
+ case WID_USER_IDX_NAME :
+ aRet <<= m_pImpl->m_sUserIndexName;
+ break;
+ case WID_MAIN_ENTRY:
+ {
+ aRet <<= static_cast<sal_Bool>(m_pImpl->m_bMainEntry);
+ }
+ break;
+ }
+ }
+ else
+ {
+ throw uno::RuntimeException();
+ }
+ return aRet;
+}
+
+void SAL_CALL
+SwXDocumentIndexMark::addPropertyChangeListener(
+ const ::rtl::OUString& /*rPropertyName*/,
+ const uno::Reference< beans::XPropertyChangeListener >& /*xListener*/)
+throw (beans::UnknownPropertyException, lang::WrappedTargetException,
+ uno::RuntimeException)
+{
+ OSL_FAIL("SwXDocumentIndexMark::addPropertyChangeListener(): not implemented");
+}
+
+void SAL_CALL
+SwXDocumentIndexMark::removePropertyChangeListener(
+ const ::rtl::OUString& /*rPropertyName*/,
+ const uno::Reference< beans::XPropertyChangeListener >& /*xListener*/)
+throw (beans::UnknownPropertyException, lang::WrappedTargetException,
+ uno::RuntimeException)
+{
+ OSL_FAIL("SwXDocumentIndexMark::removePropertyChangeListener(): not implemented");
+}
+
+void SAL_CALL
+SwXDocumentIndexMark::addVetoableChangeListener(
+ const ::rtl::OUString& /*rPropertyName*/,
+ const uno::Reference< beans::XVetoableChangeListener >& /*xListener*/)
+throw (beans::UnknownPropertyException, lang::WrappedTargetException,
+ uno::RuntimeException)
+{
+ OSL_FAIL("SwXDocumentIndexMark::addVetoableChangeListener(): not implemented");
+}
+
+void SAL_CALL
+SwXDocumentIndexMark::removeVetoableChangeListener(
+ const ::rtl::OUString& /*rPropertyName*/,
+ const uno::Reference< beans::XVetoableChangeListener >& /*xListener*/)
+throw (beans::UnknownPropertyException, lang::WrappedTargetException,
+ uno::RuntimeException)
+{
+ OSL_FAIL("SwXDocumentIndexMark::removeVetoableChangeListener(): not implemented");
+}
+
+/******************************************************************
+ * SwXDocumentIndexes
+ ******************************************************************/
+SwXDocumentIndexes::SwXDocumentIndexes(SwDoc *const _pDoc)
+ : SwUnoCollection(_pDoc)
+{
+}
+
+SwXDocumentIndexes::~SwXDocumentIndexes()
+{
+}
+
+OUString SAL_CALL
+SwXDocumentIndexes::getImplementationName() throw (uno::RuntimeException)
+{
+ return C2U("SwXDocumentIndexes");
+}
+
+static char const*const g_ServicesDocumentIndexes[] =
+{
+ "com.sun.star.text.DocumentIndexes",
+};
+
+static const size_t g_nServicesDocumentIndexes(
+ SAL_N_ELEMENTS(g_ServicesDocumentIndexes));
+
+sal_Bool SAL_CALL
+SwXDocumentIndexes::supportsService(const OUString& rServiceName)
+throw (uno::RuntimeException)
+{
+ return ::sw::SupportsServiceImpl(
+ g_nServicesDocumentIndexes, g_ServicesDocumentIndexes, rServiceName);
+}
+
+uno::Sequence< OUString > SAL_CALL
+SwXDocumentIndexes::getSupportedServiceNames() throw (uno::RuntimeException)
+{
+ return ::sw::GetSupportedServiceNamesImpl(
+ g_nServicesDocumentIndexes, g_ServicesDocumentIndexes);
+}
+
+sal_Int32 SAL_CALL
+SwXDocumentIndexes::getCount() throw (uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+
+ if(!IsValid())
+ throw uno::RuntimeException();
+
+ sal_uInt32 nRet = 0;
+ const SwSectionFmts& rFmts = GetDoc()->GetSections();
+ for( sal_uInt16 n = 0; n < rFmts.Count(); ++n )
+ {
+ const SwSection* pSect = rFmts[ n ]->GetSection();
+ if( TOX_CONTENT_SECTION == pSect->GetType() &&
+ pSect->GetFmt()->GetSectionNode() )
+ {
+ ++nRet;
+ }
+ }
+ return nRet;
+}
+
+uno::Any SAL_CALL
+SwXDocumentIndexes::getByIndex(sal_Int32 nIndex)
+throw (lang::IndexOutOfBoundsException, lang::WrappedTargetException,
+ uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+
+ if(!IsValid())
+ throw uno::RuntimeException();
+
+ sal_Int32 nIdx = 0;
+
+ const SwSectionFmts& rFmts = GetDoc()->GetSections();
+ for( sal_uInt16 n = 0; n < rFmts.Count(); ++n )
+ {
+ const SwSection* pSect = rFmts[ n ]->GetSection();
+ if( TOX_CONTENT_SECTION == pSect->GetType() &&
+ pSect->GetFmt()->GetSectionNode() &&
+ nIdx++ == nIndex )
+ {
+ const uno::Reference< text::XDocumentIndex > xTmp =
+ SwXDocumentIndex::CreateXDocumentIndex(
+ *GetDoc(), static_cast<SwTOXBaseSection const&>(*pSect));
+ uno::Any aRet;
+ aRet <<= xTmp;
+ return aRet;
+ }
+ }
+
+ throw lang::IndexOutOfBoundsException();
+}
+
+uno::Any SAL_CALL
+SwXDocumentIndexes::getByName(const OUString& rName)
+throw (container::NoSuchElementException, lang::WrappedTargetException,
+ uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+
+ if(!IsValid())
+ throw uno::RuntimeException();
+
+ String sToFind(rName);
+ const SwSectionFmts& rFmts = GetDoc()->GetSections();
+ for( sal_uInt16 n = 0; n < rFmts.Count(); ++n )
+ {
+ const SwSection* pSect = rFmts[ n ]->GetSection();
+ if( TOX_CONTENT_SECTION == pSect->GetType() &&
+ pSect->GetFmt()->GetSectionNode() &&
+ (static_cast<SwTOXBaseSection const*>(pSect)->GetTOXName()
+ == sToFind))
+ {
+ const uno::Reference< text::XDocumentIndex > xTmp =
+ SwXDocumentIndex::CreateXDocumentIndex(
+ *GetDoc(), static_cast<SwTOXBaseSection const&>(*pSect));
+ uno::Any aRet;
+ aRet <<= xTmp;
+ return aRet;
+ }
+ }
+ throw container::NoSuchElementException();
+}
+
+uno::Sequence< OUString > SAL_CALL
+SwXDocumentIndexes::getElementNames() throw (uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+
+ if(!IsValid())
+ throw uno::RuntimeException();
+
+ const SwSectionFmts& rFmts = GetDoc()->GetSections();
+ sal_Int32 nCount = 0;
+ sal_uInt16 n;
+ for( n = 0; n < rFmts.Count(); ++n )
+ {
+ SwSection const*const pSect = rFmts[ n ]->GetSection();
+ if( TOX_CONTENT_SECTION == pSect->GetType() &&
+ pSect->GetFmt()->GetSectionNode() )
+ {
+ ++nCount;
+ }
+ }
+
+ uno::Sequence< OUString > aRet(nCount);
+ OUString* pArray = aRet.getArray();
+ sal_uInt16 nCnt;
+ for( n = 0, nCnt = 0; n < rFmts.Count(); ++n )
+ {
+ SwSection const*const pSect = rFmts[ n ]->GetSection();
+ if( TOX_CONTENT_SECTION == pSect->GetType() &&
+ pSect->GetFmt()->GetSectionNode())
+ {
+ pArray[nCnt++] = OUString(
+ static_cast<SwTOXBaseSection const*>(pSect)->GetTOXName());
+ }
+ }
+ return aRet;
+}
+
+sal_Bool SAL_CALL
+SwXDocumentIndexes::hasByName(const OUString& rName)
+throw (uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+
+ if(!IsValid())
+ throw uno::RuntimeException();
+
+ String sToFind(rName);
+ const SwSectionFmts& rFmts = GetDoc()->GetSections();
+ for( sal_uInt16 n = 0; n < rFmts.Count(); ++n )
+ {
+ SwSection const*const pSect = rFmts[ n ]->GetSection();
+ if( TOX_CONTENT_SECTION == pSect->GetType() &&
+ pSect->GetFmt()->GetSectionNode())
+ {
+ if (static_cast<SwTOXBaseSection const*>(pSect)->GetTOXName()
+ == sToFind)
+ {
+ return sal_True;
+ }
+ }
+ }
+ return sal_False;
+}
+
+uno::Type SAL_CALL
+SwXDocumentIndexes::getElementType() throw (uno::RuntimeException)
+{
+ return text::XDocumentIndex::static_type();
+}
+
+sal_Bool SAL_CALL
+SwXDocumentIndexes::hasElements() throw (uno::RuntimeException)
+{
+ return 0 != getCount();
+}
+
+/******************************************************************
+ * SwXDocumentIndex::StyleAccess_Impl
+ ******************************************************************/
+SwXDocumentIndex::StyleAccess_Impl::StyleAccess_Impl(
+ SwXDocumentIndex& rParentIdx)
+ : m_xParent(&rParentIdx)
+{
+}
+
+SwXDocumentIndex::StyleAccess_Impl::~StyleAccess_Impl()
+{
+}
+
+OUString SAL_CALL
+SwXDocumentIndex::StyleAccess_Impl::getImplementationName()
+throw (uno::RuntimeException)
+{
+ return C2U("SwXDocumentIndex::StyleAccess_Impl");
+}
+
+static char const*const g_ServicesIndexStyleAccess[] =
+{
+ "com.sun.star.text.DocumentIndexParagraphStyles",
+};
+
+static const size_t g_nServicesIndexStyleAccess(
+ SAL_N_ELEMENTS(g_ServicesIndexStyleAccess));
+
+sal_Bool SAL_CALL
+SwXDocumentIndex::StyleAccess_Impl::supportsService(
+ const OUString& rServiceName)
+throw (uno::RuntimeException)
+{
+ return ::sw::SupportsServiceImpl(
+ g_nServicesIndexStyleAccess, g_ServicesIndexStyleAccess, rServiceName);
+}
+
+uno::Sequence< OUString > SAL_CALL
+SwXDocumentIndex::StyleAccess_Impl::getSupportedServiceNames()
+throw (uno::RuntimeException)
+{
+ return ::sw::GetSupportedServiceNamesImpl(
+ g_nServicesIndexStyleAccess, g_ServicesIndexStyleAccess);
+}
+
+void SAL_CALL
+SwXDocumentIndex::StyleAccess_Impl::replaceByIndex(
+ sal_Int32 nIndex, const uno::Any& rElement)
+throw (lang::IllegalArgumentException, lang::IndexOutOfBoundsException,
+ lang::WrappedTargetException, uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+
+ if(nIndex < 0 || nIndex > MAXLEVEL)
+ {
+ throw lang::IndexOutOfBoundsException();
+ }
+
+ SwTOXBase & rTOXBase( m_xParent->m_pImpl->GetTOXSectionOrThrow() );
+
+ uno::Sequence<OUString> aSeq;
+ if(!(rElement >>= aSeq))
+ {
+ throw lang::IllegalArgumentException();
+ }
+
+ const sal_Int32 nStyles = aSeq.getLength();
+ const OUString* pStyles = aSeq.getConstArray();
+ String sSetStyles;
+ String aString;
+ for(sal_Int32 i = 0; i < nStyles; i++)
+ {
+ if(i)
+ {
+ sSetStyles += TOX_STYLE_DELIMITER;
+ }
+ SwStyleNameMapper::FillUIName(pStyles[i], aString,
+ nsSwGetPoolIdFromName::GET_POOLID_TXTCOLL, sal_True);
+ sSetStyles += aString;
+ }
+ rTOXBase.SetStyleNames(sSetStyles, static_cast<sal_uInt16>(nIndex));
+}
+
+sal_Int32 SAL_CALL
+SwXDocumentIndex::StyleAccess_Impl::getCount() throw (uno::RuntimeException)
+{
+ return MAXLEVEL;
+}
+
+uno::Any SAL_CALL
+SwXDocumentIndex::StyleAccess_Impl::getByIndex(sal_Int32 nIndex)
+throw (lang::IndexOutOfBoundsException, lang::WrappedTargetException,
+ uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+
+ if(nIndex < 0 || nIndex > MAXLEVEL)
+ {
+ throw lang::IndexOutOfBoundsException();
+ }
+
+ SwTOXBase & rTOXBase( m_xParent->m_pImpl->GetTOXSectionOrThrow() );
+
+ const String& rStyles =
+ rTOXBase.GetStyleNames(static_cast<sal_uInt16>(nIndex));
+ const sal_uInt16 nStyles = rStyles.GetTokenCount(TOX_STYLE_DELIMITER);
+ uno::Sequence<OUString> aStyles(nStyles);
+ OUString* pStyles = aStyles.getArray();
+ String aString;
+ for(sal_uInt16 i = 0; i < nStyles; i++)
+ {
+ SwStyleNameMapper::FillProgName(
+ rStyles.GetToken(i, TOX_STYLE_DELIMITER),
+ aString,
+ nsSwGetPoolIdFromName::GET_POOLID_TXTCOLL,
+ sal_True);
+ pStyles[i] = OUString( aString );
+ }
+ uno::Any aRet(&aStyles, ::getCppuType((uno::Sequence<OUString>*)0));
+ return aRet;
+}
+
+uno::Type SAL_CALL
+SwXDocumentIndex::StyleAccess_Impl::getElementType()
+throw (uno::RuntimeException)
+{
+ return ::getCppuType((uno::Sequence<OUString>*)0);
+}
+
+sal_Bool SAL_CALL
+SwXDocumentIndex::StyleAccess_Impl::hasElements() throw (uno::RuntimeException)
+{
+ return sal_True;
+}
+
+/******************************************************************
+ * SwXDocumentIndex::TokenAccess_Impl
+ ******************************************************************/
+SwXDocumentIndex::TokenAccess_Impl::TokenAccess_Impl(
+ SwXDocumentIndex& rParentIdx)
+ : m_xParent(&rParentIdx)
+{
+}
+
+SwXDocumentIndex::TokenAccess_Impl::~TokenAccess_Impl()
+{
+}
+
+OUString SAL_CALL
+SwXDocumentIndex::TokenAccess_Impl::getImplementationName()
+throw (uno::RuntimeException)
+{
+ return C2U("SwXDocumentIndex::TokenAccess_Impl");
+}
+
+static char const*const g_ServicesIndexTokenAccess[] =
+{
+ "com.sun.star.text.DocumentIndexLevelFormat",
+};
+
+static const size_t g_nServicesIndexTokenAccess(
+ SAL_N_ELEMENTS(g_ServicesIndexTokenAccess));
+
+sal_Bool SAL_CALL
+SwXDocumentIndex::TokenAccess_Impl::supportsService(
+ const OUString& rServiceName)
+throw (uno::RuntimeException)
+{
+ return ::sw::SupportsServiceImpl(
+ g_nServicesIndexTokenAccess, g_ServicesIndexTokenAccess, rServiceName);
+}
+
+uno::Sequence< OUString > SAL_CALL
+SwXDocumentIndex::TokenAccess_Impl::getSupportedServiceNames()
+throw (uno::RuntimeException)
+{
+ return ::sw::GetSupportedServiceNamesImpl(
+ g_nServicesIndexTokenAccess, g_ServicesIndexTokenAccess);
+}
+
+struct TokenType {
+ const char *pName;
+ const enum FormTokenType eTokenType;
+};
+
+static const struct TokenType g_TokenTypes[] =
+{
+ { "TokenEntryNumber", TOKEN_ENTRY_NO },
+ { "TokenEntryText", TOKEN_ENTRY_TEXT },
+ { "TokenTabStop", TOKEN_TAB_STOP },
+ { "TokenText", TOKEN_TEXT },
+ { "TokenPageNumber", TOKEN_PAGE_NUMS },
+ { "TokenChapterInfo", TOKEN_CHAPTER_INFO },
+ { "TokenHyperlinkStart", TOKEN_LINK_START },
+ { "TokenHyperlinkEnd", TOKEN_LINK_END },
+ { "TokenBibliographyDataField", TOKEN_AUTHORITY },
+ { 0, static_cast<enum FormTokenType>(0) }
+};
+
+void SAL_CALL
+SwXDocumentIndex::TokenAccess_Impl::replaceByIndex(
+ sal_Int32 nIndex, const uno::Any& rElement)
+throw (lang::IllegalArgumentException, lang::IndexOutOfBoundsException,
+ lang::WrappedTargetException, uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+
+ SwTOXBase & rTOXBase( m_xParent->m_pImpl->GetTOXSectionOrThrow() );
+
+ if ((nIndex < 0) || (nIndex > rTOXBase.GetTOXForm().GetFormMax()))
+ {
+ throw lang::IndexOutOfBoundsException();
+ }
+
+ uno::Sequence<beans::PropertyValues> aSeq;
+ if(!(rElement >>= aSeq))
+ {
+ throw lang::IllegalArgumentException();
+ }
+
+ String sPattern;
+ const sal_Int32 nTokens = aSeq.getLength();
+ const beans::PropertyValues* pTokens = aSeq.getConstArray();
+ for(sal_Int32 i = 0; i < nTokens; i++)
+ {
+ const beans::PropertyValue* pProperties = pTokens[i].getConstArray();
+ const sal_Int32 nProperties = pTokens[i].getLength();
+ //create an invalid token
+ SwFormToken aToken(TOKEN_END);
+ for(sal_Int32 j = 0; j < nProperties; j++)
+ {
+ if (pProperties[j].Name.equalsAsciiL(
+ RTL_CONSTASCII_STRINGPARAM("TokenType")))
+ {
+ const OUString sTokenType =
+ lcl_AnyToString(pProperties[j].Value);
+ for (TokenType const* pTokenType = g_TokenTypes;
+ pTokenType->pName; ++pTokenType)
+ {
+ if (sTokenType.equalsAscii(pTokenType->pName))
+ {
+ aToken.eTokenType = pTokenType->eTokenType;
+ break;
+ }
+ }
+ }
+ else if (pProperties[j].Name.equalsAsciiL(
+ RTL_CONSTASCII_STRINGPARAM("CharacterStyleName")))
+ {
+ String sCharStyleName;
+ SwStyleNameMapper::FillUIName(
+ lcl_AnyToString(pProperties[j].Value),
+ sCharStyleName,
+ nsSwGetPoolIdFromName::GET_POOLID_CHRFMT,
+ sal_True);
+ aToken.sCharStyleName = sCharStyleName;
+ aToken.nPoolId = SwStyleNameMapper::GetPoolIdFromUIName (
+ sCharStyleName, nsSwGetPoolIdFromName::GET_POOLID_CHRFMT );
+ }
+ else if (pProperties[j].Name.equalsAsciiL(
+ RTL_CONSTASCII_STRINGPARAM("TabStopRightAligned")))
+ {
+ const sal_Bool bRight = lcl_AnyToBool(pProperties[j].Value);
+ aToken.eTabAlign = bRight ?
+ SVX_TAB_ADJUST_END : SVX_TAB_ADJUST_LEFT;
+ }
+ else if (pProperties[j].Name.equalsAsciiL(
+ RTL_CONSTASCII_STRINGPARAM("TabStopPosition")))
+ {
+ sal_Int32 nPosition = 0;
+ if (!(pProperties[j].Value >>= nPosition))
+ {
+ throw lang::IllegalArgumentException();
+ }
+ nPosition = MM100_TO_TWIP(nPosition);
+ if(nPosition < 0)
+ {
+ throw lang::IllegalArgumentException();
+ }
+ aToken.nTabStopPosition = nPosition;
+ }
+ else if (pProperties[j].Name.equalsAsciiL(
+ RTL_CONSTASCII_STRINGPARAM("TabStopFillCharacter")))
+ {
+ const OUString sFillChar =
+ lcl_AnyToString(pProperties[j].Value);
+ if (sFillChar.getLength() > 1)
+ {
+ throw lang::IllegalArgumentException();
+ }
+ aToken.cTabFillChar =
+ (sFillChar.getLength()) ? sFillChar[0] : ' ';
+ }
+ else if (pProperties[j].Name.equalsAsciiL(
+ RTL_CONSTASCII_STRINGPARAM("Text")))
+ {
+ const OUString sText = lcl_AnyToString(pProperties[j].Value);
+ aToken.sText = sText;
+ }
+ else if (pProperties[j].Name.equalsAsciiL(
+ RTL_CONSTASCII_STRINGPARAM("ChapterFormat")))
+ {
+ sal_Int16 nFormat = lcl_AnyToInt16(pProperties[j].Value);
+ switch(nFormat)
+ {
+ case text::ChapterFormat::NUMBER:
+ nFormat = CF_NUMBER;
+ break;
+ case text::ChapterFormat::NAME:
+ nFormat = CF_TITLE;
+ break;
+ case text::ChapterFormat::NAME_NUMBER:
+ nFormat = CF_NUM_TITLE;
+ break;
+ case text::ChapterFormat::NO_PREFIX_SUFFIX:
+ nFormat = CF_NUMBER_NOPREPST;
+ break;
+ case text::ChapterFormat::DIGIT:
+ nFormat = CF_NUM_NOPREPST_TITLE;
+ break;
+ default:
+ throw lang::IllegalArgumentException();
+ }
+ aToken.nChapterFormat = nFormat;
+ }
+// #i53420#
+ else if (pProperties[j].Name.equalsAsciiL(
+ RTL_CONSTASCII_STRINGPARAM("ChapterLevel")))
+ {
+ const sal_Int16 nLevel = lcl_AnyToInt16(pProperties[j].Value);
+ if( nLevel < 1 || nLevel > MAXLEVEL )
+ {
+ throw lang::IllegalArgumentException();
+ }
+ aToken.nOutlineLevel = nLevel;
+ }
+ else if (pProperties[j].Name.equalsAsciiL(
+ RTL_CONSTASCII_STRINGPARAM("BibliographyDataField")))
+ {
+ sal_Int16 nType = 0;
+ pProperties[j].Value >>= nType;
+ if(nType < 0 || nType > text::BibliographyDataField::ISBN)
+ {
+ lang::IllegalArgumentException aExcept;
+ aExcept.Message = C2U("BibliographyDataField - wrong value");
+ aExcept.ArgumentPosition = static_cast< sal_Int16 >(j);
+ throw aExcept;
+ }
+ aToken.nAuthorityField = nType;
+ }
+ // #i21237#
+ else if (pProperties[j].Name.equalsAsciiL(
+ RTL_CONSTASCII_STRINGPARAM("WithTab")))
+ {
+ aToken.bWithTab = lcl_AnyToBool(pProperties[j].Value);
+ }
+
+ }
+ //exception if wrong TokenType
+ if(TOKEN_END <= aToken.eTokenType )
+ {
+ throw lang::IllegalArgumentException();
+ }
+ // set TokenType from TOKEN_ENTRY_TEXT to TOKEN_ENTRY if it is
+ // not a content index
+ if(TOKEN_ENTRY_TEXT == aToken.eTokenType &&
+ (TOX_CONTENT != rTOXBase.GetType()))
+ {
+ aToken.eTokenType = TOKEN_ENTRY;
+ }
+// #i53420#
+// check for chapter format allowed values if it was TOKEN_ENTRY_NO type
+// only allowed value are CF_NUMBER and CF_NUM_NOPREPST_TITLE
+// reading from file
+ if( TOKEN_ENTRY_NO == aToken.eTokenType )
+ {
+ switch(aToken.nChapterFormat)
+ {
+ case CF_NUMBER:
+ case CF_NUM_NOPREPST_TITLE:
+ break;
+ default:
+ throw lang::IllegalArgumentException();
+ }
+ }
+ sPattern += aToken.GetString();
+ }
+ SwForm aForm(rTOXBase.GetTOXForm());
+ aForm.SetPattern(static_cast<sal_uInt16>(nIndex), sPattern);
+ rTOXBase.SetTOXForm(aForm);
+}
+
+sal_Int32 SAL_CALL
+SwXDocumentIndex::TokenAccess_Impl::getCount() throw (uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+
+ const sal_Int32 nRet = m_xParent->m_pImpl->GetFormMax();
+ return nRet;
+}
+
+uno::Any SAL_CALL
+SwXDocumentIndex::TokenAccess_Impl::getByIndex(sal_Int32 nIndex)
+throw (lang::IndexOutOfBoundsException, lang::WrappedTargetException,
+ uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+
+ SwTOXBase & rTOXBase( m_xParent->m_pImpl->GetTOXSectionOrThrow() );
+
+ if ((nIndex < 0) || (nIndex > rTOXBase.GetTOXForm().GetFormMax()))
+ {
+ throw lang::IndexOutOfBoundsException();
+ }
+
+ // #i21237#
+ SwFormTokens aPattern = rTOXBase.GetTOXForm().
+ GetPattern(static_cast<sal_uInt16>(nIndex));
+ SwFormTokens::iterator aIt = aPattern.begin();
+
+ sal_uInt16 nTokenCount = 0;
+ uno::Sequence< beans::PropertyValues > aRetSeq;
+ String aString;
+ while(aIt != aPattern.end()) // #i21237#
+ {
+ nTokenCount++;
+ aRetSeq.realloc(nTokenCount);
+ beans::PropertyValues* pTokenProps = aRetSeq.getArray();
+ SwFormToken aToken = *aIt; // #i21237#
+
+ uno::Sequence< beans::PropertyValue >& rCurTokenSeq =
+ pTokenProps[nTokenCount-1];
+ SwStyleNameMapper::FillProgName(
+ aToken.sCharStyleName,
+ aString,
+ nsSwGetPoolIdFromName::GET_POOLID_CHRFMT,
+ sal_True );
+ const OUString aProgCharStyle( aString );
+ switch(aToken.eTokenType)
+ {
+ case TOKEN_ENTRY_NO:
+ {
+// #i53420#
+// writing to file (from doc to properties)
+ sal_Int32 nElements = 2;
+ sal_Int32 nCurrentElement = 0;
+
+ // check for default value
+ if (aToken.nChapterFormat != CF_NUMBER)
+ {
+ nElements++;//we need the element
+ }
+ if( aToken.nOutlineLevel != MAXLEVEL )
+ {
+ nElements++;
+ }
+
+ rCurTokenSeq.realloc( nElements );
+
+ beans::PropertyValue* pArr = rCurTokenSeq.getArray();
+
+ pArr[nCurrentElement].Name = C2U("TokenType");
+ pArr[nCurrentElement++].Value <<=
+ OUString(RTL_CONSTASCII_USTRINGPARAM("TokenEntryNumber"));
+
+ pArr[nCurrentElement].Name = C2U("CharacterStyleName");
+ pArr[nCurrentElement++].Value <<= aProgCharStyle;
+ if( aToken.nChapterFormat != CF_NUMBER )
+ {
+ pArr[nCurrentElement].Name = C2U("ChapterFormat");
+ sal_Int16 nVal;
+// the allowed values for chapter format, when used as entry number,
+// are CF_NUMBER and CF_NUM_NOPREPST_TITLE only, all else forced to
+//CF_NUMBER
+ switch(aToken.nChapterFormat)
+ {
+ default:
+ case CF_NUMBER:
+ nVal = text::ChapterFormat::NUMBER;
+ break;
+ case CF_NUM_NOPREPST_TITLE:
+ nVal = text::ChapterFormat::DIGIT;
+ break;
+ }
+ pArr[nCurrentElement++].Value <<= nVal;
+ }
+
+ // only a ChapterLevel != MAXLEVEL is registered
+ if (aToken.nOutlineLevel != MAXLEVEL)
+ {
+ pArr[nCurrentElement].Name = C2U("ChapterLevel");
+ pArr[nCurrentElement].Value <<= aToken.nOutlineLevel;
+ }
+ }
+ break;
+ case TOKEN_ENTRY: // no difference between Entry and Entry Text
+ case TOKEN_ENTRY_TEXT:
+ {
+ rCurTokenSeq.realloc( 2 );
+ beans::PropertyValue* pArr = rCurTokenSeq.getArray();
+
+ pArr[0].Name = C2U("TokenType");
+ pArr[0].Value <<= OUString(RTL_CONSTASCII_USTRINGPARAM("TokenEntryText"));
+
+ pArr[1].Name = C2U("CharacterStyleName");
+ pArr[1].Value <<= aProgCharStyle;
+ }
+ break;
+ case TOKEN_TAB_STOP:
+ {
+ rCurTokenSeq.realloc(5); // #i21237#
+ beans::PropertyValue* pArr = rCurTokenSeq.getArray();
+
+ pArr[0].Name = C2U("TokenType");
+ pArr[0].Value <<= OUString(RTL_CONSTASCII_USTRINGPARAM("TokenTabStop"));
+
+ if(SVX_TAB_ADJUST_END == aToken.eTabAlign)
+ {
+ pArr[1].Name = C2U("TabStopRightAligned");
+ sal_Bool bTemp = sal_True;
+ pArr[1].Value.setValue(&bTemp, ::getCppuBooleanType());
+ }
+ else
+ {
+ pArr[1].Name = C2U("TabStopPosition");
+ sal_Int32 nPos = (TWIP_TO_MM100(aToken.nTabStopPosition));
+ if(nPos < 0)
+ nPos = 0;
+ pArr[1].Value <<= (sal_Int32)nPos;
+ }
+ pArr[2].Name = C2U("TabStopFillCharacter");
+ pArr[2].Value <<= OUString(aToken.cTabFillChar);
+ pArr[3].Name = C2U("CharacterStyleName");
+ pArr[3].Value <<= aProgCharStyle;
+ // #i21237#
+ pArr[4].Name = C2U("WithTab");
+ pArr[4].Value <<= static_cast<sal_Bool>(aToken.bWithTab);
+ }
+ break;
+ case TOKEN_TEXT:
+ {
+ rCurTokenSeq.realloc( 3 );
+ beans::PropertyValue* pArr = rCurTokenSeq.getArray();
+
+ pArr[0].Name = C2U("TokenType");
+ pArr[0].Value <<= OUString(RTL_CONSTASCII_USTRINGPARAM("TokenText"));
+
+ pArr[1].Name = C2U("CharacterStyleName");
+ pArr[1].Value <<= aProgCharStyle;
+
+ pArr[2].Name = C2U("Text");
+ pArr[2].Value <<= OUString(aToken.sText);
+ }
+ break;
+ case TOKEN_PAGE_NUMS:
+ {
+ rCurTokenSeq.realloc( 2 );
+ beans::PropertyValue* pArr = rCurTokenSeq.getArray();
+
+ pArr[0].Name = C2U("TokenType");
+ pArr[0].Value <<= OUString(RTL_CONSTASCII_USTRINGPARAM("TokenPageNumber"));
+
+ pArr[1].Name = C2U("CharacterStyleName");
+ pArr[1].Value <<= aProgCharStyle;
+ }
+ break;
+ case TOKEN_CHAPTER_INFO:
+ {
+ rCurTokenSeq.realloc( 4 );
+ beans::PropertyValue* pArr = rCurTokenSeq.getArray();
+
+ pArr[0].Name = C2U("TokenType");
+ pArr[0].Value <<= OUString(RTL_CONSTASCII_USTRINGPARAM("TokenChapterInfo"));
+
+ pArr[1].Name = C2U("CharacterStyleName");
+ pArr[1].Value <<= aProgCharStyle;
+
+ pArr[2].Name = C2U("ChapterFormat");
+ sal_Int16 nVal = text::ChapterFormat::NUMBER;
+ switch(aToken.nChapterFormat)
+ {
+ case CF_NUMBER:
+ nVal = text::ChapterFormat::NUMBER;
+ break;
+ case CF_TITLE:
+ nVal = text::ChapterFormat::NAME;
+ break;
+ case CF_NUM_TITLE:
+ nVal = text::ChapterFormat::NAME_NUMBER;
+ break;
+ case CF_NUMBER_NOPREPST:
+ nVal = text::ChapterFormat::NO_PREFIX_SUFFIX;
+ break;
+ case CF_NUM_NOPREPST_TITLE:
+ nVal = text::ChapterFormat::DIGIT;
+ break;
+ }
+ pArr[2].Value <<= nVal;
+// #i53420#
+ pArr[3].Name = C2U("ChapterLevel");
+ pArr[3].Value <<= aToken.nOutlineLevel;
+ }
+ break;
+ case TOKEN_LINK_START:
+ {
+ rCurTokenSeq.realloc( 2 );
+ beans::PropertyValue* pArr = rCurTokenSeq.getArray();
+
+ pArr[0].Name = C2U("TokenType");
+ pArr[0].Value <<=
+ OUString(RTL_CONSTASCII_USTRINGPARAM("TokenHyperlinkStart"));
+ pArr[1].Name = C2U("CharacterStyleName");
+ pArr[1].Value <<= aProgCharStyle;
+ }
+ break;
+ case TOKEN_LINK_END:
+ {
+ rCurTokenSeq.realloc( 1 );
+ beans::PropertyValue* pArr = rCurTokenSeq.getArray();
+
+ pArr[0].Name = C2U("TokenType");
+ pArr[0].Value <<=
+ OUString(RTL_CONSTASCII_USTRINGPARAM("TokenHyperlinkEnd"));
+ }
+ break;
+ case TOKEN_AUTHORITY:
+ {
+ rCurTokenSeq.realloc( 3 );
+ beans::PropertyValue* pArr = rCurTokenSeq.getArray();
+
+ pArr[0].Name = C2U("TokenType");
+ pArr[0].Value <<=
+ OUString(RTL_CONSTASCII_USTRINGPARAM("TokenBibliographyDataField"));
+
+ pArr[1].Name = C2U("CharacterStyleName");
+ pArr[1].Value <<= aProgCharStyle;
+
+ pArr[2].Name = C2U("BibliographyDataField");
+ pArr[2].Value <<= sal_Int16(aToken.nAuthorityField);
+ }
+ break;
+
+ default:
+ ;
+ }
+
+ ++aIt; // #i21237#
+ }
+
+ uno::Any aRet;
+ aRet <<= aRetSeq;
+ return aRet;
+}
+
+uno::Type SAL_CALL
+SwXDocumentIndex::TokenAccess_Impl::getElementType()
+throw (uno::RuntimeException)
+{
+ return ::getCppuType((uno::Sequence< beans::PropertyValues >*)0);
+}
+
+sal_Bool SAL_CALL
+SwXDocumentIndex::TokenAccess_Impl::hasElements()
+throw (uno::RuntimeException)
+{
+ return sal_True;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/unocore/unomap.cxx b/sw/source/core/unocore/unomap.cxx
new file mode 100644
index 000000000000..439396eef41d
--- /dev/null
+++ b/sw/source/core/unocore/unomap.cxx
@@ -0,0 +1,3061 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+#include <hintids.hxx>
+
+#include <svx/svxids.hrc>
+#include <comphelper/TypeGeneration.hxx>
+#include <com/sun/star/beans/PropertyAttribute.hpp>
+#include <com/sun/star/text/PageNumberType.hpp>
+#include <com/sun/star/script/XLibraryContainer.hpp>
+// #i28749#
+#include <com/sun/star/drawing/HomogenMatrix3.hpp>
+#include <swtypes.hxx>
+#include <unomap.hxx>
+#include <unoprnms.hxx>
+#include <unomid.h>
+#include <cmdid.h>
+#include <unofldmid.h>
+#include <editeng/memberids.hrc>
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::beans;
+using ::rtl::OUString;
+using namespace ::comphelper;
+
+#define SW_PROP_NMID(id) ((const char*)id), 0
+
+#ifndef MID_TXT_LMARGIN
+#define MID_TXT_LMARGIN 11
+#endif
+
+/******************************************************************************
+ UI-Maps
+******************************************************************************/
+
+SwUnoPropertyMapProvider aSwMapProvider;
+
+SwUnoPropertyMapProvider::SwUnoPropertyMapProvider()
+{
+ for( sal_uInt16 i = 0; i < PROPERTY_MAP_END; i++ )
+ {
+ aMapEntriesArr[i] = 0;
+ aPropertySetArr[i] = 0;
+ }
+}
+
+SwUnoPropertyMapProvider::~SwUnoPropertyMapProvider()
+{
+}
+
+#define _STANDARD_FONT_PROPERTIES \
+ { SW_PROP_NMID(UNO_NAME_CHAR_HEIGHT), RES_CHRATR_FONTSIZE , CPPU_E2T(CPPUTYPE_FLOAT), PropertyAttribute::MAYBEVOID, MID_FONTHEIGHT|CONVERT_TWIPS}, \
+ { SW_PROP_NMID(UNO_NAME_CHAR_WEIGHT), RES_CHRATR_WEIGHT , CPPU_E2T(CPPUTYPE_FLOAT), PropertyAttribute::MAYBEVOID, MID_WEIGHT}, \
+ { SW_PROP_NMID(UNO_NAME_CHAR_FONT_NAME), RES_CHRATR_FONT, CPPU_E2T(CPPUTYPE_OUSTRING), PropertyAttribute::MAYBEVOID, MID_FONT_FAMILY_NAME }, \
+ { SW_PROP_NMID(UNO_NAME_CHAR_FONT_STYLE_NAME), RES_CHRATR_FONT, CPPU_E2T(CPPUTYPE_OUSTRING), PropertyAttribute::MAYBEVOID, MID_FONT_STYLE_NAME }, \
+ { SW_PROP_NMID(UNO_NAME_CHAR_FONT_FAMILY), RES_CHRATR_FONT, CPPU_E2T(CPPUTYPE_INT16), PropertyAttribute::MAYBEVOID, MID_FONT_FAMILY }, \
+ { SW_PROP_NMID(UNO_NAME_CHAR_FONT_CHAR_SET), RES_CHRATR_FONT, CPPU_E2T(CPPUTYPE_INT16), PropertyAttribute::MAYBEVOID, MID_FONT_CHAR_SET }, \
+ { SW_PROP_NMID(UNO_NAME_CHAR_FONT_PITCH), RES_CHRATR_FONT, CPPU_E2T(CPPUTYPE_INT16), PropertyAttribute::MAYBEVOID, MID_FONT_PITCH }, \
+ { SW_PROP_NMID(UNO_NAME_CHAR_POSTURE), RES_CHRATR_POSTURE , CPPU_E2T(CPPUTYPE_FONTSLANT), PropertyAttribute::MAYBEVOID, MID_POSTURE}, \
+ { SW_PROP_NMID(UNO_NAME_CHAR_LOCALE), RES_CHRATR_LANGUAGE , CPPU_E2T(CPPUTYPE_LOCALE) , PropertyAttribute::MAYBEVOID, MID_LANG_LOCALE },
+
+#define _CJK_FONT_PROPERTIES \
+ { SW_PROP_NMID(UNO_NAME_CHAR_HEIGHT_ASIAN), RES_CHRATR_CJK_FONTSIZE , CPPU_E2T(CPPUTYPE_FLOAT), PropertyAttribute::MAYBEVOID, MID_FONTHEIGHT|CONVERT_TWIPS}, \
+ { SW_PROP_NMID(UNO_NAME_CHAR_WEIGHT_ASIAN), RES_CHRATR_CJK_WEIGHT , CPPU_E2T(CPPUTYPE_FLOAT), PropertyAttribute::MAYBEVOID, MID_WEIGHT}, \
+ { SW_PROP_NMID(UNO_NAME_CHAR_FONT_NAME_ASIAN), RES_CHRATR_CJK_FONT, CPPU_E2T(CPPUTYPE_OUSTRING), PropertyAttribute::MAYBEVOID, MID_FONT_FAMILY_NAME }, \
+ { SW_PROP_NMID(UNO_NAME_CHAR_FONT_STYLE_NAME_ASIAN), RES_CHRATR_CJK_FONT, CPPU_E2T(CPPUTYPE_OUSTRING), PropertyAttribute::MAYBEVOID, MID_FONT_STYLE_NAME }, \
+ { SW_PROP_NMID(UNO_NAME_CHAR_FONT_FAMILY_ASIAN), RES_CHRATR_CJK_FONT, CPPU_E2T(CPPUTYPE_INT16), PropertyAttribute::MAYBEVOID, MID_FONT_FAMILY }, \
+ { SW_PROP_NMID(UNO_NAME_CHAR_FONT_CHAR_SET_ASIAN), RES_CHRATR_CJK_FONT, CPPU_E2T(CPPUTYPE_INT16), PropertyAttribute::MAYBEVOID, MID_FONT_CHAR_SET }, \
+ { SW_PROP_NMID(UNO_NAME_CHAR_FONT_PITCH_ASIAN), RES_CHRATR_CJK_FONT, CPPU_E2T(CPPUTYPE_INT16), PropertyAttribute::MAYBEVOID, MID_FONT_PITCH }, \
+ { SW_PROP_NMID(UNO_NAME_CHAR_POSTURE_ASIAN), RES_CHRATR_CJK_POSTURE , CPPU_E2T(CPPUTYPE_FONTSLANT), PropertyAttribute::MAYBEVOID, MID_POSTURE}, \
+ { SW_PROP_NMID(UNO_NAME_CHAR_LOCALE_ASIAN), RES_CHRATR_CJK_LANGUAGE , CPPU_E2T(CPPUTYPE_LOCALE) , PropertyAttribute::MAYBEVOID, MID_LANG_LOCALE },
+
+#define _CTL_FONT_PROPERTIES \
+ { SW_PROP_NMID(UNO_NAME_CHAR_HEIGHT_COMPLEX), RES_CHRATR_CTL_FONTSIZE , CPPU_E2T(CPPUTYPE_FLOAT), PropertyAttribute::MAYBEVOID, MID_FONTHEIGHT|CONVERT_TWIPS},\
+ { SW_PROP_NMID(UNO_NAME_CHAR_WEIGHT_COMPLEX), RES_CHRATR_CTL_WEIGHT , CPPU_E2T(CPPUTYPE_FLOAT), PropertyAttribute::MAYBEVOID, MID_WEIGHT}, \
+ { SW_PROP_NMID(UNO_NAME_CHAR_FONT_NAME_COMPLEX), RES_CHRATR_CTL_FONT, CPPU_E2T(CPPUTYPE_OUSTRING), PropertyAttribute::MAYBEVOID, MID_FONT_FAMILY_NAME }, \
+ { SW_PROP_NMID(UNO_NAME_CHAR_FONT_STYLE_NAME_COMPLEX), RES_CHRATR_CTL_FONT, CPPU_E2T(CPPUTYPE_OUSTRING), PropertyAttribute::MAYBEVOID, MID_FONT_STYLE_NAME }, \
+ { SW_PROP_NMID(UNO_NAME_CHAR_FONT_FAMILY_COMPLEX), RES_CHRATR_CTL_FONT, CPPU_E2T(CPPUTYPE_INT16), PropertyAttribute::MAYBEVOID, MID_FONT_FAMILY }, \
+ { SW_PROP_NMID(UNO_NAME_CHAR_FONT_CHAR_SET_COMPLEX), RES_CHRATR_CTL_FONT, CPPU_E2T(CPPUTYPE_INT16), PropertyAttribute::MAYBEVOID, MID_FONT_CHAR_SET }, \
+ { SW_PROP_NMID(UNO_NAME_CHAR_FONT_PITCH_COMPLEX), RES_CHRATR_CTL_FONT, CPPU_E2T(CPPUTYPE_INT16), PropertyAttribute::MAYBEVOID, MID_FONT_PITCH }, \
+ { SW_PROP_NMID(UNO_NAME_CHAR_POSTURE_COMPLEX), RES_CHRATR_CTL_POSTURE , CPPU_E2T(CPPUTYPE_FONTSLANT), PropertyAttribute::MAYBEVOID, MID_POSTURE}, \
+ { SW_PROP_NMID(UNO_NAME_CHAR_LOCALE_COMPLEX), RES_CHRATR_CTL_LANGUAGE , CPPU_E2T(CPPUTYPE_LOCALE) , PropertyAttribute::MAYBEVOID, MID_LANG_LOCALE },
+
+#define _REDLINE_NODE_PROPERTIES \
+ { SW_PROP_NMID(UNO_NAME_START_REDLINE), FN_UNO_REDLINE_NODE_START , CPPU_E2T(CPPUTYPE_PROPERTYVALUE), PropertyAttribute::MAYBEVOID|PropertyAttribute::READONLY, 0xff }, \
+ { SW_PROP_NMID(UNO_NAME_END_REDLINE), FN_UNO_REDLINE_NODE_END , CPPU_E2T(CPPUTYPE_PROPERTYVALUE), PropertyAttribute::MAYBEVOID|PropertyAttribute::READONLY, 0xff },
+
+#define _REDLINE_PROPERTIES \
+ {SW_PROP_NMID(UNO_NAME_REDLINE_AUTHOR), 0, CPPU_E2T(CPPUTYPE_OUSTRING), PropertyAttribute::MAYBEVOID|PropertyAttribute::READONLY, 0},\
+ {SW_PROP_NMID(UNO_NAME_REDLINE_DATE_TIME), 0, CPPU_E2T(CPPUTYPE_DATETIME), PropertyAttribute::MAYBEVOID|PropertyAttribute::READONLY, 0},\
+ {SW_PROP_NMID(UNO_NAME_REDLINE_COMMENT), 0, CPPU_E2T(CPPUTYPE_OUSTRING), PropertyAttribute::MAYBEVOID|PropertyAttribute::READONLY, 0},\
+ {SW_PROP_NMID(UNO_NAME_REDLINE_TYPE), 0, CPPU_E2T(CPPUTYPE_OUSTRING), PropertyAttribute::MAYBEVOID|PropertyAttribute::READONLY, 0},\
+ {SW_PROP_NMID(UNO_NAME_REDLINE_SUCCESSOR_DATA), 0, CPPU_E2T(CPPUTYPE_PROPERTYVALUE), PropertyAttribute::MAYBEVOID|PropertyAttribute::READONLY, 0},\
+ {SW_PROP_NMID(UNO_NAME_REDLINE_IDENTIFIER), 0, CPPU_E2T(CPPUTYPE_OUSTRING), PropertyAttribute::MAYBEVOID|PropertyAttribute::READONLY, 0},\
+ {SW_PROP_NMID(UNO_NAME_IS_IN_HEADER_FOOTER), 0, CPPU_E2T(CPPUTYPE_BOOLEAN), PropertyAttribute::MAYBEVOID|PropertyAttribute::READONLY, 0},\
+ {SW_PROP_NMID(UNO_NAME_REDLINE_TEXT), 0, CPPU_E2T(CPPUTYPE_REFTEXT), PropertyAttribute::MAYBEVOID|PropertyAttribute::READONLY, 0},\
+ {SW_PROP_NMID(UNO_NAME_MERGE_LAST_PARA), 0, CPPU_E2T(CPPUTYPE_BOOLEAN), PropertyAttribute::MAYBEVOID|PropertyAttribute::READONLY, 0},
+
+#define COMMON_CRSR_PARA_PROPERTIES_FN_ONLY \
+ { SW_PROP_NMID(UNO_NAME_PARA_STYLE_NAME), FN_UNO_PARA_STYLE, CPPU_E2T(CPPUTYPE_OUSTRING), PropertyAttribute::MAYBEVOID, 0}, \
+ { SW_PROP_NMID(UNO_NAME_PAGE_STYLE_NAME), FN_UNO_PAGE_STYLE, CPPU_E2T(CPPUTYPE_OUSTRING), PropertyAttribute::MAYBEVOID|PropertyAttribute::READONLY, 0}, \
+ { SW_PROP_NMID(UNO_NAME_NUMBERING_IS_NUMBER), FN_UNO_IS_NUMBER, CPPU_E2T(CPPUTYPE_BOOLEAN) , PropertyAttribute::MAYBEVOID, 0}, \
+ { SW_PROP_NMID(UNO_NAME_NUMBERING_LEVEL), FN_UNO_NUM_LEVEL, CPPU_E2T(CPPUTYPE_INT16), PropertyAttribute::MAYBEVOID, 0}, \
+ { SW_PROP_NMID(UNO_NAME_NUMBERING_RULES), FN_UNO_NUM_RULES, CPPU_E2T(CPPUTYPE_REFIDXREPL), PropertyAttribute::MAYBEVOID, CONVERT_TWIPS}, \
+ { SW_PROP_NMID(UNO_NAME_NUMBERING_START_VALUE), FN_UNO_NUM_START_VALUE, CPPU_E2T(CPPUTYPE_INT16), PropertyAttribute::MAYBEVOID, CONVERT_TWIPS}, \
+ { SW_PROP_NMID(UNO_NAME_DOCUMENT_INDEX), FN_UNO_DOCUMENT_INDEX, CPPU_E2T(CPPUTYPE_REFDOCINDEX), PropertyAttribute::MAYBEVOID|PropertyAttribute::READONLY ,0 }, \
+ { SW_PROP_NMID(UNO_NAME_TEXT_TABLE), FN_UNO_TEXT_TABLE, CPPU_E2T(CPPUTYPE_REFTXTTABLE), PropertyAttribute::MAYBEVOID|PropertyAttribute::READONLY ,0 }, \
+ { SW_PROP_NMID(UNO_NAME_CELL), FN_UNO_CELL, CPPU_E2T(CPPUTYPE_REFCELL), PropertyAttribute::MAYBEVOID|PropertyAttribute::READONLY ,0 }, \
+ { SW_PROP_NMID(UNO_NAME_TEXT_FRAME), FN_UNO_TEXT_FRAME, CPPU_E2T(CPPUTYPE_REFTEXTFRAME), PropertyAttribute::MAYBEVOID|PropertyAttribute::READONLY ,0 }, \
+ { SW_PROP_NMID(UNO_NAME_TEXT_SECTION), FN_UNO_TEXT_SECTION, CPPU_E2T(CPPUTYPE_REFTEXTSECTION), PropertyAttribute::MAYBEVOID|PropertyAttribute::READONLY ,0 }, \
+ { SW_PROP_NMID(UNO_NAME_PARA_CHAPTER_NUMBERING_LEVEL), FN_UNO_PARA_CHAPTER_NUMBERING_LEVEL,CPPU_E2T(CPPUTYPE_INT8), PROPERTY_NONE, 0}, \
+ { SW_PROP_NMID(UNO_NAME_PARA_CONDITIONAL_STYLE_NAME), FN_UNO_PARA_CONDITIONAL_STYLE_NAME, CPPU_E2T(CPPUTYPE_OUSTRING), PropertyAttribute::READONLY, 0}, \
+ { SW_PROP_NMID(UNO_NAME_LIST_ID), FN_UNO_LIST_ID, CPPU_E2T(CPPUTYPE_OUSTRING), PropertyAttribute::MAYBEVOID, 0}, \
+ { SW_PROP_NMID(UNO_NAME_PARA_IS_NUMBERING_RESTART), FN_NUMBER_NEWSTART, CPPU_E2T(CPPUTYPE_BOOLEAN), PropertyAttribute::MAYBEVOID, 0 }, \
+ { SW_PROP_NMID(UNO_NAME_PARA_CONTINUEING_PREVIOUS_SUB_TREE), FN_UNO_PARA_CONT_PREV_SUBTREE, CPPU_E2T(CPPUTYPE_BOOLEAN), PropertyAttribute::READONLY, 0 }, \
+ { SW_PROP_NMID(UNO_NAME_PARA_LIST_LABEL_STRING), FN_UNO_PARA_NUM_STRING, CPPU_E2T(CPPUTYPE_OUSTRING), PropertyAttribute::READONLY, 0 }, \
+ { SW_PROP_NMID(UNO_NAME_OUTLINE_LEVEL), RES_PARATR_OUTLINELEVEL, CPPU_E2T(CPPUTYPE_INT16), PropertyAttribute::MAYBEVOID, 0},
+
+#define COMMON_HYPERLINK_PROPERTIES \
+ { SW_PROP_NMID(UNO_NAME_HYPER_LINK_U_R_L), RES_TXTATR_INETFMT, CPPU_E2T(CPPUTYPE_OUSTRING), PropertyAttribute::MAYBEVOID ,MID_URL_URL}, \
+ { SW_PROP_NMID(UNO_NAME_HYPER_LINK_TARGET), RES_TXTATR_INETFMT, CPPU_E2T(CPPUTYPE_OUSTRING), PropertyAttribute::MAYBEVOID ,MID_URL_TARGET}, \
+ { SW_PROP_NMID(UNO_NAME_HYPER_LINK_NAME), RES_TXTATR_INETFMT, CPPU_E2T(CPPUTYPE_OUSTRING), PropertyAttribute::MAYBEVOID ,MID_URL_HYPERLINKNAME }, \
+ { SW_PROP_NMID(UNO_NAME_UNVISITED_CHAR_STYLE_NAME), RES_TXTATR_INETFMT, CPPU_E2T(CPPUTYPE_OUSTRING), PropertyAttribute::MAYBEVOID ,MID_URL_UNVISITED_FMT }, \
+ { SW_PROP_NMID(UNO_NAME_VISITED_CHAR_STYLE_NAME), RES_TXTATR_INETFMT, CPPU_E2T(CPPUTYPE_OUSTRING), PropertyAttribute::MAYBEVOID ,MID_URL_VISITED_FMT },
+
+// same as COMMON_CRSR_PARA_PROPERTIES_WITHOUT_FN_01 but without
+// UNO_NAME_BREAK_TYPE and UNO_NAME_PAGE_DESC_NAME which can not be used
+// by the SwXTextTableCursor
+#define COMMON_CRSR_PARA_PROPERTIES_WITHOUT_FN_01 \
+ { SW_PROP_NMID(UNO_NAME_PARA_IS_HYPHENATION), RES_PARATR_HYPHENZONE, CPPU_E2T(CPPUTYPE_BOOLEAN), PropertyAttribute::MAYBEVOID, MID_IS_HYPHEN }, \
+ { SW_PROP_NMID(UNO_NAME_PARA_HYPHENATION_MAX_LEADING_CHARS), RES_PARATR_HYPHENZONE, CPPU_E2T(CPPUTYPE_INT16), PropertyAttribute::MAYBEVOID, MID_HYPHEN_MIN_LEAD }, \
+ { SW_PROP_NMID(UNO_NAME_PARA_HYPHENATION_MAX_TRAILING_CHARS), RES_PARATR_HYPHENZONE, CPPU_E2T(CPPUTYPE_INT16), PropertyAttribute::MAYBEVOID, MID_HYPHEN_MIN_TRAIL }, \
+ { SW_PROP_NMID(UNO_NAME_PARA_HYPHENATION_MAX_HYPHENS), RES_PARATR_HYPHENZONE, CPPU_E2T(CPPUTYPE_INT16), PropertyAttribute::MAYBEVOID, MID_HYPHEN_MAX_HYPHENS}, \
+ { SW_PROP_NMID(UNO_NAME_CHAR_AUTO_KERNING), RES_CHRATR_AUTOKERN , CPPU_E2T(CPPUTYPE_BOOLEAN) , PropertyAttribute::MAYBEVOID, 0}, \
+ { SW_PROP_NMID(UNO_NAME_CHAR_BACK_COLOR), RES_CHRATR_BACKGROUND, CPPU_E2T(CPPUTYPE_INT32), PropertyAttribute::MAYBEVOID ,MID_BACK_COLOR }, \
+ { SW_PROP_NMID(UNO_NAME_PARA_BACK_COLOR), RES_BACKGROUND, CPPU_E2T(CPPUTYPE_INT32), PropertyAttribute::MAYBEVOID ,MID_BACK_COLOR }, \
+ { SW_PROP_NMID(UNO_NAME_CHAR_CASE_MAP), RES_CHRATR_CASEMAP, CPPU_E2T(CPPUTYPE_INT16), PropertyAttribute::MAYBEVOID, 0}, \
+ { SW_PROP_NMID(UNO_NAME_CHAR_COLOR), RES_CHRATR_COLOR, CPPU_E2T(CPPUTYPE_INT32), PropertyAttribute::MAYBEVOID, 0}, \
+ { SW_PROP_NMID(UNO_NAME_CHAR_STRIKEOUT), RES_CHRATR_CROSSEDOUT, CPPU_E2T(CPPUTYPE_INT16), PropertyAttribute::MAYBEVOID, MID_CROSS_OUT}, \
+ { SW_PROP_NMID(UNO_NAME_CHAR_CROSSED_OUT), RES_CHRATR_CROSSEDOUT, CPPU_E2T(CPPUTYPE_BOOLEAN) , PropertyAttribute::MAYBEVOID, MID_CROSSED_OUT}, \
+ { SW_PROP_NMID(UNO_NAME_CHAR_ESCAPEMENT), RES_CHRATR_ESCAPEMENT, CPPU_E2T(CPPUTYPE_INT16), PropertyAttribute::MAYBEVOID, MID_ESC }, \
+ { SW_PROP_NMID(UNO_NAME_CHAR_ESCAPEMENT_HEIGHT), RES_CHRATR_ESCAPEMENT, CPPU_E2T(CPPUTYPE_INT8) , PropertyAttribute::MAYBEVOID, MID_ESC_HEIGHT}, \
+ { SW_PROP_NMID(UNO_NAME_CHAR_AUTO_ESCAPEMENT), RES_CHRATR_ESCAPEMENT, CPPU_E2T(CPPUTYPE_BOOLEAN) , PropertyAttribute::MAYBEVOID, MID_AUTO_ESC }, \
+ { SW_PROP_NMID(UNO_NAME_CHAR_FLASH), RES_CHRATR_BLINK , CPPU_E2T(CPPUTYPE_BOOLEAN) , PropertyAttribute::MAYBEVOID, 0}, \
+ { SW_PROP_NMID(UNO_NAME_CHAR_HIDDEN), RES_CHRATR_HIDDEN, CPPU_E2T(CPPUTYPE_BOOLEAN) , PropertyAttribute::MAYBEVOID, 0},\
+ { SW_PROP_NMID(UNO_NAME_CHAR_UNDERLINE), RES_CHRATR_UNDERLINE , CPPU_E2T(CPPUTYPE_INT16), PropertyAttribute::MAYBEVOID, MID_TL_STYLE}, \
+ { SW_PROP_NMID(UNO_NAME_CHAR_UNDERLINE_COLOR), RES_CHRATR_UNDERLINE , CPPU_E2T(CPPUTYPE_INT32), PropertyAttribute::MAYBEVOID, MID_TL_COLOR}, \
+ { SW_PROP_NMID(UNO_NAME_CHAR_UNDERLINE_HAS_COLOR), RES_CHRATR_UNDERLINE , CPPU_E2T(CPPUTYPE_BOOLEAN), PropertyAttribute::MAYBEVOID, MID_TL_HASCOLOR}, \
+ { SW_PROP_NMID(UNO_NAME_CHAR_OVERLINE), RES_CHRATR_OVERLINE , CPPU_E2T(CPPUTYPE_INT16), PropertyAttribute::MAYBEVOID, MID_TL_STYLE}, \
+ { SW_PROP_NMID(UNO_NAME_CHAR_OVERLINE_COLOR), RES_CHRATR_OVERLINE , CPPU_E2T(CPPUTYPE_INT32), PropertyAttribute::MAYBEVOID, MID_TL_COLOR}, \
+ { SW_PROP_NMID(UNO_NAME_CHAR_OVERLINE_HAS_COLOR), RES_CHRATR_OVERLINE , CPPU_E2T(CPPUTYPE_BOOLEAN), PropertyAttribute::MAYBEVOID, MID_TL_HASCOLOR}, \
+ { SW_PROP_NMID(UNO_NAME_PARA_GRAPHIC_URL), RES_BACKGROUND, CPPU_E2T(CPPUTYPE_OUSTRING), PropertyAttribute::MAYBEVOID ,MID_GRAPHIC_URL }, \
+ { SW_PROP_NMID(UNO_NAME_PARA_GRAPHIC_FILTER), RES_BACKGROUND, CPPU_E2T(CPPUTYPE_OUSTRING), PropertyAttribute::MAYBEVOID ,MID_GRAPHIC_FILTER }, \
+ { SW_PROP_NMID(UNO_NAME_PARA_GRAPHIC_LOCATION), RES_BACKGROUND, CPPU_E2T(CPPUTYPE_GRAPHICLOC), PropertyAttribute::MAYBEVOID ,MID_GRAPHIC_POSITION}, \
+ { SW_PROP_NMID(UNO_NAME_PARA_LEFT_MARGIN), RES_LR_SPACE, CPPU_E2T(CPPUTYPE_INT32), PropertyAttribute::MAYBEVOID, MID_TXT_LMARGIN|CONVERT_TWIPS}, \
+ { SW_PROP_NMID(UNO_NAME_PARA_RIGHT_MARGIN), RES_LR_SPACE, CPPU_E2T(CPPUTYPE_INT32), PropertyAttribute::MAYBEVOID, MID_R_MARGIN|CONVERT_TWIPS}, \
+ { SW_PROP_NMID(UNO_NAME_PARA_IS_AUTO_FIRST_LINE_INDENT), RES_LR_SPACE, CPPU_E2T(CPPUTYPE_BOOLEAN), PropertyAttribute::MAYBEVOID, MID_FIRST_AUTO}, \
+ { SW_PROP_NMID(UNO_NAME_PARA_FIRST_LINE_INDENT), RES_LR_SPACE, CPPU_E2T(CPPUTYPE_INT32), PropertyAttribute::MAYBEVOID, MID_FIRST_LINE_INDENT|CONVERT_TWIPS}, \
+ _STANDARD_FONT_PROPERTIES \
+ _CJK_FONT_PROPERTIES \
+ _CTL_FONT_PROPERTIES \
+ { SW_PROP_NMID(UNO_NAME_CHAR_KERNING), RES_CHRATR_KERNING , CPPU_E2T(CPPUTYPE_INT16) , PropertyAttribute::MAYBEVOID, CONVERT_TWIPS}, \
+ { SW_PROP_NMID(UNO_NAME_CHAR_NO_HYPHENATION), RES_CHRATR_NOHYPHEN , CPPU_E2T(CPPUTYPE_BOOLEAN) , PropertyAttribute::MAYBEVOID, 0}, \
+ { SW_PROP_NMID(UNO_NAME_CHAR_SHADOWED), RES_CHRATR_SHADOWED , CPPU_E2T(CPPUTYPE_BOOLEAN) , PropertyAttribute::MAYBEVOID, 0}, \
+ { SW_PROP_NMID(UNO_NAME_CHAR_CONTOURED), RES_CHRATR_CONTOUR, CPPU_E2T(CPPUTYPE_BOOLEAN) , PropertyAttribute::MAYBEVOID, 0}, \
+ { SW_PROP_NMID(UNO_NAME_DROP_CAP_FORMAT), RES_PARATR_DROP, CPPU_E2T(CPPUTYPE_DROPCAPFMT) , PropertyAttribute::MAYBEVOID, MID_DROPCAP_FORMAT|CONVERT_TWIPS}, \
+ { SW_PROP_NMID(UNO_NAME_DROP_CAP_WHOLE_WORD), RES_PARATR_DROP, CPPU_E2T(CPPUTYPE_BOOLEAN) , PropertyAttribute::MAYBEVOID, MID_DROPCAP_WHOLE_WORD }, \
+ { SW_PROP_NMID(UNO_NAME_DROP_CAP_CHAR_STYLE_NAME), RES_PARATR_DROP, CPPU_E2T(CPPUTYPE_OUSTRING) , PropertyAttribute::MAYBEVOID, MID_DROPCAP_CHAR_STYLE_NAME }, \
+ { SW_PROP_NMID(UNO_NAME_PARA_KEEP_TOGETHER), RES_KEEP, CPPU_E2T(CPPUTYPE_BOOLEAN) , PropertyAttribute::MAYBEVOID, 0}, \
+ { SW_PROP_NMID(UNO_NAME_PARA_SPLIT), RES_PARATR_SPLIT, CPPU_E2T(CPPUTYPE_BOOLEAN) , PropertyAttribute::MAYBEVOID, 0}, \
+ { SW_PROP_NMID(UNO_NAME_PARA_WIDOWS), RES_PARATR_WIDOWS, CPPU_E2T(CPPUTYPE_INT8),PropertyAttribute::MAYBEVOID, 0}, \
+ { SW_PROP_NMID(UNO_NAME_PARA_ORPHANS), RES_PARATR_ORPHANS, CPPU_E2T(CPPUTYPE_INT8),PropertyAttribute::MAYBEVOID, 0}, \
+ { SW_PROP_NMID(UNO_NAME_PAGE_NUMBER_OFFSET), RES_PAGEDESC, CPPU_E2T(CPPUTYPE_INT16), PropertyAttribute::MAYBEVOID, MID_PAGEDESC_PAGENUMOFFSET}, \
+ { SW_PROP_NMID(UNO_NAME_PARA_ADJUST), RES_PARATR_ADJUST, CPPU_E2T(CPPUTYPE_INT16), PropertyAttribute::MAYBEVOID, MID_PARA_ADJUST}, \
+ { SW_PROP_NMID(UNO_NAME_PARA_EXPAND_SINGLE_WORD), RES_PARATR_ADJUST, CPPU_E2T(CPPUTYPE_BOOLEAN) , PropertyAttribute::MAYBEVOID, MID_EXPAND_SINGLE }, \
+ { SW_PROP_NMID(UNO_NAME_PARA_LAST_LINE_ADJUST), RES_PARATR_ADJUST, CPPU_E2T(CPPUTYPE_INT16), PropertyAttribute::MAYBEVOID, MID_LAST_LINE_ADJUST}, \
+ { SW_PROP_NMID(UNO_NAME_PARA_LINE_NUMBER_COUNT), RES_LINENUMBER, CPPU_E2T(CPPUTYPE_BOOLEAN), PropertyAttribute::MAYBEVOID ,MID_LINENUMBER_COUNT }, \
+ { SW_PROP_NMID(UNO_NAME_PARA_LINE_NUMBER_START_VALUE), RES_LINENUMBER, CPPU_E2T(CPPUTYPE_INT32), PropertyAttribute::MAYBEVOID ,MID_LINENUMBER_STARTVALUE}, \
+ { SW_PROP_NMID(UNO_NAME_PARA_LINE_SPACING), RES_PARATR_LINESPACING, CPPU_E2T(CPPUTYPE_LINESPACE), PropertyAttribute::MAYBEVOID, CONVERT_TWIPS}, \
+ { SW_PROP_NMID(UNO_NAME_PARA_REGISTER_MODE_ACTIVE), RES_PARATR_REGISTER,CPPU_E2T(CPPUTYPE_BOOLEAN) , PropertyAttribute::MAYBEVOID, 0}, \
+ { SW_PROP_NMID(UNO_NAME_PARA_TOP_MARGIN), RES_UL_SPACE, CPPU_E2T(CPPUTYPE_INT32), PropertyAttribute::MAYBEVOID, MID_UP_MARGIN|CONVERT_TWIPS}, \
+ { SW_PROP_NMID(UNO_NAME_PARA_BOTTOM_MARGIN), RES_UL_SPACE, CPPU_E2T(CPPUTYPE_INT32), PropertyAttribute::MAYBEVOID, MID_LO_MARGIN|CONVERT_TWIPS}, \
+ { SW_PROP_NMID(UNO_NAME_CHAR_BACK_TRANSPARENT), RES_CHRATR_BACKGROUND, CPPU_E2T(CPPUTYPE_BOOLEAN), PropertyAttribute::MAYBEVOID ,MID_GRAPHIC_TRANSPARENT }, \
+ { SW_PROP_NMID(UNO_NAME_PARA_BACK_TRANSPARENT), RES_BACKGROUND, CPPU_E2T(CPPUTYPE_BOOLEAN), PropertyAttribute::MAYBEVOID ,MID_GRAPHIC_TRANSPARENT }, \
+ { SW_PROP_NMID(UNO_NAME_NUMBERING_STYLE_NAME), RES_PARATR_NUMRULE, CPPU_E2T(CPPUTYPE_OUSTRING), PropertyAttribute::MAYBEVOID, 0}, \
+ { SW_PROP_NMID(UNO_NAME_CHAR_WORD_MODE), RES_CHRATR_WORDLINEMODE,CPPU_E2T(CPPUTYPE_BOOLEAN) , PropertyAttribute::MAYBEVOID, 0}, \
+ { SW_PROP_NMID(UNO_NAME_LEFT_BORDER), RES_BOX, CPPU_E2T(CPPUTYPE_BORDERLINE), PropertyAttribute::MAYBEVOID, LEFT_BORDER |CONVERT_TWIPS }, \
+ { SW_PROP_NMID(UNO_NAME_RIGHT_BORDER), RES_BOX, CPPU_E2T(CPPUTYPE_BORDERLINE), PropertyAttribute::MAYBEVOID, RIGHT_BORDER |CONVERT_TWIPS }, \
+ { SW_PROP_NMID(UNO_NAME_TOP_BORDER), RES_BOX, CPPU_E2T(CPPUTYPE_BORDERLINE), PropertyAttribute::MAYBEVOID, TOP_BORDER |CONVERT_TWIPS }, \
+ { SW_PROP_NMID(UNO_NAME_BOTTOM_BORDER), RES_BOX, CPPU_E2T(CPPUTYPE_BORDERLINE), PropertyAttribute::MAYBEVOID, BOTTOM_BORDER|CONVERT_TWIPS }, \
+ { SW_PROP_NMID(UNO_NAME_BORDER_DISTANCE), RES_BOX, CPPU_E2T(CPPUTYPE_INT32), PropertyAttribute::MAYBEVOID, BORDER_DISTANCE|CONVERT_TWIPS }, \
+ { SW_PROP_NMID(UNO_NAME_LEFT_BORDER_DISTANCE), RES_BOX, CPPU_E2T(CPPUTYPE_INT32), PropertyAttribute::MAYBEVOID, LEFT_BORDER_DISTANCE |CONVERT_TWIPS }, \
+ { SW_PROP_NMID(UNO_NAME_RIGHT_BORDER_DISTANCE), RES_BOX, CPPU_E2T(CPPUTYPE_INT32), PropertyAttribute::MAYBEVOID, RIGHT_BORDER_DISTANCE |CONVERT_TWIPS }, \
+ { SW_PROP_NMID(UNO_NAME_TOP_BORDER_DISTANCE), RES_BOX, CPPU_E2T(CPPUTYPE_INT32), PropertyAttribute::MAYBEVOID, TOP_BORDER_DISTANCE |CONVERT_TWIPS }, \
+ { SW_PROP_NMID(UNO_NAME_BOTTOM_BORDER_DISTANCE), RES_BOX, CPPU_E2T(CPPUTYPE_INT32), PropertyAttribute::MAYBEVOID, BOTTOM_BORDER_DISTANCE|CONVERT_TWIPS }, \
+ { SW_PROP_NMID(UNO_NAME_PARA_USER_DEFINED_ATTRIBUTES), RES_UNKNOWNATR_CONTAINER, CPPU_E2T(CPPUTYPE_REFNAMECNT), PropertyAttribute::MAYBEVOID, 0 }, \
+ { SW_PROP_NMID(UNO_NAME_TEXT_USER_DEFINED_ATTRIBUTES), RES_TXTATR_UNKNOWN_CONTAINER, CPPU_E2T(CPPUTYPE_REFNAMECNT), PropertyAttribute::MAYBEVOID, 0 }, \
+ { SW_PROP_NMID(UNO_NAME_PARA_SHADOW_FORMAT), RES_SHADOW, CPPU_E2T(CPPUTYPE_SHADOWFMT), PROPERTY_NONE, CONVERT_TWIPS}, \
+ { SW_PROP_NMID(UNO_NAME_CHAR_COMBINE_IS_ON), RES_CHRATR_TWO_LINES, CPPU_E2T(CPPUTYPE_BOOLEAN), PropertyAttribute::MAYBEVOID, MID_TWOLINES}, \
+ { SW_PROP_NMID(UNO_NAME_CHAR_COMBINE_PREFIX), RES_CHRATR_TWO_LINES, CPPU_E2T(CPPUTYPE_OUSTRING), PropertyAttribute::MAYBEVOID, MID_START_BRACKET}, \
+ { SW_PROP_NMID(UNO_NAME_CHAR_COMBINE_SUFFIX), RES_CHRATR_TWO_LINES, CPPU_E2T(CPPUTYPE_OUSTRING), PropertyAttribute::MAYBEVOID, MID_END_BRACKET}, \
+ { SW_PROP_NMID(UNO_NAME_CHAR_EMPHASIS), RES_CHRATR_EMPHASIS_MARK, CPPU_E2T(CPPUTYPE_INT16), PropertyAttribute::MAYBEVOID, MID_EMPHASIS},\
+ { SW_PROP_NMID(UNO_NAME_PARA_IS_HANGING_PUNCTUATION), RES_PARATR_HANGINGPUNCTUATION, CPPU_E2T(CPPUTYPE_BOOLEAN), PropertyAttribute::MAYBEVOID ,0 }, \
+ { SW_PROP_NMID(UNO_NAME_PARA_IS_CHARACTER_DISTANCE), RES_PARATR_SCRIPTSPACE, CPPU_E2T(CPPUTYPE_BOOLEAN), PropertyAttribute::MAYBEVOID ,0 }, \
+ { SW_PROP_NMID(UNO_NAME_PARA_IS_FORBIDDEN_RULES), RES_PARATR_FORBIDDEN_RULES, CPPU_E2T(CPPUTYPE_BOOLEAN), PropertyAttribute::MAYBEVOID ,0 }, \
+ { SW_PROP_NMID(UNO_NAME_PARA_VERT_ALIGNMENT), RES_PARATR_VERTALIGN,CPPU_E2T(CPPUTYPE_INT16), PropertyAttribute::MAYBEVOID, 0 }, \
+ { SW_PROP_NMID(UNO_NAME_CHAR_ROTATION), RES_CHRATR_ROTATE, CPPU_E2T(CPPUTYPE_INT16), PropertyAttribute::MAYBEVOID, MID_ROTATE }, \
+ { SW_PROP_NMID(UNO_NAME_CHAR_ROTATION_IS_FIT_TO_LINE), RES_CHRATR_ROTATE, CPPU_E2T(CPPUTYPE_BOOLEAN), PropertyAttribute::MAYBEVOID, MID_FITTOLINE }, \
+ { SW_PROP_NMID(UNO_NAME_CHAR_SCALE_WIDTH), RES_CHRATR_SCALEW, CPPU_E2T(CPPUTYPE_INT16), PropertyAttribute::MAYBEVOID, 0 }, \
+ { SW_PROP_NMID(UNO_NAME_RUBY_TEXT), RES_TXTATR_CJK_RUBY, CPPU_E2T(CPPUTYPE_OUSTRING), PropertyAttribute::MAYBEVOID, MID_RUBY_TEXT }, \
+ { SW_PROP_NMID(UNO_NAME_RUBY_ADJUST), RES_TXTATR_CJK_RUBY, CPPU_E2T(CPPUTYPE_INT16), PropertyAttribute::MAYBEVOID, MID_RUBY_ADJUST }, \
+ { SW_PROP_NMID(UNO_NAME_RUBY_CHAR_STYLE_NAME), RES_TXTATR_CJK_RUBY, CPPU_E2T(CPPUTYPE_OUSTRING), PropertyAttribute::MAYBEVOID, MID_RUBY_CHARSTYLE }, \
+ { SW_PROP_NMID(UNO_NAME_RUBY_IS_ABOVE), RES_TXTATR_CJK_RUBY, CPPU_E2T(CPPUTYPE_BOOLEAN), PropertyAttribute::MAYBEVOID, MID_RUBY_ABOVE }, \
+ { SW_PROP_NMID(UNO_NAME_CHAR_RELIEF), RES_CHRATR_RELIEF, CPPU_E2T(CPPUTYPE_INT16), PropertyAttribute::MAYBEVOID, MID_RELIEF }, \
+ { SW_PROP_NMID(UNO_NAME_SNAP_TO_GRID), RES_PARATR_SNAPTOGRID, CPPU_E2T(CPPUTYPE_BOOLEAN), PropertyAttribute::MAYBEVOID, 0 }, \
+ { SW_PROP_NMID(UNO_NAME_PARA_IS_CONNECT_BORDER), RES_PARATR_CONNECT_BORDER, CPPU_E2T(CPPUTYPE_BOOLEAN), PropertyAttribute::MAYBEVOID, 0}, \
+ { SW_PROP_NMID(UNO_NAME_WRITING_MODE), RES_FRAMEDIR, CPPU_E2T(CPPUTYPE_INT16), PROPERTY_NONE, 0 },
+
+#define COMMON_CRSR_PARA_PROPERTIES_WITHOUT_FN \
+ COMMON_CRSR_PARA_PROPERTIES_WITHOUT_FN_01 \
+ { SW_PROP_NMID(UNO_NAME_BREAK_TYPE), RES_BREAK, CPPU_E2T(CPPUTYPE_BREAK), PropertyAttribute::MAYBEVOID, 0}, \
+ { SW_PROP_NMID(UNO_NAME_PAGE_DESC_NAME), RES_PAGEDESC, CPPU_E2T(CPPUTYPE_OUSTRING), PropertyAttribute::MAYBEVOID, MID_PAGEDESC_PAGEDESCNAME },
+
+
+#define TABSTOPS_MAP_ENTRY { SW_PROP_NMID(UNO_NAME_TABSTOPS), RES_PARATR_TABSTOP, CPPU_E2T(CPPUTYPE_SEQTABSTOP), PropertyAttribute::MAYBEVOID, CONVERT_TWIPS},
+
+#define COMMON_CRSR_PARA_PROPERTIES \
+ COMMON_CRSR_PARA_PROPERTIES_FN_ONLY \
+ COMMON_CRSR_PARA_PROPERTIES_WITHOUT_FN \
+ COMMON_HYPERLINK_PROPERTIES \
+ { SW_PROP_NMID(UNO_NAME_CHAR_STYLE_NAME), RES_TXTATR_CHARFMT, CPPU_E2T(CPPUTYPE_OUSTRING), PropertyAttribute::MAYBEVOID, 0},\
+ { SW_PROP_NMID(UNO_NAME_CHAR_STYLE_NAMES), FN_UNO_CHARFMT_SEQUENCE, CPPU_E2T(CPPUTYPE_OUSTRINGS), PropertyAttribute::MAYBEVOID, 0},\
+ { SW_PROP_NMID(UNO_NAME_CHAR_AUTO_STYLE_NAME), RES_TXTATR_AUTOFMT, CPPU_E2T(CPPUTYPE_OUSTRING), PropertyAttribute::MAYBEVOID, 0},\
+ { SW_PROP_NMID(UNO_NAME_PARA_AUTO_STYLE_NAME), RES_AUTO_STYLE, CPPU_E2T(CPPUTYPE_OUSTRING), PropertyAttribute::MAYBEVOID, 0},
+
+#define COMMON_CRSR_PARA_PROPERTIES_2 \
+ COMMON_CRSR_PARA_PROPERTIES_FN_ONLY \
+ COMMON_CRSR_PARA_PROPERTIES_WITHOUT_FN
+
+#define COMPLETE_TEXT_CURSOR_MAP\
+ COMMON_CRSR_PARA_PROPERTIES\
+ { SW_PROP_NMID(UNO_NAME_DOCUMENT_INDEX_MARK), FN_UNO_DOCUMENT_INDEX_MARK, CPPU_E2T(CPPUTYPE_REFDOCIDXMRK), PropertyAttribute::MAYBEVOID|PropertyAttribute::READONLY ,0 },\
+ { SW_PROP_NMID(UNO_NAME_TEXT_FIELD), FN_UNO_TEXT_FIELD, CPPU_E2T(CPPUTYPE_REFTXTFIELD), PropertyAttribute::MAYBEVOID|PropertyAttribute::READONLY ,0 },\
+ { SW_PROP_NMID(UNO_NAME_REFERENCE_MARK), FN_UNO_REFERENCE_MARK, CPPU_E2T(CPPUTYPE_REFTEXTCNTNT), PropertyAttribute::MAYBEVOID|PropertyAttribute::READONLY, 0 },\
+ { SW_PROP_NMID(UNO_NAME_FOOTNOTE), FN_UNO_FOOTNOTE, CPPU_E2T(CPPUTYPE_REFFOOTNOTE), PropertyAttribute::MAYBEVOID|PropertyAttribute::READONLY ,0 },\
+ { SW_PROP_NMID(UNO_NAME_ENDNOTE), FN_UNO_ENDNOTE, CPPU_E2T(CPPUTYPE_REFFOOTNOTE), PropertyAttribute::MAYBEVOID|PropertyAttribute::READONLY ,0 },\
+ { SW_PROP_NMID(UNO_NAME_HYPER_LINK_EVENTS), RES_TXTATR_INETFMT, CPPU_E2T(CPPUTYPE_REFNMREPLACE), PropertyAttribute::MAYBEVOID, MID_URL_HYPERLINKEVENTS},\
+ { SW_PROP_NMID(UNO_NAME_NESTED_TEXT_CONTENT), FN_UNO_NESTED_TEXT_CONTENT, CPPU_E2T(CPPUTYPE_REFTEXTCNTNT), PropertyAttribute::MAYBEVOID|PropertyAttribute::READONLY, 0 },\
+ TABSTOPS_MAP_ENTRY
+
+
+
+#define _BASE_INDEX_PROPERTIES_\
+ { SW_PROP_NMID(UNO_NAME_TITLE), WID_IDX_TITLE, CPPU_E2T(CPPUTYPE_OUSTRING) , PROPERTY_NONE, 0},\
+ { SW_PROP_NMID(UNO_NAME_NAME), WID_IDX_NAME, CPPU_E2T(CPPUTYPE_OUSTRING) , PROPERTY_NONE, 0},\
+ { SW_PROP_NMID(UNO_NAME_CONTENT_SECTION), WID_IDX_CONTENT_SECTION, CPPU_E2T(CPPUTYPE_REFTEXTSECTION) , PropertyAttribute::READONLY, 0},\
+ { SW_PROP_NMID(UNO_NAME_HEADER_SECTION), WID_IDX_HEADER_SECTION, CPPU_E2T(CPPUTYPE_REFTEXTSECTION) , PropertyAttribute::MAYBEVOID|PropertyAttribute::READONLY, 0},\
+
+#define ANCHOR_TYPES_PROPERTY { SW_PROP_NMID(UNO_NAME_ANCHOR_TYPES), FN_UNO_ANCHOR_TYPES, CPPU_E2T(CPPUTYPE_SEQANCHORTYPE),PropertyAttribute::READONLY, 0xff},
+
+// #i18732# #i28701# #i73249#
+#define COMMON_FRAME_PROPERTIES \
+ { SW_PROP_NMID(UNO_NAME_ANCHOR_PAGE_NO), RES_ANCHOR, CPPU_E2T(CPPUTYPE_INT16), PROPERTY_NONE, MID_ANCHOR_PAGENUM }, \
+ { SW_PROP_NMID(UNO_NAME_ANCHOR_TYPE), RES_ANCHOR, CPPU_E2T(CPPUTYPE_TXTCNTANCHOR), PROPERTY_NONE, MID_ANCHOR_ANCHORTYPE}, \
+ { SW_PROP_NMID(UNO_NAME_ANCHOR_FRAME), RES_ANCHOR, CPPU_E2T(CPPUTYPE_REFTEXTFRAME), PropertyAttribute::MAYBEVOID, MID_ANCHOR_ANCHORFRAME}, \
+ ANCHOR_TYPES_PROPERTY\
+ { SW_PROP_NMID(UNO_NAME_BACK_COLOR), RES_BACKGROUND, CPPU_E2T(CPPUTYPE_INT32), PROPERTY_NONE ,MID_BACK_COLOR }, \
+ { SW_PROP_NMID(UNO_NAME_BACK_COLOR_R_G_B), RES_BACKGROUND, CPPU_E2T(CPPUTYPE_INT32), PROPERTY_NONE ,MID_BACK_COLOR_R_G_B}, \
+ { SW_PROP_NMID(UNO_NAME_BACK_COLOR_TRANSPARENCY), RES_BACKGROUND, CPPU_E2T(CPPUTYPE_INT8), PROPERTY_NONE ,MID_BACK_COLOR_TRANSPARENCY}, \
+ { SW_PROP_NMID(UNO_NAME_CONTENT_PROTECTED), RES_PROTECT, CPPU_E2T(CPPUTYPE_BOOLEAN), PROPERTY_NONE, MID_PROTECT_CONTENT }, \
+ { SW_PROP_NMID(UNO_NAME_FRAME_STYLE_NAME), FN_UNO_FRAME_STYLE_NAME,CPPU_E2T(CPPUTYPE_OUSTRING), PROPERTY_NONE, 0}, \
+ { SW_PROP_NMID(UNO_NAME_BACK_GRAPHIC_URL), RES_BACKGROUND, CPPU_E2T(CPPUTYPE_OUSTRING), PROPERTY_NONE ,MID_GRAPHIC_URL }, \
+ { SW_PROP_NMID(UNO_NAME_BACK_GRAPHIC_FILTER), RES_BACKGROUND, CPPU_E2T(CPPUTYPE_OUSTRING), PROPERTY_NONE ,MID_GRAPHIC_FILTER }, \
+ { SW_PROP_NMID(UNO_NAME_BACK_GRAPHIC_LOCATION), RES_BACKGROUND, CPPU_E2T(CPPUTYPE_GRAPHICLOC), PROPERTY_NONE ,MID_GRAPHIC_POSITION}, \
+ { SW_PROP_NMID(UNO_NAME_BACK_GRAPHIC_TRANSPARENCY), RES_BACKGROUND, CPPU_E2T(CPPUTYPE_INT8), PROPERTY_NONE ,MID_GRAPHIC_TRANSPARENCY}, \
+ { SW_PROP_NMID(UNO_NAME_LEFT_MARGIN), RES_LR_SPACE, CPPU_E2T(CPPUTYPE_INT32), PROPERTY_NONE, MID_L_MARGIN|CONVERT_TWIPS}, \
+ { SW_PROP_NMID(UNO_NAME_RIGHT_MARGIN), RES_LR_SPACE, CPPU_E2T(CPPUTYPE_INT32), PROPERTY_NONE, MID_R_MARGIN|CONVERT_TWIPS}, \
+ { SW_PROP_NMID(UNO_NAME_WIDTH), RES_FRM_SIZE, CPPU_E2T(CPPUTYPE_INT32) , PROPERTY_NONE, MID_FRMSIZE_WIDTH|CONVERT_TWIPS},\
+ { SW_PROP_NMID(UNO_NAME_HEIGHT), RES_FRM_SIZE, CPPU_E2T(CPPUTYPE_INT32) , PROPERTY_NONE, MID_FRMSIZE_HEIGHT|CONVERT_TWIPS},\
+ { SW_PROP_NMID(UNO_NAME_HORI_ORIENT), RES_HORI_ORIENT, CPPU_E2T(CPPUTYPE_INT16), PROPERTY_NONE ,MID_HORIORIENT_ORIENT }, \
+ { SW_PROP_NMID(UNO_NAME_HORI_ORIENT_POSITION), RES_HORI_ORIENT, CPPU_E2T(CPPUTYPE_INT32), PROPERTY_NONE ,MID_HORIORIENT_POSITION|CONVERT_TWIPS }, \
+ { SW_PROP_NMID(UNO_NAME_HORI_ORIENT_RELATION), RES_HORI_ORIENT, CPPU_E2T(CPPUTYPE_INT16), PROPERTY_NONE ,MID_HORIORIENT_RELATION }, \
+ { SW_PROP_NMID(UNO_NAME_HYPER_LINK_U_R_L), RES_URL, CPPU_E2T(CPPUTYPE_OUSTRING), PROPERTY_NONE ,MID_URL_URL}, \
+ { SW_PROP_NMID(UNO_NAME_HYPER_LINK_TARGET), RES_URL, CPPU_E2T(CPPUTYPE_OUSTRING), PROPERTY_NONE ,MID_URL_TARGET}, \
+ { SW_PROP_NMID(UNO_NAME_HYPER_LINK_NAME), RES_URL, CPPU_E2T(CPPUTYPE_OUSTRING), PROPERTY_NONE ,MID_URL_HYPERLINKNAME }, \
+ { SW_PROP_NMID(UNO_NAME_OPAQUE), RES_OPAQUE, CPPU_E2T(CPPUTYPE_BOOLEAN), PROPERTY_NONE, 0}, \
+ { SW_PROP_NMID(UNO_NAME_PAGE_TOGGLE), RES_HORI_ORIENT, CPPU_E2T(CPPUTYPE_BOOLEAN), PROPERTY_NONE ,MID_HORIORIENT_PAGETOGGLE }, \
+ { SW_PROP_NMID(UNO_NAME_POSITION_PROTECTED), RES_PROTECT, CPPU_E2T(CPPUTYPE_BOOLEAN), PROPERTY_NONE, MID_PROTECT_POSITION}, \
+ { SW_PROP_NMID(UNO_NAME_PRINT), RES_PRINT, CPPU_E2T(CPPUTYPE_BOOLEAN), PROPERTY_NONE, 0}, \
+ { SW_PROP_NMID(UNO_NAME_RELATIVE_HEIGHT), RES_FRM_SIZE, CPPU_E2T(CPPUTYPE_INT16) , PROPERTY_NONE, MID_FRMSIZE_REL_HEIGHT }, \
+ { SW_PROP_NMID(UNO_NAME_RELATIVE_WIDTH), RES_FRM_SIZE, CPPU_E2T(CPPUTYPE_INT16) , PROPERTY_NONE, MID_FRMSIZE_REL_WIDTH }, \
+ { SW_PROP_NMID(UNO_NAME_SHADOW_FORMAT), RES_SHADOW, CPPU_E2T(CPPUTYPE_SHADOWFMT), PROPERTY_NONE, CONVERT_TWIPS}, \
+ { SW_PROP_NMID(UNO_NAME_IMAGE_MAP), RES_URL, CPPU_E2T(CPPUTYPE_REFIDXCNTNR), PROPERTY_NONE, MID_URL_CLIENTMAP}, \
+ { SW_PROP_NMID(UNO_NAME_SERVER_MAP), RES_URL, CPPU_E2T(CPPUTYPE_BOOLEAN), PROPERTY_NONE ,MID_URL_SERVERMAP }, \
+ { SW_PROP_NMID(UNO_NAME_SIZE), RES_FRM_SIZE, CPPU_E2T(CPPUTYPE_AWTSIZE), PROPERTY_NONE, MID_FRMSIZE_SIZE|CONVERT_TWIPS}, \
+ { SW_PROP_NMID(UNO_NAME_SIZE_PROTECTED), RES_PROTECT, CPPU_E2T(CPPUTYPE_BOOLEAN), PROPERTY_NONE, MID_PROTECT_SIZE }, \
+ { SW_PROP_NMID(UNO_NAME_IS_SYNC_WIDTH_TO_HEIGHT), RES_FRM_SIZE, CPPU_E2T(CPPUTYPE_BOOLEAN) , PROPERTY_NONE, MID_FRMSIZE_IS_SYNC_WIDTH_TO_HEIGHT }, \
+ { SW_PROP_NMID(UNO_NAME_IS_SYNC_HEIGHT_TO_WIDTH), RES_FRM_SIZE, CPPU_E2T(CPPUTYPE_BOOLEAN) , PROPERTY_NONE, MID_FRMSIZE_IS_SYNC_HEIGHT_TO_WIDTH }, \
+ { SW_PROP_NMID(UNO_NAME_TEXT_WRAP), RES_SURROUND, CPPU_E2T(CPPUTYPE_WRAPTXTMODE), PROPERTY_NONE, MID_SURROUND_SURROUNDTYPE }, \
+ { SW_PROP_NMID(UNO_NAME_SURROUND), RES_SURROUND, CPPU_E2T(CPPUTYPE_WRAPTXTMODE), PROPERTY_NONE, MID_SURROUND_SURROUNDTYPE }, \
+ { SW_PROP_NMID(UNO_NAME_SURROUND_ANCHORONLY), RES_SURROUND, CPPU_E2T(CPPUTYPE_BOOLEAN), PROPERTY_NONE, MID_SURROUND_ANCHORONLY }, \
+ { SW_PROP_NMID(UNO_NAME_TOP_MARGIN), RES_UL_SPACE, CPPU_E2T(CPPUTYPE_INT32), PROPERTY_NONE, MID_UP_MARGIN|CONVERT_TWIPS}, \
+ { SW_PROP_NMID(UNO_NAME_BOTTOM_MARGIN), RES_UL_SPACE, CPPU_E2T(CPPUTYPE_INT32), PROPERTY_NONE, MID_LO_MARGIN|CONVERT_TWIPS}, \
+ { SW_PROP_NMID(UNO_NAME_BACK_TRANSPARENT), RES_BACKGROUND, CPPU_E2T(CPPUTYPE_BOOLEAN), PROPERTY_NONE ,MID_GRAPHIC_TRANSPARENT }, \
+ { SW_PROP_NMID(UNO_NAME_VERT_ORIENT), RES_VERT_ORIENT, CPPU_E2T(CPPUTYPE_INT16), PROPERTY_NONE ,MID_VERTORIENT_ORIENT }, \
+ { SW_PROP_NMID(UNO_NAME_VERT_ORIENT_POSITION), RES_VERT_ORIENT, CPPU_E2T(CPPUTYPE_INT32), PROPERTY_NONE ,MID_VERTORIENT_POSITION|CONVERT_TWIPS }, \
+ { SW_PROP_NMID(UNO_NAME_VERT_ORIENT_RELATION), RES_VERT_ORIENT, CPPU_E2T(CPPUTYPE_INT16), PROPERTY_NONE ,MID_VERTORIENT_RELATION }, \
+ { SW_PROP_NMID(UNO_NAME_LEFT_BORDER), RES_BOX, CPPU_E2T(CPPUTYPE_BORDERLINE), 0, LEFT_BORDER |CONVERT_TWIPS }, \
+ { SW_PROP_NMID(UNO_NAME_RIGHT_BORDER), RES_BOX, CPPU_E2T(CPPUTYPE_BORDERLINE), 0, RIGHT_BORDER |CONVERT_TWIPS }, \
+ { SW_PROP_NMID(UNO_NAME_TOP_BORDER), RES_BOX, CPPU_E2T(CPPUTYPE_BORDERLINE), 0, TOP_BORDER |CONVERT_TWIPS }, \
+ { SW_PROP_NMID(UNO_NAME_BOTTOM_BORDER), RES_BOX, CPPU_E2T(CPPUTYPE_BORDERLINE), 0, BOTTOM_BORDER|CONVERT_TWIPS }, \
+ { SW_PROP_NMID(UNO_NAME_BORDER_DISTANCE), RES_BOX, CPPU_E2T(CPPUTYPE_INT32), 0, BORDER_DISTANCE|CONVERT_TWIPS }, \
+ { SW_PROP_NMID(UNO_NAME_LEFT_BORDER_DISTANCE), RES_BOX, CPPU_E2T(CPPUTYPE_INT32), 0, LEFT_BORDER_DISTANCE |CONVERT_TWIPS }, \
+ { SW_PROP_NMID(UNO_NAME_RIGHT_BORDER_DISTANCE), RES_BOX, CPPU_E2T(CPPUTYPE_INT32), 0, RIGHT_BORDER_DISTANCE |CONVERT_TWIPS }, \
+ { SW_PROP_NMID(UNO_NAME_TOP_BORDER_DISTANCE), RES_BOX, CPPU_E2T(CPPUTYPE_INT32), 0, TOP_BORDER_DISTANCE |CONVERT_TWIPS }, \
+ { SW_PROP_NMID(UNO_NAME_BOTTOM_BORDER_DISTANCE), RES_BOX, CPPU_E2T(CPPUTYPE_INT32), 0, BOTTOM_BORDER_DISTANCE|CONVERT_TWIPS }, \
+ { SW_PROP_NMID(UNO_LINK_DISPLAY_NAME), FN_PARAM_LINK_DISPLAY_NAME, CPPU_E2T(CPPUTYPE_OUSTRING), PropertyAttribute::READONLY, 0xff}, \
+ { SW_PROP_NMID(UNO_NAME_USER_DEFINED_ATTRIBUTES), RES_UNKNOWNATR_CONTAINER, CPPU_E2T(CPPUTYPE_REFNAMECNT), PropertyAttribute::MAYBEVOID, 0 },\
+ { SW_PROP_NMID(UNO_NAME_Z_ORDER), FN_UNO_Z_ORDER, CPPU_E2T(CPPUTYPE_INT32), PROPERTY_NONE, 0}, \
+ { SW_PROP_NMID(UNO_NAME_IS_FOLLOWING_TEXT_FLOW), RES_FOLLOW_TEXT_FLOW, CPPU_E2T(CPPUTYPE_BOOLEAN), PROPERTY_NONE, 0}, \
+ { SW_PROP_NMID(UNO_NAME_WRAP_INFLUENCE_ON_POSITION), RES_WRAP_INFLUENCE_ON_OBJPOS, CPPU_E2T(CPPUTYPE_INT8), PROPERTY_NONE, MID_WRAP_INFLUENCE}, \
+ { SW_PROP_NMID(UNO_NAME_TITLE), FN_UNO_TITLE, CPPU_E2T(CPPUTYPE_OUSTRING), PROPERTY_NONE, 0}, \
+ { SW_PROP_NMID(UNO_NAME_DESCRIPTION), FN_UNO_DESCRIPTION, CPPU_E2T(CPPUTYPE_OUSTRING), PROPERTY_NONE, 0}, \
+ { SW_PROP_NMID(UNO_NAME_LAYOUT_SIZE), WID_LAYOUT_SIZE, CPPU_E2T(CPPUTYPE_AWTSIZE), PropertyAttribute::MAYBEVOID | PropertyAttribute::READONLY, 0 },
+
+
+
+#define COMMON_TEXT_CONTENT_PROPERTIES \
+ { SW_PROP_NMID(UNO_NAME_ANCHOR_TYPE), FN_UNO_ANCHOR_TYPE, CPPU_E2T(CPPUTYPE_TXTCNTANCHOR), PropertyAttribute::READONLY, MID_ANCHOR_ANCHORTYPE},\
+ ANCHOR_TYPES_PROPERTY\
+ { SW_PROP_NMID(UNO_NAME_TEXT_WRAP), FN_UNO_TEXT_WRAP, CPPU_E2T(CPPUTYPE_WRAPTXTMODE), PropertyAttribute::READONLY, MID_SURROUND_SURROUNDTYPE },
+
+
+#define _PROP_DIFF_FONTHEIGHT \
+ { SW_PROP_NMID(UNO_NAME_CHAR_PROP_HEIGHT), RES_CHRATR_FONTSIZE , CPPU_E2T(CPPUTYPE_FLOAT), PROPERTY_NONE , MID_FONTHEIGHT_PROP},\
+ { SW_PROP_NMID(UNO_NAME_CHAR_DIFF_HEIGHT), RES_CHRATR_FONTSIZE , CPPU_E2T(CPPUTYPE_INT16), PROPERTY_NONE , MID_FONTHEIGHT_DIFF|CONVERT_TWIPS},\
+ { SW_PROP_NMID(UNO_NAME_CHAR_PROP_HEIGHT_ASIAN), RES_CHRATR_CJK_FONTSIZE , CPPU_E2T(CPPUTYPE_FLOAT), PROPERTY_NONE , MID_FONTHEIGHT_PROP},\
+ { SW_PROP_NMID(UNO_NAME_CHAR_DIFF_HEIGHT_ASIAN), RES_CHRATR_CJK_FONTSIZE , CPPU_E2T(CPPUTYPE_INT16), PROPERTY_NONE , MID_FONTHEIGHT_DIFF|CONVERT_TWIPS},\
+ { SW_PROP_NMID(UNO_NAME_CHAR_PROP_HEIGHT_COMPLEX), RES_CHRATR_CTL_FONTSIZE , CPPU_E2T(CPPUTYPE_FLOAT), PROPERTY_NONE , MID_FONTHEIGHT_PROP},\
+ { SW_PROP_NMID(UNO_NAME_CHAR_DIFF_HEIGHT_COMPLEX), RES_CHRATR_CTL_FONTSIZE , CPPU_E2T(CPPUTYPE_INT16), PROPERTY_NONE , MID_FONTHEIGHT_DIFF|CONVERT_TWIPS},
+
+
+#define COMMON_PARA_STYLE_PROPERTIES \
+ { SW_PROP_NMID(UNO_NAME_BREAK_TYPE), RES_BREAK, CPPU_E2T(CPPUTYPE_BREAK), PROPERTY_NONE, 0},\
+ { SW_PROP_NMID(UNO_NAME_PAGE_DESC_NAME), RES_PAGEDESC, CPPU_E2T(CPPUTYPE_OUSTRING), PropertyAttribute::MAYBEVOID, MID_PAGEDESC_PAGEDESCNAME },\
+ { SW_PROP_NMID(UNO_NAME_PAGE_NUMBER_OFFSET), RES_PAGEDESC, CPPU_E2T(CPPUTYPE_INT16), PropertyAttribute::MAYBEVOID, MID_PAGEDESC_PAGENUMOFFSET},\
+ { SW_PROP_NMID(UNO_NAME_CHAR_AUTO_KERNING), RES_CHRATR_AUTOKERN , CPPU_E2T(CPPUTYPE_BOOLEAN) , PROPERTY_NONE, 0},\
+ { SW_PROP_NMID(UNO_NAME_CHAR_BACK_TRANSPARENT), RES_CHRATR_BACKGROUND, CPPU_E2T(CPPUTYPE_BOOLEAN), PROPERTY_NONE ,MID_GRAPHIC_TRANSPARENT },\
+ { SW_PROP_NMID(UNO_NAME_CHAR_BACK_COLOR), RES_CHRATR_BACKGROUND, CPPU_E2T(CPPUTYPE_INT32), PROPERTY_NONE ,MID_BACK_COLOR },\
+ { SW_PROP_NMID(UNO_NAME_PARA_BACK_COLOR), RES_BACKGROUND, CPPU_E2T(CPPUTYPE_INT32), PROPERTY_NONE ,MID_BACK_COLOR },\
+ { SW_PROP_NMID(UNO_NAME_PARA_BACK_TRANSPARENT), RES_BACKGROUND, CPPU_E2T(CPPUTYPE_BOOLEAN), PROPERTY_NONE ,MID_GRAPHIC_TRANSPARENT },\
+ { SW_PROP_NMID(UNO_NAME_PARA_GRAPHIC_URL), RES_BACKGROUND, CPPU_E2T(CPPUTYPE_OUSTRING), PROPERTY_NONE ,MID_GRAPHIC_URL },\
+ { SW_PROP_NMID(UNO_NAME_PARA_GRAPHIC_FILTER), RES_BACKGROUND, CPPU_E2T(CPPUTYPE_OUSTRING), PROPERTY_NONE ,MID_GRAPHIC_FILTER },\
+ { SW_PROP_NMID(UNO_NAME_PARA_GRAPHIC_LOCATION), RES_BACKGROUND, CPPU_E2T(CPPUTYPE_GRAPHICLOC), PROPERTY_NONE ,MID_GRAPHIC_POSITION},\
+ { SW_PROP_NMID(UNO_NAME_CHAR_CASE_MAP), RES_CHRATR_CASEMAP, CPPU_E2T(CPPUTYPE_INT16), PROPERTY_NONE, 0},\
+ { SW_PROP_NMID(UNO_NAME_CHAR_COLOR), RES_CHRATR_COLOR, CPPU_E2T(CPPUTYPE_INT32), PROPERTY_NONE, 0},\
+ { SW_PROP_NMID(UNO_NAME_CHAR_STRIKEOUT), RES_CHRATR_CROSSEDOUT, CPPU_E2T(CPPUTYPE_INT16), PropertyAttribute::MAYBEVOID, MID_CROSS_OUT},\
+ { SW_PROP_NMID(UNO_NAME_CHAR_CROSSED_OUT), RES_CHRATR_CROSSEDOUT, CPPU_E2T(CPPUTYPE_BOOLEAN) , PROPERTY_NONE, 0},\
+ { SW_PROP_NMID(UNO_NAME_CHAR_ESCAPEMENT), RES_CHRATR_ESCAPEMENT, CPPU_E2T(CPPUTYPE_INT16), PROPERTY_NONE, MID_ESC },\
+ { SW_PROP_NMID(UNO_NAME_CHAR_ESCAPEMENT_HEIGHT), RES_CHRATR_ESCAPEMENT, CPPU_E2T(CPPUTYPE_INT8) , PROPERTY_NONE, MID_ESC_HEIGHT},\
+ { SW_PROP_NMID(UNO_NAME_CHAR_FLASH), RES_CHRATR_BLINK , CPPU_E2T(CPPUTYPE_BOOLEAN) , PROPERTY_NONE, 0},\
+ { SW_PROP_NMID(UNO_NAME_CHAR_HIDDEN), RES_CHRATR_HIDDEN, CPPU_E2T(CPPUTYPE_BOOLEAN) , PROPERTY_NONE, 0},\
+ _STANDARD_FONT_PROPERTIES\
+ _CJK_FONT_PROPERTIES\
+ _CTL_FONT_PROPERTIES\
+ { SW_PROP_NMID(UNO_NAME_CHAR_UNDERLINE), RES_CHRATR_UNDERLINE , CPPU_E2T(CPPUTYPE_INT16), PROPERTY_NONE, MID_TL_STYLE},\
+ { SW_PROP_NMID(UNO_NAME_CHAR_UNDERLINE_COLOR), RES_CHRATR_UNDERLINE , CPPU_E2T(CPPUTYPE_INT32), PROPERTY_NONE, MID_TL_COLOR},\
+ { SW_PROP_NMID(UNO_NAME_CHAR_UNDERLINE_HAS_COLOR), RES_CHRATR_UNDERLINE , CPPU_E2T(CPPUTYPE_BOOLEAN), PROPERTY_NONE, MID_TL_HASCOLOR},\
+ { SW_PROP_NMID(UNO_NAME_CHAR_OVERLINE), RES_CHRATR_OVERLINE , CPPU_E2T(CPPUTYPE_INT16), PROPERTY_NONE, MID_TL_STYLE},\
+ { SW_PROP_NMID(UNO_NAME_CHAR_OVERLINE_COLOR), RES_CHRATR_OVERLINE , CPPU_E2T(CPPUTYPE_INT32), PROPERTY_NONE, MID_TL_COLOR},\
+ { SW_PROP_NMID(UNO_NAME_CHAR_OVERLINE_HAS_COLOR), RES_CHRATR_OVERLINE , CPPU_E2T(CPPUTYPE_BOOLEAN), PROPERTY_NONE, MID_TL_HASCOLOR},\
+ { SW_PROP_NMID(UNO_NAME_PARA_LEFT_MARGIN), RES_LR_SPACE, CPPU_E2T(CPPUTYPE_INT32), PROPERTY_NONE, MID_TXT_LMARGIN|CONVERT_TWIPS},\
+ { SW_PROP_NMID(UNO_NAME_PARA_RIGHT_MARGIN), RES_LR_SPACE, CPPU_E2T(CPPUTYPE_INT32), PROPERTY_NONE, MID_R_MARGIN|CONVERT_TWIPS},\
+ { SW_PROP_NMID(UNO_NAME_PARA_LEFT_MARGIN_RELATIVE), RES_LR_SPACE, CPPU_E2T(CPPUTYPE_INT16), PROPERTY_NONE, MID_L_REL_MARGIN},\
+ { SW_PROP_NMID(UNO_NAME_PARA_RIGHT_MARGIN_RELATIVE), RES_LR_SPACE, CPPU_E2T(CPPUTYPE_INT16), PROPERTY_NONE, MID_R_REL_MARGIN},\
+ { SW_PROP_NMID(UNO_NAME_PARA_IS_AUTO_FIRST_LINE_INDENT), RES_LR_SPACE, CPPU_E2T(CPPUTYPE_BOOLEAN), PROPERTY_NONE, MID_FIRST_AUTO},\
+ { SW_PROP_NMID(UNO_NAME_PARA_FIRST_LINE_INDENT), RES_LR_SPACE, CPPU_E2T(CPPUTYPE_INT32), PROPERTY_NONE, MID_FIRST_LINE_INDENT|CONVERT_TWIPS},\
+ { SW_PROP_NMID(UNO_NAME_PARA_FIRST_LINE_INDENT_RELATIVE), RES_LR_SPACE, CPPU_E2T(CPPUTYPE_INT32), PROPERTY_NONE, MID_FIRST_LINE_REL_INDENT|CONVERT_TWIPS},\
+ { SW_PROP_NMID(UNO_NAME_CHAR_KERNING), RES_CHRATR_KERNING , CPPU_E2T(CPPUTYPE_INT16) , PROPERTY_NONE, CONVERT_TWIPS},\
+ { SW_PROP_NMID(UNO_NAME_CHAR_NO_HYPHENATION), RES_CHRATR_NOHYPHEN , CPPU_E2T(CPPUTYPE_BOOLEAN) , PROPERTY_NONE, 0},\
+ { SW_PROP_NMID(UNO_NAME_CHAR_SHADOWED), RES_CHRATR_SHADOWED , CPPU_E2T(CPPUTYPE_BOOLEAN) , PROPERTY_NONE, 0},\
+ { SW_PROP_NMID(UNO_NAME_CHAR_CONTOURED), RES_CHRATR_CONTOUR, CPPU_E2T(CPPUTYPE_BOOLEAN) , PROPERTY_NONE, 0},\
+ { SW_PROP_NMID(UNO_NAME_DROP_CAP_FORMAT), RES_PARATR_DROP, CPPU_E2T(CPPUTYPE_DROPCAPFMT) , PROPERTY_NONE, MID_DROPCAP_FORMAT|CONVERT_TWIPS },\
+ { SW_PROP_NMID(UNO_NAME_DROP_CAP_WHOLE_WORD), RES_PARATR_DROP, CPPU_E2T(CPPUTYPE_BOOLEAN) , PROPERTY_NONE, MID_DROPCAP_WHOLE_WORD },\
+ { SW_PROP_NMID(UNO_NAME_DROP_CAP_CHAR_STYLE_NAME), RES_PARATR_DROP, CPPU_E2T(CPPUTYPE_OUSTRING) , PropertyAttribute::MAYBEVOID, MID_DROPCAP_CHAR_STYLE_NAME },\
+ { SW_PROP_NMID(UNO_NAME_PARA_KEEP_TOGETHER), RES_KEEP, CPPU_E2T(CPPUTYPE_BOOLEAN) , PROPERTY_NONE, 0},\
+ { SW_PROP_NMID(UNO_NAME_PARA_SPLIT), RES_PARATR_SPLIT, CPPU_E2T(CPPUTYPE_BOOLEAN) , PROPERTY_NONE, 0},\
+ { SW_PROP_NMID(UNO_NAME_PARA_WIDOWS), RES_PARATR_WIDOWS, CPPU_E2T(CPPUTYPE_INT8),PropertyAttribute::MAYBEVOID, 0},\
+ { SW_PROP_NMID(UNO_NAME_PARA_ORPHANS), RES_PARATR_ORPHANS, CPPU_E2T(CPPUTYPE_INT8),PropertyAttribute::MAYBEVOID, 0},\
+ { SW_PROP_NMID(UNO_NAME_PARA_EXPAND_SINGLE_WORD), RES_PARATR_ADJUST, CPPU_E2T(CPPUTYPE_BOOLEAN) , PROPERTY_NONE, MID_EXPAND_SINGLE },\
+ { SW_PROP_NMID(UNO_NAME_PARA_LAST_LINE_ADJUST), RES_PARATR_ADJUST, CPPU_E2T(CPPUTYPE_INT16), PROPERTY_NONE, MID_LAST_LINE_ADJUST},\
+ { SW_PROP_NMID(UNO_NAME_PARA_LINE_NUMBER_COUNT), RES_LINENUMBER, CPPU_E2T(CPPUTYPE_BOOLEAN), PROPERTY_NONE ,MID_LINENUMBER_COUNT },\
+ { SW_PROP_NMID(UNO_NAME_PARA_LINE_NUMBER_START_VALUE), RES_LINENUMBER, CPPU_E2T(CPPUTYPE_INT32), PROPERTY_NONE ,MID_LINENUMBER_STARTVALUE},\
+ { SW_PROP_NMID(UNO_NAME_PARA_LINE_SPACING), RES_PARATR_LINESPACING, CPPU_E2T(CPPUTYPE_LINESPACE),PROPERTY_NONE, CONVERT_TWIPS},\
+ { SW_PROP_NMID(UNO_NAME_PARA_ADJUST), RES_PARATR_ADJUST, CPPU_E2T(CPPUTYPE_INT16), PROPERTY_NONE, MID_PARA_ADJUST},\
+ { SW_PROP_NMID(UNO_NAME_PARA_REGISTER_MODE_ACTIVE), RES_PARATR_REGISTER, CPPU_E2T(CPPUTYPE_BOOLEAN) , PROPERTY_NONE, 0},\
+ { SW_PROP_NMID(UNO_NAME_PARA_TOP_MARGIN), RES_UL_SPACE, CPPU_E2T(CPPUTYPE_INT32), PROPERTY_NONE, MID_UP_MARGIN|CONVERT_TWIPS},\
+ { SW_PROP_NMID(UNO_NAME_PARA_BOTTOM_MARGIN), RES_UL_SPACE, CPPU_E2T(CPPUTYPE_INT32), PROPERTY_NONE, MID_LO_MARGIN|CONVERT_TWIPS},\
+ { SW_PROP_NMID(UNO_NAME_PARA_TOP_MARGIN_RELATIVE), RES_UL_SPACE, CPPU_E2T(CPPUTYPE_INT16), PROPERTY_NONE, MID_UP_REL_MARGIN},\
+ { SW_PROP_NMID(UNO_NAME_PARA_BOTTOM_MARGIN_RELATIVE), RES_UL_SPACE, CPPU_E2T(CPPUTYPE_INT16), PROPERTY_NONE, MID_LO_REL_MARGIN},\
+ TABSTOPS_MAP_ENTRY\
+ { SW_PROP_NMID(UNO_NAME_CHAR_WORD_MODE), RES_CHRATR_WORDLINEMODE,CPPU_E2T(CPPUTYPE_BOOLEAN) , PROPERTY_NONE, 0},\
+ { SW_PROP_NMID(UNO_NAME_LEFT_BORDER), RES_BOX, CPPU_E2T(CPPUTYPE_BORDERLINE), 0, LEFT_BORDER |CONVERT_TWIPS },\
+ { SW_PROP_NMID(UNO_NAME_RIGHT_BORDER), RES_BOX, CPPU_E2T(CPPUTYPE_BORDERLINE), 0, RIGHT_BORDER |CONVERT_TWIPS },\
+ { SW_PROP_NMID(UNO_NAME_TOP_BORDER), RES_BOX, CPPU_E2T(CPPUTYPE_BORDERLINE), 0, TOP_BORDER |CONVERT_TWIPS },\
+ { SW_PROP_NMID(UNO_NAME_BOTTOM_BORDER), RES_BOX, CPPU_E2T(CPPUTYPE_BORDERLINE), 0, BOTTOM_BORDER|CONVERT_TWIPS },\
+ { SW_PROP_NMID(UNO_NAME_BORDER_DISTANCE), RES_BOX, CPPU_E2T(CPPUTYPE_INT32), 0, BORDER_DISTANCE|CONVERT_TWIPS },\
+ { SW_PROP_NMID(UNO_NAME_LEFT_BORDER_DISTANCE), RES_BOX, CPPU_E2T(CPPUTYPE_INT32), 0, LEFT_BORDER_DISTANCE |CONVERT_TWIPS },\
+ { SW_PROP_NMID(UNO_NAME_RIGHT_BORDER_DISTANCE), RES_BOX, CPPU_E2T(CPPUTYPE_INT32), 0, RIGHT_BORDER_DISTANCE |CONVERT_TWIPS },\
+ { SW_PROP_NMID(UNO_NAME_TOP_BORDER_DISTANCE), RES_BOX, CPPU_E2T(CPPUTYPE_INT32), 0, TOP_BORDER_DISTANCE |CONVERT_TWIPS },\
+ { SW_PROP_NMID(UNO_NAME_BOTTOM_BORDER_DISTANCE), RES_BOX, CPPU_E2T(CPPUTYPE_INT32), 0, BOTTOM_BORDER_DISTANCE|CONVERT_TWIPS },\
+ { SW_PROP_NMID(UNO_NAME_PARA_IS_HYPHENATION), RES_PARATR_HYPHENZONE, CPPU_E2T(CPPUTYPE_BOOLEAN), PropertyAttribute::MAYBEVOID, MID_IS_HYPHEN },\
+ { SW_PROP_NMID(UNO_NAME_PARA_HYPHENATION_MAX_LEADING_CHARS), RES_PARATR_HYPHENZONE, CPPU_E2T(CPPUTYPE_INT16), PropertyAttribute::MAYBEVOID, MID_HYPHEN_MIN_LEAD },\
+ { SW_PROP_NMID(UNO_NAME_PARA_HYPHENATION_MAX_TRAILING_CHARS), RES_PARATR_HYPHENZONE, CPPU_E2T(CPPUTYPE_INT16), PropertyAttribute::MAYBEVOID, MID_HYPHEN_MIN_TRAIL },\
+ { SW_PROP_NMID(UNO_NAME_PARA_HYPHENATION_MAX_HYPHENS), RES_PARATR_HYPHENZONE, CPPU_E2T(CPPUTYPE_INT16), PropertyAttribute::MAYBEVOID, MID_HYPHEN_MAX_HYPHENS},\
+ { SW_PROP_NMID(UNO_NAME_NUMBERING_STYLE_NAME), RES_PARATR_NUMRULE, CPPU_E2T(CPPUTYPE_OUSTRING), PropertyAttribute::MAYBEVOID, 0},\
+ { SW_PROP_NMID(UNO_NAME_PARA_USER_DEFINED_ATTRIBUTES), RES_UNKNOWNATR_CONTAINER, CPPU_E2T(CPPUTYPE_REFNAMECNT), PropertyAttribute::MAYBEVOID, 0 },\
+ { SW_PROP_NMID(UNO_NAME_PARA_SHADOW_FORMAT), RES_SHADOW, CPPU_E2T(CPPUTYPE_SHADOWFMT), PROPERTY_NONE, CONVERT_TWIPS},\
+ { SW_PROP_NMID(UNO_NAME_CHAR_COMBINE_IS_ON), RES_CHRATR_TWO_LINES, CPPU_E2T(CPPUTYPE_BOOLEAN), PROPERTY_NONE, MID_TWOLINES},\
+ { SW_PROP_NMID(UNO_NAME_CHAR_COMBINE_PREFIX), RES_CHRATR_TWO_LINES, CPPU_E2T(CPPUTYPE_OUSTRING), PROPERTY_NONE, MID_START_BRACKET},\
+ { SW_PROP_NMID(UNO_NAME_CHAR_COMBINE_SUFFIX), RES_CHRATR_TWO_LINES, CPPU_E2T(CPPUTYPE_OUSTRING), PROPERTY_NONE, MID_END_BRACKET},\
+ { SW_PROP_NMID(UNO_NAME_CHAR_EMPHASIS), RES_CHRATR_EMPHASIS_MARK, CPPU_E2T(CPPUTYPE_INT16), PROPERTY_NONE, MID_EMPHASIS},\
+ { SW_PROP_NMID(UNO_NAME_PARA_IS_HANGING_PUNCTUATION), RES_PARATR_HANGINGPUNCTUATION, CPPU_E2T(CPPUTYPE_BOOLEAN), PROPERTY_NONE ,0 },\
+ { SW_PROP_NMID(UNO_NAME_PARA_IS_CHARACTER_DISTANCE), RES_PARATR_SCRIPTSPACE, CPPU_E2T(CPPUTYPE_BOOLEAN), PROPERTY_NONE ,0 },\
+ { SW_PROP_NMID(UNO_NAME_PARA_IS_FORBIDDEN_RULES), RES_PARATR_FORBIDDEN_RULES, CPPU_E2T(CPPUTYPE_BOOLEAN), PROPERTY_NONE ,0 },\
+ { SW_PROP_NMID(UNO_NAME_PARA_VERT_ALIGNMENT), RES_PARATR_VERTALIGN, CPPU_E2T(CPPUTYPE_INT16), PROPERTY_NONE , 0 },\
+ { SW_PROP_NMID(UNO_NAME_CHAR_ROTATION), RES_CHRATR_ROTATE, CPPU_E2T(CPPUTYPE_INT16), PROPERTY_NONE, MID_ROTATE },\
+ { SW_PROP_NMID(UNO_NAME_CHAR_ROTATION_IS_FIT_TO_LINE), RES_CHRATR_ROTATE, CPPU_E2T(CPPUTYPE_BOOLEAN), PROPERTY_NONE, MID_FITTOLINE },\
+ { SW_PROP_NMID(UNO_NAME_CHAR_SCALE_WIDTH), RES_CHRATR_SCALEW, CPPU_E2T(CPPUTYPE_INT16), PROPERTY_NONE, 0 },\
+ { SW_PROP_NMID(UNO_NAME_CHAR_RELIEF), RES_CHRATR_RELIEF, CPPU_E2T(CPPUTYPE_INT16), PROPERTY_NONE, MID_RELIEF },\
+ _PROP_DIFF_FONTHEIGHT\
+ { SW_PROP_NMID(UNO_NAME_FOLLOW_STYLE), FN_UNO_FOLLOW_STYLE, CPPU_E2T(CPPUTYPE_OUSTRING), PROPERTY_NONE, 0},\
+ { SW_PROP_NMID(UNO_NAME_IS_PHYSICAL), FN_UNO_IS_PHYSICAL, CPPU_E2T(CPPUTYPE_BOOLEAN), PropertyAttribute::READONLY, 0},\
+ { SW_PROP_NMID(UNO_NAME_IS_AUTO_UPDATE), FN_UNO_IS_AUTO_UPDATE, CPPU_E2T(CPPUTYPE_BOOLEAN), PROPERTY_NONE, 0},\
+ { SW_PROP_NMID(UNO_NAME_DISPLAY_NAME), FN_UNO_DISPLAY_NAME, CPPU_E2T(CPPUTYPE_OUSTRING), PropertyAttribute::READONLY, 0},\
+ { SW_PROP_NMID(UNO_NAME_CATEGORY), FN_UNO_CATEGORY, CPPU_E2T(CPPUTYPE_INT16), PROPERTY_NONE , 0 },\
+ { SW_PROP_NMID(UNO_NAME_WRITING_MODE), RES_FRAMEDIR, CPPU_E2T(CPPUTYPE_INT16), PROPERTY_NONE, 0 },\
+ { SW_PROP_NMID(UNO_NAME_PARA_IS_CONNECT_BORDER), RES_PARATR_CONNECT_BORDER, CPPU_E2T(CPPUTYPE_BOOLEAN), PropertyAttribute::MAYBEVOID, 0},\
+ { SW_PROP_NMID(UNO_NAME_SNAP_TO_GRID), RES_PARATR_SNAPTOGRID, CPPU_E2T(CPPUTYPE_BOOLEAN), PropertyAttribute::MAYBEVOID, 0 }, \
+ { SW_PROP_NMID(UNO_NAME_OUTLINE_LEVEL), RES_PARATR_OUTLINELEVEL,CPPU_E2T(CPPUTYPE_INT16), PropertyAttribute::MAYBEVOID, 0},
+
+
+#define COMMON_FLDTYP_PROPERTIES \
+ { SW_PROP_NMID(UNO_NAME_IS_FIELD_USED), FIELD_PROP_IS_FIELD_USED, CPPU_E2T(CPPUTYPE_FLOAT), PropertyAttribute::READONLY, 0},\
+ { SW_PROP_NMID(UNO_NAME_IS_FIELD_DISPLAYED), FIELD_PROP_IS_FIELD_DISPLAYED, CPPU_E2T(CPPUTYPE_INT16), PropertyAttribute::READONLY, 0},\
+
+
+const SfxItemPropertyMapEntry* SwUnoPropertyMapProvider::GetPropertyMapEntries(sal_uInt16 nPropertyId)
+{
+ DBG_ASSERT(nPropertyId < PROPERTY_MAP_END, "Id ?" );
+ if( !aMapEntriesArr[ nPropertyId ] )
+ {
+ switch(nPropertyId)
+ {
+ case PROPERTY_MAP_TEXT_CURSOR:
+ {
+ static SfxItemPropertyMapEntry aCharAndParaMap_Impl[] =
+ {
+ COMPLETE_TEXT_CURSOR_MAP
+ {0,0,0,0,0,0}
+ };
+ aMapEntriesArr[nPropertyId] = aCharAndParaMap_Impl;
+ }
+ break;
+ case PROPERTY_MAP_PARAGRAPH:
+ {
+ static SfxItemPropertyMapEntry aParagraphMap_Impl[] =
+ {
+ COMMON_CRSR_PARA_PROPERTIES_2
+ TABSTOPS_MAP_ENTRY
+ COMMON_TEXT_CONTENT_PROPERTIES
+ { SW_PROP_NMID(UNO_NAME_CHAR_STYLE_NAME), RES_TXTATR_CHARFMT, CPPU_E2T(CPPUTYPE_OUSTRING), PropertyAttribute::MAYBEVOID, 0},\
+ { SW_PROP_NMID(UNO_NAME_CHAR_STYLE_NAMES), FN_UNO_CHARFMT_SEQUENCE, CPPU_E2T(CPPUTYPE_OUSTRINGS), PropertyAttribute::MAYBEVOID, 0},\
+ {0,0,0,0,0,0}
+ };
+ aMapEntriesArr[nPropertyId] = aParagraphMap_Impl;
+ }
+ break;
+ case PROPERTY_MAP_PARA_AUTO_STYLE :
+ {
+ static SfxItemPropertyMapEntry aAutoParaStyleMap [] =
+ {
+ { SW_PROP_NMID(UNO_NAME_PARA_STYLE_NAME), RES_FRMATR_STYLE_NAME, CPPU_E2T(CPPUTYPE_OUSTRING), PropertyAttribute::MAYBEVOID, 0}, \
+ { SW_PROP_NMID(UNO_NAME_PAGE_STYLE_NAME), FN_UNO_PAGE_STYLE, CPPU_E2T(CPPUTYPE_OUSTRING), PropertyAttribute::MAYBEVOID|PropertyAttribute::READONLY, 0}, \
+ { SW_PROP_NMID(UNO_NAME_NUMBERING_IS_NUMBER), FN_UNO_IS_NUMBER, CPPU_E2T(CPPUTYPE_BOOLEAN) , PropertyAttribute::MAYBEVOID, 0}, \
+ { SW_PROP_NMID(UNO_NAME_NUMBERING_LEVEL), FN_UNO_NUM_LEVEL, CPPU_E2T(CPPUTYPE_INT16), PropertyAttribute::MAYBEVOID, 0}, \
+ { SW_PROP_NMID(UNO_NAME_NUMBERING_START_VALUE), FN_UNO_NUM_START_VALUE, CPPU_E2T(CPPUTYPE_INT16), PropertyAttribute::MAYBEVOID, CONVERT_TWIPS}, \
+ { SW_PROP_NMID(UNO_NAME_DOCUMENT_INDEX), FN_UNO_DOCUMENT_INDEX, CPPU_E2T(CPPUTYPE_REFDOCINDEX), PropertyAttribute::MAYBEVOID|PropertyAttribute::READONLY ,0 }, \
+ { SW_PROP_NMID(UNO_NAME_TEXT_TABLE), FN_UNO_TEXT_TABLE, CPPU_E2T(CPPUTYPE_REFTXTTABLE), PropertyAttribute::MAYBEVOID|PropertyAttribute::READONLY ,0 }, \
+ { SW_PROP_NMID(UNO_NAME_CELL), FN_UNO_CELL, CPPU_E2T(CPPUTYPE_REFCELL), PropertyAttribute::MAYBEVOID|PropertyAttribute::READONLY ,0 }, \
+ { SW_PROP_NMID(UNO_NAME_TEXT_FRAME), FN_UNO_TEXT_FRAME, CPPU_E2T(CPPUTYPE_REFTEXTFRAME), PropertyAttribute::MAYBEVOID|PropertyAttribute::READONLY ,0 }, \
+ { SW_PROP_NMID(UNO_NAME_TEXT_SECTION), FN_UNO_TEXT_SECTION, CPPU_E2T(CPPUTYPE_REFTEXTSECTION), PropertyAttribute::MAYBEVOID|PropertyAttribute::READONLY ,0 }, \
+ { SW_PROP_NMID(UNO_NAME_PARA_CHAPTER_NUMBERING_LEVEL), FN_UNO_PARA_CHAPTER_NUMBERING_LEVEL,CPPU_E2T(CPPUTYPE_INT8), PROPERTY_NONE, 0}, \
+ { SW_PROP_NMID(UNO_NAME_PARA_CONDITIONAL_STYLE_NAME), RES_FRMATR_CONDITIONAL_STYLE_NAME, CPPU_E2T(CPPUTYPE_OUSTRING), PropertyAttribute::MAYBEVOID|PropertyAttribute::READONLY, 0}, \
+ { SW_PROP_NMID(UNO_NAME_PARA_IS_NUMBERING_RESTART), FN_NUMBER_NEWSTART, CPPU_E2T(CPPUTYPE_BOOLEAN), PropertyAttribute::MAYBEVOID, 0 }, \
+ { SW_PROP_NMID(UNO_NAME_OUTLINE_LEVEL), RES_PARATR_OUTLINELEVEL, CPPU_E2T(CPPUTYPE_INT16), PropertyAttribute::MAYBEVOID, 0},
+ COMMON_CRSR_PARA_PROPERTIES_WITHOUT_FN
+ TABSTOPS_MAP_ENTRY
+ COMMON_TEXT_CONTENT_PROPERTIES
+ { SW_PROP_NMID(UNO_NAME_PARA_AUTO_STYLE_NAME), RES_AUTO_STYLE, CPPU_E2T(CPPUTYPE_OUSTRING), PropertyAttribute::MAYBEVOID, 0},
+ {0,0,0,0,0,0}
+ };
+ aMapEntriesArr[nPropertyId] = aAutoParaStyleMap;
+ }
+ break;
+ case PROPERTY_MAP_CHAR_STYLE :
+ {
+ static SfxItemPropertyMapEntry aCharStyleMap [] =
+ {
+ { SW_PROP_NMID(UNO_NAME_CHAR_AUTO_KERNING), RES_CHRATR_AUTOKERN , CPPU_E2T(CPPUTYPE_BOOLEAN) , PROPERTY_NONE, 0},
+ { SW_PROP_NMID(UNO_NAME_CHAR_BACK_TRANSPARENT), RES_CHRATR_BACKGROUND, CPPU_E2T(CPPUTYPE_BOOLEAN), PROPERTY_NONE ,MID_GRAPHIC_TRANSPARENT },
+ { SW_PROP_NMID(UNO_NAME_CHAR_BACK_COLOR), RES_CHRATR_BACKGROUND, CPPU_E2T(CPPUTYPE_INT32), PROPERTY_NONE ,MID_BACK_COLOR },
+ { SW_PROP_NMID(UNO_NAME_CHAR_CASE_MAP), RES_CHRATR_CASEMAP, CPPU_E2T(CPPUTYPE_INT16), PROPERTY_NONE, 0},
+ { SW_PROP_NMID(UNO_NAME_CHAR_COLOR), RES_CHRATR_COLOR, CPPU_E2T(CPPUTYPE_INT32), PROPERTY_NONE, 0},
+ { SW_PROP_NMID(UNO_NAME_CHAR_STRIKEOUT), RES_CHRATR_CROSSEDOUT, CPPU_E2T(CPPUTYPE_INT16), PropertyAttribute::MAYBEVOID, MID_CROSS_OUT},
+ { SW_PROP_NMID(UNO_NAME_CHAR_CROSSED_OUT), RES_CHRATR_CROSSEDOUT, CPPU_E2T(CPPUTYPE_BOOLEAN) , PROPERTY_NONE, 0},
+ { SW_PROP_NMID(UNO_NAME_CHAR_ESCAPEMENT), RES_CHRATR_ESCAPEMENT, CPPU_E2T(CPPUTYPE_INT16), PROPERTY_NONE, MID_ESC },
+ { SW_PROP_NMID(UNO_NAME_CHAR_ESCAPEMENT_HEIGHT), RES_CHRATR_ESCAPEMENT, CPPU_E2T(CPPUTYPE_INT8) , PROPERTY_NONE, MID_ESC_HEIGHT},
+ { SW_PROP_NMID(UNO_NAME_CHAR_FLASH), RES_CHRATR_BLINK , CPPU_E2T(CPPUTYPE_BOOLEAN) , PROPERTY_NONE, 0},
+ { SW_PROP_NMID(UNO_NAME_CHAR_HIDDEN), RES_CHRATR_HIDDEN, CPPU_E2T(CPPUTYPE_BOOLEAN) , PROPERTY_NONE, 0},
+ _STANDARD_FONT_PROPERTIES
+ _CJK_FONT_PROPERTIES
+ _CTL_FONT_PROPERTIES
+ { SW_PROP_NMID(UNO_NAME_CHAR_UNDERLINE), RES_CHRATR_UNDERLINE , CPPU_E2T(CPPUTYPE_INT16), PROPERTY_NONE, MID_TL_STYLE},
+ { SW_PROP_NMID(UNO_NAME_CHAR_UNDERLINE_COLOR), RES_CHRATR_UNDERLINE , CPPU_E2T(CPPUTYPE_INT32), PROPERTY_NONE, MID_TL_COLOR},
+ { SW_PROP_NMID(UNO_NAME_CHAR_UNDERLINE_HAS_COLOR), RES_CHRATR_UNDERLINE , CPPU_E2T(CPPUTYPE_BOOLEAN), PROPERTY_NONE, MID_TL_HASCOLOR},
+ { SW_PROP_NMID(UNO_NAME_CHAR_OVERLINE), RES_CHRATR_OVERLINE , CPPU_E2T(CPPUTYPE_INT16), PROPERTY_NONE, MID_TL_STYLE},
+ { SW_PROP_NMID(UNO_NAME_CHAR_OVERLINE_COLOR), RES_CHRATR_OVERLINE , CPPU_E2T(CPPUTYPE_INT32), PROPERTY_NONE, MID_TL_COLOR},
+ { SW_PROP_NMID(UNO_NAME_CHAR_OVERLINE_HAS_COLOR), RES_CHRATR_OVERLINE , CPPU_E2T(CPPUTYPE_BOOLEAN), PROPERTY_NONE, MID_TL_HASCOLOR},
+ { SW_PROP_NMID(UNO_NAME_CHAR_KERNING), RES_CHRATR_KERNING , CPPU_E2T(CPPUTYPE_INT16) , PROPERTY_NONE, CONVERT_TWIPS},
+ { SW_PROP_NMID(UNO_NAME_CHAR_NO_HYPHENATION), RES_CHRATR_NOHYPHEN , CPPU_E2T(CPPUTYPE_BOOLEAN) , PROPERTY_NONE, 0},
+ { SW_PROP_NMID(UNO_NAME_CHAR_SHADOWED), RES_CHRATR_SHADOWED , CPPU_E2T(CPPUTYPE_BOOLEAN) , PROPERTY_NONE, 0},
+ { SW_PROP_NMID(UNO_NAME_CHAR_CONTOURED), RES_CHRATR_CONTOUR, CPPU_E2T(CPPUTYPE_BOOLEAN) , PROPERTY_NONE, 0},
+ { SW_PROP_NMID(UNO_NAME_CHAR_WORD_MODE), RES_CHRATR_WORDLINEMODE,CPPU_E2T(CPPUTYPE_BOOLEAN) , PROPERTY_NONE, 0},
+ { SW_PROP_NMID(UNO_NAME_USER_DEFINED_ATTRIBUTES), RES_UNKNOWNATR_CONTAINER, CPPU_E2T(CPPUTYPE_REFNAMECNT), PropertyAttribute::MAYBEVOID, 0 },
+ { SW_PROP_NMID(UNO_NAME_IS_PHYSICAL), FN_UNO_IS_PHYSICAL, CPPU_E2T(CPPUTYPE_BOOLEAN), PropertyAttribute::READONLY, 0},
+ { SW_PROP_NMID(UNO_NAME_DISPLAY_NAME), FN_UNO_DISPLAY_NAME, CPPU_E2T(CPPUTYPE_OUSTRING), PropertyAttribute::READONLY, 0},
+ { SW_PROP_NMID(UNO_NAME_CHAR_COMBINE_IS_ON), RES_CHRATR_TWO_LINES, CPPU_E2T(CPPUTYPE_BOOLEAN), PROPERTY_NONE, MID_TWOLINES},
+ { SW_PROP_NMID(UNO_NAME_CHAR_COMBINE_PREFIX), RES_CHRATR_TWO_LINES, CPPU_E2T(CPPUTYPE_OUSTRING), PROPERTY_NONE, MID_START_BRACKET},
+ { SW_PROP_NMID(UNO_NAME_CHAR_COMBINE_SUFFIX), RES_CHRATR_TWO_LINES, CPPU_E2T(CPPUTYPE_OUSTRING), PROPERTY_NONE, MID_END_BRACKET},
+ { SW_PROP_NMID(UNO_NAME_CHAR_EMPHASIS), RES_CHRATR_EMPHASIS_MARK, CPPU_E2T(CPPUTYPE_INT16), PROPERTY_NONE, MID_EMPHASIS},
+ _PROP_DIFF_FONTHEIGHT
+ { SW_PROP_NMID(UNO_NAME_CHAR_ROTATION), RES_CHRATR_ROTATE, CPPU_E2T(CPPUTYPE_INT16), PROPERTY_NONE, MID_ROTATE },
+ { SW_PROP_NMID(UNO_NAME_CHAR_ROTATION_IS_FIT_TO_LINE), RES_CHRATR_ROTATE, CPPU_E2T(CPPUTYPE_BOOLEAN), PROPERTY_NONE, MID_FITTOLINE },
+ { SW_PROP_NMID(UNO_NAME_CHAR_SCALE_WIDTH), RES_CHRATR_SCALEW, CPPU_E2T(CPPUTYPE_INT16), PROPERTY_NONE, 0 },
+ { SW_PROP_NMID(UNO_NAME_CHAR_RELIEF), RES_CHRATR_RELIEF, CPPU_E2T(CPPUTYPE_INT16), PROPERTY_NONE, MID_RELIEF },
+ {0,0,0,0,0,0}
+ };
+ aMapEntriesArr[nPropertyId] = aCharStyleMap;
+ }
+ break;
+ case PROPERTY_MAP_CHAR_AUTO_STYLE :
+ {
+ // same as PROPERTY_MAP_TEXTPORTION_EXTENSIONS
+ static SfxItemPropertyMapEntry aAutoCharStyleMap [] =
+ {
+ { SW_PROP_NMID(UNO_NAME_CHAR_AUTO_KERNING), RES_CHRATR_AUTOKERN , CPPU_E2T(CPPUTYPE_BOOLEAN) , PROPERTY_NONE, 0},
+ { SW_PROP_NMID(UNO_NAME_CHAR_BACK_TRANSPARENT), RES_CHRATR_BACKGROUND, CPPU_E2T(CPPUTYPE_BOOLEAN), PROPERTY_NONE ,MID_GRAPHIC_TRANSPARENT },
+ { SW_PROP_NMID(UNO_NAME_CHAR_BACK_COLOR), RES_CHRATR_BACKGROUND, CPPU_E2T(CPPUTYPE_INT32), PROPERTY_NONE ,MID_BACK_COLOR },
+ { SW_PROP_NMID(UNO_NAME_CHAR_CASE_MAP), RES_CHRATR_CASEMAP, CPPU_E2T(CPPUTYPE_INT16), PROPERTY_NONE, 0},
+ { SW_PROP_NMID(UNO_NAME_CHAR_COLOR), RES_CHRATR_COLOR, CPPU_E2T(CPPUTYPE_INT32), PROPERTY_NONE, 0},
+ { SW_PROP_NMID(UNO_NAME_CHAR_STRIKEOUT), RES_CHRATR_CROSSEDOUT, CPPU_E2T(CPPUTYPE_INT16), PropertyAttribute::MAYBEVOID, MID_CROSS_OUT},
+ { SW_PROP_NMID(UNO_NAME_CHAR_CROSSED_OUT), RES_CHRATR_CROSSEDOUT, CPPU_E2T(CPPUTYPE_BOOLEAN) , PROPERTY_NONE, 0},
+ { SW_PROP_NMID(UNO_NAME_CHAR_ESCAPEMENT), RES_CHRATR_ESCAPEMENT, CPPU_E2T(CPPUTYPE_INT16), PROPERTY_NONE, MID_ESC },
+ { SW_PROP_NMID(UNO_NAME_CHAR_ESCAPEMENT_HEIGHT), RES_CHRATR_ESCAPEMENT, CPPU_E2T(CPPUTYPE_INT8) , PROPERTY_NONE, MID_ESC_HEIGHT},
+ { SW_PROP_NMID(UNO_NAME_CHAR_FLASH), RES_CHRATR_BLINK , CPPU_E2T(CPPUTYPE_BOOLEAN) , PROPERTY_NONE, 0},
+ { SW_PROP_NMID(UNO_NAME_CHAR_HIDDEN), RES_CHRATR_HIDDEN, CPPU_E2T(CPPUTYPE_BOOLEAN) , PROPERTY_NONE, 0},
+ _STANDARD_FONT_PROPERTIES
+ _CJK_FONT_PROPERTIES
+ _CTL_FONT_PROPERTIES
+ { SW_PROP_NMID(UNO_NAME_CHAR_UNDERLINE), RES_CHRATR_UNDERLINE , CPPU_E2T(CPPUTYPE_INT16), PROPERTY_NONE, MID_TL_STYLE},
+ { SW_PROP_NMID(UNO_NAME_CHAR_UNDERLINE_COLOR), RES_CHRATR_UNDERLINE , CPPU_E2T(CPPUTYPE_INT32), PROPERTY_NONE, MID_TL_COLOR},
+ { SW_PROP_NMID(UNO_NAME_CHAR_UNDERLINE_HAS_COLOR), RES_CHRATR_UNDERLINE , CPPU_E2T(CPPUTYPE_BOOLEAN), PROPERTY_NONE, MID_TL_HASCOLOR},
+ { SW_PROP_NMID(UNO_NAME_CHAR_OVERLINE), RES_CHRATR_OVERLINE , CPPU_E2T(CPPUTYPE_INT16), PROPERTY_NONE, MID_TL_STYLE},
+ { SW_PROP_NMID(UNO_NAME_CHAR_OVERLINE_COLOR), RES_CHRATR_OVERLINE , CPPU_E2T(CPPUTYPE_INT32), PROPERTY_NONE, MID_TL_COLOR},
+ { SW_PROP_NMID(UNO_NAME_CHAR_OVERLINE_HAS_COLOR), RES_CHRATR_OVERLINE , CPPU_E2T(CPPUTYPE_BOOLEAN), PROPERTY_NONE, MID_TL_HASCOLOR},
+ { SW_PROP_NMID(UNO_NAME_CHAR_KERNING), RES_CHRATR_KERNING , CPPU_E2T(CPPUTYPE_INT16) , PROPERTY_NONE, CONVERT_TWIPS},
+ { SW_PROP_NMID(UNO_NAME_CHAR_NO_HYPHENATION), RES_CHRATR_NOHYPHEN , CPPU_E2T(CPPUTYPE_BOOLEAN) , PROPERTY_NONE, 0},
+ { SW_PROP_NMID(UNO_NAME_CHAR_SHADOWED), RES_CHRATR_SHADOWED , CPPU_E2T(CPPUTYPE_BOOLEAN) , PROPERTY_NONE, 0},
+ { SW_PROP_NMID(UNO_NAME_CHAR_CONTOURED), RES_CHRATR_CONTOUR, CPPU_E2T(CPPUTYPE_BOOLEAN) , PROPERTY_NONE, 0},
+ { SW_PROP_NMID(UNO_NAME_CHAR_WORD_MODE), RES_CHRATR_WORDLINEMODE,CPPU_E2T(CPPUTYPE_BOOLEAN) , PROPERTY_NONE, 0},
+ { SW_PROP_NMID(UNO_NAME_USER_DEFINED_ATTRIBUTES), RES_UNKNOWNATR_CONTAINER, CPPU_E2T(CPPUTYPE_REFNAMECNT), PropertyAttribute::MAYBEVOID, 0 },
+ { SW_PROP_NMID(UNO_NAME_TEXT_USER_DEFINED_ATTRIBUTES), RES_TXTATR_UNKNOWN_CONTAINER, CPPU_E2T(CPPUTYPE_REFNAMECNT), PropertyAttribute::MAYBEVOID, 0 },
+ { SW_PROP_NMID(UNO_NAME_IS_PHYSICAL), FN_UNO_IS_PHYSICAL, CPPU_E2T(CPPUTYPE_BOOLEAN), PropertyAttribute::READONLY, 0},
+ { SW_PROP_NMID(UNO_NAME_DISPLAY_NAME), FN_UNO_DISPLAY_NAME, CPPU_E2T(CPPUTYPE_OUSTRING), PropertyAttribute::READONLY, 0},
+ { SW_PROP_NMID(UNO_NAME_CHAR_COMBINE_IS_ON), RES_CHRATR_TWO_LINES, CPPU_E2T(CPPUTYPE_BOOLEAN), PROPERTY_NONE, MID_TWOLINES},
+ { SW_PROP_NMID(UNO_NAME_CHAR_COMBINE_PREFIX), RES_CHRATR_TWO_LINES, CPPU_E2T(CPPUTYPE_OUSTRING), PROPERTY_NONE, MID_START_BRACKET},
+ { SW_PROP_NMID(UNO_NAME_CHAR_COMBINE_SUFFIX), RES_CHRATR_TWO_LINES, CPPU_E2T(CPPUTYPE_OUSTRING), PROPERTY_NONE, MID_END_BRACKET},
+ { SW_PROP_NMID(UNO_NAME_CHAR_EMPHASIS), RES_CHRATR_EMPHASIS_MARK, CPPU_E2T(CPPUTYPE_INT16), PROPERTY_NONE, MID_EMPHASIS},
+ { SW_PROP_NMID(UNO_NAME_CHAR_ROTATION), RES_CHRATR_ROTATE, CPPU_E2T(CPPUTYPE_INT16), PROPERTY_NONE, MID_ROTATE },
+ { SW_PROP_NMID(UNO_NAME_CHAR_ROTATION_IS_FIT_TO_LINE), RES_CHRATR_ROTATE, CPPU_E2T(CPPUTYPE_BOOLEAN), PROPERTY_NONE, MID_FITTOLINE },
+ { SW_PROP_NMID(UNO_NAME_CHAR_SCALE_WIDTH), RES_CHRATR_SCALEW, CPPU_E2T(CPPUTYPE_INT16), PROPERTY_NONE, 0 },
+ { SW_PROP_NMID(UNO_NAME_CHAR_RELIEF), RES_CHRATR_RELIEF, CPPU_E2T(CPPUTYPE_INT16), PROPERTY_NONE, MID_RELIEF },
+ { SW_PROP_NMID(UNO_NAME_CHAR_AUTO_STYLE_NAME), RES_TXTATR_AUTOFMT, CPPU_E2T(CPPUTYPE_OUSTRING), PropertyAttribute::MAYBEVOID, 0},
+ {0,0,0,0,0,0}
+ };
+ aMapEntriesArr[nPropertyId] = aAutoCharStyleMap;
+ }
+ break;
+ case PROPERTY_MAP_RUBY_AUTO_STYLE :
+ {
+ static SfxItemPropertyMapEntry aAutoRubyStyleMap [] =
+ {
+ { SW_PROP_NMID(UNO_NAME_RUBY_ADJUST), RES_TXTATR_CJK_RUBY, CPPU_E2T(CPPUTYPE_INT16), PropertyAttribute::MAYBEVOID, MID_RUBY_ADJUST },
+ { SW_PROP_NMID(UNO_NAME_RUBY_IS_ABOVE), RES_TXTATR_CJK_RUBY, CPPU_E2T(CPPUTYPE_BOOLEAN), PropertyAttribute::MAYBEVOID, MID_RUBY_ABOVE },
+ {0,0,0,0,0,0}
+ };
+ aMapEntriesArr[nPropertyId] = aAutoRubyStyleMap;
+ }
+ break;
+ case PROPERTY_MAP_PARA_STYLE :
+ {
+ static SfxItemPropertyMapEntry aParaStyleMap [] =
+ {
+ COMMON_PARA_STYLE_PROPERTIES
+ {0,0,0,0,0,0}
+ };
+ aMapEntriesArr[nPropertyId] = aParaStyleMap;
+ }
+ break;
+ case PROPERTY_MAP_CONDITIONAL_PARA_STYLE :
+ {
+ static SfxItemPropertyMapEntry aParaStyleMap [] =
+ {
+ COMMON_PARA_STYLE_PROPERTIES
+ { SW_PROP_NMID(UNO_NAME_PARA_STYLE_CONDITIONS), FN_UNO_PARA_STYLE_CONDITIONS, CPPU_E2T(CPPUTYPE_SEQNAMEDVALUE), PropertyAttribute::MAYBEVOID, 0},
+ {0,0,0,0,0,0}
+ };
+ aMapEntriesArr[nPropertyId] = aParaStyleMap;
+ }
+ break;
+ case PROPERTY_MAP_FRAME_STYLE:
+ {
+ static SfxItemPropertyMapEntry aFrameStyleMap [] =
+ {
+ { SW_PROP_NMID(UNO_NAME_ANCHOR_PAGE_NO), RES_ANCHOR, CPPU_E2T(CPPUTYPE_INT16), PROPERTY_NONE, MID_ANCHOR_PAGENUM },
+ { SW_PROP_NMID(UNO_NAME_ANCHOR_TYPE), RES_ANCHOR, CPPU_E2T(CPPUTYPE_TXTCNTANCHOR), PROPERTY_NONE, MID_ANCHOR_ANCHORTYPE},
+ { SW_PROP_NMID(UNO_NAME_BACK_COLOR), RES_BACKGROUND, CPPU_E2T(CPPUTYPE_INT32), PROPERTY_NONE ,MID_BACK_COLOR },
+ { SW_PROP_NMID(UNO_NAME_BACK_COLOR_R_G_B), RES_BACKGROUND, CPPU_E2T(CPPUTYPE_INT32), PROPERTY_NONE ,MID_BACK_COLOR_R_G_B},
+ { SW_PROP_NMID(UNO_NAME_BACK_COLOR_TRANSPARENCY), RES_BACKGROUND, CPPU_E2T(CPPUTYPE_INT8), PROPERTY_NONE ,MID_BACK_COLOR_TRANSPARENCY}, \
+ // { SW_PROP_NMID(UNO_NAME_CHAIN_NEXT_NAME), RES_CHAIN, CPPU_E2T(CPPUTYPE_OUSTRING), PROPERTY_NONE ,MID_CHAIN_NEXTNAME},
+ // { SW_PROP_NMID(UNO_NAME_CHAIN_PREV_NAME), RES_CHAIN, CPPU_E2T(CPPUTYPE_OUSTRING), PROPERTY_NONE ,MID_CHAIN_PREVNAME},
+ /*not impl*/ { SW_PROP_NMID(UNO_NAME_CLIENT_MAP), RES_URL, CPPU_E2T(CPPUTYPE_BOOLEAN), PROPERTY_NONE ,MID_URL_CLIENTMAP },
+ { SW_PROP_NMID(UNO_NAME_CONTENT_PROTECTED), RES_PROTECT, CPPU_E2T(CPPUTYPE_BOOLEAN), PROPERTY_NONE, MID_PROTECT_CONTENT },
+ { SW_PROP_NMID(UNO_NAME_EDIT_IN_READONLY), RES_EDIT_IN_READONLY, CPPU_E2T(CPPUTYPE_BOOLEAN), PROPERTY_NONE, 0},
+ // { SW_PROP_NMID(UNO_NAME_GRAPHIC), RES_BACKGROUND, &, PROPERTY_NONE, MID_GRAPHIC
+ { SW_PROP_NMID(UNO_NAME_BACK_GRAPHIC_URL), RES_BACKGROUND, CPPU_E2T(CPPUTYPE_OUSTRING), PROPERTY_NONE ,MID_GRAPHIC_URL },
+ { SW_PROP_NMID(UNO_NAME_BACK_GRAPHIC_FILTER), RES_BACKGROUND, CPPU_E2T(CPPUTYPE_OUSTRING), PROPERTY_NONE ,MID_GRAPHIC_FILTER },
+ { SW_PROP_NMID(UNO_NAME_BACK_GRAPHIC_LOCATION), RES_BACKGROUND, CPPU_E2T(CPPUTYPE_GRAPHICLOC), PROPERTY_NONE ,MID_GRAPHIC_POSITION},
+ // #i50322# - add missing map entry for transparency of graphic background
+ { SW_PROP_NMID(UNO_NAME_BACK_GRAPHIC_TRANSPARENCY), RES_BACKGROUND, CPPU_E2T(CPPUTYPE_INT8), PROPERTY_NONE ,MID_GRAPHIC_TRANSPARENCY},
+ { SW_PROP_NMID(UNO_NAME_LEFT_MARGIN), RES_LR_SPACE, CPPU_E2T(CPPUTYPE_INT32), PROPERTY_NONE, MID_L_MARGIN|CONVERT_TWIPS},
+ { SW_PROP_NMID(UNO_NAME_RIGHT_MARGIN), RES_LR_SPACE, CPPU_E2T(CPPUTYPE_INT32), PROPERTY_NONE, MID_R_MARGIN|CONVERT_TWIPS},
+ { SW_PROP_NMID(UNO_NAME_HORI_ORIENT), RES_HORI_ORIENT, CPPU_E2T(CPPUTYPE_INT16), PROPERTY_NONE ,MID_HORIORIENT_ORIENT },
+ { SW_PROP_NMID(UNO_NAME_HORI_ORIENT_POSITION), RES_HORI_ORIENT, CPPU_E2T(CPPUTYPE_INT32), PROPERTY_NONE ,MID_HORIORIENT_POSITION|CONVERT_TWIPS },
+ { SW_PROP_NMID(UNO_NAME_HORI_ORIENT_RELATION), RES_HORI_ORIENT, CPPU_E2T(CPPUTYPE_INT16), PROPERTY_NONE ,MID_HORIORIENT_RELATION },
+ { SW_PROP_NMID(UNO_NAME_HYPER_LINK_U_R_L), RES_URL, CPPU_E2T(CPPUTYPE_OUSTRING), PROPERTY_NONE ,MID_URL_URL},
+ { SW_PROP_NMID(UNO_NAME_HYPER_LINK_TARGET), RES_URL, CPPU_E2T(CPPUTYPE_OUSTRING), PROPERTY_NONE ,MID_URL_TARGET},
+ { SW_PROP_NMID(UNO_NAME_HYPER_LINK_NAME), RES_URL, CPPU_E2T(CPPUTYPE_OUSTRING), PROPERTY_NONE ,MID_URL_HYPERLINKNAME },
+ { SW_PROP_NMID(UNO_NAME_OPAQUE), RES_OPAQUE, CPPU_E2T(CPPUTYPE_BOOLEAN), PROPERTY_NONE, 0},
+ { SW_PROP_NMID(UNO_NAME_PAGE_TOGGLE), RES_HORI_ORIENT, CPPU_E2T(CPPUTYPE_BOOLEAN), PROPERTY_NONE ,MID_HORIORIENT_PAGETOGGLE },
+ { SW_PROP_NMID(UNO_NAME_POSITION_PROTECTED), RES_PROTECT, CPPU_E2T(CPPUTYPE_BOOLEAN), PROPERTY_NONE, MID_PROTECT_POSITION},
+ { SW_PROP_NMID(UNO_NAME_PRINT), RES_PRINT, CPPU_E2T(CPPUTYPE_BOOLEAN), PROPERTY_NONE, 0},
+ { SW_PROP_NMID(UNO_NAME_WIDTH), RES_FRM_SIZE, CPPU_E2T(CPPUTYPE_INT32) , PROPERTY_NONE, MID_FRMSIZE_WIDTH|CONVERT_TWIPS },
+ { SW_PROP_NMID(UNO_NAME_HEIGHT), RES_FRM_SIZE, CPPU_E2T(CPPUTYPE_INT32) , PROPERTY_NONE, MID_FRMSIZE_HEIGHT|CONVERT_TWIPS },
+ { SW_PROP_NMID(UNO_NAME_RELATIVE_HEIGHT), RES_FRM_SIZE, CPPU_E2T(CPPUTYPE_INT16) , PROPERTY_NONE, MID_FRMSIZE_REL_HEIGHT },
+ { SW_PROP_NMID(UNO_NAME_RELATIVE_WIDTH), RES_FRM_SIZE, CPPU_E2T(CPPUTYPE_INT16) , PROPERTY_NONE, MID_FRMSIZE_REL_WIDTH },
+ { SW_PROP_NMID(UNO_NAME_SIZE_TYPE), RES_FRM_SIZE, CPPU_E2T(CPPUTYPE_INT16) , PROPERTY_NONE, MID_FRMSIZE_SIZE_TYPE },
+ { SW_PROP_NMID(UNO_NAME_WIDTH_TYPE), RES_FRM_SIZE, CPPU_E2T(CPPUTYPE_INT16) , PROPERTY_NONE, MID_FRMSIZE_WIDTH_TYPE },
+ { SW_PROP_NMID(UNO_NAME_SIZE), RES_FRM_SIZE, CPPU_E2T(CPPUTYPE_AWTSIZE), PROPERTY_NONE, MID_FRMSIZE_SIZE|CONVERT_TWIPS},
+ { SW_PROP_NMID(UNO_NAME_IS_SYNC_WIDTH_TO_HEIGHT), RES_FRM_SIZE, CPPU_E2T(CPPUTYPE_BOOLEAN) , PROPERTY_NONE, MID_FRMSIZE_IS_SYNC_WIDTH_TO_HEIGHT },
+ { SW_PROP_NMID(UNO_NAME_IS_SYNC_HEIGHT_TO_WIDTH), RES_FRM_SIZE, CPPU_E2T(CPPUTYPE_BOOLEAN) , PROPERTY_NONE, MID_FRMSIZE_IS_SYNC_HEIGHT_TO_WIDTH },
+ // { SW_PROP_NMID(UNO_NAME_WIDTH), RES_FRM_SIZE, CPPU_E2T(CPPUTYPE_INT32) , PROPERTY_NONE, MID_FRMSIZE_WIDTH },
+ { SW_PROP_NMID(UNO_NAME_SHADOW_FORMAT), RES_SHADOW, CPPU_E2T(CPPUTYPE_SHADOWFMT), PROPERTY_NONE, CONVERT_TWIPS},
+ { SW_PROP_NMID(UNO_NAME_SERVER_MAP), RES_URL, CPPU_E2T(CPPUTYPE_BOOLEAN), PROPERTY_NONE ,MID_URL_SERVERMAP },
+ { SW_PROP_NMID(UNO_NAME_SIZE_PROTECTED), RES_PROTECT, CPPU_E2T(CPPUTYPE_BOOLEAN), PROPERTY_NONE, MID_PROTECT_SIZE },
+ //Surround bleibt, weil es mit der 5.1 ausgeliefert wurde, obwohl es mit text::WrapTextMode identisch ist
+ { SW_PROP_NMID(UNO_NAME_SURROUND), RES_SURROUND, CPPU_E2T(CPPUTYPE_WRAPTXTMODE), PROPERTY_NONE, MID_SURROUND_SURROUNDTYPE },
+ { SW_PROP_NMID(UNO_NAME_TEXT_WRAP), RES_SURROUND, CPPU_E2T(CPPUTYPE_WRAPTXTMODE), PROPERTY_NONE, MID_SURROUND_SURROUNDTYPE },
+ { SW_PROP_NMID(UNO_NAME_SURROUND_ANCHORONLY), RES_SURROUND, CPPU_E2T(CPPUTYPE_BOOLEAN), PROPERTY_NONE, MID_SURROUND_ANCHORONLY },
+ { SW_PROP_NMID(UNO_NAME_SURROUND_CONTOUR), RES_SURROUND, CPPU_E2T(CPPUTYPE_BOOLEAN), PROPERTY_NONE, MID_SURROUND_CONTOUR },
+ { SW_PROP_NMID(UNO_NAME_CONTOUR_OUTSIDE), RES_SURROUND, CPPU_E2T(CPPUTYPE_BOOLEAN), PROPERTY_NONE, MID_SURROUND_CONTOUROUTSIDE },
+ { SW_PROP_NMID(UNO_NAME_TEXT_COLUMNS), RES_COL, CPPU_E2T(CPPUTYPE_REFTEXTCOL), PROPERTY_NONE, MID_COLUMNS},
+ { SW_PROP_NMID(UNO_NAME_TOP_MARGIN), RES_UL_SPACE, CPPU_E2T(CPPUTYPE_INT32), PROPERTY_NONE, MID_UP_MARGIN|CONVERT_TWIPS},
+ { SW_PROP_NMID(UNO_NAME_BOTTOM_MARGIN), RES_UL_SPACE, CPPU_E2T(CPPUTYPE_INT32), PROPERTY_NONE, MID_LO_MARGIN|CONVERT_TWIPS},
+ { SW_PROP_NMID(UNO_NAME_BACK_TRANSPARENT), RES_BACKGROUND, CPPU_E2T(CPPUTYPE_BOOLEAN), PROPERTY_NONE ,MID_GRAPHIC_TRANSPARENT },
+ { SW_PROP_NMID(UNO_NAME_VERT_ORIENT), RES_VERT_ORIENT, CPPU_E2T(CPPUTYPE_INT16), PROPERTY_NONE ,MID_VERTORIENT_ORIENT },
+ { SW_PROP_NMID(UNO_NAME_VERT_ORIENT_POSITION), RES_VERT_ORIENT, CPPU_E2T(CPPUTYPE_INT32), PROPERTY_NONE ,MID_VERTORIENT_POSITION|CONVERT_TWIPS },
+ { SW_PROP_NMID(UNO_NAME_VERT_ORIENT_RELATION), RES_VERT_ORIENT, CPPU_E2T(CPPUTYPE_INT16), PROPERTY_NONE ,MID_VERTORIENT_RELATION },
+ { SW_PROP_NMID(UNO_NAME_LEFT_BORDER), RES_BOX, CPPU_E2T(CPPUTYPE_BORDERLINE), 0, LEFT_BORDER |CONVERT_TWIPS },
+ { SW_PROP_NMID(UNO_NAME_RIGHT_BORDER), RES_BOX, CPPU_E2T(CPPUTYPE_BORDERLINE), 0, RIGHT_BORDER |CONVERT_TWIPS },
+ { SW_PROP_NMID(UNO_NAME_TOP_BORDER), RES_BOX, CPPU_E2T(CPPUTYPE_BORDERLINE), 0, TOP_BORDER |CONVERT_TWIPS },
+ { SW_PROP_NMID(UNO_NAME_BOTTOM_BORDER), RES_BOX, CPPU_E2T(CPPUTYPE_BORDERLINE), 0, BOTTOM_BORDER|CONVERT_TWIPS },
+ { SW_PROP_NMID(UNO_NAME_BORDER_DISTANCE), RES_BOX, CPPU_E2T(CPPUTYPE_INT32), 0, BORDER_DISTANCE|CONVERT_TWIPS },
+ { SW_PROP_NMID(UNO_NAME_LEFT_BORDER_DISTANCE), RES_BOX, CPPU_E2T(CPPUTYPE_INT32), 0, LEFT_BORDER_DISTANCE |CONVERT_TWIPS },
+ { SW_PROP_NMID(UNO_NAME_RIGHT_BORDER_DISTANCE), RES_BOX, CPPU_E2T(CPPUTYPE_INT32), 0, RIGHT_BORDER_DISTANCE |CONVERT_TWIPS },
+ { SW_PROP_NMID(UNO_NAME_TOP_BORDER_DISTANCE), RES_BOX, CPPU_E2T(CPPUTYPE_INT32), 0, TOP_BORDER_DISTANCE |CONVERT_TWIPS },
+ { SW_PROP_NMID(UNO_NAME_BOTTOM_BORDER_DISTANCE), RES_BOX, CPPU_E2T(CPPUTYPE_INT32), 0, BOTTOM_BORDER_DISTANCE|CONVERT_TWIPS },
+ { SW_PROP_NMID(UNO_NAME_USER_DEFINED_ATTRIBUTES), RES_UNKNOWNATR_CONTAINER, CPPU_E2T(CPPUTYPE_REFNAMECNT), PropertyAttribute::MAYBEVOID, 0 },
+ { SW_PROP_NMID(UNO_NAME_IS_PHYSICAL), FN_UNO_IS_PHYSICAL, CPPU_E2T(CPPUTYPE_BOOLEAN), PropertyAttribute::READONLY, 0},
+ { SW_PROP_NMID(UNO_NAME_IS_AUTO_UPDATE), FN_UNO_IS_AUTO_UPDATE, CPPU_E2T(CPPUTYPE_BOOLEAN), PROPERTY_NONE, 0},
+ { SW_PROP_NMID(UNO_NAME_DISPLAY_NAME), FN_UNO_DISPLAY_NAME, CPPU_E2T(CPPUTYPE_OUSTRING), PropertyAttribute::READONLY, 0},
+ // #i18732#
+ { SW_PROP_NMID(UNO_NAME_IS_FOLLOWING_TEXT_FLOW), RES_FOLLOW_TEXT_FLOW, CPPU_E2T(CPPUTYPE_BOOLEAN), PROPERTY_NONE, 0},
+ // #i28701#
+ { SW_PROP_NMID(UNO_NAME_WRAP_INFLUENCE_ON_POSITION), RES_WRAP_INFLUENCE_ON_OBJPOS, CPPU_E2T(CPPUTYPE_INT8), PROPERTY_NONE, MID_WRAP_INFLUENCE},
+ { SW_PROP_NMID(UNO_NAME_WRITING_MODE), RES_FRAMEDIR, CPPU_E2T(CPPUTYPE_INT16), PROPERTY_NONE, 0 },
+ {0,0,0,0,0,0}
+ };
+ aMapEntriesArr[nPropertyId] = aFrameStyleMap;
+ }
+ break;
+ case PROPERTY_MAP_PAGE_STYLE :
+ {
+ static SfxItemPropertyMapEntry aPageStyleMap [] =
+ {
+ { SW_PROP_NMID(UNO_NAME_BACK_COLOR), RES_BACKGROUND, CPPU_E2T(CPPUTYPE_INT32), PROPERTY_NONE ,MID_BACK_COLOR },
+ // { SW_PROP_NMID(UNO_NAME_GRAPHIC), RES_BACKGROUND, &, PROPERTY_NONE, MID_GRAPHIC
+ { SW_PROP_NMID(UNO_NAME_BACK_GRAPHIC_URL), RES_BACKGROUND, CPPU_E2T(CPPUTYPE_OUSTRING), PROPERTY_NONE ,MID_GRAPHIC_URL },
+ { SW_PROP_NMID(UNO_NAME_BACK_GRAPHIC_FILTER), RES_BACKGROUND, CPPU_E2T(CPPUTYPE_OUSTRING), PROPERTY_NONE ,MID_GRAPHIC_FILTER },
+ { SW_PROP_NMID(UNO_NAME_BACK_GRAPHIC_LOCATION), RES_BACKGROUND, CPPU_E2T(CPPUTYPE_GRAPHICLOC), PROPERTY_NONE ,MID_GRAPHIC_POSITION},
+ { SW_PROP_NMID(UNO_NAME_LEFT_MARGIN), RES_LR_SPACE, CPPU_E2T(CPPUTYPE_INT32), PROPERTY_NONE, MID_L_MARGIN|CONVERT_TWIPS},
+ { SW_PROP_NMID(UNO_NAME_RIGHT_MARGIN), RES_LR_SPACE, CPPU_E2T(CPPUTYPE_INT32), PROPERTY_NONE, MID_R_MARGIN|CONVERT_TWIPS},
+ { SW_PROP_NMID(UNO_NAME_BACK_TRANSPARENT), RES_BACKGROUND, CPPU_E2T(CPPUTYPE_BOOLEAN), PROPERTY_NONE ,MID_GRAPHIC_TRANSPARENT },
+ { SW_PROP_NMID(UNO_NAME_LEFT_BORDER), RES_BOX, CPPU_E2T(CPPUTYPE_BORDERLINE), 0, LEFT_BORDER |CONVERT_TWIPS },
+ { SW_PROP_NMID(UNO_NAME_RIGHT_BORDER), RES_BOX, CPPU_E2T(CPPUTYPE_BORDERLINE), 0, RIGHT_BORDER |CONVERT_TWIPS },
+ { SW_PROP_NMID(UNO_NAME_TOP_BORDER), RES_BOX, CPPU_E2T(CPPUTYPE_BORDERLINE), 0, TOP_BORDER |CONVERT_TWIPS },
+ { SW_PROP_NMID(UNO_NAME_BOTTOM_BORDER), RES_BOX, CPPU_E2T(CPPUTYPE_BORDERLINE), 0, BOTTOM_BORDER|CONVERT_TWIPS },
+ { SW_PROP_NMID(UNO_NAME_BORDER_DISTANCE), RES_BOX, CPPU_E2T(CPPUTYPE_INT32), 0, BORDER_DISTANCE|CONVERT_TWIPS },
+ { SW_PROP_NMID(UNO_NAME_LEFT_BORDER_DISTANCE), RES_BOX, CPPU_E2T(CPPUTYPE_INT32), 0, LEFT_BORDER_DISTANCE |CONVERT_TWIPS },
+ { SW_PROP_NMID(UNO_NAME_RIGHT_BORDER_DISTANCE), RES_BOX, CPPU_E2T(CPPUTYPE_INT32), 0, RIGHT_BORDER_DISTANCE |CONVERT_TWIPS },
+ { SW_PROP_NMID(UNO_NAME_TOP_BORDER_DISTANCE), RES_BOX, CPPU_E2T(CPPUTYPE_INT32), 0, TOP_BORDER_DISTANCE |CONVERT_TWIPS },
+ { SW_PROP_NMID(UNO_NAME_BOTTOM_BORDER_DISTANCE), RES_BOX, CPPU_E2T(CPPUTYPE_INT32), 0, BOTTOM_BORDER_DISTANCE|CONVERT_TWIPS },
+ { SW_PROP_NMID(UNO_NAME_SHADOW_FORMAT), RES_SHADOW, CPPU_E2T(CPPUTYPE_SHADOWFMT), PROPERTY_NONE, CONVERT_TWIPS},
+
+ { SW_PROP_NMID(UNO_NAME_HEADER_BACK_COLOR), FN_UNO_HEADER_BACKGROUND, CPPU_E2T(CPPUTYPE_INT32), PROPERTY_NONE ,MID_BACK_COLOR },
+ // { SW_PROP_NMID(UNO_NAME_HEADER_GRAPHIC), FN_UNO_HEADER_BACKGROUND, &, PROPERTY_NONE, MID_GRAPHIC
+ { SW_PROP_NMID(UNO_NAME_HEADER_GRAPHIC_URL), FN_UNO_HEADER_BACKGROUND, CPPU_E2T(CPPUTYPE_OUSTRING), PROPERTY_NONE ,MID_GRAPHIC_URL },
+ { SW_PROP_NMID(UNO_NAME_HEADER_GRAPHIC_FILTER), FN_UNO_HEADER_BACKGROUND, CPPU_E2T(CPPUTYPE_OUSTRING), PROPERTY_NONE ,MID_GRAPHIC_FILTER },
+ { SW_PROP_NMID(UNO_NAME_HEADER_GRAPHIC_LOCATION), FN_UNO_HEADER_BACKGROUND, CPPU_E2T(CPPUTYPE_GRAPHICLOC), PROPERTY_NONE ,MID_GRAPHIC_POSITION},
+ { SW_PROP_NMID(UNO_NAME_HEADER_LEFT_MARGIN), FN_UNO_HEADER_LR_SPACE, CPPU_E2T(CPPUTYPE_INT32), PROPERTY_NONE, MID_L_MARGIN|CONVERT_TWIPS},
+ { SW_PROP_NMID(UNO_NAME_HEADER_RIGHT_MARGIN), FN_UNO_HEADER_LR_SPACE, CPPU_E2T(CPPUTYPE_INT32), PROPERTY_NONE, MID_R_MARGIN|CONVERT_TWIPS},
+ { SW_PROP_NMID(UNO_NAME_HEADER_BACK_TRANSPARENT), FN_UNO_HEADER_BACKGROUND, CPPU_E2T(CPPUTYPE_BOOLEAN), PROPERTY_NONE ,MID_GRAPHIC_TRANSPARENT },
+ { SW_PROP_NMID(UNO_NAME_HEADER_LEFT_BORDER), FN_UNO_HEADER_BOX, CPPU_E2T(CPPUTYPE_BORDERLINE), 0, LEFT_BORDER |CONVERT_TWIPS },
+ { SW_PROP_NMID(UNO_NAME_HEADER_RIGHT_BORDER), FN_UNO_HEADER_BOX, CPPU_E2T(CPPUTYPE_BORDERLINE), 0, RIGHT_BORDER |CONVERT_TWIPS },
+ { SW_PROP_NMID(UNO_NAME_HEADER_TOP_BORDER), FN_UNO_HEADER_BOX, CPPU_E2T(CPPUTYPE_BORDERLINE), 0, TOP_BORDER |CONVERT_TWIPS },
+ { SW_PROP_NMID(UNO_NAME_HEADER_BOTTOM_BORDER), FN_UNO_HEADER_BOX, CPPU_E2T(CPPUTYPE_BORDERLINE), 0, BOTTOM_BORDER|CONVERT_TWIPS },
+ { SW_PROP_NMID(UNO_NAME_HEADER_BORDER_DISTANCE), FN_UNO_HEADER_BOX, CPPU_E2T(CPPUTYPE_INT32), PropertyAttribute::MAYBEVOID, BORDER_DISTANCE|CONVERT_TWIPS },
+ { SW_PROP_NMID(UNO_NAME_HEADER_LEFT_BORDER_DISTANCE), FN_UNO_HEADER_BOX, CPPU_E2T(CPPUTYPE_INT32), 0, LEFT_BORDER_DISTANCE |CONVERT_TWIPS },
+ { SW_PROP_NMID(UNO_NAME_HEADER_RIGHT_BORDER_DISTANCE), FN_UNO_HEADER_BOX, CPPU_E2T(CPPUTYPE_INT32), 0, RIGHT_BORDER_DISTANCE |CONVERT_TWIPS },
+ { SW_PROP_NMID(UNO_NAME_HEADER_TOP_BORDER_DISTANCE), FN_UNO_HEADER_BOX, CPPU_E2T(CPPUTYPE_INT32), 0, TOP_BORDER_DISTANCE |CONVERT_TWIPS },
+ { SW_PROP_NMID(UNO_NAME_HEADER_BOTTOM_BORDER_DISTANCE), FN_UNO_HEADER_BOX, CPPU_E2T(CPPUTYPE_INT32), 0, BOTTOM_BORDER_DISTANCE|CONVERT_TWIPS },
+ { SW_PROP_NMID(UNO_NAME_HEADER_SHADOW_FORMAT), FN_UNO_HEADER_SHADOW, CPPU_E2T(CPPUTYPE_SHADOWFMT), PROPERTY_NONE, CONVERT_TWIPS},
+ { SW_PROP_NMID(UNO_NAME_HEADER_BODY_DISTANCE), FN_UNO_HEADER_BODY_DISTANCE,CPPU_E2T(CPPUTYPE_INT32), PROPERTY_NONE ,MID_LO_MARGIN|CONVERT_TWIPS },
+ { SW_PROP_NMID(UNO_NAME_HEADER_IS_DYNAMIC_HEIGHT), FN_UNO_HEADER_IS_DYNAMIC_DISTANCE,CPPU_E2T(CPPUTYPE_BOOLEAN), PROPERTY_NONE ,0 },
+ { SW_PROP_NMID(UNO_NAME_HEADER_IS_SHARED), FN_UNO_HEADER_SHARE_CONTENT,CPPU_E2T(CPPUTYPE_BOOLEAN), PROPERTY_NONE ,0 },
+ { SW_PROP_NMID(UNO_NAME_HEADER_HEIGHT), FN_UNO_HEADER_HEIGHT, CPPU_E2T(CPPUTYPE_INT32), PROPERTY_NONE ,MID_SIZE_HEIGHT|CONVERT_TWIPS },
+ { SW_PROP_NMID(UNO_NAME_HEADER_IS_ON), FN_UNO_HEADER_ON, CPPU_E2T(CPPUTYPE_BOOLEAN), PROPERTY_NONE ,0 },
+ { SW_PROP_NMID(UNO_NAME_HEADER_DYNAMIC_SPACING), FN_UNO_HEADER_EAT_SPACING, CPPU_E2T(CPPUTYPE_BOOLEAN), PropertyAttribute::MAYBEVOID ,0 },
+
+ { SW_PROP_NMID(UNO_NAME_FOOTER_BACK_COLOR), FN_UNO_FOOTER_BACKGROUND, CPPU_E2T(CPPUTYPE_INT32), PROPERTY_NONE ,MID_BACK_COLOR },
+ // { SW_PROP_NMID(UNO_NAME_FOOTER_GRAPHIC), FN_UNO_FOOTER_BACKGROUND, &, PROPERTY_NONE, MID_GRAPHIC
+ { SW_PROP_NMID(UNO_NAME_FOOTER_GRAPHIC_URL), FN_UNO_FOOTER_BACKGROUND, CPPU_E2T(CPPUTYPE_OUSTRING), PROPERTY_NONE ,MID_GRAPHIC_URL },
+ { SW_PROP_NMID(UNO_NAME_FOOTER_GRAPHIC_FILTER), FN_UNO_FOOTER_BACKGROUND, CPPU_E2T(CPPUTYPE_OUSTRING), PROPERTY_NONE ,MID_GRAPHIC_FILTER },
+ { SW_PROP_NMID(UNO_NAME_FOOTER_GRAPHIC_LOCATION), FN_UNO_FOOTER_BACKGROUND, CPPU_E2T(CPPUTYPE_GRAPHICLOC), PROPERTY_NONE ,MID_GRAPHIC_POSITION},
+ { SW_PROP_NMID(UNO_NAME_FOOTER_LEFT_MARGIN), FN_UNO_FOOTER_LR_SPACE, CPPU_E2T(CPPUTYPE_INT32), PROPERTY_NONE, MID_L_MARGIN|CONVERT_TWIPS},
+ { SW_PROP_NMID(UNO_NAME_FOOTER_RIGHT_MARGIN), FN_UNO_FOOTER_LR_SPACE, CPPU_E2T(CPPUTYPE_INT32), PROPERTY_NONE, MID_R_MARGIN|CONVERT_TWIPS},
+ { SW_PROP_NMID(UNO_NAME_FOOTER_BACK_TRANSPARENT), FN_UNO_FOOTER_BACKGROUND, CPPU_E2T(CPPUTYPE_BOOLEAN), PROPERTY_NONE ,MID_GRAPHIC_TRANSPARENT },
+ { SW_PROP_NMID(UNO_NAME_FOOTER_LEFT_BORDER), FN_UNO_FOOTER_BOX, CPPU_E2T(CPPUTYPE_BORDERLINE), 0, LEFT_BORDER |CONVERT_TWIPS },
+ { SW_PROP_NMID(UNO_NAME_FOOTER_RIGHT_BORDER), FN_UNO_FOOTER_BOX, CPPU_E2T(CPPUTYPE_BORDERLINE), 0, RIGHT_BORDER |CONVERT_TWIPS },
+ { SW_PROP_NMID(UNO_NAME_FOOTER_TOP_BORDER), FN_UNO_FOOTER_BOX, CPPU_E2T(CPPUTYPE_BORDERLINE), 0, TOP_BORDER |CONVERT_TWIPS },
+ { SW_PROP_NMID(UNO_NAME_FOOTER_BOTTOM_BORDER), FN_UNO_FOOTER_BOX, CPPU_E2T(CPPUTYPE_BORDERLINE), 0, BOTTOM_BORDER|CONVERT_TWIPS },
+ { SW_PROP_NMID(UNO_NAME_FOOTER_BORDER_DISTANCE), FN_UNO_FOOTER_BOX, CPPU_E2T(CPPUTYPE_INT32), PropertyAttribute::MAYBEVOID, BORDER_DISTANCE|CONVERT_TWIPS },
+ { SW_PROP_NMID(UNO_NAME_FOOTER_LEFT_BORDER_DISTANCE), FN_UNO_FOOTER_BOX, CPPU_E2T(CPPUTYPE_INT32), 0, LEFT_BORDER_DISTANCE |CONVERT_TWIPS },
+ { SW_PROP_NMID(UNO_NAME_FOOTER_RIGHT_BORDER_DISTANCE), FN_UNO_FOOTER_BOX, CPPU_E2T(CPPUTYPE_INT32), 0, RIGHT_BORDER_DISTANCE |CONVERT_TWIPS },
+ { SW_PROP_NMID(UNO_NAME_FOOTER_TOP_BORDER_DISTANCE), FN_UNO_FOOTER_BOX, CPPU_E2T(CPPUTYPE_INT32), 0, TOP_BORDER_DISTANCE |CONVERT_TWIPS },
+ { SW_PROP_NMID(UNO_NAME_FOOTER_BOTTOM_BORDER_DISTANCE), FN_UNO_FOOTER_BOX, CPPU_E2T(CPPUTYPE_INT32), 0, BOTTOM_BORDER_DISTANCE|CONVERT_TWIPS },
+ { SW_PROP_NMID(UNO_NAME_FOOTER_SHADOW_FORMAT), FN_UNO_FOOTER_SHADOW, CPPU_E2T(CPPUTYPE_SHADOWFMT), PROPERTY_NONE, CONVERT_TWIPS},
+ { SW_PROP_NMID(UNO_NAME_FOOTER_BODY_DISTANCE), FN_UNO_FOOTER_BODY_DISTANCE,CPPU_E2T(CPPUTYPE_INT32), PROPERTY_NONE ,MID_UP_MARGIN|CONVERT_TWIPS },
+ { SW_PROP_NMID(UNO_NAME_FOOTER_IS_DYNAMIC_HEIGHT), FN_UNO_FOOTER_IS_DYNAMIC_DISTANCE,CPPU_E2T(CPPUTYPE_BOOLEAN), PROPERTY_NONE ,0 },
+ { SW_PROP_NMID(UNO_NAME_FOOTER_IS_SHARED), FN_UNO_FOOTER_SHARE_CONTENT,CPPU_E2T(CPPUTYPE_BOOLEAN), PROPERTY_NONE ,0 },
+ { SW_PROP_NMID(UNO_NAME_FOOTER_HEIGHT), FN_UNO_FOOTER_HEIGHT, CPPU_E2T(CPPUTYPE_INT32), PROPERTY_NONE ,MID_SIZE_HEIGHT|CONVERT_TWIPS },
+ { SW_PROP_NMID(UNO_NAME_FOOTER_IS_ON), FN_UNO_FOOTER_ON, CPPU_E2T(CPPUTYPE_BOOLEAN), PROPERTY_NONE ,0 },
+ { SW_PROP_NMID(UNO_NAME_FOOTER_DYNAMIC_SPACING), FN_UNO_FOOTER_EAT_SPACING, CPPU_E2T(CPPUTYPE_BOOLEAN), PropertyAttribute::MAYBEVOID ,0 },
+
+
+ { SW_PROP_NMID(UNO_NAME_IS_LANDSCAPE), SID_ATTR_PAGE, CPPU_E2T(CPPUTYPE_BOOLEAN), PROPERTY_NONE ,MID_PAGE_ORIENTATION },
+ { SW_PROP_NMID(UNO_NAME_NUMBERING_TYPE), SID_ATTR_PAGE, CPPU_E2T(CPPUTYPE_INT16), PROPERTY_NONE , MID_PAGE_NUMTYPE },
+ { SW_PROP_NMID(UNO_NAME_PAGE_STYLE_LAYOUT), SID_ATTR_PAGE, CPPU_E2T(CPPUTYPE_PAGESTYLELAY), PROPERTY_NONE ,MID_PAGE_LAYOUT },
+ { SW_PROP_NMID(UNO_NAME_PRINTER_PAPER_TRAY), RES_PAPER_BIN, CPPU_E2T(CPPUTYPE_OUSTRING), PROPERTY_NONE , 0 },
+// { SW_PROP_NMID(UNO_NAME_REGISTER_MODE_ACTIVE), SID_SWREGISTER_MODE, CPPU_E2T(CPPUTYPE_BOOLEAN), PROPERTY_NONE , 0 },
+ { SW_PROP_NMID(UNO_NAME_REGISTER_PARAGRAPH_STYLE), SID_SWREGISTER_COLLECTION, CPPU_E2T(CPPUTYPE_OUSTRING), PROPERTY_NONE , 0 },
+ { SW_PROP_NMID(UNO_NAME_SIZE), SID_ATTR_PAGE_SIZE, CPPU_E2T(CPPUTYPE_AWTSIZE), PROPERTY_NONE, MID_SIZE_SIZE|CONVERT_TWIPS},
+ { SW_PROP_NMID(UNO_NAME_WIDTH), SID_ATTR_PAGE_SIZE, CPPU_E2T(CPPUTYPE_INT32) , PROPERTY_NONE, MID_SIZE_WIDTH|CONVERT_TWIPS},
+ { SW_PROP_NMID(UNO_NAME_HEIGHT), SID_ATTR_PAGE_SIZE, CPPU_E2T(CPPUTYPE_INT32) , PROPERTY_NONE, MID_SIZE_HEIGHT|CONVERT_TWIPS },
+ { SW_PROP_NMID(UNO_NAME_TEXT_COLUMNS), RES_COL, CPPU_E2T(CPPUTYPE_REFTEXTCOL), PROPERTY_NONE, MID_COLUMNS},
+ { SW_PROP_NMID(UNO_NAME_TOP_MARGIN), RES_UL_SPACE, CPPU_E2T(CPPUTYPE_INT32), PROPERTY_NONE, MID_UP_MARGIN|CONVERT_TWIPS},
+ { SW_PROP_NMID(UNO_NAME_BOTTOM_MARGIN), RES_UL_SPACE, CPPU_E2T(CPPUTYPE_INT32), PROPERTY_NONE, MID_LO_MARGIN|CONVERT_TWIPS},
+ { SW_PROP_NMID(UNO_NAME_HEADER_TEXT), FN_UNO_HEADER, CPPU_E2T(CPPUTYPE_REFTEXT), PropertyAttribute::MAYBEVOID|PropertyAttribute::READONLY, 0},
+ { SW_PROP_NMID(UNO_NAME_HEADER_TEXT_LEFT), FN_UNO_HEADER_LEFT, CPPU_E2T(CPPUTYPE_REFTEXT), PropertyAttribute::MAYBEVOID|PropertyAttribute::READONLY, 0},
+ { SW_PROP_NMID(UNO_NAME_HEADER_TEXT_RIGHT), FN_UNO_HEADER_RIGHT, CPPU_E2T(CPPUTYPE_REFTEXT), PropertyAttribute::MAYBEVOID|PropertyAttribute::READONLY, 0},
+ { SW_PROP_NMID(UNO_NAME_FOOTER_TEXT), FN_UNO_FOOTER, CPPU_E2T(CPPUTYPE_REFTEXT), PropertyAttribute::MAYBEVOID|PropertyAttribute::READONLY, 0},
+ { SW_PROP_NMID(UNO_NAME_FOOTER_TEXT_LEFT), FN_UNO_FOOTER_LEFT, CPPU_E2T(CPPUTYPE_REFTEXT), PropertyAttribute::MAYBEVOID|PropertyAttribute::READONLY, 0},
+ { SW_PROP_NMID(UNO_NAME_FOOTER_TEXT_RIGHT), FN_UNO_FOOTER_RIGHT, CPPU_E2T(CPPUTYPE_REFTEXT), PropertyAttribute::MAYBEVOID|PropertyAttribute::READONLY, 0},
+ { SW_PROP_NMID(UNO_NAME_FOLLOW_STYLE), FN_UNO_FOLLOW_STYLE, CPPU_E2T(CPPUTYPE_OUSTRING), PROPERTY_NONE, 0},
+ { SW_PROP_NMID(UNO_NAME_USER_DEFINED_ATTRIBUTES), RES_UNKNOWNATR_CONTAINER, CPPU_E2T(CPPUTYPE_REFNAMECNT), PropertyAttribute::MAYBEVOID, 0 },
+ { SW_PROP_NMID(UNO_NAME_IS_PHYSICAL), FN_UNO_IS_PHYSICAL, CPPU_E2T(CPPUTYPE_BOOLEAN), PropertyAttribute::READONLY, 0},
+ { SW_PROP_NMID(UNO_NAME_DISPLAY_NAME), FN_UNO_DISPLAY_NAME, CPPU_E2T(CPPUTYPE_OUSTRING), PropertyAttribute::READONLY, 0},
+ { SW_PROP_NMID(UNO_NAME_FOOTNOTE_HEIGHT), FN_PARAM_FTN_INFO, CPPU_E2T(CPPUTYPE_INT32), PROPERTY_NONE , MID_FTN_HEIGHT|CONVERT_TWIPS},
+ { SW_PROP_NMID(UNO_NAME_FOOTNOTE_LINE_WEIGHT), FN_PARAM_FTN_INFO, CPPU_E2T(CPPUTYPE_INT16), PROPERTY_NONE , MID_LINE_WEIGHT|CONVERT_TWIPS},
+ { SW_PROP_NMID(UNO_NAME_FOOTNOTE_LINE_COLOR), FN_PARAM_FTN_INFO, CPPU_E2T(CPPUTYPE_INT32), PROPERTY_NONE , MID_LINE_COLOR},
+ { SW_PROP_NMID(UNO_NAME_FOOTNOTE_LINE_STYLE), FN_PARAM_FTN_INFO, CPPU_E2T(CPPUTYPE_INT8), PROPERTY_NONE , MID_FTN_LINE_STYLE},
+ { SW_PROP_NMID(UNO_NAME_FOOTNOTE_LINE_RELATIVE_WIDTH), FN_PARAM_FTN_INFO, CPPU_E2T(CPPUTYPE_INT8), PROPERTY_NONE , MID_LINE_RELWIDTH },
+ { SW_PROP_NMID(UNO_NAME_FOOTNOTE_LINE_ADJUST), FN_PARAM_FTN_INFO, CPPU_E2T(CPPUTYPE_INT16), PROPERTY_NONE , MID_LINE_ADJUST },
+ { SW_PROP_NMID(UNO_NAME_FOOTNOTE_LINE_TEXT_DISTANCE), FN_PARAM_FTN_INFO, CPPU_E2T(CPPUTYPE_INT32), PROPERTY_NONE , MID_LINE_TEXT_DIST |CONVERT_TWIPS },
+ { SW_PROP_NMID(UNO_NAME_FOOTNOTE_LINE_DISTANCE), FN_PARAM_FTN_INFO, CPPU_E2T(CPPUTYPE_INT32), PROPERTY_NONE , MID_LINE_FOOTNOTE_DIST|CONVERT_TWIPS},
+ { SW_PROP_NMID(UNO_NAME_WRITING_MODE), RES_FRAMEDIR, CPPU_E2T(CPPUTYPE_INT16), PROPERTY_NONE, 0 },
+ // writing grid
+ { SW_PROP_NMID(UNO_NAME_GRID_COLOR), RES_TEXTGRID, CPPU_E2T(CPPUTYPE_INT32), PROPERTY_NONE, MID_GRID_COLOR},
+ { SW_PROP_NMID(UNO_NAME_GRID_LINES), RES_TEXTGRID, CPPU_E2T(CPPUTYPE_INT16), PROPERTY_NONE, MID_GRID_LINES},
+ { SW_PROP_NMID(UNO_NAME_GRID_BASE_HEIGHT), RES_TEXTGRID, CPPU_E2T(CPPUTYPE_INT32), PROPERTY_NONE, MID_GRID_BASEHEIGHT|CONVERT_TWIPS},
+ { SW_PROP_NMID(UNO_NAME_GRID_RUBY_HEIGHT), RES_TEXTGRID, CPPU_E2T(CPPUTYPE_INT32), PROPERTY_NONE, MID_GRID_RUBYHEIGHT|CONVERT_TWIPS},
+ { SW_PROP_NMID(UNO_NAME_GRID_MODE), RES_TEXTGRID, CPPU_E2T(CPPUTYPE_INT16), PROPERTY_NONE, MID_GRID_TYPE},
+ { SW_PROP_NMID(UNO_NAME_GRID_RUBY_BELOW), RES_TEXTGRID, CPPU_E2T(CPPUTYPE_BOOLEAN), PROPERTY_NONE, MID_GRID_RUBY_BELOW},
+ { SW_PROP_NMID(UNO_NAME_GRID_PRINT), RES_TEXTGRID, CPPU_E2T(CPPUTYPE_BOOLEAN), PROPERTY_NONE, MID_GRID_PRINT},
+ { SW_PROP_NMID(UNO_NAME_GRID_DISPLAY), RES_TEXTGRID, CPPU_E2T(CPPUTYPE_BOOLEAN), PROPERTY_NONE, MID_GRID_DISPLAY},
+ { SW_PROP_NMID(UNO_NAME_GRID_BASE_WIDTH), RES_TEXTGRID, CPPU_E2T(CPPUTYPE_INT32), PROPERTY_NONE, MID_GRID_BASEWIDTH|CONVERT_TWIPS},
+ { SW_PROP_NMID(UNO_NAME_GRID_SNAP_TO_CHARS), RES_TEXTGRID, CPPU_E2T(CPPUTYPE_BOOLEAN), PROPERTY_NONE, MID_GRID_SNAPTOCHARS},
+ { SW_PROP_NMID(UNO_NAME_GRID_STANDARD_PAGE_MODE), RES_TEXTGRID, CPPU_E2T(CPPUTYPE_BOOLEAN), PROPERTY_NONE, MID_GRID_STANDARD_MODE},
+ {0,0,0,0,0,0}
+ };
+ aMapEntriesArr[nPropertyId] = aPageStyleMap;
+ }
+ break;
+ case PROPERTY_MAP_NUM_STYLE :
+ {
+ static SfxItemPropertyMapEntry aNumStyleMap [] =
+ {
+ { SW_PROP_NMID(UNO_NAME_NUMBERING_RULES), FN_UNO_NUM_RULES, CPPU_E2T(CPPUTYPE_REFIDXREPL), PROPERTY_NONE, CONVERT_TWIPS},
+ { SW_PROP_NMID(UNO_NAME_IS_PHYSICAL), FN_UNO_IS_PHYSICAL, CPPU_E2T(CPPUTYPE_BOOLEAN), PropertyAttribute::READONLY, 0},
+ { SW_PROP_NMID(UNO_NAME_DISPLAY_NAME), FN_UNO_DISPLAY_NAME, CPPU_E2T(CPPUTYPE_OUSTRING), PropertyAttribute::READONLY, 0},
+ {0,0,0,0,0,0}
+ };
+ aMapEntriesArr[nPropertyId] = aNumStyleMap;
+ }
+ break;
+ case PROPERTY_MAP_TEXT_TABLE :
+ {
+ static SfxItemPropertyMapEntry aTablePropertyMap_Impl[] =
+ {
+ { SW_PROP_NMID(UNO_NAME_BACK_COLOR), RES_BACKGROUND, CPPU_E2T(CPPUTYPE_INT32), PROPERTY_NONE,MID_BACK_COLOR },
+ { SW_PROP_NMID(UNO_NAME_BREAK_TYPE), RES_BREAK, CPPU_E2T(CPPUTYPE_BREAK), PROPERTY_NONE, 0},
+ { SW_PROP_NMID(UNO_NAME_BACK_GRAPHIC_URL), RES_BACKGROUND, CPPU_E2T(CPPUTYPE_OUSTRING), PROPERTY_NONE ,MID_GRAPHIC_URL },
+ { SW_PROP_NMID(UNO_NAME_BACK_GRAPHIC_FILTER), RES_BACKGROUND, CPPU_E2T(CPPUTYPE_OUSTRING), PROPERTY_NONE ,MID_GRAPHIC_FILTER },
+ { SW_PROP_NMID(UNO_NAME_BACK_GRAPHIC_LOCATION), RES_BACKGROUND, CPPU_E2T(CPPUTYPE_GRAPHICLOC), PROPERTY_NONE ,MID_GRAPHIC_POSITION},
+ { SW_PROP_NMID(UNO_NAME_LEFT_MARGIN), RES_LR_SPACE, CPPU_E2T(CPPUTYPE_INT32), PROPERTY_NONE, MID_L_MARGIN|CONVERT_TWIPS},
+ { SW_PROP_NMID(UNO_NAME_RIGHT_MARGIN), RES_LR_SPACE, CPPU_E2T(CPPUTYPE_INT32), PROPERTY_NONE, MID_R_MARGIN|CONVERT_TWIPS},
+ { SW_PROP_NMID(UNO_NAME_HORI_ORIENT), RES_HORI_ORIENT, CPPU_E2T(CPPUTYPE_INT16), PROPERTY_NONE ,MID_HORIORIENT_ORIENT },
+ { SW_PROP_NMID(UNO_NAME_KEEP_TOGETHER), RES_KEEP, CPPU_E2T(CPPUTYPE_BOOLEAN) , PROPERTY_NONE, 0},
+ { SW_PROP_NMID(UNO_NAME_SPLIT), RES_LAYOUT_SPLIT, CPPU_E2T(CPPUTYPE_BOOLEAN) , PROPERTY_NONE, 0},
+ { SW_PROP_NMID(UNO_NAME_PAGE_NUMBER_OFFSET), RES_PAGEDESC, CPPU_E2T(CPPUTYPE_INT16), PropertyAttribute::MAYBEVOID, MID_PAGEDESC_PAGENUMOFFSET},
+ { SW_PROP_NMID(UNO_NAME_PAGE_DESC_NAME), RES_PAGEDESC, CPPU_E2T(CPPUTYPE_OUSTRING), PropertyAttribute::MAYBEVOID, 0xff},
+ { SW_PROP_NMID(UNO_NAME_RELATIVE_WIDTH), FN_TABLE_RELATIVE_WIDTH,CPPU_E2T(CPPUTYPE_INT16) , PROPERTY_NONE, 0xff },
+ { SW_PROP_NMID(UNO_NAME_REPEAT_HEADLINE), FN_TABLE_HEADLINE_REPEAT,CPPU_E2T(CPPUTYPE_BOOLEAN), PROPERTY_NONE, 0xff},
+ { SW_PROP_NMID(UNO_NAME_HEADER_ROW_COUNT), FN_TABLE_HEADLINE_COUNT, CPPU_E2T(CPPUTYPE_INT32), PROPERTY_NONE, 0xff},
+ { SW_PROP_NMID(UNO_NAME_SHADOW_FORMAT), RES_SHADOW, CPPU_E2T(CPPUTYPE_SHADOWFMT), PROPERTY_NONE, 0},
+ { SW_PROP_NMID(UNO_NAME_TOP_MARGIN), RES_UL_SPACE, CPPU_E2T(CPPUTYPE_INT32), PROPERTY_NONE, MID_UP_MARGIN|CONVERT_TWIPS},
+ { SW_PROP_NMID(UNO_NAME_BOTTOM_MARGIN), RES_UL_SPACE, CPPU_E2T(CPPUTYPE_INT32), PROPERTY_NONE, MID_LO_MARGIN|CONVERT_TWIPS},
+ { SW_PROP_NMID(UNO_NAME_BACK_TRANSPARENT), RES_BACKGROUND, CPPU_E2T(CPPUTYPE_BOOLEAN), PROPERTY_NONE ,MID_GRAPHIC_TRANSPARENT },
+ { SW_PROP_NMID(UNO_NAME_WIDTH), FN_TABLE_WIDTH, CPPU_E2T(CPPUTYPE_INT32) , PROPERTY_NONE, 0xff},
+ { SW_PROP_NMID(UNO_NAME_IS_WIDTH_RELATIVE), FN_TABLE_IS_RELATIVE_WIDTH, CPPU_E2T(CPPUTYPE_BOOLEAN) , PROPERTY_NONE, 0xff},
+ { SW_PROP_NMID(UNO_NAME_CHART_ROW_AS_LABEL), FN_UNO_RANGE_ROW_LABEL, CPPU_E2T(CPPUTYPE_BOOLEAN), PROPERTY_NONE, 0},
+ { SW_PROP_NMID(UNO_NAME_CHART_COLUMN_AS_LABEL), FN_UNO_RANGE_COL_LABEL, CPPU_E2T(CPPUTYPE_BOOLEAN) , PROPERTY_NONE, 0},
+ { SW_PROP_NMID(UNO_NAME_TABLE_BORDER), FN_UNO_TABLE_BORDER, CPPU_E2T(CPPUTYPE_TABLEBORDER), PropertyAttribute::MAYBEVOID, CONVERT_TWIPS },
+ { SW_PROP_NMID(UNO_NAME_TABLE_BORDER_DISTANCES), FN_UNO_TABLE_BORDER_DISTANCES, CPPU_E2T(CPPUTYPE_TABLEBORDERDISTANCES), PropertyAttribute::MAYBEVOID, CONVERT_TWIPS },
+ { SW_PROP_NMID(UNO_NAME_TABLE_COLUMN_SEPARATORS), FN_UNO_TABLE_COLUMN_SEPARATORS, CPPU_E2T(CPPUTYPE_TBLCOLSEP), PropertyAttribute::MAYBEVOID, 0 },
+ { SW_PROP_NMID(UNO_NAME_TABLE_COLUMN_RELATIVE_SUM), FN_UNO_TABLE_COLUMN_RELATIVE_SUM, CPPU_E2T(CPPUTYPE_INT16), PropertyAttribute::READONLY, 0 },
+ COMMON_TEXT_CONTENT_PROPERTIES
+ { SW_PROP_NMID(UNO_LINK_DISPLAY_NAME), FN_PARAM_LINK_DISPLAY_NAME, CPPU_E2T(CPPUTYPE_OUSTRING), PropertyAttribute::READONLY, 0xff},
+ { SW_PROP_NMID(UNO_NAME_USER_DEFINED_ATTRIBUTES), RES_UNKNOWNATR_CONTAINER, CPPU_E2T(CPPUTYPE_REFNAMECNT), PropertyAttribute::MAYBEVOID, 0 },
+ { SW_PROP_NMID(UNO_NAME_TEXT_SECTION), FN_UNO_TEXT_SECTION, CPPU_E2T(CPPUTYPE_REFTEXTSECTION), PropertyAttribute::MAYBEVOID|PropertyAttribute::READONLY ,0 },
+ { SW_PROP_NMID(UNO_NAME_WRITING_MODE), RES_FRAMEDIR, CPPU_E2T(CPPUTYPE_INT16), PROPERTY_NONE, 0 },
+ { SW_PROP_NMID(UNO_NAME_TABLE_NAME), FN_UNO_TABLE_NAME, CPPU_E2T(CPPUTYPE_OUSTRING), PROPERTY_NONE, 0 },
+ { SW_PROP_NMID(UNO_NAME_PAGE_STYLE_NAME), RES_PAGEDESC, CPPU_E2T(CPPUTYPE_OUSTRING), PROPERTY_NONE, 0},
+ // #i29550#
+ { SW_PROP_NMID(UNO_NAME_COLLAPSING_BORDERS), RES_COLLAPSING_BORDERS, CPPU_E2T(CPPUTYPE_BOOLEAN), PROPERTY_NONE, 0},
+ _REDLINE_NODE_PROPERTIES
+ {0,0,0,0,0,0}
+ };
+
+ aMapEntriesArr[nPropertyId] = aTablePropertyMap_Impl;
+ }
+ break;
+ case PROPERTY_MAP_TABLE_CELL :
+ {
+ static SfxItemPropertyMapEntry aCellMap_Impl[] =
+ {
+ { SW_PROP_NMID(UNO_NAME_BACK_COLOR), RES_BACKGROUND, CPPU_E2T(CPPUTYPE_INT32), PROPERTY_NONE , MID_BACK_COLOR },
+ { SW_PROP_NMID(UNO_NAME_BACK_GRAPHIC_URL), RES_BACKGROUND, CPPU_E2T(CPPUTYPE_OUSTRING), PROPERTY_NONE ,MID_GRAPHIC_URL },
+ { SW_PROP_NMID(UNO_NAME_BACK_GRAPHIC_FILTER), RES_BACKGROUND, CPPU_E2T(CPPUTYPE_OUSTRING), PROPERTY_NONE ,MID_GRAPHIC_FILTER },
+ { SW_PROP_NMID(UNO_NAME_BACK_GRAPHIC_LOCATION), RES_BACKGROUND, CPPU_E2T(CPPUTYPE_GRAPHICLOC), PROPERTY_NONE ,MID_GRAPHIC_POSITION},
+ { SW_PROP_NMID(UNO_NAME_BACK_TRANSPARENT), RES_BACKGROUND, CPPU_E2T(CPPUTYPE_BOOLEAN), PROPERTY_NONE , MID_GRAPHIC_TRANSPARENT },
+ { SW_PROP_NMID(UNO_NAME_NUMBER_FORMAT), RES_BOXATR_FORMAT, CPPU_E2T(CPPUTYPE_INT32), PropertyAttribute::MAYBEVOID ,0 },
+ { SW_PROP_NMID(UNO_NAME_LEFT_BORDER), RES_BOX, CPPU_E2T(CPPUTYPE_BORDERLINE), 0, LEFT_BORDER |CONVERT_TWIPS },
+ { SW_PROP_NMID(UNO_NAME_RIGHT_BORDER), RES_BOX, CPPU_E2T(CPPUTYPE_BORDERLINE), 0, RIGHT_BORDER |CONVERT_TWIPS },
+ { SW_PROP_NMID(UNO_NAME_TOP_BORDER), RES_BOX, CPPU_E2T(CPPUTYPE_BORDERLINE), 0, TOP_BORDER |CONVERT_TWIPS },
+ { SW_PROP_NMID(UNO_NAME_BOTTOM_BORDER), RES_BOX, CPPU_E2T(CPPUTYPE_BORDERLINE), 0, BOTTOM_BORDER|CONVERT_TWIPS },
+ { SW_PROP_NMID(UNO_NAME_BORDER_DISTANCE), RES_BOX, CPPU_E2T(CPPUTYPE_INT32), 0, BORDER_DISTANCE|CONVERT_TWIPS },
+ { SW_PROP_NMID(UNO_NAME_LEFT_BORDER_DISTANCE), RES_BOX, CPPU_E2T(CPPUTYPE_INT32), 0, LEFT_BORDER_DISTANCE |CONVERT_TWIPS },
+ { SW_PROP_NMID(UNO_NAME_RIGHT_BORDER_DISTANCE), RES_BOX, CPPU_E2T(CPPUTYPE_INT32), 0, RIGHT_BORDER_DISTANCE |CONVERT_TWIPS },
+ { SW_PROP_NMID(UNO_NAME_TOP_BORDER_DISTANCE), RES_BOX, CPPU_E2T(CPPUTYPE_INT32), 0, TOP_BORDER_DISTANCE |CONVERT_TWIPS },
+ { SW_PROP_NMID(UNO_NAME_BOTTOM_BORDER_DISTANCE), RES_BOX, CPPU_E2T(CPPUTYPE_INT32), 0, BOTTOM_BORDER_DISTANCE|CONVERT_TWIPS },
+ { SW_PROP_NMID(UNO_NAME_USER_DEFINED_ATTRIBUTES), RES_UNKNOWNATR_CONTAINER, CPPU_E2T(CPPUTYPE_REFNAMECNT), PropertyAttribute::MAYBEVOID, 0 },
+ { SW_PROP_NMID(UNO_NAME_TEXT_SECTION), FN_UNO_TEXT_SECTION, CPPU_E2T(CPPUTYPE_REFTEXTSECTION), PropertyAttribute::MAYBEVOID|PropertyAttribute::READONLY ,0 },
+ { SW_PROP_NMID(UNO_NAME_IS_PROTECTED), RES_PROTECT, CPPU_E2T(CPPUTYPE_BOOLEAN), 0, MID_PROTECT_CONTENT},
+ { SW_PROP_NMID(UNO_NAME_CELL_NAME), FN_UNO_CELL_NAME, CPPU_E2T(CPPUTYPE_OUSTRING), PropertyAttribute::READONLY,0},
+ { SW_PROP_NMID(UNO_NAME_VERT_ORIENT), RES_VERT_ORIENT, CPPU_E2T(CPPUTYPE_INT16), PROPERTY_NONE ,MID_VERTORIENT_ORIENT },
+ { SW_PROP_NMID(UNO_NAME_WRITING_MODE), RES_FRAMEDIR, CPPU_E2T(CPPUTYPE_INT16), PROPERTY_NONE, 0 },
+ { SW_PROP_NMID(UNO_NAME_ROW_SPAN), FN_UNO_CELL_ROW_SPAN, CPPU_E2T(CPPUTYPE_INT32), 0, 0 },
+ _REDLINE_NODE_PROPERTIES
+ {0,0,0,0,0,0}
+ };
+ aMapEntriesArr[nPropertyId] = aCellMap_Impl;
+ }
+ break;
+ case PROPERTY_MAP_TABLE_RANGE:
+ {
+ static SfxItemPropertyMapEntry aRangePropertyMap_Impl[] =
+ {
+ COMMON_CRSR_PARA_PROPERTIES_WITHOUT_FN_01
+ TABSTOPS_MAP_ENTRY
+ { SW_PROP_NMID(UNO_NAME_BACK_COLOR), FN_UNO_TABLE_CELL_BACKGROUND, CPPU_E2T(CPPUTYPE_INT32), PropertyAttribute::MAYBEVOID|PropertyAttribute::MAYBEVOID ,MID_BACK_COLOR },
+ { SW_PROP_NMID(UNO_NAME_BACK_GRAPHIC_URL), RES_BACKGROUND, CPPU_E2T(CPPUTYPE_OUSTRING), PropertyAttribute::MAYBEVOID ,MID_GRAPHIC_URL },
+ { SW_PROP_NMID(UNO_NAME_BACK_GRAPHIC_FILTER), RES_BACKGROUND, CPPU_E2T(CPPUTYPE_OUSTRING), PropertyAttribute::MAYBEVOID ,MID_GRAPHIC_FILTER },
+ { SW_PROP_NMID(UNO_NAME_BACK_GRAPHIC_LOCATION), FN_UNO_TABLE_CELL_BACKGROUND, CPPU_E2T(CPPUTYPE_GRAPHICLOC), PropertyAttribute::MAYBEVOID|PropertyAttribute::MAYBEVOID ,MID_GRAPHIC_POSITION},
+ { SW_PROP_NMID(UNO_NAME_BACK_TRANSPARENT), FN_UNO_TABLE_CELL_BACKGROUND, CPPU_E2T(CPPUTYPE_BOOLEAN), PropertyAttribute::MAYBEVOID|PropertyAttribute::MAYBEVOID ,MID_GRAPHIC_TRANSPARENT },
+ { SW_PROP_NMID(UNO_NAME_NUMBER_FORMAT), RES_BOXATR_FORMAT, CPPU_E2T(CPPUTYPE_INT32), PropertyAttribute::MAYBEVOID ,0 },
+ { SW_PROP_NMID(UNO_NAME_VERT_ORIENT), RES_VERT_ORIENT, CPPU_E2T(CPPUTYPE_INT16), PROPERTY_NONE ,MID_VERTORIENT_ORIENT },
+ { SW_PROP_NMID(UNO_NAME_CHART_ROW_AS_LABEL), FN_UNO_RANGE_ROW_LABEL, CPPU_E2T(CPPUTYPE_BOOLEAN), PropertyAttribute::MAYBEVOID, 0},
+ { SW_PROP_NMID(UNO_NAME_CHART_COLUMN_AS_LABEL), FN_UNO_RANGE_COL_LABEL, CPPU_E2T(CPPUTYPE_BOOLEAN) , PropertyAttribute::MAYBEVOID, 0},
+
+ {0,0,0,0,0,0}
+ };
+ aMapEntriesArr[nPropertyId] = aRangePropertyMap_Impl;
+ }
+ break;
+ case PROPERTY_MAP_SECTION:
+ {
+ static SfxItemPropertyMapEntry aSectionPropertyMap_Impl[] =
+ {
+ { SW_PROP_NMID(UNO_NAME_CONDITION), WID_SECT_CONDITION, CPPU_E2T(CPPUTYPE_OUSTRING) , PROPERTY_NONE, 0},
+ { SW_PROP_NMID(UNO_NAME_DDE_COMMAND_FILE), WID_SECT_DDE_TYPE, CPPU_E2T(CPPUTYPE_OUSTRING) , PROPERTY_NONE, 0},
+ { SW_PROP_NMID(UNO_NAME_DDE_COMMAND_TYPE), WID_SECT_DDE_FILE, CPPU_E2T(CPPUTYPE_OUSTRING) , PROPERTY_NONE, 0},
+ { SW_PROP_NMID(UNO_NAME_DDE_COMMAND_ELEMENT), WID_SECT_DDE_ELEMENT, CPPU_E2T(CPPUTYPE_OUSTRING) , PROPERTY_NONE, 0},
+ { SW_PROP_NMID(UNO_NAME_IS_AUTOMATIC_UPDATE), WID_SECT_DDE_AUTOUPDATE, CPPU_E2T(CPPUTYPE_BOOLEAN), PROPERTY_NONE, 0},
+ { SW_PROP_NMID(UNO_NAME_FILE_LINK), WID_SECT_LINK , CPPU_E2T(CPPUTYPE_SECTFILELNK), PROPERTY_NONE, 0},
+ { SW_PROP_NMID(UNO_NAME_IS_VISIBLE), WID_SECT_VISIBLE , CPPU_E2T(CPPUTYPE_BOOLEAN), PROPERTY_NONE, 0},
+ { SW_PROP_NMID(UNO_NAME_IS_PROTECTED), WID_SECT_PROTECTED, CPPU_E2T(CPPUTYPE_BOOLEAN), PROPERTY_NONE, 0},
+ { SW_PROP_NMID(UNO_NAME_EDIT_IN_READONLY), WID_SECT_EDIT_IN_READONLY, CPPU_E2T(CPPUTYPE_BOOLEAN), PROPERTY_NONE, 0},
+ { SW_PROP_NMID(UNO_NAME_LINK_REGION), WID_SECT_REGION , CPPU_E2T(CPPUTYPE_OUSTRING) , PROPERTY_NONE, 0},
+ { SW_PROP_NMID(UNO_NAME_TEXT_COLUMNS), RES_COL, CPPU_E2T(CPPUTYPE_REFTEXTCOL), PROPERTY_NONE, MID_COLUMNS},
+ { SW_PROP_NMID(UNO_NAME_BACK_GRAPHIC_URL), RES_BACKGROUND, CPPU_E2T(CPPUTYPE_OUSTRING), PROPERTY_NONE ,MID_GRAPHIC_URL },
+ { SW_PROP_NMID(UNO_NAME_BACK_GRAPHIC_FILTER), RES_BACKGROUND, CPPU_E2T(CPPUTYPE_OUSTRING), PROPERTY_NONE ,MID_GRAPHIC_FILTER },
+ { SW_PROP_NMID(UNO_NAME_BACK_GRAPHIC_LOCATION), RES_BACKGROUND, CPPU_E2T(CPPUTYPE_GRAPHICLOC), PROPERTY_NONE ,MID_GRAPHIC_POSITION},
+ { SW_PROP_NMID(UNO_NAME_BACK_COLOR), RES_BACKGROUND, CPPU_E2T(CPPUTYPE_INT32), PROPERTY_NONE ,MID_BACK_COLOR },
+ { SW_PROP_NMID(UNO_NAME_BACK_TRANSPARENT), RES_BACKGROUND, CPPU_E2T(CPPUTYPE_BOOLEAN), PROPERTY_NONE ,MID_GRAPHIC_TRANSPARENT },
+ { SW_PROP_NMID(UNO_LINK_DISPLAY_NAME), FN_PARAM_LINK_DISPLAY_NAME, CPPU_E2T(CPPUTYPE_OUSTRING), PropertyAttribute::READONLY, 0xff},
+ { SW_PROP_NMID(UNO_NAME_USER_DEFINED_ATTRIBUTES), RES_UNKNOWNATR_CONTAINER, CPPU_E2T(CPPUTYPE_REFNAMECNT), PropertyAttribute::MAYBEVOID, 0 },
+ { SW_PROP_NMID(UNO_NAME_FOOTNOTE_IS_COLLECT_AT_TEXT_END), RES_FTN_AT_TXTEND, CPPU_E2T(CPPUTYPE_BOOLEAN), PROPERTY_NONE ,MID_COLLECT },
+ { SW_PROP_NMID(UNO_NAME_FOOTNOTE_IS_RESTART_NUMBERING), RES_FTN_AT_TXTEND, CPPU_E2T(CPPUTYPE_BOOLEAN), PROPERTY_NONE , MID_RESTART_NUM },
+ { SW_PROP_NMID(UNO_NAME_FOOTNOTE_RESTART_NUMBERING_AT), RES_FTN_AT_TXTEND, CPPU_E2T(CPPUTYPE_INT16), PROPERTY_NONE , MID_NUM_START_AT},
+ { SW_PROP_NMID(UNO_NAME_FOOTNOTE_IS_OWN_NUMBERING), RES_FTN_AT_TXTEND, CPPU_E2T(CPPUTYPE_BOOLEAN), PROPERTY_NONE , MID_OWN_NUM },
+ { SW_PROP_NMID(UNO_NAME_FOOTNOTE_NUMBERING_TYPE), RES_FTN_AT_TXTEND, CPPU_E2T(CPPUTYPE_INT16), PROPERTY_NONE , MID_NUM_TYPE },
+ { SW_PROP_NMID(UNO_NAME_FOOTNOTE_NUMBERING_PREFIX), RES_FTN_AT_TXTEND, CPPU_E2T(CPPUTYPE_OUSTRING) , PROPERTY_NONE, MID_PREFIX },
+ { SW_PROP_NMID(UNO_NAME_FOOTNOTE_NUMBERING_SUFFIX), RES_FTN_AT_TXTEND, CPPU_E2T(CPPUTYPE_OUSTRING) , PROPERTY_NONE, MID_SUFFIX },
+ { SW_PROP_NMID(UNO_NAME_ENDNOTE_IS_COLLECT_AT_TEXT_END), RES_END_AT_TXTEND, CPPU_E2T(CPPUTYPE_BOOLEAN), PROPERTY_NONE , MID_COLLECT },
+ { SW_PROP_NMID(UNO_NAME_ENDNOTE_IS_RESTART_NUMBERING), RES_END_AT_TXTEND, CPPU_E2T(CPPUTYPE_BOOLEAN), PROPERTY_NONE , MID_RESTART_NUM },
+ { SW_PROP_NMID(UNO_NAME_ENDNOTE_RESTART_NUMBERING_AT), RES_END_AT_TXTEND, CPPU_E2T(CPPUTYPE_INT16), PROPERTY_NONE , MID_NUM_START_AT },
+ { SW_PROP_NMID(UNO_NAME_ENDNOTE_IS_OWN_NUMBERING), RES_END_AT_TXTEND, CPPU_E2T(CPPUTYPE_BOOLEAN), PROPERTY_NONE , MID_OWN_NUM },
+ { SW_PROP_NMID(UNO_NAME_ENDNOTE_NUMBERING_TYPE), RES_END_AT_TXTEND, CPPU_E2T(CPPUTYPE_INT16), PROPERTY_NONE ,MID_NUM_TYPE },
+ { SW_PROP_NMID(UNO_NAME_ENDNOTE_NUMBERING_PREFIX), RES_END_AT_TXTEND, CPPU_E2T(CPPUTYPE_OUSTRING) , PROPERTY_NONE, MID_PREFIX },
+ { SW_PROP_NMID(UNO_NAME_ENDNOTE_NUMBERING_SUFFIX), RES_END_AT_TXTEND, CPPU_E2T(CPPUTYPE_OUSTRING) , PROPERTY_NONE, MID_SUFFIX },
+ { SW_PROP_NMID(UNO_NAME_DOCUMENT_INDEX), WID_SECT_DOCUMENT_INDEX, CPPU_E2T(CPPUTYPE_REFDOCINDEX), PropertyAttribute::READONLY | PropertyAttribute::MAYBEVOID, 0 },
+ { SW_PROP_NMID(UNO_NAME_IS_GLOBAL_DOCUMENT_SECTION), WID_SECT_IS_GLOBAL_DOC_SECTION, CPPU_E2T(CPPUTYPE_BOOLEAN), PropertyAttribute::READONLY, 0 },
+ { SW_PROP_NMID(UNO_NAME_PROTECTION_KEY), WID_SECT_PASSWORD, CPPU_E2T(CPPUTYPE_SEQINT8), PROPERTY_NONE, 0 },
+ { SW_PROP_NMID(UNO_NAME_DONT_BALANCE_TEXT_COLUMNS), RES_COLUMNBALANCE, CPPU_E2T(CPPUTYPE_BOOLEAN), PROPERTY_NONE, 0 },
+ COMMON_TEXT_CONTENT_PROPERTIES
+ _REDLINE_NODE_PROPERTIES
+ { SW_PROP_NMID(UNO_NAME_IS_CURRENTLY_VISIBLE), WID_SECT_CURRENTLY_VISIBLE, CPPU_E2T(CPPUTYPE_BOOLEAN), PROPERTY_NONE, 0},
+ { SW_PROP_NMID(UNO_NAME_WRITING_MODE), RES_FRAMEDIR, CPPU_E2T(CPPUTYPE_INT16), PROPERTY_NONE, 0 },
+ { SW_PROP_NMID(UNO_NAME_SECT_LEFT_MARGIN), RES_LR_SPACE, CPPU_E2T(CPPUTYPE_INT32), PropertyAttribute::MAYBEVOID, MID_L_MARGIN|CONVERT_TWIPS}, \
+ { SW_PROP_NMID(UNO_NAME_SECT_RIGHT_MARGIN), RES_LR_SPACE, CPPU_E2T(CPPUTYPE_INT32), PropertyAttribute::MAYBEVOID, MID_R_MARGIN|CONVERT_TWIPS}, \
+ {0,0,0,0,0,0}
+ };
+ aMapEntriesArr[nPropertyId] = aSectionPropertyMap_Impl;
+ }
+ break;
+ case PROPERTY_MAP_TEXT_SEARCH:
+ {
+ static SfxItemPropertyMapEntry aSearchPropertyMap_Impl[] =
+ {
+ { SW_PROP_NMID(UNO_NAME_SEARCH_ALL), WID_SEARCH_ALL, CPPU_E2T(CPPUTYPE_BOOLEAN) , PROPERTY_NONE, 0},
+ { SW_PROP_NMID(UNO_NAME_SEARCH_BACKWARDS), WID_BACKWARDS, CPPU_E2T(CPPUTYPE_BOOLEAN) , PROPERTY_NONE, 0},
+ { SW_PROP_NMID(UNO_NAME_SEARCH_CASE_SENSITIVE), WID_CASE_SENSITIVE, CPPU_E2T(CPPUTYPE_BOOLEAN) , PROPERTY_NONE, 0},
+ { SW_PROP_NMID(UNO_NAME_SEARCH_REGULAR_EXPRESSION), WID_REGULAR_EXPRESSION, CPPU_E2T(CPPUTYPE_BOOLEAN) , PROPERTY_NONE, 0},
+ { SW_PROP_NMID(UNO_NAME_SEARCH_SIMILARITY), WID_SIMILARITY, CPPU_E2T(CPPUTYPE_BOOLEAN) , PROPERTY_NONE, 0},
+ { SW_PROP_NMID(UNO_NAME_SEARCH_SIMILARITY_ADD), WID_SIMILARITY_ADD, CPPU_E2T(CPPUTYPE_INT16) , PROPERTY_NONE, 0},
+ { SW_PROP_NMID(UNO_NAME_SEARCH_SIMILARITY_EXCHANGE), WID_SIMILARITY_EXCHANGE,CPPU_E2T(CPPUTYPE_INT16) , PROPERTY_NONE, 0},
+ { SW_PROP_NMID(UNO_NAME_SEARCH_SIMILARITY_RELAX), WID_SIMILARITY_RELAX, CPPU_E2T(CPPUTYPE_BOOLEAN) , PROPERTY_NONE, 0},
+ { SW_PROP_NMID(UNO_NAME_SEARCH_SIMILARITY_REMOVE), WID_SIMILARITY_REMOVE, CPPU_E2T(CPPUTYPE_INT16) , PROPERTY_NONE, 0},
+ { SW_PROP_NMID(UNO_NAME_SEARCH_STYLES), WID_STYLES, CPPU_E2T(CPPUTYPE_BOOLEAN) , PROPERTY_NONE, 0},
+ { SW_PROP_NMID(UNO_NAME_SEARCH_WORDS), WID_WORDS, CPPU_E2T(CPPUTYPE_BOOLEAN) , PROPERTY_NONE, 0},
+ {0,0,0,0,0,0}
+ };
+ aMapEntriesArr[nPropertyId] = aSearchPropertyMap_Impl;
+ }
+ break;
+ case PROPERTY_MAP_TEXT_FRAME:
+ {
+ static SfxItemPropertyMapEntry aFramePropertyMap_Impl[] =
+ {
+ COMMON_FRAME_PROPERTIES
+ _REDLINE_NODE_PROPERTIES
+ { SW_PROP_NMID(UNO_NAME_CHAIN_NEXT_NAME), RES_CHAIN, CPPU_E2T(CPPUTYPE_OUSTRING), PropertyAttribute::MAYBEVOID ,MID_CHAIN_NEXTNAME},
+ { SW_PROP_NMID(UNO_NAME_CHAIN_PREV_NAME), RES_CHAIN, CPPU_E2T(CPPUTYPE_OUSTRING), PropertyAttribute::MAYBEVOID ,MID_CHAIN_PREVNAME},
+ /*not impl*/ { SW_PROP_NMID(UNO_NAME_CLIENT_MAP), RES_URL, CPPU_E2T(CPPUTYPE_BOOLEAN), PROPERTY_NONE ,MID_URL_CLIENTMAP },
+ { SW_PROP_NMID(UNO_NAME_EDIT_IN_READONLY), RES_EDIT_IN_READONLY, CPPU_E2T(CPPUTYPE_BOOLEAN), PROPERTY_NONE, 0},
+ { SW_PROP_NMID(UNO_NAME_TEXT_COLUMNS), RES_COL, CPPU_E2T(CPPUTYPE_REFTEXTCOL), PROPERTY_NONE, MID_COLUMNS},
+ //next elements are part of the service description
+ { SW_PROP_NMID(UNO_NAME_FRAME_HEIGHT_ABSOLUTE), RES_FRM_SIZE, CPPU_E2T(CPPUTYPE_INT32), PROPERTY_NONE, MID_FRMSIZE_HEIGHT|CONVERT_TWIPS },
+ { SW_PROP_NMID(UNO_NAME_FRAME_HEIGHT_PERCENT), RES_FRM_SIZE, CPPU_E2T(CPPUTYPE_INT8), PROPERTY_NONE, MID_FRMSIZE_REL_HEIGHT },
+ { SW_PROP_NMID(UNO_NAME_FRAME_ISAUTOMATIC_HEIGHT), RES_FRM_SIZE, CPPU_E2T(CPPUTYPE_BOOLEAN), PROPERTY_NONE, MID_FRMSIZE_IS_AUTO_HEIGHT },
+ { SW_PROP_NMID(UNO_NAME_FRAME_WIDTH_ABSOLUTE), RES_FRM_SIZE, CPPU_E2T(CPPUTYPE_INT32), PROPERTY_NONE, MID_FRMSIZE_WIDTH|CONVERT_TWIPS },
+ { SW_PROP_NMID(UNO_NAME_FRAME_WIDTH_PERCENT), RES_FRM_SIZE, CPPU_E2T(CPPUTYPE_INT8), PROPERTY_NONE, MID_FRMSIZE_REL_WIDTH },
+ { SW_PROP_NMID(UNO_NAME_SIZE_TYPE), RES_FRM_SIZE, CPPU_E2T(CPPUTYPE_INT16) , PROPERTY_NONE, MID_FRMSIZE_SIZE_TYPE },
+ { SW_PROP_NMID(UNO_NAME_WIDTH_TYPE), RES_FRM_SIZE, CPPU_E2T(CPPUTYPE_INT16) , PROPERTY_NONE, MID_FRMSIZE_WIDTH_TYPE },
+ { SW_PROP_NMID(UNO_NAME_WRITING_MODE), RES_FRAMEDIR, CPPU_E2T(CPPUTYPE_INT16), PROPERTY_NONE, 0 },
+ {0,0,0,0,0,0}
+ };
+ aMapEntriesArr[nPropertyId] = aFramePropertyMap_Impl;
+ }
+ break;
+ case PROPERTY_MAP_TEXT_GRAPHIC:
+ {
+ static SfxItemPropertyMapEntry aGraphicPropertyMap_Impl[] =
+ {
+ COMMON_FRAME_PROPERTIES
+ { SW_PROP_NMID(UNO_NAME_SURROUND_CONTOUR), RES_SURROUND, CPPU_E2T(CPPUTYPE_BOOLEAN), PROPERTY_NONE, MID_SURROUND_CONTOUR },
+ { SW_PROP_NMID(UNO_NAME_CONTOUR_OUTSIDE), RES_SURROUND, CPPU_E2T(CPPUTYPE_BOOLEAN), PROPERTY_NONE, MID_SURROUND_CONTOUROUTSIDE },
+ { SW_PROP_NMID(UNO_NAME_GRAPHIC_CROP), RES_GRFATR_CROPGRF, CPPU_E2T(CPPUTYPE_GRFCROP), PROPERTY_NONE, CONVERT_TWIPS },
+ { SW_PROP_NMID(UNO_NAME_HORI_MIRRORED_ON_EVEN_PAGES), RES_GRFATR_MIRRORGRF, CPPU_E2T(CPPUTYPE_BOOLEAN), PROPERTY_NONE, MID_MIRROR_HORZ_EVEN_PAGES },
+ { SW_PROP_NMID(UNO_NAME_HORI_MIRRORED_ON_ODD_PAGES), RES_GRFATR_MIRRORGRF, CPPU_E2T(CPPUTYPE_BOOLEAN), PROPERTY_NONE, MID_MIRROR_HORZ_ODD_PAGES },
+ { SW_PROP_NMID(UNO_NAME_VERT_MIRRORED), RES_GRFATR_MIRRORGRF, CPPU_E2T(CPPUTYPE_BOOLEAN), PROPERTY_NONE, MID_MIRROR_VERT },
+ { SW_PROP_NMID(UNO_NAME_GRAPHIC_URL), FN_UNO_GRAPHIC_U_R_L, CPPU_E2T(CPPUTYPE_OUSTRING), 0, 0 },
+ { SW_PROP_NMID(UNO_NAME_GRAPHIC_FILTER), FN_UNO_GRAPHIC_FILTER, CPPU_E2T(CPPUTYPE_OUSTRING), 0, 0 },
+ { SW_PROP_NMID(UNO_NAME_GRAPHIC), FN_UNO_GRAPHIC, CPPU_E2T(CPPUTYPE_REFXGRAPHIC), 0, 0 },
+ { SW_PROP_NMID(UNO_NAME_ACTUAL_SIZE), FN_UNO_ACTUAL_SIZE, CPPU_E2T(CPPUTYPE_AWTSIZE), PropertyAttribute::READONLY, CONVERT_TWIPS},
+ { SW_PROP_NMID(UNO_NAME_CONTOUR_POLY_POLYGON), FN_PARAM_COUNTOUR_PP, CPPU_E2T(CPPUTYPE_PNTSEQSEQ), PropertyAttribute::MAYBEVOID, 0 },
+ { SW_PROP_NMID(UNO_NAME_IS_PIXEL_CONTOUR), FN_UNO_IS_PIXEL_CONTOUR, CPPU_E2T(CPPUTYPE_BOOLEAN), PROPERTY_NONE, 0 },
+ { SW_PROP_NMID(UNO_NAME_IS_AUTOMATIC_CONTOUR), FN_UNO_IS_AUTOMATIC_CONTOUR , CPPU_E2T(CPPUTYPE_BOOLEAN), PROPERTY_NONE, 0 },
+ { SW_PROP_NMID(UNO_NAME_GRAPHIC_ROTATION), RES_GRFATR_ROTATION, CPPU_E2T(CPPUTYPE_INT16), 0, 0},
+ { SW_PROP_NMID(UNO_NAME_ADJUST_LUMINANCE), RES_GRFATR_LUMINANCE, CPPU_E2T(CPPUTYPE_INT16), 0, 0},
+ { SW_PROP_NMID(UNO_NAME_ADJUST_CONTRAST), RES_GRFATR_CONTRAST, CPPU_E2T(CPPUTYPE_INT16), 0, 0},
+ { SW_PROP_NMID(UNO_NAME_ADJUST_RED), RES_GRFATR_CHANNELR, CPPU_E2T(CPPUTYPE_INT16), 0, 0},
+ { SW_PROP_NMID(UNO_NAME_ADJUST_GREEN), RES_GRFATR_CHANNELG, CPPU_E2T(CPPUTYPE_INT16), 0, 0},
+ { SW_PROP_NMID(UNO_NAME_ADJUST_BLUE), RES_GRFATR_CHANNELB, CPPU_E2T(CPPUTYPE_INT16), 0, 0},
+ { SW_PROP_NMID(UNO_NAME_GAMMA), RES_GRFATR_GAMMA, CPPU_E2T(CPPUTYPE_DOUBLE), 0, 0},
+ { SW_PROP_NMID(UNO_NAME_GRAPHIC_IS_INVERTED), RES_GRFATR_INVERT, CPPU_E2T(CPPUTYPE_BOOLEAN), 0, 0},
+ { SW_PROP_NMID(UNO_NAME_TRANSPARENCY), RES_GRFATR_TRANSPARENCY, CPPU_E2T(CPPUTYPE_INT16), 0, 0},
+ { SW_PROP_NMID(UNO_NAME_GRAPHIC_COLOR_MODE), RES_GRFATR_DRAWMODE, CPPU_E2T(CPPUTYPE_COLORMODE), 0, 0},
+ {0,0,0,0,0,0}
+ };
+ aMapEntriesArr[nPropertyId] = aGraphicPropertyMap_Impl;
+ }
+ break;
+ case PROPERTY_MAP_EMBEDDED_OBJECT:
+ {
+ static SfxItemPropertyMapEntry aEmbeddedPropertyMap_Impl[] =
+ {
+ COMMON_FRAME_PROPERTIES
+ { SW_PROP_NMID(UNO_NAME_SURROUND_CONTOUR), RES_SURROUND, CPPU_E2T(CPPUTYPE_BOOLEAN), PROPERTY_NONE, MID_SURROUND_CONTOUR },
+ { SW_PROP_NMID(UNO_NAME_CONTOUR_OUTSIDE), RES_SURROUND, CPPU_E2T(CPPUTYPE_BOOLEAN), PROPERTY_NONE, MID_SURROUND_CONTOUROUTSIDE},
+ { SW_PROP_NMID(UNO_NAME_CONTOUR_POLY_POLYGON), FN_PARAM_COUNTOUR_PP, CPPU_E2T(CPPUTYPE_PNTSEQSEQ), PropertyAttribute::MAYBEVOID, 0 },
+ { SW_PROP_NMID(UNO_NAME_IS_PIXEL_CONTOUR), FN_UNO_IS_PIXEL_CONTOUR, CPPU_E2T(CPPUTYPE_BOOLEAN), PROPERTY_NONE, 0 },
+ { SW_PROP_NMID(UNO_NAME_IS_AUTOMATIC_CONTOUR), FN_UNO_IS_AUTOMATIC_CONTOUR , CPPU_E2T(CPPUTYPE_BOOLEAN), PROPERTY_NONE, 0 },
+ { SW_PROP_NMID(UNO_NAME_CLSID), FN_UNO_CLSID, CPPU_E2T(CPPUTYPE_OUSTRING), PROPERTY_NONE, 0 },
+ { SW_PROP_NMID(UNO_NAME_STREAM_NAME), FN_UNO_STREAM_NAME, CPPU_E2T(CPPUTYPE_OUSTRING), PROPERTY_NONE, 0 },
+ { SW_PROP_NMID(UNO_NAME_MODEL), FN_UNO_MODEL, CPPU_E2T(CPPUTYPE_REFMODEL), PropertyAttribute::READONLY|PropertyAttribute::MAYBEVOID, 0},
+ { SW_PROP_NMID(UNO_NAME_GRAPHIC_URL), FN_UNO_REPLACEMENT_GRAPHIC_URL, CPPU_E2T(CPPUTYPE_OUSTRING), PropertyAttribute::MAYBEVOID, 0 },
+ { SW_PROP_NMID(UNO_NAME_GRAPHIC), FN_UNO_REPLACEMENT_GRAPHIC, CPPU_E2T(CPPUTYPE_REFXGRAPHIC), PropertyAttribute::MAYBEVOID, 0 },
+ { SW_PROP_NMID(UNO_NAME_COMPONENT),FN_UNO_COMPONENT, CPPU_E2T(CPPUTYPE_REFCOMPONENT), PropertyAttribute::READONLY, 0},
+ { SW_PROP_NMID(UNO_NAME_EMBEDDED_OBJECT),FN_EMBEDDED_OBJECT, CPPU_E2T(CPPUTPYE_REFEMBEDDEDOBJECT), PropertyAttribute::READONLY, 0},
+ {0,0,0,0,0,0}
+ };
+ aMapEntriesArr[nPropertyId] = aEmbeddedPropertyMap_Impl;
+ }
+ break;
+ case PROPERTY_MAP_TEXT_SHAPE:
+ {
+ static SfxItemPropertyMapEntry aShapeMap_Impl[] =
+ {
+ { SW_PROP_NMID(UNO_NAME_ANCHOR_PAGE_NO), RES_ANCHOR, CPPU_E2T(CPPUTYPE_INT16), PROPERTY_NONE|PropertyAttribute::MAYBEVOID, MID_ANCHOR_PAGENUM },
+ { SW_PROP_NMID(UNO_NAME_ANCHOR_TYPE), RES_ANCHOR, CPPU_E2T(CPPUTYPE_TXTCNTANCHOR), PROPERTY_NONE|PropertyAttribute::MAYBEVOID, MID_ANCHOR_ANCHORTYPE},
+ { SW_PROP_NMID(UNO_NAME_ANCHOR_FRAME), RES_ANCHOR, CPPU_E2T(CPPUTYPE_REFTEXTFRAME), PropertyAttribute::MAYBEVOID, MID_ANCHOR_ANCHORFRAME},
+ { SW_PROP_NMID(UNO_NAME_HORI_ORIENT), RES_HORI_ORIENT, CPPU_E2T(CPPUTYPE_INT16), PROPERTY_NONE|PropertyAttribute::MAYBEVOID ,MID_HORIORIENT_ORIENT },
+ { SW_PROP_NMID(UNO_NAME_HORI_ORIENT_POSITION), RES_HORI_ORIENT, CPPU_E2T(CPPUTYPE_INT32), PROPERTY_NONE|PropertyAttribute::MAYBEVOID ,MID_HORIORIENT_POSITION|CONVERT_TWIPS },
+ { SW_PROP_NMID(UNO_NAME_HORI_ORIENT_RELATION), RES_HORI_ORIENT, CPPU_E2T(CPPUTYPE_INT16), PROPERTY_NONE|PropertyAttribute::MAYBEVOID ,MID_HORIORIENT_RELATION },
+ { SW_PROP_NMID(UNO_NAME_LEFT_MARGIN), RES_LR_SPACE, CPPU_E2T(CPPUTYPE_INT32), PROPERTY_NONE|PropertyAttribute::MAYBEVOID, MID_L_MARGIN|CONVERT_TWIPS},
+ { SW_PROP_NMID(UNO_NAME_RIGHT_MARGIN), RES_LR_SPACE, CPPU_E2T(CPPUTYPE_INT32), PROPERTY_NONE|PropertyAttribute::MAYBEVOID, MID_R_MARGIN|CONVERT_TWIPS},
+ { SW_PROP_NMID(UNO_NAME_SURROUND), RES_SURROUND, CPPU_E2T(CPPUTYPE_WRAPTXTMODE), PROPERTY_NONE|PropertyAttribute::MAYBEVOID, MID_SURROUND_SURROUNDTYPE },
+ { SW_PROP_NMID(UNO_NAME_TEXT_WRAP), RES_SURROUND, CPPU_E2T(CPPUTYPE_WRAPTXTMODE), PROPERTY_NONE, MID_SURROUND_SURROUNDTYPE },
+ { SW_PROP_NMID(UNO_NAME_SURROUND_ANCHORONLY), RES_SURROUND, CPPU_E2T(CPPUTYPE_BOOLEAN), PROPERTY_NONE|PropertyAttribute::MAYBEVOID, MID_SURROUND_ANCHORONLY },
+ { SW_PROP_NMID(UNO_NAME_SURROUND_CONTOUR), RES_SURROUND, CPPU_E2T(CPPUTYPE_BOOLEAN), PROPERTY_NONE, MID_SURROUND_CONTOUR },
+ { SW_PROP_NMID(UNO_NAME_CONTOUR_OUTSIDE), RES_SURROUND, CPPU_E2T(CPPUTYPE_BOOLEAN), PROPERTY_NONE, MID_SURROUND_CONTOUROUTSIDE },
+ { SW_PROP_NMID(UNO_NAME_TOP_MARGIN), RES_UL_SPACE, CPPU_E2T(CPPUTYPE_INT32), PROPERTY_NONE, MID_UP_MARGIN|CONVERT_TWIPS},
+ { SW_PROP_NMID(UNO_NAME_BOTTOM_MARGIN), RES_UL_SPACE, CPPU_E2T(CPPUTYPE_INT32), PROPERTY_NONE, MID_LO_MARGIN|CONVERT_TWIPS},
+ { SW_PROP_NMID(UNO_NAME_VERT_ORIENT), RES_VERT_ORIENT, CPPU_E2T(CPPUTYPE_INT16), PROPERTY_NONE|PropertyAttribute::MAYBEVOID ,MID_VERTORIENT_ORIENT },
+ { SW_PROP_NMID(UNO_NAME_VERT_ORIENT_POSITION), RES_VERT_ORIENT, CPPU_E2T(CPPUTYPE_INT32), PROPERTY_NONE|PropertyAttribute::MAYBEVOID ,MID_VERTORIENT_POSITION|CONVERT_TWIPS },
+ { SW_PROP_NMID(UNO_NAME_VERT_ORIENT_RELATION), RES_VERT_ORIENT, CPPU_E2T(CPPUTYPE_INT16), PROPERTY_NONE|PropertyAttribute::MAYBEVOID ,MID_VERTORIENT_RELATION },
+ { SW_PROP_NMID(UNO_NAME_TEXT_RANGE), FN_TEXT_RANGE, CPPU_E2T(CPPUTYPE_REFTXTRANGE), PROPERTY_NONE, 0},
+ { SW_PROP_NMID(UNO_NAME_OPAQUE), RES_OPAQUE, CPPU_E2T(CPPUTYPE_BOOLEAN), PROPERTY_NONE, 0},
+ { SW_PROP_NMID(UNO_NAME_ANCHOR_POSITION), FN_ANCHOR_POSITION, CPPU_E2T(CPPUTYPE_AWTPOINT), PropertyAttribute::READONLY, 0},
+ // #i26791#
+ { SW_PROP_NMID(UNO_NAME_IS_FOLLOWING_TEXT_FLOW), RES_FOLLOW_TEXT_FLOW, CPPU_E2T(CPPUTYPE_BOOLEAN), PROPERTY_NONE, 0},
+ // #i28701#
+ { SW_PROP_NMID(UNO_NAME_WRAP_INFLUENCE_ON_POSITION), RES_WRAP_INFLUENCE_ON_OBJPOS, CPPU_E2T(CPPUTYPE_INT8), PROPERTY_NONE, MID_WRAP_INFLUENCE},
+ // #i28749#
+ { SW_PROP_NMID( UNO_NAME_TRANSFORMATION_IN_HORI_L2R),
+ FN_SHAPE_TRANSFORMATION_IN_HORI_L2R,
+ CPPU_E2T(CPPUTYPE_TRANSFORMATIONINHORIL2R),
+ PropertyAttribute::READONLY, 0},
+ { SW_PROP_NMID( UNO_NAME_POSITION_LAYOUT_DIR),
+ FN_SHAPE_POSITION_LAYOUT_DIR,
+ CPPU_E2T(CPPUTYPE_INT16),
+ PROPERTY_NONE, 0},
+ // #i36248#
+ { SW_PROP_NMID( UNO_NAME_STARTPOSITION_IN_HORI_L2R),
+ FN_SHAPE_STARTPOSITION_IN_HORI_L2R,
+ CPPU_E2T(CPPUTYPE_AWTPOINT),
+ PropertyAttribute::READONLY, 0},
+ { SW_PROP_NMID( UNO_NAME_ENDPOSITION_IN_HORI_L2R),
+ FN_SHAPE_ENDPOSITION_IN_HORI_L2R,
+ CPPU_E2T(CPPUTYPE_AWTPOINT),
+ PropertyAttribute::READONLY, 0},
+ // #i71182#
+ // missing map entry for property <PageToogle>
+ { SW_PROP_NMID(UNO_NAME_PAGE_TOGGLE), RES_HORI_ORIENT, CPPU_E2T(CPPUTYPE_BOOLEAN), PROPERTY_NONE ,MID_HORIORIENT_PAGETOGGLE },
+ {0,0,0,0,0,0}
+ };
+ aMapEntriesArr[nPropertyId] = aShapeMap_Impl;
+ }
+ break;
+ case PROPERTY_MAP_INDEX_MARK:
+ {
+ static SfxItemPropertyMapEntry aIdxMarkMap_Impl[] =
+ {
+ { SW_PROP_NMID(UNO_NAME_ALTERNATIVE_TEXT), WID_ALT_TEXT, CPPU_E2T(CPPUTYPE_OUSTRING) , PROPERTY_NONE, 0},
+ { SW_PROP_NMID(UNO_NAME_PRIMARY_KEY), WID_PRIMARY_KEY, CPPU_E2T(CPPUTYPE_OUSTRING) , PROPERTY_NONE, 0},
+ { SW_PROP_NMID(UNO_NAME_SECONDARY_KEY), WID_SECONDARY_KEY, CPPU_E2T(CPPUTYPE_OUSTRING) , PROPERTY_NONE, 0},
+ { SW_PROP_NMID(UNO_NAME_TEXT_READING), WID_TEXT_READING, CPPU_E2T(CPPUTYPE_OUSTRING), PROPERTY_NONE, 0},
+ { SW_PROP_NMID(UNO_NAME_PRIMARY_KEY_READING), WID_PRIMARY_KEY_READING, CPPU_E2T(CPPUTYPE_OUSTRING), PROPERTY_NONE, 0},
+ { SW_PROP_NMID(UNO_NAME_SECONDARY_KEY_READING), WID_SECONDARY_KEY_READING, CPPU_E2T(CPPUTYPE_OUSTRING), PROPERTY_NONE, 0},
+ { SW_PROP_NMID(UNO_NAME_IS_MAIN_ENTRY), WID_MAIN_ENTRY, CPPU_E2T(CPPUTYPE_BOOLEAN) , PROPERTY_NONE, 0},
+ COMMON_TEXT_CONTENT_PROPERTIES
+ {0,0,0,0,0,0}
+ };
+ aMapEntriesArr[nPropertyId] = aIdxMarkMap_Impl;
+ }
+ break;
+ case PROPERTY_MAP_CNTIDX_MARK:
+ {
+ static SfxItemPropertyMapEntry aCntntMarkMap_Impl[] =
+ {
+ { SW_PROP_NMID(UNO_NAME_ALTERNATIVE_TEXT), WID_ALT_TEXT, CPPU_E2T(CPPUTYPE_OUSTRING) , PROPERTY_NONE, 0},
+ { SW_PROP_NMID(UNO_NAME_LEVEL), WID_LEVEL , CPPU_E2T(CPPUTYPE_INT16) , PROPERTY_NONE, 0},
+ COMMON_TEXT_CONTENT_PROPERTIES
+ {0,0,0,0,0,0}
+ };
+ aMapEntriesArr[nPropertyId] = aCntntMarkMap_Impl;
+ }
+ break;
+ case PROPERTY_MAP_USER_MARK:
+ {
+ static SfxItemPropertyMapEntry aUserMarkMap_Impl[] =
+ {
+ { SW_PROP_NMID(UNO_NAME_ALTERNATIVE_TEXT), WID_ALT_TEXT, CPPU_E2T(CPPUTYPE_OUSTRING) , PROPERTY_NONE, 0},
+ { SW_PROP_NMID(UNO_NAME_LEVEL ), WID_LEVEL , CPPU_E2T(CPPUTYPE_INT16) , PROPERTY_NONE, 0},
+ { SW_PROP_NMID(UNO_NAME_USER_INDEX_NAME), WID_USER_IDX_NAME, CPPU_E2T(CPPUTYPE_OUSTRING) , PROPERTY_NONE, 0},
+ COMMON_TEXT_CONTENT_PROPERTIES
+ {0,0,0,0,0,0}
+ };
+ aMapEntriesArr[nPropertyId] = aUserMarkMap_Impl;
+ }
+ break;
+ case PROPERTY_MAP_INDEX_IDX:
+ {
+ static SfxItemPropertyMapEntry aTOXIndexMap_Impl[] =
+ {
+ _BASE_INDEX_PROPERTIES_
+ { SW_PROP_NMID(UNO_NAME_CREATE_FROM_CHAPTER), WID_CREATE_FROM_CHAPTER , CPPU_E2T(CPPUTYPE_BOOLEAN) , PROPERTY_NONE, 0},
+ { SW_PROP_NMID(UNO_NAME_IS_PROTECTED), WID_PROTECTED , CPPU_E2T(CPPUTYPE_BOOLEAN) , PROPERTY_NONE, 0},
+ { SW_PROP_NMID(UNO_NAME_USE_ALPHABETICAL_SEPARATORS), WID_USE_ALPHABETICAL_SEPARATORS , CPPU_E2T(CPPUTYPE_BOOLEAN) , PROPERTY_NONE, 0},
+ { SW_PROP_NMID(UNO_NAME_USE_KEY_AS_ENTRY), WID_USE_KEY_AS_ENTRY , CPPU_E2T(CPPUTYPE_BOOLEAN) , PROPERTY_NONE, 0},
+ { SW_PROP_NMID(UNO_NAME_USE_COMBINED_ENTRIES), WID_USE_COMBINED_ENTRIES , CPPU_E2T(CPPUTYPE_BOOLEAN) , PROPERTY_NONE, 0},
+ { SW_PROP_NMID(UNO_NAME_IS_CASE_SENSITIVE), WID_IS_CASE_SENSITIVE , CPPU_E2T(CPPUTYPE_BOOLEAN) , PROPERTY_NONE, 0},
+ { SW_PROP_NMID(UNO_NAME_USE_P_P), WID_USE_P_P , CPPU_E2T(CPPUTYPE_BOOLEAN) , PROPERTY_NONE, 0},
+ { SW_PROP_NMID(UNO_NAME_USE_DASH), WID_USE_DASH , CPPU_E2T(CPPUTYPE_BOOLEAN) , PROPERTY_NONE, 0},
+ { SW_PROP_NMID(UNO_NAME_USE_UPPER_CASE), WID_USE_UPPER_CASE , CPPU_E2T(CPPUTYPE_BOOLEAN) , PROPERTY_NONE, 0},
+ { SW_PROP_NMID(UNO_NAME_LEVEL_FORMAT), WID_LEVEL_FORMAT , CPPU_E2T(CPPUTYPE_REFIDXREPL) , PROPERTY_NONE, 0},
+ { SW_PROP_NMID(UNO_NAME_MAIN_ENTRY_CHARACTER_STYLE_NAME), WID_MAIN_ENTRY_CHARACTER_STYLE_NAME , CPPU_E2T(CPPUTYPE_OUSTRING) , PROPERTY_NONE, 0},
+ { SW_PROP_NMID(UNO_NAME_TEXT_COLUMNS), RES_COL, CPPU_E2T(CPPUTYPE_REFTEXTCOL), PROPERTY_NONE, MID_COLUMNS},
+ { SW_PROP_NMID(UNO_NAME_BACK_GRAPHIC_URL), RES_BACKGROUND, CPPU_E2T(CPPUTYPE_OUSTRING), PROPERTY_NONE ,MID_GRAPHIC_URL },
+ { SW_PROP_NMID(UNO_NAME_BACK_GRAPHIC_FILTER), RES_BACKGROUND, CPPU_E2T(CPPUTYPE_OUSTRING), PROPERTY_NONE ,MID_GRAPHIC_FILTER },
+ { SW_PROP_NMID(UNO_NAME_BACK_GRAPHIC_LOCATION), RES_BACKGROUND, CPPU_E2T(CPPUTYPE_GRAPHICLOC), PROPERTY_NONE ,MID_GRAPHIC_POSITION},
+ { SW_PROP_NMID(UNO_NAME_BACK_COLOR), RES_BACKGROUND, CPPU_E2T(CPPUTYPE_INT32), PROPERTY_NONE ,MID_BACK_COLOR },
+ { SW_PROP_NMID(UNO_NAME_BACK_TRANSPARENT), RES_BACKGROUND, CPPU_E2T(CPPUTYPE_BOOLEAN), PROPERTY_NONE ,MID_GRAPHIC_TRANSPARENT },
+ { SW_PROP_NMID(UNO_NAME_PARA_STYLEHEADING), WID_PARA_HEAD, CPPU_E2T(CPPUTYPE_OUSTRING) , 0, 0},
+ { SW_PROP_NMID(UNO_NAME_PARA_STYLESEPARATOR), WID_PARA_SEP, CPPU_E2T(CPPUTYPE_OUSTRING) , 0, 0},
+ { SW_PROP_NMID(UNO_NAME_PARA_STYLELEVEL1), WID_PARA_LEV1, CPPU_E2T(CPPUTYPE_OUSTRING) , 0, 0},
+ { SW_PROP_NMID(UNO_NAME_PARA_STYLELEVEL2), WID_PARA_LEV2, CPPU_E2T(CPPUTYPE_OUSTRING) , 0, 0},
+ { SW_PROP_NMID(UNO_NAME_PARA_STYLELEVEL3), WID_PARA_LEV3, CPPU_E2T(CPPUTYPE_OUSTRING) , 0, 0},
+ { SW_PROP_NMID(UNO_NAME_IS_COMMA_SEPARATED), WID_IS_COMMA_SEPARATED, CPPU_E2T(CPPUTYPE_BOOLEAN), PROPERTY_NONE ,0 },
+ { SW_PROP_NMID(UNO_NAME_DOCUMENT_INDEX_MARKS), WID_INDEX_MARKS, CPPU_E2T(CPPUTYPE_DOCIDXMRK), PropertyAttribute::READONLY ,0 },
+ { SW_PROP_NMID(UNO_NAME_IS_RELATIVE_TABSTOPS), WID_IS_RELATIVE_TABSTOPS, CPPU_E2T(CPPUTYPE_BOOLEAN), PROPERTY_NONE, 0},
+ { SW_PROP_NMID(UNO_NAME_LOCALE), WID_IDX_LOCALE, CPPU_E2T(CPPUTYPE_LOCALE), PROPERTY_NONE, 0},\
+ { SW_PROP_NMID(UNO_NAME_SORT_ALGORITHM), WID_IDX_SORT_ALGORITHM, CPPU_E2T(CPPUTYPE_OUSTRING), PROPERTY_NONE, 0},\
+ {0,0,0,0,0,0}
+ };
+ aMapEntriesArr[nPropertyId] = aTOXIndexMap_Impl;
+ }
+ break;
+ case PROPERTY_MAP_INDEX_CNTNT:
+ {
+ static SfxItemPropertyMapEntry aTOXContentMap_Impl[] =
+ {
+ _BASE_INDEX_PROPERTIES_
+ { SW_PROP_NMID(UNO_NAME_LEVEL), WID_LEVEL , CPPU_E2T(CPPUTYPE_INT16) , PROPERTY_NONE, 0},
+ { SW_PROP_NMID(UNO_NAME_CREATE_FROM_MARKS), WID_CREATE_FROM_MARKS , CPPU_E2T(CPPUTYPE_BOOLEAN) , PROPERTY_NONE, 0},
+ { SW_PROP_NMID(UNO_NAME_CREATE_FROM_OUTLINE), WID_CREATE_FROM_OUTLINE , CPPU_E2T(CPPUTYPE_BOOLEAN) , PROPERTY_NONE, 0},
+ { SW_PROP_NMID(UNO_NAME_CREATE_FROM_CHAPTER), WID_CREATE_FROM_CHAPTER , CPPU_E2T(CPPUTYPE_BOOLEAN) , PROPERTY_NONE, 0},
+ { SW_PROP_NMID(UNO_NAME_IS_PROTECTED), WID_PROTECTED , CPPU_E2T(CPPUTYPE_BOOLEAN) , PROPERTY_NONE, 0},
+ { SW_PROP_NMID(UNO_NAME_LEVEL_FORMAT), WID_LEVEL_FORMAT , CPPU_E2T(CPPUTYPE_REFIDXREPL) , PROPERTY_NONE, 0},
+ { SW_PROP_NMID(UNO_NAME_LEVEL_PARAGRAPH_STYLES), WID_LEVEL_PARAGRAPH_STYLES , CPPU_E2T(CPPUTYPE_REFIDXREPL) , PropertyAttribute::READONLY, 0},
+ { SW_PROP_NMID(UNO_NAME_CREATE_FROM_LEVEL_PARAGRAPH_STYLES), WID_CREATE_FROM_PARAGRAPH_STYLES, CPPU_E2T(CPPUTYPE_BOOLEAN), PROPERTY_NONE, 0},
+ { SW_PROP_NMID(UNO_NAME_TEXT_COLUMNS), RES_COL, CPPU_E2T(CPPUTYPE_REFTEXTCOL), PROPERTY_NONE, MID_COLUMNS},
+ { SW_PROP_NMID(UNO_NAME_BACK_GRAPHIC_URL), RES_BACKGROUND, CPPU_E2T(CPPUTYPE_OUSTRING), PROPERTY_NONE ,MID_GRAPHIC_URL },
+ { SW_PROP_NMID(UNO_NAME_BACK_GRAPHIC_FILTER), RES_BACKGROUND, CPPU_E2T(CPPUTYPE_OUSTRING), PROPERTY_NONE ,MID_GRAPHIC_FILTER },
+ { SW_PROP_NMID(UNO_NAME_BACK_GRAPHIC_LOCATION), RES_BACKGROUND, CPPU_E2T(CPPUTYPE_GRAPHICLOC), PROPERTY_NONE ,MID_GRAPHIC_POSITION},
+ { SW_PROP_NMID(UNO_NAME_BACK_COLOR), RES_BACKGROUND, CPPU_E2T(CPPUTYPE_INT32), PROPERTY_NONE ,MID_BACK_COLOR },
+ { SW_PROP_NMID(UNO_NAME_BACK_TRANSPARENT), RES_BACKGROUND, CPPU_E2T(CPPUTYPE_BOOLEAN), PROPERTY_NONE ,MID_GRAPHIC_TRANSPARENT },
+ { SW_PROP_NMID(UNO_NAME_PARA_STYLEHEADING), WID_PARA_HEAD, CPPU_E2T(CPPUTYPE_OUSTRING) , 0, 0},
+ { SW_PROP_NMID(UNO_NAME_PARA_STYLELEVEL1), WID_PARA_LEV1, CPPU_E2T(CPPUTYPE_OUSTRING) , 0, 0},
+ { SW_PROP_NMID(UNO_NAME_PARA_STYLELEVEL2), WID_PARA_LEV2, CPPU_E2T(CPPUTYPE_OUSTRING) , 0, 0},
+ { SW_PROP_NMID(UNO_NAME_PARA_STYLELEVEL3), WID_PARA_LEV3, CPPU_E2T(CPPUTYPE_OUSTRING) , 0, 0},
+ { SW_PROP_NMID(UNO_NAME_PARA_STYLELEVEL4), WID_PARA_LEV4, CPPU_E2T(CPPUTYPE_OUSTRING) , 0, 0},
+ { SW_PROP_NMID(UNO_NAME_PARA_STYLELEVEL5), WID_PARA_LEV5, CPPU_E2T(CPPUTYPE_OUSTRING) , 0, 0},
+ { SW_PROP_NMID(UNO_NAME_PARA_STYLELEVEL6), WID_PARA_LEV6, CPPU_E2T(CPPUTYPE_OUSTRING) , 0, 0},
+ { SW_PROP_NMID(UNO_NAME_PARA_STYLELEVEL7), WID_PARA_LEV7, CPPU_E2T(CPPUTYPE_OUSTRING) , 0, 0},
+ { SW_PROP_NMID(UNO_NAME_PARA_STYLELEVEL8), WID_PARA_LEV8, CPPU_E2T(CPPUTYPE_OUSTRING) , 0, 0},
+ { SW_PROP_NMID(UNO_NAME_PARA_STYLELEVEL9), WID_PARA_LEV9, CPPU_E2T(CPPUTYPE_OUSTRING) , 0, 0},
+ { SW_PROP_NMID(UNO_NAME_PARA_STYLELEVEL10), WID_PARA_LEV10, CPPU_E2T(CPPUTYPE_OUSTRING) , 0, 0},
+ { SW_PROP_NMID(UNO_NAME_IS_RELATIVE_TABSTOPS), WID_IS_RELATIVE_TABSTOPS, CPPU_E2T(CPPUTYPE_BOOLEAN), PROPERTY_NONE, 0},
+ { SW_PROP_NMID(UNO_NAME_DOCUMENT_INDEX_MARKS), WID_INDEX_MARKS, CPPU_E2T(CPPUTYPE_DOCIDXMRK), PropertyAttribute::READONLY ,0 },
+ {0,0,0,0,0,0}
+ };
+ aMapEntriesArr[nPropertyId] = aTOXContentMap_Impl;
+ }
+ break;
+ case PROPERTY_MAP_INDEX_USER:
+ {
+ static SfxItemPropertyMapEntry aTOXUserMap_Impl[] =
+ {
+ _BASE_INDEX_PROPERTIES_
+ { SW_PROP_NMID(UNO_NAME_CREATE_FROM_MARKS), WID_CREATE_FROM_MARKS , CPPU_E2T(CPPUTYPE_BOOLEAN) , PROPERTY_NONE, 0},
+ { SW_PROP_NMID(UNO_NAME_CREATE_FROM_CHAPTER), WID_CREATE_FROM_CHAPTER , CPPU_E2T(CPPUTYPE_BOOLEAN) , PROPERTY_NONE, 0},
+ { SW_PROP_NMID(UNO_NAME_IS_PROTECTED), WID_PROTECTED , CPPU_E2T(CPPUTYPE_BOOLEAN) , PROPERTY_NONE, 0},
+ { SW_PROP_NMID(UNO_NAME_USE_LEVEL_FROM_SOURCE), WID_USE_LEVEL_FROM_SOURCE , CPPU_E2T(CPPUTYPE_BOOLEAN) , PROPERTY_NONE, 0},
+ { SW_PROP_NMID(UNO_NAME_LEVEL_FORMAT), WID_LEVEL_FORMAT , CPPU_E2T(CPPUTYPE_REFIDXREPL) , PROPERTY_NONE,0},
+ { SW_PROP_NMID(UNO_NAME_LEVEL_PARAGRAPH_STYLES), WID_LEVEL_PARAGRAPH_STYLES , CPPU_E2T(CPPUTYPE_REFIDXREPL) , PropertyAttribute::READONLY,0},
+ { SW_PROP_NMID(UNO_NAME_CREATE_FROM_LEVEL_PARAGRAPH_STYLES), WID_CREATE_FROM_PARAGRAPH_STYLES, CPPU_E2T(CPPUTYPE_BOOLEAN), PROPERTY_NONE, 0},
+ { SW_PROP_NMID(UNO_NAME_CREATE_FROM_TABLES), WID_CREATE_FROM_TABLES , CPPU_E2T(CPPUTYPE_BOOLEAN) , PROPERTY_NONE, 0},
+ { SW_PROP_NMID(UNO_NAME_CREATE_FROM_TEXT_FRAMES), WID_CREATE_FROM_TEXT_FRAMES , CPPU_E2T(CPPUTYPE_BOOLEAN) , PROPERTY_NONE, 0},
+ { SW_PROP_NMID(UNO_NAME_CREATE_FROM_GRAPHIC_OBJECTS), WID_CREATE_FROM_GRAPHIC_OBJECTS , CPPU_E2T(CPPUTYPE_BOOLEAN) , PROPERTY_NONE, 0},
+ { SW_PROP_NMID(UNO_NAME_CREATE_FROM_EMBEDDED_OBJECTS), WID_CREATE_FROM_EMBEDDED_OBJECTS , CPPU_E2T(CPPUTYPE_BOOLEAN) , PROPERTY_NONE, 0},
+ { SW_PROP_NMID(UNO_NAME_TEXT_COLUMNS), RES_COL, CPPU_E2T(CPPUTYPE_REFTEXTCOL), PROPERTY_NONE, MID_COLUMNS},
+ { SW_PROP_NMID(UNO_NAME_BACK_GRAPHIC_URL), RES_BACKGROUND, CPPU_E2T(CPPUTYPE_OUSTRING), PROPERTY_NONE ,MID_GRAPHIC_URL },
+ { SW_PROP_NMID(UNO_NAME_BACK_GRAPHIC_FILTER), RES_BACKGROUND, CPPU_E2T(CPPUTYPE_OUSTRING), PROPERTY_NONE ,MID_GRAPHIC_FILTER },
+ { SW_PROP_NMID(UNO_NAME_BACK_GRAPHIC_LOCATION), RES_BACKGROUND, CPPU_E2T(CPPUTYPE_GRAPHICLOC), PROPERTY_NONE ,MID_GRAPHIC_POSITION},
+ { SW_PROP_NMID(UNO_NAME_BACK_COLOR), RES_BACKGROUND, CPPU_E2T(CPPUTYPE_INT32), PROPERTY_NONE ,MID_BACK_COLOR },
+ { SW_PROP_NMID(UNO_NAME_BACK_TRANSPARENT), RES_BACKGROUND, CPPU_E2T(CPPUTYPE_BOOLEAN), PROPERTY_NONE ,MID_GRAPHIC_TRANSPARENT },
+ { SW_PROP_NMID(UNO_NAME_PARA_STYLEHEADING), WID_PARA_HEAD, CPPU_E2T(CPPUTYPE_OUSTRING) , 0, 0},
+ { SW_PROP_NMID(UNO_NAME_PARA_STYLELEVEL1), WID_PARA_LEV1, CPPU_E2T(CPPUTYPE_OUSTRING) , 0, 0},
+ { SW_PROP_NMID(UNO_NAME_PARA_STYLELEVEL2), WID_PARA_LEV2, CPPU_E2T(CPPUTYPE_OUSTRING) , 0, 0},
+ { SW_PROP_NMID(UNO_NAME_PARA_STYLELEVEL3), WID_PARA_LEV3, CPPU_E2T(CPPUTYPE_OUSTRING) , 0, 0},
+ { SW_PROP_NMID(UNO_NAME_PARA_STYLELEVEL4), WID_PARA_LEV4, CPPU_E2T(CPPUTYPE_OUSTRING) , 0, 0},
+ { SW_PROP_NMID(UNO_NAME_PARA_STYLELEVEL5), WID_PARA_LEV5, CPPU_E2T(CPPUTYPE_OUSTRING) , 0, 0},
+ { SW_PROP_NMID(UNO_NAME_PARA_STYLELEVEL6), WID_PARA_LEV6, CPPU_E2T(CPPUTYPE_OUSTRING) , 0, 0},
+ { SW_PROP_NMID(UNO_NAME_PARA_STYLELEVEL7), WID_PARA_LEV7, CPPU_E2T(CPPUTYPE_OUSTRING) , 0, 0},
+ { SW_PROP_NMID(UNO_NAME_PARA_STYLELEVEL8), WID_PARA_LEV8, CPPU_E2T(CPPUTYPE_OUSTRING) , 0, 0},
+ { SW_PROP_NMID(UNO_NAME_PARA_STYLELEVEL9), WID_PARA_LEV9, CPPU_E2T(CPPUTYPE_OUSTRING) , 0, 0},
+ { SW_PROP_NMID(UNO_NAME_PARA_STYLELEVEL10), WID_PARA_LEV10, CPPU_E2T(CPPUTYPE_OUSTRING) , 0, 0},
+ { SW_PROP_NMID(UNO_NAME_DOCUMENT_INDEX_MARKS), WID_INDEX_MARKS, CPPU_E2T(CPPUTYPE_DOCIDXMRK), PropertyAttribute::READONLY ,0 },
+ { SW_PROP_NMID(UNO_NAME_IS_RELATIVE_TABSTOPS), WID_IS_RELATIVE_TABSTOPS, CPPU_E2T(CPPUTYPE_BOOLEAN), PROPERTY_NONE, 0},
+ { SW_PROP_NMID(UNO_NAME_USER_INDEX_NAME), WID_USER_IDX_NAME, CPPU_E2T(CPPUTYPE_OUSTRING) , PROPERTY_NONE, 0},
+ {0,0,0,0,0,0}
+ };
+ aMapEntriesArr[nPropertyId] = aTOXUserMap_Impl;
+ }
+ break;
+ case PROPERTY_MAP_INDEX_TABLES:
+ {
+ static SfxItemPropertyMapEntry aTOXTablesMap_Impl[] =
+ {
+ _BASE_INDEX_PROPERTIES_
+ { SW_PROP_NMID(UNO_NAME_CREATE_FROM_CHAPTER), WID_CREATE_FROM_CHAPTER , CPPU_E2T(CPPUTYPE_BOOLEAN) , PROPERTY_NONE, 0},
+ { SW_PROP_NMID(UNO_NAME_CREATE_FROM_LABELS), WID_CREATE_FROM_LABELS , CPPU_E2T(CPPUTYPE_BOOLEAN) , PROPERTY_NONE, 0},
+ { SW_PROP_NMID(UNO_NAME_IS_PROTECTED), WID_PROTECTED , CPPU_E2T(CPPUTYPE_BOOLEAN) , PROPERTY_NONE, 0},
+ { SW_PROP_NMID(UNO_NAME_LABEL_CATEGORY), WID_LABEL_CATEGORY , CPPU_E2T(CPPUTYPE_OUSTRING) , PROPERTY_NONE, 0},
+ { SW_PROP_NMID(UNO_NAME_LABEL_DISPLAY_TYPE), WID_LABEL_DISPLAY_TYPE , CPPU_E2T(CPPUTYPE_INT16) , PROPERTY_NONE, 0},
+ { SW_PROP_NMID(UNO_NAME_LEVEL_FORMAT), WID_LEVEL_FORMAT , CPPU_E2T(CPPUTYPE_REFIDXREPL) , PROPERTY_NONE,0},
+ { SW_PROP_NMID(UNO_NAME_TEXT_COLUMNS), RES_COL, CPPU_E2T(CPPUTYPE_REFTEXTCOL), PROPERTY_NONE, MID_COLUMNS},
+ { SW_PROP_NMID(UNO_NAME_BACK_GRAPHIC_URL), RES_BACKGROUND, CPPU_E2T(CPPUTYPE_OUSTRING), PROPERTY_NONE ,MID_GRAPHIC_URL },
+ { SW_PROP_NMID(UNO_NAME_BACK_GRAPHIC_FILTER), RES_BACKGROUND, CPPU_E2T(CPPUTYPE_OUSTRING), PROPERTY_NONE ,MID_GRAPHIC_FILTER },
+ { SW_PROP_NMID(UNO_NAME_BACK_GRAPHIC_LOCATION), RES_BACKGROUND, CPPU_E2T(CPPUTYPE_GRAPHICLOC), PROPERTY_NONE ,MID_GRAPHIC_POSITION},
+ { SW_PROP_NMID(UNO_NAME_BACK_COLOR), RES_BACKGROUND, CPPU_E2T(CPPUTYPE_INT32), PROPERTY_NONE ,MID_BACK_COLOR },
+ { SW_PROP_NMID(UNO_NAME_BACK_TRANSPARENT), RES_BACKGROUND, CPPU_E2T(CPPUTYPE_BOOLEAN), PROPERTY_NONE ,MID_GRAPHIC_TRANSPARENT },
+ { SW_PROP_NMID(UNO_NAME_PARA_STYLEHEADING), WID_PARA_HEAD, CPPU_E2T(CPPUTYPE_OUSTRING) , 0, 0},
+ { SW_PROP_NMID(UNO_NAME_PARA_STYLELEVEL1), WID_PARA_LEV1, CPPU_E2T(CPPUTYPE_OUSTRING) , 0, 0},
+ { SW_PROP_NMID(UNO_NAME_IS_RELATIVE_TABSTOPS), WID_IS_RELATIVE_TABSTOPS, CPPU_E2T(CPPUTYPE_BOOLEAN), PROPERTY_NONE, 0},
+ {0,0,0,0,0,0}
+ };
+ aMapEntriesArr[nPropertyId] = aTOXTablesMap_Impl;
+ }
+ break;
+ case PROPERTY_MAP_INDEX_OBJECTS:
+ {
+ static SfxItemPropertyMapEntry aTOXObjectsMap_Impl[] =
+ {
+ _BASE_INDEX_PROPERTIES_
+ { SW_PROP_NMID(UNO_NAME_CREATE_FROM_CHAPTER), WID_CREATE_FROM_CHAPTER , CPPU_E2T(CPPUTYPE_BOOLEAN) , PROPERTY_NONE, 0},
+ { SW_PROP_NMID(UNO_NAME_IS_PROTECTED), WID_PROTECTED , CPPU_E2T(CPPUTYPE_BOOLEAN) , PROPERTY_NONE, 0},
+ { SW_PROP_NMID(UNO_NAME_USE_ALPHABETICAL_SEPARATORS), WID_USE_ALPHABETICAL_SEPARATORS , CPPU_E2T(CPPUTYPE_BOOLEAN) , PROPERTY_NONE, 0},
+ { SW_PROP_NMID(UNO_NAME_LEVEL_FORMAT), WID_LEVEL_FORMAT , CPPU_E2T(CPPUTYPE_REFIDXREPL) , PROPERTY_NONE,0},
+ { SW_PROP_NMID(UNO_NAME_CREATE_FROM_STAR_MATH), WID_CREATE_FROM_STAR_MATH , CPPU_E2T(CPPUTYPE_BOOLEAN) , PROPERTY_NONE, 0},
+ { SW_PROP_NMID(UNO_NAME_CREATE_FROM_STAR_CHART), WID_CREATE_FROM_STAR_CHART , CPPU_E2T(CPPUTYPE_BOOLEAN) , PROPERTY_NONE, 0},
+ { SW_PROP_NMID(UNO_NAME_CREATE_FROM_STAR_CALC), WID_CREATE_FROM_STAR_CALC , CPPU_E2T(CPPUTYPE_BOOLEAN) , PROPERTY_NONE, 0},
+ { SW_PROP_NMID(UNO_NAME_CREATE_FROM_STAR_DRAW), WID_CREATE_FROM_STAR_DRAW , CPPU_E2T(CPPUTYPE_BOOLEAN) , PROPERTY_NONE, 0},
+ { SW_PROP_NMID(UNO_NAME_CREATE_FROM_OTHER_EMBEDDED_OBJECTS), WID_CREATE_FROM_OTHER_EMBEDDED_OBJECTS , CPPU_E2T(CPPUTYPE_BOOLEAN) , PROPERTY_NONE, 0},
+ { SW_PROP_NMID(UNO_NAME_TEXT_COLUMNS), RES_COL, CPPU_E2T(CPPUTYPE_REFTEXTCOL), PROPERTY_NONE, MID_COLUMNS},
+ { SW_PROP_NMID(UNO_NAME_BACK_GRAPHIC_URL), RES_BACKGROUND, CPPU_E2T(CPPUTYPE_OUSTRING), PROPERTY_NONE ,MID_GRAPHIC_URL },
+ { SW_PROP_NMID(UNO_NAME_BACK_GRAPHIC_FILTER), RES_BACKGROUND, CPPU_E2T(CPPUTYPE_OUSTRING), PROPERTY_NONE ,MID_GRAPHIC_FILTER },
+ { SW_PROP_NMID(UNO_NAME_BACK_GRAPHIC_LOCATION), RES_BACKGROUND, CPPU_E2T(CPPUTYPE_GRAPHICLOC), PROPERTY_NONE ,MID_GRAPHIC_POSITION},
+ { SW_PROP_NMID(UNO_NAME_BACK_COLOR), RES_BACKGROUND, CPPU_E2T(CPPUTYPE_INT32), PROPERTY_NONE ,MID_BACK_COLOR },
+ { SW_PROP_NMID(UNO_NAME_BACK_TRANSPARENT), RES_BACKGROUND, CPPU_E2T(CPPUTYPE_BOOLEAN), PROPERTY_NONE ,MID_GRAPHIC_TRANSPARENT },
+ { SW_PROP_NMID(UNO_NAME_PARA_STYLEHEADING), WID_PARA_HEAD, CPPU_E2T(CPPUTYPE_OUSTRING) , 0, 0},
+ { SW_PROP_NMID(UNO_NAME_PARA_STYLELEVEL1), WID_PARA_LEV1, CPPU_E2T(CPPUTYPE_OUSTRING) , 0, 0},
+ { SW_PROP_NMID(UNO_NAME_IS_RELATIVE_TABSTOPS), WID_IS_RELATIVE_TABSTOPS, CPPU_E2T(CPPUTYPE_BOOLEAN), PROPERTY_NONE, 0},
+ {0,0,0,0,0,0}
+ };
+ aMapEntriesArr[nPropertyId] = aTOXObjectsMap_Impl;
+ }
+ break;
+ case PROPERTY_MAP_INDEX_ILLUSTRATIONS:
+ {
+ static SfxItemPropertyMapEntry aTOXIllustrationsMap_Impl[] =
+ {
+ _BASE_INDEX_PROPERTIES_
+ { SW_PROP_NMID(UNO_NAME_CREATE_FROM_CHAPTER), WID_CREATE_FROM_CHAPTER , CPPU_E2T(CPPUTYPE_BOOLEAN) , PROPERTY_NONE, 0},
+ { SW_PROP_NMID(UNO_NAME_CREATE_FROM_LABELS), WID_CREATE_FROM_LABELS , CPPU_E2T(CPPUTYPE_BOOLEAN) , PROPERTY_NONE, 0},
+ { SW_PROP_NMID(UNO_NAME_IS_PROTECTED), WID_PROTECTED , CPPU_E2T(CPPUTYPE_BOOLEAN) , PROPERTY_NONE, 0},
+ { SW_PROP_NMID(UNO_NAME_USE_ALPHABETICAL_SEPARATORS), WID_USE_ALPHABETICAL_SEPARATORS , CPPU_E2T(CPPUTYPE_BOOLEAN) , PROPERTY_NONE, 0},
+ { SW_PROP_NMID(UNO_NAME_LABEL_CATEGORY), WID_LABEL_CATEGORY , CPPU_E2T(CPPUTYPE_OUSTRING) , PROPERTY_NONE, 0},
+ { SW_PROP_NMID(UNO_NAME_LABEL_DISPLAY_TYPE), WID_LABEL_DISPLAY_TYPE , CPPU_E2T(CPPUTYPE_INT16) , PROPERTY_NONE, 0},
+ { SW_PROP_NMID(UNO_NAME_LEVEL_FORMAT), WID_LEVEL_FORMAT , CPPU_E2T(CPPUTYPE_REFIDXREPL) , PROPERTY_NONE,0},
+ { SW_PROP_NMID(UNO_NAME_TEXT_COLUMNS), RES_COL, CPPU_E2T(CPPUTYPE_REFTEXTCOL), PROPERTY_NONE, MID_COLUMNS},
+ { SW_PROP_NMID(UNO_NAME_BACK_GRAPHIC_URL), RES_BACKGROUND, CPPU_E2T(CPPUTYPE_OUSTRING), PROPERTY_NONE ,MID_GRAPHIC_URL },
+ { SW_PROP_NMID(UNO_NAME_BACK_GRAPHIC_FILTER), RES_BACKGROUND, CPPU_E2T(CPPUTYPE_OUSTRING), PROPERTY_NONE ,MID_GRAPHIC_FILTER },
+ { SW_PROP_NMID(UNO_NAME_BACK_GRAPHIC_LOCATION), RES_BACKGROUND, CPPU_E2T(CPPUTYPE_GRAPHICLOC), PROPERTY_NONE ,MID_GRAPHIC_POSITION},
+ { SW_PROP_NMID(UNO_NAME_BACK_COLOR), RES_BACKGROUND, CPPU_E2T(CPPUTYPE_INT32), PROPERTY_NONE ,MID_BACK_COLOR },
+ { SW_PROP_NMID(UNO_NAME_BACK_TRANSPARENT), RES_BACKGROUND, CPPU_E2T(CPPUTYPE_BOOLEAN), PROPERTY_NONE ,MID_GRAPHIC_TRANSPARENT },
+ { SW_PROP_NMID(UNO_NAME_PARA_STYLEHEADING), WID_PARA_HEAD, CPPU_E2T(CPPUTYPE_OUSTRING) , 0, 0},
+ { SW_PROP_NMID(UNO_NAME_PARA_STYLELEVEL1), WID_PARA_LEV1, CPPU_E2T(CPPUTYPE_OUSTRING) , 0, 0},
+ { SW_PROP_NMID(UNO_NAME_IS_RELATIVE_TABSTOPS), WID_IS_RELATIVE_TABSTOPS, CPPU_E2T(CPPUTYPE_BOOLEAN), PROPERTY_NONE, 0},
+ {0,0,0,0,0,0}
+ };
+ aMapEntriesArr[nPropertyId] = aTOXIllustrationsMap_Impl;
+ }
+ break;
+ case PROPERTY_MAP_TEXT_TABLE_ROW:
+ {
+ static SfxItemPropertyMapEntry aTableRowPropertyMap_Impl[] =
+ {
+ { SW_PROP_NMID(UNO_NAME_BACK_COLOR), RES_BACKGROUND, CPPU_E2T(CPPUTYPE_INT32), PROPERTY_NONE ,MID_BACK_COLOR },
+ { SW_PROP_NMID(UNO_NAME_BACK_GRAPHIC_URL), RES_BACKGROUND, CPPU_E2T(CPPUTYPE_OUSTRING), PROPERTY_NONE ,MID_GRAPHIC_URL },
+ { SW_PROP_NMID(UNO_NAME_BACK_GRAPHIC_FILTER), RES_BACKGROUND, CPPU_E2T(CPPUTYPE_OUSTRING), PROPERTY_NONE ,MID_GRAPHIC_FILTER },
+ { SW_PROP_NMID(UNO_NAME_BACK_GRAPHIC_LOCATION), RES_BACKGROUND, CPPU_E2T(CPPUTYPE_GRAPHICLOC), PROPERTY_NONE ,MID_GRAPHIC_POSITION},
+ { SW_PROP_NMID(UNO_NAME_BACK_TRANSPARENT), RES_BACKGROUND, CPPU_E2T(CPPUTYPE_BOOLEAN), PROPERTY_NONE ,MID_GRAPHIC_TRANSPARENT },
+ { SW_PROP_NMID(UNO_NAME_TABLE_COLUMN_SEPARATORS), FN_UNO_TABLE_COLUMN_SEPARATORS, CPPU_E2T(CPPUTYPE_TBLCOLSEP), PropertyAttribute::MAYBEVOID, 0 },
+ { SW_PROP_NMID(UNO_NAME_HEIGHT), FN_UNO_ROW_HEIGHT, CPPU_E2T(CPPUTYPE_INT32), PROPERTY_NONE ,CONVERT_TWIPS },
+ { SW_PROP_NMID(UNO_NAME_IS_AUTO_HEIGHT), FN_UNO_ROW_AUTO_HEIGHT, CPPU_E2T(CPPUTYPE_BOOLEAN), PROPERTY_NONE , 0 },
+ { SW_PROP_NMID(UNO_NAME_SIZE_TYPE), RES_FRM_SIZE, CPPU_E2T(CPPUTYPE_INT16) , PROPERTY_NONE, MID_FRMSIZE_SIZE_TYPE },
+ { SW_PROP_NMID(UNO_NAME_WIDTH_TYPE), RES_FRM_SIZE, CPPU_E2T(CPPUTYPE_INT16) , PROPERTY_NONE, MID_FRMSIZE_WIDTH_TYPE },
+ { SW_PROP_NMID(UNO_NAME_IS_SPLIT_ALLOWED), RES_ROW_SPLIT, CPPU_E2T(CPPUTYPE_BOOLEAN) , PropertyAttribute::MAYBEVOID, 0},
+ {0,0,0,0,0,0}
+ };
+
+ aMapEntriesArr[nPropertyId] = (SfxItemPropertyMapEntry*)aTableRowPropertyMap_Impl;
+ }
+ break;
+ case PROPERTY_MAP_TEXT_TABLE_CURSOR:
+ {
+ // das PropertySet entspricht dem Range ohne Chart-Properties
+ static SfxItemPropertyMapEntry aTableCursorPropertyMap_Impl [] =
+ {
+ COMMON_CRSR_PARA_PROPERTIES_WITHOUT_FN_01
+ TABSTOPS_MAP_ENTRY
+
+ // attributes from PROPERTY_MAP_TABLE_CELL:
+ { SW_PROP_NMID(UNO_NAME_BACK_COLOR), RES_BACKGROUND, CPPU_E2T(CPPUTYPE_INT32), PROPERTY_NONE , MID_BACK_COLOR },
+ { SW_PROP_NMID(UNO_NAME_BACK_GRAPHIC_URL), RES_BACKGROUND, CPPU_E2T(CPPUTYPE_OUSTRING), PROPERTY_NONE ,MID_GRAPHIC_URL },
+ { SW_PROP_NMID(UNO_NAME_BACK_GRAPHIC_FILTER), RES_BACKGROUND, CPPU_E2T(CPPUTYPE_OUSTRING), PROPERTY_NONE ,MID_GRAPHIC_FILTER },
+ { SW_PROP_NMID(UNO_NAME_BACK_GRAPHIC_LOCATION), RES_BACKGROUND, CPPU_E2T(CPPUTYPE_GRAPHICLOC), PROPERTY_NONE ,MID_GRAPHIC_POSITION},
+ { SW_PROP_NMID(UNO_NAME_NUMBER_FORMAT), RES_BOXATR_FORMAT, CPPU_E2T(CPPUTYPE_INT32), PropertyAttribute::MAYBEVOID ,0 },
+ { SW_PROP_NMID(UNO_NAME_BACK_TRANSPARENT), RES_BACKGROUND, CPPU_E2T(CPPUTYPE_BOOLEAN), PROPERTY_NONE , MID_GRAPHIC_TRANSPARENT },
+ { SW_PROP_NMID(UNO_NAME_USER_DEFINED_ATTRIBUTES), RES_UNKNOWNATR_CONTAINER, CPPU_E2T(CPPUTYPE_REFNAMECNT), PropertyAttribute::MAYBEVOID, 0 },
+ { SW_PROP_NMID(UNO_NAME_TEXT_SECTION), FN_UNO_TEXT_SECTION, CPPU_E2T(CPPUTYPE_REFTEXTSECTION), PropertyAttribute::MAYBEVOID|PropertyAttribute::READONLY ,0 },
+ { SW_PROP_NMID(UNO_NAME_IS_PROTECTED), RES_PROTECT, CPPU_E2T(CPPUTYPE_BOOLEAN), 0, MID_PROTECT_CONTENT},
+ { SW_PROP_NMID(UNO_NAME_VERT_ORIENT), RES_VERT_ORIENT, CPPU_E2T(CPPUTYPE_INT16), PROPERTY_NONE ,MID_VERTORIENT_ORIENT },
+ {0,0,0,0,0,0}
+ };
+ aMapEntriesArr[nPropertyId] = aTableCursorPropertyMap_Impl;
+ }
+ break;
+ case PROPERTY_MAP_BOOKMARK:
+ {
+ static SfxItemPropertyMapEntry aBookmarkPropertyMap_Impl [] =
+ {
+ { SW_PROP_NMID(UNO_LINK_DISPLAY_NAME), FN_PARAM_LINK_DISPLAY_NAME, CPPU_E2T(CPPUTYPE_OUSTRING), PropertyAttribute::READONLY, 0xff},
+ COMMON_TEXT_CONTENT_PROPERTIES
+ {0,0,0,0,0,0}
+ };
+ aMapEntriesArr[nPropertyId] = aBookmarkPropertyMap_Impl;
+ }
+ break;
+ case PROPERTY_MAP_PARAGRAPH_EXTENSIONS:
+ {
+ static SfxItemPropertyMapEntry aParagraphExtensionsMap_Impl[] =
+ {
+ COMMON_TEXT_CONTENT_PROPERTIES
+ {0,0,0,0,0,0}
+ };
+
+ aMapEntriesArr[nPropertyId] = aParagraphExtensionsMap_Impl;
+ }
+ break;
+ case PROPERTY_MAP_BIBLIOGRAPHY :
+ {
+ static SfxItemPropertyMapEntry aBibliographyMap_Impl[] =
+ {
+ _BASE_INDEX_PROPERTIES_
+ { SW_PROP_NMID(UNO_NAME_IS_PROTECTED), WID_PROTECTED , CPPU_E2T(CPPUTYPE_BOOLEAN) , PROPERTY_NONE, 0},
+ { SW_PROP_NMID(UNO_NAME_TEXT_COLUMNS), RES_COL, CPPU_E2T(CPPUTYPE_REFTEXTCOL), PROPERTY_NONE, MID_COLUMNS},
+ { SW_PROP_NMID(UNO_NAME_BACK_GRAPHIC_URL), RES_BACKGROUND, CPPU_E2T(CPPUTYPE_OUSTRING), PROPERTY_NONE ,MID_GRAPHIC_URL },
+ { SW_PROP_NMID(UNO_NAME_BACK_GRAPHIC_FILTER), RES_BACKGROUND, CPPU_E2T(CPPUTYPE_OUSTRING), PROPERTY_NONE ,MID_GRAPHIC_FILTER },
+ { SW_PROP_NMID(UNO_NAME_BACK_GRAPHIC_LOCATION), RES_BACKGROUND, CPPU_E2T(CPPUTYPE_GRAPHICLOC), PROPERTY_NONE ,MID_GRAPHIC_POSITION},
+ { SW_PROP_NMID(UNO_NAME_BACK_COLOR), RES_BACKGROUND, CPPU_E2T(CPPUTYPE_INT32), PROPERTY_NONE ,MID_BACK_COLOR },
+ { SW_PROP_NMID(UNO_NAME_BACK_TRANSPARENT), RES_BACKGROUND, CPPU_E2T(CPPUTYPE_BOOLEAN), PROPERTY_NONE ,MID_GRAPHIC_TRANSPARENT },
+ { SW_PROP_NMID(UNO_NAME_PARA_STYLEHEADING), WID_PARA_HEAD, CPPU_E2T(CPPUTYPE_OUSTRING) , 0, 0},
+ { SW_PROP_NMID(UNO_NAME_PARA_STYLELEVEL1), WID_PARA_LEV1, CPPU_E2T(CPPUTYPE_OUSTRING) , 0, 0},
+ { SW_PROP_NMID(UNO_NAME_LEVEL_FORMAT), WID_LEVEL_FORMAT , CPPU_E2T(CPPUTYPE_REFIDXREPL) , PROPERTY_NONE,0},
+ { SW_PROP_NMID(UNO_NAME_LOCALE), WID_IDX_LOCALE, CPPU_E2T(CPPUTYPE_LOCALE), PROPERTY_NONE, 0},\
+ { SW_PROP_NMID(UNO_NAME_SORT_ALGORITHM), WID_IDX_SORT_ALGORITHM, CPPU_E2T(CPPUTYPE_OUSTRING), PROPERTY_NONE, 0},\
+ {0,0,0,0,0,0}
+ };
+ aMapEntriesArr[nPropertyId] = aBibliographyMap_Impl;
+ }
+ break;
+ case PROPERTY_MAP_TEXT_DOCUMENT:
+ {
+ static SfxItemPropertyMapEntry aDocMap_Impl[] =
+ {
+ { SW_PROP_NMID(UNO_NAME_BASIC_LIBRARIES), WID_DOC_BASIC_LIBRARIES, CPPU_E2T(CPPUTYPE_REFLIBCONTAINER), PropertyAttribute::READONLY, 0},
+ { SW_PROP_NMID(UNO_NAME_CHAR_FONT_NAME), RES_CHRATR_FONT, CPPU_E2T(CPPUTYPE_OUSTRING), PropertyAttribute::MAYBEVOID, MID_FONT_FAMILY_NAME },
+ { SW_PROP_NMID(UNO_NAME_CHAR_FONT_STYLE_NAME), RES_CHRATR_FONT, CPPU_E2T(CPPUTYPE_OUSTRING), PropertyAttribute::MAYBEVOID, MID_FONT_STYLE_NAME },
+ { SW_PROP_NMID(UNO_NAME_CHAR_FONT_FAMILY), RES_CHRATR_FONT, CPPU_E2T(CPPUTYPE_INT16), PropertyAttribute::MAYBEVOID, MID_FONT_FAMILY },
+ { SW_PROP_NMID(UNO_NAME_CHAR_FONT_CHAR_SET), RES_CHRATR_FONT, CPPU_E2T(CPPUTYPE_INT16), PropertyAttribute::MAYBEVOID, MID_FONT_CHAR_SET },
+ { SW_PROP_NMID(UNO_NAME_CHAR_FONT_PITCH), RES_CHRATR_FONT, CPPU_E2T(CPPUTYPE_INT16), PropertyAttribute::MAYBEVOID, MID_FONT_PITCH },
+ { SW_PROP_NMID(UNO_NAME_CHAR_FONT_NAME_ASIAN), RES_CHRATR_CJK_FONT, CPPU_E2T(CPPUTYPE_OUSTRING), PropertyAttribute::MAYBEVOID, MID_FONT_FAMILY_NAME },
+ { SW_PROP_NMID(UNO_NAME_CHAR_FONT_STYLE_NAME_ASIAN), RES_CHRATR_CJK_FONT, CPPU_E2T(CPPUTYPE_OUSTRING), PropertyAttribute::MAYBEVOID, MID_FONT_STYLE_NAME },
+ { SW_PROP_NMID(UNO_NAME_CHAR_FONT_FAMILY_ASIAN), RES_CHRATR_CJK_FONT, CPPU_E2T(CPPUTYPE_INT16), PropertyAttribute::MAYBEVOID, MID_FONT_FAMILY },
+ { SW_PROP_NMID(UNO_NAME_CHAR_FONT_CHAR_SET_ASIAN), RES_CHRATR_CJK_FONT, CPPU_E2T(CPPUTYPE_INT16), PropertyAttribute::MAYBEVOID, MID_FONT_CHAR_SET },
+ { SW_PROP_NMID(UNO_NAME_CHAR_FONT_PITCH_ASIAN), RES_CHRATR_CJK_FONT, CPPU_E2T(CPPUTYPE_INT16), PropertyAttribute::MAYBEVOID, MID_FONT_PITCH },
+ { SW_PROP_NMID(UNO_NAME_CHAR_FONT_NAME_COMPLEX), RES_CHRATR_CTL_FONT, CPPU_E2T(CPPUTYPE_OUSTRING), PropertyAttribute::MAYBEVOID, MID_FONT_FAMILY_NAME },
+ { SW_PROP_NMID(UNO_NAME_CHAR_FONT_STYLE_NAME_COMPLEX), RES_CHRATR_CTL_FONT, CPPU_E2T(CPPUTYPE_OUSTRING), PropertyAttribute::MAYBEVOID, MID_FONT_STYLE_NAME },
+ { SW_PROP_NMID(UNO_NAME_CHAR_FONT_FAMILY_COMPLEX), RES_CHRATR_CTL_FONT, CPPU_E2T(CPPUTYPE_INT16), PropertyAttribute::MAYBEVOID, MID_FONT_FAMILY },
+ { SW_PROP_NMID(UNO_NAME_CHAR_FONT_CHAR_SET_COMPLEX), RES_CHRATR_CTL_FONT, CPPU_E2T(CPPUTYPE_INT16), PropertyAttribute::MAYBEVOID, MID_FONT_CHAR_SET },
+ { SW_PROP_NMID(UNO_NAME_CHAR_FONT_PITCH_COMPLEX), RES_CHRATR_CTL_FONT, CPPU_E2T(CPPUTYPE_INT16), PropertyAttribute::MAYBEVOID, MID_FONT_PITCH },
+ { SW_PROP_NMID(UNO_NAME_CHAR_LOCALE), RES_CHRATR_LANGUAGE , CPPU_E2T(CPPUTYPE_LOCALE), PropertyAttribute::MAYBEVOID, MID_LANG_LOCALE },
+ { SW_PROP_NMID(UNO_NAME_CHARACTER_COUNT), WID_DOC_CHAR_COUNT, CPPU_E2T(CPPUTYPE_INT32), PropertyAttribute::READONLY, 0},
+ { SW_PROP_NMID(UNO_NAME_DIALOG_LIBRARIES), WID_DOC_DIALOG_LIBRARIES, CPPU_E2T(CPPUTYPE_REFLIBCONTAINER), PropertyAttribute::READONLY, 0},
+ { SW_PROP_NMID(UNO_NAME_VBA_DOCOBJ), WID_DOC_VBA_DOCOBJ, CPPU_E2T(CPPUTYPE_PROPERTYVALUE), PropertyAttribute::READONLY, 0},
+ { SW_PROP_NMID(UNO_NAME_INDEX_AUTO_MARK_FILE_U_R_L), WID_DOC_AUTO_MARK_URL, CPPU_E2T(CPPUTYPE_OUSTRING), PROPERTY_NONE, 0},
+ { SW_PROP_NMID(UNO_NAME_PARAGRAPH_COUNT), WID_DOC_PARA_COUNT, CPPU_E2T(CPPUTYPE_INT32), PropertyAttribute::READONLY, 0},
+ { SW_PROP_NMID(UNO_NAME_RECORD_CHANGES), WID_DOC_CHANGES_RECORD, CPPU_E2T(CPPUTYPE_BOOLEAN), PROPERTY_NONE, 0},
+ { SW_PROP_NMID(UNO_NAME_SHOW_CHANGES), WID_DOC_CHANGES_SHOW, CPPU_E2T(CPPUTYPE_BOOLEAN), PROPERTY_NONE, 0},
+ { SW_PROP_NMID(UNO_NAME_WORD_COUNT), WID_DOC_WORD_COUNT, CPPU_E2T(CPPUTYPE_INT32), PropertyAttribute::READONLY, 0},
+ { SW_PROP_NMID(UNO_NAME_IS_TEMPLATE), WID_DOC_ISTEMPLATEID, CPPU_E2T(CPPUTYPE_BOOLEAN), PropertyAttribute::READONLY, 0},
+ { SW_PROP_NMID(UNO_NAME_WORD_SEPARATOR), WID_DOC_WORD_SEPARATOR, CPPU_E2T(CPPUTYPE_OUSTRING), PROPERTY_NONE, 0},
+ { SW_PROP_NMID(UNO_NAME_HIDE_FIELD_TIPS), WID_DOC_HIDE_TIPS, CPPU_E2T(CPPUTYPE_BOOLEAN), PROPERTY_NONE, 0},
+ { SW_PROP_NMID(UNO_NAME_REDLINE_DISPLAY_TYPE), WID_DOC_REDLINE_DISPLAY, CPPU_E2T(CPPUTYPE_INT16), PROPERTY_NONE, 0},
+ { SW_PROP_NMID(UNO_NAME_REDLINE_PROTECTION_KEY), WID_DOC_CHANGES_PASSWORD, CPPU_E2T(CPPUTYPE_SEQINT8), PROPERTY_NONE, 0 },
+ { SW_PROP_NMID(UNO_NAME_FORBIDDEN_CHARACTERS), WID_DOC_FORBIDDEN_CHARS, CPPU_E2T(CPPUTYPE_REFFORBCHARS), PROPERTY_NONE, 0},
+ { SW_PROP_NMID(UNO_NAME_TWO_DIGIT_YEAR), WID_DOC_TWO_DIGIT_YEAR, CPPU_E2T(CPPUTYPE_INT16), PROPERTY_NONE, 0},
+ { SW_PROP_NMID(UNO_NAME_AUTOMATIC_CONTROL_FOCUS), WID_DOC_AUTOMATIC_CONTROL_FOCUS, CPPU_E2T(CPPUTYPE_BOOLEAN), PROPERTY_NONE, 0},
+ { SW_PROP_NMID(UNO_NAME_APPLY_FORM_DESIGN_MODE), WID_DOC_APPLY_FORM_DESIGN_MODE, CPPU_E2T(CPPUTYPE_BOOLEAN), PROPERTY_NONE, 0},
+ { SW_PROP_NMID(UNO_NAME_RUNTIME_UID), WID_DOC_RUNTIME_UID, CPPU_E2T(CPPUTYPE_OUSTRING), PropertyAttribute::READONLY, 0},
+ { SW_PROP_NMID(UNO_NAME_LOCK_UPDATES), WID_DOC_LOCK_UPDATES, CPPU_E2T(CPPUTYPE_BOOLEAN), PROPERTY_NONE, 0},
+ { SW_PROP_NMID(UNO_NAME_HAS_VALID_SIGNATURES), WID_DOC_HAS_VALID_SIGNATURES, CPPU_E2T(CPPUTYPE_BOOLEAN), PropertyAttribute::READONLY, 0},
+ { SW_PROP_NMID(UNO_NAME_BUILDID), WID_DOC_BUILDID, CPPU_E2T(CPPUTYPE_OUSTRING), 0, 0},
+ { SW_PROP_NMID(UNO_NAME_APPLY_WORKAROUND_FOR_B6375613), WID_APPLY_WORKAROUND_FOR_B6375613, CPPU_E2T(CPPUTYPE_BOOLEAN), 0, 0},
+ {0,0,0,0,0,0}
+ };
+ aMapEntriesArr[nPropertyId] = aDocMap_Impl;
+ }
+ break;
+ case PROPERTY_MAP_LINK_TARGET:
+ {
+ static SfxItemPropertyMapEntry aLinkTargetMap_Impl[] =
+ {
+ { SW_PROP_NMID(UNO_LINK_DISPLAY_BITMAP), 0, CPPU_E2T(CPPUTYPE_REFBITMAP), PropertyAttribute::READONLY, 0xff},
+ { SW_PROP_NMID(UNO_LINK_DISPLAY_NAME), 0, CPPU_E2T(CPPUTYPE_OUSTRING), PropertyAttribute::READONLY, 0xff},
+ {0,0,0,0,0,0}
+ };
+ aMapEntriesArr[nPropertyId] = aLinkTargetMap_Impl;
+ }
+ break;
+ case PROPERTY_MAP_AUTO_TEXT_GROUP :
+ {
+ static SfxItemPropertyMapEntry aAutoTextGroupMap_Impl[] =
+ {
+ { SW_PROP_NMID(UNO_NAME_FILE_PATH), WID_GROUP_PATH, CPPU_E2T(CPPUTYPE_OUSTRING), PROPERTY_NONE, PropertyAttribute::READONLY},
+ { SW_PROP_NMID(UNO_NAME_TITLE), WID_GROUP_TITLE, CPPU_E2T(CPPUTYPE_OUSTRING), PROPERTY_NONE, 0},
+ {0,0,0,0,0,0}
+ };
+ aMapEntriesArr[nPropertyId] = aAutoTextGroupMap_Impl;
+ }
+ break;
+ case PROPERTY_MAP_TEXTPORTION_EXTENSIONS:
+ {
+ static SfxItemPropertyMapEntry aTextPortionExtensionMap_Impl[] =
+ {
+ COMPLETE_TEXT_CURSOR_MAP
+ {SW_PROP_NMID(UNO_NAME_BOOKMARK), FN_UNO_BOOKMARK, CPPU_E2T(CPPUTYPE_REFTEXTCNTNT), PropertyAttribute::MAYBEVOID|PropertyAttribute::READONLY ,0 },
+ {SW_PROP_NMID(UNO_NAME_CONTROL_CHARACTER), FN_UNO_CONTROL_CHARACTER, CPPU_E2T(CPPUTYPE_INT16), PropertyAttribute::MAYBEVOID|PropertyAttribute::READONLY, MID_HYPHEN_MIN_LEAD },
+ {SW_PROP_NMID(UNO_NAME_IS_COLLAPSED), FN_UNO_IS_COLLAPSED, CPPU_E2T(CPPUTYPE_BOOLEAN), PropertyAttribute::MAYBEVOID|PropertyAttribute::READONLY, 0 },
+ {SW_PROP_NMID(UNO_NAME_IS_START), FN_UNO_IS_START, CPPU_E2T(CPPUTYPE_BOOLEAN), PropertyAttribute::MAYBEVOID|PropertyAttribute::READONLY, 0 },
+ //_REDLINE_PROPERTIES
+ {SW_PROP_NMID(UNO_NAME_TEXT_PORTION_TYPE), FN_UNO_TEXT_PORTION_TYPE, CPPU_E2T(CPPUTYPE_OUSTRING), PropertyAttribute::READONLY, 0},
+ {SW_PROP_NMID(UNO_NAME_META), FN_UNO_META, CPPU_E2T(CPPUTYPE_REFTEXTCNTNT), PropertyAttribute::MAYBEVOID|PropertyAttribute::READONLY, 0 },
+ {0,0,0,0,0,0}
+ };
+ aMapEntriesArr[nPropertyId] = aTextPortionExtensionMap_Impl;
+ }
+ break;
+ case PROPERTY_MAP_FOOTNOTE:
+ {
+ static SfxItemPropertyMapEntry aFootnoteMap_Impl[] =
+ {
+ {SW_PROP_NMID(UNO_NAME_REFERENCE_ID), 0, CPPU_E2T(CPPUTYPE_INT16),PropertyAttribute::READONLY|PropertyAttribute::MAYBEVOID, 0},
+ COMMON_TEXT_CONTENT_PROPERTIES
+ _REDLINE_NODE_PROPERTIES
+ {0,0,0,0,0,0}
+ };
+ aMapEntriesArr[nPropertyId] = aFootnoteMap_Impl;
+ }
+ break;
+ case PROPERTY_MAP_TEXT_COLUMS :
+ {
+ static SfxItemPropertyMapEntry aTextColumns_Impl[] =
+ {
+ {SW_PROP_NMID(UNO_NAME_IS_AUTOMATIC), WID_TXTCOL_IS_AUTOMATIC, CPPU_E2T(CPPUTYPE_BOOLEAN),PropertyAttribute::READONLY, 0},
+ {SW_PROP_NMID(UNO_NAME_AUTOMATIC_DISTANCE), WID_TXTCOL_AUTO_DISTANCE, CPPU_E2T(CPPUTYPE_INT32),PROPERTY_NONE, 0},
+ {SW_PROP_NMID(UNO_NAME_SEPARATOR_LINE_WIDTH), WID_TXTCOL_LINE_WIDTH, CPPU_E2T(CPPUTYPE_INT32),PROPERTY_NONE, 0},
+ {SW_PROP_NMID(UNO_NAME_SEPARATOR_LINE_COLOR), WID_TXTCOL_LINE_COLOR, CPPU_E2T(CPPUTYPE_INT32),PROPERTY_NONE, 0},
+ {SW_PROP_NMID(UNO_NAME_SEPARATOR_LINE_RELATIVE_HEIGHT), WID_TXTCOL_LINE_REL_HGT, CPPU_E2T(CPPUTYPE_INT32),PROPERTY_NONE, 0},
+ {SW_PROP_NMID(UNO_NAME_SEPARATOR_LINE_VERTIVAL_ALIGNMENT), WID_TXTCOL_LINE_ALIGN, CPPU_E2T(CPPUTYPE_VERTALIGN),PROPERTY_NONE, 0},
+ {SW_PROP_NMID(UNO_NAME_SEPARATOR_LINE_IS_ON), WID_TXTCOL_LINE_IS_ON, CPPU_E2T(CPPUTYPE_BOOLEAN),PROPERTY_NONE, 0},
+ {SW_PROP_NMID(UNO_NAME_SEPARATOR_LINE_STYLE), WID_TXTCOL_LINE_STYLE, CPPU_E2T(CPPUTYPE_INT8),PROPERTY_NONE, 0},
+ {0,0,0,0,0,0}
+ };
+ aMapEntriesArr[nPropertyId] = aTextColumns_Impl;
+ }
+ break;
+ case PROPERTY_MAP_REDLINE :
+ {
+ static SfxItemPropertyMapEntry aRedlineMap_Impl[] =
+ {
+ _REDLINE_PROPERTIES
+ _REDLINE_NODE_PROPERTIES
+ {SW_PROP_NMID(UNO_NAME_REDLINE_START), 0, CPPU_E2T(CPPUTYPE_REFINTERFACE), PropertyAttribute::READONLY, 0},
+ {SW_PROP_NMID(UNO_NAME_REDLINE_END), 0, CPPU_E2T(CPPUTYPE_REFINTERFACE), PropertyAttribute::MAYBEVOID|PropertyAttribute::READONLY, 0},
+ {0,0,0,0,0,0}
+ };
+ aMapEntriesArr[nPropertyId] = aRedlineMap_Impl;
+ }
+ break;
+ case PROPERTY_MAP_TEXT_DEFAULT :
+ {
+ static SfxItemPropertyMapEntry aTextDefaultMap_Impl[] =
+ {
+ { SW_PROP_NMID(UNO_NAME_TAB_STOP_DISTANCE), RES_PARATR_TABSTOP, CPPU_E2T(CPPUTYPE_INT32), PROPERTY_NONE, MID_STD_TAB | CONVERT_TWIPS},
+ COMMON_CRSR_PARA_PROPERTIES_WITHOUT_FN
+ COMMON_HYPERLINK_PROPERTIES
+ { SW_PROP_NMID(UNO_NAME_CHAR_STYLE_NAME), RES_TXTATR_CHARFMT, CPPU_E2T(CPPUTYPE_OUSTRING), PropertyAttribute::MAYBEVOID, 0},
+ { SW_PROP_NMID(UNO_NAME_IS_SPLIT_ALLOWED), RES_ROW_SPLIT, CPPU_E2T(CPPUTYPE_BOOLEAN) , PropertyAttribute::MAYBEVOID, 0},
+ // #i29550#
+ { SW_PROP_NMID(UNO_NAME_COLLAPSING_BORDERS), RES_COLLAPSING_BORDERS, CPPU_E2T(CPPUTYPE_BOOLEAN), PROPERTY_NONE, 0},
+
+ //text grid enhancement for better CJK support. 2007-04-01
+ //just export the default page mode property, other properties are not handled in this version
+ { SW_PROP_NMID(UNO_NAME_GRID_STANDARD_PAGE_MODE), RES_TEXTGRID, CPPU_E2T(CPPUTYPE_BOOLEAN), PROPERTY_NONE, MID_GRID_STANDARD_MODE},
+ {0,0,0,0,0,0}
+ };
+ aMapEntriesArr[nPropertyId] = aTextDefaultMap_Impl;
+ for( SfxItemPropertyMapEntry * pMap = aTextDefaultMap_Impl;
+ pMap->pName; ++pMap )
+ {
+ // UNO_NAME_PAGE_DESC_NAME should keep its MAYBEVOID flag
+ if (!(RES_PAGEDESC == pMap->nWID && MID_PAGEDESC_PAGEDESCNAME == pMap->nMemberId))
+ pMap->nFlags &= ~PropertyAttribute::MAYBEVOID;
+ }
+ }
+ break;
+ case PROPERTY_MAP_REDLINE_PORTION :
+ {
+ static SfxItemPropertyMapEntry aRedlinePortionMap_Impl[] =
+ {
+ COMPLETE_TEXT_CURSOR_MAP
+ {SW_PROP_NMID(UNO_NAME_BOOKMARK), FN_UNO_BOOKMARK, CPPU_E2T(CPPUTYPE_REFTEXTCNTNT), PropertyAttribute::MAYBEVOID|PropertyAttribute::READONLY ,0 },
+ {SW_PROP_NMID(UNO_NAME_CONTROL_CHARACTER), FN_UNO_CONTROL_CHARACTER, CPPU_E2T(CPPUTYPE_INT16), PropertyAttribute::MAYBEVOID|PropertyAttribute::READONLY, MID_HYPHEN_MIN_LEAD },
+ {SW_PROP_NMID(UNO_NAME_IS_COLLAPSED), FN_UNO_IS_COLLAPSED, CPPU_E2T(CPPUTYPE_BOOLEAN), PropertyAttribute::MAYBEVOID|PropertyAttribute::READONLY, 0 },
+ {SW_PROP_NMID(UNO_NAME_IS_START), FN_UNO_IS_START, CPPU_E2T(CPPUTYPE_BOOLEAN), PropertyAttribute::MAYBEVOID|PropertyAttribute::READONLY, 0 },
+ _REDLINE_PROPERTIES
+ {SW_PROP_NMID(UNO_NAME_TEXT_PORTION_TYPE), FN_UNO_TEXT_PORTION_TYPE, CPPU_E2T(CPPUTYPE_OUSTRING), PropertyAttribute::READONLY, 0},
+ {0,0,0,0,0,0}
+ };
+ aMapEntriesArr[nPropertyId] = aRedlinePortionMap_Impl;
+ }
+ break;
+ case PROPERTY_MAP_FLDTYP_DATETIME:
+ {
+ static SfxItemPropertyMapEntry aDateTimeFieldPropMap[] =
+ {
+ {SW_PROP_NMID(UNO_NAME_ADJUST), FIELD_PROP_SUBTYPE, CPPU_E2T(CPPUTYPE_INT32), PROPERTY_NONE, 0},
+ {SW_PROP_NMID(UNO_NAME_DATE_TIME_VALUE), FIELD_PROP_DATE_TIME, CPPU_E2T(CPPUTYPE_DATETIME), PROPERTY_NONE, 0},
+ {SW_PROP_NMID(UNO_NAME_IS_FIXED), FIELD_PROP_BOOL1, CPPU_E2T(CPPUTYPE_BOOLEAN) , PROPERTY_NONE,0},
+ {SW_PROP_NMID(UNO_NAME_IS_DATE), FIELD_PROP_BOOL2, CPPU_E2T(CPPUTYPE_BOOLEAN) , PROPERTY_NONE,0},
+ {SW_PROP_NMID(UNO_NAME_NUMBER_FORMAT), FIELD_PROP_FORMAT, CPPU_E2T(CPPUTYPE_INT32), PROPERTY_NONE, 0},
+ {SW_PROP_NMID(UNO_NAME_IS_FIXED_LANGUAGE), FIELD_PROP_BOOL4, CPPU_E2T(CPPUTYPE_BOOLEAN), PROPERTY_NONE, 0},
+ COMMON_FLDTYP_PROPERTIES
+ {0,0,0,0,0,0}
+ };
+ aMapEntriesArr[nPropertyId] = aDateTimeFieldPropMap;
+ }
+ break;
+ case PROPERTY_MAP_FLDTYP_USER :
+ {
+ static SfxItemPropertyMapEntry aUserFieldPropMap[] =
+ {
+ {SW_PROP_NMID(UNO_NAME_IS_SHOW_FORMULA), FIELD_PROP_BOOL2, CPPU_E2T(CPPUTYPE_BOOLEAN), PROPERTY_NONE, 0},
+ {SW_PROP_NMID(UNO_NAME_IS_VISIBLE), FIELD_PROP_BOOL1, CPPU_E2T(CPPUTYPE_BOOLEAN), PROPERTY_NONE, 0},
+ {SW_PROP_NMID(UNO_NAME_NUMBER_FORMAT), FIELD_PROP_FORMAT, CPPU_E2T(CPPUTYPE_INT32), PROPERTY_NONE, 0},
+ {SW_PROP_NMID(UNO_NAME_IS_FIXED_LANGUAGE), FIELD_PROP_BOOL4, CPPU_E2T(CPPUTYPE_BOOLEAN), PROPERTY_NONE, 0},
+ COMMON_FLDTYP_PROPERTIES
+ {0,0,0,0,0,0}
+ };
+
+ aMapEntriesArr[nPropertyId] = aUserFieldPropMap;
+ }
+ break;
+ case PROPERTY_MAP_FLDTYP_SET_EXP :
+ {
+ static SfxItemPropertyMapEntry aSetExpFieldPropMap [] =
+ {
+ {SW_PROP_NMID(UNO_NAME_CONTENT), FIELD_PROP_PAR2, CPPU_E2T(CPPUTYPE_OUSTRING), PROPERTY_NONE, 0},
+ {SW_PROP_NMID(UNO_NAME_CURRENT_PRESENTATION), FIELD_PROP_PAR4, CPPU_E2T(CPPUTYPE_OUSTRING), PROPERTY_NONE, 0},
+ {SW_PROP_NMID(UNO_NAME_HINT), FIELD_PROP_PAR3, CPPU_E2T(CPPUTYPE_OUSTRING), PROPERTY_NONE, 0},
+ {SW_PROP_NMID(UNO_NAME_NUMBER_FORMAT), FIELD_PROP_FORMAT, CPPU_E2T(CPPUTYPE_INT32), PROPERTY_NONE, 0},
+ {SW_PROP_NMID(UNO_NAME_NUMBERING_TYPE), FIELD_PROP_USHORT2, CPPU_E2T(CPPUTYPE_INT16), PROPERTY_NONE, 0},
+ {SW_PROP_NMID(UNO_NAME_IS_INPUT), FIELD_PROP_BOOL1, CPPU_E2T(CPPUTYPE_BOOLEAN), PROPERTY_NONE, 0},
+ // #i69733# wrong name - UNO_NAME_IS_INPUT expanded to "Input" instead of "IsInput"
+ {SW_PROP_NMID(UNO_NAME_INPUT), FIELD_PROP_BOOL1, CPPU_E2T(CPPUTYPE_BOOLEAN), PROPERTY_NONE, 0},
+ {SW_PROP_NMID(UNO_NAME_IS_SHOW_FORMULA), FIELD_PROP_BOOL3, CPPU_E2T(CPPUTYPE_BOOLEAN), PROPERTY_NONE, 0},
+ {SW_PROP_NMID(UNO_NAME_IS_VISIBLE), FIELD_PROP_BOOL2, CPPU_E2T(CPPUTYPE_BOOLEAN), PROPERTY_NONE, 0},
+ //TODO: UNO_NAME_VARIABLE_NAME gibt es das wirklich?
+ {SW_PROP_NMID(UNO_NAME_SEQUENCE_VALUE), FIELD_PROP_USHORT1, CPPU_E2T(CPPUTYPE_INT16), PROPERTY_NONE, 0},
+ {SW_PROP_NMID(UNO_NAME_SUB_TYPE), FIELD_PROP_SUBTYPE, CPPU_E2T(CPPUTYPE_INT16), PROPERTY_NONE, 0},
+ {SW_PROP_NMID(UNO_NAME_VALUE), FIELD_PROP_DOUBLE, CPPU_E2T(CPPUTYPE_DOUBLE), PROPERTY_NONE, 0},
+ {SW_PROP_NMID(UNO_NAME_VARIABLE_NAME), FIELD_PROP_PAR1, CPPU_E2T(CPPUTYPE_OUSTRING), PropertyAttribute::READONLY, 0},
+ {SW_PROP_NMID(UNO_NAME_IS_FIXED_LANGUAGE), FIELD_PROP_BOOL4, CPPU_E2T(CPPUTYPE_BOOLEAN), PROPERTY_NONE, 0},
+ COMMON_FLDTYP_PROPERTIES
+ {0,0,0,0,0,0}
+ };
+ aMapEntriesArr[nPropertyId] = aSetExpFieldPropMap;
+ }
+ break;
+ case PROPERTY_MAP_FLDTYP_GET_EXP :
+ {
+ static SfxItemPropertyMapEntry aGetExpFieldPropMap [] =
+ {
+ {SW_PROP_NMID(UNO_NAME_CONTENT), FIELD_PROP_PAR1, CPPU_E2T(CPPUTYPE_OUSTRING), PROPERTY_NONE, 0},
+ {SW_PROP_NMID(UNO_NAME_CURRENT_PRESENTATION), FIELD_PROP_PAR4, CPPU_E2T(CPPUTYPE_OUSTRING), PROPERTY_NONE, 0},
+ {SW_PROP_NMID(UNO_NAME_IS_SHOW_FORMULA), FIELD_PROP_BOOL2, CPPU_E2T(CPPUTYPE_BOOLEAN), PROPERTY_NONE, 0},
+ {SW_PROP_NMID(UNO_NAME_NUMBER_FORMAT), FIELD_PROP_FORMAT, CPPU_E2T(CPPUTYPE_INT32), PROPERTY_NONE, 0},
+ {SW_PROP_NMID(UNO_NAME_SUB_TYPE), FIELD_PROP_SUBTYPE, CPPU_E2T(CPPUTYPE_INT16), PROPERTY_NONE, 0},
+ {SW_PROP_NMID(UNO_NAME_VALUE), FIELD_PROP_DOUBLE, CPPU_E2T(CPPUTYPE_DOUBLE), PropertyAttribute::READONLY, 0},
+ {SW_PROP_NMID(UNO_NAME_VARIABLE_SUBTYPE), FIELD_PROP_USHORT1, CPPU_E2T(CPPUTYPE_INT16), PROPERTY_NONE, 0},
+ {SW_PROP_NMID(UNO_NAME_IS_FIXED_LANGUAGE), FIELD_PROP_BOOL4, CPPU_E2T(CPPUTYPE_BOOLEAN), PROPERTY_NONE, 0},
+ COMMON_FLDTYP_PROPERTIES
+ {0,0,0,0,0,0}
+ };
+ aMapEntriesArr[nPropertyId] = aGetExpFieldPropMap;
+ }
+ break;
+ case PROPERTY_MAP_FLDTYP_FILE_NAME:
+ {
+ static SfxItemPropertyMapEntry aFileNameFieldPropMap [] =
+ {
+ {SW_PROP_NMID(UNO_NAME_CURRENT_PRESENTATION), FIELD_PROP_PAR3, CPPU_E2T(CPPUTYPE_OUSTRING), PROPERTY_NONE, 0},
+ {SW_PROP_NMID(UNO_NAME_FILE_FORMAT), FIELD_PROP_FORMAT, CPPU_E2T(CPPUTYPE_INT16), PROPERTY_NONE, 0},
+ {SW_PROP_NMID(UNO_NAME_IS_FIXED), FIELD_PROP_BOOL2, CPPU_E2T(CPPUTYPE_BOOLEAN), PROPERTY_NONE, 0},
+ COMMON_FLDTYP_PROPERTIES
+ {0,0,0,0,0,0}
+ };
+ aMapEntriesArr[nPropertyId] = aFileNameFieldPropMap;
+ }
+ break;
+ case PROPERTY_MAP_FLDTYP_PAGE_NUM :
+ {
+ static SfxItemPropertyMapEntry aPageNumFieldPropMap [] =
+ {
+ {SW_PROP_NMID(UNO_NAME_NUMBERING_TYPE), FIELD_PROP_FORMAT, CPPU_E2T(CPPUTYPE_INT16), PROPERTY_NONE, 0},
+ {SW_PROP_NMID(UNO_NAME_OFFSET), FIELD_PROP_USHORT1, CPPU_E2T(CPPUTYPE_INT16), PROPERTY_NONE, 0},
+ {SW_PROP_NMID(UNO_NAME_SUB_TYPE), FIELD_PROP_SUBTYPE, CPPU_E2T(CPPUTYPE_PAGENUMTYPE), PROPERTY_NONE, 0},
+ {SW_PROP_NMID(UNO_NAME_USERTEXT), FIELD_PROP_PAR1, CPPU_E2T(CPPUTYPE_OUSTRING), PROPERTY_NONE, 0},
+ COMMON_FLDTYP_PROPERTIES
+ {0,0,0,0,0,0}
+ };
+ aMapEntriesArr[nPropertyId] = aPageNumFieldPropMap;
+ }
+ break;
+ case PROPERTY_MAP_FLDTYP_AUTHOR :
+ {
+ static SfxItemPropertyMapEntry aAuthorFieldPropMap [] =
+ {
+ {SW_PROP_NMID(UNO_NAME_CONTENT), FIELD_PROP_PAR1, CPPU_E2T(CPPUTYPE_OUSTRING), PROPERTY_NONE, 0},
+ {SW_PROP_NMID(UNO_NAME_CURRENT_PRESENTATION), FIELD_PROP_PAR1, CPPU_E2T(CPPUTYPE_OUSTRING), PROPERTY_NONE, 0},
+ {SW_PROP_NMID(UNO_NAME_IS_FIXED), FIELD_PROP_BOOL2, CPPU_E2T(CPPUTYPE_BOOLEAN), PROPERTY_NONE, 0},
+ {SW_PROP_NMID(UNO_NAME_FULL_NAME),FIELD_PROP_BOOL1, CPPU_E2T(CPPUTYPE_BOOLEAN), PROPERTY_NONE, 0},
+ COMMON_FLDTYP_PROPERTIES
+ {0,0,0,0,0,0}
+ };
+ aMapEntriesArr[nPropertyId] = aAuthorFieldPropMap;
+ }
+ break;
+ case PROPERTY_MAP_FLDTYP_CHAPTER :
+ {
+ static SfxItemPropertyMapEntry aChapterFieldPropMap [] =
+ {
+ {SW_PROP_NMID(UNO_NAME_CHAPTER_FORMAT),FIELD_PROP_USHORT1, CPPU_E2T(CPPUTYPE_INT16), PROPERTY_NONE, 0},
+ {SW_PROP_NMID(UNO_NAME_LEVEL ),FIELD_PROP_BYTE1, CPPU_E2T(CPPUTYPE_INT8), PROPERTY_NONE, 0},
+ COMMON_FLDTYP_PROPERTIES
+ {0,0,0,0,0,0}
+ };
+ aMapEntriesArr[nPropertyId] = aChapterFieldPropMap;
+ }
+ break;
+ case PROPERTY_MAP_FLDTYP_GET_REFERENCE :
+ {
+ static SfxItemPropertyMapEntry aGetRefFieldPropMap [] =
+ {
+ {SW_PROP_NMID(UNO_NAME_CURRENT_PRESENTATION), FIELD_PROP_PAR3, CPPU_E2T(CPPUTYPE_OUSTRING), PROPERTY_NONE, 0},
+ {SW_PROP_NMID(UNO_NAME_REFERENCE_FIELD_PART),FIELD_PROP_USHORT1, CPPU_E2T(CPPUTYPE_INT16), PROPERTY_NONE, 0},
+ {SW_PROP_NMID(UNO_NAME_REFERENCE_FIELD_SOURCE),FIELD_PROP_USHORT2, CPPU_E2T(CPPUTYPE_INT16), PROPERTY_NONE, 0},
+ {SW_PROP_NMID(UNO_NAME_SEQUENCE_NUMBER), FIELD_PROP_SHORT1, CPPU_E2T(CPPUTYPE_INT16), PROPERTY_NONE, 0},
+ {SW_PROP_NMID(UNO_NAME_SOURCE_NAME), FIELD_PROP_PAR1, CPPU_E2T(CPPUTYPE_OUSTRING), PROPERTY_NONE, 0},
+ COMMON_FLDTYP_PROPERTIES
+ {0,0,0,0,0,0}
+ };
+ aMapEntriesArr[nPropertyId] = aGetRefFieldPropMap;
+ }
+ break;
+ case PROPERTY_MAP_FLDTYP_CONDITIONED_TEXT :
+ {
+ static SfxItemPropertyMapEntry aConditionedTxtFieldPropMap [] =
+ {
+ {SW_PROP_NMID(UNO_NAME_CONDITION), FIELD_PROP_PAR1, CPPU_E2T(CPPUTYPE_OUSTRING), PROPERTY_NONE, 0},
+ {SW_PROP_NMID(UNO_NAME_FALSE_CONTENT), FIELD_PROP_PAR3, CPPU_E2T(CPPUTYPE_OUSTRING), PROPERTY_NONE, 0},
+ {SW_PROP_NMID(UNO_NAME_IS_CONDITION_TRUE) , FIELD_PROP_BOOL1, CPPU_E2T(CPPUTYPE_BOOLEAN), PROPERTY_NONE, 0},
+ {SW_PROP_NMID(UNO_NAME_TRUE_CONTENT) , FIELD_PROP_PAR2, CPPU_E2T(CPPUTYPE_OUSTRING), PROPERTY_NONE, 0},
+ {SW_PROP_NMID(UNO_NAME_CURRENT_PRESENTATION), FIELD_PROP_PAR4, CPPU_E2T(CPPUTYPE_OUSTRING), PROPERTY_NONE, 0},
+ COMMON_FLDTYP_PROPERTIES
+ {0,0,0,0,0,0}
+ };
+ aMapEntriesArr[nPropertyId] = aConditionedTxtFieldPropMap;
+ }
+ break;
+ case PROPERTY_MAP_FLDTYP_HIDDEN_TEXT :
+ {
+ static SfxItemPropertyMapEntry aHiddenTxtFieldPropMap [] =
+ {
+ {SW_PROP_NMID(UNO_NAME_CONDITION), FIELD_PROP_PAR1, CPPU_E2T(CPPUTYPE_OUSTRING), PROPERTY_NONE, 0},
+ {SW_PROP_NMID(UNO_NAME_CONTENT) , FIELD_PROP_PAR2, CPPU_E2T(CPPUTYPE_OUSTRING), PROPERTY_NONE, 0},
+ {SW_PROP_NMID(UNO_NAME_IS_HIDDEN) , FIELD_PROP_BOOL1, CPPU_E2T(CPPUTYPE_BOOLEAN), PROPERTY_NONE, 0},
+ {SW_PROP_NMID(UNO_NAME_CURRENT_PRESENTATION), FIELD_PROP_PAR4, CPPU_E2T(CPPUTYPE_OUSTRING), PROPERTY_NONE, 0},
+ COMMON_FLDTYP_PROPERTIES
+ {0,0,0,0,0,0}
+ };
+ aMapEntriesArr[nPropertyId] = aHiddenTxtFieldPropMap;
+ }
+ break;
+ case PROPERTY_MAP_FLDTYP_ANNOTATION :
+ {
+ static SfxItemPropertyMapEntry aAnnotationFieldPropMap [] =
+ {
+ {SW_PROP_NMID(UNO_NAME_AUTHOR), FIELD_PROP_PAR1, CPPU_E2T(CPPUTYPE_OUSTRING), PROPERTY_NONE, 0},
+ {SW_PROP_NMID(UNO_NAME_CONTENT), FIELD_PROP_PAR2, CPPU_E2T(CPPUTYPE_OUSTRING), PROPERTY_NONE, 0},
+ {SW_PROP_NMID(UNO_NAME_DATE_TIME_VALUE), FIELD_PROP_DATE_TIME, CPPU_E2T(CPPUTYPE_DATETIME), PROPERTY_NONE, 0},
+ {SW_PROP_NMID(UNO_NAME_DATE), FIELD_PROP_DATE, CPPU_E2T(CPPUTYPE_DATE), PROPERTY_NONE, 0},
+ {SW_PROP_NMID(UNO_NAME_TEXT_RANGE), FIELD_PROP_TEXT, CPPU_E2T(CPPUTYPE_REFINTERFACE), PropertyAttribute::READONLY, 0},
+ COMMON_FLDTYP_PROPERTIES
+ {0,0,0,0,0,0}
+ };
+ aMapEntriesArr[nPropertyId] = aAnnotationFieldPropMap;
+ }
+ break;
+ case PROPERTY_MAP_FLDTYP_INPUT:
+ {
+ static SfxItemPropertyMapEntry aInputFieldPropMap [] =
+ {
+ {SW_PROP_NMID(UNO_NAME_CONTENT), FIELD_PROP_PAR1, CPPU_E2T(CPPUTYPE_OUSTRING), PROPERTY_NONE, 0},
+ {SW_PROP_NMID(UNO_NAME_HINT), FIELD_PROP_PAR2, CPPU_E2T(CPPUTYPE_OUSTRING), PROPERTY_NONE, 0},
+ {SW_PROP_NMID(UNO_NAME_HELP), FIELD_PROP_PAR3, CPPU_E2T(CPPUTYPE_OUSTRING), PROPERTY_NONE, 0},
+ {SW_PROP_NMID(UNO_NAME_TOOLTIP), FIELD_PROP_PAR4, CPPU_E2T(CPPUTYPE_OUSTRING), PROPERTY_NONE, 0},
+ COMMON_FLDTYP_PROPERTIES
+ {0,0,0,0,0,0}
+ };
+ aMapEntriesArr[nPropertyId] = aInputFieldPropMap;
+ }
+ break;
+ case PROPERTY_MAP_FLDTYP_MACRO :
+ {
+ static SfxItemPropertyMapEntry aMacroFieldPropMap [] =
+ {
+ {SW_PROP_NMID(UNO_NAME_HINT), FIELD_PROP_PAR2, CPPU_E2T(CPPUTYPE_OUSTRING), PROPERTY_NONE, 0},
+ {SW_PROP_NMID(UNO_NAME_MACRO_NAME),FIELD_PROP_PAR1, CPPU_E2T(CPPUTYPE_OUSTRING), PROPERTY_NONE, 0},
+ {SW_PROP_NMID(UNO_NAME_MACRO_LIBRARY),FIELD_PROP_PAR3, CPPU_E2T(CPPUTYPE_OUSTRING),PROPERTY_NONE, 0},
+ {SW_PROP_NMID(UNO_NAME_SCRIPT_URL),FIELD_PROP_PAR4, CPPU_E2T(CPPUTYPE_OUSTRING),PROPERTY_NONE, 0},
+ COMMON_FLDTYP_PROPERTIES
+ {0,0,0,0,0,0}
+ };
+ aMapEntriesArr[nPropertyId] = aMacroFieldPropMap;
+ }
+ break;
+ case PROPERTY_MAP_FLDTYP_DDE :
+ {
+ static SfxItemPropertyMapEntry aDDEFieldPropMap [] =
+ {
+ COMMON_FLDTYP_PROPERTIES
+ {0,0,0,0,0,0}
+ };
+ aMapEntriesArr[nPropertyId] = aDDEFieldPropMap;
+ }
+ break;
+ case PROPERTY_MAP_FLDTYP_DROPDOWN :
+ {
+ static SfxItemPropertyMapEntry aDropDownMap [] =
+ {
+ {SW_PROP_NMID(UNO_NAME_ITEMS), FIELD_PROP_STRINGS, CPPU_E2T(CPPUTYPE_OUSTRINGS), PROPERTY_NONE, 0},
+ {SW_PROP_NMID(UNO_NAME_SELITEM), FIELD_PROP_PAR1, CPPU_E2T(CPPUTYPE_OUSTRING), PROPERTY_NONE, 0},
+ {SW_PROP_NMID(UNO_NAME_NAME), FIELD_PROP_PAR2, CPPU_E2T(CPPUTYPE_OUSTRING), PROPERTY_NONE, 0},
+ {SW_PROP_NMID(UNO_NAME_HELP), FIELD_PROP_PAR3, CPPU_E2T(CPPUTYPE_OUSTRING), PROPERTY_NONE, 0},
+ {SW_PROP_NMID(UNO_NAME_TOOLTIP), FIELD_PROP_PAR4, CPPU_E2T(CPPUTYPE_OUSTRING), PROPERTY_NONE, 0},
+ COMMON_FLDTYP_PROPERTIES
+ {0,0,0,0,0,0}
+ };
+ aMapEntriesArr[nPropertyId] = aDropDownMap;
+ }
+ break;
+ case PROPERTY_MAP_FLDTYP_HIDDEN_PARA :
+ {
+ static SfxItemPropertyMapEntry aHiddenParaFieldPropMap [] =
+ {
+ {SW_PROP_NMID(UNO_NAME_CONDITION),FIELD_PROP_PAR1, CPPU_E2T(CPPUTYPE_OUSTRING), PROPERTY_NONE, 0},
+ {SW_PROP_NMID(UNO_NAME_IS_HIDDEN) , FIELD_PROP_BOOL1, CPPU_E2T(CPPUTYPE_BOOLEAN), PROPERTY_NONE, 0},
+ COMMON_FLDTYP_PROPERTIES
+ {0,0,0,0,0,0}
+ };
+ aMapEntriesArr[nPropertyId] = aHiddenParaFieldPropMap;
+ }
+ break;
+ case PROPERTY_MAP_FLDTYP_DOC_INFO :
+ {
+ static SfxItemPropertyMapEntry aDocInfoFieldPropMap [] =
+ {
+ {SW_PROP_NMID(UNO_NAME_IS_FIXED), FIELD_PROP_BOOL1, CPPU_E2T(CPPUTYPE_BOOLEAN), PROPERTY_NONE, 0},
+ {SW_PROP_NMID(UNO_NAME_INFO_FORMAT), FIELD_PROP_USHORT2, CPPU_E2T(CPPUTYPE_INT16), PROPERTY_NONE, 0},
+ {SW_PROP_NMID(UNO_NAME_INFO_TYPE), FIELD_PROP_USHORT1, CPPU_E2T(CPPUTYPE_INT16), PROPERTY_NONE, 0},
+ COMMON_FLDTYP_PROPERTIES
+ {0,0,0,0,0,0}
+ };
+ aMapEntriesArr[nPropertyId] = aDocInfoFieldPropMap;
+ }
+ break;
+ case PROPERTY_MAP_FLDTYP_TEMPLATE_NAME :
+ {
+ static SfxItemPropertyMapEntry aTmplNameFieldPropMap [] =
+ {
+ {SW_PROP_NMID(UNO_NAME_FILE_FORMAT), FIELD_PROP_FORMAT, CPPU_E2T(CPPUTYPE_INT16), PROPERTY_NONE, 0},
+ COMMON_FLDTYP_PROPERTIES
+ {0,0,0,0,0,0}
+ };
+ aMapEntriesArr[nPropertyId] = aTmplNameFieldPropMap;
+ }
+ break;
+ case PROPERTY_MAP_FLDTYP_USER_EXT :
+ {
+ static SfxItemPropertyMapEntry aUsrExtFieldPropMap [] =
+ {
+ {SW_PROP_NMID(UNO_NAME_CONTENT), FIELD_PROP_PAR1, CPPU_E2T(CPPUTYPE_OUSTRING), PROPERTY_NONE, 0},
+ {SW_PROP_NMID(UNO_NAME_CURRENT_PRESENTATION), FIELD_PROP_PAR1, CPPU_E2T(CPPUTYPE_OUSTRING), PROPERTY_NONE, 0},
+ {SW_PROP_NMID(UNO_NAME_IS_FIXED), FIELD_PROP_BOOL1, CPPU_E2T(CPPUTYPE_BOOLEAN), PROPERTY_NONE, 0},
+ {SW_PROP_NMID(UNO_NAME_USER_DATA_TYPE), FIELD_PROP_USHORT1, CPPU_E2T(CPPUTYPE_INT16), PROPERTY_NONE, 0},
+ COMMON_FLDTYP_PROPERTIES
+ {0,0,0,0,0,0}
+ };
+ aMapEntriesArr[nPropertyId]= aUsrExtFieldPropMap;
+ }
+ break;
+ case PROPERTY_MAP_FLDTYP_REF_PAGE_SET :
+ {
+ static SfxItemPropertyMapEntry aRefPgSetFieldPropMap [] =
+ {
+ {SW_PROP_NMID(UNO_NAME_OFFSET), FIELD_PROP_USHORT1, CPPU_E2T(CPPUTYPE_INT16), PROPERTY_NONE, 0},
+ {SW_PROP_NMID(UNO_NAME_ON), FIELD_PROP_BOOL1, CPPU_E2T(CPPUTYPE_BOOLEAN), PROPERTY_NONE, 0},
+ COMMON_FLDTYP_PROPERTIES
+ {0,0,0,0,0,0}
+ };
+ aMapEntriesArr[nPropertyId] = aRefPgSetFieldPropMap;
+ }
+ break;
+ case PROPERTY_MAP_FLDTYP_REF_PAGE_GET :
+ {
+ static SfxItemPropertyMapEntry aRefPgGetFieldPropMap [] =
+ {
+ {SW_PROP_NMID(UNO_NAME_CURRENT_PRESENTATION), FIELD_PROP_PAR1, CPPU_E2T(CPPUTYPE_OUSTRING), PROPERTY_NONE, 0},
+ {SW_PROP_NMID(UNO_NAME_NUMBERING_TYPE), FIELD_PROP_USHORT1, CPPU_E2T(CPPUTYPE_INT16), PROPERTY_NONE, 0},
+ COMMON_FLDTYP_PROPERTIES
+ {0,0,0,0,0,0}
+ };
+ aMapEntriesArr[nPropertyId] = aRefPgGetFieldPropMap;
+ }
+ break;
+ case PROPERTY_MAP_FLDTYP_JUMP_EDIT :
+ {
+ static SfxItemPropertyMapEntry aJumpEdtFieldPropMap [] =
+ {
+ {SW_PROP_NMID(UNO_NAME_HINT), FIELD_PROP_PAR1, CPPU_E2T(CPPUTYPE_OUSTRING), PROPERTY_NONE, 0},
+ {SW_PROP_NMID(UNO_NAME_PLACEHOLDER), FIELD_PROP_PAR2, CPPU_E2T(CPPUTYPE_OUSTRING), PROPERTY_NONE, 0},
+ {SW_PROP_NMID(UNO_NAME_PLACEHOLDER_TYPE), FIELD_PROP_USHORT1, CPPU_E2T(CPPUTYPE_INT16), PROPERTY_NONE, 0},
+ COMMON_FLDTYP_PROPERTIES
+ {0,0,0,0,0,0}
+ };
+ aMapEntriesArr[nPropertyId] = aJumpEdtFieldPropMap;
+ }
+ break;
+ case PROPERTY_MAP_FLDTYP_SCRIPT :
+ {
+ static SfxItemPropertyMapEntry aScriptFieldPropMap [] =
+ {
+ {SW_PROP_NMID(UNO_NAME_CONTENT), FIELD_PROP_PAR2, CPPU_E2T(CPPUTYPE_OUSTRING), PROPERTY_NONE, 0},
+ {SW_PROP_NMID(UNO_NAME_SCRIPT_TYPE), FIELD_PROP_PAR1, CPPU_E2T(CPPUTYPE_OUSTRING), PROPERTY_NONE, 0},
+ {SW_PROP_NMID(UNO_NAME_URL_CONTENT), FIELD_PROP_BOOL1, CPPU_E2T(CPPUTYPE_BOOLEAN), PROPERTY_NONE, 0},
+ COMMON_FLDTYP_PROPERTIES
+ {0,0,0,0,0,0}
+ };
+ aMapEntriesArr[nPropertyId] = aScriptFieldPropMap;
+ }
+ break;
+ case PROPERTY_MAP_FLDTYP_DATABASE_NEXT_SET :
+ {
+ static SfxItemPropertyMapEntry aDBNextSetFieldPropMap [] =
+ {
+ // Note: DATA_BASE_NAME and DATA_BASE_URL
+ // are mapped to the same nMId, because internally we only use
+ // them as DataSource and it does not matter which one it is.
+
+ {SW_PROP_NMID(UNO_NAME_DATA_BASE_NAME ) , FIELD_PROP_PAR1, CPPU_E2T(CPPUTYPE_OUSTRING), PROPERTY_NONE, 0},
+ {SW_PROP_NMID(UNO_NAME_DATA_TABLE_NAME) , FIELD_PROP_PAR2, CPPU_E2T(CPPUTYPE_OUSTRING), PROPERTY_NONE, 0},
+ {SW_PROP_NMID(UNO_NAME_CONDITION) , FIELD_PROP_PAR3, CPPU_E2T(CPPUTYPE_OUSTRING), PROPERTY_NONE, 0},
+ {SW_PROP_NMID(UNO_NAME_DATA_BASE_URL ) , FIELD_PROP_PAR1, CPPU_E2T(CPPUTYPE_OUSTRING), PROPERTY_NONE, 0},
+ {SW_PROP_NMID(UNO_NAME_DATA_COMMAND_TYPE), FIELD_PROP_SHORT1, CPPU_E2T(CPPUTYPE_INT32), PROPERTY_NONE, 0},
+ COMMON_FLDTYP_PROPERTIES
+ {0,0,0,0,0,0}
+ };
+ aMapEntriesArr[nPropertyId] = aDBNextSetFieldPropMap;
+ }
+ break;
+ case PROPERTY_MAP_FLDTYP_DATABASE_NUM_SET :
+ {
+ static SfxItemPropertyMapEntry aDBNumSetFieldPropMap [] =
+ {
+ // Note: DATA_BASE_NAME and DATA_BASE_URL
+ // are mapped to the same nMId, because internally we only use
+ // them as DataSource and it does not matter which one it is.
+
+ {SW_PROP_NMID(UNO_NAME_DATA_BASE_NAME ) , FIELD_PROP_PAR1, CPPU_E2T(CPPUTYPE_OUSTRING), PROPERTY_NONE, 0},
+ {SW_PROP_NMID(UNO_NAME_DATA_TABLE_NAME ), FIELD_PROP_PAR2, CPPU_E2T(CPPUTYPE_OUSTRING), PROPERTY_NONE, 0},
+ {SW_PROP_NMID(UNO_NAME_CONDITION), FIELD_PROP_PAR3, CPPU_E2T(CPPUTYPE_OUSTRING), PROPERTY_NONE, 0},
+ {SW_PROP_NMID(UNO_NAME_DATA_BASE_URL ) , FIELD_PROP_PAR1, CPPU_E2T(CPPUTYPE_OUSTRING), PROPERTY_NONE, 0},
+ {SW_PROP_NMID(UNO_NAME_DATA_COMMAND_TYPE), FIELD_PROP_SHORT1, CPPU_E2T(CPPUTYPE_INT32), PROPERTY_NONE, 0},
+ {SW_PROP_NMID(UNO_NAME_SET_NUMBER ), FIELD_PROP_FORMAT, CPPU_E2T(CPPUTYPE_INT32), PROPERTY_NONE, 0},
+ COMMON_FLDTYP_PROPERTIES
+ {0,0,0,0,0,0}
+ };
+ aMapEntriesArr[nPropertyId] = aDBNumSetFieldPropMap;
+ }
+ break;
+ case PROPERTY_MAP_FLDTYP_DATABASE_SET_NUM :
+ {
+ static SfxItemPropertyMapEntry aDBSetNumFieldPropMap [] =
+ {
+ // Note: DATA_BASE_NAME and DATA_BASE_URL
+ // are mapped to the same nMId, because internally we only use
+ // them as DataSource and it does not matter which one it is.
+
+ {SW_PROP_NMID(UNO_NAME_DATA_BASE_NAME ) , FIELD_PROP_PAR1, CPPU_E2T(CPPUTYPE_OUSTRING), PROPERTY_NONE, 0},
+ {SW_PROP_NMID(UNO_NAME_DATA_TABLE_NAME) , FIELD_PROP_PAR2, CPPU_E2T(CPPUTYPE_OUSTRING), PROPERTY_NONE, 0},
+ {SW_PROP_NMID(UNO_NAME_DATA_BASE_URL ) , FIELD_PROP_PAR1, CPPU_E2T(CPPUTYPE_OUSTRING), PROPERTY_NONE, 0},
+ {SW_PROP_NMID(UNO_NAME_DATA_COMMAND_TYPE), FIELD_PROP_SHORT1, CPPU_E2T(CPPUTYPE_INT32), PROPERTY_NONE, 0},
+ {SW_PROP_NMID(UNO_NAME_NUMBERING_TYPE), FIELD_PROP_USHORT1, CPPU_E2T(CPPUTYPE_INT16), PROPERTY_NONE, 0},
+ {SW_PROP_NMID(UNO_NAME_SET_NUMBER ), FIELD_PROP_FORMAT, CPPU_E2T(CPPUTYPE_INT32), PROPERTY_NONE, 0},
+ {SW_PROP_NMID(UNO_NAME_IS_VISIBLE), FIELD_PROP_BOOL2, CPPU_E2T(CPPUTYPE_BOOLEAN), PROPERTY_NONE, 0},
+ COMMON_FLDTYP_PROPERTIES
+ {0,0,0,0,0,0}
+ };
+ aMapEntriesArr[nPropertyId] = aDBSetNumFieldPropMap;
+ }
+ break;
+ case PROPERTY_MAP_FLDTYP_DATABASE :
+ {
+ static SfxItemPropertyMapEntry aDBFieldPropMap [] =
+ {
+ {SW_PROP_NMID(UNO_NAME_CONTENT), FIELD_PROP_PAR1, CPPU_E2T(CPPUTYPE_OUSTRING), PROPERTY_NONE, 0},
+ {SW_PROP_NMID(UNO_NAME_CURRENT_PRESENTATION), FIELD_PROP_PAR1, CPPU_E2T(CPPUTYPE_OUSTRING), PROPERTY_NONE, 0},
+ {SW_PROP_NMID(UNO_NAME_FIELD_CODE), FIELD_PROP_PAR2, CPPU_E2T(CPPUTYPE_OUSTRING), PROPERTY_NONE, 0},
+ {SW_PROP_NMID(UNO_NAME_IS_DATA_BASE_FORMAT),FIELD_PROP_BOOL1, CPPU_E2T(CPPUTYPE_BOOLEAN) , PROPERTY_NONE,0},
+ {SW_PROP_NMID(UNO_NAME_NUMBER_FORMAT), FIELD_PROP_FORMAT, CPPU_E2T(CPPUTYPE_INT32), PROPERTY_NONE, 0},
+ {SW_PROP_NMID(UNO_NAME_IS_VISIBLE), FIELD_PROP_BOOL2, CPPU_E2T(CPPUTYPE_BOOLEAN), PROPERTY_NONE, 0},
+ COMMON_FLDTYP_PROPERTIES
+ {0,0,0,0,0,0}
+ };
+ aMapEntriesArr[nPropertyId] = aDBFieldPropMap;
+ }
+ break;
+ case PROPERTY_MAP_FLDTYP_DATABASE_NAME :
+ {
+ static SfxItemPropertyMapEntry aDBNameFieldPropMap [] =
+ {
+ // Note: DATA_BASE_NAME and DATA_BASE_URL
+ // are mapped to the same nMId, because internally we only use
+ // them as DataSource and it does not matter which one it is.
+
+ {SW_PROP_NMID(UNO_NAME_DATA_BASE_NAME ) , FIELD_PROP_PAR1, CPPU_E2T(CPPUTYPE_OUSTRING), PROPERTY_NONE, 0},
+ {SW_PROP_NMID(UNO_NAME_DATA_TABLE_NAME) , FIELD_PROP_PAR2, CPPU_E2T(CPPUTYPE_OUSTRING), PROPERTY_NONE, 0},
+ {SW_PROP_NMID(UNO_NAME_DATA_BASE_URL ) , FIELD_PROP_PAR1, CPPU_E2T(CPPUTYPE_OUSTRING), PROPERTY_NONE, 0},
+ {SW_PROP_NMID(UNO_NAME_DATA_COMMAND_TYPE), FIELD_PROP_SHORT1, CPPU_E2T(CPPUTYPE_INT32), PROPERTY_NONE, 0},
+ {SW_PROP_NMID(UNO_NAME_IS_VISIBLE), FIELD_PROP_BOOL2, CPPU_E2T(CPPUTYPE_BOOLEAN), PROPERTY_NONE, 0},
+ COMMON_FLDTYP_PROPERTIES
+ {0,0,0,0,0,0}
+ };
+ aMapEntriesArr[nPropertyId] = aDBNameFieldPropMap;
+ }
+ break;
+ case PROPERTY_MAP_FLDTYP_DOCSTAT:
+ {
+ static SfxItemPropertyMapEntry aDocstatFieldPropMap [] =
+ {
+ {SW_PROP_NMID(UNO_NAME_NUMBERING_TYPE), FIELD_PROP_USHORT2, CPPU_E2T(CPPUTYPE_INT16), PROPERTY_NONE, 0},
+ // {UNO_NAME_STATISTIC_TYPE_ID,FIELD_PROP_USHORT1, CPPU_E2T(CPPUTYPE_INT16), PROPERTY_NONE, 0},
+ COMMON_FLDTYP_PROPERTIES
+ {0,0,0,0,0,0}
+ };
+ aMapEntriesArr[nPropertyId] = aDocstatFieldPropMap;
+ }
+ break;
+ case PROPERTY_MAP_FLDTYP_DOCINFO_AUTHOR:
+ {
+ static SfxItemPropertyMapEntry aDocInfoAuthorPropMap [] =
+ {
+ {SW_PROP_NMID(UNO_NAME_AUTHOR), FIELD_PROP_PAR1, CPPU_E2T(CPPUTYPE_OUSTRING), PROPERTY_NONE, 0},
+ {SW_PROP_NMID(UNO_NAME_CURRENT_PRESENTATION), FIELD_PROP_PAR3, CPPU_E2T(CPPUTYPE_OUSTRING), PROPERTY_NONE, 0},
+ {SW_PROP_NMID(UNO_NAME_IS_FIXED), FIELD_PROP_BOOL1, CPPU_E2T(CPPUTYPE_BOOLEAN) , PROPERTY_NONE,0},
+ COMMON_FLDTYP_PROPERTIES
+ {0,0,0,0,0,0}
+ };
+ aMapEntriesArr[nPropertyId] = aDocInfoAuthorPropMap;
+ }
+ break;
+ case PROPERTY_MAP_FLDTYP_DOCINFO_DATE_TIME:
+ {
+ static SfxItemPropertyMapEntry aDocInfoDateTimePropMap [] =
+ {
+ {SW_PROP_NMID(UNO_NAME_CURRENT_PRESENTATION), FIELD_PROP_PAR3, CPPU_E2T(CPPUTYPE_OUSTRING), PROPERTY_NONE, 0},
+ {SW_PROP_NMID(UNO_NAME_DATE_TIME_VALUE), FIELD_PROP_DOUBLE, CPPU_E2T(CPPUTYPE_DOUBLE), PropertyAttribute::READONLY, 0},
+ {SW_PROP_NMID(UNO_NAME_IS_DATE), FIELD_PROP_BOOL2, CPPU_E2T(CPPUTYPE_BOOLEAN) , PROPERTY_NONE,0},
+ {SW_PROP_NMID(UNO_NAME_NUMBER_FORMAT),FIELD_PROP_FORMAT, CPPU_E2T(CPPUTYPE_INT32), PROPERTY_NONE, 0},
+ {SW_PROP_NMID(UNO_NAME_IS_FIXED), FIELD_PROP_BOOL1, CPPU_E2T(CPPUTYPE_BOOLEAN) , PROPERTY_NONE, 0},
+ {SW_PROP_NMID(UNO_NAME_IS_FIXED_LANGUAGE), FIELD_PROP_BOOL4, CPPU_E2T(CPPUTYPE_BOOLEAN), PROPERTY_NONE, 0},
+ {0,0,0,0,0,0}
+ };
+ aMapEntriesArr[nPropertyId] = aDocInfoDateTimePropMap;
+ }
+ break;
+ case PROPERTY_MAP_FLDTYP_DOCINFO_EDIT_TIME :
+ {
+ static SfxItemPropertyMapEntry aDocInfoEditTimePropMap [] =
+ {
+ {SW_PROP_NMID(UNO_NAME_CURRENT_PRESENTATION), FIELD_PROP_PAR3, CPPU_E2T(CPPUTYPE_OUSTRING), PROPERTY_NONE, 0},
+ {SW_PROP_NMID(UNO_NAME_DATE_TIME_VALUE), FIELD_PROP_DOUBLE, CPPU_E2T(CPPUTYPE_DOUBLE), PropertyAttribute::READONLY, 0},
+ {SW_PROP_NMID(UNO_NAME_NUMBER_FORMAT),FIELD_PROP_FORMAT, CPPU_E2T(CPPUTYPE_INT32), PROPERTY_NONE, 0},
+ {SW_PROP_NMID(UNO_NAME_IS_FIXED), FIELD_PROP_BOOL1, CPPU_E2T(CPPUTYPE_BOOLEAN) , PROPERTY_NONE, 0},
+ {SW_PROP_NMID(UNO_NAME_IS_FIXED_LANGUAGE), FIELD_PROP_BOOL4, CPPU_E2T(CPPUTYPE_BOOLEAN), PROPERTY_NONE, 0},
+ COMMON_FLDTYP_PROPERTIES
+ {0,0,0,0,0,0}
+ };
+ aMapEntriesArr[nPropertyId] = aDocInfoEditTimePropMap;
+ }
+ break;
+ case PROPERTY_MAP_FLDTYP_DOCINFO_MISC:
+ {
+ static SfxItemPropertyMapEntry aDocInfoStringContentPropMap [] =
+ {
+ {SW_PROP_NMID(UNO_NAME_CONTENT), FIELD_PROP_PAR1, CPPU_E2T(CPPUTYPE_OUSTRING), PROPERTY_NONE, 0},
+ {SW_PROP_NMID(UNO_NAME_CURRENT_PRESENTATION), FIELD_PROP_PAR3, CPPU_E2T(CPPUTYPE_OUSTRING), PROPERTY_NONE, 0},
+ {SW_PROP_NMID(UNO_NAME_IS_FIXED), FIELD_PROP_BOOL1, CPPU_E2T(CPPUTYPE_BOOLEAN) , PROPERTY_NONE,0},
+ COMMON_FLDTYP_PROPERTIES
+ {0,0,0,0,0,0}
+ };
+ aMapEntriesArr[nPropertyId] = aDocInfoStringContentPropMap;
+ }
+ break;
+ case PROPERTY_MAP_FLDTYP_DOCINFO_CUSTOM:
+ {
+ static SfxItemPropertyMapEntry aDocInfoCustomPropMap [] =
+ {
+ {SW_PROP_NMID(UNO_NAME_NAME), FIELD_PROP_PAR4, CPPU_E2T(CPPUTYPE_OUSTRING), PROPERTY_NONE, 0},
+ {SW_PROP_NMID(UNO_NAME_CURRENT_PRESENTATION), FIELD_PROP_PAR3, CPPU_E2T(CPPUTYPE_OUSTRING), PROPERTY_NONE, 0},
+ {SW_PROP_NMID(UNO_NAME_IS_FIXED), FIELD_PROP_BOOL1, CPPU_E2T(CPPUTYPE_BOOLEAN) , PROPERTY_NONE,0},
+ {SW_PROP_NMID(UNO_NAME_NUMBER_FORMAT), FIELD_PROP_FORMAT, CPPU_E2T(CPPUTYPE_INT32), PROPERTY_NONE, 0},
+ {SW_PROP_NMID(UNO_NAME_IS_FIXED_LANGUAGE), FIELD_PROP_BOOL4, CPPU_E2T(CPPUTYPE_BOOLEAN), PROPERTY_NONE, 0},
+ COMMON_FLDTYP_PROPERTIES
+ {0,0,0,0,0,0}
+ };
+ aMapEntriesArr[nPropertyId] = aDocInfoCustomPropMap;
+ }
+ break;
+ case PROPERTY_MAP_FLDTYP_DOCINFO_REVISION :
+ {
+ static SfxItemPropertyMapEntry aDocInfoRevisionPropMap [] =
+ {
+ {SW_PROP_NMID(UNO_NAME_CURRENT_PRESENTATION), FIELD_PROP_PAR3, CPPU_E2T(CPPUTYPE_OUSTRING), PROPERTY_NONE, 0},
+ {SW_PROP_NMID(UNO_NAME_REVISION), FIELD_PROP_USHORT1, CPPU_E2T(CPPUTYPE_INT16), PROPERTY_NONE, 0},
+ {SW_PROP_NMID(UNO_NAME_IS_FIXED), FIELD_PROP_BOOL1, CPPU_E2T(CPPUTYPE_BOOLEAN) , PROPERTY_NONE,0},
+ COMMON_FLDTYP_PROPERTIES
+ {0,0,0,0,0,0}
+ };
+ aMapEntriesArr[nPropertyId] = aDocInfoRevisionPropMap;
+ }
+ break;
+ case PROPERTY_MAP_FLDTYP_COMBINED_CHARACTERS:
+ {
+ static SfxItemPropertyMapEntry aCombinedCharactersPropMap[] =
+ {
+ {SW_PROP_NMID(UNO_NAME_CONTENT), FIELD_PROP_PAR1, CPPU_E2T(CPPUTYPE_OUSTRING), PROPERTY_NONE, 0},
+ COMMON_FLDTYP_PROPERTIES
+ {0,0,0,0,0,0}
+ };
+ aMapEntriesArr[nPropertyId] = aCombinedCharactersPropMap;
+ }
+ break;
+ case PROPERTY_MAP_FLDTYP_TABLE_FORMULA:
+ {
+ static SfxItemPropertyMapEntry aTableFormulaPropMap[] =
+ {
+ {SW_PROP_NMID(UNO_NAME_CURRENT_PRESENTATION), FIELD_PROP_PAR1, CPPU_E2T(CPPUTYPE_OUSTRING), PROPERTY_NONE, 0},
+ {SW_PROP_NMID(UNO_NAME_CONTENT), FIELD_PROP_PAR2, CPPU_E2T(CPPUTYPE_OUSTRING), PROPERTY_NONE, 0},
+ {SW_PROP_NMID(UNO_NAME_IS_SHOW_FORMULA), FIELD_PROP_BOOL1, CPPU_E2T(CPPUTYPE_BOOLEAN), PROPERTY_NONE, 0},
+ {SW_PROP_NMID(UNO_NAME_NUMBER_FORMAT), FIELD_PROP_FORMAT, CPPU_E2T(CPPUTYPE_INT32), PROPERTY_NONE, 0},
+ COMMON_FLDTYP_PROPERTIES
+ {0,0,0,0,0,0}
+ };
+ aMapEntriesArr[nPropertyId] = aTableFormulaPropMap;
+ }
+ break;
+ case PROPERTY_MAP_FLDTYP_DUMMY_0:
+ {
+ static SfxItemPropertyMapEntry aEmptyPropMap [] =
+ {
+ COMMON_FLDTYP_PROPERTIES
+ {0,0,0,0,0,0}
+ };
+ aMapEntriesArr[nPropertyId] = aEmptyPropMap;
+ }
+ break;
+ case PROPERTY_MAP_FLDMSTR_USER :
+ {
+ static SfxItemPropertyMapEntry aUserFieldTypePropMap[] =
+ {
+ {SW_PROP_NMID(UNO_NAME_DEPENDENT_TEXT_FIELDS), FIELD_PROP_PROP_SEQ, CPPU_E2T(CPPUTYPE_SEQDEPTXTFLD), PropertyAttribute::READONLY, 0},
+ {SW_PROP_NMID(UNO_NAME_IS_EXPRESSION), FIELD_PROP_BOOL1, CPPU_E2T(CPPUTYPE_BOOLEAN), PROPERTY_NONE, 0},
+ {SW_PROP_NMID(UNO_NAME_NAME), FIELD_PROP_PAR1, CPPU_E2T(CPPUTYPE_OUSTRING), PropertyAttribute::MAYBEVOID, 0},
+ {SW_PROP_NMID(UNO_NAME_VALUE), FIELD_PROP_DOUBLE, CPPU_E2T(CPPUTYPE_DOUBLE), PROPERTY_NONE, 0},
+ {SW_PROP_NMID(UNO_NAME_CONTENT), FIELD_PROP_PAR2, CPPU_E2T(CPPUTYPE_OUSTRING), PROPERTY_NONE, 0},
+ {SW_PROP_NMID(UNO_NAME_INSTANCE_NAME), FIELD_PROP_PAR3, CPPU_E2T(CPPUTYPE_OUSTRING), PropertyAttribute::READONLY, 0},
+ {0,0,0,0,0,0}
+ };
+ aMapEntriesArr[nPropertyId] = aUserFieldTypePropMap;
+ }
+ break;
+ case PROPERTY_MAP_FLDMSTR_DDE :
+ {
+ static SfxItemPropertyMapEntry aDDEFieldTypePropMap[] =
+ {
+ {SW_PROP_NMID(UNO_NAME_DDE_COMMAND_ELEMENT ), FIELD_PROP_PAR2, CPPU_E2T(CPPUTYPE_OUSTRING), PROPERTY_NONE, 0},
+ {SW_PROP_NMID(UNO_NAME_DDE_COMMAND_FILE ), FIELD_PROP_PAR4, CPPU_E2T(CPPUTYPE_OUSTRING), PROPERTY_NONE, 0},
+ {SW_PROP_NMID(UNO_NAME_DDE_COMMAND_TYPE ), FIELD_PROP_SUBTYPE, CPPU_E2T(CPPUTYPE_OUSTRING), PROPERTY_NONE, 0},
+ {SW_PROP_NMID(UNO_NAME_DEPENDENT_TEXT_FIELDS), FIELD_PROP_PROP_SEQ, CPPU_E2T(CPPUTYPE_SEQDEPTXTFLD), PropertyAttribute::READONLY, 0},
+ {SW_PROP_NMID(UNO_NAME_IS_AUTOMATIC_UPDATE), FIELD_PROP_BOOL1, CPPU_E2T(CPPUTYPE_BOOLEAN), PROPERTY_NONE, 0},
+ {SW_PROP_NMID(UNO_NAME_NAME), FIELD_PROP_PAR1, CPPU_E2T(CPPUTYPE_OUSTRING), PROPERTY_NONE, 0},
+ {SW_PROP_NMID(UNO_NAME_INSTANCE_NAME), FIELD_PROP_PAR3, CPPU_E2T(CPPUTYPE_OUSTRING), PropertyAttribute::READONLY, 0},
+ {SW_PROP_NMID(UNO_NAME_CONTENT), FIELD_PROP_PAR5, CPPU_E2T(CPPUTYPE_OUSTRING), PROPERTY_NONE, 0},
+ {0,0,0,0,0,0}
+ };
+ aMapEntriesArr[nPropertyId] = aDDEFieldTypePropMap;
+ }
+ break;
+ case PROPERTY_MAP_FLDMSTR_SET_EXP :
+ {
+ static SfxItemPropertyMapEntry aSetExpFieldTypePropMap[] =
+ {
+ {SW_PROP_NMID(UNO_NAME_CHAPTER_NUMBERING_LEVEL),FIELD_PROP_SHORT1, CPPU_E2T(CPPUTYPE_INT8), PROPERTY_NONE, 0},
+ {SW_PROP_NMID(UNO_NAME_DEPENDENT_TEXT_FIELDS), FIELD_PROP_PROP_SEQ, CPPU_E2T(CPPUTYPE_SEQDEPTXTFLD), PropertyAttribute::READONLY, 0},
+ {SW_PROP_NMID(UNO_NAME_NAME), FIELD_PROP_PAR1, CPPU_E2T(CPPUTYPE_OUSTRING), PROPERTY_NONE, 0},
+ {SW_PROP_NMID(UNO_NAME_NUMBERING_SEPARATOR), FIELD_PROP_PAR2, CPPU_E2T(CPPUTYPE_OUSTRING), PROPERTY_NONE, 0},
+ {SW_PROP_NMID(UNO_NAME_SUB_TYPE), FIELD_PROP_SUBTYPE, CPPU_E2T(CPPUTYPE_INT16), PROPERTY_NONE, 0},
+ {SW_PROP_NMID(UNO_NAME_INSTANCE_NAME), FIELD_PROP_PAR3, CPPU_E2T(CPPUTYPE_OUSTRING), PropertyAttribute::READONLY, 0},
+ {0,0,0,0,0,0}
+ };
+ aMapEntriesArr[nPropertyId] = aSetExpFieldTypePropMap;
+ }
+ break;
+ case PROPERTY_MAP_FLDMSTR_DATABASE :
+ {
+ static SfxItemPropertyMapEntry aDBFieldTypePropMap [] =
+ {
+ // Note: DATA_BASE_NAME and DATA_BASE_URL
+ // are mapped to the same nMId, because internally we only use
+ // them as DataSource and it does not matter which one it is.
+
+ {SW_PROP_NMID(UNO_NAME_DATA_BASE_NAME ) , FIELD_PROP_PAR1, CPPU_E2T(CPPUTYPE_OUSTRING), PROPERTY_NONE, 0},
+ {SW_PROP_NMID(UNO_NAME_NAME), FIELD_PROP_PAR3, CPPU_E2T(CPPUTYPE_OUSTRING), PropertyAttribute::MAYBEVOID, 0},
+ {SW_PROP_NMID(UNO_NAME_DATA_TABLE_NAME ), FIELD_PROP_PAR2, CPPU_E2T(CPPUTYPE_OUSTRING), PROPERTY_NONE, 0},
+ {SW_PROP_NMID(UNO_NAME_DATA_COLUMN_NAME ), FIELD_PROP_PAR3, CPPU_E2T(CPPUTYPE_OUSTRING), PROPERTY_NONE, 0},
+ {SW_PROP_NMID(UNO_NAME_INSTANCE_NAME), FIELD_PROP_PAR4, CPPU_E2T(CPPUTYPE_OUSTRING), PropertyAttribute::READONLY, 0},
+ {SW_PROP_NMID(UNO_NAME_DATA_BASE_URL ) , FIELD_PROP_PAR1, CPPU_E2T(CPPUTYPE_OUSTRING), PROPERTY_NONE, 0},
+ {SW_PROP_NMID(UNO_NAME_DATA_COMMAND_TYPE), FIELD_PROP_SHORT1, CPPU_E2T(CPPUTYPE_INT32), PROPERTY_NONE, 0},
+ {SW_PROP_NMID(UNO_NAME_DEPENDENT_TEXT_FIELDS), FIELD_PROP_PROP_SEQ, CPPU_E2T(CPPUTYPE_SEQDEPTXTFLD), PropertyAttribute::READONLY, 0},
+ {0,0,0,0,0,0}
+ };
+ aMapEntriesArr[nPropertyId] = aDBFieldTypePropMap;
+ }
+ break;
+ case PROPERTY_MAP_FLDMSTR_DUMMY0 :
+ {
+ static SfxItemPropertyMapEntry aStandardFieldMasterMap[] =
+ {
+ {SW_PROP_NMID(UNO_NAME_DEPENDENT_TEXT_FIELDS), 0, CPPU_E2T(CPPUTYPE_SEQDEPTXTFLD), PropertyAttribute::READONLY, 0},
+ {SW_PROP_NMID(UNO_NAME_NAME), 0, CPPU_E2T(CPPUTYPE_OUSTRING), PROPERTY_NONE, 0},
+ {SW_PROP_NMID(UNO_NAME_INSTANCE_NAME), 0, CPPU_E2T(CPPUTYPE_OUSTRING), PropertyAttribute::READONLY, 0},
+ {0,0,0,0,0,0}
+ };
+ aMapEntriesArr[nPropertyId] = aStandardFieldMasterMap;
+ }
+ break;
+ case PROPERTY_MAP_FLDTYP_BIBLIOGRAPHY:
+ {
+ static SfxItemPropertyMapEntry aBibliographyFieldMap[] =
+ {
+ {SW_PROP_NMID(UNO_NAME_FIELDS ) , FIELD_PROP_PROP_SEQ, CPPU_E2T(CPPUTYPE_PROPERTYVALUE),PROPERTY_NONE, 0},
+ COMMON_FLDTYP_PROPERTIES
+ {0,0,0,0,0,0}
+ };
+ aMapEntriesArr[nPropertyId] = aBibliographyFieldMap;
+ }
+ break;
+ case PROPERTY_MAP_FLDMSTR_BIBLIOGRAPHY:
+ {
+ static SfxItemPropertyMapEntry aBibliographyFieldMasterMap[] =
+ {
+ {SW_PROP_NMID(UNO_NAME_BRACKET_BEFORE ) , FIELD_PROP_PAR1, CPPU_E2T(CPPUTYPE_OUSTRING), PROPERTY_NONE, 0},
+ {SW_PROP_NMID(UNO_NAME_BRACKET_AFTER ) , FIELD_PROP_PAR2, CPPU_E2T(CPPUTYPE_OUSTRING), PROPERTY_NONE, 0},
+ {SW_PROP_NMID(UNO_NAME_IS_NUMBER_ENTRIES ) , FIELD_PROP_BOOL1, CPPU_E2T(CPPUTYPE_BOOLEAN), PROPERTY_NONE, 0},
+ {SW_PROP_NMID(UNO_NAME_IS_SORT_BY_POSITION) , FIELD_PROP_BOOL2, CPPU_E2T(CPPUTYPE_BOOLEAN), PROPERTY_NONE, 0},
+ {SW_PROP_NMID(UNO_NAME_LOCALE), FIELD_PROP_LOCALE, CPPU_E2T(CPPUTYPE_LOCALE) , PROPERTY_NONE, 0},
+ {SW_PROP_NMID(UNO_NAME_SORT_ALGORITHM), FIELD_PROP_PAR3, CPPU_E2T(CPPUTYPE_OUSTRING), PROPERTY_NONE, 0},
+ {SW_PROP_NMID(UNO_NAME_SORT_KEYS ) , FIELD_PROP_PROP_SEQ, CPPU_E2T(CPPUTYPE_PROPERTYVALUES), PROPERTY_NONE, 0},
+ {SW_PROP_NMID(UNO_NAME_INSTANCE_NAME), FIELD_PROP_PAR4, CPPU_E2T(CPPUTYPE_OUSTRING), PropertyAttribute::READONLY, 0},
+ {0,0,0,0,0,0}
+ };
+ aMapEntriesArr[nPropertyId] = aBibliographyFieldMasterMap;
+ }
+ break;
+ case PROPERTY_MAP_TEXT :
+ {
+ static SfxItemPropertyMapEntry aTextMap[] =
+ {
+ _REDLINE_NODE_PROPERTIES
+ {0,0,0,0,0,0}
+ };
+ aMapEntriesArr[nPropertyId] = aTextMap;
+ }
+ break;
+ case PROPERTY_MAP_MAILMERGE :
+ {
+ static SfxItemPropertyMapEntry aMailMergeMap[] =
+ {
+ { SW_PROP_NMID(UNO_NAME_SELECTION), WID_SELECTION, CPPU_E2T(CPPUTYPE_SEQANY), PROPERTY_NONE, 0},
+ { SW_PROP_NMID(UNO_NAME_RESULT_SET), WID_RESULT_SET, CPPU_E2T(CPPUTYPE_REFRESULTSET), PROPERTY_NONE, 0},
+ { SW_PROP_NMID(UNO_NAME_CONNECTION), WID_CONNECTION, CPPU_E2T(CPPUTYPE_REFCONNECTION), PROPERTY_NONE, 0},
+ { SW_PROP_NMID(UNO_NAME_MODEL), WID_MODEL, CPPU_E2T(CPPUTYPE_REFMODEL), PropertyAttribute::READONLY, 0},
+ { SW_PROP_NMID(UNO_NAME_DATA_SOURCE_NAME), WID_DATA_SOURCE_NAME, CPPU_E2T(CPPUTYPE_OUSTRING), PROPERTY_NONE, 0},
+ { SW_PROP_NMID(UNO_NAME_DAD_COMMAND), WID_DATA_COMMAND, CPPU_E2T(CPPUTYPE_OUSTRING), PROPERTY_NONE, 0},
+ { SW_PROP_NMID(UNO_NAME_FILTER), WID_FILTER, CPPU_E2T(CPPUTYPE_OUSTRING), PROPERTY_NONE, 0},
+ { SW_PROP_NMID(UNO_NAME_DOCUMENT_URL), WID_DOCUMENT_URL, CPPU_E2T(CPPUTYPE_OUSTRING), PROPERTY_NONE, 0},
+ { SW_PROP_NMID(UNO_NAME_OUTPUT_URL), WID_OUTPUT_URL, CPPU_E2T(CPPUTYPE_OUSTRING), PROPERTY_NONE, 0},
+ { SW_PROP_NMID(UNO_NAME_DAD_COMMAND_TYPE), WID_DATA_COMMAND_TYPE, CPPU_E2T(CPPUTYPE_INT32), PROPERTY_NONE, 0},
+ { SW_PROP_NMID(UNO_NAME_OUTPUT_TYPE), WID_OUTPUT_TYPE, CPPU_E2T(CPPUTYPE_INT16), PROPERTY_NONE, 0},
+ { SW_PROP_NMID(UNO_NAME_ESCAPE_PROCESSING), WID_ESCAPE_PROCESSING, CPPU_E2T(CPPUTYPE_BOOLEAN), PROPERTY_NONE, 0},
+ { SW_PROP_NMID(UNO_NAME_SINGLE_PRINT_JOBS), WID_SINGLE_PRINT_JOBS, CPPU_E2T(CPPUTYPE_BOOLEAN), PROPERTY_NONE, 0},
+ { SW_PROP_NMID(UNO_NAME_FILE_NAME_FROM_COLUMN), WID_FILE_NAME_FROM_COLUMN, CPPU_E2T(CPPUTYPE_BOOLEAN), PROPERTY_NONE, 0},
+ { SW_PROP_NMID(UNO_NAME_FILE_NAME_PREFIX), WID_FILE_NAME_PREFIX, CPPU_E2T(CPPUTYPE_OUSTRING), PROPERTY_NONE, 0},
+ { SW_PROP_NMID(UNO_NAME_SUBJECT), WID_MAIL_SUBJECT, CPPU_E2T(CPPUTYPE_OUSTRING), PROPERTY_NONE, 0},
+ { SW_PROP_NMID(UNO_NAME_ADDRESS_FROM_COLUMN), WID_ADDRESS_FROM_COLUMN, CPPU_E2T(CPPUTYPE_OUSTRING), PROPERTY_NONE, 0},
+ { SW_PROP_NMID(UNO_NAME_SEND_AS_HTML), WID_SEND_AS_HTML, CPPU_E2T(CPPUTYPE_BOOLEAN), PROPERTY_NONE, 0},
+ { SW_PROP_NMID(UNO_NAME_SEND_AS_ATTACHMENT), WID_SEND_AS_ATTACHMENT, CPPU_E2T(CPPUTYPE_BOOLEAN), PROPERTY_NONE, 0},
+ { SW_PROP_NMID(UNO_NAME_MAIL_BODY), WID_MAIL_BODY, CPPU_E2T(CPPUTYPE_OUSTRING), PROPERTY_NONE, 0},
+ { SW_PROP_NMID(UNO_NAME_ATTACHMENT_NAME), WID_ATTACHMENT_NAME, CPPU_E2T(CPPUTYPE_OUSTRING), PROPERTY_NONE, 0},
+ { SW_PROP_NMID(UNO_NAME_ATTACHMENT_FILTER), WID_ATTACHMENT_FILTER, CPPU_E2T(CPPUTYPE_OUSTRING), PROPERTY_NONE, 0},
+ { SW_PROP_NMID(UNO_NAME_PRINT_OPTIONS), WID_PRINT_OPTIONS, CPPU_E2T(CPPUTYPE_PROPERTYVALUES), PROPERTY_NONE, 0},
+ { SW_PROP_NMID(UNO_NAME_SAVE_AS_SINGLE_FILE), WID_SAVE_AS_SINGLE_FILE, CPPU_E2T(CPPUTYPE_BOOLEAN), PROPERTY_NONE, 0},
+ { SW_PROP_NMID(UNO_NAME_SAVE_FILTER), WID_SAVE_FILTER, CPPU_E2T(CPPUTYPE_OUSTRING), PROPERTY_NONE, 0},
+ { SW_PROP_NMID(UNO_NAME_SAVE_FILTER_OPTIONS), WID_SAVE_FILTER_OPTIONS, CPPU_E2T(CPPUTYPE_OUSTRING), PROPERTY_NONE, 0},
+ { SW_PROP_NMID(UNO_NAME_SAVE_FILTER_DATA), WID_SAVE_FILTER_DATA, CPPU_E2T(CPPUTYPE_PROPERTYVALUES), PROPERTY_NONE, 0},
+ { SW_PROP_NMID(UNO_NAME_COPIES_TO), WID_COPIES_TO, CPPU_E2T(CPPUTYPE_OUSTRINGS), PROPERTY_NONE, 0},
+ { SW_PROP_NMID(UNO_NAME_BLIND_COPIES_TO), WID_BLIND_COPIES_TO, CPPU_E2T(CPPUTYPE_OUSTRINGS), PROPERTY_NONE, 0},
+ { SW_PROP_NMID(UNO_NAME_IN_SERVER_PASSWORD), WID_IN_SERVER_PASSWORD, CPPU_E2T(CPPUTYPE_OUSTRING), PROPERTY_NONE, 0},
+ { SW_PROP_NMID(UNO_NAME_OUT_SERVER_PASSWORD), WID_OUT_SERVER_PASSWORD, CPPU_E2T(CPPUTYPE_OUSTRING), PROPERTY_NONE, 0},
+ {0,0,0,0,0,0}
+ };
+ aMapEntriesArr[nPropertyId] = aMailMergeMap;
+ }
+ break;
+ case PROPERTY_MAP_TEXT_VIEW :
+ {
+ static SfxItemPropertyMapEntry pTextViewMap[] =
+ {
+ {SW_PROP_NMID(UNO_NAME_PAGE_COUNT), WID_PAGE_COUNT, CPPU_E2T(CPPUTYPE_INT32), PropertyAttribute::READONLY, 0},
+ {SW_PROP_NMID(UNO_NAME_LINE_COUNT), WID_LINE_COUNT, CPPU_E2T(CPPUTYPE_INT32), PropertyAttribute::READONLY, 0},
+ {SW_PROP_NMID(UNO_NAME_IS_CONSTANT_SPELLCHECK), WID_IS_CONSTANT_SPELLCHECK, CPPU_E2T(CPPUTYPE_BOOLEAN), PROPERTY_NONE, 0},
+ {SW_PROP_NMID(UNO_NAME_IS_HIDE_SPELL_MARKS), WID_IS_HIDE_SPELL_MARKS, CPPU_E2T(CPPUTYPE_BOOLEAN), PROPERTY_NONE, 0}, // deprecated #i91949
+ {0,0,0,0,0,0}
+ };
+ aMapEntriesArr[nPropertyId] = pTextViewMap;
+ }
+ break;
+ case PROPERTY_MAP_CHART2_DATA_SEQUENCE :
+ {
+ static SfxItemPropertyMapEntry aChart2DataSequenceMap[] =
+ {
+ {SW_PROP_NMID(UNO_NAME_ROLE), 0, CPPU_E2T(CPPUTYPE_OUSTRING), PROPERTY_NONE, 0 },
+ {0,0,0,0,0,0}
+ };
+ aMapEntriesArr[nPropertyId] = aChart2DataSequenceMap;
+ }
+ break;
+ case PROPERTY_MAP_METAFIELD:
+ {
+ static SfxItemPropertyMapEntry aMetaFieldMap[] =
+ {
+ { SW_PROP_NMID(UNO_NAME_NUMBER_FORMAT), 0,
+ CPPU_E2T(CPPUTYPE_INT32), PROPERTY_NONE, 0 },
+ { SW_PROP_NMID(UNO_NAME_IS_FIXED_LANGUAGE), 0,
+ CPPU_E2T(CPPUTYPE_BOOLEAN), PROPERTY_NONE, 0 },
+ {0,0,0,0,0,0}
+ };
+ aMapEntriesArr[nPropertyId] = aMetaFieldMap;
+ }
+ break;
+
+ default:
+ OSL_FAIL( "unexpected property map ID" );
+ }
+ //fill the character pointers and types into the arrays
+ SfxItemPropertyMapEntry* p = aMapEntriesArr[nPropertyId];
+ sal_uInt16 i = 0;
+ for( ; p->pName; ++p, ++i )
+ {
+ // set the name
+ const SwPropNameLen& rPropNm = GetPropName( (sal_uInt16)(long)p->pName );
+ p->pName = rPropNm.pName;
+ p->nNameLen = rPropNm.nNameLen;
+ // get the cppu type from the comphelper
+ CppuTypes nTyp = (CppuTypes) (long) p->pType;
+ GenerateCppuType( nTyp, p->pType );
+ DBG_ASSERT( nTyp != (CppuTypes) (long) p->pType, "unknown type" );
+ }
+ }
+ return aMapEntriesArr[nPropertyId];
+}
+
+const SfxItemPropertySet* SwUnoPropertyMapProvider::GetPropertySet( sal_uInt16 nPropertyId)
+{
+ if( !aPropertySetArr[nPropertyId] )
+ {
+ const SfxItemPropertyMapEntry* pEntries = GetPropertyMapEntries(nPropertyId);
+ switch( nPropertyId )
+ {
+ case PROPERTY_MAP_TEXT_CURSOR:
+ {
+ static SfxItemPropertySet aPROPERTY_MAP_TEXT_CURSOR(pEntries);
+ aPropertySetArr[nPropertyId] = &aPROPERTY_MAP_TEXT_CURSOR;
+ }
+ break;
+ case PROPERTY_MAP_CHAR_STYLE:
+ {
+ static SfxItemPropertySet aPROPERTY_MAP_CHAR_STYLE(pEntries);
+ aPropertySetArr[nPropertyId] = &aPROPERTY_MAP_CHAR_STYLE;
+ }
+ break;
+ case PROPERTY_MAP_PARA_STYLE:
+ {
+ static SfxItemPropertySet aPROPERTY_MAP_PARA_STYLE(pEntries);
+ aPropertySetArr[nPropertyId] = &aPROPERTY_MAP_PARA_STYLE;
+ }
+ break;
+ case PROPERTY_MAP_FRAME_STYLE:
+ {
+ static SfxItemPropertySet aPROPERTY_MAP_FRAME_STYLE(pEntries);
+ aPropertySetArr[nPropertyId] = &aPROPERTY_MAP_FRAME_STYLE;
+ }
+ break;
+ case PROPERTY_MAP_PAGE_STYLE:
+ {
+ static SfxItemPropertySet aPROPERTY_MAP_PAGE_STYLE(pEntries);
+ aPropertySetArr[nPropertyId] = &aPROPERTY_MAP_PAGE_STYLE;
+ }
+ break;
+ case PROPERTY_MAP_NUM_STYLE:
+ {
+ static SfxItemPropertySet aPROPERTY_MAP_NUM_STYLE(pEntries);
+ aPropertySetArr[nPropertyId] = &aPROPERTY_MAP_NUM_STYLE;
+ }
+ break;
+ case PROPERTY_MAP_SECTION:
+ {
+ static SfxItemPropertySet aPROPERTY_MAP_SECTION(pEntries);
+ aPropertySetArr[nPropertyId] = &aPROPERTY_MAP_SECTION;
+ }
+ break;
+ case PROPERTY_MAP_TEXT_TABLE:
+ {
+ static SfxItemPropertySet aPROPERTY_MAP_TEXT_TABLE(pEntries);
+ aPropertySetArr[nPropertyId] = &aPROPERTY_MAP_TEXT_TABLE;
+ }
+ break;
+ case PROPERTY_MAP_TABLE_CELL:
+ {
+ static SfxItemPropertySet aPROPERTY_MAP_TABLE_CELL(pEntries);
+ aPropertySetArr[nPropertyId] = &aPROPERTY_MAP_TABLE_CELL;
+ }
+ break;
+ case PROPERTY_MAP_TABLE_RANGE:
+ {
+ static SfxItemPropertySet aPROPERTY_MAP_TABLE_RANGE(pEntries);
+ aPropertySetArr[nPropertyId] = &aPROPERTY_MAP_TABLE_RANGE;
+ }
+ break;
+ case PROPERTY_MAP_TEXT_SEARCH:
+ {
+ static SfxItemPropertySet aPROPERTY_MAP_TEXT_SEARCH(pEntries);
+ aPropertySetArr[nPropertyId] = &aPROPERTY_MAP_TEXT_SEARCH;
+ }
+ break;
+ case PROPERTY_MAP_TEXT_FRAME:
+ {
+ static SfxItemPropertySet aPROPERTY_MAP_TEXT_FRAME(pEntries);
+ aPropertySetArr[nPropertyId] = &aPROPERTY_MAP_TEXT_FRAME;
+ }
+ break;
+ case PROPERTY_MAP_TEXT_GRAPHIC:
+ {
+ static SfxItemPropertySet aPROPERTY_MAP_TEXT_GRAPHIC(pEntries);
+ aPropertySetArr[nPropertyId] = &aPROPERTY_MAP_TEXT_GRAPHIC;
+ }
+ break;
+ case PROPERTY_MAP_TEXT_SHAPE:
+ {
+ static SfxItemPropertySet aPROPERTY_MAP_TEXT_SHAPE(pEntries);
+ aPropertySetArr[nPropertyId] = &aPROPERTY_MAP_TEXT_SHAPE;
+ }
+ break;
+ case PROPERTY_MAP_INDEX_USER:
+ {
+ static SfxItemPropertySet aPROPERTY_MAP_INDEX_USER(pEntries);
+ aPropertySetArr[nPropertyId] = &aPROPERTY_MAP_INDEX_USER;
+ }
+ break;
+ case PROPERTY_MAP_INDEX_CNTNT:
+ {
+ static SfxItemPropertySet aPROPERTY_MAP_INDEX_CNTNT(pEntries);
+ aPropertySetArr[nPropertyId] = &aPROPERTY_MAP_INDEX_CNTNT;
+ }
+ break;
+ case PROPERTY_MAP_INDEX_IDX:
+ {
+ static SfxItemPropertySet aPROPERTY_MAP_INDEX_IDX(pEntries);
+ aPropertySetArr[nPropertyId] = &aPROPERTY_MAP_INDEX_IDX;
+ }
+ break;
+ case PROPERTY_MAP_USER_MARK:
+ {
+ static SfxItemPropertySet aPROPERTY_MAP_USER_MARK(pEntries);
+ aPropertySetArr[nPropertyId] = &aPROPERTY_MAP_USER_MARK;
+ }
+ break;
+ case PROPERTY_MAP_CNTIDX_MARK:
+ {
+ static SfxItemPropertySet aPROPERTY_MAP_CNTIDX_MARK(pEntries);
+ aPropertySetArr[nPropertyId] = &aPROPERTY_MAP_CNTIDX_MARK;
+ }
+ break;
+ case PROPERTY_MAP_INDEX_MARK:
+ {
+ static SfxItemPropertySet aPROPERTY_MAP_INDEX_MARK(pEntries);
+ aPropertySetArr[nPropertyId] = &aPROPERTY_MAP_INDEX_MARK;
+ }
+ break;
+ case PROPERTY_MAP_TEXT_TABLE_ROW:
+ {
+ static SfxItemPropertySet aPROPERTY_MAP_TEXT_TABLE_ROW(pEntries);
+ aPropertySetArr[nPropertyId] = &aPROPERTY_MAP_TEXT_TABLE_ROW;
+ }
+ break;
+ case PROPERTY_MAP_TEXT_SHAPE_DESCRIPTOR:
+ {
+ static SfxItemPropertySet aPROPERTY_MAP_TEXT_SHAPE_DESCRIPTOR(pEntries);
+ aPropertySetArr[nPropertyId] = &aPROPERTY_MAP_TEXT_SHAPE_DESCRIPTOR;
+ }
+ break;
+ case PROPERTY_MAP_TEXT_TABLE_CURSOR:
+ {
+ static SfxItemPropertySet aPROPERTY_MAP_TEXT_TABLE_CURSOR(pEntries);
+ aPropertySetArr[nPropertyId] = &aPROPERTY_MAP_TEXT_TABLE_CURSOR;
+ }
+ break;
+ case PROPERTY_MAP_BOOKMARK:
+ {
+ static SfxItemPropertySet aPROPERTY_MAP_BOOKMARK(pEntries);
+ aPropertySetArr[nPropertyId] = &aPROPERTY_MAP_BOOKMARK;
+ }
+ break;
+ case PROPERTY_MAP_PARAGRAPH_EXTENSIONS:
+ {
+ static SfxItemPropertySet aPROPERTY_MAP_PARAGRAPH_EXTENSIONS(pEntries);
+ aPropertySetArr[nPropertyId] = &aPROPERTY_MAP_PARAGRAPH_EXTENSIONS;
+ }
+ break;
+ case PROPERTY_MAP_INDEX_ILLUSTRATIONS:
+ {
+ static SfxItemPropertySet aPROPERTY_MAP_INDEX_ILLUSTRATIONS(pEntries);
+ aPropertySetArr[nPropertyId] = &aPROPERTY_MAP_INDEX_ILLUSTRATIONS;
+ }
+ break;
+ case PROPERTY_MAP_INDEX_OBJECTS:
+ {
+ static SfxItemPropertySet aPROPERTY_MAP_INDEX_OBJECTS(pEntries);
+ aPropertySetArr[nPropertyId] = &aPROPERTY_MAP_INDEX_OBJECTS;
+ }
+ break;
+ case PROPERTY_MAP_INDEX_TABLES:
+ {
+ static SfxItemPropertySet aPROPERTY_MAP_INDEX_TABLES(pEntries);
+ aPropertySetArr[nPropertyId] = &aPROPERTY_MAP_INDEX_TABLES;
+ }
+ break;
+ case PROPERTY_MAP_BIBLIOGRAPHY :
+ {
+ static SfxItemPropertySet aPROPERTY_MAP_BIBLIOGRAPHY(pEntries);
+ aPropertySetArr[nPropertyId] = &aPROPERTY_MAP_BIBLIOGRAPHY;
+ }
+ break;
+ case PROPERTY_MAP_TEXT_DOCUMENT:
+ {
+ static SfxItemPropertySet aPROPERTY_MAP_TEXT_DOCUMENT(pEntries);
+ aPropertySetArr[nPropertyId] = &aPROPERTY_MAP_TEXT_DOCUMENT;
+ }
+ break;
+ case PROPERTY_MAP_LINK_TARGET :
+ {
+ static SfxItemPropertySet aPROPERTY_MAP_LINK_TARGET(pEntries);
+ aPropertySetArr[nPropertyId] = &aPROPERTY_MAP_LINK_TARGET;
+ }
+ break;
+ case PROPERTY_MAP_AUTO_TEXT_GROUP :
+ {
+ static SfxItemPropertySet aPROPERTY_MAP_AUTO_TEXT_GROUP(pEntries);
+ aPropertySetArr[nPropertyId] = &aPROPERTY_MAP_AUTO_TEXT_GROUP;
+ }
+ break;
+ case PROPERTY_MAP_TEXTPORTION_EXTENSIONS :
+ {
+ static SfxItemPropertySet aPROPERTY_MAP_TEXTPORTION_EXTENSIONS(pEntries);
+ aPropertySetArr[nPropertyId] = &aPROPERTY_MAP_TEXTPORTION_EXTENSIONS;
+ }
+ break;
+ case PROPERTY_MAP_FOOTNOTE :
+ {
+ static SfxItemPropertySet aPROPERTY_MAP_FOOTNOTE(pEntries);
+ aPropertySetArr[nPropertyId] = &aPROPERTY_MAP_FOOTNOTE;
+ }
+ break;
+ case PROPERTY_MAP_TEXT_COLUMS :
+ {
+ static SfxItemPropertySet aPROPERTY_MAP_TEXT_COLUMS(pEntries);
+ aPropertySetArr[nPropertyId] = &aPROPERTY_MAP_TEXT_COLUMS;
+ }
+ break;
+ case PROPERTY_MAP_PARAGRAPH :
+ {
+ static SfxItemPropertySet aPROPERTY_MAP_PARAGRAPH(pEntries);
+ aPropertySetArr[nPropertyId] = &aPROPERTY_MAP_PARAGRAPH;
+ }
+ break;
+ case PROPERTY_MAP_EMBEDDED_OBJECT :
+ {
+ static SfxItemPropertySet aPROPERTY_MAP_EMBEDDED_OBJECT(pEntries);
+ aPropertySetArr[nPropertyId] = &aPROPERTY_MAP_EMBEDDED_OBJECT;
+ }
+ break;
+ case PROPERTY_MAP_REDLINE :
+ {
+ static SfxItemPropertySet aPROPERTY_MAP_REDLINE(pEntries);
+ aPropertySetArr[nPropertyId] = &aPROPERTY_MAP_REDLINE;
+ }
+ break;
+ case PROPERTY_MAP_TEXT_DEFAULT :
+ {
+ static SfxItemPropertySet aPROPERTY_MAP_TEXT_DEFAULT(pEntries);
+ aPropertySetArr[nPropertyId] = &aPROPERTY_MAP_TEXT_DEFAULT;
+ }
+ break;
+ case PROPERTY_MAP_FLDTYP_DATETIME:
+ {
+ static SfxItemPropertySet aPROPERTY_MAP_FLDTYP_DATETIME(pEntries);
+ aPropertySetArr[nPropertyId] = &aPROPERTY_MAP_FLDTYP_DATETIME;
+ }
+ break;
+ case PROPERTY_MAP_FLDTYP_USER:
+ {
+ static SfxItemPropertySet aPROPERTY_MAP_FLDTYP_USER(pEntries);
+ aPropertySetArr[nPropertyId] = &aPROPERTY_MAP_FLDTYP_USER;
+ }
+ break;
+ case PROPERTY_MAP_FLDTYP_SET_EXP:
+ {
+ static SfxItemPropertySet aPROPERTY_MAP_FLDTYP_SET_EXP(pEntries);
+ aPropertySetArr[nPropertyId] = &aPROPERTY_MAP_FLDTYP_SET_EXP;
+ }
+ break;
+ case PROPERTY_MAP_FLDTYP_GET_EXP:
+ {
+ static SfxItemPropertySet aPROPERTY_MAP_FLDTYP_GET_EXP(pEntries);
+ aPropertySetArr[nPropertyId] = &aPROPERTY_MAP_FLDTYP_GET_EXP;
+ }
+ break;
+ case PROPERTY_MAP_FLDTYP_FILE_NAME:
+ {
+ static SfxItemPropertySet aPROPERTY_MAP_FLDTYP_FILE_NAME(pEntries);
+ aPropertySetArr[nPropertyId] = &aPROPERTY_MAP_FLDTYP_FILE_NAME;
+ }
+ break;
+ case PROPERTY_MAP_FLDTYP_PAGE_NUM:
+ {
+ static SfxItemPropertySet aPROPERTY_MAP_FLDTYP_PAGE_NUM(pEntries);
+ aPropertySetArr[nPropertyId] = &aPROPERTY_MAP_FLDTYP_PAGE_NUM;
+ }
+ break;
+ case PROPERTY_MAP_FLDTYP_AUTHOR:
+ {
+ static SfxItemPropertySet aPROPERTY_MAP_FLDTYP_AUTHOR(pEntries);
+ aPropertySetArr[nPropertyId] = &aPROPERTY_MAP_FLDTYP_AUTHOR;
+ }
+ break;
+ case PROPERTY_MAP_FLDTYP_CHAPTER:
+ {
+ static SfxItemPropertySet aPROPERTY_MAP_FLDTYP_CHAPTER(pEntries);
+ aPropertySetArr[nPropertyId] = &aPROPERTY_MAP_FLDTYP_CHAPTER;
+ }
+ break;
+ case PROPERTY_MAP_FLDTYP_GET_REFERENCE:
+ {
+ static SfxItemPropertySet aPROPERTY_MAP_FLDTYP_GET_REFERENCE(pEntries);
+ aPropertySetArr[nPropertyId] = &aPROPERTY_MAP_FLDTYP_GET_REFERENCE;
+ }
+ break;
+ case PROPERTY_MAP_FLDTYP_CONDITIONED_TEXT:
+ {
+ static SfxItemPropertySet aPROPERTY_MAP_FLDTYP_CONDITIONED_TEXT(pEntries);
+ aPropertySetArr[nPropertyId] = &aPROPERTY_MAP_FLDTYP_CONDITIONED_TEXT;
+ }
+ break;
+ case PROPERTY_MAP_FLDTYP_HIDDEN_TEXT:
+ {
+ static SfxItemPropertySet aPROPERTY_MAP_FLDTYP_HIDDEN_TEXT(pEntries);
+ aPropertySetArr[nPropertyId] = &aPROPERTY_MAP_FLDTYP_HIDDEN_TEXT;
+ }
+ break;
+ case PROPERTY_MAP_FLDTYP_ANNOTATION :
+ {
+ static SfxItemPropertySet aPROPERTY_MAP_FLDTYP_ANNOTATION(pEntries);
+ aPropertySetArr[nPropertyId] = &aPROPERTY_MAP_FLDTYP_ANNOTATION;
+ }
+ break;
+ case PROPERTY_MAP_FLDTYP_INPUT:
+ {
+ static SfxItemPropertySet aPROPERTY_MAP_FLDTYP_INPUT(pEntries);
+ aPropertySetArr[nPropertyId] = &aPROPERTY_MAP_FLDTYP_INPUT;
+ }
+ break;
+ case PROPERTY_MAP_FLDTYP_MACRO:
+ {
+ static SfxItemPropertySet aPROPERTY_MAP_FLDTYP_MACRO(pEntries);
+ aPropertySetArr[nPropertyId] = &aPROPERTY_MAP_FLDTYP_MACRO;
+ }
+ break;
+ case PROPERTY_MAP_FLDTYP_DDE:
+ {
+ static SfxItemPropertySet aPROPERTY_MAP_FLDTYP_DDE(pEntries);
+ aPropertySetArr[nPropertyId] = &aPROPERTY_MAP_FLDTYP_DDE;
+ }
+ break;
+ case PROPERTY_MAP_FLDTYP_HIDDEN_PARA:
+ {
+ static SfxItemPropertySet aPROPERTY_MAP_FLDTYP_HIDDEN_PARA(pEntries);
+ aPropertySetArr[nPropertyId] = &aPROPERTY_MAP_FLDTYP_HIDDEN_PARA;
+ }
+ break;
+ case PROPERTY_MAP_FLDTYP_DOC_INFO :
+ {
+ static SfxItemPropertySet aPROPERTY_MAP_FLDTYP_DOC_INFO(pEntries);
+ aPropertySetArr[nPropertyId] = &aPROPERTY_MAP_FLDTYP_DOC_INFO;
+ }
+ break;
+ case PROPERTY_MAP_FLDTYP_TEMPLATE_NAME:
+ {
+ static SfxItemPropertySet aPROPERTY_MAP_FLDTYP_TEMPLATE_NAME(pEntries);
+ aPropertySetArr[nPropertyId] = &aPROPERTY_MAP_FLDTYP_TEMPLATE_NAME;
+ }
+ break;
+ case PROPERTY_MAP_FLDTYP_USER_EXT :
+ {
+ static SfxItemPropertySet aPROPERTY_MAP_FLDTYP_USER_EXT(pEntries);
+ aPropertySetArr[nPropertyId] = &aPROPERTY_MAP_FLDTYP_USER_EXT;
+ }
+ break;
+ case PROPERTY_MAP_FLDTYP_REF_PAGE_SET:
+ {
+ static SfxItemPropertySet aPROPERTY_MAP_FLDTYP_REF_PAGE_SET(pEntries);
+ aPropertySetArr[nPropertyId] = &aPROPERTY_MAP_FLDTYP_REF_PAGE_SET;
+ }
+ break;
+ case PROPERTY_MAP_FLDTYP_REF_PAGE_GET:
+ {
+ static SfxItemPropertySet aPROPERTY_MAP_FLDTYP_REF_PAGE_GET(pEntries);
+ aPropertySetArr[nPropertyId] = &aPROPERTY_MAP_FLDTYP_REF_PAGE_GET;
+ }
+ break;
+ case PROPERTY_MAP_FLDTYP_JUMP_EDIT:
+ {
+ static SfxItemPropertySet aPROPERTY_MAP_FLDTYP_JUMP_EDIT(pEntries);
+ aPropertySetArr[nPropertyId] = &aPROPERTY_MAP_FLDTYP_JUMP_EDIT;
+ }
+ break;
+ case PROPERTY_MAP_FLDTYP_SCRIPT:
+ {
+ static SfxItemPropertySet aPROPERTY_MAP_FLDTYP_SCRIPT(pEntries);
+ aPropertySetArr[nPropertyId] = &aPROPERTY_MAP_FLDTYP_SCRIPT;
+ }
+ break;
+ case PROPERTY_MAP_FLDTYP_DATABASE_NEXT_SET:
+ {
+ static SfxItemPropertySet aPROPERTY_MAP_FLDTYP_DATABASE_NEXT_SET(pEntries);
+ aPropertySetArr[nPropertyId] = &aPROPERTY_MAP_FLDTYP_DATABASE_NEXT_SET;
+ }
+ break;
+ case PROPERTY_MAP_FLDTYP_DATABASE_NUM_SET:
+ {
+ static SfxItemPropertySet aPROPERTY_MAP_FLDTYP_DATABASE_NUM_SET(pEntries);
+ aPropertySetArr[nPropertyId] = &aPROPERTY_MAP_FLDTYP_DATABASE_NUM_SET;
+ }
+ break;
+ case PROPERTY_MAP_FLDTYP_DATABASE_SET_NUM:
+ {
+ static SfxItemPropertySet aPROPERTY_MAP_FLDTYP_DATABASE_SET_NUM(pEntries);
+ aPropertySetArr[nPropertyId] = &aPROPERTY_MAP_FLDTYP_DATABASE_SET_NUM;
+ }
+ break;
+ case PROPERTY_MAP_FLDTYP_DATABASE:
+ {
+ static SfxItemPropertySet aPROPERTY_MAP_FLDTYP_DATABASE(pEntries);
+ aPropertySetArr[nPropertyId] = &aPROPERTY_MAP_FLDTYP_DATABASE;
+ }
+ break;
+ case PROPERTY_MAP_FLDTYP_DATABASE_NAME:
+ {
+ static SfxItemPropertySet aPROPERTY_MAP_FLDTYP_DATABASE_NAME(pEntries);
+ aPropertySetArr[nPropertyId] = &aPROPERTY_MAP_FLDTYP_DATABASE_NAME;
+ }
+ break;
+ case PROPERTY_MAP_FLDTYP_DOCSTAT:
+ {
+ static SfxItemPropertySet aPROPERTY_MAP_FLDTYP_DOCSTAT(pEntries);
+ aPropertySetArr[nPropertyId] = &aPROPERTY_MAP_FLDTYP_DOCSTAT;
+ }
+ break;
+ case PROPERTY_MAP_FLDTYP_DOCINFO_AUTHOR:
+ {
+ static SfxItemPropertySet aPROPERTY_MAP_FLDTYP_DOCINFO_AUTHOR(pEntries);
+ aPropertySetArr[nPropertyId] = &aPROPERTY_MAP_FLDTYP_DOCINFO_AUTHOR;
+ }
+ break;
+ case PROPERTY_MAP_FLDTYP_DOCINFO_DATE_TIME:
+ {
+ static SfxItemPropertySet aPROPERTY_MAP_FLDTYP_DOCINFO_DATE_TIME(pEntries);
+ aPropertySetArr[nPropertyId] = &aPROPERTY_MAP_FLDTYP_DOCINFO_DATE_TIME;
+ }
+ break;
+ case PROPERTY_MAP_FLDTYP_DOCINFO_CHANGE_DATE_TIME:
+ {
+ static SfxItemPropertySet aPROPERTY_MAP_FLDTYP_DOCINFO_CHANGE_DATE_TIME(pEntries);
+ aPropertySetArr[nPropertyId] = &aPROPERTY_MAP_FLDTYP_DOCINFO_CHANGE_DATE_TIME;
+ }
+ break;
+ case PROPERTY_MAP_FLDTYP_DOCINFO_CREATE_DATE_TIME:
+ {
+ static SfxItemPropertySet aPROPERTY_MAP_FLDTYP_DOCINFO_CREATE_DATE_TIME(pEntries);
+ aPropertySetArr[nPropertyId] = &aPROPERTY_MAP_FLDTYP_DOCINFO_CREATE_DATE_TIME;
+ }
+ break;
+ case PROPERTY_MAP_FLDTYP_DOCINFO_EDIT_TIME:
+ {
+ static SfxItemPropertySet aPROPERTY_MAP_FLDTYP_DOCINFO_EDIT_TIME(pEntries);
+ aPropertySetArr[nPropertyId] = &aPROPERTY_MAP_FLDTYP_DOCINFO_EDIT_TIME;
+ }
+ break;
+ case PROPERTY_MAP_FLDTYP_DOCINFO_MISC :
+ {
+ static SfxItemPropertySet aPROPERTY_MAP_FLDTYP_DOCINFO_MISC(pEntries);
+ aPropertySetArr[nPropertyId] = &aPROPERTY_MAP_FLDTYP_DOCINFO_MISC;
+ }
+ break;
+ case PROPERTY_MAP_FLDTYP_DOCINFO_REVISION:
+ {
+ static SfxItemPropertySet aPROPERTY_MAP_FLDTYP_DOCINFO_REVISION(pEntries);
+ aPropertySetArr[nPropertyId] = &aPROPERTY_MAP_FLDTYP_DOCINFO_REVISION;
+ }
+ break;
+ case PROPERTY_MAP_FLDTYP_COMBINED_CHARACTERS:
+ {
+ static SfxItemPropertySet aPROPERTY_MAP_FLDTYP_COMBINED_CHARACTERS(pEntries);
+ aPropertySetArr[nPropertyId] = &aPROPERTY_MAP_FLDTYP_COMBINED_CHARACTERS;
+ }
+ break;
+ case PROPERTY_MAP_FLDTYP_DUMMY_0:
+ {
+ static SfxItemPropertySet aPROPERTY_MAP_FLDTYP_DUMMY_0(pEntries);
+ aPropertySetArr[nPropertyId] = &aPROPERTY_MAP_FLDTYP_DUMMY_0;
+ }
+ break;
+ case PROPERTY_MAP_FLDTYP_TABLE_FORMULA:
+ {
+ static SfxItemPropertySet aPROPERTY_MAP_FLDTYP_TABLE_FORMULA(pEntries);
+ aPropertySetArr[nPropertyId] = &aPROPERTY_MAP_FLDTYP_TABLE_FORMULA;
+ }
+ break;
+ case PROPERTY_MAP_FLDMSTR_USER:
+ {
+ static SfxItemPropertySet aPROPERTY_MAP_FLDMSTR_USER(pEntries);
+ aPropertySetArr[nPropertyId] = &aPROPERTY_MAP_FLDMSTR_USER;
+ }
+ break;
+ case PROPERTY_MAP_FLDMSTR_DDE:
+ {
+ static SfxItemPropertySet aPROPERTY_MAP_FLDMSTR_DDE(pEntries);
+ aPropertySetArr[nPropertyId] = &aPROPERTY_MAP_FLDMSTR_DDE;
+ }
+ break;
+ case PROPERTY_MAP_FLDMSTR_SET_EXP:
+ {
+ static SfxItemPropertySet aPROPERTY_MAP_FLDMSTR_SET_EXP(pEntries);
+ aPropertySetArr[nPropertyId] = &aPROPERTY_MAP_FLDMSTR_SET_EXP;
+ }
+ break;
+ case PROPERTY_MAP_FLDMSTR_DATABASE:
+ {
+ static SfxItemPropertySet aPROPERTY_MAP_FLDMSTR_DATABASE(pEntries);
+ aPropertySetArr[nPropertyId] = &aPROPERTY_MAP_FLDMSTR_DATABASE;
+ }
+ break;
+ case PROPERTY_MAP_FLDMSTR_DUMMY0:
+ {
+ static SfxItemPropertySet aPROPERTY_MAP_FLDMSTR_DUMMY0(pEntries);
+ aPropertySetArr[nPropertyId] = &aPROPERTY_MAP_FLDMSTR_DUMMY0;
+ }
+ break;
+ case PROPERTY_MAP_FLDTYP_BIBLIOGRAPHY:
+ {
+ static SfxItemPropertySet aPROPERTY_MAP_FLDTYP_BIBLIOGRAPHY(pEntries);
+ aPropertySetArr[nPropertyId] = &aPROPERTY_MAP_FLDTYP_BIBLIOGRAPHY;
+ }
+ break;
+ case PROPERTY_MAP_FLDMSTR_BIBLIOGRAPHY:
+ {
+ static SfxItemPropertySet aPROPERTY_MAP_FLDMSTR_BIBLIOGRAPHY(pEntries);
+ aPropertySetArr[nPropertyId] = &aPROPERTY_MAP_FLDMSTR_BIBLIOGRAPHY;
+ }
+ break;
+ case PROPERTY_MAP_TEXT:
+ {
+ static SfxItemPropertySet aPROPERTY_MAP_TEXT(pEntries);
+ aPropertySetArr[nPropertyId] = &aPROPERTY_MAP_TEXT;
+ }
+ break;
+ case PROPERTY_MAP_REDLINE_PORTION:
+ {
+ static SfxItemPropertySet aPROPERTY_MAP_REDLINE_PORTION(pEntries);
+ aPropertySetArr[nPropertyId] = &aPROPERTY_MAP_REDLINE_PORTION;
+ }
+ break;
+ case PROPERTY_MAP_MAILMERGE:
+ {
+ static SfxItemPropertySet aPROPERTY_MAP_MAILMERGE(pEntries);
+ aPropertySetArr[nPropertyId] = &aPROPERTY_MAP_MAILMERGE;
+ }
+ break;
+ case PROPERTY_MAP_FLDTYP_DROPDOWN:
+ {
+ static SfxItemPropertySet aPROPERTY_MAP_FLDTYP_DROPDOWN(pEntries);
+ aPropertySetArr[nPropertyId] = &aPROPERTY_MAP_FLDTYP_DROPDOWN;
+ }
+ break;
+ case PROPERTY_MAP_CHART2_DATA_SEQUENCE:
+ {
+ static SfxItemPropertySet aPROPERTY_MAP_CHART2_DATA_SEQUENCE(pEntries);
+ aPropertySetArr[nPropertyId] = &aPROPERTY_MAP_CHART2_DATA_SEQUENCE;
+ }
+ break;
+ case PROPERTY_MAP_TEXT_VIEW:
+ {
+ static SfxItemPropertySet aPROPERTY_MAP_TEXT_VIEW(pEntries);
+ aPropertySetArr[nPropertyId] = &aPROPERTY_MAP_TEXT_VIEW;
+ }
+ break;
+ case PROPERTY_MAP_CONDITIONAL_PARA_STYLE:
+ {
+ static SfxItemPropertySet aPROPERTY_MAP_CONDITIONAL_PARA_STYLE(pEntries);
+ aPropertySetArr[nPropertyId] = &aPROPERTY_MAP_CONDITIONAL_PARA_STYLE;
+ }
+ break;
+ case PROPERTY_MAP_CHAR_AUTO_STYLE:
+ {
+ static SfxItemPropertySet aPROPERTY_MAP_CHAR_AUTO_STYLE(pEntries);
+ aPropertySetArr[nPropertyId] = &aPROPERTY_MAP_CHAR_AUTO_STYLE;
+ }
+ break;
+ case PROPERTY_MAP_RUBY_AUTO_STYLE:
+ {
+ static SfxItemPropertySet aPROPERTY_MAP_RUBY_AUTO_STYLE(pEntries);
+ aPropertySetArr[nPropertyId] = &aPROPERTY_MAP_RUBY_AUTO_STYLE;
+ }
+ break;
+ case PROPERTY_MAP_PARA_AUTO_STYLE:
+ {
+ static SfxItemPropertySet aPROPERTY_MAP_PARA_AUTO_STYLE(pEntries);
+ aPropertySetArr[nPropertyId] = &aPROPERTY_MAP_PARA_AUTO_STYLE;
+ }
+ break;
+ case PROPERTY_MAP_FLDTYP_DOCINFO_CUSTOM:
+ {
+ static SfxItemPropertySet aPROPERTY_MAP_FLDTYP_DOCINFO_CUSTOM(pEntries);
+ aPropertySetArr[nPropertyId] = &aPROPERTY_MAP_FLDTYP_DOCINFO_CUSTOM;
+ }
+ break;
+ case PROPERTY_MAP_METAFIELD:
+ {
+ static SfxItemPropertySet aPROPERTY_MAP_METAFIELD(pEntries);
+ aPropertySetArr[nPropertyId] = &aPROPERTY_MAP_METAFIELD;
+ }
+ break;
+ }
+ }
+ return aPropertySetArr[nPropertyId];
+}
+
+sal_Bool SwItemPropertySet::FillItem(SfxItemSet& /*rSet*/, sal_uInt16 /*nWhich*/, sal_Bool /*bGetProperty*/) const
+{
+ sal_Bool bRet = sal_False;
+ return bRet;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/unocore/unoobj.cxx b/sw/source/core/unocore/unoobj.cxx
new file mode 100644
index 000000000000..c73b565cc18e
--- /dev/null
+++ b/sw/source/core/unocore/unoobj.cxx
@@ -0,0 +1,2981 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+#include <com/sun/star/table/TableSortField.hpp>
+
+#include <osl/endian.h>
+#include <rtl/ustrbuf.hxx>
+#include <unotools/collatorwrapper.hxx>
+#include <swtypes.hxx>
+#include <hintids.hxx>
+#include <cmdid.h>
+#include <hints.hxx>
+#include <IMark.hxx>
+#include <frmfmt.hxx>
+#include <doc.hxx>
+#include <IDocumentUndoRedo.hxx>
+#include <istyleaccess.hxx>
+#include <ndtxt.hxx>
+#include <ndnotxt.hxx>
+#include <unocrsr.hxx>
+#include <unocrsrhelper.hxx>
+#include <swundo.hxx>
+#include <rootfrm.hxx>
+#include <flyfrm.hxx>
+#include <ftnidx.hxx>
+#include <sfx2/linkmgr.hxx>
+#include <docary.hxx>
+#include <paratr.hxx>
+#include <tools/urlobj.hxx>
+#include <pam.hxx>
+#include <tools/cachestr.hxx>
+#include <shellio.hxx>
+#include <swerror.h>
+#include <swtblfmt.hxx>
+#include <fmtruby.hxx>
+#include <docsh.hxx>
+#include <docstyle.hxx>
+#include <charfmt.hxx>
+#include <txtfld.hxx>
+#include <fmtfld.hxx>
+#include <fmtpdsc.hxx>
+#include <pagedesc.hxx>
+#include <poolfmt.hrc>
+#include <poolfmt.hxx>
+#include <edimp.hxx>
+#include <fchrfmt.hxx>
+#include <fmtautofmt.hxx>
+#include <cntfrm.hxx>
+#include <pagefrm.hxx>
+#include <doctxm.hxx>
+#include <sfx2/docfilt.hxx>
+#include <sfx2/docfile.hxx>
+#include <sfx2/fcontnr.hxx>
+#include <fmtrfmrk.hxx>
+#include <txtrfmrk.hxx>
+#include <unotextrange.hxx>
+#include <unotextcursor.hxx>
+#include <unomap.hxx>
+#include <unosett.hxx>
+#include <unoprnms.hxx>
+#include <unotbl.hxx>
+#include <unodraw.hxx>
+#include <unocoll.hxx>
+#include <unostyle.hxx>
+#include <unofield.hxx>
+#include <unometa.hxx>
+#include <fmtanchr.hxx>
+#include <editeng/flstitem.hxx>
+#include <svtools/ctrltool.hxx>
+#include <flypos.hxx>
+#include <txtftn.hxx>
+#include <fmtftn.hxx>
+#include <com/sun/star/text/WrapTextMode.hpp>
+#include <com/sun/star/text/TextContentAnchorType.hpp>
+#include <com/sun/star/style/PageStyleLayout.hpp>
+#include <com/sun/star/text/XTextDocument.hpp>
+#include <com/sun/star/style/XStyleFamiliesSupplier.hpp>
+#include <com/sun/star/drawing/XDrawPageSupplier.hpp>
+#include <unoidx.hxx>
+#include <unoframe.hxx>
+#include <fmthdft.hxx>
+#include <osl/mutex.hxx>
+#include <vcl/svapp.hxx>
+#include <fmtflcnt.hxx>
+#define _SVSTDARR_USHORTS
+#define _SVSTDARR_USHORTSSORT
+#include <svl/svstdarr.hxx>
+#include <editeng/brshitem.hxx>
+#include <editeng/unolingu.hxx>
+#include <fmtclds.hxx>
+#include <dcontact.hxx>
+#include <SwStyleNameMapper.hxx>
+#include <crsskip.hxx>
+#include <sortopt.hxx>
+#include <com/sun/star/beans/PropertyAttribute.hpp>
+#include <memory>
+#include <unoparaframeenum.hxx>
+#include <unoparagraph.hxx>
+
+
+using namespace ::com::sun::star;
+using ::rtl::OUString;
+using ::rtl::OUStringBuffer;
+
+/****************************************************************************
+ static methods
+****************************************************************************/
+uno::Sequence< sal_Int8 > CreateUnoTunnelId()
+{
+ static osl::Mutex aCreateMutex;
+ osl::Guard<osl::Mutex> aGuard( aCreateMutex );
+ uno::Sequence< sal_Int8 > aSeq( 16 );
+ rtl_createUuid( (sal_uInt8*)aSeq.getArray(), 0, sal_True );
+ return aSeq;
+}
+
+/****************************************************************************
+ Hilfsklassen
+****************************************************************************/
+SwUnoInternalPaM::SwUnoInternalPaM(SwDoc& rDoc) :
+ SwPaM(rDoc.GetNodes())
+{
+}
+
+SwUnoInternalPaM::~SwUnoInternalPaM()
+{
+ while( GetNext() != this)
+ {
+ delete GetNext();
+ }
+}
+
+SwUnoInternalPaM& SwUnoInternalPaM::operator=(const SwPaM& rPaM)
+{
+ const SwPaM* pTmp = &rPaM;
+ *GetPoint() = *rPaM.GetPoint();
+ if(rPaM.HasMark())
+ {
+ SetMark();
+ *GetMark() = *rPaM.GetMark();
+ }
+ else
+ DeleteMark();
+ while(&rPaM != (pTmp = (const SwPaM*)pTmp->GetNext()))
+ {
+ if(pTmp->HasMark())
+ new SwPaM(*pTmp->GetMark(), *pTmp->GetPoint(), this);
+ else
+ new SwPaM(*pTmp->GetPoint(), this);
+ }
+ return *this;
+}
+
+void SwUnoCursorHelper::SelectPam(SwPaM & rPam, const bool bExpand)
+{
+ if (bExpand)
+ {
+ if (!rPam.HasMark())
+ {
+ rPam.SetMark();
+ }
+ }
+ else if (rPam.HasMark())
+ {
+ rPam.DeleteMark();
+ }
+}
+
+void SwUnoCursorHelper::GetTextFromPam(SwPaM & rPam, OUString & rBuffer)
+{
+ if (!rPam.HasMark())
+ {
+ return;
+ }
+ SvCacheStream aStream( 20480 );
+#ifdef OSL_BIGENDIAN
+ aStream.SetNumberFormatInt( NUMBERFORMAT_INT_BIGENDIAN );
+#else
+ aStream.SetNumberFormatInt( NUMBERFORMAT_INT_LITTLEENDIAN );
+#endif
+ WriterRef xWrt;
+ // TODO/MBA: looks like a BaseURL doesn't make sense here
+ SwReaderWriter::GetWriter( C2S(FILTER_TEXT_DLG), String(), xWrt );
+ if( xWrt.Is() )
+ {
+ SwWriter aWriter( aStream, rPam );
+ xWrt->bASCII_NoLastLineEnd = sal_True;
+ xWrt->bExportPargraphNumbering = sal_False;
+ SwAsciiOptions aOpt = xWrt->GetAsciiOptions();
+ aOpt.SetCharSet( RTL_TEXTENCODING_UNICODE );
+ xWrt->SetAsciiOptions( aOpt );
+ xWrt->bUCS2_WithStartChar = sal_False;
+ // --> FME #i68522#
+ const sal_Bool bOldShowProgress = xWrt->bShowProgress;
+ xWrt->bShowProgress = sal_False;
+ // <--
+
+ long lLen;
+ if( !IsError( aWriter.Write( xWrt ) ) &&
+ 0x7ffffff > (( lLen = aStream.GetSize() )
+ / sizeof( sal_Unicode )) + 1 )
+ {
+ aStream << (sal_Unicode)'\0';
+
+ long lUniLen = (lLen / sizeof( sal_Unicode ));
+ ::rtl::OUStringBuffer aStrBuffer( lUniLen );
+ aStream.Seek( 0 );
+ aStream.ResetError();
+ while(lUniLen)
+ {
+ String sBuf;
+ sal_Int32 nLocalLen = 0;
+ if( lUniLen >= STRING_MAXLEN )
+ {
+ nLocalLen = STRING_MAXLEN - 1;
+ }
+ else
+ {
+ nLocalLen = lUniLen;
+ }
+ sal_Unicode *const pStrBuf =
+ sBuf.AllocBuffer( xub_StrLen( nLocalLen + 1));
+ aStream.Read( pStrBuf, 2 * nLocalLen );
+ pStrBuf[ nLocalLen ] = '\0';
+ aStrBuffer.append( pStrBuf, nLocalLen );
+ lUniLen -= nLocalLen;
+ }
+ rBuffer = aStrBuffer.makeStringAndClear();
+ }
+ xWrt->bShowProgress = bOldShowProgress;
+ }
+}
+
+static void
+lcl_setCharStyle(SwDoc *const pDoc, const uno::Any & rValue, SfxItemSet & rSet)
+throw (lang::IllegalArgumentException)
+{
+ SwDocShell *const pDocSh = pDoc->GetDocShell();
+ if(pDocSh)
+ {
+ OUString uStyle;
+ if (!(rValue >>= uStyle))
+ {
+ throw lang::IllegalArgumentException();
+ }
+ String sStyle;
+ SwStyleNameMapper::FillUIName(uStyle, sStyle,
+ nsSwGetPoolIdFromName::GET_POOLID_CHRFMT, sal_True);
+ SwDocStyleSheet *const pStyle = static_cast<SwDocStyleSheet*>(
+ pDocSh->GetStyleSheetPool()->Find(sStyle, SFX_STYLE_FAMILY_CHAR));
+ if (!pStyle)
+ {
+ throw lang::IllegalArgumentException();
+ }
+ const SwFmtCharFmt aFmt(pStyle->GetCharFmt());
+ rSet.Put(aFmt);
+ }
+};
+
+static void
+lcl_setAutoStyle(IStyleAccess & rStyleAccess, const uno::Any & rValue,
+ SfxItemSet & rSet, const bool bPara)
+throw (lang::IllegalArgumentException)
+{
+ OUString uStyle;
+ if (!(rValue >>= uStyle))
+ {
+ throw lang::IllegalArgumentException();
+ }
+ StylePool::SfxItemSet_Pointer_t pStyle = bPara ?
+ rStyleAccess.getByName(uStyle, IStyleAccess::AUTO_STYLE_PARA ):
+ rStyleAccess.getByName(uStyle, IStyleAccess::AUTO_STYLE_CHAR );
+ if(pStyle.get())
+ {
+ SwFmtAutoFmt aFmt( (bPara)
+ ? sal::static_int_cast< sal_uInt16 >(RES_AUTO_STYLE)
+ : sal::static_int_cast< sal_uInt16 >(RES_TXTATR_AUTOFMT) );
+ aFmt.SetStyleHandle( pStyle );
+ rSet.Put(aFmt);
+ }
+ else
+ {
+ throw lang::IllegalArgumentException();
+ }
+};
+
+void
+SwUnoCursorHelper::SetTxtFmtColl(const uno::Any & rAny, SwPaM & rPaM)
+throw (lang::IllegalArgumentException)
+{
+ SwDoc *const pDoc = rPaM.GetDoc();
+ SwDocShell *const pDocSh = pDoc->GetDocShell();
+ if(!pDocSh)
+ return;
+ OUString uStyle;
+ rAny >>= uStyle;
+ String sStyle;
+ SwStyleNameMapper::FillUIName(uStyle, sStyle,
+ nsSwGetPoolIdFromName::GET_POOLID_TXTCOLL, sal_True );
+ SwDocStyleSheet *const pStyle = static_cast<SwDocStyleSheet*>(
+ pDocSh->GetStyleSheetPool()->Find(sStyle, SFX_STYLE_FAMILY_PARA));
+ if (!pStyle)
+ {
+ throw lang::IllegalArgumentException();
+ }
+
+ SwTxtFmtColl *const pLocal = pStyle->GetCollection();
+ UnoActionContext aAction(pDoc);
+ pDoc->GetIDocumentUndoRedo().StartUndo( UNDO_START, NULL );
+ SwPaM *pTmpCrsr = &rPaM;
+ do {
+ pDoc->SetTxtFmtColl(*pTmpCrsr, pLocal);
+ pTmpCrsr = static_cast<SwPaM*>(pTmpCrsr->GetNext());
+ } while ( pTmpCrsr != &rPaM );
+ pDoc->GetIDocumentUndoRedo().EndUndo( UNDO_END, NULL );
+}
+
+bool
+SwUnoCursorHelper::SetPageDesc(
+ const uno::Any& rValue, SwDoc & rDoc, SfxItemSet & rSet)
+{
+ OUString uDescName;
+ if (!(rValue >>= uDescName))
+ {
+ return false;
+ }
+ ::std::auto_ptr<SwFmtPageDesc> pNewDesc;
+ const SfxPoolItem* pItem;
+ if(SFX_ITEM_SET == rSet.GetItemState( RES_PAGEDESC, sal_True, &pItem ) )
+ {
+ pNewDesc.reset(new SwFmtPageDesc(
+ *static_cast<const SwFmtPageDesc*>(pItem)));
+ }
+ if (!pNewDesc.get())
+ {
+ pNewDesc.reset(new SwFmtPageDesc());
+ }
+ String sDescName;
+ SwStyleNameMapper::FillUIName(uDescName, sDescName,
+ nsSwGetPoolIdFromName::GET_POOLID_PAGEDESC, sal_True);
+ if (!pNewDesc->GetPageDesc() ||
+ (pNewDesc->GetPageDesc()->GetName() != sDescName))
+ {
+ sal_Bool bPut = sal_False;
+ if(sDescName.Len())
+ {
+ SwPageDesc *const pPageDesc =
+ ::GetPageDescByName_Impl(rDoc, sDescName);
+ if (!pPageDesc)
+ {
+ throw lang::IllegalArgumentException();
+ }
+ pNewDesc.get()->RegisterToPageDesc( *pPageDesc );
+ bPut = sal_True;
+ }
+ if(!bPut)
+ {
+ rSet.ClearItem(RES_BREAK);
+ rSet.Put(SwFmtPageDesc());
+ }
+ else
+ {
+ rSet.Put(*pNewDesc);
+ }
+ }
+ return true;
+}
+
+static void
+lcl_SetNodeNumStart(SwPaM & rCrsr, uno::Any const& rValue)
+{
+ sal_Int16 nTmp = 1;
+ rValue >>= nTmp;
+ sal_uInt16 nStt = (nTmp < 0 ? USHRT_MAX : (sal_uInt16)nTmp);
+ SwDoc* pDoc = rCrsr.GetDoc();
+ UnoActionContext aAction(pDoc);
+
+ if( rCrsr.GetNext() != &rCrsr ) // Mehrfachselektion ?
+ {
+ pDoc->GetIDocumentUndoRedo().StartUndo( UNDO_START, NULL );
+ SwPamRanges aRangeArr( rCrsr );
+ SwPaM aPam( *rCrsr.GetPoint() );
+ for( sal_uInt16 n = 0; n < aRangeArr.Count(); ++n )
+ {
+ pDoc->SetNumRuleStart(*aRangeArr.SetPam( n, aPam ).GetPoint());
+ pDoc->SetNodeNumStart(*aRangeArr.SetPam( n, aPam ).GetPoint(),
+ nStt );
+ }
+ pDoc->GetIDocumentUndoRedo().EndUndo( UNDO_END, NULL );
+ }
+ else
+ {
+ pDoc->SetNumRuleStart( *rCrsr.GetPoint());
+ pDoc->SetNodeNumStart( *rCrsr.GetPoint(), nStt );
+ }
+}
+
+static bool
+lcl_setCharFmtSequence(SwPaM & rPam, uno::Any const& rValue)
+{
+ uno::Sequence<OUString> aCharStyles;
+ if (!(rValue >>= aCharStyles))
+ {
+ return false;
+ }
+
+ for (sal_Int32 nStyle = 0; nStyle < aCharStyles.getLength(); nStyle++)
+ {
+ uno::Any aStyle;
+ rPam.GetDoc()->GetIDocumentUndoRedo().StartUndo(UNDO_START, NULL);
+ aStyle <<= aCharStyles.getConstArray()[nStyle];
+ // create a local set and apply each format directly
+ SfxItemSet aSet(rPam.GetDoc()->GetAttrPool(),
+ RES_TXTATR_CHARFMT, RES_TXTATR_CHARFMT);
+ lcl_setCharStyle(rPam.GetDoc(), aStyle, aSet);
+ // the first style should replace the current attributes,
+ // all other have to be added
+ SwUnoCursorHelper::SetCrsrAttr(rPam, aSet, (nStyle)
+ ? nsSetAttrMode::SETATTR_DONTREPLACE
+ : nsSetAttrMode::SETATTR_DEFAULT);
+ rPam.GetDoc()->GetIDocumentUndoRedo().EndUndo(UNDO_START, NULL);
+ }
+ return true;
+}
+
+static void
+lcl_setDropcapCharStyle(SwPaM & rPam, SfxItemSet & rItemSet,
+ uno::Any const& rValue)
+{
+ OUString uStyle;
+ if (!(rValue >>= uStyle))
+ {
+ throw lang::IllegalArgumentException();
+ }
+ String sStyle;
+ SwStyleNameMapper::FillUIName(uStyle, sStyle,
+ nsSwGetPoolIdFromName::GET_POOLID_CHRFMT, sal_True);
+ SwDoc *const pDoc = rPam.GetDoc();
+ //default character style must not be set as default format
+ SwDocStyleSheet *const pStyle = static_cast<SwDocStyleSheet*>(
+ pDoc->GetDocShell()
+ ->GetStyleSheetPool()->Find(sStyle, SFX_STYLE_FAMILY_CHAR));
+ if (!pStyle ||
+ (static_cast<SwDocStyleSheet*>(pStyle)->GetCharFmt() ==
+ pDoc->GetDfltCharFmt()))
+ {
+ throw lang::IllegalArgumentException();
+ }
+ ::std::auto_ptr<SwFmtDrop> pDrop;
+ SfxPoolItem const* pItem(0);
+ if (SFX_ITEM_SET ==
+ rItemSet.GetItemState(RES_PARATR_DROP, sal_True, &pItem))
+ {
+ pDrop.reset(new SwFmtDrop(*static_cast<const SwFmtDrop*>(pItem)));
+ }
+ if (!pDrop.get())
+ {
+ pDrop.reset(new SwFmtDrop);
+ }
+ const rtl::Reference<SwDocStyleSheet> xStyle(new SwDocStyleSheet(*pStyle));
+ pDrop->SetCharFmt(xStyle->GetCharFmt());
+ rItemSet.Put(*pDrop);
+}
+
+static void
+lcl_setRubyCharstyle(SfxItemSet & rItemSet, uno::Any const& rValue)
+{
+ OUString sTmp;
+ if (!(rValue >>= sTmp))
+ {
+ throw lang::IllegalArgumentException();
+ }
+
+ ::std::auto_ptr<SwFmtRuby> pRuby;
+ const SfxPoolItem* pItem;
+ if (SFX_ITEM_SET ==
+ rItemSet.GetItemState(RES_TXTATR_CJK_RUBY, sal_True, &pItem))
+ {
+ pRuby.reset(new SwFmtRuby(*static_cast<const SwFmtRuby*>(pItem)));
+ }
+ if (!pRuby.get())
+ {
+ pRuby.reset(new SwFmtRuby(aEmptyStr));
+ }
+ String sStyle;
+ SwStyleNameMapper::FillUIName(sTmp, sStyle,
+ nsSwGetPoolIdFromName::GET_POOLID_CHRFMT, sal_True );
+ pRuby->SetCharFmtName(sStyle);
+ pRuby->SetCharFmtId(0);
+ if (sStyle.Len() > 0)
+ {
+ const sal_uInt16 nId = SwStyleNameMapper::GetPoolIdFromUIName(
+ sStyle, nsSwGetPoolIdFromName::GET_POOLID_CHRFMT);
+ pRuby->SetCharFmtId(nId);
+ }
+ rItemSet.Put(*pRuby);
+}
+
+bool
+SwUnoCursorHelper::SetCursorPropertyValue(
+ SfxItemPropertySimpleEntry const& rEntry, const uno::Any& rValue,
+ SwPaM & rPam, SfxItemSet & rItemSet)
+throw (lang::IllegalArgumentException)
+{
+ if (!(rEntry.nFlags & beans::PropertyAttribute::MAYBEVOID) &&
+ (rValue.getValueType() == ::getCppuVoidType()))
+ {
+ return false;
+ }
+ bool bRet = true;
+ switch (rEntry.nWID)
+ {
+ case RES_TXTATR_CHARFMT:
+ lcl_setCharStyle(rPam.GetDoc(), rValue, rItemSet);
+ break;
+ case RES_TXTATR_AUTOFMT:
+ lcl_setAutoStyle(rPam.GetDoc()->GetIStyleAccess(),
+ rValue, rItemSet, false);
+ break;
+ case FN_UNO_CHARFMT_SEQUENCE:
+ lcl_setCharFmtSequence(rPam, rValue);
+ break;
+ case FN_UNO_PARA_STYLE :
+ SwUnoCursorHelper::SetTxtFmtColl(rValue, rPam);
+ break;
+ case RES_AUTO_STYLE:
+ lcl_setAutoStyle(rPam.GetDoc()->GetIStyleAccess(),
+ rValue, rItemSet, true);
+ break;
+ case FN_UNO_PAGE_STYLE:
+ //FIXME nothing here?
+ break;
+ case FN_UNO_NUM_START_VALUE:
+ lcl_SetNodeNumStart( rPam, rValue );
+ break;
+ case FN_UNO_NUM_LEVEL:
+ // --> OD 2008-07-14 #i91601#
+ case FN_UNO_LIST_ID:
+ // <--
+ case FN_UNO_IS_NUMBER:
+ {
+ // multi selection is not considered
+ SwTxtNode *const pTxtNd = rPam.GetNode()->GetTxtNode();
+ if (FN_UNO_NUM_LEVEL == rEntry.nWID)
+ {
+ sal_Int16 nLevel = 0;
+ if (rValue >>= nLevel)
+ {
+ pTxtNd->SetAttrListLevel(nLevel);
+ }
+ }
+ // --> OD 2008-07-14 #i91601#
+ else if (FN_UNO_LIST_ID == rEntry.nWID)
+ {
+ ::rtl::OUString sListId;
+ if (rValue >>= sListId)
+ {
+ pTxtNd->SetListId( sListId );
+ }
+ }
+ // <--
+ else if (FN_UNO_IS_NUMBER == rEntry.nWID)
+ {
+ sal_Bool bIsNumber(sal_False);
+ if (rValue >>= bIsNumber)
+ {
+ if (!bIsNumber)
+ {
+ pTxtNd->SetCountedInList( false );
+ }
+ }
+ }
+ //PROPERTY_MAYBEVOID!
+ }
+ break;
+ case FN_NUMBER_NEWSTART:
+ {
+ sal_Bool bVal = sal_False;
+ if (!(rValue >>= bVal))
+ {
+ throw lang::IllegalArgumentException();
+ }
+ rPam.GetDoc()->SetNumRuleStart(*rPam.GetPoint(), bVal);
+ }
+ break;
+ case FN_UNO_NUM_RULES:
+ SwUnoCursorHelper::setNumberingProperty(rValue, rPam);
+ break;
+ case RES_PARATR_DROP:
+ {
+ if (MID_DROPCAP_CHAR_STYLE_NAME == rEntry.nMemberId)
+ {
+ lcl_setDropcapCharStyle(rPam, rItemSet, rValue);
+ }
+ else
+ {
+ bRet = false;
+ }
+ }
+ break;
+ case RES_TXTATR_CJK_RUBY:
+ {
+ if (MID_RUBY_CHARSTYLE == rEntry.nMemberId)
+ {
+ lcl_setRubyCharstyle(rItemSet, rValue);
+ }
+ else
+ {
+ bRet = false;
+ }
+ }
+ break;
+ case RES_PAGEDESC:
+ {
+ if (MID_PAGEDESC_PAGEDESCNAME == rEntry.nMemberId)
+ {
+ SwUnoCursorHelper::SetPageDesc(
+ rValue, *rPam.GetDoc(), rItemSet);
+ }
+ else
+ {
+ bRet = false;
+ }
+ }
+ break;
+ default:
+ bRet = false;
+ }
+ return bRet;
+}
+
+SwFmtColl *
+SwUnoCursorHelper::GetCurTxtFmtColl(SwPaM & rPaM, const bool bConditional)
+{
+ static const sal_uInt16 nMaxLookup = 1000;
+ SwFmtColl *pFmt = 0;
+
+// if ( GetCrsrCnt() > nMaxLookup )
+// return 0;
+ bool bError = false;
+ SwPaM *pTmpCrsr = &rPaM;
+ do
+ {
+ const sal_uLong nSttNd = pTmpCrsr->Start()->nNode.GetIndex();
+ const sal_uLong nEndNd = pTmpCrsr->End()->nNode.GetIndex();
+
+ if( nEndNd - nSttNd >= nMaxLookup )
+ {
+ pFmt = 0;
+ break;
+ }
+
+ const SwNodes& rNds = rPaM.GetDoc()->GetNodes();
+ for( sal_uLong n = nSttNd; n <= nEndNd; ++n )
+ {
+ SwTxtNode const*const pNd = rNds[ n ]->GetTxtNode();
+ if( pNd )
+ {
+ SwFmtColl *const pNdFmt = (bConditional)
+ ? pNd->GetFmtColl() : &pNd->GetAnyFmtColl();
+ if( !pFmt )
+ {
+ pFmt = pNdFmt;
+ }
+ else if( pFmt != pNdFmt )
+ {
+ bError = true;
+ break;
+ }
+ }
+ }
+
+ pTmpCrsr = static_cast<SwPaM*>(pTmpCrsr->GetNext());
+ } while ( pTmpCrsr != &rPaM );
+ return (bError) ? 0 : pFmt;
+}
+
+/* --------------------------------------------------
+ * Hilfsfunktion fuer PageDesc
+ * --------------------------------------------------*/
+SwPageDesc* GetPageDescByName_Impl(SwDoc& rDoc, const String& rName)
+{
+ SwPageDesc* pRet = 0;
+ sal_uInt16 nDCount = rDoc.GetPageDescCnt();
+ sal_uInt16 i;
+
+ for( i = 0; i < nDCount; i++ )
+ {
+ SwPageDesc* pDsc = &rDoc._GetPageDesc( i );
+ if(pDsc->GetName() == rName)
+ {
+ pRet = pDsc;
+ break;
+ }
+ }
+ if(!pRet)
+ {
+ for(i = RC_POOLPAGEDESC_BEGIN; i <= STR_POOLPAGE_LANDSCAPE; ++i)
+ {
+ const String aFmtName(SW_RES(i));
+ if(aFmtName == rName)
+ {
+ pRet = rDoc.GetPageDescFromPool( static_cast< sal_uInt16 >(
+ RES_POOLPAGE_BEGIN + i - RC_POOLPAGEDESC_BEGIN) );
+ break;
+ }
+ }
+ }
+
+ return pRet;
+ }
+
+/******************************************************************
+ * SwXTextCursor
+ ******************************************************************/
+class SwXTextCursor::Impl
+ : public SwClient
+{
+
+public:
+
+ const SfxItemPropertySet & m_rPropSet;
+ const enum CursorType m_eType;
+ const uno::Reference< text::XText > m_xParentText;
+ SwEventListenerContainer m_ListenerContainer;
+ bool m_bIsDisposed;
+
+ Impl( SwXTextCursor & rThis,
+ SwDoc & rDoc,
+ const enum CursorType eType,
+ uno::Reference<text::XText> xParent,
+ SwPosition const& rPoint, SwPosition const*const pMark)
+ : SwClient(rDoc.CreateUnoCrsr(rPoint, sal_False))
+ , m_rPropSet(*aSwMapProvider.GetPropertySet(PROPERTY_MAP_TEXT_CURSOR))
+ , m_eType(eType)
+ , m_xParentText(xParent)
+ , m_ListenerContainer(static_cast< ::cppu::OWeakObject* >(&rThis))
+ , m_bIsDisposed(false)
+ {
+ if (pMark)
+ {
+ GetCursor()->SetMark();
+ *GetCursor()->GetMark() = *pMark;
+ }
+ }
+
+ ~Impl() {
+ // Impl owns the cursor; delete it here: SolarMutex is locked
+ delete GetRegisteredIn();
+ }
+
+ SwUnoCrsr * GetCursor() {
+ return (m_bIsDisposed) ? 0 :
+ static_cast<SwUnoCrsr*>(const_cast<SwModify*>(GetRegisteredIn()));
+ }
+
+ SwUnoCrsr & GetCursorOrThrow() {
+ SwUnoCrsr *const pUnoCursor( GetCursor() );
+ if (!pUnoCursor) {
+ throw uno::RuntimeException(OUString(RTL_CONSTASCII_USTRINGPARAM(
+ "SwXTextCursor: disposed or invalid")), 0);
+ }
+ return *pUnoCursor;
+ }
+
+ void Invalidate() {
+ m_bIsDisposed = true;
+ m_ListenerContainer.Disposing();
+ }
+protected:
+ // SwClient
+ virtual void Modify(const SfxPoolItem *pOld, const SfxPoolItem *pNew);
+
+};
+
+void SwXTextCursor::Impl::Modify(const SfxPoolItem *pOld, const SfxPoolItem *pNew)
+{
+ ClientModify(this, pOld, pNew);
+
+ if (!GetRegisteredIn() ||
+ // if the cursor leaves its designated section, it becomes invalid
+ ((pOld != NULL) && (pOld->Which() == RES_UNOCURSOR_LEAVES_SECTION)))
+ {
+ Invalidate();
+ }
+}
+
+SwUnoCrsr const* SwXTextCursor::GetCursor() const
+{
+ return m_pImpl->GetCursor();
+}
+
+SwUnoCrsr * SwXTextCursor::GetCursor()
+{
+ return m_pImpl->GetCursor();
+}
+
+SwPaM const* SwXTextCursor::GetPaM() const
+{
+ return m_pImpl->GetCursor();
+}
+
+SwPaM * SwXTextCursor::GetPaM()
+{
+ return m_pImpl->GetCursor();
+}
+
+SwDoc const* SwXTextCursor::GetDoc() const
+{
+ return m_pImpl->GetCursor() ? m_pImpl->GetCursor()->GetDoc() : 0;
+}
+
+SwDoc * SwXTextCursor::GetDoc()
+{
+ return m_pImpl->GetCursor() ? m_pImpl->GetCursor()->GetDoc() : 0;
+}
+
+SwXTextCursor::SwXTextCursor(
+ SwDoc & rDoc,
+ uno::Reference< text::XText > const& xParent,
+ const enum CursorType eType,
+ const SwPosition& rPos,
+ SwPosition const*const pMark)
+ : m_pImpl( new SwXTextCursor::Impl(*this, rDoc, eType, xParent,
+ rPos, pMark ) )
+{
+}
+
+SwXTextCursor::SwXTextCursor(uno::Reference< text::XText > const& xParent,
+ SwPaM const& rSourceCursor, const enum CursorType eType)
+ : m_pImpl( new SwXTextCursor::Impl(*this, *rSourceCursor.GetDoc(), eType,
+ xParent, *rSourceCursor.GetPoint(),
+ rSourceCursor.HasMark() ? rSourceCursor.GetMark() : 0) )
+{
+}
+
+SwXTextCursor::~SwXTextCursor()
+{
+}
+
+void SwXTextCursor::DeleteAndInsert(const ::rtl::OUString& rText,
+ const bool bForceExpandHints)
+{
+ SwUnoCrsr *const pUnoCrsr = m_pImpl->GetCursor();
+ if(pUnoCrsr)
+ {
+ // Start/EndAction
+ SwDoc* pDoc = pUnoCrsr->GetDoc();
+ UnoActionContext aAction(pDoc);
+ const xub_StrLen nTxtLen = rText.getLength();
+ pDoc->GetIDocumentUndoRedo().StartUndo(UNDO_INSERT, NULL);
+ SwCursor * pCurrent = pUnoCrsr;
+ do
+ {
+ if (pCurrent->HasMark())
+ {
+ pDoc->DeleteAndJoin(*pCurrent);
+ }
+ if(nTxtLen)
+ {
+ const bool bSuccess(
+ SwUnoCursorHelper::DocInsertStringSplitCR(
+ *pDoc, *pCurrent, rText, bForceExpandHints ) );
+ DBG_ASSERT( bSuccess, "Doc->Insert(Str) failed." );
+ (void) bSuccess;
+
+ SwUnoCursorHelper::SelectPam(*pUnoCrsr, true);
+ pCurrent->Left(rText.getLength(),
+ CRSR_SKIP_CHARS, sal_False, sal_False);
+ }
+ pCurrent = static_cast<SwCursor *>(pCurrent->GetNext());
+ } while (pCurrent != pUnoCrsr);
+ pDoc->GetIDocumentUndoRedo().EndUndo(UNDO_INSERT, NULL);
+ }
+}
+
+enum ForceIntoMetaMode { META_CHECK_BOTH, META_INIT_START, META_INIT_END };
+
+static sal_Bool
+lcl_ForceIntoMeta(SwPaM & rCursor,
+ uno::Reference<text::XText> const & xParentText,
+ const enum ForceIntoMetaMode eMode)
+{
+ sal_Bool bRet( sal_True ); // means not forced in META_CHECK_BOTH
+ SwXMeta const * const pXMeta( dynamic_cast<SwXMeta*>(xParentText.get()) );
+ OSL_ENSURE(pXMeta, "no parent?");
+ if (!pXMeta)
+ throw uno::RuntimeException();
+ SwTxtNode * pTxtNode;
+ xub_StrLen nStart;
+ xub_StrLen nEnd;
+ const bool bSuccess( pXMeta->SetContentRange(pTxtNode, nStart, nEnd) );
+ OSL_ENSURE(bSuccess, "no pam?");
+ if (!bSuccess)
+ throw uno::RuntimeException();
+ // force the cursor back into the meta if it has moved outside
+ SwPosition start(*pTxtNode, nStart);
+ SwPosition end(*pTxtNode, nEnd);
+ switch (eMode)
+ {
+ case META_INIT_START:
+ *rCursor.GetPoint() = start;
+ break;
+ case META_INIT_END:
+ *rCursor.GetPoint() = end;
+ break;
+ case META_CHECK_BOTH:
+ if (*rCursor.Start() < start)
+ {
+ *rCursor.Start() = start;
+ bRet = sal_False;
+ }
+ if (*rCursor.End() > end)
+ {
+ *rCursor.End() = end;
+ bRet = sal_False;
+ }
+ break;
+ }
+ return bRet;
+}
+
+bool SwXTextCursor::IsAtEndOfMeta() const
+{
+ if (CURSOR_META == m_pImpl->m_eType)
+ {
+ SwUnoCrsr const * const pCursor( m_pImpl->GetCursor() );
+ SwXMeta const*const pXMeta(
+ dynamic_cast<SwXMeta*>(m_pImpl->m_xParentText.get()) );
+ OSL_ENSURE(pXMeta, "no meta?");
+ if (pCursor && pXMeta)
+ {
+ SwTxtNode * pTxtNode;
+ xub_StrLen nStart;
+ xub_StrLen nEnd;
+ const bool bSuccess(
+ pXMeta->SetContentRange(pTxtNode, nStart, nEnd) );
+ OSL_ENSURE(bSuccess, "no pam?");
+ if (bSuccess)
+ {
+ const SwPosition end(*pTxtNode, nEnd);
+ if ( (*pCursor->GetPoint() == end)
+ || (*pCursor->GetMark() == end))
+ {
+ return true;
+ }
+ }
+ }
+ }
+ return false;
+}
+
+OUString SwXTextCursor::getImplementationName() throw (uno::RuntimeException)
+{
+ return C2U("SwXTextCursor");
+}
+
+static char const*const g_ServicesTextCursor[] =
+{
+ "com.sun.star.text.TextCursor",
+ "com.sun.star.style.CharacterProperties",
+ "com.sun.star.style.CharacterPropertiesAsian",
+ "com.sun.star.style.CharacterPropertiesComplex",
+ "com.sun.star.style.ParagraphProperties",
+ "com.sun.star.style.ParagraphPropertiesAsian",
+ "com.sun.star.style.ParagraphPropertiesComplex",
+ "com.sun.star.text.TextSortable",
+};
+
+static const size_t g_nServicesTextCursor(
+ SAL_N_ELEMENTS(g_ServicesTextCursor));
+
+sal_Bool SAL_CALL SwXTextCursor::supportsService(const OUString& rServiceName)
+throw (uno::RuntimeException)
+{
+ return ::sw::SupportsServiceImpl(
+ g_nServicesTextCursor, g_ServicesTextCursor, rServiceName);
+}
+
+uno::Sequence< OUString > SAL_CALL
+SwXTextCursor::getSupportedServiceNames() throw (uno::RuntimeException)
+{
+ return ::sw::GetSupportedServiceNamesImpl(
+ g_nServicesTextCursor, g_ServicesTextCursor);
+}
+
+const uno::Sequence< sal_Int8 > & SwXTextCursor::getUnoTunnelId()
+{
+ static uno::Sequence< sal_Int8 > aSeq = ::CreateUnoTunnelId();
+ return aSeq;
+}
+
+sal_Int64 SAL_CALL
+SwXTextCursor::getSomething(const uno::Sequence< sal_Int8 >& rId)
+throw (uno::RuntimeException)
+{
+ const sal_Int64 nRet( ::sw::UnoTunnelImpl<SwXTextCursor>(rId, this) );
+ return (nRet) ? nRet : OTextCursorHelper::getSomething(rId);
+}
+
+void SAL_CALL SwXTextCursor::collapseToStart() throw (uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+
+ SwUnoCrsr & rUnoCursor( m_pImpl->GetCursorOrThrow() );
+
+ if (rUnoCursor.HasMark())
+ {
+ if (*rUnoCursor.GetPoint() > *rUnoCursor.GetMark())
+ {
+ rUnoCursor.Exchange();
+ }
+ rUnoCursor.DeleteMark();
+ }
+}
+
+void SAL_CALL SwXTextCursor::collapseToEnd() throw (uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+
+ SwUnoCrsr & rUnoCursor( m_pImpl->GetCursorOrThrow() );
+
+ if (rUnoCursor.HasMark())
+ {
+ if (*rUnoCursor.GetPoint() < *rUnoCursor.GetMark())
+ {
+ rUnoCursor.Exchange();
+ }
+ rUnoCursor.DeleteMark();
+ }
+}
+
+sal_Bool SAL_CALL SwXTextCursor::isCollapsed() throw (uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+
+ sal_Bool bRet = sal_True;
+ SwUnoCrsr *const pUnoCrsr = m_pImpl->GetCursor();
+ if(pUnoCrsr && pUnoCrsr->GetMark())
+ {
+ bRet = (*pUnoCrsr->GetPoint() == *pUnoCrsr->GetMark());
+ }
+ return bRet;
+}
+
+sal_Bool SAL_CALL
+SwXTextCursor::goLeft(sal_Int16 nCount, sal_Bool Expand)
+throw (uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+
+ SwUnoCrsr & rUnoCursor( m_pImpl->GetCursorOrThrow() );
+
+ SwUnoCursorHelper::SelectPam(rUnoCursor, Expand);
+ sal_Bool bRet = rUnoCursor.Left( nCount, CRSR_SKIP_CHARS, sal_False, sal_False);
+ if (CURSOR_META == m_pImpl->m_eType)
+ {
+ bRet = lcl_ForceIntoMeta(rUnoCursor, m_pImpl->m_xParentText,
+ META_CHECK_BOTH)
+ && bRet;
+ }
+ return bRet;
+}
+
+sal_Bool SAL_CALL
+SwXTextCursor::goRight(sal_Int16 nCount, sal_Bool Expand)
+throw (uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+
+ SwUnoCrsr & rUnoCursor( m_pImpl->GetCursorOrThrow() );
+
+ SwUnoCursorHelper::SelectPam(rUnoCursor, Expand);
+ sal_Bool bRet = rUnoCursor.Right(nCount, CRSR_SKIP_CHARS, sal_False, sal_False);
+ if (CURSOR_META == m_pImpl->m_eType)
+ {
+ bRet = lcl_ForceIntoMeta(rUnoCursor, m_pImpl->m_xParentText,
+ META_CHECK_BOTH)
+ && bRet;
+ }
+ return bRet;
+}
+
+void SAL_CALL
+SwXTextCursor::gotoStart(sal_Bool Expand) throw (uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+
+ SwUnoCrsr & rUnoCursor( m_pImpl->GetCursorOrThrow() );
+
+ SwUnoCursorHelper::SelectPam(rUnoCursor, Expand);
+ if (CURSOR_BODY == m_pImpl->m_eType)
+ {
+ rUnoCursor.Move( fnMoveBackward, fnGoDoc );
+ //check, that the cursor is not in a table
+ SwTableNode * pTblNode = rUnoCursor.GetNode()->FindTableNode();
+ SwCntntNode * pCNode = 0;
+ while (pTblNode)
+ {
+ rUnoCursor.GetPoint()->nNode = *pTblNode->EndOfSectionNode();
+ pCNode = GetDoc()->GetNodes().GoNext(&rUnoCursor.GetPoint()->nNode);
+ pTblNode = (pCNode) ? pCNode->FindTableNode() : 0;
+ }
+ if (pCNode)
+ {
+ rUnoCursor.GetPoint()->nContent.Assign(pCNode, 0);
+ }
+ SwStartNode const*const pTmp =
+ rUnoCursor.GetNode()->StartOfSectionNode();
+ if (pTmp->IsSectionNode())
+ {
+ SwSectionNode const*const pSectionStartNode =
+ static_cast<SwSectionNode const*>(pTmp);
+ if (pSectionStartNode->GetSection().IsHiddenFlag())
+ {
+ pCNode = GetDoc()->GetNodes().GoNextSection(
+ &rUnoCursor.GetPoint()->nNode, sal_True, sal_False);
+ if (pCNode)
+ {
+ rUnoCursor.GetPoint()->nContent.Assign(pCNode, 0);
+ }
+ }
+ }
+ }
+ else if ( (CURSOR_FRAME == m_pImpl->m_eType)
+ || (CURSOR_TBLTEXT == m_pImpl->m_eType)
+ || (CURSOR_HEADER == m_pImpl->m_eType)
+ || (CURSOR_FOOTER == m_pImpl->m_eType)
+ || (CURSOR_FOOTNOTE== m_pImpl->m_eType)
+ || (CURSOR_REDLINE == m_pImpl->m_eType))
+ {
+ rUnoCursor.MoveSection(fnSectionCurr, fnSectionStart);
+ }
+ else if (CURSOR_META == m_pImpl->m_eType)
+ {
+ lcl_ForceIntoMeta(rUnoCursor, m_pImpl->m_xParentText, META_INIT_START);
+ }
+}
+
+void SAL_CALL
+SwXTextCursor::gotoEnd(sal_Bool Expand) throw (uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+
+ SwUnoCrsr & rUnoCursor( m_pImpl->GetCursorOrThrow() );
+
+ SwUnoCursorHelper::SelectPam(rUnoCursor, Expand);
+ if (CURSOR_BODY == m_pImpl->m_eType)
+ {
+ rUnoCursor.Move( fnMoveForward, fnGoDoc );
+ }
+ else if ( (CURSOR_FRAME == m_pImpl->m_eType)
+ || (CURSOR_TBLTEXT == m_pImpl->m_eType)
+ || (CURSOR_HEADER == m_pImpl->m_eType)
+ || (CURSOR_FOOTER == m_pImpl->m_eType)
+ || (CURSOR_FOOTNOTE== m_pImpl->m_eType)
+ || (CURSOR_REDLINE == m_pImpl->m_eType))
+ {
+ rUnoCursor.MoveSection( fnSectionCurr, fnSectionEnd);
+ }
+ else if (CURSOR_META == m_pImpl->m_eType)
+ {
+ lcl_ForceIntoMeta(rUnoCursor, m_pImpl->m_xParentText, META_INIT_END);
+ }
+}
+
+void SAL_CALL
+SwXTextCursor::gotoRange(
+ const uno::Reference< text::XTextRange > & xRange, sal_Bool bExpand)
+throw (uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+
+ if (!xRange.is())
+ {
+ throw uno::RuntimeException();
+ }
+
+ SwUnoCrsr & rOwnCursor( m_pImpl->GetCursorOrThrow() );
+
+ uno::Reference<lang::XUnoTunnel> xRangeTunnel( xRange, uno::UNO_QUERY);
+ SwXTextRange* pRange = 0;
+ OTextCursorHelper* pCursor = 0;
+ if(xRangeTunnel.is())
+ {
+ pRange = ::sw::UnoTunnelGetImplementation<SwXTextRange>(xRangeTunnel);
+ pCursor =
+ ::sw::UnoTunnelGetImplementation<OTextCursorHelper>(xRangeTunnel);
+ }
+
+ if (!pRange && !pCursor)
+ {
+ throw uno::RuntimeException();
+ }
+
+ SwStartNodeType eSearchNodeType = SwNormalStartNode;
+ switch (m_pImpl->m_eType)
+ {
+ case CURSOR_FRAME: eSearchNodeType = SwFlyStartNode; break;
+ case CURSOR_TBLTEXT: eSearchNodeType = SwTableBoxStartNode; break;
+ case CURSOR_FOOTNOTE: eSearchNodeType = SwFootnoteStartNode; break;
+ case CURSOR_HEADER: eSearchNodeType = SwHeaderStartNode; break;
+ case CURSOR_FOOTER: eSearchNodeType = SwFooterStartNode; break;
+ //case CURSOR_INVALID:
+ //case CURSOR_BODY:
+ default:
+ ;
+ }
+ const SwStartNode* pOwnStartNode =
+ rOwnCursor.GetNode()->FindSttNodeByType(eSearchNodeType);
+
+ SwPaM aPam(GetDoc()->GetNodes());
+ const SwPaM * pPam(0);
+ if (pCursor)
+ {
+ pPam = pCursor->GetPaM();
+ }
+ else if (pRange)
+ {
+ if (pRange->GetPositions(aPam))
+ {
+ pPam = & aPam;
+ }
+ }
+
+ if (!pPam)
+ {
+ throw uno::RuntimeException();
+ }
+ const SwStartNode* pTmp =
+ pPam->GetNode()->FindSttNodeByType(eSearchNodeType);
+
+ //SectionNodes ueberspringen
+ while(pTmp && pTmp->IsSectionNode())
+ {
+ pTmp = pTmp->StartOfSectionNode();
+ }
+ while(pOwnStartNode && pOwnStartNode->IsSectionNode())
+ {
+ pOwnStartNode = pOwnStartNode->StartOfSectionNode();
+ }
+ if(pOwnStartNode != pTmp)
+ {
+ throw uno::RuntimeException();
+ }
+
+ if (CURSOR_META == m_pImpl->m_eType)
+ {
+ SwPaM CopyPam(*pPam->GetMark(), *pPam->GetPoint());
+ const bool bNotForced( lcl_ForceIntoMeta(
+ CopyPam, m_pImpl->m_xParentText, META_CHECK_BOTH) );
+ if (!bNotForced)
+ {
+ throw uno::RuntimeException(
+ C2U("gotoRange: parameter range not contained in nesting"
+ " text content for which this cursor was created"),
+ static_cast<text::XWordCursor*>(this));
+ }
+ }
+
+ //jetzt muss die Selektion erweitert werden
+ if(bExpand)
+ {
+ // der Cursor soll alles einschliessen, was bisher von ihm und dem uebergebenen
+ // Range eingeschlossen wurde
+ const SwPosition aOwnLeft(*rOwnCursor.Start());
+ const SwPosition aOwnRight(*rOwnCursor.End());
+ SwPosition const& rParamLeft = *pPam->Start();
+ SwPosition const& rParamRight = *pPam->End();
+
+ // jetzt sind vier SwPositions da, zwei davon werden gebraucht, also welche?
+ *rOwnCursor.GetPoint() = (aOwnRight > rParamRight)
+ ? aOwnRight : *rOwnCursor.GetPoint() = rParamRight;
+ rOwnCursor.SetMark();
+ *rOwnCursor.GetMark() = (aOwnLeft < rParamLeft)
+ ? aOwnLeft : *rOwnCursor.GetMark() = rParamLeft;
+ }
+ else
+ {
+ // cursor should be the given range
+ *rOwnCursor.GetPoint() = *pPam->GetPoint();
+ if (pPam->HasMark())
+ {
+ rOwnCursor.SetMark();
+ *rOwnCursor.GetMark() = *pPam->GetMark();
+ }
+ else
+ {
+ rOwnCursor.DeleteMark();
+ }
+ }
+}
+
+sal_Bool SAL_CALL SwXTextCursor::isStartOfWord() throw (uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+
+ SwUnoCrsr & rUnoCursor( m_pImpl->GetCursorOrThrow() );
+
+ const sal_Bool bRet =
+ rUnoCursor.IsStartWordWT( i18n::WordType::DICTIONARY_WORD );
+ return bRet;
+}
+
+sal_Bool SAL_CALL SwXTextCursor::isEndOfWord() throw (uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+
+ SwUnoCrsr & rUnoCursor( m_pImpl->GetCursorOrThrow() );
+
+ const sal_Bool bRet =
+ rUnoCursor.IsEndWordWT( i18n::WordType::DICTIONARY_WORD );
+ return bRet;
+}
+
+sal_Bool SAL_CALL
+SwXTextCursor::gotoNextWord(sal_Bool Expand) throw (uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+
+ SwUnoCrsr & rUnoCursor( m_pImpl->GetCursorOrThrow() );
+
+ //Probleme gibt's noch mit einem Absatzanfang, an dem kein Wort beginnt.
+ sal_Bool bRet = sal_False;
+ // remember old position to check if cursor has moved
+ // since the called functions are sometimes a bit unreliable
+ // in specific cases...
+ SwPosition *const pPoint = rUnoCursor.GetPoint();
+ SwNode *const pOldNode = &pPoint->nNode.GetNode();
+ xub_StrLen const nOldIndex = pPoint->nContent.GetIndex();
+
+ SwUnoCursorHelper::SelectPam(rUnoCursor, Expand);
+ // end of paragraph
+ if (rUnoCursor.GetCntntNode() &&
+ (pPoint->nContent == rUnoCursor.GetCntntNode()->Len()))
+ {
+ rUnoCursor.Right(1, CRSR_SKIP_CHARS, sal_False, sal_False);
+ }
+ else
+ {
+ const bool bTmp =
+ rUnoCursor.GoNextWordWT( i18n::WordType::DICTIONARY_WORD );
+ // if there is no next word within the current paragraph
+ // try to go to the start of the next paragraph
+ if (!bTmp)
+ {
+ rUnoCursor.MovePara(fnParaNext, fnParaStart);
+ }
+ }
+
+ // return true if cursor has moved
+ bRet = (&pPoint->nNode.GetNode() != pOldNode) ||
+ (pPoint->nContent.GetIndex() != nOldIndex);
+ if (bRet && (CURSOR_META == m_pImpl->m_eType))
+ {
+ bRet = lcl_ForceIntoMeta(rUnoCursor, m_pImpl->m_xParentText,
+ META_CHECK_BOTH);
+ }
+
+ return bRet;
+}
+
+sal_Bool SAL_CALL
+SwXTextCursor::gotoPreviousWord(sal_Bool Expand) throw (uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+
+ SwUnoCrsr & rUnoCursor( m_pImpl->GetCursorOrThrow() );
+
+ // hier machen Leerzeichen am Absatzanfang Probleme
+ sal_Bool bRet = sal_False;
+ SwPosition *const pPoint = rUnoCursor.GetPoint();
+ SwNode *const pOldNode = &pPoint->nNode.GetNode();
+ xub_StrLen const nOldIndex = pPoint->nContent.GetIndex();
+
+ SwUnoCursorHelper::SelectPam(rUnoCursor, Expand);
+ // start of paragraph?
+ if (pPoint->nContent == 0)
+ {
+ rUnoCursor.Left(1, CRSR_SKIP_CHARS, sal_False, sal_False);
+ }
+ else
+ {
+ rUnoCursor.GoPrevWordWT( i18n::WordType::DICTIONARY_WORD );
+ if (pPoint->nContent == 0)
+ {
+ rUnoCursor.Left(1, CRSR_SKIP_CHARS, sal_False, sal_False);
+ }
+ }
+
+ // return true if cursor has moved
+ bRet = (&pPoint->nNode.GetNode() != pOldNode) ||
+ (pPoint->nContent.GetIndex() != nOldIndex);
+ if (bRet && (CURSOR_META == m_pImpl->m_eType))
+ {
+ bRet = lcl_ForceIntoMeta(rUnoCursor, m_pImpl->m_xParentText,
+ META_CHECK_BOTH);
+ }
+
+ return bRet;
+}
+
+sal_Bool SAL_CALL
+SwXTextCursor::gotoEndOfWord(sal_Bool Expand) throw (uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+
+ SwUnoCrsr & rUnoCursor( m_pImpl->GetCursorOrThrow() );
+
+ sal_Bool bRet = sal_False;
+ SwPosition *const pPoint = rUnoCursor.GetPoint();
+ SwNode & rOldNode = pPoint->nNode.GetNode();
+ xub_StrLen const nOldIndex = pPoint->nContent.GetIndex();
+
+ const sal_Int16 nWordType = i18n::WordType::DICTIONARY_WORD;
+ SwUnoCursorHelper::SelectPam(rUnoCursor, Expand);
+ if (!rUnoCursor.IsEndWordWT( nWordType ))
+ {
+ rUnoCursor.GoEndWordWT( nWordType );
+ }
+
+ // restore old cursor if we are not at the end of a word by now
+ // otherwise use current one
+ bRet = rUnoCursor.IsEndWordWT( nWordType );
+ if (!bRet)
+ {
+ pPoint->nNode = rOldNode;
+ pPoint->nContent = nOldIndex;
+ }
+ else if (CURSOR_META == m_pImpl->m_eType)
+ {
+ bRet = lcl_ForceIntoMeta(rUnoCursor, m_pImpl->m_xParentText,
+ META_CHECK_BOTH);
+ }
+
+ return bRet;
+}
+
+sal_Bool SAL_CALL
+SwXTextCursor::gotoStartOfWord(sal_Bool Expand) throw (uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+
+ SwUnoCrsr & rUnoCursor( m_pImpl->GetCursorOrThrow() );
+
+ sal_Bool bRet = sal_False;
+ SwPosition *const pPoint = rUnoCursor.GetPoint();
+ SwNode & rOldNode = pPoint->nNode.GetNode();
+ xub_StrLen const nOldIndex = pPoint->nContent.GetIndex();
+
+ const sal_Int16 nWordType = i18n::WordType::DICTIONARY_WORD;
+ SwUnoCursorHelper::SelectPam(rUnoCursor, Expand);
+ if (!rUnoCursor.IsStartWordWT( nWordType ))
+ {
+ rUnoCursor.GoStartWordWT( nWordType );
+ }
+
+ // restore old cursor if we are not at the start of a word by now
+ // otherwise use current one
+ bRet = rUnoCursor.IsStartWordWT( nWordType );
+ if (!bRet)
+ {
+ pPoint->nNode = rOldNode;
+ pPoint->nContent = nOldIndex;
+ }
+ else if (CURSOR_META == m_pImpl->m_eType)
+ {
+ bRet = lcl_ForceIntoMeta(rUnoCursor, m_pImpl->m_xParentText,
+ META_CHECK_BOTH);
+ }
+
+ return bRet;
+}
+
+sal_Bool SAL_CALL
+SwXTextCursor::isStartOfSentence() throw (uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+
+ SwUnoCrsr & rUnoCursor( m_pImpl->GetCursorOrThrow() );
+
+ // start of paragraph?
+ sal_Bool bRet = rUnoCursor.GetPoint()->nContent == 0;
+ // with mark ->no sentence start
+ // (check if cursor is no selection, i.e. it does not have
+ // a mark or else point and mark are identical)
+ if (!bRet && (!rUnoCursor.HasMark() ||
+ *rUnoCursor.GetPoint() == *rUnoCursor.GetMark()))
+ {
+ SwCursor aCrsr(*rUnoCursor.GetPoint(),0,false);
+ SwPosition aOrigPos = *aCrsr.GetPoint();
+ aCrsr.GoSentence(SwCursor::START_SENT );
+ bRet = aOrigPos == *aCrsr.GetPoint();
+ }
+ return bRet;
+}
+
+sal_Bool SAL_CALL
+SwXTextCursor::isEndOfSentence() throw (uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+
+ SwUnoCrsr & rUnoCursor( m_pImpl->GetCursorOrThrow() );
+
+ // end of paragraph?
+ sal_Bool bRet = rUnoCursor.GetCntntNode() &&
+ (rUnoCursor.GetPoint()->nContent == rUnoCursor.GetCntntNode()->Len());
+ // with mark->no sentence end
+ // (check if cursor is no selection, i.e. it does not have
+ // a mark or else point and mark are identical)
+ if (!bRet && (!rUnoCursor.HasMark() ||
+ *rUnoCursor.GetPoint() == *rUnoCursor.GetMark()))
+ {
+ SwCursor aCrsr(*rUnoCursor.GetPoint(), 0, false);
+ SwPosition aOrigPos = *aCrsr.GetPoint();
+ aCrsr.GoSentence(SwCursor::END_SENT);
+ bRet = aOrigPos == *aCrsr.GetPoint();
+ }
+ return bRet;
+}
+
+sal_Bool SAL_CALL
+SwXTextCursor::gotoNextSentence(sal_Bool Expand) throw (uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+
+ SwUnoCrsr & rUnoCursor( m_pImpl->GetCursorOrThrow() );
+
+ const bool bWasEOS = isEndOfSentence();
+ SwUnoCursorHelper::SelectPam(rUnoCursor, Expand);
+ sal_Bool bRet = rUnoCursor.GoSentence(SwCursor::NEXT_SENT);
+ if (!bRet)
+ {
+ bRet = rUnoCursor.MovePara(fnParaNext, fnParaStart);
+ }
+
+ // if at the end of the sentence (i.e. at the space after the '.')
+ // advance to next word in order for GoSentence to work properly
+ // next time and have isStartOfSentence return true after this call
+ if (!rUnoCursor.IsStartWord())
+ {
+ const bool bNextWord = rUnoCursor.GoNextWord();
+ if (bWasEOS && !bNextWord)
+ {
+ bRet = sal_False;
+ }
+ }
+ if (CURSOR_META == m_pImpl->m_eType)
+ {
+ bRet = lcl_ForceIntoMeta(rUnoCursor, m_pImpl->m_xParentText,
+ META_CHECK_BOTH)
+ && bRet;
+ }
+ return bRet;
+}
+
+sal_Bool SAL_CALL
+SwXTextCursor::gotoPreviousSentence(sal_Bool Expand)
+throw (uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+
+ SwUnoCrsr & rUnoCursor( m_pImpl->GetCursorOrThrow() );
+
+ SwUnoCursorHelper::SelectPam(rUnoCursor, Expand);
+ sal_Bool bRet = rUnoCursor.GoSentence(SwCursor::PREV_SENT);
+ if (!bRet)
+ {
+ bRet = rUnoCursor.MovePara(fnParaPrev, fnParaStart);
+ if (bRet)
+ {
+ rUnoCursor.MovePara(fnParaCurr, fnParaEnd);
+ // at the end of a paragraph move to the sentence end again
+ rUnoCursor.GoSentence(SwCursor::PREV_SENT);
+ }
+ }
+ if (CURSOR_META == m_pImpl->m_eType)
+ {
+ bRet = lcl_ForceIntoMeta(rUnoCursor, m_pImpl->m_xParentText,
+ META_CHECK_BOTH)
+ && bRet;
+ }
+ return bRet;
+}
+
+sal_Bool SAL_CALL
+SwXTextCursor::gotoStartOfSentence(sal_Bool Expand)
+throw (uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+
+ SwUnoCrsr & rUnoCursor( m_pImpl->GetCursorOrThrow() );
+
+ sal_Bool bRet = sal_False;
+ SwUnoCursorHelper::SelectPam(rUnoCursor, Expand);
+ // if we're at the para start then we wont move
+ // but bRet is also true if GoSentence failed but
+ // the start of the sentence is reached
+ bRet = SwUnoCursorHelper::IsStartOfPara(rUnoCursor)
+ || rUnoCursor.GoSentence(SwCursor::START_SENT)
+ || SwUnoCursorHelper::IsStartOfPara(rUnoCursor);
+ if (CURSOR_META == m_pImpl->m_eType)
+ {
+ bRet = lcl_ForceIntoMeta(rUnoCursor, m_pImpl->m_xParentText,
+ META_CHECK_BOTH)
+ && bRet;
+ }
+ return bRet;
+}
+
+sal_Bool SAL_CALL
+SwXTextCursor::gotoEndOfSentence(sal_Bool Expand) throw (uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+
+ SwUnoCrsr & rUnoCursor( m_pImpl->GetCursorOrThrow() );
+
+ sal_Bool bRet = sal_False;
+ SwUnoCursorHelper::SelectPam(rUnoCursor, Expand);
+ // bRet is true if GoSentence() succeeded or if the
+ // MovePara() succeeded while the end of the para is
+ // not reached already
+ sal_Bool bAlreadyParaEnd = SwUnoCursorHelper::IsEndOfPara(rUnoCursor);
+ bRet = !bAlreadyParaEnd
+ && (rUnoCursor.GoSentence(SwCursor::END_SENT)
+ || rUnoCursor.MovePara(fnParaCurr, fnParaEnd));
+ if (CURSOR_META == m_pImpl->m_eType)
+ {
+ bRet = lcl_ForceIntoMeta(rUnoCursor, m_pImpl->m_xParentText,
+ META_CHECK_BOTH)
+ && bRet;
+ }
+ return bRet;
+}
+
+sal_Bool SAL_CALL
+SwXTextCursor::isStartOfParagraph() throw (uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+
+ SwUnoCrsr & rUnoCursor( m_pImpl->GetCursorOrThrow() );
+
+ const sal_Bool bRet = SwUnoCursorHelper::IsStartOfPara(rUnoCursor);
+ return bRet;
+}
+
+sal_Bool SAL_CALL
+SwXTextCursor::isEndOfParagraph() throw (uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+
+ SwUnoCrsr & rUnoCursor( m_pImpl->GetCursorOrThrow() );
+
+ const sal_Bool bRet = SwUnoCursorHelper::IsEndOfPara(rUnoCursor);
+ return bRet;
+}
+
+sal_Bool SAL_CALL
+SwXTextCursor::gotoStartOfParagraph(sal_Bool Expand)
+throw (uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+
+ SwUnoCrsr & rUnoCursor( m_pImpl->GetCursorOrThrow() );
+
+ if (CURSOR_META == m_pImpl->m_eType)
+ {
+ return sal_False;
+ }
+ SwUnoCursorHelper::SelectPam(rUnoCursor, Expand);
+ sal_Bool bRet = SwUnoCursorHelper::IsStartOfPara(rUnoCursor);
+ if (!bRet)
+ {
+ bRet = rUnoCursor.MovePara(fnParaCurr, fnParaStart);
+ }
+
+ // since MovePara(fnParaCurr, fnParaStart) only returns false
+ // if we were already at the start of the paragraph this function
+ // should always complete successfully.
+ DBG_ASSERT( bRet, "gotoStartOfParagraph failed" );
+ return bRet;
+}
+
+sal_Bool SAL_CALL
+SwXTextCursor::gotoEndOfParagraph(sal_Bool Expand) throw (uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+
+ SwUnoCrsr & rUnoCursor( m_pImpl->GetCursorOrThrow() );
+
+ if (CURSOR_META == m_pImpl->m_eType)
+ {
+ return sal_False;
+ }
+ SwUnoCursorHelper::SelectPam(rUnoCursor, Expand);
+ sal_Bool bRet = SwUnoCursorHelper::IsEndOfPara(rUnoCursor);
+ if (!bRet)
+ {
+ bRet = rUnoCursor.MovePara(fnParaCurr, fnParaEnd);
+ }
+
+ // since MovePara(fnParaCurr, fnParaEnd) only returns false
+ // if we were already at the end of the paragraph this function
+ // should always complete successfully.
+ DBG_ASSERT( bRet, "gotoEndOfParagraph failed" );
+ return bRet;
+}
+
+sal_Bool SAL_CALL
+SwXTextCursor::gotoNextParagraph(sal_Bool Expand) throw (uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+
+ SwUnoCrsr & rUnoCursor( m_pImpl->GetCursorOrThrow() );
+
+ if (CURSOR_META == m_pImpl->m_eType)
+ {
+ return sal_False;
+ }
+ SwUnoCursorHelper::SelectPam(rUnoCursor, Expand);
+ const sal_Bool bRet = rUnoCursor.MovePara(fnParaNext, fnParaStart);
+ return bRet;
+}
+
+sal_Bool SAL_CALL
+SwXTextCursor::gotoPreviousParagraph(sal_Bool Expand)
+throw (uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+
+ SwUnoCrsr & rUnoCursor( m_pImpl->GetCursorOrThrow() );
+
+ if (CURSOR_META == m_pImpl->m_eType)
+ {
+ return sal_False;
+ }
+ SwUnoCursorHelper::SelectPam(rUnoCursor, Expand);
+ const sal_Bool bRet = rUnoCursor.MovePara(fnParaPrev, fnParaStart);
+ return bRet;
+}
+
+uno::Reference< text::XText > SAL_CALL
+SwXTextCursor::getText() throw (uno::RuntimeException)
+{
+ SolarMutexGuard g;
+
+ return m_pImpl->m_xParentText;
+}
+
+uno::Reference< text::XTextRange > SAL_CALL
+SwXTextCursor::getStart() throw (uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+
+ SwUnoCrsr & rUnoCursor( m_pImpl->GetCursorOrThrow() );
+
+ uno::Reference< text::XTextRange > xRet;
+ SwPaM aPam(*rUnoCursor.Start());
+ const uno::Reference< text::XText > xParent = getText();
+ if (CURSOR_META == m_pImpl->m_eType)
+ {
+ // return cursor to prevent modifying SwXTextRange for META
+ SwXTextCursor * const pXCursor(
+ new SwXTextCursor(*rUnoCursor.GetDoc(), xParent, CURSOR_META,
+ *rUnoCursor.GetPoint()) );
+ pXCursor->gotoStart(sal_False);
+ xRet = static_cast<text::XWordCursor*>(pXCursor);
+ }
+ else
+ {
+ xRet = new SwXTextRange(aPam, xParent);
+ }
+ return xRet;
+}
+
+uno::Reference< text::XTextRange > SAL_CALL
+SwXTextCursor::getEnd() throw (uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+
+ SwUnoCrsr & rUnoCursor( m_pImpl->GetCursorOrThrow() );
+
+ uno::Reference< text::XTextRange > xRet;
+ SwPaM aPam(*rUnoCursor.End());
+ const uno::Reference< text::XText > xParent = getText();
+ if (CURSOR_META == m_pImpl->m_eType)
+ {
+ // return cursor to prevent modifying SwXTextRange for META
+ SwXTextCursor * const pXCursor(
+ new SwXTextCursor(*rUnoCursor.GetDoc(), xParent, CURSOR_META,
+ *rUnoCursor.GetPoint()) );
+ pXCursor->gotoEnd(sal_False);
+ xRet = static_cast<text::XWordCursor*>(pXCursor);
+ }
+ else
+ {
+ xRet = new SwXTextRange(aPam, xParent);
+ }
+ return xRet;
+}
+
+OUString SAL_CALL SwXTextCursor::getString() throw (uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+
+ SwUnoCrsr & rUnoCursor( m_pImpl->GetCursorOrThrow() );
+
+ OUString aTxt;
+ SwUnoCursorHelper::GetTextFromPam(rUnoCursor, aTxt);
+ return aTxt;
+}
+
+void SAL_CALL
+SwXTextCursor::setString(const OUString& aString) throw (uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+
+ SwUnoCrsr & rUnoCursor( m_pImpl->GetCursorOrThrow() );
+ (void) rUnoCursor; // just to check if valid
+
+ const bool bForceExpandHints( (CURSOR_META != m_pImpl->m_eType)
+ ? false
+ : dynamic_cast<SwXMeta*>(m_pImpl->m_xParentText.get())
+ ->CheckForOwnMemberMeta(*GetPaM(), true) );
+ DeleteAndInsert(aString, bForceExpandHints);
+}
+
+uno::Any SwUnoCursorHelper::GetPropertyValue(
+ SwPaM& rPaM, const SfxItemPropertySet& rPropSet,
+ const OUString& rPropertyName)
+throw (beans::UnknownPropertyException, lang::WrappedTargetException,
+ uno::RuntimeException)
+{
+ uno::Any aAny;
+ SfxItemPropertySimpleEntry const*const pEntry =
+ rPropSet.getPropertyMap()->getByName(rPropertyName);
+
+ if (!pEntry)
+ {
+ throw beans::UnknownPropertyException(
+ OUString(RTL_CONSTASCII_USTRINGPARAM("Unknown property: "))
+ + rPropertyName, static_cast<cppu::OWeakObject *>(0));
+ }
+
+ beans::PropertyState eTemp;
+ const sal_Bool bDone = SwUnoCursorHelper::getCrsrPropertyValue(
+ *pEntry, rPaM, &aAny, eTemp );
+
+ if (!bDone)
+ {
+ SfxItemSet aSet(rPaM.GetDoc()->GetAttrPool(),
+ RES_CHRATR_BEGIN, RES_FRMATR_END - 1,
+ RES_TXTATR_UNKNOWN_CONTAINER, RES_TXTATR_UNKNOWN_CONTAINER,
+ RES_UNKNOWNATR_CONTAINER, RES_UNKNOWNATR_CONTAINER,
+ 0L);
+ SwUnoCursorHelper::GetCrsrAttr(rPaM, aSet);
+
+ rPropSet.getPropertyValue(*pEntry, aSet, aAny);
+ }
+
+ return aAny;
+}
+
+void SwUnoCursorHelper::SetPropertyValue(
+ SwPaM& rPaM, const SfxItemPropertySet& rPropSet,
+ const OUString& rPropertyName,
+ const uno::Any& rValue,
+ const SetAttrMode nAttrMode, const bool bTableMode)
+throw (beans::UnknownPropertyException, beans::PropertyVetoException,
+ lang::IllegalArgumentException, lang::WrappedTargetException,
+ uno::RuntimeException)
+{
+ SwDoc *const pDoc = rPaM.GetDoc();
+ SfxItemPropertySimpleEntry const*const pEntry =
+ rPropSet.getPropertyMap()->getByName(rPropertyName);
+ if (!pEntry)
+ {
+ throw beans::UnknownPropertyException(
+ OUString(RTL_CONSTASCII_USTRINGPARAM("Unknown property: "))
+ + rPropertyName,
+ static_cast<cppu::OWeakObject *>(0));
+ }
+
+ if (pEntry->nFlags & beans::PropertyAttribute::READONLY)
+ {
+ throw beans::PropertyVetoException(
+ OUString(RTL_CONSTASCII_USTRINGPARAM("Property is read-only: "))
+ + rPropertyName,
+ static_cast<cppu::OWeakObject *>(0));
+ }
+
+ SfxItemSet aItemSet( pDoc->GetAttrPool(), pEntry->nWID, pEntry->nWID );
+ SwUnoCursorHelper::GetCrsrAttr( rPaM, aItemSet );
+
+ if (!SwUnoCursorHelper::SetCursorPropertyValue(
+ *pEntry, rValue, rPaM, aItemSet))
+ {
+ rPropSet.setPropertyValue(*pEntry, rValue, aItemSet );
+ }
+ SwUnoCursorHelper::SetCrsrAttr(rPaM, aItemSet, nAttrMode, bTableMode);
+}
+
+uno::Sequence< beans::PropertyState >
+SwUnoCursorHelper::GetPropertyStates(
+ SwPaM& rPaM, const SfxItemPropertySet& rPropSet,
+ const uno::Sequence< OUString >& rPropertyNames,
+ const SwGetPropertyStatesCaller eCaller)
+throw (beans::UnknownPropertyException, uno::RuntimeException)
+{
+ const OUString* pNames = rPropertyNames.getConstArray();
+ uno::Sequence< beans::PropertyState > aRet(rPropertyNames.getLength());
+ beans::PropertyState* pStates = aRet.getArray();
+ SfxItemPropertyMap const*const pMap = rPropSet.getPropertyMap();
+ ::std::auto_ptr<SfxItemSet> pSet;
+ ::std::auto_ptr<SfxItemSet> pSetParent;
+
+ for (sal_Int32 i = 0, nEnd = rPropertyNames.getLength(); i < nEnd; i++)
+ {
+ SfxItemPropertySimpleEntry const*const pEntry =
+ pMap->getByName( pNames[i] );
+ if(!pEntry)
+ {
+ if (pNames[i].equalsAsciiL( SW_PROP_NAME(UNO_NAME_IS_SKIP_HIDDEN_TEXT)) ||
+ pNames[i].equalsAsciiL( SW_PROP_NAME(UNO_NAME_IS_SKIP_PROTECTED_TEXT)))
+ {
+ pStates[i] = beans::PropertyState_DEFAULT_VALUE;
+ continue;
+ }
+ else if (SW_PROPERTY_STATE_CALLER_SWX_TEXT_PORTION_TOLERANT ==
+ eCaller)
+ {
+ //this values marks the element as unknown property
+ pStates[i] = beans::PropertyState_MAKE_FIXED_SIZE;
+ continue;
+ }
+ else
+ {
+ throw beans::UnknownPropertyException(
+ OUString( RTL_CONSTASCII_USTRINGPARAM("Unknown property: "))
+ + pNames[i],
+ static_cast<cppu::OWeakObject *>(0));
+ }
+ }
+ if (((SW_PROPERTY_STATE_CALLER_SWX_TEXT_PORTION == eCaller) ||
+ (SW_PROPERTY_STATE_CALLER_SWX_TEXT_PORTION_TOLERANT == eCaller)) &&
+ pEntry->nWID < FN_UNO_RANGE_BEGIN &&
+ pEntry->nWID > FN_UNO_RANGE_END &&
+ pEntry->nWID < RES_CHRATR_BEGIN &&
+ pEntry->nWID > RES_TXTATR_END )
+ {
+ pStates[i] = beans::PropertyState_DEFAULT_VALUE;
+ }
+ else
+ {
+ if ( pEntry->nWID >= FN_UNO_RANGE_BEGIN &&
+ pEntry->nWID <= FN_UNO_RANGE_END )
+ {
+ SwUnoCursorHelper::getCrsrPropertyValue(
+ *pEntry, rPaM, 0, pStates[i] );
+ }
+ else
+ {
+ if (!pSet.get())
+ {
+ switch ( eCaller )
+ {
+ case SW_PROPERTY_STATE_CALLER_SWX_TEXT_PORTION_TOLERANT:
+ case SW_PROPERTY_STATE_CALLER_SWX_TEXT_PORTION:
+ pSet.reset(
+ new SfxItemSet( rPaM.GetDoc()->GetAttrPool(),
+ RES_CHRATR_BEGIN, RES_TXTATR_END ));
+ break;
+ case SW_PROPERTY_STATE_CALLER_SINGLE_VALUE_ONLY:
+ pSet.reset(
+ new SfxItemSet( rPaM.GetDoc()->GetAttrPool(),
+ pEntry->nWID, pEntry->nWID ));
+ break;
+ default:
+ pSet.reset( new SfxItemSet(
+ rPaM.GetDoc()->GetAttrPool(),
+ RES_CHRATR_BEGIN, RES_FRMATR_END - 1,
+ RES_UNKNOWNATR_CONTAINER, RES_UNKNOWNATR_CONTAINER,
+ RES_TXTATR_UNKNOWN_CONTAINER, RES_TXTATR_UNKNOWN_CONTAINER,
+ 0L ));
+ }
+ // --> OD 2006-07-12 #i63870#
+ SwUnoCursorHelper::GetCrsrAttr( rPaM, *pSet );
+ // <--
+ }
+
+ pStates[i] = ( pSet->Count() )
+ ? rPropSet.getPropertyState( *pEntry, *pSet )
+ : beans::PropertyState_DEFAULT_VALUE;
+
+ //try again to find out if a value has been inherited
+ if( beans::PropertyState_DIRECT_VALUE == pStates[i] )
+ {
+ if (!pSetParent.get())
+ {
+ pSetParent.reset( pSet->Clone( sal_False ) );
+ // --> OD 2006-07-12 #i63870#
+ SwUnoCursorHelper::GetCrsrAttr(
+ rPaM, *pSetParent, sal_True, sal_False );
+ // <--
+ }
+
+ pStates[i] = ( (pSetParent)->Count() )
+ ? rPropSet.getPropertyState( *pEntry, *pSetParent )
+ : beans::PropertyState_DEFAULT_VALUE;
+ }
+ }
+ }
+ }
+ return aRet;
+}
+
+beans::PropertyState SwUnoCursorHelper::GetPropertyState(
+ SwPaM& rPaM, const SfxItemPropertySet& rPropSet,
+ const OUString& rPropertyName)
+throw (beans::UnknownPropertyException, uno::RuntimeException)
+{
+ uno::Sequence< OUString > aStrings ( 1 );
+ aStrings[0] = rPropertyName;
+ uno::Sequence< beans::PropertyState > aSeq =
+ GetPropertyStates(rPaM, rPropSet, aStrings,
+ SW_PROPERTY_STATE_CALLER_SINGLE_VALUE_ONLY );
+ return aSeq[0];
+}
+
+static void
+lcl_SelectParaAndReset( SwPaM &rPaM, SwDoc & rDoc,
+ SvUShortsSort const*const pWhichIds = 0 )
+{
+ // if we are reseting paragraph attributes, we need to select the full paragraph first
+ SwPosition aStart = *rPaM.Start();
+ SwPosition aEnd = *rPaM.End();
+ ::std::auto_ptr< SwUnoCrsr > pTemp ( rDoc.CreateUnoCrsr(aStart, sal_False) );
+ if(!SwUnoCursorHelper::IsStartOfPara(*pTemp))
+ {
+ pTemp->MovePara(fnParaCurr, fnParaStart);
+ }
+ pTemp->SetMark();
+ *pTemp->GetPoint() = aEnd;
+ SwUnoCursorHelper::SelectPam(*pTemp, true);
+ if(!SwUnoCursorHelper::IsEndOfPara(*pTemp))
+ {
+ pTemp->MovePara(fnParaCurr, fnParaEnd);
+ }
+ rDoc.ResetAttrs(*pTemp, sal_True, pWhichIds);
+}
+
+void SwUnoCursorHelper::SetPropertyToDefault(
+ SwPaM& rPaM, const SfxItemPropertySet& rPropSet,
+ const OUString& rPropertyName)
+throw (beans::UnknownPropertyException, uno::RuntimeException)
+{
+ SwDoc & rDoc = *rPaM.GetDoc();
+ SfxItemPropertySimpleEntry const*const pEntry =
+ rPropSet.getPropertyMap()->getByName(rPropertyName);
+ if (!pEntry)
+ {
+ throw beans::UnknownPropertyException(
+ OUString(RTL_CONSTASCII_USTRINGPARAM("Unknown property: "))
+ + rPropertyName, static_cast<cppu::OWeakObject *>(0));
+ }
+
+ if (pEntry->nFlags & beans::PropertyAttribute::READONLY)
+ {
+ throw uno::RuntimeException(OUString(RTL_CONSTASCII_USTRINGPARAM(
+ "setPropertyToDefault: property is read-only: "))
+ + rPropertyName, 0);
+ }
+
+ if (pEntry->nWID < RES_FRMATR_END)
+ {
+ SvUShortsSort aWhichIds;
+ aWhichIds.Insert(pEntry->nWID);
+ if (pEntry->nWID < RES_PARATR_BEGIN)
+ {
+ rDoc.ResetAttrs(rPaM, sal_True, &aWhichIds);
+ }
+ else
+ {
+ lcl_SelectParaAndReset ( rPaM, rDoc, &aWhichIds );
+ }
+ }
+ else
+ {
+ SwUnoCursorHelper::resetCrsrPropertyValue(*pEntry, rPaM);
+ }
+}
+
+uno::Any SwUnoCursorHelper::GetPropertyDefault(
+ SwPaM& rPaM, const SfxItemPropertySet& rPropSet,
+ const OUString& rPropertyName)
+throw (beans::UnknownPropertyException, lang::WrappedTargetException,
+ uno::RuntimeException)
+{
+ SfxItemPropertySimpleEntry const*const pEntry =
+ rPropSet.getPropertyMap()->getByName(rPropertyName);
+ if (!pEntry)
+ {
+ throw beans::UnknownPropertyException(
+ OUString(RTL_CONSTASCII_USTRINGPARAM("Unknown property: "))
+ + rPropertyName, static_cast<cppu::OWeakObject *>(0));
+ }
+
+ uno::Any aRet;
+ if (pEntry->nWID < RES_FRMATR_END)
+ {
+ SwDoc & rDoc = *rPaM.GetDoc();
+ const SfxPoolItem& rDefItem =
+ rDoc.GetAttrPool().GetDefaultItem(pEntry->nWID);
+ rDefItem.QueryValue(aRet, pEntry->nMemberId);
+ }
+ return aRet;
+}
+
+uno::Reference< beans::XPropertySetInfo > SAL_CALL
+SwXTextCursor::getPropertySetInfo() throw (uno::RuntimeException)
+{
+ SolarMutexGuard g;
+
+ static uno::Reference< beans::XPropertySetInfo > xRef;
+ if(!xRef.is())
+ {
+ static SfxItemPropertyMapEntry aCrsrExtMap_Impl[] =
+ {
+ { SW_PROP_NAME(UNO_NAME_IS_SKIP_HIDDEN_TEXT), FN_SKIP_HIDDEN_TEXT, &::getBooleanCppuType(), PROPERTY_NONE, 0},
+ { SW_PROP_NAME(UNO_NAME_IS_SKIP_PROTECTED_TEXT), FN_SKIP_PROTECTED_TEXT, &::getBooleanCppuType(), PROPERTY_NONE, 0},
+ {0,0,0,0,0,0}
+ };
+ const uno::Reference< beans::XPropertySetInfo > xInfo =
+ m_pImpl->m_rPropSet.getPropertySetInfo();
+ // PropertySetInfo verlaengern!
+ const uno::Sequence<beans::Property> aPropSeq = xInfo->getProperties();
+ xRef = new SfxExtItemPropertySetInfo(
+ aCrsrExtMap_Impl,
+ aPropSeq );
+ }
+ return xRef;
+}
+
+void SAL_CALL
+SwXTextCursor::setPropertyValue(
+ const OUString& rPropertyName, const uno::Any& rValue)
+throw (beans::UnknownPropertyException, beans::PropertyVetoException,
+ lang::IllegalArgumentException, lang::WrappedTargetException,
+ uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+
+ SwUnoCrsr & rUnoCursor( m_pImpl->GetCursorOrThrow() );
+
+ if (rPropertyName.equalsAsciiL(SW_PROP_NAME(UNO_NAME_IS_SKIP_HIDDEN_TEXT)))
+ {
+ sal_Bool bSet(sal_False);
+ if (!(rValue >>= bSet))
+ {
+ throw lang::IllegalArgumentException();
+ }
+ rUnoCursor.SetSkipOverHiddenSections(bSet);
+ }
+ else if (rPropertyName.equalsAsciiL(
+ SW_PROP_NAME(UNO_NAME_IS_SKIP_PROTECTED_TEXT)))
+ {
+ sal_Bool bSet(sal_False);
+ if (!(rValue >>= bSet))
+ {
+ throw lang::IllegalArgumentException();
+ }
+ rUnoCursor.SetSkipOverProtectSections(bSet);
+ }
+ else
+ {
+ SwUnoCursorHelper::SetPropertyValue(rUnoCursor,
+ m_pImpl->m_rPropSet, rPropertyName, rValue);
+ }
+}
+
+uno::Any SAL_CALL
+SwXTextCursor::getPropertyValue(const OUString& rPropertyName)
+throw (beans::UnknownPropertyException, lang::WrappedTargetException,
+ uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+
+ SwUnoCrsr & rUnoCursor( m_pImpl->GetCursorOrThrow() );
+
+ uno::Any aAny;
+ if (rPropertyName.equalsAsciiL(SW_PROP_NAME(UNO_NAME_IS_SKIP_HIDDEN_TEXT)))
+ {
+ const sal_Bool bSet = rUnoCursor.IsSkipOverHiddenSections();
+ aAny <<= bSet;
+ }
+ else if (rPropertyName.equalsAsciiL(
+ SW_PROP_NAME(UNO_NAME_IS_SKIP_PROTECTED_TEXT)))
+ {
+ const sal_Bool bSet = rUnoCursor.IsSkipOverProtectSections();
+ aAny <<= bSet;
+ }
+ else
+ {
+ aAny = SwUnoCursorHelper::GetPropertyValue(rUnoCursor,
+ m_pImpl->m_rPropSet, rPropertyName);
+ }
+ return aAny;
+}
+
+void SAL_CALL
+SwXTextCursor::addPropertyChangeListener(
+ const ::rtl::OUString& /*rPropertyName*/,
+ const uno::Reference< beans::XPropertyChangeListener >& /*xListener*/)
+throw (beans::UnknownPropertyException, lang::WrappedTargetException,
+ uno::RuntimeException)
+{
+ OSL_FAIL("SwXTextCursor::addPropertyChangeListener(): not implemented");
+}
+
+void SAL_CALL
+SwXTextCursor::removePropertyChangeListener(
+ const ::rtl::OUString& /*rPropertyName*/,
+ const uno::Reference< beans::XPropertyChangeListener >& /*xListener*/)
+throw (beans::UnknownPropertyException, lang::WrappedTargetException,
+ uno::RuntimeException)
+{
+ OSL_FAIL("SwXTextCursor::removePropertyChangeListener(): not implemented");
+}
+
+void SAL_CALL
+SwXTextCursor::addVetoableChangeListener(
+ const ::rtl::OUString& /*rPropertyName*/,
+ const uno::Reference< beans::XVetoableChangeListener >& /*xListener*/)
+throw (beans::UnknownPropertyException, lang::WrappedTargetException,
+ uno::RuntimeException)
+{
+ OSL_FAIL("SwXTextCursor::addVetoableChangeListener(): not implemented");
+}
+
+void SAL_CALL
+SwXTextCursor::removeVetoableChangeListener(
+ const ::rtl::OUString& /*rPropertyName*/,
+ const uno::Reference< beans::XVetoableChangeListener >& /*xListener*/)
+throw (beans::UnknownPropertyException, lang::WrappedTargetException,
+ uno::RuntimeException)
+{
+ OSL_FAIL("SwXTextCursor::removeVetoableChangeListener(): not implemented");
+}
+
+beans::PropertyState SAL_CALL
+SwXTextCursor::getPropertyState(const OUString& rPropertyName)
+throw (beans::UnknownPropertyException, uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+
+ SwUnoCrsr & rUnoCursor( m_pImpl->GetCursorOrThrow() );
+
+ const beans::PropertyState eRet = SwUnoCursorHelper::GetPropertyState(
+ rUnoCursor, m_pImpl->m_rPropSet, rPropertyName);
+ return eRet;
+}
+
+uno::Sequence< beans::PropertyState > SAL_CALL
+SwXTextCursor::getPropertyStates(
+ const uno::Sequence< OUString >& rPropertyNames)
+throw (beans::UnknownPropertyException, uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+
+ SwUnoCrsr & rUnoCursor( m_pImpl->GetCursorOrThrow() );
+
+ return SwUnoCursorHelper::GetPropertyStates(
+ rUnoCursor, m_pImpl->m_rPropSet, rPropertyNames);
+}
+
+void SAL_CALL
+SwXTextCursor::setPropertyToDefault(const OUString& rPropertyName)
+throw (beans::UnknownPropertyException, uno::RuntimeException)
+{
+ // forward: need no solar mutex here
+ uno::Sequence < OUString > aSequence ( &rPropertyName, 1 );
+ setPropertiesToDefault ( aSequence );
+}
+
+uno::Any SAL_CALL
+SwXTextCursor::getPropertyDefault(const OUString& rPropertyName)
+throw (beans::UnknownPropertyException, lang::WrappedTargetException,
+ uno::RuntimeException)
+{
+ // forward: need no solar mutex here
+ const uno::Sequence < OUString > aSequence ( &rPropertyName, 1 );
+ return getPropertyDefaults ( aSequence ).getConstArray()[0];
+}
+
+// para specific attribut ranges
+static sal_uInt16 g_ParaResetableSetRange[] = {
+ RES_FRMATR_BEGIN, RES_FRMATR_END-1,
+ RES_PARATR_BEGIN, RES_PARATR_END-1,
+ RES_PARATR_LIST_BEGIN, RES_PARATR_LIST_END-1,
+ RES_UNKNOWNATR_BEGIN, RES_UNKNOWNATR_END-1,
+ 0
+};
+
+// selection specific attribut ranges
+static sal_uInt16 g_ResetableSetRange[] = {
+ RES_CHRATR_BEGIN, RES_CHRATR_END-1,
+ RES_TXTATR_INETFMT, RES_TXTATR_INETFMT,
+ RES_TXTATR_CHARFMT, RES_TXTATR_CHARFMT,
+ RES_TXTATR_CJK_RUBY, RES_TXTATR_CJK_RUBY,
+ RES_TXTATR_UNKNOWN_CONTAINER, RES_TXTATR_UNKNOWN_CONTAINER,
+ 0
+};
+
+static void
+lcl_EnumerateIds(sal_uInt16 const* pIdRange, SvUShortsSort & rWhichIds)
+{
+ while (*pIdRange)
+ {
+ const sal_uInt16 nStart = sal::static_int_cast<sal_uInt16>(*pIdRange++);
+ const sal_uInt16 nEnd = sal::static_int_cast<sal_uInt16>(*pIdRange++);
+ for (sal_uInt16 nId = nStart + 1; nId <= nEnd; ++nId)
+ {
+ rWhichIds.Insert( nId );
+ }
+ }
+}
+
+void SAL_CALL
+SwXTextCursor::setAllPropertiesToDefault()
+throw (uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+
+ SwUnoCrsr & rUnoCursor( m_pImpl->GetCursorOrThrow() );
+
+ SvUShortsSort aParaWhichIds;
+ SvUShortsSort aWhichIds;
+ lcl_EnumerateIds(g_ParaResetableSetRange, aParaWhichIds);
+ lcl_EnumerateIds(g_ResetableSetRange, aWhichIds);
+ if (aParaWhichIds.Count())
+ {
+ lcl_SelectParaAndReset(rUnoCursor, *rUnoCursor.GetDoc(),
+ &aParaWhichIds);
+ }
+ if (aWhichIds.Count())
+ {
+ rUnoCursor.GetDoc()->ResetAttrs(rUnoCursor, sal_True, &aWhichIds);
+ }
+}
+
+void SAL_CALL
+SwXTextCursor::setPropertiesToDefault(
+ const uno::Sequence< OUString >& rPropertyNames)
+throw (beans::UnknownPropertyException, uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+
+ SwUnoCrsr & rUnoCursor( m_pImpl->GetCursorOrThrow() );
+
+ const sal_Int32 nCount = rPropertyNames.getLength();
+ if ( nCount )
+ {
+ SwDoc & rDoc = *rUnoCursor.GetDoc();
+ const OUString * pNames = rPropertyNames.getConstArray();
+ SvUShortsSort aWhichIds;
+ SvUShortsSort aParaWhichIds;
+ for (sal_Int32 i = 0; i < nCount; i++)
+ {
+ SfxItemPropertySimpleEntry const*const pEntry =
+ m_pImpl->m_rPropSet.getPropertyMap()->getByName( pNames[i] );
+ if (!pEntry)
+ {
+ if (pNames[i].equalsAsciiL(
+ SW_PROP_NAME(UNO_NAME_IS_SKIP_HIDDEN_TEXT)) ||
+ pNames[i].equalsAsciiL(
+ SW_PROP_NAME(UNO_NAME_IS_SKIP_PROTECTED_TEXT)))
+ {
+ continue;
+ }
+ throw beans::UnknownPropertyException(
+ OUString(RTL_CONSTASCII_USTRINGPARAM("Unknown property: "))
+ + pNames[i],
+ static_cast<cppu::OWeakObject *>(this));
+ }
+ if (pEntry->nFlags & beans::PropertyAttribute::READONLY)
+ {
+ throw uno::RuntimeException(
+ OUString(RTL_CONSTASCII_USTRINGPARAM(
+ "setPropertiesToDefault: property is read-only: "))
+ + pNames[i],
+ static_cast<cppu::OWeakObject *>(this));
+ }
+
+ if (pEntry->nWID < RES_FRMATR_END)
+ {
+ if (pEntry->nWID < RES_PARATR_BEGIN)
+ {
+ aWhichIds.Insert(pEntry->nWID);
+ }
+ else
+ {
+ aParaWhichIds.Insert(pEntry->nWID);
+ }
+ }
+ else if (pEntry->nWID == FN_UNO_NUM_START_VALUE)
+ {
+ SwUnoCursorHelper::resetCrsrPropertyValue(*pEntry, rUnoCursor);
+ }
+ }
+
+ if (aParaWhichIds.Count())
+ {
+ lcl_SelectParaAndReset(rUnoCursor, rDoc, &aParaWhichIds);
+ }
+ if (aWhichIds.Count())
+ {
+ rDoc.ResetAttrs(rUnoCursor, sal_True, &aWhichIds);
+ }
+ }
+}
+
+uno::Sequence< uno::Any > SAL_CALL
+SwXTextCursor::getPropertyDefaults(
+ const uno::Sequence< OUString >& rPropertyNames)
+throw (beans::UnknownPropertyException, lang::WrappedTargetException,
+ uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+
+ SwUnoCrsr & rUnoCursor( m_pImpl->GetCursorOrThrow() );
+
+ const sal_Int32 nCount = rPropertyNames.getLength();
+ uno::Sequence< uno::Any > aRet(nCount);
+ if ( nCount )
+ {
+ SwDoc & rDoc = *rUnoCursor.GetDoc();
+ const OUString *pNames = rPropertyNames.getConstArray();
+ uno::Any *pAny = aRet.getArray();
+ for (sal_Int32 i = 0; i < nCount; i++)
+ {
+ SfxItemPropertySimpleEntry const*const pEntry =
+ m_pImpl->m_rPropSet.getPropertyMap()->getByName( pNames[i] );
+ if (!pEntry)
+ {
+ if (pNames[i].equalsAsciiL(
+ SW_PROP_NAME(UNO_NAME_IS_SKIP_HIDDEN_TEXT)) ||
+ pNames[i].equalsAsciiL(
+ SW_PROP_NAME(UNO_NAME_IS_SKIP_PROTECTED_TEXT)))
+ {
+ continue;
+ }
+ throw beans::UnknownPropertyException(
+ OUString(RTL_CONSTASCII_USTRINGPARAM("Unknown property: "))
+ + pNames[i],
+ static_cast<cppu::OWeakObject *>(0));
+ }
+ if (pEntry->nWID < RES_FRMATR_END)
+ {
+ const SfxPoolItem& rDefItem =
+ rDoc.GetAttrPool().GetDefaultItem(pEntry->nWID);
+ rDefItem.QueryValue(pAny[i], pEntry->nMemberId);
+ }
+ }
+ }
+ return aRet;
+}
+
+void SAL_CALL
+SwXTextCursor::makeRedline(
+ const ::rtl::OUString& rRedlineType,
+ const uno::Sequence< beans::PropertyValue >& rRedlineProperties)
+throw (lang::IllegalArgumentException, uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+
+ SwUnoCrsr & rUnoCursor( m_pImpl->GetCursorOrThrow() );
+
+ SwUnoCursorHelper::makeRedline(rUnoCursor, rRedlineType, rRedlineProperties);
+}
+
+void SAL_CALL SwXTextCursor::insertDocumentFromURL(const OUString& rURL,
+ const uno::Sequence< beans::PropertyValue >& rOptions)
+throw (lang::IllegalArgumentException, io::IOException,
+ uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+
+ SwUnoCrsr & rUnoCursor( m_pImpl->GetCursorOrThrow() );
+
+ SwUnoCursorHelper::InsertFile(&rUnoCursor, rURL, rOptions);
+}
+
+uno::Sequence< beans::PropertyValue >
+SwUnoCursorHelper::CreateSortDescriptor(const bool bFromTable)
+{
+ uno::Sequence< beans::PropertyValue > aRet(5);
+ beans::PropertyValue* pArray = aRet.getArray();
+
+ uno::Any aVal;
+ aVal.setValue( &bFromTable, ::getCppuBooleanType());
+ pArray[0] = beans::PropertyValue(C2U("IsSortInTable"), -1, aVal,
+ beans::PropertyState_DIRECT_VALUE);
+
+ aVal <<= sal_Unicode(' ');
+ pArray[1] = beans::PropertyValue(C2U("Delimiter"), -1, aVal,
+ beans::PropertyState_DIRECT_VALUE);
+
+ aVal <<= (sal_Bool) sal_False;
+ pArray[2] = beans::PropertyValue(C2U("IsSortColumns"), -1, aVal,
+ beans::PropertyState_DIRECT_VALUE);
+
+ aVal <<= (sal_Int32) 3;
+ pArray[3] = beans::PropertyValue(C2U("MaxSortFieldsCount"), -1, aVal,
+ beans::PropertyState_DIRECT_VALUE);
+
+ uno::Sequence< table::TableSortField > aFields(3);
+ table::TableSortField* pFields = aFields.getArray();
+
+ lang::Locale aLang( SvxCreateLocale( LANGUAGE_SYSTEM ) );
+ // get collator algorithm to be used for the locale
+ uno::Sequence< OUString > aSeq(
+ GetAppCollator().listCollatorAlgorithms( aLang ) );
+ const sal_Int32 nLen = aSeq.getLength();
+ DBG_ASSERT( nLen > 0, "list of collator algorithms is empty!");
+ OUString aCollAlg;
+ if (nLen > 0)
+ {
+ aCollAlg = aSeq.getConstArray()[0];
+ }
+
+#if OSL_DEBUG_LEVEL > 1
+ const OUString *pTxt = aSeq.getConstArray();
+ (void)pTxt;
+#endif
+
+ pFields[0].Field = 1;
+ pFields[0].IsAscending = sal_True;
+ pFields[0].IsCaseSensitive = sal_False;
+ pFields[0].FieldType = table::TableSortFieldType_ALPHANUMERIC;
+ pFields[0].CollatorLocale = aLang;
+ pFields[0].CollatorAlgorithm = aCollAlg;
+
+ pFields[1].Field = 1;
+ pFields[1].IsAscending = sal_True;
+ pFields[1].IsCaseSensitive = sal_False;
+ pFields[1].FieldType = table::TableSortFieldType_ALPHANUMERIC;
+ pFields[1].CollatorLocale = aLang;
+ pFields[1].CollatorAlgorithm = aCollAlg;
+
+ pFields[2].Field = 1;
+ pFields[2].IsAscending = sal_True;
+ pFields[2].IsCaseSensitive = sal_False;
+ pFields[2].FieldType = table::TableSortFieldType_ALPHANUMERIC;
+ pFields[2].CollatorLocale = aLang;
+ pFields[2].CollatorAlgorithm = aCollAlg;
+
+ aVal <<= aFields;
+ pArray[4] = beans::PropertyValue(C2U("SortFields"), -1, aVal,
+ beans::PropertyState_DIRECT_VALUE);
+
+ return aRet;
+}
+
+uno::Sequence< beans::PropertyValue > SAL_CALL
+SwXTextCursor::createSortDescriptor() throw (uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+
+ return SwUnoCursorHelper::CreateSortDescriptor(false);
+}
+
+sal_Bool SwUnoCursorHelper::ConvertSortProperties(
+ const uno::Sequence< beans::PropertyValue >& rDescriptor,
+ SwSortOptions& rSortOpt)
+{
+ sal_Bool bRet = sal_True;
+ const beans::PropertyValue* pProperties = rDescriptor.getConstArray();
+
+ rSortOpt.bTable = sal_False;
+ rSortOpt.cDeli = ' ';
+ rSortOpt.eDirection = SRT_COLUMNS; //!! UI text may be contrary though !!
+
+ SwSortKey* pKey1 = new SwSortKey;
+ pKey1->nColumnId = USHRT_MAX;
+ pKey1->bIsNumeric = sal_True;
+ pKey1->eSortOrder = SRT_ASCENDING;
+
+ SwSortKey* pKey2 = new SwSortKey;
+ pKey2->nColumnId = USHRT_MAX;
+ pKey2->bIsNumeric = sal_True;
+ pKey2->eSortOrder = SRT_ASCENDING;
+
+ SwSortKey* pKey3 = new SwSortKey;
+ pKey3->nColumnId = USHRT_MAX;
+ pKey3->bIsNumeric = sal_True;
+ pKey3->eSortOrder = SRT_ASCENDING;
+ SwSortKey* aKeys[3] = {pKey1, pKey2, pKey3};
+
+ sal_Bool bOldSortdescriptor(sal_False);
+ sal_Bool bNewSortdescriptor(sal_False);
+
+ for (sal_Int32 n = 0; n < rDescriptor.getLength(); ++n)
+ {
+ uno::Any aValue( pProperties[n].Value );
+// String sPropName = pProperties[n].Name;
+ const OUString& rPropName = pProperties[n].Name;
+
+ // old and new sortdescriptor
+ if (rPropName.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("IsSortInTable")))
+ {
+ if (aValue.getValueType() == ::getBooleanCppuType())
+ {
+ rSortOpt.bTable = *(sal_Bool*)aValue.getValue();
+ }
+ else
+ {
+ bRet = sal_False;
+ }
+ }
+ else if (rPropName.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("Delimiter")))
+ {
+ sal_Unicode uChar = sal_Unicode();
+ if (aValue >>= uChar)
+ {
+ rSortOpt.cDeli = uChar;
+ }
+ else
+ {
+ bRet = sal_False;
+ }
+ }
+ // old sortdescriptor
+ else if (rPropName.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("SortColumns")))
+ {
+ bOldSortdescriptor = sal_True;
+ sal_Bool bTemp(sal_False);
+ if (aValue >>= bTemp)
+ {
+ rSortOpt.eDirection = bTemp ? SRT_COLUMNS : SRT_ROWS;
+ }
+ else
+ {
+ bRet = sal_False;
+ }
+ }
+ else if ( rPropName.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("IsCaseSensitive")))
+ {
+ bOldSortdescriptor = sal_True;
+ sal_Bool bTemp(sal_False);
+ if (aValue >>= bTemp)
+ {
+ rSortOpt.bIgnoreCase = !bTemp;
+ }
+ else
+ {
+ bRet = sal_False;
+ }
+ }
+ else if (rPropName.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("CollatorLocale")))
+ {
+ bOldSortdescriptor = sal_True;
+ lang::Locale aLocale;
+ if (aValue >>= aLocale)
+ {
+ rSortOpt.nLanguage = SvxLocaleToLanguage( aLocale );
+ }
+ else
+ {
+ bRet = sal_False;
+ }
+ }
+ else if (rPropName.matchAsciiL("CollatorAlgorithm", 17) &&
+ rPropName.getLength() == 18 &&
+ (rPropName.getStr()[17] >= '0' && rPropName.getStr()[17] <= '9'))
+ {
+ bOldSortdescriptor = sal_True;
+ sal_uInt16 nIndex = rPropName.getStr()[17];
+ nIndex -= '0';
+ OUString aTxt;
+ if ((aValue >>= aTxt) && nIndex < 3)
+ {
+ aKeys[nIndex]->sSortType = aTxt;
+ }
+ else
+ {
+ bRet = sal_False;
+ }
+ }
+ else if (rPropName.matchAsciiL("SortRowOrColumnNo", 17) &&
+ rPropName.getLength() == 18 &&
+ (rPropName.getStr()[17] >= '0' && rPropName.getStr()[17] <= '9'))
+ {
+ bOldSortdescriptor = sal_True;
+ sal_uInt16 nIndex = rPropName.getStr()[17];
+ nIndex -= '0';
+ sal_Int16 nCol = -1;
+ if (aValue.getValueType() == ::getCppuType((const sal_Int16*)0)
+ && nIndex < 3)
+ {
+ aValue >>= nCol;
+ }
+ if (nCol >= 0)
+ {
+ aKeys[nIndex]->nColumnId = nCol;
+ }
+ else
+ {
+ bRet = sal_False;
+ }
+ }
+ else if (0 == rPropName.indexOf(C2U("IsSortNumeric")) &&
+ rPropName.getLength() == 14 &&
+ (rPropName.getStr()[13] >= '0' && rPropName.getStr()[13] <= '9'))
+ {
+ bOldSortdescriptor = sal_True;
+ sal_uInt16 nIndex = rPropName.getStr()[13];
+ nIndex = nIndex - '0';
+ if (aValue.getValueType() == ::getBooleanCppuType() && nIndex < 3)
+ {
+ sal_Bool bTemp = *(sal_Bool*)aValue.getValue();
+ aKeys[nIndex]->bIsNumeric = bTemp;
+ }
+ else
+ {
+ bRet = sal_False;
+ }
+ }
+ else if (0 == rPropName.indexOf(C2U("IsSortAscending")) &&
+ rPropName.getLength() == 16 &&
+ (rPropName.getStr()[15] >= '0' && rPropName.getStr()[15] <= '9'))
+ {
+ bOldSortdescriptor = sal_True;
+ sal_uInt16 nIndex = rPropName.getStr()[15];
+ nIndex -= '0';
+ if (aValue.getValueType() == ::getBooleanCppuType() && nIndex < 3)
+ {
+ sal_Bool bTemp = *(sal_Bool*)aValue.getValue();
+ aKeys[nIndex]->eSortOrder = (bTemp)
+ ? SRT_ASCENDING : SRT_DESCENDING;
+ }
+ else
+ {
+ bRet = sal_False;
+ }
+ }
+ // new sortdescriptor
+ else if (rPropName.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("IsSortColumns")))
+ {
+ bNewSortdescriptor = sal_True;
+ if (aValue.getValueType() == ::getBooleanCppuType())
+ {
+ sal_Bool bTemp = *(sal_Bool*)aValue.getValue();
+ rSortOpt.eDirection = bTemp ? SRT_COLUMNS : SRT_ROWS;
+ }
+ else
+ {
+ bRet = sal_False;
+ }
+ }
+ else if (rPropName.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("SortFields")))
+ {
+ bNewSortdescriptor = sal_True;
+ uno::Sequence < table::TableSortField > aFields;
+ if (aValue >>= aFields)
+ {
+ sal_Int32 nCount(aFields.getLength());
+ if (nCount <= 3)
+ {
+ table::TableSortField* pFields = aFields.getArray();
+ for (sal_Int32 i = 0; i < nCount; ++i)
+ {
+ rSortOpt.bIgnoreCase = !pFields[i].IsCaseSensitive;
+ rSortOpt.nLanguage =
+ SvxLocaleToLanguage( pFields[i].CollatorLocale );
+ aKeys[i]->sSortType = pFields[i].CollatorAlgorithm;
+ aKeys[i]->nColumnId =
+ static_cast<sal_uInt16>(pFields[i].Field);
+ aKeys[i]->bIsNumeric = (pFields[i].FieldType ==
+ table::TableSortFieldType_NUMERIC);
+ aKeys[i]->eSortOrder = (pFields[i].IsAscending)
+ ? SRT_ASCENDING : SRT_DESCENDING;
+ }
+ }
+ else
+ {
+ bRet = sal_False;
+ }
+ }
+ else
+ {
+ bRet = sal_False;
+ }
+ }
+ }
+
+ if (bNewSortdescriptor && bOldSortdescriptor)
+ {
+ OSL_FAIL("someone tried to set the old deprecated and "
+ "the new sortdescriptor");
+ bRet = sal_False;
+ }
+
+ if (pKey1->nColumnId != USHRT_MAX)
+ {
+ rSortOpt.aKeys.C40_INSERT(SwSortKey, pKey1, rSortOpt.aKeys.Count());
+ }
+ if (pKey2->nColumnId != USHRT_MAX)
+ {
+ rSortOpt.aKeys.C40_INSERT(SwSortKey, pKey2, rSortOpt.aKeys.Count());
+ }
+ if (pKey3->nColumnId != USHRT_MAX)
+ {
+ rSortOpt.aKeys.C40_INSERT(SwSortKey, pKey3, rSortOpt.aKeys.Count());
+ }
+
+ return bRet && rSortOpt.aKeys.Count() > 0;
+}
+
+void SAL_CALL
+SwXTextCursor::sort(const uno::Sequence< beans::PropertyValue >& rDescriptor)
+throw (uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+
+ SwUnoCrsr & rUnoCursor( m_pImpl->GetCursorOrThrow() );
+
+ if (rUnoCursor.HasMark())
+ {
+ SwSortOptions aSortOpt;
+ if (!SwUnoCursorHelper::ConvertSortProperties(rDescriptor, aSortOpt))
+ {
+ throw uno::RuntimeException();
+ }
+ UnoActionContext aContext( rUnoCursor.GetDoc() );
+
+ SwPosition & rStart = *rUnoCursor.Start();
+ SwPosition & rEnd = *rUnoCursor.End();
+
+ SwNodeIndex aPrevIdx( rStart.nNode, -1 );
+ const sal_uLong nOffset = rEnd.nNode.GetIndex() - rStart.nNode.GetIndex();
+ const xub_StrLen nCntStt = rStart.nContent.GetIndex();
+
+ rUnoCursor.GetDoc()->SortText(rUnoCursor, aSortOpt);
+
+ // Selektion wieder setzen
+ rUnoCursor.DeleteMark();
+ rUnoCursor.GetPoint()->nNode.Assign( aPrevIdx.GetNode(), +1 );
+ SwCntntNode *const pCNd = rUnoCursor.GetCntntNode();
+ xub_StrLen nLen = pCNd->Len();
+ if (nLen > nCntStt)
+ {
+ nLen = nCntStt;
+ }
+ rUnoCursor.GetPoint()->nContent.Assign(pCNd, nLen );
+ rUnoCursor.SetMark();
+
+ rUnoCursor.GetPoint()->nNode += nOffset;
+ SwCntntNode *const pCNd2 = rUnoCursor.GetCntntNode();
+ rUnoCursor.GetPoint()->nContent.Assign( pCNd2, pCNd2->Len() );
+ }
+}
+
+uno::Reference< container::XEnumeration > SAL_CALL
+SwXTextCursor::createContentEnumeration(const OUString& rServiceName)
+throw (uno::RuntimeException)
+{
+ SolarMutexGuard g;
+
+ if (!rServiceName.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("com.sun.star.text.TextContent")))
+ {
+ throw uno::RuntimeException();
+ }
+
+ SwUnoCrsr & rUnoCursor( m_pImpl->GetCursorOrThrow() );
+
+ uno::Reference< container::XEnumeration > xRet =
+ new SwXParaFrameEnumeration(rUnoCursor, PARAFRAME_PORTION_TEXTRANGE);
+ return xRet;
+}
+
+uno::Reference< container::XEnumeration > SAL_CALL
+SwXTextCursor::createEnumeration() throw (uno::RuntimeException)
+{
+ SolarMutexGuard g;
+
+ SwUnoCrsr & rUnoCursor( m_pImpl->GetCursorOrThrow() );
+
+ const uno::Reference<lang::XUnoTunnel> xTunnel(
+ m_pImpl->m_xParentText, uno::UNO_QUERY);
+ SwXText* pParentText = 0;
+ if (xTunnel.is())
+ {
+ pParentText = ::sw::UnoTunnelGetImplementation<SwXText>(xTunnel);
+ }
+ DBG_ASSERT(pParentText, "parent is not a SwXText");
+ if (!pParentText)
+ {
+ throw uno::RuntimeException();
+ }
+
+ ::std::auto_ptr<SwUnoCrsr> pNewCrsr(
+ rUnoCursor.GetDoc()->CreateUnoCrsr(*rUnoCursor.GetPoint()) );
+ if (rUnoCursor.HasMark())
+ {
+ pNewCrsr->SetMark();
+ *pNewCrsr->GetMark() = *rUnoCursor.GetMark();
+ }
+ const CursorType eSetType = (CURSOR_TBLTEXT == m_pImpl->m_eType)
+ ? CURSOR_SELECTION_IN_TABLE : CURSOR_SELECTION;
+ SwTableNode const*const pStartNode( (CURSOR_TBLTEXT == m_pImpl->m_eType)
+ ? rUnoCursor.GetPoint()->nNode.GetNode().FindTableNode()
+ : 0);
+ SwTable const*const pTable(
+ (pStartNode) ? & pStartNode->GetTable() : 0 );
+ const uno::Reference< container::XEnumeration > xRet =
+ new SwXParagraphEnumeration(
+ pParentText, pNewCrsr, eSetType, pStartNode, pTable);
+
+ return xRet;
+}
+
+uno::Type SAL_CALL
+SwXTextCursor::getElementType() throw (uno::RuntimeException)
+{
+ return text::XTextRange::static_type();
+}
+
+sal_Bool SAL_CALL SwXTextCursor::hasElements() throw (uno::RuntimeException)
+{
+ return sal_True;
+}
+
+uno::Sequence< OUString > SAL_CALL
+SwXTextCursor::getAvailableServiceNames() throw (uno::RuntimeException)
+{
+ uno::Sequence< OUString > aRet(1);
+ OUString* pArray = aRet.getArray();
+ pArray[0] = OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.text.TextContent"));
+ return aRet;
+}
+
+IMPLEMENT_FORWARD_REFCOUNT( SwXTextCursor,SwXTextCursor_Base )
+
+uno::Any SAL_CALL
+SwXTextCursor::queryInterface(const uno::Type& rType)
+throw (uno::RuntimeException)
+{
+ return (rType == lang::XUnoTunnel::static_type())
+ ? OTextCursorHelper::queryInterface(rType)
+ : SwXTextCursor_Base::queryInterface(rType);
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/unocore/unoobj2.cxx b/sw/source/core/unocore/unoobj2.cxx
new file mode 100644
index 000000000000..7d7aac27aae9
--- /dev/null
+++ b/sw/source/core/unocore/unoobj2.cxx
@@ -0,0 +1,1970 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+#include <rtl/ustrbuf.hxx>
+#include <swtypes.hxx>
+#include <hintids.hxx>
+#include <cmdid.h>
+#include <hints.hxx>
+#include <IMark.hxx>
+#include <bookmrk.hxx>
+#include <frmfmt.hxx>
+#include <doc.hxx>
+#include <IDocumentUndoRedo.hxx>
+#include <ndtxt.hxx>
+#include <ndnotxt.hxx>
+#include <unocrsr.hxx>
+#include <swundo.hxx>
+#include <rootfrm.hxx>
+#include <flyfrm.hxx>
+#include <ftnidx.hxx>
+#include <sfx2/linkmgr.hxx>
+#include <docary.hxx>
+#include <paratr.hxx>
+#include <tools/urlobj.hxx>
+#include <pam.hxx>
+#include <tools/cachestr.hxx>
+#include <shellio.hxx>
+#include <swerror.h>
+#include <swtblfmt.hxx>
+#include <docsh.hxx>
+#include <docstyle.hxx>
+#include <charfmt.hxx>
+#include <txtfld.hxx>
+#include <fmtfld.hxx>
+#include <fmtpdsc.hxx>
+#include <pagedesc.hxx>
+#include <poolfmt.hrc>
+#include <poolfmt.hxx>
+#include <edimp.hxx>
+#include <fchrfmt.hxx>
+#include <cntfrm.hxx>
+#include <pagefrm.hxx>
+#include <doctxm.hxx>
+#include <sfx2/docfilt.hxx>
+#include <sfx2/docfile.hxx>
+#include <sfx2/fcontnr.hxx>
+#include <fmtrfmrk.hxx>
+#include <txtrfmrk.hxx>
+#include <unoparaframeenum.hxx>
+#include <unofootnote.hxx>
+#include <unotextbodyhf.hxx>
+#include <unotextrange.hxx>
+#include <unoparagraph.hxx>
+#include <unomap.hxx>
+#include <unoport.hxx>
+#include <unocrsrhelper.hxx>
+#include <unosett.hxx>
+#include <unoprnms.hxx>
+#include <unotbl.hxx>
+#include <unodraw.hxx>
+#include <unocoll.hxx>
+#include <unostyle.hxx>
+#include <unofield.hxx>
+#include <fmtanchr.hxx>
+#include <editeng/flstitem.hxx>
+#include <editeng/unolingu.hxx>
+#include <svtools/ctrltool.hxx>
+#include <flypos.hxx>
+#include <txtftn.hxx>
+#include <fmtftn.hxx>
+#include <fmtcntnt.hxx>
+#include <com/sun/star/text/WrapTextMode.hpp>
+#include <com/sun/star/text/TextContentAnchorType.hpp>
+#include <com/sun/star/style/PageStyleLayout.hpp>
+#include <com/sun/star/text/XTextDocument.hpp>
+#include <com/sun/star/style/XStyleFamiliesSupplier.hpp>
+#include <com/sun/star/drawing/XDrawPageSupplier.hpp>
+#include <unoidx.hxx>
+#include <unoframe.hxx>
+#include <fmthdft.hxx>
+#include <osl/mutex.hxx>
+#include <vcl/svapp.hxx>
+#include <fmtflcnt.hxx>
+#define _SVSTDARR_USHORTS
+#define _SVSTDARR_USHORTSSORT
+#define _SVSTDARR_XUB_STRLEN
+#include <svl/svstdarr.hxx>
+#include <editeng/brshitem.hxx>
+#include <fmtclds.hxx>
+#include <dcontact.hxx>
+#include <dflyobj.hxx>
+#include <crsskip.hxx>
+#include <vector>
+#include <sortedobjs.hxx>
+#include <sortopt.hxx>
+#include <algorithm>
+#include <iterator>
+#include <boost/bind.hpp>
+#include <switerator.hxx>
+
+using namespace ::com::sun::star;
+using ::rtl::OUString;
+
+namespace sw {
+
+sal_Bool SupportsServiceImpl(
+ size_t const nServices, char const*const pServices[],
+ ::rtl::OUString const & rServiceName)
+{
+ for (size_t i = 0; i < nServices; ++i)
+ {
+ if (rServiceName.equalsAscii(pServices[i]))
+ {
+ return sal_True;
+ }
+ }
+ return sal_False;
+}
+
+uno::Sequence< ::rtl::OUString >
+GetSupportedServiceNamesImpl(
+ size_t const nServices, char const*const pServices[])
+{
+ uno::Sequence< ::rtl::OUString > ret(nServices);
+ for (size_t i = 0; i < nServices; ++i)
+ {
+ ret[i] = rtl::OUString::createFromAscii(pServices[i]);
+ }
+ return ret;
+}
+
+} // namespace sw
+
+namespace sw {
+
+void DeepCopyPaM(SwPaM const & rSource, SwPaM & rTarget)
+{
+ rTarget = rSource;
+
+ if (rSource.GetNext() != &rSource)
+ {
+ SwPaM *pPam = static_cast<SwPaM *>(rSource.GetNext());
+ do
+ {
+ // create new PaM
+ SwPaM *const pNew = new SwPaM(*pPam);
+ // insert into ring
+ pNew->MoveTo(&rTarget);
+ pPam = static_cast<SwPaM *>(pPam->GetNext());
+ }
+ while (pPam != &rSource);
+ }
+}
+
+} // namespace sw
+
+struct FrameDependSortListLess
+{
+ bool operator() (FrameDependSortListEntry const& r1,
+ FrameDependSortListEntry const& r2) const
+ {
+ return (r1.nIndex < r2.nIndex)
+ || ((r1.nIndex == r2.nIndex) && (r1.nOrder < r2.nOrder));
+ }
+};
+
+// OD 2004-05-07 #i28701# - adjust 4th parameter
+void CollectFrameAtNode( SwClient& rClnt, const SwNodeIndex& rIdx,
+ FrameDependSortList_t & rFrames,
+ const bool _bAtCharAnchoredObjs )
+{
+ // _bAtCharAnchoredObjs:
+ // <sal_True>: at-character anchored objects are collected
+ // <sal_False>: at-paragraph anchored objects are collected
+
+ // alle Rahmen, Grafiken und OLEs suchen, die an diesem Absatz
+ // gebunden sind
+ SwDoc* pDoc = rIdx.GetNode().GetDoc();
+
+ sal_uInt16 nChkType = static_cast< sal_uInt16 >((_bAtCharAnchoredObjs)
+ ? FLY_AT_CHAR : FLY_AT_PARA);
+ const SwCntntFrm* pCFrm;
+ const SwCntntNode* pCNd;
+ if( pDoc->GetCurrentViewShell() && //swmod 071108//swmod 071225
+ 0 != (pCNd = rIdx.GetNode().GetCntntNode()) &&
+ 0 != (pCFrm = pCNd->getLayoutFrm( pDoc->GetCurrentLayout())) )
+ {
+ const SwSortedObjs *pObjs = pCFrm->GetDrawObjs();
+ if( pObjs )
+ for( sal_uInt16 i = 0; i < pObjs->Count(); ++i )
+ {
+ SwAnchoredObject* pAnchoredObj = (*pObjs)[i];
+ SwFrmFmt& rFmt = pAnchoredObj->GetFrmFmt();
+ if ( rFmt.GetAnchor().GetAnchorId() == nChkType )
+ {
+ // create SwDepend and insert into array
+ SwDepend* pNewDepend = new SwDepend( &rClnt, &rFmt );
+ xub_StrLen idx =
+ rFmt.GetAnchor().GetCntntAnchor()->nContent.GetIndex();
+ sal_uInt32 nOrder = rFmt.GetAnchor().GetOrder();
+
+ // OD 2004-05-07 #i28701# - sorting no longer needed,
+ // because list <SwSortedObjs> is already sorted.
+ FrameDependSortListEntry entry(idx, nOrder, pNewDepend);
+ rFrames.push_back(entry);
+ }
+ }
+ }
+ else
+ {
+ const SwSpzFrmFmts& rFmts = *pDoc->GetSpzFrmFmts();
+ sal_uInt16 nSize = rFmts.Count();
+ for ( sal_uInt16 i = 0; i < nSize; i++)
+ {
+ const SwFrmFmt* pFmt = rFmts[ i ];
+ const SwFmtAnchor& rAnchor = pFmt->GetAnchor();
+ const SwPosition* pAnchorPos;
+ if( rAnchor.GetAnchorId() == nChkType &&
+ 0 != (pAnchorPos = rAnchor.GetCntntAnchor()) &&
+ pAnchorPos->nNode == rIdx )
+ {
+ //jetzt einen SwDepend anlegen und in das Array einfuegen
+ SwDepend* pNewDepend = new SwDepend( &rClnt, (SwFrmFmt*)pFmt);
+
+ // OD 2004-05-07 #i28701# - determine insert position for
+ // sorted <rFrameArr>
+ xub_StrLen nIndex = pAnchorPos->nContent.GetIndex();
+ sal_uInt32 nOrder = rAnchor.GetOrder();
+
+ FrameDependSortListEntry entry(nIndex, nOrder, pNewDepend);
+ rFrames.push_back(entry);
+ }
+ }
+ ::std::sort(rFrames.begin(), rFrames.end(), FrameDependSortListLess());
+ }
+}
+
+/****************************************************************************
+ ActionContext
+****************************************************************************/
+UnoActionContext::UnoActionContext(SwDoc *const pDoc)
+ : m_pDoc(pDoc)
+{
+ SwRootFrm *const pRootFrm = m_pDoc->GetCurrentLayout();
+ if (pRootFrm)
+ {
+ pRootFrm->StartAllAction();
+ }
+}
+
+UnoActionContext::~UnoActionContext()
+{
+ // Doc may already have been removed here
+ if (m_pDoc)
+ {
+ SwRootFrm *const pRootFrm = m_pDoc->GetCurrentLayout();
+ if (pRootFrm)
+ {
+ pRootFrm->EndAllAction();
+ }
+ }
+}
+
+/****************************************************************************
+ ActionRemoveContext
+****************************************************************************/
+UnoActionRemoveContext::UnoActionRemoveContext(SwDoc *const pDoc)
+ : m_pDoc(pDoc)
+{
+ SwRootFrm *const pRootFrm = m_pDoc->GetCurrentLayout();
+ if (pRootFrm)
+ {
+ pRootFrm->UnoRemoveAllActions();
+ }
+}
+
+UnoActionRemoveContext::~UnoActionRemoveContext()
+{
+ SwRootFrm *const pRootFrm = m_pDoc->GetCurrentLayout();
+ if (pRootFrm)
+ {
+ pRootFrm->UnoRestoreAllActions();
+ }
+}
+
+void ClientModify(SwClient* pClient, const SfxPoolItem *pOld, const SfxPoolItem *pNew)
+{
+ switch( pOld ? pOld->Which() : 0 )
+ {
+ case RES_REMOVE_UNO_OBJECT:
+ case RES_OBJECTDYING:
+ if( (void*)pClient->GetRegisteredIn() == ((SwPtrMsgPoolItem *)pOld)->pObject )
+ ((SwModify*)pClient->GetRegisteredIn())->Remove(pClient);
+ break;
+
+ case RES_FMT_CHG:
+ // wurden wir an das neue umgehaengt und wird das alte geloscht?
+ if( ((SwFmtChg*)pNew)->pChangedFmt == pClient->GetRegisteredIn() &&
+ ((SwFmtChg*)pOld)->pChangedFmt->IsFmtInDTOR() )
+ ((SwModify*)pClient->GetRegisteredIn())->Remove(pClient);
+ break;
+ }
+}
+
+void SwUnoCursorHelper::SetCrsrAttr(SwPaM & rPam,
+ const SfxItemSet& rSet,
+ const SetAttrMode nAttrMode, const bool bTableMode)
+{
+ const SetAttrMode nFlags = nAttrMode | nsSetAttrMode::SETATTR_APICALL;
+ SwDoc* pDoc = rPam.GetDoc();
+ //StartEndAction
+ UnoActionContext aAction(pDoc);
+ if (rPam.GetNext() != &rPam) // Ring of Cursors
+ {
+ pDoc->GetIDocumentUndoRedo().StartUndo(UNDO_INSATTR, NULL);
+
+ SwPaM *pCurrent = &rPam;
+ do
+ {
+ if (pCurrent->HasMark() &&
+ ( (bTableMode) ||
+ (*pCurrent->GetPoint() != *pCurrent->GetMark()) ))
+ {
+ pDoc->InsertItemSet(*pCurrent, rSet, nFlags);
+ }
+ pCurrent= static_cast<SwPaM *>(pCurrent->GetNext());
+ } while (pCurrent != &rPam);
+
+ pDoc->GetIDocumentUndoRedo().EndUndo(UNDO_INSATTR, NULL);
+ }
+ else
+ {
+// if( !HasSelection() )
+// UpdateAttr();
+ pDoc->InsertItemSet( rPam, rSet, nFlags );
+ }
+ //#outline level,add by zhaojianwei
+ if( rSet.GetItemState( RES_PARATR_OUTLINELEVEL, false ) >= SFX_ITEM_AVAILABLE )
+ {
+ SwTxtNode * pTmpNode = rPam.GetNode()->GetTxtNode();
+ if ( pTmpNode )
+ {
+ rPam.GetDoc()->GetNodes().UpdateOutlineNode( *pTmpNode );
+ }
+ }
+ //<-end,zhaojianwei
+}
+
+// --> OD 2006-07-12 #i63870#
+// split third parameter <bCurrentAttrOnly> into new parameters <bOnlyTxtAttr>
+// and <bGetFromChrFmt> to get better control about resulting <SfxItemSet>
+void SwUnoCursorHelper::GetCrsrAttr(SwPaM & rPam,
+ SfxItemSet & rSet, const bool bOnlyTxtAttr, const bool bGetFromChrFmt)
+{
+ static const sal_uInt16 nMaxLookup = 1000;
+ SfxItemSet aSet( *rSet.GetPool(), rSet.GetRanges() );
+ SfxItemSet *pSet = &rSet;
+ SwPaM *pCurrent = & rPam;
+ do
+ {
+ SwPosition const & rStart( *pCurrent->Start() );
+ SwPosition const & rEnd( *pCurrent->End() );
+ const sal_uLong nSttNd = rStart.nNode.GetIndex();
+ const sal_uLong nEndNd = rEnd .nNode.GetIndex();
+
+ if (nEndNd - nSttNd >= nMaxLookup)
+ {
+ rSet.ClearItem();
+ rSet.InvalidateAllItems();
+ return;// uno::Any();
+ }
+
+ // the first node inserts the values into the get set
+ // all other nodes merge their values into the get set
+ for (sal_uLong n = nSttNd; n <= nEndNd; ++n)
+ {
+ SwNode *const pNd = rPam.GetDoc()->GetNodes()[ n ];
+ switch (pNd->GetNodeType())
+ {
+ case ND_TEXTNODE:
+ {
+ const xub_StrLen nStart = (n == nSttNd)
+ ? rStart.nContent.GetIndex() : 0;
+ const xub_StrLen nEnd = (n == nEndNd)
+ ? rEnd.nContent.GetIndex()
+ : static_cast<SwTxtNode*>(pNd)->GetTxt().Len();
+ static_cast<SwTxtNode*>(pNd)->GetAttr(
+ *pSet, nStart, nEnd, bOnlyTxtAttr, bGetFromChrFmt);
+ }
+ break;
+ case ND_GRFNODE:
+ case ND_OLENODE:
+ static_cast<SwCntntNode*>(pNd)->GetAttr( *pSet );
+ break;
+
+ default:
+ continue; // skip this node
+ }
+
+ if (pSet != &rSet)
+ {
+ rSet.MergeValues( aSet );
+ }
+ else
+ {
+ pSet = &aSet;
+ }
+
+ if (aSet.Count())
+ {
+ aSet.ClearItem();
+ }
+ }
+ pCurrent= static_cast<SwPaM *>(pCurrent->GetNext());
+ } while ( pCurrent != &rPam );
+}
+
+/******************************************************************
+ * SwXParagraphEnumeration
+ ******************************************************************/
+class SwXParagraphEnumeration::Impl
+ : public SwClient
+{
+
+public:
+
+ uno::Reference< text::XText > const m_xParentText;
+ const CursorType m_eCursorType;
+ /// Start node of the cell _or_ table the enumeration belongs to.
+ /// Used to restrict the movement of the UNO cursor to the cell and its
+ /// embedded tables.
+ SwStartNode const*const m_pOwnStartNode;
+ SwTable const*const m_pOwnTable;
+ const sal_uLong m_nEndIndex;
+ sal_Int32 m_nFirstParaStart;
+ sal_Int32 m_nLastParaEnd;
+ bool m_bFirstParagraph;
+ uno::Reference< text::XTextContent > m_xNextPara;
+
+ Impl( uno::Reference< text::XText > const& xParent,
+ ::std::auto_ptr<SwUnoCrsr> pCursor,
+ const CursorType eType,
+ SwStartNode const*const pStartNode, SwTable const*const pTable)
+ : SwClient( pCursor.release() )
+ , m_xParentText( xParent )
+ , m_eCursorType( eType )
+ // remember table and start node for later travelling
+ // (used in export of tables in tables)
+ , m_pOwnStartNode( pStartNode )
+ // for import of tables in tables we have to remember the actual
+ // table and start node of the current position in the enumeration.
+ , m_pOwnTable( pTable )
+ , m_nEndIndex( GetCursor()->End()->nNode.GetIndex() )
+ , m_nFirstParaStart( -1 )
+ , m_nLastParaEnd( -1 )
+ , m_bFirstParagraph( true )
+ {
+ OSL_ENSURE(m_xParentText.is(), "SwXParagraphEnumeration: no parent?");
+ OSL_ENSURE(GetRegisteredIn(), "SwXParagraphEnumeration: no cursor?");
+ OSL_ENSURE( !((CURSOR_SELECTION_IN_TABLE == eType) ||
+ (CURSOR_TBLTEXT == eType))
+ || (m_pOwnTable && m_pOwnStartNode),
+ "SwXParagraphEnumeration: table type but no start node or table?");
+
+ if ((CURSOR_SELECTION == m_eCursorType) ||
+ (CURSOR_SELECTION_IN_TABLE == m_eCursorType))
+ {
+ SwUnoCrsr & rCursor = *GetCursor();
+ rCursor.Normalize();
+ m_nFirstParaStart = rCursor.GetPoint()->nContent.GetIndex();
+ m_nLastParaEnd = rCursor.GetMark()->nContent.GetIndex();
+ rCursor.DeleteMark();
+ }
+ }
+
+ ~Impl() {
+ // Impl owns the cursor; delete it here: SolarMutex is locked
+ delete GetRegisteredIn();
+ }
+
+ SwUnoCrsr * GetCursor() {
+ return static_cast<SwUnoCrsr*>(
+ const_cast<SwModify*>(GetRegisteredIn()));
+ }
+
+ uno::Reference< text::XTextContent > NextElement_Impl()
+ throw (container::NoSuchElementException, lang::WrappedTargetException,
+ uno::RuntimeException);
+protected:
+ // SwClient
+ virtual void Modify( const SfxPoolItem *pOld, const SfxPoolItem *pNew);
+
+};
+
+void SwXParagraphEnumeration::Impl::Modify( const SfxPoolItem *pOld, const SfxPoolItem *pNew)
+{
+ ClientModify(this, pOld, pNew);
+}
+
+SwXParagraphEnumeration::SwXParagraphEnumeration(
+ uno::Reference< text::XText > const& xParent,
+ ::std::auto_ptr<SwUnoCrsr> pCursor,
+ const CursorType eType,
+ SwStartNode const*const pStartNode, SwTable const*const pTable)
+ : m_pImpl( new SwXParagraphEnumeration::Impl(xParent, pCursor, eType,
+ pStartNode, pTable) )
+{
+}
+
+SwXParagraphEnumeration::~SwXParagraphEnumeration()
+{
+}
+
+OUString SAL_CALL
+SwXParagraphEnumeration::getImplementationName() throw (uno::RuntimeException)
+{
+ return C2U("SwXParagraphEnumeration");
+}
+
+static char const*const g_ServicesParagraphEnum[] =
+{
+ "com.sun.star.text.ParagraphEnumeration",
+};
+
+static const size_t g_nServicesParagraphEnum(
+ SAL_N_ELEMENTS(g_ServicesParagraphEnum));
+
+sal_Bool SAL_CALL
+SwXParagraphEnumeration::supportsService(const OUString& rServiceName)
+throw (uno::RuntimeException)
+{
+ return ::sw::SupportsServiceImpl(
+ g_nServicesParagraphEnum, g_ServicesParagraphEnum, rServiceName);
+}
+
+uno::Sequence< OUString > SAL_CALL
+SwXParagraphEnumeration::getSupportedServiceNames()
+throw (uno::RuntimeException)
+{
+ return ::sw::GetSupportedServiceNamesImpl(
+ g_nServicesParagraphEnum, g_ServicesParagraphEnum);
+}
+
+sal_Bool SAL_CALL
+SwXParagraphEnumeration::hasMoreElements() throw (uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+
+ return (m_pImpl->m_bFirstParagraph) ? sal_True : m_pImpl->m_xNextPara.is();
+}
+
+//!! compare to SwShellTableCrsr::FillRects() in viscrs.cxx
+static SwTableNode *
+lcl_FindTopLevelTable(
+ SwTableNode *const pTblNode, SwTable const*const pOwnTable)
+{
+ // find top-most table in current context (section) level
+
+ SwTableNode * pLast = pTblNode;
+ for (SwTableNode* pTmp = pLast;
+ pTmp != NULL && &pTmp->GetTable() != pOwnTable; /* we must not go up higher than the own table! */
+ pTmp = pTmp->StartOfSectionNode()->FindTableNode() )
+ {
+ pLast = pTmp;
+ }
+ return pLast;
+}
+
+static bool
+lcl_CursorIsInSection(
+ SwUnoCrsr const*const pUnoCrsr, SwStartNode const*const pOwnStartNode)
+{
+ // returns true if the cursor is in the section (or in a sub section!)
+ // represented by pOwnStartNode
+
+ bool bRes = true;
+ if (pUnoCrsr && pOwnStartNode)
+ {
+ const SwEndNode * pOwnEndNode = pOwnStartNode->EndOfSectionNode();
+ bRes = pOwnStartNode->GetIndex() <= pUnoCrsr->Start()->nNode.GetIndex() &&
+ pUnoCrsr->End()->nNode.GetIndex() <= pOwnEndNode->GetIndex();
+ }
+ return bRes;
+}
+
+uno::Reference< text::XTextContent >
+SwXParagraphEnumeration::Impl::NextElement_Impl()
+throw (container::NoSuchElementException, lang::WrappedTargetException,
+ uno::RuntimeException)
+{
+ SwUnoCrsr *const pUnoCrsr = GetCursor();
+ if (!pUnoCrsr)
+ {
+ throw uno::RuntimeException();
+ }
+
+ // check for exceeding selections
+ if (!m_bFirstParagraph &&
+ ((CURSOR_SELECTION == m_eCursorType) ||
+ (CURSOR_SELECTION_IN_TABLE == m_eCursorType)))
+ {
+ SwPosition* pStart = pUnoCrsr->Start();
+ const ::std::auto_ptr<SwUnoCrsr> aNewCrsr(
+ pUnoCrsr->GetDoc()->CreateUnoCrsr(*pStart, sal_False) );
+ // one may also go into tables here
+ if ((CURSOR_TBLTEXT != m_eCursorType) &&
+ (CURSOR_SELECTION_IN_TABLE != m_eCursorType))
+ {
+ aNewCrsr->SetRemainInSection( sal_False );
+ }
+
+ // os 2005-01-14: This part is only necessary to detect movements out
+ // of a selection; if there is no selection we don't have to care
+ SwTableNode *const pTblNode = aNewCrsr->GetNode()->FindTableNode();
+ if (((CURSOR_TBLTEXT != m_eCursorType) &&
+ (CURSOR_SELECTION_IN_TABLE != m_eCursorType)) && pTblNode)
+ {
+ aNewCrsr->GetPoint()->nNode = pTblNode->EndOfSectionIndex();
+ aNewCrsr->Move(fnMoveForward, fnGoNode);
+ }
+ else
+ {
+ aNewCrsr->MovePara(fnParaNext, fnParaStart);
+ }
+ if (m_nEndIndex < aNewCrsr->Start()->nNode.GetIndex())
+ {
+ return 0;
+ }
+ }
+
+ sal_Bool bInTable = sal_False;
+ if (!m_bFirstParagraph)
+ {
+ pUnoCrsr->SetRemainInSection( sal_False );
+ // what to do if already in a table?
+ SwTableNode * pTblNode = pUnoCrsr->GetNode()->FindTableNode();
+ pTblNode = lcl_FindTopLevelTable( pTblNode, m_pOwnTable );
+ if (pTblNode && (&pTblNode->GetTable() != m_pOwnTable))
+ {
+ // this is a foreign table: go to end
+ pUnoCrsr->GetPoint()->nNode = pTblNode->EndOfSectionIndex();
+ if (!pUnoCrsr->Move(fnMoveForward, fnGoNode))
+ {
+ return 0;
+ }
+ bInTable = sal_True;
+ }
+ }
+
+ uno::Reference< text::XTextContent > xRef;
+ // the cursor must remain in the current section or a subsection
+ // before AND after the movement...
+ if (lcl_CursorIsInSection( pUnoCrsr, m_pOwnStartNode ) &&
+ (m_bFirstParagraph || bInTable ||
+ (pUnoCrsr->MovePara(fnParaNext, fnParaStart) &&
+ lcl_CursorIsInSection( pUnoCrsr, m_pOwnStartNode ))))
+ {
+ SwPosition* pStart = pUnoCrsr->Start();
+ const sal_Int32 nFirstContent =
+ (m_bFirstParagraph) ? m_nFirstParaStart : -1;
+ const sal_Int32 nLastContent =
+ (m_nEndIndex == pStart->nNode.GetIndex()) ? m_nLastParaEnd : -1;
+
+ // position in a table, or in a simple paragraph?
+ SwTableNode * pTblNode = pUnoCrsr->GetNode()->FindTableNode();
+ pTblNode = lcl_FindTopLevelTable( pTblNode, m_pOwnTable );
+ if (/*CURSOR_TBLTEXT != eCursorType && CURSOR_SELECTION_IN_TABLE != eCursorType && */
+ pTblNode && (&pTblNode->GetTable() != m_pOwnTable))
+ {
+ // this is a foreign table
+ SwFrmFmt* pTableFmt =
+ static_cast<SwFrmFmt*>(pTblNode->GetTable().GetFrmFmt());
+ text::XTextTable *const pTable =
+ SwXTextTables::GetObject( *pTableFmt );
+ xRef = static_cast<text::XTextContent*>(
+ static_cast<SwXTextTable*>(pTable));
+ }
+ else
+ {
+ text::XText *const pText = m_xParentText.get();
+ xRef = SwXParagraph::CreateXParagraph(*pUnoCrsr->GetDoc(),
+ *pStart->nNode.GetNode().GetTxtNode(),
+ static_cast<SwXText*>(pText), nFirstContent, nLastContent);
+ }
+ }
+
+ return xRef;
+}
+
+uno::Any SAL_CALL SwXParagraphEnumeration::nextElement()
+throw (container::NoSuchElementException, lang::WrappedTargetException,
+ uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+
+ if (m_pImpl->m_bFirstParagraph)
+ {
+ m_pImpl->m_xNextPara = m_pImpl->NextElement_Impl();
+ m_pImpl->m_bFirstParagraph = false;
+ }
+ const uno::Reference< text::XTextContent > xRef = m_pImpl->m_xNextPara;
+ if (!xRef.is())
+ {
+ throw container::NoSuchElementException();
+ }
+ m_pImpl->m_xNextPara = m_pImpl->NextElement_Impl();
+
+ uno::Any aRet;
+ aRet <<= xRef;
+ return aRet;
+}
+
+/******************************************************************
+ * SwXTextRange
+ ******************************************************************/
+class SwXTextRange::Impl
+ : public SwClient
+{
+
+public:
+
+ const SfxItemPropertySet & m_rPropSet;
+ const enum RangePosition m_eRangePosition;
+ SwDoc & m_rDoc;
+ uno::Reference<text::XText> m_xParentText;
+ SwDepend m_ObjectDepend; // register at format of table or frame
+ ::sw::mark::IMark * m_pMark;
+
+ Impl( SwDoc & rDoc, const enum RangePosition eRange,
+ SwFrmFmt *const pTblFmt = 0,
+ const uno::Reference< text::XText > & xParent = 0)
+ : SwClient()
+ , m_rPropSet(*aSwMapProvider.GetPropertySet(PROPERTY_MAP_TEXT_CURSOR))
+ , m_eRangePosition(eRange)
+ , m_rDoc(rDoc)
+ , m_xParentText(xParent)
+ , m_ObjectDepend(this, pTblFmt)
+ , m_pMark(0)
+ {
+ }
+
+ ~Impl()
+ {
+ // Impl owns the bookmark; delete it here: SolarMutex is locked
+ Invalidate();
+ }
+
+ void Invalidate()
+ {
+ if (m_pMark)
+ {
+ m_rDoc.getIDocumentMarkAccess()->deleteMark(m_pMark);
+ m_pMark = 0;
+ }
+ }
+
+ const ::sw::mark::IMark * GetBookmark() const { return m_pMark; }
+protected:
+ // SwClient
+ virtual void Modify(const SfxPoolItem *pOld, const SfxPoolItem *pNew);
+
+};
+
+void SwXTextRange::Impl::Modify(const SfxPoolItem *pOld, const SfxPoolItem *pNew)
+{
+ const bool bAlreadyRegistered = 0 != GetRegisteredIn();
+ ClientModify(this, pOld, pNew);
+ if (m_ObjectDepend.GetRegisteredIn())
+ {
+ ClientModify(&m_ObjectDepend, pOld, pNew);
+ // if the depend was removed then the range must be removed too
+ if (!m_ObjectDepend.GetRegisteredIn() && GetRegisteredIn())
+ {
+ const_cast<SwModify*>(GetRegisteredIn())->Remove(this);
+ }
+ // or if the range has been removed but the depend ist still
+ // connected then the depend must be removed
+ else if (bAlreadyRegistered && !GetRegisteredIn() &&
+ m_ObjectDepend.GetRegisteredIn())
+ {
+ const_cast<SwModify*>(m_ObjectDepend.GetRegisteredIn())
+ ->Remove(& m_ObjectDepend);
+ }
+ }
+ if (!GetRegisteredIn())
+ {
+ m_pMark = 0;
+ }
+}
+
+SwXTextRange::SwXTextRange(SwPaM& rPam,
+ const uno::Reference< text::XText > & xParent,
+ const enum RangePosition eRange)
+ : m_pImpl( new SwXTextRange::Impl(*rPam.GetDoc(), eRange, 0, xParent) )
+{
+ SetPositions(rPam);
+}
+
+SwXTextRange::SwXTextRange(SwFrmFmt& rTblFmt)
+ : m_pImpl(
+ new SwXTextRange::Impl(*rTblFmt.GetDoc(), RANGE_IS_TABLE, &rTblFmt) )
+{
+ SwTable *const pTable = SwTable::FindTable( &rTblFmt );
+ SwTableNode *const pTblNode = pTable->GetTableNode();
+ SwPosition aPosition( *pTblNode );
+ SwPaM aPam( aPosition );
+
+ SetPositions( aPam );
+}
+
+SwXTextRange::~SwXTextRange()
+{
+}
+
+const SwDoc * SwXTextRange::GetDoc() const
+{
+ return & m_pImpl->m_rDoc;
+}
+
+SwDoc * SwXTextRange::GetDoc()
+{
+ return & m_pImpl->m_rDoc;
+}
+
+void SwXTextRange::Invalidate()
+{
+ m_pImpl->Invalidate();
+}
+
+void SwXTextRange::SetPositions(const SwPaM& rPam)
+{
+ m_pImpl->Invalidate();
+ IDocumentMarkAccess* const pMA = m_pImpl->m_rDoc.getIDocumentMarkAccess();
+ m_pImpl->m_pMark = pMA->makeMark(rPam, ::rtl::OUString(),
+ IDocumentMarkAccess::UNO_BOOKMARK);
+ m_pImpl->m_pMark->Add(m_pImpl.get());
+}
+
+void SwXTextRange::DeleteAndInsert(
+ const ::rtl::OUString& rText, const bool bForceExpandHints)
+throw (uno::RuntimeException)
+{
+ if (RANGE_IS_TABLE == m_pImpl->m_eRangePosition)
+ {
+ // setString on table not allowed
+ throw uno::RuntimeException();
+ }
+
+ const SwPosition aPos(GetDoc()->GetNodes().GetEndOfContent());
+ SwCursor aCursor(aPos, 0, false);
+ if (GetPositions(aCursor))
+ {
+ UnoActionContext aAction(& m_pImpl->m_rDoc);
+ m_pImpl->m_rDoc.GetIDocumentUndoRedo().StartUndo(UNDO_INSERT, NULL);
+ if (aCursor.HasMark())
+ {
+ m_pImpl->m_rDoc.DeleteAndJoin(aCursor);
+ }
+
+ if (rText.getLength())
+ {
+ SwUnoCursorHelper::DocInsertStringSplitCR(
+ m_pImpl->m_rDoc, aCursor, rText, bForceExpandHints);
+
+ SwUnoCursorHelper::SelectPam(aCursor, true);
+ aCursor.Left(rText.getLength(), CRSR_SKIP_CHARS, sal_False, sal_False);
+ }
+ SetPositions(aCursor);
+ m_pImpl->m_rDoc.GetIDocumentUndoRedo().EndUndo(UNDO_INSERT, NULL);
+ }
+}
+
+const uno::Sequence< sal_Int8 > & SwXTextRange::getUnoTunnelId()
+{
+ static uno::Sequence< sal_Int8 > aSeq = ::CreateUnoTunnelId();
+ return aSeq;
+}
+
+// XUnoTunnel
+sal_Int64 SAL_CALL
+SwXTextRange::getSomething(const uno::Sequence< sal_Int8 >& rId)
+throw (uno::RuntimeException)
+{
+ return ::sw::UnoTunnelImpl<SwXTextRange>(rId, this);
+}
+
+OUString SAL_CALL
+SwXTextRange::getImplementationName() throw (uno::RuntimeException)
+{
+ return OUString(RTL_CONSTASCII_USTRINGPARAM("SwXTextRange"));
+}
+
+static char const*const g_ServicesTextRange[] =
+{
+ "com.sun.star.text.TextRange",
+ "com.sun.star.style.CharacterProperties",
+ "com.sun.star.style.CharacterPropertiesAsian",
+ "com.sun.star.style.CharacterPropertiesComplex",
+ "com.sun.star.style.ParagraphProperties",
+ "com.sun.star.style.ParagraphPropertiesAsian",
+ "com.sun.star.style.ParagraphPropertiesComplex",
+};
+
+static const size_t g_nServicesTextRange(
+ SAL_N_ELEMENTS(g_ServicesTextRange));
+
+sal_Bool SAL_CALL SwXTextRange::supportsService(const OUString& rServiceName)
+throw (uno::RuntimeException)
+{
+ return ::sw::SupportsServiceImpl(
+ g_nServicesTextRange, g_ServicesTextRange, rServiceName);
+}
+
+uno::Sequence< OUString > SAL_CALL
+SwXTextRange::getSupportedServiceNames() throw (uno::RuntimeException)
+{
+ return ::sw::GetSupportedServiceNamesImpl(
+ g_nServicesTextRange, g_ServicesTextRange);
+}
+
+uno::Reference< text::XText > SAL_CALL
+SwXTextRange::getText() throw (uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+
+ if (!m_pImpl->m_xParentText.is())
+ {
+ if (m_pImpl->m_eRangePosition == RANGE_IS_TABLE &&
+ m_pImpl->m_ObjectDepend.GetRegisteredIn())
+ {
+ SwFrmFmt const*const pTblFmt = static_cast<SwFrmFmt const*>(
+ m_pImpl->m_ObjectDepend.GetRegisteredIn());
+ SwTable const*const pTable = SwTable::FindTable( pTblFmt );
+ SwTableNode const*const pTblNode = pTable->GetTableNode();
+ const SwPosition aPosition( *pTblNode );
+ m_pImpl->m_xParentText =
+ ::sw::CreateParentXText(m_pImpl->m_rDoc, aPosition);
+ }
+ }
+ OSL_ENSURE(m_pImpl->m_xParentText.is(), "SwXTextRange::getText: no text");
+ return m_pImpl->m_xParentText;
+}
+
+uno::Reference< text::XTextRange > SAL_CALL
+SwXTextRange::getStart() throw (uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+
+ uno::Reference< text::XTextRange > xRet;
+ ::sw::mark::IMark const * const pBkmk = m_pImpl->GetBookmark();
+ if (!m_pImpl->m_xParentText.is())
+ {
+ getText();
+ }
+ if(pBkmk)
+ {
+ SwPaM aPam(pBkmk->GetMarkStart());
+ xRet = new SwXTextRange(aPam, m_pImpl->m_xParentText);
+ }
+ else if (RANGE_IS_TABLE == m_pImpl->m_eRangePosition)
+ {
+ // start and end are this, if its a table
+ xRet = this;
+ }
+ else
+ {
+ throw uno::RuntimeException();
+ }
+ return xRet;
+}
+
+uno::Reference< text::XTextRange > SAL_CALL
+SwXTextRange::getEnd() throw (uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+
+ uno::Reference< text::XTextRange > xRet;
+ ::sw::mark::IMark const * const pBkmk = m_pImpl->GetBookmark();
+ if (!m_pImpl->m_xParentText.is())
+ {
+ getText();
+ }
+ if(pBkmk)
+ {
+ SwPaM aPam(pBkmk->GetMarkEnd());
+ xRet = new SwXTextRange(aPam, m_pImpl->m_xParentText);
+ }
+ else if (RANGE_IS_TABLE == m_pImpl->m_eRangePosition)
+ {
+ // start and end are this, if its a table
+ xRet = this;
+ }
+ else
+ {
+ throw uno::RuntimeException();
+ }
+ return xRet;
+}
+
+OUString SAL_CALL SwXTextRange::getString() throw (uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+
+ OUString sRet;
+ // for tables there is no bookmark, thus also no text
+ // one could export the table as ASCII here maybe?
+ SwPaM aPaM(GetDoc()->GetNodes());
+ if (GetPositions(aPaM) && aPaM.HasMark())
+ {
+ SwUnoCursorHelper::GetTextFromPam(aPaM, sRet);
+ }
+ return sRet;
+}
+
+void SAL_CALL SwXTextRange::setString(const OUString& rString)
+throw (uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+
+ DeleteAndInsert(rString, false);
+}
+
+bool SwXTextRange::GetPositions(SwPaM& rToFill) const
+{
+ ::sw::mark::IMark const * const pBkmk = m_pImpl->GetBookmark();
+ if(pBkmk)
+ {
+ *rToFill.GetPoint() = pBkmk->GetMarkPos();
+ if(pBkmk->IsExpanded())
+ {
+ rToFill.SetMark();
+ *rToFill.GetMark() = pBkmk->GetOtherMarkPos();
+ }
+ else
+ {
+ rToFill.DeleteMark();
+ }
+ return true;
+ }
+ return false;
+}
+
+namespace sw {
+
+bool XTextRangeToSwPaM( SwUnoInternalPaM & rToFill,
+ const uno::Reference< text::XTextRange > & xTextRange)
+{
+ bool bRet = false;
+
+ uno::Reference<lang::XUnoTunnel> xRangeTunnel( xTextRange, uno::UNO_QUERY);
+ SwXTextRange* pRange = 0;
+ OTextCursorHelper* pCursor = 0;
+ SwXTextPortion* pPortion = 0;
+ SwXText* pText = 0;
+ SwXParagraph* pPara = 0;
+ if(xRangeTunnel.is())
+ {
+ pRange = ::sw::UnoTunnelGetImplementation<SwXTextRange>(xRangeTunnel);
+ pCursor =
+ ::sw::UnoTunnelGetImplementation<OTextCursorHelper>(xRangeTunnel);
+ pPortion=
+ ::sw::UnoTunnelGetImplementation<SwXTextPortion>(xRangeTunnel);
+ pText = ::sw::UnoTunnelGetImplementation<SwXText>(xRangeTunnel);
+ pPara = ::sw::UnoTunnelGetImplementation<SwXParagraph>(xRangeTunnel);
+ }
+
+ // if it's a text then create a temporary cursor there and re-use
+ // the pCursor variable
+ // #i108489#: Reference in outside scope to keep cursor alive
+ uno::Reference< text::XTextCursor > xTextCursor;
+ if (pText)
+ {
+ xTextCursor.set( pText->CreateCursor() );
+ xTextCursor->gotoEnd(sal_True);
+ const uno::Reference<lang::XUnoTunnel> xCrsrTunnel(
+ xTextCursor, uno::UNO_QUERY);
+ pCursor =
+ ::sw::UnoTunnelGetImplementation<OTextCursorHelper>(xCrsrTunnel);
+ }
+ if(pRange && pRange->GetDoc() == rToFill.GetDoc())
+ {
+ bRet = pRange->GetPositions(rToFill);
+ }
+ else
+ {
+ if (pPara)
+ {
+ bRet = pPara->SelectPaM(rToFill);
+ }
+ else
+ {
+ SwDoc* const pDoc = (pCursor) ? pCursor->GetDoc()
+ : ((pPortion) ? pPortion->GetCursor()->GetDoc() : 0);
+ const SwPaM* const pUnoCrsr = (pCursor) ? pCursor->GetPaM()
+ : ((pPortion) ? pPortion->GetCursor() : 0);
+ if (pUnoCrsr && pDoc == rToFill.GetDoc())
+ {
+ DBG_ASSERT((SwPaM*)pUnoCrsr->GetNext() == pUnoCrsr,
+ "what to do about rings?");
+ bRet = true;
+ *rToFill.GetPoint() = *pUnoCrsr->GetPoint();
+ if (pUnoCrsr->HasMark())
+ {
+ rToFill.SetMark();
+ *rToFill.GetMark() = *pUnoCrsr->GetMark();
+ }
+ else
+ rToFill.DeleteMark();
+ }
+ }
+ }
+ return bRet;
+}
+
+static bool
+lcl_IsStartNodeInFormat(const bool bHeader, SwStartNode *const pSttNode,
+ SwFrmFmt const*const pFrmFmt, SwFrmFmt*& rpFormat)
+{
+ bool bRet = false;
+ const SfxItemSet& rSet = pFrmFmt->GetAttrSet();
+ const SfxPoolItem* pItem;
+ if (SFX_ITEM_SET == rSet.GetItemState(
+ static_cast<sal_uInt16>(bHeader ? RES_HEADER : RES_FOOTER),
+ sal_True, &pItem))
+ {
+ SfxPoolItem *const pItemNonConst(const_cast<SfxPoolItem *>(pItem));
+ SwFrmFmt *const pHeadFootFmt = (bHeader) ?
+ static_cast<SwFmtHeader*>(pItemNonConst)->GetHeaderFmt() :
+ static_cast<SwFmtFooter*>(pItemNonConst)->GetFooterFmt();
+ if (pHeadFootFmt)
+ {
+ const SwFmtCntnt& rFlyCntnt = pHeadFootFmt->GetCntnt();
+ const SwNode& rNode = rFlyCntnt.GetCntntIdx()->GetNode();
+ SwStartNode const*const pCurSttNode = rNode.FindSttNodeByType(
+ (bHeader) ? SwHeaderStartNode : SwFooterStartNode);
+ if (pCurSttNode && (pCurSttNode == pSttNode))
+ {
+ rpFormat = pHeadFootFmt;
+ bRet = true;
+ }
+ }
+ }
+ return bRet;
+}
+
+} // namespace sw
+
+uno::Reference< text::XTextRange >
+SwXTextRange::CreateXTextRange(
+ SwDoc & rDoc, const SwPosition& rPos, const SwPosition *const pMark)
+{
+ const uno::Reference<text::XText> xParentText(
+ ::sw::CreateParentXText(rDoc, rPos));
+ const ::std::auto_ptr<SwUnoCrsr> pNewCrsr(
+ rDoc.CreateUnoCrsr(rPos, sal_False));
+ if(pMark)
+ {
+ pNewCrsr->SetMark();
+ *pNewCrsr->GetMark() = *pMark;
+ }
+ const bool isCell( dynamic_cast<SwXCell*>(xParentText.get()) );
+ const uno::Reference< text::XTextRange > xRet(
+ new SwXTextRange(*pNewCrsr, xParentText,
+ isCell ? RANGE_IN_CELL : RANGE_IN_TEXT) );
+ return xRet;
+}
+
+namespace sw {
+
+uno::Reference< text::XText >
+CreateParentXText(SwDoc & rDoc, const SwPosition& rPos)
+{
+ uno::Reference< text::XText > xParentText;
+ SwStartNode* pSttNode = rPos.nNode.GetNode().StartOfSectionNode();
+ while(pSttNode && pSttNode->IsSectionNode())
+ {
+ pSttNode = pSttNode->StartOfSectionNode();
+ }
+ SwStartNodeType eType = pSttNode->GetStartNodeType();
+ switch(eType)
+ {
+ case SwTableBoxStartNode:
+ {
+ SwTableNode const*const pTblNode = pSttNode->FindTableNode();
+ SwFrmFmt *const pTableFmt =
+ static_cast<SwFrmFmt*>(pTblNode->GetTable().GetFrmFmt());
+ SwTableBox *const pBox = pSttNode->GetTblBox();
+
+ xParentText = (pBox)
+ ? SwXCell::CreateXCell( pTableFmt, pBox )
+ : new SwXCell( pTableFmt, *pSttNode );
+ }
+ break;
+ case SwFlyStartNode:
+ {
+ SwFrmFmt *const pFmt = pSttNode->GetFlyFmt();
+ if (0 != pFmt)
+ {
+ SwXTextFrame* pFrame = SwIterator<SwXTextFrame,SwFmt>::FirstElement( *pFmt );
+ xParentText = pFrame ? pFrame : new SwXTextFrame( *pFmt );
+ }
+ }
+ break;
+ case SwHeaderStartNode:
+ case SwFooterStartNode:
+ {
+ const bool bHeader = (SwHeaderStartNode == eType);
+ const sal_uInt16 nPDescCount = rDoc.GetPageDescCnt();
+ for(sal_uInt16 i = 0; i < nPDescCount; i++)
+ {
+ const SwPageDesc& rDesc =
+ // C++ is retarded
+ const_cast<SwDoc const&>(rDoc).GetPageDesc( i );
+ const SwFrmFmt* pFrmFmtMaster = &rDesc.GetMaster();
+ const SwFrmFmt* pFrmFmtLeft = &rDesc.GetLeft();
+
+ SwFrmFmt* pHeadFootFmt = 0;
+ if (!lcl_IsStartNodeInFormat(bHeader, pSttNode, pFrmFmtMaster,
+ pHeadFootFmt))
+ {
+ lcl_IsStartNodeInFormat(bHeader, pSttNode, pFrmFmtLeft,
+ pHeadFootFmt);
+ }
+
+ if (pHeadFootFmt)
+ {
+ xParentText = SwXHeadFootText::CreateXHeadFootText(
+ *pHeadFootFmt, bHeader);
+ }
+ }
+ }
+ break;
+ case SwFootnoteStartNode:
+ {
+ const sal_uInt16 nFtnCnt = rDoc.GetFtnIdxs().Count();
+ uno::Reference< text::XFootnote > xRef;
+ for (sal_uInt16 n = 0; n < nFtnCnt; ++n )
+ {
+ const SwTxtFtn* pTxtFtn = rDoc.GetFtnIdxs()[ n ];
+ const SwFmtFtn& rFtn = pTxtFtn->GetFtn();
+ pTxtFtn = rFtn.GetTxtFtn();
+#if OSL_DEBUG_LEVEL > 1
+ const SwStartNode* pTmpSttNode =
+ pTxtFtn->GetStartNode()->GetNode().
+ FindSttNodeByType(SwFootnoteStartNode);
+ (void)pTmpSttNode;
+#endif
+
+ if (pSttNode == pTxtFtn->GetStartNode()->GetNode().
+ FindSttNodeByType(SwFootnoteStartNode))
+ {
+ xParentText = SwXFootnote::CreateXFootnote(rDoc, rFtn);
+ break;
+ }
+ }
+ }
+ break;
+ default:
+ {
+ // then it is the body text
+ const uno::Reference<frame::XModel> xModel =
+ rDoc.GetDocShell()->GetBaseModel();
+ const uno::Reference< text::XTextDocument > xDoc(
+ xModel, uno::UNO_QUERY);
+ xParentText = xDoc->getText();
+ }
+ }
+ OSL_ENSURE(xParentText.is(), "no parent text?");
+ return xParentText;
+}
+
+} // namespace sw
+
+uno::Reference< container::XEnumeration > SAL_CALL
+SwXTextRange::createContentEnumeration(const OUString& rServiceName)
+throw (uno::RuntimeException)
+{
+ SolarMutexGuard g;
+
+ if (!rServiceName.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("com.sun.star.text.TextContent")))
+ {
+ throw uno::RuntimeException();
+ }
+
+ if (!GetDoc() || !m_pImpl->GetBookmark())
+ {
+ throw uno::RuntimeException();
+ }
+ const SwPosition aPos(GetDoc()->GetNodes().GetEndOfContent());
+ const ::std::auto_ptr<SwUnoCrsr> pNewCrsr(
+ m_pImpl->m_rDoc.CreateUnoCrsr(aPos, sal_False));
+ if (!GetPositions(*pNewCrsr))
+ {
+ throw uno::RuntimeException();
+ }
+
+ const uno::Reference< container::XEnumeration > xRet =
+ new SwXParaFrameEnumeration(*pNewCrsr, PARAFRAME_PORTION_TEXTRANGE);
+ return xRet;
+}
+
+uno::Reference< container::XEnumeration > SAL_CALL
+SwXTextRange::createEnumeration() throw (uno::RuntimeException)
+{
+ SolarMutexGuard g;
+
+ if (!GetDoc() || !m_pImpl->GetBookmark())
+ {
+ throw uno::RuntimeException();
+ }
+ const SwPosition aPos(GetDoc()->GetNodes().GetEndOfContent());
+ ::std::auto_ptr<SwUnoCrsr> pNewCrsr(
+ m_pImpl->m_rDoc.CreateUnoCrsr(aPos, sal_False));
+ if (!GetPositions(*pNewCrsr))
+ {
+ throw uno::RuntimeException();
+ }
+ if (!m_pImpl->m_xParentText.is())
+ {
+ getText();
+ }
+
+ const CursorType eSetType = (RANGE_IN_CELL == m_pImpl->m_eRangePosition)
+ ? CURSOR_SELECTION_IN_TABLE : CURSOR_SELECTION;
+ const uno::Reference< container::XEnumeration > xRet =
+ new SwXParagraphEnumeration(m_pImpl->m_xParentText, pNewCrsr, eSetType);
+ return xRet;
+}
+
+uno::Type SAL_CALL SwXTextRange::getElementType() throw (uno::RuntimeException)
+{
+ return text::XTextRange::static_type();
+}
+
+sal_Bool SAL_CALL SwXTextRange::hasElements() throw (uno::RuntimeException)
+{
+ return sal_True;
+}
+
+uno::Sequence< OUString > SAL_CALL
+SwXTextRange::getAvailableServiceNames() throw (uno::RuntimeException)
+{
+ uno::Sequence< OUString > aRet(1);
+ OUString* pArray = aRet.getArray();
+ pArray[0] = OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.text.TextContent"));
+ return aRet;
+}
+
+uno::Reference< beans::XPropertySetInfo > SAL_CALL
+SwXTextRange::getPropertySetInfo() throw (uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+
+ static uno::Reference< beans::XPropertySetInfo > xRef =
+ m_pImpl->m_rPropSet.getPropertySetInfo();
+ return xRef;
+}
+
+void SAL_CALL
+SwXTextRange::setPropertyValue(
+ const OUString& rPropertyName, const uno::Any& rValue)
+throw (beans::UnknownPropertyException, beans::PropertyVetoException,
+ lang::IllegalArgumentException, lang::WrappedTargetException,
+ uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+
+ if (!GetDoc() || !m_pImpl->GetBookmark())
+ {
+ throw uno::RuntimeException();
+ }
+ SwPaM aPaM(GetDoc()->GetNodes());
+ GetPositions(aPaM);
+ SwUnoCursorHelper::SetPropertyValue(aPaM, m_pImpl->m_rPropSet,
+ rPropertyName, rValue);
+}
+
+uno::Any SAL_CALL
+SwXTextRange::getPropertyValue(const OUString& rPropertyName)
+throw (beans::UnknownPropertyException, lang::WrappedTargetException,
+ uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+
+ if (!GetDoc() || !m_pImpl->GetBookmark())
+ {
+ throw uno::RuntimeException();
+ }
+ SwPaM aPaM(GetDoc()->GetNodes());
+ GetPositions(aPaM);
+ return SwUnoCursorHelper::GetPropertyValue(aPaM, m_pImpl->m_rPropSet,
+ rPropertyName);
+}
+
+void SAL_CALL
+SwXTextRange::addPropertyChangeListener(
+ const ::rtl::OUString& /*rPropertyName*/,
+ const uno::Reference< beans::XPropertyChangeListener >& /*xListener*/)
+throw (beans::UnknownPropertyException, lang::WrappedTargetException,
+ uno::RuntimeException)
+{
+ OSL_FAIL("SwXTextRange::addPropertyChangeListener(): not implemented");
+}
+
+void SAL_CALL
+SwXTextRange::removePropertyChangeListener(
+ const ::rtl::OUString& /*rPropertyName*/,
+ const uno::Reference< beans::XPropertyChangeListener >& /*xListener*/)
+throw (beans::UnknownPropertyException, lang::WrappedTargetException,
+ uno::RuntimeException)
+{
+ OSL_FAIL("SwXTextRange::removePropertyChangeListener(): not implemented");
+}
+
+void SAL_CALL
+SwXTextRange::addVetoableChangeListener(
+ const ::rtl::OUString& /*rPropertyName*/,
+ const uno::Reference< beans::XVetoableChangeListener >& /*xListener*/)
+throw (beans::UnknownPropertyException, lang::WrappedTargetException,
+ uno::RuntimeException)
+{
+ OSL_FAIL("SwXTextRange::addVetoableChangeListener(): not implemented");
+}
+
+void SAL_CALL
+SwXTextRange::removeVetoableChangeListener(
+ const ::rtl::OUString& /*rPropertyName*/,
+ const uno::Reference< beans::XVetoableChangeListener >& /*xListener*/)
+throw (beans::UnknownPropertyException, lang::WrappedTargetException,
+ uno::RuntimeException)
+{
+ OSL_FAIL("SwXTextRange::removeVetoableChangeListener(): not implemented");
+}
+
+beans::PropertyState SAL_CALL
+SwXTextRange::getPropertyState(const OUString& rPropertyName)
+throw (beans::UnknownPropertyException, uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+
+ if (!GetDoc() || !m_pImpl->GetBookmark())
+ {
+ throw uno::RuntimeException();
+ }
+ SwPaM aPaM(GetDoc()->GetNodes());
+ GetPositions(aPaM);
+ return SwUnoCursorHelper::GetPropertyState(aPaM, m_pImpl->m_rPropSet,
+ rPropertyName);
+}
+
+uno::Sequence< beans::PropertyState > SAL_CALL
+SwXTextRange::getPropertyStates(const uno::Sequence< OUString >& rPropertyName)
+throw (beans::UnknownPropertyException, uno::RuntimeException)
+{
+ SolarMutexGuard g;
+
+ if (!GetDoc() || !m_pImpl->GetBookmark())
+ {
+ throw uno::RuntimeException();
+ }
+ SwPaM aPaM(GetDoc()->GetNodes());
+ GetPositions(aPaM);
+ return SwUnoCursorHelper::GetPropertyStates(aPaM, m_pImpl->m_rPropSet,
+ rPropertyName);
+}
+
+void SAL_CALL SwXTextRange::setPropertyToDefault(const OUString& rPropertyName)
+throw (beans::UnknownPropertyException, uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+
+ if (!GetDoc() || !m_pImpl->GetBookmark())
+ {
+ throw uno::RuntimeException();
+ }
+ SwPaM aPaM(GetDoc()->GetNodes());
+ GetPositions(aPaM);
+ SwUnoCursorHelper::SetPropertyToDefault(aPaM, m_pImpl->m_rPropSet,
+ rPropertyName);
+}
+
+uno::Any SAL_CALL
+SwXTextRange::getPropertyDefault(const OUString& rPropertyName)
+throw (beans::UnknownPropertyException, lang::WrappedTargetException,
+ uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+
+ if (!GetDoc() || !m_pImpl->GetBookmark())
+ {
+ throw uno::RuntimeException();
+ }
+ SwPaM aPaM(GetDoc()->GetNodes());
+ GetPositions(aPaM);
+ return SwUnoCursorHelper::GetPropertyDefault(aPaM, m_pImpl->m_rPropSet,
+ rPropertyName);
+}
+
+void SAL_CALL
+SwXTextRange::makeRedline(
+ const ::rtl::OUString& rRedlineType,
+ const uno::Sequence< beans::PropertyValue >& rRedlineProperties )
+throw (lang::IllegalArgumentException, uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+
+ if (!GetDoc() || !m_pImpl->GetBookmark())
+ {
+ throw uno::RuntimeException();
+ }
+ SwPaM aPaM(GetDoc()->GetNodes());
+ SwXTextRange::GetPositions(aPaM);
+ SwUnoCursorHelper::makeRedline( aPaM, rRedlineType, rRedlineProperties );
+}
+
+/******************************************************************
+ * SwXTextRanges
+ ******************************************************************/
+class SwXTextRanges::Impl
+ : public SwClient
+{
+
+public:
+
+ ::std::vector< uno::Reference< text::XTextRange > > m_Ranges;
+
+ Impl(SwPaM *const pPaM)
+ : SwClient( (pPaM)
+ ? pPaM->GetDoc()->CreateUnoCrsr(*pPaM->GetPoint())
+ : 0 )
+ {
+ if (pPaM)
+ {
+ ::sw::DeepCopyPaM(*pPaM, *GetCursor());
+ }
+ MakeRanges();
+ }
+
+ ~Impl() {
+ // Impl owns the cursor; delete it here: SolarMutex is locked
+ delete GetRegisteredIn();
+ }
+
+ SwUnoCrsr * GetCursor() {
+ return static_cast<SwUnoCrsr*>(
+ const_cast<SwModify*>(GetRegisteredIn()));
+ }
+
+ void MakeRanges();
+protected:
+ // SwClient
+ virtual void Modify( const SfxPoolItem *pOld, const SfxPoolItem *pNew);
+
+};
+
+void SwXTextRanges::Impl::Modify( const SfxPoolItem *pOld, const SfxPoolItem *pNew)
+{
+ ClientModify(this, pOld, pNew);
+}
+
+void SwXTextRanges::Impl::MakeRanges()
+{
+ SwUnoCrsr *const pCursor = GetCursor();
+ if (pCursor)
+ {
+ SwPaM *pTmpCursor = pCursor;
+ do {
+ const uno::Reference< text::XTextRange > xRange(
+ SwXTextRange::CreateXTextRange(
+ *pTmpCursor->GetDoc(),
+ *pTmpCursor->GetPoint(), pTmpCursor->GetMark()));
+ if (xRange.is())
+ {
+ m_Ranges.push_back(xRange);
+ }
+ pTmpCursor = static_cast<SwPaM*>(pTmpCursor->GetNext());
+ }
+ while (pTmpCursor != pCursor);
+ }
+}
+
+const SwUnoCrsr* SwXTextRanges::GetCursor() const
+{
+ return m_pImpl->GetCursor();
+}
+
+SwXTextRanges::SwXTextRanges(SwPaM *const pPaM)
+ : m_pImpl( new SwXTextRanges::Impl(pPaM) )
+{
+}
+
+SwXTextRanges::~SwXTextRanges()
+{
+}
+
+const uno::Sequence< sal_Int8 > & SwXTextRanges::getUnoTunnelId()
+{
+ static uno::Sequence< sal_Int8 > aSeq = ::CreateUnoTunnelId();
+ return aSeq;
+}
+
+sal_Int64 SAL_CALL
+SwXTextRanges::getSomething(const uno::Sequence< sal_Int8 >& rId)
+throw (uno::RuntimeException)
+{
+ return ::sw::UnoTunnelImpl<SwXTextRanges>(rId, this);
+}
+
+/****************************************************************************
+ * Text positions
+ * Bis zum ersten Zugriff auf eine TextPosition wird ein SwCursor gehalten,
+ * danach wird ein Array mit uno::Reference< XTextPosition > angelegt
+ *
+****************************************************************************/
+OUString SAL_CALL
+SwXTextRanges::getImplementationName() throw (uno::RuntimeException)
+{
+ return C2U("SwXTextRanges");
+}
+
+static char const*const g_ServicesTextRanges[] =
+{
+ "com.sun.star.text.TextRanges",
+};
+
+static const size_t g_nServicesTextRanges(
+ SAL_N_ELEMENTS(g_ServicesTextRanges));
+
+sal_Bool SAL_CALL SwXTextRanges::supportsService(const OUString& rServiceName)
+throw (uno::RuntimeException)
+{
+ return ::sw::SupportsServiceImpl(
+ g_nServicesTextRanges, g_ServicesTextRanges, rServiceName);
+}
+
+uno::Sequence< OUString > SAL_CALL
+SwXTextRanges::getSupportedServiceNames() throw (uno::RuntimeException)
+{
+ return ::sw::GetSupportedServiceNamesImpl(
+ g_nServicesTextRanges, g_ServicesTextRanges);
+}
+
+sal_Int32 SAL_CALL SwXTextRanges::getCount() throw (uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+
+ return static_cast<sal_Int32>(m_pImpl->m_Ranges.size());
+}
+
+uno::Any SAL_CALL SwXTextRanges::getByIndex(sal_Int32 nIndex)
+throw (lang::IndexOutOfBoundsException, lang::WrappedTargetException,
+ uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+
+ if ((nIndex < 0) ||
+ (static_cast<size_t>(nIndex) >= m_pImpl->m_Ranges.size()))
+ {
+ throw lang::IndexOutOfBoundsException();
+ }
+ uno::Any ret;
+ ret <<= (m_pImpl->m_Ranges.at(nIndex));
+ return ret;
+}
+
+uno::Type SAL_CALL
+SwXTextRanges::getElementType() throw (uno::RuntimeException)
+{
+ return text::XTextRange::static_type();
+}
+
+sal_Bool SAL_CALL SwXTextRanges::hasElements() throw (uno::RuntimeException)
+{
+ // no mutex necessary: getCount() does locking
+ return getCount() > 0;
+}
+
+void SwUnoCursorHelper::SetString(SwCursor & rCursor, const OUString& rString)
+{
+ // Start/EndAction
+ SwDoc *const pDoc = rCursor.GetDoc();
+ UnoActionContext aAction(pDoc);
+ pDoc->GetIDocumentUndoRedo().StartUndo(UNDO_INSERT, NULL);
+ if (rCursor.HasMark())
+ {
+ pDoc->DeleteAndJoin(rCursor);
+ }
+ if (rString.getLength())
+ {
+ String aText(rString);
+ const bool bSuccess( SwUnoCursorHelper::DocInsertStringSplitCR(
+ *pDoc, rCursor, aText, false ) );
+ DBG_ASSERT( bSuccess, "DocInsertStringSplitCR" );
+ (void) bSuccess;
+ SwUnoCursorHelper::SelectPam(rCursor, true);
+ rCursor.Left(rString.getLength(), CRSR_SKIP_CHARS, sal_False, sal_False);
+ }
+ pDoc->GetIDocumentUndoRedo().EndUndo(UNDO_INSERT, NULL);
+}
+
+/******************************************************************
+ * SwXParaFrameEnumeration
+ ******************************************************************/
+class SwXParaFrameEnumeration::Impl
+ : public SwClient
+{
+
+public:
+
+ // created by hasMoreElements
+ uno::Reference< text::XTextContent > m_xNextObject;
+ FrameDependList_t m_Frames;
+
+ Impl(SwPaM const & rPaM)
+ : SwClient(rPaM.GetDoc()->CreateUnoCrsr(*rPaM.GetPoint(), sal_False))
+ {
+ if (rPaM.HasMark())
+ {
+ GetCursor()->SetMark();
+ *GetCursor()->GetMark() = *rPaM.GetMark();
+ }
+ }
+
+ ~Impl() {
+ // Impl owns the cursor; delete it here: SolarMutex is locked
+ delete GetRegisteredIn();
+ }
+
+ SwUnoCrsr * GetCursor() {
+ return static_cast<SwUnoCrsr*>(
+ const_cast<SwModify*>(GetRegisteredIn()));
+ }
+protected:
+ // SwClient
+ virtual void Modify( const SfxPoolItem *pOld, const SfxPoolItem *pNew);
+
+};
+
+struct InvalidFrameDepend {
+ bool operator() (::boost::shared_ptr<SwDepend> const & rEntry)
+ { return !rEntry->GetRegisteredIn(); }
+};
+
+void SwXParaFrameEnumeration::Impl::Modify( const SfxPoolItem *pOld, const SfxPoolItem *pNew)
+{
+ ClientModify(this, pOld, pNew);
+ if(!GetRegisteredIn())
+ {
+ m_Frames.clear();
+ m_xNextObject = 0;
+ }
+ else
+ {
+ // check if any frame went away...
+ FrameDependList_t::iterator const iter =
+ ::std::remove_if(m_Frames.begin(), m_Frames.end(),
+ InvalidFrameDepend());
+ m_Frames.erase(iter, m_Frames.end());
+ }
+}
+
+static sal_Bool
+lcl_CreateNextObject(SwUnoCrsr& i_rUnoCrsr,
+ uno::Reference<text::XTextContent> & o_rNextObject,
+ FrameDependList_t & i_rFrames)
+{
+ if (!i_rFrames.size())
+ return sal_False;
+
+ SwFrmFmt *const pFormat = static_cast<SwFrmFmt*>(const_cast<SwModify*>(
+ i_rFrames.front()->GetRegisteredIn()));
+ i_rFrames.pop_front();
+ // the format should be valid here, otherwise the client
+ // would have been removed in ::Modify
+ // check for a shape first
+ SwDrawContact* const pContact = SwIterator<SwDrawContact,SwFmt>::FirstElement( *pFormat );
+ if (pContact)
+ {
+ SdrObject * const pSdr = pContact->GetMaster();
+ if (pSdr)
+ {
+ o_rNextObject.set(pSdr->getUnoShape(), uno::UNO_QUERY);
+ }
+ }
+ else
+ {
+ const SwNodeIndex* pIdx = pFormat->GetCntnt().GetCntntIdx();
+ DBG_ASSERT(pIdx, "where is the index?");
+ SwNode const*const pNd =
+ i_rUnoCrsr.GetDoc()->GetNodes()[ pIdx->GetIndex() + 1 ];
+
+ const FlyCntType eType = (!pNd->IsNoTxtNode()) ? FLYCNTTYPE_FRM
+ : ( (pNd->IsGrfNode()) ? FLYCNTTYPE_GRF : FLYCNTTYPE_OLE );
+
+ const uno::Reference< container::XNamed > xFrame =
+ SwXFrames::GetObject(*pFormat, eType);
+ o_rNextObject.set(xFrame, uno::UNO_QUERY);
+ }
+
+ return o_rNextObject.is();
+}
+
+/* ---------------------------------------------------------------------------
+ Description: Search for a FLYCNT text attribute at the cursor point
+ and fill the frame into the array
+ ---------------------------------------------------------------------------*/
+static void
+lcl_FillFrame(SwClient & rEnum, SwUnoCrsr& rUnoCrsr,
+ FrameDependList_t & rFrames)
+{
+ // search for objects at the cursor - anchored at/as char
+ SwTxtAttr const*const pTxtAttr =
+ rUnoCrsr.GetNode()->GetTxtNode()->GetTxtAttrForCharAt(
+ rUnoCrsr.GetPoint()->nContent.GetIndex(), RES_TXTATR_FLYCNT);
+ if (pTxtAttr)
+ {
+ const SwFmtFlyCnt& rFlyCnt = pTxtAttr->GetFlyCnt();
+ SwFrmFmt * const pFrmFmt = rFlyCnt.GetFrmFmt();
+ SwDepend * const pNewDepend = new SwDepend(&rEnum, pFrmFmt);
+ rFrames.push_back( ::boost::shared_ptr<SwDepend>(pNewDepend) );
+ }
+}
+
+SwXParaFrameEnumeration::SwXParaFrameEnumeration(
+ const SwPaM& rPaM, const enum ParaFrameMode eParaFrameMode,
+ SwFrmFmt *const pFmt)
+ : m_pImpl( new SwXParaFrameEnumeration::Impl(rPaM) )
+{
+ if (PARAFRAME_PORTION_PARAGRAPH == eParaFrameMode)
+ {
+ FrameDependSortList_t frames;
+ ::CollectFrameAtNode(*m_pImpl.get(), rPaM.GetPoint()->nNode,
+ frames, false);
+ ::std::transform(frames.begin(), frames.end(),
+ ::std::back_inserter(m_pImpl->m_Frames),
+ ::boost::bind(&FrameDependSortListEntry::pFrameDepend, _1));
+ }
+ else if (pFmt)
+ {
+ // create SwDepend for frame and insert into array
+ SwDepend *const pNewDepend = new SwDepend(m_pImpl.get(), pFmt);
+ m_pImpl->m_Frames.push_back(::boost::shared_ptr<SwDepend>(pNewDepend));
+ }
+ else if ((PARAFRAME_PORTION_CHAR == eParaFrameMode) ||
+ (PARAFRAME_PORTION_TEXTRANGE == eParaFrameMode))
+ {
+ if (PARAFRAME_PORTION_TEXTRANGE == eParaFrameMode)
+ {
+ SwPosFlyFrms aFlyFrms;
+ //get all frames that are bound at paragraph or at character
+ rPaM.GetDoc()->GetAllFlyFmts(aFlyFrms, m_pImpl->GetCursor(), sal_False, sal_True);
+ for(sal_uInt16 i = 0; i < aFlyFrms.Count(); i++)
+ {
+ SwPosFlyFrm* pPosFly = aFlyFrms[i];
+ SwFrmFmt *const pFrmFmt =
+ const_cast<SwFrmFmt*>(&pPosFly->GetFmt());
+ // create SwDepend for frame and insert into array
+ SwDepend *const pNewDepend =
+ new SwDepend(m_pImpl.get(), pFrmFmt);
+ m_pImpl->m_Frames.push_back(
+ ::boost::shared_ptr<SwDepend>(pNewDepend) );
+ }
+ }
+ lcl_FillFrame(*m_pImpl.get(), *m_pImpl->GetCursor(), m_pImpl->m_Frames);
+ }
+}
+
+SwXParaFrameEnumeration::~SwXParaFrameEnumeration()
+{
+}
+
+sal_Bool SAL_CALL
+SwXParaFrameEnumeration::hasMoreElements() throw (uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+
+ if (!m_pImpl->GetCursor())
+ throw uno::RuntimeException();
+
+ return (m_pImpl->m_xNextObject.is())
+ ? sal_True
+ : lcl_CreateNextObject(*m_pImpl->GetCursor(),
+ m_pImpl->m_xNextObject, m_pImpl->m_Frames);
+}
+
+uno::Any SAL_CALL SwXParaFrameEnumeration::nextElement()
+throw (container::NoSuchElementException,
+ lang::WrappedTargetException, uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+
+ if (!m_pImpl->GetCursor())
+ {
+ throw uno::RuntimeException();
+ }
+
+ if (!m_pImpl->m_xNextObject.is() && m_pImpl->m_Frames.size())
+ {
+ lcl_CreateNextObject(*m_pImpl->GetCursor(),
+ m_pImpl->m_xNextObject, m_pImpl->m_Frames);
+ }
+ if (!m_pImpl->m_xNextObject.is())
+ {
+ throw container::NoSuchElementException();
+ }
+ uno::Any aRet;
+ aRet <<= m_pImpl->m_xNextObject;
+ m_pImpl->m_xNextObject = 0;
+ return aRet;
+}
+
+OUString SAL_CALL
+SwXParaFrameEnumeration::getImplementationName() throw (uno::RuntimeException)
+{
+ return C2U("SwXParaFrameEnumeration");
+}
+
+static char const*const g_ServicesParaFrameEnum[] =
+{
+ "com.sun.star.util.ContentEnumeration",
+};
+
+static const size_t g_nServicesParaFrameEnum(
+ SAL_N_ELEMENTS(g_ServicesParaFrameEnum));
+
+sal_Bool SAL_CALL
+SwXParaFrameEnumeration::supportsService(const OUString& rServiceName)
+throw (uno::RuntimeException)
+{
+ return ::sw::SupportsServiceImpl(
+ g_nServicesParaFrameEnum, g_ServicesParaFrameEnum, rServiceName);
+}
+
+uno::Sequence< OUString > SAL_CALL
+SwXParaFrameEnumeration::getSupportedServiceNames()
+throw (uno::RuntimeException)
+{
+ return ::sw::GetSupportedServiceNamesImpl(
+ g_nServicesParaFrameEnum, g_ServicesParaFrameEnum);
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/unocore/unoparagraph.cxx b/sw/source/core/unocore/unoparagraph.cxx
new file mode 100644
index 000000000000..f8a620c876fe
--- /dev/null
+++ b/sw/source/core/unocore/unoparagraph.cxx
@@ -0,0 +1,1327 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+#include <unoparagraph.hxx>
+#include <cmdid.h>
+#include <unomid.h>
+#include <unoparaframeenum.hxx>
+#include <unotext.hxx>
+#include <unotextrange.hxx>
+#include <unoport.hxx>
+#include <unomap.hxx>
+#include <unocrsr.hxx>
+#include <unoprnms.hxx>
+#include <unocrsrhelper.hxx>
+#include <doc.hxx>
+#include <ndtxt.hxx>
+#include <osl/mutex.hxx>
+#include <vcl/svapp.hxx>
+#include <docsh.hxx>
+
+#define _SVSTDARR_USHORTS
+#define _SVSTDARR_USHORTSSORT
+#include <svl/svstdarr.hxx>
+
+#include <com/sun/star/beans/SetPropertyTolerantFailed.hpp>
+#include <com/sun/star/beans/GetPropertyTolerantResult.hpp>
+#include <com/sun/star/beans/TolerantPropertySetResultType.hpp>
+#include <com/sun/star/beans/PropertyAttribute.hpp>
+#include <com/sun/star/text/WrapTextMode.hpp>
+#include <com/sun/star/text/TextContentAnchorType.hpp>
+
+
+using namespace ::com::sun::star;
+using ::rtl::OUString;
+
+class SwParaSelection
+{
+ SwCursor & m_rCursor;
+public:
+ SwParaSelection(SwCursor & rCursor);
+ ~SwParaSelection();
+};
+
+SwParaSelection::SwParaSelection(SwCursor & rCursor)
+ : m_rCursor(rCursor)
+{
+ if (m_rCursor.HasMark())
+ {
+ m_rCursor.DeleteMark();
+ }
+ // is it at the start?
+ if (m_rCursor.GetPoint()->nContent != 0)
+ {
+ m_rCursor.MovePara(fnParaCurr, fnParaStart);
+ }
+ // or at the end already?
+ if (m_rCursor.GetPoint()->nContent != m_rCursor.GetCntntNode()->Len())
+ {
+ m_rCursor.SetMark();
+ m_rCursor.MovePara(fnParaCurr, fnParaEnd);
+ }
+}
+
+SwParaSelection::~SwParaSelection()
+{
+ if (m_rCursor.GetPoint()->nContent != 0)
+ {
+ m_rCursor.DeleteMark();
+ m_rCursor.MovePara(fnParaCurr, fnParaStart);
+ }
+}
+
+/******************************************************************
+ * forward declarations
+ ******************************************************************/
+beans::PropertyState lcl_SwXParagraph_getPropertyState(
+ const SwTxtNode& rTxtNode,
+ const SwAttrSet** ppSet,
+ const SfxItemPropertySimpleEntry& rEntry,
+ sal_Bool &rAttrSetFetched )
+ throw (beans::UnknownPropertyException);
+
+/******************************************************************
+ * SwXParagraph
+ ******************************************************************/
+class SwXParagraph::Impl
+ : public SwClient
+{
+
+public:
+ SwXParagraph & m_rThis;
+ SwEventListenerContainer m_ListenerContainer;
+ SfxItemPropertySet const& m_rPropSet;
+ bool m_bIsDescriptor;
+ sal_Int32 m_nSelectionStartPos;
+ sal_Int32 m_nSelectionEndPos;
+ ::rtl::OUString m_sText;
+ uno::Reference<text::XText> m_xParentText;
+
+ Impl( SwXParagraph & rThis,
+ SwTxtNode *const pTxtNode = 0,
+ uno::Reference< text::XText > const & xParent = 0,
+ const sal_Int32 nSelStart = -1, const sal_Int32 nSelEnd = -1)
+ : SwClient(pTxtNode)
+ , m_rThis(rThis)
+ , m_ListenerContainer(static_cast< ::cppu::OWeakObject* >(&rThis))
+ , m_rPropSet(*aSwMapProvider.GetPropertySet(PROPERTY_MAP_PARAGRAPH))
+ // #i111177# unxsols4 (Sun C++ 5.9 SunOS_sparc) may generate wrong code
+ , m_bIsDescriptor((0 == pTxtNode) ? true : false)
+ , m_nSelectionStartPos(nSelStart)
+ , m_nSelectionEndPos(nSelEnd)
+ , m_xParentText(xParent)
+ {
+ }
+
+ const SwTxtNode * GetTxtNode() const {
+ return static_cast<const SwTxtNode*>(GetRegisteredIn());
+ }
+ SwTxtNode * GetTxtNode() {
+ return static_cast<SwTxtNode*>(GetRegisteredInNonConst());
+ }
+
+ SwTxtNode & GetTxtNodeOrThrow() {
+ SwTxtNode *const pTxtNode( GetTxtNode() );
+ if (!pTxtNode) {
+ throw uno::RuntimeException(OUString(RTL_CONSTASCII_USTRINGPARAM(
+ "SwXParagraph: disposed or invalid")), 0);
+ }
+ return *pTxtNode;
+ }
+
+ bool IsDescriptor() const { return m_bIsDescriptor; }
+
+ void SetPropertyValues_Impl(
+ const uno::Sequence< ::rtl::OUString >& rPropertyNames,
+ const uno::Sequence< uno::Any >& rValues)
+ throw (beans::UnknownPropertyException, beans::PropertyVetoException,
+ lang::IllegalArgumentException, lang::WrappedTargetException,
+ uno::RuntimeException);
+
+ uno::Sequence< uno::Any >
+ GetPropertyValues_Impl(
+ const uno::Sequence< ::rtl::OUString >& rPropertyNames)
+ throw (beans::UnknownPropertyException, lang::WrappedTargetException,
+ uno::RuntimeException);
+
+ uno::Sequence< beans::GetDirectPropertyTolerantResult >
+ GetPropertyValuesTolerant_Impl(
+ const uno::Sequence< ::rtl::OUString >& rPropertyNames,
+ bool bDirectValuesOnly)
+ throw (uno::RuntimeException);
+protected:
+ // SwClient
+ virtual void Modify(const SfxPoolItem *pOld, const SfxPoolItem *pNew);
+
+};
+
+void SwXParagraph::Impl::Modify( const SfxPoolItem *pOld, const SfxPoolItem *pNew )
+{
+ ClientModify(this, pOld, pNew);
+ if (!GetRegisteredIn())
+ {
+ m_ListenerContainer.Disposing();
+ }
+}
+
+SwXParagraph::SwXParagraph()
+ : m_pImpl( new SwXParagraph::Impl(*this) )
+{
+}
+
+SwXParagraph::SwXParagraph(
+ uno::Reference< text::XText > const & xParent,
+ SwTxtNode & rTxtNode,
+ const sal_Int32 nSelStart, const sal_Int32 nSelEnd)
+ : m_pImpl(
+ new SwXParagraph::Impl(*this, &rTxtNode, xParent, nSelStart, nSelEnd))
+{
+}
+
+SwXParagraph::~SwXParagraph()
+{
+}
+
+const SwTxtNode * SwXParagraph::GetTxtNode() const
+{
+ return m_pImpl->GetTxtNode();
+}
+
+bool SwXParagraph::IsDescriptor() const
+{
+ return m_pImpl->IsDescriptor();
+}
+
+uno::Reference<text::XTextContent>
+SwXParagraph::CreateXParagraph(SwDoc & rDoc, SwTxtNode& rTxtNode,
+ uno::Reference< text::XText> const& i_xParent,
+ const sal_Int32 nSelStart, const sal_Int32 nSelEnd)
+{
+ // re-use existing SwXParagraph
+ // #i105557#: do not iterate over the registered clients: race condition
+ uno::Reference<text::XTextContent> xParagraph;
+ if ((-1 == nSelStart) && (-1 == nSelEnd)) // only use cache if no selection!
+ {
+ xParagraph.set(rTxtNode.GetXParagraph());
+ }
+ if (xParagraph.is())
+ {
+ return xParagraph;
+ }
+
+ // create new SwXParagraph
+ uno::Reference<text::XText> xParentText(i_xParent);
+ if (!xParentText.is())
+ {
+ SwPosition Pos( rTxtNode );
+ xParentText.set(::sw::CreateParentXText( rDoc, Pos ));
+ }
+ SwXParagraph *const pXPara(
+ new SwXParagraph(xParentText, rTxtNode, nSelStart, nSelEnd) );
+ // this is why the constructor is private: need to acquire pXPara here
+ xParagraph.set(pXPara);
+ // in order to initialize the weak pointer cache in the core object
+ if ((-1 == nSelStart) && (-1 == nSelEnd))
+ {
+ rTxtNode.SetXParagraph(xParagraph);
+ }
+ return xParagraph;
+}
+
+bool SwXParagraph::SelectPaM(SwPaM & rPaM)
+{
+ SwTxtNode const*const pTxtNode( GetTxtNode() );
+
+ if (!pTxtNode)
+ {
+ return false;
+ }
+
+ *rPaM.GetPoint() = SwPosition( *pTxtNode );
+ // set selection to the whole paragraph
+ rPaM.SetMark();
+ rPaM.GetMark()->nContent = pTxtNode->GetTxt().Len();
+ return true;
+}
+
+const uno::Sequence< sal_Int8 > & SwXParagraph::getUnoTunnelId()
+{
+ static uno::Sequence< sal_Int8 > aSeq = ::CreateUnoTunnelId();
+ return aSeq;
+}
+
+sal_Int64 SAL_CALL
+SwXParagraph::getSomething(const uno::Sequence< sal_Int8 >& rId)
+throw (uno::RuntimeException)
+{
+ return ::sw::UnoTunnelImpl<SwXParagraph>(rId, this);
+}
+
+OUString SAL_CALL
+SwXParagraph::getImplementationName() throw (uno::RuntimeException)
+{
+ return C2U("SwXParagraph");
+}
+
+static char const*const g_ServicesParagraph[] =
+{
+ "com.sun.star.text.TextContent",
+ "com.sun.star.text.Paragraph",
+ "com.sun.star.style.CharacterProperties",
+ "com.sun.star.style.CharacterPropertiesAsian",
+ "com.sun.star.style.CharacterPropertiesComplex",
+ "com.sun.star.style.ParagraphProperties",
+ "com.sun.star.style.ParagraphPropertiesAsian",
+ "com.sun.star.style.ParagraphPropertiesComplex",
+};
+
+static const size_t g_nServicesParagraph(
+ SAL_N_ELEMENTS(g_ServicesParagraph));
+
+sal_Bool SAL_CALL
+SwXParagraph::supportsService(const OUString& rServiceName)
+throw (uno::RuntimeException)
+{
+ return ::sw::SupportsServiceImpl(
+ g_nServicesParagraph, g_ServicesParagraph, rServiceName);
+}
+
+uno::Sequence< OUString > SAL_CALL
+SwXParagraph::getSupportedServiceNames() throw (uno::RuntimeException)
+{
+ return ::sw::GetSupportedServiceNamesImpl(
+ g_nServicesParagraph, g_ServicesParagraph);
+}
+
+void
+SwXParagraph::attachToText(SwXText & rParent, SwTxtNode & rTxtNode)
+{
+ DBG_ASSERT(m_pImpl->m_bIsDescriptor, "Paragraph is not a descriptor");
+ if (m_pImpl->m_bIsDescriptor)
+ {
+ m_pImpl->m_bIsDescriptor = false;
+ rTxtNode.Add(m_pImpl.get());
+ rTxtNode.SetXParagraph(uno::Reference<text::XTextContent>(this));
+ m_pImpl->m_xParentText = &rParent;
+ if (m_pImpl->m_sText.getLength())
+ {
+ try { setString(m_pImpl->m_sText); }
+ catch(...){}
+ m_pImpl->m_sText = OUString();
+ }
+ }
+}
+
+uno::Reference< beans::XPropertySetInfo > SAL_CALL
+SwXParagraph::getPropertySetInfo()
+throw (uno::RuntimeException)
+{
+ SolarMutexGuard g;
+
+ static uno::Reference< beans::XPropertySetInfo > xRef =
+ m_pImpl->m_rPropSet.getPropertySetInfo();
+ return xRef;
+}
+
+void SAL_CALL
+SwXParagraph::setPropertyValue(const OUString& rPropertyName,
+ const uno::Any& rValue)
+throw (beans::UnknownPropertyException, beans::PropertyVetoException,
+ lang::IllegalArgumentException, lang::WrappedTargetException,
+ uno::RuntimeException )
+{
+ SolarMutexGuard aGuard;
+ uno::Sequence<OUString> aPropertyNames(1);
+ aPropertyNames.getArray()[0] = rPropertyName;
+ uno::Sequence<uno::Any> aValues(1);
+ aValues.getArray()[0] = rValue;
+ m_pImpl->SetPropertyValues_Impl( aPropertyNames, aValues );
+}
+
+uno::Any
+SwXParagraph::getPropertyValue(const OUString& rPropertyName)
+throw (beans::UnknownPropertyException, lang::WrappedTargetException,
+ uno::RuntimeException )
+{
+ SolarMutexGuard aGuard;
+ uno::Sequence<OUString> aPropertyNames(1);
+ aPropertyNames.getArray()[0] = rPropertyName;
+ const uno::Sequence< uno::Any > aRet =
+ m_pImpl->GetPropertyValues_Impl(aPropertyNames);
+ return aRet.getConstArray()[0];
+}
+
+void SwXParagraph::Impl::SetPropertyValues_Impl(
+ const uno::Sequence< OUString >& rPropertyNames,
+ const uno::Sequence< uno::Any >& rValues )
+throw (beans::UnknownPropertyException, beans::PropertyVetoException,
+ lang::IllegalArgumentException, lang::WrappedTargetException,
+ uno::RuntimeException)
+{
+ SwTxtNode & rTxtNode(GetTxtNodeOrThrow());
+
+ SwPosition aPos( rTxtNode );
+ SwCursor aCursor( aPos, 0, false );
+ const OUString* pPropertyNames = rPropertyNames.getConstArray();
+ const uno::Any* pValues = rValues.getConstArray();
+ SfxItemPropertyMap const*const pMap = m_rPropSet.getPropertyMap();
+ SwParaSelection aParaSel( aCursor );
+ for (sal_Int32 nProp = 0; nProp < rPropertyNames.getLength(); nProp++)
+ {
+ SfxItemPropertySimpleEntry const*const pEntry =
+ pMap->getByName( pPropertyNames[nProp] );
+ if (!pEntry)
+ {
+ throw beans::UnknownPropertyException(
+ OUString(RTL_CONSTASCII_USTRINGPARAM("Unknown property: "))
+ + pPropertyNames[nProp],
+ static_cast< cppu::OWeakObject * >(&m_rThis));
+ }
+ if (pEntry->nFlags & beans::PropertyAttribute::READONLY)
+ {
+ throw beans::PropertyVetoException(
+ OUString(RTL_CONSTASCII_USTRINGPARAM("Property is read-only: "))
+ + pPropertyNames[nProp],
+ static_cast< cppu::OWeakObject * >(&m_rThis));
+ }
+ SwUnoCursorHelper::SetPropertyValue(aCursor, m_rPropSet,
+ pPropertyNames[nProp], pValues[nProp]);
+ }
+}
+
+void SAL_CALL SwXParagraph::setPropertyValues(
+ const uno::Sequence< OUString >& rPropertyNames,
+ const uno::Sequence< uno::Any >& rValues )
+throw (beans::PropertyVetoException, lang::IllegalArgumentException,
+ lang::WrappedTargetException, uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+
+ // workaround for bad designed API
+ try
+ {
+ m_pImpl->SetPropertyValues_Impl( rPropertyNames, rValues );
+ }
+ catch (beans::UnknownPropertyException &rException)
+ {
+ // wrap the original (here not allowed) exception in
+ // a lang::WrappedTargetException that gets thrown instead.
+ lang::WrappedTargetException aWExc;
+ aWExc.TargetException <<= rException;
+ throw aWExc;
+ }
+}
+
+uno::Sequence< uno::Any > SwXParagraph::Impl::GetPropertyValues_Impl(
+ const uno::Sequence< OUString > & rPropertyNames )
+throw (beans::UnknownPropertyException, lang::WrappedTargetException,
+ uno::RuntimeException)
+{
+ SwTxtNode & rTxtNode(GetTxtNodeOrThrow());
+
+ uno::Sequence< uno::Any > aValues(rPropertyNames.getLength());
+ SwPosition aPos( rTxtNode );
+ SwPaM aPam( aPos );
+ uno::Any* pValues = aValues.getArray();
+ const OUString* pPropertyNames = rPropertyNames.getConstArray();
+ SfxItemPropertyMap const*const pMap = m_rPropSet.getPropertyMap();
+ const SwAttrSet& rAttrSet( rTxtNode.GetSwAttrSet() );
+ for (sal_Int32 nProp = 0; nProp < rPropertyNames.getLength(); nProp++)
+ {
+ SfxItemPropertySimpleEntry const*const pEntry =
+ pMap->getByName( pPropertyNames[nProp] );
+ if (!pEntry)
+ {
+ throw beans::UnknownPropertyException(
+ OUString(RTL_CONSTASCII_USTRINGPARAM("Unknown property: "))
+ + pPropertyNames[nProp],
+ static_cast< cppu::OWeakObject * >(&m_rThis));
+ }
+ if (! ::sw::GetDefaultTextContentValue(
+ pValues[nProp], pPropertyNames[nProp], pEntry->nWID))
+ {
+ beans::PropertyState eTemp;
+ const bool bDone = SwUnoCursorHelper::getCrsrPropertyValue(
+ *pEntry, aPam, &(pValues[nProp]), eTemp, &rTxtNode );
+ if (!bDone)
+ {
+ m_rPropSet.getPropertyValue(
+ *pEntry, rAttrSet, pValues[nProp]);
+ }
+ }
+ }
+ return aValues;
+}
+
+uno::Sequence< uno::Any > SAL_CALL
+SwXParagraph::getPropertyValues(const uno::Sequence< OUString >& rPropertyNames)
+throw (uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+ uno::Sequence< uno::Any > aValues;
+
+ // workaround for bad designed API
+ try
+ {
+ aValues = m_pImpl->GetPropertyValues_Impl( rPropertyNames );
+ }
+ catch (beans::UnknownPropertyException &)
+ {
+ throw uno::RuntimeException(OUString(RTL_CONSTASCII_USTRINGPARAM(
+ "Unknown property exception caught")),
+ static_cast<cppu::OWeakObject *>(this));
+ }
+ catch (lang::WrappedTargetException &)
+ {
+ throw uno::RuntimeException(OUString(RTL_CONSTASCII_USTRINGPARAM(
+ "WrappedTargetException caught")),
+ static_cast<cppu::OWeakObject *>(this));
+ }
+
+ return aValues;
+}
+
+void SAL_CALL SwXParagraph::addPropertiesChangeListener(
+ const uno::Sequence< OUString >& /*aPropertyNames*/,
+ const uno::Reference< beans::XPropertiesChangeListener >& /*xListener*/ )
+throw (uno::RuntimeException)
+{
+ OSL_FAIL("SwXParagraph::addPropertiesChangeListener(): not implemented");
+}
+
+void SAL_CALL SwXParagraph::removePropertiesChangeListener(
+ const uno::Reference< beans::XPropertiesChangeListener >& /*xListener*/ )
+throw (uno::RuntimeException)
+{
+ OSL_FAIL("SwXParagraph::removePropertiesChangeListener(): not implemented");
+}
+
+void SAL_CALL SwXParagraph::firePropertiesChangeEvent(
+ const uno::Sequence< OUString >& /*aPropertyNames*/,
+ const uno::Reference< beans::XPropertiesChangeListener >& /*xListener*/ )
+ throw(uno::RuntimeException)
+{
+ OSL_FAIL("SwXParagraph::firePropertiesChangeEvent(): not implemented");
+}
+
+/* disabled for #i46921# */
+
+uno::Sequence< beans::SetPropertyTolerantFailed > SAL_CALL
+SwXParagraph::setPropertyValuesTolerant(
+ const uno::Sequence< OUString >& rPropertyNames,
+ const uno::Sequence< uno::Any >& rValues )
+throw (lang::IllegalArgumentException, uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+
+ if (rPropertyNames.getLength() != rValues.getLength())
+ {
+ throw lang::IllegalArgumentException();
+ }
+
+ SwTxtNode & rTxtNode(m_pImpl->GetTxtNodeOrThrow());
+
+ //SwNode& rTxtNode = pUnoCrsr->GetPoint()->nNode.GetNode();
+ //const SwAttrSet& rAttrSet = ((SwTxtNode&)rTxtNode).GetSwAttrSet();
+ //sal_uInt16 nAttrCount = rAttrSet.Count();
+
+ const sal_Int32 nProps = rPropertyNames.getLength();
+ const OUString *pProp = rPropertyNames.getConstArray();
+
+ //sal_Int32 nVals = rValues.getLength();
+ const uno::Any *pValue = rValues.getConstArray();
+
+ sal_Int32 nFailed = 0;
+ uno::Sequence< beans::SetPropertyTolerantFailed > aFailed( nProps );
+ beans::SetPropertyTolerantFailed *pFailed = aFailed.getArray();
+
+ // get entry to start with
+ SfxItemPropertyMap const*const pPropMap =
+ m_pImpl->m_rPropSet.getPropertyMap();
+
+ OUString sTmp;
+ SwPosition aPos( rTxtNode );
+ SwCursor aCursor( aPos, 0, false );
+ SwParaSelection aParaSel( aCursor );
+ for (sal_Int32 i = 0; i < nProps; ++i)
+ {
+ try
+ {
+ pFailed[ nFailed ].Name = pProp[i];
+
+ SfxItemPropertySimpleEntry const*const pEntry =
+ pPropMap->getByName( pProp[i] );
+ if (!pEntry)
+ {
+ pFailed[ nFailed++ ].Result =
+ beans::TolerantPropertySetResultType::UNKNOWN_PROPERTY;
+ }
+ else
+ {
+ // set property value
+ // (compare to SwXParagraph::setPropertyValues)
+ if (pEntry->nFlags & beans::PropertyAttribute::READONLY)
+ {
+ pFailed[ nFailed++ ].Result =
+ beans::TolerantPropertySetResultType::PROPERTY_VETO;
+ }
+ else
+ {
+ SwUnoCursorHelper::SetPropertyValue(
+ aCursor, m_pImpl->m_rPropSet, pProp[i], pValue[i]);
+ }
+ }
+ }
+ catch (beans::UnknownPropertyException &)
+ {
+ // should not occur because property was searched for before
+ OSL_FAIL( "unexpected exception catched" );
+ pFailed[ nFailed++ ].Result =
+ beans::TolerantPropertySetResultType::UNKNOWN_PROPERTY;
+ }
+ catch (lang::IllegalArgumentException &)
+ {
+ pFailed[ nFailed++ ].Result =
+ beans::TolerantPropertySetResultType::ILLEGAL_ARGUMENT;
+ }
+ catch (beans::PropertyVetoException &)
+ {
+ pFailed[ nFailed++ ].Result =
+ beans::TolerantPropertySetResultType::PROPERTY_VETO;
+ }
+ catch (lang::WrappedTargetException &)
+ {
+ pFailed[ nFailed++ ].Result =
+ beans::TolerantPropertySetResultType::WRAPPED_TARGET;
+ }
+ }
+
+ aFailed.realloc( nFailed );
+ return aFailed;
+}
+
+uno::Sequence< beans::GetPropertyTolerantResult > SAL_CALL
+SwXParagraph::getPropertyValuesTolerant(
+ const uno::Sequence< OUString >& rPropertyNames )
+throw (uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+
+ uno::Sequence< beans::GetDirectPropertyTolerantResult > aTmpRes(
+ m_pImpl->GetPropertyValuesTolerant_Impl( rPropertyNames, false ) );
+ const beans::GetDirectPropertyTolerantResult *pTmpRes =
+ aTmpRes.getConstArray();
+
+ // copy temporary result to final result type
+ const sal_Int32 nLen = aTmpRes.getLength();
+ uno::Sequence< beans::GetPropertyTolerantResult > aRes( nLen );
+ beans::GetPropertyTolerantResult *pRes = aRes.getArray();
+ for (sal_Int32 i = 0; i < nLen; i++)
+ {
+ *pRes++ = *pTmpRes++;
+ }
+ return aRes;
+}
+
+uno::Sequence< beans::GetDirectPropertyTolerantResult > SAL_CALL
+SwXParagraph::getDirectPropertyValuesTolerant(
+ const uno::Sequence< OUString >& rPropertyNames )
+throw (uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+
+ return m_pImpl->GetPropertyValuesTolerant_Impl( rPropertyNames, true );
+}
+
+uno::Sequence< beans::GetDirectPropertyTolerantResult >
+SwXParagraph::Impl::GetPropertyValuesTolerant_Impl(
+ const uno::Sequence< OUString >& rPropertyNames,
+ bool bDirectValuesOnly )
+throw (uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+
+ SwTxtNode & rTxtNode(GetTxtNodeOrThrow());
+
+ // #i46786# Use SwAttrSet pointer for determining the state.
+ // Use the value SwAttrSet (from the paragraph OR the style)
+ // for determining the actual value(s).
+ const SwAttrSet* pAttrSet = rTxtNode.GetpSwAttrSet();
+ const SwAttrSet& rValueAttrSet = rTxtNode.GetSwAttrSet();
+
+ sal_Int32 nProps = rPropertyNames.getLength();
+ const OUString *pProp = rPropertyNames.getConstArray();
+
+ uno::Sequence< beans::GetDirectPropertyTolerantResult > aResult( nProps );
+ beans::GetDirectPropertyTolerantResult *pResult = aResult.getArray();
+ sal_Int32 nIdx = 0;
+
+ // get entry to start with
+ SfxItemPropertyMap const*const pPropMap = m_rPropSet.getPropertyMap();
+
+ for (sal_Int32 i = 0; i < nProps; ++i)
+ {
+ DBG_ASSERT( nIdx < nProps, "index out ouf bounds" );
+ beans::GetDirectPropertyTolerantResult &rResult = pResult[nIdx];
+
+ try
+ {
+ rResult.Name = pProp[i];
+
+ SfxItemPropertySimpleEntry const*const pEntry =
+ pPropMap->getByName( pProp[i] );
+ if (!pEntry) // property available?
+ {
+ rResult.Result =
+ beans::TolerantPropertySetResultType::UNKNOWN_PROPERTY;
+ }
+ else
+ {
+ // get property state
+ // (compare to SwXParagraph::getPropertyState)
+ sal_Bool bAttrSetFetched = sal_True;
+ beans::PropertyState eState = lcl_SwXParagraph_getPropertyState(
+ rTxtNode, &pAttrSet, *pEntry, bAttrSetFetched );
+ rResult.State = eState;
+
+// if (bDirectValuesOnly && PropertyState_DIRECT_VALUE != eState)
+// rResult.Result = beans::TolerantPropertySetResultType::NO_DIRECT_VALUE;
+// else
+ rResult.Result = beans::TolerantPropertySetResultType::UNKNOWN_FAILURE;
+ if (!bDirectValuesOnly ||
+ (beans::PropertyState_DIRECT_VALUE == eState))
+ {
+ // get property value
+ // (compare to SwXParagraph::getPropertyValue(s))
+ uno::Any aValue;
+ if (! ::sw::GetDefaultTextContentValue(
+ aValue, pProp[i], pEntry->nWID ) )
+ {
+ SwPosition aPos( rTxtNode );
+ SwPaM aPam( aPos );
+ // handle properties that are not part of the attribute
+ // and thus only pretendend to be paragraph attributes
+ beans::PropertyState eTemp;
+ const bool bDone =
+ SwUnoCursorHelper::getCrsrPropertyValue(
+ *pEntry, aPam, &aValue, eTemp, &rTxtNode );
+
+ // if not found try the real paragraph attributes...
+ if (!bDone)
+ {
+ m_rPropSet.getPropertyValue(
+ *pEntry, rValueAttrSet, aValue );
+ }
+ }
+
+ rResult.Value = aValue;
+ rResult.Result = beans::TolerantPropertySetResultType::SUCCESS;
+
+ nIdx++;
+ }
+ // this assertion should never occur!
+ DBG_ASSERT( nIdx < 1 || pResult[nIdx - 1].Result != beans::TolerantPropertySetResultType::UNKNOWN_FAILURE,
+ "unknown failure while retrieving property" );
+
+ }
+ }
+ catch (beans::UnknownPropertyException &)
+ {
+ // should not occur because property was searched for before
+ OSL_FAIL( "unexpected exception caught" );
+ rResult.Result = beans::TolerantPropertySetResultType::UNKNOWN_PROPERTY;
+ }
+ catch (lang::IllegalArgumentException &)
+ {
+ rResult.Result = beans::TolerantPropertySetResultType::ILLEGAL_ARGUMENT;
+ }
+ catch (beans::PropertyVetoException &)
+ {
+ rResult.Result = beans::TolerantPropertySetResultType::PROPERTY_VETO;
+ }
+ catch (lang::WrappedTargetException &)
+ {
+ rResult.Result = beans::TolerantPropertySetResultType::WRAPPED_TARGET;
+ }
+ }
+
+ // resize to actually used size
+ aResult.realloc( nIdx );
+
+ return aResult;
+}
+
+bool ::sw::GetDefaultTextContentValue(
+ uno::Any& rAny, const OUString& rPropertyName, sal_uInt16 nWID)
+{
+ if(!nWID)
+ {
+ if(rPropertyName.equalsAsciiL( SW_PROP_NAME(UNO_NAME_ANCHOR_TYPE)))
+ nWID = FN_UNO_ANCHOR_TYPE;
+ else if(rPropertyName.equalsAsciiL( SW_PROP_NAME(UNO_NAME_ANCHOR_TYPES)))
+ nWID = FN_UNO_ANCHOR_TYPES;
+ else if(rPropertyName.equalsAsciiL( SW_PROP_NAME(UNO_NAME_TEXT_WRAP)))
+ nWID = FN_UNO_TEXT_WRAP;
+ else
+ return sal_False;
+ }
+
+ switch(nWID)
+ {
+ case FN_UNO_TEXT_WRAP: rAny <<= text::WrapTextMode_NONE; break;
+ case FN_UNO_ANCHOR_TYPE: rAny <<= text::TextContentAnchorType_AT_PARAGRAPH; break;
+ case FN_UNO_ANCHOR_TYPES:
+ { uno::Sequence<text::TextContentAnchorType> aTypes(1);
+ text::TextContentAnchorType* pArray = aTypes.getArray();
+ pArray[0] = text::TextContentAnchorType_AT_PARAGRAPH;
+ rAny.setValue(&aTypes, ::getCppuType((uno::Sequence<text::TextContentAnchorType>*)0));
+ }
+ break;
+ default:
+ return sal_False;
+ }
+ return sal_True;
+}
+
+void SAL_CALL
+SwXParagraph::addPropertyChangeListener(
+ const ::rtl::OUString& /*rPropertyName*/,
+ const uno::Reference< beans::XPropertyChangeListener >& /*xListener*/)
+throw (beans::UnknownPropertyException, lang::WrappedTargetException,
+ uno::RuntimeException)
+{
+ OSL_FAIL("SwXParagraph::addPropertyChangeListener(): not implemented");
+}
+
+void SAL_CALL
+SwXParagraph::removePropertyChangeListener(
+ const ::rtl::OUString& /*rPropertyName*/,
+ const uno::Reference< beans::XPropertyChangeListener >& /*xListener*/)
+throw (beans::UnknownPropertyException, lang::WrappedTargetException,
+ uno::RuntimeException)
+{
+ OSL_FAIL("SwXParagraph::removePropertyChangeListener(): not implemented");
+}
+
+void SAL_CALL
+SwXParagraph::addVetoableChangeListener(
+ const ::rtl::OUString& /*rPropertyName*/,
+ const uno::Reference< beans::XVetoableChangeListener >& /*xListener*/)
+throw (beans::UnknownPropertyException, lang::WrappedTargetException,
+ uno::RuntimeException)
+{
+ OSL_FAIL("SwXParagraph::addVetoableChangeListener(): not implemented");
+}
+
+void SAL_CALL
+SwXParagraph::removeVetoableChangeListener(
+ const ::rtl::OUString& /*rPropertyName*/,
+ const uno::Reference< beans::XVetoableChangeListener >& /*xListener*/)
+throw (beans::UnknownPropertyException, lang::WrappedTargetException,
+ uno::RuntimeException)
+{
+ OSL_FAIL("SwXParagraph::removeVetoableChangeListener(): not implemented");
+}
+
+beans::PropertyState lcl_SwXParagraph_getPropertyState(
+// SwUnoCrsr& rUnoCrsr,
+ const SwTxtNode& rTxtNode,
+ const SwAttrSet** ppSet,
+ const SfxItemPropertySimpleEntry& rEntry,
+ sal_Bool &rAttrSetFetched )
+throw (beans::UnknownPropertyException)
+{
+ beans::PropertyState eRet = beans::PropertyState_DEFAULT_VALUE;
+
+ if(!(*ppSet) && !rAttrSetFetched )
+ {
+ (*ppSet) = rTxtNode.GetpSwAttrSet();
+ rAttrSetFetched = sal_True;
+ }
+ SwPosition aPos( rTxtNode );
+ SwPaM aPam( aPos );
+ switch( rEntry.nWID )
+ {
+ case FN_UNO_NUM_RULES:
+ // if numbering is set, return it; else do nothing
+ SwUnoCursorHelper::getNumberingProperty( aPam, eRet, NULL );
+ break;
+ case FN_UNO_ANCHOR_TYPES:
+ break;
+ case RES_ANCHOR:
+ if ( MID_SURROUND_SURROUNDTYPE != rEntry.nMemberId )
+ goto lcl_SwXParagraph_getPropertyStateDEFAULT;
+ break;
+ case RES_SURROUND:
+ if ( MID_ANCHOR_ANCHORTYPE != rEntry.nMemberId )
+ goto lcl_SwXParagraph_getPropertyStateDEFAULT;
+ break;
+ case FN_UNO_PARA_STYLE:
+ case FN_UNO_PARA_CONDITIONAL_STYLE_NAME:
+ {
+ SwFmtColl* pFmt = SwUnoCursorHelper::GetCurTxtFmtColl(
+ aPam, rEntry.nWID == FN_UNO_PARA_CONDITIONAL_STYLE_NAME);
+ eRet = pFmt ? beans::PropertyState_DIRECT_VALUE
+ : beans::PropertyState_AMBIGUOUS_VALUE;
+ }
+ break;
+ case FN_UNO_PAGE_STYLE:
+ {
+ String sVal;
+ SwUnoCursorHelper::GetCurPageStyle( aPam, sVal );
+ eRet = sVal.Len() ? beans::PropertyState_DIRECT_VALUE
+ : beans::PropertyState_AMBIGUOUS_VALUE;
+ }
+ break;
+ lcl_SwXParagraph_getPropertyStateDEFAULT:
+ default:
+ if((*ppSet) && SFX_ITEM_SET == (*ppSet)->GetItemState(rEntry.nWID, sal_False))
+ eRet = beans::PropertyState_DIRECT_VALUE;
+ break;
+ }
+ return eRet;
+}
+
+beans::PropertyState SAL_CALL
+SwXParagraph::getPropertyState(const OUString& rPropertyName)
+throw (beans::UnknownPropertyException, uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+
+ SwTxtNode & rTxtNode(m_pImpl->GetTxtNodeOrThrow());
+
+ const SwAttrSet* pSet = 0;
+ SfxItemPropertySimpleEntry const*const pEntry =
+ m_pImpl->m_rPropSet.getPropertyMap()->getByName(rPropertyName);
+ if (!pEntry)
+ {
+ throw beans::UnknownPropertyException(
+ OUString(RTL_CONSTASCII_USTRINGPARAM("Unknown property: "))
+ + rPropertyName,
+ static_cast<cppu::OWeakObject *>(this));
+ }
+ sal_Bool bDummy = sal_False;
+ const beans::PropertyState eRet =
+ lcl_SwXParagraph_getPropertyState(rTxtNode, &pSet, *pEntry, bDummy);
+ return eRet;
+}
+
+uno::Sequence< beans::PropertyState > SAL_CALL
+SwXParagraph::getPropertyStates(
+ const uno::Sequence< OUString >& PropertyNames)
+throw (beans::UnknownPropertyException, uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+
+ SwTxtNode & rTxtNode(m_pImpl->GetTxtNodeOrThrow());
+
+ const OUString* pNames = PropertyNames.getConstArray();
+ uno::Sequence< beans::PropertyState > aRet(PropertyNames.getLength());
+ beans::PropertyState* pStates = aRet.getArray();
+ SfxItemPropertyMap const*const pMap = m_pImpl->m_rPropSet.getPropertyMap();
+ const SwAttrSet* pSet = 0;
+ sal_Bool bAttrSetFetched = sal_False;
+
+ for (sal_Int32 i = 0, nEnd = PropertyNames.getLength(); i < nEnd;
+ ++i, ++pStates, ++pNames)
+ {
+ SfxItemPropertySimpleEntry const*const pEntry =
+ pMap->getByName( *pNames );
+ if (!pEntry)
+ {
+ throw beans::UnknownPropertyException(
+ OUString(RTL_CONSTASCII_USTRINGPARAM("Unknown property: "))
+ + *pNames,
+ static_cast<cppu::OWeakObject *>(this));
+ }
+
+ if (bAttrSetFetched && !pSet && isATR(pEntry->nWID))
+ {
+ *pStates = beans::PropertyState_DEFAULT_VALUE;
+ }
+ else
+ {
+ *pStates = lcl_SwXParagraph_getPropertyState(
+ rTxtNode, &pSet, *pEntry, bAttrSetFetched );
+ }
+ }
+
+ return aRet;
+}
+
+void SAL_CALL
+SwXParagraph::setPropertyToDefault(const OUString& rPropertyName)
+throw (beans::UnknownPropertyException, uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+
+ SwTxtNode & rTxtNode(m_pImpl->GetTxtNodeOrThrow());
+
+ SwPosition aPos( rTxtNode );
+ SwCursor aCursor( aPos, 0, false );
+ if (rPropertyName.equalsAsciiL(SW_PROP_NAME(UNO_NAME_ANCHOR_TYPE)) ||
+ rPropertyName.equalsAsciiL(SW_PROP_NAME(UNO_NAME_ANCHOR_TYPES)) ||
+ rPropertyName.equalsAsciiL(SW_PROP_NAME(UNO_NAME_TEXT_WRAP)))
+ {
+ return;
+ }
+
+ // select paragraph
+ SwParaSelection aParaSel( aCursor );
+ SfxItemPropertySimpleEntry const*const pEntry =
+ m_pImpl->m_rPropSet.getPropertyMap()->getByName( rPropertyName );
+ if (!pEntry)
+ {
+ throw beans::UnknownPropertyException(
+ OUString(RTL_CONSTASCII_USTRINGPARAM("Unknown property: "))
+ + rPropertyName,
+ static_cast<cppu::OWeakObject *>(this));
+ }
+
+ if (pEntry->nFlags & beans::PropertyAttribute::READONLY)
+ {
+ throw uno::RuntimeException(
+ OUString(RTL_CONSTASCII_USTRINGPARAM("Property is read-only: "))
+ + rPropertyName,
+ static_cast<cppu::OWeakObject *>(this));
+ }
+
+ if (pEntry->nWID < RES_FRMATR_END)
+ {
+ SvUShortsSort aWhichIds;
+ aWhichIds.Insert(pEntry->nWID);
+ if (pEntry->nWID < RES_PARATR_BEGIN)
+ {
+ aCursor.GetDoc()->ResetAttrs(aCursor, sal_True, &aWhichIds);
+ }
+ else
+ {
+ // for paragraph attributes the selection must be extended
+ // to paragraph boundaries
+ SwPosition aStart( *aCursor.Start() );
+ SwPosition aEnd ( *aCursor.End() );
+ ::std::auto_ptr<SwUnoCrsr> pTemp(
+ aCursor.GetDoc()->CreateUnoCrsr(aStart, sal_False) );
+ if(!SwUnoCursorHelper::IsStartOfPara(*pTemp))
+ {
+ pTemp->MovePara(fnParaCurr, fnParaStart);
+ }
+ pTemp->SetMark();
+ *pTemp->GetPoint() = aEnd;
+ //pTemp->Exchange();
+ SwUnoCursorHelper::SelectPam(*pTemp, true);
+ if (!SwUnoCursorHelper::IsEndOfPara(*pTemp))
+ {
+ pTemp->MovePara(fnParaCurr, fnParaEnd);
+ }
+ pTemp->GetDoc()->ResetAttrs(*pTemp, sal_True, &aWhichIds);
+ }
+ }
+ else
+ {
+ SwUnoCursorHelper::resetCrsrPropertyValue(*pEntry, aCursor);
+ }
+}
+
+uno::Any SAL_CALL
+SwXParagraph::getPropertyDefault(const OUString& rPropertyName)
+throw (beans::UnknownPropertyException, lang::WrappedTargetException,
+ uno::RuntimeException)
+{
+ SolarMutexGuard g;
+
+ SwTxtNode & rTxtNode(m_pImpl->GetTxtNodeOrThrow());
+
+ uno::Any aRet;
+ if (::sw::GetDefaultTextContentValue(aRet, rPropertyName))
+ {
+ return aRet;
+ }
+
+ SfxItemPropertySimpleEntry const*const pEntry =
+ m_pImpl->m_rPropSet.getPropertyMap()->getByName(rPropertyName);
+ if (!pEntry)
+ {
+ throw beans::UnknownPropertyException(
+ OUString(RTL_CONSTASCII_USTRINGPARAM("Unknown property: "))
+ + rPropertyName,
+ static_cast<cppu::OWeakObject *>(this));
+ }
+
+ if (pEntry->nWID < RES_FRMATR_END)
+ {
+ const SfxPoolItem& rDefItem =
+ rTxtNode.GetDoc()->GetAttrPool().GetDefaultItem(pEntry->nWID);
+ rDefItem.QueryValue(aRet, pEntry->nMemberId);
+ }
+
+ return aRet;
+}
+
+void SAL_CALL
+SwXParagraph::attach(const uno::Reference< text::XTextRange > & /*xTextRange*/)
+throw (lang::IllegalArgumentException, uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+ // SwXParagraph will only created in order to be inserted by
+ // 'insertTextContentBefore' or 'insertTextContentAfter' therefore
+ // they cannot be attached
+ throw uno::RuntimeException();
+}
+
+uno::Reference< text::XTextRange > SAL_CALL
+SwXParagraph::getAnchor() throw (uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+
+ SwTxtNode & rTxtNode(m_pImpl->GetTxtNodeOrThrow());
+
+ SwPosition aPos( rTxtNode );
+ SwCursor aCursor( aPos, 0, false );
+ // select paragraph
+ SwParaSelection aParaSel( aCursor );
+ const uno::Reference< text::XTextRange > xRet =
+ new SwXTextRange(aCursor, m_pImpl->m_xParentText);
+ return xRet;
+}
+
+void SAL_CALL SwXParagraph::dispose() throw (uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+
+ SwTxtNode *const pTxtNode( m_pImpl->GetTxtNode() );
+ if (pTxtNode)
+ {
+ SwCursor aCursor( SwPosition( *pTxtNode ), 0, false );
+ // select paragraph
+ {
+ SwParaSelection aParaSel( aCursor );
+ pTxtNode->GetDoc()->DelFullPara(aCursor);
+ }
+ m_pImpl->m_ListenerContainer.Disposing();
+ }
+}
+
+void SAL_CALL SwXParagraph::addEventListener(
+ const uno::Reference< lang::XEventListener > & xListener)
+throw (uno::RuntimeException)
+{
+ SolarMutexGuard g;
+
+ if (!m_pImpl->GetTxtNode())
+ {
+ throw uno::RuntimeException();
+ }
+ m_pImpl->m_ListenerContainer.AddListener(xListener);
+}
+
+void SAL_CALL SwXParagraph::removeEventListener(
+ const uno::Reference< lang::XEventListener > & xListener)
+throw (uno::RuntimeException)
+{
+ SolarMutexGuard g;
+
+ if (!m_pImpl->GetTxtNode() ||
+ !m_pImpl->m_ListenerContainer.RemoveListener(xListener))
+ {
+ throw uno::RuntimeException();
+ }
+}
+
+uno::Reference< container::XEnumeration > SAL_CALL
+SwXParagraph::createEnumeration() throw (uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+
+ SwTxtNode & rTxtNode(m_pImpl->GetTxtNodeOrThrow());
+
+ SwPosition aPos( rTxtNode );
+ SwPaM aPam ( aPos );
+ const uno::Reference< container::XEnumeration > xRef =
+ new SwXTextPortionEnumeration(aPam, m_pImpl->m_xParentText,
+ m_pImpl->m_nSelectionStartPos, m_pImpl->m_nSelectionEndPos);
+ return xRef;
+}
+
+uno::Type SAL_CALL SwXParagraph::getElementType() throw (uno::RuntimeException)
+{
+ return text::XTextRange::static_type();
+}
+
+sal_Bool SAL_CALL SwXParagraph::hasElements() throw (uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+ return (GetTxtNode()) ? sal_True : sal_False;
+}
+
+uno::Reference< text::XText > SAL_CALL
+SwXParagraph::getText() throw (uno::RuntimeException)
+{
+ SolarMutexGuard g;
+
+ return m_pImpl->m_xParentText;
+}
+
+uno::Reference< text::XTextRange > SAL_CALL
+SwXParagraph::getStart() throw (uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+
+ SwTxtNode & rTxtNode(m_pImpl->GetTxtNodeOrThrow());
+
+ SwPosition aPos( rTxtNode );
+ SwCursor aCursor( aPos, 0, false );
+ SwParaSelection aParaSel( aCursor );
+ SwPaM aPam( *aCursor.Start() );
+ uno::Reference< text::XText > xParent = getText();
+ const uno::Reference< text::XTextRange > xRet =
+ new SwXTextRange(aPam, xParent);
+ return xRet;
+}
+
+uno::Reference< text::XTextRange > SAL_CALL
+SwXParagraph::getEnd() throw (uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+
+ SwTxtNode & rTxtNode(m_pImpl->GetTxtNodeOrThrow());
+
+ SwPosition aPos( rTxtNode );
+ SwCursor aCursor( aPos, 0, false );
+ SwParaSelection aParaSel( aCursor );
+ SwPaM aPam( *aCursor.End() );
+ uno::Reference< text::XText > xParent = getText();
+ const uno::Reference< text::XTextRange > xRet =
+ new SwXTextRange(aPam, xParent);
+ return xRet;
+}
+
+OUString SAL_CALL SwXParagraph::getString() throw (uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+ OUString aRet;
+ SwTxtNode const*const pTxtNode( GetTxtNode() );
+ if (pTxtNode)
+ {
+ SwPosition aPos( *pTxtNode );
+ SwCursor aCursor( aPos, 0, false );
+ SwParaSelection aParaSel( aCursor );
+ SwUnoCursorHelper::GetTextFromPam(aCursor, aRet);
+ }
+ else if (m_pImpl->IsDescriptor())
+ {
+ aRet = m_pImpl->m_sText;
+ }
+ else
+ {
+ throw uno::RuntimeException();
+ }
+ return aRet;
+}
+
+void SAL_CALL SwXParagraph::setString(const OUString& aString)
+throw (uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+
+ SwTxtNode const*const pTxtNode( GetTxtNode() );
+ if (pTxtNode)
+ {
+ SwPosition aPos( *pTxtNode );
+ SwCursor aCursor( aPos, 0, false );
+ if (!SwUnoCursorHelper::IsStartOfPara(aCursor)) {
+ aCursor.MovePara(fnParaCurr, fnParaStart);
+ }
+ SwUnoCursorHelper::SelectPam(aCursor, true);
+ if (pTxtNode->GetTxt().Len()) {
+ aCursor.MovePara(fnParaCurr, fnParaEnd);
+ }
+ SwUnoCursorHelper::SetString(aCursor, aString);
+ SwUnoCursorHelper::SelectPam(aCursor, false);
+ }
+ else if (m_pImpl->IsDescriptor())
+ {
+ m_pImpl->m_sText = aString;
+ }
+ else
+ {
+ throw uno::RuntimeException();
+ }
+}
+
+uno::Reference< container::XEnumeration > SAL_CALL
+SwXParagraph::createContentEnumeration(const OUString& rServiceName)
+throw (uno::RuntimeException)
+{
+ SolarMutexGuard g;
+
+ if (!rServiceName.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("com.sun.star.text.TextContent")))
+ {
+ throw uno::RuntimeException();
+ }
+
+ SwTxtNode & rTxtNode(m_pImpl->GetTxtNodeOrThrow());
+
+ SwPosition aPos( rTxtNode );
+ SwPaM aPam( aPos );
+ uno::Reference< container::XEnumeration > xRet =
+ new SwXParaFrameEnumeration(aPam, PARAFRAME_PORTION_PARAGRAPH);
+ return xRet;
+}
+
+uno::Sequence< OUString > SAL_CALL
+SwXParagraph::getAvailableServiceNames() throw (uno::RuntimeException)
+{
+ uno::Sequence< OUString > aRet(1);
+ OUString* pArray = aRet.getArray();
+ pArray[0] = C2U("com.sun.star.text.TextContent");
+ return aRet;
+}
+
+// MetadatableMixin
+::sfx2::Metadatable* SwXParagraph::GetCoreObject()
+{
+ SwTxtNode *const pTxtNode( m_pImpl->GetTxtNode() );
+ return pTxtNode;
+}
+
+uno::Reference<frame::XModel> SwXParagraph::GetModel()
+{
+ SwTxtNode *const pTxtNode( m_pImpl->GetTxtNode() );
+ if (pTxtNode)
+ {
+ SwDocShell const*const pShell( pTxtNode->GetDoc()->GetDocShell() );
+ return (pShell) ? pShell->GetModel() : 0;
+ }
+ return 0;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/unocore/unoport.cxx b/sw/source/core/unocore/unoport.cxx
new file mode 100644
index 000000000000..132c661bef3e
--- /dev/null
+++ b/sw/source/core/unocore/unoport.cxx
@@ -0,0 +1,979 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+
+#include <cmdid.h>
+#include <osl/mutex.hxx>
+#include <vcl/svapp.hxx>
+#include <svl/itemprop.hxx>
+
+#include <unocrsrhelper.hxx>
+#include <unoport.hxx>
+#include <unoparaframeenum.hxx>
+#include <unotextrange.hxx>
+#include <unomap.hxx>
+#include <unoprnms.hxx>
+#include <unomid.h>
+#include <txtatr.hxx>
+#include <txtfld.hxx>
+#include <ndtxt.hxx>
+#include <doc.hxx>
+#include <fmtflcnt.hxx>
+#include <fmtfld.hxx>
+#include <frmfmt.hxx>
+
+#include <com/sun/star/beans/PropertyAttribute.hpp>
+#include <com/sun/star/beans/SetPropertyTolerantFailed.hpp>
+#include <com/sun/star/beans/GetPropertyTolerantResult.hpp>
+#include <com/sun/star/beans/TolerantPropertySetResultType.hpp>
+
+
+using namespace ::com::sun::star;
+using ::rtl::OUString;
+
+/******************************************************************
+ * SwXTextPortion
+ ******************************************************************/
+void SwXTextPortion::init(const SwUnoCrsr* pPortionCursor)
+{
+ SwUnoCrsr* pUnoCursor =
+ pPortionCursor->GetDoc()->CreateUnoCrsr(*pPortionCursor->GetPoint());
+ if (pPortionCursor->HasMark())
+ {
+ pUnoCursor->SetMark();
+ *pUnoCursor->GetMark() = *pPortionCursor->GetMark();
+ }
+ pUnoCursor->Add(this);
+}
+
+SwXTextPortion::SwXTextPortion(const SwUnoCrsr* pPortionCrsr,
+ uno::Reference< text::XText > const& rParent,
+ SwTextPortionType eType)
+ : m_ListenerContainer( static_cast<text::XTextRange*>(this) )
+ , m_pPropSet(aSwMapProvider.GetPropertySet(
+ (PORTION_REDLINE_START == eType ||
+ PORTION_REDLINE_END == eType)
+ ? PROPERTY_MAP_REDLINE_PORTION
+ : PROPERTY_MAP_TEXTPORTION_EXTENSIONS))
+ , m_xParentText(rParent)
+ , m_pRubyText(0)
+ , m_pRubyStyle(0)
+ , m_pRubyAdjust(0)
+ , m_pRubyIsAbove(0)
+ , m_FrameDepend(this, 0)
+ , m_pFrameFmt(0)
+ , m_ePortionType(eType)
+ , m_bIsCollapsed(false)
+{
+ init( pPortionCrsr);
+}
+
+SwXTextPortion::SwXTextPortion(const SwUnoCrsr* pPortionCrsr,
+ uno::Reference< text::XText > const& rParent,
+ SwFrmFmt& rFmt )
+ : m_ListenerContainer( static_cast<text::XTextRange*>(this) )
+ , m_pPropSet(aSwMapProvider.GetPropertySet(
+ PROPERTY_MAP_TEXTPORTION_EXTENSIONS))
+ , m_xParentText(rParent)
+ , m_pRubyText(0)
+ , m_pRubyStyle(0)
+ , m_pRubyAdjust(0)
+ , m_pRubyIsAbove(0)
+ , m_FrameDepend(this, &rFmt)
+ , m_pFrameFmt(&rFmt)
+ , m_ePortionType(PORTION_FRAME)
+ , m_bIsCollapsed(false)
+{
+ init( pPortionCrsr);
+}
+
+SwXTextPortion::SwXTextPortion(const SwUnoCrsr* pPortionCrsr,
+ SwTxtRuby const& rAttr,
+ uno::Reference< text::XText > const& xParent,
+ sal_Bool bIsEnd )
+ : m_ListenerContainer( static_cast<text::XTextRange*>(this) )
+ , m_pPropSet(aSwMapProvider.GetPropertySet(
+ PROPERTY_MAP_TEXTPORTION_EXTENSIONS))
+ , m_xParentText(xParent)
+ , m_pRubyText ( bIsEnd ? 0 : new uno::Any )
+ , m_pRubyStyle ( bIsEnd ? 0 : new uno::Any )
+ , m_pRubyAdjust ( bIsEnd ? 0 : new uno::Any )
+ , m_pRubyIsAbove( bIsEnd ? 0 : new uno::Any )
+ , m_FrameDepend(this, 0)
+ , m_pFrameFmt(0)
+ , m_ePortionType( bIsEnd ? PORTION_RUBY_END : PORTION_RUBY_START )
+ , m_bIsCollapsed(false)
+{
+ init( pPortionCrsr);
+
+ if (!bIsEnd)
+ {
+ const SfxPoolItem& rItem = rAttr.GetAttr();
+ rItem.QueryValue(*m_pRubyText, MID_RUBY_TEXT);
+ rItem.QueryValue(*m_pRubyStyle, MID_RUBY_CHARSTYLE);
+ rItem.QueryValue(*m_pRubyAdjust, MID_RUBY_ADJUST);
+ rItem.QueryValue(*m_pRubyIsAbove, MID_RUBY_ABOVE);
+ }
+}
+
+SwXTextPortion::~SwXTextPortion()
+{
+ SolarMutexGuard aGuard;
+ SwUnoCrsr* pUnoCrsr = GetCursor();
+ delete pUnoCrsr;
+}
+
+uno::Reference< text::XText > SwXTextPortion::getText()
+throw( uno::RuntimeException )
+{
+ return m_xParentText;
+}
+
+uno::Reference< text::XTextRange > SwXTextPortion::getStart()
+throw( uno::RuntimeException )
+{
+ SolarMutexGuard aGuard;
+ uno::Reference< text::XTextRange > xRet;
+ SwUnoCrsr* pUnoCrsr = GetCursor();
+ if (!pUnoCrsr)
+ throw uno::RuntimeException();
+
+ SwPaM aPam(*pUnoCrsr->Start());
+ uno::Reference< text::XText > xParent = getText();
+ xRet = new SwXTextRange(aPam, xParent);
+ return xRet;
+}
+
+uno::Reference< text::XTextRange > SwXTextPortion::getEnd()
+throw( uno::RuntimeException )
+{
+ SolarMutexGuard aGuard;
+ uno::Reference< text::XTextRange > xRet;
+ SwUnoCrsr* pUnoCrsr = GetCursor();
+ if (!pUnoCrsr)
+ throw uno::RuntimeException();
+
+ SwPaM aPam(*pUnoCrsr->End());
+ uno::Reference< text::XText > xParent = getText();
+ xRet = new SwXTextRange(aPam, xParent);
+ return xRet;
+}
+
+OUString SwXTextPortion::getString()
+throw( uno::RuntimeException )
+{
+ SolarMutexGuard aGuard;
+ OUString aTxt;
+ SwUnoCrsr* pUnoCrsr = GetCursor();
+ if (!pUnoCrsr)
+ throw uno::RuntimeException();
+
+ // TextPortions are always within a paragraph
+ SwTxtNode* pTxtNd = pUnoCrsr->GetNode()->GetTxtNode();
+ if ( pTxtNd )
+ {
+ xub_StrLen nStt = pUnoCrsr->Start()->nContent.GetIndex();
+ aTxt = pTxtNd->GetExpandTxt( nStt,
+ pUnoCrsr->End()->nContent.GetIndex() - nStt );
+ }
+ return aTxt;
+}
+
+void SwXTextPortion::setString(const OUString& aString) throw( uno::RuntimeException )
+{
+ SolarMutexGuard aGuard;
+ SwUnoCrsr* pUnoCrsr = GetCursor();
+ if (!pUnoCrsr)
+ throw uno::RuntimeException();
+
+ SwUnoCursorHelper::SetString(*pUnoCrsr, aString);
+}
+
+uno::Reference< beans::XPropertySetInfo > SwXTextPortion::getPropertySetInfo()
+throw( uno::RuntimeException )
+{
+ SolarMutexGuard aGuard;
+ //! PropertySetInfo for text portion extensions
+ static uno::Reference< beans::XPropertySetInfo >
+ xTxtPorExtRef = aSwMapProvider.GetPropertySet(
+ PROPERTY_MAP_TEXTPORTION_EXTENSIONS)->getPropertySetInfo();
+ //! PropertySetInfo for redline portions
+ static uno::Reference< beans::XPropertySetInfo >
+ xRedlPorRef = aSwMapProvider.GetPropertySet(
+ PROPERTY_MAP_REDLINE_PORTION)->getPropertySetInfo();
+
+ return (PORTION_REDLINE_START == m_ePortionType ||
+ PORTION_REDLINE_END == m_ePortionType) ? xRedlPorRef : xTxtPorExtRef;
+}
+
+void SwXTextPortion::setPropertyValue(const OUString& rPropertyName,
+ const uno::Any& aValue)
+ throw( beans::UnknownPropertyException,
+ beans::PropertyVetoException, lang::IllegalArgumentException, lang::WrappedTargetException, uno::RuntimeException )
+{
+ SolarMutexGuard aGuard;
+ SwUnoCrsr* pUnoCrsr = GetCursor();
+ if (!pUnoCrsr)
+ throw uno::RuntimeException();
+
+ SwUnoCursorHelper::SetPropertyValue(*pUnoCrsr, *m_pPropSet,
+ rPropertyName, aValue);
+}
+
+void SwXTextPortion::GetPropertyValue(
+ uno::Any &rVal,
+ const SfxItemPropertySimpleEntry& rEntry,
+ SwUnoCrsr *pUnoCrsr,
+ SfxItemSet *&pSet )
+{
+ DBG_ASSERT( pUnoCrsr, "UNO cursor missing" );
+ if (!pUnoCrsr)
+ return;
+ if(pUnoCrsr)
+ {
+ switch(rEntry.nWID)
+ {
+ case FN_UNO_TEXT_PORTION_TYPE:
+ {
+ const char* pRet;
+ switch (m_ePortionType)
+ {
+ case PORTION_TEXT: pRet = "Text";break;
+ case PORTION_FIELD: pRet = "TextField";break;
+ case PORTION_FRAME: pRet = "Frame";break;
+ case PORTION_FOOTNOTE: pRet = "Footnote";break;
+ case PORTION_REFMARK_START:
+ case PORTION_REFMARK_END: pRet = SW_PROP_NAME_STR(UNO_NAME_REFERENCE_MARK);break;
+ case PORTION_TOXMARK_START:
+ case PORTION_TOXMARK_END: pRet = SW_PROP_NAME_STR(UNO_NAME_DOCUMENT_INDEX_MARK);break;
+ case PORTION_BOOKMARK_START :
+ case PORTION_BOOKMARK_END : pRet = SW_PROP_NAME_STR(UNO_NAME_BOOKMARK);break;
+ case PORTION_REDLINE_START:
+ case PORTION_REDLINE_END: pRet = "Redline";break;
+ case PORTION_RUBY_START:
+ case PORTION_RUBY_END: pRet = "Ruby";break;
+ case PORTION_SOFT_PAGEBREAK:pRet = "SoftPageBreak";break;
+ case PORTION_META: pRet = SW_PROP_NAME_STR(UNO_NAME_META); break;
+ case PORTION_FIELD_START:pRet = "TextFieldStart";break;
+ case PORTION_FIELD_END:pRet = "TextFieldEnd";break;
+ case PORTION_FIELD_START_END:pRet = "TextFieldStartEnd";break;
+ default:
+ pRet = 0;
+ }
+
+ OUString sRet;
+ if( pRet )
+ sRet = rtl::OUString::createFromAscii( pRet );
+ rVal <<= sRet;
+ }
+ break;
+ case FN_UNO_CONTROL_CHARACTER: // obsolete!
+ break;
+ case FN_UNO_DOCUMENT_INDEX_MARK:
+ rVal <<= m_xTOXMark;
+ break;
+ case FN_UNO_REFERENCE_MARK:
+ rVal <<= m_xRefMark;
+ break;
+ case FN_UNO_BOOKMARK:
+ rVal <<= m_xBookmark;
+ break;
+ case FN_UNO_FOOTNOTE:
+ rVal <<= m_xFootnote;
+ break;
+ case FN_UNO_TEXT_FIELD:
+ rVal <<= m_xTextField;
+ break;
+ case FN_UNO_META:
+ rVal <<= m_xMeta;
+ break;
+ case FN_UNO_IS_COLLAPSED:
+ {
+ switch (m_ePortionType)
+ {
+ case PORTION_REFMARK_START:
+ case PORTION_BOOKMARK_START :
+ case PORTION_TOXMARK_START:
+ case PORTION_REFMARK_END:
+ case PORTION_TOXMARK_END:
+ case PORTION_BOOKMARK_END :
+ case PORTION_REDLINE_START :
+ case PORTION_REDLINE_END :
+ case PORTION_RUBY_START:
+ case PORTION_RUBY_END:
+ case PORTION_FIELD_START:
+ case PORTION_FIELD_END:
+ rVal.setValue(&m_bIsCollapsed, ::getBooleanCppuType());
+ break;
+ default:
+ break;
+ }
+ }
+ break;
+ case FN_UNO_IS_START:
+ {
+ sal_Bool bStart = sal_True, bPut = sal_True;
+ switch (m_ePortionType)
+ {
+ case PORTION_REFMARK_START:
+ case PORTION_BOOKMARK_START:
+ case PORTION_TOXMARK_START:
+ case PORTION_REDLINE_START:
+ case PORTION_RUBY_START:
+ case PORTION_FIELD_START:
+ break;
+
+ case PORTION_REFMARK_END:
+ case PORTION_TOXMARK_END:
+ case PORTION_BOOKMARK_END:
+ case PORTION_REDLINE_END:
+ case PORTION_RUBY_END:
+ case PORTION_FIELD_END:
+ bStart = sal_False;
+ break;
+ default:
+ bPut = sal_False;
+ }
+ if(bPut)
+ rVal.setValue(&bStart, ::getBooleanCppuType());
+ }
+ break;
+ case RES_TXTATR_CJK_RUBY:
+ {
+ const uno::Any* pToSet = 0;
+ switch(rEntry.nMemberId)
+ {
+ case MID_RUBY_TEXT : pToSet = m_pRubyText.get(); break;
+ case MID_RUBY_ADJUST : pToSet = m_pRubyAdjust.get(); break;
+ case MID_RUBY_CHARSTYLE:pToSet = m_pRubyStyle.get(); break;
+ case MID_RUBY_ABOVE : pToSet = m_pRubyIsAbove.get();break;
+ }
+ if(pToSet)
+ rVal = *pToSet;
+ }
+ break;
+ default:
+ beans::PropertyState eTemp;
+ sal_Bool bDone = SwUnoCursorHelper::getCrsrPropertyValue(
+ rEntry, *pUnoCrsr, &(rVal), eTemp );
+ if(!bDone)
+ {
+ if(!pSet)
+ {
+ pSet = new SfxItemSet(pUnoCrsr->GetDoc()->GetAttrPool(),
+ RES_CHRATR_BEGIN, RES_FRMATR_END - 1,
+ RES_UNKNOWNATR_CONTAINER, RES_UNKNOWNATR_CONTAINER,
+ RES_TXTATR_UNKNOWN_CONTAINER, RES_TXTATR_UNKNOWN_CONTAINER,
+ 0L);
+ SwUnoCursorHelper::GetCrsrAttr(*pUnoCrsr, *pSet);
+ }
+ m_pPropSet->getPropertyValue(rEntry, *pSet, rVal);
+ }
+ }
+ }
+}
+
+uno::Sequence< uno::Any > SAL_CALL SwXTextPortion::GetPropertyValues_Impl(
+ const uno::Sequence< OUString >& rPropertyNames )
+ throw( beans::UnknownPropertyException, lang::WrappedTargetException, uno::RuntimeException )
+{
+ sal_Int32 nLength = rPropertyNames.getLength();
+ const OUString *pPropertyNames = rPropertyNames.getConstArray();
+ uno::Sequence< uno::Any > aValues(rPropertyNames.getLength());
+ uno::Any *pValues = aValues.getArray();
+ SwUnoCrsr* pUnoCrsr = GetCursor();
+ if (!pUnoCrsr)
+ throw uno::RuntimeException();
+
+ {
+ SfxItemSet *pSet = 0;
+ // get startting pount fo the look-up, either the provided one or else
+ // from the beginning of the map
+ const SfxItemPropertyMap* pMap = m_pPropSet->getPropertyMap();
+ for(sal_Int32 nProp = 0; nProp < nLength; nProp++)
+ {
+ const SfxItemPropertySimpleEntry* pEntry = pMap->getByName(pPropertyNames[nProp]);
+ if(pEntry)
+ {
+ GetPropertyValue( pValues[nProp], *pEntry, pUnoCrsr, pSet );
+ }
+ else
+ throw beans::UnknownPropertyException(OUString ( RTL_CONSTASCII_USTRINGPARAM ( "Unknown property: " ) ) + pPropertyNames[nProp], static_cast < cppu::OWeakObject * > ( this ) );
+ }
+ delete pSet;
+ }
+ return aValues;
+}
+
+uno::Any SwXTextPortion::getPropertyValue(
+ const OUString& rPropertyName)
+ throw( beans::UnknownPropertyException, lang::WrappedTargetException, uno::RuntimeException )
+{
+ SolarMutexGuard aGuard;
+ uno::Sequence< ::rtl::OUString > aPropertyNames(1);
+ aPropertyNames.getArray()[0] = rPropertyName;
+ return GetPropertyValues_Impl(aPropertyNames).getConstArray()[0];
+}
+
+void SAL_CALL SwXTextPortion::SetPropertyValues_Impl(
+ const uno::Sequence< OUString >& rPropertyNames,
+ const uno::Sequence< uno::Any >& rValues )
+ throw( beans::UnknownPropertyException, beans::PropertyVetoException, lang::IllegalArgumentException,
+ lang::WrappedTargetException, uno::RuntimeException)
+{
+ SwUnoCrsr* pUnoCrsr = GetCursor();
+ if (!pUnoCrsr)
+ throw uno::RuntimeException();
+
+ {
+ const OUString* pPropertyNames = rPropertyNames.getConstArray();
+ const uno::Any* pValues = rValues.getConstArray();
+ const SfxItemPropertyMap* pMap = m_pPropSet->getPropertyMap();
+ for(sal_Int32 nProp = 0; nProp < rPropertyNames.getLength(); nProp++)
+ {
+ const SfxItemPropertySimpleEntry* pEntry = pMap->getByName(pPropertyNames[nProp]);
+ if (!pEntry)
+ throw beans::UnknownPropertyException(OUString ( RTL_CONSTASCII_USTRINGPARAM ( "Unknown property: " ) ) + pPropertyNames[nProp], static_cast < cppu::OWeakObject * > ( this ) );
+ if ( pEntry->nFlags & beans::PropertyAttribute::READONLY)
+ throw beans::PropertyVetoException ( OUString ( RTL_CONSTASCII_USTRINGPARAM ( "Property is read-only: " ) ) + pPropertyNames[nProp], static_cast < cppu::OWeakObject * > ( this ) );
+
+ SwUnoCursorHelper::SetPropertyValue( *pUnoCrsr, *m_pPropSet,
+ pPropertyNames[nProp], pValues[nProp]);
+ }
+ }
+}
+
+void SwXTextPortion::setPropertyValues(
+ const uno::Sequence< OUString >& rPropertyNames,
+ const uno::Sequence< uno::Any >& rValues )
+ throw(beans::PropertyVetoException, lang::IllegalArgumentException,
+ lang::WrappedTargetException, uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+
+ // workaround for bad designed API
+ try
+ {
+ SetPropertyValues_Impl( rPropertyNames, rValues );
+ }
+ catch (beans::UnknownPropertyException &rException)
+ {
+ // wrap the original (here not allowed) exception in
+ // a lang::WrappedTargetException that gets thrown instead.
+ lang::WrappedTargetException aWExc;
+ aWExc.TargetException <<= rException;
+ throw aWExc;
+ }
+}
+
+uno::Sequence< uno::Any > SwXTextPortion::getPropertyValues(
+ const uno::Sequence< OUString >& rPropertyNames )
+ throw(uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+ uno::Sequence< uno::Any > aValues;
+
+ // workaround for bad designed API
+ try
+ {
+ aValues = GetPropertyValues_Impl( rPropertyNames );
+ }
+ catch (beans::UnknownPropertyException &)
+ {
+ throw uno::RuntimeException(OUString ( RTL_CONSTASCII_USTRINGPARAM ( "Unknown property exception caught" ) ), static_cast < cppu::OWeakObject * > ( this ) );
+ }
+ catch (lang::WrappedTargetException &)
+ {
+ throw uno::RuntimeException(OUString ( RTL_CONSTASCII_USTRINGPARAM ( "WrappedTargetException caught" ) ), static_cast < cppu::OWeakObject * > ( this ) );
+ }
+
+ return aValues;
+}
+
+/* disabled for #i46921# */
+uno::Sequence< beans::SetPropertyTolerantFailed > SAL_CALL SwXTextPortion::setPropertyValuesTolerant(
+ const uno::Sequence< OUString >& rPropertyNames,
+ const uno::Sequence< uno::Any >& rValues )
+ throw (lang::IllegalArgumentException, uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+
+ if (rPropertyNames.getLength() != rValues.getLength())
+ throw lang::IllegalArgumentException();
+ SwUnoCrsr* pUnoCrsr = this->GetCursor();
+ if (!pUnoCrsr)
+ throw uno::RuntimeException();
+
+ sal_Int32 nProps = rPropertyNames.getLength();
+ const OUString *pProp = rPropertyNames.getConstArray();
+
+ //sal_Int32 nVals = rValues.getLength();
+ const uno::Any *pValue = rValues.getConstArray();
+
+ sal_Int32 nFailed = 0;
+ uno::Sequence< beans::SetPropertyTolerantFailed > aFailed( nProps );
+ beans::SetPropertyTolerantFailed *pFailed = aFailed.getArray();
+
+ const SfxItemPropertyMap* pPropMap = m_pPropSet->getPropertyMap();
+
+ OUString sTmp;
+ for (sal_Int32 i = 0; i < nProps; ++i)
+ {
+ try
+ {
+ pFailed[ nFailed ].Name = pProp[i];
+
+ const SfxItemPropertySimpleEntry* pEntry = pPropMap->getByName( pProp[i] );
+ if (!pEntry)
+ pFailed[ nFailed++ ].Result = beans::TolerantPropertySetResultType::UNKNOWN_PROPERTY;
+ else
+ {
+ // set property value
+ // (compare to SwXTextPortion::setPropertyValues)
+ if (pEntry->nFlags & beans::PropertyAttribute::READONLY)
+ pFailed[ nFailed++ ].Result = beans::TolerantPropertySetResultType::PROPERTY_VETO;
+ else
+ {
+ SwUnoCursorHelper::SetPropertyValue(
+ *pUnoCrsr, *m_pPropSet, pProp[i], pValue[i] );
+ }
+ }
+ }
+ catch (beans::UnknownPropertyException &)
+ {
+ // should not occur because property was searched for before
+ OSL_FAIL( "unexpected exception catched" );
+ pFailed[ nFailed++ ].Result = beans::TolerantPropertySetResultType::UNKNOWN_PROPERTY;
+ }
+ catch (lang::IllegalArgumentException &)
+ {
+ pFailed[ nFailed++ ].Result = beans::TolerantPropertySetResultType::ILLEGAL_ARGUMENT;
+ }
+ catch (beans::PropertyVetoException &)
+ {
+ pFailed[ nFailed++ ].Result = beans::TolerantPropertySetResultType::PROPERTY_VETO;
+ }
+ catch (lang::WrappedTargetException &)
+ {
+ pFailed[ nFailed++ ].Result = beans::TolerantPropertySetResultType::WRAPPED_TARGET;
+ }
+ }
+
+ aFailed.realloc( nFailed );
+ return aFailed;
+}
+
+uno::Sequence< beans::GetPropertyTolerantResult > SAL_CALL SwXTextPortion::getPropertyValuesTolerant(
+ const uno::Sequence< OUString >& rPropertyNames )
+ throw (uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+
+ uno::Sequence< beans::GetDirectPropertyTolerantResult > aTmpRes(
+ GetPropertyValuesTolerant_Impl( rPropertyNames, sal_False ) );
+ const beans::GetDirectPropertyTolerantResult *pTmpRes = aTmpRes.getConstArray();
+
+ // copy temporary result to final result type
+ sal_Int32 nLen = aTmpRes.getLength();
+ uno::Sequence< beans::GetPropertyTolerantResult > aRes( nLen );
+ beans::GetPropertyTolerantResult *pRes = aRes.getArray();
+ for (sal_Int32 i = 0; i < nLen; i++)
+ *pRes++ = *pTmpRes++;
+ return aRes;
+}
+
+uno::Sequence< beans::GetDirectPropertyTolerantResult > SAL_CALL SwXTextPortion::getDirectPropertyValuesTolerant(
+ const uno::Sequence< OUString >& rPropertyNames )
+ throw (uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+ return GetPropertyValuesTolerant_Impl( rPropertyNames, sal_True );
+}
+
+uno::Sequence< beans::GetDirectPropertyTolerantResult > SAL_CALL SwXTextPortion::GetPropertyValuesTolerant_Impl(
+ const uno::Sequence< OUString >& rPropertyNames,
+ sal_Bool bDirectValuesOnly )
+ throw (uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+
+ SwUnoCrsr* pUnoCrsr = this->GetCursor();
+ if(!pUnoCrsr)
+ throw uno::RuntimeException();
+
+ sal_Int32 nProps = rPropertyNames.getLength();
+ const OUString *pProp = rPropertyNames.getConstArray();
+
+ SfxItemSet *pSet = 0;
+
+ const SfxItemPropertyMap* pPropMap = m_pPropSet->getPropertyMap();
+
+ uno::Sequence< beans::PropertyState > aPropertyStates =
+ SwUnoCursorHelper::GetPropertyStates(
+ *pUnoCrsr, *m_pPropSet,
+ rPropertyNames,
+ SW_PROPERTY_STATE_CALLER_SWX_TEXT_PORTION_TOLERANT );
+ const beans::PropertyState* pPropertyStates = aPropertyStates.getConstArray();
+
+ std::vector< beans::GetDirectPropertyTolerantResult > aResultVector;
+ for (sal_Int32 i = 0; i < nProps; ++i)
+ {
+ beans::GetDirectPropertyTolerantResult aResult;
+ try
+ {
+ aResult.Name = pProp[i];
+ if(pPropertyStates[i] == beans::PropertyState_MAKE_FIXED_SIZE) // property unknown?
+ {
+ if( bDirectValuesOnly )
+ continue;
+ else
+ aResult.Result = beans::TolerantPropertySetResultType::UNKNOWN_PROPERTY;
+ }
+ else
+ {
+ const SfxItemPropertySimpleEntry* pEntry = pPropMap->getByName( pProp[i] );
+ aResult.State = pPropertyStates[i];
+
+ aResult.Result = beans::TolerantPropertySetResultType::UNKNOWN_FAILURE;
+ //#i104499# ruby portion attributes need special handling:
+ if( pEntry->nWID == RES_TXTATR_CJK_RUBY &&
+ m_ePortionType == PORTION_RUBY_START )
+ {
+ aResult.State = beans::PropertyState_DIRECT_VALUE;
+ }
+ if (!bDirectValuesOnly || beans::PropertyState_DIRECT_VALUE == aResult.State)
+ {
+ // get property value
+ // (compare to SwXTextPortion::getPropertyValue(s))
+ GetPropertyValue( aResult.Value, *pEntry, pUnoCrsr, pSet );
+ aResult.Result = beans::TolerantPropertySetResultType::SUCCESS;
+ aResultVector.push_back( aResult );
+ }
+ }
+ }
+ catch (beans::UnknownPropertyException &)
+ {
+ // should not occur because property was searched for before
+ OSL_FAIL( "unexpected exception catched" );
+ aResult.Result = beans::TolerantPropertySetResultType::UNKNOWN_PROPERTY;
+ }
+ catch (lang::IllegalArgumentException &)
+ {
+ aResult.Result = beans::TolerantPropertySetResultType::ILLEGAL_ARGUMENT;
+ }
+ catch (beans::PropertyVetoException &)
+ {
+ aResult.Result = beans::TolerantPropertySetResultType::PROPERTY_VETO;
+ }
+ catch (lang::WrappedTargetException &)
+ {
+ aResult.Result = beans::TolerantPropertySetResultType::WRAPPED_TARGET;
+ }
+ }
+ delete pSet;
+
+ uno::Sequence< beans::GetDirectPropertyTolerantResult > aResult( aResultVector.size() );
+ std::vector< beans::GetDirectPropertyTolerantResult >::const_iterator aIt = aResultVector.begin();
+ beans::GetDirectPropertyTolerantResult *pResult = aResult.getArray();
+ for( sal_Int32 nResult = 0; nResult < aResult.getLength(); ++nResult )
+ {
+ pResult[nResult] = *aIt;
+ ++aIt;
+ }
+
+ return aResult;
+}
+
+void SwXTextPortion::addPropertiesChangeListener(
+ const uno::Sequence< OUString >& /*aPropertyNames*/,
+ const uno::Reference< beans::XPropertiesChangeListener >& /*xListener*/ )
+ throw(uno::RuntimeException)
+{}
+
+void SwXTextPortion::removePropertiesChangeListener(
+ const uno::Reference< beans::XPropertiesChangeListener >& /*xListener*/ )
+ throw(uno::RuntimeException)
+{}
+
+void SwXTextPortion::firePropertiesChangeEvent(
+ const uno::Sequence< OUString >& /*aPropertyNames*/,
+ const uno::Reference< beans::XPropertiesChangeListener >& /*xListener*/ )
+ throw(uno::RuntimeException)
+{}
+
+void SwXTextPortion::addPropertyChangeListener(
+ const OUString& /*PropertyName*/,
+ const uno::Reference< beans::XPropertyChangeListener > & /*xListener*/)
+ throw( beans::UnknownPropertyException, lang::WrappedTargetException, uno::RuntimeException )
+{
+ DBG_WARNING("not implemented");
+}
+
+void SwXTextPortion::removePropertyChangeListener(const OUString& /*rPropertyName*/, const uno::Reference< beans::XPropertyChangeListener > & /*aListener*/) throw( beans::UnknownPropertyException, lang::WrappedTargetException, uno::RuntimeException )
+{
+ DBG_WARNING("not implemented");
+}
+
+void SwXTextPortion::addVetoableChangeListener(const OUString& /*rPropertyName*/, const uno::Reference< beans::XVetoableChangeListener > & /*aListener*/) throw( beans::UnknownPropertyException, lang::WrappedTargetException, uno::RuntimeException )
+{
+ DBG_WARNING("not implemented");
+}
+
+void SwXTextPortion::removeVetoableChangeListener(const OUString& /*rPropertyName*/, const uno::Reference< beans::XVetoableChangeListener > & /*aListener*/) throw( beans::UnknownPropertyException, lang::WrappedTargetException, uno::RuntimeException )
+{
+ DBG_WARNING("not implemented");
+}
+
+beans::PropertyState SwXTextPortion::getPropertyState(const OUString& rPropertyName)
+ throw( beans::UnknownPropertyException, uno::RuntimeException )
+{
+ SolarMutexGuard aGuard;
+ beans::PropertyState eRet = beans::PropertyState_DEFAULT_VALUE;
+ SwUnoCrsr* pUnoCrsr = GetCursor();
+ if (!pUnoCrsr)
+ throw uno::RuntimeException();
+
+ if (GetTextPortionType() == PORTION_RUBY_START &&
+ !rPropertyName.compareToAscii( RTL_CONSTASCII_STRINGPARAM("Ruby") ))
+ {
+ eRet = beans::PropertyState_DIRECT_VALUE;
+ }
+ else
+ {
+ eRet = SwUnoCursorHelper::GetPropertyState(*pUnoCrsr, *m_pPropSet,
+ rPropertyName);
+ }
+ return eRet;
+}
+
+uno::Sequence< beans::PropertyState > SwXTextPortion::getPropertyStates(
+ const uno::Sequence< OUString >& rPropertyNames)
+ throw( beans::UnknownPropertyException, uno::RuntimeException )
+{
+ SolarMutexGuard aGuard;
+ SwUnoCrsr* pUnoCrsr = GetCursor();
+ if(!pUnoCrsr)
+ throw uno::RuntimeException();
+
+ uno::Sequence< beans::PropertyState > aRet =
+ SwUnoCursorHelper::GetPropertyStates(*pUnoCrsr, *m_pPropSet,
+ rPropertyNames, SW_PROPERTY_STATE_CALLER_SWX_TEXT_PORTION);
+
+ if(GetTextPortionType() == PORTION_RUBY_START)
+ {
+ const OUString* pNames = rPropertyNames.getConstArray();
+ beans::PropertyState* pStates = aRet.getArray();
+ for(sal_Int32 nProp = 0; nProp < rPropertyNames.getLength();nProp++)
+ {
+ if(!pNames[nProp].compareToAscii( RTL_CONSTASCII_STRINGPARAM("Ruby") ))
+ pStates[nProp] = beans::PropertyState_DIRECT_VALUE;
+ }
+ }
+ return aRet;
+}
+
+void SwXTextPortion::setPropertyToDefault(const OUString& rPropertyName)
+ throw( beans::UnknownPropertyException, uno::RuntimeException )
+{
+ SolarMutexGuard aGuard;
+ SwUnoCrsr* pUnoCrsr = GetCursor();
+ if (!pUnoCrsr)
+ throw uno::RuntimeException();
+
+ SwUnoCursorHelper::SetPropertyToDefault(
+ *pUnoCrsr, *m_pPropSet, rPropertyName);
+}
+
+uno::Any SwXTextPortion::getPropertyDefault(const OUString& rPropertyName)
+ throw( beans::UnknownPropertyException, lang::WrappedTargetException, uno::RuntimeException )
+{
+ SolarMutexGuard aGuard;
+ uno::Any aRet;
+ SwUnoCrsr* pUnoCrsr = GetCursor();
+ if (!pUnoCrsr)
+ throw uno::RuntimeException();
+
+ aRet = SwUnoCursorHelper::GetPropertyDefault(*pUnoCrsr, *m_pPropSet,
+ rPropertyName);
+ return aRet;
+}
+
+void SwXTextPortion::attach(const uno::Reference< text::XTextRange > & /*xTextRange*/)
+ throw( lang::IllegalArgumentException, uno::RuntimeException )
+{
+ SolarMutexGuard aGuard;
+ // SwXTextPortion cannot be created at the factory therefore
+ // they cannot be attached
+ throw uno::RuntimeException();
+}
+
+uno::Reference< text::XTextRange > SwXTextPortion::getAnchor()
+throw( uno::RuntimeException )
+{
+ SolarMutexGuard aGuard;
+ uno::Reference< text::XTextRange > aRet;
+ SwUnoCrsr* pUnoCrsr = GetCursor();
+ if (!pUnoCrsr)
+ throw uno::RuntimeException();
+
+ aRet = new SwXTextRange(*pUnoCrsr, m_xParentText);
+ return aRet;
+}
+
+void SwXTextPortion::dispose()
+throw( uno::RuntimeException )
+{
+ SolarMutexGuard aGuard;
+ SwUnoCrsr* pUnoCrsr = GetCursor();
+ if (!pUnoCrsr)
+ throw uno::RuntimeException();
+
+ setString(aEmptyStr);
+ pUnoCrsr->Remove(this);
+}
+
+void SwXTextPortion::addEventListener(const uno::Reference< lang::XEventListener > & aListener) throw( uno::RuntimeException )
+{
+ SolarMutexGuard aGuard;
+ if(!GetRegisteredIn())
+ throw uno::RuntimeException();
+
+ m_ListenerContainer.AddListener(aListener);
+}
+
+void SwXTextPortion::removeEventListener(const uno::Reference< lang::XEventListener > & aListener) throw( uno::RuntimeException )
+{
+ SolarMutexGuard aGuard;
+ if (!GetRegisteredIn() || !m_ListenerContainer.RemoveListener(aListener))
+ throw uno::RuntimeException();
+}
+
+uno::Reference< container::XEnumeration > SwXTextPortion::createContentEnumeration(const OUString& /*aServiceName*/)
+ throw( uno::RuntimeException )
+{
+ SolarMutexGuard aGuard;
+ SwUnoCrsr* pUnoCrsr = GetCursor();
+ if(!pUnoCrsr)
+ throw uno::RuntimeException();
+
+ uno::Reference< container::XEnumeration > xRet =
+ new SwXParaFrameEnumeration(*pUnoCrsr, PARAFRAME_PORTION_CHAR,
+ m_pFrameFmt);
+ return xRet;
+
+}
+
+const uno::Sequence< sal_Int8 > & SwXTextPortion::getUnoTunnelId()
+{
+ static uno::Sequence< sal_Int8 > aSeq = ::CreateUnoTunnelId();
+ return aSeq;
+}
+
+sal_Int64 SwXTextPortion::getSomething( const uno::Sequence< sal_Int8 >& rId )
+ throw(uno::RuntimeException)
+{
+ if( rId.getLength() == 16
+ && 0 == rtl_compareMemory( getUnoTunnelId().getConstArray(),
+ rId.getConstArray(), 16 ) )
+ {
+ return sal::static_int_cast< sal_Int64 >( reinterpret_cast< sal_IntPtr >(this) );
+ }
+ return 0;
+}
+
+uno::Sequence< OUString > SwXTextPortion::getAvailableServiceNames()
+throw( uno::RuntimeException )
+{
+ SolarMutexGuard aGuard;
+ uno::Sequence< OUString > aRet(1);
+ OUString* pArray = aRet.getArray();
+ pArray[0] = C2U("com.sun.star.text.TextContent");
+ return aRet;
+}
+
+OUString SwXTextPortion::getImplementationName()
+throw( uno::RuntimeException )
+{
+ return C2U("SwXTextPortion");
+}
+
+sal_Bool SwXTextPortion::supportsService(const OUString& rServiceName) throw( uno::RuntimeException )
+{
+ SolarMutexGuard aGuard;
+ SwUnoCrsr* pUnoCrsr = GetCursor();
+ if(!pUnoCrsr)
+ throw uno::RuntimeException();
+
+ sal_Bool bRet = sal_False;
+ if(!rServiceName.compareToAscii("com.sun.star.text.TextPortion") ||
+ !rServiceName.compareToAscii("com.sun.star.style.CharacterProperties") ||
+ !rServiceName.compareToAscii("com.sun.star.style.CharacterPropertiesAsian") ||
+ !rServiceName.compareToAscii("com.sun.star.style.CharacterPropertiesComplex") ||
+ !rServiceName.compareToAscii("com.sun.star.style.ParagraphProperties") ||
+ !rServiceName.compareToAscii("com.sun.star.style.ParagraphPropertiesAsian") ||
+ !rServiceName.compareToAscii("com.sun.star.style.ParagraphPropertiesComplex"))
+ {
+ bRet = sal_True;
+ }
+
+ return bRet;
+}
+
+uno::Sequence< OUString > SwXTextPortion::getSupportedServiceNames()
+throw( uno::RuntimeException )
+{
+ SolarMutexGuard aGuard;
+ SwUnoCrsr* pUnoCrsr = GetCursor();
+ if (!pUnoCrsr)
+ throw uno::RuntimeException();
+
+ uno::Sequence< OUString > aRet(7);
+ OUString* pArray = aRet.getArray();
+ pArray[0] = C2U("com.sun.star.text.TextPortion");
+ pArray[1] = C2U("com.sun.star.style.CharacterProperties");
+ pArray[2] = C2U("com.sun.star.style.CharacterPropertiesAsian");
+ pArray[3] = C2U("com.sun.star.style.CharacterPropertiesComplex");
+ pArray[4] = C2U("com.sun.star.style.ParagraphProperties");
+ pArray[5] = C2U("com.sun.star.style.ParagraphPropertiesAsian");
+ pArray[6] = C2U("com.sun.star.style.ParagraphPropertiesComplex");
+ return aRet;
+}
+
+void SwXTextPortion::Modify( const SfxPoolItem* pOld, const SfxPoolItem *pNew)
+{
+ ClientModify(this, pOld, pNew);
+ if (!m_FrameDepend.GetRegisteredIn())
+ {
+ m_pFrameFmt = 0;
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/unocore/unoportenum.cxx b/sw/source/core/unocore/unoportenum.cxx
new file mode 100644
index 000000000000..04bbd54c893b
--- /dev/null
+++ b/sw/source/core/unocore/unoportenum.cxx
@@ -0,0 +1,1175 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+
+#include <unoport.hxx>
+#include <IMark.hxx>
+// --> OD 2007-10-23 #i81002#
+#include <crossrefbookmark.hxx>
+// <--
+#include <doc.hxx>
+#include <txatbase.hxx>
+#include <txtatr.hxx>
+#include <ndhints.hxx>
+#include <ndtxt.hxx>
+#include <unocrsr.hxx>
+#include <docary.hxx>
+#include <tox.hxx>
+#include <unomid.h>
+#include <unoparaframeenum.hxx>
+#include <unocrsrhelper.hxx>
+#include <unorefmark.hxx>
+#include <unobookmark.hxx>
+#include <unoredline.hxx>
+#include <unofield.hxx>
+#include <unometa.hxx>
+#include <fmtmeta.hxx>
+#include <fmtanchr.hxx>
+#include <fmtrfmrk.hxx>
+#include <frmfmt.hxx>
+#include <unoidx.hxx>
+#include <redline.hxx>
+#include <crsskip.hxx>
+#include <osl/mutex.hxx>
+#include <vcl/svapp.hxx>
+#include <set>
+
+#include <boost/shared_ptr.hpp>
+#include <boost/bind.hpp>
+#include <algorithm>
+#include <stack>
+
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::text;
+using ::rtl::OUString;
+using namespace ::std;
+
+typedef ::std::pair< TextRangeList_t * const, SwTxtAttr const * const > PortionList_t;
+typedef ::std::stack< PortionList_t > PortionStack_t;
+
+static void lcl_CreatePortions(
+ TextRangeList_t & i_rPortions,
+ uno::Reference< text::XText > const& i_xParentText,
+ SwUnoCrsr* pUnoCrsr,
+ FrameDependSortList_t & i_rFrames,
+ const sal_Int32 i_nStartPos, const sal_Int32 i_nEndPos );
+
+namespace
+{
+ static const sal_uInt8 BKM_TYPE_START = 0;
+ static const sal_uInt8 BKM_TYPE_END = 1;
+ static const sal_uInt8 BKM_TYPE_START_END = 2;
+
+ struct SwXBookmarkPortion_Impl
+ {
+ Reference<XTextContent> xBookmark;
+ sal_uInt8 nBkmType;
+ const SwPosition aPosition;
+
+ SwXBookmarkPortion_Impl(uno::Reference<text::XTextContent> const& xMark,
+ const sal_uInt8 nType, SwPosition const& rPosition)
+ : xBookmark ( xMark )
+ , nBkmType ( nType )
+ , aPosition ( rPosition )
+ {
+ }
+ sal_uLong getIndex ()
+ {
+ return aPosition.nContent.GetIndex();
+ }
+ };
+ typedef boost::shared_ptr < SwXBookmarkPortion_Impl > SwXBookmarkPortion_ImplSharedPtr;
+ struct BookmarkCompareStruct
+ {
+ bool operator () ( const SwXBookmarkPortion_ImplSharedPtr &r1,
+ const SwXBookmarkPortion_ImplSharedPtr &r2 ) const
+ {
+ // #i16896# for bookmark portions at the same position, the start should
+ // always precede the end. Hence compare positions, and use bookmark type
+ // as tie-breaker for same position.
+ // return ( r1->nIndex == r2->nIndex )
+ // ? ( r1->nBkmType < r2->nBkmType )
+ // : ( r1->nIndex < r2->nIndex );
+
+ // MTG: 25/11/05: Note that the above code does not correctly handle
+ // the case when one bookmark ends, and another begins in the same
+ // position. When this occurs, the above code will return the
+ // the start of the 2nd bookmark BEFORE the end of the first bookmark
+ // See bug #i58438# for more details. The below code is correct and
+ // fixes both #i58438 and #i16896#
+ return r1->aPosition < r2->aPosition;
+ }
+ };
+ typedef std::multiset < SwXBookmarkPortion_ImplSharedPtr, BookmarkCompareStruct > SwXBookmarkPortion_ImplList;
+
+
+ static void lcl_FillBookmarkArray(SwDoc& rDoc, SwUnoCrsr& rUnoCrsr, SwXBookmarkPortion_ImplList& rBkmArr)
+ {
+ IDocumentMarkAccess* const pMarkAccess = rDoc.getIDocumentMarkAccess();
+ if(!pMarkAccess->getBookmarksCount())
+ return;
+
+ // no need to consider marks starting after aEndOfPara
+ SwPosition aEndOfPara(*rUnoCrsr.GetPoint());
+ aEndOfPara.nContent = aEndOfPara.nNode.GetNode().GetTxtNode()->Len();
+ const IDocumentMarkAccess::const_iterator_t pCandidatesEnd = upper_bound(
+ pMarkAccess->getBookmarksBegin(),
+ pMarkAccess->getBookmarksEnd(),
+ aEndOfPara,
+ bind(&::sw::mark::IMark::StartsAfter, _2, _1)); // finds the first that starts after
+
+ // search for all bookmarks that start or end in this paragraph
+ const SwNodeIndex nOwnNode = rUnoCrsr.GetPoint()->nNode;
+ for(IDocumentMarkAccess::const_iterator_t ppMark = pMarkAccess->getBookmarksBegin();
+ ppMark != pCandidatesEnd;
+ ++ppMark)
+ {
+ ::sw::mark::IMark* const pBkmk = ppMark->get();
+ bool hasOther = pBkmk->IsExpanded();
+
+ const SwPosition& rStartPos = pBkmk->GetMarkStart();
+ if(rStartPos.nNode == nOwnNode)
+ {
+ const sal_uInt8 nType = hasOther ? BKM_TYPE_START : BKM_TYPE_START_END;
+ rBkmArr.insert(SwXBookmarkPortion_ImplSharedPtr(
+ new SwXBookmarkPortion_Impl(
+ SwXBookmark::CreateXBookmark(rDoc, *pBkmk),
+ nType, rStartPos)));
+ }
+
+ const SwPosition& rEndPos = pBkmk->GetMarkEnd();
+ if(rEndPos.nNode == nOwnNode)
+ {
+ auto_ptr<SwPosition> pCrossRefEndPos;
+ const SwPosition* pEndPos = NULL;
+ if(hasOther)
+ pEndPos = &rEndPos;
+ else if(dynamic_cast< ::sw::mark::CrossRefBookmark*>(pBkmk))
+ {
+ // Crossrefbookmarks only remember the start position but have to span the whole paragraph
+ pCrossRefEndPos = auto_ptr<SwPosition>(new SwPosition(rEndPos));
+ pCrossRefEndPos->nContent = pCrossRefEndPos->nNode.GetNode().GetTxtNode()->Len();
+ pEndPos = pCrossRefEndPos.get();
+ }
+ if(pEndPos)
+ {
+ rBkmArr.insert(SwXBookmarkPortion_ImplSharedPtr(
+ new SwXBookmarkPortion_Impl(
+ SwXBookmark::CreateXBookmark(rDoc, *pBkmk),
+ BKM_TYPE_END, *pEndPos)));
+ }
+ }
+ }
+ }
+}
+
+/******************************************************************
+ * SwXTextPortionEnumeration
+ ******************************************************************/
+const uno::Sequence< sal_Int8 > & SwXTextPortionEnumeration::getUnoTunnelId()
+{
+ static uno::Sequence< sal_Int8 > aSeq = ::CreateUnoTunnelId();
+ return aSeq;
+}
+
+sal_Int64 SAL_CALL SwXTextPortionEnumeration::getSomething(
+ const uno::Sequence< sal_Int8 >& rId )
+throw(uno::RuntimeException)
+{
+ if( rId.getLength() == 16
+ && 0 == rtl_compareMemory( getUnoTunnelId().getConstArray(),
+ rId.getConstArray(), 16 ) )
+ {
+ return sal::static_int_cast< sal_Int64 >( reinterpret_cast< sal_IntPtr >( this ) );
+ }
+ return 0;
+}
+
+OUString SwXTextPortionEnumeration::getImplementationName()
+throw( RuntimeException )
+{
+ return C2U("SwXTextPortionEnumeration");
+}
+
+sal_Bool
+SwXTextPortionEnumeration::supportsService(const OUString& rServiceName)
+throw( RuntimeException )
+{
+ return C2U("com.sun.star.text.TextPortionEnumeration") == rServiceName;
+}
+
+Sequence< OUString > SwXTextPortionEnumeration::getSupportedServiceNames()
+throw( RuntimeException )
+{
+ Sequence< OUString > aRet(1);
+ OUString* pArray = aRet.getArray();
+ pArray[0] = C2U("com.sun.star.text.TextPortionEnumeration");
+ return aRet;
+}
+
+SwXTextPortionEnumeration::SwXTextPortionEnumeration(
+ SwPaM& rParaCrsr,
+ uno::Reference< XText > const & xParentText,
+ const sal_Int32 nStart,
+ const sal_Int32 nEnd )
+ : m_Portions()
+{
+ SwUnoCrsr* pUnoCrsr =
+ rParaCrsr.GetDoc()->CreateUnoCrsr(*rParaCrsr.GetPoint(), sal_False);
+ pUnoCrsr->Add(this);
+
+ DBG_ASSERT(nEnd == -1 || (nStart <= nEnd &&
+ nEnd <= pUnoCrsr->Start()->nNode.GetNode().GetTxtNode()->GetTxt().Len()),
+ "start or end value invalid!");
+
+ // find all frames, graphics and OLEs that are bound AT character in para
+ FrameDependSortList_t frames;
+ ::CollectFrameAtNode(*this, pUnoCrsr->GetPoint()->nNode, frames, true);
+ lcl_CreatePortions(m_Portions, xParentText, pUnoCrsr, frames, nStart, nEnd);
+}
+
+SwXTextPortionEnumeration::SwXTextPortionEnumeration(
+ SwPaM& rParaCrsr,
+ TextRangeList_t const & rPortions )
+ : m_Portions( rPortions )
+{
+ SwUnoCrsr* const pUnoCrsr =
+ rParaCrsr.GetDoc()->CreateUnoCrsr(*rParaCrsr.GetPoint(), sal_False);
+ pUnoCrsr->Add(this);
+}
+
+SwXTextPortionEnumeration::~SwXTextPortionEnumeration()
+{
+ SolarMutexGuard aGuard;
+
+ SwUnoCrsr* pUnoCrsr = GetCursor();
+ delete pUnoCrsr;
+}
+
+sal_Bool SwXTextPortionEnumeration::hasMoreElements()
+throw( uno::RuntimeException )
+{
+ SolarMutexGuard aGuard;
+
+ return (m_Portions.size() > 0) ? sal_True : sal_False;
+}
+
+uno::Any SwXTextPortionEnumeration::nextElement()
+throw( container::NoSuchElementException, lang::WrappedTargetException,
+ uno::RuntimeException )
+{
+ SolarMutexGuard aGuard;
+
+ if (!m_Portions.size())
+ throw container::NoSuchElementException();
+
+ Any any;
+ any <<= m_Portions.front();
+ m_Portions.pop_front();
+ return any;
+}
+
+typedef ::std::deque< xub_StrLen > FieldMarks_t;
+
+static void
+lcl_FillFieldMarkArray(FieldMarks_t & rFieldMarks, SwUnoCrsr const & rUnoCrsr,
+ const sal_Int32 i_nStartPos)
+{
+ const SwTxtNode * const pTxtNode =
+ rUnoCrsr.GetPoint()->nNode.GetNode().GetTxtNode();
+ if (!pTxtNode) return;
+
+ const sal_Unicode fld[] = {
+ CH_TXT_ATR_FIELDSTART, CH_TXT_ATR_FIELDEND, CH_TXT_ATR_FORMELEMENT, 0 };
+ xub_StrLen pos = ::std::max(static_cast<const sal_Int32>(0), i_nStartPos);
+ while ((pos = pTxtNode->GetTxt().SearchChar(fld, pos)) != STRING_NOTFOUND)
+ {
+ rFieldMarks.push_back(pos);
+ ++pos;
+ }
+}
+
+static uno::Reference<text::XTextRange>
+lcl_ExportFieldMark(
+ uno::Reference< text::XText > const & i_xParentText,
+ SwUnoCrsr * const pUnoCrsr,
+ const SwTxtNode * const pTxtNode )
+{
+ uno::Reference<text::XTextRange> xRef;
+ SwDoc* pDoc = pUnoCrsr->GetDoc();
+ //flr: maybe its a good idea to add a special hint to the hints array and rely on the hint segmentation....
+ const xub_StrLen start = pUnoCrsr->Start()->nContent.GetIndex();
+ OSL_ENSURE(pUnoCrsr->End()->nContent.GetIndex() == start,
+ "hmm --- why is this different");
+
+ pUnoCrsr->Right(1, CRSR_SKIP_CHARS, sal_False, sal_False);
+ if ( *pUnoCrsr->GetMark() == *pUnoCrsr->GetPoint() )
+ {
+ OSL_FAIL("cannot move cursor?");
+ return 0;
+ }
+
+ const sal_Unicode Char = pTxtNode->GetTxt().GetChar(start);
+ if (CH_TXT_ATR_FIELDSTART == Char)
+ {
+ ::sw::mark::IFieldmark* pFieldmark = NULL;
+ if (pDoc)
+ {
+ pFieldmark = pDoc->getIDocumentMarkAccess()->
+ getFieldmarkFor(*pUnoCrsr->GetMark());
+ }
+ SwXTextPortion* pPortion = new SwXTextPortion(
+ pUnoCrsr, i_xParentText, PORTION_FIELD_START);
+ xRef = pPortion;
+ if (pPortion && pFieldmark && pDoc)
+ pPortion->SetBookmark( SwXFieldmark::CreateXFieldmark( *pDoc, *pFieldmark ) );
+ }
+ else if (CH_TXT_ATR_FIELDEND == Char)
+ {
+ ::sw::mark::IFieldmark* pFieldmark = NULL;
+ if (pDoc)
+ {
+ pFieldmark = pDoc->getIDocumentMarkAccess()->
+ getFieldmarkFor(*pUnoCrsr->GetMark());
+ }
+ SwXTextPortion* pPortion = new SwXTextPortion(
+ pUnoCrsr, i_xParentText, PORTION_FIELD_END);
+ xRef = pPortion;
+ if (pPortion && pFieldmark && pDoc)
+ pPortion->SetBookmark( SwXFieldmark::CreateXFieldmark( *pDoc, *pFieldmark ) );
+ }
+ else if (CH_TXT_ATR_FORMELEMENT == Char)
+ {
+ ::sw::mark::IFieldmark* pFieldmark = NULL;
+ if (pDoc)
+ {
+ pFieldmark = pDoc->getIDocumentMarkAccess()->
+ getFieldmarkFor(*pUnoCrsr->GetMark());
+ }
+ SwXTextPortion* pPortion = new SwXTextPortion(
+ pUnoCrsr, i_xParentText, PORTION_FIELD_START_END);
+ xRef = pPortion;
+ if (pPortion && pFieldmark && pDoc)
+ pPortion->SetBookmark( SwXFieldmark::CreateXFieldmark( *pDoc, *pFieldmark ) );
+ }
+ else
+ {
+ OSL_FAIL("no fieldmark found?");
+ }
+ return xRef;
+}
+
+static Reference<XTextRange>
+lcl_CreateRefMarkPortion(
+ Reference<XText> const& xParent,
+ const SwUnoCrsr * const pUnoCrsr,
+ const SwTxtAttr & rAttr, const bool bEnd)
+{
+ SwDoc* pDoc = pUnoCrsr->GetDoc();
+ const SwFmtRefMark& rRefMark =
+ static_cast<const SwFmtRefMark&>(rAttr.GetAttr());
+ Reference<XTextContent> xContent;
+ if (!xContent.is())
+ {
+ xContent = new SwXReferenceMark(pDoc, &rRefMark);
+ }
+
+ SwXTextPortion* pPortion = 0;
+ if (!bEnd)
+ {
+ pPortion = new SwXTextPortion(pUnoCrsr, xParent, PORTION_REFMARK_START);
+ pPortion->SetRefMark(xContent);
+ pPortion->SetCollapsed(rAttr.GetEnd() ? false : true);
+ }
+ else
+ {
+ pPortion = new SwXTextPortion(pUnoCrsr, xParent, PORTION_REFMARK_END);
+ pPortion->SetRefMark(xContent);
+ }
+ return pPortion;
+}
+
+static void
+lcl_InsertRubyPortion(
+ TextRangeList_t & rPortions,
+ Reference<XText> const& xParent,
+ const SwUnoCrsr * const pUnoCrsr,
+ const SwTxtAttr & rAttr, const sal_Bool bEnd)
+{
+ SwXTextPortion* pPortion = new SwXTextPortion(pUnoCrsr,
+ static_cast<const SwTxtRuby&>(rAttr), xParent, bEnd);
+ rPortions.push_back(pPortion);
+ pPortion->SetCollapsed(rAttr.GetEnd() ? false : true);
+}
+
+static Reference<XTextRange>
+lcl_CreateTOXMarkPortion(
+ Reference<XText> const& xParent,
+ const SwUnoCrsr * const pUnoCrsr,
+ SwTxtAttr & rAttr, const bool bEnd)
+{
+ SwDoc* pDoc = pUnoCrsr->GetDoc();
+ SwTOXMark & rTOXMark = static_cast<SwTOXMark&>(rAttr.GetAttr());
+
+ const Reference<XTextContent> xContent(
+ SwXDocumentIndexMark::CreateXDocumentIndexMark(*pDoc,
+ *const_cast<SwTOXType*>(rTOXMark.GetTOXType()), rTOXMark),
+ uno::UNO_QUERY);
+
+ SwXTextPortion* pPortion = 0;
+ if (!bEnd)
+ {
+ pPortion = new SwXTextPortion(pUnoCrsr, xParent, PORTION_TOXMARK_START);
+ pPortion->SetTOXMark(xContent);
+ pPortion->SetCollapsed(rAttr.GetEnd() ? false : true);
+ }
+ else
+ {
+ pPortion = new SwXTextPortion(pUnoCrsr, xParent, PORTION_TOXMARK_END);
+ pPortion->SetTOXMark(xContent);
+ }
+ return pPortion;
+}
+
+static uno::Reference<text::XTextRange>
+lcl_CreateMetaPortion(
+ uno::Reference<text::XText> const& xParent,
+ const SwUnoCrsr * const pUnoCrsr,
+ SwTxtAttr & rAttr, ::std::auto_ptr<TextRangeList_t const> & pPortions)
+{
+ const uno::Reference<rdf::XMetadatable> xMeta( SwXMeta::CreateXMeta(
+ *static_cast<SwFmtMeta &>(rAttr.GetAttr()).GetMeta(),
+ xParent, pPortions));
+ SwXTextPortion * pPortion(0);
+ if (RES_TXTATR_META == rAttr.Which())
+ {
+ const uno::Reference<text::XTextContent> xContent(xMeta,
+ uno::UNO_QUERY);
+ pPortion = new SwXTextPortion(pUnoCrsr, xParent, PORTION_META);
+ pPortion->SetMeta(xContent);
+ }
+ else
+ {
+ const uno::Reference<text::XTextField> xField(xMeta, uno::UNO_QUERY);
+ pPortion = new SwXTextPortion(pUnoCrsr, xParent, PORTION_FIELD);
+ pPortion->SetTextField(xField);
+ }
+ return pPortion;
+}
+
+static void
+lcl_ExportBookmark(
+ TextRangeList_t & rPortions,
+ Reference<XText> const& xParent,
+ const SwUnoCrsr * const pUnoCrsr,
+ SwXBookmarkPortion_ImplList& rBkmArr, const sal_uLong nIndex)
+{
+ for ( SwXBookmarkPortion_ImplList::iterator aIter = rBkmArr.begin(), aEnd = rBkmArr.end();
+ aIter != aEnd; )
+ {
+ SwXBookmarkPortion_ImplSharedPtr pPtr = (*aIter);
+ if ( nIndex > pPtr->getIndex() )
+ {
+ rBkmArr.erase( aIter++ );
+ continue;
+ }
+ if ( nIndex < pPtr->getIndex() )
+ break;
+
+ SwXTextPortion* pPortion = 0;
+ if ((BKM_TYPE_START == pPtr->nBkmType) ||
+ (BKM_TYPE_START_END == pPtr->nBkmType))
+ {
+ pPortion =
+ new SwXTextPortion(pUnoCrsr, xParent, PORTION_BOOKMARK_START);
+ rPortions.push_back(pPortion);
+ pPortion->SetBookmark(pPtr->xBookmark);
+ pPortion->SetCollapsed( (BKM_TYPE_START_END == pPtr->nBkmType)
+ ? true : false);
+
+ }
+ if (BKM_TYPE_END == pPtr->nBkmType)
+ {
+ pPortion =
+ new SwXTextPortion(pUnoCrsr, xParent, PORTION_BOOKMARK_END);
+ rPortions.push_back(pPortion);
+ pPortion->SetBookmark(pPtr->xBookmark);
+ }
+ rBkmArr.erase( aIter++ );
+ }
+}
+
+static void
+lcl_ExportSoftPageBreak(
+ TextRangeList_t & rPortions,
+ Reference<XText> const& xParent,
+ const SwUnoCrsr * const pUnoCrsr,
+ SwSoftPageBreakList& rBreakArr, const sal_uLong nIndex)
+{
+ for ( SwSoftPageBreakList::iterator aIter = rBreakArr.begin(),
+ aEnd = rBreakArr.end();
+ aIter != aEnd; )
+ {
+ if ( nIndex > *aIter )
+ {
+ rBreakArr.erase( aIter++ );
+ continue;
+ }
+ if ( nIndex < *aIter )
+ break;
+
+ rPortions.push_back(
+ new SwXTextPortion(pUnoCrsr, xParent, PORTION_SOFT_PAGEBREAK) );
+ rBreakArr.erase( aIter++ );
+ }
+}
+
+#define REDLINE_PORTION_START_REMOVE 0//removed redlines are visible
+#define REDLINE_PORTION_END_REMOVE 1//removed redlines are visible
+#define REDLINE_PORTION_REMOVE 2//removed redlines are NOT visible
+#define REDLINE_PORTION_INSERT_START 3
+#define REDLINE_PORTION_INSERT_END 4
+
+struct SwXRedlinePortion_Impl
+{
+ const SwRedline* m_pRedline;
+ const bool m_bStart;
+
+ SwXRedlinePortion_Impl ( const SwRedline* pRed, const bool bIsStart )
+ : m_pRedline(pRed)
+ , m_bStart(bIsStart)
+ {
+ }
+
+ sal_uLong getRealIndex ()
+ {
+ return m_bStart ? m_pRedline->Start()->nContent.GetIndex()
+ : m_pRedline->End() ->nContent.GetIndex();
+ }
+};
+
+typedef boost::shared_ptr < SwXRedlinePortion_Impl >
+ SwXRedlinePortion_ImplSharedPtr;
+
+struct RedlineCompareStruct
+{
+ const SwPosition& getPosition ( const SwXRedlinePortion_ImplSharedPtr &r )
+ {
+ return *(r->m_bStart ? r->m_pRedline->Start() : r->m_pRedline->End());
+ }
+
+ bool operator () ( const SwXRedlinePortion_ImplSharedPtr &r1,
+ const SwXRedlinePortion_ImplSharedPtr &r2 )
+ {
+ return getPosition ( r1 ) < getPosition ( r2 );
+ }
+};
+
+typedef std::multiset < SwXRedlinePortion_ImplSharedPtr, RedlineCompareStruct >
+SwXRedlinePortion_ImplList;
+
+static Reference<XTextRange>
+lcl_ExportHints(
+ PortionStack_t & rPortionStack,
+ const Reference<XText> & xParent,
+ SwUnoCrsr * const pUnoCrsr,
+ SwpHints * const pHints,
+ const sal_Int32 i_nStartPos,
+ const sal_Int32 i_nEndPos,
+ const xub_StrLen nCurrentIndex,
+ const bool bRightMoveForbidden,
+ bool & o_rbCursorMoved,
+ sal_Int32 & o_rNextAttrPosition )
+{
+ // if the attribute has a dummy character, then xRef is set (except META)
+ // otherwise, the portion for the attribute is inserted into rPortions!
+ Reference<XTextRange> xRef;
+ SwDoc* pDoc = pUnoCrsr->GetDoc();
+ //search for special text attributes - first some ends
+ sal_uInt16 nEndIndex = 0;
+ sal_uInt16 nNextEnd = 0;
+ while(nEndIndex < pHints->GetEndCount() &&
+ (!pHints->GetEnd(nEndIndex)->GetEnd() ||
+ nCurrentIndex >= (nNextEnd = (*pHints->GetEnd(nEndIndex)->GetEnd()))))
+ {
+ if(pHints->GetEnd(nEndIndex)->GetEnd())
+ {
+ SwTxtAttr * const pAttr = pHints->GetEnd(nEndIndex);
+ if (nNextEnd == nCurrentIndex)
+ {
+ const sal_uInt16 nWhich( pAttr->Which() );
+ switch (nWhich)
+ {
+ case RES_TXTATR_TOXMARK:
+ {
+ Reference<XTextRange> xTmp = lcl_CreateTOXMarkPortion(
+ xParent, pUnoCrsr, *pAttr, true);
+ rPortionStack.top().first->push_back(xTmp);
+ }
+ break;
+ case RES_TXTATR_REFMARK:
+ {
+ Reference<XTextRange> xTmp = lcl_CreateRefMarkPortion(
+ xParent, pUnoCrsr, *pAttr, true);
+ rPortionStack.top().first->push_back(xTmp);
+ }
+ break;
+ case RES_TXTATR_CJK_RUBY:
+ //#i91534# GetEnd() == 0 mixes the order of ruby start/end
+ if( *pAttr->GetEnd() == *pAttr->GetStart())
+ {
+ lcl_InsertRubyPortion( *rPortionStack.top().first,
+ xParent, pUnoCrsr, *pAttr, sal_False);
+ }
+ lcl_InsertRubyPortion( *rPortionStack.top().first,
+ xParent, pUnoCrsr, *pAttr, sal_True);
+ break;
+ case RES_TXTATR_META:
+ case RES_TXTATR_METAFIELD:
+ {
+ OSL_ENSURE(*pAttr->GetStart() != *pAttr->GetEnd(),
+ "empty meta?");
+ if ((i_nStartPos > 0) &&
+ (*pAttr->GetStart() < i_nStartPos))
+ {
+ // force skip pAttr and rest of attribute ends
+ // at nCurrentIndex
+ // because they are not contained in the meta pAttr
+ // and the meta pAttr itself is outside selection!
+ // (necessary for SwXMeta::createEnumeration)
+ if (*pAttr->GetStart() + 1 == i_nStartPos)
+ {
+ nEndIndex = pHints->GetEndCount() - 1;
+ }
+ break;
+ }
+ PortionList_t Top = rPortionStack.top();
+ if (Top.second != pAttr)
+ {
+ OSL_FAIL("ExportHints: stack error" );
+ }
+ else
+ {
+ ::std::auto_ptr<const TextRangeList_t>
+ pCurrentPortions(Top.first);
+ rPortionStack.pop();
+ const uno::Reference<text::XTextRange> xPortion(
+ lcl_CreateMetaPortion(xParent, pUnoCrsr,
+ *pAttr, pCurrentPortions));
+ rPortionStack.top().first->push_back(xPortion);
+ }
+ }
+ break;
+ }
+ }
+ }
+ nEndIndex++;
+ }
+
+ // then some starts
+ sal_uInt16 nStartIndex = 0;
+ sal_uInt16 nNextStart = 0;
+ while(nStartIndex < pHints->GetStartCount() &&
+ nCurrentIndex >= (nNextStart = (*pHints->GetStart(nStartIndex)->GetStart())))
+ {
+ SwTxtAttr * const pAttr = pHints->GetStart(nStartIndex);
+ sal_uInt16 nAttrWhich = pAttr->Which();
+ if (nNextStart == nCurrentIndex)
+ {
+ switch( nAttrWhich )
+ {
+ case RES_TXTATR_FIELD:
+ if(!bRightMoveForbidden)
+ {
+ pUnoCrsr->Right(1,CRSR_SKIP_CHARS,sal_False,sal_False);
+ if( *pUnoCrsr->GetMark() == *pUnoCrsr->GetPoint() )
+ break;
+ SwXTextPortion* pPortion;
+ xRef = pPortion = new SwXTextPortion(
+ pUnoCrsr, xParent, PORTION_FIELD);
+ Reference<XTextField> xField =
+ SwXTextField::CreateSwXTextField(*pDoc, pAttr->GetFld());
+ pPortion->SetTextField(xField);
+ }
+ break;
+ case RES_TXTATR_FLYCNT :
+ if(!bRightMoveForbidden)
+ {
+ pUnoCrsr->Right(1,CRSR_SKIP_CHARS,sal_False,sal_False);
+ if( *pUnoCrsr->GetMark() == *pUnoCrsr->GetPoint() )
+ break; // Robust #i81708 content in covered cells
+ pUnoCrsr->Exchange();
+ xRef = new SwXTextPortion(
+ pUnoCrsr, xParent, PORTION_FRAME);
+ }
+ break;
+ case RES_TXTATR_FTN :
+ {
+ if(!bRightMoveForbidden)
+ {
+ pUnoCrsr->Right(1,CRSR_SKIP_CHARS,sal_False,sal_False);
+ if( *pUnoCrsr->GetMark() == *pUnoCrsr->GetPoint() )
+ break;
+ SwXTextPortion* pPortion;
+ xRef = pPortion = new SwXTextPortion(
+ pUnoCrsr, xParent, PORTION_FOOTNOTE);
+ Reference<XFootnote> xContent =
+ SwXFootnotes::GetObject(*pDoc, pAttr->GetFtn());
+ pPortion->SetFootnote(xContent);
+ }
+ }
+ break;
+ case RES_TXTATR_TOXMARK:
+ case RES_TXTATR_REFMARK:
+ {
+ bool bIsPoint = !(pAttr->GetEnd());
+ if (!bRightMoveForbidden || !bIsPoint)
+ {
+ if (bIsPoint)
+ {
+ pUnoCrsr->Right(1,CRSR_SKIP_CHARS,sal_False,sal_False);
+ }
+ Reference<XTextRange> xTmp =
+ (RES_TXTATR_REFMARK == nAttrWhich)
+ ? lcl_CreateRefMarkPortion(
+ xParent, pUnoCrsr, *pAttr, false)
+ : lcl_CreateTOXMarkPortion(
+ xParent, pUnoCrsr, *pAttr, false);
+ if (bIsPoint) // consume CH_TXTATR!
+ {
+ pUnoCrsr->Normalize(sal_False);
+ pUnoCrsr->DeleteMark();
+ xRef = xTmp;
+ }
+ else // just insert it
+ {
+ rPortionStack.top().first->push_back(xTmp);
+ }
+ }
+ }
+ break;
+ case RES_TXTATR_CJK_RUBY:
+ //#i91534# GetEnd() == 0 mixes the order of ruby start/end
+ if(pAttr->GetEnd() && (*pAttr->GetEnd() != *pAttr->GetStart()))
+ {
+ lcl_InsertRubyPortion( *rPortionStack.top().first,
+ xParent, pUnoCrsr, *pAttr, sal_False);
+ }
+ break;
+ case RES_TXTATR_META:
+ case RES_TXTATR_METAFIELD:
+ if (*pAttr->GetStart() != *pAttr->GetEnd())
+ {
+ if (!bRightMoveForbidden)
+ {
+ pUnoCrsr->Right(1,CRSR_SKIP_CHARS,sal_False,sal_False);
+ o_rbCursorMoved = true;
+ // only if the end is included in selection!
+ if ((i_nEndPos < 0) ||
+ (*pAttr->GetEnd() <= i_nEndPos))
+ {
+ rPortionStack.push( ::std::make_pair(
+ new TextRangeList_t, pAttr ));
+ }
+ }
+ }
+ break;
+ case RES_TXTATR_AUTOFMT:
+ case RES_TXTATR_INETFMT:
+ case RES_TXTATR_CHARFMT:
+ break; // these are handled as properties of a "Text" portion
+ default:
+ OSL_FAIL("unknown attribute");
+ break;
+ }
+ }
+ nStartIndex++;
+ }
+
+ if (xRef.is()) // implies that we have moved the cursor
+ {
+ o_rbCursorMoved = true;
+ }
+ if (!o_rbCursorMoved)
+ {
+ // search for attribute changes behind the current cursor position
+ // break up at frames, bookmarks, redlines
+
+ nStartIndex = 0;
+ nNextStart = 0;
+ while(nStartIndex < pHints->GetStartCount() &&
+ nCurrentIndex >= (nNextStart = (*pHints->GetStart(nStartIndex)->GetStart())))
+ nStartIndex++;
+
+ nEndIndex = 0;
+ nNextEnd = 0;
+ while(nEndIndex < pHints->GetEndCount() &&
+ nCurrentIndex >= (nNextEnd = (*pHints->GetEnd(nEndIndex)->GetAnyEnd())))
+ nEndIndex++;
+
+ sal_Int32 nNextPos =
+ ((nNextStart > nCurrentIndex) && (nNextStart < nNextEnd))
+ ? nNextStart : nNextEnd;
+ if (nNextPos > nCurrentIndex)
+ {
+ o_rNextAttrPosition = nNextPos;
+ }
+ }
+ return xRef;
+}
+
+void lcl_MoveCursor( SwUnoCrsr * const pUnoCrsr,
+ const xub_StrLen nCurrentIndex,
+ const sal_Int32 nNextFrameIndex, const sal_Int32 nNextPortionIndex,
+ const sal_Int32 nNextAttrIndex, const sal_Int32 nNextFieldMarkIndex,
+ const sal_Int32 nEndPos )
+{
+ sal_Int32 nMovePos = pUnoCrsr->GetCntntNode()->Len();
+
+ if ((nEndPos >= 0) && (nEndPos < nMovePos))
+ {
+ nMovePos = nEndPos;
+ }
+
+ if ((nNextFrameIndex >= 0) && (nNextFrameIndex < nMovePos))
+ {
+ nMovePos = nNextFrameIndex;
+ }
+
+ if ((nNextPortionIndex >= 0) && (nNextPortionIndex < nMovePos))
+ {
+ nMovePos = nNextPortionIndex;
+ }
+
+ if ((nNextAttrIndex >= 0) && (nNextAttrIndex < nMovePos))
+ {
+ nMovePos = nNextAttrIndex;
+ }
+
+ if ((nNextFieldMarkIndex >= 0) && (nNextFieldMarkIndex < nMovePos))
+ {
+ nMovePos = nNextFieldMarkIndex;
+ }
+
+ if (nMovePos > nCurrentIndex)
+ {
+// pUnoCrsr->Right(nMovePos - nCurrentIndex);
+ pUnoCrsr->GetPoint()->nContent = static_cast<sal_uInt16>(nMovePos);
+ }
+}
+
+static void
+lcl_FillRedlineArray(SwDoc const & rDoc, SwUnoCrsr const & rUnoCrsr,
+ SwXRedlinePortion_ImplList& rRedArr )
+{
+ const SwRedlineTbl& rRedTbl = rDoc.GetRedlineTbl();
+ sal_uInt16 nRedTblCount = rRedTbl.Count();
+
+ if ( nRedTblCount > 0 )
+ {
+ const SwPosition* pStart = rUnoCrsr.GetPoint();
+ const SwNodeIndex nOwnNode = pStart->nNode;
+
+ for(sal_uInt16 nRed = 0; nRed < nRedTblCount; nRed++)
+ {
+ const SwRedline* pRedline = rRedTbl[nRed];
+ const SwPosition* pRedStart = pRedline->Start();
+ const SwNodeIndex nRedNode = pRedStart->nNode;
+ if ( nOwnNode == nRedNode )
+ rRedArr.insert( SwXRedlinePortion_ImplSharedPtr (
+ new SwXRedlinePortion_Impl ( pRedline, true ) ) );
+ if( pRedline->HasMark() && pRedline->End()->nNode == nOwnNode )
+ rRedArr.insert( SwXRedlinePortion_ImplSharedPtr (
+ new SwXRedlinePortion_Impl ( pRedline, false) ) );
+ }
+ }
+}
+
+static void
+lcl_FillSoftPageBreakArray(
+ SwUnoCrsr const & rUnoCrsr, SwSoftPageBreakList& rBreakArr )
+{
+ const SwTxtNode *pTxtNode =
+ rUnoCrsr.GetPoint()->nNode.GetNode().GetTxtNode();
+ if( pTxtNode )
+ pTxtNode->fillSoftPageBreakList( rBreakArr );
+}
+
+static void
+lcl_ExportRedline(
+ TextRangeList_t & rPortions,
+ Reference<XText> const& xParent,
+ const SwUnoCrsr * const pUnoCrsr,
+ SwXRedlinePortion_ImplList& rRedlineArr, const sal_uLong nIndex)
+{
+
+ // MTG: 23/11/05: We want this loop to iterate over all red lines in this
+ // array. We will only insert the ones with index matches
+ for ( SwXRedlinePortion_ImplList::iterator aIter = rRedlineArr.begin(), aEnd = rRedlineArr.end();
+ aIter != aEnd; )
+ {
+ SwXRedlinePortion_ImplSharedPtr pPtr = (*aIter );
+ sal_uLong nRealIndex = pPtr->getRealIndex();
+ // MTG: 23/11/05: If there are elements before nIndex, remove them
+ if ( nIndex > nRealIndex )
+ rRedlineArr.erase ( aIter++ );
+ // MTG: 23/11/05: If the elements match, and them to the list
+ else if ( nIndex == nRealIndex )
+ {
+ rPortions.push_back( new SwXRedlinePortion(
+ pPtr->m_pRedline, pUnoCrsr, xParent, pPtr->m_bStart) );
+ rRedlineArr.erase ( aIter++ );
+ }
+ // MTG: 23/11/05: If we've iterated past nIndex, exit the loop
+ else
+ break;
+ }
+}
+
+static void
+lcl_ExportBkmAndRedline(
+ TextRangeList_t & rPortions,
+ Reference<XText> const & xParent,
+ const SwUnoCrsr * const pUnoCrsr,
+ SwXBookmarkPortion_ImplList& rBkmArr,
+ SwXRedlinePortion_ImplList& rRedlineArr,
+ SwSoftPageBreakList& rBreakArr,
+ const sal_uLong nIndex)
+{
+ if (rBkmArr.size())
+ lcl_ExportBookmark(rPortions, xParent, pUnoCrsr, rBkmArr, nIndex);
+
+ if (rRedlineArr.size())
+ lcl_ExportRedline(rPortions, xParent, pUnoCrsr, rRedlineArr, nIndex);
+
+ if (rBreakArr.size())
+ lcl_ExportSoftPageBreak(rPortions, xParent, pUnoCrsr, rBreakArr, nIndex);
+}
+
+static sal_Int32
+lcl_ExportFrames(
+ TextRangeList_t & rPortions,
+ Reference<XText> const & i_xParent,
+ SwUnoCrsr * const i_pUnoCrsr,
+ FrameDependSortList_t & i_rFrames,
+ xub_StrLen const i_nCurrentIndex)
+{
+ // find first Frame in (sorted) i_rFrames at current position
+ while (i_rFrames.size() && (i_rFrames.front().nIndex == i_nCurrentIndex))
+ // do not check for i_nEnd here; this is done implicity by lcl_MoveCursor
+ {
+ const SwModify * const pFrame =
+ i_rFrames.front().pFrameDepend->GetRegisteredIn();
+ if (pFrame) // Frame could be disposed
+ {
+ SwXTextPortion* pPortion = new SwXTextPortion(i_pUnoCrsr, i_xParent,
+ *static_cast<SwFrmFmt*>( const_cast<SwModify*>( pFrame ) ) );
+ rPortions.push_back(pPortion);
+ }
+ i_rFrames.pop_front();
+ }
+
+ return i_rFrames.size() ? i_rFrames.front().nIndex : -1;
+}
+
+static sal_Int32
+lcl_GetNextIndex(
+ SwXBookmarkPortion_ImplList const & rBkmArr,
+ SwXRedlinePortion_ImplList const & rRedlineArr,
+ SwSoftPageBreakList const & rBreakArr )
+{
+ sal_Int32 nRet = -1;
+ if(rBkmArr.size())
+ {
+ SwXBookmarkPortion_ImplSharedPtr pPtr = (*rBkmArr.begin());
+ nRet = pPtr->getIndex();
+ }
+ if(rRedlineArr.size())
+ {
+ SwXRedlinePortion_ImplSharedPtr pPtr = (*rRedlineArr.begin());
+ sal_Int32 nTmp = pPtr->getRealIndex();
+ if(nRet < 0 || nTmp < nRet)
+ nRet = nTmp;
+ }
+ if(rBreakArr.size())
+ {
+ if(nRet < 0 || *rBreakArr.begin() < static_cast<sal_uInt32>(nRet))
+ nRet = *rBreakArr.begin();
+ }
+ return nRet;
+};
+
+static void
+lcl_CreatePortions(
+ TextRangeList_t & i_rPortions,
+ uno::Reference< text::XText > const & i_xParentText,
+ SwUnoCrsr * const pUnoCrsr,
+ FrameDependSortList_t & i_rFrames,
+ const sal_Int32 i_nStartPos,
+ const sal_Int32 i_nEndPos )
+{
+ if (!pUnoCrsr)
+ return;
+
+ // set the start if a selection should be exported
+ if ((i_nStartPos > 0) &&
+ (pUnoCrsr->Start()->nContent.GetIndex() != i_nStartPos))
+ {
+ pUnoCrsr->DeleteMark();
+ DBG_ASSERT(pUnoCrsr->Start()->nNode.GetNode().GetTxtNode() &&
+ (i_nStartPos <= pUnoCrsr->Start()->nNode.GetNode().GetTxtNode()->
+ GetTxt().Len()), "Incorrect start position" );
+ // ??? should this be i_nStartPos - current position ?
+ pUnoCrsr->Right(static_cast<xub_StrLen>(i_nStartPos),
+ CRSR_SKIP_CHARS, sal_False, sal_False);
+ }
+
+ FieldMarks_t FieldMarks;
+ SwXBookmarkPortion_ImplList Bookmarks;
+ SwXRedlinePortion_ImplList Redlines;
+ SwSoftPageBreakList SoftPageBreaks;
+
+ SwDoc * const pDoc = pUnoCrsr->GetDoc();
+ lcl_FillFieldMarkArray(FieldMarks, *pUnoCrsr, i_nStartPos);
+ lcl_FillBookmarkArray(*pDoc, *pUnoCrsr, Bookmarks);
+ lcl_FillRedlineArray(*pDoc, *pUnoCrsr, Redlines);
+ lcl_FillSoftPageBreakArray(*pUnoCrsr, SoftPageBreaks);
+
+ PortionStack_t PortionStack;
+ PortionStack.push( PortionList_t(&i_rPortions, 0) );
+
+ bool bAtEnd( false );
+ while (!bAtEnd) // every iteration consumes at least current character!
+ {
+ if (pUnoCrsr->HasMark())
+ {
+ pUnoCrsr->Normalize(sal_False);
+ pUnoCrsr->DeleteMark();
+ }
+
+ SwTxtNode * const pTxtNode = pUnoCrsr->GetNode()->GetTxtNode();
+ if (!pTxtNode)
+ {
+ OSL_FAIL("lcl_CreatePortions: no TextNode - what now ?");
+ return;
+ }
+
+ SwpHints * const pHints = pTxtNode->GetpSwpHints();
+ const xub_StrLen nCurrentIndex =
+ pUnoCrsr->GetPoint()->nContent.GetIndex();
+ // this contains the portion which consumes the character in the
+ // text at nCurrentIndex; i.e. it must be set _once_ per iteration
+ uno::Reference< XTextRange > xRef;
+
+ SwUnoCursorHelper::SelectPam(*pUnoCrsr, true); // set mark
+
+ const sal_Int32 nFirstFrameIndex =
+ lcl_ExportFrames( *PortionStack.top().first,
+ i_xParentText, pUnoCrsr, i_rFrames, nCurrentIndex);
+
+ lcl_ExportBkmAndRedline( *PortionStack.top().first, i_xParentText,
+ pUnoCrsr, Bookmarks, Redlines, SoftPageBreaks, nCurrentIndex );
+
+ bool bCursorMoved( false );
+ sal_Int32 nNextAttrIndex = -1;
+ // #111716# the cursor must not move right at the
+ // end position of a selection!
+ bAtEnd = ((i_nEndPos >= 0) && (nCurrentIndex >= i_nEndPos))
+ || (nCurrentIndex >= pTxtNode->Len());
+ if (pHints)
+ {
+ // N.B.: side-effects nNextAttrIndex, bCursorMoved; may move cursor
+ xRef = lcl_ExportHints(PortionStack, i_xParentText, pUnoCrsr,
+ pHints, i_nStartPos, i_nEndPos, nCurrentIndex, bAtEnd,
+ bCursorMoved, nNextAttrIndex);
+ if (PortionStack.empty())
+ {
+ OSL_FAIL("CreatePortions: stack underflow");
+ return;
+ }
+ }
+
+ if (!xRef.is() && !bCursorMoved)
+ {
+ if (!bAtEnd &&
+ FieldMarks.size() && (FieldMarks.front() == nCurrentIndex))
+ {
+ // moves cursor
+ xRef = lcl_ExportFieldMark(i_xParentText, pUnoCrsr, pTxtNode);
+ FieldMarks.pop_front();
+ }
+ }
+ else
+ {
+ OSL_ENSURE(!FieldMarks.size() ||
+ (FieldMarks.front() != nCurrentIndex),
+ "fieldmark and hint with CH_TXTATR at same pos?");
+ }
+
+ if (!bAtEnd && !xRef.is() && !bCursorMoved)
+ {
+ const sal_Int32 nNextPortionIndex =
+ lcl_GetNextIndex(Bookmarks, Redlines, SoftPageBreaks);
+ const sal_Int32 nNextFieldMarkIndex(
+ FieldMarks.size() ? FieldMarks.front() : -1);
+
+ lcl_MoveCursor(pUnoCrsr, nCurrentIndex,
+ nFirstFrameIndex, nNextPortionIndex, nNextAttrIndex,
+ nNextFieldMarkIndex,
+ i_nEndPos);
+
+ xRef = new SwXTextPortion(pUnoCrsr, i_xParentText, PORTION_TEXT);
+ }
+ else if (bAtEnd && !xRef.is() && !pTxtNode->Len())
+ {
+ // special case: for an empty paragraph, we better put out a
+ // text portion because there may be a hyperlink attribute
+ xRef = new SwXTextPortion(pUnoCrsr, i_xParentText, PORTION_TEXT);
+ }
+
+ if (xRef.is())
+ {
+ PortionStack.top().first->push_back(xRef);
+ }
+ }
+
+ OSL_ENSURE((PortionStack.size() == 1) && !PortionStack.top().second,
+ "CreatePortions: stack error" );
+}
+
+void SwXTextPortionEnumeration::Modify( const SfxPoolItem* pOld, const SfxPoolItem *pNew)
+{
+ ClientModify(this, pOld, pNew);
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/unocore/unoprnms.cxx b/sw/source/core/unocore/unoprnms.cxx
new file mode 100644
index 000000000000..d8cd403b8b97
--- /dev/null
+++ b/sw/source/core/unocore/unoprnms.cxx
@@ -0,0 +1,803 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+#include <tools/debug.hxx>
+#include <svl/itemprop.hxx>
+#include <unoprnms.hxx>
+
+
+//#define MAP_CHAR_LEN(cchar) cchar, sizeof(cchar) - 1
+
+const SwPropNameTab aPropNameTab = {
+
+/* 0001 FOLLOW_STYLE */ {MAP_CHAR_LEN("FollowStyle")},
+/* 0002 IS_PHYSICAL */ {MAP_CHAR_LEN("IsPhysical")},
+/* 0003 IS_AUTO_UPDATE */ {MAP_CHAR_LEN("IsAutoUpdate")},
+/* 0004 DISPLAY_NAME */ {MAP_CHAR_LEN("DisplayName")},
+/* 0005 PARA_GRAPHIC_URL */ {MAP_CHAR_LEN("ParaBackGraphicURL")},
+/* 0006 PARA_GRAPHIC_FILTER */ {MAP_CHAR_LEN("ParaBackGraphicFilter")},
+/* 0007 HEADER_GRAPHIC_URL */ {MAP_CHAR_LEN("HeaderBackGraphicURL")},
+/* 0008 HEADER_GRAPHIC_FILTER */ {MAP_CHAR_LEN("HeaderBackGraphicFilter")},
+/* 0009 FOOTER_GRAPHIC_URL */ {MAP_CHAR_LEN("FooterBackGraphicURL")},
+/* 0010 FOOTER_GRAPHIC_FILTER */ {MAP_CHAR_LEN("FooterBackGraphicFilter")},
+/* 0011 BACK_GRAPHIC_URL */ {MAP_CHAR_LEN("BackGraphicURL")},
+/* 0012 BACK_GRAPHIC_FILTER */ {MAP_CHAR_LEN("BackGraphicFilter")},
+/* 0013 BACK_GRAPHIC_LOCATION */ {MAP_CHAR_LEN("BackGraphicLocation")},
+/* 0014 BACK_GRAPHIC_BITMAP */ {MAP_CHAR_LEN("BackGraphicBitmap")},
+/* 0015 GRAPHIC_URL */ {MAP_CHAR_LEN("GraphicURL")},
+/* 0016 GRAPHIC_FILTER */ {MAP_CHAR_LEN("GraphicFilter")},
+/* 0017 GRAPHIC_LOCATION */ {MAP_CHAR_LEN("GraphicLocation")},
+/* 0018 GRAPHIC_SIZE */ {MAP_CHAR_LEN("GraphicSize")},
+/* 0019 GRAPHIC_BITMAP */ {MAP_CHAR_LEN("GraphicBitmap")},
+/* 0020 BULLET_FONT */ {MAP_CHAR_LEN("BulletFont")},
+/* 0021 PARA_GRAPHIC_LOCATION */ {MAP_CHAR_LEN("ParaBackGraphicLocation")},
+/* 0022 HEADER_GRAPHIC_LOCATION */ {MAP_CHAR_LEN("HeaderBackGraphicLocation")},
+/* 0023 FOOTER_GRAPHIC_LOCATION */ {MAP_CHAR_LEN("FooterBackGraphicLocation")},
+/* 0024 PARA_LEFT_PARA_MARGIN */ {MAP_CHAR_LEN("ParaLeftParaMargin")},
+/* 0025 PARA_RIGHT_PARA_MARGIN */ {MAP_CHAR_LEN("ParaRightParaMargin")},
+/* 0026 PARA_LEFT_MARGIN */ {MAP_CHAR_LEN("ParaLeftMargin")},
+/* 0027 PARA_RIGHT_MARGIN */ {MAP_CHAR_LEN("ParaRightMargin")},
+/* 0028 PARA_LEFT_MARGIN_RELATIVE */ {MAP_CHAR_LEN("ParaLeftMarginRelative")},
+/* 0029 PARA_RIGHT_MARGIN_RELATIVE */ {MAP_CHAR_LEN("ParaRightMarginRelative")},
+/* 0030 PARA_IS_AUTO_FIRST_LINE_INDENT */ {MAP_CHAR_LEN("ParaIsAutoFirstLineIndent")},
+/* 0031 PARA_FIRST_LINE_INDENT */ {MAP_CHAR_LEN("ParaFirstLineIndent")},
+/* 0032 PARA_FIRST_LINE_INDENT_RELATIVE */ {MAP_CHAR_LEN("ParaFirstLineIndentRelative")},
+/* 0033 PARA_IS_HYPHENATION */ {MAP_CHAR_LEN("ParaIsHyphenation")},
+/* 0034 PARA_HYPHENATION_MAX_LEADING_CHARS */ {MAP_CHAR_LEN("ParaHyphenationMaxLeadingChars")},
+/* 0035 PARA_HYPHENATION_MAX_TRAILING_CHARS */ {MAP_CHAR_LEN("ParaHyphenationMaxTrailingChars")},
+/* 0036 PARA_HYPHENATION_MAX_HYPHENS */ {MAP_CHAR_LEN("ParaHyphenationMaxHyphens")},
+/* 0037 LEFT_MARGIN */ {MAP_CHAR_LEN("LeftMargin")},
+/* 0038 RIGHT_MARGIN */ {MAP_CHAR_LEN("RightMargin")},
+/* 0039 HEADER_LEFT_MARGIN */ {MAP_CHAR_LEN("HeaderLeftMargin")},
+/* 0040 HEADER_RIGHT_MARGIN */ {MAP_CHAR_LEN("HeaderRightMargin")},
+/* 0041 FOOTER_LEFT_MARGIN */ {MAP_CHAR_LEN("FooterLeftMargin")},
+/* 0042 FOOTER_RIGHT_MARGIN */ {MAP_CHAR_LEN("FooterRightMargin")},
+/* 0043 TEXT_RANGE */ {MAP_CHAR_LEN("TextRange")},
+/* 0044 NAME */ {MAP_CHAR_LEN("Name")},
+/* 0045 NUMBERING_ALIGNMENT */ {MAP_CHAR_LEN("NumberingAlignment")},
+/* 0046 BULLET_FONT_NAME */ {MAP_CHAR_LEN("BulletFontName")},
+/* 0047 BULLET_ID */ {MAP_CHAR_LEN("BulletId")},
+/* 0048 CHAR_STYLE_NAME */ {MAP_CHAR_LEN("CharStyleName")},
+/* 0049 ANCHOR_CHAR_STYLE_NAME */ {MAP_CHAR_LEN("AnchorCharStyleName")},
+/* 0050 SUFFIX */ {MAP_CHAR_LEN("Suffix")},
+/* 0051 PREFIX */ {MAP_CHAR_LEN("Prefix")},
+/* 0052 PARENT_NUMBERING */ {MAP_CHAR_LEN("ParentNumbering")},
+/* 0053 START_WITH */ {MAP_CHAR_LEN("StartWith")},
+/* 0054 CHAR_FONT_NAME */ {MAP_CHAR_LEN("CharFontName")},
+/* 0055 CHAR_FONT_STYLE_NAME */ {MAP_CHAR_LEN("CharFontStyleName")},
+/* 0056 CHAR_FONT_FAMILY */ {MAP_CHAR_LEN("CharFontFamily")},
+/* 0057 CHAR_FONT_CHAR_SET */ {MAP_CHAR_LEN("CharFontCharSet")},
+/* 0058 CHAR_FONT_PITCH */ {MAP_CHAR_LEN("CharFontPitch")},
+/* 0059 CHAR_POSTURE */ {MAP_CHAR_LEN("CharPosture")},
+/* 0060 CHAR_WEIGHT */ {MAP_CHAR_LEN("CharWeight")},
+/* 0061 CHAR_HEIGHT */ {MAP_CHAR_LEN("CharHeight")},
+/* 0062 CHAR_LOCALE */ {MAP_CHAR_LEN("CharLocale")},
+/* 0063 CHAR_FONT_NAME_ASIAN */ {MAP_CHAR_LEN("CharFontNameAsian")},
+/* 0064 CHAR_FONT_STYLE_NAME_ASIAN */ {MAP_CHAR_LEN("CharFontStyleNameAsian")},
+/* 0065 CHAR_FONT_FAMILY_ASIAN */ {MAP_CHAR_LEN("CharFontFamilyAsian")},
+/* 0066 CHAR_FONT_CHAR_SET_ASIAN */ {MAP_CHAR_LEN("CharFontCharSetAsian")},
+/* 0067 CHAR_FONT_PITCH_ASIAN */ {MAP_CHAR_LEN("CharFontPitchAsian")},
+/* 0068 CHAR_POSTURE_ASIAN */ {MAP_CHAR_LEN("CharPostureAsian")},
+/* 0069 CHAR_WEIGHT_ASIAN */ {MAP_CHAR_LEN("CharWeightAsian")},
+/* 0070 CHAR_HEIGHT_ASIAN */ {MAP_CHAR_LEN("CharHeightAsian")},
+/* 0071 CHAR_LOCALE_ASIAN */ {MAP_CHAR_LEN("CharLocaleAsian")},
+/* 0072 CHAR_FONT_NAME_COMPLEX */ {MAP_CHAR_LEN("CharFontNameComplex")},
+/* 0073 CHAR_FONT_STYLE_NAME_COMPLEX */ {MAP_CHAR_LEN("CharFontStyleNameComplex")},
+/* 0074 CHAR_FONT_FAMILY_COMPLEX */ {MAP_CHAR_LEN("CharFontFamilyComplex")},
+/* 0075 CHAR_FONT_CHAR_SET_COMPLEX */ {MAP_CHAR_LEN("CharFontCharSetComplex")},
+/* 0076 CHAR_FONT_PITCH_COMPLEX */ {MAP_CHAR_LEN("CharFontPitchComplex")},
+/* 0077 CHAR_POSTURE_COMPLEX */ {MAP_CHAR_LEN("CharPostureComplex")},
+/* 0078 CHAR_WEIGHT_COMPLEX */ {MAP_CHAR_LEN("CharWeightComplex")},
+/* 0079 CHAR_HEIGHT_COMPLEX */ {MAP_CHAR_LEN("CharHeightComplex")},
+/* 0080 CHAR_LOCALE_COMPLEX */ {MAP_CHAR_LEN("CharLocaleComplex")},
+/* 0081 CHAR_AUTO_KERNING */ {MAP_CHAR_LEN("CharAutoKerning")},
+/* 0082 CHAR_UNDERLINE */ {MAP_CHAR_LEN("CharUnderline")},
+/* 0083 CHAR_UNDERLINE_COLOR */ {MAP_CHAR_LEN("CharUnderlineColor")},
+/* 0084 CHAR_UNDERLINE_HAS_COLOR */ {MAP_CHAR_LEN("CharUnderlineHasColor")},
+/* 0085 CHAR_ESCAPEMENT */ {MAP_CHAR_LEN("CharEscapement")},
+/* 0086 CHAR_CASE_MAP */ {MAP_CHAR_LEN("CharCaseMap")},
+/* 0087 CHAR_SHADOWED */ {MAP_CHAR_LEN("CharShadowed")},
+/* 0088 CHAR_STRIKEOUT */ {MAP_CHAR_LEN("CharStrikeout")},
+/* 0089 CHAR_CROSSED_OUT */ {MAP_CHAR_LEN("CharCrossedOut")},
+/* 0090 CHAR_NO_HYPHENATION */ {MAP_CHAR_LEN("CharNoHyphenation")},
+/* 0091 CHAR_AUTO_ESCAPEMENT */ {MAP_CHAR_LEN("CharAutoEscapement")},
+/* 0092 CHAR_PROP_HEIGHT */ {MAP_CHAR_LEN("CharPropHeight")},
+/* 0093 CHAR_DIFF_HEIGHT */ {MAP_CHAR_LEN("CharDiffHeight")},
+/* 0094 CHAR_PROP_HEIGHT_ASIAN */ {MAP_CHAR_LEN("CharPropHeightAsian")},
+/* 0095 CHAR_DIFF_HEIGHT_ASIAN */ {MAP_CHAR_LEN("CharDiffHeightAsian")},
+/* 0096 CHAR_PROP_HEIGHT_COMPLEX */ {MAP_CHAR_LEN("CharPropHeightComplex")},
+/* 0097 CHAR_DIFF_HEIGHT_COMPLEX */ {MAP_CHAR_LEN("CharDiffHeightComplex")},
+/* 0098 CHAR_ESCAPEMENT_HEIGHT */ {MAP_CHAR_LEN("CharEscapementHeight")},
+/* 0099 CHAR_COLOR */ {MAP_CHAR_LEN("CharColor")},
+
+/* 0100 CHAR_FLASH */ {MAP_CHAR_LEN("CharFlash")},
+/* 0101 CHAR_KERNING */ {MAP_CHAR_LEN("CharKerning")},
+/* 0102 CHAR_BACK_COLOR */ {MAP_CHAR_LEN("CharBackColor")},
+/* 0103 CHAR_BACK_TRANSPARENT */ {MAP_CHAR_LEN("CharBackTransparent")},
+/* 0104 CHAR_COMBINE_IS_ON */ {MAP_CHAR_LEN("CharCombineIsOn")},
+/* 0105 CHAR_COMBINE_PREFIX */ {MAP_CHAR_LEN("CharCombinePrefix")},
+/* 0106 CHAR_COMBINE_SUFFIX */ {MAP_CHAR_LEN("CharCombineSuffix")},
+/* 0107 CHAR_EMPHASIS */ {MAP_CHAR_LEN("CharEmphasis")},
+/* 0108 PARA_LINE_SPACING */ {MAP_CHAR_LEN("ParaLineSpacing")},
+/* 0109 PARA_TOP_MARGIN */ {MAP_CHAR_LEN("ParaTopMargin")},
+/* 0110 PARA_BOTTOM_MARGIN */ {MAP_CHAR_LEN("ParaBottomMargin")},
+/* 0111 PARA_TOP_MARGIN_RELATIVE */ {MAP_CHAR_LEN("ParaTopMarginRelative")},
+/* 0112 PARA_BOTTOM_MARGIN_RELATIVE */ {MAP_CHAR_LEN("ParaBottomMarginRelative")},
+/* 0113 PARA_EXPAND_SINGLE_WORD */ {MAP_CHAR_LEN("ParaExpandSingleWord")},
+/* 0114 END_NOTICE */ {MAP_CHAR_LEN("EndNotice")},
+/* 0115 EMBEDDED_OBJECTS */ {MAP_CHAR_LEN("EmbeddedObjects")},
+/* 0116 ALPHABETICAL_SEPARATORS */ {MAP_CHAR_LEN("AlphabeticalSeparators")},
+/* 0117 BACKGROUND_COLOR */ {MAP_CHAR_LEN("BackgroundColor")},
+/* 0118 BEGIN_NOTICE */ {MAP_CHAR_LEN("BeginNotice")},
+/* 0119 CASE_SENSITIVE */ {MAP_CHAR_LEN("CaseSensitive")},
+/* 0120 FRAME_STYLE_NAME */ {MAP_CHAR_LEN("FrameStyleName")},
+/* 0121 NUMBERING_STYLE_NAME */ {MAP_CHAR_LEN("NumberingStyleName")},
+/* 0122 NUMBERING_LEVEL */ {MAP_CHAR_LEN("NumberingLevel")},
+/* 0123 NUMBERING_START_VALUE */ {MAP_CHAR_LEN("NumberingStartValue")},
+/* 0124 NUMBERING_IS_NUMBER */ {MAP_CHAR_LEN("NumberingIsNumber")},
+/* 0125 COMBINE_ENTRIES */ {MAP_CHAR_LEN("CombineEntries")},
+/* 0126 COUNT_LINES_IN_FRAMES */ {MAP_CHAR_LEN("CountLinesInFrames")},
+/* 0127 DDE_COMMAND_TYPE */ {MAP_CHAR_LEN("DDECommandType")},
+/* 0128 DDE_COMMAND_FILE */ {MAP_CHAR_LEN("DDECommandFile")},
+/* 0129 DDE_COMMAND_ELEMENT */ {MAP_CHAR_LEN("DDECommandElement")},
+/* 0130 IS_AUTOMATIC_UPDATE */ {MAP_CHAR_LEN("IsAutomaticUpdate")},
+/* 0131 DEFAULT_TABSTOP_DISTANCE */ {MAP_CHAR_LEN("DefaultTabstopDistance")},
+/* 0132 DISTANCE */ {MAP_CHAR_LEN("Distance")},
+/* 0133 DROP_CAP_FORMAT */ {MAP_CHAR_LEN("DropCapFormat")},
+/* 0134 DROP_CAP_WHOLE_WORD */ {MAP_CHAR_LEN("DropCapWholeWord")},
+/* 0135 DROP_CAP_CHAR_STYLE_NAME */ {MAP_CHAR_LEN("DropCapCharStyleName")},
+/* 0136 FILE_LINK */ {MAP_CHAR_LEN("FileLink")},
+/* 0137 GRAPHIC */ {MAP_CHAR_LEN("Graphic")},
+/* 0138 GRAPHICS */ {MAP_CHAR_LEN("Graphics")},
+/* 0139 IS_PROTECTED */ {MAP_CHAR_LEN("IsProtected")},
+/* 0140 KEY_AS_ENTRY */ {MAP_CHAR_LEN("KeyAsEntry")},
+/* 0141 PARA_KEEP_TOGETHER */ {MAP_CHAR_LEN("ParaKeepTogether")},
+/* 0142 KEEP_TOGETHER */ {MAP_CHAR_LEN("KeepTogether")},
+/* 0143 IS_LANDSCAPE */ {MAP_CHAR_LEN("IsLandscape")},
+/* 0144 SEPARATOR_TEXT */ {MAP_CHAR_LEN("SeparatorText")},
+/* 0145 MARKS */ {MAP_CHAR_LEN("Marks")},
+/* 0146 NUMBER_POSITION */ {MAP_CHAR_LEN("NumberPosition")},
+/* 0147 OUTLINES */ {MAP_CHAR_LEN("Outlines")},
+/* 0148 PAGE_STYLE_NAME */ {MAP_CHAR_LEN("PageStyleName")},
+/* 0149 PAGE_STYLE_LAYOUT */ {MAP_CHAR_LEN("PageStyleLayout")},
+/* 0150 PARA_STYLES */ {MAP_CHAR_LEN("ParaStyles")},
+/* 0151 PARA_ADJUST */ {MAP_CHAR_LEN("ParaAdjust")},
+/* 0152 PARA_REGISTER_MODE_ACTIVE */ {MAP_CHAR_LEN("ParaRegisterModeActive")},
+/* 0153 PARA_STYLE_NAME */ {MAP_CHAR_LEN("ParaStyleName")},
+/* 0154 PARA_LAST_LINE_ADJUST */ {MAP_CHAR_LEN("ParaLastLineAdjust")},
+/* 0155 PARA_LINE_NUMBER_COUNT */ {MAP_CHAR_LEN("ParaLineNumberCount")},
+/* 0156 PARA_LINE_NUMBER_START_VALUE */ {MAP_CHAR_LEN("ParaLineNumberStartValue")},
+/* 0157 BACK_COLOR */ {MAP_CHAR_LEN("BackColor")},
+/* 0158 PARA_BACK_COLOR */ {MAP_CHAR_LEN("ParaBackColor")},
+/* 0159 PARA_WIDOWS */ {MAP_CHAR_LEN("ParaWidows")},
+/* 0160 PARA_ORPHANS */ {MAP_CHAR_LEN("ParaOrphans")},
+/* 0161 PARA_BACK_TRANSPARENT */ {MAP_CHAR_LEN("ParaBackTransparent")},
+/* 0162 POSITION_END_OF_DOC */ {MAP_CHAR_LEN("PositionEndOfDoc")},
+/* 0163 POSITION_PROTECTED */ {MAP_CHAR_LEN("PositionProtected")},
+/* 0164 ALTERNATIVE_TEXT */ {MAP_CHAR_LEN("AlternativeText")},
+/* 0165 PRIMARY_KEY */ {MAP_CHAR_LEN("PrimaryKey")},
+/* 0166 PRINT_TABLES */ {MAP_CHAR_LEN("PrintTables")},
+/* 0167 PRINT_GRAPHICS */ {MAP_CHAR_LEN("PrintGraphics")},
+/* 0168 PRINT_REVERSED */ {MAP_CHAR_LEN("PrintReversed")},
+/* 0169 PRINT_PROSPECT */ {MAP_CHAR_LEN("PrintProspect")},
+/* 0170 PRINT_CONTROLS */ {MAP_CHAR_LEN("PrintControls")},
+/* 0171 PRINT_DRAWINGS */ {MAP_CHAR_LEN("PrintDrawings")},
+/* 0172 PRINT_RIGHT_PAGES */ {MAP_CHAR_LEN("PrintRightPages")},
+/* 0173 PRINT_LEFT_PAGES */ {MAP_CHAR_LEN("PrintLeftPages")},
+/* 0174 PRINT_BLACK_FONTS */ {MAP_CHAR_LEN("PrintBlackFonts")},
+/* 0175 PRINTER_PAPER_TRAY */ {MAP_CHAR_LEN("PrinterPaperTray")},
+/* 0176 PRINT_PAGE_BACKGROUND */ {MAP_CHAR_LEN("PrintPageBackground")},
+/* 0177 PRINT_ANNOTATION_MODE */ {MAP_CHAR_LEN("PrintAnnotationMode")},
+/* 0178 PRINT_FAX_NAME */ {MAP_CHAR_LEN("PrintFaxName")},
+/* 0179 PRINT_PAPER_FROM_SETUP */ {MAP_CHAR_LEN("PrintPaperFromSetup")},
+/* 0180 REGISTER_MODE_ACTIVE */ {MAP_CHAR_LEN("RegisterModeActive")},
+/* 0181 RELATIVE_WIDTH */ {MAP_CHAR_LEN("RelativeWidth")},
+/* 0182 RELATIVE_HEIGHT */ {MAP_CHAR_LEN("RelativeHeight")},
+/* 0183 REPEAT_HEADLINE */ {MAP_CHAR_LEN("RepeatHeadline")},
+/* 0184 SEARCH_STYLES */ {MAP_CHAR_LEN("SearchStyles")},
+/* 0185 SEARCH_BACKWARDS */ {MAP_CHAR_LEN("SearchBackwards")},
+/* 0186 SEARCH_SIMILARITY */ {MAP_CHAR_LEN("SearchSimilarity")},
+/* 0187 SEARCH_IN_SELECTION */ {MAP_CHAR_LEN("SearchInSelection")},
+/* 0188 SEARCH_CASE_SENSITIVE */ {MAP_CHAR_LEN("SearchCaseSensitive")},
+/* 0189 SEARCH_SIMILARITY_ADD */ {MAP_CHAR_LEN("SearchSimilarityAdd")},
+/* 0190 SEARCH_SIMILARITY_RELAX */ {MAP_CHAR_LEN("SearchSimilarityRelax")},
+/* 0191 SEARCH_SIMILARITY_REMOVE */ {MAP_CHAR_LEN("SearchSimilarityRemove")},
+/* 0192 SEARCH_REGULAR_EXPRESSION */ {MAP_CHAR_LEN("SearchRegularExpression")},
+/* 0193 SEARCH_SIMILARITY_EXCHANGE */ {MAP_CHAR_LEN("SearchSimilarityExchange")},
+/* 0194 SECONDARY_KEY */ {MAP_CHAR_LEN("SecondaryKey")},
+/* 0195 SEPARATOR_INTERVAL */ {MAP_CHAR_LEN("SeparatorInterval")},
+/* 0196 SHOW_BREAKS */ {MAP_CHAR_LEN("ShowBreaks")},
+/* 0197 SHOW_SPACES */ {MAP_CHAR_LEN("ShowSpaces")},
+/* 0198 SHOW_TABLES */ {MAP_CHAR_LEN("ShowTables")},
+/* 0199 SHOW_GRAPHICS */ {MAP_CHAR_LEN("ShowGraphics")},
+
+/* 0200 SHOW_DRAWINGS */ {MAP_CHAR_LEN("ShowDrawings")},
+/* 0201 SHOW_TABSTOPS */ {MAP_CHAR_LEN("ShowTabstops")},
+/* 0202 SHOW_VERT_RULER */ {MAP_CHAR_LEN("ShowVertRuler")},
+/* 0203 SHOW_PARA_BREAKS */ {MAP_CHAR_LEN("ShowParaBreaks")},
+/* 0204 SHOW_HIDDEN_TEXT */ {MAP_CHAR_LEN("ShowHiddenText")},
+/* 0205 SHOW_ANNOTATIONS */ {MAP_CHAR_LEN("ShowAnnotations")},
+/* 0206 SHOW_SOFT_HYPHENS */ {MAP_CHAR_LEN("ShowSoftHyphens")},
+/* 0207 SHOW_VERT_SCROLL_BAR */ {MAP_CHAR_LEN("ShowVertScrollBar")},
+/* 0208 SHOW_HORI_SCROLL_BAR */ {MAP_CHAR_LEN("ShowHoriScrollBar")},
+/* 0209 SHOW_FIELD_COMMANDS */ {MAP_CHAR_LEN("ShowFieldCommands")},
+/* 0210 SHOW_TEXT_BOUNDARIES */ {MAP_CHAR_LEN("ShowTextBoundaries")},
+/* 0211 SHOW_PROTECTED_SPACES */ {MAP_CHAR_LEN("ShowProtectedSpaces")},
+/* 0212 SHOW_TABLE_BOUNDARIES */ {MAP_CHAR_LEN("ShowTableBoundaries")},
+/* 0213 SHOW_HIDDEN_PARAGRAPHS */ {MAP_CHAR_LEN("ShowHiddenParagraphs")},
+/* 0214 SHOW_INDEX_MARK_BACKGROUND */ {MAP_CHAR_LEN("ShowIndexMarkBackground")},
+/* 0215 SHOW_FOOTNOTE_BACKGROUND */ {MAP_CHAR_LEN("ShowFootnoteBackground")},
+/* 0216 SHOW_TEXT_FIELD_BACKGROUND */ {MAP_CHAR_LEN("ShowTextFieldBackground")},
+/* 0217 IS_SYNC_WIDTH_TO_HEIGHT */ {MAP_CHAR_LEN("IsSyncWidthToHeight")},
+/* 0218 IS_SYNC_HEIGHT_TO_WIDTH */ {MAP_CHAR_LEN("IsSyncHeightToWidth")},
+/* 0219 SIZE_PROTECTED */ {MAP_CHAR_LEN("SizeProtected")},
+/* 0220 SMOOTH_SCROLLING */ {MAP_CHAR_LEN("SmoothScrolling")},
+/* 0221 SOLID_MARK_HANDLES */ {MAP_CHAR_LEN("SolidMarkHandles")},
+/* 0222 TABLES */ {MAP_CHAR_LEN("Tables")},
+/* 0223 TEXT_FRAMES */ {MAP_CHAR_LEN("TextFrames")},
+/* 0224 TEXT_COLUMNS */ {MAP_CHAR_LEN("TextColumns")},
+/* 0225 BACK_TRANSPARENT */ {MAP_CHAR_LEN("BackTransparent")},
+/* 0226 USE_PP */ {MAP_CHAR_LEN("UsePP")},
+/* 0227 USER_METRIC */ {MAP_CHAR_LEN("UserMetric")},
+/* 0228 ANCHOR_TYPE */ {MAP_CHAR_LEN("AnchorType")},
+/* 0229 ANCHOR_TYPES */ {MAP_CHAR_LEN("AnchorTypes")},
+/* 0230 ANCHOR_PAGE_NO */ {MAP_CHAR_LEN("AnchorPageNo")},
+/* 0231 ANCHOR_FRAME */ {MAP_CHAR_LEN("AnchorFrame")},
+/* 0232 AUTHOR */ {MAP_CHAR_LEN("Author")},
+/* 0233 BREAK_TYPE */ {MAP_CHAR_LEN("BreakType")},
+/* 0234 CHAIN_NEXT_NAME */ {MAP_CHAR_LEN("ChainNextName")},
+/* 0235 CHAIN_PREV_NAME */ {MAP_CHAR_LEN("ChainPrevName")},
+/* 0236 CHAPTER_FORMAT */ {MAP_CHAR_LEN("ChapterFormat")},
+/* 0237 CLIENT_MAP */ {MAP_CHAR_LEN("ClientMap")},
+/* 0238 CONDITION */ {MAP_CHAR_LEN("Condition")},
+/* 0239 CONTENT */ {MAP_CHAR_LEN("Content")},
+/* 0240 CHAR_CONTOURED */ {MAP_CHAR_LEN("CharContoured")},
+/* 0241 CONTOUR_OUTSIDE */ {MAP_CHAR_LEN("ContourOutside")},
+/* 0242 CONTENT_PROTECTED */ {MAP_CHAR_LEN("ContentProtected")},
+/* 0243 COUNT_EMPTY_LINES */ {MAP_CHAR_LEN("CountEmptyLines")},
+/* 0244 RESTART_AT_EACH_PAGE */ {MAP_CHAR_LEN("RestartAtEachPage")},
+/* 0245 DATA_BASE_NAME */ {MAP_CHAR_LEN("DataBaseName")},
+/* 0246 DATA_TABLE_NAME */ {MAP_CHAR_LEN("DataTableName")},
+/* 0247 DATA_COMMAND_TYPE */ {MAP_CHAR_LEN("DataCommandType")},
+/* 0248 DATA_COLUMN_NAME */ {MAP_CHAR_LEN("DataColumnName")},
+/* 0249 IS_DATA_BASE_FORMAT */ {MAP_CHAR_LEN("DataBaseFormat")},
+/* 0250 DATE */ {MAP_CHAR_LEN("Date")},
+/* 0251 IS_DATE */ {MAP_CHAR_LEN("IsDate")},
+/* 0252 EDIT_IN_READONLY */ {MAP_CHAR_LEN("EditInReadonly")},
+/* 0253 FALSE_CONTENT */ {MAP_CHAR_LEN("FalseContent")},
+/* 0254 FILE_FORMAT */ {MAP_CHAR_LEN("FileFormat")},
+/* 0255 IS_FIXED */ {MAP_CHAR_LEN("IsFixed")},
+/* 0256 FOOTNOTE_COUNTING */ {MAP_CHAR_LEN("FootnoteCounting")},
+/* 0257 FORMULA */ {MAP_CHAR_LEN("Formula")},
+/* 0258 FRAME_NAME */ {MAP_CHAR_LEN("FrameName")},
+/* 0259 GRAPHIC_NAME */ {MAP_CHAR_LEN("GraphicName")},
+/* 0260 FULL_NAME */ {MAP_CHAR_LEN("FullName")},
+/* 0261 HEIGHT */ {MAP_CHAR_LEN("Height")},
+/* 0262 IS_AUTO_HEIGHT */ {MAP_CHAR_LEN("IsAutoHeight")},
+/* 0263 SIZE_TYPE */ {MAP_CHAR_LEN("SizeType")},
+/* 0264 HINT */ {MAP_CHAR_LEN("Hint")},
+/* 0265 HORI_ORIENT */ {MAP_CHAR_LEN("HoriOrient")},
+/* 0266 HORI_MIRRORED_ON_EVEN_PAGES */ {MAP_CHAR_LEN("HoriMirroredOnEvenPages")},
+/* 0267 HORI_MIRRORED_ON_ODD_PAGES */ {MAP_CHAR_LEN("HoriMirroredOnOddPages")},
+/* 0268 HORI_ORIENT_RELATION */ {MAP_CHAR_LEN("HoriOrientRelation")},
+/* 0269 HORI_ORIENT_POSITION */ {MAP_CHAR_LEN("HoriOrientPosition")},
+/* 0270 HYPER_LINK_U_R_L */ {MAP_CHAR_LEN("HyperLinkURL")},
+/* 0271 HYPER_LINK_TARGET */ {MAP_CHAR_LEN("HyperLinkTarget")},
+/* 0272 HYPER_LINK_NAME */ {MAP_CHAR_LEN("HyperLinkName")},
+/* 0273 HYPER_LINK_EVENTS */ {MAP_CHAR_LEN("HyperLinkEvents")},
+/* 0274 INFO_TYPE */ {MAP_CHAR_LEN("InfoType")},
+/* 0275 INFO_FORMAT */ {MAP_CHAR_LEN("InfoFormat")},
+/* 0276 IS_INPUT */ {MAP_CHAR_LEN("IsInput")},
+/* 0277 LEVEL */ {MAP_CHAR_LEN("Level")},
+/* 0278 INTERVAL */ {MAP_CHAR_LEN("Interval")},
+/* 0279 LINK_REGION */ {MAP_CHAR_LEN("LinkRegion")},
+/* 0280 MACRO_NAME */ {MAP_CHAR_LEN("MacroName")},
+/* 0281 SPLIT */ {MAP_CHAR_LEN("Split")},
+/* 0282 PARA_SPLIT */ {MAP_CHAR_LEN("ParaSplit")},
+/* 0283 NUMBER_FORMAT */ {MAP_CHAR_LEN("NumberFormat")},
+/* 0284 NUMBERING_TYPE */ {MAP_CHAR_LEN("NumberingType")},
+/* 0285 NUMBERING_RULES */ {MAP_CHAR_LEN("NumberingRules")},
+/* 0286 OFFSET */ {MAP_CHAR_LEN("Offset")},
+/* 0287 ON */ {MAP_CHAR_LEN("On")},
+/* 0288 OPAQUE */ {MAP_CHAR_LEN("Opaque")},
+/* 0289 PAGE_TOGGLE */ {MAP_CHAR_LEN("PageToggle")},
+/* 0290 PAGE_DESC_NAME */ {MAP_CHAR_LEN("PageDescName")},
+/* 0291 PAGE_NUMBER_OFFSET */ {MAP_CHAR_LEN("PageNumberOffset")},
+/* 0292 PLACEHOLDER */ {MAP_CHAR_LEN("PlaceHolder")},
+/* 0293 PLACEHOLDER_TYPE */ {MAP_CHAR_LEN("PlaceHolderType")},
+/* 0294 PRINT */ {MAP_CHAR_LEN("Print")},
+/* 0295 REFERENCE_FIELD_PART */ {MAP_CHAR_LEN("ReferenceFieldPart")},
+/* 0296 REFERENCE_FIELD_SOURCE */ {MAP_CHAR_LEN("ReferenceFieldSource")},
+/* 0297 REGISTER_PARAGRAPH_STYLE */ {MAP_CHAR_LEN("RegisterParagraphStyle")},
+/* 0298 SCRIPT_TYPE */ {MAP_CHAR_LEN("ScriptType")},
+/* 0299 SEARCH_ALL */ {MAP_CHAR_LEN("SearchAll")},
+
+/* 0300 SEARCH_WORDS */ {MAP_CHAR_LEN("SearchWords")},
+/* 0301 SEQUENCE_VALUE */ {MAP_CHAR_LEN("SequenceValue")},
+/* 0302 SERVER_MAP */ {MAP_CHAR_LEN("ServerMap")},
+/* 0303 IMAGE_MAP */ {MAP_CHAR_LEN("ImageMap")},
+/* 0304 SET_NUMBER */ {MAP_CHAR_LEN("SetNumber")},
+/* 0305 SHADOW_FORMAT */ {MAP_CHAR_LEN("ShadowFormat")},
+/* 0306 SHOW_HORI_RULER */ {MAP_CHAR_LEN("ShowHoriRuler")},
+/* 0307 SIZE */ {MAP_CHAR_LEN("Size")},
+/* 0308 ACTUAL_SIZE */ {MAP_CHAR_LEN("ActualSize")},
+/* 0309 SOURCE_NAME */ {MAP_CHAR_LEN("SourceName")},
+/* 0310 START_AT */ {MAP_CHAR_LEN("StartAt")},
+/* 0311 STATISTIC_TYPE_ID */ {MAP_CHAR_LEN("StatisticTypeId")},
+/* 0312 SUB_TYPE */ {MAP_CHAR_LEN("SubType")},
+/* 0313 SURROUND */ {MAP_CHAR_LEN("Surround")},
+/* 0314 IS_EXPRESSION */ {MAP_CHAR_LEN("IsExpression")},
+/* 0315 IS_SHOW_FORMULA */ {MAP_CHAR_LEN("IsShowFormula")},
+/* 0316 TEXT_WRAP */ {MAP_CHAR_LEN("TextWrap")},
+/* 0317 SURROUND_CONTOUR */ {MAP_CHAR_LEN("SurroundContour")},
+/* 0318 SURROUND_ANCHORONLY */ {MAP_CHAR_LEN("SurroundAnchorOnly")},
+/* 0319 TABLE_NAME */ {MAP_CHAR_LEN("TableName")},
+/* 0320 TABSTOPS */ {MAP_CHAR_LEN("ParaTabStops")},
+/* 0321 TITLE */ {MAP_CHAR_LEN("Title")},
+/* 0322 TOP_MARGIN */ {MAP_CHAR_LEN("TopMargin")},
+/* 0323 BOTTOM_MARGIN */ {MAP_CHAR_LEN("BottomMargin")},
+/* 0324 TRUE_CONTENT */ {MAP_CHAR_LEN("TrueContent")},
+/* 0325 URL_CONTENT */ {MAP_CHAR_LEN("URLContent")},
+/* 0326 USERTEXT */ {MAP_CHAR_LEN("UserText")},
+/* 0327 USER_DATA_TYPE */ {MAP_CHAR_LEN("UserDataType")},
+/* 0328 VALUE */ {MAP_CHAR_LEN("Value")},
+/* 0329 VARIABLE_NAME */ {MAP_CHAR_LEN("VariableName")},
+/* 0330 VARIABLE_SUBTYPE */ {MAP_CHAR_LEN("VariableSubtype")},
+/* 0331 VERT_ORIENT */ {MAP_CHAR_LEN("VertOrient")},
+/* 0332 VERT_MIRRORED */ {MAP_CHAR_LEN("VertMirrored")},
+/* 0333 VERT_ORIENT_POSITION */ {MAP_CHAR_LEN("VertOrientPosition")},
+/* 0334 VERT_ORIENT_RELATION */ {MAP_CHAR_LEN("VertOrientRelation")},
+/* 0335 IS_VISIBLE */ {MAP_CHAR_LEN("IsVisible")},
+/* 0336 WIDTH */ {MAP_CHAR_LEN("Width")},
+/* 0337 CHAR_WORD_MODE */ {MAP_CHAR_LEN("CharWordMode")},
+/* 0338 GRAPHIC_CROP */ {MAP_CHAR_LEN("GraphicCrop")},
+/* 0339 CHARACTER_FORMAT_NONE */ {MAP_CHAR_LEN("CharacterFormatNone")},
+/* 0340 TEXT_POSITION */ {MAP_CHAR_LEN("TextPosition")},
+/* 0341 DOCUMENT_INDEX_MARK */ {MAP_CHAR_LEN("DocumentIndexMark")},
+/* 0342 DOCUMENT_INDEX */ {MAP_CHAR_LEN("DocumentIndex")},
+/* 0343 IS_GLOBAL_DOCUMENT_SECTION */ {MAP_CHAR_LEN("IsGlobalDocumentSection")},
+/* 0344 TEXT_FIELD */ {MAP_CHAR_LEN("TextField")},
+/* 0345 BOOKMARK */ {MAP_CHAR_LEN("Bookmark")},
+/* 0346 TEXT_TABLE */ {MAP_CHAR_LEN("TextTable")},
+/* 0347 CELL */ {MAP_CHAR_LEN("Cell")},
+/* 0348 TEXT_FRAME */ {MAP_CHAR_LEN("TextFrame")},
+/* 0349 REFERENCE_MARK */ {MAP_CHAR_LEN("ReferenceMark")},
+/* 0350 TEXT_SECTION */ {MAP_CHAR_LEN("TextSection")},
+/* 0351 FOOTNOTE */ {MAP_CHAR_LEN("Footnote")},
+/* 0352 ENDNOTE */ {MAP_CHAR_LEN("Endnote")},
+/* 0353 CHART_ROW_AS_LABEL */ {MAP_CHAR_LEN("ChartRowAsLabel")},
+/* 0354 CHART_COLUMN_AS_LABEL */ {MAP_CHAR_LEN("ChartColumnAsLabel")},
+/* 0355 TABLE_COLUMS */ {MAP_CHAR_LEN("TableColumns")},
+/* 0356 LEFT_BORDER */ {MAP_CHAR_LEN("LeftBorder")},
+/* 0357 RIGHT_BORDER */ {MAP_CHAR_LEN("RightBorder")},
+/* 0358 TOP_BORDER */ {MAP_CHAR_LEN("TopBorder")},
+/* 0359 BOTTOM_BORDER */ {MAP_CHAR_LEN("BottomBorder")},
+/* 0360 BORDER_DISTANCE */ {MAP_CHAR_LEN("BorderDistance")},
+/* 0361 LEFT_BORDER_DISTANCE */ {MAP_CHAR_LEN("LeftBorderDistance")},
+/* 0362 RIGHT_BORDER_DISTANCE */ {MAP_CHAR_LEN("RightBorderDistance")},
+/* 0363 TOP_BORDER_DISTANCE */ {MAP_CHAR_LEN("TopBorderDistance")},
+/* 0364 BOTTOM_BORDER_DISTANCE */ {MAP_CHAR_LEN("BottomBorderDistance")},
+/* 0365 TABLE_BORDER */ {MAP_CHAR_LEN("TableBorder")},
+/* 0366 TABLE_COLUMN_SEPARATORS */ {MAP_CHAR_LEN("TableColumnSeparators")},
+/* 0367 TABLE_COLUMN_RELATIVE_SUM */ {MAP_CHAR_LEN("TableColumnRelativeSum")},
+/* 0368 HEADER_TEXT */ {MAP_CHAR_LEN("HeaderText")},
+/* 0369 HEADER_TEXT_LEFT */ {MAP_CHAR_LEN("HeaderTextLeft")},
+/* 0370 HEADER_TEXT_RIGHT */ {MAP_CHAR_LEN("HeaderTextRight")},
+/* 0371 FOOTER_TEXT */ {MAP_CHAR_LEN("FooterText")},
+/* 0372 FOOTER_TEXT_LEFT */ {MAP_CHAR_LEN("FooterTextLeft")},
+/* 0373 FOOTER_TEXT_RIGHT */ {MAP_CHAR_LEN("FooterTextRight")},
+/* 0374 HEADER_BACK_COLOR */ {MAP_CHAR_LEN("HeaderBackColor")},
+/* 0375 HEADER_GRAPHIC */ {MAP_CHAR_LEN("HeaderBackGraphic")},
+/* 0376 HEADER_BACK_TRANSPARENT */ {MAP_CHAR_LEN("HeaderBackTransparent")},
+/* 0377 HEADER_LEFT_BORDER */ {MAP_CHAR_LEN("HeaderLeftBorder")},
+/* 0378 HEADER_RIGHT_BORDER */ {MAP_CHAR_LEN("HeaderRightBorder")},
+/* 0379 HEADER_TOP_BORDER */ {MAP_CHAR_LEN("HeaderTopBorder")},
+/* 0380 HEADER_BOTTOM_BORDER */ {MAP_CHAR_LEN("HeaderBottomBorder")},
+/* 0381 HEADER_BORDER_DISTANCE */ {MAP_CHAR_LEN("HeaderBorderDistance")},
+/* 0382 HEADER_SHADOW_FORMAT */ {MAP_CHAR_LEN("HeaderShadowFormat")},
+/* 0383 HEADER_BODY_DISTANCE */ {MAP_CHAR_LEN("HeaderBodyDistance")},
+/* 0384 HEADER_IS_DYNAMIC_HEIGHT */ {MAP_CHAR_LEN("HeaderIsDynamicHeight")},
+/* 0385 HEADER_IS_SHARED */ {MAP_CHAR_LEN("HeaderIsShared")},
+/* 0386 HEADER_HEIGHT */ {MAP_CHAR_LEN("HeaderHeight")},
+/* 0387 HEADER_IS_ON */ {MAP_CHAR_LEN("HeaderIsOn")},
+/* 0388 FOOTER_BACK_COLOR */ {MAP_CHAR_LEN("FooterBackColor")},
+/* 0389 FOOTER_GRAPHIC */ {MAP_CHAR_LEN("FooterBackGraphic")},
+/* 0390 FOOTER_BACK_TRANSPARENT */ {MAP_CHAR_LEN("FooterBackTransparent")},
+/* 0391 FOOTER_LEFT_BORDER */ {MAP_CHAR_LEN("FooterLeftBorder")},
+/* 0392 FOOTER_RIGHT_BORDER */ {MAP_CHAR_LEN("FooterRightBorder")},
+/* 0393 FOOTER_TOP_BORDER */ {MAP_CHAR_LEN("FooterTopBorder")},
+/* 0394 FOOTER_BOTTOM_BORDER */ {MAP_CHAR_LEN("FooterBottomBorder")},
+/* 0395 FOOTER_BORDER_DISTANCE */ {MAP_CHAR_LEN("FooterBorderDistance")},
+/* 0396 FOOTER_SHADOW_FORMAT */ {MAP_CHAR_LEN("FooterShadowFormat")},
+/* 0397 FOOTER_BODY_DISTANCE */ {MAP_CHAR_LEN("FooterBodyDistance")},
+/* 0398 FOOTER_IS_DYNAMIC_HEIGHT */ {MAP_CHAR_LEN("FooterIsDynamicHeight")},
+/* 0399 FOOTER_IS_SHARED */ {MAP_CHAR_LEN("FooterIsShared")},
+
+/* 0400 FOOTER_HEIGHT */ {MAP_CHAR_LEN("FooterHeight")},
+/* 0401 FOOTER_IS_ON */ {MAP_CHAR_LEN("FooterIsOn")},
+/* 0402 OVERWRITE_STYLES */ {MAP_CHAR_LEN("OverwriteStyles")},
+/* 0403 LOAD_NUMBERING_STYLES */ {MAP_CHAR_LEN("LoadNumberingStyles")},
+/* 0404 LOAD_PAGE_STYLES */ {MAP_CHAR_LEN("LoadPageStyles")},
+/* 0405 LOAD_FRAME_STYLES */ {MAP_CHAR_LEN("LoadFrameStyles")},
+/* 0406 LOAD_TEXT_STYLES */ {MAP_CHAR_LEN("LoadTextStyles")},
+/* 0407 FILE_NAME */ {MAP_CHAR_LEN("FileName")},
+/* 0408 FILTER_NAME */ {MAP_CHAR_LEN("FilterName")},
+/* 0409 FILTER_OPTION */ {MAP_CHAR_LEN("FilterOption")},
+/* 0410 PASSWORD */ {MAP_CHAR_LEN("Password")},
+/* 0411 COPY_COUNT */ {MAP_CHAR_LEN("CopyCount")},
+/* 0412 COLLATE */ {MAP_CHAR_LEN("Collate")},
+/* 0413 SORT */ {MAP_CHAR_LEN("Sort")},
+/* 0414 PAGES */ {MAP_CHAR_LEN("Pages")},
+/* 0415 FIRST_LINE_OFFSET */ {MAP_CHAR_LEN("FirstLineOffset")},
+/* 0416 SYMBOL_TEXT_DISTANCE */ {MAP_CHAR_LEN("SymbolTextDistance")},
+/* 0417 USER_INDEX_NAME */ {MAP_CHAR_LEN("UserIndexName")},
+/* 0418 REVISION */ {MAP_CHAR_LEN("Revision")},
+/* 0419 UNVISITED_CHAR_STYLE_NAME */ {MAP_CHAR_LEN("UnvisitedCharStyleName")},
+/* 0420 VISITED_CHAR_STYLE_NAME */ {MAP_CHAR_LEN("VisitedCharStyleName")},
+/* 0421 PARAGRAPH_COUNT */ {MAP_CHAR_LEN("ParagraphCount")},
+/* 0422 WORD_COUNT */ {MAP_CHAR_LEN("WordCount")},
+/* 0423 WORD_SEPARATOR */ {MAP_CHAR_LEN("WordSeparator")},
+/* 0424 CHARACTER_COUNT */ {MAP_CHAR_LEN("CharacterCount")},
+/* 0425 ZOOM_VALUE */ {MAP_CHAR_LEN("ZoomValue")},
+/* 0426 ZOOM_TYPE */ {MAP_CHAR_LEN("ZoomType")},
+/* 0427 CREATE_FROM_MARKS */ {MAP_CHAR_LEN("CreateFromMarks")},
+/* 0428 CREATE_FROM_OUTLINE */ {MAP_CHAR_LEN("CreateFromOutline")},
+/* 0429 PARAGRAPH_STYLE_NAMES */ {MAP_CHAR_LEN("ParagraphStyleNames")},
+/* 0430 CREATE_FROM_CHAPTER */ {MAP_CHAR_LEN("CreateFromChapter")},
+/* 0431 CREATE_FROM_LABELS */ {MAP_CHAR_LEN("CreateFromLabels")},
+/* 0432 USE_ALPHABETICAL_SEPARATORS */ {MAP_CHAR_LEN("UseAlphabeticalSeparators")},
+/* 0433 USE_KEY_AS_ENTRY */ {MAP_CHAR_LEN("UseKeyAsEntry")},
+/* 0434 USE_COMBINED_ENTRIES */ {MAP_CHAR_LEN("UseCombinedEntries")},
+/* 0435 IS_CASE_SENSITIVE */ {MAP_CHAR_LEN("IsCaseSensitive")},
+/* 0436 USE_P_P */ {MAP_CHAR_LEN("UsePP")},
+/* 0437 USE_DASH */ {MAP_CHAR_LEN("UseDash")},
+/* 0438 USE_UPPER_CASE */ {MAP_CHAR_LEN("UseUpperCase")},
+/* 0439 LABEL_CATEGORY */ {MAP_CHAR_LEN("LabelCategory")},
+/* 0440 LABEL_DISPLAY_TYPE */ {MAP_CHAR_LEN("LabelDisplayType")},
+/* 0441 USE_LEVEL_FROM_SOURCE */ {MAP_CHAR_LEN("UseLevelFromSource")},
+/* 0442 LEVEL_FORMAT */ {MAP_CHAR_LEN("LevelFormat")},
+/* 0443 LEVEL_PARAGRAPH_STYLES */ {MAP_CHAR_LEN("LevelParagraphStyles")},
+/* 0444 RECALC_TAB_STOPS */ {MAP_CHAR_LEN("RecalcTabStops")},
+/* 0445 MAIN_ENTRY_CHARACTER_STYLE_NAME */ {MAP_CHAR_LEN("MainEntryCharacterStyleName")},
+/* 0446 CREATE_FROM_TABLES */ {MAP_CHAR_LEN("CreateFromTables")},
+/* 0447 CREATE_FROM_TEXT_FRAMES */ {MAP_CHAR_LEN("CreateFromTextFrames")},
+/* 0448 CREATE_FROM_GRAPHIC_OBJECTS */ {MAP_CHAR_LEN("CreateFromGraphicObjects")},
+/* 0449 CREATE_FROM_EMBEDDED_OBJECTS */ {MAP_CHAR_LEN("CreateFromEmbeddedObjects")},
+/* 0450 CREATE_FROM_STAR_MATH */ {MAP_CHAR_LEN("CreateFromStarMath")},
+/* 0451 CREATE_FROM_STAR_CHART */ {MAP_CHAR_LEN("CreateFromStarChart")},
+/* 0452 CREATE_FROM_STAR_CALC */ {MAP_CHAR_LEN("CreateFromStarCalc")},
+/* 0453 CREATE_FROM_STAR_DRAW */ {MAP_CHAR_LEN("CreateFromStarDraw")},
+/* 0454 CREATE_FROM_OTHER_EMBEDDED_OBJECTS */ {MAP_CHAR_LEN("CreateFromOtherEmbeddedObjects")},
+/* 0455 INDEX_AUTO_MARK_FILE_U_R_L */ {MAP_CHAR_LEN("IndexAutoMarkFileURL")},
+/* 0456 IS_COMMA_SEPARATED */ {MAP_CHAR_LEN("IsCommaSeparated")},
+/* 0457 IS_RELATIVE_TABSTOPS */ {MAP_CHAR_LEN("IsRelativeTabstops")},
+/* 0458 CREATE_FROM_LEVEL_PARAGRAPH_STYLES */ {MAP_CHAR_LEN("CreateFromLevelParagraphStyles")},
+/* 0459 SHOW_CHANGES */ {MAP_CHAR_LEN("ShowChanges")},
+/* 0460 RECORD_CHANGES */ {MAP_CHAR_LEN("RecordChanges")},
+/* 0461 DISPLAY_NAME */ {MAP_CHAR_LEN("LinkDisplayName")},
+/* 0462 DISPLAY_BITMAP */ {MAP_CHAR_LEN("LinkDisplayBitmap")},
+/* 0463 HEADING_STYLE_NAME */ {MAP_CHAR_LEN("HeadingStyleName")},
+/* 0464 SHOW_ONLINE_LAYOUT */ {MAP_CHAR_LEN("ShowOnlineLayout")},
+/* 0465 USER_DEFINED_ATTRIBUTES */ {MAP_CHAR_LEN("UserDefinedAttributes")},
+/* 0466 TEXT_USER_DEFINED_ATTRIBUTES */ {MAP_CHAR_LEN("TextUserDefinedAttributes")},
+/* 0467 FILE_PATH */ {MAP_CHAR_LEN("FilePath")},
+/* 0468 PARA_CHAPTER_NUMBERING_LEVEL */ {MAP_CHAR_LEN("ParaChapterNumberingLevel")},
+/* 0469 PARA_CONDITIONAL_STYLE_NAME */ {MAP_CHAR_LEN("ParaConditionalStyleName")},
+/* 0470 CHAPTER_NUMBERING_LEVEL */ {MAP_CHAR_LEN("ChapterNumberingLevel")},
+/* 0471 NUMBERING_SEPARATOR */ {MAP_CHAR_LEN("NumberingSeparator")},
+/* 0472 IS_CONTINUOUS_NUMBERING */ {MAP_CHAR_LEN("IsContinuousNumbering")},
+/* 0473 IS_AUTOMATIC */ {MAP_CHAR_LEN("IsAutomatic")},
+/* 0474 IS_ABSOLUTE_MARGINS */ {MAP_CHAR_LEN("IsAbsoluteMargins")},
+/* 0475 CATEGORY */ {MAP_CHAR_LEN("Category")},
+/* 0476 DEPENDENT_TEXT_FIELDS */ {MAP_CHAR_LEN("DependentTextFields")},
+/* 0477 CURRENT_PRESENTATION */ {MAP_CHAR_LEN("CurrentPresentation")},
+/* 0478 ADJUST */ {MAP_CHAR_LEN("Adjust")},
+/* 0479 INSTANCE_NAME */ {MAP_CHAR_LEN("InstanceName")},
+/* 0480 TEXT_PORTION_TYPE */ {MAP_CHAR_LEN("TextPortionType")},
+/* 0481 CONTROL_CHARACTER */ {MAP_CHAR_LEN("ControlCharacter")},
+/* 0482 IS_COLLAPSED */ {MAP_CHAR_LEN("IsCollapsed")},
+/* 0483 IS_START */ {MAP_CHAR_LEN("IsStart")},
+/* 0484 SEQUENCE_NUMBER */ {MAP_CHAR_LEN("SequenceNumber")},
+/* 0485 REFERENCE_ID */ {MAP_CHAR_LEN("ReferenceId")},
+/* 0486 HEADER_LEFT_BORDER_DISTANCE */ {MAP_CHAR_LEN("HeaderLeftBorderDistance")},
+/* 0487 HEADER_RIGHT_BORDER_DISTANCE */ {MAP_CHAR_LEN("HeaderRightBorderDistance")},
+/* 0488 HEADER_TOP_BORDER_DISTANCE */ {MAP_CHAR_LEN("HeaderTopBorderDistance")},
+/* 0489 HEADER_BOTTOM_BORDER_DISTANCE */{MAP_CHAR_LEN("HeaderBottomBorderDistance")},
+/* 0490 FOOTER_LEFT_BORDER_DISTANCE */ {MAP_CHAR_LEN("FooterLeftBorderDistance")},
+/* 0491 FOOTER_RIGHT_BORDER_DISTANCE */ {MAP_CHAR_LEN("FooterRightBorderDistance")},
+/* 0492 FOOTER_TOP_BORDER_DISTANCE */ {MAP_CHAR_LEN("FooterTopBorderDistance")},
+/* 0493 FOOTER_BOTTOM_BORDER_DISTANCE */{MAP_CHAR_LEN("FooterBottomBorderDistance")},
+/* 0494 PARA_IS_NUMBERING_RESTART */ {MAP_CHAR_LEN("ParaIsNumberingRestart")},
+/* 0495 HIDE_FIELD_TIPS */ {MAP_CHAR_LEN("HideFieldTips")},
+/* 0496 HEADER_USER_DEFINED_ATTRIBUTES */ {MAP_CHAR_LEN("HeaderUserDefinedAttributes")},
+/* 0497 FOOTER_USER_DEFINED_ATTRIBUTES */ {MAP_CHAR_LEN("FooterUserDefinedAttributes")},
+/* 0498 PARA_SHADOW_FORMAT */ {MAP_CHAR_LEN("ParaShadowFormat")},
+/* 0499 CONTOUR_POLY_POLYGON */ {MAP_CHAR_LEN("ContourPolyPolygon")},
+
+/* 0500 IS_PIXEL_CONTOUR */ {MAP_CHAR_LEN("IsPixelContour")},
+/* 0501 IS_AUTOMATIC_CONTOUR */ {MAP_CHAR_LEN("IsAutomaticContour")},
+/* 0502 SEPARATOR_LINE_WIDTH */ {MAP_CHAR_LEN("SeparatorLineWidth")},
+/* 0503 SEPARATOR_LINE_COLOR */ {MAP_CHAR_LEN("SeparatorLineColor")},
+/* 0504 SEPARATOR_LINE_RELATIVE_HEIGHT */ {MAP_CHAR_LEN("SeparatorLineRelativeHeight")},
+/* 0505 SEPARATOR_LINE_VERTIVAL_ALIGNMENT */{MAP_CHAR_LEN("SeparatorLineVerticalAlignment")},
+/* 0506 SEPARATOR_LINE_IS_ON */ {MAP_CHAR_LEN("SeparatorLineIsOn")},
+/* 0507 IS_SKIP_HIDDEN_TEXT */ {MAP_CHAR_LEN("IsSkipHiddenText")},
+/* 0508 IS_SKIP_PROTECTED_TEXT */ {MAP_CHAR_LEN("IsSkipProtectedText")},
+/* 0509 DOCUMENT_INDEX_MARKS */ {MAP_CHAR_LEN("DocumentIndexMarks")},
+/* 0510 FOOTNOTE_IS_COLLECT_AT_TEXT_END */ {MAP_CHAR_LEN("FootnoteIsCollectAtTextEnd")},
+/* 0511 FOOTNOTE_IS_RESTART_NUMBERING */ {MAP_CHAR_LEN("FootnoteIsRestartNumbering")},
+/* 0512 FOOTNOTE_RESTART_NUMBERING_AT */{MAP_CHAR_LEN("FootnoteRestartNumberingAt")},
+/* 0513 FOOTNOTE_IS_OWN_NUMBERING */ {MAP_CHAR_LEN("FootnoteIsOwnNumbering")},
+/* 0514 FOOTNOTE_NUMBERING_TYPE */ {MAP_CHAR_LEN("FootnoteNumberingType")},
+/* 0515 FOOTNOTE_NUMBERING_PREFIX */ {MAP_CHAR_LEN("FootnoteNumberingPrefix")},
+/* 0516 FOOTNOTE_NUMBERING_SUFFIX */ {MAP_CHAR_LEN("FootnoteNumberingSuffix")},
+/* 0517 ENDNOTE_IS_COLLECT_AT_TEXT_END */ {MAP_CHAR_LEN("EndnoteIsCollectAtTextEnd")},
+/* 0518 ENDNOTE_IS_RESTART_NUMBERING */ {MAP_CHAR_LEN("EndnoteIsRestartNumbering")},
+/* 0519 ENDNOTE_RESTART_NUMBERING_AT */ {MAP_CHAR_LEN("EndnoteRestartNumberingAt")},
+/* 0520 ENDNOTE_IS_OWN_NUMBERING */ {MAP_CHAR_LEN("EndnoteIsOwnNumbering")},
+/* 0521 ENDNOTE_NUMBERING_TYPE */ {MAP_CHAR_LEN("EndnoteNumberingType")},
+/* 0522 ENDNOTE_NUMBERING_PREFIX */ {MAP_CHAR_LEN("EndnoteNumberingPrefix")},
+/* 0523 ENDNOTE_NUMBERING_SUFFIX */ {MAP_CHAR_LEN("EndnoteNumberingSuffix")},
+/* 0524 BRACKET_BEFORE */ {MAP_CHAR_LEN("BracketBefore")},
+/* 0525 BRACKET_AFTER */ {MAP_CHAR_LEN("BracketAfter")},
+/* 0526 IS_NUMBER_ENTRIES */ {MAP_CHAR_LEN("IsNumberEntries")},
+/* 0527 IS_SORT_BY_POSITION */ {MAP_CHAR_LEN("IsSortByPosition")},
+/* 0528 SORT_KEYS */ {MAP_CHAR_LEN("SortKeys")},
+/* 0529 IS_SORT_ASCENDING */ {MAP_CHAR_LEN("IsSortAscending")},
+/* 0530 SORT_KEY */ {MAP_CHAR_LEN("SortKey")},
+/* 0531 FIELDS */ {MAP_CHAR_LEN("Fields")},
+/* 0532 DATE_TIME_VALUE */ {MAP_CHAR_LEN("DateTimeValue")},
+/* 0533 IS_ON */ {MAP_CHAR_LEN("IsOn")},
+/* 0534 Z_ORDER */ {MAP_CHAR_LEN("ZOrder")},
+/* 0535 CONTENT_SECTION */ {MAP_CHAR_LEN("ContentSection")},
+/* 0536 HEADER_SECTION */ {MAP_CHAR_LEN("HeaderSection")},
+/* 0537 PARA_IS_HANGING_PUNCTUATION */ {MAP_CHAR_LEN("ParaIsHangingPunctuation")},
+/* 0538 PARA_IS_CHARACTER_DISTANCE */ {MAP_CHAR_LEN("ParaIsCharacterDistance")},
+/* 0539 PARA_IS_FORBIDDEN_RULES */ {MAP_CHAR_LEN("ParaIsForbiddenRules")},
+/* 0540 PARA_VERT_ALIGNMENT */ {MAP_CHAR_LEN("ParaVertAlignment")},
+/* 0541 IS_MAIN_ENTRY */ {MAP_CHAR_LEN("IsMainEntry")},
+/* 0542 GRAPHIC_ROTATION */ {MAP_CHAR_LEN("GraphicRotation")},
+/* 0543 ADJUST_LUMINANCE */ {MAP_CHAR_LEN("AdjustLuminance")},
+/* 0544 ADJUST_CONTRAST */ {MAP_CHAR_LEN("AdjustContrast")},
+/* 0545 ADJUST_RED */ {MAP_CHAR_LEN("AdjustRed")},
+/* 0546 ADJUST_GREEN */ {MAP_CHAR_LEN("AdjustGreen")},
+/* 0547 ADJUST_BLUE */ {MAP_CHAR_LEN("AdjustBlue")},
+/* 0548 GAMMA */ {MAP_CHAR_LEN("Gamma")},
+/* 0549 GRAPHIC_IS_INVERTED */ {MAP_CHAR_LEN("GraphicIsInverted")},
+/* 0550 TRANSPARENCY */ {MAP_CHAR_LEN("Transparency")},
+/* 0551 GRAPHIC_COLOR_MODE */ {MAP_CHAR_LEN("GraphicColorMode")},
+/* 0552 REDLINE_AUTHOR */ {MAP_CHAR_LEN("RedlineAuthor")},
+/* 0553 REDLINE_DATE_TIME */ {MAP_CHAR_LEN("RedlineDateTime")},
+/* 0554 REDLINE_COMMENT */ {MAP_CHAR_LEN("RedlineComment")},
+/* 0555 REDLINE_TYPE */ {MAP_CHAR_LEN("RedlineType")},
+/* 0556 REDLINE_SUCCESSOR_DATA */ {MAP_CHAR_LEN("RedlineSuccessorData")},
+/* 0557 REDLINE_IDENTIFIER */ {MAP_CHAR_LEN("RedlineIdentifier")},
+/* 0558 IS_IN_HEADER_FOOTER */ {MAP_CHAR_LEN("IsInHeaderFooter")},
+/* 0559 START_REDLINE */ {MAP_CHAR_LEN("StartRedline")},
+/* 0560 END_REDLINE */ {MAP_CHAR_LEN("EndRedline")},
+/* 0561 REDLINE_START */ {MAP_CHAR_LEN("RedlineStart")},
+/* 0562 REDLINE_END */ {MAP_CHAR_LEN("RedlineEnd")},
+/* 0563 REDLINE_TEXT */ {MAP_CHAR_LEN("RedlineText")},
+/* 0564 REDLINE_DISPLAY_TYPE */ {MAP_CHAR_LEN("RedlineDisplayType")},
+/* 0565 FORBIDDEN_CHARACTERS */ {MAP_CHAR_LEN("ForbiddenCharacters")},
+/* 0566 RUBY_BASE_TEXT */ {MAP_CHAR_LEN("RubyBaseText")},
+/* 0567 RUBY_TEXT */ {MAP_CHAR_LEN("RubyText")},
+/* 0568 RUBY_ADJUST */ {MAP_CHAR_LEN("RubyAdjust")},
+/* 0569 RUBY_CHAR_STYLE_NAME */ {MAP_CHAR_LEN("RubyCharStyleName")},
+/* 0570 RUBY_IS_ABOVE */ {MAP_CHAR_LEN("RubyIsAbove")},
+/* 0571 FOOTNOTE_HEIGHT */ {MAP_CHAR_LEN("FootnoteHeight")},
+/* 0572 FOOTNOTE_LINE_WEIGHT */ {MAP_CHAR_LEN("FootnoteLineWeight")},
+/* 0573 FOOTNOTE_LINE_COLOR */ {MAP_CHAR_LEN("FootnoteLineColor")},
+/* 0574 FOOTNOTE_LINE_RELATIVE_WIDTH */ {MAP_CHAR_LEN("FootnoteLineRelativeWidth")},
+/* 0575 FOOTNOTE_LINE_ADJUST */ {MAP_CHAR_LEN("FootnoteLineAdjust")},
+/* 0576 FOOTNOTE_LINE_TEXT_DISTANCE */ {MAP_CHAR_LEN("FootnoteLineTextDistance")},
+/* 0577 FOOTNOTE_LINE_DISTANCE */ {MAP_CHAR_LEN("FootnoteLineDistance")},
+/* 0578 CHAR_ROTATION */ {MAP_CHAR_LEN("CharRotation")},
+/* 0579 CHAR_ROTATION_IS_FIT_TO_LINE */ {MAP_CHAR_LEN("CharRotationIsFitToLine")},
+/* 0580 CHAR_SCALE_WIDTH */ {MAP_CHAR_LEN("CharScaleWidth")},
+/* 0581 TAB_STOP_DISTANCE */ {MAP_CHAR_LEN("TabStopDistance")},
+/* 0582 IS_WIDTH_RELATIVE */ {MAP_CHAR_LEN("IsWidthRelative")},
+/* 0583 CHAR_RELIEF */ {MAP_CHAR_LEN("CharRelief")},
+/* 0584 IS_HIDDEN */ {MAP_CHAR_LEN("IsHidden")},
+/* 0585 IS_CONDITION_TRUE */ {MAP_CHAR_LEN("IsConditionTrue")},
+/* 0586 TWO_DIGIT_YEAR */ {MAP_CHAR_LEN("TwoDigitYear")},
+/* 0587 PROTECTION_KEY */ {MAP_CHAR_LEN("ProtectionKey")},
+/* 0588 REDLINE_PROTECTION_KEY */ {MAP_CHAR_LEN("RedlineProtectionKey")},
+/* 0589 AUTOMATIC_DISTANCE */ {MAP_CHAR_LEN("AutomaticDistance")},
+/* 0590 AUTOMATIC_CONTROL_FOCUS */ {MAP_CHAR_LEN("AutomaticControlFocus")},
+/* 0591 APPLY_FORM_DESIGN_MODE */ {MAP_CHAR_LEN("ApplyFormDesignMode")},
+/* 0592 LOCALE */ {MAP_CHAR_LEN("Locale")},
+/* 0593 SORT_ALGORITHM */ {MAP_CHAR_LEN("SortAlgorithm")},
+/* 0594 FRAME_HEIGHT_ABSOLUTE */ {MAP_CHAR_LEN("FrameHeightAbsolute")},
+/* 0596 FRAME_HEIGHT_PERCENT */ {MAP_CHAR_LEN("FrameHeightPercent")},
+/* 0597 FRAME_ISAUTOMATIC_HEIGHT */ {MAP_CHAR_LEN("FrameIsAutomaticHeight")},
+/* 0598 FRAME_WIDTH_ABSOLUTE */ {MAP_CHAR_LEN("FrameWidthAbsolute")},
+/* 0599 FRAME_WIDTH_PERCENT */ {MAP_CHAR_LEN("FrameWidthPercent")},
+/* 0600 PARA_STYLEHEADING */ {MAP_CHAR_LEN("ParaStyleHeading")},
+/* 0601 PARA_STYLELEVEL1 */ {MAP_CHAR_LEN("ParaStyleLevel1")},
+/* 0602 PARA_STYLELEVEL10 */ {MAP_CHAR_LEN("ParaStyleLevel10")},
+/* 0603 PARA_STYLELEVEL2 */ {MAP_CHAR_LEN("ParaStyleLevel2")},
+/* 0604 PARA_STYLELEVEL3 */ {MAP_CHAR_LEN("ParaStyleLevel3")},
+/* 0605 PARA_STYLELEVEL4 */ {MAP_CHAR_LEN("ParaStyleLevel4")},
+/* 0606 PARA_STYLELEVEL5 */ {MAP_CHAR_LEN("ParaStyleLevel5")},
+/* 0607 PARA_STYLELEVEL6 */ {MAP_CHAR_LEN("ParaStyleLevel6")},
+/* 0608 PARA_STYLELEVEL7 */ {MAP_CHAR_LEN("ParaStyleLevel7")},
+/* 0609 PARA_STYLELEVEL8 */ {MAP_CHAR_LEN("ParaStyleLevel8")},
+/* 0610 PARA_STYLELEVEL9 */ {MAP_CHAR_LEN("ParaStyleLevel9")},
+/* 0611 PARA_STYLESEPARATOR */ {MAP_CHAR_LEN("ParaStyleSeparator")},
+/* 0612 MACRO_LIBRARY */ {MAP_CHAR_LEN("MacroLibrary")},
+/* 0613 CELL_NAME */ {MAP_CHAR_LEN("CellName")},
+/* 0614 PARA_USER_DEFINED_ATTRIBUTES */ {MAP_CHAR_LEN("ParaUserDefinedAttributes")},
+/* 0615 UNO_NAME_MERGE_LAST_PARA */ {MAP_CHAR_LEN("MergeLastPara")},
+/* 0616 UNO_NAME_WRITING_MODE */ {MAP_CHAR_LEN("WritingMode")},
+/* 0617 UNO_NAME_GRID_COLOR */ {MAP_CHAR_LEN("GridColor")},
+/* 0618 UNO_NAME_GRID_LINES */ {MAP_CHAR_LEN("GridLines")},
+/* 0619 UNO_NAME_GRID_BASE_HEIGHT */ {MAP_CHAR_LEN("GridBaseHeight")},
+/* 0620 UNO_NAME_GRID_RUBY_HEIGHT */ {MAP_CHAR_LEN("GridRubyHeight")},
+/* 0621 UNO_NAME_GRID_MODE */ {MAP_CHAR_LEN("GridMode")},
+/* 0622 UNO_NAME_GRID_RUBY_BELOW */ {MAP_CHAR_LEN("RubyBelow")},
+/* 0623 UNO_NAME_GRID_PRINT */ {MAP_CHAR_LEN("GridPrint")},
+/* 0624 UNO_NAME_GRID_DISPLAY */ {MAP_CHAR_LEN("GridDisplay")},
+/* 0625 UNO_NAME_SNAP_TO_GRID */ {MAP_CHAR_LEN("SnapToGrid")},
+/* 0626 UNO_NAME_DONT_BALANCE_TEXT_COLUMNS */{MAP_CHAR_LEN("DontBalanceTextColumns")},
+/* 0627 UNO_NAME_IS_CURRENTLY_VISIBLE */{MAP_CHAR_LEN("IsCurrentlyVisible")},
+/* 0628 UNO_NAME_ANCHOR_POSITION */ {MAP_CHAR_LEN("AnchorPosition")},
+/* 0629 UNO_NAME_TEXT_READING */ {MAP_CHAR_LEN("TextReading")},
+/* 0630 UNO_NAME_PRIMARY_KEY_READING */ {MAP_CHAR_LEN("PrimaryKeyReading")},
+/* 0631 UNO_NAME_SECONDARY_KEY_READING */ {MAP_CHAR_LEN("SecondaryKeyReading")},
+/* 0632 UNO_NAME_BACK_GRAPHIC_TRANSPARENCY*/ {MAP_CHAR_LEN("BackGraphicTransparency")},
+/* 0633 UNO_NAME_BACK_COLOR_R_G_B */ {MAP_CHAR_LEN("BackColorRGB")},
+/* 0634 UNO_NAME_BACK_COLOR_TRANSPARENCY */ {MAP_CHAR_LEN("BackColorTransparency")},
+/* 0635 UNO_NAME_HEADER_DYNAMIC_SPACING */ {MAP_CHAR_LEN("HeaderDynamicSpacing")},
+/* 0636 UNO_NAME_FOOTER_DYNAMIC_SPACING */ {MAP_CHAR_LEN("FooterDynamicSpacing")},
+/* 0637 UNO_NAME_BASIC_LIBRARIES */ {MAP_CHAR_LEN("BasicLibraries")},
+/* 0638 UNO_NAME_IS_FIXED_LANGUAGE */ {MAP_CHAR_LEN("IsFixedLanguage")},
+/* 0639 UNO_NAME_SELECTION */ {MAP_CHAR_LEN("Selection")},
+/* 0640 UNO_NAME_RESULT_SET */ {MAP_CHAR_LEN("ResultSet")},
+/* 0641 UNO_NAME_CONNECTION */ {MAP_CHAR_LEN("ActiveConnection")},
+/* 0642 UNO_NAME_MODEL */ {MAP_CHAR_LEN("Model")},
+/* 0643 UNO_NAME_DATA_SOURCE_NAME */ {MAP_CHAR_LEN("DataSourceName")},
+/* 0644 UNO_NAME_DATA_COMMAND */ {MAP_CHAR_LEN("DataCommand")},
+/* 0645 UNO_NAME_FILTER */ {MAP_CHAR_LEN("Filter")},
+/* 0646 UNO_NAME_DOCUMENT_URL */ {MAP_CHAR_LEN("DocumentURL")},
+/* 0647 UNO_NAME_OUTPUT_URL */ {MAP_CHAR_LEN("OutputURL")},
+/* 0648 UNO_NAME_OUTPUT_TYPE */ {MAP_CHAR_LEN("OutputType")},
+/* 0649 UNO_NAME_ESCAPE_PROCESSING */ {MAP_CHAR_LEN("EscapeProcessing")},
+/* 0650 UNO_NAME_SINGLE_PRINT_JOBS */ {MAP_CHAR_LEN("SinglePrintJobs")},
+/* 0651 UNO_NAME_FILE_NAME_FROM_COLUMN */ {MAP_CHAR_LEN("FileNameFromColumn")},
+/* 0652 UNO_NAME_FILE_NAME_PREFIX */ {MAP_CHAR_LEN("FileNamePrefix")},
+/* 0653 UNO_NAME_CHAR_STYLE_NAMES */ {MAP_CHAR_LEN("CharStyleNames")},
+/* 0654 UNO_NAME_DAD_COMMAND */ {MAP_CHAR_LEN("Command")},
+/* 0655 UNO_NAME_DAD_COMMAND_TYPE */ {MAP_CHAR_LEN("CommandType")},
+/* 0656 UNO_NAME_CLSID*/ {MAP_CHAR_LEN("CLSID")},
+/* 0657 UNO_NAME_COMPONENT*/ {MAP_CHAR_LEN("Component")},
+/* 0658 UNO_NAME_SECT_LEFT_MARGIN*/ {MAP_CHAR_LEN("SectionLeftMargin")},
+/* 0659 UNO_NAME_SECT_RIGHT_MARGIN*/ {MAP_CHAR_LEN("SectionRightMargin")},
+/* 0660 UNO_NAME_PARA_IS_CONNECT_BORDER */{MAP_CHAR_LEN("ParaIsConnectBorder")},
+/* 0661 UNO_NAME_ITEMS*/ {MAP_CHAR_LEN("Items")},
+/* 0662 UNO_NAME_SELITEM*/ {MAP_CHAR_LEN("SelectedItem")},
+/* 0663 UNO_NAME_IS_SPLIT_ALLOWED*/ {MAP_CHAR_LEN("IsSplitAllowed")},
+/* 0664 UNO_NAME_CHAR_HIDDEN*/ {MAP_CHAR_LEN("CharHidden")},
+/* 0665 UNO_NAME_IS_FOLLOWING_TEXT_FLOW*/ {MAP_CHAR_LEN("IsFollowingTextFlow")},
+/* 0666 UNO_NAME_WIDTH_TYPE*/ {MAP_CHAR_LEN("WidthType")},
+/* 0667 UNO_NAME_SCRIPT_URL */ {MAP_CHAR_LEN("ScriptURL")},
+/* 0668 UNO_NAME_RUNTIME_UID*/ {MAP_CHAR_LEN("RuntimeUID")},
+/* 0669 UNO_NAME_COLLAPSING_BORDERS*/ {MAP_CHAR_LEN("CollapsingBorders")},
+/* 0670 UNO_NAME_WRAP_INFLUENCE_ON_POSITION*/ {MAP_CHAR_LEN("WrapInfluenceOnPosition")},
+/* 0671 DATA_BASE_URL */ {MAP_CHAR_LEN("DataBaseURL")},
+/* 0672 DATA_BASE_RESOURCE */ {MAP_CHAR_LEN("DataBaseResource")},
+/* 0673 UNO_NAME_TRANSFORMATION_IN_HORI_L2R*/ {MAP_CHAR_LEN("TransformationInHoriL2R")},
+/* 0674 UNO_NAME_POSITION_LAYOUT_DIR*/ {MAP_CHAR_LEN("PositionLayoutDir")},
+/* 0675 UNO_NAME_NUMBERING_IS_OUTLINE*/ {MAP_CHAR_LEN("NumberingIsOutline")},
+///* 0676 UNO_NAME_DEFAULT_OUTLINE_LEVEL*/ {MAP_CHAR_LEN("DefaultOutlineLevel")}, //#outline level,removed by zhaojianwei
+/* 0677 UNO_NAME_STARTPOSITION_IN_HORI_L2R*/ {MAP_CHAR_LEN("StartPositionInHoriL2R")},
+/* 0678 UNO_NAME_ENDPOSITION_IN_HORI_L2R*/ {MAP_CHAR_LEN("EndPositionInHoriL2R")},
+/* 0679 UNO_NAME_SUBJECT */ {MAP_CHAR_LEN("Subject")},
+/* 0680 UNO_NAME_ADDRESS_FROM_COLUMN */ {MAP_CHAR_LEN("AddressFromColumn")},
+/* 0681 UNO_NAME_SEND_AS_HTML */ {MAP_CHAR_LEN("SendAsHTML")},
+/* 0682 UNO_NAME_SEND_AS_ATTACHMENT */ {MAP_CHAR_LEN("SendAsAttachment")},
+/* 0683 UNO_NAME_MAIL_BODY */ {MAP_CHAR_LEN("MailBody")},
+/* 0684 UNO_NAME_ATTACHMENT_NAME */ {MAP_CHAR_LEN("AttachmentName")},
+/* 0685 UNO_NAME_ATTACHMENT_FILTER */ {MAP_CHAR_LEN("AttachmentFilter")},
+/* 0686 UNO_NAME_PRINT_OPTIONS */ {MAP_CHAR_LEN("PrintOptions")},
+/* 0687 UNO_NAME_SAVE_AS_SINGLE_FILE */ {MAP_CHAR_LEN("SaveAsSingleFile")},
+/* 0688 UNO_NAME_SAVE_FILTER */ {MAP_CHAR_LEN("SaveFilter")},
+/* 0689 UNO_NAME_COPIES_TO */ {MAP_CHAR_LEN("CopiesTo")},
+/* 0690 UNO_NAME_BLIND_COPIES_TO */ {MAP_CHAR_LEN("BlindCopiesTo")},
+/* 0691 UNO_NAME_IN_SERVER_PASSWORD */ {MAP_CHAR_LEN("InServerPassword")},
+/* 0692 UNO_NAME_OUT_SERVER_PASSWORD */ {MAP_CHAR_LEN("OutServerPassword")},
+/* 0693 UNO_NAME_SAVE_FILTER_OPTIONS */ {MAP_CHAR_LEN("SaveFilterOptions")},
+/* 0694 UNO_NAME_SAVE_FILTER_DATA */ {MAP_CHAR_LEN("SaveFilterData")},
+/* 0695 UNO_NAME_LOCK_UPDATES */ {MAP_CHAR_LEN("LockUpdates")},
+/* 0696 UNO_NAME_PAGE_COUNT*/ {MAP_CHAR_LEN("PageCount")},
+/* 0697 UNO_NAME_LINE_COUNT*/ {MAP_CHAR_LEN("LineCount")},
+/* 0698 UNO_NAME_IS_CONSTANT_SPELLCHECK*/ {MAP_CHAR_LEN("IsConstantSpellcheck")},
+/* 0699 UNO_NAME_IS_HIDE_SPELL_MARKS*/ {MAP_CHAR_LEN("IsHideSpellMarks")}, /* deprecated #i91949 */
+/* 0700 UNO_NAME_IS_FIELD_USED */ {MAP_CHAR_LEN("IsFieldUsed")},
+/* 0701 UNO_NAME_IS_FIELD_DISPLAYED */ {MAP_CHAR_LEN("IsFieldDisplayed")},
+/* 0702 UNO_NAME_BUILDID */ {MAP_CHAR_LEN("BuildId")},
+/* 0703 UNO_NAME_PARA_STYLE_CONDITIONS*/ {MAP_CHAR_LEN("ParaStyleConditions")},
+/* 0704 UNO_NAME_PRINT_EMPTY_PAGES*/ {MAP_CHAR_LEN("PrintEmptyPages")},
+/* 0705 UNO_NAME_ROLE */ {MAP_CHAR_LEN("Role")},
+/* 0706 UNO_NAME_FIELD_CODE*/ {MAP_CHAR_LEN("FieldCode")},
+/* 0707 UNO_NAME_HAS_VALID_SIGNATURES*/ {MAP_CHAR_LEN("HasValidSignatures")},
+/* 0708 UNO_CHAR_AUTO_STYLE_NAME */ {MAP_CHAR_LEN("CharAutoStyleName")},
+/* 0709 UNO_PARA_AUTO_STYLE_NAME */ {MAP_CHAR_LEN("ParaAutoStyleName")},
+/* 0710 UNO_NAME_APPLY_WORKAROUND_FOR_B6375613*/ {MAP_CHAR_LEN("ApplyWorkaroundForB6375613")},
+/* 0711 UNO_NAME_LAYOUT_SIZE*/ {MAP_CHAR_LEN("LayoutSize")},
+/* 0712 UNO_NAME_HELP */ {MAP_CHAR_LEN("Help")},
+/* 0713 UNO_NAME_TOOLTIP */ {MAP_CHAR_LEN("Tooltip")},
+/* 0714 UNO_NAME_DIALOG_LIBRARIES*/ {MAP_CHAR_LEN("DialogLibraries")},
+/* 0715 UNO_NAME_HEADER_ROW_COUNT*/ {MAP_CHAR_LEN("HeaderRowCount")},
+/* 0716 UNO_NAME_INPUT */ {MAP_CHAR_LEN("Input")},
+/* 0717 UNO_NAME_ROW_SPAN */ {MAP_CHAR_LEN("RowSpan")},
+/* 0718 UNO_NAME_POSITION_AND_SPACE_MODE */ {MAP_CHAR_LEN("PositionAndSpaceMode")},
+/* 0719 UNO_NAME_LABEL_FOLLOWED_BY */ {MAP_CHAR_LEN("LabelFollowedBy")},
+/* 0720 UNO_NAME_LISTTAB_STOP_POSITION */ {MAP_CHAR_LEN("ListtabStopPosition")},
+/* 0721 UNO_NAME_FIRST_LINE_INDENT */ {MAP_CHAR_LEN("FirstLineIndent")},
+/* 0722 UNO_NAME_INDENT_AT */ {MAP_CHAR_LEN("IndentAt")},
+/* 0723 UNO_NAME_CHAPTER_LEVEL */ {MAP_CHAR_LEN("ChapterLevel")},
+/* 0724 UNO_NAME_GRID_BASE_WIDTH*/ {MAP_CHAR_LEN("GridBaseWidth")},
+/* 0725 UNO_NAME_GRID_SNAP_TO_CHARS*/ {MAP_CHAR_LEN("GridSnapToChars")},
+/* 0726 UNO_NAME_GRID_STANDARD_PAGE_MODE*/ {MAP_CHAR_LEN("StandardPageMode")},
+/* 0727 UNO_NAME_TABLE_BORDER_DISTANCES */ {MAP_CHAR_LEN("TableBorderDistances")},
+/* 0728 UNO_NAME_LIST_ID*/ {MAP_CHAR_LEN("ListId")},
+/* 0729 UNO_NAME_DEFAULT_LIST_ID*/ {MAP_CHAR_LEN("DefaultListId")},
+/* 0730 UNO_NAME_STREAM_NAME */ {MAP_CHAR_LEN("StreamName")},
+/* 0731 UNO_NAME_PARA_CONTINUEING_PREVIOUS_SUB_TREE */ {MAP_CHAR_LEN("ContinueingPreviousSubTree")},
+/* 0732 UNO_NAME_PARA_LIST_LABEL_STRING */ {MAP_CHAR_LEN("ListLabelString")},
+/* 0733 CHAR_OVERLINE */ {MAP_CHAR_LEN("CharOverline")},
+/* 0734 CHAR_OVERLINE_COLOR */ {MAP_CHAR_LEN("CharOverlineColor")},
+/* 0735 CHAR_OVERLINE_HAS_COLOR */ {MAP_CHAR_LEN("CharOverlineHasColor")},
+/* 0736 UNO_NAME_OUTLINE_LEVEL */ {MAP_CHAR_LEN("OutlineLevel")},//#outline level,add<-zhaojianwei Outlinelevel
+/* 0737 UNO_NAME_DESCRIPTION */ {MAP_CHAR_LEN("Description")},
+/* 0738 UNO_NAME_META */ {MAP_CHAR_LEN("InContentMetadata")},
+// FIXME: these numbers are not correct post merge ...
+/* 0739 UNO_NAME_IS_TEMPLATE */ {MAP_CHAR_LEN("IsTemplate")},
+/* 0740 UNO_NAME_EMBEDDED_OBJECT */ {MAP_CHAR_LEN("EmbeddedObject")},
+/* 0740 UNO_NAME_VBA_DOCOBJ */ {MAP_CHAR_LEN("ThisVBADocObj")},
+
+/* 0741 UNO_NAME_NESTED_TEXT_CONTENT */ {MAP_CHAR_LEN("NestedTextContent")},
+/* 0742 UNO_NAME_SEPARATOR_LINE_STYLE */ {MAP_CHAR_LEN("SeparatorLineStyle")},
+/* 0743 UNO_NAME_FOOTNOTE_LINE_STYLE */ {MAP_CHAR_LEN("FootnoteLineStyle")},
+};
+
+const SwPropNameLen& SwGetPropName( sal_uInt16 nId )
+{
+ return GetPropName( nId );
+}
+const SwPropNameLen& GetPropName( sal_uInt16 nId )
+{
+ DBG_ASSERT( SW_PROPNAME_BEGIN <= nId && nId < SW_PROPNAME_END,
+ "GetPropName(): Wrong index" );
+ return aPropNameTab[ nId - SW_PROPNAME_BEGIN];
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/unocore/unoredline.cxx b/sw/source/core/unocore/unoredline.cxx
new file mode 100644
index 000000000000..755afab2e653
--- /dev/null
+++ b/sw/source/core/unocore/unoredline.cxx
@@ -0,0 +1,687 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+#include <com/sun/star/util/DateTime.hpp>
+#include <com/sun/star/text/XTextTable.hpp>
+
+#include <rtl/ustrbuf.hxx>
+#include <osl/mutex.hxx>
+#include <vcl/svapp.hxx>
+
+#include <pagedesc.hxx>
+#include "poolfmt.hxx"
+#include <redline.hxx>
+#include <section.hxx>
+#include <unoprnms.hxx>
+#include <unomid.h>
+#include <unotextrange.hxx>
+#include <unotextcursor.hxx>
+#include <unoparagraph.hxx>
+#include <unocoll.hxx>
+#include <unomap.hxx>
+#include <unocrsr.hxx>
+#include <unoredline.hxx>
+#include <doc.hxx>
+#include <docary.hxx>
+
+
+using namespace ::com::sun::star;
+using ::rtl::OUString;
+using ::rtl::OUStringBuffer;
+
+SwXRedlineText::SwXRedlineText(SwDoc* _pDoc, SwNodeIndex aIndex) :
+ SwXText(_pDoc, CURSOR_REDLINE),
+ aNodeIndex(aIndex)
+{
+}
+
+const SwStartNode* SwXRedlineText::GetStartNode() const
+{
+ return aNodeIndex.GetNode().GetStartNode();
+}
+
+uno::Any SwXRedlineText::queryInterface( const uno::Type& rType )
+ throw(uno::RuntimeException)
+{
+ uno::Any aRet;
+
+ if (::getCppuType((uno::Reference<container::XEnumerationAccess> *)0) == rType)
+ {
+ uno::Reference<container::XEnumerationAccess> aAccess = this;
+ aRet <<= aAccess;
+ }
+ else
+ {
+ // delegate to SwXText and OWeakObject
+ aRet = SwXText::queryInterface(rType);
+ if(!aRet.hasValue())
+ {
+ aRet = OWeakObject::queryInterface(rType);
+ }
+ }
+
+ return aRet;
+}
+
+uno::Sequence<uno::Type> SwXRedlineText::getTypes()
+ throw(uno::RuntimeException)
+{
+ // SwXText::getTypes()
+ uno::Sequence<uno::Type> aTypes = SwXText::getTypes();
+
+ // add container::XEnumerationAccess
+ sal_Int32 nLength = aTypes.getLength();
+ aTypes.realloc(nLength + 1);
+ aTypes[nLength] = ::getCppuType((uno::Reference<container::XEnumerationAccess> *)0);
+
+ return aTypes;
+}
+
+uno::Sequence<sal_Int8> SwXRedlineText::getImplementationId()
+ throw(uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+ static uno::Sequence< sal_Int8 > aId( 16 );
+ static sal_Bool bInit = sal_False;
+ if(!bInit)
+ {
+ rtl_createUuid( (sal_uInt8 *)(aId.getArray() ), 0, sal_True );
+ bInit = sal_True;
+ }
+ return aId;
+}
+
+uno::Reference<text::XTextCursor> SwXRedlineText::createTextCursor(void)
+ throw( uno::RuntimeException )
+{
+ SolarMutexGuard aGuard;
+
+ SwPosition aPos(aNodeIndex);
+ SwXTextCursor *const pXCursor =
+ new SwXTextCursor(*GetDoc(), this, CURSOR_REDLINE, aPos);
+ SwUnoCrsr *const pUnoCursor = pXCursor->GetCursor();
+ pUnoCursor->Move(fnMoveForward, fnGoNode);
+
+ // #101929# prevent a newly created text cursor from running inside a table
+ // because table cells have their own XText.
+ // Patterned after SwXTextFrame::createTextCursor(void).
+
+ // skip all tables at the beginning
+ SwTableNode* pTableNode = pUnoCursor->GetNode()->FindTableNode();
+ SwCntntNode* pContentNode = NULL;
+ bool bTable = pTableNode != NULL;
+ while( pTableNode != NULL )
+ {
+ pUnoCursor->GetPoint()->nNode = *(pTableNode->EndOfSectionNode());
+ pContentNode = GetDoc()->GetNodes().GoNext(&pUnoCursor->GetPoint()->nNode);
+ pTableNode = pContentNode->FindTableNode();
+ }
+ if( pContentNode != NULL )
+ pUnoCursor->GetPoint()->nContent.Assign( pContentNode, 0 );
+ if( bTable && pUnoCursor->GetNode()->FindSttNodeByType( SwNormalStartNode )
+ != GetStartNode() )
+ {
+ // We have gone too far and have left our own redline. This means that
+ // no content node outside of a table could be found, and therefore we
+ // except.
+ uno::RuntimeException aExcept;
+ aExcept.Message = OUString( RTL_CONSTASCII_USTRINGPARAM(
+ "No content node found that is inside this change section "
+ "but outside of a table" ) );
+ throw aExcept;
+ }
+
+ return static_cast<text::XWordCursor*>(pXCursor);
+}
+
+uno::Reference<text::XTextCursor> SwXRedlineText::createTextCursorByRange(
+ const uno::Reference<text::XTextRange> & aTextRange)
+ throw( uno::RuntimeException )
+{
+ uno::Reference<text::XTextCursor> xCursor = createTextCursor();
+ xCursor->gotoRange(aTextRange->getStart(), sal_False);
+ xCursor->gotoRange(aTextRange->getEnd(), sal_True);
+ return xCursor;
+}
+
+uno::Reference<container::XEnumeration> SwXRedlineText::createEnumeration(void)
+ throw( uno::RuntimeException )
+{
+ SolarMutexGuard aGuard;
+ SwPaM aPam(aNodeIndex);
+ aPam.Move(fnMoveForward, fnGoNode);
+ ::std::auto_ptr<SwUnoCrsr> pUnoCursor(
+ GetDoc()->CreateUnoCrsr(*aPam.Start(), sal_False));
+ return new SwXParagraphEnumeration(this, pUnoCursor, CURSOR_REDLINE);
+}
+
+uno::Type SwXRedlineText::getElementType( ) throw(uno::RuntimeException)
+{
+ return ::getCppuType((uno::Reference<text::XTextRange>*)0);
+}
+
+sal_Bool SwXRedlineText::hasElements( ) throw(uno::RuntimeException)
+{
+ return sal_True; // we always have a content index
+}
+
+SwXRedlinePortion::SwXRedlinePortion( const SwRedline* pRed,
+ const SwUnoCrsr* pPortionCrsr,
+ uno::Reference< text::XText > xParent, sal_Bool bStart) :
+ SwXTextPortion(pPortionCrsr, xParent, bStart ? PORTION_REDLINE_START : PORTION_REDLINE_END),
+ pRedline(pRed)
+{
+ SetCollapsed(!pRedline->HasMark());
+}
+
+SwXRedlinePortion::~SwXRedlinePortion()
+{
+}
+
+static util::DateTime lcl_DateTimeToUno(const DateTime& rDT)
+{
+ util::DateTime aRetDT;
+ aRetDT.Year = rDT.GetYear();
+ aRetDT.Month= rDT.GetMonth();
+ aRetDT.Day = rDT.GetDay();
+ aRetDT.Hours = rDT.GetHour();
+ aRetDT.Minutes = rDT.GetMin();
+ aRetDT.Seconds = rDT.GetSec();
+ aRetDT.HundredthSeconds = rDT.Get100Sec();
+ return aRetDT;
+}
+
+static OUString lcl_RedlineTypeToOUString(RedlineType_t eType)
+{
+ OUString sRet;
+ switch(eType & nsRedlineType_t::REDLINE_NO_FLAG_MASK)
+ {
+ case nsRedlineType_t::REDLINE_INSERT: sRet = C2U("Insert"); break;
+ case nsRedlineType_t::REDLINE_DELETE: sRet = C2U("Delete"); break;
+ case nsRedlineType_t::REDLINE_FORMAT: sRet = C2U("Format"); break;
+ case nsRedlineType_t::REDLINE_TABLE: sRet = C2U("TextTable"); break;
+ case nsRedlineType_t::REDLINE_FMTCOLL:sRet = C2U("Style"); break;
+ }
+ return sRet;
+}
+
+static uno::Sequence<beans::PropertyValue> lcl_GetSuccessorProperties(const SwRedline& rRedline)
+{
+ uno::Sequence<beans::PropertyValue> aValues(4);
+
+ const SwRedlineData* pNext = rRedline.GetRedlineData().Next();
+ if(pNext)
+ {
+ beans::PropertyValue* pValues = aValues.getArray();
+ pValues[0].Name = rtl::OUString::createFromAscii(SW_PROP_NAME_STR(UNO_NAME_REDLINE_AUTHOR));
+ // GetAuthorString(n) walks the SwRedlineData* chain;
+ // here we always need element 1
+ pValues[0].Value <<= OUString(rRedline.GetAuthorString(1));
+ pValues[1].Name = rtl::OUString::createFromAscii(SW_PROP_NAME_STR(UNO_NAME_REDLINE_DATE_TIME));
+ pValues[1].Value <<= lcl_DateTimeToUno(pNext->GetTimeStamp());
+ pValues[2].Name = rtl::OUString::createFromAscii(SW_PROP_NAME_STR(UNO_NAME_REDLINE_COMMENT));
+ pValues[2].Value <<= OUString(pNext->GetComment());
+ pValues[3].Name = rtl::OUString::createFromAscii(SW_PROP_NAME_STR(UNO_NAME_REDLINE_TYPE));
+ pValues[3].Value <<= lcl_RedlineTypeToOUString(pNext->GetType());
+ }
+ return aValues;
+}
+
+uno::Any SwXRedlinePortion::getPropertyValue( const OUString& rPropertyName )
+ throw(beans::UnknownPropertyException, lang::WrappedTargetException, uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+ Validate();
+ uno::Any aRet;
+ if(rPropertyName.equalsAsciiL(SW_PROP_NAME(UNO_NAME_REDLINE_TEXT)))
+ {
+ SwNodeIndex* pNodeIdx = pRedline->GetContentIdx();
+ if(pNodeIdx )
+ {
+ if ( 1 < ( pNodeIdx->GetNode().EndOfSectionIndex() - pNodeIdx->GetNode().GetIndex() ) )
+ {
+ SwUnoCrsr* pUnoCrsr = GetCursor();
+ uno::Reference<text::XText> xRet = new SwXRedlineText(pUnoCrsr->GetDoc(), *pNodeIdx);
+ aRet <<= xRet;
+ }
+ else {
+ DBG_ASSERT(0, "Empty section in redline portion! (end node immediately follows start node)");
+ }
+ }
+ }
+ else
+ {
+ aRet = GetPropertyValue( rPropertyName, *pRedline);
+ if(!aRet.hasValue() &&
+ ! rPropertyName.equalsAsciiL(SW_PROP_NAME(UNO_NAME_REDLINE_SUCCESSOR_DATA)))
+ aRet = SwXTextPortion::getPropertyValue(rPropertyName);
+ }
+ return aRet;
+}
+
+void SwXRedlinePortion::Validate() throw( uno::RuntimeException )
+{
+ SwUnoCrsr* pUnoCrsr = GetCursor();
+ if(!pUnoCrsr)
+ throw uno::RuntimeException();
+ //search for the redline
+ SwDoc* pDoc = pUnoCrsr->GetDoc();
+ const SwRedlineTbl& rRedTbl = pDoc->GetRedlineTbl();
+ sal_Bool bFound = sal_False;
+ for(sal_uInt16 nRed = 0; nRed < rRedTbl.Count() && !bFound; nRed++)
+ bFound = pRedline == rRedTbl[nRed];
+ if(!bFound)
+ throw uno::RuntimeException();
+}
+
+uno::Sequence< sal_Int8 > SAL_CALL SwXRedlinePortion::getImplementationId( ) throw(uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+ static uno::Sequence< sal_Int8 > aId( 16 );
+ static sal_Bool bInit = sal_False;
+ if(!bInit)
+ {
+ rtl_createUuid( (sal_uInt8 *)(aId.getArray() ), 0, sal_True );
+ bInit = sal_True;
+ }
+ return aId;
+}
+
+uno::Any SwXRedlinePortion::GetPropertyValue( const OUString& rPropertyName, const SwRedline& rRedline ) throw()
+{
+ uno::Any aRet;
+ if(rPropertyName.equalsAsciiL(SW_PROP_NAME(UNO_NAME_REDLINE_AUTHOR)))
+ aRet <<= OUString(rRedline.GetAuthorString());
+ else if(rPropertyName.equalsAsciiL(SW_PROP_NAME(UNO_NAME_REDLINE_DATE_TIME)))
+ {
+ aRet <<= lcl_DateTimeToUno(rRedline.GetTimeStamp());
+ }
+ else if(rPropertyName.equalsAsciiL(SW_PROP_NAME(UNO_NAME_REDLINE_COMMENT)))
+ aRet <<= OUString(rRedline.GetComment());
+ else if(rPropertyName.equalsAsciiL(SW_PROP_NAME(UNO_NAME_REDLINE_TYPE)))
+ {
+ aRet <<= lcl_RedlineTypeToOUString(rRedline.GetType());
+ }
+ else if(rPropertyName.equalsAsciiL(SW_PROP_NAME(UNO_NAME_REDLINE_SUCCESSOR_DATA)))
+ {
+ if(rRedline.GetRedlineData().Next())
+ aRet <<= lcl_GetSuccessorProperties(rRedline);
+ }
+ else if (rPropertyName.equalsAsciiL(SW_PROP_NAME(UNO_NAME_REDLINE_IDENTIFIER)))
+ {
+ OUStringBuffer sBuf;
+ sBuf.append( sal::static_int_cast< sal_Int64 >( reinterpret_cast< sal_IntPtr >(&rRedline) ) );
+ aRet <<= sBuf.makeStringAndClear();
+ }
+ else if (rPropertyName.equalsAsciiL(SW_PROP_NAME(UNO_NAME_IS_IN_HEADER_FOOTER)))
+ {
+ sal_Bool bRet =
+ rRedline.GetDoc()->IsInHeaderFooter( rRedline.GetPoint()->nNode );
+ aRet.setValue(&bRet, ::getBooleanCppuType());
+ }
+ else if (rPropertyName.equalsAsciiL(SW_PROP_NAME(UNO_NAME_MERGE_LAST_PARA)))
+ {
+ sal_Bool bRet = !rRedline.IsDelLastPara();
+ aRet.setValue( &bRet, ::getBooleanCppuType() );
+ }
+ return aRet;
+}
+
+uno::Sequence< beans::PropertyValue > SwXRedlinePortion::CreateRedlineProperties(
+ const SwRedline& rRedline, sal_Bool bIsStart ) throw()
+{
+ uno::Sequence< beans::PropertyValue > aRet(11);
+ const SwRedlineData* pNext = rRedline.GetRedlineData().Next();
+ beans::PropertyValue* pRet = aRet.getArray();
+
+ OUStringBuffer sRedlineIdBuf;
+ sRedlineIdBuf.append( sal::static_int_cast< sal_Int64 >( reinterpret_cast< sal_IntPtr >(&rRedline) ) );
+
+ sal_Int32 nPropIdx = 0;
+ pRet[nPropIdx].Name = rtl::OUString::createFromAscii(SW_PROP_NAME_STR(UNO_NAME_REDLINE_AUTHOR));
+ pRet[nPropIdx++].Value <<= OUString(rRedline.GetAuthorString());
+ pRet[nPropIdx].Name = rtl::OUString::createFromAscii(SW_PROP_NAME_STR(UNO_NAME_REDLINE_DATE_TIME));
+ pRet[nPropIdx++].Value <<= lcl_DateTimeToUno(rRedline.GetTimeStamp());
+ pRet[nPropIdx].Name = rtl::OUString::createFromAscii(SW_PROP_NAME_STR(UNO_NAME_REDLINE_COMMENT));
+ pRet[nPropIdx++].Value <<= OUString(rRedline.GetComment());
+ pRet[nPropIdx].Name = rtl::OUString::createFromAscii(SW_PROP_NAME_STR(UNO_NAME_REDLINE_TYPE));
+ pRet[nPropIdx++].Value <<= lcl_RedlineTypeToOUString(rRedline.GetType());
+ pRet[nPropIdx].Name = rtl::OUString::createFromAscii(SW_PROP_NAME_STR(UNO_NAME_REDLINE_IDENTIFIER));
+ pRet[nPropIdx++].Value <<= sRedlineIdBuf.makeStringAndClear();
+ pRet[nPropIdx].Name = rtl::OUString::createFromAscii(SW_PROP_NAME_STR(UNO_NAME_IS_COLLAPSED));
+ sal_Bool bTmp = !rRedline.HasMark();
+ pRet[nPropIdx++].Value.setValue(&bTmp, ::getBooleanCppuType()) ;
+
+ pRet[nPropIdx].Name = rtl::OUString::createFromAscii(SW_PROP_NAME_STR(UNO_NAME_IS_START));
+ pRet[nPropIdx++].Value.setValue(&bIsStart, ::getBooleanCppuType()) ;
+
+ bTmp = !rRedline.IsDelLastPara();
+ pRet[nPropIdx].Name = rtl::OUString::createFromAscii(SW_PROP_NAME_STR(UNO_NAME_MERGE_LAST_PARA));
+ pRet[nPropIdx++].Value.setValue(&bTmp, ::getBooleanCppuType()) ;
+
+ SwNodeIndex* pNodeIdx = rRedline.GetContentIdx();
+ if(pNodeIdx )
+ {
+ if ( 1 < ( pNodeIdx->GetNode().EndOfSectionIndex() - pNodeIdx->GetNode().GetIndex() ) )
+ {
+ uno::Reference<text::XText> xRet = new SwXRedlineText(rRedline.GetDoc(), *pNodeIdx);
+ pRet[nPropIdx].Name = rtl::OUString::createFromAscii(SW_PROP_NAME_STR(UNO_NAME_REDLINE_TEXT));
+ pRet[nPropIdx++].Value <<= xRet;
+ }
+ else {
+ DBG_ASSERT(0, "Empty section in redline portion! (end node immediately follows start node)");
+ }
+ }
+ if(pNext)
+ {
+ pRet[nPropIdx].Name = rtl::OUString::createFromAscii(SW_PROP_NAME_STR(UNO_NAME_REDLINE_SUCCESSOR_DATA));
+ pRet[nPropIdx++].Value <<= lcl_GetSuccessorProperties(rRedline);
+ }
+ aRet.realloc(nPropIdx);
+ return aRet;
+}
+
+TYPEINIT1(SwXRedline, SwClient);
+SwXRedline::SwXRedline(SwRedline& rRedline, SwDoc& rDoc) :
+ SwXText(&rDoc, CURSOR_REDLINE),
+ pDoc(&rDoc),
+ pRedline(&rRedline)
+{
+ pDoc->GetPageDescFromPool(RES_POOLPAGE_STANDARD)->Add(this);
+}
+
+SwXRedline::~SwXRedline()
+{
+}
+
+uno::Reference< beans::XPropertySetInfo > SwXRedline::getPropertySetInfo( ) throw(uno::RuntimeException)
+{
+ static uno::Reference< beans::XPropertySetInfo > xRef =
+ aSwMapProvider.GetPropertySet(PROPERTY_MAP_REDLINE)->getPropertySetInfo();
+ return xRef;
+}
+
+void SwXRedline::setPropertyValue( const OUString& rPropertyName, const uno::Any& aValue )
+ throw(beans::UnknownPropertyException, beans::PropertyVetoException, lang::IllegalArgumentException,
+ lang::WrappedTargetException, uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+ if(!pDoc)
+ throw uno::RuntimeException();
+ if(rPropertyName.equalsAsciiL(SW_PROP_NAME(UNO_NAME_REDLINE_AUTHOR)))
+ {
+ OSL_FAIL("currently not available");
+ }
+ else if(rPropertyName.equalsAsciiL(SW_PROP_NAME(UNO_NAME_REDLINE_DATE_TIME)))
+ {
+ OSL_FAIL("currently not available");
+ }
+ else if(rPropertyName.equalsAsciiL(SW_PROP_NAME(UNO_NAME_REDLINE_COMMENT)))
+ {
+ OUString sTmp; aValue >>= sTmp;
+ pRedline->SetComment(sTmp);
+ }
+ else if(rPropertyName.equalsAsciiL(SW_PROP_NAME(UNO_NAME_REDLINE_TYPE)))
+ {
+ OSL_FAIL("currently not available");
+ OUString sTmp; aValue >>= sTmp;
+ if(!sTmp.getLength())
+ throw lang::IllegalArgumentException();
+ }
+ else if(rPropertyName.equalsAsciiL(SW_PROP_NAME(UNO_NAME_REDLINE_SUCCESSOR_DATA)))
+ {
+ OSL_FAIL("currently not available");
+ }
+ else
+ {
+ throw lang::IllegalArgumentException();
+ }
+}
+
+uno::Any SwXRedline::getPropertyValue( const OUString& rPropertyName )
+ throw(beans::UnknownPropertyException, lang::WrappedTargetException, uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+ if(!pDoc)
+ throw uno::RuntimeException();
+ uno::Any aRet;
+ sal_Bool bStart = rPropertyName.equalsAsciiL(SW_PROP_NAME(UNO_NAME_REDLINE_START));
+ if(bStart ||
+ rPropertyName.equalsAsciiL(SW_PROP_NAME(UNO_NAME_REDLINE_END)))
+ {
+ uno::Reference<XInterface> xRet;
+ SwNode* pNode = pRedline->GetNode();
+ if(!bStart && pRedline->HasMark())
+ pNode = pRedline->GetNode(sal_False);
+ switch(pNode->GetNodeType())
+ {
+ case ND_SECTIONNODE:
+ {
+ SwSectionNode* pSectNode = pNode->GetSectionNode();
+ DBG_ASSERT(pSectNode, "No section node!");
+ xRet = SwXTextSections::GetObject( *pSectNode->GetSection().GetFmt() );
+ }
+ break;
+ case ND_TABLENODE :
+ {
+ SwTableNode* pTblNode = pNode->GetTableNode();
+ DBG_ASSERT(pTblNode, "No table node!");
+ SwTable& rTbl = pTblNode->GetTable();
+ SwFrmFmt* pTblFmt = rTbl.GetFrmFmt();
+ xRet = SwXTextTables::GetObject( *pTblFmt );
+ }
+ break;
+ case ND_TEXTNODE :
+ {
+ SwPosition* pPoint = 0;
+ if(bStart || !pRedline->HasMark())
+ pPoint = pRedline->GetPoint();
+ else
+ pPoint = pRedline->GetMark();
+ const uno::Reference<text::XTextRange> xRange =
+ SwXTextRange::CreateXTextRange(*pDoc, *pPoint, 0);
+ xRet = xRange.get();
+ }
+ break;
+ default:
+ OSL_FAIL("illegal node type");
+ }
+ aRet <<= xRet;
+ }
+ else if(rPropertyName.equalsAsciiL(SW_PROP_NAME(UNO_NAME_REDLINE_TEXT)))
+ {
+ SwNodeIndex* pNodeIdx = pRedline->GetContentIdx();
+ if( pNodeIdx )
+ {
+ if ( 1 < ( pNodeIdx->GetNode().EndOfSectionIndex() - pNodeIdx->GetNode().GetIndex() ) )
+ {
+ uno::Reference<text::XText> xRet = new SwXRedlineText(pDoc, *pNodeIdx);
+ aRet <<= xRet;
+ }
+ else {
+ DBG_ASSERT(0, "Empty section in redline portion! (end node immediately follows start node)");
+ }
+ }
+ }
+ else
+ aRet = SwXRedlinePortion::GetPropertyValue(rPropertyName, *pRedline);
+ return aRet;
+}
+
+void SwXRedline::addPropertyChangeListener(
+ const OUString& /*aPropertyName*/,
+ const uno::Reference< beans::XPropertyChangeListener >& /*xListener*/ )
+ throw(beans::UnknownPropertyException, lang::WrappedTargetException, uno::RuntimeException)
+{
+}
+
+void SwXRedline::removePropertyChangeListener(
+ const OUString& /*aPropertyName*/, const uno::Reference< beans::XPropertyChangeListener >& /*aListener*/ )
+ throw(beans::UnknownPropertyException, lang::WrappedTargetException, uno::RuntimeException)
+{
+}
+
+void SwXRedline::addVetoableChangeListener(
+ const OUString& /*PropertyName*/, const uno::Reference< beans::XVetoableChangeListener >& /*aListener*/ )
+ throw(beans::UnknownPropertyException, lang::WrappedTargetException, uno::RuntimeException)
+{
+}
+
+void SwXRedline::removeVetoableChangeListener(
+ const OUString& /*PropertyName*/, const uno::Reference< beans::XVetoableChangeListener >& /*aListener*/ )
+ throw(beans::UnknownPropertyException, lang::WrappedTargetException, uno::RuntimeException)
+{
+}
+
+void SwXRedline::Modify( const SfxPoolItem* pOld, const SfxPoolItem *pNew)
+{
+ ClientModify(this, pOld, pNew);
+ if(!GetRegisteredIn())
+ {
+ pDoc = 0;
+ pRedline = 0;
+ }
+}
+
+uno::Reference< container::XEnumeration > SwXRedline::createEnumeration(void) throw( uno::RuntimeException )
+{
+ SolarMutexGuard aGuard;
+ uno::Reference< container::XEnumeration > xRet;
+ if(!pDoc)
+ throw uno::RuntimeException();
+
+ SwNodeIndex* pNodeIndex = pRedline->GetContentIdx();
+ if(pNodeIndex)
+ {
+ SwPaM aPam(*pNodeIndex);
+ aPam.Move(fnMoveForward, fnGoNode);
+ ::std::auto_ptr<SwUnoCrsr> pUnoCursor(
+ GetDoc()->CreateUnoCrsr(*aPam.Start(), sal_False));
+ xRet = new SwXParagraphEnumeration(this, pUnoCursor, CURSOR_REDLINE);
+ }
+ return xRet;
+}
+
+uno::Type SwXRedline::getElementType( ) throw(uno::RuntimeException)
+{
+ return ::getCppuType((uno::Reference<text::XTextRange>*)0);
+}
+
+sal_Bool SwXRedline::hasElements( ) throw(uno::RuntimeException)
+{
+ if(!pDoc)
+ throw uno::RuntimeException();
+ return 0 != pRedline->GetContentIdx();
+}
+
+uno::Reference< text::XTextCursor > SwXRedline::createTextCursor(void) throw( uno::RuntimeException )
+{
+ SolarMutexGuard aGuard;
+ if(!pDoc)
+ throw uno::RuntimeException();
+
+ uno::Reference< text::XTextCursor > xRet;
+ SwNodeIndex* pNodeIndex = pRedline->GetContentIdx();
+ if(pNodeIndex)
+ {
+ SwPosition aPos(*pNodeIndex);
+ SwXTextCursor *const pXCursor =
+ new SwXTextCursor(*pDoc, this, CURSOR_REDLINE, aPos);
+ SwUnoCrsr *const pUnoCrsr = pXCursor->GetCursor();
+ pUnoCrsr->Move(fnMoveForward, fnGoNode);
+
+ //steht hier eine Tabelle?
+ SwTableNode* pTblNode = pUnoCrsr->GetNode()->FindTableNode();
+ SwCntntNode* pCont = 0;
+ while( pTblNode )
+ {
+ pUnoCrsr->GetPoint()->nNode = *pTblNode->EndOfSectionNode();
+ pCont = GetDoc()->GetNodes().GoNext(&pUnoCrsr->GetPoint()->nNode);
+ pTblNode = pCont->FindTableNode();
+ }
+ if(pCont)
+ pUnoCrsr->GetPoint()->nContent.Assign(pCont, 0);
+ xRet = static_cast<text::XWordCursor*>(pXCursor);
+ }
+ else
+ {
+ throw uno::RuntimeException();
+ }
+ return xRet;
+}
+
+uno::Reference< text::XTextCursor > SwXRedline::createTextCursorByRange(
+ const uno::Reference< text::XTextRange > & /*aTextPosition*/)
+ throw( uno::RuntimeException )
+{
+ throw uno::RuntimeException();
+}
+
+uno::Any SwXRedline::queryInterface( const uno::Type& rType )
+ throw(uno::RuntimeException)
+{
+ uno::Any aRet = SwXText::queryInterface(rType);
+ if(!aRet.hasValue())
+ {
+ aRet = SwXRedlineBaseClass::queryInterface(rType);
+ }
+ return aRet;
+}
+
+uno::Sequence<uno::Type> SwXRedline::getTypes()
+ throw(uno::RuntimeException)
+{
+ uno::Sequence<uno::Type> aTypes = SwXText::getTypes();
+ uno::Sequence<uno::Type> aBaseTypes = SwXRedlineBaseClass::getTypes();
+ const uno::Type* pBaseTypes = aBaseTypes.getConstArray();
+ sal_Int32 nCurType = aTypes.getLength();
+ aTypes.realloc(aTypes.getLength() + aBaseTypes.getLength());
+ uno::Type* pTypes = aTypes.getArray();
+ for(sal_Int32 nType = 0; nType < aBaseTypes.getLength(); nType++)
+ pTypes[nCurType++] = pBaseTypes[nType];
+ return aTypes;
+}
+
+uno::Sequence<sal_Int8> SwXRedline::getImplementationId()
+ throw(uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+ static uno::Sequence< sal_Int8 > aId( 16 );
+ static sal_Bool bInit = sal_False;
+ if(!bInit)
+ {
+ rtl_createUuid( (sal_uInt8 *)(aId.getArray() ), 0, sal_True );
+ bInit = sal_True;
+ }
+ return aId;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/unocore/unoredlines.cxx b/sw/source/core/unocore/unoredlines.cxx
new file mode 100644
index 000000000000..d0839bf25cf2
--- /dev/null
+++ b/sw/source/core/unocore/unoredlines.cxx
@@ -0,0 +1,199 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+#include <com/sun/star/beans/XPropertySet.hpp>
+
+#include <tools/debug.hxx>
+#include <osl/mutex.hxx>
+#include <vcl/svapp.hxx>
+
+#include <unoredlines.hxx>
+#include <unoredline.hxx>
+#include <unomid.h>
+#include <pagedesc.hxx>
+#include "poolfmt.hxx"
+#include <doc.hxx>
+#include <docary.hxx>
+#include <redline.hxx>
+#include <switerator.hxx>
+
+using namespace ::com::sun::star;
+using ::rtl::OUString;
+
+SwXRedlines::SwXRedlines(SwDoc* _pDoc) :
+ SwUnoCollection(_pDoc)
+{
+}
+
+SwXRedlines::~SwXRedlines()
+{
+}
+
+sal_Int32 SwXRedlines::getCount( ) throw(uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+ if(!IsValid())
+ throw uno::RuntimeException();
+ const SwRedlineTbl& rRedTbl = GetDoc()->GetRedlineTbl();
+ return rRedTbl.Count();
+}
+
+uno::Any SwXRedlines::getByIndex(sal_Int32 nIndex)
+ throw( lang::IndexOutOfBoundsException, lang::WrappedTargetException, uno::RuntimeException )
+{
+ SolarMutexGuard aGuard;
+ if(!IsValid())
+ throw uno::RuntimeException();
+ const SwRedlineTbl& rRedTbl = GetDoc()->GetRedlineTbl();
+ uno::Any aRet;
+ if(rRedTbl.Count() > nIndex && nIndex >= 0)
+ {
+ uno::Reference <beans::XPropertySet> xRet = SwXRedlines::GetObject( *rRedTbl.GetObject((sal_uInt16)nIndex), *GetDoc() );
+ aRet <<= xRet;
+ }
+ else
+ throw lang::IndexOutOfBoundsException();
+ return aRet;
+}
+
+uno::Reference< container::XEnumeration > SwXRedlines::createEnumeration(void)
+ throw( uno::RuntimeException )
+{
+ SolarMutexGuard aGuard;
+ if(!IsValid())
+ throw uno::RuntimeException();
+ return uno::Reference< container::XEnumeration >(new SwXRedlineEnumeration(*GetDoc()));
+}
+
+uno::Type SwXRedlines::getElementType( ) throw(uno::RuntimeException)
+{
+ return ::getCppuType((uno::Reference<beans::XPropertySet>*)0);
+}
+
+sal_Bool SwXRedlines::hasElements( ) throw(uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+ if(!IsValid())
+ throw uno::RuntimeException();
+ const SwRedlineTbl& rRedTbl = GetDoc()->GetRedlineTbl();
+ return rRedTbl.Count() > 0;
+}
+
+OUString SwXRedlines::getImplementationName(void) throw( uno::RuntimeException )
+{
+ return C2U("SwXRedlines");
+}
+
+sal_Bool SwXRedlines::supportsService(const rtl::OUString& /*ServiceName*/)
+ throw( uno::RuntimeException )
+{
+ OSL_FAIL("not implemented");
+ return sal_False;
+}
+
+uno::Sequence< OUString > SwXRedlines::getSupportedServiceNames(void)
+ throw( uno::RuntimeException )
+{
+ OSL_FAIL("not implemented");
+ return uno::Sequence< OUString >();
+}
+
+beans::XPropertySet* SwXRedlines::GetObject( SwRedline& rRedline, SwDoc& rDoc )
+{
+ SwPageDesc* pStdDesc = rDoc.GetPageDescFromPool(RES_POOLPAGE_STANDARD);
+ SwIterator<SwXRedline,SwPageDesc> aIter(*pStdDesc);
+ SwXRedline* pxRedline = aIter.First();
+ while(pxRedline)
+ {
+ if(pxRedline->GetRedline() == &rRedline)
+ break;
+ pxRedline = aIter.Next();
+ }
+ if( !pxRedline )
+ pxRedline = new SwXRedline(rRedline, rDoc);
+ return pxRedline;
+}
+
+SwXRedlineEnumeration::SwXRedlineEnumeration(SwDoc& rDoc) :
+ pDoc(&rDoc),
+ nCurrentIndex(0)
+{
+ pDoc->GetPageDescFromPool(RES_POOLPAGE_STANDARD)->Add(this);
+}
+
+SwXRedlineEnumeration::~SwXRedlineEnumeration()
+{
+}
+
+sal_Bool SwXRedlineEnumeration::hasMoreElements(void) throw( uno::RuntimeException )
+{
+ if(!pDoc)
+ throw uno::RuntimeException();
+ return pDoc->GetRedlineTbl().Count() > nCurrentIndex;
+}
+
+uno::Any SwXRedlineEnumeration::nextElement(void)
+ throw( container::NoSuchElementException, lang::WrappedTargetException, uno::RuntimeException )
+{
+ if(!pDoc)
+ throw uno::RuntimeException();
+ const SwRedlineTbl& rRedTbl = pDoc->GetRedlineTbl();
+ if(!(rRedTbl.Count() > nCurrentIndex))
+ throw container::NoSuchElementException();
+ uno::Reference <beans::XPropertySet> xRet = SwXRedlines::GetObject( *rRedTbl.GetObject(nCurrentIndex++), *pDoc );
+ uno::Any aRet;
+ aRet <<= xRet;
+ return aRet;
+}
+
+rtl::OUString SwXRedlineEnumeration::getImplementationName(void) throw( uno::RuntimeException )
+{
+ return C2U("SwXRedlineEnumeration");
+}
+
+sal_Bool SwXRedlineEnumeration::supportsService(const rtl::OUString& /*ServiceName*/) throw( uno::RuntimeException )
+{
+ return sal_False;
+}
+
+uno::Sequence< OUString > SwXRedlineEnumeration::getSupportedServiceNames(void) throw( uno::RuntimeException )
+{
+ return uno::Sequence< OUString >();
+}
+
+void SwXRedlineEnumeration::Modify( const SfxPoolItem* pOld, const SfxPoolItem *pNew)
+{
+ ClientModify(this, pOld, pNew);
+ if(!GetRegisteredIn())
+ pDoc = 0;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/unocore/unorefmk.cxx b/sw/source/core/unocore/unorefmk.cxx
new file mode 100644
index 000000000000..3e0b77e0f2ce
--- /dev/null
+++ b/sw/source/core/unocore/unorefmk.cxx
@@ -0,0 +1,1623 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+#include <osl/mutex.hxx>
+#include <vcl/svapp.hxx>
+
+#include <unomid.h>
+#include <unotextrange.hxx>
+#include <unorefmark.hxx>
+#include <unotextcursor.hxx>
+#include <unomap.hxx>
+#include <unocrsr.hxx>
+#include <unoevtlstnr.hxx>
+#include <unocrsrhelper.hxx>
+#include <doc.hxx>
+#include <ndtxt.hxx>
+#include <fmtrfmrk.hxx>
+#include <txtrfmrk.hxx>
+#include <hints.hxx>
+
+
+using namespace ::com::sun::star;
+using ::rtl::OUString;
+
+/******************************************************************
+ * SwXReferenceMark
+ ******************************************************************/
+class SwXReferenceMark::Impl
+ : public SwClient
+{
+
+public:
+ SwEventListenerContainer m_ListenerContainer;
+ bool m_bIsDescriptor;
+ SwDoc * m_pDoc;
+ const SwFmtRefMark * m_pMarkFmt;
+ ::rtl::OUString m_sMarkName;
+
+ Impl( SwXReferenceMark & rThis,
+ SwDoc *const pDoc, SwFmtRefMark const*const pRefMark)
+ : SwClient((pDoc) ? pDoc->GetUnoCallBack() : 0)
+ , m_ListenerContainer(static_cast< ::cppu::OWeakObject* >(&rThis))
+ // #i111177# unxsols4 (Sun C++ 5.9 SunOS_sparc) may generate wrong code
+ , m_bIsDescriptor((0 == pRefMark) ? true : false)
+ , m_pDoc(pDoc)
+ , m_pMarkFmt(pRefMark)
+ {
+ if (pRefMark)
+ {
+ m_sMarkName = pRefMark->GetRefName();
+ }
+ }
+
+ bool IsValid() const { return 0 != GetRegisteredIn(); }
+ void InsertRefMark( SwPaM & rPam, SwXTextCursor const*const pCursor );
+ void Invalidate();
+protected:
+ // SwClient
+ virtual void Modify( const SfxPoolItem* pOld, const SfxPoolItem *pNew);
+
+};
+
+void SwXReferenceMark::Impl::Invalidate()
+{
+ if (IsValid())
+ {
+ const_cast<SwModify*>(GetRegisteredIn())->Remove(this);
+ }
+ m_ListenerContainer.Disposing();
+ m_pDoc = 0;
+ m_pMarkFmt = 0;
+}
+
+void SwXReferenceMark::Impl::Modify( const SfxPoolItem* pOld, const SfxPoolItem *pNew)
+{
+ ClientModify(this, pOld, pNew);
+
+ if (!GetRegisteredIn()) // removed => dispose
+ {
+ Invalidate();
+ }
+ else if (pOld)
+ {
+ switch (pOld->Which())
+ {
+ case RES_REFMARK_DELETED:
+ if (static_cast<const void*>(m_pMarkFmt) ==
+ static_cast<const SwPtrMsgPoolItem *>(pOld)->pObject)
+ {
+ Invalidate();
+ }
+ break;
+ }
+ }
+}
+
+SwXReferenceMark::SwXReferenceMark(
+ SwDoc *const pDoc, SwFmtRefMark const*const pRefMark)
+ : m_pImpl( new SwXReferenceMark::Impl(*this, pDoc, pRefMark) )
+{
+}
+
+SwXReferenceMark::~SwXReferenceMark()
+{
+}
+
+SwXReferenceMark *
+SwXReferenceMark::GetReferenceMark(
+ SwModify const& /*rUnoCB*/, SwFmtRefMark const& /*rMarkFmt*/)
+{
+ // #i105557#: do not iterate over the registered clients: race condition
+ // to do this properly requires the SwXReferenceMark to register at the
+ // SwFmtRefMark directly, not at the unocallback
+ return 0;
+}
+
+SwXReferenceMark *
+SwXReferenceMark::CreateXReferenceMark(
+ SwDoc & rDoc, SwFmtRefMark const& rMarkFmt)
+{
+ SwXReferenceMark *const pXMark(
+ GetReferenceMark(*rDoc.GetUnoCallBack(), rMarkFmt) );
+ return (pXMark)
+ ? pXMark
+ : new SwXReferenceMark(&rDoc, &rMarkFmt);
+}
+
+const uno::Sequence< sal_Int8 > & SwXReferenceMark::getUnoTunnelId()
+{
+ static uno::Sequence< sal_Int8 > aSeq = ::CreateUnoTunnelId();
+ return aSeq;
+}
+
+sal_Int64 SAL_CALL
+SwXReferenceMark::getSomething(const uno::Sequence< sal_Int8 >& rId)
+throw (uno::RuntimeException)
+{
+ return ::sw::UnoTunnelImpl<SwXReferenceMark>(rId, this);
+}
+
+OUString SAL_CALL SwXReferenceMark::getImplementationName()
+throw (uno::RuntimeException)
+{
+ return C2U("SwXReferenceMark");
+}
+
+static char const*const g_ServicesReferenceMark[] =
+{
+ "com.sun.star.text.TextContent",
+ "com.sun.star.text.ReferenceMark",
+};
+
+static const size_t g_nServicesReferenceMark(
+ SAL_N_ELEMENTS(g_ServicesReferenceMark));
+
+sal_Bool SAL_CALL
+SwXReferenceMark::supportsService(const OUString& rServiceName)
+throw (uno::RuntimeException)
+{
+ return ::sw::SupportsServiceImpl(
+ g_nServicesReferenceMark, g_ServicesReferenceMark, rServiceName);
+}
+
+uno::Sequence< OUString > SAL_CALL
+SwXReferenceMark::getSupportedServiceNames()
+throw (uno::RuntimeException)
+{
+ return ::sw::GetSupportedServiceNamesImpl(
+ g_nServicesReferenceMark, g_ServicesReferenceMark);
+}
+
+template<typename T> struct NotContainedIn
+{
+ ::std::vector<T> const& m_rVector;
+ explicit NotContainedIn(::std::vector<T> const& rVector)
+ : m_rVector(rVector) { }
+ bool operator() (T const& rT) {
+ return ::std::find(m_rVector.begin(), m_rVector.end(), rT)
+ == m_rVector.end();
+ }
+};
+
+void SwXReferenceMark::Impl::InsertRefMark(SwPaM& rPam,
+ SwXTextCursor const*const pCursor)
+{
+ //! in some cases when this function is called the pDoc pointer member may have become
+ //! invalid/deleted thus we obtain the document pointer from rPaM where it should always
+ //! be valid.
+ SwDoc *pDoc2 = rPam.GetDoc();
+
+ UnoActionContext aCont(pDoc2);
+ SwFmtRefMark aRefMark(m_sMarkName);
+ sal_Bool bMark = *rPam.GetPoint() != *rPam.GetMark();
+
+ const bool bForceExpandHints( (!bMark && pCursor)
+ ? pCursor->IsAtEndOfMeta() : false );
+ const SetAttrMode nInsertFlags = (bForceExpandHints)
+ ? ( nsSetAttrMode::SETATTR_FORCEHINTEXPAND
+ | nsSetAttrMode::SETATTR_DONTEXPAND)
+ : nsSetAttrMode::SETATTR_DONTEXPAND;
+
+ ::std::vector<SwTxtAttr *> oldMarks;
+ if (bMark)
+ {
+ oldMarks = rPam.GetNode()->GetTxtNode()->GetTxtAttrsAt(
+ rPam.GetPoint()->nContent.GetIndex(), RES_TXTATR_REFMARK);
+ }
+
+ pDoc2->InsertPoolItem( rPam, aRefMark, nInsertFlags );
+
+ if( bMark && *rPam.GetPoint() > *rPam.GetMark())
+ {
+ rPam.Exchange();
+ }
+
+ // aRefMark was copied into the document pool; now retrieve real format...
+ SwTxtAttr * pTxtAttr(0);
+ if (bMark)
+ {
+ // #i107672#
+ // ensure that we do not retrieve a different mark at the same position
+ ::std::vector<SwTxtAttr *> const newMarks(
+ rPam.GetNode()->GetTxtNode()->GetTxtAttrsAt(
+ rPam.GetPoint()->nContent.GetIndex(), RES_TXTATR_REFMARK));
+ ::std::vector<SwTxtAttr *>::const_iterator const iter(
+ ::std::find_if(newMarks.begin(), newMarks.end(),
+ NotContainedIn<SwTxtAttr *>(oldMarks)));
+ OSL_ASSERT(newMarks.end() != iter);
+ if (newMarks.end() != iter)
+ {
+ pTxtAttr = *iter;
+ }
+ }
+ else
+ {
+ SwTxtNode *pTxtNd = rPam.GetNode()->GetTxtNode();
+ OSL_ASSERT(pTxtNd);
+ pTxtAttr = pTxtNd ? rPam.GetNode()->GetTxtNode()->GetTxtAttrForCharAt(
+ rPam.GetPoint()->nContent.GetIndex() - 1, RES_TXTATR_REFMARK) : NULL;
+ }
+
+ if (!pTxtAttr)
+ {
+ throw uno::RuntimeException(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
+ "SwXReferenceMark::InsertRefMark(): cannot insert attribute")), 0);
+ }
+
+ m_pMarkFmt = &pTxtAttr->GetRefMark();
+
+ pDoc2->GetUnoCallBack()->Add(this);
+}
+
+void SAL_CALL
+SwXReferenceMark::attach(const uno::Reference< text::XTextRange > & xTextRange)
+throw (lang::IllegalArgumentException, uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+
+ if (!m_pImpl->m_bIsDescriptor)
+ {
+ throw uno::RuntimeException();
+ }
+ uno::Reference<lang::XUnoTunnel> xRangeTunnel( xTextRange, uno::UNO_QUERY);
+ SwXTextRange* pRange = 0;
+ OTextCursorHelper* pCursor = 0;
+ if(xRangeTunnel.is())
+ {
+ pRange = ::sw::UnoTunnelGetImplementation<SwXTextRange>(xRangeTunnel);
+ pCursor =
+ ::sw::UnoTunnelGetImplementation<OTextCursorHelper>(xRangeTunnel);
+ }
+ SwDoc *const pDocument =
+ (pRange) ? pRange->GetDoc() : ((pCursor) ? pCursor->GetDoc() : 0);
+ if (!pDocument)
+ {
+ throw lang::IllegalArgumentException();
+ }
+
+ SwUnoInternalPaM aPam(*pDocument);
+ //das muss jetzt sal_True liefern
+ ::sw::XTextRangeToSwPaM(aPam, xTextRange);
+ m_pImpl->InsertRefMark(aPam, dynamic_cast<SwXTextCursor*>(pCursor));
+ m_pImpl->m_bIsDescriptor = sal_False;
+ m_pImpl->m_pDoc = pDocument;
+}
+
+uno::Reference< text::XTextRange > SAL_CALL
+SwXReferenceMark::getAnchor() throw (uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+
+ if (m_pImpl->IsValid())
+ {
+ SwFmtRefMark const*const pNewMark =
+ m_pImpl->m_pDoc->GetRefMark(m_pImpl->m_sMarkName);
+ if (pNewMark && (pNewMark == m_pImpl->m_pMarkFmt))
+ {
+ SwTxtRefMark const*const pTxtMark =
+ m_pImpl->m_pMarkFmt->GetTxtRefMark();
+ if (pTxtMark &&
+ (&pTxtMark->GetTxtNode().GetNodes() ==
+ &m_pImpl->m_pDoc->GetNodes()))
+ {
+ SwTxtNode const& rTxtNode = pTxtMark->GetTxtNode();
+ const ::std::auto_ptr<SwPaM> pPam( (pTxtMark->GetEnd())
+ ? new SwPaM( rTxtNode, *pTxtMark->GetEnd(),
+ rTxtNode, *pTxtMark->GetStart())
+ : new SwPaM( rTxtNode, *pTxtMark->GetStart()) );
+
+ return SwXTextRange::CreateXTextRange(
+ *m_pImpl->m_pDoc, *pPam->Start(), pPam->End());
+ }
+ }
+ }
+ return 0;
+}
+
+void SAL_CALL SwXReferenceMark::dispose() throw (uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+ if (m_pImpl->IsValid())
+ {
+ SwFmtRefMark const*const pNewMark =
+ m_pImpl->m_pDoc->GetRefMark(m_pImpl->m_sMarkName);
+ if (pNewMark && (pNewMark == m_pImpl->m_pMarkFmt))
+ {
+ SwTxtRefMark const*const pTxtMark =
+ m_pImpl->m_pMarkFmt->GetTxtRefMark();
+ if (pTxtMark &&
+ (&pTxtMark->GetTxtNode().GetNodes() ==
+ &m_pImpl->m_pDoc->GetNodes()))
+ {
+ SwTxtNode const& rTxtNode = pTxtMark->GetTxtNode();
+ xub_StrLen nStt = *pTxtMark->GetStart(),
+ nEnd = pTxtMark->GetEnd() ? *pTxtMark->GetEnd()
+ : nStt + 1;
+
+ SwPaM aPam( rTxtNode, nStt, rTxtNode, nEnd );
+ m_pImpl->m_pDoc->DeleteAndJoin( aPam );
+ }
+ }
+ }
+ else if (m_pImpl->m_bIsDescriptor)
+ {
+ m_pImpl->Invalidate();
+ }
+}
+
+void SAL_CALL SwXReferenceMark::addEventListener(
+ const uno::Reference< lang::XEventListener > & xListener)
+throw (uno::RuntimeException)
+{
+ SolarMutexGuard g;
+
+ if (!m_pImpl->IsValid())
+ {
+ throw uno::RuntimeException();
+ }
+ m_pImpl->m_ListenerContainer.AddListener(xListener);
+}
+
+void SAL_CALL SwXReferenceMark::removeEventListener(
+ const uno::Reference< lang::XEventListener > & xListener)
+throw (uno::RuntimeException)
+{
+ SolarMutexGuard g;
+
+ if (!m_pImpl->IsValid() ||
+ !m_pImpl->m_ListenerContainer.RemoveListener(xListener))
+ {
+ throw uno::RuntimeException();
+ }
+}
+
+OUString SAL_CALL SwXReferenceMark::getName()
+throw (uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+ if (!m_pImpl->IsValid() ||
+ !m_pImpl->m_pDoc->GetRefMark(m_pImpl->m_sMarkName))
+ {
+ throw uno::RuntimeException();
+ }
+ return m_pImpl->m_sMarkName;
+}
+
+void SAL_CALL SwXReferenceMark::setName(const OUString& rName)
+throw (uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+ if (m_pImpl->m_bIsDescriptor)
+ {
+ m_pImpl->m_sMarkName = rName;
+ }
+ else
+ {
+ if (!m_pImpl->IsValid()
+ || !m_pImpl->m_pDoc->GetRefMark(m_pImpl->m_sMarkName)
+ || m_pImpl->m_pDoc->GetRefMark(rName))
+ {
+ throw uno::RuntimeException();
+ }
+ SwFmtRefMark const*const pCurMark =
+ m_pImpl->m_pDoc->GetRefMark(m_pImpl->m_sMarkName);
+ if ((rName != m_pImpl->m_sMarkName)
+ && pCurMark && (pCurMark == m_pImpl->m_pMarkFmt))
+ {
+ const UnoActionContext aCont(m_pImpl->m_pDoc);
+ SwTxtRefMark const*const pTxtMark =
+ m_pImpl->m_pMarkFmt->GetTxtRefMark();
+ if (pTxtMark &&
+ (&pTxtMark->GetTxtNode().GetNodes() ==
+ &m_pImpl->m_pDoc->GetNodes()))
+ {
+ SwTxtNode const& rTxtNode = pTxtMark->GetTxtNode();
+ xub_StrLen nStt = *pTxtMark->GetStart(),
+ nEnd = pTxtMark->GetEnd() ? *pTxtMark->GetEnd()
+ : nStt + 1;
+
+ SwPaM aPam( rTxtNode, nStt, rTxtNode, nEnd );
+ // deletes the m_pImpl->m_pDoc member in the SwXReferenceMark!
+ m_pImpl->m_pDoc->DeleteAndJoin( aPam );
+ // The aPam will keep the correct and functional doc though
+
+ m_pImpl->m_sMarkName = rName;
+ //create a new one
+ m_pImpl->InsertRefMark( aPam, 0 );
+ m_pImpl->m_pDoc = aPam.GetDoc();
+ }
+ }
+ }
+}
+
+uno::Reference< beans::XPropertySetInfo > SAL_CALL
+SwXReferenceMark::getPropertySetInfo() throw (uno::RuntimeException)
+{
+ SolarMutexGuard g;
+
+ static uno::Reference< beans::XPropertySetInfo > xRef =
+ aSwMapProvider.GetPropertySet(PROPERTY_MAP_PARAGRAPH_EXTENSIONS)
+ ->getPropertySetInfo();
+ return xRef;
+}
+
+void SAL_CALL SwXReferenceMark::setPropertyValue(
+ const OUString& /*rPropertyName*/, const uno::Any& /*rValue*/ )
+throw (beans::UnknownPropertyException, beans::PropertyVetoException,
+ lang::IllegalArgumentException, lang::WrappedTargetException,
+ uno::RuntimeException)
+{
+ throw lang::IllegalArgumentException();
+}
+
+uno::Any SAL_CALL
+SwXReferenceMark::getPropertyValue(const OUString& rPropertyName)
+throw (beans::UnknownPropertyException, lang::WrappedTargetException,
+ uno::RuntimeException)
+{
+ // does not seem to need SolarMutex
+ uno::Any aRet;
+ if (! ::sw::GetDefaultTextContentValue(aRet, rPropertyName))
+ {
+ throw beans::UnknownPropertyException();
+ }
+ return aRet;
+}
+
+void SAL_CALL SwXReferenceMark::addPropertyChangeListener(
+ const OUString& /*rPropertyName*/,
+ const uno::Reference< beans::XPropertyChangeListener >& /*xListener*/)
+throw (beans::UnknownPropertyException, lang::WrappedTargetException,
+ uno::RuntimeException)
+{
+ OSL_FAIL("SwXReferenceMark::addPropertyChangeListener(): not implemented");
+}
+
+void SAL_CALL SwXReferenceMark::removePropertyChangeListener(
+ const OUString& /*rPropertyName*/,
+ const uno::Reference< beans::XPropertyChangeListener >& /*xListener*/)
+throw (beans::UnknownPropertyException, lang::WrappedTargetException,
+ uno::RuntimeException)
+{
+ OSL_FAIL("SwXReferenceMark::removePropertyChangeListener(): not implemented");
+}
+
+void SAL_CALL SwXReferenceMark::addVetoableChangeListener(
+ const OUString& /*rPropertyName*/,
+ const uno::Reference< beans::XVetoableChangeListener >& /*xListener*/)
+throw (beans::UnknownPropertyException, lang::WrappedTargetException,
+ uno::RuntimeException)
+{
+ OSL_FAIL("SwXReferenceMark::addVetoableChangeListener(): not implemented");
+}
+
+void SAL_CALL SwXReferenceMark::removeVetoableChangeListener(
+ const OUString& /*rPropertyName*/,
+ const uno::Reference< beans::XVetoableChangeListener >& /*xListener*/)
+throw (beans::UnknownPropertyException, lang::WrappedTargetException,
+ uno::RuntimeException)
+{
+ OSL_FAIL("SwXReferenceMark::removeVetoableChangeListener(): not implemented");
+}
+
+#include <com/sun/star/lang/DisposedException.hpp>
+#include <unometa.hxx>
+#include <unotext.hxx>
+#include <unoport.hxx>
+#include <txtatr.hxx>
+#include <fmtmeta.hxx>
+#include <docsh.hxx>
+
+/******************************************************************
+ * SwXMetaText
+ ******************************************************************/
+class SwXMetaText
+ : public SwXText
+{
+private:
+ SwXMeta & m_rMeta;
+
+ virtual void PrepareForAttach(uno::Reference< text::XTextRange > & xRange,
+ const SwPaM & rPam);
+
+ virtual bool CheckForOwnMemberMeta(const SwPaM & rPam, const bool bAbsorb)
+ throw (lang::IllegalArgumentException, uno::RuntimeException);
+
+protected:
+ virtual const SwStartNode *GetStartNode() const;
+ virtual uno::Reference< text::XTextCursor >
+ CreateCursor() throw (uno::RuntimeException);
+
+public:
+ SwXMetaText(SwDoc & rDoc, SwXMeta & rMeta);
+
+ /// make available for SwXMeta
+ void Invalidate() { SwXText::Invalidate(); };
+
+ // XInterface
+ virtual void SAL_CALL acquire() throw()
+ { OSL_FAIL("ERROR: SwXMetaText::acquire"); }
+ virtual void SAL_CALL release() throw()
+ { OSL_FAIL("ERROR: SwXMetaText::release"); }
+
+ // XTypeProvider
+ virtual uno::Sequence< sal_Int8 > SAL_CALL
+ getImplementationId() throw (uno::RuntimeException);
+
+ // XText
+ virtual uno::Reference< text::XTextCursor > SAL_CALL
+ createTextCursor() throw (uno::RuntimeException);
+ virtual uno::Reference< text::XTextCursor > SAL_CALL
+ createTextCursorByRange(
+ const uno::Reference< text::XTextRange > & xTextPosition)
+ throw (uno::RuntimeException);
+
+ SwXMeta & GetXMeta() { return m_rMeta; }
+
+};
+
+SwXMetaText::SwXMetaText(SwDoc & rDoc, SwXMeta & rMeta)
+ : SwXText(&rDoc, CURSOR_META)
+ , m_rMeta(rMeta)
+{
+}
+
+const SwStartNode *SwXMetaText::GetStartNode() const
+{
+ SwXText const * const pParent(
+ dynamic_cast<SwXText*>(m_rMeta.GetParentText().get()));
+ return (pParent) ? pParent->GetStartNode() : 0;
+}
+
+void SwXMetaText::PrepareForAttach( uno::Reference<text::XTextRange> & xRange,
+ const SwPaM & rPam)
+{
+ // create a new cursor to prevent modifying SwXTextRange
+ xRange = static_cast<text::XWordCursor*>(
+ new SwXTextCursor(*GetDoc(), &m_rMeta, CURSOR_META, *rPam.GetPoint(),
+ (rPam.HasMark()) ? rPam.GetMark() : 0));
+}
+
+bool SwXMetaText::CheckForOwnMemberMeta(const SwPaM & rPam, const bool bAbsorb)
+ throw (lang::IllegalArgumentException, uno::RuntimeException)
+{
+ return m_rMeta.CheckForOwnMemberMeta(rPam, bAbsorb);
+}
+
+uno::Reference< text::XTextCursor > SwXMetaText::CreateCursor()
+throw (uno::RuntimeException)
+{
+ uno::Reference< text::XTextCursor > xRet;
+ if (IsValid())
+ {
+ SwTxtNode * pTxtNode;
+ xub_StrLen nMetaStart;
+ xub_StrLen nMetaEnd;
+ const bool bSuccess(
+ m_rMeta.SetContentRange(pTxtNode, nMetaStart, nMetaEnd) );
+ if (bSuccess)
+ {
+ SwPosition aPos(*pTxtNode, nMetaStart);
+ xRet = static_cast<text::XWordCursor*>(
+ new SwXTextCursor(*GetDoc(), &m_rMeta, CURSOR_META, aPos));
+ }
+ }
+ return xRet;
+}
+
+uno::Sequence<sal_Int8> SAL_CALL
+SwXMetaText::getImplementationId() throw (uno::RuntimeException)
+{
+ return m_rMeta.getImplementationId();
+}
+
+// XText
+uno::Reference< text::XTextCursor > SAL_CALL
+SwXMetaText::createTextCursor() throw (uno::RuntimeException)
+{
+ return CreateCursor();
+}
+
+uno::Reference< text::XTextCursor > SAL_CALL
+SwXMetaText::createTextCursorByRange(
+ const uno::Reference<text::XTextRange> & xTextPosition)
+ throw (uno::RuntimeException)
+{
+ const uno::Reference<text::XTextCursor> xCursor( CreateCursor() );
+ xCursor->gotoRange(xTextPosition, sal_False);
+ return xCursor;
+}
+
+/******************************************************************
+ * SwXMeta
+ ******************************************************************/
+// the Meta has a cached list of text portions for its contents
+// this list is created by SwXTextPortionEnumeration
+// the Meta listens at the SwTxtNode and throws away the cache when it changes
+class SwXMeta::Impl
+ : public SwClient
+{
+
+public:
+
+ SwEventListenerContainer m_ListenerContainer;
+ ::std::auto_ptr<const TextRangeList_t> m_pTextPortions;
+ // 3 possible states: not attached, attached, disposed
+ bool m_bIsDisposed;
+ bool m_bIsDescriptor;
+ uno::Reference<text::XText> m_xParentText;
+ SwXMetaText m_Text;
+
+ Impl( SwXMeta & rThis, SwDoc & rDoc,
+ ::sw::Meta * const pMeta,
+ uno::Reference<text::XText> const& xParentText,
+ TextRangeList_t const * const pPortions)
+ : SwClient(pMeta)
+ , m_ListenerContainer(static_cast< ::cppu::OWeakObject* >(&rThis))
+ , m_pTextPortions( pPortions )
+ , m_bIsDisposed( false )
+ // #i111177# unxsols4 (Sun C++ 5.9 SunOS_sparc) may generate wrong code
+ , m_bIsDescriptor((0 == pMeta) ? true : false)
+ , m_xParentText(xParentText)
+ , m_Text(rDoc, rThis)
+ {
+ }
+
+ inline const ::sw::Meta * GetMeta() const;
+ // only for SwXMetaField!
+ inline const ::sw::MetaField * GetMetaField() const;
+protected:
+ // SwClient
+ virtual void Modify( const SfxPoolItem* pOld, const SfxPoolItem *pNew);
+
+};
+
+inline const ::sw::Meta * SwXMeta::Impl::GetMeta() const
+{
+ return static_cast< const ::sw::Meta * >(GetRegisteredIn());
+}
+
+// SwModify
+void SwXMeta::Impl::Modify( const SfxPoolItem* pOld, const SfxPoolItem *pNew )
+{
+ m_pTextPortions.reset(); // throw away cache (SwTxtNode changed)
+
+ ClientModify(this, pOld, pNew);
+
+ if (!GetRegisteredIn()) // removed => dispose
+ {
+ m_ListenerContainer.Disposing();
+ m_bIsDisposed = true;
+ m_Text.Invalidate();
+ }
+}
+
+uno::Reference<text::XText> SwXMeta::GetParentText() const
+{
+ return m_pImpl->m_xParentText;
+}
+
+SwXMeta::SwXMeta(SwDoc *const pDoc, ::sw::Meta *const pMeta,
+ uno::Reference<text::XText> const& xParentText,
+ TextRangeList_t const*const pPortions)
+ : m_pImpl( new SwXMeta::Impl(*this, *pDoc, pMeta, xParentText, pPortions) )
+{
+}
+
+SwXMeta::SwXMeta(SwDoc *const pDoc)
+ : m_pImpl( new SwXMeta::Impl(*this, *pDoc, 0, 0, 0) )
+{
+}
+
+SwXMeta::~SwXMeta()
+{
+}
+
+uno::Reference<rdf::XMetadatable>
+SwXMeta::CreateXMeta(::sw::Meta & rMeta,
+ uno::Reference<text::XText> const& i_xParent,
+ ::std::auto_ptr<TextRangeList_t const> pPortions)
+{
+ // re-use existing SwXMeta
+ // #i105557#: do not iterate over the registered clients: race condition
+ uno::Reference<rdf::XMetadatable> xMeta(rMeta.GetXMeta());
+ if (xMeta.is())
+ {
+ if (pPortions.get()) // set cache in the XMeta to the given portions
+ {
+ const uno::Reference<lang::XUnoTunnel> xUT(xMeta, uno::UNO_QUERY);
+ SwXMeta *const pXMeta(
+ ::sw::UnoTunnelGetImplementation<SwXMeta>(xUT));
+ OSL_ENSURE(pXMeta, "no pXMeta?");
+ // NB: the meta must always be created with the complete content
+ // if SwXTextPortionEnumeration is created for a selection,
+ // it must be checked that the Meta is contained in the selection!
+ pXMeta->m_pImpl->m_pTextPortions = pPortions;
+ // ??? is this necessary?
+ if (pXMeta->m_pImpl->m_xParentText.get() != i_xParent.get())
+ {
+ OSL_FAIL("SwXMeta with different parent?");
+ pXMeta->m_pImpl->m_xParentText.set(i_xParent);
+ }
+ }
+ return xMeta;
+ }
+
+ // create new SwXMeta
+ SwTxtNode * const pTxtNode( rMeta.GetTxtNode() );
+ OSL_ENSURE(pTxtNode, "CreateXMeta: no text node?");
+ if (!pTxtNode) { return 0; }
+ uno::Reference<text::XText> xParentText(i_xParent);
+ if (!xParentText.is())
+ {
+ SwTxtMeta * const pTxtAttr( rMeta.GetTxtAttr() );
+ OSL_ENSURE(pTxtAttr, "CreateXMeta: no text attr?");
+ if (!pTxtAttr) { return 0; }
+ const SwPosition aPos(*pTxtNode, *pTxtAttr->GetStart());
+ xParentText.set( ::sw::CreateParentXText(*pTxtNode->GetDoc(), aPos) );
+ }
+ if (!xParentText.is()) { return 0; }
+ SwXMeta *const pXMeta( (RES_TXTATR_META == rMeta.GetFmtMeta()->Which())
+ ? new SwXMeta (pTxtNode->GetDoc(), &rMeta, xParentText,
+ pPortions.release()) // temporarily un-auto_ptr :-(
+ : new SwXMetaField(pTxtNode->GetDoc(), &rMeta, xParentText,
+ pPortions.release()));
+ // this is why the constructor is private: need to acquire pXMeta here
+ xMeta.set(pXMeta);
+ // in order to initialize the weak pointer cache in the core object
+ rMeta.SetXMeta(xMeta);
+ return xMeta;
+}
+
+bool SwXMeta::SetContentRange(
+ SwTxtNode *& rpNode, xub_StrLen & rStart, xub_StrLen & rEnd ) const
+{
+ ::sw::Meta const * const pMeta( m_pImpl->GetMeta() );
+ if (pMeta)
+ {
+ SwTxtMeta const * const pTxtAttr( pMeta->GetTxtAttr() );
+ if (pTxtAttr)
+ {
+ rpNode = pMeta->GetTxtNode();
+ if (rpNode)
+ {
+ // rStart points at the first position _within_ the meta!
+ rStart = *pTxtAttr->GetStart() + 1;
+ rEnd = *pTxtAttr->GetEnd();
+ return true;
+ }
+ }
+ }
+ return false;
+}
+
+bool SwXMeta::CheckForOwnMemberMeta(const SwPaM & rPam, const bool bAbsorb)
+ throw (lang::IllegalArgumentException, uno::RuntimeException)
+{
+ SwTxtNode * pTxtNode;
+ xub_StrLen nMetaStart;
+ xub_StrLen nMetaEnd;
+ const bool bSuccess( SetContentRange(pTxtNode, nMetaStart, nMetaEnd) );
+ OSL_ENSURE(bSuccess, "no pam?");
+ if (!bSuccess)
+ throw lang::DisposedException();
+
+ SwPosition const * const pStartPos( rPam.Start() );
+ if (&pStartPos->nNode.GetNode() != pTxtNode)
+ {
+ throw lang::IllegalArgumentException(
+ C2U("trying to insert into a nesting text content, but start "
+ "of text range not in same paragraph as text content"),
+ 0, 0);
+ }
+ bool bForceExpandHints(false);
+ const xub_StrLen nStartPos(pStartPos->nContent.GetIndex());
+ // not <= but < because nMetaStart is behind dummy char!
+ // not >= but > because == means insert at end!
+ if ((nStartPos < nMetaStart) || (nStartPos > nMetaEnd))
+ {
+ throw lang::IllegalArgumentException(
+ C2U("trying to insert into a nesting text content, but start "
+ "of text range not inside text content"),
+ 0, 0);
+ }
+ else if (nStartPos == nMetaEnd)
+ {
+ bForceExpandHints = true;
+ }
+ if (rPam.HasMark() && bAbsorb)
+ {
+ SwPosition const * const pEndPos( rPam.End() );
+ if (&pEndPos->nNode.GetNode() != pTxtNode)
+ {
+ throw lang::IllegalArgumentException(
+ C2U("trying to insert into a nesting text content, but end "
+ "of text range not in same paragraph as text content"),
+ 0, 0);
+ }
+ const xub_StrLen nEndPos(pEndPos->nContent.GetIndex());
+ // not <= but < because nMetaStart is behind dummy char!
+ // not >= but > because == means insert at end!
+ if ((nEndPos < nMetaStart) || (nEndPos > nMetaEnd))
+ {
+ throw lang::IllegalArgumentException(
+ C2U("trying to insert into a nesting text content, but end "
+ "of text range not inside text content"),
+ 0, 0);
+ }
+ else if (nEndPos == nMetaEnd)
+ {
+ bForceExpandHints = true;
+ }
+ }
+ return bForceExpandHints;
+}
+
+const uno::Sequence< sal_Int8 > & SwXMeta::getUnoTunnelId()
+{
+ static uno::Sequence< sal_Int8 > aSeq( ::CreateUnoTunnelId() );
+ return aSeq;
+}
+
+// XUnoTunnel
+sal_Int64 SAL_CALL
+SwXMeta::getSomething( const uno::Sequence< sal_Int8 > & i_rId )
+throw (uno::RuntimeException)
+{
+ return ::sw::UnoTunnelImpl<SwXMeta>(i_rId, this);
+}
+
+// XServiceInfo
+::rtl::OUString SAL_CALL
+SwXMeta::getImplementationName() throw (uno::RuntimeException)
+{
+ return C2U("SwXMeta");
+}
+
+static char const*const g_ServicesMeta[] =
+{
+ "com.sun.star.text.TextContent",
+ "com.sun.star.text.InContentMetadata",
+};
+
+static const size_t g_nServicesMeta(
+ SAL_N_ELEMENTS(g_ServicesMeta));
+
+sal_Bool SAL_CALL
+SwXMeta::supportsService(const ::rtl::OUString& rServiceName)
+throw (uno::RuntimeException)
+{
+ return ::sw::SupportsServiceImpl(
+ g_nServicesMeta, g_ServicesMeta, rServiceName);
+}
+
+uno::Sequence< ::rtl::OUString > SAL_CALL
+SwXMeta::getSupportedServiceNames() throw (uno::RuntimeException)
+{
+ return ::sw::GetSupportedServiceNamesImpl(g_nServicesMeta, g_ServicesMeta);
+}
+
+// XComponent
+void SAL_CALL
+SwXMeta::addEventListener(
+ uno::Reference< lang::XEventListener> const & xListener )
+throw (uno::RuntimeException)
+{
+ SolarMutexGuard g;
+
+ m_pImpl->m_ListenerContainer.AddListener(xListener);
+ if (m_pImpl->m_bIsDisposed)
+ {
+ m_pImpl->m_ListenerContainer.Disposing();
+ }
+}
+
+void SAL_CALL
+SwXMeta::removeEventListener(
+ uno::Reference< lang::XEventListener> const & xListener )
+throw (uno::RuntimeException)
+{
+ SolarMutexGuard g;
+
+ if (!m_pImpl->m_bIsDisposed)
+ {
+ m_pImpl->m_ListenerContainer.RemoveListener(xListener);
+ }
+}
+
+void SAL_CALL
+SwXMeta::dispose() throw (uno::RuntimeException)
+{
+ SolarMutexGuard g;
+
+ if (m_pImpl->m_bIsDescriptor)
+ {
+ m_pImpl->m_pTextPortions.reset();
+ m_pImpl->m_ListenerContainer.Disposing();
+ m_pImpl->m_bIsDisposed = true;
+ m_pImpl->m_Text.Invalidate();
+ }
+ else if (!m_pImpl->m_bIsDisposed)
+ {
+ SwTxtNode * pTxtNode;
+ xub_StrLen nMetaStart;
+ xub_StrLen nMetaEnd;
+ const bool bSuccess(SetContentRange(pTxtNode, nMetaStart, nMetaEnd));
+ OSL_ENSURE(bSuccess, "no pam?");
+ if (bSuccess)
+ {
+ // -1 because of CH_TXTATR
+ SwPaM aPam( *pTxtNode, nMetaStart - 1, *pTxtNode, nMetaEnd );
+ SwDoc * const pDoc( pTxtNode->GetDoc() );
+ pDoc->DeleteAndJoin( aPam );
+
+ // removal should call Modify and do the dispose
+ OSL_ENSURE(m_pImpl->m_bIsDisposed, "zombie meta");
+ }
+ }
+}
+
+void SAL_CALL
+SwXMeta::AttachImpl(const uno::Reference< text::XTextRange > & i_xTextRange,
+ const sal_uInt16 i_nWhich)
+throw (lang::IllegalArgumentException, uno::RuntimeException)
+{
+ SolarMutexGuard g;
+
+ if (m_pImpl->m_bIsDisposed)
+ {
+ throw lang::DisposedException();
+ }
+ if (!m_pImpl->m_bIsDescriptor)
+ {
+ throw uno::RuntimeException(
+ C2S("SwXMeta::attach(): already attached"),
+ static_cast< ::cppu::OWeakObject* >(this));
+ }
+
+ uno::Reference<lang::XUnoTunnel> xRangeTunnel(i_xTextRange, uno::UNO_QUERY);
+ if (!xRangeTunnel.is())
+ {
+ throw lang::IllegalArgumentException(
+ C2S("SwXMeta::attach(): argument is no XUnoTunnel"),
+ static_cast< ::cppu::OWeakObject* >(this), 0);
+ }
+ SwXTextRange *const pRange(
+ ::sw::UnoTunnelGetImplementation<SwXTextRange>(xRangeTunnel));
+ OTextCursorHelper *const pCursor( (pRange) ? 0 :
+ ::sw::UnoTunnelGetImplementation<OTextCursorHelper>(xRangeTunnel));
+ if (!pRange && !pCursor)
+ {
+ throw lang::IllegalArgumentException(
+ C2S("SwXMeta::attach(): argument not supported type"),
+ static_cast< ::cppu::OWeakObject* >(this), 0);
+ }
+
+ SwDoc * const pDoc(
+ pRange ? pRange->GetDoc() : pCursor ? pCursor->GetDoc() : 0 );
+ if (!pDoc)
+ {
+ throw lang::IllegalArgumentException(
+ C2S("SwXMeta::attach(): argument has no SwDoc"),
+ static_cast< ::cppu::OWeakObject* >(this), 0);
+ }
+
+ SwUnoInternalPaM aPam(*pDoc);
+ ::sw::XTextRangeToSwPaM(aPam, i_xTextRange);
+
+ UnoActionContext aContext(pDoc);
+
+ SwXTextCursor const*const pTextCursor(
+ dynamic_cast<SwXTextCursor*>(pCursor));
+ const bool bForceExpandHints((pTextCursor)
+ ? pTextCursor->IsAtEndOfMeta() : false);
+ const SetAttrMode nInsertFlags( (bForceExpandHints)
+ ? ( nsSetAttrMode::SETATTR_FORCEHINTEXPAND
+ | nsSetAttrMode::SETATTR_DONTEXPAND)
+ : nsSetAttrMode::SETATTR_DONTEXPAND );
+
+ const ::boost::shared_ptr< ::sw::Meta> pMeta( (RES_TXTATR_META == i_nWhich)
+ ? ::boost::shared_ptr< ::sw::Meta>( new ::sw::Meta() )
+ : ::boost::shared_ptr< ::sw::Meta>(
+ pDoc->GetMetaFieldManager().makeMetaField()) );
+ SwFmtMeta meta(pMeta, i_nWhich); // this is cloned by Insert!
+ const bool bSuccess( pDoc->InsertPoolItem( aPam, meta, nInsertFlags ) );
+ SwTxtAttr * const pTxtAttr( pMeta->GetTxtAttr() );
+ if (!bSuccess)
+ {
+ throw lang::IllegalArgumentException(
+ C2S("SwXMeta::attach(): cannot create meta: range invalid?"),
+ static_cast< ::cppu::OWeakObject* >(this), 1);
+ }
+ if (!pTxtAttr)
+ {
+ OSL_FAIL("meta inserted, but has no text attribute?");
+ throw uno::RuntimeException(
+ C2S("SwXMeta::attach(): cannot create meta"),
+ static_cast< ::cppu::OWeakObject* >(this));
+ }
+
+ pMeta->Add(m_pImpl.get());
+ pMeta->SetXMeta(uno::Reference<rdf::XMetadatable>(this));
+
+ m_pImpl->m_xParentText = ::sw::CreateParentXText(*pDoc, *aPam.GetPoint());
+
+ m_pImpl->m_bIsDescriptor = false;
+}
+
+// XTextContent
+void SAL_CALL
+SwXMeta::attach(const uno::Reference< text::XTextRange > & i_xTextRange)
+throw (lang::IllegalArgumentException, uno::RuntimeException)
+{
+ return SwXMeta::AttachImpl(i_xTextRange, RES_TXTATR_META);
+}
+
+uno::Reference< text::XTextRange > SAL_CALL
+SwXMeta::getAnchor() throw (uno::RuntimeException)
+{
+ SolarMutexGuard g;
+
+ if (m_pImpl->m_bIsDisposed)
+ {
+ throw lang::DisposedException();
+ }
+ if (m_pImpl->m_bIsDescriptor)
+ {
+ throw uno::RuntimeException(
+ C2S("SwXMeta::getAnchor(): not inserted"),
+ static_cast< ::cppu::OWeakObject* >(this));
+ }
+
+ SwTxtNode * pTxtNode;
+ xub_StrLen nMetaStart;
+ xub_StrLen nMetaEnd;
+ const bool bSuccess(SetContentRange(pTxtNode, nMetaStart, nMetaEnd));
+ OSL_ENSURE(bSuccess, "no pam?");
+ if (!bSuccess)
+ {
+ throw lang::DisposedException(
+ C2S("SwXMeta::getAnchor(): not attached"),
+ static_cast< ::cppu::OWeakObject* >(this));
+ }
+
+ const SwPosition start(*pTxtNode, nMetaStart - 1); // -1 due to CH_TXTATR
+ const SwPosition end(*pTxtNode, nMetaEnd);
+ return SwXTextRange::CreateXTextRange(*pTxtNode->GetDoc(), start, &end);
+}
+
+// XTextRange
+uno::Reference< text::XText > SAL_CALL
+SwXMeta::getText() throw (uno::RuntimeException)
+{
+ SolarMutexGuard g;
+ return this;
+}
+
+uno::Reference< text::XTextRange > SAL_CALL
+SwXMeta::getStart() throw (uno::RuntimeException)
+{
+ SolarMutexGuard g;
+ return m_pImpl->m_Text.getStart();
+}
+
+uno::Reference< text::XTextRange > SAL_CALL
+SwXMeta::getEnd() throw (uno::RuntimeException)
+{
+ SolarMutexGuard g;
+ return m_pImpl->m_Text.getEnd();
+}
+
+rtl::OUString SAL_CALL
+SwXMeta::getString() throw (uno::RuntimeException)
+{
+ SolarMutexGuard g;
+ return m_pImpl->m_Text.getString();
+}
+
+void SAL_CALL
+SwXMeta::setString(const rtl::OUString& rString) throw (uno::RuntimeException)
+{
+ SolarMutexGuard g;
+ return m_pImpl->m_Text.setString(rString);
+}
+
+// XSimpleText
+uno::Reference< text::XTextCursor > SAL_CALL
+SwXMeta::createTextCursor() throw (uno::RuntimeException)
+{
+ SolarMutexGuard g;
+ return m_pImpl->m_Text.createTextCursor();
+}
+
+uno::Reference< text::XTextCursor > SAL_CALL
+SwXMeta::createTextCursorByRange(
+ const uno::Reference<text::XTextRange> & xTextPosition)
+ throw (uno::RuntimeException)
+{
+ SolarMutexGuard g;
+ return m_pImpl->m_Text.createTextCursorByRange(xTextPosition);
+}
+
+void SAL_CALL
+SwXMeta::insertString(const uno::Reference<text::XTextRange> & xRange,
+ const rtl::OUString& rString, sal_Bool bAbsorb)
+throw (uno::RuntimeException)
+{
+ SolarMutexGuard g;
+ return m_pImpl->m_Text.insertString(xRange, rString, bAbsorb);
+}
+
+void SAL_CALL
+SwXMeta::insertControlCharacter(const uno::Reference<text::XTextRange> & xRange,
+ sal_Int16 nControlCharacter, sal_Bool bAbsorb)
+throw (lang::IllegalArgumentException, uno::RuntimeException)
+{
+ SolarMutexGuard g;
+ return m_pImpl->m_Text.insertControlCharacter(xRange, nControlCharacter,
+ bAbsorb);
+}
+
+// XText
+void SAL_CALL
+SwXMeta::insertTextContent( const uno::Reference<text::XTextRange> & xRange,
+ const uno::Reference<text::XTextContent> & xContent, sal_Bool bAbsorb)
+throw (lang::IllegalArgumentException, uno::RuntimeException)
+{
+ SolarMutexGuard g;
+ return m_pImpl->m_Text.insertTextContent(xRange, xContent, bAbsorb);
+}
+
+void SAL_CALL
+SwXMeta::removeTextContent(
+ const uno::Reference< text::XTextContent > & xContent)
+ throw (container::NoSuchElementException, uno::RuntimeException)
+{
+ SolarMutexGuard g;
+ return m_pImpl->m_Text.removeTextContent(xContent);
+}
+
+// XChild
+uno::Reference< uno::XInterface > SAL_CALL
+SwXMeta::getParent() throw (uno::RuntimeException)
+{
+ SolarMutexGuard g;
+ SwTxtNode * pTxtNode;
+ xub_StrLen nMetaStart;
+ xub_StrLen nMetaEnd;
+ bool const bSuccess( SetContentRange(pTxtNode, nMetaStart, nMetaEnd) );
+ OSL_ENSURE(bSuccess, "no pam?");
+ if (!bSuccess) { throw lang::DisposedException(); }
+ // in order to prevent getting this meta, subtract 1 from nMetaStart;
+ // so we get the index of the dummy character, and we exclude it
+ // by calling GetTxtAttrAt(_, _, PARENT) in GetNestedTextContent
+ uno::Reference<text::XTextContent> const xRet(
+ SwUnoCursorHelper::GetNestedTextContent(*pTxtNode, nMetaStart - 1,
+ true) );
+ return xRet;
+}
+
+void SAL_CALL
+SwXMeta::setParent(uno::Reference< uno::XInterface > const& /*xParent*/)
+ throw (uno::RuntimeException, lang::NoSupportException)
+{
+ throw lang::NoSupportException(C2S("setting parent not supported"), *this);
+}
+
+// XElementAccess
+uno::Type SAL_CALL
+SwXMeta::getElementType() throw (uno::RuntimeException)
+{
+ return text::XTextRange::static_type();
+}
+
+sal_Bool SAL_CALL
+SwXMeta::hasElements() throw (uno::RuntimeException)
+{
+ SolarMutexGuard g;
+
+ return m_pImpl->GetRegisteredIn() ? sal_True : sal_False;
+}
+
+// XEnumerationAccess
+uno::Reference< container::XEnumeration > SAL_CALL
+SwXMeta::createEnumeration() throw (uno::RuntimeException)
+{
+ SolarMutexGuard g;
+
+ if (m_pImpl->m_bIsDisposed)
+ {
+ throw lang::DisposedException();
+ }
+ if (m_pImpl->m_bIsDescriptor)
+ {
+ throw uno::RuntimeException(
+ C2S("createEnumeration(): not inserted"),
+ static_cast< ::cppu::OWeakObject* >(this));
+ }
+
+ SwTxtNode * pTxtNode;
+ xub_StrLen nMetaStart;
+ xub_StrLen nMetaEnd;
+ const bool bSuccess(SetContentRange(pTxtNode, nMetaStart, nMetaEnd));
+ OSL_ENSURE(bSuccess, "no pam?");
+ if (!bSuccess)
+ throw lang::DisposedException();
+
+ SwPaM aPam(*pTxtNode, nMetaStart);
+
+ if (!m_pImpl->m_pTextPortions.get())
+ {
+ return new SwXTextPortionEnumeration(
+ aPam, GetParentText(), nMetaStart, nMetaEnd);
+ }
+ else // cached!
+ {
+ return new SwXTextPortionEnumeration(aPam, *m_pImpl->m_pTextPortions);
+ }
+}
+
+// MetadatableMixin
+::sfx2::Metadatable* SwXMeta::GetCoreObject()
+{
+ return const_cast< ::sw::Meta * >(m_pImpl->GetMeta());
+}
+
+uno::Reference<frame::XModel> SwXMeta::GetModel()
+{
+ ::sw::Meta const * const pMeta( m_pImpl->GetMeta() );
+ if (pMeta)
+ {
+ SwTxtNode const * const pTxtNode( pMeta->GetTxtNode() );
+ if (pTxtNode)
+ {
+ SwDocShell const * const pShell(pTxtNode->GetDoc()->GetDocShell());
+ return (pShell) ? pShell->GetModel() : 0;
+ }
+ }
+ return 0;
+}
+
+/******************************************************************
+ * SwXMetaField
+ ******************************************************************/
+inline const ::sw::MetaField * SwXMeta::Impl::GetMetaField() const
+{
+ return static_cast< const ::sw::MetaField * >(GetRegisteredIn());
+}
+
+SwXMetaField::SwXMetaField(SwDoc *const pDoc, ::sw::Meta *const pMeta,
+ uno::Reference<text::XText> const& xParentText,
+ TextRangeList_t const*const pPortions)
+ : SwXMetaField_Base(pDoc, pMeta, xParentText, pPortions)
+{
+ OSL_ENSURE(pMeta && dynamic_cast< ::sw::MetaField* >(pMeta),
+ "SwXMetaField created for wrong hint!");
+}
+
+SwXMetaField::SwXMetaField(SwDoc *const pDoc)
+ : SwXMetaField_Base(pDoc)
+{
+}
+
+SwXMetaField::~SwXMetaField()
+{
+}
+
+// XServiceInfo
+::rtl::OUString SAL_CALL
+SwXMetaField::getImplementationName() throw (uno::RuntimeException)
+{
+ return C2U("SwXMetaField");
+}
+
+static char const*const g_ServicesMetaField[] =
+{
+ "com.sun.star.text.TextContent",
+ "com.sun.star.text.TextField",
+ "com.sun.star.text.textfield.MetadataField",
+};
+
+static const size_t g_nServicesMetaField(
+ SAL_N_ELEMENTS(g_ServicesMetaField));
+
+sal_Bool SAL_CALL
+SwXMetaField::supportsService(const ::rtl::OUString& rServiceName)
+throw (uno::RuntimeException)
+{
+ return ::sw::SupportsServiceImpl(
+ g_nServicesMetaField, g_ServicesMetaField, rServiceName);
+}
+
+uno::Sequence< ::rtl::OUString > SAL_CALL
+SwXMetaField::getSupportedServiceNames() throw (uno::RuntimeException)
+{
+ return ::sw::GetSupportedServiceNamesImpl(
+ g_nServicesMetaField, g_ServicesMetaField);
+}
+
+// XComponent
+void SAL_CALL
+SwXMetaField::addEventListener(
+ uno::Reference< lang::XEventListener> const & xListener )
+throw (uno::RuntimeException)
+{
+ return SwXMeta::addEventListener(xListener);
+}
+
+void SAL_CALL
+SwXMetaField::removeEventListener(
+ uno::Reference< lang::XEventListener> const & xListener )
+throw (uno::RuntimeException)
+{
+ return SwXMeta::removeEventListener(xListener);
+}
+
+void SAL_CALL
+SwXMetaField::dispose() throw (uno::RuntimeException)
+{
+ return SwXMeta::dispose();
+}
+
+// XTextContent
+void SAL_CALL
+SwXMetaField::attach(const uno::Reference< text::XTextRange > & i_xTextRange)
+throw (lang::IllegalArgumentException, uno::RuntimeException)
+{
+ return SwXMeta::AttachImpl(i_xTextRange, RES_TXTATR_METAFIELD);
+}
+
+uno::Reference< text::XTextRange > SAL_CALL
+SwXMetaField::getAnchor() throw (uno::RuntimeException)
+{
+ return SwXMeta::getAnchor();
+}
+
+// XPropertySet
+uno::Reference< beans::XPropertySetInfo > SAL_CALL
+SwXMetaField::getPropertySetInfo() throw (uno::RuntimeException)
+{
+ SolarMutexGuard g;
+
+ static uno::Reference< beans::XPropertySetInfo > xRef(
+ aSwMapProvider.GetPropertySet(PROPERTY_MAP_METAFIELD)
+ ->getPropertySetInfo() );
+ return xRef;
+}
+
+void SAL_CALL
+SwXMetaField::setPropertyValue(
+ const ::rtl::OUString& rPropertyName, const uno::Any& rValue)
+throw (beans::UnknownPropertyException, beans::PropertyVetoException,
+ lang::IllegalArgumentException, lang::WrappedTargetException,
+ uno::RuntimeException)
+{
+ SolarMutexGuard g;
+
+ ::sw::MetaField * const pMeta(
+ const_cast< ::sw::MetaField * >(m_pImpl->GetMetaField()) );
+ if (!pMeta)
+ throw lang::DisposedException();
+
+ if (rPropertyName.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("NumberFormat")))
+ {
+ sal_Int32 nNumberFormat(0);
+ if (rValue >>= nNumberFormat)
+ {
+ pMeta->SetNumberFormat(static_cast<sal_uInt32>(nNumberFormat));
+ }
+ }
+ else if (rPropertyName.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("IsFixedLanguage")))
+ {
+ bool b(false);
+ if (rValue >>= b)
+ {
+ pMeta->SetIsFixedLanguage(b);
+ }
+ }
+ else
+ {
+ throw beans::UnknownPropertyException();
+ }
+}
+
+uno::Any SAL_CALL
+SwXMetaField::getPropertyValue(const ::rtl::OUString& rPropertyName)
+throw (beans::UnknownPropertyException, lang::WrappedTargetException,
+ uno::RuntimeException)
+{
+ SolarMutexGuard g;
+
+ ::sw::MetaField const * const pMeta( m_pImpl->GetMetaField() );
+ if (!pMeta)
+ throw lang::DisposedException();
+
+ uno::Any any;
+
+ if (rPropertyName.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("NumberFormat")))
+ {
+ const ::rtl::OUString text( getPresentation(sal_False) );
+ any <<= static_cast<sal_Int32>(pMeta->GetNumberFormat(text));
+ }
+ else if (rPropertyName.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("IsFixedLanguage")))
+ {
+ any <<= pMeta->IsFixedLanguage();
+ }
+ else
+ {
+ throw beans::UnknownPropertyException();
+ }
+
+ return any;
+}
+
+void SAL_CALL
+SwXMetaField::addPropertyChangeListener(
+ const ::rtl::OUString& /*rPropertyName*/,
+ const uno::Reference< beans::XPropertyChangeListener >& /*xListener*/)
+throw (beans::UnknownPropertyException, lang::WrappedTargetException,
+ uno::RuntimeException)
+{
+ OSL_FAIL("SwXMetaField::addPropertyChangeListener(): not implemented");
+}
+
+void SAL_CALL
+SwXMetaField::removePropertyChangeListener(
+ const ::rtl::OUString& /*rPropertyName*/,
+ const uno::Reference< beans::XPropertyChangeListener >& /*xListener*/)
+throw (beans::UnknownPropertyException, lang::WrappedTargetException,
+ uno::RuntimeException)
+{
+ OSL_FAIL("SwXMetaField::removePropertyChangeListener(): not implemented");
+}
+
+void SAL_CALL
+SwXMetaField::addVetoableChangeListener(
+ const ::rtl::OUString& /*rPropertyName*/,
+ const uno::Reference< beans::XVetoableChangeListener >& /*xListener*/)
+throw (beans::UnknownPropertyException, lang::WrappedTargetException,
+ uno::RuntimeException)
+{
+ OSL_FAIL("SwXMetaField::addVetoableChangeListener(): not implemented");
+}
+
+void SAL_CALL
+SwXMetaField::removeVetoableChangeListener(
+ const ::rtl::OUString& /*rPropertyName*/,
+ const uno::Reference< beans::XVetoableChangeListener >& /*xListener*/)
+throw (beans::UnknownPropertyException, lang::WrappedTargetException,
+ uno::RuntimeException)
+{
+ OSL_FAIL("SwXMetaField::removeVetoableChangeListener(): not implemented");
+}
+
+#include <com/sun/star/lang/WrappedTargetRuntimeException.hpp>
+#include <com/sun/star/rdf/Statement.hpp>
+#include <com/sun/star/rdf/URI.hpp>
+#include <com/sun/star/rdf/URIs.hpp>
+#include <com/sun/star/rdf/XLiteral.hpp>
+#include <com/sun/star/rdf/XRepositorySupplier.hpp>
+#include <comphelper/processfactory.hxx>
+
+static uno::Reference<rdf::XURI> const&
+lcl_getURI(const bool bPrefix)
+{
+ static uno::Reference< uno::XComponentContext > xContext(
+ ::comphelper::getProcessComponentContext());
+ static uno::Reference< rdf::XURI > xOdfPrefix(
+ rdf::URI::createKnown(xContext, rdf::URIs::ODF_PREFIX),
+ uno::UNO_SET_THROW);
+ static uno::Reference< rdf::XURI > xOdfSuffix(
+ rdf::URI::createKnown(xContext, rdf::URIs::ODF_SUFFIX),
+ uno::UNO_SET_THROW);
+ return (bPrefix) ? xOdfPrefix : xOdfSuffix;
+}
+
+static ::rtl::OUString
+lcl_getPrefixOrSuffix(
+ uno::Reference<rdf::XRepository> const & xRepository,
+ uno::Reference<rdf::XResource> const & xMetaField,
+ uno::Reference<rdf::XURI> const & xPredicate)
+{
+ const uno::Reference<container::XEnumeration> xEnum(
+ xRepository->getStatements(xMetaField, xPredicate, 0),
+ uno::UNO_SET_THROW);
+ while (xEnum->hasMoreElements()) {
+ rdf::Statement stmt;
+ if (!(xEnum->nextElement() >>= stmt)) {
+ throw uno::RuntimeException();
+ }
+ const uno::Reference<rdf::XLiteral> xObject(stmt.Object,
+ uno::UNO_QUERY);
+ if (!xObject.is()) continue;
+ if (xEnum->hasMoreElements()) {
+ OSL_TRACE("ignoring other odf:Prefix/odf:Suffix statements");
+ }
+ return xObject->getValue();
+ }
+ return ::rtl::OUString();
+}
+
+void
+getPrefixAndSuffix(
+ const uno::Reference<frame::XModel>& xModel,
+ const uno::Reference<rdf::XMetadatable>& xMetaField,
+ ::rtl::OUString *const o_pPrefix, ::rtl::OUString *const o_pSuffix)
+{
+ try {
+ const uno::Reference<rdf::XRepositorySupplier> xRS(
+ xModel, uno::UNO_QUERY_THROW);
+ const uno::Reference<rdf::XRepository> xRepo(
+ xRS->getRDFRepository(), uno::UNO_SET_THROW);
+ const uno::Reference<rdf::XResource> xMeta(
+ xMetaField, uno::UNO_QUERY_THROW);
+ if (o_pPrefix)
+ {
+ *o_pPrefix = lcl_getPrefixOrSuffix(xRepo, xMeta, lcl_getURI(true));
+ }
+ if (o_pSuffix)
+ {
+ *o_pSuffix = lcl_getPrefixOrSuffix(xRepo, xMeta, lcl_getURI(false));
+ }
+ } catch (uno::RuntimeException &) {
+ throw;
+ } catch (uno::Exception & e) {
+ throw lang::WrappedTargetRuntimeException(
+ ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("getPrefixAndSuffix: exception")),
+ 0, uno::makeAny(e));
+ }
+}
+
+// XTextField
+::rtl::OUString SAL_CALL
+SwXMetaField::getPresentation(sal_Bool bShowCommand)
+throw (uno::RuntimeException)
+{
+ SolarMutexGuard g;
+
+ if (bShowCommand)
+ {
+//FIXME ?
+ return ::rtl::OUString();
+ }
+ else
+ {
+ // getString should check if this is invalid
+ const ::rtl::OUString content( this->getString() );
+ ::rtl::OUString prefix;
+ ::rtl::OUString suffix;
+ getPrefixAndSuffix(GetModel(), this, &prefix, &suffix);
+ return prefix + content + suffix;
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/unocore/unosect.cxx b/sw/source/core/unocore/unosect.cxx
new file mode 100644
index 000000000000..4cb913e093a3
--- /dev/null
+++ b/sw/source/core/unocore/unosect.cxx
@@ -0,0 +1,1796 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+#include <com/sun/star/beans/PropertyAttribute.hpp>
+#include <com/sun/star/text/SectionFileLink.hpp>
+
+#include <cmdid.h>
+#include <hintids.hxx>
+#include <svl/urihelper.hxx>
+#include <editeng/brshitem.hxx>
+#include <editeng/xmlcnitm.hxx>
+#include <sfx2/linkmgr.hxx>
+#include <sfx2/lnkbase.hxx>
+#include <osl/mutex.hxx>
+#include <vcl/svapp.hxx>
+#include <fmtclds.hxx>
+#include <unotextrange.hxx>
+#include <unosection.hxx>
+#include <TextCursorHelper.hxx>
+#include <unoredline.hxx>
+#include <redline.hxx>
+#include <unomap.hxx>
+#include <unocrsr.hxx>
+#include <section.hxx>
+#include <doc.hxx>
+#include <IDocumentUndoRedo.hxx>
+#include <docsh.hxx>
+#include <sfx2/docfile.hxx>
+#include <docary.hxx>
+#include <swundo.hxx>
+#include <hints.hxx>
+#include <tox.hxx>
+#include <unoidx.hxx>
+#include <doctxm.hxx>
+#include <fmtftntx.hxx>
+#include <fmtclbl.hxx>
+#include <editeng/frmdiritem.hxx>
+#include <fmtcntnt.hxx>
+#include <editeng/lrspitem.hxx>
+
+
+using namespace ::com::sun::star;
+using ::rtl::OUString;
+
+struct SwTextSectionProperties_Impl
+{
+ uno::Sequence<sal_Int8> m_Password;
+ ::rtl::OUString m_sCondition;
+ ::rtl::OUString m_sLinkFileName;
+ ::rtl::OUString m_sSectionFilter;
+ ::rtl::OUString m_sSectionRegion;
+
+ ::std::auto_ptr<SwFmtCol> m_pColItem;
+ ::std::auto_ptr<SvxBrushItem> m_pBrushItem;
+ ::std::auto_ptr<SwFmtFtnAtTxtEnd> m_pFtnItem;
+ ::std::auto_ptr<SwFmtEndAtTxtEnd> m_pEndItem;
+ ::std::auto_ptr<SvXMLAttrContainerItem> m_pXMLAttr;
+ ::std::auto_ptr<SwFmtNoBalancedColumns> m_pNoBalanceItem;
+ ::std::auto_ptr<SvxFrameDirectionItem> m_pFrameDirItem;
+ ::std::auto_ptr<SvxLRSpaceItem> m_pLRSpaceItem;
+
+ bool m_bDDE;
+ bool m_bHidden;
+ bool m_bCondHidden;
+ bool m_bProtect;
+ bool m_bEditInReadonly;
+ bool m_bUpdateType;
+
+ SwTextSectionProperties_Impl()
+ : m_bDDE(false)
+ , m_bHidden(false)
+ , m_bCondHidden(false)
+ , m_bProtect(false)
+ , m_bEditInReadonly(false)
+ , m_bUpdateType(true)
+ {
+ }
+
+};
+
+class SwXTextSection::Impl
+ : public SwClient
+{
+
+public:
+
+ SwXTextSection & m_rThis;
+ const SfxItemPropertySet & m_rPropSet;
+ SwEventListenerContainer m_ListenerContainer;
+ const bool m_bIndexHeader;
+ bool m_bIsDescriptor;
+ ::rtl::OUString m_sName;
+ ::std::auto_ptr<SwTextSectionProperties_Impl> m_pProps;
+
+ Impl( SwXTextSection & rThis,
+ SwSectionFmt *const pFmt, const bool bIndexHeader)
+ : SwClient(pFmt)
+ , m_rThis(rThis)
+ , m_rPropSet(*aSwMapProvider.GetPropertySet(PROPERTY_MAP_SECTION))
+ , m_ListenerContainer(static_cast< ::cppu::OWeakObject* >(&rThis))
+ , m_bIndexHeader(bIndexHeader)
+ // #i111177# unxsols4 (Sun C++ 5.9 SunOS_sparc) may generate wrong code
+ , m_bIsDescriptor((0 == pFmt) ? true : false)
+ , m_pProps((pFmt) ? 0 : new SwTextSectionProperties_Impl())
+ {
+ }
+
+ SwSectionFmt * GetSectionFmt() const
+ {
+ return static_cast<SwSectionFmt*>(const_cast<SwModify*>(
+ GetRegisteredIn()));
+ }
+
+ SwSectionFmt & GetSectionFmtOrThrow() const {
+ SwSectionFmt *const pFmt( GetSectionFmt() );
+ if (!pFmt) {
+ throw uno::RuntimeException(OUString(RTL_CONSTASCII_USTRINGPARAM(
+ "SwXTextSection: disposed or invalid")), 0);
+ }
+ return *pFmt;
+ }
+
+ void SAL_CALL SetPropertyValues_Impl(
+ const uno::Sequence< ::rtl::OUString >& rPropertyNames,
+ const uno::Sequence< uno::Any >& aValues)
+ throw (beans::UnknownPropertyException, beans::PropertyVetoException,
+ lang::IllegalArgumentException, lang::WrappedTargetException,
+ uno::RuntimeException);
+ uno::Sequence< uno::Any > SAL_CALL
+ GetPropertyValues_Impl(
+ const uno::Sequence< ::rtl::OUString >& rPropertyNames)
+ throw (beans::UnknownPropertyException, lang::WrappedTargetException,
+ uno::RuntimeException);
+protected:
+ // SwClient
+ virtual void Modify(const SfxPoolItem *pOld, const SfxPoolItem *pNew);
+
+};
+
+void SwXTextSection::Impl::Modify( const SfxPoolItem *pOld, const SfxPoolItem *pNew)
+{
+ ClientModify(this, pOld, pNew);
+ if (!GetRegisteredIn())
+ {
+ m_ListenerContainer.Disposing();
+ }
+}
+
+SwSectionFmt * SwXTextSection::GetFmt() const
+{
+ return m_pImpl->GetSectionFmt();
+}
+
+uno::Reference< text::XTextSection >
+SwXTextSection::CreateXTextSection(
+ SwSectionFmt *const pFmt, const bool bIndexHeader)
+{
+ // re-use existing SwXTextSection
+ // #i105557#: do not iterate over the registered clients: race condition
+ uno::Reference< text::XTextSection > xSection;
+ if (pFmt)
+ {
+ xSection.set(pFmt->GetXTextSection());
+ }
+ if ( !xSection.is() )
+ {
+ SwXTextSection *const pNew = new SwXTextSection(pFmt, bIndexHeader);
+ xSection.set(pNew);
+ if (pFmt)
+ {
+ pFmt->SetXTextSection(xSection);
+ }
+ }
+ return xSection;
+}
+
+SwXTextSection::SwXTextSection(
+ SwSectionFmt *const pFmt, const bool bIndexHeader)
+ : m_pImpl( new SwXTextSection::Impl(*this, pFmt, bIndexHeader) )
+{
+}
+
+SwXTextSection::~SwXTextSection()
+{
+}
+
+const uno::Sequence< sal_Int8 > & SwXTextSection::getUnoTunnelId()
+{
+ static uno::Sequence< sal_Int8 > aSeq = ::CreateUnoTunnelId();
+ return aSeq;
+}
+
+sal_Int64 SAL_CALL
+SwXTextSection::getSomething(const uno::Sequence< sal_Int8 >& rId)
+throw (uno::RuntimeException)
+{
+ return ::sw::UnoTunnelImpl<SwXTextSection>(rId, this);
+}
+
+uno::Reference< text::XTextSection > SAL_CALL
+SwXTextSection::getParentSection() throw (uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+
+ SwSectionFmt & rSectionFmt( m_pImpl->GetSectionFmtOrThrow() );
+
+ SwSectionFmt *const pParentFmt = rSectionFmt.GetParent();
+ const uno::Reference< text::XTextSection > xRet =
+ (pParentFmt) ? CreateXTextSection(pParentFmt) : 0;
+ return xRet;
+}
+
+uno::Sequence< uno::Reference< text::XTextSection > > SAL_CALL
+SwXTextSection::getChildSections() throw (uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+
+ SwSectionFmt & rSectionFmt( m_pImpl->GetSectionFmtOrThrow() );
+
+ SwSections aChildren;
+ rSectionFmt.GetChildSections(aChildren, SORTSECT_NOT, sal_False);
+ uno::Sequence<uno::Reference<text::XTextSection> > aSeq(aChildren.Count());
+ uno::Reference< text::XTextSection > * pArray = aSeq.getArray();
+ for (sal_uInt16 i = 0; i < aChildren.Count(); i++)
+ {
+ SwSectionFmt *const pChild = aChildren.GetObject(i)->GetFmt();
+ pArray[i] = CreateXTextSection(pChild);
+ }
+ return aSeq;
+}
+
+void SAL_CALL
+SwXTextSection::attach(const uno::Reference< text::XTextRange > & xTextRange)
+throw (lang::IllegalArgumentException, uno::RuntimeException)
+{
+ SolarMutexGuard g;
+
+ if (!m_pImpl->m_bIsDescriptor)
+ {
+ throw uno::RuntimeException();
+ }
+
+ uno::Reference<lang::XUnoTunnel> xRangeTunnel( xTextRange, uno::UNO_QUERY);
+ SwXTextRange* pRange = 0;
+ OTextCursorHelper* pCursor = 0;
+ if(xRangeTunnel.is())
+ {
+ pRange = ::sw::UnoTunnelGetImplementation<SwXTextRange>(xRangeTunnel);
+ pCursor =
+ ::sw::UnoTunnelGetImplementation<OTextCursorHelper>(xRangeTunnel);
+ }
+
+ SwDoc *const pDoc =
+ (pRange) ? pRange->GetDoc() : ((pCursor) ? pCursor->GetDoc() : 0);
+ if (!pDoc)
+ {
+ throw lang::IllegalArgumentException();
+ }
+
+ SwUnoInternalPaM aPam(*pDoc);
+ //das muss jetzt sal_True liefern
+ ::sw::XTextRangeToSwPaM(aPam, xTextRange);
+ UnoActionContext aCont(pDoc);
+ pDoc->GetIDocumentUndoRedo().StartUndo( UNDO_INSSECTION, NULL );
+
+ if (!m_pImpl->m_sName.getLength())
+ {
+ m_pImpl->m_sName = C2U("TextSection");
+ }
+ SectionType eType = (m_pImpl->m_pProps->m_bDDE)
+ ? DDE_LINK_SECTION
+ : ((m_pImpl->m_pProps->m_sLinkFileName.getLength() ||
+ m_pImpl->m_pProps->m_sSectionRegion.getLength())
+ ? FILE_LINK_SECTION : CONTENT_SECTION);
+ // index header section?
+ if (m_pImpl->m_bIndexHeader)
+ {
+ // caller wants an index header section, but will only
+ // give him one if a) we are inside an index, and b) said
+ // index doesn't yet have a header section.
+ const SwTOXBase* pBase = aPam.GetDoc()->GetCurTOX(*aPam.Start());
+
+ // are we inside an index?
+ if (pBase)
+ {
+ // get all child sections
+ SwSections aSectionsArr;
+ static_cast<const SwTOXBaseSection*>(pBase)->GetFmt()->
+ GetChildSections(aSectionsArr);
+
+ // and search for current header section
+ const sal_uInt16 nCount = aSectionsArr.Count();
+ sal_Bool bHeaderPresent = sal_False;
+ for(sal_uInt16 i = 0; i < nCount; i++)
+ {
+ bHeaderPresent |=
+ (aSectionsArr[i]->GetType() == TOX_HEADER_SECTION);
+ }
+ if (! bHeaderPresent)
+ {
+ eType = TOX_HEADER_SECTION;
+ }
+ }
+ }
+
+ String tmp(m_pImpl->m_sName);
+ SwSectionData aSect(eType, pDoc->GetUniqueSectionName(&tmp));
+ aSect.SetCondition(m_pImpl->m_pProps->m_sCondition);
+ ::rtl::OUStringBuffer sLinkNameBuf(m_pImpl->m_pProps->m_sLinkFileName);
+ sLinkNameBuf.append(sfx2::cTokenSeperator);
+ sLinkNameBuf.append(m_pImpl->m_pProps->m_sSectionFilter);
+ sLinkNameBuf.append(sfx2::cTokenSeperator);
+ sLinkNameBuf.append(m_pImpl->m_pProps->m_sSectionRegion);
+ aSect.SetLinkFileName(sLinkNameBuf.makeStringAndClear());
+
+ aSect.SetHidden(m_pImpl->m_pProps->m_bHidden);
+ aSect.SetProtectFlag(m_pImpl->m_pProps->m_bProtect);
+ aSect.SetEditInReadonlyFlag(m_pImpl->m_pProps->m_bEditInReadonly);
+
+ SfxItemSet aSet(pDoc->GetAttrPool(),
+ RES_COL, RES_COL,
+ RES_BACKGROUND, RES_BACKGROUND,
+ RES_FTN_AT_TXTEND, RES_FRAMEDIR,
+ RES_LR_SPACE, RES_LR_SPACE,
+ RES_UNKNOWNATR_CONTAINER,RES_UNKNOWNATR_CONTAINER,
+ 0);
+ if (m_pImpl->m_pProps->m_pBrushItem.get())
+ {
+ aSet.Put(*m_pImpl->m_pProps->m_pBrushItem);
+ }
+ if (m_pImpl->m_pProps->m_pColItem.get())
+ {
+ aSet.Put(*m_pImpl->m_pProps->m_pColItem);
+ }
+ if (m_pImpl->m_pProps->m_pFtnItem.get())
+ {
+ aSet.Put(*m_pImpl->m_pProps->m_pFtnItem);
+ }
+ if (m_pImpl->m_pProps->m_pEndItem.get())
+ {
+ aSet.Put(*m_pImpl->m_pProps->m_pEndItem);
+ }
+ if (m_pImpl->m_pProps->m_pXMLAttr.get())
+ {
+ aSet.Put(*m_pImpl->m_pProps->m_pXMLAttr);
+ }
+ if (m_pImpl->m_pProps->m_pNoBalanceItem.get())
+ {
+ aSet.Put(*m_pImpl->m_pProps->m_pNoBalanceItem);
+ }
+ if (m_pImpl->m_pProps->m_pFrameDirItem.get())
+ {
+ aSet.Put(*m_pImpl->m_pProps->m_pFrameDirItem);
+ }
+ if (m_pImpl->m_pProps->m_pLRSpaceItem.get())
+ {
+ aSet.Put(*m_pImpl->m_pProps->m_pLRSpaceItem);
+ }
+ // section password
+ if (m_pImpl->m_pProps->m_Password.getLength() > 0)
+ {
+ aSect.SetPassword(m_pImpl->m_pProps->m_Password);
+ }
+
+ SwSection *const pRet =
+ pDoc->InsertSwSection( aPam, aSect, 0, aSet.Count() ? &aSet : 0 );
+ pRet->GetFmt()->Add(m_pImpl.get());
+ pRet->GetFmt()->SetXObject(static_cast< ::cppu::OWeakObject*>(this));
+
+ // XML import must hide sections depending on their old
+ // condition status
+ if (m_pImpl->m_pProps->m_sCondition.getLength() != 0)
+ {
+ pRet->SetCondHidden(m_pImpl->m_pProps->m_bCondHidden);
+ }
+
+ // set update type if DDE link (and connect, if necessary)
+ if (m_pImpl->m_pProps->m_bDDE)
+ {
+ if (! pRet->IsConnected())
+ {
+ pRet->CreateLink(CREATE_CONNECT);
+ }
+ pRet->SetUpdateType( static_cast< sal_uInt16 >(
+ (m_pImpl->m_pProps->m_bUpdateType) ?
+ sfx2::LINKUPDATE_ALWAYS : sfx2::LINKUPDATE_ONCALL) );
+ }
+
+ // Undo-Klammerung hier beenden
+ pDoc->GetIDocumentUndoRedo().EndUndo( UNDO_INSSECTION, NULL );
+ m_pImpl->m_pProps.reset();
+ m_pImpl->m_bIsDescriptor = false;
+}
+
+uno::Reference< text::XTextRange > SAL_CALL
+SwXTextSection::getAnchor() throw (uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+
+ uno::Reference< text::XTextRange > xRet;
+ SwSectionFmt *const pSectFmt = m_pImpl->GetSectionFmt();
+ if(pSectFmt)
+ {
+ const SwNodeIndex* pIdx;
+ if( 0 != ( pSectFmt->GetSection() ) &&
+ 0 != ( pIdx = pSectFmt->GetCntnt().GetCntntIdx() ) &&
+ pIdx->GetNode().GetNodes().IsDocNodes() )
+ {
+ SwPaM aPaM(*pIdx);
+ aPaM.Move( fnMoveForward, fnGoCntnt );
+
+ const SwEndNode* pEndNode = pIdx->GetNode().EndOfSectionNode();
+ SwPaM aEnd(*pEndNode);
+ aEnd.Move( fnMoveBackward, fnGoCntnt );
+ xRet = SwXTextRange::CreateXTextRange(*pSectFmt->GetDoc(),
+ *aPaM.Start(), aEnd.Start());
+ }
+ }
+ return xRet;
+}
+
+void SAL_CALL SwXTextSection::dispose() throw (uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+
+ SwSectionFmt *const pSectFmt = m_pImpl->GetSectionFmt();
+ if (pSectFmt)
+ {
+ pSectFmt->GetDoc()->DelSectionFmt( pSectFmt );
+ }
+}
+
+void SAL_CALL SwXTextSection::addEventListener(
+ const uno::Reference< lang::XEventListener > & xListener)
+throw (uno::RuntimeException)
+{
+ SolarMutexGuard g;
+
+ if (!m_pImpl->GetSectionFmt())
+ {
+ throw uno::RuntimeException();
+ }
+ m_pImpl->m_ListenerContainer.AddListener(xListener);
+}
+
+void SAL_CALL SwXTextSection::removeEventListener(
+ const uno::Reference< lang::XEventListener > & xListener)
+throw (uno::RuntimeException)
+{
+ SolarMutexGuard g;
+
+ if (!m_pImpl->GetSectionFmt() ||
+ !m_pImpl->m_ListenerContainer.RemoveListener(xListener))
+ {
+ throw uno::RuntimeException();
+ }
+}
+
+uno::Reference< beans::XPropertySetInfo > SAL_CALL
+SwXTextSection::getPropertySetInfo() throw (uno::RuntimeException)
+{
+ SolarMutexGuard g;
+
+ static const uno::Reference< beans::XPropertySetInfo > aRef =
+ m_pImpl->m_rPropSet.getPropertySetInfo();
+ return aRef;
+}
+
+static void
+lcl_UpdateLinkType(SwSection & rSection, bool const bLinkUpdateAlways = true)
+{
+ if (rSection.GetType() == DDE_LINK_SECTION)
+ {
+ // set update type; needs an established link
+ if (!rSection.IsConnected())
+ {
+ rSection.CreateLink(CREATE_CONNECT);
+ }
+ rSection.SetUpdateType( static_cast< sal_uInt16 >((bLinkUpdateAlways)
+ ? sfx2::LINKUPDATE_ALWAYS : sfx2::LINKUPDATE_ONCALL) );
+ }
+}
+
+static void
+lcl_UpdateSection(SwSectionFmt *const pFmt,
+ ::std::auto_ptr<SwSectionData> const& pSectionData,
+ ::std::auto_ptr<SfxItemSet> const& pItemSet,
+ bool const bLinkModeChanged, bool const bLinkUpdateAlways = true)
+{
+ if (pFmt)
+ {
+ SwSection & rSection = *pFmt->GetSection();
+ SwDoc *const pDoc = pFmt->GetDoc();
+ SwSectionFmts const& rFmts = pDoc->GetSections();
+ UnoActionContext aContext(pDoc);
+ for (sal_uInt16 i = 0; i < rFmts.Count(); i++)
+ {
+ if (rFmts[i]->GetSection()->GetSectionName()
+ == rSection.GetSectionName())
+ {
+ pDoc->UpdateSection(i, *pSectionData, pItemSet.get(),
+ pDoc->IsInReading());
+ {
+ // temporarily remove actions to allow cursor update
+ UnoActionRemoveContext aRemoveContext( pDoc );
+ }
+
+ if (bLinkModeChanged)
+ {
+ lcl_UpdateLinkType(rSection, bLinkUpdateAlways);
+ }
+ // section found and processed: break from loop
+ break;
+ }
+ }
+ }
+}
+
+void SwXTextSection::Impl::SetPropertyValues_Impl(
+ const uno::Sequence< OUString >& rPropertyNames,
+ const uno::Sequence< uno::Any >& rValues)
+throw (beans::UnknownPropertyException, beans::PropertyVetoException,
+ lang::IllegalArgumentException, lang::WrappedTargetException,
+ uno::RuntimeException)
+{
+ if(rPropertyNames.getLength() != rValues.getLength())
+ {
+ throw lang::IllegalArgumentException();
+ }
+ SwSectionFmt *const pFmt = GetSectionFmt();
+ if (!pFmt && !m_bIsDescriptor)
+ {
+ throw uno::RuntimeException();
+ }
+
+ ::std::auto_ptr<SwSectionData> const pSectionData(
+ (pFmt) ? new SwSectionData(*pFmt->GetSection()) : 0);
+
+ OUString const*const pPropertyNames = rPropertyNames.getConstArray();
+ uno::Any const*const pValues = rValues.getConstArray();
+ ::std::auto_ptr<SfxItemSet> pItemSet;
+ sal_Bool bLinkModeChanged = sal_False;
+ sal_Bool bLinkMode = sal_False;
+
+ for (sal_Int32 nProperty = 0; nProperty < rPropertyNames.getLength();
+ nProperty++)
+ {
+ SfxItemPropertySimpleEntry const*const pEntry =
+ m_rPropSet.getPropertyMap()->getByName(pPropertyNames[nProperty]);
+ if (!pEntry)
+ {
+ throw beans::UnknownPropertyException(
+ OUString(RTL_CONSTASCII_USTRINGPARAM("Unknown property: "))
+ + pPropertyNames[nProperty],
+ static_cast<cppu::OWeakObject *>(& m_rThis));
+ }
+ if (pEntry->nFlags & beans::PropertyAttribute::READONLY)
+ {
+ throw beans::PropertyVetoException(
+ OUString(RTL_CONSTASCII_USTRINGPARAM("Property is read-only: "))
+ + pPropertyNames[nProperty],
+ static_cast<cppu::OWeakObject *>(& m_rThis));
+ }
+ switch (pEntry->nWID)
+ {
+ case WID_SECT_CONDITION:
+ {
+ OUString uTmp;
+ pValues[nProperty] >>= uTmp;
+ if (m_bIsDescriptor)
+ {
+ m_pProps->m_sCondition = uTmp;
+ }
+ else
+ {
+ pSectionData->SetCondition(uTmp);
+ }
+ }
+ break;
+ case WID_SECT_DDE_TYPE:
+ case WID_SECT_DDE_FILE:
+ case WID_SECT_DDE_ELEMENT:
+ {
+ OUString uTmp;
+ pValues[nProperty] >>= uTmp;
+ String sTmp(uTmp);
+ if (m_bIsDescriptor)
+ {
+ if (!m_pProps->m_bDDE)
+ {
+ ::rtl::OUStringBuffer buf;
+ buf.append(sfx2::cTokenSeperator);
+ buf.append(sfx2::cTokenSeperator);
+ m_pProps->m_sLinkFileName = buf.makeStringAndClear();
+ m_pProps->m_bDDE = true;
+ }
+ String sLinkFileName(m_pProps->m_sLinkFileName);
+ sLinkFileName.SetToken(pEntry->nWID - WID_SECT_DDE_TYPE,
+ sfx2::cTokenSeperator, sTmp);
+ m_pProps->m_sLinkFileName = sLinkFileName;
+ }
+ else
+ {
+ String sLinkFileName(pSectionData->GetLinkFileName());
+ if (pSectionData->GetType() != DDE_LINK_SECTION)
+ {
+ sLinkFileName = sfx2::cTokenSeperator;
+ sLinkFileName += sfx2::cTokenSeperator;
+ pSectionData->SetType(DDE_LINK_SECTION);
+ }
+ sLinkFileName.SetToken(pEntry->nWID - WID_SECT_DDE_TYPE,
+ sfx2::cTokenSeperator, sTmp);
+ pSectionData->SetLinkFileName(sLinkFileName);
+ }
+ }
+ break;
+ case WID_SECT_DDE_AUTOUPDATE:
+ {
+ sal_Bool bVal(sal_False);
+ if (!(pValues[nProperty] >>= bVal))
+ {
+ throw lang::IllegalArgumentException();
+ }
+ if (m_bIsDescriptor)
+ {
+ m_pProps->m_bUpdateType = bVal;
+ }
+ else
+ {
+ bLinkModeChanged = sal_True;
+ bLinkMode = bVal;
+ }
+ }
+ break;
+ case WID_SECT_LINK:
+ {
+ text::SectionFileLink aLink;
+ if (!(pValues[nProperty] >>= aLink))
+ {
+ throw lang::IllegalArgumentException();
+ }
+ if (m_bIsDescriptor)
+ {
+ m_pProps->m_bDDE = sal_False;
+ m_pProps->m_sLinkFileName = aLink.FileURL;
+ m_pProps->m_sSectionFilter = aLink.FilterName;
+ }
+ else
+ {
+ if (pSectionData->GetType() != FILE_LINK_SECTION &&
+ aLink.FileURL.getLength())
+ {
+ pSectionData->SetType(FILE_LINK_SECTION);
+ }
+ ::rtl::OUStringBuffer sFileNameBuf;
+ if (aLink.FileURL.getLength())
+ {
+ sFileNameBuf.append( URIHelper::SmartRel2Abs(
+ pFmt->GetDoc()->GetDocShell()->GetMedium()
+ ->GetURLObject(),
+ aLink.FileURL, URIHelper::GetMaybeFileHdl()));
+ }
+ sFileNameBuf.append(sfx2::cTokenSeperator);
+ sFileNameBuf.append(aLink.FilterName);
+ sFileNameBuf.append(sfx2::cTokenSeperator);
+ sFileNameBuf.append(
+ pSectionData->GetLinkFileName().GetToken(2,
+ sfx2::cTokenSeperator));
+ const ::rtl::OUString sFileName(
+ sFileNameBuf.makeStringAndClear());
+ pSectionData->SetLinkFileName(sFileName);
+ if (sFileName.getLength() < 3)
+ {
+ pSectionData->SetType(CONTENT_SECTION);
+ }
+ }
+ }
+ break;
+ case WID_SECT_REGION:
+ {
+ OUString sLink;
+ pValues[nProperty] >>= sLink;
+ if (m_bIsDescriptor)
+ {
+ m_pProps->m_bDDE = sal_False;
+ m_pProps->m_sSectionRegion = sLink;
+ }
+ else
+ {
+ if (pSectionData->GetType() != FILE_LINK_SECTION &&
+ sLink.getLength())
+ {
+ pSectionData->SetType(FILE_LINK_SECTION);
+ }
+ String sSectLink(pSectionData->GetLinkFileName());
+ while (3 < sSectLink.GetTokenCount(sfx2::cTokenSeperator))
+ {
+ sSectLink += sfx2::cTokenSeperator;
+ }
+ sSectLink.SetToken(2, sfx2::cTokenSeperator, sLink);
+ pSectionData->SetLinkFileName(sSectLink);
+ if (sSectLink.Len() < 3)
+ {
+ pSectionData->SetType(CONTENT_SECTION);
+ }
+ }
+ }
+ break;
+ case WID_SECT_VISIBLE:
+ {
+ sal_Bool bVal(sal_False);
+ if (!(pValues[nProperty] >>= bVal))
+ {
+ throw lang::IllegalArgumentException();
+ }
+ if (m_bIsDescriptor)
+ {
+ m_pProps->m_bHidden = !bVal;
+ }
+ else
+ {
+ pSectionData->SetHidden(!bVal);
+ }
+ }
+ break;
+ case WID_SECT_CURRENTLY_VISIBLE:
+ {
+ sal_Bool bVal(sal_False);
+ if (!(pValues[nProperty] >>= bVal))
+ {
+ throw lang::IllegalArgumentException();
+ }
+ if (m_bIsDescriptor)
+ {
+ m_pProps->m_bCondHidden = !bVal;
+ }
+ else
+ {
+ if (pSectionData->GetCondition().Len() != 0)
+ {
+ pSectionData->SetCondHidden(!bVal);
+ }
+ }
+ }
+ break;
+ case WID_SECT_PROTECTED:
+ {
+ sal_Bool bVal(sal_False);
+ if (!(pValues[nProperty] >>= bVal))
+ {
+ throw lang::IllegalArgumentException();
+ }
+ if (m_bIsDescriptor)
+ {
+ m_pProps->m_bProtect = bVal;
+ }
+ else
+ {
+ pSectionData->SetProtectFlag(bVal);
+ }
+ }
+ break;
+ case WID_SECT_EDIT_IN_READONLY:
+ {
+ sal_Bool bVal(sal_False);
+ if (!(pValues[nProperty] >>= bVal))
+ {
+ throw lang::IllegalArgumentException();
+ }
+ if (m_bIsDescriptor)
+ {
+ m_pProps->m_bEditInReadonly = bVal;
+ }
+ else
+ {
+ pSectionData->SetEditInReadonlyFlag(bVal);
+ }
+ }
+ break;
+ case WID_SECT_PASSWORD:
+ {
+ uno::Sequence<sal_Int8> aSeq;
+ pValues[nProperty] >>= aSeq;
+ if (m_bIsDescriptor)
+ {
+ m_pProps->m_Password = aSeq;
+ }
+ else
+ {
+ pSectionData->SetPassword(aSeq);
+ }
+ }
+ break;
+ default:
+ {
+ if (pFmt)
+ {
+ const SfxItemSet& rOldAttrSet = pFmt->GetAttrSet();
+ pItemSet.reset( new SfxItemSet(*rOldAttrSet.GetPool(),
+ pEntry->nWID, pEntry->nWID, 0));
+ pItemSet->Put(rOldAttrSet);
+ m_rPropSet.setPropertyValue(*pEntry,
+ pValues[nProperty], *pItemSet);
+ }
+ else
+ {
+ SfxPoolItem* pPutItem = 0;
+ if (RES_COL == pEntry->nWID)
+ {
+ if (!m_pProps->m_pColItem.get())
+ {
+ m_pProps->m_pColItem.reset(new SwFmtCol);
+ }
+ pPutItem = m_pProps->m_pColItem.get();
+ }
+ else if (RES_BACKGROUND == pEntry->nWID)
+ {
+ if (!m_pProps->m_pBrushItem.get())
+ {
+ m_pProps->m_pBrushItem.reset(
+ new SvxBrushItem(RES_BACKGROUND));
+ }
+ pPutItem = m_pProps->m_pBrushItem.get();
+ }
+ else if (RES_FTN_AT_TXTEND == pEntry->nWID)
+ {
+ if (!m_pProps->m_pFtnItem.get())
+ {
+ m_pProps->m_pFtnItem.reset(new SwFmtFtnAtTxtEnd);
+ }
+ pPutItem = m_pProps->m_pFtnItem.get();
+ }
+ else if (RES_END_AT_TXTEND == pEntry->nWID)
+ {
+ if (!m_pProps->m_pEndItem.get())
+ {
+ m_pProps->m_pEndItem.reset(new SwFmtEndAtTxtEnd);
+ }
+ pPutItem = m_pProps->m_pEndItem.get();
+ }
+ else if (RES_UNKNOWNATR_CONTAINER== pEntry->nWID)
+ {
+ if (!m_pProps->m_pXMLAttr.get())
+ {
+ m_pProps->m_pXMLAttr.reset(
+ new SvXMLAttrContainerItem(
+ RES_UNKNOWNATR_CONTAINER));
+ }
+ pPutItem = m_pProps->m_pXMLAttr.get();
+ }
+ else if (RES_COLUMNBALANCE== pEntry->nWID)
+ {
+ if (!m_pProps->m_pNoBalanceItem.get())
+ {
+ m_pProps->m_pNoBalanceItem.reset(
+ new SwFmtNoBalancedColumns(RES_COLUMNBALANCE));
+ }
+ pPutItem = m_pProps->m_pNoBalanceItem.get();
+ }
+ else if (RES_FRAMEDIR == pEntry->nWID)
+ {
+ if (!m_pProps->m_pFrameDirItem.get())
+ {
+ m_pProps->m_pFrameDirItem.reset(
+ new SvxFrameDirectionItem(
+ FRMDIR_HORI_LEFT_TOP, RES_FRAMEDIR));
+ }
+ pPutItem = m_pProps->m_pFrameDirItem.get();
+ }
+ else if (RES_LR_SPACE == pEntry->nWID)
+ {
+ if (!m_pProps->m_pLRSpaceItem.get())
+ {
+ m_pProps->m_pLRSpaceItem.reset(
+ new SvxLRSpaceItem( RES_LR_SPACE ));
+ }
+ pPutItem = m_pProps->m_pLRSpaceItem.get();
+ }
+ if (pPutItem)
+ {
+ pPutItem->PutValue(pValues[nProperty],
+ pEntry->nMemberId);
+ }
+ }
+ }
+ }
+ }
+
+ lcl_UpdateSection(pFmt, pSectionData, pItemSet, bLinkModeChanged,
+ bLinkMode);
+}
+
+void SAL_CALL
+SwXTextSection::setPropertyValues(
+ const uno::Sequence< ::rtl::OUString >& rPropertyNames,
+ const uno::Sequence< uno::Any >& rValues)
+throw (beans::PropertyVetoException, lang::IllegalArgumentException,
+ lang::WrappedTargetException, uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+
+ // workaround for bad designed API
+ try
+ {
+ m_pImpl->SetPropertyValues_Impl( rPropertyNames, rValues );
+ }
+ catch (beans::UnknownPropertyException &rException)
+ {
+ // wrap the original (here not allowed) exception in
+ // a WrappedTargetException that gets thrown instead.
+ lang::WrappedTargetException aWExc;
+ aWExc.TargetException <<= rException;
+ throw aWExc;
+ }
+}
+
+void SwXTextSection::setPropertyValue(
+ const OUString& rPropertyName, const uno::Any& rValue)
+throw (beans::UnknownPropertyException, beans::PropertyVetoException,
+ lang::IllegalArgumentException, lang::WrappedTargetException,
+ uno::RuntimeException )
+{
+ SolarMutexGuard aGuard;
+
+ uno::Sequence< ::rtl::OUString > aPropertyNames(1);
+ aPropertyNames.getArray()[0] = rPropertyName;
+ uno::Sequence< uno::Any > aValues(1);
+ aValues.getArray()[0] = rValue;
+ m_pImpl->SetPropertyValues_Impl( aPropertyNames, aValues );
+}
+
+uno::Sequence< uno::Any >
+SwXTextSection::Impl::GetPropertyValues_Impl(
+ const uno::Sequence< OUString > & rPropertyNames )
+throw (beans::UnknownPropertyException, lang::WrappedTargetException,
+ uno::RuntimeException)
+{
+ SwSectionFmt *const pFmt = GetSectionFmt();
+ if (!pFmt && !m_bIsDescriptor)
+ {
+ throw uno::RuntimeException();
+ }
+
+ uno::Sequence< uno::Any > aRet(rPropertyNames.getLength());
+ uno::Any* pRet = aRet.getArray();
+ SwSection *const pSect = (pFmt) ? pFmt->GetSection() : 0;
+ const OUString* pPropertyNames = rPropertyNames.getConstArray();
+
+ for (sal_Int32 nProperty = 0; nProperty < rPropertyNames.getLength();
+ nProperty++)
+ {
+ SfxItemPropertySimpleEntry const*const pEntry =
+ m_rPropSet.getPropertyMap()->getByName(pPropertyNames[nProperty]);
+ if (!pEntry)
+ {
+ throw beans::UnknownPropertyException(
+ OUString(RTL_CONSTASCII_USTRINGPARAM("Unknown property: "))
+ + pPropertyNames[nProperty],
+ static_cast<cppu::OWeakObject *>(& m_rThis));
+ }
+ switch(pEntry->nWID)
+ {
+ case WID_SECT_CONDITION:
+ {
+ OUString uTmp( (m_bIsDescriptor)
+ ? m_pProps->m_sCondition
+ : ::rtl::OUString(pSect->GetCondition()));
+ pRet[nProperty] <<= uTmp;
+ }
+ break;
+ case WID_SECT_DDE_TYPE:
+ case WID_SECT_DDE_FILE:
+ case WID_SECT_DDE_ELEMENT:
+ {
+ ::rtl::OUString sRet;
+ if (m_bIsDescriptor)
+ {
+ if (m_pProps->m_bDDE)
+ {
+ sRet = m_pProps->m_sLinkFileName;
+ }
+ }
+ else if (DDE_LINK_SECTION == pSect->GetType())
+ {
+ sRet = pSect->GetLinkFileName();
+ }
+ sal_Int32 nDummy(0);
+ sRet = sRet.getToken(pEntry->nWID - WID_SECT_DDE_TYPE,
+ sfx2::cTokenSeperator, nDummy);
+ pRet[nProperty] <<= sRet;
+ }
+ break;
+ case WID_SECT_DDE_AUTOUPDATE:
+ {
+ // GetUpdateType() returns .._ALWAYS or .._ONCALL
+ if (pSect && pSect->IsLinkType() && pSect->IsConnected()) // #i73247#
+ {
+ const sal_Bool bTemp =
+ (pSect->GetUpdateType() == sfx2::LINKUPDATE_ALWAYS);
+ pRet[nProperty] <<= bTemp;
+ }
+ }
+ break;
+ case WID_SECT_LINK :
+ {
+ text::SectionFileLink aLink;
+ if (m_bIsDescriptor)
+ {
+ if (!m_pProps->m_bDDE)
+ {
+ aLink.FileURL = m_pProps->m_sLinkFileName;
+ aLink.FilterName = m_pProps->m_sSectionFilter;
+ }
+ }
+ else if (FILE_LINK_SECTION == pSect->GetType())
+ {
+ ::rtl::OUString sRet( pSect->GetLinkFileName() );
+ sal_Int32 nIndex(0);
+ aLink.FileURL =
+ sRet.getToken(0, sfx2::cTokenSeperator, nIndex);
+ aLink.FilterName =
+ sRet.getToken(0, sfx2::cTokenSeperator, nIndex);
+ }
+ pRet[nProperty] <<= aLink;
+ }
+ break;
+ case WID_SECT_REGION :
+ {
+ ::rtl::OUString sRet;
+ if (m_bIsDescriptor)
+ {
+ sRet = m_pProps->m_sSectionRegion;
+ }
+ else if (FILE_LINK_SECTION == pSect->GetType())
+ {
+ sRet = pSect->GetLinkFileName().GetToken(2,
+ sfx2::cTokenSeperator);
+ }
+ pRet[nProperty] <<= sRet;
+ }
+ break;
+ case WID_SECT_VISIBLE :
+ {
+ const sal_Bool bTemp = (m_bIsDescriptor)
+ ? !m_pProps->m_bHidden : !pSect->IsHidden();
+ pRet[nProperty] <<= bTemp;
+ }
+ break;
+ case WID_SECT_CURRENTLY_VISIBLE:
+ {
+ const sal_Bool bTemp = (m_bIsDescriptor)
+ ? !m_pProps->m_bCondHidden : !pSect->IsCondHidden();
+ pRet[nProperty] <<= bTemp;
+ }
+ break;
+ case WID_SECT_PROTECTED:
+ {
+ const sal_Bool bTemp = (m_bIsDescriptor)
+ ? m_pProps->m_bProtect : pSect->IsProtect();
+ pRet[nProperty] <<= bTemp;
+ }
+ break;
+ case WID_SECT_EDIT_IN_READONLY:
+ {
+ const sal_Bool bTemp = (m_bIsDescriptor)
+ ? m_pProps->m_bEditInReadonly : pSect->IsEditInReadonly();
+ pRet[nProperty] <<= bTemp;
+ }
+ break;
+ case FN_PARAM_LINK_DISPLAY_NAME:
+ {
+ if (pFmt)
+ {
+ pRet[nProperty] <<=
+ OUString(pFmt->GetSection()->GetSectionName());
+ }
+ }
+ break;
+ case WID_SECT_DOCUMENT_INDEX:
+ {
+ // search enclosing index
+ SwSection* pEnclosingSection = pSect;
+ while ((pEnclosingSection != NULL) &&
+ (TOX_CONTENT_SECTION != pEnclosingSection->GetType()))
+ {
+ pEnclosingSection = pEnclosingSection->GetParent();
+ }
+ if (pEnclosingSection)
+ {
+ // convert section to TOXBase and get SwXDocumentIndex
+ SwTOXBaseSection *const pTOXBaseSect =
+ PTR_CAST(SwTOXBaseSection, pEnclosingSection);
+ const uno::Reference<text::XDocumentIndex> xIndex =
+ SwXDocumentIndex::CreateXDocumentIndex(
+ *pTOXBaseSect->GetFmt()->GetDoc(), *pTOXBaseSect);
+ pRet[nProperty] <<= xIndex;
+ }
+ // else: no enclosing index found -> empty return value
+ }
+ break;
+ case WID_SECT_IS_GLOBAL_DOC_SECTION:
+ {
+ const sal_Bool bRet = (NULL == pFmt) ? sal_False :
+ static_cast<sal_Bool>(NULL != pFmt->GetGlobalDocSection());
+ pRet[nProperty] <<= bRet;
+ }
+ break;
+ case FN_UNO_ANCHOR_TYPES:
+ case FN_UNO_TEXT_WRAP:
+ case FN_UNO_ANCHOR_TYPE:
+ ::sw::GetDefaultTextContentValue(
+ pRet[nProperty], OUString(), pEntry->nWID);
+ break;
+ case FN_UNO_REDLINE_NODE_START:
+ case FN_UNO_REDLINE_NODE_END:
+ {
+ if (!pFmt)
+ break; // #i73247#
+ SwNode* pSectNode = pFmt->GetSectionNode();
+ if (FN_UNO_REDLINE_NODE_END == pEntry->nWID)
+ {
+ pSectNode = pSectNode->EndOfSectionNode();
+ }
+ const SwRedlineTbl& rRedTbl =
+ pFmt->GetDoc()->GetRedlineTbl();
+ for (sal_uInt16 nRed = 0; nRed < rRedTbl.Count(); nRed++)
+ {
+ const SwRedline* pRedline = rRedTbl[nRed];
+ SwNode const*const pRedPointNode = pRedline->GetNode(sal_True);
+ SwNode const*const pRedMarkNode = pRedline->GetNode(sal_False);
+ if ((pRedPointNode == pSectNode) ||
+ (pRedMarkNode == pSectNode))
+ {
+ SwNode const*const pStartOfRedline =
+ (SwNodeIndex(*pRedPointNode) <=
+ SwNodeIndex(*pRedMarkNode))
+ ? pRedPointNode : pRedMarkNode;
+ const bool bIsStart = (pStartOfRedline == pSectNode);
+ pRet[nProperty] <<=
+ SwXRedlinePortion::CreateRedlineProperties(
+ *pRedline, bIsStart);
+ break;
+ }
+ }
+ }
+ break;
+ case WID_SECT_PASSWORD:
+ {
+ pRet[nProperty] <<= (m_bIsDescriptor)
+ ? m_pProps->m_Password : pSect->GetPassword();
+ }
+ break;
+ default:
+ {
+ if (pFmt)
+ {
+ m_rPropSet.getPropertyValue(*pEntry,
+ pFmt->GetAttrSet(), pRet[nProperty]);
+ }
+ else
+ {
+ const SfxPoolItem* pQueryItem = 0;
+ if (RES_COL == pEntry->nWID)
+ {
+ if (!m_pProps->m_pColItem.get())
+ {
+ m_pProps->m_pColItem.reset(new SwFmtCol);
+ }
+ pQueryItem = m_pProps->m_pColItem.get();
+ }
+ else if (RES_BACKGROUND == pEntry->nWID)
+ {
+ if (!m_pProps->m_pBrushItem.get())
+ {
+ m_pProps->m_pBrushItem.reset(
+ new SvxBrushItem(RES_BACKGROUND));
+ }
+ pQueryItem = m_pProps->m_pBrushItem.get();
+ }
+ else if (RES_FTN_AT_TXTEND == pEntry->nWID)
+ {
+ if (!m_pProps->m_pFtnItem.get())
+ {
+ m_pProps->m_pFtnItem.reset(new SwFmtFtnAtTxtEnd);
+ }
+ pQueryItem = m_pProps->m_pFtnItem.get();
+ }
+ else if (RES_END_AT_TXTEND == pEntry->nWID)
+ {
+ if (!m_pProps->m_pEndItem.get())
+ {
+ m_pProps->m_pEndItem.reset(new SwFmtEndAtTxtEnd);
+ }
+ pQueryItem = m_pProps->m_pEndItem.get();
+ }
+ else if (RES_UNKNOWNATR_CONTAINER== pEntry->nWID)
+ {
+ if (!m_pProps->m_pXMLAttr.get())
+ {
+ m_pProps->m_pXMLAttr.reset(
+ new SvXMLAttrContainerItem);
+ }
+ pQueryItem = m_pProps->m_pXMLAttr.get();
+ }
+ else if (RES_COLUMNBALANCE== pEntry->nWID)
+ {
+ if (!m_pProps->m_pNoBalanceItem.get())
+ {
+ m_pProps->m_pNoBalanceItem.reset(
+ new SwFmtNoBalancedColumns);
+ }
+ pQueryItem = m_pProps->m_pNoBalanceItem.get();
+ }
+ else if (RES_FRAMEDIR == pEntry->nWID)
+ {
+ if (!m_pProps->m_pFrameDirItem.get())
+ {
+ m_pProps->m_pFrameDirItem.reset(
+ new SvxFrameDirectionItem(
+ FRMDIR_ENVIRONMENT, RES_FRAMEDIR));
+ }
+ pQueryItem = m_pProps->m_pFrameDirItem.get();
+ }
+ else if (RES_LR_SPACE == pEntry->nWID)
+ {
+ if (!m_pProps->m_pLRSpaceItem.get())
+ {
+ m_pProps->m_pLRSpaceItem.reset(
+ new SvxLRSpaceItem( RES_LR_SPACE ));
+ }
+ pQueryItem = m_pProps->m_pLRSpaceItem.get();
+ }
+ if (pQueryItem)
+ {
+ pQueryItem->QueryValue(pRet[nProperty],
+ pEntry->nMemberId);
+ }
+ }
+ }
+ }
+ }
+ return aRet;
+}
+
+uno::Sequence< uno::Any > SAL_CALL
+SwXTextSection::getPropertyValues(
+ const uno::Sequence< ::rtl::OUString >& rPropertyNames)
+throw (uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+ uno::Sequence< uno::Any > aValues;
+
+ // workaround for bad designed API
+ try
+ {
+ aValues = m_pImpl->GetPropertyValues_Impl( rPropertyNames );
+ }
+ catch (beans::UnknownPropertyException &)
+ {
+ throw uno::RuntimeException(OUString(
+ RTL_CONSTASCII_USTRINGPARAM("Unknown property exception caught")),
+ static_cast<cppu::OWeakObject *>(this));
+ }
+ catch (lang::WrappedTargetException &)
+ {
+ throw uno::RuntimeException(OUString(
+ RTL_CONSTASCII_USTRINGPARAM("WrappedTargetException caught")),
+ static_cast<cppu::OWeakObject *>(this));
+ }
+
+ return aValues;
+}
+
+uno::Any SAL_CALL
+SwXTextSection::getPropertyValue(const OUString& rPropertyName)
+throw (beans::UnknownPropertyException, lang::WrappedTargetException,
+ uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+
+ uno::Sequence< ::rtl::OUString > aPropertyNames(1);
+ aPropertyNames.getArray()[0] = rPropertyName;
+ return m_pImpl->GetPropertyValues_Impl(aPropertyNames).getConstArray()[0];
+}
+
+void SAL_CALL SwXTextSection::addPropertiesChangeListener(
+ const uno::Sequence< OUString >& /*aPropertyNames*/,
+ const uno::Reference< beans::XPropertiesChangeListener >& /*xListener*/ )
+throw (uno::RuntimeException)
+{
+ OSL_FAIL("SwXTextSection::addPropertiesChangeListener(): not implemented");
+}
+
+void SAL_CALL SwXTextSection::removePropertiesChangeListener(
+ const uno::Reference< beans::XPropertiesChangeListener >& /*xListener*/ )
+throw (uno::RuntimeException)
+{
+ OSL_FAIL("SwXTextSection::removePropertiesChangeListener(): not implemented");
+}
+
+void SAL_CALL SwXTextSection::firePropertiesChangeEvent(
+ const uno::Sequence< OUString >& /*aPropertyNames*/,
+ const uno::Reference< beans::XPropertiesChangeListener >& /*xListener*/ )
+ throw(uno::RuntimeException)
+{
+ OSL_FAIL("SwXTextSection::firePropertiesChangeEvent(): not implemented");
+}
+
+void SAL_CALL
+SwXTextSection::addPropertyChangeListener(
+ const ::rtl::OUString& /*rPropertyName*/,
+ const uno::Reference< beans::XPropertyChangeListener >& /*xListener*/)
+throw (beans::UnknownPropertyException, lang::WrappedTargetException,
+ uno::RuntimeException)
+{
+ OSL_FAIL("SwXTextSection::addPropertyChangeListener(): not implemented");
+}
+
+void SAL_CALL
+SwXTextSection::removePropertyChangeListener(
+ const ::rtl::OUString& /*rPropertyName*/,
+ const uno::Reference< beans::XPropertyChangeListener >& /*xListener*/)
+throw (beans::UnknownPropertyException, lang::WrappedTargetException,
+ uno::RuntimeException)
+{
+ OSL_FAIL("SwXTextSection::removePropertyChangeListener(): not implemented");
+}
+
+void SAL_CALL
+SwXTextSection::addVetoableChangeListener(
+ const ::rtl::OUString& /*rPropertyName*/,
+ const uno::Reference< beans::XVetoableChangeListener >& /*xListener*/)
+throw (beans::UnknownPropertyException, lang::WrappedTargetException,
+ uno::RuntimeException)
+{
+ OSL_FAIL("SwXTextSection::addVetoableChangeListener(): not implemented");
+}
+
+void SAL_CALL
+SwXTextSection::removeVetoableChangeListener(
+ const ::rtl::OUString& /*rPropertyName*/,
+ const uno::Reference< beans::XVetoableChangeListener >& /*xListener*/)
+throw (beans::UnknownPropertyException, lang::WrappedTargetException,
+ uno::RuntimeException)
+{
+ OSL_FAIL("SwXTextSection::removeVetoableChangeListener(): not implemented");
+}
+
+beans::PropertyState SAL_CALL
+SwXTextSection::getPropertyState(const OUString& rPropertyName)
+throw (beans::UnknownPropertyException, uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+
+ uno::Sequence< OUString > aNames(1);
+ aNames.getArray()[0] = rPropertyName;
+ return getPropertyStates(aNames).getConstArray()[0];
+}
+
+uno::Sequence< beans::PropertyState > SAL_CALL
+SwXTextSection::getPropertyStates(
+ const uno::Sequence< OUString >& rPropertyNames)
+throw (beans::UnknownPropertyException, uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+
+ SwSectionFmt *const pFmt = m_pImpl->GetSectionFmt();
+ if (!pFmt && !m_pImpl->m_bIsDescriptor)
+ {
+ throw uno::RuntimeException();
+ }
+
+ uno::Sequence< beans::PropertyState > aStates(rPropertyNames.getLength());
+ beans::PropertyState *const pStates = aStates.getArray();
+ const OUString* pNames = rPropertyNames.getConstArray();
+ for (sal_Int32 i = 0; i < rPropertyNames.getLength(); i++)
+ {
+ pStates[i] = beans::PropertyState_DEFAULT_VALUE;
+ SfxItemPropertySimpleEntry const*const pEntry =
+ m_pImpl->m_rPropSet.getPropertyMap()->getByName( pNames[i]);
+ if (!pEntry)
+ {
+ throw beans::UnknownPropertyException(
+ OUString(RTL_CONSTASCII_USTRINGPARAM("Unknown property: "))
+ + pNames[i], static_cast< cppu::OWeakObject* >(this));
+ }
+ switch (pEntry->nWID)
+ {
+ case WID_SECT_CONDITION:
+ case WID_SECT_DDE_TYPE:
+ case WID_SECT_DDE_FILE:
+ case WID_SECT_DDE_ELEMENT:
+ case WID_SECT_DDE_AUTOUPDATE:
+ case WID_SECT_LINK:
+ case WID_SECT_REGION :
+ case WID_SECT_VISIBLE:
+ case WID_SECT_PROTECTED:
+ case WID_SECT_EDIT_IN_READONLY:
+ case FN_PARAM_LINK_DISPLAY_NAME:
+ case FN_UNO_ANCHOR_TYPES:
+ case FN_UNO_TEXT_WRAP:
+ case FN_UNO_ANCHOR_TYPE:
+ pStates[i] = beans::PropertyState_DIRECT_VALUE;
+ break;
+ default:
+ {
+ if (pFmt)
+ {
+ pStates[i] = m_pImpl->m_rPropSet.getPropertyState(
+ pNames[i], pFmt->GetAttrSet());
+ }
+ else
+ {
+ if (RES_COL == pEntry->nWID)
+ {
+ if (!m_pImpl->m_pProps->m_pColItem.get())
+ {
+ pStates[i] = beans::PropertyState_DEFAULT_VALUE;
+ }
+ else
+ {
+ pStates[i] = beans::PropertyState_DIRECT_VALUE;
+ }
+ }
+ else //if(RES_BACKGROUND == pEntry->nWID)
+ {
+ if (!m_pImpl->m_pProps->m_pBrushItem.get())
+ {
+ pStates[i] = beans::PropertyState_DEFAULT_VALUE;
+ }
+ else
+ {
+ pStates[i] = beans::PropertyState_DIRECT_VALUE;
+ }
+ }
+ }
+ }
+ }
+ }
+ return aStates;
+}
+
+void SAL_CALL
+SwXTextSection::setPropertyToDefault(const OUString& rPropertyName)
+throw (beans::UnknownPropertyException, uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+
+ SwSectionFmt *const pFmt = m_pImpl->GetSectionFmt();
+ if (!pFmt && !m_pImpl->m_bIsDescriptor)
+ {
+ throw uno::RuntimeException();
+ }
+
+ SfxItemPropertySimpleEntry const*const pEntry =
+ m_pImpl->m_rPropSet.getPropertyMap()->getByName(rPropertyName);
+ if (!pEntry)
+ {
+ throw beans::UnknownPropertyException(
+ OUString(RTL_CONSTASCII_USTRINGPARAM("Unknown property: "))
+ + rPropertyName, static_cast< cppu::OWeakObject* >(this));
+ }
+ if (pEntry->nFlags & beans::PropertyAttribute::READONLY)
+ {
+ throw uno::RuntimeException(OUString(RTL_CONSTASCII_USTRINGPARAM(
+ "setPropertyToDefault: property is read-only: "))
+ + rPropertyName,
+ static_cast<cppu::OWeakObject *>(this));
+ }
+
+ ::std::auto_ptr<SwSectionData> const pSectionData(
+ (pFmt) ? new SwSectionData(*pFmt->GetSection()) : 0);
+
+ ::std::auto_ptr<SfxItemSet> pNewAttrSet;
+ bool bLinkModeChanged = false;
+
+ switch (pEntry->nWID)
+ {
+ case WID_SECT_CONDITION:
+ {
+ if (m_pImpl->m_bIsDescriptor)
+ {
+ m_pImpl->m_pProps->m_sCondition = aEmptyStr;
+ }
+ else
+ {
+ pSectionData->SetCondition(aEmptyStr);
+ }
+ }
+ break;
+ case WID_SECT_DDE_TYPE :
+ case WID_SECT_DDE_FILE :
+ case WID_SECT_DDE_ELEMENT :
+ case WID_SECT_LINK :
+ case WID_SECT_REGION :
+ if (m_pImpl->m_bIsDescriptor)
+ {
+ m_pImpl->m_pProps->m_bDDE = false;
+ m_pImpl->m_pProps->m_sLinkFileName = ::rtl::OUString();
+ m_pImpl->m_pProps->m_sSectionRegion = ::rtl::OUString();
+ m_pImpl->m_pProps->m_sSectionFilter = ::rtl::OUString();
+ }
+ else
+ {
+ pSectionData->SetType(CONTENT_SECTION);
+ }
+ break;
+ case WID_SECT_DDE_AUTOUPDATE:
+ if (m_pImpl->m_bIsDescriptor)
+ {
+ m_pImpl->m_pProps->m_bUpdateType = true;
+ }
+ else
+ {
+ bLinkModeChanged = true;
+ }
+ break;
+ case WID_SECT_VISIBLE :
+ {
+ if (m_pImpl->m_bIsDescriptor)
+ {
+ m_pImpl->m_pProps->m_bHidden = false;
+ }
+ else
+ {
+ pSectionData->SetHidden(false);
+ }
+ }
+ break;
+ case WID_SECT_PROTECTED:
+ {
+ if (m_pImpl->m_bIsDescriptor)
+ {
+ m_pImpl->m_pProps->m_bProtect = false;
+ }
+ else
+ {
+ pSectionData->SetProtectFlag(false);
+ }
+ }
+ break;
+ case WID_SECT_EDIT_IN_READONLY:
+ {
+ if (m_pImpl->m_bIsDescriptor)
+ {
+ m_pImpl->m_pProps->m_bEditInReadonly = false;
+ }
+ else
+ {
+ pSectionData->SetEditInReadonlyFlag(false);
+ }
+ }
+ break;
+ // <--
+
+ case FN_UNO_ANCHOR_TYPES:
+ case FN_UNO_TEXT_WRAP:
+ case FN_UNO_ANCHOR_TYPE:
+ break;
+ default:
+ {
+ if (pEntry->nWID <= SFX_WHICH_MAX)
+ {
+ if (pFmt)
+ {
+ const SfxItemSet& rOldAttrSet = pFmt->GetAttrSet();
+ pNewAttrSet.reset( new SfxItemSet(*rOldAttrSet.GetPool(),
+ pEntry->nWID, pEntry->nWID, 0));
+ pNewAttrSet->ClearItem(pEntry->nWID);
+ }
+ else
+ {
+ if (RES_COL == pEntry->nWID)
+ {
+ m_pImpl->m_pProps->m_pColItem.reset();
+ }
+ else if (RES_BACKGROUND == pEntry->nWID)
+ {
+ m_pImpl->m_pProps->m_pBrushItem.reset();
+ }
+ }
+ }
+ }
+ }
+
+ lcl_UpdateSection(pFmt, pSectionData, pNewAttrSet, bLinkModeChanged);
+}
+
+uno::Any SAL_CALL
+SwXTextSection::getPropertyDefault(const OUString& rPropertyName)
+throw (beans::UnknownPropertyException, lang::WrappedTargetException,
+ uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+
+ uno::Any aRet;
+ SwSectionFmt *const pFmt = m_pImpl->GetSectionFmt();
+ SfxItemPropertySimpleEntry const*const pEntry =
+ m_pImpl->m_rPropSet.getPropertyMap()->getByName(rPropertyName);
+ if (!pEntry)
+ {
+ throw beans::UnknownPropertyException(
+ OUString(RTL_CONSTASCII_USTRINGPARAM("Unknown property: "))
+ + rPropertyName,
+ static_cast<cppu::OWeakObject *>(this));
+ }
+
+ switch(pEntry->nWID)
+ {
+ case WID_SECT_CONDITION:
+ case WID_SECT_DDE_TYPE :
+ case WID_SECT_DDE_FILE :
+ case WID_SECT_DDE_ELEMENT :
+ case WID_SECT_REGION :
+ case FN_PARAM_LINK_DISPLAY_NAME:
+ aRet <<= OUString();
+ break;
+ case WID_SECT_LINK :
+ aRet <<= text::SectionFileLink();
+ break;
+ case WID_SECT_DDE_AUTOUPDATE:
+ case WID_SECT_VISIBLE :
+ {
+ sal_Bool bTemp = sal_True;
+ aRet.setValue( &bTemp, ::getCppuBooleanType());
+ }
+ break;
+ case WID_SECT_PROTECTED:
+ case WID_SECT_EDIT_IN_READONLY:
+ {
+ sal_Bool bTemp = sal_False;
+ aRet.setValue( &bTemp, ::getCppuBooleanType());
+ }
+ break;
+ case FN_UNO_ANCHOR_TYPES:
+ case FN_UNO_TEXT_WRAP:
+ case FN_UNO_ANCHOR_TYPE:
+ ::sw::GetDefaultTextContentValue(aRet, OUString(), pEntry->nWID);
+ break;
+ default:
+ if(pFmt && pEntry->nWID <= SFX_WHICH_MAX)
+ {
+ SwDoc *const pDoc = pFmt->GetDoc();
+ const SfxPoolItem& rDefItem =
+ pDoc->GetAttrPool().GetDefaultItem(pEntry->nWID);
+ rDefItem.QueryValue(aRet, pEntry->nMemberId);
+ }
+ }
+ return aRet;
+}
+
+OUString SAL_CALL SwXTextSection::getName() throw (uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+
+ ::rtl::OUString sRet;
+ SwSectionFmt const*const pFmt = m_pImpl->GetSectionFmt();
+ if(pFmt)
+ {
+ sRet = pFmt->GetSection()->GetSectionName();
+ }
+ else if (m_pImpl->m_bIsDescriptor)
+ {
+ sRet = m_pImpl->m_sName;
+ }
+ else
+ {
+ throw uno::RuntimeException();
+ }
+ return sRet;
+}
+
+void SAL_CALL SwXTextSection::setName(const OUString& rName)
+throw (uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+
+ SwSectionFmt *const pFmt = m_pImpl->GetSectionFmt();
+ if(pFmt)
+ {
+ SwSection *const pSect = pFmt->GetSection();
+ SwSectionData aSection(*pSect);
+ String sNewName(rName);
+ aSection.SetSectionName(sNewName);
+
+ const SwSectionFmts& rFmts = pFmt->GetDoc()->GetSections();
+ sal_uInt16 nApplyPos = USHRT_MAX;
+ for( sal_uInt16 i = 0; i < rFmts.Count(); i++ )
+ {
+ if(rFmts[i]->GetSection() == pSect)
+ {
+ nApplyPos = i;
+ }
+ else if (sNewName == rFmts[i]->GetSection()->GetSectionName())
+ {
+ throw uno::RuntimeException();
+ }
+ }
+ if(nApplyPos != USHRT_MAX)
+ {
+ {
+ UnoActionContext aContext(pFmt->GetDoc());
+ pFmt->GetDoc()->UpdateSection(nApplyPos, aSection);
+ }
+ {
+ // temporarily remove actions to allow cursor update
+ UnoActionRemoveContext aRemoveContext( pFmt->GetDoc() );
+ }
+ }
+ }
+ else if (m_pImpl->m_bIsDescriptor)
+ {
+ m_pImpl->m_sName = rName;
+ }
+ else
+ {
+ throw uno::RuntimeException();
+ }
+}
+
+OUString SAL_CALL
+SwXTextSection::getImplementationName() throw (uno::RuntimeException)
+{
+ return C2U("SwXTextSection");
+}
+
+static char const*const g_ServicesTextSection[] =
+{
+ "com.sun.star.text.TextContent",
+ "com.sun.star.text.TextSection",
+ "com.sun.star.document.LinkTarget",
+};
+
+static const size_t g_nServicesTextSection(SAL_N_ELEMENTS(g_ServicesTextSection));
+
+sal_Bool SAL_CALL SwXTextSection::supportsService(const OUString& rServiceName)
+throw (uno::RuntimeException)
+{
+ return ::sw::SupportsServiceImpl(
+ g_nServicesTextSection, g_ServicesTextSection, rServiceName);
+}
+
+uno::Sequence< OUString > SAL_CALL
+SwXTextSection::getSupportedServiceNames() throw (uno::RuntimeException)
+{
+ return ::sw::GetSupportedServiceNamesImpl(
+ g_nServicesTextSection, g_ServicesTextSection);
+}
+
+// MetadatableMixin
+::sfx2::Metadatable* SwXTextSection::GetCoreObject()
+{
+ SwSectionFmt *const pSectionFmt( m_pImpl->GetSectionFmt() );
+ return pSectionFmt;
+}
+
+uno::Reference<frame::XModel> SwXTextSection::GetModel()
+{
+ SwSectionFmt *const pSectionFmt( m_pImpl->GetSectionFmt() );
+ if (pSectionFmt)
+ {
+ SwDocShell const*const pShell( pSectionFmt->GetDoc()->GetDocShell() );
+ return (pShell) ? pShell->GetModel() : 0;
+ }
+ return 0;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/unocore/unosett.cxx b/sw/source/core/unocore/unosett.cxx
new file mode 100644
index 000000000000..21b663281869
--- /dev/null
+++ b/sw/source/core/unocore/unosett.cxx
@@ -0,0 +1,2639 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+#include <svx/svxids.hrc>
+#include <editeng/memberids.hrc>
+#include <swtypes.hxx>
+#include <cmdid.h>
+#include <hintids.hxx>
+#include "poolfmt.hrc"
+#include "poolfmt.hxx"
+#include <fmtcol.hxx>
+#include <unomap.hxx>
+#include <unostyle.hxx>
+#include <unosett.hxx>
+#include <unoprnms.hxx>
+#include <ftninfo.hxx>
+#include <doc.hxx>
+#include <pagedesc.hxx>
+#include <charfmt.hxx>
+#include <lineinfo.hxx>
+#include <docsh.hxx>
+#include <docary.hxx>
+#include <docstyle.hxx>
+#include <fmtclds.hxx>
+#include <editeng/brshitem.hxx>
+#include <com/sun/star/text/XFootnotesSettingsSupplier.hpp>
+#include <com/sun/star/text/XFootnote.hpp>
+#include <com/sun/star/text/XFootnotesSupplier.hpp>
+#include <com/sun/star/text/XEndnotesSupplier.hpp>
+#include <com/sun/star/text/XEndnotesSettingsSupplier.hpp>
+#include <com/sun/star/text/FootnoteNumbering.hpp>
+#include <com/sun/star/text/HoriOrientation.hpp>
+#include <com/sun/star/style/LineNumberPosition.hpp>
+#include <com/sun/star/awt/XBitmap.hpp>
+#include <com/sun/star/beans/PropertyAttribute.hpp>
+#include <com/sun/star/style/VerticalAlignment.hpp>
+#include <vcl/font.hxx>
+#include <editeng/flstitem.hxx>
+#include <vcl/metric.hxx>
+#include <svtools/ctrltool.hxx>
+#include <osl/mutex.hxx>
+#include <vcl/svapp.hxx>
+#include <toolkit/helper/vclunohelper.hxx>
+#include <editeng/unofdesc.hxx>
+#include <fmtornt.hxx>
+#include <SwStyleNameMapper.hxx>
+#include <com/sun/star/text/PositionAndSpaceMode.hpp>
+#include <com/sun/star/text/LabelFollow.hpp>
+#include <numrule.hxx>
+
+using ::rtl::OUString;
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star::beans;
+using namespace ::com::sun::star::text;
+using namespace ::com::sun::star::style;
+
+using rtl::OUString;
+
+struct PropValData
+{
+ uno::Any aVal;
+ OUString sPropName;
+ PropValData(void* pVal, const char* cPropName, uno::Type aType ) :
+ aVal(pVal, aType),
+ sPropName(OUString::createFromAscii(cPropName))
+ {}
+ PropValData(const uno::Any& rVal, const OUString& rPropName) :
+ aVal(rVal),
+ sPropName(rPropName)
+ {}
+};
+
+// Constants for the css::text::ColumnSeparatorStyle
+#define API_COL_LINE_NONE 0
+#define API_COL_LINE_SOLID 1
+#define API_COL_LINE_DOTTED 2
+#define API_COL_LINE_DASHED 3
+
+typedef PropValData* PropValDataPtr;
+SV_DECL_PTRARR(PropValDataArr, PropValDataPtr, 5, 5 )
+SV_IMPL_PTRARR(PropValDataArr, PropValDataPtr)
+
+
+#define WID_PREFIX 0
+#define WID_SUFFIX 1
+#define WID_NUMBERING_TYPE 2
+#define WID_START_AT 3
+#define WID_FOOTNOTE_COUNTING 4
+#define WID_PARAGRAPH_STYLE 5
+#define WID_PAGE_STYLE 6
+#define WID_CHARACTER_STYLE 7
+#define WID_POSITION_END_OF_DOC 8
+#define WID_END_NOTICE 9
+#define WID_BEGIN_NOTICE 10
+#define WID_ANCHOR_CHARACTER_STYLE 11
+
+const SfxItemPropertySet* GetFootnoteSet()
+{
+ static SfxItemPropertyMapEntry aFootnoteMap_Impl[] =
+ {
+ { SW_PROP_NAME(UNO_NAME_ANCHOR_CHAR_STYLE_NAME),WID_ANCHOR_CHARACTER_STYLE, &::getCppuType((const OUString*)0), PROPERTY_NONE, 0},
+ { SW_PROP_NAME(UNO_NAME_BEGIN_NOTICE), WID_BEGIN_NOTICE, &::getCppuType((const OUString*)0), PROPERTY_NONE, 0},
+ { SW_PROP_NAME(UNO_NAME_CHAR_STYLE_NAME), WID_CHARACTER_STYLE, &::getCppuType((const OUString*)0), PROPERTY_NONE, 0},
+ { SW_PROP_NAME(UNO_NAME_END_NOTICE), WID_END_NOTICE , &::getCppuType((const OUString*)0), PROPERTY_NONE, 0},
+ { SW_PROP_NAME(UNO_NAME_FOOTNOTE_COUNTING), WID_FOOTNOTE_COUNTING, &::getCppuType((const sal_Int16*)0), PROPERTY_NONE, 0},
+ { SW_PROP_NAME(UNO_NAME_NUMBERING_TYPE), WID_NUMBERING_TYPE, &::getCppuType((const sal_Int16*)0), PROPERTY_NONE, 0},
+ { SW_PROP_NAME(UNO_NAME_PAGE_STYLE_NAME), WID_PAGE_STYLE, &::getCppuType((const OUString*)0), PROPERTY_NONE, 0},
+ { SW_PROP_NAME(UNO_NAME_PARA_STYLE_NAME), WID_PARAGRAPH_STYLE, &::getCppuType((const OUString*)0), PROPERTY_NONE, 0},
+ { SW_PROP_NAME(UNO_NAME_POSITION_END_OF_DOC), WID_POSITION_END_OF_DOC,&::getBooleanCppuType(), PROPERTY_NONE, 0},
+ { SW_PROP_NAME(UNO_NAME_PREFIX), WID_PREFIX, &::getCppuType((const OUString*)0), PROPERTY_NONE, 0},
+ { SW_PROP_NAME(UNO_NAME_START_AT), WID_START_AT , &::getCppuType((const sal_Int16*)0), PROPERTY_NONE, 0},
+ { SW_PROP_NAME(UNO_NAME_SUFFIX), WID_SUFFIX, &::getCppuType((const OUString*)0), PROPERTY_NONE, 0},
+ {0,0,0,0,0,0}
+ };
+ static SfxItemPropertySet aFootnoteSet_Impl(aFootnoteMap_Impl);
+ return &aFootnoteSet_Impl;
+}
+
+const SfxItemPropertySet* GetEndnoteSet()
+{
+ static SfxItemPropertyMapEntry aEndnoteMap_Impl[] =
+ {
+ { SW_PROP_NAME(UNO_NAME_ANCHOR_CHAR_STYLE_NAME),WID_ANCHOR_CHARACTER_STYLE, &::getCppuType((const OUString*)0), PROPERTY_NONE, 0},
+ { SW_PROP_NAME(UNO_NAME_CHAR_STYLE_NAME), WID_CHARACTER_STYLE, &::getCppuType((const OUString*)0), PROPERTY_NONE, 0},
+ { SW_PROP_NAME(UNO_NAME_NUMBERING_TYPE), WID_NUMBERING_TYPE, &::getCppuType((const sal_Int16*)0), PROPERTY_NONE, 0},
+ { SW_PROP_NAME(UNO_NAME_PAGE_STYLE_NAME), WID_PAGE_STYLE, &::getCppuType((const OUString*)0), PROPERTY_NONE, 0},
+ { SW_PROP_NAME(UNO_NAME_PARA_STYLE_NAME), WID_PARAGRAPH_STYLE, &::getCppuType((const OUString*)0), PROPERTY_NONE, 0},
+ { SW_PROP_NAME(UNO_NAME_PREFIX), WID_PREFIX, &::getCppuType((const OUString*)0), PROPERTY_NONE, 0},
+ { SW_PROP_NAME(UNO_NAME_START_AT), WID_START_AT , &::getCppuType((const sal_Int16*)0), PROPERTY_NONE, 0},
+ { SW_PROP_NAME(UNO_NAME_SUFFIX), WID_SUFFIX, &::getCppuType((const OUString*)0), PROPERTY_NONE, 0},
+ {0,0,0,0,0,0}
+ };
+ static SfxItemPropertySet aEndnoteSet_Impl(aEndnoteMap_Impl);
+ return &aEndnoteSet_Impl;
+}
+
+const SfxItemPropertySet* GetNumberingRulesSet()
+{
+ static SfxItemPropertyMapEntry aNumberingRulesMap_Impl[] =
+ {
+ { SW_PROP_NAME(UNO_NAME_IS_ABSOLUTE_MARGINS), WID_IS_ABS_MARGINS, &::getBooleanCppuType(), PROPERTY_NONE, 0},
+ { SW_PROP_NAME(UNO_NAME_IS_AUTOMATIC), WID_IS_AUTOMATIC, &::getBooleanCppuType(), PROPERTY_NONE, 0},
+ { SW_PROP_NAME(UNO_NAME_IS_CONTINUOUS_NUMBERING), WID_CONTINUOUS, &::getBooleanCppuType(), PROPERTY_NONE, 0},
+ { SW_PROP_NAME(UNO_NAME_NAME), WID_RULE_NAME , &::getCppuType((const OUString*)0), PropertyAttribute::READONLY, 0},
+ { SW_PROP_NAME(UNO_NAME_NUMBERING_IS_OUTLINE), WID_IS_OUTLINE, &::getBooleanCppuType(), PROPERTY_NONE, 0},
+ { SW_PROP_NAME(UNO_NAME_DEFAULT_LIST_ID), WID_DEFAULT_LIST_ID, &::getCppuType((const OUString*)0), PropertyAttribute::READONLY, 0},
+ {0,0,0,0,0,0}
+ };
+ static SfxItemPropertySet aNumberingRulesSet_Impl( aNumberingRulesMap_Impl );
+ return &aNumberingRulesSet_Impl;
+}
+
+#define WID_NUM_ON 0
+#define WID_SEPARATOR_INTERVAL 1
+#define WID_NUMBERING_TYPE 2
+#define WID_NUMBER_POSITION 3
+#define WID_DISTANCE 4
+#define WID_INTERVAL 5
+#define WID_SEPARATOR_TEXT 6
+#define WID_COUNT_EMPTY_LINES 8
+#define WID_COUNT_LINES_IN_FRAMES 9
+#define WID_RESTART_AT_EACH_PAGE 10
+
+const SfxItemPropertySet* GetLineNumberingSet()
+{
+ static SfxItemPropertyMapEntry aLineNumberingMap_Impl[] =
+ {
+ { SW_PROP_NAME(UNO_NAME_CHAR_STYLE_NAME), WID_CHARACTER_STYLE, &::getCppuType((const OUString*)0), PROPERTY_NONE, 0},
+ { SW_PROP_NAME(UNO_NAME_COUNT_EMPTY_LINES), WID_COUNT_EMPTY_LINES , &::getBooleanCppuType(),PROPERTY_NONE, 0},
+ { SW_PROP_NAME(UNO_NAME_COUNT_LINES_IN_FRAMES), WID_COUNT_LINES_IN_FRAMES, &::getBooleanCppuType(),PROPERTY_NONE, 0},
+ { SW_PROP_NAME(UNO_NAME_DISTANCE ), WID_DISTANCE , &::getCppuType((const sal_Int32*)0),PROPERTY_NONE, 0},
+ { SW_PROP_NAME(UNO_NAME_IS_ON), WID_NUM_ON, &::getBooleanCppuType() , PROPERTY_NONE, 0},
+ { SW_PROP_NAME(UNO_NAME_INTERVAL ), WID_INTERVAL , &::getCppuType((const sal_Int16*)0),PROPERTY_NONE, 0},
+ { SW_PROP_NAME(UNO_NAME_SEPARATOR_TEXT ), WID_SEPARATOR_TEXT, &::getCppuType((const OUString*)0), PROPERTY_NONE, 0},
+ { SW_PROP_NAME(UNO_NAME_NUMBER_POSITION), WID_NUMBER_POSITION, &::getCppuType((const sal_Int16*)0),PROPERTY_NONE, 0},
+ { SW_PROP_NAME(UNO_NAME_NUMBERING_TYPE), WID_NUMBERING_TYPE , &::getCppuType((const sal_Int16*)0),PROPERTY_NONE, 0},
+ { SW_PROP_NAME(UNO_NAME_RESTART_AT_EACH_PAGE), WID_RESTART_AT_EACH_PAGE, &::getBooleanCppuType() , PROPERTY_NONE, 0},
+ { SW_PROP_NAME(UNO_NAME_SEPARATOR_INTERVAL), WID_SEPARATOR_INTERVAL, &::getCppuType((const sal_Int16*)0),PROPERTY_NONE, 0},
+ {0,0,0,0,0,0}
+ };
+ static SfxItemPropertySet aLineNumberingSet_Impl(aLineNumberingMap_Impl);
+ return &aLineNumberingSet_Impl;
+}
+
+SwCharFmt* lcl_getCharFmt(SwDoc* pDoc, const uno::Any& aValue)
+{
+ SwCharFmt* pRet = 0;
+ String sStandard(SW_RES(STR_POOLCOLL_STANDARD));
+ OUString uTmp;
+ aValue >>= uTmp;
+ String sCharFmt;
+ SwStyleNameMapper::FillUIName(uTmp, sCharFmt, nsSwGetPoolIdFromName::GET_POOLID_CHRFMT, sal_True);
+ if(sStandard != sCharFmt)
+ {
+ pRet = pDoc->FindCharFmtByName( sCharFmt );
+ }
+ if(!pRet)
+ {
+ sal_uInt16 nId = SwStyleNameMapper::GetPoolIdFromUIName(sCharFmt, nsSwGetPoolIdFromName::GET_POOLID_CHRFMT);
+ if(USHRT_MAX != nId)
+ pRet = pDoc->GetCharFmtFromPool( nId );
+ }
+ return pRet;
+}
+
+SwTxtFmtColl* lcl_GetParaStyle(SwDoc* pDoc, const uno::Any& aValue)
+{
+ OUString uTmp;
+ aValue >>= uTmp;
+ String sParaStyle;
+ SwStyleNameMapper::FillUIName(uTmp, sParaStyle, nsSwGetPoolIdFromName::GET_POOLID_TXTCOLL, sal_True );
+ SwTxtFmtColl* pRet = pDoc->FindTxtFmtCollByName( sParaStyle );
+ if( !pRet )
+ {
+ sal_uInt16 nId = SwStyleNameMapper::GetPoolIdFromUIName( sParaStyle, nsSwGetPoolIdFromName::GET_POOLID_TXTCOLL );
+ if( USHRT_MAX != nId )
+ pRet = pDoc->GetTxtCollFromPool( nId );
+ }
+ return pRet;
+}
+
+SwPageDesc* lcl_GetPageDesc(SwDoc* pDoc, const uno::Any& aValue)
+{
+ SwPageDesc* pRet = 0;
+ sal_uInt16 nCount = pDoc->GetPageDescCnt();
+ OUString uTmp;
+ aValue >>= uTmp;
+ String sPageDesc;
+ SwStyleNameMapper::FillUIName(uTmp, sPageDesc, nsSwGetPoolIdFromName::GET_POOLID_PAGEDESC, sal_True );
+ for( sal_uInt16 i = 0; i < nCount; i++)
+ {
+ const SwPageDesc& rDesc = const_cast<const SwDoc *>(pDoc)
+ ->GetPageDesc( i );
+ if(rDesc.GetName() == sPageDesc)
+ {
+ pRet = (SwPageDesc*)&rDesc;
+ break;
+ }
+ }
+ if(!pRet)
+ {
+ sal_uInt16 nId = SwStyleNameMapper::GetPoolIdFromUIName(sPageDesc, nsSwGetPoolIdFromName::GET_POOLID_PAGEDESC);
+ if(USHRT_MAX != nId)
+ pRet = pDoc->GetPageDescFromPool( nId );
+ }
+ return pRet;
+}
+
+// Numerierung
+const unsigned short aSvxToUnoAdjust[] =
+{
+ text::HoriOrientation::LEFT, //3
+ text::HoriOrientation::RIGHT, //1
+ USHRT_MAX,
+ text::HoriOrientation::CENTER, //2
+ USHRT_MAX,
+ USHRT_MAX
+};
+
+const unsigned short aUnoToSvxAdjust[] =
+{
+ USHRT_MAX,
+ SVX_ADJUST_RIGHT, // 1
+ SVX_ADJUST_CENTER, // 3
+ SVX_ADJUST_LEFT, // 0
+ USHRT_MAX,
+ USHRT_MAX
+};
+
+/******************************************************************
+ * SwXFootnoteProperties
+ ******************************************************************/
+OUString SwXFootnoteProperties::getImplementationName(void) throw( RuntimeException )
+{
+ return C2U("SwXFootnoteProperties");
+}
+
+sal_Bool SwXFootnoteProperties::supportsService(const OUString& rServiceName) throw( RuntimeException )
+{
+ return C2U("com.sun.star.text.FootnoteSettings") == rServiceName;
+}
+
+Sequence< OUString > SwXFootnoteProperties::getSupportedServiceNames(void) throw( RuntimeException )
+{
+ Sequence< OUString > aRet(1);
+ OUString* pArray = aRet.getArray();
+ pArray[0] = C2U("com.sun.star.text.FootnoteSettings");
+ return aRet;
+}
+
+SwXFootnoteProperties::SwXFootnoteProperties(SwDoc* pDc) :
+ pDoc(pDc),
+ m_pPropertySet(GetFootnoteSet())
+{
+}
+
+SwXFootnoteProperties::~SwXFootnoteProperties()
+{
+
+}
+
+uno::Reference< beans::XPropertySetInfo > SwXFootnoteProperties::getPropertySetInfo(void)
+ throw( uno::RuntimeException )
+{
+ static uno::Reference< beans::XPropertySetInfo > aRef = m_pPropertySet->getPropertySetInfo();
+ return aRef;
+}
+
+void SwXFootnoteProperties::setPropertyValue(const OUString& rPropertyName, const uno::Any& aValue)
+ throw( beans::UnknownPropertyException, beans::PropertyVetoException, lang::IllegalArgumentException, lang::WrappedTargetException, uno::RuntimeException )
+{
+ SolarMutexGuard aGuard;
+ if(pDoc)
+ {
+ const SfxItemPropertySimpleEntry* pEntry = m_pPropertySet->getPropertyMap()->getByName( rPropertyName );
+ if(pEntry)
+ {
+ if ( pEntry->nFlags & PropertyAttribute::READONLY)
+ throw PropertyVetoException( OUString ( RTL_CONSTASCII_USTRINGPARAM ( "Property is read-only: " ) ) + rPropertyName, static_cast < cppu::OWeakObject * > ( this ) );
+ SwFtnInfo aFtnInfo(pDoc->GetFtnInfo());
+ switch(pEntry->nWID)
+ {
+ case WID_PREFIX:
+ {
+ OUString uTmp;
+ aValue >>= uTmp;
+ aFtnInfo.SetPrefix(uTmp);
+ }
+ break;
+ case WID_SUFFIX:
+ {
+ OUString uTmp;
+ aValue >>= uTmp;
+ aFtnInfo.SetSuffix(uTmp);
+ }
+ break;
+ case WID_NUMBERING_TYPE :
+ {
+ sal_Int16 nTmp = 0;
+ aValue >>= nTmp;
+ if(nTmp >= 0 &&
+ (nTmp <= SVX_NUM_ARABIC ||
+ nTmp > SVX_NUM_BITMAP))
+ aFtnInfo.aFmt.SetNumberingType(nTmp);
+ else
+ throw lang::IllegalArgumentException();
+ }
+ break;
+ case WID_START_AT:
+ {
+ sal_Int16 nTmp = 0;
+ aValue >>= nTmp;
+ aFtnInfo.nFtnOffset = nTmp;
+ }
+ break;
+ case WID_FOOTNOTE_COUNTING :
+ {
+ sal_Int16 nTmp = 0;
+ aValue >>= nTmp;
+ switch(nTmp)
+ {
+ case FootnoteNumbering::PER_PAGE:
+ aFtnInfo.eNum = FTNNUM_PAGE;
+ break;
+ case FootnoteNumbering::PER_CHAPTER:
+ aFtnInfo.eNum = FTNNUM_CHAPTER;
+ break;
+ case FootnoteNumbering::PER_DOCUMENT:
+ aFtnInfo.eNum = FTNNUM_DOC;
+ break;
+ }
+ }
+ break;
+ case WID_PARAGRAPH_STYLE :
+ {
+ SwTxtFmtColl* pColl = lcl_GetParaStyle(pDoc, aValue);
+ if(pColl)
+ aFtnInfo.SetFtnTxtColl(*pColl);
+ }
+ break;
+ case WID_PAGE_STYLE :
+ {
+ SwPageDesc* pDesc = lcl_GetPageDesc(pDoc, aValue);
+ if(pDesc)
+ aFtnInfo.ChgPageDesc( pDesc );
+ }
+ break;
+ case WID_ANCHOR_CHARACTER_STYLE:
+ case WID_CHARACTER_STYLE :
+ {
+ SwCharFmt* pFmt = lcl_getCharFmt(pDoc, aValue);
+ if(pFmt)
+ {
+ if(pEntry->nWID == WID_ANCHOR_CHARACTER_STYLE)
+ aFtnInfo.SetAnchorCharFmt(pFmt);
+ else
+ aFtnInfo.SetCharFmt(pFmt);
+ }
+ }
+ break;
+ case WID_POSITION_END_OF_DOC:
+ {
+ sal_Bool bVal = *(sal_Bool*)aValue.getValue();
+ aFtnInfo.ePos = bVal ? FTNPOS_CHAPTER : FTNPOS_PAGE;
+ }
+ break;
+ case WID_END_NOTICE :
+ {
+ OUString uTmp;
+ aValue >>= uTmp;
+ aFtnInfo.aQuoVadis = String(uTmp);
+ }
+ break;
+ case WID_BEGIN_NOTICE :
+ {
+ OUString uTmp;
+ aValue >>= uTmp;
+ aFtnInfo.aErgoSum = String(uTmp);
+ }
+ break;
+ }
+ pDoc->SetFtnInfo(aFtnInfo);
+ }
+ else
+ throw beans::UnknownPropertyException(OUString ( RTL_CONSTASCII_USTRINGPARAM ( "Unknown property: " ) ) + rPropertyName, static_cast < cppu::OWeakObject * > ( this ) );
+ }
+ else
+ throw uno::RuntimeException();
+}
+
+uno::Any SwXFootnoteProperties::getPropertyValue(const OUString& rPropertyName)
+ throw( beans::UnknownPropertyException, lang::WrappedTargetException, uno::RuntimeException )
+{
+ SolarMutexGuard aGuard;
+ uno::Any aRet;
+ if(pDoc)
+ {
+ const SfxItemPropertySimpleEntry* pEntry = m_pPropertySet->getPropertyMap()->getByName( rPropertyName );
+ if(pEntry)
+ {
+ const SwFtnInfo& rFtnInfo = pDoc->GetFtnInfo();
+ switch(pEntry->nWID)
+ {
+ case WID_PREFIX:
+ {
+ aRet <<= OUString(rFtnInfo.GetPrefix());
+ }
+ break;
+ case WID_SUFFIX:
+ {
+ aRet <<= OUString(rFtnInfo.GetSuffix());
+ }
+ break;
+ case WID_NUMBERING_TYPE :
+ {
+ aRet <<= rFtnInfo.aFmt.GetNumberingType();
+ }
+ break;
+ case WID_START_AT:
+ aRet <<= (sal_Int16)rFtnInfo.nFtnOffset;
+ break;
+ case WID_FOOTNOTE_COUNTING :
+ {
+ sal_Int16 nRet = 0;
+ switch(rFtnInfo.eNum)
+ {
+ case FTNNUM_PAGE:
+ nRet = FootnoteNumbering::PER_PAGE;
+ break;
+ case FTNNUM_CHAPTER:
+ nRet = FootnoteNumbering::PER_CHAPTER;
+ break;
+ case FTNNUM_DOC:
+ nRet = FootnoteNumbering::PER_DOCUMENT;
+ break;
+ }
+ aRet <<= nRet;
+ }
+ break;
+ case WID_PARAGRAPH_STYLE :
+ {
+ SwTxtFmtColl* pColl = rFtnInfo.GetFtnTxtColl();
+ String aString;
+ if(pColl)
+ aString = String ( pColl->GetName() );
+ SwStyleNameMapper::FillProgName(aString, aString, nsSwGetPoolIdFromName::GET_POOLID_TXTCOLL, sal_True);
+ aRet <<= OUString ( aString );
+ }
+ break;
+ case WID_PAGE_STYLE :
+ {
+ String aString;
+ if( rFtnInfo.KnowsPageDesc() )
+ {
+ SwStyleNameMapper::FillProgName(
+ rFtnInfo.GetPageDesc( *pDoc )->GetName(),
+ aString,
+ nsSwGetPoolIdFromName::GET_POOLID_PAGEDESC,
+ sal_True);
+ }
+ aRet <<= OUString ( aString );
+ }
+ break;
+ case WID_ANCHOR_CHARACTER_STYLE:
+ case WID_CHARACTER_STYLE:
+ {
+ String aString;
+ const SwCharFmt* pCharFmt = 0;
+ if( pEntry->nWID == WID_ANCHOR_CHARACTER_STYLE )
+ {
+ if( rFtnInfo.GetAnchorCharFmtDep()->GetRegisteredIn() )
+ pCharFmt = rFtnInfo.GetAnchorCharFmt(*pDoc);
+ }
+ else
+ {
+ if( rFtnInfo.GetCharFmtDep()->GetRegisteredIn() )
+ pCharFmt = rFtnInfo.GetCharFmt(*pDoc);
+ }
+ if( pCharFmt )
+ {
+ SwStyleNameMapper::FillProgName(
+ pCharFmt->GetName(),
+ aString,
+ nsSwGetPoolIdFromName::GET_POOLID_CHRFMT,
+ sal_True);
+ }
+ aRet <<= OUString ( aString );
+ }
+ break;
+ case WID_POSITION_END_OF_DOC:
+ {
+ sal_Bool bTemp = FTNPOS_CHAPTER == rFtnInfo.ePos;
+ aRet.setValue(&bTemp, ::getCppuBooleanType());
+ }
+ break;
+ case WID_END_NOTICE :
+ aRet <<= OUString(rFtnInfo.aQuoVadis);
+ break;
+ case WID_BEGIN_NOTICE :
+ aRet <<= OUString(rFtnInfo.aErgoSum);
+ break;
+ }
+ }
+ else
+ throw UnknownPropertyException(OUString ( RTL_CONSTASCII_USTRINGPARAM ( "Unknown property: " ) ) + rPropertyName, static_cast < cppu::OWeakObject * > ( this ) );
+ }
+ else
+ throw uno::RuntimeException();
+ return aRet;
+}
+
+void SwXFootnoteProperties::addPropertyChangeListener(
+ const OUString& /*rPropertyName*/, const uno::Reference< beans::XPropertyChangeListener > & /*xListener*/)
+ throw( beans::UnknownPropertyException, lang::WrappedTargetException, uno::RuntimeException )
+{
+ DBG_WARNING("not implemented");
+}
+
+void SwXFootnoteProperties::removePropertyChangeListener(
+ const OUString& /*rPropertyName*/, const uno::Reference< beans::XPropertyChangeListener > & /*xListener*/)
+ throw( beans::UnknownPropertyException, lang::WrappedTargetException, uno::RuntimeException )
+{
+ DBG_WARNING("not implemented");
+}
+
+void SwXFootnoteProperties::addVetoableChangeListener(
+ const OUString& /*rPropertyName*/, const uno::Reference< beans::XVetoableChangeListener > & /*xListener*/)
+ throw( beans::UnknownPropertyException, lang::WrappedTargetException, uno::RuntimeException )
+{
+ DBG_WARNING("not implemented");
+}
+
+void SwXFootnoteProperties::removeVetoableChangeListener(
+ const OUString& /*rPropertyName*/, const uno::Reference< beans::XVetoableChangeListener > & /*xListener*/)
+ throw( beans::UnknownPropertyException, lang::WrappedTargetException, uno::RuntimeException )
+{
+ DBG_WARNING("not implemented");
+}
+
+/******************************************************************
+ * SwXEndnoteProperties
+ ******************************************************************/
+OUString SwXEndnoteProperties::getImplementationName(void) throw( RuntimeException )
+{
+ return C2U("SwXEndnoteProperties");
+}
+
+sal_Bool SwXEndnoteProperties::supportsService(const OUString& rServiceName) throw( RuntimeException )
+{
+ return C2U("com.sun.star.text.FootnoteSettings") == rServiceName;
+}
+
+Sequence< OUString > SwXEndnoteProperties::getSupportedServiceNames(void) throw( RuntimeException )
+{
+ Sequence< OUString > aRet(1);
+ OUString* pArray = aRet.getArray();
+ pArray[0] = C2U("com.sun.star.text.FootnoteSettings");
+ return aRet;
+}
+
+SwXEndnoteProperties::SwXEndnoteProperties(SwDoc* pDc) :
+ pDoc(pDc),
+ m_pPropertySet(GetEndnoteSet())
+{
+
+}
+
+SwXEndnoteProperties::~SwXEndnoteProperties()
+{
+
+}
+
+uno::Reference< beans::XPropertySetInfo > SwXEndnoteProperties::getPropertySetInfo(void) throw( uno::RuntimeException )
+{
+ static uno::Reference< beans::XPropertySetInfo > aRef = m_pPropertySet->getPropertySetInfo();
+ return aRef;
+}
+
+void SwXEndnoteProperties::setPropertyValue(const OUString& rPropertyName, const uno::Any& aValue)
+ throw( beans::UnknownPropertyException, beans::PropertyVetoException, lang::IllegalArgumentException,
+ lang::WrappedTargetException, uno::RuntimeException )
+{
+ SolarMutexGuard aGuard;
+ if(pDoc)
+ {
+ const SfxItemPropertySimpleEntry* pEntry = m_pPropertySet->getPropertyMap()->getByName( rPropertyName );
+ if(pEntry)
+ {
+ if ( pEntry->nFlags & PropertyAttribute::READONLY)
+ throw PropertyVetoException( OUString ( RTL_CONSTASCII_USTRINGPARAM ( "Property is read-only: " ) ) + rPropertyName, static_cast < cppu::OWeakObject * > ( this ) );
+ SwEndNoteInfo aEndInfo(pDoc->GetEndNoteInfo());
+ switch(pEntry->nWID)
+ {
+ case WID_PREFIX:
+ {
+ OUString uTmp;
+ aValue >>= uTmp;
+ aEndInfo.SetPrefix(uTmp);
+ }
+ break;
+ case WID_SUFFIX:
+ {
+ OUString uTmp;
+ aValue >>= uTmp;
+ aEndInfo.SetSuffix(uTmp);
+ }
+ break;
+ case WID_NUMBERING_TYPE :
+ {
+ sal_Int16 nTmp = 0;
+ aValue >>= nTmp;
+ aEndInfo.aFmt.SetNumberingType(nTmp);
+ }
+ break;
+ case WID_START_AT:
+ {
+ sal_Int16 nTmp = 0;
+ aValue >>= nTmp;
+ aEndInfo.nFtnOffset = nTmp;
+ }
+ break;
+ case WID_PARAGRAPH_STYLE :
+ {
+ SwTxtFmtColl* pColl = lcl_GetParaStyle(pDoc, aValue);
+ if(pColl)
+ aEndInfo.SetFtnTxtColl(*pColl);
+ }
+ break;
+ case WID_PAGE_STYLE :
+ {
+ SwPageDesc* pDesc = lcl_GetPageDesc(pDoc, aValue);
+ if(pDesc)
+ aEndInfo.ChgPageDesc( pDesc );
+ }
+ break;
+ case WID_ANCHOR_CHARACTER_STYLE:
+ case WID_CHARACTER_STYLE :
+ {
+ SwCharFmt* pFmt = lcl_getCharFmt(pDoc, aValue);
+ if(pFmt)
+ {
+ if(pEntry->nWID == WID_ANCHOR_CHARACTER_STYLE)
+ aEndInfo.SetAnchorCharFmt(pFmt);
+ else
+ aEndInfo.SetCharFmt(pFmt);
+ }
+ }
+ break;
+ }
+ pDoc->SetEndNoteInfo(aEndInfo);
+ }
+ else
+ throw UnknownPropertyException(OUString ( RTL_CONSTASCII_USTRINGPARAM ( "Unknown property: " ) ) + rPropertyName, static_cast < cppu::OWeakObject * > ( this ) );
+ }
+}
+
+uno::Any SwXEndnoteProperties::getPropertyValue(const OUString& rPropertyName)
+ throw( UnknownPropertyException, WrappedTargetException, RuntimeException )
+{
+ SolarMutexGuard aGuard;
+ uno::Any aRet;
+ if(pDoc)
+ {
+ const SfxItemPropertySimpleEntry* pEntry = m_pPropertySet->getPropertyMap()->getByName( rPropertyName );
+ if(pEntry)
+ {
+ const SwEndNoteInfo& rEndInfo = pDoc->GetEndNoteInfo();
+ switch(pEntry->nWID)
+ {
+ case WID_PREFIX:
+ aRet <<= OUString(rEndInfo.GetPrefix());
+ break;
+ case WID_SUFFIX:
+ aRet <<= OUString(rEndInfo.GetSuffix());
+ break;
+ case WID_NUMBERING_TYPE :
+ aRet <<= rEndInfo.aFmt.GetNumberingType();
+ break;
+ case WID_START_AT:
+ aRet <<= (sal_Int16)rEndInfo.nFtnOffset;
+ break;
+ case WID_PARAGRAPH_STYLE :
+ {
+ SwTxtFmtColl* pColl = rEndInfo.GetFtnTxtColl();
+ String aString;
+ if(pColl)
+ aString = pColl->GetName();
+ SwStyleNameMapper::FillProgName(
+ aString,
+ aString,
+ nsSwGetPoolIdFromName::GET_POOLID_TXTCOLL,
+ sal_True);
+ aRet <<= OUString ( aString );
+
+ }
+ break;
+ case WID_PAGE_STYLE :
+ {
+ String aString;
+ if( rEndInfo.KnowsPageDesc() )
+ {
+ SwStyleNameMapper::FillProgName(
+ rEndInfo.GetPageDesc( *pDoc )->GetName(),
+ aString,
+ nsSwGetPoolIdFromName::GET_POOLID_PAGEDESC,
+ sal_True );
+ }
+ aRet <<= OUString ( aString );
+ }
+ break;
+ case WID_ANCHOR_CHARACTER_STYLE:
+ case WID_CHARACTER_STYLE:
+ {
+ String aString;
+ const SwCharFmt* pCharFmt = 0;
+ if( pEntry->nWID == WID_ANCHOR_CHARACTER_STYLE )
+ {
+ if( rEndInfo.GetAnchorCharFmtDep()->GetRegisteredIn() )
+ pCharFmt = rEndInfo.GetAnchorCharFmt(*pDoc);
+ }
+ else
+ {
+ if( rEndInfo.GetCharFmtDep()->GetRegisteredIn() )
+ pCharFmt = rEndInfo.GetCharFmt(*pDoc);
+ }
+ if( pCharFmt )
+ {
+ SwStyleNameMapper::FillProgName(
+ pCharFmt->GetName(),
+ aString,
+ nsSwGetPoolIdFromName::GET_POOLID_CHRFMT,
+ sal_True );
+ }
+ aRet <<= OUString ( aString );
+ }
+ break;
+ }
+ }
+ else
+ throw UnknownPropertyException(OUString ( RTL_CONSTASCII_USTRINGPARAM ( "Unknown property: " ) ) + rPropertyName, static_cast < cppu::OWeakObject * > ( this ) );
+ }
+ return aRet;
+}
+
+void SwXEndnoteProperties::addPropertyChangeListener(
+ const OUString& /*PropertyName*/, const uno::Reference< beans::XPropertyChangeListener > & /*xListener*/) throw( beans::UnknownPropertyException, lang::WrappedTargetException, uno::RuntimeException )
+{
+ DBG_WARNING("not implemented");
+}
+
+void SwXEndnoteProperties::removePropertyChangeListener(const OUString& /*PropertyName*/,
+ const uno:: Reference< beans::XPropertyChangeListener > & /*xListener*/)
+ throw( beans::UnknownPropertyException, lang::WrappedTargetException, uno::RuntimeException )
+{
+ DBG_WARNING("not implemented");
+}
+
+void SwXEndnoteProperties::addVetoableChangeListener(const OUString& /*PropertyName*/,
+ const uno:: Reference< beans::XVetoableChangeListener > & /*xListener*/)
+ throw( beans::UnknownPropertyException, lang::WrappedTargetException, uno::RuntimeException )
+{
+ DBG_WARNING("not implemented");
+}
+
+void SwXEndnoteProperties::removeVetoableChangeListener(const OUString& /*PropertyName*/, const uno:: Reference< beans::XVetoableChangeListener > & /*xListener*/)
+ throw( beans::UnknownPropertyException, lang::WrappedTargetException, uno::RuntimeException )
+{
+ DBG_WARNING("not implemented");
+}
+
+/******************************************************************
+ * SwXLineNumberingProperties
+ ******************************************************************/
+OUString SwXLineNumberingProperties::getImplementationName(void) throw( RuntimeException )
+{
+ return C2U("SwXLineNumberingProperties");
+}
+
+sal_Bool SwXLineNumberingProperties::supportsService(const OUString& rServiceName) throw( RuntimeException )
+{
+ return C2U("com.sun.star.text.LineNumberingProperties") == rServiceName;
+}
+
+Sequence< OUString > SwXLineNumberingProperties::getSupportedServiceNames(void) throw( RuntimeException )
+{
+ Sequence< OUString > aRet(1);
+ OUString* pArray = aRet.getArray();
+ pArray[0] = C2U("com.sun.star.text.LineNumberingProperties");
+ return aRet;
+}
+
+SwXLineNumberingProperties::SwXLineNumberingProperties(SwDoc* pDc) :
+ pDoc(pDc),
+ m_pPropertySet(GetLineNumberingSet())
+{
+
+}
+
+SwXLineNumberingProperties::~SwXLineNumberingProperties()
+{
+
+}
+
+uno::Reference< beans::XPropertySetInfo > SwXLineNumberingProperties::getPropertySetInfo(void) throw( uno::RuntimeException )
+{
+ static uno::Reference< beans::XPropertySetInfo > aRef = m_pPropertySet->getPropertySetInfo();
+ return aRef;
+}
+
+void SwXLineNumberingProperties::setPropertyValue(
+ const OUString& rPropertyName, const Any& aValue)
+ throw( UnknownPropertyException, PropertyVetoException,
+ IllegalArgumentException, WrappedTargetException, RuntimeException )
+{
+ SolarMutexGuard aGuard;
+ if(pDoc)
+ {
+ const SfxItemPropertySimpleEntry* pEntry = m_pPropertySet->getPropertyMap()->getByName( rPropertyName );
+ if(pEntry)
+ {
+ if ( pEntry->nFlags & PropertyAttribute::READONLY)
+ throw PropertyVetoException( OUString ( RTL_CONSTASCII_USTRINGPARAM ( "Property is read-only: " ) ) + rPropertyName, static_cast < cppu::OWeakObject * > ( this ) );
+ SwLineNumberInfo aInfo(pDoc->GetLineNumberInfo());
+ switch(pEntry->nWID)
+ {
+ case WID_NUM_ON:
+ {
+ sal_Bool bVal = *(sal_Bool*)aValue.getValue();
+ aInfo.SetPaintLineNumbers(bVal);
+ }
+ break;
+ case WID_CHARACTER_STYLE :
+ {
+ SwCharFmt* pFmt = lcl_getCharFmt(pDoc, aValue);
+ if(pFmt)
+ aInfo.SetCharFmt(pFmt);
+ }
+ break;
+ case WID_NUMBERING_TYPE :
+ {
+ SvxNumberType aNumType(aInfo.GetNumType());
+ sal_Int16 nTmp = 0;
+ aValue >>= nTmp;
+ aNumType.SetNumberingType(nTmp);
+ aInfo.SetNumType(aNumType);
+ }
+ break;
+ case WID_NUMBER_POSITION :
+ {
+ sal_Int16 nTmp = 0;
+ aValue >>= nTmp;
+ switch(nTmp)
+ {
+ case style::LineNumberPosition::LEFT:
+ aInfo.SetPos(LINENUMBER_POS_LEFT); ;
+ break;
+ case style::LineNumberPosition::RIGHT :
+ aInfo.SetPos(LINENUMBER_POS_RIGHT); ;
+ break;
+ case style::LineNumberPosition::INSIDE:
+ aInfo.SetPos(LINENUMBER_POS_INSIDE); ;
+ break;
+ case style::LineNumberPosition::OUTSIDE:
+ aInfo.SetPos(LINENUMBER_POS_OUTSIDE);
+ break;
+ }
+ }
+ break;
+ case WID_DISTANCE :
+ {
+ sal_Int32 nVal = 0;
+ aValue >>= nVal;
+ sal_Int32 nTmp = MM100_TO_TWIP(nVal);
+ if (nTmp > USHRT_MAX)
+ nTmp = USHRT_MAX;
+ aInfo.SetPosFromLeft( static_cast< sal_uInt16 >(nTmp) );
+ }
+ break;
+ case WID_INTERVAL :
+ {
+ sal_Int16 nTmp = 0;
+ aValue >>= nTmp;
+ if( nTmp > 0)
+ aInfo.SetCountBy(nTmp);
+ }
+ break;
+ case WID_SEPARATOR_TEXT :
+ {
+ OUString uTmp;
+ aValue >>= uTmp;
+ aInfo.SetDivider(uTmp);
+ }
+ break;
+ case WID_SEPARATOR_INTERVAL:
+ {
+ sal_Int16 nTmp = 0;
+ aValue >>= nTmp;
+ if( nTmp >= 0)
+ aInfo.SetDividerCountBy(nTmp);
+ }
+ break;
+ case WID_COUNT_EMPTY_LINES :
+ {
+ sal_Bool bVal = *(sal_Bool*)aValue.getValue();
+ aInfo.SetCountBlankLines(bVal);
+ }
+ break;
+ case WID_COUNT_LINES_IN_FRAMES :
+ {
+ sal_Bool bVal = *(sal_Bool*)aValue.getValue();
+ aInfo.SetCountInFlys(bVal);
+ }
+ break;
+ case WID_RESTART_AT_EACH_PAGE :
+ {
+ sal_Bool bVal = *(sal_Bool*)aValue.getValue();
+ aInfo.SetRestartEachPage(bVal);
+ }
+ break;
+ }
+ pDoc->SetLineNumberInfo(aInfo);
+ }
+ else
+ throw UnknownPropertyException(OUString ( RTL_CONSTASCII_USTRINGPARAM ( "Unknown property: " ) ) + rPropertyName, static_cast < cppu::OWeakObject * > ( this ) );
+ }
+ else
+ throw uno::RuntimeException();
+}
+
+Any SwXLineNumberingProperties::getPropertyValue(const OUString& rPropertyName)
+ throw( UnknownPropertyException, WrappedTargetException, RuntimeException )
+{
+ SolarMutexGuard aGuard;
+ Any aRet;
+ if(pDoc)
+ {
+ const SfxItemPropertySimpleEntry* pEntry = m_pPropertySet->getPropertyMap()->getByName( rPropertyName );
+ if(pEntry)
+ {
+ const SwLineNumberInfo& rInfo = pDoc->GetLineNumberInfo();
+ switch(pEntry->nWID)
+ {
+ case WID_NUM_ON:
+ {
+ sal_Bool bTemp = rInfo.IsPaintLineNumbers();
+ aRet.setValue(&bTemp, ::getCppuBooleanType());
+ }
+ break;
+ case WID_CHARACTER_STYLE :
+ {
+ String aString;
+ // return empty string if no char format is set
+ // otherwise it would be created here
+ if(rInfo.HasCharFormat())
+ {
+ SwStyleNameMapper::FillProgName(
+ rInfo.GetCharFmt(*pDoc)->GetName(),
+ aString,
+ nsSwGetPoolIdFromName::GET_POOLID_CHRFMT,
+ sal_True);
+ }
+ aRet <<= OUString ( aString );
+ }
+ break;
+ case WID_NUMBERING_TYPE :
+ aRet <<= rInfo.GetNumType().GetNumberingType();
+ break;
+ case WID_NUMBER_POSITION :
+ {
+ sal_Int16 nRet = 0;
+ switch(rInfo.GetPos())
+ {
+ case LINENUMBER_POS_LEFT:
+ nRet = style::LineNumberPosition::LEFT;
+ break;
+ case LINENUMBER_POS_RIGHT :
+ nRet = style::LineNumberPosition::RIGHT ;
+ break;
+ case LINENUMBER_POS_INSIDE:
+ nRet = style::LineNumberPosition::INSIDE ;
+ break;
+ case LINENUMBER_POS_OUTSIDE :
+ nRet = style::LineNumberPosition::OUTSIDE ;
+ break;
+ }
+ aRet <<= nRet;
+ }
+ break;
+ case WID_DISTANCE :
+ {
+ sal_uInt32 nPos = rInfo.GetPosFromLeft();
+ if(USHRT_MAX == nPos)
+ nPos = 0;
+ aRet <<= static_cast < sal_Int32 >(TWIP_TO_MM100_UNSIGNED(nPos));
+ }
+ break;
+ case WID_INTERVAL :
+ aRet <<= (sal_Int16)rInfo.GetCountBy();
+ break;
+ case WID_SEPARATOR_TEXT :
+ aRet <<= OUString(rInfo.GetDivider());
+ break;
+ case WID_SEPARATOR_INTERVAL:
+ aRet <<= (sal_Int16)rInfo.GetDividerCountBy();
+ break;
+ case WID_COUNT_EMPTY_LINES :
+ {
+ sal_Bool bTemp = rInfo.IsCountBlankLines();
+ aRet.setValue(&bTemp, ::getCppuBooleanType());
+ }
+ break;
+ case WID_COUNT_LINES_IN_FRAMES :
+ {
+ sal_Bool bTemp = rInfo.IsCountInFlys();
+ aRet.setValue(&bTemp, ::getCppuBooleanType());
+ }
+ break;
+ case WID_RESTART_AT_EACH_PAGE :
+ {
+ sal_Bool bTemp = rInfo.IsRestartEachPage();
+ aRet.setValue(&bTemp, ::getCppuBooleanType());
+ }
+ break;
+ }
+ }
+ else
+ throw UnknownPropertyException(OUString ( RTL_CONSTASCII_USTRINGPARAM ( "Unknown property: " ) ) + rPropertyName, static_cast < cppu::OWeakObject * > ( this ) );
+ }
+ else
+ throw uno::RuntimeException();
+ return aRet;
+}
+
+void SwXLineNumberingProperties::addPropertyChangeListener(const OUString& /*rPropertyName*/, const uno:: Reference< beans::XPropertyChangeListener > & /*xListener*/) throw( beans::UnknownPropertyException, lang::WrappedTargetException, uno::RuntimeException )
+{
+DBG_WARNING("not implemented");
+}
+
+void SwXLineNumberingProperties::removePropertyChangeListener(const OUString& /*rPropertyName*/, const uno:: Reference< beans::XPropertyChangeListener > & /*xListener*/) throw( beans::UnknownPropertyException, lang::WrappedTargetException, uno::RuntimeException )
+{
+DBG_WARNING("not implemented");
+}
+
+void SwXLineNumberingProperties::addVetoableChangeListener(const OUString& /*rPropertyName*/, const uno:: Reference< beans::XVetoableChangeListener > & /*xListener*/) throw( beans::UnknownPropertyException, lang::WrappedTargetException, uno::RuntimeException )
+{
+DBG_WARNING("not implemented");
+}
+
+void SwXLineNumberingProperties::removeVetoableChangeListener(const OUString& /*rPropertyName*/, const uno:: Reference< beans::XVetoableChangeListener > & /*xListener*/)
+ throw( beans::UnknownPropertyException, lang::WrappedTargetException, uno::RuntimeException )
+{
+DBG_WARNING("not implemented");
+}
+
+/******************************************************************
+ * SwXNumberingRules
+ ******************************************************************/
+String SwXNumberingRules::sInvalidStyle(String::CreateFromAscii("__XXX___invalid"));
+
+const String& SwXNumberingRules::GetInvalidStyle()
+{
+ return sInvalidStyle;
+}
+
+const uno::Sequence< sal_Int8 > & SwXNumberingRules::getUnoTunnelId()
+{
+ static uno::Sequence< sal_Int8 > aSeq = ::CreateUnoTunnelId();
+ return aSeq;
+}
+
+// return implementation specific data
+sal_Int64 SwXNumberingRules::getSomething( const uno::Sequence< sal_Int8 > & rId ) throw(uno::RuntimeException)
+{
+ if( rId.getLength() == 16
+ && 0 == rtl_compareMemory( getUnoTunnelId().getConstArray(),
+ rId.getConstArray(), 16 ) )
+ {
+ return sal::static_int_cast< sal_Int64 >( reinterpret_cast< sal_IntPtr >(this) );
+ }
+ return 0;
+}
+
+OUString SwXNumberingRules::getImplementationName(void) throw( RuntimeException )
+{
+ return C2U("SwXNumberingRules");
+}
+
+sal_Bool SwXNumberingRules::supportsService(const OUString& rServiceName) throw( RuntimeException )
+{
+ return C2U("com.sun.star.text.NumberingRules") == rServiceName;
+}
+
+Sequence< OUString > SwXNumberingRules::getSupportedServiceNames(void) throw( RuntimeException )
+{
+ Sequence< OUString > aRet(1);
+ OUString* pArray = aRet.getArray();
+ pArray[0] = C2U("com.sun.star.text.NumberingRules");
+ return aRet;
+}
+
+SwXNumberingRules::SwXNumberingRules(const SwNumRule& rRule) :
+ pDoc(0),
+ pDocShell(0),
+ pNumRule(new SwNumRule(rRule)),
+ m_pPropertySet(GetNumberingRulesSet()),
+ bOwnNumRuleCreated(sal_True)
+{
+ sal_uInt16 i;
+
+ //erstmal das Doc organisieren; es haengt an den gesetzten Zeichenvorlagen - wenn
+ // keine gesetzt sind, muss es auch ohne gehen
+ for( i = 0; i < MAXLEVEL; i++)
+ {
+ SwNumFmt rFmt(pNumRule->Get(i));
+ SwCharFmt* pCharFmt = rFmt.GetCharFmt();
+ if(pCharFmt)
+ {
+ pDoc = pCharFmt->GetDoc();
+ break;
+ }
+ }
+ if(pDoc)
+ pDoc->GetPageDescFromPool(RES_POOLPAGE_STANDARD)->Add(this);
+ for(i = 0; i < MAXLEVEL; i++)
+ {
+ sNewCharStyleNames[i] = SwXNumberingRules::GetInvalidStyle();
+ sNewBulletFontNames[i] = SwXNumberingRules::GetInvalidStyle();
+ }
+}
+
+SwXNumberingRules::SwXNumberingRules(SwDocShell& rDocSh) :
+ pDoc(0),
+ pDocShell(&rDocSh),
+ pNumRule(0),
+ m_pPropertySet(GetNumberingRulesSet()),
+ bOwnNumRuleCreated(sal_False)
+{
+ pDocShell->GetDoc()->GetPageDescFromPool(RES_POOLPAGE_STANDARD)->Add(this);
+}
+
+SwXNumberingRules::SwXNumberingRules(SwDoc& rDoc) :
+ pDoc(&rDoc),
+ pDocShell(0),
+ pNumRule(0),
+ m_pPropertySet(GetNumberingRulesSet()),
+ bOwnNumRuleCreated(sal_False)
+{
+ rDoc.GetPageDescFromPool(RES_POOLPAGE_STANDARD)->Add(this);
+ sCreatedNumRuleName = rDoc.GetUniqueNumRuleName();
+#if OSL_DEBUG_LEVEL > 1
+ sal_uInt16 nIndex =
+#endif
+ rDoc.MakeNumRule( sCreatedNumRuleName, 0, sal_False,
+ // --> OD 2008-06-06 #i89178#
+ numfunc::GetDefaultPositionAndSpaceMode() );
+ // <--
+#if OSL_DEBUG_LEVEL > 1
+ (void)nIndex;
+#endif
+}
+
+SwXNumberingRules::~SwXNumberingRules()
+{
+ SolarMutexGuard aGuard;
+ if(pDoc && sCreatedNumRuleName.Len())
+ pDoc->DelNumRule( sCreatedNumRuleName );
+ if( pNumRule && bOwnNumRuleCreated )
+ delete pNumRule;
+}
+
+void SwXNumberingRules::replaceByIndex(sal_Int32 nIndex, const uno::Any& rElement)
+ throw( lang::IllegalArgumentException, lang::IndexOutOfBoundsException,
+ lang::WrappedTargetException, uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+ if(nIndex < 0 || MAXLEVEL <= nIndex)
+ throw lang::IndexOutOfBoundsException();
+
+ if(rElement.getValueType().getTypeClass() != uno::TypeClass_SEQUENCE)
+ throw lang::IllegalArgumentException();
+ const uno::Sequence<beans::PropertyValue>& rProperties =
+ *(const uno::Sequence<beans::PropertyValue>*)rElement.getValue();
+ SwNumRule* pRule = 0;
+ if(pNumRule)
+ SwXNumberingRules::SetNumberingRuleByIndex( *pNumRule,
+ rProperties, nIndex);
+ else if(pDocShell)
+ {
+ // #i87650# - correction of cws swwarnings:
+ SwNumRule aNumRule( *(pDocShell->GetDoc()->GetOutlineNumRule()) );
+ SwXNumberingRules::SetNumberingRuleByIndex( aNumRule,
+ rProperties, nIndex);
+ //hier noch die Zeichenformate bei Bedarf setzen
+ const SwCharFmts* pFmts = pDocShell->GetDoc()->GetCharFmts();
+ sal_uInt16 nChCount = pFmts->Count();
+ for(sal_uInt16 i = 0; i < MAXLEVEL;i++)
+ {
+ SwNumFmt aFmt(aNumRule.Get( i ));
+ if(sNewCharStyleNames[i].Len() &&
+ !sNewCharStyleNames[i].EqualsAscii(SW_PROP_NAME_STR(UNO_NAME_CHARACTER_FORMAT_NONE)) &&
+ (!aFmt.GetCharFmt() ||
+ aFmt.GetCharFmt()->GetName()!= sNewCharStyleNames[i] ))
+ {
+ SwCharFmt* pCharFmt = 0;
+ for(sal_uInt16 j = 0; j< nChCount; j++)
+ {
+ SwCharFmt* pTmp = (*pFmts)[j];
+ if(pTmp->GetName() == sNewCharStyleNames[i])
+ {
+ pCharFmt = pTmp;
+ break;
+ }
+ }
+ if(!pCharFmt)
+ {
+ SfxStyleSheetBase* pBase;
+ pBase = pDocShell->GetStyleSheetPool()->Find(sNewCharStyleNames[i],
+ SFX_STYLE_FAMILY_CHAR);
+ if(!pBase)
+ pBase = &pDocShell->GetStyleSheetPool()->Make(sNewCharStyleNames[i], SFX_STYLE_FAMILY_CHAR);
+ pCharFmt = ((SwDocStyleSheet*)pBase)->GetCharFmt();
+
+ }
+ aFmt.SetCharFmt( pCharFmt );
+ aNumRule.Set( i, aFmt );
+ }
+ }
+ pDocShell->GetDoc()->SetOutlineNumRule( aNumRule );
+ }
+ else if(!pNumRule && pDoc && sCreatedNumRuleName.Len() &&
+ 0 != (pRule = pDoc->FindNumRulePtr( sCreatedNumRuleName )))
+ {
+ SwXNumberingRules::SetNumberingRuleByIndex( *pRule,
+ rProperties, nIndex);
+
+ pRule->Validate();
+ }
+ else
+ throw uno::RuntimeException();
+
+}
+
+sal_Int32 SwXNumberingRules::getCount(void) throw( uno::RuntimeException )
+{
+ return MAXLEVEL;
+}
+
+uno::Any SwXNumberingRules::getByIndex(sal_Int32 nIndex)
+ throw( lang::IndexOutOfBoundsException, lang::WrappedTargetException,
+ uno::RuntimeException )
+{
+ SolarMutexGuard aGuard;
+ if(nIndex < 0 || MAXLEVEL <= nIndex)
+ throw lang::IndexOutOfBoundsException();
+
+ uno::Any aVal;
+ const SwNumRule* pRule = pNumRule;
+ if(!pRule && pDoc && sCreatedNumRuleName.Len())
+ pRule = pDoc->FindNumRulePtr( sCreatedNumRuleName );
+ if(pRule)
+ {
+ uno::Sequence<beans::PropertyValue> aRet = GetNumberingRuleByIndex(
+ *pRule, nIndex);
+ aVal.setValue(&aRet, ::getCppuType((uno::Sequence<beans::PropertyValue>*)0));
+
+ }
+ else if(pDocShell)
+ {
+ uno::Sequence<beans::PropertyValue> aRet = GetNumberingRuleByIndex(
+ *pDocShell->GetDoc()->GetOutlineNumRule(), nIndex);
+ aVal.setValue(&aRet, ::getCppuType((uno::Sequence<beans::PropertyValue>*)0));
+ }
+ else
+ throw uno::RuntimeException();
+ return aVal;
+}
+
+uno::Type SwXNumberingRules::getElementType(void)
+ throw( uno::RuntimeException )
+{
+ return ::getCppuType((uno::Sequence<beans::PropertyValue>*)0);
+}
+
+sal_Bool SwXNumberingRules::hasElements(void) throw( uno::RuntimeException )
+{
+ return sal_True;
+}
+
+uno::Sequence<beans::PropertyValue> SwXNumberingRules::GetNumberingRuleByIndex(
+ const SwNumRule& rNumRule, sal_Int32 nIndex) const
+{
+ SolarMutexGuard aGuard;
+ DBG_ASSERT( 0 <= nIndex && nIndex < MAXLEVEL, "index out of range" );
+
+ const SwNumFmt& rFmt = rNumRule.Get( (sal_uInt16)nIndex );
+
+ sal_Bool bChapterNum = pDocShell != 0;
+
+ PropValDataArr aPropertyValues;
+ //fill all properties into the array
+
+ //adjust
+ SvxAdjust eAdj = rFmt.GetNumAdjust();
+ sal_Int16 nINT16 = aSvxToUnoAdjust[(sal_uInt16)eAdj];
+ PropValData* pData = new PropValData((void*)&nINT16, "Adjust", ::getCppuType((const sal_Int16*)0) );
+ aPropertyValues.Insert(pData, aPropertyValues.Count());
+
+ //parentnumbering
+ nINT16 = rFmt.GetIncludeUpperLevels();
+ pData = new PropValData((void*)&nINT16, "ParentNumbering", ::getCppuType((const sal_Int16*)0));
+ aPropertyValues.Insert(pData, aPropertyValues.Count());
+
+ //prefix
+ OUString aUString = rFmt.GetPrefix();
+ pData = new PropValData((void*)&aUString, "Prefix", ::getCppuType((const OUString*)0));
+ aPropertyValues.Insert(pData, aPropertyValues.Count());
+
+ //suffix
+ aUString = rFmt.GetSuffix();
+ pData = new PropValData((void*)&aUString, "Suffix", ::getCppuType((const OUString*)0));
+ aPropertyValues.Insert(pData, aPropertyValues.Count());
+
+ //char style name
+ SwCharFmt* pCharFmt = rFmt.GetCharFmt();
+ String CharStyleName;
+ if(pCharFmt)
+ CharStyleName = pCharFmt->GetName();
+ //egal ob ein Style vorhanden ist oder nicht ueberschreibt der Array-Eintrag diesen String
+ if(sNewCharStyleNames[(sal_uInt16)nIndex].Len() &&
+ SwXNumberingRules::sInvalidStyle != sNewCharStyleNames[(sal_uInt16)nIndex])
+ CharStyleName = sNewCharStyleNames[(sal_uInt16)nIndex];
+
+ String aString;
+ SwStyleNameMapper::FillProgName( CharStyleName, aString, nsSwGetPoolIdFromName::GET_POOLID_CHRFMT, sal_True );
+ aUString = aString;
+ pData = new PropValData((void*)&aUString, "CharStyleName", ::getCppuType((const OUString*)0));
+ aPropertyValues.Insert(pData, aPropertyValues.Count());
+
+ //startvalue
+ nINT16 = rFmt.GetStart();
+ pData = new PropValData((void*)&nINT16, "StartWith", ::getCppuType((const sal_Int16*)0));
+ aPropertyValues.Insert(pData, aPropertyValues.Count());
+
+ if ( rFmt.GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_WIDTH_AND_POSITION )
+ {
+ //leftmargin
+ sal_Int32 nINT32 = TWIP_TO_MM100(rFmt.GetAbsLSpace());
+ pData = new PropValData((void*)&nINT32, SW_PROP_NAME_STR(UNO_NAME_LEFT_MARGIN), ::getCppuType((const sal_Int32*)0));
+ aPropertyValues.Insert(pData, aPropertyValues.Count());
+
+ //chartextoffset
+ nINT32 = TWIP_TO_MM100(rFmt.GetCharTextDistance());
+ pData = new PropValData((void*)&nINT32, SW_PROP_NAME_STR(UNO_NAME_SYMBOL_TEXT_DISTANCE), ::getCppuType((const sal_Int32*)0));
+ aPropertyValues.Insert(pData, aPropertyValues.Count());
+
+ //firstlineoffset
+ nINT32 = TWIP_TO_MM100(rFmt.GetFirstLineOffset());
+ pData = new PropValData((void*)&nINT32, SW_PROP_NAME_STR(UNO_NAME_FIRST_LINE_OFFSET), ::getCppuType((const sal_Int32*)0));
+ aPropertyValues.Insert(pData, aPropertyValues.Count());
+ }
+
+ // PositionAndSpaceMode
+ nINT16 = PositionAndSpaceMode::LABEL_WIDTH_AND_POSITION;
+ if ( rFmt.GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_ALIGNMENT )
+ {
+ nINT16 = PositionAndSpaceMode::LABEL_ALIGNMENT;
+ }
+ pData = new PropValData( (void*)&nINT16,
+ SW_PROP_NAME_STR(UNO_NAME_POSITION_AND_SPACE_MODE),
+ ::getCppuType((const sal_Int16*)0) );
+ aPropertyValues.Insert(pData, aPropertyValues.Count());
+
+ if ( rFmt.GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_ALIGNMENT )
+ {
+ // LabelFollowedBy
+ nINT16 = LabelFollow::LISTTAB;
+ if ( rFmt.GetLabelFollowedBy() == SvxNumberFormat::SPACE )
+ {
+ nINT16 = LabelFollow::SPACE;
+ }
+ else if ( rFmt.GetLabelFollowedBy() == SvxNumberFormat::NOTHING )
+ {
+ nINT16 = LabelFollow::NOTHING;
+ }
+ pData = new PropValData( (void*)&nINT16,
+ SW_PROP_NAME_STR(UNO_NAME_LABEL_FOLLOWED_BY),
+ ::getCppuType((const sal_Int16*)0) );
+ aPropertyValues.Insert(pData, aPropertyValues.Count());
+
+ // ListtabStopPosition
+ sal_Int32 nINT32 = TWIP_TO_MM100(rFmt.GetListtabPos());
+ pData = new PropValData( (void*)&nINT32,
+ SW_PROP_NAME_STR(UNO_NAME_LISTTAB_STOP_POSITION),
+ ::getCppuType((const sal_Int32*)0));
+ aPropertyValues.Insert(pData, aPropertyValues.Count());
+
+ // FirstLineIndent
+ nINT32 = TWIP_TO_MM100(rFmt.GetFirstLineIndent());
+ pData = new PropValData( (void*)&nINT32,
+ SW_PROP_NAME_STR(UNO_NAME_FIRST_LINE_INDENT),
+ ::getCppuType((const sal_Int32*)0));
+ aPropertyValues.Insert(pData, aPropertyValues.Count());
+
+ // IndentAt
+ nINT32 = TWIP_TO_MM100(rFmt.GetIndentAt());
+ pData = new PropValData( (void*)&nINT32,
+ SW_PROP_NAME_STR(UNO_NAME_INDENT_AT),
+ ::getCppuType((const sal_Int32*)0));
+ aPropertyValues.Insert(pData, aPropertyValues.Count());
+ }
+
+ //numberingtype
+ nINT16 = rFmt.GetNumberingType();
+ pData = new PropValData((void*)&nINT16, "NumberingType", ::getCppuType((const sal_Int16*)0));
+ aPropertyValues.Insert(pData, aPropertyValues.Count());
+
+ if(!bChapterNum)
+ {
+ if(SVX_NUM_CHAR_SPECIAL == rFmt.GetNumberingType())
+ {
+ //BulletId
+ nINT16 = rFmt.GetBulletChar();
+ pData = new PropValData((void*)&nINT16, "BulletId", ::getCppuType((const sal_Int16*)0));
+ aPropertyValues.Insert(pData, aPropertyValues.Count());
+
+ const Font* pFont = rFmt.GetBulletFont();
+
+ //BulletChar
+ aUString = OUString(rFmt.GetBulletChar());
+ pData = new PropValData((void*)&aUString, "BulletChar", ::getCppuType((const OUString*)0));
+ aPropertyValues.Insert(pData, aPropertyValues.Count());
+
+ //BulletFontName
+ String sBulletFontName;
+ if(pFont)
+ sBulletFontName = pFont->GetStyleName();
+ aUString = sBulletFontName;
+ pData = new PropValData((void*)&aUString, "BulletFontName", ::getCppuType((const OUString*)0));
+ aPropertyValues.Insert(pData, aPropertyValues.Count());
+
+ //BulletFont
+ if(pFont)
+ {
+ awt::FontDescriptor aDesc;
+ SvxUnoFontDescriptor::ConvertFromFont( *pFont, aDesc );
+ pData = new PropValData((void*)&aDesc, SW_PROP_NAME_STR(UNO_NAME_BULLET_FONT), ::getCppuType((const awt::FontDescriptor*)0));
+ aPropertyValues.Insert(pData, aPropertyValues.Count());
+ }
+ }
+ if(SVX_NUM_BITMAP == rFmt.GetNumberingType())
+ {
+ //GraphicURL
+ const SvxBrushItem* pBrush = rFmt.GetBrush();
+ if(pBrush)
+ {
+ Any aAny;
+ pBrush->QueryValue( aAny, MID_GRAPHIC_URL );
+ aAny >>= aUString;
+ }
+ else
+ aUString = aEmptyStr;
+ pData = new PropValData((void*)&aUString, SW_PROP_NAME_STR(UNO_NAME_GRAPHIC_URL), ::getCppuType((const OUString*)0));
+ aPropertyValues.Insert(pData, aPropertyValues.Count());
+
+ //graphicbitmap
+ const Graphic* pGraphic = 0;
+ if(pBrush )
+ pGraphic = pBrush->GetGraphic();
+ if(pGraphic)
+ {
+ uno::Reference<awt::XBitmap> xBmp = VCLUnoHelper::CreateBitmap( pGraphic->GetBitmapEx() );
+ pData = new PropValData((void*)&xBmp, SW_PROP_NAME_STR(UNO_NAME_GRAPHIC_BITMAP),
+ ::getCppuType((const uno::Reference<awt::XBitmap>*)0));
+ aPropertyValues.Insert(pData, aPropertyValues.Count());
+ }
+ Size aSize = rFmt.GetGraphicSize();
+ // #i101131#
+ // adjust conversion due to type mismatch between <Size> and <awt::Size>
+ awt::Size aAwtSize(TWIP_TO_MM100(aSize.Width()), TWIP_TO_MM100(aSize.Height()));
+ pData = new PropValData((void*)&aAwtSize, SW_PROP_NAME_STR(UNO_NAME_GRAPHIC_SIZE), ::getCppuType((const awt::Size*)0));
+ // <--
+ aPropertyValues.Insert(pData, aPropertyValues.Count());
+
+ const SwFmtVertOrient* pOrient = rFmt.GetGraphicOrientation();
+ if(pOrient)
+ {
+ pData = new PropValData((void*)0, SW_PROP_NAME_STR(UNO_NAME_VERT_ORIENT), ::getCppuType((const sal_Int16*)0));
+ ((const SfxPoolItem*)pOrient)->QueryValue(pData->aVal, MID_VERTORIENT_ORIENT);
+ aPropertyValues.Insert(pData, aPropertyValues.Count());
+ }
+ }
+
+ }
+ else
+ {
+ //Vorlagenname
+ String sValue(SW_RES(STR_POOLCOLL_HEADLINE1 + nIndex));
+ const SwTxtFmtColls* pColls = pDocShell->GetDoc()->GetTxtFmtColls();
+ const sal_uInt16 nCount = pColls->Count();
+ for(sal_uInt16 i = 0; i < nCount;++i)
+ {
+ SwTxtFmtColl &rTxtColl = *pColls->operator[](i);
+ if(rTxtColl.IsDefault())
+ continue;
+
+ //sal_Int8 nOutLevel = rTxtColl.GetOutlineLevel(); //#outline level,zhaojianwei
+ const sal_Int16 nOutLevel = rTxtColl.IsAssignedToListLevelOfOutlineStyle()
+ ? static_cast<sal_Int16>(rTxtColl.GetAssignedOutlineStyleLevel())
+ : MAXLEVEL; //<-end,zhaojianwei
+ if ( nOutLevel == nIndex )
+ {
+ sValue = rTxtColl.GetName();
+ break; // the style for the level in question has been found
+ }
+ else if( sValue==rTxtColl.GetName() )
+ {
+ // if the default for the level is existing, but its
+ // level is different, then it cannot be the default.
+ sValue.Erase();
+ }
+ }
+ String aName;
+ SwStyleNameMapper::FillProgName(sValue, aName, nsSwGetPoolIdFromName::GET_POOLID_TXTCOLL, sal_True);
+ aUString = aName;
+
+ pData = new PropValData((void*)&aUString, SW_PROP_NAME_STR(UNO_NAME_HEADING_STYLE_NAME), ::getCppuType((const OUString*)0));
+ aPropertyValues.Insert(pData, aPropertyValues.Count());
+ }
+
+ uno::Sequence<beans::PropertyValue> aSeq(aPropertyValues.Count());
+ beans::PropertyValue* pArray = aSeq.getArray();
+
+ for(sal_uInt16 i = 0; i < aPropertyValues.Count(); i++)
+ {
+ pData = aPropertyValues.GetObject(i);
+ pArray[i].Value = pData->aVal;
+ pArray[i].Name = pData->sPropName;
+ pArray[i].Handle = -1;
+ }
+ aPropertyValues.DeleteAndDestroy(0, aPropertyValues.Count());
+ return aSeq;
+}
+
+PropValData* lcl_FindProperty(const char* cName, PropValDataArr& rPropertyValues)
+{
+ OUString sCmp = rtl::OUString::createFromAscii(cName);
+ for(sal_uInt16 i = 0; i < rPropertyValues.Count(); i++)
+ {
+ PropValData* pTemp = rPropertyValues.GetObject(i);
+ if(sCmp == pTemp->sPropName)
+ return pTemp;
+ }
+ return 0;
+}
+
+void SwXNumberingRules::SetNumberingRuleByIndex(
+ SwNumRule& rNumRule,
+ const uno::Sequence<beans::PropertyValue>& rProperties, sal_Int32 nIndex)
+ throw( uno::RuntimeException, lang::IllegalArgumentException )
+{
+ SolarMutexGuard aGuard;
+ DBG_ASSERT( 0 <= nIndex && nIndex < MAXLEVEL, "index out of range" );
+
+ // the order of the names is important!
+ static const char* aNumPropertyNames[] =
+ {
+ "Adjust", //0
+ "ParentNumbering", //1
+ "Prefix", //2
+ "Suffix", //3
+ "CharStyleName", //4
+ "StartWith", //5
+ SW_PROP_NAME_STR(UNO_NAME_LEFT_MARGIN), //6
+ SW_PROP_NAME_STR(UNO_NAME_SYMBOL_TEXT_DISTANCE), //7
+ SW_PROP_NAME_STR(UNO_NAME_FIRST_LINE_OFFSET), //8
+ SW_PROP_NAME_STR(UNO_NAME_POSITION_AND_SPACE_MODE), //9
+ SW_PROP_NAME_STR(UNO_NAME_LABEL_FOLLOWED_BY), //10
+ SW_PROP_NAME_STR(UNO_NAME_LISTTAB_STOP_POSITION), //11
+ SW_PROP_NAME_STR(UNO_NAME_FIRST_LINE_INDENT), //12
+ SW_PROP_NAME_STR(UNO_NAME_INDENT_AT), //13
+ "NumberingType", //14
+ "BulletId", //15
+ SW_PROP_NAME_STR(UNO_NAME_BULLET_FONT), //16
+ "BulletFontName", //17
+ "BulletChar", //18
+ SW_PROP_NAME_STR(UNO_NAME_GRAPHIC_URL), //19
+ SW_PROP_NAME_STR(UNO_NAME_GRAPHIC_BITMAP), //20
+ SW_PROP_NAME_STR(UNO_NAME_GRAPHIC_SIZE), //21
+ SW_PROP_NAME_STR(UNO_NAME_VERT_ORIENT), //22
+ SW_PROP_NAME_STR(UNO_NAME_HEADING_STYLE_NAME) //23
+ };
+ const sal_uInt16 nPropNameCount = 24;
+ const sal_uInt16 nNotInChapter = 15;
+
+ const beans::PropertyValue* pPropArray = rProperties.getConstArray();
+ PropValDataArr aPropertyValues;
+ sal_Bool bExcept = sal_False;
+ for(int i = 0; i < rProperties.getLength() && !bExcept; i++)
+ {
+ const beans::PropertyValue& rProp = pPropArray[i];
+ bExcept = sal_True;
+ for(sal_uInt16 j = 0; j < (pDocShell ? nPropNameCount : nPropNameCount - 1); j++)
+ {
+ //some values not in chapter numbering
+ if(pDocShell && j == nNotInChapter)
+ j = nPropNameCount - 1;
+ if(COMPARE_EQUAL == rProp.Name.compareToAscii(aNumPropertyNames[j]))
+ {
+ bExcept = sal_False;
+ break;
+ }
+ }
+ if(bExcept &&
+ (rProp.Name.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("BulletRelSize")) ||
+ rProp.Name.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("BulletColor")) ) )
+ {
+ bExcept = sal_False;
+ }
+ PropValData* pData = new PropValData(rProp.Value, rProp.Name );
+ aPropertyValues.Insert(pData, aPropertyValues.Count());
+ }
+
+ SwNumFmt aFmt(rNumRule.Get( (sal_uInt16)nIndex ));
+ sal_Bool bWrongArg = sal_False;
+ if(!bExcept)
+ {
+ SvxBrushItem* pSetBrush = 0;
+ Size* pSetSize = 0;
+ SwFmtVertOrient* pSetVOrient = 0;
+ sal_Bool bCharStyleNameSet = sal_False;
+
+ for(sal_uInt16 i = 0; i < nPropNameCount && !bExcept && !bWrongArg; i++)
+ {
+ PropValData* pData = lcl_FindProperty(aNumPropertyNames[i], aPropertyValues);
+ if(!pData)
+ continue;
+ switch(i)
+ {
+ case 0: //"Adjust"
+ {
+ sal_Int16 nValue = 0;
+ pData->aVal >>= nValue;
+ if(nValue > 0 &&
+ nValue <= text::HoriOrientation::LEFT &&
+ USHRT_MAX != aUnoToSvxAdjust[nValue])
+ {
+ aFmt.SetNumAdjust((SvxAdjust)aUnoToSvxAdjust[nValue]);
+ }
+ else
+ bWrongArg = sal_True;
+ }
+ break;
+ case 1: //"ParentNumbering",
+ {
+ sal_Int16 nSet = 0;
+ pData->aVal >>= nSet;
+ if(nSet >= 0 && MAXLEVEL >= nSet)
+ aFmt.SetIncludeUpperLevels( static_cast< sal_uInt8 >(nSet) );
+ }
+ break;
+ case 2: //"Prefix",
+ {
+ OUString uTmp;
+ pData->aVal >>= uTmp;
+ aFmt.SetPrefix(uTmp);
+ }
+ break;
+ case 3: //"Suffix",
+ {
+ OUString uTmp;
+ pData->aVal >>= uTmp;
+ aFmt.SetSuffix(uTmp);
+ }
+ break;
+ case 4: //"CharStyleName",
+ {
+ bCharStyleNameSet = sal_True;
+ OUString uTmp;
+ pData->aVal >>= uTmp;
+ String sCharFmtName;
+ SwStyleNameMapper::FillUIName( uTmp, sCharFmtName, nsSwGetPoolIdFromName::GET_POOLID_CHRFMT, sal_True );
+ if(sCharFmtName.EqualsAscii(SW_PROP_NAME_STR(UNO_NAME_CHARACTER_FORMAT_NONE)))
+ {
+ sNewCharStyleNames[(sal_uInt16)nIndex] = SwXNumberingRules::GetInvalidStyle();
+ aFmt.SetCharFmt(0);
+ }
+ else if(pDocShell || pDoc)
+ {
+ SwDoc* pLocalDoc = pDoc ? pDoc : pDocShell->GetDoc();
+ const SwCharFmts* pFmts = pLocalDoc->GetCharFmts();
+ sal_uInt16 nChCount = pFmts->Count();
+
+ SwCharFmt* pCharFmt = 0;
+ if(sCharFmtName.Len())
+ {
+ for(sal_uInt16 j = 0; j< nChCount; j++)
+ {
+ SwCharFmt* pTmp = (*pFmts)[j];
+ if(pTmp->GetName() == sCharFmtName)
+ {
+ pCharFmt = pTmp;
+ break;
+ }
+ }
+ if(!pCharFmt)
+ {
+
+ SfxStyleSheetBase* pBase;
+ SfxStyleSheetBasePool* pPool = pLocalDoc->GetDocShell()->GetStyleSheetPool();
+ pBase = ((SfxStyleSheetBasePool*)pPool)->Find(sCharFmtName, SFX_STYLE_FAMILY_CHAR);
+ if(!pBase)
+ pBase = &pPool->Make(sCharFmtName, SFX_STYLE_FAMILY_CHAR);
+ pCharFmt = ((SwDocStyleSheet*)pBase)->GetCharFmt();
+ }
+ }
+ aFmt.SetCharFmt( pCharFmt );
+ // #i51842#
+ // If the character format has been found it's name should not be in the
+ // char style names array
+ sNewCharStyleNames[(sal_uInt16)nIndex].Erase();
+ }
+ else
+ sNewCharStyleNames[(sal_uInt16)nIndex] = sCharFmtName;
+ }
+ break;
+ case 5: //"StartWith",
+ {
+ sal_Int16 nVal = 0;
+ pData->aVal >>= nVal;
+ aFmt.SetStart(nVal);
+ }
+ break;
+ case 6: //UNO_NAME_LEFT_MARGIN,
+ {
+ sal_Int32 nValue = 0;
+ pData->aVal >>= nValue;
+ // #i23727# nValue can be negative
+ aFmt.SetAbsLSpace((sal_uInt16) MM100_TO_TWIP(nValue));
+ }
+ break;
+ case 7: //UNO_NAME_SYMBOL_TEXT_DISTANCE,
+ {
+ sal_Int32 nValue = 0;
+ pData->aVal >>= nValue;
+ if(nValue >= 0)
+ aFmt.SetCharTextDistance((sal_uInt16) MM100_TO_TWIP(nValue));
+ else
+ bWrongArg = sal_True;
+ }
+ break;
+ case 8: //UNO_NAME_FIRST_LINE_OFFSET,
+ {
+ sal_Int32 nValue = 0;
+ pData->aVal >>= nValue;
+ // #i23727# nValue can be positive
+ nValue = MM100_TO_TWIP(nValue);
+ aFmt.SetFirstLineOffset((short)nValue);
+ }
+ break;
+ case 9: // UNO_NAME_POSITION_AND_SPACE_MODE
+ {
+ sal_Int16 nValue = 0;
+ pData->aVal >>= nValue;
+ if ( nValue == 0 )
+ {
+ aFmt.SetPositionAndSpaceMode( SvxNumberFormat::LABEL_WIDTH_AND_POSITION );
+ }
+ else if ( nValue == 1 )
+ {
+ aFmt.SetPositionAndSpaceMode( SvxNumberFormat::LABEL_ALIGNMENT );
+ }
+ else
+ {
+ bWrongArg = sal_True;
+ }
+ }
+ break;
+ case 10: // UNO_NAME_LABEL_FOLLOWED_BY
+ {
+ sal_Int16 nValue = 0;
+ pData->aVal >>= nValue;
+ if ( nValue == 0 )
+ {
+ aFmt.SetLabelFollowedBy( SvxNumberFormat::LISTTAB );
+ }
+ else if ( nValue == 1 )
+ {
+ aFmt.SetLabelFollowedBy( SvxNumberFormat::SPACE );
+ }
+ else if ( nValue == 2 )
+ {
+ aFmt.SetLabelFollowedBy( SvxNumberFormat::NOTHING );
+ }
+ else
+ {
+ bWrongArg = sal_True;
+ }
+ }
+ break;
+ case 11: // UNO_NAME_LISTTAB_STOP_POSITION
+ {
+ sal_Int32 nValue = 0;
+ pData->aVal >>= nValue;
+ nValue = MM100_TO_TWIP(nValue);
+ if ( nValue >= 0 )
+ {
+ aFmt.SetListtabPos( nValue );
+ }
+ else
+ {
+ bWrongArg = sal_True;
+ }
+ }
+ break;
+ case 12: // UNO_NAME_FIRST_LINE_INDENT
+ {
+ sal_Int32 nValue = 0;
+ pData->aVal >>= nValue;
+ nValue = MM100_TO_TWIP(nValue);
+ aFmt.SetFirstLineIndent( nValue );
+ }
+ break;
+ case 13: // UNO_NAME_INDENT_AT
+ {
+ sal_Int32 nValue = 0;
+ pData->aVal >>= nValue;
+ nValue = MM100_TO_TWIP(nValue);
+ aFmt.SetIndentAt( nValue );
+ }
+ break;
+ case 14: //"NumberingType"
+ {
+ sal_Int16 nSet = 0;
+ pData->aVal >>= nSet;
+ if(nSet >= 0)
+ aFmt.SetNumberingType(nSet);
+ else
+ bWrongArg = sal_True;
+ }
+ break;
+ case 15: //"BulletId",
+ {
+ sal_Int16 nSet = 0;
+ if( pData->aVal >>= nSet )
+ aFmt.SetBulletChar(nSet);
+ else
+ bWrongArg = sal_True;
+ }
+ break;
+ case 16: //UNO_NAME_BULLET_FONT,
+ {
+ awt::FontDescriptor* pDesc = (awt::FontDescriptor*)pData->aVal.getValue();
+ if(pDesc)
+ {
+ // #i93725#
+ // do not accept "empty" font
+ if ( pDesc->Name.getLength() > 0 )
+ {
+ Font aFont;
+ SvxUnoFontDescriptor::ConvertToFont( *pDesc, aFont );
+ aFmt.SetBulletFont(&aFont);
+ }
+ // <--
+ }
+ else
+ bWrongArg = sal_True;
+ }
+ break;
+ case 17: //"BulletFontName",
+ {
+ OUString uTmp;
+ pData->aVal >>= uTmp;
+ String sBulletFontName(uTmp);
+ SwDocShell* pLclDocShell = pDocShell ? pDocShell : pDoc ? pDoc->GetDocShell() : 0;
+ if( sBulletFontName.Len() && pLclDocShell )
+ {
+ const SvxFontListItem* pFontListItem =
+ (const SvxFontListItem* )pLclDocShell
+ ->GetItem( SID_ATTR_CHAR_FONTLIST );
+ const FontList* pList = pFontListItem->GetFontList();
+ FontInfo aInfo = pList->Get(
+ sBulletFontName, WEIGHT_NORMAL, ITALIC_NONE);
+ Font aFont(aInfo);
+ aFmt.SetBulletFont(&aFont);
+ }
+ else
+ sNewBulletFontNames[(sal_uInt16)nIndex] = sBulletFontName;
+ }
+ break;
+ case 18: //"BulletChar",
+ {
+ OUString aChar;
+ pData->aVal >>= aChar;
+ if(aChar.getLength() == 1)
+ {
+ aFmt.SetBulletChar(aChar.toChar());
+ }
+ else
+ bWrongArg = sal_True;
+ }
+ break;
+ case 19: //UNO_NAME_GRAPHIC_URL,
+ {
+ OUString sBrushURL;
+ pData->aVal >>= sBrushURL;
+ if(!pSetBrush)
+ {
+ const SvxBrushItem* pOrigBrush = aFmt.GetBrush();
+ if(pOrigBrush)
+ {
+ pSetBrush = new SvxBrushItem(*pOrigBrush);
+ }
+ else
+ pSetBrush = new SvxBrushItem(aEmptyStr, aEmptyStr, GPOS_AREA, RES_BACKGROUND);
+ }
+ pSetBrush->PutValue( pData->aVal, MID_GRAPHIC_URL );
+ }
+ break;
+ case 20: //UNO_NAME_GRAPHIC_BITMAP,
+ {
+ uno::Reference< awt::XBitmap >* pBitmap = (uno::Reference< awt::XBitmap > *)pData->aVal.getValue();
+ if(pBitmap)
+ {
+ if(!pSetBrush)
+ {
+ const SvxBrushItem* pOrigBrush = aFmt.GetBrush();
+ if(pOrigBrush)
+ {
+ pSetBrush = new SvxBrushItem(*pOrigBrush);
+ }
+ else
+ pSetBrush = new SvxBrushItem(aEmptyStr, aEmptyStr, GPOS_AREA, RES_BACKGROUND);
+ }
+
+ BitmapEx aBmp = VCLUnoHelper::GetBitmap( *pBitmap );
+ Graphic aNewGr(aBmp);
+ pSetBrush->SetGraphic( aNewGr );
+ }
+ else
+ bWrongArg = sal_True;
+ }
+ break;
+ case 21: //UNO_NAME_GRAPHIC_SIZE,
+ {
+ if(!pSetSize)
+ pSetSize = new Size;
+ if(pData->aVal.getValueType() == ::getCppuType((awt::Size*)0))
+ {
+ awt::Size* pSize = (awt::Size*)pData->aVal.getValue();
+ pSize->Width = MM100_TO_TWIP(pSize->Width);
+ pSize->Height = MM100_TO_TWIP(pSize->Height);
+ pSetSize->Width() = pSize->Width;
+ pSetSize->Height() = pSize->Height;
+ }
+ else
+ bWrongArg = sal_True;
+ }
+ break;
+ case 22: //VertOrient
+ {
+ if(!pSetVOrient)
+ {
+ if(aFmt.GetGraphicOrientation())
+ pSetVOrient = (SwFmtVertOrient*)aFmt.GetGraphicOrientation()->Clone();
+ else
+ pSetVOrient = new SwFmtVertOrient;
+ }
+ ((SfxPoolItem*)pSetVOrient)->PutValue(pData->aVal, MID_VERTORIENT_ORIENT);
+ }
+ break;
+ case 23: //"HeadingStyleName"
+ {
+ OUString uTmp;
+ pData->aVal >>= uTmp;
+ String sStyleName;
+ SwStyleNameMapper::FillUIName(uTmp, sStyleName, nsSwGetPoolIdFromName::GET_POOLID_TXTCOLL, sal_True );
+ const SwTxtFmtColls* pColls = pDocShell->GetDoc()->GetTxtFmtColls();
+ const sal_uInt16 nCount = pColls->Count();
+ for(sal_uInt16 k = 0; k < nCount; ++k)
+ {
+ SwTxtFmtColl &rTxtColl = *((*pColls)[k]);
+ if(rTxtColl.IsDefault())
+ continue;
+ if ( rTxtColl.IsAssignedToListLevelOfOutlineStyle() &&
+ rTxtColl.GetAssignedOutlineStyleLevel() == nIndex &&
+ rTxtColl.GetName() != sStyleName )
+ {
+ rTxtColl.DeleteAssignmentToListLevelOfOutlineStyle();
+ }
+ else if ( rTxtColl.GetName() == sStyleName )
+ {
+ rTxtColl.AssignToListLevelOfOutlineStyle( nIndex );
+ }
+ }
+ }
+ break;
+ case 24: // BulletRelSize - unsupported - only available in Impress
+ break;
+ }
+ }
+ if(!bExcept && !bWrongArg && (pSetBrush || pSetSize || pSetVOrient))
+ {
+ if(!pSetBrush && aFmt.GetBrush())
+ pSetBrush = new SvxBrushItem(*aFmt.GetBrush());
+
+ if(pSetBrush)
+ {
+ if(!pSetVOrient && aFmt.GetGraphicOrientation())
+ pSetVOrient = new SwFmtVertOrient(*aFmt.GetGraphicOrientation());
+
+ if(!pSetSize)
+ {
+ pSetSize = new Size(aFmt.GetGraphicSize());
+ if(!pSetSize->Width() || !pSetSize->Height())
+ {
+ const Graphic* pGraphic = pSetBrush->GetGraphic();
+ if(pGraphic)
+ *pSetSize = ::GetGraphicSizeTwip(*pGraphic, 0);
+ }
+ }
+ sal_Int16 eOrient = pSetVOrient ?
+ (sal_Int16)pSetVOrient->GetVertOrient() : text::VertOrientation::NONE;
+ aFmt.SetGraphicBrush( pSetBrush, pSetSize, text::VertOrientation::NONE == eOrient ? 0 : &eOrient );
+ }
+ }
+ if((!bCharStyleNameSet || !sNewCharStyleNames[(sal_uInt16)nIndex].Len()) &&
+ aFmt.GetNumberingType() == NumberingType::BITMAP && !aFmt.GetCharFmt()
+ && SwXNumberingRules::GetInvalidStyle() != sNewCharStyleNames[(sal_uInt16)nIndex])
+ {
+ SwStyleNameMapper::FillProgName ( RES_POOLCHR_BUL_LEVEL, sNewCharStyleNames[(sal_uInt16)nIndex] );
+ }
+ delete pSetBrush;
+ delete pSetSize;
+ delete pSetVOrient;
+ }
+ aPropertyValues.DeleteAndDestroy(0, aPropertyValues.Count());
+
+ if(bWrongArg)
+ throw lang::IllegalArgumentException();
+ else if(bExcept)
+ throw uno::RuntimeException();
+ rNumRule.Set( (sal_uInt16)nIndex, aFmt );
+
+}
+
+uno::Reference< XPropertySetInfo > SwXNumberingRules::getPropertySetInfo()
+ throw(RuntimeException)
+{
+ static uno::Reference< beans::XPropertySetInfo > aRef = m_pPropertySet->getPropertySetInfo();
+ return aRef;
+}
+
+void SwXNumberingRules::setPropertyValue( const OUString& rPropertyName, const Any& rValue )
+ throw(UnknownPropertyException, PropertyVetoException,
+ IllegalArgumentException, WrappedTargetException, RuntimeException)
+{
+ Any aRet;
+ SwNumRule* pDocRule = 0;
+ SwNumRule* pCreatedRule = 0;
+ if(!pNumRule)
+ {
+ if(!pNumRule && pDocShell)
+ {
+ pDocRule = new SwNumRule(*pDocShell->GetDoc()->GetOutlineNumRule());
+ }
+ else if(pDoc && sCreatedNumRuleName.Len())
+ {
+ pCreatedRule = pDoc->FindNumRulePtr( sCreatedNumRuleName);
+ }
+
+ }
+ if(!pNumRule && !pDocRule && !pCreatedRule)
+ throw RuntimeException();
+
+
+ if(rPropertyName.equalsAsciiL( SW_PROP_NAME(UNO_NAME_IS_AUTOMATIC)))
+ {
+ sal_Bool bVal = *(sal_Bool*)rValue.getValue();
+ if(!pCreatedRule)
+ pDocRule ? pDocRule->SetAutoRule(bVal) : pNumRule->SetAutoRule(bVal);
+ }
+ else if(rPropertyName.equalsAsciiL( SW_PROP_NAME(UNO_NAME_IS_CONTINUOUS_NUMBERING)))
+ {
+ sal_Bool bVal = *(sal_Bool*)rValue.getValue();
+ pDocRule ? pDocRule->SetContinusNum(bVal) :
+ pCreatedRule ? pCreatedRule->SetContinusNum(bVal) : pNumRule->SetContinusNum(bVal);
+ }
+ else if(rPropertyName.equalsAsciiL( SW_PROP_NAME(UNO_NAME_NAME)))
+ {
+ delete pDocRule;
+ throw IllegalArgumentException();
+ }
+ else if(rPropertyName.equalsAsciiL( SW_PROP_NAME(UNO_NAME_IS_ABSOLUTE_MARGINS)))
+ {
+ sal_Bool bVal = *(sal_Bool*)rValue.getValue();
+ pDocRule ? pDocRule->SetAbsSpaces(bVal) :
+ pCreatedRule ? pCreatedRule->SetAbsSpaces(bVal) : pNumRule->SetAbsSpaces(bVal);
+ }
+ else if(rPropertyName.equalsAsciiL( SW_PROP_NAME(UNO_NAME_NUMBERING_IS_OUTLINE)))
+ {
+ sal_Bool bVal = *(sal_Bool*)rValue.getValue();
+ SwNumRuleType eNumRuleType = bVal ? OUTLINE_RULE : NUM_RULE;
+ pDocRule ? pDocRule->SetRuleType(eNumRuleType) :
+ pCreatedRule ? pCreatedRule->SetRuleType(eNumRuleType) : pNumRule->SetRuleType(eNumRuleType);
+ }
+ else if(rPropertyName.equalsAsciiL( SW_PROP_NAME(UNO_NAME_DEFAULT_LIST_ID)))
+ {
+ delete pDocRule;
+ throw IllegalArgumentException();
+ }
+ else
+ throw UnknownPropertyException();
+
+ if(pDocRule)
+ {
+ pDocShell->GetDoc()->SetOutlineNumRule(*pDocRule);
+ delete pDocRule;
+ }
+ else if(pCreatedRule)
+ {
+ pCreatedRule->Validate();
+ }
+}
+
+Any SwXNumberingRules::getPropertyValue( const OUString& rPropertyName )
+ throw(UnknownPropertyException, WrappedTargetException, RuntimeException)
+{
+ Any aRet;
+ const SwNumRule* pRule = pNumRule;
+ if(!pRule && pDocShell)
+ pRule = pDocShell->GetDoc()->GetOutlineNumRule();
+ else if(pDoc && sCreatedNumRuleName.Len())
+ pRule = pDoc->FindNumRulePtr( sCreatedNumRuleName );
+ if(!pRule)
+ throw RuntimeException();
+
+ if(rPropertyName.equalsAsciiL( SW_PROP_NAME(UNO_NAME_IS_AUTOMATIC)))
+ {
+ sal_Bool bVal = pRule->IsAutoRule();
+ aRet.setValue(&bVal, ::getBooleanCppuType());
+ }
+ else if(rPropertyName.equalsAsciiL( SW_PROP_NAME(UNO_NAME_IS_CONTINUOUS_NUMBERING)))
+ {
+ sal_Bool bVal = pRule->IsContinusNum();
+ aRet.setValue(&bVal, ::getBooleanCppuType());
+ }
+ else if(rPropertyName.equalsAsciiL( SW_PROP_NAME(UNO_NAME_NAME)))
+ aRet <<= OUString(pRule->GetName());
+ else if(rPropertyName.equalsAsciiL( SW_PROP_NAME(UNO_NAME_IS_ABSOLUTE_MARGINS)))
+ {
+ sal_Bool bVal = pRule->IsAbsSpaces();
+ aRet.setValue(&bVal, ::getBooleanCppuType());
+ }
+ else if(rPropertyName.equalsAsciiL( SW_PROP_NAME(UNO_NAME_NUMBERING_IS_OUTLINE)))
+ {
+ sal_Bool bVal = pRule->IsOutlineRule();
+ aRet.setValue(&bVal, ::getBooleanCppuType());
+ }
+ else if(rPropertyName.equalsAsciiL( SW_PROP_NAME(UNO_NAME_DEFAULT_LIST_ID)))
+ {
+ OSL_ENSURE( pRule->GetDefaultListId().Len() != 0,
+ "<SwXNumberingRules::getPropertyValue(..)> - no default list id found. Serious defect -> please inform OD." );
+ aRet <<= OUString(pRule->GetDefaultListId());
+ }
+ else
+ throw UnknownPropertyException();
+ return aRet;
+}
+
+void SwXNumberingRules::addPropertyChangeListener(
+ const OUString& /*rPropertyName*/, const uno::Reference< XPropertyChangeListener >& /*xListener*/ )
+ throw(UnknownPropertyException, WrappedTargetException, RuntimeException)
+{
+}
+
+void SwXNumberingRules::removePropertyChangeListener(
+ const OUString& /*rPropertyName*/, const uno::Reference< XPropertyChangeListener >& /*xListener*/ )
+ throw(UnknownPropertyException, WrappedTargetException, RuntimeException)
+{
+}
+
+void SwXNumberingRules::addVetoableChangeListener(
+ const OUString& /*rPropertyName*/, const uno::Reference< XVetoableChangeListener >& /*xListener*/ )
+ throw(UnknownPropertyException, WrappedTargetException, RuntimeException)
+{
+}
+
+void SwXNumberingRules::removeVetoableChangeListener(
+ const OUString& /*rPropertyName*/, const uno::Reference< XVetoableChangeListener >& /*xListener*/ )
+ throw(UnknownPropertyException, WrappedTargetException, RuntimeException)
+{
+}
+
+OUString SwXNumberingRules::getName() throw( RuntimeException )
+{
+ String aString;
+ if(pNumRule)
+ {
+ SwStyleNameMapper::FillProgName(pNumRule->GetName(), aString, nsSwGetPoolIdFromName::GET_POOLID_NUMRULE, sal_True );
+ return OUString ( aString );
+ }
+ // consider chapter numbering <SwXNumberingRules>
+ else if ( pDocShell )
+ {
+ SwStyleNameMapper::FillProgName( pDocShell->GetDoc()->GetOutlineNumRule()->GetName(),
+ aString, nsSwGetPoolIdFromName::GET_POOLID_NUMRULE, sal_True );
+ return OUString ( aString );
+ }
+ // <--
+ else
+ return sCreatedNumRuleName;
+}
+
+void SwXNumberingRules::setName(const OUString& /*rName*/) throw( RuntimeException )
+{
+ RuntimeException aExcept;
+ aExcept.Message = C2U("readonly");
+ throw aExcept;
+}
+
+void SwXNumberingRules::Modify( const SfxPoolItem* pOld, const SfxPoolItem *pNew)
+{
+ ClientModify(this, pOld, pNew);
+ if(!GetRegisteredIn())
+ {
+ if(bOwnNumRuleCreated)
+ delete pNumRule;
+ pNumRule = 0;
+ pDoc = 0;
+ }
+}
+
+OUString SwXChapterNumbering::getImplementationName(void) throw( RuntimeException )
+{
+ return C2U("SwXChapterNumbering");
+}
+
+sal_Bool SwXChapterNumbering::supportsService(const OUString& rServiceName) throw( RuntimeException )
+{
+ String sServiceName(rServiceName);
+ return sServiceName.EqualsAscii("com.sun.star.text.ChapterNumbering") ||
+ sServiceName.EqualsAscii("com.sun.star.text.NumberingRules");
+}
+
+Sequence< OUString > SwXChapterNumbering::getSupportedServiceNames(void) throw( RuntimeException )
+{
+ Sequence< OUString > aRet(2);
+ OUString* pArray = aRet.getArray();
+ pArray[0] = C2U("com.sun.star.text.ChapterNumbering");
+ pArray[1] = C2U("com.sun.star.text.NumberingRules");
+ return aRet;
+}
+
+SwXChapterNumbering::SwXChapterNumbering(SwDocShell& rDocSh) :
+ SwXNumberingRules(rDocSh)
+{
+}
+
+SwXChapterNumbering::~SwXChapterNumbering()
+{
+}
+
+/******************************************************************
+ * SwXTextColumns
+ ******************************************************************/
+OUString SwXTextColumns::getImplementationName(void) throw( RuntimeException )
+{
+ return C2U("SwXTextColumns");
+}
+
+sal_Bool SwXTextColumns::supportsService(const OUString& rServiceName) throw( RuntimeException )
+{
+ return C2U("com.sun.star.text.TextColumns") == rServiceName;
+}
+
+Sequence< OUString > SwXTextColumns::getSupportedServiceNames(void) throw( RuntimeException )
+{
+ Sequence< OUString > aRet(1);
+ OUString* pArray = aRet.getArray();
+ pArray[0] = C2U("com.sun.star.text.TextColumns");
+ return aRet;
+}
+
+SwXTextColumns::SwXTextColumns(sal_uInt16 nColCount) :
+ nReference(0),
+ bIsAutomaticWidth(sal_True),
+ nAutoDistance(0),
+ m_pPropSet(aSwMapProvider.GetPropertySet(PROPERTY_MAP_TEXT_COLUMS)),
+ nSepLineWidth(0),
+ nSepLineColor(0), //black
+ nSepLineHeightRelative(100),//full height
+ nSepLineVertAlign(style::VerticalAlignment_MIDDLE),
+ bSepLineIsOn(sal_False),
+ nSepLineStyle(API_COL_LINE_NONE) // None
+{
+ if(nColCount)
+ setColumnCount(nColCount);
+}
+
+SwXTextColumns::SwXTextColumns(const SwFmtCol& rFmtCol) :
+ nReference(0),
+ aTextColumns(rFmtCol.GetNumCols()),
+ bIsAutomaticWidth(rFmtCol.IsOrtho()),
+ m_pPropSet(aSwMapProvider.GetPropertySet(PROPERTY_MAP_TEXT_COLUMS))
+{
+ sal_uInt16 nItemGutterWidth = rFmtCol.GetGutterWidth();
+ nAutoDistance = bIsAutomaticWidth ?
+ USHRT_MAX == nItemGutterWidth ? DEF_GUTTER_WIDTH : (sal_Int32)nItemGutterWidth
+ : 0;
+ nAutoDistance = TWIP_TO_MM100(nAutoDistance);
+
+ TextColumn* pColumns = aTextColumns.getArray();
+ const SwColumns& rCols = rFmtCol.GetColumns();
+ for(sal_uInt16 i = 0; i < aTextColumns.getLength(); i++)
+ {
+ SwColumn* pCol = rCols[i];
+
+ pColumns[i].Width = pCol->GetWishWidth();
+ nReference += pColumns[i].Width;
+ pColumns[i].LeftMargin = TWIP_TO_MM100_UNSIGNED(pCol->GetLeft ());
+ pColumns[i].RightMargin = TWIP_TO_MM100_UNSIGNED(pCol->GetRight());
+ }
+ if(!aTextColumns.getLength())
+ nReference = USHRT_MAX;
+
+ nSepLineWidth = rFmtCol.GetLineWidth();
+ nSepLineColor = rFmtCol.GetLineColor().GetColor();
+ nSepLineHeightRelative = rFmtCol.GetLineHeight();
+ bSepLineIsOn = rFmtCol.GetLineAdj() != COLADJ_NONE;
+ sal_Int8 nStyle = API_COL_LINE_NONE;
+ switch (rFmtCol.GetLineStyle())
+ {
+ case editeng::SOLID: nStyle = API_COL_LINE_SOLID; break;
+ case editeng::DOTTED: nStyle = API_COL_LINE_DOTTED; break;
+ case editeng::DASHED: nStyle = API_COL_LINE_DASHED; break;
+ default: break;
+ }
+ nSepLineStyle = nStyle;
+ switch(rFmtCol.GetLineAdj())
+ {
+ case COLADJ_TOP: nSepLineVertAlign = style::VerticalAlignment_TOP; break;
+ case COLADJ_BOTTOM: nSepLineVertAlign = style::VerticalAlignment_BOTTOM; break;
+ case COLADJ_CENTER:
+ case COLADJ_NONE: nSepLineVertAlign = style::VerticalAlignment_MIDDLE;
+ }
+}
+
+SwXTextColumns::~SwXTextColumns()
+{
+
+}
+
+sal_Int32 SwXTextColumns::getReferenceValue(void) throw( uno::RuntimeException )
+{
+ SolarMutexGuard aGuard;
+ return nReference;
+}
+
+sal_Int16 SwXTextColumns::getColumnCount(void) throw( uno::RuntimeException )
+{
+ SolarMutexGuard aGuard;
+ return static_cast< sal_Int16>( aTextColumns.getLength() );
+}
+
+void SwXTextColumns::setColumnCount(sal_Int16 nColumns) throw( uno::RuntimeException )
+{
+ SolarMutexGuard aGuard;
+ if(nColumns <= 0)
+ throw uno::RuntimeException();
+ bIsAutomaticWidth = sal_True;
+ aTextColumns.realloc(nColumns);
+ TextColumn* pCols = aTextColumns.getArray();
+ nReference = USHRT_MAX;
+ sal_Int32 nWidth = nReference / nColumns;
+ sal_Int32 nDiff = nReference - nWidth * nColumns;
+ sal_Int32 nDist = nAutoDistance / 2;
+ for(sal_Int16 i = 0; i < nColumns; i++)
+ {
+ pCols[i].Width = nWidth;
+ pCols[i].LeftMargin = i == 0 ? 0 : nDist;
+ pCols[i].RightMargin = i == nColumns - 1 ? 0 : nDist;
+ }
+ pCols[nColumns - 1].Width += nDiff;
+}
+
+uno::Sequence< TextColumn > SwXTextColumns::getColumns(void) throw( uno::RuntimeException )
+{
+ SolarMutexGuard aGuard;
+ return aTextColumns;
+}
+
+void SwXTextColumns::setColumns(const uno::Sequence< TextColumn >& rColumns)
+ throw( uno::RuntimeException )
+{
+ SolarMutexGuard aGuard;
+ sal_Int32 nReferenceTemp = 0;
+ const TextColumn* prCols = rColumns.getConstArray();
+ for(long i = 0; i < rColumns.getLength(); i++)
+ {
+ nReferenceTemp += prCols[i].Width;
+ }
+ bIsAutomaticWidth = sal_False;
+ nReference = !nReferenceTemp ? USHRT_MAX : nReferenceTemp;
+ aTextColumns = rColumns;
+}
+
+uno::Reference< XPropertySetInfo > SwXTextColumns::getPropertySetInfo( ) throw(RuntimeException)
+{
+ static uno::Reference< beans::XPropertySetInfo > aRef = m_pPropSet->getPropertySetInfo();
+ return aRef;
+}
+
+void SwXTextColumns::setPropertyValue( const OUString& rPropertyName, const Any& aValue )
+ throw(UnknownPropertyException, PropertyVetoException, IllegalArgumentException,
+ WrappedTargetException, RuntimeException)
+{
+ const SfxItemPropertySimpleEntry* pEntry = m_pPropSet->getPropertyMap()->getByName( rPropertyName );
+ if (!pEntry)
+ throw UnknownPropertyException(OUString ( RTL_CONSTASCII_USTRINGPARAM ( "Unknown property: " ) ) + rPropertyName, static_cast < cppu::OWeakObject * > ( this ) );
+ if ( pEntry->nFlags & PropertyAttribute::READONLY)
+ throw PropertyVetoException( OUString ( RTL_CONSTASCII_USTRINGPARAM ( "Property is read-only: " ) ) + rPropertyName, static_cast < cppu::OWeakObject * > ( this ) );
+
+ switch(pEntry->nWID)
+ {
+ case WID_TXTCOL_LINE_WIDTH:
+ {
+ sal_Int32 nTmp = 0;
+ aValue >>= nTmp;
+ if(nTmp < 0)
+ throw IllegalArgumentException();
+ nSepLineWidth = MM100_TO_TWIP(nTmp);
+ }
+ break;
+ case WID_TXTCOL_LINE_COLOR:
+ aValue >>= nSepLineColor;
+ break;
+ case WID_TXTCOL_LINE_STYLE:
+ {
+ aValue >>= nSepLineStyle;
+ }
+ break;
+ case WID_TXTCOL_LINE_REL_HGT:
+ {
+ sal_Int8 nTmp = 0;
+ aValue >>= nTmp;
+ if(nTmp < 0)
+ throw IllegalArgumentException();
+ nSepLineHeightRelative = nTmp;
+ }
+ break;
+ case WID_TXTCOL_LINE_ALIGN:
+ {
+ style::VerticalAlignment eAlign;
+ if(!(aValue >>= eAlign) )
+ {
+ sal_Int8 nTmp = 0;
+ if (! ( aValue >>= nTmp ) )
+ throw IllegalArgumentException();
+ else
+ nSepLineVertAlign = nTmp;
+ }
+ else
+ nSepLineVertAlign = static_cast< sal_Int8 >(eAlign);
+ }
+ break;
+ case WID_TXTCOL_LINE_IS_ON:
+ bSepLineIsOn = *(sal_Bool*)aValue.getValue();
+ break;
+ case WID_TXTCOL_AUTO_DISTANCE:
+ {
+ sal_Int32 nTmp = 0;
+ aValue >>= nTmp;
+ if(nTmp < 0 || nTmp >= nReference)
+ throw IllegalArgumentException();
+ nAutoDistance = nTmp;
+ sal_Int32 nColumns = aTextColumns.getLength();
+ TextColumn* pCols = aTextColumns.getArray();
+ sal_Int32 nDist = nAutoDistance / 2;
+ for(sal_Int32 i = 0; i < nColumns; i++)
+ {
+ pCols[i].LeftMargin = i == 0 ? 0 : nDist;
+ pCols[i].RightMargin = i == nColumns - 1 ? 0 : nDist;
+ }
+ }
+ break;
+ }
+}
+
+Any SwXTextColumns::getPropertyValue( const OUString& rPropertyName )
+ throw(UnknownPropertyException, WrappedTargetException, RuntimeException)
+{
+ const SfxItemPropertySimpleEntry* pEntry = m_pPropSet->getPropertyMap()->getByName( rPropertyName );
+ if (!pEntry)
+ throw UnknownPropertyException(OUString ( RTL_CONSTASCII_USTRINGPARAM ( "Unknown property: " ) ) + rPropertyName, static_cast < cppu::OWeakObject * > ( this ) );
+
+ Any aRet;
+ switch(pEntry->nWID)
+ {
+ case WID_TXTCOL_LINE_WIDTH:
+ aRet <<= static_cast < sal_Int32 >(TWIP_TO_MM100(nSepLineWidth));
+ break;
+ case WID_TXTCOL_LINE_COLOR:
+ aRet <<= nSepLineColor;
+ break;
+ case WID_TXTCOL_LINE_STYLE:
+ aRet <<= nSepLineStyle;
+ break;
+ case WID_TXTCOL_LINE_REL_HGT:
+ aRet <<= nSepLineHeightRelative;
+ break;
+ case WID_TXTCOL_LINE_ALIGN:
+ aRet <<= (style::VerticalAlignment)nSepLineVertAlign;
+ break;
+ case WID_TXTCOL_LINE_IS_ON:
+ aRet.setValue(&bSepLineIsOn, ::getBooleanCppuType());
+ break;
+ case WID_TXTCOL_IS_AUTOMATIC :
+ aRet.setValue(&bIsAutomaticWidth, ::getBooleanCppuType());
+ break;
+ case WID_TXTCOL_AUTO_DISTANCE:
+ aRet <<= nAutoDistance;
+ break;
+ }
+ return aRet;
+}
+
+void SwXTextColumns::addPropertyChangeListener(
+ const OUString& /*rPropertyName*/, const uno::Reference< XPropertyChangeListener >& /*xListener*/ )
+ throw(UnknownPropertyException, WrappedTargetException, RuntimeException)
+{
+}
+
+void SwXTextColumns::removePropertyChangeListener(
+ const OUString& /*rPropertyName*/, const uno::Reference< XPropertyChangeListener >& /*xListener*/ )
+ throw(UnknownPropertyException, WrappedTargetException, RuntimeException)
+{
+}
+
+void SwXTextColumns::addVetoableChangeListener(
+ const OUString& /*rPropertyName*/, const uno::Reference< XVetoableChangeListener >& /*xListener*/ )
+ throw(UnknownPropertyException, WrappedTargetException, RuntimeException)
+{
+}
+
+void SwXTextColumns::removeVetoableChangeListener(
+ const OUString& /*rPropertyName*/, const uno::Reference< XVetoableChangeListener >& /*xListener*/ )
+ throw(UnknownPropertyException, WrappedTargetException, RuntimeException)
+{
+}
+
+const uno::Sequence< sal_Int8 > & SwXTextColumns::getUnoTunnelId()
+{
+ static uno::Sequence< sal_Int8 > aSeq = ::CreateUnoTunnelId();
+ return aSeq;
+}
+
+sal_Int64 SAL_CALL SwXTextColumns::getSomething( const uno::Sequence< sal_Int8 >& rId )
+ throw(uno::RuntimeException)
+{
+ if( rId.getLength() == 16
+ && 0 == rtl_compareMemory( getUnoTunnelId().getConstArray(),
+ rId.getConstArray(), 16 ) )
+ {
+ return sal::static_int_cast< sal_Int64 >( reinterpret_cast< sal_IntPtr >(this) );
+ }
+ return 0;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/unocore/unosrch.cxx b/sw/source/core/unocore/unosrch.cxx
new file mode 100644
index 000000000000..5d531b17d899
--- /dev/null
+++ b/sw/source/core/unocore/unosrch.cxx
@@ -0,0 +1,746 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+#include "unosrch.hxx"
+#include <doc.hxx>
+#include <hints.hxx>
+#include <unomap.hxx>
+#include <unobaseclass.hxx>
+#include <unomid.h>
+
+#include <osl/mutex.hxx>
+#include <vcl/svapp.hxx>
+#include "editeng/unolingu.hxx"
+#include <com/sun/star/util/SearchOptions.hpp>
+#include <com/sun/star/util/SearchFlags.hpp>
+#include <com/sun/star/i18n/TransliterationModules.hpp>
+#include <com/sun/star/beans/PropertyAttribute.hpp>
+
+using namespace ::com::sun::star;
+using ::rtl::OUString;
+
+class SwSearchProperties_Impl
+{
+ beans::PropertyValue** pValueArr; //
+ sal_uInt32 nArrLen;
+ const PropertyEntryVector_t aPropertyEntries;
+public:
+ SwSearchProperties_Impl();
+ ~SwSearchProperties_Impl();
+
+ void SetProperties(const uno::Sequence< beans::PropertyValue >& aSearchAttribs)
+ throw( beans::UnknownPropertyException, lang::IllegalArgumentException, uno::RuntimeException );
+ const uno::Sequence< beans::PropertyValue > GetProperties() const;
+
+ void FillItemSet(SfxItemSet& rSet, sal_Bool bIsValueSearch) const;
+ sal_Bool HasAttributes() const;
+};
+
+SwSearchProperties_Impl::SwSearchProperties_Impl() :
+ nArrLen(0),
+ aPropertyEntries( aSwMapProvider.GetPropertySet(PROPERTY_MAP_TEXT_CURSOR)->getPropertyMap()->getPropertyEntries())
+{
+ nArrLen = aPropertyEntries.size();
+ pValueArr = new beans::PropertyValue*[nArrLen];
+ for(sal_uInt32 i = 0; i < nArrLen; i++)
+ pValueArr[i] = 0;
+}
+
+SwSearchProperties_Impl::~SwSearchProperties_Impl()
+{
+ for(sal_uInt32 i = 0; i < nArrLen; i++)
+ delete pValueArr[i];
+ delete[] pValueArr;
+}
+
+void SwSearchProperties_Impl::SetProperties(const uno::Sequence< beans::PropertyValue >& aSearchAttribs)
+ throw( beans::UnknownPropertyException, lang::IllegalArgumentException, uno::RuntimeException )
+{
+ const beans::PropertyValue* pProps = aSearchAttribs.getConstArray();
+ sal_uInt32 i;
+
+ //delete all existing values
+ for( i = 0; i < nArrLen; i++)
+ {
+ delete pValueArr[i];
+ pValueArr[i] = 0;
+ }
+
+ sal_uInt32 nLen = aSearchAttribs.getLength();
+ for(i = 0; i < nLen; i++)
+ {
+ sal_uInt16 nIndex = 0;
+ PropertyEntryVector_t::const_iterator aIt = aPropertyEntries.begin();
+ while(pProps[i].Name != aIt->sName)
+ {
+ ++aIt;
+ nIndex++;
+ if( aIt == aPropertyEntries.end() )
+ throw beans::UnknownPropertyException();
+ }
+ pValueArr[nIndex] = new beans::PropertyValue(pProps[i]);
+ }
+}
+
+const uno::Sequence< beans::PropertyValue > SwSearchProperties_Impl::GetProperties() const
+{
+ sal_uInt32 nPropCount = 0;
+ sal_uInt32 i;
+ for( i = 0; i < nArrLen; i++)
+ if(pValueArr[i])
+ nPropCount++;
+
+ uno::Sequence< beans::PropertyValue > aRet(nPropCount);
+ beans::PropertyValue* pProps = aRet.getArray();
+ nPropCount = 0;
+ for(i = 0; i < nArrLen; i++)
+ {
+ if(pValueArr[i])
+ {
+ pProps[nPropCount++] = *(pValueArr[i]);
+ }
+ }
+ return aRet;
+}
+
+void SwSearchProperties_Impl::FillItemSet(SfxItemSet& rSet, sal_Bool bIsValueSearch) const
+{
+ //
+
+ SfxPoolItem* pBoxItem = 0,
+ *pBreakItem = 0,
+ *pAutoKernItem = 0,
+ *pWLineItem = 0,
+ *pTabItem = 0,
+ *pSplitItem = 0,
+ *pRegItem = 0,
+ *pLineSpaceItem = 0,
+ *pLineNumItem = 0,
+ *pKeepItem = 0,
+ *pLRItem = 0,
+ *pULItem = 0,
+ *pBackItem = 0,
+ *pAdjItem = 0,
+ *pDescItem = 0,
+ *pInetItem = 0,
+ *pDropItem = 0,
+ *pWeightItem = 0,
+ *pULineItem = 0,
+ *pOLineItem = 0,
+ *pCharFmtItem = 0,
+ *pShadItem = 0,
+ *pPostItem = 0,
+ *pNHyphItem = 0,
+ *pLangItem = 0,
+ *pKernItem = 0,
+ *pFontSizeItem = 0,
+ *pFontItem = 0,
+ *pBlinkItem = 0,
+ *pEscItem = 0,
+ *pCrossedOutItem = 0,
+ *pContourItem = 0,
+ *pCharColorItem = 0,
+ *pCasemapItem = 0,
+ *pBrushItem = 0,
+ *pFontCJKItem = 0,
+ *pFontSizeCJKItem = 0,
+ *pCJKLangItem = 0,
+ *pCJKPostureItem = 0,
+ *pCJKWeightItem = 0,
+ *pFontCTLItem = 0,
+ *pFontSizeCTLItem = 0,
+ *pCTLLangItem = 0,
+ *pCTLPostureItem = 0,
+ *pCTLWeightItem = 0;
+
+ PropertyEntryVector_t::const_iterator aIt = aPropertyEntries.begin();
+ for(sal_uInt32 i = 0; i < nArrLen; i++, ++aIt)
+ {
+ if(pValueArr[i])
+ {
+ SfxPoolItem* pTempItem = 0;
+ switch(aIt->nWID)
+ {
+ case RES_BOX:
+ if(!pBoxItem)
+ pBoxItem = rSet.GetPool()->GetDefaultItem(aIt->nWID).Clone();
+ pTempItem = pBoxItem;
+ break;
+ case RES_BREAK:
+ if(!pBreakItem)
+ pBreakItem = rSet.GetPool()->GetDefaultItem(aIt->nWID).Clone();
+ pTempItem = pBreakItem;
+ break;
+ case RES_CHRATR_AUTOKERN:
+ if(!pAutoKernItem)
+ pAutoKernItem = rSet.GetPool()->GetDefaultItem(aIt->nWID).Clone();
+ pTempItem = pAutoKernItem;
+ break;
+ case RES_CHRATR_BACKGROUND:
+ if(!pBrushItem)
+ pBrushItem = rSet.GetPool()->GetDefaultItem(aIt->nWID).Clone();
+ pTempItem = pBrushItem;
+ break;
+ case RES_CHRATR_CASEMAP:
+ if(!pCasemapItem)
+ pCasemapItem = rSet.GetPool()->GetDefaultItem(aIt->nWID).Clone();
+ pTempItem = pCasemapItem;
+ break;
+ case RES_CHRATR_COLOR:
+ if(!pCharColorItem)
+ pCharColorItem = rSet.GetPool()->GetDefaultItem(aIt->nWID).Clone();
+ pTempItem = pCharColorItem;
+ break;
+ case RES_CHRATR_CONTOUR:
+ if(!pContourItem)
+ pContourItem = rSet.GetPool()->GetDefaultItem(aIt->nWID).Clone();
+ pTempItem = pContourItem;
+ break;
+ case RES_CHRATR_CROSSEDOUT:
+ if(!pCrossedOutItem)
+ pCrossedOutItem = rSet.GetPool()->GetDefaultItem(aIt->nWID).Clone();
+ pTempItem = pCrossedOutItem;
+ break;
+ case RES_CHRATR_ESCAPEMENT:
+ if(!pEscItem)
+ pEscItem = rSet.GetPool()->GetDefaultItem(aIt->nWID).Clone();
+ pTempItem = pEscItem;
+ break;
+ case RES_CHRATR_BLINK:
+ if(!pBlinkItem)
+ pBlinkItem = rSet.GetPool()->GetDefaultItem(aIt->nWID).Clone();
+ pTempItem = pBlinkItem;
+ break;
+ case RES_CHRATR_FONT:
+ if(!pFontItem)
+ pFontItem = rSet.GetPool()->GetDefaultItem(aIt->nWID).Clone();
+ pTempItem = pFontItem;
+ break;
+ case RES_CHRATR_FONTSIZE:
+ if(!pFontSizeItem)
+ pFontSizeItem = rSet.GetPool()->GetDefaultItem(aIt->nWID).Clone();
+ pTempItem = pFontSizeItem;
+ break;
+ case RES_CHRATR_KERNING:
+ if(!pKernItem)
+ pKernItem = rSet.GetPool()->GetDefaultItem(aIt->nWID).Clone();
+ pTempItem = pKernItem;
+ break;
+ case RES_CHRATR_LANGUAGE:
+ if(!pLangItem)
+ pLangItem = rSet.GetPool()->GetDefaultItem(aIt->nWID).Clone();
+ pTempItem = pLangItem;
+ break;
+ case RES_CHRATR_NOHYPHEN:
+ if(!pNHyphItem)
+ pNHyphItem = rSet.GetPool()->GetDefaultItem(aIt->nWID).Clone();
+ pTempItem = pNHyphItem;
+ break;
+ case RES_CHRATR_POSTURE:
+ if(!pPostItem)
+ pPostItem = rSet.GetPool()->GetDefaultItem(aIt->nWID).Clone();
+ pTempItem = pPostItem;
+ break;
+ case RES_CHRATR_SHADOWED:
+ if(!pShadItem)
+ pShadItem = rSet.GetPool()->GetDefaultItem(aIt->nWID).Clone();
+ pTempItem = pShadItem;
+ break;
+ case RES_TXTATR_CHARFMT:
+ if(!pCharFmtItem)
+ pCharFmtItem = rSet.GetPool()->GetDefaultItem(aIt->nWID).Clone();
+ pTempItem = pCharFmtItem;
+ break;
+ case RES_CHRATR_UNDERLINE:
+ if(!pULineItem)
+ pULineItem = rSet.GetPool()->GetDefaultItem(aIt->nWID).Clone();
+ pTempItem = pULineItem;
+ break;
+ case RES_CHRATR_OVERLINE:
+ if(!pOLineItem)
+ pOLineItem = rSet.GetPool()->GetDefaultItem(aIt->nWID).Clone();
+ pTempItem = pOLineItem;
+ break;
+ case RES_CHRATR_WEIGHT:
+ if(!pWeightItem)
+ pWeightItem = rSet.GetPool()->GetDefaultItem(aIt->nWID).Clone();
+ pTempItem = pWeightItem;
+ break;
+ case RES_PARATR_DROP:
+ if(!pDropItem)
+ pDropItem = rSet.GetPool()->GetDefaultItem(aIt->nWID).Clone();
+ pTempItem = pDropItem;
+ break;
+ case RES_TXTATR_INETFMT:
+ if(!pInetItem)
+ pInetItem = rSet.GetPool()->GetDefaultItem(aIt->nWID).Clone();
+ pTempItem = pInetItem;
+ break;
+ case RES_PAGEDESC:
+ if(!pDescItem)
+ pDescItem = rSet.GetPool()->GetDefaultItem(aIt->nWID).Clone();
+ pTempItem = pDescItem;
+ break;
+ case RES_PARATR_ADJUST:
+ if(!pAdjItem)
+ pAdjItem = rSet.GetPool()->GetDefaultItem(aIt->nWID).Clone();
+ pTempItem = pAdjItem;
+ break;
+ case RES_BACKGROUND:
+ if(!pBackItem)
+ pBackItem = rSet.GetPool()->GetDefaultItem(aIt->nWID).Clone();
+ pTempItem = pBackItem;
+ break;
+ case RES_UL_SPACE:
+ if(!pULItem)
+ pULItem = rSet.GetPool()->GetDefaultItem(aIt->nWID).Clone();
+ pTempItem = pULItem;
+ break;
+ case RES_LR_SPACE:
+ if(!pLRItem)
+ pLRItem = rSet.GetPool()->GetDefaultItem(aIt->nWID).Clone();
+ pTempItem = pLRItem;
+ break;
+ case RES_KEEP:
+ if(!pKeepItem)
+ pKeepItem = rSet.GetPool()->GetDefaultItem(aIt->nWID).Clone();
+ pTempItem = pKeepItem;
+ break;
+ case RES_LINENUMBER:
+ if(!pLineNumItem)
+ pLineNumItem = rSet.GetPool()->GetDefaultItem(aIt->nWID).Clone();
+ pTempItem = pLineNumItem;
+ break;
+ case RES_PARATR_LINESPACING:
+ if(!pLineSpaceItem)
+ pLineSpaceItem = rSet.GetPool()->GetDefaultItem(aIt->nWID).Clone();
+ pTempItem = pLineSpaceItem;
+ break;
+ case RES_PARATR_REGISTER:
+ if(!pRegItem)
+ pRegItem = rSet.GetPool()->GetDefaultItem(aIt->nWID).Clone();
+ pTempItem = pRegItem;
+ break;
+ case RES_PARATR_SPLIT:
+ if(!pSplitItem)
+ pSplitItem = rSet.GetPool()->GetDefaultItem(aIt->nWID).Clone();
+ pTempItem = pSplitItem;
+ break;
+ case RES_PARATR_TABSTOP:
+ if(!pTabItem)
+ pTabItem = rSet.GetPool()->GetDefaultItem(aIt->nWID).Clone();
+ pTempItem = pTabItem;
+ break;
+ case RES_CHRATR_WORDLINEMODE:
+ if(!pWLineItem)
+ pWLineItem = rSet.GetPool()->GetDefaultItem(aIt->nWID).Clone();
+ pTempItem = pWLineItem;
+ break;
+ case RES_CHRATR_CJK_FONT:
+ if(!pFontCJKItem )
+ pFontCJKItem = rSet.GetPool()->GetDefaultItem(aIt->nWID).Clone();
+ pTempItem = pFontCJKItem;
+ break;
+ case RES_CHRATR_CJK_FONTSIZE:
+ if(!pFontSizeCJKItem )
+ pFontSizeCJKItem = rSet.GetPool()->GetDefaultItem(aIt->nWID).Clone();
+ pTempItem = pFontSizeCJKItem;
+ break;
+ case RES_CHRATR_CJK_LANGUAGE:
+ if(!pCJKLangItem )
+ pCJKLangItem = rSet.GetPool()->GetDefaultItem(aIt->nWID).Clone();
+ pTempItem = pCJKLangItem;
+ break;
+ case RES_CHRATR_CJK_POSTURE:
+ if(!pCJKPostureItem )
+ pCJKPostureItem = rSet.GetPool()->GetDefaultItem(aIt->nWID).Clone();
+ pTempItem = pCJKPostureItem;
+ break;
+ case RES_CHRATR_CJK_WEIGHT:
+ if(!pCJKWeightItem )
+ pCJKWeightItem = rSet.GetPool()->GetDefaultItem(aIt->nWID).Clone();
+ pTempItem = pCJKWeightItem;
+ break;
+ case RES_CHRATR_CTL_FONT:
+ if(!pFontCTLItem )
+ pFontCTLItem = rSet.GetPool()->GetDefaultItem(aIt->nWID).Clone();
+ pTempItem = pFontCTLItem;
+ break;
+ case RES_CHRATR_CTL_FONTSIZE:
+ if(!pFontSizeCTLItem )
+ pFontSizeCTLItem = rSet.GetPool()->GetDefaultItem(aIt->nWID).Clone();
+ pTempItem = pFontSizeCTLItem;
+ break;
+ case RES_CHRATR_CTL_LANGUAGE:
+ if(!pCTLLangItem )
+ pCTLLangItem = rSet.GetPool()->GetDefaultItem(aIt->nWID).Clone();
+ pTempItem = pCTLLangItem;
+ break;
+ case RES_CHRATR_CTL_POSTURE:
+ if(!pCTLPostureItem )
+ pCTLPostureItem = rSet.GetPool()->GetDefaultItem(aIt->nWID).Clone();
+ pTempItem = pCTLPostureItem;
+ break;
+ case RES_CHRATR_CTL_WEIGHT:
+ if(!pCTLWeightItem )
+ pCTLWeightItem = rSet.GetPool()->GetDefaultItem(aIt->nWID).Clone();
+ pTempItem = pCTLWeightItem;
+ break;
+ }
+ if(pTempItem)
+ {
+ if(bIsValueSearch)
+ {
+ pTempItem->PutValue(pValueArr[i]->Value, aIt->nMemberId);
+ rSet.Put(*pTempItem);
+ }
+ else
+ rSet.InvalidateItem( pTempItem->Which() );
+ }
+ }
+ }
+ delete pBoxItem;
+ delete pBreakItem;
+ delete pBreakItem ;
+ delete pAutoKernItem ;
+ delete pWLineItem;
+ delete pTabItem;
+ delete pSplitItem;
+ delete pRegItem;
+ delete pLineSpaceItem ;
+ delete pLineNumItem ;
+ delete pKeepItem;
+ delete pLRItem ;
+ delete pULItem ;
+ delete pBackItem;
+ delete pAdjItem;
+ delete pDescItem;
+ delete pInetItem;
+ delete pDropItem;
+ delete pWeightItem;
+ delete pULineItem;
+ delete pOLineItem;
+ delete pCharFmtItem ;
+ delete pShadItem;
+ delete pPostItem;
+ delete pNHyphItem;
+ delete pLangItem;
+ delete pKernItem;
+ delete pFontSizeItem ;
+ delete pFontItem;
+ delete pBlinkItem;
+ delete pEscItem;
+ delete pCrossedOutItem;
+ delete pContourItem ;
+ delete pCharColorItem;
+ delete pCasemapItem ;
+ delete pBrushItem ;
+}
+
+sal_Bool SwSearchProperties_Impl::HasAttributes() const
+{
+ for(sal_uInt32 i = 0; i < nArrLen; i++)
+ if(pValueArr[i])
+ return sal_True;
+ return sal_False;
+}
+
+SwXTextSearch::SwXTextSearch() :
+ pSearchProperties( new SwSearchProperties_Impl),
+ pReplaceProperties( new SwSearchProperties_Impl),
+ m_pPropSet(aSwMapProvider.GetPropertySet(PROPERTY_MAP_TEXT_SEARCH)),
+ bAll(sal_False),
+ bWord(sal_False),
+ bBack(sal_False),
+ bExpr(sal_False),
+ bCase(sal_False),
+ bStyles(sal_False),
+ bSimilarity(sal_False),
+ bLevRelax(sal_False),
+ nLevExchange(2),
+ nLevAdd(2),
+ nLevRemove(2),
+ bIsValueSearch(sal_True)
+{
+}
+
+SwXTextSearch::~SwXTextSearch()
+{
+ delete pSearchProperties;
+ delete pReplaceProperties;
+}
+
+const uno::Sequence< sal_Int8 > & SwXTextSearch::getUnoTunnelId()
+{
+ static uno::Sequence< sal_Int8 > aSeq = ::CreateUnoTunnelId();
+ return aSeq;
+}
+
+sal_Int64 SAL_CALL SwXTextSearch::getSomething( const uno::Sequence< sal_Int8 >& rId )
+ throw(uno::RuntimeException)
+{
+ if( rId.getLength() == 16
+ && 0 == rtl_compareMemory( getUnoTunnelId().getConstArray(),
+ rId.getConstArray(), 16 ) )
+ {
+ return sal::static_int_cast< sal_Int64 >( reinterpret_cast< sal_IntPtr >(this) );
+ }
+ return 0;
+}
+
+OUString SwXTextSearch::getSearchString(void) throw( uno::RuntimeException )
+{
+ SolarMutexGuard aGuard;
+ return sSearchText;
+}
+
+void SwXTextSearch::setSearchString(const OUString& rString)
+ throw( uno::RuntimeException )
+{
+ SolarMutexGuard aGuard;
+ sSearchText = String(rString);
+}
+
+OUString SwXTextSearch::getReplaceString(void) throw( uno::RuntimeException )
+{
+ SolarMutexGuard aGuard;
+ return sReplaceText;
+}
+
+void SwXTextSearch::setReplaceString(const OUString& rReplaceString) throw( uno::RuntimeException )
+{
+ SolarMutexGuard aGuard;
+ sReplaceText = String(rReplaceString);
+}
+
+uno::Reference< beans::XPropertySetInfo > SwXTextSearch::getPropertySetInfo(void) throw( uno::RuntimeException )
+{
+ static uno::Reference< beans::XPropertySetInfo > aRef = m_pPropSet->getPropertySetInfo();
+ return aRef;
+}
+
+void SwXTextSearch::setPropertyValue(const OUString& rPropertyName, const uno::Any& aValue)
+ throw( beans::UnknownPropertyException, beans::PropertyVetoException,
+ lang::IllegalArgumentException, lang::WrappedTargetException, uno::RuntimeException )
+{
+ SolarMutexGuard aGuard;
+ const SfxItemPropertySimpleEntry* pEntry = m_pPropSet->getPropertyMap()->getByName(rPropertyName);
+ if(pEntry)
+ {
+ if ( pEntry->nFlags & beans::PropertyAttribute::READONLY)
+ throw beans::PropertyVetoException ( OUString ( RTL_CONSTASCII_USTRINGPARAM ( "Property is read-only: " ) ) + rPropertyName, static_cast < cppu::OWeakObject * > ( this ) );
+ sal_Bool bVal = sal_False;
+ if(aValue.getValueType() == ::getBooleanCppuType())
+ bVal = *(sal_Bool*)aValue.getValue();
+ switch(pEntry->nWID)
+ {
+ case WID_SEARCH_ALL : bAll = bVal; break;
+ case WID_WORDS: bWord = bVal; break;
+ case WID_BACKWARDS : bBack = bVal; break;
+ case WID_REGULAR_EXPRESSION : bExpr = bVal; break;
+ case WID_CASE_SENSITIVE : bCase = bVal; break;
+ //case WID_IN_SELECTION : bInSel = bVal; break;
+ case WID_STYLES : bStyles = bVal; break;
+ case WID_SIMILARITY : bSimilarity = bVal; break;
+ case WID_SIMILARITY_RELAX: bLevRelax = bVal; break;
+ case WID_SIMILARITY_EXCHANGE: aValue >>= nLevExchange; break;
+ case WID_SIMILARITY_ADD: aValue >>= nLevAdd; break;
+ case WID_SIMILARITY_REMOVE : aValue >>= nLevRemove;break;
+ };
+ }
+ else
+ throw beans::UnknownPropertyException(OUString ( RTL_CONSTASCII_USTRINGPARAM ( "Unknown property: " ) ) + rPropertyName, static_cast < cppu::OWeakObject * > ( this ) );
+}
+
+uno::Any SwXTextSearch::getPropertyValue(const OUString& rPropertyName) throw( beans::UnknownPropertyException, lang::WrappedTargetException, uno::RuntimeException )
+{
+ SolarMutexGuard aGuard;
+ uno::Any aRet;
+
+ const SfxItemPropertySimpleEntry* pEntry = m_pPropSet->getPropertyMap()->getByName(rPropertyName);
+ sal_Bool bSet = sal_False;
+ if(pEntry)
+ {
+ sal_Int16 nSet = 0;
+ switch(pEntry->nWID)
+ {
+ case WID_SEARCH_ALL : bSet = bAll; goto SET_BOOL;
+ case WID_WORDS: bSet = bWord; goto SET_BOOL;
+ case WID_BACKWARDS : bSet = bBack; goto SET_BOOL;
+ case WID_REGULAR_EXPRESSION : bSet = bExpr; goto SET_BOOL;
+ case WID_CASE_SENSITIVE : bSet = bCase; goto SET_BOOL;
+ //case WID_IN_SELECTION : bSet = bInSel; goto SET_BOOL;
+ case WID_STYLES : bSet = bStyles; goto SET_BOOL;
+ case WID_SIMILARITY : bSet = bSimilarity; goto SET_BOOL;
+ case WID_SIMILARITY_RELAX: bSet = bLevRelax;
+SET_BOOL:
+ aRet.setValue(&bSet, ::getBooleanCppuType());
+ break;
+ case WID_SIMILARITY_EXCHANGE: nSet = nLevExchange; goto SET_UINT16;
+ case WID_SIMILARITY_ADD: nSet = nLevAdd; goto SET_UINT16;
+ case WID_SIMILARITY_REMOVE : nSet = nLevRemove;
+SET_UINT16:
+ aRet <<= nSet;
+ break;
+ };
+ }
+ else
+ throw beans::UnknownPropertyException(OUString ( RTL_CONSTASCII_USTRINGPARAM ( "Unknown property: " ) ) + rPropertyName, static_cast < cppu::OWeakObject * > ( this ) );
+ return aRet;
+}
+
+void SwXTextSearch::addPropertyChangeListener(const OUString& /*rPropertyName*/, const uno::Reference< beans::XPropertyChangeListener > & /*xListener*/) throw(beans::UnknownPropertyException, lang::WrappedTargetException, uno::RuntimeException )
+{
+ DBG_WARNING("not implemented");
+}
+
+void SwXTextSearch::removePropertyChangeListener(const OUString& /*rPropertyName*/, const uno::Reference< beans::XPropertyChangeListener > & /*xListener*/) throw(beans::UnknownPropertyException, lang::WrappedTargetException,uno::RuntimeException )
+{
+ DBG_WARNING("not implemented");
+}
+
+void SwXTextSearch::addVetoableChangeListener(const OUString& /*rPropertyName*/, const uno::Reference< beans::XVetoableChangeListener > & /*xListener*/) throw(beans::UnknownPropertyException, lang::WrappedTargetException,uno::RuntimeException )
+{
+ DBG_WARNING("not implemented");
+}
+
+void SwXTextSearch::removeVetoableChangeListener(const OUString& /*rPropertyName*/, const uno::Reference< beans::XVetoableChangeListener > & /*xListener*/) throw(beans::UnknownPropertyException, lang::WrappedTargetException,uno::RuntimeException )
+{
+ DBG_WARNING("not implemented");
+}
+
+sal_Bool SwXTextSearch::getValueSearch(void) throw( uno::RuntimeException )
+{
+ SolarMutexGuard aGuard;
+ return bIsValueSearch;
+}
+
+void SwXTextSearch::setValueSearch(sal_Bool ValueSearch_) throw( uno::RuntimeException )
+{
+ SolarMutexGuard aGuard;
+ bIsValueSearch = ValueSearch_;
+}
+
+uno::Sequence< beans::PropertyValue > SwXTextSearch::getSearchAttributes(void) throw( uno::RuntimeException )
+{
+ return pSearchProperties->GetProperties();
+}
+
+void SwXTextSearch::setSearchAttributes(const uno::Sequence< beans::PropertyValue >& rSearchAttribs)
+ throw( beans::UnknownPropertyException, lang::IllegalArgumentException, uno::RuntimeException )
+{
+ pSearchProperties->SetProperties(rSearchAttribs);
+}
+
+uno::Sequence< beans::PropertyValue > SwXTextSearch::getReplaceAttributes(void)
+ throw( uno::RuntimeException )
+{
+ return pReplaceProperties->GetProperties();
+}
+
+void SwXTextSearch::setReplaceAttributes(const uno::Sequence< beans::PropertyValue >& rReplaceAttribs)
+ throw( beans::UnknownPropertyException, lang::IllegalArgumentException, uno::RuntimeException )
+{
+ pReplaceProperties->SetProperties(rReplaceAttribs);
+}
+
+void SwXTextSearch::FillSearchItemSet(SfxItemSet& rSet) const
+{
+ pSearchProperties->FillItemSet(rSet, bIsValueSearch);
+}
+
+void SwXTextSearch::FillReplaceItemSet(SfxItemSet& rSet) const
+{
+ pReplaceProperties->FillItemSet(rSet, bIsValueSearch);
+}
+
+sal_Bool SwXTextSearch::HasSearchAttributes() const
+{
+ return pSearchProperties->HasAttributes();
+}
+
+sal_Bool SwXTextSearch::HasReplaceAttributes() const
+{
+ return pReplaceProperties->HasAttributes();
+}
+
+OUString SwXTextSearch::getImplementationName(void) throw( uno::RuntimeException )
+{
+ return C2U("SwXTextSearch");
+}
+
+sal_Bool SwXTextSearch::supportsService(const OUString& rServiceName) throw( uno::RuntimeException )
+{
+ return C2U("com.sun.star.util.SearchDescriptor") == rServiceName ||
+ C2U("com.sun.star.util.ReplaceDescriptor") == rServiceName;
+}
+
+uno::Sequence< OUString > SwXTextSearch::getSupportedServiceNames(void) throw( uno::RuntimeException )
+{
+ uno::Sequence< OUString > aRet(2);
+ OUString* pArray = aRet.getArray();
+ pArray[0] = C2U("com.sun.star.util.SearchDescriptor");
+ pArray[1] = C2U("com.sun.star.util.ReplaceDescriptor");
+ return aRet;
+}
+
+void SwXTextSearch::FillSearchOptions( util::SearchOptions& rSearchOpt ) const
+{
+ if( bSimilarity )
+ {
+ rSearchOpt.algorithmType = util::SearchAlgorithms_APPROXIMATE;
+ rSearchOpt.changedChars = nLevExchange;
+ rSearchOpt.deletedChars = nLevRemove;
+ rSearchOpt.insertedChars = nLevAdd;
+ if( bLevRelax )
+ rSearchOpt.searchFlag |= util::SearchFlags::LEV_RELAXED;
+ }
+ else if( bExpr )
+ rSearchOpt.algorithmType = util::SearchAlgorithms_REGEXP;
+ else
+ rSearchOpt.algorithmType = util::SearchAlgorithms_ABSOLUTE;
+
+ rSearchOpt.Locale = SvxCreateLocale( GetAppLanguage() );
+ rSearchOpt.searchString = sSearchText;
+ rSearchOpt.replaceString = sReplaceText;
+
+ if( !bCase )
+ rSearchOpt.transliterateFlags |= i18n::TransliterationModules_IGNORE_CASE;
+ if( bWord )
+ rSearchOpt.searchFlag |= util::SearchFlags::NORM_WORD_ONLY;
+
+// bInSel: 1; // wie geht das?
+// TODO: pSearch->bStyles!
+// inSelection??
+// aSrchParam.SetSrchInSelection(TypeConversion::toBOOL(aVal));
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/unocore/unostyle.cxx b/sw/source/core/unocore/unostyle.cxx
new file mode 100644
index 000000000000..dcd88b5da130
--- /dev/null
+++ b/sw/source/core/unocore/unostyle.cxx
@@ -0,0 +1,4126 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+#include <svx/svxids.hrc>
+#include <hintids.hxx>
+#include <osl/mutex.hxx>
+#include <vcl/svapp.hxx>
+#include <svl/smplhint.hxx>
+#include <svtools/ctrltool.hxx>
+#include <svl/style.hxx>
+#include <svl/itemiter.hxx>
+#include <svx/pageitem.hxx>
+#include <editeng/sizeitem.hxx>
+#include <editeng/ulspitem.hxx>
+#include <editeng/lrspitem.hxx>
+#include <editeng/boxitem.hxx>
+#include <editeng/shaditem.hxx>
+#include <editeng/brshitem.hxx>
+#include <editeng/flstitem.hxx>
+#include <editeng/paperinf.hxx>
+#include <pagedesc.hxx>
+#include <doc.hxx>
+#include <IDocumentUndoRedo.hxx>
+#include <docary.hxx>
+#include <charfmt.hxx>
+#include <cmdid.h>
+#include <unostyle.hxx>
+#include <unosett.hxx>
+#include <docsh.hxx>
+#include <swstyle.h>
+#include <paratr.hxx>
+#include <unoprnms.hxx>
+#include <shellio.hxx>
+#include <docstyle.hxx>
+#include <unotextbodyhf.hxx>
+#include <fmthdft.hxx>
+#include <fmtpdsc.hxx>
+#include <tools/urlobj.hxx>
+#include <poolfmt.hrc>
+#include <poolfmt.hxx>
+#include "unoevent.hxx"
+#include <fmtruby.hxx>
+#include <SwStyleNameMapper.hxx>
+#include <sfx2/printer.hxx>
+#include <com/sun/star/style/ParagraphStyleCategory.hpp>
+#include <com/sun/star/style/XStyleFamiliesSupplier.hpp>
+#include <com/sun/star/beans/PropertyAttribute.hpp>
+#include <com/sun/star/beans/NamedValue.hpp>
+#include <istyleaccess.hxx>
+#include <GetMetricVal.hxx>
+#include <fmtfsize.hxx>
+#include <numrule.hxx>
+
+#include <boost/shared_ptr.hpp>
+
+#include "ccoll.hxx"
+#include "unocore.hrc"
+
+#include <set>
+
+#define STYLE_FAMILY_COUNT 5 // we have 5 style families
+#define TYPE_BOOL 0
+#define TYPE_SIZE 1
+#define TYPE_BRUSH 2
+#define TYPE_ULSPACE 3
+#define TYPE_SHADOW 4
+#define TYPE_LRSPACE 5
+#define TYPE_BOX 6
+
+const unsigned short aStyleByIndex[] =
+{
+ SFX_STYLE_FAMILY_CHAR,
+ SFX_STYLE_FAMILY_PARA,
+ SFX_STYLE_FAMILY_PAGE ,
+ SFX_STYLE_FAMILY_FRAME ,
+ SFX_STYLE_FAMILY_PSEUDO
+};
+
+// Already implemented autostyle families: 3
+#define AUTOSTYLE_FAMILY_COUNT 3
+const IStyleAccess::SwAutoStyleFamily aAutoStyleByIndex[] =
+{
+ IStyleAccess::AUTO_STYLE_CHAR,
+ IStyleAccess::AUTO_STYLE_RUBY,
+ IStyleAccess::AUTO_STYLE_PARA
+};
+
+using namespace ::com::sun::star;
+using ::rtl::OUString;
+
+//convert FN_... to RES_ in header and footer itemset
+sal_uInt16 lcl_ConvertFNToRES(sal_uInt16 nFNId)
+{
+ sal_uInt16 nRes = USHRT_MAX;
+ switch(nFNId)
+ {
+ case FN_UNO_FOOTER_ON:
+ case FN_UNO_HEADER_ON:
+ break;
+ case FN_UNO_FOOTER_BACKGROUND:
+ case FN_UNO_HEADER_BACKGROUND: nRes = RES_BACKGROUND;
+ break;
+ case FN_UNO_FOOTER_BOX:
+ case FN_UNO_HEADER_BOX: nRes = RES_BOX;
+ break;
+ case FN_UNO_FOOTER_LR_SPACE:
+ case FN_UNO_HEADER_LR_SPACE: nRes = RES_LR_SPACE;
+ break;
+ case FN_UNO_FOOTER_SHADOW:
+ case FN_UNO_HEADER_SHADOW: nRes = RES_SHADOW;
+ break;
+ case FN_UNO_FOOTER_BODY_DISTANCE:
+ case FN_UNO_HEADER_BODY_DISTANCE: nRes = RES_UL_SPACE;
+ break;
+ case FN_UNO_FOOTER_IS_DYNAMIC_DISTANCE:
+ case FN_UNO_HEADER_IS_DYNAMIC_DISTANCE: nRes = SID_ATTR_PAGE_DYNAMIC;
+ break;
+ case FN_UNO_FOOTER_SHARE_CONTENT:
+ case FN_UNO_HEADER_SHARE_CONTENT: nRes = SID_ATTR_PAGE_SHARED;
+ break;
+ case FN_UNO_FOOTER_HEIGHT:
+ case FN_UNO_HEADER_HEIGHT: nRes = SID_ATTR_PAGE_SIZE;
+ break;
+ case FN_UNO_FOOTER_EAT_SPACING:
+ case FN_UNO_HEADER_EAT_SPACING: nRes = RES_HEADER_FOOTER_EAT_SPACING;
+ break;
+ }
+ return nRes;
+
+}
+
+SwGetPoolIdFromName lcl_GetSwEnumFromSfxEnum ( SfxStyleFamily eFamily )
+{
+ switch ( eFamily )
+ {
+ case SFX_STYLE_FAMILY_CHAR:
+ return nsSwGetPoolIdFromName::GET_POOLID_CHRFMT;
+ case SFX_STYLE_FAMILY_PARA:
+ return nsSwGetPoolIdFromName::GET_POOLID_TXTCOLL;
+ case SFX_STYLE_FAMILY_FRAME:
+ return nsSwGetPoolIdFromName::GET_POOLID_FRMFMT;
+ case SFX_STYLE_FAMILY_PAGE:
+ return nsSwGetPoolIdFromName::GET_POOLID_PAGEDESC;
+ case SFX_STYLE_FAMILY_PSEUDO:
+ return nsSwGetPoolIdFromName::GET_POOLID_NUMRULE;
+ default:
+ DBG_ASSERT(sal_False, "someone asking for all styles in unostyle.cxx!" );
+ return nsSwGetPoolIdFromName::GET_POOLID_CHRFMT;
+ }
+}
+
+class SwAutoStylesEnumImpl
+{
+ std::vector<SfxItemSet_Pointer_t> mAutoStyles;
+ std::vector<SfxItemSet_Pointer_t>::iterator aIter;
+ SwDoc* pDoc;
+ IStyleAccess::SwAutoStyleFamily eFamily;
+public:
+ SwAutoStylesEnumImpl( SwDoc* pInitDoc, IStyleAccess::SwAutoStyleFamily eFam );
+ ::sal_Bool hasMoreElements() { return aIter != mAutoStyles.end(); }
+ SfxItemSet_Pointer_t nextElement() { return *(aIter++); }
+ IStyleAccess::SwAutoStyleFamily getFamily() const { return eFamily; }
+ SwDoc* getDoc() const { return pDoc; }
+};
+
+/******************************************************************
+ * SwXStyleFamilies
+ ******************************************************************/
+OUString SwXStyleFamilies::getImplementationName(void) throw( uno::RuntimeException )
+{
+ return C2U("SwXStyleFamilies");
+}
+
+sal_Bool SwXStyleFamilies::supportsService(const OUString& rServiceName) throw( uno::RuntimeException )
+{
+ return C2U("com.sun.star.style.StyleFamilies") == rServiceName;
+}
+
+uno::Sequence< OUString > SwXStyleFamilies::getSupportedServiceNames(void) throw( uno::RuntimeException )
+{
+ uno::Sequence< OUString > aRet(1);
+ OUString* pArray = aRet.getArray();
+ pArray[0] = C2U("com.sun.star.style.StyleFamilies");
+ return aRet;
+}
+
+SwXStyleFamilies::SwXStyleFamilies(SwDocShell& rDocShell) :
+ SwUnoCollection(rDocShell.GetDoc()),
+ pDocShell(&rDocShell),
+ pxCharStyles(0),
+ pxParaStyles(0),
+ pxFrameStyles(0),
+ pxPageStyles(0),
+ pxNumberingStyles(0)
+{
+
+}
+
+SwXStyleFamilies::~SwXStyleFamilies()
+{
+ delete pxCharStyles;
+ delete pxParaStyles;
+ delete pxFrameStyles;
+ delete pxPageStyles;
+ delete pxNumberingStyles;
+}
+
+uno::Any SAL_CALL SwXStyleFamilies::getByName(const OUString& Name)
+ throw(
+ container::NoSuchElementException,
+ lang::WrappedTargetException,
+ uno::RuntimeException )
+{
+ SolarMutexGuard aGuard;
+// der Index kommt aus const unsigned short aStyleByIndex[] =
+ uno::Any aRet;
+ if(!IsValid())
+ throw uno::RuntimeException();
+ if(Name.compareToAscii("CharacterStyles") == 0 )
+ aRet = getByIndex(0);
+ else if(Name.compareToAscii("ParagraphStyles") == 0)
+ aRet = getByIndex(1);
+ else if(Name.compareToAscii("FrameStyles") == 0 )
+ aRet = getByIndex(3);
+ else if(Name.compareToAscii("PageStyles") == 0 )
+ aRet = getByIndex(2);
+ else if(Name.compareToAscii("NumberingStyles") == 0 )
+ aRet = getByIndex(4);
+ else
+ throw container::NoSuchElementException();
+ return aRet;
+}
+
+uno::Sequence< OUString > SwXStyleFamilies::getElementNames(void) throw( uno::RuntimeException )
+{
+ uno::Sequence< OUString > aNames(STYLE_FAMILY_COUNT);
+ OUString* pNames = aNames.getArray();
+ pNames[0] = C2U("CharacterStyles");
+ pNames[1] = C2U("ParagraphStyles");
+ pNames[2] = C2U("FrameStyles");
+ pNames[3] = C2U("PageStyles");
+ pNames[4] = C2U("NumberingStyles");
+ return aNames;
+}
+
+sal_Bool SwXStyleFamilies::hasByName(const OUString& Name) throw( uno::RuntimeException )
+{
+ if( Name.compareToAscii("CharacterStyles") == 0 ||
+ Name.compareToAscii("ParagraphStyles") == 0 ||
+ Name.compareToAscii("FrameStyles") == 0 ||
+ Name.compareToAscii("PageStyles") == 0 ||
+ Name.compareToAscii("NumberingStyles") == 0 )
+ return sal_True;
+ else
+ return sal_False;
+}
+
+sal_Int32 SwXStyleFamilies::getCount(void) throw( uno::RuntimeException )
+{
+ return STYLE_FAMILY_COUNT;
+}
+
+uno::Any SwXStyleFamilies::getByIndex(sal_Int32 nIndex)
+ throw( lang::IndexOutOfBoundsException, lang::WrappedTargetException, uno::RuntimeException )
+{
+ SolarMutexGuard aGuard;
+ uno::Any aRet;
+ if(nIndex < 0 || nIndex >= STYLE_FAMILY_COUNT)
+ throw lang::IndexOutOfBoundsException();
+ if(IsValid())
+ {
+ uno::Reference< container::XNameContainer > aRef;
+ sal_uInt16 nType = aStyleByIndex[nIndex];
+ switch( nType )
+ {
+ case SFX_STYLE_FAMILY_CHAR:
+ {
+ if(!pxCharStyles)
+ {
+ ((SwXStyleFamilies*)this)->pxCharStyles = new uno::Reference< container::XNameContainer > ();
+ *pxCharStyles = new SwXStyleFamily(pDocShell, nType);
+ }
+ aRef = *pxCharStyles;
+ }
+ break;
+ case SFX_STYLE_FAMILY_PARA:
+ {
+ if(!pxParaStyles)
+ {
+ ((SwXStyleFamilies*)this)->pxParaStyles = new uno::Reference< container::XNameContainer > ();
+ *pxParaStyles = new SwXStyleFamily(pDocShell, nType);
+ }
+ aRef = *pxParaStyles;
+ }
+ break;
+ case SFX_STYLE_FAMILY_PAGE :
+ {
+ if(!pxPageStyles)
+ {
+ ((SwXStyleFamilies*)this)->pxPageStyles = new uno::Reference< container::XNameContainer > ();
+ *pxPageStyles = new SwXStyleFamily(pDocShell, nType);
+ }
+ aRef = *pxPageStyles;
+ }
+ break;
+ case SFX_STYLE_FAMILY_FRAME :
+ {
+ if(!pxFrameStyles)
+ {
+ ((SwXStyleFamilies*)this)->pxFrameStyles = new uno::Reference< container::XNameContainer > ();
+ *pxFrameStyles = new SwXStyleFamily(pDocShell, nType);
+ }
+ aRef = *pxFrameStyles;
+ }
+ break;
+ case SFX_STYLE_FAMILY_PSEUDO:
+ {
+ if(!pxNumberingStyles)
+ {
+ ((SwXStyleFamilies*)this)->pxNumberingStyles = new uno::Reference< container::XNameContainer > ();
+ *pxNumberingStyles = new SwXStyleFamily(pDocShell, nType);
+ }
+ aRef = *pxNumberingStyles;
+ }
+ break;
+ }
+ aRet.setValue(&aRef, ::getCppuType((const uno::Reference<container::XNameContainer>*)0));
+ }
+ else
+ throw uno::RuntimeException();
+ return aRet;
+}
+
+uno::Type SwXStyleFamilies::getElementType(void)
+ throw( uno::RuntimeException )
+{
+ return ::getCppuType((const uno::Reference<container::XNameContainer>*)0);
+
+}
+
+sal_Bool SwXStyleFamilies::hasElements(void) throw( uno::RuntimeException )
+{
+ return sal_True;
+}
+
+void SwXStyleFamilies::loadStylesFromURL(const OUString& rURL,
+ const uno::Sequence< beans::PropertyValue >& aOptions)
+ throw( io::IOException, uno::RuntimeException )
+{
+ SolarMutexGuard aGuard;
+ sal_Bool bLoadStyleText = sal_True;
+ sal_Bool bLoadStylePage = sal_True;
+ sal_Bool bLoadStyleOverwrite = sal_True;
+ sal_Bool bLoadStyleNumbering = sal_True;
+ sal_Bool bLoadStyleFrame = sal_True;
+ if(IsValid() && rURL.getLength())
+ {
+ const uno::Any* pVal;
+ int nCount = aOptions.getLength();
+ const beans::PropertyValue* pArray = aOptions.getConstArray();
+ for(int i = 0; i < nCount; i++)
+ if( ( pVal = &pArray[i].Value)->getValueType() ==
+ ::getBooleanCppuType() )
+ {
+ String sName = pArray[i].Name;
+ sal_Bool bVal = *(sal_Bool*)pVal->getValue();
+ if( sName.EqualsAscii(SW_PROP_NAME_STR(UNO_NAME_OVERWRITE_STYLES )))
+ bLoadStyleOverwrite = bVal;
+ else if( sName.EqualsAscii(SW_PROP_NAME_STR(UNO_NAME_LOAD_NUMBERING_STYLES )))
+ bLoadStyleNumbering = bVal;
+ else if( sName.EqualsAscii(SW_PROP_NAME_STR(UNO_NAME_LOAD_PAGE_STYLES )))
+ bLoadStylePage = bVal;
+ else if( sName.EqualsAscii(SW_PROP_NAME_STR(UNO_NAME_LOAD_FRAME_STYLES )))
+ bLoadStyleFrame = bVal;
+ else if( sName.EqualsAscii(SW_PROP_NAME_STR(UNO_NAME_LOAD_TEXT_STYLES )))
+ bLoadStyleText = bVal;
+ }
+
+ SwgReaderOption aOpt;
+ aOpt.SetFrmFmts( bLoadStyleFrame );
+ aOpt.SetTxtFmts( bLoadStyleText );
+ aOpt.SetPageDescs( bLoadStylePage );
+ aOpt.SetNumRules( bLoadStyleNumbering );
+ aOpt.SetMerge( !bLoadStyleOverwrite );
+
+ sal_uLong nErr = pDocShell->LoadStylesFromFile( rURL, aOpt, sal_True );
+ if( nErr )
+ throw io::IOException();
+ }
+ else
+ throw uno::RuntimeException();
+}
+
+uno::Sequence< beans::PropertyValue > SwXStyleFamilies::getStyleLoaderOptions(void)
+ throw( uno::RuntimeException )
+{
+ SolarMutexGuard aGuard;
+ uno::Sequence< beans::PropertyValue > aSeq(5);
+ beans::PropertyValue* pArray = aSeq.getArray();
+ uno::Any aVal;
+ sal_Bool bTemp = sal_True;
+ aVal.setValue(&bTemp, ::getCppuBooleanType());
+ pArray[0] = beans::PropertyValue(rtl::OUString::createFromAscii(SW_PROP_NAME_STR(UNO_NAME_LOAD_TEXT_STYLES)), -1, aVal, beans::PropertyState_DIRECT_VALUE);
+ aVal.setValue(&bTemp, ::getCppuBooleanType());
+ pArray[1] = beans::PropertyValue(rtl::OUString::createFromAscii(SW_PROP_NAME_STR(UNO_NAME_LOAD_FRAME_STYLES)), -1, aVal, beans::PropertyState_DIRECT_VALUE);
+ aVal.setValue(&bTemp, ::getCppuBooleanType());
+ pArray[2] = beans::PropertyValue(rtl::OUString::createFromAscii(SW_PROP_NAME_STR(UNO_NAME_LOAD_PAGE_STYLES)), -1, aVal, beans::PropertyState_DIRECT_VALUE);
+ aVal.setValue(&bTemp, ::getCppuBooleanType());
+ pArray[3] = beans::PropertyValue(rtl::OUString::createFromAscii(SW_PROP_NAME_STR(UNO_NAME_LOAD_NUMBERING_STYLES)), -1, aVal, beans::PropertyState_DIRECT_VALUE);
+ aVal.setValue(&bTemp, ::getCppuBooleanType());
+ pArray[4] = beans::PropertyValue(rtl::OUString::createFromAscii(SW_PROP_NAME_STR(UNO_NAME_OVERWRITE_STYLES)), -1, aVal, beans::PropertyState_DIRECT_VALUE);
+ return aSeq;
+}
+
+/******************************************************************
+ * SwXStyleFamily
+ ******************************************************************/
+OUString SwXStyleFamily::getImplementationName(void) throw( uno::RuntimeException )
+{
+ return C2U("SwXStyleFamily");
+}
+
+sal_Bool SwXStyleFamily::supportsService(const OUString& rServiceName) throw( uno::RuntimeException )
+{
+ return C2U("com.sun.star.style.StyleFamily") == rServiceName;
+}
+
+uno::Sequence< OUString > SwXStyleFamily::getSupportedServiceNames(void) throw( uno::RuntimeException )
+{
+ uno::Sequence< OUString > aRet(1);
+ OUString* pArray = aRet.getArray();
+ pArray[0] = C2U("com.sun.star.style.StyleFamily");
+ return aRet;
+}
+
+SwXStyleFamily::SwXStyleFamily(SwDocShell* pDocSh, sal_uInt16 nFamily) :
+ eFamily((SfxStyleFamily)nFamily),
+ pBasePool(pDocSh->GetStyleSheetPool()),
+ pDocShell(pDocSh)
+{
+ StartListening(*pBasePool);
+}
+
+SwXStyleFamily::~SwXStyleFamily()
+{
+
+}
+
+sal_Int32 lcl_GetCountOrName ( const SwDoc &rDoc, SfxStyleFamily eFamily, String *pString, sal_uInt16 nIndex = USHRT_MAX )
+{
+ sal_Int32 nCount = 0;
+ switch( eFamily )
+ {
+ case SFX_STYLE_FAMILY_CHAR:
+ {
+ sal_uInt16 nBaseCount = RES_POOLCHR_HTML_END - RES_POOLCHR_HTML_BEGIN +
+ RES_POOLCHR_NORMAL_END - RES_POOLCHR_NORMAL_BEGIN;
+ nIndex = nIndex - nBaseCount;
+ const sal_uInt16 nArrLen = rDoc.GetCharFmts()->Count();
+ for( sal_uInt16 i = 0; i < nArrLen; i++ )
+ {
+ SwCharFmt* pFmt = (*rDoc.GetCharFmts())[ i ];
+ if( pFmt->IsDefault() && pFmt != rDoc.GetDfltCharFmt() )
+ continue;
+ if ( IsPoolUserFmt ( pFmt->GetPoolFmtId() ) )
+ {
+ if ( nIndex == nCount )
+ {
+ // the default character format needs to be set to "Default!"
+ if(rDoc.GetDfltCharFmt() == pFmt)
+ SwStyleNameMapper::FillUIName(
+ RES_POOLCOLL_STANDARD, *pString );
+ else
+ *pString = pFmt->GetName();
+ break;
+ }
+ nCount++;
+ }
+ }
+ nCount += nBaseCount;
+ }
+ break;
+ case SFX_STYLE_FAMILY_PARA:
+ {
+ sal_uInt16 nBaseCount = RES_POOLCOLL_HTML_END - RES_POOLCOLL_HTML_BEGIN +
+ RES_POOLCOLL_DOC_END - RES_POOLCOLL_DOC_BEGIN +
+ RES_POOLCOLL_REGISTER_END - RES_POOLCOLL_REGISTER_BEGIN +
+ RES_POOLCOLL_EXTRA_END - RES_POOLCOLL_EXTRA_BEGIN +
+ RES_POOLCOLL_LISTS_END - RES_POOLCOLL_LISTS_BEGIN +
+ RES_POOLCOLL_TEXT_END - RES_POOLCOLL_TEXT_BEGIN;
+ nIndex = nIndex - nBaseCount;
+ const sal_uInt16 nArrLen = rDoc.GetTxtFmtColls()->Count();
+ for ( sal_uInt16 i = 0; i < nArrLen; i++ )
+ {
+ SwTxtFmtColl * pColl = (*rDoc.GetTxtFmtColls())[i];
+ if ( pColl->IsDefault() )
+ continue;
+ if ( IsPoolUserFmt ( pColl->GetPoolFmtId() ) )
+ {
+ if ( nIndex == nCount )
+ {
+ *pString = pColl->GetName();
+ break;
+ }
+ nCount++;
+ }
+ }
+ nCount += nBaseCount;
+ }
+ break;
+ case SFX_STYLE_FAMILY_FRAME:
+ {
+ sal_uInt16 nBaseCount = RES_POOLFRM_END - RES_POOLFRM_BEGIN;
+ nIndex = nIndex - nBaseCount;
+ const sal_uInt16 nArrLen = rDoc.GetFrmFmts()->Count();
+ for( sal_uInt16 i = 0; i < nArrLen; i++ )
+ {
+ SwFrmFmt* pFmt = (*rDoc.GetFrmFmts())[ i ];
+ if(pFmt->IsDefault() || pFmt->IsAuto())
+ continue;
+ if ( IsPoolUserFmt ( pFmt->GetPoolFmtId() ) )
+ {
+ if ( nIndex == nCount )
+ {
+ *pString = pFmt->GetName();
+ break;
+ }
+ nCount++;
+ }
+ }
+ nCount += nBaseCount;
+ }
+ break;
+ case SFX_STYLE_FAMILY_PAGE:
+ {
+ sal_uInt16 nBaseCount = RES_POOLPAGE_END - RES_POOLPAGE_BEGIN;
+ nIndex = nIndex - nBaseCount;
+ const sal_uInt16 nArrLen = rDoc.GetPageDescCnt();
+ for(sal_uInt16 i = 0; i < nArrLen; ++i)
+ {
+ const SwPageDesc& rDesc = rDoc.GetPageDesc(i);
+
+ if ( IsPoolUserFmt ( rDesc.GetPoolFmtId() ) )
+ {
+ if ( nIndex == nCount )
+ {
+ *pString = rDesc.GetName();
+ break;
+ }
+ nCount++;
+ }
+ }
+ nCount += nBaseCount;
+ }
+ break;
+ case SFX_STYLE_FAMILY_PSEUDO:
+ {
+ sal_uInt16 nBaseCount = RES_POOLNUMRULE_END - RES_POOLNUMRULE_BEGIN;
+ nIndex = nIndex - nBaseCount;
+ const SwNumRuleTbl& rNumTbl = rDoc.GetNumRuleTbl();
+ for(sal_uInt16 i = 0; i < rNumTbl.Count(); ++i)
+ {
+ const SwNumRule& rRule = *rNumTbl[ i ];
+ if( rRule.IsAutoRule() )
+ continue;
+ if ( IsPoolUserFmt ( rRule.GetPoolFmtId() ) )
+ {
+ if ( nIndex == nCount )
+ {
+ *pString = rRule.GetName();
+ break;
+ }
+ nCount++;
+ }
+ }
+ nCount += nBaseCount;
+ }
+ break;
+
+ default:
+ ;
+ }
+ return nCount;
+}
+
+sal_Int32 SwXStyleFamily::getCount(void) throw( uno::RuntimeException )
+{
+ SolarMutexGuard aGuard;
+ return lcl_GetCountOrName ( *pDocShell->GetDoc(), eFamily, NULL );
+}
+
+uno::Any SwXStyleFamily::getByIndex(sal_Int32 nTempIndex)
+ throw( lang::IndexOutOfBoundsException, lang::WrappedTargetException, uno::RuntimeException )
+{
+ SolarMutexGuard aGuard;
+ uno::Any aRet;
+ if ( nTempIndex >= 0 && nTempIndex < USHRT_MAX )
+ {
+ sal_uInt16 nIndex = static_cast < sal_uInt16 > ( nTempIndex );
+ if(pBasePool)
+ {
+ String sStyleName;
+ switch( eFamily )
+ {
+ case SFX_STYLE_FAMILY_CHAR:
+ {
+ if ( nIndex < ( RES_POOLCHR_NORMAL_END - RES_POOLCHR_NORMAL_BEGIN ) )
+ SwStyleNameMapper::FillUIName ( static_cast< sal_uInt16 >(RES_POOLCHR_NORMAL_BEGIN + nIndex), sStyleName );
+ else if ( nIndex < ( RES_POOLCHR_HTML_END - RES_POOLCHR_HTML_BEGIN +
+ RES_POOLCHR_NORMAL_END - RES_POOLCHR_NORMAL_BEGIN ) )
+ SwStyleNameMapper::FillUIName ( RES_POOLCHR_HTML_BEGIN
+ - RES_POOLCHR_NORMAL_END + RES_POOLCHR_NORMAL_BEGIN
+ + nIndex, sStyleName );
+ }
+ break;
+ case SFX_STYLE_FAMILY_PARA:
+ {
+ if ( nIndex < ( RES_POOLCOLL_TEXT_END - RES_POOLCOLL_TEXT_BEGIN ) )
+ SwStyleNameMapper::FillUIName ( static_cast< sal_uInt16 >(RES_POOLCOLL_TEXT_BEGIN + nIndex), sStyleName );
+ else if ( nIndex < ( RES_POOLCOLL_LISTS_END - RES_POOLCOLL_LISTS_BEGIN +
+ RES_POOLCOLL_TEXT_END - RES_POOLCOLL_TEXT_BEGIN ) )
+ SwStyleNameMapper::FillUIName ( RES_POOLCOLL_LISTS_BEGIN
+ - RES_POOLCOLL_TEXT_END + RES_POOLCOLL_TEXT_BEGIN
+ + nIndex, sStyleName );
+ else if ( nIndex < ( RES_POOLCOLL_EXTRA_END - RES_POOLCOLL_EXTRA_BEGIN +
+ RES_POOLCOLL_LISTS_END - RES_POOLCOLL_LISTS_BEGIN +
+ RES_POOLCOLL_TEXT_END - RES_POOLCOLL_TEXT_BEGIN ) )
+ SwStyleNameMapper::FillUIName ( static_cast< sal_uInt16 >(RES_POOLCOLL_EXTRA_BEGIN
+ - RES_POOLCOLL_LISTS_END + RES_POOLCOLL_LISTS_BEGIN
+ - RES_POOLCOLL_TEXT_END + RES_POOLCOLL_TEXT_BEGIN
+ + nIndex), sStyleName );
+ else if ( nIndex < ( RES_POOLCOLL_REGISTER_END - RES_POOLCOLL_REGISTER_BEGIN +
+ RES_POOLCOLL_EXTRA_END - RES_POOLCOLL_EXTRA_BEGIN +
+ RES_POOLCOLL_LISTS_END - RES_POOLCOLL_LISTS_BEGIN +
+ RES_POOLCOLL_TEXT_END - RES_POOLCOLL_TEXT_BEGIN ) )
+ SwStyleNameMapper::FillUIName ( static_cast< sal_uInt16 >(RES_POOLCOLL_REGISTER_BEGIN
+ - RES_POOLCOLL_EXTRA_END + RES_POOLCOLL_EXTRA_BEGIN
+ - RES_POOLCOLL_LISTS_END + RES_POOLCOLL_LISTS_BEGIN
+ - RES_POOLCOLL_TEXT_END + RES_POOLCOLL_TEXT_BEGIN
+ + nIndex), sStyleName );
+ else if ( nIndex < ( RES_POOLCOLL_DOC_END - RES_POOLCOLL_DOC_BEGIN +
+ RES_POOLCOLL_REGISTER_END - RES_POOLCOLL_REGISTER_BEGIN +
+ RES_POOLCOLL_EXTRA_END - RES_POOLCOLL_EXTRA_BEGIN +
+ RES_POOLCOLL_LISTS_END - RES_POOLCOLL_LISTS_BEGIN +
+ RES_POOLCOLL_TEXT_END - RES_POOLCOLL_TEXT_BEGIN ) )
+ SwStyleNameMapper::FillUIName ( static_cast< sal_uInt16 >(RES_POOLCOLL_DOC_BEGIN
+ - RES_POOLCOLL_REGISTER_END + RES_POOLCOLL_REGISTER_BEGIN
+ - RES_POOLCOLL_EXTRA_END + RES_POOLCOLL_EXTRA_BEGIN
+ - RES_POOLCOLL_LISTS_END + RES_POOLCOLL_LISTS_BEGIN
+ - RES_POOLCOLL_TEXT_END + RES_POOLCOLL_TEXT_BEGIN
+ + nIndex), sStyleName );
+ else if ( nIndex < ( RES_POOLCOLL_HTML_END - RES_POOLCOLL_HTML_BEGIN +
+ RES_POOLCOLL_DOC_END - RES_POOLCOLL_DOC_BEGIN +
+ RES_POOLCOLL_REGISTER_END - RES_POOLCOLL_REGISTER_BEGIN +
+ RES_POOLCOLL_EXTRA_END - RES_POOLCOLL_EXTRA_BEGIN +
+ RES_POOLCOLL_LISTS_END - RES_POOLCOLL_LISTS_BEGIN +
+ RES_POOLCOLL_TEXT_END - RES_POOLCOLL_TEXT_BEGIN ) )
+ SwStyleNameMapper::FillUIName ( static_cast< sal_uInt16 >(RES_POOLCOLL_HTML_BEGIN
+ - RES_POOLCOLL_DOC_END + RES_POOLCOLL_DOC_BEGIN
+ - RES_POOLCOLL_REGISTER_END + RES_POOLCOLL_REGISTER_BEGIN
+ - RES_POOLCOLL_EXTRA_END + RES_POOLCOLL_EXTRA_BEGIN
+ - RES_POOLCOLL_LISTS_END + RES_POOLCOLL_LISTS_BEGIN
+ - RES_POOLCOLL_TEXT_END + RES_POOLCOLL_TEXT_BEGIN
+ + nIndex), sStyleName );
+ }
+ break;
+ case SFX_STYLE_FAMILY_FRAME:
+ {
+ if ( nIndex < ( RES_POOLFRM_END - RES_POOLFRM_BEGIN ) )
+ {
+ SwStyleNameMapper::FillUIName ( static_cast< sal_uInt16 >(RES_POOLFRM_BEGIN + nIndex), sStyleName );
+ }
+ }
+ break;
+ case SFX_STYLE_FAMILY_PAGE:
+ {
+ if ( nIndex < ( RES_POOLPAGE_END - RES_POOLPAGE_BEGIN ) )
+ {
+ SwStyleNameMapper::FillUIName ( static_cast< sal_uInt16 >(RES_POOLPAGE_BEGIN + nIndex), sStyleName );
+ }
+ }
+ break;
+ case SFX_STYLE_FAMILY_PSEUDO:
+ {
+ if ( nIndex < ( RES_POOLNUMRULE_END - RES_POOLNUMRULE_BEGIN ) )
+ {
+ SwStyleNameMapper::FillUIName ( static_cast< sal_uInt16 >(RES_POOLNUMRULE_BEGIN + nIndex), sStyleName );
+ }
+ }
+ break;
+
+ default:
+ ;
+ }
+ if ( !sStyleName.Len() )
+ lcl_GetCountOrName ( *pDocShell->GetDoc(), eFamily, &sStyleName, nIndex );
+
+ if ( sStyleName.Len() )
+ {
+ SfxStyleSheetBase* pBase = pBasePool->Find( sStyleName, eFamily );
+ if(pBase)
+ {
+ uno::Reference< style::XStyle > xStyle = _FindStyle(sStyleName);
+ if(!xStyle.is())
+ {
+ xStyle = eFamily == SFX_STYLE_FAMILY_PAGE ?
+ new SwXPageStyle(*pBasePool, pDocShell, eFamily, sStyleName) :
+ eFamily == SFX_STYLE_FAMILY_FRAME ?
+ new SwXFrameStyle(*pBasePool, pDocShell->GetDoc(), pBase->GetName()):
+ new SwXStyle(*pBasePool, eFamily, pDocShell->GetDoc(), sStyleName);
+ }
+ aRet.setValue(&xStyle, ::getCppuType((uno::Reference<style::XStyle>*)0));
+ }
+ else
+ throw container::NoSuchElementException();
+ }
+ else
+ throw lang::IndexOutOfBoundsException();
+ }
+ else
+ throw uno::RuntimeException();
+ }
+ else
+ throw lang::IndexOutOfBoundsException();
+
+ return aRet;
+}
+
+uno::Any SwXStyleFamily::getByName(const OUString& rName)
+ throw( container::NoSuchElementException, lang::WrappedTargetException, uno::RuntimeException )
+{
+ SolarMutexGuard aGuard;
+ uno::Any aRet;
+ String sStyleName;
+ SwStyleNameMapper::FillUIName(rName, sStyleName, lcl_GetSwEnumFromSfxEnum ( eFamily ), sal_True );
+ if(pBasePool)
+ {
+ pBasePool->SetSearchMask(eFamily, SFXSTYLEBIT_ALL );
+ SfxStyleSheetBase* pBase = pBasePool->Find(sStyleName);
+ if(pBase)
+ {
+ uno::Reference< style::XStyle > xStyle = _FindStyle(sStyleName);
+ if(!xStyle.is())
+ {
+ xStyle = eFamily == SFX_STYLE_FAMILY_PAGE ?
+ new SwXPageStyle(*pBasePool, pDocShell, eFamily, sStyleName) :
+ eFamily == SFX_STYLE_FAMILY_FRAME ?
+ new SwXFrameStyle(*pBasePool, pDocShell->GetDoc(), pBase->GetName()):
+ new SwXStyle(*pBasePool, eFamily, pDocShell->GetDoc(), sStyleName);
+ }
+ aRet.setValue(&xStyle, ::getCppuType((uno::Reference<style::XStyle>*)0));
+ }
+ else
+ throw container::NoSuchElementException();
+ }
+ else
+ throw uno::RuntimeException();
+ return aRet;
+
+}
+
+uno::Sequence< OUString > SwXStyleFamily::getElementNames(void) throw( uno::RuntimeException )
+{
+ SolarMutexGuard aGuard;
+ uno::Sequence< OUString > aRet;
+ if(pBasePool)
+ {
+ SfxStyleSheetIterator* pIterator = pBasePool->CreateIterator(eFamily, 0xffff);
+ sal_uInt16 nCount = pIterator->Count();
+ aRet.realloc(nCount);
+ OUString* pArray = aRet.getArray();
+ String aString;
+ for(sal_uInt16 i = 0; i < nCount; i++)
+ {
+ SwStyleNameMapper::FillProgName((*pIterator)[i]->GetName(), aString, lcl_GetSwEnumFromSfxEnum ( eFamily ), sal_True );
+ pArray[i] = OUString ( aString );
+ }
+ delete pIterator;
+ }
+ else
+ throw uno::RuntimeException();
+ return aRet;
+}
+
+sal_Bool SwXStyleFamily::hasByName(const OUString& rName) throw( uno::RuntimeException )
+{
+ SolarMutexGuard aGuard;
+ sal_Bool bRet = sal_False;
+ if(pBasePool)
+ {
+ String sStyleName;
+ SwStyleNameMapper::FillUIName(rName, sStyleName, lcl_GetSwEnumFromSfxEnum ( eFamily ), sal_True );
+ pBasePool->SetSearchMask(eFamily, SFXSTYLEBIT_ALL );
+ SfxStyleSheetBase* pBase = pBasePool->Find(sStyleName);
+ bRet = 0 != pBase;
+ }
+ else
+ throw uno::RuntimeException();
+ return bRet;
+
+}
+
+uno::Type SwXStyleFamily::getElementType(void) throw( uno::RuntimeException )
+{
+ return ::getCppuType((const uno::Reference<style::XStyle>*)0);
+
+}
+
+sal_Bool SwXStyleFamily::hasElements(void) throw( uno::RuntimeException )
+{
+ if(!pBasePool)
+ throw uno::RuntimeException();
+ return sal_True;
+}
+
+void SwXStyleFamily::insertByName(const OUString& rName, const uno::Any& rElement)
+ throw( lang::IllegalArgumentException, container::ElementExistException, lang::WrappedTargetException, uno::RuntimeException )
+{
+ SolarMutexGuard aGuard;
+ if(pBasePool)
+ {
+ String sStyleName;
+ SwStyleNameMapper::FillUIName(rName, sStyleName, lcl_GetSwEnumFromSfxEnum ( eFamily ), sal_True);
+ pBasePool->SetSearchMask(eFamily, SFXSTYLEBIT_ALL );
+ SfxStyleSheetBase* pBase = pBasePool->Find(sStyleName);
+ SfxStyleSheetBase* pUINameBase = pBasePool->Find( sStyleName );
+ if(pBase || pUINameBase)
+ throw container::ElementExistException();
+ else
+ {
+ if(rElement.getValueType().getTypeClass() ==
+ uno::TypeClass_INTERFACE)
+ {
+ uno::Reference< uno::XInterface > * pxRef =
+ (uno::Reference< uno::XInterface > *)rElement.getValue();
+
+ uno::Reference<lang::XUnoTunnel> xStyleTunnel( *pxRef, uno::UNO_QUERY);
+
+ SwXStyle* pNewStyle = 0;
+ if(xStyleTunnel.is())
+ {
+ pNewStyle = reinterpret_cast< SwXStyle * >(
+ sal::static_int_cast< sal_IntPtr >( xStyleTunnel->getSomething( SwXStyle::getUnoTunnelId()) ));
+ }
+ if(!pNewStyle || !pNewStyle->IsDescriptor() ||
+ pNewStyle->GetFamily() != eFamily)
+ throw lang::IllegalArgumentException();
+ if(pNewStyle)
+ {
+ sal_uInt16 nMask = 0xffff;
+ if(eFamily == SFX_STYLE_FAMILY_PARA && !pNewStyle->IsConditional())
+ nMask &= ~SWSTYLEBIT_CONDCOLL;
+#if OSL_DEBUG_LEVEL > 1
+ SfxStyleSheetBase& rNewBase =
+#endif
+ pBasePool->Make(sStyleName, eFamily, nMask);
+ pNewStyle->SetDoc(pDocShell->GetDoc(), pBasePool);
+ pNewStyle->SetStyleName(sStyleName);
+ String sParentStyleName(pNewStyle->GetParentStyleName());
+ if(sParentStyleName.Len())
+ {
+ pBasePool->SetSearchMask(eFamily, SFXSTYLEBIT_ALL );
+ SfxStyleSheetBase* pParentBase = pBasePool->Find(sParentStyleName);
+ if(pParentBase && pParentBase->GetFamily() == eFamily &&
+ &pParentBase->GetPool() == pBasePool)
+ pBasePool->SetParent( eFamily, sStyleName, sParentStyleName );
+
+ }
+#if OSL_DEBUG_LEVEL > 1
+ (void)rNewBase;
+#endif
+ //so, jetzt sollten noch die Properties des Descriptors angewandt werden
+ pNewStyle->ApplyDescriptorProperties();
+ }
+ else
+ throw lang::IllegalArgumentException();
+ }
+ else
+ throw lang::IllegalArgumentException();
+ }
+ }
+ else
+ throw uno::RuntimeException();
+}
+
+void SwXStyleFamily::replaceByName(const OUString& rName, const uno::Any& rElement)
+ throw( lang::IllegalArgumentException, container::NoSuchElementException, lang::WrappedTargetException, uno::RuntimeException )
+{
+ SolarMutexGuard aGuard;
+ if(pBasePool)
+ {
+ pBasePool->SetSearchMask(eFamily);
+ SfxStyleSheetBase* pBase = pBasePool->Find(rName);
+ //Ersetzung geht nur fuer benutzerdefinierte Styles
+ if(!pBase)
+ throw container::NoSuchElementException();
+ if(!pBase->IsUserDefined())
+ throw lang::IllegalArgumentException();
+ //if theres an object available to this style then it must be invalidated
+ uno::Reference< style::XStyle > xStyle = _FindStyle(pBase->GetName());
+ if(xStyle.is())
+ {
+ uno::Reference<lang::XUnoTunnel> xTunnel( xStyle, uno::UNO_QUERY);
+ if(xTunnel.is())
+ {
+ SwXStyle* pStyle = reinterpret_cast< SwXStyle * >(
+ sal::static_int_cast< sal_IntPtr >( xTunnel->getSomething( SwXStyle::getUnoTunnelId()) ));
+ pStyle->Invalidate();
+ }
+ }
+
+ pBasePool->Remove(pBase);
+ insertByName(rName, rElement);
+ }
+ else
+ throw uno::RuntimeException();
+}
+
+void SwXStyleFamily::removeByName(const OUString& rName) throw( container::NoSuchElementException, lang::WrappedTargetException, uno::RuntimeException )
+{
+ SolarMutexGuard aGuard;
+ if(pBasePool)
+ {
+ pBasePool->SetSearchMask(eFamily, SFXSTYLEBIT_ALL );
+ String aString;
+ SwStyleNameMapper::FillUIName(rName, aString, lcl_GetSwEnumFromSfxEnum ( eFamily ), sal_True );
+
+ SfxStyleSheetBase* pBase = pBasePool->Find( aString );
+ if(pBase)
+ pBasePool->Remove(pBase);
+ else
+ throw container::NoSuchElementException();
+ }
+ else
+ throw uno::RuntimeException();
+}
+
+uno::Reference< beans::XPropertySetInfo > SAL_CALL SwXStyleFamily::getPropertySetInfo( ) throw (uno::RuntimeException)
+{
+ OSL_FAIL( "###unexpected!" );
+ return uno::Reference< beans::XPropertySetInfo >();
+}
+
+void SAL_CALL SwXStyleFamily::setPropertyValue( const ::rtl::OUString&, const uno::Any& ) throw (beans::UnknownPropertyException, beans::PropertyVetoException, lang::IllegalArgumentException, lang::WrappedTargetException, uno::RuntimeException)
+{
+ OSL_FAIL( "###unexpected!" );
+}
+
+uno::Any SAL_CALL SwXStyleFamily::getPropertyValue( const ::rtl::OUString& sPropertyName ) throw (beans::UnknownPropertyException, lang::WrappedTargetException, uno::RuntimeException)
+{
+ uno::Any aRet;
+
+ if ( sPropertyName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("DisplayName") ) )
+ {
+ SolarMutexGuard aGuard;
+ sal_uInt32 nResId = 0;
+ switch ( eFamily )
+ {
+ case SFX_STYLE_FAMILY_CHAR:
+ nResId = STR_STYLE_FAMILY_CHARACTER; break;
+ case SFX_STYLE_FAMILY_PARA:
+ nResId = STR_STYLE_FAMILY_PARAGRAPH; break;
+ case SFX_STYLE_FAMILY_FRAME:
+ nResId = STR_STYLE_FAMILY_FRAME; break;
+ case SFX_STYLE_FAMILY_PAGE:
+ nResId = STR_STYLE_FAMILY_PAGE; break;
+ case SFX_STYLE_FAMILY_PSEUDO:
+ nResId = STR_STYLE_FAMILY_NUMBERING; break;
+ default:
+ OSL_FAIL( "SwXStyleFamily::getPropertyValue(): invalid family" );
+ }
+ if ( nResId > 0 )
+ {
+ OUString sDisplayName( String( SW_RES( nResId ) ) );
+ aRet = uno::makeAny( sDisplayName );
+ }
+ }
+ else
+ {
+ throw beans::UnknownPropertyException( OUString( RTL_CONSTASCII_USTRINGPARAM("unknown property: ") ) + sPropertyName, static_cast<OWeakObject *>(this) );
+ }
+
+ return aRet;
+}
+
+void SAL_CALL SwXStyleFamily::addPropertyChangeListener( const ::rtl::OUString&, const uno::Reference< beans::XPropertyChangeListener >& ) throw (beans::UnknownPropertyException, lang::WrappedTargetException, uno::RuntimeException)
+{
+ OSL_FAIL( "###unexpected!" );
+}
+
+void SAL_CALL SwXStyleFamily::removePropertyChangeListener( const ::rtl::OUString&, const uno::Reference< beans::XPropertyChangeListener >& ) throw (beans::UnknownPropertyException, lang::WrappedTargetException, uno::RuntimeException)
+{
+ OSL_FAIL( "###unexpected!" );
+}
+
+void SAL_CALL SwXStyleFamily::addVetoableChangeListener( const ::rtl::OUString&, const uno::Reference< beans::XVetoableChangeListener >& ) throw (beans::UnknownPropertyException, lang::WrappedTargetException, uno::RuntimeException)
+{
+ OSL_FAIL( "###unexpected!" );
+}
+
+void SAL_CALL SwXStyleFamily::removeVetoableChangeListener( const ::rtl::OUString&, const uno::Reference< beans::XVetoableChangeListener >& ) throw (beans::UnknownPropertyException, lang::WrappedTargetException, uno::RuntimeException)
+{
+ OSL_FAIL( "###unexpected!" );
+}
+
+void SwXStyleFamily::Notify( SfxBroadcaster& rBC, const SfxHint& rHint )
+{
+ SfxSimpleHint *pHint = PTR_CAST( SfxSimpleHint, &rHint );
+ if( pHint && ( pHint->GetId() & SFX_HINT_DYING ) )
+ {
+ pBasePool = 0;
+ pDocShell = 0;
+ EndListening(rBC);
+ }
+}
+
+SwXStyle* SwXStyleFamily::_FindStyle(const String& rStyleName)const
+{
+ sal_uInt16 nLCount = pBasePool->GetListenerCount();
+ SfxListener* pListener = 0;
+ for( sal_uInt16 i = 0; i < nLCount; i++)
+ {
+ pListener = pBasePool->GetListener( i );
+ SwXStyle* pTempStyle = dynamic_cast<SwXStyle*>( pListener );
+ if(pTempStyle && pTempStyle->GetFamily() == eFamily && pTempStyle->GetStyleName() == rStyleName)
+ {
+ return pTempStyle;
+ }
+ }
+ return 0;
+}
+
+class SwStyleProperties_Impl
+{
+ const PropertyEntryVector_t aPropertyEntries;
+ uno::Any** pAnyArr;
+ sal_uInt32 nArrLen;
+
+public:
+ SwStyleProperties_Impl(const SfxItemPropertyMap* _pMap);
+ ~SwStyleProperties_Impl();
+
+ sal_Bool SetProperty(const ::rtl::OUString& rName, uno::Any aVal);
+ sal_Bool GetProperty(const ::rtl::OUString& rName, uno::Any*& rpAny);
+ sal_Bool ClearProperty( const ::rtl::OUString& rPropertyName );
+ void ClearAllProperties( );
+ void GetProperty(const ::rtl::OUString &rPropertyName, const uno::Reference < beans::XPropertySet > &rxPropertySet, uno::Any& rAny );
+
+ const PropertyEntryVector_t& GetPropertyVector() const {return aPropertyEntries; }
+
+};
+
+SwStyleProperties_Impl::SwStyleProperties_Impl(const SfxItemPropertyMap* pMap) :
+ aPropertyEntries( pMap->getPropertyEntries() ),
+ nArrLen(0)
+{
+ nArrLen = aPropertyEntries.size();
+
+ pAnyArr = new uno::Any* [nArrLen];
+ for ( sal_uInt32 i =0 ; i < nArrLen; i++ )
+ pAnyArr[i] = 0;
+}
+
+SwStyleProperties_Impl::~SwStyleProperties_Impl()
+{
+ for ( sal_uInt16 i =0 ; i < nArrLen; i++ )
+ delete pAnyArr[i];
+ delete[] pAnyArr;
+}
+
+sal_Bool SwStyleProperties_Impl::SetProperty(const ::rtl::OUString& rName, uno::Any aVal)
+{
+ sal_uInt16 nPos = 0;
+ sal_Bool bRet = sal_False;
+ PropertyEntryVector_t::const_iterator aIt = aPropertyEntries.begin();
+ while( aIt != aPropertyEntries.end() )
+ {
+ if(rName == aIt->sName)
+ {
+ delete pAnyArr[nPos];
+ pAnyArr[nPos] = new uno::Any ( aVal );
+ bRet = sal_True;
+ break;
+ }
+ ++nPos;
+ ++aIt;
+ }
+ return bRet;
+}
+
+sal_Bool SwStyleProperties_Impl::ClearProperty( const OUString& rName )
+{
+ sal_Bool bRet = sal_False;
+ sal_uInt16 nPos = 0;
+ PropertyEntryVector_t::const_iterator aIt = aPropertyEntries.begin();
+ while( aIt != aPropertyEntries.end() )
+ {
+ if( rName == aIt->sName )
+ {
+ delete pAnyArr[nPos];
+ pAnyArr[ nPos ] = 0;
+ bRet = sal_True;
+ break;
+ }
+ ++nPos;
+ ++aIt;
+ }
+ return bRet;
+}
+
+void SwStyleProperties_Impl::ClearAllProperties( )
+{
+ for ( sal_uInt16 i = 0; i < nArrLen; i++ )
+ {
+ delete pAnyArr[i];
+ pAnyArr[ i ] = 0;
+ }
+}
+
+sal_Bool SwStyleProperties_Impl::GetProperty(const ::rtl::OUString& rName, uno::Any*& rpAny )
+{
+ sal_Bool bRet = sal_False;
+ sal_uInt16 nPos = 0;
+ PropertyEntryVector_t::const_iterator aIt = aPropertyEntries.begin();
+ while( aIt != aPropertyEntries.end() )
+ {
+ if( rName == aIt->sName )
+ {
+ rpAny = pAnyArr[nPos];
+ bRet = sal_True;
+ break;
+ }
+ ++nPos;
+ ++aIt;
+ }
+
+ return bRet;
+}
+
+void SwStyleProperties_Impl::GetProperty( const OUString &rPropertyName, const uno::Reference < beans::XPropertySet > &rxPropertySet, uno::Any & rAny )
+{
+ rAny = rxPropertySet->getPropertyValue( rPropertyName );
+}
+
+const uno::Sequence< sal_Int8 > & SwXStyle::getUnoTunnelId()
+{
+ static uno::Sequence< sal_Int8 > aSeq = ::CreateUnoTunnelId();
+ return aSeq;
+}
+
+sal_Int64 SAL_CALL SwXStyle::getSomething( const uno::Sequence< sal_Int8 >& rId )
+ throw(uno::RuntimeException)
+{
+ if( rId.getLength() == 16
+ && 0 == rtl_compareMemory( getUnoTunnelId().getConstArray(),
+ rId.getConstArray(), 16 ) )
+ {
+ return sal::static_int_cast< sal_Int64 >( reinterpret_cast< sal_IntPtr >(this) );
+ }
+ return 0;
+}
+
+TYPEINIT1(SwXStyle, SfxListener);
+
+OUString SwXStyle::getImplementationName(void) throw( uno::RuntimeException )
+{
+ return C2U("SwXStyle");
+}
+
+sal_Bool SwXStyle::supportsService(const OUString& rServiceName) throw( uno::RuntimeException )
+{
+ sal_Bool bRet = C2U("com.sun.star.style.Style") == rServiceName;
+ if(!bRet && SFX_STYLE_FAMILY_CHAR == eFamily)
+ bRet = !rServiceName.compareToAscii("com.sun.star.style.CharacterStyle")||
+ !rServiceName.compareToAscii("com.sun.star.style.CharacterProperties")||
+ !rServiceName.compareToAscii("com.sun.star.style.CharacterPropertiesAsian")||
+ !rServiceName.compareToAscii("com.sun.star.style.CharacterPropertiesComplex");
+ if(!bRet && SFX_STYLE_FAMILY_PARA == eFamily)
+ bRet = (C2U("com.sun.star.style.ParagraphStyle") == rServiceName)||
+ (C2U("com.sun.star.style.ParagraphProperties") == rServiceName) ||
+ (C2U("com.sun.star.style.ParagraphPropertiesAsian") == rServiceName) ||
+ (C2U("com.sun.star.style.ParagraphPropertiesComplex") == rServiceName);
+ if(!bRet && SFX_STYLE_FAMILY_PAGE == eFamily)
+ bRet = (C2U("com.sun.star.style.PageStyle") == rServiceName)||
+ (C2U("com.sun.star.style.PageProperties") == rServiceName);
+
+ return bRet;
+}
+
+uno::Sequence< OUString > SwXStyle::getSupportedServiceNames(void) throw( uno::RuntimeException )
+{
+ long nCount = 1;
+ if(SFX_STYLE_FAMILY_PARA == eFamily)
+ {
+ nCount = 5;
+ if(bIsConditional)
+ nCount++;
+ }
+ else if(SFX_STYLE_FAMILY_CHAR == eFamily)
+ nCount = 5;
+ else if(SFX_STYLE_FAMILY_PAGE == eFamily)
+ nCount = 3;
+ uno::Sequence< OUString > aRet(nCount);
+ OUString* pArray = aRet.getArray();
+ pArray[0] = C2U("com.sun.star.style.Style");
+ switch(eFamily)
+ {
+ case SFX_STYLE_FAMILY_CHAR:
+ pArray[1] = C2U("com.sun.star.style.CharacterStyle");
+ pArray[2] = C2U("com.sun.star.style.CharacterProperties");
+ pArray[3] = C2U("com.sun.star.style.CharacterPropertiesAsian");
+ pArray[4] = C2U("com.sun.star.style.CharacterPropertiesComplex");
+ break;
+ case SFX_STYLE_FAMILY_PAGE:
+ pArray[1] = C2U("com.sun.star.style.PageStyle");
+ pArray[2] = C2U("com.sun.star.style.PageProperties");
+ break;
+ case SFX_STYLE_FAMILY_PARA:
+ pArray[1] = C2U("com.sun.star.style.ParagraphStyle");
+ pArray[2] = C2U("com.sun.star.style.ParagraphProperties");
+ pArray[3] = C2U("com.sun.star.style.ParagraphPropertiesAsian");
+ pArray[4] = C2U("com.sun.star.style.ParagraphPropertiesComplex");
+ if(bIsConditional)
+ pArray[5] = C2U("com.sun.star.style.ConditionalParagraphStyle");
+ break;
+
+ default:
+ ;
+ }
+ return aRet;
+}
+
+SwXStyle::SwXStyle( SwDoc *pDoc, SfxStyleFamily eFam, sal_Bool bConditional) :
+ m_pDoc( pDoc ),
+ pBasePool(0),
+ eFamily(eFam),
+ bIsDescriptor(sal_True),
+ bIsConditional(bConditional)
+{
+ // Register ourselves as a listener to the document (via the page descriptor)
+ pDoc->GetPageDescFromPool(RES_POOLPAGE_STANDARD)->Add(this);
+ // get the property set for the default style data
+ // First get the model
+ uno::Reference < frame::XModel > xModel = pDoc->GetDocShell()->GetBaseModel();
+ // Ask the model for it's family supplier interface
+ uno::Reference < style::XStyleFamiliesSupplier > xFamilySupplier ( xModel, uno::UNO_QUERY );
+ // Get the style families
+ uno::Reference < container::XNameAccess > xFamilies = xFamilySupplier->getStyleFamilies();
+
+ uno::Any aAny;
+ sal_uInt16 nMapId = PROPERTY_MAP_NUM_STYLE;
+ switch( eFamily )
+ {
+ case SFX_STYLE_FAMILY_CHAR:
+ {
+ nMapId = PROPERTY_MAP_CHAR_STYLE;
+ aAny = xFamilies->getByName ( OUString ( RTL_CONSTASCII_USTRINGPARAM ( "CharacterStyles" ) ) );
+ // Get the Frame family (and keep it for later)
+ aAny >>= mxStyleFamily;
+ }
+ break;
+ case SFX_STYLE_FAMILY_PARA:
+ {
+ nMapId = bIsConditional ? PROPERTY_MAP_CONDITIONAL_PARA_STYLE : PROPERTY_MAP_PARA_STYLE;
+ aAny = xFamilies->getByName ( OUString ( RTL_CONSTASCII_USTRINGPARAM ( "ParagraphStyles" ) ) );
+ // Get the Frame family (and keep it for later)
+ aAny >>= mxStyleFamily;
+ aAny = mxStyleFamily->getByName ( OUString ( RTL_CONSTASCII_USTRINGPARAM ( "Standard" ) ) );
+ aAny >>= mxStyleData;
+ }
+ break;
+ case SFX_STYLE_FAMILY_PAGE:
+ {
+ nMapId = PROPERTY_MAP_PAGE_STYLE;
+ aAny = xFamilies->getByName ( OUString ( RTL_CONSTASCII_USTRINGPARAM ( "PageStyles" ) ) );
+ // Get the Frame family (and keep it for later)
+ aAny >>= mxStyleFamily;
+ aAny = mxStyleFamily->getByName ( OUString ( RTL_CONSTASCII_USTRINGPARAM ( "Standard" ) ) );
+ aAny >>= mxStyleData;
+ }
+ break;
+ case SFX_STYLE_FAMILY_FRAME :
+ {
+ nMapId = PROPERTY_MAP_FRAME_STYLE;
+ }
+ break;
+ case SFX_STYLE_FAMILY_PSEUDO:
+ {
+ nMapId = PROPERTY_MAP_NUM_STYLE;
+ }
+ break;
+
+ default:
+ ;
+ }
+ pPropImpl = new SwStyleProperties_Impl(aSwMapProvider.GetPropertySet(nMapId)->getPropertyMap());
+}
+
+SwXStyle::SwXStyle(SfxStyleSheetBasePool& rPool, SfxStyleFamily eFam,
+ SwDoc* pDoc, const String& rStyleName) :
+ m_pDoc(pDoc),
+ sStyleName(rStyleName),
+ pBasePool(&rPool),
+ eFamily(eFam),
+ bIsDescriptor(sal_False),
+ bIsConditional(sal_False),
+ pPropImpl(0)
+{
+ StartListening(rPool);
+ if(eFam == SFX_STYLE_FAMILY_PARA)
+ {
+ pBasePool->SetSearchMask(eFamily, SFXSTYLEBIT_ALL );
+ SfxStyleSheetBase* pBase = pBasePool->Find(sStyleName);
+ DBG_ASSERT(pBase, "where is the style?" );
+ if(pBase)
+ {
+ const sal_uInt16 nId = SwStyleNameMapper::GetPoolIdFromUIName(sStyleName, nsSwGetPoolIdFromName::GET_POOLID_TXTCOLL);
+ if(nId != USHRT_MAX)
+ bIsConditional = ::IsConditionalByPoolId( nId );
+ else
+ bIsConditional = RES_CONDTXTFMTCOLL == ((SwDocStyleSheet*)pBase)->GetCollection()->Which();
+ }
+ }
+}
+
+SwXStyle::~SwXStyle()
+{
+ if(pBasePool)
+ EndListening(*pBasePool);
+ delete pPropImpl;
+}
+
+void SwXStyle::Modify( const SfxPoolItem* pOld, const SfxPoolItem *pNew)
+{
+ ClientModify(this, pOld, pNew);
+ if(!GetRegisteredIn())
+ {
+ m_pDoc = 0;
+ mxStyleData.clear();
+ mxStyleFamily.clear();
+ }
+}
+
+OUString SwXStyle::getName(void) throw( uno::RuntimeException )
+{
+ SolarMutexGuard aGuard;
+ String aString;
+ if(pBasePool)
+ {
+ pBasePool->SetSearchMask(eFamily, SFXSTYLEBIT_ALL );
+ SfxStyleSheetBase* pBase = pBasePool->Find(sStyleName);
+ DBG_ASSERT(pBase, "where is the style?" );
+ if(!pBase)
+ throw uno::RuntimeException();
+ SwStyleNameMapper::FillProgName(pBase->GetName(), aString, lcl_GetSwEnumFromSfxEnum ( eFamily ), sal_True);
+ }
+ else
+ aString = sStyleName;
+ return OUString (aString);
+}
+
+void SwXStyle::setName(const OUString& rName) throw( uno::RuntimeException )
+{
+ SolarMutexGuard aGuard;
+ if(pBasePool)
+ {
+ pBasePool->SetSearchMask(eFamily, SFXSTYLEBIT_ALL );
+ SfxStyleSheetBase* pBase = pBasePool->Find(sStyleName);
+ DBG_ASSERT(pBase, "where is the style?" );
+ sal_Bool bExcept = sal_True;
+ if(pBase && pBase->IsUserDefined())
+ {
+ rtl::Reference< SwDocStyleSheet > xTmp( new SwDocStyleSheet( *(SwDocStyleSheet*)pBase ) );
+ bExcept = !xTmp->SetName(rName);
+ if(!bExcept)
+ sStyleName = String(rName);
+ }
+ if(bExcept)
+ throw uno::RuntimeException();
+ }
+ else
+ sStyleName = String(rName);
+}
+
+sal_Bool SwXStyle::isUserDefined(void) throw( uno::RuntimeException )
+{
+ SolarMutexGuard aGuard;
+ sal_Bool bRet = sal_False;
+ if(pBasePool)
+ {
+ pBasePool->SetSearchMask(eFamily, SFXSTYLEBIT_ALL );
+ SfxStyleSheetBase* pBase = pBasePool->Find(sStyleName);
+ //if it is not found it must be non user defined
+ if(pBase)
+ bRet = pBase->IsUserDefined();
+ }
+ else
+ throw uno::RuntimeException();
+ return bRet;
+}
+
+sal_Bool SwXStyle::isInUse(void) throw( uno::RuntimeException )
+{
+ SolarMutexGuard aGuard;
+ sal_Bool bRet = sal_False;
+ if(pBasePool)
+ {
+ pBasePool->SetSearchMask(eFamily, SFXSTYLEBIT_USED);
+ SfxStyleSheetBase* pBase = pBasePool->Find(sStyleName);
+ if(pBase)
+ bRet = pBase->IsUsed();
+ }
+ else
+ throw uno::RuntimeException();
+ return bRet;
+}
+
+OUString SwXStyle::getParentStyle(void) throw( uno::RuntimeException )
+{
+ SolarMutexGuard aGuard;
+ String aString;
+ if(pBasePool)
+ {
+ pBasePool->SetSearchMask(eFamily, SFXSTYLEBIT_ALL);
+ SfxStyleSheetBase* pBase = pBasePool->Find(sStyleName);
+ if(pBase)
+ aString = pBase->GetParent();
+ }
+ else if(bIsDescriptor)
+ aString = sParentStyleName;
+ else
+ throw uno::RuntimeException();
+ SwStyleNameMapper::FillProgName(aString, aString, lcl_GetSwEnumFromSfxEnum ( eFamily ), sal_True );
+ return OUString ( aString );
+}
+
+void SwXStyle::setParentStyle(const OUString& rParentStyle)
+ throw( container::NoSuchElementException, uno::RuntimeException )
+{
+ SolarMutexGuard aGuard;
+ String sParentStyle;
+ SwStyleNameMapper::FillUIName(rParentStyle, sParentStyle, lcl_GetSwEnumFromSfxEnum ( eFamily ), sal_True );
+ if(pBasePool)
+ {
+ pBasePool->SetSearchMask(eFamily);
+ sal_Bool bExcept = sal_False;
+ SfxStyleSheetBase* pBase = pBasePool->Find(sStyleName);
+ if(pBase)
+ {
+ rtl::Reference< SwDocStyleSheet > xBase( new SwDocStyleSheet(*(SwDocStyleSheet*)pBase) );
+ //make it a 'real' style - necessary for pooled styles
+ xBase->GetItemSet();
+ if(xBase->GetParent() != sParentStyle)
+ {
+ bExcept = !xBase->SetParent(sParentStyle);
+ }
+ }
+ else
+ bExcept = sal_True;
+ if(bExcept)
+ throw uno::RuntimeException();
+ }
+ else if(bIsDescriptor)
+ {
+ sParentStyleName = String(sParentStyle);
+ try
+ {
+ uno::Any aAny = mxStyleFamily->getByName ( sParentStyle );
+ aAny >>= mxStyleData;
+ }
+ catch ( container::NoSuchElementException& )
+ {
+ }
+ catch ( lang::WrappedTargetException& )
+ {
+ }
+ catch ( uno::RuntimeException& )
+ {
+ }
+ }
+ else
+ throw uno::RuntimeException();
+}
+
+uno::Reference< beans::XPropertySetInfo > lcl_getPropertySetInfo( SfxStyleFamily eFamily, sal_Bool bIsConditional )
+{
+ uno::Reference< beans::XPropertySetInfo > xRet;
+ switch( eFamily )
+ {
+ case SFX_STYLE_FAMILY_CHAR:
+ {
+ static uno::Reference< beans::XPropertySetInfo > xCharRef;
+ if(!xCharRef.is())
+ {
+ xCharRef = aSwMapProvider.GetPropertySet(PROPERTY_MAP_CHAR_STYLE)->getPropertySetInfo();
+ }
+ xRet = xCharRef;
+ }
+ break;
+ case SFX_STYLE_FAMILY_PARA:
+ {
+ static uno::Reference< beans::XPropertySetInfo > xParaRef;
+ if(!xParaRef.is())
+ {
+ sal_uInt16 nMapId = bIsConditional ? PROPERTY_MAP_CONDITIONAL_PARA_STYLE : PROPERTY_MAP_PARA_STYLE;
+ xParaRef = aSwMapProvider.GetPropertySet(nMapId)->getPropertySetInfo();
+ }
+ xRet = xParaRef;
+ }
+ break;
+ case SFX_STYLE_FAMILY_PAGE :
+ {
+ static uno::Reference< beans::XPropertySetInfo > xPageRef;
+ if(!xPageRef.is())
+ {
+ xPageRef = aSwMapProvider.GetPropertySet(PROPERTY_MAP_PAGE_STYLE)->getPropertySetInfo();
+ }
+ xRet = xPageRef;
+ }
+ break;
+ case SFX_STYLE_FAMILY_FRAME :
+ {
+ static uno::Reference< beans::XPropertySetInfo > xFrameRef;
+ if(!xFrameRef.is())
+ {
+ xFrameRef = aSwMapProvider.GetPropertySet(PROPERTY_MAP_FRAME_STYLE)->getPropertySetInfo();
+ }
+ xRet = xFrameRef;
+ }
+ break;
+ case SFX_STYLE_FAMILY_PSEUDO:
+ {
+ static uno::Reference< beans::XPropertySetInfo > xNumRef;
+ if(!xNumRef.is())
+ {
+ xNumRef = aSwMapProvider.GetPropertySet(PROPERTY_MAP_NUM_STYLE)->getPropertySetInfo();
+ }
+ xRet = xNumRef;
+ }
+ break;
+
+ default:
+ ;
+ }
+ return xRet;
+}
+
+uno::Reference< beans::XPropertySetInfo > SwXStyle::getPropertySetInfo(void)
+ throw( uno::RuntimeException )
+{
+ return lcl_getPropertySetInfo( eFamily, bIsConditional );
+}
+
+void SwXStyle::ApplyDescriptorProperties()
+{
+ bIsDescriptor = sal_False;
+ mxStyleData.clear();
+ mxStyleFamily.clear();
+
+ const PropertyEntryVector_t& rPropertyVector = pPropImpl->GetPropertyVector();
+ PropertyEntryVector_t::const_iterator aIt = rPropertyVector.begin();
+ while(aIt != rPropertyVector.end())
+ {
+ uno::Any* pAny;
+ pPropImpl->GetProperty(aIt->sName, pAny);
+ if(pAny)
+ setPropertyValue(aIt->sName, *pAny);
+ ++aIt;
+ }
+}
+
+struct SwStyleBase_Impl
+{
+ SwDoc& rDoc;
+
+ const SwPageDesc* pOldPageDesc;
+
+ rtl::Reference< SwDocStyleSheet > mxNewBase;
+ SfxItemSet* pItemSet;
+
+ const String& rStyleName;
+ sal_uInt16 nPDescPos;
+
+ SwStyleBase_Impl(SwDoc& rSwDoc, const String& rName) :
+ rDoc(rSwDoc),
+ pOldPageDesc(0),
+ pItemSet(0),
+ rStyleName(rName),
+ nPDescPos(0xffff)
+ {}
+
+ ~SwStyleBase_Impl(){ delete pItemSet; }
+
+ sal_Bool HasItemSet() {return mxNewBase.is();}
+ SfxItemSet& GetItemSet()
+ {
+ DBG_ASSERT(mxNewBase.is(), "no SwDocStyleSheet available");
+ if(!pItemSet)
+ pItemSet = new SfxItemSet(mxNewBase->GetItemSet());
+ return *pItemSet;
+ }
+
+ const SwPageDesc& GetOldPageDesc();
+};
+
+const SwPageDesc& SwStyleBase_Impl::GetOldPageDesc()
+{
+ if(!pOldPageDesc)
+ {
+ sal_uInt16 i;
+ sal_uInt16 nPDescCount = rDoc.GetPageDescCnt();
+ for(i = 0; i < nPDescCount; i++)
+ {
+ const SwPageDesc& rDesc =
+ const_cast<const SwDoc &>(rDoc).GetPageDesc( i );
+ if(rDesc.GetName() == rStyleName)
+ {
+ pOldPageDesc = & rDesc;
+ nPDescPos = i;
+ break;
+ }
+ }
+ if(!pOldPageDesc)
+ {
+ for(i = RC_POOLPAGEDESC_BEGIN; i <= STR_POOLPAGE_LANDSCAPE; ++i)
+ {
+ const String aFmtName(SW_RES(i));
+ if(aFmtName == rStyleName)
+ {
+ pOldPageDesc = rDoc.GetPageDescFromPool( static_cast< sal_uInt16 >(RES_POOLPAGE_BEGIN + i - RC_POOLPAGEDESC_BEGIN) );
+ break;
+ }
+ }
+ for(i = 0; i < nPDescCount + 1; i++)
+ {
+ const SwPageDesc& rDesc =
+ const_cast<const SwDoc &>(rDoc).GetPageDesc( i );
+ if(rDesc.GetName() == rStyleName)
+ {
+ nPDescPos = i;
+ break;
+ }
+ }
+ }
+ }
+ return *pOldPageDesc;
+}
+
+void lcl_SetStyleProperty(const SfxItemPropertySimpleEntry& rEntry,
+ const SfxItemPropertySet& rPropSet,
+ const uno::Any& rValue,
+ SwStyleBase_Impl& rBase,
+ SfxStyleSheetBasePool* pBasePool,
+ SwDoc* pDoc,
+ SfxStyleFamily eFamily)
+ throw(beans::PropertyVetoException, lang::IllegalArgumentException,
+ lang::WrappedTargetException, uno::RuntimeException)
+
+{
+ switch(rEntry.nWID)
+ {
+ case RES_PAPER_BIN:
+ {
+ SfxPrinter *pPrinter = pDoc->getPrinter( true );
+ OUString sTmp;
+ sal_uInt16 nBin = USHRT_MAX;
+ if ( !( rValue >>= sTmp ) )
+ throw lang::IllegalArgumentException();
+ if ( sTmp.equalsAsciiL ( RTL_CONSTASCII_STRINGPARAM ( "[From printer settings]" ) ) )
+ nBin = USHRT_MAX-1;
+ else if ( pPrinter )
+ {
+ for (sal_uInt16 i=0, nEnd = pPrinter->GetPaperBinCount(); i < nEnd; i++ )
+ {
+ if (sTmp == OUString ( pPrinter->GetPaperBinName ( i ) ) )
+ {
+ nBin = i;
+ break;
+ }
+ }
+ }
+ if ( nBin == USHRT_MAX )
+ throw lang::IllegalArgumentException();
+ else
+ {
+ SfxItemSet& rStyleSet = rBase.GetItemSet();
+ SfxItemSet aSet(*rStyleSet.GetPool(), rEntry.nWID, rEntry.nWID);
+ aSet.SetParent(&rStyleSet);
+ rPropSet.setPropertyValue(rEntry, uno::makeAny ( static_cast < sal_Int8 > ( nBin == USHRT_MAX-1 ? -1 : nBin ) ), aSet);
+ rStyleSet.Put(aSet);
+ }
+ }
+ break;
+ case FN_UNO_NUM_RULES: //Sonderbehandlung fuer das SvxNumRuleItem:
+ {
+ if(rValue.getValueType() == ::getCppuType((uno::Reference< container::XIndexReplace>*)0) )
+ {
+ uno::Reference< container::XIndexReplace > * pxRulesRef =
+ (uno::Reference< container::XIndexReplace > *)rValue.getValue();
+
+ uno::Reference<lang::XUnoTunnel> xNumberTunnel( *pxRulesRef, uno::UNO_QUERY);
+
+ SwXNumberingRules* pSwXRules = 0;
+ if(xNumberTunnel.is())
+ {
+ pSwXRules = reinterpret_cast< SwXNumberingRules * >(
+ sal::static_int_cast< sal_IntPtr >(xNumberTunnel->getSomething( SwXNumberingRules::getUnoTunnelId()) ));
+ }
+ if(pSwXRules)
+ {
+ const String* pCharStyleNames = pSwXRules->GetNewCharStyleNames();
+ const String* pBulletFontNames = pSwXRules->GetBulletFontNames();
+
+ SwNumRule aSetRule(*pSwXRules->GetNumRule());
+ const SwCharFmts* pFmts = pDoc->GetCharFmts();
+ sal_uInt16 nChCount = pFmts->Count();
+ for(sal_uInt16 i = 0; i < MAXLEVEL; i++)
+ {
+
+ const SwNumFmt* pFmt = aSetRule.GetNumFmt( i );
+ if(pFmt)
+ {
+ SwNumFmt aFmt(*pFmt);
+ if(
+ pCharStyleNames[i] != SwXNumberingRules::GetInvalidStyle() &&
+ ((pCharStyleNames[i].Len() && !pFmt->GetCharFmt()) ||
+ (pCharStyleNames[i].Len() &&
+ pFmt->GetCharFmt()->GetName() != pCharStyleNames[i]) ))
+ {
+
+ SwCharFmt* pCharFmt = 0;
+ if(pCharStyleNames[i].Len())
+ {
+ for(sal_uInt16 j = 0; j< nChCount; j++)
+ {
+ SwCharFmt* pTmp = (*pFmts)[j];
+ if(pTmp->GetName() == pCharStyleNames[i])
+ {
+ pCharFmt = pTmp;
+ break;
+ }
+ }
+ if(!pCharFmt)
+ {
+
+ SfxStyleSheetBase* pBase;
+ pBase = ((SfxStyleSheetBasePool*)pBasePool)->Find(pCharStyleNames[i], SFX_STYLE_FAMILY_CHAR);
+ if(!pBase)
+ pBase = &pBasePool->Make(pCharStyleNames[i], SFX_STYLE_FAMILY_CHAR);
+ pCharFmt = ((SwDocStyleSheet*)pBase)->GetCharFmt();
+
+ }
+
+ aFmt.SetCharFmt( pCharFmt );
+ }
+ }
+ //jetzt nochmal fuer Fonts
+ if(pBulletFontNames[i] != SwXNumberingRules::GetInvalidStyle() &&
+ ((pBulletFontNames[i].Len() && !pFmt->GetBulletFont()) ||
+ (pBulletFontNames[i].Len() &&
+ pFmt->GetBulletFont()->GetName() != pBulletFontNames[i]) ))
+ {
+ const SvxFontListItem* pFontListItem =
+ (const SvxFontListItem* )pDoc->GetDocShell()
+ ->GetItem( SID_ATTR_CHAR_FONTLIST );
+ const FontList* pList = pFontListItem->GetFontList();
+ FontInfo aInfo = pList->Get(
+ pBulletFontNames[i],WEIGHT_NORMAL, ITALIC_NONE);
+ Font aFont(aInfo);
+ aFmt.SetBulletFont(&aFont);
+ }
+ aSetRule.Set( i, &aFmt );
+ }
+ }
+ rBase.mxNewBase->SetNumRule(aSetRule);
+ }
+ }
+ else
+ throw lang::IllegalArgumentException();
+ }
+ break;
+ case RES_PARATR_OUTLINELEVEL:
+ {
+ sal_Int16 nLevel = 0;
+ rValue >>= nLevel;
+ if( 0 <= nLevel && nLevel <= MAXLEVEL)
+ rBase.mxNewBase->GetCollection()->SetAttrOutlineLevel( nLevel );
+ }
+ break;
+ case FN_UNO_FOLLOW_STYLE:
+ {
+ OUString sTmp;
+ rValue >>= sTmp;
+ String aString;
+ SwStyleNameMapper::FillUIName(sTmp, aString, lcl_GetSwEnumFromSfxEnum ( eFamily ), sal_True ) ;
+ rBase.mxNewBase->SetFollow( aString );
+ }
+ break;
+ case RES_PAGEDESC :
+ if( MID_PAGEDESC_PAGEDESCNAME != rEntry.nMemberId)
+ goto put_itemset;
+ {
+ // Sonderbehandlung RES_PAGEDESC
+ if(rValue.getValueType() != ::getCppuType((const OUString*)0))
+ throw lang::IllegalArgumentException();
+ SfxItemSet& rStyleSet = rBase.GetItemSet();
+
+ SwFmtPageDesc* pNewDesc = 0;
+ const SfxPoolItem* pItem;
+ if(SFX_ITEM_SET == rStyleSet.GetItemState( RES_PAGEDESC, sal_True, &pItem ) )
+ {
+ pNewDesc = new SwFmtPageDesc(*((SwFmtPageDesc*)pItem));
+ }
+ if(!pNewDesc)
+ pNewDesc = new SwFmtPageDesc();
+ OUString uDescName;
+ rValue >>= uDescName;
+ String sDescName;
+ SwStyleNameMapper::FillUIName(uDescName, sDescName, nsSwGetPoolIdFromName::GET_POOLID_PAGEDESC, sal_True );
+ if(!pNewDesc->GetPageDesc() || pNewDesc->GetPageDesc()->GetName() != sDescName)
+ {
+ sal_Bool bPut = sal_False;
+ if(sDescName.Len())
+ {
+ SwPageDesc* pPageDesc = ::GetPageDescByName_Impl(*pDoc, sDescName);
+ if(pPageDesc)
+ {
+ pNewDesc->RegisterToPageDesc( *pPageDesc );
+ bPut = sal_True;
+ }
+ else
+ {
+ throw lang::IllegalArgumentException();
+ }
+ }
+ if(!bPut)
+ {
+ rStyleSet.ClearItem(RES_BREAK);
+ rStyleSet.Put(SwFmtPageDesc());
+ }
+ else
+ rStyleSet.Put(*pNewDesc);
+ }
+ delete pNewDesc;
+ }
+ break;
+ case FN_UNO_IS_AUTO_UPDATE:
+ {
+ sal_Bool bAuto = *(sal_Bool*)rValue.getValue();
+ if(SFX_STYLE_FAMILY_PARA == eFamily)
+ rBase.mxNewBase->GetCollection()->SetAutoUpdateFmt(bAuto);
+ else if(SFX_STYLE_FAMILY_FRAME == eFamily)
+ rBase.mxNewBase->GetFrmFmt()->SetAutoUpdateFmt(bAuto);
+ }
+ break;
+ case FN_UNO_PARA_STYLE_CONDITIONS:
+ {
+ uno::Sequence< beans::NamedValue > aSeq;
+ if (!(rValue >>= aSeq))
+ throw lang::IllegalArgumentException();
+
+ DBG_ASSERT(COND_COMMAND_COUNT == 28,
+ "invalid size of comman count?");
+ const beans::NamedValue *pSeq = aSeq.getConstArray();
+ sal_Int32 nLen = aSeq.getLength();
+
+ sal_Bool bFailed = sal_False;
+ SwCondCollItem aCondItem;
+ for(sal_uInt16 i = 0; i < nLen; i++)
+ {
+ OUString aTmp;
+ if ((pSeq[i].Value >>= aTmp))
+ {
+ // get UI style name from programmatic style name
+ String aStyleName;
+ SwStyleNameMapper::FillUIName( aTmp, aStyleName, lcl_GetSwEnumFromSfxEnum ( eFamily ), sal_True );
+
+ //
+ // check for correct context and style name
+ //
+ sal_Int16 nIdx = GetCommandContextIndex( pSeq[i].Name );
+
+ pBasePool->SetSearchMask( SFX_STYLE_FAMILY_PARA, SFXSTYLEBIT_ALL );
+ sal_Bool bStyleFound = sal_False;
+ const SfxStyleSheetBase* pBase = pBasePool->First();
+ while (pBase && !bStyleFound)
+ {
+ if(pBase->GetName() == aStyleName)
+ bStyleFound = sal_True;
+ pBase = pBasePool->Next();
+ }
+
+ if (nIdx == -1 || !bStyleFound)
+ {
+ bFailed = sal_True;
+ break;
+ }
+
+ aCondItem.SetStyle( &aStyleName, nIdx);
+ }
+ else
+ bFailed = sal_True;
+ }
+ if (bFailed)
+ throw lang::IllegalArgumentException();
+ rBase.GetItemSet().Put( aCondItem );
+ }
+ break;
+ case FN_UNO_CATEGORY:
+ {
+ if(!rBase.mxNewBase->IsUserDefined())
+ throw lang::IllegalArgumentException();
+ short nSet = 0;
+ rValue >>= nSet;
+
+ sal_uInt16 nId;
+ switch( nSet )
+ {
+ case style::ParagraphStyleCategory::TEXT:
+ nId = SWSTYLEBIT_TEXT;
+ break;
+ case style::ParagraphStyleCategory::CHAPTER:
+ nId = SWSTYLEBIT_CHAPTER;
+ break;
+ case style::ParagraphStyleCategory::LIST:
+ nId = SWSTYLEBIT_LIST;
+ break;
+ case style::ParagraphStyleCategory::INDEX:
+ nId = SWSTYLEBIT_IDX;
+ break;
+ case style::ParagraphStyleCategory::EXTRA:
+ nId = SWSTYLEBIT_EXTRA;
+ break;
+ case style::ParagraphStyleCategory::HTML:
+ nId = SWSTYLEBIT_HTML;
+ break;
+ default: throw lang::IllegalArgumentException();
+ }
+ rBase.mxNewBase->SetMask( nId|SFXSTYLEBIT_USERDEF );
+ }
+ break;
+ case SID_SWREGISTER_COLLECTION:
+ {
+ OUString sName;
+ rValue >>= sName;
+ SwRegisterItem aReg( sName.getLength() != 0);
+ aReg.SetWhich(SID_SWREGISTER_MODE);
+ rBase.GetItemSet().Put(aReg);
+ String aString;
+ SwStyleNameMapper::FillUIName(sName, aString, nsSwGetPoolIdFromName::GET_POOLID_TXTCOLL, sal_True);
+
+ rBase.GetItemSet().Put(SfxStringItem(SID_SWREGISTER_COLLECTION, aString ) );
+ }
+ break;
+ case RES_TXTATR_CJK_RUBY:
+ if(MID_RUBY_CHARSTYLE == rEntry.nMemberId )
+ {
+ OUString sTmp;
+ if(rValue >>= sTmp)
+ {
+ SfxItemSet& rStyleSet = rBase.GetItemSet();
+ SwFmtRuby* pRuby = 0;
+ const SfxPoolItem* pItem;
+ if(SFX_ITEM_SET == rStyleSet.GetItemState( RES_TXTATR_CJK_RUBY, sal_True, &pItem ) )
+ pRuby = new SwFmtRuby(*((SwFmtRuby*)pItem));
+ if(!pRuby)
+ pRuby = new SwFmtRuby(aEmptyStr);
+ String sStyle;
+ SwStyleNameMapper::FillUIName(sTmp, sStyle, nsSwGetPoolIdFromName::GET_POOLID_CHRFMT, sal_True );
+ pRuby->SetCharFmtName( sTmp );
+ pRuby->SetCharFmtId( 0 );
+ if(sTmp.getLength())
+ {
+ sal_uInt16 nId = SwStyleNameMapper::GetPoolIdFromUIName( sTmp, nsSwGetPoolIdFromName::GET_POOLID_CHRFMT );
+ pRuby->SetCharFmtId(nId);
+ }
+ rStyleSet.Put(*pRuby);
+ delete pRuby;
+ }
+ else
+ throw lang::IllegalArgumentException();
+ }
+ goto put_itemset;
+ case RES_PARATR_DROP:
+ {
+ if( MID_DROPCAP_CHAR_STYLE_NAME == rEntry.nMemberId)
+ {
+ if(rValue.getValueType() == ::getCppuType((const OUString*)0))
+ {
+ SfxItemSet& rStyleSet = rBase.GetItemSet();
+
+ SwFmtDrop* pDrop = 0;
+ const SfxPoolItem* pItem;
+ if(SFX_ITEM_SET == rStyleSet.GetItemState( RES_PARATR_DROP, sal_True, &pItem ) )
+ pDrop = new SwFmtDrop(*((SwFmtDrop*)pItem));
+ if(!pDrop)
+ pDrop = new SwFmtDrop();
+ OUString uStyle;
+ rValue >>= uStyle;
+ String sStyle;
+ SwStyleNameMapper::FillUIName(uStyle, sStyle, nsSwGetPoolIdFromName::GET_POOLID_CHRFMT, sal_True );
+ SwDocStyleSheet* pStyle =
+ (SwDocStyleSheet*)pDoc->GetDocShell()->GetStyleSheetPool()->Find(sStyle, SFX_STYLE_FAMILY_CHAR);
+ if(pStyle)
+ pDrop->SetCharFmt(pStyle->GetCharFmt());
+ else
+ throw lang::IllegalArgumentException();
+ rStyleSet.Put(*pDrop);
+ delete pDrop;
+ }
+ else
+ throw lang::IllegalArgumentException();
+ break;
+ }
+ }
+ //no break!
+ default:
+put_itemset:
+ {
+ SfxItemSet& rStyleSet = rBase.GetItemSet();
+ SfxItemSet aSet(*rStyleSet.GetPool(), rEntry.nWID, rEntry.nWID);
+ aSet.SetParent(&rStyleSet);
+ rPropSet.setPropertyValue(rEntry, rValue, aSet);
+ rStyleSet.Put(aSet);
+ // #i70223#
+ if ( SFX_STYLE_FAMILY_PARA == eFamily &&
+ rEntry.nWID == RES_PARATR_NUMRULE &&
+ rBase.mxNewBase.is() && rBase.mxNewBase->GetCollection() &&
+ rBase.mxNewBase->GetCollection()->IsAssignedToListLevelOfOutlineStyle() )
+
+ {
+ OUString sNewNumberingRuleName;
+ rValue >>= sNewNumberingRuleName;
+ String sTmp( sNewNumberingRuleName );
+ if ( sNewNumberingRuleName.getLength() == 0 ||
+ sTmp != pDoc->GetOutlineNumRule()->GetName() )
+ {
+ rBase.mxNewBase->GetCollection()->DeleteAssignmentToListLevelOfOutlineStyle();
+ }
+ }
+ }
+ }
+}
+
+void SAL_CALL SwXStyle::SetPropertyValues_Impl(
+ const uno::Sequence< OUString >& rPropertyNames,
+ const uno::Sequence< uno::Any >& rValues )
+ throw( beans::UnknownPropertyException, beans::PropertyVetoException, lang::IllegalArgumentException,
+ lang::WrappedTargetException, uno::RuntimeException)
+{
+ if ( !m_pDoc )
+ throw uno::RuntimeException();
+ sal_Int8 nPropSetId = PROPERTY_MAP_CHAR_STYLE;
+ switch(eFamily)
+ {
+ case SFX_STYLE_FAMILY_PARA : nPropSetId = bIsConditional ? PROPERTY_MAP_CONDITIONAL_PARA_STYLE : PROPERTY_MAP_PARA_STYLE; break;
+ case SFX_STYLE_FAMILY_FRAME : nPropSetId = PROPERTY_MAP_FRAME_STYLE ;break;
+ case SFX_STYLE_FAMILY_PAGE : nPropSetId = PROPERTY_MAP_PAGE_STYLE ;break;
+ case SFX_STYLE_FAMILY_PSEUDO: nPropSetId = PROPERTY_MAP_NUM_STYLE ;break;
+ default:
+ ;
+ }
+ const SfxItemPropertySet* pPropSet = aSwMapProvider.GetPropertySet(nPropSetId);
+ const SfxItemPropertyMap *pMap = pPropSet->getPropertyMap();
+
+ if(rPropertyNames.getLength() != rValues.getLength())
+ throw lang::IllegalArgumentException();
+
+ const OUString* pNames = rPropertyNames.getConstArray();
+ const uno::Any* pValues = rValues.getConstArray();
+
+ SwStyleBase_Impl aBaseImpl(*m_pDoc, sStyleName);
+ if(pBasePool)
+ {
+ sal_uInt16 nSaveMask = pBasePool->GetSearchMask();
+ pBasePool->SetSearchMask(eFamily);
+ SfxStyleSheetBase* pBase = pBasePool->Find(sStyleName);
+ pBasePool->SetSearchMask(eFamily, nSaveMask );
+ DBG_ASSERT(pBase, "where is the style?" );
+ if(pBase)
+ aBaseImpl.mxNewBase = new SwDocStyleSheet(*(SwDocStyleSheet*)pBase);
+ else
+ throw uno::RuntimeException();
+ }
+
+ for(sal_Int16 nProp = 0; nProp < rPropertyNames.getLength(); nProp++)
+ {
+ const SfxItemPropertySimpleEntry* pEntry = pMap->getByName( pNames[nProp]);
+
+ if(!pEntry ||
+ (!bIsConditional && pNames[nProp].equalsAsciiL(SW_PROP_NAME(UNO_NAME_PARA_STYLE_CONDITIONS))))
+ throw beans::UnknownPropertyException(OUString ( RTL_CONSTASCII_USTRINGPARAM ( "Unknown property: " ) ) + pNames[nProp], static_cast < cppu::OWeakObject * > ( this ) );
+ if ( pEntry->nFlags & beans::PropertyAttribute::READONLY)
+ throw beans::PropertyVetoException ( OUString ( RTL_CONSTASCII_USTRINGPARAM ( "Property is read-only: " ) ) + pNames[nProp], static_cast < cppu::OWeakObject * > ( this ) );
+ if(aBaseImpl.mxNewBase.is())
+ {
+ lcl_SetStyleProperty(*pEntry, *pPropSet, pValues[nProp], aBaseImpl,
+ pBasePool, m_pDoc, eFamily);
+ }
+ else if(bIsDescriptor)
+ {
+ if(!pPropImpl->SetProperty(pNames[nProp], pValues[nProp]))
+ throw lang::IllegalArgumentException();
+ }
+ else
+ throw uno::RuntimeException();
+ }
+ if(aBaseImpl.HasItemSet())
+ aBaseImpl.mxNewBase->SetItemSet(aBaseImpl.GetItemSet());
+}
+
+void SwXStyle::setPropertyValues(
+ const uno::Sequence< OUString >& rPropertyNames,
+ const uno::Sequence< uno::Any >& rValues )
+ throw(beans::PropertyVetoException, lang::IllegalArgumentException,
+ lang::WrappedTargetException, uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+
+ // workaround for bad designed API
+ try
+ {
+ SetPropertyValues_Impl( rPropertyNames, rValues );
+ }
+ catch (beans::UnknownPropertyException &rException)
+ {
+ // wrap the original (here not allowed) exception in
+ // a lang::WrappedTargetException that gets thrown instead.
+ lang::WrappedTargetException aWExc;
+ aWExc.TargetException <<= rException;
+ throw aWExc;
+ }
+}
+
+uno::Any lcl_GetStyleProperty(const SfxItemPropertySimpleEntry& rEntry,
+ const SfxItemPropertySet& rPropSet,
+ SwStyleBase_Impl& rBase,
+ SfxStyleSheetBase* pBase,
+ SfxStyleFamily eFamily,
+ SwDoc *pDoc) throw(uno::RuntimeException)
+{
+ uno::Any aRet;
+ if(FN_UNO_IS_PHYSICAL == rEntry.nWID)
+ {
+ sal_Bool bPhys = pBase != 0;
+ if(pBase)
+ {
+ bPhys = ((SwDocStyleSheet*)pBase)->IsPhysical();
+ // The standard character format is not existing physically
+ if( bPhys && SFX_STYLE_FAMILY_CHAR == eFamily &&
+ ((SwDocStyleSheet*)pBase)->GetCharFmt() &&
+ ((SwDocStyleSheet*)pBase)->GetCharFmt()->IsDefault() )
+ bPhys = sal_False;
+ }
+ aRet.setValue(&bPhys, ::getBooleanCppuType());
+ }
+ else if(pBase)
+ {
+ if(!rBase.mxNewBase.is())
+ rBase.mxNewBase = new SwDocStyleSheet( *(SwDocStyleSheet*)pBase );
+ switch(rEntry.nWID)
+ {
+ case RES_PAPER_BIN:
+ {
+ SfxItemSet& rSet = rBase.GetItemSet();
+ rPropSet.getPropertyValue(rEntry, rSet, aRet);
+ sal_Int8 nBin = 0;
+ aRet >>= nBin;
+ if ( nBin == -1 )
+ aRet <<= OUString ( RTL_CONSTASCII_USTRINGPARAM ( "[From printer settings]" ) );
+ else
+ {
+ SfxPrinter *pPrinter = pDoc->getPrinter( false );
+ OUString sTmp;
+ if (pPrinter )
+ sTmp = pPrinter->GetPaperBinName ( nBin );
+ aRet <<= sTmp;
+ }
+ }
+ break;
+ case FN_UNO_NUM_RULES: //Sonderbehandlung fuer das SvxNumRuleItem:
+ {
+ const SwNumRule* pRule = rBase.mxNewBase->GetNumRule();
+ DBG_ASSERT(pRule, "Wo ist die NumRule?");
+ uno::Reference< container::XIndexReplace > xRules = new SwXNumberingRules(*pRule);
+ aRet.setValue(&xRules, ::getCppuType((uno::Reference<container::XIndexReplace>*)0));
+ }
+ break;
+ case RES_PARATR_OUTLINELEVEL:
+ {
+ DBG_ASSERT( SFX_STYLE_FAMILY_PARA == eFamily, "only paras" );
+ int nLevel = rBase.mxNewBase->GetCollection()->GetAttrOutlineLevel();
+ aRet <<= static_cast<sal_Int16>( nLevel );
+ }
+ break;
+ case FN_UNO_FOLLOW_STYLE:
+ {
+ String aString;
+ SwStyleNameMapper::FillProgName(rBase.mxNewBase->GetFollow(), aString, lcl_GetSwEnumFromSfxEnum ( eFamily ), sal_True);
+ aRet <<= OUString( aString );
+ }
+ break;
+ case RES_PAGEDESC :
+ if( MID_PAGEDESC_PAGEDESCNAME != rEntry.nMemberId)
+ goto query_itemset;
+ {
+ // Sonderbehandlung RES_PAGEDESC
+ const SfxPoolItem* pItem;
+ if(SFX_ITEM_SET == rBase.GetItemSet().GetItemState( RES_PAGEDESC, sal_True, &pItem ) )
+ {
+ const SwPageDesc* pDesc = ((const SwFmtPageDesc*)pItem)->GetPageDesc();
+ if(pDesc)
+ {
+ String aString;
+ SwStyleNameMapper::FillProgName(pDesc->GetName(), aString, nsSwGetPoolIdFromName::GET_POOLID_PAGEDESC, sal_True );
+ aRet <<= OUString( aString );
+ }
+ }
+ }
+ break;
+ case FN_UNO_IS_AUTO_UPDATE:
+ {
+ sal_Bool bAuto = sal_False;
+ if(SFX_STYLE_FAMILY_PARA == eFamily)
+ bAuto = rBase.mxNewBase->GetCollection()->IsAutoUpdateFmt();
+ else if(SFX_STYLE_FAMILY_FRAME == eFamily)
+ bAuto = rBase.mxNewBase->GetFrmFmt()->IsAutoUpdateFmt();
+ aRet.setValue(&bAuto, ::getBooleanCppuType());
+ }
+ break;
+ case FN_UNO_DISPLAY_NAME:
+ {
+ OUString sName(rBase.mxNewBase->GetDisplayName());
+ aRet <<= sName;
+ }
+ break;
+ case FN_UNO_PARA_STYLE_CONDITIONS:
+ {
+ DBG_ASSERT(COND_COMMAND_COUNT == 28,
+ "invalid size of comman count?");
+ uno::Sequence< beans::NamedValue > aSeq(COND_COMMAND_COUNT);
+ beans::NamedValue *pSeq = aSeq.getArray();
+
+ SwFmt *pFmt = ((SwDocStyleSheet*)pBase)->GetCollection();
+ const CommandStruct *pCmds = SwCondCollItem::GetCmds();
+ for (sal_uInt16 n = 0; n < COND_COMMAND_COUNT; ++n)
+ {
+ String aStyleName;
+
+ const SwCollCondition* pCond = 0;
+ if( pFmt && RES_CONDTXTFMTCOLL == pFmt->Which() &&
+ 0 != ( pCond = ((SwConditionTxtFmtColl*)pFmt)->
+ HasCondition( SwCollCondition( 0, pCmds[n].nCnd, pCmds[n].nSubCond ) ) )
+ && pCond->GetTxtFmtColl() )
+ {
+ // get programmatic style name from UI style name
+ aStyleName = pCond->GetTxtFmtColl()->GetName();
+ SwStyleNameMapper::FillProgName(aStyleName, aStyleName, lcl_GetSwEnumFromSfxEnum ( eFamily ), sal_True);
+ }
+
+ pSeq[n].Name = GetCommandContextByIndex(n);
+ pSeq[n].Value <<= rtl::OUString( aStyleName );
+ }
+ aRet <<= aSeq;
+ }
+ break;
+ case FN_UNO_CATEGORY:
+ {
+ sal_uInt16 nPoolId = rBase.mxNewBase->GetCollection()->GetPoolFmtId();
+ short nRet = -1;
+ switch ( COLL_GET_RANGE_BITS & nPoolId )
+ {
+ case COLL_TEXT_BITS:
+ nRet = style::ParagraphStyleCategory::TEXT;
+ break;
+ case COLL_DOC_BITS:
+ nRet = style::ParagraphStyleCategory::CHAPTER;
+ break;
+ case COLL_LISTS_BITS:
+ nRet = style::ParagraphStyleCategory::LIST;
+ break;
+ case COLL_REGISTER_BITS:
+ nRet = style::ParagraphStyleCategory::INDEX;
+ break;
+ case COLL_EXTRA_BITS:
+ nRet = style::ParagraphStyleCategory::EXTRA;
+ break;
+ case COLL_HTML_BITS:
+ nRet = style::ParagraphStyleCategory::HTML;
+ break;
+ }
+ aRet <<= nRet;
+ }
+ break;
+ case SID_SWREGISTER_COLLECTION:
+ {
+ const SwPageDesc *pPageDesc = rBase.mxNewBase->GetPageDesc();
+ const SwTxtFmtColl* pCol = 0;
+ String aString;
+ if( pPageDesc )
+ pCol = pPageDesc->GetRegisterFmtColl();
+ if( pCol )
+ SwStyleNameMapper::FillProgName(
+ pCol->GetName(), aString, nsSwGetPoolIdFromName::GET_POOLID_TXTCOLL, sal_True );
+ aRet <<= OUString ( aString );
+ }
+ break;
+ default:
+query_itemset:
+ {
+ SfxItemSet& rSet = rBase.GetItemSet();
+ rPropSet.getPropertyValue(rEntry, rSet, aRet);
+ }
+ }
+ }
+ else
+ throw uno::RuntimeException();
+ return aRet;
+}
+
+uno::Sequence< uno::Any > SAL_CALL SwXStyle::GetPropertyValues_Impl(
+ const uno::Sequence< OUString > & rPropertyNames )
+ throw( beans::UnknownPropertyException, lang::WrappedTargetException, uno::RuntimeException )
+{
+ if ( !m_pDoc )
+ throw uno::RuntimeException();
+ sal_Int8 nPropSetId = PROPERTY_MAP_CHAR_STYLE;
+ switch(eFamily)
+ {
+ case SFX_STYLE_FAMILY_PARA : nPropSetId = bIsConditional ? PROPERTY_MAP_CONDITIONAL_PARA_STYLE : PROPERTY_MAP_PARA_STYLE; break;
+ case SFX_STYLE_FAMILY_FRAME : nPropSetId = PROPERTY_MAP_FRAME_STYLE ;break;
+ case SFX_STYLE_FAMILY_PAGE : nPropSetId = PROPERTY_MAP_PAGE_STYLE ;break;
+ case SFX_STYLE_FAMILY_PSEUDO: nPropSetId = PROPERTY_MAP_NUM_STYLE ;break;
+ default:
+ ;
+ }
+ const SfxItemPropertySet* pPropSet = aSwMapProvider.GetPropertySet(nPropSetId);
+ const SfxItemPropertyMap *pMap = pPropSet->getPropertyMap();
+
+ const OUString* pNames = rPropertyNames.getConstArray();
+ uno::Sequence< uno::Any > aRet(rPropertyNames.getLength());
+ uno::Any* pRet = aRet.getArray();
+ SwStyleBase_Impl aBase(*m_pDoc, sStyleName);
+ SfxStyleSheetBase* pBase = 0;
+ for(sal_Int32 nProp = 0; nProp < rPropertyNames.getLength(); nProp++)
+ {
+ const SfxItemPropertySimpleEntry* pEntry = pMap->getByName( pNames[nProp]);
+ if(!pEntry ||
+ (!bIsConditional && pNames[nProp].equalsAsciiL(SW_PROP_NAME(UNO_NAME_PARA_STYLE_CONDITIONS))))
+ throw beans::UnknownPropertyException(OUString ( RTL_CONSTASCII_USTRINGPARAM ( "Unknown property: " ) ) + pNames[nProp], static_cast < cppu::OWeakObject * > ( this ) );
+ if(pBasePool)
+ {
+ if(!pBase)
+ {
+ sal_uInt16 nSaveMask = pBasePool->GetSearchMask();
+ pBasePool->SetSearchMask(eFamily, SFXSTYLEBIT_ALL );
+ pBase = pBasePool->Find(sStyleName);
+ pBasePool->SetSearchMask(eFamily, nSaveMask );
+ }
+ pRet[nProp] = lcl_GetStyleProperty(*pEntry, *pPropSet, aBase, pBase, eFamily, GetDoc() );
+ }
+ else if(bIsDescriptor)
+ {
+ uno::Any *pAny = 0;
+ pPropImpl->GetProperty ( pNames[nProp], pAny );
+ if( !pAny )
+ {
+ sal_Bool bExcept = sal_False;
+ switch( eFamily )
+ {
+ case SFX_STYLE_FAMILY_PSEUDO:
+ bExcept = sal_True;
+ break;
+ case SFX_STYLE_FAMILY_PARA:
+ case SFX_STYLE_FAMILY_PAGE:
+ pPropImpl->GetProperty ( pNames[nProp], mxStyleData, pRet[ nProp ] );
+ break;
+ case SFX_STYLE_FAMILY_CHAR:
+ case SFX_STYLE_FAMILY_FRAME :
+ {
+ if (pEntry->nWID >= POOLATTR_BEGIN && pEntry->nWID < RES_UNKNOWNATR_END )
+ {
+ SwFmt * pFmt;
+ if ( eFamily == SFX_STYLE_FAMILY_CHAR )
+ pFmt = m_pDoc->GetDfltCharFmt();
+ else
+ pFmt = m_pDoc->GetDfltFrmFmt();
+ const SwAttrPool * pPool = pFmt->GetAttrSet().GetPool();
+ const SfxPoolItem & rItem = pPool->GetDefaultItem ( pEntry->nWID );
+ rItem.QueryValue ( pRet[nProp], pEntry->nMemberId );
+ }
+ else
+ bExcept = sal_True;
+ }
+ break;
+
+ default:
+ ;
+ }
+ if (bExcept )
+ {
+ uno::RuntimeException aExcept;
+ aExcept.Message = OUString ( RTL_CONSTASCII_USTRINGPARAM ( "No default value for: " ) ) + pNames[nProp];
+ throw aExcept;
+ }
+ }
+ else
+ pRet [ nProp ] = *pAny;
+ }
+ else
+ throw uno::RuntimeException();
+ }
+ return aRet;
+}
+
+uno::Sequence< uno::Any > SwXStyle::getPropertyValues(
+ const uno::Sequence< OUString >& rPropertyNames ) throw(uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+ uno::Sequence< uno::Any > aValues;
+
+ // workaround for bad designed API
+ try
+ {
+ aValues = GetPropertyValues_Impl( rPropertyNames );
+ }
+ catch (beans::UnknownPropertyException &)
+ {
+ throw uno::RuntimeException(OUString ( RTL_CONSTASCII_USTRINGPARAM ( "Unknown property exception caught" ) ), static_cast < cppu::OWeakObject * > ( this ) );
+ }
+ catch (lang::WrappedTargetException &)
+ {
+ throw uno::RuntimeException(OUString ( RTL_CONSTASCII_USTRINGPARAM ( "WrappedTargetException caught" ) ), static_cast < cppu::OWeakObject * > ( this ) );
+ }
+
+ return aValues;
+}
+
+void SwXStyle::addPropertiesChangeListener(
+ const uno::Sequence< OUString >& /*aPropertyNames*/,
+ const uno::Reference< beans::XPropertiesChangeListener >& /*xListener*/ )
+ throw(uno::RuntimeException)
+{
+}
+
+void SwXStyle::removePropertiesChangeListener(
+ const uno::Reference< beans::XPropertiesChangeListener >& /*xListener*/ )
+ throw(uno::RuntimeException)
+{
+}
+
+void SwXStyle::firePropertiesChangeEvent(
+ const uno::Sequence< OUString >& /*aPropertyNames*/,
+ const uno::Reference< beans::XPropertiesChangeListener >& /*xListener*/ )
+ throw(uno::RuntimeException)
+{
+}
+
+void SwXStyle::setPropertyValue(const OUString& rPropertyName, const uno::Any& rValue)
+ throw( beans::UnknownPropertyException,
+ beans::PropertyVetoException,
+ lang::IllegalArgumentException,
+ lang::WrappedTargetException,
+ uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+ const uno::Sequence<OUString> aProperties(&rPropertyName, 1);
+ const uno::Sequence<uno::Any> aValues(&rValue, 1);
+ SetPropertyValues_Impl( aProperties, aValues );
+}
+
+uno::Any SwXStyle::getPropertyValue(const OUString& rPropertyName)
+ throw( beans::UnknownPropertyException, lang::WrappedTargetException, uno::RuntimeException )
+{
+ SolarMutexGuard aGuard;
+ const uno::Sequence<OUString> aProperties(&rPropertyName, 1);
+ return GetPropertyValues_Impl(aProperties).getConstArray()[0];
+
+}
+
+void SwXStyle::addPropertyChangeListener(const OUString& /*rPropertyName*/,
+ const uno::Reference< beans::XPropertyChangeListener > & /*xListener*/)
+ throw( beans::UnknownPropertyException, lang::WrappedTargetException, uno::RuntimeException )
+{
+ DBG_WARNING("not implemented");
+}
+
+void SwXStyle::removePropertyChangeListener(const OUString& /*rPropertyName*/,
+ const uno::Reference< beans::XPropertyChangeListener > & /*xListener*/)
+ throw( beans::UnknownPropertyException, lang::WrappedTargetException, uno::RuntimeException )
+{
+ DBG_WARNING("not implemented");
+}
+
+void SwXStyle::addVetoableChangeListener(const OUString& /*rPropertyName*/,
+ const uno::Reference< beans::XVetoableChangeListener > & /*xListener*/)
+ throw( beans::UnknownPropertyException, lang::WrappedTargetException, uno::RuntimeException )
+{
+ DBG_WARNING("not implemented");
+}
+
+void SwXStyle::removeVetoableChangeListener(const OUString& /*rPropertyName*/,
+ const uno::Reference< beans::XVetoableChangeListener > & /*xListener*/)
+ throw( beans::UnknownPropertyException, lang::WrappedTargetException, uno::RuntimeException )
+{
+ DBG_WARNING("not implemented");
+}
+
+beans::PropertyState SwXStyle::getPropertyState(const OUString& rPropertyName)
+ throw( beans::UnknownPropertyException, uno::RuntimeException )
+{
+ SolarMutexGuard aGuard;
+
+ uno::Sequence< OUString > aNames(1);
+ OUString* pNames = aNames.getArray();
+ pNames[0] = rPropertyName;
+ uno::Sequence< beans::PropertyState > aStates = getPropertyStates(aNames);
+ return aStates.getConstArray()[0];
+}
+
+uno::Sequence< beans::PropertyState > SwXStyle::getPropertyStates(
+ const uno::Sequence< OUString >& rPropertyNames)
+ throw( beans::UnknownPropertyException, uno::RuntimeException )
+{
+ SolarMutexGuard aGuard;
+ uno::Sequence< beans::PropertyState > aRet(rPropertyNames.getLength());
+ beans::PropertyState* pStates = aRet.getArray();
+ if(pBasePool)
+ {
+ pBasePool->SetSearchMask(eFamily );
+ SfxStyleSheetBase* pBase = pBasePool->Find(sStyleName);
+ DBG_ASSERT(pBase, "where is the style?" );
+
+ if(pBase)
+ {
+ const OUString* pNames = rPropertyNames.getConstArray();
+ rtl::Reference< SwDocStyleSheet > xStyle( new SwDocStyleSheet( *(SwDocStyleSheet*)pBase ) );
+ sal_Int8 nPropSetId = PROPERTY_MAP_CHAR_STYLE;
+ switch(eFamily)
+ {
+ case SFX_STYLE_FAMILY_PARA : nPropSetId = bIsConditional ? PROPERTY_MAP_CONDITIONAL_PARA_STYLE : PROPERTY_MAP_PARA_STYLE; break;
+ case SFX_STYLE_FAMILY_FRAME : nPropSetId = PROPERTY_MAP_FRAME_STYLE ;break;
+ case SFX_STYLE_FAMILY_PAGE : nPropSetId = PROPERTY_MAP_PAGE_STYLE; break;
+ case SFX_STYLE_FAMILY_PSEUDO: nPropSetId = PROPERTY_MAP_NUM_STYLE ;break;
+ default:
+ ;
+ }
+ const SfxItemPropertySet* pPropSet = aSwMapProvider.GetPropertySet(nPropSetId);
+ const SfxItemPropertyMap *pMap = pPropSet->getPropertyMap();
+
+ SfxItemSet aSet = xStyle->GetItemSet();
+ for(sal_Int32 i = 0; i < rPropertyNames.getLength(); i++)
+ {
+ const String& rPropName = pNames[i];
+ const SfxItemPropertySimpleEntry* pEntry = pMap->getByName( rPropName);
+ if(!pEntry)
+ throw beans::UnknownPropertyException(OUString ( RTL_CONSTASCII_USTRINGPARAM ( "Unknown property: " ) ) + rPropName, static_cast < cppu::OWeakObject * > ( this ) );
+ if( FN_UNO_NUM_RULES == pEntry->nWID ||
+ FN_UNO_FOLLOW_STYLE == pEntry->nWID )
+ {
+ pStates[i] = beans::PropertyState_DIRECT_VALUE;
+ }
+ else if(SFX_STYLE_FAMILY_PAGE == eFamily &&
+ (rPropName.EqualsAscii("Header", 0, 6)
+ || rPropName.EqualsAscii("Footer", 0, 6)))
+ {
+ sal_uInt16 nResId = lcl_ConvertFNToRES(pEntry->nWID);
+ sal_Bool bFooter = rPropName.EqualsAscii("Footer", 0, 6);
+ const SvxSetItem* pSetItem;
+ if(SFX_ITEM_SET == aSet.GetItemState(
+ bFooter ? SID_ATTR_PAGE_FOOTERSET : SID_ATTR_PAGE_HEADERSET,
+ sal_False, (const SfxPoolItem**)&pSetItem))
+ {
+ const SfxItemSet& rSet = pSetItem->GetItemSet();
+ SfxItemState eState = rSet.GetItemState(nResId, sal_False);
+ if(SFX_ITEM_SET == eState)
+ pStates[i] = beans::PropertyState_DIRECT_VALUE;
+ else
+ pStates[i] = beans::PropertyState_DEFAULT_VALUE;
+ }
+ else
+ pStates[i] = beans::PropertyState_AMBIGUOUS_VALUE;
+ }
+ else
+ {
+ pStates[i] = pPropSet->getPropertyState(*pEntry, aSet);
+ if( SFX_STYLE_FAMILY_PAGE == eFamily &&
+ SID_ATTR_PAGE_SIZE == pEntry->nWID &&
+ beans::PropertyState_DIRECT_VALUE == pStates[i] )
+ {
+ const SvxSizeItem& rSize =
+ static_cast < const SvxSizeItem& >(
+ aSet.Get(SID_ATTR_PAGE_SIZE) );
+ sal_uInt8 nMemberId = pEntry->nMemberId & 0x7f;
+ if( ( LONG_MAX == rSize.GetSize().Width() &&
+ (MID_SIZE_WIDTH == nMemberId ||
+ MID_SIZE_SIZE == nMemberId ) ) ||
+ ( LONG_MAX == rSize.GetSize().Height() &&
+ MID_SIZE_HEIGHT == nMemberId ) )
+ {
+ pStates[i] = beans::PropertyState_DEFAULT_VALUE;
+ }
+ }
+ }
+ }
+ }
+ else
+ throw uno::RuntimeException();
+ }
+ else
+ throw uno::RuntimeException();
+ return aRet;
+}
+
+void SwXStyle::setPropertyToDefault(const OUString& rPropertyName)
+ throw( beans::UnknownPropertyException, uno::RuntimeException )
+{
+ const uno::Sequence < OUString > aSequence ( &rPropertyName, 1 );
+ setPropertiesToDefault ( aSequence );
+}
+
+void SAL_CALL SwXStyle::setPropertiesToDefault( const uno::Sequence< OUString >& aPropertyNames )
+ throw (beans::UnknownPropertyException, uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+ SwFmt *pTargetFmt = 0;
+
+ if(pBasePool)
+ {
+ pBasePool->SetSearchMask(eFamily);
+ SfxStyleSheetBase* pBase = pBasePool->Find(sStyleName);
+ DBG_ASSERT(pBase, "Where is the style?");
+
+ if(pBase)
+ {
+ rtl::Reference< SwDocStyleSheet > xStyle( new SwDocStyleSheet( *(SwDocStyleSheet*)pBase ) );
+ switch(eFamily)
+ {
+ case SFX_STYLE_FAMILY_CHAR: pTargetFmt = xStyle->GetCharFmt(); break;
+ case SFX_STYLE_FAMILY_PARA: pTargetFmt = xStyle->GetCollection(); break;
+ case SFX_STYLE_FAMILY_FRAME: pTargetFmt = xStyle->GetFrmFmt(); break;
+ case SFX_STYLE_FAMILY_PAGE:
+ {
+ sal_uInt16 nPgDscPos = USHRT_MAX;
+ SwPageDesc *pDesc = m_pDoc->FindPageDescByName( xStyle->GetPageDesc()->GetName(), &nPgDscPos );
+ if( pDesc )
+ pTargetFmt = &pDesc->GetMaster();
+ }
+ break;
+ case SFX_STYLE_FAMILY_PSEUDO:
+ break;
+ default:
+ ;
+ }
+ }
+ }
+ sal_Int8 nPropSetId = PROPERTY_MAP_CHAR_STYLE;
+ switch(eFamily)
+ {
+ case SFX_STYLE_FAMILY_PARA : nPropSetId = bIsConditional ? PROPERTY_MAP_CONDITIONAL_PARA_STYLE : PROPERTY_MAP_PARA_STYLE; break;
+ case SFX_STYLE_FAMILY_FRAME : nPropSetId = PROPERTY_MAP_FRAME_STYLE; break;
+ case SFX_STYLE_FAMILY_PAGE : nPropSetId = PROPERTY_MAP_PAGE_STYLE; break;
+ case SFX_STYLE_FAMILY_PSEUDO: nPropSetId = PROPERTY_MAP_NUM_STYLE; break;
+ default:
+ ;
+ }
+ const SfxItemPropertySet* pPropSet = aSwMapProvider.GetPropertySet(nPropSetId);
+ const SfxItemPropertyMap *pMap = pPropSet->getPropertyMap();
+
+ const OUString* pNames = aPropertyNames.getConstArray();
+
+ if ( pTargetFmt )
+ {
+ for( sal_Int32 nProp = 0, nEnd = aPropertyNames.getLength(); nProp < nEnd; nProp++ )
+ {
+ const SfxItemPropertySimpleEntry* pEntry = pMap->getByName( pNames[nProp] );
+ if( !pEntry )
+ throw beans::UnknownPropertyException ( OUString ( RTL_CONSTASCII_USTRINGPARAM ( "Property is unknown: " ) ) + pNames[nProp], static_cast < cppu::OWeakObject * > ( this ) );
+ if ( pEntry->nWID == FN_UNO_FOLLOW_STYLE || pEntry->nWID == FN_UNO_NUM_RULES )
+ throw uno::RuntimeException ( OUString ( RTL_CONSTASCII_USTRINGPARAM ( "Cannot reset: " ) ) + pNames[nProp], static_cast < cppu::OWeakObject * > ( this ) );
+ if ( pEntry->nFlags & beans::PropertyAttribute::READONLY )
+ throw uno::RuntimeException( OUString ( RTL_CONSTASCII_USTRINGPARAM ( "setPropertiesToDefault: property is read-only: " ) ) + pNames[nProp], static_cast < cppu::OWeakObject * > ( this ) );
+
+ if( pEntry->nWID == RES_PARATR_OUTLINELEVEL )
+ static_cast<SwTxtFmtColl*>(pTargetFmt)->DeleteAssignmentToListLevelOfOutlineStyle();
+ else
+ pTargetFmt->ResetFmtAttr( pEntry->nWID );
+ }
+ }
+ else if ( bIsDescriptor )
+ {
+ for( sal_Int32 nProp = 0, nEnd = aPropertyNames.getLength(); nProp < nEnd; nProp++ )
+ pPropImpl->ClearProperty ( pNames[ nProp ] );
+ }
+}
+
+void SAL_CALL SwXStyle::setAllPropertiesToDefault( )
+ throw (uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+ if(pBasePool)
+ {
+ pBasePool->SetSearchMask(eFamily);
+ SfxStyleSheetBase* pBase = pBasePool->Find(sStyleName);
+ DBG_ASSERT(pBase, "where is the style, you fiend!?");
+
+ if(pBase)
+ {
+ rtl::Reference< SwDocStyleSheet > xStyle( new SwDocStyleSheet( *(SwDocStyleSheet*)pBase ) );
+
+ SwFmt *pTargetFmt = 0;
+ sal_uInt16 nPgDscPos = USHRT_MAX;
+ switch( eFamily )
+ {
+ case SFX_STYLE_FAMILY_CHAR :
+ pTargetFmt = xStyle->GetCharFmt();
+ break;
+ case SFX_STYLE_FAMILY_PARA :
+ {
+ pTargetFmt = xStyle->GetCollection();
+ if ( xStyle->GetCollection() )
+ xStyle->GetCollection()->DeleteAssignmentToListLevelOfOutlineStyle();
+ }
+ break;
+ case SFX_STYLE_FAMILY_FRAME:
+ pTargetFmt = xStyle->GetFrmFmt();
+ break;
+ case SFX_STYLE_FAMILY_PAGE:
+ {
+ SwPageDesc *pDesc = m_pDoc->FindPageDescByName( xStyle->GetPageDesc()->GetName(), &nPgDscPos );
+ if( pDesc )
+ {
+ pTargetFmt = &pDesc->GetMaster();
+ pDesc->SetUseOn ( nsUseOnPage::PD_ALL );
+ }
+ }
+ break;
+ case SFX_STYLE_FAMILY_PSEUDO:
+ break;
+
+ default:
+ ;
+ }
+ if( pTargetFmt )
+ {
+ if( USHRT_MAX != nPgDscPos )
+ {
+ SwPageDesc& rPageDesc = m_pDoc->_GetPageDesc(nPgDscPos);
+ rPageDesc.ResetAllMasterAttr();
+
+ SvxLRSpaceItem aLR(RES_LR_SPACE);
+ sal_Int32 nSize = GetMetricVal ( CM_1) * 2;
+ aLR.SetLeft ( nSize );
+ aLR.SetLeft ( nSize );
+ SvxULSpaceItem aUL( RES_UL_SPACE );
+ aUL.SetUpper ( static_cast < sal_uInt16 > ( nSize ) );
+ aUL.SetLower ( static_cast < sal_uInt16 > ( nSize ) );
+ pTargetFmt->SetFmtAttr( aLR );
+ pTargetFmt->SetFmtAttr( aUL );
+
+ SwPageDesc* pStdPgDsc = m_pDoc->GetPageDescFromPool( RES_POOLPAGE_STANDARD );
+ SwFmtFrmSize aFrmSz( ATT_FIX_SIZE );
+ if( RES_POOLPAGE_STANDARD == rPageDesc.GetPoolFmtId() )
+ {
+ if( m_pDoc->getPrinter( false ) )
+ {
+ const Size aPhysSize( SvxPaperInfo::GetPaperSize(
+ static_cast<Printer*>( m_pDoc->getPrinter( false ) )) );
+ aFrmSz.SetSize( aPhysSize );
+ }
+ else
+ aFrmSz.SetSize( SvxPaperInfo::GetDefaultPaperSize() );
+
+ }
+ else
+ {
+ aFrmSz = pStdPgDsc->GetMaster().GetFrmSize();
+ }
+ if( pStdPgDsc->GetLandscape() )
+ {
+ SwTwips nTmp = aFrmSz.GetHeight();
+ aFrmSz.SetHeight( aFrmSz.GetWidth() );
+ aFrmSz.SetWidth( nTmp );
+ }
+ pTargetFmt->SetFmtAttr( aFrmSz );
+ }
+ else
+ pTargetFmt->ResetAllFmtAttr();
+
+ if( USHRT_MAX != nPgDscPos )
+ m_pDoc->ChgPageDesc( nPgDscPos,
+ const_cast<const SwDoc *>(m_pDoc)
+ ->GetPageDesc(nPgDscPos) );
+ }
+
+ }
+ else
+ throw uno::RuntimeException();
+ }
+ else if ( bIsDescriptor )
+ pPropImpl->ClearAllProperties();
+ else
+ throw uno::RuntimeException();
+}
+
+uno::Sequence< uno::Any > SAL_CALL SwXStyle::getPropertyDefaults( const uno::Sequence< OUString >& aPropertyNames )
+ throw (beans::UnknownPropertyException, lang::WrappedTargetException, uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+ sal_Int32 nCount = aPropertyNames.getLength();
+ uno::Sequence < uno::Any > aRet ( nCount );
+ if ( nCount )
+ {
+ if( pBasePool)
+ {
+ pBasePool->SetSearchMask(eFamily);
+ SfxStyleSheetBase* pBase = pBasePool->Find(sStyleName);
+ DBG_ASSERT(pBase, "Doesn't seem to be a style!");
+
+ if(pBase)
+ {
+ rtl::Reference< SwDocStyleSheet > xStyle( new SwDocStyleSheet( *(SwDocStyleSheet*)pBase ) );
+ sal_Int8 nPropSetId = PROPERTY_MAP_CHAR_STYLE;
+ switch(eFamily)
+ {
+ case SFX_STYLE_FAMILY_PARA : nPropSetId = bIsConditional ? PROPERTY_MAP_CONDITIONAL_PARA_STYLE : PROPERTY_MAP_PARA_STYLE; break;
+ case SFX_STYLE_FAMILY_FRAME : nPropSetId = PROPERTY_MAP_FRAME_STYLE; break;
+ case SFX_STYLE_FAMILY_PAGE : nPropSetId = PROPERTY_MAP_PAGE_STYLE; break;
+ case SFX_STYLE_FAMILY_PSEUDO: nPropSetId = PROPERTY_MAP_NUM_STYLE; break;
+ default:
+ ;
+ }
+ const SfxItemPropertySet* pPropSet = aSwMapProvider.GetPropertySet(nPropSetId);
+ const SfxItemPropertyMap* pMap = pPropSet->getPropertyMap();
+
+ const SfxItemSet &rSet = xStyle->GetItemSet(), *pParentSet = rSet.GetParent();
+ const OUString *pNames = aPropertyNames.getConstArray();
+ uno::Any *pRet = aRet.getArray();
+ for ( sal_Int32 i = 0 ; i < nCount; i++)
+ {
+ const SfxItemPropertySimpleEntry* pEntry = pMap->getByName( pNames[i] );
+ if ( !pEntry )
+ throw beans::UnknownPropertyException ( OUString ( RTL_CONSTASCII_USTRINGPARAM ( "Unknown property: " ) ) + pNames[i], static_cast < cppu::OWeakObject * > ( this ) );
+
+ if( pParentSet )
+ aSwMapProvider.GetPropertySet(nPropSetId)->getPropertyValue(pNames[i], *pParentSet, pRet[i]);
+ else if( pEntry->nWID != rSet.GetPool()->GetSlotId(pEntry->nWID) )
+ {
+ const SfxPoolItem& rItem = rSet.GetPool()->GetDefaultItem(pEntry->nWID);
+ rItem.QueryValue(pRet[i], pEntry->nMemberId);
+ }
+ }
+ }
+ else
+ throw uno::RuntimeException();
+ }
+ else
+ throw uno::RuntimeException();
+ }
+ return aRet;
+}
+
+uno::Any SwXStyle::getPropertyDefault(const OUString& rPropertyName)
+ throw( beans::UnknownPropertyException, lang::WrappedTargetException, uno::RuntimeException )
+{
+ const uno::Sequence < OUString > aSequence ( &rPropertyName, 1 );
+ return getPropertyDefaults ( aSequence ).getConstArray()[0];
+}
+
+void SwXStyle::Notify( SfxBroadcaster& rBC, const SfxHint& rHint )
+{
+ SfxSimpleHint *pHint = PTR_CAST( SfxSimpleHint, &rHint );
+ if( pHint )
+ {
+ if(( pHint->GetId() & SFX_HINT_DYING ) || ( pHint->GetId() & SFX_STYLESHEET_ERASED))
+ {
+ pBasePool = 0;
+ EndListening(rBC);
+ }
+ else if( pHint->GetId() &(SFX_STYLESHEET_CHANGED|SFX_STYLESHEET_ERASED) )
+ {
+ ((SfxStyleSheetBasePool&)rBC).SetSearchMask(eFamily);
+ SfxStyleSheetBase* pOwnBase = ((SfxStyleSheetBasePool&)rBC).Find(sStyleName);
+ if(!pOwnBase)
+ {
+ EndListening(rBC);
+ Invalidate();
+ }
+ }
+ }
+}
+
+void SwXStyle::Invalidate()
+{
+ sStyleName.Erase();
+ pBasePool = 0;
+ m_pDoc = 0;
+ mxStyleData.clear();
+ mxStyleFamily.clear();
+}
+
+/******************************************************************
+ * SwXPageStyle
+ ******************************************************************/
+SwXPageStyle::SwXPageStyle(SfxStyleSheetBasePool& rPool,
+ SwDocShell* pDocSh, SfxStyleFamily eFam,
+ const String& rStyleName):
+ SwXStyle(rPool, eFam, pDocSh->GetDoc(), rStyleName),
+ pDocShell(pDocSh)
+{
+
+}
+
+SwXPageStyle::SwXPageStyle(SwDocShell* pDocSh) :
+ SwXStyle(pDocSh->GetDoc(), SFX_STYLE_FAMILY_PAGE),
+ pDocShell(pDocSh)
+{
+}
+
+SwXPageStyle::~SwXPageStyle()
+{
+
+}
+
+void SAL_CALL SwXPageStyle::SetPropertyValues_Impl(
+ const uno::Sequence< OUString >& rPropertyNames,
+ const uno::Sequence< uno::Any >& rValues )
+ throw( beans::UnknownPropertyException, beans::PropertyVetoException, lang::IllegalArgumentException,
+ lang::WrappedTargetException, uno::RuntimeException)
+{
+ if(!GetDoc())
+ throw uno::RuntimeException();
+
+ if(rPropertyNames.getLength() != rValues.getLength())
+ throw lang::IllegalArgumentException();
+
+ const OUString* pNames = rPropertyNames.getConstArray();
+ const uno::Any* pValues = rValues.getConstArray();
+ const SfxItemPropertySet* pPropSet = aSwMapProvider.GetPropertySet(PROPERTY_MAP_PAGE_STYLE);
+ const SfxItemPropertyMap* pMap = pPropSet->getPropertyMap();
+ SwStyleBase_Impl aBaseImpl(*GetDoc(), GetStyleName());
+ if(GetBasePool())
+ {
+ sal_uInt16 nSaveMask = GetBasePool()->GetSearchMask();
+ GetBasePool()->SetSearchMask(GetFamily());
+ SfxStyleSheetBase* pBase = GetBasePool()->Find(GetStyleName());
+ GetBasePool()->SetSearchMask(GetFamily(), nSaveMask );
+ DBG_ASSERT(pBase, "where is the style?" );
+ if(pBase)
+ aBaseImpl.mxNewBase = new SwDocStyleSheet(*(SwDocStyleSheet*)pBase);
+ else
+ throw uno::RuntimeException();
+ }
+
+ for(sal_Int16 nProp = 0; nProp < rPropertyNames.getLength(); nProp++)
+ {
+ const SfxItemPropertySimpleEntry* pEntry = pMap->getByName( pNames[nProp] );
+ if (!pEntry)
+ throw beans::UnknownPropertyException(OUString ( RTL_CONSTASCII_USTRINGPARAM ( "Unknown property: " ) ) + pNames[nProp], static_cast < cppu::OWeakObject * > ( this ) );
+ if ( pEntry->nFlags & beans::PropertyAttribute::READONLY)
+ throw beans::PropertyVetoException ( OUString ( RTL_CONSTASCII_USTRINGPARAM ( "Property is read-only: " ) ) + pNames[nProp], static_cast < cppu::OWeakObject * > ( this ) );
+
+ if(GetBasePool())
+ {
+ switch(pEntry->nWID)
+ {
+ case FN_UNO_HEADER_ON:
+ case FN_UNO_HEADER_BACKGROUND:
+ case FN_UNO_HEADER_BOX:
+ case FN_UNO_HEADER_LR_SPACE:
+ case FN_UNO_HEADER_SHADOW:
+ case FN_UNO_HEADER_BODY_DISTANCE:
+ case FN_UNO_HEADER_IS_DYNAMIC_DISTANCE:
+ case FN_UNO_HEADER_SHARE_CONTENT:
+ case FN_UNO_HEADER_HEIGHT:
+ case FN_UNO_HEADER_EAT_SPACING:
+
+ case FN_UNO_FOOTER_ON:
+ case FN_UNO_FOOTER_BACKGROUND:
+ case FN_UNO_FOOTER_BOX:
+ case FN_UNO_FOOTER_LR_SPACE:
+ case FN_UNO_FOOTER_SHADOW:
+ case FN_UNO_FOOTER_BODY_DISTANCE:
+ case FN_UNO_FOOTER_IS_DYNAMIC_DISTANCE:
+ case FN_UNO_FOOTER_SHARE_CONTENT:
+ case FN_UNO_FOOTER_HEIGHT:
+ case FN_UNO_FOOTER_EAT_SPACING:
+ {
+ sal_Bool bFooter = sal_False;
+ sal_uInt16 nItemType = TYPE_BOOL;
+ sal_uInt16 nRes = 0;
+ switch(pEntry->nWID)
+ {
+ case FN_UNO_FOOTER_ON: bFooter = sal_True;
+ //kein break;
+ case FN_UNO_HEADER_ON: nRes = SID_ATTR_PAGE_ON;
+ break;
+ case FN_UNO_FOOTER_BACKGROUND: bFooter = sal_True;
+ // kein break;
+ case FN_UNO_HEADER_BACKGROUND: nRes = RES_BACKGROUND; nItemType = TYPE_BRUSH;
+ break;
+ case FN_UNO_FOOTER_BOX: bFooter = sal_True;
+ // kein break;
+ case FN_UNO_HEADER_BOX: nRes = RES_BOX; nItemType = TYPE_BOX;
+ break;
+ case FN_UNO_FOOTER_LR_SPACE: bFooter = sal_True;
+ // kein break;
+ case FN_UNO_HEADER_LR_SPACE: nRes = RES_LR_SPACE;nItemType = TYPE_LRSPACE;
+ break;
+ case FN_UNO_FOOTER_SHADOW: bFooter = sal_True;
+ // kein break;
+ case FN_UNO_HEADER_SHADOW: nRes = RES_SHADOW;nItemType = TYPE_SHADOW;
+ break;
+ case FN_UNO_FOOTER_BODY_DISTANCE: bFooter = sal_True;
+ // kein break;
+ case FN_UNO_HEADER_BODY_DISTANCE: nRes = RES_UL_SPACE;nItemType = TYPE_ULSPACE;
+ break;
+ case FN_UNO_FOOTER_IS_DYNAMIC_DISTANCE: bFooter = sal_True;
+ // kein break;
+ case FN_UNO_HEADER_IS_DYNAMIC_DISTANCE: nRes = SID_ATTR_PAGE_DYNAMIC;
+ break;
+ case FN_UNO_FOOTER_SHARE_CONTENT: bFooter = sal_True;
+ // kein break;
+ case FN_UNO_HEADER_SHARE_CONTENT: nRes = SID_ATTR_PAGE_SHARED;
+ break;
+ case FN_UNO_FOOTER_HEIGHT: bFooter = sal_True;
+ // kein break;
+ case FN_UNO_HEADER_HEIGHT: nRes = SID_ATTR_PAGE_SIZE;nItemType = TYPE_SIZE;
+ break;
+ case FN_UNO_FOOTER_EAT_SPACING: bFooter = sal_True;
+ // kein break;
+ case FN_UNO_HEADER_EAT_SPACING: nRes = RES_HEADER_FOOTER_EAT_SPACING;nItemType = TYPE_SIZE;
+ break;
+ }
+ const SvxSetItem* pSetItem;
+ if(SFX_ITEM_SET == aBaseImpl.GetItemSet().GetItemState(
+ bFooter ? SID_ATTR_PAGE_FOOTERSET : SID_ATTR_PAGE_HEADERSET,
+ sal_False, (const SfxPoolItem**)&pSetItem))
+ {
+ SvxSetItem* pNewSetItem = (SvxSetItem*)pSetItem->Clone();
+ SfxItemSet& rSetSet = pNewSetItem->GetItemSet();
+ const SfxPoolItem* pItem = 0;
+ SfxPoolItem* pNewItem = 0;
+ rSetSet.GetItemState(nRes, sal_True, &pItem);
+ if(!pItem && nRes != rSetSet.GetPool()->GetSlotId(nRes))
+ pItem = &rSetSet.GetPool()->GetDefaultItem(nRes);
+ if(pItem)
+ {
+ pNewItem = pItem->Clone();
+ }
+ else
+ {
+ switch(nItemType)
+ {
+ case TYPE_BOOL: pNewItem = new SfxBoolItem(nRes); break;
+ case TYPE_SIZE: pNewItem = new SvxSizeItem(nRes); break;
+ case TYPE_BRUSH: pNewItem = new SvxBrushItem(nRes); break;
+ case TYPE_ULSPACE: pNewItem = new SvxULSpaceItem(nRes); break;
+ case TYPE_SHADOW : pNewItem = new SvxShadowItem(nRes); break;
+ case TYPE_LRSPACE: pNewItem = new SvxLRSpaceItem(nRes); break;
+ case TYPE_BOX: pNewItem = new SvxBoxItem(nRes); break;
+ }
+ }
+ pNewItem->PutValue(pValues[nProp], pEntry->nMemberId);
+ rSetSet.Put(*pNewItem);
+ aBaseImpl.GetItemSet().Put(*pNewSetItem);
+ delete pNewItem;
+ delete pNewSetItem;
+ }
+ else if(SID_ATTR_PAGE_ON == nRes )
+ {
+ sal_Bool bVal = *(sal_Bool*)pValues[nProp].getValue();
+ if(bVal)
+ {
+ SfxItemSet aTempSet(*aBaseImpl.GetItemSet().GetPool(),
+ RES_BACKGROUND, RES_SHADOW,
+ RES_LR_SPACE, RES_UL_SPACE,
+ nRes, nRes,
+ SID_ATTR_PAGE_SIZE, SID_ATTR_PAGE_SIZE,
+ SID_ATTR_PAGE_DYNAMIC, SID_ATTR_PAGE_DYNAMIC,
+ SID_ATTR_PAGE_SHARED, SID_ATTR_PAGE_SHARED,
+ 0 );
+ aTempSet.Put(SfxBoolItem(nRes, sal_True));
+ aTempSet.Put(SvxSizeItem(SID_ATTR_PAGE_SIZE, Size(MM50, MM50)));
+ aTempSet.Put(SvxLRSpaceItem(RES_LR_SPACE));
+ aTempSet.Put(SvxULSpaceItem(RES_UL_SPACE));
+ aTempSet.Put(SfxBoolItem(SID_ATTR_PAGE_SHARED, sal_True));
+ aTempSet.Put(SfxBoolItem(SID_ATTR_PAGE_DYNAMIC, sal_True));
+
+ SvxSetItem aNewSetItem( bFooter ? SID_ATTR_PAGE_FOOTERSET : SID_ATTR_PAGE_HEADERSET,
+ aTempSet);
+ aBaseImpl.GetItemSet().Put(aNewSetItem);
+ }
+ }
+ }
+ break;
+ case FN_PARAM_FTN_INFO :
+ {
+ const SfxPoolItem& rItem = aBaseImpl.GetItemSet().Get(FN_PARAM_FTN_INFO);
+ SfxPoolItem* pNewFtnItem = rItem.Clone();
+ sal_Bool bPut = pNewFtnItem->PutValue(pValues[nProp], pEntry->nMemberId);
+ aBaseImpl.GetItemSet().Put(*pNewFtnItem);
+ delete pNewFtnItem;
+ if(!bPut)
+ throw lang::IllegalArgumentException();
+ }
+ break;
+ case FN_UNO_HEADER :
+ case FN_UNO_HEADER_LEFT :
+ case FN_UNO_HEADER_RIGHT :
+ case FN_UNO_FOOTER :
+ case FN_UNO_FOOTER_LEFT :
+ case FN_UNO_FOOTER_RIGHT :
+ throw lang::IllegalArgumentException();
+ //break;
+ default:
+ lcl_SetStyleProperty(*pEntry, *pPropSet, pValues[nProp], aBaseImpl,
+ GetBasePool(), GetDoc(), GetFamily());
+ }
+ }
+ else if(IsDescriptor())
+ {
+ if(!GetPropImpl()->SetProperty(pNames[nProp], pValues[nProp]))
+ throw lang::IllegalArgumentException();
+ }
+ else
+ throw uno::RuntimeException();
+ }
+ if(aBaseImpl.HasItemSet())
+ {
+ ::sw::UndoGuard const undoGuard(GetDoc()->GetIDocumentUndoRedo());
+ if (undoGuard.UndoWasEnabled())
+ {
+ // Fix i64460: as long as Undo of page styles with header/footer causes trouble...
+ GetDoc()->GetIDocumentUndoRedo().DelAllUndoObj();
+ }
+ aBaseImpl.mxNewBase->SetItemSet(aBaseImpl.GetItemSet());
+ }
+}
+
+void SwXPageStyle::setPropertyValues(
+ const uno::Sequence< OUString >& rPropertyNames,
+ const uno::Sequence< uno::Any >& rValues )
+ throw(beans::PropertyVetoException, lang::IllegalArgumentException, lang::WrappedTargetException, uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+
+ // workaround for bad designed API
+ try
+ {
+ SetPropertyValues_Impl( rPropertyNames, rValues );
+ }
+ catch (beans::UnknownPropertyException &rException)
+ {
+ // wrap the original (here not allowed) exception in
+ // a lang::WrappedTargetException that gets thrown instead.
+ lang::WrappedTargetException aWExc;
+ aWExc.TargetException <<= rException;
+ throw aWExc;
+ }
+}
+
+static uno::Reference<text::XText>
+lcl_makeHeaderFooter(
+ const sal_uInt16 nRes, const bool bHeader, SwFrmFmt const*const pFrmFmt)
+{
+ if (!pFrmFmt) { return 0; }
+
+ const SfxItemSet& rSet = pFrmFmt->GetAttrSet();
+ const SfxPoolItem* pItem;
+ if (SFX_ITEM_SET == rSet.GetItemState(nRes, sal_True, &pItem))
+ {
+ SwFrmFmt *const pHeadFootFmt = (bHeader)
+ ? static_cast<SwFmtHeader*>(const_cast<SfxPoolItem*>(pItem))->
+ GetHeaderFmt()
+ : static_cast<SwFmtFooter*>(const_cast<SfxPoolItem*>(pItem))->
+ GetFooterFmt();
+ if (pHeadFootFmt)
+ {
+ return SwXHeadFootText::CreateXHeadFootText(*pHeadFootFmt, bHeader);
+ }
+ }
+ return 0;
+}
+
+uno::Sequence< uno::Any > SAL_CALL SwXPageStyle::GetPropertyValues_Impl(
+ const uno::Sequence< OUString >& rPropertyNames )
+ throw( beans::UnknownPropertyException, lang::WrappedTargetException, uno::RuntimeException )
+{
+ if(!GetDoc())
+ throw uno::RuntimeException();
+
+ sal_Int32 nLength = rPropertyNames.getLength();
+ const OUString* pNames = rPropertyNames.getConstArray();
+ uno::Sequence< uno::Any > aRet ( nLength );
+
+ uno::Any* pRet = aRet.getArray();
+ const SfxItemPropertySet* pPropSet = aSwMapProvider.GetPropertySet(PROPERTY_MAP_PAGE_STYLE);
+ const SfxItemPropertyMap* pMap = pPropSet->getPropertyMap();
+ SwStyleBase_Impl aBase(*GetDoc(), GetStyleName());
+ SfxStyleSheetBase* pBase = 0;
+ for(sal_Int32 nProp = 0; nProp < nLength; nProp++)
+ {
+ const SfxItemPropertySimpleEntry* pEntry = pMap->getByName( pNames[nProp] );
+ if (!pEntry)
+ throw beans::UnknownPropertyException(OUString ( RTL_CONSTASCII_USTRINGPARAM ( "Unknown property: " ) ) + pNames[nProp], static_cast < cppu::OWeakObject * > ( this ) );
+
+ if(GetBasePool())
+ {
+ if(!pBase)
+ {
+ sal_uInt16 nSaveMask = GetBasePool()->GetSearchMask();
+ GetBasePool()->SetSearchMask(GetFamily(), SFXSTYLEBIT_ALL );
+ pBase = GetBasePool()->Find(GetStyleName());
+ GetBasePool()->SetSearchMask(GetFamily(), nSaveMask );
+ }
+ sal_uInt16 nRes = 0;
+ bool bHeader = false;
+ sal_Bool bLeft = sal_False;
+ switch(pEntry->nWID)
+ {
+ case FN_UNO_HEADER_ON:
+ case FN_UNO_HEADER_BACKGROUND:
+ case FN_UNO_HEADER_BOX:
+ case FN_UNO_HEADER_LR_SPACE:
+ case FN_UNO_HEADER_SHADOW:
+ case FN_UNO_HEADER_BODY_DISTANCE:
+ case FN_UNO_HEADER_IS_DYNAMIC_DISTANCE:
+ case FN_UNO_HEADER_SHARE_CONTENT:
+ case FN_UNO_HEADER_HEIGHT:
+ case FN_UNO_HEADER_EAT_SPACING:
+
+ case FN_UNO_FOOTER_ON:
+ case FN_UNO_FOOTER_BACKGROUND:
+ case FN_UNO_FOOTER_BOX:
+ case FN_UNO_FOOTER_LR_SPACE:
+ case FN_UNO_FOOTER_SHADOW:
+ case FN_UNO_FOOTER_BODY_DISTANCE:
+ case FN_UNO_FOOTER_IS_DYNAMIC_DISTANCE:
+ case FN_UNO_FOOTER_SHARE_CONTENT:
+ case FN_UNO_FOOTER_HEIGHT:
+ case FN_UNO_FOOTER_EAT_SPACING:
+ {
+ SfxStyleSheetBasePool* pBasePool2 = ((SwXPageStyle*)this)->GetBasePool();
+ pBasePool2->SetSearchMask(GetFamily());
+ SfxStyleSheetBase* pBase2 = pBasePool2->Find(GetStyleName());
+ if(pBase2)
+ {
+ rtl::Reference< SwDocStyleSheet > xStyle( new SwDocStyleSheet( *(SwDocStyleSheet*)pBase ) );
+ const SfxItemSet& rSet = xStyle->GetItemSet();
+ sal_Bool bFooter = sal_False;
+ switch(pEntry->nWID)
+ {
+ case FN_UNO_FOOTER_ON:
+ bFooter = sal_True;
+ // kein break!
+ case FN_UNO_HEADER_ON:
+ {
+ //falls das SetItem nicht da ist, dann ist der Wert sal_False
+ sal_Bool bRet = sal_False;
+ pRet[nProp].setValue(&bRet, ::getCppuBooleanType());
+ nRes = SID_ATTR_PAGE_ON;
+ }
+ break;
+ case FN_UNO_FOOTER_BACKGROUND: bFooter = sal_True;
+ // kein break;
+ case FN_UNO_HEADER_BACKGROUND: nRes = RES_BACKGROUND;
+ break;
+ case FN_UNO_FOOTER_BOX: bFooter = sal_True;
+ // kein break;
+ case FN_UNO_HEADER_BOX: nRes = RES_BOX;
+ break;
+ case FN_UNO_FOOTER_LR_SPACE: bFooter = sal_True;
+ // kein break;
+ case FN_UNO_HEADER_LR_SPACE: nRes = RES_LR_SPACE;
+ break;
+ case FN_UNO_FOOTER_SHADOW: bFooter = sal_True;
+ // kein break;
+ case FN_UNO_HEADER_SHADOW: nRes = RES_SHADOW;
+ break;
+ case FN_UNO_FOOTER_BODY_DISTANCE: bFooter = sal_True;
+ // kein break;
+ case FN_UNO_HEADER_BODY_DISTANCE: nRes = RES_UL_SPACE;
+ break;
+ case FN_UNO_FOOTER_IS_DYNAMIC_DISTANCE: bFooter = sal_True;
+ // kein break;
+ case FN_UNO_HEADER_IS_DYNAMIC_DISTANCE: nRes = SID_ATTR_PAGE_DYNAMIC;
+ break;
+ case FN_UNO_FOOTER_SHARE_CONTENT: bFooter = sal_True;
+ // kein break;
+ case FN_UNO_HEADER_SHARE_CONTENT: nRes = SID_ATTR_PAGE_SHARED;
+ break;
+ case FN_UNO_FOOTER_HEIGHT: bFooter = sal_True;
+ // kein break;
+ case FN_UNO_HEADER_HEIGHT: nRes = SID_ATTR_PAGE_SIZE;
+ break;
+ case FN_UNO_FOOTER_EAT_SPACING: bFooter = sal_True;
+ // kein break;
+ case FN_UNO_HEADER_EAT_SPACING: nRes = RES_HEADER_FOOTER_EAT_SPACING;
+ break;
+ }
+ const SvxSetItem* pSetItem;
+ if(SFX_ITEM_SET == rSet.GetItemState(
+ bFooter ? SID_ATTR_PAGE_FOOTERSET : SID_ATTR_PAGE_HEADERSET,
+ sal_False, (const SfxPoolItem**)&pSetItem))
+ {
+ const SfxItemSet& rTmpSet = pSetItem->GetItemSet();
+ const SfxPoolItem* pItem = 0;
+ rTmpSet.GetItemState(nRes, sal_True, &pItem);
+ if(!pItem && nRes != rTmpSet.GetPool()->GetSlotId(nRes))
+ pItem = &rTmpSet.GetPool()->GetDefaultItem(nRes);
+ if(pItem)
+ pItem->QueryValue(pRet[nProp], pEntry->nMemberId);
+ }
+ }
+ }
+ break;
+ case FN_UNO_HEADER :
+ goto Header;
+ case FN_UNO_HEADER_LEFT :
+ bLeft = sal_True; goto Header;
+ case FN_UNO_HEADER_RIGHT :
+ goto Header;
+Header:
+ bHeader = true;
+ nRes = RES_HEADER; goto MakeObject;
+ case FN_UNO_FOOTER :
+ goto Footer;
+ case FN_UNO_FOOTER_LEFT :
+ bLeft = sal_True; goto Footer;
+ case FN_UNO_FOOTER_RIGHT :
+Footer:
+ nRes = RES_FOOTER;
+MakeObject:
+ {
+ const SwPageDesc& rDesc = aBase.GetOldPageDesc();
+ const SwFrmFmt* pFrmFmt = 0;
+ sal_Bool bShare = (bHeader && rDesc.IsHeaderShared())||
+ (!bHeader && rDesc.IsFooterShared());
+ // TextLeft returns the left content if there is one,
+ // Text and TextRight return the master content.
+ // TextRight does the same as Text and is for
+ // comptability only.
+ if( bLeft && !bShare )
+ {
+ pFrmFmt = &rDesc.GetLeft();
+ }
+ else
+ {
+ pFrmFmt = &rDesc.GetMaster();
+ }
+ const uno::Reference< text::XText > xRet =
+ lcl_makeHeaderFooter(nRes, bHeader, pFrmFmt);
+ if (xRet.is())
+ {
+ pRet[nProp] <<= xRet;
+ }
+ }
+ break;
+ case FN_PARAM_FTN_INFO :
+ {
+ rtl::Reference< SwDocStyleSheet > xStyle( new SwDocStyleSheet( *(SwDocStyleSheet*)pBase ) );
+ const SfxItemSet& rSet = xStyle->GetItemSet();
+ const SfxPoolItem& rItem = rSet.Get(FN_PARAM_FTN_INFO);
+ rItem.QueryValue(pRet[nProp], pEntry->nMemberId);
+ }
+ break;
+ default:
+ pRet[nProp] = lcl_GetStyleProperty(*pEntry, *pPropSet, aBase, pBase, GetFamily(), GetDoc() );
+ }
+ }
+ else if(IsDescriptor())
+ {
+ uno::Any* pAny = 0;
+ GetPropImpl()->GetProperty(pNames[nProp], pAny);
+ if ( !pAny )
+ GetPropImpl()->GetProperty ( pNames[nProp], mxStyleData, pRet[ nProp ] );
+ else
+ pRet[nProp] = *pAny;
+ }
+ else
+ throw uno::RuntimeException();
+ }
+ return aRet;
+}
+
+uno::Sequence< uno::Any > SwXPageStyle::getPropertyValues(
+ const uno::Sequence< OUString >& rPropertyNames )
+ throw(uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+ uno::Sequence< uno::Any > aValues;
+
+ // workaround for bad designed API
+ try
+ {
+ aValues = GetPropertyValues_Impl( rPropertyNames );
+ }
+ catch (beans::UnknownPropertyException &)
+ {
+ throw uno::RuntimeException(OUString ( RTL_CONSTASCII_USTRINGPARAM ( "Unknown property exception caught" ) ), static_cast < cppu::OWeakObject * > ( this ) );
+ }
+ catch (lang::WrappedTargetException &)
+ {
+ throw uno::RuntimeException(OUString ( RTL_CONSTASCII_USTRINGPARAM ( "WrappedTargetException caught" ) ), static_cast < cppu::OWeakObject * > ( this ) );
+ }
+
+ return aValues;
+}
+
+uno::Any SwXPageStyle::getPropertyValue(const OUString& rPropertyName) throw(
+ beans::UnknownPropertyException, lang::WrappedTargetException, uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+ const uno::Sequence<OUString> aProperties(&rPropertyName, 1);
+ return GetPropertyValues_Impl(aProperties).getConstArray()[0];
+}
+
+void SwXPageStyle::setPropertyValue(const OUString& rPropertyName, const uno::Any& rValue)
+ throw( beans::UnknownPropertyException,
+ beans::PropertyVetoException,
+ lang::IllegalArgumentException,
+ lang::WrappedTargetException,
+ uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+ const uno::Sequence<OUString> aProperties(&rPropertyName, 1);
+ const uno::Sequence<uno::Any> aValues(&rValue, 1);
+ SetPropertyValues_Impl( aProperties, aValues );
+}
+
+SwXFrameStyle::SwXFrameStyle ( SwDoc *pDoc )
+: SwXStyle ( pDoc, SFX_STYLE_FAMILY_FRAME, sal_False)
+{
+}
+
+SwXFrameStyle::~SwXFrameStyle()
+{
+}
+
+uno::Sequence< uno::Type > SwXFrameStyle::getTypes( ) throw(uno::RuntimeException)
+{
+ uno::Sequence< uno::Type > aTypes = SwXStyle::getTypes();
+ sal_Int32 nLen = aTypes.getLength();
+ aTypes.realloc(nLen + 1);
+ aTypes.getArray()[nLen] = ::getCppuType((uno::Reference<XEventsSupplier>*)0);
+ return aTypes;
+}
+
+uno::Any SwXFrameStyle::queryInterface( const uno::Type& rType ) throw(uno::RuntimeException)
+{
+ uno::Any aRet;
+ if(rType == ::getCppuType((uno::Reference<XEventsSupplier>*)0))
+ aRet <<= uno::Reference<XEventsSupplier>(this);
+ else
+ aRet = SwXStyle::queryInterface(rType);
+ return aRet;
+}
+
+uno::Reference< container::XNameReplace > SwXFrameStyle::getEvents( ) throw(uno::RuntimeException)
+{
+ return new SwFrameStyleEventDescriptor( *this );
+}
+
+SwXAutoStyles::SwXAutoStyles(SwDocShell& rDocShell) :
+ SwUnoCollection(rDocShell.GetDoc()), pDocShell( &rDocShell )
+{
+}
+
+SwXAutoStyles::~SwXAutoStyles()
+{
+}
+
+sal_Int32 SwXAutoStyles::getCount(void) throw( uno::RuntimeException )
+{
+ return AUTOSTYLE_FAMILY_COUNT;
+}
+
+uno::Any SwXAutoStyles::getByIndex(sal_Int32 nIndex)
+ throw( lang::IndexOutOfBoundsException, lang::WrappedTargetException,
+ uno::RuntimeException )
+{
+ SolarMutexGuard aGuard;
+ uno::Any aRet;
+ if(nIndex < 0 || nIndex >= AUTOSTYLE_FAMILY_COUNT)
+ throw lang::IndexOutOfBoundsException();
+ if(IsValid())
+ {
+ uno::Reference< style::XAutoStyleFamily > aRef;
+ IStyleAccess::SwAutoStyleFamily nType = aAutoStyleByIndex[nIndex];
+ switch( nType )
+ {
+ case IStyleAccess::AUTO_STYLE_CHAR:
+ {
+ if(!xAutoCharStyles.is())
+ xAutoCharStyles = new SwXAutoStyleFamily(pDocShell, nType);
+ aRef = xAutoCharStyles;
+ }
+ break;
+ case IStyleAccess::AUTO_STYLE_RUBY:
+ {
+ if(!xAutoRubyStyles.is())
+ xAutoRubyStyles = new SwXAutoStyleFamily(pDocShell, nType );
+ aRef = xAutoRubyStyles;
+ }
+ break;
+ case IStyleAccess::AUTO_STYLE_PARA:
+ {
+ if(!xAutoParaStyles.is())
+ xAutoParaStyles = new SwXAutoStyleFamily(pDocShell, nType );
+ aRef = xAutoParaStyles;
+ }
+ break;
+
+ default:
+ ;
+ }
+ aRet.setValue(&aRef, ::getCppuType((const uno::Reference<style::XAutoStyleFamily>*)0));
+ }
+ else
+ throw uno::RuntimeException();
+ return aRet;
+}
+
+uno::Type SwXAutoStyles::getElementType( ) throw(uno::RuntimeException)
+{
+ return ::getCppuType((const uno::Reference<style::XAutoStyleFamily>*)0);
+}
+
+sal_Bool SwXAutoStyles::hasElements( ) throw(uno::RuntimeException)
+{
+ return sal_True;
+}
+
+uno::Any SwXAutoStyles::getByName(const rtl::OUString& Name)
+ throw( container::NoSuchElementException, lang::WrappedTargetException, uno::RuntimeException )
+{
+ uno::Any aRet;
+ if(Name.compareToAscii("CharacterStyles") == 0 )
+ aRet = getByIndex(0);
+ else if(Name.compareToAscii("RubyStyles") == 0 )
+ aRet = getByIndex(1);
+ else if(Name.compareToAscii("ParagraphStyles") == 0 )
+ aRet = getByIndex(2);
+ else
+ throw container::NoSuchElementException();
+ return aRet;
+}
+
+uno::Sequence< rtl::OUString > SwXAutoStyles::getElementNames(void)
+ throw( uno::RuntimeException )
+{
+ uno::Sequence< OUString > aNames(AUTOSTYLE_FAMILY_COUNT);
+ OUString* pNames = aNames.getArray();
+ pNames[0] = C2U("CharacterStyles");
+ pNames[1] = C2U("RubyStyles");
+ pNames[2] = C2U("ParagraphStyles");
+ return aNames;
+}
+
+sal_Bool SwXAutoStyles::hasByName(const rtl::OUString& Name)
+ throw( uno::RuntimeException )
+{
+ if( Name.compareToAscii("CharacterStyles") == 0 ||
+ Name.compareToAscii("RubyStyles") == 0 ||
+ Name.compareToAscii("ParagraphStyles") == 0 )
+ return sal_True;
+ else
+ return sal_False;
+}
+
+SwXAutoStyleFamily::SwXAutoStyleFamily(SwDocShell* pDocSh, IStyleAccess::SwAutoStyleFamily nFamily) :
+ pDocShell( pDocSh ), eFamily(nFamily)
+{
+ // Register ourselves as a listener to the document (via the page descriptor)
+ pDocSh->GetDoc()->GetPageDescFromPool(RES_POOLPAGE_STANDARD)->Add(this);
+}
+
+SwXAutoStyleFamily::~SwXAutoStyleFamily()
+{
+}
+
+void SwXAutoStyleFamily::Modify( const SfxPoolItem* pOld, const SfxPoolItem *pNew)
+{
+ ClientModify(this, pOld, pNew);
+ if(!GetRegisteredIn())
+ pDocShell = 0;
+}
+
+uno::Reference< style::XAutoStyle > SwXAutoStyleFamily::insertStyle(
+ const uno::Sequence< beans::PropertyValue >& Values )
+ throw (uno::RuntimeException)
+{
+ if( !pDocShell )
+ throw uno::RuntimeException();
+ const sal_uInt16* pRange = 0;
+ const SfxItemPropertySet* pPropSet = 0;
+ switch( eFamily )
+ {
+ case IStyleAccess::AUTO_STYLE_CHAR:
+ {
+ pRange = aCharAutoFmtSetRange;
+ pPropSet = aSwMapProvider.GetPropertySet(PROPERTY_MAP_CHAR_AUTO_STYLE);
+ }
+ break;
+ case IStyleAccess::AUTO_STYLE_RUBY:
+ {
+ pRange = 0;//aTxtNodeSetRange;
+ pPropSet = aSwMapProvider.GetPropertySet(PROPERTY_MAP_RUBY_AUTO_STYLE);
+ }
+ break;
+ case IStyleAccess::AUTO_STYLE_PARA:
+ {
+ pRange = aTxtNodeSetRange;
+ pPropSet = aSwMapProvider.GetPropertySet(PROPERTY_MAP_PARA_AUTO_STYLE);
+ }
+ break;
+
+ default:
+ ;
+ }
+ SwAttrSet aSet( pDocShell->GetDoc()->GetAttrPool(), pRange );
+ const beans::PropertyValue* pSeq = Values.getConstArray();
+ sal_Int32 nLen = Values.getLength();
+ for( sal_Int32 i = 0; i < nLen; ++i )
+ {
+ try
+ {
+ pPropSet->setPropertyValue( pSeq[i].Name, pSeq[i].Value, aSet );
+ }
+ catch (beans::UnknownPropertyException &)
+ {
+ OSL_FAIL( "Unknown property" );
+ }
+ catch (lang::IllegalArgumentException &)
+ {
+ OSL_FAIL( "Illegal argument" );
+ }
+ }
+
+ SfxItemSet_Pointer_t pSet = pDocShell->GetDoc()->GetIStyleAccess().cacheAutomaticStyle( aSet, eFamily );
+ uno::Reference<style::XAutoStyle> xRet = new SwXAutoStyle(pDocShell->GetDoc(), pSet, eFamily);
+ return xRet;
+}
+
+uno::Reference< container::XEnumeration > SwXAutoStyleFamily::createEnumeration( )
+ throw (uno::RuntimeException)
+{
+ if( !pDocShell )
+ throw uno::RuntimeException();
+ return uno::Reference< container::XEnumeration >
+ (new SwXAutoStylesEnumerator( pDocShell->GetDoc(), eFamily ));
+}
+
+uno::Type SwXAutoStyleFamily::getElementType( ) throw(uno::RuntimeException)
+{
+ return ::getCppuType((const uno::Reference<style::XAutoStyle>*)0);
+}
+
+sal_Bool SwXAutoStyleFamily::hasElements( ) throw(uno::RuntimeException)
+{
+ return sal_False;
+}
+
+SwAutoStylesEnumImpl::SwAutoStylesEnumImpl( SwDoc* pInitDoc, IStyleAccess::SwAutoStyleFamily eFam )
+: pDoc( pInitDoc ), eFamily( eFam )
+{
+ // special case for ruby auto styles:
+ if ( IStyleAccess::AUTO_STYLE_RUBY == eFam )
+ {
+ std::set< std::pair< sal_uInt16, sal_uInt16 > > aRubyMap;
+ SwAttrPool& rAttrPool = pDoc->GetAttrPool();
+ sal_uInt32 nCount = rAttrPool.GetItemCount2( RES_TXTATR_CJK_RUBY );
+
+ for ( sal_uInt32 nI = 0; nI < nCount; ++nI )
+ {
+ const SwFmtRuby* pItem = static_cast<const SwFmtRuby*>(rAttrPool.GetItem2( RES_TXTATR_CJK_RUBY, nI ));
+ if ( pItem && pItem->GetTxtRuby() )
+ {
+ std::pair< sal_uInt16, sal_uInt16 > aPair( pItem->GetPosition(), pItem->GetAdjustment() );
+ if ( aRubyMap.find( aPair ) == aRubyMap.end() )
+ {
+ aRubyMap.insert( aPair );
+ SfxItemSet_Pointer_t pItemSet( new SfxItemSet( rAttrPool, RES_TXTATR_CJK_RUBY, RES_TXTATR_CJK_RUBY ) );
+ pItemSet->Put( *pItem );
+ mAutoStyles.push_back( pItemSet );
+ }
+ }
+ }
+ }
+ else
+ {
+ pDoc->GetIStyleAccess().getAllStyles( mAutoStyles, eFamily );
+ }
+
+ aIter = mAutoStyles.begin();
+}
+
+SwXAutoStylesEnumerator::SwXAutoStylesEnumerator( SwDoc* pDoc, IStyleAccess::SwAutoStyleFamily eFam )
+: pImpl( new SwAutoStylesEnumImpl( pDoc, eFam ) )
+{
+ // Register ourselves as a listener to the document (via the page descriptor)
+ pDoc->GetPageDescFromPool(RES_POOLPAGE_STANDARD)->Add(this);
+}
+
+SwXAutoStylesEnumerator::~SwXAutoStylesEnumerator()
+{
+ delete pImpl;
+}
+
+void SwXAutoStylesEnumerator::Modify( const SfxPoolItem* pOld, const SfxPoolItem *pNew)
+{
+ ClientModify(this, pOld, pNew);
+ if(!GetRegisteredIn())
+ {
+ delete pImpl;
+ pImpl = 0;
+ }
+}
+
+::sal_Bool SwXAutoStylesEnumerator::hasMoreElements( )
+ throw (uno::RuntimeException)
+{
+ if( !pImpl )
+ throw uno::RuntimeException();
+ return pImpl->hasMoreElements();
+}
+
+uno::Any SwXAutoStylesEnumerator::nextElement( )
+ throw (container::NoSuchElementException, lang::WrappedTargetException, uno::RuntimeException)
+{
+ if( !pImpl )
+ throw uno::RuntimeException();
+ uno::Any aRet;
+ if( pImpl->hasMoreElements() )
+ {
+ SfxItemSet_Pointer_t pNextSet = pImpl->nextElement();
+ uno::Reference< style::XAutoStyle > xAutoStyle = new SwXAutoStyle(pImpl->getDoc(),
+ pNextSet, pImpl->getFamily());
+ aRet.setValue(&xAutoStyle, ::getCppuType((uno::Reference<style::XAutoStyle>*)0));
+ }
+ return aRet;
+}
+
+SwXAutoStyle::SwXAutoStyle( SwDoc* pDoc, SfxItemSet_Pointer_t pInitSet, IStyleAccess::SwAutoStyleFamily eFam )
+: pSet( pInitSet ), eFamily( eFam )
+{
+ // Register ourselves as a listener to the document (via the page descriptor)
+ pDoc->GetPageDescFromPool(RES_POOLPAGE_STANDARD)->Add(this);
+}
+
+SwXAutoStyle::~SwXAutoStyle()
+{
+}
+
+void SwXAutoStyle::Modify( const SfxPoolItem* pOld, const SfxPoolItem *pNew)
+{
+ ClientModify(this, pOld, pNew);
+ if(!GetRegisteredIn())
+ pSet.reset();
+}
+
+uno::Reference< beans::XPropertySetInfo > SwXAutoStyle::getPropertySetInfo( )
+ throw (uno::RuntimeException)
+{
+ uno::Reference< beans::XPropertySetInfo > xRet;
+ switch( eFamily )
+ {
+ case IStyleAccess::AUTO_STYLE_CHAR:
+ {
+ static uno::Reference< beans::XPropertySetInfo > xCharRef;
+ if(!xCharRef.is())
+ {
+ xCharRef = aSwMapProvider.GetPropertySet(PROPERTY_MAP_CHAR_AUTO_STYLE)->getPropertySetInfo();
+ }
+ xRet = xCharRef;
+ }
+ break;
+ case IStyleAccess::AUTO_STYLE_RUBY:
+ {
+ static uno::Reference< beans::XPropertySetInfo > xRubyRef;
+ if(!xRubyRef.is())
+ {
+ sal_uInt16 nMapId = PROPERTY_MAP_RUBY_AUTO_STYLE;
+ xRubyRef = aSwMapProvider.GetPropertySet(nMapId)->getPropertySetInfo();
+ }
+ xRet = xRubyRef;
+ }
+ break;
+ case IStyleAccess::AUTO_STYLE_PARA:
+ {
+ static uno::Reference< beans::XPropertySetInfo > xParaRef;
+ if(!xParaRef.is())
+ {
+ sal_uInt16 nMapId = PROPERTY_MAP_PARA_AUTO_STYLE;
+ xParaRef = aSwMapProvider.GetPropertySet(nMapId)->getPropertySetInfo();
+ }
+ xRet = xParaRef;
+ }
+ break;
+
+ default:
+ ;
+ }
+
+ return xRet;
+}
+
+void SwXAutoStyle::setPropertyValue( const OUString& /*rPropertyName*/, const uno::Any& /*rValue*/ )
+ throw( beans::UnknownPropertyException,
+ beans::PropertyVetoException,
+ lang::IllegalArgumentException,
+ lang::WrappedTargetException,
+ uno::RuntimeException)
+{
+}
+
+uno::Any SwXAutoStyle::getPropertyValue( const OUString& rPropertyName )
+ throw( beans::UnknownPropertyException,
+ lang::WrappedTargetException,
+ uno::RuntimeException )
+{
+ SolarMutexGuard aGuard;
+ const uno::Sequence<OUString> aProperties(&rPropertyName, 1);
+ return GetPropertyValues_Impl(aProperties).getConstArray()[0];
+}
+
+void SwXAutoStyle::addPropertyChangeListener( const OUString& /*aPropertyName*/,
+ const uno::Reference< beans::XPropertyChangeListener >& /*xListener*/ )
+ throw( beans::UnknownPropertyException,
+ lang::WrappedTargetException,
+ uno::RuntimeException )
+{
+}
+
+void SwXAutoStyle::removePropertyChangeListener( const OUString& /*aPropertyName*/,
+ const uno::Reference< beans::XPropertyChangeListener >& /*aListener*/ )
+ throw( beans::UnknownPropertyException,
+ lang::WrappedTargetException,
+ uno::RuntimeException )
+{
+}
+
+void SwXAutoStyle::addVetoableChangeListener( const OUString& /*PropertyName*/,
+ const uno::Reference< beans::XVetoableChangeListener >& /*aListener*/ )
+ throw( beans::UnknownPropertyException,
+ lang::WrappedTargetException,
+ uno::RuntimeException )
+{
+}
+
+void SwXAutoStyle::removeVetoableChangeListener( const OUString& /*PropertyName*/,
+ const uno::Reference< beans::XVetoableChangeListener >& /*aListener*/ )
+ throw( beans::UnknownPropertyException,
+ lang::WrappedTargetException,
+ uno::RuntimeException )
+{
+}
+
+void SwXAutoStyle::setPropertyValues(
+ const uno::Sequence< ::rtl::OUString >& /*aPropertyNames*/,
+ const uno::Sequence< uno::Any >& /*aValues*/ )
+ throw (beans::PropertyVetoException, lang::IllegalArgumentException,
+ lang::WrappedTargetException, uno::RuntimeException)
+{
+}
+
+uno::Sequence< uno::Any > SwXAutoStyle::GetPropertyValues_Impl(
+ const uno::Sequence< OUString > & rPropertyNames )
+ throw( beans::UnknownPropertyException, lang::WrappedTargetException, uno::RuntimeException )
+{
+ if( !pSet.get() )
+ throw uno::RuntimeException();
+ // query_item
+
+ sal_Int8 nPropSetId = PROPERTY_MAP_CHAR_AUTO_STYLE;
+ switch(eFamily)
+ {
+ case IStyleAccess::AUTO_STYLE_CHAR : nPropSetId = PROPERTY_MAP_CHAR_AUTO_STYLE; break;
+ case IStyleAccess::AUTO_STYLE_RUBY : nPropSetId = PROPERTY_MAP_RUBY_AUTO_STYLE; break;
+ case IStyleAccess::AUTO_STYLE_PARA : nPropSetId = PROPERTY_MAP_PARA_AUTO_STYLE; break;
+ default:
+ ;
+ }
+
+ const SfxItemPropertySet* pPropSet = aSwMapProvider.GetPropertySet(nPropSetId);
+ const SfxItemPropertyMap *pMap = pPropSet->getPropertyMap();
+ const OUString* pNames = rPropertyNames.getConstArray();
+
+ sal_Int32 nLen = rPropertyNames.getLength();
+ uno::Sequence< uno::Any > aRet( nLen );
+ uno::Any* pValues = aRet.getArray();
+
+ SfxItemSet& rSet = *pSet.get();
+
+ for( sal_Int32 i = 0; i < nLen; ++i )
+ {
+ const String& rPropName = pNames[i];
+ const SfxItemPropertySimpleEntry* pEntry = pMap->getByName(rPropName);
+ if(!pEntry)
+ throw beans::UnknownPropertyException(OUString ( RTL_CONSTASCII_USTRINGPARAM ( "Unknown property: " ) ) + rPropName, static_cast < cppu::OWeakObject * > ( this ) );
+ else if ( RES_TXTATR_AUTOFMT == pEntry->nWID || RES_AUTO_STYLE == pEntry->nWID )
+ {
+ OUString sName(StylePool::nameOf( pSet ));
+ pValues[i] <<= sName;
+ }
+ else
+ pPropSet->getPropertyValue( *pEntry, rSet, pValues[i] );
+ }
+ return aRet;
+}
+
+uno::Sequence< uno::Any > SwXAutoStyle::getPropertyValues (
+ const uno::Sequence< ::rtl::OUString >& rPropertyNames )
+ throw (uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+ uno::Sequence< uno::Any > aValues;
+
+ // workaround for bad designed API
+ try
+ {
+ aValues = GetPropertyValues_Impl( rPropertyNames );
+ }
+ catch (beans::UnknownPropertyException &)
+ {
+ throw uno::RuntimeException(OUString ( RTL_CONSTASCII_USTRINGPARAM ( "Unknown property exception caught" ) ), static_cast < cppu::OWeakObject * > ( this ) );
+ }
+ catch (lang::WrappedTargetException &)
+ {
+ throw uno::RuntimeException(OUString ( RTL_CONSTASCII_USTRINGPARAM ( "WrappedTargetException caught" ) ), static_cast < cppu::OWeakObject * > ( this ) );
+ }
+
+ return aValues;
+}
+
+void SwXAutoStyle::addPropertiesChangeListener(
+ const uno::Sequence< ::rtl::OUString >& /*aPropertyNames*/,
+ const uno::Reference< beans::XPropertiesChangeListener >& /*xListener*/ )
+ throw (uno::RuntimeException)
+{
+}
+
+void SwXAutoStyle::removePropertiesChangeListener(
+ const uno::Reference< beans::XPropertiesChangeListener >& /*xListener*/ )
+ throw (uno::RuntimeException)
+{
+}
+
+void SwXAutoStyle::firePropertiesChangeEvent(
+ const uno::Sequence< ::rtl::OUString >& /*aPropertyNames*/,
+ const uno::Reference< beans::XPropertiesChangeListener >& /*xListener*/ )
+ throw (uno::RuntimeException)
+{
+}
+
+beans::PropertyState SwXAutoStyle::getPropertyState( const OUString& rPropertyName )
+ throw( beans::UnknownPropertyException,
+ uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+
+ uno::Sequence< OUString > aNames(1);
+ OUString* pNames = aNames.getArray();
+ pNames[0] = rPropertyName;
+ uno::Sequence< beans::PropertyState > aStates = getPropertyStates(aNames);
+ return aStates.getConstArray()[0];
+}
+
+void SwXAutoStyle::setPropertyToDefault( const OUString& /*PropertyName*/ )
+ throw( beans::UnknownPropertyException,
+ uno::RuntimeException )
+{
+}
+
+uno::Any SwXAutoStyle::getPropertyDefault( const OUString& rPropertyName )
+ throw( beans::UnknownPropertyException,
+ lang::WrappedTargetException,
+ uno::RuntimeException)
+{
+ const uno::Sequence < OUString > aSequence ( &rPropertyName, 1 );
+ return getPropertyDefaults ( aSequence ).getConstArray()[0];
+}
+
+uno::Sequence< beans::PropertyState > SwXAutoStyle::getPropertyStates(
+ const uno::Sequence< ::rtl::OUString >& rPropertyNames )
+ throw (beans::UnknownPropertyException, uno::RuntimeException)
+{
+ if( !pSet.get() )
+ throw uno::RuntimeException();
+ SolarMutexGuard aGuard;
+ uno::Sequence< beans::PropertyState > aRet(rPropertyNames.getLength());
+ beans::PropertyState* pStates = aRet.getArray();
+ const OUString* pNames = rPropertyNames.getConstArray();
+
+ sal_Int8 nPropSetId = PROPERTY_MAP_CHAR_AUTO_STYLE;
+ switch(eFamily)
+ {
+ case IStyleAccess::AUTO_STYLE_CHAR : nPropSetId = PROPERTY_MAP_CHAR_AUTO_STYLE; break;
+ case IStyleAccess::AUTO_STYLE_RUBY : nPropSetId = PROPERTY_MAP_RUBY_AUTO_STYLE; break;
+ case IStyleAccess::AUTO_STYLE_PARA : nPropSetId = PROPERTY_MAP_PARA_AUTO_STYLE; break;
+ default:
+ ;
+ }
+
+ const SfxItemPropertySet* pPropSet = aSwMapProvider.GetPropertySet(nPropSetId);
+ const SfxItemPropertyMap *pMap = pPropSet->getPropertyMap();
+ SfxItemSet& rSet = *pSet.get();
+ for(sal_Int32 i = 0; i < rPropertyNames.getLength(); i++)
+ {
+ const String& rPropName = pNames[i];
+ const SfxItemPropertySimpleEntry* pEntry = pMap->getByName(rPropName);
+ if(!pEntry)
+ throw beans::UnknownPropertyException(OUString ( RTL_CONSTASCII_USTRINGPARAM ( "Unknown property: " ) ) + rPropName, static_cast < cppu::OWeakObject * > ( this ) );
+ pStates[i] = pPropSet->getPropertyState(*pEntry, rSet );
+ }
+ return aRet;
+}
+
+void SwXAutoStyle::setAllPropertiesToDefault( )
+ throw (uno::RuntimeException)
+{
+}
+
+void SwXAutoStyle::setPropertiesToDefault(
+ const uno::Sequence< ::rtl::OUString >& /*aPropertyNames*/ )
+ throw (beans::UnknownPropertyException, uno::RuntimeException)
+{
+}
+
+uno::Sequence< uno::Any > SwXAutoStyle::getPropertyDefaults(
+ const uno::Sequence< ::rtl::OUString >& /*aPropertyNames*/ )
+ throw (beans::UnknownPropertyException, lang::WrappedTargetException,
+ uno::RuntimeException)
+{
+ uno::Sequence< uno::Any > aRet(0);
+ return aRet;
+}
+
+uno::Sequence< beans::PropertyValue > SwXAutoStyle::getProperties() throw (uno::RuntimeException)
+{
+ if( !pSet.get() )
+ throw uno::RuntimeException();
+ SolarMutexGuard aGuard;
+ std::vector< beans::PropertyValue > aPropertyVector;
+
+ sal_Int8 nPropSetId = 0;
+ switch(eFamily)
+ {
+ case IStyleAccess::AUTO_STYLE_CHAR : nPropSetId = PROPERTY_MAP_CHAR_AUTO_STYLE; break;
+ case IStyleAccess::AUTO_STYLE_RUBY : nPropSetId = PROPERTY_MAP_RUBY_AUTO_STYLE; break;
+ case IStyleAccess::AUTO_STYLE_PARA : nPropSetId = PROPERTY_MAP_PARA_AUTO_STYLE; break;
+ default:
+ ;
+ }
+
+ const SfxItemPropertySet* pPropSet = aSwMapProvider.GetPropertySet(nPropSetId);
+ const SfxItemPropertyMap *pMap = pPropSet->getPropertyMap();
+ PropertyEntryVector_t aPropVector = pMap->getPropertyEntries();
+
+ SfxItemSet& rSet = *pSet.get();
+ SfxItemIter aIter(rSet);
+ const SfxPoolItem* pItem = aIter.FirstItem();
+
+ while ( pItem )
+ {
+ const sal_uInt16 nWID = pItem->Which();
+
+ // TODO: Optimize - and fix! the old iteration filled each WhichId
+ // only once but there are more properties than WhichIds
+ PropertyEntryVector_t::const_iterator aIt = aPropVector.begin();
+ while( aIt != aPropVector.end() )
+ {
+ if ( aIt->nWID == nWID )
+ {
+ beans::PropertyValue aPropertyValue;
+ aPropertyValue.Name = aIt->sName;
+ pItem->QueryValue( aPropertyValue.Value, aIt->nMemberId );
+ aPropertyVector.push_back( aPropertyValue );
+ }
+ ++aIt;
+ }
+ pItem = aIter.NextItem();
+ }
+
+ const sal_Int32 nCount = aPropertyVector.size();
+ uno::Sequence< beans::PropertyValue > aRet( nCount );
+ beans::PropertyValue* pProps = aRet.getArray();
+
+ for ( int i = 0; i < nCount; ++i, pProps++ )
+ {
+ *pProps = aPropertyVector[i];
+ }
+
+ return aRet;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/unocore/unotbl.cxx b/sw/source/core/unocore/unotbl.cxx
new file mode 100644
index 000000000000..89839f5dcb17
--- /dev/null
+++ b/sw/source/core/unocore/unotbl.cxx
@@ -0,0 +1,5045 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+
+// STL includes
+#include <list>
+
+#include <svx/svxids.hrc>
+#include <editeng/memberids.hrc>
+#include <float.h> // for DBL_MIN
+#include <swtypes.hxx>
+#include <cmdid.h>
+#include <unotbl.hxx>
+#include <unostyle.hxx>
+#include <section.hxx>
+#include <unocrsr.hxx>
+#include <svx/unomid.hxx>
+#include <hints.hxx>
+#include <swtblfmt.hxx>
+#include <doc.hxx>
+#include <IDocumentUndoRedo.hxx>
+#include <shellres.hxx>
+#include <docary.hxx>
+#include <ndole.hxx>
+#include <frame.hxx>
+#include <vcl/svapp.hxx>
+#include <fmtfsize.hxx>
+#include <tblafmt.hxx>
+#include <tabcol.hxx>
+#include <cellatr.hxx>
+#include <fmtpdsc.hxx>
+#include <pagedesc.hxx>
+#define _SVSTDARR_STRINGS
+#include <svl/svstdarr.hxx>
+#include <viewsh.hxx>
+#include <tabfrm.hxx>
+#include <redline.hxx>
+#include <unoredline.hxx>
+#include <unoprnms.hxx>
+#include <unocrsrhelper.hxx>
+#include <com/sun/star/text/WrapTextMode.hpp>
+#include <com/sun/star/text/TextContentAnchorType.hpp>
+#include <com/sun/star/text/TableColumnSeparator.hpp>
+#include <com/sun/star/text/XTextSection.hpp>
+#include <com/sun/star/text/VertOrientation.hpp>
+#include <com/sun/star/table/ShadowFormat.hpp>
+#include <com/sun/star/table/TableBorder.hpp>
+#include <com/sun/star/table/BorderLine2.hpp>
+#include <com/sun/star/table/TableBorderDistances.hpp>
+#include <com/sun/star/style/PageStyleLayout.hpp>
+#include <com/sun/star/style/BreakType.hpp>
+#include <com/sun/star/style/GraphicLocation.hpp>
+#include <com/sun/star/beans/PropertyAttribute.hpp>
+#include <com/sun/star/chart/XChartDataChangeEventListener.hpp>
+#include <com/sun/star/chart/ChartDataChangeEvent.hpp>
+#include <com/sun/star/chart2/data/XDataSequence.hpp>
+#include <com/sun/star/chart2/data/XLabeledDataSequence.hpp>
+#include <com/sun/star/table/CellContentType.hpp>
+#include <unotextrange.hxx>
+#include <unotextcursor.hxx>
+#include <unoparagraph.hxx>
+#include <svl/zforlist.hxx> // SvNumberFormatter
+#include <editeng/brkitem.hxx>
+#include <editeng/shaditem.hxx>
+#include <editeng/lrspitem.hxx>
+#include <editeng/ulspitem.hxx>
+#include <fmtornt.hxx>
+#include <editeng/keepitem.hxx>
+#include <fmtlsplt.hxx>
+#include <swundo.hxx>
+#include <osl/mutex.hxx>
+#include <SwStyleNameMapper.hxx>
+#include <frmatr.hxx>
+#include <crsskip.hxx>
+#include <unochart.hxx>
+#include <sortopt.hxx>
+#include <rtl/math.hxx>
+#include <editeng/frmdiritem.hxx>
+#include <switerator.hxx>
+
+using namespace ::com::sun::star;
+using ::rtl::OUString;
+using ::editeng::SvxBorderLine;
+
+// from swtable.cxx
+extern void lcl_GetTblBoxColStr( sal_uInt16 nCol, String& rNm );
+
+#define UNO_TABLE_COLUMN_SUM 10000
+
+table::BorderLine lcl_SvxLineToLine(const SvxBorderLine* pLine)
+{
+ table::BorderLine2 aLine;
+ if(pLine)
+ {
+ aLine.Color = pLine->GetColor().GetColor() ;
+ aLine.LineWidth = TWIP_TO_MM100_UNSIGNED( pLine->GetWidth() );
+
+ // Set only for backwards compatibility
+ aLine.InnerLineWidth = TWIP_TO_MM100_UNSIGNED( pLine->GetInWidth() );
+ aLine.OuterLineWidth = TWIP_TO_MM100_UNSIGNED( pLine->GetOutWidth() );
+ aLine.LineDistance = TWIP_TO_MM100_UNSIGNED( pLine->GetDistance() );
+ }
+ else
+ aLine.Color = aLine.InnerLineWidth = aLine.OuterLineWidth = aLine.LineDistance = 0;
+ return aLine;
+}
+
+sal_Bool lcl_LineToSvxLine(const table::BorderLine& rLine, SvxBorderLine& rSvxLine)
+{
+ const table::BorderLine2& rLine2 = static_cast< const table::BorderLine2& >( rLine );
+ rSvxLine.SetColor( Color(rLine.Color));
+
+ if ( rLine2.LineWidth > 0 )
+ {
+ rSvxLine.SetStyle( editeng::SvxBorderStyle( rLine2.LineStyle ) );
+ rSvxLine.SetWidth( MM100_TO_TWIP_UNSIGNED( rLine2.LineWidth ) );
+ }
+ else
+ rSvxLine.GuessLinesWidths( editeng::SvxBorderStyle( rLine2.LineStyle ),
+ MM100_TO_TWIP( rLine.OuterLineWidth ),
+ MM100_TO_TWIP( rLine.InnerLineWidth ),
+ MM100_TO_TWIP( rLine.LineDistance ) );
+ sal_Bool bRet = rLine.InnerLineWidth > 0 || rLine.OuterLineWidth > 0 || rLine2.LineWidth > 0;
+ return bRet;
+}
+
+void lcl_SetSpecialProperty(SwFrmFmt* pFmt, const SfxItemPropertySimpleEntry* pEntry, const uno::Any& aValue)
+ throw (lang::IllegalArgumentException)
+{
+ //Sonderbehandlung fuer "Nicht-Items"
+ switch(pEntry->nWID)
+ {
+ case FN_TABLE_HEADLINE_REPEAT:
+ case FN_TABLE_HEADLINE_COUNT:
+ {
+ SwTable* pTable = SwTable::FindTable( pFmt );
+ {
+ UnoActionContext aAction(pFmt->GetDoc());
+ if( pEntry->nWID == FN_TABLE_HEADLINE_REPEAT)
+ {
+ sal_Bool bVal = *(sal_Bool*)aValue.getValue();
+ pFmt->GetDoc()->SetRowsToRepeat( *pTable, bVal ? 1 : 0 );
+ }
+ else
+ {
+ sal_Int32 nRepeat = 0;
+ aValue >>= nRepeat;
+ if( nRepeat >= 0 && nRepeat < USHRT_MAX )
+ pFmt->GetDoc()->SetRowsToRepeat( *pTable, (sal_uInt16) nRepeat );
+ }
+ }
+ }
+ break;
+ case FN_TABLE_IS_RELATIVE_WIDTH:
+ case FN_TABLE_WIDTH:
+ case FN_TABLE_RELATIVE_WIDTH:
+ {
+ SwFmtFrmSize aSz( pFmt->GetFrmSize() );
+ if(FN_TABLE_WIDTH == pEntry->nWID)
+ {
+ sal_Int32 nWidth = 0;
+ aValue >>= nWidth;
+ aSz.SetWidthPercent(0);
+ aSz.SetWidth ( MM100_TO_TWIP ( nWidth ) );
+ }
+ else if(FN_TABLE_RELATIVE_WIDTH == pEntry->nWID)
+ {
+ sal_Int16 nSet = 0;
+ aValue >>= nSet;
+ if(nSet && nSet <=100)
+ aSz.SetWidthPercent( (sal_uInt8)nSet );
+ }
+ else if(FN_TABLE_IS_RELATIVE_WIDTH == pEntry->nWID)
+ {
+ sal_Bool bPercent = *(sal_Bool*)aValue.getValue();
+ if(!bPercent)
+ aSz.SetWidthPercent(0);
+ else
+ {
+ lang::IllegalArgumentException aExcept;
+ aExcept.Message = C2U("relative width cannot be switched on with this property");
+ throw aExcept;
+ }
+ }
+ pFmt->GetDoc()->SetAttr(aSz, *pFmt);
+ }
+ break;
+ case RES_PAGEDESC:
+ {
+ OUString uTemp;
+ aValue >>= uTemp;
+ String sPageStyle = uTemp;
+ const SwPageDesc* pDesc = 0;
+ if(sPageStyle.Len())
+ {
+ SwStyleNameMapper::FillUIName(sPageStyle, sPageStyle, nsSwGetPoolIdFromName::GET_POOLID_PAGEDESC, sal_True );
+ pDesc = ::GetPageDescByName_Impl(*pFmt->GetDoc(), sPageStyle);
+ }
+ SwFmtPageDesc aDesc( pDesc );
+ pFmt->GetDoc()->SetAttr(aDesc, *pFmt);
+ }
+ break;
+ default:
+ throw lang::IllegalArgumentException();
+ }
+}
+
+uno::Any lcl_GetSpecialProperty(SwFrmFmt* pFmt, const SfxItemPropertySimpleEntry* pEntry )
+{
+ uno::Any aRet;
+ switch(pEntry->nWID)
+ {
+ case FN_TABLE_HEADLINE_REPEAT:
+ case FN_TABLE_HEADLINE_COUNT:
+ {
+ SwTable* pTable = SwTable::FindTable( pFmt );
+ sal_uInt16 nRepeat = pTable->GetRowsToRepeat();
+ if(pEntry->nWID == FN_TABLE_HEADLINE_REPEAT)
+ {
+ sal_Bool bTemp = nRepeat > 0;
+ aRet.setValue(&bTemp, ::getCppuBooleanType());
+ }
+ else
+ aRet <<= (sal_Int32)nRepeat;
+ }
+ break;
+ case FN_TABLE_WIDTH:
+ case FN_TABLE_IS_RELATIVE_WIDTH:
+ case FN_TABLE_RELATIVE_WIDTH:
+ {
+ const SwFmtFrmSize& rSz = pFmt->GetFrmSize();
+ if(FN_TABLE_WIDTH == pEntry->nWID)
+ rSz.QueryValue(aRet, MID_FRMSIZE_WIDTH|CONVERT_TWIPS);
+ else if(FN_TABLE_RELATIVE_WIDTH == pEntry->nWID)
+ rSz.QueryValue(aRet, MID_FRMSIZE_REL_WIDTH);
+ else
+ {
+ sal_Bool bTemp = 0 != rSz.GetWidthPercent();
+ aRet.setValue(&bTemp, ::getBooleanCppuType());
+ }
+ }
+ break;
+ case RES_PAGEDESC:
+ {
+ const SfxItemSet& rSet = pFmt->GetAttrSet();
+ const SfxPoolItem* pItem;
+ String sPDesc;
+ if(SFX_ITEM_SET == rSet.GetItemState(RES_PAGEDESC, sal_False, &pItem))
+ {
+ const SwPageDesc* pDsc = ((const SwFmtPageDesc*)pItem)->GetPageDesc();
+ if(pDsc)
+ {
+ sPDesc = SwStyleNameMapper::GetProgName(pDsc->GetName(), nsSwGetPoolIdFromName::GET_POOLID_PAGEDESC );
+ }
+ }
+ aRet <<= OUString(sPDesc);
+ }
+ break;
+ case RES_ANCHOR :
+ aRet <<= text::TextContentAnchorType_AT_PARAGRAPH;
+ break;
+ case FN_UNO_ANCHOR_TYPES :
+ {
+ uno::Sequence<text::TextContentAnchorType> aTypes(1);
+ text::TextContentAnchorType* pArray = aTypes.getArray();
+ pArray[0] = text::TextContentAnchorType_AT_PARAGRAPH;
+ aRet <<= aTypes;
+ }
+ break;
+ case FN_UNO_WRAP :
+ {
+ aRet <<= text::WrapTextMode_NONE;
+ }
+ break;
+ case FN_PARAM_LINK_DISPLAY_NAME :
+ aRet <<= OUString(pFmt->GetName());
+ break;
+ case FN_UNO_REDLINE_NODE_START:
+ case FN_UNO_REDLINE_NODE_END:
+ {
+ SwTable* pTable = SwTable::FindTable( pFmt );
+ SwNode* pTblNode = pTable->GetTableNode();
+ if(FN_UNO_REDLINE_NODE_END == pEntry->nWID)
+ pTblNode = pTblNode->EndOfSectionNode();
+ const SwRedlineTbl& rRedTbl = pFmt->GetDoc()->GetRedlineTbl();
+ for(sal_uInt16 nRed = 0; nRed < rRedTbl.Count(); nRed++)
+ {
+ const SwRedline* pRedline = rRedTbl[nRed];
+ const SwNode* pRedPointNode = pRedline->GetNode(sal_True);
+ const SwNode* pRedMarkNode = pRedline->GetNode(sal_False);
+ if(pRedPointNode == pTblNode || pRedMarkNode == pTblNode)
+ {
+ const SwNode* pStartOfRedline = SwNodeIndex(*pRedPointNode) <= SwNodeIndex(*pRedMarkNode) ?
+ pRedPointNode : pRedMarkNode;
+ sal_Bool bIsStart = pStartOfRedline == pTblNode;
+ aRet <<= SwXRedlinePortion::CreateRedlineProperties(*pRedline, bIsStart);
+ break;
+ }
+ }
+ }
+ break;
+ }
+ return aRet;
+}
+
+// returns the position for the cell with the specified name
+// (note that the indices rColumn and rRow are 0 based here)
+// Also since the implementations of tables does not really have
+// columns using this function is appropriate only for tables
+// that are not complex (i.e. where IsTblComplex() returns false).
+//
+// returns: both indices for column and row (all >= 0) if everything was Ok.
+// At least one value < 0 if sth was wrong.
+//
+// Sample for naming scheme of cell in a single row (in groups a 26):
+// A1..Z1, a1..z1, AA1..AZ1, Aa1..Az1, BA1..BZ1, Ba1..Bz1, ...
+void lcl_GetCellPosition( const String &rCellName,
+ sal_Int32 &rColumn, sal_Int32 &rRow)
+{
+ rColumn = rRow = -1; // default return values indicating failure
+ xub_StrLen nLen = rCellName.Len();
+ if (nLen)
+ {
+ const sal_Unicode *pBuf = rCellName.GetBuffer();
+ const sal_Unicode *pEnd = pBuf + nLen;
+ while (pBuf < pEnd && !('0' <= *pBuf && *pBuf <= '9'))
+ ++pBuf;
+ // start of number found?
+ if (pBuf < pEnd && ('0' <= *pBuf && *pBuf <= '9'))
+ {
+ String aColTxt( rCellName.GetBuffer(), static_cast< xub_StrLen >(pBuf - rCellName.GetBuffer()) );
+ String aRowTxt( pBuf, static_cast< xub_StrLen >(rCellName.GetBuffer() + nLen - pBuf) );
+ if (aColTxt.Len() && aRowTxt.Len())
+ {
+ sal_Int32 nColIdx = 0;
+ sal_Int32 nLength = aColTxt.Len();
+ for (xub_StrLen i = 0; i < nLength; ++i)
+ {
+ nColIdx = 52 * nColIdx;
+ if (i < nLength - 1)
+ ++nColIdx;
+ sal_Unicode cChar = aColTxt.GetBuffer()[i];
+ if ('A' <= cChar && cChar <= 'Z')
+ nColIdx = nColIdx + (cChar - 'A');
+ else if ('a' <= cChar && cChar <= 'z')
+ nColIdx = nColIdx + (26 + cChar - 'a');
+ else
+ {
+ nColIdx = -1; // sth failed
+ break;
+ }
+ }
+
+ rColumn = nColIdx;
+ rRow = aRowTxt.ToInt32() - 1; // - 1 because indices ought to be 0 based
+ }
+ }
+ }
+#if OSL_DEBUG_LEVEL > 1
+ DBG_ASSERT( rColumn != -1 && rRow != -1, "failed to get column or row index" );
+#endif
+}
+
+// arguments: must be non-empty strings with valid cell names
+//
+// returns: -1 if first cell < second cell
+// 0 if both cells are equal
+// +1 if the first cell > second cell
+//
+// Note: this function probably also make sense only
+// for cell names of non-complex tables
+int lcl_CompareCellsByRowFirst( const String &rCellName1, const String &rCellName2 )
+{
+ sal_Int32 nCol1 = -1, nRow1 = -1, nCol2 = -1, nRow2 = -1;
+ lcl_GetCellPosition( rCellName1, nCol1, nRow1 );
+ lcl_GetCellPosition( rCellName2, nCol2, nRow2 );
+
+ if (nRow1 < nRow2 || (nRow1 == nRow2 && nCol1 < nCol2))
+ return -1;
+ else if (nCol1 == nCol2 && nRow1 == nRow2)
+ return 0;
+ else
+ return +1;
+}
+
+// arguments: must be non-empty strings with valid cell names
+//
+// returns: -1 if first cell < second cell
+// 0 if both cells are equal
+// +1 if the first cell > second cell
+//
+// Note: this function probably also make sense only
+// for cell names of non-complex tables
+int lcl_CompareCellsByColFirst( const String &rCellName1, const String &rCellName2 )
+{
+ sal_Int32 nCol1 = -1, nRow1 = -1, nCol2 = -1, nRow2 = -1;
+ lcl_GetCellPosition( rCellName1, nCol1, nRow1 );
+ lcl_GetCellPosition( rCellName2, nCol2, nRow2 );
+
+ if (nCol1 < nCol2 || (nCol1 == nCol2 && nRow1 < nRow2))
+ return -1;
+ else if (nRow1 == nRow2 && nCol1 == nCol2)
+ return 0;
+ else
+ return +1;
+}
+
+// arguments: must be non-empty strings with valid cell names
+//
+// returns: -1 if first cell range < second cell range
+// 0 if both cell ranges are identical
+// +1 if the first cell range > second cell range
+//
+// Note: this function probably also make sense only
+// for cell names of non-complex tables
+int lcl_CompareCellRanges(
+ const String &rRange1StartCell, const String &rRange1EndCell,
+ const String &rRange2StartCell, const String &rRange2EndCell,
+ sal_Bool bCmpColsFirst )
+{
+ int (*pCompareCells)( const String &, const String & ) =
+ bCmpColsFirst ? &lcl_CompareCellsByColFirst : &lcl_CompareCellsByRowFirst;
+
+ int nCmpResStartCells = pCompareCells( rRange1StartCell, rRange2StartCell );
+ if ((-1 == nCmpResStartCells ) ||
+ ( 0 == nCmpResStartCells &&
+ -1 == pCompareCells( rRange1EndCell, rRange2EndCell ) ))
+ return -1;
+ else if (0 == nCmpResStartCells &&
+ 0 == pCompareCells( rRange1EndCell, rRange2EndCell ))
+ return 0;
+ else
+ return +1;
+}
+
+// returns the cell name for the cell at the specified position
+// (note that the indices nColumn and nRow are 0 based here)
+String lcl_GetCellName( sal_Int32 nColumn, sal_Int32 nRow )
+{
+#if OSL_DEBUG_LEVEL > 1
+ {
+ sal_Int32 nCol, nRow2;
+ lcl_GetCellPosition( String::CreateFromAscii("z1"), nCol, nRow2);
+ DBG_ASSERT( nCol == 51, "lcl_GetCellPosition failed" );
+ lcl_GetCellPosition( String::CreateFromAscii("AA1"), nCol, nRow2);
+ DBG_ASSERT( nCol == 52, "lcl_GetCellPosition failed" );
+ lcl_GetCellPosition( String::CreateFromAscii("AB1"), nCol, nRow2);
+ DBG_ASSERT( nCol == 53, "lcl_GetCellPosition failed" );
+ lcl_GetCellPosition( String::CreateFromAscii("BB1"), nCol, nRow2);
+ DBG_ASSERT( nCol == 105, "lcl_GetCellPosition failed" );
+ }
+#endif
+
+ String sCellName;
+ if (nColumn < 0 || nRow < 0)
+ return sCellName;
+ lcl_GetTblBoxColStr( static_cast< sal_uInt16 >(nColumn), sCellName );
+ sCellName += String::CreateFromInt32( nRow + 1 );
+ return sCellName;
+}
+
+/** Find the top left or bottom right corner box in given table.
+ Consider nested lines when finding the box.
+
+ @param i_pTable the table
+
+ @param i_bTopLeft if true, find top left box, otherwise find bottom
+ right box
+ */
+const SwTableBox* lcl_FindCornerTableBox(const SwTableLines& rTableLines, const bool i_bTopLeft)
+{
+ bool bFirst = true;
+ const SwTableBox* pBox = 0;
+ do
+ {
+ const SwTableLines& rLines(bFirst ? rTableLines : pBox->GetTabLines());
+ bFirst = false;
+ OSL_ASSERT(rLines.Count() != 0);
+ if (rLines.Count() != 0)
+ {
+ const SwTableLine* pLine(rLines[i_bTopLeft ? 0 : rLines.Count() - 1]);
+ OSL_ASSERT(pLine);
+ const SwTableBoxes& rBoxes(pLine->GetTabBoxes());
+ OSL_ASSERT(rBoxes.Count() != 0);
+ pBox = rBoxes[i_bTopLeft ? 0 : rBoxes.Count() - 1];
+ OSL_ASSERT(pBox);
+ }
+ else
+ {
+ pBox = 0;
+ }
+ } while (pBox && !pBox->GetSttNd());
+ return pBox;
+}
+
+// start cell should be in the upper-left corner of the range and
+// end cell in the lower-right.
+// I.e. from the four possible representation
+// A1:C5, C5:A1, A5:C1, C1:A5
+// only A1:C5 is the one to use
+void lcl_NormalizeRange(
+ String &rCell1, // will hold the upper-left cell of the range upon return
+ String &rCell2 ) // will hold the lower-right cell of the range upon return
+{
+ sal_Int32 nCol1 = -1, nRow1 = -1, nCol2 = -1, nRow2 = -1;
+ lcl_GetCellPosition( rCell1, nCol1, nRow1 );
+ lcl_GetCellPosition( rCell2, nCol2, nRow2 );
+ if (nCol2 < nCol1 || nRow2 < nRow1)
+ {
+ rCell1 = lcl_GetCellName( Min(nCol1, nCol2), Min(nRow1, nRow2) );
+ rCell2 = lcl_GetCellName( Max(nCol1, nCol2), Max(nRow1, nRow2) );
+ }
+
+}
+
+void SwRangeDescriptor::Normalize()
+{
+ if (nTop > nBottom)
+ {
+ sal_Int32 nTmp = nTop;
+ nTop = nBottom;
+ nBottom = nTmp;
+ }
+ if (nLeft > nRight)
+ {
+ sal_Int32 nTmp = nLeft;
+ nLeft = nRight;
+ nRight = nTmp;
+ }
+}
+
+SwXCell* lcl_CreateXCell(SwFrmFmt* pFmt, sal_Int32 nColumn, sal_Int32 nRow)
+{
+ SwXCell* pXCell = 0;
+ String sCellName = lcl_GetCellName(nColumn, nRow);
+ SwTable* pTable = SwTable::FindTable( pFmt );
+ SwTableBox* pBox = (SwTableBox*)pTable->GetTblBox( sCellName );
+ if(pBox)
+ {
+ pXCell = SwXCell::CreateXCell(pFmt, pBox, pTable);
+ }
+ return pXCell;
+}
+
+void lcl_InspectLines(SwTableLines& rLines, SvStrings& rAllNames)
+{
+ for( sal_uInt16 i = 0; i < rLines.Count(); i++ )
+ {
+ SwTableLine* pLine = rLines[i];
+ SwTableBoxes& rBoxes = pLine->GetTabBoxes();
+ for(sal_uInt16 j = 0; j < rBoxes.Count(); j++)
+ {
+ SwTableBox* pBox = rBoxes[j];
+ if(pBox->GetName().Len() && pBox->getRowSpan() > 0 )
+ rAllNames.Insert(new String(pBox->GetName()), rAllNames.Count());
+ SwTableLines& rBoxLines = pBox->GetTabLines();
+ if(rBoxLines.Count())
+ {
+ lcl_InspectLines(rBoxLines, rAllNames);
+ }
+ }
+ }
+}
+
+void lcl_FormatTable(SwFrmFmt* pTblFmt)
+{
+ SwIterator<SwFrm,SwFmt> aIter( *pTblFmt );
+ for( SwFrm* pFrm = aIter.First(); pFrm; pFrm = aIter.Next() )
+ {
+ // mba: no TYPEINFO for SwTabFrm
+ if( pFrm->IsTabFrm() )
+ {
+ if(pFrm->IsValid())
+ pFrm->InvalidatePos();
+ ((SwTabFrm*)pFrm)->SetONECalcLowers();
+ ((SwTabFrm*)pFrm)->Calc();
+ }
+ }
+}
+
+void lcl_CrsrSelect(SwPaM* pCrsr, sal_Bool bExpand)
+{
+ if(bExpand)
+ {
+ if(!pCrsr->HasMark())
+ pCrsr->SetMark();
+ }
+ else if(pCrsr->HasMark())
+ pCrsr->DeleteMark();
+
+}
+
+void lcl_GetTblSeparators(uno::Any& rRet, SwTable* pTable, SwTableBox* pBox, sal_Bool bRow)
+{
+ SwTabCols aCols;
+ aCols.SetLeftMin ( 0 );
+ aCols.SetLeft ( 0 );
+ aCols.SetRight ( UNO_TABLE_COLUMN_SUM );
+ aCols.SetRightMax( UNO_TABLE_COLUMN_SUM );
+
+ pTable->GetTabCols( aCols, pBox, sal_False, bRow );
+
+ sal_uInt16 nSepCount = aCols.Count();
+ uno::Sequence< text::TableColumnSeparator> aColSeq(nSepCount);
+ text::TableColumnSeparator* pArray = aColSeq.getArray();
+ sal_Bool bError = sal_False;
+ for(sal_uInt16 i = 0; i < nSepCount; i++)
+ {
+ pArray[i].Position = static_cast< sal_Int16 >(aCols[i]);
+ pArray[i].IsVisible = !aCols.IsHidden(i);
+ if(!bRow && !pArray[i].IsVisible)
+ {
+ bError = sal_True;
+ break;
+ }
+ }
+ if(!bError)
+ rRet.setValue(&aColSeq, ::getCppuType((uno::Sequence< text::TableColumnSeparator>*)0));
+
+}
+
+void lcl_SetTblSeparators(const uno::Any& rVal, SwTable* pTable, SwTableBox* pBox, sal_Bool bRow, SwDoc* pDoc)
+{
+ SwTabCols aOldCols;
+
+ aOldCols.SetLeftMin ( 0 );
+ aOldCols.SetLeft ( 0 );
+ aOldCols.SetRight ( UNO_TABLE_COLUMN_SUM );
+ aOldCols.SetRightMax( UNO_TABLE_COLUMN_SUM );
+
+ pTable->GetTabCols( aOldCols, pBox, sal_False, bRow );
+ sal_uInt16 nOldCount = aOldCols.Count();
+ //there's no use in setting tab cols if there's only one column
+ if( !nOldCount )
+ return;
+
+ const uno::Sequence< text::TableColumnSeparator>* pSepSeq =
+ (uno::Sequence< text::TableColumnSeparator>*) rVal.getValue();
+ if(pSepSeq && pSepSeq->getLength() == nOldCount)
+ {
+ SwTabCols aCols(aOldCols);
+ sal_Bool bError = sal_False;
+ const text::TableColumnSeparator* pArray = pSepSeq->getConstArray();
+ sal_Int32 nLastValue = 0;
+ //sal_Int32 nTblWidth = aCols.GetRight() - aCols.GetLeft();
+ for(sal_uInt16 i = 0; i < nOldCount; i++)
+ {
+ aCols[i] = pArray[i].Position;
+ if(pArray[i].IsVisible == aCols.IsHidden(i) ||
+ (!bRow && aCols.IsHidden(i)) ||
+ long(aCols[i] - long(nLastValue)) < 0 ||
+ UNO_TABLE_COLUMN_SUM < aCols[i] )
+ {
+ bError = sal_True;
+ break;
+ }
+ nLastValue = aCols[i];
+ }
+ if(!bError)
+ {
+ pDoc->SetTabCols(*pTable, aCols, aOldCols, pBox, bRow );
+ }
+ }
+}
+
+inline rtl::OUString lcl_getString( SwXCell &rCell )
+{
+ // getString is a member function of the base class...
+ return rCell.getString();
+}
+
+/* non UNO function call to set string in SwXCell */
+void lcl_setString( SwXCell &rCell, const rtl::OUString &rTxt,
+ sal_Bool bKeepNumberFmt )
+{
+ if(rCell.IsValid())
+ {
+ SwFrmFmt* pBoxFmt = rCell.pBox->ClaimFrmFmt();
+ pBoxFmt->LockModify();
+ pBoxFmt->ResetFmtAttr( RES_BOXATR_FORMULA );
+ pBoxFmt->ResetFmtAttr( RES_BOXATR_VALUE );
+ if (!bKeepNumberFmt)
+ pBoxFmt->SetFmtAttr( SwTblBoxNumFormat(NUMBERFORMAT_TEXT) );
+ pBoxFmt->UnlockModify();
+ }
+ rCell.SwXText::setString(rTxt);
+}
+
+/* non UNO function call to get value from SwXCell */
+double lcl_getValue( SwXCell &rCell )
+{
+ double fRet;
+ if(rCell.IsValid() && rCell.getString().getLength()!=0)
+ fRet = rCell.pBox->GetFrmFmt()->GetTblBoxValue().GetValue();
+ else
+ ::rtl::math::setNan( &fRet );
+ return fRet;
+}
+
+/* non UNO function call to set value in SwXCell */
+void lcl_setValue( SwXCell &rCell, double nVal )
+{
+ if(rCell.IsValid())
+ {
+ // Der Text mu? zunaechst (vielleicht) geloescht werden
+ sal_uLong nNdPos = rCell.pBox->IsValidNumTxtNd( sal_True );
+ if(ULONG_MAX != nNdPos)
+ lcl_setString( rCell, OUString(), sal_True ); // sal_True == keep number format
+ SwDoc* pDoc = rCell.GetDoc();
+ UnoActionContext aAction(pDoc);
+ SwFrmFmt* pBoxFmt = rCell.pBox->ClaimFrmFmt();
+ SfxItemSet aSet(pDoc->GetAttrPool(), RES_BOXATR_FORMAT, RES_BOXATR_VALUE);
+ const SfxPoolItem* pItem;
+
+ //!! do we need to set a new number format? Yes, if
+ // - there is no current number format
+ // - the current number format is not a number format according to the number formatter, but rather a text format
+ // - the current number format is not even a valid number formatter number format, but rather Writer's own 'special' text number format
+ if(SFX_ITEM_SET != pBoxFmt->GetAttrSet().GetItemState(RES_BOXATR_FORMAT, sal_True, &pItem)
+ || pDoc->GetNumberFormatter()->IsTextFormat(((SwTblBoxNumFormat*)pItem)->GetValue())
+ || ((SwTblBoxNumFormat*)pItem)->GetValue() == NUMBERFORMAT_TEXT)
+ {
+ aSet.Put(SwTblBoxNumFormat(0));
+ }
+
+ SwTblBoxValue aVal(nVal);
+ aSet.Put(aVal);
+ pDoc->SetTblBoxFormulaAttrs( *rCell.pBox, aSet );
+ //Tabelle aktualisieren
+ SwTableFmlUpdate aTblUpdate( SwTable::FindTable( rCell.GetFrmFmt() ));
+ pDoc->UpdateTblFlds( &aTblUpdate );
+ }
+}
+
+/******************************************************************
+ * SwXCell
+ ******************************************************************/
+TYPEINIT1(SwXCell, SwClient);
+
+SwXCell::SwXCell(SwFrmFmt* pTblFmt, SwTableBox* pBx, sal_uInt16 nPos ) :
+ SwXText(pTblFmt->GetDoc(), CURSOR_TBLTEXT),
+ SwClient(pTblFmt),
+ m_pPropSet(aSwMapProvider.GetPropertySet(PROPERTY_MAP_TABLE_CELL)),
+ pBox(pBx),
+ pStartNode(0),
+ nFndPos(nPos)
+{
+}
+
+SwXCell::SwXCell(SwFrmFmt* pTblFmt, const SwStartNode& rStartNode) :
+ SwXText(pTblFmt->GetDoc(), CURSOR_TBLTEXT),
+ SwClient(pTblFmt),
+ m_pPropSet(aSwMapProvider.GetPropertySet(PROPERTY_MAP_TABLE_CELL)),
+ pBox(0),
+ pStartNode(&rStartNode),
+ nFndPos(USHRT_MAX)
+{
+}
+
+SwXCell::~SwXCell()
+{
+
+}
+
+const uno::Sequence< sal_Int8 > & SwXCell::getUnoTunnelId()
+{
+ static uno::Sequence< sal_Int8 > aSeq = ::CreateUnoTunnelId();
+ return aSeq;
+}
+
+sal_Int64 SAL_CALL SwXCell::getSomething( const uno::Sequence< sal_Int8 >& rId )
+ throw(uno::RuntimeException)
+{
+ if( rId.getLength() == 16
+ && 0 == rtl_compareMemory( getUnoTunnelId().getConstArray(),
+ rId.getConstArray(), 16 ) )
+ {
+ return sal::static_int_cast< sal_Int64 >( reinterpret_cast< sal_IntPtr >(this) );
+ }
+ else
+ return SwXText::getSomething(rId);
+}
+
+uno::Sequence< uno::Type > SAL_CALL SwXCell::getTypes( ) throw(uno::RuntimeException)
+{
+ static uno::Sequence< uno::Type > aRetTypes;
+ if(!aRetTypes.getLength())
+ {
+ aRetTypes = SwXCellBaseClass::getTypes();
+ uno::Sequence< uno::Type > aTextTypes = SwXText::getTypes();
+
+ long nIndex = aRetTypes.getLength();
+ aRetTypes.realloc(
+ aRetTypes.getLength() +
+ aTextTypes.getLength());
+
+ uno::Type* pRetTypes = aRetTypes.getArray();
+
+ const uno::Type* pTextTypes = aTextTypes.getConstArray();
+ for(long nPos = 0; nPos <aTextTypes.getLength(); nPos++)
+ pRetTypes[nIndex++] = pTextTypes[nPos];
+ }
+ return aRetTypes;
+}
+
+uno::Sequence< sal_Int8 > SAL_CALL SwXCell::getImplementationId( ) throw(uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+ static uno::Sequence< sal_Int8 > aId( 16 );
+ static sal_Bool bInit = sal_False;
+ if(!bInit)
+ {
+ rtl_createUuid( (sal_uInt8 *)(aId.getArray() ), 0, sal_True );
+ bInit = sal_True;
+ }
+ return aId;
+}
+
+void SAL_CALL SwXCell::acquire( ) throw()
+{
+ SwXCellBaseClass::acquire();
+}
+
+void SAL_CALL SwXCell::release( ) throw()
+{
+ SwXCellBaseClass::release();
+}
+
+uno::Any SAL_CALL SwXCell::queryInterface( const uno::Type& aType )
+ throw (uno::RuntimeException)
+{
+ uno::Any aRet = SwXCellBaseClass::queryInterface(aType);
+ if(aRet.getValueType() == ::getCppuVoidType())
+ aRet = SwXText::queryInterface(aType);
+ return aRet;
+}
+
+const SwStartNode *SwXCell::GetStartNode() const
+{
+ const SwStartNode *pSttNd = 0;
+
+ if( pStartNode || ((SwXCell *)this)->IsValid() )
+ pSttNd = pStartNode ? pStartNode : pBox->GetSttNd();
+
+ return pSttNd;
+}
+
+uno::Reference< text::XTextCursor >
+SwXCell::CreateCursor() throw (uno::RuntimeException)
+{
+ return createTextCursor();
+}
+
+bool SwXCell::IsValid() const
+{
+ // FIXME: this is now a const method, to make SwXText::IsValid invisible
+ // but the const_cast here are still ridiculous. TODO: find a better way.
+ SwFrmFmt* pTblFmt = pBox ? GetFrmFmt() : 0;
+ if(!pTblFmt)
+ {
+ const_cast<SwXCell*>(this)->pBox = 0;
+ }
+ else
+ {
+ SwTable* pTable = SwTable::FindTable( pTblFmt );
+ SwTableBox const*const pFoundBox =
+ const_cast<SwXCell*>(this)->FindBox(pTable, pBox);
+ if (!pFoundBox)
+ {
+ const_cast<SwXCell*>(this)->pBox = 0;
+ }
+ }
+ return 0 != pBox;
+}
+
+OUString SwXCell::getFormula(void) throw( uno::RuntimeException )
+{
+ SolarMutexGuard aGuard;
+ OUString sRet;
+ if(IsValid())
+ {
+ SwTblBoxFormula aFormula( pBox->GetFrmFmt()->GetTblBoxFormula() );
+ SwTable* pTable = SwTable::FindTable( GetFrmFmt() );
+ aFormula.PtrToBoxNm( pTable );
+ sRet = aFormula.GetFormula();
+ }
+ return sRet;
+}
+
+void SwXCell::setFormula(const OUString& rFormula) throw( uno::RuntimeException )
+{
+ SolarMutexGuard aGuard;
+ if(IsValid())
+ {
+ // Der Text mu? zunaechst (vielleicht) geloescht werden
+ sal_uInt32 nNdPos = pBox->IsValidNumTxtNd( sal_True );
+ if(USHRT_MAX == nNdPos)
+ lcl_setString( *this, OUString(), sal_True );
+ String sFml(rFormula);
+ if( sFml.EraseLeadingChars().Len() && '=' == sFml.GetChar( 0 ) )
+ sFml.Erase( 0, 1 );
+ SwTblBoxFormula aFml( sFml );
+ SwDoc* pMyDoc = GetDoc();
+ UnoActionContext aAction(pMyDoc);
+ SfxItemSet aSet(pMyDoc->GetAttrPool(), RES_BOXATR_FORMAT, RES_BOXATR_FORMULA);
+ const SfxPoolItem* pItem;
+ SwFrmFmt* pBoxFmt = pBox->GetFrmFmt();
+ if(SFX_ITEM_SET != pBoxFmt->GetAttrSet().GetItemState(RES_BOXATR_FORMAT, sal_True, &pItem)
+ || pMyDoc->GetNumberFormatter()->IsTextFormat(((SwTblBoxNumFormat*)pItem)->GetValue()))
+ {
+ aSet.Put(SwTblBoxNumFormat(0));
+ }
+ aSet.Put(aFml);
+ GetDoc()->SetTblBoxFormulaAttrs( *pBox, aSet );
+ //Tabelle aktualisieren
+ SwTableFmlUpdate aTblUpdate( SwTable::FindTable( GetFrmFmt() ));
+ pMyDoc->UpdateTblFlds( &aTblUpdate );
+ }
+}
+
+double SwXCell::getValue(void) throw( uno::RuntimeException )
+{
+ SolarMutexGuard aGuard;
+
+ double const fRet = lcl_getValue( *this );
+ // #i112652# a table cell may contain NaN as a value, do not filter that
+ return fRet;
+}
+
+void SwXCell::setValue(double rValue) throw( uno::RuntimeException )
+{
+ SolarMutexGuard aGuard;
+ lcl_setValue( *this, rValue );
+}
+
+table::CellContentType SwXCell::getType(void) throw( uno::RuntimeException )
+{
+ SolarMutexGuard aGuard;
+
+ table::CellContentType nRes = table::CellContentType_EMPTY;
+ sal_uInt32 nNdPos = pBox->IsFormulaOrValueBox();
+ switch (nNdPos)
+ {
+ case 0 : nRes = table::CellContentType_TEXT; break;
+ case USHRT_MAX : nRes = table::CellContentType_EMPTY; break;
+ case RES_BOXATR_VALUE : nRes = table::CellContentType_VALUE; break;
+ case RES_BOXATR_FORMULA : nRes = table::CellContentType_FORMULA; break;
+ default :
+ OSL_FAIL( "unexpected case" );
+ }
+ return nRes;
+}
+
+void SwXCell::setString(const OUString& aString) throw( uno::RuntimeException )
+{
+ SolarMutexGuard aGuard;
+ lcl_setString( *this, aString );
+}
+
+sal_Int32 SwXCell::getError(void) throw( uno::RuntimeException )
+{
+ SolarMutexGuard aGuard;
+ OUString sContent = getString();
+ return sContent.equals(ViewShell::GetShellRes()->aCalc_Error);
+}
+
+uno::Reference< text::XTextCursor > SwXCell::createTextCursor(void) throw( uno::RuntimeException )
+{
+ SolarMutexGuard aGuard;
+ uno::Reference< text::XTextCursor > aRef;
+ if(pStartNode || IsValid())
+ {
+ const SwStartNode* pSttNd = pStartNode ? pStartNode : pBox->GetSttNd();
+ SwPosition aPos(*pSttNd);
+ SwXTextCursor *const pXCursor =
+ new SwXTextCursor(*GetDoc(), this, CURSOR_TBLTEXT, aPos);
+ SwUnoCrsr *const pUnoCrsr = pXCursor->GetCursor();
+ pUnoCrsr->Move(fnMoveForward, fnGoNode);
+ aRef = static_cast<text::XWordCursor*>(pXCursor);
+// // no Cursor in protected sections
+// SwCrsrSaveState aSave( *pUnoCrsr );
+// if(pUnoCrsr->IsInProtectTable( sal_True ) ||
+// pUnoCrsr->IsSelOvr( nsSwCursorSelOverFlags::SELOVER_TOGGLE | nsSwCursorSelOverFlags::SELOVER_CHANGEPOS ))
+// throw( uno::RuntimeException() );
+ }
+ else
+ throw uno::RuntimeException();
+ return aRef;
+}
+
+uno::Reference< text::XTextCursor > SwXCell::createTextCursorByRange(const uno::Reference< text::XTextRange > & xTextPosition)
+ throw( uno::RuntimeException )
+{
+ SolarMutexGuard aGuard;
+ uno::Reference< text::XTextCursor > aRef;
+ SwUnoInternalPaM aPam(*GetDoc());
+ if ((pStartNode || IsValid())
+ && ::sw::XTextRangeToSwPaM(aPam, xTextPosition))
+ {
+ const SwStartNode* pSttNd = pStartNode ? pStartNode : pBox->GetSttNd();
+ //skip sections
+ SwStartNode* p1 = aPam.GetNode()->StartOfSectionNode();
+ while(p1->IsSectionNode())
+ p1 = p1->StartOfSectionNode();
+
+ if( p1 == pSttNd )
+ {
+ aRef = static_cast<text::XWordCursor*>(
+ new SwXTextCursor(*GetDoc(), this, CURSOR_TBLTEXT,
+ *aPam.GetPoint(), aPam.GetMark()));
+ }
+ }
+ else
+ throw uno::RuntimeException();
+ return aRef;
+}
+
+uno::Reference< beans::XPropertySetInfo > SwXCell::getPropertySetInfo(void) throw( uno::RuntimeException )
+{
+ static uno::Reference< beans::XPropertySetInfo > xRef = m_pPropSet->getPropertySetInfo();
+ return xRef;
+}
+
+void SwXCell::setPropertyValue(const OUString& rPropertyName, const uno::Any& aValue)
+ throw( beans::UnknownPropertyException, beans::PropertyVetoException, lang::IllegalArgumentException, lang::WrappedTargetException, uno::RuntimeException )
+{
+ SolarMutexGuard aGuard;
+ if(IsValid())
+ {
+ // Hack to support hidden property to transfer textDirection
+ if ( rPropertyName.equals( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("FRMDirection") ) ) )
+ {
+ SvxFrameDirection eDir = FRMDIR_ENVIRONMENT;
+ sal_Int16 nNum = 0;
+ aValue >>= nNum;
+ OSL_TRACE("FRMDirection val %d", nNum );
+ switch (nNum)
+ {
+ case 0:
+ eDir = FRMDIR_HORI_LEFT_TOP;
+ break;
+ case 1:
+ eDir = FRMDIR_HORI_RIGHT_TOP;
+ break;
+ case 2:
+ eDir = FRMDIR_VERT_TOP_RIGHT;
+ break;
+ default:
+ OSL_FAIL( "unknown direction code, maybe its a bitfield");
+ }
+ SvxFrameDirectionItem aItem( eDir, RES_FRAMEDIR);
+ pBox->GetFrmFmt()->SetFmtAttr(aItem);
+ }
+ else
+ {
+ const SfxItemPropertySimpleEntry* pEntry =
+ m_pPropSet->getPropertyMap()->getByName(rPropertyName);
+ if( !pEntry )
+ {
+ beans::UnknownPropertyException aEx;
+ aEx.Message = rPropertyName;
+ throw( aEx );
+ }
+ if( pEntry->nWID == FN_UNO_CELL_ROW_SPAN )
+ {
+ sal_Int32 nRowSpan = 0;
+ if( aValue >>= nRowSpan )
+ pBox->setRowSpan( nRowSpan );
+ }
+ else
+ {
+ SwFrmFmt* pBoxFmt = pBox->ClaimFrmFmt();
+ SwAttrSet aSet(pBoxFmt->GetAttrSet());
+ m_pPropSet->setPropertyValue(rPropertyName, aValue, aSet);
+ pBoxFmt->GetDoc()->SetAttr(aSet, *pBoxFmt);
+ }
+ }
+ }
+}
+
+uno::Any SwXCell::getPropertyValue(const OUString& rPropertyName)
+ throw( beans::UnknownPropertyException, lang::WrappedTargetException, uno::RuntimeException )
+{
+ SolarMutexGuard aGuard;
+ uno::Any aRet;
+ if(IsValid())
+ {
+ const SfxItemPropertySimpleEntry* pEntry =
+ m_pPropSet->getPropertyMap()->getByName(rPropertyName);
+ if( !pEntry )
+ {
+ beans::UnknownPropertyException aEx;
+ aEx.Message = rPropertyName;
+ throw( aEx );
+ }
+ switch( pEntry->nWID )
+ {
+ case FN_UNO_CELL_ROW_SPAN:
+ aRet <<= pBox->getRowSpan();
+ break;
+ case FN_UNO_TEXT_SECTION:
+ {
+ SwFrmFmt* pTblFmt = GetFrmFmt();
+ SwTable* pTable = SwTable::FindTable( pTblFmt );
+ SwTableNode* pTblNode = pTable->GetTableNode();
+ SwSectionNode* pSectionNode = pTblNode->FindSectionNode();
+ if(pSectionNode)
+ {
+ const SwSection& rSect = pSectionNode->GetSection();
+ uno::Reference< text::XTextSection > xSect =
+ SwXTextSections::GetObject( *rSect.GetFmt() );
+ aRet <<= xSect;
+ }
+ }
+ break;
+ case FN_UNO_CELL_NAME:
+ aRet <<= OUString ( pBox->GetName() );
+ break;
+ case FN_UNO_REDLINE_NODE_START:
+ case FN_UNO_REDLINE_NODE_END:
+ {
+ //redline can only be returned if it's a living object
+ aRet = SwXText::getPropertyValue(rPropertyName);
+ }
+ break;
+ default:
+ {
+ const SwFrmFmt* pBoxFmt = pBox->GetFrmFmt();
+ const SwAttrSet& rSet = pBoxFmt->GetAttrSet();
+ m_pPropSet->getPropertyValue(rPropertyName, rSet, aRet);
+ }
+ }
+ }
+ return aRet;
+}
+
+void SwXCell::addPropertyChangeListener(const OUString& /*rPropertyName*/, const uno::Reference< beans::XPropertyChangeListener > & /*xListener*/) throw( beans::UnknownPropertyException, lang::WrappedTargetException, uno::RuntimeException )
+{
+ DBG_WARNING("not implemented");
+}
+
+void SwXCell::removePropertyChangeListener(const OUString& /*rPropertyName*/, const uno::Reference< beans::XPropertyChangeListener > & /*xListener*/) throw( beans::UnknownPropertyException, lang::WrappedTargetException, uno::RuntimeException )
+{
+ DBG_WARNING("not implemented");
+}
+
+void SwXCell::addVetoableChangeListener(const OUString& /*rPropertyName*/, const uno::Reference< beans::XVetoableChangeListener > & /*xListener*/) throw( beans::UnknownPropertyException, lang::WrappedTargetException, uno::RuntimeException )
+{
+ DBG_WARNING("not implemented");
+}
+
+void SwXCell::removeVetoableChangeListener(const OUString& /*rPropertyName*/, const uno::Reference< beans::XVetoableChangeListener > & /*xListener*/) throw( beans::UnknownPropertyException, lang::WrappedTargetException, uno::RuntimeException )
+{
+ DBG_WARNING("not implemented");
+}
+
+uno::Reference< container::XEnumeration > SwXCell::createEnumeration(void) throw( uno::RuntimeException )
+{
+ SolarMutexGuard aGuard;
+ uno::Reference< container::XEnumeration > aRef;
+ if(IsValid())
+ {
+ const SwStartNode* pSttNd = pBox->GetSttNd();
+ SwPosition aPos(*pSttNd);
+ ::std::auto_ptr<SwUnoCrsr> pUnoCursor(
+ GetDoc()->CreateUnoCrsr(aPos, sal_False));
+ pUnoCursor->Move(fnMoveForward, fnGoNode);
+
+ // remember table and start node for later travelling
+ // (used in export of tables in tables)
+ SwTable const*const pTable( & pSttNd->FindTableNode()->GetTable() );
+ SwXParagraphEnumeration *const pEnum =
+ new SwXParagraphEnumeration(this, pUnoCursor, CURSOR_TBLTEXT,
+ pSttNd, pTable);
+
+ aRef = pEnum;
+// // no Cursor in protected sections
+// SwCrsrSaveState aSave( *pUnoCrsr );
+// if(pUnoCrsr->IsInProtectTable( sal_True ) ||
+// pUnoCrsr->IsSelOvr( nsSwCursorSelOverFlags::SELOVER_TOGGLE | nsSwCursorSelOverFlags::SELOVER_CHANGEPOS ))
+// throw( uno::RuntimeException() );
+ }
+ return aRef;
+}
+
+uno::Type SAL_CALL SwXCell::getElementType(void) throw( uno::RuntimeException )
+{
+ return ::getCppuType((const uno::Reference<text::XTextRange>*)0);
+
+}
+
+sal_Bool SwXCell::hasElements(void) throw( uno::RuntimeException )
+{
+ return sal_True;
+}
+
+void SwXCell::Modify( const SfxPoolItem* pOld, const SfxPoolItem *pNew)
+{
+ ClientModify(this, pOld, pNew);
+}
+
+SwXCell* SwXCell::CreateXCell(SwFrmFmt* pTblFmt, SwTableBox* pBox, SwTable *pTable )
+{
+ SwXCell* pRet = 0;
+ if(pTblFmt && pBox)
+ {
+ if( !pTable )
+ pTable = SwTable::FindTable( pTblFmt );
+ sal_uInt16 nPos = USHRT_MAX;
+ SwTableBox* pFoundBox =
+ pTable->GetTabSortBoxes().Seek_Entry( pBox, &nPos ) ? pBox : NULL;
+
+ //wenn es die Box gibt, dann wird auch eine Zelle zurueckgegeben
+ if(pFoundBox)
+ {
+ SwIterator<SwXCell,SwFmt> aIter( *pTblFmt );
+ SwXCell* pXCell = aIter.First();
+ while( pXCell )
+ {
+ // gibt es eine passende Zelle bereits?
+ if(pXCell->GetTblBox() == pBox)
+ break;
+ pXCell = aIter.Next();
+ }
+ //sonst anlegen
+ if(!pXCell)
+ pXCell = new SwXCell(pTblFmt, pBox, nPos );
+ pRet = pXCell;
+ }
+ }
+ return pRet;
+}
+
+/* does box exist in given table? */
+SwTableBox* SwXCell::FindBox(SwTable* pTable, SwTableBox* pBox2)
+{
+ // check if nFndPos happens to point to the right table box
+ if( nFndPos < pTable->GetTabSortBoxes().Count() &&
+ pBox2 == pTable->GetTabSortBoxes()[ nFndPos ] )
+ return pBox2;
+
+ // if not, seek the entry (and return, if successful)
+ if( pTable->GetTabSortBoxes().Seek_Entry( pBox2, &nFndPos ))
+ return pBox2;
+
+ // box not found: reset nFndPos pointer
+ nFndPos = USHRT_MAX;
+ return 0;
+}
+
+OUString SwXCell::getImplementationName(void) throw( uno::RuntimeException )
+{
+ return C2U("SwXCell");
+}
+
+sal_Bool SwXCell::supportsService(const OUString& rServiceName) throw( uno::RuntimeException )
+{
+ String sServiceName(rServiceName);
+ return sServiceName.EqualsAscii("com.sun.star.text.CellProperties");
+}
+
+uno::Sequence< OUString > SwXCell::getSupportedServiceNames(void) throw( uno::RuntimeException )
+{
+ uno::Sequence< OUString > aRet(1);
+ OUString* pArray = aRet.getArray();
+ pArray[0] = C2U("com.sun.star.text.CellProperties");
+ return aRet;
+}
+
+/******************************************************************
+ * SwXTextTableRow
+ ******************************************************************/
+OUString SwXTextTableRow::getImplementationName(void) throw( uno::RuntimeException )
+{
+ return C2U("SwXTextTableRow");
+}
+
+sal_Bool SwXTextTableRow::supportsService(const OUString& rServiceName) throw( uno::RuntimeException )
+{
+ return C2U("com.sun.star.text.TextTableRow") == rServiceName;
+}
+
+uno::Sequence< OUString > SwXTextTableRow::getSupportedServiceNames(void) throw( uno::RuntimeException )
+{
+ uno::Sequence< OUString > aRet(1);
+ OUString* pArray = aRet.getArray();
+ pArray[0] = C2U("com.sun.star.text.TextTableRow");
+ return aRet;
+}
+TYPEINIT1(SwXTextTableRow, SwClient);
+
+SwXTextTableRow::SwXTextTableRow(SwFrmFmt* pFmt, SwTableLine* pLn) :
+ SwClient(pFmt),
+ m_pPropSet(aSwMapProvider.GetPropertySet(PROPERTY_MAP_TEXT_TABLE_ROW)),
+ pLine(pLn)
+{
+
+}
+
+SwXTextTableRow::~SwXTextTableRow()
+{
+
+}
+
+uno::Reference< beans::XPropertySetInfo > SwXTextTableRow::getPropertySetInfo(void) throw( uno::RuntimeException )
+{
+ static uno::Reference< beans::XPropertySetInfo > xRef = m_pPropSet->getPropertySetInfo();
+ return xRef;
+}
+
+void SwXTextTableRow::setPropertyValue(const OUString& rPropertyName,
+ const uno::Any& aValue)
+ throw( beans::UnknownPropertyException, beans::PropertyVetoException, lang::IllegalArgumentException, lang::WrappedTargetException, uno::RuntimeException )
+{
+ SolarMutexGuard aGuard;
+ SwFrmFmt* pFmt = GetFrmFmt();
+ if(pFmt)
+ {
+ SwTable* pTable = SwTable::FindTable( pFmt );
+ SwTableLine* pLn = SwXTextTableRow::FindLine(pTable, pLine);
+ if(pLn)
+ {
+ const SfxItemPropertySimpleEntry* pEntry =
+ m_pPropSet->getPropertyMap()->getByName(rPropertyName);
+ SwDoc* pDoc = pFmt->GetDoc();
+ if (!pEntry)
+ throw beans::UnknownPropertyException(OUString ( RTL_CONSTASCII_USTRINGPARAM ( "Unknown property: " ) ) + rPropertyName, static_cast < cppu::OWeakObject * > ( this ) );
+ if ( pEntry->nFlags & beans::PropertyAttribute::READONLY)
+ throw beans::PropertyVetoException( OUString ( RTL_CONSTASCII_USTRINGPARAM ( "Property is read-only: " ) ) + rPropertyName, static_cast < cppu::OWeakObject * > ( this ) );
+
+ switch(pEntry->nWID)
+ {
+ case FN_UNO_ROW_HEIGHT:
+ case FN_UNO_ROW_AUTO_HEIGHT:
+ {
+ SwFmtFrmSize aFrmSize(pLn->GetFrmFmt()->GetFrmSize());
+ if(FN_UNO_ROW_AUTO_HEIGHT== pEntry->nWID)
+ {
+ sal_Bool bSet = *(sal_Bool*)aValue.getValue();
+ aFrmSize.SetHeightSizeType(bSet ? ATT_VAR_SIZE : ATT_FIX_SIZE);
+ }
+ else
+ {
+ sal_Int32 nHeight = 0;
+ aValue >>= nHeight;
+ Size aSz(aFrmSize.GetSize());
+ aSz.Height() = MM100_TO_TWIP(nHeight);
+ aFrmSize.SetSize(aSz);
+ }
+ pDoc->SetAttr(aFrmSize, *pLn->ClaimFrmFmt());
+ }
+ break;
+ case FN_UNO_TABLE_COLUMN_SEPARATORS:
+ {
+ UnoActionContext aContext(pDoc);
+ SwTable* pTable2 = SwTable::FindTable( pFmt );
+ lcl_SetTblSeparators(aValue, pTable2, pLine->GetTabBoxes()[0], sal_True, pDoc);
+ }
+ break;
+ default:
+ {
+ SwFrmFmt* pLnFmt = pLn->ClaimFrmFmt();
+ SwAttrSet aSet(pLnFmt->GetAttrSet());
+ m_pPropSet->setPropertyValue(*pEntry, aValue, aSet);
+ pDoc->SetAttr(aSet, *pLnFmt);
+ }
+ }
+ }
+ }
+}
+
+uno::Any SwXTextTableRow::getPropertyValue(const OUString& rPropertyName) throw( beans::UnknownPropertyException, lang::WrappedTargetException, uno::RuntimeException )
+{
+ SolarMutexGuard aGuard;
+ uno::Any aRet;
+ SwFrmFmt* pFmt = GetFrmFmt();
+ if(pFmt)
+ {
+ SwTable* pTable = SwTable::FindTable( pFmt );
+ SwTableLine* pLn = SwXTextTableRow::FindLine(pTable, pLine);
+ if(pLn)
+ {
+ const SfxItemPropertySimpleEntry* pEntry =
+ m_pPropSet->getPropertyMap()->getByName(rPropertyName);
+ if (!pEntry)
+ throw beans::UnknownPropertyException(OUString ( RTL_CONSTASCII_USTRINGPARAM ( "Unknown property: " ) ) + rPropertyName, static_cast < cppu::OWeakObject * > ( this ) );
+
+ switch(pEntry->nWID)
+ {
+ case FN_UNO_ROW_HEIGHT:
+ case FN_UNO_ROW_AUTO_HEIGHT:
+ {
+ const SwFmtFrmSize& rSize = pLn->GetFrmFmt()->GetFrmSize();
+ if(FN_UNO_ROW_AUTO_HEIGHT== pEntry->nWID)
+ {
+ sal_Bool bTmp = ATT_VAR_SIZE == rSize.GetHeightSizeType();
+ aRet.setValue(&bTmp, ::getCppuBooleanType());
+ }
+ else
+ aRet <<= (sal_Int32)(TWIP_TO_MM100(rSize.GetSize().Height()));
+ }
+ break;
+ case FN_UNO_TABLE_COLUMN_SEPARATORS:
+ {
+ lcl_GetTblSeparators(aRet, pTable, pLine->GetTabBoxes()[0], sal_True);
+ }
+ break;
+ default:
+ {
+ const SwAttrSet& rSet = pLn->GetFrmFmt()->GetAttrSet();
+ m_pPropSet->getPropertyValue(*pEntry, rSet, aRet);
+ }
+ }
+ }
+ }
+ return aRet;
+}
+
+void SwXTextTableRow::addPropertyChangeListener(const OUString& /*rPropertyName*/, const uno::Reference< beans::XPropertyChangeListener > & /*xListener*/) throw( beans::UnknownPropertyException, lang::WrappedTargetException, uno::RuntimeException )
+{
+ DBG_WARNING("not implemented");
+}
+
+void SwXTextTableRow::removePropertyChangeListener(const OUString& /*rPropertyName*/, const uno::Reference< beans::XPropertyChangeListener > & /*xListener*/) throw( beans::UnknownPropertyException, lang::WrappedTargetException, uno::RuntimeException )
+{
+ DBG_WARNING("not implemented");
+}
+
+void SwXTextTableRow::addVetoableChangeListener(const OUString& /*rPropertyName*/, const uno::Reference< beans::XVetoableChangeListener > & /*xListener*/) throw( beans::UnknownPropertyException, lang::WrappedTargetException, uno::RuntimeException )
+{
+ DBG_WARNING("not implemented");
+}
+
+void SwXTextTableRow::removeVetoableChangeListener(const OUString& /*rPropertyName*/, const uno::Reference< beans::XVetoableChangeListener > & /*xListener*/) throw( beans::UnknownPropertyException, lang::WrappedTargetException, uno::RuntimeException )
+{
+ DBG_WARNING("not implemented");
+}
+
+void SwXTextTableRow::Modify( const SfxPoolItem* pOld, const SfxPoolItem *pNew)
+{
+ ClientModify(this, pOld, pNew);
+}
+
+SwTableLine* SwXTextTableRow::FindLine(SwTable* pTable, SwTableLine* pLine)
+{
+ SwTableLine* pRet = 0;
+ SwTableLines &rLines = pTable->GetTabLines();
+ for(sal_uInt16 i = 0; i < rLines.Count(); i++)
+ if(rLines.GetObject(i) == pLine)
+ {
+ pRet = pLine;
+ break;
+ }
+ return pRet;
+}
+
+/******************************************************************
+ * SwXTextTableCursor
+ ******************************************************************/
+OUString SwXTextTableCursor::getImplementationName(void) throw( uno::RuntimeException )
+{
+ return C2U("SwXTextTableCursor");
+}
+
+sal_Bool SwXTextTableCursor::supportsService(const OUString& rServiceName) throw( uno::RuntimeException )
+{
+ return C2U("com.sun.star.text.TextTableCursor") == rServiceName;
+}
+
+IMPLEMENT_FORWARD_XINTERFACE2(SwXTextTableCursor,SwXTextTableCursor_Base,OTextCursorHelper)
+const SwPaM* SwXTextTableCursor::GetPaM() const { return GetCrsr(); }
+SwPaM* SwXTextTableCursor::GetPaM() { return GetCrsr(); }
+const SwDoc* SwXTextTableCursor::GetDoc() const { return GetFrmFmt()->GetDoc(); }
+SwDoc* SwXTextTableCursor::GetDoc() { return GetFrmFmt()->GetDoc(); }
+const SwUnoCrsr* SwXTextTableCursor::GetCrsr() const { return (SwUnoCrsr*)aCrsrDepend.GetRegisteredIn(); }
+SwUnoCrsr* SwXTextTableCursor::GetCrsr() { return (SwUnoCrsr*)aCrsrDepend.GetRegisteredIn(); }
+
+uno::Sequence< OUString > SwXTextTableCursor::getSupportedServiceNames(void) throw( uno::RuntimeException )
+{
+ uno::Sequence< OUString > aRet(1);
+ OUString* pArray = aRet.getArray();
+ pArray[0] = C2U("com.sun.star.text.TextTableCursor");
+ return aRet;
+}
+
+SwXTextTableCursor::SwXTextTableCursor(SwFrmFmt* pFmt, SwTableBox* pBox) :
+ SwClient(pFmt),
+ aCrsrDepend(this, 0),
+ m_pPropSet(aSwMapProvider.GetPropertySet(PROPERTY_MAP_TEXT_TABLE_CURSOR))
+{
+ SwDoc* pDoc = pFmt->GetDoc();
+ const SwStartNode* pSttNd = pBox->GetSttNd();
+ SwPosition aPos(*pSttNd);
+ SwUnoCrsr* pUnoCrsr = pDoc->CreateUnoCrsr(aPos, sal_True);
+ pUnoCrsr->Move( fnMoveForward, fnGoNode );
+ pUnoCrsr->Add(&aCrsrDepend);
+ SwUnoTableCrsr* pTblCrsr = dynamic_cast<SwUnoTableCrsr*>(pUnoCrsr);
+ pTblCrsr->MakeBoxSels();
+}
+
+SwXTextTableCursor::SwXTextTableCursor(SwFrmFmt& rTableFmt, const SwTableCursor* pTableSelection) :
+ SwClient(&rTableFmt),
+ aCrsrDepend(this, 0),
+ m_pPropSet(aSwMapProvider.GetPropertySet(PROPERTY_MAP_TEXT_TABLE_CURSOR))
+{
+ SwUnoCrsr* pUnoCrsr = pTableSelection->GetDoc()->CreateUnoCrsr(*pTableSelection->GetPoint(), sal_True);
+ if(pTableSelection->HasMark())
+ {
+ pUnoCrsr->SetMark();
+ *pUnoCrsr->GetMark() = *pTableSelection->GetMark();
+ }
+ const SwSelBoxes& rBoxes = pTableSelection->GetBoxes();
+ SwTableCursor* pTableCrsr = dynamic_cast<SwTableCursor*>(pUnoCrsr);
+ for(sal_uInt16 i = 0; i < rBoxes.Count(); i++)
+ pTableCrsr->InsertBox( *rBoxes.GetObject(i) );
+
+ pUnoCrsr->Add(&aCrsrDepend);
+ SwUnoTableCrsr* pTblCrsr = dynamic_cast<SwUnoTableCrsr*>(pUnoCrsr);
+ pTblCrsr->MakeBoxSels();
+}
+
+SwXTextTableCursor::~SwXTextTableCursor()
+{
+ SolarMutexGuard aGuard;
+ SwUnoCrsr* pUnoCrsr = GetCrsr();
+ if(pUnoCrsr)
+ delete pUnoCrsr;
+}
+
+OUString SwXTextTableCursor::getRangeName(void) throw( uno::RuntimeException )
+{
+ SolarMutexGuard aGuard;
+ OUString aRet;
+ SwUnoCrsr* pUnoCrsr = GetCrsr();
+
+ //!! see also SwChartDataSequence::getSourceRangeRepresentation
+ if(pUnoCrsr)
+ {
+ SwUnoTableCrsr* pTblCrsr = dynamic_cast<SwUnoTableCrsr*>(pUnoCrsr);
+ pTblCrsr->MakeBoxSels();
+ const SwStartNode* pNode = pTblCrsr->GetPoint()->nNode.GetNode().FindTableBoxStartNode();
+ const SwTable* pTable = SwTable::FindTable( GetFrmFmt() );
+ const SwTableBox* pEndBox = pTable->GetTblBox( pNode->GetIndex());
+ String aTmp( pEndBox->GetName() );
+
+ if(pTblCrsr->HasMark())
+ {
+ pNode = pTblCrsr->GetMark()->nNode.GetNode().FindTableBoxStartNode();
+ const SwTableBox* pStartBox = pTable->GetTblBox( pNode->GetIndex());
+ if(pEndBox != pStartBox)
+ {
+ // need to switch start and end?
+ if (*pTblCrsr->GetPoint() < *pTblCrsr->GetMark())
+ {
+ const SwTableBox* pTmpBox = pStartBox;
+ pStartBox = pEndBox;
+ pEndBox = pTmpBox;
+ }
+
+ aTmp = pStartBox->GetName();
+ aTmp += ':';
+ aTmp += pEndBox->GetName();
+ }
+ }
+ aRet = aTmp;
+ }
+ return aRet;
+}
+
+sal_Bool SwXTextTableCursor::gotoCellByName(const OUString& CellName, sal_Bool Expand)
+ throw( uno::RuntimeException )
+{
+ SolarMutexGuard aGuard;
+ sal_Bool bRet = sal_False;
+ SwUnoCrsr* pUnoCrsr = GetCrsr();
+ if(pUnoCrsr)
+ {
+ SwUnoTableCrsr* pTblCrsr = dynamic_cast<SwUnoTableCrsr*>(pUnoCrsr);
+ lcl_CrsrSelect( pTblCrsr, Expand );
+ String sCellName(CellName);
+ bRet = pTblCrsr->GotoTblBox(sCellName);
+ }
+ return bRet;
+}
+
+sal_Bool SwXTextTableCursor::goLeft(sal_Int16 Count, sal_Bool Expand) throw( uno::RuntimeException )
+{
+ SolarMutexGuard aGuard;
+ sal_Bool bRet = sal_False;
+ SwUnoCrsr* pUnoCrsr = GetCrsr();
+ if(pUnoCrsr)
+ {
+ SwUnoTableCrsr* pTblCrsr = dynamic_cast<SwUnoTableCrsr*>(pUnoCrsr);
+ lcl_CrsrSelect( pTblCrsr, Expand );
+ bRet = pTblCrsr->Left( Count,CRSR_SKIP_CHARS, sal_False, sal_False);
+ }
+ return bRet;
+}
+
+sal_Bool SwXTextTableCursor::goRight(sal_Int16 Count, sal_Bool Expand) throw( uno::RuntimeException )
+{
+ SolarMutexGuard aGuard;
+ sal_Bool bRet = sal_False;
+ SwUnoCrsr* pUnoCrsr = GetCrsr();
+ if(pUnoCrsr)
+ {
+ SwUnoTableCrsr* pTblCrsr = dynamic_cast<SwUnoTableCrsr*>(pUnoCrsr);
+ lcl_CrsrSelect( pTblCrsr, Expand );
+ bRet = pTblCrsr->Right( Count, CRSR_SKIP_CHARS, sal_False, sal_False);
+ }
+ return bRet;
+}
+
+sal_Bool SwXTextTableCursor::goUp(sal_Int16 Count, sal_Bool Expand) throw( uno::RuntimeException )
+{
+ SolarMutexGuard aGuard;
+ sal_Bool bRet = sal_False;
+ SwUnoCrsr* pUnoCrsr = GetCrsr();
+ if(pUnoCrsr)
+ {
+ SwUnoTableCrsr* pTblCrsr = dynamic_cast<SwUnoTableCrsr*>(pUnoCrsr);
+ lcl_CrsrSelect( pTblCrsr, Expand );
+ bRet = pTblCrsr->UpDown(sal_True, Count, 0, 0);
+ }
+ return bRet;
+}
+
+sal_Bool SwXTextTableCursor::goDown(sal_Int16 Count, sal_Bool Expand) throw( uno::RuntimeException )
+{
+ SolarMutexGuard aGuard;
+ sal_Bool bRet = sal_False;
+ SwUnoCrsr* pUnoCrsr = GetCrsr();
+ if(pUnoCrsr)
+ {
+ SwUnoTableCrsr* pTblCrsr = dynamic_cast<SwUnoTableCrsr*>(pUnoCrsr);
+ lcl_CrsrSelect( pTblCrsr, Expand );
+ bRet = pTblCrsr->UpDown(sal_False, Count, 0, 0);
+ }
+ return bRet;
+}
+
+void SwXTextTableCursor::gotoStart(sal_Bool Expand) throw( uno::RuntimeException )
+{
+ SolarMutexGuard aGuard;
+ SwUnoCrsr* pUnoCrsr = GetCrsr();
+ if(pUnoCrsr)
+ {
+ SwUnoTableCrsr* pTblCrsr = dynamic_cast<SwUnoTableCrsr*>(pUnoCrsr);
+ lcl_CrsrSelect( pTblCrsr, Expand );
+ pTblCrsr->MoveTable(fnTableCurr, fnTableStart);
+ }
+}
+
+void SwXTextTableCursor::gotoEnd(sal_Bool Expand) throw( uno::RuntimeException )
+{
+ SolarMutexGuard aGuard;
+ SwUnoCrsr* pUnoCrsr = GetCrsr();
+ if(pUnoCrsr)
+ {
+ SwUnoTableCrsr* pTblCrsr = dynamic_cast<SwUnoTableCrsr*>(pUnoCrsr);
+ lcl_CrsrSelect( pTblCrsr, Expand );
+ pTblCrsr->MoveTable(fnTableCurr, fnTableEnd);
+ }
+}
+
+sal_Bool SwXTextTableCursor::mergeRange(void) throw( uno::RuntimeException )
+{
+ SolarMutexGuard aGuard;
+ sal_Bool bRet = sal_False;
+ SwUnoCrsr* pUnoCrsr = GetCrsr();
+ if(pUnoCrsr)
+ {
+ {
+ // hier muessen die Actions aufgehoben werden
+ UnoActionRemoveContext aRemoveContext(pUnoCrsr->GetDoc());
+ }
+ SwUnoTableCrsr* pTblCrsr = dynamic_cast<SwUnoTableCrsr*>(pUnoCrsr);
+ pTblCrsr->MakeBoxSels();
+
+ {
+ UnoActionContext aContext(pUnoCrsr->GetDoc());
+ bRet = TBLMERGE_OK == pTblCrsr->GetDoc()->MergeTbl(*pTblCrsr);
+ if(bRet)
+ {
+ sal_uInt16 nCount = pTblCrsr->GetBoxesCount();
+ while(nCount--)
+ pTblCrsr->DeleteBox(nCount);
+ }
+ }
+ pTblCrsr->MakeBoxSels();
+ }
+ return bRet;
+}
+
+sal_Bool SwXTextTableCursor::splitRange(sal_Int16 Count, sal_Bool Horizontal) throw( uno::RuntimeException )
+{
+ SolarMutexGuard aGuard;
+ if (Count <= 0)
+ throw uno::RuntimeException( OUString( RTL_CONSTASCII_USTRINGPARAM( "Illegal first argument: needs to be > 0" ) ), static_cast < cppu::OWeakObject * > ( this ) );
+ sal_Bool bRet = sal_False;
+ SwUnoCrsr* pUnoCrsr = GetCrsr();
+ if(pUnoCrsr)
+ {
+ {
+ // hier muessen die Actions aufgehoben werden
+ UnoActionRemoveContext aRemoveContext(pUnoCrsr->GetDoc());
+ }
+ SwUnoTableCrsr* pTblCrsr = dynamic_cast<SwUnoTableCrsr*>(pUnoCrsr);
+ pTblCrsr->MakeBoxSels();
+ {
+ UnoActionContext aContext(pUnoCrsr->GetDoc());
+ bRet = pTblCrsr->GetDoc()->SplitTbl( pTblCrsr->GetBoxes(), !Horizontal, Count );
+ }
+ pTblCrsr->MakeBoxSels();
+ }
+ return bRet;
+}
+
+uno::Reference< beans::XPropertySetInfo > SwXTextTableCursor::getPropertySetInfo(void) throw( uno::RuntimeException )
+{
+ static uno::Reference< beans::XPropertySetInfo > xRef = m_pPropSet->getPropertySetInfo();
+ return xRef;
+}
+
+void SwXTextTableCursor::setPropertyValue(const OUString& rPropertyName,
+ const uno::Any& aValue)
+ throw( beans::UnknownPropertyException,
+ beans::PropertyVetoException,
+ lang::IllegalArgumentException,
+ lang::WrappedTargetException,
+ uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+ SwUnoCrsr* pUnoCrsr = GetCrsr();
+ if(pUnoCrsr)
+ {
+ SwStartNode* pSttNode = pUnoCrsr->GetNode()->StartOfSectionNode();
+ const SwTableNode* pTblNode = pSttNode->FindTableNode();
+ lcl_FormatTable((SwFrmFmt*)pTblNode->GetTable().GetFrmFmt());
+ SwUnoTableCrsr* pTblCrsr = dynamic_cast<SwUnoTableCrsr*>(pUnoCrsr);
+ const SfxItemPropertySimpleEntry* pEntry =
+ m_pPropSet->getPropertyMap()->getByName(rPropertyName);
+ if(pEntry)
+ {
+ if ( pEntry->nFlags & beans::PropertyAttribute::READONLY)
+ throw beans::PropertyVetoException( OUString ( RTL_CONSTASCII_USTRINGPARAM ( "Property is read-only: " ) ) + rPropertyName, static_cast < cppu::OWeakObject * > ( this ) );
+ pTblCrsr->MakeBoxSels();
+ SwDoc* pDoc = pUnoCrsr->GetDoc();
+ switch(pEntry->nWID )
+ {
+ case FN_UNO_TABLE_CELL_BACKGROUND:
+ {
+ SvxBrushItem aBrush( RES_BACKGROUND );
+ pDoc->GetBoxAttr( *pUnoCrsr, aBrush );
+ aBrush.PutValue(aValue, pEntry->nMemberId);
+ pDoc->SetBoxAttr( *pUnoCrsr, aBrush );
+
+ }
+ break;
+ case RES_BOXATR_FORMAT:
+ {
+ SfxUInt32Item aNumberFormat(RES_BOXATR_FORMAT);
+ aNumberFormat.PutValue(aValue, 0);
+ pDoc->SetBoxAttr( *pUnoCrsr, aNumberFormat);
+ }
+ break;
+ case FN_UNO_PARA_STYLE:
+ SwUnoCursorHelper::SetTxtFmtColl(aValue, *pUnoCrsr);
+ break;
+ default:
+ {
+ SfxItemSet aItemSet( pDoc->GetAttrPool(), pEntry->nWID, pEntry->nWID );
+ SwUnoCursorHelper::GetCrsrAttr(pTblCrsr->GetSelRing(),
+ aItemSet);
+
+ if (!SwUnoCursorHelper::SetCursorPropertyValue(
+ *pEntry, aValue, pTblCrsr->GetSelRing(), aItemSet))
+ {
+ m_pPropSet->setPropertyValue(*pEntry, aValue, aItemSet);
+ }
+ SwUnoCursorHelper::SetCrsrAttr(pTblCrsr->GetSelRing(),
+ aItemSet, nsSetAttrMode::SETATTR_DEFAULT, true);
+ }
+ }
+ }
+ else
+ throw beans::UnknownPropertyException(OUString ( RTL_CONSTASCII_USTRINGPARAM ( "Unknown property: " ) ) + rPropertyName, static_cast < cppu::OWeakObject * > ( this ) );
+ }
+}
+
+uno::Any SwXTextTableCursor::getPropertyValue(const OUString& rPropertyName)
+ throw( beans::UnknownPropertyException, lang::WrappedTargetException, uno::RuntimeException )
+{
+ SolarMutexGuard aGuard;
+ uno::Any aRet;
+ SwUnoCrsr* pUnoCrsr = GetCrsr();
+ if(pUnoCrsr)
+ {
+ SwStartNode* pSttNode = pUnoCrsr->GetNode()->StartOfSectionNode();
+ const SwTableNode* pTblNode = pSttNode->FindTableNode();
+ lcl_FormatTable((SwFrmFmt*)pTblNode->GetTable().GetFrmFmt());
+ SwUnoTableCrsr* pTblCrsr = dynamic_cast<SwUnoTableCrsr*>(pUnoCrsr);
+ const SfxItemPropertySimpleEntry* pEntry =
+ m_pPropSet->getPropertyMap()->getByName(rPropertyName);
+ if(pEntry)
+ {
+ pTblCrsr->MakeBoxSels();
+ switch(pEntry->nWID )
+ {
+ case FN_UNO_TABLE_CELL_BACKGROUND:
+ {
+ SvxBrushItem aBrush( RES_BACKGROUND );
+ if(pTblCrsr->GetDoc()->GetBoxAttr( *pUnoCrsr, aBrush ))
+ aBrush.QueryValue(aRet, pEntry->nMemberId);
+
+ }
+ break;
+ case RES_BOXATR_FORMAT:
+ //GetAttr fuer Tabellenselektion am Doc fehlt noch
+ DBG_WARNING("not implemented");
+ break;
+ case FN_UNO_PARA_STYLE:
+ {
+ SwFmtColl *const pFmt =
+ SwUnoCursorHelper::GetCurTxtFmtColl(*pUnoCrsr, sal_False);
+ OUString sRet;
+ if(pFmt)
+ sRet = pFmt->GetName();
+ aRet <<= sRet;
+ }
+ break;
+ default:
+ {
+ SfxItemSet aSet(pTblCrsr->GetDoc()->GetAttrPool(),
+ RES_CHRATR_BEGIN, RES_FRMATR_END -1,
+ RES_UNKNOWNATR_CONTAINER, RES_UNKNOWNATR_CONTAINER,
+ 0L);
+ // erstmal die Attribute des Cursors
+ SwUnoCursorHelper::GetCrsrAttr(pTblCrsr->GetSelRing(),
+ aSet);
+ m_pPropSet->getPropertyValue(*pEntry, aSet, aRet);
+ }
+ }
+ }
+ else
+ throw beans::UnknownPropertyException(OUString ( RTL_CONSTASCII_USTRINGPARAM ( "Unknown property: " ) ) + rPropertyName, static_cast < cppu::OWeakObject * > ( this ) );
+ }
+ return aRet;
+}
+
+void SwXTextTableCursor::addPropertyChangeListener(const OUString& /*rPropertyName*/, const uno::Reference< beans::XPropertyChangeListener > & /*xListener*/) throw( beans::UnknownPropertyException, lang::WrappedTargetException, uno::RuntimeException )
+{
+ DBG_WARNING("not implemented");
+}
+
+void SwXTextTableCursor::removePropertyChangeListener(const OUString& /*rPropertyName*/, const uno::Reference< beans::XPropertyChangeListener > & /*xListener*/) throw( beans::UnknownPropertyException, lang::WrappedTargetException, uno::RuntimeException )
+{
+ DBG_WARNING("not implemented");
+}
+
+void SwXTextTableCursor::addVetoableChangeListener(const OUString& /*rPropertyName*/, const uno::Reference< beans::XVetoableChangeListener > & /*xListener*/) throw( beans::UnknownPropertyException, lang::WrappedTargetException, uno::RuntimeException )
+{
+ DBG_WARNING("not implemented");
+}
+
+void SwXTextTableCursor::removeVetoableChangeListener(const OUString& /*rPropertyName*/, const uno::Reference< beans::XVetoableChangeListener > & /*xListener*/) throw( beans::UnknownPropertyException, lang::WrappedTargetException, uno::RuntimeException )
+{
+ DBG_WARNING("not implemented");
+}
+
+void SwXTextTableCursor::Modify( const SfxPoolItem* pOld, const SfxPoolItem *pNew)
+{
+ ClientModify(this, pOld, pNew);
+}
+
+/******************************************************************
+ * SwXTextTable
+ ******************************************************************/
+/****************************************************************************
+ Tabellenbeschreibung
+****************************************************************************/
+class SwTableProperties_Impl
+{
+ SwUnoCursorHelper::SwAnyMapHelper aAnyMap;
+public:
+ SwTableProperties_Impl();
+ ~SwTableProperties_Impl();
+
+ void SetProperty(sal_uInt16 nWhichId, sal_uInt16 nMemberId, const uno::Any& aVal);
+ sal_Bool GetProperty(sal_uInt16 nWhichId, sal_uInt16 nMemberId, const uno::Any*& rpAny);
+
+ void ApplyTblAttr(const SwTable& rTbl, SwDoc& rDoc);
+};
+
+
+SwTableProperties_Impl::SwTableProperties_Impl()
+{
+}
+
+SwTableProperties_Impl::~SwTableProperties_Impl()
+{
+}
+
+void SwTableProperties_Impl::SetProperty(sal_uInt16 nWhichId, sal_uInt16 nMemberId, const uno::Any& rVal)
+{
+ aAnyMap.SetValue( nWhichId, nMemberId, rVal );
+}
+
+sal_Bool SwTableProperties_Impl::GetProperty(sal_uInt16 nWhichId, sal_uInt16 nMemberId, const uno::Any*& rpAny )
+{
+ return aAnyMap.FillValue( nWhichId, nMemberId, rpAny );
+}
+
+void SwTableProperties_Impl::ApplyTblAttr(const SwTable& rTbl, SwDoc& rDoc)
+{
+ SfxItemSet aSet(rDoc.GetAttrPool(),
+ RES_LAYOUT_SPLIT, RES_LAYOUT_SPLIT,
+ RES_BACKGROUND, RES_BACKGROUND,
+ RES_FRM_SIZE, RES_UL_SPACE,
+ RES_HORI_ORIENT, RES_HORI_ORIENT,
+ RES_BREAK, RES_BREAK,
+ RES_KEEP, RES_KEEP,
+ RES_SHADOW, RES_SHADOW,
+ RES_PAGEDESC, RES_PAGEDESC,
+ 0
+ );
+ const uno::Any* pRepHead;
+ const SwFrmFmt &rFrmFmt = *rTbl.GetFrmFmt();
+ if(GetProperty(FN_TABLE_HEADLINE_REPEAT, 0xff, pRepHead ))
+ {
+ sal_Bool bVal = *(sal_Bool*)pRepHead->getValue();
+ ((SwTable&)rTbl).SetRowsToRepeat( bVal ? 1 : 0 ); // TODO MULTIHEADER
+ }
+
+ const uno::Any* pBackColor = 0;
+ GetProperty(RES_BACKGROUND, MID_BACK_COLOR, pBackColor );
+ const uno::Any* pBackTrans = 0;
+ GetProperty(RES_BACKGROUND, MID_GRAPHIC_TRANSPARENT, pBackTrans );
+ const uno::Any* pGrLoc = 0;
+ GetProperty(RES_BACKGROUND, MID_GRAPHIC_POSITION, pGrLoc );
+ const uno::Any* pGrURL = 0;
+ GetProperty(RES_BACKGROUND, MID_GRAPHIC_URL, pGrURL );
+ const uno::Any* pGrFilter = 0;
+ GetProperty(RES_BACKGROUND, MID_GRAPHIC_FILTER, pGrFilter );
+
+ if(pBackColor||pBackTrans||pGrURL||pGrFilter||pGrLoc)
+ {
+ SvxBrushItem aBrush ( rFrmFmt.GetBackground() );
+ if(pBackColor)
+ aBrush.PutValue(*pBackColor, MID_BACK_COLOR);
+ if(pBackTrans)
+ aBrush.PutValue(*pBackTrans, MID_GRAPHIC_TRANSPARENT);
+ if(pGrURL)
+ aBrush.PutValue(*pGrURL, MID_GRAPHIC_URL);
+ if(pGrFilter)
+ aBrush.PutValue(*pGrFilter, MID_GRAPHIC_FILTER);
+ if(pGrLoc)
+ aBrush.PutValue(*pGrLoc, MID_GRAPHIC_POSITION);
+ aSet.Put(aBrush);
+ }
+
+ sal_Bool bPutBreak = sal_True;
+ const uno::Any* pPage;
+ if(GetProperty(FN_UNO_PAGE_STYLE, 0, pPage) || GetProperty(RES_PAGEDESC, 0xff, pPage))
+ {
+ OUString uTmp;
+ (*pPage) >>= uTmp;
+ String sPageStyle = uTmp;
+ if(sPageStyle.Len())
+ {
+ SwStyleNameMapper::FillUIName(sPageStyle, sPageStyle, nsSwGetPoolIdFromName::GET_POOLID_PAGEDESC, sal_True );
+ const SwPageDesc* pDesc = ::GetPageDescByName_Impl(rDoc, sPageStyle);
+ if(pDesc)
+ {
+ SwFmtPageDesc aDesc( pDesc );
+ const uno::Any* pPgNo;
+ if(GetProperty(RES_PAGEDESC, MID_PAGEDESC_PAGENUMOFFSET, pPgNo ))
+ {
+ sal_Int16 nTmp = 0;
+ (*pPgNo) >>= nTmp;
+ aDesc.SetNumOffset( nTmp );
+ }
+ aSet.Put(aDesc);
+ bPutBreak = sal_False;
+ }
+
+ }
+ }
+ const uno::Any* pBreak;
+ if(bPutBreak && GetProperty(RES_BREAK, 0, pBreak))
+ {
+ SvxFmtBreakItem aBreak ( rFrmFmt.GetBreak() );
+ aBreak.PutValue(*pBreak, 0);
+ aSet.Put(aBreak);
+ }
+ const uno::Any* pShadow;
+ if(GetProperty(RES_SHADOW, 0, pShadow))
+ {
+ SvxShadowItem aShd ( rFrmFmt.GetShadow() );
+ aShd.PutValue(*pShadow, CONVERT_TWIPS);
+ aSet.Put(aShd);
+ }
+ const uno::Any* pKeep;
+ if(GetProperty(RES_KEEP, 0, pKeep))
+ {
+ SvxFmtKeepItem aKeep( rFrmFmt.GetKeep() );
+ aKeep.PutValue(*pKeep, 0);
+ aSet.Put(aKeep);
+ }
+
+ const uno::Any* pHOrient;
+ if(GetProperty(RES_HORI_ORIENT, MID_HORIORIENT_ORIENT, pHOrient))
+ {
+ SwFmtHoriOrient aOrient ( rFrmFmt.GetHoriOrient() );
+ ((SfxPoolItem&)aOrient).PutValue(*pHOrient, MID_HORIORIENT_ORIENT|CONVERT_TWIPS);
+ aSet.Put(aOrient);
+ }
+
+ const uno::Any* pSzRel = 0;
+ GetProperty(FN_TABLE_IS_RELATIVE_WIDTH, 0xff, pSzRel );
+ const uno::Any* pRelWidth = 0;
+ GetProperty(FN_TABLE_RELATIVE_WIDTH, 0xff, pRelWidth);
+ const uno::Any* pWidth = 0;
+ GetProperty(FN_TABLE_WIDTH, 0xff, pWidth );
+
+ sal_Bool bPutSize = pWidth != 0;
+ SwFmtFrmSize aSz( ATT_VAR_SIZE);
+ if(pWidth)
+ {
+ ((SfxPoolItem&)aSz).PutValue(*pWidth, MID_FRMSIZE_WIDTH);
+ bPutSize = sal_True;
+ }
+ sal_Bool bTemp = pSzRel ? *(sal_Bool*)pSzRel->getValue() : sal_False;
+ if(pSzRel && bTemp && pRelWidth)
+ {
+ ((SfxPoolItem&)aSz).PutValue(*pRelWidth, MID_FRMSIZE_REL_WIDTH|CONVERT_TWIPS);
+ bPutSize = sal_True;
+ }
+ if(bPutSize)
+ {
+ if(!aSz.GetWidth())
+ aSz.SetWidth(MINLAY);
+ aSet.Put(aSz);
+ }
+ const uno::Any* pL = 0;
+ GetProperty(RES_LR_SPACE, MID_L_MARGIN|CONVERT_TWIPS, pL);
+ const uno::Any* pR = 0;
+ GetProperty(RES_LR_SPACE, MID_R_MARGIN|CONVERT_TWIPS, pR);
+ if(pL||pR)
+ {
+ SvxLRSpaceItem aLR ( rFrmFmt.GetLRSpace() );
+ if(pL)
+ ((SfxPoolItem&)aLR).PutValue(*pL, MID_L_MARGIN|CONVERT_TWIPS);
+ if(pR)
+ ((SfxPoolItem&)aLR).PutValue(*pR, MID_R_MARGIN|CONVERT_TWIPS);
+ aSet.Put(aLR);
+ }
+ const uno::Any* pU = 0;
+ GetProperty(RES_UL_SPACE, MID_UP_MARGIN|CONVERT_TWIPS, pU);
+ const uno::Any* pLo = 0;
+ GetProperty(RES_UL_SPACE, MID_LO_MARGIN|CONVERT_TWIPS, pLo);
+ if(pU||pLo)
+ {
+ SvxULSpaceItem aUL ( rFrmFmt.GetULSpace() );
+ if(pU)
+ ((SfxPoolItem&)aUL).PutValue(*pU, MID_UP_MARGIN|CONVERT_TWIPS);
+ if(pLo)
+ ((SfxPoolItem&)aUL).PutValue(*pLo, MID_LO_MARGIN|CONVERT_TWIPS);
+ aSet.Put(aUL);
+ }
+ const::uno::Any* pSplit;
+ if(GetProperty(RES_LAYOUT_SPLIT, 0, pSplit ))
+ {
+ sal_Bool bTmp = *(sal_Bool*)pSplit->getValue();
+ SwFmtLayoutSplit aSp(bTmp);
+ aSet.Put(aSp);
+ }
+
+ //TODO: folgende Propertiers noch impl.
+// FN_UNO_RANGE_ROW_LABEL
+// FN_UNO_RANGE_COL_LABEL
+// FN_UNO_TABLE_BORDER
+
+ if(aSet.Count())
+ {
+ rDoc.SetAttr( aSet, *rTbl.GetFrmFmt() );
+ }
+}
+const uno::Sequence< sal_Int8 > & SwXTextTable::getUnoTunnelId()
+{
+ static uno::Sequence< sal_Int8 > aSeq = ::CreateUnoTunnelId();
+ return aSeq;
+}
+
+sal_Int64 SAL_CALL SwXTextTable::getSomething( const uno::Sequence< sal_Int8 >& rId )
+ throw(uno::RuntimeException)
+{
+ if( rId.getLength() == 16
+ && 0 == rtl_compareMemory( getUnoTunnelId().getConstArray(),
+ rId.getConstArray(), 16 ) )
+ {
+ return sal::static_int_cast< sal_Int64 >( reinterpret_cast< sal_IntPtr >(this) );
+ }
+ return 0;
+}
+
+TYPEINIT1(SwXTextTable, SwClient)
+
+SwXTextTable::SwXTextTable() :
+ aLstnrCntnr( (text::XTextTable*)this),
+ aChartLstnrCntnr( (text::XTextTable*)this),
+ m_pPropSet(aSwMapProvider.GetPropertySet(PROPERTY_MAP_TEXT_TABLE)),
+ pTableProps(new SwTableProperties_Impl),
+ bIsDescriptor(sal_True),
+ nRows(2),
+ nColumns(2),
+ bFirstRowAsLabel(sal_False),
+ bFirstColumnAsLabel(sal_False)
+{
+}
+
+SwXTextTable::SwXTextTable(SwFrmFmt& rFrmFmt) :
+ SwClient( &rFrmFmt ),
+ aLstnrCntnr( (text::XTextTable*)this),
+ aChartLstnrCntnr( (text::XTextTable*)this),
+ m_pPropSet(aSwMapProvider.GetPropertySet(PROPERTY_MAP_TEXT_TABLE)),
+ pTableProps(0),
+ bIsDescriptor(sal_False),
+ nRows(0),
+ nColumns(0),
+ bFirstRowAsLabel(sal_False),
+ bFirstColumnAsLabel(sal_False)
+{
+}
+
+SwXTextTable::~SwXTextTable()
+{
+ delete pTableProps;
+}
+
+void SwXTextTable::initialize(sal_Int32 nR, sal_Int32 nC) throw( uno::RuntimeException )
+{
+ if(!bIsDescriptor || nR <= 0 || nC <= 0 || nR >= USHRT_MAX || nC >= USHRT_MAX )
+ throw uno::RuntimeException();
+ else
+ {
+ nRows = (sal_uInt16)nR;
+ nColumns = (sal_uInt16)nC;
+ }
+}
+
+uno::Reference< table::XTableRows > SwXTextTable::getRows(void) throw( uno::RuntimeException )
+{
+ SolarMutexGuard aGuard;
+ uno::Reference< table::XTableRows > xRet;
+ if (SwFrmFmt* pFmt = GetFrmFmt())
+ {
+ SwXTableRows* pRows = SwIterator<SwXTableRows,SwFmt>::FirstElement(*pFmt);
+ if (!pRows)
+ pRows = new SwXTableRows(*pFmt);
+ xRet = pRows;
+ }
+ if (!xRet.is())
+ throw uno::RuntimeException();
+ return xRet;
+}
+
+uno::Reference< table::XTableColumns > SwXTextTable::getColumns(void) throw( uno::RuntimeException )
+{
+ SolarMutexGuard aGuard;
+ uno::Reference< table::XTableColumns > xRet;
+ if (SwFrmFmt* pFmt = GetFrmFmt())
+ {
+ SwXTableColumns* pCols = SwIterator<SwXTableColumns,SwFmt>::FirstElement(*pFmt);
+ if (!pCols)
+ pCols = new SwXTableColumns(*pFmt);
+ xRet = pCols;
+ }
+ if (!xRet.is())
+ throw uno::RuntimeException();
+ return xRet;
+}
+
+uno::Reference< table::XCell > SwXTextTable::getCellByName(const OUString& CellName) throw( uno::RuntimeException )
+{
+ SolarMutexGuard aGuard;
+ uno::Reference< table::XCell > xRet;
+ SwFrmFmt* pFmt = GetFrmFmt();
+ if(pFmt)
+ {
+ SwTable* pTable = SwTable::FindTable( pFmt );
+ String sCellName(CellName);
+ SwTableBox* pBox = (SwTableBox*)pTable->GetTblBox( sCellName );
+ if(pBox)
+ {
+ xRet = SwXCell::CreateXCell(pFmt, pBox);
+ }
+ }
+ else
+ throw uno::RuntimeException();
+ return xRet;
+}
+
+uno::Sequence< OUString > SwXTextTable::getCellNames(void) throw( uno::RuntimeException )
+{
+ SolarMutexGuard aGuard;
+ SwFrmFmt* pFmt = GetFrmFmt();
+ if(pFmt)
+ {
+ SwTable* pTable = SwTable::FindTable( pFmt );
+ // gibts an der Tabelle und an allen Boxen
+ SwTableLines& rTblLines = pTable->GetTabLines();
+ SvStrings aAllNames;
+ lcl_InspectLines(rTblLines, aAllNames);
+ uno::Sequence< OUString > aRet(aAllNames.Count());
+ OUString* pArray = aRet.getArray();
+ for(sal_uInt16 i = aAllNames.Count(); i; i--)
+ {
+ String* pObject = aAllNames.GetObject(i-1);
+ pArray[i - 1] = *pObject;
+ aAllNames.Remove(i - 1);
+ delete pObject;
+ }
+ return aRet;
+ }
+ return uno::Sequence< OUString >();
+}
+
+uno::Reference< text::XTextTableCursor > SwXTextTable::createCursorByCellName(const OUString& CellName)
+ throw( uno::RuntimeException )
+{
+ SolarMutexGuard aGuard;
+ uno::Reference< text::XTextTableCursor > xRet;
+ SwFrmFmt* pFmt = GetFrmFmt();
+ if(pFmt)
+ {
+ SwTable* pTable = SwTable::FindTable( pFmt );
+ String sCellName(CellName);
+ SwTableBox* pBox = (SwTableBox*)pTable->GetTblBox( sCellName );
+ if(pBox && pBox->getRowSpan() > 0 )
+ {
+ xRet = new SwXTextTableCursor(pFmt, pBox);
+ }
+ }
+ if(!xRet.is())
+ throw uno::RuntimeException();
+ return xRet;
+}
+
+void SwXTextTable::attachToRange(const uno::Reference< text::XTextRange > & xTextRange)
+ throw( lang::IllegalArgumentException, uno::RuntimeException )
+{
+ // attachToRange must only be called once
+ if(!bIsDescriptor) /* already attached ? */
+ throw uno::RuntimeException( OUString ( RTL_CONSTASCII_USTRINGPARAM ( "SwXTextTable: already attached to range." ) ), static_cast < cppu::OWeakObject * > ( this ) );
+
+ uno::Reference<XUnoTunnel> xRangeTunnel( xTextRange, uno::UNO_QUERY);
+ SwXTextRange* pRange = 0;
+ OTextCursorHelper* pCursor = 0;
+ if(xRangeTunnel.is())
+ {
+ pRange = reinterpret_cast< SwXTextRange * >(
+ sal::static_int_cast< sal_IntPtr >( xRangeTunnel->getSomething( SwXTextRange::getUnoTunnelId()) ));
+ pCursor = reinterpret_cast< OTextCursorHelper * >(
+ sal::static_int_cast< sal_IntPtr >( xRangeTunnel->getSomething( OTextCursorHelper::getUnoTunnelId()) ));
+ }
+ SwDoc* pDoc = pRange ? (SwDoc*)pRange->GetDoc() : pCursor ? (SwDoc*)pCursor->GetDoc() : 0;
+ if(pDoc && nRows && nColumns)
+ {
+ SwUnoInternalPaM aPam(*pDoc);
+ //das muss jetzt sal_True liefern
+ ::sw::XTextRangeToSwPaM(aPam, xTextRange);
+
+ {
+ UnoActionContext aCont( pDoc );
+
+ pDoc->GetIDocumentUndoRedo().StartUndo(UNDO_EMPTY, NULL);
+ const SwTable *pTable = 0;
+ if( 0 != aPam.Start()->nContent.GetIndex() )
+ {
+ pDoc->SplitNode(*aPam.Start(), false );
+ }
+ //TODO: wenn es der letzte Absatz ist, dann muss noch ein Absatz angehaengt werden!
+ if( aPam.HasMark() )
+ {
+ pDoc->DeleteAndJoin(aPam);
+ aPam.DeleteMark();
+ }
+ pTable = pDoc->InsertTable( SwInsertTableOptions( tabopts::HEADLINE | tabopts::DEFAULT_BORDER | tabopts::SPLIT_LAYOUT, 0 ),
+ *aPam.GetPoint(),
+ nRows,
+ nColumns,
+ text::HoriOrientation::FULL );
+ if(pTable)
+ {
+ // hier muessen die Properties des Descriptors ausgewertet werden
+ pTableProps->ApplyTblAttr(*pTable, *pDoc);
+ SwFrmFmt* pTblFmt = pTable->GetFrmFmt();
+ lcl_FormatTable( pTblFmt );
+
+ pTblFmt->Add(this);
+ if(m_sTableName.Len())
+ {
+ sal_uInt16 nIndex = 1;
+ const String sTmpName(m_sTableName);
+ String sTmpNameIndex(sTmpName);
+ while(pDoc->FindTblFmtByName( sTmpNameIndex, sal_True ) && nIndex < USHRT_MAX)
+ {
+ sTmpNameIndex = sTmpName;
+ sTmpNameIndex += nIndex++;
+ }
+ pDoc->SetTableName( *pTblFmt, sTmpNameIndex);
+ }
+
+ const::uno::Any* pName;
+ if(pTableProps->GetProperty(FN_UNO_TABLE_NAME, 0, pName))
+ {
+ OUString sTmp;
+ (*pName) >>= sTmp;
+ setName(sTmp);
+ }
+ bIsDescriptor = sal_False;
+ DELETEZ(pTableProps);
+ }
+ pDoc->GetIDocumentUndoRedo().EndUndo( UNDO_END, NULL );
+ }
+ }
+ else
+ throw lang::IllegalArgumentException();
+}
+
+void SwXTextTable::attach(const uno::Reference< text::XTextRange > & xTextRange)
+ throw( lang::IllegalArgumentException, uno::RuntimeException )
+{
+ SolarMutexGuard aGuard;
+ attachToRange( xTextRange );
+}
+
+uno::Reference< text::XTextRange > SwXTextTable::getAnchor(void)
+ throw( uno::RuntimeException )
+{
+ SolarMutexGuard aGuard;
+ SwFrmFmt* pFmt = GetFrmFmt();
+ if(!pFmt)
+ throw uno::RuntimeException();
+ uno::Reference< text::XTextRange > xRet = new SwXTextRange(*pFmt);
+ return xRet;
+}
+
+void SwXTextTable::dispose(void) throw( uno::RuntimeException )
+{
+ SolarMutexGuard aGuard;
+ SwFrmFmt* pFmt = GetFrmFmt();
+ if(pFmt)
+ {
+ SwTable* pTable = SwTable::FindTable( pFmt );
+ SwTableSortBoxes& rBoxes = pTable->GetTabSortBoxes();
+ SwSelBoxes aSelBoxes;
+ aSelBoxes.Insert(rBoxes.GetData(), rBoxes.Count());
+ pFmt->GetDoc()->DeleteRowCol(aSelBoxes);
+ }
+ else
+ throw uno::RuntimeException();
+}
+
+void SwXTextTable::addEventListener(const uno::Reference< lang::XEventListener > & aListener) throw( uno::RuntimeException )
+{
+ if(!GetRegisteredIn())
+ throw uno::RuntimeException();
+ aLstnrCntnr.AddListener(aListener);
+}
+
+void SwXTextTable::removeEventListener(const uno::Reference< lang::XEventListener > & aListener) throw( uno::RuntimeException )
+{
+ if(!GetRegisteredIn() || !aLstnrCntnr.RemoveListener(aListener))
+ throw uno::RuntimeException();
+}
+
+uno::Reference< table::XCell > SwXTextTable::getCellByPosition(sal_Int32 nColumn, sal_Int32 nRow)
+ throw( uno::RuntimeException, lang::IndexOutOfBoundsException )
+{
+ SolarMutexGuard aGuard;
+ uno::Reference< table::XCell > aRef;
+ SwFrmFmt* pFmt = GetFrmFmt();
+ // Sheet interessiert nicht
+ if(nColumn >= 0 && nRow >= 0 && nColumn < USHRT_MAX && nRow < USHRT_MAX && pFmt)
+ {
+ SwXCell* pXCell = lcl_CreateXCell(pFmt, nColumn, nRow);
+ if(pXCell)
+ aRef = pXCell;
+ }
+ if(!aRef.is())
+ throw lang::IndexOutOfBoundsException();
+ return aRef;
+
+}
+
+uno::Reference< table::XCellRange > SwXTextTable::GetRangeByName(SwFrmFmt* pFmt, SwTable* pTable,
+ const String& rTLName, const String& rBRName,
+ SwRangeDescriptor& rDesc)
+{
+ SolarMutexGuard aGuard;
+ uno::Reference< table::XCellRange > aRef;
+ String sTLName(rTLName);
+ String sBRName(rBRName);
+ const SwTableBox* pTLBox = pTable->GetTblBox( sTLName );
+ if(pTLBox)
+ {
+ // hier muessen die Actions aufgehoben werden
+ UnoActionRemoveContext aRemoveContext(pFmt->GetDoc());
+ const SwStartNode* pSttNd = pTLBox->GetSttNd();
+ SwPosition aPos(*pSttNd);
+ // Cursor in die obere linke Zelle des Ranges setzen
+ SwUnoCrsr* pUnoCrsr = pFmt->GetDoc()->CreateUnoCrsr(aPos, sal_True);
+ pUnoCrsr->Move( fnMoveForward, fnGoNode );
+ pUnoCrsr->SetRemainInSection( sal_False );
+ const SwTableBox* pBRBox = pTable->GetTblBox( sBRName );
+ if(pBRBox)
+ {
+ pUnoCrsr->SetMark();
+ pUnoCrsr->GetPoint()->nNode = *pBRBox->GetSttNd();
+ pUnoCrsr->Move( fnMoveForward, fnGoNode );
+ SwUnoTableCrsr* pCrsr = dynamic_cast<SwUnoTableCrsr*>(pUnoCrsr);
+ pCrsr->MakeBoxSels();
+ // pUnoCrsr wird uebergeben und nicht geloescht
+ SwXCellRange* pCellRange = new SwXCellRange(pUnoCrsr, *pFmt, rDesc);
+ aRef = pCellRange;
+ }
+ else
+ delete pUnoCrsr;
+ }
+ return aRef;
+}
+
+uno::Reference< table::XCellRange > SwXTextTable::getCellRangeByPosition(sal_Int32 nLeft, sal_Int32 nTop,
+ sal_Int32 nRight, sal_Int32 nBottom)
+ throw( uno::RuntimeException, lang::IndexOutOfBoundsException )
+{
+ SolarMutexGuard aGuard;
+ uno::Reference< table::XCellRange > aRef;
+ SwFrmFmt* pFmt = GetFrmFmt();
+ if(pFmt && nRight < USHRT_MAX && nBottom < USHRT_MAX &&
+ nLeft <= nRight && nTop <= nBottom &&
+ nLeft >= 0 && nRight >= 0 && nTop >= 0 && nBottom >= 0 )
+ {
+ SwTable* pTable = SwTable::FindTable( pFmt );
+ if(!pTable->IsTblComplex())
+ {
+ SwRangeDescriptor aDesc;
+ aDesc.nTop = nTop;
+ aDesc.nBottom = nBottom;
+ aDesc.nLeft = nLeft;
+ aDesc.nRight = nRight;
+ String sTLName = lcl_GetCellName(aDesc.nLeft, aDesc.nTop);
+ String sBRName = lcl_GetCellName(aDesc.nRight, aDesc.nBottom);
+
+ // please note that according to the 'if' statement at the begin
+ // sTLName:sBRName already denotes the normalized range string
+
+ aRef = GetRangeByName(pFmt, pTable, sTLName, sBRName, aDesc);
+ }
+ }
+ if(!aRef.is())
+ throw lang::IndexOutOfBoundsException();
+ return aRef;
+}
+
+uno::Reference< table::XCellRange > SwXTextTable::getCellRangeByName(const OUString& aRange)
+ throw( uno::RuntimeException )
+{
+ SolarMutexGuard aGuard;
+ uno::Reference< table::XCellRange > aRef;
+ SwFrmFmt* pFmt = GetFrmFmt();
+ if(pFmt)
+ {
+ SwTable* pTable = SwTable::FindTable( pFmt );
+ if(!pTable->IsTblComplex())
+ {
+ String sRange(aRange);
+ String sTLName(sRange.GetToken(0, ':'));
+ String sBRName(sRange.GetToken(1, ':'));
+ if(!sTLName.Len() || !sBRName.Len())
+ throw uno::RuntimeException();
+ SwRangeDescriptor aDesc;
+ aDesc.nTop = aDesc.nLeft = aDesc.nBottom = aDesc.nRight = -1;
+ lcl_GetCellPosition(sTLName, aDesc.nLeft, aDesc.nTop );
+ lcl_GetCellPosition(sBRName, aDesc.nRight, aDesc.nBottom );
+
+ // we should normalize the range now (e.g. A5:C1 will become A1:C5)
+ // since (depending on what is done later) it will be troublesome
+ // elsewhere when the cursor in the implementation does not
+ // point to the top-left and bottom-right cells
+ aDesc.Normalize();
+
+ aRef = GetRangeByName(pFmt, pTable, sTLName, sBRName, aDesc);
+ }
+ }
+ if(!aRef.is())
+ throw uno::RuntimeException();
+ return aRef;
+}
+
+uno::Sequence< uno::Sequence< uno::Any > > SAL_CALL SwXTextTable::getDataArray()
+ throw (uno::RuntimeException)
+{
+ // see SwXTextTable::getData(...) also
+
+ SolarMutexGuard aGuard;
+ sal_Int16 nRowCount = getRowCount();
+ sal_Int16 nColCount = getColumnCount();
+ if(!nRowCount || !nColCount)
+ {
+ uno::RuntimeException aRuntime;
+ aRuntime.Message = C2U("Table too complex");
+ throw aRuntime;
+ }
+ SwFrmFmt* pFmt = GetFrmFmt();
+ uno::Sequence< uno::Sequence< uno::Any > > aRowSeq(nRowCount);
+ if(pFmt)
+ {
+ uno::Sequence< uno::Any > * pRowArray = aRowSeq.getArray();
+ for(sal_uInt16 nRow = 0; nRow < nRowCount; nRow++)
+ {
+ uno::Sequence< uno::Any > aColSeq(nColCount);
+ uno::Any * pColArray = aColSeq.getArray();
+ uno::Reference< table::XCell > xCellRef;
+ for(sal_uInt16 nCol = 0; nCol < nColCount; nCol++)
+ {
+ SwXCell* pXCell = lcl_CreateXCell(pFmt, nCol, nRow);
+ //! keep (additional) reference to object to prevent implicit destruction
+ //! in following UNO calls (when object will get referenced)
+ xCellRef = pXCell;
+ SwTableBox * pBox = pXCell ? pXCell->GetTblBox() : 0;
+ if(!pBox)
+ {
+ throw uno::RuntimeException();
+ }
+ else
+ {
+ // check if table box value item is set
+ SwFrmFmt* pBoxFmt = pBox->GetFrmFmt();
+ sal_Bool bIsNum = pBoxFmt->GetItemState( RES_BOXATR_VALUE, sal_False ) == SFX_ITEM_SET;
+ //const SfxPoolItem* pItem;
+ //SwDoc* pDoc = pXCell->GetDoc();
+ //sal_Bool bIsText = (SFX_ITEM_SET != pBoxFmt->GetAttrSet().GetItemState(RES_BOXATR_FORMAT, sal_True, &pItem)
+ // || pDoc->GetNumberFormatter()->IsTextFormat(((SwTblBoxNumFormat*)pItem)->GetValue())
+ // || ((SwTblBoxNumFormat*)pItem)->GetValue() == NUMBERFORMAT_TEXT);
+
+ if(!bIsNum/*bIsText*/)
+ pColArray[nCol] <<= lcl_getString(*pXCell);
+ else
+ pColArray[nCol] <<= lcl_getValue(*pXCell);
+ }
+ }
+ pRowArray[nRow] = aColSeq;
+ }
+ }
+ else
+ throw uno::RuntimeException();
+ return aRowSeq;
+}
+
+void SAL_CALL SwXTextTable::setDataArray(
+ const uno::Sequence< uno::Sequence< uno::Any > >& rArray )
+ throw (uno::RuntimeException)
+{
+ // see SwXTextTable::setData(...) also
+
+ SolarMutexGuard aGuard;
+ sal_Int16 nRowCount = getRowCount();
+ sal_Int16 nColCount = getColumnCount();
+
+ SwFrmFmt* pFmt = GetFrmFmt();
+ if(pFmt)
+ {
+ SwTable* pTable = SwTable::FindTable( pFmt );
+ if(pTable->IsTblComplex())
+ {
+ uno::RuntimeException aRuntime;
+ aRuntime.Message = C2U("Table too complex");
+ throw aRuntime;
+ }
+
+ if(rArray.getLength() != nRowCount)
+ {
+ throw uno::RuntimeException();
+ }
+ const uno::Sequence< uno::Any >* pRowArray = rArray.getConstArray();
+ for(sal_uInt16 nRow = 0; nRow < nRowCount; nRow++)
+ {
+ const uno::Sequence< uno::Any >& rColSeq = pRowArray[nRow];
+ if(rColSeq.getLength() != nColCount)
+ {
+ throw uno::RuntimeException();
+ }
+ const uno::Any * pColArray = rColSeq.getConstArray();
+ uno::Reference< table::XCell > xCellRef;
+ for(sal_uInt16 nCol = 0; nCol < nColCount; nCol++)
+ {
+ SwXCell* pXCell = lcl_CreateXCell(pFmt, nCol, nRow);
+ //! keep (additional) reference to object to prevent implicit destruction
+ //! in following UNO calls (when object will get referenced)
+ xCellRef = pXCell;
+ SwTableBox * pBox = pXCell ? pXCell->GetTblBox() : 0;
+ if(!pBox)
+ {
+ throw uno::RuntimeException();
+ }
+ else
+ {
+ const uno::Any &rAny = pColArray[nCol];
+ if (uno::TypeClass_STRING == rAny.getValueTypeClass())
+ lcl_setString( *pXCell, *(rtl::OUString *) rAny.getValue() );
+ else
+ {
+ double d = 0;
+ // #i20067# don't throw exception just do nothing if
+ // there is no value set
+ if( (rAny >>= d) )
+ lcl_setValue( *pXCell, d );
+ else
+ lcl_setString( *pXCell, OUString(), sal_True );
+
+ }
+ }
+ }
+ }
+ }
+}
+
+uno::Sequence< uno::Sequence< double > > SwXTextTable::getData(void)
+ throw( uno::RuntimeException )
+{
+ SolarMutexGuard aGuard;
+ sal_Int16 nRowCount = getRowCount();
+ sal_Int16 nColCount = getColumnCount();
+ if(!nRowCount || !nColCount)
+ {
+ uno::RuntimeException aRuntime;
+ aRuntime.Message = C2U("Table too complex");
+ throw aRuntime;
+ }
+ //
+ SwFrmFmt* pFmt = GetFrmFmt();
+ uno::Sequence< uno::Sequence< double > > aRowSeq(bFirstRowAsLabel ? nRowCount - 1 : nRowCount);
+ if(pFmt)
+ {
+ uno::Sequence< double >* pArray = aRowSeq.getArray();
+
+ sal_uInt16 nRowStart = bFirstRowAsLabel ? 1 : 0;
+ for(sal_uInt16 nRow = nRowStart; nRow < nRowCount; nRow++)
+ {
+ uno::Sequence< double > aColSeq(bFirstColumnAsLabel ? nColCount - 1 : nColCount);
+ double* pColArray = aColSeq.getArray();
+ sal_uInt16 nColStart = bFirstColumnAsLabel ? 1 : 0;
+ for(sal_uInt16 nCol = nColStart; nCol < nColCount; nCol++)
+ {
+ uno::Reference< table::XCell > xCell = getCellByPosition(nCol, nRow);
+ if(!xCell.is())
+ {
+ throw uno::RuntimeException();
+ }
+ pColArray[nCol - nColStart] = xCell->getValue();
+ }
+ pArray[nRow - nRowStart] = aColSeq;
+ }
+ }
+ else
+ throw uno::RuntimeException();
+ return aRowSeq;
+}
+
+void SwXTextTable::setData(const uno::Sequence< uno::Sequence< double > >& rData)
+ throw( uno::RuntimeException )
+{
+ SolarMutexGuard aGuard;
+ sal_Int16 nRowCount = getRowCount();
+ sal_Int16 nColCount = getColumnCount();
+ sal_Bool bChanged = sal_False;
+
+ if(!nRowCount || !nColCount)
+ {
+ uno::RuntimeException aRuntime;
+ aRuntime.Message = C2U("Table too complex");
+ throw aRuntime;
+ }
+ SwFrmFmt* pFmt = GetFrmFmt();
+ if(pFmt )
+ {
+ sal_uInt16 nRowStart = bFirstRowAsLabel ? 1 : 0;
+ if(rData.getLength() < nRowCount - nRowStart)
+ {
+ throw uno::RuntimeException();
+ }
+ const uno::Sequence< double >* pRowArray = rData.getConstArray();
+ for(sal_uInt16 nRow = nRowStart; nRow < nRowCount; nRow++)
+ {
+ const uno::Sequence< double >& rColSeq = pRowArray[nRow - nRowStart];
+ sal_uInt16 nColStart = bFirstColumnAsLabel ? 1 : 0;
+ if(rColSeq.getLength() < nColCount - nColStart)
+ {
+ throw uno::RuntimeException();
+ }
+ const double * pColArray = rColSeq.getConstArray();
+ for(sal_uInt16 nCol = nColStart; nCol < nColCount; nCol++)
+ {
+ uno::Reference< table::XCell > xCell = getCellByPosition(nCol, nRow);
+ if(!xCell.is())
+ {
+ throw uno::RuntimeException();
+ }
+ xCell->setValue(pColArray[nCol - nColStart]);
+ bChanged=sal_True;
+ }
+ }
+ if ( bChanged )
+ aChartLstnrCntnr.ChartDataChanged();
+ }
+}
+
+uno::Sequence< OUString > SwXTextTable::getRowDescriptions(void) throw( uno::RuntimeException )
+{
+ SolarMutexGuard aGuard;
+ sal_Int16 nRowCount = getRowCount();
+ if(!nRowCount)
+ {
+ uno::RuntimeException aRuntime;
+ aRuntime.Message = C2U("Table too complex");
+ throw aRuntime;
+ }
+ uno::Sequence< OUString > aRet(bFirstColumnAsLabel ? nRowCount - 1 : nRowCount);
+ SwFrmFmt* pFmt = GetFrmFmt();
+ if(pFmt)
+ {
+ OUString* pArray = aRet.getArray();
+ if(bFirstColumnAsLabel)
+ {
+ sal_uInt16 nStart = bFirstRowAsLabel ? 1 : 0;
+ for(sal_uInt16 i = nStart; i < nRowCount; i++)
+ {
+ uno::Reference< table::XCell > xCell = getCellByPosition(0, i);
+ if(!xCell.is())
+ {
+ //exception ...
+ break;
+ }
+ uno::Reference< text::XText > xText(xCell, uno::UNO_QUERY);
+ pArray[i - nStart] = xText->getString();
+ }
+ }
+ else
+ {
+ OSL_FAIL("Wo kommen die Labels her?");
+ }
+ }
+ else
+ throw uno::RuntimeException();
+ return aRet;
+}
+
+void SwXTextTable::setRowDescriptions(const uno::Sequence< OUString >& rRowDesc) throw( uno::RuntimeException )
+{
+ SolarMutexGuard aGuard;
+ SwFrmFmt* pFmt = GetFrmFmt();
+ if(pFmt)
+ {
+ sal_Int16 nRowCount = getRowCount();
+ if(!nRowCount || rRowDesc.getLength() < (bFirstRowAsLabel ? nRowCount - 1 : nRowCount))
+ {
+ throw uno::RuntimeException();
+ }
+ const OUString* pArray = rRowDesc.getConstArray();
+ if(bFirstColumnAsLabel)
+ {
+ sal_uInt16 nStart = bFirstRowAsLabel ? 1 : 0;
+ for(sal_uInt16 i = nStart; i < nRowCount; i++)
+ {
+ uno::Reference< table::XCell > xCell = getCellByPosition(0, i);
+ if(!xCell.is())
+ {
+ throw uno::RuntimeException();
+ }
+ uno::Reference< text::XText > xText(xCell, uno::UNO_QUERY);
+ xText->setString(pArray[i - nStart]);
+ }
+ }
+ else
+ {
+ OSL_FAIL("Wohin mit den Labels?");
+ }
+ }
+ else
+ throw uno::RuntimeException();
+}
+
+uno::Sequence< OUString > SwXTextTable::getColumnDescriptions(void)
+ throw( uno::RuntimeException )
+{
+ SolarMutexGuard aGuard;
+ sal_Int16 nColCount = getColumnCount();
+ if(!nColCount)
+ {
+ uno::RuntimeException aRuntime;
+ aRuntime.Message = C2U("Table too complex");
+ throw aRuntime;
+ }
+ uno::Sequence< OUString > aRet(bFirstRowAsLabel ? nColCount - 1 : nColCount);
+ SwFrmFmt* pFmt = GetFrmFmt();
+ if(pFmt)
+ {
+ OUString* pArray = aRet.getArray();
+ if(bFirstRowAsLabel)
+ {
+ sal_uInt16 nStart = bFirstColumnAsLabel ? 1 : 0;
+ for(sal_uInt16 i = nStart; i < nColCount; i++)
+ {
+ uno::Reference< table::XCell > xCell = getCellByPosition(i, 0);
+ if(!xCell.is())
+ {
+ throw uno::RuntimeException();
+ }
+ uno::Reference< text::XText > xText(xCell, uno::UNO_QUERY);
+
+ pArray[i - nStart] = xText->getString();
+ }
+ }
+ else
+ {
+ OSL_FAIL("Wo kommen die Labels her?");
+ }
+ }
+ else
+ throw uno::RuntimeException();
+ return aRet;
+}
+
+void SwXTextTable::setColumnDescriptions(const uno::Sequence< OUString >& rColumnDesc) throw( uno::RuntimeException )
+{
+ SolarMutexGuard aGuard;
+ sal_Int16 nColCount = getColumnCount();
+ if(!nColCount)
+ {
+ uno::RuntimeException aRuntime;
+ aRuntime.Message = C2U("Table too complex");
+ throw aRuntime;
+ }
+ SwFrmFmt* pFmt = GetFrmFmt();
+ if(pFmt)
+ {
+ const OUString* pArray = rColumnDesc.getConstArray();
+ if(bFirstRowAsLabel && rColumnDesc.getLength() >= nColCount - bFirstColumnAsLabel ? 1 : 0)
+ {
+ sal_uInt16 nStart = bFirstColumnAsLabel ? 1 : 0;
+ for(sal_uInt16 i = nStart; i < nColCount; i++)
+ {
+ uno::Reference< table::XCell > xCell = getCellByPosition(i, 0);
+ if(!xCell.is())
+ {
+ throw uno::RuntimeException();
+ }
+ uno::Reference< text::XText > xText(xCell, uno::UNO_QUERY);
+ xText->setString(pArray[i - nStart]);
+ }
+ }
+ else
+ {
+ OSL_FAIL("Wo kommen die Labels her?");
+ }
+ }
+ else
+ throw uno::RuntimeException();
+}
+
+void SwXTextTable::addChartDataChangeEventListener(
+ const uno::Reference< chart::XChartDataChangeEventListener > & aListener)
+ throw( uno::RuntimeException )
+{
+ if(!GetRegisteredIn())
+ throw uno::RuntimeException();
+ aChartLstnrCntnr.AddListener(aListener.get());
+}
+
+void SwXTextTable::removeChartDataChangeEventListener(
+ const uno::Reference< chart::XChartDataChangeEventListener > & aListener)
+ throw( uno::RuntimeException )
+{
+ if(!GetRegisteredIn() || !aChartLstnrCntnr.RemoveListener(aListener.get()))
+ throw uno::RuntimeException();
+}
+
+sal_Bool SwXTextTable::isNotANumber(double nNumber) throw( uno::RuntimeException )
+{
+ // We use DBL_MIN because starcalc does (which uses it because chart
+ // wants it that way!)
+ return ( nNumber == DBL_MIN );
+}
+
+double SwXTextTable::getNotANumber(void) throw( uno::RuntimeException )
+{
+ // We use DBL_MIN because starcalc does (which uses it because chart
+ // wants it that way!)
+ return DBL_MIN;
+}
+
+uno::Sequence< beans::PropertyValue > SwXTextTable::createSortDescriptor(void)
+ throw( uno::RuntimeException )
+{
+ SolarMutexGuard aGuard;
+
+ return SwUnoCursorHelper::CreateSortDescriptor(true);
+}
+
+void SwXTextTable::sort(const uno::Sequence< beans::PropertyValue >& rDescriptor)
+ throw( uno::RuntimeException )
+{
+ SolarMutexGuard aGuard;
+ SwSortOptions aSortOpt;
+ SwFrmFmt* pFmt = GetFrmFmt();
+ if(pFmt &&
+ SwUnoCursorHelper::ConvertSortProperties(rDescriptor, aSortOpt))
+ {
+ SwTable* pTable = SwTable::FindTable( pFmt );
+ SwSelBoxes aBoxes;
+ const SwTableSortBoxes& rTBoxes = pTable->GetTabSortBoxes();
+ for( sal_uInt16 n = 0; n < rTBoxes.Count(); ++n )
+ {
+ SwTableBox* pBox = rTBoxes[ n ];
+ aBoxes.Insert( pBox );
+ }
+ UnoActionContext aContext( pFmt->GetDoc() );
+ pFmt->GetDoc()->SortTbl(aBoxes, aSortOpt);
+ }
+}
+
+void SwXTextTable::autoFormat(const OUString& aName) throw( lang::IllegalArgumentException, uno::RuntimeException )
+{
+ SolarMutexGuard aGuard;
+ SwFrmFmt* pFmt = GetFrmFmt();
+ if(pFmt)
+ {
+ SwTable* pTable = SwTable::FindTable( pFmt );
+ if(!pTable->IsTblComplex())
+ {
+
+ String sAutoFmtName(aName);
+ SwTableAutoFmtTbl aAutoFmtTbl;
+ aAutoFmtTbl.Load();
+ for( sal_uInt16 i = aAutoFmtTbl.Count(); i; )
+ if( sAutoFmtName == aAutoFmtTbl[ --i ]->GetName() )
+ {
+ SwSelBoxes aBoxes;
+ const SwTableSortBoxes& rTBoxes = pTable->GetTabSortBoxes();
+ for( sal_uInt16 n = 0; n < rTBoxes.Count(); ++n )
+ {
+ SwTableBox* pBox = rTBoxes[ n ];
+ aBoxes.Insert( pBox );
+ }
+ UnoActionContext aContext( pFmt->GetDoc() );
+ pFmt->GetDoc()->SetTableAutoFmt( aBoxes, *aAutoFmtTbl[i] );
+ break;
+ }
+ }
+ }
+ else
+ throw uno::RuntimeException();
+}
+
+uno::Reference< beans::XPropertySetInfo > SwXTextTable::getPropertySetInfo(void) throw( uno::RuntimeException )
+{
+ static uno::Reference< beans::XPropertySetInfo > xRef = m_pPropSet->getPropertySetInfo();
+ return xRef;
+}
+
+void SwXTextTable::setPropertyValue(const OUString& rPropertyName,
+ const uno::Any& aValue)
+ throw( beans::UnknownPropertyException, beans::PropertyVetoException,
+ lang::IllegalArgumentException, lang::WrappedTargetException, uno::RuntimeException )
+{
+ SolarMutexGuard aGuard;
+ SwFrmFmt* pFmt = GetFrmFmt();
+ if(!aValue.hasValue())
+ throw lang::IllegalArgumentException();
+ const SfxItemPropertySimpleEntry* pEntry =
+ m_pPropSet->getPropertyMap()->getByName(rPropertyName);
+ if( !pEntry )
+ throw lang::IllegalArgumentException();
+ if(pFmt)
+ {
+ if ( pEntry->nFlags & beans::PropertyAttribute::READONLY)
+ throw beans::PropertyVetoException( OUString ( RTL_CONSTASCII_USTRINGPARAM ( "Property is read-only: " ) ) + rPropertyName, static_cast < cppu::OWeakObject * > ( this ) );
+
+ if(0xFF == pEntry->nMemberId)
+ {
+ lcl_SetSpecialProperty(pFmt, pEntry, aValue);
+ }
+ else
+ {
+ switch(pEntry->nWID)
+ {
+ case UNO_NAME_TABLE_NAME :
+ {
+ ::rtl::OUString sName;
+ aValue >>= sName;
+ setName( sName );
+ }
+ break;
+ case FN_UNO_RANGE_ROW_LABEL:
+ {
+ sal_Bool bTmp = *(sal_Bool*)aValue.getValue();
+ if(bFirstRowAsLabel != bTmp)
+ {
+ aChartLstnrCntnr.ChartDataChanged();
+ bFirstRowAsLabel = bTmp;
+ }
+ }
+ break;
+ case FN_UNO_RANGE_COL_LABEL:
+ {
+ sal_Bool bTmp = *(sal_Bool*)aValue.getValue();
+ if(bFirstColumnAsLabel != bTmp)
+ {
+ aChartLstnrCntnr.ChartDataChanged();
+ bFirstColumnAsLabel = bTmp;
+ }
+ }
+ break;
+ case FN_UNO_TABLE_BORDER:
+ {
+ const table::TableBorder* pBorder =
+ (const table::TableBorder* )aValue.getValue();
+ if(aValue.getValueType() == ::getCppuType((const table::TableBorder* )0)
+ && pBorder)
+ {
+ SwDoc* pDoc = pFmt->GetDoc();
+ SwFrm* pFrm = SwIterator<SwFrm,SwFmt>::FirstElement( *pFmt );
+ //Tabellen ohne Layout (unsichtbare Header/Footer )
+ if( pFrm )
+ {
+ lcl_FormatTable(pFmt);
+ SwTable* pTable = SwTable::FindTable( pFmt );
+ SwTableLines &rLines = pTable->GetTabLines();
+
+
+ // hier muessen die Actions aufgehoben werden
+ UnoActionRemoveContext aRemoveContext(pDoc);
+ const SwTableBox* pTLBox = lcl_FindCornerTableBox(rLines, true);
+ const SwStartNode* pSttNd = pTLBox->GetSttNd();
+ SwPosition aPos(*pSttNd);
+ // Cursor in die obere linke Zelle des Ranges setzen
+ SwUnoCrsr* pUnoCrsr = pDoc->CreateUnoCrsr(aPos, sal_True);
+ pUnoCrsr->Move( fnMoveForward, fnGoNode );
+ pUnoCrsr->SetRemainInSection( sal_False );
+
+
+
+ const SwTableBox* pBRBox = lcl_FindCornerTableBox(rLines, false);
+ pUnoCrsr->SetMark();
+ pUnoCrsr->GetPoint()->nNode = *pBRBox->GetSttNd();
+ pUnoCrsr->Move( fnMoveForward, fnGoNode );
+ SwUnoTableCrsr* pCrsr = dynamic_cast<SwUnoTableCrsr*>(pUnoCrsr);
+ pCrsr->MakeBoxSels();
+
+ SfxItemSet aSet(pDoc->GetAttrPool(),
+ RES_BOX, RES_BOX,
+ SID_ATTR_BORDER_INNER, SID_ATTR_BORDER_INNER,
+ 0);
+
+ SvxBoxItem aBox( RES_BOX );
+ SvxBoxInfoItem aBoxInfo( SID_ATTR_BORDER_INNER );
+ SvxBorderLine aLine;
+
+ sal_Bool bSet = lcl_LineToSvxLine(pBorder->TopLine, aLine);
+ aBox.SetLine(bSet ? &aLine : 0, BOX_LINE_TOP);
+ aBoxInfo.SetValid(VALID_TOP, pBorder->IsTopLineValid);
+
+ bSet = lcl_LineToSvxLine(pBorder->BottomLine, aLine);
+ aBox.SetLine(bSet ? &aLine : 0, BOX_LINE_BOTTOM);
+ aBoxInfo.SetValid(VALID_BOTTOM, pBorder->IsBottomLineValid);
+
+ bSet = lcl_LineToSvxLine(pBorder->LeftLine, aLine);
+ aBox.SetLine(bSet ? &aLine : 0, BOX_LINE_LEFT);
+ aBoxInfo.SetValid(VALID_LEFT, pBorder->IsLeftLineValid);
+
+ bSet = lcl_LineToSvxLine(pBorder->RightLine, aLine);
+ aBox.SetLine(bSet ? &aLine : 0, BOX_LINE_RIGHT);
+ aBoxInfo.SetValid(VALID_RIGHT, pBorder->IsRightLineValid);
+
+ bSet = lcl_LineToSvxLine(pBorder->HorizontalLine, aLine);
+ aBoxInfo.SetLine(bSet ? &aLine : 0, BOXINFO_LINE_HORI);
+ aBoxInfo.SetValid(VALID_HORI, pBorder->IsHorizontalLineValid);
+
+ bSet = lcl_LineToSvxLine(pBorder->VerticalLine, aLine);
+ aBoxInfo.SetLine(bSet ? &aLine : 0, BOXINFO_LINE_VERT);
+ aBoxInfo.SetValid(VALID_VERT, pBorder->IsVerticalLineValid);
+
+ aBox.SetDistance((sal_uInt16)MM100_TO_TWIP(pBorder->Distance));
+ aBoxInfo.SetValid(VALID_DISTANCE, pBorder->IsDistanceValid);
+
+ aSet.Put(aBox);
+ aSet.Put(aBoxInfo);
+
+ pDoc->SetTabBorders(*pCrsr, aSet);
+ delete pUnoCrsr;
+ }
+ }
+ }
+ break;
+ case FN_UNO_TABLE_BORDER_DISTANCES:
+ {
+ table::TableBorderDistances aTableBorderDistances;
+ if( !(aValue >>= aTableBorderDistances) ||
+ (!aTableBorderDistances.IsLeftDistanceValid &&
+ !aTableBorderDistances.IsRightDistanceValid &&
+ !aTableBorderDistances.IsTopDistanceValid &&
+ !aTableBorderDistances.IsBottomDistanceValid ))
+ break;
+
+ sal_uInt16 nLeftDistance = MM100_TO_TWIP_UNSIGNED( aTableBorderDistances.LeftDistance);
+ sal_uInt16 nRightDistance = MM100_TO_TWIP_UNSIGNED( aTableBorderDistances.RightDistance);
+ sal_uInt16 nTopDistance = MM100_TO_TWIP_UNSIGNED( aTableBorderDistances.TopDistance);
+ sal_uInt16 nBottomDistance = MM100_TO_TWIP_UNSIGNED( aTableBorderDistances.BottomDistance);
+ SwDoc* pDoc = pFmt->GetDoc();
+ SwTable* pTable = SwTable::FindTable( pFmt );
+ SwTableLines &rLines = pTable->GetTabLines();
+ pDoc->GetIDocumentUndoRedo().StartUndo(UNDO_START, NULL);
+ for(sal_uInt16 i = 0; i < rLines.Count(); i++)
+ {
+ SwTableLine* pLine = rLines.GetObject(i);
+ SwTableBoxes& rBoxes = pLine->GetTabBoxes();
+ for(sal_uInt16 k = 0; k < rBoxes.Count(); k++)
+ {
+ SwTableBox* pBox = rBoxes.GetObject(k);
+ const SwFrmFmt* pBoxFmt = pBox->GetFrmFmt();
+ const SvxBoxItem& rBox = pBoxFmt->GetBox();
+ if(
+ (aTableBorderDistances.IsLeftDistanceValid && nLeftDistance != rBox.GetDistance( BOX_LINE_LEFT )) ||
+ (aTableBorderDistances.IsRightDistanceValid && nRightDistance != rBox.GetDistance( BOX_LINE_RIGHT )) ||
+ (aTableBorderDistances.IsTopDistanceValid && nTopDistance != rBox.GetDistance( BOX_LINE_TOP )) ||
+ (aTableBorderDistances.IsBottomDistanceValid && nBottomDistance != rBox.GetDistance( BOX_LINE_BOTTOM )))
+ {
+ SvxBoxItem aSetBox( rBox );
+ SwFrmFmt* pSetBoxFmt = pBox->ClaimFrmFmt();
+ if( aTableBorderDistances.IsLeftDistanceValid )
+ aSetBox.SetDistance( nLeftDistance, BOX_LINE_LEFT );
+ if( aTableBorderDistances.IsRightDistanceValid )
+ aSetBox.SetDistance( nRightDistance, BOX_LINE_RIGHT );
+ if( aTableBorderDistances.IsTopDistanceValid )
+ aSetBox.SetDistance( nTopDistance, BOX_LINE_TOP );
+ if( aTableBorderDistances.IsBottomDistanceValid )
+ aSetBox.SetDistance( nBottomDistance, BOX_LINE_BOTTOM );
+ pDoc->SetAttr( aSetBox, *pSetBoxFmt );
+ }
+ }
+ }
+ pDoc->GetIDocumentUndoRedo().EndUndo(UNDO_END, NULL);
+ }
+ break;
+ case FN_UNO_TABLE_COLUMN_SEPARATORS:
+ {
+ UnoActionContext aContext(pFmt->GetDoc());
+ SwTable* pTable = SwTable::FindTable( pFmt );
+ lcl_SetTblSeparators(aValue, pTable, pTable->GetTabLines()[0]->GetTabBoxes()[0], sal_False, pFmt->GetDoc());
+ }
+ break;
+ case FN_UNO_TABLE_COLUMN_RELATIVE_SUM:/*_readonly_*/ break;
+ default:
+ {
+ SwAttrSet aSet(pFmt->GetAttrSet());
+ m_pPropSet->setPropertyValue(*pEntry, aValue, aSet);
+ pFmt->GetDoc()->SetAttr(aSet, *pFmt);
+ }
+ }
+ }
+ }
+ else if(bIsDescriptor)
+ {
+ String aPropertyName(rPropertyName);
+ pTableProps->SetProperty( pEntry->nWID, pEntry->nMemberId, aValue);
+ }
+ else
+ throw uno::RuntimeException();
+}
+
+uno::Any SwXTextTable::getPropertyValue(const OUString& rPropertyName) throw( beans::UnknownPropertyException, lang::WrappedTargetException, uno::RuntimeException )
+{
+ SolarMutexGuard aGuard;
+ uno::Any aRet;
+ SwFrmFmt* pFmt = GetFrmFmt();
+ const SfxItemPropertySimpleEntry* pEntry =
+ m_pPropSet->getPropertyMap()->getByName(rPropertyName);
+ if(pFmt)
+ {
+ if (!pEntry)
+ throw beans::UnknownPropertyException(OUString ( RTL_CONSTASCII_USTRINGPARAM ( "Unknown property: " ) ) + rPropertyName, static_cast < cppu::OWeakObject * > ( this ) );
+
+ if(0xFF == pEntry->nMemberId)
+ {
+ aRet = lcl_GetSpecialProperty(pFmt, pEntry );
+ }
+ else
+ {
+ switch(pEntry->nWID)
+ {
+ case UNO_NAME_TABLE_NAME:
+ {
+ aRet <<= getName();
+ }
+ break;
+ case FN_UNO_ANCHOR_TYPES:
+ case FN_UNO_TEXT_WRAP:
+ case FN_UNO_ANCHOR_TYPE:
+ ::sw::GetDefaultTextContentValue(
+ aRet, OUString(), pEntry->nWID);
+ break;
+ case FN_UNO_RANGE_ROW_LABEL:
+ {
+ sal_Bool bTemp = bFirstRowAsLabel;
+ aRet.setValue(&bTemp, ::getCppuBooleanType());
+ }
+ break;
+ case FN_UNO_RANGE_COL_LABEL:
+ {
+ sal_Bool bTemp = bFirstColumnAsLabel;
+ aRet.setValue(&bTemp, ::getCppuBooleanType());
+ }
+ break;
+ case FN_UNO_TABLE_BORDER:
+ {
+ SwDoc* pDoc = pFmt->GetDoc();
+ SwFrm* pFrm = SwIterator<SwFrm,SwFmt>::FirstElement( *pFmt );
+ //Tabellen ohne Layout (unsichtbare Header/Footer )
+ if( pFrm )
+ {
+ lcl_FormatTable(pFmt);
+ SwTable* pTable = SwTable::FindTable( pFmt );
+ SwTableLines &rLines = pTable->GetTabLines();
+
+ // hier muessen die Actions aufgehoben werden
+ UnoActionRemoveContext aRemoveContext(pDoc);
+ const SwTableBox* pTLBox = lcl_FindCornerTableBox(rLines, true);
+ const SwStartNode* pSttNd = pTLBox->GetSttNd();
+ SwPosition aPos(*pSttNd);
+ // Cursor in die obere linke Zelle des Ranges setzen
+ SwUnoCrsr* pUnoCrsr = pDoc->CreateUnoCrsr(aPos, sal_True);
+ pUnoCrsr->Move( fnMoveForward, fnGoNode );
+ pUnoCrsr->SetRemainInSection( sal_False );
+
+ const SwTableBox* pBRBox = lcl_FindCornerTableBox(rLines, false);
+ pUnoCrsr->SetMark();
+ const SwStartNode* pLastNd = pBRBox->GetSttNd();
+ pUnoCrsr->GetPoint()->nNode = *pLastNd;
+
+ pUnoCrsr->Move( fnMoveForward, fnGoNode );
+ SwUnoTableCrsr* pCrsr = dynamic_cast<SwUnoTableCrsr*>(pUnoCrsr);
+ pCrsr->MakeBoxSels();
+
+ SfxItemSet aSet(pDoc->GetAttrPool(),
+ RES_BOX, RES_BOX,
+ SID_ATTR_BORDER_INNER, SID_ATTR_BORDER_INNER,
+ 0);
+ aSet.Put(SvxBoxInfoItem( SID_ATTR_BORDER_INNER ));
+ pDoc->GetTabBorders(*pCrsr, aSet);
+ const SvxBoxInfoItem& rBoxInfoItem = (const SvxBoxInfoItem&)aSet.Get(SID_ATTR_BORDER_INNER);
+ const SvxBoxItem& rBox = (const SvxBoxItem&)aSet.Get(RES_BOX);
+
+ table::TableBorder aTableBorder;
+ aTableBorder.TopLine = lcl_SvxLineToLine(rBox.GetTop());
+ aTableBorder.IsTopLineValid = rBoxInfoItem.IsValid(VALID_TOP);
+ aTableBorder.BottomLine = lcl_SvxLineToLine(rBox.GetBottom());
+ aTableBorder.IsBottomLineValid = rBoxInfoItem.IsValid(VALID_BOTTOM);
+ aTableBorder.LeftLine = lcl_SvxLineToLine(rBox.GetLeft());
+ aTableBorder.IsLeftLineValid = rBoxInfoItem.IsValid(VALID_LEFT);
+ aTableBorder.RightLine = lcl_SvxLineToLine(rBox.GetRight());
+ aTableBorder.IsRightLineValid = rBoxInfoItem.IsValid(VALID_RIGHT );
+ aTableBorder.HorizontalLine = lcl_SvxLineToLine(rBoxInfoItem.GetHori());
+ aTableBorder.IsHorizontalLineValid = rBoxInfoItem.IsValid(VALID_HORI);
+ aTableBorder.VerticalLine = lcl_SvxLineToLine(rBoxInfoItem.GetVert());
+ aTableBorder.IsVerticalLineValid = rBoxInfoItem.IsValid(VALID_VERT);
+ aTableBorder.Distance = TWIP_TO_MM100_UNSIGNED( rBox.GetDistance() );
+ aTableBorder.IsDistanceValid = rBoxInfoItem.IsValid(VALID_DISTANCE);
+ aRet.setValue(&aTableBorder, ::getCppuType((const table::TableBorder*)0));
+ delete pUnoCrsr;
+ }
+ }
+ break;
+ case FN_UNO_TABLE_BORDER_DISTANCES :
+ {
+ table::TableBorderDistances aTableBorderDistances( 0, sal_True, 0, sal_True, 0, sal_True, 0, sal_True ) ;
+ SwTable* pTable = SwTable::FindTable( pFmt );
+ const SwTableLines &rLines = pTable->GetTabLines();
+ bool bFirst = true;
+ sal_uInt16 nLeftDistance = 0;
+ sal_uInt16 nRightDistance = 0;
+ sal_uInt16 nTopDistance = 0;
+ sal_uInt16 nBottomDistance = 0;
+
+ for(sal_uInt16 i = 0; i < rLines.Count(); i++)
+ {
+ const SwTableLine* pLine = rLines.GetObject(i);
+ const SwTableBoxes& rBoxes = pLine->GetTabBoxes();
+ for(sal_uInt16 k = 0; k < rBoxes.Count(); k++)
+ {
+ const SwTableBox* pBox = rBoxes.GetObject(k);
+ SwFrmFmt* pBoxFmt = pBox->GetFrmFmt();
+ const SvxBoxItem& rBox = pBoxFmt->GetBox();
+ if( bFirst )
+ {
+ nLeftDistance = TWIP_TO_MM100_UNSIGNED( rBox.GetDistance( BOX_LINE_LEFT ));
+ nRightDistance = TWIP_TO_MM100_UNSIGNED( rBox.GetDistance( BOX_LINE_RIGHT ));
+ nTopDistance = TWIP_TO_MM100_UNSIGNED( rBox.GetDistance( BOX_LINE_TOP ));
+ nBottomDistance = TWIP_TO_MM100_UNSIGNED( rBox.GetDistance( BOX_LINE_BOTTOM ));
+ bFirst = false;
+ }
+ else
+ {
+ if( aTableBorderDistances.IsLeftDistanceValid &&
+ nLeftDistance != TWIP_TO_MM100_UNSIGNED( rBox.GetDistance( BOX_LINE_LEFT )))
+ aTableBorderDistances.IsLeftDistanceValid = sal_False;
+ if( aTableBorderDistances.IsRightDistanceValid &&
+ nRightDistance != TWIP_TO_MM100_UNSIGNED( rBox.GetDistance( BOX_LINE_RIGHT )))
+ aTableBorderDistances.IsRightDistanceValid = sal_False;
+ if( aTableBorderDistances.IsTopDistanceValid &&
+ nTopDistance != TWIP_TO_MM100_UNSIGNED( rBox.GetDistance( BOX_LINE_TOP )))
+ aTableBorderDistances.IsTopDistanceValid = sal_False;
+ if( aTableBorderDistances.IsBottomDistanceValid &&
+ nBottomDistance != TWIP_TO_MM100_UNSIGNED( rBox.GetDistance( BOX_LINE_BOTTOM )))
+ aTableBorderDistances.IsBottomDistanceValid = sal_False;
+ }
+
+ }
+ if( !aTableBorderDistances.IsLeftDistanceValid &&
+ !aTableBorderDistances.IsRightDistanceValid &&
+ !aTableBorderDistances.IsTopDistanceValid &&
+ !aTableBorderDistances.IsBottomDistanceValid )
+ break;
+ }
+ if( aTableBorderDistances.IsLeftDistanceValid)
+ aTableBorderDistances.LeftDistance = nLeftDistance;
+ if( aTableBorderDistances.IsRightDistanceValid)
+ aTableBorderDistances.RightDistance = nRightDistance;
+ if( aTableBorderDistances.IsTopDistanceValid)
+ aTableBorderDistances.TopDistance = nTopDistance;
+ if( aTableBorderDistances.IsBottomDistanceValid)
+ aTableBorderDistances.BottomDistance = nBottomDistance;
+
+ aRet <<= aTableBorderDistances;
+ }
+ break;
+ case FN_UNO_TABLE_COLUMN_SEPARATORS:
+ {
+ SwTable* pTable = SwTable::FindTable( pFmt );
+ lcl_GetTblSeparators(aRet, pTable, pTable->GetTabLines()[0]->GetTabBoxes()[0], sal_False);
+ }
+ break;
+ case FN_UNO_TABLE_COLUMN_RELATIVE_SUM:
+ aRet <<= (sal_Int16) UNO_TABLE_COLUMN_SUM;
+ break;
+ case RES_ANCHOR:
+ //AnchorType ist readonly und maybevoid und wird nicht geliefert
+ break;
+ case FN_UNO_TEXT_SECTION:
+ {
+ SwTable* pTable = SwTable::FindTable( pFmt );
+ SwTableNode* pTblNode = pTable->GetTableNode();
+ SwSectionNode* pSectionNode = pTblNode->FindSectionNode();
+ if(pSectionNode)
+ {
+ const SwSection& rSect = pSectionNode->GetSection();
+ uno::Reference< text::XTextSection > xSect =
+ SwXTextSections::GetObject( *rSect.GetFmt() );
+ aRet <<= xSect;
+ }
+ }
+ break;
+ default:
+ {
+ const SwAttrSet& rSet = pFmt->GetAttrSet();
+ m_pPropSet->getPropertyValue(*pEntry, rSet, aRet);
+ }
+ }
+ }
+ }
+ else if(bIsDescriptor)
+ {
+ const uno::Any* pAny = 0;
+ String aPropertyName(rPropertyName);
+ if(!pTableProps->GetProperty(pEntry->nWID, pEntry->nMemberId, pAny))
+ throw lang::IllegalArgumentException();
+ else if(pAny)
+ aRet = *pAny;
+ }
+ else
+ throw uno::RuntimeException();
+ return aRet;
+}
+
+void SwXTextTable::addPropertyChangeListener(const OUString& /*rPropertyName*/, const uno::Reference< beans::XPropertyChangeListener > & /*xListener*/) throw( beans::UnknownPropertyException, lang::WrappedTargetException, uno::RuntimeException )
+{
+ DBG_WARNING("not implemented");
+}
+
+void SwXTextTable::removePropertyChangeListener(const OUString& /*rPropertyName*/, const uno::Reference< beans::XPropertyChangeListener > & /*xListener*/) throw( beans::UnknownPropertyException, lang::WrappedTargetException, uno::RuntimeException )
+{
+ DBG_WARNING("not implemented");
+}
+
+void SwXTextTable::addVetoableChangeListener(const OUString& /*rPropertyName*/, const uno::Reference< beans::XVetoableChangeListener > & /*xListener*/) throw( beans::UnknownPropertyException, lang::WrappedTargetException, uno::RuntimeException )
+{
+ DBG_WARNING("not implemented");
+}
+
+void SwXTextTable::removeVetoableChangeListener(const OUString& /*rPropertyName*/, const uno::Reference< beans::XVetoableChangeListener > & /*xListener*/) throw( beans::UnknownPropertyException, lang::WrappedTargetException, uno::RuntimeException )
+{
+ DBG_WARNING("not implemented");
+}
+
+OUString SwXTextTable::getName(void) throw( uno::RuntimeException )
+{
+ SolarMutexGuard aGuard;
+ String sRet;
+ SwFrmFmt* pFmt = GetFrmFmt();
+ if(!pFmt && !bIsDescriptor)
+ throw uno::RuntimeException();
+ if(pFmt)
+ {
+ sRet = pFmt->GetName();
+ }
+ else
+ sRet = m_sTableName;
+ return sRet;
+}
+
+void SwXTextTable::setName(const OUString& rName) throw( uno::RuntimeException )
+{
+ SolarMutexGuard aGuard;
+ SwFrmFmt* pFmt = GetFrmFmt();
+ String sNewTblName(rName);
+ if((!pFmt && !bIsDescriptor) ||
+ !sNewTblName.Len() ||
+ STRING_NOTFOUND != sNewTblName.Search('.') ||
+ STRING_NOTFOUND != sNewTblName.Search(' ') )
+ throw uno::RuntimeException();
+
+ if(pFmt)
+ {
+ const String aOldName( pFmt->GetName() );
+ sal_Bool bNameFound = sal_False;
+ SwFrmFmt* pTmpFmt;
+ const SwFrmFmts* pTbl = pFmt->GetDoc()->GetTblFrmFmts();
+ for( sal_uInt16 i = pTbl->Count(); i; )
+ if( !( pTmpFmt = (*pTbl)[ --i ] )->IsDefault() &&
+ pTmpFmt->GetName() == sNewTblName &&
+ pFmt->GetDoc()->IsUsed( *pTmpFmt ))
+ {
+ bNameFound = sal_True;
+ break;
+ }
+
+ if(bNameFound)
+ {
+ throw uno::RuntimeException();
+ }
+ pFmt->SetName( sNewTblName );
+
+
+ SwStartNode *pStNd;
+ SwNodeIndex aIdx( *pFmt->GetDoc()->GetNodes().GetEndOfAutotext().StartOfSectionNode(), 1 );
+ while ( 0 != (pStNd = aIdx.GetNode().GetStartNode()) )
+ {
+ aIdx++;
+ SwNode *const pNd = & aIdx.GetNode();
+ if ( pNd->IsOLENode() &&
+ aOldName == ((SwOLENode*)pNd)->GetChartTblName() )
+ {
+ ((SwOLENode*)pNd)->SetChartTblName( sNewTblName );
+
+ ((SwOLENode*)pNd)->GetOLEObj();
+
+ SwTable* pTable = SwTable::FindTable( pFmt );
+ //TL_CHART2: chart needs to be notfied about name changes
+ pFmt->GetDoc()->UpdateCharts( pTable->GetFrmFmt()->GetName() );
+ }
+ aIdx.Assign( *pStNd->EndOfSectionNode(), + 1 );
+ }
+ pFmt->GetDoc()->SetModified();
+ }
+ else
+ m_sTableName = sNewTblName;
+}
+
+sal_uInt16 SwXTextTable::getRowCount(void)
+{
+ SolarMutexGuard aGuard;
+ sal_Int16 nRet = 0;
+ SwFrmFmt* pFmt = GetFrmFmt();
+ if(pFmt)
+ {
+ SwTable* pTable = SwTable::FindTable( pFmt );
+ if(!pTable->IsTblComplex())
+ {
+ nRet = pTable->GetTabLines().Count();
+ }
+ }
+ return nRet;
+}
+
+sal_uInt16 SwXTextTable::getColumnCount(void)
+{
+ SolarMutexGuard aGuard;
+ SwFrmFmt* pFmt = GetFrmFmt();
+ sal_Int16 nRet = 0;
+ if(pFmt)
+ {
+ SwTable* pTable = SwTable::FindTable( pFmt );
+ if(!pTable->IsTblComplex())
+ {
+ SwTableLines& rLines = pTable->GetTabLines();
+ SwTableLine* pLine = rLines.GetObject(0);
+ nRet = pLine->GetTabBoxes().Count();
+ }
+ }
+ return nRet;
+}
+
+void SwXTextTable::Modify( const SfxPoolItem* pOld, const SfxPoolItem *pNew)
+{
+ if(pOld && pOld->Which() == RES_REMOVE_UNO_OBJECT &&
+ (void*)GetRegisteredIn() == ((SwPtrMsgPoolItem *)pOld)->pObject )
+ ((SwModify*)GetRegisteredIn())->Remove(this);
+ else
+ ClientModify(this, pOld, pNew);
+ if(!GetRegisteredIn())
+ {
+ aLstnrCntnr.Disposing();
+ aChartLstnrCntnr.Disposing();
+ }
+ else
+ aChartLstnrCntnr.ChartDataChanged();
+}
+
+OUString SAL_CALL SwXTextTable::getImplementationName(void) throw( uno::RuntimeException )
+{
+ return C2U("SwXTextTable");
+}
+
+sal_Bool SwXTextTable::supportsService(const OUString& rServiceName) throw( uno::RuntimeException )
+{
+ String sServiceName(rServiceName);
+ return (sServiceName.EqualsAscii("com.sun.star.document.LinkTarget") ||
+ sServiceName.EqualsAscii("com.sun.star.text.TextTable") ||
+ sServiceName.EqualsAscii("com.sun.star.text.TextContent") ||
+ sServiceName.EqualsAscii("com.sun.star.text.TextSortable"));
+}
+
+uno::Sequence< OUString > SwXTextTable::getSupportedServiceNames(void) throw( uno::RuntimeException )
+{
+ uno::Sequence< OUString > aRet(4);
+ OUString* pArr = aRet.getArray();
+ pArr[0] = C2U("com.sun.star.document.LinkTarget");
+ pArr[1] = C2U("com.sun.star.text.TextTable");
+ pArr[2] = C2U("com.sun.star.text.TextContent");
+ pArr[2] = C2U("com.sun.star.text.TextSortable");
+ return aRet;
+}
+
+const uno::Sequence< sal_Int8 > & SwXCellRange::getUnoTunnelId()
+{
+ static uno::Sequence< sal_Int8 > aSeq = ::CreateUnoTunnelId();
+ return aSeq;
+}
+
+sal_Int64 SAL_CALL SwXCellRange::getSomething( const uno::Sequence< sal_Int8 >& rId )
+ throw(uno::RuntimeException)
+{
+ if( rId.getLength() == 16
+ && 0 == rtl_compareMemory( getUnoTunnelId().getConstArray(),
+ rId.getConstArray(), 16 ) )
+ {
+ return sal::static_int_cast< sal_Int64 >( reinterpret_cast< sal_IntPtr >(this) );
+ }
+ return 0;
+}
+
+TYPEINIT1(SwXCellRange, SwClient);
+
+OUString SwXCellRange::getImplementationName(void) throw( uno::RuntimeException )
+{
+ return C2U("SwXCellRange");
+}
+
+sal_Bool SwXCellRange::supportsService(const OUString& rServiceName) throw( uno::RuntimeException )
+{
+ return
+ rServiceName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM ( "com.sun.star.text.CellRange" ) ) ||
+ rServiceName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM ( "com.sun.star.style.CharacterProperties" ) ) ||
+ rServiceName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM ( "com.sun.star.style.CharacterPropertiesAsian" ) ) ||
+ rServiceName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM ( "com.sun.star.style.CharacterPropertiesComplex") ) ||
+ rServiceName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM ( "com.sun.star.style.ParagraphProperties" ) ) ||
+ rServiceName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM ( "com.sun.star.style.ParagraphPropertiesAsian" ) ) ||
+ rServiceName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM ( "com.sun.star.style.ParagraphPropertiesComplex" ) );
+}
+
+uno::Sequence< OUString > SwXCellRange::getSupportedServiceNames(void) throw( uno::RuntimeException )
+{
+ uno::Sequence< OUString > aRet(7);
+ OUString* pArray = aRet.getArray();
+ pArray[0] = C2U("com.sun.star.text.CellRange");
+ pArray[1] = C2U("com.sun.star.style.CharacterProperties");
+ pArray[2] = C2U("com.sun.star.style.CharacterPropertiesAsian");
+ pArray[3] = C2U("com.sun.star.style.CharacterPropertiesComplex");
+ pArray[4] = C2U("com.sun.star.style.ParagraphProperties");
+ pArray[5] = C2U("com.sun.star.style.ParagraphPropertiesAsian");
+ pArray[6] = C2U("com.sun.star.style.ParagraphPropertiesComplex");
+ return aRet;
+}
+
+SwXCellRange::SwXCellRange(SwUnoCrsr* pCrsr, SwFrmFmt& rFrmFmt,
+ SwRangeDescriptor& rDesc)
+ :
+ SwClient(&rFrmFmt),
+ aCursorDepend(this, pCrsr),
+ aChartLstnrCntnr((cppu::OWeakObject*)this),
+ aRgDesc(rDesc),
+ m_pPropSet(aSwMapProvider.GetPropertySet(PROPERTY_MAP_TABLE_RANGE)),
+ pTblCrsr(pCrsr),
+ bFirstRowAsLabel(sal_False),
+ bFirstColumnAsLabel(sal_False)
+{
+ aRgDesc.Normalize();
+}
+
+SwXCellRange::~SwXCellRange()
+{
+ SolarMutexGuard aGuard;
+ delete pTblCrsr;
+}
+
+uno::Reference< table::XCell > SwXCellRange::getCellByPosition(sal_Int32 nColumn, sal_Int32 nRow)
+ throw( uno::RuntimeException, lang::IndexOutOfBoundsException )
+{
+ SolarMutexGuard aGuard;
+ uno::Reference< table::XCell > aRet;
+ SwFrmFmt* pFmt = GetFrmFmt();
+ if(pFmt)
+ {
+ if(nColumn >= 0 && nRow >= 0 &&
+ getColumnCount() > nColumn && getRowCount() > nRow )
+ {
+ SwXCell* pXCell = lcl_CreateXCell(pFmt,
+ aRgDesc.nLeft + nColumn, aRgDesc.nTop + nRow);
+ if(pXCell)
+ aRet = pXCell;
+ }
+ }
+ if(!aRet.is())
+ throw lang::IndexOutOfBoundsException();
+ return aRet;
+}
+
+uno::Reference< table::XCellRange > SwXCellRange::getCellRangeByPosition(
+ sal_Int32 nLeft, sal_Int32 nTop, sal_Int32 nRight, sal_Int32 nBottom)
+ throw( uno::RuntimeException, lang::IndexOutOfBoundsException )
+{
+ SolarMutexGuard aGuard;
+ uno::Reference< table::XCellRange > aRet;
+ SwFrmFmt* pFmt = GetFrmFmt();
+ if(pFmt && getColumnCount() > nRight && getRowCount() > nBottom &&
+ nLeft <= nRight && nTop <= nBottom
+ && nLeft >= 0 && nRight >= 0 && nTop >= 0 && nBottom >= 0 )
+ {
+ SwTable* pTable = SwTable::FindTable( pFmt );
+ if(!pTable->IsTblComplex())
+ {
+ SwRangeDescriptor aNewDesc;
+ aNewDesc.nTop = nTop + aRgDesc.nTop;
+ aNewDesc.nBottom = nBottom + aRgDesc.nTop;
+ aNewDesc.nLeft = nLeft + aRgDesc.nLeft;
+ aNewDesc.nRight = nRight + aRgDesc.nLeft;
+ aNewDesc.Normalize();
+ String sTLName = lcl_GetCellName(aNewDesc.nLeft, aNewDesc.nTop);
+ String sBRName = lcl_GetCellName(aNewDesc.nRight, aNewDesc.nBottom);
+ const SwTableBox* pTLBox = pTable->GetTblBox( sTLName );
+ if(pTLBox)
+ {
+ // hier muessen die Actions aufgehoben
+ UnoActionRemoveContext aRemoveContext(pFmt->GetDoc());
+ const SwStartNode* pSttNd = pTLBox->GetSttNd();
+ SwPosition aPos(*pSttNd);
+ // Cursor in die obere linke Zelle des Ranges setzen
+ SwUnoCrsr* pUnoCrsr = pFmt->GetDoc()->CreateUnoCrsr(aPos, sal_True);
+ pUnoCrsr->Move( fnMoveForward, fnGoNode );
+ pUnoCrsr->SetRemainInSection( sal_False );
+ const SwTableBox* pBRBox = pTable->GetTblBox( sBRName );
+ if(pBRBox)
+ {
+ pUnoCrsr->SetMark();
+ pUnoCrsr->GetPoint()->nNode = *pBRBox->GetSttNd();
+ pUnoCrsr->Move( fnMoveForward, fnGoNode );
+ SwUnoTableCrsr* pCrsr = dynamic_cast<SwUnoTableCrsr*>(pUnoCrsr);
+ pCrsr->MakeBoxSels();
+ // pUnoCrsr wird uebergeben und nicht geloescht
+ SwXCellRange* pCellRange = new SwXCellRange(pUnoCrsr, *pFmt, aNewDesc);
+ aRet = pCellRange;
+ }
+ else
+ delete pUnoCrsr;
+ }
+ }
+ }
+ if(!aRet.is())
+ throw lang::IndexOutOfBoundsException();
+ return aRet;
+
+}
+
+uno::Reference< table::XCellRange > SwXCellRange::getCellRangeByName(const OUString& rRange)
+ throw( uno::RuntimeException )
+{
+ SolarMutexGuard aGuard;
+ String sRange(rRange);
+ String sTLName(sRange.GetToken(0, ':'));
+ String sBRName(sRange.GetToken(1, ':'));
+ if(!sTLName.Len() || !sBRName.Len())
+ throw uno::RuntimeException();
+ SwRangeDescriptor aDesc;
+ aDesc.nTop = aDesc.nLeft = aDesc.nBottom = aDesc.nRight = -1;
+ lcl_GetCellPosition( sTLName, aDesc.nLeft, aDesc.nTop );
+ lcl_GetCellPosition( sBRName, aDesc.nRight, aDesc.nBottom );
+ aDesc.Normalize();
+ return getCellRangeByPosition(aDesc.nLeft - aRgDesc.nLeft, aDesc.nTop - aRgDesc.nTop,
+ aDesc.nRight - aRgDesc.nLeft, aDesc.nBottom - aRgDesc.nTop);
+}
+
+uno::Reference< beans::XPropertySetInfo > SwXCellRange::getPropertySetInfo(void) throw( uno::RuntimeException )
+{
+ static uno::Reference< beans::XPropertySetInfo > xRef = m_pPropSet->getPropertySetInfo();
+ return xRef;
+}
+
+void SwXCellRange::setPropertyValue(const OUString& rPropertyName,
+ const uno::Any& aValue) throw( beans::UnknownPropertyException,
+ beans::PropertyVetoException, lang::IllegalArgumentException,
+ lang::WrappedTargetException, uno::RuntimeException )
+{
+ SolarMutexGuard aGuard;
+ SwFrmFmt* pFmt = GetFrmFmt();
+ if(pFmt)
+ {
+ /* ASK OLIVER
+ lcl_FormatTable(pFmt);*/
+ const SfxItemPropertySimpleEntry* pEntry =
+ m_pPropSet->getPropertyMap()->getByName(rPropertyName);
+ if(pEntry)
+ {
+ if ( pEntry->nFlags & beans::PropertyAttribute::READONLY)
+ throw beans::PropertyVetoException( OUString ( RTL_CONSTASCII_USTRINGPARAM ( "Property is read-only: " ) ) + rPropertyName, static_cast < cppu::OWeakObject * > ( this ) );
+
+ SwDoc* pDoc = pTblCrsr->GetDoc();
+ {
+ // remove actions to enable box selection
+ UnoActionRemoveContext aRemoveContext(pDoc);
+ }
+ SwUnoTableCrsr* pCrsr = dynamic_cast<SwUnoTableCrsr*>(pTblCrsr);
+ pCrsr->MakeBoxSels();
+ switch(pEntry->nWID )
+ {
+ case FN_UNO_TABLE_CELL_BACKGROUND:
+ {
+ SvxBrushItem aBrush( RES_BACKGROUND );
+ pDoc->GetBoxAttr( *pTblCrsr, aBrush );
+ ((SfxPoolItem&)aBrush).PutValue(aValue, pEntry->nMemberId);
+ pDoc->SetBoxAttr( *pTblCrsr, aBrush );
+
+ }
+ break;
+ case RES_BOX :
+ {
+ SfxItemSet aSet(pDoc->GetAttrPool(),
+ RES_BOX, RES_BOX,
+ SID_ATTR_BORDER_INNER, SID_ATTR_BORDER_INNER,
+ 0);
+ SvxBoxInfoItem aBoxInfo( SID_ATTR_BORDER_INNER );
+ aBoxInfo.SetValid(0xff, sal_False);
+ sal_uInt8 nValid = 0;
+ switch(pEntry->nMemberId & ~CONVERT_TWIPS)
+ {
+ case LEFT_BORDER : nValid = VALID_LEFT; break;
+ case RIGHT_BORDER: nValid = VALID_RIGHT; break;
+ case TOP_BORDER : nValid = VALID_TOP; break;
+ case BOTTOM_BORDER: nValid = VALID_BOTTOM; break;
+ case LEFT_BORDER_DISTANCE :
+ case RIGHT_BORDER_DISTANCE:
+ case TOP_BORDER_DISTANCE :
+ case BOTTOM_BORDER_DISTANCE:
+ nValid = VALID_DISTANCE;
+ break;
+ }
+ aBoxInfo.SetValid(nValid, sal_True);
+
+
+ aSet.Put(aBoxInfo);
+ pDoc->GetTabBorders(*pCrsr, aSet);
+
+ aSet.Put(aBoxInfo);
+ SvxBoxItem aBoxItem((const SvxBoxItem&)aSet.Get(RES_BOX));
+ ((SfxPoolItem&)aBoxItem).PutValue(aValue, pEntry->nMemberId);
+ aSet.Put(aBoxItem);
+ pDoc->SetTabBorders( *pTblCrsr, aSet );
+ }
+ break;
+ case RES_BOXATR_FORMAT:
+ {
+ SfxUInt32Item aNumberFormat(RES_BOXATR_FORMAT);
+ ((SfxPoolItem&)aNumberFormat).PutValue(aValue, 0);
+ pDoc->SetBoxAttr( *pCrsr, aNumberFormat);
+ }
+ break;
+ case RES_VERT_ORIENT:
+ {
+ sal_Int16 nAlign = -1;
+ aValue >>= nAlign;
+ if( nAlign >= text::VertOrientation::NONE && nAlign <= text::VertOrientation::BOTTOM)
+ pDoc->SetBoxAlign( *pCrsr, nAlign );
+ }
+ break;
+ case FN_UNO_RANGE_ROW_LABEL:
+ {
+ sal_Bool bTmp = *(sal_Bool*)aValue.getValue();
+ if(bFirstRowAsLabel != bTmp)
+ {
+ aChartLstnrCntnr.ChartDataChanged();
+ bFirstRowAsLabel = bTmp;
+ }
+ }
+ break;
+ case FN_UNO_RANGE_COL_LABEL:
+ {
+ sal_Bool bTmp = *(sal_Bool*)aValue.getValue();
+ if(bFirstColumnAsLabel != bTmp)
+ {
+ aChartLstnrCntnr.ChartDataChanged();
+ bFirstColumnAsLabel = bTmp;
+ }
+ }
+ break;
+ default:
+ {
+ SfxItemSet aItemSet( pDoc->GetAttrPool(), pEntry->nWID, pEntry->nWID );
+ SwUnoCursorHelper::GetCrsrAttr(pCrsr->GetSelRing(),
+ aItemSet);
+
+ if (!SwUnoCursorHelper::SetCursorPropertyValue(
+ *pEntry, aValue, pCrsr->GetSelRing(), aItemSet))
+ {
+ m_pPropSet->setPropertyValue(*pEntry, aValue, aItemSet);
+ }
+ SwUnoCursorHelper::SetCrsrAttr(pCrsr->GetSelRing(),
+ aItemSet, nsSetAttrMode::SETATTR_DEFAULT, true);
+ }
+ }
+ }
+ else
+ throw beans::UnknownPropertyException(OUString ( RTL_CONSTASCII_USTRINGPARAM ( "Unknown property: " ) ) + rPropertyName, static_cast < cppu::OWeakObject * > ( this ) );
+ }
+}
+
+uno::Any SwXCellRange::getPropertyValue(const OUString& rPropertyName) throw( beans::UnknownPropertyException, lang::WrappedTargetException, uno::RuntimeException )
+{
+ SolarMutexGuard aGuard;
+ uno::Any aRet;
+ SwFrmFmt* pFmt = GetFrmFmt();
+ if(pFmt)
+ {
+ /* ASK OLIVER
+ lcl_FormatTable(pFmt);*/
+ const SfxItemPropertySimpleEntry* pEntry =
+ m_pPropSet->getPropertyMap()->getByName(rPropertyName);
+ if(pEntry)
+ {
+ switch(pEntry->nWID )
+ {
+ case FN_UNO_TABLE_CELL_BACKGROUND:
+ {
+ SvxBrushItem aBrush( RES_BACKGROUND );
+ if(pTblCrsr->GetDoc()->GetBoxAttr( *pTblCrsr, aBrush ))
+ aBrush.QueryValue(aRet, pEntry->nMemberId);
+
+ }
+ break;
+ case RES_BOX :
+ {
+ SwDoc* pDoc = pTblCrsr->GetDoc();
+ SfxItemSet aSet(pDoc->GetAttrPool(),
+ RES_BOX, RES_BOX,
+ SID_ATTR_BORDER_INNER, SID_ATTR_BORDER_INNER,
+ 0);
+ aSet.Put(SvxBoxInfoItem( SID_ATTR_BORDER_INNER ));
+ pDoc->GetTabBorders(*pTblCrsr, aSet);
+ const SvxBoxItem& rBoxItem = ((const SvxBoxItem&)aSet.Get(RES_BOX));
+ rBoxItem.QueryValue(aRet, pEntry->nMemberId);
+ }
+ break;
+ case RES_VERT_ORIENT:
+ {
+ SwFmtVertOrient aVertOrient;
+ if( pTblCrsr->GetDoc()->GetBoxAttr( *pTblCrsr, aVertOrient ) )
+ {
+ aVertOrient.QueryValue( aRet, pEntry->nMemberId );
+ }
+ }
+ break;
+ case RES_BOXATR_FORMAT:
+ //GetAttr fuer Tabellenselektion am Doc fehlt noch
+ DBG_WARNING("not implemented");
+ break;
+ case FN_UNO_PARA_STYLE:
+ {
+ SwFmtColl *const pTmpFmt =
+ SwUnoCursorHelper::GetCurTxtFmtColl(*pTblCrsr, sal_False);
+ OUString sRet;
+ if(pFmt)
+ sRet = pTmpFmt->GetName();
+ aRet <<= sRet;
+ }
+ break;
+ case FN_UNO_RANGE_ROW_LABEL:
+ {
+ sal_Bool bTemp = bFirstRowAsLabel;
+ aRet.setValue(&bTemp, ::getCppuBooleanType());
+ }
+ break;
+ case FN_UNO_RANGE_COL_LABEL:
+ {
+ sal_Bool bTemp = bFirstColumnAsLabel;
+ aRet.setValue(&bTemp, ::getCppuBooleanType());
+ }
+ break;
+ default:
+ {
+ SfxItemSet aSet(pTblCrsr->GetDoc()->GetAttrPool(),
+ RES_CHRATR_BEGIN, RES_FRMATR_END -1,
+ RES_TXTATR_UNKNOWN_CONTAINER, RES_TXTATR_UNKNOWN_CONTAINER,
+ RES_UNKNOWNATR_CONTAINER, RES_UNKNOWNATR_CONTAINER,
+ 0L);
+ // erstmal die Attribute des Cursors
+ SwUnoTableCrsr* pCrsr = dynamic_cast<SwUnoTableCrsr*>(pTblCrsr);
+ SwUnoCursorHelper::GetCrsrAttr(pCrsr->GetSelRing(), aSet);
+ m_pPropSet->getPropertyValue(*pEntry, aSet, aRet);
+ }
+ }
+ }
+ else
+ throw beans::UnknownPropertyException(OUString ( RTL_CONSTASCII_USTRINGPARAM ( "Unknown property: " ) ) + rPropertyName, static_cast < cppu::OWeakObject * > ( this ) );
+ }
+ return aRet;
+}
+
+void SwXCellRange::addPropertyChangeListener(const OUString& /*PropertyName*/, const uno::Reference< beans::XPropertyChangeListener > & /*aListener*/) throw( beans::UnknownPropertyException, lang::WrappedTargetException, uno::RuntimeException )
+{
+ DBG_WARNING("not implemented");
+}
+
+void SwXCellRange::removePropertyChangeListener(const OUString& /*PropertyName*/, const uno::Reference< beans::XPropertyChangeListener > & /*aListener*/) throw( beans::UnknownPropertyException, lang::WrappedTargetException, uno::RuntimeException )
+{
+ DBG_WARNING("not implemented");
+}
+
+void SwXCellRange::addVetoableChangeListener(const OUString& /*PropertyName*/, const uno::Reference< beans::XVetoableChangeListener > & /*aListener*/) throw( beans::UnknownPropertyException, lang::WrappedTargetException, uno::RuntimeException )
+{
+ DBG_WARNING("not implemented");
+}
+
+void SwXCellRange::removeVetoableChangeListener(const OUString& /*PropertyName*/, const uno::Reference< beans::XVetoableChangeListener > & /*aListener*/) throw( beans::UnknownPropertyException, lang::WrappedTargetException, uno::RuntimeException )
+{
+ DBG_WARNING("not implemented");
+}
+
+void SwXCellRange::GetDataSequence(
+ uno::Sequence< uno::Any > *pAnySeq, //-> first pointer != 0 is used
+ uno::Sequence< OUString > *pTxtSeq, //-> as output sequence
+ uno::Sequence< double > *pDblSeq, //-> (previous data gets overwritten)
+ sal_Bool bForceNumberResults ) //-> when 'true' requires to make an
+ // extra effort to return a value different
+ // from 0 even if the cell is formatted to text
+ throw (uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+
+ // compare to SwXCellRange::getDataArray (note different return types though)
+
+ sal_Int16 nRowCount = getRowCount();
+ sal_Int16 nColCount = getColumnCount();
+ //
+ if(!nRowCount || !nColCount)
+ {
+ uno::RuntimeException aRuntime;
+ aRuntime.Message = C2U("Table too complex");
+ throw aRuntime;
+ }
+
+ sal_Int32 nSize = nRowCount * nColCount;
+ if (pAnySeq)
+ pAnySeq->realloc( nSize );
+ else if (pTxtSeq)
+ pTxtSeq->realloc( nSize );
+ else if (pDblSeq)
+ pDblSeq->realloc( nSize );
+ else
+ {
+ OSL_FAIL( "argument missing" );
+ return;
+ }
+ uno::Any *pAnyData = pAnySeq ? pAnySeq->getArray() : 0;
+ OUString *pTxtData = pTxtSeq ? pTxtSeq->getArray() : 0;
+ double *pDblData = pDblSeq ? pDblSeq->getArray() : 0;
+
+ sal_Int32 nDtaCnt = 0;
+ SwFrmFmt* pFmt = GetFrmFmt();
+ if(pFmt)
+ {
+ double fNan;
+ ::rtl::math::setNan( & fNan );
+
+ uno::Reference< table::XCell > xCellRef;
+ for(sal_uInt16 nRow = 0; nRow < nRowCount; nRow++)
+ {
+ for(sal_uInt16 nCol = 0; nCol < nColCount; nCol++)
+ {
+ SwXCell * pXCell = lcl_CreateXCell(pFmt,
+ aRgDesc.nLeft + nCol,
+ aRgDesc.nTop + nRow);
+ //! keep (additional) reference to object to prevent implicit destruction
+ //! in following UNO calls (when object will get referenced)
+ xCellRef = pXCell;
+ SwTableBox * pBox = pXCell ? pXCell->GetTblBox() : 0;
+ if(!pBox)
+ {
+ throw uno::RuntimeException();
+ }
+ else
+ {
+ if (pAnyData)
+ {
+ // check if table box value item is set
+ sal_Bool bIsNum = pBox->GetFrmFmt()->GetItemState( RES_BOXATR_VALUE, sal_False ) == SFX_ITEM_SET;
+ //sal_uLong nNdPos = pBox->IsValidNumTxtNd( sal_True );
+ if (!bIsNum/* && ULONG_MAX == nNdPos*/)
+ pAnyData[nDtaCnt++] <<= lcl_getString(*pXCell);
+ else
+ pAnyData[nDtaCnt++] <<= lcl_getValue(*pXCell);
+ }
+ else if (pTxtData)
+ pTxtData[nDtaCnt++] = lcl_getString(*pXCell);
+ else if (pDblData)
+ {
+ double fVal = fNan;
+ if (!bForceNumberResults || table::CellContentType_TEXT != pXCell->getType())
+ fVal = lcl_getValue(*pXCell);
+ else
+ {
+ DBG_ASSERT( table::CellContentType_TEXT == pXCell->getType(),
+ "this branch of 'if' is only for text formatted cells" );
+
+ // now we'll try to get a useful numerical value
+ // from the text in the cell...
+
+ sal_uInt32 nFIndex;
+ SvNumberFormatter* pNumFormatter = pTblCrsr->GetDoc()->GetNumberFormatter();
+
+ // look for SwTblBoxNumFormat value in parents as well
+ const SfxPoolItem* pItem;
+ SwFrmFmt *pBoxFmt = pXCell->GetTblBox()->GetFrmFmt();
+ SfxItemState eState = pBoxFmt->GetAttrSet().GetItemState(RES_BOXATR_FORMAT, sal_True, &pItem);
+
+ if (eState == SFX_ITEM_SET)
+ {
+ // please note that the language of the numberformat
+ // is implicitly coded into the below value as well
+ nFIndex = ((SwTblBoxNumFormat*)pItem)->GetValue();
+
+ // since the current value indicates a text format but the call
+ // to 'IsNumberFormat' below won't work for text formats
+ // we need to get rid of the part that indicates the text format.
+ // According to ER this can be done like this:
+ nFIndex -= (nFIndex % SV_COUNTRY_LANGUAGE_OFFSET);
+ }
+ else
+ {
+ // system language is probably not the best possible choice
+ // but since we have to guess anyway (because the language of at
+ // the text is NOT the one used for the number format!)
+ // it is at least conform to to what is used in
+ // SwTableShell::Execute when
+ // SID_ATTR_NUMBERFORMAT_VALUE is set...
+ LanguageType eLang = LANGUAGE_SYSTEM;
+ nFIndex = pNumFormatter->GetStandardIndex( eLang );
+ }
+
+ OUString aTxt( lcl_getString(*pXCell) );
+ double fTmp;
+ if (pNumFormatter->IsNumberFormat( aTxt, nFIndex, fTmp ))
+ fVal = fTmp;
+ }
+ pDblData[nDtaCnt++] = fVal;
+ }
+ else {
+ OSL_FAIL( "output sequence missing" );
+ }
+ }
+ }
+ }
+ }
+ DBG_ASSERT( nDtaCnt == nSize, "size mismatch. Invalid cell range?" );
+ if (pAnySeq)
+ pAnySeq->realloc( nDtaCnt );
+ else if (pTxtSeq)
+ pTxtSeq->realloc( nDtaCnt );
+ else if (pDblSeq)
+ pDblSeq->realloc( nDtaCnt );
+}
+
+uno::Sequence< uno::Sequence< uno::Any > > SAL_CALL SwXCellRange::getDataArray()
+ throw (uno::RuntimeException)
+{
+ // see SwXCellRange::getData also
+ // also see SwXCellRange::GetDataSequence
+
+ SolarMutexGuard aGuard;
+ sal_Int16 nRowCount = getRowCount();
+ sal_Int16 nColCount = getColumnCount();
+ //
+ if(!nRowCount || !nColCount)
+ {
+ uno::RuntimeException aRuntime;
+ aRuntime.Message = C2U("Table too complex");
+ throw aRuntime;
+ }
+ uno::Sequence< uno::Sequence< uno::Any > > aRowSeq(nRowCount);
+ SwFrmFmt* pFmt = GetFrmFmt();
+ if(pFmt)
+ {
+ uno::Sequence< uno::Any >* pRowArray = aRowSeq.getArray();
+ uno::Reference< table::XCell > xCellRef;
+ for(sal_uInt16 nRow = 0; nRow < nRowCount; nRow++)
+ {
+ uno::Sequence< uno::Any > aColSeq(nColCount);
+ uno::Any * pColArray = aColSeq.getArray();
+ for(sal_uInt16 nCol = 0; nCol < nColCount; nCol++)
+ {
+ SwXCell * pXCell = lcl_CreateXCell(pFmt,
+ aRgDesc.nLeft + nCol,
+ aRgDesc.nTop + nRow);
+ //! keep (additional) reference to object to prevent implicit destruction
+ //! in following UNO calls (when object will get referenced)
+ xCellRef = pXCell;
+ SwTableBox * pBox = pXCell ? pXCell->GetTblBox() : 0;
+ if(!pBox)
+ {
+ throw uno::RuntimeException();
+ }
+ else
+ {
+ // check if table box value item is set
+ SwFrmFmt* pBoxFmt = pBox->GetFrmFmt();
+ sal_Bool bIsNum = pBoxFmt->GetItemState( RES_BOXATR_VALUE, sal_False ) == SFX_ITEM_SET;
+ //const SfxPoolItem* pItem;
+ //SwDoc* pDoc = pXCell->GetDoc();
+ //sal_Bool bIsText = (SFX_ITEM_SET != pBoxFmt->GetAttrSet().GetItemState(RES_BOXATR_FORMAT, sal_True, &pItem)
+ // || pDoc->GetNumberFormatter()->IsTextFormat(((SwTblBoxNumFormat*)pItem)->GetValue())
+ // || ((SwTblBoxNumFormat*)pItem)->GetValue() == NUMBERFORMAT_TEXT);
+
+ if(!bIsNum/*bIsText*/)
+ pColArray[nCol] <<= lcl_getString(*pXCell);
+ else
+ pColArray[nCol] <<= lcl_getValue(*pXCell);
+ }
+ }
+ pRowArray[nRow] = aColSeq;
+ }
+ }
+ return aRowSeq;
+}
+
+void SAL_CALL SwXCellRange::setDataArray(
+ const uno::Sequence< uno::Sequence< uno::Any > >& rArray )
+ throw (uno::RuntimeException)
+{
+ // see SwXCellRange::setData also
+
+ SolarMutexGuard aGuard;
+ sal_Int16 nRowCount = getRowCount();
+ sal_Int16 nColCount = getColumnCount();
+ if(!nRowCount || !nColCount)
+ {
+ uno::RuntimeException aRuntime;
+ aRuntime.Message = C2U("Table too complex");
+ throw aRuntime;
+ }
+ SwFrmFmt* pFmt = GetFrmFmt();
+ if(pFmt )
+ {
+ if(rArray.getLength() != nRowCount)
+ {
+ throw uno::RuntimeException();
+ }
+ const uno::Sequence< uno::Any >* pRowArray = rArray.getConstArray();
+ for(sal_uInt16 nRow = 0; nRow < nRowCount; nRow++)
+ {
+ const uno::Sequence< uno::Any >& rColSeq = pRowArray[nRow];
+ if(rColSeq.getLength() != nColCount)
+ {
+ throw uno::RuntimeException();
+ }
+ const uno::Any * pColArray = rColSeq.getConstArray();
+ uno::Reference< table::XCell > xCellRef;
+ for(sal_uInt16 nCol = 0; nCol < nColCount; nCol++)
+ {
+ SwXCell * pXCell = lcl_CreateXCell(pFmt,
+ aRgDesc.nLeft + nCol,
+ aRgDesc.nTop + nRow);
+ //! keep (additional) reference to object to prevent implicit destruction
+ //! in following UNO calls (when object will get referenced)
+ xCellRef = pXCell;
+ SwTableBox * pBox = pXCell ? pXCell->GetTblBox() : 0;
+ if(!pBox)
+ {
+ throw uno::RuntimeException();
+ }
+ else
+ {
+ const uno::Any &rAny = pColArray[nCol];
+ if (uno::TypeClass_STRING == rAny.getValueTypeClass())
+ lcl_setString( *pXCell, *(rtl::OUString *) rAny.getValue() );
+ else
+ {
+ double d = 0;
+ // #i20067# don't throw exception just do nothing if
+ // there is no value set
+ if( (rAny >>= d) )
+ lcl_setValue( *pXCell, d );
+ else
+ lcl_setString( *pXCell, OUString(), sal_True );
+ }
+ }
+ }
+ }
+ }
+}
+
+uno::Sequence< uno::Sequence< double > > SwXCellRange::getData(void) throw( uno::RuntimeException )
+{
+ SolarMutexGuard aGuard;
+ sal_Int16 nRowCount = getRowCount();
+ sal_Int16 nColCount = getColumnCount();
+ //
+ if(!nRowCount || !nColCount)
+ {
+ uno::RuntimeException aRuntime;
+ aRuntime.Message = C2U("Table too complex");
+ throw aRuntime;
+ }
+ uno::Sequence< uno::Sequence< double > > aRowSeq(bFirstRowAsLabel ? nRowCount - 1 : nRowCount);
+ SwFrmFmt* pFmt = GetFrmFmt();
+ if(pFmt)
+ {
+ uno::Sequence< double >* pRowArray = aRowSeq.getArray();
+
+ sal_uInt16 nRowStart = bFirstRowAsLabel ? 1 : 0;
+ for(sal_uInt16 nRow = nRowStart; nRow < nRowCount; nRow++)
+ {
+ uno::Sequence< double > aColSeq(bFirstColumnAsLabel ? nColCount - 1 : nColCount);
+ double * pArray = aColSeq.getArray();
+ sal_uInt16 nColStart = bFirstColumnAsLabel ? 1 : 0;
+ for(sal_uInt16 nCol = nColStart; nCol < nColCount; nCol++)
+ {
+ uno::Reference< table::XCell > xCell = getCellByPosition(nCol, nRow);
+ if(!xCell.is())
+ {
+ throw uno::RuntimeException();
+ }
+ pArray[nCol - nColStart] = xCell->getValue();
+ }
+ pRowArray[nRow - nRowStart] = aColSeq;
+ }
+ }
+ return aRowSeq;
+}
+
+void SwXCellRange::setData(const uno::Sequence< uno::Sequence< double > >& rData)
+ throw( uno::RuntimeException )
+{
+ SolarMutexGuard aGuard;
+ sal_Int16 nRowCount = getRowCount();
+ sal_Int16 nColCount = getColumnCount();
+ if(!nRowCount || !nColCount)
+ {
+ uno::RuntimeException aRuntime;
+ aRuntime.Message = C2U("Table too complex");
+ throw aRuntime;
+ }
+ SwFrmFmt* pFmt = GetFrmFmt();
+ if(pFmt )
+ {
+ sal_uInt16 nRowStart = bFirstRowAsLabel ? 1 : 0;
+ if(rData.getLength() < nRowCount - nRowStart)
+ {
+ throw uno::RuntimeException();
+ }
+ const uno::Sequence< double >* pRowArray = rData.getConstArray();
+ for(sal_uInt16 nRow = nRowStart; nRow < nRowCount; nRow++)
+ {
+ const uno::Sequence< double >& rColSeq = pRowArray[nRow - nRowStart];
+ sal_uInt16 nColStart = bFirstColumnAsLabel ? 1 : 0;
+ if(rColSeq.getLength() < nColCount - nColStart)
+ {
+ throw uno::RuntimeException();
+ }
+ const double * pColArray = rColSeq.getConstArray();
+ for(sal_uInt16 nCol = nColStart; nCol < nColCount; nCol++)
+ {
+ uno::Reference< table::XCell > xCell = getCellByPosition(nCol, nRow);
+ if(!xCell.is())
+ {
+ throw uno::RuntimeException();
+ }
+ xCell->setValue(pColArray[nCol - nColStart]);
+ }
+ }
+ }
+}
+
+uno::Sequence< OUString > SwXCellRange::getRowDescriptions(void)
+ throw( uno::RuntimeException )
+{
+ SolarMutexGuard aGuard;
+ sal_Int16 nRowCount = getRowCount();
+ if(!nRowCount)
+ {
+ uno::RuntimeException aRuntime;
+ aRuntime.Message = C2U("Table too complex");
+ throw aRuntime;
+ }
+ uno::Sequence< OUString > aRet(bFirstColumnAsLabel ? nRowCount - 1 : nRowCount);
+ SwFrmFmt* pFmt = GetFrmFmt();
+ if(pFmt)
+ {
+ OUString* pArray = aRet.getArray();
+ if(bFirstColumnAsLabel)
+ {
+ sal_uInt16 nStart = bFirstRowAsLabel ? 1 : 0;
+ for(sal_uInt16 i = nStart; i < nRowCount; i++)
+ {
+ uno::Reference< table::XCell > xCell = getCellByPosition(0, i);
+ if(!xCell.is())
+ {
+ throw uno::RuntimeException();
+ }
+ uno::Reference< text::XText > xText(xCell, uno::UNO_QUERY);
+ pArray[i - nStart] = xText->getString();
+ }
+ }
+ else
+ {
+ OSL_FAIL("Wo kommen die Labels her?");
+ }
+ }
+ else
+ throw uno::RuntimeException();
+ return aRet;
+}
+
+void SwXCellRange::setRowDescriptions(const uno::Sequence< OUString >& rRowDesc)
+ throw( uno::RuntimeException )
+{
+ SolarMutexGuard aGuard;
+ SwFrmFmt* pFmt = GetFrmFmt();
+ if(pFmt)
+ {
+ sal_Int16 nRowCount = getRowCount();
+ if(!nRowCount || rRowDesc.getLength() < bFirstRowAsLabel ? nRowCount - 1 : nRowCount)
+ {
+ throw uno::RuntimeException();
+ }
+ const OUString* pArray = rRowDesc.getConstArray();
+ if(bFirstColumnAsLabel)
+ {
+ sal_uInt16 nStart = bFirstRowAsLabel ? 1 : 0;
+ for(sal_uInt16 i = nStart; i < nRowCount; i++)
+ {
+ uno::Reference< table::XCell > xCell = getCellByPosition(0, i);
+ if(!xCell.is())
+ {
+ throw uno::RuntimeException();
+ }
+ uno::Reference< text::XText > xText(xCell, uno::UNO_QUERY);
+ xText->setString(pArray[i - nStart]);
+ }
+ }
+ else
+ {
+ OSL_FAIL("Wohin mit den Labels?");
+ }
+ }
+}
+
+uno::Sequence< OUString > SwXCellRange::getColumnDescriptions(void)
+ throw( uno::RuntimeException )
+{
+ SolarMutexGuard aGuard;
+ sal_Int16 nColCount = getColumnCount();
+ if(!nColCount)
+ {
+ uno::RuntimeException aRuntime;
+ aRuntime.Message = C2U("Table too complex");
+ throw aRuntime;
+ }
+ uno::Sequence< OUString > aRet(bFirstRowAsLabel ? nColCount - 1 : nColCount);
+ SwFrmFmt* pFmt = GetFrmFmt();
+ if(pFmt)
+ {
+ OUString* pArray = aRet.getArray();
+ if(bFirstRowAsLabel)
+ {
+ sal_uInt16 nStart = bFirstColumnAsLabel ? 1 : 0;
+ for(sal_uInt16 i = nStart; i < nColCount; i++)
+ {
+ uno::Reference< table::XCell > xCell = getCellByPosition(i, 0);
+ if(!xCell.is())
+ {
+ throw uno::RuntimeException();
+ }
+ uno::Reference< text::XText > xText(xCell, uno::UNO_QUERY);
+ pArray[i - nStart] = xText->getString();
+ }
+ }
+ else
+ {
+ OSL_FAIL("Wo kommen die Labels her?");
+ }
+ }
+ else
+ throw uno::RuntimeException();
+ return aRet;
+}
+
+void SwXCellRange::setColumnDescriptions(const uno::Sequence< OUString >& ColumnDesc)
+ throw( uno::RuntimeException )
+{
+ SolarMutexGuard aGuard;
+ sal_Int16 nColCount = getColumnCount();
+ SwFrmFmt* pFmt = GetFrmFmt();
+ if(pFmt)
+ {
+ const OUString* pArray = ColumnDesc.getConstArray();
+ if(bFirstRowAsLabel && ColumnDesc.getLength() >= nColCount - bFirstColumnAsLabel ? 1 : 0)
+ {
+ sal_uInt16 nStart = bFirstColumnAsLabel ? 1 : 0;
+ for(sal_uInt16 i = nStart; i < nColCount; i++)
+ {
+ uno::Reference< table::XCell > xCell = getCellByPosition(i, 0);
+ if(!xCell.is())
+ {
+ throw uno::RuntimeException();
+ }
+ uno::Reference< text::XText > xText(xCell, uno::UNO_QUERY);
+
+ xText->setString(pArray[i - nStart]);
+ }
+ }
+ else
+ {
+ OSL_FAIL("Wo kommen die Labels her?");
+ }
+ }
+}
+
+void SwXCellRange::addChartDataChangeEventListener(const uno::Reference< chart::XChartDataChangeEventListener > & aListener) throw( uno::RuntimeException )
+{
+ if(!GetRegisteredIn())
+ throw uno::RuntimeException();
+ aChartLstnrCntnr.AddListener(aListener.get());
+}
+
+void SwXCellRange::removeChartDataChangeEventListener(const uno::Reference< chart::XChartDataChangeEventListener > & aListener) throw( uno::RuntimeException )
+{
+ if(!GetRegisteredIn() || !aChartLstnrCntnr.RemoveListener(aListener.get()))
+ throw uno::RuntimeException();
+}
+
+sal_Bool SwXCellRange::isNotANumber(double /*fNumber*/) throw( uno::RuntimeException )
+{
+ DBG_WARNING("not implemented");
+ return sal_False;
+
+}
+
+double SwXCellRange::getNotANumber(void) throw( uno::RuntimeException )
+{
+ DBG_WARNING("not implemented");
+ return 0.;
+}
+
+uno::Sequence< beans::PropertyValue > SwXCellRange::createSortDescriptor(void) throw( uno::RuntimeException )
+{
+ SolarMutexGuard aGuard;
+
+ return SwUnoCursorHelper::CreateSortDescriptor(true);
+}
+
+void SAL_CALL SwXCellRange::sort(const uno::Sequence< beans::PropertyValue >& rDescriptor)
+ throw( uno::RuntimeException )
+{
+ SolarMutexGuard aGuard;
+ SwSortOptions aSortOpt;
+ SwFrmFmt* pFmt = GetFrmFmt();
+ if(pFmt &&
+ SwUnoCursorHelper::ConvertSortProperties(rDescriptor, aSortOpt))
+ {
+ SwUnoTableCrsr* pTableCrsr = dynamic_cast<SwUnoTableCrsr*>(pTblCrsr);
+ pTableCrsr->MakeBoxSels();
+ UnoActionContext aContext( pFmt->GetDoc() );
+ pFmt->GetDoc()->SortTbl(pTableCrsr->GetBoxes(), aSortOpt);
+ }
+}
+
+sal_uInt16 SwXCellRange::getColumnCount(void)
+{
+ return static_cast< sal_uInt16 >(aRgDesc.nRight - aRgDesc.nLeft + 1);
+}
+
+sal_uInt16 SwXCellRange::getRowCount(void)
+{
+ return static_cast< sal_uInt16 >(aRgDesc.nBottom - aRgDesc.nTop + 1);
+}
+
+const SwUnoCrsr* SwXCellRange::GetTblCrsr() const
+{
+ const SwUnoCrsr* pRet = 0;
+ SwFrmFmt* pFmt = GetFrmFmt();
+ if(pFmt)
+ pRet = pTblCrsr;
+ return pRet;
+}
+
+void SwXCellRange::Modify( const SfxPoolItem* pOld, const SfxPoolItem *pNew)
+{
+ ClientModify(this, pOld, pNew );
+ if(!GetRegisteredIn() || !aCursorDepend.GetRegisteredIn())
+ {
+ /*
+ * Not sure if this will cause a memory leak - this pTblCrsr
+ * is deleted in SwDoc and GPFs here when deleted again
+ * if(!aCursorDepend.GetRegisteredIn())
+ delete pTblCrsr;
+ */
+ pTblCrsr = 0;
+ aChartLstnrCntnr.Disposing();
+ }
+ else
+ aChartLstnrCntnr.ChartDataChanged();
+}
+
+/******************************************************************
+ * SwXTableRows
+ ******************************************************************/
+OUString SwXTableRows::getImplementationName(void) throw( uno::RuntimeException )
+{
+ return C2U("SwXTableRows");
+}
+
+sal_Bool SwXTableRows::supportsService(const OUString& rServiceName) throw( uno::RuntimeException )
+{
+ return C2U("com.sun.star.text.TableRows") == rServiceName;
+}
+
+uno::Sequence< OUString > SwXTableRows::getSupportedServiceNames(void) throw( uno::RuntimeException )
+{
+ uno::Sequence< OUString > aRet(1);
+ OUString* pArray = aRet.getArray();
+ pArray[0] = C2U("com.sun.star.text.TableRows");
+ return aRet;
+}
+TYPEINIT1(SwXTableRows, SwClient);
+
+SwXTableRows::SwXTableRows(SwFrmFmt& rFrmFmt) :
+ SwClient(&rFrmFmt)
+{
+}
+
+SwXTableRows::~SwXTableRows()
+{
+}
+
+sal_Int32 SwXTableRows::getCount(void) throw( uno::RuntimeException )
+{
+ SolarMutexGuard aGuard;
+ sal_Int32 nRet = 0;
+ SwFrmFmt* pFrmFmt = GetFrmFmt();
+ if(!pFrmFmt)
+ throw uno::RuntimeException();
+ else
+ {
+ SwTable* pTable = SwTable::FindTable( pFrmFmt );
+ nRet = pTable->GetTabLines().Count();
+ }
+ return nRet;
+}
+
+uno::Any SwXTableRows::getByIndex(sal_Int32 nIndex)
+ throw( lang::IndexOutOfBoundsException, lang::WrappedTargetException, uno::RuntimeException )
+{
+ SolarMutexGuard aGuard;
+ uno::Any aRet;
+ SwFrmFmt* pFrmFmt = GetFrmFmt();
+ if(!pFrmFmt || nIndex < 0 )
+ throw lang::IndexOutOfBoundsException();
+ else
+ {
+ SwTable* pTable = SwTable::FindTable( pFrmFmt );
+ if(pTable->GetTabLines().Count() > nIndex)
+ {
+ SwTableLine* pLine = pTable->GetTabLines().GetObject((sal_uInt16)nIndex);
+ SwIterator<SwXTextTableRow,SwFmt> aIter( *pFrmFmt );
+ SwXTextTableRow* pXRow = aIter.First();
+ while( pXRow )
+ {
+ // gibt es eine passende Zelle bereits?
+ if(pXRow->GetTblRow() == pLine)
+ break;
+ pXRow = aIter.Next();
+ }
+ //sonst anlegen
+ if(!pXRow)
+ pXRow = new SwXTextTableRow(pFrmFmt, pLine);
+ uno::Reference< beans::XPropertySet > xRet =
+ (beans::XPropertySet*)pXRow;
+ aRet.setValue(&xRet, ::getCppuType((const uno::Reference<beans::XPropertySet>*)0));
+ }
+ else
+ throw lang::IndexOutOfBoundsException();
+ }
+ return aRet;
+}
+
+uno::Type SAL_CALL SwXTableRows::getElementType(void) throw( uno::RuntimeException )
+{
+ return ::getCppuType((const uno::Reference<beans::XPropertySet>*)0);
+}
+
+sal_Bool SwXTableRows::hasElements(void) throw( uno::RuntimeException )
+{
+ SolarMutexGuard aGuard;
+ SwFrmFmt* pFrmFmt = GetFrmFmt();
+ if(!pFrmFmt)
+ throw uno::RuntimeException();
+ //es gibt keine Tabelle ohne Zeilen
+ return sal_True;
+}
+
+void SwXTableRows::insertByIndex(sal_Int32 nIndex, sal_Int32 nCount) throw( uno::RuntimeException )
+{
+ SolarMutexGuard aGuard;
+ if (nCount == 0)
+ return;
+ SwFrmFmt* pFrmFmt = GetFrmFmt();
+ if(!pFrmFmt)
+ throw uno::RuntimeException();
+ else
+ {
+ SwTable* pTable = SwTable::FindTable( pFrmFmt );
+ if(!pTable->IsTblComplex())
+ {
+ sal_uInt16 nRowCount = pTable->GetTabLines().Count();
+ if (nCount <= 0 || !(0 <= nIndex && nIndex <= nRowCount))
+ {
+ uno::RuntimeException aExcept;
+ aExcept.Message = C2U("Illegal arguments");
+ throw aExcept;
+ }
+
+ String sTLName = lcl_GetCellName(0, nIndex);
+ const SwTableBox* pTLBox = pTable->GetTblBox( sTLName );
+ sal_Bool bAppend = sal_False;
+ if(!pTLBox)
+ {
+ bAppend = sal_True;
+ // am Ende anfuegen, dazu muss der Cursor in die letzte Zeile!
+ SwTableLines& rLines = pTable->GetTabLines();
+ SwTableLine* pLine = rLines.GetObject(rLines.Count() -1);
+ SwTableBoxes& rBoxes = pLine->GetTabBoxes();
+ pTLBox = rBoxes.GetObject(0);
+ }
+ if(pTLBox)
+ {
+ const SwStartNode* pSttNd = pTLBox->GetSttNd();
+ SwPosition aPos(*pSttNd);
+ // Cursor in die obere linke Zelle des Ranges setzen
+ UnoActionContext aAction(pFrmFmt->GetDoc());
+ SwUnoCrsr* pUnoCrsr = pFrmFmt->GetDoc()->CreateUnoCrsr(aPos, sal_True);
+ pUnoCrsr->Move( fnMoveForward, fnGoNode );
+
+ {
+ // remove actions
+ UnoActionRemoveContext aRemoveContext(pUnoCrsr->GetDoc());
+ }
+
+ pFrmFmt->GetDoc()->InsertRow(*pUnoCrsr, (sal_uInt16)nCount, bAppend);
+ delete pUnoCrsr;
+ }
+ }
+ }
+}
+
+void SwXTableRows::removeByIndex(sal_Int32 nIndex, sal_Int32 nCount) throw( uno::RuntimeException )
+{
+ SolarMutexGuard aGuard;
+ if (nCount == 0)
+ return;
+ SwFrmFmt* pFrmFmt = GetFrmFmt();
+ if(!pFrmFmt || nIndex < 0 || nCount <=0 )
+ throw uno::RuntimeException();
+ else
+ {
+ sal_Bool bSuccess = sal_False;
+ SwTable* pTable = SwTable::FindTable( pFrmFmt );
+ if(!pTable->IsTblComplex())
+ {
+ String sTLName = lcl_GetCellName(0, nIndex);
+ const SwTableBox* pTLBox = pTable->GetTblBox( sTLName );
+ if(pTLBox)
+ {
+ {
+ // hier muessen die Actions aufgehoben werden
+ UnoActionRemoveContext aRemoveContext(pFrmFmt->GetDoc());
+ }
+ const SwStartNode* pSttNd = pTLBox->GetSttNd();
+ SwPosition aPos(*pSttNd);
+ // Cursor in die obere linke Zelle des Ranges setzen
+ SwUnoCrsr* pUnoCrsr = pFrmFmt->GetDoc()->CreateUnoCrsr(aPos, sal_True);
+ pUnoCrsr->Move( fnMoveForward, fnGoNode );
+ pUnoCrsr->SetRemainInSection( sal_False );
+ String sBLName = lcl_GetCellName(0, nIndex + nCount - 1);
+ const SwTableBox* pBLBox = pTable->GetTblBox( sBLName );
+ if(pBLBox)
+ {
+ pUnoCrsr->SetMark();
+ pUnoCrsr->GetPoint()->nNode = *pBLBox->GetSttNd();
+ pUnoCrsr->Move( fnMoveForward, fnGoNode );
+ SwUnoTableCrsr* pCrsr =
+ dynamic_cast<SwUnoTableCrsr*>(pUnoCrsr);
+ pCrsr->MakeBoxSels();
+ { // Die Klammer ist wichtig
+ UnoActionContext aAction(pFrmFmt->GetDoc());
+ pFrmFmt->GetDoc()->DeleteRow(*pUnoCrsr);
+ delete pUnoCrsr;
+ bSuccess = sal_True;
+ }
+ {
+ // hier muessen die Actions aufgehoben werden
+ UnoActionRemoveContext aRemoveContext(pFrmFmt->GetDoc());
+ }
+ }
+ }
+ }
+ if(!bSuccess)
+ {
+ uno::RuntimeException aExcept;
+ aExcept.Message = C2U("Illegal arguments");
+ throw aExcept;
+ }
+ }
+}
+
+void SwXTableRows::Modify( const SfxPoolItem* pOld, const SfxPoolItem *pNew)
+{
+ ClientModify(this, pOld, pNew);
+}
+
+/******************************************************************
+ * SwXTableColumns
+ ******************************************************************/
+OUString SwXTableColumns::getImplementationName(void) throw( uno::RuntimeException )
+{
+ return C2U("SwXTableColumns");
+}
+
+sal_Bool SwXTableColumns::supportsService(const OUString& rServiceName) throw( uno::RuntimeException )
+{
+ return C2U("com.sun.star.text.TableColumns") == rServiceName;
+}
+
+uno::Sequence< OUString > SwXTableColumns::getSupportedServiceNames(void) throw( uno::RuntimeException )
+{
+ uno::Sequence< OUString > aRet(1);
+ OUString* pArray = aRet.getArray();
+ pArray[0] = C2U("com.sun.star.text.TableColumns");
+ return aRet;
+}
+
+TYPEINIT1(SwXTableColumns, SwClient);
+
+SwXTableColumns::SwXTableColumns(SwFrmFmt& rFrmFmt) :
+ SwClient(&rFrmFmt)
+{
+}
+
+SwXTableColumns::~SwXTableColumns()
+{
+}
+
+sal_Int32 SwXTableColumns::getCount(void) throw( uno::RuntimeException )
+{
+ SolarMutexGuard aGuard;
+ sal_Int32 nRet = 0;
+ SwFrmFmt* pFrmFmt = GetFrmFmt();
+ if(!pFrmFmt)
+ throw uno::RuntimeException();
+ else
+ {
+ SwTable* pTable = SwTable::FindTable( pFrmFmt );
+ if(!pTable->IsTblComplex())
+ {
+ SwTableLines& rLines = pTable->GetTabLines();
+ SwTableLine* pLine = rLines.GetObject(0);
+ nRet = pLine->GetTabBoxes().Count();
+ }
+ }
+ return nRet;
+}
+
+uno::Any SwXTableColumns::getByIndex(sal_Int32 nIndex)
+ throw( lang::IndexOutOfBoundsException, lang::WrappedTargetException, uno::RuntimeException )
+{
+ SolarMutexGuard aGuard;
+ uno::Reference< uno::XInterface > xRet;
+ SwFrmFmt* pFrmFmt = GetFrmFmt();
+ if(!pFrmFmt)
+ throw uno::RuntimeException();
+ else
+ {
+ sal_uInt16 nCount = 0;
+ SwTable* pTable = SwTable::FindTable( pFrmFmt );
+ if(!pTable->IsTblComplex())
+ {
+ SwTableLines& rLines = pTable->GetTabLines();
+ SwTableLine* pLine = rLines.GetObject(0);
+ nCount = pLine->GetTabBoxes().Count();
+ }
+ if(nCount <= nIndex || nIndex < 0)
+ throw lang::IndexOutOfBoundsException();
+ xRet = uno::Reference<uno::XInterface>(); //!! writer tables do not have columns !!
+ }
+ return uno::Any(&xRet, ::getCppuType((const uno::Reference<uno::XInterface>*)0));
+}
+
+uno::Type SAL_CALL SwXTableColumns::getElementType(void) throw( uno::RuntimeException )
+{
+ return ::getCppuType((uno::Reference<uno::XInterface>*)0);
+}
+
+sal_Bool SwXTableColumns::hasElements(void) throw( uno::RuntimeException )
+{
+ SolarMutexGuard aGuard;
+ SwFrmFmt* pFrmFmt = GetFrmFmt();
+ if(!pFrmFmt)
+ throw uno::RuntimeException();
+ return sal_True;
+}
+
+void SwXTableColumns::insertByIndex(sal_Int32 nIndex, sal_Int32 nCount) throw( uno::RuntimeException )
+{
+ SolarMutexGuard aGuard;
+ if (nCount == 0)
+ return;
+ SwFrmFmt* pFrmFmt = GetFrmFmt();
+ if(!pFrmFmt)
+ throw uno::RuntimeException();
+ else
+ {
+ SwTable* pTable = SwTable::FindTable( pFrmFmt );
+ if(!pTable->IsTblComplex())
+ {
+ SwTableLines& rLines = pTable->GetTabLines();
+ SwTableLine* pLine = rLines.GetObject(0);
+ sal_uInt16 nColCount = pLine->GetTabBoxes().Count();
+ if (nCount <= 0 || !(0 <= nIndex && nIndex <= nColCount))
+ {
+ uno::RuntimeException aExcept;
+ aExcept.Message = C2U("Illegal arguments");
+ throw aExcept;
+ }
+
+ String sTLName = lcl_GetCellName(nIndex, 0);
+ const SwTableBox* pTLBox = pTable->GetTblBox( sTLName );
+ sal_Bool bAppend = sal_False;
+ if(!pTLBox)
+ {
+ bAppend = sal_True;
+ // am Ende anfuegen, dazu muss der Cursor in die letzte Spalte!
+ SwTableBoxes& rBoxes = pLine->GetTabBoxes();
+ pTLBox = rBoxes.GetObject(rBoxes.Count() - 1);
+ }
+ if(pTLBox)
+ {
+ const SwStartNode* pSttNd = pTLBox->GetSttNd();
+ SwPosition aPos(*pSttNd);
+ UnoActionContext aAction(pFrmFmt->GetDoc());
+ SwUnoCrsr* pUnoCrsr = pFrmFmt->GetDoc()->CreateUnoCrsr(aPos, sal_True);
+ pUnoCrsr->Move( fnMoveForward, fnGoNode );
+
+ {
+ // remove actions
+ UnoActionRemoveContext aRemoveContext(pUnoCrsr->GetDoc());
+ }
+
+ pFrmFmt->GetDoc()->InsertCol(*pUnoCrsr, (sal_uInt16)nCount, bAppend);
+ delete pUnoCrsr;
+ }
+ }
+ }
+}
+
+void SwXTableColumns::removeByIndex(sal_Int32 nIndex, sal_Int32 nCount) throw( uno::RuntimeException )
+{
+ SolarMutexGuard aGuard;
+ if (nCount == 0)
+ return;
+ SwFrmFmt* pFrmFmt = GetFrmFmt();
+ if(!pFrmFmt|| nIndex < 0 || nCount <=0 )
+ throw uno::RuntimeException();
+ else
+ {
+ sal_Bool bSuccess = sal_False;
+ SwTable* pTable = SwTable::FindTable( pFrmFmt );
+ if(!pTable->IsTblComplex())
+ {
+ String sTLName = lcl_GetCellName(nIndex, 0);
+ const SwTableBox* pTLBox = pTable->GetTblBox( sTLName );
+ if(pTLBox)
+ {
+ {
+ // hier muessen die Actions aufgehoben werden
+ UnoActionRemoveContext aRemoveContext(pFrmFmt->GetDoc());
+ }
+ const SwStartNode* pSttNd = pTLBox->GetSttNd();
+ SwPosition aPos(*pSttNd);
+ // Cursor in die obere linke Zelle des Ranges setzen
+ SwUnoCrsr* pUnoCrsr = pFrmFmt->GetDoc()->CreateUnoCrsr(aPos, sal_True);
+ pUnoCrsr->Move( fnMoveForward, fnGoNode );
+ pUnoCrsr->SetRemainInSection( sal_False );
+ String sTRName = lcl_GetCellName(nIndex + nCount - 1, 0);
+ const SwTableBox* pTRBox = pTable->GetTblBox( sTRName );
+ if(pTRBox)
+ {
+ pUnoCrsr->SetMark();
+ pUnoCrsr->GetPoint()->nNode = *pTRBox->GetSttNd();
+ pUnoCrsr->Move( fnMoveForward, fnGoNode );
+ SwUnoTableCrsr* pCrsr =
+ dynamic_cast<SwUnoTableCrsr*>(pUnoCrsr);
+ pCrsr->MakeBoxSels();
+ { // Die Klammer ist wichtig
+ UnoActionContext aAction(pFrmFmt->GetDoc());
+ pFrmFmt->GetDoc()->DeleteCol(*pUnoCrsr);
+ delete pUnoCrsr;
+ bSuccess = sal_True;
+ }
+ {
+ // hier muessen die Actions aufgehoben werden
+ UnoActionRemoveContext aRemoveContext(pFrmFmt->GetDoc());
+ }
+ }
+ }
+ }
+ if(!bSuccess)
+ {
+ uno::RuntimeException aExcept;
+ aExcept.Message = C2U("Illegal arguments");
+ throw aExcept;
+ }
+ }
+}
+
+void SwXTableColumns::Modify( const SfxPoolItem* pOld, const SfxPoolItem *pNew)
+{
+ ClientModify(this, pOld, pNew);
+}
+
+void SwChartEventListenerContainer::ChartDataChanged()
+{
+ if(pListenerArr)
+ {
+ //TODO: find appropriate settings of the Event
+ lang::EventObject aObj(pxParent);
+ chart::ChartDataChangeEvent aEvent;
+ aEvent.Type = chart::ChartDataChangeType_ALL;
+ aEvent.StartColumn = 0;
+ aEvent.EndColumn = 1;
+ aEvent.StartRow = 0;
+ aEvent.EndRow = 1;
+
+ for(sal_uInt16 i = 0; i < pListenerArr->Count(); i++)
+ {
+ try
+ {
+ XEventListenerPtr pElem = pListenerArr->GetObject(i);
+ uno::Reference<lang::XEventListener> xEventListener = *pElem;
+ uno::Reference<chart::XChartDataChangeEventListener> xChartEventListener = (chart::XChartDataChangeEventListener*)(*pElem).get();
+ xChartEventListener->chartDataChanged( aEvent );
+ }
+ catch(uno::Exception const &)
+ {
+ }
+ }
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/unocore/unotext.cxx b/sw/source/core/unocore/unotext.cxx
new file mode 100644
index 000000000000..17e3723d9df0
--- /dev/null
+++ b/sw/source/core/unocore/unotext.cxx
@@ -0,0 +1,2815 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+#include <stdlib.h>
+
+#include <memory>
+#include <iostream>
+
+#include <com/sun/star/drawing/XDrawPageSupplier.hpp>
+#include <com/sun/star/text/ControlCharacter.hpp>
+#include <com/sun/star/text/TableColumnSeparator.hpp>
+
+#include <rtl/uuid.h>
+
+#include <osl/mutex.hxx>
+#include <vcl/svapp.hxx>
+#include <comphelper/sequence.hxx>
+
+#include <cmdid.h>
+#include <unotextbodyhf.hxx>
+#include <unotext.hxx>
+#include <unotextrange.hxx>
+#include <unotextcursor.hxx>
+#include <unosection.hxx>
+#include <unobookmark.hxx>
+#include <unorefmark.hxx>
+#include <unoport.hxx>
+#include <unotbl.hxx>
+#include <unoidx.hxx>
+#include <unoframe.hxx>
+#include <unofield.hxx>
+#include <unometa.hxx>
+#include <unodraw.hxx>
+#include <unoredline.hxx>
+#include <unomap.hxx>
+#include <unoprnms.hxx>
+#include <unoparagraph.hxx>
+#include <unocrsrhelper.hxx>
+#include <docsh.hxx>
+#include <docary.hxx>
+#include <doc.hxx>
+#include <IDocumentUndoRedo.hxx>
+#include <redline.hxx>
+#include <swundo.hxx>
+#include <section.hxx>
+#include <IMark.hxx>
+#include <fmtanchr.hxx>
+#include <fmtcntnt.hxx>
+#include <crsskip.hxx>
+#include <ndtxt.hxx>
+
+
+using namespace ::com::sun::star;
+using ::rtl::OUString;
+
+
+const sal_Char cInvalidObject[] = "this object is invalid";
+
+/******************************************************************
+ * SwXText
+ ******************************************************************/
+class SwXText::Impl
+{
+
+public:
+ SwXText & m_rThis;
+ SfxItemPropertySet const& m_rPropSet;
+ const enum CursorType m_eType;
+ SwDoc * m_pDoc;
+ bool m_bIsValid;
+
+ Impl( SwXText & rThis,
+ SwDoc *const pDoc, const enum CursorType eType)
+ : m_rThis(rThis)
+ , m_rPropSet(*aSwMapProvider.GetPropertySet(PROPERTY_MAP_TEXT))
+ , m_eType(eType)
+ , m_pDoc(pDoc)
+ , m_bIsValid(0 != pDoc)
+ {
+ }
+
+ uno::Reference< text::XTextRange >
+ finishOrAppendParagraph(
+ const bool bFinish,
+ const uno::Sequence< beans::PropertyValue >&
+ rCharacterAndParagraphProperties)
+ throw (lang::IllegalArgumentException, uno::RuntimeException);
+
+ sal_Int16 ComparePositions(
+ const uno::Reference<text::XTextRange>& xPos1,
+ const uno::Reference<text::XTextRange>& xPos2)
+ throw (lang::IllegalArgumentException, uno::RuntimeException);
+
+ bool CheckForOwnMember(const SwPaM & rPaM)
+ throw (lang::IllegalArgumentException, uno::RuntimeException);
+
+ void ConvertCell(
+ const bool bFirstCell,
+ const uno::Sequence< uno::Reference< text::XTextRange > > & rCell,
+ ::std::vector<SwNodeRange> & rRowNodes,
+ ::std::auto_ptr< SwPaM > & rpFirstPaM,
+ SwPaM & rLastPaM,
+ bool & rbExcept);
+
+};
+
+SwXText::SwXText(SwDoc *const pDoc, const enum CursorType eType)
+ : m_pImpl( new SwXText::Impl(*this, pDoc, eType) )
+{
+}
+
+SwXText::~SwXText()
+{
+}
+
+const SwDoc * SwXText::GetDoc() const
+{
+ return m_pImpl->m_pDoc;
+}
+ SwDoc * SwXText::GetDoc()
+{
+ return m_pImpl->m_pDoc;
+}
+
+bool SwXText::IsValid() const
+{
+ return m_pImpl->m_bIsValid;
+}
+
+void SwXText::Invalidate()
+{
+ m_pImpl->m_bIsValid = false;
+}
+
+void SwXText::SetDoc(SwDoc *const pDoc)
+{
+ OSL_ENSURE(!m_pImpl->m_pDoc || !pDoc,
+ "SwXText::SetDoc: already have a doc?");
+ m_pImpl->m_pDoc = pDoc;
+ m_pImpl->m_bIsValid = (0 != pDoc);
+}
+
+void
+SwXText::PrepareForAttach(uno::Reference< text::XTextRange > &, const SwPaM &)
+{
+}
+
+bool SwXText::CheckForOwnMemberMeta(const SwPaM &, const bool)
+ throw (lang::IllegalArgumentException, uno::RuntimeException)
+{
+ OSL_ENSURE(CURSOR_META != m_pImpl->m_eType, "should not be called!");
+ return false;
+}
+
+const SwStartNode *SwXText::GetStartNode() const
+{
+ return GetDoc()->GetNodes().GetEndOfContent().StartOfSectionNode();
+}
+
+uno::Reference< text::XTextCursor >
+SwXText::CreateCursor() throw (uno::RuntimeException)
+{
+ uno::Reference< text::XTextCursor > xRet;
+ if(IsValid())
+ {
+ SwNode& rNode = GetDoc()->GetNodes().GetEndOfContent();
+ SwPosition aPos(rNode);
+ xRet = static_cast<text::XWordCursor*>(
+ new SwXTextCursor(*GetDoc(), this, m_pImpl->m_eType, aPos));
+ xRet->gotoStart(sal_False);
+ }
+ return xRet;
+}
+
+uno::Any SAL_CALL
+SwXText::queryInterface(const uno::Type& rType) throw (uno::RuntimeException)
+{
+ uno::Any aRet;
+ if (rType == text::XText::static_type())
+ {
+ aRet <<= uno::Reference< text::XText >(this);
+ }
+ else if (rType == text::XSimpleText::static_type())
+ {
+ aRet <<= uno::Reference< text::XSimpleText >(this);
+ }
+ else if (rType == text::XTextRange::static_type())
+ {
+ aRet <<= uno::Reference< text::XTextRange>(this);
+ }
+ else if (rType == text::XTextRangeCompare::static_type())
+ {
+ aRet <<= uno::Reference< text::XTextRangeCompare >(this);
+ }
+ else if (rType == lang::XTypeProvider::static_type())
+ {
+ aRet <<= uno::Reference< lang::XTypeProvider >(this);
+ }
+ else if (rType == text::XRelativeTextContentInsert::static_type())
+ {
+ aRet <<= uno::Reference< text::XRelativeTextContentInsert >(this);
+ }
+ else if (rType == text::XRelativeTextContentRemove::static_type())
+ {
+ aRet <<= uno::Reference< text::XRelativeTextContentRemove >(this);
+ }
+ else if (rType == beans::XPropertySet::static_type())
+ {
+ aRet <<= uno::Reference< beans::XPropertySet >(this);
+ }
+ else if (rType == lang::XUnoTunnel::static_type())
+ {
+ aRet <<= uno::Reference< lang::XUnoTunnel >(this);
+ }
+ else if (rType == text::XTextAppendAndConvert::static_type())
+ {
+ aRet <<= uno::Reference< text::XTextAppendAndConvert >(this);
+ }
+ else if (rType == text::XTextAppend::static_type())
+ {
+ aRet <<= uno::Reference< text::XTextAppend >(this);
+ }
+ else if (rType == text::XTextPortionAppend::static_type())
+ {
+ aRet <<= uno::Reference< text::XTextPortionAppend >(this);
+ }
+ else if (rType == text::XParagraphAppend::static_type())
+ {
+ aRet <<= uno::Reference< text::XParagraphAppend >(this);
+ }
+ else if (rType == text::XTextConvert::static_type() )
+ {
+ aRet <<= uno::Reference< text::XTextConvert >(this);
+ }
+ else if (rType == text::XTextContentAppend::static_type())
+ {
+ aRet <<= uno::Reference< text::XTextContentAppend >(this);
+ }
+ else if(rType == text::XTextCopy::static_type())
+ {
+ aRet <<= uno::Reference< text::XTextCopy >( this );
+ }
+ return aRet;
+}
+
+uno::Sequence< uno::Type > SAL_CALL
+SwXText::getTypes() throw (uno::RuntimeException)
+{
+ uno::Sequence< uno::Type > aRet(12);
+ uno::Type* pTypes = aRet.getArray();
+ pTypes[0] = text::XText::static_type();
+ pTypes[1] = text::XTextRangeCompare::static_type();
+ pTypes[2] = text::XRelativeTextContentInsert::static_type();
+ pTypes[3] = text::XRelativeTextContentRemove::static_type();
+ pTypes[4] = lang::XUnoTunnel::static_type();
+ pTypes[5] = beans::XPropertySet::static_type();
+ pTypes[6] = text::XTextPortionAppend::static_type();
+ pTypes[7] = text::XParagraphAppend::static_type();
+ pTypes[8] = text::XTextContentAppend::static_type();
+ pTypes[9] = text::XTextConvert::static_type();
+ pTypes[10] = text::XTextAppend::static_type();
+ pTypes[11] = text::XTextAppendAndConvert::static_type();
+
+ return aRet;
+}
+
+// belongs the range in the text ? insert it then.
+void SAL_CALL
+SwXText::insertString(const uno::Reference< text::XTextRange >& xTextRange,
+ const OUString& rString, sal_Bool bAbsorb)
+throw (uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+
+ if (!xTextRange.is())
+ {
+ throw uno::RuntimeException();
+ }
+ if (!GetDoc())
+ {
+ throw uno::RuntimeException();
+ }
+ const uno::Reference<lang::XUnoTunnel> xRangeTunnel(xTextRange,
+ uno::UNO_QUERY);
+ SwXTextRange *const pRange =
+ ::sw::UnoTunnelGetImplementation<SwXTextRange>(xRangeTunnel);
+ OTextCursorHelper *const pCursor =
+ ::sw::UnoTunnelGetImplementation<OTextCursorHelper>(xRangeTunnel);
+ if ((!pRange || pRange ->GetDoc() != GetDoc()) &&
+ (!pCursor || pCursor->GetDoc() != GetDoc()))
+ {
+ throw uno::RuntimeException();
+ }
+
+ const SwStartNode *const pOwnStartNode = GetStartNode();
+ SwPaM aPam(GetDoc()->GetNodes());
+ const SwPaM * pPam(0);
+ if (pCursor)
+ {
+ pPam = pCursor->GetPaM();
+ }
+ else // pRange
+ {
+ if (pRange->GetPositions(aPam))
+ {
+ pPam = &aPam;
+ }
+ }
+ if (!pPam)
+ {
+ throw uno::RuntimeException();
+ }
+
+ const SwStartNode* pTmp(pPam->GetNode()->StartOfSectionNode());
+ while (pTmp && pTmp->IsSectionNode())
+ {
+ pTmp = pTmp->StartOfSectionNode();
+ }
+ if (!pOwnStartNode || (pOwnStartNode != pTmp))
+ {
+ throw uno::RuntimeException();
+ }
+
+ bool bForceExpandHints( false );
+ if (CURSOR_META == m_pImpl->m_eType)
+ {
+ try
+ {
+ bForceExpandHints = CheckForOwnMemberMeta(*pPam, bAbsorb);
+ }
+ catch (lang::IllegalArgumentException & iae)
+ {
+ // stupid method not allowed to throw iae
+ throw uno::RuntimeException(iae.Message, 0);
+ }
+ }
+ if (bAbsorb)
+ {
+ //!! scan for CR characters and inserting the paragraph breaks
+ //!! has to be done in the called function.
+ //!! Implemented in SwXTextRange::DeleteAndInsert
+ if (pCursor)
+ {
+ SwXTextCursor * const pTextCursor(
+ dynamic_cast<SwXTextCursor*>(pCursor) );
+ if (pTextCursor)
+ {
+ pTextCursor->DeleteAndInsert(rString, bForceExpandHints);
+ }
+ else
+ {
+ xTextRange->setString(rString);
+ }
+ }
+ else
+ {
+ pRange->DeleteAndInsert(rString, bForceExpandHints);
+ }
+ }
+ else
+ {
+ // create a PaM positioned before the parameter PaM,
+ // so the text is inserted before
+ UnoActionContext aContext(GetDoc());
+ SwPaM aInsertPam(*pPam->Start());
+ ::sw::GroupUndoGuard const undoGuard(GetDoc()->GetIDocumentUndoRedo());
+ SwUnoCursorHelper::DocInsertStringSplitCR(
+ *GetDoc(), aInsertPam, rString, bForceExpandHints );
+ }
+}
+
+void SAL_CALL
+SwXText::insertControlCharacter(
+ const uno::Reference< text::XTextRange > & xTextRange,
+ sal_Int16 nControlCharacter, sal_Bool bAbsorb)
+throw (lang::IllegalArgumentException, uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+
+ if (!xTextRange.is())
+ {
+ throw lang::IllegalArgumentException();
+ }
+ if (!GetDoc())
+ {
+ throw uno::RuntimeException();
+ }
+
+ SwUnoInternalPaM aPam(*GetDoc());
+ if (!::sw::XTextRangeToSwPaM(aPam, xTextRange))
+ {
+ throw uno::RuntimeException();
+ }
+ const bool bForceExpandHints(CheckForOwnMemberMeta(aPam, bAbsorb));
+
+ const enum IDocumentContentOperations::InsertFlags nInsertFlags =
+ (bForceExpandHints)
+ ? static_cast<IDocumentContentOperations::InsertFlags>(
+ IDocumentContentOperations::INS_FORCEHINTEXPAND |
+ IDocumentContentOperations::INS_EMPTYEXPAND)
+ : IDocumentContentOperations::INS_EMPTYEXPAND;
+
+ SwPaM aTmp(*aPam.Start());
+ if (bAbsorb && aPam.HasMark())
+ {
+ m_pImpl->m_pDoc->DeleteAndJoin(aPam);
+ }
+
+ sal_Unicode cIns = 0;
+ switch (nControlCharacter)
+ {
+ case text::ControlCharacter::PARAGRAPH_BREAK :
+ // a table cell now becomes an ordinary text cell!
+ m_pImpl->m_pDoc->ClearBoxNumAttrs( aTmp.GetPoint()->nNode );
+ m_pImpl->m_pDoc->SplitNode( *aTmp.GetPoint(), sal_False );
+ break;
+ case text::ControlCharacter::APPEND_PARAGRAPH:
+ {
+ m_pImpl->m_pDoc->ClearBoxNumAttrs( aTmp.GetPoint()->nNode );
+ m_pImpl->m_pDoc->AppendTxtNode( *aTmp.GetPoint() );
+
+ const uno::Reference<lang::XUnoTunnel> xRangeTunnel(
+ xTextRange, uno::UNO_QUERY);
+ SwXTextRange *const pRange =
+ ::sw::UnoTunnelGetImplementation<SwXTextRange>(xRangeTunnel);
+ OTextCursorHelper *const pCursor =
+ ::sw::UnoTunnelGetImplementation<OTextCursorHelper>(
+ xRangeTunnel);
+ if (pRange)
+ {
+ pRange->SetPositions(aTmp);
+ }
+ else if (pCursor)
+ {
+ SwPaM *const pCrsr = pCursor->GetPaM();
+ *pCrsr->GetPoint() = *aTmp.GetPoint();
+ pCrsr->DeleteMark();
+ }
+ }
+ break;
+ case text::ControlCharacter::LINE_BREAK: cIns = 10; break;
+ case text::ControlCharacter::SOFT_HYPHEN: cIns = CHAR_SOFTHYPHEN; break;
+ case text::ControlCharacter::HARD_HYPHEN: cIns = CHAR_HARDHYPHEN; break;
+ case text::ControlCharacter::HARD_SPACE: cIns = CHAR_HARDBLANK; break;
+ }
+ if (cIns)
+ {
+ m_pImpl->m_pDoc->InsertString( aTmp, cIns, nInsertFlags );
+ }
+
+ if (bAbsorb)
+ {
+ const uno::Reference<lang::XUnoTunnel> xRangeTunnel(
+ xTextRange, uno::UNO_QUERY);
+ SwXTextRange *const pRange =
+ ::sw::UnoTunnelGetImplementation<SwXTextRange>(xRangeTunnel);
+ OTextCursorHelper *const pCursor =
+ ::sw::UnoTunnelGetImplementation<OTextCursorHelper>(xRangeTunnel);
+
+ SwCursor aCrsr(*aTmp.GetPoint(),0,false);
+ SwUnoCursorHelper::SelectPam(aCrsr, true);
+ aCrsr.Left(1, CRSR_SKIP_CHARS, sal_False, sal_False);
+ //hier muss der uebergebene PaM umgesetzt werden:
+ if (pRange)
+ {
+ pRange->SetPositions(aCrsr);
+ }
+ else
+ {
+ SwPaM *const pUnoCrsr = pCursor->GetPaM();
+ *pUnoCrsr->GetPoint() = *aCrsr.GetPoint();
+ if (aCrsr.HasMark())
+ {
+ pUnoCrsr->SetMark();
+ *pUnoCrsr->GetMark() = *aCrsr.GetMark();
+ }
+ else
+ {
+ pUnoCrsr->DeleteMark();
+ }
+ }
+ }
+}
+
+void SAL_CALL
+SwXText::insertTextContent(
+ const uno::Reference< text::XTextRange > & xRange,
+ const uno::Reference< text::XTextContent > & xContent,
+ sal_Bool bAbsorb)
+throw (lang::IllegalArgumentException, uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+
+ if (!xRange.is())
+ {
+ lang::IllegalArgumentException aIllegal;
+ aIllegal.Message = C2U("first parameter invalid;");
+ throw aIllegal;
+ }
+ if (!xContent.is())
+ {
+ lang::IllegalArgumentException aIllegal;
+ aIllegal.Message += C2U("second parameter invalid");
+ throw aIllegal;
+ }
+ if(!GetDoc())
+ {
+ uno::RuntimeException aRuntime;
+ aRuntime.Message = C2U(cInvalidObject);
+ throw aRuntime;
+ }
+
+ SwUnoInternalPaM aPam(*GetDoc());
+ if (!::sw::XTextRangeToSwPaM(aPam, xRange))
+ {
+ lang::IllegalArgumentException aIllegal;
+ aIllegal.Message = C2U("first parameter invalid");
+ throw aIllegal;
+ }
+ // first test if the range is at the right position, then call
+ // xContent->attach
+ const SwStartNode* pOwnStartNode = GetStartNode();
+ SwStartNodeType eSearchNodeType = SwNormalStartNode;
+ switch (m_pImpl->m_eType)
+ {
+ case CURSOR_FRAME: eSearchNodeType = SwFlyStartNode; break;
+ case CURSOR_TBLTEXT: eSearchNodeType = SwTableBoxStartNode; break;
+ case CURSOR_FOOTNOTE: eSearchNodeType = SwFootnoteStartNode; break;
+ case CURSOR_HEADER: eSearchNodeType = SwHeaderStartNode; break;
+ case CURSOR_FOOTER: eSearchNodeType = SwFooterStartNode; break;
+ //case CURSOR_INVALID:
+ //case CURSOR_BODY:
+ default:
+ break;
+ }
+
+ const SwStartNode* pTmp =
+ aPam.GetNode()->FindSttNodeByType(eSearchNodeType);
+
+ // ignore SectionNodes
+ while (pTmp && pTmp->IsSectionNode())
+ {
+ pTmp = pTmp->StartOfSectionNode();
+ }
+ // if the document starts with a section
+ while (pOwnStartNode->IsSectionNode())
+ {
+ pOwnStartNode = pOwnStartNode->StartOfSectionNode();
+ }
+ // this checks if (this) and xRange are in the same text::XText interface
+ if (pOwnStartNode != pTmp)
+ {
+ uno::RuntimeException aRunException;
+ aRunException.Message = C2U("text interface and cursor not related");
+ throw aRunException;
+ }
+
+ const bool bForceExpandHints(CheckForOwnMemberMeta(aPam, bAbsorb));
+
+ // special treatment for Contents that do not replace the range, but
+ // instead are "overlaid"
+ const uno::Reference<lang::XUnoTunnel> xContentTunnel(xContent,
+ uno::UNO_QUERY);
+ if (!xContentTunnel.is())
+ {
+ lang::IllegalArgumentException aArgException;
+ aArgException.Message =
+ C2U("text content does not support lang::XUnoTunnel");
+ throw aArgException;
+ }
+ SwXDocumentIndexMark *const pDocumentIndexMark =
+ ::sw::UnoTunnelGetImplementation<SwXDocumentIndexMark>(xContentTunnel);
+ SwXTextSection *const pSection =
+ ::sw::UnoTunnelGetImplementation<SwXTextSection>(xContentTunnel);
+ SwXBookmark *const pBookmark =
+ ::sw::UnoTunnelGetImplementation<SwXBookmark>(xContentTunnel);
+ SwXReferenceMark *const pReferenceMark =
+ ::sw::UnoTunnelGetImplementation<SwXReferenceMark>(xContentTunnel);
+ SwXMeta *const pMeta =
+ ::sw::UnoTunnelGetImplementation<SwXMeta>(xContentTunnel);
+
+ const bool bAttribute = pBookmark || pDocumentIndexMark
+ || pSection || pReferenceMark || pMeta;
+
+ if (bAbsorb && !bAttribute)
+ {
+ xRange->setString(aEmptyStr);
+ }
+ uno::Reference< text::XTextRange > xTempRange =
+ (bAttribute && bAbsorb) ? xRange : xRange->getStart();
+ if (bForceExpandHints)
+ {
+ // if necessary, replace xTempRange with a new SwXTextCursor
+ PrepareForAttach(xTempRange, aPam);
+ }
+ xContent->attach(xTempRange);
+}
+
+void SAL_CALL
+SwXText::insertTextContentBefore(
+ const uno::Reference< text::XTextContent>& xNewContent,
+ const uno::Reference< text::XTextContent>& xSuccessor)
+throw (lang::IllegalArgumentException, uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+
+ if(!GetDoc())
+ {
+ uno::RuntimeException aRuntime;
+ aRuntime.Message = C2U(cInvalidObject);
+ throw aRuntime;
+ }
+
+ const uno::Reference<lang::XUnoTunnel> xParaTunnel(xNewContent,
+ uno::UNO_QUERY);
+ SwXParagraph *const pPara =
+ ::sw::UnoTunnelGetImplementation<SwXParagraph>(xParaTunnel);
+ if (!pPara || !pPara->IsDescriptor() || !xSuccessor.is())
+ {
+ throw lang::IllegalArgumentException();
+ }
+
+ sal_Bool bRet = sal_False;
+ const uno::Reference<lang::XUnoTunnel> xSuccTunnel(xSuccessor,
+ uno::UNO_QUERY);
+ SwXTextSection *const pXSection =
+ ::sw::UnoTunnelGetImplementation<SwXTextSection>(xSuccTunnel);
+ SwXTextTable *const pXTable =
+ ::sw::UnoTunnelGetImplementation<SwXTextTable>(xSuccTunnel);
+ SwFrmFmt *const pTableFmt = (pXTable) ? pXTable->GetFrmFmt() : 0;
+ SwTxtNode * pTxtNode = 0;
+ if(pTableFmt && pTableFmt->GetDoc() == GetDoc())
+ {
+ SwTable *const pTable = SwTable::FindTable( pTableFmt );
+ SwTableNode *const pTblNode = pTable->GetTableNode();
+
+ const SwNodeIndex aTblIdx( *pTblNode, -1 );
+ SwPosition aBefore(aTblIdx);
+ bRet = GetDoc()->AppendTxtNode( aBefore );
+ pTxtNode = aBefore.nNode.GetNode().GetTxtNode();
+ }
+ else if (pXSection && pXSection->GetFmt() &&
+ pXSection->GetFmt()->GetDoc() == GetDoc())
+ {
+ SwSectionFmt *const pSectFmt = pXSection->GetFmt();
+ SwSectionNode *const pSectNode = pSectFmt->GetSectionNode();
+
+ const SwNodeIndex aSectIdx( *pSectNode, -1 );
+ SwPosition aBefore(aSectIdx);
+ bRet = GetDoc()->AppendTxtNode( aBefore );
+ pTxtNode = aBefore.nNode.GetNode().GetTxtNode();
+ }
+ if (!bRet || !pTxtNode)
+ {
+ throw lang::IllegalArgumentException();
+ }
+ pPara->attachToText(*this, *pTxtNode);
+}
+
+void SAL_CALL
+SwXText::insertTextContentAfter(
+ const uno::Reference< text::XTextContent>& xNewContent,
+ const uno::Reference< text::XTextContent>& xPredecessor)
+throw (lang::IllegalArgumentException, uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+
+ if(!GetDoc())
+ {
+ throw uno::RuntimeException();
+ }
+
+ const uno::Reference<lang::XUnoTunnel> xParaTunnel(xNewContent,
+ uno::UNO_QUERY);
+ SwXParagraph *const pPara =
+ ::sw::UnoTunnelGetImplementation<SwXParagraph>(xParaTunnel);
+ if(!pPara || !pPara->IsDescriptor() || !xPredecessor.is())
+ {
+ throw lang::IllegalArgumentException();
+ }
+
+ const uno::Reference<lang::XUnoTunnel> xPredTunnel(xPredecessor,
+ uno::UNO_QUERY);
+ SwXTextSection *const pXSection =
+ ::sw::UnoTunnelGetImplementation<SwXTextSection>(xPredTunnel);
+ SwXTextTable *const pXTable =
+ ::sw::UnoTunnelGetImplementation<SwXTextTable>(xPredTunnel);
+ SwFrmFmt *const pTableFmt = (pXTable) ? pXTable->GetFrmFmt() : 0;
+ sal_Bool bRet = sal_False;
+ SwTxtNode * pTxtNode = 0;
+ if(pTableFmt && pTableFmt->GetDoc() == GetDoc())
+ {
+ SwTable *const pTable = SwTable::FindTable( pTableFmt );
+ SwTableNode *const pTblNode = pTable->GetTableNode();
+
+ SwEndNode *const pTableEnd = pTblNode->EndOfSectionNode();
+ SwPosition aTableEnd(*pTableEnd);
+ bRet = GetDoc()->AppendTxtNode( aTableEnd );
+ pTxtNode = aTableEnd.nNode.GetNode().GetTxtNode();
+ }
+ else if (pXSection && pXSection->GetFmt() &&
+ pXSection->GetFmt()->GetDoc() == GetDoc())
+ {
+ SwSectionFmt *const pSectFmt = pXSection->GetFmt();
+ SwSectionNode *const pSectNode = pSectFmt->GetSectionNode();
+ SwEndNode *const pEnd = pSectNode->EndOfSectionNode();
+ SwPosition aEnd(*pEnd);
+ bRet = GetDoc()->AppendTxtNode( aEnd );
+ pTxtNode = aEnd.nNode.GetNode().GetTxtNode();
+ }
+ if (!bRet || !pTxtNode)
+ {
+ throw lang::IllegalArgumentException();
+ }
+ pPara->attachToText(*this, *pTxtNode);
+}
+
+void SAL_CALL
+SwXText::removeTextContentBefore(
+ const uno::Reference< text::XTextContent>& xSuccessor)
+throw (lang::IllegalArgumentException, uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+
+ if(!GetDoc())
+ {
+ uno::RuntimeException aRuntime;
+ aRuntime.Message = C2U(cInvalidObject);
+ throw aRuntime;
+ }
+
+ sal_Bool bRet = sal_False;
+ const uno::Reference<lang::XUnoTunnel> xSuccTunnel(xSuccessor,
+ uno::UNO_QUERY);
+ SwXTextSection *const pXSection =
+ ::sw::UnoTunnelGetImplementation<SwXTextSection>(xSuccTunnel);
+ SwXTextTable *const pXTable =
+ ::sw::UnoTunnelGetImplementation<SwXTextTable>(xSuccTunnel);
+ SwFrmFmt *const pTableFmt = (pXTable) ? pXTable->GetFrmFmt() : 0;
+ if(pTableFmt && pTableFmt->GetDoc() == GetDoc())
+ {
+ SwTable *const pTable = SwTable::FindTable( pTableFmt );
+ SwTableNode *const pTblNode = pTable->GetTableNode();
+
+ const SwNodeIndex aTblIdx( *pTblNode, -1 );
+ if(aTblIdx.GetNode().IsTxtNode())
+ {
+ SwPaM aBefore(aTblIdx);
+ bRet = GetDoc()->DelFullPara( aBefore );
+ }
+ }
+ else if (pXSection && pXSection->GetFmt() &&
+ pXSection->GetFmt()->GetDoc() == GetDoc())
+ {
+ SwSectionFmt *const pSectFmt = pXSection->GetFmt();
+ SwSectionNode *const pSectNode = pSectFmt->GetSectionNode();
+
+ const SwNodeIndex aSectIdx( *pSectNode, -1 );
+ if(aSectIdx.GetNode().IsTxtNode())
+ {
+ SwPaM aBefore(aSectIdx);
+ bRet = GetDoc()->DelFullPara( aBefore );
+ }
+ }
+ if(!bRet)
+ {
+ throw lang::IllegalArgumentException();
+ }
+}
+
+void SAL_CALL
+SwXText::removeTextContentAfter(
+ const uno::Reference< text::XTextContent>& xPredecessor)
+throw (lang::IllegalArgumentException, uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+
+ if(!GetDoc())
+ {
+ uno::RuntimeException aRuntime;
+ aRuntime.Message = C2U(cInvalidObject);
+ throw aRuntime;
+ }
+
+ sal_Bool bRet = sal_False;
+ const uno::Reference<lang::XUnoTunnel> xPredTunnel(xPredecessor,
+ uno::UNO_QUERY);
+ SwXTextSection *const pXSection =
+ ::sw::UnoTunnelGetImplementation<SwXTextSection>(xPredTunnel);
+ SwXTextTable *const pXTable =
+ ::sw::UnoTunnelGetImplementation<SwXTextTable>(xPredTunnel);
+ SwFrmFmt *const pTableFmt = (pXTable) ? pXTable->GetFrmFmt() : 0;
+ if(pTableFmt && pTableFmt->GetDoc() == GetDoc())
+ {
+ SwTable *const pTable = SwTable::FindTable( pTableFmt );
+ SwTableNode *const pTblNode = pTable->GetTableNode();
+ SwEndNode *const pTableEnd = pTblNode->EndOfSectionNode();
+
+ const SwNodeIndex aTblIdx( *pTableEnd, 1 );
+ if(aTblIdx.GetNode().IsTxtNode())
+ {
+ SwPaM aPaM(aTblIdx);
+ bRet = GetDoc()->DelFullPara( aPaM );
+ }
+ }
+ else if (pXSection && pXSection->GetFmt() &&
+ pXSection->GetFmt()->GetDoc() == GetDoc())
+ {
+ SwSectionFmt *const pSectFmt = pXSection->GetFmt();
+ SwSectionNode *const pSectNode = pSectFmt->GetSectionNode();
+ SwEndNode *const pEnd = pSectNode->EndOfSectionNode();
+ const SwNodeIndex aSectIdx( *pEnd, 1 );
+ if(aSectIdx.GetNode().IsTxtNode())
+ {
+ SwPaM aAfter(aSectIdx);
+ bRet = GetDoc()->DelFullPara( aAfter );
+ }
+ }
+ if(!bRet)
+ {
+ throw lang::IllegalArgumentException();
+ }
+}
+
+void SAL_CALL
+SwXText::removeTextContent(
+ const uno::Reference< text::XTextContent > & xContent)
+throw (container::NoSuchElementException, uno::RuntimeException)
+{
+ // forward: need no solar mutex here
+ if(!xContent.is())
+ {
+ uno::RuntimeException aRuntime;
+ aRuntime.Message = C2U("first parameter invalid");
+ throw aRuntime;
+ }
+ xContent->dispose();
+}
+
+uno::Reference< text::XText > SAL_CALL
+SwXText::getText() throw (uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+
+ const uno::Reference< text::XText > xRet(this);
+ return xRet;
+}
+
+uno::Reference< text::XTextRange > SAL_CALL
+SwXText::getStart() throw (uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+
+ const uno::Reference< text::XTextCursor > xRef = CreateCursor();
+ if(!xRef.is())
+ {
+ uno::RuntimeException aRuntime;
+ aRuntime.Message = C2U(cInvalidObject);
+ throw aRuntime;
+ }
+ xRef->gotoStart(sal_False);
+ const uno::Reference< text::XTextRange > xRet(xRef, uno::UNO_QUERY);
+ return xRet;
+}
+
+uno::Reference< text::XTextRange > SAL_CALL
+SwXText::getEnd() throw (uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+
+ const uno::Reference< text::XTextCursor > xRef = CreateCursor();
+ if(!xRef.is())
+ {
+ uno::RuntimeException aRuntime;
+ aRuntime.Message = C2U(cInvalidObject);
+ throw aRuntime;
+ }
+ xRef->gotoEnd(sal_False);
+ const uno::Reference< text::XTextRange > xRet(xRef, uno::UNO_QUERY);
+ return xRet;
+}
+
+OUString SAL_CALL SwXText::getString() throw (uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+
+ const uno::Reference< text::XTextCursor > xRet = CreateCursor();
+ if(!xRet.is())
+ {
+ uno::RuntimeException aRuntime;
+ aRuntime.Message = C2U(cInvalidObject);
+ throw aRuntime;
+ }
+ xRet->gotoEnd(sal_True);
+ return xRet->getString();
+}
+
+void SAL_CALL
+SwXText::setString(const OUString& rString) throw (uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+
+ if (!GetDoc())
+ {
+ uno::RuntimeException aRuntime;
+ aRuntime.Message = C2U(cInvalidObject);
+ throw aRuntime;
+ }
+
+ const SwStartNode* pStartNode = GetStartNode();
+ if (!pStartNode)
+ {
+ throw uno::RuntimeException();
+ }
+
+ GetDoc()->GetIDocumentUndoRedo().StartUndo(UNDO_START, NULL);
+ //insert an empty paragraph at the start and at the end to ensure that
+ //all tables and sections can be removed by the selecting text::XTextCursor
+ if (CURSOR_META != m_pImpl->m_eType)
+ {
+ SwPosition aStartPos(*pStartNode);
+ const SwEndNode* pEnd = pStartNode->EndOfSectionNode();
+ SwNodeIndex aEndIdx(*pEnd);
+ aEndIdx--;
+ //the inserting of nodes should only be done if really necessary
+ //to prevent #97924# (removes paragraph attributes when setting the text
+ //e.g. of a table cell
+ sal_Bool bInsertNodes = sal_False;
+ SwNodeIndex aStartIdx(*pStartNode);
+ do
+ {
+ aStartIdx++;
+ SwNode& rCurrentNode = aStartIdx.GetNode();
+ if(rCurrentNode.GetNodeType() == ND_SECTIONNODE
+ ||rCurrentNode.GetNodeType() == ND_TABLENODE)
+ {
+ bInsertNodes = sal_True;
+ break;
+ }
+ }
+ while(aStartIdx < aEndIdx);
+ if(bInsertNodes)
+ {
+ GetDoc()->AppendTxtNode( aStartPos );
+ SwPosition aEndPos(aEndIdx.GetNode());
+ SwPaM aPam(aEndPos);
+ GetDoc()->AppendTxtNode( *aPam.Start() );
+ }
+ }
+
+ const uno::Reference< text::XTextCursor > xRet = CreateCursor();
+ if(!xRet.is())
+ {
+ GetDoc()->GetIDocumentUndoRedo().EndUndo(UNDO_END, NULL);
+ uno::RuntimeException aRuntime;
+ aRuntime.Message = C2U(cInvalidObject);
+ throw aRuntime;
+ }
+ xRet->gotoEnd(sal_True);
+ xRet->setString(rString);
+ GetDoc()->GetIDocumentUndoRedo().EndUndo(UNDO_END, NULL);
+}
+
+//FIXME why is CheckForOwnMember duplicated in some insert methods?
+// Description: Checks if pRange/pCursor are member of the same text interface.
+// Only one of the pointers has to be set!
+bool SwXText::Impl::CheckForOwnMember(
+ const SwPaM & rPaM)
+throw (lang::IllegalArgumentException, uno::RuntimeException)
+{
+ const uno::Reference<text::XTextCursor> xOwnCursor(m_rThis.CreateCursor());
+
+ const uno::Reference<lang::XUnoTunnel> xTunnel(xOwnCursor, uno::UNO_QUERY);
+ OTextCursorHelper *const pOwnCursor =
+ ::sw::UnoTunnelGetImplementation<OTextCursorHelper>(xTunnel);
+ DBG_ASSERT(pOwnCursor, "OTextCursorHelper::getUnoTunnelId() ??? ");
+ const SwStartNode* pOwnStartNode =
+ pOwnCursor->GetPaM()->GetNode()->StartOfSectionNode();
+ SwStartNodeType eSearchNodeType = SwNormalStartNode;
+ switch (m_eType)
+ {
+ case CURSOR_FRAME: eSearchNodeType = SwFlyStartNode; break;
+ case CURSOR_TBLTEXT: eSearchNodeType = SwTableBoxStartNode; break;
+ case CURSOR_FOOTNOTE: eSearchNodeType = SwFootnoteStartNode; break;
+ case CURSOR_HEADER: eSearchNodeType = SwHeaderStartNode; break;
+ case CURSOR_FOOTER: eSearchNodeType = SwFooterStartNode; break;
+ //case CURSOR_INVALID:
+ //case CURSOR_BODY:
+ default:
+ ;
+ }
+
+ SwNode const*const pSrcNode(rPaM.GetNode());
+ if (!pSrcNode) { return false; }
+ const SwStartNode* pTmp = pSrcNode->FindSttNodeByType(eSearchNodeType);
+
+ //SectionNodes ueberspringen
+ while(pTmp && pTmp->IsSectionNode())
+ {
+ pTmp = pTmp->StartOfSectionNode();
+ }
+
+ //if the document starts with a section
+ while(pOwnStartNode->IsSectionNode())
+ {
+ pOwnStartNode = pOwnStartNode->StartOfSectionNode();
+ }
+
+ //this checks if (this) and xRange are in the same text::XText interface
+ return (pOwnStartNode == pTmp);
+}
+
+sal_Int16
+SwXText::Impl::ComparePositions(
+ const uno::Reference<text::XTextRange>& xPos1,
+ const uno::Reference<text::XTextRange>& xPos2)
+throw (lang::IllegalArgumentException, uno::RuntimeException)
+{
+ SwUnoInternalPaM aPam1(*m_pDoc);
+ SwUnoInternalPaM aPam2(*m_pDoc);
+
+ if (!::sw::XTextRangeToSwPaM(aPam1, xPos1) ||
+ !::sw::XTextRangeToSwPaM(aPam2, xPos2))
+ {
+ throw lang::IllegalArgumentException();
+ }
+ if (!CheckForOwnMember(aPam1) || !CheckForOwnMember(aPam2))
+ {
+ throw lang::IllegalArgumentException();
+ }
+
+ sal_Int16 nCompare = 0;
+ SwPosition const*const pStart1 = aPam1.Start();
+ SwPosition const*const pStart2 = aPam2.Start();
+ if (*pStart1 < *pStart2)
+ {
+ nCompare = 1;
+ }
+ else if (*pStart1 > *pStart2)
+ {
+ nCompare = -1;
+ }
+ else
+ {
+ DBG_ASSERT(*pStart1 == *pStart2,
+ "SwPositions should be equal here");
+ nCompare = 0;
+ }
+
+ return nCompare;
+}
+
+sal_Int16 SAL_CALL
+SwXText::compareRegionStarts(
+ const uno::Reference<text::XTextRange>& xRange1,
+ const uno::Reference<text::XTextRange>& xRange2)
+throw (lang::IllegalArgumentException, uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+
+ if (!xRange1.is() || !xRange2.is())
+ {
+ throw lang::IllegalArgumentException();
+ }
+ const uno::Reference<text::XTextRange> xStart1 = xRange1->getStart();
+ const uno::Reference<text::XTextRange> xStart2 = xRange2->getStart();
+
+ return m_pImpl->ComparePositions(xStart1, xStart2);
+}
+
+sal_Int16 SAL_CALL
+SwXText::compareRegionEnds(
+ const uno::Reference<text::XTextRange>& xRange1,
+ const uno::Reference<text::XTextRange>& xRange2)
+throw (lang::IllegalArgumentException, uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+
+ if (!xRange1.is() || !xRange2.is())
+ {
+ throw lang::IllegalArgumentException();
+ }
+ uno::Reference<text::XTextRange> xEnd1 = xRange1->getEnd();
+ uno::Reference<text::XTextRange> xEnd2 = xRange2->getEnd();
+
+ return m_pImpl->ComparePositions(xEnd1, xEnd2);
+}
+
+uno::Reference< beans::XPropertySetInfo > SAL_CALL
+SwXText::getPropertySetInfo() throw(uno::RuntimeException)
+{
+ SolarMutexGuard g;
+
+ static uno::Reference< beans::XPropertySetInfo > xInfo =
+ m_pImpl->m_rPropSet.getPropertySetInfo();
+ return xInfo;
+}
+
+void SAL_CALL
+SwXText::setPropertyValue(const ::rtl::OUString& /*aPropertyName*/,
+ const uno::Any& /*aValue*/)
+throw (beans::UnknownPropertyException, beans::PropertyVetoException,
+ lang::IllegalArgumentException, lang::WrappedTargetException,
+ uno::RuntimeException)
+{
+ throw lang::IllegalArgumentException();
+}
+
+uno::Any SAL_CALL
+SwXText::getPropertyValue(
+ const ::rtl::OUString& rPropertyName)
+throw (beans::UnknownPropertyException, lang::WrappedTargetException,
+ uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+
+ if(!IsValid())
+ {
+ throw uno::RuntimeException();
+ }
+
+ SfxItemPropertySimpleEntry const*const pEntry =
+ m_pImpl->m_rPropSet.getPropertyMap()->getByName(rPropertyName);
+ if (!pEntry)
+ {
+ beans::UnknownPropertyException aExcept;
+ aExcept.Message = C2U("Unknown property: ");
+ aExcept.Message += rPropertyName;
+ throw aExcept;
+ }
+
+ uno::Any aRet;
+ switch (pEntry->nWID)
+ {
+// no code necessary - the redline is always located at the end node
+// case FN_UNO_REDLINE_NODE_START:
+// break;
+ case FN_UNO_REDLINE_NODE_END:
+ {
+ const SwRedlineTbl& rRedTbl = GetDoc()->GetRedlineTbl();
+ const sal_uInt16 nRedTblCount = rRedTbl.Count();
+ if (nRedTblCount > 0)
+ {
+ SwStartNode const*const pStartNode = GetStartNode();
+ const sal_uLong nOwnIndex = pStartNode->EndOfSectionIndex();
+ for (sal_uInt16 nRed = 0; nRed < nRedTblCount; nRed++)
+ {
+ SwRedline const*const pRedline = rRedTbl[nRed];
+ SwPosition const*const pRedStart = pRedline->Start();
+ const SwNodeIndex nRedNode = pRedStart->nNode;
+ if (nOwnIndex == nRedNode.GetIndex())
+ {
+ aRet <<= SwXRedlinePortion::CreateRedlineProperties(
+ *pRedline, sal_True);
+ break;
+ }
+ }
+ }
+ }
+ break;
+ }
+ return aRet;
+}
+
+void SAL_CALL
+SwXText::addPropertyChangeListener(
+ const ::rtl::OUString& /*rPropertyName*/,
+ const uno::Reference< beans::XPropertyChangeListener >& /*xListener*/)
+throw (beans::UnknownPropertyException, lang::WrappedTargetException,
+ uno::RuntimeException)
+{
+ OSL_FAIL("SwXText::addPropertyChangeListener(): not implemented");
+}
+
+void SAL_CALL
+SwXText::removePropertyChangeListener(
+ const ::rtl::OUString& /*rPropertyName*/,
+ const uno::Reference< beans::XPropertyChangeListener >& /*xListener*/)
+throw (beans::UnknownPropertyException, lang::WrappedTargetException,
+ uno::RuntimeException)
+{
+ OSL_FAIL("SwXText::removePropertyChangeListener(): not implemented");
+}
+
+void SAL_CALL
+SwXText::addVetoableChangeListener(
+ const ::rtl::OUString& /*rPropertyName*/,
+ const uno::Reference< beans::XVetoableChangeListener >& /*xListener*/)
+throw (beans::UnknownPropertyException, lang::WrappedTargetException,
+ uno::RuntimeException)
+{
+ OSL_FAIL("SwXText::addVetoableChangeListener(): not implemented");
+}
+
+void SAL_CALL
+SwXText::removeVetoableChangeListener(
+ const ::rtl::OUString& /*rPropertyName*/,
+ const uno::Reference< beans::XVetoableChangeListener >& /*xListener*/)
+throw (beans::UnknownPropertyException, lang::WrappedTargetException,
+ uno::RuntimeException)
+{
+ OSL_FAIL("SwXText::removeVetoableChangeListener(): not implemented");
+}
+
+const uno::Sequence< sal_Int8 > & SwXText::getUnoTunnelId()
+{
+ static uno::Sequence< sal_Int8 > aSeq = ::CreateUnoTunnelId();
+ return aSeq;
+}
+
+sal_Int64 SAL_CALL
+SwXText::getSomething(const uno::Sequence< sal_Int8 >& rId)
+throw (uno::RuntimeException)
+{
+ return ::sw::UnoTunnelImpl<SwXText>(rId, this);
+}
+
+uno::Reference< text::XTextRange > SAL_CALL
+SwXText::appendParagraph(
+ const uno::Sequence< beans::PropertyValue > & rProperties)
+throw (lang::IllegalArgumentException, uno::RuntimeException)
+{
+ SolarMutexGuard g;
+
+ return m_pImpl->finishOrAppendParagraph(false, rProperties);
+}
+
+uno::Reference< text::XTextRange > SAL_CALL
+SwXText::finishParagraph(
+ const uno::Sequence< beans::PropertyValue > & rProperties)
+throw (lang::IllegalArgumentException, uno::RuntimeException)
+{
+ SolarMutexGuard g;
+
+ return m_pImpl->finishOrAppendParagraph(true, rProperties);
+}
+
+uno::Reference< text::XTextRange >
+SwXText::Impl::finishOrAppendParagraph(
+ const bool bFinish,
+ const uno::Sequence< beans::PropertyValue > & rProperties)
+throw (lang::IllegalArgumentException, uno::RuntimeException)
+{
+ if (!m_bIsValid)
+ {
+ throw uno::RuntimeException();
+ }
+
+ const SwStartNode* pStartNode = m_rThis.GetStartNode();
+ if(!pStartNode)
+ {
+ throw uno::RuntimeException();
+ }
+
+ uno::Reference< text::XTextRange > xRet;
+ bool bIllegalException = false;
+ bool bRuntimeException = false;
+ ::rtl::OUString sMessage;
+ m_pDoc->GetIDocumentUndoRedo().StartUndo(UNDO_START , NULL);
+ // find end node, go backward - don't skip tables because the new
+ // paragraph has to be the last node
+ //aPam.Move( fnMoveBackward, fnGoNode );
+ SwPosition aInsertPosition(
+ SwNodeIndex( *pStartNode->EndOfSectionNode(), -1 ) );
+ SwPaM aPam(aInsertPosition);
+ m_pDoc->AppendTxtNode( *aPam.GetPoint() );
+ // remove attributes from the previous paragraph
+ m_pDoc->ResetAttrs(aPam);
+ // in case of finishParagraph the PaM needs to be moved to the
+ // previous paragraph
+ if (bFinish)
+ {
+ aPam.Move( fnMoveBackward, fnGoNode );
+ }
+ if (rProperties.getLength())
+ {
+ // now set the properties
+ SfxItemPropertySet const*const pParaPropSet =
+ aSwMapProvider.GetPropertySet(PROPERTY_MAP_PARAGRAPH);
+ SfxItemPropertyMap const*const pParagraphMap =
+ pParaPropSet->getPropertyMap();
+
+ const beans::PropertyValue* pValues = rProperties.getConstArray();
+
+ for (sal_Int32 nProp = 0; nProp < rProperties.getLength(); ++nProp)
+ {
+ if (!pParagraphMap->getByName(pValues[nProp].Name))
+ {
+ bIllegalException = true;
+ break;
+ }
+ try
+ {
+ SwUnoCursorHelper::SetPropertyValue(aPam, *pParaPropSet,
+ pValues[nProp].Name, pValues[nProp].Value);
+ }
+ catch (lang::IllegalArgumentException& rIllegal)
+ {
+ sMessage = rIllegal.Message;
+ bIllegalException = true;
+ break;
+ }
+ catch (uno::RuntimeException& rRuntime)
+ {
+ sMessage = rRuntime.Message;
+ bRuntimeException = true;
+ break;
+ }
+ }
+ }
+ m_pDoc->GetIDocumentUndoRedo().EndUndo(UNDO_END, NULL);
+ if (bIllegalException || bRuntimeException)
+ {
+ m_pDoc->GetIDocumentUndoRedo().Undo();
+ if (bIllegalException)
+ {
+ lang::IllegalArgumentException aEx;
+ aEx.Message = sMessage;
+ throw aEx;
+ }
+ else // if(bRuntimeException)
+ {
+ uno::RuntimeException aEx;
+ aEx.Message = sMessage;
+ throw aEx;
+ }
+ }
+ SwTxtNode *const pTxtNode( aPam.Start()->nNode.GetNode().GetTxtNode() );
+ OSL_ENSURE(pTxtNode, "no SwTxtNode?");
+ if (pTxtNode)
+ {
+ xRet.set(SwXParagraph::CreateXParagraph(*m_pDoc, *pTxtNode, &m_rThis),
+ uno::UNO_QUERY);
+ }
+
+ return xRet;
+}
+
+/*-------------------------------------------------------------------------
+ Append text portions at the end of the last paragraph of the text
+ interface. Support of import filters.
+ -----------------------------------------------------------------------*/
+uno::Reference< text::XTextRange > SAL_CALL
+SwXText::appendTextPortion(
+ const ::rtl::OUString& rText,
+ const uno::Sequence< beans::PropertyValue > &
+ rCharacterAndParagraphProperties)
+throw (lang::IllegalArgumentException, uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+
+ if(!IsValid())
+ {
+ throw uno::RuntimeException();
+ }
+ uno::Reference< text::XTextRange > xRet;
+ const uno::Reference< text::XTextCursor > xTextCursor = CreateCursor();
+ xTextCursor->gotoEnd(sal_False);
+
+ const uno::Reference< lang::XUnoTunnel > xRangeTunnel(
+ xTextCursor, uno::UNO_QUERY_THROW );
+ SwXTextCursor *const pTextCursor =
+ ::sw::UnoTunnelGetImplementation<SwXTextCursor>(xRangeTunnel);
+
+ bool bIllegalException = false;
+ bool bRuntimeException = false;
+ ::rtl::OUString sMessage;
+ m_pImpl->m_pDoc->GetIDocumentUndoRedo().StartUndo(UNDO_INSERT, NULL);
+
+// SwPaM aPam(*pStartNode->EndOfSectionNode());
+ //aPam.Move( fnMoveBackward, fnGoNode );
+ SwUnoCrsr *const pCursor = pTextCursor->GetCursor();
+ pCursor->MovePara( fnParaCurr, fnParaEnd );
+ m_pImpl->m_pDoc->DontExpandFmt( *pCursor->Start() );
+
+ if (rText.getLength())
+ {
+ const xub_StrLen nContentPos = pCursor->GetPoint()->nContent.GetIndex();
+ SwUnoCursorHelper::DocInsertStringSplitCR(
+ *m_pImpl->m_pDoc, *pCursor, rText, false);
+ SwUnoCursorHelper::SelectPam(*pCursor, true);
+ pCursor->GetPoint()->nContent = nContentPos;
+ }
+
+ if (rCharacterAndParagraphProperties.getLength())
+ {
+ SfxItemPropertyMap const*const pCursorMap =
+ aSwMapProvider.GetPropertySet(PROPERTY_MAP_TEXT_CURSOR)
+ ->getPropertyMap();
+ beans::PropertyValue const*const pValues =
+ rCharacterAndParagraphProperties.getConstArray();
+ SfxItemPropertySet const*const pCursorPropSet =
+ aSwMapProvider.GetPropertySet(PROPERTY_MAP_TEXT_CURSOR);
+ const sal_Int32 nLen(rCharacterAndParagraphProperties.getLength());
+ for (sal_Int32 nProp = 0; nProp < nLen; ++nProp)
+ {
+ if (!pCursorMap->getByName( pValues[nProp].Name ))
+ {
+ bIllegalException = true;
+ break;
+ }
+ try
+ {
+ SwUnoCursorHelper::SetPropertyValue(
+ *pCursor, *pCursorPropSet,
+ pValues[nProp].Name, pValues[nProp].Value,
+ nsSetAttrMode::SETATTR_NOFORMATATTR);
+ }
+ catch( lang::IllegalArgumentException& rIllegal )
+ {
+ sMessage = rIllegal.Message;
+ bIllegalException = true;
+ break;
+ }
+ catch( uno::RuntimeException& rRuntime )
+ {
+ sMessage = rRuntime.Message;
+ bRuntimeException = true;
+ break;
+ }
+ }
+ }
+ m_pImpl->m_pDoc->GetIDocumentUndoRedo().EndUndo(UNDO_INSERT, NULL);
+ if (bIllegalException || bRuntimeException)
+ {
+ m_pImpl->m_pDoc->GetIDocumentUndoRedo().Undo();
+ if (bIllegalException)
+ {
+ lang::IllegalArgumentException aEx;
+ aEx.Message = sMessage;
+ throw aEx;
+ }
+ else //if(bRuntimeException)
+ {
+ uno::RuntimeException aEx;
+ aEx.Message = sMessage;
+ throw aEx;
+ }
+ }
+ xRet = new SwXTextRange(*pCursor, this);
+ return xRet;
+}
+
+/*-------------------------------------------------------------------------
+ enable appending text contents like graphic objects, shapes and so on
+ to support import filters
+ -----------------------------------------------------------------------*/
+uno::Reference< text::XTextRange > SAL_CALL
+SwXText::appendTextContent(
+ const uno::Reference< text::XTextContent >& xTextContent,
+ const uno::Sequence< beans::PropertyValue >&
+ rCharacterAndParagraphProperties)
+throw (lang::IllegalArgumentException, uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+
+ if (!IsValid())
+ {
+ throw uno::RuntimeException();
+ }
+ SwStartNode const*const pStartNode = GetStartNode();
+ if(!pStartNode)
+ {
+ throw uno::RuntimeException();
+ }
+
+ uno::Reference< text::XTextRange > xRet;
+ m_pImpl->m_pDoc->GetIDocumentUndoRedo().StartUndo(UNDO_INSERT, NULL);
+ // find end node, go backward - don't skip tables because the
+ // new paragraph has to be the last node
+ SwPaM aPam(*pStartNode->EndOfSectionNode());
+ aPam.Move( fnMoveBackward, fnGoNode );
+ // set cursor to the end of the last text node
+ SwCursor aCursor( *aPam.Start(), 0, false );
+ xRet = new SwXTextRange(aCursor, this);
+ aCursor.MovePara( fnParaCurr, fnParaEnd );
+ m_pImpl->m_pDoc->DontExpandFmt( *aCursor.Start() );
+ // now attach the text content here
+ insertTextContent( xRet, xTextContent, false );
+ // now apply the properties to the anchor
+ if (rCharacterAndParagraphProperties.getLength())
+ {
+ try
+ {
+ const sal_Int32 nLen(rCharacterAndParagraphProperties.getLength());
+ const uno::Reference< beans::XPropertySet > xAnchor(
+ xTextContent->getAnchor(), uno::UNO_QUERY);
+ if (xAnchor.is())
+ {
+ for (sal_Int32 nElement = 0; nElement < nLen; ++nElement)
+ {
+ xAnchor->setPropertyValue(
+ rCharacterAndParagraphProperties[nElement].Name,
+ rCharacterAndParagraphProperties[nElement].Value);
+ }
+ }
+ }
+ catch (const uno::Exception&)
+ {
+ throw uno::RuntimeException();
+ }
+ }
+ m_pImpl->m_pDoc->GetIDocumentUndoRedo().EndUndo(UNDO_INSERT, NULL);
+ return xRet;
+}
+
+// move previously appended paragraphs into a text frames
+// to support import filters
+uno::Reference< text::XTextContent > SAL_CALL
+SwXText::convertToTextFrame(
+ const uno::Reference< text::XTextRange >& xStart,
+ const uno::Reference< text::XTextRange >& xEnd,
+ const uno::Sequence< beans::PropertyValue >& rFrameProperties)
+throw (lang::IllegalArgumentException, uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+
+ if(!IsValid())
+ {
+ throw uno::RuntimeException();
+ }
+ uno::Reference< text::XTextContent > xRet;
+ SwUnoInternalPaM aStartPam(*GetDoc());
+ std::auto_ptr< SwUnoInternalPaM > pEndPam(new SwUnoInternalPaM(*GetDoc()));
+ if (!::sw::XTextRangeToSwPaM(aStartPam, xStart) ||
+ !::sw::XTextRangeToSwPaM(*pEndPam, xEnd))
+ {
+ throw lang::IllegalArgumentException();
+ }
+
+ const uno::Reference<lang::XUnoTunnel> xStartRangeTunnel(xStart,
+ uno::UNO_QUERY);
+ SwXTextRange *const pStartRange =
+ ::sw::UnoTunnelGetImplementation<SwXTextRange>(xStartRangeTunnel);
+ const uno::Reference<lang::XUnoTunnel> xEndRangeTunnel(xEnd,
+ uno::UNO_QUERY);
+ SwXTextRange *const pEndRange =
+ ::sw::UnoTunnelGetImplementation<SwXTextRange>(xEndRangeTunnel);
+ // bookmarks have to be removed before the referenced text node
+ // is deleted in DelFullPara
+ if (pStartRange)
+ {
+ pStartRange->Invalidate();
+ }
+ if (pEndRange)
+ {
+ pEndRange->Invalidate();
+ }
+
+ m_pImpl->m_pDoc->GetIDocumentUndoRedo().StartUndo( UNDO_START, NULL );
+ bool bIllegalException = false;
+ bool bRuntimeException = false;
+ ::rtl::OUString sMessage;
+ SwStartNode* pStartStartNode = aStartPam.GetNode()->StartOfSectionNode();
+ while (pStartStartNode && pStartStartNode->IsSectionNode())
+ {
+ pStartStartNode = pStartStartNode->StartOfSectionNode();
+ }
+ SwStartNode* pEndStartNode = pEndPam->GetNode()->StartOfSectionNode();
+ while (pEndStartNode && pEndStartNode->IsSectionNode())
+ {
+ pEndStartNode = pEndStartNode->StartOfSectionNode();
+ }
+ bool bParaAfterInserted = false;
+ bool bParaBeforeInserted = false;
+ if (pStartStartNode != pEndStartNode || pStartStartNode != GetStartNode())
+ {
+ // todo: if the start/end is in a table then insert a paragraph
+ // before/after, move the start/end nodes, then convert and
+ // remove the addtional paragraphs in the end
+ if (pStartStartNode->GetStartNodeType() == SwTableBoxStartNode)
+ {
+ SwTableNode *const pSartTableNode(pStartStartNode->FindTableNode());
+ const SwNodeIndex aTblIdx( *pSartTableNode, -1 );
+ SwPosition aBefore(aTblIdx);
+ bParaBeforeInserted = GetDoc()->AppendTxtNode( aBefore );
+ aStartPam.DeleteMark();
+ *aStartPam.GetPoint() = aBefore;
+ pStartStartNode = aStartPam.GetNode()->StartOfSectionNode();
+ }
+ if (pEndStartNode->GetStartNodeType() == SwTableBoxStartNode)
+ {
+ SwTableNode *const pEndTableNode = pEndStartNode->FindTableNode();
+ SwEndNode *const pTableEnd = pEndTableNode->EndOfSectionNode();
+ SwPosition aTableEnd(*pTableEnd);
+ bParaAfterInserted = GetDoc()->AppendTxtNode( aTableEnd );
+ pEndPam->DeleteMark();
+ *pEndPam->GetPoint() = aTableEnd;
+ pEndStartNode = pEndPam->GetNode()->StartOfSectionNode();
+ }
+ // now we should have the positions in the same hierarchy
+ if ((pStartStartNode != pEndStartNode) ||
+ (pStartStartNode != GetStartNode()))
+ {
+ // if not - remove the additional paragraphs and throw
+ if (bParaBeforeInserted)
+ {
+ SwCursor aDelete(*aStartPam.GetPoint(), 0, false);
+ aDelete.MovePara(fnParaCurr, fnParaStart);
+ aDelete.SetMark();
+ aDelete.MovePara(fnParaCurr, fnParaEnd);
+ GetDoc()->DelFullPara(aDelete);
+ }
+ if (bParaAfterInserted)
+ {
+ SwCursor aDelete(*pEndPam->GetPoint(), 0, false);
+ aDelete.MovePara(fnParaCurr, fnParaStart);
+ aDelete.SetMark();
+ aDelete.MovePara(fnParaCurr, fnParaEnd);
+ GetDoc()->DelFullPara(aDelete);
+ }
+ throw lang::IllegalArgumentException();
+ }
+ }
+
+ // make a selection from aStartPam to a EndPam
+ SwSelBoxes aBoxes;
+ SfxItemSet aFrameItemSet(m_pImpl->m_pDoc->GetAttrPool(),
+ RES_FRMATR_BEGIN, RES_FRMATR_END-1,
+ 0 );
+ // If there is no content in the frame the shape is in
+ // it gets deleted in the DelFullPara call below,
+ // In this case insert a tmp text node ( we delete it later )
+ if ( aStartPam.Start()->nNode == pEndPam->Start()->nNode
+ && aStartPam.End()->nNode == pEndPam->End()->nNode )
+ {
+ SwPosition aEnd(*aStartPam.End());
+ bParaAfterInserted = GetDoc()->AppendTxtNode( aEnd );
+ pEndPam->DeleteMark();
+ *pEndPam->GetPoint() = aEnd;
+ }
+ aStartPam.SetMark();
+ *aStartPam.End() = *pEndPam->End();
+ pEndPam.reset(0);
+ SwXTextFrame *const pNewFrame = new SwXTextFrame(m_pImpl->m_pDoc);
+ const uno::Reference< text::XTextFrame > xNewFrame = pNewFrame;
+ pNewFrame->SetSelection( aStartPam );
+ try
+ {
+ const beans::PropertyValue* pValues = rFrameProperties.getConstArray();
+ for (sal_Int32 nProp = 0; nProp < rFrameProperties.getLength(); ++nProp)
+ {
+ pNewFrame->SwXFrame::setPropertyValue(
+ pValues[nProp].Name, pValues[nProp].Value);
+ }
+
+ { // has to be in a block to remove the SwIndexes before
+ // DelFullPara is called
+ const uno::Reference< text::XTextRange> xInsertTextRange =
+ new SwXTextRange(aStartPam, this);
+ pNewFrame->attach( xInsertTextRange );
+ pNewFrame->setName(m_pImpl->m_pDoc->GetUniqueFrameName());
+ }
+
+ if (!aStartPam.GetTxt().Len())
+ {
+ bool bMoved = false;
+ { // has to be in a block to remove the SwIndexes before
+ // DelFullPara is called
+ SwPaM aMovePam( *aStartPam.GetNode() );
+ if (aMovePam.Move( fnMoveForward, fnGoCntnt ))
+ {
+ // move the anchor to the next paragraph
+ SwFmtAnchor aNewAnchor(pNewFrame->GetFrmFmt()->GetAnchor());
+ aNewAnchor.SetAnchor( aMovePam.Start() );
+ m_pImpl->m_pDoc->SetAttr(
+ aNewAnchor, *pNewFrame->GetFrmFmt() );
+ }
+ bMoved = true;
+ }
+ if (bMoved)
+ {
+ aStartPam.DeleteMark();
+// SwPaM aDelPam( *aStartPam.GetNode() );
+ m_pImpl->m_pDoc->DelFullPara(aStartPam/*aDelPam*/);
+ }
+ }
+ }
+ catch (lang::IllegalArgumentException& rIllegal)
+ {
+ sMessage = rIllegal.Message;
+ bIllegalException = true;
+ }
+ catch (uno::RuntimeException& rRuntime)
+ {
+ sMessage = rRuntime.Message;
+ bRuntimeException = true;
+ }
+ xRet = pNewFrame;
+ if (bParaBeforeInserted || bParaAfterInserted)
+ {
+ const uno::Reference<text::XTextCursor> xFrameTextCursor =
+ pNewFrame->createTextCursor();
+ const uno::Reference<XUnoTunnel> xTunnel(xFrameTextCursor,
+ uno::UNO_QUERY);
+ SwXTextCursor *const pFrameCursor =
+ ::sw::UnoTunnelGetImplementation<SwXTextCursor>(xTunnel);
+ if (bParaBeforeInserted)
+ {
+ // todo: remove paragraph before frame
+ m_pImpl->m_pDoc->DelFullPara(*pFrameCursor->GetPaM());
+ }
+ if (bParaAfterInserted)
+ {
+ xFrameTextCursor->gotoEnd(sal_False);
+ m_pImpl->m_pDoc->DelFullPara(*pFrameCursor->GetPaM());
+ }
+ }
+
+ m_pImpl->m_pDoc->GetIDocumentUndoRedo().EndUndo(UNDO_END, NULL);
+ if (bIllegalException || bRuntimeException)
+ {
+ m_pImpl->m_pDoc->GetIDocumentUndoRedo().Undo();
+ if (bIllegalException)
+ {
+ lang::IllegalArgumentException aEx;
+ aEx.Message = sMessage;
+ throw aEx;
+ }
+ else //if(bRuntimeException)
+ {
+ uno::RuntimeException aEx;
+ aEx.Message = sMessage;
+ throw aEx;
+ }
+ }
+ return xRet;
+}
+
+/*-------------------------------------------------------------------------
+ Move previously imported paragraphs into a new text table.
+ -----------------------------------------------------------------------*/
+struct VerticallyMergedCell
+{
+ std::vector<uno::Reference< beans::XPropertySet > > aCells;
+ sal_Int32 nLeftPosition;
+ bool bOpen;
+
+ VerticallyMergedCell(uno::Reference< beans::XPropertySet > const& rxCell,
+ const sal_Int32 nLeft)
+ : nLeftPosition( nLeft )
+ , bOpen( true )
+ {
+ aCells.push_back( rxCell );
+ }
+};
+
+#define COL_POS_FUZZY 2
+
+static bool lcl_SimilarPosition( const sal_Int32 nPos1, const sal_Int32 nPos2 )
+{
+ return abs( nPos1 - nPos2 ) < COL_POS_FUZZY;
+}
+
+void SwXText::Impl::ConvertCell(
+ const bool bFirstCell,
+ const uno::Sequence< uno::Reference< text::XTextRange > > & rCell,
+ ::std::vector<SwNodeRange> & rRowNodes,
+ ::std::auto_ptr< SwPaM > & rpFirstPaM,
+ SwPaM & rLastPaM,
+ bool & rbExcept)
+{
+ if (rCell.getLength() != 2)
+ {
+ throw lang::IllegalArgumentException();
+ }
+ const uno::Reference<text::XTextRange> xStartRange = rCell[0];
+ const uno::Reference<text::XTextRange> xEndRange = rCell[1];
+ SwUnoInternalPaM aStartCellPam(*m_pDoc);
+ SwUnoInternalPaM aEndCellPam(*m_pDoc);
+
+ // !!! TODO - PaMs in tables and sections do not work here -
+ // the same applies to PaMs in frames !!!
+
+ if (!::sw::XTextRangeToSwPaM(aStartCellPam, xStartRange) ||
+ !::sw::XTextRangeToSwPaM(aEndCellPam, xEndRange))
+ {
+ throw lang::IllegalArgumentException();
+ }
+
+ SwNodeRange aTmpRange(aStartCellPam.Start()->nNode,
+ aEndCellPam.End()->nNode);
+ SwNodeRange * pCorrectedRange =
+ m_pDoc->GetNodes().ExpandRangeForTableBox(aTmpRange);
+
+ if (pCorrectedRange != NULL)
+ {
+ SwPaM aNewStartPaM(pCorrectedRange->aStart, 0);
+ aStartCellPam = aNewStartPaM;
+
+ xub_StrLen nEndLen = 0;
+ SwTxtNode * pTxtNode = pCorrectedRange->aEnd.GetNode().GetTxtNode();
+ if (pTxtNode != NULL)
+ nEndLen = pTxtNode->Len();
+
+ SwPaM aNewEndPaM(pCorrectedRange->aEnd, nEndLen);
+ aEndCellPam = aNewEndPaM;
+ }
+
+ /** check the nodes between start and end
+ it is allowed to have pairs of StartNode/EndNodes
+ */
+ if (aStartCellPam.Start()->nNode < aEndCellPam.End()->nNode)
+ {
+ // increment on each StartNode and decrement on each EndNode
+ // we must reach zero at the end and must not go below zero
+ long nOpenNodeBlock = 0;
+ SwNodeIndex aCellIndex = aStartCellPam.Start()->nNode;
+ while (aCellIndex < aEndCellPam.End()->nNode.GetIndex())
+ {
+ if (aCellIndex.GetNode().IsStartNode())
+ {
+ ++nOpenNodeBlock;
+ }
+ else if (aCellIndex.GetNode().IsEndNode())
+ {
+ --nOpenNodeBlock;
+ }
+ if (nOpenNodeBlock < 0)
+ {
+ rbExcept = true;
+ break;
+ }
+ ++aCellIndex;
+ }
+ if (nOpenNodeBlock != 0)
+ {
+ rbExcept = true;
+ return;
+ }
+ }
+
+ /** The vector<vector> NodeRanges has to contain consecutive nodes.
+ In rTableRanges the ranges don't need to be full paragraphs but
+ they have to follow each other. To process the ranges they
+ have to be aligned on paragraph borders by inserting paragraph
+ breaks. Non-consecutive ranges must initiate an exception.
+ */
+ if (bFirstCell)
+ {
+ // align the beginning - if necessary
+ if (aStartCellPam.Start()->nContent.GetIndex())
+ {
+ m_pDoc->SplitNode(*aStartCellPam.Start(), sal_False);
+ }
+ }
+ else
+ {
+ // check the predecessor
+ const sal_uLong nLastNodeIndex = rLastPaM.End()->nNode.GetIndex();
+ const sal_uLong nStartCellNodeIndex =
+ aStartCellPam.Start()->nNode.GetIndex();
+ const sal_uLong nLastNodeEndIndex = rLastPaM.End()->nNode.GetIndex();
+ if (nLastNodeIndex == nStartCellNodeIndex)
+ {
+ // same node as predecessor then equal nContent?
+ if (rLastPaM.End()->nContent != aStartCellPam.Start()->nContent)
+ {
+ rbExcept = true;
+ }
+ else
+ {
+ m_pDoc->SplitNode(*aStartCellPam.Start(), sal_False);
+ }
+ }
+ else if (nStartCellNodeIndex == (nLastNodeEndIndex + 1))
+ {
+ // next paragraph - now the content index of the new should be 0
+ // and of the old one should be equal to the text length
+ // but if it isn't we don't care - the cell is being inserted on
+ // the node border anyway
+ }
+ else
+ {
+ rbExcept = true;
+ }
+ }
+ // now check if there's a need to insert another paragraph break
+ if (aEndCellPam.End()->nContent.GetIndex() <
+ aEndCellPam.End()->nNode.GetNode().GetTxtNode()->Len())
+ {
+ m_pDoc->SplitNode(*aEndCellPam.End(), sal_False);
+ // take care that the new start/endcell is moved to the right position
+ // aStartCellPam has to point to the start of the new (previous) node
+ // aEndCellPam has to point to the end of the new (previous) node
+ aStartCellPam.DeleteMark();
+ aStartCellPam.Move(fnMoveBackward, fnGoNode);
+ aStartCellPam.GetPoint()->nContent = 0;
+ aEndCellPam.DeleteMark();
+ aEndCellPam.Move(fnMoveBackward, fnGoNode);
+ aEndCellPam.GetPoint()->nContent =
+ aEndCellPam.GetNode()->GetTxtNode()->Len();
+ }
+
+ *rLastPaM.GetPoint() = *aEndCellPam.Start();
+ if (aStartCellPam.HasMark())
+ {
+ rLastPaM.SetMark();
+ *rLastPaM.GetMark() = *aEndCellPam.End();
+ }
+ else
+ {
+ rLastPaM.DeleteMark();
+ }
+
+ SwNodeRange aCellRange(aStartCellPam.Start()->nNode,
+ aEndCellPam.End()->nNode);
+ rRowNodes.push_back(aCellRange);
+ if (bFirstCell)
+ {
+ rpFirstPaM.reset(new SwPaM(*aStartCellPam.Start()));
+ }
+}
+
+typedef uno::Sequence< text::TableColumnSeparator > TableColumnSeparators;
+
+static void
+lcl_ApplyRowProperties(
+ uno::Sequence<beans::PropertyValue> const& rRowProperties,
+ uno::Any const& rRow,
+ TableColumnSeparators & rRowSeparators)
+{
+ uno::Reference< beans::XPropertySet > xRow;
+ rRow >>= xRow;
+ const beans::PropertyValue* pProperties = rRowProperties.getConstArray();
+ for (sal_Int32 nProperty = 0; nProperty < rRowProperties.getLength();
+ ++nProperty)
+ {
+ if (pProperties[ nProperty ].Name.equalsAsciiL(
+ RTL_CONSTASCII_STRINGPARAM("TableColumnSeparators")))
+ {
+ // add the separators to access the cell's positions
+ // for vertical merging later
+ TableColumnSeparators aSeparators;
+ pProperties[ nProperty ].Value >>= aSeparators;
+ rRowSeparators = aSeparators;
+ }
+ xRow->setPropertyValue(
+ pProperties[ nProperty ].Name, pProperties[ nProperty ].Value);
+ }
+}
+
+#ifdef DEBUG
+//-->debug cell properties of all rows
+static void
+lcl_DebugCellProperties(
+ const uno::Sequence< uno::Sequence< uno::Sequence<
+ beans::PropertyValue > > >& rCellProperties)
+{
+ ::rtl::OUString sNames;
+ for (sal_Int32 nDebugRow = 0; nDebugRow < rCellProperties.getLength();
+ ++nDebugRow)
+ {
+ const uno::Sequence< beans::PropertyValues > aDebugCurrentRow =
+ rCellProperties[nDebugRow];
+ sal_Int32 nDebugCells = aDebugCurrentRow.getLength();
+ (void) nDebugCells;
+ for (sal_Int32 nDebugCell = 0; nDebugCell < nDebugCells;
+ ++nDebugCell)
+ {
+ const uno::Sequence< beans::PropertyValue >&
+ rDebugCellProperties = aDebugCurrentRow[nDebugCell];
+ const sal_Int32 nDebugCellProperties =
+ rDebugCellProperties.getLength();
+ for (sal_Int32 nDebugProperty = 0;
+ nDebugProperty < nDebugCellProperties; ++nDebugProperty)
+ {
+ const ::rtl::OUString sName =
+ rDebugCellProperties[nDebugProperty].Name;
+ sNames += sName;
+ sNames += ::rtl::OUString('-');
+ }
+ sNames += ::rtl::OUString('+');
+ }
+ sNames += ::rtl::OUString('|');
+ }
+ (void)sNames;
+}
+//--<
+#endif
+
+static void
+lcl_ApplyCellProperties(
+ const sal_Int32 nCell,
+ TableColumnSeparators const& rRowSeparators,
+ const uno::Sequence< beans::PropertyValue >& rCellProperties,
+ uno::Reference< uno::XInterface > xCell,
+ ::std::vector<VerticallyMergedCell> & rMergedCells)
+{
+ const sal_Int32 nCellProperties = rCellProperties.getLength();
+ const uno::Reference< beans::XPropertySet > xCellPS(xCell, uno::UNO_QUERY);
+ for (sal_Int32 nProperty = 0; nProperty < nCellProperties; ++nProperty)
+ {
+ const OUString & rName = rCellProperties[nProperty].Name;
+ const uno::Any & rValue = rCellProperties[nProperty].Value;
+ if (rName.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("VerticalMerge")))
+ {
+ // determine left border position
+ // add the cell to a queue of merged cells
+ sal_Bool bMerge = sal_False;
+ rValue >>= bMerge;
+ sal_Int32 nLeftPos = -1;
+ if (!nCell)
+ {
+ nLeftPos = 0;
+ }
+ else if (rRowSeparators.getLength() >= nCell)
+ {
+ const text::TableColumnSeparator* pSeparators =
+ rRowSeparators.getConstArray();
+ nLeftPos = pSeparators[nCell - 1].Position;
+ }
+ if (bMerge)
+ {
+ // 'close' all the cell with the same left position
+ // if separate vertical merges in the same column exist
+ if (rMergedCells.size())
+ {
+ std::vector<VerticallyMergedCell>::iterator aMergedIter =
+ rMergedCells.begin();
+ while (aMergedIter != rMergedCells.end())
+ {
+ if (lcl_SimilarPosition(aMergedIter->nLeftPosition,
+ nLeftPos))
+ {
+ aMergedIter->bOpen = false;
+ }
+ ++aMergedIter;
+ }
+ }
+ // add the new group of merged cells
+ rMergedCells.push_back(VerticallyMergedCell(xCellPS, nLeftPos));
+ }
+ else
+ {
+ // find the cell that
+ DBG_ASSERT(rMergedCells.size(),
+ "the first merged cell is missing");
+ if (rMergedCells.size())
+ {
+ std::vector<VerticallyMergedCell>::iterator aMergedIter =
+ rMergedCells.begin();
+#if OSL_DEBUG_LEVEL > 1
+ bool bDbgFound = false;
+#endif
+ while (aMergedIter != rMergedCells.end())
+ {
+ if (aMergedIter->bOpen &&
+ lcl_SimilarPosition(aMergedIter->nLeftPosition,
+ nLeftPos))
+ {
+ aMergedIter->aCells.push_back( xCellPS );
+#if OSL_DEBUG_LEVEL > 1
+ bDbgFound = true;
+#endif
+ }
+ ++aMergedIter;
+ }
+#if OSL_DEBUG_LEVEL > 1
+ DBG_ASSERT( bDbgFound,
+ "couldn't find first vertically merged cell" );
+#endif
+ }
+ }
+ }
+ else
+ {
+ try
+ {
+ xCellPS->setPropertyValue(rName, rValue);
+ }
+ catch (uno::Exception const& e)
+ {
+ // Apply the paragraph and char properties to the cell's content
+ const uno::Reference< text::XText > xCellText(xCell,
+ uno::UNO_QUERY);
+ const uno::Reference< text::XTextCursor > xCellCurs =
+ xCellText->createTextCursor();
+ xCellCurs->gotoStart( sal_False );
+ xCellCurs->gotoEnd( sal_True );
+ const uno::Reference< beans::XPropertySet > xCellTextProps(
+ xCellCurs, uno::UNO_QUERY);
+ xCellTextProps->setPropertyValue(rName, rValue);
+ }
+ }
+ }
+}
+
+static void
+lcl_MergeCells(::std::vector<VerticallyMergedCell> & rMergedCells)
+{
+ if (rMergedCells.size())
+ {
+ std::vector<VerticallyMergedCell>::iterator aMergedIter =
+ rMergedCells.begin();
+ while (aMergedIter != rMergedCells.end())
+ {
+ sal_Int32 nCellCount =
+ static_cast<sal_Int32>(aMergedIter->aCells.size());
+ std::vector<uno::Reference< beans::XPropertySet > >::iterator
+ aCellIter = aMergedIter->aCells.begin();
+ bool bFirstCell = true;
+ // the first of the cells gets the number of cells set as RowSpan
+ // the others get the inverted number of remaining merged cells
+ // (3,-2,-1)
+ while (aCellIter != aMergedIter->aCells.end())
+ {
+ (*aCellIter)->setPropertyValue(
+ rtl::OUString::createFromAscii(SW_PROP_NAME_STR(UNO_NAME_ROW_SPAN)),
+ uno::makeAny(nCellCount));
+ if (bFirstCell)
+ {
+ nCellCount *= -1;
+ bFirstCell = false;
+ }
+ ++nCellCount;
+ ++aCellIter;
+ }
+ ++aMergedIter;
+ }
+ }
+}
+
+uno::Reference< text::XTextTable > SAL_CALL
+SwXText::convertToTable(
+ const uno::Sequence< uno::Sequence< uno::Sequence<
+ uno::Reference< text::XTextRange > > > >& rTableRanges,
+ const uno::Sequence< uno::Sequence< uno::Sequence<
+ beans::PropertyValue > > >& rCellProperties,
+ const uno::Sequence< uno::Sequence< beans::PropertyValue > >&
+ rRowProperties,
+ const uno::Sequence< beans::PropertyValue >& rTableProperties)
+throw (lang::IllegalArgumentException, uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+
+ if(!IsValid())
+ {
+ throw uno::RuntimeException();
+ }
+
+ //at first collect the text ranges as SwPaMs
+ const uno::Sequence< uno::Sequence< uno::Reference< text::XTextRange > > >*
+ pTableRanges = rTableRanges.getConstArray();
+ std::auto_ptr < SwPaM > pFirstPaM;
+ std::vector< std::vector<SwNodeRange> > aTableNodes;
+ bool bExcept = false;
+ SwPaM aLastPaM(m_pImpl->m_pDoc->GetNodes());
+ for (sal_Int32 nRow = 0; !bExcept && (nRow < rTableRanges.getLength());
+ ++nRow)
+ {
+ std::vector<SwNodeRange> aRowNodes;
+ const uno::Sequence< uno::Reference< text::XTextRange > >* pRow =
+ pTableRanges[nRow].getConstArray();
+ const sal_Int32 nCells(pTableRanges[nRow].getLength());
+
+ for (sal_Int32 nCell = 0; nCell < nCells; ++nCell)
+ {
+ m_pImpl->ConvertCell((nCell == 0) && (nRow == 0), pRow[nCell],
+ aRowNodes, pFirstPaM, aLastPaM, bExcept);
+ }
+ aTableNodes.push_back(aRowNodes);
+ }
+
+ if(bExcept)
+ {
+ m_pImpl->m_pDoc->GetIDocumentUndoRedo().Undo();
+ throw lang::IllegalArgumentException();
+ }
+
+ std::vector< TableColumnSeparators >
+ aRowSeparators(rRowProperties.getLength());
+ std::vector<VerticallyMergedCell> aMergedCells;
+
+ SwTable const*const pTable = m_pImpl->m_pDoc->TextToTable( aTableNodes );
+ SwXTextTable *const pTextTable = new SwXTextTable( *pTable->GetFrmFmt() );
+ const uno::Reference< text::XTextTable > xRet = pTextTable;
+ const uno::Reference< beans::XPropertySet > xPrSet = pTextTable;
+ // set properties to the table
+ // catch lang::WrappedTargetException and lang::IndexOutOfBoundsException
+ try
+ {
+ //apply table properties
+ const beans::PropertyValue* pTableProperties =
+ rTableProperties.getConstArray();
+ for (sal_Int32 nProperty = 0; nProperty < rTableProperties.getLength();
+ ++nProperty)
+ {
+ try
+ {
+ xPrSet->setPropertyValue( pTableProperties[nProperty].Name,
+ pTableProperties[nProperty].Value );
+ }
+ catch ( uno::Exception const& e )
+ {
+#if DEBUG
+ std::clog << "Exception when setting property: ";
+ std::clog << rtl::OUStringToOString(
+ pTableProperties[nProperty].Name, RTL_TEXTENCODING_UTF8)
+ .getStr();
+ std::clog << ". Message: ";
+ std::clog << rtl::OUStringToOString( e.Message,
+ RTL_TEXTENCODING_UTF8 ).getStr();
+ std::clog << std::endl;
+#endif
+ }
+ }
+
+ //apply row properties
+ const uno::Reference< table::XTableRows > xRows = xRet->getRows();
+
+ const beans::PropertyValues* pRowProperties =
+ rRowProperties.getConstArray();
+ for (sal_Int32 nRow = 0; nRow < xRows->getCount(); ++nRow)
+ {
+ if( nRow >= rRowProperties.getLength())
+ {
+ break;
+ }
+ lcl_ApplyRowProperties(pRowProperties[nRow],
+ xRows->getByIndex(nRow), aRowSeparators[nRow]);
+ }
+
+#ifdef DEBUG
+ lcl_DebugCellProperties(rCellProperties);
+#endif
+
+ //apply cell properties
+ for (sal_Int32 nRow = 0; nRow < rCellProperties.getLength(); ++nRow)
+ {
+ const uno::Sequence< beans::PropertyValues > aCurrentRow =
+ rCellProperties[nRow];
+ sal_Int32 nCells = aCurrentRow.getLength();
+ for (sal_Int32 nCell = 0; nCell < nCells; ++nCell)
+ {
+ lcl_ApplyCellProperties(nCell,
+ aRowSeparators[nRow], aCurrentRow[nCell],
+ pTextTable->getCellByPosition(nCell, nRow),
+ aMergedCells);
+ }
+ }
+ // now that the cell properties are set the vertical merge values
+ // have to be applied
+ lcl_MergeCells(aMergedCells);
+ }
+ catch( const lang::WrappedTargetException& rWrapped )
+ {
+ (void)rWrapped;
+ }
+ catch ( const lang::IndexOutOfBoundsException& rBounds )
+ {
+ (void)rBounds;
+ }
+
+ return xRet;
+}
+
+
+void SAL_CALL
+SwXText::copyText(
+ const uno::Reference< text::XTextCopy >& xSource )
+throw (uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+
+ uno::Reference< text::XText > const xText(xSource, uno::UNO_QUERY_THROW);
+ uno::Reference< text::XTextCursor > const xCursor =
+ xText->createTextCursor();
+ xCursor->gotoEnd( sal_True );
+
+ uno::Reference< lang::XUnoTunnel > const xCursorTunnel(xCursor,
+ uno::UNO_QUERY_THROW);
+
+ OTextCursorHelper *const pCursor =
+ ::sw::UnoTunnelGetImplementation<OTextCursorHelper>(xCursorTunnel);
+ if (!pCursor)
+ {
+ throw uno::RuntimeException();
+ }
+
+ SwNodeIndex rNdIndex( *GetStartNode( ), 1 );
+ SwPosition rPos( rNdIndex );
+ m_pImpl->m_pDoc->CopyRange( *pCursor->GetPaM(), rPos, false );
+}
+
+
+/******************************************************************
+ * SwXBodyText
+ ******************************************************************/
+SwXBodyText::SwXBodyText(SwDoc *const pDoc)
+ : SwXText(pDoc, CURSOR_BODY)
+{
+}
+
+SwXBodyText::~SwXBodyText()
+{
+}
+
+OUString SAL_CALL
+SwXBodyText::getImplementationName() throw (uno::RuntimeException)
+{
+ return C2U("SwXBodyText");
+}
+
+static char const*const g_ServicesBodyText[] =
+{
+ "com.sun.star.text.Text",
+};
+
+static const size_t g_nServicesBodyText(
+ SAL_N_ELEMENTS(g_ServicesBodyText));
+
+sal_Bool SAL_CALL SwXBodyText::supportsService(const OUString& rServiceName)
+throw (uno::RuntimeException)
+{
+ return ::sw::SupportsServiceImpl(
+ g_nServicesBodyText, g_ServicesBodyText, rServiceName);
+}
+
+uno::Sequence< OUString > SAL_CALL
+SwXBodyText::getSupportedServiceNames() throw (uno::RuntimeException)
+{
+ return ::sw::GetSupportedServiceNamesImpl(
+ g_nServicesBodyText, g_ServicesBodyText);
+}
+
+uno::Any SAL_CALL
+SwXBodyText::queryAggregation(const uno::Type& rType)
+throw (uno::RuntimeException)
+{
+ uno::Any aRet;
+ if (rType == container::XEnumerationAccess::static_type())
+ {
+ aRet <<= uno::Reference< container::XEnumerationAccess >(this);
+ }
+ else if (rType == container::XElementAccess::static_type())
+ {
+ aRet <<= uno::Reference< container::XElementAccess >(this);
+ }
+ else if (rType == lang::XServiceInfo::static_type())
+ {
+ aRet <<= uno::Reference< lang::XServiceInfo >(this);
+ }
+ else
+ {
+ aRet = SwXText::queryInterface( rType );
+ }
+ if(aRet.getValueType() == ::getCppuVoidType())
+ {
+ aRet = OWeakAggObject::queryAggregation( rType );
+ }
+ return aRet;
+}
+
+uno::Sequence< uno::Type > SAL_CALL
+SwXBodyText::getTypes() throw (uno::RuntimeException)
+{
+ const uno::Sequence< uno::Type > aTypes = SwXBodyText_Base::getTypes();
+ const uno::Sequence< uno::Type > aTextTypes = SwXText::getTypes();
+ return ::comphelper::concatSequences(aTypes, aTextTypes);
+}
+
+uno::Sequence< sal_Int8 > SAL_CALL
+SwXBodyText::getImplementationId() throw (uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+ static uno::Sequence< sal_Int8 > aId( 16 );
+ static sal_Bool bInit = sal_False;
+ if(!bInit)
+ {
+ rtl_createUuid( (sal_uInt8 *)(aId.getArray() ), 0, sal_True );
+ bInit = sal_True;
+ }
+ return aId;
+}
+
+uno::Any SAL_CALL
+SwXBodyText::queryInterface(const uno::Type& rType)
+throw (uno::RuntimeException)
+{
+ const uno::Any ret = SwXText::queryInterface(rType);
+ return (ret.getValueType() == ::getCppuVoidType())
+ ? SwXBodyText_Base::queryInterface(rType)
+ : ret;
+}
+
+SwXTextCursor * SwXBodyText::CreateTextCursor(const bool bIgnoreTables)
+{
+ if(!IsValid())
+ {
+ return 0;
+ }
+
+ // the cursor has to skip tables contained in this text
+ SwPaM aPam(GetDoc()->GetNodes().GetEndOfContent());
+ aPam.Move( fnMoveBackward, fnGoDoc );
+ if (!bIgnoreTables)
+ {
+ SwTableNode * pTblNode = aPam.GetNode()->FindTableNode();
+ SwCntntNode * pCont = 0;
+ while (pTblNode)
+ {
+ aPam.GetPoint()->nNode = *pTblNode->EndOfSectionNode();
+ pCont = GetDoc()->GetNodes().GoNext(&aPam.GetPoint()->nNode);
+ pTblNode = pCont->FindTableNode();
+ }
+ if (pCont)
+ {
+ aPam.GetPoint()->nContent.Assign(pCont, 0);
+ }
+ }
+ return new SwXTextCursor(*GetDoc(), this, CURSOR_BODY, *aPam.GetPoint());
+}
+
+uno::Reference< text::XTextCursor > SAL_CALL
+SwXBodyText::createTextCursor() throw (uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+
+ const uno::Reference< text::XTextCursor > xRef(
+ static_cast<text::XWordCursor*>(CreateTextCursor(false)) );
+ if (!xRef.is())
+ {
+ uno::RuntimeException aRuntime;
+ aRuntime.Message = C2U(cInvalidObject);
+ throw aRuntime;
+ }
+ return xRef;
+}
+
+uno::Reference< text::XTextCursor > SAL_CALL
+SwXBodyText::createTextCursorByRange(
+ const uno::Reference< text::XTextRange > & xTextPosition)
+throw (uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+
+ if(!IsValid())
+ {
+ uno::RuntimeException aRuntime;
+ aRuntime.Message = C2U(cInvalidObject);
+ throw aRuntime;
+ }
+
+ uno::Reference< text::XTextCursor > aRef;
+ SwUnoInternalPaM aPam(*GetDoc());
+ if (::sw::XTextRangeToSwPaM(aPam, xTextPosition))
+ {
+ SwNode& rNode = GetDoc()->GetNodes().GetEndOfContent();
+
+ SwStartNode* p1 = aPam.GetNode()->StartOfSectionNode();
+ //document starts with a section?
+ while(p1->IsSectionNode())
+ {
+ p1 = p1->StartOfSectionNode();
+ }
+ SwStartNode *const p2 = rNode.StartOfSectionNode();
+
+ if(p1 == p2)
+ {
+ aRef = static_cast<text::XWordCursor*>(
+ new SwXTextCursor(*GetDoc(), this, CURSOR_BODY,
+ *aPam.GetPoint(), aPam.GetMark()));
+ }
+ }
+ if(!aRef.is())
+ {
+ throw uno::RuntimeException();
+ }
+ return aRef;
+}
+
+uno::Reference< container::XEnumeration > SAL_CALL
+SwXBodyText::createEnumeration()
+throw (uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+
+ if (!IsValid())
+ {
+ uno::RuntimeException aRuntime;
+ aRuntime.Message = C2U(cInvalidObject);
+ throw aRuntime;
+ }
+
+ SwNode& rNode = GetDoc()->GetNodes().GetEndOfContent();
+ SwPosition aPos(rNode);
+ ::std::auto_ptr<SwUnoCrsr> pUnoCursor(
+ GetDoc()->CreateUnoCrsr(aPos, sal_False));
+ pUnoCursor->Move(fnMoveBackward, fnGoDoc);
+ const uno::Reference< container::XEnumeration > xRet
+ = new SwXParagraphEnumeration(this, pUnoCursor, CURSOR_BODY);
+ return xRet;
+}
+
+uno::Type SAL_CALL
+SwXBodyText::getElementType() throw (uno::RuntimeException)
+{
+ return text::XTextRange::static_type();
+}
+
+sal_Bool SAL_CALL
+SwXBodyText::hasElements() throw (uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+
+ if (!IsValid())
+ {
+ uno::RuntimeException aRuntime;
+ aRuntime.Message = C2U(cInvalidObject);
+ throw aRuntime;
+ }
+
+ return sal_True;
+}
+
+/******************************************************************
+ * SwXHeadFootText
+ ******************************************************************/
+class SwXHeadFootText::Impl
+ : public SwClient
+{
+
+public:
+
+ bool m_bIsHeader;
+
+ Impl( SwXHeadFootText & /*rThis*/,
+ SwFrmFmt & rHeadFootFmt, const bool bIsHeader)
+ : SwClient(& rHeadFootFmt)
+ , m_bIsHeader(bIsHeader)
+ {
+ }
+
+ SwFrmFmt * GetHeadFootFmt() const {
+ return static_cast<SwFrmFmt*>(
+ const_cast<SwModify*>(GetRegisteredIn()));
+ }
+
+ SwFrmFmt & GetHeadFootFmtOrThrow() {
+ SwFrmFmt *const pFmt( GetHeadFootFmt() );
+ if (!pFmt) {
+ throw uno::RuntimeException(OUString(RTL_CONSTASCII_USTRINGPARAM(
+ "SwXHeadFootText: disposed or invalid")), 0);
+ }
+ return *pFmt;
+ }
+protected:
+ // SwClient
+ virtual void Modify(const SfxPoolItem *pOld, const SfxPoolItem *pNew);
+
+};
+
+void SwXHeadFootText::Impl::Modify( const SfxPoolItem *pOld, const SfxPoolItem *pNew)
+{
+ ClientModify(this, pOld, pNew);
+}
+
+bool SwXHeadFootText::IsXHeadFootText(SwClient *const pClient)
+{
+ return 0 != dynamic_cast<SwXHeadFootText::Impl*>(pClient);
+}
+
+uno::Reference< text::XText >
+SwXHeadFootText::CreateXHeadFootText(
+ SwFrmFmt & rHeadFootFmt, const bool bIsHeader)
+{
+ // re-use existing SwXHeadFootText
+ // #i105557#: do not iterate over the registered clients: race condition
+ uno::Reference< text::XText > xText(rHeadFootFmt.GetXObject(),
+ uno::UNO_QUERY);
+ if (!xText.is())
+ {
+ SwXHeadFootText *const pXHFT(
+ new SwXHeadFootText(rHeadFootFmt, bIsHeader));
+ xText.set(pXHFT);
+ rHeadFootFmt.SetXObject(xText);
+ }
+ return xText;
+}
+
+SwXHeadFootText::SwXHeadFootText(SwFrmFmt & rHeadFootFmt, const bool bIsHeader)
+ : SwXText(rHeadFootFmt.GetDoc(),
+ (bIsHeader) ? CURSOR_HEADER : CURSOR_FOOTER)
+ , m_pImpl( new SwXHeadFootText::Impl(*this, rHeadFootFmt, bIsHeader) )
+{
+}
+
+SwXHeadFootText::~SwXHeadFootText()
+{
+}
+
+OUString SAL_CALL
+SwXHeadFootText::getImplementationName() throw (uno::RuntimeException)
+{
+ return C2U("SwXHeadFootText");
+}
+
+static char const*const g_ServicesHeadFootText[] =
+{
+ "com.sun.star.text.Text",
+};
+
+static const size_t g_nServicesHeadFootText(SAL_N_ELEMENTS(g_ServicesHeadFootText));
+
+sal_Bool SAL_CALL SwXHeadFootText::supportsService(const OUString& rServiceName)
+throw (uno::RuntimeException)
+{
+ return ::sw::SupportsServiceImpl(
+ g_nServicesHeadFootText, g_ServicesHeadFootText, rServiceName);
+}
+
+uno::Sequence< OUString > SAL_CALL
+SwXHeadFootText::getSupportedServiceNames() throw (uno::RuntimeException)
+{
+ return ::sw::GetSupportedServiceNamesImpl(
+ g_nServicesHeadFootText, g_ServicesHeadFootText);
+}
+
+const SwStartNode *SwXHeadFootText::GetStartNode() const
+{
+ const SwStartNode *pSttNd = 0;
+ SwFrmFmt *const pHeadFootFmt = m_pImpl->GetHeadFootFmt();
+ if(pHeadFootFmt)
+ {
+ const SwFmtCntnt& rFlyCntnt = pHeadFootFmt->GetCntnt();
+ if( rFlyCntnt.GetCntntIdx() )
+ {
+ pSttNd = rFlyCntnt.GetCntntIdx()->GetNode().GetStartNode();
+ }
+ }
+ return pSttNd;
+}
+
+uno::Reference< text::XTextCursor >
+SwXHeadFootText::CreateCursor() throw (uno::RuntimeException)
+{
+ return createTextCursor();
+}
+
+uno::Sequence< uno::Type > SAL_CALL
+SwXHeadFootText::getTypes() throw (uno::RuntimeException)
+{
+ const uno::Sequence< uno::Type > aTypes = SwXHeadFootText_Base::getTypes();
+ const uno::Sequence< uno::Type > aTextTypes = SwXText::getTypes();
+ return ::comphelper::concatSequences(aTypes, aTextTypes);
+}
+
+uno::Sequence< sal_Int8 > SAL_CALL
+SwXHeadFootText::getImplementationId() throw (uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+ static uno::Sequence< sal_Int8 > aId( 16 );
+ static sal_Bool bInit = sal_False;
+ if(!bInit)
+ {
+ rtl_createUuid( (sal_uInt8 *)(aId.getArray() ), 0, sal_True );
+ bInit = sal_True;
+ }
+ return aId;
+}
+
+uno::Any SAL_CALL
+SwXHeadFootText::queryInterface(const uno::Type& rType)
+throw (uno::RuntimeException)
+{
+ const uno::Any ret = SwXHeadFootText_Base::queryInterface(rType);
+ return (ret.getValueType() == ::getCppuVoidType())
+ ? SwXText::queryInterface(rType)
+ : ret;
+}
+
+uno::Reference< text::XTextCursor > SAL_CALL
+SwXHeadFootText::createTextCursor() throw (uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+
+ SwFrmFmt & rHeadFootFmt( m_pImpl->GetHeadFootFmtOrThrow() );
+
+ uno::Reference< text::XTextCursor > xRet;
+ const SwFmtCntnt& rFlyCntnt = rHeadFootFmt.GetCntnt();
+ const SwNode& rNode = rFlyCntnt.GetCntntIdx()->GetNode();
+ SwPosition aPos(rNode);
+ SwXTextCursor *const pXCursor = new SwXTextCursor(*GetDoc(), this,
+ (m_pImpl->m_bIsHeader) ? CURSOR_HEADER : CURSOR_FOOTER, aPos);
+ SwUnoCrsr *const pUnoCrsr = pXCursor->GetCursor();
+ pUnoCrsr->Move(fnMoveForward, fnGoNode);
+
+ // save current start node to be able to check if there is content
+ // after the table - otherwise the cursor would be in the body text!
+ SwStartNode const*const pOwnStartNode = rNode.FindSttNodeByType(
+ (m_pImpl->m_bIsHeader) ? SwHeaderStartNode : SwFooterStartNode);
+ // is there a table here?
+ SwTableNode* pTblNode = pUnoCrsr->GetNode()->FindTableNode();
+ SwCntntNode* pCont = 0;
+ while (pTblNode)
+ {
+ pUnoCrsr->GetPoint()->nNode = *pTblNode->EndOfSectionNode();
+ pCont = GetDoc()->GetNodes().GoNext(&pUnoCrsr->GetPoint()->nNode);
+ pTblNode = pCont->FindTableNode();
+ }
+ if (pCont)
+ {
+ pUnoCrsr->GetPoint()->nContent.Assign(pCont, 0);
+ }
+ SwStartNode const*const pNewStartNode =
+ pUnoCrsr->GetNode()->FindSttNodeByType(
+ (m_pImpl->m_bIsHeader) ? SwHeaderStartNode : SwFooterStartNode);
+ if (!pNewStartNode || (pNewStartNode != pOwnStartNode))
+ {
+ uno::RuntimeException aExcept;
+ aExcept.Message = S2U("no text available");
+ throw aExcept;
+ }
+ xRet = static_cast<text::XWordCursor*>(pXCursor);
+ return xRet;
+}
+
+uno::Reference< text::XTextCursor > SAL_CALL
+SwXHeadFootText::createTextCursorByRange(
+ const uno::Reference< text::XTextRange > & xTextPosition)
+throw (uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+
+ SwFrmFmt & rHeadFootFmt( m_pImpl->GetHeadFootFmtOrThrow() );
+
+ SwUnoInternalPaM aPam(*GetDoc());
+ if (!::sw::XTextRangeToSwPaM(aPam, xTextPosition))
+ {
+ uno::RuntimeException aRuntime;
+ aRuntime.Message = C2U(cInvalidObject);
+ throw aRuntime;
+ }
+
+ uno::Reference< text::XTextCursor > xRet;
+ SwNode& rNode = rHeadFootFmt.GetCntnt().GetCntntIdx()->GetNode();
+ SwPosition aPos(rNode);
+ SwPaM aHFPam(aPos);
+ aHFPam.Move(fnMoveForward, fnGoNode);
+ SwStartNode *const pOwnStartNode = aHFPam.GetNode()->FindSttNodeByType(
+ (m_pImpl->m_bIsHeader) ? SwHeaderStartNode : SwFooterStartNode);
+ SwStartNode *const p1 = aPam.GetNode()->FindSttNodeByType(
+ (m_pImpl->m_bIsHeader) ? SwHeaderStartNode : SwFooterStartNode);
+ if (p1 == pOwnStartNode)
+ {
+ xRet = static_cast<text::XWordCursor*>(
+ new SwXTextCursor(*GetDoc(), this,
+ (m_pImpl->m_bIsHeader) ? CURSOR_HEADER : CURSOR_FOOTER,
+ *aPam.GetPoint(), aPam.GetMark()));
+ }
+ return xRet;
+}
+
+uno::Reference< container::XEnumeration > SAL_CALL
+SwXHeadFootText::createEnumeration()
+throw (uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+
+ SwFrmFmt & rHeadFootFmt( m_pImpl->GetHeadFootFmtOrThrow() );
+
+ uno::Reference< container::XEnumeration > aRef;
+ const SwFmtCntnt& rFlyCntnt = rHeadFootFmt.GetCntnt();
+ const SwNode& rNode = rFlyCntnt.GetCntntIdx()->GetNode();
+ SwPosition aPos(rNode);
+ ::std::auto_ptr<SwUnoCrsr> pUnoCursor(
+ GetDoc()->CreateUnoCrsr(aPos, sal_False));
+ pUnoCursor->Move(fnMoveForward, fnGoNode);
+ aRef = new SwXParagraphEnumeration(this, pUnoCursor,
+ (m_pImpl->m_bIsHeader) ? CURSOR_HEADER : CURSOR_FOOTER);
+
+ return aRef;
+}
+
+uno::Type SAL_CALL
+SwXHeadFootText::getElementType() throw (uno::RuntimeException)
+{
+ return text::XTextRange::static_type();
+}
+
+sal_Bool SAL_CALL SwXHeadFootText::hasElements() throw (uno::RuntimeException)
+{
+ return sal_True;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/unocore/unotextmarkup.cxx b/sw/source/core/unocore/unotextmarkup.cxx
new file mode 100644
index 000000000000..5f932220bb54
--- /dev/null
+++ b/sw/source/core/unocore/unotextmarkup.cxx
@@ -0,0 +1,490 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+#include <unotextmarkup.hxx>
+
+#include <osl/mutex.hxx>
+#include <vcl/svapp.hxx>
+#include <SwSmartTagMgr.hxx>
+#include <com/sun/star/text/TextMarkupType.hpp>
+#include <com/sun/star/text/TextMarkupDescriptor.hpp>
+#include <com/sun/star/container/XStringKeyMap.hpp>
+#include <ndtxt.hxx>
+#include <SwGrammarMarkUp.hxx>
+
+#include <IGrammarContact.hxx>
+
+using namespace ::com::sun::star;
+
+/*
+ * SwXTextMarkup
+ */
+SwXTextMarkup::SwXTextMarkup( SwTxtNode& rTxtNode, const ModelToViewHelper::ConversionMap* pMap )
+ : mpTxtNode( &rTxtNode ), mpConversionMap( pMap )
+{
+ // FME 2007-07-16 #i79641# SwXTextMarkup is allowed to be removed ...
+ SetIsAllowedToBeRemovedInModifyCall(true);
+ mpTxtNode->Add(this);
+}
+
+SwXTextMarkup::~SwXTextMarkup()
+{
+ delete mpConversionMap;
+}
+
+uno::Reference< container::XStringKeyMap > SAL_CALL SwXTextMarkup::getMarkupInfoContainer() throw (uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+
+ uno::Reference< container::XStringKeyMap > xProp = new SwXStringKeyMap;
+ return xProp;
+}
+
+void SAL_CALL SwXTextMarkup::commitTextMarkup(
+ ::sal_Int32 nType,
+ const ::rtl::OUString & rIdentifier,
+ ::sal_Int32 nStart,
+ ::sal_Int32 nLength,
+ const uno::Reference< container::XStringKeyMap > & xMarkupInfoContainer)
+ throw (uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+
+ // paragraph already dead or modified?
+ if ( !mpTxtNode || nLength <= 0 )
+ return;
+
+ if ( nType == text::TextMarkupType::SMARTTAG &&
+ !SwSmartTagMgr::Get().IsSmartTagTypeEnabled( rIdentifier ) )
+ return;
+
+ // get appropriate list to use...
+ SwWrongList* pWList = 0;
+ bool bRepaint = false;
+ if ( nType == text::TextMarkupType::SPELLCHECK )
+ {
+ pWList = mpTxtNode->GetWrong();
+ if ( !pWList )
+ {
+ pWList = new SwWrongList( WRONGLIST_SPELL );
+ mpTxtNode->SetWrong( pWList );
+ }
+ }
+ else if ( nType == text::TextMarkupType::PROOFREADING || nType == text::TextMarkupType::SENTENCE )
+ {
+ IGrammarContact *pGrammarContact = getGrammarContact( *mpTxtNode );
+ if( pGrammarContact )
+ {
+ pWList = pGrammarContact->getGrammarCheck( *mpTxtNode, true );
+ OSL_ENSURE( pWList, "GrammarContact _has_ to deliver a wrong list" );
+ }
+ else
+ {
+ pWList = mpTxtNode->GetGrammarCheck();
+ if ( !pWList )
+ {
+ mpTxtNode->SetGrammarCheck( new SwGrammarMarkUp() );
+ pWList = mpTxtNode->GetGrammarCheck();
+ }
+ }
+ bRepaint = pWList == mpTxtNode->GetGrammarCheck();
+ if( pWList->GetBeginInv() < STRING_LEN )
+ ((SwGrammarMarkUp*)pWList)->ClearGrammarList();
+ }
+ else if ( nType == text::TextMarkupType::SMARTTAG )
+ {
+ pWList = mpTxtNode->GetSmartTags();
+ if ( !pWList )
+ {
+ pWList = new SwWrongList( WRONGLIST_SMARTTAG );
+ mpTxtNode->SetSmartTags( pWList );
+ }
+ }
+ else
+ {
+ OSL_FAIL( "Unknown mark-up type" );
+ return;
+ }
+
+
+ const ModelToViewHelper::ModelPosition aStartPos =
+ ModelToViewHelper::ConvertToModelPosition( mpConversionMap, nStart );
+ const ModelToViewHelper::ModelPosition aEndPos =
+ ModelToViewHelper::ConvertToModelPosition( mpConversionMap, nStart + nLength - 1);
+
+ const bool bStartInField = aStartPos.mbIsField;
+ const bool bEndInField = aEndPos.mbIsField;
+ bool bCommit = false;
+
+ if ( bStartInField && bEndInField && aStartPos.mnPos == aEndPos.mnPos )
+ {
+ nStart = aStartPos.mnSubPos;
+ const xub_StrLen nFieldPosModel = static_cast< xub_StrLen >(aStartPos.mnPos);
+ const sal_uInt16 nInsertPos = pWList->GetWrongPos( nFieldPosModel );
+
+ SwWrongList* pSubList = pWList->SubList( nInsertPos );
+ if ( !pSubList )
+ {
+ if( nType == text::TextMarkupType::PROOFREADING || nType == text::TextMarkupType::SENTENCE )
+ pSubList = new SwGrammarMarkUp();
+ else
+ pSubList = new SwWrongList( pWList->GetWrongListType() );
+ pWList->InsertSubList( nFieldPosModel, 1, nInsertPos, pSubList );
+ }
+
+ pWList = pSubList;
+ bCommit = true;
+ }
+ else if ( !bStartInField && !bEndInField )
+ {
+ nStart = aStartPos.mnPos;
+ bCommit = true;
+ nLength = aEndPos.mnPos + 1 - aStartPos.mnPos;
+ }
+ else if( nType == text::TextMarkupType::PROOFREADING || nType == text::TextMarkupType::SENTENCE )
+ {
+ bCommit = true;
+ nStart = aStartPos.mnPos;
+ sal_Int32 nEnd = aEndPos.mnPos;
+ if( bStartInField && nType != text::TextMarkupType::SENTENCE )
+ {
+ const xub_StrLen nFieldPosModel = static_cast< xub_StrLen >(aStartPos.mnPos);
+ const sal_uInt16 nInsertPos = pWList->GetWrongPos( nFieldPosModel );
+ SwWrongList* pSubList = pWList->SubList( nInsertPos );
+ if ( !pSubList )
+ {
+ pSubList = new SwGrammarMarkUp();
+ pWList->InsertSubList( nFieldPosModel, 1, nInsertPos, pSubList );
+ }
+ const sal_uInt32 nTmpStart = ModelToViewHelper::ConvertToViewPosition( mpConversionMap, aStartPos.mnPos );
+ const sal_uInt32 nTmpLen = ModelToViewHelper::ConvertToViewPosition( mpConversionMap, aStartPos.mnPos + 1 )
+ - nTmpStart - aStartPos.mnSubPos;
+ if( nTmpLen > 0 )
+ {
+ if( nType == text::TextMarkupType::SENTENCE )
+ {
+ ((SwGrammarMarkUp*)pSubList)->setSentence( static_cast< xub_StrLen >(aStartPos.mnSubPos) );
+ bCommit = false;
+ }
+ else
+ pSubList->Insert( rIdentifier, xMarkupInfoContainer,
+ static_cast< xub_StrLen >(aStartPos.mnSubPos), static_cast< xub_StrLen >(nTmpLen) );
+ }
+ ++nStart;
+ }
+ if( bEndInField && nType != text::TextMarkupType::SENTENCE )
+ {
+ const xub_StrLen nFieldPosModel = static_cast< xub_StrLen >(aEndPos.mnPos);
+ const sal_uInt16 nInsertPos = pWList->GetWrongPos( nFieldPosModel );
+ SwWrongList* pSubList = pWList->SubList( nInsertPos );
+ if ( !pSubList )
+ {
+ pSubList = new SwGrammarMarkUp();
+ pWList->InsertSubList( nFieldPosModel, 1, nInsertPos, pSubList );
+ }
+ const sal_uInt32 nTmpLen = aEndPos.mnSubPos + 1;
+ pSubList->Insert( rIdentifier, xMarkupInfoContainer, 0, static_cast< xub_StrLen >(nTmpLen) );
+ }
+ else
+ ++nEnd;
+ if( nEnd > nStart )
+ nLength = nEnd - nStart;
+ else
+ bCommit = false;
+ }
+
+ if ( bCommit )
+ {
+ if( nType == text::TextMarkupType::SENTENCE )
+ ((SwGrammarMarkUp*)pWList)->setSentence( static_cast< xub_StrLen >(nStart) );
+ else
+ pWList->Insert( rIdentifier, xMarkupInfoContainer,
+ static_cast< xub_StrLen >(nStart), static_cast< xub_StrLen >(nLength) );
+ }
+
+ if( bRepaint )
+ finishGrammarCheck( *mpTxtNode );
+}
+
+
+void lcl_commitGrammarMarkUp(
+ const ModelToViewHelper::ConversionMap* pConversionMap,
+ SwGrammarMarkUp* pWList,
+ ::sal_Int32 nType,
+ const ::rtl::OUString & rIdentifier,
+ ::sal_Int32 nStart,
+ ::sal_Int32 nLength,
+ const uno::Reference< container::XStringKeyMap > & xMarkupInfoContainer)
+{
+ OSL_ENSURE( nType == text::TextMarkupType::PROOFREADING || nType == text::TextMarkupType::SENTENCE, "Wrong mark-up type" );
+ const ModelToViewHelper::ModelPosition aStartPos =
+ ModelToViewHelper::ConvertToModelPosition( pConversionMap, nStart );
+ const ModelToViewHelper::ModelPosition aEndPos =
+ ModelToViewHelper::ConvertToModelPosition( pConversionMap, nStart + nLength - 1);
+
+ const bool bStartInField = aStartPos.mbIsField;
+ const bool bEndInField = aEndPos.mbIsField;
+ bool bCommit = false;
+
+ if ( bStartInField && bEndInField && aStartPos.mnPos == aEndPos.mnPos )
+ {
+ nStart = aStartPos.mnSubPos;
+ const xub_StrLen nFieldPosModel = static_cast< xub_StrLen >(aStartPos.mnPos);
+ const sal_uInt16 nInsertPos = pWList->GetWrongPos( nFieldPosModel );
+
+ SwGrammarMarkUp* pSubList = (SwGrammarMarkUp*)pWList->SubList( nInsertPos );
+ if ( !pSubList )
+ {
+ pSubList = new SwGrammarMarkUp();
+ pWList->InsertSubList( nFieldPosModel, 1, nInsertPos, pSubList );
+ }
+
+ pWList = pSubList;
+ bCommit = true;
+ }
+ else if ( !bStartInField && !bEndInField )
+ {
+ nStart = aStartPos.mnPos;
+ bCommit = true;
+ nLength = aEndPos.mnPos + 1 - aStartPos.mnPos;
+ }
+ else
+ {
+ bCommit = true;
+ nStart = aStartPos.mnPos;
+ sal_Int32 nEnd = aEndPos.mnPos;
+ if( bStartInField && nType != text::TextMarkupType::SENTENCE )
+ {
+ const xub_StrLen nFieldPosModel = static_cast< xub_StrLen >(aStartPos.mnPos);
+ const sal_uInt16 nInsertPos = pWList->GetWrongPos( nFieldPosModel );
+ SwGrammarMarkUp* pSubList = (SwGrammarMarkUp*)pWList->SubList( nInsertPos );
+ if ( !pSubList )
+ {
+ pSubList = new SwGrammarMarkUp();
+ pWList->InsertSubList( nFieldPosModel, 1, nInsertPos, pSubList );
+ }
+ const sal_uInt32 nTmpStart = ModelToViewHelper::ConvertToViewPosition( pConversionMap, aStartPos.mnPos );
+ const sal_uInt32 nTmpLen = ModelToViewHelper::ConvertToViewPosition( pConversionMap, aStartPos.mnPos + 1 )
+ - nTmpStart - aStartPos.mnSubPos;
+ if( nTmpLen > 0 )
+ pSubList->Insert( rIdentifier, xMarkupInfoContainer,
+ static_cast< xub_StrLen >(aStartPos.mnSubPos), static_cast< xub_StrLen >(nTmpLen) );
+ ++nStart;
+ }
+ if( bEndInField && nType != text::TextMarkupType::SENTENCE )
+ {
+ const xub_StrLen nFieldPosModel = static_cast< xub_StrLen >(aEndPos.mnPos);
+ const sal_uInt16 nInsertPos = pWList->GetWrongPos( nFieldPosModel );
+ SwGrammarMarkUp* pSubList = (SwGrammarMarkUp*)pWList->SubList( nInsertPos );
+ if ( !pSubList )
+ {
+ pSubList = new SwGrammarMarkUp();
+ pWList->InsertSubList( nFieldPosModel, 1, nInsertPos, pSubList );
+ }
+ const sal_uInt32 nTmpLen = aEndPos.mnSubPos + 1;
+ pSubList->Insert( rIdentifier, xMarkupInfoContainer, 0, static_cast< xub_StrLen >(nTmpLen) );
+ }
+ else
+ ++nEnd;
+ if( nEnd > nStart )
+ nLength = nEnd - nStart;
+ else
+ bCommit = false;
+ }
+
+ if ( bCommit )
+ {
+ if( nType == text::TextMarkupType::SENTENCE )
+ ((SwGrammarMarkUp*)pWList)->setSentence( static_cast< xub_StrLen >(nStart+nLength) );
+ else
+ pWList->Insert( rIdentifier, xMarkupInfoContainer,
+ static_cast< xub_StrLen >(nStart), static_cast< xub_StrLen >(nLength) );
+ }
+}
+
+
+void SAL_CALL SwXTextMarkup::commitMultiTextMarkup(
+ const uno::Sequence< text::TextMarkupDescriptor > &rMarkups )
+throw (lang::IllegalArgumentException, uno::RuntimeException)
+{
+ SolarMutexGuard aGuard;
+
+ // paragraph already dead or modified?
+ if ( !mpTxtNode )
+ return;
+
+ // check for equal length of all sequnces
+ sal_Int32 nLen = rMarkups.getLength();
+
+ // for grammar checking there should be exactly one sentence markup
+ // and 0..n grammar markups.
+ // Different markups are not expected but may be applied anyway since
+ // that should be no problem...
+ // but it has to be implemented, at the moment only this function is for
+ // grammar markups and sentence markup only!
+ sal_Int32 nSentenceMarkUpIndex = -1;
+ const text::TextMarkupDescriptor *pMarkups = rMarkups.getConstArray();
+ sal_Int32 i;
+ for( i = 0; i < nLen; ++i )
+ {
+ if (pMarkups[i].nType == text::TextMarkupType::SENTENCE)
+ {
+ if (nSentenceMarkUpIndex == -1)
+ nSentenceMarkUpIndex = i;
+ else // there is already one sentence markup
+ throw lang::IllegalArgumentException();
+ }
+ else if( pMarkups[i].nType != text::TextMarkupType::PROOFREADING )
+ return;
+ }
+
+ if( nSentenceMarkUpIndex == -1 )
+ return;
+
+ // get appropriate list to use...
+ SwGrammarMarkUp* pWList = 0;
+ bool bRepaint = false;
+ IGrammarContact *pGrammarContact = getGrammarContact( *mpTxtNode );
+ if( pGrammarContact )
+ {
+ pWList = pGrammarContact->getGrammarCheck( *mpTxtNode, true );
+ OSL_ENSURE( pWList, "GrammarContact _has_ to deliver a wrong list" );
+ }
+ else
+ {
+ pWList = mpTxtNode->GetGrammarCheck();
+ if ( !pWList )
+ {
+ mpTxtNode->SetGrammarCheck( new SwGrammarMarkUp() );
+ pWList = mpTxtNode->GetGrammarCheck();
+ pWList->SetInvalid( 0, STRING_LEN );
+ }
+ }
+ bRepaint = pWList == mpTxtNode->GetGrammarCheck();
+
+ bool bAcceptGrammarError = false;
+ if( pWList->GetBeginInv() < STRING_LEN )
+ {
+ const ModelToViewHelper::ModelPosition aSentenceEnd =
+ ModelToViewHelper::ConvertToModelPosition( mpConversionMap,
+ pMarkups[nSentenceMarkUpIndex].nOffset + pMarkups[nSentenceMarkUpIndex].nLength );
+ bAcceptGrammarError = (xub_StrLen)aSentenceEnd.mnPos > pWList->GetBeginInv();
+ pWList->ClearGrammarList( (xub_StrLen)aSentenceEnd.mnPos );
+ }
+
+ if( bAcceptGrammarError )
+ {
+ for( i = 0; i < nLen; ++i )
+ {
+ const text::TextMarkupDescriptor &rDesc = pMarkups[i];
+ lcl_commitGrammarMarkUp( mpConversionMap, pWList, rDesc.nType,
+ rDesc.aIdentifier, rDesc.nOffset, rDesc.nLength, rDesc.xMarkupInfoContainer );
+ }
+ }
+ else
+ {
+ bRepaint = false;
+ i = nSentenceMarkUpIndex;
+ const text::TextMarkupDescriptor &rDesc = pMarkups[i];
+ lcl_commitGrammarMarkUp( mpConversionMap, pWList, rDesc.nType,
+ rDesc.aIdentifier, rDesc.nOffset, rDesc.nLength, rDesc.xMarkupInfoContainer );
+ }
+
+ if( bRepaint )
+ finishGrammarCheck( *mpTxtNode );
+
+ return;
+}
+
+
+void SwXTextMarkup::Modify( const SfxPoolItem* /*pOld*/, const SfxPoolItem* /*pNew*/ )
+{
+ // FME 2007-07-16 #i79641# In my opinion this is perfectly legal,
+ // therefore I remove the assertion in SwModify::_Remove()
+ if ( GetRegisteredIn() )
+ GetRegisteredInNonConst()->Remove( this );
+ // <--
+
+ SolarMutexGuard aGuard;
+ mpTxtNode = 0;
+}
+
+/*
+ * SwXStringKeyMap
+ */
+SwXStringKeyMap::SwXStringKeyMap()
+{
+}
+
+uno::Any SAL_CALL SwXStringKeyMap::getValue(const ::rtl::OUString & aKey) throw (uno::RuntimeException, container::NoSuchElementException)
+{
+ std::map< rtl::OUString, uno::Any >::const_iterator aIter = maMap.find( aKey );
+ if ( aIter == maMap.end() )
+ throw container::NoSuchElementException();
+
+ return (*aIter).second;
+}
+
+::sal_Bool SAL_CALL SwXStringKeyMap::hasValue(const ::rtl::OUString & aKey) throw (uno::RuntimeException)
+{
+ return maMap.find( aKey ) != maMap.end();
+}
+
+void SAL_CALL SwXStringKeyMap::insertValue(const ::rtl::OUString & aKey, const uno::Any & aValue) throw (uno::RuntimeException, lang::IllegalArgumentException, container::ElementExistException)
+{
+ std::map< rtl::OUString, uno::Any >::const_iterator aIter = maMap.find( aKey );
+ if ( aIter != maMap.end() )
+ throw container::ElementExistException();
+
+ maMap[ aKey ] = aValue;
+}
+
+::sal_Int32 SAL_CALL SwXStringKeyMap::getCount() throw (uno::RuntimeException)
+{
+ return maMap.size();
+}
+
+::rtl::OUString SAL_CALL SwXStringKeyMap::getKeyByIndex(::sal_Int32 nIndex) throw (uno::RuntimeException, lang::IndexOutOfBoundsException)
+{
+ if ( (sal_uInt32)nIndex >= maMap.size() )
+ throw lang::IndexOutOfBoundsException();
+
+ return ::rtl::OUString();
+}
+
+uno::Any SAL_CALL SwXStringKeyMap::getValueByIndex(::sal_Int32 nIndex) throw (uno::RuntimeException, lang::IndexOutOfBoundsException)
+{
+ if ( (sal_uInt32)nIndex >= maMap.size() )
+ throw lang::IndexOutOfBoundsException();
+
+ return uno::Any();
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/view/pagepreviewlayout.cxx b/sw/source/core/view/pagepreviewlayout.cxx
new file mode 100644
index 000000000000..fc24047a0b91
--- /dev/null
+++ b/sw/source/core/view/pagepreviewlayout.cxx
@@ -0,0 +1,1393 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+#include <pagepreviewlayout.hxx>
+#include <prevwpage.hxx>
+
+#include <algorithm>
+#include <vcl/window.hxx>
+#include <rootfrm.hxx>
+#include <pagefrm.hxx>
+#include <viewsh.hxx>
+#include <viewimp.hxx>
+#include <viewopt.hxx>
+#include <swregion.hxx>
+#include <comcore.hrc>
+#include <frmtool.hxx>
+#include <svx/zoomitem.hxx>
+#include <printdata.hxx>
+
+#include <IDocumentDeviceAccess.hxx>
+
+// method to update statics for paint
+// Note: method defined in '/sw/source/core/layout/paintfrm.cxx'
+extern void SwCalcPixStatics( OutputDevice *pOut );
+
+// =============================================================================
+// methods to initialize page preview layout
+// =============================================================================
+SwPagePreviewLayout::SwPagePreviewLayout( ViewShell& _rParentViewShell,
+ const SwRootFrm& _rLayoutRootFrm )
+ : mnXFree ( 4*142 ),
+ mnYFree ( 4*142 ),
+ mrParentViewShell( _rParentViewShell ),
+ mrLayoutRootFrm ( _rLayoutRootFrm )
+{
+ _Clear();
+
+ mbBookPreview = false;
+ mbBookPreviewModeToggled = false;
+
+ mbPrintEmptyPages = mrParentViewShell.getIDocumentDeviceAccess()->getPrintData().IsPrintEmptyPages();
+}
+
+void SwPagePreviewLayout::_Clear()
+{
+ mbLayoutInfoValid = mbLayoutSizesValid = mbPaintInfoValid = false;
+
+ maWinSize.Width() = 0;
+ maWinSize.Height() = 0;
+ mnCols = mnRows = 0;
+
+ _ClearPrevwLayoutSizes();
+
+ mbDoesLayoutRowsFitIntoWindow = false;
+ mbDoesLayoutColsFitIntoWindow = false;
+
+ mnPaintPhyStartPageNum = 0;
+ mnPaintStartCol = mnPaintStartRow = 0;
+ mbNoPageVisible = false;
+ maPaintStartPageOffset.X() = 0;
+ maPaintStartPageOffset.Y() = 0;
+ maPaintPreviewDocOffset.X() = 0;
+ maPaintPreviewDocOffset.Y() = 0;
+ maAdditionalPaintOffset.X() = 0;
+ maAdditionalPaintOffset.Y() = 0;
+ maPaintedPrevwDocRect.Left() = 0;
+ maPaintedPrevwDocRect.Top() = 0;
+ maPaintedPrevwDocRect.Right() = 0;
+ maPaintedPrevwDocRect.Bottom() = 0;
+ mnSelectedPageNum = 0;
+ _ClearPrevwPageData();
+
+ mbInPaint = false;
+ mbNewLayoutDuringPaint = false;
+}
+
+void SwPagePreviewLayout::_ClearPrevwLayoutSizes()
+{
+ mnPages = 0;
+
+ maMaxPageSize.Width() = 0;
+ maMaxPageSize.Height() = 0;
+ maPreviewDocRect.Left() = maPreviewDocRect.Top() = 0;
+ maPreviewDocRect.Right() = maPreviewDocRect.Bottom() = 0;
+ mnColWidth = mnRowHeight = 0;
+ mnPrevwLayoutWidth = mnPrevwLayoutHeight = 0;
+}
+
+void SwPagePreviewLayout::_ClearPrevwPageData()
+{
+ for ( std::vector<PrevwPage*>::iterator aPageDelIter = maPrevwPages.begin();
+ aPageDelIter != maPrevwPages.end();
+ ++aPageDelIter )
+ {
+ delete (*aPageDelIter);
+ }
+ maPrevwPages.clear();
+}
+
+void SwPagePreviewLayout::_CalcPrevwLayoutSizes()
+{
+ // calculate maximal page size; calculate also number of pages
+
+ const SwPageFrm* pPage = static_cast<const SwPageFrm*>(mrLayoutRootFrm.Lower());
+ while ( pPage )
+ {
+ if ( !mbBookPreview && !mbPrintEmptyPages && pPage->IsEmptyPage() )
+ {
+ pPage = static_cast<const SwPageFrm*>(pPage->GetNext());
+ continue;
+ }
+
+ ++mnPages;
+ pPage->Calc();
+ const Size& rPageSize = pPage->Frm().SSize();
+ if ( rPageSize.Width() > maMaxPageSize.Width() )
+ maMaxPageSize.Width() = rPageSize.Width();
+ if ( rPageSize.Height() > maMaxPageSize.Height() )
+ maMaxPageSize.Height() = rPageSize.Height();
+ pPage = static_cast<const SwPageFrm*>(pPage->GetNext());
+ }
+ // calculate and set column width and row height
+ mnColWidth = maMaxPageSize.Width() + mnXFree;
+ mnRowHeight = maMaxPageSize.Height() + mnYFree;
+
+ // calculate and set preview layout width and height
+ mnPrevwLayoutWidth = mnCols * mnColWidth + mnXFree;
+ mnPrevwLayoutHeight = mnRows * mnRowHeight + mnYFree;
+
+ // calculate document rectangle in preview layout
+ {
+ Size aDocSize;
+ // document width
+ aDocSize.Width() = mnPrevwLayoutWidth;
+
+ // document height
+ // determine number of rows needed for <nPages> in preview layout
+ sal_uInt16 nDocRows = GetRowOfPage( mnPages );
+ aDocSize.Height() = nDocRows * maMaxPageSize.Height() +
+ (nDocRows+1) * mnYFree;
+ maPreviewDocRect.SetPos( Point( 0, 0 ) );
+ maPreviewDocRect.SetSize( aDocSize );
+ }
+}
+
+/** init page preview layout
+
+ initialize the page preview settings for a given layout.
+ side effects:
+ (1) If parameter <_bCalcScale> is true, mapping mode with calculated
+ scaling is set at the output device and the zoom at the view options of
+ the given view shell is set with the calculated scaling.
+
+*/
+bool SwPagePreviewLayout::Init( const sal_uInt16 _nCols,
+ const sal_uInt16 _nRows,
+ const Size& _rPxWinSize,
+ const bool _bCalcScale
+ )
+{
+ // check environment and parameters
+ {
+ bool bColsRowsValid = (_nCols != 0) && (_nRows != 0);
+ OSL_ENSURE( bColsRowsValid, "preview layout parameters not correct - preview layout can *not* be initialized" );
+ if ( !bColsRowsValid )
+ return false;
+
+ bool bPxWinSizeValid = (_rPxWinSize.Width() >= 0) &&
+ (_rPxWinSize.Height() >= 0);
+ OSL_ENSURE( bPxWinSizeValid, "no window size - preview layout can *not* be initialized" );
+ if ( !bPxWinSizeValid )
+ return false;
+ }
+
+ // environment and parameters ok
+
+ // clear existing preview settings
+ _Clear();
+
+ // set layout information columns and rows
+ mnCols = _nCols;
+ mnRows = _nRows;
+
+ _CalcPrevwLayoutSizes();
+
+ // validate layout information
+ mbLayoutInfoValid = true;
+
+ if ( _bCalcScale )
+ {
+ // calculate scaling
+ MapMode aMapMode( MAP_TWIP );
+ Size aWinSize = mrParentViewShell.GetOut()->PixelToLogic( _rPxWinSize, aMapMode );
+ Fraction aXScale( aWinSize.Width(), mnPrevwLayoutWidth );
+ Fraction aYScale( aWinSize.Height(), mnPrevwLayoutHeight );
+ if( aXScale < aYScale )
+ aYScale = aXScale;
+ {
+ // adjust scaling for Drawing layer.
+ aYScale *= Fraction( 1000, 1 );
+ long nNewNuminator = aYScale.operator long();
+ if( nNewNuminator < 1 )
+ nNewNuminator = 1;
+ aYScale = Fraction( nNewNuminator, 1000 );
+ // propagate scaling as zoom percentage to view options for font cache
+ _ApplyNewZoomAtViewShell( static_cast<sal_uInt8>(nNewNuminator/10) );
+ }
+ aMapMode.SetScaleY( aYScale );
+ aMapMode.SetScaleX( aYScale );
+ // set created mapping mode with calculated scaling at output device.
+ mrParentViewShell.GetOut()->SetMapMode( aMapMode );
+ ::SwCalcPixStatics( mrParentViewShell.GetOut() );
+ }
+
+ // set window size in twips
+ maWinSize = mrParentViewShell.GetOut()->PixelToLogic( _rPxWinSize );
+ // validate layout sizes
+ mbLayoutSizesValid = true;
+
+ return true;
+}
+
+void SwPagePreviewLayout::_ApplyNewZoomAtViewShell( sal_uInt8 _aNewZoom )
+{
+ SwViewOption aNewViewOptions = *(mrParentViewShell.GetViewOptions());
+ if ( aNewViewOptions.GetZoom() != _aNewZoom )
+ {
+ aNewViewOptions.SetZoom( _aNewZoom );
+ //#i19975# - consider zoom type.
+ enum SvxZoomType eZoomType = SVX_ZOOM_PERCENT;
+ aNewViewOptions.SetZoomType( eZoomType );
+ mrParentViewShell.ApplyViewOptions( aNewViewOptions );
+ }
+}
+
+bool SwPagePreviewLayout::ReInit()
+{
+ // check environment and parameters
+ {
+ bool bLayoutSettingsValid = mbLayoutInfoValid && mbLayoutSizesValid;
+ OSL_ENSURE( bLayoutSettingsValid,
+ "no valid preview layout info/sizes - no re-init of page preview layout");
+ if ( !bLayoutSettingsValid )
+ return false;
+ }
+
+ _ClearPrevwLayoutSizes();
+ _CalcPrevwLayoutSizes();
+
+ return true;
+}
+
+// =============================================================================
+// methods to prepare paint of page preview
+// =============================================================================
+
+// _nProposedStartPageNum, _onStartPageNum are absolute
+bool SwPagePreviewLayout::Prepare( const sal_uInt16 _nProposedStartPageNum,
+ const Point _aProposedStartPos,
+ const Size& _rPxWinSize,
+ sal_uInt16& _onStartPageNum,
+ Rectangle& _orDocPreviewPaintRect,
+ const bool _bStartWithPageAtFirstCol
+ )
+{
+ sal_uInt16 nProposedStartPageNum = ConvertAbsoluteToRelativePageNum( _nProposedStartPageNum );
+ // check environment and parameters
+ {
+ bool bLayoutSettingsValid = mbLayoutInfoValid && mbLayoutSizesValid;
+ OSL_ENSURE( bLayoutSettingsValid,
+ "no valid preview layout info/sizes - no prepare of preview paint");
+ if ( !bLayoutSettingsValid )
+ return false;
+
+ bool bStartPageRangeValid = nProposedStartPageNum <= mnPages;
+ OSL_ENSURE( bStartPageRangeValid,
+ "proposed start page not existing - no prepare of preview paint");
+ if ( !bStartPageRangeValid )
+ return false;
+
+ bool bStartPosRangeValid =
+ _aProposedStartPos.X() >= 0 && _aProposedStartPos.Y() >= 0 &&
+ _aProposedStartPos.X() <= maPreviewDocRect.Right() &&
+ _aProposedStartPos.Y() <= maPreviewDocRect.Bottom();
+ OSL_ENSURE( bStartPosRangeValid,
+ "proposed start position out of range - no prepare of preview paint");
+ if ( !bStartPosRangeValid )
+ return false;
+
+ bool bWinSizeValid = _rPxWinSize.Width() != 0 && _rPxWinSize.Height() != 0;
+ OSL_ENSURE( bWinSizeValid, "no window size - no prepare of preview paint");
+ if ( !bWinSizeValid )
+ return false;
+
+ bool bStartInfoValid = _nProposedStartPageNum > 0 ||
+ _aProposedStartPos != Point(0,0);
+ if ( !bStartInfoValid )
+ nProposedStartPageNum = 1;
+ }
+
+ // environment and parameter ok
+
+ // update window size at preview setting data
+ maWinSize = mrParentViewShell.GetOut()->PixelToLogic( _rPxWinSize );
+
+ mbNoPageVisible = false;
+ if ( nProposedStartPageNum > 0 )
+ {
+ // determine column and row of proposed start page in virtual preview layout
+ sal_uInt16 nColOfProposed = GetColOfPage( nProposedStartPageNum );
+ sal_uInt16 nRowOfProposed = GetRowOfPage( nProposedStartPageNum );
+ // determine start page
+ if ( _bStartWithPageAtFirstCol )
+ {
+ // leaving left-top-corner blank is controlled by <mbBookPreview>.
+ if ( mbBookPreview &&
+ ( nProposedStartPageNum == 1 || nRowOfProposed == 1 )
+ )
+ mnPaintPhyStartPageNum = 1;
+ else
+ mnPaintPhyStartPageNum = nProposedStartPageNum - (nColOfProposed-1);
+ }
+ else
+ mnPaintPhyStartPageNum = nProposedStartPageNum;
+
+ mnPaintPhyStartPageNum = ConvertRelativeToAbsolutePageNum( mnPaintPhyStartPageNum );
+
+ // set starting column
+ if ( _bStartWithPageAtFirstCol )
+ mnPaintStartCol = 1;
+ else
+ mnPaintStartCol = nColOfProposed;
+ // set starting row
+ mnPaintStartRow = nRowOfProposed;
+ // page offset == (-1,-1), indicating no offset and paint of free space.
+ maPaintStartPageOffset.X() = -1;
+ maPaintStartPageOffset.Y() = -1;
+ // virtual preview document offset.
+ if ( _bStartWithPageAtFirstCol )
+ maPaintPreviewDocOffset.X() = 0;
+ else
+ maPaintPreviewDocOffset.X() = (nColOfProposed-1) * mnColWidth;
+ maPaintPreviewDocOffset.Y() = (nRowOfProposed-1) * mnRowHeight;
+ }
+ else
+ {
+ // determine column and row of proposed start position.
+ // Note: paint starts at point (0,0)
+ sal_uInt16 nColOfProposed =
+ static_cast<sal_uInt16>(_aProposedStartPos.X() / mnColWidth) + 1;
+ sal_uInt16 nRowOfProposed =
+ static_cast<sal_uInt16>(_aProposedStartPos.Y() / mnRowHeight) + 1;
+ // determine start page == page at proposed start position
+ // leaving left-top-corner blank is controlled by <mbBookPreview>.
+ if ( mbBookPreview &&
+ ( nRowOfProposed == 1 && nColOfProposed == 1 )
+ )
+ mnPaintPhyStartPageNum = 1;
+ else
+ {
+ // leaving left-top-corner blank is controlled by <mbBookPreview>.
+ mnPaintPhyStartPageNum = (nRowOfProposed-1) * mnCols + nColOfProposed;
+ if ( mbBookPreview )
+ --mnPaintPhyStartPageNum;
+ if ( mnPaintPhyStartPageNum > mnPages )
+ {
+ // no page will be visible, because shown part of document
+ // preview is the last row to the right of the last page
+ mnPaintPhyStartPageNum = mnPages;
+ mbNoPageVisible = true;
+ }
+ }
+ // set starting column and starting row
+ mnPaintStartCol = nColOfProposed;
+ mnPaintStartRow = nRowOfProposed;
+ // page offset
+ maPaintStartPageOffset.X() =
+ (_aProposedStartPos.X() % mnColWidth) - mnXFree;
+ maPaintStartPageOffset.Y() =
+ (_aProposedStartPos.Y() % mnRowHeight) - mnYFree;
+ // virtual preview document offset.
+ maPaintPreviewDocOffset = _aProposedStartPos;
+ }
+
+ // determine additional paint offset, if preview layout fits into window.
+ _CalcAdditionalPaintOffset();
+
+ // determine rectangle to be painted from document preview
+ _CalcDocPrevwPaintRect();
+ _orDocPreviewPaintRect = maPaintedPrevwDocRect;
+
+ // shift visible preview document area to the left,if on the right is an area left blank.
+ if ( !mbDoesLayoutColsFitIntoWindow &&
+ maPaintedPrevwDocRect.GetWidth() < maWinSize.Width() )
+ {
+ maPaintedPrevwDocRect.Move(
+ -(maWinSize.Width() - maPaintedPrevwDocRect.GetWidth()), 0 );
+ Prepare( 0, maPaintedPrevwDocRect.TopLeft(),
+ _rPxWinSize, _onStartPageNum,
+ _orDocPreviewPaintRect, _bStartWithPageAtFirstCol );
+ }
+ // shift visible preview document area to the left,if on the right is an area left blank.
+ if ( mbBookPreviewModeToggled &&
+ maPaintedPrevwDocRect.Bottom() == maPreviewDocRect.Bottom() &&
+ maPaintedPrevwDocRect.GetHeight() < maWinSize.Height() )
+ {
+ if ( mbDoesLayoutRowsFitIntoWindow )
+ {
+ if ( maPaintedPrevwDocRect.GetHeight() < mnPrevwLayoutHeight)
+ {
+ maPaintedPrevwDocRect.Move(
+ 0, -(mnPrevwLayoutHeight - maPaintedPrevwDocRect.GetHeight()) );
+ Prepare( 0, maPaintedPrevwDocRect.TopLeft(),
+ _rPxWinSize, _onStartPageNum,
+ _orDocPreviewPaintRect, _bStartWithPageAtFirstCol );
+ }
+ }
+ else
+ {
+ maPaintedPrevwDocRect.Move(
+ 0, -(maWinSize.Height() - maPaintedPrevwDocRect.GetHeight()) );
+ Prepare( 0, maPaintedPrevwDocRect.TopLeft(),
+ _rPxWinSize, _onStartPageNum,
+ _orDocPreviewPaintRect, _bStartWithPageAtFirstCol );
+ }
+ }
+
+ // determine preview pages - visible pages with needed data for paint and
+ // accessible pages with needed data.
+ _CalcPreviewPages();
+
+ // indicate new layout, if print preview is in paint
+ if ( mbInPaint )
+ {
+ mbNewLayoutDuringPaint = true;
+ }
+
+ // validate paint data
+ mbPaintInfoValid = true;
+
+ // return start page
+ _onStartPageNum = mnPaintPhyStartPageNum;
+
+ return true;
+}
+
+void SwPagePreviewLayout::_CalcAdditionalPaintOffset()
+{
+ if ( mnPrevwLayoutWidth <= maWinSize.Width() &&
+ maPaintStartPageOffset.X() <= 0 )
+ {
+ mbDoesLayoutColsFitIntoWindow = true;
+ maAdditionalPaintOffset.X() = (maWinSize.Width() - mnPrevwLayoutWidth) / 2;
+ }
+ else
+ {
+ mbDoesLayoutColsFitIntoWindow = false;
+ maAdditionalPaintOffset.X() = 0;
+ }
+
+ if ( mnPrevwLayoutHeight <= maWinSize.Height() &&
+ maPaintStartPageOffset.Y() <= 0 )
+ {
+ mbDoesLayoutRowsFitIntoWindow = true;
+ maAdditionalPaintOffset.Y() = (maWinSize.Height() - mnPrevwLayoutHeight) / 2;
+ }
+ else
+ {
+ mbDoesLayoutRowsFitIntoWindow = false;
+ maAdditionalPaintOffset.Y() = 0;
+ }
+}
+
+void SwPagePreviewLayout::_CalcDocPrevwPaintRect()
+{
+ Point aTopLeftPos = maPaintPreviewDocOffset;
+ maPaintedPrevwDocRect.SetPos( aTopLeftPos );
+
+ Size aSize;
+ if ( mbDoesLayoutColsFitIntoWindow )
+ aSize.Width() = Min( mnPrevwLayoutWidth,
+ maPreviewDocRect.GetWidth() - aTopLeftPos.X() );
+ else
+ aSize.Width() = Min( maPreviewDocRect.GetWidth() - aTopLeftPos.X(),
+ maWinSize.Width() - maAdditionalPaintOffset.X() );
+ if ( mbDoesLayoutRowsFitIntoWindow )
+ aSize.Height() = Min( mnPrevwLayoutHeight,
+ maPreviewDocRect.GetHeight() - aTopLeftPos.Y() );
+ else
+ aSize.Height() = Min( maPreviewDocRect.GetHeight() - aTopLeftPos.Y(),
+ maWinSize.Height() - maAdditionalPaintOffset.Y() );
+ maPaintedPrevwDocRect.SetSize( aSize );
+}
+
+void SwPagePreviewLayout::_CalcPreviewPages()
+{
+ _ClearPrevwPageData();
+
+ if ( mbNoPageVisible )
+ return;
+
+ // determine start page frame
+ const SwPageFrm* pStartPage = mrLayoutRootFrm.GetPageByPageNum( mnPaintPhyStartPageNum );
+
+ // calculate initial paint offset
+ Point aInitialPaintOffset;
+ if ( maPaintStartPageOffset != Point( -1, -1 ) )
+ aInitialPaintOffset = Point(0,0) - maPaintStartPageOffset;
+ else
+ aInitialPaintOffset = Point( mnXFree, mnYFree );
+ aInitialPaintOffset += maAdditionalPaintOffset;
+
+ // prepare loop data
+ const SwPageFrm* pPage = pStartPage;
+ sal_uInt16 nCurrCol = mnPaintStartCol;
+ sal_uInt16 nConsideredRows = 0;
+ Point aCurrPaintOffset = aInitialPaintOffset;
+ // loop on pages to determine preview background retangles
+ while ( pPage &&
+ (!mbDoesLayoutRowsFitIntoWindow || nConsideredRows < mnRows) &&
+ aCurrPaintOffset.Y() < maWinSize.Height()
+ )
+ {
+ if ( !mbBookPreview && !mbPrintEmptyPages && pPage->IsEmptyPage() )
+ {
+ pPage = static_cast<const SwPageFrm*>(pPage->GetNext());
+ continue;
+ }
+
+ pPage->Calc();
+
+ // consider only pages, which have to be painted.
+ if ( nCurrCol < mnPaintStartCol )
+ {
+ // calculate data of unvisible page needed for accessibility
+ PrevwPage* pPrevwPage = new PrevwPage;
+ Point aCurrAccOffset = aCurrPaintOffset -
+ Point( (mnPaintStartCol-nCurrCol) * mnColWidth, 0 );
+ _CalcPreviewDataForPage( *(pPage), aCurrAccOffset, pPrevwPage );
+ pPrevwPage->bVisible = false;
+ maPrevwPages.push_back( pPrevwPage );
+ // continue with next page and next column
+ pPage = static_cast<const SwPageFrm*>(pPage->GetNext());
+ ++nCurrCol;
+ continue;
+ }
+ if ( aCurrPaintOffset.X() < maWinSize.Width() )
+ {
+ // leaving left-top-corner blank is controlled by <mbBookPreview>.
+ if ( mbBookPreview && pPage->GetPhyPageNum() == 1 && mnCols != 1 && nCurrCol == 1
+ )
+ {
+ // first page in 2nd column
+ // --> continue with increased paint offset and next column
+ aCurrPaintOffset.X() += mnColWidth;
+ ++nCurrCol;
+ continue;
+ }
+
+ // calculate data of visible page
+ PrevwPage* pPrevwPage = new PrevwPage;
+ _CalcPreviewDataForPage( *(pPage), aCurrPaintOffset, pPrevwPage );
+ pPrevwPage->bVisible = true;
+ maPrevwPages.push_back( pPrevwPage );
+ }
+ else
+ {
+ // calculate data of unvisible page needed for accessibility
+ PrevwPage* pPrevwPage = new PrevwPage;
+ _CalcPreviewDataForPage( *(pPage), aCurrPaintOffset, pPrevwPage );
+ pPrevwPage->bVisible = false;
+ maPrevwPages.push_back( pPrevwPage );
+ }
+
+ // prepare data for next loop
+ pPage = static_cast<const SwPageFrm*>(pPage->GetNext());
+
+ aCurrPaintOffset.X() += mnColWidth;
+ ++nCurrCol;
+ if ( nCurrCol > mnCols )
+ {
+ ++nConsideredRows;
+ aCurrPaintOffset.X() = aInitialPaintOffset.X();
+ nCurrCol = 1;
+ aCurrPaintOffset.Y() += mnRowHeight;
+ }
+ }
+}
+
+bool SwPagePreviewLayout::_CalcPreviewDataForPage( const SwPageFrm& _rPage,
+ const Point& _rPrevwOffset,
+ PrevwPage* _opPrevwPage )
+{
+ // page frame
+ _opPrevwPage->pPage = &_rPage;
+ // size of page frame
+ if ( _rPage.IsEmptyPage() )
+ {
+ if ( _rPage.GetPhyPageNum() % 2 == 0 )
+ _opPrevwPage->aPageSize = _rPage.GetPrev()->Frm().SSize();
+ else
+ _opPrevwPage->aPageSize = _rPage.GetNext()->Frm().SSize();
+ }
+ else
+ _opPrevwPage->aPageSize = _rPage.Frm().SSize();
+ // position of page in preview window
+ Point aPrevwWinOffset( _rPrevwOffset );
+ if ( _opPrevwPage->aPageSize.Width() < maMaxPageSize.Width() )
+ aPrevwWinOffset.X() += ( maMaxPageSize.Width() - _opPrevwPage->aPageSize.Width() ) / 2;
+ if ( _opPrevwPage->aPageSize.Height() < maMaxPageSize.Height() )
+ aPrevwWinOffset.Y() += ( maMaxPageSize.Height() - _opPrevwPage->aPageSize.Height() ) / 2;
+ _opPrevwPage->aPrevwWinPos = aPrevwWinOffset;
+ // logic position of page and mapping offset for paint
+ if ( _rPage.IsEmptyPage() )
+ {
+ _opPrevwPage->aLogicPos = _opPrevwPage->aPrevwWinPos;
+ _opPrevwPage->aMapOffset = Point( 0, 0 );
+ }
+ else
+ {
+ _opPrevwPage->aLogicPos = _rPage.Frm().Pos();
+ _opPrevwPage->aMapOffset = _opPrevwPage->aPrevwWinPos - _opPrevwPage->aLogicPos;
+ }
+
+ return true;
+}
+
+bool SwPagePreviewLayout::SetBookPreviewMode( const bool _bEnableBookPreview,
+ sal_uInt16& _onStartPageNum,
+ Rectangle& _orDocPreviewPaintRect )
+{
+ bool bRet = false;
+
+ if ( mbBookPreview != _bEnableBookPreview)
+ {
+ mbBookPreview = _bEnableBookPreview;
+ // re-initialize page preview layout
+ ReInit();
+ // re-prepare page preview layout
+ {
+ mbBookPreviewModeToggled = true;
+ Point aProposedStartPos( maPaintPreviewDocOffset );
+ // if proposed start position is below virtual preview document
+ // bottom, adjust it to the virtual preview document bottom
+ if ( aProposedStartPos.Y() > maPreviewDocRect.Bottom() )
+ {
+ aProposedStartPos.Y() = maPreviewDocRect.Bottom();
+ }
+ Prepare( 0, aProposedStartPos,
+ mrParentViewShell.GetOut()->LogicToPixel( maWinSize ),
+ _onStartPageNum, _orDocPreviewPaintRect );
+ mbBookPreviewModeToggled = false;
+ }
+
+ bRet = true;
+ }
+
+ return bRet;
+}
+
+// =============================================================================
+// methods to determine new data for changing the current shown part of the
+// document preview.
+// =============================================================================
+
+Point SwPagePreviewLayout::GetPreviewStartPosForNewScale(
+ const Fraction& _aNewScale,
+ const Fraction& _aOldScale,
+ const Size& _aNewWinSize ) const
+{
+ Point aNewPaintStartPos = maPaintedPrevwDocRect.TopLeft();
+ if ( _aNewScale < _aOldScale )
+ {
+ // increase paint width by moving start point to left.
+ if ( mnPrevwLayoutWidth < _aNewWinSize.Width() )
+ aNewPaintStartPos.X() = 0;
+ else if ( maPaintedPrevwDocRect.GetWidth() < _aNewWinSize.Width() )
+ {
+ aNewPaintStartPos.X() -=
+ (_aNewWinSize.Width() - maPaintedPrevwDocRect.GetWidth()) / 2;
+ if ( aNewPaintStartPos.X() < 0)
+ aNewPaintStartPos.X() = 0;
+ }
+
+ if ( !mbDoesLayoutRowsFitIntoWindow )
+ {
+ // increase paint height by moving start point to top.
+ if ( mnPrevwLayoutHeight < _aNewWinSize.Height() )
+ {
+ aNewPaintStartPos.Y() =
+ ( (mnPaintStartRow - 1) * mnRowHeight );
+ }
+ else if ( maPaintedPrevwDocRect.GetHeight() < _aNewWinSize.Height() )
+ {
+ aNewPaintStartPos.Y() -=
+ (_aNewWinSize.Height() - maPaintedPrevwDocRect.GetHeight()) / 2;
+ if ( aNewPaintStartPos.Y() < 0)
+ aNewPaintStartPos.Y() = 0;
+ }
+ }
+ }
+ else
+ {
+ // decrease paint width by moving start point to right
+ if ( maPaintedPrevwDocRect.GetWidth() > _aNewWinSize.Width() )
+ aNewPaintStartPos.X() +=
+ (maPaintedPrevwDocRect.GetWidth() - _aNewWinSize.Width()) / 2;
+ // decrease paint height by moving start point to bottom
+ if ( maPaintedPrevwDocRect.GetHeight() > _aNewWinSize.Height() )
+ {
+ aNewPaintStartPos.Y() +=
+ (maPaintedPrevwDocRect.GetHeight() - _aNewWinSize.Height()) / 2;
+ // check, if new y-position is outside document preview
+ if ( aNewPaintStartPos.Y() > maPreviewDocRect.Bottom() )
+ aNewPaintStartPos.Y() =
+ Max( 0L, maPreviewDocRect.Bottom() - mnPrevwLayoutHeight );
+ }
+ }
+
+ return aNewPaintStartPos;
+}
+
+/** determines, if page with given page number is visible in preview
+
+ @author OD, _nPageNum is absolut!
+*/
+bool SwPagePreviewLayout::IsPageVisible( const sal_uInt16 _nPageNum ) const
+{
+ const PrevwPage* pPrevwPage = _GetPrevwPageByPageNum( _nPageNum );
+ return pPrevwPage && pPrevwPage->bVisible;
+}
+
+/** calculate data to bring new selected page into view.
+
+ @author OD, IN/OUT parameters are absolute page numbers!!!
+*/
+bool SwPagePreviewLayout::CalcStartValuesForSelectedPageMove(
+ const sal_Int16 _nHoriMove,
+ const sal_Int16 _nVertMove,
+ sal_uInt16& _orNewSelectedPage,
+ sal_uInt16& _orNewStartPage,
+ Point& _orNewStartPos ) const
+{
+ // determine position of current selected page
+ sal_uInt16 nTmpRelSelPageNum = ConvertAbsoluteToRelativePageNum( mnSelectedPageNum );
+ sal_uInt16 nNewRelSelectedPageNum = nTmpRelSelPageNum;
+
+ // leaving left-top-corner blank is controlled
+ // by <mbBookPreview>.
+ if ( mbBookPreview )
+ {
+ // Note: consider that left-top-corner is left blank --> +1
+ ++nTmpRelSelPageNum;
+ }
+ sal_uInt16 nTmpCol = nTmpRelSelPageNum % mnCols;
+ sal_uInt16 nCurrRow = nTmpRelSelPageNum / mnCols;
+ if ( nTmpCol > 0 )
+ ++nCurrRow;
+
+ // determine new selected page number
+ {
+ if ( _nHoriMove != 0 )
+ {
+ if ( (nNewRelSelectedPageNum + _nHoriMove) < 1 )
+ nNewRelSelectedPageNum = 1;
+ else if ( (nNewRelSelectedPageNum + _nHoriMove) > mnPages )
+ nNewRelSelectedPageNum = mnPages;
+ else
+ nNewRelSelectedPageNum = nNewRelSelectedPageNum + _nHoriMove;
+ }
+ if ( _nVertMove != 0 )
+ {
+ if ( (nNewRelSelectedPageNum + (_nVertMove * mnCols)) < 1 )
+ nNewRelSelectedPageNum = 1;
+ else if ( (nNewRelSelectedPageNum + (_nVertMove * mnCols)) > mnPages )
+ nNewRelSelectedPageNum = mnPages;
+ else
+ nNewRelSelectedPageNum += ( _nVertMove * mnCols );
+ }
+ }
+
+ sal_uInt16 nNewStartPage = mnPaintPhyStartPageNum;
+ Point aNewStartPos = Point(0,0);
+
+ sal_uInt16 nNewAbsSelectedPageNum = ConvertRelativeToAbsolutePageNum( nNewRelSelectedPageNum );
+ if ( !IsPageVisible( nNewAbsSelectedPageNum ) )
+ {
+ if ( _nHoriMove != 0 && _nVertMove != 0 )
+ {
+ OSL_FAIL( "missing implementation for moving preview selected page horizontal AND vertical");
+ return false;
+ }
+
+ // new selected page has to be brought into view considering current
+ // visible preview.
+ sal_Int16 nTotalRows = GetRowOfPage( mnPages );
+ if ( (_nHoriMove > 0 || _nVertMove > 0) &&
+ mbDoesLayoutRowsFitIntoWindow &&
+ mbDoesLayoutColsFitIntoWindow &&
+ nCurrRow > nTotalRows - mnRows )
+ {
+ // new proposed start page = left-top-corner of last possible
+ // preview page.
+ nNewStartPage = (nTotalRows - mnRows) * mnCols + 1;
+ // leaving left-top-corner blank is controlled
+ // by <mbBookPreview>.
+ if ( mbBookPreview )
+ {
+ // Note: decrease new proposed start page number by one,
+ // because of blank left-top-corner
+ --nNewStartPage;
+ }
+ nNewStartPage = ConvertRelativeToAbsolutePageNum( nNewStartPage );
+ }
+ else
+ {
+ // new proposed start page = new selected page.
+ nNewStartPage = ConvertRelativeToAbsolutePageNum( nNewRelSelectedPageNum );
+ }
+ }
+
+ _orNewSelectedPage = nNewAbsSelectedPageNum;
+ _orNewStartPage = nNewStartPage;
+ _orNewStartPos = aNewStartPos;
+
+ return true;
+}
+
+/** checks, if given position is inside a shown document page
+
+ @author OD
+*/
+struct PrevwPosInsidePagePred
+{
+ const Point mnPrevwPos;
+ PrevwPosInsidePagePred( const Point _nPrevwPos ) : mnPrevwPos( _nPrevwPos ) {};
+ bool operator() ( const PrevwPage* _pPrevwPage )
+ {
+ if ( _pPrevwPage->bVisible )
+ {
+ Rectangle aPrevwPageRect( _pPrevwPage->aPrevwWinPos, _pPrevwPage->aPageSize );
+ return aPrevwPageRect.IsInside( mnPrevwPos ) ? true : false;
+ }
+ else
+ return false;
+ }
+};
+
+bool SwPagePreviewLayout::IsPrevwPosInDocPrevwPage( const Point _aPrevwPos,
+ Point& _orDocPos,
+ bool& _obPosInEmptyPage,
+ sal_uInt16& _onPageNum ) const
+{
+ bool bIsPosInsideDoc;
+
+ // initialize variable parameter values.
+ _orDocPos.X() = 0;
+ _orDocPos.Y() = 0;
+ _obPosInEmptyPage = false;
+ _onPageNum = 0;
+
+ std::vector<PrevwPage*>::const_iterator aFoundPrevwPageIter =
+ std::find_if( maPrevwPages.begin(), maPrevwPages.end(),
+ PrevwPosInsidePagePred( _aPrevwPos ) );
+
+ if ( aFoundPrevwPageIter == maPrevwPages.end() )
+ // given preview position outside a document page.
+ bIsPosInsideDoc = false;
+ else
+ {
+ _onPageNum = (*aFoundPrevwPageIter)->pPage->GetPhyPageNum();
+ if ( (*aFoundPrevwPageIter)->pPage->IsEmptyPage() )
+ {
+ // given preview position inside an empty page
+ bIsPosInsideDoc = false;
+ _obPosInEmptyPage = true;
+ }
+ else
+ {
+ // given preview position inside a normal page
+ bIsPosInsideDoc = true;
+ _orDocPos = _aPrevwPos -
+ (*aFoundPrevwPageIter)->aPrevwWinPos +
+ (*aFoundPrevwPageIter)->aLogicPos;
+ }
+ }
+
+ return bIsPosInsideDoc;
+}
+
+/** determine window page scroll amount
+
+ @author OD
+*/
+SwTwips SwPagePreviewLayout::GetWinPagesScrollAmount(
+ const sal_Int16 _nWinPagesToScroll ) const
+{
+ SwTwips nScrollAmount;
+ if ( mbDoesLayoutRowsFitIntoWindow )
+ {
+ nScrollAmount = (mnPrevwLayoutHeight - mnYFree) * _nWinPagesToScroll;
+ }
+ else
+ nScrollAmount = _nWinPagesToScroll * maPaintedPrevwDocRect.GetHeight();
+
+ // check, if preview layout size values are valid.
+ // If not, the checks for an adjustment of the scroll amount aren't useful.
+ if ( mbLayoutSizesValid )
+ {
+ if ( (maPaintedPrevwDocRect.Top() + nScrollAmount) <= 0 )
+ nScrollAmount = -maPaintedPrevwDocRect.Top();
+
+ // correct scroll amount
+ if ( nScrollAmount > 0 &&
+ maPaintedPrevwDocRect.Bottom() == maPreviewDocRect.Bottom()
+ )
+ {
+ nScrollAmount = 0;
+ }
+ else
+ {
+ while ( (maPaintedPrevwDocRect.Top() + nScrollAmount + mnYFree) >= maPreviewDocRect.GetHeight() )
+ {
+ nScrollAmount -= mnRowHeight;
+ }
+ }
+ }
+
+ return nScrollAmount;
+}
+
+// =============================================================================
+// methods to paint page preview layout
+// =============================================================================
+
+bool SwPagePreviewLayout::Paint( const Rectangle _aOutRect ) const
+{
+ // check environment and parameters
+ {
+ if ( !mrParentViewShell.GetWin() &&
+ !mrParentViewShell.GetOut()->GetConnectMetaFile() )
+ return false;
+
+ OSL_ENSURE( mbPaintInfoValid,
+ "invalid preview settings - no paint of preview" );
+ if ( !mbPaintInfoValid )
+ return false;
+ }
+
+ // #i22014# no paint if <superfluous> flag is set at layout
+ if ( mrLayoutRootFrm.IsSuperfluous() )
+ {
+ return true;
+ }
+
+ // environment and parameter ok
+
+ // #i22014#
+ if ( mbInPaint )
+ {
+ return false;
+ }
+ mbInPaint = true;
+
+ OutputDevice* pOutputDev = mrParentViewShell.GetOut();
+
+ // prepare paint
+ if ( maPrevwPages.size() > 0 )
+ {
+ mrParentViewShell.Imp()->bFirstPageInvalid = sal_False;
+ mrParentViewShell.Imp()->pFirstVisPage =
+ const_cast<SwPageFrm*>(maPrevwPages[0]->pPage);
+ }
+
+ // paint preview background
+ {
+ SwRegionRects aPreviewBackgrdRegion( _aOutRect );
+ // calculate preview background rectangles
+ for ( std::vector<PrevwPage*>::const_iterator aPageIter = maPrevwPages.begin();
+ aPageIter != maPrevwPages.end();
+ ++aPageIter )
+ {
+ if ( (*aPageIter)->bVisible )
+ {
+ aPreviewBackgrdRegion -=
+ SwRect( (*aPageIter)->aPrevwWinPos, (*aPageIter)->aPageSize );
+ }
+ }
+ // paint preview background rectangles
+ mrParentViewShell._PaintDesktop( aPreviewBackgrdRegion );
+ }
+
+ // prepare data for paint of pages
+ const Rectangle aPxOutRect( pOutputDev->LogicToPixel( _aOutRect ) );
+
+ MapMode aMapMode( pOutputDev->GetMapMode() );
+ MapMode aSavedMapMode = aMapMode;
+
+ const Font& rEmptyPgFont = SwPageFrm::GetEmptyPageFont();
+
+ for ( std::vector<PrevwPage*>::const_iterator aPageIter = maPrevwPages.begin();
+ aPageIter != maPrevwPages.end();
+ ++aPageIter )
+ {
+ if ( !(*aPageIter)->bVisible )
+ continue;
+
+ Rectangle aPageRect( (*aPageIter)->aLogicPos, (*aPageIter)->aPageSize );
+ aMapMode.SetOrigin( (*aPageIter)->aMapOffset );
+ pOutputDev->SetMapMode( aMapMode );
+ Rectangle aPxPaintRect = pOutputDev->LogicToPixel( aPageRect );
+ if ( aPxOutRect.IsOver( aPxPaintRect) )
+ {
+ if ( (*aPageIter)->pPage->IsEmptyPage() )
+ {
+ const Color aRetouche( mrParentViewShell.Imp()->GetRetoucheColor() );
+ if( pOutputDev->GetFillColor() != aRetouche )
+ pOutputDev->SetFillColor( aRetouche );
+ pOutputDev->SetLineColor(); // no line color
+ // use aligned page rectangle
+ {
+ SwRect aTmpPageRect( aPageRect );
+ ::SwAlignRect( aTmpPageRect, &mrParentViewShell);
+ aPageRect = aTmpPageRect.SVRect();
+ }
+ pOutputDev->DrawRect( aPageRect );
+
+ // paint empty page text
+ Font aOldFont( pOutputDev->GetFont() );
+ pOutputDev->SetFont( rEmptyPgFont );
+ pOutputDev->DrawText( aPageRect, SW_RESSTR( STR_EMPTYPAGE ),
+ TEXT_DRAW_VCENTER |
+ TEXT_DRAW_CENTER |
+ TEXT_DRAW_CLIP );
+ pOutputDev->SetFont( aOldFont );
+ // paint shadow and border for empty page
+ // use new method to paint page border and shadow
+ SwPageFrm::PaintBorderAndShadow( aPageRect, &mrParentViewShell, true, false, true );
+ }
+ else
+ {
+ mrParentViewShell.aVisArea = aPageRect;
+ aPxPaintRect.Intersection( aPxOutRect );
+ Rectangle aPaintRect = pOutputDev->PixelToLogic( aPxPaintRect );
+ mrParentViewShell.Paint( aPaintRect );
+ // #i80691# paint page border and shadow
+ {
+ SwRect aPageBorderRect;
+ SwPageFrm::GetBorderAndShadowBoundRect( SwRect( aPageRect ), &mrParentViewShell, aPageBorderRect,
+ (*aPageIter)->pPage->IsLeftShadowNeeded(), (*aPageIter)->pPage->IsRightShadowNeeded(), true );
+ const Region aDLRegion(aPageBorderRect.SVRect());
+ mrParentViewShell.DLPrePaint2(aDLRegion);
+ SwPageFrm::PaintBorderAndShadow( aPageRect, &mrParentViewShell, true, false, true );
+ mrParentViewShell.DLPostPaint2(true);
+ }
+ }
+ // #i22014# stop painting, because new print preview layout is created during paint.
+ if ( mbNewLayoutDuringPaint )
+ {
+ break;
+ }
+
+ if ( (*aPageIter)->pPage->GetPhyPageNum() == mnSelectedPageNum )
+ {
+ _PaintSelectMarkAtPage( (*aPageIter) );
+ }
+
+ }
+ }
+
+ // #i22014# no update of accessible preview, if a new print preview layout is created during paint.
+ if ( !mbNewLayoutDuringPaint )
+ {
+ // update at accessiblilty interface
+ mrParentViewShell.Imp()->UpdateAccessiblePreview(
+ maPrevwPages,
+ aMapMode.GetScaleX(),
+ mrLayoutRootFrm.GetPageByPageNum( mnSelectedPageNum ),
+ maWinSize );
+ }
+
+ pOutputDev->SetMapMode( aSavedMapMode );
+ mrParentViewShell.aVisArea.Clear();
+
+ mbInPaint = false;
+ mbNewLayoutDuringPaint = false;
+
+ return true;
+}
+
+void SwPagePreviewLayout::Repaint( const Rectangle _aInvalidCoreRect ) const
+{
+ // check environment and parameters
+ {
+ if ( !mrParentViewShell.GetWin() &&
+ !mrParentViewShell.GetOut()->GetConnectMetaFile() )
+ return;
+
+ OSL_ENSURE( mbPaintInfoValid,
+ "invalid preview settings - no paint of preview" );
+ if ( !mbPaintInfoValid )
+ return;
+ }
+
+ // environment and parameter ok
+
+ // prepare paint
+ if ( maPrevwPages.size() > 0 )
+ {
+ mrParentViewShell.Imp()->bFirstPageInvalid = sal_False;
+ mrParentViewShell.Imp()->pFirstVisPage =
+ const_cast<SwPageFrm*>(maPrevwPages[0]->pPage);
+ }
+
+ // invalidate visible pages, which overlap the invalid core rectangle
+ for ( std::vector<PrevwPage*>::const_iterator aPageIter = maPrevwPages.begin();
+ aPageIter != maPrevwPages.end();
+ ++aPageIter )
+ {
+ if ( !(*aPageIter)->bVisible )
+ continue;
+
+ Rectangle aPageRect( (*aPageIter)->aLogicPos, (*aPageIter)->aPageSize );
+ if ( _aInvalidCoreRect.IsOver( aPageRect ) )
+ {
+ aPageRect.Intersection( _aInvalidCoreRect );
+ Rectangle aInvalidPrevwRect = aPageRect;
+ aInvalidPrevwRect.SetPos( aInvalidPrevwRect.TopLeft() -
+ (*aPageIter)->aLogicPos +
+ (*aPageIter)->aPrevwWinPos );
+ mrParentViewShell.GetWin()->Invalidate( aInvalidPrevwRect );
+ }
+ }
+}
+
+void SwPagePreviewLayout::_PaintSelectMarkAtPage(
+ const PrevwPage* _aSelectedPrevwPage ) const
+{
+ OutputDevice* pOutputDev = mrParentViewShell.GetOut();
+ MapMode aMapMode( pOutputDev->GetMapMode() );
+ // save mapping mode of output device
+ MapMode aSavedMapMode = aMapMode;
+ // save fill and line color of output device
+ Color aFill( pOutputDev->GetFillColor() );
+ Color aLine( pOutputDev->GetLineColor() );
+
+ // determine selection mark color
+ Color aSelPgLineColor(COL_LIGHTBLUE);
+ const StyleSettings& rSettings =
+ mrParentViewShell.GetWin()->GetSettings().GetStyleSettings();
+ if ( rSettings.GetHighContrastMode() )
+ aSelPgLineColor = rSettings.GetHighlightTextColor();
+
+ // set needed mapping mode at output device
+ aMapMode.SetOrigin( _aSelectedPrevwPage->aMapOffset );
+ pOutputDev->SetMapMode( aMapMode );
+
+ // calculate page rectangle in pixel coordinates
+ SwRect aPageRect( _aSelectedPrevwPage->aLogicPos,
+ _aSelectedPrevwPage->aPageSize );
+ // use aligned page rectangle, as it is used for
+ // page border and shadow paint - see <SwPageFrm::PaintBorderAndShadow(..)>
+ ::SwAlignRect( aPageRect, &mrParentViewShell);
+ Rectangle aPxPageRect = pOutputDev->LogicToPixel( aPageRect.SVRect() );
+
+ // draw two rectangle
+ // adjust position of select mark rectangle
+ Rectangle aRect( aPxPageRect.Left(), aPxPageRect.Top(),
+ aPxPageRect.Right(), aPxPageRect.Bottom() );
+ aRect = pOutputDev->PixelToLogic( aRect );
+ pOutputDev->SetFillColor(); // no fill color
+ pOutputDev->SetLineColor( aSelPgLineColor );
+ pOutputDev->DrawRect( aRect );
+ // adjust position of select mark rectangle
+ aRect = Rectangle( aPxPageRect.Left()+1, aPxPageRect.Top()+1,
+ aPxPageRect.Right()-1, aPxPageRect.Bottom()-1 );
+ aRect = pOutputDev->PixelToLogic( aRect );
+ pOutputDev->DrawRect( aRect );
+
+ // reset fill and line color of output device
+ pOutputDev->SetFillColor( aFill );
+ pOutputDev->SetLineColor( aLine );
+
+ // reset mapping mode of output device
+ pOutputDev->SetMapMode( aSavedMapMode );
+}
+
+// Perform paint for current selected page in order to unmark it.
+// Set new selected page and perform paint to mark this page.
+void SwPagePreviewLayout::MarkNewSelectedPage( const sal_uInt16 _nSelectedPage )
+{
+ sal_uInt16 nOldSelectedPageNum = mnSelectedPageNum;
+ mnSelectedPageNum = _nSelectedPage;
+
+ // re-paint for current selected page in order to umark it.
+ const PrevwPage* pOldSelectedPrevwPage = _GetPrevwPageByPageNum( nOldSelectedPageNum );
+ if ( pOldSelectedPrevwPage && pOldSelectedPrevwPage->bVisible )
+ {
+ // invalidate only areas of selection mark.
+ SwRect aPageRect( pOldSelectedPrevwPage->aPrevwWinPos,
+ pOldSelectedPrevwPage->aPageSize );
+ ::SwAlignRect( aPageRect, &mrParentViewShell);
+ OutputDevice* pOutputDev = mrParentViewShell.GetOut();
+ Rectangle aPxPageRect = pOutputDev->LogicToPixel( aPageRect.SVRect() );
+ // invalidate top mark line
+ Rectangle aInvalPxRect( aPxPageRect.Left(), aPxPageRect.Top(),
+ aPxPageRect.Right(), aPxPageRect.Top()+1 );
+ mrParentViewShell.GetWin()->Invalidate( pOutputDev->PixelToLogic( aInvalPxRect ) );
+ // invalidate right mark line
+ aInvalPxRect = Rectangle( aPxPageRect.Right()-1, aPxPageRect.Top(),
+ aPxPageRect.Right(), aPxPageRect.Bottom() );
+ mrParentViewShell.GetWin()->Invalidate( pOutputDev->PixelToLogic( aInvalPxRect ) );
+ // invalidate bottom mark line
+ aInvalPxRect = Rectangle( aPxPageRect.Left(), aPxPageRect.Bottom()-1,
+ aPxPageRect.Right(), aPxPageRect.Bottom() );
+ mrParentViewShell.GetWin()->Invalidate( pOutputDev->PixelToLogic( aInvalPxRect ) );
+ // invalidate left mark line
+ aInvalPxRect = Rectangle( aPxPageRect.Left(), aPxPageRect.Top(),
+ aPxPageRect.Left()+1, aPxPageRect.Bottom() );
+ mrParentViewShell.GetWin()->Invalidate( pOutputDev->PixelToLogic( aInvalPxRect ) );
+ }
+
+ // re-paint for new selected page in order to mark it.
+ const PrevwPage* pNewSelectedPrevwPage = _GetPrevwPageByPageNum( _nSelectedPage );
+ if ( pNewSelectedPrevwPage && pNewSelectedPrevwPage->bVisible )
+ _PaintSelectMarkAtPage( pNewSelectedPrevwPage );
+}
+
+
+// =============================================================================
+// helper methods
+// =============================================================================
+
+struct EqualsPageNumPred
+{
+ const sal_uInt16 mnPageNum;
+ EqualsPageNumPred( const sal_uInt16 _nPageNum ) : mnPageNum( _nPageNum ) {};
+ bool operator() ( const PrevwPage* _pPrevwPage )
+ {
+ return _pPrevwPage->pPage->GetPhyPageNum() == mnPageNum;
+ }
+};
+
+const PrevwPage* SwPagePreviewLayout::_GetPrevwPageByPageNum( const sal_uInt16 _nPageNum ) const
+{
+ std::vector<PrevwPage*>::const_iterator aFoundPrevwPageIter =
+ std::find_if( maPrevwPages.begin(), maPrevwPages.end(),
+ EqualsPageNumPred( _nPageNum ) );
+
+ if ( aFoundPrevwPageIter == maPrevwPages.end() )
+ return 0;
+ else
+ return (*aFoundPrevwPageIter);
+}
+
+sal_uInt16 SwPagePreviewLayout::GetRowOfPage( sal_uInt16 _nPageNum ) const
+{
+ // leaving left-top-corner blank is controlled by <mbBookPreview>.
+ if ( mbBookPreview )
+ {
+ // Note: increase given physical page number by one, because left-top-corner
+ // in the preview layout is left blank.
+ ++_nPageNum;
+ }
+
+ sal_uInt16 nRow = (_nPageNum) / mnCols;
+ if ( ( (_nPageNum) % mnCols ) > 0 )
+ ++nRow;
+
+ return nRow;
+}
+sal_uInt16 SwPagePreviewLayout::GetColOfPage( sal_uInt16 _nPageNum ) const
+{
+ // leaving left-top-corner blank is controlled by <mbBookPreview>.
+ if ( mbBookPreview )
+ {
+ // Note: increase given physical page number by one, because left-top-corner
+ // in the preview layout is left blank.
+ ++_nPageNum;
+ }
+
+ sal_uInt16 nCol = (_nPageNum) % mnCols;
+ if ( nCol == 0 )
+ nCol = mnCols;
+
+ return nCol;
+}
+
+Size SwPagePreviewLayout::GetPrevwDocSize() const
+{
+ OSL_ENSURE( PreviewLayoutValid(), "PagePreviewLayout not valid" );
+ return maPreviewDocRect.GetSize();
+}
+
+Size SwPagePreviewLayout::GetPrevwPageSizeByPageNum( sal_uInt16 _nPageNum ) const
+{
+ const PrevwPage* pPrevwPage = _GetPrevwPageByPageNum( _nPageNum );
+ if ( pPrevwPage )
+ {
+ return pPrevwPage->aPageSize;
+ }
+ else
+ {
+ return Size( 0, 0 );
+ }
+}
+
+sal_uInt16 SwPagePreviewLayout::GetVirtPageNumByPageNum( sal_uInt16 _nPageNum ) const
+{
+ const PrevwPage* pPrevwPage = _GetPrevwPageByPageNum( _nPageNum );
+ if ( pPrevwPage )
+ {
+ return pPrevwPage->pPage->GetVirtPageNum();
+ }
+ else
+ {
+ return 0;
+ }
+}
+
+sal_uInt16 SwPagePreviewLayout::ConvertAbsoluteToRelativePageNum( sal_uInt16 _nAbsPageNum ) const
+{
+ if ( mbBookPreview || mbPrintEmptyPages || !_nAbsPageNum )
+ {
+ return _nAbsPageNum;
+ }
+
+ const SwPageFrm* pTmpPage = static_cast<const SwPageFrm*>(mrLayoutRootFrm.Lower());
+
+ sal_uInt16 nRet = 1;
+
+ while ( pTmpPage && pTmpPage->GetPhyPageNum() != _nAbsPageNum )
+ {
+ if ( !pTmpPage->IsEmptyPage() )
+ ++nRet;
+
+ pTmpPage = static_cast<const SwPageFrm*>( pTmpPage->GetNext() );
+ }
+
+ return nRet;
+}
+
+sal_uInt16 SwPagePreviewLayout::ConvertRelativeToAbsolutePageNum( sal_uInt16 _nRelPageNum ) const
+{
+ if ( mbBookPreview || mbPrintEmptyPages || !_nRelPageNum )
+ {
+ return _nRelPageNum;
+ }
+
+ const SwPageFrm* pTmpPage = static_cast<const SwPageFrm*>(mrLayoutRootFrm.Lower());
+ const SwPageFrm* pRet = 0;
+
+ sal_uInt16 i = 0;
+ while( pTmpPage && i != _nRelPageNum )
+ {
+ if ( !pTmpPage->IsEmptyPage() )
+ ++i;
+
+ pRet = pTmpPage;
+ pTmpPage = static_cast<const SwPageFrm*>( pTmpPage->GetNext() );
+ }
+
+ return pRet->GetPhyPageNum();
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/view/printdata.cxx b/sw/source/core/view/printdata.cxx
new file mode 100644
index 000000000000..aabb24a294b3
--- /dev/null
+++ b/sw/source/core/view/printdata.cxx
@@ -0,0 +1,541 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/**************************************************************************
+ *
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+#include <printdata.hxx>
+
+#include <globals.hrc>
+#include <doc.hxx>
+#include <unotxdoc.hxx>
+#include <wdocsh.hxx>
+#include <viewsh.hxx>
+#include <docfld.hxx>
+
+#include <svl/languageoptions.hxx>
+#include <toolkit/awt/vclxdevice.hxx>
+#include <tools/string.hxx>
+#include <tools/debug.hxx>
+#include <tools/resary.hxx>
+#include <unotools/moduleoptions.hxx>
+#include <vcl/outdev.hxx>
+
+
+extern bool lcl_GetPostIts( IDocumentFieldsAccess* pIDFA, _SetGetExpFlds * pSrtLst );
+
+
+using namespace ::com::sun::star;
+using ::rtl::OUString;
+
+
+//////////////////////////////////////////////////////////////////////
+
+SwRenderData::SwRenderData()
+{
+ m_pPostItFields = 0;
+ m_pPostItDoc = 0;
+ m_pPostItShell = 0;
+
+ m_pViewOptionAdjust = 0;
+ m_pPrtOptions = 0;
+}
+
+
+SwRenderData::~SwRenderData()
+{
+ delete m_pViewOptionAdjust; m_pViewOptionAdjust = 0;
+ delete m_pPrtOptions; m_pPrtOptions = 0;
+ DBG_ASSERT( !m_pPostItShell, "m_pPostItShell should already have been deleted" );
+ DBG_ASSERT( !m_pPostItDoc, "m_pPostItDoc should already have been deleted" );
+ DBG_ASSERT( !m_pPostItFields, " should already have been deleted" );
+}
+
+
+void SwRenderData::CreatePostItData( SwDoc *pDoc, const SwViewOption *pViewOpt, OutputDevice *pOutDev )
+{
+ DBG_ASSERT( !m_pPostItFields && !m_pPostItDoc && !m_pPostItShell, "some post-it data already exists" );
+ m_pPostItFields = new _SetGetExpFlds;
+ lcl_GetPostIts( pDoc, m_pPostItFields );
+ m_pPostItDoc = new SwDoc;
+
+ //!! Disable spell and grammar checking in the temporary document.
+ //!! Otherwise the grammar checker might process it and crash if we later on
+ //!! simply delete this document while he is still at it.
+ SwViewOption aViewOpt( *pViewOpt );
+ aViewOpt.SetOnlineSpell( sal_False );
+
+ m_pPostItShell = new ViewShell( *m_pPostItDoc, 0, &aViewOpt, pOutDev );
+}
+
+
+void SwRenderData::DeletePostItData()
+{
+ if (HasPostItData())
+ {
+ m_pPostItDoc->setPrinter( 0, false, false ); // So that the printer remains at the real DOC
+ delete m_pPostItShell;
+ delete m_pPostItFields;
+ m_pPostItDoc = 0;
+ m_pPostItShell = 0;
+ m_pPostItFields = 0;
+ }
+}
+
+bool SwRenderData::NeedNewViewOptionAdjust( const ViewShell& rCompare ) const
+{
+ return m_pViewOptionAdjust ? ! m_pViewOptionAdjust->checkShell( rCompare ) : true;
+}
+
+
+void SwRenderData::ViewOptionAdjustStart( ViewShell &rSh, const SwViewOption &rViewOptions )
+{
+ if (m_pViewOptionAdjust)
+ {
+ DBG_ASSERT( 0, "error: there should be no ViewOptionAdjust active when calling this function" );
+ }
+ m_pViewOptionAdjust = new SwViewOptionAdjust_Impl( rSh, rViewOptions );
+}
+
+
+void SwRenderData::ViewOptionAdjust(SwPrintData const*const pPrtOptions)
+{
+ m_pViewOptionAdjust->AdjustViewOptions( pPrtOptions );
+}
+
+
+void SwRenderData::ViewOptionAdjustStop()
+{
+ if (m_pViewOptionAdjust)
+ {
+ delete m_pViewOptionAdjust;
+ m_pViewOptionAdjust = 0;
+ }
+}
+
+
+void SwRenderData::MakeSwPrtOptions(
+ SwPrintData & rOptions,
+ const SwDocShell *pDocShell,
+ const SwPrintUIOptions *pOpt,
+ const SwRenderData *pData,
+ bool bIsPDFExport )
+{
+ if (!pDocShell || !pOpt || !pData)
+ return;
+
+ // get default print options
+ const TypeId aSwWebDocShellTypeId = TYPE(SwWebDocShell);
+ sal_Bool bWeb = pDocShell->IsA( aSwWebDocShellTypeId );
+ ::sw::InitPrintOptionsFromApplication(rOptions, bWeb);
+
+ // get print options to use from provided properties
+ rOptions.bPrintGraphic = pOpt->IsPrintGraphics();
+ rOptions.bPrintTable = pOpt->IsPrintTables();
+ rOptions.bPrintDraw = pOpt->IsPrintDrawings();
+ rOptions.bPrintControl = pOpt->IsPrintFormControls();
+ rOptions.bPrintLeftPages = pOpt->IsPrintLeftPages();
+ rOptions.bPrintRightPages = pOpt->IsPrintRightPages();
+ rOptions.bPrintPageBackground = pOpt->IsPrintPageBackground();
+ rOptions.bPrintEmptyPages = pOpt->IsPrintEmptyPages( bIsPDFExport );
+ // bUpdateFieldsInPrinting <-- not set here; mail merge only
+ rOptions.bPaperFromSetup = pOpt->IsPaperFromSetup();
+ rOptions.bPrintReverse = pOpt->IsPrintReverse();
+ rOptions.bPrintProspect = pOpt->IsPrintProspect();
+ rOptions.bPrintProspectRTL = pOpt->IsPrintProspectRTL();
+ // bPrintSingleJobs <-- not set here; mail merge and or configuration
+ // bModified <-- not set here; mail merge only
+ rOptions.bPrintBlackFont = pOpt->IsPrintWithBlackTextColor();
+ rOptions.bPrintHiddenText = pOpt->IsPrintHiddenText();
+ rOptions.bPrintTextPlaceholder = pOpt->IsPrintTextPlaceholders();
+ rOptions.nPrintPostIts = pOpt->GetPrintPostItsType();
+
+ //! needs to be set after MakeOptions since the assignment operation in that
+ //! function will destroy the pointers
+ rOptions.SetPrintUIOptions( pOpt );
+ rOptions.SetRenderData( pData );
+}
+
+
+//////////////////////////////////////////////////////////////////////
+
+SwPrintUIOptions::SwPrintUIOptions(
+ bool bWeb,
+ bool bSwSrcView,
+ bool bHasSelection,
+ bool bHasPostIts,
+ const SwPrintData &rDefaultPrintData ) :
+ m_pLast( NULL ),
+ m_rDefaultPrintData( rDefaultPrintData )
+{
+ ResStringArray aLocalizedStrings( SW_RES( STR_PRINTOPTUI ) );
+
+ DBG_ASSERT( aLocalizedStrings.Count() >= 30, "resource incomplete" );
+ if( aLocalizedStrings.Count() < 30 ) // bad resource ?
+ return;
+
+ // printing HTML sources does not have any valid UI options.
+ // Its just the source code that gets printed ...
+ if (bSwSrcView)
+ {
+ m_aUIProperties.realloc( 0 );
+ return;
+ }
+
+ // check if CTL is enabled
+ SvtLanguageOptions aLangOpt;
+ bool bCTL = aLangOpt.IsCTLFontEnabled();
+
+ // create sequence of print UI options
+ // (5 options are not available for Writer-Web)
+ const int nCTLOpts = bCTL ? 1 : 0;
+ const int nNumProps = nCTLOpts + (bWeb ? 14 : 20);
+ m_aUIProperties.realloc( nNumProps );
+ int nIdx = 0;
+
+ // create "writer" section (new tab page in dialog)
+ SvtModuleOptions aModOpt;
+ String aAppGroupname( aLocalizedStrings.GetString( 0 ) );
+ aAppGroupname.SearchAndReplace( String( RTL_CONSTASCII_USTRINGPARAM( "%s" ) ),
+ aModOpt.GetModuleName( SvtModuleOptions::E_SWRITER ) );
+ m_aUIProperties[ nIdx++ ].Value = getGroupControlOpt( aAppGroupname, rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ".HelpID:vcl:PrintDialog:TabPage:AppPage" ) ) );
+
+ // create sub section for Contents
+ m_aUIProperties[ nIdx++ ].Value = getSubgroupControlOpt( aLocalizedStrings.GetString( 1 ), rtl::OUString() );
+
+ // create a bool option for background
+ bool bDefaultVal = rDefaultPrintData.IsPrintPageBackground();
+ m_aUIProperties[ nIdx++ ].Value = getBoolControlOpt( aLocalizedStrings.GetString( 2 ),
+ rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ".HelpID:vcl:PrintDialog:PrintPageBackground:CheckBox" ) ),
+ rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "PrintPageBackground" ) ),
+ bDefaultVal );
+
+ // create a bool option for pictures/graphics AND OLE and drawing objects as well
+ bDefaultVal = rDefaultPrintData.IsPrintGraphic() || rDefaultPrintData.IsPrintDraw();
+ m_aUIProperties[ nIdx++ ].Value = getBoolControlOpt( aLocalizedStrings.GetString( 3 ),
+ rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ".HelpID:vcl:PrintDialog:PrintPicturesAndObjects:CheckBox" ) ),
+ rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "PrintPicturesAndObjects" ) ),
+ bDefaultVal );
+ if (!bWeb)
+ {
+ // create a bool option for hidden text
+ bDefaultVal = rDefaultPrintData.IsPrintHiddenText();
+ m_aUIProperties[ nIdx++ ].Value = getBoolControlOpt( aLocalizedStrings.GetString( 4 ),
+ rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ".HelpID:vcl:PrintDialog:PrintHiddenText:CheckBox" ) ),
+ rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "PrintHiddenText" ) ),
+ bDefaultVal );
+
+ // create a bool option for place holder
+ bDefaultVal = rDefaultPrintData.IsPrintTextPlaceholder();
+ m_aUIProperties[ nIdx++ ].Value = getBoolControlOpt( aLocalizedStrings.GetString( 5 ),
+ rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ".HelpID:vcl:PrintDialog:PrintTextPlaceholder:CheckBox" ) ),
+ rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "PrintTextPlaceholder" ) ),
+ bDefaultVal );
+ }
+
+ // create a bool option for controls
+ bDefaultVal = rDefaultPrintData.IsPrintControl();
+ m_aUIProperties[ nIdx++ ].Value = getBoolControlOpt( aLocalizedStrings.GetString( 6 ),
+ rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ".HelpID:vcl:PrintDialog:PrintControls:CheckBox" ) ),
+ rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "PrintControls" ) ),
+ bDefaultVal );
+
+ // create sub section for Color
+ m_aUIProperties[ nIdx++ ].Value = getSubgroupControlOpt( aLocalizedStrings.GetString( 7 ), rtl::OUString() );
+
+ // create a bool option for printing text with black font color
+ bDefaultVal = rDefaultPrintData.IsPrintBlackFont();
+ m_aUIProperties[ nIdx++ ].Value = getBoolControlOpt( aLocalizedStrings.GetString( 8 ),
+ rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ".HelpID:vcl:PrintDialog:PrintBlackFonts:CheckBox" ) ),
+ rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "PrintBlackFonts" ) ),
+ bDefaultVal );
+
+ if (!bWeb)
+ {
+ // create subgroup for misc options
+ m_aUIProperties[ nIdx++ ].Value = getSubgroupControlOpt( rtl::OUString( aLocalizedStrings.GetString( 9 ) ), rtl::OUString() );
+
+ // create a bool option for printing automatically inserted blank pages
+ bDefaultVal = rDefaultPrintData.IsPrintEmptyPages();
+ m_aUIProperties[ nIdx++ ].Value = getBoolControlOpt( aLocalizedStrings.GetString( 10 ),
+ rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ".HelpID:vcl:PrintDialog:PrintEmptyPages:CheckBox" ) ),
+ rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "PrintEmptyPages" ) ),
+ bDefaultVal );
+ }
+
+ // create a bool option for paper tray
+ bDefaultVal = rDefaultPrintData.IsPaperFromSetup();
+ vcl::PrinterOptionsHelper::UIControlOptions aPaperTrayOpt;
+ aPaperTrayOpt.maGroupHint = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "OptionsPageOptGroup" ) );
+ m_aUIProperties[ nIdx++ ].Value = getBoolControlOpt( aLocalizedStrings.GetString( 11 ),
+ rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ".HelpID:vcl:PrintDialog:PrintPaperFromSetup:CheckBox" ) ),
+ rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "PrintPaperFromSetup" ) ),
+ bDefaultVal,
+ aPaperTrayOpt
+ );
+
+ // print range selection
+ vcl::PrinterOptionsHelper::UIControlOptions aPrintRangeOpt;
+ aPrintRangeOpt.maGroupHint = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "PrintRange" ) );
+ aPrintRangeOpt.mbInternalOnly = sal_True;
+ m_aUIProperties[nIdx++].Value = getSubgroupControlOpt( rtl::OUString( aLocalizedStrings.GetString( 26 ) ),
+ rtl::OUString(),
+ aPrintRangeOpt
+ );
+
+ // create a choice for the content to create
+ rtl::OUString aPrintRangeName( RTL_CONSTASCII_USTRINGPARAM( "PrintContent" ) );
+ uno::Sequence< rtl::OUString > aChoices( 3 );
+ uno::Sequence< sal_Bool > aChoicesDisabled( 3 );
+ uno::Sequence< rtl::OUString > aHelpIds( 3 );
+ aChoices[0] = aLocalizedStrings.GetString( 27 );
+ aChoicesDisabled[0] = sal_False;
+ aHelpIds[0] = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ".HelpID:vcl:PrintDialog:PrintContent:RadioButton:0" ) );
+ aChoices[1] = aLocalizedStrings.GetString( 28 );
+ aChoicesDisabled[1] = sal_False;
+ aHelpIds[1] = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ".HelpID:vcl:PrintDialog:PrintContent:RadioButton:1" ) );
+ aChoices[2] = aLocalizedStrings.GetString( 29 );
+ aChoicesDisabled[2] = sal_Bool(! bHasSelection);
+ aHelpIds[2] = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ".HelpID:vcl:PrintDialog:PrintContent:RadioButton:2" ) );
+ m_aUIProperties[nIdx++].Value = getChoiceControlOpt( rtl::OUString(),
+ aHelpIds,
+ aPrintRangeName,
+ aChoices,
+ bHasSelection ? 2 /*enable 'Selection' radio button*/ : 0 /* enable 'All pages' */,
+ rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Radio" ) ),
+ aChoicesDisabled
+ );
+ // create a an Edit dependent on "Pages" selected
+ vcl::PrinterOptionsHelper::UIControlOptions aPageRangeOpt( aPrintRangeName, 1, sal_True );
+ m_aUIProperties[nIdx++].Value = getEditControlOpt( rtl::OUString(),
+ rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ".HelpID:vcl:PrintDialog:PageRange:Edit" ) ),
+ rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "PageRange" ) ),
+ rtl::OUString(),
+ aPageRangeOpt
+ );
+ // print content selection
+ vcl::PrinterOptionsHelper::UIControlOptions aContentsOpt;
+ aContentsOpt.maGroupHint = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "JobPage" ) );
+ m_aUIProperties[nIdx++].Value = getSubgroupControlOpt( rtl::OUString( aLocalizedStrings.GetString( 12 ) ),
+ rtl::OUString(),
+ aContentsOpt
+ );
+ // create a list box for notes content
+ const sal_Int16 nPrintPostIts = rDefaultPrintData.GetPrintPostIts();
+ aChoices.realloc( 4 );
+ aChoices[0] = aLocalizedStrings.GetString( 13 );
+ aChoices[1] = aLocalizedStrings.GetString( 14 );
+ aChoices[2] = aLocalizedStrings.GetString( 15 );
+ aChoices[3] = aLocalizedStrings.GetString( 16 );
+ aHelpIds.realloc( 2 );
+ aHelpIds[0] = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ".HelpID:vcl:PrintDialog:PrintAnnotationMode:FixedText" ) );
+ aHelpIds[1] = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ".HelpID:vcl:PrintDialog:PrintAnnotationMode:ListBox" ) );
+ vcl::PrinterOptionsHelper::UIControlOptions aAnnotOpt( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "PrintProspect" ) ), 0, sal_False );
+ aAnnotOpt.mbEnabled = bHasPostIts;
+ m_aUIProperties[ nIdx++ ].Value = getChoiceControlOpt( aLocalizedStrings.GetString( 17 ),
+ aHelpIds,
+ rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "PrintAnnotationMode" ) ),
+ aChoices,
+ nPrintPostIts,
+ rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "List" ) ),
+ uno::Sequence< sal_Bool >(),
+ aAnnotOpt
+ );
+
+ // create subsection for Page settings
+ vcl::PrinterOptionsHelper::UIControlOptions aPageSetOpt;
+ aPageSetOpt.maGroupHint = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "LayoutPage" ) );
+
+ if (!bWeb)
+ {
+ m_aUIProperties[nIdx++].Value = getSubgroupControlOpt( rtl::OUString( aLocalizedStrings.GetString( 18 ) ),
+ rtl::OUString(),
+ aPageSetOpt
+ );
+ uno::Sequence< rtl::OUString > aRLChoices( 3 );
+ aRLChoices[0] = aLocalizedStrings.GetString( 19 );
+ aRLChoices[1] = aLocalizedStrings.GetString( 20 );
+ aRLChoices[2] = aLocalizedStrings.GetString( 21 );
+ uno::Sequence< rtl::OUString > aRLHelp( 1 );
+ aRLHelp[0] = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ".HelpID:vcl:PrintDialog:PrintLeftRightPages:ListBox" ) );
+ // create a choice option for all/left/right pages
+ // 0 : all pages (left & right)
+ // 1 : left pages
+ // 2 : right pages
+ DBG_ASSERT( rDefaultPrintData.IsPrintLeftPage() || rDefaultPrintData.IsPrintRightPage(),
+ "unexpected value combination" );
+ sal_Int16 nPagesChoice = 0;
+ if (rDefaultPrintData.IsPrintLeftPage() && !rDefaultPrintData.IsPrintRightPage())
+ nPagesChoice = 1;
+ else if (!rDefaultPrintData.IsPrintLeftPage() && rDefaultPrintData.IsPrintRightPage())
+ nPagesChoice = 2;
+ m_aUIProperties[ nIdx++ ].Value = getChoiceControlOpt( aLocalizedStrings.GetString( 22 ),
+ aRLHelp,
+ rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "PrintLeftRightPages" ) ),
+ aRLChoices,
+ nPagesChoice,
+ rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "List" ) )
+ );
+ }
+
+ // create a bool option for brochure
+ bDefaultVal = rDefaultPrintData.IsPrintProspect();
+ rtl::OUString aBrochurePropertyName( RTL_CONSTASCII_USTRINGPARAM( "PrintProspect" ) );
+ m_aUIProperties[ nIdx++ ].Value = getBoolControlOpt( aLocalizedStrings.GetString( 23 ),
+ rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ".HelpID:vcl:PrintDialog:PrintProspect:CheckBox" ) ),
+ aBrochurePropertyName,
+ bDefaultVal,
+ aPageSetOpt
+ );
+
+ if (bCTL)
+ {
+ // create a bool option for brochure RTL dependent on brochure
+ uno::Sequence< rtl::OUString > aBRTLChoices( 2 );
+ aBRTLChoices[0] = aLocalizedStrings.GetString( 24 );
+ aBRTLChoices[1] = aLocalizedStrings.GetString( 25 );
+ vcl::PrinterOptionsHelper::UIControlOptions aBrochureRTLOpt( aBrochurePropertyName, -1, sal_True );
+ uno::Sequence< rtl::OUString > aBRTLHelpIds( 1 );
+ aBRTLHelpIds[0] = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ".HelpID:vcl:PrintDialog:PrintProspectRTL:ListBox" ) );
+ aBrochureRTLOpt.maGroupHint = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "LayoutPage" ) );
+ // RTL brochure choices
+ // 0 : left-to-right
+ // 1 : right-to-left
+ const sal_Int16 nBRTLChoice = rDefaultPrintData.IsPrintProspectRTL() ? 1 : 0;
+ m_aUIProperties[ nIdx++ ].Value = getChoiceControlOpt( rtl::OUString(),
+ aBRTLHelpIds,
+ rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "PrintProspectRTL" ) ),
+ aBRTLChoices,
+ nBRTLChoice,
+ rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "List" ) ),
+ uno::Sequence< sal_Bool >(),
+ aBrochureRTLOpt
+ );
+ }
+
+
+ DBG_ASSERT( nIdx == nNumProps, "number of added properties is not as expected" );
+}
+
+
+SwPrintUIOptions::~SwPrintUIOptions()
+{
+}
+
+bool SwPrintUIOptions::IsPrintLeftPages() const
+{
+ // take care of different property names for the option.
+ // for compatibility the old name should win (may still be used for PDF export or via Uno API)
+
+ // 0: left and right pages
+ // 1: left pages only
+ // 2: right pages only
+ sal_Int64 nLRPages = getIntValue( "PrintLeftRightPages", 0 /* default: all */ );
+ bool bRes = nLRPages == 0 || nLRPages == 1;
+ bRes = getBoolValue( "PrintLeftPages", bRes /* <- default value if property is not found */ );
+ return bRes;
+}
+
+bool SwPrintUIOptions::IsPrintRightPages() const
+{
+ // take care of different property names for the option.
+ // for compatibility the old name should win (may still be used for PDF export or via Uno API)
+
+ sal_Int64 nLRPages = getIntValue( "PrintLeftRightPages", 0 /* default: all */ );
+ bool bRes = nLRPages == 0 || nLRPages == 2;
+ bRes = getBoolValue( "PrintRightPages", bRes /* <- default value if property is not found */ );
+ return bRes;
+}
+
+bool SwPrintUIOptions::IsPrintEmptyPages( bool bIsPDFExport ) const
+{
+ // take care of different property names for the option.
+
+ bool bRes = bIsPDFExport ?
+ !getBoolValue( "IsSkipEmptyPages", sal_True ) :
+ getBoolValue( "PrintEmptyPages", sal_True );
+ return bRes;
+}
+
+bool SwPrintUIOptions::IsPrintTables() const
+{
+ // take care of different property names currently in use for this option.
+ // for compatibility the old name should win (may still be used for PDF export or via Uno API)
+
+// bool bRes = getBoolValue( "PrintTablesGraphicsAndDiagrams", sal_True );
+// bRes = getBoolValue( "PrintTables", bRes );
+// return bRes;
+ // for now it was decided that tables should always be printed
+ return true;
+}
+
+bool SwPrintUIOptions::IsPrintGraphics() const
+{
+ // take care of different property names for the option.
+ // for compatibility the old name should win (may still be used for PDF export or via Uno API)
+
+ bool bRes = getBoolValue( "PrintPicturesAndObjects", sal_True );
+ bRes = getBoolValue( "PrintGraphics", bRes );
+ return bRes;
+}
+
+bool SwPrintUIOptions::IsPrintDrawings() const
+{
+ // take care of different property names for the option.
+ // for compatibility the old name should win (may still be used for PDF export or via Uno API)
+
+ bool bRes = getBoolValue( "PrintPicturesAndObjects", sal_True );
+ bRes = getBoolValue( "PrintDrawings", bRes );
+ return bRes;
+}
+
+bool SwPrintUIOptions::processPropertiesAndCheckFormat( const uno::Sequence< beans::PropertyValue >& i_rNewProp )
+{
+ bool bChanged = processProperties( i_rNewProp );
+
+ uno::Reference< awt::XDevice > xRenderDevice;
+ uno::Any aVal( getValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "RenderDevice" ) ) ) );
+ aVal >>= xRenderDevice;
+
+ OutputDevice* pOut = 0;
+ if (xRenderDevice.is())
+ {
+ VCLXDevice* pDevice = VCLXDevice::GetImplementation( xRenderDevice );
+ pOut = pDevice ? pDevice->GetOutputDevice() : 0;
+ }
+ bChanged = bChanged || (pOut != m_pLast);
+ if( pOut )
+ m_pLast = pOut;
+
+ return bChanged;
+}
+
+//////////////////////////////////////////////////////////////////////
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/view/vdraw.cxx b/sw/source/core/view/vdraw.cxx
new file mode 100644
index 000000000000..17710c82ee78
--- /dev/null
+++ b/sw/source/core/view/vdraw.cxx
@@ -0,0 +1,276 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+
+#include <svx/svdmodel.hxx>
+#include <svx/svdpage.hxx>
+#include <tools/shl.hxx>
+#include <swmodule.hxx>
+#include <svtools/accessibilityoptions.hxx>
+#include <svx/svdpagv.hxx>
+#include <fmtanchr.hxx>
+#include <frmfmt.hxx>
+
+#include <svx/svdoutl.hxx>
+
+#if OSL_DEBUG_LEVEL > 1
+#include <svx/fmglob.hxx>
+#endif
+
+#include "fesh.hxx"
+#include "pagefrm.hxx"
+#include "rootfrm.hxx"
+#include "viewimp.hxx"
+#include "dflyobj.hxx"
+#include "viewopt.hxx"
+#include "printdata.hxx"
+#include "dcontact.hxx"
+#include "dview.hxx"
+#include "flyfrm.hxx"
+#include <vcl/svapp.hxx>
+
+#include <IDocumentDrawModelAccess.hxx>
+
+
+void SwViewImp::StartAction()
+{
+ if ( HasDrawView() )
+ {
+ SET_CURR_SHELL( GetShell() );
+ if ( pSh->ISA(SwFEShell) )
+ ((SwFEShell*)pSh)->HideChainMarker();
+ }
+}
+
+void SwViewImp::EndAction()
+{
+ if ( HasDrawView() )
+ {
+ SET_CURR_SHELL( GetShell() );
+ if ( pSh->ISA(SwFEShell) )
+ ((SwFEShell*)pSh)->SetChainMarker(); // May have changed
+ }
+}
+
+void SwViewImp::LockPaint()
+{
+ if ( HasDrawView() )
+ {
+ bResetHdlHiddenPaint = !GetDrawView()->areMarkHandlesHidden();
+ GetDrawView()->hideMarkHandles();
+ }
+ else
+ {
+ bResetHdlHiddenPaint = sal_False;
+ }
+}
+
+void SwViewImp::UnlockPaint()
+{
+ if ( bResetHdlHiddenPaint )
+ GetDrawView()->showMarkHandles();
+}
+
+void SwViewImp::PaintLayer( const SdrLayerID _nLayerID,
+ SwPrintData const*const pPrintData,
+ const SwRect& ,
+ const Color* _pPageBackgrdColor,
+ const bool _bIsPageRightToLeft ) const
+{
+ if ( HasDrawView() )
+ {
+ //change the draw mode in high contrast mode
+ OutputDevice* pOutDev = GetShell()->GetOut();
+ sal_uLong nOldDrawMode = pOutDev->GetDrawMode();
+ if( GetShell()->GetWin() &&
+ Application::GetSettings().GetStyleSettings().GetHighContrastMode() &&
+ (!GetShell()->IsPreView()||SW_MOD()->GetAccessibilityOptions().GetIsForPagePreviews()))
+ {
+ pOutDev->SetDrawMode( nOldDrawMode | DRAWMODE_SETTINGSLINE | DRAWMODE_SETTINGSFILL |
+ DRAWMODE_SETTINGSTEXT | DRAWMODE_SETTINGSGRADIENT );
+ }
+ // For correct handling of accessibility, high contrast, the page background
+ // color is set as the background color at the outliner of the draw view.
+ // Only necessary for the layers hell and heaven
+ Color aOldOutlinerBackgrdColor;
+ // set default horizontal text direction on painting <hell> or <heaven>.
+ EEHorizontalTextDirection aOldEEHoriTextDir = EE_HTEXTDIR_L2R;
+ const IDocumentDrawModelAccess* pIDDMA = GetShell()->getIDocumentDrawModelAccess();
+ if ( (_nLayerID == pIDDMA->GetHellId()) ||
+ (_nLayerID == pIDDMA->GetHeavenId()) )
+ {
+ OSL_ENSURE( _pPageBackgrdColor,
+ "incorrect usage of SwViewImp::PaintLayer: pPageBackgrdColor have to be set for painting layer <hell> or <heaven>");
+ if ( _pPageBackgrdColor )
+ {
+ aOldOutlinerBackgrdColor =
+ GetDrawView()->GetModel()->GetDrawOutliner().GetBackgroundColor();
+ GetDrawView()->GetModel()->GetDrawOutliner().SetBackgroundColor( *_pPageBackgrdColor );
+ }
+
+ aOldEEHoriTextDir =
+ GetDrawView()->GetModel()->GetDrawOutliner().GetDefaultHorizontalTextDirection();
+ EEHorizontalTextDirection aEEHoriTextDirOfPage =
+ _bIsPageRightToLeft ? EE_HTEXTDIR_R2L : EE_HTEXTDIR_L2R;
+ GetDrawView()->GetModel()->GetDrawOutliner().SetDefaultHorizontalTextDirection( aEEHoriTextDirOfPage );
+ }
+
+ pOutDev->Push( PUSH_LINECOLOR ); // #114231#
+ if (pPrintData)
+ {
+ // hide drawings but not form controls (form controls are handled elsewhere)
+ SdrView &rSdrView = const_cast< SdrView & >(GetPageView()->GetView());
+ rSdrView.setHideDraw( !pPrintData->IsPrintDraw() );
+ }
+ GetPageView()->DrawLayer(_nLayerID, pOutDev);
+ pOutDev->Pop();
+
+ // reset background color of the outliner
+ // reset default horizontal text direction
+ if ( (_nLayerID == pIDDMA->GetHellId()) ||
+ (_nLayerID == pIDDMA->GetHeavenId()) )
+ {
+ GetDrawView()->GetModel()->GetDrawOutliner().SetBackgroundColor( aOldOutlinerBackgrdColor );
+ GetDrawView()->GetModel()->GetDrawOutliner().SetDefaultHorizontalTextDirection( aOldEEHoriTextDir );
+ }
+
+ pOutDev->SetDrawMode( nOldDrawMode );
+ }
+}
+
+#define WIEDUWILLST 400
+
+sal_Bool SwViewImp::IsDragPossible( const Point &rPoint )
+{
+ if ( !HasDrawView() )
+ return sal_False;
+
+ const SdrMarkList &rMrkList = GetDrawView()->GetMarkedObjectList();
+
+ if( !rMrkList.GetMarkCount() )
+ return sal_False;
+
+ SdrObject *pO = rMrkList.GetMark(rMrkList.GetMarkCount()-1)->GetMarkedSdrObj();
+
+ SwRect aRect;
+ if( pO && ::CalcClipRect( pO, aRect, sal_False ) )
+ {
+ SwRect aTmp;
+ ::CalcClipRect( pO, aTmp, sal_True );
+ aRect.Union( aTmp );
+ }
+ else
+ aRect = GetShell()->GetLayout()->Frm();
+
+ aRect.Top( aRect.Top() - WIEDUWILLST );
+ aRect.Bottom( aRect.Bottom() + WIEDUWILLST );
+ aRect.Left( aRect.Left() - WIEDUWILLST );
+ aRect.Right( aRect.Right() + WIEDUWILLST );
+ return aRect.IsInside( rPoint );
+}
+
+void SwViewImp::NotifySizeChg( const Size &rNewSz )
+{
+ if ( !HasDrawView() )
+ return;
+
+ if ( GetPageView() )
+ GetPageView()->GetPage()->SetSize( rNewSz );
+
+ const Rectangle aRect( Point( DOCUMENTBORDER, DOCUMENTBORDER ), rNewSz );
+ const Rectangle &rOldWork = GetDrawView()->GetWorkArea();
+ sal_Bool bCheckDrawObjs = sal_False;
+ if ( aRect != rOldWork )
+ {
+ if ( rOldWork.Bottom() > aRect.Bottom() || rOldWork.Right() > aRect.Right())
+ bCheckDrawObjs = sal_True;
+ GetDrawView()->SetWorkArea( aRect );
+ }
+ if ( !bCheckDrawObjs )
+ return;
+
+ OSL_ENSURE( pSh->getIDocumentDrawModelAccess()->GetDrawModel(), "NotifySizeChg without DrawModel" );
+ SdrPage* pPage = pSh->getIDocumentDrawModelAccess()->GetDrawModel()->GetPage( 0 );
+ const sal_uLong nObjs = pPage->GetObjCount();
+ for( sal_uLong nObj = 0; nObj < nObjs; ++nObj )
+ {
+ SdrObject *pObj = pPage->GetObj( nObj );
+ if( !pObj->ISA(SwVirtFlyDrawObj) )
+ {
+ const SwContact *pCont = (SwContact*)GetUserCall(pObj);
+ //JP - 16.3.00 Bug 73920: this function might be called by the
+ // InsertDocument, when a PageDesc-Attribute is
+ // set on a node. Then the SdrObject must not have
+ // an UserCall.
+ if( !pCont || !pCont->ISA(SwDrawContact) )
+ continue;
+
+ const SwFrm *pAnchor = ((SwDrawContact*)pCont)->GetAnchorFrm();
+ if ( !pAnchor || pAnchor->IsInFly() || !pAnchor->IsValid() ||
+ !pAnchor->GetUpper() || !pAnchor->FindPageFrm() ||
+ (FLY_AS_CHAR == pCont->GetFmt()->GetAnchor().GetAnchorId()) )
+ {
+ continue;
+ }
+
+ // no move for drawing objects in header/footer
+ if ( pAnchor->FindFooterOrHeader() )
+ {
+ continue;
+ }
+
+ const Rectangle aBound( pObj->GetCurrentBoundRect() );
+ if ( !aRect.IsInside( aBound ) )
+ {
+ Size aSz;
+ if ( aBound.Left() > aRect.Right() )
+ aSz.Width() = (aRect.Right() - aBound.Left()) - MINFLY;
+ if ( aBound.Top() > aRect.Bottom() )
+ aSz.Height() = (aRect.Bottom() - aBound.Top()) - MINFLY;
+ if ( aSz.Width() || aSz.Height() )
+ pObj->Move( aSz );
+
+ //Note anchor: Large objects can not disappear from the top.
+ aSz.Width() = aSz.Height() = 0;
+ if ( aBound.Bottom() < aRect.Top() )
+ aSz.Width() = (aBound.Bottom() - aRect.Top()) - MINFLY;
+ if ( aBound.Right() < aRect.Left() )
+ aSz.Height() = (aBound.Right() - aRect.Left()) - MINFLY;
+ if ( aSz.Width() || aSz.Height() )
+ pObj->Move( aSz );
+ }
+ }
+ }
+}
+
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/view/viewimp.cxx b/sw/source/core/view/viewimp.cxx
new file mode 100644
index 000000000000..c3ca3f655ae1
--- /dev/null
+++ b/sw/source/core/view/viewimp.cxx
@@ -0,0 +1,476 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+
+#include "crsrsh.hxx"
+#include "rootfrm.hxx"
+#include "pagefrm.hxx"
+#include "viewimp.hxx"
+#include "viewopt.hxx"
+#include "flyfrm.hxx"
+#include "frmfmt.hxx"
+#include "layact.hxx"
+#include "swregion.hxx"
+#include "dflyobj.hxx"
+#include "dview.hxx"
+#include <tools/shl.hxx>
+#include <swmodule.hxx>
+#include <svx/svdpage.hxx>
+#include <accmap.hxx>
+
+#include <pagepreviewlayout.hxx>
+
+#include <comcore.hrc>
+#include <svx/svdundo.hxx>
+#include <IDocumentLayoutAccess.hxx>
+#include <IDocumentDrawModelAccess.hxx>
+#include <IDocumentDeviceAccess.hxx>
+#include <IDocumentSettingAccess.hxx>
+
+void SwViewImp::Init( const SwViewOption *pNewOpt )
+{
+ OSL_ENSURE( pDrawView, "SwViewImp::Init without DrawView" );
+ //Now create the page view if it does not exist.
+ SwRootFrm *pRoot = pSh->GetLayout(); //swmod 071108//swmod 071225
+ if ( !pSdrPageView )
+ {
+ IDocumentDrawModelAccess* pIDDMA = pSh->getIDocumentDrawModelAccess();
+ if ( !pRoot->GetDrawPage() )
+ pRoot->SetDrawPage( pIDDMA->GetDrawModel()->GetPage( 0 ) );
+
+ if ( pRoot->GetDrawPage()->GetSize() != pRoot->Frm().SSize() )
+ pRoot->GetDrawPage()->SetSize( pRoot->Frm().SSize() );
+
+ pSdrPageView = pDrawView->ShowSdrPage( pRoot->GetDrawPage());
+ // notify drawing page view about invisible layers.
+ pIDDMA->NotifyInvisibleLayers( *pSdrPageView );
+ }
+ pDrawView->SetDragStripes( pNewOpt->IsCrossHair() );
+ pDrawView->SetGridSnap( pNewOpt->IsSnap() );
+ pDrawView->SetGridVisible( pNewOpt->IsGridVisible() );
+ const Size &rSz = pNewOpt->GetSnapSize();
+ pDrawView->SetGridCoarse( rSz );
+ const Size aFSize
+ ( rSz.Width() ? rSz.Width() /Max(short(1),pNewOpt->GetDivisionX()):0,
+ rSz.Height()? rSz.Height()/Max(short(1),pNewOpt->GetDivisionY()):0);
+ pDrawView->SetGridFine( aFSize );
+ Fraction aSnGrWdtX(rSz.Width(), pNewOpt->GetDivisionX() + 1);
+ Fraction aSnGrWdtY(rSz.Height(), pNewOpt->GetDivisionY() + 1);
+ pDrawView->SetSnapGridWidth( aSnGrWdtX, aSnGrWdtY );
+
+ if ( pRoot->Frm().HasArea() )
+ pDrawView->SetWorkArea( pRoot->Frm().SVRect() );
+
+ if ( GetShell()->IsPreView() )
+ pDrawView->SetAnimationEnabled( sal_False );
+
+ pDrawView->SetUseIncompatiblePathCreateInterface( sal_False );
+ pDrawView->SetSolidMarkHdl(pNewOpt->IsSolidMarkHdl());
+
+ // it's a JOE interface !
+ pDrawView->SetMarkHdlSizePixel(pNewOpt->IsBigMarkHdl() ? 9 : 7);
+}
+
+SwViewImp::SwViewImp( ViewShell *pParent ) :
+ pSh( pParent ),
+ pDrawView( 0 ),
+ pSdrPageView( 0 ),
+ pFirstVisPage( 0 ),
+ pRegion( 0 ),
+ pLayAct( 0 ),
+ pIdleAct( 0 ),
+ pAccMap( 0 ),
+ pSdrObjCached(NULL),
+ nRestoreActions( 0 ),
+ mpPgPrevwLayout( 0 )
+{
+ bResetHdlHiddenPaint =
+ bSmoothUpdate = bStopSmooth = bStopPrt = sal_False;
+ bFirstPageInvalid = sal_True;
+}
+
+SwViewImp::~SwViewImp()
+{
+ delete pAccMap;
+
+ delete mpPgPrevwLayout;
+
+ if( pDrawView )
+ pDrawView->HideSdrPage();
+
+ delete pDrawView;
+
+ DelRegion();
+
+ OSL_ENSURE( !pLayAct, "Have action for the rest of your life." );
+ OSL_ENSURE( !pIdleAct,"Be idle for the rest of your life." );
+}
+
+void SwViewImp::DelRegion()
+{
+ DELETEZ(pRegion);
+}
+
+sal_Bool SwViewImp::AddPaintRect( const SwRect &rRect )
+{
+ if ( rRect.IsOver( pSh->VisArea() ) )
+ {
+ if ( !pRegion )
+ pRegion = new SwRegionRects( pSh->VisArea() );
+ (*pRegion) -= rRect;
+ return sal_True;
+ }
+ return sal_False;
+}
+
+void SwViewImp::CheckWaitCrsr()
+{
+ if ( pLayAct )
+ pLayAct->CheckWaitCrsr();
+}
+
+sal_Bool SwViewImp::IsCalcLayoutProgress() const
+{
+ if ( pLayAct )
+ return pLayAct->IsCalcLayout();
+ return sal_False;
+}
+
+sal_Bool SwViewImp::IsUpdateExpFlds()
+{
+ if ( pLayAct && pLayAct->IsCalcLayout() )
+ {
+ pLayAct->SetUpdateExpFlds();
+ return sal_True;
+ }
+ return sal_False;
+}
+
+void SwViewImp::SetFirstVisPage()
+{
+ if ( pSh->bDocSizeChgd && pSh->VisArea().Top() > pSh->GetLayout()->Frm().Height() )
+ {
+ //We are in an "Action", and the VisArea is behind the first visible page due
+ //to delete operations. To prevent expensive formatting, return the last page
+ pFirstVisPage = (SwPageFrm*)pSh->GetLayout()->Lower();
+ while ( pFirstVisPage && pFirstVisPage->GetNext() )
+ pFirstVisPage = (SwPageFrm*)pFirstVisPage->GetNext();
+ }
+ else
+ {
+ const SwViewOption* pSwViewOption = GetShell()->GetViewOptions();
+ const bool bBookMode = pSwViewOption->IsViewLayoutBookMode();
+
+ SwPageFrm *pPage = (SwPageFrm*)pSh->GetLayout()->Lower();
+ SwRect aPageRect = pPage->GetBoundRect();
+ while ( pPage && !aPageRect.IsOver( pSh->VisArea() ) )
+ {
+ pPage = (SwPageFrm*)pPage->GetNext();
+ if ( pPage )
+ {
+ aPageRect = pPage->GetBoundRect();
+ if ( bBookMode && pPage->IsEmptyPage() )
+ {
+ const SwPageFrm& rFormatPage = pPage->GetFormatPage();
+ aPageRect.SSize() = rFormatPage.GetBoundRect().SSize();
+ }
+ }
+ }
+ pFirstVisPage = pPage ? pPage : (SwPageFrm*)pSh->GetLayout()->Lower();
+ }
+ bFirstPageInvalid = sal_False;
+}
+
+void SwViewImp::MakeDrawView()
+{
+ IDocumentDrawModelAccess* pIDDMA = GetShell()->getIDocumentDrawModelAccess();
+
+ // the else here is not an error, _MakeDrawModel() calls this method again
+ // after the DrawModel is created to create DrawViews for all shells...
+ if( !pIDDMA->GetDrawModel() )
+ {
+ pIDDMA->_MakeDrawModel();
+ }
+ else
+ {
+ if ( !pDrawView )
+ {
+ // #i72809#
+ // Discussed with FME, he also thinks that the getPrinter is old and not correct. When i got
+ // him right, it anyways returns GetOut() when it's a printer, but NULL when not. He suggested
+ // to use GetOut() and check the existing cases.
+ // Check worked well. Took a look at viewing, printing, PDF export and print preview with a test
+ // document which has an empty 2nd page (right page, see bug)
+ OutputDevice* pOutDevForDrawView = GetShell()->GetWin();
+
+ if(!pOutDevForDrawView)
+ {
+ pOutDevForDrawView = GetShell()->GetOut();
+ }
+
+ pDrawView = new SwDrawView( *this, pIDDMA->GetDrawModel(), pOutDevForDrawView);
+ }
+
+ GetDrawView()->SetActiveLayer( XubString::CreateFromAscii( RTL_CONSTASCII_STRINGPARAM( "Heaven" ) ) );
+ const SwViewOption* pSwViewOption = GetShell()->GetViewOptions();
+ Init(pSwViewOption);
+
+ // #i68597# If document is read-only, we will not profit from overlay, so switch it off.
+ if(pDrawView && pDrawView->IsBufferedOverlayAllowed())
+ {
+ if(pSwViewOption->IsReadonly())
+ {
+ pDrawView->SetBufferedOverlayAllowed(false);
+ }
+ }
+ }
+}
+
+Color SwViewImp::GetRetoucheColor() const
+{
+ Color aRet( COL_TRANSPARENT );
+ const ViewShell &rSh = *GetShell();
+ if ( rSh.GetWin() )
+ {
+ if ( rSh.GetViewOptions()->getBrowseMode() &&
+ COL_TRANSPARENT != rSh.GetViewOptions()->GetRetoucheColor().GetColor() )
+ aRet = rSh.GetViewOptions()->GetRetoucheColor();
+ else if(rSh.GetViewOptions()->IsPagePreview() &&
+ !SW_MOD()->GetAccessibilityOptions().GetIsForPagePreviews())
+ aRet.SetColor(COL_WHITE);
+ else
+ aRet = SwViewOption::GetDocColor();
+ }
+ return aRet;
+}
+
+void SwViewImp::InitPagePreviewLayout()
+{
+ OSL_ENSURE( pSh->GetLayout(), "no layout - page preview layout can not be created.");
+ if ( pSh->GetLayout() )
+ mpPgPrevwLayout = new SwPagePreviewLayout( *pSh, *(pSh->GetLayout()) );
+}
+
+void SwViewImp::UpdateAccessible()
+{
+ // We require a layout and an XModel to be accessible.
+ IDocumentLayoutAccess* pIDLA = GetShell()->getIDocumentLayoutAccess();
+ Window *pWin = GetShell()->GetWin();
+ OSL_ENSURE( GetShell()->GetLayout(), "no layout, no access" ); //swmod 071108//swmod 071225
+ OSL_ENSURE( pWin, "no window, no access" );
+
+ if( IsAccessible() && pIDLA->GetCurrentViewShell() && pWin ) //swmod 071108//swmod 071225
+ GetAccessibleMap().GetDocumentView();
+}
+
+void SwViewImp::DisposeAccessible( const SwFrm *pFrm,
+ const SdrObject *pObj,
+ sal_Bool bRecursive )
+{
+ OSL_ENSURE( !pFrm || pFrm->IsAccessibleFrm(), "frame is not accessible" );
+ ViewShell *pVSh = GetShell();
+ ViewShell *pTmp = pVSh;
+ do
+ {
+ if( pTmp->Imp()->IsAccessible() )
+ pTmp->Imp()->GetAccessibleMap().Dispose( pFrm, pObj, 0, bRecursive );
+ pTmp = (ViewShell *)pTmp->GetNext();
+ } while ( pTmp != pVSh );
+}
+
+void SwViewImp::MoveAccessible( const SwFrm *pFrm, const SdrObject *pObj,
+ const SwRect& rOldFrm )
+{
+ OSL_ENSURE( !pFrm || pFrm->IsAccessibleFrm(), "frame is not accessible" );
+ ViewShell *pVSh = GetShell();
+ ViewShell *pTmp = pVSh;
+ do
+ {
+ if( pTmp->Imp()->IsAccessible() )
+ pTmp->Imp()->GetAccessibleMap().InvalidatePosOrSize( pFrm, pObj, 0,
+ rOldFrm );
+ pTmp = (ViewShell *)pTmp->GetNext();
+ } while ( pTmp != pVSh );
+}
+
+void SwViewImp::InvalidateAccessibleFrmContent( const SwFrm *pFrm )
+{
+ OSL_ENSURE( pFrm->IsAccessibleFrm(), "frame is not accessible" );
+ ViewShell *pVSh = GetShell();
+ ViewShell *pTmp = pVSh;
+ do
+ {
+ if( pTmp->Imp()->IsAccessible() )
+ pTmp->Imp()->GetAccessibleMap().InvalidateContent( pFrm );
+ pTmp = (ViewShell *)pTmp->GetNext();
+ } while ( pTmp != pVSh );
+}
+
+void SwViewImp::InvalidateAccessibleCursorPosition( const SwFrm *pFrm )
+{
+ if( IsAccessible() )
+ GetAccessibleMap().InvalidateCursorPosition( pFrm );
+}
+
+void SwViewImp::InvalidateAccessibleEditableState( sal_Bool bAllShells,
+ const SwFrm *pFrm )
+{
+ if( bAllShells )
+ {
+ ViewShell *pVSh = GetShell();
+ ViewShell *pTmp = pVSh;
+ do
+ {
+ if( pTmp->Imp()->IsAccessible() )
+ pTmp->Imp()->GetAccessibleMap().InvalidateStates( ACC_STATE_EDITABLE, pFrm );
+ pTmp = (ViewShell *)pTmp->GetNext();
+ } while ( pTmp != pVSh );
+ }
+ else if( IsAccessible() )
+ {
+ GetAccessibleMap().InvalidateStates( ACC_STATE_EDITABLE, pFrm );
+ }
+}
+
+void SwViewImp::InvalidateAccessibleRelationSet( const SwFlyFrm *pMaster,
+ const SwFlyFrm *pFollow )
+{
+ ViewShell *pVSh = GetShell();
+ ViewShell *pTmp = pVSh;
+ do
+ {
+ if( pTmp->Imp()->IsAccessible() )
+ pTmp->Imp()->GetAccessibleMap().InvalidateRelationSet( pMaster,
+ pFollow );
+ pTmp = (ViewShell *)pTmp->GetNext();
+ } while ( pTmp != pVSh );
+}
+
+// #i27138# invalidate CONTENT_FLOWS_FROM/_TO relation for paragraphs
+void SwViewImp::_InvalidateAccessibleParaFlowRelation( const SwTxtFrm* _pFromTxtFrm,
+ const SwTxtFrm* _pToTxtFrm )
+{
+ if ( !_pFromTxtFrm && !_pToTxtFrm )
+ {
+ // No text frame provided. Thus, nothing to do.
+ return;
+ }
+
+ ViewShell* pVSh = GetShell();
+ ViewShell* pTmp = pVSh;
+ do
+ {
+ if ( pTmp->Imp()->IsAccessible() )
+ {
+ if ( _pFromTxtFrm )
+ {
+ pTmp->Imp()->GetAccessibleMap().
+ InvalidateParaFlowRelation( *_pFromTxtFrm, true );
+ }
+ if ( _pToTxtFrm )
+ {
+ pTmp->Imp()->GetAccessibleMap().
+ InvalidateParaFlowRelation( *_pToTxtFrm, false );
+ }
+ }
+ pTmp = (ViewShell *)pTmp->GetNext();
+ } while ( pTmp != pVSh );
+}
+
+//#i27301# invalidate text selection for paragraphs
+void SwViewImp::_InvalidateAccessibleParaTextSelection()
+{
+ ViewShell* pVSh = GetShell();
+ ViewShell* pTmp = pVSh;
+ do
+ {
+ if ( pTmp->Imp()->IsAccessible() )
+ {
+ pTmp->Imp()->GetAccessibleMap().InvalidateTextSelectionOfAllParas();
+ }
+
+ pTmp = (ViewShell *)pTmp->GetNext();
+ } while ( pTmp != pVSh );
+}
+
+//#i88069# invalidate attributes for paragraphs
+void SwViewImp::_InvalidateAccessibleParaAttrs( const SwTxtFrm& rTxtFrm )
+{
+ ViewShell* pVSh = GetShell();
+ ViewShell* pTmp = pVSh;
+ do
+ {
+ if ( pTmp->Imp()->IsAccessible() )
+ {
+ pTmp->Imp()->GetAccessibleMap().InvalidateAttr( rTxtFrm );
+ }
+
+ pTmp = (ViewShell *)pTmp->GetNext();
+ } while ( pTmp != pVSh );
+}
+
+void SwViewImp::UpdateAccessiblePreview( const std::vector<PrevwPage*>& _rPrevwPages,
+ const Fraction& _rScale,
+ const SwPageFrm* _pSelectedPageFrm,
+ const Size& _rPrevwWinSize )
+{
+ if( IsAccessible() )
+ GetAccessibleMap().UpdatePreview( _rPrevwPages, _rScale,
+ _pSelectedPageFrm, _rPrevwWinSize );
+}
+
+void SwViewImp::InvalidateAccessiblePreViewSelection( sal_uInt16 nSelPage )
+{
+ if( IsAccessible() )
+ GetAccessibleMap().InvalidatePreViewSelection( nSelPage );
+}
+
+SwAccessibleMap *SwViewImp::CreateAccessibleMap()
+{
+ OSL_ENSURE( !pAccMap, "accessible map exists" );
+ pAccMap = new SwAccessibleMap( GetShell() );
+ return pAccMap;
+}
+
+void SwViewImp::FireAccessibleEvents()
+{
+ if( IsAccessible() )
+ GetAccessibleMap().FireEvents();
+}
+
+IMPL_LINK(SwViewImp, SetStopPrt, void *, EMPTYARG)
+{
+ bStopPrt = sal_True;
+
+ return 0;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/view/viewpg.cxx b/sw/source/core/view/viewpg.cxx
new file mode 100644
index 000000000000..765a6cd94fab
--- /dev/null
+++ b/sw/source/core/view/viewpg.cxx
@@ -0,0 +1,247 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+#include <com/sun/star/uno/Sequence.hxx>
+
+#include <hintids.hxx>
+#include <vcl/window.hxx>
+#include <vcl/oldprintadaptor.hxx>
+#include <sfx2/printer.hxx>
+#include <sfx2/progress.hxx>
+#include <pvprtdat.hxx>
+#include <viewsh.hxx>
+#include <pagefrm.hxx>
+#include <rootfrm.hxx>
+#include <viewimp.hxx>
+#include <viewopt.hxx>
+#include <printdata.hxx>
+#include <fldbas.hxx>
+#include <ptqueue.hxx>
+#include <swregion.hxx>
+#include <hints.hxx>
+#include <fntcache.hxx>
+
+#include <statstr.hrc> // Text fuer SfxProgress
+#include <comcore.hrc>
+
+#include <IDocumentFieldsAccess.hxx>
+#include <IDocumentDeviceAccess.hxx>
+
+
+using namespace ::com::sun::star;
+
+
+SwPagePreviewLayout* ViewShell::PagePreviewLayout()
+{
+ return Imp()->PagePreviewLayout();
+}
+
+void ViewShell::ShowPreViewSelection( sal_uInt16 nSelPage )
+{
+ Imp()->InvalidateAccessiblePreViewSelection( nSelPage );
+}
+
+//#i6467# adjust view options for page preview
+void ViewShell::AdjustOptionsForPagePreview(SwPrintData const& rPrintOptions)
+{
+ if ( !IsPreView() )
+ {
+ OSL_FAIL( "view shell doesn't belongs to a page preview - no adjustment of its view options");
+ return;
+ }
+
+ PrepareForPrint( rPrintOptions );
+
+ return;
+}
+
+//#i14016# - consider empty pages on calculation of the scaling for a page to be printed.
+void ViewShell::PrintProspect(
+ OutputDevice *pOutDev,
+ const SwPrintData &rPrintData,
+ sal_Int32 nRenderer // the index in the vector of prospect pages to be printed
+ )
+{
+ const sal_Int32 nMaxRenderer = rPrintData.GetRenderData().GetPagePairsForProspectPrinting().size() - 1;
+#if OSL_DEBUG_LEVEL > 1
+ DBG_ASSERT( 0 <= nRenderer && nRenderer <= nMaxRenderer, "nRenderer out of bounds");
+#endif
+ Printer *pPrinter = dynamic_cast< Printer * >(pOutDev);
+ if (!pPrinter || nMaxRenderer < 0 || nRenderer < 0 || nRenderer > nMaxRenderer)
+ return;
+
+ // save settings of OutputDevice (should be done always since the
+ // output device is now provided by a call from outside the Writer)
+ pPrinter->Push();
+
+ std::pair< sal_Int32, sal_Int32 > rPagesToPrint =
+ rPrintData.GetRenderData().GetPagePairsForProspectPrinting()[ nRenderer ];
+#if OSL_DEBUG_LEVEL > 1
+ DBG_ASSERT( rPagesToPrint.first == -1 || rPrintData.GetRenderData().GetValidPagesSet().count( rPagesToPrint.first ) == 1, "first Page not valid" );
+ DBG_ASSERT( rPagesToPrint.second == -1 || rPrintData.GetRenderData().GetValidPagesSet().count( rPagesToPrint.second ) == 1, "second Page not valid" );
+#endif
+
+ // create a new shell for the Printer
+ ViewShell aShell( *this, 0, pPrinter );
+
+ SET_CURR_SHELL( &aShell );
+
+ aShell.PrepareForPrint( rPrintData );
+
+ //!! applying view options and formatting the dcoument should now only be done in getRendererCount!
+
+ MapMode aMapMode( MAP_TWIP );
+ Size aPrtSize( pPrinter->PixelToLogic( pPrinter->GetPaperSizePixel(), aMapMode ) );
+
+ SwTwips nMaxRowSz, nMaxColSz;
+
+ const SwPageFrm *pStPage = 0;
+ const SwPageFrm *pNxtPage = 0;
+ const SwRenderData::ValidStartFramesMap_t &rFrms = rPrintData.GetRenderData().GetValidStartFrames();
+ if (rPagesToPrint.first > 0)
+ {
+ SwRenderData::ValidStartFramesMap_t::const_iterator aIt( rFrms.find( rPagesToPrint.first ) );
+ DBG_ASSERT( aIt != rFrms.end(), "failed to find start frame" );
+ pStPage = aIt->second;
+ }
+ if (rPagesToPrint.second > 0)
+ {
+ SwRenderData::ValidStartFramesMap_t::const_iterator aIt( rFrms.find( rPagesToPrint.second ) );
+ DBG_ASSERT( aIt != rFrms.end(), "failed to find start frame" );
+ pNxtPage = aIt->second;
+ }
+
+ //#i14016# - consider empty pages on calculation of page size, used for calculation of scaling.
+ Size aSttPageSize;
+ if ( pStPage )
+ {
+ if ( pStPage->IsEmptyPage() )
+ {
+ if ( pStPage->GetPhyPageNum() % 2 == 0 )
+ aSttPageSize = pStPage->GetPrev()->Frm().SSize();
+ else
+ aSttPageSize = pStPage->GetNext()->Frm().SSize();
+ }
+ else
+ {
+ aSttPageSize = pStPage->Frm().SSize();
+ }
+ }
+ Size aNxtPageSize;
+ if ( pNxtPage )
+ {
+ if ( pNxtPage->IsEmptyPage() )
+ {
+ if ( pNxtPage->GetPhyPageNum() % 2 == 0 )
+ aNxtPageSize = pNxtPage->GetPrev()->Frm().SSize();
+ else
+ aNxtPageSize = pNxtPage->GetNext()->Frm().SSize();
+ }
+ else
+ {
+ aNxtPageSize = pNxtPage->Frm().SSize();
+ }
+ }
+
+ if( !pStPage )
+ {
+ nMaxColSz = 2 * aNxtPageSize.Width();
+ nMaxRowSz = aNxtPageSize.Height();
+ }
+ else if( !pNxtPage )
+ {
+ nMaxColSz = 2 * aSttPageSize.Width();
+ nMaxRowSz = aSttPageSize.Height();
+ }
+ else
+ {
+ nMaxColSz = aNxtPageSize.Width() + aSttPageSize.Width();
+ nMaxRowSz = Max( aNxtPageSize.Height(), aSttPageSize.Height() );
+ }
+
+ aMapMode.SetOrigin( Point() );
+ {
+ Fraction aScX( aPrtSize.Width(), nMaxColSz );
+ Fraction aScY( aPrtSize.Height(), nMaxRowSz );
+ if( aScX < aScY )
+ aScY = aScX;
+
+ {
+ aScY *= Fraction( 1000, 1 );
+ long nTmp = (long)aScY;
+ if( 1 < nTmp )
+ --nTmp;
+ else
+ nTmp = 1;
+ aScY = Fraction( nTmp, 1000 );
+ }
+
+ aMapMode.SetScaleY( aScY );
+ aMapMode.SetScaleX( aScY );
+ }
+
+ Size aTmpPrtSize( pPrinter->PixelToLogic( pPrinter->GetPaperSizePixel(), aMapMode ) );
+
+ // calculate start point for equal border on all sides
+ Point aSttPt( (aTmpPrtSize.Width() - nMaxColSz) / 2,
+ (aTmpPrtSize.Height() - nMaxRowSz) / 2 );
+ for( int nC = 0; nC < 2; ++nC )
+ {
+ if( pStPage )
+ {
+ aShell.Imp()->SetFirstVisPageInvalid();
+ aShell.aVisArea = pStPage->Frm();
+
+ Point aPos( aSttPt );
+ aPos -= aShell.aVisArea.Pos();
+// aPos -= aPrtOff;
+ aMapMode.SetOrigin( aPos );
+ pPrinter->SetMapMode( aMapMode );
+ pStPage->GetUpper()->Paint( pStPage->Frm() );
+ }
+
+ pStPage = pNxtPage;
+ aSttPt.X() += aTmpPrtSize.Width() / 2;
+ }
+
+ SwPaintQueue::Repaint();
+
+ //!! applying/modifying view options and formatting the dcoument should now only be done in getRendererCount!
+
+ pFntCache->Flush();
+
+ // restore settings of OutputDevice (should be done always now since the
+ // output device is now provided by a call from outside the Writer)
+ pPrinter->Pop();
+}
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/view/viewsh.cxx b/sw/source/core/view/viewsh.cxx
new file mode 100644
index 000000000000..797ed01a3287
--- /dev/null
+++ b/sw/source/core/view/viewsh.cxx
@@ -0,0 +1,2326 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+#define _SVX_PARAITEM_HXX
+#define _SVX_TEXTITEM_HXX
+
+#include <com/sun/star/accessibility/XAccessible.hpp>
+
+#include <sfx2/viewfrm.hxx>
+#include <sfx2/progress.hxx>
+#include <svx/srchdlg.hxx>
+#include <svx/svdobj.hxx>
+#include <sfx2/viewsh.hxx>
+#include <swwait.hxx>
+#include <swmodule.hxx>
+#include <fesh.hxx>
+#include <doc.hxx>
+#include <rootfrm.hxx>
+#include <pagefrm.hxx>
+#include <cntfrm.hxx>
+#include <viewimp.hxx>
+#include <frmtool.hxx>
+#include <viewopt.hxx>
+#include <dview.hxx>
+#include <swregion.hxx>
+#include <hints.hxx>
+#include <fmtfsize.hxx>
+#include <docufld.hxx>
+#include <txtfrm.hxx>
+#include <layact.hxx>
+#include <mdiexp.hxx>
+#include <fntcache.hxx>
+#include <ptqueue.hxx>
+#include <tabfrm.hxx>
+#include <docsh.hxx>
+#include <pagedesc.hxx>
+#include <ndole.hxx>
+#include <ndindex.hxx>
+#include <accmap.hxx>
+#include <svtools/colorcfg.hxx>
+#include <svtools/accessibilityoptions.hxx>
+#include <accessibilityoptions.hxx>
+#include <statstr.hrc>
+#include <comcore.hrc>
+#include <pagepreviewlayout.hxx>
+#include <sortedobjs.hxx>
+#include <anchoredobject.hxx>
+
+#include "../../ui/inc/view.hxx"
+#include <PostItMgr.hxx>
+#include <vcl/virdev.hxx>
+
+#include <vcl/svapp.hxx>
+
+#include <svx/sdrpaintwindow.hxx>
+
+sal_Bool ViewShell::bLstAct = sal_False;
+ShellResource *ViewShell::pShellRes = 0;
+Window *ViewShell::pCareWindow = 0;
+BitmapEx* ViewShell::pErrorBmp = NULL;
+BitmapEx* ViewShell::pReplaceBmp = NULL;
+
+sal_Bool bInSizeNotify = sal_False;
+
+DBG_NAME(LayoutIdle)
+
+TYPEINIT0(ViewShell);
+
+using namespace ::com::sun::star;
+
+//////////////////////////////////////////////////////////////////////////////
+// #i72754# 2nd set of Pre/PostPaints
+// This time it uses the lock counter mnPrePostPaintCount to allow only one activation
+// and deactivation and mpPrePostOutDev to remember the OutDev from the BeginDrawLayers
+// call. That way, all places where paint take place can be handled the same way, even
+// when calling other paint methods. This is the case at the places where SW paints
+// buffered into VDevs to avoid flicker. Tis is in general problematic and should be
+// solved once using the BufferedOutput functionality of the DrawView.
+
+void ViewShell::PrePaint()
+{
+ // forward PrePaint event from VCL Window to DrawingLayer
+ if(HasDrawView())
+ {
+ Imp()->GetDrawView()->PrePaint();
+ }
+}
+
+void ViewShell::DLPrePaint2(const Region& rRegion)
+{
+ if(0L == mnPrePostPaintCount)
+ {
+ // #i75172# ensure DrawView to use DrawingLayer bufferings
+ if ( !HasDrawView() )
+ MakeDrawView();
+
+ // Prefer window; if tot available, get pOut (e.g. printer)
+ mpPrePostOutDev = (GetWin() ? GetWin() : GetOut());
+
+ // #i74769# use SdrPaintWindow now direct
+ mpTargetPaintWindow = Imp()->GetDrawView()->BeginDrawLayers(mpPrePostOutDev, rRegion);
+ OSL_ENSURE(mpTargetPaintWindow, "BeginDrawLayers: Got no SdrPaintWindow (!)");
+
+ // #i74769# if prerender, save OutDev and redirect to PreRenderDevice
+ if(mpTargetPaintWindow->GetPreRenderDevice())
+ {
+ mpBufferedOut = pOut;
+ pOut = &(mpTargetPaintWindow->GetTargetOutputDevice());
+ }
+
+ // remember original paint MapMode for wrapped FlyFrame paints
+ maPrePostMapMode = pOut->GetMapMode();
+ }
+
+ mnPrePostPaintCount++;
+}
+
+void ViewShell::DLPostPaint2(bool bPaintFormLayer)
+{
+ OSL_ENSURE(mnPrePostPaintCount > 0L, "ViewShell::DLPostPaint2: Pre/PostPaint encapsulation broken (!)");
+ mnPrePostPaintCount--;
+
+ if((0L == mnPrePostPaintCount) && (0 != mpTargetPaintWindow))
+ {
+ // #i74769# restore buffered OutDev
+ if(mpTargetPaintWindow->GetPreRenderDevice())
+ {
+ pOut = mpBufferedOut;
+ }
+
+ // #i74769# use SdrPaintWindow now direct
+ Imp()->GetDrawView()->EndDrawLayers(*mpTargetPaintWindow, bPaintFormLayer);
+ mpTargetPaintWindow = 0;
+ }
+}
+
+//////////////////////////////////////////////////////////////////////////////
+
+void ViewShell::ImplEndAction( const sal_Bool bIdleEnd )
+{
+ //There is nothing to do here for the printer
+ if ( !GetWin() || IsPreView() )
+ {
+ bPaintWorks = sal_True;
+ UISizeNotify();
+ return;
+ }
+
+ bInEndAction = sal_True;
+
+ ViewShell::bLstAct = sal_True;
+ ViewShell *pSh = (ViewShell*)this->GetNext();
+ while ( pSh != this )
+ {
+ if ( pSh->ActionPend() )
+ {
+ ViewShell::bLstAct = sal_False;
+ pSh = this;
+ }
+ else
+ pSh = (ViewShell*)pSh->GetNext();
+ }
+
+ const bool bIsShellForCheckViewLayout = ( this == GetLayout()->GetCurrShell() );
+
+ SET_CURR_SHELL( this );
+ if ( Imp()->HasDrawView() && !Imp()->GetDrawView()->areMarkHandlesHidden() )
+ Imp()->StartAction();
+
+ if ( Imp()->GetRegion() && Imp()->GetRegion()->GetOrigin() != VisArea() )
+ Imp()->DelRegion();
+
+ const sal_Bool bExtraData = ::IsExtraData( GetDoc() );
+
+ if ( !bIdleEnd )
+ {
+ SwLayAction aAction( GetLayout(), Imp() );
+ aAction.SetComplete( sal_False );
+ if ( nLockPaint )
+ aAction.SetPaint( sal_False );
+ aAction.SetInputType( INPUT_KEYBOARD );
+ aAction.Action();
+ }
+
+ if ( bIsShellForCheckViewLayout )
+ GetLayout()->CheckViewLayout( GetViewOptions(), &aVisArea );
+
+ //If we do not generate Paints, we wait for the paint by the system.
+ //Then, the clipping is set correctly, for example: move a DrawObject.
+ if ( Imp()->GetRegion() ||
+ aInvalidRect.HasArea() ||
+ bExtraData )
+ {
+ if ( !nLockPaint )
+ {
+ sal_Bool bPaintsFromSystem = aInvalidRect.HasArea();
+ GetWin()->Update();
+ if ( aInvalidRect.HasArea() )
+ {
+ if ( bPaintsFromSystem )
+ Imp()->AddPaintRect( aInvalidRect );
+
+ ResetInvalidRect();
+ bPaintsFromSystem = sal_True;
+ }
+ bPaintWorks = sal_True;
+
+ SwRegionRects *pRegion = Imp()->GetRegion();
+
+ sal_Bool bShowCrsr = pRegion && IsA( TYPE(SwCrsrShell) );
+ if( bShowCrsr )
+ ((SwCrsrShell*)this)->HideCrsrs();
+
+ if ( pRegion )
+ {
+ SwRootFrm* pCurrentLayout = GetLayout();
+
+ Imp()->pRegion = NULL;
+
+ // First Invert then Compress, never the other way round!
+ pRegion->Invert();
+
+ pRegion->Compress();
+
+ VirtualDevice *pVout = 0;
+ while ( pRegion->Count() )
+ {
+ SwRect aRect( (*pRegion)[ pRegion->Count() - 1 ] );
+ pRegion->Remove( pRegion->Count() - 1 );
+
+ sal_Bool bPaint = sal_True;
+ if ( IsEndActionByVirDev() )
+ {
+ if ( !pVout )
+ pVout = new VirtualDevice( *GetOut() );
+ MapMode aMapMode( GetOut()->GetMapMode() );
+ pVout->SetMapMode( aMapMode );
+
+ sal_Bool bSizeOK = sal_True;
+
+ Rectangle aTmp1( aRect.SVRect() );
+ aTmp1 = GetOut()->LogicToPixel( aTmp1 );
+ Rectangle aTmp2( GetOut()->PixelToLogic( aTmp1 ) );
+ if ( aTmp2.Left() > aRect.Left() )
+ aTmp1.Left() = Max( 0L, aTmp1.Left() - 1L );
+ if ( aTmp2.Top() > aRect.Top() )
+ aTmp1.Top() = Max( 0L, aTmp1.Top() - 1L );
+ aTmp1.Right() += 1;
+ aTmp1.Bottom() += 1;
+ aTmp1 = GetOut()->PixelToLogic( aTmp1 );
+ aRect = SwRect( aTmp1 );
+
+ const Size aTmp( pVout->GetOutputSize() );
+ if ( aTmp.Height() < aRect.Height() ||
+ aTmp.Width() < aRect.Width() )
+ {
+ bSizeOK = pVout->SetOutputSize( aRect.SSize() );
+ }
+ if ( bSizeOK )
+ {
+ bPaint = sal_False;
+
+ // #i72754# start Pre/PostPaint encapsulation before pOut is changed to the buffering VDev
+ const Region aRepaintRegion(aRect.SVRect());
+ DLPrePaint2(aRepaintRegion);
+
+ OutputDevice *pOld = GetOut();
+ pVout->SetLineColor( pOld->GetLineColor() );
+ pVout->SetFillColor( pOld->GetFillColor() );
+ Point aOrigin( aRect.Pos() );
+ aOrigin.X() = -aOrigin.X(); aOrigin.Y() = -aOrigin.Y();
+ aMapMode.SetOrigin( aOrigin );
+ pVout->SetMapMode( aMapMode );
+
+ pOut = pVout;
+ if ( bPaintsFromSystem )
+ PaintDesktop( aRect );
+ pCurrentLayout->Paint( aRect );
+ pOld->DrawOutDev( aRect.Pos(), aRect.SSize(),
+ aRect.Pos(), aRect.SSize(), *pVout );
+ pOut = pOld;
+
+ // #i72754# end Pre/PostPaint encapsulation when pOut is back and content is painted
+ DLPostPaint2(true);
+ }
+ }
+ if ( bPaint )
+ {
+ // #i75172# begin DrawingLayer paint
+ // need to do begin/end DrawingLayer preparation for each single rectangle of the
+ // repaint region. I already tried to prepare only once for the whole Region. This
+ // seems to work (and does technically) but fails with transparent objects. Since the
+ // region given to BeginDarwLayers() defines the clip region for DrawingLayer paint,
+ // transparent objects in the single rectangles will indeed be painted multiple times.
+ DLPrePaint2(Region(aRect.SVRect()));
+
+ if ( bPaintsFromSystem )
+ PaintDesktop( aRect );
+ pCurrentLayout->Paint( aRect );
+
+ // #i75172# end DrawingLayer paint
+ DLPostPaint2(true);
+ }
+
+ // #i107365#
+ // Direct paint has been performed. Thus, take care of
+ // transparent child windows.
+ if ( GetWin() )
+ {
+ Window& rWindow = *(GetWin());
+ if(rWindow.IsChildTransparentModeEnabled() && rWindow.GetChildCount())
+ {
+ const Rectangle aRectanglePixel(rWindow.LogicToPixel(aRect.SVRect()));
+
+ for ( sal_uInt16 a(0); a < rWindow.GetChildCount(); a++ )
+ {
+ Window* pCandidate = rWindow.GetChild(a);
+
+ if ( pCandidate && pCandidate->IsPaintTransparent() )
+ {
+ const Rectangle aCandidatePosSizePixel(
+ pCandidate->GetPosPixel(),
+ pCandidate->GetSizePixel());
+
+ if ( aCandidatePosSizePixel.IsOver(aRectanglePixel) )
+ {
+ pCandidate->Invalidate( INVALIDATE_NOTRANSPARENT|INVALIDATE_CHILDREN );
+ pCandidate->Update();
+ }
+ }
+ }
+ }
+ }
+ }
+
+ delete pVout;
+ delete pRegion;
+ Imp()->DelRegion();
+ }
+ if( bShowCrsr )
+ ((SwCrsrShell*)this)->ShowCrsrs( sal_True );
+ }
+ else
+ {
+ Imp()->DelRegion();
+ bPaintWorks = sal_True;
+ }
+ }
+ else
+ bPaintWorks = sal_True;
+
+ bInEndAction = sal_False;
+ ViewShell::bLstAct = sal_False;
+ Imp()->EndAction();
+
+
+ --nStartAction;
+ UISizeNotify();
+ ++nStartAction;
+
+ if( Imp()->IsAccessible() )
+ Imp()->FireAccessibleEvents();
+}
+
+void ViewShell::ImplStartAction()
+{
+ bPaintWorks = sal_False;
+ Imp()->StartAction();
+}
+
+void ViewShell::ImplLockPaint()
+{
+ if ( GetWin() && GetWin()->IsVisible() )
+ GetWin()->EnablePaint( sal_False );
+ Imp()->LockPaint();
+}
+
+
+void ViewShell::ImplUnlockPaint( sal_Bool bVirDev )
+{
+ SET_CURR_SHELL( this );
+ if ( GetWin() && GetWin()->IsVisible() )
+ {
+ if ( (bInSizeNotify || bVirDev ) && VisArea().HasArea() )
+ {
+ //prevent refresh with virtual device to flicker.
+ VirtualDevice *pVout = new VirtualDevice( *pOut );
+ pVout->SetMapMode( pOut->GetMapMode() );
+ Size aSize( VisArea().SSize() );
+ aSize.Width() += 20;
+ aSize.Height()+= 20;
+ if( pVout->SetOutputSize( aSize ) )
+ {
+ GetWin()->EnablePaint( sal_True );
+ GetWin()->Validate();
+
+ Imp()->UnlockPaint();
+ pVout->SetLineColor( pOut->GetLineColor() );
+ pVout->SetFillColor( pOut->GetFillColor() );
+
+ // #i72754# start Pre/PostPaint encapsulation before pOut is changed to the buffering VDev
+ const Region aRepaintRegion(VisArea().SVRect());
+ DLPrePaint2(aRepaintRegion);
+
+ OutputDevice *pOld = pOut;
+ pOut = pVout;
+ Paint( VisArea().SVRect() );
+ pOut = pOld;
+ pOut->DrawOutDev( VisArea().Pos(), aSize,
+ VisArea().Pos(), aSize, *pVout );
+
+ // #i72754# end Pre/PostPaint encapsulation when pOut is back and content is painted
+ DLPostPaint2(true);
+ }
+ else
+ {
+ Imp()->UnlockPaint();
+ GetWin()->EnablePaint( sal_True );
+ GetWin()->Invalidate( INVALIDATE_CHILDREN );
+ }
+ delete pVout;
+ }
+ else
+ {
+ Imp()->UnlockPaint();
+ GetWin()->EnablePaint( sal_True );
+ GetWin()->Invalidate( INVALIDATE_CHILDREN );
+ }
+ }
+ else
+ Imp()->UnlockPaint();
+}
+
+sal_Bool ViewShell::AddPaintRect( const SwRect & rRect )
+{
+ sal_Bool bRet = sal_False;
+ ViewShell *pSh = this;
+ do
+ {
+ if( pSh->Imp() )
+ {
+ if ( pSh->IsPreView() && pSh->GetWin() )
+ ::RepaintPagePreview( pSh, rRect );
+ else
+ bRet |= pSh->Imp()->AddPaintRect( rRect );//swmod 080111
+ }
+ pSh = (ViewShell*)pSh->GetNext();
+ } while ( pSh != this );
+ return bRet;
+}
+
+void ViewShell::InvalidateWindows( const SwRect &rRect )
+{
+ if ( !Imp()->IsCalcLayoutProgress() )
+ {
+ ViewShell *pSh = this;
+ do
+ {
+ if ( pSh->GetWin() )
+ {
+ if ( pSh->IsPreView() )
+ ::RepaintPagePreview( pSh, rRect );
+ else if ( pSh->VisArea().IsOver( rRect ) )
+ pSh->GetWin()->Invalidate( rRect.SVRect() );
+ }
+ pSh = (ViewShell*)pSh->GetNext();
+
+ } while ( pSh != this );
+ }
+}
+
+void ViewShell::MakeVisible( const SwRect &rRect )
+{
+ if ( !VisArea().IsInside( rRect ) || IsScrollMDI( this, rRect ) || GetCareWin(*this) )
+ {
+ if ( !IsViewLocked() )
+ {
+ if( pWin )
+ {
+ const SwFrm* pRoot = GetLayout();
+ int nLoopCnt = 3;
+ long nOldH;
+ do{
+ nOldH = pRoot->Frm().Height();
+ StartAction();
+ ScrollMDI( this, rRect, USHRT_MAX, USHRT_MAX );
+ EndAction();
+ } while( nOldH != pRoot->Frm().Height() && nLoopCnt-- ); //swmod 071108//swmod 071225
+ }
+#if OSL_DEBUG_LEVEL > 1
+ else
+ {
+ OSL_ENSURE( !this, "MakeVisible fuer Drucker wird doch gebraucht?" );
+ }
+
+#endif
+ }
+ }
+}
+
+Window* ViewShell::CareChildWin(ViewShell& rVSh)
+{
+ if(rVSh.pSfxViewShell)
+ {
+ const sal_uInt16 nId = SvxSearchDialogWrapper::GetChildWindowId();
+ SfxViewFrame* pVFrame = rVSh.pSfxViewShell->GetViewFrame();
+ const SfxChildWindow* pChWin = pVFrame->GetChildWindow( nId );
+ Window *pWin = pChWin ? pChWin->GetWindow() : NULL;
+ if ( pWin && pWin->IsVisible() )
+ return pWin;
+ }
+ return NULL;
+}
+
+Point ViewShell::GetPagePos( sal_uInt16 nPageNum ) const
+{
+ return GetLayout()->GetPagePos( nPageNum );
+}
+
+sal_uInt16 ViewShell::GetNumPages()
+{
+ //It can happen that there still no Layout exists due to the
+ //method being called from the Root ctor.
+ return GetLayout() ? GetLayout()->GetPageNum() : 0;
+}
+
+sal_Bool ViewShell::IsDummyPage( sal_uInt16 nPageNum ) const
+{
+ return GetLayout() ? GetLayout()->IsDummyPage( nPageNum ) : 0;
+}
+
+void ViewShell::UpdateFlds(sal_Bool bCloseDB)
+{
+ SET_CURR_SHELL( this );
+
+ sal_Bool bCrsr = ISA(SwCrsrShell);
+ if ( bCrsr )
+ ((SwCrsrShell*)this)->StartAction();
+ else
+ StartAction();
+
+ GetDoc()->UpdateFlds(0, bCloseDB);
+
+ if ( bCrsr )
+ ((SwCrsrShell*)this)->EndAction();
+ else
+ EndAction();
+}
+
+// update all charts, for that exists any table
+void ViewShell::UpdateAllCharts()
+{
+ SET_CURR_SHELL( this );
+ // Start-/EndAction handled in the SwDoc-Method!
+ GetDoc()->UpdateAllCharts();
+}
+
+sal_Bool ViewShell::HasCharts() const
+{
+ sal_Bool bRet = sal_False;
+ const SwStartNode *pStNd;
+ SwNodeIndex aIdx( *GetDoc()->GetNodes().GetEndOfAutotext().
+ StartOfSectionNode(), 1 );
+ while ( 0 != (pStNd = aIdx.GetNode().GetStartNode()) )
+ {
+ aIdx++;
+ const SwOLENode *pNd = aIdx.GetNode().GetOLENode();
+ if( pNd && pNd->GetChartTblName().Len() )
+ {
+ bRet = sal_True;
+ break;
+ }
+ }
+ return bRet;
+}
+
+void ViewShell::LayoutIdle()
+{
+#ifdef TCOVER
+ TCovCall::Idle();
+#endif
+ if( !pOpt->IsIdle() || !GetWin() ||
+ ( Imp()->HasDrawView() && Imp()->GetDrawView()->IsDragObj() ) )
+ return;
+
+
+ ViewShell *pSh = this;
+ do
+ { if ( !pSh->GetWin() )
+ return;
+ pSh = (ViewShell*)pSh->GetNext();
+
+ } while ( pSh != this );
+
+ SET_CURR_SHELL( this );
+
+#if OSL_DEBUG_LEVEL > 1
+ if( pOpt->IsTest5() )
+ return;
+#endif
+
+ {
+ DBG_PROFSTART( LayoutIdle );
+
+ SwSaveSetLRUOfst aSave( *SwTxtFrm::GetTxtCache(),
+ SwTxtFrm::GetTxtCache()->GetCurMax() - 50 );
+ DBG_ASSERT(Imp(), "ViewShell already deleted?");
+ if(!Imp())
+ return;
+ SwLayIdle aIdle( GetLayout(), Imp() );
+ DBG_PROFSTOP( LayoutIdle );
+ }
+}
+
+/*************************************************************************
+|*
+|* DOCUMENT COMPATIBILITY FLAGS
+|*
+*************************************************************************/
+
+void lcl_InvalidateAllCntnt( ViewShell& rSh, sal_uInt8 nInv )
+{
+ sal_Bool bCrsr = rSh.ISA(SwCrsrShell);
+ if ( bCrsr )
+ ((SwCrsrShell&)rSh).StartAction();
+ else
+ rSh.StartAction();
+ rSh.GetLayout()->InvalidateAllCntnt( nInv );
+ if ( bCrsr )
+ ((SwCrsrShell&)rSh).EndAction();
+ else
+ rSh.EndAction();
+
+ rSh.GetDoc()->SetModified();
+}
+
+/** local method to invalidate/re-calculate positions of floating screen
+ objects (Writer fly frame and drawing objects), which are anchored
+ to paragraph or to character.
+
+ #i11860#
+
+ @author OD
+*/
+void lcl_InvalidateAllObjPos( ViewShell &_rSh )
+{
+ const bool bIsCrsrShell = _rSh.ISA(SwCrsrShell);
+ if ( bIsCrsrShell )
+ static_cast<SwCrsrShell&>(_rSh).StartAction();
+ else
+ _rSh.StartAction();
+
+ _rSh.GetLayout()->InvalidateAllObjPos();
+
+ if ( bIsCrsrShell )
+ static_cast<SwCrsrShell&>(_rSh).EndAction();
+ else
+ _rSh.EndAction();
+
+ _rSh.GetDoc()->SetModified();
+}
+
+void ViewShell::SetParaSpaceMax( bool bNew )
+{
+ IDocumentSettingAccess* pIDSA = getIDocumentSettingAccess();
+ if( pIDSA->get(IDocumentSettingAccess::PARA_SPACE_MAX) != bNew )
+ {
+ SwWait aWait( *GetDoc()->GetDocShell(), sal_True );
+ pIDSA->set(IDocumentSettingAccess::PARA_SPACE_MAX, bNew );
+ const sal_uInt8 nInv = INV_PRTAREA | INV_TABLE | INV_SECTION;
+ lcl_InvalidateAllCntnt( *this, nInv );
+ }
+}
+
+void ViewShell::SetParaSpaceMaxAtPages( bool bNew )
+{
+ IDocumentSettingAccess* pIDSA = getIDocumentSettingAccess();
+ if( pIDSA->get(IDocumentSettingAccess::PARA_SPACE_MAX_AT_PAGES) != bNew )
+ {
+ SwWait aWait( *GetDoc()->GetDocShell(), sal_True );
+ pIDSA->set(IDocumentSettingAccess::PARA_SPACE_MAX_AT_PAGES, bNew );
+ const sal_uInt8 nInv = INV_PRTAREA | INV_TABLE | INV_SECTION;
+ lcl_InvalidateAllCntnt( *this, nInv );
+ }
+}
+
+void ViewShell::SetTabCompat( bool bNew )
+{
+ IDocumentSettingAccess* pIDSA = getIDocumentSettingAccess();
+ if( pIDSA->get(IDocumentSettingAccess::TAB_COMPAT) != bNew )
+ {
+ SwWait aWait( *GetDoc()->GetDocShell(), sal_True );
+ pIDSA->set(IDocumentSettingAccess::TAB_COMPAT, bNew );
+ const sal_uInt8 nInv = INV_PRTAREA | INV_SIZE | INV_TABLE | INV_SECTION;
+ lcl_InvalidateAllCntnt( *this, nInv );
+ }
+}
+
+void ViewShell::SetAddExtLeading( bool bNew )
+{
+ IDocumentSettingAccess* pIDSA = getIDocumentSettingAccess();
+ if ( pIDSA->get(IDocumentSettingAccess::ADD_EXT_LEADING) != bNew )
+ {
+ SwWait aWait( *GetDoc()->GetDocShell(), sal_True );
+ pIDSA->set(IDocumentSettingAccess::ADD_EXT_LEADING, bNew );
+ SdrModel* pTmpDrawModel = getIDocumentDrawModelAccess()->GetDrawModel();
+ if ( pTmpDrawModel )
+ pTmpDrawModel->SetAddExtLeading( bNew );
+ const sal_uInt8 nInv = INV_PRTAREA | INV_SIZE | INV_TABLE | INV_SECTION;
+ lcl_InvalidateAllCntnt( *this, nInv );
+ }
+}
+
+void ViewShell::SetUseVirDev( bool bNewVirtual )
+{
+ IDocumentSettingAccess* pIDSA = getIDocumentSettingAccess();
+ if ( pIDSA->get(IDocumentSettingAccess::USE_VIRTUAL_DEVICE) != bNewVirtual )
+ {
+ SwWait aWait( *GetDoc()->GetDocShell(), sal_True );
+ // this sets the flag at the document and calls PrtDataChanged
+ IDocumentDeviceAccess* pIDDA = getIDocumentDeviceAccess();
+ pIDDA->setReferenceDeviceType( bNewVirtual, true );
+ }
+}
+
+void ViewShell::SetAddParaSpacingToTableCells( bool _bAddParaSpacingToTableCells )
+{
+ IDocumentSettingAccess* pIDSA = getIDocumentSettingAccess();
+ if ( pIDSA->get(IDocumentSettingAccess::ADD_PARA_SPACING_TO_TABLE_CELLS) != _bAddParaSpacingToTableCells )
+ {
+ SwWait aWait( *GetDoc()->GetDocShell(), sal_True );
+ pIDSA->set(IDocumentSettingAccess::ADD_PARA_SPACING_TO_TABLE_CELLS, _bAddParaSpacingToTableCells );
+ const sal_uInt8 nInv = INV_PRTAREA;
+ lcl_InvalidateAllCntnt( *this, nInv );
+ }
+}
+
+// #i11859# - control, if former formatting of text lines with
+// proportional line spacing is used or not.
+void ViewShell::SetUseFormerLineSpacing( bool _bUseFormerLineSpacing )
+{
+ IDocumentSettingAccess* pIDSA = getIDocumentSettingAccess();
+ if ( pIDSA->get(IDocumentSettingAccess::OLD_LINE_SPACING) != _bUseFormerLineSpacing )
+ {
+ SwWait aWait( *GetDoc()->GetDocShell(), sal_True );
+ pIDSA->set(IDocumentSettingAccess::OLD_LINE_SPACING, _bUseFormerLineSpacing );
+ const sal_uInt8 nInv = INV_PRTAREA;
+ lcl_InvalidateAllCntnt( *this, nInv );
+ }
+}
+
+// #i11860# - control, if former object positioning is used or not.
+void ViewShell::SetUseFormerObjectPositioning( bool _bUseFormerObjPos )
+{
+ IDocumentSettingAccess* pIDSA = getIDocumentSettingAccess();
+ if ( pIDSA->get(IDocumentSettingAccess::USE_FORMER_OBJECT_POS) != _bUseFormerObjPos )
+ {
+ SwWait aWait( *GetDoc()->GetDocShell(), sal_True );
+ pIDSA->set(IDocumentSettingAccess::USE_FORMER_OBJECT_POS, _bUseFormerObjPos );
+ lcl_InvalidateAllObjPos( *this );
+ }
+}
+
+// #i28701#
+void ViewShell::SetConsiderWrapOnObjPos( bool _bConsiderWrapOnObjPos )
+{
+ IDocumentSettingAccess* pIDSA = getIDocumentSettingAccess();
+ if ( pIDSA->get(IDocumentSettingAccess::CONSIDER_WRAP_ON_OBJECT_POSITION) != _bConsiderWrapOnObjPos )
+ {
+ SwWait aWait( *GetDoc()->GetDocShell(), sal_True );
+ pIDSA->set(IDocumentSettingAccess::CONSIDER_WRAP_ON_OBJECT_POSITION, _bConsiderWrapOnObjPos );
+ lcl_InvalidateAllObjPos( *this );
+ }
+}
+
+void ViewShell::SetUseFormerTextWrapping( bool _bUseFormerTextWrapping )
+{
+ IDocumentSettingAccess* pIDSA = getIDocumentSettingAccess();
+ if ( pIDSA->get(IDocumentSettingAccess::USE_FORMER_TEXT_WRAPPING) != _bUseFormerTextWrapping )
+ {
+ SwWait aWait( *GetDoc()->GetDocShell(), sal_True );
+ pIDSA->set(IDocumentSettingAccess::USE_FORMER_TEXT_WRAPPING, _bUseFormerTextWrapping );
+ const sal_uInt8 nInv = INV_PRTAREA | INV_SIZE | INV_TABLE | INV_SECTION;
+ lcl_InvalidateAllCntnt( *this, nInv );
+ }
+}
+
+// #i45491#
+void ViewShell::SetDoNotJustifyLinesWithManualBreak( bool _bDoNotJustifyLinesWithManualBreak )
+{
+ IDocumentSettingAccess* pIDSA = getIDocumentSettingAccess();
+ if ( pIDSA->get(IDocumentSettingAccess::DO_NOT_JUSTIFY_LINES_WITH_MANUAL_BREAK) != _bDoNotJustifyLinesWithManualBreak )
+ {
+ SwWait aWait( *GetDoc()->GetDocShell(), sal_True );
+ pIDSA->set(IDocumentSettingAccess::DO_NOT_JUSTIFY_LINES_WITH_MANUAL_BREAK, _bDoNotJustifyLinesWithManualBreak );
+ const sal_uInt8 nInv = INV_PRTAREA | INV_SIZE | INV_TABLE | INV_SECTION;
+ lcl_InvalidateAllCntnt( *this, nInv );
+ }
+}
+
+void ViewShell::Reformat()
+{
+ SwWait aWait( *GetDoc()->GetDocShell(), sal_True );
+
+#ifdef FNTMET
+ aFntMetList.Flush();
+#else
+ pFntCache->Flush( );
+#endif
+
+ if( GetLayout()->IsCallbackActionEnabled() )
+ {
+
+ StartAction();
+ GetLayout()->InvalidateAllCntnt( INV_SIZE | INV_POS | INV_PRTAREA );
+ EndAction();
+ }
+}
+
+ void ViewShell::ChgNumberDigits()
+ {
+ SdrModel* pTmpDrawModel = getIDocumentDrawModelAccess()->GetDrawModel();
+ if ( pTmpDrawModel )
+ pTmpDrawModel->ReformatAllTextObjects();
+ Reformat();
+ }
+
+void ViewShell::CalcLayout()
+{
+ SET_CURR_SHELL( this );
+ SwWait aWait( *GetDoc()->GetDocShell(), sal_True );
+
+ SwSaveSetLRUOfst aSaveLRU( *SwTxtFrm::GetTxtCache(),
+ SwTxtFrm::GetTxtCache()->GetCurMax() - 50 );
+
+ const sal_Bool bEndProgress = SfxProgress::GetActiveProgress( GetDoc()->GetDocShell() ) == 0;
+ if ( bEndProgress )
+ {
+ sal_uInt16 nEndPage = GetLayout()->GetPageNum();
+ nEndPage += nEndPage * 10 / 100;
+ ::StartProgress( STR_STATSTR_REFORMAT, 0, nEndPage, GetDoc()->GetDocShell() );
+ }
+
+ SwLayAction aAction( GetLayout(), Imp() );
+ aAction.SetPaint( sal_False );
+ aAction.SetStatBar( sal_True );
+ aAction.SetCalcLayout( sal_True );
+ aAction.SetReschedule( sal_True );
+ GetDoc()->LockExpFlds();
+ aAction.Action();
+ GetDoc()->UnlockExpFlds();
+
+ // The SetNewFldLst() on Doc was stopped and has to be rescheduled
+ // (see flowfrm.cxx, txtfld.cxx)
+ if ( aAction.IsExpFlds() )
+ {
+ aAction.Reset();
+ aAction.SetPaint( sal_False );
+ aAction.SetStatBar( sal_True );
+ aAction.SetReschedule( sal_True );
+
+ SwDocPosUpdate aMsgHnt( 0 );
+ GetDoc()->UpdatePageFlds( &aMsgHnt );
+ GetDoc()->UpdateExpFlds(NULL, true);
+
+ aAction.Action();
+ }
+
+ if ( VisArea().HasArea() )
+ InvalidateWindows( VisArea() );
+ if ( bEndProgress )
+ ::EndProgress( GetDoc()->GetDocShell() );
+}
+
+void ViewShell::SetFirstVisPageInvalid()
+{
+ ViewShell *pSh = this;
+ do
+ { pSh->Imp()->SetFirstVisPageInvalid();
+ pSh = (ViewShell*)pSh->GetNext();
+
+ } while ( pSh != this );
+}
+
+void ViewShell::SizeChgNotify()
+{
+ if ( !pWin )
+ bDocSizeChgd = sal_True;
+ else if( ActionPend() || Imp()->IsCalcLayoutProgress() || bPaintInProgress )
+ {
+ bDocSizeChgd = sal_True;
+
+ if ( !Imp()->IsCalcLayoutProgress() && ISA( SwCrsrShell ) )
+ {
+ const SwFrm *pCnt = ((SwCrsrShell*)this)->GetCurrFrm( sal_False );
+ const SwPageFrm *pPage;
+ if ( pCnt && 0 != (pPage = pCnt->FindPageFrm()) )
+ {
+ sal_uInt16 nVirtNum = pPage->GetVirtPageNum();
+ const SvxNumberType& rNum = pPage->GetPageDesc()->GetNumType();
+ String sDisplay = rNum.GetNumStr( nVirtNum );
+ PageNumNotify( this, pCnt->GetPhyPageNum(), nVirtNum, sDisplay );
+ }
+ }
+ }
+ else
+ {
+ bDocSizeChgd = sal_False;
+ ::SizeNotify( this, GetDocSize() );
+ }
+}
+
+void ViewShell::VisPortChgd( const SwRect &rRect)
+{
+ OSL_ENSURE( GetWin(), "VisPortChgd ohne Window." );
+
+ if ( rRect == VisArea() )
+ return;
+
+#if OSL_DEBUG_LEVEL > 1
+ if ( bInEndAction )
+ {
+ OSL_ENSURE( !this, "Scroll waehrend einer EndAction." );
+ }
+#endif
+
+ const SwFrm *pOldPage = Imp()->GetFirstVisPage();
+
+ const SwRect aPrevArea( VisArea() );
+ const sal_Bool bFull = aPrevArea.IsEmpty();
+ aVisArea = rRect;
+ SetFirstVisPageInvalid();
+
+ // When there is still a PaintRegion and the VisArea has changed,
+ // Then the PaintRegion becomes obsolete. The PaintRegion can have been
+ // produced by RootFrm::Paint.
+ if ( !bInEndAction &&
+ Imp()->GetRegion() && Imp()->GetRegion()->GetOrigin() != VisArea() )
+ Imp()->DelRegion();
+
+ SET_CURR_SHELL( this );
+
+ bool bScrolled = false;
+
+ SwPostItMgr* pPostItMgr = GetPostItMgr();
+
+ if ( bFull )
+ GetWin()->Invalidate();
+ else
+ {
+ const long nXDiff = aPrevArea.Left() - VisArea().Left();
+ const long nYDiff = aPrevArea.Top() - VisArea().Top();
+
+ if( !nXDiff && !GetViewOptions()->getBrowseMode() &&
+ (!Imp()->HasDrawView() || !Imp()->GetDrawView()->IsGridVisible() ) )
+ {
+ const SwPageFrm *pPage = (SwPageFrm*)GetLayout()->Lower(); //swmod 071108//swmod 071225
+ if ( pPage->Frm().Top() > pOldPage->Frm().Top() )
+ pPage = (SwPageFrm*)pOldPage;
+ SwRect aBoth( VisArea() );
+ aBoth.Union( aPrevArea );
+ const SwTwips nBottom = aBoth.Bottom();
+ SwTwips nMinLeft = LONG_MAX;
+ SwTwips nMaxRight= 0;
+
+ const bool bBookMode = GetViewOptions()->IsViewLayoutBookMode();
+
+ while ( pPage && pPage->Frm().Top() <= nBottom )
+ {
+ SwRect aPageRect( pPage->GetBoundRect() );
+ if ( bBookMode )
+ {
+ const SwPageFrm& rFormatPage = static_cast<const SwPageFrm*>(pPage)->GetFormatPage();
+ aPageRect.SSize() = rFormatPage.GetBoundRect().SSize();
+ }
+
+ if ( aPageRect.IsOver( aBoth ) )
+ {
+ SwTwips nPageLeft = 0;
+ SwTwips nPageRight = 0;
+ const sw::sidebarwindows::SidebarPosition aSidebarPos = pPage->SidebarPosition();
+
+ if( aSidebarPos != sw::sidebarwindows::SIDEBAR_NONE )
+ {
+ nPageLeft = aPageRect.Left();
+ nPageRight = aPageRect.Right();
+ }
+
+ if( nPageLeft < nMinLeft )
+ nMinLeft = nPageLeft;
+ if( nPageRight > nMaxRight )
+ nMaxRight = nPageRight;
+ if ( pPage->GetSortedObjs() )
+ {
+ const long nOfst = GetOut()->PixelToLogic(
+ Size(Imp()->GetDrawView()->GetMarkHdlSizePixel()/2,0)).Width();
+ for ( sal_uInt16 i = 0;
+ i < pPage->GetSortedObjs()->Count(); ++i )
+ {
+ SwAnchoredObject* pObj = (*pPage->GetSortedObjs())[i];
+ const Rectangle &rBound = pObj->GetObjRect().SVRect();
+ const SwTwips nL = Max( 0L, rBound.Left() - nOfst );
+ if ( nL < nMinLeft )
+ nMinLeft = nL;
+ if( rBound.Right() + nOfst > nMaxRight )
+ nMaxRight = rBound.Right() + nOfst;
+ }
+ }
+ }
+ pPage = (SwPageFrm*)pPage->GetNext();
+ }
+ Rectangle aRect( aPrevArea.SVRect() );
+ aRect.Left() = nMinLeft;
+ aRect.Right() = nMaxRight;
+ if( VisArea().IsOver( aPrevArea ) && !nLockPaint )
+ {
+ bScrolled = true;
+ aVisArea.Pos() = aPrevArea.Pos();
+ if ( SmoothScroll( nXDiff, nYDiff, &aRect ) )
+ return;
+ aVisArea.Pos() = rRect.Pos();
+ }
+ else
+ GetWin()->Invalidate( aRect );
+ }
+ else if ( !nLockPaint )
+ {
+ if( VisArea().IsOver( aPrevArea ) )
+ {
+ bScrolled = true;
+ aVisArea.Pos() = aPrevArea.Pos();
+ if ( SmoothScroll( nXDiff, nYDiff, 0 ) )
+ return;
+ aVisArea.Pos() = rRect.Pos();
+ }
+ else
+ GetWin()->Invalidate();
+ }
+ }
+
+ Point aPt( VisArea().Pos() );
+ aPt.X() = -aPt.X(); aPt.Y() = -aPt.Y();
+ MapMode aMapMode( GetWin()->GetMapMode() );
+ aMapMode.SetOrigin( aPt );
+ GetWin()->SetMapMode( aMapMode );
+ if ( HasDrawView() )
+ {
+ Imp()->GetDrawView()->VisAreaChanged( GetWin() );
+ Imp()->GetDrawView()->SetActualWin( GetWin() );
+ }
+ GetWin()->Update();
+
+ // #i88070#
+ if ( pPostItMgr )
+ {
+ pPostItMgr->Rescale();
+ pPostItMgr->CalcRects();
+ pPostItMgr->LayoutPostIts();
+ }
+
+ if ( !bScrolled && pPostItMgr && pPostItMgr->HasNotes() && pPostItMgr->ShowNotes() )
+ pPostItMgr->CorrectPositions();
+
+ if( Imp()->IsAccessible() )
+ Imp()->UpdateAccessible();
+
+}
+
+sal_Bool ViewShell::SmoothScroll( long lXDiff, long lYDiff, const Rectangle *pRect )
+{
+ const sal_uLong nColCnt = pOut->GetColorCount();
+ long lMult = 1, lMax = LONG_MAX;
+ if ( nColCnt == 65536 )
+ {
+ lMax = 7000;
+ lMult = 2;
+ }
+ if ( nColCnt == 16777216 )
+ {
+ lMax = 5000;
+ lMult = 6;
+ }
+ else if ( nColCnt == 1 )
+ {
+ lMax = 3000;
+ lMult = 12;
+ }
+
+ // #i75172# isolated static conditions
+ const bool bOnlyYScroll(!lXDiff && Abs(lYDiff) != 0 && Abs(lYDiff) < lMax);
+ const bool bAllowedWithChildWindows(GetWin()->GetWindowClipRegionPixel(WINDOW_GETCLIPREGION_NOCHILDREN|WINDOW_GETCLIPREGION_NULL).IsNull());
+// #i98766# - disable smooth scrolling for Mac port builds
+#ifdef QUARTZ
+ const bool bSmoothScrollAllowed(false);
+ (void) bOnlyYScroll;
+ (void) bAllowedWithChildWindows;
+#else
+ const bool bSmoothScrollAllowed(bOnlyYScroll && bEnableSmooth && GetViewOptions()->IsSmoothScroll() && bAllowedWithChildWindows);
+#endif
+
+ const bool bIAmCursorShell(ISA(SwCrsrShell));
+ (void) bIAmCursorShell;
+
+ // #i75172# with selection on overlay, smooth scroll should be allowed with it
+ const bool bAllowedForSelection(true || (bIAmCursorShell && !((SwCrsrShell*)this)->HasSelection()));
+
+ // #i75172# with cursors on overlay, smooth scroll should be allowed with it
+ const bool bAllowedForMultipleCursors(true || (bIAmCursorShell && ((SwCrsrShell*)this)->GetCrsrCnt() < 2));
+
+ if(bSmoothScrollAllowed && bAllowedForSelection && bAllowedForMultipleCursors)
+ {
+ Imp()->bStopSmooth = sal_False;
+
+ const SwRect aOldVis( VisArea() );
+
+ const Size aPixSz = GetWin()->PixelToLogic(Size(1,1));
+ VirtualDevice *pVout = new VirtualDevice( *GetWin() );
+ pVout->SetLineColor( GetWin()->GetLineColor() );
+ pVout->SetFillColor( GetWin()->GetFillColor() );
+ MapMode aMapMode( GetWin()->GetMapMode() );
+ pVout->SetMapMode( aMapMode );
+ Size aSize( aVisArea.Width()+2*aPixSz.Width(), Abs(lYDiff)+(2*aPixSz.Height()) );
+ if ( pRect )
+ aSize.Width() = Min(aSize.Width(), pRect->GetWidth()+2*aPixSz.Width());
+ if ( pVout->SetOutputSize( aSize ) )
+ {
+ nLockPaint++;
+
+ SwRect aRect( VisArea() );
+ aRect.Height( aSize.Height() );
+ if ( pRect )
+ {
+ aRect.Pos().X() = Max(aRect.Left(),pRect->Left()-aPixSz.Width());
+ aRect.Right( Min(aRect.Right()+2*aPixSz.Width(), pRect->Right()+aPixSz.Width()));
+ }
+ else
+ aRect.SSize().Width() += 2*aPixSz.Width();
+ aRect.Pos().Y() = lYDiff < 0 ? aOldVis.Bottom() - aPixSz.Height()
+ : aRect.Top() - aSize.Height() + aPixSz.Height();
+ aRect.Pos().X() = Max( 0L, aRect.Left()-aPixSz.Width() );
+ aRect.Pos() = GetWin()->PixelToLogic( GetWin()->LogicToPixel( aRect.Pos()));
+ aRect.SSize()= GetWin()->PixelToLogic( GetWin()->LogicToPixel( aRect.SSize()));
+ aVisArea = aRect;
+ const Point aPt( -aRect.Left(), -aRect.Top() );
+ aMapMode.SetOrigin( aPt );
+ pVout->SetMapMode( aMapMode );
+ OutputDevice *pOld = pOut;
+ pOut = pVout;
+
+ {
+ // #i75172# To get a clean repaint, a new ObjectContact is needed here. Without, the
+ // repaint would not be correct since it would use the wrong DrawPage visible region.
+ // This repaint IS about painting something currently outside the visible part (!).
+ // For that purpose, AddWindowToPaintView is used which creates a new SdrPageViewWindow
+ // and all the necessary stuff. It's not cheap, but necessary here. Alone because repaint
+ // target really is NOT the current window.
+ // Also will automatically NOT use PreRendering and overlay (since target is VirtualDevice)
+ if(!HasDrawView())
+ MakeDrawView();
+ SdrView* pDrawView = GetDrawView();
+ pDrawView->AddWindowToPaintView(pVout);
+
+ // clear pWin during DLPrePaint2 to get paint preparation for pOut, but set it again
+ // immediately afterwards. There are many decisions in SW which imply that Printing
+ // is used when pWin == 0 (wrong but widely used).
+ Window* pOldWin = pWin;
+ pWin = 0;
+ DLPrePaint2(Region(aRect.SVRect()));
+ pWin = pOldWin;
+
+ // SW paint stuff
+ PaintDesktop( aRect );
+ ViewShell::bLstAct = sal_True;
+ GetLayout()->Paint( aRect );
+ ViewShell::bLstAct = sal_False;
+
+ // end paint and destroy ObjectContact again
+ DLPostPaint2(true);
+ pDrawView->DeleteWindowFromPaintView(pVout);
+ }
+
+ pOut = pOld;
+ aVisArea = aOldVis;
+
+ long lMaDelta = aPixSz.Height();
+ if ( Abs(lYDiff) > ( aVisArea.Height() / 3 ) )
+ lMaDelta *= 6;
+ else
+ lMaDelta *= 2;
+
+ lMaDelta *= lMult;
+
+ if ( lYDiff < 0 )
+ lMaDelta = -lMaDelta;
+
+ long lDiff = lYDiff;
+ while ( lDiff )
+ {
+ long lScroll;
+ if ( Imp()->bStopSmooth || Abs(lDiff) <= Abs(lMaDelta) )
+ {
+ lScroll = lDiff;
+ lDiff = 0;
+ }
+ else
+ {
+ lScroll = lMaDelta;
+ lDiff -= lMaDelta;
+ }
+
+ const SwRect aTmpOldVis = VisArea();
+ aVisArea.Pos().Y() -= lScroll;
+ aVisArea.Pos() = GetWin()->PixelToLogic( GetWin()->LogicToPixel( VisArea().Pos()));
+ lScroll = aTmpOldVis.Top() - VisArea().Top();
+ if ( pRect )
+ {
+ Rectangle aTmp( aTmpOldVis.SVRect() );
+ aTmp.Left() = pRect->Left();
+ aTmp.Right()= pRect->Right();
+ GetWin()->Scroll( 0, lScroll, aTmp, SCROLL_CHILDREN);
+ }
+ else
+ GetWin()->Scroll( 0, lScroll, SCROLL_CHILDREN );
+
+ const Point aTmpPt( -VisArea().Left(), -VisArea().Top() );
+ MapMode aTmpMapMode( GetWin()->GetMapMode() );
+ aTmpMapMode.SetOrigin( aTmpPt );
+ GetWin()->SetMapMode( aTmpMapMode );
+
+ if ( Imp()->HasDrawView() )
+ Imp()->GetDrawView()->VisAreaChanged( GetWin() );
+
+ SetFirstVisPageInvalid();
+ if ( !Imp()->bStopSmooth )
+ {
+ const bool bScrollDirectionIsUp(lScroll > 0);
+ Imp()->aSmoothRect = VisArea();
+
+ if(bScrollDirectionIsUp)
+ {
+ Imp()->aSmoothRect.Bottom( VisArea().Top() + lScroll + aPixSz.Height());
+ }
+ else
+ {
+ Imp()->aSmoothRect.Top( VisArea().Bottom() + lScroll - aPixSz.Height());
+ }
+
+ Imp()->bSmoothUpdate = sal_True;
+ GetWin()->Update();
+ Imp()->bSmoothUpdate = sal_False;
+
+ if(!Imp()->bStopSmooth)
+ {
+ // start paint on logic base
+ const Rectangle aTargetLogic(Imp()->aSmoothRect.SVRect());
+ DLPrePaint2(Region(aTargetLogic));
+
+ // get target rectangle in discrete pixels
+ OutputDevice& rTargetDevice = mpTargetPaintWindow->GetTargetOutputDevice();
+ const Rectangle aTargetPixel(rTargetDevice.LogicToPixel(aTargetLogic));
+
+ // get source top-left in discrete pixels
+ const Point aSourceTopLeft(pVout->LogicToPixel(aTargetLogic.TopLeft()));
+
+ // switch off MapModes
+ const bool bMapModeWasEnabledDest(rTargetDevice.IsMapModeEnabled());
+ const bool bMapModeWasEnabledSource(pVout->IsMapModeEnabled());
+ rTargetDevice.EnableMapMode(false);
+ pVout->EnableMapMode(false);
+
+ rTargetDevice.DrawOutDev(
+ aTargetPixel.TopLeft(), aTargetPixel.GetSize(), // dest
+ aSourceTopLeft, aTargetPixel.GetSize(), // source
+ *pVout);
+
+ // restore MapModes
+ rTargetDevice.EnableMapMode(bMapModeWasEnabledDest);
+ pVout->EnableMapMode(bMapModeWasEnabledSource);
+
+ // end paint on logoc base
+ DLPostPaint2(true);
+ }
+ else
+ --nLockPaint;
+ }
+ }
+ delete pVout;
+ GetWin()->Update();
+ if ( !Imp()->bStopSmooth )
+ --nLockPaint;
+ SetFirstVisPageInvalid();
+ return sal_True;
+ }
+ delete pVout;
+ }
+
+ aVisArea.Pos().X() -= lXDiff;
+ aVisArea.Pos().Y() -= lYDiff;
+ if ( pRect )
+ GetWin()->Scroll( lXDiff, lYDiff, *pRect, SCROLL_CHILDREN);
+ else
+ GetWin()->Scroll( lXDiff, lYDiff, SCROLL_CHILDREN);
+ return sal_False;
+}
+
+void ViewShell::PaintDesktop( const SwRect &rRect )
+{
+ if ( !GetWin() && !GetOut()->GetConnectMetaFile() )
+ return;
+ sal_Bool bBorderOnly = sal_False;
+ const SwRootFrm *pRoot = GetLayout();//swmod 080305
+ if ( rRect.Top() > pRoot->Frm().Bottom() )
+ {
+ const SwFrm *pPg = pRoot->Lower();
+ while ( pPg && pPg->GetNext() )
+ pPg = pPg->GetNext();
+ if ( !pPg || !pPg->Frm().IsOver( VisArea() ) )
+ bBorderOnly = sal_True;
+ }
+
+ const bool bBookMode = GetViewOptions()->IsViewLayoutBookMode();
+
+ SwRegionRects aRegion( rRect );
+
+ //#i6193: remove sidebar area to avoid flickering
+ const SwPostItMgr* pPostItMgr = GetPostItMgr();
+ const SwTwips nSidebarWidth = pPostItMgr && pPostItMgr->HasNotes() && pPostItMgr->ShowNotes() ?
+ pPostItMgr->GetSidebarWidth() + pPostItMgr->GetSidebarBorderWidth() :
+ 0;
+
+ if ( bBorderOnly )
+ {
+ const SwFrm *pPage =pRoot->Lower(); //swmod 071108//swmod 071225
+ SwRect aLeft( rRect ), aRight( rRect );
+ while ( pPage )
+ {
+ long nTmp = pPage->Frm().Left();
+ if ( nTmp < aLeft.Right() )
+ aLeft.Right( nTmp );
+ nTmp = pPage->Frm().Right();
+ if ( nTmp > aRight.Left() )
+ {
+ aRight.Left( nTmp + nSidebarWidth );
+ }
+ pPage = pPage->GetNext();
+ }
+ aRegion.Remove( 0, aRegion.Count() );
+ if ( aLeft.HasArea() )
+ aRegion.Insert( aLeft, 0 );
+ if ( aRight.HasArea() )
+ aRegion.Insert( aRight, 1 );
+ }
+ else
+ {
+ const SwFrm *pPage = Imp()->GetFirstVisPage();
+ const SwTwips nBottom = rRect.Bottom();
+
+ while ( pPage && aRegion.Count() &&
+ (pPage->Frm().Top() <= nBottom) )
+ {
+ SwRect aPageRect( pPage->Frm() );
+ if ( bBookMode )
+ {
+ const SwPageFrm& rFormatPage = static_cast<const SwPageFrm*>(pPage)->GetFormatPage();
+ aPageRect.SSize() = rFormatPage.Frm().SSize();
+ }
+
+ const bool bSidebarRight =
+ static_cast<const SwPageFrm*>(pPage)->SidebarPosition() == sw::sidebarwindows::SIDEBAR_RIGHT;
+ aPageRect.Pos().X() -= bSidebarRight ? 0 : nSidebarWidth;
+ aPageRect.SSize().Width() += nSidebarWidth;
+
+ if ( aPageRect.IsOver( rRect ) )
+ aRegion -= aPageRect;
+
+ pPage = pPage->GetNext();
+ }
+ }
+ if ( aRegion.Count() )
+ _PaintDesktop( aRegion );
+}
+
+void ViewShell::_PaintDesktop( const SwRegionRects &rRegion )
+{
+ GetOut()->Push( PUSH_FILLCOLOR|PUSH_LINECOLOR );
+ GetOut()->SetLineColor();
+
+ for ( sal_uInt16 i = 0; i < rRegion.Count(); ++i )
+ {
+ const Rectangle aRectangle(rRegion[i].SVRect());
+
+ // #i93170#
+ // Here we have a real Problem. On the one hand we have the buffering for paint
+ // and overlay which needs an embracing pair of DLPrePaint2/DLPostPaint2 calls,
+ // on the other hand the MapMode is not set correctly when this code is executed.
+ // This is done in the users of this method, for each SWpage before painting it.
+ // Since the MapMode is not correct here, the call to DLPostPaint2 will paint
+ // existing FormControls due to the current MapMode.
+ //
+ // There are basically three solutions for this:
+ //
+ // (1) Set the MapMode correct, move the background painting to the users of
+ // this code
+ //
+ // (2) Do no DLPrePaint2/DLPostPaint2 here; no SdrObjects are allowed to lie in
+ // the desktop region. Disadvantage: the desktop will not be part of the
+ // buffers, e.g. overlay. Thus, as soon as overlay will be used over the
+ // desktop, it will not work.
+ //
+ // (3) expand DLPostPaint2 with a flag to signal if FormControl paints shall
+ // be done or not
+ //
+ // Currently, (3) will be the best possible solution. It will keep overlay and
+ // buffering intact and work without MapMode for single pages. In the medium
+ // to long run, (1) will need to be used and the bool bPaintFormLayer needs
+ // to be removed again
+
+ // #i68597# inform Drawinglayer about display change
+ DLPrePaint2(Region(aRectangle));
+
+ // #i75172# needed to move line/Fill color setters into loop since DLPrePaint2
+ // may exchange GetOut(), that's it's purpose. This happens e.g. at print preview.
+ GetOut()->SetFillColor( SwViewOption::GetAppBackgroundColor());
+ GetOut()->SetLineColor();
+ GetOut()->DrawRect(aRectangle);
+
+ DLPostPaint2(false);
+ }
+
+ GetOut()->Pop();
+}
+
+sal_Bool ViewShell::CheckInvalidForPaint( const SwRect &rRect )
+{
+ if ( !GetWin() )
+ return sal_False;
+
+ const SwPageFrm *pPage = Imp()->GetFirstVisPage();
+ const SwTwips nBottom = VisArea().Bottom();
+ const SwTwips nRight = VisArea().Right();
+ sal_Bool bRet = sal_False;
+ while ( !bRet && pPage && !((pPage->Frm().Top() > nBottom) ||
+ (pPage->Frm().Left() > nRight)))
+ {
+ if ( pPage->IsInvalid() || pPage->IsInvalidFly() )
+ bRet = sal_True;
+ pPage = (SwPageFrm*)pPage->GetNext();
+ }
+
+ if ( bRet )
+ {
+ //Start/EndAction wuerden hier leider nix helfen, weil das Paint vom
+ //GUI 'reinkam und somit ein Clipping gesetzt ist gegen das wir nicht
+ //nicht ankommen.
+ //Ergo: Alles selbst machen (siehe ImplEndAction())
+ if ( Imp()->GetRegion() && Imp()->GetRegion()->GetOrigin() != VisArea())
+ Imp()->DelRegion();
+
+ SwLayAction aAction( GetLayout(), Imp() );
+ aAction.SetComplete( sal_False );
+ // We increment the action counter to avoid a recursive call of actions
+ // e.g. from a SwFEShell::RequestObjectResize(..) in bug 95829.
+ // A recursive call of actions is no good idea because the inner action
+ // can't format frames which are locked by the outer action. This may
+ // cause and endless loop.
+ ++nStartAction;
+ aAction.Action();
+ --nStartAction;
+
+ SwRegionRects *pRegion = Imp()->GetRegion();
+ if ( pRegion && aAction.IsBrowseActionStop() )
+ {
+ sal_Bool bStop = sal_True;
+ for ( sal_uInt16 i = 0; i < pRegion->Count(); ++i )
+ {
+ const SwRect &rTmp = (*pRegion)[i];
+ if ( sal_False == (bStop = rTmp.IsOver( VisArea() )) )
+ break;
+ }
+ if ( bStop )
+ {
+ Imp()->DelRegion();
+ pRegion = 0;
+ }
+ }
+
+ if ( pRegion )
+ {
+ //First Invert, then Compress, never the other way round!
+ pRegion->Invert();
+ pRegion->Compress();
+ bRet = sal_False;
+ if ( pRegion->Count() )
+ {
+ SwRegionRects aRegion( rRect );
+ for ( sal_uInt16 i = 0; i < pRegion->Count(); ++i )
+ { const SwRect &rTmp = (*pRegion)[i];
+ if ( !rRect.IsInside( rTmp ) )
+ {
+ InvalidateWindows( rTmp );
+ if ( rTmp.IsOver( VisArea() ) )
+ { aRegion -= rTmp;
+ bRet = sal_True;
+ }
+ }
+ }
+ if ( bRet )
+ {
+ for ( sal_uInt16 i = 0; i < aRegion.Count(); ++i )
+ GetWin()->Invalidate( aRegion[i].SVRect() );
+
+ if ( rRect != VisArea() )
+ {
+ //rRect == VisArea ist der spezialfall fuer neu bzw.
+ //Shift-Ctrl-R, dafuer sollte es nicht notwendig sein
+ //das Rechteck nocheinmal in Dokumentkoordinaten v
+ //vorzuhalten.
+ if ( aInvalidRect.IsEmpty() )
+ aInvalidRect = rRect;
+ else
+ aInvalidRect.Union( rRect );
+ }
+ }
+ }
+ else
+ bRet = sal_False;
+ Imp()->DelRegion();
+ }
+ else
+ bRet = sal_False;
+ }
+ return bRet;
+}
+
+void ViewShell::Paint(const Rectangle &rRect)
+{
+ if ( nLockPaint )
+ {
+ if ( Imp()->bSmoothUpdate )
+ {
+ SwRect aTmp( rRect );
+ if ( !Imp()->aSmoothRect.IsInside( aTmp ) )
+ Imp()->bStopSmooth = sal_True;
+ else
+ {
+ Imp()->aSmoothRect = aTmp;
+ return;
+ }
+ }
+ else
+ return;
+ }
+
+ if ( SwRootFrm::IsInPaint() )
+ {
+ //Waehrend der Ausgabe einer Seite beim Druckvorgang wird das
+ //Paint gepuffert.
+ SwPaintQueue::Add( this, SwRect( rRect ) );
+ return;
+ }
+
+ // mit !nStartAction versuche ich mal mich gegen
+ //fehlerhaften Code an anderen Stellen zu wehren. Hoffentlich fuehrt das
+ //nicht zu Problemen!?
+ if ( bPaintWorks && !nStartAction )
+ {
+ if( GetWin() && GetWin()->IsVisible() )
+ {
+ SwRect aRect( rRect );
+ if ( bPaintInProgress ) //Schutz gegen doppelte Paints!
+ {
+ GetWin()->Invalidate( rRect );
+ return;
+ }
+
+ bPaintInProgress = sal_True;
+ SET_CURR_SHELL( this );
+ SwRootFrm::SetNoVirDev( sal_True );
+
+ //Wir wollen nicht staendig hin und her Clippen, wir verlassen
+ //uns darauf, das sich alle auf das Rechteck beschraeken und
+ //brauchen das Clipping hier nur einmalig einkalkulieren. Das
+ //ClipRect wird hier einmal entfernt und nicht Restauriert, denn
+ //von aussen braucht es sowieso keiner mehr.
+ //Nicht wenn wir ein MetaFile aufzeichnen.
+ if( !GetOut()->GetConnectMetaFile() && GetOut()->IsClipRegion())
+ GetOut()->SetClipRegion();
+
+ if ( IsPreView() )
+ {
+ //Falls sinnvoll gleich das alte InvalidRect verarbeiten bzw.
+ //vernichten.
+ if ( aRect.IsInside( aInvalidRect ) )
+ ResetInvalidRect();
+ ViewShell::bLstAct = sal_True;
+ GetLayout()->Paint( aRect );
+ ViewShell::bLstAct = sal_False;
+ }
+ else
+ {
+ if ( !CheckInvalidForPaint( aRect ) )
+ {
+ // #i101192# start Pre/PostPaint encapsulation to avoid screen blinking
+ const Region aRepaintRegion(aRect.SVRect());
+ DLPrePaint2(aRepaintRegion);
+
+ PaintDesktop( aRect );
+
+ if ( aRect.IsInside( aInvalidRect ) )
+ ResetInvalidRect();
+ ViewShell::bLstAct = sal_True;
+ GetLayout()->Paint( aRect );
+ ViewShell::bLstAct = sal_False;
+ // #i101192# end Pre/PostPaint encapsulation
+ DLPostPaint2(true);
+
+ }
+ }
+ SwRootFrm::SetNoVirDev( sal_False );
+ bPaintInProgress = sal_False;
+ UISizeNotify();
+ }
+ }
+ else
+ {
+ if ( aInvalidRect.IsEmpty() )
+ aInvalidRect = SwRect( rRect );
+ else
+ aInvalidRect.Union( SwRect( rRect ) );
+
+ if ( bInEndAction && GetWin() )
+ {
+ Region aRegion( GetWin()->GetPaintRegion() );
+ RegionHandle hHdl( aRegion.BeginEnumRects() );
+ Rectangle aRect;
+ while ( aRegion.GetNextEnumRect( hHdl, aRect ) )
+ Imp()->AddPaintRect( aRect );
+ aRegion.EndEnumRects( hHdl );
+ }
+ else if ( SfxProgress::GetActiveProgress( GetDoc()->GetDocShell() ) &&
+ GetOut() == GetWin() )
+ {
+ // #i68597#
+ const Region aDLRegion(rRect);
+ DLPrePaint2(aDLRegion);
+
+ pOut->Push( PUSH_FILLCOLOR|PUSH_LINECOLOR );
+ pOut->SetFillColor( Imp()->GetRetoucheColor() );
+ pOut->SetLineColor();
+ pOut->DrawRect( rRect );
+ pOut->Pop();
+
+ // #i68597#
+ DLPostPaint2(true);
+ }
+ }
+}
+
+void ViewShell::SetBrowseBorder( const Size& rNew )
+{
+ if( rNew != aBrowseBorder )
+ {
+ aBrowseBorder = rNew;
+ if ( aVisArea.HasArea() )
+ CheckBrowseView( sal_False );
+ }
+}
+
+const Size& ViewShell::GetBrowseBorder() const
+{
+ return aBrowseBorder;
+}
+
+sal_Int32 ViewShell::GetBrowseWidth() const
+{
+ const SwPostItMgr* pPostItMgr = GetPostItMgr();
+ if ( pPostItMgr && pPostItMgr->HasNotes() && pPostItMgr->ShowNotes() )
+ {
+ Size aBorder( aBrowseBorder );
+ aBorder.Width() += aBrowseBorder.Width();
+ aBorder.Width() += pPostItMgr->GetSidebarWidth(true) + pPostItMgr->GetSidebarBorderWidth(true);
+ return aVisArea.Width() - GetOut()->PixelToLogic(aBorder).Width();
+ }
+ else
+ return aVisArea.Width() - 2 * GetOut()->PixelToLogic(aBrowseBorder).Width();
+}
+
+void ViewShell::CheckBrowseView( sal_Bool bBrowseChgd )
+{
+ if ( !bBrowseChgd && !GetViewOptions()->getBrowseMode() )
+ return;
+
+ SET_CURR_SHELL( this );
+
+ OSL_ENSURE( GetLayout(), "Layout not ready" );
+
+ // Wenn das Layout noch nicht einmal eine Hoehe hat,
+ // ist sowieso nichts formatiert.
+ // Dann eruebrigt sich die Invalidierung
+ // Falsch, z.B. beim Anlegen einer neuen View wird der Inhalt eingef?gt
+ // und formatiert (trotz einer leeren VisArea). Hier muessen deshalb
+ // die Seiten zur Formatierung angeregt werden.
+ if( !GetLayout()->Frm().Height() )
+ {
+ SwFrm* pPage = GetLayout()->Lower();
+ while( pPage )
+ {
+ pPage->_InvalidateSize();
+ pPage = pPage->GetNext();
+ }
+ return;
+ }
+
+ LockPaint();
+ StartAction();
+
+ SwPageFrm *pPg = (SwPageFrm*)GetLayout()->Lower();
+ do
+ { pPg->InvalidateSize();
+ pPg->_InvalidatePrt();
+ pPg->InvaPercentLowers();
+ if ( bBrowseChgd )
+ {
+ pPg->PrepareHeader();
+ pPg->PrepareFooter();
+ }
+ pPg = (SwPageFrm*)pPg->GetNext();
+ } while ( pPg );
+
+ // Wenn sich die Groessenverhaeltnise im BrowseModus aendern,
+ // muss die Position und PrtArea der Cntnt- und Tab-Frames invalidiert werden.
+ sal_uInt8 nInv = INV_PRTAREA | INV_TABLE | INV_POS;
+ // Beim BrowseModus-Wechsel benoetigen die CntntFrms
+ // wg. der Drucker/Bildschirmformatierung eine Size-Invalidierung
+ if( bBrowseChgd )
+ nInv |= INV_SIZE | INV_DIRECTION;
+
+ GetLayout()->InvalidateAllCntnt( nInv );
+
+ SwFrm::CheckPageDescs( (SwPageFrm*)GetLayout()->Lower() );
+
+ EndAction();
+ UnlockPaint();
+}
+
+SwRootFrm *ViewShell::GetLayout() const
+{
+ return pLayout.get(); //swmod 080116
+}
+/***********************************************************************/
+
+OutputDevice& ViewShell::GetRefDev() const
+{
+ OutputDevice* pTmpOut = 0;
+ if ( GetWin() &&
+ GetViewOptions()->getBrowseMode() &&
+ !GetViewOptions()->IsPrtFormat() )
+ pTmpOut = GetWin();
+ else if ( 0 != mpTmpRef )
+ pTmpOut = mpTmpRef;
+ else
+ pTmpOut = GetDoc()->getReferenceDevice( true );
+
+ return *pTmpOut;
+}
+
+const SwNodes& ViewShell::GetNodes() const
+{
+ return pDoc->GetNodes();
+}
+
+
+void ViewShell::DrawSelChanged()
+{
+}
+
+
+Size ViewShell::GetDocSize() const
+{
+ Size aSz;
+ const SwRootFrm* pRoot = GetLayout();
+ if( pRoot )
+ aSz = pRoot->Frm().SSize();
+
+ return aSz;
+}
+
+
+SfxItemPool& ViewShell::GetAttrPool()
+{
+ return GetDoc()->GetAttrPool();
+}
+
+void ViewShell::ApplyViewOptions( const SwViewOption &rOpt )
+{
+
+ ViewShell *pSh = this;
+ do
+ { pSh->StartAction();
+ pSh = (ViewShell*)pSh->GetNext();
+ } while ( pSh != this );
+
+ ImplApplyViewOptions( rOpt );
+
+ // With one layout per view it is not longer necessary
+ // to sync these "layout related" view options
+ // But as long as we have to disable "multiple layout"
+ pSh = (ViewShell*)this->GetNext();
+ while ( pSh != this )
+ {
+ SwViewOption aOpt( *pSh->GetViewOptions() );
+ aOpt.SetFldName( rOpt.IsFldName() );
+ aOpt.SetShowHiddenField( rOpt.IsShowHiddenField() );
+ aOpt.SetShowHiddenPara( rOpt.IsShowHiddenPara() );
+ aOpt.SetShowHiddenChar( rOpt.IsShowHiddenChar() );
+ aOpt.SetViewLayoutBookMode( rOpt.IsViewLayoutBookMode() );
+ aOpt.SetViewLayoutColumns( rOpt.GetViewLayoutColumns() );
+ aOpt.SetPostIts(rOpt.IsPostIts());
+ if ( !(aOpt == *pSh->GetViewOptions()) )
+ pSh->ImplApplyViewOptions( aOpt );
+ pSh = (ViewShell*)pSh->GetNext();
+ }
+ // End of disabled multiple window
+
+ pSh = this;
+ do
+ { pSh->EndAction();
+ pSh = (ViewShell*)pSh->GetNext();
+ } while ( pSh != this );
+
+}
+
+void ViewShell::ImplApplyViewOptions( const SwViewOption &rOpt )
+{
+ if (*pOpt == rOpt)
+ return;
+
+ Window *pMyWin = GetWin();
+ if( !pMyWin )
+ {
+ OSL_ENSURE( pMyWin, "ViewShell::ApplyViewOptions: no window" );
+ return;
+ }
+
+ SET_CURR_SHELL( this );
+
+ sal_Bool bReformat = sal_False;
+
+ if( pOpt->IsShowHiddenField() != rOpt.IsShowHiddenField() )
+ {
+ ((SwHiddenTxtFieldType*)pDoc->GetSysFldType( RES_HIDDENTXTFLD ))->
+ SetHiddenFlag( !rOpt.IsShowHiddenField() );
+ bReformat = sal_True;
+ }
+ if ( pOpt->IsShowHiddenPara() != rOpt.IsShowHiddenPara() )
+ {
+ SwHiddenParaFieldType* pFldType = (SwHiddenParaFieldType*)GetDoc()->
+ GetSysFldType(RES_HIDDENPARAFLD);
+ if( pFldType && pFldType->GetDepends() )
+ {
+ SwMsgPoolItem aHnt( RES_HIDDENPARA_PRINT );
+ pFldType->ModifyNotification( &aHnt, 0);
+ }
+ bReformat = sal_True;
+ }
+ if ( !bReformat && pOpt->IsShowHiddenChar() != rOpt.IsShowHiddenChar() )
+ {
+ bReformat = GetDoc()->ContainsHiddenChars();
+ }
+
+ // bReformat wird sal_True, wenn ...
+ // - Feldnamen anzeigen oder nicht ...
+ // ( - SwEndPortion muessen _nicht_ mehr generiert werden. )
+ // - Das Window ist natuerlich was ganz anderes als der Drucker...
+ bReformat = bReformat || pOpt->IsFldName() != rOpt.IsFldName();
+
+ // Der Mapmode wird veraendert, Minima/Maxima werden von der UI beachtet
+ if( pOpt->GetZoom() != rOpt.GetZoom() && !IsPreView() )
+ {
+ MapMode aMode( pMyWin->GetMapMode() );
+ Fraction aNewFactor( rOpt.GetZoom(), 100 );
+ aMode.SetScaleX( aNewFactor );
+ aMode.SetScaleY( aNewFactor );
+ pMyWin->SetMapMode( aMode );
+ // Wenn kein ReferenzDevice (Drucker) zum Formatieren benutzt wird,
+ // sondern der Bildschirm, muss bei Zoomfaktoraenderung neu formatiert
+ // werden.
+ if( pOpt->getBrowseMode() )
+ bReformat = sal_True;
+ }
+
+ bool bBrowseModeChanged = false;
+ if( pOpt->getBrowseMode() != rOpt.getBrowseMode() )
+ {
+ bBrowseModeChanged = true;
+ bReformat = sal_True;
+ }
+ else if( pOpt->getBrowseMode() && pOpt->IsPrtFormat() != rOpt.IsPrtFormat() )
+ bReformat = sal_True;
+
+ if ( HasDrawView() || rOpt.IsGridVisible() )
+ {
+ if ( !HasDrawView() )
+ MakeDrawView();
+
+ SwDrawView *pDView = Imp()->GetDrawView();
+ if ( pDView->IsDragStripes() != rOpt.IsCrossHair() )
+ pDView->SetDragStripes( rOpt.IsCrossHair() );
+
+ if ( pDView->IsGridSnap() != rOpt.IsSnap() )
+ pDView->SetGridSnap( rOpt.IsSnap() );
+
+ if ( pDView->IsGridVisible() != rOpt.IsGridVisible() )
+ pDView->SetGridVisible( rOpt.IsGridVisible() );
+
+ const Size &rSz = rOpt.GetSnapSize();
+ pDView->SetGridCoarse( rSz );
+
+ const Size aFSize
+ ( rSz.Width() ? rSz.Width() / (rOpt.GetDivisionX()+1) : 0,
+ rSz.Height()? rSz.Height()/ (rOpt.GetDivisionY()+1) : 0);
+ pDView->SetGridFine( aFSize );
+ Fraction aSnGrWdtX(rSz.Width(), rOpt.GetDivisionX() + 1);
+ Fraction aSnGrWdtY(rSz.Height(), rOpt.GetDivisionY() + 1);
+ pDView->SetSnapGridWidth( aSnGrWdtX, aSnGrWdtY );
+
+ if ( pOpt->IsSolidMarkHdl() != rOpt.IsSolidMarkHdl() )
+ pDView->SetSolidMarkHdl( rOpt.IsSolidMarkHdl() );
+
+ // it's a JOE interface !
+ if ( pOpt->IsBigMarkHdl() != rOpt.IsBigMarkHdl() )
+ pDView->SetMarkHdlSizePixel(rOpt.IsBigMarkHdl() ? 9 : 7);
+ }
+
+ sal_Bool bOnlineSpellChgd = pOpt->IsOnlineSpell() != rOpt.IsOnlineSpell();
+
+ *pOpt = rOpt;
+ pOpt->SetUIOptions(rOpt);
+
+ pDoc->set(IDocumentSettingAccess::HTML_MODE, 0 != ::GetHtmlMode(pDoc->GetDocShell()));
+
+ if( bBrowseModeChanged )
+ {
+ // --> FME 2005-03-16 #i44963# Good occasion to check if page sizes in
+ // page descriptions are still set to (LONG_MAX, LONG_MAX) (html import)
+ pDoc->CheckDefaultPageFmt();
+ // <--
+ CheckBrowseView( sal_True );
+ }
+
+ pMyWin->Invalidate();
+ if ( bReformat )
+ {
+ // Es hilft alles nichts, wir muessen an alle CntntFrms ein
+ // Prepare verschicken, wir formatieren neu:
+ StartAction();
+ Reformat();
+ EndAction();
+ }
+
+ if( bOnlineSpellChgd )
+ {
+ ViewShell *pSh = (ViewShell*)this->GetNext();
+ sal_Bool bOnlineSpl = rOpt.IsOnlineSpell();
+ while( pSh != this )
+ { pSh->pOpt->SetOnlineSpell( bOnlineSpl );
+ Window *pTmpWin = pSh->GetWin();
+ if( pTmpWin )
+ pTmpWin->Invalidate();
+ pSh = (ViewShell*)pSh->GetNext();
+ }
+ }
+
+}
+
+void ViewShell::SetUIOptions( const SwViewOption &rOpt )
+{
+ pOpt->SetUIOptions(rOpt);
+ //the API-Flag of the view options is set but never reset
+ //it is required to set scroll bars in readonly documents
+ if(rOpt.IsStarOneSetting())
+ pOpt->SetStarOneSetting(sal_True);
+
+ pOpt->SetSymbolFont(rOpt.GetSymbolFont());
+}
+
+void ViewShell::SetReadonlyOption(sal_Bool bSet)
+{
+ if( bSet != pOpt->IsReadonly() )
+ {
+ pOpt->SetReadonly( sal_False );
+
+ sal_Bool bReformat = pOpt->IsFldName();
+
+ pOpt->SetReadonly( bSet );
+
+ if( bReformat )
+ {
+ StartAction();
+ Reformat();
+ if ( GetWin() )
+ GetWin()->Invalidate();
+ EndAction();
+ }
+ else if ( GetWin() )
+ GetWin()->Invalidate();
+ if( Imp()->IsAccessible() )
+ Imp()->InvalidateAccessibleEditableState( sal_False );
+ }
+}
+
+void ViewShell::SetPDFExportOption(sal_Bool bSet)
+{
+ if( bSet != pOpt->IsPDFExport() )
+ {
+ if( bSet && pOpt->getBrowseMode() )
+ pOpt->SetPrtFormat( sal_True );
+ pOpt->SetPDFExport(bSet);
+ }
+}
+
+void ViewShell::SetReadonlySelectionOption(sal_Bool bSet)
+{
+ if( bSet != pOpt->IsSelectionInReadonly() )
+ {
+ pOpt->SetSelectionInReadonly(bSet);
+ }
+}
+
+void ViewShell::SetPrtFormatOption( sal_Bool bSet )
+{
+ pOpt->SetPrtFormat( bSet );
+}
+
+void ViewShell::UISizeNotify()
+{
+ if ( bDocSizeChgd )
+ {
+ bDocSizeChgd = sal_False;
+ sal_Bool bOld = bInSizeNotify;
+ bInSizeNotify = sal_True;
+ ::SizeNotify( this, GetDocSize() );
+ bInSizeNotify = bOld;
+ }
+}
+
+
+void ViewShell::SetRestoreActions(sal_uInt16 nSet)
+{
+ DBG_ASSERT(!GetRestoreActions()||!nSet, "mehrfaches Restore der Actions ?");
+ Imp()->SetRestoreActions(nSet);
+}
+sal_uInt16 ViewShell::GetRestoreActions() const
+{
+ return Imp()->GetRestoreActions();
+}
+
+sal_Bool ViewShell::IsNewLayout() const
+{
+ return GetLayout()->IsNewLayout();
+}
+
+uno::Reference< ::com::sun::star::accessibility::XAccessible > ViewShell::CreateAccessible()
+{
+ uno::Reference< ::com::sun::star::accessibility::XAccessible > xAcc;
+
+ // We require a layout and an XModel to be accessible.
+ OSL_ENSURE( pLayout, "no layout, no access" );
+ OSL_ENSURE( GetWin(), "no window, no access" );
+
+ if( pDoc->GetCurrentViewShell() && GetWin() ) //swmod 071108
+ xAcc = Imp()->GetAccessibleMap().GetDocumentView();
+
+ return xAcc;
+}
+
+uno::Reference< ::com::sun::star::accessibility::XAccessible >
+ViewShell::CreateAccessiblePreview()
+{
+ DBG_ASSERT( IsPreView(),
+ "Can't create accessible preview for non-preview ViewShell" );
+
+ // We require a layout and an XModel to be accessible.
+ OSL_ENSURE( pLayout, "no layout, no access" );
+ OSL_ENSURE( GetWin(), "no window, no access" );
+
+ if ( IsPreView() && GetLayout()&& GetWin() )
+ {
+ return Imp()->GetAccessibleMap().GetDocumentPreview(
+ PagePreviewLayout()->maPrevwPages,
+ GetWin()->GetMapMode().GetScaleX(),
+ GetLayout()->GetPageByPageNum( PagePreviewLayout()->mnSelectedPageNum ),
+ PagePreviewLayout()->maWinSize ); //swmod 080305
+ }
+ return NULL;
+}
+
+void ViewShell::InvalidateAccessibleFocus()
+{
+ if( Imp()->IsAccessible() )
+ Imp()->GetAccessibleMap().InvalidateFocus();
+}
+
+// #i27138# invalidate CONTENT_FLOWS_FROM/_TO relation for paragraphs
+void ViewShell::InvalidateAccessibleParaFlowRelation( const SwTxtFrm* _pFromTxtFrm,
+ const SwTxtFrm* _pToTxtFrm )
+{
+ if ( GetLayout() && GetLayout()->IsAnyShellAccessible() )
+ {
+ Imp()->_InvalidateAccessibleParaFlowRelation( _pFromTxtFrm, _pToTxtFrm );
+ }
+}
+
+// #i27301# invalidate text selection for paragraphs
+void ViewShell::InvalidateAccessibleParaTextSelection()
+{
+ if ( GetLayout() && GetLayout()->IsAnyShellAccessible() )
+ {
+ Imp()->_InvalidateAccessibleParaTextSelection();
+ }
+}
+
+// #i88069# invalidate attributes for paragraphs
+void ViewShell::InvalidateAccessibleParaAttrs( const SwTxtFrm& rTxtFrm )
+{
+ if ( GetLayout() && GetLayout()->IsAnyShellAccessible() )
+ {
+ Imp()->_InvalidateAccessibleParaAttrs( rTxtFrm );
+ }
+}
+
+SwAccessibleMap* ViewShell::GetAccessibleMap()
+{
+ if ( Imp()->IsAccessible() )
+ {
+ return &(Imp()->GetAccessibleMap());
+ }
+
+ return 0;
+}
+void ViewShell::ApplyAccessiblityOptions(SvtAccessibilityOptions& rAccessibilityOptions)
+{
+ if(pOpt->IsPagePreview() && !rAccessibilityOptions.GetIsForPagePreviews())
+ {
+ pAccOptions->SetAlwaysAutoColor(sal_False);
+ pAccOptions->SetStopAnimatedGraphics(sal_False);
+ pAccOptions->SetStopAnimatedText(sal_False);
+ }
+ else
+ {
+ pAccOptions->SetAlwaysAutoColor(rAccessibilityOptions.GetIsAutomaticFontColor());
+ pAccOptions->SetStopAnimatedGraphics(! rAccessibilityOptions.GetIsAllowAnimatedGraphics());
+ pAccOptions->SetStopAnimatedText(! rAccessibilityOptions.GetIsAllowAnimatedText());
+
+ // Formular view
+ // Always set this option, not only if document is read-only:
+ pOpt->SetSelectionInReadonly(rAccessibilityOptions.IsSelectionInReadonly());
+ }
+}
+
+ShellResource* ViewShell::GetShellRes()
+{
+ return pShellRes;
+}
+
+void ViewShell::SetCareWin( Window* pNew )
+{
+ pCareWindow = pNew;
+}
+
+sal_uInt16 ViewShell::GetPageCount() const
+{
+ return GetLayout() ? GetLayout()->GetPageNum() : 1;
+}
+
+const Size ViewShell::GetPageSize( sal_uInt16 nPageNum, bool bSkipEmptyPages ) const
+{
+ Size aSize;
+ const SwRootFrm* pTmpRoot = GetLayout();
+ if( pTmpRoot && nPageNum )
+ {
+ const SwPageFrm* pPage = static_cast<const SwPageFrm*>
+ (pTmpRoot->Lower());
+
+ while( --nPageNum && pPage->GetNext() )
+ pPage = static_cast<const SwPageFrm*>( pPage->GetNext() );
+
+ if( !bSkipEmptyPages && pPage->IsEmptyPage() && pPage->GetNext() )
+ pPage = static_cast<const SwPageFrm*>( pPage->GetNext() );
+
+ aSize = pPage->Frm().SSize();
+ }
+ return aSize;
+}
+
+// #i12836# enhanced pdf export
+sal_Int32 ViewShell::GetPageNumAndSetOffsetForPDF( OutputDevice& rOut, const SwRect& rRect ) const
+{
+ OSL_ENSURE( GetLayout(), "GetPageNumAndSetOffsetForPDF assumes presence of layout" );
+
+ sal_Int32 nRet = -1;
+
+ // #i40059# Position out of bounds
+ SwRect aRect( rRect );
+ aRect.Pos().X() = Max( aRect.Left(), GetLayout()->Frm().Left() );
+
+ const SwPageFrm* pPage = GetLayout()->GetPageAtPos( aRect.Center() );
+ if ( pPage )
+ {
+ OSL_ENSURE( pPage, "GetPageNumAndSetOffsetForPDF: No page found" );
+
+ Point aOffset( pPage->Frm().Pos() );
+ aOffset.X() = -aOffset.X();
+ aOffset.Y() = -aOffset.Y();
+
+ MapMode aMapMode( rOut.GetMapMode() );
+ aMapMode.SetOrigin( aOffset );
+ rOut.SetMapMode( aMapMode );
+
+ nRet = pPage->GetPhyPageNum() - 1;
+ }
+
+ return nRet;
+}
+
+const BitmapEx& ViewShell::GetReplacementBitmap( bool bIsErrorState )
+{
+ BitmapEx** ppRet;
+ sal_uInt16 nResId = 0;
+ if( bIsErrorState )
+ {
+ ppRet = &pErrorBmp;
+ nResId = RID_GRAPHIC_ERRORBMP;
+ }
+ else
+ {
+ ppRet = &pReplaceBmp;
+ nResId = RID_GRAPHIC_REPLACEBMP;
+ }
+
+ if( !*ppRet )
+ {
+ *ppRet = new BitmapEx( SW_RES( nResId ) );
+ }
+ return **ppRet;
+}
+
+void ViewShell::DeleteReplacementBitmaps()
+{
+ DELETEZ( pErrorBmp );
+ DELETEZ( pReplaceBmp );
+}
+
+SwPostItMgr* ViewShell::GetPostItMgr()
+{
+ SwView* pView = GetDoc()->GetDocShell() ? GetDoc()->GetDocShell()->GetView() : 0;
+ if ( pView )
+ return pView->GetPostItMgr();
+
+ return 0;
+}
+
+/*
+ * Document Interface Access
+ */
+const IDocumentSettingAccess* ViewShell::getIDocumentSettingAccess() const { return pDoc; }
+IDocumentSettingAccess* ViewShell::getIDocumentSettingAccess() { return pDoc; }
+const IDocumentDeviceAccess* ViewShell::getIDocumentDeviceAccess() const { return pDoc; }
+IDocumentDeviceAccess* ViewShell::getIDocumentDeviceAccess() { return pDoc; }
+const IDocumentMarkAccess* ViewShell::getIDocumentMarkAccess() const { return pDoc->getIDocumentMarkAccess(); }
+IDocumentMarkAccess* ViewShell::getIDocumentMarkAccess() { return pDoc->getIDocumentMarkAccess(); }
+const IDocumentDrawModelAccess* ViewShell::getIDocumentDrawModelAccess() const { return pDoc; }
+IDocumentDrawModelAccess* ViewShell::getIDocumentDrawModelAccess() { return pDoc; }
+const IDocumentRedlineAccess* ViewShell::getIDocumentRedlineAccess() const { return pDoc; }
+IDocumentRedlineAccess* ViewShell::getIDocumentRedlineAccess() { return pDoc; }
+const IDocumentLayoutAccess* ViewShell::getIDocumentLayoutAccess() const { return pDoc; }
+IDocumentLayoutAccess* ViewShell::getIDocumentLayoutAccess() { return pDoc; }
+const IDocumentFieldsAccess* ViewShell::getIDocumentFieldsAccess() const { return pDoc; }
+IDocumentContentOperations* ViewShell::getIDocumentContentOperations() { return pDoc; }
+IDocumentStylePoolAccess* ViewShell::getIDocumentStylePoolAccess() { return pDoc; }
+const IDocumentStatistics* ViewShell::getIDocumentStatistics() const { return pDoc; }
+
+IDocumentUndoRedo & ViewShell::GetIDocumentUndoRedo()
+{ return pDoc->GetIDocumentUndoRedo(); }
+IDocumentUndoRedo const& ViewShell::GetIDocumentUndoRedo() const
+{ return pDoc->GetIDocumentUndoRedo(); }
+
+// #i83479#
+const IDocumentListItems* ViewShell::getIDocumentListItemsAccess() const
+{
+ return pDoc;
+}
+const IDocumentOutlineNodes* ViewShell::getIDocumentOutlineNodesAccess() const
+{
+ return pDoc;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/view/vnew.cxx b/sw/source/core/view/vnew.cxx
new file mode 100644
index 000000000000..668a9028d36a
--- /dev/null
+++ b/sw/source/core/view/vnew.cxx
@@ -0,0 +1,369 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+
+#include <sfx2/printer.hxx>
+#include <rtl/logfile.hxx>
+#include <doc.hxx>
+#include <IDocumentUndoRedo.hxx>
+#include <docsh.hxx>
+#include <viewsh.hxx>
+#include <rootfrm.hxx>
+#include <viewimp.hxx>
+#include <viewopt.hxx>
+#include <txtfrm.hxx>
+#include <notxtfrm.hxx>
+#include <fntcache.hxx>
+#include <docufld.hxx>
+#include <ptqueue.hxx>
+#include <dview.hxx>
+#include <ndgrf.hxx>
+#include <ndindex.hxx>
+#include <accessibilityoptions.hxx>
+#include <switerator.hxx>
+void ViewShell::Init( const SwViewOption *pNewOpt )
+{
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLog, "SW", "JP93722", "ViewShell::Init" );
+
+ bDocSizeChgd = sal_False;
+
+ pFntCache->Flush( );
+
+ if( !pOpt )
+ {
+ pOpt = new SwViewOption;
+
+ if( pNewOpt )
+ {
+ *pOpt = *pNewOpt;
+ if( GetWin() && 100 != pOpt->GetZoom() )
+ {
+ MapMode aMode( pWin->GetMapMode() );
+ const Fraction aNewFactor( pOpt->GetZoom(), 100 );
+ aMode.SetScaleX( aNewFactor );
+ aMode.SetScaleY( aNewFactor );
+ pWin->SetMapMode( aMode );
+ }
+ }
+ }
+
+ SwDocShell* pDShell = pDoc->GetDocShell();
+ pDoc->set(IDocumentSettingAccess::HTML_MODE, 0 != ::GetHtmlMode( pDShell ) );
+
+ if( pDShell && pDShell->IsReadOnly() )
+ pOpt->SetReadonly( sal_True );
+
+ RTL_LOGFILE_CONTEXT_TRACE( aLog, "View::Init - before InitPrt" );
+
+ // #i82967#
+ OutputDevice* pPDFOut = 0;
+
+ if ( pOut && pOut->GetPDFWriter() )
+ pPDFOut = pOut;
+ // #i41075# Only setup the printer if we need one:
+ const bool bBrowseMode = pOpt->getBrowseMode();
+ if( pPDFOut )
+ InitPrt( pPDFOut );
+ // #i44963# Good occasion to check if page sizes in page descriptions
+ // are still set to (LONG_MAX, LONG_MAX) (html import)
+ if ( !bBrowseMode )
+ {
+ pDoc->CheckDefaultPageFmt();
+ }
+
+ RTL_LOGFILE_CONTEXT_TRACE( aLog, "View::Init - after InitPrt" );
+
+ if( GetWin() )
+ {
+ pOpt->Init( GetWin() );
+ GetWin()->SetFillColor();
+ GetWin()->SetBackground();
+ GetWin()->SetLineColor();
+ }
+
+ // Create a new layout, if there is no one available
+ if( !pLayout )
+ {
+ // Here's the code which disables the usage of "multiple" layouts at the moment
+ // If the problems with controls and groups objects are solved,
+ // this code can be removed...
+ ViewShell *pCurrShell = GetDoc()->GetCurrentViewShell();
+ if( pCurrShell )
+ pLayout = pCurrShell->pLayout;
+ // end of "disable multiple layouts"
+ if( !pLayout )
+ {
+ // switched to two step construction because creating the layout in SwRootFrm needs a valid pLayout set
+ pLayout = SwRootFrmPtr(new SwRootFrm( pDoc->GetDfltFrmFmt(), this ));//swmod081016
+ pLayout->Init( pDoc->GetDfltFrmFmt() );
+ }
+ }
+ SizeChgNotify(); //swmod 071108
+
+ // #i31958#
+ // XForms mode: initialize XForms mode, based on design mode (draw view)
+ // MakeDrawView() requires layout
+ if( GetDoc()->isXForms() )
+ {
+ if( ! HasDrawView() )
+ MakeDrawView();
+ pOpt->SetFormView( ! GetDrawView()->IsDesignMode() );
+ }
+}
+
+ViewShell::ViewShell( SwDoc& rDocument, Window *pWindow,
+ const SwViewOption *pNewOpt, OutputDevice *pOutput,
+ long nFlags )
+ :
+ aBrowseBorder(),
+ pSfxViewShell( 0 ),
+ pImp( new SwViewImp( this ) ),
+ pWin( pWindow ),
+ pOut( pOutput ? pOutput
+ : pWindow ? (OutputDevice*)pWindow
+ : (OutputDevice*)rDocument.getPrinter( true )),
+ mpTmpRef( 0 ),
+ pOpt( 0 ),
+ pAccOptions( new SwAccessibilityOptions ),
+ mpTargetPaintWindow(0),
+ mpBufferedOut(0),
+ pDoc( &rDocument ),
+ nStartAction( 0 ),
+ nLockPaint( 0 ),
+ mnPrePostPaintCount(0L),
+ mpPrePostOutDev(0),
+ maPrePostMapMode()
+{
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLog, "SW", "JP93722", "ViewShell::SwViewShell" );
+
+ // #i26791# in order to suppress event handling in
+ // <SwDrawContact::Changed> during contruction of <ViewShell> instance
+ mbInConstructor = true;
+
+ bPaintInProgress = bViewLocked = bInEndAction = bFrameView =
+ bEndActionByVirDev = sal_False;
+ bPaintWorks = bEnableSmooth = sal_True;
+ bPreView = 0 !=( VSHELLFLAG_ISPREVIEW & nFlags );
+
+ // #i38810# Do not reset modified state of document, if it's already been modified.
+ const bool bIsDocModified( pDoc->IsModified() );
+ // <--
+ pDoc->acquire();
+ pOutput = pOut;
+ Init( pNewOpt );
+ pOut = pOutput;
+
+ // initialize print preview layout after layout is created in <ViewShell::Init(..)> - called above.
+ if ( bPreView )
+ {
+ pImp->InitPagePreviewLayout();
+ }
+
+ SET_CURR_SHELL( this );
+
+ ((SwHiddenTxtFieldType*)pDoc->GetSysFldType( RES_HIDDENTXTFLD ))->
+ SetHiddenFlag( !pOpt->IsShowHiddenField() );
+
+ // #i38810#
+ if ( !pDoc->GetIDocumentUndoRedo().IsUndoNoResetModified()
+ && !bIsDocModified )
+ {
+ pDoc->ResetModified();
+ }
+
+ if ( SwTxtFrm::GetTxtCache()->GetCurMax() < 2550 )
+ SwTxtFrm::GetTxtCache()->IncreaseMax( 100 );
+ if( pOpt->IsGridVisible() || getIDocumentDrawModelAccess()->GetDrawModel() )
+ Imp()->MakeDrawView();
+
+ // #i26791#
+ mbInConstructor = false;
+}
+
+ViewShell::ViewShell( ViewShell& rShell, Window *pWindow,
+ OutputDevice *pOutput, long nFlags ) :
+ Ring( &rShell ),
+ aBrowseBorder( rShell.aBrowseBorder ),
+ pSfxViewShell( 0 ),
+ pImp( new SwViewImp( this ) ),
+ pWin( pWindow ),
+ pOut( pOutput ? pOutput
+ : pWindow ? (OutputDevice*)pWindow
+ : (OutputDevice*)rShell.GetDoc()->getPrinter( true )),
+ mpTmpRef( 0 ),
+ pOpt( 0 ),
+ pAccOptions( new SwAccessibilityOptions ),
+ mpTargetPaintWindow(0),
+ mpBufferedOut(0),
+ pDoc( rShell.GetDoc() ),
+ nStartAction( 0 ),
+ nLockPaint( 0 ),
+ mnPrePostPaintCount(0L),
+ mpPrePostOutDev(0),
+ maPrePostMapMode()
+{
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLog, "SW", "JP93722", "ViewShell::SwViewShell" );
+
+ // #i26791# in order to suppress event handling in
+ // <SwDrawContact::Changed> during contruction of <ViewShell> instance
+ mbInConstructor = true;
+
+ bPaintWorks = bEnableSmooth = sal_True;
+ bPaintInProgress = bViewLocked = bInEndAction = bFrameView =
+ bEndActionByVirDev = sal_False;
+ bPreView = 0 !=( VSHELLFLAG_ISPREVIEW & nFlags );
+ if( nFlags & VSHELLFLAG_SHARELAYOUT ) //swmod 080125
+ pLayout = rShell.pLayout;//swmod 080125
+
+ SET_CURR_SHELL( this );
+
+ pDoc->acquire();
+ sal_Bool bModified = pDoc->IsModified();
+
+ pOutput = pOut;
+ Init( rShell.GetViewOptions() );
+ pOut = pOutput;
+
+ // OD 12.12.2002 #103492#
+ if ( bPreView )
+ pImp->InitPagePreviewLayout();
+
+ ((SwHiddenTxtFieldType*)pDoc->GetSysFldType( RES_HIDDENTXTFLD ))->
+ SetHiddenFlag( !pOpt->IsShowHiddenField() );
+
+ if( !bModified && !pDoc->GetIDocumentUndoRedo().IsUndoNoResetModified() )
+ {
+ pDoc->ResetModified();
+ }
+
+ if ( SwTxtFrm::GetTxtCache()->GetCurMax() < 2550 )
+ SwTxtFrm::GetTxtCache()->IncreaseMax( 100 );
+ if( pOpt->IsGridVisible() || getIDocumentDrawModelAccess()->GetDrawModel() )
+ Imp()->MakeDrawView();
+
+ // #i26791#
+ mbInConstructor = false;
+
+}
+
+ViewShell::~ViewShell()
+{
+ {
+ SET_CURR_SHELL( this );
+ bPaintWorks = sal_False;
+
+ // #i9684#Stopping the animated graphics is not
+ // necessary during printing or pdf export, because the animation
+ // has not been started in this case.
+ if( pDoc && GetWin() )
+ {
+ SwNodes& rNds = pDoc->GetNodes();
+ SwGrfNode *pGNd;
+
+ SwStartNode *pStNd;
+ SwNodeIndex aIdx( *rNds.GetEndOfAutotext().StartOfSectionNode(), 1 );
+ while ( 0 != (pStNd = aIdx.GetNode().GetStartNode()) )
+ {
+ aIdx++;
+ if ( 0 != ( pGNd = aIdx.GetNode().GetGrfNode() ) )
+ {
+ if( pGNd->IsAnimated() )
+ {
+ SwIterator<SwFrm,SwGrfNode> aIter( *pGNd );
+ for( SwFrm* pFrm = aIter.First(); pFrm; pFrm = aIter.Next() )
+ {
+ OSL_ENSURE( pFrm->IsNoTxtFrm(), "GraphicNode with Text?" );
+ ((SwNoTxtFrm*)pFrm)->StopAnimation( pOut );
+ }
+ }
+ }
+ aIdx.Assign( *pStNd->EndOfSectionNode(), +1 );
+ }
+
+ GetDoc()->StopNumRuleAnimations( pOut );
+ }
+
+ delete pImp;
+ pImp = 0; // Set to zero, because ~SwFrm relies on it.
+
+ if ( pDoc )
+ {
+ if( !pDoc->release() )
+ delete pDoc, pDoc = 0;
+ else
+ GetLayout()->ResetNewLayout();
+ }//swmod 080317
+
+ delete pOpt;
+
+ if ( SwTxtFrm::GetTxtCache()->GetCurMax() > 250 )
+ SwTxtFrm::GetTxtCache()->DecreaseMax( 100 );
+
+ SwPaintQueue::Remove( this );
+
+ OSL_ENSURE( !nStartAction, "EndAction() pending." );
+ }
+
+ if ( pDoc )
+ {
+ GetLayout()->DeRegisterShell( this );
+ if(pDoc->GetCurrentViewShell()==this)
+ pDoc->SetCurrentViewShell( this->GetNext()!=this ?
+ (ViewShell*)this->GetNext() : NULL );
+ }
+
+ delete mpTmpRef;
+ delete pAccOptions;
+}
+
+sal_Bool ViewShell::HasDrawView() const
+{
+ return Imp() ? Imp()->HasDrawView() : 0;
+}
+
+void ViewShell::MakeDrawView()
+{
+ Imp()->MakeDrawView( );
+}
+
+SdrView* ViewShell::GetDrawView()
+{
+ return Imp()->GetDrawView();
+}
+
+SdrView* ViewShell::GetDrawViewWithValidMarkList()
+{
+ SwDrawView* pDView = Imp()->GetDrawView();
+ pDView->ValidateMarkList();
+ return pDView;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/view/vprint.cxx b/sw/source/core/view/vprint.cxx
new file mode 100644
index 000000000000..ac62ba424ead
--- /dev/null
+++ b/sw/source/core/view/vprint.cxx
@@ -0,0 +1,653 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/**************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+
+#include <com/sun/star/uno/Sequence.hxx>
+#include <com/sun/star/uno/Any.hxx>
+#include <com/sun/star/view/XRenderable.hpp>
+
+#include <hintids.hxx>
+#include <rtl/ustring.hxx>
+#include <sfx2/app.hxx>
+#include <sfx2/objsh.hxx>
+#include <sfx2/prnmon.hxx>
+#include <svl/languageoptions.hxx>
+#include <editeng/paperinf.hxx>
+#include <editeng/pbinitem.hxx>
+#include <svx/svdview.hxx>
+#include <toolkit/awt/vclxdevice.hxx>
+#include <tools/debug.hxx>
+#include <unotools/localedatawrapper.hxx>
+#include <unotools/moduleoptions.hxx>
+#include <unotools/syslocale.hxx>
+#include <vcl/oldprintadaptor.hxx>
+
+#include <unotxdoc.hxx>
+#include <docsh.hxx>
+#include <txtfld.hxx>
+#include <fmtfld.hxx>
+#include <fmtfsize.hxx>
+#include <frmatr.hxx>
+#include <rootfrm.hxx>
+#include <pagefrm.hxx>
+#include <cntfrm.hxx>
+#include <doc.hxx>
+#include <IDocumentUndoRedo.hxx>
+#include <wdocsh.hxx>
+#include <fesh.hxx>
+#include <pam.hxx>
+#include <viewimp.hxx> // Imp->SetFirstVisPageInvalid()
+#include <layact.hxx>
+#include <ndtxt.hxx>
+#include <fldbas.hxx>
+#include <docfld.hxx> // _SetGetExpFld
+#include <docufld.hxx> // PostItFld /-Type
+#include <shellres.hxx>
+#include <viewopt.hxx>
+#include <printdata.hxx> // SwPrintData
+#include <pagedesc.hxx>
+#include <poolfmt.hxx>
+#include <mdiexp.hxx>
+#include <statstr.hrc>
+#include <ptqueue.hxx>
+#include <tabfrm.hxx>
+#include <txtfrm.hxx> // MinPrtLine
+#include <viscrs.hxx> // SwShellCrsr
+#include <fmtpdsc.hxx> // SwFmtPageDesc
+#include <globals.hrc>
+
+
+using namespace ::com::sun::star;
+
+class SwQueuedPaint
+{
+public:
+ SwQueuedPaint *pNext;
+ ViewShell *pSh;
+ SwRect aRect;
+
+ SwQueuedPaint( ViewShell *pNew, const SwRect &rRect ) :
+ pNext( 0 ),
+ pSh( pNew ),
+ aRect( rRect )
+ {}
+};
+
+SwQueuedPaint *SwPaintQueue::pQueue = 0;
+
+// saves some settings from the draw view
+class SwDrawViewSave
+{
+ String sLayerNm;
+ SdrView* pDV;
+ sal_Bool bPrintControls;
+public:
+ SwDrawViewSave( SdrView* pSdrView );
+ ~SwDrawViewSave();
+};
+
+
+void SwPaintQueue::Add( ViewShell *pNew, const SwRect &rNew )
+{
+ SwQueuedPaint *pPt;
+ if ( 0 != (pPt = pQueue) )
+ {
+ while ( pPt->pSh != pNew && pPt->pNext )
+ pPt = pPt->pNext;
+ if ( pPt->pSh == pNew )
+ {
+ pPt->aRect.Union( rNew );
+ return;
+ }
+ }
+ SwQueuedPaint *pNQ = new SwQueuedPaint( pNew, rNew );
+ if ( pPt )
+ pPt->pNext = pNQ;
+ else
+ pQueue = pNQ;
+}
+
+
+
+void SwPaintQueue::Repaint()
+{
+ if ( !SwRootFrm::IsInPaint() && pQueue )
+ {
+ SwQueuedPaint *pPt = pQueue;
+ do
+ { ViewShell *pSh = pPt->pSh;
+ SET_CURR_SHELL( pSh );
+ if ( pSh->IsPreView() )
+ {
+ if ( pSh->GetWin() )
+ {
+ //Fuer PreView aussenherum, weil im PaintHdl (UI) die
+ //Zeilen/Spalten bekannt sind.
+ pSh->GetWin()->Invalidate();
+ pSh->GetWin()->Update();
+ }
+ }
+ else
+ pSh->Paint( pPt->aRect.SVRect() );
+ pPt = pPt->pNext;
+ } while ( pPt );
+
+ do
+ { pPt = pQueue;
+ pQueue = pQueue->pNext;
+ delete pPt;
+ } while ( pQueue );
+ }
+}
+
+
+
+void SwPaintQueue::Remove( ViewShell *pSh )
+{
+ SwQueuedPaint *pPt;
+ if ( 0 != (pPt = pQueue) )
+ {
+ SwQueuedPaint *pPrev = 0;
+ while ( pPt && pPt->pSh != pSh )
+ {
+ pPrev = pPt;
+ pPt = pPt->pNext;
+ }
+ if ( pPt )
+ {
+ if ( pPrev )
+ pPrev->pNext = pPt->pNext;
+ else if ( pPt == pQueue )
+ pQueue = 0;
+ delete pPt;
+ }
+ }
+}
+
+void SetSwVisArea( ViewShell *pSh, const SwRect &rRect, sal_Bool /*bPDFExport*/ )
+{
+ OSL_ENSURE( !pSh->GetWin(), "Drucken mit Window?" );
+ pSh->aVisArea = rRect;
+ pSh->Imp()->SetFirstVisPageInvalid();
+ Point aPt( rRect.Pos() );
+
+ // calculate an offset for the rectangle of the n-th page to
+ // move the start point of the output operation to a position
+ // such that in the output device all pages will be painted
+ // at the same position
+ aPt.X() = -aPt.X(); aPt.Y() = -aPt.Y();
+
+ OutputDevice *pOut = pSh->GetOut();
+
+ MapMode aMapMode( pOut->GetMapMode() );
+ aMapMode.SetOrigin( aPt );
+ pOut->SetMapMode( aMapMode );
+}
+
+/******************************************************************************/
+
+void ViewShell::InitPrt( OutputDevice *pOutDev )
+{
+ //Fuer den Printer merken wir uns einen negativen Offset, der
+ //genau dem Offset de OutputSize entspricht. Das ist notwendig,
+ //weil unser Ursprung der linken ober Ecke der physikalischen
+ //Seite ist, die Ausgaben (SV) aber den Outputoffset als Urstprung
+ //betrachten.
+ if ( pOutDev )
+ {
+ aPrtOffst = Point();
+
+ aPrtOffst += pOutDev->GetMapMode().GetOrigin();
+ MapMode aMapMode( pOutDev->GetMapMode() );
+ aMapMode.SetMapUnit( MAP_TWIP );
+ pOutDev->SetMapMode( aMapMode );
+ pOutDev->SetLineColor();
+ pOutDev->SetFillColor();
+ }
+ else
+ aPrtOffst.X() = aPrtOffst.Y() = 0;
+
+ if ( !pWin )
+ pOut = pOutDev; //Oder was sonst?
+}
+
+void ViewShell::ChgAllPageOrientation( sal_uInt16 eOri )
+{
+ OSL_ENSURE( nStartAction, "missing an Action" );
+ SET_CURR_SHELL( this );
+
+ sal_uInt16 nAll = GetDoc()->GetPageDescCnt();
+ sal_Bool bNewOri = Orientation(eOri) == ORIENTATION_PORTRAIT ? sal_False : sal_True;
+
+ for( sal_uInt16 i = 0; i < nAll; ++ i )
+ {
+ const SwPageDesc& rOld =
+ const_cast<const SwDoc *>(GetDoc())->GetPageDesc( i );
+
+ if( rOld.GetLandscape() != bNewOri )
+ {
+ SwPageDesc aNew( rOld );
+ {
+ ::sw::UndoGuard const ug(GetDoc()->GetIDocumentUndoRedo());
+ GetDoc()->CopyPageDesc(rOld, aNew);
+ }
+ aNew.SetLandscape( bNewOri );
+ SwFrmFmt& rFmt = aNew.GetMaster();
+ SwFmtFrmSize aSz( rFmt.GetFrmSize() );
+ if( bNewOri ? aSz.GetHeight() > aSz.GetWidth()
+ : aSz.GetHeight() < aSz.GetWidth() )
+ {
+ SwTwips aTmp = aSz.GetHeight();
+ aSz.SetHeight( aSz.GetWidth() );
+ aSz.SetWidth( aTmp );
+ rFmt.SetFmtAttr( aSz );
+ }
+ GetDoc()->ChgPageDesc( i, aNew );
+ }
+ }
+}
+
+void ViewShell::ChgAllPageSize( Size &rSz )
+{
+ OSL_ENSURE( nStartAction, "missing an Action" );
+ SET_CURR_SHELL( this );
+
+ SwDoc* pMyDoc = GetDoc();
+ sal_uInt16 nAll = pMyDoc->GetPageDescCnt();
+
+ for( sal_uInt16 i = 0; i < nAll; ++i )
+ {
+ const SwPageDesc &rOld = const_cast<const SwDoc *>(pMyDoc)->GetPageDesc( i );
+ SwPageDesc aNew( rOld );
+ {
+ ::sw::UndoGuard const ug(GetDoc()->GetIDocumentUndoRedo());
+ GetDoc()->CopyPageDesc( rOld, aNew );
+ }
+ SwFrmFmt& rPgFmt = aNew.GetMaster();
+ Size aSz( rSz );
+ const sal_Bool bOri = aNew.GetLandscape();
+ if( bOri ? aSz.Height() > aSz.Width()
+ : aSz.Height() < aSz.Width() )
+ {
+ SwTwips aTmp = aSz.Height();
+ aSz.Height() = aSz.Width();
+ aSz.Width() = aTmp;
+ }
+
+ SwFmtFrmSize aFrmSz( rPgFmt.GetFrmSize() );
+ aFrmSz.SetSize( aSz );
+ rPgFmt.SetFmtAttr( aFrmSz );
+ pMyDoc->ChgPageDesc( i, aNew );
+ }
+}
+
+
+void ViewShell::CalcPagesForPrint( sal_uInt16 nMax )
+{
+ SET_CURR_SHELL( this );
+
+ SwRootFrm* pMyLayout = GetLayout();
+
+ const SwFrm *pPage = pMyLayout->Lower();
+ SwLayAction aAction( pMyLayout, Imp() );
+
+ pMyLayout->StartAllAction();
+ for ( sal_uInt16 i = 1; pPage && i <= nMax; pPage = pPage->GetNext(), ++i )
+ {
+ pPage->Calc();
+ SwRect aOldVis( VisArea() );
+ aVisArea = pPage->Frm();
+ Imp()->SetFirstVisPageInvalid();
+ aAction.Reset();
+ aAction.SetPaint( sal_False );
+ aAction.SetWaitAllowed( sal_False );
+ aAction.SetReschedule( sal_True );
+
+ aAction.Action();
+
+ aVisArea = aOldVis;
+ Imp()->SetFirstVisPageInvalid();
+
+ }
+
+ pMyLayout->EndAllAction();
+}
+
+/******************************************************************************/
+
+SwDoc * ViewShell::FillPrtDoc( SwDoc *pPrtDoc, const SfxPrinter* pPrt)
+{
+ OSL_ENSURE( this->IsA( TYPE(SwFEShell) ),"ViewShell::Prt for FEShell only");
+ SwFEShell* pFESh = (SwFEShell*)this;
+ pPrtDoc->LockExpFlds();
+
+ // Make a copy of it since it gets destroyed with the temporary document
+ // used for PDF export
+ if (pPrt)
+ pPrtDoc->setPrinter( new SfxPrinter(*pPrt), true, true );
+
+ const SfxPoolItem* pCpyItem;
+ const SfxItemPool& rPool = GetAttrPool();
+ for( sal_uInt16 nWh = POOLATTR_BEGIN; nWh < POOLATTR_END; ++nWh )
+ if( 0 != ( pCpyItem = rPool.GetPoolDefaultItem( nWh ) ) )
+ pPrtDoc->GetAttrPool().SetPoolDefaultItem( *pCpyItem );
+
+ pPrtDoc->ReplaceStyles( *GetDoc() );
+
+ SwShellCrsr *pActCrsr = pFESh->_GetCrsr();
+ SwShellCrsr *pFirstCrsr = dynamic_cast<SwShellCrsr*>(pActCrsr->GetNext());
+ if( !pActCrsr->HasMark() )
+ {
+ pActCrsr = dynamic_cast<SwShellCrsr*>(pActCrsr->GetPrev());
+ }
+
+ Point aSelPoint;
+ if( pFESh->IsTableMode() )
+ {
+ SwShellTableCrsr* pShellTblCrsr = pFESh->GetTableCrsr();
+
+ const SwCntntNode* pCntntNode = pShellTblCrsr->GetNode()->GetCntntNode();
+ const SwCntntFrm *pCntntFrm = pCntntNode ? pCntntNode->getLayoutFrm( GetLayout(), 0, pShellTblCrsr->Start() ) : 0;
+ if( pCntntFrm )
+ {
+ SwRect aCharRect;
+ SwCrsrMoveState aTmpState( MV_NONE );
+ pCntntFrm->GetCharRect( aCharRect, *pShellTblCrsr->Start(), &aTmpState );
+ aSelPoint = Point( aCharRect.Left(), aCharRect.Top() );
+ }
+ }
+ else
+ {
+ aSelPoint = pFirstCrsr->GetSttPos();
+ }
+
+ const SwPageFrm* pPage = GetLayout()->GetPageAtPos( aSelPoint );
+ OSL_ENSURE( pPage, "no page found!" );
+
+ // get page descriptor - fall back to the first one if pPage could not be found
+ const SwPageDesc* pPageDesc = pPage ? pPrtDoc->FindPageDescByName(
+ pPage->GetPageDesc()->GetName() ) : &pPrtDoc->_GetPageDesc( (sal_uInt16)0 );
+
+ if( !pFESh->IsTableMode() && pActCrsr->HasMark() )
+ {
+ SwNodeIndex aNodeIdx( *pPrtDoc->GetNodes().GetEndOfContent().StartOfSectionNode() );
+ SwTxtNode* pTxtNd = pPrtDoc->GetNodes().GoNext( &aNodeIdx )->GetTxtNode();
+ SwCntntNode *pLastNd =
+ pActCrsr->GetCntntNode( (*pActCrsr->GetMark()) <= (*pActCrsr->GetPoint()) );
+
+ if( pLastNd && pLastNd->IsTxtNode() )
+ ((SwTxtNode*)pLastNd)->CopyCollFmt( *pTxtNd );
+ }
+
+ pFESh->Copy( pPrtDoc );
+
+ {
+ SwNodeIndex aNodeIdx( *pPrtDoc->GetNodes().GetEndOfContent().StartOfSectionNode() );
+ SwCntntNode* pCNd = pPrtDoc->GetNodes().GoNext( &aNodeIdx );
+ if( pFESh->IsTableMode() )
+ {
+ SwTableNode* pTNd = pCNd->FindTableNode();
+ if( pTNd )
+ pTNd->GetTable().GetFrmFmt()->SetFmtAttr( SwFmtPageDesc( pPageDesc ) );
+ }
+ else
+ {
+ pCNd->SetAttr( SwFmtPageDesc( pPageDesc ) );
+ if( pFirstCrsr->HasMark() )
+ {
+ SwTxtNode *pTxtNd = pCNd->GetTxtNode();
+ if( pTxtNd )
+ {
+ SwCntntNode *pFirstNd =
+ pFirstCrsr->GetCntntNode( (*pFirstCrsr->GetMark()) > (*pFirstCrsr->GetPoint()) );
+
+ if( pFirstNd && pFirstNd->IsTxtNode() )
+ ((SwTxtNode*)pFirstNd)->CopyCollFmt( *pTxtNd );
+ }
+ }
+ }
+ }
+ return pPrtDoc;
+}
+
+
+sal_Bool ViewShell::PrintOrPDFExport(
+ OutputDevice *pOutDev,
+ SwPrintData const& rPrintData,
+ sal_Int32 nRenderer /* the index in the vector of pages to be printed */ )
+{
+
+ const sal_Int32 nMaxRenderer = rPrintData.GetRenderData().GetPagesToPrint().size() - 1;
+#if OSL_DEBUG_LEVEL > 1
+ DBG_ASSERT( 0 <= nRenderer && nRenderer <= nMaxRenderer, "nRenderer out of bounds");
+#endif
+ if (!pOutDev || nMaxRenderer < 0 || nRenderer < 0 || nRenderer > nMaxRenderer)
+ return sal_False;
+
+ // save settings of OutputDevice (should be done always since the
+ // output device is now provided by a call from outside the Writer)
+ pOutDev->Push();
+
+ ViewShell *pShell;
+ SwDoc *pOutDevDoc;
+
+ // Print/PDF export for (multi-)selection has already generated a
+ // temporary document with the selected text.
+ // (see XRenderable implementation in unotxdoc.cxx)
+ // It is implemented this way because PDF export calls this Prt function
+ // once per page and we do not like to always have the temporary document
+ // to be created that often here.
+ pOutDevDoc = GetDoc();
+ pShell = new ViewShell( *this, 0, pOutDev );
+
+ SdrView *pDrawView = pShell->GetDrawView();
+ if (pDrawView)
+ {
+ pDrawView->SetBufferedOutputAllowed( false );
+ pDrawView->SetBufferedOverlayAllowed( false );
+ }
+
+ {
+ SET_CURR_SHELL( pShell );
+
+
+ if( pOpt->IsReadonly() )
+ pShell->pOpt->SetReadonly( sal_True );
+
+ // save options at draw view:
+ SwDrawViewSave aDrawViewSave( pShell->GetDrawView() );
+
+ pShell->PrepareForPrint( rPrintData );
+
+ const sal_Int32 nPage = rPrintData.GetRenderData().GetPagesToPrint()[ nRenderer ];
+#if OSL_DEBUG_LEVEL > 1
+ DBG_ASSERT( nPage == 0 || rPrintData.GetRenderData().GetValidPagesSet().count( nPage ) == 1, "nPage not valid" );
+#endif
+ const SwPageFrm *pStPage = 0;
+ if (nPage > 0) // a 'regular' page, not one from the post-it document
+ {
+ const SwRenderData::ValidStartFramesMap_t &rFrms = rPrintData.GetRenderData().GetValidStartFrames();
+ SwRenderData::ValidStartFramesMap_t::const_iterator aIt( rFrms.find( nPage ) );
+ DBG_ASSERT( aIt != rFrms.end(), "failed to find start frame" );
+ if (aIt == rFrms.end())
+ return sal_False;
+ pStPage = aIt->second;
+ }
+ else // a page from the post-its document ...
+ {
+ DBG_ASSERT( nPage == 0, "unexpected page number. 0 for post-it pages expected" );
+ pStPage = rPrintData.GetRenderData().GetPostItStartFrames()[ nRenderer ];
+ }
+ DBG_ASSERT( pStPage, "failed to get start page" );
+
+ //!! applying view options and formatting the dcoument should now only be done in getRendererCount!
+
+ ViewShell *pViewSh2 = nPage == 0 ? /* post-it page? */
+ rPrintData.GetRenderData().m_pPostItShell : pShell;
+ ::SetSwVisArea( pViewSh2, pStPage->Frm() );
+
+// FIXME disabled because rPrintData.aOffset is always (0,0)
+#if 0
+ if( pStPage->GetFmt()->GetPoolFmtId() == RES_POOLPAGE_JAKET )
+ {
+ Point aNewOrigin = pOutDev->GetMapMode().GetOrigin();
+ aNewOrigin += rPrintData.aOffset;
+ MapMode aTmp( pOutDev->GetMapMode() );
+ aTmp.SetOrigin( aNewOrigin );
+ pOutDev->SetMapMode( aTmp );
+ }
+#endif
+
+ pShell->InitPrt( pOutDev );
+
+ pViewSh2 = nPage == 0 ? /* post-it page? */
+ rPrintData.GetRenderData().m_pPostItShell : pShell;
+ ::SetSwVisArea( pViewSh2, pStPage->Frm() );
+
+ pStPage->GetUpper()->Paint( pStPage->Frm(), &rPrintData );
+
+ SwPaintQueue::Repaint();
+ }
+
+ delete pShell;
+
+ // restore settings of OutputDevice (should be done always now since the
+ // output device is now provided by a call from outside the Writer)
+ pOutDev->Pop();
+
+ return sal_True;
+}
+
+void ViewShell::PrtOle2( SwDoc *pDoc, const SwViewOption *pOpt, const SwPrintData& rOptions,
+ OutputDevice* pOleOut, const Rectangle& rRect )
+{
+ ViewShell *pSh;
+ if( pDoc->GetCurrentViewShell() )
+ pSh = new ViewShell( *pDoc->GetCurrentViewShell(), 0, pOleOut,VSHELLFLAG_SHARELAYOUT );//swmod 080129
+ else //swmod 071108//swmod 071225
+ pSh = new ViewShell( *pDoc, 0, pOpt, pOleOut);//swmod 080129
+
+ {
+ SET_CURR_SHELL( pSh );
+ pSh->PrepareForPrint( rOptions );
+ pSh->SetPrtFormatOption( sal_True );
+
+ SwRect aSwRect( rRect );
+ pSh->aVisArea = aSwRect;
+
+ if ( pSh->GetViewOptions()->getBrowseMode() &&
+ pSh->GetNext() == pSh )
+ {
+ pSh->CheckBrowseView( sal_False );
+ pSh->GetLayout()->Lower()->InvalidateSize();
+ }
+
+ // CalcPagesForPrint() should not be necessary here. The pages in the
+ // visible area will be formatted in SwRootFrm::Paint().
+ // Removing this gives us a performance gain during saving the
+ // document because the thumbnail creation will not trigger a complete
+ // formatting of the document.
+ // Seiten fuers Drucken formatieren
+ // pSh->CalcPagesForPrint( SHRT_MAX );
+ pOleOut->Push( PUSH_CLIPREGION );
+ pOleOut->IntersectClipRegion( aSwRect.SVRect() );
+ pSh->GetLayout()->Paint( aSwRect );
+
+ pOleOut->Pop();
+
+ }
+ delete pSh;
+}
+
+sal_Bool ViewShell::IsAnyFieldInDoc() const
+{
+ const SfxPoolItem* pItem;
+ sal_uInt32 nMaxItems = pDoc->GetAttrPool().GetItemCount2( RES_TXTATR_FIELD );
+ for( sal_uInt32 n = 0; n < nMaxItems; ++n )
+ if( 0 != (pItem = pDoc->GetAttrPool().GetItem2( RES_TXTATR_FIELD, n )))
+ {
+ const SwFmtFld* pFmtFld = (SwFmtFld*)pItem;
+ const SwTxtFld* pTxtFld = pFmtFld->GetTxtFld();
+ //#i101026# do not include postits in field check
+ const SwField* pFld = pFmtFld->GetFld();
+ if( pTxtFld && pTxtFld->GetTxtNode().GetNodes().IsDocNodes() && (pFld->Which() != RES_POSTITFLD))
+ return sal_True;
+ }
+ return sal_False;
+}
+
+SwDrawViewSave::SwDrawViewSave( SdrView* pSdrView )
+ : pDV( pSdrView )
+{
+ if ( pDV )
+ {
+ sLayerNm.AssignAscii( RTL_CONSTASCII_STRINGPARAM("Controls" ) );
+ bPrintControls = pDV->IsLayerPrintable( sLayerNm );
+ }
+}
+
+SwDrawViewSave::~SwDrawViewSave()
+{
+ if ( pDV )
+ {
+ pDV->SetLayerPrintable( sLayerNm, bPrintControls );
+ }
+}
+
+
+// #i6467# - method also called for page preview
+void ViewShell::PrepareForPrint( const SwPrintData &rOptions )
+{
+ pOpt->SetGraphic ( sal_True == rOptions.bPrintGraphic );
+ pOpt->SetTable ( sal_True == rOptions.bPrintTable );
+ pOpt->SetDraw ( sal_True == rOptions.bPrintDraw );
+ pOpt->SetControl ( sal_True == rOptions.bPrintControl );
+ pOpt->SetPageBack( sal_True == rOptions.bPrintPageBackground );
+ pOpt->SetBlackFont( sal_True == rOptions.bPrintBlackFont );
+
+ if ( HasDrawView() )
+ {
+ SdrView *pDrawView = GetDrawView();
+ String sLayerNm;
+ sLayerNm.AssignAscii(RTL_CONSTASCII_STRINGPARAM("Controls" ));
+ // #i6467# - consider, if view shell belongs to page preview
+ if ( !IsPreView() )
+ {
+ pDrawView->SetLayerPrintable( sLayerNm, rOptions.bPrintControl );
+ }
+ else
+ {
+ pDrawView->SetLayerVisible( sLayerNm, rOptions.bPrintControl );
+ }
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */